azureus-4.3.0.6/0000755000175000017500000000000011312516557012644 5ustar adrianadrianazureus-4.3.0.6/build/0000755000175000017500000000000011310377506013740 5ustar adrianadrianazureus-4.3.0.6/build/libs/0000755000175000017500000000000011310377506014671 5ustar adrianadrianazureus-4.3.0.6/build/libs/JavaApplicationStub0000644000175000017500000012756011257011434020525 0ustar adrianadrianJP  `Op (8__PAGEZERO__TEXT__text__TEXT __cstring__TEXT$__unwind_info__TEXTHH__DATA __dyld__DATA __cfstring__DATA __data__DATA __common__DATA( 4__IMPORT0 __pointers__IMPORT0 __jump_table__IMPORT@0U@ 8__LINKEDIT@ 0P0(<2, P11 /usr/lib/dyld{;,Z?։?P /System/Library/PrivateFrameworks/JavaApplicationLauncher.framework/Versions/A/JavaApplicationLauncher `,/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation 4g/usr/lib/libgcc_s.1.dylib 4{/usr/lib/libSystem.B.dylib h&/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundationp5j]$ML$ˉ\$UWVS,} uE = 5 Qu $V v05p com.apple.JavaApplicationStubYGk"MNmxZ^ +*Ezԕ{?9c(]F#IhWCQT.d8d4<c뵲v$C5:ţo l XlibSystem.B.dyliblibSystem.B.dylib 0 *H 01 0 +0 *H  000  *H 0b1 0 UUS10U  Apple Inc.1&0$U Apple Certification Authority10U Apple Root CA0 070214211919Z 150214211919Z01 0 UUS10U  Apple Inc.1&0$U Apple Certification Authority1301U*Apple Code Signing Certification Authority0"0  *H 0 q k% ]kYZ9#59H!' d8k P[]Tes/b8drm|iGa&,$j?̬)LIyuv LSxv2ʑ9Pjf K;-Ɉ-i¤*a/ۇ!L-rn?̣@Q-YN]e3'g$LJy]i>H$m0ȧ#8_a00U0U% 0 +0U00UiwBNVBQ 0U#0+iGv k.@GM^06U/0-0+)'%http://www.apple.com/appleca/root.crl0  *H cLrѦKX~̫м'0=ƭaV }lٝRb$0ыbj?[DޫۭK?QKK:IaNՀzľ[Wb*Fר7?8 8B]㫚V>C '"W:vG0<9sb̡G˟!+oW6f㍙D4EY X')7dCf)d^+-?BpK"hͤo000  *H 0b1 0 UUS10U  Apple Inc.1&0$U Apple Certification Authority10U Apple Root CA0 060425214036Z 350209214036Z0b1 0 UUS10U  Apple Inc.1&0$U Apple Certification Authority10U Apple Root CA0"0  *H 0 䑩 GP^y-6WLUKl"0>P Af$kУ*z G[73Mir]_%UM] d5#KYPXPg ˬ, op?0C=+I(ε^=: !.t< bqGSU/ApLE~LkPAtb A30XZ2hesg^eIv3ew-z0v0U0U00U+iGv k.@GM^0U#0+iGv k.@GM^0U 00 *Hcd00*+https://www.apple.com/appleca/0+0Reliance on this certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certificate policy and certification practice statements.0  *H \6L-x팛wvw0O=G7@,ԱؾsdyO4آ>xk}9S 8ıO k+Y |@Vtӷ#;Go$ѷpE'mx~"5%kԢ$#s`[ /DH`8=&g 3j /Sj[dc3w:,V!ںsO6U٧2Bq~RB$*M^cKP 7uu!000  *H 01 0 UUS10U  Apple Inc.1&0$U Apple Certification Authority1301U*Apple Code Signing Certification Authority0 070223220256Z 150114220256Z0V1 0 UUS10U  Apple Inc.10U Apple Software10USoftware Signing0"0  *H 0 Mza/]3NE.·;sD`ϬA91Mٸ=Acz&ҵ/&!InvR")-||f]ny 2;d:*KEA3%|k=bK_; {|}}S7,mn%6 s=ҬSEKǿ눗|{a(tEw']ruS,V3[SR@Uῢ00U0 U00U% 0 +0U sS!p386CL0U#0iwBNVBQ 0U 00 *Hcd00)+http://www.apple.com/appleca/0+0Reliance on this certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certificate policy and certification practice statements.0=U604020.,http://www.apple.com/appleca/codesigning.crl0  *H +\_5$r*.;)ẃ,M|j@Zl*YEzI$ݴug7SF;KkW4ܗ/Jw.N| /T!DיWP) ; GIuC"P!Bə e@)狐q~uLȤ_y99+!bpQ|z#r|U=mfs a;~teQVyɁ10001 0 UUS10U  Apple Inc.1&0$U Apple Certification Authority1301U*Apple Code Signing Certification Authority0 +0  *H w; ul1X~溥/" B^ )zN,nQ3i3UsM-=+XOdg{IbM=Oa0#%\.e`%,J-&#;m>FoٮYE\Թ uiSڀv1{e|.G5j}*GR2Mm,cR,TRzG|O-+j\$_J#!U- Y*e_ڛW9  8__PAGEZEROH__TEXT __text__TEXT x__symbol_stub1__TEXT)__cstring__TEXT,__const__TEXT/__DATA0 __dyld__DATA0 __la_symbol_ptr__DATA0 .__nl_symbol_ptr__DATA0 \__data__DATA0 __common__DATA04__bss__DATA18__LINKEDIT@ 0p0F4 P33Hb /usr/lib/dyld]?6iyR;5K)( /System/Library/PrivateFrameworks/JavaApplicationLauncher.framework/Versions/A/JavaApplicationLauncher `,/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation 4{/usr/lib/libSystem.B.dylib:|: x8!T!48!z8;cW{:|H |<@= |#x!|xxb0ؐ0<@|+x0$/8I@ <@9",H //@|Ix8B|u@<@_x"0H;/@<@B0B/A|I|LxN!<@B0ȀB/A|I|LxN!H <@B0̀/AH)<`8<8c,H<| | xN!<`8@8c- H<`8D8c- H<`8H8c-8H<`8L8c-PH<`8P8c-pHA@/A4D/A(H/AL/AP/A|I|Lx;N!<@= |}x;-;)-HԀDx| | xN!8CH//@|Cx8B|u@x9`| uA | 8B|tH@p9kK܀Hx| | xN!/ALL$x8| | xN!/A,P| | xN!,A|i|lxN!H;@,<`888c-HUa8/AH <@8dxExB08xHH =0}=9N =`k0}iN ``|B!H <_BB/A+A<8cDH <8cdH 8!P|N ``||}x!8`-|#xH }/aLA|~x8AL```@(@^/(A H M/AD8^|xKL8`-H  /A| x| xN!xH UH|dx8`-H8!`|N `|a||x!|#x8`8(H8(|}x8`-}H}x}8`-H}8!`a|N |<@;-|zxx!H<@;-|yxxH<@;b-|~xcxH/A<`8c-H||x<`8c.H|}xxHxx|exCxH |yxxHm|}xxHaxx|exCxH|~xcxHA|}xcxH5xx|exCxH<@)xx"/8889a8Hy8!p|N |!H|~yA<`8c. H|dxxH|yAd<`8c.0H|dxxH/AD<`88c.8H/A,<88-HAH ,A|lx|iN!8!Px|HP8!P|N |a|#x|+x!H|yA;888xHU|}xxH/Al<8x8.PHxHU/@0<`<xc08.T8cH<`8c.HuH\KxdxH8`HH<<`808c.898H <<`808c.8.8H8`8!`a|N |!|{x|#x!H|}yAH||yA<`8c/H|dxxH|yA<`8c/H88|dx8`H|dx8`H5|~xxH|}xHq@D/AxH9<`@A$<`8c/THM|dxxH!|yy@<`8c/\H-|dxxH!|yAH%|}xHM@;X<x`x8@H/A;8x8 x;H xH8c}!I88BTB>+A )8;<`88c/hH/@<@8/H <@8//AxHq/AH xH]/AxK9HPKUcxDxxHH<xdxExKH(<<`808c/88H8`8! !|N |B|H|=9l/@!|> x|_xlptx|>^~h<_8b HM|lx<_8Bl~h^>|xtpl!|}N ||dxB!p8_;88a98HxHA=?<_|~x9it)t;|]xK x}=.BHu,@|}xxHmHI8!|N =`0}N =`0}N =`0(}N =`0 }N =`0}N =`04}N =`08}N =`00}N =`0}N =`0,}N =`0}N =`0@}N =`0<}N =`0}N =`0$}N =`0}N =`0}N =`0}N =`0}N =`0}N =`0\}N =`0`}N =`0}N =`0}N =`0}N =`0d}N =`0t}N =`0x}N =`0p}N =`0|}N =`0}N =`0}N =`0h}N =`0}N =`0 }N =`0l}N =`0}N =`0}N =`0T}N =`0}N =`0L}N =`0P}N =`0X}N =`0}N =`0D}N =`0H}N __dyld_make_delayed_module_initializer_calls__dyld_image_count__dyld_get_image_name__dyld_get_image_header__dyld_NSLookupSymbolInImage__dyld_NSAddressOfSymbollibobjc__objcInit__dyld_mod_term_funcsCannot launch applicationIt requires a newer javaQuitOldJavaAlertCannotLaunchApplicationProductVersion10.3/usr/lib/libobjc.dylib/..ERROR: Could not change the current working directory to %s ERRORCFURLGetFileSystemRepresentation() failed on main bundle CFBundleCopyBundleURL() failed on main bundle Java/System/Library/PrivateFrameworks/JavaApplicationLauncher.frameworkJNLPJVMVersion/System/Library/Frameworks/JavaVM.framework/Versions/1.3.11.3.11.3CFBundleGetMainBundle() failed fprintf$LDBL128libSystem.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!<aEB0 00 4 0K 0h 0 0 0 0 1 1  1. 1 P 1t 10 1%?Xo9Q]p&7=Tw$*2I\djrz !"#$%&'()*+,012345678:;<=?@ABCDEC8?$<!DE@A=B'(,6:201354;7+#* %)&">9/-._NXArgc_NXArgv___progname__mh_execute_header_catch_exception_raise_catch_exception_raise_state_catch_exception_raise_state_identity_clock_alarm_reply_do_mach_notify_dead_name_do_mach_notify_no_senders_do_mach_notify_port_deleted_do_mach_notify_send_once_do_seqnos_mach_notify_dead_name_do_seqnos_mach_notify_no_senders_do_seqnos_mach_notify_port_deleted_do_seqnos_mach_notify_send_once_environ_receive_samples_CFBundleCopyBundleURL_CFBundleCopyLocalizedString_CFBundleCreate_CFBundleGetInfoDictionary_CFBundleGetMainBundle_CFBundleGetVersionNumber_CFDictionaryContainsKey_CFDictionaryGetTypeID_CFDictionaryGetValue_CFGetTypeID_CFRelease_CFStringGetCString_CFStringGetTypeID_CFStringHasPrefix_CFURLCreateWithFileSystemPath_CFURLGetFileSystemRepresentation_CFUserNotificationDisplayNotice_MRJApplicationMainArgs_NSAddImage_NSAddressOfSymbol_NSIsSymbolNameDefinedWithHint_NSLookupAndBindSymbolWithHint_NSLookupSymbolInImage__CFCopySystemVersionDictionary___CFStringMakeConstantString___keymgr_dwarf2_register_sections___keymgr_global___sF__cthread_init_routine__dyld_register_func_for_add_image__dyld_register_func_for_remove_image__init_keymgr__keymgr_get_and_lock_processwide_ptr__keymgr_set_and_unlock_processwide_ptr_abort_atexit_calloc_chdir_errno_exit_free_fwrite_launchJavaApplication_mach_init_routine_perror_stat_strcmp_strcpy_strlcat_strlcpy_strlenradr://5614542 N$f v0: com.apple.JavaApplicationStub;幑A:F2 ]fe"~ Kpy>c&QI B=Y'yx; ~@~@rAKr+ |L 0com.apple.translate 0libSystem.B.dylib 0 *H 01 0 +0 *H  000  *H 0b1 0 UUS10U  Apple Inc.1&0$U Apple Certification Authority10U Apple Root CA0 070214211919Z 150214211919Z01 0 UUS10U  Apple Inc.1&0$U Apple Certification Authority1301U*Apple Code Signing Certification Authority0"0  *H 0 q k% ]kYZ9#59H!' d8k P[]Tes/b8drm|iGa&,$j?̬)LIyuv LSxv2ʑ9Pjf K;-Ɉ-i¤*a/ۇ!L-rn?̣@Q-YN]e3'g$LJy]i>H$m0ȧ#8_a00U0U% 0 +0U00UiwBNVBQ 0U#0+iGv k.@GM^06U/0-0+)'%http://www.apple.com/appleca/root.crl0  *H cLrѦKX~̫м'0=ƭaV }lٝRb$0ыbj?[DޫۭK?QKK:IaNՀzľ[Wb*Fר7?8 8B]㫚V>C '"W:vG0<9sb̡G˟!+oW6f㍙D4EY X')7dCf)d^+-?BpK"hͤo000  *H 0b1 0 UUS10U  Apple Inc.1&0$U Apple Certification Authority10U Apple Root CA0 060425214036Z 350209214036Z0b1 0 UUS10U  Apple Inc.1&0$U Apple Certification Authority10U Apple Root CA0"0  *H 0 䑩 GP^y-6WLUKl"0>P Af$kУ*z G[73Mir]_%UM] d5#KYPXPg ˬ, op?0C=+I(ε^=: !.t< bqGSU/ApLE~LkPAtb A30XZ2hesg^eIv3ew-z0v0U0U00U+iGv k.@GM^0U#0+iGv k.@GM^0U 00 *Hcd00*+https://www.apple.com/appleca/0+0Reliance on this certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certificate policy and certification practice statements.0  *H \6L-x팛wvw0O=G7@,ԱؾsdyO4آ>xk}9S 8ıO k+Y |@Vtӷ#;Go$ѷpE'mx~"5%kԢ$#s`[ /DH`8=&g 3j /Sj[dc3w:,V!ںsO6U٧2Bq~RB$*M^cKP 7uu!000  *H 01 0 UUS10U  Apple Inc.1&0$U Apple Certification Authority1301U*Apple Code Signing Certification Authority0 070223220256Z 150114220256Z0V1 0 UUS10U  Apple Inc.10U Apple Software10USoftware Signing0"0  *H 0 Mza/]3NE.·;sD`ϬA91Mٸ=Acz&ҵ/&!InvR")-||f]ny 2;d:*KEA3%|k=bK_; {|}}S7,mn%6 s=ҬSEKǿ눗|{a(tEw']ruS,V3[SR@Uῢ00U0 U00U% 0 +0U sS!p386CL0U#0iwBNVBQ 0U 00 *Hcd00)+http://www.apple.com/appleca/0+0Reliance on this certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certificate policy and certification practice statements.0=U604020.,http://www.apple.com/appleca/codesigning.crl0  *H +\_5$r*.;)ẃ,M|j@Zl*YEzI$ݴug7SF;KkW4ܗ/Jw.N| /T!DיWP) ; GIuC"P!Bə e@)狐q~uLȤ_y99+!bpQ|z#r|U=mfs a;~teQVyɁ10001 0 UUS10U  Apple Inc.1&0$U Apple Certification Authority1301U*Apple Code Signing Certification Authority0 +0  *H # R𲫖|37rUZKOR#`%7*=|8z(ڑy/UW7GU*lp"h1v5Yb Lo4SL@\k2r ^F؝!Rn/K)smkQ7. t=[A@MNձ iiEYΩ=uW7LG<5%EZ65썜LC(~XL6%Gazureus-4.3.0.6/build/libs/win32 native libs/0000755000175000017500000000000011310377506020014 5ustar adrianadrianazureus-4.3.0.6/org/0000755000175000017500000000000011310377564013434 5ustar adrianadrianazureus-4.3.0.6/org/json/0000755000175000017500000000000011310377564014405 5ustar adrianadrianazureus-4.3.0.6/org/json/simple/0000755000175000017500000000000011310377640015671 5ustar adrianadrianazureus-4.3.0.6/org/json/simple/JSONObject.java0000644000175000017500000000420511046520736020437 0ustar adrianadrian/* * $Id: JSONObject.java,v 1.2 2008/08/07 01:18:54 parg Exp $ * Created on 2006-4-10 */ package org.json.simple; import java.util.Iterator; import java.util.Map; import org.gudy.azureus2.core3.util.LightHashMap; /** * @author FangYidong */ public class JSONObject extends LightHashMap{ public JSONObject() { super(); } public JSONObject(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } public JSONObject(int initialCapacity) { super(initialCapacity); } public JSONObject(Map arg0) { super(arg0); } public String toString(){ ItemList list=new ItemList(); Iterator iter=entrySet().iterator(); while(iter.hasNext()){ Map.Entry entry=(Map.Entry)iter.next(); list.add(toString(entry.getKey().toString(),entry.getValue())); } return "{"+list.toString()+"}"; } public static String toString(String key,Object value){ StringBuffer sb=new StringBuffer(); sb.append("\""); sb.append(escape(key)); sb.append("\":"); if(value==null){ sb.append("null"); return sb.toString(); } if(value instanceof String){ sb.append("\""); sb.append(escape((String)value)); sb.append("\""); } else sb.append(value); return sb.toString(); } /** * " => \" , \ => \\ * @param s * @return */ public static String escape(String s){ if(s==null) return null; StringBuffer sb=new StringBuffer(); for(int i=0;i='\u0000' && ch<='\u001F'){ String ss=Integer.toHexString(ch); sb.append("\\u"); for(int k=0;k<4-ss.length();k++){ sb.append('0'); } sb.append(ss.toUpperCase()); } else{ sb.append(ch); } } }//for return sb.toString(); } } azureus-4.3.0.6/org/json/simple/parser/0000755000175000017500000000000011310377640017165 5ustar adrianadrianazureus-4.3.0.6/org/json/simple/parser/Yytoken.java0000644000175000017500000000145710631203054021471 0ustar adrianadrian/* * $Id: Yytoken.java,v 1.1 2007/06/05 00:43:56 tuxpaper Exp $ * Created on 2006-4-15 */ package org.json.simple.parser; /** * @author FangYidong */ public class Yytoken { public static final int TYPE_VALUE=0;//JSON primitive value: string,number,boolean,null public static final int TYPE_LEFT_BRACE=1; public static final int TYPE_RIGHT_BRACE=2; public static final int TYPE_LEFT_SQUARE=3; public static final int TYPE_RIGHT_SQUARE=4; public static final int TYPE_COMMA=5; public static final int TYPE_COLON=6; public static final int TYPE_EOF=-1;//end of file public int type=0; public Object value=null; public Yytoken(int type,Object value){ this.type=type; this.value=value; } public String toString(){ return String.valueOf(type+"=>|"+value+"|"); } } azureus-4.3.0.6/org/json/simple/parser/Yylex.java0000644000175000017500000002570310631203054021141 0ustar adrianadrianpackage org.json.simple.parser; class Yylex { private final int YY_BUFFER_SIZE = 512; private final int YY_F = -1; private final int YY_NO_STATE = -1; private final int YY_NOT_ACCEPT = 0; private final int YY_START = 1; private final int YY_END = 2; private final int YY_NO_ANCHOR = 4; private final int YY_BOL = 65536; private final int YY_EOF = 65537; private StringBuffer sb=new StringBuffer(); private java.io.BufferedReader yy_reader; private int yy_buffer_index; private int yy_buffer_read; private int yy_buffer_start; private int yy_buffer_end; private char yy_buffer[]; private boolean yy_at_bol; private int yy_lexical_state; Yylex (java.io.Reader reader) { this (); if (null == reader) { throw (new Error("Error: Bad input stream initializer.")); } yy_reader = new java.io.BufferedReader(reader); } Yylex (java.io.InputStream instream) { this (); if (null == instream) { throw (new Error("Error: Bad input stream initializer.")); } yy_reader = new java.io.BufferedReader(new java.io.InputStreamReader(instream)); } private Yylex () { yy_buffer = new char[YY_BUFFER_SIZE]; yy_buffer_read = 0; yy_buffer_index = 0; yy_buffer_start = 0; yy_buffer_end = 0; yy_at_bol = true; yy_lexical_state = YYINITIAL; } private boolean yy_eof_done = false; private final int YYINITIAL = 0; private final int STRING_BEGIN = 1; private final int yy_state_dtrans[] = { 0, 39 }; private void yybegin (int state) { yy_lexical_state = state; } private int yy_advance () throws java.io.IOException { int next_read; int i; int j; if (yy_buffer_index < yy_buffer_read) { return yy_buffer[yy_buffer_index++]; } if (0 != yy_buffer_start) { i = yy_buffer_start; j = 0; while (i < yy_buffer_read) { yy_buffer[j] = yy_buffer[i]; ++i; ++j; } yy_buffer_end = yy_buffer_end - yy_buffer_start; yy_buffer_start = 0; yy_buffer_read = j; yy_buffer_index = j; next_read = yy_reader.read(yy_buffer, yy_buffer_read, yy_buffer.length - yy_buffer_read); if (-1 == next_read) { return YY_EOF; } yy_buffer_read = yy_buffer_read + next_read; } while (yy_buffer_index >= yy_buffer_read) { if (yy_buffer_index >= yy_buffer.length) { yy_buffer = yy_double(yy_buffer); } next_read = yy_reader.read(yy_buffer, yy_buffer_read, yy_buffer.length - yy_buffer_read); if (-1 == next_read) { return YY_EOF; } yy_buffer_read = yy_buffer_read + next_read; } return yy_buffer[yy_buffer_index++]; } private void yy_move_end () { if (yy_buffer_end > yy_buffer_start && '\n' == yy_buffer[yy_buffer_end-1]) yy_buffer_end--; if (yy_buffer_end > yy_buffer_start && '\r' == yy_buffer[yy_buffer_end-1]) yy_buffer_end--; } private boolean yy_last_was_cr=false; private void yy_mark_start () { yy_buffer_start = yy_buffer_index; } private void yy_mark_end () { yy_buffer_end = yy_buffer_index; } private void yy_to_mark () { yy_buffer_index = yy_buffer_end; yy_at_bol = (yy_buffer_end > yy_buffer_start) && ('\r' == yy_buffer[yy_buffer_end-1] || '\n' == yy_buffer[yy_buffer_end-1] || 2028/*LS*/ == yy_buffer[yy_buffer_end-1] || 2029/*PS*/ == yy_buffer[yy_buffer_end-1]); } private java.lang.String yytext () { return (new java.lang.String(yy_buffer, yy_buffer_start, yy_buffer_end - yy_buffer_start)); } private int yylength () { return yy_buffer_end - yy_buffer_start; } private char[] yy_double (char buf[]) { int i; char newbuf[]; newbuf = new char[2*buf.length]; for (i = 0; i < buf.length; ++i) { newbuf[i] = buf[i]; } return newbuf; } private final int YY_E_INTERNAL = 0; private final int YY_E_MATCH = 1; private java.lang.String yy_error_string[] = { "Error: Internal error.\n", "Error: Unmatched input.\n" }; private void yy_error (int code,boolean fatal) { java.lang.System.out.print(yy_error_string[code]); java.lang.System.out.flush(); if (fatal) { throw new Error("Fatal Error.\n"); } } private int[][] unpackFromString(int size1, int size2, String st) { int colonIndex = -1; String lengthString; int sequenceLength = 0; int sequenceInteger = 0; int commaIndex; String workString; int res[][] = new int[size1][size2]; for (int i= 0; i < size1; i++) { for (int j= 0; j < size2; j++) { if (sequenceLength != 0) { res[i][j] = sequenceInteger; sequenceLength--; continue; } commaIndex = st.indexOf(','); workString = (commaIndex==-1) ? st : st.substring(0, commaIndex); st = st.substring(commaIndex+1); colonIndex = workString.indexOf(':'); if (colonIndex == -1) { res[i][j]=Integer.parseInt(workString); continue; } lengthString = workString.substring(colonIndex+1); sequenceLength=Integer.parseInt(lengthString); workString=workString.substring(0,colonIndex); sequenceInteger=Integer.parseInt(workString); res[i][j] = sequenceInteger; sequenceLength--; } } return res; } private int yy_acpt[] = { /* 0 */ YY_NOT_ACCEPT, /* 1 */ YY_NO_ANCHOR, /* 2 */ YY_NO_ANCHOR, /* 3 */ YY_NO_ANCHOR, /* 4 */ YY_NO_ANCHOR, /* 5 */ YY_NO_ANCHOR, /* 6 */ YY_NO_ANCHOR, /* 7 */ YY_NO_ANCHOR, /* 8 */ YY_NO_ANCHOR, /* 9 */ YY_NO_ANCHOR, /* 10 */ YY_NO_ANCHOR, /* 11 */ YY_NO_ANCHOR, /* 12 */ YY_NO_ANCHOR, /* 13 */ YY_NO_ANCHOR, /* 14 */ YY_NO_ANCHOR, /* 15 */ YY_NO_ANCHOR, /* 16 */ YY_NO_ANCHOR, /* 17 */ YY_NO_ANCHOR, /* 18 */ YY_NO_ANCHOR, /* 19 */ YY_NO_ANCHOR, /* 20 */ YY_NO_ANCHOR, /* 21 */ YY_NO_ANCHOR, /* 22 */ YY_NO_ANCHOR, /* 23 */ YY_NO_ANCHOR, /* 24 */ YY_NO_ANCHOR, /* 25 */ YY_NOT_ACCEPT, /* 26 */ YY_NO_ANCHOR, /* 27 */ YY_NO_ANCHOR, /* 28 */ YY_NOT_ACCEPT, /* 29 */ YY_NOT_ACCEPT, /* 30 */ YY_NOT_ACCEPT, /* 31 */ YY_NOT_ACCEPT, /* 32 */ YY_NOT_ACCEPT, /* 33 */ YY_NOT_ACCEPT, /* 34 */ YY_NOT_ACCEPT, /* 35 */ YY_NOT_ACCEPT, /* 36 */ YY_NOT_ACCEPT, /* 37 */ YY_NOT_ACCEPT, /* 38 */ YY_NOT_ACCEPT, /* 39 */ YY_NOT_ACCEPT, /* 40 */ YY_NOT_ACCEPT, /* 41 */ YY_NOT_ACCEPT, /* 42 */ YY_NOT_ACCEPT, /* 43 */ YY_NOT_ACCEPT, /* 44 */ YY_NOT_ACCEPT }; private int yy_cmap[] = unpackFromString(1,65538, "11:8,27:2,28,11,27,28,11:18,27,11,2,11:8,16,25,12,14,3,13:10,26,11:6,10:4,1" + "5,10,11:20,23,1,24,11:3,18,4,10:2,17,5,11:5,19,11,6,11:3,7,20,8,9,11:5,21,1" + "1,22,11:65410,0:2")[0]; private int yy_rmap[] = unpackFromString(1,45, "0,1:2,2,1:7,3,1:2,4,1:10,5,6,1,7,8,9,10,11,12,13,14,15,16,6,17,18,19,20,21," + "22")[0]; private int yy_nxt[][] = unpackFromString(23,29, "1,-1,2,-1:2,25,28,-1,29,-1:3,30,3,-1:7,4,5,6,7,8,9,10:2,-1:42,3,33,34,-1,34" + ",-1:24,11,-1,34,-1,34,-1:12,16,17,18,19,20,21,22,23,40,-1:37,31,-1:23,26,-1" + ":24,42,-1:26,32,-1:34,3,-1:34,35,-1:18,37,-1:32,11,-1:27,38,26,-1:2,38,-1:3" + "2,37,-1:27,12,-1:26,13,-1:11,1,14,15,27:25,-1:5,44:2,-1:4,44,-1:2,44,-1,44," + "-1,44:2,-1:14,24:2,-1:4,24,-1:2,24,-1,24,-1,24:2,-1:29,36,-1:13,41:2,-1:4,4" + "1,-1:2,41,-1,41,-1,41:2,-1:14,43:2,-1:4,43,-1:2,43,-1,43,-1,43:2,-1:10"); public Yytoken yylex () throws java.io.IOException { int yy_lookahead; int yy_anchor = YY_NO_ANCHOR; int yy_state = yy_state_dtrans[yy_lexical_state]; int yy_next_state = YY_NO_STATE; int yy_last_accept_state = YY_NO_STATE; boolean yy_initial = true; int yy_this_accept; yy_mark_start(); yy_this_accept = yy_acpt[yy_state]; if (YY_NOT_ACCEPT != yy_this_accept) { yy_last_accept_state = yy_state; yy_mark_end(); } while (true) { if (yy_initial && yy_at_bol) yy_lookahead = YY_BOL; else yy_lookahead = yy_advance(); yy_next_state = YY_F; yy_next_state = yy_nxt[yy_rmap[yy_state]][yy_cmap[yy_lookahead]]; if (YY_EOF == yy_lookahead && true == yy_initial) { return null; } if (YY_F != yy_next_state) { yy_state = yy_next_state; yy_initial = false; yy_this_accept = yy_acpt[yy_state]; if (YY_NOT_ACCEPT != yy_this_accept) { yy_last_accept_state = yy_state; yy_mark_end(); } } else { if (YY_NO_STATE == yy_last_accept_state) { throw (new Error("Lexical Error: Unmatched Input.")); } else { yy_anchor = yy_acpt[yy_last_accept_state]; if (0 != (YY_END & yy_anchor)) { yy_move_end(); } yy_to_mark(); switch (yy_last_accept_state) { case 1: case -2: break; case 2: { sb.delete(0,sb.length());yybegin(STRING_BEGIN);} case -3: break; case 3: { Long val=Long.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);} case -4: break; case 4: { return new Yytoken(Yytoken.TYPE_LEFT_BRACE,null);} case -5: break; case 5: { return new Yytoken(Yytoken.TYPE_RIGHT_BRACE,null);} case -6: break; case 6: { return new Yytoken(Yytoken.TYPE_LEFT_SQUARE,null);} case -7: break; case 7: { return new Yytoken(Yytoken.TYPE_RIGHT_SQUARE,null);} case -8: break; case 8: { return new Yytoken(Yytoken.TYPE_COMMA,null);} case -9: break; case 9: { return new Yytoken(Yytoken.TYPE_COLON,null);} case -10: break; case 10: {} case -11: break; case 11: { Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);} case -12: break; case 12: { return new Yytoken(Yytoken.TYPE_VALUE,null);} case -13: break; case 13: { Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);} case -14: break; case 14: { sb.append(yytext());} case -15: break; case 15: { yybegin(YYINITIAL);return new Yytoken(Yytoken.TYPE_VALUE,sb.toString());} case -16: break; case 16: {sb.append('\\');} case -17: break; case 17: {sb.append('"');} case -18: break; case 18: {sb.append('/');} case -19: break; case 19: {sb.append('\b');} case -20: break; case 20: {sb.append('\f');} case -21: break; case 21: {sb.append('\n');} case -22: break; case 22: {sb.append('\r');} case -23: break; case 23: {sb.append('\t');} case -24: break; case 24: { int ch=Integer.parseInt(yytext().substring(2),16); sb.append((char)ch); } case -25: break; case 26: { Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);} case -26: break; case 27: { sb.append(yytext());} case -27: break; default: yy_error(YY_E_INTERNAL,false); case -1: } yy_initial = true; yy_state = yy_state_dtrans[yy_lexical_state]; yy_next_state = YY_NO_STATE; yy_last_accept_state = YY_NO_STATE; yy_mark_start(); yy_this_accept = yy_acpt[yy_state]; if (YY_NOT_ACCEPT != yy_this_accept) { yy_last_accept_state = yy_state; yy_mark_end(); } } } } } } azureus-4.3.0.6/org/json/simple/parser/JSONParser.java0000644000175000017500000001151611046520740021757 0ustar adrianadrian/* * $Id: JSONParser.java,v 1.2 2008/08/07 01:18:55 parg Exp $ * Created on 2006-4-15 */ package org.json.simple.parser; import java.io.Reader; import java.util.Stack; import org.gudy.azureus2.core3.util.LightHashMap; import org.json.simple.JSONArray; import org.json.simple.JSONObject; /** * @author FangYidong */ public class JSONParser { public static final int S_INIT=0; public static final int S_IN_FINISHED_VALUE=1;//string,number,boolean,null,object,array public static final int S_IN_OBJECT=2; public static final int S_IN_ARRAY=3; public static final int S_PASSED_PAIR_KEY=4; public static final int S_IN_ERROR=-1; private int peekStatus(Stack statusStack){ if(statusStack.size()==0) return -1; Integer status=(Integer)statusStack.peek(); return status.intValue(); } public Object parse(Reader in) throws Exception{ Stack statusStack=new Stack(); Stack valueStack=new Stack(); Yylex lexer=new Yylex(in); Yytoken token=null; int status=S_INIT; try{ do{ token=lexer.yylex(); if(token==null) token=new Yytoken(Yytoken.TYPE_EOF,null); switch(status){ case S_INIT: switch(token.type){ case Yytoken.TYPE_VALUE: status=S_IN_FINISHED_VALUE; statusStack.push(new Integer(status)); valueStack.push(token.value); break; case Yytoken.TYPE_LEFT_BRACE: status=S_IN_OBJECT; statusStack.push(new Integer(status)); valueStack.push(new JSONObject()); break; case Yytoken.TYPE_LEFT_SQUARE: status=S_IN_ARRAY; statusStack.push(new Integer(status)); valueStack.push(new JSONArray()); break; default: status=S_IN_ERROR; }//inner switch break; case S_IN_FINISHED_VALUE: if(token.type==Yytoken.TYPE_EOF) return valueStack.pop(); else return null; case S_IN_OBJECT: switch(token.type){ case Yytoken.TYPE_COMMA: break; case Yytoken.TYPE_VALUE: if(token.value instanceof String){ String key=(String)token.value; valueStack.push(key); status=S_PASSED_PAIR_KEY; statusStack.push(new Integer(status)); } else{ status=S_IN_ERROR; } break; case Yytoken.TYPE_RIGHT_BRACE: if(valueStack.size()>1){ statusStack.pop(); JSONObject map = (JSONObject)valueStack.pop(); map.compactify(-0.9f); status=peekStatus(statusStack); } else{ status=S_IN_FINISHED_VALUE; } break; default: status=S_IN_ERROR; break; }//inner switch break; case S_PASSED_PAIR_KEY: switch(token.type){ case Yytoken.TYPE_COLON: break; case Yytoken.TYPE_VALUE: statusStack.pop(); String key=(String)valueStack.pop(); JSONObject parent=(JSONObject)valueStack.peek(); parent.put(key,token.value); status=peekStatus(statusStack); break; case Yytoken.TYPE_LEFT_SQUARE: statusStack.pop(); key=(String)valueStack.pop(); parent=(JSONObject)valueStack.peek(); JSONArray newArray=new JSONArray(); parent.put(key,newArray); status=S_IN_ARRAY; statusStack.push(new Integer(status)); valueStack.push(newArray); break; case Yytoken.TYPE_LEFT_BRACE: statusStack.pop(); key=(String)valueStack.pop(); parent=(JSONObject)valueStack.peek(); JSONObject newObject=new JSONObject(); parent.put(key,newObject); status=S_IN_OBJECT; statusStack.push(new Integer(status)); valueStack.push(newObject); break; default: status=S_IN_ERROR; } break; case S_IN_ARRAY: switch(token.type){ case Yytoken.TYPE_COMMA: break; case Yytoken.TYPE_VALUE: JSONArray val=(JSONArray)valueStack.peek(); val.add(token.value); break; case Yytoken.TYPE_RIGHT_SQUARE: if(valueStack.size()>1){ statusStack.pop(); valueStack.pop(); status=peekStatus(statusStack); } else{ status=S_IN_FINISHED_VALUE; } break; case Yytoken.TYPE_LEFT_BRACE: val=(JSONArray)valueStack.peek(); JSONObject newObject=new JSONObject(); val.add(newObject); status=S_IN_OBJECT; statusStack.push(new Integer(status)); valueStack.push(newObject); break; case Yytoken.TYPE_LEFT_SQUARE: val=(JSONArray)valueStack.peek(); JSONArray newArray=new JSONArray(); val.add(newArray); status=S_IN_ARRAY; statusStack.push(new Integer(status)); valueStack.push(newArray); break; default: status=S_IN_ERROR; }//inner switch break; case S_IN_ERROR: return null; }//switch if(status==S_IN_ERROR) return null; }while(token.type!=Yytoken.TYPE_EOF); } catch(Exception e){ throw e; } return null; } } azureus-4.3.0.6/org/json/simple/LICENSE.txt0000644000175000017500000006350410631203054017514 0ustar adrianadrian GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! azureus-4.3.0.6/org/json/simple/JSONValue.java0000644000175000017500000000131610631203054020273 0ustar adrianadrian/* * $Id: JSONValue.java,v 1.1 2007/06/05 00:43:56 tuxpaper Exp $ * Created on 2006-4-15 */ package org.json.simple; import java.io.Reader; import java.io.StringReader; import org.json.simple.parser.JSONParser; /** * @author FangYidong */ public class JSONValue { /** * parse into java object from input source. * @param in * @return instance of : JSONObject,JSONArray,String,Boolean,Long,Double or null */ public static Object parse(Reader in){ try{ JSONParser parser=new JSONParser(); return parser.parse(in); } catch(Exception e){ return null; } } public static Object parse(String s){ StringReader in=new StringReader(s); return parse(in); } } azureus-4.3.0.6/org/json/simple/JSONArray.java0000644000175000017500000000144610631203054020301 0ustar adrianadrian/* * $Id: JSONArray.java,v 1.1 2007/06/05 00:43:56 tuxpaper Exp $ * Created on 2006-4-10 */ package org.json.simple; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * @author FangYidong */ public class JSONArray extends ArrayList { public JSONArray() { super(); } public JSONArray(Collection arg0) { super(arg0); } public JSONArray(int initialCapacity) { super(initialCapacity); } public String toString(){ ItemList list=new ItemList(); Iterator iter=iterator(); while(iter.hasNext()){ Object value=iter.next(); if(value instanceof String){ list.add("\""+JSONObject.escape((String)value)+"\""); } else list.add(String.valueOf(value)); } return "["+list.toString()+"]"; } } azureus-4.3.0.6/org/json/simple/ItemList.java0000644000175000017500000000667111157341622020300 0ustar adrianadrian/* * $Id: ItemList.java,v 1.2 2009/03/15 22:12:18 parg Exp $ * Created on 2006-3-24 */ package org.json.simple; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; /** * ÷ָֿһitem.ָһһitem.ÿitem߲ǿհ׷. * 磺 * |a:b:c| => |a|,|b|,|c| * |:| => ||,|| * |a:| => |a|,|| * @author FangYidong */ public class ItemList { private String sp=","; List items=new ArrayList(); public ItemList(){} /** * * @param s ָһַ */ public ItemList(String s){ this.split(s,sp,items); } /** * * @param s ָһַ * @param sp ָ */ public ItemList(String s,String sp){ this.sp=s; this.split(s,sp,items); } /** * * @param s * @param sp * @param isMultiToken spǷΪָ */ public ItemList(String s,String sp,boolean isMultiToken){ split(s,sp,items,isMultiToken); } public List getItems(){ return this.items; } public String[] getArray(){ return (String[])this.items.toArray(new String[items.size()]); } public void split(String s,String sp,List append,boolean isMultiToken){ if(s==null || sp==null) return; if(isMultiToken){ StringTokenizer tokens=new StringTokenizer(s,sp); while(tokens.hasMoreTokens()){ append.add(tokens.nextToken().trim()); } } else{ this.split(s,sp,append); } } public void split(String s,String sp,List append){ if(s==null || sp==null) return; int pos=0; int prevPos=0; do{ prevPos=pos; pos=s.indexOf(sp,pos); if(pos==-1) break; append.add(s.substring(prevPos,pos).trim()); pos+=sp.length(); }while(pos!=-1); append.add(s.substring(prevPos).trim()); } /** * ÷ָ. * @param sp ָ */ public void setSP(String sp){ this.sp=sp; } /** * 뵥item. * @param i λ(֮ǰ) * @param item */ public void add(int i,String item){ if(item==null) return; items.add(i,item.trim()); } /** * 뵥item. * @param item */ public void add(String item){ if(item==null) return; items.add(item.trim()); } /** * һitem. * @param list list */ public void addAll(ItemList list){ items.addAll(list.items); } /** * һitem. * @param s ָһַ */ public void addAll(String s){ this.split(s,sp,items); } /** * һitem. * @param s ָһַ * @param sp ָ */ public void addAll(String s,String sp){ this.split(s,sp,items); } public void addAll(String s,String sp,boolean isMultiToken){ this.split(s,sp,items,isMultiToken); } /** * õiitem. 0-based. * @param i * @return */ public String get(int i){ return (String)items.get(i); } /** * item. * @return */ public int size(){ return items.size(); } /** * ÷ָָıʾ. */ public String toString(){ return toString(sp); } /** * ÷ָָıʾ. * @param sp ø÷ָָ. * @return */ public String toString(String sp){ StringBuffer sb=new StringBuffer(); for(int i=0;iazureus-4.3.0.6/org/json/simple/README.txt0000644000175000017500000001207310631203054017362 0ustar adrianadrianSimple Java toolkit for JSON (JSON.simple) ========================================== 1.Why the Simple Java toolkit (also named as JSON.simple) for JSON? When I use JSON as the data exchange format between the AJAX client and JSP for the first time, what worry me mostly is how to encode Java strings and numbers correctly in the server side so the AJAX client will receive a well formed JSON data. When I looked into the 'JSON in Java' directory in JSON website,I found that wrappers to JSONObject and JSONArray can be simpler, due to the simplicity of JSON itself. So I wrote the JSON.simple package. 2.Is it simple,really? I think so. Take an example: import org.json.simple.JSONObject; JSONObject obj=new JSONObject(); obj.put("name","foo"); obj.put("num",new Integer(100)); obj.put("balance",new Double(1000.21)); obj.put("is_vip",new Boolean(true)); obj.put("nickname",null); System.out.print(obj); Result: {"nickname":null,"num":100,"balance":1000.21,"is_vip":true,"name":"foo"} The JSONObject.toString() will escape controls and specials correctly. 3.How to use JSON.simple in JSP? Take an example in JSP: <%@page contentType="text/html; charset=UTF-8"%> <%@page import="org.json.simple.JSONObject"%> <% JSONObject obj=new JSONObject(); obj.put("name","foo"); obj.put("num",new Integer(100)); obj.put("balance",new Double(1000.21)); obj.put("is_vip",new Boolean(true)); obj.put("nickname",null); out.print(obj); out.flush(); %> So the AJAX client will get the responseText. 4.Some details about JSONObject? JSONObject inherits java.util.HashMap,so it don't have to worry about the mapping things between keys and values. Feel free to use the Map methods like get(), put(), and remove() and others. JSONObject.toString() will combine key value pairs to get the JSON data string. Values will be escaped into JSON quote string format if it's an instance of java.lang.String. Other type of instance like java.lang.Number,java.lang.Boolean,null,JSONObject and JSONArray will NOT escape, just take their java.lang.String.valueOf() result. null value will be the JSON 'null' in the result. It's still correct if you put an instance of JSONObject or JSONArray into an instance of JSONObject or JSONArray. Take the example about: JSONObject obj2=new JSONObject(); obj2.put("phone","123456"); obj2.put("zip","7890"); obj.put("contact",obj2); System.out.print(obj); Result: {"nickname":null,"num":100,"contact":{"phone":"123456","zip":"7890"},"balance":1000.21,"is_vip":true,"name":"foo"} The method JSONObject.escape() is used to escape Java string into JSON quote string. Controls and specials will be escaped correctly into \b,\f,\r,\n,\t, \",\\,\/,\uhhhh. 5.Some detail about JSONArray? org.json.simple.JSONArray inherits java.util.ArrayList. Feel free to use the List methods like get(),add(),remove(),iterator() and so on. The rules of JSONArray.toString() is similar to JSONObject.toString(). Here's the example: import org.json.simple.JSONArray; JSONArray array=new JSONArray(); array.add("hello"); array.add(new Integer(123)); array.add(new Boolean(false)); array.add(null); array.add(new Double(123.45)); array.add(obj2);//see above System.out.print(array); Result: ["hello",123,false,null,123.45,{"phone":"123456","zip":"7890"}] 6.What is JSONValue for? org.json.simple.JSONValue is use to parse JSON data into Java Object. In JSON, the topmost entity is JSON value, not the JSON object. But it's not necessary to wrap JSON string,boolean,number and null again, for the Java has already had the according classes: java.lang.String, java.lang.Boolean,java.lang.Number and null. The mapping is: JSON Java ------------------------------------------------ string <=> java.lang.String number <=> java.lang.Number true|false <=> java.lang.Boolean null <=> null array <=> org.json.simple.JSONArray object <=> org.json.simple.JSONObject ------------------------------------------------ JSONValue has only one kind of method, JSONValue.parse(), which receives a java.io.Reader or java.lang.String. Return type of JSONValue.parse() is according to the mapping above. If the input is incorrect in syntax or there's exceptions during the parsing, I choose to return null, ignoring the exception: I have no idea if it's a serious implementaion, but I think it's convenient to the user. Here's the example: String s="[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]"; Object obj=JSONValue.parse(s); JSONArray array=(JSONArray)obj; System.out.println(array.get(1)); JSONObject obj2=(JSONObject)array.get(1); System.out.println(obj2.get("1")); Result: {"1":{"2":{"3":{"4":[5,{"6":7}]}}}} {"2":{"3":{"4":[5,{"6":7}]}}} 7.About the author. I'm a Java EE developer on Linux. I'm working on web systems and information retrieval systems. I also develop 3D games and Flash games. You can contact me through: Fang Yidong Fang Yidong azureus-4.3.0.6/org/json/simple/Test.java0000644000175000017500000000271210631203054017445 0ustar adrianadrian/* * $Id: Test.java,v 1.1 2007/06/05 00:43:56 tuxpaper Exp $ * Created on 2006-4-15 */ package org.json.simple; /** * @author FangYidong */ public class Test { public static void main(String[] args) throws Exception{ JSONArray array1=new JSONArray(); array1.add("abc\u0010a/"); array1.add(new Integer(123)); array1.add(new Double(122.22)); array1.add(new Boolean(true)); System.out.println("======array1=========="); System.out.println(array1); System.out.println(); JSONObject obj1=new JSONObject(); obj1.put("name","fang"); obj1.put("age",new Integer(27)); obj1.put("is_developer",new Boolean(true)); obj1.put("weight",new Double(60.21)); obj1.put("array1",array1); System.out.println(); System.out.println("======obj1 with array1==========="); System.out.println(obj1); System.out.println(); obj1.remove("array1"); array1.add(obj1); System.out.println("======array1 with obj1========"); System.out.println(array1); System.out.println(); System.out.println("======parse to java========"); String s="[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]"; Object obj=JSONValue.parse(s); JSONArray array=(JSONArray)obj; System.out.println("======the 2nd element of array======"); System.out.println(array.get(1)); System.out.println(); JSONObject obj2=(JSONObject)array.get(1); System.out.println("======field \"1\"=========="); System.out.println(obj2.get("1")); } } azureus-4.3.0.6/org/gudy/0000755000175000017500000000000011310377466014405 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/0000755000175000017500000000000011310377466016165 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/0000755000175000017500000000000011310377634017643 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/config/0000755000175000017500000000000011310377616021110 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/config/ConfigParameterListener.java0000644000175000017500000000216710373051036026526 0ustar adrianadrian/* * Created on 30-Aug-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.config; /** * @author parg * */ public interface ConfigParameterListener { public void configParameterChanged( ConfigParameter param ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/config/PluginConfigSource.java0000644000175000017500000001056511011407706025517 0ustar adrianadrian/* * Created on 6 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.config; import java.io.File; import org.gudy.azureus2.plugins.Plugin; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.PluginConfig; /** * This interface provides a mechanism for plugins to store configuration * settings in a separate configuration file (rather than the main Azureus * configuration file). * *

* * Important: If you are using this class for a plugin which previously * used to store configuration settings in the main configuration file * (which is what most existing plugins do), you should call the * {@link #forceSettingsMigration()} method to get existing settings moved * over - please read the comments for that file if you need to do that. * *

* * To create an instance of this file, you need to call * {@link PluginConfig#enableExternalConfigSource()}. Once you have an instance, * you then need to call {@link #initialize()} to configure it - though there * are additional methods that you can call for additional configuration. * *

Note: Only for implementation by Azureus, not plugins.

*/ public interface PluginConfigSource { /** * This initializes this configuration object and gets the external * configuration file integrated with Azureus. * *

* * It performs the following steps: *

    *
  • Loads the data of any existing config file into Azureus. *
  • Registers all parameters in the file to be stored inside * this configuration file (so all changes will be stored here). *
  • Adds a hook to allow it to be automatically saved when * Azureus autosaves its own internal configuration files. *
  • Adds a hook to intercept any configuration settings created * and used by the plugin and stores it internally (rather than * being saved in the main Azureus config file). *
*/ public void initialize(); /** * This method sets the filename for the configuration file that this * object links to - this must be done before the {@link #initialize()} * method is called. * * @param filename The filename to use. */ public void setConfigFilename(String filename); /** * Returns a file object which represents the location of the configuration * file that this object interacts with. */ public File getConfigFile(); /** * Manually saves the configuration settings recorded by this object to * disk. This isn't normally required, as Azureus will automatically * save the configuration file when the main configuration file is * saved, but you can choose to save on demand if you wish. * *

* * @param force true if you want the file to be written to * regardless of whether there are any changes, false if * you only want to save the file if there are unsaved changes. */ public void save(boolean force); /** * If your plugin previously used to store data in the main configuration file, * you can call this method (which needs to be done soon after initialization) * which will move all monitored parameters over to this object. * *

* * You have to call this method before you initialize the object. It's also * recommended that if you call this method, that you call {@link #save(boolean)} * to save any settings copied across - probably best to be done as the last thing * of the {@link Plugin#initialize(PluginInterface)} method. */ public void forceSettingsMigration(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/config/ConfigParameter.java0000644000175000017500000000230710373051036025014 0ustar adrianadrian/* * Created on 30-Aug-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.config; /** * @author parg * */ public interface ConfigParameter { public void addConfigParameterListener( ConfigParameterListener l ); public void removeConfigParameterListener( ConfigParameterListener l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/installer/0000755000175000017500000000000011310377616021640 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/installer/PluginInstallationListener.java0000644000175000017500000000202111155331574030024 0ustar adrianadrian/* * Created on Mar 6, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.installer; import org.gudy.azureus2.plugins.PluginException; public interface PluginInstallationListener { public void completed(); public void cancelled(); public void failed( PluginException e ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/installer/PluginInstallerListener.java0000644000175000017500000000247610373051022027322 0ustar adrianadrian/* * Created on 22-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.installer; import org.gudy.azureus2.plugins.PluginException; public interface PluginInstallerListener { /** * * @param reason * @param plugin * @return true if the request can be satisfied * @throws PluginException */ public boolean installRequest( String reason, InstallablePlugin plugin ) throws PluginException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/installer/InstallablePlugin.java0000644000175000017500000000416511040206514026106 0ustar adrianadrian/* * Created on 30-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.installer; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.PluginInterface; /** * @author parg * */ public interface InstallablePlugin { public String getId(); public String getVersion(); public String getName(); public String getDescription(); public String getRelativeURLBase(); /** * Returns the plugin's interface if already installed, null if it isn't * @return */ public PluginInterface getAlreadyInstalledPlugin(); public boolean isAlreadyInstalled(); public void install( boolean shared ) throws PluginException; /** * Install with a few options to control process * @param shared * @param low_noise don't prompt user * @param wait_until_done if true blocks until process complete, otherwise it is async * @throws PluginException * @since 3.1.1.1 */ public void install( boolean shared, boolean low_noise, boolean wait_until_done ) throws PluginException; /** * uninstall this plugin * @throws PluginException */ public void uninstall() throws PluginException; public PluginInstaller getInstaller(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/installer/PluginInstaller.java0000644000175000017500000000545111154423450025616 0ustar adrianadrian/* * Created on 28-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.installer; import java.io.File; import java.util.Map; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.PluginInterface; /** * @author parg * */ public interface PluginInstaller { /** * Gives access to the list of standard plugins listed on the Azureus website * @return */ public StandardPlugin[] getStandardPlugins() throws PluginException; public StandardPlugin getStandardPlugin( String id ) throws PluginException; /** * Requests any registered listeners to initiate a plugin install process * @param plugin * @throws PluginException */ public void requestInstall( String reason, InstallablePlugin plugin ) throws PluginException; /** * Install one of more plugins in a single operation * @param plugins */ public void install( InstallablePlugin[] plugins, boolean shared ) throws PluginException; public void install( InstallablePlugin[] plugins, boolean shared, Map properties, PluginInstallationListener listener ) throws PluginException; /** * Installs a plugin from a file - must be either a ZIP file or a JAR file as per * normal plugin update semantics. Name of file must be of the form: * "_" "." ["jar" | "zip" ]. * For example * myplugin_1.0.jar * @param file * @throws PluginException */ public FilePluginInstaller installFromFile( File file ) throws PluginException; public void uninstall( PluginInterface plugin_interface ) throws PluginException; public void uninstall( PluginInterface[] plugin_interfaces ) throws PluginException; public void addListener( PluginInstallerListener l ); public void removeListener( PluginInstallerListener l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/installer/StandardPlugin.java0000644000175000017500000000211310373051022025403 0ustar adrianadrian/* * Created on 28-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.installer; /** * @author parg * */ public interface StandardPlugin extends InstallablePlugin { } azureus-4.3.0.6/org/gudy/azureus2/plugins/installer/FilePluginInstaller.java0000644000175000017500000000217610373051022026411 0ustar adrianadrian/* * Created on 30-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.installer; import java.io.File; /** * @author parg * */ public interface FilePluginInstaller extends InstallablePlugin { public File getFile(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginInterface.java0000644000175000017500000003324011053114254023556 0ustar adrianadrian/* * File : PluginInterface.java * Created : 2 nov. 2003 18:48:47 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins; import java.util.Properties; import org.gudy.azureus2.plugins.sharing.ShareManager; import org.gudy.azureus2.plugins.sharing.ShareException; import org.gudy.azureus2.plugins.tracker.Tracker; import org.gudy.azureus2.plugins.utils.Utilities; import org.gudy.azureus2.plugins.logging.Logger; import org.gudy.azureus2.plugins.messaging.MessageManager; import org.gudy.azureus2.plugins.network.ConnectionManager; import org.gudy.azureus2.plugins.ipc.IPCInterface; import org.gudy.azureus2.plugins.ipfilter.IPFilter; import org.gudy.azureus2.plugins.ddb.DistributedDatabase; import org.gudy.azureus2.plugins.download.DownloadManager; import org.gudy.azureus2.plugins.torrent.TorrentManager; import org.gudy.azureus2.plugins.platform.PlatformManager; import org.gudy.azureus2.plugins.ui.*; import org.gudy.azureus2.plugins.ui.config.Parameter; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.plugins.ui.config.PluginConfigUIFactory; import org.gudy.azureus2.plugins.update.UpdateManager; import org.gudy.azureus2.plugins.utils.ShortCuts; import org.gudy.azureus2.plugins.clientid.*; import org.gudy.azureus2.plugins.dht.mainline.MainlineDHTManager; /** * Defines the communication interface between Azureus and Plugins * @author Olivier */ public interface PluginInterface { /** * Retrieve the name of the application. * * @return the Application's name * * @since 2.1.0.0 */ public String getAzureusName(); /** * Returns the name of the application that the user sees - if you need to * display the name of the program, you should use this method. * * @return 3.0.5.3 */ public String getApplicationName(); /** Retrieve the Application's version as a string. * * @return Application's version. Typically in the following formats (regexp):
* [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+
* [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+_CVS
* [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+_B[0-9]+ * * @since 2.1.0.0 */ public String getAzureusVersion(); /** * A Plugin might call this method to add a View to Azureus's views * The View will be accessible from View > Plugins > View name * @param view The PluginView to be added * * @since 2.0.4.0 * * @deprecated use {@link org.gudy.azureus2.ui.swt.plugins.UISWTInstance#addView} */ public void addView(PluginView view); /** * adds a tab under the 'plugins' tab in the config view.
* Use {@link #getPluginConfigUIFactory()} to get the * {@link PluginConfigUIFactory} class, from which you can create different * types of parameters. * * @param parameters the Parameter(s) to be edited * @param displayName the under which it should display.
* Azureus will look-up for ConfigView.section.plugins.displayName; into the lang files * in order to find the localized displayName. (see i18n) * * @since 2.0.6.0 * @deprecated Use of this is discouraged - use {@link UIManager#getBasicPluginViewModel(String)} * to get a BasicPluginViewModel instance, and then use the methods on that to add * parameters. */ public void addConfigUIParameters(Parameter[] parameters, String displayName); /** * adds a ConfigSection to the config view.

* In contrast to addConfigUIParameters, this gives you total control over * a tab. Please be kind and use localizable text.
* * @param section ConfigSection to be added to the Config view * * @since 2.0.8.0 * @deprecated Use {@link UIManager#createBasicPluginConfigModel(String)} instead. */ public void addConfigSection(ConfigSection section); /** * * @param section * @since 2.3.0.5 */ public void removeConfigSection( ConfigSection section ); /** * * @return List of ConfigSections for this plugin * * @since 2.5.0.1 */ ConfigSection[] getConfigSections(); /** * Gives access to the tracker functionality * @return The tracker * * @since 2.0.6.0 */ public Tracker getTracker(); /** * Gives access to the logger * @return The logger * * @since 2.0.7.0 */ public Logger getLogger(); /** * Gives access to the IP filter * @return An object that allows access to IP Filtering * * @since 2.0.8.0 */ public IPFilter getIPFilter(); /** * Gives access to the download manager * @return An object that allows management of downloads * * @since 2.0.7.0 */ public DownloadManager getDownloadManager(); /** * Gives access to the sharing functionality * @return * * @since 2.0.7.0 */ public ShareManager getShareManager() throws ShareException; /** * Gives access to the torrent manager * @return An object to manage torrents * * @since 2.0.8.0 */ public TorrentManager getTorrentManager(); /** * access to various utility functions * @return * * @since 2.1.0.0 */ public Utilities getUtilities(); /** * access to a set of convenience routines for doing things in a quicker, although less * structured, fashion * @return * * @since 2.1.0.0 */ public ShortCuts getShortCuts(); /** * access to UI extension features * @return * * @since 2.1.0.0 */ public UIManager getUIManager(); /** * access to the update manager used to update plugins. required for non-Azureus SF hosted * plugins (SF ones are managed automatically) * @return * * @since 2.1.0.0 */ public UpdateManager getUpdateManager(); /** * opens a torrent file given its name * @param fileName The Name of the file that azureus must open * * @since 2.0.4.0 * * @deprecated Use {@link DownloadManager#addDownload} */ public void openTorrentFile(String fileName); /** * opens a torrent file given the url it's at * @param url The String representation of the url pointing to a torrent file * * @since 2.0.4.0 * * @deprecated Use {@link DownloadManager#addDownload} */ public void openTorrentURL(String url); /** * gives access to the plugin properties * @return the properties from the file plugin.properties * * @since 2.0.4.0 */ public Properties getPluginProperties(); /** * Gives access to the plugin installation path - note, if you want to use this * path to store data files in, it would be better for you to use * {@link PluginConfig#getPluginUserFile(String)} instead. * @return the full path the plugin is installed in * * @since 2.0.4.0 */ public String getPluginDirectoryName(); /** * Returns the value of "plugin.name" if it exists in the properties file, otherwise the directory name is returned. * @since 2.1.0.0 */ public String getPluginName(); /** * Returns the version number of the plugin it if can be deduced from either the name of * the jar file it is loaded from or the properties file. null otherwise * * @return Version number as a string, or null * * @since 2.1.0.0 */ public String getPluginVersion(); /** * Returns an identifier used to identify this particular plugin * @return * * @since 2.1.0.0 */ public String getPluginID(); /** * Whether or not this is a mandatory plugin. Mandatory plugins take priority over update checks, for example, * over optional ones. * * @deprecated Use {@link PluginState#isMandatory()}. */ public boolean isMandatory(); /** * Built-in plugins are those used internally by Azureus, for example the UPnP plugin * @deprecated Use {@link PluginState#isBuiltIn()}. */ public boolean isBuiltIn(); /** * gives access to the plugin config interface * @return the PluginConfig object associated with this plugin */ public PluginConfig getPluginconfig(); /** * gives access to the plugin Config UI Factory * @return the PluginConfigUIFactory associated with this plugin * * @deprecated Use of this is discouraged - use {@link UIManager#getBasicPluginViewModel(String)} * to get a BasicPluginViewModel instance, and then use the methods on that to add * parameters. */ public PluginConfigUIFactory getPluginConfigUIFactory(); /** * gives access to the ClassLoader used to load the plugin * @return * * @since 2.0.8.0 */ public ClassLoader getPluginClassLoader(); /** * Returns an initialised plugin instance with its own scope (e.g. for config params). * Designed for loading secondary plugins directly from a primary one. * Note - ensure that the bundled secondary plugins do *not* contain a plugin.properties as * this will cause no end of problems. * @param plugin must implement Plugin * @param id the unique id of this plugin (used to scope config params etc) * @return */ public PluginInterface getLocalPluginInterface( Class plugin, String id ) throws PluginException; /** * get the inter-plugin-communcations interface for this plugin * @return */ public IPCInterface getIPC (); /** * Gives access to the plugin itself * @return * * @since 2.1.0.0 */ public Plugin getPlugin(); /** * Returns true if the plugin is running, returns false if the * plugin isn't running for some reason. * * @since 2.1.0.0 * @deprecated Use {@link PluginState#isOperational()}. */ public boolean isOperational(); /** * Returns true if the plugin has been marked as disabled, and prevented * from initialising. * * @deprecated Use {@link PluginState#isDisabled}. */ public boolean isDisabled(); /** * Sets whether the plugin can be loaded or not. If you are trying to affect if the plugin * can be loaded at startup - use {@link #setLoadedAtStartup(boolean)} instead. This needs * to be called prior to a plugin's initialisation to take effect. * * @since 2.3.0.1 * @param disabled * @deprecated Use {@link PluginState#setDisabled(boolean)}. */ public void setDisabled(boolean disabled); /** * @deprecated Use {@link PluginState#isUnloadable()}. * @since 2.1.0.0 */ public boolean isUnloadable(); /** * @since 2503/3005 * @deprecated Use {@link PluginState#isShared()}. */ public boolean isShared(); /** * @deprecated Use {@link PluginState#unload()}. * @since 2.1.0.0 */ public void unload() throws PluginException; /** * @deprecated Use {@link PluginState#reload()}. * @since 2.1.0.0 */ public void reload() throws PluginException; /** * Uninstall this plugin if it has been loaded from a plugin directory. Deletes the * plugin directory * @deprecated Use {@link PluginState#uninstall()}. * @throws PluginException */ public void uninstall() throws PluginException; /** * Indicates whether or not the current thread is the one responsible for running * plugin initialisation * @return */ public boolean isInitialisationThread(); /** * gives access to the plugin manager * @return * * @since 2.1.0.0 */ public PluginManager getPluginManager(); /** * * @return * @since 2.2.0.3 */ public ClientIDManager getClientIDManager(); /** * Get the connection manager. * @since 2.2.0.3 * @return manager */ public ConnectionManager getConnectionManager(); /** * Get the peer messaging manager. * @since 2.2.0.3 * @return manager */ public MessageManager getMessageManager(); /** * Get the distributed database * @since 2.2.0.3 * @return */ public DistributedDatabase getDistributedDatabase(); /** * Gets the platform manager that gives access to native functionality * @return */ public PlatformManager getPlatformManager(); /** * * @since 2.0.7.0 */ public void addListener( PluginListener l ); /** * * @since 2.0.7.0 */ public void removeListener( PluginListener l ); /** * Fire a plugin-specific event. See PluginEvent for details of type values to use * @since 2403 * @param event */ public void firePluginEvent( PluginEvent event ); /** * * @since 2.0.8.0 */ public void addEventListener( PluginEventListener l ); /** * * @since 2.0.8.0 */ public void removeEventListener( PluginEventListener l ); /** * Returns the manager object for registering plugins that connect to the * Mainline DHT. * * @since 3.0.4.3 */ public MainlineDHTManager getMainlineDHTManager(); /** * Returns an object that provides information the current state of the plugin, * and provides various mechanisms to query and control plugins and their * integration with Azureus at a low-level. * * @since 3.1.1.1 */ public PluginState getPluginState(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/0000755000175000017500000000000011310377634021276 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/TrackerTorrentListener.java0000644000175000017500000000262510221666412026620 0ustar adrianadrian/* * File : TrackerTorrentListener.java * Created : 14-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker; /** * @author parg * */ public interface TrackerTorrentListener { public void preProcess( TrackerTorrentRequest request ) throws TrackerException; /** * This is called to give the opportunity to post-process the reply being * sent to a peer. * If the reply is cached and reused this method *won't* be re-invoked. It is therefore * not appropriate to insert peer-specific data unless caching is *switched off* * @param request */ public void postProcess( TrackerTorrentRequest request ) throws TrackerException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/TrackerTorrent.java0000644000175000017500000000603210362264224025107 0ustar adrianadrian/* * File : TrackerTorrent.java * Created : 08-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker; /** * @author parg * */ import org.gudy.azureus2.plugins.torrent.*; public interface TrackerTorrent { public static final int TS_STARTED = 0; public static final int TS_STOPPED = 1; public static final int TS_PUBLISHED = 2; public void start() throws TrackerException; public void stop() throws TrackerException; public void remove() throws TrackerTorrentRemovalVetoException; public boolean canBeRemoved() throws TrackerTorrentRemovalVetoException; public Torrent getTorrent(); public TrackerPeer[] getPeers(); public int getStatus(); public int getSeedCount(); public int getLeecherCount(); /** * Gives access to the number of peers that have failed NAT checks, 0 if NAT checking * is disabled. * @return */ public int getBadNATCount(); public long getTotalUploaded(); public long getTotalDownloaded(); public long getAverageUploaded(); public long getAverageDownloaded(); public long getTotalLeft(); public long getCompletedCount(); /** * total bytes received by the tracker for this torrent - announce and scrape requests * @return */ public long getTotalBytesIn(); /** * average rate of bytes in * @return */ public long getAverageBytesIn(); /** * total bytes sent as response by the tracker - announce and scrape responses * @return */ public long getTotalBytesOut(); /** * average bytes sent * @return */ public long getAverageBytesOut(); public long getScrapeCount(); public long getAverageScrapeCount(); public long getAnnounceCount(); public long getAverageAnnounceCount(); /** * stops the tracker from caching replies to announces/scrapes for this torrent */ public void disableReplyCaching(); public boolean isPassive(); /** * @since 2.3.0.5 * @return */ public long getDateAdded(); public void addListener( TrackerTorrentListener listener ); public void removeListener( TrackerTorrentListener listener ); public void addRemovalListener( TrackerTorrentWillBeRemovedListener listener ); public void removeRemovalListener( TrackerTorrentWillBeRemovedListener listener ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/TrackerTorrentRemovalVetoException.java0000644000175000017500000000206011012741706031145 0ustar adrianadrian/* * File : TrackerTorrentRemovalVetoException.java * Created : 22-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker; /** * @author parg * */ public class TrackerTorrentRemovalVetoException extends Exception { public TrackerTorrentRemovalVetoException( String str ) { super( str ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/TrackerTorrentRequest.java0000644000175000017500000000236610221672464026471 0ustar adrianadrian/* * File : TrackerTorrentRequest.java * Created : 14-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker; import java.util.Map; /** * @author parg * */ public interface TrackerTorrentRequest { public static final int RT_ANNOUNCE = 1; public static final int RT_SCRAPE = 2; public static final int RT_FULL_SCRAPE = 3; public int getRequestType(); public TrackerTorrent getTorrent(); public TrackerPeer getPeer(); public String getRequest(); public Map getResponse(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/Tracker.java0000644000175000017500000000516010466155452023541 0ustar adrianadrian/* * File : Tracker.java * Created : 30 nov. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker; /** * @author Olivier * */ import java.net.InetAddress; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.tracker.web.TrackerWebContext; public interface Tracker extends TrackerWebContext { public static final int PR_HTTP = 1; public static final int PR_HTTPS = 2; public TrackerTorrent host( Torrent torrent, boolean persistent ) throws TrackerException; public TrackerTorrent host( Torrent torrent, boolean persistent, boolean passive ) throws TrackerException; public TrackerTorrent publish( Torrent torrent ) throws TrackerException; public TrackerTorrent getTorrent( Torrent torrent ); public TrackerTorrent[] getTorrents(); public TrackerWebContext createWebContext( int port, int protocol ) throws TrackerException; /** * Create a new web context for the given port and protocol * @param name name of the context - will be used as basic realm for auth * @param port * @param protocol * @return * @throws TrackerException */ public TrackerWebContext createWebContext( String name, int port, int protocol ) throws TrackerException; /** * Creates a new context bound to the supplied ip * @param name * @param port * @param protocol * @param bind_ip * @return * @throws TrackerException */ public TrackerWebContext createWebContext( String name, int port, int protocol, InetAddress bind_ip ) throws TrackerException; public void addListener( TrackerListener listener ); public void removeListener( TrackerListener listener ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/TrackerListener.java0000644000175000017500000000213010020501476025224 0ustar adrianadrian/* * File : TrackerListener.java * Created : 14-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker; /** * @author parg * */ public interface TrackerListener { public void torrentAdded( TrackerTorrent torrent ); public void torrentChanged( TrackerTorrent torrent ); public void torrentRemoved( TrackerTorrent torrent ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/TrackerException.java0000644000175000017500000000212211012741706025402 0ustar adrianadrian/* * File : TrackerException.java * Created : 05-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker; /** * @author parg * */ public class TrackerException extends Exception { public TrackerException( String str ) { super(str); } public TrackerException( String str, Throwable cause ) { super(str,cause); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/TrackerPeerListener.java0000644000175000017500000000215210373051044026046 0ustar adrianadrian/* * Created on 09-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.tracker; /** * @author parg * */ public interface TrackerPeerListener { public void eventOccurred( TrackerPeerEvent ev ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/TrackerPeer.java0000644000175000017500000000234110433237716024351 0ustar adrianadrian/* * File : PeerKey.java * Created : 30 nov. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker; /** * @author Olivier * */ public interface TrackerPeer { public boolean isSeed(); public long getAmountLeft(); public long getDownloaded(); public long getUploaded(); public String getIP(); public int getPort(); public byte[] getPeerID(); /** * Raw value is as read, not InetAddress lookuped * @return */ public String getIPRaw(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/web/0000755000175000017500000000000011310377634022053 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/web/TrackerWebContext.java0000644000175000017500000000311311223045276026307 0ustar adrianadrian/* * File : TrackerWebContext.java * Created : 23-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker.web; /** * @author parg * */ import java.net.URL; public interface TrackerWebContext { public String getName(); /** * returns the context URLS (can be two for the tracker as http + https) * @return */ public URL[] getURLs(); public void setEnableKeepAlive( boolean enable ); public void addPageGenerator( TrackerWebPageGenerator generator ); public void removePageGenerator( TrackerWebPageGenerator generator ); public TrackerWebPageGenerator[] getPageGenerators(); public void addAuthenticationListener( TrackerAuthenticationListener l ); public void removeAuthenticationListener( TrackerAuthenticationListener l ); /** * @since 3.0.2.3 */ public void destroy(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/web/TrackerAuthenticationListener.java0000644000175000017500000000335610373051004030712 0ustar adrianadrian/* * Created on 10-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.tracker.web; /** * @author parg * */ import java.net.URL; public interface TrackerAuthenticationListener { /** * authentica a given user/password pair for access to the given resource * @param resource * @param user * @param password * @return true - access OK, false access denied */ public boolean authenticate( URL resource, String user, String password ); /** * For the UDP tracker protocol it is necessary to return the SHA1 hash of the * password for the user, allowing the core to perform the necessary checks * @param resource * @param user * @return SHA1 password hash or null if either user unknown of user can't access the resource */ public byte[] authenticate( URL resource, String user ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/web/TrackerAuthenticationAdapter.java0000644000175000017500000000250710373051004030502 0ustar adrianadrian/* * Created on 10-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.tracker.web; import java.net.URL; /** * @author parg * */ public class TrackerAuthenticationAdapter implements TrackerAuthenticationListener { public boolean authenticate( URL resource, String user, String password ) { return( false ); } public byte[] authenticate( URL resource, String user ) { return( null ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageResponse.java0000644000175000017500000000442011223045276027260 0ustar adrianadrian/* * File : TrackerWebPageResponse.java * Created : 08-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker.web; /** * @author parg * */ import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; import org.gudy.azureus2.plugins.tracker.*; public interface TrackerWebPageResponse { public OutputStream getOutputStream(); public void setReplyStatus( int status ); public void setContentType( String type ); public void setLastModified( long time ); public void setExpires( long time ); public void setHeader( String name, String value ); public void setGZIP( boolean gzip ); /** * use a file contents as the response. returns true of loaded ok, false if doesn't exist * exception if error occurred during processing. * @param root_dir e.g. c:\temp\parp or /tmp/trout/ * @param relative_url e.g. /here/there/wibble.html * @return * @throws IOException */ public boolean useFile( String root_dir, String relative_url ) throws IOException; public void useStream( String file_type, InputStream stream ) throws IOException; public void writeTorrent( TrackerTorrent torrent ) throws IOException; /** * For a non-blocking tracker the construction of the response can be completed asynchronously * by setting async=true and then, when complete, setting it to false * @param async */ public void setAsynchronous( boolean async ) throws IOException; public boolean getAsynchronous(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageGenerator.java0000644000175000017500000000226707765174514027435 0ustar adrianadrian/* * File : TrackerWebPageGenerator.java * Created : 08-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker.web; /** * @author parg * */ import java.io.IOException; public interface TrackerWebPageGenerator { /** * * @param request * @param response * @return true if the request was handled */ public boolean generate( TrackerWebPageRequest request, TrackerWebPageResponse response ) throws IOException; }azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageRequest.java0000644000175000017500000000344011233522512027105 0ustar adrianadrian/* * File : TrackerWebPageRequest.java * Created : 08-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker.web; /** * @author parg * */ import java.io.InputStream; import java.net.InetSocketAddress; import java.net.URL; import java.util.Map; import org.gudy.azureus2.plugins.tracker.*; public interface TrackerWebPageRequest { public Tracker getTracker(); public String getClientAddress(); public InetSocketAddress getClientAddress2(); public InetSocketAddress getLocalAddress(); public String getUser(); /** * This gives the relative URL of the request (e.g. /fred.html) * @return */ public String getURL(); public String getHeader(); /** * Returns a map containing the separate headers. Keys are lowercase * @return * @since 2.3.0.7 */ public Map getHeaders(); public InputStream getInputStream(); /** * Absolute URL including protocol and port e.g. https://a.b.c:1235/fred.html * @return */ public URL getAbsoluteURL(); public TrackerWebContext getContext(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/TrackerTorrentWillBeRemovedListener.java0000644000175000017500000000207610004100434031223 0ustar adrianadrian/* * File : TrackerTorrentWillBeRemovedListener.java * Created : 22-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.tracker; /** * @author parg * */ public interface TrackerTorrentWillBeRemovedListener { public void torrentWillBeRemoved( TrackerTorrent torrent ) throws TrackerTorrentRemovalVetoException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/tracker/TrackerPeerEvent.java0000644000175000017500000000233410373051044025344 0ustar adrianadrian/* * Created on 09-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.tracker; /** * @author parg * */ public interface TrackerPeerEvent { public static final int ET_PEER_ADDED = 1; public static final int ET_PEER_CHANGED = 2; public static final int ET_PEER_REMOVED = 3; public int getEventType(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/0000755000175000017500000000000011310377634021452 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadScrapeResult.java0000644000175000017500000000446310207131716026421 0ustar adrianadrian/* * File : DownloadScrapeResult.java * Created : 12-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; import java.net.URL; /** * @author parg * This class represents the results of scrapes for the download */ public interface DownloadScrapeResult { public static final int RT_SUCCESS = 1; public static final int RT_ERROR = 2; /** * Gives access to the associated download * @return * * @since 2.0.7.0 */ public Download getDownload(); /** * A scrape result can denote either a successful or failed scrape. * @return RT_SUCCESS or RT_ERROR * * @since 2.0.7.0 */ public int getResponseType(); // either RT_SUCCESS or RT_ERROR /** * Gives the number of seeds returned by the scrape * @return * * @since 2.0.7.0 */ public int getSeedCount(); /** * Gives the number of non-seeds returned by the scrape * @return * * @since 2.0.7.0 */ public int getNonSeedCount(); /* Gives the next scrape time * @return time next scrape will start in milliseconds since epoch * * @since 2.0.8.0 */ public long getScrapeStartTime(); /** Sets the next scrape time * * @param nextScrapeStartTime time to start in milliseconds since epoch * * @since 2.1.0.2 */ public void setNextScrapeStartTime(long nextScrapeStartTime); public long getNextScrapeStartTime(); /** * returns a string representation of the scrape status * @return * @since 2.1.0.4 */ public String getStatus(); /** * The URL for the tracker * @return */ public URL getURL(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadAnnounceResult.java0000644000175000017500000000560710342550422026752 0ustar adrianadrian/* * File : DownloadAnnounceResult.java * Created : 12-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; import java.net.URL; import java.util.Map; /** * @author parg * This class represents the results of an "announce" made to a tracker. */ public interface DownloadAnnounceResult { public static final int RT_SUCCESS = 1; public static final int RT_ERROR = 2; /** * Gives access to the Download associated with this announce result * @return * * @since 2.0.7.0 */ public Download getDownload(); /** * The response may represent a successful or failed announce * @return either RT_SUCCESS or RT_ERROR * * @since 2.0.7.0 */ public int getResponseType(); /** * For RT_SUCCESS this gives the number of peers returned by the tracker * @return * * @since 2.0.7.0 */ public int getReportedPeerCount(); // number returned by the announce /** * This method gives the number of seeds we know about (and may have received * from a succession of announces). * * @return * * @since 2.0.7.0 * * @note This is not the number of seeds that the tracker knows about, even * when the tracker returns the total seeds it knows of within * its announce results. Use DownloadScrapeResult to retrieve that * value. */ public int getSeedCount(); // seeds we know about /** * This method gives the number of non-seeds (peers) we know about * @return * * @since 2.0.7.0 * * @note This is not the number of non-seeds that the tracker knows about, * even when the tracker returns the total non-seeds it knows of within * its announce results. Use DownloadScrapeResult to retrieve that * value. */ public int getNonSeedCount(); // non-seeds we know about /** * For RT_ERROR this gives error details * @return * * @since 2.0.7.0 */ public String getError(); /** * The URL for the tracker. * @return WILL BE NULL if the torrent isn't running */ public URL getURL(); public DownloadAnnounceResultPeer[] getPeers(); public long getTimeToWait(); public Map getExtensions(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadActivationListener.java0000644000175000017500000000266310455472132027621 0ustar adrianadrian/* * Created on 13 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.download; public interface DownloadActivationListener { /** * A request has been made to activate the download. Not this is only fired on an increase in the * activation request count, not on a decrease. To get a current snapshot of this use the method * getActivationState in Download * @param event * @return return true if the download will be activated, false otherwise */ public boolean activationRequested( DownloadActivationEvent event ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadWillBeAddedListener.java0000644000175000017500000000241710410066600027603 0ustar adrianadrian/* * Created on 21-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.download; public interface DownloadWillBeAddedListener { /** * this will be called early during download initialisation and allows the initial * file state to be set before allocation occurs (for example) * @param the file initialised */ public void initialised( Download download ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadTypeIncomplete.java0000644000175000017500000000170411066073412026743 0ustar adrianadrian/** * Created on Sep 19, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; /** * For registering columns, menus, etc with a datasource * @author TuxPaper * @created Sep 19, 2008 * */ public interface DownloadTypeIncomplete { } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadActivationEvent.java0000644000175000017500000000212610455463376027121 0ustar adrianadrian/* * Created on 13 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.download; public interface DownloadActivationEvent { public Download getDownload(); public int getActivationCount(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadManagerStats.java0000644000175000017500000000353010632376632026402 0ustar adrianadrian/* * Created on 15-Jul-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.download; public interface DownloadManagerStats { /** * bytes ever received * @return */ public long getOverallDataBytesReceived(); /** * bytes ever sent * @return */ public long getOverallDataBytesSent(); /** * how long since az started * @return */ public long getSessionUptimeSeconds(); /** * current data receive rate * @return */ public int getDataReceiveRate(); public int getProtocolReceiveRate(); public int getDataAndProtocolReceiveRate(); public int getDataSendRate(); public int getProtocolSendRate(); public int getDataAndProtocolSendRate(); /** * data received since session start * @return */ public long getDataBytesReceived(); public long getProtocolBytesReceived(); public long getDataBytesSent(); public long getProtocolBytesSent(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadWillBeRemovedListener.java0000644000175000017500000000205110000122400030157 0ustar adrianadrian/* * File : DownloadWillBeRemovedListener.java * Created : 10-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; /** * @author parg * */ public interface DownloadWillBeRemovedListener { public void downloadWillBeRemoved( Download download ) throws DownloadRemovalVetoException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadAttributeListener.java0000644000175000017500000000331210777323232027456 0ustar adrianadrian/* * Created on 8 Nov 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.download; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; /** * Event listener interface to be notified when particular attributes are handled. * * @sionce 3.0.3.5 * @author Allan Crooks */ public interface DownloadAttributeListener { public int WRITTEN = DownloadPropertyEvent.PT_TORRENT_ATTRIBUTE_WRITTEN; public int WILL_BE_READ = DownloadPropertyEvent.PT_TORRENT_ATTRIBUTE_WILL_BE_READ; /** * This method will be called when an attribute event occurs. * * @param download The download object involved. * @param attribute The attribute involved. * @param event_type Either WRITTEN or WILL_BE_READ. */ public void attributeEventOccurred(Download download, TorrentAttribute attribute, int event_type); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadPropertyListener.java0000644000175000017500000000222110373051022027320 0ustar adrianadrian/* * Created on 10-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.download; /** * @author parg * */ public interface DownloadPropertyListener { public void propertyChanged( Download download, DownloadPropertyEvent event ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadTrackerListener.java0000644000175000017500000000410310343601342027073 0ustar adrianadrian/* * File : DownloadTrackerListener.java * Created : 11-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; /** * A listener that will be informed when the latest announce/scrape results * change. See {@link org.gudy.azureus2.plugins.download#addTrackerListener} * * @author parg * @author TuxPaper 2005/Oct/01: JavaDocs & reformat to Java Conventions w/Tabs */ public interface DownloadTrackerListener { /** * A scrape result has been returned from a tracker * * @param result Information about the scrape * * @since 2.0.7.0 * * @note If an announce result is returned from the tracker contains * seed and non-seed (peer) counts, a new DownloadScrapeResult will be * created with the new information, and a scrapeResult will be * triggered. *

* The DownloadScrapeResult isn't always information from the currently * selected tracker. Compare result.getURL() with * getDownload().getTorrent().getAnnounceURL() to determine if it's * from the currently selected tracker. */ public void scrapeResult(DownloadScrapeResult result); /** * An announce result has been returned from the tracker * * @param result Information about the announce * * @since 2.0.7.0 */ public void announceResult(DownloadAnnounceResult result); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadStats.java0000644000175000017500000001517711224751004025105 0ustar adrianadrian/* * File : DownloadStats.java * Created : 08-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; /** * @author parg * This class gives access to various stats associated with the download */ public interface DownloadStats { public static final int HEALTH_STOPPED = 1; public static final int HEALTH_NO_TRACKER = 2; public static final int HEALTH_NO_REMOTE = 3; public static final int HEALTH_OK = 4; /** not connected to any peer and downloading */ public static final int HEALTH_KO = 5; /** download in STATE_ERROR, see {@link #getStatus()} for error */ public static final int HEALTH_ERROR = 6; /** * Returns an overall string representing the state of the download * @return * * @since 2.0.7.0 */ public String getStatus(); /** * Returns an overall string representing the state of the download * *localised* * @return * * @since 2.3.0.7 */ public String getStatus( boolean localised); /** * Gives access to the directory into which the download is being saved * @return * * @since 2.0.7.0 */ public String getDownloadDirectory(); /** * Gives access to the target file or directory that the download is being saved to * @return * * @since 2.0.7.0 */ public String getTargetFileOrDir(); /** * returns an general status string for the tracker * @return * * @since 2.0.7.0 */ public String getTrackerStatus(); /** * returns a value between 0 and 1000 giving the completion status of the current download * task (e.g. checking, downloading) * @return * * @since 2.0.7.0 */ public int getCompleted(); /** Retrieve the level of download completion. * * To understand the bLive parameter, you must know a bit about the * Torrent activation process: * 1) Torrent goes into ST_WAITING * 2) Torrent moves to ST_PREPARING * 3) Torrent moves to ST_DOWNLOADING or ST_SEEDING * * While in ST_PREPARING, Completion Level is rebuilt (either via Fast Resume * or via piece checking). Quite often, the download completion level before * ST_PREPARING and after ST_PREPARING are identical. * * Before going into ST_PREPARING, we store the download completion level. * If you wish to retrieve this value instead of the live "building" one, * pass false for the parameter. * * @param bLive true - Always returns the known completion level of the torrent * false - In the case of ST_PREPARING, return completion level * before of the torrent ST_PREPARING started. * Otherwise, same as true. * @return 0 - 1000 * * @since 2.0.8.0 */ public int getDownloadCompleted(boolean bLive); /** * if isChecking then returns completeness, 1000 -> 100% * @return */ public int getCheckingDoneInThousandNotation(); /** * Gives the number of bytes downloaded * @return * * @since 2.0.7.0 */ public long getDownloaded(); /** * Gives number of bytes remaining * @return */ public long getRemaining(); /** * Gives the number of bytes uploaded * @return * * @since 2.0.7.0 */ public long getUploaded(); /** * Gives the number of bytes discarded * @return * * @since 2.0.7.0 */ public long getDiscarded(); /** * Gives average number of bytes downloaded in last second * @return * * @since 2.0.7.0 */ public long getDownloadAverage(); /** * Gives average number of bytes uploaded in last second * @return * * @since 2.0.7.0 */ public long getUploadAverage(); /** * Gives average number of bytes computed for torrent in last second * @return * * @since 2.0.7.0 */ public long getTotalAverage(); /** * Gives the elapsed download time as a string * @return * * @since 2.0.7.0 */ public String getElapsedTime(); /** * Gives the estimated time to completion as a string * @return * * @since 2.0.7.0 */ public String getETA(); /** * @since 4.2.0.3 * @return Long.MAX_VALUE -> infinite */ public long getETASecs(); /** * Gives the number of bytes thrown away due to piece hash check fails * @return * * @since 2.0.7.0 */ public long getHashFails(); /** * Gives the share ratio of the torrent in 1000ths (i.e. 1000 = share ratio of 1) * @return * * @since 2.0.7.0 */ public int getShareRatio(); /** in ms since epoch * * @since 2.0.8.0 */ public long getTimeStarted(); /* Time that the torrent started seeding. * @return the difference, measured in milliseconds, between the torrent * started seeding and midnight, January 1, 1970 UTC. see * SystemTime.getCurrentTime(). * -1 is not seeding * * @since 2.1.0.0 */ public long getTimeStartedSeeding(); /** * Gives the currently seen availability of the torrent * @return * * @since 2.0.8.2 */ public float getAvailability(); /* Return the # of seconds that the torrent has been downloading. This * number is totalled across sessions. * * @return -1 if it has never downloaded * * @since 2.1.0.0 */ public long getSecondsDownloading(); /* Return the # of seconds that the torrent has been only seeding. This * number is totalled across sessions, and does not include the time * seeding during the download phase. * * @return -1 if it has never seeded * * @since 2.1.0.0 */ public long getSecondsOnlySeeding(); /** * Returns the number of seconds running time since data was downloaded, -1 if never * @since 2501 * @return */ public long getSecondsSinceLastDownload(); /** * Returns the number of seconds running time since data was uploaded, -1 if never * @since 2501 * @return */ public long getSecondsSinceLastUpload(); /** * returns an indication of the health of the torrent * @return see above HEALTH constants */ public int getHealth(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadRemovalVetoException.java0000644000175000017500000000246511012742460030126 0ustar adrianadrian/* * File : DownloadRemovalVetoException.java * Created : 10-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; /** This exception is thrown to prevent the removal of a download * * @author parg * @since 2.0.7.0 */ public class DownloadRemovalVetoException extends Exception { private boolean silent; public DownloadRemovalVetoException( String str, boolean silent) { super(str); this.silent = silent; } public DownloadRemovalVetoException( String str ) { this(str,false); } public boolean isSilent() { return silent; } } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadManagerListener.java0000644000175000017500000000217510061315112027053 0ustar adrianadrian/* * File : DownloadManagerListener.java * Created : 11-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; /** A listener that is informed of the addition and removal of downloads * * @author parg * @since 2.0.7.0 */ public interface DownloadManagerListener { public void downloadAdded( Download download ); public void downloadRemoved( Download download ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadListener.java0000644000175000017500000000306410053411650025563 0ustar adrianadrian/* * File : DownloadListener.java * Created : 11-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; /** A listener informed of changes to a Download's state and position * * @author parg * @author TuxPaper (positionChanged) */ public interface DownloadListener { /** The Download's state has changed. This is also triggered if the user * toggles the Force Start on/off. */ public void stateChanged( Download download, int old_state, int new_state ); /** Position of download has changed. * * @param download object in which the position has changed * @param oldPosition position that the download used to be at * @param newPosition position that the download is now at */ public void positionChanged( Download download, int oldPosition, int newPosition ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/Download.java0000644000175000017500000006462511263244650024077 0ustar adrianadrian/* * File : Download.java * Created : 06-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; import java.io.File; import java.util.Map; import org.gudy.azureus2.plugins.download.savelocation.DefaultSaveLocationManager; import org.gudy.azureus2.plugins.download.savelocation.SaveLocationChange; import org.gudy.azureus2.plugins.download.savelocation.SaveLocationManager; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.disk.DiskManager; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.peers.PeerManager; /** * Management of a Torrent's activity. * * Note: All listener based methods are now located in {@link DownloadEventNotifier}. * *

 * A download's lifecycle:
 * torrent gets added
 *    state -> QUEUED
 * slot becomes available, queued torrent is picked, "restart" executed
 *    state -> WAITING
 * state moves through PREPARING to READY
 *    state -> PREPARING
 *    state -> READY
 * execute "start" method
 *    state -> SEEDING -or- DOWNLOADING
 * if torrent is DOWNLOADING, and completes, state changes to SEEDING
 *
 * Path 1                   | Path 2
 * -------------------------+------------------------------------------------
 * execute "stop" method    | startstop rules are met, execute "stopandQueue"
 *    state -> STOPPING     |     state -> STOPPING
 *    state -> STOPPED      |     state -> STOPPED
 *                          |     state -> QUEUED
 * execute "remove" method -> deletes the download
 * a "stop" method call can be made when the download is in all states except STOPPED
 * 
* * @author parg */ public interface Download extends DownloadEventNotifier { /** waiting to be told to start preparing */ public static final int ST_WAITING = 1; /** getting files ready (allocating/checking) */ public static final int ST_PREPARING = 2; /** ready to be started if required */ public static final int ST_READY = 3; /** downloading */ public static final int ST_DOWNLOADING = 4; /** seeding */ public static final int ST_SEEDING = 5; /** stopping */ public static final int ST_STOPPING = 6; /** stopped, do not auto-start! */ public static final int ST_STOPPED = 7; /** failed */ public static final int ST_ERROR = 8; /** stopped, but ready for auto-starting */ public static final int ST_QUEUED = 9; public static final String[] ST_NAMES = { "", "Waiting", "Preparing", "Ready", "Downloading", "Seeding", "Stopping", "Stopped", "Error", "Queued", }; /** Use more of the upload bandwidth than low priority downloads * don't change these as they are used by remote clients */ public static final int PR_HIGH_PRIORITY = 1; /** Use less of the upload bandwidth than high priority downloads */ public static final int PR_LOW_PRIORITY = 2; /** * Flags values * @since 2.3.0.5 */ public static final long FLAG_ONLY_EVER_SEEDED = 0x00000001; public static final long FLAG_SCAN_INCOMPLETE_PIECES = 0x00000002; /** * Flag value - if set, it prevents any of the "move on completion" or * "move on removal" rules taking place. * * @since 2.5.0.1 */ public static final long FLAG_DISABLE_AUTO_FILE_MOVE = 0x00000004; /** * Flag value - if set, then it means this download has been considered * for "move on completion", and it should not be considered again for * it. This value is more for internal use rather than plugin use. * * @since 2.5.0.1 */ public static final long FLAG_MOVE_ON_COMPLETION_DONE = 0x00000008; /** * Flag value - if set the user won't be bothered with popups/completion events during * the download's life. This is used, for example, for downloads used to run speed-tests * @since 3.0.1.3 */ public static final long FLAG_LOW_NOISE = 0x00000010; /** * Flag value - normally the permitted peer sources for a download are fixed and can't be changed * this flag allows the permitted peer source set to be increased/decreased (but not beyond the enforced * values required to honour a torrent's 'private' flag */ public static final long FLAG_ALLOW_PERMITTED_PEER_SOURCE_CHANGES = 0x00000020; /** * Flag value - if set the data will not be delete when the download is "deleted" from * the v3 interface. * @since 3.1.0.0 */ public static final long FLAG_DO_NOT_DELETE_DATA_ON_REMOVE = 0x00000040; /** get state from above ST_ set * @return ST_ constant * * @since 2.0.7.0 */ public int getState(); /** * For the STOPPING state this method gives the state that is being transited too (STOPPED, QUEUED or ERROR) * @return * @since 2.3.0.5 */ public int getSubState(); /** When the download state is ERROR this method returns the error details * @return * * @since 2.0.7.0 */ public String getErrorStateDetails(); /** * Get the flag value * @since 2.3.0.5 * @param flag FLAG value from above * @return */ public boolean getFlag(long flag); /** * Set the flag value. * * @since 2.5.0.1 * @param flag FLAG value from above * @param set true to enable the flag, false to disable it. */ public void setFlag(long flag, boolean set); /** * get all the flags as a bitmap * @since 4209 * @return */ public long getFlags(); /** * Index of download. {@link #getPosition()} * @return index - 0 based * * @since 2.0.7.0 */ public int getIndex(); /** * Each download has a corresponding torrent * @return the download's torrent * * @since 2.0.7.0 */ public Torrent getTorrent(); /** * See lifecycle description above * @throws DownloadException * * @since 2.0.7.0 */ public void initialize() throws DownloadException; /** * See lifecycle description above * @throws DownloadException * * @since 2.0.7.0 */ public void start() throws DownloadException; /** * See lifecycle description above * @throws DownloadException * * @since 2.0.7.0 */ public void stop() throws DownloadException; /** * See lifecycle description above * @throws DownloadException * * @since 2.0.8.0 */ public void stopAndQueue() throws DownloadException; /** * See lifecycle description above * @throws DownloadException * * @since 2.0.7.0 */ public void restart() throws DownloadException; /** * Performs a complete recheck of the downloaded data * Download must be in stopped, queued or error state * Action is performed asynchronously and will progress the download through * states PREPARING back to the relevant state * @throws DownloadException * @since 2.1.0.3 */ public void recheckData() throws DownloadException; /** * When a download is "start-stop locked" it means that seeding rules shouldn't start or * stop the download as it is under manual control * @return True if download is locked and should not be started or stopped * * @since 2.0.7.0 */ public boolean isStartStopLocked(); /** Retrieves whether the download is force started * @return True if download is force started. False if not. * * @since 2.0.8.0 */ public boolean isForceStart(); /** Set the forcestart state of the download * @param forceStart True - Download will start, despite any Start/Stop rules/limits
* False - Turn forcestart state off. Download may or may not stop, depending on * Start/Stop rules/limits * * @since 2.0.8.0 */ public void setForceStart(boolean forceStart); /** * Downloads can either be low or high priority (see PR_ constants above) * @return the download's priority * * @deprecated >= 2.1.0.6 does nothing * @since 2.0.7.0 */ public int getPriority(); /** * This method sets a download's priority * @param priority the required priority, see PR_ constants above * @deprecated >= 2.1.0.6 does nothing * * @since 2.0.7.0 */ public void setPriority( int priority ); /** When a download's priority is locked this means that seeding rules should not change * a downloads priority, it is under manual control * @return whether it is locked or not * @deprecated >= 2.0.8.0 does nothing * * @since 2.0.7.0 */ public boolean isPriorityLocked(); /** * @since 2403 * @return */ public boolean isPaused(); /** * Pause the download * @since 2501 */ public void pause(); /** * Resume the download if paused * @since 2501 */ public void resume(); /** Returns the name of the torrent. Similar to Torrent.getName() and is usefull * if getTorrent() returns null and you still need the name. * @return name of the torrent * * @since 2.0.8.0 */ public String getName(); /** Returns the full file path and name of the .torrent file * * @return File name of the torrent. * * @since 2.1.0.0 */ public String getTorrentFileName(); /** * Gets an attribute of this download. For category use the Category torrent attribute * @param attribute * @return */ public String getAttribute( TorrentAttribute attribute ); /** * Sets an attribute of this download. For category use the Category torrent attribute * * @param attribute Previously created attribute * @param value Value to store. null to remove attribute */ public void setAttribute( TorrentAttribute attribute, String value ); public String[] getListAttribute( TorrentAttribute attribute ); /** * * @param attribute * @param value * @since 2.5.0.1 */ public void setListAttribute(TorrentAttribute attribute, String[] value); /** * * @param attribute * @param value must be bencodable - key is string, value is Map, List, Long or byte[] */ public void setMapAttribute( TorrentAttribute attribute, Map value ); public Map getMapAttribute( TorrentAttribute attribute ); /** * Gets the value of the given attribute from the download. If no value is * set, then 0 will be returned. */ public int getIntAttribute(TorrentAttribute attribute); /** * Sets an integer attribute on this download. */ public void setIntAttribute(TorrentAttribute attribute, int value); /** * Gets the value of the given attribute from the download. If no value is * set, then 0 will be returned. */ public long getLongAttribute(TorrentAttribute attribute); /** * Sets a long attribute on this download. */ public void setLongAttribute(TorrentAttribute attribute, long value); /** * Gets the value of the given attribute from the download. If no value is * set, then false will be returned. */ public boolean getBooleanAttribute(TorrentAttribute attribute); /** * Sets a boolean attribute on this download. */ public void setBooleanAttribute(TorrentAttribute attribute, boolean value); /** * Returns true if the download has an explicit value stored for * the given attribute. */ public boolean hasAttribute(TorrentAttribute attribute); /** Returns the name of the Category * * @return name of the category * * @since 2.1.0.0 * @deprecated Use TorrentAttribute.TA_CATEGORY (2.2.0.3) */ public String getCategoryName(); /** Sets the category for the download * * @param sName Category name * * @since 2.1.0.0 * @deprecated Use TorrentAttribute.TA_CATEGORY (2.2.0.3) */ public void setCategory(String sName); /** * Removes a download. The download must be stopped or in error. Removal may fail if another * component does not want the removal to occur - in this case a "veto" exception is thrown * @throws DownloadException * @throws DownloadRemovalVetoException * * @since 2.0.7.0 */ public void remove() throws DownloadException, DownloadRemovalVetoException; /** * Same as "remove" but, if successful, deletes the torrent and/or data * @param delete_torrent * @param delete_data * @throws DownloadException * @throws DownloadRemovalVetoException * @since 2.2.0.3 */ public void remove( boolean delete_torrent, boolean delete_data ) throws DownloadException, DownloadRemovalVetoException; /** * Returns the current position in the queue * Completed and Incompleted downloads have seperate position sets. This means * we can have a position x for Completed, and position x for Incompleted. * * @since 2.0.8.0 */ public int getPosition(); /** * returns the time this download was created in milliseconds * @return */ public long getCreationTime(); /** * Sets the position in the queue * Completed and Incompleted downloads have seperate position sets * * @since 2.0.8.0 */ public void setPosition( int newPosition); /** * Moves the download position up one * * @since 2.1.0.0 */ public void moveUp(); /** * Moves the download down one position * * @since 2.1.0.0 */ public void moveDown(); /** * Moves a download and re-orders the others appropriately. Note that setPosition does not do this, it * merely sets the position thus making it possible, for example, for two downloads to have the same * position * @param position * @since 2.3.0.7 */ public void moveTo( int position ); /** * Tests whether or not a download can be removed. Due to synchronization issues it is possible * for a download to report OK here but still fail removal. * @return * @throws DownloadRemovalVetoException * * @since 2.0.7.0 */ public boolean canBeRemoved() throws DownloadRemovalVetoException; public void setAnnounceResult( DownloadAnnounceResult result ); public void setScrapeResult( DownloadScrapeResult result ); /** * Gives access to the last announce result received from the tracker for the download * @return * * @since 2.0.7.0 */ public DownloadAnnounceResult getLastAnnounceResult(); /** * Gives access to the last scrape result received from the tracker for the download * @return a non-null DownloadScrapeResult * * @since 2.0.7.0 */ public DownloadScrapeResult getLastScrapeResult(); /** * Gives access to the current activation state. Note that we currently only fire the activation listener * on an increase in activation requirements. This method however gives the current view of the state * and takes into account decreases too * @return * @since 2.4.0.3 */ public DownloadActivationEvent getActivationState(); /** * Gives access to the download's statistics * @return * * @since 2.0.7.0 */ public DownloadStats getStats(); /** Downloads can be persistent (be remembered accross Azureus sessions), or * non-persistent. * * @return true - persistent
* false - non-persistent * * @since 2.1.0.0 */ public boolean isPersistent(); /** * Sets the maximum download speed in bytes per second. 0 -> unlimited * @since 2.1.0.2 * @param kb */ public void setMaximumDownloadKBPerSecond( int kb ); public int getMaximumDownloadKBPerSecond(); /** * Get the max upload rate allowed for this download. * @return upload rate in bytes per second, 0 for unlimited, -1 for upload disabled */ public int getUploadRateLimitBytesPerSecond(); /** * Set the max upload rate allowed for this download. * @param max_rate_bps limit in bytes per second, 0 for unlimited, -1 for upload disabled */ public void setUploadRateLimitBytesPerSecond( int max_rate_bps ); /** * Get the max download rate allowed for this download. * @return upload rate in bytes per second, 0 for unlimited, -1 for download disabled * @since 3013 */ public int getDownloadRateLimitBytesPerSecond(); /** * Set the max download rate allowed for this download. * @param max_rate_bps limit in bytes per second, 0 for unlimited, -1 for dowmload disabled * @since 3013 */ public void setDownloadRateLimitBytesPerSecond( int max_rate_bps ); /** * Indicates if the download has completed or not, exluding any files marked * as Do No Download * * @return Download Complete status * @since 2.1.0.4 */ public boolean isComplete(); /** * Indicates if the download has completed or not * * @param bIncludeDND Whether to include DND files when determining * completion state * @return Download Complete status * * @since 2.4.0.3 */ public boolean isComplete(boolean bIncludeDND); /** * When a download is completed it is rechecked (if the option is enabled). This method * returns true during this phase (at which time the status will be seeding) * @return * @since 2.3.0.6 */ public boolean isChecking(); /** * This returns the full save path for the download. If the download is a simple torrent, * this will be the full path of the file being downloaded. If the download is a multiple * file torrent, this will be the path to the directory containing all the files in the * torrent. * * @return Full save path for this download. */ public String getSavePath(); /** * Move a download's data files to a new location. Download must be stopped and persistent * *

* * If a download is running, it will be automatically paused and resumed afterwards - be * aware that this behaviour may generate stateChanged events being fired. * * @since 2.3.0.5 * @param new_parent_dir * @throws DownloadException */ public void moveDataFiles( File new_parent_dir ) throws DownloadException; /** * Move a download's data files to a new location, and rename the download at the same time. * Download must be stopped and persistent. This is equivalent to calling moveDataFiles[File] * and then renameDownload[String]. * * For convenience, either argument can be null, but not both. * *

* * If a download is running, it will be automatically paused and resumed afterwards - be * aware that this behaviour may generate stateChanged events being fired. * * @since 3.0.2 * @throws DownloadException * @see {@link #moveDataFiles(File)} * @see {@link #renameDownload(String)} */ public void moveDataFiles(File new_parent_dir, String new_name) throws DownloadException; /** * Move a download's torrent file to a new location. Download must be stopped and persistent * @since 2.3.0.5 * @param new_parent_dir * @throws DownloadException */ public void moveTorrentFile( File new_parent_dir ) throws DownloadException; /** * Renames the file (for a single file torrent) or directory (for a multi file torrent) where the * download is being saved to. The download must be in a state to move the data files to a new location * (see {@link #moveDataFiles(File)}). * *

* * This will not rename the displayed name for the torrent - if you wish to do that, you must do it via * the {@link org.gudy.azureus2.plugins.torrent.TorrentAttribute TorrentAttribute} class. * *

* * If a download is running, it will be automatically paused and resumed afterwards - be * aware that this behaviour may generate stateChanged events being fired. * * @param name New name for the download. * @see #moveDataFiles(File) */ public void renameDownload(String name) throws DownloadException; /** * return the current peer manager for the download. * @return null returned if torrent currently doesn't have one (e.g. it is stopped) */ public PeerManager getPeerManager(); /** * Return the disk manager, null if its not running * @return * @since 2.3.0.1 */ public DiskManager getDiskManager(); /** * Returns info about the torrent's files. Note that this will return "stub" values if the * download isn't running (not including info such as completion status) * @return * @since 2.3.0.1 */ public DiskManagerFileInfo[] getDiskManagerFileInfo(); /** * request a tracker announce * @since 2.1.0.5 */ public void requestTrackerAnnounce(); /** * request a tracker announce * @since 2.3.0.7 */ public void requestTrackerAnnounce( boolean immediate ); /** * request a tracker announce * @since 2.3.0.7 */ public void requestTrackerScrape( boolean immediate ); /** * The torrents with the highest rankings will be seeded first. * * @return Seeding Rank */ public int getSeedingRank(); /** * The torrents with the highest rankings will be seeded first. * * @param rank New Ranking */ public void setSeedingRank(int rank); /** * Get the local peerID advertised to the download swarm. * @return self peer id * * @since 2.1.0.5 */ public byte[] getDownloadPeerId(); /** * Is advanced AZ messaging enabled for this download. * @return true if enabled, false if disabled */ public boolean isMessagingEnabled(); /** * Enable or disable advanced AZ messaging for this download. * @param enabled true to enabled, false to disabled */ public void setMessagingEnabled( boolean enabled ); /** * Returns an array of size 2 indicating the appropriate locations for this * download's data files and torrent file, based on Azureus's rules regarding * default save paths, and move on completion rules. * *

* * This method takes one argument - for_moving. This essentially * indicates whether you are getting this information for purposes of just * finding where Azureus would store these files by default, or whether you * are considering moving the files from its current location. * *

* * If for_moving is false, this method will determine locations * for the download and the torrent file where Azureus would store them by * default (it may return the current paths used by this download). * *

* * If for_moving is true, then this method will consider the * download's current location, and whether it is allowed to move it - you * may not be allowed to move this download (based on Azureus's current rules) * if the download doesn't exist within a default save directory already. If * a download is complete, we consider whether we are allowed to move downloads * on completion, and whether that includes downloads outside the default save * directory. * *

* * In this case, the array may contain null indicating that the Azureus * doesn't believe that the download should be moved (based on the current rules * the user has set out). However, you are not prevented from changing the * location of the torrent file or download. * * @since 2.5.0.2 * @param for_moving Indicates whether you want this information for the purposes * of moving the download or not. * @author amc1 * @deprecated Use {@link #calculateDefaultDownloadLocation()} instead. * @return An array of type File of size 2, first element containing the * calculated location for the download's data files, and the second element * containing the location for the download's torrent file. */ public File[] calculateDefaultPaths(boolean for_moving); /** * Returns true if the download is being saved to one of the default * save directories. * * @since 2.5.0.2 * @deprecated Use {@link DefaultSaveLocationManager#isInDefaultSaveDir(Download)} instead. * @author amc1 */ public boolean isInDefaultSaveDir(); /** * @since 3.0.4.3 * @return */ public boolean isRemoved(); /** * Returns true if Azureus will allow the data files for the torrent * to be moved. * * @since 3.0.5.1 */ public boolean canMoveDataFiles(); /** * Returns a {@link SaveLocationChange} object describing the appropriate location * for the download (and torrent file) to exist in, based on the download's completion * state, the for-completion rules in place, and the {@link SaveLocationManager} * object in use. * * @since 3.0.5.3 */ public SaveLocationChange calculateDefaultDownloadLocation(); /** * Apply the changes in the given {@link SaveLocationChange} object - this includes * moving torrent and data file data. * * @param slc The change to apply. * @since 3.1.0.1 * @throws DownloadException If there is a problem moving the data. */ public void changeLocation(SaveLocationChange slc) throws DownloadException; /** * get user-defined key/value * @param key * @return * @since 3.0.5.3 */ public Object getUserData( Object key ); /** * set user defined value. this is TRANSIENT and not persisted over Azureus stop/start * @param key * @param data */ public void setUserData( Object key, Object data ); /** * Simple method to start the download. Will not raise an error if it * didn't work, or if the download is already running. * * @since 3.0.5.3 * @param force true to force the download to be started. */ public void startDownload(boolean force); /** * Simple method to stop the download. Will not raise an error if it * didn't work, or if the download is already stopped. * * @since 3.0.5.3 */ public void stopDownload(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadManager.java0000644000175000017500000002370611024374164025364 0ustar adrianadrian/* * File : DownloadManager.java * Created : 06-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; import java.io.File; import java.net.URL; import java.util.Map; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.download.savelocation.DefaultSaveLocationManager; import org.gudy.azureus2.plugins.download.savelocation.SaveLocationManager; /** * The DownloadManager gives access to functions used to monitor and manage Azureus's downloads * @author parg */ public interface DownloadManager { /** * Add a torrent from a file. This may prompt the user for a download location etc. if required. * This is an async operation, so no Download is returned. * * If you want to force a download to be added without prompting the user, you should create a * Torrent object first, and then use an alternative addDownload method. * * @see #addDownload(Torrent) * @see #addDownload(Torrent, File, File) * @see org.gudy.azureus2.plugins.torrent.TorrentManager#createFromBEncodedFile(File) TorrentManager.createFromBEncodedFile * @param torrent_file * @throws DownloadException * * @since 2.0.7.0 */ public void addDownload( File torrent_file ) throws DownloadException; /** * add a torrent from a URL. This will prompt the user for download location etc. if required * This is an async operation so no Download returned * @param url * @throws DownloadException * * @since 2.0.7.0 */ public void addDownload( URL url ) throws DownloadException; /** * Add a torrent from a URL with explicit auto-download option * @param url * @param auto_download * @throws DownloadException * @since 2403 */ public void addDownload( URL url, boolean auto_download ) throws DownloadException; /** * add a torrent from a URL. This will prompt the user for download location etc. if required * This is an async operation so no Download returned * @param url * @param referer * @throws DownloadException * * @since 2.1.0.6 */ public void addDownload( URL url, URL referer); /** * add a torrent from a URL and use the supplied request properties * @param url * @param request_properties * @since 3.0.5.3 */ public void addDownload( URL url, Map request_properties ); /** * Add a torrent from a "Torrent" object. The default torrent file and data locations will be * used if defined - a DownloadException will be thrown if they're not. You can explicitly set * these values by using the {@link #addDownload(Torrent, File, File) addDownload(Torrent, File, File)} method. * @param torrent * @see #addDownload(Torrent, File, File) * @return * * @since 2.0.8.0 */ public Download addDownload( Torrent torrent ) throws DownloadException; /** * Add a torrent from a "Torrent" object and point it at the data location. * * The torrent_location should be the location of where the torrent file is on disk. * This will be the torrent file that Azureus will use internally. If null is passed, * then a file to store the torrent data in will be automatically created by Azureus. * * @param torrent The torrent object to create a download with. * @param torrent_location The location of the file on disk - if null, * a file to store the torrent data into will be created automatically. * @param data_location null -> user default data save location if defined * @return * support for null params for torrent_location/data_location since 2.1.0.4 * @since 2.0.7.0 */ public Download addDownload( Torrent torrent, File torrent_location, File data_location ) throws DownloadException; /** * Explicit way of adding a download in a stopped state * @since 3013 * @param torrent * @param torrent_location * @param data_location * @return * @throws DownloadException */ public Download addDownloadStopped( Torrent torrent, File torrent_location, File data_location ) throws DownloadException; /** * Add a non-persistent download. Such downloads are not persisted by Azureus and as such will * not be remembered across an Azureus close and restart. * @param torrent * @param torrent_location * @param data_location * @return * @throws DownloadException * * @since 2.0.7.0 */ public Download addNonPersistentDownload( Torrent torrent, File torrent_location, File data_location ) throws DownloadException; /** * Gets the download for a particular torrent, returns null if not found * @param torrent * @return * * @since 2.0.7.0 */ public Download getDownload( Torrent torrent ); /** * Gets a download given its hash * @param hash * @return * @throws DownloadException * @since 2.3.0.7 */ public Download getDownload( byte[] hash ) throws DownloadException; /** * Gets all the downloads. Returned in Download "index" order * @return * * @since 2.0.7.0 */ public Download[] getDownloads(); /** * Gets all the downloads. * @param bSorted true - Returned in Download "index" order.
* false - Order not guaranteed. Faster retrieval. * @return array of Download object * * @since 2.0.8.0 */ public Download[] getDownloads(boolean bSorted); /** * pause all running downloads * @since 2.1.0.5 * */ public void pauseDownloads(); public boolean canPauseDownloads(); /** * resume previously paused downloads * @since 2.1.0.5 */ public void resumeDownloads(); public boolean canResumeDownloads(); /** * starts all non-running downloads * @since 2.1.0.5 */ public void startAllDownloads(); /** * stops all running downloads * @since 2.1.0.5 */ public void stopAllDownloads(); /** * Get the download manager statistics * @return */ public DownloadManagerStats getStats(); /** * indicates whether or not all active downloads are in a seeding (or effective) seeding state * @since 2.3.0.5 * @return */ public boolean isSeedingOnly(); /** * Add a listener that will be informed when a download is added to and removed * from Azureus. *

* Invoking this method is equivalent to addListener(l, true). * * @param l The listener to add. * @since 2.0.7.0 * @see #addListener(DownloadManagerListener, boolean) */ public void addListener(DownloadManagerListener l); /** * Add a listener that will be informed when a download is added to and removed * from Azureus. * @param l The listener to add. * @param notify_of_current_downloads true - if you want the listener to * have its {@link DownloadManagerListener#downloadAdded(Download) downloadAdded} * method invoked immediately with all downloads currently managed by Azureus. * false - if you only want to be notified about new downloads added after * this method is called. * @since 3.0.0.7 */ public void addListener(DownloadManagerListener l, boolean notify_of_current_downloads); /** * Removes a previously added listener. * @param l The listener to remove. * @param notify_of_current_downloads true - if you want the listener to * have its {@link DownloadManagerListener#downloadRemoved(Download) downloadRemoved} * method invoked immediately with all downloads currently managed by Azureus, * false otherwise. * @since 3.0.0.7 */ public void removeListener(DownloadManagerListener l, boolean notify_of_current_downloads); /** * Removes a previously added listener. *

* Invoking this method is equivalent to removeListener(l, false). * @see #removeListener(DownloadManagerListener, boolean) * @param l The listener to remove. * @since 2.0.7.0 */ public void removeListener(DownloadManagerListener l); public void addDownloadWillBeAddedListener( DownloadWillBeAddedListener listener ); public void removeDownloadWillBeAddedListener( DownloadWillBeAddedListener listener ); /** * Return a {@link DownloadEventNotifier} object which can be used as * an easy way to register listeners against all downloads handled by * Azureus. * * @since 3.0.1.5 */ public DownloadEventNotifier getGlobalDownloadEventNotifier(); /** * Registers an object to be in control of determining the default save * location for downloads. You can set it to null to remove any * object which was previously set. * *

* * By default, Azureus will use its default save location manager which * handles on-completion and on-removal events. * * @param manager The new manager object to use. * @since 3.0.5.3 */ public void setSaveLocationManager(SaveLocationManager manager); /** * Returns the current {@link SaveLocationManager} object which decides * where downloads should be placed. * * @return The manager object currently in use. * @since 3.0.5.3 */ public SaveLocationManager getSaveLocationManager(); /** * Returns the default {@link SaveLocationManager} object that controls * where downloads should be placed. * * @return The default save location manager object. * @since 3.0.5.3 */ public DefaultSaveLocationManager getDefaultSaveLocationManager(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/savelocation/0000755000175000017500000000000011310377616024141 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/download/savelocation/DefaultSaveLocationManager.java0000644000175000017500000000235311016142610032161 0ustar adrianadrian/* * Created on 23 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.download.savelocation; import org.gudy.azureus2.plugins.download.Download; /** *

Note: Only for implementation by Azureus, not plugins.

*/ public interface DefaultSaveLocationManager extends SaveLocationManager { public boolean isInDefaultSaveDir(Download d); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/savelocation/SaveLocationManager.java0000644000175000017500000001104511031330136030651 0ustar adrianadrian/* * Created on 12 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.download.savelocation; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadManager; /** * Plugins which want to control the logic of where the default save location * for downloads (including for on-completion and on-removal * behaviour) can implement this class and register it through the * {@link DownloadManager#setSaveLocationManager(SaveLocationManager)}. * *

* * Each method here returns a {@link SaveLocationChange} object, which contains * instructions which allows both the download and the torrent to be moved and * renamed. * *

* * The methods here take two arguments - for_move and on_event. * *

    *
  • When events happen to downloads (like the download being completed or removed), * both of these values will be true. *
  • When something is trying to update the logical location for the download, * for_move will be true, while on_event will be false. *
  • When something is trying to determine all the places where existing data * files might exist, both values will be false. *
* * If for_move is false, any checks normally performed on a download * to see if it is applicable or not (to be managed by this object) should not be applied * here. * *

Note: This interface is intended to be implemented by plugins.

* * @since 3.1.0.1 */ public interface SaveLocationManager { /** * Return the location to move the download to when it first started (or * return null to keep the download and torrent in the same * location). * * @param download Download to handle. * @param for_move true if the download is going to be moved, or false * if the logical path is just being calculated for other reasons. * @param on_event true if the download really is being initialised, or * false if we are just determining the appropriate location for an incomplete * download. * @return The new save location instructions. */ public SaveLocationChange onInitialization(Download download, boolean for_move, boolean on_event); /** * Return the location to move the download to when it is completed (or * return null to keep the download and torrent in the same * location). * * @param download Download to handle. * @param for_move true if the download is going to be moved, or false * if the logical path is just being calculated for other reasons. * @param on_event true if the download really is being moved for completion, or * false if we are just determining the appropriate location for an complete * download. * @return The new save location instructions. */ public SaveLocationChange onCompletion(Download download, boolean for_move, boolean on_event); /** * Return the location to move the download to when it is removed (or * return null to keep the download and torrent in the same * location). * * @param download Download to handle. * @param for_move true if the download is going to be moved, or false * if the logical path is just being calculated for other reasons. * @param on_event true if the download really is being removed, or * false if we are just determining the appropriate location for the download * when it is removed. * @return The new save location instructions. */ public SaveLocationChange onRemoval(Download download, boolean for_move, boolean on_event); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/savelocation/SaveLocationChange.java0000644000175000017500000001076311026552476030513 0ustar adrianadrian/* * Created on 12 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.download.savelocation; import java.io.File; /** * Used by {@link SaveLocationManager} - you create an instance, set the * attributes here and return the value. * * @since 3.0.5.3 */ public class SaveLocationChange { /** * The new location to move the download to. */ public File download_location = null; /** * The new name to give the download. */ public String download_name = null; /** * The new location to move the torrent to. */ public File torrent_location = null; /** * The new name to give the torrent. */ public String torrent_name = null; /** * String representation of this object. */ public final String toString() { StringBuffer res = new StringBuffer("SaveLocationChange: "); res.append("DL-LOC="); res.append(download_location); res.append(", DL-NAME="); res.append(download_name); res.append(", TOR-LOC="); res.append(torrent_location); res.append(", TOR-NAME="); res.append(torrent_name); return res.toString(); } /** * Given the location of the existing torrent, determine the new path * to store the torrent. */ public final File normaliseTorrentLocation(File old_torrent_location) { return this.normaliseTorrentLocation(old_torrent_location.getParentFile(), old_torrent_location.getName()); } /** * Given the location of the existing torrent, determine the new path * to store the torrent. */ public final File normaliseTorrentLocation(File old_torrent_directory, String old_torrent_name) { return new File( (torrent_location != null) ? torrent_location : old_torrent_directory, (torrent_name != null) ? torrent_name : old_torrent_name ); } /** * Given the location of the existing download, determine the new path * to store the download. */ public final File normaliseDownloadLocation(File old_download_location) { return this.normaliseDownloadLocation(old_download_location.getParentFile(), old_download_location.getName()); } /** * Given the location of the existing download, determine the new path * to store the download. */ public final File normaliseDownloadLocation(File old_download_directory, String old_download_name) { return new File( (download_location != null) ? download_location : old_download_directory, (download_name != null) ? download_name : old_download_name ); } /** * Returns true if this object indicates a new location for * a download. */ public final boolean hasDownloadChange() { return this.download_location != null || this.download_name != null; } /** * Returns true if this object indicates a new location for * a torrent. */ public final boolean hasTorrentChange() { return this.torrent_location != null || this.torrent_name != null; } /** * Returns true if this object represents a download location * different to the one provided - it will check whether the location * represented here is already the same as the one provided. */ public final boolean isDifferentDownloadLocation(File current_location) { if (!hasDownloadChange()) {return false;} return !current_location.equals(this.normaliseDownloadLocation(current_location)); } /** * Returns true if this object represents a torrent location * different to the one provided - it will check whether the location * represented here is already the same as the one provided. */ public final boolean isDifferentTorrentLocation(File current_location) { if (!hasTorrentChange()) {return false;} return !current_location.equals(this.normaliseTorrentLocation(current_location)); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadPropertyEvent.java0000644000175000017500000000244510373051022026624 0ustar adrianadrian/* * Created on 10-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.download; /** * @author parg * */ public interface DownloadPropertyEvent { public static final int PT_TORRENT_ATTRIBUTE_WRITTEN = 1; // data is a TorrentAttribute public static final int PT_TORRENT_ATTRIBUTE_WILL_BE_READ = 2; // data is a TorrentAttribute public int getType(); public Object getData(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadAnnounceResultPeer.java0000644000175000017500000000446410743527200027571 0ustar adrianadrian/* * Created on 07-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.download; import org.gudy.azureus2.core3.peer.PEPeerSource; /** * @author parg * */ public interface DownloadAnnounceResultPeer { public static final short PROTOCOL_NORMAL = 1; public static final short PROTOCOL_CRYPT = 2; /** * Peer source for all peers discovered through a tracker announce */ public static final String PEERSOURCE_BT_TRACKER = PEPeerSource.PS_BT_TRACKER; /** * Peer source for all peers discovered through other peers from a globally accessible gossiping protocl (usually a DHT) */ public static final String PEERSOURCE_DHT = PEPeerSource.PS_DHT; /** * Peer source for all peers discovered through other peers in the same swarm via gossiping protocols */ public static final String PEERSOURCE_PEX = PEPeerSource.PS_OTHER_PEER; /** * Peer source for all peers discovered by plugins that do not fall into the other categories */ public static final String PEERSOURCE_PLUGIN = PEPeerSource.PS_PLUGIN; /** * Peer source for all peers which already connected to us but we know nothing about since the connection is incoming */ public static final String PEERSOURCE_INCOMING = PEPeerSource.PS_INCOMING; public String getSource(); public int getPort(); public int getUDPPort(); public String getAddress(); public byte[] getPeerID(); public short getProtocol(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadException.java0000644000175000017500000000224111012742460025732 0ustar adrianadrian/* * File : DownloadException.java * Created : 08-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; /** Throws by various Download methods to indicate errors * * @author parg * @since 2.0.7.0 */ public class DownloadException extends Exception { public DownloadException( String str ) { super(str); } public DownloadException( String str, Throwable cause ) { super(str,cause); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadCompletionListener.java0000644000175000017500000000245511021114756027623 0ustar adrianadrian/* * Created on 2 Jun 2008 * Created by Allan Crooks * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.download; /** * Listener interface to be used for plugins to be notified when downloads * enter a completed state. * *

Note: This interface is intended to be implemented by plugins.

* * @since 3.0.5.3 */ public interface DownloadCompletionListener { /** * Called when a download enters a complete state (previously being * incomplete). * * @param d Download which has been completed. */ public void onCompletion(Download d); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadPeerListener.java0000644000175000017500000000223710061315112026373 0ustar adrianadrian/* * File : DownloadPeerListener.java * Created : 01-Apr-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; /** * * @author parg * @since 2.1.0.0 */ import org.gudy.azureus2.plugins.peers.*; public interface DownloadPeerListener { public void peerManagerAdded( Download download, PeerManager peer_manager ); public void peerManagerRemoved( Download download, PeerManager peer_manager ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadEventNotifier.java0000644000175000017500000001445611021114756026571 0ustar adrianadrian/* * Created on 12 Feb 2007. * Created by Allan Crooks. * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. This program is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, write * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. AELITIS, SAS au capital de 46,603.30 euros 8 Allee * Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.download; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; /** * This interface defines what methods an object should have defined to be able * to inform listener objects about various events which occur on a download. * * In previous versions of Azureus, the {@link Download} class was the only * interface which defined these methods - now * {@link DownloadManager#getGlobalDownloadEventNotifier} supports these methods too. * * @since 3.0.0.9 * @author amc1 */ public interface DownloadEventNotifier { /** * Adds a listener that will be informed of changes to a download's state. * * @param l The listener to add. * @since 2.0.7.0 */ public void addListener(DownloadListener l); /** * Removes a listener object added via the * {@link #addDownloadListener(DownloadListener)} method. * * @param l The listener to remove. * @since 2.0.7.0 */ public void removeListener(DownloadListener l); /** * Adds a listener that will be informed when the latest announce/scrape * results change. *

* Listener events will be immediately triggered after the listener has been * added. * * @param l The listener to add. * @since 2.0.7.0 */ public void addTrackerListener(DownloadTrackerListener l); /** * Adds a listener that will be informed when the latest announce/scrape * results change. * * @param l The listener to add. * @param immediateTrigger Whether to immediately trigger listener's events. * @since 2.4.0.3 */ public void addTrackerListener(DownloadTrackerListener l, boolean immediateTrigger); /** * Removes a listener object added via the * {@link #addTrackerListener(DownloadTrackerListener)} or * {@link #addTrackerListener(DownloadTrackerListener, boolean)} method. * * @param l The listener to remove. * @since 2.0.7.0 */ public void removeTrackerListener(DownloadTrackerListener l); /** * Adds a listener that will be informed when a download is about to be * removed. This gives the implementor the opportunity to veto the removal. * * @param l The listener to add. * @since 2.0.7.0 */ public void addDownloadWillBeRemovedListener(DownloadWillBeRemovedListener l); /** * Removes a listener object added via the * {@link #addDownloadWillBeRemovedListener(DownloadWillBeRemovedListener)} * method. * * @param l The listener to remove. * @since 2.0.7.0 */ public void removeDownloadWillBeRemovedListener( DownloadWillBeRemovedListener l); /** * Adds a listener that will be invoked when a request is made to activate a * torrent. * * @param l The listener to add. * @since 2.4.0.3 */ public void addActivationListener(DownloadActivationListener l); /** * Removes a listener object added via the * {@link #addActivationListener(DownloadActivationListener)} method. * * @param l The listener to remove. * @since 2.4.0.3 */ public void removeActivationListener(DownloadActivationListener l); /** * Adds a listener that will be informed of when peer managers have been * added / removed for a download. * * @param l The listener to add. * @since 2.1.0.0 */ public void addPeerListener(DownloadPeerListener l); /** * Removes a listener object added via the * {@link #addPeerListener(DownloadPeerListener)} method. * * @param l The listener to remove. * @since 2.1.0.0 */ public void removePeerListener(DownloadPeerListener l); /** * Adds a listener that will be informed of when properties on a download * have been read / modified. * * @param l The listener to add. * @since 2.2.0.2 * @deprecated Use {@link #addAttributeListener(DownloadAttributeListener, TorrentAttribute, int)} * instead - support for this method will be removed in future. */ public void addPropertyListener(DownloadPropertyListener l); /** * Removes a listener object added via the * {@link #addPropertyListener(DownloadPropertyListener)} method. * * @param l The listener to remove. * @since 2.2.0.2 */ public void removePropertyListener(DownloadPropertyListener l); /** * Adds a listener that will be informed of when attributes on a download * have been read / modified. * * @param l The listener to add. * @param attr The torrent attribute to be notified about. * @param event_type The type of event to be notified of, as defined on {@link DownloadAttributeListener}. * @since 3.0.3.5 */ public void addAttributeListener(DownloadAttributeListener l, TorrentAttribute attr, int event_type); /** * Removes a listener object added via the * {@link #addAttributeListener(DownloadAttributeListener, TorrentAttribute, int) method. * * @param l The listener to remove. * @param attr The torrent attribute which it registered with. * @param event_type The type of event which it registered with. * @since 3.0.3.5 */ public void removeAttributeListener(DownloadAttributeListener l, TorrentAttribute attr, int event_type); /** * Adds a listener that will be informed when a download moves into a * completed state. * * @param l The listener to add. * @since 3.0.5.3 */ public void addCompletionListener(DownloadCompletionListener l); /** * Removes a listener object removed via the * {@link #addCompletionListener(DownloadCompletionListener)} method. * * @param l The listener to remove. * @since 3.0.5.3 */ public void removeCompletionListener(DownloadCompletionListener l); } azureus-4.3.0.6/org/gudy/azureus2/plugins/download/DownloadTypeComplete.java0000644000175000017500000000170611066073412026416 0ustar adrianadrian/** * Created on Sep 19, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.download; /** * For registering columns, menus, etc with a datasource * * @author TuxPaper * @created Sep 19, 2008 * */ public interface DownloadTypeComplete { } azureus-4.3.0.6/org/gudy/azureus2/plugins/UnloadablePlugin.java0000644000175000017500000000217410373051030023722 0ustar adrianadrian/* * Created on 26-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins; /** * @author parg * * @since 2.1.0.0 */ public interface UnloadablePlugin extends Plugin { public void unload() throws PluginException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/package.html0000644000175000017500000000045710561764740022137 0ustar adrianadrian Provides interfaces in order to create Azureus Plugins.

For non API information about developing plugins for Azureus, visit the Wiki at Plugin Documentation azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginConfig.java0000644000175000017500000013655511062600114023073 0ustar adrianadrian/* * File : PluginConfig.java * Created : 17 nov. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins; /** * @author Olivier * */ import java.io.File; import java.util.List; import java.util.Map; import org.gudy.azureus2.plugins.config.*; /** * This class provides a way for a plugin to get and set configuration settings - both for the plugin * itself and for core settings as well. * *

* * This class interface contains four different variations of get and set parameter methods: *

    *
  • gettypeParameter
  • *
  • getCoretypeParameter
  • *
  • getUnsafetypeParameter
  • *
  • getPlugintypeParameter
  • *
* * The first set of methods are deprecated and should not be used in general - this is because the method names were * ambiguous and it wasn't always obvious what data you were trying to get or set. *

* The second set of methods do what the first set of methods were primarily intended for - you can use these * methods to get or set some core parameters. You should use the parameter names defined as constants in this interface * (the ones labelled CORE_PARAM). These parameters will be properly supported by Azureus, even if the way these * values are stored or handled differently in the Azureus core itself.
*
* Attempting to set or get parameters not mentioned here should raise an error (in some cases in the past, this wasn't * always enforced by the first set of methods. *

* The third set of methods allow you to modify configuration settings which are stored directly inside Azureus. These * settings may change (without warning) between versions, so there is no guarantee that plugins that use these values * will behave properly in different versions of Azureus. *

* The last set of methods are used to store and retrieve data intended exclusively for the use of the plugin itself, * which is what you will be using most of the time. */ public interface PluginConfig { public static final String CORE_PARAM_INT_MAX_UPLOAD_SPEED_KBYTES_PER_SEC = "Max Upload Speed KBs"; public static final String CORE_PARAM_INT_MAX_UPLOAD_SPEED_SEEDING_KBYTES_PER_SEC = "Max Upload Speed When Only Seeding KBs"; public static final String CORE_PARAM_INT_MAX_DOWNLOAD_SPEED_KBYTES_PER_SEC = "Max Download Speed KBs"; public static final String CORE_PARAM_INT_MAX_CONNECTIONS_PER_TORRENT = "Max Connections Per Torrent"; public static final String CORE_PARAM_INT_MAX_CONNECTIONS_GLOBAL = "Max Connections Global"; public static final String CORE_PARAM_INT_MAX_DOWNLOADS = "Max Downloads"; public static final String CORE_PARAM_INT_MAX_ACTIVE = "Max Active Torrents"; public static final String CORE_PARAM_INT_MAX_ACTIVE_SEEDING = "Max Active Torrents When Only Seeding"; public static final String CORE_PARAM_INT_MAX_UPLOADS = "Max Uploads"; public static final String CORE_PARAM_INT_MAX_UPLOADS_SEEDING = "Max Uploads Seeding"; public static final String CORE_PARAM_BOOLEAN_AUTO_SPEED_ON = "Auto Upload Speed Enabled"; public static final String CORE_PARAM_BOOLEAN_MAX_UPLOAD_SPEED_SEEDING = "Max Upload Speed When Only Seeding Enabled"; public static final String CORE_PARAM_BOOLEAN_MAX_ACTIVE_SEEDING = "Max Active Torrents When Only Seeding Enabled"; public static final String CORE_PARAM_BOOLEAN_SOCKS_PROXY_NO_INWARD_CONNECTION = "SOCKS Proxy No Inward Connection"; public static final String CORE_PARAM_BOOLEAN_NEW_SEEDS_START_AT_TOP = "Newly Seeding Torrents Get First Priority"; /** * @since 2.3.0.5 */ public static final String CORE_PARAM_STRING_LOCAL_BIND_IP = "CORE_PARAM_STRING_LOCAL_BIND_IP"; public static final String CORE_PARAM_BOOLEAN_FRIENDLY_HASH_CHECKING = "CORE_PARAM_BOOLEAN_FRIENDLY_HASH_CHECKING"; /** * @since 3.0.4.3 */ public static final String GUI_PARAM_INT_SWT_REFRESH_IN_MS = "GUI_PARAM_INT_SWT_REFRESH_IN_MS"; /** * @since 3.0.4.3 */ public static final String CORE_PARAM_BOOLEAN_NEW_TORRENTS_START_AS_STOPPED = "CORE_PARAM_BOOLEAN_NEW_TORRENTS_START_AS_STOPPED"; /** * @since 3.0.5.3 */ public static final String CORE_PARAM_INT_INCOMING_TCP_PORT = "Incoming TCP Port"; /** * @since 3.0.5.3 */ public static final String CORE_PARAM_INT_INCOMING_UDP_PORT = "Incoming UDP Port"; /** * @since 3.1.1.1 */ public static final String CORE_PARAM_STRING_DEFAULT_SAVE_PATH = "Default save path"; /** * Returns the value of a core boolean parameter. * * @param key The parameter name. * @return The value of the parameter. * * @deprecated Use {@link #getUnsafeBooleanParameter(String)} for internal core parameters, or {@link #getCoreBooleanParameter(String)} for core parameters defined here. * @since 2.0.4.2 */ public boolean getBooleanParameter(String key); /** * Returns the value of a core boolean parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @deprecated Use {@link #getUnsafeBooleanParameter(String, boolean)} for internal core parameters, or {@link #getCoreBooleanParameter(String, boolean)} for core parameters defined here. * @since 2.0.6.0 */ public boolean getBooleanParameter(String key, boolean default_value); /** * Returns the value of a core byte array parameter. * * @param key The parameter name. * @return The value of the parameter. * * @deprecated Use {@link #getUnsafeByteParameter(String)} for internal core parameters, or {@link #getCoreByteParameter(String)} for core parameters defined here. * @since 3.0.0.7 */ public byte[] getByteParameter(String key); /** * Returns the value of a core byte array parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @deprecated Use {@link #getUnsafeByteParameter(String, byte[])} for internal core parameters, or {@link #getCoreByteParameter(String, byte[])} for core parameters defined here. * @since 2.1.0.2 */ public byte[] getByteParameter(String key, byte[] default_value); /** * Returns the value of a core float parameter. * * @param key The parameter name. * @return The value of the parameter. * * @deprecated Use {@link #getUnsafeFloatParameter(String)} for internal core parameters, or {@link #getCoreFloatParameter(String)} for core parameters defined here. * @since 2.1.0.0 */ public float getFloatParameter(String key); /** * Returns the value of a core float parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @deprecated Use {@link #getUnsafeFloatParameter(String, float)} for internal core parameters, or {@link #getCoreFloatParameter(String, float)} for core parameters defined here. * @since 3.0.0.7 */ public float getFloatParameter(String key, float default_value); /** * Returns the value of a core int parameter. * * @param key The parameter name. * @return The value of the parameter. * * @deprecated Use {@link #getUnsafeIntParameter(String)} for internal core parameters, or {@link #getCoreIntParameter(String)} for core parameters defined here. * @since 2.0.4.2 */ public int getIntParameter(String key); /** * Returns the value of a core int parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @deprecated Use {@link #getUnsafeIntParameter(String, int)} for internal core parameters, or {@link #getCoreIntParameter(String, int)} for core parameters defined here. * @since 2.0.7.0 */ public int getIntParameter(String key, int default_value); /** * Returns the value of a core long parameter. * * @param key The parameter name. * @return The value of the parameter. * * @deprecated Use {@link #getUnsafeLongParameter(String)} for internal core parameters, or {@link #getCoreLongParameter(String)} for core parameters defined here. * @since 3.0.0.7 */ public long getLongParameter(String key); /** * Returns the value of a core long parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @deprecated Use {@link #getUnsafeLongParameter(String, long)} for internal core parameters, or {@link #getCoreLongParameter(String, long)} for core parameters defined here. * @since 3.0.0.7 */ public long getLongParameter(String key, long default_value); /** * Returns the value of a core string parameter. * * @param key The parameter name. * @return The value of the parameter. * * @deprecated Use {@link #getUnsafeStringParameter(String)} for internal core parameters, or {@link #getCoreStringParameter(String)} for core parameters defined here. * @since 2.0.4.2 */ public String getStringParameter(String key); /** * Returns the value of a core string parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @deprecated Use {@link #getUnsafeStringParameter(String, String)} for internal core parameters, or {@link #getCoreStringParameter(String, String)} for core parameters defined here. * @since 2.1.0.0 */ public String getStringParameter(String key, String default_value); /** * Sets the value of a core boolean parameter. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @deprecated Use {@link #setUnsafeBooleanParameter(String, boolean)} for internal core parameters, or {@link #setCoreBooleanParameter(String, boolean)} for core parameters defined here. */ public void setBooleanParameter(String key, boolean value); /** * Sets the value of a core byte array parameter. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @deprecated Use {@link #setUnsafeByteParameter(String, byte[])} for internal core parameters, or {@link #setCoreByteParameter(String, byte[])} for core parameters defined here. * @since 3.0.0.7 */ public void setByteParameter(String key, byte[] value); /** * Sets the value of a core float parameter. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @deprecated Use {@link #setUnsafeFloatParameter(String, float)} for internal core parameters, or {@link #setCoreFloatParameter(String, float)} for core parameters defined here. * @since 3.0.0.7 */ public void setFloatParameter(String key, float value); /** * Sets the value of a core int parameter. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @deprecated Use {@link #setUnsafeIntParameter(String, int)} for internal core parameters, or {@link #setCoreIntParameter(String, int)} for core parameters defined here. * @since 2.0.8.0 */ public void setIntParameter(String key, int value); /** * Sets the value of a core long parameter. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @deprecated Use {@link #setUnsafeLongParameter(String, long)} for internal core parameters, or {@link #setCoreLongParameter(String, long)} for core parameters defined here. * @since 3.0.0.7 */ public void setLongParameter(String key, long value); /** * Sets the value of a core string parameter. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @deprecated Use {@link #setUnsafeStringParameter(String, String)} for internal core parameters, or {@link #setCoreStringParameter(String, String)} for core parameters defined here. * @since 3.0.0.7 */ public void setStringParameter(String key, String value); /** * Returns the value of a core boolean parameter. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.4.3 */ public boolean getCoreBooleanParameter(String key); /** * Returns the value of a core boolean parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.4.3 */ public boolean getCoreBooleanParameter(String key, boolean default_value); /** * Returns the value of a core byte array parameter. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.4.3 */ public byte[] getCoreByteParameter(String key); /** * Returns the value of a core byte array parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.5.3 */ public byte[] getCoreByteParameter(String key, byte[] default_value); /** * Returns the value of a core color parameter. * *

* * It will return null if no color parameter is stored, or an * integer array of size 4 representing the red, green and blue values, * and a flag indicating if the color is an override of the default or * not (0 indicates no override, 1 means it is overridden). * *

* * In many cases, the override flag can just be ignored. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.5.3 */ public int[] getCoreColorParameter(String key); /** * Returns the value of a core color parameter. * *

* * It will return null if no color parameter is stored, or an * integer array of size 4 representing the red, green and blue values, * and a flag indicating if the color is an override of the default or * not (0 indicates no override, 1 means it is overridden). * *

* * In many cases, the override flag can just be ignored. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.5.3 */ public int[] getCoreColorParameter(String key, int[] default_value); /** * Returns the value of a core float parameter. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.4.3 */ public float getCoreFloatParameter(String key); /** * Returns the value of a core float parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.4.3 */ public float getCoreFloatParameter(String key, float default_value); /** * Returns the value of a core int parameter. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.4.3 */ public int getCoreIntParameter(String key); /** * Returns the value of a core int parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.4.3 */ public int getCoreIntParameter(String key, int default_value); /** * Returns the value of a core long parameter. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.4.3 */ public long getCoreLongParameter(String key); /** * Returns the value of a core long parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.4.3 */ public long getCoreLongParameter(String key, long default_value); /** * Returns the value of a core string parameter. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.4.3 */ public String getCoreStringParameter(String key); /** * Returns the value of a core string parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.4.3 */ public String getCoreStringParameter(String key, String default_value); /** * Sets the value of a core boolean parameter. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.4.2 */ public void setCoreBooleanParameter(String key, boolean value); /** * Sets the value of a core byte array parameter. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.4.2 */ public void setCoreByteParameter(String key, byte[] value); /** * Sets the value of a core byte array parameter. * *

* * The value should be an integer array of size 3 representing * the red, green and blue values - or null to disable it. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.5.3 */ public void setCoreColorParameter(String key, int[] value); /** * Sets the value of a core byte array parameter. * *

* * The value should be an integer array of size 3 representing * the red, green and blue values - or null to disable it. * *

* * The override flag is used to indicate if the value being set is overriding * the default value. This is mainly used for interface purposes. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * @param override true if the value is overridden from the default. * * @since 3.0.5.3 */ public void setCoreColorParameter(String key, int[] value, boolean override); /** * Sets the value of a core float parameter. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.4.2 */ public void setCoreFloatParameter(String key, float value); /** * Sets the value of a core int parameter. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.4.2 */ public void setCoreIntParameter(String key, int value); /** * Sets the value of a core long parameter. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.4.2 */ public void setCoreLongParameter(String key, long value); /** * Sets the value of a core string parameter. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.4.2 */ public void setCoreStringParameter(String key, String value); /** * Returns the value of a plugin boolean parameter. * * @param key The parameter name. * @return The value of the parameter. * * @since 2.0.4.2 */ public boolean getPluginBooleanParameter(String key); /** * Returns the value of a plugin boolean parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 2.0.4.2 */ public boolean getPluginBooleanParameter(String key, boolean default_value); /** * Returns the value of a plugin byte array parameter. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.0.7 */ public byte[] getPluginByteParameter(String key); /** * Returns the value of a plugin byte array parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 2.2.0.3 */ public byte[] getPluginByteParameter(String key, byte[] default_value); /** * Returns the value of a plugin color parameter. * *

* * It will return null if no color parameter is stored, or an * integer array of size 4 representing the red, green and blue values, * and a flag indicating if the color is an override of the default or * not (0 indicates no override, 1 means it is overridden). * *

* * In many cases, the override flag can just be ignored. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.5.3 */ public int[] getPluginColorParameter(String key); /** * Returns the value of a plugin color parameter. * *

* * It will return null if no color parameter is stored, or an * integer array of size 4 representing the red, green and blue values, * and a flag indicating if the color is an override of the default or * not (0 indicates no override, 1 means it is overridden). * *

* * In many cases, the override flag can just be ignored. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.5.3 */ public int[] getPluginColorParameter(String key, int[] default_value); /** * Returns the value of a plugin float parameter. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.0.7 */ public float getPluginFloatParameter(String key); /** * Returns the value of a plugin float parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.0.7 */ public float getPluginFloatParameter(String key, float default_value); /** * Returns the value of a plugin int parameter. * * @param key The parameter name. * @return The value of the parameter. * * @since 2.0.4.2 */ public int getPluginIntParameter(String key); /** * Returns the value of a plugin int parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 2.0.4.2 */ public int getPluginIntParameter(String key, int default_value); /** * Returns the value of a plugin list parameter. The contents of the list must conform * to bencodable rules (e.g. Map, Long, byte[], List) * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 2.3.0.1 */ public List getPluginListParameter(String key, List default_value); /** * Returns the value of a plugin long parameter. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.0.7 */ public long getPluginLongParameter(String key); /** * Returns the value of a plugin long parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.0.7 */ public long getPluginLongParameter(String key, long default_value); /** * Returns the value of a plugin map parameter. The contents of the map must conform * to bencodable rules (e.g. Map, Long, byte[], List) * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 2.3.0.1 */ public Map getPluginMapParameter(String key, Map default_value); /** * Returns the value of a plugin string parameter. * * @param key The parameter name. * @return The value of the parameter. * * @since 2.0.4.2 */ public String getPluginStringParameter(String key); /** * Returns the value of a plugin string parameter. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 2.0.4.2 */ public String getPluginStringParameter(String key, String default_value); /** * Returns the value of a plugin string-list parameter. If no value is set, * an empty string array will be returned. * * @param key The parameter name. * @return The value of the parameter. * @since 3.0.5.3 */ public String[] getPluginStringListParameter(String key); /** * Sets the value of a plugin boolean parameter. * * @param key The parameter name. * @param value The new value for the parameter. * * @since 2.0.4.2 */ public void setPluginParameter(String key, boolean value); /** * Sets the value of a plugin byte array parameter. * * @param key The parameter name. * @param value The new value for the parameter. * * @since 2.1.0.2 */ public void setPluginParameter(String key, byte[] value); /** * Sets the value of a plugin float parameter. * * @param key The parameter name. * @param value The new value for the parameter. * * @since 3.0.0.7 */ public void setPluginParameter(String key, float value); /** * Sets the value of a plugin int parameter. * * @param key The parameter name. * @param value The new value for the parameter. * * @since 2.0.4.2 */ public void setPluginParameter(String key, int value); /** * Sets the value of a plugin int parameter. * * @param key The parameter name. * @param value The new value for the parameter. * @param global Whether or not this parameter should be made externally accessible. * * @since 2.5.0.1 */ public void setPluginParameter(String key, int value, boolean global); /** * Sets the value of a plugin long parameter. * * @param key The parameter name. * @param value The new value for the parameter. * * @since 3.0.0.7 */ public void setPluginParameter(String key, long value); /** * Sets the value of a plugin string parameter. * * @param key The parameter name. * @param value The new value for the parameter. * * @since 2.0.4.2 */ public void setPluginParameter(String key, String value); /** * Sets the value of a plugin string-list parameter. * * @param key The parameter name. * @param value The new value of the parameter. * @since 3.0.5.3 */ public void setPluginStringListParameter(String key, String[] value); /** * Sets the value of a plugin color parameter. * *

* * The value should be an integer array of size 3 representing * the red, green and blue values - or null to disable it. * * @param key The parameter name. * @param value The new value for the parameter. * @return The value of the parameter. * * @since 3.0.5.3 */ public void setPluginColorParameter(String key, int[] value); /** * Sets the value of a plugin color parameter. * *

* * The value should be an integer array of size 3 representing * the red, green and blue values - or null to disable it. * *

* * The override flag is used to indicate if the value being set is overriding * the default value. This is mainly used for interface purposes. * * @param key The parameter name. * @param value The new value for the parameter. * @param override true if the value is overridden from the default. * @return The value of the parameter. * * @since 3.0.5.3 */ public void setPluginColorParameter(String key, int[] value, boolean override); /** * Sets the value of a plugin list parameter. The contents of the list must conform * to bencodable rules (e.g. Map, Long, byte[], List) * * @param key The parameter name. * @param value The new value for the parameter. * * @since 2.3.0.1 */ public void setPluginListParameter(String key, List value); /** * Sets the value of a plugin map parameter. The contents of the map must conform * to bencodable rules (e.g. Map, Long, byte[], List) * * @param key The parameter name. * @param value The new value for the parameter. * * @since 2.3.0.1 */ public void setPluginMapParameter(String key, Map value); /** * Returns the value of a core boolean parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.0.7 */ public boolean getUnsafeBooleanParameter(String key); /** * Returns the value of a core boolean parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.0.5 */ public boolean getUnsafeBooleanParameter(String key, boolean default_value); /** * Returns the value of a core byte array parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.0.7 */ public byte[] getUnsafeByteParameter(String key); /** * Returns the value of a core byte array parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.0.7 */ public byte[] getUnsafeByteParameter(String key, byte[] default_value); /** * Returns the value of a core color parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * *

* * It will return null if no color parameter is stored, or an * integer array of size 4 representing the red, green and blue values, * and a flag indicating if the color is an override of the default or * not (0 indicates no override, 1 means it is overridden). * *

* * In many cases, the override flag can just be ignored. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.5.3 */ public int[] getUnsafeColorParameter(String key); /** * Returns the value of a core color parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * *

* * It will return null if no color parameter is stored, or an * integer array of size 4 representing the red, green and blue values, * and a flag indicating if the color is an override of the default or * not (0 indicates no override, 1 means it is overridden). * *

* * In many cases, the override flag can just be ignored. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.5.3 */ public int[] getUnsafeColorParameter(String key, int[] default_value); /** * Returns the value of a core float parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.0.7 */ public float getUnsafeFloatParameter(String key); /** * Returns the value of a core float parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.0.5 */ public float getUnsafeFloatParameter(String key, float default_value); /** * Returns the value of a core int parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.0.7 */ public int getUnsafeIntParameter(String key); /** * Returns the value of a core int parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.0.5 */ public int getUnsafeIntParameter(String key, int default_value); /** * Returns the value of a core long parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.0.7 */ public long getUnsafeLongParameter(String key); /** * Returns the value of a core long parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.0.5 */ public long getUnsafeLongParameter(String key, long default_value); /** * Returns the value of a core string parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name. * @return The value of the parameter. * * @since 3.0.0.7 */ public String getUnsafeStringParameter(String key); /** * Returns the value of a core string parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name. * @param default_value The default value to return if one is not defined. * @return The value of the parameter. * * @since 3.0.0.5 */ public String getUnsafeStringParameter(String key, String default_value); /** * Sets the value of a core boolean parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.0.5 */ public void setUnsafeBooleanParameter(String key, boolean value); /** * Sets the value of a core byte array parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.0.7 */ public void setUnsafeByteParameter(String key, byte[] value); /** * Returns the value of a core color parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * *

* * The value should be an integer array of size 3 representing * the red, green and blue values - or null to disable it. * * @param key The parameter name. * @param value The new value for the parameter. * * @since 3.0.5.3 */ public void setUnsafeColorParameter(String key, int[] value); /** * Returns the value of a core color parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * *

* * The value should be an integer array of size 3 representing * the red, green and blue values - or null to disable it. * *

* * The override flag is used to indicate if the value being set is overriding * the default value. This is mainly used for interface purposes. * * @param key The parameter name. * @param value The default value to return if one is not defined. * @param override true if the value is overridden from the default. * * @since 3.0.5.3 */ public void setUnsafeColorParameter(String key, int[] value, boolean override); /** * Sets the value of a core float parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.0.5 */ public void setUnsafeFloatParameter(String key, float value); /** * Sets the value of a core int parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.0.5 */ public void setUnsafeIntParameter(String key, int value); /** * Sets the value of a core long parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.0.5 */ public void setUnsafeLongParameter(String key, long value); /** * Sets the value of a core string parameter. Note: the semantics of this * method will not be guaranteed - core parameter names may change in the future, * and this method will not do any parameter name mapping for you, so take care when * using this method. * * @param key The parameter name, which must be one defined from the above core constants. * @param value The new value for the parameter. * * @since 3.0.0.5 */ public void setUnsafeStringParameter(String key, String value); /** * Removes the plugin parameter with the given name. * * @param key Name of the parameter. * @return true if the parameter was found and removed. */ public boolean removePluginParameter(String key); /** * Removes the plugin color parameter with the given name. * * @param key Name of the parameter. * @return true if the parameter was found and removed. * * @since 3.0.5.3 */ public boolean removePluginColorParameter(String key); /** * @return the prefix used when storing configuration values in the config file for * this plugin's config parameters * * @since 2.1.0.0 */ public String getPluginConfigKeyPrefix(); public ConfigParameter getParameter( String key ); public ConfigParameter getPluginParameter( String key ); public boolean isNewInstall(); /** * Returns a map giving parameter names -> parameter values. Value can be Long or String * as the type is actually not known by the core (might fix one day). Therefore, float values are actually * represented by their String format: * * boolean - Long 0 or 1 * int - Long.intValue * float - String value * String - String * * Unsafe methods - existence/semantics of parameters not guaranteed to be maintained across versions * If something changes and breaks your plugin, don't come complaining to me * @since 2.5.0.3 */ public Map getUnsafeParameterList(); /** * make sure you save it after making changes! * * @since 2.0.8.0 */ public void save() throws PluginException; /** * Returns a file that can be used by the plugin to save user-specific state. *

* * This will be azureus-user-dir/plugins/plugin-name/name. * @param name * @return */ public File getPluginUserFile( String name ); /** * Returns true if a core parameter with the given name exists. * @param key The name of the parameter to check. * @since 2.5.0.2 */ public boolean hasParameter(String param_name); /** * Returns true if a plugin parameter with the given name exists. * @param key The name of the parameter to check. * @since 2.5.0.2 */ public boolean hasPluginParameter(String param_name); public void addListener( PluginConfigListener l ); /** * @param _key * * @since 2.5.0.1 */ public void setPluginConfigKeyPrefix(String _key); /** * Enable the plugin to store configuration parameters into a separate * external configuration file. Note: once this method is called, * you need to invoke {@link PluginConfigSource#initialize()} for the * external configuration file to be properly integrated with Azureus. * *

* * When a plugin is first initialised, it should call this method as * soon as possible during the initialization stage. This then configures * the PluginConfig object to store any parameter values into an external * configuration file (rather than storing it directly with the main * configuration file used by Azureus). * *

* * When this method is invoked, it will return an object which allows * the filename to be chosen - it allows a limited amount of manipulation * of the configuration file. This method only needs to be invoked once. * *

* * All methods which get and set plugin parameters on this object will store * data in the external configuration file. The use of classes like * {@link org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel BasicPluginConfigModel} * will automatically integrate parameters to the external configuration * source. * *

* * However, if you use any other mechanism to store parameter data, you may need to call * the {@link org.gudy.azureus2.plugins.ui.config.PluginConfigSource#registerParameter registerParameter} * to integrate the parameter properly. * * @since 3.0.5.3 * @return The PluginConfigSource object representing the external configuration file. */ public PluginConfigSource enableExternalConfigSource(); /** * Returns the PluginConfigSource object used for this plugin configuration (or * null if an external configuration object isn't used). * * @since 3.0.5.3 * @return The PluginConfigSource object. */ public PluginConfigSource getPluginConfigSource(); /** * Sets the plugin configuration source object to use for storing parameters for this * plugin config object. * *

* * This method should only be used as an alternative to {@link #enableExternalConfigSource()}. * You will only need to use this method if you use the * {@link PluginInterface#getLocalPluginInterface(Class, String) getLocalPluginInterface} * method to store data in a separate namespace, but want to use the same configuration file to * store data in. * * @param source The PluginConfigSource object to use. * @since 3.0.5.3 */ public void setPluginConfigSource(PluginConfigSource source); } azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginListener.java0000644000175000017500000000204310061315112023432 0ustar adrianadrian/* * File : PluginListener.java * Created : 31-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins; /** * @author parg * * @since 2.0.7.0 */ public interface PluginListener { public void initializationComplete(); public void closedownInitiated(); public void closedownComplete(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginManagerDefaults.java0000644000175000017500000000752411264027746024743 0ustar adrianadrian/* * Created on 13-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins; /** * @author parg * */ public interface PluginManagerDefaults { // if default plugins get removed then set their id to -1! public static final String PID_START_STOP_RULES = "Start/Stop Rules"; public static final String PID_REMOVE_RULES = "Torrent Removal Rules"; public static final String PID_SHARE_HOSTER = "Share Hoster"; public static final String PID_DEFAULT_TRACKER_WEB = "Default Tracker Web"; //public static final String PID_UPDATE_LANGUAGE = "Update Language"; public static final String PID_PLUGIN_UPDATE_CHECKER = "Plugin Update Checker"; public static final String PID_CORE_UPDATE_CHECKER = "Core Update Checker"; public static final String PID_CORE_PATCH_CHECKER = "Core Patch Checker"; public static final String PID_PLATFORM_CHECKER = "Platform Checker"; public static final String PID_UPNP = "UPnP"; //public static final String PID_CLIENT_ID = "Client ID"; public static final String PID_DHT = "DHT"; public static final String PID_DHT_TRACKER = "DHT Tracker"; public static final String PID_MAGNET = "Magnet URI Handler"; //public static final String PID_JPC = "JPC"; public static final String PID_EXTERNAL_SEED = "External Seed"; public static final String PID_LOCAL_TRACKER = "Local Tracker"; public static final String PID_TRACKER_PEER_AUTH = "Tracker Peer Auth"; public static final String PID_NET_STATUS = "Network Status"; public static final String PID_BUDDY = "Buddy"; public static final String PID_RSS = "RSS"; public static final String[] PLUGIN_IDS = { PID_START_STOP_RULES, PID_REMOVE_RULES, PID_SHARE_HOSTER, PID_DEFAULT_TRACKER_WEB, //PID_UPDATE_LANGUAGE, PID_CORE_UPDATE_CHECKER, PID_CORE_PATCH_CHECKER, PID_PLATFORM_CHECKER, PID_UPNP, //PID_CLIENT_ID, PID_DHT, PID_DHT_TRACKER, PID_MAGNET, //PID_JPC, PID_EXTERNAL_SEED, PID_LOCAL_TRACKER, PID_TRACKER_PEER_AUTH, PID_NET_STATUS, PID_BUDDY, PID_RSS, }; public String[] getDefaultPlugins(); /** * by default all default plugins are enabled. This methods allows them to be disabled * @param plugin_id */ public void setDefaultPluginEnabled( String plugin_id, boolean enabled ); public boolean isDefaultPluginEnabled( String plugin_id ); /** * Set the name of the application, default is "Azureus", and an identifier for it, default is "az" * default for entry point is the SWT UI * @param name */ public void setApplicationName( String name ); public String getApplicationName(); public void setApplicationIdentifier( String identifier ); public String getApplicationIdentifier(); public void setApplicationEntryPoint( String entry_point ); public String getApplicationEntryPoint(); public void setSingleInstanceHandler( int single_instance_port, PluginManagerArgumentHandler handler ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/clientid/0000755000175000017500000000000011310377616021436 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/clientid/ClientIDManager.java0000644000175000017500000000213511037436220025221 0ustar adrianadrian/* * Created on 29-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.clientid; /** * @author parg * */ public interface ClientIDManager { public ClientIDGenerator getGenerator(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/clientid/ClientIDGenerator.java0000644000175000017500000000446610373051040025601 0ustar adrianadrian/* * Created on 29-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.clientid; import java.util.Properties; import org.gudy.azureus2.plugins.torrent.Torrent; /** * @author parg * */ public interface ClientIDGenerator { public static final String PR_URL = "URL"; // in/out, the target URL public static final String PR_USER_AGENT = "User-Agent"; // out /** * generate a peer id - must be exactly 20 bytes * @param torrent * @param for_tracker generator to give to tracker or for peer-peer comms * @return */ public byte[] generatePeerID( Torrent torrent, boolean for_tracker ) throws ClientIDException; /** * generate appropriate properties to be supplied to HTTP(S) URL connection * If you want to access the torrents then you need to decode the URL to extract the * hashes and then look them up (for scrape there could be multiple torrents) * Enabled when the generator isn't specified as a filter * @param torrent * @param properties */ public void generateHTTPProperties( Properties properties ) throws ClientIDException; /** * For more complex situations a filter approach is used. The lines of the request are * passed in for modification and return * Enabled when the generator is specified as a filter * @param lines_in * @return */ public String[] filterHTTP( String[] lines_in ) throws ClientIDException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/clientid/ClientIDException.java0000644000175000017500000000234111012742460025603 0ustar adrianadrian/* * Created on 30-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.clientid; /** * @author parg * */ public class ClientIDException extends Exception { public ClientIDException( String str ) { super( str ); } public ClientIDException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginEventListener.java0000644000175000017500000000202710061315112024436 0ustar adrianadrian/* * File : PluginEventListener.java * Created : 06-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins; /** allow config wizard progress to be determined * @author parg * * @since 2.0.8.0 */ public interface PluginEventListener { public void handleEvent( PluginEvent ev ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/0000755000175000017500000000000011310377616021334 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/network/TransportCipher.java0000644000175000017500000000203311017134546025321 0ustar adrianadrian/* * Created on 17 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.network; /** * @since 3.0.5.3 */ public interface TransportCipher { } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/IncomingMessageQueueListener.java0000644000175000017500000000277510373051014027762 0ustar adrianadrian/* * Created on Feb 11, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.network; import org.gudy.azureus2.plugins.messaging.Message; /** * Listener for incoming message queue. */ public interface IncomingMessageQueueListener { /** * A message has been read from the connection. * @param message recevied * @return true if this message was accepted, false if not handled */ public boolean messageReceived( Message message ); /** * The given number of bytes read from the connection. * @param byte_count number of protocol bytes */ public void bytesReceived( int byte_count ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/ConnectionListener.java0000644000175000017500000000346010373051014025774 0ustar adrianadrian/* * Created on Feb 9, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.network; /** * Listener for notification of connection events. */ public interface ConnectionListener { /** * The connection establishment process has started, * i.e. the connection is actively being attempted. */ public void connectStarted(); /** * The connection attempt succeeded. * The connection is now established. * NOTE: Called only during initial connect attempt. */ public void connectSuccess(); /** * The connection attempt failed. * NOTE: Called only during initial connect attempt. * @param failure_msg failure reason */ public void connectFailure( Throwable failure_msg ); /** * Handle exception thrown by this connection. * NOTE: Can be called at any time during connection lifetime. * @param error exception */ public void exceptionThrown( Throwable error ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/Connection.java0000644000175000017500000000463311017134546024301 0ustar adrianadrian/* * Created on Feb 9, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.network; /** * Represents a managed peer connection, over which messages can be sent and received. */ public interface Connection { /** * Connect this connection's transport, i.e. establish the peer connection. * If this connection is already established (from an incoming connection for example), * then this provides a mechanism to register the connection listener, in which case * connectSuccess() will be called immediately. * @param listener notified on connect success or failure */ public void connect( ConnectionListener listener ); /** * Close and shutdown this connection. */ public void close(); /** * Get the connection's outgoing message queue. * @return outbound message queue */ public OutgoingMessageQueue getOutgoingMessageQueue(); /** * Get the connection's incoming message queue. * @return inbound message queue */ public IncomingMessageQueue getIncomingMessageQueue(); /** * Begin processing incoming and outgoing message queues. */ public void startMessageProcessing(); /** * Returns the transport object for this connection. * @since 3.0.5.3 */ public Transport getTransport(); /** * Returns true if the connection represents an incoming * connection. * * @since 3.0.5.3 */ public boolean isIncoming(); /** * descriptive text for the connection * @return */ public String getString(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/OutgoingMessageQueue.java0000644000175000017500000000374010373051014026275 0ustar adrianadrian/* * Created on Feb 9, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.network; import org.gudy.azureus2.plugins.messaging.*; /** * Queue for sending outgoing messages. */ public interface OutgoingMessageQueue { /** * Set the message stream encoder that will be used to encode outgoing messages. * @param encoder to use */ public void setEncoder( MessageStreamEncoder encoder ); /** * Queue the given message for sending. * @param message to send */ public void sendMessage( Message message ); /** * Register queue listener. * @param listener to register */ public void registerListener( OutgoingMessageQueueListener listener ); /** * Remove registration of queue listener. * @param listener to remove */ public void deregisterListener( OutgoingMessageQueueListener listener ); /** * Notifty the queue (and its listeners) of a message sent externally on the queue's behalf. * @param message sent externally */ public void notifyOfExternalSend( Message message ); public int getPercentDoneOfCurrentMessage(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/IncomingMessageQueue.java0000644000175000017500000000325510444636734026267 0ustar adrianadrian/* * Created on Feb 9, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.network; import org.gudy.azureus2.plugins.messaging.*; /** * Inbound message queue. */ public interface IncomingMessageQueue { /** * Register queue listener. * @param listener to register */ public void registerListener( IncomingMessageQueueListener listener ); /** * Remove registration of queue listener. * @param listener to remove */ public void deregisterListener( IncomingMessageQueueListener listener ); /** * Notifty the queue (and its listeners) of a message received externally on the queue's behalf. * @param message received externally */ public void notifyOfExternalReceive( Message message ); public int getPercentDoneOfCurrentMessage(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/RawMessage.java0000644000175000017500000000265210373051014024227 0ustar adrianadrian/* * Created on Feb 9, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.network; import java.nio.ByteBuffer; import org.gudy.azureus2.plugins.messaging.Message; /** * A raw data payload used for outbound messages. */ public interface RawMessage extends Message { /** * Get the raw data payload for this message. * @return raw payload */ public ByteBuffer[] getRawPayload(); /** * Get the message this raw message is based upon. * @return original message */ public Message getOriginalMessage(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/TransportFilter.java0000644000175000017500000000015411017134546025336 0ustar adrianadrianpackage org.gudy.azureus2.plugins.network; /** * @since 3.0.5.3 */ public interface TransportFilter { } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/ConnectionManager.java0000644000175000017500000000434711017134546025576 0ustar adrianadrian/* * Created on Feb 9, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.network; import java.net.InetSocketAddress; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.gudy.azureus2.plugins.messaging.*; /** * Manages connections. */ public interface ConnectionManager { public static final int NAT_UNKNOWN = 0; public static final int NAT_OK = 1; public static final int NAT_PROBABLY_OK = 2; public static final int NAT_BAD = 3; /** * Create a new unconnected remote connection (for outbound-initiated connections). * @param remote_address to connect to * @return not yet established connection */ public Connection createConnection( InetSocketAddress remote_address, MessageStreamEncoder encoder, MessageStreamDecoder decoder ); /** * Returns the current view on whether or not we are inwardly connectable via our listener port * @return */ public int getNATStatus(); /** * @since 3.0.5.3 */ public TransportCipher createTransportCipher(String algorithm, int mode, SecretKeySpec key_spec, AlgorithmParameterSpec params) throws TransportException; /** * @since 3.0.5.3 */ public TransportFilter createTransportFilter(Connection connection, TransportCipher read_cipher, TransportCipher write_cipher) throws TransportException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/RateLimiter.java0000644000175000017500000000207211001631246024406 0ustar adrianadrian/* * Created on Apr 16, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.network; import com.aelitis.azureus.core.networkmanager.LimitedRateGroup; public interface RateLimiter extends LimitedRateGroup { /** * Get rate limit. 0 -> unlimited, -1 -> disabled * @return */ public int getRateLimitBytesPerSecond(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/OutgoingMessageQueueListener.java0000644000175000017500000000324110373051014027777 0ustar adrianadrian/* * Created on Feb 9, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.network; import org.gudy.azureus2.plugins.messaging.Message; /** * Listener for outgoing message queue. */ public interface OutgoingMessageQueueListener { /** * The given message has just been added to the queue. * @param message added for queuing * @return true if this message addition is allowed, false if it should be immediately removed without being queued or sent */ public boolean messageAdded( Message message ); /** * The given message has just been completely sent. * @param message */ public void messageSent( Message message ); /** * The given number of bytes has been sent. * @param byte_count */ public void bytesSent( int byte_count ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/Transport.java0000644000175000017500000000433611017134546024176 0ustar adrianadrian/* * Created on Feb 11, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.network; import java.io.IOException; import java.nio.ByteBuffer; /** * Represents an underlying network transport. */ public interface Transport { /** * Read data from the transport into the given buffers. * NOTE: Works like ScatteringByteChannel. * @param buffers into which bytes are to be placed * @param array_offset offset within the buffer array of the first buffer into which bytes are to be placed * @param length maximum number of buffers to be accessed * @return number of bytes read * @throws IOException on read error */ public long read( ByteBuffer[] buffers, int array_offset, int length ) throws IOException; /** * Write data to the transport from the given buffers. * NOTE: Works like GatheringByteChannel. * @param buffers from which bytes are to be retrieved * @param array_offset offset within the buffer array of the first buffer from which bytes are to be retrieved * @param length maximum number of buffers to be accessed * @return number of bytes written * @throws IOException on write error */ public long write( ByteBuffer[] buffers, int array_offset, int length ) throws IOException; /** * @since 3.0.5.3 */ public void setFilter(TransportFilter filter) throws IOException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/network/TransportException.java0000644000175000017500000000306511017134546026053 0ustar adrianadrian/* * Created on 17 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.network; /** * @since 3.0.5.3 */ public class TransportException extends Exception { /** * */ public TransportException() { // TODO Auto-generated constructor stub } /** * @param arg0 */ public TransportException(String arg0) { super(arg0); // TODO Auto-generated constructor stub } /** * @param arg0 */ public TransportException(Throwable arg0) { super(arg0); // TODO Auto-generated constructor stub } /** * @param arg0 * @param arg1 */ public TransportException(String arg0, Throwable arg1) { super(arg0, arg1); // TODO Auto-generated constructor stub } } azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginManagerArgumentHandler.java0000644000175000017500000000210610373051030026222 0ustar adrianadrian/* * Created on 12-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins; public interface PluginManagerArgumentHandler { public void processArguments( String[] args ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/0000755000175000017500000000000011310377616021620 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/MessageManagerListener.java0000644000175000017500000000321710373051040027037 0ustar adrianadrian/* * Created on Feb 26, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.peers.Peer; /** * Listener for message manager events. */ public interface MessageManagerListener { /** * Notify of new peer connection that supports the given message type. * @param download containing the peer * @param peer that supports the message type * @param message that is supported */ public void compatiblePeerFound( Download download, Peer peer, Message message ); /** * Notify of peer connection removal. * @param download that contained the peer * @param peer that was dropped */ public void peerRemoved( Download download, Peer peer ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/MessageStreamEncoder.java0000644000175000017500000000254110373051040026511 0ustar adrianadrian/* * Created on Feb 9, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging; import org.gudy.azureus2.plugins.network.RawMessage; /** * Encodes messages into a raw message stream format for sending. */ public interface MessageStreamEncoder { /** * Encode the given message into the raw message output stream format. * @param message to encode * @return raw message encoding */ public RawMessage encodeMessage( Message message ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/bittorrent/0000755000175000017500000000000011310377634024014 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessagePiece.java0000644000175000017500000000333210373051050027425 0ustar adrianadrian/* * Created on Feb 28, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging.bittorrent; import java.nio.ByteBuffer; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.pluginsimpl.local.messaging.MessageAdapter; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTPiece; /** * */ public class BTMessagePiece extends MessageAdapter { private final BTPiece piece; protected BTMessagePiece( com.aelitis.azureus.core.peermanager.messaging.Message core_msg ) { super( core_msg ); piece = (BTPiece)core_msg; } public int getPieceNumber() { return piece.getPieceNumber(); } public int getPieceOffset() { return piece.getPieceOffset(); } public ByteBuffer getPieceData() { return piece.getPieceData().getBuffer( DirectByteBuffer.SS_EXTERNAL ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageCancel.java0000644000175000017500000000313110373051050027562 0ustar adrianadrian/* * Created on Feb 28, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging.bittorrent; import org.gudy.azureus2.pluginsimpl.local.messaging.MessageAdapter; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTCancel; /** * */ public class BTMessageCancel extends MessageAdapter { private final BTCancel cancel; protected BTMessageCancel( com.aelitis.azureus.core.peermanager.messaging.Message core_msg ) { super( core_msg ); cancel = (BTCancel)core_msg; } public int getPieceNumber() { return cancel.getPieceNumber(); } public int getPieceOffset() { return cancel.getPieceOffset(); } public int getLength() { return cancel.getLength(); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageRequest.java0000644000175000017500000000314310373051050030030 0ustar adrianadrian/* * Created on Feb 28, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging.bittorrent; import org.gudy.azureus2.pluginsimpl.local.messaging.MessageAdapter; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTRequest; /** * */ public class BTMessageRequest extends MessageAdapter { private final BTRequest request; protected BTMessageRequest( com.aelitis.azureus.core.peermanager.messaging.Message core_msg ) { super( core_msg ); request = (BTRequest)core_msg; } public int getPieceNumber() { return request.getPieceNumber(); } public int getPieceOffset() { return request.getPieceOffset(); } public int getLength() { return request.getLength(); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageManager.java0000644000175000017500000001141410572775042027771 0ustar adrianadrian/* * Created on Feb 28, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging.bittorrent; import java.nio.ByteBuffer; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.plugins.messaging.*; import org.gudy.azureus2.pluginsimpl.local.messaging.MessageAdapter; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTCancel; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTMessage; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTPiece; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTRequest; /** * */ public class BTMessageManager { public static final String ID_BTMESSAGE_REQUEST = BTMessage.ID_BT_REQUEST; public static final String ID_BTMESSAGE_CANCEL = BTMessage.ID_BT_CANCEL; public static final String ID_BTMESSAGE_PIECE = BTMessage.ID_BT_PIECE; public static final String ID_BTMESSAGE_UNCHOKE = BTMessage.ID_BT_UNCHOKE; /** * Translate the given core-made BT Request message into a specific plugin message adaptation. * @param core_made_message to translate * @return adapted plugin message */ public static BTMessageRequest createCoreBTRequestAdaptation( Message core_made_message ) { //the message was originally created by core and wrapped com.aelitis.azureus.core.peermanager.messaging.Message core_msg = ((MessageAdapter)core_made_message).getCoreMessage(); if( core_msg.getID().equals( BTMessage.ID_BT_REQUEST ) ) { return new BTMessageRequest( core_msg ); } return null; } /** * Translate the given core-made BT Cancel message into a specific plugin message adaptation. * @param core_made_message to translate * @return adapted plugin message */ public static BTMessageCancel createCoreBTCancelAdaptation( Message core_made_message ) { //the message was originally created by core and wrapped com.aelitis.azureus.core.peermanager.messaging.Message core_msg = ((MessageAdapter)core_made_message).getCoreMessage(); if( core_msg.getID().equals( BTMessage.ID_BT_CANCEL ) ) { return new BTMessageCancel( core_msg ); } return null; } /** * Translate the given core-made BT Piece message into a specific plugin message adaptation. * @param core_made_message to translate * @return adapted plugin message */ public static BTMessagePiece createCoreBTPieceAdaptation( Message core_made_message ) { //the message was originally created by core and wrapped com.aelitis.azureus.core.peermanager.messaging.Message core_msg = ((MessageAdapter)core_made_message).getCoreMessage(); if( core_msg.getID().equals( BTMessage.ID_BT_PIECE ) ) { return new BTMessagePiece( core_msg ); } return null; } /** * Create a core BT Request message instance. * @param piece_number * @param piece_offset * @param length * @return core message wrapped in an adapter */ public static Message createCoreBTRequest( int piece_number, int piece_offset, int length ) { return new MessageAdapter( new BTRequest( piece_number, piece_offset, length, (byte)1 ) ); } /** * Create a core BT Cancel message instance. * @param piece_number * @param piece_offset * @param length * @return core message wrapped in an adapter */ public static Message createCoreBTCancel( int piece_number, int piece_offset, int length ) { return new MessageAdapter( new BTCancel( piece_number, piece_offset, length, (byte)1 ) ); } /** * Create a core BT Piece message instance. * @param piece_number * @param piece_offset * @param data * @return core message wrapped in an adapter */ public static Message createCoreBTPiece( int piece_number, int piece_offset, ByteBuffer data ) { return new MessageAdapter( new BTPiece( piece_number, piece_offset, new DirectByteBuffer( data ), (byte)1 ) ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/MessageManager.java0000644000175000017500000000563410446261566025357 0ustar adrianadrian/* * Created on Feb 24, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.messaging.generic.GenericMessageHandler; import org.gudy.azureus2.plugins.messaging.generic.GenericMessageRegistration; /** * Manages peer message handling. */ public interface MessageManager { public static final int STREAM_ENCRYPTION_NONE = 1; public static final int STREAM_ENCRYPTION_RC4_PREFERRED = 2; public static final int STREAM_ENCRYPTION_RC4_REQUIRED = 3; /** * Register the given message type with the manager for processing. * NOTE: A message type needs to be registered in order for support to be * advertised to other peers. * @param message instance to use for decoding * @throws MessageException if this message type has already been registered */ public void registerMessageType( Message message ) throws MessageException; /** * Remove registration of given message type from manager. * @param message type to remove */ public void deregisterMessageType( Message message ); /** * Globally register for notification of peers that support the given message type. * @param plug_interface to get the download manager * @param message to match * @param listener to notify */ public void locateCompatiblePeers( PluginInterface plug_interface, Message message, MessageManagerListener listener ); /** * Cancel registration for compatible-peer notification. * @param orig_listener listener used for registration */ public void cancelCompatiblePeersLocation( MessageManagerListener orig_listener ); /** * Register a peer-independent message handler * @param type * @param description * @param handler * @return * @throws MessageException */ public GenericMessageRegistration registerGenericMessageType( String type, String description, int stream_encryption, GenericMessageHandler handler ) throws MessageException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/Message.java0000644000175000017500000000427310373051040024041 0ustar adrianadrian/* * Created on Feb 9, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging; import java.nio.ByteBuffer; /** * Basic peer message. * A message is uniquely identified by the combination of ID and version. */ public interface Message { /** * Is a protocol-bearing message, i.e. messaging/overhead data. */ public static final int TYPE_PROTOCOL_PAYLOAD = 0; /** * Is a data-bearing message, i.e. file data. */ public static final int TYPE_DATA_PAYLOAD = 1; /** * Get message id. * @return id */ public String getID(); /** * Get message type. * @return type */ public int getType(); /** * Get textual description of this particular message. * @return description */ public String getDescription(); /** * Get message payload data. * @return message data buffers */ public ByteBuffer[] getPayload(); /** * Create a new instance of this message by decoding the given byte serialization. * @param data to deserialize * @return decoded message instance * @throws MessageException if the decoding process fails */ public Message create( ByteBuffer data ) throws MessageException; /** * Destroy the message; i.e. perform cleanup actions. */ public void destroy(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/generic/0000755000175000017500000000000011310377616023234 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/generic/GenericMessageConnectionListener.java0000644000175000017500000000271410446016634032511 0ustar adrianadrian/* * Created on 19 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging.generic; import org.gudy.azureus2.plugins.messaging.MessageException; import org.gudy.azureus2.plugins.utils.PooledByteBuffer; public interface GenericMessageConnectionListener { public void connected( GenericMessageConnection connection ); public void receive( GenericMessageConnection connection, PooledByteBuffer message ) throws MessageException; public void failed( GenericMessageConnection connection, Throwable error ) throws MessageException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/generic/GenericMessageEndpoint.java0000644000175000017500000000244710446567432030476 0ustar adrianadrian/* * Created on 19 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging.generic; import java.net.InetSocketAddress; public interface GenericMessageEndpoint { public InetSocketAddress getNotionalAddress(); public void addTCP( InetSocketAddress target ); public InetSocketAddress getTCP(); public void addUDP( InetSocketAddress target ); public InetSocketAddress getUDP(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/generic/GenericMessageRegistration.java0000644000175000017500000000255010446016634031354 0ustar adrianadrian/* * Created on 19 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging.generic; import java.net.InetSocketAddress; import org.gudy.azureus2.plugins.messaging.MessageException; public interface GenericMessageRegistration { public GenericMessageEndpoint createEndpoint( InetSocketAddress notional_target ); public GenericMessageConnection createConnection( GenericMessageEndpoint endpoint ) throws MessageException; public void cancel(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/generic/GenericMessageConnection.java0000644000175000017500000000414711031023514030767 0ustar adrianadrian/* * Created on 19 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging.generic; import org.gudy.azureus2.plugins.messaging.MessageException; import org.gudy.azureus2.plugins.network.RateLimiter; import org.gudy.azureus2.plugins.utils.PooledByteBuffer; public interface GenericMessageConnection { public static final int TT_NONE = 0; public static final int TT_TCP = 0; public static final int TT_UDP = 0; public static final int TT_INDIRECT = 0; public GenericMessageEndpoint getEndpoint(); public void connect() throws MessageException; public void send( PooledByteBuffer message ) throws MessageException; public void close() throws MessageException; public int getMaximumMessageSize(); public String getType(); public int getTransportType(); public void addInboundRateLimiter( RateLimiter limiter ); public void removeInboundRateLimiter( RateLimiter limiter ); public void addOutboundRateLimiter( RateLimiter limiter ); public void removeOutboundRateLimiter( RateLimiter limiter ); public void addListener( GenericMessageConnectionListener listener ); public void removeListener( GenericMessageConnectionListener listener ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/generic/GenericMessageHandler.java0000644000175000017500000000226310446016634030260 0ustar adrianadrian/* * Created on 19 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging.generic; import org.gudy.azureus2.plugins.messaging.MessageException; public interface GenericMessageHandler { public boolean accept( GenericMessageConnection connection ) throws MessageException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/MessageException.java0000644000175000017500000000230111012741710025707 0ustar adrianadrian/* * Created on Jan 8, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging; /** * */ public class MessageException extends Exception { public MessageException( String reason ) { super( reason ); } public MessageException( String reason, Throwable e ){ super( reason,e ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/messaging/MessageStreamDecoder.java0000644000175000017500000000465410373051040026506 0ustar adrianadrian/* * Created on Feb 11, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.messaging; import java.io.IOException; import java.nio.ByteBuffer; import org.gudy.azureus2.plugins.network.Transport; /** * Decodes a message stream into separate messages. */ public interface MessageStreamDecoder { /** * Decode message stream from the given transport. * @param transport to decode from * @param max_bytes to decode/read from the stream * @return number of bytes decoded * @throws IOException on decoding error */ public int performStreamDecode( Transport transport, int max_bytes ) throws IOException; /** * Get the messages decoded from the transport, if any, from the last decode op. * @return decoded messages, or null if no new complete messages were decoded */ public Message[] removeDecodedMessages(); /** * Get the number of protocol (overhead) bytes decoded from the transport, from the last decode op. * @return number of protocol bytes recevied */ public int getProtocolBytesDecoded(); /** * Get the number of (piece) data bytes decoded from the transport, from the last decode op. * @return number of data bytes received */ public int getDataBytesDecoded(); /** * Pause message decoding. */ public void pauseDecoding(); /** * Resume message decoding. */ public void resumeDecoding(); /** * Destroy this decoder, i.e. perform cleanup. * @return any bytes already-read and still remaining within the decoder */ public ByteBuffer destroy(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginState.java0000644000175000017500000000577511276652172022767 0ustar adrianadrian/** * File: PluginState.java * Date: 19 Aug 2008 * Author: Allan Crooks * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the COPYING file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins; /** * This object provides information the current state of the plugin, and * provides various mechanisms to query and control plugins and their integration * with Azureus at a low-level. * * Most plugins will have no need to interact with this object - it is primarily * used by Azureus for plugin management. * * @since 3.1.1.1 */ public interface PluginState { /** * Returns true if the plugin is set to load at startup, false otherwise. */ public boolean isLoadedAtStartup(); /** * Sets whether the plugin is loaded at startup or not. */ public void setLoadedAtStartup(boolean load_at_startup); /** * Returns true if there was a problem loading or initialising the plugin. */ public boolean hasFailed(); /** * Returns true if the plugin has been marked as disabled, and prevented * from initialising. */ public boolean isDisabled(); /** * Sets whether the plugin can be loaded or not. If you are trying to affect if the plugin * can be loaded at startup - use {@link #setLoadedAtStartup(boolean)} instead. This needs * to be called prior to a plugin's initialisation to take effect. * * @param disabled */ public void setDisabled(boolean disabled); /** * Built-in plugins are those used internally by Azureus, for example * the UPnP plugin. */ public boolean isBuiltIn(); /** * Whether or not this is a mandatory plugin. Mandatory plugins take priority over update checks, for example, * over optional ones. */ public boolean isMandatory(); /** * Returns true if the plugin is running, returns false if the * plugin isn't running for some reason. */ public boolean isOperational(); /** * Uninstall this plugin if it has been loaded from a plugin directory. * Deletes the plugin directory. */ public void uninstall() throws PluginException; public boolean isShared(); public boolean isUnloadable(); public boolean isUnloaded(); public void unload() throws PluginException; public void reload() throws PluginException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/0000755000175000017500000000000011310377634020260 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/0000755000175000017500000000000011310377634021525 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/ParameterListener.java0000644000175000017500000000215010373051014026001 0ustar adrianadrian/* * Created on 02-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.config; /** * @author parg * */ public interface ParameterListener { public void parameterChanged( Parameter param ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/FileParameter.java0000644000175000017500000000213410530472122025077 0ustar adrianadrian/* * Created on 20-Nov-2006 * Created by Allan Crooks * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.config; /** * @since 2.5.0.1 */ public interface FileParameter extends Parameter { public String getValue(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/HyperlinkParameter.java0000644000175000017500000000035310537152060026171 0ustar adrianadrian/** * */ package org.gudy.azureus2.plugins.ui.config; /** * @author Allan Crooks * */ public interface HyperlinkParameter extends LabelParameter { public void setHyperlink(String url_location); public String getHyperlink(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/EnablerParameter.java0000644000175000017500000000277407762276526025631 0ustar adrianadrian/* * File : EnablerParameter.java * Created : 30 nov. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.config; /** * represents a parameter that is able to enable/disable other parameters.
* @author Olivier * */ public interface EnablerParameter extends Parameter { /** * enables parameter when EnablerParameter is selected.
* parameter is disabled is EnablerParameter isn't selected. * @param parameter the Parameter to act on */ public void addEnabledOnSelection(Parameter parameter); /** * disables parameter when EnablerParameter is selected.
* parameter is enabled is EnablerParameter isn't selected. * @param parameter the Parameter to act on */ public void addDisabledOnSelection(Parameter parameter); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/BooleanParameter.java0000644000175000017500000000222110373051014025572 0ustar adrianadrian/* * Created on 02-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.config; /** * @author parg * */ public interface BooleanParameter extends EnablerParameter { public boolean getValue(); public void setValue( boolean b ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/PluginConfigUIFactory.java0000644000175000017500000001464510020423274026541 0ustar adrianadrian/* * File : PluginConfigUIFactory.java * Created : 17 nov. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.config; /** Functions to create various plugin UI Config Parameters.

* * The label parameter passed to these functions is a lookup name. * The UI label's text will be assigned the value looked up in the language file * using the label parameter as the key name. *

* If you wish your configuration option to be displaying in console mode, * add the following to your key:

 * _b      Boolean Value
 * _i      Integer Value
 * _s      String Value
 * 
the above tags must be added before any other "_" characters. * * @see org.gudy.azureus2.plugins.PluginInterface#addConfigUIParameters PluginInterface.addConfigUIParameters * * @author Olivier * */ public interface PluginConfigUIFactory { /** * Creates a boolean parameter.
* The UI component used will be a checkBox.
* The parameter can be accessed using the PluginConfig.getPluginBooleanParameter(String key).
* The return object, and EnablerParameter, can be used to add dependency to other parameters. * For example, you can use a boolean parameter to choose from logging or not, and a file parameter * to choose the logging file. You can call the EnablerParameter.addEnabledOnSelection method with the * file Parameter in argument, so that the file parameter will only be enabled if the 'logging' (boolean) one is. * @param key the parameter key * @param label the label for this checkBox (cf. i18n) * @param defaultValue the default value of the parameter * @return an EnablerParameter */ public EnablerParameter createBooleanParameter( String key, String label, boolean defaultValue); /** * Creates an int parameter.
* The UI component will be a Text field, but only accepting int values.
* The parameter can be accessed using the PluginConfig.getPluginIntParameter(String key).
* @param key the parameter key * @param label the label for this field (cf. i18n) * @param defaultValue the default value of the parameter * @return a Parameter */ public Parameter createIntParameter( String key, String label, int defaultValue); /** * Creates an int parameter.
* The UI component will be a List.
* The parameter can be accessed using the PluginConfig.getPluginIntParameter(String key).
* @param key the parameter key * @param label the label for this field (cf. i18n) * @param defaultValue the default value of the parameter * @param values the list of values * @param labels the list of labels (no i18n here) * @return a Parameter */ public Parameter createIntParameter( String key, String label, int defaultValue, int[] values, String labels[]); /** * Creates a String parameter.
* The UI Component will be a Text field.
* The parameter can be accessed using the PluginConfig.getPluginStringParameter(String key).
* @param key the parameter key * @param label the label for this field (cf. i18n) * @param defaultValue the default value of the parameter * @return a Parameter */ public Parameter createStringParameter( String key, String label, String defaultValue); /** * Creates an String parameter.
* The UI component will be a List.
* The parameter can be accessed using the PluginConfig.getPluginStringParameter(String key).
* @param key the parameter key * @param label The label for this field (cf. i18n) * @param defaultValue the default value of the parameter * @param values the list of values * @param labels the list of labels (no i18n here) * @return a Parameter */ public Parameter createStringParameter( String key, String label, String defaultValue, String[] values, String labels[]); /** * Creates a File Parameter.
* The UI component will be a Text field with a browse button.
* The parameter can be accessed using the PluginConfig.getPluginStringParameter(String key).
* @param key the parameter key * @param label the label for this field (cf. i18n) * @param defaultValue the default value of the parameter * @return a File Parameter */ public Parameter createFileParameter( String key, String label, String defaultValue); /** * Creates a Directory Parameter.
* The UI component will be a Text field with a browse button.
* The parameter can be accessed using the PluginConfig.getPluginStringParameter(String key).
* @param key the parameter key * @param label the label for this field (cf. i18n) * @param defaultValue the default value of the parameter * @return a File Parameter */ public Parameter createDirectoryParameter( String key, String label, String defaultValue); /** * Creates a Color Parameter.
* The UI component will be a button with a Color area.
* The parameter is in fact separacted in 3 parameters:
* key.red
* key.green
* key.blue
* Each color component is stored as an int parameter and can be accessed using PluginConfig.getPluginIntParameter(String key.(red|green|blue)).
* @param key the parameter key * @param label the label for this field (cf. i18n) * @param defaultValueRed the red component of the default color (0-255) * @param defaultValueGreen the green component of the default color (0-255) * @param defaultValueBlue the blue component of the default color (0-255) * @return a Color Parameter */ public Parameter createColorParameter( String key, String label, int defaultValueRed, int defaultValueGreen, int defaultValueBlue); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/DirectoryParameter.java0000644000175000017500000000221511173215444026172 0ustar adrianadrian/* * Created on 08-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.config; /** * @author parg * */ public interface DirectoryParameter extends Parameter { public void setValue( String str ); public String getValue(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/ConfigSection.java0000644000175000017500000000501410361321162025110 0ustar adrianadrian/* * File : ConfigSection.java * Created : 23 jan. 2004 * By : Paper * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.config; /** * Base class for adding "ConfigSection"s.

* This class does nothing. Extend the subinterfaces to add a section to a * particular type of view (currently only SWT is supported). */ public interface ConfigSection { /** * Configuration panel will be added to main configuration view area */ public static final String SECTION_ROOT = "root"; /** * Configuration panel will be added to the plugins view area. */ public static final String SECTION_PLUGINS = "plugins"; public static final String SECTION_TRACKER = "tracker"; public static final String SECTION_FILES = "files"; public static final String SECTION_INTERFACE = "style"; public static final String SECTION_CONNECTION = "server"; public static final String SECTION_TRANSFER = "transfer"; /** * Returns section you want your configuration panel to be under. * See SECTION_* constants. To add a subsection to your own ConfigSection, * return the configSectionGetName result of your parent.
*/ public String configSectionGetParentSection(); /** * In order for the plugin to display its section correctly, a key in the * Plugin language file will need to contain * ConfigView.section.<configSectionGetName() result>=The Section name.
* * @return The name of the configuration section */ public String configSectionGetName(); /** * User selected Save. * All saving of non-plugin tabs have been completed, as well as * saving of plugins that implement org.gudy.azureus2.plugins.ui.config * parameters. */ public void configSectionSave(); /** * Config view is closing */ public void configSectionDelete(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/ConfigSectionSWT.java0000644000175000017500000000277610311061442025517 0ustar adrianadrian/* * File : ConfigSection.java * Created : 23 jan. 2004 * By : Paper * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.config; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.plugins.ui.config.ConfigSection; /** * Extend this class to add a new configuration panel to the SWT config view. * * @deprecated use {@link org.gudy.azureus2.ui.swt.plugins.UISWTInstance} */ public interface ConfigSectionSWT extends ConfigSection { /** * Create your own configuration panel here. It can be anything that inherits * from SWT's Composite class. * Please be mindfull of small screen resolutions * * @param parent The parent of your configuration panel * @return your configuration panel */ public Composite configSectionCreate(Composite parent); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/Parameter.java0000644000175000017500000000775511017415470024321 0ustar adrianadrian/* * File : Parameter.java * Created : 30 nov. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.config; import org.gudy.azureus2.plugins.config.ConfigParameter; /** * represents a generic parameter description * @author Olivier * */ public interface Parameter extends ConfigParameter { public static final int MODE_BEGINNER = 0; public static final int MODE_INTERMEDIATE = 1; public static final int MODE_ADVANCED = 2; /** * Sets whether the UI object for this parameter is enabled (changeable) or * disabled (not changeable, and usually grayed out) * * @param enabled The new enabled state * * @since 2.3.0.0 */ public void setEnabled( boolean enabled ); /** * Retrieves the enabled state for the UI object for this parameter * * @return The enabled state * * @since 2.3.0.0 */ public boolean isEnabled(); /** * Gets the lowest user mode required for this parameter to be displayed. * * @return MODE_ constants above * @since 3.0.5.3 */ public int getMinimumRequiredUserMode(); /** * Sets the lowest user mode required for this parameter to be displayed. * * @param mode see MODE_ constants defined above * @since 3.0.5.3 */ public void setMinimumRequiredUserMode( int mode ); /** * Sets whether the UI object for this parameter is visible to the user * * @param visible The new visibility state * * @since 2.3.0.4 */ public void setVisible( boolean visible ); /** * Retrieves the visiblility state for the UI object for this parameter * * @return The visibility state * * @since 2.3.0.4 */ public boolean isVisible(); /** * Controls whether or not 'parameter change' events are fired for each incremental value change * @param b * * @since 3.0.5.1 */ public void setGenerateIntermediateEvents( boolean b ); /** * * @return * * @since 3.0.5.1 */ public boolean getGenerateIntermediateEvents(); /** * Adds a listener triggered when the parameter is changed by the user * * @param l Listener to add * * @since 2.1.0.2 */ public void addListener( ParameterListener l ); /** * Removes a previously added listener * * @param l Listener to remove. * * @since 2.1.0.2 */ public void removeListener( ParameterListener l ); /** * Retrieve the actual text of the label associated with this parameter. * This is the text after it has been looked up in the language bundle. * * @return The label's text * * @since 2.3.0.6 */ public String getLabelText(); /** * Set the text of the label associated to with this parameter to the literal * text supplied. * * @param sText The actual text to assign to the label * * @since 2.3.0.6 */ public void setLabelText(String sText); /** * Retrieve the language bundle key for the label associated with this * parameter. * * @return The language bundle key, or null if the label is using literal * text * * @since 2.3.0.6 */ public String getLabelKey(); /** * Set the label to use the supplied language bundle key for the label * associated with this parameter * * @param sLabelKey The language bundle key to use. * * @since 2.3.0.6 */ public void setLabelKey(String sLabelKey); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/StringListParameter.java0000644000175000017500000000227611030342714026330 0ustar adrianadrian/* * Created on 10-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.config; /** * @author parg * */ public interface StringListParameter extends Parameter { public void setValue( String value ); public String getValue(); public void setLabels( String[] labels ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/ParameterGroup.java0000644000175000017500000000206110373051014025311 0ustar adrianadrian/* * Created on 10-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.config; /** * @author parg * */ public interface ParameterGroup { } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/PasswordParameter.java0000644000175000017500000000251410373051014026022 0ustar adrianadrian/* * Created on 10-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.config; /** * @author parg * */ public interface PasswordParameter extends Parameter { public static final int ET_PLAIN = 1; public static final int ET_SHA1 = 2; public static final int ET_MD5 = 3; // note that even for encoded parameters, an empty value ("") will be returned // as "" (not an encoded "") public byte[] getValue(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/ActionParameter.java0000644000175000017500000000233710373051014025440 0ustar adrianadrian/* * Created on 17-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.config; /** * @author parg * */ public interface ActionParameter extends Parameter { public static final int STYLE_BUTTON = 1; public static final int STYLE_LINK = 2; public void setStyle( int style ); public int getStyle(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/ColorParameter.java0000644000175000017500000000227210714505102025300 0ustar adrianadrian/* * Created on 23 Oct 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ui.config; /** * @author Allan Crooks * */ public interface ColorParameter extends Parameter { public int getRedValue(); public int getGreenValue(); public int getBlueValue(); public void setRGBValue(int r, int g, int b); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/InfoParameter.java0000644000175000017500000000221111135305412025106 0ustar adrianadrian/* * Created on 04-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.config; /** * @author parg * */ public interface InfoParameter extends Parameter { public String getValue(); public void setValue( String str ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/LabelParameter.java0000644000175000017500000000210310373051014025231 0ustar adrianadrian/* * Created on 04-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.config; /** * @author parg * */ public interface LabelParameter extends Parameter { } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/IntParameter.java0000644000175000017500000000217610373051014024756 0ustar adrianadrian/* * Created on 02-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.config; /** * @author parg * */ public interface IntParameter extends Parameter { public int getValue(); public void setValue( int v ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/UIParameter.java0000644000175000017500000000240211017134464024540 0ustar adrianadrian/* * Created on 25 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ui.config; /** * This parameter represents a native UI object to be displayed in a configuration * section. * *

Note: Only for implementation by Azureus, not plugins.

* * @since 3.0.5.3 */ public interface UIParameter extends Parameter { public UIParameterContext getContext(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/UIParameterContext.java0000644000175000017500000000275511017134464026120 0ustar adrianadrian/* * Created on 25 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ui.config; /** * Any class implementing this interface represent an object which is to be used * to generate a {@link UIParameter} object. Any plugin wishing to implement this * interface shouldn't implement it directly - it will need to implement a * sub-interface which defines methods directly related to the user interface * you want to integrate with. * *

Note: This interface is intended to be implemented by plugins.

* * @author Allan Crooks * @since 3.0.5.3 */ public interface UIParameterContext { } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/config/StringParameter.java0000644000175000017500000000221310373051014025462 0ustar adrianadrian/* * Created on 02-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.config; /** * @author parg * */ public interface StringParameter extends Parameter { public void setValue( String value ); public String getValue(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIInstance.java0000644000175000017500000000467411017134544023133 0ustar adrianadrian/* * Created on 05-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui; /** * This interface represents a UI running on the core (e.g. the SWT UI). * The actual implementation of this will support UI-specific operations - * you need to cast this to the appropriate type to access them. * * This is to allow "native" UI plugin access - for example a plugin that * directly accesses SWT functionality would do it via this object (it'll be * an instance of org.gudy.azureus2.ui.swt.plugins.UISWTInstance ) */ public interface UIInstance { /** * Prompts the user with a title, text, and a series of options. The options * are typically displayed as buttons. * * @param title * @param text * @param options * @return Index of option chosen, -1 if cancelled or error */ public int promptUser(String title, String text, String[] options, int defaultOption); /** * Creates a {@link UIInputReceiver} instance to allow a plugin to request * text input from the user. Some interfaces may not allow or support the * ability for a plugin to request text input from a user, in which case * they will return null for this method. */ public UIInputReceiver getInputReceiver(); /** * Creates a {@link UIMessage} instance to allow a plugin to inform or ask the * user something. Some interfaces may not allow or support the * ability for a plugin to ask a user in this manner, in which case * they will return null for this method. * * @since 3.0.5.3 */ public UIMessage createMessage(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/model/0000755000175000017500000000000011310377616021360 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/ui/model/BasicPluginConfigModel.java0000644000175000017500000001501511135305412026522 0ustar adrianadrian/* * Created on 28-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.model; import org.gudy.azureus2.plugins.ui.config.*; import org.gudy.azureus2.plugins.ui.config.FileParameter; /** * This object represents a configuration section. * *

* * If you specify "_blank" as a resource name (the label for the parameter), * (or use the {@link #BLANK_RESOURCE} constant defined here), then this will * be a blank label (available since 3.0.5.3). */ public interface BasicPluginConfigModel extends PluginConfigModel { /** * @since 3.0.5.3 */ public String BLANK_RESOURCE = "_blank"; /** * @deprecated use addBooleanParameter2 * @param key * @param resource_name * @param defaultValue * @return * * @since 2.1.0.0 */ public void addBooleanParameter( String key, String resource_name, boolean defaultValue ); /** * @deprecated user addStringParameter2 * @param key * @param resource_name * @param defaultValue * @return * * @since 2.1.0.0 */ public void addStringParameter( String key, String resource_name, String defaultValue ); /** * * @param key * @param resource_name * @param defaultValue * @return * * @since 2.1.0.2 */ public BooleanParameter addBooleanParameter2( String key, String resource_name, boolean defaultValue ); /** * * @param key * @param resource_name * @param defaultValue * @return * @since 2.1.0.2 */ public StringParameter addStringParameter2( String key, String resource_name, String defaultValue ); /** * * @param key * @param resource_name * @param values * @param defaultValue * @return * @since 2.1.0.2 */ public StringListParameter addStringListParameter2( String key, String resource_name, String[] values, String defaultValue ); /** * * @param key * @param resource_name * @param values * @param labels A list of localised message strings corresponding to each value. * @param defaultValue * @return * @since 2.3.0.6 */ public StringListParameter addStringListParameter2( String key, String resource_name, String[] values, String[] labels, String defaultValue ); /** * * @param key * @param resource_name * @param encoding_type * @param defaultValue * @return * @since 2.1.0.2 */ public PasswordParameter addPasswordParameter2( String key, String resource_name, int encoding_type, // see PasswordParameter.ET_ constants byte[] defaultValue ); // plain default value /** * * @param key * @param resource_name * @param defaultValue * @return * @since 2.1.0.2 */ public IntParameter addIntParameter2( String key, String resource_name, int defaultValue ); /** * * @param key * @param resource_name * @param defaultValue * @param min_value Minimum allowed value * @param max_value Maximum allowed value * @return * @since 3.0.3.5 */ public IntParameter addIntParameter2( String key, String resource_name, int defaultValue, int min_value, int max_value); /** * * @param resource_name * @return * @since 2.1.0.2 */ public LabelParameter addLabelParameter2( String resource_name ); /** * @since 4005 * @param resource_name * @param value * @return */ public InfoParameter addInfoParameter2( String resource_name, String value ); /** * @since 2.5.0.2 */ public HyperlinkParameter addHyperlinkParameter2(String resource_name, String url_location); /** * * @param key * @param resource_name * @param defaultValue * @return * @since 2.1.0.2 */ public DirectoryParameter addDirectoryParameter2( String key, String resource_name, String defaultValue ); /** * * @param key * @param resource_name * @param defaultValue * @return * @since 2.5.0.1 */ public FileParameter addFileParameter2( String key, String resource_name, String defaultValue ); /** * * @param key * @param resource_name * @param defaultValue * @param file_extensions Allowed list of file extensions. * @return * @since 2.5.0.1 */ public FileParameter addFileParameter2( String key, String resource_name, String defaultValue, String[] file_extensions); /** * * @param label_resource_name * @param action_resource_name * @return * @since 2.1.0.2 */ public ActionParameter addActionParameter2( String label_resource_name, String action_resource_name ); /** * @since 3.0.3.5 * @param key * @param resource_name * @param r * @param g * @param b * @return */ public ColorParameter addColorParameter2(String key, String resource_name, int r, int g, int b); /** * Creates a {@link UIParameter} object to add to this config model object. * * @since 3.0.5.3 */ public UIParameter addUIParameter2(UIParameterContext context, String name); /** * * @param resource_name * @param parameters * @return * @since 2.3.0.0 */ public ParameterGroup createGroup( String resource_name, Parameter[] parameters ); /** * * @return * @since 2.3.0.5 */ public String getSection(); /** * * @return * @since 2.3.0.5 */ public String getParentSection(); /** * Retrieve all the parameters added to this plugin config * * @return parameter list * @since 2.3.0.5 */ public Parameter[] getParameters(); /** * Sets the name of the configuration model - this is useful in * situations where the configuration section is being dynamically * created (perhaps with user input). * * @since 3.0.5.3 */ public void setLocalizedName(String name); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/model/PluginViewModel.java0000644000175000017500000000214510373051032025264 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.model; /** * @author parg * */ public interface PluginViewModel { public String getName(); public void destroy(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/model/PluginConfigModel.java0000644000175000017500000000225610373051032025562 0ustar adrianadrian/* * Created on 28-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.model; import org.gudy.azureus2.plugins.PluginInterface; /** * @author parg * */ public interface PluginConfigModel { public PluginInterface getPluginInterface(); public void destroy(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/model/BasicPluginViewModel.java0000644000175000017500000000421011017134464026230 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.model; import org.gudy.azureus2.plugins.logging.*; /** * @author parg * *

Note: Only for implementation by Azureus, not plugins.

*/ import org.gudy.azureus2.plugins.ui.components.*; public interface BasicPluginViewModel extends PluginViewModel { /** * All UI Components are initially enabled - disable if not required * @return */ public UITextField getStatus(); public UITextField getActivity(); public UITextArea getLogArea(); public UIProgressBar getProgress(); /** * * @param id * * @since 2.3.0.7 */ public void setConfigSectionID(String id); /** * * @return * * @since 2.3.0.7 */ public String getConfigSectionID(); /** * Convenience method to configure this model to receive any logged * messages on the associated channel and display it in the main * window area. * *

* * You can handle this manually if you want to, by creating your own * {@link LoggerChannelListener} instance and making it append to the * log area on this object. * * @since 3.0.5.3 * @param channel The log channel to listen to. */ public void attachLoggerChannel(LoggerChannel channel); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIException.java0000644000175000017500000000227411012741706023316 0ustar adrianadrian/* * Created on 19-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui; /** * @author parg * */ public class UIException extends Exception { public UIException( String str ) { super(str); } public UIException( String str, Throwable c ) { super(str, c); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/components/0000755000175000017500000000000011310377616022445 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/ui/components/UIProgressBar.java0000644000175000017500000000243510373051034025772 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.components; /** * @author parg * */ public interface UIProgressBar extends UIComponent { /** * Setting values results in a PT_VALUE property change with an Integer value * @param precentage */ public void setPercentageComplete( int percentage ); public int getPercentageComplete(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/components/UITextField.java0000644000175000017500000000237210373051034025431 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.components; /** * @author parg * */ public interface UITextField extends UIComponent { /** * Setting values results in a PT_VALUE property change with a String value * @param precentage */ public void setText( String text ); public String getText(); }azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/components/UIComponent.java0000644000175000017500000000331510373051034025501 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.components; /** * @author parg * */ public interface UIComponent { public static final String PT_ENABLED = "enabled"; // Boolean public static final String PT_VALUE = "value"; // Depends on component type public static final String PT_VISIBLE = "visible"; // Boolean public void setEnabled( boolean enabled ); public boolean getEnabled(); public void setVisible( boolean visible ); public boolean getVisible(); public void setProperty( String property_type, Object property_value ); public Object getProperty( String property_type ); public void addPropertyChangeListener( UIPropertyChangeListener l ); public void removePropertyChangeListener( UIPropertyChangeListener l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/components/UIPropertyChangeEvent.java0000644000175000017500000000232310373051034027471 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.components; /** * @author parg * */ public interface UIPropertyChangeEvent { public UIComponent getSource(); public String getPropertyType(); public Object getNewPropertyValue(); public Object getOldPropertyValue(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/components/UITextArea.java0000644000175000017500000000334010373051034025252 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.components; /** * @author parg * */ public interface UITextArea extends UIComponent { public static final int DEFAULT_MAX_SIZE = 60000; /** * Setting values results in a PT_VALUE property change with a String value * @param precentage */ public void setText( String text ); /** * Appends the supplied text to the existing text value * @param text */ public void appendText( String text ); public String getText(); /** * Limits the maximum size of text held by the area. When then size is exceeded the text * will be truncated (text at the start of the string is removed, NOT the end) * All areas have a default max size as defined by the constant above */ public void setMaximumSize( int max_size ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/components/UIPropertyChangeListener.java0000644000175000017500000000217210373051034030177 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.components; /** * @author parg * */ public interface UIPropertyChangeListener { public void propertyChanged( UIPropertyChangeEvent ev ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIInputReceiverListener.java0000644000175000017500000000022211267524616025654 0ustar adrianadrianpackage org.gudy.azureus2.plugins.ui; public interface UIInputReceiverListener { public void UIInputReceiverClosed(UIInputReceiver receiver); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIManagerListener.java0000644000175000017500000000305710373051006024434 0ustar adrianadrian/* * Created on 05-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui; /** * * @see UIManager#addUIListener(UIManagerListener) * @see org.gudy.azureus2.ui.swt.plugins.UISWTInstance */ public interface UIManagerListener { /** * Triggered when an UI is attached * * @param instance Check with instanceof to see what UI is being * attached */ public void UIAttached( UIInstance instance ); /** * Triggered when an UI is detached * * @param instance Check with instanceof to see what UI is being * dettached */ public void UIDetached( UIInstance instance ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/Graphic.java0000644000175000017500000000204210373051006022464 0ustar adrianadrian/* * Created on 2004/May/23 * Created by TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ui; /** An image to be used in Azureus */ public interface Graphic { } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIPluginView.java0000644000175000017500000000327110373051006023443 0ustar adrianadrian/* * File : PluginView.java * Created : Oct 12, 2005 * By : TuxPaper * * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ui; /** * All plugin views should inherit from this interface so that we can always * check to see if they are a plugin view. *

* Any non generic UI plugin view functions are placed here, and every UI * should implement them. * * @author TuxPaper * @since 2.3.0.5 * * @see org.gudy.azureus2.ui.swt.plugins.UISWTView */ public interface UIPluginView { /** * Retrieve the data sources related to this view. * * @return dependent upon subclasses implementation */ public Object getDataSource(); /** * ID of the view * * @return ID of the view * * @since 2.3.0.6 */ public String getViewID(); /** * Closes the view * * @since 2.3.0.6 */ public void closeView(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/menus/0000755000175000017500000000000011310377616021407 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/ui/menus/MenuManager.java0000644000175000017500000000752511021645772024462 0ustar adrianadrian/* * Created on 25 January 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ui.menus; /** * Helper class to allow plugins to register their own menus. If you want to * add menus to be available in tables, you should use the TableManager * class. * * @author amc1 * @see org.gudy.azureus2.plugins.local.ui.tables.TableManager TableManager * @since 3.0.0.7 */ public interface MenuManager { /** * The menu used for tables - this value cannot be used directly to create * menus used by tables, you need to use the TableManager class * to create such menu items. * * @see org.gudy.azureus2.plugins.local.ui.tables.TableManager TableManager */ public static final String MENU_TABLE = "table"; /** * The menu used for the system tray icon. */ public static final String MENU_SYSTRAY = "systray"; /** * The menu used on download bars. */ public static final String MENU_DOWNLOAD_BAR = "downloadbar"; /** * The "Plugins" menu on the menu bar. */ public static final String MENU_MENUBAR = "mainmenu"; /** * The "transfers bar". * * @since 3.0.1.3 */ public static final String MENU_TRANSFERSBAR = "transfersbar"; /** * The "Torrents" menu. * * @since 3.0.2 */ public static final String MENU_TORRENT_MENU = "torrentmenu"; /** * All menus which are Download specific, such as download bars, the Torrent * menu, torrent tables etc. * * @since 3.0.2 */ public static final String MENU_DOWNLOAD_CONTEXT = "download_context"; /** * Creates a menu item for the appropriate menu. * * @param menuID The MENU_ identifier as defined above. * @param resource_key ID of the menu, which is also used to retrieve the * textual name from the plugin language file. * @return The newly created menu item. */ public MenuItem addMenuItem(String menuID, String resource_key); /** * Creates a menu item in a particular context. {@link MenuContext} * instances can be retrieved from some plugin objects that support * menu items to be added to it. * * @param context The menu context object which represents the place to * add a menu item. * @param resource_key ID of the menu, which is also used to retrieve the * textual name from the plugin language file. * @return The newly created menu item. * @since 3.0.5.3 */ public MenuItem addMenuItem(MenuContext context, String resource_key); /** * Creates a menu item as a sub-item of the given menu item. * * @param parent The MenuItem to add this new item to. The parent MenuItem * must have its style attribute to be set to "menu". * @param resource_key ID of the menu, which is also used to retrieve the * textual name from the plugin language file. * @return The newly created menu item. */ public MenuItem addMenuItem(MenuItem parent, String resource_key); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/menus/MenuItemListener.java0000644000175000017500000000370710672334314025510 0ustar adrianadrian/* * Created on 19-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.menus; /** A listener that is triggered when the user selects a menu item * * @author parg (Original ContextMenuItemListener) * @author tuxpaper (generic-izing and comments) */ public interface MenuItemListener { /** Menu item has been selected by the user. * * Note - this method will be called when a "deselection" takes place, like * if the MenuItem has STYLE_CHECK or STYLE_RADIO (where a * previously selected item has been deselected because another item has been * selected instead). * * Therefore, you should check the state of the MenuItem, rather than assuming * that it has been "activated". * * @param menu Which menu item was selected * @param target What this menu item applies to. For the default * implementation, target is null. Implementing classes * may provide an object related to the menu selection. */ public void selected( MenuItem menu, Object target ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/menus/MenuItemFillListener.java0000644000175000017500000000235010373051046026304 0ustar adrianadrian/* * Created on 03-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.menus; public interface MenuItemFillListener { /** * This is fired before a menu is shown * @param data For table context menu items this will be TableRow[] * of selected rows */ public void menuWillBeShown( MenuItem menu, Object data ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/menus/MenuContext.java0000644000175000017500000000210511021645772024521 0ustar adrianadrian/* * Created on 4 Jun 2008 * Created by Allan Crooks * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.ui.menus; /** * An object to be used with {@link MenuManager#addMenuItem(MenuItemContext, String)}. * *

Note: Only for implementation by Azureus, not plugins.

* @since 3.0.5.3 */ public interface MenuContext { } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/menus/MenuItem.java0000644000175000017500000001456410672334314024005 0ustar adrianadrian/* * Created on 19-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.menus; import org.gudy.azureus2.plugins.ui.Graphic; /** Menu item access for the UI. * * @author parg (Original ContextMenuItem code) * @author TuxPaper (Generic-izing, commenting) */ public interface MenuItem { /** * normal selection menu, no Data value required */ public static final int STYLE_PUSH = 1; /** * check box style menu item - data must be of type Boolean */ public static final int STYLE_CHECK = 2; /** * radio style - data must be Boolean */ public static final int STYLE_RADIO = 3; /** * separator line */ public static final int STYLE_SEPARATOR = 4; /** * menu containing submenu items */ public static final int STYLE_MENU = 5; /** Retrieve the resource key ("name") of this menu item * * @return resource key for this menu */ public String getResourceKey(); /** * Get the type of the menu item */ public int getStyle(); /** * Set the style of the menu item (see STYLE_ constants) * @param style */ public void setStyle( int style ); /** * Get the current data value associated with the menu: Boolean for CHECK style * @return */ public Object getData(); /** * Set the current data value associated with the menu: Boolean for CHECK style * @param data */ public void setData( Object data ); /** * Whether or not this item is enabled or not * @return */ public boolean isEnabled(); /** * Set the enabled status of the menu item * @param enabled */ public void setEnabled( boolean enabled ); /** * set the menu item's icon * @param graphic */ public void setGraphic( Graphic graphic ); /** * get the menu's graphic * @return */ public Graphic getGraphic(); /** * Adds a listener to be notified when the menu item is about to be * displayed. The "context" object provided is always going to be either * be null (if there is no context) or an array of objects * (such as an array of TableRows or an array of Download objects). * @param listener */ public void addFillListener(MenuItemFillListener listener); public void removeFillListener(MenuItemFillListener listener); /** * Adds a selection listener for this menu item. * * This differs from {@link #addListener(MenuItemListener)}, in that the * target object which will be passed to the listener will be an * array of objects, rather than just a single object. * * @param l listener to be notified when user has selected the menu item. * @since 3.0.2 */ public void addMultiListener(MenuItemListener l); /** * Removes a selection listener from this menu item. * * You only use this method to remove a listener added via * {@link #addMultiListener(MenuItemListener)}. * * @param l listener to remove * @since 3.0.2 */ public void removeMultiListener(MenuItemListener l); /** * Adds a selection listener for this menu item. * @param l listener to be notified when user has selected the menu item. */ public void addListener(MenuItemListener l); /** * Removes a selection listener from this menu item. * @param l listener to remove */ public void removeListener(MenuItemListener l); /** * Retrieve the parent MenuItem. * * @return parent menu object, or null if no parent */ public MenuItem getParent(); /** * Get all child items currently associated with this MenuItem. * * @return An array of items (if this object has the menu style * associated) or null otherwise. */ public MenuItem[] getItems(); /** * Get the child item with the given resource key. * * @return The child MenuItem object which has the resource key * specified, or null otherwise. */ public MenuItem getItem(String key_id); /** * Gets the text to display for this menu item. */ public String getText(); /** * Sets the text to display for this menu item. You can also * pass null to revert back to the default behaviour. */ public void setText(String text); /** * Retrieve the menu ID that the menu item belongs to * @return {@link MenuManager}.MENU_ constant. * * @since 3.0.0.7 */ public String getMenuID(); /** * Removes the menu item. * * Calling this will remove the item from the menus, as well as removing all * listeners and removing all child menu items (if any exist). * * The behaviour of this object is undefined after this method has been called. * If you need to interact with this object when you are about to destroy it, * you should do it before you call the remove method. * * @since 3.0.0.7 */ public void remove(); /** * Removes all child menu items from this menu (if any exist). * * @since 3.0.0.7 */ public void removeAllChildItems(); /** * Sets whether the menu item is visible or not. * @since 3.0.2.0 */ public void setVisible(boolean visible); /** * Returns whether the menu item is visible or not. * @since 3.0.2.0 */ public boolean isVisible(); /** * Returns whether the menu item is selected or not. * * This method should only be called if the menu is of type STYLE_RADIO or * type STYLE_CHECK and if the menu item has already had a selected or * deselected state assigned to it. * * @since 3.0.2.4 */ public boolean isSelected(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/0000755000175000017500000000000011310377634021532 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableColumnCreationListener.java0000644000175000017500000000221711066073414027774 0ustar adrianadrian/** * Created on Sep 19, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; /** * @author TuxPaper * @created Sep 19, 2008 * */ public interface TableColumnCreationListener { /** * Triggered when a new column is created. Use the column parameter to * get information about the new column, such as which table created it * * @param column * * @since 3.1.1.1 */ public void tableColumnCreated(TableColumn column); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableCellLightRefreshListener.java0000644000175000017500000000267510747110702030245 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.tables; /** * @author Aaron Grunthal * @create 16.09.2007 */ public interface TableCellLightRefreshListener extends TableCellRefreshListener { /** Triggered based on refresh interval specified in {@link TableColumn#getRefreshInterval()} * * @param cell TableCell that the refresh trigger is for * @param sortOnlyRefresh true when the cell is being refreshed despite not being visible (this usually occurs when the cell belongs to the sort column) */ public void refresh(TableCell cell, boolean sortOnlyRefresh); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableCellDisposeListener.java0000644000175000017500000000211010052113432027235 0ustar adrianadrian/* * Created : 2004/Apr/30 * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; /** A listener that triggers when a cell is being disposed * * @author TuxPaper */ public interface TableCellDisposeListener { /** triggered when a cell is being dispose of * * @param cell TableCell that is being disposed of */ void dispose(TableCell cell); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableCellVisibilityListener.java0000644000175000017500000000241510535733532030005 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.tables; /** * Not implemented for Plugin Interface * * @author TuxPaper * @created Dec 5, 2006 * */ public interface TableCellVisibilityListener { public static int VISIBILITY_SHOWN = 0; public static int VISIBILITY_HIDDEN = 1; // Future: GAINED_FOCUS, LOST_FOCUS, SELECTED, UNSELECTED? void cellVisibilityChanged(TableCell cell, int visibility); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableCellMouseEvent.java0000644000175000017500000000230310640433412026225 0ustar adrianadrian/* * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; /** * Mouse event information for * {@link org.gudy.azureus2.plugins.ui.tables.TableCellMouseListener} *

* Note: 3.0.1.7 moved most functions to {@link TableRowMouseEvent} * * @author TuxPaper * @created Jan 10, 2006 * @since 2.3.0.7 */ public class TableCellMouseEvent extends TableRowMouseEvent { /** * TableCell that the mouse trigger applies to * * @since 2.3.0.7 */ public TableCell cell; } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableManager.java0000644000175000017500000001574711164323310024722 0ustar adrianadrian/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.ui.tables; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadTypeComplete; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; /** Allows plugins to manage Azureus UI tables. * * @author TuxPaper * @since 2.0.8.5 */ public interface TableManager { /** Visible for Completed Torrents table */ public static final String TABLE_MYTORRENTS_COMPLETE = "MySeeders"; /** Visible for Incompleted Torrents table */ public static final String TABLE_MYTORRENTS_INCOMPLETE = "MyTorrents"; public static final String TABLE_MYTORRENTS_UNOPENED = "Unopened"; /** Visible for Completed Torrents table (big version)*/ public static final String TABLE_MYTORRENTS_COMPLETE_BIG = "MySeeders.big"; /** Visible for Incompleted Torrents table (big version)*/ public static final String TABLE_MYTORRENTS_INCOMPLETE_BIG = "MyTorrents.big"; public static final String TABLE_MYTORRENTS_UNOPENED_BIG = "Unopened.big"; public static final String TABLE_MYTORRENTS_ALL_BIG = "MyLibrary.big"; public static final String TABLE_ACTIVITY = "Activity"; public static final String TABLE_ACTIVITY_BIG = "Activity.big"; /** Visible for Torrent Peers table */ public static final String TABLE_TORRENT_PEERS = "Peers"; /** Visible for Torrent Pieces table */ public static final String TABLE_TORRENT_PIECES = "Pieces"; /** Visible for Torrent Files table */ public static final String TABLE_TORRENT_FILES = "Files"; /** Visible for My Tracker table */ public static final String TABLE_MYTRACKER = "MyTracker"; /** Visible for My Shares table */ public static final String TABLE_MYSHARES = "MyShares"; /** Visible for All Peers table */ public static final String TABLE_ALL_PEERS = "AllPeers"; /** Creates a column for a UI table. * In order for this object to be displayed in an Azureus UI table, the * returned object must be added via the {@link #addColumn(TableColumn)} *

* The distinction between creating and adding a column is required because * some TableColumn functions are not available or act differently after the * column had been added. *

* In order to the plugin to display correctly the column name, you are * required to create a key in your language file consisting of the * {@link TableManager} Table ID of the table you are adding the column to, * plus ".column." plus the logical name of your column. *

* For example, if you are creating a column named "quality" in the table * TABLE_TORRENT_FILES, youwould have to add the following to your language * file:
* Files.column.quality=Column Title
* and if you wish to have a short description of the column (visible when * the user is setting up columns), create another entry with the same key * plus ".info". For the example above:
* Files.column.quality.info=One line description * * * @param tableID Which table the column will be visible in. See {@link TableManager}. * @param cellID The logical name of the column. * * @return an interface object allowing modification of the table column. */ public TableColumn createColumn(String tableID, String cellID); /** * Register a column for a specific data source type. When the column * is created, the listener will be fired. *

* This method is independent of {@link #createColumn(String, String)} and * {@link #addColumn(TableColumn)}. This method improves upon them by * saving you from creating and adding the column to every potential table * it could be displayed in. It allows for your column to be added to future * tables without and code changes on your end. * * @param forDataSourceType Class of datasource you want to add a column to, * such as {@link Download}, {@link DownloadTypeComplete}, * {@link DownloadTypeIncomplete} * * @param cellID The logical name of the column. * * @param listener * * @return an interface object allowing modification of the table column. * * @since 3.1.1.1 */ public void registerColumn(Class forDataSourceType, String cellID, TableColumnCreationListener listener); /** * unregister a listener added by @link {@link #registerColumn(Class, String, TableColumnCreationListener)} * @param forDataSourceType * @param cellID * @param listener * @since 4005 */ public void unregisterColumn(Class forDataSourceType, String cellID, TableColumnCreationListener listener); /** Adds a column to an Azureus UI table. * * @param tableColumn a column previously created with {@link #createColumn} */ public void addColumn(TableColumn tableColumn); /** Adds a Context Menu item to the specified table or to all table context menus. * * @param tableID Which table the menu item will be visible in. See {@link TableManager}. * If null, the menu item will be added to all table context menus. * @param resourceKey ID of the context menu, which is also used to retrieve * the textual name from the plugin language file. * * @return a newly created menu item for the table's context menu. */ public TableContextMenuItem addContextMenuItem(String tableID, String resourceKey); /** Adds a Context Menu item as a sub-item of the given menu item. * * @param parent The MenuItem to add this new item to. The parent MenuItem must have its * style attribute to be set to "menu". * @param resourceKey ID of the context menu, which is also used to retrieve * the textual name from the plugin language file. * * @return a newly created menu item existing inside the given menu item. */ public TableContextMenuItem addContextMenuItem(TableContextMenuItem parent, String resourceKey); /** Future Implementations: public TableContextMenuItem addContextMenuItem(String tableID, String resourceKey, String parentKey); public Menu addContextMenu(String tableID, String resourceKey); public Menu addContextMenu(String tableID, String resourceKey, String parentKey); */ } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/package.html0000644000175000017500000000027510052113432024001 0ustar adrianadrian Classes that manage aspects of Azureus tables. azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableRowMouseListener.java0000644000175000017500000000235210640623240026625 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.tables; /** * @author TuxPaper * @created May 13, 2007 * */ public interface TableRowMouseListener { /** * triggered when a mouse event for the TableRow occurs, excluding * mouse move. * * @param event Mouse event information * * @since 3.0.1.7 */ public void rowMouseTrigger(TableRowMouseEvent event); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableColumn.java0000644000175000017500000004051311232522032024570 0ustar adrianadrian/* * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; /** * This interface provides access to an Azureus table column. */ public interface TableColumn { public static final int MENU_STYLE_HEADER = 1; public static final int MENU_STYLE_COLUMN_DATA = 2; /** The cells in this column display textual information. */ public static final int TYPE_TEXT = 1; /** The graphic type, providing access to graphic specific functions in * {@link TableCell}. */ public static final int TYPE_GRAPHIC = 2; /** * The cells in this column display only textual information, and does not * set any other visible properties of cell (background, foreground, icon, * etc). * * Using this type allows azureus to call refresh less, and saves on CPU. */ public static final int TYPE_TEXT_ONLY = 3; /** leading alignment */ public static final int ALIGN_LEAD = 1; /** trailing alignment */ public static final int ALIGN_TRAIL = 2; /** center alignment */ public static final int ALIGN_CENTER = 3; /** top align */ public static final int ALIGN_TOP = 4; /** bottom align */ public static final int ALIGN_BOTTOM = 8; /** For {@link #setPosition(int)}. Make column invisible initially. */ public static final int POSITION_INVISIBLE = -1; /** For {@link #setPosition(int)}. Make column the last column initially. */ public static final int POSITION_LAST = -2; /** Trigger refresh listeners every time a graphic cycle occurs (set by user) */ public static final int INTERVAL_GRAPHIC = -1; /** Trigger refresh listeners every time a GUI update cycle occurs (set by user) */ public static final int INTERVAL_LIVE = -2; /** Trigger refresh only when the cell/row becomes invalid */ public static final int INTERVAL_INVALID_ONLY = -3; public static final String CAT_ESSENTIAL = "essential"; public static final String CAT_SHARING = "sharing"; public static final String CAT_TRACKER = "tracker"; public static final String CAT_TIME = "time"; public static final String CAT_SWARM = "swarm"; public static final String CAT_CONTENT = "content"; public static final String CAT_PEER_IDENTIFICATION = "identification"; public static final String CAT_PROTOCOL = "protocol"; public static final String CAT_BYTES = "bytes"; public static final String CAT_SETTINGS = "settings"; public static final String CAT_CONNECTION = "connection"; public static final String CAT_PROGRESS = "progress"; /** Initialize a group of variables all at once. Saves on individual setXxx. * * @param iAlignment See {@link #setAlignment(int)} * @param iPosition See {@link #setPosition(int)} * @param iWidth See {@link #setWidth(int)} * @param iInterval See {@link #setRefreshInterval(int)} * * @since 2.1.0.0 */ public void initialize(int iAlignment, int iPosition, int iWidth, int iInterval); /** Initialize a group of variables all at once. Saves on individual setXxx. * * @param iAlignment See {@link #setAlignment(int)} * @param iPosition See {@link #setPosition(int)} * @param iWidth See {@link #setWidth(int)} * * @since 2.1.0.0 */ public void initialize(int iAlignment, int iPosition, int iWidth); /** * The logical name of the column. This was set via * {@link TableManager#createColumn} and can not be changed. * * @return the column name (identification) * * @since 2.1.0.0 */ public String getName(); /** Which table the column will be visible in. This was set via * {@link TableManager#createColumn} and can not be changed. * * @return {@link TableManager}.TABLE_* constant(s) * * @since 2.1.0.0 */ public String getTableID(); /** The type of the contained data.
* Current supported types are long, string, and graphic. *

* NOTE: This MUST be set BEFORE adding the column to a table. *
* The default type is {@link #TYPE_TEXT_ONLY}. * * @param type {@link #TYPE_TEXT}, {@link #TYPE_TEXT_ONLY}, {@link #TYPE_GRAPHIC} * * @since 2.1.0.0 */ public void setType(int type); /** Returns the type of the contained data. * * @return type TYPE_TEXT, or TYPE_GRAPHIC * * @since 2.1.0.0 */ public int getType(); /** The column size. *

* NOTE: This MUST be set BEFORE adding the column to a table. * * @param width the size in pixels * * @since 2.1.0.0 */ public void setWidth(int width); /** Returns the column's size * * @return width in pixels * * @since 2.1.0.0 */ public int getWidth(); /** Location to put the column. When set before being added to the UI * (see {@link TableManager#addColumn}), the supplied value will be used * as the default position. If the user has moved the column previously, * the new position will be used, and the default position will be ignored. * * This function cannot be called after you have added the column to a UI * table. In the future, setting the position after adding the column to the * UI table will result in the column being moved. * * @param position Column Number (0 based), POSITION_INVISIBLE or POSITION_LAST * * @since 2.1.0.0 */ public void setPosition(int position); /** Returns the position of the column * * @return Column Number (0 based), POSITION_INVISIBLE or POSITION_LAST * * @since 2.1.0.0 */ public int getPosition(); /** Orientation of the columns text and header. *

* NOTE: This MUST be set BEFORE adding the column to a table. * * @param alignment ALIGN_TRAIL, ALIGN_LEAD, or ALIGN_CENTER * * @since 2.1.0.0 */ public void setAlignment(int alignment); /** Returns the alignment of the column * * @return ALIGN_TRAIL, ALIGN_LEAD, or ALIGN_CENTER * * @since 2.1.0.0 */ public int getAlignment(); /** Set how often the cell receives a refresh() trigger * * @param interval INTERVAL_GRAPHIC, INTERVAL_LIVE, INTERVAL_INVALID_ONLY * constants, or an integer based on the user-configurable * "GUI refresh interval". For example, specifying 4 will * result in a refresh trigger every 4 "GUI refresh intervals" * * @since 2.1.0.0 */ public void setRefreshInterval(int interval); /** Returns the refresh interval of the column. * The default is INTERVAL_INVALID_ONLY * * @return INTERVAL_* constant, or a number representing the # of GUI refresh * cycles between each cell refresh call. * * @since 2.1.0.0 */ public int getRefreshInterval(); /** * Sets the minimum width that the column can be before other columns * start collapsing. This may not prevent the user from resizing the column * smaller than specified. *

* If not set, the width specified on initialize will be the minimum width *

* Not all UIs may have this feature implemented. * * @param minwidth new minumum width * * @since 3.0.0.7 */ public void setMinWidth(int minwidth); /** * Gets the minimum width that the column can be before other columns * start collapsing. *

* If not set, the width specified on initialize will be the minimum width *

* Not all UIs may have this feature implemented. * * @return minumum width of the column * * @since 3.0.0.7 */ public int getMinWidth(); /** * Sets the maximum width that the column can be *

* Not all UIs may have this feature implemented. * * @param maxwidth new maximum width * * @since 3.0.0.7 */ public void setMaxWidth(int maxwidth); /** * Gets the maximum width the column can be *

* Not all UIs may have this feature implemented. * * @return maximum width of column * * @since 3.0.0.7 */ public int getMaxWidth(); /** * Sets the minimum and maximum widths in one call *

* Not all UIs may have this min and max limits implemented. * * @param min New minimum column width * @param max New maximum column width * * @since 3.0.0.7 */ public void setWidthLimits(int min, int max); /** * Sets whether the max width is automatically set. Depending on the UI, * automatically setting the max width usually results in the maximum width * being grown to fit the largest text set for any cell (past or present). * Therefore, the column will never grow larger than the largest text it * contains or contained. * * @param automaxwidth * * @since 3.0.0.7 */ public void setMaxWidthAuto(boolean automaxwidth); /** * Retrieve whether the max width is automatically being set. * * @return max width auto setting state * * @since 3.0.0.7 */ public boolean isMaxWidthAuto(); /** * Sets whether the min width of the column is automatically set. Depending * on the UI, automatically setting the min width usually results in the * column never shrinking below the maximum text width ever encountered. * * @param autowidth * * @since 3.0.0.7 */ public void setMinWidthAuto(boolean autowidth); /** * Retrieve whether the min width is automatically being set * * @return min width auto setting state * * @since 3.0.0.7 */ public boolean isMinWidthAuto(); /** * Sets the preferred width of the column. When the UI is in auto-expand * mode and space is made available, the columns will first fill to their * preferred width, then to their maximum width. * * @param width New preferred width * * @since 3.0.0.7 */ public void setPreferredWidth(int width); /** * Gets the preferred width of the coloumn. * * @return preferred width * * @since 3.0.0.7 */ public int getPreferredWidth(); /** * Retrieves whether the preferred width is automatically calculated. * * @return preferred width auto calculation state * * @since 3.0.0.7 */ public boolean isPreferredWidthAuto(); /** * Sets whether the preferred with is automatically calculated. An * automatically calculated preferred width will be set to the largest * text width known to that column * * @param auto Preferred Width Auto State * * @since 3.0.0.7 */ public void setPreferredWidthAuto(boolean auto); /** * Gets the visibility of the column *

* Not all UIs may have this feature implemented. * * @return Column visibility * * @since 3.0.0.7 */ public boolean isVisible(); /** * Associates custom data with the column, usually meant for column-specific settings and stores it across sessions * @param key the key under which the value will be stored and serialized * @param value should be BEncodable, otherwise it won't be serialized */ public void setUserData(String key, Object value); public void removeUserData(String key); /** * implement this method if you want to be notified when the stored column * configuration such as user data or GUI-adjustable properties have been * loaded */ public void postConfigLoad(); /** * implement this method if you want to be notified when the column * configuration is about to be serialized */ public void preConfigSave(); /** * * @param key * @return data set via setUserData() */ public Object getUserData(String key); /** * Sets the visibility of the column * * @param visible New visibility state * * @since 3.0.0.7 */ public void setVisible(boolean visible); /** Adds a listener that triggers when a TableCell that belongs to this column * needs refreshing. * * @param listener Listener Object to be called when refresh is needed. * * @since 2.1.0.0 */ public void addCellRefreshListener(TableCellRefreshListener listener); /** Removed a previously added TableCellRefreshListener * * @param listener Previously added listener * * @since 2.1.0.0 */ public void removeCellRefreshListener(TableCellRefreshListener listener); /** Adds a listener that triggers when a TableCell that belongs to this column * is being added. * * @param listener Listener Object to be called when refresh is needed. * * @since 2.1.0.0 */ public void addCellAddedListener(TableCellAddedListener listener); public void removeCellAddedListener(TableCellAddedListener listener); /** Adds a listener that triggers when a TableCell that belongs to this column * is being disposed. * * @param listener Listener Object to be called when refresh is needed. * * @since 2.1.0.0 */ public void addCellDisposeListener(TableCellDisposeListener listener); public void removeCellDisposeListener(TableCellDisposeListener listener); /** Adds a listener that triggers when a TableCell that belongs to this column * has a tooltip action * * @param listener Listener Object to be called when refresh is needed. * * @since 2.1.0.2 */ public void addCellToolTipListener(TableCellToolTipListener listener); public void removeCellToolTipListener(TableCellToolTipListener listener); /** * Adds a listener that triggers when a TableCell that belongs to this column * has a mouse event. * * @param listener * * @since 2.3.0.7 */ public void addCellMouseListener(TableCellMouseListener listener); /** Remove a previously added TableCellMouseListener * * @param listener Previously added listener * @since 2.3.0.7 */ public void removeCellMouseListener(TableCellMouseListener listener); /** * A listener is added for every type of cell listener the supplied object * implements * * @param listenerObject Object implementing some cell listeneters * * @since 2.4.0.0 */ public void addListeners(Object listenerObject); /** Invalidate all cells in this column. The cells will be forced to * update on the next refresh. * * @since 2.1.0.0 */ public void invalidateCells(); /** * Invalidates any cells which are linked to the given data source object. * * @since 3.0.1.5 */ public void invalidateCell(Object data_source); /** Adds a Context Menu item to the column * * @param resourceKey ID of the context menu, which is also used to retreieve * the textual name from the plugin language file. * @param menuStyle See MENU_STYLE_* constants (header or data) * * @return a newly created menu item * * @since 4.2.0.5 */ public TableContextMenuItem addContextMenuItem(String resourceKey, int menuStyle); /** Adds a Context Menu item to data section of the column * * @param resourceKey ID of the context menu, which is also used to retreieve * the textual name from the plugin language file. * * @return a newly created menu item * * @since 2.4.0.0 */ public TableContextMenuItem addContextMenuItem(String resourceKey); /** * Returns whether the column's data will be obfusticated when screen * capturing (for bug reports, etc). *

* Currently not fully implemented for plugins * * @return Obfusticated value * * @since 2.4.0.3 */ boolean isObfusticated(); /** * Sets whether the column's data will be obfusticated during a screen * capture (for bug reports, etc). * * @param hideData new state of obfustication * * @since 2.4.0.3 */ void setObfustication(boolean hideData); /** * @since 4005 */ public void remove(); /** * @param listener * * @since 4.0.0.5 */ void addColumnExtraInfoListener(TableColumnExtraInfoListener listener); /** * @param listener * * @since 4.0.0.5 */ void removeColumnExtraInfoListener(TableColumnExtraInfoListener listener); /** * @return * * @since 4.0.0.5 */ Class getForDataSourceType(); }azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableCellRefreshListener.java0000644000175000017500000000226410055717112027247 0ustar adrianadrian/* * Created : 2004/Apr/30 * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; /** A listener that triggers based on refresh interval specified in * {@link TableColumn#getRefreshInterval()} * * @author TuxPaper */ public interface TableCellRefreshListener { /** Triggered based on refresh interval specified in {@link TableColumn#getRefreshInterval()} * * @param cell TableCell that the refresh trigger is for */ void refresh(TableCell cell); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableCell.java0000644000175000017500000003075411066072462024234 0ustar adrianadrian/* * File : TableCell.java * Created : 29 nov. 2003 * By : Olivier * Adapted to MyTorrents by TuxPaper 2004/02/16 * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; import org.gudy.azureus2.plugins.ui.Graphic; /** This interface provides access to an Azureus table cell. * * @see TableManager * * @author Oliver (Original PeerTableItem Code) * @author TuxPaper (Generic-izing) * * @since 2.0.8.5 */ // Modified from MyTorrentsTableItem/PeerTableItem public interface TableCell { /** Retrieve the data object associated with the current table row and cell. * The results of this method MUST NOT BE CACHED. * The link between a table cell and a DataSource is not persistent and can * change from call to call (for example when the table is re-ordered, the * link may be modified) * * @return The return type is dependent upon which table the cell is for:
* TABLE_MYTORRENTS_*: {@link org.gudy.azureus2.plugins.download.Download} * object for the current row
* TABLE_TORRENT_PEERS: {@link org.gudy.azureus2.plugins.peers.Peer} * object for the current row
* TABLE_TORRENT_FILES: {@link org.gudy.azureus2.plugins.disk.DiskManagerFileInfo} * object for the current row
* TABLE_MYTRACKER: {@link org.gudy.azureus2.plugins.tracker.TrackerTorrent} * object for the current row
* TABLE_MYSHARES: {@link org.gudy.azureus2.plugins.sharing.ShareResource} * object for the current row
* remaining TABLE_* constants: undefined or null
*/ Object getDataSource(); /** Retreive the TableColumn that this cell belongs to * * @return this cell's TableColumn */ TableColumn getTableColumn(); /** Retrieve the TableRow that this cell belongs to * * @return this cell's TableRow */ TableRow getTableRow(); /** Returns which table the cell is being displayed in. * * @return {@link TableManager}.TABLE_* constant */ String getTableID(); /** * This method is called to set the cell's text. * Caching is done, so that if same text is used several times, * there won't be any 'flickering' effect. Ie the text is only updated if * it's different from current value. *

* This function must be called from the same thread that the GUI is running * under. Listeners like {@link TableCellAddedListener} do not always get * called on the GUI thread. *

* If you wish to set the text and not worry about changing to the GUI thread, * use {@link #invalidate()}, and set the text in the * {@link TableCellRefreshListener} * * @param text the text to be set * @return True - the text was updated.
* False - the text was the same and not modified. */ boolean setText(String text); /** Retrieve the Cell's text * * @return Cell's text */ String getText(); /** Change the cell's foreground color. *

* pass -1 to return color back to default * * @param red red value (0 - 255) * @param green green value (0 - 255) * @param blue blue value (0 - 255) * @return True - Color changed.
* False - Color was already set. */ boolean setForeground(int red, int green, int blue); /** * Change the cell's foreground color * * @param rgb int array containing red, green, and blue values, respectively. * null to return color back to default * @return * * @since 3.0.4.3 */ boolean setForeground(int[] rgb); /** * Change the cell's foreground color to the user's defined "error" color. * * @since 3.0.3.5 * @return True - Color changed.
* False - Color was already set. */ boolean setForegroundToErrorColor(); /** * Get the foreground color of the cell * * @return array containing red, green, and blue color * * @since 2.5.0.1 */ int[] getForeground(); /** * Get the background color of the cell * * @return array containing red, green, and blue color. Might be null * * @since 3.0.3.5 */ int[] getBackground(); /** Sets a Comparable object that column sorting will act on. If you never * call setSortValue, your column will be sorted by the cell's text. * * @param valueToSort the object that will be used when the column cell's * are compared to each other * @return True - Sort Value changed.
* False - Sort Value was already set to object supplied. */ public boolean setSortValue(Comparable valueToSort); /** Sets a long value that the column sorting will act on. * * @param valueToSort sorting value. * @return True - Sort Value changed.
* False - Sort Value was already set to value supplied. */ public boolean setSortValue(long valueToSort); /** * Sets a float value that the column sorting will act upon. * @param valueToSort float sort value * @return true if sort value changed, or false if sort value already set to value supplied */ public boolean setSortValue( float valueToSort ); /** Retrieves the sorting value * * @return Object that will be sorted on */ public Comparable getSortValue(); /** Determines if the user has chosen to display the cell * * @return True - User has chosen to display cell */ boolean isShown(); /** Validility of the cell's text. * * @return True - Text is the same as last call. You do not need to update * unless you have new text to display.
* False - Cell-to-Datasource link has changed, and the text is * definitely not valid. */ boolean isValid(); /** Sets the cell to invalid. This will result in a refresh on the next * scheduled interval. * * @since 2.3.0.7 */ public void invalidate(); /** * Set the cell's tooltip display. * * * @param tooltip Object to display. Currently, only String is supported * * @see #addToolTipListener(TableCellToolTipListener) * @since 2.1.0.2 */ public void setToolTip(Object tooltip); /** * Retrieve the tooltip object assigned to this cell * * @return tooltip object * * @see #addToolTipListener(TableCellToolTipListener) * @since 2.1.0.2 */ public Object getToolTip(); /** * Retrieve whether the cell has been disposed. This will return true after * the {@link TableCellDisposeListener} is triggered. * * @return disposal state * @since 2.3.0.7 */ public boolean isDisposed(); /** * Retrieves the number of lines available for setting text * * @return # of lines available, -1 if unknown * * @since 3.0.1.1 */ public int getMaxLines(); ////////////////////////////////// // Start TYPE_GRAPHIC functions // ////////////////////////////////// /** Retrieve the width of the cell's drawing area (excluding any margin) for * TableColumn objects of TYPE_GRAPHIC only. * * @return if you are filling the cell, this is the width your image should be */ public int getWidth(); /** Retrieve the height of the cell's drawing area (excluding any margin) for * TableColumn objects of TYPE_GRAPHIC only. * * @return if you are filling the cell, this is the height your image should be */ public int getHeight(); /** Sets the image to be drawn. *

* From 3.0.1.1, setting the graphic to the same Graphic object will not * redraw the image. You need to {@link #invalidate()} the cell if you * know the image bits have changed (or you could pass a new Graphic object * in each time a new image is generated) *

* Previously, setting the graphic to the same object resulted in a repaint. * Plugins were naughty and would do this on every refresh, causing horrible * repaint slowdowns. * * @param img image to be stored & drawn * @return true - image was changed.
* false = image was the same */ public boolean setGraphic(Graphic img); /** Retrieve the SWT graphic related to this table item for * TableColumn objects of TYPE_GRAPHIC only. * * @return the Image that is draw in the cell, or null if there is none. */ public Graphic getGraphic(); /** TODO: /** Sets the image to be drawn to the file specified for * TableColumn objects of TYPE_GRAPHIC only. * * @param imageLocation URI of image * @return true - image was changed.
* false = image was the same * public boolean setGraphic(String imageLocation); */ /** Sets whether the graphic fills the whole cell for * TableColumn objects of TYPE_GRAPHIC only. This may effect how often * a refresh of the cell is needed, and effects alignment. * * @param bFillCell true - the whole cell is filled by the graphic */ public void setFillCell(boolean bFillCell); /** * @return * * @since 3.0.5.3 */ int getMarginHeight(); /** * Specifies the number of pixels of vertical margin that will * be placed along the top and bottom edges of the layout for * TableColumn objects of TYPE_GRAPHIC only. *

* The default is 1. * * @param height new margin height */ public void setMarginHeight(int height); /** * @return * * @since 3.0.5.3 */ int getMarginWidth(); /** * Specifies the number of pixels of horizontal margin that will * be placed along the left and right edges of the layout for * TableColumn object of TYPE_GRAPHIC only. *

* The default is 1. * * @param width new margin width */ public void setMarginWidth(int width); // End TYPE_GRAPHIC functions /** Adds a listener that triggers when the TableCell needs refreshing * * @param listener Listener Object to be called when refresh is needed. */ public void addRefreshListener(TableCellRefreshListener listener); /** Remove a previously added TableCellRefreshListener * * @param listener Previously added listener */ public void removeRefreshListener(TableCellRefreshListener listener); /** Adds a listener that triggers when the TableCell has been disposed * * @param listener listener object to be called */ public void addDisposeListener(TableCellDisposeListener listener); /** Remove a previously added TableCellDisposeListener * * @param listener Previously added listener */ public void removeDisposeListener(TableCellDisposeListener listener); /** Adds a listener related to tooltip actions * * @param listener listener object to be called */ public void addToolTipListener(TableCellToolTipListener listener); /** Remove a previously added TableCellToolTipListener * * @param listener Previously added listener */ public void removeToolTipListener(TableCellToolTipListener listener); /** * Adds a listener that triggers when a TableCell that belongs to this column * has a mouse event. * * @param listener * * @since 2.3.0.7 */ public void addMouseListener(TableCellMouseListener listener); /** Remove a previously added TableCellMouseListener * * @param listener Previously added listener * @since 2.3.0.7 */ public void removeMouseListener(TableCellMouseListener listener); /** * A listener is added for every type of cell listener the supplied object * implements * * @param listenerObject Object implementing some cell listeneters */ public void addListeners(Object listenerObject); /** * Returns a Graphic of what's behind the cell * * @return * * @since 3.0.3.5 */ public Graphic getBackgroundGraphic(); /** * Return the position of the mouse relative to the cell. * * @return array of 2 containing x and y position position relative to cell. * null if cell doesn't have mouse. * * @since 3.0.4.3 */ public int[] getMouseOffset(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableCellMouseListener.java0000644000175000017500000000307410640623240026737 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ui.tables; /** * A listener that triggers on various mouse events (see * {@link org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent}) that occur * on a TableCell, excluding mouse move events. * * @see TableCell#addMouseListener(TableCellMouseListener) * @see TableColumn#addCellMouseListener(TableCellMouseListener) * * @author TuxPaper * @created Jan 10, 2006 * @since 2.3.0.7 */ public interface TableCellMouseListener { /** * triggered when a mouse event for the TableCell occurs, excluding * mouse move. * * @param event Mouse event information * * @since 2.3.0.7 */ public void cellMouseTrigger(TableCellMouseEvent event); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableCellToolTipListener.java0000644000175000017500000000247110624700050027236 0ustar adrianadrian/* * Created : 2004/Apr/30 * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; /** A listener that triggers when a cell's tooltip is about to be * displayed or removed * * @author TuxPaper */ public interface TableCellToolTipListener { /** triggered when a cell's tooltip is about to be displayed. * * @param cell TableCell which the tooltip will be displayed for */ void cellHover(TableCell cell); /** triggered when a cell's tooltip is about to be removed. * * @param cell TableCell which the tooltip will be removed */ void cellHoverComplete(TableCell cell); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableColumnExtraInfoListener.java0000644000175000017500000000213411135264370030125 0ustar adrianadrian/** * Created on Jan 10, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; /** * @author TuxPaper * @created Jan 10, 2009 * */ public interface TableColumnExtraInfoListener { /** * Provide the app with information about your Table Column * * @param info Use setters to set information * * @since 4.0.0.5 */ public void fillTableColumnInfo(TableColumnInfo info); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableCellAddedListener.java0000644000175000017500000000207310052113432026640 0ustar adrianadrian/* * Created : 2004/Apr/30 * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; /** A listener that triggers when a cell is being added * * @author TuxPaper */ public interface TableCellAddedListener { /** triggered when a cell is being added. * * @param cell TableCell that is being added */ void cellAdded(TableCell cell); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableRowMouseEvent.java0000644000175000017500000000607210640433412026124 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui.tables; /** * @author TuxPaper * @created May 13, 2007 * * @note originally TableCellMouseEvent */ public class TableRowMouseEvent { /** * eventType is triggered when mouse is pressed down * * @since 2.3.0.7 */ public final static int EVENT_MOUSEDOWN = 0; /** * eventType is triggered when mouse is let go * * @since 2.3.0.7 */ public final static int EVENT_MOUSEUP = 1; /** * eventType is trigggered when mouse is double clicked * * @since 2.3.0.7 */ public final static int EVENT_MOUSEDOUBLECLICK = 2; /** * eventType is triggered when the mouse is moved. ONLY fires for * listeners with subclass of TableMouseMoveListener. * {@link TableCellMouseListener} will not recieve mouse move events. */ public final static int EVENT_MOUSEMOVE = 3; public final static int EVENT_MOUSEENTER = 4; public final static int EVENT_MOUSEEXIT = 5; /** * EVENT_* constant specifying the type of event that has been triggered * * @since 2.3.0.7 */ public int eventType; /** * x position of mouse relative to table cell * * @since 2.3.0.7 */ public int x; /** * y position of mouse relative to table cell */ public int y; /** * Which button was pressed. 1 = first button (left), * 2 = second button (middle), 3 = third button (right) *

* More buttons may already be pressed down. *

* For events of type EVENT_MOUSEMOVE, button will be 0 * * @since 2.3.0.7 */ public int button; /** * Keyboard state when the mouse event was triggered. * * @TODO Define state constants * * @since 2.3.0.7 */ public int keyboardState; /** * Setting this value to true will prevent Azureus from running its * core functionality (if any) for the mouse event. * * For example, by default the double click in My Torrents goes to * the details view. If your plugin remaps double click to do a different * function, set skipCoreFunctionality = true. */ public boolean skipCoreFunctionality; /** * Misc data * * @since 3.0.1.7 */ public Object data; /** * TableRow that the mouse trigger applies to * * @since 3.0.1.6 */ public TableRow row; } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableColumnInfo.java0000644000175000017500000000247111135264370025417 0ustar adrianadrian/** * Created on Jan 10, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; import org.gudy.azureus2.plugins.ui.config.Parameter; /** * @author TuxPaper * @created Jan 10, 2009 * */ public interface TableColumnInfo { public byte PROFICIENCY_BEGINNER = Parameter.MODE_BEGINNER; public byte PROFICIENCY_INTERMEDIATE = Parameter.MODE_INTERMEDIATE; public byte PROFICIENCY_ADVANCED = Parameter.MODE_ADVANCED; public String[] getCategories(); public void addCategories(String[] categories); public byte getProficiency(); public void setProficiency(byte proficiency); TableColumn getColumn(); }azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableCellRefresher.java0000644000175000017500000000554211127543020026066 0ustar adrianadrianpackage org.gudy.azureus2.plugins.ui.tables; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.ui.swt.Utils; /** * * Provides a simple way to get a TableCell refreshed more often than the normal GUI refresh cycle * It always clocks at 100ms * as well as time synchronization methods for cells showing animated icons * @author olivier * */ public class TableCellRefresher { private static TableCellRefresher instance = null; private AEThread2 refresher; private Map mapCellsToColumn = new HashMap(); private long iterationNumber; private boolean inProgress = false; private AERunnable runnable; private TableCellRefresher() { runnable = new AERunnable() { public void runSupport() { try { Map cellsCopy; synchronized (mapCellsToColumn) { cellsCopy = new HashMap(mapCellsToColumn); mapCellsToColumn.clear(); } for (TableCell cell : cellsCopy.keySet()) { TableColumn column = (TableColumn) cellsCopy.get(cell); try { //cc.cell.invalidate(); if (column instanceof TableCellRefreshListener) { ((TableCellRefreshListener) column).refresh(cell); } } catch (Throwable t) { t.printStackTrace(); } } } finally { inProgress = false; } } }; refresher = new AEThread2("Cell Refresher",true) { public void run() { try { iterationNumber = 0; while (true) { if (mapCellsToColumn.size() > 0 && !inProgress) { inProgress = true; Utils.execSWTThread(runnable); } Thread.sleep(200); iterationNumber++; } }catch (Exception e) { e.printStackTrace(); } } }; refresher.start(); } private void _addColumnCell(TableColumn column,TableCell cell) { synchronized (mapCellsToColumn) { if (mapCellsToColumn.containsKey(cell)) { return; } mapCellsToColumn.put(cell, column); } } private int _getRefreshIndex(int refreshEvery100ms, int nbIndices) { if(refreshEvery100ms <= 0) return 1; if(nbIndices <= 0) return 1; return (int) ( (iterationNumber / refreshEvery100ms) % nbIndices); } private static synchronized TableCellRefresher getInstance() { if(instance == null) { instance = new TableCellRefresher(); } return instance; } //Add a cell to be refreshed within the next iteration //The cell will only get refreshed once public static void addCell(TableColumn column,TableCell cell) { getInstance()._addColumnCell(column,cell); } public static int getRefreshIndex(int refreshEvery100ms, int nbIndices) { return getInstance()._getRefreshIndex(refreshEvery100ms, nbIndices); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableContextMenuItem.java0000644000175000017500000000443410654744226026447 0ustar adrianadrian/* * Azureus - a Java Bittorrent client * 2004/May/16 TuxPaper * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.menus.MenuItemListener; /** Represents on context menu item for a table. */ public interface TableContextMenuItem extends MenuItem { /** * Adds a selection listener for this menu item. * * The {@link MenuItemListener#selected(MenuItem, Object)} method invoked * with the target being a {@link TableRow} instance. This will be one of * the items which was selected - this method will be invoked multiple * times with each item that was selected - if you want the entire selection * of items in one go, you should register the listener via * {@link #addMultiListener(MenuItemListener)}. * * @param l listener to be notified when user has selected the menu item. */ public void addListener(MenuItemListener l); /** * Adds a selection listener for this menu item. * * This differs from {@link #addListener(MenuItemListener)}, in that the * target object which will be passed to the listener will be an * array of {@link TableRow} objects, rather than just a single object. * * @param l listener to be notified when user has selected the menu item. * @since 2.5.0.2 */ public void addMultiListener(MenuItemListener l); /** * Retrieve the Table ID that the menu item belongs to * @return {@link TableManager}.TABLE_ constant */ public String getTableID(); }azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableCellMouseMoveListener.java0000644000175000017500000000251710640623240027567 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ui.tables; /** * A listener that triggers on mouse move events (see * {@link org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent}) that occur * on a TableCell. * * @see TableCell#addMouseListener(TableCellMouseMoveListener) * @see TableColumn#addCellMouseListener(TableCellMouseMoveListener) * * @author TuxPaper * @since 3.0.1.7 */ public interface TableCellMouseMoveListener extends TableCellMouseListener { } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableRow.java0000644000175000017500000000726310736661612024127 0ustar adrianadrian/* * File : TableRow.java * Created : 2004/Apr/30 * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; /** * This interface provides access to an Azureus table row. * * @author TuxPaper * @since 2.0.8.5 */ public interface TableRow { /** Retrieve the data object associated with the current table row. * * @return The return type is dependent upon which table the cell is for:
* TABLE_MYTORRENTS_*: {@link org.gudy.azureus2.plugins.download.Download} * object for the current row
* TABLE_TORRENT_PEERS: {@link org.gudy.azureus2.plugins.peers.Peer} * object for the current row
* TABLE_TORRENT_FILES: {@link org.gudy.azureus2.plugins.disk.DiskManagerFileInfo} * object for the current row
* TABLE_MYTRACKER: {@link org.gudy.azureus2.plugins.tracker.TrackerTorrent} * object for the current row
* TABLE_MYSHARES: {@link org.gudy.azureus2.plugins.sharing.ShareResource} * object for the current row
* remaining TABLE_* constants: undefined or null
*/ Object getDataSource(); /** Returns which table the row is being displayed in. * * @return {@link TableManager}.TABLE_* constant */ String getTableID(); /** * Change the row's foreground color. * * @param red red value (0 - 255) * @param green green value (0 - 255) * @param blue blue value (0 - 255) * @since 3.0.3.5 */ public void setForeground(int red, int green, int blue); /** * Change the row's foreground color * * @param rgb int array of red, green, and blue values. Null to reset to * default color * * @since 3.0.4.3 */ public void setForeground(int[] rgb); /** * Change the row's foreground color to the user's defined "error" color. * * @since 3.0.3.5 */ public void setForegroundToErrorColor(); /** Validility of the row's cells. * * @return True - Text is the same as last call. You do not need to update * unless you have new text to display.
* False - Cell-to-Datasource link has changed, and the text is * definitely not valid. */ boolean isValid(); /** Retrieve a cell based on its column name * * @param sColumnName Name/ID of column * @return TableCell object related to this row and the column specified */ TableCell getTableCell(String sColumnName); /** * Retrieve whether the row is selected by the user * * @return selection status */ boolean isSelected(); /** * Adds a listener that triggers when this TableRow has a mouse event. * * @param listener * * @since 3.0.1.7 */ public void addMouseListener(TableRowMouseListener listener); /** Remove a previously added TableRowMouseListener * * @param listener Previously added listener * @since 3.0.1.7 */ public void removeMouseListener(TableRowMouseListener listener); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/tables/TableRowRefreshListener.java0000644000175000017500000000166211072556246027151 0ustar adrianadrian/** * Created on Oct 6, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.tables; /** * @author TuxPaper * @created Oct 6, 2008 * */ public interface TableRowRefreshListener { public void rowRefresh(TableRow row); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIManager.java0000644000175000017500000002121511061141360022720 0ustar adrianadrian/* * Created on 19-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui; import java.io.File; import java.net.URL; import org.gudy.azureus2.plugins.PluginView; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.logging.LoggerChannel; import org.gudy.azureus2.plugins.ui.model.*; import org.gudy.azureus2.plugins.ui.SWT.SWTManager; import org.gudy.azureus2.plugins.ui.menus.MenuManager; import org.gudy.azureus2.plugins.ui.tables.TableManager; /** * Management tools for the user interface. * * @author parg */ public interface UIManager { /** * Gets a basic plugin view model that supports simple plugin requirements * After getting the model create the view using createPluginView * @param name name * @return BasicPluginViewModel * @deprecated Use createBasicPluginViewModel */ public BasicPluginViewModel getBasicPluginViewModel( String name ); /** * Creates a view from the model. It is then necessary to add it to the plugin * as any other PluginView * @param model * @return PluginView * @deprecated Use createBasicPluginViewModel */ public PluginView createPluginView( PluginViewModel model ); /** * * @param section_name * @return BasicPluginConfigModel * @since 2.1.0.0 */ public BasicPluginConfigModel createBasicPluginConfigModel( String section_name ); /** * Creates a basic plugin view model and adds it to the plugin in one step. * * @param parent_section * @param section_name see {@link org.gudy.azureus2.plugins.ui.config.ConfigSection}.SECTION_* * @return BasicPluginConfigModel * @since 2.1.0.0 */ public BasicPluginConfigModel createBasicPluginConfigModel( String parent_section, String section_name ); /** * * @return * @since 2.5.0.1 */ public PluginConfigModel[] getPluginConfigModels(); /** * Creates a basic plugin view model and adds it to the plugin in one step. * view is placed inside the plugins section of the configuration page. * * @param name The name for the view (this should be localised text, rather * than a message string). * @return BasicPluginViewModel * @since 2.1.0.2 */ public BasicPluginViewModel createBasicPluginViewModel( String name ); /** * Creates a {@link BasicPluginViewModel} object primarily to be used for * storing logging output. This is just a shortcut way of creating a log * view for the logger channel. * * @param channel The {@link LoggerChannel} to associate with. * @param use_plugin_name If set to true, the log view will be * taken from the plugin name, if false, it will be taken from * the channel name. * @since 3.1.1.1 */ public BasicPluginViewModel createLoggingViewModel( LoggerChannel channel, boolean use_plugin_name ); /** * * @param data * @throws UIException * @since 2.1.0.0 */ public void copyToClipBoard( String data ) throws UIException; /** * Retrieve the Table Manager * * @return Table management functions * @since 2.1.0.0 */ public TableManager getTableManager(); /** * * @param title_resource * @param message_resource * @param contents * @since 2.3.0.5 */ public void showTextMessage( String title_resource, String message_resource, String contents ); /** * * @param title_resource * @param message * @param message_map - see UIManagerEvent.MT_x * @return selected value * @since 3.0.5.3 */ public long showMessageBox( String title_resource, String message_resource, long message_map ); /** * @since 2.3.0.6 * @param url */ public void openURL( URL url ) throws UIException; /** * * @param torrent * @since 3.0.5.3 */ public void openTorrent( Torrent torrent ); /** Retrieve a class of SWT specific functions * * @deprecated * @return SWTManager * * @since 2.1.0.0 */ public SWTManager getSWTManager(); /** * Open Config View to the section specified * * @param sectionID ID of section to open to. * {@link org.gudy.azureus2.plugins.ui.config.ConfigSection}.SECTION_* constants * @return true-Section opened; false-Section invalid or UI does not support config views * * @since 2.3.0.7 */ public boolean showConfigSection(String sectionID); /** * Retrieve the menu manager. * * @return Menu management functions * @since 3.0.0.7 */ public MenuManager getMenuManager(); /** * UIs should support generic UI-agnostic views such as the basic config model by default. The can also * expose a UI-specific plugin interface to plugins via the UIInstance (see interface for details). * To get access to this it is necessary to use the UIManagerListener */ /** * attach a new UI * * @param factory * @throws UIException * * @since 2.3.0.5 */ public void attachUI( UIInstanceFactory factory ) throws UIException; /** * detach a UI - can fail if the UI doesn't support detaching * * @param factory * @throws UIException * * @since 2.3.0.5 */ public void detachUI( UIInstanceFactory factory ) throws UIException; /** * * @param listener * * @since 2.3.0.5 */ public void addUIListener( UIManagerListener listener ); /** * * @param listener * * @since 2.3.0.5 */ public void removeUIListener( UIManagerListener listener ); /** * * @param listener * * @since 2.3.0.5 */ public void addUIEventListener( UIManagerEventListener listener ); /** * * @param listener * * @since 2.3.0.5 */ public void removeUIEventListener( UIManagerEventListener listener ); /** * Returns true if there any user interfaces currently attached to * Azureus. * * Note that this value may change over time, and that at the point when a * plugin is being initialised, there is no guarantee over whether if the * user interfaces will have been created yet or not. * * If you want to monitor what user interfaces are being attached / detached * from Azureus, you should add a UIListener to this object. * * @since 3.0.0.7 */ public boolean hasUIInstances(); /** * Returns an array of all currently attached user interfaces. * * Note that this value may change over time, and that at the point when a * plugin is being initialised, there is no guarantee over whether if the * user interfaces will have been created yet or not. * * If you want to monitor what user interfaces are being attached / detached * from Azureus, you should add a UIListener to this object. * * @since 3.0.0.7 */ public UIInstance[] getUIInstances(); /** * Retrieves a {@link UIInputReceiver} from any interface available, or * returns null if one is not available. This is a convenience * method to allow you to grab an instance without having to iterate over * any attached interfaces. * * @see UIInstance#getInputReceiver() * @since 3.0.5.3 */ public UIInputReceiver getInputReceiver(); /** * Retrieves a {@link UIMessage} from any interface available, or * returns null if one is not available. This is a convenience * method to allow you to grab an instance without having to iterate over * any attached interfaces. * * @see UIInstance#createMessage() * @since 3.0.5.3 */ public UIMessage createMessage(); /** * Opens up the file using the associated application. * * @param file The file to open. * @since 3.0.5.3 */ public void openFile(File file); /** * Shows the file in a file explorer application in its parent folder. * * @param file The file to show. * @since 3.0.5.3 */ public void showFile(File file); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/sidebar/0000755000175000017500000000000011310377632021667 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/ui/sidebar/SideBarEntry.java0000644000175000017500000000302411145466612025067 0ustar adrianadrian/** * Created on Aug 13, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.sidebar; /** * @author TuxPaper * @created Aug 13, 2008 * */ public interface SideBarEntry { public String getParentID(); public Object getDatasource(); public boolean isCloseable(); public Class getIViewClass(); public Class[] getIViewClassArgs(); public Object[] getIViewClassVals(); public String getId(); public SideBarVitalityImage addVitalityImage(String imageID); /** * @param l * * @since 4.1.0.3 */ void addListener(SideBarCloseListener l); /** * @param l * * @since 4.1.0.3 */ void removeListener(SideBarCloseListener l); /** * @param l * * @since 4.1.0.3 */ void addListener(SideBarOpenListener l); /** * @param l * * @since 4.1.0.3 */ void removeListener(SideBarOpenListener l); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/sidebar/SideBarOpenListener.java0000644000175000017500000000167211145466614026406 0ustar adrianadrian/** * Created on Dec 3, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.sidebar; /** * @author TuxPaper * @created Dec 3, 2008 * */ public interface SideBarOpenListener { public void sideBarEntryOpen(SideBarEntry entry); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/sidebar/SideBarCloseListener.java0000644000175000017500000000167311145466614026553 0ustar adrianadrian/** * Created on Sep 24, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.sidebar; /** * @author TuxPaper * @created Sep 24, 2008 * */ public interface SideBarCloseListener { public void sidebarClosed(SideBarEntry entry); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/sidebar/SideBarVitalityImageListener.java0000644000175000017500000000170611063667750030256 0ustar adrianadrian/** * Created on Sep 15, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.sidebar; /** * @author TuxPaper * @created Sep 15, 2008 * */ public interface SideBarVitalityImageListener { public void sbVitalityImage_clicked(int x, int y); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/sidebar/SideBarVitalityImage.java0000644000175000017500000000243711156376172026550 0ustar adrianadrian/** * Created on Sep 15, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.sidebar; /** * @author TuxPaper * @created Sep 15, 2008 * */ public interface SideBarVitalityImage { public String getImageID(); public void setImageID(String id ); public SideBarEntry getSideBarEntry(); public void addListener(SideBarVitalityImageListener l); public void setToolTip(String tooltip); public void setVisible(boolean visible); public boolean isVisible(); public void triggerClickedListeners(int x, int y); public int getAlignment(); public void setAlignment(int a); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/sidebar/SideBarDropListener.java0000644000175000017500000000210111301136110026350 0ustar adrianadrian/** * Created on Feb 13, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ui.sidebar; /** * @author TuxPaper * @created Feb 13, 2009 * */ public interface SideBarDropListener { /** * @param entry * @param droppedObject * @return true if you handled it, false if you didn't */ public boolean sideBarEntryDrop(SideBarEntry entry, Object droppedObject); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIInputReceiver.java0000644000175000017500000001602011267524616024151 0ustar adrianadrian/* * Created on 11-Nov-2006 * Created by Allan Crooks * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ui; /** * This interface provides a mechanism to get some textual input from a user. * *

* * There are various methods which allow you to customise the appearance of * the prompt that the user receives - subclasses may provide additional * methods to customise the interface too. * *

* * Once the object has been set up, you then call the {@link #prompt}method. This * will ask the user for some input based on the values previously given. * It will only return once the user has either given some validated input, * or has indicated they don't want to give any input (like pressing a * Cancel button). * *

* * The {@link #hasSubmittedText()} and {@link #getSubmittedText()} methods can then * be invoked to retrieve the input (if the user has submitted any). * *

* * There are various methods which have a setXXX and setLocalisedXXX * counterparts. The setXXX methods will attempt to translate the given * string to a localised representation of it - the setLocalisedXXX method * will assume that the localisation has already been done, and leave it intact. * *

Note: Only for implementation by Azureus, not plugins.

*/ public interface UIInputReceiver { /** * Sets the title for the text entry input. For some interfaces, this * means that a window will be presented, and the title of the window * will be the value passed here. */ public void setTitle(String title); /** * Sets the title for the text entry input. For some interfaces, this * means that a window will be presented, and the title of the window * will be the value passed here. */ public void setLocalisedTitle(String title); /** * Sets the message to display for the text entry input. This will * normally be displayed near the position where the text will be * entered - this method is usually used to present the user with * an indication of what to enter. * *

* * For multiple lines, see {@link #setMessages}. */ public void setMessage(String message); /** * Sets the message to display for the text entry input. This will * normally be displayed near the position where the text will be * entered - this method is usually used to present the user with * an indication of what to enter. * *

* * For multiple lines, see {@link #setLocalisedMessages}. */ public void setLocalisedMessage(String message); /** * Sets the message to display for the text entry input. This will * normally be displayed near the position where the text will be * entered - this method is usually used to present the user with * an indication of what to enter. * *

* * The value passed here will be an array of strings - each string * will be usually outputted on its own line. The last value in * the array will usually be the message displayed closest to the * users prompt. */ public void setMessages(String[] messages); /** * Sets the message to display for the text entry input. This will * normally be displayed near the position where the text will be * entered - this method is usually used to present the user with * an indication of what to enter. * *

* * The value passed here will be an array of strings - each string * will be usually outputted on its own line. The last value in * the array will usually be the message displayed closest to the * users prompt. */ public void setLocalisedMessages(String[] messages); /** * This sets a value to be displayed as pre-entered text for the * input. This may be called if the caller wants to suggest a * value for the user to use, or if the caller wants to provide * a previous value (for example). * *

* * The text may appear in the same location as the text should * be entered (allowing it to be directly overwritten or submitted * immediately) - but some interfaces may not support this. * *

* * A flag should be passed indicating whether the pre-entered text * is being entered as a suggestion for a value, or whether it is * an old value being currently stored. Some interfaces may choose * to differentiate between the two. * * @param text The text to pre-enter. * @param as_suggested true if the value is a suggested * input value, false if it is an old value. */ public void setPreenteredText(String text, boolean as_suggested); /** * Indicates whether to allow multi-line input. * Default behaviour is to not allow multiple lines. */ public void setMultiLine(boolean multiline); /** * Indicates whether to keep whitespace are kept when input is entered, * or whether to strip it out. Default behaviour is to strip whitespace. */ public void maintainWhitespace(boolean keep_whitespace); /** * Indicates whether blank input can be entered. */ public void allowEmptyInput(boolean empty_input); /** * Sets the UIInputValidator for this object. This allows an external * object to validate or reject input submitted by the user. * *

* * By default, there is no input validator associated with a * UIInputReceiver, meaning all input is allowed. * * @see UIInputValidator */ public void setInputValidator(UIInputValidator validator); /** * This prompts the user for input. This method will not return until * the user has either entered valid input, or signalled they want to * cancel entering any data. * * @deprecated Use {@link #prompt(UIInputReceiverListener)} */ @Deprecated public void prompt(); /** * This prompts the user for input and returns immediately. When the user * has closed the input ui, the {@link UIInputReceiverListener} will * be triggered * * @param receiver_listener * @since 4.2.0.9 */ public void prompt(UIInputReceiverListener receiver_listener); /** * Returns true if the user submitted any data. */ public boolean hasSubmittedInput(); /** * Returns the string if the user submitted any data - you should check * for this by calling {@link #hasSubmittedInput()} first. */ public String getSubmittedInput(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIMessage.java0000644000175000017500000001071311017134544022742 0ustar adrianadrian/* * Created on 12 Apr 2008 * Created by Allan Crooks * Copyright (C) 2008 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ui; /** * This interface provides a mechanism to display a message to the user, * potentially to ask the user a question. * *

* * There are four main elements to set: *

    *
  • the message type - defaults to MSG_NONE. *
  • the input type - defaults to INPUT_OK. *
  • the message title. *
  • the message text. *
* * In the case of the main SWT interface, the use of this object will present * a message box to a user. The message type indicates what sort of icon to display, * the input type indicates what buttons are present, the message title is the message * box title and the message text is the main message to be displayed. * *

* * There are various methods which have a setXXX and setLocalisedXXX * counterparts. The setXXX methods will attempt to translate the given * string to a localised representation of it - the setLocalisedXXX method * will assume that the localisation has already been done, and leave it intact. * *

Note: Only for implementation by Azureus, not plugins.

* * @author Allan Crooks * @since 3.0.5.3 */ public interface UIMessage { public int MSG_NONE = 0; public int MSG_ERROR = 1; public int MSG_INFO = 2; public int MSG_WARN = 3; public int MSG_QUESTION = 4; public int MSG_WORKING = 5; public int INPUT_OK = 0; public int INPUT_OK_CANCEL = 1; public int INPUT_YES_NO = 2; public int INPUT_YES_NO_CANCEL = 3; public int INPUT_RETRY_CANCEL = 4; public int INPUT_RETRY_CANCEL_IGNORE = 5; public int ANSWER_OK = 0; public int ANSWER_CANCEL = 1; public int ANSWER_YES = 2; public int ANSWER_NO = 3; public int ANSWER_RETRY = 4; public int ANSWER_IGNORE = 5; public int ANSWER_ABORT = ANSWER_CANCEL; /** * Sets what type of message to display - use one of the MSG_ * constants defined here. */ public void setMessageType(int msg_type); /** * Sets what type of input is allowed - use one of the INPUT_ * constants defined here. */ public void setInputType(int input_type); /** * Sets the title for the message. For some interfaces, this * means that a window will be presented, and the title of the window * will be the value passed here. */ public void setTitle(String title); /** * Sets the title for the message. For some interfaces, this * means that a window will be presented, and the title of the window * will be the value passed here. */ public void setLocalisedTitle(String title); /** * Sets the main message to display the user. * * For multiple lines, see {@link #setMessages}. */ public void setMessage(String message); /** * Sets the main message to display the user. * * For multiple lines, see {@link #setLocalisedMessages}. */ public void setLocalisedMessage(String message); /** * Sets the main message to display the user. * *

* * The value passed here will be an array of strings - each string * will be usually outputted on its own line. */ public void setMessages(String[] messages); /** * Sets the main message to display the user. * *

* * The value passed here will be an array of strings - each string * will be usually outputted on its own line. */ public void setLocalisedMessages(String[] messages); /** * This displays the message to the user. The way that the user * acknowledges will be the method result - which will be one of * the ANSWER_ constants defined here. */ public int ask(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIInputValidator.java0000644000175000017500000000324511003263732024322 0ustar adrianadrian/* * Created on 11-Nov-2006 * Created by Allan Crooks * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ui; /** * Interface class which provides a way to validate or reject input provided * by a user. This is mainly to be used with {@link UIInputReceiver}. * *

Note: This interface is intended to be implemented by plugins.

*/ public interface UIInputValidator { /** * Validates a input string from the user. This function has to return * a localised string message indicating why the given string is not * valid. If the string is valid, the function should return null. * *

* * Note - the returned string in the case of invalid input must be * localised - no translating of the string returned will take place. */ public String validate(String input); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIManagerEventListener.java0000644000175000017500000000224510373051006025434 0ustar adrianadrian/* * Created on 11-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui; public interface UIManagerEventListener { /** * Return true if the event has been handled * @param event * @return */ public boolean eventOccurred( UIManagerEvent event ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIManagerEvent.java0000644000175000017500000001004311117455236023733 0ustar adrianadrian/* * Created on 11-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui; public interface UIManagerEvent { public static final int MT_NONE = 0x00000000; public static final int MT_OK = 0x00000001; public static final int MT_CANCEL = 0x00000002; public static final int MT_YES = 0x00000004; public static final int MT_NO = 0x00000008; public static final int ET_SHOW_TEXT_MESSAGE = 1; // data is String[] - title, message, text public static final int ET_OPEN_TORRENT_VIA_FILE = 2; // data is File public static final int ET_OPEN_TORRENT_VIA_URL = 3; // data is Object[]{URL,URL,Boolean} - { torrent_url, referrer url, auto_download, Map request_properties} public static final int ET_PLUGIN_VIEW_MODEL_CREATED = 4; // data is PluginViewModel (or subtype) public static final int ET_PLUGIN_CONFIG_MODEL_CREATED = 5; // data is PluginConfigModel (or subtype) public static final int ET_COPY_TO_CLIPBOARD = 6; // data is String public static final int ET_PLUGIN_VIEW_MODEL_DESTROYED = 7; // data is PluginViewModel (or subtype) public static final int ET_PLUGIN_CONFIG_MODEL_DESTROYED = 8; // data is PluginConfigModel (or subtype) public static final int ET_OPEN_URL = 9; // data is URL public static final int ET_CREATE_TABLE_COLUMN = 10; // data is String[] - table_id, cell_id: result is TableColumn public static final int ET_ADD_TABLE_COLUMN = 11; // data is TableColumn previously created public static final int ET_ADD_TABLE_CONTEXT_MENU_ITEM = 12; // data is TableContextMenuItem public static final int ET_SHOW_CONFIG_SECTION = 13; // data is String - section id public static final int ET_ADD_TABLE_CONTEXT_SUBMENU_ITEM = 14; // data is TableContextMenuItem[] - child, parent public static final int ET_ADD_MENU_ITEM = 15; // data is MenuItem public static final int ET_ADD_SUBMENU_ITEM = 16; // data is MenuItem[] - child, parent public static final int ET_REMOVE_TABLE_CONTEXT_MENU_ITEM = 17; // data is MenuItem public static final int ET_REMOVE_TABLE_CONTEXT_SUBMENU_ITEM = 18; // data is MenuItem[] - child, parent public static final int ET_REMOVE_MENU_ITEM = 19; // data is MenuItem public static final int ET_REMOVE_SUBMENU_ITEM = 20; // data is MenuItem[] - child, parent public static final int ET_SHOW_MSG_BOX = 21; // data is Object[]{ String,String,Long} - title, message, MT options public static final int ET_OPEN_TORRENT_VIA_TORRENT = 22; // data is Torrent public static final int ET_FILE_SHOW = 23; // data is File public static final int ET_FILE_OPEN = 24; // data is File public static final int ET_REGISTER_COLUMN = 25; // data is Class, String, TableColumnCreationListener public static final int ET_UNREGISTER_COLUMN = 26; // data is Class, String, TableColumnCreationListener public static final int ET_CALLBACK_MSG_SELECTION = 100; // data is Long - MT_OK etc public int getType(); public Object getData(); public void setResult( Object result ); public Object getResult(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIInstanceFactory.java0000644000175000017500000000316310373051006024446 0ustar adrianadrian/* * Created on 04-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ui; import org.gudy.azureus2.plugins.PluginInterface; public interface UIInstanceFactory { /** * Some UI instances need to understand which plugin they are associated with. This method * gives the opportunity to customise the UIInstance returned to a plugin so that operations * on it can take the appropriate actions */ public UIInstance getInstance( PluginInterface plugin_interface ); /** * This method will be called by the UI manager when detaching the UI to permit the action to be * vetoed/any detach logic to occur. It should not be directly called by the plugin code */ public void detach() throws UIException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/SWT/0000755000175000017500000000000011310377616020735 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/ui/SWT/SWTManager.java0000644000175000017500000000577610307201604023553 0ustar adrianadrian/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.ui.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.graphics.Image; import org.gudy.azureus2.plugins.PluginView; /** Evil SWT Specific stuff that plugins may need access to * * @author TuxPaper * @deprecated use {@link org.gudy.azureus2.ui.swt.plugins.UISWTInstance} */ public interface SWTManager { /** Retrieve the SWT Display object that Azureus uses (when in SWT mode). * If you have a thread that does some periodic/asynchronous stuff, Azureus * will crashes with and 'InvalidThreadAccess' exception unless you * embed your calls in a Runnable, and use getDisplay().aSyncExec(Runnable r); * * @return SWT Display object that Azureus uses * * @since 2.1.0.0 */ public Display getDisplay(); /** Creates an UIImageSWT object with the supplied SWT Image * * @param img Image to assign to the object * @return a new UIImagetSWT object * * @since 2.1.0.0 */ public GraphicSWT createGraphic(Image img); /** * A Plugin might call this method to add a View to Azureus's views * The View will be accessible from View > Plugins > View name * @param view The PluginView to be added * * @since 2.1.0.2 */ public void addView(PluginView view); /** * A Plugin might call this method to add a View to Azureus's views * The View will be accessible from View > Plugins > View name * @param view The PluginView to be added * @param autoOpen Whether the plugin should auto-open at startup * * @since 2.1.0.2 */ public void addView(PluginView view, boolean autoOpen); /** * A Plugin might call this method to load an image from * a resource (eg: "org/my_name/my_plugin/images/te_image.gif" * @see getImage(String name) * @param resource the resource path to the image * @param name the name used for the image, please use names starting with your plugin name. * @return true is the image was correctly loaded * @since 2.1.0.6 */ //public boolean loadImage(String resource,String name); /** * Once an image is loaded (@see loadImage(String resource,String name) ) * a plugin can retrieve it by calling this method. * * @param name the name used in loadImage to identify the image. * @return the image * */ //public Image getImage(String name); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/SWT/GraphicSWT.java0000644000175000017500000000320110373051040023533 0ustar adrianadrian/* * Created on 2004/May/23 * Created by TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ui.SWT; import org.gudy.azureus2.plugins.ui.Graphic; import org.eclipse.swt.graphics.Image; /** An SWT image to be used in Azureus * * @see SWTManager#createGraphic * @deprecated use {@link org.gudy.azureus2.ui.swt.plugins.UISWTGraphic} */ public interface GraphicSWT extends Graphic { /** Retrieve the Image object * * @return image that is stored in this object */ public Image getImage(); /** Sets the image stored in this object to the supplied parameter. * * @param img new image to be stored in this object * @return true - Image Set
* false - Image already set to supplied parameter */ public boolean setImage(Image img); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ui/UIRuntimeException.java0000644000175000017500000000210711012741706024655 0ustar adrianadrian/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.ui; /** Like UIException, except does not require one to declare or catch it. * * @author TuxPaper * @since 2.0.8.5 */ public class UIRuntimeException extends RuntimeException { public UIRuntimeException( String str, Throwable cause ) { super(str,cause); } public UIRuntimeException( String str) { super(str); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/0000755000175000017500000000000011310377616021340 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentException.java0000644000175000017500000000231611012741710025506 0ustar adrianadrian/* * File : TorrentException.java * Created : 02-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ public class TorrentException extends Exception { public TorrentException() { super(); } public TorrentException( String str ) { super(str); } public TorrentException( Throwable cause ) { super(cause); } public TorrentException( String str, Throwable cause ) { super(str,cause); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentAnnounceURLListSet.java0000644000175000017500000000202710021435642027213 0ustar adrianadrian/* * File : TorrentAnnounceURLListSet.java * Created : 03-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ import java.net.URL; public interface TorrentAnnounceURLListSet { public URL[] getURLs(); public void setURLs( URL[] urls ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentAttribute.java0000644000175000017500000000525610526740110025523 0ustar adrianadrian/* * Created on 23-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ public interface TorrentAttribute { public static final String TA_CATEGORY = "Category"; public static final String TA_NETWORKS = "Networks"; public static final String TA_PEER_SOURCES = "PeerSources"; public static final String TA_TRACKER_CLIENT_EXTENSIONS = "TrackerClientExtensions"; public static final String TA_SHARE_PROPERTIES = "ShareProperties"; // private=true/false;dht_backup=true/false public static final String TA_CONTENT_MAP = "ContentMap"; /** * Controls the displayed name of a download. * * @since 2.5.0.0 */ public static final String TA_DISPLAY_NAME = "DisplayName"; /** * The user-defined comment for a download. * * @since 2.5.0.1 */ public static final String TA_USER_COMMENT = "UserComment"; /** * Defines a relative file path for this download - this attribute is used * when moving downloads for completion or removal - this path is relative * to the default download directories. * * @since 2.5.0.1 */ public static final String TA_RELATIVE_SAVE_PATH = "RelativePath"; public String getName(); /** * Returns the currently defined values for this attribute * @return */ public String[] getDefinedValues(); /** * Adds a new value to the attribute set * @param name */ public void addDefinedValue( String name ); /** * Removes a value from the attribute set * @param name */ public void removeDefinedValue( String name ); public void addTorrentAttributeListener( TorrentAttributeListener l ); public void removeTorrentAttributeListener( TorrentAttributeListener l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentEncodingException.java0000644000175000017500000000316311012741710027156 0ustar adrianadrian/* * Created on 26-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ public class TorrentEncodingException extends TorrentException { // needs to be public for xml serialisation public String[] valid_charsets; public String[] valid_names; public TorrentEncodingException( String[] charsets, String[] names ) { super("Torrent encoding selection required"); valid_charsets = charsets; valid_names = names; } public TorrentEncodingException( String str, Throwable cause ) { super( str, cause ); } public String[] getValidCharsets() { return( valid_charsets ); } public String[] getValidTorrentNames() { return( valid_names ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/Torrent.java0000644000175000017500000001175110734652270023646 0ustar adrianadrian/* * File : Torrent.java * Created : 08-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ import java.io.File; import java.net.URL; import java.util.Map; public interface Torrent { public String getName(); public URL getAnnounceURL(); public void setAnnounceURL( URL url ); /** * get the announce list for multi-tracker torrents. Will always be present but * may contain 0 sets which means that this is not a multi-tracker torrent * @return */ public TorrentAnnounceURLList getAnnounceURLList(); public byte[] getHash(); /** * If size is 0 then this is an "external" torrent and we only know its hash (and name * constructed from hash). e.g. we don't know file details * @return */ public long getSize(); public String getComment(); public void setComment( String comment ); public long getCreationDate(); public String getCreatedBy(); public long getPieceSize(); public long getPieceCount(); public byte[][] getPieces(); public TorrentFile[] getFiles(); public String getEncoding(); public void setEncoding( String encoding) throws TorrentEncodingException; public void setDefaultEncoding() throws TorrentEncodingException; /** * Access to top-level properties in the torrent * @param name * @return */ public Object getAdditionalProperty( String name ); /** * Removal all non-standard properties (excluding plugin-properties below) * @return */ public Torrent removeAdditionalProperties(); /** * Set a property specific to this plugin * @param name * @param value */ public void setPluginStringProperty( String name, String value ); /** * Get a property specific to this plugin * @param name * @return */ public String getPluginStringProperty( String name ); /** * Sets a map property in the torrent, retrievable via getMapProperty * @param name should be unique across plugins (i.e. prefix it with something unique) * @param value bencodable Map value */ public void setMapProperty( String name, Map value ); /** * Gets a previously set map value * @see setMapProperty * @param name should be unique across plugins (i.e. prefix it with something unique) * @return */ public Map getMapProperty( String name ); /** * A decentralised torrent uses the DHT only as a "tracker" * @return */ public boolean isDecentralised(); /** * Decentralised backup permits the DHT to be used as a tracker when the * "real" tracker is unavailable * @return */ public boolean isDecentralisedBackupEnabled(); /** * By default torrents with OK trackers are not tracked in the DHT. This allows a specific * torrent to be marked so that it will be * @param requested */ public void setDecentralisedBackupRequested( boolean requested ); public boolean isDecentralisedBackupRequested(); /** * A private torrent is either explicitly private via info/private or * has decentralised backup disabled and peer exchange disabled * @return */ public boolean isPrivate(); public void setPrivate( boolean priv ); /** * @since 2501 * @return */ public boolean wasCreatedByUs(); /** * Gets the magnet URI for the torrent - throws exception if not available * @return */ public URL getMagnetURI() throws TorrentException; public Map writeToMap() throws TorrentException; public void writeToFile( File file ) throws TorrentException; public byte[] writeToBEncodedData() throws TorrentException; /** * Saves the torrent to its persistent location * @throws TorrentException */ public void save() throws TorrentException; /** * sets the torrent complete - i.e. ready for seeding. Doing this avoids * a recheck on torrent addition * @param data_dir * @throws TorrentException */ public void setComplete( File data_dir ) throws TorrentException; public boolean isComplete(); /** * Returns true if the torrent is a single file torrent, * false if it is a multi file torrent. * * @since 3.0.4.3 */ public boolean isSimpleTorrent(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentCreatorListener.java0000644000175000017500000000233410457571112026666 0ustar adrianadrian/* * Created on 19 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.torrent; public interface TorrentCreatorListener { public void reportPercentageDone( int percent ); public void reportActivity( String activity ); public void complete( Torrent torrent ); public void failed( TorrentException cause ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentAnnounceURLList.java0000644000175000017500000000376610021474110026543 0ustar adrianadrian/* * File : TorrentAnnounceURLList.java * Created : 03-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ import java.net.*; public interface TorrentAnnounceURLList { public TorrentAnnounceURLListSet[] getSets(); public void setSets( TorrentAnnounceURLListSet[] sets ); /** * create a new set. This is NOT added to the list, you have to manually add it afterwards * @param urls * @return */ public TorrentAnnounceURLListSet create( URL[] urls ); /** * Adds a set to the torrent at the end of the list. If the torrent currently has NO announcelist * entries then the existing "announce-url" is also added to the set as the first entry. To avoid * this behaviour manipulate the sets yourself and use setSets * Duplicate set entries are ignored * @param urls */ public void addSet( URL[] urls ); /** * Adds a set to the torrent at the front of the list. If the torrent currently has NO announcelist * entries then the existing "announce-url" is also added to the set as the first entry. To avoid * this behaviour manipulate the sets yourself and use setSets * Duplicate set entries are ignored * @param urls */ public void insertSetAtFront( URL[] urls ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentManagerListener.java0000644000175000017500000000214710373051034026634 0ustar adrianadrian/* * Created on 24-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ public interface TorrentManagerListener { public void event( TorrentManagerEvent ev ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentAttributeListener.java0000644000175000017500000000215310373051034027222 0ustar adrianadrian/* * Created on 08-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ public interface TorrentAttributeListener { public void event( TorrentAttributeEvent ev ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentManagerEvent.java0000644000175000017500000000211610373051034026124 0ustar adrianadrian/* * Created on 24-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ public interface TorrentManagerEvent { public Object getData(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentFile.java0000644000175000017500000000172507766363260024457 0ustar adrianadrian/* * File : TorrentFile.java * Created : 12-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ public interface TorrentFile { public String getName(); public long getSize(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentManager.java0000644000175000017500000001241711021162316025124 0ustar adrianadrian/* * File : TorrentManager.java * Created : 28-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ import java.net.URL; import java.io.File; import java.io.InputStream; public interface TorrentManager { /** * Preserve no additional Attributes * value is 0 * @since 3009 * @author Damokles */ public static final int PRESERVE_NONE = 0; /** * Preserve the encoding Attribute * value is 0x00000001 * @since 3009 * @author Damokles */ public static final int PRESERVE_ENCODING = 0x00000001; /** * Preserve all additional Attributes * value is 0xffffffff; * @since 3009 * @author Damokles */ public static final int PRESERVE_ALL = 0xffffffff; public TorrentDownloader getURLDownloader( URL url ) throws TorrentException; public TorrentDownloader getURLDownloader( URL url, String user_name, String password ) throws TorrentException; /** * decodes a torrent encoded using the normal "bencoding" rules from a file * @param file * @return * @throws TorrentException */ public Torrent createFromBEncodedFile( File file ) throws TorrentException; /** * decodes a torrent encoded using the normal "bencoding" rules from a file but discards the piece * hashes to save memory. note that this means that if something reads the hashes they will be * re-read from the torrent file and if the file has since been deleted things go smelly * @param file * @param for_seeding reduces memory usage by discarding piece hashes * @return */ public Torrent createFromBEncodedFile( File file, boolean for_seeding ) throws TorrentException; /** * decodes a torrent encoded using the normal "bencoding" rules from an InputStream * @param file * @return * @throws TorrentException */ public Torrent createFromBEncodedInputStream( InputStream data ) throws TorrentException; /** * decodes a torrent encoded using the normal "bencoding" rules from a byte array * @param file * @return * @throws TorrentException */ public Torrent createFromBEncodedData( byte[] data ) throws TorrentException; /** * decodes a torrent encoded using the normal "bencoding" rules from a file * @param file * @param preserve PRESERVE_* flags * @return * @throws TorrentException * @author Damokles * @since 3009 */ public Torrent createFromBEncodedFile( File file, int preserve ) throws TorrentException; /** * decodes a torrent encoded using the normal "bencoding" rules from an InputStream * @param data * @param preserve PRESERVE_* flags * @return * @throws TorrentException * @author Damokles * @since 3009 */ public Torrent createFromBEncodedInputStream( InputStream data, int preserve ) throws TorrentException; /** * decodes a torrent encoded using the normal "bencoding" rules from a byte array * @param data * @param preserve PRESERVE_* flags * @return * @throws TorrentException * @author Damokles * @since 3009 */ public Torrent createFromBEncodedData( byte[] data, int preserve ) throws TorrentException; /** * creates a new torrent from an input file * @param data * @return * @throws TorrentException */ public Torrent createFromDataFile( File data, URL announce_url ) throws TorrentException; public Torrent createFromDataFile( File data, URL announce_url, boolean include_other_hashes ) throws TorrentException; public TorrentCreator createFromDataFileEx( File data, URL announce_url, boolean include_other_hashes ) throws TorrentException; /** * Gives access to the currently defined torrent attributes. As of 2.1.0.2 * only "category" is defined, however in the future more could be added * such as "quality", "bit rate" etc. * @return */ public TorrentAttribute[] getDefinedAttributes(); /** * Gives access to the standard built-in attributes * @param name * @return */ public TorrentAttribute getAttribute( String name ); /** * Gives access to/creates arbitrary String attributes for plugins to use. The * attribute will be specific to the plugin, so you can use short torrent names * like "name", you won't need to add the plugin ID or any other sort of unique * identifier to the attribute name. * * @param name * @return */ public TorrentAttribute getPluginAttribute( String name ); public void addListener( TorrentManagerListener l ); public void removeListener( TorrentManagerListener l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentCreator.java0000644000175000017500000000230010457433256025157 0ustar adrianadrian/* * Created on 19 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.torrent; public interface TorrentCreator { public void start(); public void cancel(); public void addListener( TorrentCreatorListener listener ); public void removeListener( TorrentCreatorListener listener ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentAttributeEvent.java0000644000175000017500000000247310373051034026523 0ustar adrianadrian/* * Created on 08-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ public interface TorrentAttributeEvent { public static final int ET_ATTRIBUTE_VALUE_ADDED = 1; // data is String value public static final int ET_ATTRIBUTE_VALUE_REMOVED = 2; // data is String value public int getType(); public TorrentAttribute getAttribute(); public Object getData(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/torrent/TorrentDownloader.java0000644000175000017500000000271010101623006025637 0ustar adrianadrian/* * File : TorrentDownloader.java * Created : 28-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.torrent; /** * @author parg * */ public interface TorrentDownloader { /** * Downloads and prompts the user/guesses the torrent encoding * @return * @throws TorrentException */ public Torrent download() throws TorrentException; /** * Downloads and tries to use the supplied encoding. If the supplied encoding isn't * valed then a TorrentEncodingException is thrown detailing the valid ones * * @param encoding use "System" for system encoding * @return * @throws TorrentException */ public Torrent download( String encoding ) throws TorrentException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/LaunchablePlugin.java0000644000175000017500000000305210373051030023706 0ustar adrianadrian/* * Created on 25-Jul-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins; public interface LaunchablePlugin extends Plugin { /** * Invoked before azureus core is started to set defaults such as application details */ public void setDefaults( String[] args ); /** * Some environments have requirements regarding the main application thread and processing * on it. In particular SWT on OSX insists that the SWT dispatch thread. When this thread * is returned from Azureus is either stopper or restarted, depending on the return value * @return whether to close down or restart (true->restart) */ public boolean process(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ipfilter/0000755000175000017500000000000011310377616021461 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/ipfilter/IPBlocked.java0000644000175000017500000000224110060700704024104 0ustar adrianadrian/* * File : IPBlocked.java * Created : 05-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ipfilter; /** * @author parg * */ public interface IPBlocked { public String getBlockedIP(); /** * returns the torrent name the IP was blocked trying to access * @return */ public String getBlockedTorrentName(); public long getBlockedTime(); public IPRange getBlockingRange(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ipfilter/IPBanned.java0000644000175000017500000000246110550555322023744 0ustar adrianadrian/* * File : IPBanned.java * Created : 08-Jan-2007 * By : jstockall * Copyright (C) 2007 Aelitis, All Rights Reserved. * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.ipfilter; /** * @author jstockall * @since 2.5.0.2 */ public interface IPBanned { public String getBannedIP(); /** * returns the torrent name the IP was banned by the user * @return */ public String getBannedTorrentName(); public long getBannedTime(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ipfilter/IPRange.java0000644000175000017500000000326010046571416023611 0ustar adrianadrian/* * File : IPRange.java * Created : 05-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ipfilter; /** * @author parg * IPRange instances implement Comparable. Rules are identical start+end IPs */ public interface IPRange extends Comparable { public String getDescription(); public void setDescription( String str ); /** * For a range to be usable it has to be valid. To make it valid you have * to call checkValid. Failure to do so will leave newly created ranges * as invalid and therefore checks won't be made against it!!!! */ public void checkValid(); public boolean isValid(); public boolean isSessionOnly(); public String getStartIP(); public void setStartIP( String str ); public String getEndIP(); public void setEndIP( String str ); public void setSessionOnly( boolean sessionOnly ); public boolean isInRange( String ipAddress ); public void delete(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ipfilter/IPFilterException.java0000644000175000017500000000212711012741716025656 0ustar adrianadrian/* * File : IPFilterException.java * Created : 02-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ipfilter; /** * @author parg * */ public class IPFilterException extends Exception { public IPFilterException( String str ) { super(str); } public IPFilterException( String str, Throwable cause ) { super(str,cause); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/ipfilter/IPFilter.java0000644000175000017500000001021110550555322023772 0ustar adrianadrian/* * File : IPFilter.java * Created : 02-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.ipfilter; /** * @author parg * */ import java.io.File; public interface IPFilter { /** * Gets the file name used for persistent ranges * @return */ public File getFile(); /** * creates a new range but *doesn't* add it to the list. Use the add method * to add it * @param this_session_only // not persisted if "this_session_only" is true * @return */ public IPRange createRange( boolean this_session_only ); /** * Adds a range. Only ranges created with "create" above can be added * @param range */ public void addRange( IPRange range ); /** * Creates, validates and adds a range * @param description * @param start_ip * @param end_ip * @param this_session_only not persisted if true * @return new range or null if invalid */ public IPRange createAndAddRange( String description, String start_ip, String end_ip, boolean this_session_only ); /** * Remove a range * @param range */ public void removeRange( IPRange range ); /** * Reloads the ip filter from the config file (obtainable using "getFile") * @throws IPFilterException */ public void reload() throws IPFilterException; /** * Gets the current set of defined IP ranges * @return */ public IPRange[] getRanges(); /** * returns length of ranges list * @return */ public int getNumberOfRanges(); /** * Checks an address to see if its in an allowed range * @param IPAddress * @return */ public boolean isInRange( String IPAddress ); /** * Gets the current list of blocked addresses * @return */ public IPBlocked[] getBlockedIPs(); /** * returns length of blocked ip list * @return */ public int getNumberOfBlockedIPs(); /** * Explicitly blocks an address * @param IPAddress */ public void block( String IPAddress); /** * Gets the current list of b addresses * @since 2.5.0.2 * @return */ public IPBanned[] getBannedIPs(); /** * returns length of banned ip list * @since 2.5.0.2 * @return */ public int getNumberOfBannedIPs(); /** * Explicitly bans an address * @param IPAddress * @since 2.5.0.2 */ public void ban( String IPAddress, String text); /** * Removes a ban on an address * @param IPAddress * @since 2.5.0.2 */ public void unban( String IPAddress); /** * The filter either allows defined ranges to be allowed or denied access * @return */ public boolean getInRangeAddressesAreAllowed(); /** * Set the behaviour of the filter to either allow or deny access for defined ranges * @param b */ public void setInRangeAddressesAreAllowed( boolean b ); /** * Test if ipfilter is enabled or not * @return */ public boolean isEnabled(); /** * change the enabled status * @param enabled */ public void setEnabled( boolean enabled ); /** * saves current setting to file given by getFile * @throws IPFilterException */ public void save() throws IPFilterException; /** * Marks the IPFilter set as being uptodate * */ public void markAsUpToDate(); /** * Gets the last time the filter set was updated or marked as up to date * @return */ public long getLastUpdateTime(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/Plugin.java0000644000175000017500000000361310263514234021742 0ustar adrianadrian/* * File : Plugin.java * Created : 2 nov. 2003 18:43:21 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins; /** * Defines the plugin interface to implement in order to create a Plugin * @author Olivier */ public interface Plugin { /** * This method is called when the Plugin is loaded by Azureus * @param pluginInterface the interface that the plugin must use to communicate with Azureus * * @since 2.0.4.0 */ public void initialize( PluginInterface pluginInterface ) throws PluginException; /** * This method is invoke by reflection, if it exists. It couldn't be added to the interface as * doing so would have broken existing plugins. * It is called at load time, and as such *most* of the plugin framework is unavailable. Therefore * it should only be used for bootstrap situations where the plugin must perform some action before * the rest of Azureus initialises. * The only framework guaranteed to be available is the plugin-configuration. * * public static void * load( * PluginInterface pluginInterface ) * * throws PluginException; * @author parg * @since 2.2.0.3 */ } azureus-4.3.0.6/org/gudy/azureus2/plugins/disk/0000755000175000017500000000000011310377616020575 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/disk/DiskManager.java0000644000175000017500000000163610350607662023633 0ustar adrianadrian/* * File : DiskManager.java * Created : 22-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.disk; /** * @author parg * */ public interface DiskManager { } azureus-4.3.0.6/org/gudy/azureus2/plugins/disk/DiskManagerRequest.java0000644000175000017500000000351111156364760025202 0ustar adrianadrian/* * Created on 29-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.disk; public interface DiskManagerRequest { public static final int REQUEST_READ = 1; public void setType( int type ); public void setOffset( long offset ); public void setLength( long length ); /** * Get the number of bytes available for immediate reading from the request given its current * position. If this information is not known (download not running) then -1 is returned * @return */ public long getAvailableBytes(); /** * Get the number of bytes remaining to be read for the request * @return */ public long getRemaining(); public void run(); public void cancel(); public void setUserAgent( String agent ); public void setMaximumReadChunkSize( int size ); public void addListener( DiskManagerListener listener ); public void removeListener( DiskManagerListener listener ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/disk/DiskManagerListener.java0000644000175000017500000000210110412617206025317 0ustar adrianadrian/* * Created on 29-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.disk; public interface DiskManagerListener { public void eventOccurred( DiskManagerEvent event ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/disk/DiskManagerChannel.java0000644000175000017500000000217110617001470025106 0ustar adrianadrian/* * Created on 29-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.disk; public interface DiskManagerChannel { public DiskManagerRequest createRequest(); public DiskManagerFileInfo getFile(); public void destroy(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/disk/DiskManagerEvent.java0000644000175000017500000000270210421270630024616 0ustar adrianadrian/* * Created on 29-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.disk; import org.gudy.azureus2.plugins.utils.PooledByteBuffer; public interface DiskManagerEvent { public static final int EVENT_TYPE_SUCCESS = 1; public static final int EVENT_TYPE_FAILED = 2; public static final int EVENT_TYPE_BLOCKED = 3; // operation has blocked pending data public int getType(); public DiskManagerRequest getRequest(); public long getOffset(); public int getLength(); public PooledByteBuffer getBuffer(); public Throwable getFailure(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/disk/DiskManagerFileInfo.java0000644000175000017500000000445011145166426025245 0ustar adrianadrian/* * Created : 2004/May/26 * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.disk; import java.io.File; import org.gudy.azureus2.plugins.download.*; /** * @author TuxPaper * * @since 2.1.0.0 */ public interface DiskManagerFileInfo { public static final int READ = 1; public static final int WRITE = 2; // set methods public void setPriority( boolean b ); public void setSkipped( boolean b ); /** * Mark the file as deleted or not (deleted means the file will be truncated to take up minimum * space). This is generally 0 <= X < 2*piece_length as pieces can span file boundaries. * @since 2403 * @param b */ public void setDeleted(boolean b); // links the file to the named destination public void setLink( File link_destination ); // gets the current link, null if none public File getLink(); // get methods public int getAccessMode(); public long getDownloaded(); public long getLength(); public File getFile(); public int getIndex(); public int getFirstPieceNumber(); public long getPieceSize(); public int getNumPieces(); public boolean isPriority(); public boolean isSkipped(); public boolean isDeleted(); public byte[] getDownloadHash() throws DownloadException; public Download getDownload() throws DownloadException; public DiskManagerChannel createChannel() throws DownloadException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/0000755000175000017500000000000011310377616021276 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/ShareException.java0000644000175000017500000000211111012741710025042 0ustar adrianadrian/* * File : ShareException.java * Created : 31-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.sharing; /** * @author parg * */ public class ShareException extends Exception { public ShareException( String str ) { super(str); } public ShareException( String str, Throwable cause ) { super(str,cause); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/ShareResource.java0000644000175000017500000000412411237645572024723 0ustar adrianadrian/* * File : ShareResource.java * Created : 30-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.sharing; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; /** * @author parg * */ public interface ShareResource { public static final int ST_FILE = 1; public static final int ST_DIR = 2; public static final int ST_DIR_CONTENTS = 3; public int getType(); public String getName(); public void delete() throws ShareException, ShareResourceDeletionVetoException; public void delete( boolean force ) throws ShareException, ShareResourceDeletionVetoException; public void setAttribute( TorrentAttribute attribute, String value ); /** * @param attribute * @return null if no value defined */ public String getAttribute( TorrentAttribute attribute ); /** * get the defined attributes for this resource * @return */ public TorrentAttribute[] getAttributes(); public boolean canBeDeleted() throws ShareResourceDeletionVetoException; public ShareResourceDirContents getParent(); public void addChangeListener( ShareResourceListener l ); public void removeChangeListener( ShareResourceListener l ); public void addDeletionListener( ShareResourceWillBeDeletedListener l ); public void removeDeletionListener( ShareResourceWillBeDeletedListener l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/ShareManager.java0000644000175000017500000000372410336140744024501 0ustar adrianadrian/* * File : ShareManager.java * Created : 30-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.sharing; /** * @author parg * */ import java.io.File; public interface ShareManager { public void initialise() throws ShareException; public boolean isInitialising(); public ShareResource[] getShares(); /** * returns null if share not defined * @param file_or_dir * @return */ public ShareResource getShare( File file_or_dir ); public ShareResourceFile addFile( File file ) throws ShareException, ShareResourceDeletionVetoException; public ShareResourceDir addDir( File dir ) throws ShareException, ShareResourceDeletionVetoException; public ShareResourceDirContents addDirContents( File dir, boolean recursive ) throws ShareException, ShareResourceDeletionVetoException; /** * adding shares can take a long time due to the torrent creation process. The current * activity can be interrupted by calling this function, in which case the original * activity will fail with a ShareException */ public void cancelOperation(); public void addListener( ShareManagerListener listener ); public void removeListener( ShareManagerListener listener ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/ShareResourceListener.java0000644000175000017500000000222510373051046026414 0ustar adrianadrian/* * Created on 10-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.sharing; /** * @author parg * */ public interface ShareResourceListener { public void shareResourceChanged( ShareResource resource, ShareResourceEvent event ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/ShareResourceDeletionVetoException.java0000644000175000017500000000206511012741710031104 0ustar adrianadrian/* * File : ShareResourceDeletionVetoException.java * Created : 22-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.sharing; /** * @author parg * */ public class ShareResourceDeletionVetoException extends ShareException { public ShareResourceDeletionVetoException( String str ) { super( str ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/ShareManagerListener.java0000644000175000017500000000240711275142106026201 0ustar adrianadrian/* * File : ShareManagerListener.java * Created : 02-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.sharing; /** * @author parg * */ public interface ShareManagerListener { public void resourceAdded( ShareResource resource ); public void resourceModified( ShareResource old_resource, ShareResource new_resource ); public void resourceDeleted( ShareResource resource ); public void reportProgress( int percent_complete ); public void reportCurrentTask( String task_description ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/ShareResourceDirContents.java0000644000175000017500000000211607776145142027100 0ustar adrianadrian/* * File : ShareResourceDirContents.java * Created : 30-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.sharing; /** * @author parg * */ import java.io.File; public interface ShareResourceDirContents extends ShareResource { public File getRoot(); public boolean isRecursive(); public ShareResource[] getChildren(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/ShareItem.java0000644000175000017500000000210107776711052024023 0ustar adrianadrian/* * File : ShareItem.java * Created : 30-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.sharing; /** * @author parg * */ import java.io.File; import org.gudy.azureus2.plugins.torrent.Torrent; public interface ShareItem { public File getTorrentFile(); public Torrent getTorrent() throws ShareException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/ShareResourceFile.java0000644000175000017500000000202307774404644025523 0ustar adrianadrian/* * File : ShareResourceFile.java * Created : 30-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.sharing; /** * @author parg * */ import java.io.File; public interface ShareResourceFile extends ShareResource { public File getFile(); public ShareItem getItem(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/ShareResourceDir.java0000644000175000017500000000202007774404644025357 0ustar adrianadrian/* * File : ShareResourceDir.java * Created : 30-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.sharing; /** * @author parg * */ import java.io.File; public interface ShareResourceDir extends ShareResource { public File getDir(); public ShareItem getItem(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/ShareResourceEvent.java0000644000175000017500000000237610373051046025717 0ustar adrianadrian/* * Created on 10-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.sharing; /** * @author parg * */ public interface ShareResourceEvent { public static final int ET_ATTRIBUTE_CHANGED = 1; public int getType(); /** * For attribute change the value is an instance of TorrentAttribute * @return */ public Object getData(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/sharing/ShareResourceWillBeDeletedListener.java0000644000175000017500000000207610004100510030764 0ustar adrianadrian/* * File : ShareResourceWillBeDeletedListener.java * Created : 22-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.sharing; /** * @author parg * */ public interface ShareResourceWillBeDeletedListener { public void resourceWillBeDeleted( ShareResource resource ) throws ShareResourceDeletionVetoException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginConfigListener.java0000644000175000017500000000204710373051030024566 0ustar adrianadrian/* * Created on 22-May-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins; public interface PluginConfigListener { public void configSaved(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/0000755000175000017500000000000011310377634021003 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/LocaleListener.java0000644000175000017500000000212110373051004024533 0ustar adrianadrian/* * Created on 11-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils; import java.util.Locale; public interface LocaleListener { public void localeChanged( Locale locale ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/security/0000755000175000017500000000000011310377616022652 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/security/SEPublicKey.java0000644000175000017500000000321410775524126025640 0ustar adrianadrian/* * Created on 19 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.security; public interface SEPublicKey { public static final int KEY_TYPE_ECC_192 = 1; public int getType(); /** * Gets a generic encoded form that includes type identification information. So * don't treat this as a raw encoding as it can only sensibly be used to later * import via SESecurityManager.decodePublicKey * * @return */ public byte[] encodePublicKey(); /** * Raw encoding of the specific key type * @return */ public byte[] encodeRawPublicKey(); /** * Overridden to perform equality based on public key * @param other * @return */ public boolean equals( Object other ); public int hashCode(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/security/SEPublicKeyLocator.java0000644000175000017500000000213210775524126027162 0ustar adrianadrian/* * Created on 19 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.security; public interface SEPublicKeyLocator { public boolean accept( Object context, SEPublicKey other_key ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/security/PasswordListener.java0000644000175000017500000000241310373051044027015 0ustar adrianadrian/* * Created on 19-Jul-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.security; import java.net.PasswordAuthentication; import java.net.URL; public interface PasswordListener { public PasswordAuthentication getAuthentication( String realm, URL target ); public void setAuthenticationOutcome( String realm, URL target, boolean success ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/security/SESecurityManager.java0000644000175000017500000000763310446320662027056 0ustar adrianadrian/* * Created on 17-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.security; /** * @author parg * */ import java.net.Authenticator; import java.net.URL; import java.security.KeyStore; import java.security.cert.Certificate; import javax.net.ssl.SSLSocketFactory; import org.gudy.azureus2.plugins.messaging.generic.GenericMessageConnection; public interface SESecurityManager { public static final int BLOCK_ENCRYPTION_NONE = 1; public static final int BLOCK_ENCRYPTION_AES = 2; // runs the given task with the supplied Authenticator. Note that the // scope of the authenticator is "vm-wide" so that if by chance another // thread attempts to perform an operation that requires authentication // which the supplied one is in force, the request will be directed to the // authenticator public void runWithAuthenticator( Authenticator authenticator, Runnable task ); public void addPasswordListener( PasswordListener listener ); public void removePasswordListener( PasswordListener listener ); public void addCertificateListener( CertificateListener listener ); public void removeCertificateListener( CertificateListener listener ); /** * returns the SHA1 hash of the input data * @param data_in * @return */ public byte[] calculateSHA1( byte[] data_in ); /** * Installs the SSL certificate necessary to support the connection * @param url */ public SSLSocketFactory installServerCertificate( URL url ); public KeyStore getKeyStore() throws Exception; public KeyStore getTrustStore() throws Exception; /** * creates and installs a certificate capable of supporting SSL of type MD5withRSA * @param alias alias - e.g. "mycert" * @param cert_dn dn for the cert e.g. "CN=fred,OU=wap,O=wip,L=here,ST=there,C=GB" * @param strength keyt strength - e.g. 1024 * @return * @throws Exception */ public Certificate createSelfSignedCertificate( String alias, String cert_dn, int strength ) throws Exception; /** * Gets this azureus instance's unique random identity * @return */ public byte[] getIdentity(); /** * Gets the public key for this az instance of the supplied key type * @param key_type see KEY_TYPE_x constants in SEPublicKey * @param reason_resource a message text resource giving the reason for the key being required * @return */ public SEPublicKey getPublicKey( int key_type, String reason_resource ) throws Exception; public SEPublicKey decodePublicKey( byte[] encoded ) throws Exception; /** * Returns a proxy generic STS connection for incoming connection requests * @param connection * @param my_public_key * @param key_locator * @return * @throws Exception */ public GenericMessageConnection getSTSConnection( GenericMessageConnection connection, SEPublicKey my_public_key, SEPublicKeyLocator key_locator, String reason_resource, int block_encryption ) throws Exception; } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/security/CertificateListener.java0000644000175000017500000000222610373051044027437 0ustar adrianadrian/* * Created on 23-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.security; import java.security.cert.X509Certificate; public interface CertificateListener { public boolean trustCertificate( String resource, X509Certificate cert ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/PooledByteBuffer.java0000644000175000017500000000245110446016644025050 0ustar adrianadrian/* * Created on 21-Jul-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Map; public interface PooledByteBuffer { public byte[] toByteArray(); public ByteBuffer toByteBuffer(); /** * Data must be b-encoded... * @return */ public Map toMap() throws IOException; public void returnToPool(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/search/0000755000175000017500000000000011310377616022250 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/search/SearchListener.java0000644000175000017500000000172111222571362026023 0ustar adrianadrian/* * Created on Jun 30, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.search; public interface SearchListener { public void receivedResults( SearchProviderResults[] results ); public void completed(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/search/SearchInitiator.java0000644000175000017500000000304211222640230026165 0ustar adrianadrian/* * Created on Jun 30, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.search; import java.util.Map; public interface SearchInitiator { public static final String PR_SEARCH_TERM = "search_term"; // search expression public static final String PR_MATURE = "mature"; // "true" or "false" public SearchProvider[] getProviders(); public Search createSearch( SearchProvider[] providers, Map properties, SearchListener listener ) throws SearchException; /** * Convenience method for remote invocation * @param provider_ids * @param properties * @return * @throws SearchException */ public Search createSearch( String provider_ids, // comma separated list String properties ) // name=value, comma separated throws SearchException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/search/SearchProvider.java0000644000175000017500000000342711222571362026035 0ustar adrianadrian/* * Created on Jun 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.search; import java.util.Map; public interface SearchProvider { // properties public static final int PR_ID = 0; // getProperty only; Long public static final int PR_NAME = 1; // mandatory; String public static final int PR_ICON_URL = 2; // optional; String public static final int PR_DOWNLOAD_LINK_LOCATOR = 3; // optional; String public static final int PR_REFERER = 4; // optional; String public static final int PR_SUPPORTS_RESULT_FIELDS = 5; // optional; int[] public static final int PR_USE_ACCURACY_FOR_RANK = 6; // optional; Boolean // search parameters public static final String SP_SEARCH_TERM = "s"; // String public static final String SP_MATURE = "m"; // Boolean public SearchInstance search( Map search_parameters, SearchObserver observer ) throws SearchException; public Object getProperty( int property ); public void setProperty( int property, Object value ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/search/SearchException.java0000644000175000017500000000202411027073036026167 0ustar adrianadrian/* * Created on Jun 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.search; public class SearchException extends Exception { public SearchException( String str ) { super( str ); } public SearchException( String str, Throwable e ) { super( str, e ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/search/SearchResult.java0000644000175000017500000000467311222762226025526 0ustar adrianadrian/* * Created on Jun 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.search; public interface SearchResult { public static final int PR_NAME = 1; // String public static final int PR_PUB_DATE = 2; // Date public static final int PR_SIZE = 3; // Long public static final int PR_LEECHER_COUNT = 4; // Long (-1 unknown) public static final int PR_SEED_COUNT = 5; // Long (-1 unknown) public static final int PR_SUPER_SEED_COUNT = 6; // Long (-1 unknown) public static final int PR_CATEGORY = 7; // String public static final int PR_COMMENTS = 8; // Long (-1 unknown) public static final int PR_VOTES = 9; // Long (-1 unknown) public static final int PR_CONTENT_TYPE = 10; // String ("video","audio","game") public static final int PR_DETAILS_LINK = 11; // URL as String public static final int PR_DOWNLOAD_LINK = 12; // URL as String public static final int PR_PLAY_LINK = 13; // URL as String public static final int PR_PRIVATE = 14; // Boolean public static final int PR_DRM_KEY = 15; // String public static final int PR_DOWNLOAD_BUTTON_LINK = 16; // URL as String public static final int PR_RANK = 17; // Long value, 0->100 (-1 unknown) public static final int PR_ACCURACY = 18; // Long value, 0->100 (-1 unknown) public static final int PR_VOTES_DOWN = 19; // Long (-1 unknown) public static final int PR_UID = 20; // String public static final int PR_HASH = 21; // byte[] torrent hash // if you add more properties make sure you amend the mapping in PluginEngine appropriately // AND the reverse mapping in MetaSearchManagerImpl // AND generic XML attributes in xml-http plugin public Object getProperty( int property_name ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/search/SearchInstance.java0000644000175000017500000000160711027073036026003 0ustar adrianadrian/* * Created on Jun 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.search; public interface SearchInstance { public void cancel(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/search/SearchProviderResults.java0000644000175000017500000000201511222571362027407 0ustar adrianadrian/* * Created on Jun 30, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.search; public interface SearchProviderResults { public SearchProvider getProvider(); public SearchResult[] getResults(); public boolean isComplete(); public SearchException getError(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/search/Search.java0000644000175000017500000000166711222571362024326 0ustar adrianadrian/* * Created on Jun 30, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.search; public interface Search { public SearchProviderResults[] getResults(); public boolean isComplete(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/search/SearchObserver.java0000644000175000017500000000215211066421754026031 0ustar adrianadrian/* * Created on Jun 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.search; public interface SearchObserver { public static final int PR_MAX_RESULTS_WANTED = 1; // Long public void resultReceived( SearchInstance search, SearchResult result ); public void complete(); public void cancelled(); public Object getProperty( int property ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/Utilities.java0000644000175000017500000002174711275216146023634 0ustar adrianadrian/* * File : Utilities.java * Created : 24-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.utils; /** * @author parg * */ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.net.URL; import java.nio.ByteBuffer; import java.util.Map; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.utils.resourcedownloader.*; import org.gudy.azureus2.plugins.utils.resourceuploader.ResourceUploaderFactory; import org.gudy.azureus2.plugins.utils.search.SearchException; import org.gudy.azureus2.plugins.utils.search.SearchInitiator; import org.gudy.azureus2.plugins.utils.search.SearchProvider; import org.gudy.azureus2.plugins.utils.security.*; import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionException; import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionManager; import org.gudy.azureus2.plugins.utils.xml.simpleparser.*; import org.gudy.azureus2.plugins.utils.xml.rss.*; public interface Utilities { public String getAzureusUserDir(); public String getAzureusProgramDir(); public boolean isCVSVersion(); public boolean isWindows(); public boolean isLinux(); public boolean isSolaris(); public boolean isOSX(); /** * @return Whether the OS is a unix flavor (linux, bsd, aix, etc) * * @since 2.4.0.3 */ boolean isUnix(); /** * @return Whether the OS is FreeBSD * * @note Up to at least v2.4.0.2, the FreeBSD port has identified itself * to azureus as Linux and not FreeBSD * * @since 2.4.0.3 */ boolean isFreeBSD(); public InputStream getImageAsStream( String image_name ); public Semaphore getSemaphore(); public Monitor getMonitor(); public ByteBuffer allocateDirectByteBuffer( int size ); public void freeDirectByteBuffer( ByteBuffer buffer ); public PooledByteBuffer allocatePooledByteBuffer( int size ); public PooledByteBuffer allocatePooledByteBuffer( byte[] data ); /** * * @param data must be b-encodable * @return */ public PooledByteBuffer allocatePooledByteBuffer( Map data ) throws IOException; public Formatters getFormatters(); public LocaleUtilities getLocaleUtilities(); /** * Creates a UTTimer instance. It will be configured for non-lightweight * tasks by default. * * @param name Name for the UTTimer object. * @return A UTTimer instance. */ public UTTimer createTimer( String name ); /** * Creates a UTTimer instance. * * @param name Name for the UTTimer object. * @param lightweight If true, it indicates that this timer will be used to * perform small lightweight tasks. If false, it indicates that * this timer will be used to perform expensive tasks. This allows Azureus to create * the appropriate amount of resources to manage this timer. * @return A UTTimer instance. */ public UTTimer createTimer( String name, boolean lightweight ); /** * Creates a UTTimer instance. * * @param name Name for the UTTimer object. * @param priority The Thread.XXX_PRIORITY value to use. * @return A UTTimer instance. */ public UTTimer createTimer(String name, int priority); /** * create and run a thread for the target. This will be a daemon thread so that * its existence doesn't interfere with Azureus closedown * @param name * @param target */ public void createThread( String name, Runnable target ); /** * create a child process and executes the supplied command line. The child process * will not inherit any open handles on Windows, which does happen if Runtime is * used directly. This relies on the Platform plugin, if this is not installed then * this will fall back to using Runtime.exec * @param command_line */ public void createProcess( String command_line ) throws PluginException; public ResourceDownloaderFactory getResourceDownloaderFactory(); public ResourceUploaderFactory getResourceUploaderFactory(); public SESecurityManager getSecurityManager(); public SimpleXMLParserDocumentFactory getSimpleXMLParserDocumentFactory(); public RSSFeed getRSSFeed( InputStream is ) throws SimpleXMLParserDocumentException; public RSSFeed getRSSFeed( URL feed_location ) throws ResourceDownloaderException, SimpleXMLParserDocumentException; public RSSFeed getRSSFeed( ResourceDownloader feed_location ) throws ResourceDownloaderException, SimpleXMLParserDocumentException; /** * Returns a public IP address of the machine or null if it can't be determined */ public InetAddress getPublicAddress(); public InetAddress getPublicAddress( boolean ipv6 ); /** * attempts a reverse DNS lookup of an address, null if it fails * @param address * @return */ public String reverseDNSLookup( InetAddress address ); /** * Get the current system time, like System.currentTimeMillis(), * only the time lookup is cached for performance reasons. * @return current system time */ public long getCurrentSystemTime(); public ByteArrayWrapper createWrapper( byte[] data ); /** * create a dispatcher that will queue runnable items until either the limit * is reached or the dispatcher hasn't had an entry added for the defined idle time * @param idle_dispatch_time milliseconds * @param max_queue_size 0 -> infinite * @return */ public AggregatedDispatcher createAggregatedDispatcher( long idle_dispatch_time, long max_queue_size ); public AggregatedList createAggregatedList( AggregatedListAcceptor acceptor, long idle_dispatch_time, long max_queue_size ); public Map readResilientBEncodedFile( File parent_dir, String file_name, boolean use_backup ); public void writeResilientBEncodedFile( File parent_dir, String file_name, Map data, boolean use_backup ); public void deleteResilientBEncodedFile( File parent_dir, String file_name, boolean use_backup ); /** * Compares two version strings for order. * Returns a negative integer, zero, or a positive integer as the first * argument is less than, equal to, or greater than the second. *

* Example:
* compareVersions("1.1.0.0", "1.1.2.0"); // - * compareVersions("1.1.0.0", "1.1.0"); // 0 * compareVersions("1.1.1.1", "1.1.1"); // + * * @param v1 the first version string to be compared * @param v2 the second version string to be compared * @return a negative integer, zero, or a positive integer as the first * argument is less than, equal to, or greater than the second. * * @since 2.3.0.7 */ public int compareVersions(String v1, String v2); /** * Converts a file name so that all characters in the file name are * compatible with the underlying filesystem. This includes quote * characters, back and forwarded slashes, newline characters and so on. * *

* * Note - this is only intended for file names, rather than file paths. * * @param f_name File name to convert. * @return Converted file name. */ public String normaliseFileName(String f_name); /** * Adds a low priority task that will be scheduled at some point after existing tasks have * completed. In particular a system task exists that will block subsequent ones until after * UI initialisation is complete. Plugins can therefore use this to schedule initialisation * actions to occur after UI init is complete. * * @since 3.0.5.3 * @return */ public DelayedTask createDelayedTask(Runnable r); public void registerSearchProvider( SearchProvider provider ) throws SearchException; public SearchInitiator getSearchInitiator() throws SearchException; public SubscriptionManager getSubscriptionManager() throws SubscriptionException; public boolean isFeatureEnabled( String feature_id, Map feature_properties ); public void registerFeatureEnabler( FeatureEnabler enabler ); public void unregisterFeatureEnabler( FeatureEnabler enabler ); public interface FeatureEnabler { public boolean isFeatureEnabled( String requester_id, String feature_id, Map feature_properties ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/DelayedTask.java0000644000175000017500000000216211164323230024027 0ustar adrianadrian/* * Created on Apr 24, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils; public interface DelayedTask { /** * Queue the task for execution. The task MUST have been set prior to this. If successful * this will result in the runnable target being invoked when all prior delayed tasks * have completed */ public void queue(); public void queueFirst(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/UTTimerEvent.java0000644000175000017500000000210110373051004024157 0ustar adrianadrian/* * Created on 29-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils; /** * @author parg * */ public interface UTTimerEvent { public void cancel(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourcedownloader/0000755000175000017500000000000011310377634024711 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderAdapter.java0000644000175000017500000000317410563174620032667 0ustar adrianadrian/* * Created on 20-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.resourcedownloader; /** * @author parg * */ import java.io.InputStream; public class ResourceDownloaderAdapter implements ResourceDownloaderListener { public void reportPercentComplete( ResourceDownloader downloader, int percentage ) { } public void reportAmountComplete( ResourceDownloader downloader, long amount ) { } public void reportActivity( ResourceDownloader downloader, String activity ) { } public boolean completed( ResourceDownloader downloader, InputStream data ) { return( true ); } public void failed( ResourceDownloader downloader, ResourceDownloaderException e ) { } } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderFactory.java0000644000175000017500000001353411027644322032714 0ustar adrianadrian/* * File : TorrentDownloader2Factory.java * Created : 27-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.utils.resourcedownloader; /** * @author parg * */ import java.io.File; import java.net.URL; public interface ResourceDownloaderFactory { /** * Creates a downloader for a local file - in particular this is useful for installing a plugin * from a local file as the installer required ResourceDownloader instances to operate * @param file * @return */ public ResourceDownloader create( File file ); /** * creates a basic downloader. current url must be http or https * @param url * @return */ public ResourceDownloader create( URL url ); /** * Creates a basic downloader, where you can force any configured proxy * to be avoided. * * @since 3.1.0.1 */ public ResourceDownloader create(URL url, boolean force_no_proxy); public ResourceDownloader create( URL url, String user_name, String password ); /** * creates a downloader that will be asked to create a ResourceDownloader * when required. Useful when used in combination with an alternate downloader * so that time isn't wasted creating downloaders for subsequent possibilities * if the first one succeeds * @param factory * @return */ public ResourceDownloader create( ResourceDownloaderDelayedFactory factory ); /** * gets a downloader that will retry a number of times before failing * @param downloader * @param retry_count * @return */ public ResourceDownloader getRetryDownloader( ResourceDownloader downloader, int retry_count ); /** * gets a downloader that will timeout after a given period * @param downloader * @param timeout_millis * @return */ public ResourceDownloader getTimeoutDownloader( ResourceDownloader downloader, int timeout_millis ); /** * Gets a downloader that will cycle through a list of downloaders until * a download succeeds. The resource downloaders will be tried in order. */ public ResourceDownloader getAlternateDownloader( ResourceDownloader[] downloaders ); /** * Gets a downloader that will cycle through a list of downloaders until * a download succeeds. The resource downloaders will be tried in order. */ public ResourceDownloader getAlternateDownloader( ResourceDownloader[] downloaders, int max_to_try ); /** * Gets a downloader that will cycle through a list of downloaders until * a download succeeds. The resource downloaders will be tried randomly. */ public ResourceDownloader getRandomDownloader( ResourceDownloader[] downloaders ); /** * Gets a downloader that will cycle through a list of downloaders until * a download succeeds. The resource downloaders will be tried randomly. */ public ResourceDownloader getRandomDownloader( ResourceDownloader[] downloaders, int max_to_try ); /** * gets a downloader that will automatically follow META refresh tags * Will only do a single level of indirection * @param downloader * @return */ public ResourceDownloader getMetaRefreshDownloader( ResourceDownloader downloader ); /** * Given a downloader that will download a torrent, this will download * the torrent data itself. Note that the torrent MUST contain only a * single file (although a future enhancement may return a ZIP input stream * for multi-file torrents) * @param downloader * @param persistent whether or not the d/l will be retained over az stop/start * @return */ public ResourceDownloader getTorrentDownloader( ResourceDownloader downloader, boolean persistent ); /** * Download a torrent's data to the given download location * @param downloader * @param persistent * @param download_directory * @return */ public ResourceDownloader getTorrentDownloader( ResourceDownloader downloader, boolean persistent, File download_directory ); /** * Returns a downloader that does something sensible based on the url suffix. * In particular will return a torrent downloader if the URL ends with ".torrent" * The decision is made based on a random child downloader, so don't mix URL * suffixes below this point in the hierarchy * @param url * @return */ public ResourceDownloader getSuffixBasedDownloader( ResourceDownloader downloader ); /** * @param url * @param postData * @return */ ResourceDownloader create(URL url, String postData); /** * Creates multiple resource downloaders which can be used to download * a file from a Sourceforge project (from different mirrors). The resulting * downloaders can then be passed to a method such as {@link #getRandomDownloader(ResourceDownloader[])}. * * @since 3.0.5.3 */ public ResourceDownloader[] getSourceforgeDownloaders(String project_name, String file_name); /** * Creates a resource downloader which can be used to download * a file from a Sourceforge project (from different mirrors). * * @since 3.0.5.3 */ public ResourceDownloader getSourceforgeDownloader(String project_name, String file_name); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderException.java0000644000175000017500000000241011012741722033226 0ustar adrianadrian/* * Created on 24-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.resourcedownloader; /** * @author parg * */ public class ResourceDownloaderException extends Exception { public ResourceDownloaderException( String str ) { super(str); } public ResourceDownloaderException( String str, Throwable cause ) { super(str, cause); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloader.java0000644000175000017500000000504311065032272031355 0ustar adrianadrian/* * File : TorrentDownloader2.java * Created : 27-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.utils.resourcedownloader; /** * @author parg * */ import java.io.InputStream; public interface ResourceDownloader { public static final String PR_STRING_CONTENT_TYPE = "ContentType"; // Properties prefixed with URL_ will be passed directly to URL connections. For example // URL_User-Agent will be passed as User-Agent /** * Get a sensible name for the download based on its details (e.g. URL) * @return */ public String getName(); /** * Synchronously download. Events are still reported to listeners * @return * @throws ResourceDownloaderException */ public InputStream download() throws ResourceDownloaderException; /** * Asynchronously download. * */ public void asyncDownload(); /** * Attempts to get the size of the download. Returns -1 if the size can't be determined. * *

* * Note: You must not call this method from the reportActivity callback method. * * @throws ResourceDownloaderException */ public long getSize() throws ResourceDownloaderException; public void setProperty( String name, Object value ) throws ResourceDownloaderException; /** * Warning! URL response properties have a type of 'List of String' * * @param name * @return * @throws ResourceDownloaderException */ public Object getProperty( String name ) throws ResourceDownloaderException; /** * Cancel the download. */ public void cancel(); public boolean isCancelled(); public void reportActivity( String activity ); public void addListener( ResourceDownloaderListener l ); public void removeListener( ResourceDownloaderListener l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderListener.java0000644000175000017500000000330410563174620033067 0ustar adrianadrian/* * File : TorrentDownloader2Listener.java * Created : 27-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.utils.resourcedownloader; /** * @author parg * */ import java.io.*; public interface ResourceDownloaderListener { public void reportPercentComplete( ResourceDownloader downloader, int percentage ); public void reportAmountComplete( ResourceDownloader downloader, long amount ); public void reportActivity( ResourceDownloader downloader, String activity ); /** * * @param downloader * @param data * @return return true if the completed download is OK. If false is returned then * if there are alternative download sources they will be tried. If there are no * other sources then the download will be "failed" */ public boolean completed( ResourceDownloader downloader, InputStream data ); public void failed( ResourceDownloader downloader, ResourceDownloaderException e ); } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderDelayedFactory.javaazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderDelayedFactory.0000644000175000017500000000223610373051004033327 0ustar adrianadrian/* * Created on 21-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.resourcedownloader; /** * @author parg * */ public interface ResourceDownloaderDelayedFactory { public ResourceDownloader create() throws ResourceDownloaderException; } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderCancelledException.javaazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderCancelledExcept0000644000175000017500000000226511017134376033411 0ustar adrianadrian/* * Created on 21 Apr 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.utils.resourcedownloader; /** * @since 3.0.5.3 */ public class ResourceDownloaderCancelledException extends ResourceDownloaderException { public ResourceDownloaderCancelledException() { super("Download cancelled"); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/subscriptions/0000755000175000017500000000000011310377616023712 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionResult.java0000644000175000017500000000207611263261712030441 0ustar adrianadrian/* * Created on Oct 7, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.subscriptions; public interface SubscriptionResult { // this maps to the SearchResult properties (well, some subset ) public Object getProperty( int property_name ); public boolean isRead(); public void setRead( boolean read ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/subscriptions/Subscription.java0000644000175000017500000000172711264473520027247 0ustar adrianadrian/* * Created on Oct 7, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.subscriptions; public interface Subscription { public String getID(); public String getName(); public SubscriptionResult[] getResults(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionException.java0000644000175000017500000000205511263261712031116 0ustar adrianadrian/* * Created on Jun 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.subscriptions; public class SubscriptionException extends Exception { public SubscriptionException( String str ) { super( str ); } public SubscriptionException( String str, Throwable e ) { super( str, e ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionManager.java0000644000175000017500000000164711263261712030540 0ustar adrianadrian/* * Created on Oct 7, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.utils.subscriptions; public interface SubscriptionManager { public Subscription[] getSubscriptions(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourceuploader/0000755000175000017500000000000011310377616024366 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploaderFactory.java0000644000175000017500000000242110373051010032024 0ustar adrianadrian/* * Created on 19-Oct-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.resourceuploader; import java.io.InputStream; import java.net.URL; public interface ResourceUploaderFactory { public ResourceUploader create( URL url, InputStream data ); public ResourceUploader create( URL url, InputStream data, String user_name, String password ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploader.java0000644000175000017500000000262511055703204030511 0ustar adrianadrian/* * Created on 19-Oct-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.resourceuploader; import java.io.InputStream; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException; public interface ResourceUploader { public InputStream upload() throws ResourceUploaderException; public void setProperty( String name, Object value ) throws ResourceDownloaderException; public Object getProperty( String name ) throws ResourceDownloaderException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploaderException.java0000644000175000017500000000240011012741722032357 0ustar adrianadrian/* * Created on 24-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.resourceuploader; /** * @author parg * */ public class ResourceUploaderException extends Exception { public ResourceUploaderException( String str ) { super(str); } public ResourceUploaderException( String str, Throwable cause ) { super(str, cause); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/ByteArrayWrapper.java0000644000175000017500000000211210373051004025071 0ustar adrianadrian/* * Created on 14-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils; /** * @author parg * */ public interface ByteArrayWrapper { public byte[] getBytes(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/AggregatedList.java0000644000175000017500000000222610373051004024522 0ustar adrianadrian/* * Created on 14-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils; /** * @author parg * */ public interface AggregatedList { public void add( Object obj ); public Object remove( Object obj ); public void destroy(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/AggregatedListAcceptor.java0000644000175000017500000000215710373051004026206 0ustar adrianadrian/* * Created on 14-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils; import java.util.List; /** * @author parg * */ public interface AggregatedListAcceptor { public void accept( List l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/UTTimerEventPerformer.java0000644000175000017500000000214210373051004026046 0ustar adrianadrian/* * Created on 29-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils; /** * @author parg * */ public interface UTTimerEventPerformer { public void perform( UTTimerEvent event ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/0000755000175000017500000000000011310377420021574 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/simpleparser/0000755000175000017500000000000011310377616024311 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentNode.java0000644000175000017500000000302611064372146032450 0ustar adrianadrian/* * Created on Jul 24, 2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.xml.simpleparser; import java.io.PrintWriter; public interface SimpleXMLParserDocumentNode { public String getName(); public String getFullName(); public String getNameSpaceURI(); public String getValue(); public SimpleXMLParserDocumentAttribute[] getAttributes(); public SimpleXMLParserDocumentAttribute getAttribute( String name ); public SimpleXMLParserDocumentNode[] getChildren(); public SimpleXMLParserDocumentNode getChild( String name ); public void print(); public void print( PrintWriter pw ); } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentAttribute.javaazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentAttribute.ja0000644000175000017500000000215610373051024033171 0ustar adrianadrian/* * Created on Jul 24, 2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.xml.simpleparser; public interface SimpleXMLParserDocumentAttribute { public String getName(); public String getValue(); } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentFactory.javaazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentFactory.java0000644000175000017500000000267510373051024033172 0ustar adrianadrian/* * Created on 24-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.xml.simpleparser; import java.io.File; import java.io.InputStream; /** * @author parg * */ public interface SimpleXMLParserDocumentFactory { public SimpleXMLParserDocument create( File file ) throws SimpleXMLParserDocumentException; public SimpleXMLParserDocument create( InputStream is ) throws SimpleXMLParserDocumentException; public SimpleXMLParserDocument create( String data ) throws SimpleXMLParserDocumentException; } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentException.javaazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentException.ja0000644000175000017500000000234611012741720033165 0ustar adrianadrian/* * Created on Jul 24, 2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.xml.simpleparser; public class SimpleXMLParserDocumentException extends Exception { public SimpleXMLParserDocumentException( String str ) { super( str ); } public SimpleXMLParserDocumentException( Throwable e ) { super( e ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocument.java0000644000175000017500000000215010373051024031626 0ustar adrianadrian/* * Created on Jul 24, 2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.xml.simpleparser; public interface SimpleXMLParserDocument extends SimpleXMLParserDocumentNode { public void print(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/rss/0000755000175000017500000000000011310377616022412 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/rss/RSSChannel.java0000644000175000017500000000344510373051022025207 0ustar adrianadrian/* * Created on 02-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.xml.rss; import java.net.URL; import java.util.Date; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentNode; /** * @author parg * */ public interface RSSChannel { /** * Returns the mandatory title * @return */ public String getTitle(); /** * Returns the mandatory description * @return */ public String getDescription(); /** * Returns the mandatory link * @return */ public URL getLink(); /** * Returns the *optional* publication date * @return */ public Date getPublicationDate(); /** * returns the items in the channel * @return */ public RSSItem[] getItems(); /** * returns the underlying XML node for extraction of extensions * @return */ public SimpleXMLParserDocumentNode getNode(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/rss/RSSFeed.java0000644000175000017500000000245111050462754024511 0ustar adrianadrian/* * Created on 02-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.xml.rss; /** * @author parg * */ public interface RSSFeed { /** * True if this is an Atom feed http://www.w3.org/2005/Atom, RSS otherwise * @return */ public boolean isAtomFeed(); /** * A feed is composed of one (or more?) channels * @return */ public RSSChannel[] getChannels(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/xml/rss/RSSItem.java0000644000175000017500000000317711077300676024555 0ustar adrianadrian/* * Created on 02-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils.xml.rss; import java.net.URL; import java.util.Date; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentNode; /** * @author parg * */ public interface RSSItem { // all attributes of an item are optional, however one of title or description must be present /** * Get the item's title, null if not defined */ public String getTitle(); public String getDescription(); public URL getLink(); public Date getPublicationDate(); public String getUID(); /** * Gets the items underlying XML node for extraction of extensions * @return */ public SimpleXMLParserDocumentNode getNode(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/LocaleUtilities.java0000644000175000017500000000502311024630156024732 0ustar adrianadrian/* * File : LocaleUtilities.java * Created : 30-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.utils; import java.util.Locale; import java.util.Properties; import java.util.ResourceBundle; /** * @author parg * */ public interface LocaleUtilities { /** * Allows programatic registration of plugin messages, as opposed to using the * plugin.langfile property in plugin.properties * If you message base file is, say, a.b.c.Messages.properties, pass a.b.c.Messages * @param resource_bundle_prefix */ public void integrateLocalisedMessageBundle( String resource_bundle_prefix ); /** * Allows plugins to dynamically pass in a resource bundle to be used * for message text translation. * * @since 3.0.2.3 */ public void integrateLocalisedMessageBundle(ResourceBundle rb); /** * Allows plugins to dynamically pass in a properties object to be used * for message text translation. * * @since 3.0.2.3 */ public void integrateLocalisedMessageBundle(Properties p); public String getLocalisedMessageText( String key ); public String getLocalisedMessageText( String key, String[] params ); /** * Returns true if there exists a message string * with the given key name. * * @since 3.0.5.3 */ public boolean hasLocalisedMessageText(String key); /** * An alias for {@link #getLocalisedMessageText(String)} which returns * null if there is no message string definition for the given * key. * * @since 3.0.5.3 */ public String localise(String key); public LocaleDecoder[] getDecoders(); public void addListener( LocaleListener l ); public void removeListener( LocaleListener l ); /** * Returns the current locale being used. * * @since 3.0.0.9 */ public Locale getCurrentLocale(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/ShortCuts.java0000644000175000017500000000424510373051004023575 0ustar adrianadrian/* * Created on 10-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils; /** * @author parg * */ import org.gudy.azureus2.plugins.download.*; public interface ShortCuts { /** * A quick way of looking up a download given its hash * @param hash * @return * @throws DownloadException */ public Download getDownload( byte[] hash ) throws DownloadException; /** * A quick way of getting a download's statistics given its hash * @param hash * @return * @throws DownloadException */ public DownloadStats getDownloadStats( byte[] hash ) throws DownloadException; /** * A quick way of restarting a download given its hash * @param hash * @throws DownloadException */ public void restartDownload( byte[] hash ) throws DownloadException; /** * A quick way of stopping a download given its hash * @param hash * @throws DownloadException */ public void stopDownload( byte[] hash ) throws DownloadException; /** * A quick way of deleting a download given its hash * @param hash * @throws DownloadException * @throws DownloadRemovalVetoException */ public void removeDownload( byte[] hash ) throws DownloadException, DownloadRemovalVetoException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/Formatters.java0000644000175000017500000000451011023365764023776 0ustar adrianadrian/* * File : Formatter.java * Created : 30-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.utils; import java.io.IOException; import java.util.Comparator; import java.util.Map; import org.gudy.azureus2.core3.util.Constants; /** * @author parg * */ public interface Formatters { public String BYTE_ENCODING = Constants.BYTE_ENCODING; public String TEXT_ENCODING = Constants.DEFAULT_ENCODING; public String formatByteCountToKiBEtc( long bytes ); public String formatByteCountToKiBEtcPerSec( long bytes ); public String formatPercentFromThousands( long thousands ); public String formatByteArray( byte[] data, boolean no_spaces ); public String encodeBytesToString( byte[] bytes ); public byte[] decodeBytesFromString( String str ); public String formatDate( long millis ); /** * @since 3.0.5.3 */ public String formatTimeOnly(long millis); /** * @since 3.0.5.3 */ public String formatTimeOnly(long millis, boolean include_secs); /** * @since 3.0.5.3 */ public String formatDateOnly(long millis); public String formatTimeFromSeconds( long seconds ); /** * Format seconds remaining into an ETA value. * @param seconds * @return * @since 2.4.0.3 */ public String formatETAFromSeconds( long seconds ); public byte[] bEncode( Map map ) throws IOException; public Map bDecode( byte[] data ) throws IOException; public String base32Encode( byte[] data ); public byte[] base32Decode( String data ); public Comparator getAlphanumericComparator( boolean ignore_case ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/Semaphore.java0000644000175000017500000000237110473777716023612 0ustar adrianadrian/* * File : Semaphore.java * Created : 24-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.utils; /** * @author parg * */ public interface Semaphore { public void reserve(); public boolean reserveIfAvailable(); /** * reserve a semaphore subject to timeout * @param timeout_millis time to wait * @return true -> semaphore reserved, false -> timeout exceeded */ public boolean reserve( long timeout_millis ); public void release(); public void releaseAllWaiters(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/Monitor.java0000644000175000017500000000216510373051004023265 0ustar adrianadrian/* * Created on May 20, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils; public interface Monitor { public void enter(); public void exit(); public boolean isOwned(); public boolean hasWaiters(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/AggregatedDispatcher.java0000644000175000017500000000224610373051004025677 0ustar adrianadrian/* * Created on 14-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils; /** * @author parg * */ public interface AggregatedDispatcher { public void add( Runnable runnable ); public Runnable remove( Runnable obj ); public void destroy(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/StaticUtilities.java0000644000175000017500000001152011171750564024772 0ustar adrianadrian/* * Created on Feb 15, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils; import java.io.InputStream; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.ui.*; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory; import org.gudy.azureus2.plugins.utils.resourceuploader.ResourceUploaderFactory; import org.gudy.azureus2.plugins.utils.xml.rss.RSSFeed; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentException; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader.ResourceDownloaderFactoryImpl; import org.gudy.azureus2.pluginsimpl.local.utils.resourceuploader.ResourceUploaderFactoryImpl; import com.aelitis.azureus.core.AzureusCoreFactory; /** * Plugin utility class for easy access to static helper methods, * without the need for a plugin interface instance. */ public class StaticUtilities { private static Formatters formatters; static { try { Class c = Class.forName("org.gudy.azureus2.pluginsimpl.local.utils.FormattersImpl"); formatters = (Formatters) c.newInstance(); } catch (Exception e) { e.printStackTrace(); } } /** * Get display and byte format utilities. * @return formatters */ public static Formatters getFormatters() { return formatters; } public static ResourceDownloaderFactory getResourceDownloaderFactory() { return( ResourceDownloaderFactoryImpl.getSingleton()); } public static ResourceUploaderFactory getResourceUploaderFactory() { return( ResourceUploaderFactoryImpl.getSingleton()); } public static RSSFeed getRSSFeed( InputStream is ) throws SimpleXMLParserDocumentException { return( PluginInitializer.getDefaultInterface().getUtilities().getRSSFeed( is )); } /** * See UIInstance.promptUser * @param title * @param desc * @param options * @param default_option * @return */ public static int promptUser( String title, String desc, String[] options, int default_option ) { UIInstance[] instances = PluginInitializer.getDefaultInterface().getUIManager().getUIInstances(); if ( instances.length > 0 ){ return( instances[0].promptUser(title, desc, options, default_option )); }else{ Debug.out( "No UIInstances to handle prompt: " + title + "/" + desc ); return( -1 ); } } /** * gets the default UI manager and also waits for up to a specified time for a UI instance to * attach. useful when doing things during initialisation * @param millis_to_wait_for_attach * @return */ public static UIManager getUIManager( long millis_to_wait_for_attach ) { final UIManager ui_manager = PluginInitializer.getDefaultInterface().getUIManager(); if ( ui_manager.getUIInstances().length == 0 ){ final AESemaphore sem = new AESemaphore( "waitforui") ; ui_manager.addUIListener( new UIManagerListener() { public void UIAttached( UIInstance instance ) { ui_manager.removeUIListener( this ); sem.releaseForever(); } public void UIDetached( UIInstance instance ) { } }); // UIAttached is only fired once initialisation is complete. However, the instance // can be made available prior to this and there is a case where this event is blocking // the firing of the completion event. therefore pick it up if present directly long time_to_go = millis_to_wait_for_attach; while( ui_manager.getUIInstances().length == 0 ){ if ( sem.reserve( 1000 )){ break; } time_to_go -= 1000; if ( time_to_go <= 0 ){ Debug.out( "Timeout waiting for UI to attach" ); break; } } } return( ui_manager ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/LocaleDecoder.java0000644000175000017500000000176310032373314024331 0ustar adrianadrian/* * File : LocaleDecoder.java * Created : 30-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.utils; /** * @author parg * */ public interface LocaleDecoder { public String getName(); public String decode( byte[] encoded_bytes ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/utils/UTTimer.java0000644000175000017500000000331210373051004023162 0ustar adrianadrian/* * Created on 29-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.utils; /** * @author parg * */ public interface UTTimer { /** * Create a single-shot event with delay * @param when when it is to occur (absolute time, not relative) * @param performer * @return */ public UTTimerEvent addEvent( long when, UTTimerEventPerformer performer ); /** * Create a periodic event that will fire every specified number of milliseconds until cancelled * or the timer is destroyed * @param periodic_millis * @param performer * @return */ public UTTimerEvent addPeriodicEvent( long periodic_millis, UTTimerEventPerformer performer ); /** * Releases resources associated with this timer and renders it unusable */ public void destroy(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/0000755000175000017500000000000011310377616020761 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/peers/PeerEvent.java0000644000175000017500000000474610370411636023530 0ustar adrianadrian/* * Created on 02-Feb-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.peers; public interface PeerEvent { /** * peer state has changed * data - Integer holding one of the state values defined in Peer */ public static final int ET_STATE_CHANGED = 1; /** * The peer has sent us a bad piece data chunk. * data - Integer[2] * piece_num piece that failed hash check * total_bad_chunks total number of bad chunks sent by this peer so far */ public static final int ET_BAD_CHUNK = 2; /** The peer asserts that their availability should be added to the torrent-global availability pool. * The peer must send this when, and only when, their availability is known (such as after * receiving a bitfield message) but not after going to CLOSING state. After having sent this * message, the peer must remember they've done so and later send a corresponding removeAvailability * message at an appropriate time. * data - peerHavePieces boolean[] of pieces availabile */ public static final int ET_ADD_AVAILABILITY = 3; /** The peer asserts that their availability must now be taken from the torrent-global availability pool * The peer must send this only after having sent a corresponding addAvailability message, * and must not send it in a state prior to CLOSING state. The BitFlags must be complete, with all * pieces from any Bitfield message as well as those from any Have messages. * data - peerHavePieces boolean[] of pieces no longer available */ public static final int ET_REMOVE_AVAILABILITY = 4; public int getType(); public Object getData(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/PeerManagerListener2.java0000644000175000017500000000164711124122752025602 0ustar adrianadrian/* * Created on Dec 22, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.peers; public interface PeerManagerListener2 { public void eventOccurred( PeerManagerEvent event ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/PeerManagerListener.java0000644000175000017500000000233211124122752025510 0ustar adrianadrian/* * Created on 24-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.peers; /** * @author parg * @deprecated Use PeerManagerListener2 */ public interface PeerManagerListener { public void peerAdded( PeerManager manager, Peer peer ); public void peerRemoved( PeerManager manager, Peer peer ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/Peer.java0000644000175000017500000001320411124122752022507 0ustar adrianadrian/* * File : Peer.java * Created : 01-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.peers; /** * @author parg * */ import java.util.List; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.messaging.Message; import org.gudy.azureus2.plugins.network.Connection; public interface Peer { public final static int CONNECTING = PEPeer.CONNECTING; public final static int HANDSHAKING = PEPeer.HANDSHAKING; public final static int TRANSFERING = PEPeer.TRANSFERING; public final static int CLOSING = PEPeer.CLOSING; public final static int DISCONNECTED = PEPeer.DISCONNECTED; public final static Object PR_PRIORITY_CONNECTION = new Object(); public PeerManager getManager(); public int getState(); // from above set public byte[] getId(); /** * Get the peer's local TCP connection port. * @return local port */ public String getIp(); /** * Get the TCP port this peer is listening for incoming connections on. * @return TCP port, or 0 if port is unknown */ public int getTCPListenPort(); /** * Get the UDP port this peer is listening for incoming connections on. * @return UDP port, or 0 if port is unknown */ public int getUDPListenPort(); /** * Get the UDP port this peer is listening on for non-data connections * @return */ public int getUDPNonDataListenPort(); public int getPort(); public boolean[] getAvailable(); /** * @param pieceNumber int * @return true if this peers makes this piece available */ public boolean isPieceAvailable(int pieceNumber); public boolean isTransferAvailable(); /** * Rate control - gives the maximum number of bytes that can be read from this * connection at this time and returns the actual number read * @param max * @return */ public int readBytes( int max ); public int writeBytes( int max ); /** * This is much list isTransferAvailable(), except is more comprehensive. * That is; it checks a few more factors, within the object for speed, * so that a more timely status is considered and the caller doesn't need * to try to check each thing on it's own. * @return true if several factors say downloading can be tried. */ public boolean isDownloadPossible(); public boolean isChoked(); public boolean isChoking(); public boolean isInterested(); public boolean isInteresting(); public boolean isSeed(); public boolean isSnubbed(); public long getSnubbedTime(); public void setSnubbed( boolean b); public PeerStats getStats(); public boolean isIncoming(); /** * @deprecated This erroneously returns percent in 1000 (i.e. 100% = 1000 :) Therefore replaces * with something more accurately named! * @return */ public int getPercentDone(); public int getPercentDoneInThousandNotation(); public String getClient(); public boolean isOptimisticUnchoke(); public void setOptimisticUnchoke( boolean is_optimistic ); public List getExpiredRequests(); public List getRequests(); public int getMaximumNumberOfRequests(); public int getNumberOfRequests(); public void cancelRequest( PeerReadRequest request ); public boolean requestAllocationStarts( int[] base_priorities ); public int[] getPriorityOffsets(); public void requestAllocationComplete(); public boolean addRequest( PeerReadRequest request ); public void close( String reason, boolean closedOnError, boolean attemptReconnect ); public int getPercentDoneOfCurrentIncomingRequest(); public int getPercentDoneOfCurrentOutgoingRequest(); /** * Add peer listener. * @param listener * @deprecated use addListener( PeerListener2 ) */ public void addListener( PeerListener listener ); /** * Remove peer listener. * @param listener * @deprecated use removeListener( PeerListener2 ) */ public void removeListener( PeerListener listener ); /** * Add peer listener. * @param listener */ public void addListener( PeerListener2 listener ); /** * Remove peer listener. * @param listener */ public void removeListener( PeerListener2 listener ); /** * Get the network connection that backs this peer. * @return connection */ public Connection getConnection(); /** * Whether or not this peer supports the advanced messaging API. * @return true if extended messaging is supported, false if not */ public boolean supportsMessaging(); /** * Get the list of messages that this peer and us mutually understand. * @return messages available for use, or null of supported is yet unknown */ public Message[] getSupportedMessages(); public void setUserData( Object key, Object value ); public Object getUserData( Object key ); public byte[] getHandshakeReservedBytes(); public boolean isPriorityConnection(); public void setPriorityConnection( boolean is_priority ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/PeerManagerStats.java0000644000175000017500000000253210373051010025014 0ustar adrianadrian/* * Created on 13-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.peers; /** * @author parg * */ public interface PeerManagerStats { public int getConnectedSeeds(); public int getConnectedLeechers(); // session stats public long getDownloaded(); public long getUploaded(); public long getDownloadAverage(); public long getUploadAverage(); public long getDiscarded(); public long getHashFailBytes(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/PeerManagerEvent.java0000644000175000017500000000253311135270206025007 0ustar adrianadrian/* * Created on Dec 22, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.peers; public interface PeerManagerEvent { public static final int ET_PEER_ADDED = 1; // getPeer public static final int ET_PEER_REMOVED = 2; // getPeer public static final int ET_PEER_DISCOVERED = 3; // getPeerDescriptor; opt getPeer if discovered from a Peer public static final int ET_PEER_SENT_BAD_DATA = 4; // getPeer; getData -> Integer piece number public PeerManager getPeerManager(); public int getType(); public Peer getPeer(); public PeerDescriptor getPeerDescriptor(); public Object getData(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/PeerListener2.java0000644000175000017500000000206510370411636024306 0ustar adrianadrian/* * Created on 02-Feb-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.peers; public interface PeerListener2 { public void eventOccurred( PeerEvent event ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/PeerListener.java0000644000175000017500000000274210373051010024213 0ustar adrianadrian/* * Created on 21-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.peers; /** * Listener for peer events. * @deprecated use PeerListener2 */ public interface PeerListener { /** * The peer has changed to the given state. * @param new_state of peer */ public void stateChanged( int new_state ); /** * The peer has sent us a bad piece data chunk. * @param piece_num piece that failed hash check * @param total_bad_chunks total number of bad chunks sent by this peer so far */ public void sentBadChunk( int piece_num, int total_bad_chunks ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/PeerManager.java0000644000175000017500000000613111125344750024010 0ustar adrianadrian/* * File : PeerManager.java * Created : 28-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.peers; import java.util.Map; import org.gudy.azureus2.plugins.download.*; import org.gudy.azureus2.plugins.disk.*; import org.gudy.azureus2.plugins.utils.PooledByteBuffer; /** * @author parg * */ public interface PeerManager { public Download getDownload() throws DownloadException; public void addPeer( Peer peer ); /** * Add a new peer, using the default internal Peer implementation * (like for peers given in announce reply), using the given address * and port. * @param ip_address of peer to inject * @param port of peer to inject */ public void addPeer( String ip_address, int port ); public void addPeer( String ip_address, int tcp_port, boolean use_crypto ); public void addPeer( String ip_address, int tcp_port, int udp_port, boolean use_crypto ); public void addPeer( String ip_address, int tcp_port, int udp_port, boolean use_crypto, Map user_data ); public void removePeer( Peer peer ); public Peer[] getPeers(); /** * returns the peers for the given address * @param address * @return */ public Peer[] getPeers( String address ); /** * Get the list of currently pending peers * @since 4005 * @return */ public PeerDescriptor[] getPendingPeers(); /** * returns the pending connections to the given address * @param address * @return */ public PeerDescriptor[] getPendingPeers( String address ); public DiskManager getDiskManager(); public PeerManagerStats getStats(); public boolean isSeeding(); public boolean isSuperSeeding(); public PeerStats createPeerStats( Peer peer ); public void requestComplete( PeerReadRequest request, PooledByteBuffer data, Peer sender); public void requestCancelled( PeerReadRequest request, Peer sender ); public Piece[] getPieces(); public int getUploadRateLimitBytesPerSecond(); public int getDownloadRateLimitBytesPerSecond(); public void addListener( PeerManagerListener l ); public void removeListener( PeerManagerListener l ); public void addListener( PeerManagerListener2 l ); public void removeListener( PeerManagerListener2 l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/PeerDescriptor.java0000644000175000017500000000217411124122752024552 0ustar adrianadrian/* * Created on 12 Oct 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.peers; public interface PeerDescriptor { public String getIP(); public int getTCPPort(); public int getUDPPort(); public boolean useCrypto(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/PeerStats.java0000644000175000017500000000652211277161106023540 0ustar adrianadrian/* * File : PeerStats.java * Created : 01-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.peers; /** * Statistical information for a Peer. */ public interface PeerStats { /** * Get the the average bytes-per-second speed that we are receiving piece * data from the peer. * * @return average speed. * * @since 2.0.6.0 */ public int getDownloadAverage(); /** * Get the the longer-average bytes-per-second speed at which the peer is * uploading data to us. * * @return average speed * * @since 2.0.6.0 */ public int getReception(); /** * Get the the average bytes-per-second speed that we are sending piece data * to the peer. * * @return average speed. * * @since 2.0.6.0 */ public int getUploadAverage(); /** * Get the estimated total download rate of the peer. * @return estimated rate in bytes-per-second */ public int getTotalAverage(); /** * Get the total number of discarded bytes received from the peer. * @return total discarded * * @since 2.0.6.0 */ public long getTotalDiscarded(); /** * Get the total number of data (payload) bytes sent to the peer. * @return total * * @since 2.0.6.0 */ public long getTotalSent(); /** * Get the total number of data (payload) bytes received from the peer. * @return total * * @since 2.0.6.0 */ public long getTotalReceived(); /** * Get the estimated total upload rate of the peer. * @return estimated rate in bytes-per-second * * @since 2.0.6.0 */ public int getStatisticSentAverage(); /** * The given number of data (payload) bytes have been received from the peer. * This number gets added to the total and is used to calculate the rate. *

* Use this if you are talking to the peer outside of Azureus' API, and * want your stats added into Azureus' * * @param bytes * * @since 2.1.0.0 */ public void received(int bytes); /** * The given number of bytes received from the peer were discarded. * This number gets added to the total and is used to calculate rates that * include disgarded inforamtion. *

* Use this if you are talking to the peer outside of Azureus' API, and * want your stats added into Azureus' * * @param bytes * * @since 2.1.0.0 */ public void discarded(int bytes); /** * Get the amount of time that has elapsed since the connection with the * peer has been established. * * @return Amount of time in ms. * * @since 2.4.0.0 */ public long getTimeSinceConnectionEstablished(); public void setDownloadRateLimit( int bytes_per_sec ); public int getDownloadRateLimit(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/Piece.java0000644000175000017500000000262610432650122022645 0ustar adrianadrian/* * Created on 15 May 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.peers; public interface Piece { public boolean isDone(); public boolean isNeeded(); public boolean isDownloading(); /** * indicates if this piece is free and available to be allocated for download * not done, needed and not downloading * @return */ public boolean isFullyAllocatable(); /** * number of requests that are available to be made * @return */ public int getAllocatableRequestCount(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/peers/PeerReadRequest.java0000644000175000017500000000231710432650122024655 0ustar adrianadrian/* * File : DiskManagerRequest.java * Created : 22-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.peers; /** * @author parg * * @since 2307 */ public interface PeerReadRequest { public static final int NORMAL_REQUEST_SIZE = 16384; public int getPieceNumber(); public int getOffset(); public int getLength(); public void resetTime(final long now); public boolean isExpired(); public void cancel(); public boolean isCancelled(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/0000755000175000017500000000000011310377616021125 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdateProgressListener.java0000644000175000017500000000214310373051020026427 0ustar adrianadrian/* * Created on 01-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; /** * @author parg * */ public interface UpdateProgressListener { public void reportProgress( String str ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdateCheckInstance.java0000644000175000017500000000571611222362534025641 0ustar adrianadrian/* * Created on 11-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; /** * @author parg * */ public interface UpdateCheckInstance { public static final int UCI_INSTALL = 1; public static final int UCI_UPDATE = 2; public static final int UCI_UNINSTALL = 3; public static final int PT_UI_STYLE = 1; //Integer public static final int PT_UI_STYLE_DEFAULT = 1; public static final int PT_UI_STYLE_SIMPLE = 2; public static final int PT_UI_PARENT_SWT_COMPOSITE = 2; // SWT Composite public static final int PT_UI_DISABLE_ON_SUCCESS_SLIDEY = 3; // Boolean public static final int PT_CLOSE_OR_RESTART_ALREADY_IN_PROGRESS = 4; // Boolean /** * returns one of the above UCI_ constants * @return */ public int getType(); /** * returns the name supplied when the instance was created (or "" if it wasn't) * @return */ public String getName(); public void start(); public void cancel(); public boolean isCancelled(); public UpdateChecker[] getCheckers(); public Update[] getUpdates(); public UpdateInstaller createInstaller() throws UpdateException; /** * Add a further updatable component to this instance. Must be called before * the check process is started * @param component * @param mandatory */ public void addUpdatableComponent( UpdatableComponent component, boolean mandatory ); /** * Access to the update manager * @return */ public UpdateManager getManager(); public void setAutomatic( boolean automatic ); public boolean isAutomatic(); public void setLowNoise( boolean low_noise ); public boolean isLowNoise(); public Object getProperty( int property_name ); public void setProperty( int property_name, Object value ); public void addDecisionListener( UpdateManagerDecisionListener l ); public void removeDecisionListener( UpdateManagerDecisionListener l ); public void addListener( UpdateCheckInstanceListener l ); public void removeListener( UpdateCheckInstanceListener l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdatableComponent.java0000644000175000017500000000253410373051020025542 0ustar adrianadrian/* * Created on 11-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; /** * @author parg * */ public interface UpdatableComponent { /** * Name of the updatable component * @return */ public String getName(); /** * estimated maximum time to check whether an update is required or not in SECONDS * @return */ public int getMaximumCheckTime(); public void checkForUpdate( UpdateChecker checker ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdateCheckerListener.java0000644000175000017500000000273610373051020026177 0ustar adrianadrian/* * Created on 23-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; /** * @author parg * */ public interface UpdateCheckerListener { /** * Called when the checking process has completed successfully * @param checker */ public void completed( UpdateChecker checker ); /** * Called when the checking process failed * @param checker */ public void failed( UpdateChecker checker ); /** * Called when the checking process has been cancelled * @param checker */ public void cancelled( UpdateChecker checker ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdateListener.java0000644000175000017500000000220611026614270024712 0ustar adrianadrian/* * Created on 25-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; /** * @author parg * */ public interface UpdateListener { public void complete( Update update ); public void cancelled( Update update ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdateException.java0000644000175000017500000000232511012741724025065 0ustar adrianadrian/* * Created on 16-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; /** * @author parg * */ public class UpdateException extends Exception { public UpdateException( String str ) { super( str ); } public UpdateException( String str, Throwable cause ) { super(str, cause); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdateCheckInstanceListener.java0000644000175000017500000000226310373051020027330 0ustar adrianadrian/* * Created on 11-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; /** * @author parg * */ public interface UpdateCheckInstanceListener { public void cancelled( UpdateCheckInstance instance ); public void complete( UpdateCheckInstance instance ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/Update.java0000644000175000017500000000521411026614272023210 0ustar adrianadrian/* * Created on 07-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; /** * @author parg * */ import java.io.InputStream; import org.gudy.azureus2.plugins.utils.resourcedownloader.*; public interface Update { public static final int RESTART_REQUIRED_NO = 1; public static final int RESTART_REQUIRED_YES = 2; public static final int RESTART_REQUIRED_MAYBE = 3; public String getName(); public String[] getDescription(); public String getRelativeURLBase(); public void setRelativeURLBase( String base ); /** * * @param url URL to load instead of showing the description text) * * @since 3.0.1.7 */ public void setDescriptionURL( String url); /** * @return null if no description url * * @since 3.0.1.7 */ public String getDesciptionURL(); public String getNewVersion(); public ResourceDownloader[] getDownloaders(); public boolean isMandatory(); public void setRestartRequired( int restart_required ); public int getRestartRequired(); public void setUserObject( Object obj ); public Object getUserObject(); /** * mark the update as complete and inform any listeners */ public void complete(); /** * cancel this update */ public void cancel(); public boolean isCancelled(); public boolean isComplete(); public UpdateCheckInstance getCheckInstance(); public Object getDecision( int decision_type, // see UpdateManagerDecisionListener String decision_name, String decision_description, Object decision_data ); public InputStream verifyData( InputStream is, boolean force ) throws UpdateException; public void addListener( UpdateListener l ); public void removeListener( UpdateListener l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdateManagerListener.java0000644000175000017500000000217110373051020026176 0ustar adrianadrian/* * Created on 19-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; /** * @author parg * */ public interface UpdateManagerListener { public void checkInstanceCreated( UpdateCheckInstance instance ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdateManagerVerificationListener.java0000644000175000017500000000224010431212040030532 0ustar adrianadrian/* * Created on 11 May 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; public interface UpdateManagerVerificationListener { public boolean acceptUnVerifiedUpdate( Update update ); public void verificationFailed( Update update, Throwable cause ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdateManager.java0000644000175000017500000000646410457717044024523 0ustar adrianadrian/* * Created on 07-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; /** * @author parg * */ public interface UpdateManager { /** * All updateable components must register in order to receive update check events * @param component * @param mandatory indicates that this component must successfully complete checking * for any overall update check to complete */ public void registerUpdatableComponent( UpdatableComponent component, boolean mandatory ); /** * creates an update check instance with currently registered updatable components * Default check type is "UCI_UPDATE" * @return */ public UpdateCheckInstance createUpdateCheckInstance(); /** * creates an update check instance with currently registered updatable components * @param check_type see UpdateCheckInstance.UCI_xx * @param name name of the update instance */ public UpdateCheckInstance createUpdateCheckInstance( int check_type, String name ); /** * creates an update check instance with no attached updateable components (as opposed * to automatically including all registered * @param check_type see UpdateCheckInstance.UCI_xx * @param name name of the update instance * @return */ public UpdateCheckInstance createEmptyUpdateCheckInstance( int check_type, String name ); /** * create a stand alone update installer. you will need to restart Azureus for it to * be installed * @return * @throws UpdateException */ public UpdateInstaller createInstaller() throws UpdateException; public String getInstallDir(); public String getUserDir(); /** * returns the currently declared installers, if any * @return */ public UpdateInstaller[] getInstallers(); /** * restart azureus after applying any updates * @deprecated - use applyUpdates * @throws UpdateException */ public void restart() throws UpdateException; /** * applies any updates and stops or restarts Azureus * @throws UpdateException */ public void applyUpdates( boolean restart_after ) throws UpdateException; public void addVerificationListener( UpdateManagerVerificationListener l ); public void removeVerificationListener( UpdateManagerVerificationListener l ); public void addListener( UpdateManagerListener l ); public void removeListener( UpdateManagerListener l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdateInstaller.java0000644000175000017500000000607210373051020025057 0ustar adrianadrian/* * Created on 16-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; /** * @author parg * */ import java.io.*; public interface UpdateInstaller { /** * Add a resource to the installation. The file will be saved away for later use. * * @param resource_name non-qualified name for the resource - i.e. not an absolute file * name but rather something local like "fred". This can then be used * later in actions * @param is */ public void addResource( String resource_name, InputStream is ) throws UpdateException; /** * Add a resource to the installation. The file will be saved away for later use. * * @param resource_name non-qualified name for the resource - i.e. not an absolute file * name but rather something local like "fred". This can then be used * later in actions * @param is * @param closeInputStream if false, the InputStream is won't be closed */ public void addResource( String resource_name, InputStream is, boolean closeInputStream) throws UpdateException; /** * Returns the absolute path of the Azureus install dir (i.e. where Azureus2.jar etc is located) * @return */ public String getInstallDir(); /** * Returns the absolute path of the user dir (i.e. where config is stored) * @return */ public String getUserDir(); /** * Add an installation "move" action to move either an absolute file or resource * @param from_file either absolute or relative * @param to_file absolute */ public void addMoveAction( String from_file_or_resource, String to_file ) throws UpdateException; /** * Add an installation "change rights" action to change a file rights * @param rights the rights, for example "776" * @param to_file absolute */ public void addChangeRightsAction( String rights, String to_file ) throws UpdateException; /** * Adds an action to remove either a directory (recursively delete) or file * @param file * @throws UpdateException */ public void addRemoveAction( String file ) throws UpdateException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdateChecker.java0000644000175000017500000000537510457717044024515 0ustar adrianadrian/* * Created on 11-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; /** * @author parg * */ import org.gudy.azureus2.plugins.utils.resourcedownloader.*; public interface UpdateChecker { public UpdatableComponent getComponent(); public UpdateCheckInstance getCheckInstance(); /** * Add an update with a single downloader * @param mandatory indicates that in a group of updates this one must succeed */ public Update addUpdate( String name, String[] description, String new_version, ResourceDownloader downloader, int restart_required ); /** * Add an update with a number of downloaders */ public Update addUpdate( String name, String[] description, String new_version, ResourceDownloader[] downloaders, int restart_required ); /** * For updates that require a stop, update-action and then start you create an installer. * This allows the specification of actions such as the replacement of a DLL * @return */ public UpdateInstaller createInstaller() throws UpdateException; /** * Indicate that update checking is complete and that any updates required have * been added by the addUpdate methods */ public void completed(); /** * Indicates that the update check failed. Of particular importance for mandatory * components (e.g. AZ core) as failure of a mandatory one causes all other * updates to be aborted */ public void failed(); /** * report a progress string to registered listeners * @param str */ public void reportProgress( String str ); public void addListener( UpdateCheckerListener l ); public void removeListener( UpdateCheckerListener l ); public void addProgressListener( UpdateProgressListener l ); public void removeProgressListener( UpdateProgressListener l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/update/UpdateManagerDecisionListener.java0000644000175000017500000000235210373051020027655 0ustar adrianadrian/* * Created on 04-Aug-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.update; public interface UpdateManagerDecisionListener { public static final int DT_STRING_ARRAY_TO_STRING = 0; public Object decide( Update update, int decision_type, String decision_name, String decision_description, Object decision_data ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ddb/0000755000175000017500000000000011310377616020374 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/ddb/DistributedDatabaseProgressListener.java0000644000175000017500000000231610373051020030365 0ustar adrianadrian/* * Created on 06-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ddb; /** * @author parg * */ public interface DistributedDatabaseProgressListener { public void reportSize( long size ); public void reportActivity( String str ); public void reportCompleteness( int percent ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ddb/DistributedDatabase.java0000644000175000017500000000731511262527612025153 0ustar adrianadrian/* * Created on 18-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ddb; import java.net.InetSocketAddress; /** * @author parg * */ public interface DistributedDatabase { public static final int OP_NONE = 0x00000000; public static final int OP_EXHAUSTIVE_READ = 0x00000001; public static final int OP_PRIORITY_HIGH = 0x00000002; // diversification types public static final byte DT_NONE = 1; public static final byte DT_FREQUENCY = 2; public static final byte DT_SIZE = 3; public boolean isAvailable(); public boolean isExtendedUseAllowed(); public DistributedDatabaseContact getLocalContact(); public DistributedDatabaseKey createKey( Object key ) throws DistributedDatabaseException; public DistributedDatabaseKey createKey( Object key, String description ) throws DistributedDatabaseException; public DistributedDatabaseValue createValue( Object value ) throws DistributedDatabaseException; public DistributedDatabaseContact importContact( InetSocketAddress address ) throws DistributedDatabaseException; public DistributedDatabaseContact importContact( InetSocketAddress address, byte protocol_version ) throws DistributedDatabaseException; public void write( DistributedDatabaseListener listener, DistributedDatabaseKey key, DistributedDatabaseValue value ) throws DistributedDatabaseException; public void write( DistributedDatabaseListener listener, DistributedDatabaseKey key, DistributedDatabaseValue[] values ) throws DistributedDatabaseException; public void read( DistributedDatabaseListener listener, DistributedDatabaseKey key, long timeout ) throws DistributedDatabaseException; public void read( DistributedDatabaseListener listener, DistributedDatabaseKey key, long timeout, int options ) throws DistributedDatabaseException; public void readKeyStats( DistributedDatabaseListener listener, DistributedDatabaseKey key, long timeout ) throws DistributedDatabaseException; public void delete( DistributedDatabaseListener listener, DistributedDatabaseKey key ) throws DistributedDatabaseException; public void delete( DistributedDatabaseListener listener, DistributedDatabaseKey key, DistributedDatabaseContact[] targets ) throws DistributedDatabaseException; public void addTransferHandler( DistributedDatabaseTransferType type, DistributedDatabaseTransferHandler handler ) throws DistributedDatabaseException; public DistributedDatabaseTransferType getStandardTransferType( int standard_type ) throws DistributedDatabaseException; public void addListener( DistributedDatabaseListener l ); public void removeListener( DistributedDatabaseListener l ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ddb/DistributedDatabaseKeyStats.java0000644000175000017500000000234310434652644026643 0ustar adrianadrian/* * Created on 23 May 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ddb; public interface DistributedDatabaseKeyStats { public int getEntryCount(); public int getSize(); public int getReadsPerMinute(); /** * See {@link DistributedDatabase#DT_FREQUENCY) etc} * @return */ public byte getDiversification(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ddb/DistributedDatabaseValue.java0000644000175000017500000000237510412370562026145 0ustar adrianadrian/* * Created on 18-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ddb; /** * @author parg * */ public interface DistributedDatabaseValue { public Object getValue( Class type ) throws DistributedDatabaseException; public long getCreationTime(); public long getVersion(); public DistributedDatabaseContact getContact(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ddb/DistributedDatabaseContact.java0000644000175000017500000000370211265520556026466 0ustar adrianadrian/* * Created on 18-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ddb; import java.net.InetSocketAddress; /** * @author parg * */ public interface DistributedDatabaseContact { public String getName(); public InetSocketAddress getAddress(); public boolean isAlive( long timeout ); // async version - event types: complete -> alive, timeout -> dead public void isAlive( long timeout, DistributedDatabaseListener listener ); public boolean isOrHasBeenLocal(); /** * Tries to open a NAT tunnel to the contact. Should only be used if direct contact fails * @return */ public boolean openTunnel(); public void write( DistributedDatabaseTransferType type, DistributedDatabaseKey key, DistributedDatabaseValue data ) throws DistributedDatabaseException; public DistributedDatabaseValue read( DistributedDatabaseProgressListener listener, DistributedDatabaseTransferType type, DistributedDatabaseKey key, long timeout ) throws DistributedDatabaseException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/ddb/DistributedDatabaseEvent.java0000644000175000017500000000332311043601320026132 0ustar adrianadrian/* * Created on 18-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ddb; /** * @author parg * */ public interface DistributedDatabaseEvent { // operation level public static final int ET_VALUE_WRITTEN = 1; public static final int ET_VALUE_READ = 2; public static final int ET_VALUE_DELETED = 3; public static final int ET_OPERATION_COMPLETE = 4; public static final int ET_OPERATION_TIMEOUT = 5; public static final int ET_KEY_STATS_READ = 6; public static final int ET_OPERATION_STARTS = 7; // ddb level public static final int ET_LOCAL_CONTACT_CHANGED = 10; public int getType(); public DistributedDatabaseKey getKey(); public DistributedDatabaseKeyStats getKeyStats(); public DistributedDatabaseValue getValue(); public DistributedDatabaseContact getContact(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ddb/DistributedDatabaseException.java0000644000175000017500000000237411012742464027027 0ustar adrianadrian/* * Created on 18-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ddb; /** * @author parg * */ public class DistributedDatabaseException extends Exception { public DistributedDatabaseException( String str ) { super( str ); } public DistributedDatabaseException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/ddb/DistributedDatabaseListener.java0000644000175000017500000000216110373051020026636 0ustar adrianadrian/* * Created on 18-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ddb; /** * @author parg * */ public interface DistributedDatabaseListener { public void event( DistributedDatabaseEvent event ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ddb/DistributedDatabaseTransferHandler.java0000644000175000017500000000273310373051020030140 0ustar adrianadrian/* * Created on 18-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ddb; /** * @author parg * */ public interface DistributedDatabaseTransferHandler { public DistributedDatabaseValue read( DistributedDatabaseContact contact, DistributedDatabaseTransferType type, DistributedDatabaseKey key ) throws DistributedDatabaseException; public void write( DistributedDatabaseContact contact, DistributedDatabaseTransferType type, DistributedDatabaseKey key, DistributedDatabaseValue value ) throws DistributedDatabaseException; } azureus-4.3.0.6/org/gudy/azureus2/plugins/ddb/DistributedDatabaseTransferType.java0000644000175000017500000000214410373051020027500 0ustar adrianadrian/* * Created on 18-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ddb; /** * @author parg * */ public interface DistributedDatabaseTransferType { public static final int ST_TORRENT = 1; } azureus-4.3.0.6/org/gudy/azureus2/plugins/ddb/DistributedDatabaseKey.java0000644000175000017500000000223010373051020025576 0ustar adrianadrian/* * Created on 18-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ddb; /** * @author parg * */ public interface DistributedDatabaseKey { public Object getKey() throws DistributedDatabaseException; public String getDescription(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/platform/0000755000175000017500000000000011310377616021467 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/platform/PlatformManagerException.java0000644000175000017500000000236111012741716027265 0ustar adrianadrian/* * Created on 18-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.platform; /** * @author parg * */ public class PlatformManagerException extends Exception { public PlatformManagerException( String str ) { super(str); } public PlatformManagerException( String str, Throwable cause ) { super(str, cause ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/platform/PlatformManager.java0000644000175000017500000000560111133516744025413 0ustar adrianadrian/* * Created on 12-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.platform; import java.io.File; public interface PlatformManager { public static final int LOC_USER_DATA = 1; public static final int LOC_MUSIC = 2; public static final int LOC_DOCUMENTS = 3; public static final int LOC_VIDEO = 4; /** * Checks to see if the supplied file type is registered with this application * @param name * @param type * @return * @throws PlatformManagerException */ public boolean isAdditionalFileTypeRegistered( String name, // e.g. "Wibble" String type ) // e.g. ".wib" throws PlatformManagerException; /** * Registers a file type with this application * @param name * @param description * @param type * @param content_type * @throws PlatformManagerException */ public void registerAdditionalFileType( String name, // e.g. "Wibble" String description, // e.g. "Wibble File" String type, // e.g. ".wib" String content_type ) // e.g. "application/x-wibble" throws PlatformManagerException; /** * Removes a file-type registration * @param name * @param type * @return * @throws PlatformManagerException */ public void unregisterAdditionalFileType( String name, // e.g. "Wibble" String type ) // e.g. ".wib" throws PlatformManagerException; /** * Reveals the file or directory with the platform's default browser * @param file_name The full path to a file or directory * @throws PlatformManagerException If this operation fails */ public void showFile( String file_name ) throws PlatformManagerException; /** * Get a well-known location, if defined for the platform * @param location_id from above LOC_constants * @return * @since 2.3.0.6 */ public File getLocation( long location_id ) throws PlatformManagerException; /** * * @return null if can't be found */ public String getComputerName(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginEvent.java0000644000175000017500000000506611263017510022744 0ustar adrianadrian/* * File : PluginEvent.java * Created : 06-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins; /** allow config wizard progress to be determined * * @author parg * @since 2.0.8.0 */ public interface PluginEvent { /** * Not guaranteed to trigger. Used to be triggered at startup */ public static final int PEV_CONFIGURATION_WIZARD_STARTS = 1; /** * Not guaranteed to trigger. Used to be triggered at startup */ public static final int PEV_CONFIGURATION_WIZARD_COMPLETES = 2; public static final int PEV_INITIALISATION_PROGRESS_TASK = 3; public static final int PEV_INITIALISATION_PROGRESS_PERCENT = 4; /** * @since 2403 */ public static final int PEV_INITIAL_SHARING_COMPLETE = 5; /** * Triggered when UI Initialization is complete. This is after the UI * is attached. This trigger is helpful if you need access to an UI * element from a plugin after you in the UI attachment order. * * @since 2403 */ public static final int PEV_INITIALISATION_UI_COMPLETES = 6; /** * This event is triggered when all plugins have had their 'initialize' method called * on startup. This differs from the 'initialisationComplete' callback on PluginListener * in that it is *guranteed* to be triggered before any other initialisation actions * take place. */ public static final int PEV_ALL_PLUGINS_INITIALISED = 7; /** * Data is the PluginInterface of installed plugin * @since 4.1.0.1 */ public static final int PEV_PLUGIN_OPERATIONAL = 8; public static final int PEV_PLUGIN_NOT_OPERATIONAL = 9; /** * Plugin specific events can be raised by a plugin to communicate with * other components. The event type must start from the number below */ public static final int PEV_FIRST_USER_EVENT = 1024; public int getType(); public Object getValue(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginManager.java0000644000175000017500000001301011053126316023223 0ustar adrianadrian/* * File : PluginManager.java * Created : 14-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins; import java.util.Properties; import org.gudy.azureus2.pluginsimpl.local.*; import org.gudy.azureus2.plugins.installer.*; /** * This class allows Azureus to be started as an embedded component and also allows plugins to * be dynamically registered * @author parg */ public abstract class PluginManager { /** * No user interface * * @since 2.0.8.0 */ public static final int UI_NONE = 0; /** * SWT user inferface * * @since 2.0.6.0 */ public static final int UI_SWT = 1; /** * Property Key: Allow multiple instances. * Normally Azureus will only permit a single instance to run per machine. * Values for this key are: "true" or "false" * * @since 2.0.7.0 */ public static final String PR_MULTI_INSTANCE = "MULTI_INSTANCE"; public static PluginManagerDefaults getDefaults() { return( PluginManagerDefaultsImpl.getSingleton()); } /** * Runs Azureus * @param ui_type Type of user interface to provide. See UI_* Constants * @param properties A list of properties to pass Azureus. See PR_* constants. * * @since 2.0.6.0 */ public static PluginManager startAzureus( int ui_type, Properties properties ) { return( PluginManagerImpl.startAzureus( ui_type, properties )); } /** * Shuts down Azureus * @throws PluginException * * @since 2.0.8.0 */ public static void stopAzureus() throws PluginException { PluginManagerImpl.stopAzureus(); } /** * restarts azureus and performs any Update actions defined via the plugin "update" * interface. Currently only works for SWT UIs. * @throws PluginException * * @since 2.1.0.0 */ public static void restartAzureus() throws PluginException { PluginManagerImpl.restartAzureus(); } /** * Programatic plugin registration interface * @param plugin_class this must implement Plugin * * @since 2.0.6.0 */ public static void registerPlugin( Class plugin_class ) { PluginManagerImpl.registerPlugin( plugin_class ); } public static void registerPlugin( Plugin plugin, String id ) { PluginManagerImpl.registerPlugin( plugin, id ); } /** * Returns the plugin interface with a given id, or null if not found. * * @param id * @param operational If true, only return a PluginInterface if the plugin * is operational (i.e. is running). * @since 3.1.1.1 */ public abstract PluginInterface getPluginInterfaceByID(String id, boolean operational); /** * Returns the plugin interface with a given class name, or null if not found. * * @param class_name * @param operational If true, only return a PluginInterface if the plugin * is operational (i.e. is running). * @since 3.1.1.1 */ public abstract PluginInterface getPluginInterfaceByClass(String class_name, boolean operational); /** * Returns the plugin interface with a given class, or null if not found. * * @param class_object * @param operational If true, only return a PluginInterface if the plugin * is operational (i.e. is running). * @since 3.1.1.1 */ public abstract PluginInterface getPluginInterfaceByClass(Class class_object, boolean operational); /** * Gets the current set of registered plugins. During initialisation this will probably give partial * results as plugin initialisation is non-deterministic. * @return * * @since 2.1.0.0 */ public abstract PluginInterface[] getPluginInterfaces(); /** * returns the default plugin interface that can be used to access plugin functionality without an * explicit plugin * @return null if unavailable */ public abstract PluginInterface getDefaultPluginInterface(); /** * Gets the current set of registered plugins. During initialisation this will probably give partial * results as plugin initialisation is non-deterministic. * @return * * @since 2.1.0.0 */ public abstract PluginInterface[] getPlugins(); public abstract void firePluginEvent( int event_type ); public abstract PluginInstaller getPluginInstaller(); public final void refreshPluginList() { refreshPluginList(true); } /** * @since 3.1.1.1 */ public abstract void refreshPluginList(boolean initialise); public abstract boolean isSilentRestartEnabled(); /** * returns the plugin interface with a given id, or null if not found * @param id * @return * * @since 2.1.0.0 */ public abstract PluginInterface getPluginInterfaceByID( String id ); /** * * @since 2.1.0.0 */ public abstract PluginInterface getPluginInterfaceByClass( String class_name ); public abstract PluginInterface getPluginInterfaceByClass( Class c ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginException.java0000644000175000017500000000222011045720150023605 0ustar adrianadrian/* * File : PluginException.java * Created : 25-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins; /** * * @author parg * @since 2.0.7.0 */ public class PluginException extends Exception { public PluginException( String str ) { super( str ); } public PluginException( String str, Throwable e ) { super( str, e ); } public PluginException(Throwable e) { super(e); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/ipc/0000755000175000017500000000000011310377616020416 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/ipc/IPCInterface.java0000644000175000017500000000461011131772700023510 0ustar adrianadrian/* * Created on 02-May-2006 * Created by Damokles * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ipc; /** * @author Damokles * */ public interface IPCInterface { /** * This function will call the given method on the plugin. * * This function allows direct method calls to the plugin * using Java Reflection API. * * Primitives like int, boolean need to be wrapped in their * Objects (int -> Integer).

* * Results will be returned as Object and can be classcasted. * *

* * WARNING: only call Methods that use Java or Azureus Classes * the use of custom classes may cause problems. * *

* * Examples: *

* * 1. * Plugin has method * int add (int x, int y); * *

	 * int result = ((Integer)invoke ("add", new Object[] {Integer.valueOf(10),Integer.valueOf(5)}).intValue();
	 * //result (15)
	 * 
* * 2. Plugin has method * String randomize (String x); * *
	 * String result = (String)invoke("randomize", new Object[]{"foobar"});
	 * //result ("bfaoro")
	 * 
* * * @param methodName the name of the Methods to be called * @param params Parameters of the Method * @return returns the result of the method */ public Object invoke (String methodName, Object[] params) throws IPCException; /** * Test for existance of IPC method - params as above * @param methodName * @param params * @return */ public boolean canInvoke( String methodName, Object[] params ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/ipc/IPCException.java0000644000175000017500000000243511012741714023550 0ustar adrianadrian/* * Created on 02-May-2006 * Created by Damokles * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.ipc; /** * @author Damokles * */ public class IPCException extends Exception { public IPCException() { super(); } public IPCException(String message, Throwable cause) { super(message, cause); } public IPCException(String message) { super(message); } public IPCException(Throwable cause) { super(cause); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/logging/0000755000175000017500000000000011310377616021271 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/logging/LogAlertListener.java0000644000175000017500000000216011044765276025361 0ustar adrianadrian/* * Created on 1 Aug 2008 * Created by Allan Crooks * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.logging; /** * Listener class to be used to be notified of alerts to display to the user. * *

Note: This interface is intended to be implemented by plugins.

* @since 3.1.1.1 */ public interface LogAlertListener { public void alertRaised(LogAlert alert); } azureus-4.3.0.6/org/gudy/azureus2/plugins/logging/LoggerChannelListener.java0000644000175000017500000000206510010330740026334 0ustar adrianadrian/* * File : LoggerChannelListener.java * Created : 04-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.logging; /** * @author parg * */ public interface LoggerChannelListener { public void messageLogged( int type, String content ); public void messageLogged( String str, Throwable error ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/logging/LoggerAlertListener.java0000644000175000017500000000230510373051046026043 0ustar adrianadrian/* * Created on 11-Jul-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins.logging; public interface LoggerAlertListener { public void alertLogged( int alert_type, String message, boolean repeatable ); public void alertLogged( String message, Throwable e, boolean repeatable ); } azureus-4.3.0.6/org/gudy/azureus2/plugins/logging/FileLoggerAdapter.java0000644000175000017500000000243410402043230025436 0ustar adrianadrian/* * Created on Mar 3, 2006 11:39:23 AM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.logging; /** * Listener(s) for FileLogging * */ public class FileLoggerAdapter { /** * Called when we are about to log an event to file. * * @param lineOut line to be written to file (modifyable) * @return true-ok to log to file; false-skip logging to file */ public boolean logToFile(StringBuffer lineOut) { return true; } } azureus-4.3.0.6/org/gudy/azureus2/plugins/logging/LoggerChannel.java0000644000175000017500000001540611216142364024645 0ustar adrianadrian/* * File : LoggerChannel.java * Created : 28-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.logging; /** * Manipulation of a subsection (a channel) of Azureus' logging. * * A logger channel is created or retrieve via {@link Logger}. Typically, * a plugin has it's own channel which it can manipulate. All channels * are part of Azureus logging as a whole, meaning anything logged here will * also be fed to any functionality that operates on logging data (with * the exception of {@link Logger#getNullChannel(String)}). * * @since 2.0.7.0 */ public interface LoggerChannel { /** Information Log Type */ public static final int LT_INFORMATION = 1; /** Warning Log Type */ public static final int LT_WARNING = 2; /** Error Log Type */ public static final int LT_ERROR = 3; /** * Returns the name of the Logger Channel * * @return Logger channel name * @since 2.0.7.0 */ public String getName(); /** * Indicates whether or not logging is enabled - use to optimise calls to * the log methods that require resources to construct the message to be * logged. * * Note that this doesn't apply to alerts - these will always be handled * * @return Enabled state of logging * * @since 2.3.0.2 */ public boolean isEnabled(); /** * This causes the channel to also write to logs/name files in a cyclic * fashion (c.f. the debug_1/2._log files) * * @since 2.4.0.2 */ public void setDiagnostic(); public void setDiagnostic( long max_file_size, boolean timestamp ); /** * Log a message of a specific type to this channel's logger * * @param log_type LT_* constant * @param data text to log * * @since 2.0.7.0 */ public void log(int log_type, String data); /** * log text with implicit type {@link #LT_INFORMATION} * * @param data text to log * * @since 2.1.0.0 */ public void log(String data); /** * log an error with implicit type of {@link #LT_ERROR} * * @param error Throwable object to log * * @since 2.0.7.0 */ public void log(Throwable error); /** * log an error with implicit type of {@link #LT_ERROR} * * @param data text to log * @param error Throwable object to log * * @since 2.0.7.0 */ public void log(String data, Throwable error); /** * Log a string against a list of objects * * @param relatedTo a list of what this log is related to (ex. Peer, Torrent, * Download, Object) * @param log_type LT_* constant * @param data text to log * * @since 2.3.0.7 */ public void log(Object[] relatedTo, int log_type, String data); /** * Log an error against an object. * * @param relatedTo What this log is related to (ex. Peer, Torrent, * Download, Object, etc) * @param log_type LT_* constant * @param data text to log * * @since 2.3.0.7 */ public void log(Object relatedTo, int log_type, String data); /** * Log an error against an object. * * @param relatedTo What this log is related to (ex. Peer, Torrent, * Download, Object, etc) * @param data text to log * @param error Error that will be appended to the log entry * * @since 2.3.0.7 */ public void log(Object relatedTo, String data, Throwable error); /** * Log an error against a list of objects * * @param relatedTo a list of what this log is related to (ex. Peer, Torrent, * Download, Object) * @param data text to log * @param error Error that will be appended to the log entry * * @since 2.3.0.7 */ public void log(Object[] relatedTo, String data, Throwable error); /** * Log an error against a list of objects with implicit type {@link #LT_INFORMATION} * * @param relatedTo a list of what this log is related to (ex. Peer, Torrent, * Download, Object) * @param data text to log * @since 2.5.0.1 */ public void log(Object[] relatedTo, String data); /** * Log an error against an object with implicit type {@link #LT_INFORMATION} * * @param relatedTo What this log is related to (ex. Peer, Torrent, * Download, Object, etc) * @param data text to log * * @since 2.5.0.1 */ public void log(Object relatedTo, String data); /** * raise an alert to the user, if UI present * Note that messages shown to the user are filtered on unique message content * So if you raise an identical alert the second + subsequent messages will not be * shown. Thus, if you want "identical" messages to be shown, prefix them with something * unique like a timestamp. * * @param alert_type LT_* constant * @param message text to alert user with * * @since 2.0.8.0 */ public void logAlert(int alert_type, String message); /** * Alert the user of an error * * @param message text to alert user with * @param e Error that will be attached to the alert * * @since 2.1.0.2 */ public void logAlert(String message, Throwable e); /** * Raise an alert to the user, if UI present. Subsequent, identical messages * will always generate an alert (i.e. duplicates won't be filtered) * * @param alert_type LT_* constant * @param message text to alert user with * * @since 2.1.0.2 */ public void logAlertRepeatable(int alert_type, String message); /** * Raise an alert to the user, if UI present. Subsequent, identical messages * will always generate an alert (i.e. duplicates won't be filtered) * * @param message text to alert user with * @param e Error that will be attached to the alert * * @since 2.1.0.2 */ public void logAlertRepeatable(String message, Throwable e); /** * Add a LoggerChannelListener to this LoggerChannel * * @param l Listener to add * * @since 2.0.8.0 */ public void addListener(LoggerChannelListener l); /** * Remove a reviously added LoggerChannelListener * * @param l Listener to remove. * * @since 2.0.8.0 */ public void removeListener(LoggerChannelListener l); /** * Retrieve the parent Logger object for this LoggerChannel. * * @return Logger object * * @since 2.3.0.0 */ public Logger getLogger(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/logging/Logger.java0000644000175000017500000000635411044765276023372 0ustar adrianadrian/* * File : Logger.java * Created : 28-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins.logging; import org.gudy.azureus2.plugins.PluginInterface; /** * Logging utilities class * * @since 2.0.7.0 */ public interface Logger { /** * Create a normal logging channel. Multiple calls to this method with the * same name parameter results in different channels. * * @param name Name of LoggerChannel * @return a new LoggerChannel * * @since 2.0.7.0 */ public LoggerChannel getChannel(String name); /** * Create a timestamped logging channel. Multiple calls to this method with * the same name parameter results in different channels. * * @param name Name of LoggerChannel * @return a new LoggerChannel * * @since 2.3.0.0 */ public LoggerChannel getTimeStampedChannel(String name); /** * Create a logger channel that doesn't output to the standard AZ log. * Add listeners to it if output needs to be routed somewhere. * Multiple calls to this method with the same name parameter results in * different channels * * @param name Name of LoggerChannel * @return a new LoggerChannel * * @since 2.3.0.0 */ public LoggerChannel getNullChannel(String name); /** * Retrieve all the channels that have been created for all plugins. * * @return Array of LoggerChannel objects * * @since 2.1.0.0 */ public LoggerChannel[] getChannels(); /** * Retrieve the PluginInterface * * @return PluginInterface object * * @since 2.3.0.0 */ public PluginInterface getPluginInterface(); /** * Add LoggerAlertListener for all alerts raised. It might be a * better idea to use {@link #addAlertListener(LogAlertListener)}, * as it is more flexible. * * @param listener Listener to add * @see #addAlertListener(LogAlertListener) * @since 2.3.0.6 */ public void addAlertListener(LoggerAlertListener listener); /** * Remove previously added AlertListener. * * @param listener LoggerAlertListener to remove * @since 2.3.0.6 */ public void removeAlertListener(LoggerAlertListener listener); /** * Add a listener to be informed of any alerts to be displayed to users. * * @since 3.1.1.1 */ public void addAlertListener(LogAlertListener listener); /** * Remove a previously added alert listener. * * @since 3.1.1.1 */ public void removeAlertListener(LogAlertListener listener); public void addFileLoggingListener(FileLoggerAdapter listener); public void removeFileLoggingListener(FileLoggerAdapter listener); }azureus-4.3.0.6/org/gudy/azureus2/plugins/logging/LogAlert.java0000644000175000017500000000545211044765276023662 0ustar adrianadrian/* * Created on 1 Aug 2008 * Created by Allan Crooks * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.plugins.logging; /** * A LogAlert represents a message that should be displayed to the * user. * *

Note: Only for implementation by Azureus, not plugins.

* * @since 3.1.1.1 */ public interface LogAlert { /** * Log Type: Information */ public int LT_INFORMATION = 1; /** * Log Type: Warning */ public int LT_WARNING = 2; /** * Log Type: Error */ public int LT_ERROR = 3; /** * How long should to display the alert for - this will be the value that was given * when creating the alert. * * @return How long to display the timeout for - -1 for no explicit value, * 0 to display it indefinitely, otherwise it is the number of seconds to * display the value for. */ public int getGivenTimeoutSecs(); /** * How long should to display the alert for - this will be either the explicit value * given when creating the alert, or a value determined from Azureus's behaviour and * its configuration settings. * * @return How long to display the timeout for - 0 to display it indefinitely, * otherwise it is the number of seconds to display the value for. */ public int getTimeoutSecs(); /** * Returns the text of the message - this may include formatting tags (for example, * hyperlinks). * * @return The text to display. */ public String getText(); /** * Returns the text of the message - this will have any formatting stripped out. * * @return The text to display. */ public String getPlainText(); /** * Returns the error associated with the alert - null if there is no error. */ public Throwable getError(); /** * Returns the log type of the alert - the value of which will be one of the LT_ * constants defined above. */ public int getType(); /** * Returns the objects associated with the alert - this will return null if * the alert isn't associated with such any objects. */ public Object[] getContext(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginLauncher.java0000644000175000017500000000237710373051030023422 0ustar adrianadrian/* * Created on 25-Jul-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.plugins; import org.gudy.azureus2.pluginsimpl.local.launch.PluginLauncherImpl; public class PluginLauncher { /** * An entry point for launching Azureus via a LaunchablePlugin * @param args */ public static void main( String[] args ) { PluginLauncherImpl.launch( args ); } } azureus-4.3.0.6/org/gudy/azureus2/plugins/PluginView.java0000644000175000017500000000236710307201604022573 0ustar adrianadrian/* * File : PluginView.java * Created : 2 nov. 2003 20:58:14 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.plugins; import org.gudy.azureus2.ui.swt.views.AbstractIView; /** * This Class must be extended by Plugin willing to have their own view in Azureus * @author Olivier * @deprecated */ public abstract class PluginView extends AbstractIView { /** * @return The name of the Plugin, as seen in the View > Plugins menu * * @since 2.0.4.0 */ public abstract String getPluginViewName(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/dht/0000755000175000017500000000000011310377420020413 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/dht/mainline/0000755000175000017500000000000011310377616022216 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/plugins/dht/mainline/MainlineDHTProvider.java0000644000175000017500000000362210743534364026677 0ustar adrianadrian/* * Created on 14 Jan 2008 * Created by Allan Crooks * Copyright (C) 2008 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.dht.mainline; /** * The interface that a plugin (or a helper class) must implement to * enable DHT support inside Azureus. By implementing this class, and * then registering it via {@link MainlineDHTManager#setProvider(MainlineDHTProvider)}, * Azureus will indicate DHT support via the BT handshake, and exchange PORT * messages with other clients - passing received messages to this class. */ public interface MainlineDHTProvider { /** * This method is called by Azureus when a PORT message is received * by a peer. Note: When this method is called, try to make * sure that it won't take long to return - if it needs to do something * time-consuming, then the work should be delegated to another thread. * * @param ip_addr IP address of peer. * @param port DHT port of peer. */ public void notifyOfIncomingPort(String ip_addr, int port); /** * Returns the DHT port used by the plugin. */ public int getDHTPort(); } azureus-4.3.0.6/org/gudy/azureus2/plugins/dht/mainline/MainlineDHTManager.java0000644000175000017500000000342410743534364026457 0ustar adrianadrian/* * Created on 14 Jan 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.plugins.dht.mainline; /** * Used for registering and unregistering plugins which connect to the mainline DHT * network. Plugins must implement the {@link MainlineDHTProvider} interface and * register with this class so that Azureus can indicate it provides DHT support. * * @since 3.0.4.3 */ public interface MainlineDHTManager { /** * Registers an object to be used for mainline DHT support. There is only one * slot available, so if multiple plugins attempt to register themselves, * only the last one will be used. If you pass null as an argument, it * will cause Azureus to disable support for mainline DHT. */ public void setProvider(MainlineDHTProvider provider); /** * Returns the current DHT provider, or null if there isn't one. */ public MainlineDHTProvider getProvider(); } azureus-4.3.0.6/org/gudy/azureus2/internat/0000755000175000017500000000000011310377466020011 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_es_ES.properties0000644000175000017500000055727711301156004026114 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Archivo .torrent... Main.parameter.usage=Uso : java org.gudy.azureus2.cl.Main [par\u00e1metros] "archivo.torrent" "ruta de descarga" Main.parameter.maxUploads=N\u00famero m\u00e1ximo de env\u00edos simult\u00e1neos Main.parameter.maxSpeed=Velocidad m\u00e1xima de subida en bytes/seg MainWindow.menu.file=&Archivo MainWindow.menu.file.open=&Abrir MainWindow.menu.file.create=Nuevo .&torrent... MainWindow.menu.file.create.fromfile=Desde un &archivo MainWindow.menu.file.create.fromdir=Desde una &carpeta MainWindow.menu.file.export=&Exportar un XML .torrent... MainWindow.menu.file.import=&Importar un XML .torrent... MainWindow.menu.file.closetab=Cerrar &Pesta\u00f1a MainWindow.menu.file.closewindow=Cerrar &Ventana MainWindow.menu.file.exit=&Salir MainWindow.dialog.choose.file=Seleccione el archivo .torrent MainWindow.menu.file.folder=&Carpeta... MainWindow.dialog.choose.folder=Seleccione la carpeta MainWindow.menu.view=&Vista MainWindow.menu.view.show=Mostrar MainWindow.menu.view.mytorrents=Mis &Torrents MainWindow.menu.view.open_global_transfer_bar=Barra de Transferencias MainWindow.menu.view.configuration=&Opciones MainWindow.menu.view.console=Con&sola MainWindow.menu.view.irc=Cliente &IRC MainWindow.menu.view.allpeers=Todos los Pares MainWindow.menu.view.detailedlist=Lista &Detallada MainWindow.menu.closealldetails=Cerrar todos los &detalles MainWindow.menu.closealldownloadbars=Cerrar las &barras de descarga MainWindow.menu.language=&Idioma ConfigView.section.language=Idioma MainWindow.menu.window=&Ventana MainWindow.menu.window.minimize=&Minimizar MainWindow.menu.window.zoom=Ampliar/reducir MainWindow.menu.window.alltofront=Poner todo en &1er. plano MainWindow.menu.help=A&yuda MainWindow.menu.help.about=Acerca de Vuze MainWindow.about.title=Acerca MainWindow.about.section.developers=Desarrolladores MainWindow.about.section.translators=Traductores MainWindow.about.section.system=Sistema MainWindow.about.internet.homepage=P\u00e1gina de Vuze MainWindow.about.internet.sourceforge=P\u00e1gina del proyecto en Sourceforge MainWindow.about.internet.sourceforgedownloads=Descargas desde Sourceforge MainWindow.about.internet.bugreports=Informe de fallos MainWindow.about.internet.forumdiscussion=Foros MainWindow.dialog.choose.savepath=Seleccione la carpeta donde guardar la descarga MainWindow.dialog.choose.savepath_forallfiles=Seleccione la carpeta para las descargas MainWindow.status.latestversion=Ultima versi\u00f3n MainWindow.status.latestversion.clickupdate=Clic para actualizar MainWindow.status.unknown=Desconocido MainWindow.status.checking=Comprobando MyTorrentsView.mytorrents=Mis Torrents TableColumn.header.name=Nombre TableColumn.header.size=Tama\u00f1o TableColumn.header.done=Completado TableColumn.header.done.info=Porcentaje terminado de la tarea actual TableColumn.header.status=Estado TableColumn.header.status.info=Lo que est\u00e1 haciendo el torrent TableColumn.header.seeds=Semillas TableColumn.header.seeds.info=N\u00ba de semillas conectadas a (N\u00ba total semillas) TableColumn.header.peers=Clientes TableColumn.header.peers.info=N\u00ba de clientes conectados a (N\u00ba total clientes) TableColumn.header.completed=Completado TableColumn.header.completed.info=n\u00ba de pares que han completado la descarga del torrent seg\u00fan informa el rastreador TableColumn.header.downspeed=Vel. descarga TableColumn.header.upspeed=Vel. subida TableColumn.header.eta=Tiempo estimado TableColumn.header.tracker=Estado Rastreador TableColumn.header.tracker.info=Estado del rastreador TableColumn.header.trackernextaccess=Sigte. Acceso al rastreador TableColumn.header.trackernextaccess.info=Cu\u00e1ndo ser\u00e1 el siguiente acceso al rastreador TableColumn.header.priority=Prioridad TableColumn.header.priority.info=Determina de cuanto ancho de banda dispone el torrent para compartir TableColumn.header.seeds.fullcopycalc=%2 copias completas asumidas por cada %1 clientes MyTorrentsView.menu.showdetails=Mostrar &detalles MyTorrentsView.menu.showdownloadbar=Mostrar &barra de descarga MyTorrentsView.menu.open=&Abrir archivo MyTorrentsView.menu.setpriority=Establecer &prioridad MyTorrentsView.menu.setpriority.high=&Alta MyTorrentsView.menu.setpriority.low=&Baja MyTorrentsView.menu.start=&Iniciar MyTorrentsView.menu.stop=&Detener MyTorrentsView.menu.remove=&Eliminar MyTorrentsView.menu.changeTracker=&A\u00f1adir la URL del Rastreador TrayWindow.menu.exit=&Salir TrayWindow.menu.show=&Mostrar Vuze SystemTray.menu.exit=&Salir SystemTray.menu.closealldownloadbars=Cerrar &todas la barras de descarga SystemTray.menu.open_global_transfer_bar=Mostrar la Barra de Transferencias SystemTray.menu.show=&Mostrar Vuze PeersView.ip.info=IP del cliente PeersView.port=Puerto PeersView.port.info=Puerto utilizado PeersView.T.info=L (local): t\u00fa has establecido la conexi\u00f3n; R (remota): el otro cliente estableci\u00f3 la conexi\u00f3n. PeersView.T.L.tooltip=T\u00fa estableciste la conexi\u00f3n PeersView.T.R.tooltip=El otro cliente estableci\u00f3 la conexi\u00f3n PeersView.I1=Isc PeersView.I1.info=\u00bfEst\u00e1s interesado en lo que tiene el otro cliente? (Interesado por su cliente) PeersView.C1=Cpc PeersView.C1.info=Si el otro cliente no te deja descargar (Choked por el cliente) PeersView.pieces=Partes PeersView.downloadspeed=Vel. descarga PeersView.download=Recibido PeersView.I2=Imc PeersView.I2.info=\u00bfEst\u00e1 el otro cliente interesado en lo que tienes? (Interesado por mi cliente) PeersView.C2=Cac PeersView.C2.info=Si no dejas descargar al otro cliente (Choking al otro cliente) PeersView.uploadspeed=Vel. subida PeersView.uploadspeed.info=Tu velocidad de subida para el otro cliente PeersView.upload=Enviado PeersView.upload.info=Tu subida total al cliente. PeersView.statup=Subida media PeersView.statup.info=Un valor estimado de la vel. de subida al cliente PeersView.S.info=Snubbed: Un cliente puede ser "ignorado-por-no-cumplir" (snubbed) manual o autom\u00e1ticamente (por no servirte los datos con la suficiente presteza) PeersView.downloadspeedoverall=Velocidad media de descarga PeersView.optunchoke=Unchoke Opc. PeersView.client=Cliente PeersView.client.info=Tipo de cliente BT que usa el cliente PeersView.menu.snubbed=I&gnorado PeersView.title.short=Clientes PeersView.title.full=Clientes AllPeersView.title.full=Todos los Pares ConfigView.section.files=Archivos ConfigView.label.usefastresume=Usar modo de reanudaci\u00f3n r\u00e1pida ConfigView.label.incrementalfile=Crear los archivos incrementalmente (necesario para operar con FAT32 desde Linux) ConfigView.label.defaultsavepath=Ruta de descarga (por defecto) ConfigView.button.browse=&Examinar... ConfigView.dialog.choosedefaultsavepath=Seleccione la carpeta para las descargas ConfigView.section.server=Conexi\u00f3n ConfigView.section.global=Global ConfigView.label.disconnetseed=Desconectar semillas al servir ConfigView.label.switchpriority=Autoestablecer prioridad baja al servir ConfigView.label.maxdownloads=Descargas simult\u00e1neas - N\u00ba m\u00e1ximo [0 : sin l\u00edmite]\n - No puede ser mayor al n\u00ba m\u00e1x. de torrents activos ConfigView.label.maxdownloads.tooltip=Siempre podr\u00e1s descargar el n\u00ba que pongas aqu\u00ed, con una excepci\u00f3n.\nUn torrent completado que cumpla la Primera Prioridad,si es necesario puede reclamar una posici\u00f3n activa para descarga. ConfigView.label.maxactivetorrents=Torrents activos - N\u00ba m\u00e1x. [0 : sin l\u00edmite]\n - Los nuevos torrents no se iniciar\u00e1n si est\u00e1 descargando/sirviendo m\u00e1s de ConfigView.label.priorityExtensions=Autopriorizar los archivos con\n (ejemplo: .txt;.nfo;.jpg) ConfigView.section.transfer=Transferencia ConfigView.label.maxuploads='Puestos de subida' para cada torrent - N\u00ba m\u00e1ximo (por defecto) ConfigView.label.maxuploadspeed=Subida - Velocidad m\u00e1xima en KB/s (global) [0 : sin l\u00edmite] ConfigView.label.saveresumeinterval=Actualizar los datos para resumir cada ConfigView.unlimited=Sin l\u00edmite ConfigView.section.display=Visualizaci\u00f3n ConfigView.label.opendetails=Abrir autom\u00e1ticamente la 'Barra de Detalles' ConfigView.label.openbar=Abrir autom\u00e1ticamente la 'Barra de Descarga' ConfigView.label.use_old_speed_menus=Usar el anterior estilo para agilizar menus [precisa reinicio] ConfigView.label.closetotray=Cerrar como icono en la 'Bandeja de Sistema' ConfigView.label.minimizetotray=Minimizar como icono en la 'Bandeja de Sistema' ConfigView.section.start=Comienzo ConfigView.label.showsplash=Mostrar pantalla de presentaci\u00f3n al inicio ConfigView.label.autoupdate=Abrir el di\u00e1logo de actualizaciones cuando haya alguna disponible ConfigView.label.openconsole=Abrir la consola durante el inicio ConfigView.label.openconfig=Abrir las opciones durante el inicio ConfigView.label.startminimized=Empezar minimizado ConfigView.section.irc=Cliente IRC ConfigView.label.ircwiki=Vea http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Servidor ConfigView.label.ircchannel=Canal ConfigView.label.irclogin=Apodo ConfigView.group.irctitle=Preferencias de IRC ConfigView.boolean.ircsendinfo=Permitir el env\u00edo an\u00f3nimo de tus preferencias a\nlos operadores de canal para que puedan ayudarte ConfigView.boolean.irclog=Registrar la actividad del canal (en IRC_log.htm) ConfigView.section.security=Seguridad ConfigView.label.password=Proteger Vuze mediante contrase\u00f1a.\n(al restaurar Vuze se te preguntar\u00e1 la contrase\u00f1a) ConfigView.label.passwordconfirm=Contrase\u00f1a (confirmar) ConfigView.label.passwordmatch=Contrase\u00f1a activada : ConfigView.label.passwordmatchno=No / Las contrase\u00f1as no concuerdan ConfigView.label.passwordmatchyes=Si ConfigView.button.save=Guardar ConfigView.title.short=Opciones ConfigView.title.full=Opciones ConfigView.title.full._mac=Preferencias ConsoleView.title.short=Consola ConsoleView.title.full=Consola FileItem.write=Escritura FileItem.read=Lectura FileItem.normal=Normal FileItem.high=Alta FileItem.donotdownload=No descargar FileItem.delete=Eliminar FilesView.name=Nombre FilesView.name.fastRename=Renombrado r\u00e1pido FilesView.size=Tama\u00f1o FilesView.done=Completado FilesView.firstpiece=1\u00aa parte N\u00ba FilesView.numberofpieces=N\u00ba de partes FilesView.pieces=Partes FilesView.mode=Modo FilesView.priority=Prioridad FilesView.menu.open=&Abrir FilesView.menu.setpriority=&Establecer prioridad FilesView.menu.setpriority.high=&Alta FilesView.menu.setpriority.skipped=N&o descargar FilesView.title.short=Archivos FilesView.title.full=Archivos GeneralView.section.downloaded=Descargado GeneralView.label.status.file=Estado archivo GeneralView.label.status.pieces=Estado partes GeneralView.section.availability=Disponibilidad GeneralView.label.status.pieces_available=Estado partes GeneralView.section.transfer=Transferencia GeneralView.section.info=Informaci\u00f3n GeneralView.label.timeelapsed=Tiempo activo : GeneralView.label.remaining=Restante : GeneralView.label.downloaded=Descargado : GeneralView.label.downloadspeed=Vel. descarga : GeneralView.label.maxuploads=Puestos de Subida : GeneralView.label.maxuploads.tooltip=N\u00ba m\u00e1x de clientes que tendr\u00e1n la posibilidad de descargar (unchocked) en un momento dado. GeneralView.label.uploaded=Enviado : GeneralView.label.uploadspeed=Vel. subida : GeneralView.label.seeds=Semillas : GeneralView.label.peers=Clientes : GeneralView.label.completed=Completado : GeneralView.label.totalspeed=Veloc. del enjambre : GeneralView.label.totalspeed.tooltip=Velocidad total (y media) de todos los clientes a los que est\u00e1s conectado. GeneralView.label.averagespeed=de media GeneralView.label.filename=Nombre : GeneralView.label.totalsize=Tama\u00f1o total : GeneralView.label.savein=Guardado en : GeneralView.label.hash=Hash : GeneralView.label.numberofpieces=N\u00ba de partes : GeneralView.label.size=Tama\u00f1o parte : GeneralView.label.tracker=Estado Rastreador : GeneralView.label.updatein=Se actualizar\u00e1 en : GeneralView.label.trackerurl=URL del rastreador : GeneralView.label.trackerurlupdate=Actualizar Rastreador GeneralView.label.comment=Comentarios del Torrent : GeneralView.label.user_comment=Comentario del Usuario : GeneralView.label.status=Estado : ManagerItem.waiting=Esperando ManagerItem.allocating=Reservando espacio ManagerItem.checking=Comprobando ManagerItem.ready=Esperando a poner otro(s) torrent(s) en la cola ManagerItem.downloading=Descargando ManagerItem.seeding=Compartiendo ManagerItem.stopped=Detenido ManagerItem.high=Alta ManagerItem.low=Baja MinimizedWindow.name=Nombre: MinimizedWindow.all_transfers=Transferencias de Vuze PiecesView.#=N\u00ba PiecesView.size=Tama\u00f1o PiecesView.numberofblocks=N\u00ba de bloques PiecesView.blocks=Bloques PiecesView.completed=Completados PiecesView.availability=Disponibilidad PiecesView.reservedby=Reservado PiecesView.writers=Donantes de Bloques PiecesView.title.short=Partes PiecesView.title.full=Partes SystemTray.tooltip.seeding=%1 compartiendo, SystemTray.tooltip.downloading=%1 descargando, DownloadManager.error.filenotfound=No se encuentra el archivo DownloadManager.error.fileempty=El archivo .torrent est\u00e1 vac\u00edo DownloadManager.error.filetoobig=El archivo .torrent es muy grande DownloadManager.error.filewithouttorrentinfo=No hay informaci\u00f3n torrent en el archivo DownloadManager.error.unsupportedencoding=Codificaci\u00f3n no soportada DownloadManager.error.ioerror=Error de E/S DownloadManager.error.sha1=Error de Algoritmo (SHA1) PeerManager.status.offline=Error de conexi\u00f3n PeerManager.status.ok=Activo PeerManager.status.checking=Comprobando PeerManager.status.finished=Completado PeerManager.status.finishedin=Completado en MainWindow.upgrade.assistant=Asistente de actualizaci\u00f3n MainWindow.upgrade.newerversion=Tiene disponible para descarga una nueva versi\u00f3n de Vuze MainWindow.upgrade.explanation=Este asistente descargar\u00e1 la nueva versi\u00f3n en la carpeta de Vuze y luego reiniciar\u00e1 Vuze MainWindow.upgrade.explanation.manual=Usted puede actualizar manualmente cerrando Vuze descargando la nueva versi\u00f3n y reinici\u00e1ndolo MainWindow.upgrade.step1=Paso 1: Descarga de la nueva versi\u00f3n MainWindow.upgrade.step2=Paso 2: Cerrar esta versi\u00f3n para reiniciar con la nueva versi\u00f3n de Vuze MainWindow.upgrade.hint1=Consejo:\tSi presionas 'Terminar' , el proceso ser\u00e1 autom\u00e1tico MainWindow.upgrade.hint2=Consejo:\tSi quieres cerrar Vuze m\u00e1s tarde, presiona Cancelar, cierra\n\ty renombra Azureus2-new.jar a Azureus2.jar MainWindow.upgrade.error.downloading.hint=Error:\tImposible descargar la nueva versi\u00f3n, por favor actualice manualmente MainWindow.upgrade.section.info=Nueva versi\u00f3n disponible MainWindow.upgrade.section.manual=Actualizaci\u00f3n manual MainWindow.upgrade.section.automatic=Actualizaci\u00f3n autom\u00e1tica MainWindow.upgrade.tooltip.progressbar=El progreso de la descarga se muestra aqu\u00ed Button.next=Siguiente Button.finish=Terminar Button.cancel=&Cancelar LocaleUtil.title=Elija la codificaci\u00f3n LocaleUtil.section.chooseencoding=Elija la codificaci\u00f3n para el archivo LocaleUtil.label.chooseencoding=Por favor seleccione la codificaci\u00f3n que mejor corresponda LocaleUtil.label.hint.doubleclick=Pista: doble clic en una fila selecciona esa codificaci\u00f3n y cierra el cuadro de di\u00e1logo LocaleUtil.label.checkbox.rememberdecision=Recordar lo que decida para los dem\u00e1s archivos LocaleUtil.column.encoding=Codificaci\u00f3n IrcClient.defaultChannel=#Azureus-Espa\u00f1ol IrcClient.copyright=Usando PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Conectando a IrcClient.connected=Conectado con IrcClient.joining=Uni\u00e9ndose a IrcClient.channel=Canal IrcClient.joined=unido correctamente IrcClient.hasjoined=se ha unido IrcClient.haskicked=ha sido pateado IrcClient.hasleft=se ha ido IrcClient.nowknown=es ahora conocido como IrcClient.topicforchannel=Tema para el canal IrcClient.disconnected=Desconectado de IrcClient.noNick=No has especificado ning\u00fan apodo. Por favor ve a la pantalla de 'Opciones' IrcView.actionnotsupported=Esta acci\u00f3n no est\u00e1 soportada IrcView.clientsconnected=Usuarios IrcView.privateto=Para IrcView.privatefrom=De IrcView.noticefrom=Aviso : IrcView.errormsg=Sintaxis incorrecta en /msg : /msg usuario mensaje IrcView.help=Los comandos v\u00e1lidos son :\n . /help : muestra este mensaje\n . /nick | /name : cambia tu apodo \n . /me acci\u00f3n : env\u00eda una acci\u00f3n \n ./ msg apodo mensaje : envia un mensaje privado a \n . /r mensaje : responde el ultimo mensaje privado \n . /join #canalB : (no pinches aqu\u00ed, es s\u00f3lo un ejemplo) : cambia el canal actual al canalB PasswordWindow.title=Vuze est\u00e1 protegido por contrase\u00f1a PasswordWindow.passwordprotected=Vuze est\u00e1 protegido por contrase\u00f1a.\nPara restaurar Vuze teclee aqu\u00ed por favor su contrase\u00f1a : Button.ok=&Aceptar TrackerChangerWindow.title=A\u00f1adir Rastreador (Tracker) TrackerChangerWindow.newtracker=Escriba la nueva url del Rastreador PeersView.discarded=Descartado PeersView.discarded.info=Datos que de alguna forma has recibido, pero no los necesitas, as\u00ed que los descartas. discarded=descartados MyTorrentsView.#=N\u00ba MyTorrentsView.menu.move=&Mover MyTorrentsView.menu.moveUp=A&rriba MyTorrentsView.menu.moveDown=A&bajo GeneralView.label.hashfails=Hash Fallidos : GeneralView.label.shareRatio=Compartici\u00f3n media : ConfigView.section.downloadManagement=Administrador de descargas ConfigView.label.startRatioPeers=Empezar a servir cuando haya menos de 1 semilla para ConfigView.text.neverStop=No detener nunca ConfigView.text.neverStart=No empezar nunca ConfigView.text.peers=Clientes ConfigView.label.checkOncompletion=Re-Comprobar las partes una vez descargadas wizard.title=Crear un .torrent wizard.previous=< Anterior wizard.next=Siguiente > wizard.finish=Terminado wizard.mode=Rastreador / Modo wizard.tracker=Rastreador: wizard.invalidurl=Esta URL no es v\u00e1lida wizard.singlefile=Archivo \u00fanico wizard.singlefile.help=Crear el .torrent de un \u00fanico archivo wizard.directory=Carpeta wizard.directory.help=Crear un .torrent desde una carpeta wizard.choosefile=Elige el archivo wizard.file=Archivo : wizard.browse=Examinar... wizard.choosedirectory=Elige la carpeta wizard.invalidfile=\u00a1Archivo inv\u00e1lido! wizard.invaliddirectory=\u00a1Carpeta inv\u00e1lida! wizard.torrentFile=Archivo .torrent wizard.choosetorrent=Por favor elige el archivo .torrent a crear wizard.information=Informaci\u00f3n wizard.notimplemented=A\u00fan sin implementar wizard.progresstitle=Creando archivo .torrent wizard.savingfile=Guardando archivo... wizard.filesaved=Archivo guardado. wizard.close=Cerrar Torrent.create.progress.piecelength=Longitud de la parte: Torrent.create.progress.piececount=Cantidad de partes: Torrent.create.progress.totalfilesize=Tama\u00f1o total del archivo: Torrent.create.progress.totalfilecount=Cantidad total de archivos: Torrent.create.progress.parsingfiles=Analizando archivos Torrent.create.progress.hashing=Comprobando archivos MainWindow.upgrade.downloadingfrom=Descargando desde : MainWindow.menu.view.ipFilter=Filtros de &IP ConfigView.section.ipfilter=Filtros de IP ConfigView.section.ipfilter.description=Descripci\u00f3n ConfigView.section.ipfilter.start=IP inicial ConfigView.section.ipfilter.end=IP final ConfigView.section.ipfilter.add=A\u00f1adir ConfigView.section.ipfilter.remove=Eliminar ConfigView.section.ipfilter.edit=Editar ConfigView.section.ipfilter.save=Guardar ConfigView.section.ipfilter.editFilter=Edici\u00f3n del filtro ConfigView.section.ipfilter.enable=Activar PeersView.menu.close=&Cerrar seedmore.title=Este torrent no ha sido compartido lo suficiente seedmore.shareratio=Has compartido este torrent hasta el seedmore.uploadmore=En la red bittorrent, compartir menos del 100x100 no es algo bueno.\nDeber\u00edas servir m\u00e1s este torrent.\n\n\t\u00bfSeguro que deseas proceder? ConfigView.label.showpopuponclose=Pedir confirmaci\u00f3n al detener un torrent compartido cuando su promedio es menor de 1 ConfigView.label.startNumSeeds=\nEmpezar a servir si hay menos de\n - Se salta las dem\u00e1s reglas ConfigView.label.seeds=semillas ConfigView.section.seeding=Compartiendo MyTorrentsView.menu.removeand=E&liminar y MyTorrentsView.menu.removeand.deletetorrent=Borrar archivo .&torrent MyTorrentsView.menu.removeand.deletedata=Borrar &datos MyTorrentsView.menu.removeand.deleteboth=Borrar &ambos deletedata.title=Cuidado deletedata.message1=Va usted a eliminar LOS DATOS guardados en :\n deletedata.noprompt=No preguntarme de nuevo MainWindow.menu.file.configure=Asistente de con&figuraci\u00f3n... configureWizard.title=Asistente de configuraci\u00f3n configureWizard.welcome.title=Bienvenido al asistente de configuraci\u00f3n de Vuze configureWizard.welcome.message=Este asistente te ayudar\u00e1 a configurar las opciones m\u00e1s comunes de Azureus. Puedes modificar con mayor profundidad estas opciones en el men\u00fa 'Herramientas->Opciones'. configureWizard.transfer.title=Configuraci\u00f3n de la conexi\u00f3n y las transferencias configureWizard.transfer.hint=Consejo: Usa un valor un poco menor a la velocidad de tu l\u00ednea. configureWizard.transfer.message=Selecciona una conexi\u00f3n de la lista siguiente. Ten en cuenta que si env\u00edas datos a una velocidad baja tus descargas ser\u00e1n lentas. Como la velocidad de subida s\u00f3lo cuenta por torrent INDIVIDUAL que est\u00e1s descargando, si intentas descargar muchos torrents simult\u00e1neamente obtendr\u00e1s velocidades bajas. Recomendamos usar 5kB/s por torrent como un m\u00ednimo ESTRICTO. Cuanto m\u00e1s r\u00e1pido env\u00edes, m\u00e1s r\u00e1pido descargar\u00e1s (con respecto a la velocidad del torrent). configureWizard.transfer.connection=L\u00ednea configureWizard.transfer.connection.0=Personalizado configureWizard.transfer.maxUpSpeed=Velocidad m\u00e1xima para enviar (kB/s) configureWizard.transfer.maxActiveTorrents=M\u00e1x. Activos configureWizard.transfer.maxDownloads=M\u00e1x. Descargas configureWizard.transfer.maxUploadsPerTorrent=M\u00e1x. env\u00edos por torrent configureWizard.nat.title=NAT / Puertos del servidor configureWizard.nat.message=Para obtener lo mejor de BitTorrent, se recomienda encarecidamente que sea totalmente accesible desde Internet. Esta herramienta te permite probar y/o cambiar los puertos que se usan para aceptar conexiones entrantes de los clientes.\n\nNOTA: Esta herramienta s\u00f3lo prueba las conexiones TCP. La BD Distribuida tambi\u00e9n necesita conexiones UDP entrantes, pero te avisar\u00e1 autom\u00e1ticamente si descubre un cortafuegos bloque\u00e1ndolas.\n\nNOTA: el programa se reserva internamente el puerto TCP 6880, as\u00ed que no puedes usar \u00e9ste. configureWizard.nat.test=Probar configureWizard.nat.testing=Probando puertos configureWizard.nat.ok=OK configureWizard.nat.ko=Error de NAT configureWizard.nat.unable=Imposible de comprobar: O el puerto no es v\u00e1lido, o ha fallado el servicio a probar.\nPuede ser que otra aplicaci\u00f3n ya estuviera usando este puerto. configureWizard.file.title=Torrents / Archivos configureWizard.file.message1=Vuze guardar\u00e1 los .torrent abiertos en una carpeta espec\u00edfica, puedes elegir esta carpeta aqu\u00ed: configureWizard.file.path=Ruta configureWizard.file.browse=Examinar configureWizard.file.message2=Vuze es capaz de reanudar instant\u00e1neamente tus descargas a\u00f1adiendo algunos datos de resumen a tus .torrents. Usando esta caracter\u00edstica, tambi\u00e9n podr\u00e1s reanudar archivos parcialmente descargados. configureWizard.file.fastResume=Activar reanudaci\u00f3n r\u00e1pida configureWizard.file.invalidPath=Carpeta inv\u00e1lida configureWizard.finish.title=Completado configureWizard.finish.message=Ahora ya tienes configurado Vuze \u00a1disfr\u00fatalo! wizard.close.confirmation=Confirmaci\u00f3n wizard.close.message=\u00bfQuieres que se muestre este Asistente la pr\u00f3xima vez que inicies Vuze exportTorrentWizard.title=Exportar un XML .torrent exportTorrentWizard.torrentfile.title=Selecci\u00f3n del archivo .torrent exportTorrentWizard.torrentfile.message=Selecciona el archivo .torrent a exportar exportTorrentWizard.torrentfile.path=Ruta exportTorrentWizard.torrentfile.browse=Examinar exportTorrentWizard.torrentfile.invalidPath=Archivo .torrent inv\u00e1lido exportTorrentWizard.exportfile.title=Exportar los archivos seleccionados exportTorrentWizard.exportfile.message=Introduzca el archivo XML al que se va a exportar exportTorrentWizard.exportfile.path=Ruta exportTorrentWizard.exportfile.browse=Examinar exportTorrentWizard.exportfile.invalidPath=Archivo de exportaci\u00f3n inv\u00e1lido exportTorrentWizard.finish.title=Completado exportTorrentWizard.finish.message=El proceso de exportaci\u00f3n se complet\u00f3 correctamente exportTorrentWizard.process.inputfilebad.title=Archivo .torrent inv\u00e1lido exportTorrentWizard.process.inputfilebad.message=Ocurri\u00f3 un error cuando se estaba accediendo a los archivos: exportTorrentWizard.process.outputfileexists.title=El archivo existe exportTorrentWizard.process.outputfileexists.message=El archivo de salida existe - \u00bfsobreescribir? exportTorrentWizard.process.torrentfail.title=Fall\u00f3 la lectura del .torrent exportTorrentWizard.process.exportfail.title=Fall\u00f3 el proceso de exportaci\u00f3n exportTorrentWizard.process.unknownfail.title=Error inesperado importTorrentWizard.title=Importar un XML .torrent importTorrentWizard.torrentfile.title=Selecci\u00f3n del archivo .torrent importTorrentWizard.torrentfile.message=Selecciona el archivo .torrent a importar importTorrentWizard.torrentfile.path=Ruta importTorrentWizard.torrentfile.browse=Examinar importTorrentWizard.torrentfile.invalidPath=Archivo .torrent inv\u00e1lido importTorrentWizard.importfile.title=Selecci\u00f3n de archivos a Importar importTorrentWizard.importfile.message=Especifique el archivo XML a importar importTorrentWizard.importfile.path=Ruta importTorrentWizard.importfile.browse=Examinar importTorrentWizard.importfile.invalidPath=Archivo a importar inv\u00e1lido importTorrentWizard.finish.title=Completado importTorrentWizard.finish.message=La importaci\u00f3n se complet\u00f3 correctamente importTorrentWizard.process.inputfilebad.title=Archivo a importar inv\u00e1lido importTorrentWizard.process.inputfilebad.message=Ocurri\u00f3 un error cuando se estaba accediendo a los archivos: importTorrentWizard.process.outputfileexists.title=El archivo existe importTorrentWizard.process.outputfileexists.message=Ya existe el archivo de salida - \u00bfsobreescribir? importTorrentWizard.process.torrentfail.title=Fallo al escribir torrent importTorrentWizard.process.importfail.title=Fallo al importar torrent importTorrentWizard.process.unknownfail.title=Error Inesperado ConfigView.label.bindip=Vincularse a la direcci\u00f3n IP local o interfaz ConfigView.label.xfs.allocation=Asignar espacio para los nuevos archivos mediante un m\u00e9todo espec\u00edfico al sistema de archivos XFS ConfigView.label.xfs.allocation.tooltip=Por favor, aseg\u00farese de que /usr/sbin/xfs_io est\u00e1 adecuadamente instalado en su sistema. En la mayor\u00eda de las distrbuciones Linux est\u00e1 incluida en el paquete "xfsprogs". xfs.allocation.xfs_io.not.found=La asignaci\u00f3n de espacio XFS ha fallado porque no se puede ejecutar /usr/sbin/xfs_io. Aseg\u00farese de que est\u00e1 adecuadamente instalado en su sistema. El error original fu\u00e9 : "%1". ConfigView.label.zeronewfiles=Al crear nuevos archivos, reservar espacio y rellenarlo con ceros. ConfigView.label.zeronewfiles.tooltip=Minimiza la fragmentaci\u00f3n ConfigView.section.stats=Estad\u00edsticas ConfigView.section.stats.enable=Activadas ConfigView.section.stats.defaultsavepath=Carpeta para estad\u00edsticas ConfigView.section.stats.choosedefaultsavepath=Escoja la carpeta donde guardar las estad\u00edsticas ConfigView.section.stats.savefreq=Guardar cada... ConfigView.section.stats.seconds=seg ConfigView.section.stats.savefile=Nombre del archivo de estad\u00edsticas ConfigView.section.stats.graph_update_dividers=Mostrar la linea vertical cada 60 actualizaciones MyTorrentsView.menu.export=Torrent &XML... MyTorrentsView.menu.host=&Servidor... ManagerItem.finishing=Terminando ConfigView.dialog.choosedefaulttorrentpath=Por favor, elija la carpeta por defecto para el torrent ConfigView.dialog.choosemovepath=Por favor, elija a qu\u00e9 carpeta moverlo ConfigView.label.movecompleted=Mover archivos completados (tras descargarlos) ConfigView.label.moveremoved=Mover archivos completados (cuando se est\u00e1n eliminando) ConfigView.label.savetorrents=Guardar archivos .torrent MainWindow.menu.view.mytracker=Mi &Rastreador MyTrackerView.title.full=Mi Rastreador MyTrackerView.name=Nombre MyTrackerView.tracker=Rastreador MyTrackerView.status=Estado MyTrackerView.status.started=Ejecutando MyTrackerView.status.stopped=Detenido MyTrackerView.peers=Clientes MyTrackerView.seeds=Semillas MyTrackerView.announces=Anuncios MyTrackerView.uploaded=Subido MyTrackerView.downloaded=Descargado MyTrackerView.left=Restante ConfigView.section.style=Interfaz ConfigView.label.set_ui_transfer_speeds=Ignorar las velocidades de transferencia seleccionables ConfigView.label.set_ui_transfer_speeds.description=Puedes elegir el definir manualmente la velocidades de descarga y env\u00edo seleccionables en la barra de estado de la bandeja de sistema.\nEsos valores van separados por comas. ConfigView.label.set_ui_transfer_speeds.description.download=Establecer las velocidades de descarga (en KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Establecer las velocidades de env\u00edo (en KB/s) ConfigView.section.style.useCustomTabs=Usar Pesta\u00f1as susceptibles de cerrar (necesita reiniciar) MainWindow.menu.view.plugins=&Complementos fileDownloadWindow.saveTorrentIn=Guardar el archivo torrent en fileDownloadWindow.title=Vuze - Descargador de Torrent fileDownloadWindow.downloading=Descargando de : fileDownloadWindow.status=Estado : fileDownloadWindow.state_initializing=Inicializando fileDownloadWindow.state_downloading=Descargando fileDownloadWindow.state_error=Error : MainWindow.menu.file.open.url=Direcci\u00f3n... MainWindow.menu.file.open.url.keybinding=Meta+D openUrl.title=Vuze - Ir a Direcci\u00f3n MyTorrentsView.menu.host.error.title=Fall\u00f3 el hospedaje del torrent MyTorrentsView.menu.host.error.message=Ocurri\u00f3 el siguiente error al hospedar el torrent ConfigView.section.tracker=Rastreador ConfigView.section.tracker.pollinterval=Intervalo comprobaci\u00f3n Rastreador (segs) ConfigView.section.tracker.publishenable=Publicar los detalles del torrent a "" ConfigView.section.tracker.ip=Direcci\u00f3n IP del rastreador Externo ConfigView.section.style.enableXPStyle=Activar estilo XP (precisa reiniciar) ConfigView.section.tracker.checkip=Auto-descubrir la direcci\u00f3n IP externa... ipCheckerWizard.title=Asistente para comprobar tu direcci\u00f3n IP ipCheckerWizard.service=Servicio ipCheckerWizard.chooseService=Por favor elija un 'Servicio Comprobador de direcciones IP' de los mostrados a continuaci\u00f3n ipCheckerWizard.explanations=Puedes usar el asistente para hallar tu direcci\u00f3n IP externa. Si tu direcci\u00f3n IP es din\u00e1mica, recomendamos que abras una cuenta con un proveedor de DNS din\u00e1mico. Algunos de los proveedores de estos servicios est\u00e1n listados a continuaci\u00f3n, usa el enlace para abrir una nueva cuenta. Luego rellena el campo 'IP address' con tu servidor din\u00e1mico (ej. myhostname.dyndns.org). Necesitar\u00e1s un programa que autom\u00e1ticamente actualice tu proveedor de DNS din\u00e1mico con tu direcci\u00f3n IP. De esta forma podr\u00e1s ofrecer torrents, aunque cambie tu direcci\u00f3n IP. ipCheckerWizard.service.description=Descripci\u00f3n : ipCheckerWizard.service.url=Enlace : ipCheckerWizard.progresstitle=Comprobando IP ipCheckerWizard.checkComplete=IP Completada : ipCheckerWizard.checkFailed=Fall\u00f3, raz\u00f3n : wizard.tracker.local=Usar el Rastreador integrado de Vuze wizard.tracker.external=Usar un Rastreador externo wizard.tracker.howToLocal=\tHabilitar en 'Herramientas->Opciones->Rastreador' wizard.announceUrl=Direcci\u00f3n URL de anuncio : IPChecker.external.service.discoveryvip.description=Discoveryvip - solamente la comprobaci\u00f3n de dir. IP IPChecker.external.httpinvalidresponse=Respuesta HTTP inv\u00e1lida IPChecker.external.loadingwebpage=Cargando p\u00e1g. web IPChecker.external.analysingresponse=Analizando respuesta IPChecker.external.addressextracted=Direcciones IP Extra\u00eddas IPChecker.external.httploadfail=No se lleg\u00f3 a cargar la p\u00e1gina IPChecker.external.timeout=Pas\u00f3 el tiempo IPChecker.external.ipnotfound=Direcci\u00f3n IP no encontrada ConfigView.section.tracker.pollintervalmin=M\u00ednimo ConfigView.section.tracker.pollintervalmax=M\u00e1ximo ConfigView.section.tracker.pollintervalincby=Incrementar por ConfigView.section.tracker.pollintervalincper=Cada 'n' Clientes splash.loadingImages=Cargando Im\u00e1genes splash.initializeGui=Iniciando ventana principal splash.openViews=Abriendo vistas splash.plugin=Cargando complemento : configureWizard.nat.tooManyPorts=Demasiados puertos para probar (m\u00e1x 9) ConfigView.section.color=Esquema de color MyTorrentsView.menu.publish=&Publicar... MyTrackerView.status.published=Publicado MyTrackerView.completed=Completado MainWindow.menu.file.open.torrentnodefault=Archivo .torrent... (Sin guardar por defecto) wizard.comment=Comentarios ConfigView.label.movetorrent=Mover .torrent ConfigView.label.movepartialdownloads=Mover incluso si algunos archivos est\u00e1n marcados como "No Descargar" ConfigView.label.subdir_is_in_default=Al considerar si ya existen las descargas en la carpeta por defecto, hacerlo tambi\u00e9n con sus subidrectorios ConfigView.section.file.decoder.label=Codificaci\u00f3n por defecto del torrent\ncuando se precisa elecci\u00f3n ConfigView.section.file.decoder.nodecoder=Ninguno IPChecker.external.service.no-ip.description=Proveedor del servicio DNS Din\u00e1mico y Est\u00e1tico\n(servicio 'check address' no disponible gratuitamente) ConfigView.section.tracker.publicenable=Activar .torrents externos ConfigView.label.playdownloadspeech=Aviso hablado al terminar una descarga ConfigView.label.playdownloadspeech.info=Los Servicios de Habla por el momento funcionan mejor en Ingl\u00e9s # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Muestra el n\u00famero disponible de copias para cada parte.\nSi el n\u00famero de la dcha. es menor de 1, est\u00e1s \nviendo una copia incompleta de este archivo \n(y puede que tengas problemas para completar la descarga). GeneralView.label.trackerurl.tooltip=Clic para copiar la dir. de anuncio al portapapeles GeneralView.label.trackerurlopen.tooltip=Clic para abrir la p\u00e1gina principal del rastreador # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Actualizar el GUI cada ConfigView.section.style.inactiveUpdate=Actualizar la ventana principal cada N actualizaciones del GUI cuando \u00e9sta no es la ventana activa ConfigView.section.style.graphicsUpdate=Actualizar los gr\u00e1ficos de barras cada N actualizaciones del GUI ConfigView.section.style.reOrderDelay=Re Ordenar listas cada N actualizacion(es) del GUI [0: nunca] ConfigView.section.style.reOrderDelay.never=Nunca ConfigView.section.logging=Registrando... ConfigView.section.logging.enable=Guardar informe en un archivo ConfigView.section.logging.logdir=Carpeta para el archivo de informe ConfigView.section.logging.choosedefaultsavepath=Por favor seleccione la carpeta donde guardar GeneralView.label.updatein.querying=Preguntando... configureWizard.nat.sharePort=Usar un solo puerto compartido para todos los .torrent ConfigView.section.logging.maxsize=Tama\u00f1o M\u00e1ximo del archivo de informe ConfigView.section.tracker.passwordenableweb=Activar contrase\u00f1a en el rastreador web ConfigView.section.tracker.passwordenabletorrent=Activar contrase\u00f1as en los torrents ConfigView.section.tracker.username=Nombre de usuario ConfigView.section.tracker.password=Contrase\u00f1a columnChooser.title=Marque las columnas a mostrar columnChooser.move=Arrastre las filas para reordenarlas columnChooser.apply=Aplicar columnChooser.columnname=Nombre de la Columna columnChooser.columndescription=Descripci\u00f3n TableColumn.header.shareRatio=\u00cdndice de compartici\u00f3n MyTorrentsView.menu.editTableColumns=Distribuci\u00f3n de &Columnas wizard.operationfailed=Operaci\u00f3n fallida authenticator.title=Es necesario identificarse authenticator.realm=Dominio authenticator.user=Nombre de usuario authenticator.password=Contrase\u00f1a ConfigView.label.allowSendVersion=Permitir a Vuze enviar numero de versi\u00f3n an\u00f3nimo e id aleatoria al buscar actualizaciones ConfigView.label.version.info.link=Aqu\u00ed encontrar\u00e1 informaci\u00f3n detallada sobre qu\u00e9 datos se env\u00edan al servidor comprobador de versiones wizard.hint.mode=Pista:\tPuedes 'Arrastrar y Soltar' un solo archivo o carpeta en este asistente\n\tpara elegir ese archivo o carpeta wizard.hint.file=Pista:\tPuedes elegir un solo archivo mediante 'Arrastrar y Soltar' wizard.hint.directory=Pista:\tPuedes elegir una sola carpeta mediante 'Arrastrar y Soltar' MainWindow.menu.help.checkupdate=Buscar &actualizaciones TableColumn.header.down=Descargado TableColumn.header.up=Subido ConfigView.section.tracker.passwordenabletorrent.info=Precisa de un cliente BitTorrent adecuado (p.ej. Vuze) ConfigView.section.style.confirmationOnExit=Pedir confirmaci\u00f3n de salida MainWindow.dialog.exitconfirmation.title=\u00bfSalir de Vuze MainWindow.dialog.exitconfirmation.text=\u00bfSeguro que quieres salir de Vuze SystemTray.menu.stopalltransfers=&Detener Todas las Transferencias TrayWindow.menu.stopalldownloads=&Detener Todas las Descargas ConfigView.section.tracker.sslport.info=Lea las FAQ para ampliar informaci\u00f3n wizard.tracker.ssl=Usar SSL ConfigView.label.playdownloadfinished=Aviso sonoro al terminar una descarga ConfigView.label.popupdownloadfinished=Aviso en ventana emergente al terminar una descarga ConfigView.label.popupfilefinished=Aviso en ventana emergente al terminar un archivo TableColumn.header.pieces=Partes TableColumn.header.pieces.info=Barra Gr\u00e1fica representando las partes que has descargado TableColumn.header.completion=Finalizaci\u00f3n TableColumn.header.completion.info=Representaci\u00f3n gr\u00e1fica del % descargado ConfigView.section.style.showdownloadbasket=Mostrar Dep\u00f3sito de Descarga ('Arrastrar y Soltar' .torrents) ConfigView.section.style.alwaysShowTorrentFiles=Mostrar siempre los archivos torrent en Detalles/Archivos wizard.multitracker=A\u00f1adir informaci\u00f3n Multi-Rastreador al torrent wizard.multitracker.title=Multi-Rastreador wizard.multitracker.configuration=Configuraci\u00f3n Multi-Rastreador wizard.multitracker.new=Nuevo... wizard.multitracker.edit=Editar... wizard.multitracker.delete=Borrar wizard.multitracker.group=Grupo Rastreador wizard.multitracker.edit.title=Editor Multi-Rastreador wizard.multitracker.edit.name=Nombre wizard.multitracker.edit.save=Guardar wizard.multitracker.edit.newgroup=Grupo Nuevo wizard.multitracker.edit.deletegroup=Borrar wizard.multitracker.edit.newtracker=Nuevo Rastreador wizard.multitracker.edit.deletetracker=Borrar wizard.multitracker.edit.edit=Editar wizard.addingmt=A\u00f1adir info Multi-Rastreador wizard.multitracker.noannounce=La URL de Anuncio no est\u00e1 entre tu lista de rastreadores MyTorrentsView.menu.recheck=Forzar &Re-comprobaci\u00f3n iconBar.showDownloadBar.tooltip=Mostrar Barra de Descarga iconBar.start.tooltip=Comenzar iconBar.stop.tooltip=Detener iconBar.remove.tooltip=Quitar iconBar.openNoDefault.tooltip=Abrir un archivo .torrent (sin guardar por defecto) iconBar.openURL.tooltip=Abrir una URL iconBar.openFolder.tooltip=Abrir una Carpeta iconBar.new.tooltip=Crear un torrent iconBar.up.tooltip=Subir iconBar.down.tooltip=Bajar iconBar.run.tooltip=Abrir iconBar.host.tooltip=Servidor iconBar.publish.tooltip=Publicar iconBar.editcolumns.tooltip=Configuraci\u00f3n de columnas MyTorrentsView.menu.editTracker=&Editar URL(s) del Rastreador GeneralView.menu.selectTracker=Seleccionar ConfigView.section.stats.xslfile=Nombre del archivo XSL ConfigView.section.stats.xslfiledetails=Esto se incluir\u00e1 en la cabecera del archivo de\nestad\u00edsticas v\u00eda etiqueta ConfigView.label.savetorrentbackup=Guardar una Copia ConfigView.section.tracker.forceport=Forzar a los torrents alojados externamente a usar el puerto por defecto ConfigView.section.ipfilter.allow=PERMITIR estos rangos (Lo normal es DENEGAR) ConfigView.section.ipfilter.list.inrange=estaba en el rango ConfigView.section.ipfilter.list.notinrange=no estaba en ning\u00fan rango ConfigView.section.ipfilter.list.title=IPs Bloqueadas ConfigView.label.allowsameip=Permitir m\u00faltiples conexiones desde la misma IP ConfigView.label.allowsameip.tooltip=Act\u00edvalo s\u00f3lo si lo NECESITAS.\nEsta es una protecci\u00f3n contra leechers (si est\u00e1 desactivado). ManagerItem.superseeding=Super-Compartici\u00f3n ConfigView.label.userSuperSeeding=Usar Super-Compartici\u00f3n PeersView.uniquepiece=Parte (Modo Super-Compartir) PeersView.uniquepiece.none=Ninguno PeersView.timetosend=Tiempo para reenviar parte (Modo Super-Compartir) ConfigView.section.style.addurlsilently=Abrir URL silenciosamente ConfigView.section.style.addurlsilently.tooltip=Descargar autom\u00e1ticamente las URLs de los .torrent pasados/soltados sin presentar el di\u00e1logo de confirmaci\u00f3n ConfigView.section.file.decoder.prompt=Avisar siempre que existan alternativas de codificaci\u00f3n ConfigView.section.file.decoder.prompt.tooltip=Mostrar siempre un di\u00e1logo cuando existan alternativas de codificaci\u00f3n MyTorrentsView.menu.moveTop=&Principio MyTorrentsView.menu.moveEnd=&Final ConfigView.label.moveonlyusingdefaultsave=s\u00f3lo si est\u00e1 en la carpeta de datos por defecto ConfigView.label.moveonlyusingdefaultsave.tooltip=Mover s\u00f3lo si los datos descargados est\u00e1n en su dir. por defecto ConfigView.label.watchtorrentfolder=Auto-Importar nuevos .torrent ConfigView.label.watchtorrentfolder.tooltip=Buscar regularmente nuevos .torrent ConfigView.label.watchtorrentfolderinterval=Intervalo ConfigView.label.watchtorrentfolderinterval.tooltip=Pausa hasta que la carpeta sea examinada de nuevo ConfigView.dialog.choosewatchtorrentfolderpath=Seleccione por favor la carpeta donde importar el .torrent ConfigView.label.startwatchedtorrentsstopped=Comenzar detenido ConfigView.label.startwatchedtorrentsstopped.tooltip=A\u00f1adir los nuevos .torrents en estado DETENIDO ConfigView.section.plugins=Complementos wizard.maketorrent.filesize=Tama\u00f1o de Archivo(s) wizard.maketorrent.piececount=N\u00famero de Partes wizard.maketorrent.piecesize=Tama\u00f1o de las partes MainWindow.menu.view.stats=&Estad\u00edsticas SpeedView.title.full=Actividad SpeedView.downloadSpeed.title=Velocidad de Descarga SpeedView.uploadSpeed.title=Velocidad de Subida ConfigView.section.style.useSIUnits=Usar Unidades IEC (KB -> KiB etc.) iconBar.top.tooltip=Mover al principio iconBar.bottom.tooltip=Mover al final TableColumn.header.health=Salud MyTorrentsView.menu.health=Acerca de la Salud health.explain.grey=significa que tu torrent no est\u00e1 en marcha (descargando o enviando) health.explain.red=significa que no est\u00e1s conectado a ning\u00fan cliente (si est\u00e1s descargando) health.explain.blue=cuando est\u00e1s sirviendo (seeding), significa que a\u00fan no est\u00e1s conectado a ning\u00fan cliente (peer)\ncuando est\u00e1s descargando, significa que est\u00e1s conectado a algunos clientes PERO el rastreador ha ca\u00eddo health.explain.yellow=significa que el rastreador est\u00e1 bien, est\u00e1s conectado a los clientes, pero no tienes ninguna conexi\u00f3n entrante.\nSi tus torrents permanecen en estado amarillo puede que tengas un problema de NAT. health.explain.green=significa que todo va bien. ConfigView.section.style.alwaysRefreshMyTorrents=Refrescar siempre Mis Torrents ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Esta opci\u00f3n refrescar\u00e1 la vista 'Mis Torrents' incluso si no est\u00e1 visible\n(\u00fatil para algunos plugins de mirc) # #2.0.7.0 # security.certtruster.title=Advertencia sobre el Certificado de Seguridad security.certtruster.intro=El certificado de seguridad fue emitido por una compa\u00f1\u00eda en la que no conf\u00edas security.certtruster.resource=Recurso: security.certtruster.issuedto=Emitido a: security.certtruster.issuedby=Emitido por: security.certtruster.prompt=\u00bfConf\u00eda en \u00e9l? security.certtruster.yes=Si ConfigView.section.tracker.torrentsperpage=\u00bfCu\u00e1ntos torrents por p\u00e1gina? [0=ilimitados] MainWindow.menu.file.share=&Compartir cl\u00e1sico MainWindow.menu.file.share.file=&Archivo... MainWindow.menu.file.share.dir=Car&peta... MainWindow.menu.file.share.dircontents=C&ontenidos de la carpeta... MainWindow.menu.file.share.dircontentsrecursive=Contenidos de la carpeta... (&Recursivo) MainWindow.dialog.share.sharefile=Seleccione el archivo a compartir MainWindow.dialog.share.sharedir=Seleccione la carpeta a compartir MainWindow.dialog.share.sharedircontents=Seleccionar los contenidos (en carpeta) a compartir MainWindow.dialog.share.sharedircontents.recursive=Recursivo globalmanager.download.remove.veto=Vetada la Acci\u00f3n de Retiro plugin.sharing.download.remove.veto=Esta descarga es resultado de un recurso que est\u00e1 compartiendo cl\u00e1sicamente.\nPara quitar la descarga quite la compartici\u00f3n cl\u00e1sica asociada ConfigView.section.tracker.main=Principal ConfigView.label.prioritizefirstpiece=Dar prioridad a la 1\u00aa parte del archivo(s) ConfigView.label.prioritizefirstpiece.tooltip=Intenta descargar primero el principio y el final del archivo.\nPara ayudar a la 'vista previa' temprana. ConfigView.section.file.confirm_data_delete=Confirmar la eliminaci\u00f3n de datos ConfigView.section.file.confirm_data_delete.tooltip=Confirmar el borrado de datos al usar 'Quitar y Borrar...' ConfigView.section.file.delete.include_files_outside_save_dir=Al eliminar los datos, tambi\u00e9n permitir la eliminaci\u00f3n de los archivos enlazados en el exterior de la carpeta donde se guarda el torrent TrayWindow.menu.startalldownloads=&Iniciar Todas las Descargas SystemTray.menu.startalltransfers=&Iniciar Todas las Transferencias sharing.progress.title=Evoluci\u00f3n de la Compartici\u00f3n cl\u00e1sica sharing.progress.hide=Ocultar MainWindow.menu.view.myshares=Mis Com&partidos cl\u00e1sicos MySharesView.title.full=Mis Comparticiones cl\u00e1sicas MySharesView.name=Nombre MySharesView.type=Tipo MySharesView.type.file=Archivo MySharesView.type.dir=Carpeta MySharesView.type.dircontents=Contenidos de la carpeta MySharesView.type.dircontentsrecursive=Contenidos de la carpeta (&Recursivo) MySharesView.menu.remove=Quitar ConfigView.section.tracker.extensions=Extensiones ConfigView.section.tracker.sendpeerids=Enviar identidad del cliente a los que descargan ConfigView.section.tracker.enableudp=Activar protocolo UDP del rastreador plugin.sharing.torrent.remove.veto=Este registro en el rastreador es resultado de un recurso compartido cl\u00e1sicamente.\nPara quitar la descarga quite la compartici\u00f3n cl\u00e1sica asociada plugin.download.remove.veto.notstopped=No se puede quitar la descarga porque no est\u00e1 detenida plugin.sharing.remove.veto=Esta es una sub-compartici\u00f3n de un 'contenidos de carpeta' compartida y no se puede borrar directamente.\n Borre la compartici\u00f3n cl\u00e1sica ra\u00edz GeneralView.label.hash.tooltip=Clic para copiar el hash al portapapeles ConfigView.section.tracker.maxpeersreturned=Clientes - N\u00ba m\u00e1x. devuelto [0=ilimit.] ConfigView.label.serverport=Puerto de entrada TCP / UDP ConfigView.label.serverport.tooltip=El puerto debe estar en el rango 1-65535, menos el 6880 porque esta reservado para uso interno de Azureus. configureWizard.nat.server.tcp_listen_port=Puerto TCP para conexiones entrantes ConfigView.section.sharing=Compartici\u00f3n cl\u00e1sica ConfigView.section.sharing.usessl=Usar SSL para los recursos compartidos cl\u00e1sicamente (necesita configurar el tracker) ConfigView.section.style.dropdiraction=Acci\u00f3n 'Arrastrar y Soltar' para carpetas ConfigView.section.style.dropdiraction.opentorrents=Abrir torrents ConfigView.section.style.dropdiraction.sharefolder=Compartir cl\u00e1sicamente la Carpeta ConfigView.section.style.dropdiraction.sharefoldercontents=Compartir cl\u00e1sicamente los Contenidos # # 2.0.7.x # Categories.all=Todo Categories.uncategorized=Sin categorizar CategoryAddWindow.message=Introduzca el nombre de la nueva categor\u00eda CategoryAddWindow.title=A\u00f1adir una Nueva Categor\u00eda ConfigView.label.autoSeedingIgnoreInfo=Los torrents ignorados pasan al final de la cola de compartici\u00f3n. No se autoiniciar\u00e1n.\nLas reglas para ignorar no son aplicables a los torrents que cumplan el criterio de la 1\u00aa Prioridad.\nA menos que se diga, un valor de 0 desactiva la regla\n\n ConfigView.label.directory=a la carpeta ConfigView.label.disconnetseed.tooltip=Cuando sirves un torrent, desconecta cualquier cliente que tambi\u00e9n est\u00e9 sirviendo.\nNo necesit\u00e1is comunicaros. ConfigView.label.ignoreCase=Ignorar MAYUS/min\u00fasc ConfigView.label.ignoreSeeds=Ignorar torrents con al menos ConfigView.label.importdirectory=Carpeta desde donde Importar ConfigView.label.minPeersToBoostNoSeeds.tooltip=Cualquier torrent sin semillas y con menos clientes de los que especifiques\nse enviar\u00e1 al final de la cola. ConfigView.label.minPeersToBoostNoSeeds=Disminuir el rango de compartici\u00f3n para los torrents sin semillas y menos de ConfigView.label.minSeedingTime.tooltip=Las posiciones pueden fluctuar constantemente durante un corto periodo de tiempo, causando\na veces el autoinicio del torrent, s\u00f3lo para detenerlo enseguida y enviarlo a la cola.\n\nEsto mitigar\u00e1 el problema forzando al torrent a permanecer compartiendo durante un rato. \nAunque si quieres, puedes detenerlo manualmente. ConfigView.label.minSeedingTime=Tiempo m\u00ednimo sirviendo (en segundos) ConfigView.label.minSpeedForActiveDL.tooltip=Durante los primeros 30 segundos al empezar a redescargar\nun torrent incompleto se usa siempre un 'puesto de descarga'. ConfigView.label.minSpeedForActiveDL=No contar como 'puesto de descarga' aquellos cuya velocidad sea menor de ConfigView.label.peers=clientes ConfigView.label.queue.debuglog=Registrar informaci\u00f3n de depuraci\u00f3n ConfigView.label.queue.debuglog.info=A\u00f1ade info depuraci\u00f3n de cola al archivo de consola/log.\nAunque cr\u00edptica, la info de depuraci\u00f3n te dir\u00e1 el estado de los torrents y el porqu\u00e9 se est\u00e1n o no iniciando/pasando a cola. ConfigView.label.queue.minQueueingShareRatio=No poner en cola ni detener el torrent hasta que su '\u00ednd. de compartic.' alcance ConfigView.label.ratio=\u00edndice ConfigView.label.removeOnStop=Quitar el torrent de la lista al autodetenerse ConfigView.label.savedirectory=en la carpeta ConfigView.label.seeding.autoReposition.tooltip=Si se activa, se cambiar\u00e1 el orden de los torrents (la columna 'N\u00ba') para adaptarse al 'Rango de compartici\u00f3n'\nEsto es \u00fatil si no te gusta ver los n\u00fameros de 'Rango de Compartici\u00f3n', pero quieres saber el orden en que se iniciar\u00e1n los torrents ya completados. ConfigView.label.seeding.autoReposition=Autorecolocaci\u00f3n de los torrents en base a su 'Rango de Compartici\u00f3n' ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=A menudo, hay torrents que tienen pocas semillas y muchos clientes, y esto indica que es probable que no exista 1 copia completa entre estos clientes.\nPor tanto, no querr\u00e1s que las reglas para compartir presupongan que s\u00ed la hay (y por tanto, rebajar incorrectamente su rango) ConfigView.label.seeding.fakeFullCopySeedStart=pero s\u00f3lo para torrents con al menos ConfigView.label.seeding.ignore=Ignorar las Reglas ConfigView.label.seeding.ignore0Peers=Ignorar torrents con 0 clientes ConfigView.label.seeding.ignoreRatioPeers=Ignorar torrents que tienen al menos 1 semilla por cada ConfigView.label.seeding.ignoreShareRatio=Ignorar torrents cuyo \u00edndice de compartici\u00f3n es de ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorar torrent incluso si\nse aplica la regla de 1\u00aa Prioridad ConfigView.label.seeding.ignore.header.rule=Regla ConfigView.label.seeding.ignore.header.value=Valor ConfigView.label.seeding.firstPriority.info=Los torrents de 1\u00aa Prioridad siempre estar\u00e1n al principio de la cola.\nCualquier torrent que cumpla el este criterio no se autodentendr\u00e1 ni pasar\u00e1\na la cola, y si lo necesita coger\u00e1 una 'posici\u00f3n de Descarga Simult\u00e1nea'.\n\n ConfigView.label.seeding.firstPriority.FP=1\u00aa Prioridad ConfigView.label.seeding.firstPriority=La 1\u00aa Prioridad se aplica a los torrents con ConfigView.label.seeding.firstPriority.following=de lo siguiente: ConfigView.label.seeding.firstPriority.shareRatio=Un \u00edndice de compartici\u00f3n inferior a ConfigView.label.seeding.firstPriority.seedingMinutes=Un tiempo transcurrido desde que se pas\u00f3 de descargar a compartir ConfigView.label.seeding.firstPriority.DLMinutes=Un tiempo transcurrido desde el comienzo de la descarga ConfigView.label.seeding.numPeersAsFullCopy.tooltip=El suponer que existe 1 copia completa cada X clientes, reduce el rango de torrents con muchos clientes.\nAdem\u00e1s, los torrents con muchos clientes tienen tambi\u00e9n mucho tr\u00e1fico.\nEsto no cambia ning\u00fan marcadador 'N\u00ba de semillas'. ConfigView.label.seeding.numPeersAsFullCopy=Suponer que hay 1 copia completa por cada\n(0 : No suponer nada) ConfigView.label.seeding.preferLargerSwarms.tooltip=Si est\u00e1s sirviendo torrents con clientes que se han quedado "atascados", tiene sentido el preferir los enjambres m\u00e1s grandes\nCuando sirves torrents de gran disponibilidad, tiene sentido el preferirlos m\u00e1s peque\u00f1os. ConfigView.label.seeding.preferLargerSwarms=Cuando los torrents tienen el mismo rango, elegir los mayores enjambres (swarms) ConfigView.label.seeding.rankType.none.tooltip=Ordenar por el N\u00ba de columna ConfigView.label.seeding.rankType.none=Ninguno ConfigView.label.seeding.rankType.peer.tooltip=m\u00e1s pares y menos semillas = rango m\u00e1s alto\nEsta valoraci\u00f3n minimiza el n\u00famero de torrents que necesitan mantenerse activos para maximizar la subida ConfigView.label.seeding.rankType.peer=Suma ponderada de pares ConfigView.label.seeding.rankType.peerSeed.options=Opciones del \u00edndice Semillas:Clientes ConfigView.label.seeding.rankType.peerSeed.tooltip=Mayor Indice = Rango m\u00e1s alto ConfigView.label.seeding.rankType.peerSeed=Indice de Clientes:Compartici\u00f3n ConfigView.label.seeding.rankType.seed.fallback=Recurrir a la relaci\u00f3n Clientes:Compartido tras\n[0 : No Recurrir] ConfigView.label.seeding.rankType.seed.options=Opciones del N\u00ba de Semillas ConfigView.label.seeding.rankType.seed.tooltip=Menos Semillas = Mayor Rango ConfigView.label.seeding.rankType.seed=Contador de Semillas ConfigView.label.seeding.rankType.timedRotation.tooltip=Todos los torrents (completados) rotar\u00e1n en cola bajo el modo compartici\u00f3n.\nLa duraci\u00f3n del tiempo a servir se ajusta mediante 'Tiempo m\u00ednimo a servir' de m\u00e1s abajo. ConfigView.label.seeding.rankType.timedRotation=Rotaci\u00f3n Temporizada ConfigView.label.seeding.rankType.tooltip=Los torrents de m\u00e1s alto rango se autoiniciar\u00e1n.\nCuando otro torrent consiga una posici\u00f3n m\u00e1s alta, el de m\u00e1s baja se detiene y se pone al final de la cola.\n\nSolo pueden autoiniciarse los torrents que est\u00e1n 'En cola'.\nLos que est\u00e1n 'detenido' nunca se autoiniciar\u00e1n. ConfigView.label.seeding.rankType=Asignar Rango para autoinicio a los torrents completados, en base a: ConfigView.label.stopAfterMinutes=Una vez puesto a servir, detenerse tras x tiempo ConfigView.label.switchpriority.tooltip=La prioridad baja reduce la cantidad de 'ancho de banda saliente' necesarios por el torrent. ConfigView.pluginlist.info=\n\nSe han identificado los siguientes complementos. Puede que algunos no tengan pesta\u00f1as para poder configurarlos. ConfigView.pluginlist.noplugins=No se han encontrado complementos. ConfigView.section.pluginslist=Lista ConfigView.section.queue.seeding=Compartiendo ConfigView.section.queue.seeding.autoStarting=Auto Iniciando ConfigView.section.queue.seeding.ignore=Ignorar Reglas ConfigView.section.queue.seeding.firstPriority=Primera Prioridad ConfigView.section.queue.main=Principal ConfigView.section.queue=Cola ConfigView.text.all=todo ConfigView.text.hours=horas ConfigView.text.ignoreRule=Ignorar Regla ConfigView.text.ignore=Ignorar ConfigView.text.minutes=minutos ConfigView.text.neverIgnore=Nunca Ignorar ConfigView.text.any=cualquier DownloadManager.error.datamissing=Datos Perdidos MainWindow.menu.file.open.torrentforseeding=Archivo .torrent... (Para Compartir) MainWindow.menu.language.refresh=&Actualizar ManagerItem.forced=(Forzado) ManagerItem.queued=En cola MySeedersView.header=Torrents Completos TableColumn.header.availability.info=N\u00ba de copias completas encontradas TableColumn.header.availability=Disponibilidad TableColumn.header.category=Categor\u00eda MyTorrentsView.header=Torrents Incompletos TableColumn.header.maxuploads=N\u00ba M\u00e1x Env\u00edos MyTorrentsView.menu.category.delete=&Borrar Categor\u00eda MyTorrentsView.menu.forceStart=&Forzar Inicio MyTorrentsView.menu.queue=&Cola MyTorrentsView.menu.setCategory.add=&A\u00f1adir Categor\u00eda... MyTorrentsView.menu.setCategory=Asignar a la Categor\u00eda TableColumn.header.savepath=Ruta donde Guardar TableColumn.header.SeedingRank=Rango de Compartici\u00f3n TableColumn.header.totalspeed.info=Velocidad Total de todos los clientes a los que est\u00e1s conectado TableColumn.header.totalspeed=Velocidad Total splash.initializePlugins=Inicializando Complementos StartStopRules.SPratioMet=Relaci\u00f3n S:C OK StartStopRules.FP0Peers=FP / 0 Clientes StartStopRules.0Peers=0 Clientes StartStopRules.numSeedsMet=N\u00ba de Semillas OK StartStopRules.ratioMet=Clientes:Semilla OK StartStopRules.shareRatioMet=\u00cdndice Compartici\u00f3n OK StartStopRules.waiting=Esperando StartStopRules.firstPriority=1\u00aa Prioridad ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Compartir cl\u00e1sicamente los Contenidos (recursivo) DownloadManager.error.unabletostartserver=Incapaz de iniciar el servidor - compruebe la configuraci\u00f3n de puertos de entrada / permisos del cortafuegos para que esta aplicaci\u00f3n act\u00fae como servidor GeneralView.label.creationdate=Creado el d\u00eda : ConfigView.section.tracker.announcescrapepercentage=Intervalo de raspado como %edad del anuncio\np.ej. 200 = 2:1. 0 = dejar decidir al cliente ManagerItem.stopping=Deteni\u00e9ndolo ConfigView.section.tracker.announcecacheperiod=Cach\u00e9 de Anuncios (millis) ConfigView.section.tracker.scrapecacheperiod=Cach\u00e9 de Raspado (millis) ConfigView.section.tracker.scrapeandcache=Raspado (petici\u00f3n al rastreador del n\u00ba de semillas+clientes) y cach\u00e9 ConfigView.section.tracker.announcecacheminpeers=La 'Cach\u00e9 de Anuncios' activa el umbral de clientes MyTrackerView.scrapes=Raspados fileDownloadWindow.retry=Reintentar MyTrackerView.bytesin=Bytes Ent MyTrackerView.bytesinave=Prom Ent MyTrackerView.bytesout=Bytes Sal MyTrackerView.bytesoutave=Prom Sal ConfigView.section.file.max_open_files=N\u00ba m\u00e1x. de archivos abiertos en lectura/escritura \n[0 = ilimitado] ConfigView.section.file.max_open_files.tooltip=Es \u00fatil si descargas torrents de cientos/miles de archivos, y est\u00e1s rozando el l\u00edmite de ese SO para gestionar archivos. ConfigView.section.proxy=Opciones de Proxy ConfigView.section.proxy.enable_proxy=Proximizar las comunicaciones del rastreador [precisa reinicio] ConfigView.section.proxy.host=Servidor ConfigView.section.proxy.port=Puerto ConfigView.section.proxy.username=Usuario ConfigView.section.proxy.password=Contrase\u00f1a ConfigView.section.proxy.enable_socks=Tengo un proxy SOCKS wizard.createtorrent.extrahashes=A\u00f1adir hashes para otras redes (p.ej. Gnutella2, ed2k) GeneralView.label.connected=conectados GeneralView.label.in_swarm=en total ManagerItem.initializing=Inicializando AlertMessageBox.warning=Advertencia AlertMessageBox.comment=Informaci\u00f3n AlertMessageBox.information=Informaci\u00f3n AlertMessageBox.unread=Tiene mensajes de alerta sin leer - clic aqu\u00ed para mostrarlos. SharedPortServer.alert.selectorfailed=No se pudo determinar el puerto para entrada de datos.\nCompruebe que el cortafuegos permite a 'java(w).exe' actuar como 'servidor'. Tracker.alert.listenfail=No se pudo establecer %1 como puerto de entrada.\nCompruebe si otras aplicaciones est\u00e1n utilizando ahora este puerto.\nVea tambi\u00e9n si es que tiene funcionando otra copia de Azureus. DiskManager.alert.movefileexists=Error al mover los archivos completados\nEl archivo %1 ya existe en la carpeta de destino DiskManager.alert.movefilefails=Error al mover los archivos completados\nEl traslado del archivo %1 fall\u00f3, %2 DiskManager.alert.movefilerecoveryfails=Error al recuperar tras fallar el traslado\nLa reposici\u00f3n del archivo %1 fall\u00f3, %2 ConfigView.section.tracker.logenable=Guardar las estad\u00edsticas en 'tracker.log' SpeedView.stats.title=Estad\u00edsticas SpeedView.stats.session=Esta Sesi\u00f3n SpeedView.stats.session.tooltip=Total (Protocolo) SpeedView.stats.downloaded=Descargado (Protocolo) SpeedView.stats.uploaded=Subido (Protocolo) SpeedView.stats.ratio=Compartici\u00f3n SpeedView.stats.uptime=Tiempo activo SpeedView.stats.now=Ahora SpeedView.stats.now.tooltip=Total (Protocolo) AutoMigration.useralert=Resultados de la auto-migraci\u00f3n de los archivos/carpetas de conf. del usuario:\n\n%1\nCualquier fallo deber\u00e1 ser migrado a mano.\n\u00a1NO OLVIDES ACTUALIZAR EN LA CONFIGURACION LAS RUTAS DONDE GUARDAR (si estas han sido migradas)!. # # > 2.0.8.0 # OpenTorrentWindow.title=Abrir Torrent(s) OpenTorrentWindow.addFiles=&A\u00f1adir Archivos OpenTorrentWindow.dataLocation=Sitio donde guardar datos: OpenTorrentWindow.startMode=A\u00f1adir en Modo OpenTorrentWindow.startMode.queued=En Cola OpenTorrentWindow.startMode.stopped=Detenido OpenTorrentWindow.startMode.forceStarted=Inicio Forzado OpenTorrentWindow.addPosition=Posici\u00f3n en la cola OpenTorrentWindow.addPosition.first=Primero OpenTorrentWindow.addPosition.last=Ultimo TableColumn.header.remaining.info=Lo que queda por descargar TableColumn.header.remaining=Restante ConfigView.section.tracker.enablecompact=Activar 'protocolo de anuncio compacto' ConfigView.section.tracker.enablekey=Activar intercambio de contrase\u00f1a al rastreador (para mejorar la seguridad) ConfigView.section.file.perf=Opciones de Rendimiento ConfigView.section.file.perf.explain=Advertencia - el cambiar sin conocimiento estos par\u00e1metros puede afectar negativamente el rendimiento. Se precisa reiniciar.\nSi obtienes problemas tipo "out of memory" considera el limitar las conexiones por torrent (Ver config. de Transferencia)\n\n ConfigView.section.file.max_open_files.explain=Abrir demasiados archivos puede causar problemas al sistema operativo ya que hay recursos limitados como p.ej. los file handlers. Esto limita el n\u00ba de archivos abiertos simult\u00e1neamente. popup.error.hide=Ocultar popup.error.details=Detalles ConfigView.section.style.colorOverrides=Anulaciones de Color ConfigView.section.style.colorOverride.progressBar=Barra de Progreso MainWindow.status.tooOld=es antiguo, actual\u00edzalo por favor. ConfigView.section.style.colorOverride.warning=Advertencia ConfigView.section.style.colorOverride.altRow=Filas Alternativas ConfigView.section.file.save.peers.enable=Recordar los clientes (para reconexi\u00f3n r\u00e1pida) ConfigView.section.file.save.peers.max=N\u00ba m\u00e1ximo de clientes a recordar [0: ilimitado] ConfigView.section.file.save.peers.pertorrent=por torrent ConfigView.label.max_peers_per_torrent=Conexiones por torrent - N\u00ba m\u00e1ximo por defecto [0: ilimitadas] ConfigView.label.max_peers_total=Conexiones globales - N\u00ba m\u00e1ximo [0: ilimitadas] ConfigView.section.style.colorOverrides.reset=Reiniciar Color ConfigView.section.language.info=Si se activa, se buscar\u00e1n actualizaciones en cada arranque de Azureus. ConfigView.section.language.enableUpdate=Activar Actualizaci\u00f3n Web ConfigView.section.language.UpdateURL=URL de Actualizaci\u00f3n ConfigView.section.language.UpdateNow=\u00a1Actualizar ahora! Button.revert=Revertir MyTorrentsView.menu.changeDirectory=Cambiar la carpeta de datos GenericText.column=columna MyTorrentsView.menu.thisColumn.remove=Quitar Columna MyTorrentsView.menu.thisColumn.toClipboard=Copiar texto al portapapeles MyTorrentsView.menu.thisColumn.autoTooltip=Mostrar siempre el tooltip MyTorrentsView.menu.tracker=Rastreador ConfigView.upload.abbreviated=S: TableColumn.header.secondsseeding=Compartiendo durante TableColumn.header.secondsseeding.info=Tiempo total que has estado compartiendo. TableColumn.header.secondsdownloading=Descargando durante TableColumn.header.secondsdownloading.info=Tiempo que has estado descargando. ConfigView.section.tracker.udpversion=Versi\u00f3n del Protocolo UDP (1 o 2) window.updateswt.title=\u00a1Tu Versi\u00f3n de SWT est\u00e1 anticuada! window.updateswt.text=\u00a1Tu Versi\u00f3n de SWT est\u00e1 anticuada!\nSWT es la librer\u00eda gr\u00e1fica que usa Vuze y la versi\u00f3n que tienes es demasiado antigua para que funcione la \u00faltima versi\u00f3n de Azureus.Pincha en el bot\u00f3n OK para actualizar tu SWT. window.updateswt.status=Estado window.updateswt.failed=Actualizaci\u00f3n fallida, pulsa OK para probar otra vez window.updateswt.status.downloading.updater=Descargando el m\u00f3dulo actualizador window.updateswt.status.finding=Buscando la \u00faltima Versi\u00f3n de SWT window.updateswt.status.downloading=Descargando la \u00faltima Versi\u00f3n de SWT window.updateswt.status.done=Reiniciando window.updateswt.cancel=Cancelar swt.updater.downloader.downloading=Descargando SWT desde swt.updater.urlsgetter.downloading=Obteniendo una lista de servidores espejo desde swt.updater.urlsgetter.platform=SWT para la plataforma : window.updateswt.ignore=Ignorar ConfigView.section.style.useFancyTabs=Utilizar Pesta\u00f1as Elegantes splash.initializeGM=Inicializando el Administrador Global Torrent splash.loadingTorrents=Cargando torrents MyTorrentsView.menu.thisColumn.sort=&Ordenar Scrape.status.ok=Raspado OK. Scrape.status.error=Error de Raspado: Scrape.status.error.badURL=La URL de anuncio no sigue las especificaciones de raspado. Scrape.status.error.nohash=El hash no est\u00e1 en la respuesta. Scrape.status.error.invalid=Respuesta inv\u00e1lida. Scrape.status.nextScrapeAt=Siguiente raspado a las %1 Scrape.status.scraping=Raspando... Scrape.status.initializing=Esperando raspado... Scrape.status.scraping.queued=Raspado en cola... ConfigView.label.minSpeedForActiveSeeding=Al servir un torrent, no contar como 'puestos de subida' aquellos con una veloc. menor de ConfigView.section.stats.exportpeers=Exportar detalles del cliente MainWindow.menu.view.irc.moved=Ahora el Irc est\u00e1 disponible como un plugin, mira en http://azureus.sourceforge.net/plugin_list.php. Cuando lo instales lo encontrar\u00e1s en el men\u00fa Complementos->IRC. MyTrackerView.webui.contextmenu.copyurl=Copiar URL del torrent al portapapeles ConfigView.section.file.torrent.ignorefiles=Archivos a ignorar al crear torrents\np.ej. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignorando Archivo ConfigView.section.style.useUnitsRateBits=Usar bits en lugar de bytes para tasas de 'valores basados en byte' (KiB/s->Kibit/s etc.) ConfigView.section.interface.resetassoc=Reasociar la extensi\u00f3n '.torrent' con Vuze ConfigView.section.interface.resetassocbutton=Reiniciar ConfigView.section.interface.checkassoc=Comprobar al arrancar dialog.associations.title=Prueba de Asociaci\u00f3n Button.yes=&Si ConfigView.label.seeding.autoStart0Peers=AutoIniciar todos los torrents completados y con 0 clientes ConfigView.label.seeding.autoStart0Peers.tooltip=Act\u00edvalo si quieres que el rastreador liste siempre las semillas de los torrents con 0 clientes. dialog.associations.prompt=Vuze no es la aplicaci\u00f3n asociada por defecto a los archivos BitTorrent.\n\u00bfQuieres asociar los archivos .torrent con Vuze? dialog.associations.askagain=Comprobar durante el arranque ConfigView.section.plugins.update=Actualizaci\u00f3n de Complementos Plugin.pluginupdate.enablecheck=Permitir actualizaciones plugins.basicview.status=Estado: plugins.basicview.activity=Actividad: plugins.basicview.progress=Progreso: plugins.basicview.log=Informe: ConfigView.label.maxdownloadspeed=Descarga - Velocidad m\u00e1xima en KB/s (global) [0: ilimitada] splash.loadingTorrent=Cargando torrent splash.of=de UpdateWindow.title=Actualizador de Vuze UpdateWindow.header=Los siguientes componentes necesitan actualizarse: UpdateWindow.columns.install=Instalar UpdateWindow.columns.name=Nombre UpdateWindow.columns.version=Versi\u00f3n UpdateWindow.columns.size=Tama\u00f1o UpdateWindow.cancel=Cancelar UpdateWindow.quit=Salir UpdateWindow.close=Cerrar UpdateWindow.ok=Actualizar UpdateWindow.restart=Reiniciar ahora UpdateWindow.status.downloading=Descargando UpdateWindow.status.done=Terminado UpdateWindow.status.failed=Fall\u00f3 UpdateWindow.status.restartNeeded=\u00a1 Requerir\u00e1 reiniciar ! ConfigView.pluginlist.broken=Estropeado, roto. ConfigView.pluginlist.whereToPut=Colocar cualquier complemento espec\u00edfico del usuario en su propia carpeta a partir de \u00e9sta: ConfigView.pluginlist.whereToPutOr=Para los complementos compartidos usar esta carpeta: MainWindow.statusText.checking=Buscando Actualizaciones TableColumn.header.OnlyCDing4=Sirviendo TableColumn.header.OnlyCDing4.info=Tiempo sirviendo el torrent. No contabiliza lo compartido durante la descarga. ConfigView.section.style.alternateTablePainting=Usar el m\u00e9todo alternativo para dibujar las columnas gr\u00e1ficas (puede necesitarse reiniciar) UpdateWindow.status.restartMaybeNeeded=Podr\u00eda necesitarse un reinicio ConfigView.pluginlist.shared=compartido PeersView.host=Nombre del Servidor PeersView.host.info=El nombre de host del cliente, si est\u00e1 disponible (puede afectar al rendimiento) MainWindow.menu.help.whatsnew=Lo nuevo ConfigView.label.checkonstart=Buscar la \u00faltima versi\u00f3n al iniciar Vuze ConfigView.label.periodiccheck=Buscar peri\u00f3dicamente la \u00faltima versi\u00f3n ConfigView.label.opendialog=Autoiniciar el 'Asistente de Actualizaci\u00f3n' cuando haya una disponible MainWindow.updateavail=Clic aqu\u00ed para actualizar MainWindow.status.latestversionunchecked=Comprobaci\u00f3n de actualizaciones desactivada GeneralView.label.updatein.stopped=Detenido StartStopRules.menu.viewDebug=Ver Info Depuraci\u00f3n ConfigView.section.style.doNotUseGB=No usar la medida GB ConfigView.section.style.doNotUseGB.tooltip=Si la marcas, Vuze seguir\u00e1 contando en MB incluso m\u00e1s all\u00e1 de los 1024MB MainWindow.menu.help.plugins=Obtener complementos ConfigView.section.plugins.TrackerWeb=Rastreador Web ConfigView.section.tracker.enablecategories=Separar torrents por categor\u00edas health.explain.share=significa que o el torrent est\u00e1 hospedado o publicado ConfigView.section.tracker.createcert=Crear un certificado autofirmado ConfigView.section.tracker.createbutton=Crear security.certcreate.title=Crear un Certificado Autofirmado security.certcreate.intro=Este di\u00e1logo te permite crear un certificado autofirmado security.certcreate.strength=Potencia security.certcreate.firstlastname=Nombre y primer apellido security.certcreate.orgunit=Unidad de organizaci\u00f3n security.certcreate.org=Organizaci\u00f3n security.certcreate.city=Ciudad o Lugar security.certcreate.state=Estado o Provincia security.certcreate.country=C\u00f3digo de pa\u00eds de 2 letras security.certcreate.ok=Crear security.certcreate.cancel=Cancelar security.certcreate.createok=Certificado creado con \u00e9xito security.certcreate.createfail=Creaci\u00f3n de certificado fallida ConfigView.section.plugins.webui=Interfaz Web Swing ConfigView.section.plugins.xml_http_if=Interfaz XML/HTTP webui.passwordenable=Activar contrase\u00f1a webui.user=Nombre de usuario webui.password=Contrase\u00f1a webui.port=Puerto (*) webui.protocol=Protocolo (*) webui.homepage=P\u00e1gina principal (*) webui.rootdir=Carpeta Ra\u00edz (*) webui.rootres=Recurso Ra\u00edz (*) webui.mode=Modo (*) webui.mode.info=El modo puede ser\n\t"total"\t= todas las operaciones est\u00e1n disponibles (por defecto)\n\t"vista"\t= solo ver (pero puede actualizar la frecuencia de refresco) webui.access=Acceso (*) webui.access.info=El acceso puede ser\n\t"local"\t= donde s\u00f3lo puede conectar la m\u00e1quina local\n\t"todos"\t= acceso sin restricciones (por defecto)\n\tIP\t= e.g. 192.168.0.2\t\t\ts\u00f3lo una IP\n\tIP1-IP2\t= p.ej. 192.168.0.1-192.168.0.255\trango inclusivo de IPs GeneralView.label.maxdownloadspeed=Limitar la Descarga Security.keystore.corrupt=Fallo al cargar Keystore '%1', b\u00f3rrela por favor y recree/re-importe los certificados Security.keystore.empty=Keystore est\u00e1 vac\u00edo. Por favor, cree un certificado auto-firmado (vea Herramientas->Opciones->Seguridad) o importe un certificado existente a '%1' webui.restart.info=Es necesario reiniciar la aplicaci\u00f3n para que los cambios aplicados a los par\u00e1metros marcados con una (*) se hagan efectivos GeneralView.label.maxdownloadspeed.tooltip=velocidad m\u00e1xima de descarga [0: ilimitada] upnp.enable=Activar UPnP upnp.info=Universal Plug and Play (UPnP) te permite el mapeado autom\u00e1tico de los puertos en enrutadores UPnP. upnp.mapping.dataport=Puerto de Datos entrantes de los clientes upnp.mapping.tcptrackerport=Puerto TCP del rastreador upnp.mapping.udptrackerport=Puerto UDP rastreador upnp.alert.differenthost=UPnP: El Mapeado '%1' ha sido reservado por '%2' - por favor, seleccione un puerto diferente upnp.alert.mappingok=UPnP: Mapeado '%1' establecido upnp.alert.mappingfailed=UPnP: El Mapeado '%1' ha fallado upnp.alertsuccess=Informar de mapeados exitosos upnp.alert.lostdevice=UPnP: Conexi\u00f3n perdida con el servicio '%1' del dispositivo UPnP '%2' upnp.grabports=Mapear los puertos incluso si los posee otro ordenador upnp.refresh.label=Actualizar el mapeado upnp.refresh.button=Actualizar upnp.alert.mappinggrabbed=UPnP: Mapeo '%1' establecido - cogido de '%2' upnp.mapping.tcpssltrackerport=Puerto TCP SSL del rastreador upnp.alertothermappings=Informar de los puertos propiedad de otros ordenadores upnp.alertdeviceproblems=Informar sobre los problemas con el dispositivo UPnP upnp.trace_to_log=Volcar info completa para depuraci\u00f3n en su registro upnp.wiki_link=P\u00e1gina de Vuze Wiki sobre el UPnP ConfigView.pluginlist.coreplugins=\nYa est\u00e1n cargados los siguientes complementos incorporados en el programa: Peers.column.DLedFromOthers=Desde Otros Peers.column.DLedFromOthers.info=Cantidad de datos descargados desde otros mientras estaban conectados contigo Peers.column.UpDownRatio=Sub:Desc Peers.column.UpDownRatio.info=Montante "Subido : Descargado" del cliente Peers.column.UpRatio=Tasa Sub Peers.column.UpRatio.info=Montante "Subido desde t\u00ed : Subido desde otros" del cliente upnp.releasemappings=Liberar los mapeados al salir webui.upnpenable=Activar UPnP para este puerto (*) ConfigView.section.file.friendly.hashchecking=Comprobaci\u00f3n amistosa del hash ConfigView.section.file.friendly.hashchecking.tooltip=Otro modo de comprobar el hash de las partes, es un poco mas lento pero gasta mucha menos cpu/sistema. ConfigView.section.tracker.seedretention=Semillas a recordar - N\u00ba m\u00e1x por torrent [0: ilimitadas] ConfigView.section.tracker.seedretention.info=Nota: Se perder\u00e1n las estad\u00edsticas de subida de las semilas no-recordadas ConfigView.section.tracker.port=Activar el rastreador en un puerto HTTP ConfigView.section.tracker.sslport=Activar el rastreador en un puerto HTTPS ConfigView.section.tracker.publicenable.info=Esto permite a otros el crear torrents que utilicen\ntu rastreador sin que t\u00fa los hospedes/publiques Button.clear=Limpiar MainWindow.IPs.tooltip=\u00daltima actualizaci\u00f3n de la lista: %1\nN\u00ba total de Filtros IP - N\u00ba de IPs bloqueadas/expulsadas/da\u00f1inas durante esta sesi\u00f3n.\nDoble clic para m\u00e1s detalles. ConfigView.section.ipfilter.list.banned=ha sido expulsado ConfigView.section.ipfilter.list.baddata=envi\u00f3 datos corruptos: veces = Button.reset=Reiniciar ConfigView.section.ipfilter.bannedinfo=IPs que enviaron datos corruptos - expulsadas si sobrepasan el l\u00edmite ConfigView.section.ipfilter.blockedinfo=IPs bloqueadas por los filtros IP download.removerules.name=Reglas de eliminaci\u00f3n download.removerules.unauthorised.info=torrents desautorizados son aquellos cuya respuesta del announce contiene o "not authoris(z)ed" o bien "unauthoris(z)ed" en la "failure response" download.removerules.unauthorised=Autoeliminar torrents desautorizados download.removerules.unauthorised.seedingonly=\tS\u00f3lo si est\u00e1s de seed download.removerules.removed.ok=Torrent '%1' autoeliminado con \u00e9xito. Esto se hizo siguiendo las reglas de autoeliminaci\u00f3n de torrents. download.removerules.updatetorrents=Vuze deja de actualizar torrents como precisa el emjambre ConfigView.label.defaultstarttorrentsstopped=Los torrents nuevos empiezan detenidos (por defecto) ConfigView.section.server.enableudp=Activar el protocolo UDP para clientes del rastreador. upnp.mapping.dataportudp=puerto de cliente UDP del rastreador ConfigView.section.file.decoder.showlax=Mostrar las codificaciones menos probables ConfigView.section.file.decoder.showall=Tener en cuenta todas las codificaciones posibles MainWindow.status.updowndetails.tooltip=Detalles velocidad Subida/Descarga\nclic-dcho. para cambiarlas, doble clic para abrir las estad\u00edsticas TrackerClient.announce.warningmessage=El rastreador de '%1' ha devuelto el aviso '%2' ConfigView.section.tracker.natcheckenable=Probar el 'puerto para datos entrantes' e informar a los clientes de los fallos en su disponibilidad ConfigView.section.tracker.publishenabledetails=Publicar todos los detalles del torrent ConfigView.section.tracker.publishenablepeerdetails=Publicar detalles de los clientes MyTrackerView.badnat=Mala NAT MyTrackerView.badnat.info=Semillas/Clientes que han fallado una prueba de NAT, si est\u00e1 activado ConfigView.section.tracker.natchecktimeout=Temporizador de la Comprobaci\u00f3n (segs) ConfigView.section.file.perf.cache.enable=Activar cach\u00e9 de disco ConfigView.section.file.perf.cache.size=Tama\u00f1o de la cach\u00e9 en %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=T&ransferencias MainWindow.menu.transfers.startalltransfers=&Iniciar Todo MainWindow.menu.transfers.stopalltransfers=D&etener Todo MainWindow.menu.transfers.pausetransfers=&Pausa MainWindow.menu.transfers.resumetransfers=&Reanudar ConfigView.label.experimental.osx.kernel.panic.fix=Arreglo experimental para kernel panics en sistemas OSX de doble cpu [precisa reiniciar] SystemTray.menu.pausetransfers=Pausar las Transferencias SystemTray.menu.resumetransfers=Continuar Transferencias ConfigView.section.file.truncate.too.large=Truncar los archivos mayores de lo que indica su .torrent (error 'File length is too large') ConfigView.section.file.perf.cache.trace=Rastrear operaciones de cach\u00e9 para realizar diagn\u00f3stico ConfigView.section.interface.enabletray=Activar 'Bandeja de Sistema' [necesita reiniciar] Stats.title.full=Estad\u00edsticas TransferStatsView.title.full=Transferencias CacheView.title.full=Cach\u00e9 CacheView.general.size=Tama\u00f1o total CacheView.general.inUse=Usada CacheView.general.title=Info sobre la Cach\u00e9 CacheView.reads.title=Lecturas de E/S CacheView.reads.fromFile=Desde Archivo CacheView.reads.fromCache=Desde la Cach\u00e9 CacheView.reads.hits=de Aciertos CacheView.writes.title=Escrituras de E/S CacheView.writes.toCache=A la Cach\u00e9 CacheView.writes.toFile=A Archivo CacheView.writes.hits=de Aciertos CacheView.speeds.title=Proporciones de Datos CacheView.speeds.reads=Lecturas CacheView.speeds.writes=Escrituras CacheView.speeds.fromCache=Desde/A Cach\u00e9 CacheView.speeds.fromFile=Desde/A Archivo CacheView.reads.#=N\u00ba CacheView.reads.amount=Cantidad CacheView.reads.avgsize=Tama\u00f1o medio openUrl.referrer=URL de la p\u00e1gina de referencia: openUrl.referrer.info=S\u00f3lo es necesaria para los sitios Web que la piden ConfigView.label.maxuploadspeedseeding=Velocidad alternativa para cuando solo se est\u00e1 sirviendo ConfigView.label.transfer.ignorepeerports=Ignorar los clientes con estos puertos para datos (separador ';', p.ej. 0;25) ConfigView.section.proxy.enable_socks.peer=Proximizar la comunicaci\u00f3n con los clientes (s\u00f3lo conexiones de salida) [precisa reinicio] ConfigView.section.proxy.peer.informtracker=Informar al rastreador de la limitaci\u00f3n ConfigView.section.proxy.socks.version=versi\u00f3n de SOCKS PiecesView.legend.written=Bloque Escrito PiecesView.legend.requested=Bloque Pedido PiecesView.legend.downloaded=Ya descargado, por escribir PiecesView.legend.incache=Datos que est\u00e1n en cach\u00e9 PiecesView.typeItem.0=Lenta PiecesView.typeItem.1=R\u00e1pida PiecesView.type=Tipo Security.jar.tools_not_found=Fallo en la firma JAR - no se ha encontrado 'tools.jar' en %1. M\u00e1s info en Herramientas->Opciones->Seguridad. Security.jar.signfail=Fallo en la firma JAR - %1 ConfigView.section.security.toolsinfo=Los archivos JAR firmados se usan para dar soporte a algunos complementos, p.ej. el Interfaz Web Swing (cuando se configura para ello).\nPara firmar archivos JAR se necesita tener acceso al archivo 'tools.jar' que viene con la instalaci\u00f3n del Sun JDK (no en el JRE).\nSi s\u00f3lo has instalado el JRE, instala el JDK.\n\nNormalmente Vuze econtrar\u00e1 \u00e9l solo el archivo, pero si falla, puedes dirigirlo a la carpeta donde est\u00e9 ConfigView.section.security.toolsdir=Carpeta continente de 'tools.jar' ConfigView.section.security.choosetoolssavedir=Seleccione la carpeta donde est\u00e1 'tools.jar' ConfigView.section.proxy.peer.same=Usar el mismo valor de proxy para comunicarse con el rastreador y con los clientes ConfigView.section.connection.network.max.simultaneous.connect.attempts=Conexiones de Salida: N\u00ba m\u00e1x de intentos simult\u00e1neos para establecerlas ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=N\u00ba m\u00e1x permitido de nuevas conexiones salientes que Vuze puede probar a establecer en un momento dado.\nNOTA: WindowsXP Service Pack 2 (SP2) impone un l\u00edmite de 10 intentos simult\u00e1neos de conexi\u00f3n.\n El valor por defecto es de 8. Un valor de 0, desactiva completamente las conexiones salientes. ConfigView.section.file.perf.cache.size.explain=La cach\u00e9 se usa para disminuir las lecturas y escrituras desde/a disco. A menos que utilices la opci\u00f3n java '-XX:MaxDirectMemorySize para especificar la cantidad de memoria destinada a cach\u00e9 y E/S, tienes que mantener este valor al menos unos %1 por debajo del tama\u00f1o m\u00e1ximo de tu MV(=MemoriaVirtual). El tama\u00f1o m\u00e1ximo actual de la MV es de %2. Para aprender a cambiarlo, mira VirtualMemory en el wiki de %3. Si introduces valores incongruentes, obtendr\u00e1s errores tipo 'out of memory'. No es bueno poner m\u00e1s de 32 Mb de memoria. MyTorrentsView.menu.setSpeed.unlimit=Sin l\u00edmite MyTorrentsView.menu.setSpeed.unlimited=Ilimitada MyTorrentsView.menu.setSpeed.disable=Desactivar Subidas MyTorrentsView.menu.setSpeed.disabled=Desactivado MyTorrentsView.menu.setSpeed.in=en MyTorrentsView.menu.setSpeed.slots=puestos de GeneralView.label.maxuploadspeed=Limitar la Subida GeneralView.label.maxuploadspeed.tooltip=velocidad m\u00e1xima de subida [0 : ilimitada] MyTorrents.items.UpSpeedLimit.disabled=No enviar MyTorrents.items.UpSpeedLimit.unlimited=Ilimitada TableColumn.header.maxupspeed=Veloc. Max Sub TableColumn.header.maxupspeed.info=Veloc. m\u00e1x de subida por torrent ConfigView.section.file.perf.cache.enable.write=Cachear los datos descargados para reducir las escrituras/lecturas a/desde disco, necesarias para comprobaci\u00f3n de partes ConfigView.section.file.perf.cache.enable.read=Hacer pre-lecturas al subir para reducir lecturas desde disco ConfigView.section.tracker.separatepeerids=Usar diferentes identidades de cliente para las comunicaciones con el rastreador y las de datos ConfigView.section.tracker.separatepeerids.info=Aumenta el anonimato si est\u00e1s descargando/sirviendo an\u00f3nimamente\nmediante una conexi\u00f3n no-an\u00f3nima con el rastreador ConfigView.section.interface.wavlocation=Localizaci\u00f3n del archivo .wav ConfigView.section.interface.wavlocation.info=Elegir un wav (dejarlo en blanco\npara usar el sonido por defecto) ConfigView.section.tracker.server=Servidor ConfigView.section.tracker.client=Cliente ConfigView.section.tracker.client.connecttimeout=Temporizador de la Conexi\u00f3n (segs) ConfigView.section.tracker.client.readtimeout=Temporizador para la Lectura (segs) MainWindow.menu.tools=&Herramientas FilesView.path=Ruta FilesView.fullpath=Mostrar ruta completa FilesView.remaining=Partes restantes TableColumn.header.trackername=Nombre rastreador TableColumn.header.trackername.info=El nombre que la URL de anuncio le d\u00e9 al rastreador ConfigView.group.override=Opciones a Ignorar ConfigView.section.file.perf.cache.notsmallerthan=No cachear archivos menores de esto (en %1) PeersView.menu.blockupload=Bloquear subida PeersView.menu.kickandban=Patada y expulsi\u00f3n PeersView.menu.kickandban.reason=Cliente expulsado manualmente PeersView.state=Estado PeersView.state.info=El estado de la conexi\u00f3n con el otro cliente PeersView.state.pending=Pendiente PeersView.state.connecting=Conectando PeersView.state.handshake=Negociando conexi\u00f3n PeersView.state.established=Totalmente establecida ConfigView.section.tracker.processinglimits=L\u00edmites de procesamiento ConfigView.section.tracker.maxgettime=Duraci\u00f3n m\u00e1x. para procesado de GET (segs) [0: ilimitado] ConfigView.section.tracker.maxgettime.info=Utilizado para announces y scrapes ConfigView.section.tracker.maxposttimemultiplier=Multiplicador de la duraci\u00f3n de GET para el procesado de POST [0: ilimitado] ConfigView.section.tracker.maxposttimemultiplier.info=Utilizado para el env\u00edo de formularios y descargas ConfigView.section.tracker.maxthreads=Peticiones concurrentes - N\u00ba m\u00e1x DownloadManager.error.operationcancancelled=Operaci\u00f3n cancelada Torrent.create.progress.cancelled=Operaci\u00f3n cancelada sharing.progress.cancel=Cancelar wizard.maketorrents.autoopen=Empezar a compartir el torrent en cuanto est\u00e9 echo ConfigView.section.sharing.rescanenable=Observar peri\u00f3dicamente mis comparticiones cl\u00e1sicas en busca de cambios ConfigView.section.sharing.rescanperiod=Periodicidad de la observaci\u00f3n (segs) ConfigView.section.connection.advanced=Opciones avanzadas de red ConfigView.section.connection.advanced.mtu=Unidad de transmisi\u00f3n m\u00e1xima de la l\u00ednea (MTU) ConfigView.section.connection.advanced.mtu.tooltip=El tama\u00f1o m\u00e1ximo de un paquete que se puede transferir en un frame por una red.\nVuze utiliza MTU-40 (MSS) para optimizar la carga \u00fatil de los paquetes en env\u00edo.\nLos valores recomendados son:\n 576 - Conexiones de marcado telef\u00f3nico\n 1492 - Conexiones de banda ancha PPPoE\n 1500 - Conexiones de banda ancha por Ethernet, DSL y Cable ConfigView.section.connection.advanced.SO_RCVBUF=Tama\u00f1o del Socket SO_RCVBUF [0: usar valores por defecto del SO] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Establece el valor est\u00e1ndar de socket SO_RCVBUF (en bytes), p.ej. tama\u00f1o y escala de la ventana de recepci\u00f3n TCP.\nVuze deja este valor sin ajustar por defecto, lo que significa que se usan los valores del SO en que corre.\nNOTA: Linux dobla los valores dados. ConfigView.section.connection.advanced.SO_SNDBUF=Tama\u00f1o del Socket SO_SNDBUF [0: usar valores por defecto del SO] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Establece el valor est\u00e1ndar de socket SO_SNDBUF value (en bytes), p.ej. tama\u00f1o de la ventana de env\u00edo TCP.\nVuze deja este valor sin ajustar por defecto, lo que significa que se usan los valores del SO en que corre.\nNOTA: Linux dobla el valor dado. ConfigView.section.connection.advanced.IPDiffServ=Valor DiffServ del paquete saliente (campo TOS) ConfigView.section.connection.advanced.IPDiffServ.tooltip=Establece la parte DiffServ del campo tipo-de-servicio (TOS) en la cabecera IP de los paquetes salientes.\nSe pueden especificar valores hexadecimales precendiendoles con '0x', p.ej. 0x10.\nVuze deja este valor sin ajustar por defecto, lo que significa que se usan los valores del SO en que corre.\nNOTA: Las implementaciones de red subyacentes pueden ignorar este valor, as\u00ed que esta opci\u00f3n depende en gran medida de las versiones del SO y del JRE. ConfigView.section.interface.confirm_torrent_removal=Mostrar un di\u00e1logo de confirmaci\u00f3n al eliminar un torrent ConfigView.section.interface.confirm_torrent_removal.tooltip=Confirmar al eliminar un torrent desde la vista Mis Torrents. MyTorrentsView.confirm_torrent_removal=\u00bfSeguro que quieres eliminarlo?\n TableColumn.header.seed_to_peer_ratio=Proporci\u00f3n Sem/Cli TableColumn.header.seed_to_peer_ratio.info=Proporci\u00f3n semillas por cliente del enjambre PeersView.connected_time=Tiempo conectado PeersView.connected_time.info=Tiempo en total conectado con el cliente ConfigView.section.interface.display.add_torrents_silently=A\u00f1adir silenciosamente los torrents ConfigView.section.interface.display.add_torrents_silently.tooltip=A\u00f1ade las descargas torrent sin activar la ventana principal de Vuze TableColumn.header.maxdownspeed=Veloc. m\u00e1x. descarga TableColumn.header.maxdownspeed.info=La velocidad m\u00e1x. de descarga por torrent PeersGraphicView.title=Enjambre ConfigView.section.tracker.passwordwebhttpsonly=Permitir el acceso s\u00f3lo mediante HTTPS TableColumn.header.torrentpath=Ubicaci\u00f3n del Torrent TableColumn.header.torrentpath.info=Lugar del disco donde est\u00e1 el Torrent ConfigView.section.sharing.torrentcomment=Comentario para los torrents generados ConfigView.label.copyanddeleteratherthanmove=Copiar y luego borrar los datos originales en lugar de moverlos en una sola operaci\u00f3n (en algunos sistemas de archivos servir\u00e1 para evitar la p\u00e9rdida de los datos.) ConfigView.label.openstatsonstart=Abrir las estad\u00edsticas durante el inicio swt.install.window.title=Instalador de Complementos de Vuze swt.install.window.ok=Instalar swt.install.window.header=Se van a instalar los siguientes componentes : swt.uninstall.window.title=Desinstalador de Complementos de Vuze swt.uninstall.window.ok=Desinstalar swt.uninstall.window.header=Se van a desinstalar los siguientes componentes : installPluginsWizard.title=Instalar Complementos installPluginsWizard.mode.title=Por favor, elija un m\u00e9todo de instalaci\u00f3n installPluginsWizard.mode.list=Mediante listado desde sourceforge.net installPluginsWizard.list.title=Lista de Complementos instalables installPluginsWizard.list.loading=Espere mientras se carga la lista de complementos. installPluginsWizard.list.loaded=Seleccione por favor los complementos que quiere instalar. installPluginsWizard.list.name=Nombre installPluginsWizard.list.version=Versi\u00f3n installPluginsWizard.list.description=Descripci\u00f3n del Complemento installPluginsWizard.finish.title=Instalando installPluginsWizard.finish.explanation=El Asistente de Actualizaci\u00f3n instalar\u00e1 los complementos seleccionados.\n\nSea paciente por favor, tardar\u00e1 un poco en aparecer.\n\nEncontrar\u00e1 el informe de progreso haciendo doble clic en la parte izda de la barra de estado. installPluginsWizard.details.loading=Cargando los detalles, espere por favor... installPluginsWizard.mode.file=Mediante un archivo installPluginsWizard.installMode.title=Por favor, elija el tipo de instalaci\u00f3n installPluginsWizard.installMode.user=Instalar el/los complemento(s) solo para t\u00ed installPluginsWizard.installMode.shared=Instalar el/los complemento(s) para todos los usuarios installPluginsWizard.file.title=Por favor despl\u00e1cese hasta el complemento que quiere instalar installPluginsWizard.file.file=Archivo : installPluginsWizard.file.invalidfile=El archivo no es un complemento v\u00e1lido de Azureus. installPluginsWizard.file.no_such_file=No existe ningun archivo con ese nombre. installPluginsWizard.file.browse=Navegar... uninstallPluginsWizard.title=Desinstalar Complementos uninstallPluginsWizard.list.title=Lista de complementos instalados uninstallPluginsWizard.list.loaded=Seleccione los complementos que quiere desinstalar. installPluginsWizard.list.nullversion=Sin Versi\u00f3n uninstallPluginsWizard.finish.title=Desinstalando uninstallPluginsWizard.finish.explanation=El Asistente de Actualizaci\u00f3n desinstalar\u00e1 los complementos seleccionados. MainWindow.menu.plugins.installPlugins=Asistente de Instalaci\u00f3n... MainWindow.menu.plugins.uninstallPlugins=Asistente de Desinstalaci\u00f3n... ConfigView.section.ipfilter.totalIPs=Hay un total de %1 IPs a bloquear, que representan el %2 de internet. update.instance.install=Comprobando Instalaci\u00f3n update.instance.uninstall=Comprobando Desinstalaci\u00f3n update.instance.update=Buscando Actualizaciones MainWindow.status.update.tooltip=Doble clic ofrece info sobre su progreso updater.progress.window.title=Tareas de Instalaci\u00f3n en curso updater.progress.window.info=Pulse 'Abortar' para terminar todas las tareas pendientes Button.abort=Abortar ConfigView.section.ipfilter.enablebanning=Bloquear a los clientes que repetidamente env\u00eden datos corruptos Network.alert.acceptfail=Han ocurrido demasiados fallos consecutivos en el puerto %1, %2 - se abandona su procesado. Compruebe por favor que su cortafuegos permite conexiones entrantes por este puerto. MyShares.column.category=Categor\u00eda UpdateWindow.restartLater=Reiniciar despu\u00e9s MainWindow.menu.file.restart=Reiniciar Vuze MainWindow.dialog.restartconfirmation.title=\u00bfReiniciar Vuze MainWindow.dialog.restartconfirmation.text=\u00bfSeguro que quieres reiniciar Vuze deletetorrent.message1=Est\u00e1 a punto de borrar el descriptor .TORRENT de :\n deletetorrent.message2=\n\u00bfQuiere seguir? ConfigView.label.prioritizemostcompletedfiles=Priorizar los archivos de m\u00e1s alta prioridad atendiendo a su % completado y el tama\u00f1o del archivo splash.plugin.init=Inicializando complemento: splash.plugin.UIinit=Inicializando complemento GUI: %1 ConfigView.section.style.osx_small_fonts=Usar fuentes peque\u00f1as [ser\u00e1 necesario reiniciar] ConfigView.section.tracker.tcpnonblocking=Usar E/S no-bloqueantes para el procesado del rastreador TCP. Esta opci\u00f3n precisa de que el rastreador web funcione en un puerto alternativo. \u00a1Experimental! ConfigView.section.tracker.nonblocking=Opciones No-bloqueantes ConfigView.section.tracker.nonblockingconcmax=Conexiones simult\u00e1neas - N\u00ba m\u00e1x.[0: ilimitadas] MyTorrentsView.menu.exportmenu=Exportar ConfigView.group.scrape=Raspado (Scrape) ConfigView.section.tracker.client.scrapeinfo=Al deshabilitar el raspado, dejar\u00e1n de funcionar muchas de las 'reglas de colas' (ya que dependen de la informaci\u00f3n sobre el enjambre obtenida por estos raspados). ConfigView.section.tracker.client.scrapeenable=Permitir raspado ConfigView.section.tracker.client.scrapestoppedenable=Raspar los torrents que no est\u00e1n en marcha Scrape.status.disabled=Raspado desactivado MyTorrentsView.menu.explore=Mostrar archivo MyTorrentsView.menu.explore._mac=Mostrar en el Finder MyTorrentsView.menu.explore._windows=Mostrar en el Explorer wizard.maketorrents.autohost=Hospedar el torrent en el rastreador incorporado ConfigView.label.overrideip=Ignorar la(s) IP(s) de Anuncio del rastreador - separar con ";" si se usaran m\u00e1s de una para redes diferentes ConfigView.label.overrideip.tooltip=Informar al rastreador de que se usa una direcci\u00f3n IP para los paquetes entrantres y otra diferente para los salientes. Dejarlo en blanco para no usar esta opci\u00f3n. ConfigView.section.connection.group.networks=Redes ConfigView.section.connection.group.networks.info=Seleccione las redes a las que permite realizar transmisiones de datos p2p ConfigView.section.connection.networks.prompt=Pedir selecci\u00f3n cuando se a\u00f1ade una descarga de un rastreador an\u00f3nimo ConfigView.section.connection.networks.Public=Red IP p\u00fablica (no an\u00f3nima) ConfigView.section.connection.networks.I2P=Red I2P ConfigView.section.connection.networks.Tor=La red enrutadora Onion (Tor) TableColumn.header.networks=Redes TableColumn.header.networks.info=Redes permitidas para realizar las comunicaciones cliente-cliente (peer-peer) Scrape.status.networkdisabled=Red no activada ConfigView.section.tracker.server.group.networks=Redes ConfigView.section.tracker.server.group.networks.info=Seleccione las redes de las que el rastreador aceptar\u00e1 clientes window.networkselection.title=Seleccci\u00f3n de Red window.networkselection.info=El torrent listado m\u00e1s abajo tiene rastreador(es) que soportan las siguientes redes.\nSeleccione las que quiera permitirles comunicarse con el rastreador y cliente.\nSi es un rastreador an\u00f3nimo que soporta clientes p\u00fablicos, active ambas redes (an\u00f3nimas y p\u00fablicas).\n\u00a1El precio evidente de permitir la red p\u00fablica es perder el anonimato! plugins.basicview.clear=Limpiar ConfigView.section.connection.group.peersources=Fuentes de clientes ConfigView.section.connection.group.peersources.info=Seleccione el origen de los clientes a los que permitir\u00e1 conect\u00e1rsele ConfigView.section.connection.peersource.Tracker=Desde un tracker ConfigView.section.connection.peersource.DHT=Rastreo descentralizado ConfigView.section.connection.peersource.PeerExchange=Suministrado por otro cliente ConfigView.section.connection.peersource.Plugin=A\u00f1adido por un complemento ConfigView.section.connection.peersource.Incoming=Conexion entrante PeersView.source=Origen PeersView.source.info=El origen de este cliente TableColumn.header.peersources=Or\u00edgenes de cliente TableColumn.header.peersources.info=Or\u00edgenes de clientes a los que se les permite establecer conexiones de pares wizard.tracker.dht=Descentralizado (solo los clientes Vuze MyTorrentsView.menu.advancedmenu=Avanzado MyTorrentsView.menu.networks=Redes MyTorrentsView.menu.peersource=Fuentes de clientes ConfigView.section.sharing.permitdht=Permitir rastreo descentralizado cuando el tracker no est\u00e9 disponible ConfigView.section.sharing.protocol=Protocolo para los recursos compartidos cl\u00e1sicamente PeersView.Messaging=Mensajer\u00eda PeersView.Messaging.info=Indica el sistema de mensajer\u00eda que se est\u00e1 usando ConfigView.label.queue.newseedsmovetop=Mover los torrents reci\u00e9n completados al principio de la lista a compartir ConfigView.label.seeding.firstPriority.ignore.info=Tenga en cuenta que usar estar reglas puede terminar en la\nparada de un torrent tan pronto como termine de descargarse. ConfigView.label.seeding.firstPriority.ignore=Ignorar las reglas de 1\u00aa Prioridad anteriores con: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents con una distribuci\u00f3n aproximada de Semillas a Clientes de ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents con 0 Clientes ConfigView.section.tracker.sendjavaversionandos=Enviar versi\u00f3n de Java y nombre del SO MagnetPlugin.contextmenu.exporturi=Copiar Magnet URI al portapapeles ConfigView.section.plugins.dht=DB distribu\u00edda dht.info=Este complemento soporta entre otras cosas, el rastreo descentralizado - desactiv\u00e1ndolo reducir\u00e1s tu capacidad para descargar dht.enabled=Activar la base de datos distribu\u00edda dht.portdefault=Usar el puerto por defecto dht.port=Puerto UDP para la database dht.execute.command=Comando de diagn\u00f3stico dht.execute.info=Pulsar para ejecutar el comando dht.execute=Arrancar dht.logging=Activar seguimiento de la actividad ConfigView.section.plugins.dhttracker=Rastreador distribu\u00eddo dhttracker.tracknormalwhenoffline=Rastrear torrents normales solamente cuando su rastreador no est\u00e9 disponible ConfigView.section.file.nativedelete._mac=Usar la Papelera al eliminar archivos ConfigView.section.file.nativedelete._windows=Enviar los archivos borrados a la papelera ConfigView.section.logging.generatediagnostics=Crear ConfigView.section.logging.netinfo=Generar info de la red ConfigView.section.logging.statsinfo=Generar info de las estad\u00edsticas ConfigView.section.logging.generatediagnostics.info=Crear informaci\u00f3n de diagn\u00f3stico y copiarla al portapapeles y al archivo log, si as\u00ed se configura ConfigView.section.sharing.privatetorrent=Torrent privado (s\u00f3lo se aceptan los clientes que decida el tracker) MainWindow.menu.tools.nattest=Probar &NAT / Cortafuegos Button.apply=Aplicar Button.close=Cerrar window.welcome.title=Bienvenido a Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Notas sobre esta versi\u00f3n dht.reseed.label=Normalmente no es necesario re-sembrar la Base de datos Ditribu\u00edda. Sin embargo, si el n\u00ba de contactos es bajo, esto se puede usar para re-integrarla.\nO la deja en blanco, recreando la red y olvid\u00e1ndose de los clientes a los que est\u00e1 conectado o bien puede especificar la IP y el puerto de un cliente conocido al que engancharse para recrear la red. dht.reseed.group=Re-sembrar dht.reseed.ip=Direcci\u00f3n IP dht.reseed.port=Puerto dht.reseed=Re-sembrar dht.reseed.info=Re-sembar la base de datos dht.diagnostics.group=Diagn\u00f3sticos DHTView.title.full=Base de datos Distribu\u00edda DHTView.title.fullcvs=Base de datos Distribu\u00edda CVS DHTView.general.uptime=Funcionando desde: DHTView.general.users=Usuarios: DHTView.general.nodes=Nodos: DHTView.general.leaves=Abandonos: DHTView.general.contacts=Contactos: DHTView.general.replacements=Sustitutos: DHTView.general.live=En vivo: DHTView.general.unknown=Desconocido: DHTView.general.dying=Expirando: DHTView.transport.title=Detalles del Transporte DHTView.transport.packets=Paquetes DHTView.transport.received=Recibido DHTView.transport.sent=Enviado DHTView.transport.in=Entrada : DHTView.transport.out=Salida : DHTView.operations.title=Detalles de la Operaci\u00f3n DHTView.operations.sent=Enviado DHTView.operations.failed=Fallidas DHTView.operations.received=Recibido DHTView.operations.findNode=Hallar Nodo DHTView.operations.findValue=Hallar Valor DHTView.operations.store=Almacenar DHTView.activity.title=Actividad DHTView.activity.status=Estado DHTView.activity.status.true=En cola DHTView.activity.status.false=Funcionando DHTView.activity.type=Tipo DHTView.activity.type.1=Get Interno DHTView.activity.type.2=Get Externo DHTView.activity.type.3=Put Interno DHTView.activity.type.4=Put Externo DHTView.activity.target=Objetivo DHTView.activity.details=Detalles DHTView.db.title=Base de datos DHTView.db.keys=Claves DHTView.db.values=Valores DHTView.db.direct=Directo DHTView.db.indirect=Indirecto DHTView.db.divfreq=Frec. Div. DHTView.db.divsize=Tama\u00f1o Div. MainWindow.dht.status.tooltip=Cuando el DHT est\u00e1 funcionando, muestra el n\u00ba estimado de usuarios conectados en ese momento MainWindow.dht.status.disabled=DHT Desactivado MainWindow.dht.status.failed=DHT Fallido MainWindow.dht.status.initializing=Inicializando DHT MainWindow.dht.status.users=%1 usuarios MainWindow.dht.status.unreachable=DHT bloqueado por cortafuegos MainWindow.dht.status.unreachabletooltip=Parece ser que existe un problema con el mapeado de puertos UDP de la Base de datos distribu\u00edda (NAT/cortafuegos) MyTorrentsView.menu.setUpSpeed=Ajustar la velocidad de Subida MyTorrentsView.menu.setDownSpeed=Ajustar la velocidad de Descarga ConfigView.section.tracker.client.showwarnings=Mostrar advertencias de los rastreadores dht.advanced=Activar las preferencias avanzadas dht.advanced.group=Preferencias avanzadas dht.advanced.label=Altera estos valores s\u00f3lo si realmente sabes lo que est\u00e1s haciendo dht.override.ip=Ignorar direcciones IP externas ConfigView.section.logging.loggerenable=Activar Registro ConfigView.section.ipfilter.blockbanning=Expulsar las 256 direcciones de un bloque, si de \u00e9ste ya se han expulsado MyTrackerView.passive=Pasivo TableColumn.header.swarm_average_speed=Veloc. media enjambre TableColumn.header.swarm_average_speed.info=La velocidad media de los clientes que componen el enjambre TableColumn.header.comment=Comentario TableColumn.header.comment.info=Comentario definido por el usuario para la descarga TableColumn.header.commenticon=Icono de Comentario TableColumn.header.commenticon.info=Presenta un icono si la descarga contiene un comentario definido por el usuario MyTrackerView.category=Categor\u00eda MainWindow.menu.file.open.torrentfortracking=Archivo .torrent... (S\u00f3lo Rastreo) MyTrackerView.date_added=A\u00f1adido ConfigView.section.tracker.portbackup=Puertos de respaldo (separados por ';') ConfigView.label.playfilespeech=Mensaje hablado al terminar un archivo ConfigView.label.playfilespeech.info=Por el momento, los servicios de habla funcionan mejor con el Ingl\u00e9s ConfigView.label.playfilefinished=Reproducir un sonido al terminar un archivo ConfigView.label.backupconfigfiles=Mantener una copia de seguridad de los archivos de configuraci\u00f3n. ConfigView.section.tracker.client.scrapesingleonly=Desactiva la suma de raspados por-rastreador (para casos en que los rastreadores dan el error 'URL too long' (414) (URL demasiado larga)) dht.ipfilter.log=Anotar las violaciones en el Filtrado de IPs ConfigView.label.seeding.addForSeedingDLCopyCount=Considerar como descargas 'a\u00f1adir para compartir' las que han descargado este n\u00ba de copias ActivityView.legend.limit=Tasa l\u00edmite ActivityView.legend.achieved=Tasa alcanzada ActivityView.legend.overhead=Tasa de gasto ActivityView.legend.peeraverage=Media ActivityView.legend.swarmaverage=Media del enjambre ActivityView.legend.trimmed=Recortada (punteado) MyTorrentsView.menu.movemenu=Mover Archivos MyTorrentsView.menu.movedata=Mover Archivos de Datos... MyTorrentsView.menu.movetorrent=Mover Archivo Torrent... MyTorrentsView.menu.movedata.dialog=Escoja el nuevo destino DHTView.operations.data=Datos DHTView.general.reachable=Alcanzable: DHTView.general.rendezvous=Presentaci\u00f3n: ConfigView.label.queue.maxactivetorrentswhenseeding=M\u00e1x. al 'solo servir' [0:ilimitado] Views.plugins.IRC.title=IRC - Soporte T\u00e9cnico Online Formats.units.alot=\u00a1\u00a1\u00a1 Un mont\u00f3n !!! ConfigView.section.ipfilter.persistblocking=Recordar entre reinicios los detalles de las IP bloqueadas. FilesView.menu.rename=Renombra o Recoloca FilesView.menu.rename_only=Renombrado r\u00e1pido FilesView.menu.retarget=Mover archivos FilesView.rename.choose.path=Elegir un archivo nuevo o uno ya existente FilesView.rename.choose.path.dir=Escoja una carpeta nueva o una ya existente FilesView.rename.confirm.delete.title=Confirmar Eliminaci\u00f3n FilesView.rename.confirm.delete.text=Confirma la eliminaci\u00f3n del archivo original '%1' FilesView.rename.filename.title=Renombrar archivo FilesView.rename.filename.text=Escoja un nombre nuevo para el archivo ConfigView.higher.mode.available=Dispone de m\u00e1s opciones en los modos de usuario m\u00e1s elevados ConfigView.section.mode=Modo ConfigView.section.mode.title=Experiencia del Usuario ConfigView.section.mode.beginner=Principiante ConfigView.section.mode.beginner.wiki.definitions=Vocabulario BitTorrent ConfigView.section.mode.intermediate=Intermedio ConfigView.section.mode.intermediate.wiki.host=Hospedando Archivos ConfigView.section.mode.intermediate.wiki.publish=Publicando Archivos ConfigView.section.mode.advanced=Avanzado ConfigView.section.mode.advanced.wiki.main=P\u00e1gina principal del Wiki ConfigView.section.mode.beginner.text=Todo lo que necesitas para descargar torrents.\nUsa este modo si lo \u00fanico que quieres es administrar tus torrents.\n ConfigView.section.mode.intermediate.text=Acceso a las funciones de rastreador.\nUsa este modo si quieres crear tu propio rastreador y hospedar/publicar tus archivos.\n ConfigView.section.mode.advanced.text=Acceso a las preferencias de red.\nUsa este modo si sabes lo que son MTU o E/S sin bloqueo...\n Files.column.storagetype=Tipo de almacenamiento Files.column.fileext=Tipo FileItem.storage.linear=Lineal FileItem.storage.compact=Compacto MessageBoxWindow.rememberdecision=Recordar mi decisi\u00f3n ConfigView.section.interface.cleardecisions=Olvida todas las decisiones que recuerda ConfigView.section.interface.cleardecisionsbutton=Olvidar ConfigView.section.interface.cleartrackers=Olvidar los rastreadores recordados ConfigView.section.interface.cleartrackersbutton=Olvidar ConfigView.section.interface.clearsavepaths=Limpiar las rutas donde guardar recordadas ConfigView.section.interface.clearsavepathsbutton=Limpiar configureWizard.welcome.usermodes=De acuerdo a la 'experiencia del usuario' que establezcas aqu\u00ed, se mostrar\u00e1n m\u00e1s o menos opciones en Herramientas -> Opciones. Te interesa establecerlo en lo m\u00e1s indicado para t\u00ed. FilesView.skip.confirm.delete.text=\u00bfTruncar el archivo '%1' para ahorrar espacio? FilesView.rename.failed.title=Fall\u00f3 Renombrar/Recolocar FilesView.rename.failed.text=La operaci\u00f3n fall\u00f3, porque probablemente has elegido un destino no v\u00e1lido diagnostics.log_found=Vuze no se cerr\u00f3 correctamente. Observe cualquier diagnostic log files. Lea tambi\u00e9n el art\u00edculo Wiki Vuze Disappears para ampliar informaci\u00f3n. ManagerItem.paused=Pausado Utils.link.visit=Visite por favor ConfigView.section.connection.serverport.wiki=Puertos buenos para elegir ConfigView.section.transfer.speeds.wiki=Preferencias de velocidad buenas installPluginsWizard.installMode.info.text=No se necesita ning\u00fan complemento para que Vuze funcione bien, pero a\u00f1aden caracter\u00edsticas de las que disfrutar, automatizaci\u00f3n o control remoto. Por favor lee atentamente las descripciones de cada complemento antes de decidirte a instalarlos.\nLa mayor\u00eda de los complementos son seguros, pero no sobrecargues tu configuraci\u00f3n con complementos que luego no vas a usar. Views.plugins.Distributed.DB.title=DB Distribu\u00edda Views.plugins.Distributed.Tracker.title=Rastreador Distribu\u00eddo Views.plugins.Plugin.Update.title=Actualizar Complemento openUrl.url.info=Soporta cadenas infohash magnet, hexadecimales en bruto, http y https TableColumn.header.swarm_average_completion=Finalizaci\u00f3n media (clientes) TableColumn.header.swarm_average_completion.info=La media de lo ya descargado por los clientes del enjambre GeneralView.label.swarm_average_completion=Finalizaci\u00f3n Media: GeneralView.label.swarm_average_completion.tooltip=El porcentaje medio de finalizaci\u00f3n en los clientes del enjambre MainWindow.nat.status.tooltip.unknown=Accesibilidad (TCP) del Cortafuegos/NAT: Estado desconocido MainWindow.nat.status.tooltip.ok=Accesibilidad OK (TCP) MainWindow.nat.status.probok=\u00bfNAT OK? MainWindow.nat.status.tooltip.probok=La accesibilidad est\u00e1 bien, sin embargo no hay conexiones TCP entrantes recientes MainWindow.nat.status.bad=Bloqueado por cortafuegos MainWindow.nat.status.tooltip.bad=Problema de accesibilidad (TCP) por NAT/cortafuegos, obtendr\u00e1 ayuda en el Wiki plugin.installer.recommended.plugin=Complemento recomendado - por favor v\u00e9alo e inst\u00e1lelo si lo necesita LoggerView.pause=Pausar Registro LoggerView.clear=&Limpiar LoggerView.filter=Filtro LoggerView.filter.uncheckAll=Desmarcar todas las categor\u00edas LoggerView.filter.checkAll=Marcar todas las categor\u00edas LoggerView.loggingDisabled=El registro no est\u00e1 activado. LoggerView.includeOnly=Mostrar s\u00f3lo las l\u00edneas que concuerden con esta expresi\u00f3n regular: LoggerView.excludeAll=No mostrar las l\u00edneas que concuerden con esta expresi\u00f3n regular: ConfigView.section.logging.log0type=Informaci\u00f3n ConfigView.section.logging.log1type=Advertencia ConfigView.section.logging.log2type=Enviado ConfigView.section.logging.filter=Filtrar al registrar en archivo ConfigView.section.logging.level=Nivel de Registro ConfigView.section.logging.showLogsFor=Mostrar %1 de los registros para las siguientes categor\u00edas ConfigView.pluginlist.column.loadAtStartup=Cargar al Inicio ConfigView.pluginlist.column.type=Tipo ConfigView.pluginlist.column.type.perUser=Por Usuario ConfigView.pluginlist.column.type.shared=Compartido ConfigView.pluginlist.column.type.builtIn=Incorporado ConfigView.pluginlist.column.name=Nombre ConfigView.pluginlist.column.version=Versi\u00f3n ConfigView.pluginlist.column.directory=Carpeta ConfigView.pluginlist.column.isOperational=\u00bfOperativo? PeersView.BlockView.Avail.Have=Ambos ten\u00e9is PeersView.BlockView.Avail.NoHave=el Cliente tiene, T\u00fa no PeersView.BlockView.NoAvail.Have=Tienes, el Cliente no PeersView.BlockView.NoAvail.NoHave=Ninguno tiene PeersView.BlockView.Transfer=Transfiriendo PeersView.BlockView.NextRequest=Sigte. Petici\u00f3n PeersView.BlockView.title=Mapa de Partes PeersView.BlockView.AvailCount=Disponibilidad MyTorrentsView.dialog.NumberError.title=N\u00ba Inv\u00e1lido o Irreconocible MyTorrentsView.dialog.NumberError.text=El n\u00famero que has introducido es irreconocible o no v\u00e1lido. MyTorrentsView.menu.manual.per_torrent=Manual (por torrent) MyTorrentsView.menu.manual.shared_torrents=Manual (entre torrents) MyTorrentsView.dialog.setSpeed.title=Establecer velocidad de %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Introduzca un n\u00famero %1 para cambiar %2 a: MyTorrentsView.dialog.setNumber.upload=subida MyTorrentsView.dialog.setNumber.download=descarga MyTorrentsView.dialog.setNumber.inKbps=en %1 OpenTorrentWindow.torrentLocation=Torrent(s) a descargar: OpenTorrentWindow.addFiles.URL=A\u00f1adir &URL OpenTorrentWindow.addFiles.Folder=A\u00f1adir &Carpeta OpenTorrentWindow.addFiles.Clipboard=A\u00f1adir desde el P&ortapapeles OpenTorrentWindow.changeDestination=Cambiar Destino OpenTorrentWindow.fileList=Archivos en torrents: OpenTorrentWindow.torrentTable.name=Nombre OpenTorrentWindow.torrentTable.saveLocation=A Guardar en OpenTorrentWindow.fileTable.fileName=Nombre de Arch. OpenTorrentWindow.fileTable.size=Tama\u00f1o OpenTorrentWindow.fileTable.destinationName=Nombre Dest. OpenTorrentWindow.startMode.seeding=Sirviendo OpenTorrentWindow.fileList.changeDestination=Cambiar Destino OpenTorrentWindow.mb.badSize.title=Archivo Incompatible OpenTorrentWindow.mb.badSize.text='%1' no es '%2' y no se puede usar para servirlo OpenTorrentWindow.mb.alreadyExists.text=%3 ya se hab\u00eda a\u00f1adido como '%2' OpenTorrentWindow.mb.alreadyExists.default.name=Medios OpenTorrentWindow.mb.alreadyExists.title=El Torrent ya exist\u00eda OpenTorrentWindow.mb.openError.title=Error al abrir OpenTorrentWindow.mb.openError.text='%1' no se pudo abrir: OpenTorrentWindow.torrent.remove=Quitar torrent de la lista OpenTorrentWindow.torrent.options=Los siguientes valores se aplicar\u00e1n a los torrents seleccionados m\u00e1s abajo: OpenTorrentWindow.xOfTotal=(%1 de %2) iconBar.open.tooltip=Abrir Torrent(s) LocaleUtil.column.text=Texto Desconocido Tracker.tooltip.MultiSupport=Este rastreador soporta m\u00faltiples raspados de hash en una petici\u00f3n. Tracker.tooltip.NoMultiSupport=Este rastreador NO soporta m\u00faltiples raspados de hash en una petici\u00f3n.\nEsto no afectar\u00e1 a tu rendimiento, pero supone una carga extra para el rastreador. ConfigView.label.lazybitfield=Utilizar lazy bitfield (ayuda a compartir sobre redes que emplean bloqueo basado en bitfield) LoggerView.realtime=Actualizar en tiempro real ConfigView.section.file.perf.cache.flushpieces=Escribir inmediatamente a disco las partes completadas. Esto facilita el acceso a disco a costa de realizar m\u00e1s operaciones de escritura. ConfigView.section.file.writemblimit=N\u00ba m\u00e1ximo de peticiones de escritura en cola (en %1) ConfigView.section.file.writemblimit.explain=Cuando se escribe a disco m\u00e1s lento que se descarga, este par\u00e1metro limita la cantidad de datos que se pondr\u00e1n en cola antes de reducir la(s) velocidad(es) de descarga. ConfigView.section.file.readmblimit=N\u00ba m\u00e1ximo de peticiones de lectura en cola (en %1) ConfigView.section.file.readmblimit.explain=Este par\u00e1metro limita la cantidad de memoria que se va a usar para almacenar las lecturas pendientes de procesar. Button.moveUp=Subir Button.moveDown=Bajar ConfigView.notAvailableForMode=Esta secci\u00f3n est\u00e1 pensada para el modo %1 o superior. No est\u00e1 disponible en el modo %2. health.explain.error=Existe un error en este torrent. Observe el error en la columna de estado o en el tooltip sobre el icono. GeneralView.label.trackerscrapeupdate=Raspar el Rastreador PeersView.piece=Parte PeersView.piece.info=N\u00ba de la \u00faltima parte solicitada a este par PiecesView.priority=Prioridad PiecesView.priority.info=la prioridad de completado de este parte, pero no le prestes demasiada atenci\u00f3n PiecesView.speed=Velocidad PiecesView.speed.info=A los pares m\u00e1s lentos se les impide interferir demasiado con partes m\u00e1s r\u00e1pidas TableColumn.header.AvgAvail.info=Relaci\u00f3n entre la disponibilidad media de las partes, y el n\u00ba de conexiones TableColumn.header.AvgAvail=Dispon. Media/parte ConfigView.label.strictfilelocking=Entre torrents, hacer cumplir el bloqueo al acceso exclusivo en escritura a archivos MyTorrentsView.menu.checkfilesexist=Comprobar si existen los archivos MyTorrentsView.menu.rescanfile=Recomprobar peri\u00f3dicamente las Partes Incompletas MyTorrentsView.menu.clear_resume_data=Limpiar Datos para Reanudaci\u00f3n Plugin.extseed.name=Semillas Externas Plugin.localtracker.name=Buscador de pares en LAN Plugin.localtracker.info=El Buscador de pares en red local (LAN) permite que existan varias copias de Vuze tras un cortafuegos y una red com\u00fan\npara poder descargar eficiencientemente los torrents mediante la activaci\u00f3n de conexiones directas entre ellos Plugin.localtracker.enable=Activar el Buscador de pares en LAN azinstancehandler.alert.portclash=Colisi\u00f3n de puertos detectada en la LAN: %1 ya est\u00e1 siendo utilizado por otro usuario de Vuze; elija aleatoriamente otro(s) puerto(s) para atender la entrada TCP / UDP [entre %2 y %3]. ConfigView.section.transfer.lan.tooltip=Valores espec\u00edficos de la LAN ConfigView.section.transfer.lan.uploadrate=Velocidad m\u00e1x de env\u00edo de la LAN en KB/s [0: ilimitada] ConfigView.section.transfer.lan.uploadrate.tooltip=Las conexiones entre pares de la misma LAN interna, tienen diferentes l\u00edmites en la tasa de env\u00edo. ConfigView.section.transfer.lan.downloadrate=Velocidad m\u00e1x de recepci\u00f3n de la LAN en KB/s [0: ilimitada] ConfigView.section.transfer.lan.downloadrate.tooltip=Las conexiones entre pares de la misma LAN interna, tienen diferentes l\u00edmites en la tasa de descarga. TorrentOptionsView.title.short=Opciones TorrentOptionsView.title.full=Opciones TorrentOptionsView.param.max.peers=N\u00ba m\u00e1x. de conexiones [0: ilimitadas] ConfigView.section.connection.encryption.require_encrypted_transport=Requerir transporte encriptado ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Forzar el uso de conexiones encriptadas con otros clientes. ConfigView.section.connection.encryption.min_encryption_level=Nivel m\u00ednimo de encriptado. ConfigView.section.connection.encryption.min_encryption_level.tooltip=Sencillo - s\u00f3lo la negociaci\u00f3n\nRC4 - todo el stream\nEncriptados m\u00e1s fuertes usan m\u00e1s CPU. Peers.column.Encryption=Encriptado Peers.column.Encryption.info=Nivel de encriptado en uso ConfigView.section.connection.encryption.encrypt.info=Si se activa el el encriptado, no podr\u00e1 conectar con clientes incompatibles a menos que configure opciones retro. ConfigView.section.connection.encryption.encrypt.info.link=Aqu\u00ed podr\u00e1 obtener m\u00e1s detalles MainWindow.sr.status.tooltip.ok=Indice de compartici\u00f3n %1 OK MainWindow.sr.status.tooltip.poor=Indice de compartici\u00f3n %1 pobre: < 0.9 MainWindow.sr.status.tooltip.bad=Indice de compartici\u00f3n %1 malo: < 0.5 ConfigView.section.style.status=Area de Estado: ConfigView.section.style.status.show_sr=Indice de compartici\u00f3n ConfigView.section.style.status.show_nat=Estado del NAT ConfigView.section.style.status.show_ddb=Estado del DDB ConfigView.section.style.status.show_ipf=Estado del Filtro IP ConfigView.section.connection.encryption.encrypt.group=Cifrado del Transporte/Ofuscaci\u00f3n ConfigView.section.connection.encryption.encrypt.fallback_info=Activar cualquier opci\u00f3n retro le permitir\u00e1 conectar con clientes incompatibles PERO las conexiones estar\u00e1n sin encriptar ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Permitir conexiones salientes sin encriptar si falla al intentar las encriptadas ConfigView.section.connection.encryption.encrypt.fallback_incoming=Permitir conexiones entrantes no encriptadas ConfigView.section.connection.encryption=Encriptado del Transporte upnp.selectedinterfaces=Interfaces seleccionadas (separadas por ';' como p. ej. eth0;eth1) [en blanco: todas] ConfigView.section.style.defaultSortOrder=Tipo de orden por defecto ConfigView.section.style.defaultSortOrder.desc=Descendente ConfigView.section.style.defaultSortOrder.asc=Ascendente ConfigView.section.style.defaultSortOrder.flip=Invertir el orden anterior LoggerView.autoscroll=Auto-desplazar Button.selectAll=Seleccionar Todo Button.markSelected=Marcar lo Seleccionado Button.unmarkSelected=Desmarcar lo Seleccionado TorrentOptionsView.param.max.uploads=N\u00ba m\u00e1ximo de puestos de subida [m\u00ednimo:2] MyTorrentsView.dialog.setPosition.title=Establecer Posici\u00f3n MyTorrentsView.dialog.setPosition.text=Introduzca la posici\u00f3n a la que van los torrents seleccionados: MyTorrentsView.menu.reposition.manual=Reposicionamiento.. ConfigView.section.connection.advanced.info.link=Aqu\u00ed podr\u00e1 obtener m\u00e1s detalles ConfigView.section.connection.advanced.socket.group=Opciones de Socket ConfigView.section.connection.advanced.bind_port=Asociarse al puerto local [0: desactivado] ConfigView.section.connection.advanced.bind_port.tooltip=Las conexiones salientes por socket se asociar\u00e1n localmente al puerto dado.\nActivarlo puede ser de ayuda para con la inestabilidad del enrutador NAT. ConfigView.section.proxy.group.tracker=Comunicaciones con el Rastreador ConfigView.section.proxy.group.peer=Comunicaciones con los Clientes Pieces.column.Requested=Pedidas Pieces.column.Requested.info=Muestra si se puede o no hacer m\u00e1s peticiones sobre la parte (*) ConfigView.label.maxuploadsseeding=Valor Alternativo por defecto al s\u00f3lo servir MyTorrentsView.filter=Filtro: popup.error.hideall=Ocultar Todo ConfigView.section.style.dataStatsOnly=S\u00f3lo mostrar estad\u00edsticas de los datos (ocultar las del protocolo) ConfigView.section.style.separateProtDataStats=Mostrar las estad\u00edsticas de los datos y del protocolo separadas tal como 'data (protocol)' MyTorrentsView.dialog.setFilter.title=Modificar Filtro MyTorrentsView.dialog.setFilter.text=La secci\u00f3n %1 se filtrar\u00e1 con el texto que escriba aqu\u00ed debajo. Utilice el s\u00edmbolo | (tuber\u00eda) para filtrar m\u00faltiples frases. MyTorrentsView.filter.tooltip=Ctrl+X conmuta los modos de b\u00fasqueda RegEx y normal.\nUtilice el s\u00edmbolo | (tuber\u00eda) para filtrar m\u00faltiples frases. MyTorrentsView.clearFilter.tooltip=Limpiar Filtro MyTorrentsView.menu.filter=Lista de Filtros... ConfigView.section.file.resume.recheck.all=Comprobar todo el archivo durante el reinicio tras un cuelgue; (por defecto s\u00f3lo comprueba las partes activas durante el \u00faltimo punto de reanudaci\u00f3n). ConfigureWizard.language.choose=Elija un idioma de la lista inferior: popup.closing.in=Auto-cerrando ventana en %1 segundos popup.more.waiting=%1 mensaje(s) m\u00e1s.. # > 2402 popup.download.finished="%1" ha terminado de descargarse. popup.file.finished="%1" ha terminado de descargarse. ConfigView.auto=Autom\u00e1tico Plugin.localtracker.autoadd.info=Autoa\u00f1adir estos clientes locales [';' direcciones separadas, p.ej. 1.2.3.4] Plugin.localtracker.autoadd=Clientes expl\u00edcitos Plugin.localtracker.networks.info=Considerar como locales las siguientes redes [';' redes separadas, p.ej. 145.227.*.*] Plugin.localtracker.networks=Redes locales MainWindow.menu.view.plugins.logViews=Vista de Registros SpeedView.stats.autospeed=Velocidad Autom\u00e1tica de Subida SpeedView.stats.autospeed.disabled=O esta caracter\u00edstica est\u00e1 desactivada (porque necesitas el DHT) o sin usar (por ajuste manual de la velocidad de subida) SpeedView.stats.idlePing=Ping si Ocioso: SpeedView.stats.maxPing=Ping M\u00e1x: SpeedView.stats.currentPing=Ping Actual: SpeedView.stats.maxUp=Veloc M\u00e1x Subida: ConfigView.pluginlist.unloadSelected=Descarga la Selecci\u00f3n ConfigView.pluginlist.scan=Buscar localmente nuevos Complementos ConfigView.section.transfer.autospeed=Auto-Velocidad (cl\u00e1sica) ConfigView.section.transfer.autospeed.tooltip=Ajustes espec\u00edficos de la Auto-velocidad ConfigView.section.transfer.autospeed.info='Auto-velocidad' ajusta autom\u00e1ticamente la velocidad de env\u00edo para evitar sobrecargar la conexi\u00f3n a red.\n\nEsta opci\u00f3n estar\u00e1 sujeta a los siguientes l\u00edmites. (Necesita que previamente se haya activado la base de datos distribu\u00edda).\n ConfigView.section.transfer.autospeed.minupload=velocidad de env\u00edo m\u00ednima (en %1) ConfigView.section.transfer.autospeed.minupload.tooltip=Normalmente, la velocidad de env\u00edo no bajar\u00e1 de este valor ConfigView.section.transfer.autospeed.maxupload=velocidad de env\u00edo m\u00e1xima (en %1) [0: ilimitada] ConfigView.section.transfer.autospeed.maxupload.tooltip=Normalmente, la velocidad de env\u00edo no superar\u00e1 este valor ConfigView.section.transfer.autospeed.chokeping=Tiempo para Choking ping [milisegundos] ConfigView.section.transfer.autospeed.chokeping.tooltip=Los tiempos de ping que sobrepasen este valor se considerar\u00e1 como indicadores de saturaci\u00f3n de la red ConfigView.section.transfer.autospeed.enableauto=Activar al descargar y al servir ConfigView.section.transfer.autospeed.enableautoseeding=Activar al s\u00f3lo servir ConfigView.pluginlist.column.unloadable=No descargable ConfigView.section.transfer.lan.enable=Permitir a las conexiones LAN diferentes l\u00edmites de velocidad Plugin.localtracker.wellknownlocals=Incluir autom\u00e1ticamente bucle local/enlace/redes de \u00e1mbito local (192.168 etc) TableColumn.header.filesdone=Archivos Terminados TableColumn.header.filesdone.info=Archivos terminados/Total de archivos *o* archivos Sin-saltar terminados (Archivos terminados)/Total de archivos Sin-saltar (Total de archivos) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=esperando la inicializaci\u00f3n DDB... MagnetPlugin.report.searching=buscando... MagnetPlugin.report.found=hallado %1 MagnetPlugin.report.alive=%1 est\u00e1 vivo MagnetPlugin.report.dead=%1 est\u00e1 muerto MagnetPlugin.report.downloading=descargando desde %1 MagnetURLHandler.report.no_sources=no se hallaron fuentes para el torrent MagnetURLHandler.report.torrent_size=tama\u00f1o del torrent: %1 MagnetURLHandler.report.percent=completado: %1% DHTTransport.report.request_all=pidiendo la transferencia completa desde %1 DHTTransport.report.received_bit=recibido %1 a %2 desde %3 DHTTransport.report.complete=completado DHTTransport.report.timeout=temporizaci\u00f3n cumplida, sin respuestas desde %1 DHTTransport.report.rerequest_all=re-pidiendo transferencia completa desde %1 DHTTransport.report.rerequest_bit=re-pidiendo %1 a %2 desde %3 DHTTransport.report.timeout_some=temporizaci\u00f3n cumplida, recibidos %1 paquetes desde %2 pero est\u00e1n incompletos DHTTransport.report.sending=enviando datos DHTTransport.report.resending=reenviando datos DHTTransport.report.send_complete=env\u00edo completado DHTTransport.report.send_timeout=temporizaci\u00f3n cumplida para env\u00edo ConfigView.section.transfer.autospeed.enabledebug=Registrar informaci\u00f3n de depuraci\u00f3n TableColumn.header.date_added=A\u00f1adido el d\u00eda TableColumn.header.date_added.info=Fecha en que se a\u00f1adi\u00f3 el torrent ConfigView.section.file.hashchecking.smallestfirst=Recomprobar primero las descargas m\u00e1s peque\u00f1as platform.win32.baddll.info=Vuze ha detectado la presencia de '%1'. Este es parte de '%2' y se sabe que provoca problemas graves tales como ca\u00edda de la aplicaci\u00f3n y uso elevado de la CPU. Si se encuentra con estos s\u00edntomas desinstale el programa o config\u00farelo para que no afecte a Azureus. platform.win32.baddll.niphk=Norman Anti-Virus platform.win32.baddll.nvappfilter=NVidia Firewall platform.win32.baddll.MxAVLsp=VCom Fix-It Utilities platform.win32.baddll.mclsp=McAfee Privacy Service platform.win32.baddll.radhslib=Naomi Internet Filter (Radiant) platform.win32.baddll.nl_lsp=NetLimiter upnp.ignorebaddevices=Ignorar los dispositivos que dejan de responder correctamente upnp.ignorebaddevices.info=Dispositivos actualmente ignorados: %1 upnp.ignorebaddevices.reset=Limpia la lista de dispositivos ignorados upnp.ignorebaddevices.reset.action=Reiniciar upnp.ignorebaddevices.alert=Se est\u00e1 ignorando al dispositivo UPnP situado en %1 debido a repetidos fallos. Busque en la configuraci\u00f3n del complemento UPnP las opciones respecto a esta acci\u00f3n. TorrentOptionsView.param.max.uploads.when.busy=Vel. m\u00e1x de subida en KB/s cuando se alcance su l\u00edmite global [0: desactivado] UpdateMonitor.messagebox.verification.failed.title=Ha fracasado la verificaci\u00f3n de la instalaci\u00f3n UpdateMonitor.messagebox.verification.failed.text=Ha fracasado la verificaci\u00f3n de '%1': %2 UpdateMonitor.messagebox.accept.unverified.title=Aceptar instalaci\u00f3n No verificada UpdateMonitor.messagebox.accept.unverified.text=No se pudo verificar que '%1' sea un complemento oficial de Azureus.\nSi \u00e9ste no lo es, NO deber\u00edas continuar.\n\u00bfSeguir con la instalaci\u00f3n? FileView.BlockView.title=Partes del Archivo FileView.BlockView.Done=Terminado FileView.BlockView.Skipped=Ignorado FileView.BlockView.Active=Activo FileView.BlockView.Outstanding=Pendiente ConfigView.label.tcplistenport=Puerto de escucha para entrada TCP ConfigView.label.udplistenport=Puerto de escucha para entrada UDP upnp.portchange.alert=Los siguientes puertos han cambiado para evitar problemas con dispositivos UPnP: %1 [puerto anterior=%2] %3 [puerto anterior=%4] ConfigView.section.proxy.username.info=Si el servidor proxy pidiera autenticaci\u00f3n incluso cuando no se ha definido ninguna, utilice la cadena "" como usuario(s) ConfigView.label.maxuploadswhenbusymin=Veloc. m\u00e1x de env\u00edo cuando temporizaci\u00f3n de ocupado [seg] MainWindow.menu.help.debug=Generar Info de Depuraci\u00f3n (Crash Log) DownloadManager.error.badsize=Tama\u00f1o Incorrecto natpmp.info=NAT-PMP es la alternativa de Apple al UPnP y es soportada por las recientes estaciones Airport\n\nAdvierta que actualmente el UPnP ha de estar activado para poder activar el NAT-PMP, ya que el dispositivo NAT-PMP es tratado como un tipo especial de dispositivo UPnP natpmp.enable=Activar (para que funcione tambi\u00e9n ha de estar activado en la configuraci\u00f3n del Airport) ConfigView.section.tracker.host.addurls=Asegurarse de que las URLs de este rastreador est\u00e1n presentes en los torrents hospedados ConfigView.filter=buscar aqu\u00ed ConfigView.section.files.move=Traslado al Completar ConfigView.section.file.defaultdir.section=Opciones de la Carpeta por defecto ConfigView.section.file.defaultdir.auto=Descargar autom\u00e1ticamente en la carpeta por defecto (No pregunta) ConfigView.section.file.defaultdir.bestguess=Adivinar cu\u00e1l es la mejor carpeta por defecto donde guardar ConfigView.section.file.defaultdir.ask=Carpeta por defecto: ConfigView.section.file.defaultdir.lastused=Poner como carpeta por defecto a la \u00faltima que se us\u00f3 para guardar ConfigView.section.file.config.section=Preferencias de la Configuraci\u00f3n ConfigView.section.file.config.currentdir=Carpeta de configuraci\u00f3n actual ConfigView.section.torrent.decoding=Decodificando Juegos de Caracteres ConfigView.section.logging.udptransport=Activar traza (detallada) del transporte UDP Tracker.announce.ignorePeerSeed=Ignorando relaci\u00f3n Clientes/Semillas. %1 ConfigView.section.connection.encryption.use_crypto_port=Usar la extensi\u00f3n 'cryptoport' del rastreador para impedir los intentos de conexi\u00f3n entrante 'a pelo'.\n Algunos rastreadores no lo aceptan y dan fallo con errores como "Puerto inv\u00e1lido" o "Argumentos Ilegales" TorrentOptionsView.param.reset.to.default=Volver a dejar las opciones en sus valores por defecto TorrentOptionsView.param.reset.button=Reiniciar natpmp.routeraddress=Direcci\u00f3n de la estaci\u00f3n [en blanco: auto] ConfigView.section.style.disableAlertSliding=Desactivar el estilo/la animaci\u00f3n que se desplaza en 1er. plano para los mensajes de alerta ConfigView.section.transfer.autospeed.maxinc=aumento m\u00e1ximo por ciclo (en %1) ConfigView.section.transfer.autospeed.maxdec=disminuci\u00f3n m\u00e1xima por ciclo (en %1) ConfigView.section.transfer.autospeed.enabledownadj=Activar el ajuste de la velocidad de descarga ConfigView.section.transfer.autospeed.downadjratio=Raz\u00f3n entre las velocidades de Descarga:Subida (p. ej. 2.0 -> la velocidad l\u00edmite de descarga es el doble que la de env\u00edo) ConfigView.section.transfer.autospeed.latencyfactor=Factor utilizado para relacionar los cambios de latencia con los de velocidad (n\u00fameros mayores disminuyen la sensibilidad) ConfigView.section.transfer.autospeed.reset=Reiniciar los valores avanzados ConfigView.section.transfer.autospeed.reset.button=Reiniciar PeerColumn.activationCount=Clientes intentando conectarse: %1 TableColumn.header.timesincedownload.info=Tiempo transcurrido desde que se descargaron datos para el torrent TableColumn.header.timesincedownload=Latencia en Descarga TableColumn.header.timesinceupload.info=Tiempo transcurrido desde que se enviaron datos del torrent TableColumn.header.timesinceupload=Latencia en Envio PeersView.incomingreqcount=Pet. Ent. PeersView.incomingreqcount.info=El n\u00ba de peticiones de entrada realizadas por el cliente PeersView.outgoingreqcount=Pet. Sal. PeersView.outgoingreqcount.info=El n\u00ba de peticiones de salida realizadas al cliente upnp.mapping.trackerclientudp=Puerto de Cliente del rastreador (UDP) upnp.mapping.dhtudp=Base de Datos Distribu\u00edda ConfigView.section.connection.nondata.udp.same=Utiliza el mismo puerto UDP para la Base de Datos Distribu\u00edda y el Rastreador UDP ConfigView.section.connection.tcp.enable=Permitir TCP ConfigView.section.connection.udp.enable=Permitir UDP ConfigView.section.style.showiconbar=Mostrar Barra de Herramientas MainWindow.menu.view.iconbar=Barra de Herramientas MyTorrentsView.menu.rename=Renombrar MyTorrentsView.menu.rename.displayed=Renombrar el Nombre mostrado MyTorrentsView.menu.rename.save_path=Renombrar la Ruta donde Guardar MyTorrentsView.menu.rename.displayed.enter.title=Renombrar el Nombre mostrado MyTorrentsView.menu.rename.displayed.enter.message=Escriba el nuevo nombre a mostrar para esta descarga.\nSi no escribe nada, se usar\u00e1 el nombre original. MyTorrentsView.menu.edit_comment=Editar Comentario MyTorrentsView.menu.edit_comment.enter.title=Editar Comentario MyTorrentsView.menu.edit_comment.enter.message=Introduzca un comentario para esta descarga UIDebugGenerator.messageask.title=Generador para Depuraci\u00f3n UIDebugGenerator.messageask.text=Por favor, escriba una descripci\u00f3n del error sobre el que quiere informar UIDebugGenerator.complete.title=Completada la Generaci\u00f3n para Depuraci\u00f3n UIDebugGenerator.complete.text=Por favor, env\u00ede el archivo '%1'.\n\nClic en Ok para abrir una ventana a este archivo. ConfigView.section.style.showProgramIcon=Mostrar el icono del programa en la columna nombre ConfigView.section.style.showProgramIcon.tooltip=Para actualizarse a los cambios puede que tenga que reabrir la vista swt.alert.cant.update=La librer\u00eda SWT cargada desde "%3" no puede actualizarse desde la versi\u00f3n %1 a la %2 (debe cargarse desde "%4"). Obtendr\u00e1 mas destalles en el wiki. authenticator.savepassword=Recordar mi contrase\u00f1a ConfigView.section.security.clearpasswords=Reiniciar contrase\u00f1as recordadas ConfigView.section.security.clearpasswords.button=Reiniciar Content.alert.notuploaded.title=Subida Incompleta Content.alert.notuploaded.text=No se ha terminado de subir '%1'. Si ahora %2, nadie terminar\u00e1 de descargar lo que intentas publicar.\n\n\u00bfSeguro que quieres %2? Content.alert.notuploaded.multi.title=Subidas Incompletas Content.alert.notuploaded.multi.text=El %1 del contenido que intentas publicar, no lo has compartido completamente. Si ahora %2, nadie terminar\u00e1 de descargar tu trabajo. \u00bfSeguro que quieres %2?\n\nContenido parcialmente compartido:\n%3 Content.alert.notuploaded.stop=detienes Content.alert.notuploaded.quit=cierras Vuze TorrentInfoView.torrent.encoding=Codificaci\u00f3n del Torrent TorrentInfoView.columns=Columnas desde la vista 'Mis Torrents' progress.window.title=Operaci\u00f3n en marcha progress.window.msg.filemove=Por favor, espera mientras se termina de mover/renombrar el archivo ConfigView.label.popup.timestamp=Estampar la hora a las alertas emergentes ConfigView.label.popup.autohide=Auto-ocultar las alertas (no de error) emergentes pasados x segundos (0 = desactivado) ConfigView.label.popup.suppress_alerts=Suprimir alertas ConfigView.label.popup.use_message_boxes=Utilizar cajas emergentes para mensajes en puesto de la caja est\u00e1ndar emergente para alerta. ConfigView.label.popup.show=Mostrar todas las alertas emergentes registradas hasta ahora (si existen) ConfigView.label.popup.show.button=Mostrar ConfigView.label.please.visit.here=Aqu\u00ed podr\u00e1 ampliar detalles ConfigView.section.ipfilter.enable.descriptionCache=Almacenar las descripciones IP en un archivo de trabajo ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Las descripciones no se recordar\u00e1n si est\u00e1 desactivado OpenTorrentWindow.filesInfo=se descargar\u00e1n %1 de %2. OpenTorrentWindow.diskUsage=%1 de %2 ConfigView.label.openmytorrents=Abrir 'Mis Torrents' durante el inicio ConfigView.label.open_transfer_bar_on_start=Abrir la Barra de Transferencias durante el inicio ConfigView.section.style.DNDalwaysInIncomplete=Mostrar siempre los torrents con archivos marcados como 'No descargar' en la secci\u00f3n Incompletos de Mis Torrents OpenTorrentWindow.mb.noGlobalDestDir.title=Carpeta de Destino OpenTorrentWindow.mb.noGlobalDestDir.text=La carpeta de destino '%1' no es v\u00e1lida. OpenTorrentWindow.mb.noDestDir.title=No se ha encontrado la carpeta de destino OpenTorrentWindow.mb.noDestDir.text=La carpeta de destino '%1' del torrent '%2' no existe o no es v\u00e1lida. OpenTorrentWindow.mb.notValid.title=Abrir Torrent OpenTorrentWindow.mb.notValid.text=No se pudo abrir el torrent '%1'. Si est\u00e1 abri\u00e9ndolo en modo compartir, antes aseg\u00farese de que ya existen los archivos de datos del torrent. OpenTorrentWindow.mb.notTorrent.title=Abrir Torrent OpenTorrentWindow.mb.notTorrent.text=No pude abrir '%1'. Parece que no es un archivo .torrent.\n\nParte de los datos recibidos:\n%2 ConfigView.label.pause.downloads.on.exit=Pausar las descargas antes de salir ConfigView.label.resume.downloads.on.start=Reanudar las descargas pausadas al terminar de iniciar el programa UIDebugGenerator.message.cancel.title=Cancelada la generaci\u00f3n de Info para depurar UIDebugGenerator.message.cancel.text=No introdujo ninguna descripci\u00f3n sobre el error del que intenta informar. A usted puede parecerle obvio el error que ha sufrido, pero sin una descripci\u00f3n, s\u00f3lo podremos conjeturar cu\u00e1l es su problema.\n\nSe ha cancelado la Generaci\u00f3n de la Info para Depuraci\u00f3n. ConfigView.section.connection.group.http.info=Soporte para HTTP seeding. ConfigView.section.connection.http.enable=Activar ConfigView.section.connection.http.port=n\u00ba de puerto para Entrada ConfigView.section.connection.http.portoverride=Invalidaci\u00f3n del Puerto HTTP del rastreador [0: ninguno] window.update.noupdates.title=Resultados de la b\u00fasqueda de actualizaciones window.update.noupdates.text=No hay actualizaciones para usted.\n\n\u00a1Felicidades! ConfigView.label.bindip.details=Ejemplo: 192.168.1.5;eth0;eth1[2] ligar\u00e1 la IP especificada, a todas las del 1er. interfaz y a la 3\u00aa IP del 2\u00ba interfaz.\nLa 1\u00aa IP se usar\u00e1 para todos los servicios, todas las dem\u00e1s solo se usan para equilibrar la carga.\nEst\u00e1n disponibles los siguientes interfaces:\n%1 ConfigView.label.mindownloads=N\u00ba m\u00edn. de descargas simult\u00e1neas UI.cannot_submit_blank_text=Tienes que introducir un valor. crypto.alert.as.warning=Se sabe que la red '%1' controla el tr\u00e1fico de red para reducir el rendimiento de las descargas. Se ha activado autom\u00e1ticamente el encriptado del transporte (de datos) - esto se puede desactivar/modificar via par\u00e1metros de configuraci\u00f3n. ConfigView.section.interface.alerts=Alertas ConfigView.label.popupdownloadadded=Al a\u00f1adir una descarga, anunciarlo mediante una ventana emergente popup.download.added=Se ha a\u00f1adido "%1" a su lista de descargas. MessageBoxWindow.nomoreprompting=No volver a avisarme TorrentOptionsView.param.max.seeds=N\u00ba m\u00e1x. de conexiones a semillas [0: l\u00edmite de la conexi\u00f3n] TorrentOptionsView.param.alternative.value.enable=Alternar el valor al compartir ConfigView.section.proxy.check.on.start=Comprobar el estado del proxy durante el arranque TransferStatsView.legend.pingaverage=Media TransferStatsView.legend.ping1=Objetivo 1 TransferStatsView.legend.ping2=Objetivo 2 TransferStatsView.legend.ping3=Objetivo 3 ConfigView.section.interface.enabletray._mac=Activar icono en la Barra de Estado [necesitar\u00e1 reiniciar] ConfigView.label.closetotray._mac=Cerrar minimiza como icono en la Barra de Estado ConfigView.label.minimizetotray._mac=Minimizar minimiza como icono en la Barra de Estado OpenTorrentWindow.mb.existingFiles.title=\u00a1El/los archivo(s) ya existe(n)! OpenTorrentWindow.mb.existingFiles.text=Algunos de los arhivos ya existen en la(s) carpeta(s) destino que ha especificado:\n\n%1\nSi sigue, Vuze rebuscar\u00e1 datos correctos en el/los archivo(s) de m\u00e1s abajo y los sobrescribir\u00e1 si fuera necesario. splash.unloadingTorrents=Retirando Torrents splash.unloadingTorrent=Retirando Torrent ConfigView.section.file.defaultdir.autorename=Auto renombrar los datos del torrent si hay archivos en la misma ruta que parecen iguales ConfigView.section.file.defaultdir.autorename.tooltip=Esto impide que un torrent sobrescriba los archivos de otro cuando los nombres de archivo son iguales. alert.raised.at.close=(Mensaje procedente de un cierre anterior de Vuze) Plugin.trackerpeerauth.name=Autorizaci\u00f3n como par perteneciente al Rastreador Plugin.trackerpeerauth.info=Este complemento funciona con rastreadores que verifican si los pares son miembros v\u00e1lidos del enjambre Peers.column.maxupspeed=Veloc Max Sub Peers.column.maxdownspeed=Veloc Max Desc MyTorrents.items.DownSpeedLimit.disabled=No descargar upnp.selectedaddresses=Direcciones (';' separador, '-' prefijo=denegar, '+' =permitir) [en blanco: cualquiera] upnp.alert.multipledevice.warning=Se han detectado m\u00faltiples dispositivos UPnP - compruebe si necesitan mapearles los puertos (vea registro y configuraci\u00f3n de UPnP) UpdateMonitor.messagebox.restart.title=Actualizaci\u00f3n de Software UpdateMonitor.messagebox.restart.text=Vuze acaba de descargar una actualizaci\u00f3n importante y ahora tiene que reiniciarse para poder instalarla. PiecesView.BlockView.Have=Tengo PiecesView.BlockView.NoHave=No tengo PiecesView.BlockView.Header=%1 columna(s), %2 fila(s), %3 partes ConfigView.section.update.autodownload=Descargar autom\u00e1ticamente las actualizaciones y avisar cuando la instalaci\u00f3n ya est\u00e9 preparada Peers.column.peer_id.info=Peer ID en formato legible Peers.column.peer_byte_id.info=Peer ID en formato octeto Peers.column.handshake_reserved=Bytes Reservados para el Handshake Peers.column.handshake_reserved.info=Indica cu\u00e1les de los bits reservados fueron activados en el protocolo handshake del BT Peers.column.client_identification=Identificaci\u00f3n del Cliente Peers.column.client_identification.info=Indica los nombres tal y como los recibi\u00f3 Vuze - \u00fautil para poder depurar dht.warn.user=Avisar de problemas potenciales con el NAT/mapeado de puertos ConfigView.label.openbar.incomplete=Barras de descarga: auto-abrir descargas ConfigView.label.openbar.complete=auto-abrir comparticiones ConfigView.label.transferbar.remember_location=Recordar la \u00faltima posici\u00f3n de la barra de transferencias ConfigView.section.transfer.autospeed.forcemin=%1 de la velocidad de subida forzada al auditar la conexi\u00f3n MainWindow.menu.tools.speedtest=Prueba de Velocidad... speedtest.wizard.title=Prueba de Velocidad speedtest.wizard.run=Realizar una prueba de velocidad speedtest.wizard.test.mode.updown=subida y descarga speedtest.wizard.test.mode.up=subida speedtest.wizard.test.mode.down=descarga SpeedTestWizard.test.panel.currinfo=Comprobaci\u00f3n del ancho de banda BitTorrent. SpeedTestWizard.test.panel.label=Velocidad de prueba de Vuze SpeedTestWizard.test.panel.already.running=Prueba en marcha! SpeedTestWizard.test.panel.not.accepted=Petici\u00f3n de prueba denegada: SpeedTestWizard.test.panel.abort=Abortar SpeedTestWizard.test.panel.abort.countdown=abortar prueba en: SpeedTestWizard.test.panel.test.countdown=la prueba termina en: SpeedTestWizard.test.panel.testfailed=Prueba fallida SpeedTestWizard.test.panel.aborted=Prueba abortada manualmente. SpeedTestWizard.test.panel.enc.label=Pulse para probar con encriptado: SpeedTestWizard.test.panel.standard=Est\u00e1ndar SpeedTestWizard.test.panel.encrypted=encriptado SpeedTestWizard.set.upload.button.apply=Aplicar SpeedTestWizard.set.upload.result=Resultado de la \u00faltima prueba SpeedTestWizard.set.upload.bytes.per.sec=kBytes/seg SpeedTestWizard.set.upload.bits.per.sec=bits/seg SpeedTestWizard.finish.panel.title=Prueba de Velocidad Terminada! SpeedTestWizard.finish.panel.click.close=Ha finalizado el asistente para prueba de velocidad. Clic en cerrar para salir. SpeedTestWizard.finish.panel.max.upload=Subida M\u00e1x : SpeedTestWizard.finish.panel.max.seeding.upload=M\u00e1x subida al sembrar : SpeedTestWizard.finish.panel.max.download=Descarga M\u00e1x : SpeedTestWizard.finish.panel.enabled=activado SpeedTestWizard.finish.panel.disabled=desactivado SpeedTestWizard.abort.message.scheduled.in=prueba planificada para dentro de ... %1 segundos" SpeedTestWizard.abort.message.unsupported.type=\u00a1\u00a1\u00a1\u00a1Tipo de prueba no soportada!!!! SpeedTestWizard.abort.message.manual.abort=Abortada Manualmente SpeedTestWizard.abort.message.scheduling.failed=Fall\u00f3 la planificaci\u00f3n de la prueba SpeedTestWizard.abort.message.download.added=Descarga %1 a\u00f1adida durante la prueba SpeedTestWizard.abort.message.entered.error=La prueba de descarga entr\u00f3 en el estado de error '%1' SpeedTestWizard.abort.message.entered.queued=Prueba descargado entr\u00f3 en un estado en cola/detenido SpeedTestWizard.abort.message.interrupted=Se interrumpi\u00f3 TorrentSpeedTestMonitorThread antes de terminar la prueba SpeedTestWizard.abort.message.execution.failed=Fallo al ejecutar la prueba SpeedTestWizard.abort.message.failed.peers=Fallo al conectar a cualquier par SpeedTestWizard.abort.message.insufficient.slots=No se pudo enviar a ninguno de los pares - insuficientes puestos de subida? SpeedTestWizard.abort.message.not.unchoked=No se pudo descargar de ninguno de los pares ya que nunca fuimos unchoked por ellos SpeedTestWizard.stage.message.requesting=pidiendo prueba... SpeedTestWizard.stage.message.preparing=preparando prueba... SpeedTestWizard.stage.message.starting=iniciando prueba... SpeedTestWizard.stage.message.connect.stats=Estadisticas de la Conexi\u00f3n: pares=%1, down_ok=%2, up_ok=%3 window.uiswitcher.title=Selector del GUI de Vuze window.uiswitcher.text=Seleccione por favor de m\u00e1s abajo el interfaz de usuario que mejor satisfaga sus necesidades. window.uiswitcher.NewUI.text=* Recomendado para principiantes y nuevos usuarios.\n\n* F\u00e1cil, interfaz grafico e intuitivo\n\n* Interfaz necesario para poder publicar sobre la plataforma Vuze window.uiswitcher.ClassicUI.title=Interfaz Cl\u00e1sico window.uiswitcher.ClassicUI.text=* Mantiene la funcionalidad de los clientes de las series 2.x\n\n* No se cargar\u00e1 la capa de contenido Vuze window.uiswitcher.bottom.text=Cuando quiera, podr\u00e1 cambiar f\u00e1cilmente de GUI con el bot\u00f3n Selector del GUI de Vuze iconBar.switch.tooltip=Selector del GUI de Vuze VivaldiView.notAvailable=Vista Vivaldi no disponible restart.error=Fallo el reinicio:\n%1\nVea situaciones de reinicio. restart.error.oom=Sin Memoria restart.error.fnf='%1' no hallado en '%2' restart.error.pnf=Path '%1' no hallado restart.error.bad=Mal formato de archivo para '%1' restart.error.denied=Se deneg\u00f3 el acceso al intentar ejecutar '%1'. Aseg\u00farese de que tiene los derechos necesarios para poder ejecutar este programa. TableColumn.header.date_completed=Completado el d\u00eda TableColumn.menu.date_added.reset=Reiniciar Fecha ConfigView.section.ipfilter.discardbanning=Bloquear los pares cuya proporci\u00f3n de datos descartados/buenos excede [0: desactivado] ConfigView.section.ipfilter.discardminkb=M\u00ednimo %1 descartado antes de aplicarle la proporci\u00f3n ConfigView.interface.start.advanced=Empezar con la Vista Avanzada (AZ 2.x) MyTorrents.column.ColumnQuality=Calidad MyTorrents.column.ColumnSpeed=Velocidad MyTorrents.column.ColumnProgressETA.2ndLine=TEF: %1 MyTorrents.column.ColumnProgressETA.StreamReady=Streaming Listo MyTorrents.column.ColumnProgressETA.PlayableIn=Reproducible en %1 TableColumn.header.Quality=Calidad TableColumn.header.Speed=Velocidad TableColumn.header.RateIt=Valor TableColumn.header.Rating=Valoraci\u00f3n TableColumn.header.SpeedGraphic=Velocidad TableColumn.header.AzProduct=Desde TableColumn.header.MediaThumb=Medio TableColumn.header.ProgressETA=Progreso #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=Tipo de Archvo: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=Inicio v3.MainWindow.tab.browse=En Vuze v3.MainWindow.tab.library=Biblioteca v3.MainWindow.tab.publish=Publicar v3.MainWindow.tab.advanced=Avanzado v3.MainWindow.menu.home=&Inicio v3.MainWindow.menu.browse=&Examinar Contenido v3.MainWindow.menu.library=&Biblioteca v3.MainWindow.menu.publish=&Publicar v3.MainWindow.menu.advanced=&Avanzado v3.MainWindow.menu.view.searchbar=Barra de B\u00fasqueda v3.MainWindow.menu.view.tabbar=Barra de Pesta\u00f1as v3.MainWindow.currentDL=Descargando Ahora v3.MainWindow.button.stop=Detener v3.MainWindow.button.start=Empezar v3.MainWindow.button.pause=Pausa v3.MainWindow.button.resume=Seguir v3.MainWindow.button.delete=Eliminar v3.MainWindow.button.comment=Comentario v3.MainWindow.button.viewdetails=Ver Detalles v3.MainWindow.button.play=Reproducir v3.MainWindow.button.cancel=Cancelar v3.MainWindow.button.preview=Vista previa v3.MainWindow.view.wait=Inicializando la vista, espere por favor. v3.MainWindow.xofx=%1 de %2 v3.MainWindow.Loading=Cargando.. Espere por favor v3.filter-bar=Filtro de Titulo: v3.MainWindow.search.defaultText=Buscar en sitios torrent v3.mb.delPublished.title=Dejar de Compartir Contenido v3.mb.delPublished.text=CUIDADO: Esta acci\u00f3n NO eliminar\u00e1 su contenido publicado '%1' desde %3 .\u005cn\nClic "Eliminar" solo si quieres que tu contenido siga publicado y descargable, pero quieres liberar tu ancho de banda. Aseg\u00farate de que el proceso de env\u00edo se ha completaqdo antes de hacerlo (how?).\u005cn\nClic "Cancelar" si quieres eliminar completamente tu contenido publicado desde %3, y usa el boton (X) del panel Contenido Publicado de la pesta\u00f1a Publicar.\u005cn\nMore help.\u005cn\n v3.mb.delPublished.delete=&Eliminar v3.mb.delPublished.cancel=&Cancelar v3.mb.openFile.text.known=Este contenido no est\u00e1 soportado a\u00fan por el Reproductor Vuze. Busque ayuda en la Gu\u00eda de Reproducci\u00f3n creada por la comunidad.\n\nEl archivo parece ser: %2 (%3)\n v3.mb.openFile.text.unknown=Este contenido no est\u00e1 soportado a\u00fan por el Reproductor Vuze. Busque ayuda en la Gu\u00eda de Reproducci\u00f3n creada por la comunidad.\n\nExtensi\u00f3n del archivo : %2\n v3.mb.openFile.button.play=Reproducr v3.mb.openFile.button.cancel=Cancelar v3.mb.openFile.button.guide=Leer Gu\u00eda de Reproducci\u00f3n v3.mb.openFile.remember=Abrir siempre los archivos sin preguntarme v3.mb.PlayFileNotFound.title=Archivo No Encontrado v3.mb.PlayFileNotFound.text=Los archivos de '%1' est\u00e1n borrados o perdidos. v3.mb.PlayFileNotFound.button.remove=Eliminar de Vuze v3.mb.PlayFileNotFound.button.redownload=Volver a descargar Datos v3.mb.PlayFileNotFound.button.find=Buscar Manualmente.. v3.mb.deletePurchased.title=Eliminar Contenido Comprado v3.mb.deletePurchased.text=Seguro que quieres eliminar el contenido '%1'?\u005cn\nEs uno que compraste, o que se te exigi\u00f3 identificarte para poder descargarlo. v3.mb.deletePurchased.button.delete=&Eliminar v3.mb.deletePurchased.button.cancel=&Cancelar v3.topbar.menu.show.plugin=\u00c1rea de Complementos v3.topbar.menu.show.search=Buscar splash.initializeCore=Inicializando N\u00facleo splash.initializeUIElements=Inicializando Elementos del GUI ConfigView.section.transfer.autospeedbeta=Auto-Velocidad-Beta # ConfigView.section.ipfilter.peerblocking.group=Bloqueo de Pares ConfigView.section.ipfilter.autoload.group=Auto Cargando ConfigView.section.ipfilter.autoload.file=Archivo de filtros IP a autocargar ConfigView.section.ipfilter.autoload.info=Soporta los formatos DAT (eMule), P2P (PeerGuardian, splist), y P2B v1,2,3 (PeerGuardian 2). El archivo puede ser local o una URL, en zip, en gzip o de solo texto. Las URLs se volver\u00e1n a descargar autom\u00e1ticamente tras 7 dias, mientras que los archivos se recargar\u00e1n al minuto de ser cambiadas/tocadas. ConfigView.section.ipfilter.autoload.loadnow=Cargar Ahora splash.loadIpFilters=Cargando Filtros de IP.. SpeedTestWizard.set.upload.title=Establecer los L\u00edmites de Envio y Descarga SpeedTestWizard.set.download.label=Velocidad L\u00edmite Descarga: SpeedTestWizard.set.upload.label=Velocidad L\u00edmite Env\u00edo: SpeedTestWizard.name.conf.level.absolute=Absoluta SpeedTestWizard.name.conf.level.high=Alta SpeedTestWizard.name.conf.level.med=Media SpeedTestWizard.name.conf.level.low=Baja SpeedTestWizard.name.conf.level.none=Ninguna ConfigView.section.transfer.select=Auto-Velocidad ConfigView.section.transfer.select.v2=Auto-Velocidad (beta) mb.azmustclose.title=Error de Arranque mb.azmustclose.text=Vuze tiene que cerrar por un problema (re)iniciando Vuze que seguramente le obligo a funcionar con privilegios de Administrador.\n\nDespues de que Vuze cierre, \u00e1bralo por favor manualmente. network.ipv6.prefer.addresses=Decantarse por direcciones IPv6 cuando ambas est\u00e9n disponibles (IPv6 e IPv4). network.bindError=No se pudo vincular al socket del servidor al no haber disponibles direcciones compatibles, compruebe por favor sus preferencias para vincularse-a-IP network.enforce.ipbinding=Forzar v\u00ednculos con la IP incluso en caso de que los interfaces (de red) no est\u00e1n disponibles, impide cualquier conexi\u00f3n si ninguno de ellos lo est\u00e1. DHTView.title.full_v6=Base de Datos Distribu\u00edda IPv6 ConfigView.pluginlist.loadSelected=Carga Seleccionada SpeedView.stats.asn=Red: SpeedView.stats.estupcap=L\u00edmite de Env\u00edo: SpeedView.stats.estdowncap=L\u00edmite de Descarga: SpeedView.stats.unknown=Desconocido SpeedView.stats.estimate=Estimado SpeedView.stats.measured=Medido SpeedView.stats.measuredmin=Min Medido SpeedView.stats.manual=Fijo ConfigView.section.transfer.autospeed.networks=Detalles de la Red ConfigView.section.transfer.autospeed.resetnetwork=Reiniciar detalles de red ConfigView.section.transfer.autospeed.network.info=Los l\u00edmites de arriba se auto-calculan durante la descarga o como resultado de una prueba de velocidad. Si los quieres establecer a mano, utiliza las opciones de m\u00e1s abajo.\nTodos aquellos l\u00edmites que no sean 'fijo' se auto-ajustar\u00e1n si fuera necesario.\nIntroduce el valor y selecciona su tipo. Las velocidades est\u00e1n expresadas en %1. dialog.uiswitcher.restart.title=Conmutador del GUI: Precisa Reiniciar Vuze dialog.uiswitcher.restart.text=Vuze necesita reiniciarse para pasar al nuevo modo de GUI. TrayWindow.menu.close=Cerrar Cesta de Descarga # Used for peers which we can't determine. PeerSocket.unknown=Desconocido PeerSocket.fake_client=ENGA\u00d1O PeerSocket.bad_peer_id=mala ID de par PeerSocket.mismatch_id=desacuerdo PeerSocket.unknown_az_style=Desconocido %1/%2 PeerSocket.unknown_shadow_style=Desconocido %1/%2 OpenTorrentWindow.mb.askCreateDir.title=No existe la Carpeta de Destino OpenTorrentWindow.mb.askCreateDir.text=La carpeta de destino '%1' no existe.\n\n\u00bfCrearla ahora? SpeedView.stats.estimatechoke=Estimado (choke) ConfigTransferAutoSpeed.upload.capacity.usage=Uso de la Capacidad de Env\u00edo ConfigTransferAutoSpeed.mode=Modo: ConfigTransferAutoSpeed.capacity.used=% Capacidad Usada ConfigTransferAutoSpeed.while.downloading=Descargando: ConfigTransferAutoSpeed.set.dht.ping=Valor de Ping DHT: ConfigTransferAutoSpeed.set.point=establecer punto (ms) ConfigTransferAutoSpeed.set.tolerance=tolerancia (ms) ConfigTransferAutoSpeed.ping.time.good=Bueno: ConfigTransferAutoSpeed.ping.time.bad=Malo: ConfigTransferAutoSpeed.adjustment.interval=Intervalo de Ajuste: ConfigTransferAutoSpeed.skip.after.adjust=Saltar tras el ajuste: GeneralView.label.distributedCopies=Copias Distribu\u00eddas: PiecesView.DistributionView.title=Distribuci\u00f3n de las Partes PiecesView.DistributionView.NoAvl=Partes no disponibles PiecesView.DistributionView.SeedAvl=Avl Contribuci\u00f3n Semil PiecesView.DistributionView.PeerAvl=Avl Contribuci\u00f3n Pares PiecesView.DistributionView.RarestAvl=Partes mas raras: %1 (Avl:%2) PiecesView.DistributionView.weHave=Partes que tienes PiecesView.DistributionView.theyHave=Partes que el par ten\u00eda PiecesView.DistributionView.weDownload=Partes que estas descargando PeersView.gain=Ganancia PeersView.gain.info=Montante de datos descargados - enviados unix.script.new.title=Disponible un Nuevo Script de Arranque para Vuze unix.script.new.text=Hay un nuevo script de arranque para Vuze y se ha guardado en '%1'.\n\nEs altamente recomendable que salgas ahora de Vuzey pases a este script ('%2').\u005cn\nSi has modificado mucho su script de arranque para Vuze mira por favor AzureusWiki: Script Unix.\u005cn\nSi instalaste Vuze desde una distro (yum, apt-get, etc), es recomendable que reinstales Vuze mediante el paquete de Vuze Sourceforge Page (Mantendr\u00e1s el mismo GUI que tienes ahora) unix.script.new.button.quit=Salir Ahora unix.script.new.button.continue=Lo har\u00e9 despues unix.script.new.button.asknomore=No me lo repitas unix.script.new.auto.title=Nuevo Script de Arranque para Vuze unix.script.new.auto.text=Hay disponible un nuevo Script de Arranque para Azureus.\n\nEs altamente recomendable que reinicies Vuze ahora. Content.alert.notuploaded.button.stop=&Detener Content.alert.notuploaded.button.continue=&Seguir Compartiendo Content.alert.notuploaded.button.abort=&No Salir ConfigView.label.checkOnSeeding=Hacer una recomprobaci\u00f3n de partes a baja prioridad mientras se comparte ConfigView.label.ui_switcher=Mostrar Selector del GUI de Vuze ConfigView.label.ui_switcher_button=Mostrar SpeedTestWizard.test.panel.explain=Mide tu velocidad con el protocolo de Azureus. Selecciona el tipo de prueba de velocidad el modo de encriptado. Visita la p\u00e1gina del wiki Vuze para ampliar detalles sobre esta prueba. La prueba se detendr\u00e1 autom\u00e1ticamente si le lleva mas de dos minutos. Las pruebas normalmente terminan en menos de un minuto. SpeedTestWizard.set.upload.hint=Establece los l\u00edmites de env\u00edo y descarga que utiliza el algoritmo de AutoVelocidad Azureus. SpeedTestWizard.set.upload.panel.explain=El algoritmo de AutoVelocidad de Vuze usar\u00e1 los l\u00edmites puestos aqu\u00ed. Pon los l\u00edmites de transferencia y los de confianza.\n\nTen en cuenta que las velocidades de l\u00ednea se citan a menudo en "bits por segundo" - pero el valor de mas abajo se muestra en "kilobytes por segundo". SpeedTestWizard.set.limit.conf.level=Confianza SpeedTestWizard.finish.panel.auto.speed=La AutoVelocidad es : SpeedTestWizard.finish.panel.auto.speed.seeding=AutoVelocidad al compartir es : ConfigTransferAutoSpeed.add.comment.to.log.group=A\u00f1adir comentario al registro de depuraci\u00f3n ConfigTransferAutoSpeed.add.comment.to.log=A\u00f1adir comentario: ConfigTransferAutoSpeed.log.button=Registro ConfigTransferAutoSpeed.algorithm.selector=Selector de Auto-Velocidad ConfigTransferAutoSpeed.algorithm=Algoritmo: ConfigTransferAutoSpeed.auto.speed.classic=Auto-Velocidad (cl\u00e1sico) ConfigTransferAutoSpeed.auto.speed.beta=Auto-Velocidad (beta) ConfigTransferAutoSpeed.data.update.frequency=Frecuencia de Actualizaci\u00f3n Alert.failed.update=Ha fallado la instalaci\u00f3n de al menos un componente. Vea AzureusWiki: Actualizaci\u00f3n Fallida [%1] OpenTorrentWindow.mb.existingFiles.partialList=(Lista Parcial. Ya existen mas archivos) TableColumn.header.bad_avail_time.info=\u00daltima vez que estuvo disponible una copia completa de la descarga TableColumn.header.bad_avail_time=Copia Completa Vista MyTorrentsView.menu.exporthttpseeds=Exportar URLs HTTP de la semilla al portapapeles SWT.alert.erroringuithread=Ocurri\u00f3 en el GUI un error no gestionado, se le informar\u00e1 de los posibles fallos posteriores ConfigView.label.minannounce=Tiempo m\u00ednimo entre dos anuncios del rastreador (en segundos) ConfigView.label.maxnumwant=Limitar el n\u00famero de pares que puede devolver el rastreador ConfigView.label.announceport=Invalida el puerto TCP para anuncios del rastreador, pex y dht \n[en blanco: sin invalidar, 0: sin conexiones entrantes] ConfigView.label.noportannounce=No anunciar el puerto de escucha al rastreador (esto no afecta a pex, dht) ConfigView.label.maxseedspertorrent=N\u00ba m\u00e1x. por defecto de semillas por torrent [0: ilimitadas] wizard.webseed=A\u00f1adir Semillas HTTP al torrent wizard.webseed.title=Semillas HTTP wizard.webseed.configuration=Configuraci\u00f3n de Semilla HTTP wizard.webseed.adding=A\u00f1adiendo Semillas HTTP GeneralView.label.private=Torrent Privado: GeneralView.yes=S\u00ed ConfigView.label.userequestlimiting=Usar 'regulaci\u00f3n de peticiones' en vez de 'lecturas retardadas' para limitar la velocidad de descarga [sin efecto cuando la velocidad de descarga es ilimitada] ConfigView.label.userequestlimiting.tooltip='Regulaci\u00f3n de peticiones' no es tan fluido como 'lecturas retardadas' , pero permite la priorizaci\u00f3n de las descargas en base a la posici\u00f3n en la cola de descargas y puede mejorar el rendimiento en la red ConfigView.label.userequestlimitingpriorities=Si se llega a descargar al m\u00e1ximo de velocidad (de descarga), dar prioridad al principio de la cola (de descargas) ConfigView.section.logging.timestamp=Formato del Estampado de Fecha en los archivos de registro Peers.column.timetocomplete=Tiempo Restante Peers.column.timetocomplete.info=El tiempo que queda hasta que el par haya completado ConfigView.section.interface.display.suppress.file.download.dialog=Suprimir el di\u00e1logo emergente para Descarga de Archivos ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Muestra en la barra de estado la marcha de la descarga de todos los archivos en vez de un di\u00e1logo emergente FileDownload.canceled=Se ha cancelado con \u00e9xito por una intervenci\u00f3n del usuario la descarga de un archivo torrent: %1 Progress.reporting.status.canceled=Cancelado Progress.reporting.status.finished=Terminado Progress.reporting.status.retrying=Reintentando... Progress.reporting.action.label.retry.tooltip=reintentar la operaci\u00f3n Progress.reporting.action.label.remove.tooltip=Quitar del historial este Informe de Progreso Progress.reporting.action.label.cancel.tooltip=Cancelar la operaci\u00f3n Progress.reporting.action.label.detail=Detalles Progress.reporting.default.error=Fallido Progress.reporting.no.reports.to.display=En este momento no hay ning\u00fan infome de progreso que mostrar Progress.reporting.no.history.to.display=No hay ning\u00fan mensaje de detalle que mostrar Progress.reporting.detail.history.limit=Se ha excedido el l\u00edmite de detalle del mensaje (%1) para este informe de progreso; los siguiente mensajes no se a\u00f1adir\u00e1n al hist\u00f3rico Progress.reporting.statusbar.button.tooltip=Mostrar la Ventana del Informe de Progreso webui.bindip=Bind IP - normalmente no es necesario (*) v3.MainWindow.text.log.in=Identificarse v3.MainWindow.text.log.out=Despedirse v3.MainWindow.text.get.started=Registrarse v3.MainWindow.text.my.account=Info sobre la cuenta v3.MainWindow.text.my.profile=Perfil OpenTorrentWindow.simple.open=Lugar del Torrent (Archivo, URL, Hash) Progress.reporting.window.remove.auto=Autoeliminar los elementos inactivos Progress.reporting.window.remove.auto.tooltip=Autoeliminar de la vista todos los procesos completados, fallidos, o cancelados Progress.reporting.window.remove.now=Eliminar los elementos inactivos Progress.reporting.window.remove.now.tooltip=Eliminar de la vista todos los procesos completados, fallidos, o cancelados dhttracker.tracklimitedwhenonline=Sin embargo y para poblar el enjambre, hacer un rastreo bajo en recursos cuando se est\u00e9 online TorrentOptionsView.multi.title.short=Opciones del Torrent TorrentOptionsView.multi.title.full=Opciones del Torrent MyTorrentsView.menu.open_parent_folder=Abrir la carpeta contenedora ConfigView.section.style.use_show_parent_folder=Usar en los men\u00fa del torrent "%1" en lugar de "%2" ConfigView.section.style.use_show_parent_folder.tooltip=Con esta opci\u00f3n activa podr\u00e1s abrir la carpeta contenedora con el programa para administrar archivos de tu elecci\u00f3n.\nSin embargo, esto puede implicar que el destino donde guardar no se autoseleccione. PeerManager.status.ps_disabled='Usar la lista de pares proporcionada por el rastreador' est\u00e1 desactivado ConfigView.section.stats.exportfiles=Exportar detalles del archivo updater.cant.write.to.app.title=No puedo escribir en la carpeta de la aplicaci\u00f3n updater.cant.write.to.app.details=La carpeta "%1" no es escribible.\n\nEsto puede impedir que se apliquen futuras actualizaciones del programa.\n\nMire por favor el wiki para ampliar detalles. plugin.install.class_version_error=Este complemento necesita una versi\u00f3n de Java m\u00e1s moderna. v3.MainWindow.tab.minilibrary=Descargas v3.MainWindow.tab.events=Actividad button.columnsetup.tooltip=Preferencias de Columna v3.activity.remove.title=Borrar los asientos de actividad v3.activity.remove.text=\u00bfSeguro que quiere borrar el suceso sobre la actividad '%1'? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=Cerrar Menu.show.torrent.menu=Mostrar el men\u00fa Torrents Menu.show.torrent.menu.tooltip=Muestra el men\u00fa Torrents sobre la barra del men\u00fa de la aplicaci\u00f3n #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=Estado de la Red ConfigView.section.style.usePathFinder=Usar 'Path Finder' en vez del 'Finder' menu.sortByColumn=Ordenar por %1 MyTorrentsView.menu.manual.per_peer=Manual (por par) MyTorrentsView.menu.manual.shared_peers=Manual (entre pares) v3.button.removeActivityEntry=Eliminar asiento de actividad v3.splash.initSkin=Inicializando Apariencia del GUI v3.splash.hookPluginUI=Enganchando el complemento GUI OpenTorrentWindow.mb.notTorrent.cannot.display=Los datos no se pueden mostrar correctamente MainWindow.menu.window.zoom.maximize=Maximizar MainWindow.menu.window.zoom.restore=Restaurar ImageResizer.image.too.small=La imagen proporcionada es demasiado peque\u00f1a, escoja por favor otra (que ha de ser al menos de %1 x %2) ImageResizer.title=Esta herramienta le permite ver el aspecto que va a tener su miniatura en la Plataforma Vuze ImageResizer.move.image=Mueva la imagen arrastr\u00e1ndola ImageResizer.move.image.with.slider=Mueva la imagen arrastr\u00e1ndola, redimensi\u00f3nela mediante la barra de desplazamiento inferior security.crypto.title=Acceso a la Clave de cifrado security.crypto.encrypt=Por favor, introduzca una contrase\u00f1a que proteja su clave de cifrado reci\u00e9n creada. No la olvide, ya que \u00a1no hay manera de recuperarla! security.crypto.decrypt=Introduzca por favor la contrase\u00f1a para desbloquear su clave de cifrado security.crypto.reason=Raz\u00f3n para la operaci\u00f3n security.crypto.password=Contrase\u00f1a security.crypto.password2=Reintroduzca la contrase\u00f1a security.crypto.persist_for=Periodo de validez de la contrase\u00f1a security.crypto.persist_for.dont_save=No guardar security.crypto.persist_for.session=Esta sesi\u00f3n security.crypto.persist_for.day=1 d\u00eda security.crypto.persist_for.week=1 semana security.crypto.persist_for.30days=30 d\u00edas security.crypto.persist_for.forever=Por siempre security.crypto.password.mismatch.title=Error en la Contrase\u00f1a security.crypto.password.mismatch=Las contrase\u00f1as no coinciden; por favor, introd\u00fazcalas de nuevo. ConfigView.section.security.group.crypto=Claves P\u00fablicas/Privadas ConfigView.section.security.resetkey=Reiniciar las claves ConfigView.section.security.resetkey.warning.title=Aviso de P\u00e9rdida de Datos ConfigView.section.security.resetkey.warning=\u00bfSeguro que quiere reiniciar sus claves de cifrado? Si lo hace, PERDER\u00c1 PERMANENTEMENTE toda la informaci\u00f3n cifrada con ellas. Del mismo modo, cualquier par que est\u00e9 en posesi\u00f3n de su clave p\u00fablica ya no podr\u00e1 comunicarse con usted sin antes conseguir la nueva. As\u00ed que a menos que sepa realmente lo que est\u00e1 haciendo, ni se le ocurra hacerlo. ConfigView.section.security.unlockkey=Claves de desbloqueo expl\u00edcitamente ConfigView.section.security.unlockkey.button=Desbloquear ConfigView.section.security.publickey=Clave p\u00fablica ConfigView.section.security.publickey.undef=Sin definir a\u00fan ConfigView.section.security.resetkey.error.title=Operaci\u00f3n Fallida ConfigView.section.security.resetkey.error=Intento fallido de reiniciar las claves ConfigView.section.security.unlockkey.error=Intento fallido de desbloqueo de clave - la contrase\u00f1a es incorrecta ConfigView.copy.to.clipboard.tooltip=Copiar al portapapeles Views.plugins.azbuddy.title=Amigos Browser.popup.error.no.access=Ha ocurrido un error al intentar acceder a un recurso remoto.\nPor favor, reint\u00e9ntelo m\u00e1s tarde.\n ConfigView.label.queue.stoponcebandwidthmet=No empezar m\u00e1s torrents desde el momento en que se alcancen los l\u00edmites de velocidad en env\u00edo/descarga ConfigView.section.style.forceMozilla=Forzar a Vuze el uso de Browser widgets de Mozilla [se necesita xulrunner o firefox 3; precisa reinicio] ConfigView.section.style.xulRunnerPath=Especifique manualmente la ruta a XulRunner / Firefox [necesario para FF3; precisa reinicio] azbuddy.name=Amigos azbuddy.enabled=Activado azbuddy.disabled=El complemento est\u00e1 desactivado, mire la config. del complemento para cambiarlo. azbuddy.nickname=Tu Apodo azbuddy.msglog.title=Informaci\u00f3n sobre el Amigo azbuddy.addtorrent.title=\u00bfAceptar Descarga? azbuddy.addtorrent.msg=Tu amigo '%1' te ha enviado '%2'.\n\u00bfQuieres a\u00f1adir esta descarga? azbuddy.contextmenu=Enviar a Amigo azbuddy.ui.mykey=Mi clave: azbuddy.ui.add=A\u00f1adir azbuddy.ui.new_buddy=Nueva clave del amigo: azbuddy.ui.table.name=Nombre azbuddy.ui.table.online=Conectado azbuddy.ui.table.last_msg=\u00daltimo mensaje azbuddy.ui.menu.remove=Eliminar azbuddy.ui.menu.copypk=Copiar la Clave P\u00fablica azbuddy.ui.menu.send=Enviar Mensaje azbuddy.ui.menu.send_msg=Escriba el texto que va a enviar a su(s) amigo(s) azbuddy.ui.menu.ygm=Enviar YGM azbuddy.ui.menu.enc=Encriptar el Portapapeles azbuddy.ui.menu.dec=Desencriptar el Portapapeles azbuddy.ui.menu.sign=Firmar el Portapapeles azbuddy.ui.menu.verify=Verificar el Portapapeles azbuddy.ui.table.lastseen=Visto el Button.retry=&Reintentar Button.ignore=&Ignorar DHTView.general.skew=Distorsi\u00f3n: azbuddy.ui.table.msg_in=Msg Entra. azbuddy.ui.table.msg_out=Msg Sal. v3.MainWindow.menu.view.footer=Pie azbuddy.downspeed=Veloc. m\u00e1x. de descarga del amigo en KB/s [0: ilimitada] security.crypto.badpw=La contrase\u00f1a proporcionada era inccorrecta ConfigView.section.security.backupkeys=Guardar las claves en un fichero ConfigView.section.security.backupkeys.button=Guardar ConfigView.section.security.restorekeys=Recuperar las claves desde un fichero ConfigView.section.security.restorekeys.button=Recuperar ConfigView.section.security.op.error.title=Operaci\u00f3n Fallida ConfigView.section.security.op.error=No se pudo completar la operaci\u00f3n:\n %1 ConfigView.section.security.restart.title=Reinicio Necesario ConfigView.section.security.restart.msg=Vuze reiniciar\u00e1 ahora para completar la operaci\u00f3n. ConfigView.section.security.system.managed=Protecci\u00f3n de claves administrada por el sistema azbuddy.ui.table.msg_queued=En cola azbuddy.chat.title=Chat de Vuze azbuddy.chat.says=%1 dice: Button.bar.show=Mostrar Button.bar.hide=Ocultar Button.bar.share=Compartir Button.bar.add=Invitar a Amigos Button.bar.edit=Editar Button.bar.edit.cancel=Terminado de Editar v3.MainWindow.menu.view.pluginbar=Barra de Complementos MainWindow.dialog.select.vuze.file=Seleccione archivo Vuze MainWindow.menu.file.open.vuze=Archivo Vuze ... metasearch.addtemplate.title=\u00bfInstalar la Plantilla de B\u00fasqueda? metasearch.addtemplate.desc=\u00bfEst\u00e1 seguro de querer instalar una plantilla de b\u00fasqueda de nombre '%1'? v3.share.private.title=Compartiendo Torrent v3.share.private.text=El torrent elegido viene marcado como Torrent Privado.\n\nNo puedes compartir torrents privados. metasearch.addtemplate.dup.title=Duplicar Plantilla metasearch.addtemplate.dup.desc=La plantilla de b\u00fasqueda %1 ya estaba instalada metasearch.export.select.template.file=Guardar Plantilla metasearch.import.select.template.file=Abrir Plantilla dialog.uiswitch.title=Pasar al GUI de Vuze dialog.uiswitch.text=Para poder usar esto, necesitas estar usando el GUI de Vuze.\n\nVuze necesitar\u00e1 reiniciarse. dialog.uiswitch.button=Pasar al GUI de Vuze azbuddy.tracker.enabled=Active 'Impulsar Amigos' para priorizar la descarga con sus amigos azbuddy.protocolspeed=Carga m\u00e1x del protocolo de amigo en KB/s v3.MainWindow.button.download=Descarga v3.MainWindow.button.run=Ejecutar el archivo descargado v3.activity.header.downloads=Descargas v3.activity.header.vuze.news=Noticias sobre Vuze message.taking.too.long=Parece que esto se est\u00e1 tomando m\u00e1s tiempo del esperado\nPulse 'ESC' si quiere cancelar esta operaci\u00f3n message.status.success=Con \u00e9xito azbuddy.tracker.bbb.status.title=Impulsar Amigos azbuddy.tracker.bbb.status.title.tooltip=Doble clic para ampliar detalles azbuddy.tracker.bbb.status.idle=Sin Impulsar azbuddy.tracker.bbb.status.nli=Es necesario Identificarse azbuddy.tracker.bbb.status.in=Estoy siendo Impulsado azbuddy.tracker.bbb.status.out=Impulsando a Amigos en este momento v3.MainWindow.search.go.tooltip=Ejecutar B\u00fasqueda v3.MainWindow.search.last.tooltip=Volver a los resultados de la b\u00fasqueda metasearch.addtemplate.done.title=Plantilla A\u00f1adida metasearch.addtemplate.done.desc=La plantilla '%1' se a\u00f1adi\u00f3 con \u00e9xito.\n\u00a1Se utilizar\u00e1 a partir de la pr\u00f3xima b\u00fasqueda! ConfigView.section.security.nopw=Falta la contrase\u00f1a ConfigView.section.security.nopw_v=No se dispone de contrase\u00f1a, por favor ap\u00fantese en Vuze fileplugininstall.install.title=\u00bfInstalar el Complemento? fileplugininstall.install.desc=\u00bfSeguro que quiere instalar el complemento '%1', cuya versi\u00f3n es %2? fileplugininstall.duplicate.title=Complemento duplicado fileplugininstall.duplicate.desc=El complemento '%1', version %2 ya estaba instalado azbuddy.online_status=Estado Online azbuddy.os_online=Conectado azbuddy.os_away=Lejos azbuddy.os_not_avail=No Disponible azbuddy.os_busy=Ocupado azbuddy.os_offline=Desconectado azbuddy.ui.menu.disconnect=Desconectar azbuddy.enable_chat_notif=Permitir las notificaciones de chat DetailedListView.title=Lista Detallada ConfigView.section.connection.network.max.outstanding.connect.attempts=N\u00ba m\u00e1x de conexiones salientes pendientes plugins.init.force_enabled=Vuze ha detectado que el complemento "%1" estaba desactivado - Ha sido reactivado para permitir a Vuze funcionar correctamente. ConfigView.section.connection.prefer.udp=Prefiero las conexiones UDP subscript.add.title=\u00bfInstalar la Subscripci\u00f3n? subscript.add.desc=\u00bfSeguro que quiere instalar la subscripci\u00f3n a '%1'? subscript.add.dup.title=Subscripci\u00f3n Duplicada subscript.add.dup.desc=La Subscripci\u00f3n a '%1' ya estaba instalada. subscript.add.upgrade.title=\u00bfActualizar la Subscripci\u00f3n? subscript.add.upgrade.desc=\u00bfSeguro que quiere actualizar la subscripci\u00f3n a '%1'? subscript.add.upgradeto.desc=Est\u00e1 disponible la versi\u00f3n %1 de la subscripci\u00f3n '%2'.\n\u00bfQuiere actualizarla? azsubs.contextmenu.addassoc=A\u00f1adir asociaci\u00f3n de subscripci\u00f3n azsubs.contextmenu.lookupassoc=Buscar asociaciones de subscripci\u00f3n iconBar.start=Empezar iconBar.stop=Detener iconBar.remove=Eliminar iconBar.up=Subir iconBar.down=Bajar iconBar.run=Lanzar iconBar.editcolumns=Configuraci\u00f3n de columnas iconBar.top=Mover al principio iconBar.bottom=Mover al final iconBar.queue=Cola iconBar.open=A\u00f1adir Torrent iconBar.share=Compartir iconBar.share.tooltip=Compartir contenido iconBar.details=Detalles iconBar.comment=Comentario iconBar.play=Reproducir iconBar.queue.tooltip=Cola v3.MainWindow.menu.view.sidebar=Barra Lateral v3.MainWindow.menu.view.actionbar=Barra de Acci\u00f3n v3.MainWindow.menu.view.toolbars=Barra de Herramientas ump.install=Para reproducir este v\u00eddeo necesitar\u00e1 componentes adicionales. Instal\u00e1ndolos ahora. Espere por favor. subscriptions.listwindow.title=Buscador de Subscripciones subscriptions.listwindow.autochecktext=Vuze puede hallar subscripciones relacionadas con el contenido de su biblioteca. \u00bfQuiere activar esta caracter\u00edstica? subscriptions.listwindow.loadingtext=Buscando subscripciones relacionadas con %1 subscriptions.listwindow.failed=Subscripci\u00f3n no hallada subscriptions.listwindow.popularity=Popularidad subscriptions.listwindow.popularity.unknown=Desconocido subscriptions.listwindow.name=Nombre subscriptions.listwindow.subscribe=Subscribirse TableColumn.header.azsubs.ui.column.subs=Subscripciones subscriptions.listwindow.popularity.reading=Leyendo... PluginDeprecation.log.start=Esta ventana contiene informaci\u00f3n sobre los complementos que utilizan una funcionalidad que se eliminar\u00e1 en posteriores versiones de Vuze.\nNo necesita desinstalar los complementos, s\u00f3lo tendr\u00e1 que actualizar elcomplemento a su \u00faltima versi\u00f3n.\nSi ya est\u00e1 ejecutando esta \u00faltima versi\u00f3n, copie el contenido de esta ventana y post\u00e9elo en el foro situado aqu\u00ed:\n \u005ct%1\n\n PluginDeprecation.log.details=---------\nIDENTIFICADOR: %1\nCONTEXTO: %2\n\n*** COMENZAR RASTREO ***\n%3*** FINALIZAR RASTREO ***\n\n PluginDeprecation.view=Depuraci\u00f3n de Complementos PluginDeprecation.alert=Un complemento ha intentado usar una funcionalidad que ser\u00e1 eliminada en el futuro -para ampliar informaci\u00f3n abra por favor la vista del registro de Depuraci\u00f3n de Complementos. TableColumn.header.Thumbnail=Icono TableColumn.header.Thumbnail.info=El tama\u00f1o de la miniatura del contenido Vuze; para todos los dem\u00e1s contenidos, el sistema operativo proporcionar\u00e1 esos iconos. v3.MainWindow.menu.getting_started=&Primeros pasos MainWindow.menu.community=&Comunidad MainWindow.menu.help.faq=&Preguntas Frecuentes MainWindow.menu.community.forums=&Foros Comunitarios MainWindow.menu.community.blog=Blog de &Vuze MainWindow.menu.help.support=&Ayuda and Soporte Button.done=Hecho GeneralView.torrent_created_on_and_by=%1 por %2 Button.continue=Continuar Button.preview=Previsualizar authenticator.location=Localizaci\u00f3n authenticator.details=Detalles Button.remove=Eliminar Button.send=Enviar Button.back=Atr\u00e1s ConfigView.section.Subscriptions=Suscripciones Wizard.Subscription.title=Subscribirse Wizard.Subscription.optin.title=Activar Suscripciones #what you've watched? Discover more with a single click... Wizard.Subscription.subscribe.title=Subscripciones Disponibles Wizard.Subscription.create.title=Crear Nueva Subscripci\u00f3n Button.search=Buscar Button.save=Guardar Button.add=A\u00f1adir Button.createNewSubscription=Crear Nueva Subscripci\u00f3n Button.availableSubscriptions=Subscripciones disponibles Wizard.Subscription.optin.description=Con Suscripciones activadas, Vuze le mostrar\u00e1 suscripciones en relaci\u00f3n con el contenido de su Biblioteca, y le permitir\u00e1 saber cuando el contenido suscrito est\u00e1 disponible para su descarga.\n\n\u00bfLe gustar\u00eda activar las Suscripciones? Wizard.Subscription.create.search=Buscar Wizard.Subscription.subscribe.library=Contenido en su Biblioteca Wizard.Subscription.subscribe.subscriptions=Subscripciones Relacionadas Wizard.Subscription.subscribe.library.empty=\u00bfNo hay subscripciones disponibles?\n \nBusca el bot\u00f3n de suscripci\u00f3n naranja brillante en Vuze HD Network.\n \nLeer m\u00e1s message.confirm.delete.title=Confirmar Eliminaci\u00f3n message.confirm.delete.text=\u00bfEst\u00e1 seguro de querer eliminar '%1'? externalLogin.wait=Cargando p\u00e1gina, por favor, espere... metasearch.addtemplate.failed.title=Instalaci\u00f3n fallida Button.deleteContent.fromLibrary=Eliminar de la Biblioteca Button.deleteContent.fromComputer=Eliminar del Ordenador configureWizard.file.message3=Vuze descargar\u00e1 los archivos en una carpeta espec\u00edfica, puede elegir esta carpeta aqu\u00ed: ConfigView.label.systray=Bandeja de Sistema azbuddy.ui.menu.cat=Categor\u00edas azbuddy.ui.menu.cat_subs=Subscribirse ColumnSetup.categories=Categor\u00edas: ColumnSetup.filters=Filtros devices.view.title=Dispositivos device.manu.desc=Fabricante device.mediaserver.configure=Configurar Mi Servidor Multimedia device.hide=Ocultar Dispositivo device.show=Mostrar Dispositivos Ocultos device.search=Buscar Dispositivos device.upnp.desc_url=Descripci\u00f3n del Dispositivo device.upnp.present_url=Administraci\u00f3n del Dispositivo device.search.auto=Buscar dispositivos autom\u00e1ticamente devices.sidebar.simple=Vista simple devices.device=Dispositivo devices.profile=Perfil General.percent=Porcentaje devices.installed=Instalado devices.state=Estado MainWindow.menu.help.donate=Haz una &Donaci\u00f3n DonationWindow.noload.title=Donaci\u00f3n DonationWindow.noload.text=La ventana de donaci\u00f3n falla al cargar. Por favor, int\u00e9ntelo de nuevo m\u00e1s tarde. download.removerules.unauthorised.data=\tEliminar datos device.xcode.always=Siempre device.xcode.whenreq=Cuando sea necesario device.xcode.never=Nunca devices.sidebar.hide.rend.generic=Ocultar dispositivos gen\u00e9ricos iconBar.transcode=Dispositivo devices.ready=Preparado TableColumn.header.profile=Dispositivo TableColumn.header.device=Dispositivo TableColumn.header.device.info=Dispositivo de destino # This is the beginning of the word "View". It's right aligned under the icon bar item # This is the end of the word "View". It's left aligned under the icon bar item general.dont.ask.again=No preguntar de nuevo general.na.short=N/D v3.menu.device.exploreTranscodes=Mostrar Archivos v3.menu.device.exploreTranscodes._windows=Mostrar Archivos en el Explorador v3.menu.device.exploreTranscodes._mac=Mostrar Archivos en el Buscador v3.menu.device.defaultprofile=Perfil Predeterminado device.itunes.install=Necesita instalar iTunes device.itunes.start=Necesita iniciar iTunes o activar auto-iniciar devices.downloading=Descargando ConfigView.option.dm.dblclick.play=Reproducir Contenido ConfigView.option.dm.dblclick.show=Mostrar Archivo ConfigView.option.dm.dblclick.show._mac=Mostrar Archivo(s) en el Buscador ConfigView.option.dm.dblclick.show._windows=Mostrar Archivo(s) en el Explorador xcode.deletedata.message.2=\n(todav\u00eda debe existir una copia en '%1') devices.converting=Convirtiendo Button.reload=Recargar devices.auto.start=Auto-iniciar azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_cs_CZ.properties0000644000175000017500000044317511301156004026106 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=.torrent soubor Main.parameter.usage=Pou\u017eit\u00ed : java org.gudy.azureus2.cl.Main [parametry] "soubor.torrent" "c\u00edlov\u00e1 slo\u017eka" Main.parameter.maxUploads=Maxim\u00e1ln\u00ed po\u010det simult\u00e1ln\u00edch upload\u016f Main.parameter.maxSpeed=Maxim\u00e1ln\u00ed rychlost uploadu (B/s) MainWindow.menu.file=&Soubor MainWindow.menu.file.open=&Otev\u0159\u00edt MainWindow.menu.file.create=&Vytvo\u0159it Torrent MainWindow.menu.file.create.fromfile=Ze &souboru MainWindow.menu.file.create.fromdir=Ze s&lo\u017eky MainWindow.menu.file.export=&Exportovat Torrent do XML... MainWindow.menu.file.import=&Importovat Torrent z XML... MainWindow.menu.file.closetab=Zav\u0159\u00edt &Tab MainWindow.menu.file.closewindow=Zav\u0159\u00edt &Okno MainWindow.menu.file.exit=&Konec MainWindow.dialog.choose.file=Vyberte .torrent soubor MainWindow.menu.file.folder=S&lo\u017eku MainWindow.dialog.choose.folder=Vyberte slo\u017eku s .torrent soubory MainWindow.menu.view=&Zobrazit MainWindow.menu.view.show=Zobrazit MainWindow.menu.view.mytorrents=&Moje Torrenty MainWindow.menu.view.configuration=&Nastaven\u00ed MainWindow.menu.view.console=&Konzola MainWindow.menu.closealldetails=Schovat v\u0161echny &Detaily MainWindow.menu.closealldownloadbars=Schovat v\u0161echny &Informa\u010dn\u00ed prou\u017eky MainWindow.menu.language=&Jazyk ConfigView.section.language=Jazyk MainWindow.menu.window=&Okno MainWindow.menu.window.minimize=&Minimalizovat MainWindow.menu.window.zoom=&Zv\u011bt\u0161it MainWindow.menu.window.alltofront=P\u0159esunot v\u0161e na &za\u010d\u00e1tek MainWindow.menu.help=&N\u00e1pov\u011bda MainWindow.menu.help.about=&O programu Vuze MainWindow.about.title=O programu Vuze MainWindow.about.section.developers=V\u00fdvoj\u00e1\u0159i MainWindow.about.section.translators=P\u0159ekladatel\u00e9 MainWindow.about.section.system=Syst\u00e9m MainWindow.about.internet.homepage=Domovsk\u00e1 str\u00e1nka programu Vuze MainWindow.about.internet.sourceforge=Sourceforge - Str\u00e1nka projetku MainWindow.about.internet.sourceforgedownloads=Sourceforge - Downloads MainWindow.about.internet.bugreports=Hl\u00e1\u0161en\u00ed chyb MainWindow.about.internet.forumdiscussion=Diskusn\u00ed f\u00f3ra MainWindow.about.internet.wiki=Vuze Wiki \u010dast\u00e9 dotazy MainWindow.dialog.choose.savepath=Vyberte c\u00edlovou slo\u017eku MainWindow.dialog.choose.savepath_forallfiles=Vyberte c\u00edlovou slo\u017eku pro V\u0160ECHNY soubory MainWindow.status.latestversion=Nejnov\u011bj\u0161\u00ed MainWindow.status.latestversion.clickupdate=Klin\u011bte pro update MainWindow.status.unknown=nezn\u00e1m\u00fd MainWindow.status.checking=zji\u0161\u0165uji MyTorrentsView.mytorrents=Moje Torrenty TableColumn.header.name=N\u00e1zev TableColumn.header.size=Velikost TableColumn.header.done=Hotovo TableColumn.header.done.info=Ud\u00e1v\u00e1 na kolik procent je pr\u00e1v\u011b prob\u00edhaj\u00edc\u00ed \u00fakol dokon\u010den TableColumn.header.status=Stav TableColumn.header.status.info=Ud\u00e1v\u00e1, co se s torrentem pr\u00e1v\u011b d\u011bje TableColumn.header.seeds=Zdroje TableColumn.header.seeds.info=Ud\u00e1v\u00e1 po\u010det p\u0159ipojen\u00fdch zdroj\u016f (celkov\u00fd po\u010det zdroj\u016f) TableColumn.header.peers=Klienti TableColumn.header.peers.info=Ud\u00e1v\u00e1 po\u010det p\u0159ipojen\u00fdch klient\u016f (celkov\u00fd po\u010det klient\u016f) TableColumn.header.downspeed=Download rychlost TableColumn.header.upspeed=Upload rychlost TableColumn.header.eta=Zb\u00fdv\u00e1 TableColumn.header.tracker=Server TableColumn.header.tracker.info=Ud\u00e1v\u00e1 stav serveru TableColumn.header.trackernextaccess=Dal\u0161\u00ed tracker je p\u0159\u00edstupn\u00fd TableColumn.header.trackernextaccess.info=Nastavit p\u0159istup dal\u0161\u00edho servru TableColumn.header.priority=Priorita TableColumn.header.priority.info=Ur\u010duje, jak velk\u00fd datov\u00fd tok pro upload je torrentu vyhrazen TableColumn.header.seeds.fullcopycalc=%2 p\u0159ezet\u00ed upln\u00fdch kopi\u00ed pro %1 peers MyTorrentsView.menu.showdetails=&Zobrazit Detaily MyTorrentsView.menu.showdownloadbar=Zobrazit &Informa\u010dn\u00ed prou\u017eek MyTorrentsView.menu.open=&Otev\u0159\u00edt MyTorrentsView.menu.setpriority=Nastavit &prioritu MyTorrentsView.menu.setpriority.high=&Vysok\u00e1 MyTorrentsView.menu.setpriority.low=&N\u00edzk\u00e1 MyTorrentsView.menu.start=&Start MyTorrentsView.menu.stop=Sto&p MyTorrentsView.menu.remove=O&debrat MyTorrentsView.menu.changeTracker=P\u0159idat URL &Servru TrayWindow.menu.exit=&Konec TrayWindow.menu.show=&Zobrazit Vuze SystemTray.menu.exit=&Konec SystemTray.menu.closealldownloadbars=Schovat v\u0161echny &Informa\u010dn\u00ed prou\u017eky SystemTray.menu.show=&Zobrazit Vuze PeersView.ip.info=IP adresa p\u0159ipojen\u00e9ho u\u017eivatele PeersView.port.info=Pou\u017eit\u00fd port PeersView.T.info=L (lok\u00e1ln\u00ed): P\u0159ipojen\u00ed bylo nav\u00e1z\u00e1no odsud, R (vzd\u00e1len\u00e9): P\u0159ipojen\u00ed bylo nav\u00e1z\u00e1no zven\u010d\u00ed PeersView.T.L.tooltip=P\u0159ipojen\u00ed bylo nav\u00e1z\u00e1no odsud PeersView.T.R.tooltip=P\u0159ipojen\u00ed bylo nav\u00e1z\u00e1no zven\u010d\u00ed PeersView.I1=I (Klient m\u00e1 pro mne zaj\u00edmav\u00e9 \u010d\u00e1sti) PeersView.I1.info=M\u00e1 klient pro mne zaj\u00edmav\u00e9 \u010d\u00e1sti? PeersView.C1=C (Vybr\u00e1n klientem) PeersView.C1.info=Ud\u00e1v\u00e1, jestli klient zastavuje Va\u0161e stahov\u00e1n\u00ed od n\u011bj PeersView.pieces=D\u00edly PeersView.downloadspeed=Download rychlost PeersView.download=P\u0159ijato PeersView.I2=I (Klient se zaj\u00edm\u00e1 o m\u00e9 \u010d\u00e1sti) PeersView.I2.info=Zaj\u00edm\u00e1 se klient o m\u00e9 \u010d\u00e1sti? PeersView.C2=C (Klient je vybr\u00e1n) PeersView.C2.info=Ud\u00e1v\u00e1, jestli blokujete klienta od stahov\u00e1n\u00ed PeersView.uploadspeed=Upload rychlost PeersView.uploadspeed.info=Rychlost odes\u00edl\u00e1n\u00ed ke klientovi PeersView.upload=Odesl\u00e1no PeersView.upload.info=Celkov\u00e9 mno\u017estv\u00ed odeslan\u00fdch dat klientovi PeersView.statup=Stav Up PeersView.statup.info=Odhadovan\u00e1 celkov\u00e1 rychlost odes\u00edl\u00e1n\u00ed klienta PeersView.S.info=Nespolehliv\u00fd: Klient m\u016f\u017ee b\u00fdt ozna\u010den "nespolehliv\u00fdm" manualn\u011b nebo automaticky (za nedostate\u010dn\u011b rychl\u00e9 odes\u00edl\u00e1n\u00ed dat) PeersView.downloadspeedoverall=Celkov\u00e1 Download rychlost PeersView.optunchoke=Opt. uvoln\u011bn\u00ed PeersView.client=Klient PeersView.client.info=BitTorrent program, kter\u00fd klient pou\u017e\u00edv\u00e1 PeersView.menu.snubbed=&Ned\u016fv\u011bryhodn\u00fd PeersView.title.short=Zdroje PeersView.title.full=Zdroje ConfigView.section.files=Soubory ConfigView.label.usefastresume=Pou\u017e\u00edvat m\u00f3d rychl\u00e9ho obnoven\u00ed ConfigView.label.incrementalfile=Povolit postupn\u00e9 vytv\u00e1\u0159en\u00ed soubor\u016f [Nutn\u00e9 p\u0159i pou\u017e\u00edv\u00e1n\u00ed souborov\u00e9ho syst\u00e9mu FAT32 v Linuxu] ConfigView.label.defaultsavepath=Ukl\u00e1dat do v\u00fdchoz\u00ed slo\u017eky ConfigView.button.browse=Proch\u00e1zet... ConfigView.dialog.choosedefaultsavepath=Vyberte v\u00fdchoz\u00ed c\u00edlovou slo\u017eku ConfigView.section.server=Server ConfigView.section.global=Obecn\u00e9 ConfigView.label.disconnetseed=Kdy\u017e jsem zdroj, odpojit ostatn\u00ed zdroje ConfigView.label.switchpriority=Kdy\u017e jsem zdroj, automaticky p\u0159epnout na n\u00edzkou prioritu ConfigView.label.maxdownloads=Max. po\u010det simult\u00e1ln\u00edch download\u016f [0: neomezen\u011b] ConfigView.label.maxdownloads.tooltip=V\u017edy budete schopen aktivn\u011b stahovat po\u010det, kter\u00fd poskytnete.\nKompletn\u00ed torrent odpov\u00eddaj\u00edc\u00ed prvn\u00ed priorit\u011b m\u016f\u017ee p\u0159evz\u00edt download slotem. ConfigView.label.maxactivetorrents=Max. po\u010det aktivn\u00edch Torrent\u016f [0: neomezen\u011b]\n - Nov\u00e9 Torrenty se automaticky nespust\u00ed, pokud jich stahujete/distribujete v\u00edc ConfigView.label.priorityExtensions=Zv\u00fd\u0161it prioritu pro soubory s p\u0159\u00edponou\n - nap\u0159\u00edklad: .txt;.nfo;.jpg ConfigView.section.transfer=P\u0159enos ConfigView.label.maxuploads=V\u00fdchoz\u00ed max.upload\u016f na torrent ConfigView.label.maxuploadspeed=Celkov\u00e1 max.rychlost uploadu v KB/s [0: neomezen\u011b] ConfigView.label.saveresumeinterval=Ukl\u00e1dat data pro obnoven\u00ed ka\u017ed\u00fdch ConfigView.unlimited=Neomezen\u011b ConfigView.section.display=Zobrazen\u00ed ConfigView.label.opendetails=Automaticky zobrazovat tabulku s detaily (Detaily) ConfigView.label.openbar=Automaticky zobrazovat informa\u010dn\u00ed prou\u017eek ConfigView.label.closetotray=Zav\u0159en\u00ed programu jej minimalizuje do syst\u00e9mov\u00e9 li\u0161ty. ConfigView.label.minimizetotray=Minimalizovat do syst\u00e9mov\u00e9 li\u0161ty. ConfigView.section.general=Obecn\u00e9 ConfigView.section.start=Spu\u0161t\u011bn\u00ed ConfigView.label.showsplash=Zobrazit uv\u00edtac\u00ed obrazovku ConfigView.label.autoupdate=Zobrazit dialogov\u00e9 okno o nov\u00e9 verzi, pokud je dostupn\u00e1. ConfigView.label.openconsole=Po spu\u0161t\u011bn\u00ed otev\u0159\u00edt konzoli (Konzole) ConfigView.label.openconfig=Po spu\u0161t\u011bn\u00ed otev\u0159\u00edt nastaven\u00ed (Nastaven\u00ed) ConfigView.label.startminimized=Spustit Azurea minimalizovan\u011b ConfigView.section.irc=IRC ConfigView.label.ircwiki=Pros\u00edm \u010dt\u011bte na http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Server ConfigView.label.ircchannel=Kan\u00e1l ConfigView.label.irclogin=P\u0159ezd\u00edvka ConfigView.group.irctitle=IRC Nastaven\u00ed ConfigView.boolean.ircsendinfo=Povolit odesl\u00e1n\u00ed Va\u0161eho nastaven\u00ed (anonymn\u011b) \n kan\u00e1lov\u00e9mu operatorovi pro pomoc. ConfigView.boolean.irclog=Povolit z\u00e1pis o \u010dinnosti kan\u00e1lu (in IRC_log.htm) ConfigView.section.security=Zabezpe\u010den\u00ed ConfigView.label.password=Chr\u00e1nit Vuze heslem\n - Bude po\u017eadov\u00e1no p\u0159i obnoven\u00ed z ikonky a p\u0159i spu\u0161t\u011bn\u00ed ConfigView.label.passwordconfirm=Heslo (znovu - potvrzen\u00ed) ConfigView.label.passwordmatch=Heslo je aktivn\u00ed : ConfigView.label.passwordmatchnone=Ne ConfigView.label.passwordmatchno=Ne / Hesla se neshoduj\u00ed ConfigView.label.passwordmatchyes=Ano ConfigView.button.save=Ulo\u017eit ConfigView.title.short=Nastaven\u00ed ConfigView.title.full=Nastaven\u00ed ConsoleView.title.short=Konzole ConsoleView.title.full=Konzole FileItem.write=Z\u00e1pis FileItem.read=\u010cten\u00ed FileItem.normal=norm\u00e1ln\u00ed FileItem.high=vysok\u00e1 FileItem.donotdownload=Nestahovat FilesView.name=Jm\u00e9no FilesView.size=Velikost FilesView.done=Hotovo FilesView.%=% FilesView.firstpiece=Prvn\u00ed d\u00edl \u010d. FilesView.numberofpieces=Po\u010det d\u00edl\u016f FilesView.pieces=D\u00edly FilesView.mode=M\u00f3d FilesView.priority=Priorita FilesView.menu.open=&Otev\u0159\u00edt FilesView.menu.setpriority=Nastavit &prioritu FilesView.menu.setpriority.high=&Vysok\u00e1 FilesView.menu.setpriority.normal=&Normaln\u00ed FilesView.menu.setpriority.skipped=Ne&stahovat FilesView.title.short=Soubory FilesView.title.full=Soubory GeneralView.section.downloaded=Sta\u017eeno GeneralView.label.status.file=Stav souboru GeneralView.label.status.pieces=Sta\u017een\u00e9 d\u00edly GeneralView.section.availability=Dostupnost GeneralView.label.status.pieces_available=Dostupnost d\u00edl\u016f GeneralView.section.transfer=P\u0159esun GeneralView.section.info=Informace GeneralView.title.short=Torrent GeneralView.title.full=Torrent GeneralView.label.timeelapsed=Uplynul\u00fd \u010das: GeneralView.label.remaining=Zb\u00fdvaj\u00edc\u00ed \u010das : GeneralView.label.downloaded=Sta\u017eeno : GeneralView.label.downloadspeed=Rychlost downloadu : GeneralView.label.maxuploads=Maximum upload\u016f: GeneralView.label.maxuploads.tooltip=Maxim\u00e1ln\u00ed po\u010det u\u017eivatel\u016f, kte\u0159\u00ed uvoln\u00ed p\u0159ipojen\u00ed v dan\u00e9m \u010dase. GeneralView.label.uploaded=Odesl\u00e1no: GeneralView.label.uploadspeed=Rychlost uploadu: GeneralView.label.seeds=Zdroje : GeneralView.label.peers=Klienti : GeneralView.label.totalspeed=Celkov\u00e1 rychlost: GeneralView.label.totalspeed.tooltip=Celkov\u00e1 rychlost v\u0161ech p\u0159ipojen\u00fdch klient\u016f. GeneralView.label.averagespeed=pr\u016fm\u011br GeneralView.label.filename=N\u00e1zev : GeneralView.label.totalsize=Celkov\u00e1 velikost: GeneralView.label.savein=C\u00edl : GeneralView.label.numberofpieces=Po\u010det d\u00edl\u016f : GeneralView.label.size=Velikost d\u00edlu : GeneralView.label.tracker=Stav trackeru : GeneralView.label.updatein=Aktualizovat za: GeneralView.label.trackerurl=URL Trackeru: GeneralView.label.trackerurlupdate=Aktualizovat server GeneralView.label.comment=Koment\u00e1\u0159 : ManagerItem.waiting=\u010cek\u00e1n\u00ed ManagerItem.allocating=Alokace m\u00edsta ManagerItem.checking=Ov\u011b\u0159ov\u00e1n\u00ed ManagerItem.ready=P\u0159ipraven ManagerItem.downloading=Stahov\u00e1n\u00ed ManagerItem.seeding=Distribuce ManagerItem.stopped=Zastaveno ManagerItem.error=Chyba ManagerItem.high=vysok\u00e1 ManagerItem.low=n\u00edzk\u00e1 MinimizedWindow.name=N\u00e1zev: PiecesView.size=Velikost PiecesView.numberofblocks=Po\u010det blok\u016f PiecesView.blocks=Bloky PiecesView.completed=P\u0159ijato PiecesView.availability=Dostupnost PiecesView.reservedby=Z\u00e1lo\u017en\u00ed PiecesView.writers=Blokovan\u00ed p\u0159ip\u011bvatel\u00e9 PiecesView.title.short=D\u00edly PiecesView.title.full=D\u00edly SystemTray.tooltip.seeding=%1 distribuov\u00e1no, SystemTray.tooltip.downloading=%1 stahov\u00e1no, DownloadManager.error.filenotfound=Soubor nenalezen DownloadManager.error.fileempty=Torrent soubor je pr\u00e1zdn\u00fd DownloadManager.error.filetoobig=Torrent soubor je moc velk\u00fd DownloadManager.error.filewithouttorrentinfo=Informace o Torrentu nebyly v souboru nalezeny DownloadManager.error.unsupportedencoding=Nepodporovan\u00e9 k\u00f3dov\u00e1n\u00ed DownloadManager.error.ioerror=Chyba V/V DownloadManager.error.sha1=Algoritmus nen\u00ed podporov\u00e1n (SHA1) PeerManager.status.offline=Chyba p\u0159ipojen\u00ed PeerManager.status.checking=Aktualizace PeerManager.status.finished=Dokon\u010deno PeerManager.status.finishedin=Dokon\u010deno za MainWindow.upgrade.assistant=Pr\u016fvodce aktualizac\u00ed MainWindow.upgrade.newerversion=Je k dispozici nov\u00e1 verze programu Azureus. MainWindow.upgrade.explanation=Tento pr\u016fvodce v\u00e1m pom\u016f\u017ee aktualizovat Azureus. St\u00e1hne novou verzi a restartuje program. MainWindow.upgrade.explanation.manual=Novou verzi m\u016f\u017eete nainstalovat ru\u010dn\u011b, zav\u0159en\u00edm programu, sta\u017een\u00edm nov\u00e9 verze do slo\u017eky programu a jeho op\u011btovn\u00fdm spu\u0161t\u011bn\u00edm. MainWindow.upgrade.step1=Krok 1: Sta\u017een\u00ed nov\u00e9 verze MainWindow.upgrade.step2=Krok 2: Zav\u0159en\u00ed t\u00e9to verze a spu\u0161t\u011bn\u00ed nov\u00e9 verze programu MainWindow.upgrade.hint1=Tip : Tla\u010d\u00edtkem Dokon\u010dit m\u016f\u017eete prov\u00e9st cel\u00fd proces automaticky MainWindow.upgrade.hint2=Tip : Pokud chcete ukon\u010dit Vuze pozd\u011bji, pou\u017eijte tla\u010d\u00edtko Storno.\n\tPo ukon\u010den\u00ed programu pak p\u0159ejmenujte soubor Azureus2-new.jar na Azureus2.jar MainWindow.upgrade.error.downloading.hint=Chyba : Nepoda\u0159ilo se st\u00e1hnout novou verzi programu Azureus. Aktualizujte pros\u00edm program ru\u010dn\u011b. MainWindow.upgrade.section.info=Dostupn\u00e1 nov\u00e1 verze programu MainWindow.upgrade.section.manual=Ru\u010dn\u00ed aktualizace MainWindow.upgrade.section.automatic=Automatick\u00e1 aktualizace MainWindow.upgrade.tooltip.progressbar=Pr\u016fb\u011bh stahov\u00e1n\u00ed je zobrazen zde Button.next=Dal\u0161\u00ed Button.finish=Dokon\u010dit Button.cancel=Storno LocaleUtil.title=Vyberte k\u00f3dov\u00e1n\u00ed LocaleUtil.section.chooseencoding=Vyberte k\u00f3dov\u00e1n\u00ed pro soubor LocaleUtil.label.chooseencoding=Vyberte k\u00f3dov\u00e1n\u00ed, kter\u00e9 nejv\u00edce odpov\u00edd\u00e1 LocaleUtil.label.hint.doubleclick=Tip: Poklep\u00e1n\u00ed na \u0159\u00e1dek vybere k\u00f3dov\u00e1n\u00ed a zav\u0159e dialog LocaleUtil.label.checkbox.rememberdecision=Pamatovat nastaven\u00ed pro ostatn\u00ed soubory LocaleUtil.column.encoding=K\u00f3dov\u00e1n\u00ed IrcClient.defaultChannel=#Azureus-U\u017eivatel\u00e9 IrcClient.copyright=Vuze pou\u017e\u00edv\u00e1 PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=P\u0159ipojov\u00e1n\u00ed k IrcClient.connected=P\u0159ipojeno k IrcClient.joining=Otev\u00edr\u00e1n\u00ed kan\u00e1lu IrcClient.channel=Kan\u00e1l IrcClient.joined=otev\u0159en IrcClient.error=Chyba IrcClient.hasjoined=vstoupil IrcClient.haskicked=byl vyhozen IrcClient.hasleft=ode\u0161el IrcClient.nowknown=je nyn\u00ed zn\u00e1m jako IrcClient.topicforchannel=T\u00e9ma pro kan\u00e1l IrcClient.disconnected=Odpojeno od IrcClient.noNick=P\u0159ezd\u00edvka nen\u00ed nastavena. Pou\u017eijte 'Nastaven\u00ed' IrcView.actionnotsupported=Tato akce nen\u00ed podporov\u00e1na IrcView.clientsconnected=u\u017eivatel\u016f IrcView.privateto=Pro IrcView.privatefrom=Od IrcView.noticefrom=Ozn\u00e1men\u00ed : IrcView.errormsg=\u0160patn\u00e1 syntaxe /msg : /msg u\u017eivatel zpr\u00e1va IrcView.help=Pou\u017eiteln\u00e9 p\u0159\u00edkazy jsou :\n . /help : zobraz\u00ed tuto n\u00e1pov\u011bdu\n . /nick | /name : zm\u011bn\u00ed va\u0161i p\u0159ezd\u00edvku \n . /me \u00fakon : po\u0161le jako \u00fakon \n . /msg u\u017eivatel zpr\u00e1va : po\u0161le privatn\u00ed zpr\u00e1vu \n . /r message : odpov\u011b\u010f na posledn\u00ed privatn\u00ed zpr\u00e1vu\n . /join #kan\u00e1l : zm\u011bnit aktu\u00e1ln\u00ed kan\u00e1l PasswordWindow.title=Vuze je uzam\u010den PasswordWindow.passwordprotected=Vuze je chr\u00e1n\u011bn heslem.\nNa zobrazen\u00ed hlavn\u00edho okna, vypl\u0148te heslo : Button.ok=OK ! TrackerChangerWindow.title=P\u0159idat Tracker TrackerChangerWindow.newtracker=Nov\u00e1 URL Trackeru PeersView.discarded=Zahozeno PeersView.discarded.info=Data, kter\u00e1 v\u00e1m byla doru\u010dena a p\u0159itom nebyla pot\u0159eba a tak byla zahozena. discarded=zahozeno MyTorrentsView.#=\u010d\u00edslo MyTorrentsView.menu.move=Posunout MyTorrentsView.menu.moveUp=&Nahoru MyTorrentsView.menu.moveDown=&Dolu GeneralView.label.hashfails=Nesouhlas\u00edc\u00ed Hash : GeneralView.label.shareRatio=Pom\u011br sd\u00edlen\u00ed : ConfigView.section.downloadManagement=Spr\u00e1vce stahov\u00e1n\u00ed ConfigView.label.startRatioPeers=Za\u010d\u00edt sd\u00edlet, kdy\u017e je m\u00e9n\u011b ne\u017e 1 zdroj na ConfigView.text.neverStop=Nikdy neukon\u010dit ConfigView.text.neverStart=Nikdy neza\u010d\u00edt ConfigView.text.peers=klient\u016f ConfigView.label.checkOncompletion=Po dokon\u010den\u00ed stahov\u00e1n\u00ed znovu zkontrolovat d\u00edly wizard.title=Vytvo\u0159it Torrent wizard.previous=< Zp\u011bt wizard.next=Dal\u0161\u00ed > wizard.finish=Dokon\u010dit wizard.mode=Tracker / M\u00f3d wizard.tracker=Tracker: wizard.invalidurl=Tato URL je neplatn\u00e1 wizard.singlefile=Jeden soubor wizard.singlefile.help=Vytvo\u0159it Torrent z jednoho souboru wizard.directory=Slo\u017eka wizard.directory.help=Vytvo\u0159it Torrent ze slo\u017eky wizard.choosefile=Vyberte soubor wizard.file=Soubor : wizard.browse=Proch\u00e1zet... wizard.choosedirectory=Vyberte slo\u017eku wizard.invalidfile=Neplatn\u00fd soubor! wizard.invaliddirectory=Neplatn\u00e1 slo\u017eka! wizard.torrentFile=Torrent soubor wizard.choosetorrent=Ulo\u017eit torrent soubor jako wizard.information=Informace wizard.notimplemented=Nen\u00ed zat\u00edm implementov\u00e1no wizard.progresstitle=Vytv\u00e1\u0159en\u00ed Torrent souboru wizard.savingfile=Ukl\u00e1d\u00e1n\u00ed souboru... wizard.filesaved=Soubor ulo\u017een. wizard.close=Zav\u0159\u00edt Torrent.create.progress.piecelength=Velikost d\u00edlu: Torrent.create.progress.piececount=Po\u010det d\u00edl\u016f: Torrent.create.progress.totalfilesize=Celkov\u00e1 velikost: Torrent.create.progress.totalfilecount=Po\u010det soubor\u016f: Torrent.create.progress.parsingfiles=Anal\u00fdza soubor\u016f Torrent.create.progress.hashing=Vytv\u00e1\u0159en\u00ed Hash MainWindow.upgrade.downloadingfrom=Stahov\u00e1n\u00ed z : MainWindow.menu.view.ipFilter=&IP filtry ConfigView.section.ipfilter=IP filtry ConfigView.section.ipfilter.description=Popis ConfigView.section.ipfilter.start=Prvn\u00ed IP ConfigView.section.ipfilter.end=Posledn\u00ed IP ConfigView.section.ipfilter.add=P\u0159idat ConfigView.section.ipfilter.remove=Odebrat ConfigView.section.ipfilter.edit=Upravit ConfigView.section.ipfilter.save=Ulo\u017eit ConfigView.section.ipfilter.editFilter=Upravit filtr ConfigView.section.ipfilter.enable=Povolit PeersView.menu.close=&Zav\u0159\u00edt seedmore.title=Torrent nen\u00ed dostate\u010dn\u011b distribuov\u00e1n seedmore.shareratio=Pom\u011br stahov\u00e1n\u00ed tohoto torrentu je seedmore.uploadmore=Pro BitTorrent s\u00ed\u0165 nen\u00ed dobr\u00e9 m\u00edt Pom\u011br sd\u00edlen\u00ed pod 100%.\nNechejte tento torrent sd\u00edlet je\u0161t\u011b chv\u00edli.\nOpravdu si p\u0159ejete torrent zastavit? ConfigView.label.showpopuponclose=Zobrazit varov\u00e1n\u00ed o nedostate\u010dn\u00e9 distribuci p\u0159i ukon\u010dov\u00e1n\u00ed torrentu, pokud m\u00e1te pom\u011br sd\u00edlen\u00ed pod 1 ConfigView.label.startNumSeeds=\nZa\u010d\u00edt sd\u00edlet, pokud je m\u00e9n\u011b ne\u017e\n - Anuluje ostatn\u00ed nastaven\u00ed ConfigView.label.seeds=zdroji ConfigView.section.seeding=Distribuce MyTorrentsView.menu.removeand=Odebrat a MyTorrentsView.menu.removeand.deletetorrent=Smazat .&torrent MyTorrentsView.menu.removeand.deletedata=Smazat &data MyTorrentsView.menu.removeand.deleteboth=Smazat .torrent &i data deletedata.title=!!! Upozorn\u011bn\u00ed !!! deletedata.message1=Chyst\u00e1te se smazat data z :\n MainWindow.menu.file.configure=Spustit Pr\u016fvodce nastaven\u00ed configureWizard.title=Pr\u016fvodce nastaven\u00ed configureWizard.welcome.title=V\u00edtejte v Pr\u016fvodci nastaven\u00ed configureWizard.welcome.message=Tento pr\u016fvodce V\u00e1m pom\u016f\u017ee nastavit Vuze pro ka\u017edodenn\u00ed pou\u017e\u00edv\u00e1n\u00ed. Podrobn\u011bj\u0161\u00ed nastaven\u00ed m\u016f\u017eete prov\u00e9st pomoc\u00ed nab\u00eddky N\u00e1stroje > Nastaven\u00ed configureWizard.transfer.title=Nastaven\u00ed p\u0159ipojen\u00ed a p\u0159enos\u016f configureWizard.transfer.hint=Tip : Nejlep\u0161\u00ed je nastavit o n\u011bco pomalej\u0161\u00ed linku, ne\u017e je Va\u0161e fyzick\u00e9 p\u0159ipojen\u00ed configureWizard.transfer.message=Vyberte zp\u016fsob p\u0159ipojen\u00ed. M\u011bjte v\u0161ak na pam\u011bti, \u017ee nepovolen\u00ed rychl\u00e9ho uploadu (odes\u00edl\u00e1n\u00ed) m\u016f\u017ee v\u00e9st k pomal\u00fdm download\u016fm (stahov\u00e1n\u00edm). Jeliko\u017e se uploady po\u010d\u00edtaj\u00ed pro ka\u017ed\u00fd torrent ZVL\u00c1\u0160\u0164, vede snaha st\u00e1hnout p\u0159\u00edli\u0161 mnoho torrent\u016f najednou tak\u00e9 k pomalej\u0161\u00edmu stahov\u00e1n\u00ed. Doporu\u010dujeme nastaven\u00ed 5KB/s jako NEJZAZ\u0160\u00cd minimum. \u010c\u00edm rychleji budete data odes\u00edlat, t\u00edm rychleji je budete i stahovat (s ohledem na rychlost torrentu). configureWizard.transfer.connection=P\u0159ipojen\u00ed configureWizard.transfer.connection.0=Vlastn\u00ed configureWizard.transfer.connection.1=Modem configureWizard.transfer.connection.2=ADSL/Kabel xxx/128 kbps configureWizard.transfer.connection.3=ADSL/Kabel xxx/256 kbps configureWizard.transfer.connection.4=ADSL/Kabel xxx/384 kbps configureWizard.transfer.connection.5=ADSL/Kabel xxx/512 kbps configureWizard.transfer.connection.6=ADSL/Kabel xxx/768 kbps configureWizard.transfer.connection.7=ADSL/Kabel xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Maxim\u00e1ln\u00ed rychlost uploadu (KB/s) configureWizard.transfer.maxActiveTorrents=Maximum aktivn\u00edch torrent\u016f configureWizard.transfer.maxDownloads=Maximum stahovan\u00fdch torrent\u016f configureWizard.transfer.maxUploadsPerTorrent=Maximum upload\u016f na torrent configureWizard.nat.title=NAT / Server Port configureWizard.nat.message=Abyste ziskali co nejv\u00edce z BitTorrent s\u00edt\u011b, m\u011bli byste b\u00fdti p\u0159istupn\u00ed z internetu. V\u00fdchoz\u00ed BitTorrent port je 6881. Tento n\u00e1stroj v\u00e1m umo\u017en\u00ed tento port zm\u011bnit a n\u00e1sledn\u011b ho otestovat. configureWizard.nat.test=Zkusit configureWizard.nat.testing=Testuji port configureWizard.nat.ok=OK! configureWizard.nat.ko=Chyba NAT configureWizard.nat.unable=Nelze otestovat: Zad\u00e1n neplatn\u00fd port nebo selhalo testov\u00e1n\u00ed.\n Port m\u016f\u017ee b\u00fdt ji\u017e pou\u017e\u00edv\u00e1n jin\u00fdm programem. configureWizard.file.title=Torrenty / Soubory configureWizard.file.message1=Vuze si bude ukl\u00e1dat v\u0161echny otev\u0159en\u00e9 torrent soubory do zde ur\u010den\u00e9 slo\u017eky: configureWizard.file.path=Cesta: configureWizard.file.browse=Proch\u00e1zet... configureWizard.file.message2=Vuze je schopn\u00fd rychle obnovit torrent a skoro okam\u017eit\u011b pokra\u010dovat v distribuci/stahov\u00e1n\u00ed. Aby tak mohl fungovat, mus\u00ed si k torrent\u016fm ukl\u00e1dat dodate\u010dn\u00e1 data. configureWizard.file.fastResume=Povolit rychl\u00e9 obnoven\u00ed configureWizard.file.invalidPath=Neplatn\u00e1 slo\u017eka! configureWizard.finish.title=Hotovo configureWizard.finish.message=Vuze je nastaven, p\u0159ejeme p\u0159ijemnou z\u00e1bavu! wizard.close.confirmation=Potvrzen\u00ed wizard.close.message=Opravdu chcete otev\u0159\u00edt tohoto pr\u016fvodce p\u0159i dal\u0161\u00edm spu\u0161t\u011bn\u00ed? exportTorrentWizard.title=Exportovat torrent do XML exportTorrentWizard.torrentfile.title=V\u00fdb\u011br torrentu exportTorrentWizard.torrentfile.message=Vyberte torrent soubor k exportu exportTorrentWizard.torrentfile.path=Cesta: exportTorrentWizard.torrentfile.browse=Proch\u00e1zet... exportTorrentWizard.torrentfile.invalidPath=Neplatn\u00fd torrent soubor exportTorrentWizard.exportfile.title=Exportovan\u00fd soubor exportTorrentWizard.exportfile.message=Vypl\u0148te n\u00e1zev exportovan\u00e9ho XML souboru exportTorrentWizard.exportfile.path=Cesta: exportTorrentWizard.exportfile.browse=Proch\u00e1zet... exportTorrentWizard.exportfile.invalidPath=Neplatn\u00fd exportovan\u00fd soubor exportTorrentWizard.finish.title=Hotovo exportTorrentWizard.finish.message=Export byl \u00fasp\u011b\u0161n\u011b dokon\u010den exportTorrentWizard.process.inputfilebad.title=Soubor torrentu je chybn\u00fd exportTorrentWizard.process.inputfilebad.message=Chyba p\u0159i \u010dten\u00ed vstupn\u00edho souboru: exportTorrentWizard.process.outputfileexists.title=Soubor existuje exportTorrentWizard.process.outputfileexists.message=V\u00fdstupn\u00ed soubor ji\u017e existuje - p\u0159epsat? exportTorrentWizard.process.torrentfail.title=Chyba p\u0159i \u010dten\u00ed torrentu exportTorrentWizard.process.exportfail.title=Chyba p\u0159i exportu torrentu exportTorrentWizard.process.unknownfail.title=Neo\u010dek\u00e1van\u00e1 chyba importTorrentWizard.title=Importovat Torrent z XML importTorrentWizard.torrentfile.title=V\u00fdb\u011br Torrentu importTorrentWizard.torrentfile.message=Vyberte torrent soubor k importu importTorrentWizard.torrentfile.path=Cesta: importTorrentWizard.torrentfile.browse=Proch\u00e1zet... importTorrentWizard.torrentfile.invalidPath=Neplatn\u00fd .torrent soubor importTorrentWizard.importfile.title=Importovan\u00fd soubor importTorrentWizard.importfile.message=Vypl\u0148te n\u00e1zev importovan\u00e9ho XML souboru importTorrentWizard.importfile.path=Cesta: importTorrentWizard.importfile.browse=Proch\u00e1zet... importTorrentWizard.importfile.invalidPath=Naplatn\u00fd importovan\u00fd soubor importTorrentWizard.finish.title=Hotovo importTorrentWizard.finish.message=Import byl \u00fasp\u011b\u0161n\u011b dokon\u010den importTorrentWizard.process.inputfilebad.title=Neplatn\u00fd soubor importu importTorrentWizard.process.inputfilebad.message=Chyba p\u0159i \u010dten\u00ed vstupn\u00edho souboru: importTorrentWizard.process.outputfileexists.title=Soubor existuje importTorrentWizard.process.outputfileexists.message=V\u00fdstupn\u00ed soubor ji\u017e existuje - p\u0159epsat? importTorrentWizard.process.torrentfail.title=Chyba p\u0159i z\u00e1pisu torrentu importTorrentWizard.process.importfail.title=Chyba p\u0159i importu torrentu importTorrentWizard.process.unknownfail.title=Neo\u010dek\u00e1van\u00e1 chyba ConfigView.label.bindip=Sv\u00e1zat s lok\u00e1ln\u00ed IP adresou or interface ConfigView.label.zeronewfiles=P\u0159i vytv\u00e1\u0159en\u00ed alokovat a vynulovat soubory ConfigView.label.zeronewfiles.tooltip=Sni\u017euje fragmentaci ConfigView.section.stats=Statistika ConfigView.section.stats.enable=Povolit ConfigView.section.stats.defaultsavepath=Slo\u017eka pro statistiky ConfigView.section.stats.choosedefaultsavepath=Vyberte slo\u017eku, kam se budou ukl\u00e1dat statistick\u00e9 informace ConfigView.section.stats.savefreq=Frekvence ukl\u00e1d\u00e1n\u00ed ConfigView.section.stats.minutes=min ConfigView.section.stats.hours=hod ConfigView.section.stats.savefile=Jm\u00e9no souboru se statistikami MyTorrentsView.menu.export=&Exportovat do XML... MyTorrentsView.menu.host=&Hostovat... ManagerItem.finishing=Dokon\u010dov\u00e1n\u00ed ConfigView.dialog.choosedefaulttorrentpath=Vyberte v\u00fdchoz\u00ed slo\u017eku pro torrent soubory ConfigView.dialog.choosemovepath=Vyberte slo\u017eku, kam chcete slo\u017eku p\u0159esunout ConfigView.label.movecompleted=P\u0159esouvat dokon\u010den\u00e9 soubory do jin\u00e9 slo\u017eky ConfigView.label.moveremoved=P\u0159esunout dokon\u010den\u00e9 soubory (p\u0159i odstran\u011bn\u00ed) ConfigView.label.savetorrents=Ukl\u00e1dat .torrent soubory MainWindow.menu.view.mytracker=M\u016fj &Servr MyTrackerView.title.full=M\u016fj server MyTrackerView.name=N\u00e1zev MyTrackerView.tracker=Server MyTrackerView.status=Stav MyTrackerView.status.started=B\u011b\u017e\u00ed MyTrackerView.status.stopped=Zastaveno MyTrackerView.peers=Klienti MyTrackerView.seeds=Zdroje MyTrackerView.announces=Ozn\u00e1men\u00ed MyTrackerView.uploaded=Odesl\u00e1no MyTrackerView.downloaded=Sta\u017eeno MyTrackerView.left=Zb\u00fdv\u00e1 ConfigView.section.style=Rozhran\u00ed ConfigView.label.set_ui_transfer_speeds=P\u0159epsat vybrateln\u00e9 p\u0159enosov\u00e9 rychlosti ConfigView.label.set_ui_transfer_speeds.description=M\u016f\u017eete si vybrat manu\u00e1ln\u011b definovat v\u00fdchoz\u00ed rychlost stahov\u00e1n\u00ed a odes\u00edl\u00e1n\u00ed dostupn\u00e9 na stavov\u00e9m \u0159\u00e1dku na syst\u00e9mov\u00e9 li\u0161t\u011b\n Hodnoty mus\u00ed b\u00fdt odd\u011bleny \u010d\u00e1rkou (",") ConfigView.section.style.useCustomTabs=Pou\u017e\u00edvat zav\u00edrateln\u00e9 z\u00e1lo\u017eky (vy\u017eaduje restart programu) MainWindow.menu.view.plugins=&Dopl\u0148ky fileDownloadWindow.saveTorrentIn=Ulo\u017eit Torrent do souboru fileDownloadWindow.title=Vuze - Stahov\u00e1n\u00ed torrentu fileDownloadWindow.downloading=Stahovan\u00ed od : fileDownloadWindow.status=Stav : fileDownloadWindow.state_initializing=Inicializace fileDownloadWindow.state_downloading=Stahov\u00e1n\u00ed fileDownloadWindow.state_error=Chyba : MainWindow.menu.file.open.url=&URL openUrl.title=Vuze - Otev\u0159\u00edt URL openUrl.url=URL : MyTorrentsView.menu.host.error.title=Hostv\u00e1n\u00ed torrentu se nepoda\u0159ilo MyTorrentsView.menu.host.error.message=P\u0159i hostov\u00e1n\u00ed torrentu nastala n\u00e1sleduj\u00edc\u00ed chyba ConfigView.section.tracker=Server ConfigView.section.tracker.pollinterval=Interval mezi dotazy klienta trackeru (sec) ConfigView.section.tracker.publishenable=Publikovat detaily o Torrentech do "" ConfigView.section.tracker.ip=Ve\u0159ejn\u00e1 IP adresa trackeru ConfigView.section.style.enableXPStyle=Povolit XP styl (vy\u017eaduje restart programu) IPChecker.external.service.dyndns.description=Dynamick\u00fd DNS S\u00ed\u0165 srvis, LLC ConfigView.section.tracker.checkip=Zjistit ve\u0159ejnou IP adresu... ipCheckerWizard.title=Pr\u016fvodce kontrolou IP adresy ipCheckerWizard.service=Slu\u017eba ipCheckerWizard.chooseService=Vyberte slu\u017ebu, kter\u00e1 bude pou\u017eita ke kontrole IP adresy ipCheckerWizard.explanations=Tento pr\u016fvodce V\u00e1m pom\u016f\u017ee zjistit Va\u0161i ve\u0159ejnou IP adresu. Pokud m\u00e1te dynamickou IP adresu, doporu\u010dujeme V\u00e1m zalo\u017eit si \u00fa\u010det u n\u011bkter\u00e9 spole\u010dnosti poskytuj\u00edc\u00ed dynamick\u00e9 DNS z\u00e1znamy. Na pomoc je zde seznam n\u011bkolika spole\u010dnost\u00ed s odkazy, kde si takovou slu\u017ebu m\u016f\u017eete z\u0159\u00eddit (pokud tuto slu\u017ebu nab\u00edz\u00ed). Pot\u00e9 vypl\u0148te pole IP adresy va\u0161\u00edm dynamick\u00fdm DNS z\u00e1znamem (nap\u0159.: mujnazev.dyndns.org). Aby se DNS z\u00e1znam automaticky aktualizoval, budete pot\u0159ebovat program, kter\u00fd poskutovatel slu\u017eby dod\u00e1v\u00e1. T\u00edmto zp\u016fsobem budete schopni provozovat Tracker, i kdy\u017e se Va\u0161e IP adresa zm\u011bn\u00ed. ipCheckerWizard.service.description=Popis : ipCheckerWizard.service.url=Odkaz : ipCheckerWizard.progresstitle=Kontrola IP adresy ipCheckerWizard.checkComplete=Zji\u0161t\u011bn\u00e1 IP adresa : ipCheckerWizard.checkFailed=Chyba : wizard.tracker.local=Pou\u017e\u00edvat vestav\u011bn\u00fd Tracker wizard.tracker.external=Pou\u017e\u00edvat ve\u0159ejn\u00fd Tracker wizard.tracker.howToLocal=\tK povolen\u00ed pou\u017eijte dialog 'Nastaven\u00ed>Tracker' wizard.announceUrl=Oznamovac\u00ed URL : IPChecker.external.service.discoveryvip.name=Objeven\u00ed VIP IPChecker.external.service.discoveryvip.description=Objeven\u00ed VIP - Pouze zji\u0161t\u011bn\u00ed IP adresy IPChecker.external.httpinvalidresponse=Neplatn\u00e1 odezva HTTP IPChecker.external.loadingwebpage=Na\u010d\u00edt\u00e1n\u00ed str\u00e1nky IPChecker.external.analysingresponse=Anal\u00fdza odpov\u011bdi IPChecker.external.addressextracted=Nalezen\u00e1 IP adresa IPChecker.external.httploadfail=Nepoda\u0159ilo se na\u010d\u00edst str\u00e1nku IPChecker.external.timeout=Vypr\u0161el \u010dasov\u00fd limit IPChecker.external.ipnotfound=IP adresa nenalezena ConfigView.section.tracker.pollintervalincby=Zvy\u0161ovat o ConfigView.section.tracker.pollintervalincper=Ka\u017ed\u00fdch 'n' klient\u016f splash.loadingImages=Na\u010d\u00edt\u00e1n\u00ed obr\u00e1zk\u016f splash.initializeGui=Inicializace hlavn\u00edho okna splash.openViews=Otev\u00edr\u00e1n\u00ed z\u00e1lo\u017eek splash.plugin=Na\u010d\u00edt\u00e1n\u00ed dopl\u0148ku : configureWizard.nat.tooManyPorts=P\u0159\u00edli\u0161 mnoho port\u016f na testov\u00e1n\u00ed (maxim\u00e1ln\u011b 9) ConfigView.section.color=Barevn\u00e9 sch\u00e9ma MyTorrentsView.menu.publish=Publikovat... MyTrackerView.status.published=Publikov\u00e1n MyTrackerView.completed=Dokon\u010den\u00ed MainWindow.menu.file.open.torrentnodefault=.torrent soubor (Nestahovat do v\u00fdchoz\u00ed slo\u017eky) wizard.comment=Koment\u00e1\u0159 ConfigView.label.movetorrent=P\u0159esunout i .torrent ConfigView.label.movepartialdownloads=Move when some files are flagged "Do Not Download" ConfigView.section.file.decoder.label=V\u00fdchoz\u00ed k\u00f3dov\u00e1n\u00ed .torrent souboru, pokud je pot\u0159eba vybrat ConfigView.section.file.decoder.nodecoder=\u017d\u00e1dn\u00e9 IPChecker.external.service.no-ip.name=No-IP IPChecker.external.service.no-ip.url=http://www.no-ip.com/ IPChecker.external.service.no-ip.description=Poskytovatel dynamick\u00e9ho a statick\u00e9ho DNS\n(nepodporuje voln\u011b slu\u017ebu zji\u0161t\u011bn\u00ed adresy) ConfigView.section.tracker.publicenable=Povolit ve\u0159ejn\u00e9 torrenty ConfigView.label.playdownloadspeech=Ozn\u00e1mit, kdy je download (stahov\u00e1n\u00ed) ukon\u010den ConfigView.label.playdownloadspeech.info=Hovorov\u00e9 slu\u017eby pracuji jen v anglick\u00e9m jazyce # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Zobrazuje po\u010det dostupn\u00fdch kopi\u00ed ka\u017ed\u00e9ho d\u00edlu.\nPokud je \u010d\u00edslo vpravo men\u0161\u00ed ne\u017e 1, nejsou dostupn\u00e9 v\u0161echny d\u00edly souboru (a m\u016f\u017eete m\u00edt probl\u00e9m dokon\u010dit stahov\u00e1n\u00ed) GeneralView.label.trackerurl.tooltip=Kliknut\u00edm zkop\u00edrujete Oznamovac\u00ed URL do schr\u00e1nky GeneralView.label.trackerurlopen.tooltip=Kliknut\u00edm otev\u0159ete hlavn\u00ed str\u00e1nku serveru # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Aktualizovat UI (u\u017eivatelsk\u00e9 rozhran\u00ed) ka\u017ed\u00fdch ConfigView.section.style.graphicsUpdate=Aktualizovat grafy ka\u017ed\u00fdch N aktualizac\u00ed UI ConfigView.section.style.reOrderDelay=Se\u0159azovat tabulky ka\u017ed\u00fdch N aktualizac\u00ed UI [0: zak\u00e1zano] ConfigView.section.style.reOrderDelay.never=Nikdy ConfigView.section.logging=Protokoly ConfigView.section.logging.enable=Zapisovat protokoly do souboru ConfigView.section.logging.logdir=Slo\u017eka s protokoly ConfigView.section.logging.choosedefaultsavepath=Vyberte slo\u017eku pro ulo\u017een\u00ed GeneralView.label.updatein.querying=dotazov\u00e1n\u00ed... configureWizard.nat.sharePort=Pou\u017e\u00edvat jeden sd\u00edlen\u00fd port pro v\u0161echny torrenty ConfigView.section.logging.maxsize=Max. velikost souboru protokolu ConfigView.section.tracker.passwordenableweb=Povolit u\u017e\u00edv\u00e1n\u00ed hesel na trackeru ConfigView.section.tracker.passwordenabletorrent=Povolit u\u017e\u00edv\u00e1n\u00ed hesel na torrentech ConfigView.section.tracker.username=U\u017eivatelsk\u00e9 jm\u00e9no ConfigView.section.tracker.password=Heslo columnChooser.title=Zobrazovan\u00e9 sloupce columnChooser.move=Po\u0159ad\u00ed sloupc\u016f zm\u011bn\u00edte p\u0159eta\u017een\u00edm polo\u017eek columnChooser.apply=Pou\u017e\u00edt columnChooser.columnname=N\u00e1zev sloupce columnChooser.columndescription=Popis TableColumn.header.shareRatio=Pom\u011br sd\u00edlen\u00ed MyTorrentsView.menu.editTableColumns=Nastaven\u00ed sloupc\u016f wizard.operationfailed=Operace se nezda\u0159ila authenticator.title=Po\u017eadov\u00e1na autentizace authenticator.realm=Oblast authenticator.tracker=Server authenticator.user=U\u017eivatelsk\u00e9 jm\u00e9no authenticator.password=Heslo ConfigView.label.allowSendVersion=P\u0159i kontrole nov\u00e9 verze povolit anonymn\u00ed odes\u00edl\u00e1n\u00ed \u010d\u00edsla verze Azurea a n\u00e1hodn\u00e9ho ID. wizard.hint.mode=Tip:\tSoubor nebo slo\u017eku m\u016f\u017eete vybrat i jejich p\u0159eta\u017een\u00edm\n\t(Drag and Drop) na toto okno wizard.hint.file=Tip:\tSoubor lze vybrat i jeho p\u0159eta\u017een\u00edm na toto okno wizard.hint.directory=Tip:\tSlo\u017eku lze vybrat i jej\u00edm p\u0159eta\u017een\u00edm na toto okno MainWindow.menu.help.checkupdate=&Kontrola nov\u00e9 verze TableColumn.header.down=P\u0159ijato TableColumn.header.up=Odesl\u00e1no ConfigView.section.tracker.passwordenabletorrent.info=Vy\u017eaduje podporu BitTorrent klientem (nap\u0159.: Vuze ConfigView.section.style.confirmationOnExit=Potvrzovat ukon\u010den\u00ed programu MainWindow.dialog.exitconfirmation.title=Ukon\u010dit Azurea? MainWindow.dialog.exitconfirmation.text=Opravdu chcete ukon\u010dit Azurea? SystemTray.menu.stopalltransfers=Zastavit &v\u0161echny p\u0159enosy TrayWindow.menu.stopalldownloads=Zastavit v\u0161echny Torrenty ConfigView.section.tracker.sslport.info=Pro v\u00edce informac\u00ed nahl\u00e9dn\u011bte do FAQ wizard.tracker.ssl=Pou\u017e\u00edvat SSL ConfigView.label.playdownloadfinished=P\u0159ehr\u00e1t zvuk p\u0159i dokon\u010den\u00ed stahov\u00e1n\u00ed ConfigView.label.popupdownloadfinished=Varov\u00e1n\u00ed vysko\u010d\u00ed, kdy\u017e je dokon\u010deno stahov\u00e1n\u00ed torrentu ConfigView.label.popupfilefinished=Varov\u00e1n\u00ed vysko\u010d\u00ed, kdy\u017e je dokon\u010deno stahov\u00e1n\u00ed souboru TableColumn.header.pieces=D\u00edly TableColumn.header.pieces.info=Grafick\u00e1 reprezentace informace o sta\u017een\u00fdch d\u00edlech TableColumn.header.completion=Dokon\u010deno TableColumn.header.completion.info=Grafick\u00e1 presentace kolik % m\u00e1te sta\u017eeno ConfigView.section.style.showdownloadbasket=Zobrazit T\u00e1hni a spus\u0165 c\u00edl pro .torrent soubory ConfigView.section.style.alwaysShowTorrentFiles=V\u017edy zobrazovat seznam soubor\u016f v okn\u011b Detaily/Soubory wizard.multitracker=K Torrentu p\u0159idat informaci o V\u00edcen\u00e1sobn\u00e9m -Trackeru wizard.multitracker.title=V\u00edcen\u00e1sobn\u00fd -Tracker wizard.multitracker.configuration=Nastaven\u00ed V\u00edcen\u00e1sobn\u00e9ho -Trackeru wizard.multitracker.new=Nov\u00fd... wizard.multitracker.edit=Upravit... wizard.multitracker.delete=Smazat wizard.multitracker.group=Skupina Tracker\u016f wizard.multitracker.edit.title=Editor Multi-Trackeru wizard.multitracker.edit.name=N\u00e1zev wizard.multitracker.edit.save=Ulo\u017eit wizard.multitracker.edit.newgroup=Nov\u00e1 skupina wizard.multitracker.edit.deletegroup=Smazat wizard.multitracker.edit.newtracker=Nov\u00fd Tracker wizard.multitracker.edit.deletetracker=Smazat wizard.multitracker.edit.edit=Upravit wizard.addingmt=P\u0159id\u00e1v\u00e1n\u00ed informac\u00ed o Multi-Trackeru wizard.multitracker.noannounce=Oznamovac\u00ed URL nen\u00ed p\u0159\u00edtomna ve va\u0161em seznamu Tracker\u016f MyTorrentsView.menu.recheck=P\u0159ekontrolovat iconBar.showDownloadBar.tooltip=Zobrazit Informa\u010dn\u00ed prou\u017eek iconBar.start.tooltip=Start iconBar.stop.tooltip=Stop iconBar.remove.tooltip=Odebrat iconBar.openNoDefault.tooltip=Otev\u0159\u00edt .torrent soubor (Nestahovat do v\u00fdchoz\u00ed slo\u017eky) iconBar.openURL.tooltip=Otev\u0159\u00edt URL iconBar.openFolder.tooltip=Otev\u0159\u00edt slo\u017eku iconBar.new.tooltip=Vytvo\u0159it Torrent iconBar.up.tooltip=Posunout nahoru iconBar.down.tooltip=Posunout dol\u016f iconBar.run.tooltip=Otev\u0159\u00edt iconBar.host.tooltip=Hostovat iconBar.publish.tooltip=Publikovat MyTorrentsView.menu.editTracker=Zm\u011bnit URL Trackeru/\u016f GeneralView.menu.selectTracker=Vybrat ConfigView.section.stats.xslfile=Jm\u00e9no XSL souboru ConfigView.section.stats.xslfiledetails=Toto bude obsa\u017eeno v souboru se stastistikami pomoc\u00ed tagu ConfigView.label.savetorrentbackup=Vytv\u00e1\u0159et z\u00e1lohy ConfigView.section.tracker.forceport=Donutit extern\u00ed torrenty pou\u017e\u00edvat v\u00fdchoz\u00ed port ConfigView.section.ipfilter.allow=POVOLIT pouze tyto IP adresy (norm\u00e1ln\u011b jsou tyto ZAK\u00c1Z\u00c1NY) ConfigView.section.ipfilter.list.inrange=byla v rozsahu ConfigView.section.ipfilter.list.notinrange=nebyla v \u017e\u00e1dn\u00e9m rozsahu ConfigView.section.ipfilter.list.title=Seznam zablokovan\u00fdch IP adres ConfigView.label.allowsameip=Povolit v\u00edce p\u0159ipojen\u00ed z jedn\u00e9 IP adresy ConfigView.label.allowsameip.tooltip=Zapn\u011bte pouze pokud to OPRAVDU pot\u0159ebujete.\nSlou\u017e\u00ed jako ochrana proti podvodn\u00edk\u016fm (kdy\u017e je vypnuto). ManagerItem.superseeding=Super-Distribuce ConfigView.label.userSuperSeeding=Pou\u017e\u00edvat superdistribuci (Superseeding) PeersView.uniquepiece=D\u00edl (m\u00f3d Superdistribuce) PeersView.uniquepiece.none=\u017d\u00e1dn\u00fd PeersView.timetosend=\u010cas do znovuzasl\u00e1n\u00ed d\u00edlu (m\u00f3d Superdistribuce) ConfigView.section.style.addurlsilently=Otev\u00edrat URL bez dialogu ConfigView.section.style.addurlsilently.tooltip=Automaticky stahovat URL adresy p\u0159i\u0161l\u00fdch torrent\u016f bez otev\u00edr\u00e1n\u00ed potvrzovac\u00edho dialogov\u00e9ho okna ConfigView.section.file.decoder.prompt=V\u017edy, kdy je mo\u017en\u00e9, zeptat se na k\u00f3dov\u00e1n\u00ed ConfigView.section.file.decoder.prompt.tooltip=Poka\u017ed\u00e9, kdy je mo\u017en\u00e9 vybrat k\u00f3dov\u00e1n\u00ed, bude zobrazen dialog s jeho v\u00fdb\u011brem MyTorrentsView.menu.moveTop=Nej&v\u00fd\u0161e MyTorrentsView.menu.moveEnd=Nej&n\u00ed\u017ee ConfigView.label.moveonlyusingdefaultsave=pouze z v\u00fdchoz\u00ed slo\u017eky ConfigView.label.moveonlyusingdefaultsave.tooltip=P\u0159esunout pouze pokud jsou sta\u017een\u00e1 data ve v\u00fdchoz\u00ed slo\u017ece ConfigView.label.watchtorrentfolder=Automaticky p\u0159id\u00e1vat nov\u00e9 torrenty ze slo\u017eky ConfigView.label.watchtorrentfolder.tooltip=Pravideln\u011b kontroluje slo\u017eku na p\u0159itomnost nov\u00fdch .torrent soubor\u016f ConfigView.label.watchtorrentfolderinterval=Interval ConfigView.label.watchtorrentfolderinterval.tooltip=Prodleva mezi kontrolami slo\u017eky na nov\u00e9 torrenty ConfigView.dialog.choosewatchtorrentfolderpath=Vyberte kontrolovanou slo\u017eku na .torrent soubory ConfigView.label.startwatchedtorrentsstopped=P\u0159idat zastaven\u00e9 ConfigView.label.startwatchedtorrentsstopped.tooltip=P\u0159id\u00e1 nov\u00e9 Torrenty v ZASTAVEN\u00c9M stavu ConfigView.section.plugins=Dopl\u0148ky wizard.maketorrent.filesize=Velikost souboru/\u016f wizard.maketorrent.piececount=Po\u010det d\u00edl\u016f wizard.maketorrent.piecesize=Velikost d\u00edlu wizard.maketorrent.auto=Auto MainWindow.menu.view.stats=Statistiky SpeedView.title.full=Aktivita SpeedView.downloadSpeed.title=Rychlost downloadu SpeedView.uploadSpeed.title=Rychlost stahov\u00e1n\u00ed ConfigView.section.style.useSIUnits=Pou\u017e\u00edvat jednotky soustavy SI (KB -> KiB, atd.) iconBar.top.tooltip=P\u0159esunout \u00fapln\u011b nahoru iconBar.bottom.tooltip=P\u0159esunout \u00fapln\u011b dol\u016f TableColumn.header.health=Zdrav\u00ed MyTorrentsView.menu.health=O Zdrav\u00ed Torrentu health.explain.grey=znamen\u00e1, \u017ee V\u00e1\u0161 torrent neb\u011b\u017e\u00ed (ani download, ani upload) health.explain.red=znamen\u00e1, \u017ee nejste p\u0159i stahov\u00e1n\u00ed p\u0159ipojeni k \u017e\u00e1dn\u00e9mu klientovi health.explain.blue=znamen\u00e1 p\u0159i distribuci, \u017ee nejste p\u0159ipojeni k \u017e\u00e1dnemu klientovi\np\u0159i stahov\u00e1n\u00ed znamen\u00e1, \u017ee jste p\u0159ipojeni k n\u011bjak\u00fdm klient\u016fm, ale Tracker nen\u00ed dostupn\u00fd health.explain.yellow=znamen\u00e1, \u017ee Tracker je v po\u0159\u00e1dku, jste p\u0159ipojen ke klient\u016fm, ale neexistuje \u017eadn\u00e9 p\u0159ipojen\u00ed zven\u010d\u00ed.\nPokud st\u00e1le vid\u00edte tuto \u017elutou u Va\u0161ich Torrent\u016f, pak nejsp\u00ed\u0161 m\u00e1te probl\u00e9my s NAT health.explain.green=znamen\u00e1, \u017ee v\u0161e je v po\u0159\u00e1dku ConfigView.section.style.alwaysRefreshMyTorrents=Neust\u00e1le obnovovat Moje Torrenty ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Obnovovat okno Moje Torrenty, i kdy\u017e nen\u00ed zobrazeno (pro n\u011bkter\u00e9 dopl\u0148ky mIrc) # #2.0.7.0 # security.certtruster.title=Varov\u00e1n\u00ed bezpe\u010dnostn\u00edho certifik\u00e1tu security.certtruster.intro=Certifik\u00e1t byl vyd\u00e1n spole\u010dnost\u00ed, kter\u00e9 jste se rozhodli ned\u016fv\u011b\u0159ovat security.certtruster.resource=Zdroj: security.certtruster.issuedto=Vyd\u00e1no pro: security.certtruster.issuedby=Vydal: security.certtruster.prompt=Chcete certifik\u00e1tu d\u016fv\u011b\u0159ovat? security.certtruster.yes=Ano security.certtruster.no=Ne ConfigView.section.tracker.torrentsperpage=Kolik torrent\u016f na str\u00e1nku ? [0: neomezen\u011b] MainWindow.menu.file.share=Sd\u00edlet MainWindow.menu.file.share.file=&Soubor... MainWindow.menu.file.share.dir=S&lo\u017eku... MainWindow.menu.file.share.dircontents=&Obsah slo\u017eky... MainWindow.menu.file.share.dircontentsrecursive=Obsah slo\u017eky (&Rekurzivn\u011b)... MainWindow.dialog.share.sharefile=Vyberte soubor ke sd\u00edlen\u00ed MainWindow.dialog.share.sharedir=Vyberte slo\u017eku ke sd\u00edlen\u00ed MainWindow.dialog.share.sharedircontents=Vyberte slo\u017eku, jej\u00ed\u017e obsah bude sd\u00edlen MainWindow.dialog.share.sharedircontents.recursive=Rekurzivn\u011b globalmanager.download.remove.veto=Odebr\u00e1n\u00ed zam\u00edtnuto plugin.sharing.download.remove.veto=Tato polo\u017eka vznikla sd\u00edlen\u00edm.\nK odebr\u00e1n\u00ed polo\u017eky je pot\u0159eba odebrat p\u0159idru\u017een\u00e9 sd\u00edlen\u00ed: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Hlavn\u00ed ConfigView.label.prioritizefirstpiece=V\u011bt\u0161\u00ed priorita pro prvn\u00ed a posledn\u00ed d\u00edly soubor\u016f ConfigView.label.prioritizefirstpiece.tooltip=Vuze se pokus\u00ed st\u00e1hnout za\u010d\u00e1tek souboru jako prvn\u00ed.\nUmo\u017en\u00ed rychl\u00e9 ov\u011b\u0159en\u00ed a n\u00e1hled. ConfigView.section.file.confirm_data_delete=Potvrzovat maz\u00e1n\u00ed dat ConfigView.section.file.confirm_data_delete.tooltip=Vy\u017eadovat potvrzen\u00ed akce p\u0159i pou\u017eit\u00ed "Odebrat a smazat ..." TrayWindow.menu.startalldownloads=Spustit v\u0161echny Torrenty SystemTray.menu.startalltransfers=Spustit v\u0161echny p\u0159enosy sharing.progress.title=Proces sd\u00edlen\u00ed sharing.progress.hide=Skr\u00fdt MainWindow.menu.view.myshares=M\u00e1 Sd\u00edlen\u00ed MySharesView.title.full=M\u00e1 Sd\u00edlen\u00ed MySharesView.name=N\u00e1zev MySharesView.type=Typ MySharesView.type.file=Soubor MySharesView.type.dir=Slo\u017eka MySharesView.type.dircontents=Obsah slo\u017eky MySharesView.type.dircontentsrecursive=Obsah slo\u017eky (rekurzivn\u011b) MySharesView.menu.remove=Odebrat ConfigView.section.tracker.extensions=Roz\u0161\u00ed\u0159en\u00ed ConfigView.section.tracker.sendpeerids=Pos\u00edlat klient\u016fm jejich ozna\u010den\u00ed (identitu) ConfigView.section.tracker.enableudp=Povolit UDP Tracker Protokol plugin.sharing.torrent.remove.veto=Tato polo\u017eka Trackeru vznikla sd\u00edlen\u00edm.\nK odebr\u00e1n\u00ed polo\u017eky je pot\u0159eba odebrat p\u0159idru\u017een\u00e9 sd\u00edlen\u00ed: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Torrent nem\u016f\u017ee b\u00fdt odebr\u00e1n, proto\u017ee nen\u00ed zastaven plugin.sharing.remove.veto=Tato sd\u00edlen\u00e1 polo\u017eka je v\u00fdsledek "Sd\u00edlen\u00e9 slo\u017eky" a nem\u016f\u017ee b\u00fdt samostatn\u011b odstran\u011bna.\n Odeberte ko\u0159enovou slo\u017eku GeneralView.label.hash.tooltip=Kliknut\u00edm zkop\u00edrujete Hash do schr\u00e1nky ConfigView.section.tracker.maxpeersreturned=Maxim\u00e1ln\u00ed po\u010det vr\u00e1cen\u00fdch klient\u016f [0: neomezen\u011b] ConfigView.label.serverport=P\u0159\u00edchoz\u00ed TCP port ConfigView.label.serverport.tooltip=Port mus\u00ed b\u00fdt v rozsahu 1-65535, ne 6880 ten je rezervovan\u00fd pro vnit\u0159n\u00ed pot\u0159ebul Azurea. configureWizard.nat.server.tcp_listen_port=P\u0159\u00edchoz\u00ed naslouchan\u00fd TCP port ConfigView.section.sharing=Sd\u00edlen\u00ed ConfigView.section.sharing.usessl=Pro sd\u00edlen\u00e9 soubory pou\u017e\u00edvat SSL (vy\u017eaduje nastaven\u00ed Trackeru) ConfigView.section.style.dropdiraction=P\u0159eta\u017een\u00ed (T\u00e1hni a spus\u0165) slo\u017eky ConfigView.section.style.dropdiraction.opentorrents=Otev\u0159e torrenty ConfigView.section.style.dropdiraction.sharefolder=Nasd\u00edl\u00ed slo\u017eku ConfigView.section.style.dropdiraction.sharefoldercontents=Nasd\u00edl\u00ed obsah slo\u017eky # # 2.0.7.x # Categories.all=V\u0161e Categories.uncategorized=Neza\u0159azen\u00e9 CategoryAddWindow.message=Jm\u00e9no nov\u00e9 kategorie CategoryAddWindow.title=P\u0159idat novou kategorii ConfigView.label.autoSeedingIgnoreInfo=Ignorovan\u00e9 torrenty jdou nakonec distribu\u010dn\u00ed fronty a nejsou automaticky spu\u0161t\u011bny. Pravidla ignorov\u00e1n\u00ed se nevztahuj\u00ed na torrenty, pro kter\u00e9 plat\u00ed pravidla top priority. Pokud nen\u00ed ud\u00e1no jinak, pak hodnota 0 znamen\u00e1 vypnut\u00ed pravidla. ConfigView.label.directory=Slo\u017eka ConfigView.label.disconnetseed.tooltip=P\u0159i distribuci odpojit v\u0161echny distribuj\u00edc\u00ed klienty.\nNen\u00ed nutn\u00e9 b\u00fdt s nimi v kontaktu (ni\u017e\u0161\u00ed p\u0159enos dat). ConfigView.label.ignoreCase=Ignorovat velikost p\u00edsmen ConfigView.label.ignoreSeeds=Ignorovat torrenty a alespo\u0148 ConfigView.label.importdirectory=Slo\u017eka importu ConfigView.label.minPeersToBoostNoSeeds.tooltip=Jak\u00fdkoliv torrent bez zdroj\u016f maj\u00edc\u00ed m\u00e9n\u011b stahuj\u00edc\u00edch ne\u017e nastav\u00edte,\nbude posunut na konec fronty. ConfigView.label.minPeersToBoostNoSeeds=Ni\u017e\u0161\u00ed hodnocen\u00ed pro torrenty bez zdroj\u016f nebo s m\u00e9n\u011b ne\u017e ConfigView.label.minSeedingTime.tooltip=Hodnocen\u00ed se m\u016f\u017ee \u010dasto v kr\u00e1tk\u00fdch intervalech m\u011bnit; n\u011bkdy jsou torrenty spu\u0161t\u011bny, jen aby se z\u00e1hy zase ukon\u010dily a byly zp\u011bt za\u0159azeny do fronty.\nToto nastaven\u00ed obch\u00e1z\u00ed probl\u00e9m donucen\u00edm torrent\u016f z\u016fstat v distribuci po nastaven\u00fd \u010das.\nPokud chcete, m\u016f\u017eete torrent kdykoliv zastavit ru\u010dn\u011b. ConfigView.label.minSeedingTime=Minim\u00e1ln\u00ed \u010das distribuce v sekund\u00e1ch ConfigView.label.minSpeedForActiveDL.tooltip=Prvn\u00edch 30 sekund je ka\u017ed\u00fd nedokon\u010den\u00fd torrent pova\u017eov\u00e1n za stahuj\u00edc\u00ed ConfigView.label.minSpeedForActiveDL=Rychlost stahov\u00e1n\u00ed, pod kterou se nepo\u010d\u00edt\u00e1 torrent jako aktivn\u011b stahuj\u00edc\u00ed ConfigView.label.peers=klient\u016f ConfigView.label.queue.debuglog=Zapisovat informace o lad\u011bn\u00ed programu ConfigView.label.queue.debuglog.info=P\u0159idat seznam vyla\u010fovac\u00edch informac\u00ed do konzole/zaznamen\u00e1vac\u00edho souboru.\nA\u010dkoli zak\u00f3dovan\u011b, ladic\u00ed informace ud\u00e1v\u00e1j\u00ed stav torrent\u016f a pro\u010d byly/nebyly \u010di spu\u0161t\u011bny/za\u0159azeny do fronty. ConfigView.label.queue.minQueueingShareRatio=Neza\u0159azovat do fronty ani nezastavovat torrent, dokud pom\u011br sd\u00edlen\u00ed nedos\u00e1hne ConfigView.label.ratio=Pom\u011br ConfigView.label.removeOnStop=Jakmile je torrent zastaven, odebrat ho ze seznamu ConfigView.label.savedirectory=Slo\u017eka pro torrenty ConfigView.label.seeding.autoReposition.tooltip=Pokud je za\u0161krtnuto, je po\u0159ad\u00ed torrent\u016f (sloupec '#') upravov\u00e1no podle seeding po\u0159ad\u00ed\nPokud v\u00e1s nezaj\u00edmaj\u00ed hodnoty seeding po\u0159ad\u00ed, pak t\u00edmto zp\u016fsobem vid\u00edte, v jak\u00e9m po\u0159ad\u00ed budou dokon\u010den\u00e9 torrenty spou\u0161t\u011bny. ConfigView.label.seeding.autoReposition=Automaticky \u0159adit torrenty podle jejich hodnocen\u00ed ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u010casto torrenty s m\u00e1l\u00fdm po\u010dtem distribuuj\u00edc\u00edch a velk\u00fdm po\u010dtem stahuj\u00edc\u00edch znamenaj\u00ed, \u017ee nen\u00ed mezi klienty roz\u0161\u00ed\u0159en\u00e1 cel\u00e1 kopie souboru.\nProto nen\u00ed vhodn\u00e9 aby pravidla distribuce p\u0159edpokl\u00e1dala dal\u0161\u00ed cel\u00e9 kopie (a tak nespr\u00e1vn\u011b sni\u017eovala hodnocen\u00ed torrentu) ConfigView.label.seeding.fakeFullCopySeedStart=ale pouze pro torrenty s alespo\u0148 ConfigView.label.seeding.ignore=Ignorovat pravidla ConfigView.label.seeding.ignore0Peers=Ignorovat torrenty s 0 klienty ConfigView.label.seeding.ignoreRatioPeers=Ignorovat torrenty s alespo\u0148 1 distributorem na ConfigView.label.seeding.ignoreShareRatio=Ignorovat torrenty s pom\u011brem sd\u00edlen\u00ed ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorovat torrent, i kdy\u017e\n plat\u00ed pravidla top priority ConfigView.label.seeding.ignore.header.rule=Pravidlo ConfigView.label.seeding.ignore.header.value=Hodnota ConfigView.label.seeding.firstPriority.info=Torrenty ur\u010den\u00e9 pravidly top priority budou v\u017edy na za\u010d\u00e1tku fronty. \u017d\u00e1dn\u00fd z t\u011bchto torrent\u016f nebude automaticky zastaven a za\u0159azen zp\u011bt do fronty. Torrenty s top prioritou si t\u00e9\u017e vezmou simult\u00e1nn\u00ed slot na stahov\u00e1n\u00ed, pokud ho pot\u0159ebuj\u00ed. ConfigView.label.seeding.firstPriority.FP=Top priorita ConfigView.label.seeding.firstPriority=Top priorita plat\u00ed pro torrenty s ConfigView.label.seeding.firstPriority.following=z n\u00e1sleduj\u00edc\u00edch pravidel: ConfigView.label.seeding.firstPriority.shareRatio=Pom\u011br sd\u00edlen\u00ed pod ConfigView.label.seeding.firstPriority.seedingMinutes=\u010cas od zm\u011bny stahov\u00e1n\u00ed v distribuci ConfigView.label.seeding.firstPriority.DLMinutes=\u010cas od za\u010d\u00e1tku stahov\u00e1n\u00ed ConfigView.label.seeding.numPeersAsFullCopy.tooltip=P\u0159edpokl\u00e1d\u00e1n\u00edm existence jedn\u00e9 cel\u00e9 kopie na X klient\u016f sn\u00ed\u017e\u00edte hodnocen\u00ed torrent\u016f s velk\u00fdm po\u010dtem klient\u016f.\nTyto Torrenty pravd\u011bpodobn\u011b budou m\u00edt i velk\u00fd provoz.\nToto nastaven\u00ed nezm\u011bn\u00ed zobrazen\u00ed informace "po\u010det zdroj\u016f" ConfigView.label.seeding.numPeersAsFullCopy=P\u0159edpokl\u00e1dat existenci alespo\u0148 jedn\u00e9 cel\u00e9 kopie pro ka\u017ed\u00fdch\n(0 : nep\u0159edpokl\u00e1dat) ConfigView.label.seeding.preferLargerSwarms.tooltip=Pokud distribuujete torrenty klient\u016fm s pomal\u00fdm \u010di \u010d\u00e1ste\u010dn\u011b blokovan\u00fdm p\u0159ipojen\u00edm k internetu, pom\u016f\u017ee preferov\u00e1n\u00ed torrent\u016f s v\u011bt\u0161\u00edm po\u010dtem \u00fa\u010dastn\u00edk\u016f.\nPokud distribuujete torrenty s velkou roz\u0161\u00ed\u0159enost\u00ed d\u00edl\u016f, pak je v\u00fdhodn\u00e9 preferovat torrenty s men\u0161\u00edm po\u010dtem \u00fa\u010dastn\u00edk\u016f. ConfigView.label.seeding.preferLargerSwarms=Kdy\u017e maj\u00ed dva torrenty stejn\u00e9 hodnocen\u00ed, preferovat ten s v\u011bt\u0161\u00edm po\u010dtem \u00fa\u010dastn\u00edk\u016f ConfigView.label.seeding.rankType.none.tooltip=Po\u0159ad\u00ed zalo\u017eeno na sloupci '#' (Po\u010det) ConfigView.label.seeding.rankType.none=\u017d\u00e1dn\u00e9 ConfigView.label.seeding.rankType.peerSeed.options=Distrubuto\u0159i:stahuj\u00edc\u00ed - ukazatel mo\u017enost\u00ed ConfigView.label.seeding.rankType.peerSeed.tooltip=Vy\u0161\u0161\u00ed pom\u011br = vy\u0161\u0161\u00ed hodnocen\u00ed ConfigView.label.seeding.rankType.peerSeed=Pom\u011br stahuj\u00edc\u00ed:distributo\u0159i ConfigView.label.seeding.rankType.seed.fallback=Sn\u00ed\u017eit pom\u011br popt\u00e1vky:nab\u00eddky podle\n(0 : Nikdy nesn\u00ed\u017eit) ConfigView.label.seeding.rankType.seed.options=Po\u010det nab\u00eddky dle volby ConfigView.label.seeding.rankType.seed.tooltip=M\u00e9n\u011b distributor\u016f = vy\u0161\u0161\u00ed hodnocen\u00ed ConfigView.label.seeding.rankType.seed=Po\u010det distributor\u016f ConfigView.label.seeding.rankType.timedRotation.tooltip=V\u0161echny dokon\u010den\u00e9 torrenty ve front\u011b se budou st\u0159\u00eddat v distribuci.\n\u010cas, po kter\u00fd budou poka\u017ed\u00e9 distribuov\u00e1ny je nastaven pomoc\u00ed 'Minim\u00e1ln\u00ed \u010das distribuce' ConfigView.label.seeding.rankType.timedRotation=St\u0159\u00edd\u00e1n\u00ed po \u010dasov\u00fdch intervalech ConfigView.label.seeding.rankType.tooltip=Automaticky jsou spu\u0161t\u011bny torrenty s nejvy\u0161\u0161\u00edm ohodnocen\u00edm.\nPokud n\u011bkter\u00fd torrent dos\u00e1hne vy\u0161\u0161\u00edho hodnocen\u00ed, je ten s ni\u017e\u0161\u00edm pozastaven a vrac\u00ed se zp\u011bt do fronty.\n\nAutomatick\u00e9 spu\u0161t\u011bn\u00ed je umo\u017en\u011bno jen torrent\u016fm ve front\u011b.\nZastaven\u00e9 torrenty nejsou nikdy automaticky spu\u0161t\u011bny. ConfigView.label.seeding.rankType=Hodnocen\u00ed dokon\u010den\u00fdch torrent\u016f pro automatick\u00e9 spou\u0161t\u011bn\u00ed zalo\u017een\u00e9 na: ConfigView.label.stopAfterMinutes=Zastavit distribuci po ur\u010den\u00e9m \u010dase ConfigView.label.switchpriority.tooltip=N\u00edzk\u00e1 priorita sni\u017euje torrentu p\u0159id\u011blen\u00fd pr\u016ftok dat sm\u011brem ven ConfigView.pluginlist.info=Byly nalezeny n\u00e1sleduj\u00edc\u00ed dopl\u0148ky. N\u011bkter\u00e9 z nich nemusej\u00ed m\u00edt konfigura\u010dn\u00ed dialog. ConfigView.pluginlist.noplugins=Nebyly nalezeny \u017e\u00e1dn\u00e9 dopl\u0148ky. ConfigView.section.pluginslist=Seznam ConfigView.section.queue.seeding=Distribuce ConfigView.section.queue.seeding.autoStarting=Automatick\u00e9 spou\u0161t\u011bn\u00ed ConfigView.section.queue.seeding.ignore=Pravidla ignorov\u00e1n\u00ed ConfigView.section.queue.seeding.firstPriority=Top priorita ConfigView.section.queue.main=Hlavn\u00ed ConfigView.section.queue=Fronta ConfigView.section.torrents=Torrenty ConfigView.text.all=v\u0161emi ConfigView.text.hours=hodin ConfigView.text.ignoreRule=Ignorovat pravidlo ConfigView.text.ignore=Ignorovat ConfigView.text.minutes=minut ConfigView.text.neverIgnore=Nikdy neignorovat ConfigView.text.any=jak\u00fdmkoliv DownloadManager.error.datamissing=Chyb\u011bj\u00edc\u00ed data MainWindow.menu.file.open.torrentforseeding=.torrent soubor (pro distribuci) MainWindow.menu.language.refresh=&Obnovit ManagerItem.forced=Vynucen\u00e9 ManagerItem.queued=Ve front\u011b MySeedersView.header=Dokon\u010den\u00e9/Distribuovan\u00e9 Torrenty TableColumn.header.availability.info=Po\u010det dostupn\u00fdch kopi\u00ed TableColumn.header.availability=Dostupnost TableColumn.header.category=Kategorie MyTorrentsView.header=Nedokon\u010den\u00e9/stahovan\u00e9 torrenty TableColumn.header.maxuploads=Maximum upload\u016f MyTorrentsView.menu.category.delete=O&debrat kategorii MyTorrentsView.menu.forceStart=&Vynutit spu\u0161t\u011bn\u00ed MyTorrentsView.menu.queue=Za\u0159adit do &fronty MyTorrentsView.menu.setCategory.add=&P\u0159idat kategorii.. MyTorrentsView.menu.setCategory=Nastavit Kategorii TableColumn.header.savepath=C\u00edlov\u00e1 slo\u017eka TableColumn.header.totalspeed.info=Celkov\u00e1 rychlost klient\u016f, ke kter\u00fdm jste p\u0159ipojeni TableColumn.header.totalspeed=Celkov\u00e1 rychlost splash.initializePlugins=Inicializace Dopl\u0148k\u016f StartStopRules.SPratioMet=S:P Pom\u011br OK StartStopRules.FP0Peers=FP / 0 Stahujic\u00edch StartStopRules.0Peers=0 stahuj\u00edc\u00edch StartStopRules.numSeedsMet=Po\u010det distributor\u016f v po\u0159\u00e1dku StartStopRules.ratioMet=Pom\u011br klienti:distrubuto\u0159i v po\u0159\u00e1dku StartStopRules.shareRatioMet=Pom\u011br sd\u00edlen\u00ed OK StartStopRules.waiting=\u010cek\u00e1n\u00ed StartStopRules.firstPriority=Top Priorita ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Nasd\u00edl\u00ed obsah slo\u017eky (Rekurzivn\u011b) DownloadManager.error.unabletostartserver=Server nelze spustit - zkontrolujte nastaven\u00ed p\u0159\u00edchoz\u00edho portu / nastaven\u00ed firewallu, aby umo\u017enil aplikaci b\u00fdt serverem GeneralView.label.creationdate=Vytvo\u0159eno : ConfigView.section.tracker.announcescrapepercentage=Interval mezi Scrapy jako st\u00e1\u0159\u00ed ozn\u00e1men\u00ed\nnap\u0159. 200 = 2:1. 0 = a\u0165 rozhodne klient ManagerItem.stopping=Zastavov\u00e1n\u00ed ConfigView.section.tracker.announcecacheperiod=Ozn\u00e1mit vyrovn\u00e1vac\u00ed pam\u011bt (ms) ConfigView.section.tracker.scrapecacheperiod=Vyrovn\u00e1vac\u00ed pam\u011b\u0165 scrape (ms) ConfigView.section.tracker.scrapeandcache=Scrape a vyrovn\u00e1vac\u00ed pam\u011bt ConfigView.section.tracker.announcecacheminpeers=Povolit ozn\u00e1men\u00ed p\u0159ekro\u010den\u00ed velikosti vyrovn\u00e1vac\u00ed pam\u011bti MyTrackerView.scrapes=Scrapy fileDownloadWindow.retry=Znovu MyTrackerView.bytesin=Do (Byty) MyTrackerView.bytesinave=Do (pr\u016fm\u011br) MyTrackerView.bytesout=Ven (Byty) MyTrackerView.bytesoutave=Ven (pr\u016fm\u011br) ConfigView.section.file.max_open_files=Maximum otev\u0159en\u00fdch soubor\u016f pro \u010dten\u00ed/z\u00e1pis\n[0: neomezen\u011b] ConfigView.section.file.max_open_files.tooltip=Pou\u017eijte v p\u0159\u00edpad\u011b, \u017ee stahujete torrenty se stovkami/tis\u00edci soubory a dosahujete limit OS pro po\u010det otev\u0159en\u00fdch soubor\u016f. ConfigView.section.proxy=Mo\u017enosti proxy ConfigView.section.proxy.enable_proxy=Pou\u017e\u00edt proxy server (je t\u0159eba restartovat Vuze ConfigView.section.proxy.host=Server ConfigView.section.proxy.username=U\u017eivatelsk\u00e9 jm\u00e9no ConfigView.section.proxy.password=Heslo ConfigView.section.proxy.enable_socks=M\u00e1m SOCKS proxy server wizard.createtorrent.extrahashes=P\u0159idat hash hodnoty pro ostatn\u00ed s\u00edt\u011b (nap\u0159.: Gnutella2, eDonkey2000) GeneralView.label.connected=p\u0159ipojeno GeneralView.label.in_swarm=celkem ManagerItem.initializing=Inicializace AlertMessageBox.error=Chyba AlertMessageBox.warning=Varov\u00e1n\u00ed AlertMessageBox.comment=Informace AlertMessageBox.information=Informace SharedPortServer.alert.selectorfailed=Nepoda\u0159ilo se otev\u0159\u00edt port pro p\u0159ichoz\u00ed data.\nZkontrolujte nastaven\u00ed firewallu, zda umo\u017enuje java(w).exe jednat jako 'server' Tracker.alert.listenfail=Nepoda\u0159\u00edlo se naslouchat na portu %1.\nZkontrolujte, jestli ostatn\u00ed aplikace nepou\u017e\u00edvaj\u00ed tento port.\nT\u00e9\u017e zkontrolujte, jestli u\u017e jeden Vuze neb\u011b\u017e\u00ed. DiskManager.alert.movefileexists=Chyba p\u0159i p\u0159esunu dokon\u010den\u00fdch soubor\u016f\nSoubor %1 v c\u00edlov\u00e9 slo\u017ece ji\u017e existuje DiskManager.alert.movefilefails=Chyba p\u0159i p\u0159esunu dokon\u010den\u00fdch soubor\u016f\nP\u0159esun souboru %1 se nezda\u0159il, %2 DiskManager.alert.movefilerecoveryfails=Chyba p\u0159i obnov\u011b z nepoveden\u00e9ho p\u0159esunu\nObnova souboru %1 se nezda\u0159ila, %2 ConfigView.section.tracker.logenable=Pravideln\u011b zapisovat statistiku do 'tracker.log' SpeedView.stats.title=Statistika SpeedView.stats.total=Celkem SpeedView.stats.session=Toto spu\u0161t\u011bn\u00ed SpeedView.stats.session.tooltip=Celkov\u00fd (protocol) SpeedView.stats.downloaded=P\u0159ijato SpeedView.stats.uploaded=Odesl\u00e1no SpeedView.stats.ratio=Pom\u011br SpeedView.stats.uptime=Spu\u0161t\u011bno (hod) SpeedView.stats.now=Nyn\u00ed SpeedView.stats.now.tooltip=Celkov\u00fd (protokol) AutoMigration.useralert=V\u00fdsledky automatick\u00e9 migrace konfigura\u010dn\u00edch soubor\u016f:\n\n%1\n%2NEP\u0158ESUNUT\u00c9 SOUBORY MUS\u00cd P\u0158ESUNUTY RU\u010cN\u011a. # # > 2.0.8.0 # OpenTorrentWindow.title=Otev\u0159\u00edt Torrent(y) OpenTorrentWindow.message=Experiment\u00e1ln\u00ed OpenTorrentWindow.addFiles=&P\u0159idat soubory OpenTorrentWindow.dataLocation=Um\u00edst\u011bn\u00ed pro ulo\u017een\u00ed dat: OpenTorrentWindow.startMode=Stav OpenTorrentWindow.startMode.queued=Za\u0159adit do fronty OpenTorrentWindow.startMode.stopped=Zastaven\u00e9 OpenTorrentWindow.startMode.forceStarted=Vynucen\u00e9 spu\u0161t\u011bn\u00ed OpenTorrentWindow.addPosition=P\u0159idat do fronty OpenTorrentWindow.addPosition.first=Na za\u010d\u00e1tek OpenTorrentWindow.addPosition.last=Na konec TableColumn.header.remaining.info=Objem dat zb\u00fdvaj\u00edc\u00ed ke st\u00e1\u017een\u00ed TableColumn.header.remaining=Zb\u00fdv\u00e1 ConfigView.section.tracker.enablecompact=Pou\u017e\u00edvat kompaktn\u00ed oznamovac\u00ed protokol ConfigView.section.tracker.enablekey=Pro v\u011bt\u0161\u00ed bezpe\u010dnost pos\u00edlat trackeru kl\u00ed\u010d ConfigView.section.file.perf=Nastaven\u00ed v\u00fdkonu ConfigView.section.file.perf.explain=Varov\u00e1n\u00ed - neodborn\u00e9 zm\u011bny t\u011bchto parametr\u016f m\u016f\u017eou v\u00e1\u017ene ovlivnit v\u00fdkon stahov\u00e1n\u00ed. Po zm\u011bn\u011b je t\u0159eba program restartovat.\nPokud m\u00e1te probl\u00e9my s nedostatkem pam\u011bti, zkuste omezit po\u010det p\u0159ipojen\u00ed na torrent (v\u00edce v Nastaven\u00ed->P\u0159enos) ConfigView.section.file.max_open_files.explain=Otev\u0159en\u00ed p\u0159\u00edli\u0161 mnoha soubor\u016f m\u016f\u017ee zp\u016fsobit probl\u00e9my opera\u010dn\u00edmu syst\u00e9mu kv\u016fli nedostatku zdroj\u016f. Toto omez\u00ed po\u010det najednou otev\u0159en\u00fdch soubor\u016f. popup.error.hide=Skr\u00fdt popup.error.details=Detaily ConfigView.section.style.colorOverrides=Zm\u011bna barev ConfigView.section.style.colorOverride.progressBar=Diagram postupu ConfigView.section.style.colorOverride.error=Chyba MainWindow.status.tooOld=je moc zastaral\u00fd, pros\u00edme aktualizujte jej. ConfigView.section.style.colorOverride.warning=Varov\u00e1n\u00ed ConfigView.section.style.colorOverride.altRow=Lich\u00e9 \u0159\u00e1dky ConfigView.section.file.save.peers.enable=Ukl\u00e1dat adresy p\u0159ipojen\u00fdch klient\u016f pro rychlej\u0161\u00ed spou\u0161t\u011bn\u00ed ConfigView.section.file.save.peers.max=Maximum ulo\u017een\u00fdch klient\u016f [0: neomezen\u011b] ConfigView.section.file.save.peers.pertorrent=na torrent ConfigView.label.max_peers_per_torrent=Maximum p\u0159ipojen\u00ed na torrent [0: neomezen\u011b] ConfigView.label.max_peers_total=Celkov\u00e9 max.p\u0159ipojen\u00ed [0: neomezen\u011b] ConfigView.section.style.colorOverrides.reset=P\u016fvodn\u00ed barva ConfigView.section.language.info=Pokud je aktualizace povolena,kontrola nov\u00fdch dostupn\u00fdch verz\u00ed bude provedena p\u0159i ka\u017ed\u00e9m spu\u0161t\u011bn\u00ed Azurea. ConfigView.section.language.enableUpdate=Povolit aktualizace z internetu ConfigView.section.language.UpdateURL=URL s aktualizac\u00ed ConfigView.section.language.UpdateNow=Aktualizovat! Button.revert=Vr\u00e1tit MyTorrentsView.menu.changeDirectory=Zm\u011bnit cestu k soubor\u016fm GenericText.column=sloupec MyTorrentsView.menu.thisColumn.remove=Odebrat sloupec MyTorrentsView.menu.thisColumn.toClipboard=Kop\u00edrovat text do schr\u00e1nky TableColumn.header.secondsseeding=Doba distribuce TableColumn.header.secondsseeding.info=Doba, po kterou torrent distribuujete TableColumn.header.secondsdownloading=D\u00e9lka stahov\u00e1n\u00ed TableColumn.header.secondsdownloading.info=Doba, po kterou torrent stahujete ConfigView.section.tracker.udpversion=Verze UDP Protokolu (1 nebo 2) window.updateswt.title=Va\u0161e verze SWT knihovny je zastaral\u00e1! window.updateswt.text=Va\u0161e verze SWT knihovny je zastaral\u00e1!\nSWT je grafick\u00e1 knihovna pou\u017e\u00edvan\u00e1 programem Azureus. Tato knihovna je zastaral\u00e1 pro b\u011bh nejnov\u011bj\u0161\u00ed verze programu Azureus. Tla\u010d\u00edtkem OK aktualizujete Va\u0161\u00ed SWT knihovnu. window.updateswt.status=Stav window.updateswt.failed=Aktualizace selhala, stiskn\u011bte OK pro znovusta\u017een\u00ed. window.updateswt.status.downloading.updater=Stahov\u00e1n\u00ed Aktualiza\u010dn\u00edho modulu window.updateswt.status.finding=Hled\u00e1n\u00ed nejnov\u011bj\u0161\u00ed verze SWT window.updateswt.status.downloading=Stahov\u00e1n\u00ed nejnovej\u0161i verze SWT window.updateswt.status.done=Restartuji window.updateswt.ok=OK !! window.updateswt.cancel=Zru\u0161it swt.updater.downloader.downloading=Stahov\u00e1n\u00ed SWT z swt.updater.urlsgetter.downloading=Stahuji seznam mirror\u016f z swt.updater.urlsgetter.platform=SWT pro platformu : window.updateswt.ignore=Ignorovat ConfigView.section.style.useFancyTabs=Pou\u017e\u00edvat ozdobn\u00e9 z\u00e1lo\u017eky splash.initializeGM=Inicializace globaln\u00edho torrent mana\u017eeru splash.loadingTorrents=Na\u010d\u00edt\u00e1n\u00ed Torrent\u016f MyTorrentsView.menu.thisColumn.sort=&Se\u0159adit Scrape.status.ok=Scrape OK. Scrape.status.error=Scrape: Scrape.status.error.badURL=Oznamovac\u00ed URL neodpov\u00edd\u00e1 Scrape specifikaci. Scrape.status.error.nohash=V odpov\u011bd\u00ed chyb\u00ed hash hodnota. Scrape.status.error.invalid=Neplatn\u00e1 odpov\u011b\u010f. Scrape.status.nextScrapeAt=Dal\u0161\u00ed Scrape v %1 Scrape.status.scraping=Scrapuji... Scrape.status.initializing=\u010cek\u00e1n\u00ed na Scrape ConfigView.label.minSpeedForActiveSeeding=Nepo\u010d\u00edtat vyu\u017eit\u00ed slotu, pokud je rychlost dokon\u010den\u00e9ho torrentu pod ConfigView.section.stats.exportpeers=Exportovat detaily o klientech MainWindow.menu.view.irc.moved=IRC klient je nyn\u00ed dostupn\u00fd jako plugin; nav\u0161tivte http://azureus.sourceforge.net/plugin_list.php. Po nainstalov\u00e1n\u00ed pou\u017eijte menu Zobrazit->Dopl\u0148ky->IRC. MyTrackerView.webui.contextmenu.copyurl=Kop\u00edrovat URL Torrentu do schr\u00e1nky ConfigView.section.file.torrent.ignorefiles=Ignorovan\u00e9 soubory p\u0159i vytv\u00e1\u0159en\u00ed torrent\u016f\nnap\u0159. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignoruji soubor ConfigView.section.style.useUnitsRateBits=Pro rychlostn\u00ed p\u0159enosy pou\u017e\u00edvat bity misto byt\u016f (KiB/s->Kibit/s atd.) ConfigView.section.interface.resetassoc=Obnovit v\u00fdchoz\u00ed nastaven\u00ed asociace soubor\u016f (.torrent) ConfigView.section.interface.resetassocbutton=Obnovit ConfigView.section.interface.checkassoc=P\u0159i startu kontrolovat asociace soubor\u016f dialog.associations.title=Kontrola asociace soubor\u016f Button.yes=Ano Button.no=Ne ConfigView.label.seeding.autoStart0Peers=Automaticky spou\u0161t\u011bt v\u0161echny dokon\u010den\u00e9 torrenty s 0 klienty ConfigView.label.seeding.autoStart0Peers.tooltip=Zapnut\u00edm doc\u00edl\u00edte, aby Tracker st\u00e1le vypisoval seznam distributor\u016f pro torrenty s 0 klienty. dialog.associations.prompt=Vuze nen\u00ed v\u00fdchoz\u00ed aplikace pro BitTorrent soubory.\nP\u0159ejete si nastavit Vuze jako v\u00fdchoz\u00ed aplikaci pro .torrent soubory? dialog.associations.askagain=Zkontrolovat p\u0159i startu ConfigView.section.plugins.update=Aktualizace dopl\u0148k\u016f Plugin.pluginupdate.enablecheck=Povolit kontrolu nov\u00fdch verz\u00ed dopl\u0148k\u016f plugins.basicview.status=Stav: plugins.basicview.activity=Aktivita: plugins.basicview.progress=Postup: plugins.basicview.log=Protokol: ConfigView.label.maxdownloadspeed=KB/s celkov\u00e9 max.rychlosti downloadu [0: neomezen\u011b] splash.loadingTorrent=Na\u010d\u00edt\u00e1n\u00ed Torrentu splash.of=z UpdateWindow.title=Aktualizace programu Vuze UpdateWindow.header=Je t\u0159eba aktualizovat n\u00e1sleduj\u00edc\u00ed komponenty : UpdateWindow.columns.install=Instalovat UpdateWindow.columns.name=N\u00e1zev UpdateWindow.columns.version=Verze UpdateWindow.columns.size=Velikost UpdateWindow.cancel=Storno UpdateWindow.quit=Konec UpdateWindow.close=Zav\u0159\u00edt UpdateWindow.ok=Aktualizovat UpdateWindow.restart=Restartovat UpdateWindow.status.downloading=Stahov\u00e1n\u00ed UpdateWindow.status.done=Hotovo UpdateWindow.status.failed=Chyba UpdateWindow.status.restartNeeded=Bude t\u0159eba restartovat Vuze ConfigView.pluginlist.broken=Nefunk\u010dn\u00ed ConfigView.pluginlist.whereToPut=U\u017eivatelsk\u00e9 dopl\u0148ky um\u00edst\u011bte do slo\u017eky (ka\u017ed\u00fd do zvl\u00e1\u0161tn\u00ed podslo\u017eky): ConfigView.pluginlist.whereToPutOr=Pro sd\u00edlen\u00e9 dopl\u0148ky pou\u017eijte slo\u017eku: MainWindow.statusText.checking=Kontrola aktualizac\u00ed TableColumn.header.OnlyCDing4=Pouze distribuov\u00e1no po TableColumn.header.OnlyCDing4.info=Mno\u017estv\u00ed \u010dasu, po kter\u00e9 byl torrent distribuov\u00e1n. Nezapo\u010d\u00edt\u00e1n \u010das, po kter\u00fd se torrent z\u00e1rove\u0148 stahoval i odes\u00edlal. ConfigView.section.style.alternateTablePainting=Pou\u017e\u00edt alternativn\u00ed metodu pro barevnost grafiky tabulek a sloupc\u016f (m\u016f\u017ee vy\u017eadovat restartovat) UpdateWindow.status.restartMaybeNeeded=Je nutn\u00e9 restartovat ConfigView.pluginlist.shared=Sd\u00edlet PeersView.host=N\u00e1zev hostitele PeersView.host.info=Jm\u00e9no hostitela the peer, ke k dispozici (m\u016f\u017ee ovlivnit v\u00fdkon) MainWindow.menu.help.whatsnew=Co je nov\u00e9ho ConfigView.label.checkonstart=Za\u010d\u00edn\u00e1 kontrola posledn\u00ed verze Azurea. ConfigView.label.periodiccheck=Pravideln\u00e1 kontrola posledn\u00ed verze ConfigView.label.opendialog=Pokud je dostupn\u00e1 aktualizace otev\u0159i aktualiza\u010dn\u00edho asistenta MainWindow.updateavail=Klikni zde pro updates MainWindow.status.latestversionunchecked=Kontrola verze je zak\u00e1z\u00e1na GeneralView.label.updatein.stopped=Zastavit StartStopRules.menu.viewDebug=Zobrazit lad\u00edc\u00ed informace ConfigView.section.style.doNotUseGB=Nepou\u017e\u00edvat jednotku GB ConfigView.section.style.doNotUseGB.tooltip=Pokud je za\u0161krtnuto, Vuze bude pokra\u010dovat v pou\u017e\u00edv\u00e1n\u00ed jednotek MB i pro velikosti p\u0159esahuj\u00edc\u00ed 1024MB (1GB) MainWindow.menu.help.plugins=Z\u00edskat pluginy ConfigView.section.plugins.TrackerWeb=Webov\u00fd server ConfigView.section.tracker.enablecategories=Rozd\u011blit torrenty podle kategorie health.explain.share=znamen\u00e1, \u017ee torrent je bu\u010f hostitel nebo publikov\u00e1n\u00fd ConfigView.section.tracker.createcert=Vytvo\u0159it podepsan\u00fd certifik\u00e1t ConfigView.section.tracker.createbutton=Vytvo\u0159it security.certcreate.title=Vytvo\u0159it vlastn\u00ed podepsan\u00fd certifik\u00e1t security.certcreate.intro=Tento dialog V\u00e1m pom\u016f\u017ee vytvo\u0159it podepsan\u00fd certifik\u00e1t security.certcreate.strength=S\u00edla security.certcreate.firstlastname=Jm\u00e9no a p\u0159\u00edjmen\u00ed security.certcreate.orgunit=Organiza\u010dn\u00ed jednotka security.certcreate.org=Organizace security.certcreate.city=M\u011bsto nebo m\u00edsto security.certcreate.state=St\u00e1t nebo provincie security.certcreate.country=Dvojp\u00edsmenn\u00fd k\u00f3d zem\u011b (nap\u0159 CZ) security.certcreate.ok=Vytvo\u0159it security.certcreate.cancel=Zru\u0161it security.certcreate.createok=\u00dasp\u011b\u0161n\u00e9 vytvo\u0159en\u00ed certifik\u00e1tu security.certcreate.createfail=Chyba vytvo\u0159en\u00e9ho certifik\u00e1tu ConfigView.section.plugins.webui=Swing Web rozhran\u00ed ConfigView.section.plugins.xml_http_if=XML/HTTP rozhran\u00ed webui.passwordenable=Povolit Heslo webui.user=U\u017eivatelsk\u00e9 jm\u00e9no webui.password=Heslo webui.protocol=Protokol (*) webui.homepage=Dom\u00e1c\u00ed str\u00e1nka (*) webui.rootdir=Ko\u0159enov\u00fd adres\u00e1\u0159 (*) webui.rootres=Ko\u0159enov\u00e9 zdroje (*) webui.mode=M\u00f3d (*) webui.mode.info=M\u00f3d m\u00fa\u017ee b\u00fdt\t"full"\t= v\u0161echny dosa\u017eiteln\u00e9 operace (standartn\u011bt)\n\t"zobrazit"\t= zobrazit jen p\u0159i aktualizaci (nebo obnoven\u00ed frekvence) webui.access=P\u0159\u00edstup (*) webui.access.info=P\u0159\u00edstup m\u00fa\u017ee b\u00fdt\n\t"m\u00edstn\u00ed"\t= v\u00fdznam jen u m\u00edstn\u00edho stroje p\u0159i p\u0159ipojen\u00ed\n\t"v\u0161e"\t= voln\u00fd p\u0159\u00edstup (standartn\u00ed)\n\tIP\t= e.g. 192.168.0.2\t\t\tone IP pouze\n\tIP1-IP2\t= e.g. 192.168.0.1-192.168.0.255\texlusivn\u00ed rozsah IPs GeneralView.label.maxdownloadspeed=Max odes. Security.keystore.corrupt=Keystore '%1' selhalo na\u010dten\u00ed, pros\u00edm sma\u017ete to a obnovte/re-importujte certifik\u00e1t Security.keystore.empty=Keystore je pr\u00e1zdn\u00e9. Pros\u00edm vytvo\u0159te podepsan\u00fd certifik\u00e1t (pod\u00edvej se N\u00e1stroje ->Mo\u017enosti->Bezpe\u010dnost) nebo importuj existuj\u00edc\u00ed certifik\u00e1t '%1' webui.restart.info=Zm\u011bnit ozna\u010den\u00e9 parametry (*) efekty se projev\u00ed po\u017eaduje restartovat GeneralView.label.maxdownloadspeed.tooltip=Max rychlost stahov\u00e1n\u00ed [0: bneomezen\u011b] upnp.enable=Povolit UPnP upnp.info=Univers\u00e1ln\u00ed Plug and Play (UPnP) povoluje automat. mapov\u00e1n\u00ed portu UPnP povoleno routers. upnp.mapping.dataport=Odchoz\u00ed Peer Data Port upnp.mapping.tcptrackerport=TCP server Port upnp.mapping.udptrackerport=UDP serve Port upnp.alert.differenthost=UPnP: Mapuji '%1' rezervaci '%2' - pros\u00edm vyberte port upnp.alert.mappingok=UPnP: Mapuji '%1' ustanoven\u00ed upnp.alert.mappingfailed=UPnP: Mapuji '%1' po\u0161kozen\u00e9 upnp.alertsuccess=Zpr\u00e1va \u00fasp\u011b\u0161n\u00e9h mapov\u00e1n\u00ed upnp.alert.lostdevice=UPnP: ztracen\u00e9 p\u0159ipojen\u00ed - udr\u017eba '%1' on UPnP ovlada\u010d '%2' upnp.grabports=Mapov\u00e1n\u00ed port\u00fa na jin\u00e9m po\u010d\u00edta\u010di upnp.refresh.label=Obnovit mapov\u00e1n\u00ed upnp.refresh.button=Obnovit upnp.alert.mappinggrabbed=UPnP: Mapuji '%1' ustanoven\u00ed propadli\u0161t\u011b z '%2' upnp.mapping.tcpssltrackerport=TCP SSL server Port upnp.alertothermappings=Zpr\u00e1va o portech jin\u00fdch po\u010d\u00edta\u010d\u016f upnp.alertdeviceproblems=Zpr\u00e1va o probl\u00e9mu v UPnP ovlada\u010di blank.resource=Zdroje ConfigView.pluginlist.coreplugins=N\u00e1sleduj\u00edc\u00ed dopln\u011bk je aktualizov\u00e1n: Peers.column.DLedFromOthers=Dal\u0161\u00ed Peers.column.DLedFromOthers.info=Mno\u017estv\u00ed dat sta\u017een\u00fdch od jin\u00fdch po dobu p\u0159ipojen\u00ed Peers.column.UpDownRatio=Odesl\u00e1no:sta\u017eeno Peers.column.UpDownRatio.info=Klient\u016fv pom\u011br "odesl\u00e1no:sta\u017eeno" Peers.column.UpRatio=Pom\u011br odeslan\u00fdch dat Peers.column.UpRatio.info=Klient\u016fv pom\u011br "sta\u017eeno od V\u00e1s:sta\u017eeno od ostatn\u00edch" upnp.releasemappings=Vyd\u00e1n\u00edzastaven\u00ed mapov\u00e1n\u00ed webui.upnpenable=Povolit UPnP tento port (*) ConfigView.section.file.friendly.hashchecking=Kontrola hash \u010dekejte ConfigView.section.file.friendly.hashchecking.tooltip=M\u00edrn\u011b pomalej\u0161\u00ed, m\u00e9n\u011b n\u00e1ro\u010dn\u00e9 na procesor a syst\u00e9m, m\u00f3d kontrolov\u00e1n\u00ed hashe. ConfigView.section.tracker.seedretention=Maxim\u00e1ln\u00ed po\u010det klient\u016f na jeden torrent [0: neomezen\u011b] ConfigView.section.tracker.seedretention.info=Pozn\u00e1mka: Upload statistika bude ztracena pro odpojen\u00ed ConfigView.section.tracker.port=Povolit serveru HTTP port ConfigView.section.tracker.sslport=Povolit servru HTTPS port ConfigView.section.tracker.publicenable.info=Povol\u00ed vytvo\u0159it ostatn\u00edm torrenty, kter\u00e9 pou\u017eije V\u00e1\u0161 tracker\nbez jejich hostov\u00e1n\u00ed/publikov\u00e1n\u00ed Button.clear=Smazat MainWindow.IPs.tooltip={\u010cas posledn\u00ed aktualizace IP Filtr\u016f} Po\u010det IP Filtr\u016f - Po\u010det zablokovan\u00fdch IP adres p\u0159i tomto spu\u0161t\u011bn\u00ed\nPoklep\u00e1n\u00edm zobraz\u00edte dal\u0161\u00ed informace ConfigView.section.ipfilter.list.banned=IP adrese tohoto u\u017eivatele je blokov\u00e1no p\u0159ipojen\u00ed se k V\u00e1m ConfigView.section.ipfilter.list.baddata=poslal neplatn\u00e1 data = Button.reset=Zru\u0161it ConfigView.section.ipfilter.bannedinfo=IP adresy kter\u00e9 poslaly neplatn\u00e1 data budou zablokov\u00e1ny pokud p\u0159es\u00e1hnou limit ConfigView.section.ipfilter.blockedinfo=IP adresy, kter\u00e9 jsou zablokov\u00e1ny va\u0161imi IP filtry download.removerules.name=Odstran\u011bn\u00ed pravidel download.removerules.unauthorised.info=Neautorizov\u00e9 torrenty jsou ty, kde je ozn\u00e1men obsah odezvy bu\u010f "neopr\u00e1vn\u011bn\u00ed" nebo "neautorizov\u00e1n\u00e9", nebo chyb\u011bj\u00edc\u00ed odezva download.removerules.unauthorised=Automatick\u00e9 odstran\u011bn\u00ed neautorizovan\u00fdch torrent\u016f download.removerules.unauthorised.seedingonly=\tJen p\u0159i distrubuci download.removerules.removed.ok=Automatick\u00e9 odstran\u011bn\u00ed torrentu '%1' prob\u011bhlo \u00fasp\u011b\u0161n\u011b. Toto bylo zp\u016fsobeno pravidly na odstran\u011bn\u00ed torrentu. download.removerules.updatetorrents=Vuze swarm po\u017eaduje odstran\u011bn\u00ed aktualizac\u00ed torrentu ConfigView.label.defaultstarttorrentsstopped=Implicitn\u011b p\u0159id\u00e1vej torrenty v zastaven\u00e9m stavu ConfigView.section.server.enableudp=Povolit UDP tracker klient protokol. upnp.mapping.dataportudp=UDP server klient port ConfigView.section.file.decoder.showlax=Zobrazit men\u0161\u00ed pravd\u011bpodobnost zak\u00f3dov\u00e1n\u00ed ConfigView.section.file.decoder.showall=Po\u017eadovat v\u0161e zakodovan\u011b MainWindow.status.updowndetails.tooltip=Detaily rychlost\u00ed stahov\u00e1n\u00ed/odes\u00edl\u00e1n\u00ed\nPrav\u00fdm tla\u010d\u00edtkem rychlosti zm\u011b\u0148\u00edte, dvojklikem prav\u00fdm tla\u010d\u00edtkem otev\u0159ete statistiky. TrackerClient.announce.warningmessage=Sever pro '%1' vrac\u00ed varov\u00e1n\u00ed '%2' ConfigView.section.tracker.natcheckenable=Kontroluje spojen\u00edschopnost portu na p\u0159\u00edchoz\u00ed data a oznamuje klient\u016fm selh\u00e1n\u00ed ConfigView.section.tracker.publishenabledetails=Publikovat .torrent soubor a detaily o zdroj\u00edch ConfigView.section.tracker.publishenablepeerdetails=Publikovat detaily u\u017eivatele MyTrackerView.badnat=Chyba NAT MyTrackerView.badnat.info=Distrubuj\u00edc\u00ed/klienti, kter\u00fdm selhala kontrola NAT, pokud je tato mo\u017enost povolena ConfigView.section.tracker.natchecktimeout=Kontrola p\u0159ekro\u010den\u00ed \u010das. limitu (sec) ConfigView.section.file.perf.cache.enable=Spustit diskovou pam\u011b\u0165 ConfigView.section.file.perf.cache.size=Velikost vyrovn\u00e1vac\u00ed pam\u011bti v %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=P&\u0159enos MainWindow.menu.transfers.startalltransfers=Sp&ustit v\u0161e MainWindow.menu.transfers.stopalltransfers=St&op v\u0161e MainWindow.menu.transfers.pausetransfers=&Pauza MainWindow.menu.transfers.resumetransfers=&Pokra\u010dovat ConfigView.label.experimental.osx.kernel.panic.fix=Experiment\u00e1ln\u00ed z\u00e1plata kv\u016fli panice j\u00e1dra na dvouprocesorov\u00fdch OSX syst\u00e9mech [vy\u017eaduje restart] SystemTray.menu.pausetransfers=Pauza v p\u0159enosu SystemTray.menu.resumetransfers=Znovu spustit p\u0159enos ConfigView.section.file.truncate.too.large=O\u0159\u00edzne existujic\u00ed velk\u00e9 soubory ConfigView.section.file.perf.cache.trace=Opera\u010dn\u00ed stopa vyrovn\u00e1vac\u00ed pam\u011bti pro diagnostick\u00e9 \u00fa\u010dely ConfigView.section.interface.enabletray=Povolit zobrazen\u00ed v syst\u00e9mov\u00e9 li\u0161t\u011b (vy\u017eaduje restart) PeerManager.status.error=Chyba Stats.title.full=Statistika TransferStatsView.title.full=P\u0159enos CacheView.title.full=Vyrovn\u00e1vac\u00ed pam\u011b\u0165 CacheView.general.size=Celkov\u00e1 velikost CacheView.general.inUse=Pou\u017e\u00edv\u00e1 se CacheView.general.title=Info o vyrovn\u00e1vac\u00ed pam\u011bti CacheView.reads.title=I/O \u010dten\u00ed CacheView.reads.fromFile=Ze souboru CacheView.reads.fromCache=Z vyrov. pam\u011bti CacheView.reads.hits=Hity CacheView.writes.title=I/O z\u00e1pisy CacheView.writes.toCache=Do vyrov. pam\u011bti CacheView.writes.toFile=Do souboru CacheView.writes.hits=Ulo\u017eeno CacheView.speeds.title=P\u0159enosov\u00e9 rychlosti CacheView.speeds.reads=\u010cten\u00ed CacheView.speeds.writes=Z\u00e1pisy CacheView.speeds.fromCache=Z/do vyrov. pam\u011bti CacheView.speeds.fromFile=Ze/do souboru CacheView.reads.amount=Mno\u017estv\u00ed CacheView.reads.avgsize=Pr\u016fm. velikost openUrl.referrer=Referen\u010dn\u00ed str\u00e1nka URL : openUrl.referrer.info=Po\u017eadov\u00e1n p\u0159\u00edstupov\u00fd mand\u00e1t na web sites ConfigView.label.maxuploadspeedseeding=KB/s glob\u00e1ln\u00ed max. rychlost uploadu pokud pouze distrubujete [0: neomezen\u011b] ConfigView.label.transfer.ignorepeerports=Ignorovat klienty s t\u00edmto datov\u00fdm vstupn\u00edm portem (odd\u011blte st\u0159edn\u00edkem ";", nap\u0159\u00edklad: 0;25) ConfigView.section.proxy.enable_socks.peer=Povolen\u00ed proxy pro komunikaci (odchoz\u00ed p\u0159ipojen\u00ed) [je t\u0159eba restartovat Vuze ConfigView.section.proxy.peer.informtracker=Informovat server o omezen\u00ed ConfigView.section.proxy.socks.version=Verze SOCKS PiecesView.legend.written=Z\u00e1pisov\u00e1n\u00ed PiecesView.legend.requested=Po\u017eadovan\u00fd PiecesView.legend.downloaded=Sta\u017eeno, zaps\u00e1ny nevy\u0159e\u0161en\u00e9 PiecesView.legend.incache=Data ve vyrovn\u00e1vac\u00ed pam\u011bti PiecesView.typeItem.0=Pomal\u00e9 PiecesView.typeItem.1=Rychl\u00e9 PiecesView.type=Typ Security.jar.tools_not_found=JAR selh\u00e1n\u00ed podpisu - 'n\u00e1stroje.jar' nenelazen %1. Zkontroluj N\u00e1stroje->Mo\u017enosti->Zabezpe\u010den\u00ed detaily. Security.jar.signfail=JAR selh\u00e1n\u00ed podpisu - %1 ConfigView.section.security.toolsinfo=Ozna\u010den\u00e9 JAR soubory se pou\u017e\u00edvaj\u00ed pro podporu n\u011bkter\u00fdch plugin\u016f jako nap\u0159. Swing Web Interface (pokud je to tak nakonfigurov\u00e1no).\nPro pou\u017eit\u00ed JAR soubor\u016f je nezbytn\u00e9 m\u00edt p\u0159\u00edstup k 'tools.jar', kter\u00fd najdete v instalaci Sun JDK (ne JRE).\nJestli\u017ee jste naistalovali jen JRE, pak naistalujte i JDK.\nVuze pro V\u00e1s v\u011bt\u0161inou soubor najde s\u00e1m. Nicm\u00e9n\u011b jestli se mu to nepoda\u0159\u00ed, m\u016f\u017eete slo\u017eku obsahuj\u00edc\u00ed tento soubor nastavit zde. ConfigView.section.security.toolsdir=Adres\u00e1\u0159 obsahujic\u00ed 'tools.jar' ConfigView.section.security.choosetoolssavedir=Vyberte slo\u017eku obsahujic\u00ed 'tools.jar' ConfigView.section.proxy.peer.same=Pou\u017eit\u00ed stejn\u00e9 proxy nastaven\u00ed pro server i u\u017eivatele u\u017e\u00edvaj\u00edc\u00ed proxy ConfigView.section.connection.network.max.simultaneous.connect.attempts=Maxim\u00e1ln\u00ed po\u010det pokus\u016f simult\u00e1nn\u00edho odchoz\u00edho p\u0159ipojen\u00ed ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Maxim\u00e1ln\u00ed po\u010det nov\u00fdch odchoz\u00edch nav\u00e1zan\u00fdch p\u0159ipojen\u00ed. Vuze se bude pokou\u0161et o p\u0159ipojen\u00ed kdykoli.\nPozn\u00e1mka Windows XP Service Pack 2 (SP2) celosyst\u00e9mov\u011b nastavuje limit 10 simultann\u00edch spojen\u00ed.\nStandarni hodnota je 8. Hodnota 0 zak\u00e1\u017ee odchoz\u00ed spojen\u00ed \u00fapln\u011b. ConfigView.section.file.perf.cache.size.explain=Vyrovn\u00e1vac\u00ed pam\u011b\u0165 je vyu\u017eita pro redukci \u010dten\u00ed a z\u00e1pisu na disk. Jestli\u017ee nepou\u017e\u00edvate Java mo\u017enosti '-XX:MaxDirectMemorySize' pro implicitn\u011b nastavenou pam\u011b\u0165 dosa\u017eitelnou pro vyrovn\u00e1vac\u00ed pam\u011b\u0165 a s\u00ed\u0165 IO, pou\u017eijte tuto hodnotu nejm\u00e9n\u011b %1 pod Va\u0161i maxim\u00e1ln\u00ed velikost virtu\u00e1ln\u00ed pam\u011bti. Sou\u010dasn\u00e1 maxim\u00e1ln\u00ed velikost virtu\u00e1ln\u00ed pam\u011bti je %2. Ke zm\u011bn\u011b tohoto nastaven\u00ed se pod\u00edvejte na vyu\u017eit\u00ed pam\u011bti ve wiki na %3. Selh\u00e1n\u00ed p\u0159i nastaven\u00ed ide\u00e1ln\u00ed hodnoty se projev\u00ed v hl\u00e1\u0161en\u00ed o chyb\u00e1ch s nedostatkem pam\u011bti. V\u00edce jak 32MB je zbyte\u010dn\u011b moc a m\u016f\u017ee zp\u016fsobit kolaps syst\u00e9mu. MyTorrentsView.menu.setSpeed.unlimit=\u017d\u00e1dn\u00fd limit MyTorrentsView.menu.setSpeed.unlimited=Bez limitu MyTorrentsView.menu.setSpeed.disable=Zak\u00e1zan\u00fd upload MyTorrentsView.menu.setSpeed.disabled=Zak\u00e1zan\u00fd MyTorrentsView.menu.setSpeed.in=v MyTorrentsView.menu.setSpeed.slots=sloty z GeneralView.label.maxuploadspeed=Max stah. GeneralView.label.maxuploadspeed.tooltip=Maxim\u00e1ln\u00ed rychlost odes\u00edl\u00e1n\u00ed [0 : neomezen\u011b] MyTorrents.items.UpSpeedLimit.disabled=\u017d\u00e1dn\u00fd upload MyTorrents.items.UpSpeedLimit.unlimited=neomezen\u011b TableColumn.header.maxupspeed=Maxim\u00e1ln\u00ed rychlost odes\u00edl\u00e1n\u00ed TableColumn.header.maxupspeed.info=Maxim\u00e1ln\u00ed rychlost stahov\u00e1n\u00ed na jeden torrent ConfigView.section.file.perf.cache.enable.write=Zapisovat sta\u017een\u00e1 data do vyrovn\u00e1vac\u00ed pam\u011bti pro sn\u00ed\u017een\u00ed aktivity harddisku ConfigView.section.file.perf.cache.enable.read=Vykon\u00e1vat na\u010d\u00edt\u00e1n\u00ed soubor\u016f dop\u0159edu pro redukci aktivity harddisku p\u0159i odes\u00edl\u00e1n\u00ed dat ConfigView.section.tracker.separatepeerids=Pou\u017e\u00edt r\u016fzn\u00e9 identity pro tracker a datov\u00fd p\u0159enos ConfigView.section.tracker.separatepeerids.info=Zv\u00fd\u0161\u00ed anonymitu jestli stahujete/distribujete anonymn\u011b\np\u0159i pou\u017eit\u00ed neanonmn\u00edho spojen\u00ed trackeru ConfigView.section.interface.wavlocation=Um\u00edst\u011bn\u00ed .wav souboru ConfigView.section.interface.wavlocation.info=Vyberte .wav soubor nebo ponechte pr\u00e1zdn\u00e9 pro v\u00fdchoz\u00ed zvuk ConfigView.section.tracker.client=Klient ConfigView.section.tracker.client.connecttimeout=P\u0159ekro\u010den\u00ed \u010dasov\u00e9ho limitu (sec) ConfigView.section.tracker.client.readtimeout=Na\u010dten\u00ed p\u0159ekro\u010den\u00ed \u010das. limitu (sec) MainWindow.menu.tools=&N\u00e1stroje FilesView.path=Cesta FilesView.fullpath=Zobrazit celou cestu FilesView.remaining=Zb\u00fdvaj\u00edc\u00ed d\u00edly TableColumn.header.trackername=N\u00e1zev trackeru TableColumn.header.trackername.info=N\u00e1zev serveru zalo\u017een\u00fd na ozn\u00e1men\u00ed URL ConfigView.group.override=P\u0159epsat mo\u017enosti ConfigView.section.file.perf.cache.notsmallerthan=Do vyrovn\u00e1vac\u00ed pam\u011bti nejdou men\u0161\u00ed soubory ne\u017e (v %1) PeersView.menu.blockupload=Blokov\u00e1n\u00ed odes\u00edl\u00e1n\u00ed PeersView.menu.kickandban=Vykopnout a zablokovat u\u017eivatele PeersView.menu.kickandban.reason=Klient byl manu\u00e1ln\u011b zablokov\u00e1n PeersView.state=Stav PeersView.state.info=Stav peer p\u0159ipojen\u00ed PeersView.state.pending=\u010cek\u00e1 na obslou\u017een\u00ed PeersView.state.connecting=Navazuje se PeersView.state.handshake=\u010cek\u00e1 na souhlas PeersView.state.established=Spojen\u00ed nav\u00e1z\u00e1no ConfigView.section.tracker.processinglimits=Limit pro zpracov\u00e1n\u00ed ConfigView.section.tracker.maxgettime=Maxim\u00e1ln\u00ed \u010das pro zpracov\u00e1n\u00ed GET (sec) [0: neomezeno] ConfigView.section.tracker.maxgettime.info=Pou\u017eito pro ozn\u00e1men\u00ed a scrapy ConfigView.section.tracker.maxposttimemultiplier=\u010casov\u00fd n\u00e1sobitel GET pro zpracov\u00e1n\u00ed POST [0: bezlimitu] ConfigView.section.tracker.maxposttimemultiplier.info=Pou\u017eito pro formu pod\u0159\u00edzen\u00ed a odes\u00edl\u00e1n\u00ed ConfigView.section.tracker.maxthreads=Maxim\u00e1ln\u00ed po\u010det soub\u011b\u017en\u00fdch po\u017eadavk\u016f DownloadManager.error.operationcancancelled=Operace je zru\u0161ena Torrent.create.progress.cancelled=Operace zru\u0161ena sharing.progress.cancel=Zru\u0161it wizard.maketorrents.autoopen=Otev\u0159ete torrent pro seeding, kdy\u017e je dokon\u010den ConfigView.section.sharing.rescanenable=Povolit pravideln\u00e9 skenov\u00e1n\u00ed sd\u00edlen\u00ed pro zm\u011bny ConfigView.section.sharing.rescanperiod=Obnoven\u00ed skenov\u00e1n\u00ed (sekundy) ConfigView.section.connection.advanced=Pokro\u010dil\u00e9 nastaven\u00ed s\u00edt\u011b ConfigView.section.connection.advanced.mtu=Maxim\u00e1ln\u00ed p\u0159enosov\u00e1 jednotka (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Maxim\u00e1ln\u00ed velikost paketu, p\u0159en\u00e1\u0161en\u00e9ho v jednom framu p\u0159es s\u00ed\u0165.\nVuze pou\u017e\u00edv\u00e1 MTU-40 (MSS) pro optim\u00e1ln\u011b vyu\u017eit\u00e9 zat\u00ed\u017een\u00ed odes\u00edlan\u00e9ho paketu.\nDoporu\u010den\u00e9 hodnoty:\n 576 - Vyt\u00e1\u010den\u00e9 p\u0159ipojen\u00ed\n1492 - PPPoE \u0161irokop\u00e1sm\u00e9 p\u0159ipojen\u00ed\n1500 - Ethernet, DSL a kabelov\u00e9 \u0161irokop\u00e1sm\u00e9 p\u0159ipojen\u00ed ConfigView.section.connection.advanced.SO_RCVBUF=Velikost socketu SO_RCVBUF [0: pou\u017e\u00edt OS standart] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Nastav\u00ed standartn\u00ed hodnotu socketu SO_RCVBUF (v bytech), co\u017e znamen\u00e1, \u017ee TCP p\u0159ijme velikost a pom\u011br okna.\nVuze toto nech\u00e1v\u00e1 na v\u00fdchoz\u00edch hodnot\u00e1ch (pro z\u00e1kladn\u00ed opera\u010dn\u00ed syst\u00e9m).\nPozn\u00e1mka : V Linuxu jsou hodnoty dvakr\u00e1t vy\u0161\u0161\u00ed. ConfigView.section.connection.advanced.SO_SNDBUF=Socket SO_SNDBUF velikost [0: pou\u017e\u00edt OS standart] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Nastav\u00ed standartn\u00ed hodnotu socketu SO_SNDBUF (v bytech), co\u017e znamen\u00e1, \u017ee TCP po\u0161le velikost okna.\nVuze toto nastaven\u00ed nech\u00e1v\u00e1 na v\u00fdchoz\u00edch hodnot\u00e1ch (pro z\u00e1kladn\u00ed opera\u010dn\u00ed syst\u00e9m).\nPozn\u00e1mka : Pozn\u00e1mka : V Linuxu jsou hodnoty dvakr\u00e1t vy\u0161\u0161\u00ed. ConfigView.section.interface.confirm_torrent_removal=Zobrazit potvrzovac\u00ed dialog odstran\u011bn\u00ed torrentu ConfigView.section.interface.confirm_torrent_removal.tooltip=Potvr\u010fte p\u0159i odstran\u011bn\u00ed torrentu z Moje Torrenty. MyTorrentsView.confirm_torrent_removal=Jste si jist\u00ed, \u017ee to chceta odstranit?\n TableColumn.header.seed_to_peer_ratio=Pom\u011br distrubuj\u00edc\u00ed/stahuj\u00edc\u00ed TableColumn.header.seed_to_peer_ratio.info=Pom\u011br distrubuj\u00edc\u00ed/stahuj\u00edc\u00ed v cel\u00e9m torrentu PeersView.connected_time=\u010cas p\u0159ipojen\u00ed PeersView.connected_time.info=Celkov\u00fd \u010das p\u0159ipojen\u00ed s peer ConfigView.section.interface.display.add_torrents_silently=P\u0159idat torrenty ConfigView.section.interface.display.add_torrents_silently.tooltip=P\u0159idat stahov\u00e1n\u00ed torrent\u016f bez aktivace v hlavn\u00edm okn\u011b Azureus. TableColumn.header.maxdownspeed=Maxim\u00e1ln\u00ed rychlost stahov\u00e1n\u00ed TableColumn.header.maxdownspeed.info=Maxim\u00e1ln\u00ed rychlost stahov\u00e1n\u00ed na jeden torrent ConfigView.section.tracker.passwordwebhttpsonly=Povolit p\u0159\u00edstup jen p\u0159es HTTPS TableColumn.header.torrentpath=Um\u00edst\u011bn\u00ed Torrentu TableColumn.header.torrentpath.info=Um\u00edst\u011bn\u00ed Torrentu na disku ConfigView.section.sharing.torrentcomment=Koment\u00e1\u0159 pro generov\u00e1n\u00ed torrent\u016f ConfigView.label.copyanddeleteratherthanmove=Rad\u011bji origin\u00e1ln\u00ed data nejprve zkop\u00edrujte a a\u017e potom sma\u017ete m\u00edsto p\u0159esouv\u00e1n\u00ed v jedin\u00e9 operaci. \nZabr\u00e1n\u00edte tak ztr\u00e1t\u00e1m dat na n\u011bkter\u00fdch souborov\u00fdch syst\u00e9mech.\n ConfigView.label.openstatsonstart=Po spu\u0161t\u011bn\u00ed otev\u0159\u00edt statistiky (Statistika) swt.install.window.title=Instal\u00e1tor Vuze plugin\u016f swt.install.window.ok=Instalovat swt.install.window.header=N\u00e1sleduj\u00edc\u00ed sou\u010d\u00e1sti byly vybr\u00e1ny pro instalaci : swt.uninstall.window.title=Odinstal\u00e1tor Vuze plugin\u016f swt.uninstall.window.ok=Odstranit swt.uninstall.window.header=N\u00e1sleduj\u00edc\u00ed sou\u010dasti byly vybr\u00e1ny pro odstran\u011bn\u00ed : installPluginsWizard.title=Instalace dopl\u0148k\u016f installPluginsWizard.mode.title=Pros\u00edm vyberte metodu instalace installPluginsWizard.mode.list=Ze seznamu na sourceforge.net installPluginsWizard.list.title=Seznam instalovan\u00fdch dopl\u0148k\u016f installPluginsWizard.list.loading=Pros\u00edm \u010dekejte, na\u010d\u00edt\u00e1m seznam plugin\u016f. installPluginsWizard.list.loaded=Pros\u00edm vyberte si pluginy, kter\u00e9 si p\u0159ejete nainstalovat. installPluginsWizard.list.name=N\u00e1zev installPluginsWizard.list.version=Verze installPluginsWizard.list.description=Popis dopl\u0148k\u016f installPluginsWizard.finish.title=Instalace pr\u00e1v\u011b prob\u00edh\u00e1 installPluginsWizard.finish.explanation=Vybran\u00e9 pluginy budou nainstalov\u00e1ny pou\u017eit\u00edm Update Assistenta.\n\nPros\u00edm m\u011bjte strpen\u00ed, tato operace m\u016f\u017ee chv\u00edli trvat.\n\nPro v\u00edce informac\u00ed dvakr\u00e1t klikn\u011bte nalevo do stavov\u00e9m \u0159\u00e1dku. installPluginsWizard.details.loading=Pros\u00edm \u010dekejte, na\u010d\u00edt\u00e1m detaily... installPluginsWizard.mode.file=Ze souboru installPluginsWizard.installMode.title=Pros\u00edm vyberte typ instalace installPluginsWizard.installMode.user=Nainstaluje plugin(y) jen pro pr\u00e1v\u011b p\u0159ihl\u00e1\u0161en\u00e9ho u\u017eivatele installPluginsWizard.installMode.shared=Nainstaluje plugin(y) pro v\u0161echny u\u017eivatele installPluginsWizard.file.title=Pros\u00edm vyhledejte plugin, kter\u00fd chcete nainstalovat installPluginsWizard.file.file=Soubor : installPluginsWizard.file.invalidfile=Toto nen\u00ed platn\u00fd Vuze plugin. installPluginsWizard.file.browse=Prohl\u00ed\u017eet... uninstallPluginsWizard.title=Odinstalace Plugin\u016f uninstallPluginsWizard.list.title=Instalovat sezna Plugin\u016f uninstallPluginsWizard.list.loaded=Pros\u00edm vyberte plugins k odinstalov\u00e1n\u00ed. installPluginsWizard.list.nullversion=\u017d\u00e1dn\u00e1 verze uninstallPluginsWizard.finish.title=Postup odinstalace uninstallPluginsWizard.finish.explanation=Vybran\u00e9 Pluginy budou odinstalov\u00e1ny po\u017e\u00edv\u00e1n\u00edm Update Asistenta. MainWindow.menu.plugins.installPlugins=Instala\u010dn\u00ed pr\u016fvodce..... MainWindow.menu.plugins.uninstallPlugins=Pr\u016fvodce odinstalac\u00ed... ConfigView.section.ipfilter.totalIPs=%1 Celkov\u011b blokovano IP, kter\u00e9 tvo\u0159\u00ed %2 z internetu. update.instance.install=\u010cekejte instaluji update.instance.uninstall=\u010cekejte odinstaluji update.instance.update=\u010cekejte aktualizuji MainWindow.status.update.tooltip=Dvakr\u00e1t klikni pro zobrazen\u00ed informac\u00ed updater.progress.window.title=Aktu\u00e1ln\u00ed instala\u010dn\u00ed \u00fakoly updater.progress.window.info=Stiskem 'Abort' ukon\u010d\u00ed v\u0161echny vyjime\u010dn\u00e9 \u00fakoly Button.abort=P\u0159eru\u0161it ConfigView.section.ipfilter.enablebanning=Blokovat u\u017eivatele, kte\u0159\u00ed opakovan\u011b pos\u00edlaj\u00ed \u0161patn\u00e1 data Network.alert.acceptfail=Velk\u00fd po\u010det po sob\u011b jdouc\u00edch poruch na portu %1, %2 - zpracov\u00e1n\u00ed ukon\u010deno. Pros\u00edm zkontrolujte nastaven\u00ed internetov\u00e9 ochrany a ujist\u011bte se, \u017ee m\u00e1te na tomto portu povoleno navazov\u00e1n\u00ed p\u0159ipojen\u00ed. MyShares.column.category=Kategorie UpdateWindow.restartLater=Restartovat pozd\u011bji MainWindow.menu.file.restart=Restartovat Vuze MainWindow.dialog.restartconfirmation.title=Restartovat Azurea? MainWindow.dialog.restartconfirmation.text=Chcete restartovat Azurea? deletetorrent.message1=Chcete smazat TORRENT z :\n deletetorrent.message2=\nJste si jist\u00fd, \u017ee chete pokra\u010dovat? ConfigView.label.prioritizemostcompletedfiles=Up\u0159ednost\u0148ovat jen dokon\u010den\u00e9 soubory splash.plugin.init=Aktualizace Plugin: ConfigView.section.style.osx_small_fonts=Pou\u017e\u00edt mal\u00e9 fonty [vy\u017eaduje restart] ConfigView.section.tracker.tcpnonblocking=Pou\u017e\u00edvejte neblokov\u00e1n\u00ed I/O pro zpracov\u00e1n\u00ed TCP trackeru. Vybr\u00e1n\u00ed t\u00e9to volby vy\u017eaduje p\u0159id\u011blen\u00ed alternativn\u00edho portu pro server. Experiment\u00e1ln\u00ed mo\u017enost! ConfigView.section.tracker.nonblocking=Neblokujic\u00ed mo\u017enosti ConfigView.section.tracker.nonblockingconcmax=Maximum soub\u011b\u017en\u00fdch p\u0159ipojen\u00ed [0: bezlimitu] ConfigView.group.scrape=Probl\u00e9m ConfigView.section.tracker.client.scrapeinfo=Zak\u00e1z\u00e1n\u00edm scraping zabr\u00e1nite torrent\u016fm \u0159azen\u00ed se do fronty dle pravidel spoleh\u00e1j\u00edc\u00ed jen na informace swarmu z\u00edskan\u00e9 scrapingem tracker\u016f. ConfigView.section.tracker.client.scrapeenable=Povolit scraping ConfigView.section.tracker.client.scrapestoppedenable=Scrape torrenty, kter\u00e9 neb\u011b\u017e\u00ed Scrape.status.disabled=Scrape zak\u00e1z\u00e1n MyTorrentsView.menu.explore=Zobrazit soubor MyTorrentsView.menu.explore._mac=Zobrazit vyhled\u00e1v\u00e1n\u00ed MyTorrentsView.menu.explore._windows=Zobrazit Explorer wizard.maketorrents.autohost=Hostitel torrent\u016f m\u00e1 vytvo\u0159en\u00fd server ConfigView.label.overrideip=IP adresa pos\u00edlan\u00e1 trackeru - Pou\u017eijte pouze pokud v\u00edte, pro\u010d to pot\u0159ebujete! ConfigView.label.overrideip.tooltip=Informace pro sever z r\u016fzn\u00fdch IP adres pro odch\u00e1zej\u00edc\u00ed a p\u0159ich\u00e1zej\u00edc\u00ed pakety. Tuto volbu nepou\u017e\u00edvejte. ConfigView.section.connection.group.networks=S\u00edt\u011b ConfigView.section.connection.group.networks.info=Vyberte standartn\u00ed povolen\u00e9 s\u00ed\u0165\u011b pro p\u0159enos dat mezi klienty ConfigView.section.connection.networks.prompt=Vyzvat k v\u00fdb\u011bru, kdy\u017e je p\u0159id\u00e1no stahov\u00e1n\u00ed z anonymn\u00edho trackeru ConfigView.section.connection.networks.Public=Ve\u0159ejn\u00e1 IP s\u00ed\u0165 (neanonymn\u00ed) ConfigView.section.connection.networks.I2P=I2P s\u00ed\u0165 ConfigView.section.connection.networks.Tor=Router (Tor) s\u00ed\u0165 TableColumn.header.networks=S\u00ed\u0165 TableColumn.header.networks.info=S\u00ed\u0165 povoluje peer-peer data spojen\u00ed Scrape.status.networkdisabled=S\u00ed\u0165 nen\u00ed povolena ConfigView.section.tracker.server.group.networks=S\u00edt\u011b ConfigView.section.tracker.server.group.networks.info=Vyberte s\u00edt\u011b pro kter\u00e9 tracker p\u0159ijme stahuji\u00edc\u00ed u\u017eivatele window.networkselection.title=Vybrat s\u00ed\u0165 window.networkselection.info=Torrent uvedeny dole v seznamu servru(u) podporuje n\u00e1sleduj\u00edc\u00ed s\u00edt\u011b.\nPovolte jeden server pro p\u0159\u00edm\u00e9 p\u0159ipojen\u00ed.\nJestli je to anonimn\u00ed server, kter\u00fd podporuje ve\u0159ejn\u00e9 klienty povol\u00edte anonimn\u00ed publikov\u00e1n\u00ed na s\u00edti.\nPovolen\u00ed ve\u0159ejn\u00e9 s\u00edt\u011b m\u00e1 z\u0159ejm\u011b za n\u00e1sledek odstran\u011bn\u00ed anonymity! plugins.basicview.clear=Vy\u010distit ConfigView.section.connection.group.peersources=Stahujic\u00ed zdroje ConfigView.section.connection.group.peersources.info=Vyberte standartn\u00ed p\u0159\u00edpustn\u00e9 zdroje pro p\u0159ipojen\u00ed klient\u016f ConfigView.section.connection.peersource.Tracker=Ze trackeru ConfigView.section.connection.peersource.DHT=Decentralizovan\u00e9 stahov\u00e1n\u00ed ConfigView.section.connection.peersource.PeerExchange=Dodan\u00fd jin\u00fdm u\u017eivatelem ConfigView.section.connection.peersource.Plugin=P\u0159idan\u00fd p\u0159es plugin ConfigView.section.connection.peersource.Incoming=P\u0159\u00edchoz\u00ed p\u0159ipojen\u00ed PeersView.source=Zdroje PeersView.source.info=Zdroje od u\u017eivatel\u016f TableColumn.header.peersources=Klienti TableColumn.header.peersources.info=Klienti, kte\u0159\u00ed maj\u00ed povoleno nav\u00e1z\u00e1n\u00ed p\u0159ipojen\u00ed wizard.tracker.dht=Decentralizovan\u011b jen (klienty Azureusu ) MyTorrentsView.menu.advancedmenu=Pokro\u010dil\u00e9 MyTorrentsView.menu.networks=S\u00edt\u011b MyTorrentsView.menu.peersource=Zdroje klient\u016f ConfigView.section.sharing.permitdht=Povolit decentralizovanou distrubuci, kdy\u017e je server nedostupn\u00fd ConfigView.section.sharing.protocol=Protokol pro spole\u010dn\u00e9 sd\u00edlen\u00ed zdroj\u016f PeersView.Messaging=Zpr\u00e1vy PeersView.Messaging.info=Podporuje pokro\u010dil\u00e9 zpr\u00e1vy API. ConfigView.label.queue.newseedsmovetop=Zobrazit nov\u00e9 kompletn\u00ed torrenty na za\u010d\u00e1tku stahovac\u00edho seznamu ConfigView.label.seeding.firstPriority.ignore.info=M\u011bjte na pam\u011bti, \u017ee pou\u017e\u00edt\u00ed t\u011bchto pravidel, m\u016f\u017ee m\u00edt za n\u00e1sledek zastaven\u00ed torrentu hned jak bude stahov\u00e1n\u00ed ukon\u010deno. ConfigView.label.seeding.firstPriority.ignore=Ignorovat pravidla top priority pro: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrenty s pom\u011brem distribuj\u00edc\u00ed/stahuj\u00edc\u00ed v\u011bt\u0161\u00edm ne\u017e ConfigView.label.seeding.firstPriority.ignore0Peer=Torrenty s 0 u\u017eivateli ConfigView.section.tracker.sendjavaversionandos=Poslat versi Java a n\u00e1zev opera\u010dn\u00edho syst\u00e9mu MagnetPlugin.contextmenu.exporturi=Kop\u00edrovat Magnet URI do schr\u00e1nky ConfigView.section.plugins.dht=Distrubuovan\u00e1 datab\u00e1ze dht.info=Tento dopln\u011bk podporuje decentralizovan\u00e9 distribuov\u00e1n\u00ed, mezi dal\u0161\u00edmi v\u011bcmi, - zak\u00e1z\u00e1n\u00ed bude redukovat Va\u0161i schopnost stahovat dht.enabled=Povolit distribuci database dht.portdefault=Pou\u017eijte standartn\u00ed port dht.port=UDP port pro database dht.execute.command=Diagnostiku p\u0159\u00edkaz\u016f dht.execute.info=Stiskni k vykon\u00e1n\u00ed p\u0159\u00edkazu dht.execute=Spustit dht.logging=Povolit sledov\u00e1n\u00ed aktivit ConfigView.section.plugins.dhttracker=Distribuovan\u00fd server dhttracker.tracknormalwhenoffline=Jen stopa pro norm\u00e1ln\u00ed torrenty, kdy\u017e je jejich sever nedostupn\u00fd ConfigView.section.file.nativedelete._mac=Pou\u017e\u00edt Ko\u0161 p\u0159i maz\u00e1n\u00ed soubor\u016f ConfigView.section.file.nativedelete._windows=P\u0159esunout smazan\u00e9 soubory do ko\u0161e ConfigView.section.logging.generatediagnostics=Generovat ConfigView.section.logging.generatediagnostics.info=Generovat diagnostick\u00e9 informace a kop\u00edrovat je do schr\u00e1nky a do zaznamen\u00e1vac\u00edho souboru, jestli je nasteveno ConfigView.section.sharing.privatetorrent=Soukrom\u00fd torrent - p\u0159ijme jen u\u017eivatele ze trackeru MainWindow.menu.tools.nattest=Test &NAT / internetov\u00e9 ochrany Button.apply=Pou\u017e\u00edt Button.close=Zav\u0159\u00edt window.welcome.title=V\u00edtejte v Azureu %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Pozn\u00e1mky o vyd\u00e1n\u00ed dht.reseed.label=Norm\u00e1ln\u00ed znovudistribuce datab\u00e1ze nen\u00ed nutn\u00e9. Nicm\u00e9n\u011b je-li po\u010det p\u0159ipojen\u00ed n\u00edzk\u00fd, m\u016f\u017eete pou\u017e\u00edt znovuintegraci.\nPonechte pole pr\u00e1zdn\u00e9 pro samozaveden\u00ed p\u0159ipojen\u00fdch klient\u016f nebo vpi\u0161te IP adresu a port pro vylou\u010den\u00ed samozaveden\u00ed od zn\u00e1m\u00e9ho klienta. dht.reseed.group=Znovudistribuovat dht.reseed.ip=IP adresa dht.reseed=Znovudistribuovat dht.reseed.info=Znovudistribuovat datab\u00e1zi dht.diagnostics.group=Diagnostika DHTView.title.full=Distribuce Database DHTView.title.fullcvs=Distribuce Database CVS DHTView.general.title=Hlavn\u00ed DHTView.general.uptime=Doba provozuschopnosti: DHTView.general.users=U\u017eivatel: DHTView.general.nodes=Uzel: DHTView.general.leaves=Odchoz\u00ed: DHTView.general.contacts=kontakty: DHTView.general.replacements=Nahrazen\u00ed: DHTView.general.live=Funk\u010dn\u00ed: DHTView.general.unknown=Nezn\u00e1m\u00ed: DHTView.general.dying=Um\u00edraj\u00edc\u00ed: DHTView.transport.title=Detaily p\u0159enosu DHTView.transport.packets=Pakety DHTView.transport.bytes=Byt\u016f DHTView.transport.received=P\u0159ijato DHTView.transport.sent=Odesl\u00e1no DHTView.transport.in=Vstup: DHTView.transport.out=V\u00fdstup: DHTView.operations.title=Detaily operace DHTView.operations.sent=Odesl\u00e1no DHTView.operations.failed=Ne\u00fasp\u011b\u0161n\u011b DHTView.operations.received=P\u0159ijato DHTView.operations.ping=Odezva serveru DHTView.operations.findNode=Naj\u00edt uzel DHTView.operations.findValue=Naj\u00edt hodnotu DHTView.operations.store=Ulo\u017ei\u0161t\u011b DHTView.activity.title=Aktivita DHTView.activity.status=Stav DHTView.activity.status.true=Ve front\u011b DHTView.activity.status.false=Spustit DHTView.activity.type=Typ DHTView.activity.type.1=Vnit\u0159n\u00ed Get DHTView.activity.type.2=Vn\u011bj\u0161\u00ed Get DHTView.activity.type.3=Vnit\u0159n\u00ed Put DHTView.activity.type.4=Vn\u011bj\u0161\u00ed Put DHTView.activity.target=C\u00edl DHTView.activity.details=Detaily DHTView.db.title=Datab\u00e1ze DHTView.db.keys=Kl\u00ed\u010d DHTView.db.values=Hodnota DHTView.db.local=M\u00edstn\u00ed DHTView.db.direct=P\u0159\u00edm\u00e9 spoejn\u00ed DHTView.db.indirect=Nep\u0159\u00edm\u00e9 spojen\u00ed DHTView.db.divfreq=Frekvence Div. DHTView.db.divsize=Velikost Div. MainWindow.dht.status.tooltip=Kdy\u017e je spu\u0161t\u011bna distribuovan\u00e1 datab\u00e1ze, je zobrazen aktu\u00e1ln\u00ed po\u010det p\u0159ipojen\u00fdch u\u017eivatel\u016f. MainWindow.dht.status.disabled=Zak\u00e1z\u00e1no MainWindow.dht.status.failed=Selh\u00e1n\u00ed MainWindow.dht.status.initializing=Inicializace MainWindow.dht.status.users=%1 U\u017eivatel\u00e9 MainWindow.dht.status.unreachable=K DHT se nelze p\u0159ipojit kv\u016fli Va\u0161\u00ed internetov\u00e9 ochran\u011b. MainWindow.dht.status.unreachabletooltip=V distribuovan\u00e9 datab\u00e1zi pravd\u011bpodobn\u011b je probl\u00e9m s UDP portem mapov\u00e1n\u00ed (NAT/firewall). MyTorrentsView.menu.setUpSpeed=nastavit rychlost odes\u00edl\u00e1n\u00ed MyTorrentsView.menu.setDownSpeed=Nastavit rychlost stahov\u00e1n\u00ed ConfigView.section.tracker.client.showwarnings=Zobrazit v\u00fdstra\u017en\u00e9 zpr\u00e1vy trackeru dht.advanced=Povolit pokro\u010dil\u00e9 nastaven\u00ed dht.advanced.group=Pokro\u010dil\u00e9 nastaven\u00ed dht.advanced.label=Pou\u017eijte tyto hodnoty, jestli\u017ee skute\u010dn\u011b v\u00edte, co d\u011bl\u00e1te dht.override.ip=Ov\u011b\u0159it extern\u00ed IP adresu ConfigView.section.logging.loggerenable=Povolit logov\u00e1n\u00ed ConfigView.section.ipfilter.blockbanning=Zak\u00e1zat blok 256 IP adres, pokud alespo\u0148 toto mno\u017estv\u00ed z bloku bylo zak\u00e1z\u00e1no MyTrackerView.passive=Pasivn\u00ed TableColumn.header.swarm_average_speed=Swarm Pr\u016fm\u011brn\u00e1 rychlost TableColumn.header.swarm_average_speed.info=Pr\u016fm\u011brn\u00e1 rychlost peers in the swarm MyTrackerView.category=Kategorie MainWindow.menu.file.open.torrentfortracking=Torrent Soubory... (Tracking Only) MyTrackerView.date_added=P\u0159id\u00e1no ConfigView.section.tracker.portbackup=Z\u00e1lo\u017en\u00ed port (odd\u011blte st\u0159edn\u00edkem ";") ConfigView.label.playfilespeech=Ozn\u00e1mit kdy\u017e je soubor ukon\u010den ConfigView.label.playfilespeech.info=Hovorov\u00e9 slu\u017eby pracuji jen s angli\u010dtinou ConfigView.label.playfilefinished=P\u0159ehraje zvuk p\u0159i ukon\u010den\u00ed souboru ConfigView.label.backupconfigfiles=Z\u00e1lo\u017en\u00ed konfigura\u010dn\u00ed soubory pro obnoven\u00ed ConfigView.section.tracker.client.scrapesingleonly=Zak\u00e1zat scrape agregaci pro ka\u017ed\u00fd torrent (m\u016f\u017ee pomoci tracker\u016fm, kter\u00e9 hl\u00e1s\u00ed chybu 'URL too long' (414)) dht.ipfilter.log=Zapisovat naru\u0161en\u00ed IP Filtru ConfigView.label.seeding.addForSeedingDLCopyCount=P\u0159id\u00e1 do stahovac\u00edho seznamu downloads, a vyp\u00ed\u0161e po\u010det sta\u017een\u00fdch kopii ActivityView.legend.limit=Rychlostn\u00ed limit ActivityView.legend.achieved=Dosa\u017een\u00e1 rychlost ActivityView.legend.peeraverage=Pr\u016fm\u011br ActivityView.legend.swarmaverage=Pr\u016fm\u011br sd\u00edlen\u00ed MyTorrentsView.menu.movemenu=P\u0159esunout soubor MyTorrentsView.menu.movedata=P\u0159esunout datov\u00e9 soubory.... MyTorrentsView.menu.movetorrent=P\u0159esunout torrent soubory... MyTorrentsView.menu.movedata.dialog=Vyberta nov\u00e9 um\u00edst\u011bn\u00ed DHTView.general.reachable=Dosa\u017eiteln\u00fd: DHTView.general.rendezvous=Setk\u00e1n\u00ed: ConfigView.label.queue.maxactivetorrentswhenseeding=Max. po\u010det stah. u\u017eivatel\u016f [0: neomezen\u011b] Views.plugins.IRC.title=IRC - Online Technick\u00e1 popora Formats.units.persec=za s Formats.units.alot=Hodn\u011b !!! ConfigView.section.ipfilter.persistblocking=Ulo\u017eit blokovan\u00e9 detaily IP adres po restartu FilesView.menu.rename=P\u0159ejmenovat nebo zm\u011bnit c\u00edl FilesView.rename.choose.path=Vyberte nov\u00fd nebo existuj\u00edc\u00ed soubor FilesView.rename.confirm.delete.title=Potvr\u010fte smaz\u00e1n\u00ed FilesView.rename.confirm.delete.text=Potvr\u010fte smaz\u00e1n\u00ed origin\u00e1ln\u00edho souboru '%1' ConfigView.section.mode=M\u00f3d ConfigView.section.mode.title=U\u017eivatelsk\u00e9 znalosti ConfigView.section.mode.beginner=Za\u010d\u00e1te\u010dn\u00edk ConfigView.section.mode.beginner.wiki.definitions=BitTorrent slovn\u00edk ConfigView.section.mode.intermediate=St\u0159edn\u011b zku\u0161en\u00fd ConfigView.section.mode.intermediate.wiki.host=Nab\u00edzen\u00e9 soubory ConfigView.section.mode.intermediate.wiki.publish=Publikovan\u00e9 soubory ConfigView.section.mode.advanced=Pokro\u010dil\u00e9 ConfigView.section.mode.advanced.wiki.main=Hlavn\u00ed str\u00e1nka Wiki ConfigView.section.mode.beginner.text=Obsahuje v\u0161e, co pot\u0159ebujete na stahov\u00e1n\u00ed torrent\u016f.\nPou\u017eijte tento m\u00f3d pokud chcete pouze stahovat a \u0159\u00eddit Va\u0161e torrenty. ConfigView.section.mode.intermediate.text=P\u0159\u00edstup k funkc\u00edm serveru.\nPou\u017eijte tento m\u00f3d, jestli\u017ee chcete vytvo\u0159it sv\u016fj server a hostovat/publkovat Va\u0161e soubory. ConfigView.section.mode.advanced.text=P\u0159\u00edstup k s\u00ed\u0165ov\u00e9mu nastaven\u00ed.\nPou\u017eijte tento m\u00f3d jen jestli v\u00edte co to je MTU nebo neblokovan\u00e9 I/O... Files.column.storagetype=Typ ulo\u017een\u00ed FileItem.storage.linear=Line\u00e1rn\u00ed FileItem.storage.compact=Kompaktn\u00ed MessageBoxWindow.rememberdecision=Zapamatovat moje rozhodnut\u00ed ConfigView.section.interface.cleardecisions=Smazat ulo\u017een\u00e9 dialogy ConfigView.section.interface.cleardecisionsbutton=Vy\u010distit configureWizard.welcome.usermodes=Toto nastaven\u00ed odbornosti u\u017eivatele ur\u010d\u00ed, jak\u00e9 mo\u017enosti se budou zobrazovat v menu N\u00e1stroje > Mo\u017enosti. Je ve va\u0161em z\u00e1jmu nastavit \u00farove\u0148 podle skute\u010dnosti. FilesView.skip.confirm.delete.text=Zmen\u0161it soubor '%1' pro ulo\u017een\u00ed? FilesView.rename.failed.title=P\u0159ejmenovat/\u0161patn\u00e9 zad\u00e1n\u00ed c\u00edle FilesView.rename.failed.text=Tato operace selhala, pravd\u011bpodobn\u011b kv\u016fli volb\u011b neplatn\u00e9ho c\u00edle diagnostics.log_found=Vuzenebyl ukon\u010den spr\u00e1vn\u011b. Pros\u00edm zkontrolujte %1 diagnostiku zaznamen\u00e1vac\u00edho souboru a zva\u017ete, zda tuto zpr\u00e1vu nahl\u00e1s\u00edte Vuze t\u00fdmu technick\u00e9 podpory, pokud jste chybu nezavinil Vy s\u00e1m. Tak\u00e9 zkontrolujte sekci 'Vuze Disappears' (ne\u010dekan\u00e1 vypnut\u00ed Azurea) ve Wiki (menu N\u00e1pov\u011bda). ManagerItem.paused=Pauza Utils.link.visit=\u010cekejte Pros\u00edm ConfigView.section.connection.serverport.wiki=V\u00fdb\u011br dobr\u00fdch port\u016f ConfigView.section.transfer.speeds.wiki=Dob\u0159e nastaven\u00e1 rychlost installPluginsWizard.installMode.info.title=Informace installPluginsWizard.installMode.info.text=K pr\u00e1ci Azurea nepot\u0159ebujete tento dopln\u011bk, zm\u011bn\u00ed se jen dopl\u0148kov\u00e9 rysy, automatizace nebo d\u00e1lkov\u00e9 ovl\u00e1d\u00e1n\u00ed.\nPros\u00edm p\u0159e\u010dt\u011bte si ka\u017ed\u00fd popis dopl\u0148ku pe\u010dliv\u011b p\u0159edt\u00edm, ne\u017e se rozhodnete jej nainstalovat.\nV\u011bt\u0161ina plugin\u016f je bezpe\u010dn\u00e1 a d\u016fkladn\u011b ov\u011b\u0159en\u00e1, av\u0161ak nedoporu\u010dujeme stahovat pluginy o kter\u00fdch v\u00edte, \u017ee je nebudete pou\u017e\u00edvat. Views.plugins.Distributed.DB.title=Distribuce DB Views.plugins.Distributed.Tracker.title=Distribuce servru openUrl.url.info=Podporuje http, https, magnet and hexadecim\u00e1ln\u00ed infohash \u0159et\u011bzce TableColumn.header.swarm_average_completion=Pr\u016fm\u011brn\u00e9 dokon\u010den\u00ed klient\u016f TableColumn.header.swarm_average_completion.info=Pr\u016fm\u011brn\u00e9 procento dokon\u010den\u00ed stahov\u00e1n\u00ed klienty v torrentu GeneralView.label.swarm_average_completion=Pr\u016fm\u011br dokon\u010den\u00ed: GeneralView.label.swarm_average_completion.tooltip=Pr\u016fm\u011br dokon\u010den\u00ed v procentech (klient\u016f torrentu) MainWindow.nat.status.tooltip.unknown=Dosa\u017eitelnost ostatn\u00edch u\u017eivatel\u016f p\u0159es internetovou ochranu/NAT je nezn\u00e1m\u00e1 (TCP), pravd\u011bpodobn\u011b proto\u017ee nejsou spu\u0161t\u011bny \u017e\u00e1dn\u00e9 torrenty MainWindow.nat.status.ok=NAT je v po\u0159\u00e1dku MainWindow.nat.status.tooltip.ok=Dosa\u017eitelnost je v po\u0159\u00e1dku (TCP) MainWindow.nat.status.tooltip.probok=Dosa\u017eitelnost je v po\u0159\u00e1dku, ale nep\u0159ich\u00e1zej\u00ed \u017e\u00e1dn\u00e9 TCP p\u0159ipojen\u00ed MainWindow.nat.status.bad=Internetov\u00e1 ochrana MainWindow.nat.status.tooltip.bad=Zji\u0161t\u011bn\u00fd probl\u00e9m s internetovou ochranou/NAT (TCP). Informace a n\u00e1pov\u011bdu najdete na Wiki plugin.installer.recommended.plugin=Doporu\u010den\u00fd plugin - pros\u00edm pohl\u00e9dn\u011bte si ho, v p\u0159\u00edpad\u011b nutnosti a nainstalujte LoggerView.pause=Pause z\u00e1pisu LoggerView.clear=&Vy\u010distit LoggerView.filter=Filtr LoggerView.filter.uncheckAll=Nekontrolovat v\u0161echny kategorie LoggerView.filter.checkAll=Kontrola v\u0161ech kategori\u00ed LoggerView.loggingDisabled=Z\u00e1pis nen\u00ed povolen ConfigView.section.logging.log0type=Informace ConfigView.section.logging.log1type=Varov\u00e1n\u00ed ConfigView.section.logging.log2type=Chyba ConfigView.section.logging.filter=Filtrovat kdy\u017e zapisuji do souboru ConfigView.section.logging.level=\u00darove\u0148 log ConfigView.section.logging.showLogsFor=Zobrazit %1 logy z n\u00e1sleduj\u00edcich kategori\u00ed: ConfigView.pluginlist.column.type=Typ ConfigView.pluginlist.column.type.perUser=Ka\u017ed\u00fd u\u017eivatel ConfigView.pluginlist.column.type.shared=Sd\u00edlet ConfigView.pluginlist.column.type.builtIn=Zapojit ConfigView.pluginlist.column.name=Jm\u00e9no/N\u00e1zev ConfigView.pluginlist.column.version=Verze ConfigView.pluginlist.column.directory=Adres\u00e1\u0159 ConfigView.pluginlist.column.isOperational=Opera\u010dn\u00ed? PeersView.BlockView.Avail.Have=Oba maj\u00ed PeersView.BlockView.Avail.NoHave=Klient m\u00e1, Vy nem\u00e1te PeersView.BlockView.NoAvail.Have=Vy m\u00e1te, klient nem\u00e1 PeersView.BlockView.NoAvail.NoHave=Ani jeden z v\u00e1s nem\u00e1 PeersView.BlockView.Transfer=P\u0159enosy PeersView.BlockView.NextRequest=Dal\u0161\u00ed po\u017eadavek PeersView.BlockView.title=Mapov\u00e1n\u00ed PeersView.BlockView.AvailCount=Dostupn\u00fd po\u010det MyTorrentsView.dialog.NumberError.title=\u0160patn\u00e9 nebo nezn\u00e1m\u00e9 \u010d\u00edslo MyTorrentsView.dialog.NumberError.text=\u010c\u00edslo, kter\u00e9 jste vlo\u017eili je \u0161patn\u00e9 nebo nezn\u00e1m\u00e9. MyTorrentsView.menu.manual=&Manu\u00e1l MyTorrentsView.dialog.setSpeed.title=Set %1 rychlost # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Pro vstup zadejte \u010d\u00edslo %1 ke zm\u011bn\u011b %2 to: MyTorrentsView.dialog.setNumber.upload=odes\u00edl\u00e1n\u00ed MyTorrentsView.dialog.setNumber.download=stahov\u00e1n\u00ed MyTorrentsView.dialog.setNumber.inKbps=v %1 OpenTorrentWindow.torrentLocation=Torrent soubory: OpenTorrentWindow.addFiles.URL=P\u0159idat &URL OpenTorrentWindow.addFiles.Folder=P\u0159idat &Adres\u00e1\u0159 OpenTorrentWindow.addFiles.Clipboard=P\u0159idat ze Sch&r\u00e1nky OpenTorrentWindow.changeDestination=Zm\u011bnit um\u00edst\u011bn\u00ed OpenTorrentWindow.fileList=Soubory v torrents: OpenTorrentWindow.torrentTable.name=N\u00e1zev OpenTorrentWindow.torrentTable.saveLocation=Ulo\u017eit um\u00edst\u011bn\u00ed OpenTorrentWindow.fileTable.fileName=N\u00e1zev souboru OpenTorrentWindow.fileTable.size=Velikost OpenTorrentWindow.fileTable.destinationName=Jm\u00e9no c\u00edle OpenTorrentWindow.startMode.seeding=Distrubuce OpenTorrentWindow.fileList.changeDestination=Zm\u011bnit um\u00edst\u011bn\u00ed OpenTorrentWindow.mb.badSize.title=Neslu\u010diteln\u00fd soubor OpenTorrentWindow.mb.badSize.text='%1' nen\u00ed '%2' a nem\u016f\u017ee b\u00fdt pou\u017eit pro distribuci OpenTorrentWindow.mb.alreadyExists.text=%3 ji\u017e byl p\u0159id\u00e1n jako '%2' OpenTorrentWindow.mb.alreadyExists.title=Torrent ji\u017e existuje OpenTorrentWindow.mb.openError.title=Chyba ote\u0159en\u00ed OpenTorrentWindow.mb.openError.text='%1' nelze otev\u0159\u00edt: OpenTorrentWindow.torrent.remove=Odstranit seznam torrent\u016f OpenTorrentWindow.torrent.options=N\u00e1sleduj\u00edc\u00ed nastaven\u00ed bude aplikov\u00e1no na vybran\u00e9 torrenty: OpenTorrentWindow.xOfTotal=(%1 z %2) iconBar.open.tooltip=Otev\u0159\u00edt Torrent(y) LocaleUtil.column.text=Nezn\u00e1m\u00fd text Tracker.tooltip.MultiSupport=Tento server podporuje v\u00edcen\u00e1sobn\u00e9 hashov\u00e1n\u00ed a scrapes na po\u017e\u00e1d\u00e1n\u00ed. Tracker.tooltip.NoMultiSupport=Tento server nepodporuje v\u00edcen\u00e1sobn\u00e9 hashov\u00e1n\u00ed a scrapes na po\u017e\u00e1d\u00e1n\u00ed. ConfigView.label.lazybitfield=Pou\u017eit\u00ed pomal\u00e9ho bitov\u00e9ho pole (pom\u00e1h\u00e1 vzniku sitov\u00fdch chyb- pou\u017e\u00edv\u00e1n\u00edm blokov\u00e1n \u00edbitov\u00fdch pol\u00ed) LoggerView.realtime=Update v re\u00e1ln\u00e9m \u010dase ConfigView.section.file.perf.cache.flushpieces=Zapisuje ihned kompletn\u00ed d\u00edly na disk. Toto zjednodu\u0161uje p\u0159\u00edstup na na disk, ale m\u016f\u017ee to m\u00edt za n\u00e1sledek vice opera\u010dn\u00edch z\u00e1pis\u016f. ConfigView.section.file.writemblimit=Maximum \u017e\u00e1dosti o z\u00e1pis ve front\u011b (in %1) ConfigView.section.file.writemblimit.explain=Kdy\u017e se zapisuje na disk rychlost\u00ed men\u0161\u00ed ne\u017e je rychlost stahov\u00e1n\u00ed ,tento parametr omez\u00ed kolik dat bude front\u011b ne\u017e se sta\u017een\u00e1 data zredukuj\u00ed. ConfigView.section.file.readmblimit=Maxim\u00e1ln\u00ed po\u010det \u017e\u00e1dost\u00ed ve front\u011b k na\u010dten\u00ed (in %1) ConfigView.section.file.readmblimit.explain=Tento parametr limituje kolik pam\u011bti bude pou\u017eito na ulo\u017een\u00ed pro nevy\u0159e\u0161en\u00e9 procesy. Button.moveUp=Posunout nahoru Button.moveDown=Posunout dol\u016f ConfigView.notAvailableForMode=Tato \u010d\u00e1st je ur\u010dena k %1 m\u00f3du nebo vy\u0161\u0161\u00ed. je nedosa\u017eiteln\u00fd v %2 m\u00f3du. health.explain.error=Chyba torrentu. Pod\u00edvejte se do stavov\u00e9ho sloupce, nebo na n\u00e1strojov\u00fd tip pro zji\u0161t\u011bn\u00ed chyby. PeersView.piece=D\u00edly PeersView.piece.info=\u010c\u00edslo posledn\u00edho po\u017eadovan\u00e9ho d\u00edlu PiecesView.priority=Priorita PiecesView.priority.info=Tyto d\u00edly jsou prioritou dokon\u010den\u00ed, ale nevy\u017eaduj\u00ed mnoho pozornosti PiecesView.speed=Rychlost PiecesView.speed.info=Pomal\u00fdm klient\u016fm je \u010d\u00e1ste\u010dn\u011b blokov\u00e1n p\u0159\u00edstup k rychl\u00fdm d\u00edl\u016fm TableColumn.header.AvgAvail.info=Sou\u010det po\u010dtu dostupnosti d\u011blen\u00e9 # po\u010dtem p\u0159ipojen\u00ed # connections TableColumn.header.AvgAvail=Pr\u016fm\u011brn\u00e1 dostupnost/d\u00edl ConfigView.label.strictfilelocking=Zabezpe\u010dte svoje soubory, zamezen\u00edm p\u0159\u00edstupu p\u0159es torrenty MyTorrentsView.menu.rescanfile=Periodicky kontrolvat ne\u00fapln\u00e9 d\u00edly Plugin.extseed.name=Extern\u00ed klienti Plugin.localtracker.name=LAN vyhled\u00e1va\u010d klient\u016f Plugin.localtracker.info=LAN vyhledava\u010d klient\u016f povolil v\u00edcen\u00e1sobn\u00e9 kopie z Azurea za firewallem a na b\u011b\u017en\u00e9 sit\u00ed\nefektivn\u00ed download torrent\u016f umo\u017e\u0148uj\u00edc\u00ed p\u0159\u00edm\u00e9 p\u0159ipojen\u00ed mezi nimi. Plugin.localtracker.enable=Povolit LAN vyhled\u00e1n\u00ed klient\u016f azinstancehandler.alert.portclash=Nastaven\u00fd port v LAN: %1 je pou\u017e\u00edvan\u00e1 jin\u00fdm u\u017eivatele (programem), vyberte nov\u00fd p\u0159\u00edchoz\u00ed port (s) pro p\u0159\u00edchoz\u00ed TCP / UDP naslouch\u00e1n\u00ed [mezi %2 and %3]. ConfigView.section.transfer.lan.tooltip=LAN - specifick\u00e9 nastaven\u00ed ConfigView.section.transfer.lan.uploadrate=KB/s LAN maxim\u00e1ln\u00ed rychlost odes\u00edl\u00e1n\u00ed [0: neomezeno] ConfigView.section.transfer.lan.uploadrate.tooltip=Klienti p\u0159ipojen\u00ed ve stejn\u00e9 vnit\u0159n\u00ed s\u00edti LAN maj\u00ed odd\u011blen\u00fd limit odes\u00edlan\u00fdch dat. ConfigView.section.transfer.lan.downloadrate=KB/s LAN maxim\u00e1ln\u00ed stahovac\u00ed rychlost [0: neomezn\u011b] ConfigView.section.transfer.lan.downloadrate.tooltip=Klienti p\u0159ipojen\u00ed ve stejn\u00e9 vnit\u0159n\u00ed s\u00edti LAN maj\u00ed odd\u011blen\u00fd limit stahovan\u00fdch dat. TorrentOptionsView.title.short=Mo\u017enosti TorrentOptionsView.title.full=Mo\u017enosti TorrentOptionsView.param.max.peers=Max. po\u010det p\u0159ipojen\u00ed [0: neomezen\u011b] ConfigView.section.connection.encryption.require_encrypted_transport=Po\u017eadujte \u0161ifrovan\u00fd p\u0159enos ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Vynucen\u00e9 pou\u017eit\u00ed \u0161ifrov\u00e1n\u00e9ho p\u0159ipojen\u00ed s dal\u0161\u00edmi klienty. ConfigView.section.connection.encryption.min_encryption_level=Minim\u00e1ln\u00ed \u0161ifrovac\u00ed \u00farove\u0148 ConfigView.section.connection.encryption.min_encryption_level.tooltip=P\u0159\u00edm\u00e9 propojen\u00ed jen v\nRC4 - pln\u00fd proud\n\u0160ifrov\u00e1n\u00ed v\u00edce zat\u011b\u017euje procesor. Peers.column.Encryption=\u0160ifrov\u00e1n\u00ed Peers.column.Encryption.info=\u00darove\u0148 pou\u017eit\u00e9ho \u0161ifrov\u00e1n\u00ed ConfigView.section.connection.encryption.encrypt.info=M\u00e1te-li povolen \u0161ifrovan\u00fd p\u0159enos. nebudete se moci p\u0159ipojit k nekompabilitn\u00edm klient\u016fm, pokud v nastaven\u00ed nepovol\u00edte nouzovou mo\u017enost p\u0159ipojen\u00ed ConfigView.section.connection.encryption.encrypt.info.link=Pros\u00edm prohl\u00e9dn\u011bte si zobrazen\u00e9 detaily MainWindow.sr.status.tooltip.ok=Pom\u011br sd\u00edlen\u00ed %1 v po\u0159\u00e1dku MainWindow.sr.status.tooltip.poor=Pom\u011br sd\u00edlen\u00ed %1 n\u00edzk\u00fd: < 0.9 MainWindow.sr.status.tooltip.bad=Pom\u011br sd\u00edlen\u00ed %1 p\u0159\u00ed\u0161ern\u00fd: < 0.5 ConfigView.section.style.status=Stav oblasti: ConfigView.section.style.status.show_sr=Koeficient sd\u00edlen\u00ed ConfigView.section.style.status.show_nat=Stav NAT ConfigView.section.style.status.show_ddb=Stav DDB ConfigView.section.connection.encryption.encrypt.group=\u0160ifrovan\u00fd p\u0159enos dat ConfigView.section.connection.encryption.encrypt.fallback_info=Povolit nouzovou mo\u017enost, kter\u00e1 dovol\u00ed spojen\u00ed s nekompatibiln\u00edmi klienty, ALE jen v ne\u0161ifrovan\u00e9m spojen\u00ed ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Povolit neza\u0161ifrovan\u00e9 odchoz\u00ed p\u0159ipojen\u00ed p\u0159i selh\u00e1n\u00ed \u0161ifrovan\u00e9ho odchoz\u00edho p\u0159ipojen\u00ed ConfigView.section.connection.encryption.encrypt.fallback_incoming=Povolit neza\u0161ifrvan\u00e1 p\u0159\u00edchoz\u00ed p\u0159ipojen\u00ed ConfigView.section.connection.encryption=Zaslat \u0161ifrovan\u011b upnp.selectedinterfaces=Vyberte rozhran\u00ed (';' odd\u011blova\u010d, e.g. eth0;eth1) [blank: all] ConfigView.section.style.defaultSortOrder=Standartn\u00ed po\u0159ad\u00ed ConfigView.section.style.defaultSortOrder.desc=Sestupn\u011b ConfigView.section.style.defaultSortOrder.asc=Vzestupn\u011b ConfigView.section.style.defaultSortOrder.flip=Opa\u010dn\u00e9 p\u0159edchoz\u00ed po\u0159ad\u00ed LoggerView.autoscroll=Auto-rolov\u00e1n\u00ed Button.selectAll=Vybrat v\u0161e Button.markSelected=Ozna\u010dit vybran\u00e9 Button.unmarkSelected=Zru\u0161it vybran\u00e9 plugins.basicview.config=Configurace TorrentOptionsView.param.max.uploads=Max. po\u010det upload slotu [minimum: 2] MyTorrentsView.dialog.setPosition.title=Nastaven\u00ed polohy MyTorrentsView.dialog.setPosition.text=Enter potvrd\u00edte vybran\u00e9 torrents: MyTorrentsView.menu.reposition.manual=P\u0159em\u00edstit... ConfigView.section.connection.advanced.info.link=Pros\u00edm pod\u00edvej se na zobrazen\u00e9 detaily ConfigView.section.connection.advanced.socket.group=Mo\u017enosti socketu ConfigView.section.connection.advanced.bind_port=P\u0159ipojit m\u00edstn\u00ed port [0: neomezen\u011b] ConfigView.section.connection.advanced.bind_port.tooltip=Odchoz\u00ed socket p\u0159ipojen\u00ed je sv\u00e1z\u00e1no s m\u00edstn\u00edm dan\u00fdm portem.\nPovolen\u00ed V\u00e1m m\u016f\u017ee pomoci s nestabilnosti NAT routeru. ConfigView.section.proxy.group.tracker=Komunikace se serverem ConfigView.section.proxy.group.peer=Komunikace s klienty Pieces.column.Requested=Po\u017eadovan\u00fd Pieces.column.Requested.info=Ukazuje,zda m\u016f\u017ee b\u00fdt na d\u00edl posl\u00e1no v\u00edce \u017e\u00e1dost\u00ed (*) ConfigView.label.maxuploadsseeding=Alternativn\u00ed standart pro stahuj\u00edc\u00ed u\u017eivatele MyTorrentsView.filter=Filtr: [%1] popup.error.hideall=Skr\u00fdt v\u0161e ConfigView.section.style.dataStatsOnly=Ukazovat pouze statistiky dat (skr\u00fdt statistiky protokol\u016f) ConfigView.section.style.separateProtDataStats=Zobrazit odd\u011blen\u011b data a protokol jako 'data (protocol)' MyTorrentsView.dialog.setFilter.title=Upravit filtr MyTorrentsView.dialog.setFilter.text=Sekce %1 bude filtrovat text, kter\u00fd zde dol\u016f nap\u00ed\u0161ete. Pou\u017eijte symbol | (svisl\u00e1 \u010d\u00e1ra) pro filtrov\u00e1n\u00ed souslov\u00ed. MyTorrentsView.filter.tooltip=Pou\u017eijte Ctrl+X pro p\u0159ep\u00edn\u00e1n\u00ed mezi RexEx a norm\u00e1ln\u00edm vyhled\u00e1vac\u00edm m\u00f3dem.\n Pou\u017eijte symbol | (svisl\u00e1 \u010d\u00e1ra) pro filtrov\u00e1n\u00ed souslov\u00ed. MyTorrentsView.clearFilter.tooltip=Vy\u010distit filtr MyTorrentsView.menu.filter=Filtr list... ConfigureWizard.language.choose=Choose a language from the list below (Vyberte si jazyk z n\u00e1sleduj\u00edc\u00edch): popup.closing.in=Okno se samo zav\u0159e za %1 sekund. popup.more.waiting=%1 zb\u00fdvaj\u00edc\u00ed zpr\u00e1vy. # > 2402 popup.download.finished="%1" dokon\u010dil stahov\u00e1n\u00ed. popup.file.finished="%1" dokon\u010dil stahov\u00e1n\u00ed. Plugin.localtracker.autoadd.info=Automaticky p\u0159id\u00e1vat tyto klienty (adresy odd\u011blte st\u0159edn\u00edkem ";"): Plugin.localtracker.autoadd=Explicitn\u00ed klienti Plugin.localtracker.networks.info=Pova\u017eovat n\u00e1sleduj\u00edc\u00ed s\u00edt\u011b za m\u00edstn\u00ed (adresy odd\u011blte st\u0159edn\u00edkem ";"): Plugin.localtracker.networks=M\u00edstn\u00ed s\u00edt\u011b SpeedView.stats.autospeed=Automatick\u00e1 rychlost odes\u00edl\u00e1n\u00ed SpeedView.stats.autospeed.disabled=tato mo\u017enoat je bu\u010f zak\u00e1z\u00e1na (pot\u0159ebujete DHT) nebo se nepou\u017e\u00edv\u00e1 (je vybr\u00e1no manu\u00e1ln\u00ed nastaven\u00ed odchoz\u00ed rychlosti). SpeedView.stats.idlePing=Pomal\u00e1 odezva (ping): SpeedView.stats.maxPing=Maxim\u00e1ln\u00ed odezva (ping): SpeedView.stats.currentPing=Sou\u010dasn\u00e1 odezva (ping): SpeedView.stats.maxUp=Maxim\u00e1ln\u00ed odchoz\u00ed rychlost ConfigView.section.transfer.autospeed=Automatick\u00e1 rychlost ConfigView.section.transfer.autospeed.tooltip=Specifick\u00e9 nastaven\u00ed automatick\u00e9 rychlosti ConfigView.section.transfer.autospeed.info=Automatick\u00e1 rychlost automaticky nastavuje rychlost odes\u00edl\u00e1n\u00ed dat, aby nedoch\u00e1zelo k p\u0159et\u00ed\u017een\u00ed s\u00edt\u011b.\n\u005cTyto limity budou pou\u017eity pouze pokud je povoleno automatick\u00e9 nastaven\u00ed odchoz\u00ed rychlosti a pokud je povolena distrubuovan\u00e1 datab\u00e1ze\n ConfigView.section.transfer.autospeed.minupload=%1 minim\u00e1ln\u00ed rychlost odes\u00edl\u00e1n\u00ed dat ConfigView.section.transfer.autospeed.minupload.tooltip=Rychlost odes\u00edl\u00e1n\u00ed dat nebude automaticky sni\u017eov\u00e1na pod tuto hranici ConfigView.section.transfer.autospeed.maxupload=%1 maxim\u00e1ln\u00ed odchoz\u00ed rychlost [0: neomezen\u011b] ConfigView.section.transfer.autospeed.maxupload.tooltip=Rychlost odes\u00edl\u00e1n\u00ed dat nebude automaticky zvy\u0161ov\u00e1na nad tuto hranici ConfigView.section.transfer.autospeed.chokeping=Choking ping time [ms] ConfigView.section.transfer.autospeed.chokeping.tooltip=\u010casy odezvy (ping) nad tuto hodnotu budou pova\u017eov\u00e1ny za indik\u00e1tor saturace s\u00edt\u011b ConfigView.section.transfer.autospeed.enableauto=Povolit p\u0159i stahov\u00e1n\u00ed a distrubuci ConfigView.section.transfer.autospeed.enableautoseeding=Povolit pouze p\u0159i distrubuci ConfigView.section.transfer.lan.enable=Povolit odd\u011blen\u00ed rychlostn\u00edch limit\u016f pro LAN s\u00edt\u011b Plugin.localtracker.wellknownlocals=Automaticky p\u0159idat zkracov\u00e1n\u00ed/odkaz/str\u00e1nka m\u00edstn\u00ed s\u00edt\u011b (192.168. atd.) TableColumn.header.filesdone=Pln\u011b dokon\u010deno soubor\u016f: TableColumn.header.filesdone.info=Dokon\u010den\u00e9 soubory/kompletn\u00ed soubory *nebo* Dokon\u010den\u00e9 nep\u0159esko\u010den\u00e9 soubory (Dokon\u010den\u00e9 soubory)/V\u0161echny nep\u0159esko\u010den\u00e9 soubory (V\u0161echny soubory) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=\u010dek\u00e1m na inicializaci DDB... MagnetPlugin.report.searching=vyhled\u00e1v\u00e1m... MagnetPlugin.report.found=nalezeno %1 MagnetPlugin.report.alive=%1 je na \u017eivu MagnetPlugin.report.dead=%1 je mrtv\u00fd MagnetPlugin.report.tunnel=dost\u00e1v\u00e1m se do %1 MagnetPlugin.report.downloading=stahuji z %1 MagnetPlugin.report.error=chyba %1 MagnetURLHandler.report.no_sources=pro torrent nebyly nalezeny \u017e\u00e1dn\u00e9 zdroje MagnetURLHandler.report.torrent_size=velikost torrentu: %1 MagnetURLHandler.report.percent=hotovo: %1% MagnetURLHandler.report.error=chyba %1 DHTTransport.report.request_all=po\u017eadov\u00e1n cel\u00fd p\u0159enos od %1 DHTTransport.report.received_bit=p\u0159ijmuto %1 k %2 od %3 DHTTransport.report.complete=hotovo DHTTransport.report.timeout=vypr\u0161el \u010dasov\u00fd limit, od %1 nep\u0159i\u0161la \u017e\u00e1dn\u00e1 odpov\u011b\u010f DHTTransport.report.rerequest_all=znovu po\u017eadov\u00e1n cel\u00fd p\u0159enos od %1 DHTTransport.report.rerequest_bit=znovu po\u017eadov\u00e1no %1 k %2 od %3 DHTTransport.report.timeout_some=vypr\u0161el \u010dasov\u00fd limit, %1 pakety obdr\u017eeny od %2, ale nekompletn\u00ed DHTTransport.report.sending=pos\u00edl\u00e1n\u00ed dat DHTTransport.report.resending=znovupos\u00edl\u00e1n\u00ed dat DHTTransport.report.send_complete=odes\u00edl\u00e1n\u00ed hotovo DHTTransport.report.send_timeout=poslat \u010dasov\u00fd limit ConfigView.section.transfer.autospeed.enabledebug=Zaznamen\u00e1vat informace o odstra\u0148ov\u00e1n\u00ed chyb TableColumn.header.date_added=Datum p\u0159id\u00e1n\u00ed TableColumn.header.date_added.info=datum, kdy byl torrent p\u0159id\u00e1n platform.win32.baddll.info=Vuze detekoval obsah '%1'. Toto je sou\u010d\u00e1st\u00ed '%2' a je zn\u00e1mo t\u00edm, \u017ee n\u011bkdy zp\u016fsobuje probl\u00e9my jako je nap\u0159\u00edklad selh\u00e1v\u00e1n\u00ed program\u016f \u010di vysok\u00e9 vyu\u017e\u00edv\u00e1n\u00ed procesoru. Pokud se s t\u00edmto setk\u00e1v\u00e1te, pros\u00edm odinstalujte tento software nebo ho nastavte tak, aby neru\u0161il Azurea. upnp.ignorebaddevices=Ignorovat za\u0159\u00edzen\u00ed, kter\u00e9 nedok\u00e1\u017e\u00ed spr\u00e1vn\u011b odpov\u00eddat upnp.ignorebaddevices.info=Sou\u010dasn\u011b ignorovan\u00e9 za\u0159\u00edzen\u00ed: %1 upnp.ignorebaddevices.reset=Resetovat ignorovan\u00e9 za\u0159\u00edzen\u00ed upnp.ignorebaddevices.alert=UPnP za\u0159\u00edzen\u00ed v %1 je ignorov\u00e1no vzhledem k opakovan\u00fdm chb\u00e1m. Pod\u00edvejte se na UPnP plugin na nastaven\u00ed, kter\u00e9 se t\u00e9to akce t\u00fdkaj\u00ed. TorrentOptionsView.param.max.uploads.when.busy=Maxim\u00e1ln\u00ed odchoz\u00ed rychlost (KB/s) p\u0159i dosa\u017een\u00ed glob\u00e1ln\u00edho limitu odchoz\u00edch dat (0:zak\u00e1z\u00e1no) UpdateMonitor.messagebox.verification.failed.title=Ov\u011b\u0159en\u00ed instalace selhalo UpdateMonitor.messagebox.verification.failed.text=Ov\u011b\u0159en\u00ed '%1' selhalo: %2 UpdateMonitor.messagebox.accept.unverified.title=P\u0159ijata neov\u011b\u0159en\u00e1 instalace UpdateMonitor.messagebox.accept.unverified.text='%1' nemohl b\u00fdt ov\u011b\u0159en jako ofici\u00e1ln\u00ed Vuze plugin.\nPokud to takov\u00fd plugin nen\u00ed, NEM\u011aLI byste d\u00e1le pokra\u010dovat.\nPokra\u010dovat v instalaci\u00a8? FileView.BlockView.title=D\u00edly souboru FileView.BlockView.Done=Hotovo FileView.BlockView.Skipped=P\u0159esko\u010den\u00fd FileView.BlockView.Active=Aktivn\u00ed FileView.BlockView.Outstanding=V\u00fdjime\u010dn\u00fd upnp.portchange.alert=N\u00e1sleduj\u00edc\u00ed porty byly zm\u011bn\u011bny, aby se p\u0159ede\u0161lo probl\u00e9m\u016fm UPnP: %1 [star\u00fd port=%2] %3 [star\u00fd port=%4] ConfigView.section.proxy.username.info=Pokud proxy server vy\u017eaduje autentifikaci, i kdy\u017e nen\u00ed \u017e\u00e1dn\u00e1 nadefinovan\u00e1, pou\u017eijte jako u\u017eivatelsk\u00e9 jm\u00e9no "" (bez uvozovek) ConfigView.label.maxuploadswhenbusymin=Maxim\u00e1ln\u00ed odchoz\u00ed rychlost na torrent p\u0159i busy timer (s) MainWindow.menu.help.debug=Vygenerovat info o oprav\u011b chyb DownloadManager.error.badsize=Nespr\u00e1vn\u00e1 velikost natpmp.info=NAT-PMP je alternativa Apple k UPnP a je podporov\u00e1na nov\u00fdmi leti\u0161tmi.\n\nPamatujte, \u017ee sou\u010dasn\u00e9 UPnP mus\u00ed b\u00fdt povoleno, aby mohlo b\u00fdt povoleno i NAT-PMP, proto\u017ee NAT-PMP je speci\u00e1ln\u00ed typ za\u0159\u00edzen\u00ed UPnP. natpmp.enable=Povolit (pamatujte, \u017ee toto tak\u00e9 mus\u00edte povolit v Leti\u0161tn\u00ed konfiguraci) ConfigView.section.tracker.host.addurls=Zabezpe\u010dit, \u017ee URL trackeru je obsa\u017eena v hostovan\u00fdch torrentech Tracker.announce.ignorePeerSeed=ignorovat klienti/distrubuto\u0159i count. %1 TorrentOptionsView.param.reset.to.default=Vr\u00e1tit nastaven\u00ed na jejich p\u016fvodn\u00ed hodnoty natpmp.routeraddress=N\u00e1zev stanice (pokud ponech\u00e1te pr\u00e1zdn\u00e9, vypln\u00ed se samo) ConfigView.section.style.disableAlertSliding=Zak\u00e1zat zobrazen\u00ed posunuj\u00edc\u00ed se animace varovn\u00fdch zpr\u00e1v navrchu ConfigView.section.transfer.autospeed.maxinc=%1 maxim\u00e1ln\u00ed zv\u00fd\u0161en\u00ed za cyklus ConfigView.section.transfer.autospeed.maxdec=%1 maxim\u00e1ln\u00ed sn\u00ed\u017een\u00ed za cyklus ConfigView.section.transfer.autospeed.enabledownadj=Dovolit \u00fapravu rychlosti stahov\u00e1n\u00ed ConfigView.section.transfer.autospeed.downadjratio=Pom\u011br rychlost stahov\u00e1n\u00ed/rychlost odes\u00edl\u00e1n\u00ed (nap\u0159. 2.0 -> limit stahov\u00e1n\u00ed je dvakr\u00e1t v\u011bt\u0161\u00ed ne\u017e limit odes\u00edl\u00e1n\u00ed dat) ConfigView.section.transfer.autospeed.latencyfactor=Faktor pou\u017eit\u00fd ke spojen\u00ed skryt\u00fdch sm\u011bn k rychlostn\u00edm zm\u011bn\u00e1m (vy\u0161\u0161\u00ed \u010d\u00edsla sni\u017euj\u00ed citlivost) ConfigView.section.transfer.autospeed.reset=Resetovat pokro\u010dil\u00e9 hodnoty ConfigView.section.transfer.autospeed.reset.button=Resetovat PeerColumn.activationCount=Klienti se sna\u017e\u00ed p\u0159ipojit: %1 TableColumn.header.timesincedownload.info=\u010cas, kter\u00fd uplynul od doby, kdy byly sta\u017eena pro torrent posledn\u00ed data TableColumn.header.timesincedownload=\u010cas od stahov\u00e1n\u00ed TableColumn.header.timesinceupload.info=\u010cas, kter\u00fd uplynul od doby, kdy byly odesl\u00e1na torrent posledn\u00ed data torrentu TableColumn.header.timesinceupload=\u010cas od odes\u00edl\u00e1n\u00ed PeersView.incomingreqcount.info=Po\u010det p\u0159\u00edchoz\u00edch po\u017eadavk\u016f od klienta PeersView.outgoingreqcount.info=Po\u010det odchoz\u00edch po\u017eadavk\u016f ke klientovi upnp.mapping.dhtudp=Distribuovan\u00e1 datab\u00e1ze ConfigView.section.style.showiconbar=Zobrazit n\u00e1strojovou li\u0161tu MyTorrentsView.menu.rename=P\u0159ejmenovat MyTorrentsView.menu.rename.displayed=P\u0159ejmenovat zobrazen\u00e9 jm\u00e9no MyTorrentsView.menu.rename.save_path=P\u0159ejmenovat slo\u017eku, do kter\u00e9 se stahovan\u00e9 soubory ukl\u00e1daj\u00ed MyTorrentsView.menu.rename.displayed.enter.title=P\u0159ejmenovat zobrazen\u00e9 jm\u00e9no MyTorrentsView.menu.rename.displayed.enter.message=Vpi\u0161te nov\u00e9 jm\u00e9no, kter\u00e9 se bude zobrazovat p\u0159i tomto stahov\u00e1n\u00ed.\nPokud nebude veps\u00e1t \u017e\u00e1dn\u00fd text, Vuze pou\u017eije p\u016fvodn\u00ed jm\u00e9no. UIDebugGenerator.messageask.text=Pros\u00edm zadejte popis chyby, kterou nahla\u0161ujete UIDebugGenerator.complete.title=Generace odstran\u011bn\u00ed chyb hotova UIDebugGenerator.complete.text=Pros\u00edm po\u0161lete soubor '%1'.\n\nKlikn\u011bte na OK pro otev\u0159en\u00ed okna k tomuto souboru. ConfigView.section.style.showProgramIcon=Zobrazit ikonu programu v seznamu soubor\u016f ConfigView.section.style.showProgramIcon.tooltip=Zobrazen\u00ed mo\u017en\u00e1 bude vy\u017eadovat znovuotev\u0159en\u00ed, aby m\u011bly zm\u011bny \u00fa\u010dinek swt.alert.cant.update=Knihovna SWT na\u010dten\u00e1 z "%3" nem\u016f\u017ee b\u00fdt automaticky updatovan\u00e1 z %1 na %2 (mmus\u00ed b\u00fdt na\u010dtena z "%4"). Pros\u00edm pod\u00edvejte se na the wiki pro detaily. authenticator.savepassword=Pamatovat si moje heslo ConfigView.section.security.clearpasswords=Resetovat ulo\u017een\u00e9 hesla ConfigView.section.security.clearpasswords.button=Resetovat Content.alert.notuploaded.title=Odeslan\u00e1 data nejsou kompletn\u00ed Content.alert.notuploaded.text=Odesl\u00e1n\u00ed '%1'nen\u00ed dokon\u010deno. Pokud te\u010f %2, klienti nebudou schopni kompletn\u011b st\u00e1hnout V\u00e1mi publikovan\u00e9 soubory.\n\nJste si jsit\u00fd, \u017ee chcete %2? Content.alert.notuploaded.multi.title=Odeslan\u00e1 data nejsou kompletn\u00ed Content.alert.notuploaded.multi.text=%1 V\u00e1mi publikovan\u00e9ho obsahu nen\u00ed kompletn\u011b distribuov\u00e1no. Pokud te\u010f %2, klienti nebudou schopni kompletn\u011b st\u00e1hnout V\u00e1mi publikovan\u00e9 soubory. Skute\u010dn\u011b chcete %2?\n\nTorrent nen\u00ed dostate\u010dn\u011b distrubuov\u00e1n:\n%3 Content.alert.notuploaded.stop=ukon\u010d\u00edte torrent Content.alert.notuploaded.quit=opustit Azurea TorrentInfoView.torrent.encoding=K\u00f3dov\u00e1n\u00ed torrentu TorrentInfoView.columns=Sloupce z 'Moje Torrenty' progress.window.title=Operace pr\u00e1v\u011b prob\u00edh\u00e1 progress.window.msg.filemove=Pros\u00edm \u010dekejte, dokud se soubor nep\u0159esune/nep\u0159ejmenuje ConfigView.label.popup.timestamp=P\u0159idat \u010dasom\u00edru k vyskakovac\u00edm varov\u00e1n\u00edm ConfigView.label.popup.autohide=Automaticky skr\u00fdvat vyskakuj\u00edc\u00ed (nechybov\u00e9) hl\u00e1\u0161en\u00ed po x sekund\u00e1ch (vpi\u0161te 0 pro zak\u00e1z\u00e1n\u00ed automatick\u00e9ho skr\u00fdv\u00e1n\u00ed) ConfigView.label.please.visit.here=Pros\u00edm pod\u00edvejte se sem na detaily #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} # # Used for peers which we can't determine. PeerSocket.unknown=Nezn\u00e1m\u00fd ConfigView.label.announceport=P\u0159epsat oznamovac\u00ed port trackeru #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences iconBar.queue.tooltip=Fronta MainWindow.menu.help.faq=&Wiki \u010cast\u00e9 dotazy #what you've watched? Discover more with a single click... MainWindow.menu.help.donate=&Podpo\u0159it dotac\u00ed !!! azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_ja_JP.properties0000644000175000017500000074741211301156004026071 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torrent \u30d5\u30a1\u30a4\u30eb... Main.parameter.maxUploads=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6570 Main.parameter.maxSpeed=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 (bytes/sec) MainWindow.menu.file=\u30d5\u30a1\u30a4\u30eb MainWindow.menu.file.open=\u958b\u304f MainWindow.menu.file.create=Torrent \u306e\u4f5c\u6210... MainWindow.menu.file.create.fromfile=\u30d5\u30a1\u30a4\u30eb\u304b\u3089 MainWindow.menu.file.create.fromdir=\u30d5\u30a9\u30eb\u30c0\u304b\u3089 MainWindow.menu.file.export=XML Torrent \u3092\u66f8\u304d\u51fa\u3059... MainWindow.menu.file.import=XML Torrent \u3092\u8aad\u307f\u8fbc\u3080... MainWindow.menu.file.closetab=\u30bf\u30d6\u3092\u9589\u3058\u308b MainWindow.menu.file.closewindow=\u30a6\u30a4\u30f3\u30c9\u30a6\u3092\u9589\u3058\u308b MainWindow.menu.file.exit=\u7d42\u4e86 MainWindow.dialog.choose.file=Torrent \u30d5\u30a1\u30a4\u30eb\u306e\u9078\u629e MainWindow.menu.file.folder=\u30d5\u30a9\u30eb\u30c0... MainWindow.dialog.choose.folder=Torrent \u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308b\u30d5\u30a9\u30eb\u30c0\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 MainWindow.menu.view=\u8868\u793a MainWindow.menu.view.show=\u8868\u793a MainWindow.menu.view.mytorrents=Torrent MainWindow.menu.view.open_global_transfer_bar=\u8ee2\u9001\u30d0\u30fc MainWindow.menu.view.configuration=\u74b0\u5883\u8a2d\u5b9a... MainWindow.menu.view.console=\u30b3\u30f3\u30bd\u30fc\u30eb MainWindow.menu.view.irc=IRC MainWindow.menu.view.allpeers=\u3059\u3079\u3066\u306e\u30d4\u30a2 MainWindow.menu.closealldetails=\u3059\u3079\u3066\u306e\u8a73\u7d30\u3092\u9589\u3058\u308b MainWindow.menu.closealldownloadbars=\u3059\u3079\u3066\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30d0\u30fc\u3092\u9589\u3058\u308b MainWindow.menu.language=\u8a00\u8a9e ConfigView.section.language=\u8a00\u8a9e MainWindow.menu.window=\u30a6\u30a4\u30f3\u30c9\u30a6 MainWindow.menu.window.minimize=\u6700\u5c0f\u5316 MainWindow.menu.window.zoom=\u62e1\u5927\uff0f\u7e2e\u5c0f MainWindow.menu.window.alltofront=\u3059\u3079\u3066\u3092\u624b\u524d\u306b\u79fb\u52d5 MainWindow.menu.help=\u30d8\u30eb\u30d7 MainWindow.menu.help.about=Vuze \u306b\u3064\u3044\u3066 MainWindow.menu.torrent=Torrent MainWindow.about.title=Vuze \u306b\u3064\u3044\u3066 MainWindow.about.section.developers=\u958b\u767a\u8005 MainWindow.about.section.translators=\u7ffb\u8a33\u8005 MainWindow.about.section.system=\u30b7\u30b9\u30c6\u30e0 MainWindow.about.section.internet=\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8 MainWindow.about.internet.homepage=Vuze \u30db\u30fc\u30e0\u30da\u30fc\u30b8 MainWindow.about.internet.sourceforge=Sourceforge \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u30da\u30fc\u30b8 MainWindow.about.internet.sourceforgedownloads=Sourceforge \u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30da\u30fc\u30b8 MainWindow.about.internet.bugreports=\u30d0\u30b0\u30ec\u30dd\u30fc\u30c8 MainWindow.about.internet.forumdiscussion=\u30d5\u30a9\u30fc\u30e9\u30e0 MainWindow.dialog.choose.savepath=\u4fdd\u5b58\u5148\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 MainWindow.dialog.choose.savepath_forallfiles=\u3059\u3079\u3066\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u4fdd\u5b58\u5148\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 MainWindow.status.latestversion=\u6700\u65b0 MainWindow.status.latestversion.clickupdate=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8 MainWindow.status.unknown=\u4e0d\u660e MainWindow.status.checking=\u78ba\u8a8d\u4e2d TableColumn.header.name=\u540d\u524d TableColumn.header.size=\u30b5\u30a4\u30ba TableColumn.header.done=\u72b6\u6cc1 (%) TableColumn.header.done.info=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u306e\u9032\u6357\u72b6\u6cc1 TableColumn.header.status=\u30b9\u30c6\u30fc\u30bf\u30b9 TableColumn.header.status.info=Torrent \u304c\u73fe\u5728\u4f55\u3092\u3057\u3066\u3044\u308b\u304b TableColumn.header.seeds=\u30b7\u30fc\u30c0\u30fc TableColumn.header.seeds.info=\u63a5\u7d9a\u4e2d\u306e\u30b7\u30fc\u30c0\u30fc\uff08\u5408\u8a08\u30b7\u30fc\u30c0\u30fc\uff09 TableColumn.header.peers=\u30d4\u30a2 TableColumn.header.peers.info=\u63a5\u7d9a\u4e2d\u306e\u30d4\u30a2\uff08\u5408\u8a08\u30d4\u30a2\uff09 TableColumn.header.completed=\u5b8c\u4e86\u8005\u6570 TableColumn.header.completed.info=\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u5831\u544a\u3055\u308c\u3066\u3044\u308b\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u304c\u5b8c\u4e86\u3057\u305f\u30d4\u30a2\u306e\u6570 TableColumn.header.downspeed=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6 TableColumn.header.upspeed=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 TableColumn.header.eta=\u6b8b\u308a\u6642\u9593 TableColumn.header.tracker=\u30c8\u30e9\u30c3\u30ab\u30fc\u306e\u72b6\u6cc1 TableColumn.header.tracker.info=\u30c8\u30e9\u30c3\u30ab\u30fc\u306e\u72b6\u6cc1 TableColumn.header.trackernextaccess=\u30c8\u30e9\u30c3\u30ab\u30fc\u3078\u306e\u6b21\u56de\u30a2\u30af\u30bb\u30b9 TableColumn.header.trackernextaccess.info=\u6b21\u56de\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u30a2\u30af\u30bb\u30b9\u3059\u308b\u6642\u9593 TableColumn.header.priority=\u512a\u5148\u5ea6 TableColumn.header.priority.info=\u6307\u5b9a\u3055\u308c\u305f Torrent \u306b\u5272\u308a\u5f53\u3066\u308b\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u5e2f\u57df\u306e\u512a\u5148\u5ea6\u3092\u6c7a\u5b9a TableColumn.header.seeds.fullcopycalc=%1 \u306e\u30d4\u30a2\u306b\u5bfe\u3057\u3066 %2 \u500b\u5206\u76f8\u5f53\u306e\u30c7\u30fc\u30bf\u304c\u5b58\u5728\u3059\u308b MyTorrentsView.menu.showdetails=\u8a73\u7d30\u3092\u8868\u793a MyTorrentsView.menu.showdownloadbar=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30d0\u30fc\u3092\u8868\u793a MyTorrentsView.menu.open=\u958b\u304f MyTorrentsView.menu.setpriority=\u512a\u5148\u5ea6\u3092\u8a2d\u5b9a MyTorrentsView.menu.setpriority.high=\u9ad8 MyTorrentsView.menu.setpriority.low=\u4f4e MyTorrentsView.menu.start=\u958b\u59cb MyTorrentsView.menu.stop=\u505c\u6b62 MyTorrentsView.menu.remove=\u524a\u9664 MyTorrentsView.menu.changeTracker=\u30c8\u30e9\u30c3\u30ab\u30fc\u306e URL \u3092\u8ffd\u52a0... TrayWindow.menu.exit=\u7d42\u4e86 TrayWindow.menu.show=Vuze \u3092\u8868\u793a SystemTray.menu.exit=\u7d42\u4e86 SystemTray.menu.closealldownloadbars=\u3059\u3079\u3066\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30d0\u30fc\u3092\u9589\u3058\u308b SystemTray.menu.open_global_transfer_bar=\u8ee2\u9001\u30d0\u30fc\u3092\u8868\u793a SystemTray.menu.show=Vuze \u3092\u8868\u793a PeersView.ip.info=\u30d4\u30a2\u306e IP \u30a2\u30c9\u30ec\u30b9 PeersView.port=\u30dd\u30fc\u30c8 PeersView.port.info=\u4f7f\u7528\u3057\u3066\u3044\u308b\u30dd\u30fc\u30c8\u756a\u53f7 PeersView.T.info=L (local): \u3053\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304b\u3089\u30d4\u30a2\u3078\u306e\u63a5\u7d9a, R (remote): \u30d4\u30a2\u304b\u3089\u3053\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3078\u306e\u63a5\u7d9a PeersView.T.L.tooltip=\u3053\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304b\u3089\u30d4\u30a2\u306b\u63a5\u7d9a\u3057\u305f PeersView.T.R.tooltip=\u30d4\u30a2\u304b\u3089\u3053\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3078\u63a5\u7d9a\u3057\u305f PeersView.I1=I (\u30d4\u30a2\u306b\u6ce8\u76ee\u3055\u308c\u3066\u3044\u308b) PeersView.I1.info=\u3053\u306e\u30d4\u30a2\u304c\u6301\u3063\u3066\u3044\u308b\u30d4\u30fc\u30b9\u304c\u5fc5\u8981 PeersView.C1=C (\u30d4\u30a2\u306b\u5236\u88c1\u3055\u308c\u3066\u3044\u308b) PeersView.C1.info=\u3042\u306a\u305f\u3078\u306e\u30c7\u30fc\u30bf\u8ee2\u9001\u3092\u505c\u6b62\u3057\u3066\u3044\u308b\u304b\u3069\u3046\u304b PeersView.pieces=\u30d4\u30fc\u30b9 PeersView.%=\u72b6\u6cc1 (%) PeersView.downloadspeed=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6 PeersView.download=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 PeersView.I2=I (\u30d4\u30a2\u306b\u6ce8\u76ee\u3057\u3066\u3044\u308b) PeersView.I2.info=\u3053\u306e\u30d4\u30a2\u306f\u3042\u306a\u305f\u304c\u6301\u3063\u3066\u3044\u308b\u30d4\u30fc\u30b9\u304c\u5fc5\u8981 PeersView.C2=C (\u30d4\u30a2\u3092\u30c1\u30e7\u30fc\u30af\u3057\u3066\u3044\u308b) PeersView.C2.info=\u3053\u306e\u30d4\u30a2\u3078\u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3092\u505c\u6b62\u3057\u3066\u3044\u308b\u304b\u3069\u3046\u304b PeersView.uploadspeed=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 PeersView.uploadspeed.info=\u3053\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304b\u3089\u30d4\u30a2\u3078\u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 PeersView.upload=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9 PeersView.upload.info=\u3053\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304b\u3089\u30d4\u30a2\u3078\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3057\u305f\u7dcf\u91cf PeersView.statup=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u7d71\u8a08 PeersView.statup.info=\u3053\u306e\u30d4\u30a2\u306e\u63a8\u5b9a\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 PeersView.S.info=Snubbed: \u624b\u52d5\u3082\u3057\u304f\u306f\u81ea\u52d5\u3067\u30d4\u30a2\u306b\u5236\u88c1\u3067\u304d\u308b\uff08\u5341\u5206\u306a\u901f\u5ea6\u3067\u8ee2\u9001\u3057\u3066\u3053\u306a\u3044\u30d4\u30a2\u306b\u5bfe\u3057\u3066\uff09 PeersView.downloadspeedoverall=\u5408\u8a08\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6 PeersView.optunchoke=\u5236\u88c1\u89e3\u9664 PeersView.client=\u30af\u30e9\u30a4\u30a2\u30f3\u30c8 PeersView.client.info=\u30d4\u30a2\u304c\u4f7f\u7528\u3057\u3066\u3044\u308b BitTorrent \u30af\u30e9\u30a4\u30a2\u30f3\u30c8 PeersView.menu.snubbed=\u5236\u88c1 PeersView.title.short=\u30d4\u30a2 PeersView.title.full=\u30d4\u30a2 AllPeersView.title.full=\u3059\u3079\u3066\u306e\u30d4\u30a2 ConfigView.section.files=\u30d5\u30a1\u30a4\u30eb ConfigView.label.usefastresume=\u9ad8\u901f\u30ec\u30b8\u30e5\u30fc\u30e0\u3092\u4f7f\u7528 ConfigView.label.incrementalfile=\u30d5\u30a1\u30a4\u30eb\u9818\u57df\u3092\u4e00\u5ea6\u306b\u78ba\u4fdd\u3057\u306a\u3044\uff08Linux \u3067 FAT32 \u306e\u5834\u5408\u5fc5\u8981\uff09 ConfigView.label.defaultsavepath=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u4fdd\u5b58\u5148\u3078\u4fdd\u5b58\u3059\u308b ConfigView.button.browse=\u53c2\u7167... ConfigView.dialog.choosedefaultsavepath=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u4fdd\u5b58\u5148\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 ConfigView.section.server=\u63a5\u7d9a ConfigView.section.global=\u4e00\u822c ConfigView.label.disconnetseed=\u30b7\u30fc\u30c9\u6642\u306b\u30b7\u30fc\u30c0\u30fc\u3068\u306e\u63a5\u7d9a\u3092\u5207\u308b ConfigView.label.switchpriority=\u30b7\u30fc\u30c9\u6642\u306b\u512a\u5148\u5ea6\u3092\u81ea\u52d5\u7684\u306b\u4e0b\u3052\u308b ConfigView.label.maxdownloads=\u6700\u5927\u540c\u6642\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u6570 [0: \u7121\u5236\u9650] ConfigView.label.maxdownloads.tooltip=\u3053\u3053\u3067\u6307\u5b9a\u3057\u305f\u6570\u3060\u3051\u3001\u540c\u6642\u306b\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3067\u304d\u307e\u3059\u3002\n\u305f\u3060\u3057\u6700\u512a\u5148\u306b\u306a\u3063\u305f Torrent \u304c\u3042\u308c\u3070\u305d\u308c\u304c\u512a\u5148\u3055\u308c\u307e\u3059 ConfigView.label.maxactivetorrents=\u6700\u5927\u30a2\u30af\u30c6\u30a3\u30d6\u6570 [0: \u7121\u5236\u9650]\n - \u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\uff0f\u30b7\u30fc\u30c9\u4e2d\u306e Torrent \u304c\u3053\u306e\u5024\u306b\u9054\u3057\u3066\u3044\u308b\u5834\u5408\u3001\u65b0\u3057\u3044 Torrent \u306f\u958b\u59cb\u3055\u308c\u307e\u305b\u3093 ConfigView.label.priorityExtensions=\u62e1\u5f35\u5b50\u3088\u308a\u512a\u5148\u5ea6\u3067\u81ea\u52d5\u8a2d\u5b9a\n - \u4f8b\uff1a.txt;.nfo;.jpg ConfigView.section.transfer=\u8ee2\u9001 ConfigView.label.maxuploads=Torrent \u3054\u3068\u306e\u6700\u5927\u540c\u6642\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6570\u306e\u30c7\u30d5\u30a9\u30eb\u30c8 ConfigView.label.maxuploadspeed=\u7dcf\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 (KB/s) [0: \u7121\u5236\u9650] ConfigView.label.saveresumeinterval=\u30ec\u30b8\u30e5\u30fc\u30e0\u30c7\u30fc\u30bf\u306e\u66f4\u65b0\u9593\u9694 ConfigView.unlimited=\u7121\u5236\u9650 ConfigView.section.display=\u8868\u793a ConfigView.label.opendetails=\u81ea\u52d5\u3067\u8a73\u7d30\u30bf\u30d6\u3092\u958b\u304f ConfigView.label.openbar=\u81ea\u52d5\u3067\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30d0\u30fc\u3092\u958b\u304f ConfigView.label.use_old_speed_menus=\u4ee5\u524d\u306e\u30b9\u30d4\u30fc\u30c9\u30e1\u30cb\u30e5\u30fc\u3092\u4f7f\u7528\uff08\u518d\u8d77\u52d5\u304c\u5fc5\u8981\uff09 ConfigView.label.closetotray=\u9589\u3058\u308b\u30dc\u30bf\u30f3\u3067\u30b7\u30b9\u30c6\u30e0\u30c8\u30ec\u30a4\u3078\u5165\u308c\u308b ConfigView.label.minimizetotray=\u6700\u5c0f\u5316\u30dc\u30bf\u30f3\u3067\u30b7\u30b9\u30c6\u30e0\u30c8\u30ec\u30a4\u3078\u5165\u308c\u308b ConfigView.section.general=\u4e00\u822c ConfigView.section.start=\u8d77\u52d5 ConfigView.label.showsplash=\u30b9\u30d7\u30e9\u30c3\u30b7\u30e5\u3092\u8868\u793a ConfigView.label.autoupdate=\u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u898b\u3064\u3051\u305f\u5834\u5408\u306b\u30a2\u30c3\u30d7\u30b0\u30ec\u30fc\u30c9\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u958b\u304f ConfigView.label.openconsole=\u8d77\u52d5\u6642\u306b\u30b3\u30f3\u30bd\u30fc\u30eb\u3092\u958b\u304f ConfigView.label.openconfig=\u8d77\u52d5\u6642\u306b\u74b0\u5883\u8a2d\u5b9a\u3092\u958b\u304f ConfigView.label.startminimized=\u8d77\u52d5\u5f8c\u306b\u6700\u5c0f\u5316 ConfigView.label.ircwiki=http://wiki.vuze.com/index.php/Rules_for_IRC \u3092\u3054\u89a7\u304f\u3060\u3055\u3044 ConfigView.label.ircserver=\u30b5\u30fc\u30d0\uff1a ConfigView.label.ircchannel=\u30c1\u30e3\u30cd\u30eb\uff1a ConfigView.label.irclogin=\u30cb\u30c3\u30af\u30cd\u30fc\u30e0\uff1a ConfigView.group.irctitle=IRC \u306e\u8a2d\u5b9a ConfigView.boolean.ircsendinfo=\u8a2d\u5b9a\u60c5\u5831\u3092\uff08\u533f\u540d\u3067\uff09\u30c1\u30e3\u30cd\u30eb\u7ba1\u7406\u8005\u3078\u9001\u4fe1 ConfigView.boolean.irclog=\u30c1\u30e3\u30cd\u30eb\u306e\u30ed\u30b0\uff08IRC_log.htm\uff09\u3092\u4fdd\u5b58 ConfigView.section.security=\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3 ConfigView.label.password=Vuze \u3092\u30d1\u30b9\u30ef\u30fc\u30c9\u3067\u4fdd\u8b77\n\u8d77\u52d5\u6642\u3068\u30a2\u30a4\u30b3\u30f3\u5316\u304b\u3089\u306e\u5fa9\u5e30\u6642\u306b\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u8981\u6c42\u3057\u307e\u3059\u3002 ConfigView.label.passwordconfirm=\u30d1\u30b9\u30ef\u30fc\u30c9\uff08\u78ba\u8a8d\uff09 ConfigView.label.passwordmatch=\u6709\u52b9\u306a\u30d1\u30b9\u30ef\u30fc\u30c9\uff1a ConfigView.label.passwordmatchnone=\u7121\u52b9 ConfigView.label.passwordmatchno=\u7121\u52b9\uff0f\u4e0d\u4e00\u81f4 ConfigView.label.passwordmatchyes=\u6709\u52b9 ConfigView.button.save=\u4fdd\u5b58 ConfigView.title.short=\u8a2d\u5b9a ConfigView.title.full=\u8a2d\u5b9a ConsoleView.title.short=\u30b3\u30f3\u30bd\u30fc\u30eb ConsoleView.title.full=\u30b3\u30f3\u30bd\u30fc\u30eb FileItem.write=\u66f8\u304d FileItem.read=\u8aad\u307f FileItem.normal=\u901a\u5e38 FileItem.high=\u9ad8 FileItem.donotdownload=\u30b9\u30ad\u30c3\u30d7 FilesView.name=\u540d\u524d FilesView.name.fastRename=\u540d\u524d\u3092\u5909\u66f4 FilesView.size=\u30b5\u30a4\u30ba FilesView.done=\u5b8c\u4e86 FilesView.%=\u72b6\u6cc1 (%) FilesView.firstpiece=\u5148\u982d\u30d4\u30fc\u30b9 No. FilesView.numberofpieces=\u30d4\u30fc\u30b9\u6570 FilesView.pieces=\u30d4\u30fc\u30b9 FilesView.mode=\u30e2\u30fc\u30c9 FilesView.priority=\u512a\u5148\u5ea6 FilesView.menu.open=\u958b\u304f FilesView.menu.setpriority=\u512a\u5148\u5ea6\u3092\u8a2d\u5b9a FilesView.menu.setpriority.high=\u9ad8 FilesView.menu.setpriority.normal=\u901a\u5e38 FilesView.menu.setpriority.skipped=\u30b9\u30ad\u30c3\u30d7 FilesView.title.short=\u30d5\u30a1\u30a4\u30eb FilesView.title.full=\u30d5\u30a1\u30a4\u30eb GeneralView.section.downloaded=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u6e08 GeneralView.label.status.file=\u30d5\u30a1\u30a4\u30eb\u306e\u72b6\u614b GeneralView.label.status.pieces=\u30d4\u30fc\u30b9\u306e\u72b6\u614b GeneralView.section.availability=\u5165\u624b\u53ef\u80fd\u6027 GeneralView.label.status.pieces_available=\u30d4\u30fc\u30b9\u306e\u72b6\u614b GeneralView.section.transfer=\u8ee2\u9001 GeneralView.section.info=\u60c5\u5831 GeneralView.title.short=\u4e00\u822c GeneralView.title.full=\u4e00\u822c GeneralView.label.timeelapsed=\u7d4c\u904e\u6642\u9593\uff1a GeneralView.label.remaining=\u6b8b\u308a\u6642\u9593\uff1a GeneralView.label.downloaded=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u6e08\uff1a GeneralView.label.downloadspeed=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6\uff1a GeneralView.label.maxuploads=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6570\uff1a GeneralView.label.maxuploads.tooltip=\u5236\u88c1\u4e2d\u306e\u30d4\u30a2\u3092\u9664\u304f\u30d4\u30a2\u306e\u6700\u5927\u6570 GeneralView.label.uploaded=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6e08\uff1a GeneralView.label.uploadspeed=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6\uff1a GeneralView.label.seeds=\u30b7\u30fc\u30c0\u30fc\u6570\uff1a GeneralView.label.peers=\u30d4\u30a2\u6570\uff1a GeneralView.label.completed=\u5b8c\u4e86 GeneralView.label.totalspeed=Swarm \u901f\u5ea6\uff1a GeneralView.label.totalspeed.tooltip=\u63a5\u7d9a\u3057\u3066\u3044\u308b\u3059\u3079\u3066\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u5408\u8a08\uff08\u3068\u5e73\u5747\uff09\u901f\u5ea6 GeneralView.label.averagespeed=\u5e73\u5747 GeneralView.label.filename=\u540d\u524d\uff1a GeneralView.label.totalsize=\u5408\u8a08\u30b5\u30a4\u30ba\uff1a GeneralView.label.savein=\u4fdd\u5b58\u5148\uff1a GeneralView.label.hash=\u30cf\u30c3\u30b7\u30e5\uff1a GeneralView.label.numberofpieces=\u30d4\u30fc\u30b9\u6570\uff1a GeneralView.label.size=\u30b5\u30a4\u30ba\uff1a GeneralView.label.tracker=\u30c8\u30e9\u30c3\u30ab\u30fc\u306e\u72b6\u614b\uff1a GeneralView.label.updatein=\u6b21\u56de\u66f4\u65b0\uff1a GeneralView.label.trackerurl=\u30c8\u30e9\u30c3\u30ab\u30fc\u306e URL\uff1a GeneralView.label.trackerurlupdate=\u30c8\u30e9\u30c3\u30ab\u30fc\u3092\u66f4\u65b0 GeneralView.label.comment=Torrent \u30b3\u30e1\u30f3\u30c8\uff1a GeneralView.label.user_comment=\u30e6\u30fc\u30b6\u30b3\u30e1\u30f3\u30c8\uff1a GeneralView.label.status=\u72b6\u614b\uff1a ManagerItem.waiting=\u5f85\u6a5f ManagerItem.allocating=\u6e96\u5099\u4e2d ManagerItem.checking=\u78ba\u8a8d\u4e2d ManagerItem.ready=\u6e96\u5099\u5b8c\u4e86 ManagerItem.downloading=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d ManagerItem.seeding=\u30b7\u30fc\u30c9\u4e2d ManagerItem.stopped=\u505c\u6b62 ManagerItem.error=\u30a8\u30e9\u30fc ManagerItem.high=\u9ad8 ManagerItem.low=\u4f4e MinimizedWindow.name=\u540d\u524d: PiecesView.#=No. PiecesView.size=\u30b5\u30a4\u30ba PiecesView.numberofblocks=\u30d6\u30ed\u30c3\u30af\u6570 PiecesView.blocks=\u30d6\u30ed\u30c3\u30af PiecesView.completed=\u5b8c\u4e86 PiecesView.availability=\u30b3\u30d4\u30fc\u6570 PiecesView.reservedby=\u4e88\u7d04\u6e08 PiecesView.writers=\u63d0\u4f9b\u8005 PiecesView.title.short=\u30d4\u30fc\u30b9 PiecesView.title.full=\u30d4\u30fc\u30b9 SystemTray.tooltip.seeding=\u30b7\u30fc\u30c9\u4e2d: %1, SystemTray.tooltip.downloading=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d: %1, DownloadManager.error.filenotfound=\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 DownloadManager.error.fileempty=Torrent \u30d5\u30a1\u30a4\u30eb\u304c\u7a7a\u3067\u3059 DownloadManager.error.filetoobig=Torrent \u30d5\u30a1\u30a4\u30eb\u304c\u5927\u304d\u3059\u304e\u307e\u3059 DownloadManager.error.filewithouttorrentinfo=\u30d5\u30a1\u30a4\u30eb\u306b Torrent \u60c5\u5831\u304c\u3042\u308a\u307e\u305b\u3093 DownloadManager.error.unsupportedencoding=\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u306a\u3044\u30a8\u30f3\u30b3\u30fc\u30c9\u3067\u3059 DownloadManager.error.ioerror=IO \u30a8\u30e9\u30fc DownloadManager.error.sha1=\u672a\u77e5\u306e\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0 (SHA1) \u30a8\u30e9\u30fc PeerManager.status.offline=\u63a5\u7d9a\u30a8\u30e9\u30fc PeerManager.status.checking=\u78ba\u8a8d\u4e2d PeerManager.status.finished=\u5b8c\u4e86 PeerManager.status.finishedin=\u5b8c\u4e86\u307e\u3067 MainWindow.upgrade.assistant=\u30a2\u30c3\u30d7\u30b0\u30ec\u30fc\u30c9\u30a2\u30b7\u30b9\u30bf\u30f3\u30c8 MainWindow.upgrade.newerversion=Vuze \u306e\u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u304c\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3067\u304d\u307e\u3059 MainWindow.upgrade.explanation=\u3053\u306e\u30a2\u30b7\u30b9\u30bf\u30f3\u30c8\u306f\u3001Vuze \u3092\u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u306b\u66f4\u65b0\u3057\u307e\u3059 MainWindow.upgrade.explanation.manual=Vuze \u3092\u624b\u52d5\u3067\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3059\u308b\u306b\u306f\u6b21\u306e\u624b\u9806\u306b\u5f93\u3063\u3066\u304f\u3060\u3055\u3044 MainWindow.upgrade.step1=\u30b9\u30c6\u30c3\u30d7 1\uff1a\u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b MainWindow.upgrade.step2=\u30b9\u30c6\u30c3\u30d7 2\uff1a\u3053\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u7d42\u4e86\u3057\u3001\u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u306e Vuze \u3092\u8d77\u52d5\u3059\u308b MainWindow.upgrade.hint1=\u30d2\u30f3\u30c8\uff1a\t\u5b8c\u4e86\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u3059\u3079\u3066\u81ea\u52d5\u3067\u51e6\u7406\u3055\u308c\u307e\u3059 MainWindow.upgrade.hint2=\u30d2\u30f3\u30c8\uff1a\t\u3082\u3057\u4eca Vuze \u3092\u7d42\u4e86\u3057\u305f\u304f\u306a\u3044\u5834\u5408\u306f\u30ad\u30e3\u30f3\u30bb\u30eb\u30dc\u30bf\u30f3\u3092\u62bc\u3057\u3001\nVuze \u3092\u7d42\u4e86\u3057\u305f\u5f8c\u306b Azureus2-new.jar \u3092Azureus2.jar \u306b\u30ea\u30cd\u30fc\u30e0\u3057\u3066\u304f\u3060\u3055\u3044\u3002 MainWindow.upgrade.error.downloading.hint=\u30a8\u30e9\u30fc\uff1a\t\u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u624b\u52d5\u3067\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3057\u3066\u304f\u3060\u3055\u3044\u3002 MainWindow.upgrade.section.info=\u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f MainWindow.upgrade.section.manual=\u624b\u52d5\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8 MainWindow.upgrade.section.automatic=\u81ea\u52d5\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8 MainWindow.upgrade.tooltip.progressbar=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u72b6\u6cc1 Button.next=\u6b21\u3078 Button.finish=\u5b8c\u4e86 Button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb LocaleUtil.title=\u6587\u5b57\u30a8\u30f3\u30b3\u30fc\u30c9\u306e\u9078\u629e LocaleUtil.section.chooseencoding=\u30d5\u30a1\u30a4\u30eb\u540d\u306e\u30a8\u30f3\u30b3\u30fc\u30c9\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 LocaleUtil.label.chooseencoding=\u6700\u9069\u306a\u30a8\u30f3\u30b3\u30fc\u30c9\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 LocaleUtil.label.hint.doubleclick=\u30d2\u30f3\u30c8\uff1a\u5217\u3092\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u305d\u306e\u30a8\u30f3\u30b3\u30fc\u30c9\u3092\u9078\u629e\u3057\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u9589\u3058\u307e\u3059 LocaleUtil.label.checkbox.rememberdecision=\u6b8b\u308a\u306e\u30d5\u30a1\u30a4\u30eb\u306b\u3082\u9069\u7528 LocaleUtil.column.encoding=\u30a8\u30f3\u30b3\u30fc\u30c9 IrcClient.connecting=\u63a5\u7d9a\u4e2d IrcClient.connected=\u63a5\u7d9a\u6e08 IrcClient.joining=\u53c2\u52a0\u4e2d IrcClient.channel=\u30c1\u30e3\u30cd\u30eb IrcClient.joined=\u53c2\u52a0\u3057\u307e\u3057\u305f IrcClient.error=\u30a8\u30e9\u30fc IrcClient.hasjoined=\u304c\u53c2\u52a0\u3057\u307e\u3057\u305f IrcClient.haskicked=\u304c\u30ad\u30c3\u30af\u3055\u308c\u307e\u3057\u305f IrcClient.hasleft=\u304c\u9000\u51fa\u3057\u307e\u3057\u305f IrcClient.nowknown=\u3053\u3068 IrcClient.topicforchannel=\u30c1\u30e3\u30cd\u30eb\u306e\u30c8\u30d4\u30c3\u30af IrcClient.disconnected=\u5207\u65ad IrcClient.noNick=\u30cb\u30c3\u30af\u30cd\u30fc\u30e0\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u74b0\u5883\u8a2d\u5b9a\u3092\u958b\u3044\u3066\u304f\u3060\u3055\u3044\u3002 IrcView.actionnotsupported=\u30a2\u30af\u30b7\u30e7\u30f3\u306f\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 IrcView.clientsconnected=\u30e6\u30fc\u30b6 IrcView.noticefrom=\u6ce8\u610f: IrcView.errormsg=Wrong Syntax on /msg\uff1a/msg user text PasswordWindow.title=Vuze \u306f\u30ed\u30c3\u30af\u3055\u308c\u3066\u3044\u307e\u3059 PasswordWindow.passwordprotected=Vuze \u306f\u30d1\u30b9\u30ef\u30fc\u30c9\u306b\u3088\u3063\u3066\u4fdd\u8b77\u3055\u308c\u3066\u3044\u307e\u3059\u3002\nVuze \u306e\u30a6\u30a4\u30f3\u30c9\u30a6\u3092\u8868\u793a\u3059\u308b\u306b\u306f\u3001\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\uff1a Button.ok=OK TrackerChangerWindow.title=\u30c8\u30e9\u30c3\u30ab\u30fc\u3092\u8ffd\u52a0 TrackerChangerWindow.newtracker=\u65b0\u3057\u3044\u30c8\u30e9\u30c3\u30ab\u30fc\u306e URL \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044 PeersView.discarded=\u7834\u68c4 PeersView.discarded.info=\uff08\u4f55\u3089\u304b\u306e\u7406\u7531\u3067\uff09\u5fc5\u8981\u3068\u3057\u306a\u3044\u306e\u306b\u53d7\u4fe1\u3057\u3001\u7834\u68c4\u3055\u308c\u305f\u30c7\u30fc\u30bf discarded=\u3092\u7834\u68c4 MyTorrentsView.menu.move=\u79fb\u52d5 MyTorrentsView.menu.moveUp=\u4e0a\u3078 MyTorrentsView.menu.moveDown=\u4e0b\u3078 GeneralView.label.hashfails=\u30cf\u30c3\u30b7\u30e5\u30a8\u30e9\u30fc\uff1a GeneralView.label.shareRatio=\u8ca0\u62c5\u7387\uff1a ConfigView.section.downloadManagement=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u306e\u7ba1\u7406 ConfigView.label.startRatioPeers=\u30b7\u30fc\u30c0\u30fc\u304c\u304a\u3089\u305a\u8ca0\u62c5\u7387\u304c\u4f4e\u3044\u5834\u5408\u30b7\u30fc\u30c9\u3092\u958b\u59cb ConfigView.text.neverStop=\u505c\u6b62\u3057\u306a\u3044 ConfigView.text.neverStart=\u958b\u59cb\u3057\u306a\u3044 ConfigView.text.peers=\u30d4\u30a2 ConfigView.label.checkOncompletion=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5b8c\u4e86\u5f8c\u306b\u30d4\u30fc\u30b9\u3092\u518d\u30c1\u30a7\u30c3\u30af\u3059\u308b wizard.title=Torrent \u306e\u4f5c\u6210 wizard.previous=\u623b\u308b wizard.next=\u6b21\u3078 wizard.finish=\u5b8c\u4e86 wizard.mode=\u30c8\u30e9\u30c3\u30ab\u30fc / \u30e2\u30fc\u30c9 wizard.tracker=\u30c8\u30e9\u30c3\u30ab\u30fc\uff1a wizard.invalidurl=\u7121\u52b9\u306a URL \u3067\u3059 wizard.singlefile=1 \u3064\u306e\u30d5\u30a1\u30a4\u30eb wizard.singlefile.help=1 \u3064\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u914d\u4fe1\u3059\u308b Torrent \u3092\u4f5c\u6210\u3057\u307e\u3059 wizard.directory=\u30d5\u30a9\u30eb\u30c0 wizard.directory.help=\u30d5\u30a9\u30eb\u30c0\u3092\u914d\u4fe1\u3059\u308b Torrent \u3092\u4f5c\u6210\u3057\u307e\u3059 wizard.choosefile=\u30d5\u30a1\u30a4\u30eb\u306e\u9078\u629e wizard.file=\u30d5\u30a1\u30a4\u30eb wizard.browse=\u53c2\u7167... wizard.choosedirectory=\u30d5\u30a9\u30eb\u30c0\u306e\u9078\u629e wizard.invalidfile=\u7121\u52b9\u306a\u30d5\u30a1\u30a4\u30eb\u3067\u3059 wizard.invaliddirectory=\u7121\u52b9\u306a\u30d5\u30a9\u30eb\u30c0\u3067\u3059 wizard.torrentFile=Torrent \u30d5\u30a1\u30a4\u30eb wizard.choosetorrent=\u4f5c\u6210\u3059\u308b Torrent \u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 wizard.information=\u60c5\u5831 wizard.notimplemented=\u307e\u3060\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093 wizard.progresstitle=Torrent \u30d5\u30a1\u30a4\u30eb\u306e\u4f5c\u6210 wizard.savingfile=\u30d5\u30a1\u30a4\u30eb\u3092\u4fdd\u5b58\u4e2d... wizard.filesaved=\u30d5\u30a1\u30a4\u30eb\u3092\u4fdd\u5b58\u3057\u307e\u3057\u305f\u3002 wizard.close=\u9589\u3058\u308b Torrent.create.progress.piecelength=\u30d4\u30fc\u30b9\u9577: Torrent.create.progress.piececount=\u30d4\u30fc\u30b9\u6570: Torrent.create.progress.totalfilesize=\u5408\u8a08\u30b5\u30a4\u30ba: Torrent.create.progress.totalfilecount=\u5408\u8a08\u30d5\u30a1\u30a4\u30eb\u6570: Torrent.create.progress.parsingfiles=\u30d5\u30a1\u30a4\u30eb\u3092\u5206\u6790\u4e2d Torrent.create.progress.hashing=\u30cf\u30c3\u30b7\u30e5\u3092\u8a08\u7b97\u4e2d MainWindow.upgrade.downloadingfrom=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d\uff1a MainWindow.menu.view.ipFilter=IP \u30d5\u30a3\u30eb\u30bf ConfigView.section.ipfilter=IP \u30d5\u30a3\u30eb\u30bf ConfigView.section.ipfilter.description=\u8aac\u660e ConfigView.section.ipfilter.start=\u958b\u59cb IP \u30a2\u30c9\u30ec\u30b9 ConfigView.section.ipfilter.end=\u7d42\u4e86 ConfigView.section.ipfilter.add=\u8ffd\u52a0 ConfigView.section.ipfilter.remove=\u524a\u9664 ConfigView.section.ipfilter.edit=\u7de8\u96c6 ConfigView.section.ipfilter.save=\u4fdd\u5b58 ConfigView.section.ipfilter.editFilter=\u30d5\u30a3\u30eb\u30bf\u3092\u7de8\u96c6 ConfigView.section.ipfilter.enable=\u6709\u52b9 PeersView.menu.close=\u9589\u3058\u308b seedmore.title=\u3053\u306e Torrent \u306f\u5341\u5206\u306b\u30b7\u30fc\u30c9\u3055\u308c\u3066\u3044\u307e\u305b\u3093 seedmore.shareratio=\u3053\u306e Torrent \u306e\u3042\u306a\u305f\u306e\u8ca0\u62c5\u7387\uff1a seedmore.uploadmore=\u8ca0\u62c5\u7387\u304c 100% \u3092\u4e0b\u56de\u308b\u306e\u306f BitTorrent \u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306b\u304a\u3044\u3066\u597d\u307e\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002\n\u3082\u3046\u5c11\u3057\u3053\u306e Torrent \u3092\u30b7\u30fc\u30c9\u3059\u3079\u304d\u3067\u3059\u3002\n\u305d\u308c\u3067\u3082\u30b7\u30fc\u30c9\u3092\u505c\u6b62\u3057\u307e\u3059\u304b\uff1f ConfigView.label.showpopuponclose=\u30b7\u30fc\u30c9\u3092\u505c\u6b62\u3059\u308b\u969b\u3001\u8ca0\u62c5\u7387\u304c 1 \u3088\u308a\u5c0f\u3055\u3044\u5834\u5408\u306f\u8b66\u544a ConfigView.label.startNumSeeds=\n\u30b7\u30fc\u30c0\u30fc\u304c\u5c11\u306a\u3044\u5834\u5408\u30b7\u30fc\u30c9\u3092\u958b\u59cb\n - \u307b\u304b\u306e\u30eb\u30fc\u30eb\u306b\u512a\u5148\u3057\u307e\u3059 ConfigView.label.seeds=\u30b7\u30fc\u30c0\u30fc ConfigView.section.seeding=\u30b7\u30fc\u30c9 MyTorrentsView.menu.removeand=\u524a\u9664... MyTorrentsView.menu.removeand.deletetorrent=Torrent \u30d5\u30a1\u30a4\u30eb\u306e\u307f MyTorrentsView.menu.removeand.deletedata=\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb MyTorrentsView.menu.removeand.deleteboth=\u4e21\u65b9\u3068\u3082 deletedata.title=\u8b66\u544a deletedata.message1=\u6b21\u306e\u30c7\u30fc\u30bf\u3092\u524a\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059:\n MainWindow.menu.file.configure=\u8a2d\u5b9a\u30a6\u30a3\u30b6\u30fc\u30c9... configureWizard.title=\u8a2d\u5b9a\u30a6\u30a3\u30b6\u30fc\u30c9 configureWizard.welcome.title=Vuze \u8a2d\u5b9a\u30a6\u30a3\u30b6\u30fc\u30c9\u3078\u3088\u3046\u3053\u305d configureWizard.welcome.message=\u3053\u306e\u30a6\u30a3\u30b6\u30fc\u30c9\u3067\u306f\u3088\u304f\u4f7f\u308f\u308c\u308b\u9805\u76ee\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u3002\u3055\u3089\u306b\u8a73\u7d30\u306a\u8a2d\u5b9a\u306f\u3001\u30c4\u30fc\u30eb\uff1e\u74b0\u5883\u8a2d\u5b9a \u3067\u884c\u3046\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 configureWizard.transfer.title=\u8ee2\u9001\u3068\u63a5\u7d9a\u306b\u95a2\u3059\u308b\u8a2d\u5b9a configureWizard.transfer.hint=\u30d2\u30f3\u30c8\uff1a\u5b9f\u969b\u306e\u63a5\u7d9a\u901f\u5ea6\u3088\u308a\u5c11\u3057\u5c0f\u3055\u3044\u5024\u304c\u9069\u5207\u3067\u3059 configureWizard.transfer.message=\u4e0b\u8a18\u304b\u3089\u63a5\u7d9a\u901f\u5ea6\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u5341\u5206\u306a\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6\u3092\u8a2d\u5b9a\u3057\u306a\u3044\u3068\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6\u3082\u9045\u304f\u306a\u308a\u307e\u3059\u3002\u307e\u305f\u3001\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6\u306f\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d\u306e Torrent \u3054\u3068\u306b\u6c7a\u5b9a\u3055\u308c\u308b\u305f\u3081\u3001\u540c\u6642\u306b\u591a\u6570\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u3068\u9045\u304f\u306a\u308a\u307e\u3059\u3002\u6700\u4f4e\u3067\u3082 1 \u3064\u306e Torrent \u3054\u3068\u306b 5kB/s \u306f\u78ba\u4fdd\u3059\u308b\u3053\u3068\u3092\u304a\u52e7\u3081\u3057\u307e\u3059\u3002\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u304c\u901f\u3051\u308c\u3070\u901f\u3044\u307b\u3069\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6\u3082\u901f\u304f\u306a\u308a\u307e\u3059\u3002 configureWizard.transfer.connection=\u63a5\u7d9a\u56de\u7dda configureWizard.transfer.connection.0=\u30ab\u30b9\u30bf\u30e0 configureWizard.transfer.connection.1=\u30e2\u30c7\u30e0 configureWizard.transfer.connection.2=ADSL/\u30b1\u30fc\u30d6\u30eb xxx/128 kbps configureWizard.transfer.connection.3=ADSL/\u30b1\u30fc\u30d6\u30eb xxx/256 kbps configureWizard.transfer.connection.4=ADSL/\u30b1\u30fc\u30d6\u30eb xxx/384 kbps configureWizard.transfer.connection.5=ADSL/\u30b1\u30fc\u30d6\u30eb xxx/512 kbps configureWizard.transfer.connection.6=ADSL/\u30b1\u30fc\u30d6\u30eb xxx/768 kbps configureWizard.transfer.connection.7=ADSL/\u30b1\u30fc\u30d6\u30eb xxx/1024 kbps configureWizard.transfer.maxUpSpeed=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 (KB/s) configureWizard.transfer.maxActiveTorrents=\u6700\u5927\u30a2\u30af\u30c6\u30a3\u30d6\u6570 configureWizard.transfer.maxDownloads=\u6700\u5927\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u6570 configureWizard.transfer.maxUploadsPerTorrent=Torrent \u3054\u3068\u306e\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6570 configureWizard.nat.title=NAT / \u30b5\u30fc\u30d0\u30dd\u30fc\u30c8 configureWizard.nat.message=Vuze \u3092\u6700\u9ad8\u306e\u72b6\u614b\u3067\u4f7f\u7528\u3059\u308b\u305f\u3081\u306b\u3001\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u5074\u304b\u3089\u306e\u30a2\u30af\u30bb\u30b9\u3092\u8a31\u53ef\u3059\u308b\u3053\u3068\u3092\u5f37\u304f\u304a\u5968\u3081\u3057\u307e\u3059\u3002\u3053\u306e\u30c4\u30fc\u30eb\u306f\u30d4\u30a2\u304b\u3089\u306e\u63a5\u7d9a\u3092\u5f85\u3061\u53d7\u3051\u308b\u30dd\u30fc\u30c8\u3092\u30c6\u30b9\u30c8\u307e\u305f\u306f\u5909\u66f4\u3057\u307e\u3059\u3002\n\n\u6ce8\u610f\uff1a\u3053\u306e\u30c4\u30fc\u30eb\u306f TCP \u63a5\u7d9a\u306e\u30c6\u30b9\u30c8\u306e\u307f\u3092\u884c\u3044\u307e\u3059\u3002\u5206\u6563 DB \u3092\u5229\u7528\u3059\u308b\u306b\u306f UDP \u63a5\u7d9a\u304c\u5fc5\u8981\u3067\u3059\u304c\u3001\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3067\u30d6\u30ed\u30c3\u30af\u3055\u308c\u305f\u5834\u5408\u306f\u81ea\u52d5\u7684\u306b\u901a\u77e5\u3055\u308c\u307e\u3059\u3002\u6ce8\u610f\uff1aTCP 6880 \u30dd\u30fc\u30c8\u306f\u5185\u90e8\u3067\u5229\u7528\u3059\u308b\u305f\u3081\u3001\u6307\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002 configureWizard.nat.test=\u30c6\u30b9\u30c8 configureWizard.nat.testing=\u30dd\u30fc\u30c8\u3092\u30c6\u30b9\u30c8\u4e2d configureWizard.nat.ok=OK configureWizard.nat.ko=NAT \u30a8\u30e9\u30fc configureWizard.nat.unable=\u6b63\u3057\u3044\u30dd\u30fc\u30c8\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u306a\u3044\u304b\u3001\u30c6\u30b9\u30c8\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\n\u307b\u304b\u306e\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u304c\u3053\u306e\u30dd\u30fc\u30c8\u3092\u5229\u7528\u3057\u3066\u3044\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 configureWizard.file.title=Torrent / \u30d5\u30a1\u30a4\u30eb configureWizard.file.message1=Torrent \u3092\u4fdd\u5b58\u3059\u308b\u30d5\u30a9\u30eb\u30c0\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044: configureWizard.file.path=\u30d1\u30b9 configureWizard.file.browse=\u53c2\u7167 configureWizard.file.message2=Torrent \u306b\u30ec\u30b8\u30e5\u30fc\u30e0\u7528\u30c7\u30fc\u30bf\u3092\u8ffd\u52a0\u3059\u308b\u3053\u3068\u3067\u30ec\u30b8\u30e5\u30fc\u30e0\u304c\u53ef\u80fd\u306b\u306a\u308a\u307e\u3059\u3002\u30ec\u30b8\u30e5\u30fc\u30e0\u3092\u6709\u52b9\u306b\u3059\u308b\u3068\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u9014\u4e2d\u304b\u3089\u518d\u958b\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002 configureWizard.file.fastResume=\u9ad8\u901f\u30ec\u30b8\u30e5\u30fc\u30e0\u3092\u6709\u52b9\u306b\u3059\u308b configureWizard.file.invalidPath=\u7121\u52b9\u306a\u30d5\u30a9\u30eb\u30c0\u3067\u3059 configureWizard.finish.title=\u5b8c\u4e86 configureWizard.finish.message=\u8a2d\u5b9a\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f\u3002 wizard.close.confirmation=\u78ba\u8a8d wizard.close.message=\u6b21\u56de Vuze \u3092\u8d77\u52d5\u3057\u305f\u3068\u304d\u306b\n\u30a6\u30a3\u30b6\u30fc\u30c9\u3092\u5b9f\u884c\u3057\u307e\u3059\u304b\uff1f exportTorrentWizard.title=XML Torrent \u3092\u66f8\u304d\u51fa\u3057 exportTorrentWizard.torrentfile.title=\u5165\u529b\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e exportTorrentWizard.torrentfile.message=\u66f8\u304d\u51fa\u3059 Torrent \u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 exportTorrentWizard.torrentfile.path=\u30d1\u30b9 exportTorrentWizard.torrentfile.browse=\u53c2\u7167 exportTorrentWizard.torrentfile.invalidPath=\u7121\u52b9\u306a Torrent \u30d5\u30a1\u30a4\u30eb\u3067\u3059 exportTorrentWizard.exportfile.title=\u51fa\u529b\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e exportTorrentWizard.exportfile.message=\u51fa\u529b\u5148\u306e XML \u30d5\u30a1\u30a4\u30eb\u540d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044 exportTorrentWizard.exportfile.path=\u30d1\u30b9 exportTorrentWizard.exportfile.browse=\u53c2\u7167 exportTorrentWizard.exportfile.invalidPath=\u7121\u52b9\u306a\u30d5\u30a1\u30a4\u30eb\u3067\u3059 exportTorrentWizard.finish.title=\u5b8c\u4e86 exportTorrentWizard.finish.message=\u66f8\u304d\u51fa\u3057\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f exportTorrentWizard.process.inputfilebad.title=\u7121\u52b9\u306a Torrent \u30d5\u30a1\u30a4\u30eb exportTorrentWizard.process.inputfilebad.message=\u5165\u529b\u30d5\u30a1\u30a4\u30eb\u306e\u30a2\u30af\u30bb\u30b9\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a exportTorrentWizard.process.outputfileexists.title=\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u307e\u3059 exportTorrentWizard.process.outputfileexists.message=\u540c\u540d\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002\u4e0a\u66f8\u304d\u3057\u307e\u3059\u304b\uff1f exportTorrentWizard.process.torrentfail.title=Torrent \u306e\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557 exportTorrentWizard.process.exportfail.title=Torrent \u306e\u66f8\u304d\u51fa\u3057\u306b\u5931\u6557 exportTorrentWizard.process.unknownfail.title=\u4e88\u671f\u3057\u306a\u3044\u30a8\u30e9\u30fc importTorrentWizard.title=XML Torrent \u306e\u8aad\u307f\u8fbc\u307f importTorrentWizard.torrentfile.title=\u51fa\u529b\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e importTorrentWizard.torrentfile.message=\u8aad\u307f\u8fbc\u3080 Torrent \u30d5\u30a1\u30a4\u30eb\u540d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\uff1a importTorrentWizard.torrentfile.path=\u30d1\u30b9 importTorrentWizard.torrentfile.browse=\u53c2\u7167 importTorrentWizard.torrentfile.invalidPath=\u7121\u52b9\u306a\u30d5\u30a1\u30a4\u30eb\u3067\u3059 importTorrentWizard.importfile.title=\u5165\u529b\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e importTorrentWizard.importfile.message=\u8aad\u307f\u8fbc\u3080 XML \u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\uff1a importTorrentWizard.importfile.path=\u30d1\u30b9 importTorrentWizard.importfile.browse=\u53c2\u7167 importTorrentWizard.importfile.invalidPath=\u7121\u52b9\u306a\u30d5\u30a1\u30a4\u30eb\u3067\u3059 importTorrentWizard.finish.title=\u5b8c\u4e86 importTorrentWizard.finish.message=\u8aad\u307f\u8fbc\u307f\u3092\u5b8c\u4e86\u3057\u307e\u3057\u305f importTorrentWizard.process.inputfilebad.title=\u7121\u52b9\u306a\u5165\u529b\u30d5\u30a1\u30a4\u30eb importTorrentWizard.process.inputfilebad.message=\u5165\u529b\u30d5\u30a1\u30a4\u30eb\u306e\u30a2\u30af\u30bb\u30b9\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a importTorrentWizard.process.outputfileexists.title=\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u307e\u3059 importTorrentWizard.process.outputfileexists.message=\u540c\u540d\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002\u4e0a\u66f8\u304d\u3057\u307e\u3059\u304b\uff1f importTorrentWizard.process.torrentfail.title=Torrent \u306e\u66f8\u304d\u51fa\u3057\u306b\u5931\u6557 importTorrentWizard.process.importfail.title=Torrent \u306e\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557 importTorrentWizard.process.unknownfail.title=\u4e88\u671f\u3057\u306a\u3044\u30a8\u30e9\u30fc ConfigView.label.bindip=\u30ed\u30fc\u30ab\u30eb IP \u30a2\u30c9\u30ec\u30b9\u307e\u305f\u306f\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30a4\u30b9\u3092\u30d0\u30a4\u30f3\u30c9 ConfigView.label.xfs.allocation=XFS \u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u56fa\u6709\u306e\u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u7528\u3057\u3066\u30d5\u30a1\u30a4\u30eb\u9818\u57df\u3092\u78ba\u4fdd ConfigView.label.xfs.allocation.tooltip=/usr/sbin/xfs_io \u304c\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u3066\u3044\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u307b\u3068\u3093\u3069\u306e Linux \u30c7\u30a3\u30b9\u30c8\u30ea\u30d3\u30e5\u30fc\u30b7\u30e7\u30f3\u3067\u306f "xfsprogs" \u30d1\u30c3\u30b1\u30fc\u30b8\u306b\u542b\u307e\u308c\u3066\u3044\u307e\u3059\u3002 xfs.allocation.xfs_io.not.found=XFS \u30d5\u30a1\u30a4\u30eb\u30a2\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002/usr/sbin/xfs_io \u3092\u5b9f\u884c\u3067\u304d\u307e\u305b\u3093\u3002\u6b63\u3057\u304f\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u3066\u3044\u308b\u304b\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30a8\u30e9\u30fc: "%1" ConfigView.label.zeronewfiles=\u30d5\u30a1\u30a4\u30eb\u3092\u4f5c\u6210\u3059\u308b\u969b\u3001\u30d5\u30a1\u30a4\u30eb\u9818\u57df\u3092\u3059\u3079\u3066\u78ba\u4fdd\u3057\u3066\u30bc\u30ed\u3067\u57cb\u3081\u308b ConfigView.label.zeronewfiles.tooltip=\u30d5\u30a1\u30a4\u30eb\u306e\u65ad\u7247\u5316\u3092\u6291\u3048\u307e\u3059 ConfigView.section.stats=\u7d71\u8a08\u60c5\u5831 ConfigView.section.stats.enable=\u6709\u52b9 ConfigView.section.stats.defaultsavepath=\u7d71\u8a08\u60c5\u5831\u306e\u4fdd\u5b58\u5148 ConfigView.section.stats.choosedefaultsavepath=\u7d71\u8a08\u60c5\u5831\u3092\u4fdd\u5b58\u3059\u308b\u30d5\u30a9\u30eb\u30c0\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 ConfigView.section.stats.savefreq=\u4fdd\u5b58\u9593\u9694 ConfigView.section.stats.minutes=\u5206 ConfigView.section.stats.hours=\u6642 ConfigView.section.stats.seconds=\u79d2 ConfigView.section.stats.savefile=\u7d71\u8a08\u60c5\u5831\u30d5\u30a1\u30a4\u30eb\u540d ConfigView.section.stats.graph_update_dividers=60 \u79d2\u3054\u3068\u306b\u5782\u76f4\u7dda\u3092\u8868\u793a MyTorrentsView.menu.export=XML Torrent \u306b\u66f8\u304d\u51fa\u3059... MyTorrentsView.menu.host=\u914d\u4fe1... ManagerItem.finishing=\u6700\u7d42\u51e6\u7406\u4e2d ConfigView.dialog.choosedefaulttorrentpath=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e Torrent \u306e\u4fdd\u5b58\u5148\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 ConfigView.dialog.choosemovepath=\u5b8c\u6210\u3057\u305f\u30d5\u30a1\u30a4\u30eb\u306e\u79fb\u52d5\u5148\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 ConfigView.label.movecompleted=\u5b8c\u6210\u3057\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u79fb\u52d5 ConfigView.label.moveremoved=\u5b8c\u6210\u3057\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u79fb\u52d5\uff08\u5143\u306e\u30d5\u30a1\u30a4\u30eb\u306f\u524a\u9664\uff09 ConfigView.label.savetorrents=.torrent \u30d5\u30a1\u30a4\u30eb\u3092\u4fdd\u5b58 MainWindow.menu.view.mytracker=\u30c8\u30e9\u30c3\u30ab\u30fc MyTrackerView.title.full=\u30c8\u30e9\u30c3\u30ab\u30fc MyTrackerView.name=\u540d\u524d MyTrackerView.tracker=\u30c8\u30e9\u30c3\u30ab\u30fc MyTrackerView.status=\u72b6\u6cc1 MyTrackerView.status.started=\u5b9f\u884c\u4e2d MyTrackerView.status.stopped=\u505c\u6b62 MyTrackerView.peers=\u30d4\u30a2 MyTrackerView.seeds=\u30b7\u30fc\u30c0\u30fc MyTrackerView.announces=\u30a2\u30ca\u30a6\u30f3\u30b9 MyTrackerView.uploaded=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9 MyTrackerView.downloaded=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 MyTrackerView.left=\u6b8b\u308a ConfigView.section.style=\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30fc\u30b9 ConfigView.label.set_ui_transfer_speeds=\u8ee2\u9001\u901f\u5ea6\u3092\u9078\u629e\u3067\u304d\u308b\u3088\u3046\u306b\u3059\u308b ConfigView.label.set_ui_transfer_speeds.description=\u30b7\u30b9\u30c6\u30e0\u30c8\u30ec\u30a4\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\u30d0\u30fc\u304b\u3089\u624b\u52d5\u3067\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9/\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6\u3092\u9078\u629e\u3067\u304d\u307e\u3059\u3002\n\u30ab\u30f3\u30de\u533a\u5207\u308a\u3067\u5024\u3092\u5217\u6319\u3057\u3066\u304f\u3060\u3055\u3044\u3002 ConfigView.label.set_ui_transfer_speeds.description.download=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6 (KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 (KB/s) ConfigView.section.style.useCustomTabs=\u9589\u3058\u3089\u308c\u308b\u30bf\u30d6\u3092\u4f7f\u7528\uff08\u518d\u8d77\u52d5\u304c\u5fc5\u8981\uff09 MainWindow.menu.view.plugins=\u30d7\u30e9\u30b0\u30a4\u30f3 fileDownloadWindow.saveTorrentIn=Torrent \u30d5\u30a1\u30a4\u30eb\u306e\u4fdd\u5b58\u5148\uff1a fileDownloadWindow.title=Vuze - Torrent \u30c0\u30a6\u30f3\u30ed\u30fc\u30c0 fileDownloadWindow.downloading=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5143\uff1a fileDownloadWindow.status=\u72b6\u6cc1\uff1a fileDownloadWindow.state_initializing=\u521d\u671f\u5316\u4e2d fileDownloadWindow.state_downloading=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d fileDownloadWindow.state_error=\u30a8\u30e9\u30fc\uff1a MainWindow.menu.file.open.url=\u5834\u6240... openUrl.title=\u5834\u6240\u3092\u958b\u304f openUrl.url=URL\uff1a MyTorrentsView.menu.host.error.title=Torrent \u914d\u4fe1\u5931\u6557 MyTorrentsView.menu.host.error.message=Torrent \u3092\u914d\u4fe1\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f ConfigView.section.tracker=\u30c8\u30e9\u30c3\u30ab\u30fc ConfigView.section.tracker.pollinterval=\u30c8\u30e9\u30c3\u30ab\u30fc\u3078\u306e\u554f\u3044\u5408\u308f\u305b\u9593\u9694\uff08\u79d2\uff09 ConfigView.section.tracker.publishenable=\u30c8\u30e9\u30c3\u30ab\u30fc\u306e\u8a73\u7d30\u3092 "" \u306b\u516c\u958b ConfigView.section.tracker.ip=\u30c8\u30e9\u30c3\u30ab\u30fc\u306e\u30b0\u30ed\u30fc\u30d0\u30eb IP \u30a2\u30c9\u30ec\u30b9 ConfigView.section.style.enableXPStyle=XP \u30b9\u30bf\u30a4\u30eb\u3092\u4f7f\u7528\uff08\u518d\u8d77\u52d5\u304c\u5fc5\u8981\uff09 ConfigView.section.tracker.checkip=\u81ea\u52d5\u691c\u51fa... ipCheckerWizard.title=IP \u30c1\u30a7\u30c3\u30ab\u30fc\u30a6\u30a3\u30b6\u30fc\u30c9 ipCheckerWizard.service=\u30b5\u30fc\u30d3\u30b9 ipCheckerWizard.chooseService=\u4e00\u89a7\u304b\u3089 IP \u30c1\u30a7\u30c3\u30ab\u30fc\u30b5\u30fc\u30d3\u30b9\u3092\u9078\u3093\u3067\u304f\u3060\u3055\u3044 ipCheckerWizard.explanations=\u3053\u306e\u30a6\u30a3\u30b6\u30fc\u30c9\u3067\u306f\u3042\u306a\u305f\u306e\u5916\u90e8 IP \u30a2\u30c9\u30ec\u30b9\u3092\u691c\u51fa\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u52d5\u7684 IP \u30a2\u30c9\u30ec\u30b9\u3092\u304a\u4f7f\u3044\u306e\u5834\u5408\u306f\u52d5\u7684 DNS \u30b5\u30fc\u30d3\u30b9\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u4f5c\u308b\u3053\u3068\u3092\u304a\u52e7\u3081\u3057\u307e\u3059\u3002\u4e0b\u8a18\u306e\u30ea\u30f3\u30af\u3088\u308a\uff08\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u308b\uff09\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u4f5c\u6210\u3067\u304d\u307e\u3059\u3002\u305d\u3057\u3066 IP \u30a2\u30c9\u30ec\u30b9\u6b04\u306b\u30db\u30b9\u30c8\u540d\uff08\u4f8b\uff1amyhostname.dydns.org\uff09\u3092\u5165\u529b\u3057\u307e\u3059\u3002IP \u30a2\u30c9\u30ec\u30b9\u304c\u5909\u308f\u3063\u3066\u3082 Torrent \u3092\u30db\u30b9\u30c8\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u308b\u3088\u3046\u306b\u3059\u308b\u305f\u3081\u306b\u3001\u52d5\u7684 DNS \u30b5\u30fc\u30d3\u30b9\u306b\u6700\u65b0\u306e IP \u30a2\u30c9\u30ec\u30b9\u3092\u81ea\u52d5\u7684\u306b\u4f1d\u9054\u3059\u308b\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u5c0e\u5165\u3057\u3066\u304f\u3060\u3055\u3044\u3002 ipCheckerWizard.service.description=\u8aac\u660e : ipCheckerWizard.service.url=\u30ea\u30f3\u30af : ipCheckerWizard.progresstitle=IP \u30a2\u30c9\u30ec\u30b9\u3092\u78ba\u8a8d\u4e2d ipCheckerWizard.checkComplete=IP \u30a2\u30c9\u30ec\u30b9\uff1a ipCheckerWizard.checkFailed=\u5931\u6557\u7406\u7531\uff1a wizard.tracker.local=Vuze \u5185\u8535\u30c8\u30e9\u30c3\u30ab\u30fc\u3092\u4f7f\u7528 wizard.tracker.external=\u5916\u90e8\u306e\u30c8\u30e9\u30c3\u30ab\u30fc\u3092\u4f7f\u7528 wizard.tracker.howToLocal=\t\u30c4\u30fc\u30eb\uff1e\u74b0\u5883\u8a2d\u5b9a>\u30c8\u30e9\u30c3\u30ab\u30fc \u3067\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044 wizard.announceUrl=\u30a2\u30ca\u30a6\u30f3\u30b9 URL : IPChecker.external.service.discoveryvip.name=Discoveryvip - IP \u30a2\u30c9\u30ec\u30b9\u306e\u78ba\u8a8d\u306e\u307f IPChecker.external.httpinvalidresponse=\u7121\u52b9\u306a HTTP \u5fdc\u7b54 IPChecker.external.loadingwebpage=Web \u30da\u30fc\u30b8\u3092\u8aad\u307f\u8fbc\u307f\u4e2d IPChecker.external.analysingresponse=\u5fdc\u7b54\u3092\u89e3\u6790\u4e2d IPChecker.external.addressextracted=\u5c55\u958b\u3055\u308c\u305f IP \u30a2\u30c9\u30ec\u30b9 IPChecker.external.httploadfail=\u30da\u30fc\u30b8\u306e\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3057\u307e\u3057\u305f IPChecker.external.timeout=\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u304c\u767a\u751f\u3057\u307e\u3057\u305f IPChecker.external.ipnotfound=IP \u30a2\u30c9\u30ec\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f ConfigView.section.tracker.pollintervalmin=\u6700\u77ed\uff1a ConfigView.section.tracker.pollintervalmax=\u6700\u9577\uff1a ConfigView.section.tracker.pollintervalincby=\u9593\u9694\u3092\u5ef6\u3070\u3059\uff1a ConfigView.section.tracker.pollintervalincper=\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u6570\u3054\u3068\u306b\u5ef6\u3070\u3059\uff1a splash.loadingImages=\u753b\u50cf\u3092\u30ed\u30fc\u30c9\u4e2d splash.initializeGui=\u30e1\u30a4\u30f3\u30a6\u30a4\u30f3\u30c9\u30a6\u3092\u521d\u671f\u5316\u4e2d splash.openViews=\u30d3\u30e5\u30fc\u3092\u4f5c\u6210\u4e2d splash.plugin=\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u30ed\u30fc\u30c9\u4e2d\uff1a configureWizard.nat.tooManyPorts=\u30dd\u30fc\u30c8\u304c\u591a\u3059\u304e\u307e\u3059\uff08\u6700\u5927 9 \u500b\uff09 ConfigView.section.color=\u30ab\u30e9\u30fc MyTorrentsView.menu.publish=\u516c\u958b... MyTrackerView.status.published=\u516c\u958b\u4e2d MyTrackerView.completed=\u5b8c\u4e86 MainWindow.menu.file.open.torrentnodefault=Torrent \u30d5\u30a1\u30a4\u30eb... wizard.comment=\u30b3\u30e1\u30f3\u30c8 ConfigView.label.movetorrent=.torrent \u30d5\u30a1\u30a4\u30eb\u3092\u79fb\u52d5 ConfigView.label.movepartialdownloads=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u306a\u3044 \u306b\u30de\u30fc\u30af\u3057\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u79fb\u52d5 ConfigView.label.subdir_is_in_default=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5148\u306e\u30d5\u30a9\u30eb\u30c0\u304c\u5b58\u5728\u3059\u308b\u3068\u304d\u3001\u30b5\u30d6\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d\u306e\u30d5\u30a9\u30eb\u30c0\u3068\u898b\u306a\u3059 ConfigView.section.file.decoder.label=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u6587\u5b57\u30a8\u30f3\u30b3\u30fc\u30c9 ConfigView.section.file.decoder.nodecoder=\u306a\u3057 IPChecker.external.service.no-ip.description=\u30c0\u30a4\u30ca\u30df\u30c3\u30af\uff0f\u30b9\u30bf\u30c6\u30a3\u30c3\u30af DNS \u30b5\u30fc\u30d3\u30b9\u30d7\u30ed\u30d0\u30a4\u30c0\n\uff08\u5229\u7528\u53ef\u80fd\u306a\u7121\u6599\u306e '\u30c1\u30a7\u30c3\u30af\u30a2\u30c9\u30ec\u30b9' \u30b5\u30fc\u30d3\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\uff09 ConfigView.section.tracker.publicenable=\u5916\u90e8 Torrent \u3092\u6709\u52b9\u306b\u3059\u308b ConfigView.label.playdownloadspeech=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5b8c\u4e86\u6642\u306b\u97f3\u58f0\u3067\u77e5\u3089\u305b\u308b ConfigView.label.playdownloadspeech.info=\u73fe\u5728\u3053\u306e\u6a5f\u80fd\u306f\u82f1\u8a9e\u3067\u306e\u307f\u52d5\u4f5c\u3057\u307e\u3059 # # Tooltips # GeneralView.label.status.pieces_available.tooltip=\u305d\u308c\u305e\u308c\u306e\u30d4\u30fc\u30b9\u304c\u3044\u304f\u3064\u5165\u624b\u3067\u304d\u308b\u304b\u3092\u8868\u3057\u3066\u3044\u307e\u3059\u3002\n\u3053\u306e\u6570\u5024\u304c 1 \u3088\u308a\u3082\u5c0f\u3055\u3044\u5834\u5408\u3001\u30d5\u30a1\u30a4\u30eb\u3092\u5b8c\u6210\u3055\u305b\u308b\u305f\u3081\u306b\u5fc5\u8981\u306a\u30d4\u30fc\u30b9\u304c\u63c3\u3063\u3066\u3044\u307e\u305b\u3093\uff08\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u304c\u5b8c\u4e86\u3057\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\uff09 GeneralView.label.trackerurl.tooltip=\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u30a2\u30ca\u30a6\u30f3\u30b9 URL \u304c\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u306b\u30b3\u30d4\u30fc\u3055\u308c\u307e\u3059 GeneralView.label.trackerurlopen.tooltip=\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u30c8\u30e9\u30c3\u30ab\u30fc\u306e\u30e1\u30a4\u30f3\u30da\u30fc\u30b8\u304c\u958b\u304d\u307e\u3059 # # 2.0.4.4 # ConfigView.section.style.guiUpdate=\u753b\u9762\u306e\u66f4\u65b0\u983b\u5ea6 ConfigView.section.style.inactiveUpdate=\u30a2\u30af\u30c6\u30a3\u30d6\u3067\u306a\u3044\u6642\u3082\u6307\u5b9a\u3057\u305f\u6642\u9593\u3054\u3068\u306b\u30e1\u30a4\u30f3\u30a6\u30a4\u30f3\u30c9\u30a6\u3092\u66f4\u65b0 ConfigView.section.style.graphicsUpdate=\u30b0\u30e9\u30d5\u306e\u66f4\u65b0\u983b\u5ea6\uff08\u753b\u9762\u306e\u66f4\u65b0\u56de\u6570\uff09 ConfigView.section.style.reOrderDelay=\u30bd\u30fc\u30c8\u306e\u983b\u5ea6\uff08\u753b\u9762\u306e\u66f4\u65b0\u56de\u6570\uff09 [0: \u3057\u306a\u3044] ConfigView.section.style.reOrderDelay.never=\u3057\u306a\u3044 ConfigView.section.logging=\u30ed\u30b0 ConfigView.section.logging.enable=\u30ed\u30b0\u8a18\u9332\u3092\u6709\u52b9\u306b\u3059\u308b ConfigView.section.logging.logdir=\u30ed\u30b0\u30d5\u30a1\u30a4\u30eb\u306e\u30d1\u30b9\uff1a ConfigView.section.logging.choosedefaultsavepath=\u30ed\u30b0\u30d5\u30a1\u30a4\u30eb\u306e\u4fdd\u5b58\u5148\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 GeneralView.label.updatein.querying=\u554f\u3044\u5408\u308f\u305b\u4e2d... configureWizard.nat.sharePort=1 \u3064\u306e\u30dd\u30fc\u30c8\u3092\u3059\u3079\u3066\u306e Torrent \u3067\u5171\u6709 ConfigView.section.logging.maxsize=\u6700\u5927\u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba\uff1a ConfigView.section.tracker.passwordenableweb=Tracker Web \u3092\u8a8d\u8a3c ConfigView.section.tracker.passwordenabletorrent=Torrent \u3092\u8a8d\u8a3c ConfigView.section.tracker.username=\u30e6\u30fc\u30b6\u540d\uff1a ConfigView.section.tracker.password=\u30d1\u30b9\u30ef\u30fc\u30c9\uff1a columnChooser.title=\u8868\u793a\u3059\u308b\u9805\u76ee\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 columnChooser.move=\u5217\u3092\u30c9\u30e9\u30c3\u30b0\u3057\u3066\u4e26\u3079\u66ff\u3048\u307e\u3059 columnChooser.apply=\u9069\u7528 columnChooser.columnname=\u9805\u76ee columnChooser.columndescription=\u8aac\u660e TableColumn.header.shareRatio=\u8ca0\u62c5\u7387 MyTorrentsView.menu.editTableColumns=\u8868\u793a\u9805\u76ee\u306e\u8a2d\u5b9a wizard.operationfailed=\u64cd\u4f5c\u306b\u5931\u6557\u3057\u307e\u3057\u305f authenticator.title=\u30e6\u30fc\u30b6\u8a8d\u8a3c authenticator.realm=\u30ec\u30eb\u30e0 authenticator.tracker=\u30c8\u30e9\u30c3\u30ab\u30fc authenticator.user=\u30e6\u30fc\u30b6\u540d authenticator.password=\u30d1\u30b9\u30ef\u30fc\u30c9 ConfigView.label.allowSendVersion=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306e\u78ba\u8a8d\u6642\u306b\u30d0\u30fc\u30b8\u30e7\u30f3\u3068\u4e00\u610f\u306e ID \u306e\u9001\u4fe1\uff08\u533f\u540d\uff09\u3092\u8a31\u53ef ConfigView.label.version.info.link=\u30d0\u30fc\u30b8\u30e7\u30f3\u30c1\u30a7\u30c3\u30af\u6642\u306b\u30b5\u30fc\u30d0\u306b\u9001\u4fe1\u3059\u308b\u60c5\u5831\u306b\u3064\u3044\u3066\u306f\u3053\u3061\u3089\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 wizard.hint.mode=\u30d2\u30f3\u30c8\uff1a\t\u3053\u306e\u30a6\u30a3\u30b6\u30fc\u30c9\u306b\u30c9\u30e9\u30c3\u30b0\uff06\u30c9\u30ed\u30c3\u30d7\u3059\u308b\u3053\u3068\u3067\n\u30d5\u30a1\u30a4\u30eb\u304b\u30d5\u30a9\u30eb\u30c0\u3092\u9078\u629e\u3067\u304d\u307e\u3059 wizard.hint.file=\u30d2\u30f3\u30c8\uff1a\t\u30c9\u30e9\u30c3\u30b0\uff06\u30c9\u30ed\u30c3\u30d7\u3067\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3067\u304d\u307e\u3059 wizard.hint.directory=\u30d2\u30f3\u30c8\uff1a\t\u30c9\u30e9\u30c3\u30b0\uff06\u30c9\u30ed\u30c3\u30d7\u3067\u30d5\u30a9\u30eb\u30c0\u3092\u9078\u629e\u3067\u304d\u307e\u3059 MainWindow.menu.help.checkupdate=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d... TableColumn.header.down=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u6e08 TableColumn.header.up=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6e08 ConfigView.section.tracker.passwordenabletorrent.info=\u9069\u5f53\u306a\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u5fc5\u8981\u3067\u3059\uff08\u4f8b\uff1aVuze\uff09 ConfigView.section.style.confirmationOnExit=\u7d42\u4e86\u6642\u306b\u78ba\u8a8d\u306e\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u8868\u793a MainWindow.dialog.exitconfirmation.title=\u7d42\u4e86\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f MainWindow.dialog.exitconfirmation.text=Vuze \u3092\u7d42\u4e86\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f SystemTray.menu.stopalltransfers=\u3059\u3079\u3066\u306e\u8ee2\u9001\u3092\u505c\u6b62 TrayWindow.menu.stopalldownloads=\u3059\u3079\u3066\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u505c\u6b62 ConfigView.section.tracker.sslport.info=\u8a73\u7d30\u306f FAQ \u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044 wizard.tracker.ssl=SSL \u3092\u4f7f\u7528 ConfigView.label.playdownloadfinished=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5b8c\u4e86\u6642\u306b\u30b5\u30a6\u30f3\u30c9\u3092\u9cf4\u3089\u3059 ConfigView.label.popupdownloadfinished=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5b8c\u4e86\u6642\u306b\u30dd\u30c3\u30d7\u30a2\u30c3\u30d7\u3067\u77e5\u3089\u305b\u308b ConfigView.label.popupfilefinished=\u30d5\u30a1\u30a4\u30eb\u5b8c\u6210\u6642\u306b\u30dd\u30c3\u30d7\u30a2\u30c3\u30d7\u3067\u77e5\u3089\u305b\u308b TableColumn.header.pieces=\u30d4\u30fc\u30b9 TableColumn.header.pieces.info=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u305f\u30d4\u30fc\u30b9\u3092\u30b0\u30e9\u30d5\u8868\u793a TableColumn.header.completion=\u9032\u884c\u72b6\u6cc1 TableColumn.header.completion.info=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u306e\u9032\u884c\u72b6\u6cc1\u3092\u30b0\u30e9\u30d5\u8868\u793a ConfigView.section.style.showdownloadbasket=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30d0\u30b9\u30b1\u30c3\u30c8\u3092\u8868\u793a\uff08.torrent \u30d5\u30a1\u30a4\u30eb\u3092\u30c9\u30e9\u30c3\u30b0\uff06\u30c9\u30ed\u30c3\u30d7\u3057\u3066\u304f\u3060\u3055\u3044\uff09 ConfigView.section.style.alwaysShowTorrentFiles=\u8a73\u7d30\u30a6\u30a4\u30f3\u30c9\u30a6\u306b Torrent \u30d5\u30a1\u30a4\u30eb\u3092\u5e38\u306b\u8868\u793a wizard.multitracker=Torrent \u306b\u30de\u30eb\u30c1\u30c8\u30e9\u30c3\u30ab\u30fc\u60c5\u5831\u3092\u8ffd\u52a0 wizard.multitracker.title=\u30de\u30eb\u30c1\u30c8\u30e9\u30c3\u30ab\u30fc wizard.multitracker.configuration=\u30de\u30eb\u30c1\u30c8\u30e9\u30c3\u30ab\u30fc\u8a2d\u5b9a wizard.multitracker.new=\u8ffd\u52a0... wizard.multitracker.edit=\u7de8\u96c6... wizard.multitracker.delete=\u524a\u9664 wizard.multitracker.group=\u30c8\u30e9\u30c3\u30ab\u30fc\u30b0\u30eb\u30fc\u30d7 wizard.multitracker.edit.title=\u30de\u30eb\u30c1\u30c8\u30e9\u30c3\u30ab\u30fc\u30a8\u30c7\u30a3\u30bf wizard.multitracker.edit.name=\u540d\u524d wizard.multitracker.edit.save=\u4fdd\u5b58 wizard.multitracker.edit.newgroup=\u65b0\u898f\u30b0\u30eb\u30fc\u30d7 wizard.multitracker.edit.deletegroup=\u524a\u9664 wizard.multitracker.edit.newtracker=\u65b0\u898f\u30c8\u30e9\u30c3\u30ab\u30fc wizard.multitracker.edit.deletetracker=\u524a\u9664 wizard.multitracker.edit.edit=\u7de8\u96c6 wizard.addingmt=\u30de\u30eb\u30c1\u30c8\u30e9\u30c3\u30ab\u30fc\u60c5\u5831\u3092\u8ffd\u52a0\u4e2d wizard.multitracker.noannounce=\u30c8\u30e9\u30c3\u30ab\u30fc\u4e00\u89a7\u306b\u30a2\u30ca\u30a6\u30f3\u30b9 URL \u304c\u3042\u308a\u307e\u305b\u3093 MyTorrentsView.menu.recheck=\u5f37\u5236\u7684\u306b\u518d\u30c1\u30a7\u30c3\u30af iconBar.showDownloadBar.tooltip=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30d0\u30fc\u3092\u8868\u793a\u3057\u307e\u3059 iconBar.start.tooltip=\u958b\u59cb iconBar.stop.tooltip=\u505c\u6b62 iconBar.remove.tooltip=\u524a\u9664 iconBar.openNoDefault.tooltip=.torrent \u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304d\u307e\u3059 iconBar.openURL.tooltip=URL \u3092\u958b\u304d\u307e\u3059 iconBar.openFolder.tooltip=\u30d5\u30a9\u30eb\u30c0\u3092\u958b\u304d\u307e\u3059 iconBar.new.tooltip=Torrent \u3092\u4f5c\u6210\u3057\u307e\u3059 iconBar.up.tooltip=\u4e0a\u3078 iconBar.down.tooltip=\u4e0b\u3078 iconBar.run.tooltip=\u958b\u304f iconBar.host.tooltip=\u914d\u4fe1 iconBar.publish.tooltip=\u516c\u958b MyTorrentsView.menu.editTracker=\u30c8\u30e9\u30c3\u30ab\u30fc \u306e URL \u3092\u7de8\u96c6... GeneralView.menu.selectTracker=\u9078\u629e ConfigView.section.stats.xslfile=XSL \u30d5\u30a1\u30a4\u30eb\u540d ConfigView.section.stats.xslfiledetails= \u30bf\u30b0\u3092\u901a\u3058\u3066\u7d71\u8a08\u30d5\u30a1\u30a4\u30eb\u306e\u30d8\u30c3\u30c0\u306b\u7d44\u307f\u8fbc\u307e\u308c\u307e\u3059 ConfigView.label.savetorrentbackup=\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u3092\u4fdd\u5b58 ConfigView.section.tracker.forceport=\u5f37\u5236\u7684\u306b\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30dd\u30fc\u30c8\u3067\u914d\u4fe1 ConfigView.section.ipfilter.allow=\u6307\u5b9a\u3057\u305f\u7bc4\u56f2\u3092\u8a31\u53ef\uff08\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u306f\u62d2\u5426\uff09 ConfigView.section.ipfilter.list.inrange=\u306f\u7bc4\u56f2\u5185 ConfigView.section.ipfilter.list.notinrange=\u306f\u7bc4\u56f2\u5916 ConfigView.section.ipfilter.list.title=\u30d6\u30ed\u30c3\u30af\u3055\u308c\u305f IP ConfigView.label.allowsameip=\u540c\u4e00 IP \u304b\u3089\u306e\u591a\u91cd\u63a5\u7d9a\u3092\u8a31\u53ef ConfigView.label.allowsameip.tooltip=\u5fc5\u8981\u306a\u5834\u5408\u306b\u9650\u308a ON \u306b\u3057\u3066\u4e0b\u3055\u3044\u3002\n\u3053\u308c\u306f\u30ea\u30fc\u30c1\u30e3\u30fc\u306b\u5bfe\u3059\u308b\u9632\u8b77\u6a5f\u80fd\u3067\u3059\uff08\u30c7\u30d5\u30a9\u30eb\u30c8\u306f OFF\uff09 ManagerItem.superseeding=\u30b9\u30fc\u30d1\u30fc\u30b7\u30fc\u30c9\u4e2d ConfigView.label.userSuperSeeding=\u30b9\u30fc\u30d1\u30fc\u30b7\u30fc\u30c9\u3092\u4f7f\u7528 PeersView.uniquepiece=\u30d4\u30fc\u30b9\uff08\u30b9\u30fc\u30d1\u30fc\u30b7\u30fc\u30c9\u30e2\u30fc\u30c9\uff09 PeersView.uniquepiece.none=\u306a\u3057 PeersView.timetosend=\u30d4\u30fc\u30b9\u518d\u9001\u307e\u3067\uff08\u30b9\u30fc\u30d1\u30fc\u30b7\u30fc\u30c9\u30e2\u30fc\u30c9\uff09 ConfigView.section.style.addurlsilently=URL \u3092\u78ba\u8a8d\u305b\u305a\u306b\u958b\u304f ConfigView.section.style.addurlsilently.tooltip=.torrent \u3092\u30c9\u30ed\u30c3\u30d7\u3057\u305f\u969b\u306b\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u8868\u793a\u3057\u306a\u3044\u3067\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u958b\u59cb\u3057\u307e\u3059 ConfigView.section.file.decoder.prompt=\u6587\u5b57\u30a8\u30f3\u30b3\u30fc\u30c9\u304c\u9078\u629e\u3067\u304d\u308b\u5834\u5408\u306f\u5e38\u306b\u305f\u305a\u306d\u308b ConfigView.section.file.decoder.prompt.tooltip=\u6587\u5b57\u30a8\u30f3\u30b3\u30fc\u30c9\u304c\u9078\u629e\u3067\u304d\u308b\u5834\u5408\u306b\u9078\u629e\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u8868\u793a\u3057\u307e\u3059 MyTorrentsView.menu.moveTop=\u5148\u982d\u3078 MyTorrentsView.menu.moveEnd=\u672b\u5c3e\u3078 ConfigView.label.moveonlyusingdefaultsave=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u4fdd\u5b58\u5148\u306b\u4fdd\u5b58\u3057\u305f\u5834\u5408\u306e\u307f ConfigView.label.moveonlyusingdefaultsave.tooltip=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30c7\u30fc\u30bf\u30d5\u30a9\u30eb\u30c0\u306b\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u305f\u30c7\u30fc\u30bf\u304c\u3042\u308b\u5834\u5408\u306e\u307f\u79fb\u52d5\u3057\u307e\u3059 ConfigView.label.watchtorrentfolder=\u76e3\u8996\u30d5\u30a9\u30eb\u30c0\u306e .torrent \u30d5\u30a1\u30a4\u30eb\u3092\u81ea\u52d5\u7684\u306b\u8aad\u307f\u8fbc\u3080 ConfigView.label.watchtorrentfolder.tooltip=\u5b9a\u671f\u7684\u306b\u65b0\u3057\u3044 .torrent \u30d5\u30a1\u30a4\u30eb\u3092\u78ba\u8a8d\u3057\u307e\u3059 ConfigView.label.watchtorrentfolderinterval=\u76e3\u8996\u9593\u9694 ConfigView.label.watchtorrentfolderinterval.tooltip=\u30d5\u30a9\u30eb\u30c0\u3092\u78ba\u8a8d\u3059\u308b\u9593\u9694 ConfigView.dialog.choosewatchtorrentfolderpath=Torrent \u306e\u30a4\u30f3\u30dd\u30fc\u30c8\u5148\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 ConfigView.label.startwatchedtorrentsstopped=\u505c\u6b62\u72b6\u614b\u3067\u8ffd\u52a0 ConfigView.label.startwatchedtorrentsstopped.tooltip=.torrent \u3092\u8aad\u307f\u8fbc\u3093\u3060\u5f8c '\u505c\u6b62' \u72b6\u614b\u306b\u3057\u307e\u3059 ConfigView.section.plugins=\u30d7\u30e9\u30b0\u30a4\u30f3 wizard.maketorrent.filesize=\u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba wizard.maketorrent.piececount=\u30d4\u30fc\u30b9\u6570 wizard.maketorrent.piecesize=\u30d4\u30fc\u30b9\u9577 wizard.maketorrent.auto=\u81ea\u52d5 MainWindow.menu.view.stats=\u7d71\u8a08\u60c5\u5831 SpeedView.title.full=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 SpeedView.downloadSpeed.title=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6 SpeedView.uploadSpeed.title=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 ConfigView.section.style.useSIUnits=SI \u5358\u4f4d\u3092\u4f7f\u7528\uff08KB \u2192 KiB \u7b49\uff09 iconBar.top.tooltip=\u5148\u982d\u3078 iconBar.bottom.tooltip=\u6700\u5f8c\u3078 TableColumn.header.health=\u5065\u5eb7\u5ea6 MyTorrentsView.menu.health=\u5065\u5eb7\u5ea6\u306b\u3064\u3044\u3066 health.explain.grey=\u73fe\u5728\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u30fb\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3068\u3082\u884c\u3063\u3066\u3044\u307e\u305b\u3093\u3002 health.explain.red=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d\u3067\u3059\u304c\u3001\u30d4\u30a2\u306b\u63a5\u7d9a\u3057\u3066\u3044\u307e\u305b\u3093\u3002 health.explain.blue=\u30b7\u30fc\u30c9\u4e2d\u306e\u5834\u5408\u3001\u307e\u3060\u30d4\u30a2\u3068\u63a5\u7d9a\u3057\u3066\u3044\u307e\u305b\u3093\u3002\n\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d\u306e\u5834\u5408\u3001\u30d4\u30a2\u3068\u63a5\u7d9a\u3057\u3066\u3044\u307e\u3059\u304c\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3059\u3002 health.explain.yellow=\u30d4\u30a2\u3068\u63a5\u7d9a\u3057\u3066\u304a\u308a\u3001\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u3082\u554f\u984c\u3042\u308a\u307e\u305b\u3093\u304c\u3001\u5916\u90e8\u304b\u3089\u306e\u63a5\u7d9a\u304c\u3042\u308a\u307e\u305b\u3093\u3002\n\u305a\u3063\u3068\u3053\u306e\u72b6\u6cc1\u306a\u3089\u3001NAT\u306b\u554f\u984c\u304c\u3042\u308b\u3067\u3057\u3087\u3046\u3002 health.explain.green=\u6b63\u5e38\u306b\u51e6\u7406\u3057\u3066\u3044\u307e\u3059\u3002 ConfigView.section.style.alwaysRefreshMyTorrents=Torrent \u30d3\u30e5\u30fc\u3092\u5e38\u306b\u66f4\u65b0 ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Torrent \u30d3\u30e5\u30fc\u3092\u8868\u793a\u3057\u3066\u3044\u306a\u304f\u3066\u3082\u66f4\u65b0\u3057\u307e\u3059\uff08\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u3044\u304f\u3064\u304b\u306e mirc \u30d7\u30e9\u30b0\u30a4\u30f3\u3067\u6709\u52b9\u3067\u3059\uff09 # #2.0.7.0 # security.certtruster.title=\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u8a3c\u660e\u66f8\u306e\u8b66\u544a security.certtruster.intro=\u3053\u306e\u8a3c\u660e\u66f8\u306f\u307e\u3060\u8a8d\u8a3c\u3055\u308c\u3066\u3044\u306a\u3044\u6a5f\u95a2\u306b\u3088\u3063\u3066\u767a\u884c\u3055\u308c\u3066\u3044\u307e\u3059 security.certtruster.resource=\u30ea\u30bd\u30fc\u30b9\uff1a security.certtruster.issuedto=\u767a\u884c\u5148\uff1a security.certtruster.issuedby=\u767a\u884c\u8005\uff1a security.certtruster.prompt=\u3053\u306e\u8a3c\u660e\u66f8\u3092\u8a8d\u8a3c\u3057\u307e\u3059\u304b\uff1f security.certtruster.yes=\u306f\u3044 security.certtruster.no=\u3044\u3044\u3048 ConfigView.section.tracker.torrentsperpage=1 \u30da\u30fc\u30b8\u3042\u305f\u308a\u306e Torrent \u6570 [0: \u7121\u5236\u9650] MainWindow.menu.file.share=\u5171\u6709 MainWindow.menu.file.share.file=\u30d5\u30a1\u30a4\u30eb... MainWindow.menu.file.share.dir=\u30d5\u30a9\u30eb\u30c0... MainWindow.menu.file.share.dircontents=\u30d5\u30a9\u30eb\u30c0\u306e\u5185\u5bb9... MainWindow.menu.file.share.dircontentsrecursive=\u30d5\u30a9\u30eb\u30c0\u306e\u5185\u5bb9\uff08\u518d\u5e30\uff09... MainWindow.dialog.share.sharefile=\u5171\u6709\u3059\u308b\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 MainWindow.dialog.share.sharedir=\u5171\u6709\u3059\u308b\u30d5\u30a9\u30eb\u30c0\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 MainWindow.dialog.share.sharedircontents=\u5171\u6709\u3059\u308b\u30d5\u30a9\u30eb\u30c0\u306e\u5185\u5bb9\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 MainWindow.dialog.share.sharedircontents.recursive=\u518d\u5e30 globalmanager.download.remove.veto=\u524a\u9664\u306e\u62d2\u5426 plugin.sharing.download.remove.veto=\u3053\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u306f\u5171\u6709\u3055\u308c\u3066\u3044\u307e\u3059\u3002\n\u95a2\u9023\u3059\u308b\u5171\u6709\u3092\u524a\u9664\u3057\u3066\u304f\u3060\u3055\u3044\u3002: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=\u30e1\u30a4\u30f3 ConfigView.label.prioritizefirstpiece=\u30d5\u30a1\u30a4\u30eb\u306e\u5148\u982d\u3068\u672b\u5c3e\u306e\u30d4\u30fc\u30b9\u3092\u512a\u5148 ConfigView.label.prioritizefirstpiece.tooltip=\u3067\u304d\u308b\u3060\u3051\u65e9\u304f\u30d7\u30ec\u30d3\u30e5\u30fc\u304c\u51fa\u6765\u308b\u3088\u3046\u3001\n\u30d5\u30a1\u30a4\u30eb\u306e\u5148\u982d\u3068\u672b\u5c3e\u306b\u3042\u305f\u308b\u30d4\u30fc\u30b9\u3092\u512a\u5148\u3057\u3066\u53d6\u5f97\u3057\u307e\u3059 ConfigView.section.file.confirm_data_delete=\u30c7\u30fc\u30bf\u3092\u524a\u9664\u3059\u308b\u524d\u306b\u78ba\u8a8d ConfigView.section.file.confirm_data_delete.tooltip=\u30c7\u30fc\u30bf\u3092\u524a\u9664\u3059\u308b\u969b\u306b\u78ba\u8a8d\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u8868\u793a\u3057\u307e\u3059 ConfigView.section.file.delete.include_files_outside_save_dir=\u30c7\u30fc\u30bf\u3092\u524a\u9664\u3059\u308b\u969b\u3001 Torrent \u5916\u306b\u30ea\u30f3\u30af\u3055\u308c\u3066\u3044\u308b\u30d5\u30a1\u30a4\u30eb\u3082\u524a\u9664 TrayWindow.menu.startalldownloads=\u3059\u3079\u3066\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u958b\u59cb SystemTray.menu.startalltransfers=\u3059\u3079\u3066\u306e\u8ee2\u9001\u3092\u958b\u59cb sharing.progress.title=\u72b6\u6cc1\u3092\u5171\u6709 sharing.progress.hide=\u96a0\u3059 MainWindow.menu.view.myshares=\u5171\u6709 MySharesView.title.full=\u5171\u6709 MySharesView.name=\u540d\u524d MySharesView.type=\u7a2e\u985e MySharesView.type.file=\u30d5\u30a1\u30a4\u30eb MySharesView.type.dir=\u30d5\u30a9\u30eb\u30c0 MySharesView.type.dircontents=\u30d5\u30a9\u30eb\u30c0\u5185\u5bb9 MySharesView.type.dircontentsrecursive=\u30d5\u30a9\u30eb\u30c0\u5185\u5bb9\uff08\u518d\u5e30\uff09 MySharesView.menu.remove=\u524a\u9664 ConfigView.section.tracker.extensions=\u62e1\u5f35 ConfigView.section.tracker.sendpeerids=\u30d4\u30a2 ID \u3092\u5404\u30d4\u30a2\u3078\u9001\u4fe1 ConfigView.section.tracker.enableudp=UDP \u3092\u4f7f\u7528 plugin.sharing.torrent.remove.veto=\u3053\u306e\u30c8\u30e9\u30c3\u30ab\u30fc\u767b\u9332\u306f\u5171\u6709\u3055\u308c\u3066\u3044\u307e\u3059\u3002\n\u95a2\u9023\u3059\u308b\u5171\u6709\u3092\u524a\u9664\u3057\u3066\u304f\u3060\u3055\u3044\u3002: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=\u505c\u6b62\u3057\u3066\u3044\u306a\u3044\u305f\u3081\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 plugin.sharing.remove.veto=\u3053\u306e\u5171\u6709\u306f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30b3\u30f3\u30c6\u30f3\u30c4\u5171\u6709\u306e\u30b5\u30d6\u5171\u6709\u3067\u3059\u3002\n\u30eb\u30fc\u30c8\u5171\u6709\u3092\u524a\u9664\u3057\u3066\u304f\u3060\u3055\u3044\u3002 GeneralView.label.hash.tooltip=\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u30cf\u30c3\u30b7\u30e5\u304c\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u306b\u30b3\u30d4\u30fc\u3055\u308c\u307e\u3059 ConfigView.section.tracker.maxpeersreturned=\u30d4\u30a2\u3078\u56de\u7b54\u3059\u308b\u53c2\u52a0\u30d4\u30a2\u4e00\u89a7\u306e\u4e0a\u9650 [0: \u7121\u5236\u9650] ConfigView.label.serverport=TCP/UDP \u30dd\u30fc\u30c8 ConfigView.label.serverport.tooltip=\u30dd\u30fc\u30c8\u306f 6880 \u4ee5\u5916\u306e 1 \u301c 65535 \u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u30dd\u30fc\u30c8 6880 \u306f Vuze \u304c\u5185\u90e8\u3067\u4f7f\u7528\u3057\u307e\u3059 configureWizard.nat.server.tcp_listen_port=TCP \u53d7\u4fe1\u30dd\u30fc\u30c8 ConfigView.section.sharing=\u5171\u6709 ConfigView.section.sharing.usessl=\u5171\u6709\u306b SSL \u3092\u4f7f\u7528\uff08\u30c8\u30e9\u30c3\u30ab\u30fc\u8a2d\u5b9a\u3092\u53c2\u7167\uff09 ConfigView.section.style.dropdiraction=\u30d5\u30a9\u30eb\u30c0\u3092\u30c9\u30e9\u30c3\u30b0\uff06\u30c9\u30ed\u30c3\u30d7\u3057\u305f\u3068\u304d\u306e\u52d5\u4f5c ConfigView.section.style.dropdiraction.opentorrents=Torrent \u3092\u958b\u304f ConfigView.section.style.dropdiraction.sharefolder=\u30d5\u30a9\u30eb\u30c0\u3092\u5171\u6709\u3059\u308b ConfigView.section.style.dropdiraction.sharefoldercontents=\u30d5\u30a9\u30eb\u30c0\u306e\u5185\u5bb9\u3092\u5171\u6709\u3059\u308b # # 2.0.7.x # Categories.all=\u3059\u3079\u3066 Categories.uncategorized=\u672a\u5206\u985e CategoryAddWindow.message=\u30ab\u30c6\u30b4\u30ea\u540d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044 CategoryAddWindow.title=\u65b0\u898f\u30ab\u30c6\u30b4\u30ea\u3092\u8ffd\u52a0 ConfigView.label.autoSeedingIgnoreInfo=\u7121\u8996\u3055\u308c\u305f Torrent \u306f\u30b7\u30fc\u30c9\u30ad\u30e5\u30fc\u306e\u6700\u5f8c\u3078\u79fb\u52d5\u3055\u308c\u3001\u81ea\u52d5\u7684\u306b\u958b\u59cb\u3055\u308c\u308b\u3053\u3068\u306f\u3042\u308a\u307e\u305b\u3093\u3002\n\u7121\u8996\u30eb\u30fc\u30eb\u306f\u6700\u512a\u5148\u306e Torrent \u306b\u306f\u9069\u7528\u3055\u308c\u307e\u305b\u3093\u3002\n\u958b\u59cb\u3055\u305b\u308b\u306b\u306f 0 \u3092\u6307\u5b9a\u3057\u3066\u30eb\u30fc\u30eb\u3092\u7121\u52b9\u306b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 ConfigView.label.directory=\u30d5\u30a9\u30eb\u30c0\uff1a ConfigView.label.disconnetseed.tooltip=\u30b7\u30fc\u30c9\u4e2d\u3001\u30b7\u30fc\u30c9\u4e2d\u306e\u307b\u304b\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3068\u306e\u63a5\u7d9a\u3092\u5207\u65ad\u3057\u307e\u3059\u3002\n\u30b7\u30fc\u30c0\u30fc\u540c\u58eb\u306e\u63a5\u7d9a\u306f\u5fc5\u8981\u3042\u308a\u307e\u305b\u3093 ConfigView.label.ignoreCase=\u5927\u6587\u5b57\uff0f\u5c0f\u6587\u5b57\u3092\u533a\u5225\u3057\u306a\u3044 ConfigView.label.ignoreSeeds=\u591a\u304f\u306e\u30b7\u30fc\u30c0\u30fc\u304c\u3044\u308b Torrent \u3092\u7121\u8996\uff1a ConfigView.label.importdirectory=\u76e3\u8996\u30d5\u30a9\u30eb\u30c0\uff1a ConfigView.label.minPeersToBoostNoSeeds.tooltip=\u30b7\u30fc\u30c0\u30fc\u304c\u304a\u3089\u305a\u30d4\u30a2\u304c\u6307\u5b9a\u3057\u305f\u6570\u3088\u308a\u5c11\u306a\u3044 Torrent \u306f\n\u30ad\u30e5\u30fc\u306e\u6700\u5f8c\u3078\u79fb\u52d5\u3057\u307e\u3059 ConfigView.label.minPeersToBoostNoSeeds=\u30b7\u30fc\u30c0\u30fc\u304c\u304a\u3089\u305a\u30d4\u30a2\u304c\u6307\u5b9a\u3057\u305f\u6570\u3088\u308a\u5c11\u306a\u3044 Torrent \u306f\u30e9\u30f3\u30af\u3092\u4e0b\u3052\u308b\uff1a ConfigView.label.minSeedingTime.tooltip=\u30b7\u30fc\u30c9\u30e9\u30f3\u30ad\u30f3\u30b0\u304c\u77ed\u6642\u9593\u306e\u3046\u3061\u306b\u5909\u52d5\u3059\u308b\u3068\u3001\u81ea\u52d5\u7684\u306b\u958b\u59cb\u3055\u308c\u305f\u5f8c\u306b\u305f\u3060\u3061\u306b\u505c\u6b62\u3057\u3066\u30ad\u30e5\u30fc\u306b\u5165\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002\n\u3053\u3053\u3067\u6307\u5b9a\u3057\u305f\u6642\u9593\u3060\u3051\u5f37\u5236\u7684\u306b\u30b7\u30fc\u30c9\u3092\u7d9a\u3051\u308b\u3053\u3068\u3067\u3053\u306e\u554f\u984c\u3092\u7de9\u548c\u3057\u307e\u3059\u3002\n\u3082\u3057\u5fc5\u8981\u306a\u3089\u3070\u624b\u52d5\u3067\u505c\u6b62\u3059\u308b\u3053\u3068\u3082\u3067\u304d\u307e\u3059\u3002 ConfigView.label.minSeedingTime=\u6700\u5c0f\u30b7\u30fc\u30c9\u6642\u9593 [sec] ConfigView.label.minSpeedForActiveDL.tooltip=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u958b\u59cb\u5f8c 30 \u79d2\u304c\u7d4c\u904e\u3057\u305f Torrent \u306e\u307f\u3092\u30ab\u30a6\u30f3\u30c8\u3057\u307e\u3059 ConfigView.label.minSpeedForActiveDL=\u6307\u5b9a\u3057\u305f\u901f\u5ea6\u306b\u6e80\u305f\u306a\u3044 Torrent \u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u53ef\u80fd\u3068\u307f\u306a\u3055\u306a\u3044 ConfigView.label.peers=\u30d4\u30a2 ConfigView.label.queue.debuglog=\u30c7\u30d0\u30c3\u30b0\u60c5\u5831\u3092\u30ed\u30b0\u306b\u8a18\u9332 ConfigView.label.queue.debuglog.info=\u30ad\u30e5\u30fc\u306e\u30c7\u30d0\u30c3\u30b0\u60c5\u5831\u3092\u30b3\u30f3\u30bd\u30fc\u30eb\uff0f\u30ed\u30b0\u30d5\u30a1\u30a4\u30eb\u306b\u8ffd\u52a0\u3057\u307e\u3059\u3002\nTorrent \u306e\u72b6\u614b\u3084\u958b\u59cb\u3055\u308c\u306a\u3044\uff0f\u30ad\u30e5\u30fc\u30a4\u30f3\u30b0\u3055\u308c\u306a\u3044\u7406\u7531\u3092\u77e5\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 ConfigView.label.queue.minQueueingShareRatio=\u8ca0\u62c5\u7387\u306b\u9054\u3059\u308b\u307e\u3067 Torrent \u3092\u30ad\u30e5\u30fc\u30a4\u30f3\u30b0\uff0f\u505c\u6b62\u3057\u306a\u3044 ConfigView.label.ratio=\u8ca0\u62c5\u7387 ConfigView.label.removeOnStop=\u81ea\u52d5\u505c\u6b62\u5f8c\u3001\u30ea\u30b9\u30c8\u304b\u3089 Torrent \u3092\u524a\u9664 ConfigView.label.savedirectory=\u4fdd\u5b58\u5148 ConfigView.label.seeding.autoReposition.tooltip=Torrent \u3092\u30b7\u30fc\u30c9\u30e9\u30f3\u30af\u306b\u3088\u3063\u3066\u4e26\u3079\u66ff\u3048\u307e\u3059\u3002\n\u30b7\u30fc\u30c9\u5f85\u3061\u306e\u9806\u756a\u306e\u307f\u3092\u77e5\u308a\u305f\u3044\u3068\u304d\u306b\u4fbf\u5229\u3067\u3059 ConfigView.label.seeding.autoReposition=\u30b7\u30fc\u30c9\u30e9\u30f3\u30af\u306b\u3088\u3063\u3066\u81ea\u52d5\u7684\u306b Torrent \u3092\u4e26\u3079\u66ff\u3048\u308b ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u5c11\u306a\u3044\u30b7\u30fc\u30c0\u30fc\u3068\u591a\u304f\u306e\u30d4\u30a2\u3067\u69cb\u6210\u3055\u308c\u308b Torrent \u306f\u3001\u304a\u305d\u3089\u304f\u30d4\u30a2\u306e\u9593\u3067\u306f\u5b8c\u5168\u306a\u30b3\u30d4\u30fc\u3092\u4fdd\u6301\u3057\u3066\u3044\u307e\u305b\u3093\u3002\n\u3057\u305f\u304c\u3063\u3066\u3001\u5b8c\u5168\u306a\u30b3\u30d4\u30fc\u304c\u3042\u308b\u3088\u3046\u306b\u507d\u3063\u305f\u308a\u3001\u30e9\u30f3\u30ad\u30f3\u30b0\u3092\u64cd\u4f5c\u3057\u3066\u306f\u3044\u3051\u307e\u305b\u3093 ConfigView.label.seeding.fakeFullCopySeedStart=\u305f\u3060\u3057\u6307\u5b9a\u3057\u305f\u6570\u4ee5\u4e0a\u306e\u30b7\u30fc\u30c0\u30fc\u304c\u3044\u308b\u5834\u5408\u306b\u9650\u308b ConfigView.label.seeding.ignore=\u7121\u8996\u30eb\u30fc\u30eb ConfigView.label.seeding.ignore0Peers=\u30d4\u30a2\u304c\u3044\u306a\u3044 Torrent \u3092\u7121\u8996 ConfigView.label.seeding.ignoreRatioPeers=\u6307\u5b9a\u3057\u305f\u6570\u306e\u30d4\u30a2\u3054\u3068\u306b\u6700\u4f4e 1 \u4eba\u30b7\u30fc\u30c0\u30fc\u304c\u3044\u308b\u5834\u5408\u306b\u7121\u8996 ConfigView.label.seeding.ignoreShareRatio=\u8ca0\u62c5\u7387\u304c\u6b21\u3088\u308a\u9ad8\u3044 Torrent \u3092\u7121\u8996 ConfigView.label.seeding.ignore.header.evenFirstPriority=\u512a\u5148\u5ea6\u304c\u6700\u3082\u9ad8\u3044\u30eb\u30fc\u30eb\u3092\u9069\u7528\u3057\u305f\u5834\u5408\u306b\u7121\u8996 ConfigView.label.seeding.ignore.header.rule=\u30eb\u30fc\u30eb ConfigView.label.seeding.ignore.header.value=\u5024 ConfigView.label.seeding.firstPriority.info=\u6700\u512a\u5148\u306e Torrent \u306f\u5e38\u306b\u30ad\u30e5\u30fc\u306e\u5148\u982d\u306b\u3044\u307e\u3059\u3002\u6700\u512a\u5148\u304c\u9069\u7528\u3055\u308c\u305f Torrent \u306f\u81ea\u52d5\u7684\u306b\u505c\u6b62\u3057\u305f\u308a\u9806\u756a\u5f85\u3061\u306b\u306a\u3063\u305f\u308a\u3057\u307e\u305b\u3093\u3002\u5fc5\u8981\u306a\u3089\u3070\u6700\u512a\u5148\u306e Torrent \u306f\u8a2d\u5b9a\u306b\u304b\u304b\u308f\u3089\u305a\u540c\u6642\u306b\u30b7\u30fc\u30c9\u3055\u308c\u307e\u3059\u3002 ConfigView.label.seeding.firstPriority.FP=\u6700\u512a\u5148 ConfigView.label.seeding.firstPriority=\u6b21\u306e ConfigView.label.seeding.firstPriority.following=\u306e\u6761\u4ef6\u306b\u3042\u3066\u306f\u307e\u308b Torrent \u3092\u6700\u512a\u5148\u306b\u3059\u308b\uff1a ConfigView.label.seeding.firstPriority.shareRatio=\u8ca0\u62c5\u7387\u304c\u6b21\u3088\u308a\u3082\u5c0f\u3055\u3044\u5834\u5408 ConfigView.label.seeding.firstPriority.seedingMinutes=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d\u304b\u3089\u30b7\u30fc\u30c9\u4e2d\u306b\u306a\u3063\u3066\u304b\u3089\u306e\u7d4c\u904e\u6642\u9593 ConfigView.label.seeding.firstPriority.DLMinutes=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u958b\u59cb\u3057\u3066\u304b\u3089\u306e\u7d4c\u904e\u6642\u9593 ConfigView.label.seeding.numPeersAsFullCopy.tooltip=\u30d4\u30a2\u304c\u6307\u5b9a\u3057\u305f\u6570\u3044\u308b\u3054\u3068\u306b\uff11\u3064\u306e\u5b8c\u5168\u306a\u30b3\u30d4\u30fc\u304c\u3042\u308b\u3068\u507d\u308a\u307e\u3059\u3002\u30d4\u30a2\u304c\u305f\u304f\u3055\u3093\u3044\u308b Torrent \u306e\u30e9\u30f3\u30af\u3092\u4e0b\u3052\u308b\u306e\u306b\u6709\u52b9\u3067\u3059\nTorrent \u306b\u30d4\u30a2\u304c\u591a\u3044\u3068\u901a\u4fe1\u91cf\u3082\u5927\u304d\u304f\u306a\u308a\u307e\u3059\u3002\n\u3053\u308c\u306f '\u30b7\u30fc\u30c0\u30fc No.' \u306b\u306f\u5f71\u97ff\u3057\u307e\u305b\u3093\u3002 ConfigView.label.seeding.numPeersAsFullCopy=\u6307\u5b9a\u3057\u305f\u6570\u306e\u30d4\u30a2\u6bce\u306b\uff11\u3064\u306e\u5b8c\u5168\u306a\u30b3\u30d4\u30fc\u304c\u3042\u308b\u3075\u308a\u3092\u3059\u308b (0\uff1a\u7121\u52b9) ConfigView.label.seeding.preferLargerSwarms.tooltip=\u4e3b\u306b\u300c\u884c\u304d\u8a70\u307e\u3063\u305f\u300d\u30d4\u30a2\u3068\u30b7\u30fc\u30c9\u3057\u3066\u3044\u308b\u5834\u5408\u3001\u30d4\u30a2\u304c\u591a\u3044 Swarm \u3092\u512a\u5148\u3059\u308b\u306e\u304c\u6709\u52b9\u3067\u3059\u3002\n\u4e3b\u306b\u5165\u624b\u6027\u304c\u9ad8\u3044 Swarm \u3067\u30b7\u30fc\u30c9\u3057\u3066\u3044\u308b\u5834\u5408\u306f\u3001\u30d4\u30a2\u306e\u5c11\u306a\u3044 Swarm \u3092\u512a\u5148\u3059\u308b\u306e\u304c\u6709\u52b9\u3067\u3059 ConfigView.label.seeding.preferLargerSwarms=Torrent \u306e\u30e9\u30f3\u30af\u304c\u540c\u3058\u5834\u5408\u306b\u30d4\u30a2\u306e\u591a\u3044 Swarm \u3092\u512a\u5148 ConfigView.label.seeding.rankType.none.tooltip=No.' \u306e\u9806\u306b\u4e26\u3079\u307e\u3059 ConfigView.label.seeding.rankType.none=\u7121\u3057 ConfigView.label.seeding.rankType.peerSeed.options=\u30b7\u30fc\u30c0\u30fc\uff1a\u30d4\u30a2\u6bd4 ConfigView.label.seeding.rankType.peerSeed.tooltip=\u30d4\u30a2\u306e\u6bd4\u7387\u304c\u9ad8\u3051\u308c\u3070\u9ad8\u3044\u307b\u3069\u4e0a\u4f4d\u306b\u30e9\u30f3\u30ad\u30f3\u30b0\u3055\u308c\u307e\u3059 ConfigView.label.seeding.rankType.peerSeed=\u30d4\u30a2\uff1a\u30b7\u30fc\u30c0\u30fc\u6bd4 ConfigView.label.seeding.rankType.seed.fallback=\u6307\u5b9a\u3057\u305f\u6570\u4ee5\u4e0a\u306e\u30b7\u30fc\u30c0\u30fc\u304c\u3044\u308b\u3082\u306e\u306f\u30d4\u30a2\uff1a\u30b7\u30fc\u30c0\u30fc\u6bd4\u3067\u4e26\u3079\u308b\n(0\uff1a\u30b7\u30fc\u30c0\u30fc\u6570\u306e\u307f\u3067\u4e26\u3079\u308b) ConfigView.label.seeding.rankType.seed.options=\u30b7\u30fc\u30c0\u30fc\u6570\u306e\u307f\u306e\u30aa\u30d7\u30b7\u30e7\u30f3 ConfigView.label.seeding.rankType.seed.tooltip=\u30b7\u30fc\u30c0\u30fc\u304c\u5c11\u306a\u3051\u308c\u3070\u5c11\u306a\u3044\u307b\u3069\u4e0a\u4f4d\u306b\u30e9\u30f3\u30ad\u30f3\u30b0\u3055\u308c\u307e\u3059 ConfigView.label.seeding.rankType.seed=\u30b7\u30fc\u30c0\u30fc\u6570\u306e\u307f ConfigView.label.seeding.rankType.timedRotation.tooltip=\u5b8c\u4e86\u3057\u305f\u3059\u3079\u3066\u306e Torrent \u3092\u30b7\u30fc\u30c9\u30e2\u30fc\u30c9\u306b\u79fb\u884c\u3057\u307e\u3059\u3002\n\u30b7\u30fc\u30c9\u3059\u308b\u6642\u9593\u306f\u300c\u6700\u5c0f\u9650\u30b7\u30fc\u30c9\u3059\u308b\u6642\u9593\u300d\u3067\u8a2d\u5b9a\u3057\u307e\u3059 ConfigView.label.seeding.rankType.timedRotation=\u6642\u9593\u3067\u30ed\u30fc\u30c6\u30fc\u30b7\u30e7\u30f3\u3059\u308b ConfigView.label.seeding.rankType.tooltip=1 \u4f4d\u306b\u30e9\u30f3\u30ad\u30f3\u30b0\u3055\u308c\u305f Torrent \u306f\u81ea\u52d5\u7684\u306b\u958b\u59cb\u3055\u308c\u307e\u3059\u3002\n\u3042\u308b Torrent \u304c\u9ad8\u3044\u30e9\u30f3\u30af\u3092\u7372\u5f97\u3057\u305f\u5834\u5408\u3001\u4f4e\u3044\u30e9\u30f3\u30af\u306e Torrent \u306f\u9806\u756a\u5f85\u3061\u3078\u3068\u4e0b\u304c\u308a\u307e\u3059\u3002\n\n\u81ea\u52d5\u7684\u306b\u958b\u59cb\u3055\u308c\u308b\u306e\u306f\u9806\u756a\u5f85\u3061\u306e Torrent \u3060\u3051\u3067\u3059\u3002\n\u505c\u6b62\u3055\u308c\u305f Torrent \u306f\u81ea\u52d5\u7684\u306b\u958b\u59cb\u3059\u308b\u3053\u3068\u306f\u3042\u308a\u307e\u305b\u3093 ConfigView.label.seeding.rankType=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5b8c\u4e86\u3057\u305f Torrent \u3092\u81ea\u52d5\u958b\u59cb\u3059\u308b\u6761\u4ef6\uff1a ConfigView.label.stopAfterMinutes=\u30b7\u30fc\u30c9\u306b\u5207\u308a\u66ff\u308f\u3063\u305f\u5f8c\u3001\u4e00\u5b9a\u6642\u9593\u304c\u7d4c\u904e\u3057\u305f\u3089\u505c\u6b62 ConfigView.label.switchpriority.tooltip=\u512a\u5148\u5ea6\u3092\u4f4e\u304f\u3059\u308b\u3068\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u5e2f\u57df\u304c\u5c11\u306a\u304f\u306a\u308a\u307e\u3059\u3002 ConfigView.pluginlist.info=\u6b21\u306e\u30d7\u30e9\u30b0\u30a4\u30f3\u304c\u7d44\u307f\u8fbc\u307e\u308c\u3066\u3044\u307e\u3059\u3002\uff08\u8a2d\u5b9a\u753b\u9762\u3092\u6301\u305f\u306a\u3044\u30d7\u30e9\u30b0\u30a4\u30f3\u3082\u3042\u308a\u307e\u3059\uff09 ConfigView.pluginlist.noplugins=\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 ConfigView.section.pluginslist=\u4e00\u89a7 ConfigView.section.queue.seeding=\u30b7\u30fc\u30c9 ConfigView.section.queue.seeding.autoStarting=\u81ea\u52d5\u958b\u59cb ConfigView.section.queue.seeding.ignore=\u7121\u8996\u30eb\u30fc\u30eb ConfigView.section.queue.seeding.firstPriority=\u6700\u512a\u5148 ConfigView.section.queue.main=\u30e1\u30a4\u30f3 ConfigView.section.queue=\u30ad\u30e5\u30fc ConfigView.section.torrents=Torrent ConfigView.text.all=\u3059\u3079\u3066 ConfigView.text.hours=\u6642\u9593 ConfigView.text.ignoreRule=\u30eb\u30fc\u30eb\u3092\u7121\u8996 ConfigView.text.ignore=\u7121\u8996 ConfigView.text.minutes=\u5206 ConfigView.text.neverIgnore=\u7121\u8996\u3057\u306a\u3044 ConfigView.text.any=\u3044\u305a\u308c\u304b DownloadManager.error.datamissing=\u30c7\u30fc\u30bf\u7121\u3057 MainWindow.menu.file.open.torrentforseeding=Torrent \u30d5\u30a1\u30a4\u30eb\uff08\u30b7\u30fc\u30c9\u7528\uff09... MainWindow.menu.language.refresh=\u518d\u8aad\u307f\u8fbc\u307f ManagerItem.forced=\u5f37\u5236 ManagerItem.queued=\u9806\u756a\u5f85\u3061 MySeedersView.header=\u30b7\u30fc\u30c9\u4e2d\u306e Torrent TableColumn.header.availability.info=\u30b3\u30d4\u30fc\u304c\u4f55\u500b\u5206\u5b58\u5728\u3059\u308b\u304b TableColumn.header.availability=\u5165\u624b\u53ef\u80fd\u6027 TableColumn.header.category=\u30ab\u30c6\u30b4\u30ea MyTorrentsView.header=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d\u306e Torrent TableColumn.header.maxuploads=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6570 MyTorrentsView.menu.category.delete=\u30ab\u30c6\u30b4\u30ea\u3092\u524a\u9664 MyTorrentsView.menu.forceStart=\u5f37\u5236\u7684\u306b\u958b\u59cb MyTorrentsView.menu.queue=\u30ad\u30e5\u30fc\u306b\u8ffd\u52a0 MyTorrentsView.menu.setCategory.add=\u30ab\u30c6\u30b4\u30ea\u3092\u8ffd\u52a0... MyTorrentsView.menu.setCategory=\u30ab\u30c6\u30b4\u30ea\u306e\u8a2d\u5b9a TableColumn.header.savepath=\u4fdd\u5b58\u5148 TableColumn.header.SeedingRank=\u30b7\u30fc\u30c9\u30e9\u30f3\u30af TableColumn.header.totalspeed.info=\u63a5\u7d9a\u3057\u3066\u3044\u308b\u3059\u3079\u3066\u306e\u30d4\u30a2\u306e\u5408\u8a08\u901f\u5ea6 TableColumn.header.totalspeed=\u5408\u8a08\u901f\u5ea6 splash.initializePlugins=\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u521d\u671f\u5316\u4e2d StartStopRules.SPratioMet=S:P \u6bd4 OK StartStopRules.FP0Peers=FP / 0 \u30d4\u30a2 StartStopRules.0Peers=0 \u30d4\u30a2 StartStopRules.numSeedsMet=\u30b7\u30fc\u30c0\u30fc OK StartStopRules.ratioMet=\u30d4\u30a2\uff1a\u30b7\u30fc\u30c0\u30fc\u6bd4 OK StartStopRules.shareRatioMet=\u8ca0\u62c5\u7387 OK StartStopRules.waiting=\u5f85\u6a5f\u4e2d StartStopRules.firstPriority=\u6700\u512a\u5148 ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\u30d5\u30a9\u30eb\u30c0\u306e\u5185\u5bb9\u3092\u5171\u6709\u3059\u308b\uff08\u4e0b\u5c64\u30d5\u30a9\u30eb\u30c0\u3082\u542b\u3080\uff09 DownloadManager.error.unabletostartserver=\u30b5\u30fc\u30d0\u3092\u958b\u59cb\u3067\u304d\u307e\u305b\u3093 - \u30dd\u30fc\u30c8\u307e\u305f\u306f\u30b5\u30fc\u30d0\u3068\u3057\u3066\u7a3c\u50cd\u3059\u308b\u305f\u3081\u306b\u5fc5\u8981\u306a\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u306e\u8a2d\u5b9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044 GeneralView.label.creationdate=\u4f5c\u6210\u65e5\u6642: ConfigView.section.tracker.announcescrapepercentage=\u30b9\u30af\u30ec\u30a4\u30d7\u9593\u9694\uff08\u4f8b\uff1a200\uff09 ManagerItem.stopping=\u505c\u6b62\u4e2d ConfigView.section.tracker.announcecacheperiod=\u30a2\u30ca\u30a6\u30f3\u30b9\u30ad\u30e3\u30c3\u30b7\u30e5 (ms) ConfigView.section.tracker.scrapecacheperiod=\u30b9\u30af\u30ec\u30a4\u30d7\u30ad\u30e3\u30c3\u30b7\u30e5 (ms) ConfigView.section.tracker.scrapeandcache=\u30b9\u30af\u30ec\u30a4\u30d7\u3068\u30ad\u30e3\u30c3\u30b7\u30e5 ConfigView.section.tracker.announcecacheminpeers=\u30a2\u30ca\u30a6\u30f3\u30b9\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u6709\u52b9\u306b\u3059\u308b\u30d4\u30a2\u6570 MyTrackerView.scrapes=\u30b9\u30af\u30ec\u30a4\u30d7 fileDownloadWindow.retry=\u30ea\u30c8\u30e9\u30a4 MyTrackerView.bytesin=\u53d7\u4fe1 MyTrackerView.bytesinave=\u53d7\u4fe1\u5e73\u5747 MyTrackerView.bytesout=\u9001\u4fe1 MyTrackerView.bytesoutave=\u9001\u4fe1\u5e73\u5747 ConfigView.section.file.max_open_files=\u30aa\u30fc\u30d7\u30f3\u3059\u308b\u30d5\u30a1\u30a4\u30eb\u306e\u4e0a\u9650 [0: \u7121\u5236\u9650] ConfigView.section.file.max_open_files.tooltip=\u975e\u5e38\u306b\u591a\u304f\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u305f\u308a\u3001\u30d5\u30a1\u30a4\u30eb\u30cf\u30f3\u30c9\u30eb\u304c OS \u306e\u4e0a\u9650\u306b\u9054\u3059\u308b\u5834\u5408\u306b\u6709\u52b9\u3067\u3059 ConfigView.section.proxy=\u30d7\u30ed\u30ad\u30b7 ConfigView.section.proxy.enable_proxy=\u30c8\u30e9\u30c3\u30ab\u30fc\u3068\u306e\u901a\u4fe1\u306b\u30d7\u30ed\u30ad\u30b7\u3092\u4f7f\u7528 ConfigView.section.proxy.host=\u30db\u30b9\u30c8\u540d ConfigView.section.proxy.port=\u30dd\u30fc\u30c8 ConfigView.section.proxy.username=\u30e6\u30fc\u30b6\u540d ConfigView.section.proxy.password=\u30d1\u30b9\u30ef\u30fc\u30c9 ConfigView.section.proxy.enable_socks=Socks \u30d7\u30ed\u30ad\u30b7\u3092\u4f7f\u7528 wizard.createtorrent.extrahashes=\u307b\u304b\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u7528\u306b\u30cf\u30c3\u30b7\u30e5\u3092\u8ffd\u52a0 (\u4f8b Gnutella2, eDonkey2000) GeneralView.label.connected=\u63a5\u7d9a\u4e2d GeneralView.label.in_swarm=\u306e\u3046\u3061 ManagerItem.initializing=\u521d\u671f\u5316\u4e2d AlertMessageBox.error=\u30a8\u30e9\u30fc AlertMessageBox.warning=\u8b66\u544a AlertMessageBox.comment=\u60c5\u5831 AlertMessageBox.information=\u60c5\u5831 AlertMessageBox.unread=\u672a\u8aad\u306e\u8b66\u544a\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u3042\u308a\u307e\u3059\u3002\u8868\u793a\u3059\u308b\u306b\u306f\u3053\u3053\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002 SharedPortServer.alert.selectorfailed=\u53d7\u4fe1\u30c7\u30fc\u30bf\u306b\u5bfe\u3059\u308b\u30ea\u30b9\u30ca\u30fc\u3068\u306e\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\n\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u306e\u8a2d\u5b9a\u3092\u78ba\u8a8d\u3057\u3001java(w).exe \u3092 'server' \u3068\u3057\u3066\u4f7f\u3046\u3088\u3046\u8a31\u53ef\u3057\u3066\u304f\u3060\u3055\u3044\u3002 Tracker.alert.listenfail=\u30dd\u30fc\u30c8%1\u306e\u30aa\u30fc\u30d7\u30f3\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\n\u307b\u304b\u306e\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u304c\u3059\u3067\u306b\u30dd\u30fc\u30c8\u3092\u4f7f\u7528\u3057\u3066\u3044\u306a\u3044\u304b\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\u307e\u305fVuze u304c\u591a\u91cd\u8d77\u52d5\u3057\u3066\u3044\u306a\u3044\u304b\u3082\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 DiskManager.alert.movefileexists=\u30a8\u30e9\u30fc\uff1a\u30d5\u30a1\u30a4\u30eb\u3092\u79fb\u52d5\u3067\u304d\u307e\u305b\u3093\u3002\n%1 \u306f\u79fb\u52d5\u5148\u306e\u30d5\u30a9\u30eb\u30c0\u306b\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002 DiskManager.alert.movefilefails=\u30a8\u30e9\u30fc\uff1a\u30d5\u30a1\u30a4\u30eb\u3092\u79fb\u52d5\u3067\u304d\u307e\u305b\u3093\u3002\n%1 \u306e\u79fb\u52d5\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 %2 DiskManager.alert.movefilerecoveryfails=\u30a8\u30e9\u30fc\uff1a\u30d5\u30a1\u30a4\u30eb\u79fb\u52d5\u5f8c\u306e\u51e6\u7406\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\n%1 \u3092\u5fa9\u65e7\u3057\u307e\u3057\u305f\u3002 %2 ConfigView.section.tracker.logenable=tracker.log' \u306b\u5b9a\u671f\u7684\u306b\u7d71\u8a08\u60c5\u5831\u3092\u8a18\u9332\u3059\u308b SpeedView.stats.title=\u7d71\u8a08 SpeedView.stats.total=\u5408\u8a08 SpeedView.stats.session=\u4eca\u56de SpeedView.stats.session.tooltip=\u5408\u8a08 SpeedView.stats.downloaded=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u6e08 SpeedView.stats.uploaded=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6e08 SpeedView.stats.ratio=\u8ca0\u62c5\u7387 SpeedView.stats.uptime=\u7d4c\u904e\u6642\u9593 SpeedView.stats.now=\u73fe\u5728 SpeedView.stats.now.tooltip=\u5408\u8a08 AutoMigration.useralert=Vuze \u30e6\u30fc\u30b6\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u81ea\u52d5\u79fb\u884c\u7d50\u679c\uff1a\n\n%1\n\u5931\u6557\u3057\u305f\u500b\u6240\u306f\u624b\u52d5\u3067\u79fb\u884c\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\n\u79fb\u884c\u3057\u305f\u5f8c\u306b\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u4e2d\u306e\u30c7\u30fc\u30bf\u4fdd\u5b58\u5148\u3092\u66f4\u65b0\u3059\u308b\u306e\u3092\u5fd8\u308c\u306a\u3044\u3088\u3046\u306b\u3057\u3066\u304f\u3060\u3055\u3044\uff01 # # > 2.0.8.0 # OpenTorrentWindow.title=Torrent \u3092\u958b\u304f OpenTorrentWindow.message=\u5b9f\u9a13\u4e2d OpenTorrentWindow.addFiles=\u30d5\u30a1\u30a4\u30eb\u3092\u8ffd\u52a0 OpenTorrentWindow.dataLocation=\u30c7\u30fc\u30bf\u306e\u4fdd\u5b58\u5148\uff1a OpenTorrentWindow.startMode=\u8ffd\u52a0\u30e2\u30fc\u30c9 OpenTorrentWindow.startMode.queued=\u9806\u756a\u5f85\u3061 OpenTorrentWindow.startMode.stopped=\u505c\u6b62\u6e08 OpenTorrentWindow.startMode.forceStarted=\u5f37\u5236\u958b\u59cb\u6e08 OpenTorrentWindow.addPosition=\u9806\u756a OpenTorrentWindow.addPosition.first=\u6700\u521d OpenTorrentWindow.addPosition.last=\u6700\u5f8c TableColumn.header.remaining.info=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u306e\u6b8b\u308a\u30b5\u30a4\u30ba TableColumn.header.remaining=\u6b8b\u308a ConfigView.section.tracker.enablecompact=\u7c21\u6613\u30a2\u30ca\u30a6\u30f3\u30b9\u30d7\u30ed\u30c8\u30b3\u30eb\u3092\u4f7f\u7528 ConfigView.section.tracker.enablekey=\u3088\u308a\u9ad8\u3044\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u306e\u305f\u3081\u3001\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u8a8d\u8a3c\u3092\u4f7f\u7528 ConfigView.section.file.perf=\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9 ConfigView.section.file.perf.explain=\u8b66\u544a - \u4e0d\u9069\u5207\u306a\u5909\u66f4\u306f\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6\u306b\u60aa\u5f71\u97ff\u3092\u4e0e\u3048\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002\u8a2d\u5b9a\u3092\u5909\u66f4\u3057\u305f\u5834\u5408\u306f Vuze \u3092\u518d\u8d77\u52d5\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\u3082\u3057\u30e1\u30e2\u30ea\u4e0d\u8db3\u306e\u30a8\u30e9\u30fc\u304c\u51fa\u305f\u3089\u30011 Torrent \u3042\u305f\u308a\u306e\u63a5\u7d9a\u6570\u3092\u5c11\u306a\u304f\u3057\u3066\u304f\u3060\u3055\u3044\u3002\uff08\u8ee2\u9001\u8a2d\u5b9a\u3092\u53c2\u7167\uff09 ConfigView.section.file.max_open_files.explain=\u540c\u6642\u306b\u958b\u304f\u30d5\u30a1\u30a4\u30eb\u306e\u6570\u3092\u5236\u9650\u3057\u307e\u3059\u3002\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304d\u3059\u304e\u308b\u3068\u3001\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u306e\u5236\u7d04\u306b\u3088\u308a\u3001\u30b7\u30b9\u30c6\u30e0\u306e\u52d5\u4f5c\u306b\u652f\u969c\u3092\u304d\u305f\u3059\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002 popup.error.hide=\u96a0\u3059 popup.error.details=\u8a73\u7d30 ConfigView.section.style.colorOverrides=\u500b\u5225\u306b\u6307\u5b9a ConfigView.section.style.colorOverride.progressBar=\u30d7\u30ed\u30b0\u30ec\u30b9\u30d0\u30fc ConfigView.section.style.colorOverride.error=\u30a8\u30e9\u30fc MainWindow.status.tooOld=\u306f\u53e4\u3044\u305f\u3081\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3057\u3066\u304f\u3060\u3055\u3044\u3002 ConfigView.section.style.colorOverride.warning=\u8b66\u544a ConfigView.section.style.colorOverride.altRow=\u30c6\u30fc\u30d6\u30eb\u306e\u884c ConfigView.section.file.save.peers.enable=\u30d4\u30a2\u3068\u306e\u63a5\u7d9a\u3092\u4fdd\u5b58\u3057\u3066\u518d\u63a5\u7d9a\u3092\u9ad8\u901f\u5316 ConfigView.section.file.save.peers.max=\u4fdd\u5b58\u3059\u308b\u30d4\u30a2\u4e0a\u9650 [0: \u7121\u5236\u9650] ConfigView.section.file.save.peers.pertorrent=/ Torrent ConfigView.label.max_peers_per_torrent=1 Torrent \u3042\u305f\u308a\u306e\u6700\u5927\u63a5\u7d9a\u6570 [0: \u7121\u5236\u9650] ConfigView.label.max_peers_total=\u7dcf\u63a5\u7d9a\u6570 [0: \u7121\u5236\u9650] ConfigView.section.style.colorOverrides.reset=\u5143\u306b\u623b\u3059 ConfigView.section.language.info=\u6709\u52b9\u306b\u3059\u308b\u3068\u3001\u6bce\u8d77\u52d5\u6642\u306b\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u3057\u307e\u3059\u3002 ConfigView.section.language.enableUpdate=Web \u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u4f7f\u7528 ConfigView.section.language.UpdateURL=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8 URL ConfigView.section.language.UpdateNow=\u4eca\u3059\u3050\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8 Button.revert=\u3084\u308a\u76f4\u3057 MyTorrentsView.menu.changeDirectory=\u30c7\u30fc\u30bf\u30d5\u30a9\u30eb\u30c0\u3092\u5909\u66f4 GenericText.column=\u9805\u76ee MyTorrentsView.menu.thisColumn.remove=\u9805\u76ee\u3092\u524a\u9664 MyTorrentsView.menu.thisColumn.toClipboard=\u30b3\u30d4\u30fc MyTorrentsView.menu.thisColumn.autoTooltip=\u30c4\u30fc\u30eb\u30c1\u30c3\u30d7\u3092\u3044\u3064\u3082\u8868\u793a MyTorrentsView.menu.tracker=\u30c8\u30e9\u30c3\u30ab\u30fc TableColumn.header.secondsseeding=\u30b7\u30fc\u30c9\u6642\u9593 TableColumn.header.secondsseeding.info=\u3053\u308c\u307e\u3067\u306e\u30b7\u30fc\u30c9\u6642\u9593\u306e\u5408\u8a08 TableColumn.header.secondsdownloading=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u6642\u9593 TableColumn.header.secondsdownloading.info=\u3053\u308c\u307e\u3067\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u6642\u9593\u306e\u5408\u8a08 ConfigView.section.tracker.udpversion=UDP \u306e\u30d0\u30fc\u30b8\u30e7\u30f3 (1 \u304b 2) window.updateswt.title=\u53e4\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u306e SWT \u3092\u304a\u4f7f\u3044\u3067\u3059\u3002 window.updateswt.text=\u304a\u4f7f\u3044\u306e SWT \u306f\u53e4\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u3067\u3059\u3002\nSWT \u306f Vuze \u304c\u4f7f\u7528\u3059\u308b\u30b0\u30e9\u30d5\u30a3\u30c3\u30af\u30b9\u30e9\u30a4\u30d6\u30e9\u30ea\u3067\u3001Vuze \u3092\u52d5\u4f5c\u3055\u305b\u308b\u306b\u306f\u3088\u308a\u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u306e SWT \u304c\u5fc5\u8981\u3067\u3059\u3002OK \u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u3001SWT \u3092\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3057\u3066\u304f\u3060\u3055\u3044\u3002 window.updateswt.status=\u9032\u884c\u72b6\u6cc1 window.updateswt.failed=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002OK \u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u518d\u8d77\u52d5\u3057\u3066\u304f\u3060\u3055\u3044\u3002 window.updateswt.status.downloading.updater=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d window.updateswt.status.finding=\u6700\u65b0\u30d0\u30fc\u30b8\u30e7\u30f3\u306e SWT \u3092\u691c\u7d22\u4e2d window.updateswt.status.downloading=\u6700\u65b0\u30d0\u30fc\u30b8\u30e7\u30f3\u306e SWT \u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d window.updateswt.status.done=\u518d\u8d77\u52d5\u4e2d window.updateswt.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb swt.updater.downloader.downloading=SWT \u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d\uff1a swt.updater.urlsgetter.downloading=\u30df\u30e9\u30fc\u30b5\u30a4\u30c8\u306e\u4e00\u89a7\u3092\u53d6\u5f97\u4e2d\uff1a swt.updater.urlsgetter.platform=SWT \u306e\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\uff1a window.updateswt.ignore=\u7121\u8996 ConfigView.section.style.useFancyTabs=\u30d5\u30a1\u30f3\u30b7\u30fc\u30bf\u30d6\u3092\u4f7f\u7528 splash.initializeGM=Global Torrent Manager \u3092\u521d\u671f\u5316\u4e2d splash.loadingTorrents=Torrent \u3092\u30ed\u30fc\u30c9\u4e2d MyTorrentsView.menu.thisColumn.sort=\u4e26\u3079\u66ff\u3048 Scrape.status.ok=OK Scrape.status.error=\u30a8\u30e9\u30fc\uff1a Scrape.status.error.badURL=\u30a2\u30ca\u30a6\u30f3\u30b9\u30d7\u30ed\u30c8\u30b3\u30eb\u306f\u6b21\u306e\u30b9\u30af\u30ec\u30a4\u30d7\u4ed5\u69d8\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u307e\u305b\u3093\u3002 Scrape.status.error.nohash=\u5fdc\u7b54\u306b\u30cf\u30c3\u30b7\u30e5\u304c\u3042\u308a\u307e\u305b\u3093\u3002 Scrape.status.error.invalid=\u7121\u52b9\u306a\u5fdc\u7b54\u3067\u3059\u3002 Scrape.status.nextScrapeAt=\u6b21\u306e\u30b9\u30af\u30ec\u30a4\u30d7\uff1a%1 Scrape.status.scraping=\u30b9\u30af\u30ec\u30a4\u30d7\u4e2d... Scrape.status.initializing=\u30b9\u30af\u30ec\u30a4\u30d7\u4e2d... Scrape.status.scraping.queued=\u30ad\u30e5\u30fc\u3092\u30b9\u30af\u30ec\u30a4\u30d7\u4e2d... ConfigView.label.minSpeedForActiveSeeding=\u6307\u5b9a\u3057\u305f\u901f\u5ea6\u306b\u6e80\u305f\u306a\u3044 Torrent \u3092\u30b7\u30fc\u30c9\u53ef\u80fd\u3068\u307f\u306a\u3055\u306a\u3044 ConfigView.section.stats.exportpeers=\u30d4\u30a2\u306e\u8a73\u7d30\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 MainWindow.menu.view.irc.moved=IRC \u306f\u30d7\u30e9\u30b0\u30a4\u30f3\u306b\u306a\u308a\u307e\u3057\u305f\u3002http://azureus.sourceforge.net/plugin_list.php \u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u306f \u8868\u793a\uff1e\u30d7\u30e9\u30b0\u30a4\u30f3\uff1eIRC \u3092\u958b\u3044\u3066\u304f\u3060\u3055\u3044\u3002 MyTrackerView.webui.contextmenu.copyurl=URL \u3092\u30b3\u30d4\u30fc ConfigView.section.file.torrent.ignorefiles=Torrent \u4f5c\u6210\u6642\u306b\u6b21\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u7121\u8996\n\u4f8b .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=\u7121\u8996\u3059\u308b\u30d5\u30a1\u30a4\u30eb ConfigView.section.style.useUnitsRateBits=\u30c7\u30fc\u30bf\u306e\u5358\u4f4d\u3092\u30d0\u30a4\u30c8\u304b\u3089\u30d3\u30c3\u30c8\u306b\u5909\u66f4\uff08KiB/s \u2192 Kibit/s \u7b49\uff09 ConfigView.section.interface.resetassoc=\u30a8\u30af\u30b9\u30d7\u30ed\u30fc\u30e9\u306e\u95a2\u9023\u4ed8\u3051\u3092\u518d\u8a2d\u5b9a (.torrent) ConfigView.section.interface.resetassocbutton=\u5143\u306b\u623b\u3059 ConfigView.section.interface.checkassoc=\u8d77\u52d5\u6642\u306b\u95a2\u9023\u4ed8\u3051\u3092\u78ba\u8a8d\u3059\u308b dialog.associations.title=\u95a2\u9023\u4ed8\u3051 Button.yes=\u306f\u3044 Button.no=\u3044\u3044\u3048 ConfigView.label.seeding.autoStart0Peers=\u30d4\u30a2\u304c\u3044\u306a\u3044\u5b8c\u6210\u6e08\u307f Torrent \u3092\u3059\u3079\u3066\u81ea\u52d5\u3067\u958b\u59cb ConfigView.label.seeding.autoStart0Peers.tooltip=\u30d4\u30a2\u304c\u3044\u306a\u3044 Torrent \u3082\u30b7\u30fc\u30c9\u3057\u305f\u3044\u3068\u304d\u306f\u30c1\u30a7\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044 dialog.associations.prompt=Vuze \u306f BitTorrent \u30d5\u30a1\u30a4\u30eb\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\n.torrent \u30d5\u30a1\u30a4\u30eb\u3092 Vuze \u306b\u95a2\u9023\u4ed8\u3051\u307e\u3059\u304b\uff1f dialog.associations.askagain=\u8d77\u52d5\u6642\u306b\u78ba\u8a8d ConfigView.section.plugins.update=\u30d7\u30e9\u30b0\u30a4\u30f3\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8 Plugin.pluginupdate.enablecheck=\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d plugins.basicview.status=\u72b6\u614b\uff1a plugins.basicview.activity=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\uff1a plugins.basicview.progress=\u9032\u884c\u72b6\u6cc1\uff1a plugins.basicview.log=\u30ed\u30b0\uff1a ConfigView.label.maxdownloadspeed=\u7dcf\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6 (KB/s) [0: \u7121\u5236\u9650] splash.loadingTorrent=Torrent \u3092\u30ed\u30fc\u30c9\u4e2d splash.of=/ UpdateWindow.title=Vuze \u30a2\u30c3\u30d7\u30c7\u30fc\u30bf UpdateWindow.header=\u6b21\u306e\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u304c\u5fc5\u8981\u3067\u3059\uff1a UpdateWindow.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb UpdateWindow.quit=\u7d42\u4e86 UpdateWindow.close=\u9589\u3058\u308b UpdateWindow.ok=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8 UpdateWindow.restart=\u518d\u8d77\u52d5 UpdateWindow.status.downloading=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d UpdateWindow.status.done=\u5b8c\u4e86 UpdateWindow.status.failed=\u5931\u6557 UpdateWindow.status.restartNeeded=\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u3067\u3059 ConfigView.pluginlist.broken=\u7834\u640d ConfigView.pluginlist.whereToPut=\u3053\u306e\u30e6\u30fc\u30b6\u306e\u307f\u304c\u4f7f\u3046\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u6b21\u306e\u30d5\u30a9\u30eb\u30c0\u306e\u4e0b\u3078\u7f6e\u3044\u3066\u304f\u3060\u3055\u3044\uff1a ConfigView.pluginlist.whereToPutOr=\u5171\u6709\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u6b21\u306e\u30d5\u30a9\u30eb\u30c0\u306e\u4e0b\u3078\u7f6e\u3044\u3066\u304f\u3060\u3055\u3044\uff1a MainWindow.statusText.checking=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d TableColumn.header.OnlyCDing4.info=\u30b7\u30fc\u30c9\u6642\u9593\u306e\u5408\u8a08\u3002\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d\u306e\u6642\u9593\u306f\u542b\u307f\u307e\u305b\u3093\u3002 ConfigView.section.style.alternateTablePainting=\u30c6\u30fc\u30d6\u30eb\u306e\u80cc\u666f\u8272\u3092\u884c\u3054\u3068\u306b\u5207\u308a\u66ff\u3048\u308b\uff08\u518d\u8d77\u52d5\u304c\u5fc5\u8981\uff09 UpdateWindow.status.restartMaybeNeeded=\u518d\u8d77\u52d5\u304c\u5fc5\u8981 ConfigView.pluginlist.shared=\u5171\u6709 PeersView.host=\u30db\u30b9\u30c8\u540d PeersView.host.info=\u53ef\u80fd\u306a\u5834\u5408\u3001\u30d4\u30a2\u306e\u30db\u30b9\u30c8\u540d\u3092\u8868\u793a\u3057\u307e\u3059\u3002\uff08\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u306b\u5f71\u97ff\u3057\u307e\u3059\uff09 MainWindow.menu.help.whatsnew=\u66f4\u65b0\u5185\u5bb9 ConfigView.label.checkonstart=\u8d77\u52d5\u6642\u306b Vuze \u306e\u6700\u65b0\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u78ba\u8a8d ConfigView.label.periodiccheck=\u5b9a\u671f\u7684\u306b Vuze \u306e\u6700\u65b0\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u78ba\u8a8d ConfigView.label.opendialog=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u304c\u898b\u3064\u304b\u3063\u305f\u5834\u5408\u3001\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u30a2\u30b7\u30b9\u30bf\u30f3\u30c8\u3092\u8868\u793a MainWindow.updateavail=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d MainWindow.status.unofficialversion=Vuze \u30d9\u30fc\u30bf MainWindow.status.latestversionunchecked=\u30d0\u30fc\u30b8\u30e7\u30f3\u30c1\u30a7\u30c3\u30af\u304c\u7121\u52b9\u3067\u3059 GeneralView.label.updatein.stopped=\u505c\u6b62\u4e2d StartStopRules.menu.viewDebug=\u30c7\u30d0\u30c3\u30b0\u60c5\u5831\u3092\u8868\u793a ConfigView.section.style.doNotUseGB=GB \u5358\u4f4d\u3092\u4f7f\u7528\u3057\u306a\u3044 ConfigView.section.style.doNotUseGB.tooltip=\u30c1\u30a7\u30c3\u30af\u3059\u308b\u3068 1024MB \u3092\u8d85\u3048\u3066\u3082 MB \u306e\u5358\u4f4d\u3067\u8868\u793a\u3057\u307e\u3059 MainWindow.menu.help.plugins=\u30d7\u30e9\u30b0\u30a4\u30f3 ConfigView.section.tracker.enablecategories=Torrent \u3092\u30ab\u30c6\u30b4\u30ea\u3054\u3068\u306b\u5206\u985e health.explain.share=\u3053\u306e Torrent \u306f\u914d\u4fe1\u307e\u305f\u306f Torrent \u30d5\u30a1\u30a4\u30eb\u3092\u914d\u5e03\u3057\u3066\u3044\u307e\u3059\u3002 ConfigView.section.tracker.createcert=\u81ea\u5df1\u7f72\u540d\u8a3c\u660e\u66f8\u3092\u4f5c\u6210 ConfigView.section.tracker.createbutton=\u4f5c\u6210 security.certcreate.title=\u81ea\u5df1\u7f72\u540d\u8a3c\u660e\u66f8\u3092\u4f5c\u6210 security.certcreate.intro=\u3053\u306e\u30c0\u30a4\u30a2\u30ed\u30b0\u3067\u306f\u81ea\u5df1\u7f72\u540d\u8a3c\u660e\u66f8\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002 security.certcreate.alias=\u5225\u540d security.certcreate.strength=\u5f37\u5ea6 security.certcreate.firstlastname=\u6c0f\u540d security.certcreate.orgunit=\u7d44\u7e54 (ou) security.certcreate.org=\u7d44\u7e54 (o) security.certcreate.city=\u5e02 security.certcreate.state=\u5dde security.certcreate.country=2 \u6841\u306e\u56fd\u30b3\u30fc\u30c9 security.certcreate.ok=\u4f5c\u6210 security.certcreate.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb security.certcreate.createok=\u8a3c\u660e\u66f8\u3092\u4f5c\u6210\u3057\u307e\u3057\u305f security.certcreate.createfail=\u8a3c\u660e\u66f8\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f ConfigView.section.plugins.webui=Swing Web \u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30a4\u30b9 ConfigView.section.plugins.xml_http_if=XML/HTTP \u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30a4\u30b9 webui.passwordenable=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u8a2d\u5b9a webui.user=\u30e6\u30fc\u30b6\u540d webui.password=\u30d1\u30b9\u30ef\u30fc\u30c9 webui.port=\u30dd\u30fc\u30c8 (*) webui.protocol=\u30d7\u30ed\u30c8\u30b3\u30eb (*) webui.homepage=\u30db\u30fc\u30e0\u30da\u30fc\u30b8 (*) webui.rootdir=\u30eb\u30fc\u30c8\u30c7\u30a3\u30ec\u30af\u30c8\u30ea (*) webui.rootres=\u30eb\u30fc\u30c8\u30ea\u30bd\u30fc\u30b9 (*) webui.mode=\u30e2\u30fc\u30c9 (*) webui.mode.info=\u8a2d\u5b9a\u53ef\u80fd\u306a\u30e2\u30fc\u30c9\u306f\n\t"full"\t=\u3059\u3079\u3066\u306e\u64cd\u4f5c\u304c\u53ef\u80fd\uff08\u30c7\u30d5\u30a9\u30eb\u30c8\uff09\n\t"view"\t=\u8868\u793a\u306e\u307f\u53ef\u80fd\uff08\u4ee3\u308f\u308a\u306b\u983b\u7e41\u306b\u66f4\u65b0\u53ef\u80fd\uff09 webui.access=\u30a2\u30af\u30bb\u30b9 (*) webui.access.info=\u30a2\u30af\u30bb\u30b9\u306f\u901a\u5e38\n\t"local"\t GeneralView.label.maxdownloadspeed=\u6700\u5927\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6 Security.keystore.corrupt=\u30ad\u30fc\u30b9\u30c8\u30a2 '%1' \u306e\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u8a3c\u660e\u66f8\u3092\u4e00\u65e6\u524a\u9664\u3057\u305f\u5f8c\u306b\u518d\u4f5c\u6210\uff0f\u518d\u30a4\u30f3\u30dd\u30fc\u30c8\u3057\u3066\u304f\u3060\u3055\u3044\u3002 Security.keystore.empty=\u30ad\u30fc\u30b9\u30c8\u30a2\u304c\u7a7a\u3067\u3059\u3002\u81ea\u5df1\u7f72\u540d\u8a3c\u660e\u66f8\u3092\u4f5c\u6210\uff08\u30c4\u30fc\u30eb\uff1e\u74b0\u5883\u8a2d\u5b9a\uff1e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\uff09\u3059\u308b\u304b\u304a\u624b\u6301\u3061\u306e\u8a3c\u660e\u66f8\u3092 '%1' \u306b\u30a4\u30f3\u30dd\u30fc\u30c8\u3057\u3066\u304f\u3060\u3055\u3044\u3002 webui.restart.info=(*) \u3067\u30de\u30fc\u30af\u3055\u308c\u305f\u9805\u76ee\u306e\u5909\u66f4\u306f\u518d\u8d77\u52d5\u5f8c\u306b\u6709\u52b9\u306b\u306a\u308a\u307e\u3059 GeneralView.label.maxdownloadspeed.tooltip=\u6700\u5927\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6 [0: \u7121\u5236\u9650] upnp.enable=\u6709\u52b9 upnp.info=\u30e6\u30cb\u30d0\u30fc\u30b5\u30eb\u30d7\u30e9\u30b0\u30a2\u30f3\u30c9\u30d7\u30ec\u30a4 (UPnP) \u5bfe\u5fdc\u30eb\u30fc\u30bf\u306b\u81ea\u52d5\u7684\u306b\u30dd\u30fc\u30c8\u3092\u5272\u308a\u5f53\u3066\u307e\u3059\u3002 upnp.mapping.dataport=\u53d7\u4fe1\u30d4\u30a2\u30c7\u30fc\u30bf\u30dd\u30fc\u30c8 upnp.mapping.tcptrackerport=TCP Tracker \u30dd\u30fc\u30c8 upnp.mapping.udptrackerport=UDP Tracker \u30dd\u30fc\u30c8 upnp.alertsuccess=\u5272\u308a\u5f53\u3066\u306e\u6210\u529f\u3092\u901a\u77e5 upnp.grabports=\u307b\u304b\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u304c\u30dd\u30fc\u30c8\u3092\u4f7f\u7528\u3057\u3066\u3044\u3066\u3082\u5272\u308a\u5f53\u3066\u308b upnp.refresh.label=\u30dd\u30fc\u30c8\u3092\u66f4\u65b0 upnp.refresh.button=\u66f4\u65b0 upnp.mapping.tcpssltrackerport=TCP SSL Tracker \u30dd\u30fc\u30c8 upnp.alertothermappings=\u307b\u304b\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u304c\u30dd\u30fc\u30c8\u3092\u4f7f\u7528\u3057\u3066\u3044\u308b\u5834\u5408\u306b\u901a\u77e5 upnp.alertdeviceproblems=UPnP \u30c7\u30d0\u30a4\u30b9\u306b\u554f\u984c\u304c\u3042\u308b\u5834\u5408\u306b\u901a\u77e5 upnp.trace_to_log=\u30c7\u30d0\u30c3\u30b0\u60c5\u5831\u3092\u30ed\u30b0\u306b\u51fa\u529b ConfigView.pluginlist.coreplugins=\u6b21\u306e\u30d7\u30e9\u30b0\u30a4\u30f3\u304c\u7d44\u307f\u8fbc\u307e\u308c\u3066\u3044\u307e\u3059\uff1a Peers.column.DLedFromOthers=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9(\u4ed6) Peers.column.DLedFromOthers.info=\u3053\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3068\u63a5\u7d9a\u3057\u305f\u6642\u70b9\u304b\u3089\u306e\u3001\u307b\u304b\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304b\u3089\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u305f\u7dcf\u91cf upnp.releasemappings=\u5272\u308a\u5f53\u3066\u305f\u30dd\u30fc\u30c8\u3092\u7d42\u4e86\u6642\u306b\u89e3\u653e webui.upnpenable=\u3053\u306e\u30dd\u30fc\u30c8\u306b\u5bfe\u3057\u3066 UPnP \u3092\u4f7f\u7528 (*) ConfigView.section.file.friendly.hashchecking=\u30d4\u30fc\u30b9\u30c1\u30a7\u30c3\u30af\u306e\u983b\u5ea6\u3092\u4e0b\u3052\u308b ConfigView.section.file.friendly.hashchecking.tooltip=\u30d4\u30fc\u30b9\u306e\u30cf\u30c3\u30b7\u30e5\u8a08\u7b97\u6642\u306e CPU, HDD \u8ca0\u8377\u3092\u4e0b\u3052\u307e\u3059\u3002\u305f\u3060\u3057\u901f\u5ea6\u306f\u591a\u5c11\u9045\u304f\u306a\u308a\u307e\u3059 ConfigView.section.tracker.seedretention=Torrent \u3054\u3068\u306b\u4fdd\u6301\u3059\u308b\u30b7\u30fc\u30c0\u30fc\u306e\u4e0a\u9650 [0: \u7121\u5236\u9650] ConfigView.section.tracker.seedretention.info=\u8a18\u9332\u5916\u306b\u306a\u3063\u305f\u30b7\u30fc\u30c0\u30fc\u306f\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u7d71\u8a08\u304b\u3089\u9664\u5916\u3055\u308c\u307e\u3059 ConfigView.section.tracker.port=HTTP \u30dd\u30fc\u30c8\u3067\u958b\u304f ConfigView.section.tracker.sslport=HTTPS \u30dd\u30fc\u30c8\u3067\u958b\u304f ConfigView.section.tracker.publicenable.info=\u307b\u304b\u306e\u30e6\u30fc\u30b6\u30fc\u304c\u5185\u8535\u306e\u30c8\u30e9\u30c3\u30ab\u30fc\u3092\u5229\u7528\u3057\u3066\nTorrent \u3092\u4f5c\u6210\u3059\u308b\u3053\u3068\u3092\u8a31\u53ef\u3057\u307e\u3059 Button.clear=\u6d88\u53bb MainWindow.IPs.tooltip=\u30d5\u30a3\u30eb\u30bf\u4e00\u89a7\u306e\u6700\u7d42\u66f4\u65b0\u65e5\u6642: %1\n\u30d5\u30a3\u30eb\u30bf\u4e2d\u306e IPFilters \u6570 - \u30d6\u30ed\u30c3\u30af\uff0f\u62d2\u5426\uff0f\u4e0d\u6b63 \u306a IP \u306e\u4e00\u89a7\n\u8a73\u7d30\u3092\u898b\u308b\u306b\u306f\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002 ConfigView.section.ipfilter.list.banned=\u306f\u30d6\u30ed\u30c3\u30af\u3055\u308c\u307e\u3057\u305f ConfigView.section.ipfilter.list.baddata=\u306f\u4e0d\u6b63\u306a\u30c7\u30fc\u30bf\u3092\u9001\u4fe1\u3057\u307e\u3057\u305f Button.reset=\u5143\u306b\u623b\u3059 ConfigView.section.ipfilter.bannedinfo=\u4e0d\u6b63\u306a\u30c7\u30fc\u30bf\u3092\u9001\u4fe1\u3057\u305f IP\uff08\u9650\u5ea6\u8d85\u904e\u3059\u308b\u3068\u30d6\u30ed\u30c3\u30af\uff09 ConfigView.section.ipfilter.blockedinfo=IP \u30d5\u30a3\u30eb\u30bf\u306b\u3088\u3063\u3066\u30d6\u30ed\u30c3\u30af\u3055\u308c\u305f IP download.removerules.name=\u524a\u9664\u30eb\u30fc\u30eb download.removerules.unauthorised.info=\u8a8d\u8a3c\u3055\u308c\u3066\u3044\u306a\u3044 Torrent \u3068\u306f\u3001Torrent \u304c\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u767b\u9332\u3055\u308c\u3066\u304a\u3089\u305a "not authoris(z)ed" \u304b "unauthoris(z)ed" \u306e\u3044\u305a\u308c\u304b\u306e\u30a8\u30e9\u30fc\u5fdc\u7b54\u304c\u8fd4\u3063\u3066\u304d\u305f\u3082\u306e\u3092\u6307\u3057\u307e\u3059\u3002 download.removerules.unauthorised=\u8a8d\u8a3c\u3055\u308c\u3066\u3044\u306a\u3044 Torrent \u3092\u81ea\u52d5\u7684\u306b\u524a\u9664 download.removerules.unauthorised.seedingonly=\t\u30b7\u30fc\u30c9\u4e2d\u306e Torrent \u306e\u307f download.removerules.removed.ok=\u524a\u9664\u30eb\u30fc\u30eb\u306b\u3088\u308a\u3001'%1'\u306f\u81ea\u52d5\u7684\u306b\u524a\u9664\u3055\u308c\u307e\u3057\u305f\u3002 download.removerules.updatetorrents=Vuze \u306e\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u7528 Torrent \u3092\u524a\u9664 ConfigView.label.defaultstarttorrentsstopped=\u65b0\u3057\u3044 Torrent \u306f\u505c\u6b62\u72b6\u614b\u3067\u8ffd\u52a0 ConfigView.section.server.enableudp=UDP \u3092\u4f7f\u7528 upnp.mapping.dataportudp=UDP Tracker \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30dd\u30fc\u30c8 ConfigView.section.file.decoder.showlax=\u9069\u5207\u3067\u306f\u306a\u3044\u3068\u601d\u308f\u308c\u308b\u6587\u5b57\u30a8\u30f3\u30b3\u30fc\u30c9\u3082\u8868\u793a ConfigView.section.file.decoder.showall=\u9078\u629e\u53ef\u80fd\u306a\u3059\u3079\u3066\u306e\u6587\u5b57\u30a8\u30f3\u30b3\u30fc\u30c9\u3092\u8868\u793a MainWindow.status.updowndetails.tooltip=\u30a2\u30c3\u30d7\uff0f\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6\u306e\u8a73\u7d30\n\u53f3\u30af\u30ea\u30c3\u30af\u3067\u8a2d\u5b9a\u3092\u5909\u66f4\u3001\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u3067\u7d71\u8a08\u60c5\u5831\u304c\u958b\u304d\u307e\u3059 TrackerClient.announce.warningmessage=%1' \u306e\u30c8\u30e9\u30c3\u30ab\u30fc\u306f\u8b66\u544a '%2' \u3092\u8fd4\u3057\u307e\u3057\u305f ConfigView.section.tracker.natcheckenable=\u30c7\u30fc\u30bf\u5165\u529b\u30dd\u30fc\u30c8\u304c\u63a5\u7d9a\u53ef\u80fd\u304b\u78ba\u8a8d\u3057\u3001\u5931\u6557\u3057\u305f\u3089\u30d4\u30a2\u306b\u5831\u544a ConfigView.section.tracker.publishenabledetails=\u3059\u3079\u3066\u306e Torrent \u306e\u8a73\u7d30\u3092\u516c\u958b ConfigView.section.tracker.publishenablepeerdetails=\u30d4\u30a2\u306e\u8a73\u7d30\u3092\u516c\u958b MyTrackerView.badnat=NAT \u30a8\u30e9\u30fc MyTrackerView.badnat.info=NAT \u30c1\u30a7\u30c3\u30af\u306b\u5931\u6557\u3057\u305f\u30d4\u30a2\u6570 ConfigView.section.tracker.natchecktimeout=\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\uff08\u79d2\uff09 ConfigView.section.file.perf.cache.enable=\u30c7\u30a3\u30b9\u30af\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u4f7f\u7528 ConfigView.section.file.perf.cache.size=\u30ad\u30e3\u30c3\u30b7\u30e5\u30b5\u30a4\u30ba(%1) #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u8ee2\u9001 MainWindow.menu.transfers.startalltransfers=\u3059\u3079\u3066\u958b\u59cb MainWindow.menu.transfers.stopalltransfers=\u3059\u3079\u3066\u505c\u6b62 MainWindow.menu.transfers.pausetransfers=\u4e00\u6642\u505c\u6b62 MainWindow.menu.transfers.resumetransfers=\u518d\u958b ConfigView.label.experimental.osx.kernel.panic.fix=\u30c7\u30e5\u30a2\u30eb CPU \u306e OS X \u30b7\u30b9\u30c6\u30e0\u3067\u306e\u30ab\u30fc\u30cd\u30eb\u30d1\u30cb\u30c3\u30af\u306b\u5bfe\u3059\u308b\u5b9f\u9a13\u7684\u306a\u4fee\u6b63\u3092\u6709\u52b9\u306b\u3059\u308b\uff08\u518d\u8d77\u52d5\u304c\u5fc5\u8981\uff09 SystemTray.menu.pausetransfers=\u8ee2\u9001\u3092\u4e00\u6642\u505c\u6b62 SystemTray.menu.resumetransfers=\u8ee2\u9001\u3092\u518d\u958b ConfigView.section.file.truncate.too.large=\u65e2\u5b58\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u5927\u304d\u3059\u304e\u308b\u5834\u5408\u306b\u5207\u308a\u8a70\u3081\u308b ConfigView.section.file.perf.cache.trace=\u30ad\u30e3\u30c3\u30b7\u30e5\u64cd\u4f5c\u3092\u8a3a\u65ad\u7528\u306b\u30c8\u30ec\u30fc\u30b9 ConfigView.section.interface.enabletray=\u30b7\u30b9\u30c6\u30e0\u30c8\u30ec\u30a4\u3092\u4f7f\u7528\uff08\u518d\u8d77\u52d5\u304c\u5fc5\u8981\uff09 PeerManager.status.error=\u30a8\u30e9\u30fc Stats.title.full=\u7d71\u8a08\u60c5\u5831 TransferStatsView.title.full=\u8ee2\u9001\u91cf CacheView.title.full=\u30ad\u30e3\u30c3\u30b7\u30e5 CacheView.general.size=\u5408\u8a08\u30b5\u30a4\u30ba CacheView.general.inUse=\u4f7f\u7528\u4e2d CacheView.general.title=\u30ad\u30e3\u30c3\u30b7\u30e5 CacheView.reads.title=I/O \u8aad\u307f\u51fa\u3057 CacheView.reads.fromFile=\u30d5\u30a1\u30a4\u30eb CacheView.reads.fromCache=\u30ad\u30e3\u30c3\u30b7\u30e5 CacheView.reads.hits=\u30d2\u30c3\u30c8 CacheView.writes.title=I/O \u66f8\u304d\u8fbc\u307f CacheView.writes.toCache=\u30ad\u30e3\u30c3\u30b7\u30e5 CacheView.writes.toFile=\u30d5\u30a1\u30a4\u30eb CacheView.writes.hits=\u30bb\u30fc\u30d6 CacheView.speeds.title=\u30c7\u30fc\u30bf\u30ec\u30fc\u30c8 CacheView.speeds.reads=\u8aad\u307f\u51fa\u3057 CacheView.speeds.writes=\u66f8\u304d\u8fbc\u307f CacheView.speeds.fromCache=\u30ad\u30e3\u30c3\u30b7\u30e5 CacheView.speeds.fromFile=\u30d5\u30a1\u30a4\u30eb CacheView.reads.#=No. CacheView.reads.amount=\u7dcf\u8a08 CacheView.reads.avgsize=\u5e73\u5747\u30b5\u30a4\u30ba openUrl.referrer=\u30ea\u30d5\u30a1\u30e9 URL : openUrl.referrer.info=Web \u30b5\u30a4\u30c8\u304c\u8981\u6c42\u3059\u308b\u5834\u5408\u306b\u306e\u307f\u5fc5\u8981 ConfigView.label.maxuploadspeedseeding=\u30b7\u30fc\u30c9\u306e\u307f\u306e\u5834\u5408\u306e\u4ee3\u66ff\u30ec\u30fc\u30c8 ConfigView.label.transfer.ignorepeerports=\u6307\u5b9a\u3057\u305f\u30dd\u30fc\u30c8\u756a\u53f7\u3092\u4f7f\u7528\u3059\u308b\u30d4\u30a2\u3092\u7121\u8996\uff08';' \u3067\u533a\u5207\u308a \u4f8b 0;25\uff09 ConfigView.section.proxy.enable_socks.peer=\u30d4\u30a2\u9593\u306e\u901a\u4fe1\uff08\u3053\u3061\u3089\u304b\u3089\u306e\u63a5\u7d9a\u306e\u307f\uff09\u3067\u30d7\u30ed\u30ad\u30b7\u3092\u4f7f\u7528\uff08\u518d\u8d77\u52d5\u304c\u5fc5\u8981\uff09 ConfigView.section.proxy.peer.informtracker=\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u5236\u7d04\u3092\u901a\u77e5 ConfigView.section.proxy.socks.version=Socks \u30d0\u30fc\u30b8\u30e7\u30f3 PiecesView.legend.written=\u66f8\u304d\u8fbc\u307f\u6e08 PiecesView.legend.requested=\u88ab\u30ea\u30af\u30a8\u30b9\u30c8 PiecesView.legend.downloaded=\u66f8\u304d\u8fbc\u307f\u5f85\u3061 PiecesView.legend.incache=\u30ad\u30e3\u30c3\u30b7\u30e5\u5185 PiecesView.typeItem.0=\u9045\u3044 PiecesView.typeItem.1=\u901f\u3044 PiecesView.type=\u7a2e\u985e Security.jar.tools_not_found=JAR \u306e\u7f72\u540d\u306b\u5931\u6557 - %1\u306b'tools.jar'\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002\u8a2d\u5b9a\uff1e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3 \u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 Security.jar.signfail=JAR \u306e\u7f72\u540d\u306b\u5931\u6557 - %1 ConfigView.section.security.toolsinfo=\u7f72\u540d\u4ed8\u304d JAR \u30d5\u30a1\u30a4\u30eb\u306f\u3044\u304f\u3064\u304b\u306e\u30d7\u30e9\u30b0\u30a4\u30f3\u3067\u4f7f\u7528\u3055\u308c\u307e\u3059\u3002\nJAR \u30d5\u30a1\u30a4\u30eb\u306e\u7f72\u540d\u306b\u306f\u3001Sun \u306e JDK \u306b\u542b\u307e\u308c\u308b 'tools.jar' \u304c\u5fc5\u8981\u3067\u3059\u3002\n\u3082\u3057 JRE \u3057\u304b\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u3066\u3044\u306a\u3044\u5834\u5408\u306f JDK \u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\u901a\u5e38\u3001Vuze \u306f 'tools.jar' \u3092\u81ea\u52d5\u3067\u898b\u3064\u3051\u307e\u3059\u304c\u3001\u5931\u6557\u3057\u305f\u5834\u5408\u306f\u3053\u3053\u3067\u30d5\u30a9\u30eb\u30c0\u3092\u6307\u5b9a\u3059\u308b\u3053\u3068\u3082\u3067\u304d\u307e\u3059\u3002 ConfigView.section.security.toolsdir='tools.jar' \u304c\u3042\u308b\u30d5\u30a9\u30eb\u30c0 ConfigView.section.security.choosetoolssavedir='tools.jar' \u304c\u3042\u308b\u30d5\u30a9\u30eb\u30c0\u3092\u9078\u629e ConfigView.section.proxy.peer.same=\u30d4\u30a2\u9593\u306e\u901a\u4fe1\u3082\u30c8\u30e9\u30c3\u30ab\u30fc\u3068\u306e\u901a\u4fe1\u3068\u540c\u3058\u30d7\u30ed\u30ad\u30b7\u8a2d\u5b9a\u3092\u4f7f\u7528 ConfigView.section.connection.network.max.simultaneous.connect.attempts=\u6700\u5927\u540c\u6642\u30bb\u30c3\u30b7\u30e7\u30f3\u6570 ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=\u6700\u5927\u540c\u6642\u30bb\u30c3\u30b7\u30e7\u30f3\u6570\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002\n\u6ce8\u610f: Windows XP Service Pack 2 (SP2) \u3067\u306f\u30b7\u30b9\u30c6\u30e0\u5168\u4f53\u3067 10 \u306b\u5236\u9650\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u306f 8 \u3067\u3059 ConfigView.section.file.perf.cache.size.explain=\u3053\u306e\u30ad\u30e3\u30c3\u30b7\u30e5\u306f\u30cf\u30fc\u30c9\u30c7\u30a3\u30b9\u30af\u306e I/O \u3092\u8efd\u6e1b\u3067\u304d\u307e\u3059\u3002Java \u30aa\u30d7\u30b7\u30e7\u30f3 '-XX:MaxDirectMemorySize' \u3092\u6307\u5b9a\u3057\u3066\u3044\u306a\u3044\u9650\u308a\uff08\u6700\u5927 VM \u30b5\u30a4\u30ba\u4ee5\u4e0b\u306e\uff09%1 \u7a0b\u5ea6\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u73fe\u5728\u306e\u6700\u5927 VM \u30b5\u30a4\u30ba\u306f %2 \u3067\u3059\u3002\u8a73\u3057\u304f\u306f %3 \u306b\u3042\u308b Wiki \u306e MemoryUsage \u306e\u9805\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u9069\u5207\u3067\u306a\u3044\u5834\u5408\u30e1\u30e2\u30ea\u4e0d\u8db3\u306e\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3059\u3002\u591a\u304f\u306e\u5834\u5408 32MB \u4ee5\u4e0a\u306f\u904e\u5270\u3067\u3059\u3002 MyTorrentsView.menu.setSpeed.unlimit=\u7121\u5236\u9650 MyTorrentsView.menu.setSpeed.unlimited=\u7121\u5236\u9650 MyTorrentsView.menu.setSpeed.disable=\u30a2\u30c3\u30d7\u7981\u6b62 MyTorrentsView.menu.setSpeed.disabled=\u30a2\u30c3\u30d7\u7981\u6b62 MyTorrentsView.menu.setSpeed.in=- MyTorrentsView.menu.setSpeed.slots=\u500b\u306f\u305d\u308c\u305e\u308c GeneralView.label.maxuploadspeed=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 GeneralView.label.maxuploadspeed.tooltip=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 [0: \u7121\u5236\u9650] MyTorrents.items.UpSpeedLimit.disabled=\u306a\u3057 MyTorrents.items.UpSpeedLimit.unlimited=\u7121\u5236\u9650 TableColumn.header.maxupspeed=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 TableColumn.header.maxupspeed.info=Torrent \u3054\u3068\u306e\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 ConfigView.section.file.perf.cache.enable.write=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u6e08\u307f\u30c7\u30fc\u30bf\u3092\u30ad\u30e3\u30c3\u30b7\u30e5\uff08\u30c7\u30a3\u30b9\u30af\u66f8\u304d\u8fbc\u307f\u3092\u6e1b\u3089\u3057\u3001\u30d4\u30fc\u30b9\u30c1\u30a7\u30c3\u30af\u306b\u3088\u308b\u8aad\u307f\u51fa\u3057\u3082\u8efd\u6e1b\u3057\u307e\u3059\uff09 ConfigView.section.file.perf.cache.enable.read=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6642\u306b\u30c7\u30fc\u30bf\u3092\u5148\u8aad\u307f\u3057\u3001\u30c7\u30a3\u30b9\u30af\u30a2\u30af\u30bb\u30b9\u3092\u8efd\u6e1b ConfigView.section.tracker.separatepeerids=\u30c8\u30e9\u30c3\u30ab\u30fc\u3068\u30c7\u30fc\u30bf\u901a\u4fe1\u3067\u7570\u306a\u308b\u30d4\u30a2 ID \u3092\u4f7f\u7528 ConfigView.section.tracker.separatepeerids.info=\u975e\u533f\u540d\u30c8\u30e9\u30c3\u30ab\u30fc\u3067\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9/\u30b7\u30fc\u30c9\u4e2d\u3092\u884c\u3046\u5834\u5408\u306b\u533f\u540d\u6027\u3092\u4e0a\u3052\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 ConfigView.section.interface.wavlocation=.wav \u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e ConfigView.section.interface.wavlocation.info=.wav \u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\uff08\u7a7a\u767d\u306e\u5834\u5408\u306f\u30c7\u30d5\u30a9\u30eb\u30c8\uff09 ConfigView.section.tracker.server=\u30b5\u30fc\u30d0 ConfigView.section.tracker.client=\u30af\u30e9\u30a4\u30a2\u30f3\u30c8 ConfigView.section.tracker.client.connecttimeout=\u63a5\u7d9a\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\uff08\u79d2\uff09 ConfigView.section.tracker.client.readtimeout=\u8aad\u307f\u8fbc\u307f\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\uff08\u79d2\uff09 MainWindow.menu.tools=\u30c4\u30fc\u30eb FilesView.path=\u30d1\u30b9 FilesView.fullpath=\u30d5\u30eb\u30d1\u30b9\u3092\u8868\u793a FilesView.remaining=\u6b8b\u308a\u30d4\u30fc\u30b9 TableColumn.header.trackername=\u30c8\u30e9\u30c3\u30ab\u30fc\u540d TableColumn.header.trackername.info=\u30a2\u30ca\u30a6\u30f3\u30b9 URL \u3092\u5143\u306b\u3057\u305f\u30c8\u30e9\u30c3\u30ab\u30fc\u306e\u540d\u524d ConfigView.group.override=\u8ffd\u52a0\u8a2d\u5b9a ConfigView.section.file.perf.cache.notsmallerthan=\u6307\u5b9a\u30b5\u30a4\u30ba\u3088\u308a\u5c0f\u3055\u3044\u30d5\u30a1\u30a4\u30eb\u3092\u30ad\u30e3\u30c3\u30b7\u30e5\u3057\u306a\u3044 (%1) PeersView.menu.blockupload=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3057\u306a\u3044 PeersView.menu.kickandban=\u30ad\u30c3\u30af\uff06\u30d0\u30f3 PeersView.menu.kickandban.reason=\u72b6\u614b PeersView.state=\u30d4\u30a2\u306e\u63a5\u7d9a\u72b6\u614b PeersView.state.info=\u30d4\u30a2\u63a5\u7d9a\u306e\u72b6\u614b PeersView.state.pending=\u4fdd\u7559 PeersView.state.connecting=\u63a5\u7d9a\u4e2d PeersView.state.handshake=\u30cf\u30f3\u30c9\u30b7\u30a7\u30a4\u30af PeersView.state.established=\u63a5\u7d9a\u78ba\u7acb ConfigView.section.tracker.processinglimits=\u51e6\u7406\u4e0a\u9650 ConfigView.section.tracker.maxgettime=GET \u51e6\u7406\u6642\u9593\u306e\u4e0a\u9650 (sec) [0: \u7121\u5236\u9650] ConfigView.section.tracker.maxgettime.info=\u30a2\u30ca\u30a6\u30f3\u30b9\u3068\u30b9\u30af\u30ec\u30a4\u30d7\u306b\u4f7f\u7528\u3055\u308c\u307e\u3059 ConfigView.section.tracker.maxposttimemultiplier=POST \u51e6\u7406\u306b\u5bfe\u3059\u308b GET \u51e6\u7406\u306e\u6570 [0: \u7121\u5236\u9650] ConfigView.section.tracker.maxposttimemultiplier.info=\u30b5\u30d6\u30df\u30c3\u30b7\u30e7\u30f3\u3068\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u306b\u4f7f\u7528\u3055\u308c\u307e\u3059 ConfigView.section.tracker.maxthreads=\u6700\u5927\u540c\u6642\u30ea\u30af\u30a8\u30b9\u30c8\u6570 DownloadManager.error.operationcancancelled=\u64cd\u4f5c\u306f\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f Torrent.create.progress.cancelled=\u64cd\u4f5c\u306f\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f sharing.progress.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb wizard.maketorrents.autoopen=\u4f5c\u6210\u5f8c\u3001\u30b7\u30fc\u30c9\u30e2\u30fc\u30c9\u3067Torrent\u3092\u958b\u304f ConfigView.section.sharing.rescanenable=\u5b9a\u671f\u7684\u306b\u5171\u6709\u304c\u5909\u66f4\u3055\u308c\u3066\u3044\u306a\u3044\u304b\u518d\u30b9\u30ad\u30e3\u30f3 ConfigView.section.sharing.rescanperiod=\u518d\u30b9\u30ad\u30e3\u30f3\u9593\u9694\uff08\u79d2\uff09 ConfigView.section.connection.advanced=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u8a73\u7d30 ConfigView.section.connection.advanced.url=http://wiki.vuze.com/index.php/AdvancedNetworkSettings ConfigView.section.connection.advanced.mtu=MTU ConfigView.section.connection.advanced.SO_RCVBUF=SO_RCVBUF \u30b5\u30a4\u30ba [0: OS \u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u5024] ConfigView.section.connection.advanced.SO_SNDBUF=SO_SNDBUF \u30b5\u30a4\u30ba [0: OS \u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u5024] ConfigView.section.connection.advanced.IPDiffServ=\u9001\u4fe1\u30d1\u30b1\u30c3\u30c8 DiffServ\uff08TOS \u30d5\u30a3\u30fc\u30eb\u30c9\uff09 ConfigView.section.interface.confirm_torrent_removal=Torrent \u3092\u524a\u9664\u3059\u308b\u3068\u304d\u3001\u78ba\u8a8d\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u8868\u793a ConfigView.section.interface.confirm_torrent_removal.tooltip=Torrent \u30ea\u30b9\u30c8\u304b\u3089 Torrent \u3092\u524a\u9664\u3059\u308b\u969b\u306b\u78ba\u8a8d\u3057\u307e\u3059 TableColumn.header.seed_to_peer_ratio.info=\u30b7\u30fc\u30c0\u30fc\u306b\u5bfe\u3059\u308b\u30d4\u30a2\u306e\u6bd4\u7387 PeersView.connected_time=\u63a5\u7d9a\u6642\u9593 PeersView.connected_time.info=\u30d4\u30a2\u3068\u306e\u5408\u8a08\u63a5\u7d9a\u6642\u9593 ConfigView.section.interface.display.add_torrents_silently=\u30b5\u30a4\u30ec\u30f3\u30c8\u30e2\u30fc\u30c9\u3067 Torrent \u3092\u8ffd\u52a0 ConfigView.section.interface.display.add_torrents_silently.tooltip=Torrent \u3092\u30ea\u30b9\u30c8\u306b\u8ffd\u52a0\u3059\u308b\u969b\u3001\u30e1\u30a4\u30f3\u30a6\u30a3\u30f3\u30c9\u30a6\u3092\u30a2\u30af\u30c6\u30a3\u30d6\u306b\u3057\u306a\u3044 TableColumn.header.maxdownspeed=\u6700\u5927\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6 TableColumn.header.maxdownspeed.info=Torrent \u3054\u3068\u306e\u6700\u5927\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6 ConfigView.section.tracker.passwordwebhttpsonly=HTTPS \u306b\u3088\u308b\u30a2\u30af\u30bb\u30b9\u306e\u307f\u8a31\u53ef TableColumn.header.torrentpath=Torrent \u30d5\u30a9\u30eb\u30c0 TableColumn.header.torrentpath.info=Torrent \u30d5\u30a1\u30a4\u30eb\u306e\u3042\u308b\u30d5\u30a9\u30eb\u30c0 ConfigView.section.sharing.torrentcomment=\u751f\u6210\u3057\u305f Torrent \u3078\u306e\u30b3\u30e1\u30f3\u30c8 ConfigView.label.copyanddeleteratherthanmove=\u79fb\u52d5\u3059\u308b\u4ee3\u308f\u308a\u306b\u30b3\u30d4\u30fc\u3057\u3066\u304b\u3089\u5143\u30c7\u30fc\u30bf\u3092\u524a\u9664 - \u3042\u308b\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u3067\u8d77\u304d\u308b\u30c7\u30fc\u30bf\u640d\u5931\u3092\u9632\u6b62\u3057\u307e\u3059 ConfigView.label.openstatsonstart=\u8d77\u52d5\u6642\u306b\u7d71\u8a08\u60c5\u5831\u3092\u958b\u304f swt.install.window.title=Vuze \u30d7\u30e9\u30b0\u30a4\u30f3 \u30a4\u30f3\u30b9\u30c8\u30fc\u30e9 swt.install.window.ok=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb swt.install.window.header=\u6b21\u306e\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u304c\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u307e\u3059\uff1a swt.uninstall.window.title=Vuze \u30d7\u30e9\u30b0\u30a4\u30f3 \u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30e9 swt.uninstall.window.ok=\u524a\u9664 swt.uninstall.window.header=\u6b21\u306e\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u304c\u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u307e\u3059\uff1a installPluginsWizard.title=\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb installPluginsWizard.mode.title=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u5834\u6240\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 installPluginsWizard.mode.list=sourceforge.net \u306e\u4e00\u89a7\u304b\u3089 installPluginsWizard.list.title=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3067\u304d\u308b\u30d7\u30e9\u30b0\u30a4\u30f3 installPluginsWizard.list.loading=\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u30ea\u30b9\u30c8\u3092\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059\u3002 installPluginsWizard.list.loaded=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 installPluginsWizard.list.name=\u540d\u524d installPluginsWizard.list.version=\u30d0\u30fc\u30b8\u30e7\u30f3 installPluginsWizard.list.description=\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u8aac\u660e installPluginsWizard.finish.title=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb installPluginsWizard.finish.explanation=\u9078\u629e\u3055\u308c\u305f\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u30a2\u30b7\u30b9\u30bf\u30f3\u30c8\u306b\u3088\u308a\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u307e\u3059\u3002\n\n\u3057\u3070\u3089\u304f\u6642\u9593\u304c\u304b\u304b\u308a\u307e\u3059\u306e\u3067\u304a\u5f85\u3061\u304f\u3060\u3055\u3044\u3002\n\n\u9032\u6357\u72b6\u6cc1\u306e\u8868\u793a\u306f\u30b9\u30c6\u30fc\u30bf\u30b9\u30d0\u30fc\u306e\u5de6\u3092\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002 installPluginsWizard.details.loading=\u8a73\u7d30\u3092\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059... installPluginsWizard.mode.file=\u30d5\u30a1\u30a4\u30eb\u304b\u3089 installPluginsWizard.installMode.title=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306e\u7a2e\u985e\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 installPluginsWizard.installMode.user=\u3053\u306e\u30e6\u30fc\u30b6\u306e\u307f\u4f7f\u7528\u3059\u308b installPluginsWizard.installMode.shared=\u3059\u3079\u3066\u306e\u30e6\u30fc\u30b6\u3067\u4f7f\u7528\u3059\u308b installPluginsWizard.file.title=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044 installPluginsWizard.file.file=\u30d5\u30a1\u30a4\u30eb : installPluginsWizard.file.invalidfile=\u3053\u306e\u30d5\u30a1\u30a4\u30eb\u306f\u6709\u52b9\u306a Vuze \u30d7\u30e9\u30b0\u30a4\u30f3\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 installPluginsWizard.file.no_such_file=\u6307\u5b9a\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 installPluginsWizard.file.browse=\u53c2\u7167... uninstallPluginsWizard.title=\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb uninstallPluginsWizard.list.title=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u6e08\u307f\u306e\u30d7\u30e9\u30b0\u30a4\u30f3 uninstallPluginsWizard.list.loaded=\u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 installPluginsWizard.list.nullversion=\u30d0\u30fc\u30b8\u30e7\u30f3\u4e0d\u660e uninstallPluginsWizard.finish.title=\u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb uninstallPluginsWizard.finish.explanation=\u9078\u629e\u3055\u308c\u305f\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u30a2\u30b7\u30b9\u30bf\u30f3\u30c8\u306b\u3088\u308a\u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u307e\u3059\u3002 MainWindow.menu.plugins.installPlugins=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb \u30a6\u30a3\u30b6\u30fc\u30c9... MainWindow.menu.plugins.uninstallPlugins=\u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb \u30a6\u30a3\u30b6\u30fc\u30c9... ConfigView.section.ipfilter.totalIPs=\u5408\u8a08 %1 IP\u3092\u30d6\u30ed\u30c3\u30af\u3057\u307e\u3057\u305f\u3002\uff08\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u4e2d %2\uff09 update.instance.install=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306e\u78ba\u8a8d update.instance.uninstall=\u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306e\u78ba\u8a8d update.instance.update=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306e\u78ba\u8a8d MainWindow.status.update.tooltip=\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u9032\u884c\u72b6\u6cc1\u3092\u78ba\u8a8d\u3067\u304d\u307e\u3059 updater.progress.window.title=\u73fe\u5728\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u30bf\u30b9\u30af updater.progress.window.info=\u51e6\u7406\u3092\u4e2d\u6b62\u3059\u308b\u306b\u306f '\u4e2d\u6b62' \u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059 Button.abort=\u4e2d\u6b62 ConfigView.section.ipfilter.enablebanning=\u4e0d\u6b63\u306a\u30c7\u30fc\u30bf\u3092\u9001\u308a\u7d9a\u3051\u308b\u30d4\u30a2\u3092\u30d6\u30ed\u30c3\u30af\u3059\u308b Network.alert.acceptfail=\u30dd\u30fc\u30c8 %1, %2 \u3067\u4e0a\u9650\u4ee5\u4e0a\u306e\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u305f\u305f\u3081\u3001\u51e6\u7406\u3092\u4e2d\u6b62\u3057\u307e\u3057\u305f\u3002\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u306e\u8a2d\u5b9a\u3092\u78ba\u8a8d\u3057\u3001\u5916\u90e8\u304b\u3089\u306e\u63a5\u7d9a\u3092\u53d7\u3051\u5165\u308c\u3089\u308c\u308b\u3088\u3046\u306b\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 MyShares.column.category=\u30ab\u30c6\u30b4\u30ea UpdateWindow.restartLater=\u5f8c\u3067 MainWindow.menu.file.restart=Vuze \u3092\u518d\u8d77\u52d5 MainWindow.dialog.restartconfirmation.title=Vuze \u3092\u518d\u8d77\u52d5\u3057\u307e\u3059\u304b\uff1f MainWindow.dialog.restartconfirmation.text=Vuze \u3092\u518d\u8d77\u52d5\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f deletetorrent.message1=\u6b21\u306e Torrent \u3092\u524a\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059:\n deletetorrent.message2=\n\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f ConfigView.label.prioritizemostcompletedfiles=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5b8c\u4e86\u7387\u304c\u6307\u5b9a\u5024\u3088\u308a\u3082\u9ad8\u3044\u30d5\u30a1\u30a4\u30eb\u3092\u512a\u5148 splash.plugin.init=\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u521d\u671f\u5316: splash.plugin.UIinit=\u30d7\u30e9\u30b0\u30a4\u30f3 GUI \u3092\u521d\u671f\u5316\u4e2d: %1 ConfigView.section.style.osx_small_fonts=\u5c0f\u3055\u3044\u30d5\u30a9\u30f3\u30c8\u3092\u4f7f\u7528\uff08\u518d\u8d77\u52d5\u304c\u5fc5\u8981\uff09 ConfigView.section.tracker.tcpnonblocking=TCP \u30c8\u30e9\u30c3\u30ab\u30fc\u3067\u975e\u30d6\u30ed\u30c3\u30ad\u30f3\u30b0 I/O \u3092\u4f7f\u7528\u3059\u308b\u3002\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3059\u308b\u306b\u306f\u30c8\u30e9\u30c3\u30ab\u30fc Web \u3092\u4ee3\u66ff\u30dd\u30fc\u30c8\u3067\u5b9f\u884c\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 ConfigView.section.tracker.nonblocking=\u975e\u30d6\u30ed\u30c3\u30ad\u30f3\u30b0\u8a2d\u5b9a ConfigView.section.tracker.nonblockingconcmax=\u6700\u5927\u540c\u6642\u63a5\u7d9a\u6570 [0: \u7121\u5236\u9650] MyTorrentsView.menu.exportmenu=\u66f8\u304d\u51fa\u3057 ConfigView.group.scrape=\u30b9\u30af\u30ec\u30a4\u30d7 ConfigView.section.tracker.client.scrapeinfo=\u30b9\u30af\u30ec\u30a4\u30d7\u3092\u505c\u6b62\u3059\u308b\u3068\u3001\u30c8\u30e9\u30c3\u30ab\u30fc\u306e\u5236\u5fa1\u306b\u5fc5\u8981\u306a\u30c7\u30fc\u30bf\u3092\u5f97\u3089\u308c\u306a\u304f\u306a\u308a\u307e\u3059\u3002 ConfigView.section.tracker.client.scrapeenable=\u30b9\u30af\u30ec\u30a4\u30d7\u3092\u884c\u3046 ConfigView.section.tracker.client.scrapestoppedenable=\u975e\u30a2\u30af\u30c6\u30a3\u30d6\u306e Torrent \u3092\u30b9\u30af\u30ec\u30a4\u30d7 Scrape.status.disabled=Scrape \u306f\u7121\u52b9 MyTorrentsView.menu.explore=\u30d5\u30a1\u30a4\u30eb\u3092\u8868\u793a MyTorrentsView.menu.explore._mac=Finder \u3067\u8868\u793a MyTorrentsView.menu.explore._windows=\u30a8\u30af\u30b9\u30d7\u30ed\u30fc\u30e9\u3067\u8868\u793a wizard.maketorrents.autohost=\u5185\u8535\u30c8\u30e9\u30c3\u30ab\u30fc\u3067 Torrent \u3092\u914d\u4fe1\u3059\u308b ConfigView.label.overrideip=\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u901a\u77e5\u3059\u308b IP \u30a2\u30c9\u30ec\u30b9\u3092\u500b\u5225\u306b\u6307\u5b9a\uff082 \u3064\u4ee5\u4e0a\u306e\u7570\u306a\u308b\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u304c\u3042\u308b\u5834\u5408\u3001';' \u533a\u5207\u308a\u3067\u5217\u6319\uff09 ConfigView.label.overrideip.tooltip=\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u30a2\u30af\u30bb\u30b9\u3057\u305f\u3082\u306e\u3068\u306f\u5225\u306e IP \u3092\u901a\u77e5\u3057\u307e\u3059\u3002\u4f7f\u308f\u306a\u3044\u5834\u5408\u306f\u7a7a\u767d\u306b\u3057\u3066\u304f\u3060\u3055\u3044 ConfigView.section.connection.group.networks=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af ConfigView.section.connection.group.networks.info=\u30c7\u30d5\u30a9\u30eb\u30c8\u3067 P2P \u8ee2\u9001\u3092\u8a31\u53ef\u3059\u308b\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 ConfigView.section.connection.networks.prompt=\u533f\u540d\u306e\u30c8\u30e9\u30c3\u30ab\u30fc\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u304c\u8ffd\u52a0\u3055\u308c\u308b\u969b\u306b\u305f\u305a\u306d\u308b ConfigView.section.connection.networks.Public=\u4e00\u822c\u306e IP \u30cd\u30c3\u30c8\u30ef\u30fc\u30af\uff08\u533f\u540d\u6027\u7121\u3057\uff09 ConfigView.section.connection.networks.I2P=I2P \u30cd\u30c3\u30c8\u30ef\u30fc\u30af ConfigView.section.connection.networks.Tor=The Onion Router \u30cd\u30c3\u30c8\u30ef\u30fc\u30af TableColumn.header.networks=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af TableColumn.header.networks.info=P2P \u63a5\u7d9a\u3092\u8a31\u53ef\u3055\u308c\u305f\u30cd\u30c3\u30c8\u30ef\u30fc\u30af Scrape.status.networkdisabled=Network \u304c\u6709\u52b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093 ConfigView.section.tracker.server.group.networks=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af ConfigView.section.tracker.server.group.networks.info=\u30c8\u30e9\u30c3\u30ab\u30fc\u304c\u30d4\u30a2\u3092\u53d7\u3051\u5165\u308c\u308b\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 window.networkselection.title=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u9078\u629e window.networkselection.info=\u4e0b\u306e\u30c8\u30e9\u30c3\u30ab\u30fc\u306f\u6b21\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u307e\u3059\u3002\n\u30c8\u30e9\u30c3\u30ab\u30fc\u3068\u30d4\u30a2\u306e\u901a\u4fe1\u3092\u6709\u52b9\u306b\u3059\u308b\u3042\u3081\u306b 1 \u3064\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\u533f\u540d\u30c8\u30e9\u30c3\u30ab\u30fc\u306e\u5834\u5408\u3001\u533f\u540d\u3068\u30d1\u30d6\u30ea\u30c3\u30af\u306a\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u4e21\u65b9\u3068\u306e\u901a\u4fe1\u304c\u53ef\u80fd\u306a\u30d1\u30d6\u30ea\u30c3\u30af\u306a\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u307e\u3059\u3002 window.networkselection.description=Torrent\uff1a plugins.basicview.clear=\u6d88\u53bb ConfigView.section.connection.group.peersources=\u30d4\u30a2\u306e\u30bd\u30fc\u30b9 ConfigView.section.connection.group.peersources.info=\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u8a31\u53ef\u3059\u308b\u30bd\u30fc\u30b9\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 ConfigView.section.connection.peersource.Tracker=\u30c8\u30e9\u30c3\u30ab\u30fc ConfigView.section.connection.peersource.DHT=\u5206\u6563\u30c8\u30e9\u30c3\u30ad\u30f3\u30b0 ConfigView.section.connection.peersource.PeerExchange=\u307b\u304b\u306e\u30d4\u30a2 ConfigView.section.connection.peersource.Plugin=\u30d7\u30e9\u30b0\u30a4\u30f3 ConfigView.section.connection.peersource.Incoming=\u5916\u90e8\u304b\u3089\u306e\u63a5\u7d9a PeersView.source=\u30bd\u30fc\u30b9 PeersView.source.info=\u3053\u306e\u30d4\u30a2\u306e\u30bd\u30fc\u30b9 TableColumn.header.peersources=\u30d4\u30a2\u306e\u30bd\u30fc\u30b9 TableColumn.header.peersources.info=\u30d4\u30a2\u63a5\u7d9a\u306e\u305f\u3081\u306e\u30d4\u30a2\u30bd\u30fc\u30b9 wizard.tracker.dht=\u5206\u6563\uff08Vuze \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u307f\uff09 MyTorrentsView.menu.advancedmenu=\u9ad8\u5ea6\u306a\u8a2d\u5b9a MyTorrentsView.menu.networks=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af MyTorrentsView.menu.peersource=\u30d4\u30a2\u306e\u30bd\u30fc\u30b9 ConfigView.section.sharing.permitdht=\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u63a5\u7d9a\u3067\u304d\u306a\u3044\u5834\u5408\u306b\u5206\u6563\u30c8\u30e9\u30c3\u30ad\u30f3\u30b0\u3092\u884c\u3046 ConfigView.section.sharing.protocol=\u5171\u6709\u30d7\u30ed\u30c8\u30b3\u30eb\uff1a PeersView.Messaging=\u30e1\u30c3\u30bb\u30fc\u30b8\u9001\u4fe1 PeersView.Messaging.info=\u62e1\u5f35\u30e1\u30c3\u30bb\u30fc\u30b8\u30f3\u30b0 API \u3092\u30b5\u30dd\u30fc\u30c8\u3057\u307e\u3059\u3002 ConfigView.label.queue.newseedsmovetop=\u3088\u308a\u65b0\u3057\u304f\u5b8c\u6210\u3057\u305f Torrent \u304c\u5148\u982d\u306b\u306a\u308b\u3088\u3046\u30b7\u30fc\u30c9\u30ea\u30b9\u30c8\u306b\u4e26\u3079\u308b ConfigView.label.seeding.firstPriority.ignore.info=\u3053\u308c\u3089\u306e\u30eb\u30fc\u30eb\u3092\u4f7f\u3063\u305f\u5834\u5408\u3001\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5b8c\u4e86\u5f8c\u3059\u3050\u306b\nTorrent \u304c\u505c\u6b62\u3059\u308b\u304b\u3082\u3057\u308c\u306a\u3044\u3053\u3068\u306b\u6ce8\u610f\u3057\u3066\u304f\u3060\u3055\u3044 ConfigView.label.seeding.firstPriority.ignore=\u6700\u512a\u5148\u306e\u30eb\u30fc\u30eb\u3092\u7121\u8996 ConfigView.label.seeding.firstPriority.ignoreSPRatio=\u30b7\u30fc\u30c9\uff0f\u30d4\u30a2\u6bd4\u304c\u6b21\u3092\u8d85\u3048\u308b\u5834\u5408 ConfigView.label.seeding.firstPriority.ignore0Peer=\u30d4\u30a2\u304c\u3044\u306a\u3044\u5834\u5408 ConfigView.section.tracker.sendjavaversionandos=OS \u3084 Java \u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u9001\u4fe1 MagnetPlugin.contextmenu.exporturi=\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u306b Magnet URI \u3092\u30b3\u30d4\u30fc ConfigView.section.plugins.dht=\u5206\u6563\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 dht.info=\u5206\u6563\u30c8\u30e9\u30c3\u30ad\u30f3\u30b0\u306a\u3069\u3092\u30b5\u30dd\u30fc\u30c8\u3059\u308b\u30d7\u30e9\u30b0\u30a4\u30f3\u3067\u3059\u3002\u7121\u52b9\u306b\u3059\u308b\u3068\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u52b9\u7387\u304c\u4f4e\u4e0b\u3057\u307e\u3059\u3002 dht.enabled=\u5206\u6563\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u6709\u52b9\u306b\u3059\u308b dht.portdefault=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30dd\u30fc\u30c8\u3092\u4f7f\u7528\u3059\u308b dht.port=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u7528 UDP \u30dd\u30fc\u30c8 dht.execute.command=\u8a3a\u65ad\u30b3\u30de\u30f3\u30c9 dht.execute.info=\u30b3\u30de\u30f3\u30c9\u5b9f\u884c dht.execute=\u5b9f\u884c dht.logging=\u52d5\u4f5c\u30c8\u30ec\u30fc\u30b9\u3092\u6709\u52b9\u306b\u3059\u308b ConfigView.section.plugins.dhttracker=\u5206\u6563\u30c8\u30e9\u30c3\u30ab\u30fc dhttracker.tracknormalwhenoffline=\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u63a5\u7d9a\u3067\u304d\u306a\u3044\u5834\u5408\u306b\u901a\u5e38\u306e Torrent \u3092\u30c8\u30e9\u30c3\u30af\u306e\u307f\u884c\u3046 ConfigView.section.file.nativedelete._mac=\u524a\u9664\u3057\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u30b4\u30df\u7bb1\u3078\u79fb\u52d5 ConfigView.section.file.nativedelete._windows=\u524a\u9664\u3057\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u3054\u307f\u7bb1\u3078\u79fb\u52d5 ConfigView.section.logging.generatediagnostics=\u751f\u6210 ConfigView.section.logging.netinfo=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u60c5\u5831\u3092\u751f\u6210 ConfigView.section.logging.statsinfo=\u7d71\u8a08\u60c5\u5831\u3092\u751f\u6210 ConfigView.section.logging.generatediagnostics.info=\u7d71\u8a08\u60c5\u5831\u3092\u751f\u6210\u3057\u3001\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u3068\u30ed\u30b0\u30d5\u30a1\u30a4\u30eb\u306b\u30b3\u30d4\u30fc\u3057\u307e\u3059 ConfigView.section.sharing.privatetorrent=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 Torrent\uff08\u30c8\u30e9\u30c3\u30ab\u30fc\u304b\u3089\u306e\u30d4\u30a2\u306e\u307f\u8a31\u53ef\uff09 MainWindow.menu.tools.nattest=NAT\uff0f\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u30c6\u30b9\u30c8 Button.apply=\u9069\u7528 Button.close=\u9589\u3058\u308b window.welcome.title=Vuze %1 \u30ea\u30ea\u30fc\u30b9\u30ce\u30fc\u30c8 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=\u30ea\u30ea\u30fc\u30b9\u30ce\u30fc\u30c8 dht.reseed.group=\u518d\u30b7\u30fc\u30c9 dht.reseed.ip=IP \u30a2\u30c9\u30ec\u30b9 dht.reseed.port=\u30dd\u30fc\u30c8 dht.reseed=\u518d\u30b7\u30fc\u30c9 dht.reseed.info=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u518d\u30b7\u30fc\u30c9 dht.diagnostics.group=\u7d71\u8a08\u60c5\u5831 DHTView.title.full=\u5206\u6563\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 DHTView.title.fullcvs=\u5206\u6563\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 CVS DHTView.general.title=\u4e00\u822c DHTView.general.uptime=\u5b9f\u884c\u6642\u9593\uff1a DHTView.general.users=\u30e6\u30fc\u30b6\uff1a DHTView.general.nodes=\u30ce\u30fc\u30c9\uff1a DHTView.general.leaves=\u6b8b\u308a\uff1a DHTView.general.contacts=\u63a5\u7d9a\uff1a DHTView.general.replacements=\u7f6e\u63db\uff1a DHTView.general.live=\u30a2\u30af\u30c6\u30a3\u30d6\uff1a DHTView.general.unknown=\u4e0d\u660e\uff1a DHTView.general.dying=\u975e\u30a2\u30af\u30c6\u30a3\u30d6\uff1a DHTView.transport.title=\u8ee2\u9001\u306e\u8a73\u7d30 DHTView.transport.packets=\u30d1\u30b1\u30c3\u30c8 DHTView.transport.received=\u53d7\u4fe1\u6e08 DHTView.transport.sent=\u9001\u4fe1\u6e08 DHTView.transport.in=In\uff1a DHTView.transport.out=Out\uff1a DHTView.operations.title=\u64cd\u4f5c\u306e\u8a73\u7d30 DHTView.operations.sent=\u9001\u4fe1\u6e08 DHTView.operations.ok=OK DHTView.operations.failed=\u5931\u6557 DHTView.operations.received=\u53d7\u4fe1\u6e08 DHTView.operations.findNode=\u30ce\u30fc\u30c9\u3092\u691c\u7d22 DHTView.operations.findValue=\u5024\u3092\u691c\u7d22 DHTView.operations.store=\u30b9\u30c8\u30a2 DHTView.activity.title=\u72b6\u614b DHTView.activity.status=\u30b9\u30c6\u30fc\u30bf\u30b9 DHTView.activity.status.true=\u30ad\u30e5\u30fc\u6e08 DHTView.activity.status.false=\u5b9f\u884c\u4e2d DHTView.activity.type=\u7a2e\u985e DHTView.activity.type.1=\u5185\u90e8 Get DHTView.activity.type.2=\u5916\u90e8 Get DHTView.activity.type.3=\u5185\u90e8 Put DHTView.activity.type.4=\u5916\u90e8 Put DHTView.activity.target=\u30bf\u30fc\u30b2\u30c3\u30c8 DHTView.activity.details=\u8a73\u7d30 DHTView.db.title=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 DHTView.db.keys=\u30ad\u30fc DHTView.db.values=\u5024 DHTView.db.local=\u30ed\u30fc\u30ab\u30eb DHTView.db.direct=\u76f4\u63a5 DHTView.db.indirect=\u9593\u63a5 MainWindow.dht.status.tooltip=\u5206\u6563\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u5b9f\u884c\u4e2d\u306e\u5834\u5408\u3001\u73fe\u5728\u30aa\u30f3\u30e9\u30a4\u30f3\u306e\u30e6\u30fc\u30b6\u6570\u304c\u8868\u793a\u3055\u308c\u307e\u3059\u3002 MainWindow.dht.status.disabled=DHT \u7121\u52b9 MainWindow.dht.status.failed=DHT \u5931\u6557 MainWindow.dht.status.initializing=DHT \u521d\u671f\u5316\u4e2d MainWindow.dht.status.users=%1 \u4eba MainWindow.dht.status.unreachable=DHT \u5230\u9054\u4e0d\u80fd MainWindow.dht.status.unreachabletooltip=\u5206\u6563\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e UDP \u30dd\u30fc\u30c8\u30de\u30c3\u30d4\u30f3\u30b0\uff08NAT/\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\uff09\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3059\u3002 MyTorrentsView.menu.setUpSpeed=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6\u3092\u8a2d\u5b9a MyTorrentsView.menu.setDownSpeed=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6\u3092\u8a2d\u5b9a ConfigView.section.tracker.client.showwarnings=\u30c8\u30e9\u30c3\u30ab\u30fc\u304b\u3089\u306e\u8b66\u544a\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u8868\u793a dht.advanced=\u9ad8\u5ea6\u306a\u8a2d\u5b9a\u3092\u884c\u3046 dht.advanced.group=\u9ad8\u5ea6\u306a\u8a2d\u5b9a dht.advanced.label=\u5341\u5206\u77e5\u8b58\u3092\u304a\u6301\u3061\u306e\u65b9\u4ee5\u5916\u306f\u3053\u308c\u3089\u306e\u5024\u3092\u5909\u66f4\u3057\u306a\u3044\u3067\u304f\u3060\u3055\u3044\u3002 dht.override.ip=\u5916\u90e8 IP \u30a2\u30c9\u30ec\u30b9\u3092\u500b\u5225\u306b\u8a2d\u5b9a ConfigView.section.logging.loggerenable=\u30ed\u30b0\u3092\u4fdd\u5b58 ConfigView.section.ipfilter.blockbanning=\u6b21\u306e\u500b\u6570\u3092\u30d6\u30ed\u30c3\u30af\u3057\u305f\u5834\u5408\u3001256 \u500b\u3059\u3079\u3066\u306e\u30a2\u30c9\u30ec\u30b9\u3092\u30d6\u30ed\u30c3\u30af MyTrackerView.passive=\u30d1\u30c3\u30b7\u30d6 TableColumn.header.swarm_average_speed=Swarm \u5e73\u5747\u901f\u5ea6 TableColumn.header.swarm_average_speed.info=Swarm \u4e2d\u306e\u30d4\u30a2\u306e\u5e73\u5747\u901f\u5ea6 TableColumn.header.comment=\u30b3\u30e1\u30f3\u30c8 TableColumn.header.comment.info=\u30e6\u30fc\u30b6\u304c\u5165\u529b\u3057\u305f\u30b3\u30e1\u30f3\u30c8 TableColumn.header.commenticon=\u30b3\u30e1\u30f3\u30c8\u30a2\u30a4\u30b3\u30f3 TableColumn.header.commenticon.info=\u30e6\u30fc\u30b6\u30b3\u30e1\u30f3\u30c8\u304c\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u3068\u304d\u30a2\u30a4\u30b3\u30f3\u3092\u8868\u793a MyTrackerView.category=\u30ab\u30c6\u30b4\u30ea MainWindow.menu.file.open.torrentfortracking=Torrent \u30d5\u30a1\u30a4\u30eb...\uff08\u30c8\u30e9\u30c3\u30ad\u30f3\u30b0\u306e\u307f\uff09 MyTrackerView.date_added=\u8ffd\u52a0\u6e08 ConfigView.section.tracker.portbackup=\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30dd\u30fc\u30c8\uff08':' \u533a\u5207\u308a\uff09 ConfigView.label.playfilespeech=\u30d5\u30a1\u30a4\u30eb\u5b8c\u6210\u6642\u306b\u97f3\u58f0\u3067\u77e5\u3089\u305b\u308b ConfigView.label.playfilespeech.info=\u73fe\u5728\u3053\u306e\u6a5f\u80fd\u306f\u82f1\u8a9e\u3067\u306e\u307f\u52d5\u4f5c\u3057\u307e\u3059 ConfigView.label.playfilefinished=\u30d5\u30a1\u30a4\u30eb\u5b8c\u6210\u6642\u306b\u30b5\u30a6\u30f3\u30c9\u3092\u9cf4\u3089\u3059 ConfigView.label.backupconfigfiles=\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u3092\u30d0\u30c3\u30af\u30a2\u30c3\u30d7 ConfigView.section.tracker.client.scrapesingleonly=\u30c8\u30e9\u30c3\u30ab\u30fc\u3054\u3068\u306e\u30b9\u30af\u30ec\u30a4\u30d7\u3092\u7121\u52b9\u306b\u3059\u308b\uff08'URL too long' (414) \u30a8\u30e9\u30fc\u3092\u8fd4\u3059\u5834\u5408\u306b\u6709\u52b9\u3067\u3059\uff09 dht.ipfilter.log=IP \u30d5\u30a3\u30eb\u30bf\u306b\u5408\u81f4\u3057\u305f\u5834\u5408\u306b\u30ed\u30b0\u306b\u8a18\u9332 MyTorrentsView.menu.movemenu=\u30d5\u30a1\u30a4\u30eb\u3092\u79fb\u52d5 MyTorrentsView.menu.movedata=\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u3092\u79fb\u52d5... MyTorrentsView.menu.movetorrent=Torrent \u30d5\u30a1\u30a4\u30eb\u3092\u79fb\u52d5... MyTorrentsView.menu.movedata.dialog=\u65b0\u3057\u3044\u5834\u6240\u3092\u9078\u629e DHTView.operations.data=\u30c7\u30fc\u30bf DHTView.general.reachable=\u5230\u9054\u53ef\u80fd\uff1a DHTView.general.rendezvous=Rendezvous\uff1a ConfigView.label.queue.maxactivetorrentswhenseeding=\u30b7\u30fc\u30c9\u306e\u307f\u306e\u5834\u5408\u306e\u6700\u5927\u30a2\u30af\u30c6\u30a3\u30d6\u6570 [0: \u7121\u5236\u9650] Views.plugins.IRC.title=IRC - \u30aa\u30f3\u30e9\u30a4\u30f3\u6280\u8853\u30b5\u30dd\u30fc\u30c8 Formats.units.alot=\u5927\u304d\u3059\u304e\u307e\u3059\uff01 ConfigView.section.ipfilter.persistblocking=\u518d\u8d77\u52d5\u5f8c\u3082\u30d6\u30ed\u30c3\u30af\u3057\u305f IP \u306e\u8a73\u7d30\u3092\u4fdd\u6301 FilesView.menu.rename=\u540d\u524d\u3092\u5909\u66f4\u3059\u308b\u304b\u5225\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e FilesView.menu.rename_only=\u540d\u524d\u3092\u5909\u66f4 FilesView.menu.retarget=\u5225\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e FilesView.rename.choose.path=\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 FilesView.rename.choose.path.dir=\u30d5\u30a9\u30eb\u30c0\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 FilesView.rename.confirm.delete.title=\u524a\u9664\u6642\u306b\u78ba\u8a8d FilesView.rename.confirm.delete.text=\u30aa\u30ea\u30b8\u30ca\u30eb\u306e\u30d5\u30a1\u30a4\u30eb %1 \u306e\u524a\u9664\u6642\u306b\u78ba\u8a8d FilesView.rename.filename.title=\u30d5\u30a1\u30a4\u30eb\u540d\u3092\u5909\u66f4 FilesView.rename.filename.text=\u30d5\u30a1\u30a4\u30eb\u540d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044 ConfigView.higher.mode.available=\u3053\u308c\u3089\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u4e0a\u7d1a\u30e6\u30fc\u30b6\u306e\u307f\u8a2d\u5b9a\u53ef\u80fd\u3067\u3059\u3002 ConfigView.section.mode=\u30e2\u30fc\u30c9 ConfigView.section.mode.title=\u30e6\u30fc\u30b6\u306e\u30ec\u30d9\u30eb ConfigView.section.mode.beginner=\u521d\u5fc3\u8005 ConfigView.section.mode.beginner.wiki.definitions=BitTorrent \u7528\u8a9e\u96c6 ConfigView.section.mode.intermediate=\u4e2d\u7d1a\u8005 ConfigView.section.mode.intermediate.wiki.host=\u30d5\u30a1\u30a4\u30eb\u3092\u914d\u4fe1\u3059\u308b ConfigView.section.mode.intermediate.wiki.publish=\u30d5\u30a1\u30a4\u30eb\u3092\u516c\u958b\u3059\u308b ConfigView.section.mode.advanced=\u4e0a\u7d1a\u8005 ConfigView.section.mode.advanced.wiki.main=Wiki \u30e1\u30a4\u30f3\u30da\u30fc\u30b8 ConfigView.section.mode.beginner.text=Torrent \u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u3060\u3051\u306e\u65b9\u306f\u3053\u306e\u30e2\u30fc\u30c9\u3092\u304a\u4f7f\u3044\u304f\u3060\u3055\u3044\u3002 ConfigView.section.mode.intermediate.text=\u30c8\u30e9\u30c3\u30ab\u30fc\u6a5f\u80fd\u304c\u5fc5\u8981\u306a\u65b9\u5411\u3051\u3002\u30c8\u30e9\u30c3\u30ab\u30fc\u3092\u7acb\u3066\u3066\u30d5\u30a1\u30a4\u30eb\u3092\u914d\u4fe1\uff0f\u516c\u958b\u3057\u305f\u3044\u65b9\u306f\u3053\u306e\u30e2\u30fc\u30c9\u3092\u304a\u4f7f\u3044\u304f\u3060\u3055\u3044\u3002 ConfigView.section.mode.advanced.text=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u8a2d\u5b9a\u304c\u5fc5\u8981\u306a\u65b9\u5411\u3051\u3002MTU \u3084\u975e\u30d6\u30ed\u30c3\u30ad\u30f3\u30b0 I/O \u306a\u3069\u3092\u8abf\u6574\u3057\u305f\u3044\u65b9\u306f\u3053\u306e\u30e2\u30fc\u30c9\u3092\u304a\u4f7f\u3044\u304f\u3060\u3055\u3044\u3002 Files.column.storagetype=\u30b9\u30c8\u30ec\u30fc\u30b8\u306e\u7a2e\u985e Files.column.fileext=\u7a2e\u985e FileItem.storage.linear=\u30ea\u30cb\u30a2 FileItem.storage.compact=\u30b3\u30f3\u30d1\u30af\u30c8 MessageBoxWindow.rememberdecision=\u9078\u629e\u5185\u5bb9\u3092\u8a18\u61b6 ConfigView.section.interface.cleardecisions=\u30c0\u30a4\u30a2\u30ed\u30b0\u306e\u5c65\u6b74\u3092\u6d88\u53bb ConfigView.section.interface.cleardecisionsbutton=\u6d88\u53bb ConfigView.section.interface.cleartrackers=\u30c8\u30e9\u30c3\u30ab\u30fc\u306e\u5c65\u6b74\u3092\u6d88\u53bb ConfigView.section.interface.cleartrackersbutton=\u6d88\u53bb ConfigView.section.interface.clearsavepaths=\u4fdd\u5b58\u5148\u306e\u5c65\u6b74\u3092\u6d88\u53bb ConfigView.section.interface.clearsavepathsbutton=\u6d88\u53bb configureWizard.welcome.usermodes=\u3053\u306e\u9805\u76ee\u306f \u30c4\u30fc\u30eb\uff1e\u30aa\u30d7\u30b7\u30e7\u30f3 \u306b\u8868\u793a\u3059\u308b\u5185\u5bb9\u3092\u5909\u66f4\u3057\u307e\u3059\u3002\u304a\u4f7f\u3044\u306e\u30ec\u30d9\u30eb\u306b\u3042\u308f\u305b\u3066\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 FilesView.skip.confirm.delete.text=%1' \u3092\u5207\u308a\u8a70\u3081\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f FilesView.rename.failed.title=\u540d\u524d\u306e\u5909\u66f4\uff0f\u30bf\u30fc\u30b2\u30c3\u30c8\u5909\u66f4\u306b\u5931\u6557 FilesView.rename.failed.text=\u64cd\u4f5c\u306f\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u5bfe\u8c61\u304c\u6b63\u3057\u304f\u9078\u629e\u3055\u308c\u3066\u3044\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059 diagnostics.log_found=Vuze \u306f\u524d\u56de\u6b63\u5e38\u306b\u7d42\u4e86\u3057\u307e\u305b\u3093\u3067\u3057\u305f\u3002diagnostic log files \u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u8a73\u7d30\u306f wiki \u30da\u30fc\u30b8 Vuze Disappears \u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002 ManagerItem.paused=\u4e00\u6642\u505c\u6b62 Utils.link.visit=Web \u30b5\u30a4\u30c8 ConfigView.section.connection.serverport.wiki=\u9069\u5207\u306a\u30dd\u30fc\u30c8\u3092\u9078\u629e\u3059\u308b ConfigView.section.transfer.speeds.wiki=\u9069\u5207\u306a\u901f\u5ea6\u8a2d\u5b9a installPluginsWizard.installMode.info.title=\u60c5\u5831 installPluginsWizard.installMode.info.text=\u30d7\u30e9\u30b0\u30a4\u30f3\u306f Vuze \u306e\u52d5\u4f5c\u3055\u305b\u308b\u4e0a\u3067\u306f\u5fc5\u9808\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u304c\u3001\u81ea\u52d5\u5316\u30fb\u30ea\u30e2\u30fc\u30c8\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\u306a\u3069\u306e\u6a5f\u80fd\u3092\u8ffd\u52a0\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\n\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u524d\u306b\u8aac\u660e\u3092\u304a\u8aad\u307f\u304f\u3060\u3055\u3044\u3002\n\u307b\u3068\u3093\u3069\u306e\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u5b89\u5168\u3067\u3001\u304a\u4f7f\u3044\u306e\u8a2d\u5b9a\u3092\u4e0a\u66f8\u304d\u3059\u308b\u3053\u3068\u3082\u3042\u308a\u307e\u305b\u3093\u3002 Views.plugins.Distributed.DB.title=\u5206\u6563 DB Views.plugins.Distributed.Tracker.title=\u5206\u6563\u30c8\u30e9\u30c3\u30ab\u30fc Views.plugins.Plugin.Update.title=\u30d7\u30e9\u30b0\u30a4\u30f3\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8 Views.plugins.UPnP.title.tooltip=\u30e6\u30cb\u30d0\u30fc\u30b5\u30eb\u30d7\u30e9\u30b0\u30a2\u30f3\u30c9\u30d7\u30ec\u30a4 openUrl.url.info=http, https, magnet \u3084 raw hex \u30a4\u30f3\u30d5\u30a9\u30cf\u30c3\u30b7\u30e5\u6587\u5b57\u5217\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u3059 TableColumn.header.swarm_average_completion=\u5e73\u5747\u30d4\u30a2\u5b8c\u4e86\u7387 TableColumn.header.swarm_average_completion.info=Swarm \u4e2d\u306e\u30d4\u30a2\u306e\u5e73\u5747\u5b8c\u4e86\u7387 GeneralView.label.swarm_average_completion=\u5e73\u5747\u5b8c\u4e86\u7387\uff1a GeneralView.label.swarm_average_completion.tooltip=Swarm \u4e2d\u306e\u30d4\u30a2\u306e\u5e73\u5747\u5b8c\u4e86\u7387 MainWindow.nat.status.tooltip.unknown=\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\uff0fNAT \u306e\u5230\u9054\u6027\u306f\u4e0d\u660e (TCP) MainWindow.nat.status.tooltip.ok=\u5230\u9054\u6027 OK (TCP) MainWindow.nat.status.tooltip.probok=\u5230\u9054\u6027\u306f OK \u3067\u3059\u304c\u3001\u73fe\u5728 TCP \u63a5\u7d9a\u306f\u3042\u308a\u307e\u305b\u3093 MainWindow.nat.status.tooltip.bad=\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\uff0fNAT (TCP) \u306e\u5230\u9054\u6027\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3059\u3002\u8a73\u3057\u304f\u306f Wiki \u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 plugin.installer.recommended.plugin=\u63a8\u5968\u30d7\u30e9\u30b0\u30a4\u30f3 - \u5fc5\u8981\u306b\u5fdc\u3058\u3066\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u3066\u304f\u3060\u3055\u3044 LoggerView.pause=\u30ed\u30b0\u8a18\u9332\u3092\u4e00\u6642\u505c\u6b62 LoggerView.clear=\u6d88\u53bb LoggerView.filter=\u30d5\u30a3\u30eb\u30bf LoggerView.filter.uncheckAll=\u3059\u3079\u3066\u306e\u9805\u76ee\u3092\u89e3\u9664 LoggerView.filter.checkAll=\u3059\u3079\u3066\u3092\u9805\u76ee\u3092\u9078\u629e LoggerView.loggingDisabled=\u30ed\u30b0\u8a18\u9332\u306f\u6709\u52b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 LoggerView.includeOnly=\u6b21\u306e\u6b63\u898f\u8868\u73fe\u306b\u30de\u30c3\u30c1\u3059\u308b\u884c\u306e\u307f\u3092\u8868\u793a\uff1a LoggerView.excludeAll=\u6b21\u306e\u6b63\u898f\u8868\u73fe\u306b\u30de\u30c3\u30c1\u3059\u308b\u884c\u3092\u8868\u793a\u3057\u306a\u3044\uff1a ConfigView.section.logging.log0type=\u60c5\u5831 ConfigView.section.logging.log1type=\u8b66\u544a ConfigView.section.logging.log2type=\u30a8\u30e9\u30fc ConfigView.section.logging.filter=\u8a18\u9332\u3059\u308b\u30ed\u30b0\u3092\u30d5\u30a3\u30eb\u30bf ConfigView.section.logging.level=\u30ed\u30b0\u30ec\u30d9\u30eb ConfigView.section.logging.showLogsFor=\u6b21\u306e\u30ab\u30c6\u30b4\u30ea\u306b\u5408\u81f4\u3059\u308b %1 \u306e\u30ed\u30b0\u3092\u8868\u793a\uff1a ConfigView.pluginlist.column.type=\u7a2e\u985e ConfigView.pluginlist.column.type.perUser=\u30e6\u30fc\u30b6 ConfigView.pluginlist.column.type.shared=\u5171\u6709 ConfigView.pluginlist.column.type.builtIn=\u5185\u8535 ConfigView.pluginlist.column.name=\u540d\u524d ConfigView.pluginlist.column.version=\u30d0\u30fc\u30b8\u30e7\u30f3 ConfigView.pluginlist.column.directory=\u30d5\u30a9\u30eb\u30c0 ConfigView.pluginlist.column.isOperational=\u64cd\u4f5c\u53ef\u80fd\uff1f PeersView.BlockView.Avail.Have=\u4e21\u8005\u3068\u3082\u6240\u6709 PeersView.BlockView.Avail.NoHave=\u30d4\u30a2\u306e\u307f\u6240\u6709 PeersView.BlockView.NoAvail.Have=\u3042\u306a\u305f\u306e\u307f\u6240\u6709 PeersView.BlockView.NoAvail.NoHave=\u4e21\u8005\u3068\u3082\u672a\u6240\u6709 PeersView.BlockView.Transfer=\u8ee2\u9001\u4e2d PeersView.BlockView.NextRequest=\u6b21\u306e\u8981\u6c42 PeersView.BlockView.title=\u30d4\u30fc\u30b9\u30de\u30c3\u30d7 PeersView.BlockView.AvailCount=\u6709\u52b9\u6570 MyTorrentsView.menu.manual=\u624b\u52d5... MyTorrentsView.menu.manual.per_torrent=\u624b\u52d5\uff08Torrent \u3054\u3068\uff09 MyTorrentsView.menu.manual.shared_torrents=\u624b\u52d5\uff08Torrent \u5171\u6709\uff09 # %1 = "in kbps" or ""; %2 = "upload" or "download" OpenTorrentWindow.torrentLocation=Torrent \u30d5\u30a1\u30a4\u30eb\uff1a OpenTorrentWindow.addFiles.URL=URL \u3092\u8ffd\u52a0 OpenTorrentWindow.addFiles.Folder=\u30d5\u30a9\u30eb\u30c0\u3092\u8ffd\u52a0 OpenTorrentWindow.addFiles.Clipboard=\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u304b\u3089\u8ffd\u52a0 OpenTorrentWindow.changeDestination=\u4fdd\u5b58\u5148\u3092\u5909\u66f4 OpenTorrentWindow.fileList=Torrent \u5185\u306e\u30d5\u30a1\u30a4\u30eb\uff1a OpenTorrentWindow.torrentTable.name=\u540d\u524d OpenTorrentWindow.torrentTable.saveLocation=\u4fdd\u5b58\u5148 OpenTorrentWindow.fileTable.fileName=\u30d5\u30a1\u30a4\u30eb\u540d OpenTorrentWindow.fileTable.size=\u30b5\u30a4\u30ba OpenTorrentWindow.fileTable.destinationName=\u914d\u5e03\u5148 OpenTorrentWindow.startMode.seeding=\u30b7\u30fc\u30c9\u4e2d OpenTorrentWindow.fileList.changeDestination=\u4fdd\u5b58\u5148\u3092\u5909\u66f4 OpenTorrentWindow.mb.badSize.title=\u4e92\u63db\u6027\u306e\u7121\u3044\u30d5\u30a1\u30a4\u30eb OpenTorrentWindow.mb.badSize.text=%1 \u306f %2 \u3067\u306f\u306a\u3044\u305f\u3081\u30b7\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093 OpenTorrentWindow.mb.alreadyExists.text=Torrent %1 \u306f %2 \u306b\u65e2\u306b\u8ffd\u52a0\u3055\u308c\u3066\u3044\u307e\u3059 OpenTorrentWindow.mb.alreadyExists.title=Torrent \u304c\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059 OpenTorrentWindow.mb.openError.title=\u30aa\u30fc\u30d7\u30f3\u30a8\u30e9\u30fc OpenTorrentWindow.mb.openError.text=%1 \u3092\u958b\u304f\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 OpenTorrentWindow.torrent.remove=\u4e00\u89a7\u304b\u3089 Torrent \u3092\u524a\u9664 OpenTorrentWindow.torrent.options=\u6b21\u306e\u8a2d\u5b9a\u306f\u4e0b\u8a18\u3067\u9078\u629e\u3055\u308c\u305f Torrent \u306b\u9069\u7528\u3055\u308c\u307e\u3059\uff1a OpenTorrentWindow.xOfTotal=(%1 / %2) iconBar.open.tooltip=Torrent \u3092\u958b\u304d\u307e\u3059 LocaleUtil.column.text=\u4e0d\u660e\u306a\u30c6\u30ad\u30b9\u30c8 Tracker.tooltip.MultiSupport=\u3053\u306e\u30c8\u30e9\u30c3\u30ab\u30fc\u306f\u30ea\u30af\u30a8\u30b9\u30c8\u3054\u3068\u306e\u591a\u91cd\u30b9\u30af\u30ec\u30a4\u30d7\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u307e\u3059\u3002 Tracker.tooltip.NoMultiSupport=\u3053\u306e\u30c8\u30e9\u30c3\u30ab\u30fc\u306f\u30ea\u30af\u30a8\u30b9\u30c8\u3054\u3068\u306e\u591a\u91cd\u30b9\u30af\u30ec\u30a4\u30d7\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u307e\u305b\u3093\u3002 ConfigView.label.lazybitfield=\u9045\u5ef6\u30d3\u30c3\u30c8\u30d5\u30a3\u30fc\u30eb\u30c9\u3092\u4f7f\u7528\uff08\u30d3\u30c3\u30c8\u30d5\u30a3\u30fc\u30eb\u30c9\u30d9\u30fc\u30b9\u306e\u30d6\u30ed\u30c3\u30ad\u30f3\u30b0\u3092\u884c\u3046\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u4e0a\u3067\u30b7\u30fc\u30c9\u3059\u308b\u969b\u306b\u6709\u52b9\u3067\u3059\uff09 LoggerView.realtime=\u30ea\u30a2\u30eb\u30bf\u30a4\u30e0\u3067\u66f4\u65b0 ConfigView.section.file.perf.cache.flushpieces=\u5b8c\u6210\u3057\u305f\u30d4\u30fc\u30b9\u3092\u5373\u5ea7\u306b\u30c7\u30a3\u30b9\u30af\u306b\u66f8\u304d\u8fbc\u3080\uff08\u3053\u306e\u30e2\u30fc\u30c9\u3067\u306f\u30c7\u30a3\u30b9\u30af\u66f8\u304d\u8fbc\u307f\u304c\u5897\u3048\u307e\u3059\uff09 ConfigView.section.file.writemblimit=\u66f8\u304d\u8fbc\u307f\u8981\u6c42\u30ad\u30e5\u30fc\u306e\u4e0a\u9650 (%1) ConfigView.section.file.writemblimit.explain=\u30c7\u30a3\u30b9\u30af\u3078\u306e\u66f8\u304d\u8fbc\u307f\u304c\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3088\u308a\u3082\u9045\u3044\u5834\u5408\u3001\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6\u304c\u843d\u3061\u308b\u524d\u306b\u30ad\u30e5\u30fc\u30a4\u30f3\u30b0\u3059\u308b\u30c7\u30fc\u30bf\u3092\u5236\u9650\u3057\u307e\u3059 ConfigView.section.file.readmblimit=\u8aad\u307f\u51fa\u3057\u8981\u6c42\u30ad\u30e5\u30fc\u306e\u4e0a\u9650 (%1) ConfigView.section.file.readmblimit.explain=\u8aad\u307f\u51fa\u3057\u51e6\u7406\u3092\u4fdd\u7559\u3059\u308b\u306e\u306b\u4f7f\u7528\u3059\u308b\u30e1\u30e2\u30ea\u3092\u5236\u9650\u3057\u307e\u3059 Button.moveUp=\u4e0a\u3078 Button.moveDown=\u4e0b\u3078 ConfigView.notAvailableForMode=\u3053\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u306f%1\u30e2\u30fc\u30c9\u4ee5\u4e0a\u3067\u306e\u307f\u5229\u7528\u3067\u304d\u307e\u3059\u3002%2\u30e2\u30fc\u30c9\u3067\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 health.explain.error=\u3053\u306e Torrent \u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u30b9\u30c6\u30fc\u30bf\u30b9\u306e\u9805\u76ee\u307e\u305f\u306f\u30a8\u30e9\u30fc\u306e\u30a2\u30a4\u30b3\u30f3\u306e\u30c4\u30fc\u30eb\u30c1\u30c3\u30d7\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 GeneralView.label.trackerscrapeupdate=\u30c8\u30e9\u30c3\u30ab\u30fc\u3092\u30b9\u30af\u30ec\u30a4\u30d7 PeersView.piece=\u30d4\u30fc\u30b9 PeersView.piece.info=\u3053\u306e\u30d4\u30a2\u304b\u3089\u8981\u6c42\u3055\u308c\u305f\u6700\u5f8c\u306e\u30d4\u30fc\u30b9 No. PiecesView.priority=\u512a\u5148\u5ea6 PiecesView.priority.info=\u3053\u306e\u30d4\u30fc\u30b9\u306e\u512a\u5148\u5ea6\u3002\u6ce8\u610f\u3092\u6255\u3046\u5fc5\u8981\u306f\u3042\u308a\u307e\u305b\u3093 PiecesView.speed=\u901f\u5ea6 PiecesView.speed.info=\u9045\u3044\u30d4\u30a2\u306f\u30d4\u30fc\u30b9\u306e\u9ad8\u901f\u306a\u8ee2\u9001\u3092\u59a8\u3052\u307e\u3059 TableColumn.header.AvgAvail.info=\u6709\u52b9\u306a\u30d4\u30fc\u30b9\u306e\u7dcf\u548c\u3092\u30d4\u30fc\u30b9\u3068\u63a5\u7d9a\u6570\u3067\u5272\u3063\u305f\u5024 TableColumn.header.AvgAvail=\u5e73\u5747 \u6709\u52b9\u6570/\u30d4\u30fc\u30b9 ConfigView.label.strictfilelocking=\u5e38\u306b\u6392\u4ed6\u7684\u30d5\u30a1\u30a4\u30eb\u66f8\u304d\u8fbc\u307f\u30ed\u30c3\u30af\u3092\u884c\u3046 MyTorrentsView.menu.checkfilesexist=\u30d5\u30a1\u30a4\u30eb\u306e\u6709\u7121\u3092\u78ba\u8a8d MyTorrentsView.menu.rescanfile=\u5b9a\u671f\u7684\u306b\u672a\u5b8c\u6210\u306e\u30d4\u30fc\u30b9\u3092\u518d\u30c1\u30a7\u30c3\u30af MyTorrentsView.menu.clear_resume_data=\u30ec\u30b8\u30e5\u30fc\u30e0\u30c7\u30fc\u30bf\u3092\u6d88\u53bb Plugin.extseed.name=\u5916\u90e8\u30b7\u30fc\u30c9 Plugin.localtracker.info=LAN Peer Finder \u3092\u4f7f\u3046\u3068\u901a\u5e38\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306b\u52a0\u3048\u3066\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u306e\u5185\u5074\u306b Vuze \u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u69cb\u7bc9\u3067\u304d\u307e\u3059\u3002\n\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u306e\u5185\u5074\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u540c\u58eb\u3067\u76f4\u63a5\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u884c\u3048\u307e\u3059\u3002 Plugin.localtracker.enable=\u6709\u52b9 azinstancehandler.alert.portclash=LAN \u4e0a\u3067\u30dd\u30fc\u30c8\u756a\u53f7\u306e\u885d\u7a81\u3092\u691c\u77e5\u3057\u307e\u3057\u305f: %1 \u306f\u307b\u304b\u306e Vuze \u30e6\u30fc\u30b6\u306b\u3088\u3063\u3066\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u5225\u306e\u4e00\u610f\u306a\u30dd\u30fc\u30c8 (TCP/UDP %2 \u301c %3) \u3092\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002 ConfigView.section.transfer.lan.tooltip=LAN \u56fa\u6709\u306e\u8a2d\u5b9a ConfigView.section.transfer.lan.uploadrate=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 (KB/s) [0: \u7121\u5236\u9650] ConfigView.section.transfer.lan.uploadrate.tooltip=\u540c\u3058 LAN \u306b\u63a5\u7d9a\u3055\u308c\u305f\u30d4\u30a2\u306b\u306f\u901a\u5e38\u3068\u306f\u5225\u306e\u4e0a\u9650\u5024\u304c\u9069\u7528\u3055\u308c\u307e\u3059\u3002 ConfigView.section.transfer.lan.downloadrate=\u6700\u5927\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6 (KB/s) [0: \u7121\u5236\u9650] ConfigView.section.transfer.lan.downloadrate.tooltip=\u540c\u4e00 LAN \u306b\u63a5\u7d9a\u3055\u308c\u3066\u3044\u308b\u30d4\u30a2\u306b\u306f\u901a\u5e38\u3068\u306f\u5225\u306e\u4e0a\u9650\u5024\u304c\u9069\u7528\u3055\u308c\u307e\u3059\u3002 TorrentOptionsView.title.short=\u74b0\u5883\u8a2d\u5b9a TorrentOptionsView.title.full=\u74b0\u5883\u8a2d\u5b9a TorrentOptionsView.param.max.peers=\u6700\u5927\u63a5\u7d9a\u6570 [0: \u7121\u5236\u9650] ConfigView.section.connection.encryption.require_encrypted_transport=\u63a5\u7d9a\u3092\u6697\u53f7\u5316 ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=\u307b\u304b\u306e\u30d4\u30a2\u3068\u306e\u63a5\u7d9a\u3092\u5f37\u5236\u7684\u306b\u6697\u53f7\u5316\u3057\u307e\u3059 ConfigView.section.connection.encryption.min_encryption_level=\u6700\u4f4e\u306e\u6697\u53f7\u5316\u5f37\u5ea6 ConfigView.section.connection.encryption.min_encryption_level.tooltip=\u30d7\u30ec\u30fc\u30f3 - \u30cf\u30f3\u30c9\u30b7\u30a7\u30fc\u30af\u306e\u307f\nRC4 - \u30b9\u30c8\u30ea\u30fc\u30e0\u5168\u4f53\n\u9ad8\u3044\u6697\u53f7\u5316\u5f37\u5ea6\u306f\u3088\u308a CPU \u3092\u5fc5\u8981\u3068\u3057\u307e\u3059 Peers.column.Encryption=\u6697\u53f7\u5316 Peers.column.Encryption.info=\u4f7f\u7528\u4e2d\u306e\u6697\u53f7\u5316\u5f37\u5ea6 ConfigView.section.connection.encryption.encrypt.info=\u6697\u53f7\u5316\u3092\u884c\u3046\u3068\u4e92\u63db\u6027\u306e\u7121\u3044\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3068\u901a\u4fe1\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002 ConfigView.section.connection.encryption.encrypt.info.link=\u8a73\u3057\u304f\u306f\u3053\u3061\u3089\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044 MainWindow.sr.status.tooltip.ok=\u25cb\uff1a\u8ca0\u62c5\u7387 0.9 \u4ee5\u4e0a (%1) MainWindow.sr.status.tooltip.poor=\u25b3\uff1a\u8ca0\u62c5\u7387 0.9 \u672a\u6e80 (%1) MainWindow.sr.status.tooltip.bad=\u00d7\uff1a\u8ca0\u62c5\u7387 0.5 \u672a\u6e80 (%1) ConfigView.section.style.status=\u30b9\u30c6\u30fc\u30bf\u30b9\u30a8\u30ea\u30a2\uff1a ConfigView.section.style.status.show_sr=\u8ca0\u62c5\u7387 ConfigView.section.style.status.show_nat=NAT \u30b9\u30c6\u30fc\u30bf\u30b9 ConfigView.section.style.status.show_ddb=DDB \u30b9\u30c6\u30fc\u30bf\u30b9 ConfigView.section.style.status.show_ipf=IP \u30d5\u30a3\u30eb\u30bf \u30b9\u30c6\u30fc\u30bf\u30b9 ConfigView.section.connection.encryption.encrypt.group=\u8ee2\u9001\u7d4c\u8def\u306e\u6697\u53f7\u5316 ConfigView.section.connection.encryption.encrypt.fallback_info=\u3053\u308c\u3089\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u6709\u52b9\u306b\u3059\u308b\u3068\u4e92\u63db\u6027\u306e\u7121\u3044\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3068\u63a5\u7d9a\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u304c\u3001\u6697\u53f7\u5316\u306f\u3055\u308c\u307e\u305b\u3093\u3002 ConfigView.section.connection.encryption.encrypt.fallback_outgoing=\u3053\u3061\u3089\u304b\u3089\u306e\u63a5\u7d9a\u3067\u6697\u53f7\u5316\u3057\u305f\u63a5\u7d9a\u304c\u5931\u6557\u3057\u305f\u5834\u5408\u306b\u6697\u53f7\u5316\u3057\u306a\u3044\u3067\u63a5\u7d9a ConfigView.section.connection.encryption.encrypt.fallback_incoming=\u6697\u53f7\u5316\u3055\u308c\u3066\u3044\u306a\u3044\u63a5\u7d9a\u3092\u53d7\u3051\u5165\u308c\u308b ConfigView.section.connection.encryption=\u6697\u53f7\u5316 upnp.selectedinterfaces=\u9078\u629e\u3055\u308c\u305f\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30a4\u30b9\uff08';' \u533a\u5207\u308a, \u4f8b eth0;eth1\uff09 [\u7a7a\u767d: \u3059\u3079\u3066] ConfigView.section.style.defaultSortOrder=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30bd\u30fc\u30c8\u9806 ConfigView.section.style.defaultSortOrder.desc=\u964d\u9806 ConfigView.section.style.defaultSortOrder.asc=\u6607\u9806 ConfigView.section.style.defaultSortOrder.flip=\u6700\u5f8c\u306b\u4f7f\u7528\u3057\u305f\u9806 LoggerView.autoscroll=\u81ea\u52d5\u30b9\u30af\u30ed\u30fc\u30eb Button.selectAll=\u3059\u3079\u3066\u3092\u8868\u793a Button.markSelected=\u9078\u629e\u3055\u308c\u305f\u3082\u306e\u3092\u30de\u30fc\u30af Button.unmarkSelected=\u30de\u30fc\u30af\u3092\u5916\u3059 plugins.basicview.config=\u8a2d\u5b9a TorrentOptionsView.param.max.uploads=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6570 [\u6700\u5c0f: 2] MyTorrentsView.menu.reposition.manual=\u518d\u914d\u7f6e... ConfigView.section.connection.advanced.info.link=\u8a73\u3057\u304f\u306f\u3053\u3061\u3089\u3092\u3054\u89a7\u304f\u3060\u3055\u3044 ConfigView.section.connection.advanced.socket.group=Socket ConfigView.section.connection.advanced.bind_port=\u30ed\u30fc\u30ab\u30eb\u30dd\u30fc\u30c8\u306b\u30d0\u30a4\u30f3\u30c9 [0: \u7121\u52b9] ConfigView.section.connection.advanced.bind_port.tooltip=\u5916\u90e8\u3078\u306e\u30bd\u30b1\u30c3\u30c8\u63a5\u7d9a\u3092\u8a2d\u5b9a\u3055\u308c\u305f\u30dd\u30fc\u30c8\u306b\u30d0\u30a4\u30f3\u30c9\u3057\u307e\u3059\u3002\n\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u6709\u52b9\u306b\u3059\u308b\u3068 NAT \u30eb\u30fc\u30bf\u306e\u5b89\u5b9a\u6027\u3092\u5411\u4e0a\u3055\u305b\u307e\u3059\u3002 ConfigView.section.proxy.group.tracker=\u30c8\u30e9\u30c3\u30ab\u30fc\u3068\u306e\u901a\u4fe1 ConfigView.section.proxy.group.peer=\u30d4\u30a2\u3068\u306e\u901a\u4fe1 Pieces.column.Requested=\u8981\u6c42\u3055\u308c\u305f ConfigView.label.maxuploadsseeding=\u30b7\u30fc\u30c9\u6642\u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6570\u306e\u30c7\u30d5\u30a9\u30eb\u30c8 popup.error.hideall=\u3059\u3079\u3066\u3092\u96a0\u3059 ConfigView.section.style.dataStatsOnly=\u30c7\u30fc\u30bf\u7d71\u8a08\u60c5\u5831\u306e\u307f\u8868\u793a ConfigView.section.style.separateProtDataStats=\u30c7\u30fc\u30bf\u3068\u30d7\u30ed\u30c8\u30b3\u30eb\u7d71\u8a08\u3092\u5225\u3005\u306b\u8868\u793a MyTorrentsView.menu.filter=\u30d5\u30a3\u30eb\u30bf\u4e00\u89a7... ConfigView.section.file.resume.recheck.all=\u30af\u30e9\u30c3\u30b7\u30e5\u3057\u305f\u5f8c\u306e\u8d77\u52d5\u6642\u306b\u5b8c\u6210\u3057\u305f\u30d4\u30fc\u30b9\u3092\u3059\u3079\u3066\u30c1\u30a7\u30c3\u30af\uff08\u30aa\u30d5\u306e\u5834\u5408\u306f\u6700\u5f8c\u306b\u4fdd\u5b58\u3057\u305f\u30d4\u30fc\u30b9\u306e\u307f\u3092\u30c1\u30a7\u30c3\u30af\uff09 ConfigureWizard.language.choose=\u8a00\u8a9e\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\uff1a popup.closing.in=%1 \u79d2\u7d4c\u904e\u3057\u305f\u3089\u30a6\u30a4\u30f3\u30c9\u30a6\u3092\u81ea\u52d5\u3067\u9589\u3058\u308b popup.more.waiting=\u3055\u3089\u306b %1 \u500b\u306e\u30e1\u30c3\u30bb\u30fc\u30b8... # > 2402 popup.next=\u2192 popup.previous=\u2190 (%1) popup.download.finished=%1 \u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f\u3002 popup.file.finished=%1 \u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5b8c\u4e86 ConfigView.auto=\u81ea\u52d5 Plugin.localtracker.autoadd.info=\u81ea\u52d5\u7684\u306b\u30ed\u30fc\u30ab\u30eb\u306e\u30d4\u30a2\u306b\u8ffd\u52a0 [';' \u533a\u5207\u308a\u3067 IP \u30a2\u30c9\u30ec\u30b9\u3092\u5217\u6319 \uff08\u4f8b\uff09 1.2.3.4] Plugin.localtracker.autoadd=\u30d4\u30a2\u3092\u660e\u793a Plugin.localtracker.networks.info=\u30ed\u30fc\u30ab\u30eb\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3068\u307f\u306a\u3059 [';' \u533a\u5207\u308a\u3067\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u5217\u6319 \uff08\u4f8b\uff09 145.227.*.*] Plugin.localtracker.networks=\u30ed\u30fc\u30ab\u30eb\u30cd\u30c3\u30c8\u30ef\u30fc\u30af MainWindow.menu.view.plugins.logViews=\u30ed\u30b0 SpeedView.stats.autospeed=\u81ea\u52d5\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 ConfigView.pluginlist.unloadSelected=\u9078\u629e\u3055\u308c\u305f\u9805\u76ee\u3092\u30a2\u30f3\u30ed\u30fc\u30c9 ConfigView.pluginlist.scan=\u65b0\u3057\u3044\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u78ba\u8a8d ConfigView.section.transfer.autospeed=\u81ea\u52d5\u901f\u5ea6\u8abf\u6574 ConfigView.section.transfer.autospeed.tooltip=\u81ea\u52d5\u901f\u5ea6\u8abf\u6574\u306b\u95a2\u3059\u308b\u8a2d\u5b9a ConfigView.section.transfer.autospeed.info=Auto-Speed \u306f\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6\u3092\u81ea\u52d5\u7684\u306b\u8abf\u6574\u3057\u307e\u3059\u3002\n\n\u3053\u306e\u5024\u306f Auto-Speed \u304c\u6709\u52b9\u306a\u5834\u5408\u306e\u307f\u9069\u7528\u3055\u308c\u307e\u3059\u3002\u307e\u305f\u3001\u5206\u6563\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u6709\u52b9\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\n ConfigView.section.transfer.autospeed.minupload=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 (%1) ConfigView.section.transfer.autospeed.minupload.tooltip=\u3053\u306e\u5024\u3088\u308a\u3082\u5c0f\u3055\u3044\u5834\u5408\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6\u306f\u81ea\u52d5\u7684\u306b\u9045\u304f\u306a\u308a\u307e\u305b\u3093 ConfigView.section.transfer.autospeed.maxupload=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 (%1) [0: \u7121\u5236\u9650] ConfigView.section.transfer.autospeed.maxupload.tooltip=\u3053\u306e\u5024\u3088\u308a\u3082\u5927\u304d\u3044\u5834\u5408\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6\u306f\u81ea\u52d5\u7684\u306b\u65e9\u304f\u306a\u308a\u307e\u305b\u3093 ConfigView.section.transfer.autospeed.chokeping=Ping \u5fdc\u7b54\u6642\u9593 (msec) ConfigView.section.transfer.autospeed.chokeping.tooltip=\u3053\u306e\u5024\u3092\u8d85\u3048\u305f\u5834\u5408\u3001\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u304c\u98fd\u548c\u72b6\u614b\u306b\u3042\u308b\u3068\u898b\u306a\u3055\u308c\u307e\u3059\u3002 ConfigView.section.transfer.autospeed.enableauto=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\uff0f\u30b7\u30fc\u30c9\u6642\u306e\u4e21\u65b9\u3067\u6709\u52b9\u306b\u3059\u308b ConfigView.section.transfer.autospeed.enableautoseeding=\u30b7\u30fc\u30c9\u6642\u306e\u307f\u6709\u52b9\u306b\u3059\u308b ConfigView.pluginlist.column.unloadable=\u30ed\u30fc\u30c9\u6e08\u307f ConfigView.section.transfer.lan.enable=LAN \u5185\u306e\u63a5\u7d9a\u306b\u5bfe\u3057\u3066\u5c02\u7528\u306e\u6700\u5927\u901f\u5ea6\u3092\u8a2d\u5b9a Plugin.localtracker.wellknownlocals=\u81ea\u52d5\u7684\u306b\u30ed\u30fc\u30ab\u30eb\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\uff08\u30eb\u30fc\u30d7\u30d0\u30c3\u30af\uff0f\u30ea\u30f3\u30af\uff09\u3092\u542b\u3081\u308b \uff08192.168 \u7b49\uff09 TableColumn.header.filesdone=\u5b8c\u6210\u3057\u305f\u30d5\u30a1\u30a4\u30eb TableColumn.header.filesdone.info=\u5b8c\u6210\u3057\u305f\u30d5\u30a1\u30a4\u30eb\u6570/\u7dcf\u30d5\u30a1\u30a4\u30eb\u6570 \u307e\u305f\u306f \u30b9\u30ad\u30c3\u30d7\u3057\u3066\u3044\u306a\u3044\u30d5\u30a1\u30a4\u30eb\u6570/\u30b9\u30ad\u30c3\u30d7\u3057\u3066\u3044\u306a\u3044\u30d5\u30a1\u30a4\u30eb\u306e\u7dcf\u6570 MagnetPlugin.private_torrent=<\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 Torrent> MagnetPlugin.decentral_disabled=<\u5206\u6563\u30c8\u30e9\u30c3\u30ad\u30f3\u30b0\u306f\u7121\u52b9> MagnetPlugin.decentral_backup_disabled=<\u5206\u6563\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u306f\u7121\u52b9> MagnetPlugin.report.waiting_ddb=DDB \u3092\u521d\u671f\u5316\u4e2d... MagnetPlugin.report.searching=\u691c\u7d22\u4e2d... MagnetPlugin.report.found=%1 \u3092\u898b\u3064\u3051\u307e\u3057\u305f MagnetPlugin.report.alive=%1 \u306f\u6709\u52b9\u3067\u3059 MagnetPlugin.report.dead=%1 \u306f\u7121\u52b9\u3067\u3059 MagnetPlugin.report.tunnel=%1 \u3078\u30c8\u30f3\u30cd\u30ea\u30f3\u30b0\u4e2d MagnetPlugin.report.downloading=%1 \u304b\u3089\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d MagnetPlugin.report.error=\u30a8\u30e9\u30fc %1 MagnetURLHandler.report.no_sources=\u30bd\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093 MagnetURLHandler.report.torrent_size=Torrent \u30b5\u30a4\u30ba: %1 MagnetURLHandler.report.percent=\u72b6\u6cc1: %1% MagnetURLHandler.report.error=\u30a8\u30e9\u30fc %1 DHTTransport.report.request_all=\u8981\u6c42\u4e2d\uff08%1 \u304b\u3089\uff09 DHTTransport.report.received_bit=%1 \u3092\u53d7\u4fe1\uff08%3 \u304b\u3089 %2 \u3078\uff09 DHTTransport.report.complete=\u5b8c\u4e86 DHTTransport.report.timeout=\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\uff08%1 \u304b\u3089\u5fdc\u7b54\u306a\u3057\uff09 DHTTransport.report.rerequest_all=\u518d\u8981\u6c42\u4e2d\uff08%1 \u304b\u3089\uff09 DHTTransport.report.rerequest_bit=%1 \u3092\u518d\u8981\u6c42\u4e2d\uff08%3 \u304b\u3089 %2 \u3078\uff09 DHTTransport.report.timeout_some=\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\uff08%2 \u304b\u3089\u3000%1 \u30d1\u30b1\u30c3\u30c8\u3092\u53d7\u4fe1\uff09 DHTTransport.report.sending=\u30c7\u30fc\u30bf\u3092\u9001\u4fe1\u4e2d DHTTransport.report.resending=\u30c7\u30fc\u30bf\u3092\u518d\u9001\u4e2d DHTTransport.report.send_complete=\u9001\u4fe1\u5b8c\u4e86 DHTTransport.report.send_timeout=\u9001\u4fe1\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8 ConfigView.section.transfer.autospeed.enabledebug=\u30c7\u30d0\u30c3\u30b0\u60c5\u5831\u3092\u8a18\u9332 TableColumn.header.date_added=\u8ffd\u52a0\u65e5\u6642 TableColumn.header.date_added.info=Torrent \u3092\u8ffd\u52a0\u3057\u305f\u65e5\u6642 ConfigView.section.file.hashchecking.smallestfirst=\u6700\u5c0f\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u6700\u521d\u306b\u518d\u30c1\u30a7\u30c3\u30af platform.win32.baddll.info=Vuze \u306f '%1' \u3092\u767a\u898b\u3057\u307e\u3057\u305f\u3002\u3053\u308c\u306f '%2' \u306e\u4e00\u90e8\u3067\u3042\u308a\u3001CPU \u4f7f\u7528\u7387\u304c\u9ad8\u304f\u306a\u3063\u305f\u308a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u304c\u30af\u30e9\u30c3\u30b7\u30e5\u3057\u305f\u308a\u3068\u3044\u3063\u305f\u554f\u984c\u3092\u5f15\u304d\u8d77\u3053\u3059\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002\u3053\u306e\u3088\u3046\u306a\u554f\u984c\u304c\u8d77\u304d\u305f\u5834\u5408\u306f\u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u304b Vuze \u306b\u5f71\u97ff\u3092\u53ca\u307c\u3055\u306a\u3044\u3088\u3046\u8a2d\u5b9a\u3092\u884c\u3063\u3066\u304f\u3060\u3055\u3044\u3002 upnp.ignorebaddevices=\u6b63\u5e38\u306a\u5fdc\u7b54\u3092\u8fd4\u3055\u306a\u3044\u30c7\u30d0\u30a4\u30b9\u3092\u7121\u8996 upnp.ignorebaddevices.info=\u73fe\u5728\u7121\u8996\u3055\u308c\u305f\u30c7\u30d0\u30a4\u30b9\uff1a%1 upnp.ignorebaddevices.reset=\u7121\u8996\u3055\u308c\u305f\u30c7\u30d0\u30a4\u30b9\u306e\u4e00\u89a7\u3092\u30ea\u30bb\u30c3\u30c8 upnp.ignorebaddevices.reset.action=\u30ea\u30bb\u30c3\u30c8 upnp.ignorebaddevices.alert=\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3 %1 \u306b\u3042\u308b UPnP \u30c7\u30d0\u30a4\u30b9\u306f\u6b63\u3057\u304f\u5fdc\u7b54\u3057\u306a\u3044\u305f\u3081\u7121\u8996\u3055\u308c\u307e\u3059\u3002UPnP \u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u8a2d\u5b9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 TorrentOptionsView.param.max.uploads.when.busy=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6570\u4e0a\u9650\u306b\u9054\u3057\u305f\u3068\u304d\u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6\u4e0a\u9650 (KB/s) [0: \u7121\u52b9] UpdateMonitor.messagebox.verification.failed.title=\u691c\u8a3c\u5931\u6557 UpdateMonitor.messagebox.verification.failed.text=%1' \u306e\u691c\u8a3c\u306b\u5931\u6557\u3057\u307e\u3057\u305f: %2 UpdateMonitor.messagebox.accept.unverified.title=\u672a\u691c\u8a3c\u306e\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb UpdateMonitor.messagebox.accept.unverified.text='%1' \u306f Vuze \u306e\u516c\u5f0f\u30d7\u30e9\u30b0\u30a4\u30f3\u3067\u3042\u308b\u3053\u3068\u304c\u78ba\u8a8d\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\n\u3053\u306e\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u3079\u304d\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\n\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3092\u7d9a\u3051\u307e\u3059\u304b\uff1f FileView.BlockView.title=\u30d4\u30fc\u30b9 FileView.BlockView.Done=\u5b8c\u4e86 FileView.BlockView.Skipped=\u30b9\u30ad\u30c3\u30d7 FileView.BlockView.Active=\u30a2\u30af\u30c6\u30a3\u30d6 FileView.BlockView.Outstanding=\u672a\u9001\u4fe1 ConfigView.label.tcplistenport=TCP \u5f85\u3061\u53d7\u3051\u30dd\u30fc\u30c8 ConfigView.label.udplistenport=UDP \u5f85\u3061\u53d7\u3051\u30dd\u30fc\u30c8 upnp.portchange.alert=\u6b21\u306e\u30dd\u30fc\u30c8\u306f UPnP \u30c7\u30d0\u30a4\u30b9\u306e\u554f\u984c\u3092\u56de\u907f\u3059\u308b\u305f\u3081\u5909\u66f4\u3055\u308c\u307e\u3057\u305f\uff1a%1 [\u65e7\u30dd\u30fc\u30c8=%2] %3 [\u65e7\u30dd\u30fc\u30c8=%4] ConfigView.section.proxy.username.info=\u30d7\u30ed\u30ad\u30b7\u30b5\u30fc\u30d0\u304c\u8a8d\u8a3c\u3092\u5fc5\u8981\u3068\u3057\u3066\u3044\u308b\u306b\u3082\u304b\u304b\u308f\u3089\u305a\u4f55\u3082\u8a2d\u5b9a\u3057\u3066\u3044\u306a\u3044\u5834\u5408\u3001"" \u304c\u30e6\u30fc\u30b6\u540d\u3068\u3057\u3066\u4f7f\u308f\u308c\u307e\u3059\u3002 ConfigView.label.maxuploadswhenbusymin=\u30d3\u30b8\u30fc\u6642\u306e Torrent \u3054\u3068\u306e\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 [sec] MainWindow.menu.help.debug=\u30c7\u30d0\u30c3\u30b0\u60c5\u5831\u3092\u751f\u6210 DownloadManager.error.badsize=\u4e0d\u6b63\u306a\u30b5\u30a4\u30ba natpmp.info=NAT-PMP \u306f Apple \u306b\u3088\u308b UPnP \u306e\u4ee3\u66ff\u6a5f\u80fd\u3067\u3001\u6700\u8fd1\u306e AirMac \u30b9\u30c6\u30fc\u30b7\u30e7\u30f3\u3067\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u3059\u3002\n\nNAT-PMP \u30c7\u30d0\u30a4\u30b9\u304c\u7279\u5225\u306a UPnP \u30c7\u30d0\u30a4\u30b9\u3068\u3057\u3066\u6271\u308f\u308c\u308b\u3088\u3046\u306b\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u3044\u3053\u3068\u306b\u6ce8\u610f\u3057\u3066\u304f\u3060\u3055\u3044\u3002 natpmp.enable=\u6709\u52b9\uff08\u52d5\u4f5c\u3055\u305b\u308b\u306b\u306f AirMac \u306e\u8a2d\u5b9a\u3082\u6709\u52b9\u306b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\uff09 ConfigView.section.tracker.host.addurls=\u3053\u306e Torrent \u3092\u30db\u30b9\u30c8\u3059\u308b URL \u3092\u6b63\u3057\u304f\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 ConfigView.filter=\u691c\u7d22\u3059\u308b\u8a9e\u53e5\u3092\u5165\u529b ConfigView.section.files.move=\u5b8c\u6210\u3057\u305f\u30d5\u30a1\u30a4\u30eb\u306e\u79fb\u52d5 ConfigView.section.file.defaultdir.section=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 ConfigView.section.file.defaultdir.auto=\u81ea\u52d5\u7684\u306b\u4e0a\u8a18\u306e\u30d5\u30a9\u30eb\u30c0\u306b\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 ConfigView.section.file.defaultdir.bestguess=\u6bce\u56de\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5148\u3092\u6307\u5b9a ConfigView.section.file.defaultdir.ask=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u4fdd\u5b58\u5148\uff1a ConfigView.section.file.defaultdir.lastused=\u6700\u5f8c\u306b\u6307\u5b9a\u3057\u305f\u30d1\u30b9\u3092\u8a18\u61b6 ConfigView.section.file.config.section=\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb ConfigView.section.file.config.currentdir=\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u4fdd\u5b58\u5148\uff1a ConfigView.section.torrent.decoding=\u6587\u5b57\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0 ConfigView.section.logging.udptransport=UDP \u8ee2\u9001\u3092\u8a73\u7d30\u306b\u30c8\u30ec\u30fc\u30b9 Tracker.announce.ignorePeerSeed=\u30d4\u30a2\uff0f\u30b7\u30fc\u30c9\u6570\u3092\u7121\u8996 %1 ConfigView.section.connection.encryption.use_crypto_port=\u6697\u53f7\u5316\u3055\u308c\u3066\u3044\u306a\u3044\u63a5\u7d9a\u3092\u62d2\u5426\u3059\u308b\u306b\u306f 'cryptport' \u30c8\u30e9\u30c3\u30ab\u30fc\u62e1\u5f35\u3092\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\u3044\u304f\u3064\u304b\u306e\u30c8\u30e9\u30c3\u30ab\u30fc\u306f\u3053\u308c\u3092\u53d7\u3051\u5165\u308c\u305a\u3001"\u7121\u52b9\u306a\u30dd\u30fc\u30c8" \u307e\u305f\u306f "\u7121\u52b9\u306a\u5f15\u6570" \u30a8\u30e9\u30fc\u3092\u8fd4\u3059\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002 TorrentOptionsView.param.reset.to.default=\u74b0\u5883\u8a2d\u5b9a\u306e\u5024\u3092\u30c7\u30d5\u30a9\u30eb\u30c8\u306b\u623b\u3059 TorrentOptionsView.param.reset.button=\u30ea\u30bb\u30c3\u30c8 natpmp.routeraddress=\u30b9\u30c6\u30fc\u30b7\u30e7\u30f3\u306e\u30a2\u30c9\u30ec\u30b9 [\u7a7a\u767d\u306e\u5834\u5408\u3001\u81ea\u52d5] ConfigView.section.style.disableAlertSliding=\u8b66\u544a\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u8868\u793a\u3057\u306a\u3044 ConfigView.section.transfer.autospeed.maxinc=1 \u56de\u3042\u305f\u308a\u306e\u6700\u5927\u5897\u52a0\u91cf (%1) ConfigView.section.transfer.autospeed.maxdec=1 \u56de\u3042\u305f\u308a\u306e\u6700\u5927\u6e1b\u5c11\u91cf (%1) ConfigView.section.transfer.autospeed.enabledownadj=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6\u3092\u81ea\u52d5\u7684\u306b\u8abf\u6574 ConfigView.section.transfer.autospeed.downadjratio=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6\u6bd4\uff08\u4f8b\uff1a2.0 \u2192 \u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6\u306e\u4e0a\u9650\u306f\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6\u4e0a\u9650\u306e 2 \u500d\uff09 ConfigView.section.transfer.autospeed.latencyfactor=\u901f\u5ea6\u306e\u5897\u6e1b\u306b\u5fdc\u3058\u3066\u3069\u306e\u7a0b\u5ea6\u5909\u5316\u3055\u305b\u308b\u304b\uff08\u6570\u5024\u304c\u5927\u304d\u3044\u307b\u3069\u611f\u5ea6\u304c\u4e0b\u304c\u308b\uff09 ConfigView.section.transfer.autospeed.reset=\u8a2d\u5b9a\u5024\u3092\u521d\u671f\u5024\u306b\u623b\u3059 ConfigView.section.transfer.autospeed.reset.button=\u521d\u671f\u5024\u306b\u623b\u3059 PeerColumn.activationCount=\u63a5\u7d9a\u3092\u8a66\u307f\u3066\u3044\u308b\u30d4\u30a2: %1 TableColumn.header.timesincedownload.info=\u6700\u5f8c\u306b\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3055\u308c\u3066\u304b\u3089\u306e\u7d4c\u904e\u6642\u9593 TableColumn.header.timesincedownload=\u5f85\u6a5f\u6642\u9593 TableColumn.header.timesinceupload.info=\u6700\u5f8c\u306b\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3055\u308c\u3066\u304b\u3089\u306e\u7d4c\u904e\u6642\u9593 TableColumn.header.timesinceupload=\u5f85\u6a5f\u6642\u9593 PeersView.incomingreqcount=\u88ab\u30ea\u30af\u30a8\u30b9\u30c8\u56de\u6570 PeersView.incomingreqcount.info=\u30d4\u30a2\u304b\u3089\u9001\u4fe1\u3055\u308c\u305f\u30ea\u30af\u30a8\u30b9\u30c8\u306e\u7dcf\u6570 PeersView.outgoingreqcount=\u30ea\u30af\u30a8\u30b9\u30c8\u56de\u6570 PeersView.outgoingreqcount.info=\u30d4\u30a2\u3078\u9001\u4fe1\u3057\u305f\u30ea\u30af\u30a8\u30b9\u30c8\u306e\u7dcf\u6570 upnp.mapping.trackerclientudp=UDP Tracker \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30dd\u30fc\u30c8 upnp.mapping.dhtudp=\u5206\u6563\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 ConfigView.section.connection.nondata.udp.same=\u5206\u6563 DB \u3068 UDP \u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u306f\u540c\u3058 UDP \u30dd\u30fc\u30c8\u3092\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002 ConfigView.section.connection.tcp.enable=TCP \u3092\u4f7f\u7528 ConfigView.section.connection.udp.enable=UDP \u3092\u4f7f\u7528 ConfigView.section.style.showiconbar=\u30c4\u30fc\u30eb\u30d0\u30fc\u3092\u8868\u793a MainWindow.menu.view.iconbar=\u30c4\u30fc\u30eb\u30d0\u30fc MyTorrentsView.menu.rename=\u540d\u524d\u3092\u5909\u66f4 MyTorrentsView.menu.rename.displayed=\u8868\u793a\u540d\u3092\u5909\u66f4 MyTorrentsView.menu.rename.save_path=\u4fdd\u5b58\u5148\u3092\u5909\u66f4 MyTorrentsView.menu.rename.displayed.enter.title=\u8868\u793a\u540d\u3092\u5909\u66f4 MyTorrentsView.menu.rename.displayed.enter.message=\u8868\u793a\u540d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\u4f55\u3082\u5165\u529b\u3057\u306a\u3044\u5834\u5408\u306f\u30aa\u30ea\u30b8\u30ca\u30eb\u306e\u540d\u524d\u304c\u4f7f\u308f\u308c\u307e\u3059\u3002 MyTorrentsView.menu.edit_comment=\u30b3\u30e1\u30f3\u30c8\u3092\u7de8\u96c6 MyTorrentsView.menu.edit_comment.enter.title=\u30b3\u30e1\u30f3\u30c8\u3092\u7de8\u96c6 MyTorrentsView.menu.edit_comment.enter.message=\u30b3\u30e1\u30f3\u30c8\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044 UIDebugGenerator.messageask.title=\u30c7\u30d0\u30c3\u30b0 \u30b8\u30a7\u30cd\u30ec\u30fc\u30bf UIDebugGenerator.messageask.text=\u30d0\u30b0\u306b\u95a2\u3059\u308b\u8aac\u660e\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044 UIDebugGenerator.complete.title=\u30c7\u30d0\u30c3\u30b0\u60c5\u5831\u306e\u751f\u6210\u3092\u5b8c\u4e86\u3057\u307e\u3057\u305f UIDebugGenerator.complete.text=\u30d5\u30a1\u30a4\u30eb '%1' \u3092 az-bugreports@azureus-inc.com \u3078\u9001\u3063\u3066\u304f\u3060\u3055\u3044\u3002\n\nOK \u3092\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304d\u307e\u3059\u3002 ConfigView.section.style.showProgramIcon='\u540d\u524d'\u5217\u306b\u30d7\u30ed\u30b0\u30e9\u30e0\u30a2\u30a4\u30b3\u30f3\u3092\u8868\u793a ConfigView.section.style.showProgramIcon.tooltip=\u5909\u66f4\u5185\u5bb9\u306f\u6b21\u306b\u958b\u3044\u305f\u3068\u304d\u306b\u6709\u52b9\u306b\u306a\u308a\u307e\u3059 swt.alert.cant.update=%3" \u304b\u3089\u30ed\u30fc\u30c9\u3055\u308c\u305f SWT \u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u30d0\u30fc\u30b8\u30e7\u30f3 %1 \u304b\u3089 %2 \u3078\u81ea\u52d5\u7684\u306b\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\uff08"%4" \u304b\u3089\u30ed\u30fc\u30c9\u3055\u308c\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\uff09\u3002\u8a73\u3057\u304f\u306f the wiki \u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002 authenticator.savepassword=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u4fdd\u5b58 ConfigView.section.security.clearpasswords=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u30ea\u30bb\u30c3\u30c8 ConfigView.section.security.clearpasswords.button=\u30ea\u30bb\u30c3\u30c8 Content.alert.notuploaded.title=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u304c\u4e0d\u5341\u5206\u3067\u3059 Content.alert.notuploaded.text='%1' \u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u304c\u4e0d\u5341\u5206\u3067\u3059\u3002\u3082\u3057\u3053\u3053\u3067 %2 \u3059\u308b\u3068\u3001\u307b\u304b\u306e\u30e6\u30fc\u30b6\u306f\u30d5\u30a1\u30a4\u30eb\u3092\u5b8c\u5168\u306b\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002\n\n\u672c\u5f53\u306b %2 \u3057\u307e\u3059\u304b\uff1f Content.alert.notuploaded.multi.title=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u304c\u4e0d\u5341\u5206\u3067\u3059 Content.alert.notuploaded.multi.text='%1' \u306f\u307e\u3060\u5341\u5206\u306b\u30b7\u30fc\u30c9\u3067\u304d\u3066\u3044\u307e\u305b\u3093\u3002\u3082\u3057 %2 \u3059\u308b\u3068\u3001\u307b\u304b\u306e\u30e6\u30fc\u30b6\u306f\u30d5\u30a1\u30a4\u30eb\u3092\u5b8c\u5168\u306b\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002\n\n\u672c\u5f53\u306b %2 \u3057\u307e\u3059\u304b\uff1f\n\n\u30b7\u30fc\u30c9\u304c\u4e0d\u5b8c\u5168\u306a\u30b3\u30f3\u30c6\u30f3\u30c4:\n%3 Content.alert.notuploaded.stop=\u4e2d\u6b62 Content.alert.notuploaded.quit=Vuze \u3092\u7d42\u4e86 TorrentInfoView.torrent.encoding=Torrent \u306e\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0 TorrentInfoView.columns=Torrent \u30bf\u30d6\u306b\u8868\u793a\u3059\u308b\u5217 progress.window.title=\u9032\u884c\u4e2d\u306e\u52d5\u4f5c progress.window.msg.filemove=\u30d5\u30a1\u30a4\u30eb\u306e\u79fb\u52d5\uff0f\u540d\u524d\u306e\u5909\u66f4\u304c\u7d42\u308f\u308b\u307e\u3067\u304a\u5f85\u3061\u304f\u3060\u3055\u3044\u3002 ConfigView.label.popup.timestamp=\u8b66\u544a\u30dd\u30c3\u30d7\u30a2\u30c3\u30d7\u306b\u65e5\u6642\u3092\u8ffd\u52a0 ConfigView.label.popup.autohide=\u6307\u5b9a\u3057\u305f\u79d2\u6570\u304c\u7d4c\u904e\u3057\u305f\u5f8c\u306b\u3001\u30a8\u30e9\u30fc\u901a\u77e5\u4ee5\u5916\u306e\u30dd\u30c3\u30d7\u30a2\u30c3\u30d7\u3092\u81ea\u52d5\u7684\u306b\u96a0\u3059\uff080: \u7121\u52b9\uff09 ConfigView.label.popup.suppress_alerts=\u8b66\u544a\u3092\u7701\u7565 ConfigView.label.popup.use_message_boxes=\u901a\u5e38\u306e\u8b66\u544a\u3067\u306f\u306a\u304f\u30dd\u30c3\u30d7\u30a2\u30c3\u30d7\u30e1\u30c3\u30bb\u30fc\u30b8\u30dc\u30c3\u30af\u30b9\u3092\u4f7f\u7528 ConfigView.label.popup.show=\u4ee5\u524d\u306b\u901a\u77e5\u3055\u308c\u305f\u30dd\u30c3\u30d7\u30a2\u30c3\u30d7\u3092\u3059\u3079\u3066\u3092\u8868\u793a ConfigView.label.popup.show.button=\u8868\u793a ConfigView.label.please.visit.here=\u8a73\u3057\u304f\u306f\u3053\u3061\u3089\u3092\u3054\u89a7\u304f\u3060\u3055\u3044 ConfigView.section.ipfilter.enable.descriptionCache=\u30b9\u30af\u30e9\u30c3\u30c1\u30d5\u30a1\u30a4\u30eb\u306b IP \u306e\u8a73\u7d30\u3092\u4fdd\u5b58 ConfigView.section.ipfilter.enable.descriptionCache.tooltip=\u7121\u52b9\u306b\u3059\u308b\u3068\u3001\u8a73\u7d30\u306f\u8a18\u9332\u3055\u308c\u307e\u305b\u3093\u3002 OpenTorrentWindow.filesInfo=%2 \u4e2d %1 \u304c\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3055\u308c\u307e\u3059\u3002 OpenTorrentWindow.diskUsage=%1 / %2 ConfigView.label.openmytorrents=\u8d77\u52d5\u6642\u306b Torrent \u30bf\u30d6\u3092\u958b\u304f ConfigView.label.open_transfer_bar_on_start=\u8d77\u52d5\u6642\u306b\u8ee2\u9001\u30d0\u30fc\u3092\u958b\u304f ConfigView.section.style.DNDalwaysInIncomplete=\u5e38\u306b'\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u306a\u3044'\u30d5\u30a1\u30a4\u30eb\u3082 Torrent \u30bf\u30d6\u306b\u8868\u793a OpenTorrentWindow.mb.noGlobalDestDir.title=\u4fdd\u5b58\u5148\u306e\u30d5\u30a9\u30eb\u30c0\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 OpenTorrentWindow.mb.noGlobalDestDir.text=\u4fdd\u5b58\u5148\u306e\u30d5\u30a9\u30eb\u30c0 '%1' \u304c\u898b\u3064\u304b\u3089\u306a\u3044\u304b\u7121\u52b9\u3067\u3059\u3002 OpenTorrentWindow.mb.noDestDir.title=\u4fdd\u5b58\u5148\u306e\u30d5\u30a9\u30eb\u30c0\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 OpenTorrentWindow.mb.noDestDir.text=Torrent '%1' \u306b\u5bfe\u3059\u308b\u4fdd\u5b58\u5148\u306e\u30d5\u30a9\u30eb\u30c0 '%1' \u304c\u898b\u3064\u304b\u3089\u306a\u3044\u304b\u7121\u52b9\u3067\u3059\u3002 OpenTorrentWindow.mb.notValid.title=Torrent \u3092\u958b\u304f OpenTorrentWindow.mb.notValid.text=Torrent '%1' \u3092\u958b\u3051\u307e\u305b\u3093\u3002\u30b7\u30fc\u30c9\u30e2\u30fc\u30c9\u3067\u958b\u3053\u3046\u3068\u3057\u3066\u3044\u308b\u5834\u5408\u306f\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3059\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 OpenTorrentWindow.mb.notTorrent.title=Torrent \u3092\u958b\u304f OpenTorrentWindow.mb.notTorrent.text=Torrent '%1' \u3092\u958b\u3051\u307e\u305b\u3093\u3002.torrent \u30d5\u30a1\u30a4\u30eb\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\n\n\u30d5\u30a1\u30a4\u30eb\u306e\u5185\u5bb9:\n%2 ConfigView.label.pause.downloads.on.exit=\u7d42\u4e86\u6642\u306b\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u4e00\u6642\u505c\u6b62 ConfigView.label.resume.downloads.on.start=\u8d77\u52d5\u5f8c\u306b\u4e00\u6642\u505c\u6b62\u4e2d\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u518d\u958b UIDebugGenerator.message.cancel.title=\u30c7\u30d0\u30c3\u30b0\u60c5\u5831\u306e\u751f\u6210\u3092\u30ad\u30e3\u30f3\u30bb\u30eb UIDebugGenerator.message.cancel.text=\u30d0\u30b0\u306b\u95a2\u3059\u308b\u8aac\u660e\u304c\u5165\u529b\u3055\u308c\u306a\u304b\u3063\u305f\u305f\u3081\u3001\u30c7\u30d0\u30c3\u30b0\u60c5\u5831\u306e\u751f\u6210\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3057\u305f\u3002 ConfigView.section.connection.group.http.info=HTTP \u30b7\u30fc\u30c9\u3092\u4f7f\u7528\u3057\u307e\u3059\u3002 ConfigView.section.connection.http.enable=\u4f7f\u7528\u3059\u308b ConfigView.section.connection.http.port=\u5f85\u3061\u53d7\u3051\u30dd\u30fc\u30c8 ConfigView.section.connection.http.portoverride=\u30c8\u30e9\u30c3\u30ab\u30fc\u5c02\u7528 HTTP \u30dd\u30fc\u30c8\u3000[0: \u306a\u3057] window.update.noupdates.title=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u7d50\u679c\u3092\u78ba\u8a8d window.update.noupdates.text=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306f\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 ConfigView.label.mindownloads=\u6700\u5c0f\u540c\u6642\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u6570 UI.cannot_submit_blank_text=\u5024\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 crypto.alert.as.warning=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af '%1' \u306f\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6\u3092\u6291\u3048\u308b\u305f\u3081\u306b\u30c8\u30e9\u30d5\u30a3\u30c3\u30af \u30b7\u30a7\u30fc\u30d4\u30f3\u30b0\u3092\u5b9f\u88c5\u3057\u3066\u3044\u307e\u3059\u3002\u30c7\u30fc\u30bf\u8ee2\u9001\u306e\u6697\u53f7\u5316\u306f\u81ea\u52d5\u7684\u306b\u30aa\u30f3\u306b\u306a\u3063\u3066\u304a\u308a\u3001\u74b0\u5883\u8a2d\u5b9a\u3092\u901a\u3058\u3066\u30aa\u30d5\u306b\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 ConfigView.section.interface.alerts=\u8b66\u544a ConfigView.label.popupdownloadadded=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u8ffd\u52a0\u6642\u306b\u30dd\u30c3\u30d7\u30a2\u30c3\u30d7\u3067\u77e5\u3089\u305b\u308b popup.download.added=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30ea\u30b9\u30c8\u306b %1 \u304c\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f\u3002 MessageBoxWindow.nomoreprompting=\u4eca\u5f8c\u3001\u8a0a\u306d\u306a\u3044 TorrentOptionsView.param.max.seeds=\u6700\u5927\u30b7\u30fc\u30c9\u63a5\u7d9a\u6570 [0: \u7121\u5236\u9650] TorrentOptionsView.param.alternative.value.enable=\u30b7\u30fc\u30c9\u6642\u306e\u4ee3\u66ff\u5024 ConfigView.section.proxy.check.on.start=\u8d77\u52d5\u6642\u306b\u30d7\u30ed\u30ad\u30b7\u306e\u72b6\u614b\u3092\u78ba\u8a8d TransferStatsView.legend.pingaverage=\u5e73\u5747 TransferStatsView.legend.ping1=\u30bf\u30fc\u30b2\u30c3\u30c8 1 TransferStatsView.legend.ping2=\u30bf\u30fc\u30b2\u30c3\u30c8 2 TransferStatsView.legend.ping3=\u30bf\u30fc\u30b2\u30c3\u30c8 3 ConfigView.section.interface.enabletray._mac=\u30b9\u30c6\u30fc\u30bf\u30b9\u30d0\u30fc\u30a2\u30a4\u30b3\u30f3\u3092\u8868\u793a\uff08\u518d\u8d77\u52d5\u304c\u5fc5\u8981\uff09 ConfigView.label.closetotray._mac=\u9589\u3058\u308b\u30dc\u30bf\u30f3\u3067 Dock \u306b\u3057\u307e\u3046 ConfigView.label.minimizetotray._mac=\u6700\u5c0f\u5316\u30dc\u30bf\u30f3\u3067 Dock \u306b\u3057\u307e\u3046 OpenTorrentWindow.mb.existingFiles.title=\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u307e\u3059 OpenTorrentWindow.mb.existingFiles.text=\u6307\u5b9a\u3055\u308c\u305f\u4fdd\u5b58\u5148\u30d5\u30a9\u30eb\u30c0\u306b\u540c\u540d\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u307e\u3059\u3002\n\n%1\n\u7d9a\u884c\u3059\u308b\u3068 Vuze \u306f\u30d5\u30a1\u30a4\u30eb\u3092\u78ba\u8a8d\u3057\u3066\u5fc5\u8981\u306b\u5fdc\u3058\u3066\u6b63\u5e38\u306a\u30c7\u30fc\u30bf\u3067\u4e0a\u66f8\u304d\u3057\u307e\u3059\u3002 splash.unloadingTorrents=Torrent \u3092\u30a2\u30f3\u30ed\u30fc\u30c9\u4e2d splash.unloadingTorrent=Torrent \u3092\u30a2\u30f3\u30ed\u30fc\u30c9\u4e2d ConfigView.section.file.defaultdir.autorename=\u540c\u540d\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308b\u5834\u5408\u3001\u81ea\u52d5\u7684\u306b\u30d5\u30a1\u30a4\u30eb\u540d\u3092\u5909\u66f4\u3059\u308b ConfigView.section.file.defaultdir.autorename.tooltip=\u5225\u306e Torrent \u306b\u540c\u540d\u306e\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u304c\u542b\u307e\u308c\u308b\u5834\u5408\u3001\u4e0a\u66f8\u304d\u3055\u308c\u308b\u3053\u3068\u3092\u9632\u3050\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 alert.raised.at.close=\uff08\u524d\u56de Vuze \u3092\u9589\u3058\u305f\u3068\u304d\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\uff09 MyTorrents.items.DownSpeedLimit.disabled=\u306a\u3057 upnp.selectedaddresses=\u30a2\u30c9\u30ec\u30b9 (';' \u533a\u5207\u308a\u6587\u5b57, \u5148\u982d\u306b '-' =\u62d2\u5426, '+' =\u8a31\u53ef) [\u7a7a\u6b04: \u3059\u3079\u3066] UpdateMonitor.messagebox.restart.title=\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8 UpdateMonitor.messagebox.restart.text=\u91cd\u8981\u306a\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f\u3002\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u305f\u3081\u306b\u4eca\u3059\u3050\u518d\u8d77\u52d5\u3057\u3066\u304f\u3060\u3055\u3044\u3002 PiecesView.BlockView.Have=\u6240\u6709 PiecesView.BlockView.NoHave=\u672a\u6240\u6709 PiecesView.BlockView.Header=%1 \u5217, %2 \u884c, %3 \u30d4\u30fc\u30b9 ConfigView.section.update.autodownload=\u81ea\u52d5\u7684\u306b\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u3001\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306e\u6e96\u5099\u304c\u3067\u304d\u305f\u3089\u901a\u77e5 Peers.column.client_identification=\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u7279\u5b9a Peers.column.client_identification.info=Vuze \u304c\u53d7\u4fe1\u3057\u305f\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u540d\u3092\u305d\u306e\u307e\u307e\u8868\u793a\u3057\u307e\u3059 - \u30c7\u30d0\u30c3\u30b0\u306b\u6709\u52b9\u3067\u3059 dht.warn.user=NAT\uff0f\u30dd\u30fc\u30c8\u30de\u30c3\u30d4\u30f3\u30b0\u306b\u95a2\u3059\u308b\u554f\u984c\u3092\u8b66\u544a ConfigView.label.openbar.incomplete=\u81ea\u52d5\u3067\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u958b\u59cb ConfigView.label.openbar.complete=\u81ea\u52d5\u3067\u30b7\u30fc\u30c9\u3092\u958b\u59cb ConfigView.label.transferbar.remember_location=\u8ee2\u9001\u30d0\u30fc\u306e\u6700\u5f8c\u306b\u958b\u3044\u305f\u4f4d\u7f6e\u3092\u8a18\u61b6 ConfigView.section.transfer.autospeed.forcemin=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6\u3092\u5f37\u5236\u7684\u306b\u5909\u66f4 (%1) MainWindow.menu.tools.speedtest=\u30b9\u30d4\u30fc\u30c9\u30c6\u30b9\u30c8... window.uiswitcher.text=\u6b21\u304b\u3089\u304a\u597d\u307f\u306e\u30e6\u30fc\u30b6\u30fc\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30a4\u30b9\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 window.uiswitcher.NewUI.text=* \u521d\u5fc3\u8005\u3084\u65b0\u898f\u30e6\u30fc\u30b6\u306b\u304a\u52e7\u3081\n\n* \u4f7f\u3044\u3084\u3059\u3044\u30b0\u30e9\u30d5\u30a3\u30ab\u30eb\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30a4\u30b9\n\n* Vuze \u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u3067\u516c\u958b\u3059\u308b\u306b\u306f\u5fc5\u9808 window.uiswitcher.ClassicUI.title=\u30af\u30e9\u30b7\u30c3\u30af\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30a4\u30b9 window.uiswitcher.ClassicUI.text=* 2.x \u306e\u6a5f\u80fd\u3092\u4fdd\u6301\u3002\n\n* Vuze \u30b3\u30f3\u30c6\u30f3\u30c4\u30ec\u30a4\u30e4\u30fc\u306f\u30ed\u30fc\u30c9\u3055\u308c\u307e\u305b\u3093 window.uiswitcher.bottom.text=Vuze UI Chooser \u3067\u3044\u3064\u3067\u3082\u5909\u66f4\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 VivaldiView.notAvailable=Vivaldi View \u306f\u7121\u52b9\u3067\u3059 restart.error=\u518d\u8d77\u52d5\u306b\u5931\u6557:\n%1\nrestarting issues \u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002 restart.error.oom=\u30e1\u30e2\u30ea\u4e0d\u8db3 restart.error.fnf='%1' \u304c '%2' \u306b\u3042\u308a\u307e\u305b\u3093 restart.error.pnf=\u30d1\u30b9 '%1' \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 restart.error.bad=\u4e0d\u6b63\u306a\u30d5\u30a1\u30a4\u30eb\u5f62\u5f0f '%1' restart.error.denied='%1' \u306e\u5b9f\u884c\u306b\u5fc5\u8981\u306a\u30a2\u30af\u30bb\u30b9\u6a29\u304c\u3042\u308a\u307e\u305b\u3093\u3002\u30a2\u30af\u30bb\u30b9\u6a29\u3092\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 TableColumn.header.date_completed=\u5b8c\u4e86\u65e5\u6642 TableColumn.menu.date_added.reset=\u65e5\u6642\u3092\u30ea\u30bb\u30c3\u30c8 ConfigView.section.ipfilter.discardbanning=\u4e0d\u6b63\u306a\u30c7\u30fc\u30bf\u306e\u542b\u6709\u7387\u304c\u9ad8\u3044\u30d4\u30a2\u3092\u30d6\u30ed\u30c3\u30af [0: \u7121\u5236\u9650] ConfigView.section.ipfilter.discardminkb=\u6700\u5c0f\u30c7\u30fc\u30bf\u91cf (%1) ConfigView.interface.start.advanced=\u30a2\u30c9\u30d0\u30f3\u30b9\u30c8\u30d3\u30e5\u30fc (AZ 2.x) \u3067\u8d77\u52d5 MyTorrents.column.ColumnQuality=\u54c1\u8cea MyTorrents.column.ColumnSpeed=\u901f\u5ea6 MyTorrents.column.ColumnProgressETA.2ndLine=\u6b8b\u308a\uff1a%1 MyTorrents.column.ColumnProgressETA.StreamReady=\u6e96\u5099\u5b8c\u4e86 MyTorrents.column.ColumnProgressETA.PlayableIn=\u518d\u751f\u53ef\u80fd\u307e\u3067 %1 TableColumn.header.Quality=\u54c1\u8cea TableColumn.header.Speed=\u901f\u5ea6 TableColumn.header.RateIt=\u30ec\u30fc\u30c8 TableColumn.header.Rating=\u30ec\u30fc\u30c8 TableColumn.header.SpeedGraphic=\u901f\u5ea6 TableColumn.header.AzProduct=\u63d0\u4f9b\u5143 TableColumn.header.MediaThumb=\u30e1\u30c7\u30a3\u30a2 TableColumn.header.ProgressETA=\u72b6\u6cc1 #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=\u30d5\u30a1\u30a4\u30eb\u5f62\u5f0f: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9 v3.MainWindow.tab.browse=Vuze v3.MainWindow.tab.library=\u30e9\u30a4\u30d6\u30e9\u30ea v3.MainWindow.tab.publish=\u516c\u958b v3.MainWindow.tab.advanced=\u30a2\u30c9\u30d0\u30f3\u30b9\u30c8 v3.MainWindow.menu.home=\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9 v3.MainWindow.menu.browse=Vuze v3.MainWindow.menu.library=\u30e9\u30a4\u30d6\u30e9\u30ea v3.MainWindow.menu.publish=\u516c\u958b v3.MainWindow.menu.advanced=\u30a2\u30c9\u30d0\u30f3\u30b9\u30c8 v3.MainWindow.menu.view.searchbar=\u691c\u7d22\u30d0\u30fc v3.MainWindow.menu.view.tabbar=\u30bf\u30d6\u30d0\u30fc v3.MainWindow.currentDL=\u73fe\u5728\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d v3.MainWindow.button.stream=\u30b9\u30c8\u30ea\u30fc\u30e0 v3.MainWindow.button.stop=\u505c\u6b62 v3.MainWindow.button.start=\u958b\u59cb v3.MainWindow.button.pause=\u4e00\u6642\u505c\u6b62 v3.MainWindow.button.resume=\u518d\u958b v3.MainWindow.button.delete=\u524a\u9664 v3.MainWindow.button.comment=\u30b3\u30e1\u30f3\u30c8 v3.MainWindow.button.viewdetails=\u8a73\u7d30\u3092\u8868\u793a v3.MainWindow.button.play=\u518d\u751f v3.MainWindow.button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb v3.MainWindow.button.preview=\u30d7\u30ec\u30d3\u30e5\u30fc v3.MainWindow.view.wait=\u521d\u671f\u5316\u4e2d\u3067\u3059\u3002\u304a\u5f85\u3061\u304f\u3060\u3055\u3044\u3002 v3.MainWindow.xofx=%1 / %2 v3.MainWindow.Loading=\u30ed\u30fc\u30c9\u4e2d...\u304a\u5f85\u3061\u304f\u3060\u3055\u3044 v3.filter-bar=\u30d5\u30a3\u30eb\u30bf\uff1a v3.MainWindow.search.defaultText=Torrent \u30b5\u30a4\u30c8\u3092\u691c\u7d22 v3.mb.delPublished.title=\u30b3\u30f3\u30c6\u30f3\u30c4\u306e\u30b7\u30fc\u30c9\u3092\u505c\u6b62 v3.mb.delPublished.text=\u8b66\u544a\uff1a\u3053\u306e\u64cd\u4f5c\u3067\u306f %3 \u304b\u3089\u516c\u958b\u3055\u308c\u3066\u3044\u308b\u30b3\u30f3\u30c6\u30f3\u30c4 '%1' \u306f\u524a\u9664\u3055\u308c\u307e\u305b\u3093\u3002\n\n\u524a\u9664\u3092\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u516c\u958b\u3092\u53d6\u308a\u6d88\u3059\u3060\u3051\u3067\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u53ef\u80fd\u306a\u307e\u307e\u306b\u306a\u308a\u307e\u3059\u3002\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u306b\u5fc5\u8981\u306a\u624b\u9806 (how?) \u304c\u5b8c\u4e86\u3057\u3066\u3044\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\n%3 \u304b\u3089\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u524a\u9664\u3059\u308b\u306b\u306f\u30ad\u30e3\u30f3\u30bb\u30eb\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u3001\u516c\u958b\u30bf\u30d6\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u30d1\u30cd\u30eb\u304b\u3089 (X) \u30dc\u30bf\u30f3\u3092\u62bc\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\n\u8a73\u3057\u304f\u306f More help \u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002\n\n v3.mb.delPublished.delete=\u524a\u9664 v3.mb.delPublished.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb v3.mb.openFile.title=\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304f v3.mb.openFile.text.known=\u3053\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u306f Vuze Player \u3067\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u30b3\u30df\u30e5\u30cb\u30c6\u30a3\u306b\u3088\u3063\u3066\u4f5c\u6210\u3055\u308c\u3066\u3044\u308b Playback Guide \u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002\n\n\u30d5\u30a1\u30a4\u30eb\u5f62\u5f0f: %2 (%3)\n v3.mb.openFile.text.unknown=\u3053\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u306f Vuze Player \u3067\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u30b3\u30df\u30e5\u30cb\u30c6\u30a3\u306b\u3088\u3063\u3066\u4f5c\u6210\u3055\u308c\u3066\u3044\u308b Playback Guide \u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002\n\n\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50: %2\n v3.mb.openFile.button.play=\u518d\u751f v3.mb.openFile.button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb v3.mb.openFile.button.guide=Playback Guide \u3092\u8aad\u3080 v3.mb.openFile.remember=\u78ba\u8a8d\u306a\u3057\u306b\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304f v3.mb.PlayFileNotFound.title=\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 v3.mb.PlayFileNotFound.text=\u6307\u5b9a\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb '%1' \u306f\u524a\u9664\u3055\u308c\u305f\u304b\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 v3.mb.PlayFileNotFound.button.remove=Vuze \u304b\u3089\u524a\u9664 v3.mb.PlayFileNotFound.button.redownload=\u30c7\u30fc\u30bf\u3092\u518d\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 v3.mb.PlayFileNotFound.button.find=\u624b\u52d5\u3067\u691c\u7d22... v3.mb.deletePurchased.title=\u8cfc\u5165\u3057\u305f\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u524a\u9664 v3.mb.deletePurchased.text='%1' \u3092\u524a\u9664\u3057\u307e\u3059\u304b\uff1f\n\n\u3053\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u306f\u8cfc\u5165\u3057\u305f\u3082\u306e\u304b\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u306e\u306b\u30ed\u30b0\u30a4\u30f3\u304c\u5fc5\u8981\u306a\u3082\u306e\u3067\u3059\u3002 v3.mb.deletePurchased.button.delete=\u524a\u9664 v3.mb.deletePurchased.button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb v3.topbar.menu.show.logo=\u30ed\u30b4 v3.topbar.menu.show.plugin=\u30d7\u30e9\u30b0\u30a4\u30f3 v3.topbar.menu.show.search=\u691c\u7d22 splash.initializeCore=Core \u3092\u521d\u671f\u5316\u4e2d splash.initializeUIElements=UI Elements \u3092\u521d\u671f\u5316\u4e2d # ConfigView.section.ipfilter.peerblocking.group=\u30d4\u30a2\u306e\u30d6\u30ed\u30c3\u30af splash.loadIpFilters=IP \u30d5\u30a3\u30eb\u30bf\u3092\u30ed\u30fc\u30c9\u4e2d ConfigView.section.transfer.select.v2=Auto-Speed\uff08\u30d9\u30fc\u30bf\uff09 mb.azmustclose.title=\u8d77\u52d5\u30a8\u30e9\u30fc mb.azmustclose.text=Administrator \u30e6\u30fc\u30b6\u3067\u8d77\u52d5\u3055\u308c\u305f\u305f\u3081 Vuze \u3092\u7d42\u4e86\u3057\u307e\u3059\u3002\n\nVuze \u304c\u7d42\u4e86\u3057\u305f\u5f8c\u3001\u624b\u52d5\u3067\u8d77\u52d5\u3057\u3066\u304f\u3060\u3055\u3044\u3002 network.ipv6.prefer.addresses=IPv6 \u3068 IPv4 \u306e\u4e21\u65b9\u304c\u5229\u7528\u53ef\u80fd\u306a\u5834\u5408\u3001IPv6 \u30a2\u30c9\u30ec\u30b9\u3092\u4f7f\u7528 DHTView.title.full_v6=\u5206\u6563\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 IPv6 ConfigView.pluginlist.loadSelected=\u9078\u629e\u3055\u308c\u305f\u9805\u76ee\u3092\u30ed\u30fc\u30c9 ConfigView.section.transfer.autospeed.networks=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u8a73\u7d30 ConfigView.section.transfer.autospeed.resetnetwork=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u8a73\u7d30\u8a2d\u5b9a\u3092\u5143\u306b\u623b\u3059 ConfigView.section.transfer.autospeed.network.info=\u4e0a\u8a18\u306e\u5024\u306f\u901a\u5e38\u3001\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d\u306e\u81ea\u52d5\u8abf\u6574\u5024\u304b\u30b9\u30d4\u30fc\u30c9\u30c6\u30b9\u30c8\u306e\u7d50\u679c\u5024\u3067\u3059\u3002\u4e0b\u8a18\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306b\u3088\u308a\u624b\u52d5\u3067\u8a2d\u5b9a\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\n'\u56fa\u5b9a'\u4ee5\u5916\u306e\u5024\u306f\u5fc5\u8981\u306b\u5fdc\u3058\u3066\u81ea\u52d5\u7684\u306b\u8abf\u6574\u3055\u308c\u307e\u3059\u3002\n\u5024\u3092\u5165\u529b\u3057\u3066\u7a2e\u985e\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u901f\u5ea6\u306f %1 \u3067\u3059\u3002 dialog.uiswitcher.restart.title=UI Switcher: Vuze \u306e\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u3067\u3059 dialog.uiswitcher.restart.text=\u65b0\u3057\u3044 UI \u30e2\u30fc\u30c9\u306b\u5207\u308a\u66ff\u3048\u308b\u305f\u3081 Vuze \u3092\u518d\u8d77\u52d5\u3057\u3066\u304f\u3060\u3055\u3044\u3002 TrayWindow.menu.close=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30d0\u30b9\u30b1\u30c3\u30c8\u3092\u9589\u3058\u308b # Used for peers which we can't determine. OpenTorrentWindow.mb.askCreateDir.title=\u4fdd\u5b58\u5148\u306e\u30d5\u30a9\u30eb\u30c0\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 OpenTorrentWindow.mb.askCreateDir.text=\u4fdd\u5b58\u5148\u306e\u30d5\u30a9\u30eb\u30c0 '%1' \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002\n\n\u4f5c\u6210\u3057\u307e\u3059\u304b\uff1f ConfigTransferAutoSpeed.upload.capacity.usage=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u5bb9\u91cf\u306e\u4f7f\u7528\u7387 ConfigTransferAutoSpeed.mode=\u30e2\u30fc\u30c9\uff1a ConfigTransferAutoSpeed.while.downloading=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d\uff1a ConfigTransferAutoSpeed.set.dht.ping=DHT Ping \u8a2d\u5b9a: ConfigTransferAutoSpeed.adjustment.interval=\u8abf\u6574\u9593\u9694: ConfigTransferAutoSpeed.skip.after.adjust=\u8abf\u6574\u5f8c\u306b\u30b9\u30ad\u30c3\u30d7 GeneralView.label.distributedCopies=\u5206\u6563\u30b3\u30d4\u30fc\uff1a PeersView.gain=\u8ee2\u9001\u91cf\u306e\u5dee PeersView.gain.info=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 - \u30a2\u30c3\u30d7\u30ed\u30fc\u30c9 \u306e\u5dee unix.script.new.title=\u65b0\u3057\u3044 Vuze \u8d77\u52d5\u30b9\u30af\u30ea\u30d7\u30c8\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f unix.script.new.text=\u65b0\u3057\u3044 Vuze \u8d77\u52d5\u30b9\u30af\u30ea\u30d7\u30c8\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002\u30b9\u30af\u30ea\u30d7\u30c8\u306f '%1' \u306b\u4fdd\u5b58\u3055\u308c\u307e\u3057\u305f\u3002\n\n\u4eca\u3059\u3050 Vuze \u3092\u7d42\u4e86\u3057\u3066\u65b0\u3057\u3044\u30b9\u30af\u30ea\u30d7\u30c8 ('%2') \u306b\u5207\u308a\u66ff\u3048\u308b\u3053\u3068\u3092\u304a\u52e7\u3081\u3057\u307e\u3059\u3002\n\n\u3082\u3057 Vuze \u8d77\u52d5\u30b9\u30af\u30ea\u30d7\u30c8\u3092\u5909\u66f4\u3057\u3066\u3044\u308b\u5834\u5408\u306f\u3001AzureusWiki: Unix Script \u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002\n\n\u3082\u3057 Vuze \u3092\u30c7\u30a3\u30b9\u30c8\u30ea\u30d3\u30e5\u30fc\u30b7\u30e7\u30f3 (yum, apt-get, etc) \u304b\u3089\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u306f Vuze \u3092 Vuze Sourceforge Page \u304b\u3089\u30d1\u30c3\u30b1\u30fc\u30b8\u3092\u5165\u624b\u3057\u3066\u518d\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u3053\u3068\u3092\u304a\u52e7\u3081\u3057\u307e\u3059\u3002 unix.script.new.button.quit=\u4eca\u3059\u3050\u7d42\u4e86 unix.script.new.button.continue=\u5f8c\u3067 unix.script.new.button.asknomore=\u4eca\u5f8c\u5c0b\u306d\u306a\u3044 unix.script.new.auto.title=\u65b0\u3057\u3044 Vuze \u8d77\u52d5\u30b9\u30af\u30ea\u30d7\u30c8 unix.script.new.auto.text=\u65b0\u3057\u3044 Vuze \u8d77\u52d5\u30b9\u30af\u30ea\u30d7\u30c8\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002\n\n\u4eca\u3059\u3050 Vuze \u3092\u518d\u8d77\u52d5\u3059\u308b\u3053\u3068\u3092\u304a\u52e7\u3081\u3057\u307e\u3059\u3002 Content.alert.notuploaded.button.stop=\u505c\u6b62 Content.alert.notuploaded.button.continue=\u30b7\u30fc\u30c9\u3092\u7d9a\u3051\u308b Content.alert.notuploaded.button.abort=\u7d42\u4e86\u3057\u306a\u3044 ConfigView.label.checkOnSeeding=\u30b7\u30fc\u30c9\u6642\u306b\u30d4\u30fc\u30b9\u3092\u518d\u30c1\u30a7\u30c3\u30af\u3059\u308b ConfigView.label.ui_switcher=Vuze UI Chooser \u3092\u8868\u793a ConfigView.label.ui_switcher_button=\u8868\u793a ConfigTransferAutoSpeed.add.comment.to.log.group=\u30c7\u30d0\u30c3\u30b0\u30ed\u30b0\u306b\u30b3\u30e1\u30f3\u30c8\u3092\u8ffd\u52a0 ConfigTransferAutoSpeed.add.comment.to.log=\u30b3\u30e1\u30f3\u30c8\uff1a ConfigTransferAutoSpeed.log.button=\u30ed\u30b0 ConfigTransferAutoSpeed.algorithm.selector=\u81ea\u52d5\u901f\u5ea6\u9078\u629e ConfigTransferAutoSpeed.algorithm=\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0: ConfigTransferAutoSpeed.auto.speed.classic=\u81ea\u52d5\u901f\u5ea6\uff08\u65e7\u30d0\u30fc\u30b8\u30e7\u30f3\uff09 ConfigTransferAutoSpeed.auto.speed.beta=\u81ea\u52d5\u901f\u5ea6\uff08\u30d9\u30fc\u30bf\uff09 ConfigTransferAutoSpeed.data.update.frequency=\u66f4\u65b0\u9593\u9694 Alert.failed.update=\u5c11\u306a\u304f\u3068\u3082 1 \u3064\u4ee5\u4e0a\u306e\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u304c\u5931\u6557\u3057\u307e\u3057\u305f\u3002AzureusWiki: Failed Update [%1] \u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002 OpenTorrentWindow.mb.existingFiles.partialList=\uff08\u4e00\u90e8\u306e\u307f\u3067\u3059\u3002\u3055\u3089\u306b\u591a\u304f\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u307e\u3059\u3002\uff09 TableColumn.header.bad_avail_time.info=\u30d5\u30a1\u30a4\u30eb\u306e\u5b8c\u5168\u306a\u30b3\u30d4\u30fc\u304c\u6700\u5f8c\u306b\u78ba\u8a8d\u3055\u308c\u305f\u65e5\u6642 TableColumn.header.bad_avail_time=\u751f\u5b58\u78ba\u8a8d\u65e5\u6642 MyTorrentsView.menu.exporthttpseeds=HTTP \u30b7\u30fc\u30c9 URL \u3092\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u306b\u66f8\u304d\u51fa\u3059 SWT.alert.erroringuithread=GUI \u3067\u672a\u30cf\u30f3\u30c9\u30eb\u306e\u30a8\u30e9\u30fc\u304c\u7f6e\u304d\u307e\u3057\u305f\u3002\u3055\u3089\u306b\u30a8\u30e9\u30fc\u304c\u5831\u544a\u3055\u308c\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 ConfigView.label.minannounce=\u6700\u5c0f\u30c8\u30e9\u30c3\u30ab\u30fc\u30a2\u30ca\u30a6\u30f3\u30b9\u9593\u9694 [sec] ConfigView.label.announceport=\u30c8\u30e9\u30c3\u30ab\u30fc, DHT \u306b\u901a\u77e5\u3059\u308b\u30dd\u30fc\u30c8\u756a\u53f7\u3092\u500b\u5225\u306b\u6307\u5b9a\n[\u7a7a\u6b04: \u6307\u5b9a\u3057\u306a\u3044, 0: \u63a5\u7d9a\u3092\u53d7\u3051\u5165\u308c\u306a\u3044] ConfigView.label.noportannounce=\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u30dd\u30fc\u30c8\u3092\u901a\u77e5\u3057\u306a\u3044\uff08PEX, DHT \u306b\u306f\u5f71\u97ff\u3057\u307e\u305b\u3093\uff09 ConfigView.label.maxseedspertorrent=Torrent \u3054\u3068\u306e\u6700\u5927\u30b7\u30fc\u30c9\u6570\u306e\u30c7\u30d5\u30a9\u30eb\u30c8 [0: \u7121\u5236\u9650] wizard.webseed=Torrent \u306b HTTP \u30b7\u30fc\u30c9\u3092\u8ffd\u52a0 wizard.webseed.title=HTTP \u30b7\u30fc\u30c9 wizard.webseed.configuration=HTTP \u30b7\u30fc\u30c9\u306e\u8a2d\u5b9a wizard.webseed.adding=HTTP \u30b7\u30fc\u30c9\u3092\u8ffd\u52a0\u4e2d GeneralView.label.private=Private Torrent\uff1a GeneralView.yes=\u306f\u3044 GeneralView.no=\u3044\u3044\u3048 ConfigView.label.userequestlimitingpriorities=\u6700\u5927\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6\u306b\u9054\u3057\u305f\u5834\u5408\u3001\u30ad\u30e5\u30fc\u306e\u5148\u982d\u306e\u30bf\u30b9\u30af\u3092\u512a\u5148 ConfigView.section.logging.timestamp=\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u306e\u66f8\u5f0f\uff1a ConfigView.section.interface.display.suppress.file.download.dialog=\u30d5\u30a1\u30a4\u30eb\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30dd\u30c3\u30d7\u30a2\u30c3\u30d7\u3092\u8868\u793a\u3057\u306a\u3044 ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=\u3059\u3079\u3066\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u72b6\u6cc1\u3092\u30dd\u30c3\u30d7\u30a2\u30c3\u30d7\u30c0\u30a4\u30a2\u30ed\u30b0\u306e\u4ee3\u308f\u308a\u306b\u30b9\u30c6\u30fc\u30bf\u30b9\u30d0\u30fc\u306b\u8868\u793a\u3057\u307e\u3059 FileDownload.canceled=\u30e6\u30fc\u30b6\u306e\u30a2\u30af\u30b7\u30e7\u30f3\uff08%1\uff09\u306b\u3088\u308a Torrent \u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u53d6\u308a\u6d88\u3057\u307e\u3057\u305f Progress.reporting.status.canceled=\u30ad\u30e3\u30f3\u30bb\u30eb Progress.reporting.status.finished=\u5b8c\u4e86 Progress.reporting.status.retrying=\u30ea\u30c8\u30e9\u30a4\u4e2d... Progress.reporting.action.label.retry.tooltip=\u64cd\u4f5c\u3092\u30ea\u30c8\u30e9\u30a4 Progress.reporting.action.label.remove.tooltip=\u5c65\u6b74\u304b\u3089\u9032\u884c\u72b6\u6cc1\u30ec\u30dd\u30fc\u30c8\u3092\u524a\u9664 Progress.reporting.action.label.cancel.tooltip=\u64cd\u4f5c\u3092\u30ad\u30e3\u30f3\u30bb\u30eb Progress.reporting.action.label.detail=\u8a73\u7d30 Progress.reporting.default.error=\u5931\u6557 Progress.reporting.no.reports.to.display=\u73fe\u5728\u8868\u793a\u3067\u304d\u308b\u9032\u884c\u72b6\u6cc1\u30ec\u30dd\u30fc\u30c8\u306f\u3042\u308a\u307e\u305b\u3093\u3002 Progress.reporting.no.history.to.display=\u8a73\u7d30\u30e1\u30c3\u30bb\u30fc\u30b8\u306f\u3042\u308a\u307e\u305b\u3093\u3002 Progress.reporting.detail.history.limit=ProgressReporter \u304b\u3089\u306e\u8a73\u7d30\u30e1\u30c3\u30bb\u30fc\u30b8\u8a18\u9332\u4e0a\u9650 (%1) \u3092\u8d85\u3048\u307e\u3057\u305f\u3002\u3053\u308c\u4ee5\u4e0a\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u306f\u5c65\u6b74\u306b\u8ffd\u52a0\u3055\u308c\u307e\u305b\u3093\u3002 Progress.reporting.statusbar.button.tooltip=\u9032\u884c\u72b6\u6cc1\u30ec\u30dd\u30fc\u30c8\u30a6\u30a4\u30f3\u30c9\u30a6\u3092\u8868\u793a webui.bindip=IP \u3092\u30d0\u30a4\u30f3\u30c9 - \u901a\u5e38\u306f\u4e0d\u8981 (*) v3.MainWindow.text.log.in=\u30b5\u30a4\u30f3\u30a4\u30f3 v3.MainWindow.text.log.out=\u30b5\u30a4\u30f3\u30a2\u30a6\u30c8 v3.MainWindow.text.get.started=\u30b5\u30a4\u30f3\u30a2\u30c3\u30d7 v3.MainWindow.text.my.account=\u30a2\u30ab\u30a6\u30f3\u30c8 OpenTorrentWindow.simple.open=Torrent \u306e\u5834\u6240\uff08\u30d5\u30a1\u30a4\u30eb, URL, \u30cf\u30c3\u30b7\u30e5\uff09 Progress.reporting.window.remove.auto=\u975e\u30a2\u30af\u30c6\u30a3\u30d6\u306a\u9805\u76ee\u3092\u81ea\u52d5\u7684\u306b\u524a\u9664 Progress.reporting.window.remove.auto.tooltip=\u5b8c\u4e86\u30fb\u5931\u6557\u30fb\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u305f\u9805\u76ee\u3092\u81ea\u52d5\u7684\u306b\u524a\u9664\u3057\u307e\u3059 Progress.reporting.window.remove.now=\u975e\u30a2\u30af\u30c6\u30a3\u30d6\u306a\u9805\u76ee\u3092\u524a\u9664 Progress.reporting.window.remove.now.tooltip=\u5b8c\u4e86\u30fb\u5931\u6557\u30fb\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u305f\u9805\u76ee\u3092\u524a\u9664\u3057\u307e\u3059 TorrentOptionsView.multi.title.short=\u74b0\u5883\u8a2d\u5b9a TorrentOptionsView.multi.title.full=\u74b0\u5883\u8a2d\u5b9a MyTorrentsView.menu.open_parent_folder=\u5305\u6709\u3059\u308b\u30d5\u30a9\u30eb\u30c0\u3092\u958b\u304f ConfigView.section.style.use_show_parent_folder=Torren \u30e1\u30cb\u30e5\u30fc\u306e "%2" \u306e\u4ee3\u308f\u308a\u306b "%1" \u3092\u4f7f\u7528 ConfigView.section.style.use_show_parent_folder.tooltip=\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306b\u3088\u308a\u30d5\u30a1\u30a4\u30eb\u30de\u30cd\u30fc\u30b8\u30e3\u3067\u30d5\u30a9\u30eb\u30c0\u3092\u958b\u3051\u308b\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002\n\u3057\u304b\u3057\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5148\u306f\u81ea\u52d5\u7684\u306b\u6c7a\u5b9a\u3055\u308c\u307e\u305b\u3093\u3002 PeerManager.status.ps_disabled=\u30c8\u30e9\u30c3\u30ab\u30fc\u306e\u30d4\u30a2\u30bd\u30fc\u30b9\u304c\u7121\u52b9\u3067\u3059 ConfigView.section.stats.exportfiles=\u30d5\u30a1\u30a4\u30eb\u306e\u8a73\u7d30\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 updater.cant.write.to.app.title=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30d5\u30a9\u30eb\u30c0\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093 updater.cant.write.to.app.details=\u30d5\u30a9\u30eb\u30c0 "%1" \u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002\n\n\u4eca\u5f8c\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306b\u3088\u308b\u66f4\u65b0\u304c\u3067\u304d\u307e\u305b\u3093\u3002\n\nsee the wiki for details \u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002 plugin.install.class_version_error=\u3053\u306e\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u4f7f\u7528\u3059\u308b\u306b\u306f\u6700\u65b0\u306e Java \u304c\u5fc5\u8981\u3067\u3059\u3002 v3.MainWindow.tab.minilibrary=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 v3.MainWindow.tab.events=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 button.columnsetup.tooltip=\u5217\u306e\u8a2d\u5b9a v3.activity.remove.title=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u30a4\u30d9\u30f3\u30c8\u306e\u524a\u9664 v3.activity.remove.text=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u30a4\u30d9\u30f3\u30c8 '%1' \u3092\u524a\u9664\u3057\u307e\u3059\u304b\uff1f #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=\u9589\u3058\u308b Menu.show.torrent.menu=Torrent \u30e1\u30cb\u30e5\u30fc\u3092\u8868\u793a Menu.show.torrent.menu.tooltip=\u30e1\u30cb\u30e5\u30fc\u30d0\u30fc\u306b Torrent \u30e1\u30cb\u30e5\u30fc\u3092\u8868\u793a\u3057\u307e\u3059 #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u72b6\u614b plugin.aznetstatus.pingtarget=Ping/traceroute \u5148 ConfigView.section.style.usePathFinder='Finder' \u306e\u4ee3\u308f\u308a\u306b 'Path Finder' \u3092\u4f7f\u7528 menu.sortByColumn=%1 \u3067\u30bd\u30fc\u30c8 MyTorrentsView.menu.manual.per_peer=\u624b\u52d5\uff08\u30d4\u30a2\u3054\u3068\uff09 MyTorrentsView.menu.manual.shared_peers=\u624b\u52d5\uff08\u30d4\u30a2\u5171\u6709\uff09 v3.button.removeActivityEntry=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u30a8\u30f3\u30c8\u30ea\u3092\u524a\u9664 v3.splash.initSkin=UI \u30b9\u30ad\u30f3\u3092\u521d\u671f\u5316\u4e2d v3.splash.hookPluginUI=\u30d7\u30e9\u30b0\u30a4\u30f3 UI \u3092\u30d5\u30c3\u30af\u4e2d OpenTorrentWindow.mb.notTorrent.cannot.display=\u30c7\u30fc\u30bf\u3092\u8868\u793a\u3067\u304d\u307e\u305b\u3093\u3002 MainWindow.menu.window.zoom.maximize=\u6700\u5927\u5316 MainWindow.menu.window.zoom.restore=\u30ea\u30b9\u30c8\u30a2 ImageResizer.image.too.small=\u753b\u50cf\u304c\u5c0f\u3055\u3059\u304e\u307e\u3059\u3002\u5225\u306e\u753b\u50cf\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\uff08%1 x %2 \u4ee5\u4e0a\uff09 ImageResizer.title=Vuze \u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u306b\u8868\u793a\u3055\u308c\u308b\u30b5\u30e0\u30cd\u30fc\u30eb\u3092\u30d7\u30ec\u30d3\u30e5\u30fc\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059 ImageResizer.move.image=\u30c9\u30e9\u30c3\u30b0\u3057\u3066\u753b\u50cf\u3092\u79fb\u52d5\u3057\u307e\u3059 ImageResizer.move.image.with.slider=\u30c9\u30e9\u30c3\u30b0\u3057\u3066\u753b\u50cf\u3092\u79fb\u52d5\u3057\u3001\u4e0b\u306e\u30b9\u30e9\u30a4\u30c0\u30fc\u3067\u30b5\u30a4\u30ba\u3092\u5909\u66f4\u3057\u307e\u3059 security.crypto.title=\u6697\u53f7\u9375\u3078\u306e\u30a2\u30af\u30bb\u30b9 security.crypto.encrypt=\u65b0\u3057\u304f\u4f5c\u6210\u3057\u305f\u6697\u53f7\u9375\u3092\u4fdd\u8b77\u3059\u308b\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5fd8\u308c\u308b\u3068\u89e3\u9664\u3067\u304d\u306a\u3044\u305f\u3081\u3001\u5fd8\u308c\u306a\u3044\u3088\u3046\u306b\u6ce8\u610f\u3057\u3066\u304f\u3060\u3055\u3044\u3002 security.crypto.decrypt=\u6697\u53f7\u9375\u3092\u89e3\u9664\u3059\u308b\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 security.crypto.reason=\u64cd\u4f5c\u7406\u7531 security.crypto.password=\u30d1\u30b9\u30ef\u30fc\u30c9 security.crypto.password2=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u518d\u5165\u529b security.crypto.persist_for=\u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u6709\u52b9\u671f\u9593 security.crypto.persist_for.dont_save=\u4fdd\u5b58\u3057\u306a\u3044 security.crypto.persist_for.session=\u4eca\u56de\u306e\u307f security.crypto.persist_for.day=1 \u65e5 security.crypto.persist_for.week=1 \u9031\u9593 security.crypto.persist_for.30days=30 \u65e5 security.crypto.persist_for.forever=\u7121\u671f\u9650 security.crypto.password.mismatch.title=\u30d1\u30b9\u30ef\u30fc\u30c9\u30a8\u30e9\u30fc security.crypto.password.mismatch=\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u4e00\u81f4\u3057\u307e\u305b\u3093\u3002\u3082\u3046\u4e00\u5ea6\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 ConfigView.section.security.group.crypto=\u516c\u958b\uff0f\u79d8\u5bc6\u9375 ConfigView.section.security.resetkey=\u9375\u3092\u30ea\u30bb\u30c3\u30c8 ConfigView.section.security.resetkey.warning.title=\u8b66\u544a ConfigView.section.security.resetkey.warning=\u6697\u53f7\u9375\u3092\u30ea\u30bb\u30c3\u30c8\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f\u6697\u53f7\u5316\u3055\u308c\u305f\u60c5\u5831\u306f\u3059\u3079\u3066\u7121\u304f\u306a\u308a\u307e\u3059\u3002\u3042\u306a\u305f\u3068\u306e\u63a5\u7d9a\u306b\u516c\u958b\u9375\u3092\u5229\u7528\u3057\u3066\u3044\u308b\u307b\u304b\u306e\u30e6\u30fc\u30b6\u306f\u65b0\u3057\u3044\u9375\u306b\u7f6e\u304d\u63db\u3048\u308b\u307e\u3067\u3042\u306a\u305f\u306b\u63a5\u7d9a\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002\u3088\u304f\u308f\u304b\u3089\u306a\u3044\u5834\u5408\u306f\u30ea\u30bb\u30c3\u30c8\u3057\u306a\u3044\u3067\u304f\u3060\u3055\u3044\u3002 ConfigView.section.security.unlockkey=\u9375\u306e\u89e3\u9664 ConfigView.section.security.unlockkey.button=\u89e3\u9664 ConfigView.section.security.publickey=\u516c\u958b\u9375 ConfigView.section.security.publickey.undef=\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093 ConfigView.section.security.resetkey.error.title=\u30a8\u30e9\u30fc ConfigView.section.security.resetkey.error=\u9375\u306e\u30ea\u30bb\u30c3\u30c8\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 ConfigView.section.security.unlockkey.error=\u9375\u306e\u89e3\u9664\u306b\u5931\u6557\u3057\u307e\u3057\u305f - \u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u9055\u3044\u307e\u3059 ConfigView.copy.to.clipboard.tooltip=\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u306b\u30b3\u30d4\u30fc Views.plugins.azbuddy.title=Friend Browser.popup.error.no.access=\u30ea\u30e2\u30fc\u30c8\u30ea\u30bd\u30fc\u30b9\u3078\u306e\u30a2\u30af\u30bb\u30b9\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u7f6e\u304d\u307e\u3057\u305f\u3002\n\u3057\u3070\u3089\u304f\u3057\u305f\u5f8c\u306b\u30a2\u30af\u30bb\u30b9\u3057\u3066\u307f\u3066\u304f\u3060\u3055\u3044\u3002\n ConfigView.label.queue.stoponcebandwidthmet=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9/\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u901f\u5ea6\u304c\u4e0a\u9650\u306b\u9054\u3057\u305f\u5834\u5408\u3001\u307b\u304b\u306e Torrent \u3092\u958b\u59cb\u3057\u306a\u3044 ConfigView.section.style.forceMozilla=Vuze \u306e\u30d6\u30e9\u30a6\u30b6\u30a6\u30a3\u30b8\u30a7\u30c3\u30c8\u306b Mozilla \u3092\u4f7f\u7528 [XulRunner \u307e\u305f\u306f Firefox 3 \u304c\u5fc5\u8981; \u8981\u518d\u8d77\u52d5] ConfigView.section.style.xulRunnerPath=XulRunner/Firefox \u306e\u30d1\u30b9\u3092\u6307\u5b9a [FF3 \u306e\u5834\u5408\u306b\u5fc5\u8981; \u8981\u518d\u8d77\u52d5] azbuddy.enabled=\u6709\u52b9 azbuddy.disabled=\u30d7\u30e9\u30b0\u30a4\u30f3\u304c\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002\u30d7\u30e9\u30b0\u30a4\u30f3\u8a2d\u5b9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 azbuddy.nickname=\u30cb\u30c3\u30af\u30cd\u30fc\u30e0\uff1a azbuddy.msglog.title=Friend \u306e\u60c5\u5831 azbuddy.addtorrent.title=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u306e\u78ba\u8a8d azbuddy.addtorrent.msg=Friend '%1' \u304b\u3089 '%2' \u304c\u9001\u3089\u308c\u3066\u304d\u307e\u3057\u305f\u3002\n\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30ea\u30b9\u30c8\u306b\u8ffd\u52a0\u3057\u307e\u3059\u304b\uff1f azbuddy.contextmenu=Friend \u306b\u9001\u308b azbuddy.ui.mykey=\u3042\u306a\u305f\u306e\u9375: azbuddy.ui.add=\u8ffd\u52a0 azbuddy.ui.new_buddy=\u65b0\u898f Friend \u306e\u9375: azbuddy.ui.menu.remove=\u524a\u9664 azbuddy.ui.menu.copypk=\u30d1\u30d6\u30ea\u30c3\u30af\u30ad\u30fc\u3092\u30b3\u30d4\u30fc azbuddy.ui.menu.send=\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u9001\u4fe1 azbuddy.ui.menu.send_msg=Friend \u306b\u9001\u308b\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044 azbuddy.ui.menu.ygm=YGM \u3092\u9001\u4fe1 azbuddy.ui.menu.enc=\u30af\u30ea\u30c3\u30d4\u30dc\u30fc\u30c9\u3092\u6697\u53f7\u5316 azbuddy.ui.menu.dec=\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u3092\u5fa9\u53f7\u5316 azbuddy.ui.menu.sign=\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u306b\u7f72\u540d azbuddy.ui.menu.verify=\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u3092\u691c\u8a3c Button.retry=\u30ea\u30c8\u30e9\u30a4 Button.ignore=\u7121\u8996 v3.MainWindow.menu.view.footer=Friend \u30d0\u30fc security.crypto.badpw=\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u9055\u3044\u307e\u3059\u3002 ConfigView.section.security.backupkeys=\u9375\u3092\u30d0\u30c3\u30af\u30a2\u30c3\u30d7 ConfigView.section.security.backupkeys.button=\u30d0\u30c3\u30af\u30a2\u30c3\u30d7 ConfigView.section.security.restorekeys=\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u9375\u3092\u30ea\u30b9\u30c8\u30a2 ConfigView.section.security.restorekeys.button=\u30ea\u30b9\u30c8\u30a2 ConfigView.section.security.op.error.title=\u30a8\u30e9\u30fc ConfigView.section.security.op.error=\u6b21\u306e\u51e6\u7406\u306b\u5931\u6557\u3057\u307e\u3057\u305f:\n %1 ConfigView.section.security.restart.title=\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u3067\u3059 ConfigView.section.security.restart.msg=\u64cd\u4f5c\u3092\u5b8c\u4e86\u3055\u305b\u308b\u305f\u3081\u306b\u518d\u8d77\u52d5\u3057\u307e\u3059\u3002 azbuddy.ui.menu.chat=\u30c1\u30e3\u30c3\u30c8 azbuddy.chat.title=Vuze \u30c1\u30e3\u30c3\u30c8 azbuddy.chat.says=%1 \u306e\u767a\u8a00: Button.bar.show=\u8868\u793a Button.bar.hide=\u96a0\u3059 Button.bar.share=\u5171\u6709 Button.bar.add=Friends \u3092\u8ffd\u52a0 Button.bar.edit=\u7de8\u96c6 Button.bar.edit.cancel=\u7d42\u4e86 v3.MainWindow.menu.view.pluginbar=\u30d7\u30e9\u30b0\u30a4\u30f3\u30d0\u30fc MainWindow.dialog.select.vuze.file=Vuze \u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 MainWindow.menu.file.open.vuze=Vuze \u30d5\u30a1\u30a4\u30eb... metasearch.addtemplate.title=\u691c\u7d22\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb metasearch.addtemplate.desc=\u691c\u7d22\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 '%1' \u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u307e\u3059\u304b\uff1f v3.share.private.title=Torrent \u3092\u5171\u6709 v3.share.private.text=\u9078\u629e\u3055\u308c\u305f Torrent \u306f Private Torrent \u3067\u3059\u3002\n\nPrivate Torrent \u306f\u5171\u6709\u3067\u304d\u307e\u305b\u3093\u3002 metasearch.addtemplate.dup.title=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u91cd\u8907 metasearch.addtemplate.dup.desc=\u691c\u7d22\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 %1 \u306f\u65e2\u306b\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u3066\u3044\u307e\u3059\u3002 metasearch.export.select.template.file=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4fdd\u5b58 metasearch.import.select.template.file=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u958b\u304f dialog.uiswitch.title=Vuze UI \u306e\u5207\u308a\u66ff\u3048 dialog.uiswitch.text=\u3053\u306e\u6a5f\u80fd\u3092\u5229\u7528\u3059\u308b\u306b\u306f Vuze UI \u306b\u5207\u308a\u66ff\u3048\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\n\nVuze \u3092\u518d\u8d77\u52d5\u3057\u3066\u304f\u3060\u3055\u3044\u3002 dialog.uiswitch.button=Vuze UI \u306b\u5207\u308a\u66ff\u3048\u308b azbuddy.tracker.enabled=Friend \u3068\u306e\u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u3092\u9ad8\u901f\u306b\u3059\u308b 'Friends Boost' \u3092\u4f7f\u7528 v3.MainWindow.button.download=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 v3.MainWindow.button.run=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304f v3.activity.header.downloads=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 v3.activity.header.vuze.news=Vuze \u30cb\u30e5\u30fc\u30b9 message.taking.too.long=\u9577\u3044\u6642\u9593\u304b\u304b\u3063\u3066\u3044\u308b\u5834\u5408\u306f\u3001\n'ESC' \u3092\u62bc\u3059\u3068\u64cd\u4f5c\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 message.status.success=\u6210\u529f azbuddy.tracker.bbb.status.title.tooltip=\u8a73\u7d30\u3092\u898b\u308b\u306b\u306f\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002 v3.MainWindow.search.go.tooltip=\u691c\u7d22\u3092\u5b9f\u884c\u3057\u307e\u3059 v3.MainWindow.search.last.tooltip=\u691c\u7d22\u7d50\u679c\u306b\u623b\u308a\u307e\u3059 metasearch.addtemplate.done.title=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u304c\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f metasearch.addtemplate.done.desc=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 '%1' \u304c\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f\u3002\n\u6b21\u56de\u306e\u691c\u7d22\u304b\u3089\u3054\u5229\u7528\u306b\u306a\u308c\u307e\u3059\u3002 ConfigView.section.security.nopw=\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 ConfigView.section.security.nopw_v=\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002Vuze \u306b\u7f72\u540d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 fileplugininstall.install.title=\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb fileplugininstall.install.desc=\u30d7\u30e9\u30b0\u30a4\u30f3 '%1' %2 \u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u307e\u3059\u304b\uff1f fileplugininstall.duplicate.title=\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u91cd\u8907 fileplugininstall.duplicate.desc=\u30d7\u30e9\u30b0\u30a4\u30f3 '%1' %2 \u306f\u65e2\u306b\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u3066\u3044\u307e\u3059\u3002 azbuddy.online_status=\u30b9\u30c6\u30fc\u30bf\u30b9\uff1a azbuddy.ui.menu.disconnect=\u5207\u65ad azbuddy.enable_chat_notif=\u30c1\u30e3\u30c3\u30c8\u306e\u7740\u4fe1\u3092\u901a\u77e5 iconBar.queue.tooltip=\u30ad\u30e5\u30fc MainWindow.menu.help.faq=FAQ TableColumn.header.#=No. MainWindow.menu.help.donate=\u5bc4\u4ed8\u3092\u9001\u4ed8 azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_pt_PT.properties0000644000175000017500000042452411301156004026130 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Ficheiro .torrent Main.parameter.usage=Utiliza\u00e7\u00e3o : java org.gudy.azureus2.cl.Main [par\u00e2metros] "file.torrent" "guardar pasta" Main.parameter.maxUploads=N\u00famero m\u00e1ximo de envios Main.parameter.maxSpeed=Velocidade m\u00e1xima de envio em bytes/seg MainWindow.menu.file=&Ficheiro MainWindow.menu.file.open=&Abrir MainWindow.menu.file.create=&Criar um Torrent MainWindow.menu.file.create.fromfile=De um &Ficheiro MainWindow.menu.file.create.fromdir=De uma &Directoria MainWindow.menu.file.export=&Exportar um Torrent... MainWindow.menu.file.import=&Importar um Torrent... MainWindow.menu.file.closetab=Fechar &Tab MainWindow.menu.file.closewindow=Fechar &Janela MainWindow.menu.file.exit=&Sair MainWindow.dialog.choose.file=Escolha o ficheiro .torrent MainWindow.menu.file.folder=&Directoria MainWindow.dialog.choose.folder=Escolha o direct\u00f3rio que cont\u00e9m os ficheiros .torrent MainWindow.menu.view=&Ver MainWindow.menu.view.show=Mostrar MainWindow.menu.view.mytorrents=&Os meus torrents MainWindow.menu.view.configuration=&Configura\u00e7\u00e3o MainWindow.menu.view.console=C&onsola MainWindow.menu.closealldetails=Fe&char todos os Detalhes MainWindow.menu.closealldownloadbars=Fechar todas as &barras de download MainWindow.menu.language=&Idioma ConfigView.section.language=Idioma MainWindow.menu.window=&Janela MainWindow.menu.window.minimize=&Minimizar MainWindow.menu.window.alltofront=Trazer tudo para a &Frente MainWindow.menu.help=&Ajuda MainWindow.menu.help.about=&Sobre o Vuze MainWindow.about.title=Sobre MainWindow.about.section.developers=Colaboradores MainWindow.about.section.translators=Tradutores MainWindow.about.section.system=Sistema MainWindow.about.internet.homepage=P\u00e1gina do Vuze MainWindow.about.internet.sourceforge=P\u00e1gina do Projecto na Sourceforge MainWindow.about.internet.sourceforgedownloads=Transfer\u00eancias da Sourceforge MainWindow.about.internet.bugreports=Reportar Erros MainWindow.about.internet.forumdiscussion=Forum Geral MainWindow.about.internet.wiki=Wiki FAQ do Vuze MainWindow.dialog.choose.savepath=Escolha o direct\u00f3rio 'para guardar' MainWindow.dialog.choose.savepath_forallfiles=Escolher o direct\u00f3rio onde guardar TODOS os ficheiros MainWindow.status.latestversion=Mais recente MainWindow.status.latestversion.clickupdate=Carregue para Actualizar MainWindow.status.unknown=desconhecido MainWindow.status.checking=verificando MyTorrentsView.mytorrents=Os meus torrents TableColumn.header.name=Nome TableColumn.header.size=Tamanho TableColumn.header.done=Conclu\u00eddo TableColumn.header.done.info=Percentagem feita da tarefa corrente TableColumn.header.status=Estado TableColumn.header.status.info=O que o torrent est\u00e1 a fazer TableColumn.header.seeds=Sementes TableColumn.header.seeds.info=# de sementes ligadas (# total de sementes) TableColumn.header.peers=Utilizadores TableColumn.header.peers.info=# pares ligados (# total de pares) TableColumn.header.downspeed=Recebendo a TableColumn.header.upspeed=Enviando a TableColumn.header.eta=TEC TableColumn.header.tracker=Servidor TableColumn.header.tracker.info=Estado do Tracker TableColumn.header.trackernextaccess=Pr\u00f3ximo Acesso do Tracker TableColumn.header.trackernextaccess.info=Quando ocorrer o pr\u00f3ximo acesso do tracker TableColumn.header.priority=Prioridade TableColumn.header.priority.info=Determina quanta largura de banda \u00e9 atribuida a um torrent TableColumn.header.seeds.fullcopycalc=%2 c\u00f3pias completas assumidas para %1 pares MyTorrentsView.menu.showdetails=Ver &detalhes MyTorrentsView.menu.showdownloadbar=Mostrar &barra de download MyTorrentsView.menu.open=&Abrir MyTorrentsView.menu.setpriority=Configurar &Prioridade MyTorrentsView.menu.setpriority.high=&Alta MyTorrentsView.menu.setpriority.low=&Baixa MyTorrentsView.menu.start=&Arrancar MyTorrentsView.menu.stop=&Parar MyTorrentsView.menu.remove=&Remover MyTorrentsView.menu.changeTracker=&Mudar Endere\u00e7o do Servidor TrayWindow.menu.exit=&Sair TrayWindow.menu.show=&Mostrar Vuze SystemTray.menu.exit=&Sair SystemTray.menu.closealldownloadbars=Fechar &Todas as barras de download SystemTray.menu.show=&Mostrar Vuze PeersView.ip.info=IP do par PeersView.port=Porto PeersView.port.info=Porto est\u00e1 em uso PeersView.T=T (Tipo de Cliente) PeersView.T.info=L (Local): Foi voc\u00ea que iniciou a liga\u00e7\u00e3o. R (Remoto): A liga\u00e7\u00e3o foi iniciada pelo par. PeersView.T.L.tooltip=Vo\u00e7\u00ea estabeleceu a liga\u00e7\u00e3o PeersView.T.R.tooltip=O par estabeleceu a liga\u00e7\u00e3o PeersView.I1=I (Voc\u00ea est\u00e1 interessado no par) PeersView.I1.info=Voc\u00ea est\u00e1 interessado no que o par tem? PeersView.C1=C (Engasgado pelo par) PeersView.C1.info=Se o par est\u00e1 a impedir que vo\u00e7\u00ea saque dele PeersView.pieces=Peda\u00e7os PeersView.downloadspeed=Recebendo a PeersView.download=Recebido PeersView.I2=I (O par est\u00e1 interessado em voc\u00ea) PeersView.I2.info=Estar\u00e1 o par interessado naquilo que voc\u00ea tem? PeersView.C2=C (A engasgar o par) PeersView.C2.info=Se voc\u00ea est\u00e1 a bloquear o par de sacar de s\u00ed PeersView.uploadspeed=Enviando a PeersView.uploadspeed.info=A sua velocidade de envio para o par. PeersView.upload=Enviado PeersView.upload.info=A sua velocidade m\u00e9dia de envio para o par. PeersView.statup=Estat\u00edsticas de Envio PeersView.statup.info=Um valor estimado da velocidade de envio do par PeersView.S=S (Snubbed) PeersView.S.info=Snubbed: Um par pode ser "snubbed" manualmente, ou autom\u00e1ticamente (se o par enviar dados a uma taxa de envio demasiado baixa) PeersView.downloadspeedoverall=Velocidade global de recep\u00e7\u00e3o PeersView.optunchoke=Desbloqueio Optimizado PeersView.client=Cliente PeersView.client.info=Tipo de Cliente BT que o par est\u00e1 a usar PeersView.title.short=Detalhes PeersView.title.full=Detalhes ConfigView.section.files=Ficheiros ConfigView.label.usefastresume=Usar modo de Resumo R\u00e1pido ConfigView.label.incrementalfile=Cria\u00e7\u00e3o incremental de ficheiros ConfigView.label.defaultsavepath=Guardar no direct\u00f3rio pr\u00e9-definido ConfigView.button.browse=Procurar... ConfigView.dialog.choosedefaultsavepath=Por favor, escolha o direct\u00f3rio de grava\u00e7\u00e3o ConfigView.section.server=Liga\u00e7\u00e3o ConfigView.section.global=Global ConfigView.label.disconnetseed=Desligar liga\u00e7\u00f5es de sementes quando semente ConfigView.label.switchpriority=Mudar autom\u00e1ticamente para baixa prioridade quando semente ConfigView.label.maxdownloads=N\u00famero m\u00e1ximo de transfer\u00eancias simult\u00e2neas (0 : ilimitadas) ConfigView.label.maxdownloads.tooltip=Voc\u00ea conseguir\u00e1 sempre, de forma activa, sacar o n\u00famero de torrents aqui indicado, com uma excep\u00e7\u00e3o.\nUm torrent terminado que verifique a Primeira Prioridade pode capturar um slot de transfer\u00eancia se for absolutamente necess\u00e1rio. ConfigView.label.maxactivetorrents=N\u00famero m\u00e1ximo de torrents activos (0 : ilimitados)\nNovos torrents n\u00e3o ser\u00e3o inciados se outros estiverem abertos ConfigView.label.priorityExtensions=Prioridade autom\u00e1tica para ficheiros com extens\u00e3o\n - ex: .txt;.nfo;.jpg ConfigView.section.transfer=Transfer\u00eancias ConfigView.label.maxuploads=N\u00famero m\u00e1ximo de envios por torrent ConfigView.label.maxuploadspeed=Velocidade m\u00e1xima de envio (global) ConfigView.label.saveresumeinterval=Actualizar informa\u00e7\u00f5es de 'Resumo R\u00e1pido' a cada ConfigView.unlimited=Ilimitada ConfigView.section.display=Mostrar ConfigView.label.opendetails=Abrir autom\u00e1ticamente o painel de detalhes ConfigView.label.openbar=Abrir autom\u00e1ticamente a barra de transfer\u00eancia ConfigView.label.closetotray=Fechar -> minimiza para a Barra de Tarefas ConfigView.label.minimizetotray=Minimizar -> minimiza para a Barra de Tarefas ConfigView.section.general=Geral ConfigView.section.start=Iniciar ConfigView.label.showsplash=Mostrar imagem inicial ConfigView.label.autoupdate=Abrir a Janela de Actualiza\u00e7\u00e3o quando surgir uma nova vers\u00e3o ConfigView.label.openconsole=Abrir Consola ao iniciar ConfigView.label.openconfig=Abrir Configura\u00e7\u00e3o ao iniciar ConfigView.label.startminimized=Iniciar Minimizado ConfigView.label.ircwiki=Por favor leia http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Servidor IRC ConfigView.label.ircchannel=Canal ConfigView.label.irclogin=Alcunha ConfigView.group.irctitle=Configura\u00e7\u00f5es de IRC ConfigView.boolean.ircsendinfo=Permite o envio das suas configura\u00e7\u00f5es (an\u00f3nimo) para os operadores do canal para ajud\u00e1-los a o ajudarem ConfigView.boolean.irclog=Activa o registo da actividade do canal (em IRC_log.htm) ConfigView.section.security=Seguran\u00e7a ConfigView.label.password=Protejer o Vuze com uma senha\nSer\u00e1 pedida quando restaurar, ou no arranque. ConfigView.label.passwordconfirm=Senha (confirmar) ConfigView.label.passwordmatch=Senha activada : ConfigView.label.passwordmatchnone=N\u00e3o ConfigView.label.passwordmatchno=N\u00e3o /As Senhas n\u00e3o s\u00e3o iguais ConfigView.label.passwordmatchyes=Sim ConfigView.button.save=Guardar ConfigView.title.short=Configura\u00e7\u00e3o ConfigView.title.full=Configura\u00e7\u00e3o ConsoleView.title.short=Consola ConsoleView.title.full=Consola FileItem.write=escrita FileItem.read=leitura FileItem.high=alta FileItem.donotdownload=N\u00e3o receber FilesView.name=Nome FilesView.size=Tamanho FilesView.done=Conclu\u00eddo FilesView.firstpiece=Primeiro bloco # FilesView.numberofpieces=# de blocos FilesView.pieces=Peda\u00e7os FilesView.mode=Modo FilesView.priority=Prioridade FilesView.menu.open=A&brir FilesView.menu.setpriority=Atribuir &Prioridade FilesView.menu.setpriority.high=&Alta FilesView.menu.setpriority.skipped=N\u00e3&o receber FilesView.title.short=Ficheiros FilesView.title.full=Ficheiros GeneralView.section.downloaded=Recebido GeneralView.label.status.file=Estado do ficheiro GeneralView.label.status.pieces=Estado dos Peda\u00e7os GeneralView.section.availability=Disponibilidade GeneralView.label.status.pieces_available=Estado dos Peda\u00e7os GeneralView.section.transfer=Transfer\u00eancias GeneralView.title.short=Geral GeneralView.title.full=Geral GeneralView.label.timeelapsed=Tempo passado : GeneralView.label.remaining=Faltam : GeneralView.label.downloaded=Recebido : GeneralView.label.downloadspeed=Recebendo a : GeneralView.label.maxuploads=Envios M\u00e1ximos : GeneralView.label.maxuploads.tooltip=N\u00famero m\u00e1ximo de Pares qie ser\u00e3o unchoked num determinado per\u00edodo. GeneralView.label.uploaded=Enviado : GeneralView.label.uploadspeed=Enviando a : GeneralView.label.seeds=Sementes : GeneralView.label.peers=Pares : GeneralView.label.totalspeed=Velocidade total : GeneralView.label.totalspeed.tooltip=Velocidade total de todos os clientes a que est\u00e1 ligado. GeneralView.label.averagespeed=m\u00e9dia GeneralView.label.filename=Nome : GeneralView.label.totalsize=Tamanho total : GeneralView.label.savein=Guardando em : GeneralView.label.hash=Hash : GeneralView.label.numberofpieces=# de Peda\u00e7os : GeneralView.label.size=Tamanho : GeneralView.label.tracker=Tracker : GeneralView.label.updatein=Actualiza\u00e7\u00e3o em : GeneralView.label.trackerurl=Endere\u00e7o do Tracker : GeneralView.label.trackerurlupdate=Actualiza\u00e7\u00e3o Manual GeneralView.label.comment=Coment\u00e1rio : GeneralView.label.user_comment=Coment\u00e1rio do Utilizador : ManagerItem.waiting=Esperando ManagerItem.allocating=Alocando ManagerItem.checking=A Verificar ManagerItem.ready=Pronto ManagerItem.downloading=A Transferir ManagerItem.seeding=A Semear ManagerItem.stopped=Parado ManagerItem.error=Erro ManagerItem.high=alta ManagerItem.low=baixa MinimizedWindow.name=Nome: PiecesView.size=Tamanho PiecesView.numberofblocks=# de Blocos PiecesView.blocks=Blocos PiecesView.completed=Completos PiecesView.availability=Disponibilidade PiecesView.reservedby=Reservado PiecesView.writers=Bloquear Contribuintes PiecesView.title.short=Blocos PiecesView.title.full=Blocos SystemTray.tooltip.seeding=%1 semeando, SystemTray.tooltip.downloading=%1 recebendo, DownloadManager.error.filenotfound=Ficheiro n\u00e3o encontrado DownloadManager.error.fileempty=O Torrent est\u00e1 vazio DownloadManager.error.filetoobig=O Torrent \u00e9 demasiado grande DownloadManager.error.filewithouttorrentinfo=Nenhuma informa\u00e7\u00e3o encontrada no ficheiro DownloadManager.error.unsupportedencoding=Codifica\u00e7\u00e3o n\u00e3o suportada DownloadManager.error.ioerror=Erro: E/S DownloadManager.error.sha1=Erro: Algoritmo desconhecido (SHA1) PeerManager.status.offline=desligado PeerManager.status.ok=ok PeerManager.status.checking=a verificar... PeerManager.status.finished=Terminado PeerManager.status.finishedin=Terminado em MainWindow.upgrade.assistant=Assistente de Actualiza\u00e7\u00e3o MainWindow.upgrade.newerversion=Existe uma nova vers\u00e3o do Vuze dispon\u00edvel para transfer\u00eancia MainWindow.upgrade.explanation=Este assistente ir\u00e1 receber a nova vers\u00e3o para a directoria do Vuze e reiniciar o Vuze MainWindow.upgrade.explanation.manual=Voc\u00ea pode actualizar manualmente fechando o Vuze descarregar a nova vers\u00e3o e reiniciar o Vuze MainWindow.upgrade.step1=Passo 1: Receber a nova vers\u00e3o MainWindow.upgrade.step2=Passo 2: Feche esta vers\u00e3o e reinicie a nova vers\u00e3o do Vuze MainWindow.upgrade.hint1=Dica:\tCarregar em Terminar faz tudo autom\u00e1ticamente MainWindow.upgrade.hint2=Dica:\tSe quiser fechar o Vuze mais tarde, carregue em Cancelar e\n\tmude o nome Azureus2-new.jar para Azureus2.jar depois de fechar MainWindow.upgrade.error.downloading.hint=Erro:\tIncapaz de receber a nova vers\u00e3o, por favor actualize manualmente MainWindow.upgrade.section.info=Nova Vers\u00e3o Dispon\u00edvel MainWindow.upgrade.section.manual=Actualiza\u00e7\u00e3o Manual MainWindow.upgrade.section.automatic=Actualiza\u00e7\u00e3o Autom\u00e1tica MainWindow.upgrade.tooltip.progressbar=A barra de progresso \u00e9 mostrada aqui Button.next=Pr\u00f3ximo Button.finish=Terminar Button.cancel=Cancelar LocaleUtil.title=Escolher Codifica\u00e7\u00e3o LocaleUtil.section.chooseencoding=Escolher codifica\u00e7\u00e3o por nome de ficheiro LocaleUtil.label.chooseencoding=Por favor seleccione a codifica\u00e7\u00e3o LocaleUtil.label.hint.doubleclick=Dica: clicar duas vezes numa linha escolhe a codifica\u00e7\u00e3o e fecha a janela LocaleUtil.label.checkbox.rememberdecision=Lembrar esta decis\u00e3o para os ficheiros que faltam LocaleUtil.column.encoding=Codifica\u00e7\u00e3o IrcClient.defaultChannel=#Azureus-Portuguese IrcClient.copyright=Usando PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Ligando a IrcClient.connected=Ligado a IrcClient.joining=Entrando IrcClient.channel=Canal IrcClient.joined=entrou IrcClient.error=Erro IrcClient.hasjoined=j\u00e1 entrou IrcClient.haskicked=foi kickado IrcClient.hasleft=saiu IrcClient.nowknown=\u00e9 conhecido como IrcClient.topicforchannel=T\u00f3pico para o canal IrcClient.disconnected=Desligado de IrcClient.noNick=Nickname n\u00e3o especificado. Por favor verifique as 'Configura\u00e7\u00f5es' IrcView.actionnotsupported=Esta ac\u00e7\u00e3o n\u00e3o \u00e9 suportada IrcView.clientsconnected=utilizadores IrcView.privateto=Para IrcView.privatefrom=De IrcView.noticefrom=Notifica\u00e7\u00e3o : IrcView.errormsg=Sintaxe Errada em /msg : /msg utilizador texto IrcView.help=Os comandos v\u00e1lidos s\u00e3o :\n . /help : mostra esta mensagem\n . /nick | /name : muda o seu nome \n . /me action : envia uma ac\u00e7\u00e3o \n . /msg nick mensagem : envia uma privada para o \n . /r message : responder \u00e0 ultima mensagem\n . /join #canal : muda de canal PasswordWindow.title=Vuze est\u00e1 bloqueado PasswordWindow.passwordprotected=O Vuze est\u00e1 protegido com senha.\nPara mostrar a janela principal, por favor introduza aqui a senha : Button.ok=Ok TrackerChangerWindow.title=Adicionar Tracker TrackerChangerWindow.newtracker=Indique o novo endere\u00e7o do tracker PeersView.discarded=Descartado PeersView.discarded.info=Dados que voc\u00ea recebeu apesar de j\u00e1 n\u00e3o precisar, por isso viu-se livre deles. discarded=descartado MyTorrentsView.menu.move=&Mover MyTorrentsView.menu.moveUp=&Cima MyTorrentsView.menu.moveDown=&Baixo GeneralView.label.hashfails=Falha de Hash : GeneralView.label.shareRatio=R\u00e1cio de Partilha : ConfigView.section.downloadManagement=Gest\u00e3o de Transfer\u00eancias ConfigView.label.startRatioPeers=Iniciar semente quando h\u00e1 menos de 1 semente para ConfigView.text.neverStop=Nunca Parar ConfigView.text.neverStart=Nunca Iniciar ConfigView.text.peers=Pares ConfigView.label.checkOncompletion=Verificar de novo quando a transfer\u00eancia termina wizard.title=Criar um Torrent wizard.previous=< Anterior wizard.next=Seguinte > wizard.finish=Terminar wizard.mode=Tracker / Modo wizard.tracker=Servidor: wizard.invalidurl=Este endere\u00e7o n\u00e3o \u00e9 v\u00e1lido wizard.singlefile=Ficheiro \u00fanico wizard.singlefile.help=Criar um torrent a partir de um \u00fanico ficheiro wizard.directory=Direct\u00f3rio wizard.directory.help=Criar um torrent a partir de um direct\u00f3rio wizard.choosefile=Escolha o ficheiro wizard.file=Ficheiro : wizard.browse=Procurar... wizard.choosedirectory=Escolha o directorio wizard.invalidfile=Ficheiro Inv\u00e1lido! wizard.invaliddirectory=Direct\u00f3rio Inv\u00e1lido! wizard.torrentFile=Ficheiro Torrent wizard.choosetorrent=Escolha o ficheiro torrent a criar wizard.information=Informa\u00e7\u00e3o wizard.notimplemented=Ainda n\u00e3o implementado wizard.progresstitle=A Criar o Ficheiro Torrent wizard.savingfile=Gravando Ficheiro... wizard.filesaved=Ficheiro Gravado. wizard.close=Fechar Torrent.create.progress.piecelength=Tamanho dos Peda\u00e7os: Torrent.create.progress.piececount=N\u00famero de Peda\u00e7os: Torrent.create.progress.totalfilesize=Tamanho total dos dados: Torrent.create.progress.totalfilecount=N\u00famero total de ficheiros: Torrent.create.progress.parsingfiles=Analizando ficheiros Torrent.create.progress.hashing=Verificando ficheiros MainWindow.upgrade.downloadingfrom=Descarregando de : MainWindow.menu.view.ipFilter=Filtros de &IP ConfigView.section.ipfilter=Filtros de IP ConfigView.section.ipfilter.description=Descri\u00e7\u00e3o ConfigView.section.ipfilter.start=IP Inicial ConfigView.section.ipfilter.end=IP Final ConfigView.section.ipfilter.add=Adicionar ConfigView.section.ipfilter.remove=Remover ConfigView.section.ipfilter.edit=Editar ConfigView.section.ipfilter.save=Gravar ConfigView.section.ipfilter.editFilter=Editar Filtro ConfigView.section.ipfilter.enable=Ligar Filtros PeersView.menu.close=&Fechar seedmore.title=Torrent n\u00e3o est\u00e1 suficientement partilhado seedmore.shareratio=O seu r\u00e1cio de partilha neste Torrent \u00e9 de seedmore.uploadmore=Ter um r\u00e1cio de partilha abaixo de 100% \u00e9 mau para a rede de Bit-Torrent.\nDeve deixar semear este torrent mais um pouco.\nTens a certeza que queres continuar? ConfigView.label.showpopuponclose=Mostrar janela de confirma\u00e7\u00e3o quando parar de semear tendo um r\u00e1cio de partilha inferior a 1 ConfigView.label.startNumSeeds=Iniciar partilha se existir menos de\n - Sobrep\u00f5e-se a todas as outras regras ConfigView.label.seeds=sementes ConfigView.section.seeding=A semear MyTorrentsView.menu.removeand=Remover e MyTorrentsView.menu.removeand.deletetorrent=Apaga o &Torrent MyTorrentsView.menu.removeand.deletedata=Apaga os &Dados MyTorrentsView.menu.removeand.deleteboth=Apaga &Ambos deletedata.title=!!! Aviso !!! deletedata.message1=Est\u00e1 prestes a apagar os DADOS de :\n MainWindow.menu.file.configure=A&ssistente de Configura\u00e7\u00e3o configureWizard.title=Assistente de Configura\u00e7\u00e3o configureWizard.welcome.title=Bem-vindo ao Assistente de Configura\u00e7\u00e3o configureWizard.welcome.message=Este assistentevai ajud\u00e1-lo a configurar o Vuze para uma utiliza\u00e7\u00e3o comum.\n\nPara configura\u00e7\u00f5es avan\u00e7adas use o menu Ver -> Configura\u00e7\u00e3o. configureWizard.transfer.title=Configura\u00e7\u00e3o das Trasfer\u00eancias e Liga\u00e7\u00f5es configureWizard.transfer.hint=Dica : Usar o Envio ligeiramente inferior (cerca de 80%) do que o suportado pela sua liga\u00e7\u00e3o \u00e9 a melhor configura\u00e7\u00e3o. configureWizard.transfer.message=Por favor use uma das Liga\u00e7\u00f5es.\nTenha em aten\u00e7\u00e3o que enviar a velocidades muito baixas por torrent (<2Kb/s) pode resultar em velocidades baixas de tranfer\u00eancia.\nComo a velocidade de envio \u00e9 significativa apenas PARA CADA torrent que esteja activo, ter muitos torrents activos resultar\u00e1 em velocidades baixas de transfer\u00eancia.\nRecomendamos que envie no m\u00ednimo a 5Kb/s por torrent para uma boa recep\u00e7\u00e3o.\nQuanto maior a velocidade de envio de um torrent maior ser\u00e1 a velocidade de transfer\u00eancia desse torrent (desde que hajam blocos dispon\u00edveis).\n\nDica: Use o m\u00ednimo de envios por torrent (=2) e calcule o numero m\u00e1ximo de torrents activos com base na velocidade de envio m\u00e1ximo de forma a que a velocidade m\u00e9dia por torrent seja >= 2Kb/s configureWizard.transfer.connection=Liga\u00e7\u00e3o configureWizard.transfer.connection.0=Personalizar configureWizard.transfer.connection.1=Modem/Isdn configureWizard.transfer.connection.2=Adsl/Cabo xxx/128 kbps configureWizard.transfer.connection.3=Adsl/Cabo xxx/256 kbps configureWizard.transfer.connection.4=Adsl/Cabo xxx/384 kbps configureWizard.transfer.connection.5=Adsl/Cabo xxx/512 kbps configureWizard.transfer.connection.6=Adsl/Cabo xxx/768 kbps configureWizard.transfer.connection.7=Adsl/Cabo xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Velocidade M\u00e1xima de Envio (Global) (kB/s) configureWizard.transfer.maxActiveTorrents=N\u00famero m\u00e1ximo de torrents activos configureWizard.transfer.maxDownloads=N\u00famero m\u00e1ximo de transfer\u00eancias configureWizard.transfer.maxUploadsPerTorrent=N\u00famero m\u00e1ximo de envios por torrent configureWizard.nat.title=NAT / Portas do Servidor configureWizard.nat.message=De forma a ter o melhor uso do protocolo BitTorrent, \u00e9 altamente recomendado que d\u00ea acessos completos ao Vuze na sua Firewall/Router.\nO porto de escuta usado para o protocolo bittorrent por omiss\u00e3o \u00e9 6881.\nEsta ferramenta permite testar e/ou efectuar a sua altera\u00e7\u00e3o. configureWizard.nat.test=Testar configureWizard.nat.testing=A testar porta configureWizard.nat.ok=Ok configureWizard.nat.ko=Erro de NAT configureWizard.nat.unable=Indispon\u00edvel para teste configureWizard.file.title=Torrents / Ficheiros configureWizard.file.message1=O Vuze pode gravar uma c\u00f3pia dos torrents abertos num direct\u00f3rio espec\u00edfico, pode definir esse direct\u00f3rio aqui: configureWizard.file.path=Direct\u00f3rio configureWizard.file.browse=Procurar... configureWizard.file.message2=O Vuze permite continuar os downloads instant\u00e2neamente, adicionando alguma informa\u00e7\u00e3o aos ficheiros Torrent.\nUsando esta funcionalidade, pode ainda continuar blocos que j\u00e1 estavam parcialmente sacados. configureWizard.file.fastResume=Usar modo de resumo r\u00e1pido configureWizard.file.invalidPath=Direct\u00f3rio inv\u00e1lido configureWizard.finish.title=Terminado configureWizard.finish.message=O Vuze est\u00e1 configurado, divirta-se ! wizard.close.confirmation=Confirma\u00e7\u00e3o wizard.close.message=Deseja usar este assistente da\npr\u00f3xima vez que o Vuze iniciar? exportTorrentWizard.title=Exportar um Torrent exportTorrentWizard.torrentfile.title=Selec\u00e7\u00e3o do Torrent exportTorrentWizard.torrentfile.message=Escolha o ficheiro torrent a exportar exportTorrentWizard.torrentfile.path=Caminho exportTorrentWizard.torrentfile.browse=Procurar... exportTorrentWizard.torrentfile.invalidPath=Ficheiro Torrent Inv\u00e1lido exportTorrentWizard.exportfile.title=Selec\u00e7\u00e3o do Ficheiro a Exportar exportTorrentWizard.exportfile.message=Indique o ficheiro para onde exportar exportTorrentWizard.exportfile.path=Caminho exportTorrentWizard.exportfile.browse=Procurar... exportTorrentWizard.exportfile.invalidPath=Ficheiro inv\u00e1lido de exporta\u00e7\u00e3o exportTorrentWizard.finish.title=Terminado exportTorrentWizard.finish.message=Exporta\u00e7\u00e3o terminada com Sucesso exportTorrentWizard.process.inputfilebad.title=Ficheiro Torrent Inv\u00e1lido exportTorrentWizard.process.inputfilebad.message=Ocorreu um erro a aceder ao ficheiro de origem: exportTorrentWizard.process.outputfileexists.title=O Ficheiro j\u00e1 Existe! exportTorrentWizard.process.outputfileexists.message=O Ficheiro de destino j\u00e1 existe - substituir? exportTorrentWizard.process.torrentfail.title=Erro a Ler o Torrent exportTorrentWizard.process.exportfail.title=Erro a Exportar o Torrent exportTorrentWizard.process.unknownfail.title=Erro Inesperado importTorrentWizard.title=Importar um Torrent importTorrentWizard.torrentfile.title=Selec\u00e7\u00e3o do Torrent importTorrentWizard.torrentfile.message=Escolha o ficheiro torrent para onde inportar importTorrentWizard.torrentfile.path=Caminho importTorrentWizard.torrentfile.browse=Procurar... importTorrentWizard.torrentfile.invalidPath=Ficheiro Torrent Inv\u00e1lido importTorrentWizard.importfile.title=Selec\u00e7\u00e3o do Ficheiro a Importar importTorrentWizard.importfile.message=Indique o ficheiro a importar importTorrentWizard.importfile.path=Caminho importTorrentWizard.importfile.browse=Procurar... importTorrentWizard.importfile.invalidPath=Ficheiro inv\u00e1lido de importa\u00e7\u00e3o importTorrentWizard.finish.title=Terminado importTorrentWizard.finish.message=Importa\u00e7\u00e3o terminada com sucesso importTorrentWizard.process.inputfilebad.title=Ficheiro Inv\u00e1lido de Importa\u00e7\u00e3o importTorrentWizard.process.inputfilebad.message=Ocorreu um erro a aceder ao ficheiro de origem: importTorrentWizard.process.outputfileexists.title=Ficheiro j\u00e1 Existe! importTorrentWizard.process.outputfileexists.message=Ficheiro de destino j\u00e1 existe - substituir? importTorrentWizard.process.torrentfail.title=Erro a Escrever o Torrent importTorrentWizard.process.importfail.title=Erro a Importar o Torrent importTorrentWizard.process.unknownfail.title=Erro Inesperado ConfigView.label.bindip=Ligar (Bind) ao endere\u00e7o de IP local or interface ConfigView.label.xfs.allocation=Alocar novos ficheiros utilizando o m\u00e9todo especifico ao sistema de ficheiros XFS ConfigView.label.xfs.allocation.tooltip=Por favor tenha a certeza que /usr/sbin/xfs_io est\u00e1 correctamente instalado no seu sistema. Na maioria das distribui\u00e7\u00f5es de Linuz est\u00e1 incluido no pacote "xfsprogs". xfs.allocation.xfs_io.not.found=A aloca\u00e7\u00e3o do ficheiro XFS falhou porque /usr/sbin/xfs_io n\u00e3o pode ser iniciado. Verifique que o tem bem instalado no seu sistema. O erro original foi : "%1". ConfigView.label.zeronewfiles=For\u00e7ar cria\u00e7\u00e3o de novos ficheiros com 0 bytes ConfigView.label.zeronewfiles.tooltip=Minimiza fragmenta\u00e7\u00e3o de ficheiros em disco ConfigView.section.stats=Estat\u00edsticas ConfigView.section.stats.enable=Activar ConfigView.section.stats.defaultsavepath=Directoria onde guardar as estat\u00edsticas ConfigView.section.stats.choosedefaultsavepath=Escolha a directoria onde guardar as estat\u00edsticas ConfigView.section.stats.savefreq=Frequ\u00eancia para guardar ConfigView.section.stats.minutes=m ConfigView.section.stats.hours=h ConfigView.section.stats.seconds=s ConfigView.section.stats.savefile=Nome do ficheiro de estat\u00edsticas MyTorrentsView.menu.export=&Exportar... MyTorrentsView.menu.host=&Servidor... ManagerItem.finishing=A Terminar ConfigView.dialog.choosedefaulttorrentpath=Escolha o direct\u00f3rio onde gravar os Torrents ConfigView.dialog.choosemovepath=Escolha o directorio para onde mover ConfigView.label.movecompleted=Mover ficheiros finalizados (ap\u00f3s transfer\u00eancia) ConfigView.label.moveremoved=Mover os ficheiros terminados (quando est\u00e3o a ser removidos) ConfigView.label.savetorrents=Guardar ficheiros .torrent MainWindow.menu.view.mytracker=O Meu &Tracker MyTrackerView.title.full=O Meu Tracker MyTrackerView.name=Nome MyTrackerView.tracker=Servidor MyTrackerView.status=Estado MyTrackerView.status.started=A Executar MyTrackerView.status.stopped=Parado MyTrackerView.peers=Pares MyTrackerView.seeds=Sementes MyTrackerView.announces=An\u00fancios MyTrackerView.uploaded=Enviado MyTrackerView.downloaded=Recebido MyTrackerView.left=Faltam ConfigView.label.set_ui_transfer_speeds=Sobrepor as velocidades de transfer\u00eancia seleccion\u00e1veis ConfigView.label.set_ui_transfer_speeds.description=Pode escolher por definir manualmente as velocidades de transfer\u00eancia e upload dispon\u00edveis na barra de estado na \u00e1rea de notifica\u00e7\u00e3o.\nOs valores t\u00eam de ser separados por v\u00edrgulas. ConfigView.label.set_ui_transfer_speeds.description.download=Configurar as velocidades de transfer\u00eancia (em KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Configurar as velocidades de upload (em KB/s) ConfigView.section.style.useCustomTabs=Usar Separadores que Fecham [requer reinicio] fileDownloadWindow.saveTorrentIn=Gravar Ficheiro Torrent em fileDownloadWindow.title=Vuze - Sacar Torrent fileDownloadWindow.downloading=A Receber de : fileDownloadWindow.status=Estado : fileDownloadWindow.state_initializing=Inicializando fileDownloadWindow.state_downloading=Recebendo fileDownloadWindow.state_error=Erro : MainWindow.menu.file.open.url=&Localiza\u00e7\u00e3o... openUrl.title=Vuze - Abrir Endere\u00e7o URL openUrl.url=Endere\u00e7o URL : MyTorrentsView.menu.host.error.title=Servir Torrent Falhou MyTorrentsView.menu.host.error.message=O seguinte erro ocurreu a servir o torrent ConfigView.section.tracker.pollinterval=Intervalo de pedidos (seg), Servidor / Clientes ConfigView.section.tracker.publishenable=Publicar detalhes do torrent para "" ConfigView.section.tracker.ip=Endere\u00e7o IP do Servidor externo ConfigView.section.style.enableXPStyle=Permitir estilo XP (necess\u00e1rio reiniciar) ConfigView.section.tracker.checkip=Auto-descobrir o Endere\u00e7o IP externo... ipCheckerWizard.title=Assistente de Verifica\u00e7\u00e3o de IP ipCheckerWizard.service=Servi\u00e7o ipCheckerWizard.chooseService=Escolha um dos Servi\u00e7os de Verifica\u00e7\u00e3o de IP da lista ipCheckerWizard.explanations=Pode usar este assistente para descobrir qual o seu endere\u00e7o externo de IP.\nSe o tem endere\u00e7o de IP dinamico, recomendamos que tenha uma conta com algum Servi\u00e7o de DNS Dinamico.\nalguns desses servi\u00e7os est\u00e3o listados em baixo, use o link fornecido para criar um conta (onde for suportado).\nDepois preencha o endere\u00e7o de IP com o seu endere\u00e7o dinamico (Ex: meuservidor.dynds.org).\nNecessita de um programa que actualize automaticamente o Servi\u00e7o de DNS Dinamico com o seu IP (geralmente disponivel nas paginas deses servi\u00e7os).\nAssim \u00e9-lhe possivel servir torrents mesmo que o seu endere\u00e7o de IP mude. ipCheckerWizard.service.description=Descri\u00e7\u00e3o : ipCheckerWizard.service.url=Atalho : ipCheckerWizard.progresstitle=A Verificar IP ipCheckerWizard.checkComplete=Verfica\u00e7\u00e3o completa, IP : ipCheckerWizard.checkFailed=Falhou, raz\u00e3o : wizard.tracker.local=Usar o Tracker Privado do Vuze wizard.tracker.external=Usar um Tracker Externo wizard.tracker.howToLocal=\tIr a 'Configura\u00e7\u00e3o > Tracker' para activ\u00e1-lo wizard.announceUrl=URL de Announce : IPChecker.external.service.discoveryvip.description=Discoveryvip - verifica apenas o endere\u00e7o IP IPChecker.external.httpinvalidresponse=Resposta de HTTP Inv\u00e1lida IPChecker.external.loadingwebpage=A carregar pagina web IPChecker.external.analysingresponse=Analisando resposta IPChecker.external.addressextracted=Endere\u00e7o de IP extra\u00eddo IPChecker.external.httploadfail=Falhou a carregar pagina IPChecker.external.timeout=Falha por tempo excedido IPChecker.external.ipnotfound=Endere\u00e7o de IP n\u00e3o encontrado ConfigView.section.tracker.pollintervalmin=M\u00ednimo ConfigView.section.tracker.pollintervalmax=M\u00e1ximo ConfigView.section.tracker.pollintervalincby=Aumentar por ConfigView.section.tracker.pollintervalincper=A cada 'n' Clientes splash.loadingImages=A Carregar as Imagens splash.initializeGui=A Inicializar Janela Principal splash.openViews=A Abrir Vistas splash.plugin=A Carregar a Extensao : configureWizard.nat.tooManyPorts=Demasiados portos a testar (9 max) ConfigView.section.color=Esquema de Cores MyTorrentsView.menu.publish=&Publicar... MyTrackerView.status.published=Publicado MyTrackerView.completed=Completos MainWindow.menu.file.open.torrentnodefault=Ficheiro .torrent (sem directoria pr\u00e9-definia) wizard.comment=Coment\u00e1rio ConfigView.label.movetorrent=Move o ficheiro .torrent ConfigView.label.movepartialdownloads=Mover quando alguns ficheiros est\u00e3o etiquetados como "N\u00e3oTransferir" ConfigView.label.subdir_is_in_default=Ao considerar se as transfer\u00eancias existem na directoria pr\u00e9-definida, considerar tamb\u00e9m subdirectorias ConfigView.section.file.decoder.label=Modo de codifica\u00e7\u00e3o do torrent (por omiss\u00e3o) quando for necess\u00e1ria escolha ConfigView.section.file.decoder.nodecoder=Nenhum IPChecker.external.service.no-ip.description=provedor de servi\u00e7os de DNS Est\u00e1ticos e Din\u00e2micos\n(n\u00e3o tem servi\u00e7o gr\u00e1tis de verificar endere\u00e7o) ConfigView.section.tracker.publicenable=Permitir torrents externos ConfigView.label.playdownloadspeech=Fala quando a transfer\u00eancia termina. ConfigView.label.playdownloadspeech.info=Os Servi\u00e7os de Fala actualmente funcionam melhor em Ingl\u00eas # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Mostra o n\u00famero de c\u00f3pias dispon\u00edveis de cada peda\u00e7o.\nSe o n\u00famero da direita for inferior a 1, voc\u00ea n\u00e3o est\u00e1 a ver uma c\u00f3pia inteira dos ficheiros (e pode ter problemas a completar o download). GeneralView.label.trackerurl.tooltip=Clique para copiar endere\u00e7o de an\u00fancio para a \u00e1rea de transfer\u00eancia GeneralView.label.trackerurlopen.tooltip=Clique para abrir a p\u00e1gina principal do tracker # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Actualizar GUI a cada ConfigView.section.style.graphicsUpdate=Actualizar barras dos Graficos a cada N actualiza\u00e7\u00f5es da GUI ConfigView.section.style.reOrderDelay=Re-Ordenar tabelas a cada N actualiza\u00e7\u00f5es GUI [0: nunca] ConfigView.section.style.reOrderDelay.never=Nunca ConfigView.section.logging=Registo ConfigView.section.logging.enable=Permitir fazer o registo para um ficheiro ConfigView.section.logging.logdir=Directoria do ficheiro de Registo ConfigView.section.logging.choosedefaultsavepath=Por favor escolha o direct\u00f3rio de grava\u00e7\u00e3o GeneralView.label.updatein.querying=perguntando... configureWizard.nat.sharePort=Usar um \u00fanico porto de entrada partilhado para todos os torrents ConfigView.section.logging.maxsize=Tamanho m\u00e1ximo de ficheiro de registo ConfigView.section.tracker.passwordenableweb=Ligar senha na p\u00e1gina do tracker ConfigView.section.tracker.passwordenabletorrent=Ligar senha nos torrents ConfigView.section.tracker.username=Utilizador ConfigView.section.tracker.password=Senha columnChooser.title=Escolha as colunas a mostrar columnChooser.move=Arraste as linhas para ordenar columnChooser.apply=Aplicar columnChooser.columnname=Nome da Coluna columnChooser.columndescription=Descri\u00e7\u00e3o TableColumn.header.shareRatio=R\u00e1cio de Partilha MyTorrentsView.menu.editTableColumns=&Colunas a Mostrar wizard.operationfailed=Opera\u00e7\u00e3o falhou authenticator.title=Autentica\u00e7\u00e3o Necess\u00e1ria authenticator.realm=Dom\u00ednio authenticator.tracker=Servidor authenticator.user=Utilizador authenticator.password=Senha ConfigView.label.allowSendVersion=Permitir que o Vuze envie n\u00famero de vers\u00e3o an\u00f3nimo\n e identificador aleat\u00f3rio quando procurar actualiza\u00e7\u00f5es wizard.hint.mode=Dica:\tVoce pode usar Arrastar e Largar para dentro deste assistente\n\tpara escolher um directorio ou ficheiro wizard.hint.file=Dica:\tVoce pode escolher um ficheiro isolado usando Arrastar e Largar wizard.hint.directory=Dica:\tVoce pode escolher um directorio isolado usando Arrastar e Largar MainWindow.menu.help.checkupdate=&Verificar exist\u00eancia de actualiza\u00e7\u00e3o TableColumn.header.down=Recebido TableColumn.header.up=Enviado ConfigView.section.tracker.passwordenabletorrent.info=Necessita de Cliente BitTorrent apropriado (ex: Vuze ConfigView.section.style.confirmationOnExit=Mostrar confirma\u00e7\u00e3o ao sair MainWindow.dialog.exitconfirmation.title=Sair do Vuze MainWindow.dialog.exitconfirmation.text=Quer realmente sair do Vuze SystemTray.menu.stopalltransfers=Parar &Todas as Transf\u00earencias TrayWindow.menu.stopalldownloads=&Parar Todos os Downloads ConfigView.section.tracker.sslport.info=Ver a FAQ para mais informa\u00e7\u00f5es wizard.tracker.ssl=Usar SSL ConfigView.label.playdownloadfinished=Tocar um som quando uma transfer\u00eancia termina ConfigView.label.popupdownloadfinished=Mostrar um alerta pop-up quando uma transfer\u00eancia \u00e9 terminada ConfigView.label.popupfilefinished=Mostrar um alerta pop-up quando um ficheiro \u00e9 terminado TableColumn.header.pieces=Peda\u00e7os TableColumn.header.pieces.info=Barra gr\u00e1fica representando os peda\u00e7os j\u00e1 recebidos TableColumn.header.completion=A Completar TableColumn.header.completion.info=Representa\u00e7\u00e3o gr\u00e1fica da % recebida ConfigView.section.style.showdownloadbasket=Mostrar Cesto de Download (Arrastar/Largar .torrents) ConfigView.section.style.alwaysShowTorrentFiles=Mostrar sempre os ficheiros Torrent em Detalhes/Ficheiros wizard.multitracker=Adicionar informa\u00e7\u00e3o Multi-Tracker ao torrent wizard.multitracker.configuration=Configura\u00e7\u00e3o Multi-Tracker wizard.multitracker.new=Novo... wizard.multitracker.edit=Editar.. wizard.multitracker.delete=Apagar wizard.multitracker.group=Grupo de Tracker wizard.multitracker.edit.title=Editor Multi-Tracker wizard.multitracker.edit.name=Nome wizard.multitracker.edit.save=Gravar wizard.multitracker.edit.newgroup=Novo Grupo wizard.multitracker.edit.deletegroup=Apagar wizard.multitracker.edit.newtracker=Novo Tracker wizard.multitracker.edit.deletetracker=Apagar wizard.multitracker.edit.edit=Editar wizard.addingmt=Adicionar Informa\u00e7\u00e3o Multi-Tracker wizard.multitracker.noannounce=O Endere\u00e7o URL de an\u00fancio n\u00e3o est\u00e1 presente na sua lista de trackers MyTorrentsView.menu.recheck=For\u00e7ar Verifica\u00e7\u00e3o iconBar.showDownloadBar.tooltip=Mostrar barra de Transfer\u00eancia iconBar.start.tooltip=Iniciar iconBar.stop.tooltip=Parar iconBar.remove.tooltip=Remover iconBar.openNoDefault.tooltip=Abrir um ficheiro .torrent (sem grava\u00e7\u00e3o pre-definida) iconBar.openURL.tooltip=Abrir um URL iconBar.openFolder.tooltip=Abrir um Directorio iconBar.new.tooltip=Criar um torrent iconBar.up.tooltip=Move para cima iconBar.down.tooltip=Move para baixo iconBar.run.tooltip=Abrir iconBar.host.tooltip=Servidor iconBar.publish.tooltip=Publicar MyTorrentsView.menu.editTracker=&Editar Endere\u00e7os de Tracker GeneralView.menu.selectTracker=Seleccione ConfigView.section.stats.xslfile=Nome do ficheiro XSL ConfigView.section.stats.xslfiledetails=Isto ser\u00e1 inclu\u00eddo no cabe\u00e7alho do ficheiro de estat\u00edsticas via a etiqueta ConfigView.label.savetorrentbackup=Guardar C\u00f3pia (.bak) ConfigView.section.tracker.forceport=For\u00e7ar torrents externos servidos a usar porto por omiss\u00e3o ConfigView.section.ipfilter.allow=PERMITIR apenas os IPs dentro destas regras (desligado = BLOQUEAR) ConfigView.section.ipfilter.list.inrange=pertencia \u00e0s regras ConfigView.section.ipfilter.list.notinrange=n\u00e3o pertencia \u00e0s regras ConfigView.section.ipfilter.list.title=Lista de IPs Bloqueados ConfigView.label.allowsameip=Permitir V\u00e1rias liga\u00e7\u00f5es a partir do mesmo IP ConfigView.label.allowsameip.tooltip=Ligue APENAS se Necessita.\nIsto \u00e9 uma protec\u00e7\u00e3o contra Sanguessugas (quando desligado). ManagerItem.superseeding=Super-Semente ConfigView.label.userSuperSeeding=Usar modo de Super Semente PeersView.uniquepiece=Peda\u00e7o (Modo Super-Semente) PeersView.uniquepiece.none=Nenhum PeersView.timetosend=Per\u00edodo at\u00e9 re-enviar Peda\u00e7o (Modo Super-Semente) ConfigView.section.style.addurlsilently=Abrir URL silenciosamente (sem di\u00e1logo) ConfigView.section.style.addurlsilently.tooltip=AVISO: A janela principal n\u00e3o ficar\u00e1 visivel se isto for activado|\nSe voc\u00ea perder o icon na barra de tarefas, deve desactivar esta op\u00e7\u00e3o. ConfigView.section.file.decoder.prompt=Perguntar sempre quando for necess\u00e1rio escolher o modo de codifica\u00e7\u00e3o ConfigView.section.file.decoder.prompt.tooltip=Mostra sempre o di\u00e1logo quando for necess\u00e1ria a escolha do modo de codifica\u00e7\u00e3o MyTorrentsView.menu.moveTop=&\u00cdnicio MyTorrentsView.menu.moveEnd=&Fim ConfigView.label.moveonlyusingdefaultsave=apenas se estiver na directoria pr\u00e9-definida de dados ConfigView.label.moveonlyusingdefaultsave.tooltip=Move apenas se os ficheiros sacados est\u00e3o na directoria pr\u00e9-definida de dados ConfigView.label.watchtorrentfolder=Importar novos .torrent autom\u00e1ticamente ConfigView.label.watchtorrentfolder.tooltip=Procurar regularmente novos .torrent ConfigView.label.watchtorrentfolderinterval=Intervalo ConfigView.label.watchtorrentfolderinterval.tooltip=O per\u00edodo de tempo at\u00e9 que o direct\u00f3rio seja verificado de novo ConfigView.dialog.choosewatchtorrentfolderpath=Escolha o direct\u00f3rio de importa\u00e7\u00e3o de Torrents ConfigView.label.startwatchedtorrentsstopped=Iniciar parado ConfigView.label.startwatchedtorrentsstopped.tooltip=Adicionar novos .torrents em modo PARADO ConfigView.section.plugins=Extens\u00f5es wizard.maketorrent.filesize=Tamanho Ficheiro(s) wizard.maketorrent.piececount=N\u00famero de Peda\u00e7os wizard.maketorrent.piecesize=Tamanho de um Peda\u00e7o MainWindow.menu.view.stats=Estat\u00edsticas SpeedView.title.full=Actividade SpeedView.downloadSpeed.title=Velocidade de Recep\u00e7\u00e3o SpeedView.uploadSpeed.title=Velocidade de Envio ConfigView.section.style.useSIUnits=Usar unidades SI (KB -> KiB etc.) iconBar.top.tooltip=Mover para o Inicio iconBar.bottom.tooltip=Mover para o fim TableColumn.header.health=Sa\u00fade MyTorrentsView.menu.health=Sobre a Sa\u00fade health.explain.grey=significa que o seu torrent n\u00e3o est\u00e1 a correr (seja a sacar ou semear) health.explain.red=significa que n\u00e3o est\u00e1 ligado a nenhum peer enquanto est\u00e1 a sacar health.explain.blue=quando estiver a semear, significa que n\u00e3o est\u00e1 ligado a nenhum par\nquando estivar a sacar, significa que est\u00e1 ligado a alguns pares mas que o tracker est\u00e1 inacess\u00edvel health.explain.yellow=significa que o tracker est\u00e1 bom, voc\u00ea est\u00e1 ligado a alguns pares, mas n\u00e3o est\u00e1 a aceitar liga\u00e7\u00f5es remotas.\nVoc\u00ea pode ter um problema de NAT se o torrents ficarem amarelos por muito tempo health.explain.green=significa que est\u00e1 tudo a decorrer normalmente. ConfigView.section.style.alwaysRefreshMyTorrents=Actualizar sempre os Meus Torrents ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Esta op\u00e7\u00e3o actualizar sempre os Meus Torrents mesmo que n\u00e3o mostrados (\u00fatil para algumas extens\u00f5es do mirc) # #2.0.7.0 # security.certtruster.title=Aviso, Certificado de Seguran\u00e7a security.certtruster.intro=O certificado de seguran\u00e7a foi emitido por uma companhia em que n\u00e3o confia security.certtruster.resource=Recurso: security.certtruster.issuedto=Emitido Para:: security.certtruster.issuedby=Emitido Por: security.certtruster.prompt=Voc\u00ea quer confiar nele? security.certtruster.yes=Sim security.certtruster.no=N\u00e3o ConfigView.section.tracker.torrentsperpage=Quantos torrents por p\u00e1gina? [0: sem limite] MainWindow.menu.file.share=&Partilhar MainWindow.menu.file.share.file=&Ficheiro... MainWindow.menu.file.share.dir=&Directoria... MainWindow.menu.file.share.dircontents=&Conteudo da Directoria... MainWindow.menu.file.share.dircontentsrecursive=Conte\u00fado da Pasta (&Recursivo)... MainWindow.dialog.share.sharefile=Seleccione Ficheiro a Partilhar MainWindow.dialog.share.sharedir=Seleccione Direct\u00f3rio Para Partilhar MainWindow.dialog.share.sharedircontents=Seleccione os Conte\u00fados de um Direct\u00f3rio a partilhar MainWindow.dialog.share.sharedircontents.recursive=Recursivamente globalmanager.download.remove.veto=Ac\u00e7\u00e3o de remo\u00e7\u00e3o Vetada plugin.sharing.download.remove.veto=Este download \u00e9 o resultado de um recurso que est\u00e1 em partilha.\nPara remover este download, remova a partilha associada.: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Principal ConfigView.section.tracker.web=P\u00e1gina ConfigView.label.prioritizefirstpiece=Dar prioridade ao primeiro bloco de cada ficheiro ConfigView.label.prioritizefirstpiece.tooltip=Tenta sacar primeiro o in\u00edcio de cada ficheiro.\nPara suportar a pr\u00e9-visualiza\u00e7\u00e3o de ficheiros incompletos. ConfigView.section.file.confirm_data_delete=Confirmar quando apagar ficheiros ConfigView.section.file.confirm_data_delete.tooltip=Confirma apagar ficheiros quando usar 'Remover e Apagar...' TrayWindow.menu.startalldownloads=Iniciar Todos as Transfer\u00eancias SystemTray.menu.startalltransfers=Iniciar todas as Transfer\u00eancias sharing.progress.title=Progresso da Partilha sharing.progress.hide=Esconder MainWindow.menu.view.myshares=&As Minhas Partilhas MySharesView.title.full=As Minhas Partilhas MySharesView.name=Nome MySharesView.type=Tipo MySharesView.type.file=Ficheiro MySharesView.type.dir=Directoria MySharesView.type.dircontents=Conte\u00fado da Directoria MySharesView.type.dircontentsrecursive=Conte\u00fado da Directoria (recursivo) MySharesView.menu.remove=Remover ConfigView.section.tracker.extensions=Extens\u00f5es ConfigView.section.tracker.sendpeerids=Enviar identidade dos pares ConfigView.section.tracker.enableudp=Ligar protocolo de tracker UDP plugin.sharing.torrent.remove.veto=O registo deste tracker \u00e9 o resultado de um recurso que est\u00e1 a ser partilhado.\nPara remover o download, remova a partilha associada.: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=A transfer\u00eancia n\u00e3o pode ser removida porque ainda n\u00e3o foi parado plugin.sharing.remove.veto=Esta partilha \u00e9 uma subdirectoria da partilha do \u2018Conte\u00fados do Direct\u00f3rio\u2019 e n\u00e3o pode ser explicitamente apagado.\nApague a partilha pela raiz. GeneralView.label.hash.tooltip=Clique para copiar hash para a \u00e1rea de transfer\u00eancia ConfigView.section.tracker.maxpeersreturned=N\u00famero m\u00e1ximo de pares retornado [0: sem limite] ConfigView.label.serverport=Porto TCP de entrada \u00e0 escuta ConfigView.label.serverport.tooltip=A Porta tem de estar entre 1-65535, e n\u00e3o 6880 pois est\u00e1 reservada para funcionamento interno do Azureus. configureWizard.nat.server.tcp_listen_port=Porto de entrada TCP \u00e0 escuta ConfigView.section.sharing=Partilhar ConfigView.section.sharing.usessl=Usar SSL para recursos partilhados (necessita configura\u00e7\u00e3o do Servidor interno) ConfigView.section.style.dropdiraction=Ac\u00e7\u00f5es de Arrastar/Largar para direct\u00f3rios ConfigView.section.style.dropdiraction.opentorrents=Abrir Torrents ConfigView.section.style.dropdiraction.sharefolder=Partilhar Direct\u00f3rio ConfigView.section.style.dropdiraction.sharefoldercontents=Partilhar Conteudo # # 2.0.7.x # Categories.all=Todas Categories.uncategorized=N\u00e3o Categorizado CategoryAddWindow.message=Indique a nova Categoria CategoryAddWindow.title=Adicionar nova Categoria ConfigView.label.autoSeedingIgnoreInfo=Torrents ignorados v\u00e3o para o fim da fila de sementes. Estes n\u00e3o s\u00e3o semeados autom\u00e1ticamente. As regras de Ignorar n\u00e3o se aplicam a torrents em que se verifique o crit\u00e9rio de Primeira Prioridade. A menos que indicado em contr\u00e1rio, usar o valor 0 para inibir uma regra. ConfigView.label.directory=Directoria ConfigView.label.disconnetseed.tooltip=Quando estiver a semear, desliga-se de qualquer cliente que tamb\u00e9m esteja a semear.\nEles n\u00e3o precisam de comunicar consigo. ConfigView.label.ignoreCase=Ignorar Mai\u00fasculas/min\u00fasculas ConfigView.label.ignoreSeeds=Ignorar torrents com pelo menos ConfigView.label.importdirectory=Importar Directoria ConfigView.label.minPeersToBoostNoSeeds.tooltip=Qualquer torrent sem sementes e tendo menor numero de pares do que o especificado, seguir\u00e3o para o fim da fila ConfigView.label.minPeersToBoostNoSeeds=Baixar Prioridade de Semente para torrents sem sementes e com menos de ConfigView.label.minSeedingTime.tooltip=As Prioridades de Semente podem oscilar frequentemente em per\u00edodos de tempo curtos, \u00e0s vezes causando o torrent a iniciar autom\u00e1ticamente, s\u00f3 para ser parado imediatamente a seguir. Isto reduz o problema, for\u00e7ando a que o torrent permane\u00e7a a semear pelo per\u00edodo de tempo dado. Voc\u00ea pode ainda par\u00e1-lo manualmente se o desejar. ConfigView.label.minSeedingTime=Tempo minimo a semear (em segundos) ConfigView.label.minSpeedForActiveDL.tooltip=Um slot de transfer\u00eancia \u00e9 sempre usado para os 30 segundos iniciais ap\u00f3s o torrent incompleto iniciar. ConfigView.label.minSpeedForActiveDL=N\u00e3o considerar torrent como usando uma slot detransfer\u00eancia se a velocidade for inferior a ConfigView.label.peers=pares ConfigView.label.queue.debuglog=Registo da Informa\u00e7\u00e3o de debug ConfigView.label.queue.debuglog.info=Adiciona ao registo informa\u00e7\u00e3o de debug relativa \u00e0s Filas.\nApesar de cr\u00edptico, a informa\u00e7\u00e3o de debug d\u00e1 o estado dos torrents e porque \u00e9 que eles est\u00e3o (ou n\u00e3o) A Iniciar/Em Fila ConfigView.label.queue.minQueueingShareRatio=N\u00e3o p\u00f4r na fila ou parar torrent at\u00e9 que o r\u00e1cio de partilha atinja ConfigView.label.ratio=r\u00e1cio ConfigView.label.removeOnStop=Remove o torrent da lista depois de parar autom\u00e1ticamente ConfigView.label.savedirectory=Direct\u00f3rio de grava\u00e7\u00e3o ConfigView.label.seeding.autoReposition.tooltip=Se ligado, a ordem dos torrents (coluna '#') ser\u00e1 alterada para corresponder \u00e0 de Prioridade de Semente\u005cmIsto \u00e9 \u00fatil se voc\u00ea n\u00e3o gostar de ver os valores da Prioridade de Semente, mas ainda assim quer saber a ordem pela qual as sementes ir\u00e3o iniciar. ConfigView.label.seeding.autoReposition=Repor autom\u00e1ticamente os torrents com base na Prioridade de Semente ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Frequentemente, torrents com baixo n\u00famero de sementes e alto n\u00famero de pares, significa que provavelmente n\u00e3o existe uma c\u00f3pia completa entre os pares.\nPortanto, voc\u00ea poder\u00e1 n\u00e3o querer que as regras de semente finjam que exista uma c\u00f3pia completa (e assim reduzir incorrectamente a sua Prioridade) ConfigView.label.seeding.fakeFullCopySeedStart=mas apenas para torrents com pelo menos ConfigView.label.seeding.ignore=Ignorar Regras ConfigView.label.seeding.ignore0Peers=Ignorar torrents com 0 pares ConfigView.label.seeding.ignoreRatioPeers=Ignorar torrents que t\u00eam pelo menos 1 semente por cada ConfigView.label.seeding.ignoreShareRatio=Ignorar torrents que t\u00eam um r\u00e1cio de partilha de ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorar torrent mesmo que a regra\nde Primeira Prioridade se aplique ConfigView.label.seeding.ignore.header.rule=Regra ConfigView.label.seeding.ignore.header.value=Valor ConfigView.label.seeding.firstPriority.info=Torrents de Primeira Prioridade estar\u00e3o sempre no topo da fila. Qualquer torrent que verifique o crit\u00e9rio da Primeira Prioridade n\u00e3o ser\u00e1 automaticamente parado ou remetido para a fila. Um torrent que verifique a Primeira Prioridade tomar\u00e1 conta de um Slot de Download Simult\u00e2neo se for necess\u00e1rio. ConfigView.label.seeding.firstPriority.FP=Primeira Prioridade ConfigView.label.seeding.firstPriority=A Primeira Prioridade vai para torrents com ConfigView.label.seeding.firstPriority.following=dos seguintes: ConfigView.label.seeding.firstPriority.shareRatio=Um r\u00e1cio de partilha abaixo de ConfigView.label.seeding.firstPriority.seedingMinutes=O tempo decorrido desde que passou de download a semente ConfigView.label.seeding.firstPriority.DLMinutes=O tempo decorrido desde o come\u00e7o do download ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Fingindo que existe 1 c\u00f3pia completa por cada X pares, voc\u00ea reduz a prioridade dos torrents com grande n\u00famero de pares.\nProvavelmente, torrents com grande n\u00famero de pares tamb\u00e9m t\u00eam maiores velocidades.\nIsto n\u00e3o muda nenhum dos n\u00fameros de sementes mostrados. ConfigView.label.seeding.numPeersAsFullCopy=Fingir que existe 1 c\u00f3pia completa por cada\n(0 : n\u00e3o finge) ConfigView.label.seeding.preferLargerSwarms.tooltip=Se voc\u00ea semeia principalmente torrents com pares encravados, preferir torrents com mais utilizadores faz sentido.\nQuando voc\u00ea semeia principalmente torrents em fim de vida, preferir torrents com menos utilizadores faz sentido. ConfigView.label.seeding.preferLargerSwarms=Quando os torrents t\u00eam a mesma prioridade, preferir swarms maiores ConfigView.label.seeding.rankType.none.tooltip=Ordem baseada na coluna # ConfigView.label.seeding.rankType.none=Nenhum ConfigView.label.seeding.rankType.peerSeed.options=Op\u00e7\u00f5es do R\u00e1cio Pares:Sementes ConfigView.label.seeding.rankType.peerSeed.tooltip=Maior R\u00e1cio = Maior Prioridade ConfigView.label.seeding.rankType.peerSeed=R\u00e1cio Par:Semente ConfigView.label.seeding.rankType.seed.fallback=Usar R\u00e1cio Pares:Sementes depois de\n(0: Nunca Usar) ConfigView.label.seeding.rankType.seed.options=Op\u00e7\u00f5es de Contar Apenas Sementes ConfigView.label.seeding.rankType.seed.tooltip=Menos Sementes = Maior Propridade ConfigView.label.seeding.rankType.seed=Contar Apenas Sementes ConfigView.label.seeding.rankType.timedRotation.tooltip=Todos os torrents finalizados ir\u00e3o rodar para o modo de semente.\nDura\u00e7\u00e3o do tempo em semente \u00e9 defenido pelo 'Per\u00edodo M\u00ednimo de Semente' ConfigView.label.seeding.rankType.timedRotation=Rota\u00e7\u00e3o por Tempo ConfigView.label.seeding.rankType.tooltip=Torrents com maior prioridade s\u00e3o iniciados autom\u00e1ticamente.\nQuando outro torrent obt\u00eam uma prioridade maior, o de mais baixa prioridade para e volta para a fila.\n\nApenas torrents no estado Em Fila est\u00e3o dispon\u00edveis para iniciar autom\u00e1ticamente.\nTorrents parados nunca s\u00e3o iniciados autom\u00e1ticamente. ConfigView.label.seeding.rankType=Dar prioridade a torrents finalizados para auto-iniciar baseados em: ConfigView.label.stopAfterMinutes=Quando mudar para Semente, parar ap\u00f3s um per\u00edodo de tempo ConfigView.label.switchpriority.tooltip=Baixa prioridade reduz a quantidade da largura de banda para envio alocada ao torrent. ConfigView.pluginlist.info=As seguintes extens\u00f5es foram identificadas. Algumas extens\u00f5es podem n\u00e3o ter pain\u00e9is de configura\u00e7\u00e3o. ConfigView.pluginlist.noplugins=Nenhuma extens\u00e3o encontrada. ConfigView.section.pluginslist=Lista ConfigView.section.queue.seeding=Semeando ConfigView.section.queue.seeding.autoStarting=Inciar Autom\u00e1ticamente ConfigView.section.queue.seeding.ignore=Ignorar Regras ConfigView.section.queue.seeding.firstPriority=Primeira Prioridade ConfigView.section.queue.main=Principal ConfigView.section.queue=Filas ConfigView.text.all=todas ConfigView.text.hours=horas ConfigView.text.ignoreRule=Ignorar Regra ConfigView.text.ignore=ignorar ConfigView.text.minutes=minutos ConfigView.text.neverIgnore=Nunca Ignorar ConfigView.text.any=qualquer DownloadManager.error.datamissing=Dados em Falta MainWindow.menu.file.open.torrentforseeding=Ficheiro .torrent (Para Semear) MainWindow.menu.language.refresh=&Actualizar ManagerItem.forced=For\u00e7ado ManagerItem.queued=Em Fila MySeedersView.header=Torrents Completos TableColumn.header.availability.info=# c\u00f3pias completas a serem vistas TableColumn.header.availability=Disponibilidade TableColumn.header.category=Categoria MyTorrentsView.header=Torrents Incompletos/Recebendo TableColumn.header.maxuploads=Max # Envios MyTorrentsView.menu.category.delete=&Apagar Categoria MyTorrentsView.menu.forceStart=&For\u00e7ar In\u00edcio MyTorrentsView.menu.queue=&Fila MyTorrentsView.menu.setCategory.add=&Adiciona Categoria MyTorrentsView.menu.setCategory=Atribui Categoria TableColumn.header.savepath=Caminho para Guardar TableColumn.header.SeedingRank=Prioridade de Semente TableColumn.header.totalspeed.info=Velocidade Total de todos os pares a que est\u00e1 ligado TableColumn.header.totalspeed=Velocidade Total splash.initializePlugins=A Inicializar as extens\u00c3\u00b5es StartStopRules.SPratioMet=S:P R\u00e1cio OK StartStopRules.FP0Peers=FP / 0 Pares StartStopRules.0Peers=0 Pares StartStopRules.numSeedsMet=# Sementes OK StartStopRules.ratioMet=Pares:Sementes OK StartStopRules.shareRatioMet=R\u00e1cio Partilha Ok StartStopRules.waiting=\u00c0 Espera StartStopRules.firstPriority=Primeira Pioridade ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Partilhar Conte\u00fado (Recursivo) DownloadManager.error.unabletostartserver=N\u00e3o consegui iniciar Servidor - verifique a configura\u00e7\u00e3o do porto de entrada / permiss\u00f5es de firewall para a aplica\u00e7\u00e3o funcionar como servidor GeneralView.label.creationdate=Criado Em : ConfigView.section.tracker.announcescrapepercentage=Intervalo de Scrape como %age do an\u00fancio\u005cex. 200 = 2:1. 0 = deixar o peer decidir ManagerItem.stopping=A Parar ConfigView.section.tracker.announcecacheperiod=Anunciar cache (millis) ConfigView.section.tracker.scrapecacheperiod=Cache de Scrape (milissegundos) ConfigView.section.tracker.scrapeandcache=Scrape e cache fileDownloadWindow.retry=Re-tentar MyTrackerView.bytesin=Bytes que entraram MyTrackerView.bytesinave=M\u00e9dia de entradas MyTrackerView.bytesout=Bytes que sairam MyTrackerView.bytesoutave=M\u00e9dia de sa\u00eddas ConfigView.section.file.max_open_files=N\u00famero m\u00e1ximo de ficheiros abertos para leitura/escrita\n[0: sem limite] ConfigView.section.file.max_open_files.tooltip=\u00datil se voc\u00ea usar torrents com centenas/milhares de ficheiros, e se estiver a atingir os limites de gest\u00e3o de ficheiros no SO. ConfigView.section.proxy=Op\u00e7\u00f5es Proxy ConfigView.section.proxy.enable_proxy=Permitir Proxy ConfigView.section.proxy.host=Servidor ConfigView.section.proxy.port=Porto ConfigView.section.proxy.username=Nome de Utilizador ConfigView.section.proxy.password=Senha ConfigView.section.proxy.enable_socks=Eu tenho um Proxy SOCKS wizard.createtorrent.extrahashes=Adicionar verifica\u00e7\u00f5es (hashes) para outras redes (Ex: Gnutella2, eDonkey2000) GeneralView.label.connected=ligado GeneralView.label.in_swarm=No swarm ManagerItem.initializing=A Inicializar AlertMessageBox.error=Erro AlertMessageBox.warning=Aviso AlertMessageBox.comment=Informa\u00e7\u00e3o AlertMessageBox.information=Informa\u00e7\u00e3o SharedPortServer.alert.selectorfailed=Falha ao estabelecer o porto de escuta para dados de entrada\nVerifique se a configura\u00e7\u00e3o Firewall permite que processos java(w).exe funcionem como 'Servidor' Tracker.alert.listenfail=Falha ao estabelecer escuta no porto %1.\nVerifique se outra aplica\u00e7\u00e3o est\u00e1 a usar este porto.\nVerifique ainda se tem outra c\u00f3pia do Vuze a executar. DiskManager.alert.movefileexists=Erro ao mover ficheiros finalizados\nO Ficheiro %1 j\u00e1 existe no direct\u00f3rio de destino DiskManager.alert.movefilefails=Erro ao mover ficheiros finalizados\nFalha ao mover ficheiro %1, %2 DiskManager.alert.movefilerecoveryfails=Erro ao recuperar ap\u00f3s falha de mover\nFalha ao restaurar ficheiro %1, %2 ConfigView.section.tracker.logenable=Registar as estat\u00edsticas peri\u00f3dicamente para 'tracker.log' SpeedView.stats.title=Estat\u00edsticas SpeedView.stats.total=Totais SpeedView.stats.session=Esta Sess\u00e3o SpeedView.stats.session.tooltip=Total (Protocolo) SpeedView.stats.downloaded=Recebido SpeedView.stats.uploaded=Enviado SpeedView.stats.ratio=R\u00e1cio SpeedView.stats.uptime=Tempo Execu\u00e7\u00e3o (horas) SpeedView.stats.now=Agora SpeedView.stats.now.tooltip=Total (Protocolo) AutoMigration.useralert=Resultado da migra\u00e7\u00e3o autom\u00e1tica dos ficheiros/configura\u00e7\u00f5es/directorios:\n\n%1\n%2QUAISQUER FALHAS DEVEM SER RESOLVIDAS MANUALMENTE. # # > 2.0.8.0 # OpenTorrentWindow.title=Abrir Torrent(s) OpenTorrentWindow.message=Em teste OpenTorrentWindow.addFiles=&Adicionar Ficheiros OpenTorrentWindow.dataLocation=Directorio onde guardar dados: OpenTorrentWindow.startMode=Modo de Adi\u00e7\u00e3o OpenTorrentWindow.startMode.queued=Em Fila OpenTorrentWindow.startMode.stopped=Parado OpenTorrentWindow.startMode.forceStarted=Execu\u00e7\u00e3o For\u00e7ada OpenTorrentWindow.addPosition=Posi\u00e7\u00e3o na Fila OpenTorrentWindow.addPosition.first=Primeiro OpenTorrentWindow.addPosition.last=\u00daltimo TableColumn.header.remaining.info=Quantidade restante a receber TableColumn.header.remaining=Restam ConfigView.section.tracker.enablecompact=Ligar protocolo de an\u00fancio compacto ConfigView.section.tracker.enablekey=Ligar envio de chave para o tracker para melhor seguran\u00e7a ConfigView.section.file.perf=Op\u00e7\u00f5es de Performance ConfigView.section.file.perf.explain=AVISO - altera\u00e7\u00f5es mal definidas destes par\u00e2metros, podem agravar a performance de recep\u00e7\u00e3o. \n[\u00c9 necess\u00e1rio reiniciar a aplica\u00e7\u00e3o]\nSe voc\u00ea tiver problemas de "falta de mem\u00f3ria", considere limitar o n\u00famero de liga\u00e7\u00f5es por torrent (veja a sec\u00e7\u00e3o de configura\u00e7\u00e3o, Transfer\u00eancias) ConfigView.section.file.max_open_files.explain=Abrir demasiados ficheiros pode causar problemas no sistema operativo, devido a recursos limitados tais como gest\u00e3o de ficheiros. Isto limita o n\u00famero de ficheiros que podem estar abertos simultaneamente. popup.error.hide=Esconder popup.error.details=Detalhes ConfigView.section.style.colorOverrides=Definir Outra Cor ConfigView.section.style.colorOverride.progressBar=Barra de Progresso ConfigView.section.style.colorOverride.error=Erro MainWindow.status.tooOld=est\u00e1 desactualizado, por favor actualize ConfigView.section.style.colorOverride.warning=Aviso ConfigView.section.style.colorOverride.altRow=Linhas Alternadas ConfigView.section.file.save.peers.enable=Guardar liga\u00e7\u00f5es aos pares para r\u00e1pidos recome\u00e7os ConfigView.section.file.save.peers.max=N\u00famero m\u00e1ximo de liga\u00e7\u00f5es a guardar [0: ilimitadas] ConfigView.section.file.save.peers.pertorrent=por torrent ConfigView.label.max_peers_per_torrent=N\u00famero m\u00e1ximo de liga\u00e7\u00f5es por torrent [0: ilimitadas] ConfigView.label.max_peers_total=N\u00famero m\u00e1ximo de liga\u00e7\u00f5es (Global) [0: ilimitadas] ConfigView.section.style.colorOverrides.reset=Rep\u00f4r Cores ConfigView.section.language.info=Quando ligada, uma actualiza\u00e7\u00e3o \u00e9 efectuada cada vez que o Vuze arranca. ConfigView.section.language.enableUpdate=Ligar Actualiza\u00e7\u00e3o Web ConfigView.section.language.UpdateURL=URL de Actualiza\u00e7\u00e3o ConfigView.section.language.UpdateNow=Actualizar Agora! Button.revert=Reverter MyTorrentsView.menu.changeDirectory=Mudar Direct\u00f3rio de Dados GenericText.column=coluna MyTorrentsView.menu.thisColumn.remove=Remover Coluna MyTorrentsView.menu.thisColumn.toClipboard=Copiar Texto para \u00c1rea de Transfer\u00eancia TableColumn.header.secondsseeding=Enviando \u00e0 TableColumn.header.secondsseeding.info=A quantidade de tempo a que est\u00e1 a enviar TableColumn.header.secondsdownloading=DLing para TableColumn.header.secondsdownloading.info=A quantidade de tempo a que est\u00e1 a receber ConfigView.section.tracker.udpversion=Vers\u00e3o do Protocolo UDP (1 ou 2) window.updateswt.title=A sua vers\u00e3o do SWT est\u00e1 desactualizada! window.updateswt.text=A sua vers\u00e3o do SWT est\u00e1 desactualizada!\nSWT \u00e9 a libraria gr\u00e1fica usada pelo Vuze e a vers\u00e3o que tem \u00e9 demasiado velha para correr a vers\u00e3o mais recente do Azureus. Carregue em OK para actualizar o SWT window.updateswt.status=Estado window.updateswt.failed=Falhou a actualiza\u00e7\u00e3o, carregue OK outra vez para reiniciar. window.updateswt.status.downloading.updater=Recebendo o M\u00f3dulo de Actualiza\u00e7\u00e3o window.updateswt.status.finding=\u00c0 procura de vers\u00e3o mais recente do SWT window.updateswt.status.downloading=Recebendo a vers\u00e3o mais recente do SWT window.updateswt.status.done=A Reiniciar window.updateswt.cancel=Cancelar swt.updater.downloader.downloading=Recebendo SWT de swt.updater.urlsgetter.downloading=Obtendo uma lista de mirrors de swt.updater.urlsgetter.platform=SWT para a plataforma : window.updateswt.ignore=Ignorar ConfigView.section.style.useFancyTabs=Usar Separadores Com Estilo splash.initializeGM=Iinicializando Gestor Global de Torrents splash.loadingTorrents=Carregando Torrents splash.firstMessageNoI18N=(-: Vuze :-) MyTorrentsView.menu.thisColumn.sort=&Ordenar Scrape.status.ok=Scrape Ok. Scrape.status.error=Erro de Scrape: Scrape.status.error.badURL=URL do An\u00fancio n\u00e3o segue as especifica\u00e7\u00f5es de Scrape. Scrape.status.error.nohash=Hash n\u00e3o existe na resposta. Scrape.status.error.invalid=Resposta inv\u00e1lida. Scrape.status.nextScrapeAt=Prox. scrape \u00e0s %1 Scrape.status.initializing=\u00c0 Espera para Scrape Scrape.status.scraping.queued=Scraping em espera... ConfigView.label.minSpeedForActiveSeeding=N\u00e3o considerar slot em uso se velocidade de envio de semente for inferior a ConfigView.section.stats.exportpeers=Exportar detalhes do par MainWindow.menu.view.irc.moved=O IRC est\u00e1 disponivel como uma extens\u00e3o, veja http://azureus.sourceforge.net/plugin_list.php.\nQuando instalado use o menu Ver > Extens\u00f5es > IRC para aceder a este. MyTrackerView.webui.contextmenu.copyurl=Copiar URL do torrent para \u00c1rea de Transfer\u00eancia ConfigView.section.file.torrent.ignorefiles=Ficheiros a ignorar quando cria torrents:\nex: .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignorando ficheiro ConfigView.section.style.useUnitsRateBits=Usar bits em vez de bytes para valores de taxas baseados em bytes (KiB/s->Kibit/s etc.) ConfigView.section.interface.resetassoc=Rep\u00f4r associa\u00e7\u00e3o a ficheiros .torrent ConfigView.section.interface.resetassocbutton=Rep\u00f4r ConfigView.section.interface.checkassoc=Verificar associa\u00e7\u00f5es no arranque dialog.associations.title=Verificar Associa\u00e7\u00e3o Button.yes=Sim Button.no=N\u00e3o ConfigView.label.seeding.autoStart0Peers=Ligar autom\u00e1ticamente sementes com 0 leechers ConfigView.label.seeding.autoStart0Peers.tooltip=Ligar se voc\u00ea quer que o tracker contabilize as sementes para torrents com 0 leechers. dialog.associations.prompt=O Vuze n\u00e3o \u00e9 a aplica\u00e7\u00e3o predefinida para ficheiros BitTorrent.\nQuer associar os ficheiros .torrent com o Vuze dialog.associations.askagain=Verificar no Arranque ConfigView.section.plugins.update=Actualiza\u00e7\u00e3o de Extens\u00f5es Plugin.pluginupdate.enablecheck=Ligar actualiza\u00e7\u00e3o de extens\u00f5es plugins.basicview.status=Estado: plugins.basicview.activity=Actividade: plugins.basicview.progress=Progresso: plugins.basicview.log=Registo: ConfigView.label.maxdownloadspeed=Velocidade m\u00e1xima de transfer\u00eancia - KB/s (Global) [0: ilimitado] splash.loadingTorrent=Carregando Torrent splash.of=de ConfigView.pluginlist.broken=Partido ConfigView.pluginlist.whereToPut=Coloque qualquer extens\u00e3o especifica de utilizador num direct\u00f3rio individual, dentro de: ConfigView.pluginlist.whereToPutOr=Para extens\u00f5es partilhadas entre utilizadores, use: MainWindow.statusText.checking=Verificando por Actualiza\u00e7\u00f5es TableColumn.header.OnlyCDing4.info=Quantidade de tempo que o torrent esteve apenas a semear. Exclui o tempo que o torrent esteve a receber (e a semear) ConfigView.section.style.alternateTablePainting=Usar m\u00e9todo alternativo para pintar colunas das tabelas com gr\u00e1ficos (pode requerer reinicio) ConfigView.pluginlist.shared=partilhado PeersView.host=Nome do PC PeersView.host.info=O nome da m\u00e1quina em que se encontra o par, quando disponivel (pode afectar a performance) MainWindow.menu.help.whatsnew=O que h\u00e1 de novo ConfigView.label.checkonstart=Procurar nova vers\u00e3o no arranque do Vuze ConfigView.label.periodiccheck=Verificar peri\u00f3dicamente se h\u00e1 uma nova vers\u00e3o ConfigView.label.opendialog=Abrir autom\u00e1ticamente o Assistente de Actualiza\u00e7\u00e3o quando h\u00e1 uma actualiza\u00e7\u00e3o MainWindow.updateavail=(Actualiza\u00e7\u00e3o Dispon\u00edvel) MainWindow.status.latestversionunchecked=Verifica\u00e7\u00e3o de vers\u00e3o desligada GeneralView.label.updatein.stopped=Parado StartStopRules.menu.viewDebug=Ver Informa\u00e7\u00e3o de Debug ConfigView.section.style.doNotUseGB=N\u00e3o usar a unidade GB ConfigView.section.style.doNotUseGB.tooltip=Se ligado, O Vuze continua a usar MB mesmo para tamanhos superiores a 1024 MB MainWindow.menu.help.plugins=Extens\u00f5es ConfigView.section.plugins.TrackerWeb=Web do Tracker ConfigView.section.tracker.enablecategories=Separar torrents por categoria health.explain.share=sinifica que o torrent est\u00e1 ou hospedado ou publicado ConfigView.section.tracker.createcert=Criar um certificado auto assinado ConfigView.section.tracker.createbutton=Criar security.certcreate.title=Criar um Certificado assinado por si security.certcreate.intro=Este di\u00e1logo deixa-o criar um certificado assinado por si security.certcreate.alias=Alcunha security.certcreate.strength=For\u00e7a security.certcreate.firstlastname=Primeiro e \u00faltimo nome security.certcreate.orgunit=Unidade Organizacional security.certcreate.org=Organiza\u00e7\u00e3o security.certcreate.city=Cidade ou Localidade security.certcreate.state=Estado ou Prov\u00edncia security.certcreate.country=C\u00f3digo do Pa\u00eds(duas letras) security.certcreate.ok=Criar security.certcreate.cancel=Cancelar security.certcreate.createok=Cria\u00e7\u00e3o do Certificado com sucesso security.certcreate.createfail=Cria\u00e7\u00e3o do Certificado falhou ConfigView.section.plugins.webui=Swing Interface Web ConfigView.section.plugins.xml_http_if=Interface XML/HTTP webui.passwordenable=Activar palavra-chave webui.user=Nome de utilizador webui.password=Palavra-Chave webui.port=Porta (*) webui.protocol=Protocolo (*) webui.homepage=P\u00e1gina Inicial (*) webui.rootdir=Directoria Base (*) webui.rootres=Recurso Base (*) webui.mode=Modo (*) webui.mode.info=Modo pode ser \n\t"full"\t= todas as opera\u00e7\u00f5es dispon\u00edveis (pr\u00e9 definido)\n\t"view"\t= ver apenas (mas pode actualizar a frequ\u00eancia de actualiza\u00e7\u00e3o) webui.access=Acesso (*) webui.access.info=O Acesso pode ser\n\t"local"\t= significa que apenas a m\u00e1quina local se pode ligar\n\t"todos"\t= acesso sem restri\u00e7\u00f5es (pr\u00e9-definido)\n\tIP\t= ex, 192.168.0.2\t\t\tum IP apenas\n\tIP1-IP2\t= ex, 192.168.0.1-192.168.0.255\tinclusive gamas de IPs GeneralView.label.maxdownloadspeed=M\u00e1x Down Security.keystore.corrupt=Falhou o carregamento da Keystore '%1' , por favor apague-o e recrie(re-importe os certificados Security.keystore.empty=A Keystore est\u00e1 vazia.Por favor crie um cerificado auto-assinado (ver ferramentas->Op\u00e7\u00f5es->Seguran\u00e7a) ou importe um certificado existente para o '%1' webui.restart.info=Altera\u00e7\u00f5es de par\u00e2metros marcados com (*) requer uma reinicializa\u00e7\u00e3o para ter efeito GeneralView.label.maxdownloadspeed.tooltip=M\u00e1x velocidade de transfer\u00eancia [0: ilimitado] upnp.enable=Activar UPnP upnp.info=O Universal Plug and Play (UPnP) permite o mapeamento autom\u00e1tico das portas UPnP em routers. upnp.mapping.dataport=Porta de dados do Par a chegar upnp.mapping.tcptrackerport=Porta TCP do Tracker upnp.mapping.udptrackerport=porta UDP do Tracker upnp.alert.differenthost=UPnP:O Mapeamento '%1' foi reservado por '%2' - por favor seleccione uma porta diferente upnp.alert.mappingok=UPnP: Mapeamento '%1' estabelecido upnp.alert.mappingfailed=UPnP: O Mapeamento '%1' falhou upnp.alertsuccess=Relat\u00f3rio de Mapeamentos com Sucesso upnp.alert.lostdevice=UPnP: Perdeu-se a liga\u00e7\u00e3o ao servi\u00e7o '%1'no dispositivo UPnP '%2' upnp.grabports=Mapeamento de portas mesmo as propriedade de outro computador upnp.refresh.label=Actualizar os Mapeamentos upnp.refresh.button=Actualizar upnp.alert.mappinggrabbed=UPnP: Mapeamento '%1' estabelecido - agarrado de '%2' upnp.mapping.tcpssltrackerport=Porta TCP SSL do Tracker upnp.alertothermappings=Relat\u00f3rios sobre portas propriedade de outros computadores upnp.alertdeviceproblems=Reportar problemas com o dispositivo UPnP ConfigView.pluginlist.coreplugins=As seguintes extens\u00f5es internas est\u00e3o carregadas: Peers.column.DLedFromOthers=De Outros Peers.column.DLedFromOthers.info=Quantidade de dados transferidos de outros enquanto ligados a si Peers.column.UpDownRatio=Up:Transf Peers.column.UpDownRatio.info=R\u00e1cio do Par "Uploaded : Transferido" Peers.column.UpRatio=R\u00e1cio de Up Peers.column.UpRatio.info=R\u00e1cio do Par "Upload de si : Uploadedde outros" upnp.releasemappings=Libertar Mapeamentos ao sair webui.upnpenable=Activar UPnP para esta porta (*) ConfigView.section.file.friendly.hashchecking=Verifica\u00e7\u00e3o de hash amig\u00e1vel ConfigView.section.file.friendly.hashchecking.tooltip=Um modo de verifica\u00e7\u00e3o de hash de blocos, ligeiramente mais lento, mas com bastante menos impacto no CPU/Sistema. ConfigView.section.tracker.seedretention=M\u00e1x de seeds retidas pelo torrent [0: ilimitado] ConfigView.section.tracker.seedretention.info=Nota: As estat\u00edsticas de Upload ser\u00e3o perdidas para os pares n\u00e3o retidos ConfigView.section.tracker.port=Activar tracker na porta HTTP ConfigView.section.tracker.sslport=Activar tracker na porta HTTPS ConfigView.section.tracker.publicenable.info=Isto permite que outros criem torrents que usam o seu tracker\nsem que vo\u00e7\u00ea os hospede/publique Button.clear=Limpar MainWindow.IPs.tooltip={ultima actualiza\u00e7\u00e3o da lista dos filtros} N\u00famero total de Filtros de IP na lista - N\u00famero de IPs bloqueados na sess\u00e3o. Clique 2x para detalhes. ConfigView.section.ipfilter.list.banned=foi banido ConfigView.section.ipfilter.list.baddata=enviou dados errados: ocorr\u00eancias = Button.reset=Reinicializar ConfigView.section.ipfilter.bannedinfo=IPs que enviaram dados errados \u2013 banidos se excederem os limites ConfigView.section.ipfilter.blockedinfo=IPs que foram bloqueados devido aos Filtros de IP download.removerules.name=Regras de Remo\u00e7\u00e3o download.removerules.unauthorised.info=Torrents n\u00e3o autorizados s\u00e3o aqueles em que o an\u00facio de resposta cont\u00e9m ou"n\u00e3o autori(z)ado" ou "desautori(z)ado"na "falha da resposta" download.removerules.unauthorised=remover autom\u00e1ticamente torrents n\u00e3o autorizados download.removerules.unauthorised.seedingonly=\tApenas se estiver a seedar download.removerules.removed.ok=A remo\u00e7\u00e3o autom\u00e1tica do torrent '%1' foi bem sucedida. Isto foi causado pelas regras de remo\u00e7\u00e3o do torrent. download.removerules.updatetorrents=Remover os torrents de actualiza\u00e7\u00e3o do Vuze conforme o swarm requerer ConfigView.label.defaultstarttorrentsstopped=Por pr\u00e9-defini\u00e7\u00e3o adiciona novos torrents no estado Parado ConfigView.section.server.enableudp=Ligar protocolo Cliente/Tracker UDP. upnp.mapping.dataportudp=Porta Cliente UDP do tracker ConfigView.section.file.decoder.showlax=Considerar os modos de codifica\u00e7\u00e3o menos prov\u00e1veis ConfigView.section.file.decoder.showall=Considerar todos os modos de codifica\u00e7\u00e3o poss\u00edveis MainWindow.status.updowndetails.tooltip=Detalhes da velocidade de Download/Upload\nClique com o bot\u00e3o direito do rato para alterar, \nclique duas vezes para abrir as estat\u00edsticas TrackerClient.announce.warningmessage=Tracker para '%1' retornou um aviso '%2' ConfigView.section.tracker.natcheckenable=Verificar 'dados da porta a receber' conectividade e reportar falhas aos pares ConfigView.section.tracker.publishenabledetails=Publicar ficheiro torrent e detalhes dos pares ConfigView.section.tracker.publishenablepeerdetails=Publicar detalhes do par MyTrackerView.badnat=M\u00e1 NAT MyTrackerView.badnat.info=Seeds/Pares que falharam uma verifica\u00e7\u00e3o de NAT, se activado ConfigView.section.tracker.natchecktimeout=Verificar quando expira (seg.) ConfigView.section.file.perf.cache.enable=Ligar cache de disco ConfigView.section.file.perf.cache.size=Tamanho da cache em %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=T&ransfer\u00eancias MainWindow.menu.transfers.startalltransfers=Ini&ciar Todos MainWindow.menu.transfers.stopalltransfers=Pa&rar Todos MainWindow.menu.transfers.pausetransfers=&Pausa MainWindow.menu.transfers.resumetransfers=&Resumir ConfigView.label.experimental.osx.kernel.panic.fix=Correc\u00e7\u00e3o experimental para \u201ckernel panics\u201d em sistemas OSX dual-cpu [requer reinicio] SystemTray.menu.pausetransfers=Pausar Transf\u00earencias SystemTray.menu.resumetransfers=Retomar Transfer\u00eancias ConfigView.section.file.truncate.too.large=Truncar ficheiros existentes que s\u00e3o demasiado grandes ConfigView.section.file.perf.cache.trace=Rastrear opera\u00e7\u00f5es de cache com prop\u00f3sito de diagn\u00f3stico ConfigView.section.interface.enabletray=Ligar Barra de Sistema [requer reinicio] PeerManager.status.error=Erro Stats.title.full=Estat\u00edsticas TransferStatsView.title.full=Transfer\u00eancias CacheView.general.size=Tamanho Total CacheView.general.inUse=Em Uso CacheView.general.title=Info de Cache CacheView.reads.title=Leituras E/S CacheView.reads.fromFile=De Ficheiro CacheView.reads.fromCache=Da Cache CacheView.writes.title=Escritas E/S CacheView.writes.toCache=Para Cache CacheView.writes.toFile=Para Ficheiro CacheView.writes.hits=Guardados CacheView.speeds.title=Propor\u00e7\u00e3o de Dados CacheView.speeds.reads=Leituras CacheView.speeds.writes=Escritas CacheView.speeds.fromCache=De/Para Cache CacheView.speeds.fromFile=De/Para Ficheiro CacheView.reads.amount=Quantidade CacheView.reads.avgsize=Tam. M\u00e9dio openUrl.referrer=Referring URL da p\u00e1gina: openUrl.referrer.info=Apenas requerido por s\u00edtios web que o mandataram ConfigView.label.maxuploadspeedseeding=Alternar r\u00e1cio quando est\u00e1 apenas a seedar ConfigView.label.transfer.ignorepeerports=Ignora pares com estas portas (separados com \u2018;\u2019, ex: 0;25) ConfigView.section.proxy.enable_socks.peer=Ligar envio por proxy das comunica\u00e7\u00f5es de pares (apenas liga\u00e7\u00f5es de sa\u00edda) [requer reinicio] ConfigView.section.proxy.peer.informtracker=Informa o Tracker da limita\u00e7\u00e3o ConfigView.section.proxy.socks.version=Vers\u00e3o de SOCKS PiecesView.legend.written=Escrito PiecesView.legend.requested=Pedido PiecesView.legend.downloaded=Transferido, escrita em espera PiecesView.legend.incache=Os Dados est\u00e3o em Cache PiecesView.typeItem.0=Lento PiecesView.typeItem.1=R\u00e1pido PiecesView.type=Tipo Security.jar.tools_not_found=JAR signing fails - 'tools.jar' n\u00e3o foi encontrado %1. Ver Ferramentas->Op\u00e7\u00f5es->Seguran\u00e7a para detalhes. Security.jar.signfail=Liga\u00e7\u00e3o JAR falhou - %1 ConfigView.section.security.toolsinfo=Ficheiros JAR assinados s\u00e3o usados para suportar algumas extens\u00f5es, por exemplo a Interface Web Swing Interface (quando configurada para assim ser).\nDe forma a poder assinar ficheiro JAR \u00e9 necess\u00e1rio ter acesso ao ficheiro \u2018tools.jar\u2019 que vem com a instala\u00e7\u00e3o Sun JDK (e n\u00e3o a JRE normal).\nSe tem instalado o JRE, ent\u00e3o por favor instale o JDK.\nO Vuze consegue normalmente encontrar este ficheiro por si. No entanto se falhar, voc\u00ea deve indicar manualmente o direct\u00f3rio que cont\u00e9m este ficheiro. ConfigView.section.security.toolsdir=Direct\u00f3rio que cont\u00e9m \u2018tools.jar\u2019 ConfigView.section.security.choosetoolssavedir=Seleccionar a directora que cont\u00e9m \u2018tools.jar\u2019 ConfigView.section.proxy.peer.same=Usar o mesmo proxy para comunica\u00e7\u00f5es com o Tracker e Pares ConfigView.section.connection.network.max.simultaneous.connect.attempts=Nr. m\u00e1ximo de tentativas simult\u00e2neas de liga\u00e7\u00f5es de sa\u00edda [0: sa\u00edda inibida] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Nr. m\u00e1ximo de tentativas simult\u00e2neas de liga\u00e7\u00f5es de sa\u00edda que o Vuze pode estabelecer num dado instante.\nNOTA: O WindowsXP SP2 impoe uma limita\u00e7\u00e3o no sistema de 10 liga\u00e7\u00f5es (incompletas) simult\u00e2neas.\nValor por omiss\u00e3o \u00e9 8. Valor 0 inibe as liga\u00e7\u00f5es de sa\u00edda. ConfigView.section.file.perf.cache.size.explain=A cache \u00e9 usada para minimizar leituras de/para o disco. A menos que esteja a usar o Java com a op\u00e7\u00e3o '-XX:MaxDirectMemorySize' para definir explicitamente a memoria a ser usada para cache e uso de rede, voc\u00ea deve manter este valor pelo menos %1 abaixo do m\u00e1ximo da MV. O tamanho actual m\u00e1ximo da MV \u00e9 de %2. Para instru\u00e7\u00f5es de como mudar isto, ver MemoryUsage no wiki em %3. N\u00e3o usar valores correctos pode resultar em erros do tipo \u2018out of memory\u2019 (acabou-se a mem\u00f3ria). Mais de 32Mb de cache poder\u00e3o ser demais. MyTorrentsView.menu.setSpeed.unlimit=Sem Limite MyTorrentsView.menu.setSpeed.unlimited=Ilimitado MyTorrentsView.menu.setSpeed.disable=Desactivar o Upload MyTorrentsView.menu.setSpeed.disabled=Desactivado MyTorrentsView.menu.setSpeed.in=em MyTorrentsView.menu.setSpeed.slots=slots de GeneralView.label.maxuploadspeed=M\u00e1x Up GeneralView.label.maxuploadspeed.tooltip=velocidade max de upload [0 : ilimitado] MyTorrents.items.UpSpeedLimit.disabled=Sem upload MyTorrents.items.UpSpeedLimit.unlimited=Ilimitado TableColumn.header.maxupspeed=Velocidade M\u00e1x de Up TableColumn.header.maxupspeed.info=Velocidade M\u00e1x de Upload por torrent ConfigView.section.file.perf.cache.enable.write=Manter dados recebidos em cache para reduzir escritas em disco e reduzir leituras de disco para verifica\u00e7\u00e3o de blocos ConfigView.section.file.perf.cache.enable.read=Efectuar leituras adiantadas para reduzir as leituras de disco nos uploads ConfigView.section.tracker.separatepeerids=Usar identidades diferentes para o tracker e para a comunica\u00e7\u00e3o de dados ConfigView.section.tracker.separatepeerids.info=Aumenta o anonimato ao transferir/seedar an\u00f3nimamente\nao usar uma liga\u00e7\u00e3o a um tracker n\u00e3o an\u00f3nimo ConfigView.section.interface.wavlocation=Localiza\u00e7\u00e3o de ficheiro .wav ConfigView.section.interface.wavlocation.info=Selecciona ficheiro .wav ou deixa em branco para som predefinido ConfigView.section.tracker.server=Servidor ConfigView.section.tracker.client=Cliente ConfigView.section.tracker.client.connecttimeout=A Liga\u00e7\u00e3o expirou (segs) ConfigView.section.tracker.client.readtimeout=Expirar a leitura (seg.) MainWindow.menu.tools=&Ferramentas FilesView.path=Caminho FilesView.fullpath=Mostrar Caminho Completo FilesView.remaining=Peda\u00e7os restantes TableColumn.header.trackername=Nome do Tracker TableColumn.header.trackername.info=Nome do tracker baseado no URL de an\u00fancio ConfigView.group.override=Sobrepor Op\u00e7\u00f5es ConfigView.section.file.perf.cache.notsmallerthan=N\u00e3o fazer cache de ficheiros mais pequenos que isto (em %1) PeersView.menu.blockupload=Bloquear Upload PeersView.menu.kickandban=Kickar e Banir PeersView.menu.kickandban.reason=Par banido manualmente PeersView.state=Estado PeersView.state.info=Estado da liga\u00e7\u00e3o do par PeersView.state.pending=Em espera PeersView.state.connecting=A ligar PeersView.state.handshake=A esperar por aperto de m\u00e3o PeersView.state.established=Totalmente Estabelecido ConfigView.section.tracker.processinglimits=Limites de processamento ConfigView.section.tracker.maxgettime=Tempo M\u00e1x para obter o processamento GET (segs) [0: ilimitado] ConfigView.section.tracker.maxgettime.info=Utilizados para an\u00fancios e scrapes ConfigView.section.tracker.maxposttimemultiplier=Multiplicador de tempo GET para processamento POST [0: ilimitado] ConfigView.section.tracker.maxposttimemultiplier.info=Usado para fazer submiss\u00f5es e uploads ConfigView.section.tracker.maxthreads=Pedidos M\u00e1x concurrentes DownloadManager.error.operationcancancelled=Opera\u00e7\u00e3o Cancelada Torrent.create.progress.cancelled=Opera\u00e7\u00e3o cancelada sharing.progress.cancel=Cancelar wizard.maketorrents.autoopen=Abre o torrent para semear quando terminado ConfigView.section.sharing.rescanenable=Permitir peri\u00f3dicamente verificar as partilhas para mudan\u00e7as ConfigView.section.sharing.rescanperiod=Per\u00edodo de reverifica\u00e7\u00e3o (segs) ConfigView.section.connection.advanced=Defini\u00e7\u00f5es Avan\u00e7adas de Rede ConfigView.section.connection.advanced.mtu=Unidade de Transmiss\u00e3o M\u00e1xima por Linha (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Tamanho m\u00e1ximo de pacote que pode ser transferido numa Frame sobre a rede.\nO Vuze usa MTU-40 (MSS) para optimiza\u00e7\u00f5es do envio de pacotes (packet-payload).\nValores recomendados:\n 576 \u2013 Liga\u00e7\u00f5es dial-up\n1492 \u2013 Liga\u00e7\u00f5es banda-larga PPPoE\n1500 - Liga\u00e7\u00f5es banda-larga Ethernet, DSL e Cable ConfigView.section.connection.advanced.SO_RCVBUF=Tamanho do buffer de entrada - SO_RCVBUF [0: definido pelo SO] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Define o valor (em bytes) do socket SO_RCVBUF, isto \u00e9 o tamanho e escala da janela de recep\u00e7\u00e3o TCP.\nO Vuze n\u00e3o define isto por omiss\u00e3o, isto significa que as defini\u00e7\u00f5es do Sistema Operativo s\u00e3o usadas.\nNOTE: Em Linux os valores dados s\u00e3o duplicados. ConfigView.section.connection.advanced.SO_SNDBUF=Tamanho do buffer de sa\u00edda - SO_SNDBUF [0: definido pelo SO] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Define o valor (em bytes) do socket SO_SNDBUF, isto \u00e9 o tamanho e escala da janela de envio TCP.\nO Vuze n\u00e3o define isto por omiss\u00e3o, isto significa que as defini\u00e7\u00f5es do Sistema Operativo s\u00e3o usadas.\nNOTE: Em Linux os valores dados s\u00e3o duplicados.\n ConfigView.section.interface.confirm_torrent_removal=Mostrar di\u00e1logo de confirma\u00e7\u00e3o ao remover torrents ConfigView.section.interface.confirm_torrent_removal.tooltip=Confirmar quando Remover um Torrent da vista \u201cMeus Torrents\u201d MyTorrentsView.confirm_torrent_removal=Tem a certeza que deseja remover?\n TableColumn.header.seed_to_peer_ratio=R\u00e1cioSeed2Peer TableColumn.header.seed_to_peer_ratio.info=R\u00e1cio Total de swarm entre seeders e pares PeersView.connected_time=Tempo Ligado PeersView.connected_time.info=Tempo total ligado ao par ConfigView.section.interface.display.add_torrents_silently=Adicionar torrents silenciosamente ConfigView.section.interface.display.add_torrents_silently.tooltip=Adicionar download de torrents sem activar a janela principal do Azureus. TableColumn.header.maxdownspeed=Velocidade M\u00e1x de Transf TableColumn.header.maxdownspeed.info=Velocidade M\u00e1x de transfer\u00eancia por torrent ConfigView.section.tracker.passwordwebhttpsonly=Permitir apenas acesso via HTTPS TableColumn.header.torrentpath=Localiza\u00e7\u00e3o do Torrent TableColumn.header.torrentpath.info=Localiza\u00e7\u00e3o do Torrent no disco ConfigView.section.sharing.torrentcomment=Coment\u00e1rio para torrents gerados ConfigView.label.copyanddeleteratherthanmove=Copia e apaga os ficheiros originais em vez de mover numa s\u00f3 opera\u00e7\u00e3o \u2013 pode evitar perda de dados em alguns sistemas de ficheiro. ConfigView.label.openstatsonstart=Abrir Estat\u00edsticas no arranque swt.install.window.title=Instalador de extens\u00f5es do Vuze swt.install.window.ok=Instalar swt.install.window.header=Os seguintes componentes foram seleccionados para instala\u00e7\u00e3o : swt.uninstall.window.title=Desinstalador de extens\u00f5es do Vuze swt.uninstall.window.ok=Remover swt.uninstall.window.header=Os seguintes componentes foram seleccionados para desinstala\u00e7\u00e3ol : installPluginsWizard.title=Instalar Extens\u00f5es installPluginsWizard.mode.title=Por favor escolha um m\u00e9todo de instala\u00e7\u00e3o installPluginsWizard.mode.list=Por lista na sourceforge.net installPluginsWizard.list.title=Lista de extens\u00f5es installPluginsWizard.list.loading=Por favor aguarde enquanto a lista de extens\u00f5es \u00e9 carregada installPluginsWizard.list.loaded=Por favor escolha as extens\u00f5es que deseja instalar installPluginsWizard.list.name=Nome installPluginsWizard.list.version=Vers\u00e3o installPluginsWizard.list.description=Descri\u00e7\u00e3o das Extens\u00f5es installPluginsWizard.finish.title=Instala\u00e7\u00e3o em Curso installPluginsWizard.finish.explanation=As extens\u00f5e seleccionadas ser\u00e3o instaladas usando o Assistente de Actualiza\u00e7\u00f5es.T\n\nPor favor tenha paci\u00eancia, pois pode demorar um pouco a aparecer.\n\nPara um relat\u00f3rio sobre o progresso, clique duas vezes \u00e0 esquerda da barra de estado. installPluginsWizard.details.loading=A carregar Detalhes, por favor aguarde... installPluginsWizard.mode.file=Por ficheiro installPluginsWizard.installMode.title=Por favor escolha o tipo de instala\u00e7\u00e3o installPluginsWizard.installMode.user=Instalar as extens\u00f5es apenas para si installPluginsWizard.installMode.shared=Instalar as extens\u00f5es para todos os utilizadores installPluginsWizard.file.title=por favor navegue at\u00e9 \u00e0 extens\u00e3o que deseja instalar installPluginsWizard.file.file=Ficheiro : installPluginsWizard.file.invalidfile=O ficheiro n\u00e3o \u00e9 uma extens\u00e3o v\u00e1lida do Azureus. installPluginsWizard.file.browse=Navegar... uninstallPluginsWizard.title=Desinstalar Extens\u00c3\u00b5es uninstallPluginsWizard.list.title=Lista de Extens\u00f5es Instaladas uninstallPluginsWizard.list.loaded=Por favor escolha as extens\u00f5es que deseja desinstalar installPluginsWizard.list.nullversion=Sem Vers\u00e3o uninstallPluginsWizard.finish.title=Desinstala\u00e7\u00e3o em Curso uninstallPluginsWizard.finish.explanation=As Extens\u00f5es seleccionadas ser\u00e3o desisntaladas usando o Assistente de Actualiza\u00e7\u00e3o. MainWindow.menu.plugins.installPlugins=Assistente de Actualiza\u00e7\u00e3o... MainWindow.menu.plugins.uninstallPlugins=Assistente de Desinstala\u00e7\u00e3o... ConfigView.section.ipfilter.totalIPs=%1 IPs bloqueados no total, que corresponde a %2 da internet. update.instance.install=A Verificar Instala\u00e7\u00e3o update.instance.uninstall=A Verificar Desinstala\u00e7\u00e3o update.instance.update=A Verificar por Actualiza\u00e7\u00f5es MainWindow.status.update.tooltip=Clique duas vezes para Informa\u00e7\u00e3o sobre o progresso updater.progress.window.title=Tarefas de instala\u00e7\u00e3o Actuais updater.progress.window.info=Pressione 'Abortar' para terminar todas as tarefas Button.abort=Abortar ConfigView.section.ipfilter.enablebanning=Bloquear pares que consistentemente enviam dados errados Network.alert.acceptfail=Ocorreram demasiadas falhas sucessivas na porta %1, %2 -o processamento foi abandonado. Por favor verifique as configura\u00e7\u00f5es da firewall para esta porta assegurando que esta activada para receber liga\u00e7\u00f5es. MyShares.column.category=Categoria MainWindow.menu.file.restart=Reiniciar Vuze MainWindow.dialog.restartconfirmation.title=Reiniciar Vuze MainWindow.dialog.restartconfirmation.text=Deseja mesmo reiniciar o Vuze deletetorrent.message1=Est\u00e1 prestes a apagar o TORRENT para :\n deletetorrent.message2=\nTem a certeza que deseja continuar? ConfigView.label.prioritizemostcompletedfiles=Dar prioridade aos ficheiros com prioridade alta de acordo com a % e o tamanho do ficheiro splash.plugin.init=A inicializar extens\u00e3o: ConfigView.section.style.osx_small_fonts=Usar fontes pequenas [requer reinicio] ConfigView.section.tracker.tcpnonblocking=Utilizar o n\u00e3o bloqueamento de I/O para o processamento TCP do tracker. Seleccionar esta op\u00e7\u00e3o requer que a web do tracker corra numa porta alternativa.Em experi\u00eancia! ConfigView.section.tracker.nonblocking=Op\u00e7\u00f5es de N\u00e3o-Bloqueio ConfigView.section.tracker.nonblockingconcmax=M\u00e1x de liga\u00e7\u00f5es concurrentes [0: ilimitado] MyTorrentsView.menu.exportmenu=Exportar ConfigView.section.tracker.client.scrapeinfo=Desactivar o Scraping previne que muitas das regras de queueing dos torrents funcionem pois elas dependem da informa\u00e7\u00e3o de swarm obtida por scraping dos trackers. ConfigView.section.tracker.client.scrapeenable=Activar scraping ConfigView.section.tracker.client.scrapestoppedenable=Scrape torrents que est\u00e3o a correr Scrape.status.disabled=Scrape Desactivado MyTorrentsView.menu.explore=Mostrar ficheiro MyTorrentsView.menu.explore._mac=Mostrar no Procurar MyTorrentsView.menu.explore._windows=Mostrar no Explorer wizard.maketorrents.autohost=Serve o torrent no tracker interno ConfigView.label.overrideip=Sobrepor endere\u00e7o de IP enviado para o servidor - Utilize apenas se voc\u00ea sabe que precisa disto! ConfigView.label.overrideip.tooltip=Informa o Tracker de endere\u00e7o(s) de IP diferente(s) do que o registado nos pacotes enviados. Deixe em branco para n\u00e3o usar. ConfigView.section.connection.group.networks=Redes ConfigView.section.connection.group.networks.info=Selecciona as redes pr\u00e9-definidas permitidas para transmiss\u00e3o de dados em redes P2P ConfigView.section.connection.networks.prompt=Pergunta para seleccionar quando \u00e9 adicionado uma transfer\u00eancia de um tracker an\u00f3nimo ConfigView.section.connection.networks.Public=Rede p\u00fablica de IPs (n\u00e3o an\u00f3nima) ConfigView.section.connection.networks.I2P=Rede I2P ConfigView.section.connection.networks.Tor=Rede Onion Router (Tor) TableColumn.header.networks=Redes TableColumn.header.networks.info=Redes permitidas para comunica\u00e7\u00e3o de dados peer-pee Scrape.status.networkdisabled=Rede n\u00e3o activada ConfigView.section.tracker.server.group.networks=Redes ConfigView.section.tracker.server.group.networks.info=Selecciona as redes ao qual o tracker ir\u00e1 aceitar pares window.networkselection.title=Selecc\u00e7\u00e3o de Rede window.networkselection.info=O torrent listado em baixo tem tracker(s) que suportam as seguintes redes.\nSeleccione as redes para activar a comunica\u00e7\u00e3o para o tracker e para o parS.\nSe for um tracker an\u00f3nimo que suporta clientes p\u00fablicos active ambas as redes an\u00f3nima e p\u00fablica.\nActivar as redes p\u00fablicas tem a consequencia \u00f3bvia que \u00e9 a de revover o anonimato! plugins.basicview.clear=Limpar ConfigView.section.connection.group.peersources=Origem dos Pares ConfigView.section.connection.group.peersources.info=Selecciona as origens pr\u00e9-definidas permitidas para liga\u00e7\u00f5es a pares ConfigView.section.connection.peersource.Tracker=De um Tracker ConfigView.section.connection.peersource.DHT=Tracking descentralizado ConfigView.section.connection.peersource.PeerExchange=Fornecida por outro par ConfigView.section.connection.peersource.Plugin=Adicionado por uma extens\u00e3o ConfigView.section.connection.peersource.Incoming=Liga\u00e7\u00e3o de entrada PeersView.source=Origem PeersView.source.info=A origem deste par TableColumn.header.peersources=Origens dos Pares TableColumn.header.peersources.info=Origens dos pares permitidas para estabelecimento de liga\u00e7\u00f5es ao par wizard.tracker.dht=Descentralizado (apenas para clientes Vuze MyTorrentsView.menu.advancedmenu=Avan\u00e7ado MyTorrentsView.menu.networks=Redes MyTorrentsView.menu.peersource=Origens dos Pares ConfigView.section.sharing.permitdht=Permitir tracking descentralizado quando o Tracker n\u00e3o estiver dispon\u00edvel ConfigView.section.sharing.protocol=Protocolo para recursos partilhados PeersView.Messaging.info=Suporta messaging API avan\u00e7ado. ConfigView.label.queue.newseedsmovetop=Mover os torrents que acabam a transfer\u00eancia para a frente da lista de sementes ConfigView.label.seeding.firstPriority.ignore.info=Preste aten\u00e7\u00e3o que usando estas regras pode resultar em parar um torrent mal ele termine o download. ConfigView.label.seeding.firstPriority.ignore=Ignora regras de Primeira Prioridade definidas acima para: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents com uma propor\u00e7\u00e3o de Sementes para Leechers acima de ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents com 0 Leechers ConfigView.section.tracker.sendjavaversionandos=Enviar a vers\u00e3o de Java e o nome do S.O. MagnetPlugin.contextmenu.exporturi=Copiar o Magnet URI para o Clipboard ConfigView.section.plugins.dht=BD Distribu\u00edda dht.info=Esta extens\u00e3o suporta o tracking descentralizado, entre outras coisas, - desactiv\u00e1-la ir\u00e1 reduzir a sua capacidade para transferir dht.enabled=Activa a base de dados distribu\u00edda dht.portdefault=Utilizar a Porta Pr\u00e9-Definida dht.port=Porta UDP para a base de dados dht.execute.command=Comando de Diagn\u00f3stico dht.execute.info=Pressione para executar o comando dht.execute=Correr dht.logging=Activar o rastreamento da actividade ConfigView.section.plugins.dhttracker=Tracker Distribu\u00eddo dhttracker.tracknormalwhenoffline=Apenas faz o track de torrents normais quando o tracker deles est\u00e1 indispon\u00edvel ConfigView.section.file.nativedelete._mac=Usar a Lixeira quando apagar ficheiros ConfigView.section.file.nativedelete._windows=Mover ficheiros apagados para a Lixeira ConfigView.section.logging.generatediagnostics=Gerar ConfigView.section.logging.generatediagnostics.info=Gera informa\u00e7\u00e3o de diagn\u00f3stico e copia para a \u00e1rea de transfer\u00eancia e ficheiro de registo, se configurado ConfigView.section.sharing.privatetorrent=Torrent privado \u2013 apenas aceita liga\u00e7\u00f5es definidas pelo Tracker MainWindow.menu.tools.nattest=&NAT / Teste de Firewall Button.apply=Aplicar Button.close=Fechar window.welcome.title=Bem-vindo ao Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Notas da Vers\u00e3o dht.reseed.label=Normalmente Reseedar a base de dados Distribu\u00edda n\u00e3o \u00e9 necess\u00e1rio.No entanto, se o n\u00famero de contactos for baixo isto pode ser utilizado para reintegra\u00e7\u00e3o.\nDeixar em branco para o bootstrap de pares ligados ou introduza o IP e a porta para explicitamente fazer bootstrap de um par conhecido. dht.reseed.group=Reseedar dht.reseed.ip=Endere\u00e7o IP dht.reseed.port=Porta dht.reseed=Reseedar dht.reseed.info=Re-seedar a base de dados dht.diagnostics.group=Diagn\u00f3sticos DHTView.title.full=Base de Dados Distrubu\u00edda DHTView.title.fullcvs=Base de Dados Distribu\u00edda CVS DHTView.general.title=Geral DHTView.general.uptime=TempodeUp: DHTView.general.users=Utilizadores: DHTView.general.nodes=N\u00f3s: DHTView.general.leaves=A Deixar: DHTView.general.contacts=Contactos: DHTView.general.replacements=Substitutos: DHTView.general.live=Activo: DHTView.general.unknown=Desconhecido: DHTView.general.dying=A morrer: DHTView.transport.title=Detalhes do Transporte DHTView.transport.packets=Pacotes DHTView.transport.received=Recebido DHTView.transport.sent=Enviado DHTView.transport.in=Em : DHTView.transport.out=Fora : DHTView.operations.title=Detalhes da Opera\u00e7\u00e3o DHTView.operations.sent=Enviado DHTView.operations.ok=OK DHTView.operations.failed=Falhou DHTView.operations.received=Recebido DHTView.operations.findNode=Procurar N\u00f3 DHTView.operations.findValue=Procurar Valor DHTView.operations.store=Guardar DHTView.activity.title=Actividade DHTView.activity.status=Estado DHTView.activity.status.true=Em espera DHTView.activity.status.false=Em Curso DHTView.activity.type=Tipo DHTView.activity.type.1=Obter Internamente DHTView.activity.type.2=Obter Externamente DHTView.activity.type.3=Put Interno DHTView.activity.type.4=Put Externo DHTView.activity.target=Alvo DHTView.activity.details=Detalhes DHTView.db.title=Base de dados DHTView.db.keys=Chaves DHTView.db.values=Valores DHTView.db.direct=Directo DHTView.db.indirect=Indirecto DHTView.db.divfreq=Frequ\u00eancia Div. DHTView.db.divsize=Tamanho Div. MainWindow.dht.status.tooltip=Quando a Base de Dados Distribu\u00edda est\u00e1 a correr mostra o n\u00famero estimado de utilizadores actualmente ligados MainWindow.dht.status.disabled=DHT Desactivado MainWindow.dht.status.failed=DHT Falhou MainWindow.dht.status.initializing=DHT a Inicializar MainWindow.dht.status.users=%1 Utilizadores MainWindow.dht.status.unreachable=DHT Bloqueado MainWindow.dht.status.unreachabletooltip=Parece que existe um problema com o mapeamento da porta UDP na Base de Dados Distribu\u00edda (NAT/firewall) MyTorrentsView.menu.setUpSpeed=Configurar Velocidade de Up MyTorrentsView.menu.setDownSpeed=Configurar Velocidade de Down ConfigView.section.tracker.client.showwarnings=Mostrar mensagens de aviso dadas pelos trackers dht.advanced=Activar defini\u00e7\u00f5es avan\u00e7adas dht.advanced.group=Configura\u00e7\u00f5es Avan\u00e7adas dht.advanced.label=Emende estes valores se realmente souber o que est\u00e1 a fazer dht.override.ip=Ultrapassar os endere\u00e7os IP externos ConfigView.section.logging.loggerenable=Activar o registo ConfigView.section.ipfilter.blockbanning=Banir um bloco de 256 endere\u00e7os quando pelo menos outros tantos no bloco foram banidos MyTrackerView.passive=Passivo TableColumn.header.swarm_average_speed=M\u00e9dia de velocidade de Swarm TableColumn.header.swarm_average_speed.info=A m\u00e9dia de velocidades dos pares no swarm TableColumn.header.comment=Coment\u00e1rio TableColumn.header.comment.info=Coment\u00e1rio definido pelo utilizador para transferir TableColumn.header.commenticon=\u00eccone do Coment\u00e1rio TableColumn.header.commenticon.info=Mostra um \u00edcone se a transfer\u00eancia tem um coment\u00e1rio definido pelo utilizador MyTrackerView.category=Categoria MainWindow.menu.file.open.torrentfortracking=Ficheiro Torrent... (Apenas Tracking ) MyTrackerView.date_added=Adicionado ConfigView.section.tracker.portbackup=Portas de Backup (';' separado) ConfigView.label.playfilespeech=Falar quando um ficheiro \u00e9 terminado ConfigView.label.playfilespeech.info=Os Servi\u00e7os de Fala actualmente funcionam melhor em Ingl\u00eas ConfigView.label.playfilefinished=Tocar um som quando um ficheiro \u00e9 terminado ConfigView.label.backupconfigfiles=Guardar ficheiros de recupera\u00e7\u00e3o para prop\u00f3sitos de restauro ConfigView.section.tracker.client.scrapesingleonly=Desactivar a agrega\u00e7\u00e3o per-tracker scrape (pode ajudar com trackers que informam 'URL demasiado comprido' (414) erros) dht.ipfilter.log=Registar viola\u00e7\u00f5es do Filtro IP ConfigView.label.seeding.addForSeedingDLCopyCount=Considerar 'adicionar para seedar' transfer\u00eancias que tenham transferido este n\u00famero de c\u00f3pias ActivityView.legend.limit=R\u00e1cio Limite ActivityView.legend.achieved=R\u00e1cio Alcan\u00e7ado ActivityView.legend.peeraverage=M\u00e9dia ActivityView.legend.swarmaverage=M\u00e9dia de Swarm ActivityView.legend.trimmed=Trimmed (dotted) MyTorrentsView.menu.movemenu=Mover Ficheiros MyTorrentsView.menu.movedata=Mover dados dos Ficheiros... MyTorrentsView.menu.movetorrent=Mover Ficheiro Torrent... MyTorrentsView.menu.movedata.dialog=Escolher nova localiza\u00e7\u00e3o DHTView.operations.data=Dados DHTView.general.reachable=Alcan\u00e7\u00e1vel: ConfigView.label.queue.maxactivetorrentswhenseeding=M\u00e1x apenas quando est\u00e1 a seedar [0:ilimitado] Views.plugins.IRC.title=IRC - Suporte T\u00e9cnico Online Formats.units.alot=Bastante !!! ConfigView.section.ipfilter.persistblocking=Guardar detalhes de IP bloqueados ap\u00f3s re\u00ednicio FilesView.menu.rename=Mudar nome ou mudar o Alvo FilesView.menu.rename_only=Mudar Nome FilesView.menu.retarget=Mudar alvo FilesView.rename.choose.path=Escolha um ficheiro novo ou existente FilesView.rename.choose.path.dir=Escolha uma directoria nova ou existente FilesView.rename.confirm.delete.title=Corfirmar Apagar FilesView.rename.confirm.delete.text=Confirmar elimina\u00e7\u00e3o do ficheiro original '%1' FilesView.rename.filename.title=Mudar o nome do ficheiro FilesView.rename.filename.text=Escolha um novo nome para o ficheiro ConfigView.section.mode=Modo ConfigView.section.mode.title=N\u00edvel do Utilizador ConfigView.section.mode.beginner=Principiante ConfigView.section.mode.beginner.wiki.definitions=Vocabul\u00e1rio BitTorrent ConfigView.section.mode.intermediate=Interm\u00e9dio ConfigView.section.mode.intermediate.wiki.host=Anfitri\u00e3o de Ficheiros ConfigView.section.mode.intermediate.wiki.publish=Publicar ficheiros ConfigView.section.mode.advanced=Avan\u00e7ado ConfigView.section.mode.advanced.wiki.main=P\u00e1gina inicial da Wiki ConfigView.section.mode.beginner.text=Tudo o que necessita para transferir torrents.\nUse este modo se apenas deseja gerir os seus torrents. ConfigView.section.mode.intermediate.text=Acesso \u00e0s fun\u00e7\u00f5es do tracker.\nUtilize este modo se quiser criar o seu pr\u00f3prio tracker e hospedar/publicar os seu ficheiros. ConfigView.section.mode.advanced.text=Acesso \u00e0s configura\u00e7\u00f5es de rede.\nUtilize este modo se sabe o que s\u00e3o o MTU ou o non blocking I/O... Files.column.storagetype=Tipo de Armazenamento Files.column.fileext=Tipo FileItem.storage.compact=Compacto MessageBoxWindow.rememberdecision=Lembrar a minha decis\u00e3o ConfigView.section.interface.cleardecisions=Limpar lembran\u00e7as dos di\u00e1logos de decis\u00f5es \n ConfigView.section.interface.cleardecisionsbutton=Limpar configureWizard.welcome.usermodes=Este tipo de configura\u00e7\u00e3o de determina o n\u00edvel de op\u00e7\u00f5es apresentadas em Ferramentas > Op\u00e7\u00f5es. \u00c9 do seu interesse configur\u00e1-lo correctamente. FilesView.skip.confirm.delete.text=Truncar o ficheiro '%1'para libertar espa\u00e7o? FilesView.rename.failed.title=Renomear/Alterar Destino falhou FilesView.rename.failed.text=A opera\u00e7\u00e3o falhou, provavelmente devido a uma selec\u00e7\u00e3o de destino inv\u00e1lida diagnostics.log_found=O Vuze n\u00e3o encerrou correctamente. Verifique %1para um diagn\u00f3stico do ficheiro de registo e considere report\u00e1-lo \u00e0 equipa do Vuze se for o resultado de um erro da aplica\u00e7\u00e3o. ManagerItem.paused=Em Pausa Utils.link.visit=Por favor visite ConfigView.section.connection.serverport.wiki=Escolha de boas portas ConfigView.section.transfer.speeds.wiki=Boas Configura\u00e7\u00f5es de velocidade installPluginsWizard.installMode.info.text=N\u00e3o necessita de extens\u00f5es para que o Vuze funcione correctamente, elas trazem fun\u00e7\u00f5es complementares por brincadeira,automa\u00e7\u00e3o ou controlo remoto.\nPortanto leia a descri\u00e7\u00e3o de cada extens\u00e3o com cuidado antes de decidir instal\u00e1-la.\nMuitas extens\u00f5es s\u00e3o seguras para experimentar, apenas n\u00e3o sobrecarregue a sua configura\u00e7\u00e3o com extens\u00f5es que n\u00e3o utiliza. Views.plugins.Distributed.DB.title=DB Distribu\u00edda Views.plugins.Distributed.Tracker.title=Tracker Distribu\u00eddo Views.plugins.Plugin.Update.title=Actualiza\u00e7\u00e3o de Extens\u00f5es openUrl.url.info=Suporta http, https, magnet e strings raw hex infohash TableColumn.header.swarm_average_completion=M\u00e9dia de Pares Completos TableColumn.header.swarm_average_completion.info=A m\u00e9dia da percentagem de pares completos no swarm GeneralView.label.swarm_average_completion=M\u00e9dia de Terminados: GeneralView.label.swarm_average_completion.tooltip=A m\u00e9dia da percentagem dos pares completos no swarm MainWindow.nat.status.tooltip.unknown=Estado do Alcan\u00e7e da Firewall/NAT desconhecido (TCP) MainWindow.nat.status.tooltip.ok=Alcan\u00e7\u00e1vel OK (TCP) MainWindow.nat.status.tooltip.probok=O alcan\u00e7e estava OK, no entanto n\u00e3o houve liga\u00e7\u00f5es TCP a chegar MainWindow.nat.status.bad=Bloqueado MainWindow.nat.status.tooltip.bad=Problema de Alcance da Firewall/NAT (TCP). Veja aWiki para ajuda plugin.installer.recommended.plugin=Extens\u00e3o recomendada - por favor reveja e instale se necess\u00e1rio LoggerView.pause=Pausar o Logging LoggerView.clear=&Limpar LoggerView.filter=Filtro LoggerView.filter.uncheckAll=Des-seleccionar Todas as Categorias LoggerView.filter.checkAll=Seleccionar Todas as Categorias LoggerView.loggingDisabled=O Logging n\u00e3o est\u00e1 activo. ConfigView.section.logging.log0type=Informa\u00e7\u00e3o ConfigView.section.logging.log1type=Aviso ConfigView.section.logging.log2type=Erro ConfigView.section.logging.filter=Filtrar quando faz o registo ao ficheiro ConfigView.section.logging.level=N\u00edvel do Registo ConfigView.section.logging.showLogsFor=Mostrar %1 registos para as seguintes categorias: ConfigView.pluginlist.column.loadAtStartup=Iniciar ao Arranque ConfigView.pluginlist.column.type=Tipo ConfigView.pluginlist.column.type.perUser=Por Utilizador ConfigView.pluginlist.column.type.shared=Partilhado ConfigView.pluginlist.column.type.builtIn=Incorporado ConfigView.pluginlist.column.name=Nome ConfigView.pluginlist.column.version=Vers\u00e3o ConfigView.pluginlist.column.directory=Directoria ConfigView.pluginlist.column.isOperational=Operacional? PeersView.BlockView.Avail.Have=Ambos t\u00eam PeersView.BlockView.Avail.NoHave=O Par tem; Voc\u00ea n\u00e3o PeersView.BlockView.NoAvail.Have=Vo\u00e7\u00ea tem; O par n\u00e3o PeersView.BlockView.NoAvail.NoHave=Nenhum tem PeersView.BlockView.Transfer=A transferir PeersView.BlockView.NextRequest=Pr\u00f3ximo Pedido PeersView.BlockView.title=Mapa dos Peda\u00e7os PeersView.BlockView.AvailCount=Contador de Disponibilidade MyTorrentsView.dialog.NumberError.title=N\u00famero Inv\u00e1lido ou N\u00e3o reconhecido MyTorrentsView.dialog.NumberError.text=O n\u00famero que introduziu \u00e9 inv\u00e1lido ou n\u00e3o \u00e9 reconhecido MyTorrentsView.dialog.setSpeed.title=Configurar %1 velocidade # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=introduza um n\u00famero %1 para modificar %2 para: MyTorrentsView.dialog.setNumber.upload=Enviar MyTorrentsView.dialog.setNumber.download=transferir MyTorrentsView.dialog.setNumber.inKbps=em %1 OpenTorrentWindow.torrentLocation=Ficheiros Torrents: OpenTorrentWindow.addFiles.URL=Adicionar &URL OpenTorrentWindow.addFiles.Folder=Adicionar &Pasta OpenTorrentWindow.addFiles.Clipboard=Adicionar desde o Clip&board OpenTorrentWindow.changeDestination=Alterar Destino OpenTorrentWindow.fileList=Ficheiros no torrent: OpenTorrentWindow.torrentTable.name=Nome OpenTorrentWindow.torrentTable.saveLocation=Guardar Localiza\u00e7\u00e3o OpenTorrentWindow.fileTable.fileName=Nome do Ficheiro OpenTorrentWindow.fileTable.size=Tamanho OpenTorrentWindow.fileTable.destinationName=Nome Dest. OpenTorrentWindow.startMode.seeding=A seedar OpenTorrentWindow.fileList.changeDestination=Alterar Destino OpenTorrentWindow.mb.badSize.title=Ficheiro Imcompat\u00edvel OpenTorrentWindow.mb.badSize.text='%1' n\u00e3o \u00e9 '%2' e n\u00e3o pode ser utilizado para seedar OpenTorrentWindow.mb.alreadyExists.text=O %3 j\u00e1 existe e foi adicionado como '%2' OpenTorrentWindow.mb.alreadyExists.title=O Torrent torrent j\u00e1 existe OpenTorrentWindow.mb.openError.title=Erro ao Abrir OpenTorrentWindow.mb.openError.text='%1' n\u00e3o pode ser aberto:\n%2 OpenTorrentWindow.torrent.remove=Remover torrrents da lista OpenTorrentWindow.torrent.options=As seguintes configura\u00e7\u00f5es ser\u00e3o aplicadas aos torrents seleccionados abaixo: OpenTorrentWindow.xOfTotal=(%1 de %2) iconBar.open.tooltip=Abrir Torrent(s) LocaleUtil.column.text=Texto Desconhecido Tracker.tooltip.MultiSupport=Este tracker n\u00e3o suporta Tmultiple hash scrapes por pedido. Tracker.tooltip.NoMultiSupport=Este tracker n\u00e3o suporta multiple hash scrapes por pedido. ConfigView.label.lazybitfield=Usar lazy bitfield (ajuda a seedar em redes que empregam o bloqueamento baseado em bitfield) LoggerView.realtime=Actualizar em tempo real ConfigView.section.file.perf.cache.flushpieces=Escrever os peda\u00e7os completos no disco imediatamente. Isto torna o acesso ao disco mais suave mas pode resultar em mais opera\u00e7\u00f5es de escrita. ConfigView.section.file.writemblimit=pedidos m\u00e1ximos de escrita queued (em %1) ConfigView.section.file.writemblimit.explain=Quando a velocidade de escrita do disco \u00e9 mais baixa do que a velocidade de transfer\u00eancia este par\u00e2metro limita a quantidade de dados que ser\u00e3o queued antes da velocidade da transfer~encia ser diminu\u00edda. ConfigView.section.file.readmblimit=Pedidos m\u00e1ximos de leitura queued (em %1) ConfigView.section.file.readmblimit.explain=Este par\u00e2metro limite quanta mem\u00f3ria ser\u00e1 usada para guardar leituras que est\u00e3o \u00e0 espera de processamento. Button.moveUp=Move para cima Button.moveDown=Move para baixo ConfigView.notAvailableForMode=Esta sec\u00e7\u00e3o est\u00e1 destinada para o modo %1 ou superior. N\u00e3o est\u00e1 disponivel no modo %2. health.explain.error=Existe um erro com esteT torrent. Ver a coluna de estado, ou a dica de ajuda no \u00edcone para o erro. PeersView.piece=Peda\u00e7o PeersView.piece.info=\u00daltimo peda\u00e7o # pedido por este par PiecesView.priority=Prioridade PiecesView.priority.info=a prioridade de finalizar o peda\u00e7o, mas n\u00e3o tome muita aten\u00e7\u00e3o a isto PiecesView.speed=Velocidade PiecesView.speed.info=Os pares lentos s\u00e3o prevenidos de interferir com peda\u00e7os r\u00e1pidos muitas vezes TableColumn.header.AvgAvail.info=Soma dos peda\u00e7os dispon\u00edveis dividido por # peda\u00e7os, dividido por # liga\u00e7\u00f5es TableColumn.header.AvgAvail=M\u00e9dia Disp/peda\u00e7o ConfigView.label.strictfilelocking=For\u00e7ar acesso exclusivo de escrita do ficheiro pelos torrents MyTorrentsView.menu.rescanfile=Verificar Peri\u00f3dicamente os Peda\u00e7os Imcompletos Plugin.extseed.name=Pares Externos Plugin.localtracker.name=Pesquisador de Pares na LAN Plugin.localtracker.info=Pesquisador de Pares na LAN permite v\u00e1rias c\u00f3pias do Vuze por detr\u00e1s de uma firewall e numa rede comum\npara transfererir eficientemente torrents ao activar liga\u00e7\u00f5es directas entre eles Plugin.localtracker.enable=Activar o Pesquisador de Pares na LAN azinstancehandler.alert.portclash=Detectado um clash da porta na LAN: %1 j\u00e1 est\u00e1 em uso por outro utilizador do Vuze seleccione nova(s) porta(s ) aleat\u00f3rias para a escuta de liga\u00e7\u00f5es TCP / UDP a chegar entre %2 e %3]. ConfigView.section.transfer.lan.tooltip=LAN-Configura\u00e7\u00f5es Espec\u00edficas ConfigView.section.transfer.lan.uploadrate=M\u00e1x velocidade de upload da LAN - KB/s [0: ilimitado] ConfigView.section.transfer.lan.uploadrate.tooltip=Liga\u00e7\u00f5es entre pares dentro da mesma LAN interna t\u00eaem um r\u00e1cio de upload limite separado. ConfigView.section.transfer.lan.downloadrate=M\u00e1x velocidade de download da LAN - KB/s [0: ilimitado] ConfigView.section.transfer.lan.downloadrate.tooltip=Liga\u00e7\u00f5es entre pares dentro da mesma LAN interna t\u00eaem um r\u00e1cio de transfer\u00eancia limite separado TorrentOptionsView.title.short=Op\u00e7\u00f5es TorrentOptionsView.title.full=Op\u00e7\u00f5es TorrentOptionsView.param.max.peers=N\u00famero m\u00e1ximo de liga\u00e7\u00f5es [0: ilimitadas] ConfigView.section.connection.encryption.require_encrypted_transport=Requerer transporte cifrado ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=For\u00e7ar o uso de liga\u00e7\u00f5es cifradas com outros pares. ConfigView.section.connection.encryption.min_encryption_level=N\u00edvel m\u00ednimo da cifra ConfigView.section.connection.encryption.min_encryption_level.tooltip=Plano - apenas aperto de m\u00e3o\nRC4 - full stream\nUma Cifra mais alta requer mais CPU. Peers.column.Encryption=Encripta\u00e7\u00e3o Peers.column.Encryption.info=N\u00edvel de Encripta\u00e7\u00e3o em uso ConfigView.section.connection.encryption.encrypt.info=Se a cifra estiver activa n\u00e3o poder\u00e1 ligar-se a clientes incompat\u00edveis a n\u00e3o ser que configure as op\u00e7\u00f5es de fallback ConfigView.section.connection.encryption.encrypt.info.link=Para mais detalhes, visite MainWindow.sr.status.tooltip.ok=R\u00e1cio de Partilha %1 OK MainWindow.sr.status.tooltip.poor=R\u00e1cio de Partilha %1 pobre: < 0.9 MainWindow.sr.status.tooltip.bad=R\u00e1cio de Partilha %1 Mau: < 0.5 ConfigView.section.style.status=\u00c1rea de Estado: ConfigView.section.style.status.show_sr=R\u00e1cio de Partilha ConfigView.section.style.status.show_nat=Estado da NAT ConfigView.section.style.status.show_ddb=Estado da DDB ConfigView.section.style.status.show_ipf=Estado do IPFilter ConfigView.section.connection.encryption.encrypt.group=Cifra do Transporte/Obfuscation ConfigView.section.connection.encryption.encrypt.fallback_info=Activar ambas as op\u00e7\u00f5es de fallback vai permitir liga\u00e7\u00f5es a clientes incompat\u00edveis MAS ir\u00e1 resultar em liga\u00e7\u00f5es n\u00e3o cifradas ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Permitir liga\u00e7\u00f5es de sa\u00edda n\u00e3o cifradas se a liga\u00e7\u00e3o cifrada falhar ConfigView.section.connection.encryption.encrypt.fallback_incoming=Permitir liga\u00e7\u00f5es a chegar n\u00e3o-cifradas ConfigView.section.connection.encryption=Transporte Cifrado upnp.selectedinterfaces=Interfaces seleccionados (';' seperados, ex. eth0;eth1) [em branco: todos] ConfigView.section.style.defaultSortOrder=Ordenar por pr\u00e9-defini\u00e7\u00e3o ConfigView.section.style.defaultSortOrder.desc=Descendente ConfigView.section.style.defaultSortOrder.asc=Ascendente ConfigView.section.style.defaultSortOrder.flip=Oposto da ordem anterior LoggerView.autoscroll=Deslocamento-Auto Button.selectAll=Seleccionar Tudo Button.markSelected=Marcar Selecc\u00e3o Button.unmarkSelected=Desmarcar Selec\u00e7\u00e3o plugins.basicview.config=Configurar TorrentOptionsView.param.max.uploads=N\u00famero m\u00e1ximo de slots de upload [m\u00ednimo: 2] MyTorrentsView.dialog.setPosition.title=Configurar Posi\u00e7\u00e3o MyTorrentsView.dialog.setPosition.text=Introduza a posi\u00e7\u00e3o para configurar os torrents seleccionados: MyTorrentsView.menu.reposition.manual=Repor.. ConfigView.section.connection.advanced.info.link=Para mais detalhes, visite ConfigView.section.connection.advanced.socket.group=Op\u00e7\u00f5es Socket ConfigView.section.connection.advanced.bind_port=Bind \u00e0 porta local [0: desactivado] ConfigView.section.connection.advanced.bind_port.tooltip=As liga\u00e7\u00f5es de sa\u00edda do socket ser\u00e3o dadas localmente \u00e0 porta.\nActivar esta fun\u00e7\u00e3o pode ajudar com a instabilidade de NAT no router. ConfigView.section.proxy.group.tracker=Comunica\u00e7\u00f5es do Tracker ConfigView.section.proxy.group.peer=Comunica\u00e7\u00f5es do Par Pieces.column.Requested=Pedido Pieces.column.Requested.info=Mostra se mais pedidos ao peda\u00e7o podem ser feitos ou n\u00e3o (*) ConfigView.label.maxuploadsseeding=Alternar Pr\u00e9-defini\u00e7\u00e3o ao seedar MyTorrentsView.filter=Filtro: popup.error.hideall=Esconder tudo ConfigView.section.style.dataStatsOnly=Mostrar apenas estat\u00edsticas dos dados(esconder estat\u00edsticas do protocolo) ConfigView.section.style.separateProtDataStats=Mostra estat\u00edsticas separadas para dados e protocolos como 'dados (protocolo)' MyTorrentsView.dialog.setFilter.title=Modificar Filtro MyTorrentsView.dialog.setFilter.text=A sec\u00e7\u00e3o %1 ser\u00e1 filtrada pelo texto que especificou em baixo. utilize o s\u00edmbolo | (pipe) para filtrar frases m\u00faltiplas. MyTorrentsView.filter.tooltip=Ctrl+X para alternar entre RegEx e o modo de pesquisa normal.\nUtilize o s\u00edmbolo | (pipe) para filtrar em frases m\u00faltiplas. MyTorrentsView.clearFilter.tooltip=Limpar Filtros MyTorrentsView.menu.filter=Lista de Filtros... ConfigView.section.file.resume.recheck.all=Num re\u00ednicio ap\u00f3s um crash verificar a totalidade do ficheiro por peda\u00e7os completos (De outra maneira apenas peda\u00e7os activos por \u00faltimo ser\u00e3o verificados) ConfigureWizard.language.choose=Escolha um idioma da lista em baixo: popup.closing.in=A Fechar a janela em %1 segundos popup.more.waiting=%1 maisnmensagen(s).. # > 2402 popup.download.finished="%1"terminou a transfer\u00eancia. popup.file.finished="%1" terminou a transf\u00earencia. ConfigView.auto=Autom\u00e1tico Plugin.localtracker.autoadd.info=Adicicionar Autom\u00e1ticamente aos pares locais [';' endere\u00e7os separados, ex. 1.2.3.4] Plugin.localtracker.autoadd=Pares Explicitos Plugin.localtracker.networks.info=Cosiderar as seguintes redes como locais [';' redes separadas, ex. 145.227.*.*] Plugin.localtracker.networks=Redes Locais MainWindow.menu.view.plugins.logViews=Vistas do Registo SpeedView.stats.autospeed=Velocidade Autom\u00e1tica de Upload SpeedView.stats.autospeed.disabled=Esta op\u00e7\u00e3o est\u00e1 ou desactivada (necessita do DHT) ou n\u00e3o est\u00e1 em uso (velocidade de upload seleccionada manualmente) SpeedView.stats.maxPing=Ping M\u00e1x: SpeedView.stats.currentPing=Ping Actual: SpeedView.stats.maxUp=Velocidade M\u00e1x Up : ConfigView.pluginlist.unloadSelected=Descarregar Seleccionado ConfigView.pluginlist.scan=Pesquisar por novas Extens\u00f5es ConfigView.section.transfer.autospeed=Velocidade-Auto ConfigView.section.transfer.autospeed.tooltip=Configura\u00e7\u00f5es espec\u00edficas da velocidade Auto ConfigView.section.transfer.autospeed.info=A velocidade-Auto ajusta autom\u00e1ticamente a velocidade limite de upload para evitar sobrecarregar a liga\u00e7\u00e3o de rede.\n\nEstes limites apenas ser\u00e3o aplicados quando a velocidade autom\u00e1tica de upload est\u00e1 activada e tamb\u00e9m requer que a base de dados distribu\u00edda esteja tamb\u00e9m activa.\n ConfigView.section.transfer.autospeed.minupload=%1 velocidade m\u00ednima de upload ConfigView.section.transfer.autospeed.minupload.tooltip=A velocidade de upload normalmente n\u00e3o ser\u00e1 diminuida abaixo deste limite ConfigView.section.transfer.autospeed.maxupload=%1 velocidade m\u00e1xima de upload [0: ilimitado] ConfigView.section.transfer.autospeed.maxupload.tooltip=A velocidade de upload n\u00e3o ser\u00e1 aumentada acima deste limite ConfigView.section.transfer.autospeed.chokeping=Choking ping time [milisegundos] ConfigView.section.transfer.autospeed.chokeping.tooltip=Ping timesem em excesso deste valor ser\u00e1 considerado como um indicador de satura\u00e7\u00e3o da rede ConfigView.section.transfer.autospeed.enableauto=Activar quando est\u00e1 a transferir e a seedar ConfigView.section.transfer.autospeed.enableautoseeding=Activar quando est\u00e1 apenas a seedar ConfigView.pluginlist.column.unloadable=N\u00e3o \u00e9 poss\u00edvel descarregar ConfigView.section.transfer.lan.enable=Activar limites de velocidade separados para liga\u00e7\u00f5es dentro da LAN Plugin.localtracker.wellknownlocals=Incluir autom\u00e1ticamente loopback/link/site redes locais (192.168 etc) TableColumn.header.filesdone=Ficheiros Feito TableColumn.header.filesdone.info=Ficheiros feito/Ficheiros totais *ou* Ficheiros feitos Non-skipped (Ficheiros feito)/Ficheiros totais non-skipped (Ficheiros totais) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled=< tracking descentralizado desactivado> MagnetPlugin.decentral_backup_disabled=< backup descentralizado desactivado> MagnetPlugin.report.waiting_ddb=\u00e0 espera pela inicializa\u00e7\u00e3o da DDB... MagnetPlugin.report.searching=a procurar... MagnetPlugin.report.found=encontrado %1 MagnetPlugin.report.alive=%1 est\u00e1 viva MagnetPlugin.report.dead=%1 est\u00e1 morto MagnetPlugin.report.tunnel=tunnelling para %1 MagnetPlugin.report.downloading=A transferir de %1 MagnetPlugin.report.error=erro %1 MagnetURLHandler.report.no_sources=nenhuma fonte encontrada para o torrent MagnetURLHandler.report.torrent_size=tamanho do torrent: %1 MagnetURLHandler.report.percent=completado: %1% MagnetURLHandler.report.error=erro %1 DHTTransport.report.request_all=a pedir transfer\u00eancia total desde %1 DHTTransport.report.received_bit=recebido %1 para %2 de %3 DHTTransport.report.complete=terminado DHTTransport.report.timeout=expirou, nenhuma resposta desde %1 DHTTransport.report.rerequest_all=re-pedir a transfer\u00eancia inteira de %1 DHTTransport.report.rerequest_bit=re-pedir %1 para %2 de %3 DHTTransport.report.timeout_some=expirou, %1 pacotes recebidos de %2 mas imcompletos DHTTransport.report.sending=a enviar dados DHTTransport.report.resending=reenviar dados DHTTransport.report.send_complete=envio terminado DHTTransport.report.send_timeout=o envio expirou ConfigView.section.transfer.autospeed.enabledebug=Registar informa\u00e7\u00e3o de debug TableColumn.header.date_added=Data adicionada TableColumn.header.date_added.info=Data em que o torrent foi adicionado ConfigView.section.file.hashchecking.smallestfirst=Re-verificar primeiro as transfer\u00eancias mais pequenas platform.win32.baddll.info=O Vuze detectou a presen\u00e7a de '%1'. Isto faz parte do '%2' que \u00e9 conhecido como causador de problemas s\u00e9rios como crashes de aplica\u00e7\u00f5es e elevado uso da CPU.Se encontrou isto ent\u00e3o por favor desinstale o software ou configure-o para n\u00e3o afectar o Azureus. platform.win32.baddll.niphk=Norman Anti-V\u00edrus platform.win32.baddll.nvappfilter=Firewall NVidia platform.win32.baddll.netdog=Firewall Pessoal Armor2net platform.win32.baddll.vlsp=Firewall Venturi platform.win32.baddll.sarah=FRITZ! Aplica\u00e7\u00e3o de Layer da Firewall platform.win32.baddll.MxAVLsp=Utilit\u00e1rios VCom Fix-It platform.win32.baddll.mclsp=Servi\u00e7o de Privacidade McAfee platform.win32.baddll.radhslib=Filtro da Internet Naomi (Radiant) platform.win32.baddll.winsflt=Filtro de conte\u00fado da Internet PureSight upnp.ignorebaddevices=Ignorar dispositivos que falham em responder correctamnte upnp.ignorebaddevices.info=Dispositivos ignorados actualmente: %1 upnp.ignorebaddevices.reset=Reinicializar a lista dos aparelhos ignorados upnp.ignorebaddevices.reset.action=Reinicializar upnp.ignorebaddevices.alert=O dispositivo UPnP na localiza\u00e7\u00e3o %1 est\u00e1 a ser ignorado devido a falhas repetidas. Veja a configura\u00e7\u00e3o do plugin para op\u00e7\u00f5es acerca desta ac\u00e7\u00e3o. TorrentOptionsView.param.max.uploads.when.busy=velocidade max de upload quando alcan\u00e7ado o limite global de upload - KB/s [0: desactivado] UpdateMonitor.messagebox.verification.failed.title=A Verifica\u00e7\u00e3o da Instala\u00e7\u00e3o falhou UpdateMonitor.messagebox.verification.failed.text=A Verifica\u00e7\u00e3o de '%1' falhou: %2 UpdateMonitor.messagebox.accept.unverified.title=Aceitar Instala\u00e7\u00e3o N\u00e3o verificada UpdateMonitor.messagebox.accept.unverified.text='%1' n\u00e3o p\u00f4de ser verificada como uma extens\u00e3o oficial do Azureus.\nSe for o caso N\u00c3O deve continuar.\nContinuar com a instala\u00e7\u00e3o? FileView.BlockView.title=Peda\u00e7os do Ficheiro FileView.BlockView.Done=Feito FileView.BlockView.Skipped=Ignorado FileView.BlockView.Active=Activo FileView.BlockView.Outstanding=Not\u00e1vel ConfigView.label.tcplistenport=Porta de escuta de TCP a receber ConfigView.label.udplistenport=Porta de escuta UDP upnp.portchange.alert=As portas seguintes foram alteradas para evitar problemas do aparelho UPnP : %1 [porta antiga=%2] %3 [porta antiga=%4] ConfigView.section.proxy.username.info=Se o servidor proxy pede autentica\u00e7\u00e3o mesmo quando n\u00e3o est\u00e1 nenhuma definida, utilize o string "" como o(s)Nomes(s) de Utilizadore(s) ConfigView.label.maxuploadswhenbusymin=Velocidade Max de upload do torrent quando o temporizador est\u00e1 ocupado [seg] MainWindow.menu.help.debug=Gerar Info de Debug DownloadManager.error.badsize=Tamanho Incorrecto natpmp.info=NAT-PMP \u00e9 o nome alternativo dado pela Apple ao UPnP e \u00e9 suportado por esta\u00e7\u00f5es recentes em Aeroportos\nNote que actualmente o UPnP tem de estar activo para activar o NAT-PMP pois o dispositivo de NAT-PMP \u00e9 tratado como um tipo de dispositivo especial de UPnP natpmp.enable=Activado (note que tem de estar activado na configura\u00e7\u00e3o do aeroporto para funcionar) ConfigView.section.tracker.host.addurls=Certificar que o URL deste tracker est\u00e1 presente nos torrents ConfigView.filter=escrever o texto do filtro ConfigView.section.files.move=Mover foi completado ConfigView.section.file.defaultdir.section=Op\u00e7\u00f5es Pr\u00e9-definidas da Directoria ConfigView.section.file.defaultdir.auto=Transferir autom\u00e1ticamente para a directoria pr\u00e9-definida (No Prompt) ConfigView.section.file.defaultdir.bestguess=Utilizar a melhor escolha ao escolher a directoria onde guardar ConfigView.section.file.defaultdir.ask=Directoria pr\u00e9.Definida: ConfigView.section.file.defaultdir.lastused=Actualiza\u00e7\u00e3o da directoria pr\u00e9-definida para a \u00faltima localiza\u00e7\u00e3o guardada para ConfigView.section.torrent.decoding=Descodifica\u00e7\u00e3o dos Conjuntos de Caracteres ConfigView.section.logging.udptransport=Activar o seguimento do transporte verbose UDP Tracker.announce.ignorePeerSeed=Ignorar cont. Par/Seed . %1 ConfigView.section.connection.encryption.use_crypto_port=Use a extens\u00e3o 'cryptoport' do tracker para prevenir tentativas de liga\u00e7\u00f5es a receber planas. Alguns trackers n\u00e3o aceitam isto e falham com error tipo "porta inv\u00e1lida" ou "Argumento Ilegal" TorrentOptionsView.param.reset.to.default=Configurar op\u00e7\u00f5es de volta aos valores pr\u00e9-definidos TorrentOptionsView.param.reset.button=Reinicializar natpmp.routeraddress=Endere\u00e7o da Esta\u00e7\u00e3o [em branco: auto] ConfigView.section.style.disableAlertSliding=Desactivar anima\u00e7\u00e3o/no estilo do topo para mensagens de alerta ConfigView.section.transfer.autospeed.maxinc=%1 aumento m\u00e1ximo por ciclo ConfigView.section.transfer.autospeed.maxdec=%1 diminui\u00e7\u00e3o m\u00e1xima por ciclo ConfigView.section.transfer.autospeed.enabledownadj=Activar o ajuste da velocidade de transfer\u00eancia ConfigView.section.transfer.autospeed.downadjratio=transferir: R\u00e1cio da velocidade de Upload (ex. 2.0 ->o limite da velocidade de transfer\u00eancia \u00e9 o dobro do limite de upload) ConfigView.section.transfer.autospeed.latencyfactor=Factor usado para ligar as mudan\u00e7as de lat\u00eancia \u00e0s mudan\u00e7as de velocidade (n\u00fameros elevados diminuem a sensibilidade) ConfigView.section.transfer.autospeed.reset=Reiniciar valores avan\u00e7ados ConfigView.section.transfer.autospeed.reset.button=Reinicializar PeerColumn.activationCount=Pares a tentarem ligar-se: %1 TableColumn.header.timesincedownload.info=O tempo que passou desde que foram transferidos dados para o torrent TableColumn.header.timesinceupload.info=O tempo que passou desde que foram carregados dados para o torrent PeersView.incomingreqcount=Em Reqs PeersView.incomingreqcount.info=Conta os pedidos recebidos feitos pelo par PeersView.outgoingreqcount=Reqs de sa\u00edd PeersView.outgoingreqcount.info=Contar os pedidos de sa\u00edda feitos ao peda\u00e7o upnp.mapping.trackerclientudp=Porta Cliente UDP do Tracker upnp.mapping.dhtudp=Base de Dados Distribu\u00edda ConfigView.section.connection.nondata.udp.same=Utilizar a mesma porta UDP para a Base de dados Distribu\u00eddae para o Tracker UDP ConfigView.section.connection.tcp.enable=Activar TCP ConfigView.section.connection.udp.enable=Activar UDP ConfigView.section.style.showiconbar=Mostrar barra de ferramentas MainWindow.menu.view.iconbar=Barra de Ferramentas MyTorrentsView.menu.rename=Mudar Nome MyTorrentsView.menu.rename.displayed=Mudar o Nome a Mostrar MyTorrentsView.menu.rename.save_path=Mudar o Caminho Guardado MyTorrentsView.menu.rename.displayed.enter.title=Mudar o Nome Mostrado MyTorrentsView.menu.rename.displayed.enter.message=Introduza um novo nome a mostrar para esta transfer\u00eancia\nSe nenhum texto for introduzido,o nome original ser\u00e1 usado MyTorrentsView.menu.edit_comment=Editar Coment\u00e1rio MyTorrentsView.menu.edit_comment.enter.title=Editar Coment\u00e1rio MyTorrentsView.menu.edit_comment.enter.message=Escreva um coment\u00e1rio para esta transfer\u00eancia. UIDebugGenerator.messageask.title=Gerador de Debug UIDebugGenerator.messageask.text=Por favor d\u00ea uma descri\u00e7\u00e3o do bug que est\u00e1 a reportar UIDebugGenerator.complete.title=Debug Generation Terminada UIDebugGenerator.complete.text=Por favor envie o ficheiro '%1'.\n\nClique em Ok para abrir uma janela para este ficheiro. ConfigView.section.style.showProgramIcon=Mostrar o \u00edcone do programa na coluna nome ConfigView.section.style.showProgramIcon.tooltip=Ver pode necessitar de uma reabertura para que as altera\u00e7\u00f5es tomem efeito swt.alert.cant.update=Livraria SWT carregada de"%3" n\u00e3o pode ser actualizada autom\u00e1aticamente da vers\u00e3o %1 to %2 (tem de ser carregada desde "%4"). Por favor veja o wiki para detalhes. authenticator.savepassword=Lembrar a minha Senha ConfigView.section.security.clearpasswords=Reinicia rsenhas guardadas ConfigView.section.security.clearpasswords.button=Reinicializar Content.alert.notuploaded.title=Upload N\u00e3o Terminado Content.alert.notuploaded.text=O Upload de '%1' n\u00e3o est\u00e1 completo. Se %2 j\u00e1, as pessoas n\u00e3o poder\u00e3o transferir completamente o seu trabalho.\n\nTem a certeza que deseja %2? Content.alert.notuploaded.multi.title=Uploads N\u00e3o Terminados Content.alert.notuploaded.multi.text=%1 do seu conte\u00fado publicado n\u00e3o doi completamente seedado. Se vo\u00e7\u00ea %2 j\u00e1, as pessoas n\u00e3o poder\u00e3o transferir completamente o seu trabalho publicado. tem a certeza que deseja %2?\n\nConte\u00fado n\u00e3o seedado completamente:\n%3 Content.alert.notuploaded.stop=parar Content.alert.notuploaded.quit=sair do Vuze TorrentInfoView.torrent.encoding=Codifica\u00e7\u00e3o do Torrent TorrentInfoView.columns=Colunas da vista dos 'Meus Torrents' progress.window.title=Opera\u00e7\u00e3o em Curso progress.window.msg.filemove=Por favor aguarde enquanto mover/renomear o ficheiro termina ConfigView.label.popup.timestamp=Adicionar marca\u00e7\u00f5es hor\u00e1rias aos alertas de pop-up ConfigView.label.popup.autohide=Esconder autom\u00e1ticamente os alertas de n\u00e3o-erro ap\u00f3s x segundos (defenir como 0 para desactivar o esconder auto) ConfigView.label.please.visit.here=Por favor para mais detalhes visite ConfigView.section.ipfilter.enable.descriptionCache=Guardar descri\u00e7\u00f5es IP num ficheiro scratch ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Quando desactivadas, as descri\u00e7\u00f5es n\u00e3o ser\u00e3o lembradas OpenTorrentWindow.filesInfo=%1 de %2 ser\u00e3o transferidos. ConfigView.label.openmytorrents=Abrir 'Meus Torrents' ao iniciar ConfigView.section.style.DNDalwaysInIncomplete=Mostrar sempre torrents com 'N\u00e3o Transferir' ficheiros na Sec\u00e7\u00e3o Imcompletos dos Meus Torrents OpenTorrentWindow.mb.noGlobalDestDir.title=Directoria de Destino n\u00e3o encontrada OpenTorrentWindow.mb.noGlobalDestDir.text=A directoria de destino '%1' n\u00e3o existe ou \u00e9 inv\u00e1lida OpenTorrentWindow.mb.noDestDir.title=Directoria de Destino n\u00e3o encontrada OpenTorrentWindow.mb.noDestDir.text=O direct\u00f3rio de destino '%1' para o torrent '%2' n\u00e3o existe ou \u00e9 inv\u00e1lido. OpenTorrentWindow.mb.notValid.title=Abrir Torrent OpenTorrentWindow.mb.notValid.text=N\u00e3o foi poss\u00edvel abrir o torrent '%1'. Se estiver a abrir em modo seeding , verifique que os ficheiros do torrent existem OpenTorrentWindow.mb.notTorrent.title=Abrir Torrent OpenTorrentWindow.mb.notTorrent.text=N\u00e3o foi poss\u00edvel abrir '%1'. Parece que n\u00e3o \u00e9 um ficheiro .torrent.\n\nAlguns dos dados recebidos:\n%2 ConfigView.label.pause.downloads.on.exit=Pausar transfer\u00eancias ao sair ConfigView.label.resume.downloads.on.start=Reinicia transfer\u00eancias em pausa ao iniciar ap\u00f3s a inicializa\u00e7\u00e3o completar UIDebugGenerator.message.cancel.title=Foi Cancelada a Info de Debug UIDebugGenerator.message.cancel.text=N\u00e3o escreveu uma descri\u00e7\u00e3o do bug que est\u00e1 a reportar. O seu bug pode ser \u00f3bvio para si, mas sem uma descri\u00e7\u00e3o, apenas poderemos tentar adivinhar qual o seu problema.\n\nFoi Cancelada o Informa\u00e7\u00e3o de Debug ConfigView.section.connection.group.http.info=Suporte para seeding HTTP. ConfigView.section.connection.http.enable=Activar ConfigView.section.connection.http.port=N\u00famero da porta a chegar ConfigView.section.connection.http.portoverride=Porta do Tracker HTTP [0: nenhum] window.update.noupdates.title=Verificar resultados da actualiza\u00e7\u00e3o window.update.noupdates.text=N\u00e3o existem novas actualiza\u00e7\u00f5es dispon\u00edveis para si.\n\nParab\u00e9ns! ConfigView.label.mindownloads=Min de Transfer\u00eancias simult\u00e2neas UI.cannot_submit_blank_text=Tem de introduzir um valor crypto.alert.as.warning=A rede '%1' \u00e9 conhecida por impor traffic shaping para reduzir a performance de transfer\u00eancia. O Transportecifrado foi ligado autom\u00e1ticamente -pode ser desligado/modificado via par\u00e2metros de configura\u00e7\u00e3o. ConfigView.section.interface.alerts=Alertas ConfigView.label.popupdownloadadded=Pop-up um alerta quando uma transfer\u00eancia \u00e9 adicionada popup.download.added="%1" foi adicionado \u00e1 sua lista de transfer\u00eancias. MessageBoxWindow.nomoreprompting=N\u00e3o me avisar de novo TorrentOptionsView.param.max.seeds=N\u00famero de liga\u00e7\u00f5es m\u00e1ximas so seedar [0: limite da liga\u00e7\u00e3o] TorrentOptionsView.param.alternative.value.enable=Alternar valor quando est\u00e1 a seedar ConfigView.section.proxy.check.on.start=Verificar o estado do Proxy ao in\u00edcio TransferStatsView.legend.pingaverage=M\u00e9dia TransferStatsView.legend.ping1=Destino 1 TransferStatsView.legend.ping2=Destino 2 TransferStatsView.legend.ping3=Destino 3 ConfigView.section.interface.enabletray._mac=Activar o \u00edcone da barra de estado [\u00e9 necess\u00e1rio reiniciar] ConfigView.label.closetotray._mac=Fecha o \u00edcone de minimizar na barra de estado ConfigView.label.minimizetotray._mac=Minimizar minimiza para um \u00eccone na barra de estado OpenTorrentWindow.mb.existingFiles.title=O(s) Ficheiro(s) j\u00e1 existe(m)! OpenTorrentWindow.mb.existingFiles.text=Alguns dos ficheiros j\u00e1 existem na pasta de destino que especificou:\n\n%\u005c\nSe continuar, o Vuze vai verificar os ficheiros e se necess\u00e1rio ir\u00e1 sobrescreve-los. splash.unloadingTorrents=A descarregar Torrents splash.unloadingTorrent=A descarregar Torrent ConfigView.section.file.defaultdir.autorename=Mudar o nome ao torrent se os dados do ficheiro parecerem diferentes ConfigView.section.file.defaultdir.autorename.tooltip=Isto previne que um torrent escreva por cima dos ficheiros de outro torrent quando os nomes dos ficheiros s\u00e3o iguais alert.raised.at.close=(Mensagem sobre o encerramento anterior do Vuze) # Used for peers which we can't determine. PeerSocket.unknown=Desconhecido ConfigView.label.announceport=Sobrepor porta de an\u00fancio do tracker iconBar.queue.tooltip=Por Em Fila MainWindow.menu.help.faq=&FAQ MainWindow.menu.help.donate=Fazer um Donativo (2\u20ac,5\u20ac,...) azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_no_NO.properties0000644000175000017500000045163211232522032026113 0ustar adrianadrian################################################################################ # # # Translated by Leif Lislegrd # # Please email me for corrections: lento81 at users sourceforge net # # Encoding: utf-8 # ################################################################################ #!Changelog text in welcome window #file can be a URL or a path in the jar #window.welcome.file=/changelog.txt MainWindow.menu.file.open.torrent=.torrent fil Main.parameter.usage=Bruk: java org.gudy.azureus2.cl.Main [Parameter] "din.torrent" "sti\\for\\lagring" Main.parameter.maxUploads=maks antall samtidige opplastinger Main.parameter.maxSpeed=maks opplastingshastighet i bytes/sek MainWindow.menu.file=&Fil MainWindow.menu.file.open=&pne MainWindow.menu.file.create=&Opprett torrent MainWindow.menu.file.create.keybinding=Meta+O MainWindow.menu.file.create.fromfile=Fra &fil MainWindow.menu.file.create.fromdir=Fra &mappe MainWindow.menu.file.export=&Eksporter en torrent... MainWindow.menu.file.import=&Importer en torrent... MainWindow.menu.file.closetab=Lukk &fane MainWindow.menu.file.closetab.keybinding=Meta+F MainWindow.menu.file.closewindow=Lukk &vindu MainWindow.menu.file.closewindow.keybinding=Meta+Shift+V MainWindow.menu.file.exit=&Avslutt MainWindow.dialog.choose.file=Velg torrent-fil MainWindow.menu.file.folder=&Mappe MainWindow.dialog.choose.folder=Velg mappen som inneholder torrent-filene MainWindow.menu.view=&Vis MainWindow.menu.view.show=Vis MainWindow.menu.view.mytorrents=&Mine torrenter MainWindow.menu.view.open_global_transfer_bar=Samlet overfringslinje MainWindow.menu.view.configuration=&Konfigurasjon MainWindow.menu.view.configuration.keybinding=Meta+K MainWindow.menu.view.console=K&onsoll MainWindow.menu.view.irc=&IRC MainWindow.menu.view.allpeers=Alle kilder MainWindow.menu.closealldetails=Lukk alle &detaljfaner MainWindow.menu.closealldownloadbars=Lukk alle &statuslinjer MainWindow.menu.language=&Sprk ConfigView.section.language=Sprk MainWindow.menu.window=&Vindu MainWindow.menu.window.minimize=&Minimer MainWindow.menu.window.zoom=Forstrr MainWindow.menu.window.alltofront=Plasser alt i &front MainWindow.menu.help=&Hjelp MainWindow.menu.help.about=&Om Vuze #MainWindow.menu.torrent=T&orrent MainWindow.about.title=Om MainWindow.about.section.developers=Utviklere MainWindow.about.section.translators=Oversettere MainWindow.about.section.system=Ditt system MainWindow.about.section.internet=Internett MainWindow.about.internet.homepage=Hjemmeside for Vuze MainWindow.about.internet.sourceforge=SourceForge-prosjektside MainWindow.about.internet.sourceforgedownloads=SourceForge-nedlasting MainWindow.about.internet.bugreports=Feilrapporter MainWindow.about.internet.forumdiscussion=Generelt fora MainWindow.dialog.choose.savepath=Velg sti for lagring MainWindow.dialog.choose.savepath_forallfiles=Velg sti for ALLE filer MainWindow.status.latestversion=Siste MainWindow.status.latestversion.clickupdate=Klikk for oppdatere MainWindow.status.unknown=ukjent MainWindow.status.checking=kontrollerer MyTorrentsView.mytorrents=Mine torrenter TableColumn.header.name=Navn TableColumn.header.size=Strrelse TableColumn.header.done=Ferdig TableColumn.header.done.info=Andel ferdig av gjeldende oppgave (%) TableColumn.header.status.info=Hvilken status torrenten har TableColumn.header.seeds.info=Tilkoblet # sendere (# sendere totalt) TableColumn.header.peers=Mottakere TableColumn.header.peers.info=Tilkoblet # mottakere (# mottakere totalt) TableColumn.header.downspeed=Nedlastingshastighet TableColumn.header.upspeed=Opplastingshastighet TableColumn.header.eta=Gjenstende tid TableColumn.header.tracker=Tracker TableColumn.header.tracker.info=Tracker status TableColumn.header.trackernextaccess=Neste Tracker aksess TableColumn.header.trackernextaccess.info=Neste Tracker aksess skjer TableColumn.header.priority=Prioritet TableColumn.header.priority.info=Bestemmer bndbredden torrenten har for opplasting TableColumn.header.seeds.fullcopycalc=%2 komplette kopier antatt for %1 kilder MyTorrentsView.menu.showdetails=Vis &detaljfane MyTorrentsView.menu.showdownloadbar=Vis statuslinje MyTorrentsView.menu.open=pne MyTorrentsView.menu.setpriority=Sett prioritet MyTorrentsView.menu.setpriority.high=Hy MyTorrentsView.menu.setpriority.low=Lav MyTorrentsView.menu.start=Start MyTorrentsView.menu.stop=Stopp MyTorrentsView.menu.remove=Fjern MyTorrentsView.menu.changeTracker=Skift tracker-URL TrayWindow.menu.exit=Avslutt TrayWindow.menu.show=Vis Vuze SystemTray.menu.exit=Avslutt SystemTray.menu.closealldownloadbars=Lukk alle statuslinjer SystemTray.menu.open_global_transfer_bar=Vis samlet overfringslinje SystemTray.menu.show=Vis Vuze PeersView.ip.info=IP-adresse til kilde PeersView.port.info=Port i bruk PeersView.T.info=L (local): du initierte forbindelsen, R (remote): Forbindelse initiert av andre. PeersView.T.L.tooltip=Du opprettet forbindelsen PeersView.T.R.tooltip=Kilen opprettet forbindelsen PeersView.I1=I (interessert i kilden) PeersView.I1.info=Er du interesser i hva den andre deleren har? PeersView.C1=C (strupet av deler) PeersView.C1.info=Nedlastingen er stoppet av andre PeersView.pieces=Bruddstykker PeersView.downloadspeed=Nedlastingshastighet PeersView.download=Nedlasting PeersView.I2=I (kilden er interessert) PeersView.I2.info=Er den andre interessert i hva du har? PeersView.C2=C (struping av andre) PeersView.C2.info=Nr du vil forhindre andre laste ned PeersView.uploadspeed=Opplastingshastighet PeersView.uploadspeed.info=Din opplastingshastighet til mottaker PeersView.upload=Opplasting PeersView.upload.info=Samlet opplastingshastiget til kilde. PeersView.statup=Opplastings-statistikk PeersView.statup.info=Forventet opplastings-hastighet PeersView.S.info=Irettesettelse: En kilde kan manuelt eller automatisk bli "irettesatt" (ved for sakte opplastings-hastighet ifra kilde) PeersView.downloadspeedoverall=Samlet nedlastingshastighet PeersView.optunchoke=Optimistisk de-struping PeersView.client=Klient PeersView.client.info=Navn p BitTorrent-klient til kilde PeersView.menu.snubbed=Strup PeersView.title.short=Detaljer PeersView.title.full=Detaljer AllPeersView.title.full=Alle kilder ConfigView.section.files=Filer ConfigView.label.usefastresume=Bruk hurtig fortsettelses-modus ConfigView.label.incrementalfile=Bruk inkrementell filopprettelse (ndvendig ved bruk av FAT32 og Linux) ConfigView.label.defaultsavepath=Standard lagringssti ConfigView.button.browse=&Utforsk... ConfigView.dialog.choosedefaultsavepath=Velg standard lagringssti ConfigView.section.server=Tjener ConfigView.section.global=Globalt ConfigView.label.disconnetseed=Koble fra komplette kilder ved ren spredning ConfigView.label.switchpriority=Skift til lav prioritet nr torrenten er ferdig nedlastet ConfigView.label.maxactivetorrents=Maks aktive torrenter [0: ubegrenset] \nFlere torrenter vil ikke bli startet ConfigView.label.priorityExtensions=Prioriter utvalgte filtyper \n (f.eks: .txt;.nfo;.jpg) ConfigView.section.transfer=Overfring ConfigView.label.maxdownloads=Maks samtidige nedlastinger [0: ubegrenset] ConfigView.label.maxdownloads.tooltip=Du vil alltid vre i stand til laste ned angitt antall. Unntaket er komplette torrenter med hyeste prioritet. Disse kan overta en slot dersom det aboslutt er nvendig ConfigView.label.maxdownloadspeed=Maks total nedlastingshastighet i KB/s [0: ubegrenset] ConfigView.label.maxuploads=Maks slots per torrent som standard ConfigView.label.maxuploadspeed=Maks total opplastingshastighet i KB/s. [0: ubegrenset] ConfigView.label.saveresumeinterval=Intervall for lagring av 'hurtig fortsettelse'-data ConfigView.unlimited=Ubegrenset ConfigView.section.display=Visning ConfigView.label.opendetails=pne detaljfane automatisk ConfigView.label.openbar=pne statuslinje automatisk ConfigView.label.use_old_speed_menus=Bruk gammelt utseende med hurtige menyer [krever omstart] ConfigView.label.closetotray='Lukk' minimerer Vuze til system-statuslinje/Dock ConfigView.label.minimizetotray='Ikonmodus' minimerer Vuze til system-statuslinje/Dock ConfigView.section.general=Generelt ConfigView.label.showsplash=Vis oppstartsbilde ConfigView.label.autoupdate=pne oppgraderingsdialog nr nyere versjon er tilgjengelig ConfigView.label.openconsole=pne konsoll ved oppstart ConfigView.label.openconfig=pne konfigurasjonsfane ved oppstart ConfigView.label.startminimized=Minimere ved start ConfigView.label.ircwiki=Vennligst les http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Tjener ConfigView.label.ircchannel=Kanal ConfigView.label.irclogin=Kallenavn ConfigView.group.irctitle=IRC innstillinger ConfigView.boolean.ircsendinfo=Tillat sending av innstillinger (anonymt) til \nkanaloperatorer for hjelp ConfigView.boolean.irclog=Aktiver logging av kanalaktivitet (til IRC_log.htm) ConfigView.section.security=Sikkerhet ConfigView.label.password=Beskytt Vuze med passord\nVil avkreves ved gjenoppretting fra ikonmodus og ved oppstart ConfigView.label.passwordconfirm=Passord (bekreft) ConfigView.label.passwordmatch=Passord aktivert: ConfigView.label.passwordmatchnone=Nei ConfigView.label.passwordmatchno=Nei / Passord stemmer ikke overens ConfigView.label.passwordmatchyes=Ja ConfigView.button.save=Lagre ConfigView.title.short=Konfigurasjon ConfigView.title.full=Konfigurasjon ConsoleView.title.short=Konsoll ConsoleView.title.full=Konsoll FileItem.write=skriv FileItem.read=les FileItem.high=hy FileItem.donotdownload=Ikke last ned FilesView.name=Navn FilesView.size=Strrelse FilesView.done=Ferdig FilesView.firstpiece=Frste bruddstykke # FilesView.numberofpieces=# bruddstykker FilesView.pieces=Bruddstykker FilesView.mode=Tilstand FilesView.priority=Prioritet FilesView.menu.open=pne FilesView.menu.setpriority=Set prioritet FilesView.menu.setpriority.high=Hy FilesView.menu.setpriority.normal=Normal FilesView.menu.setpriority.skipped=Ikke last ned FilesView.title.short=Filer FilesView.title.full=Filer GeneralView.section.downloaded=Lastet ned GeneralView.label.status.file=Filstatus GeneralView.label.status.pieces=Bruddstykke-status GeneralView.section.availability=Tilgjengelighet GeneralView.label.status.pieces_available=Bruddstykke-status GeneralView.section.transfer=Overfring GeneralView.title.short=Generelt GeneralView.title.full=Generelt GeneralView.label.timeelapsed=Tid brukt: GeneralView.label.remaining=Gjenstende: GeneralView.label.downloaded=Lastet ned: GeneralView.label.downloadspeed=Nedlastingshastighet: GeneralView.label.maxuploads=Maks opplastinger: GeneralView.label.maxuploads.tooltip=Maksimalt antall av mottakere som samtidig vil bli destrupet GeneralView.label.uploaded=Lastet opp: GeneralView.label.uploadspeed=Opplastingshastighet: GeneralView.label.seeds=Sendere: GeneralView.label.peers=Mottakere: GeneralView.label.totalspeed=Total hastighet: GeneralView.label.totalspeed.tooltip=Total hastighet til alle tilkoblede klienter GeneralView.label.averagespeed=gjennomsnitt GeneralView.label.filename=Filnavn: GeneralView.label.totalsize=Total strrelse: GeneralView.label.savein=Lagringssti: GeneralView.label.hash=Hashkode: GeneralView.label.numberofpieces=# bruddstykker: GeneralView.label.size=Strrelse: GeneralView.label.tracker=Tracker: GeneralView.label.updatein=Oppdater om: GeneralView.label.trackerurl=Tracker-URL: GeneralView.label.trackerurlupdate=Oppdater tracker GeneralView.label.comment=Torrentkommentar: GeneralView.label.user_comment=Brukerkommentar: GeneralView.label.status=Status ManagerItem.waiting=Venter ManagerItem.allocating=Tildeler ManagerItem.checking=Kontrollerer ManagerItem.ready=Venter p at andre torrenter legges til k ManagerItem.downloading=Laster ned ManagerItem.seeding=Sprer ManagerItem.stopped=Stoppet ManagerItem.error=Feil ManagerItem.high=hy ManagerItem.low=lav MinimizedWindow.name=Navn: MinimizedWindow.all_transfers=Samlede overfringer PiecesView.size=Strrelse PiecesView.numberofblocks=# blokker PiecesView.blocks=Blokker PiecesView.completed=Ferdig PiecesView.availability=Tilgjengelighet PiecesView.reservedby=Reservert PiecesView.writers=Blokk, bidragsytere PiecesView.title.short=Bruddstykker PiecesView.title.full=Bruddstykker SystemTray.tooltip.seeding=%1 spres, SystemTray.tooltip.downloading=%1 lastes ned, DownloadManager.error.filenotfound=Fil ikke funnet DownloadManager.error.fileempty=Torrent-fil er tom DownloadManager.error.filetoobig=Torrent-fil er for stor DownloadManager.error.filewithouttorrentinfo=Ingen torrent-informasjon funnet i fil DownloadManager.error.unsupportedencoding=Enkodning ikke stttet DownloadManager.error.ioerror=IO-feil DownloadManager.error.sha1=Ukjent algoritme (SHA1) PeerManager.status.offline=frakoplet PeerManager.status.ok=ok PeerManager.status.checking=kontrollerer PeerManager.status.finished=Ferdig PeerManager.status.finishedin=Ferdig om MainWindow.upgrade.assistant=Oppgraderinghjelper MainWindow.upgrade.newerversion=Det er en nyere versjon av Vuze tilgjengelig for nedlasting MainWindow.upgrade.explanation=Denne hjelperen vil laste ned den nye versjonen til din Azureus-mappe og starte Vuze p nytt MainWindow.upgrade.explanation.manual=Du kan oppdatere manuelt ved lukke Vuze laste ned den nye versjonen og starte Vuze p ny MainWindow.upgrade.step1=Trinn 1: Last ned den nye versjonen MainWindow.upgrade.step2=Trinn 2: Stopp kjringen av Vuze og start den nye versjonen MainWindow.upgrade.hint1=Tips:\tVed klikke p 'Ferdig' utfres alt automatisk MainWindow.upgrade.hint2=Hint:\tHvis du vil lukke Vuze senere, trykk avbryt og\n\tomdp Azureus2-new.jar til Azureus2.jar etter lukkingen MainWindow.upgrade.error.downloading.hint=Feil:\tKunne ikke laste ned den nye versjonen, vennligst oppdater manuelt MainWindow.upgrade.section.info=Ny versjon tilgjengelig MainWindow.upgrade.section.manual=Manuell oppdatering MainWindow.upgrade.section.automatic=Automatisk oppdatering MainWindow.upgrade.tooltip.progressbar=Nedlastingens fremdrift vises her Button.next=Neste Button.finish=Avslutt Button.cancel=Av&bryt LocaleUtil.title=Velg koding LocaleUtil.section.chooseencoding=Velg koding for filnavn LocaleUtil.label.chooseencoding=Velg den kodingen som samsvarer best LocaleUtil.label.hint.doubleclick=Tip: dobbeltklikk p en rekke velger koding og lukker dialogen LocaleUtil.label.checkbox.rememberdecision=Husk valg for resterende filnavn LocaleUtil.column.encoding=Koding IrcClient.copyright=Bruker PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Kopler til IrcClient.connected=Koplet til IrcClient.joining=Gr inn i IrcClient.channel=Kanal IrcClient.joined=P plass i kanal IrcClient.error=Feil IrcClient.hasjoined=har kommet IrcClient.haskicked=har sparket ut IrcClient.hasleft=har forlatt IrcClient.nowknown=er n kjent som IrcClient.topicforchannel=Emne for kanal IrcClient.disconnected=Forbindelsen brutt - IrcClient.noNick=Kallenavn ikke spesifisert. Vennligst g til 'Konfigurasjon' p Vis-menyen IrcView.actionnotsupported=Denne handlingen stttes ikke IrcView.clientsconnected=brukere IrcView.privateto=Til IrcView.privatefrom=Fra IrcView.noticefrom=Merknad: IrcView.errormsg=Feil syntaks til /msg : /msg kallenavn melding IrcView.help=Gyldige kommandoer er:\n . /help : viser denne meldingen\n . /nick | /name: endrer ditt kallenavn \n . /me handling: sender en handling \n . /msg kallenavn melding: sender en privat melding til \n . /r melding : gjentar svar p siste private melding\n . /join #kanal (ikke klikk her, dette er kun et eksempel): endrer gjeldende kanal til 'kanal' PasswordWindow.title=Vuze er lst PasswordWindow.passwordprotected=Vuze er lst med passord.\nSkriv inn passordet her for gjenpne hovedvinduet: Button.ok=&OK TrackerChangerWindow.title=Skift Tracker TrackerChangerWindow.newtracker=Skriv ny Tracker-URL PeersView.discarded=Forkastet PeersView.discarded.info=Overfldig mottatt data ble fjernet. discarded=forkastet MyTorrentsView.menu.move=&Flytt MyTorrentsView.menu.moveUp=&Opp MyTorrentsView.menu.moveDown=&Ned GeneralView.label.hashfails=Hashkode-feil: GeneralView.label.shareRatio=Delingsrate: ConfigView.section.downloadManagement=Nedlasting ConfigView.label.startRatioPeers=Start spredning nr der er mindre enn n sender for ConfigView.text.neverStop=Aldri stopp ConfigView.text.neverStart=Aldri start ConfigView.text.peers=mottakere ConfigView.label.checkOncompletion=Kontroller bruddstykker p ny nr nedlasting er ferdig wizard.title=Opprett en torrent wizard.previous=< Tilbake wizard.next=Neste > wizard.finish=Avslutt wizard.mode=Tracker / Tilstand wizard.invalidurl=Denne URL er ugyldig wizard.singlefile=Enkelt-fil wizard.singlefile.help=Opprett en torrent ut fra en enkelt fil wizard.directory=Mappe wizard.directory.help=Opprett en torrent ut fra en mappe wizard.choosefile=Velg fil wizard.file=Fil: wizard.browse=Utforsk... wizard.choosedirectory=Velg en mappe wizard.invalidfile=Ugyldig fil! wizard.invaliddirectory=Ugyldig mappe! wizard.torrentFile=Torrent fil wizard.choosetorrent=Vennligst velg den torrent-filen du vil opprette wizard.information=Informasjon wizard.notimplemented=Enn ikke implementert wizard.progresstitle=Oppretter torrent-fil wizard.savingfile=Lagrer fil... wizard.filesaved=Fil lagret wizard.close=Lukk Torrent.create.progress.piecelength=Bruddstykketykke-lengde: Torrent.create.progress.piececount=Antall bruddstykker: Torrent.create.progress.totalfilesize=Total filstrrelse: Torrent.create.progress.totalfilecount=Totalt antall filer: Torrent.create.progress.parsingfiles=Analyserer filer Torrent.create.progress.hashing=Genererer hash-koder MainWindow.upgrade.downloadingfrom=Laster ned fra: MainWindow.menu.view.ipFilter=IP-filter ConfigView.section.ipfilter=IP-filter ConfigView.section.ipfilter.description=Beskrivelse ConfigView.section.ipfilter.start=Fra IP ConfigView.section.ipfilter.end=Til IP ConfigView.section.ipfilter.add=Legg til ConfigView.section.ipfilter.remove=Fjern ConfigView.section.ipfilter.edit=Rediger ConfigView.section.ipfilter.save=Lagre ConfigView.section.ipfilter.editFilter=Rediger filter ConfigView.section.ipfilter.enable=Aktiver PeersView.menu.close=Lukk seedmore.title=Torrenten har for lav delingsrate seedmore.shareratio=Din delingsrate til denne torrenten er seedmore.uploadmore= ha en delingsrate mindre enn 100% er ikke bra for bittorrent-nettverket.\nDu burde la denne torrenten spres litt mer.\nEr du sikker p at du vil stoppe torrenten? ConfigView.label.showpopuponclose=Vis bekreftelsesmelding nr du avslutter torrenten, og delingsforholdet er mindre en 1 ConfigView.label.startNumSeeds=Start spredning dersom der er mindre enn (overstyrer alle andre regler) ConfigView.label.seeds=sendere ConfigView.section.seeding=Sprer MyTorrentsView.menu.removeand=Fjern og MyTorrentsView.menu.removeand.deletetorrent=Slett .torrent MyTorrentsView.menu.removeand.deletedata=Slett data MyTorrentsView.menu.removeand.deleteboth=Slett begge deletedata.title=!!! Advarsel !!! deletedata.message1=Du skal til slette DATAENE fra: deletedata.message2=\nVil du virkelig dette? MainWindow.menu.file.configure=Konfigurasjonsveiviser configureWizard.title=Konfigurasjonsveiviser configureWizard.welcome.title=Velkommen til konfigurasjonsveiviseren for Vuze configureWizard.welcome.message=Denne veiviseren vil hjelpe deg med konfigurere Vuze for normal bruk. Du kan endre konfigurasjonsdetaljer med menyvalget Vis > Konfigurasjon. configureWizard.transfer.title=Overfrings- og tilkoblingsoppsett configureWizard.transfer.hint=Tips: Anbefalt er velge litt mindre enn din fulle bndbredde til opplasting. configureWizard.transfer.message=Velg tilkoblingstype nedenfor. Vr oppmerksom p at en lav opplastingshastighet vil resultere i lave nedlastingshastigheter. Siden opplastingshastigheten kun teller per torrent du laster ned, vil forsk p laste ned for mange torrenter av gangen ogs resultere i lave hastigheter. Vi anbefaler sette 5 KB/s per torrent som et ABSOLUTT minimum. Jo hurtigere du laster opp, desto hurtigere vil du laste ned (med hensyn til torrent-hastigheten). configureWizard.transfer.connection=Tilkobling configureWizard.transfer.connection.0=Egendefinert configureWizard.transfer.connection.1=Modem/ISDN configureWizard.transfer.connection.2=ADSL/kabel xxx/128 kbps configureWizard.transfer.connection.3=ADSL/kabel xxx/256 kbps configureWizard.transfer.connection.4=ADSL/kabel xxx/384 kbps configureWizard.transfer.connection.5=ADSL/kabel xxx/512 kbps configureWizard.transfer.connection.6=ADSL/kabel xxx/768 kbps configureWizard.transfer.connection.7=ADSL/kabel xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Maks opplastingshastighet (kB/s) configureWizard.transfer.maxActiveTorrents=Maks aktive torrenter configureWizard.transfer.maxDownloads=Maks nedlastinger configureWizard.transfer.maxUploadsPerTorrent=Maks # opplastinger per torrent configureWizard.nat.title=NAT / tjener-porter configureWizard.nat.message=For f det beste ut av BitTorrent, er det sterkt anbefalt vre fullt tilgengelig p Internett. Standard BitTorrent-port er 6881. Med dette verktyet kan du teste og/eller forandre portnummer. OBS: Port 6880 er reservert til internt bruk, og kan derfor ikke benyttes. configureWizard.nat.testing=Tester port configureWizard.nat.ok=OK! configureWizard.nat.ko=NAT-feil configureWizard.nat.unable=Kan ikke teste (ugyldig port angitt, eller svikt i testverktyet) configureWizard.file.title=Torrenter / Filer configureWizard.file.message1=Vuze vil lagre pnede torrenter i en standard mappe, mappen velger du her: configureWizard.file.path=Sti configureWizard.file.browse=Utforsk configureWizard.file.message2=Vuze er i stand til bruke 'lynrask fortsettelse', ved legge til 'fortsettelsesdata' til dine torrenter. Ved bruk av denne funksjonen vil du ogs kunne fortsette delvis nedlastede bruddstykker. configureWizard.file.fastResume=Bruk 'hurtig fortsettelse' configureWizard.file.invalidPath=Ugyldig mappe configureWizard.finish.title=Ferdig configureWizard.finish.message=Vuze er n konfigurert. God fornyelse! wizard.close.confirmation=Bekreftelse wizard.close.message=Vil du kjre denne veiviseren neste gang Vuze startes? exportTorrentWizard.title=Eksporter en torrent exportTorrentWizard.torrentfile.title=Valg av torrent exportTorrentWizard.torrentfile.message=Velg torrent-filen som skal eksporteres exportTorrentWizard.torrentfile.path=Sti exportTorrentWizard.torrentfile.browse=Utforsk exportTorrentWizard.torrentfile.invalidPath=Ugyldig torrentfil exportTorrentWizard.exportfile.title=Eksporter til exportTorrentWizard.exportfile.message=Velg filen som det skal eksporteres til exportTorrentWizard.exportfile.path=Sti exportTorrentWizard.exportfile.browse=Utforsk exportTorrentWizard.exportfile.invalidPath=Ugyldig eksport-fil exportTorrentWizard.finish.title=Ferdig exportTorrentWizard.finish.message=Eksportering fullfrt exportTorrentWizard.process.inputfilebad.title=Torrent-fil ugyldig exportTorrentWizard.process.inputfilebad.message=Det skjedde en feil under lesing av filen: exportTorrentWizard.process.outputfileexists.title=Filen eksisterer fra fr exportTorrentWizard.process.outputfileexists.message=Filen eksisterer fra fr - overskrive? exportTorrentWizard.process.torrentfail.title=Lesing av torrent feilet exportTorrentWizard.process.exportfail.title=Eksportering av torrent feilet exportTorrentWizard.process.unknownfail.title=Uventet feil importTorrentWizard.title=Importer en torrent importTorrentWizard.torrentfile.title=Valg av torrent importTorrentWizard.torrentfile.message=Velg en torrentfil importere til importTorrentWizard.torrentfile.path=Sti importTorrentWizard.torrentfile.browse=Utforsk importTorrentWizard.torrentfile.invalidPath=Ugyldig torrentfil importTorrentWizard.importfile.title=Velg importering importTorrentWizard.importfile.message=Velg filen som skal importeres importTorrentWizard.importfile.path=Sti importTorrentWizard.importfile.browse=Utforsk importTorrentWizard.importfile.invalidPath=Ugyldig importfil importTorrentWizard.finish.title=Ferdig importTorrentWizard.finish.message=Importering fullfrt uten problemer importTorrentWizard.process.inputfilebad.title=Importfil ugyldig importTorrentWizard.process.inputfilebad.message=Der skjedde en feil under lesing av filen: importTorrentWizard.process.outputfileexists.title=Fil eksisterer fra fr importTorrentWizard.process.outputfileexists.message=Filen eksisterer - overskrive? importTorrentWizard.process.torrentfail.title=Skriving til torrent feilet importTorrentWizard.process.importfail.title=Importering av torrent feilet importTorrentWizard.process.unknownfail.title=Uventet feil ConfigView.label.bindip=Bind til lokal IP-adresse eller interface ConfigView.label.xfs.allocation=Alloker nye filer ved hjelp av spesiell metode for XFS-filsystem ConfigView.label.xfs.allocation.tooltip=Overprv at /usr/sbin/xfs_io er korrekt installert p systemet. I de fleste Linux distribusjonene flger dette med "xfsprogs"-pakken. xfs.allocation.xfs_io.not.found=XFS-filallokasjon misslyktes p grunn av at /usr/sbin/xfs_io ikke kunne kjres. Forsikre deg om at xfs er korrekt installert p systemet. Opprinnelig feilmelding: "%1". ConfigView.label.zeronewfiles=Tildel plass og null ut filer ved opprettelse ConfigView.label.zeronewfiles.tooltip=Reduserer disk-fragmentering ConfigView.section.stats=Statistikk ConfigView.section.stats.enable=Aktiver ConfigView.section.stats.defaultsavepath=Mappe for statistikk ConfigView.section.stats.choosedefaultsavepath=Velg mappe for lagring av statistikkdata ConfigView.section.stats.savefreq=Lagringsfrekvens ConfigView.section.stats.hours=t ConfigView.section.stats.seconds=sek ConfigView.section.stats.savefile=Statistikk - filnavn ConfigView.section.stats.graph_update_dividers=Vis vertikale linjer for hver 60. oppfriskning MyTorrentsView.menu.export=&Eksporter... MyTorrentsView.menu.host=&Vert... ManagerItem.finishing=Avslutter ConfigView.dialog.choosedefaulttorrentpath=Velg standard torrent-mappe ConfigView.dialog.choosemovepath=Velg mappen det skal flyttes til ConfigView.label.movecompleted=Flytt ferdig nedlastede filer (etter nedlasting) ConfigView.label.moveremoved=Flytt ferdig nedlastede filer (ved fjerning ifra Vuze ConfigView.label.savetorrents=Lagre torrent-filer MainWindow.menu.view.mytracker=Min tracker MyTrackerView.title.full=Min tracker MyTrackerView.name=Navn MyTrackerView.status.started=Kjrer MyTrackerView.status.stopped=Stoppet MyTrackerView.peers=Mottakere MyTrackerView.seeds=Sendere MyTrackerView.announces=Kunngjr MyTrackerView.uploaded=Lastet opp MyTrackerView.downloaded=Lastet ned MyTrackerView.left=tilbake ConfigView.section.style=Brukergrensesnitt ConfigView.label.set_ui_transfer_speeds=Overstyr valgbare overfringshastigheter =Du kan selv velge sette opp- og nedlastingshastigheter tilgjengelig p statuslinjen.\nVerdiene m vre kommaseparerte. ConfigView.label.set_ui_transfer_speeds.description.download=Velg hastigheter for nedlasting (i KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Velg hastigheter for opplasting (i KB/s) ConfigView.section.style.useCustomTabs=Bruk lukkbare faner [krever omstart] MainWindow.menu.view.plugins=&Programtillegg fileDownloadWindow.saveTorrentIn=Lagre torrent-fil i fileDownloadWindow.title=Vuze - Torrentnedlasting fileDownloadWindow.downloading=Laster ned fra: fileDownloadWindow.status=Status: fileDownloadWindow.state_initializing=Initialiserer fileDownloadWindow.state_downloading=Laster ned fileDownloadWindow.state_error=Feil: MainWindow.menu.file.open.url=&URL MainWindow.menu.file.open.url.keybinding=Meta+U openUrl.title=Vuze - pne URL openUrl.url=URL: MyTorrentsView.menu.host.error.title=Torrent-'hosting' feilet MyTorrentsView.menu.host.error.message=Flgende feil oppsto ved forsk p 'hoste' torrenten ConfigView.section.tracker.pollinterval=Tracker-klient, pollingsintervall (sekunder) ConfigView.section.tracker.publishenable=Publiser torrent-detaljer til "" ConfigView.section.tracker.ip=Ekstern tracker IP-adresse MainWindow.menu.help.faq=Ofte Stilte Sprsml (wiki) ConfigView.section.style.enableXPStyle=Anvend XP-stil [krever omstart] ConfigView.section.tracker.checkip=Automatisk detektering av ekstern IP-adresse... ipCheckerWizard.title=IP-sjekk-veiviser ipCheckerWizard.service=Tjeneste ipCheckerWizard.chooseService=Velg en IP-sjekk-tjeneste fra tjeneste-listen ipCheckerWizard.explanations=Du kan bruke denne veiviseren til finne ut hva din eksterne IP-adresse er. Hvis din IP-adresse er dynamisk, anbefaler vi at du pner en konto hos en dynamisk DNS-tjeneste. Noen av disse tjenestene er listet nedenfor, benytt en av lenkene (eller andre) til opprette en konto (der det stttes). Fyll dereetter ut IP-adresse-feltet med ditt dynamiske vertsnavn (f.eks. mittvertsnavn.dyndns.org). Du bruker et program til automatisk oppdatere din dynamiske DNS-tjeneste med din IP-adresse. Slik vil du vre i stand til 'hoste' torrenter selv om din IP-adresse endres. ipCheckerWizard.service.description=Beskrivelse: ipCheckerWizard.service.url=Lenk: ipCheckerWizard.progresstitle=Sjekker IP ipCheckerWizard.checkComplete=Ferdig IP: ipCheckerWizard.checkFailed=Feilet, rsak : wizard.tracker.local=Bruk innbygget Azureus-tracker wizard.tracker.external=Bruk en ekstern tracker wizard.tracker.howToLocal=G til 'Konfigurasjon>Tracker' for aktivisering wizard.announceUrl=Annonserings-URL : IPChecker.external.service.discoveryvip.description=Discoveryvip - Kun IP-adresse-sjekk IPChecker.external.httpinvalidresponse=Ugyldig HTTP respons IPChecker.external.loadingwebpage=Henter nettside IPChecker.external.analysingresponse=Analyserer respons IPChecker.external.addressextracted=IP-adresse trukket ut IPChecker.external.httploadfail=Kunne ikke hente side IPChecker.external.timeout=Det oppsto en timeout IPChecker.external.ipnotfound=IP-adresse ikke funnet ConfigView.section.tracker.pollintervalmin=Min ConfigView.section.tracker.pollintervalmax=Maks ConfigView.section.tracker.pollintervalincby=k med ConfigView.section.tracker.pollintervalincper=For hver 'n' klienter splash.loadingImages=Laster bilder splash.initializeGui=Initialiserer hovedvindu splash.openViews=pner faner splash.plugin=Henter programtillegg: configureWizard.nat.tooManyPorts=For mange porter teste (maks 9) ConfigView.section.color=Farge Tema MyTorrentsView.menu.publish=Pub&liser... MyTrackerView.status.published=Publisert MyTrackerView.completed=Ferdig MainWindow.menu.file.open.torrentnodefault=.torrent-fil (velg mlmappe) wizard.comment=Kommentar ConfigView.label.movetorrent=Flytt .torrent ConfigView.label.movepartialdownloads=Flytt nr noen filer er merket "ikke last ned" ConfigView.label.subdir_is_in_default=Ved overveielse om nedlasting finnes i standard lagringsmappe, betrakt ogs standard undermapper ConfigView.section.file.decoder.label=Standard torrent-koding m settes ved flervalg ConfigView.section.file.decoder.nodecoder=Ingen IPChecker.external.service.no-ip.description=Dynamisk og statisk DNS-tjenestetilbyder\n(ikke gratis IP-sjekk-tjeneste) ConfigView.section.tracker.publicenable=Aktiver eksterne torrenter ConfigView.label.playdownloadspeech=Talelyd nr en nedlasting ferdigstilles ConfigView.label.playdownloadspeech.info="Speech Services" virker for tiden best for engelsk GeneralView.label.status.pieces_available.tooltip=Viser for yeblikket antall tilgjengelige kopier av hvert bruddstykke. \nEr verdien til hyre mindre enn 1, finnes det ingen nvrende komplett kopi av torrenten. (Dette vanskeliggjr nedlastingen). GeneralView.label.trackerurl.tooltip=Klikk for kopiere annonserings-URL til utklippstavle GeneralView.label.trackerurlopen.tooltip=Klikk for pne trackerens hovedside ConfigView.section.style.guiUpdate=Oppfrisk brukergrensesnitt (GUI) hvert ConfigView.section.style.graphicsUpdate=Oppfrisk grafiske linjer etter hver n'te GUI-opptegning ConfigView.section.style.reOrderDelay=Sorter tabeller etter hver n'te GUI-opptegning ConfigView.section.style.reOrderDelay.never=Aldri ConfigView.section.logging.enable=Aktiver loggfring til fil ConfigView.section.logging.logdir=Mappe for loggfiler ConfigView.section.logging.choosedefaultsavepath=Velg mappe GeneralView.label.updatein.querying=sprring pgr... configureWizard.nat.sharePort=Bruk en enkelt - delt - inn-port for alle torrenter ConfigView.section.logging.maxsize=Maks strrelse til loggfil ConfigView.section.tracker.passwordenableweb=Bruk passord p tracker-vev ConfigView.section.tracker.passwordenabletorrent=Passordbelegg torrenter ConfigView.section.tracker.username=Brukernavn ConfigView.section.tracker.password=Passord columnChooser.title=Velg kolonnene som skal vises columnChooser.move=Dra og slipp rader for stokke om columnChooser.apply=Bruk columnChooser.columnname=Kolonnenavn columnChooser.columndescription=Beskrivelse TableColumn.header.shareRatio=Delingsrate MyTorrentsView.menu.editTableColumns=Velg kolonnene som skal vises wizard.operationfailed=Operasjon feilet authenticator.title=Autorisering pkrevd authenticator.realm=Omrde authenticator.user=Brukernavn authenticator.password=Passord ConfigView.label.allowSendVersion=Tillat Vuze sende anonymt versjonsnummer og tilfeldig id nr det sees etter nyeste versjon ConfigView.label.version.info.link=Se her for beskrivelse av data som blir sendt til server ved versjonssjekk wizard.hint.mode=Tips:\tDu kan dra-og-slippe en enkelt fil eller en valgt mappe p denne veiviseren wizard.hint.file=Tips:\tDu kan velge en enkelt fil med dra-og-slipp wizard.hint.directory=Tips:\tDu kan velge en enkelt mappe med dra-og-slipp MainWindow.menu.help.checkupdate=Sjekk for ny versjon (oppdatering) TableColumn.header.down=Lastet ned TableColumn.header.up=Lastet opp ConfigView.section.tracker.passwordenabletorrent.info=Krever kompatibel BitTorrent klient (f.eks. Vuze ConfigView.section.style.confirmationOnExit=Vis bekreftelsesdialog ved avsluttning MainWindow.dialog.exitconfirmation.title=Avslutt Vuze MainWindow.dialog.exitconfirmation.text=Vil du virkelig avslutte Vuze SystemTray.menu.stopalltransfers=Stopp &alle overfringer TrayWindow.menu.stopalldownloads=Stopp alle nedlastinger ConfigView.section.tracker.sslport.info=Se FAQ for ytterligere informasjon wizard.tracker.ssl=Bruk SSL ConfigView.label.playdownloadfinished=Spill av en lyd nr en nedlasting er ferdig ConfigView.label.popupdownloadfinished=Vis sprettoppmelding nr en nedlasting er ferdig ConfigView.label.popupfilefinished=Vis sprettoppmelding nr en fil er ferdig TableColumn.header.pieces=Bruddstykker TableColumn.header.pieces.info=Grafisk diagram som viser deler du har lastet ned TableColumn.header.completion=Fullfring TableColumn.header.completion.info=Grafisk visning av % nedlastet ConfigView.section.style.showdownloadbasket=Vis nedlastingskurv (dra-og-slipp .torrenter) ConfigView.section.style.alwaysShowTorrentFiles=Vis alltid torrent-filer i detaljer/filer wizard.multitracker=Legg Multi-Tracker-informasjon til torrenten wizard.multitracker.configuration=Multi-Tracker: konfigurasjon wizard.multitracker.new=Ny... wizard.multitracker.edit=Rediger.. wizard.multitracker.delete=Slett wizard.multitracker.group=Tracker-gruppe wizard.multitracker.edit.title=Multi-Tracker: redigering wizard.multitracker.edit.name=Navn wizard.multitracker.edit.save=Lagre wizard.multitracker.edit.newgroup=Ny gruppe wizard.multitracker.edit.deletegroup=Slett wizard.multitracker.edit.newtracker=Ny Tracker wizard.multitracker.edit.deletetracker=Slett wizard.multitracker.edit.edit=Rediger wizard.addingmt=Legger til Multi-Tracker-informasjon wizard.multitracker.noannounce=Annonserings-URL finnes ikke i din tracker-liste MyTorrentsView.menu.recheck=Tvungen re-sjekk iconBar.showDownloadBar.tooltip=Vis nedlastingslinje iconBar.stop.tooltip=Stopp iconBar.remove.tooltip=Fjern iconBar.openNoDefault.tooltip=pne en .torrent fil (ingen standard lagring) iconBar.openURL.tooltip=pne en URL iconBar.openFolder.tooltip=pne en mappe iconBar.new.tooltip=Opprett en torrent iconBar.up.tooltip=Flytt opp iconBar.down.tooltip=Flytt ned iconBar.run.tooltip=pne iconBar.host.tooltip=Vert iconBar.publish.tooltip=Publiser MyTorrentsView.menu.editTracker=Rediger Tracker-URL(er) GeneralView.menu.selectTracker=Velg ConfigView.section.stats.xslfile=XSL filnavn ConfigView.section.stats.xslfiledetails=Dette vil bli inkludert i statistikk-fil via -tag ConfigView.label.savetorrentbackup=Lagre sikkerhetskopi ConfigView.section.tracker.forceport=Tving 'hostede' eksterne torrenter til standard port ConfigView.section.ipfilter.allow=TILLAT disse omrder (normalen er NEKT) ConfigView.section.ipfilter.list.inrange=var i IP-omrde ConfigView.section.ipfilter.list.notinrange=var ikke i noen IP-omrder ConfigView.section.ipfilter.list.title=Liste over blokkerte IP'er ConfigView.label.allowsameip=Tillat flere tilkoblinger fra samme IP ConfigView.label.allowsameip.tooltip=Kryss kun av hvis du M det.\nDette er et anti-snylte vern (nr ikke krysset av). ManagerItem.superseeding=Super-spredning ConfigView.label.userSuperSeeding=Bruk super-spredning PeersView.uniquepiece=Bruddstykke (super-spredning) PeersView.uniquepiece.none=Ingen PeersView.timetosend=Tid for re-sende bruddstykke (super-spredning) ConfigView.section.style.addurlsilently=pne URL direkte (uten dialog) ConfigView.section.style.addurlsilently.tooltip=Advarsel: Hovedvinduet vil ikke bli synlig igjen hvis aktivert! \nHvis du mister systemstatusomrde-ikonet, burde du deaktivere denne muligheten. ConfigView.section.file.decoder.prompt=Spr alltid nr valg av koding er mulig ConfigView.section.file.decoder.prompt.tooltip=Vis alltid dialogvindu nr valg av koding er mulig MyTorrentsView.menu.moveTop=Topp MyTorrentsView.menu.moveEnd=Bunn ConfigView.label.moveonlyusingdefaultsave=dersom i standard mappe ConfigView.label.moveonlyusingdefaultsave.tooltip=Flytt bare hvis torrenten er i standard mappe ConfigView.label.watchtorrentfolder=Importer nye torrenter automatisk ConfigView.label.watchtorrentfolder.tooltip=Ser etter nye .torrenter regelmessig ConfigView.label.watchtorrentfolderinterval=Intervall ConfigView.label.watchtorrentfolderinterval.tooltip=Pausen mellom hver skanning av mappen (etter nye torrenter) ConfigView.dialog.choosewatchtorrentfolderpath=Velg mappe for .torrent-importering ConfigView.label.startwatchedtorrentsstopped=Start stoppet ConfigView.label.startwatchedtorrentsstopped.tooltip=Legg til nye .torrenter i STOPPET tilstand ConfigView.section.plugins=Programtillegg wizard.maketorrent.filesize=Filstrrelse wizard.maketorrent.piececount=Antall bruddstykker wizard.maketorrent.piecesize=Bruddstykkestrrelse wizard.maketorrent.auto=Automatisk MainWindow.menu.view.stats=&Statistikk SpeedView.title.full=Aktivitet SpeedView.downloadSpeed.title=Nedlastingshastighet SpeedView.uploadSpeed.title=Opplastingshastighet ConfigView.section.style.useSIUnits=Bruk IEC-enheter (KB -> KiB osv.) iconBar.top.tooltip=Flytt til toppen iconBar.bottom.tooltip=Flytt til bunnen TableColumn.header.health=Helse MyTorrentsView.menu.health=Om helse health.explain.grey=Betyr at torrenten ikke er i gang (ned/opplasting). health.explain.red=Betyr at du under nedlasting ikke er koblet til noen andre som sprer. health.explain.blue=Ved spredning betyr dette at du ikke er tilkoblet noen. \nVed nedlasting betyr det at du er tilkoblet andre spredere, men at trackeren er nede. health.explain.yellow=Betyr at trackeren er ok, at du er koplet til andre spredere, men ingen innkommende forbindelser til deg. \nDu kan ha et NAT-problem dersom dine torrenter forblir i gul modus over tid. health.explain.green=Betyr at alt fungerer utmerket. health.explain.share=Betyr at torrenten enten er 'hosted' eller publisert. health.explain.error=Det er en feil med denne torrenten. Se statuskolonne eller ikonets bildetips. ConfigView.section.style.alwaysRefreshMyTorrents=Oppfrisk alltid 'Mine torrenter' ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Dette valget vil friske opp 'Mine torrenter'-fanen selv om den ikke vises (nyttig for noen prate-programtillegg) security.certtruster.title=Sikkerhets-sertifikat-advarsel security.certtruster.intro=Sikkerhets-sertifikatet er utstedt av et firma som du ikke stoler p. security.certtruster.resource=Ressurs: security.certtruster.issuedto=Utstedt til: security.certtruster.issuedby=Utstedt av: security.certtruster.prompt=Velger du stole p det? security.certtruster.yes=Ja security.certtruster.no=Nei ConfigView.section.tracker.torrentsperpage=Hvor mange torrenst per side? [0: ubegrenset] MainWindow.menu.file.share=&Del MainWindow.menu.file.share.file=&Fil... MainWindow.menu.file.share.dir=Mappe... MainWindow.menu.file.share.dircontents=Mappe-innhold... MainWindow.menu.file.share.dircontentsrecursive=Mappe-innhold (&rekursivt)... MainWindow.dialog.share.sharefile=Velg fil til deling MainWindow.dialog.share.sharedir=Velg mappe til deling MainWindow.dialog.share.sharedircontents=Velg mappeinnhold til deling MainWindow.dialog.share.sharedircontents.recursive=Rekursiv globalmanager.download.remove.veto=Lagt inn veto mot fjerning plugin.sharing.download.remove.veto=Denne nedlastingen er oppsttt ved at en ressurs er utdelt.\nFor fjerne nedlastingen, m du fjerne deling.: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Hoved ConfigView.section.tracker.web=Vev ConfigView.label.prioritizefirstpiece=Prioriter frste delen av filer. ConfigView.label.prioritizefirstpiece.tooltip=Forsker laste ned begynnelsen av filene frst. ConfigView.section.file.confirm_data_delete=Bekreft sletting av data ConfigView.section.file.confirm_data_delete.tooltip=Bekreft sletting av data ved 'Fjern og slett...' TrayWindow.menu.startalldownloads=Start alle nedlastinger SystemTray.menu.startalltransfers=Start alle overfringer sharing.progress.title=Delings-prosess sharing.progress.hide=Skjul MainWindow.menu.view.myshares=Mine delinger MySharesView.title.full=Mine delinger MySharesView.name=Navn MySharesView.type.file=Fil MySharesView.type.dir=Mappe MySharesView.type.dircontents=Mappeinnhold MySharesView.type.dircontentsrecursive=Mappeinnhold (rekursiv) MySharesView.menu.remove=Fjern ConfigView.section.tracker.extensions=Utvidelser ConfigView.section.tracker.sendpeerids=Send kilde-identitet til klienter ConfigView.section.tracker.enableudp=Aktiver UDP-tracker protokoll plugin.sharing.torrent.remove.veto=Registreringen av denne trackeren ble til av at en ressurs ble delt. \nFor fjerne nedlastingen, fjern da tilhrende deling (share).: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Nedlastingen er ikke stoppet, og kan da ikke bli fjernet. plugin.sharing.remove.veto=Denne delingen er en under-deling av en 'mappe-innhold'-deling, og kan dermed ikke bli fjernet.\n Slett frst den overordnede delingen. GeneralView.label.hash.tooltip=Klikk for kopiere hash til utklippstavle ConfigView.section.tracker.maxpeersreturned=Maks kilder fra tracker [0: ubegrenset] ConfigView.label.serverport=Innkommende TCP / UDP port ConfigView.label.serverport.tooltip=Porter eksisterer i intervallet 1-65535, men ikke 6880 da denne er reservert for Vuze (brukt internt). configureWizard.nat.server.tcp_listen_port=Innkommende TCP-port ConfigView.section.sharing=Deling ConfigView.section.sharing.usessl=Benytt SSL for delte ressurser (krever Tracker-konfigurasjon) ConfigView.section.style.dropdiraction='Dra og slipp' for mapper ConfigView.section.style.dropdiraction.opentorrents=pne Torrenter ConfigView.section.style.dropdiraction.sharefolder=Del mappe ConfigView.section.style.dropdiraction.sharefoldercontents=Del innhold Categories.all=Alle Categories.uncategorized=Ikke kategorisert CategoryAddWindow.message=Skriv inn navn til ny kategori CategoryAddWindow.title=Legg til ny kategori ConfigView.label.autoSeedingIgnoreInfo=Ignorerte torrenter blir lagt bakerst i ken. De blir ikke startet automatisk. Ignoreringsregler gjelder ikke for torrenter med frsteprioritet. Dersom ikke annet er gitt, bruk verdien 0 for deaktivere regelen. ConfigView.label.directory=Mappe ConfigView.label.disconnetseed.tooltip=Nr en torrent er komplett, koble s ifra alle andre komplette kilder.\nYtterligere kommunikasjon med dem behves ikke. ConfigView.label.ignoreCase=Ignorerings tilfelle ConfigView.label.ignoreSeeds=Ignorer torrenter med minst ConfigView.label.importdirectory=Import-mappe ConfigView.label.minPeersToBoostNoSeeds.tooltip=Hver torrent uten noen sendere og frre mottakere enn spesifisert, \nblir skjvet bakover i ken. ConfigView.label.minPeersToBoostNoSeeds=Lavere rangering av torrenter uten sendere og frre spredere enn ConfigView.label.minSeedingTime.tooltip=Fordelingsrangeringen kan ofte flukutere i korte perioder, som noen ganger frer til at torrenten automatisk blir startet, for s kortsiktig bli stoppet og lagt tilbake i ken igjen. \nDenne innstillingen forringer problemet ved tvinge torrenten til vre delt over et visst tidsrom. Du kan nr som helst manuelt stoppe den. ConfigView.label.minSeedingTime=Minimum fordelingstid i sekunder ConfigView.label.minSpeedForActiveDL.tooltip=En nedlastings-slot blir alltid brukt de 30 frste sekundene etter at den uferdige torrenten starter. ConfigView.label.minSpeedForActiveDL=Torrenten gjr ikke beslag p en nedlastings-slot, dersom hastigheten er lavere enn ConfigView.label.peers=mottakere ConfigView.label.queue.debuglog=Logg debug-informasjon ConfigView.label.queue.debuglog.info=Legger debug-informasjon om ken til konsoll/logg-fil. \nSelv med kryptisk innhold, forteller debug-informasjonen deg statusen til torrentene og muligvis opptrdte problemer. ConfigView.label.queue.minQueueingShareRatio=Ikke stopp eller legg torrenter til ken, dersom delingsraten er mindre enn ConfigView.label.ratio=Forhold ConfigView.label.removeOnStop=Fjern torrent fra listen, etter at den automatisk ble stoppet ConfigView.label.savedirectory=Mappe for lagring ConfigView.label.seeding.autoReposition.tooltip=Dersom aktivert vil rekkeflgen til torrentene bli ordnet ('#' kolonne) etter fordelingsrangeringen. \nDette er nyttig dersom du vil gjemme rangering-nummerering, men vil se startrekkeflgen til ferdigstillte torrenter. ConfigView.label.seeding.autoReposition=Automatisk posisjonering av torrenter basert p fordelingsrangering ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Ofte betyr torrenter med f sendere og mange delere at ingen fullstendig nvrende kopi finnes. \n Derfor vil du muligvis se bort ifra at en komplett kopi finnes i fordelingsregelen (slik at rangeringen blir satt ned) ConfigView.label.seeding.fakeFullCopySeedStart=men kun for torrenter med minst ConfigView.label.seeding.ignore=Ignoreringsregler ConfigView.label.seeding.ignore0Peers=Ignorer torrenter med 0 kilder ConfigView.label.seeding.ignoreRatioPeers=Ignorer torrenter som minst har 1 komplett kilde av ConfigView.label.seeding.ignoreShareRatio=Ignorer torrenter med delingsrate av ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorer torrenter selv om \nfrste regel er gjeldende ConfigView.label.seeding.ignore.header.rule=Regel ConfigView.label.seeding.ignore.header.value=Vedi ConfigView.label.seeding.firstPriority.info=Torrenter med frste prioritet vil alltid vre plassert frst i ken. Alle torrenter med hyeste prioritetskriterie vil ikke automatisk bli stoppet og lagt i venteken. En torrent som oppfyller hyeste proiritetskriterie, kan oppta en simultan-nedlastings-slot dersom det viser seg for ndvendig. ConfigView.label.seeding.firstPriority.FP=Hyeste prioritet ConfigView.label.seeding.firstPriority=Hyeste prioritet til torrenter med ConfigView.label.seeding.firstPriority.following=flgende regel/regler: ConfigView.label.seeding.firstPriority.shareRatio=Et delingsforhold mindre enn ConfigView.label.seeding.firstPriority.seedingMinutes=Et tidsforlp etter fullfring av torrent p ConfigView.label.seeding.firstPriority.DLMinutes=Et tisdforlp etter start p nedlasting av ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Ved anta det er 1 komplett kopi per x antall mottakere, reduseres rangering av torrenten med stort antall av mottakere. \nMest sannsynlig vil dette store antallet mottakere ogs ha hy trafikk. \nDette endrer ikke visningen av '# sendere'. ConfigView.label.seeding.numPeersAsFullCopy=Anta det finnes 1 fullverdig kopi for hver \n(0 : Ingen antakelse) ConfigView.label.seeding.preferLargerSwarms.tooltip=Foretrekk strre svermer dersom du hovedsakligt deler komplette torrenter med andre mottakere som "sitter fast". \nForetrekk da sm svermer for torrenter med hy tilgjengelighet. ConfigView.label.seeding.preferLargerSwarms=Foretrekk strre svermer ved torrenter som har lik rangering ConfigView.label.seeding.rankType.none.tooltip=Ordne etter #-kolonne ConfigView.label.seeding.rankType.none=Ingen ConfigView.label.seeding.rankType.peerSeed.options=Innstillinger - sendere : mottakere ConfigView.label.seeding.rankType.peerSeed.tooltip=Strre forhold = hyere rangering ConfigView.label.seeding.rankType.peerSeed=Forhold sendere:mottakere ConfigView.label.seeding.rankType.seed.fallback=Fall tilbake til sendere:mottakere etter\n(0 : Fall aldri tilbake) ConfigView.label.seeding.rankType.seed.options=Innstilling - Telling av sendere ConfigView.label.seeding.rankType.seed.tooltip=Frre sendere = hyere rangering ConfigView.label.seeding.rankType.seed=Tell kun med komplette kilder ConfigView.label.seeding.rankType.timedRotation.tooltip=Alle komplette torrenter blir rotert i fordelingsmodus. \nVarigheten til hver fordeling bestemmes av 'min. fordelingstid'. ConfigView.label.seeding.rankType.timedRotation=Tidsbestemt rotering ConfigView.label.seeding.rankType.tooltip=Torrenter med strst rang blir startet automatisk. \nOppnr en annen torrent en strre rangering, blir den laveste rangerte torrenten stoppet og lagt til venteken. \n\Kun torrenter i ventetilstand vil automatisk bli startet. \nTorrenter som er stoppet vill aldri bli automatisk startet. ConfigView.label.seeding.rankType=Ranger komplette torrenter for automatisk start basert p: ConfigView.label.stopAfterMinutes=Nr torrenten blir komplett, stopp torrenten etter flgende tidsluke ConfigView.label.switchpriority.tooltip=Lav prioritet minsker torrentens tildelte bndbredde for opplasting. ConfigView.pluginlist.info=Flgende programtillegg er blitt identifisert. Enkelte programtillegg har ingen innstillingsmuligheter. ConfigView.pluginlist.noplugins=Ingen programtillegg funnet. ConfigView.section.pluginslist=Liste ConfigView.section.queue.seeding.autoStarting=Automatisk start ConfigView.section.queue.seeding.ignore=Ignoreringsregler ConfigView.section.queue.seeding.firstPriority=verste prioritet ConfigView.section.queue.main=Hoved ConfigView.section.queue=Ventek ConfigView.section.torrents=Torrenter ConfigView.text.all=alle ConfigView.text.hours=timer ConfigView.text.ignoreRule=Ignorerings-regel ConfigView.text.ignore=Ignorer ConfigView.text.minutes=minutter ConfigView.text.neverIgnore=Aldri ignorer ConfigView.text.any=noen DownloadManager.error.datamissing=Data mangler iconBar.queue.tooltip=Ventek MainWindow.menu.file.open.torrentforseeding=.torrent-fil (kompl. torrent for deling) MainWindow.menu.language.refresh=Oppfrisk ManagerItem.forced=Tvungen ManagerItem.queued=Ventende MySeedersView.header=Komplette torrenter TableColumn.header.availability.info=# synlige, komplette kopier TableColumn.header.availability=Tilgjengelighet TableColumn.header.category=Kategori MyTorrentsView.header=Ufullstendigt nedlastede torrenter TableColumn.header.maxuploads=Maks # opplastinger MyTorrentsView.menu.category.delete=Slett kategori MyTorrentsView.menu.forceStart=Tving start MyTorrentsView.menu.queue=Ventek MyTorrentsView.menu.setCategory.add=Ny kategori.. MyTorrentsView.menu.setCategory=Set kategori TableColumn.header.savepath=Lagringssti TableColumn.header.SeedingRank=Fordelingsrang TableColumn.header.totalspeed.info=Total hastighet til alle kilder tilkoblet TableColumn.header.totalspeed=Total hastighet splash.initializePlugins=Initialiserer programtillegg StartStopRules.SPratioMet=S:M forhold OK StartStopRules.0Peers=0 mottakere StartStopRules.numSeedsMet=# sendere OK StartStopRules.ratioMet=Sendere:Mottakere OK StartStopRules.shareRatioMet=Delingsforhold OK StartStopRules.waiting=Venter StartStopRules.firstPriority=1. prioritet ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Mappeinnhold (rekursiv) DownloadManager.error.unabletostartserver=Kan ikke starte server - overprv konfigurasjonen av innkommende porter og brannmurinnstillinger slik at applikasjonen kan opptre som server GeneralView.label.creationdate=Opprettet den: ConfigView.section.tracker.announcescrapepercentage=Scrape-intervall som prosentdel av annonseringen \nf.eks. 200 = 2:1. 0 = la kilden avgjre ManagerItem.stopping=Stopper ConfigView.section.tracker.announcecacheperiod=Annonserings-cache (i millisekunder) ConfigView.section.tracker.scrapecacheperiod=Scrape-cache (i millisekunder) ConfigView.section.tracker.scrapeandcache=Scrape og cache ConfigView.section.tracker.announcecacheminpeers=Annonserings-cache aktiviserer kilde-terskel fileDownloadWindow.retry=Gjenta MyTrackerView.bytesin=Bytes inn MyTrackerView.bytesinave=Gj.snitt inn MyTrackerView.bytesout=Bytes ut MyTrackerView.bytesoutave=Gj.snitt ut ConfigView.section.file.max_open_files=Maks antall pnede filer for lesing/skriving \n[0: ubegrenset] ConfigView.section.file.max_open_files.tooltip=Nyttig nr du laster ned torrenter som inneholder hundrevis/tusenvis av filer, og du nrmer deg grensen for operativsystemets filhndtering. ConfigView.section.proxy=Proxy valg ConfigView.section.proxy.enable_proxy=Aktiver proxy for tracker kommunikasjon [krever omstart] ConfigView.section.proxy.host=Tjener ConfigView.section.proxy.username=Brukernavn ConfigView.section.proxy.password=Passord ConfigView.section.proxy.enable_socks=Jeg har en SOCKS proxy wizard.createtorrent.extrahashes=Legg til hash for andre nettverk (f.eks. Gnutella2, eDonkey2000) GeneralView.label.connected=tilkoblet GeneralView.label.in_swarm=i sverm ManagerItem.initializing=Initialiserer AlertMessageBox.error=Feil AlertMessageBox.warning=Advarsel AlertMessageBox.comment=Informasjon AlertMessageBox.information=Informasjon AlertMessageBox.information=Du har uleste meldinger - klikk for vise dem. SharedPortServer.alert.selectorfailed=Kunne ikke opprette innkommende (lyttende) forbindelse for inkommende data. \nSjekk at brannmurinnstillingene aksepterer java(w).exe opptr som 'server' Tracker.alert.listenfail=Kunne ikke opprette inkommende forbindelse p port %1. \nSjekk at denne porten ikke er i bruk av andre programmer. \nOverprv at ikke en annen instans av Vuze kjrer. DiskManager.alert.movefileexists=Feil ved flytting av fullstendige filer. \nFilen %1 finnes allerede i mlmappen DiskManager.alert.movefilefails=Feil ved flytting av fullstendige filer. \nFlytting av filen %1 misslyktes, %2 DiskManager.alert.movefilerecoveryfails=Feil ved tilbakefring av flyttet fil. \nFlyttingen av filen %1 misslyktes, %2 ConfigView.section.tracker.logenable=Periodisk protokollfring (logging) til 'tracker.log' SpeedView.stats.title=Statistikker SpeedView.stats.session=Denne sesjon SpeedView.stats.session.tooltip=Totalt (Protokoll) SpeedView.stats.downloaded=Lastet ned SpeedView.stats.uploaded=Lastet opp SpeedView.stats.ratio=Rate SpeedView.stats.uptime=Oppetid SpeedView.stats.now=N SpeedView.stats.now.tooltip=Totalt (Protokoll) AutoMigration.useralert=Resultatet av Vuze sin automatiske migrering av bruker-konfigurasjonsfiler/-biblioteker:\n\n%1\nMislykkede auto-migreringer m overfres manuelt.\nHUSK OPPDATERE STIENE I KONFIGURASJONEN HVIS DE ER BLITT FLYTTET! OpenTorrentWindow.title=pnede torrent(er) OpenTorrentWindow.message=Eksperimentell OpenTorrentWindow.addFiles=Tilfy filer OpenTorrentWindow.dataLocation=Lagringssted for data: OpenTorrentWindow.startMode=Tilfy-modus OpenTorrentWindow.startMode.queued=Ventende OpenTorrentWindow.startMode.stopped=Stoppet OpenTorrentWindow.startMode.forceStarted=Tvungen start OpenTorrentWindow.addPosition=Vente-posisjon OpenTorrentWindow.addPosition.first=Frst OpenTorrentWindow.addPosition.last=Sist TableColumn.header.remaining.info=Gjenstende mengde laste ned TableColumn.header.remaining=Gjenstende ConfigView.section.tracker.enablecompact=Aktiver 'kompakt annonseringsprotokoll' ConfigView.section.tracker.enablekey=Aktiver sending av nkkel til tracker for kt sikkerhet ConfigView.section.file.perf=Ytelsesopsjoner ConfigView.section.file.perf.explain=Advarsel - ukyndige endringer av disse intillinger kan sl negativt ut p nedlastingshastigheten. Omstart ndvendig.\nDersom det oppstr 'out of memory'-problemer, begrens antall forbindelser per torrent (konfigurasjon av overfring). ConfigView.section.file.max_open_files.explain=pning av for mange filer kan forrsake problemer i opertativsystemet (dette p grunn av begrensede ressurser som foreksempel filhndtak). Dette begrenser antall av samtidig pnede filer. popup.error.hide=Skjul popup.error.details=Detaljer ConfigView.section.style.colorOverrides=Farge-overstyring ConfigView.section.style.colorOverride.progressBar=Fremdriftsvising ConfigView.section.style.colorOverride.error=Feil MainWindow.status.tooOld=er gammel, vennligst forny denne. ConfigView.section.style.colorOverride.warning=Advarsel ConfigView.section.style.colorOverride.altRow=Annen hver rekke ConfigView.section.file.save.peers.enable=Lagre kilde-forbindelser for rask gjenopprettelse av forbindelse. ConfigView.section.file.save.peers.max=Maks. antall forbindelser som lagres. [0: ubegrenset] ConfigView.label.max_peers_per_torrent=Maks. antall forbindelser per torrent som standard [0: ubegrenset] ConfigView.label.max_peers_total=Maks. antall forbindelser globalt [0: ubegrenset] ConfigView.section.style.colorOverrides.reset=Tilbakestill farger ConfigView.section.language.info=Dersom aktivert, vil det skes etter en nyere versjon hver gang Azuerus starter. ConfigView.section.language.enableUpdate=Benytt oppdatering via vev. ConfigView.section.language.UpdateURL=URL for oppdatering ConfigView.section.language.UpdateNow=Oppdater N! Button.revert=Angre endringer MyTorrentsView.menu.changeDirectory=Endre mlmappe GenericText.column=kolonne MyTorrentsView.menu.thisColumn.remove=Fjern kolonne MyTorrentsView.menu.thisColumn.toClipboard=Kopier tekst til utklippstavle MyTorrentsView.menu.thisColumn.autoTooltip=Vis alltid skjermtips ConfigView.download.abbreviated=Ned: ConfigView.upload.abbreviated=Opp: ConfigView.complete.abbreviated=K: TableColumn.header.secondsseeding=Komplettert siden TableColumn.header.secondsseeding.info=Forlpt tid etter at torrenten ble komplettert. TableColumn.header.secondsdownloading=Nedlastingstid TableColumn.header.secondsdownloading.info=Tid brukt p laste ned torrenten. ConfigView.section.tracker.udpversion=UDP protokollversjon (1 eller 2) window.updateswt.title=Din versjon av SWT er foreldet! window.updateswt.text=Din versjon av SWT er for gammel!\nSWT er det grafiske biblioteket Vuze benytter seg av. Nyeste versjon av Vuze krever en oppdatert versjon av SWT. Velg OK for oppdatere SWT. window.updateswt.failed=Oppdatering misslyktes, trykk OK for omstart av programmet. window.updateswt.status.downloading.updater=Oppdaterings-modul lastes ned window.updateswt.status.finding=Sker etter nyeste versjon av SWT window.updateswt.status.downloading=Laster ned nyeste versjon av SWT window.updateswt.status.done=Starter om window.updateswt.cancel=Avbryt swt.updater.downloader.downloading=SWT lastes ned fra swt.updater.urlsgetter.downloading=Mottar serverliste fra swt.updater.urlsgetter.platform=SWT for : window.updateswt.ignore=Ignorer ConfigView.section.style.useFancyTabs=Vis avrundede faner splash.initializeGM=Initialiserer 'Global Torrent Manager' splash.loadingTorrents=Laster torrenter MyTorrentsView.menu.thisColumn.sort=&Sorter Scrape.status.error=Scrape Error: Scrape.status.error.badURL=Annonserings-URL flger ikke scrape-spesifikasjoner. Scrape.status.error.nohash=Hash manlger i svarmelding. Scrape.status.error.invalid=Ugyldig svarmelding. Scrape.status.nextScrapeAt=Neste scrape om %1 Scrape.status.initializing=Venter p 'scrape'... Scrape.status.scraping.queued=Scrape klagt... Scrape.status.scraping=Scraping... ConfigView.label.minSpeedForActiveSeeding=Komplettert torrent opptar ingen slot dersom hastighet er mindre enn ConfigView.section.stats.exportpeers=Eksporter kildedetaljer MainWindow.menu.view.irc.moved=IRC er n tilgjengelig som et programtillegg, se http://azureus.sourceforge.net/plugin_list.php. Etter installasjonen ns denne under programtillegg->IRC menyen. MyTrackerView.webui.contextmenu.copyurl=Kopier gjeldende URL til utklippstavle. ConfigView.section.file.torrent.ignorefiles=Flgende filer blir ignorert ved opprettelse av torrenter\nf.eks. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignorerer fil ConfigView.section.style.useUnitsRateBits=Bruk bits istedet for bytes for byte-baserte verdier (KiB/s->Kibit/s osv.) ConfigView.section.interface.resetassoc=Tilbakestill tildeling av filtype (.torrent) ConfigView.section.interface.resetassocbutton=Tilbakestill ConfigView.section.interface.checkassoc=Sjekk filtype-tilknyttning ved oppstart dialog.associations.title=Sjekk av filtype-tilknyttning Button.yes=&Ja Button.no=&Nei ConfigView.label.seeding.autoStart0Peers=Start alle komplette torrenter uten kilder automatisk ConfigView.label.seeding.autoStart0Peers.tooltip=Aktiver dersom tracker alltid skal vise sendere for kildelse torrenter. dialog.associations.prompt=Vuze er ikke den forhndsvalgte applikasjon for BitTorrent filer.\nVil du knytte filtypen .torrent til Vuze dialog.associations.askagain=Sjekk ved oppstart ConfigView.section.plugins.update=Oppdatering av programtillegg Plugin.pluginupdate.enablecheck=Se etter nye oppdateringer av programtillegg plugins.basicview.activity=Aktivitet: plugins.basicview.progress=Fremskritt: plugins.basicview.log=Logg: splash.loadingTorrent=Laster torrent splash.of=av ConfigView.section.plugins.irc=Irc UpdateWindow.title=Oppdatering av Vuze UpdateWindow.header=Flgende komponenter trenger en oppdatering : UpdateWindow.columns.install=Installasjon UpdateWindow.columns.name=Navn UpdateWindow.columns.version=Versjon UpdateWindow.columns.size=Strrelse UpdateWindow.cancel=Avbryt UpdateWindow.quit=Avslutt UpdateWindow.close=Lukk UpdateWindow.ok=Oppdater UpdateWindow.restart=Omstart av Vuze n UpdateWindow.status.downloading=Laster ned UpdateWindow.status.done=Ferdig UpdateWindow.status.failed=Feilsltt UpdateWindow.status.restartNeeded=Omstart pkreves! ConfigView.pluginlist.broken=Defekt ConfigView.pluginlist.whereToPut=Plasser alle brukerspesifike programtillegg i egne mapper under: ConfigView.pluginlist.whereToPutOr=For felles programtillegg, bruk: MainWindow.statusText.checking=Sker etter oppdateringer TableColumn.header.OnlyCDing4.info=Forgtt tid siden torrenten ble komplett. Utelater tiden torrenten var under nedlasting (seeding). ConfigView.section.style.alternateTablePainting=Bruk alternativ metode for opptegning av tabellkolonner. (krever muligens omstart) UpdateWindow.status.restartMaybeNeeded=Omstart kan trenges ConfigView.pluginlist.shared=delt PeersView.host=Vertsnavn PeersView.host.info=Vertsnavn til kilde, nr tilgjengelig (kan pvirke ytelsen) MainWindow.menu.help.whatsnew=Hva er nytt? ConfigView.label.checkonstart=Se etter nyeste versjon nr Azuerus starter ConfigView.label.periodiccheck=Se etter nyeste versjon periodisk ConfigView.label.opendialog=pne oppdaterings-assistenten automatisk nr en oppdatering er tilgjenglig MainWindow.updateavail=(Tigjengelig oppdatering) MainWindow.status.latestversionunchecked=Versjon-sjekking deaktivert GeneralView.label.updatein.stopped=Stoppet StartStopRules.menu.viewDebug=Vis debug-informasjon ConfigView.section.style.doNotUseGB=Benytt ikke GB som enhet ConfigView.section.style.doNotUseGB.tooltip=Dersom aktivert, vil Vuze bruke MB ogs for verdier strre enn 1024MB MainWindow.menu.help.plugins=Programtillegg ConfigView.section.plugins.TrackerWeb=Tracker-Web ConfigView.section.tracker.enablecategories=Kategoriser torrenter ConfigView.section.tracker.createcert=Opprett selv-signert sertifikat ConfigView.section.tracker.createbutton=Opprett security.certcreate.title=Opprett selv-signert sertifikat security.certcreate.intro=Denne dialogen lar deg opprette et selv-signert sertifikat security.certcreate.strength=Styrke security.certcreate.firstlastname=For- og etternavn security.certcreate.orgunit=Organisatorisk enhet security.certcreate.org=Organisasjon security.certcreate.city=By eller sted security.certcreate.state=Fylke eller provins security.certcreate.country=Landskode (NO=Norge) security.certcreate.ok=Opprett security.certcreate.cancel=Avbryt security.certcreate.createok=Vellykket opprettelse av sertifikat security.certcreate.createfail=Sertifikat-opprettelse feilsltt ConfigView.section.plugins.webui=Swing vevgrensesnitt ConfigView.section.plugins.xml_http_if=XML/HTTP-grensesnitt webui.passwordenable=Bruk passord webui.user=Brukernavn webui.password=Passord webui.protocol=Protokoll (*) webui.homepage=Hjemmeside (*) webui.rootdir=Rotkatalog (*) webui.rootres=Rotressurs (*) webui.mode=Modus (*) webui.mode.info=Modus kan vre flgende\n\t"full"\t= alle operasjoner er tilgjenelige (standard)\n\t"visning"\t= kun visning (kan oppdatere oppdaterings-frekvens) webui.access=Aksess (*) webui.access.info=Aksess kan vre flgende\n\t"lokal"\t= kun lokale maskiner kan koble til\n\t"alle"\t= uinnskrenket aksess (standard)\n\tIP\t= f.eks. 192.168.0.2\t\t\tkun en IP-addresse\n\tIP1-IP2\t= f.eks. 192.168.0.1-192.168.0.255\tinklusivt adresseomrde GeneralView.label.maxdownloadspeed=Ned-grense GeneralView.label.maxdownloadspeed.tooltip=Maks nedlastingshastighet [0: ubegrenset] Security.keystore.corrupt=Lesing av "keystore" '%1' feilet. Vennligst slett den og opprett/importer sertifikatet p nytt Security.keystore.empty="Keystore" er tomt. Vennligst opprett et selv-signert sertifikat (Verkty > Konfigurasjon > Sikkerhet) eller importer et eksisterende sertifikat til '%1' webui.restart.info=Endring av parametere merket med (*) trenger omstart for tre ikraft upnp.enable=Aktiviser UPnP upnp.info=Universell Plug and Play (UPnP) tillater automatisk tildeling av porter p routere med UPnP-sttte. upnp.mapping.dataport=Innkommende dataport fra kilder upnp.mapping.tcptrackerport=TCP Tracker-port upnp.mapping.udptrackerport=UDP Tracker-port upnp.alert.differenthost=UPnP: Tildeling '%1' er allerede blitt tildelt '%2' - vennligst velg en annen port upnp.alert.mappingok=UPnP: Tildeling '%1' opprettet upnp.alert.mappingfailed=UPnP: Tildeling '%1' feilsltt upnp.alertsuccess=Vellykkede tildelinger upnp.alert.lostdevice=UPnP: Forbindelse til tjeneste '%1' p UPnP enhet '%2' upnp.grabports=Tildel porter som brukes av en annen datamaskin upnp.refresh.label=Oppdater tildelinger upnp.refresh.button=Oppdaterer upnp.alert.mappinggrabbed=UPnP: Tildeling '%1' opprettet - brukt fra '%2' upnp.mapping.tcpssltrackerport=TCP SSL Tracker-port upnp.alertothermappings=Rapporter porter brukt av andre maskiner upnp.alertdeviceproblems=Rapporter problemer med UPnP enheten +upnp.trace_to_log=Skriv full debuginformasjon til logg +upnp.wiki_link=Vuze Wiki-side om UPnP ConfigView.pluginlist.coreplugins=Flgende installerte programtillegg er lastet: Peers.column.DLedFromOthers=Fra andre Peers.column.DLedFromOthers.info=Mengde data lastet ned ifra andre mens tilkoblet til deg Peers.column.UpDownRatio=Opp:Ned Peers.column.UpDownRatio.info="Opp:Ned" forhold til kilde Peers.column.UpRatio=Opp-forhold Peers.column.UpRatio.info="Opplasting ifra deg : Opplasting ifra andre" forhold til kilde upnp.releasemappings=Frigjr tildelinger ved slutt webui.upnpenable=Aktiviser UPnP for denne porten (*) ConfigView.section.file.friendly.hashchecking="Sknsom hash-sjekking" ConfigView.section.file.friendly.hashchecking.tooltip=En litt langsomre hash-metode, men som frer til mindre last p prosessor/system. ConfigView.section.tracker.seedretention=Maks benyttede komplette kilder (sendere) per torrent [0: ubegrenset] ConfigView.section.tracker.seedretention.info=NB: Oppplastingstatistikk til ikke benyttede komplette kilder vil bli borte ConfigView.section.tracker.port=Aktiviser tracker p HTTP-port ConfigView.section.tracker.sslport=Aktiviser tracker p HTTPS-port ConfigView.section.tracker.publicenable.info=Dette tillater andre lage torrenter som bruker din tracker\nuten at du selv hoster eller publiserer disse Button.clear=Nullstill MainWindow.IPs.tooltip=Antall IP-omrder i filterliste - Antall faktisk blokkerte IPer ConfigView.section.ipfilter.list.banned=har blitt sperret ConfigView.section.ipfilter.list.baddata=har sendt falske data: tilfeller = Button.reset=Tilbakestill ConfigView.section.ipfilter.bannedinfo=IPer som har send falske data - sperres dersom grense overskrides ConfigView.section.ipfilter.blockedinfo=IPer som er blitt blokkert p bakgrunn av IP-filtere download.removerules.name=Fjerninsregler download.removerules.unauthorised.info=Uautoriserte torrenter er de hvor annonseringsresponsen inneholder enten "not authoris(z)ed" eller "unauthoris(z)ed" i "failure response" download.removerules.unauthorised=Automatisk fjerning av uautoriserte torrenter download.removerules.unauthorised.seedingonly=Bare nr komplett download.removerules.removed.ok=Velykket fjerning av torrenten '%1'. Dette p bakgrunn av automatisk fjerningsregel. download.removerules.updatetorrents=Fjern oppdaterings-torrenten for Vuze ettersom svermen trenger disse ConfigView.label.defaultstarttorrentsstopped=Legg til nye torrenter i stoppet tilstand som standard ConfigView.section.server.enableudp=Aktiver UDP tracker klient-protokoll upnp.mapping.dataportudp=UDP tracker klient-port ConfigView.section.file.decoder.showlax=Vis mindre vanlige kodinger ConfigView.section.file.decoder.showall=Vurder alle mulige kodinger MainWindow.status.updowndetails.tooltip=Hastighetsdetaljer for opp- og nedlasting. \nHyreklikk for endringer, dobbeltklikk for statistikk. TrackerClient.announce.warningmessage=Tracker for '%1' sendte advarselen '%2' ConfigView.section.tracker.natcheckenable=Overprv tilkoblingsevne til innkommende port og send feilmelding til kilder (peers) ConfigView.section.tracker.publishenabledetails=Publiser torrentfil og kildedetaljer ConfigView.section.tracker.publishenablepeerdetails=Publiser kildedetaljer MyTrackerView.badnat=Feil i NAT MyTrackerView.badnat.info=Kilder som feilet en nat-sjekk, hvis aktivisert ConfigView.section.tracker.natchecktimeout=Tidsoverskrivelse til sjekk (sek) ConfigView.section.file.perf.cache.enable=Aktiver mellomlagring til disk ConfigView.section.file.perf.cache.size=Strrelse til mellomlager i %1 MainWindow.menu.transfers=Overf&ringer MainWindow.menu.transfers.startalltransfers=St&art alle MainWindow.menu.transfers.stopalltransfers=St&opp alle MainWindow.menu.transfers.resumetransfers=&Fortsett ConfigView.label.experimental.osx.kernel.panic.fix=Eksperimentell lsning mot kernel-problemer p dual-cpu OSX systemer [krever omstart] SystemTray.menu.pausetransfers=Pausr overfringer SystemTray.menu.resumetransfers=Fortsett overfringer ConfigView.section.file.truncate.too.large=Kort ned filer som er for store ConfigView.section.file.perf.cache.trace=Flg mellomlagrings-operasjoner til diagnoseforml ConfigView.section.interface.enabletray=Aktiviser "System Tray" [krever omstart] PeerManager.status.error=Feil Stats.title.full=Statistikk TransferStatsView.title.full=Overfringer CacheView.title.full=Buffer CacheView.general.size=Total strrelse CacheView.general.inUse=I bruk CacheView.general.title=Mellomlager-informasjon CacheView.reads.title=I/U lest CacheView.reads.fromFile=Fra fil CacheView.reads.fromCache=Fra mellomlager CacheView.reads.hits=Treff CacheView.writes.title=I/U skrevet CacheView.writes.toCache=Til mellomlager CacheView.writes.toFile=Til fil CacheView.writes.hits=Lagret CacheView.speeds.title=Data-rater CacheView.speeds.reads=Lest CacheView.speeds.writes=Skrevet CacheView.speeds.fromCache=Fra/til mellomlager CacheView.speeds.fromFile=Fra/til fil CacheView.reads.amount=Mengde CacheView.reads.avgsize=Gj.sn. strrelse openUrl.referrer=Henvist side URL: openUrl.referrer.info=Kun ndvendig for nettsteder som krever dette ConfigView.label.maxuploadspeedseeding=Alternativ verdi nr man kun deler (seeding) ConfigView.label.transfer.ignorepeerports=Ignorer kilder med flgende data-porter (';'-separert. F.eks. 0;25) ConfigView.section.proxy.enable_socks.peer=Tillat 'proxying' av kommunikasjon mellom kilder (peers) (kun utgende forbindelser) [krever omstart] ConfigView.section.proxy.peer.informtracker=Opplys tracker om begrensning ConfigView.section.proxy.socks.version=SOCKS versjon PiecesView.legend.written=Skrevet PiecesView.legend.requested=Forespurt PiecesView.legend.downloaded=I pvente av skriving PiecesView.legend.incache=Data er mellomlagret PiecesView.typeItem.0=Langsom PiecesView.typeItem.1=Rask Security.jar.tools_not_found=JAR-signering feilsltt - 'tools.jar' ikke funnet i %1. Se Verkty > Konfigurasjon > Sikkerhet for datajer. Security.jar.signfail=JAR-signering feilsltt - %1 ConfigView.section.security.toolsinfo=Signerte JAR-filer blir brukt av noen programtillegg, f.eks. Swing vev-grensesnitt (dersom konfigurert).\nFor signere JAR-filer er tilgang til filen 'tools.jar' som flger med intallasjonen til Sun JDK (ikke JRE) pkrevd.\nDersom du kun har installert JRE, vennligst installer da JDK.\nVuze finner vanligvis filen for deg. Skulle imiddlertid dette sl feil, kan du eksplisitt sette mlmappen selv. ConfigView.section.security.toolsdir=Mappe som inneholder 'tools.jar' ConfigView.section.security.choosetoolssavedir=Velg mappe som inneholder 'tools.jar' ConfigView.section.proxy.peer.same=Bruk samme proxy-innstillinger for tracker og kommunikasjonsproxy ConfigView.section.connection.network.max.simultaneous.connect.attempts=Maks samtidige utgende forbindelsesforsk [0: deaktiverer utgende] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Maks antall nye utgende forbindelser Vuze til en hver tid kan initiere.\nMERK: Windows XP Service Pack 2 (SP2) plegger en grense for hele systemet p 10 samtidige forbindelsesforsk.\nStandard verdi er 8. Verdien 0 deaktiverer alle forsk p utgende forbindelser. ConfigView.section.file.perf.cache.size.explain=Mellomlager blir brukt for redusere antall diskaksesser. Med mindre du bruker javaopsjonen '-XX:MaxDirectMemorySize' som ekplisitt angir tilgjengelig minne for mellomlagring og nettverks IO, burde du holde denne verdien til minst %1 under maksimal strrelse av VM. Den gjeldende maksimale strrelse til VM er %2. For veiledning om hvordan du forandrer dette, se 'MemoryUsage' p wiki: %3. Ufornuftige verdier til innstillingen vil resultere i 'out of memory' feil. Mer en 32MB mellomlager er antakeligvis overdrevent. MyTorrentsView.menu.setSpeed.unlimit=Uten grenser MyTorrentsView.menu.setSpeed.unlimited=Ubegrenset MyTorrentsView.menu.setSpeed.disable=Deaktiver opplasting MyTorrentsView.menu.setSpeed.disabled=Deaktivert MyTorrentsView.menu.setSpeed.in=inn MyTorrentsView.menu.setSpeed.slots='slots' av GeneralView.label.maxuploadspeed=Opp-grense GeneralView.label.maxuploadspeed.tooltip=Maks opplastingshastighet [0: ubegrenset] MyTorrents.items.UpSpeedLimit.disabled=Ingen opplasting MyTorrents.items.UpSpeedLimit.unlimited=Ubegrenset TableColumn.header.maxupspeed=Maks opplastingshastighet TableColumn.header.maxupspeed.info=Maks opplastingshastighet per torrent ConfigView.section.file.perf.cache.enable.write=Mellomlagre nedlastingsdata for redusering av skriveaksesser og samtidig redusering av lese aksesser ved sjekking av bruddstykker ConfigView.section.file.perf.cache.enable.read=Utfr "read-aheads" for redusering av diskaksesser ved opplasting ConfigView.section.tracker.separatepeerids=Benytt ulike kilde-identiteter for tracker- og datakommunikasjon ConfigView.section.tracker.separatepeerids.info=ker anonymitet ved anonym nedlasting/spredning\n ved bruk av en ikke-anonym trackerforbindelse ConfigView.section.interface.wavlocation=Lagersted til .wav fil ConfigView.section.interface.wavlocation.info=Velg .wav fil eller la st tom for standard lyd ConfigView.section.tracker.client=Klient ConfigView.section.tracker.client.connecttimeout=Timeout til forbindelse (sek) ConfigView.section.tracker.client.readtimeout=Timeout for lesing (sek) MainWindow.menu.tools=&Verkty FilesView.path=Sti FilesView.fullpath=Vis fulstendig sti FilesView.remaining=Gjenstende bruddstykker TableColumn.header.trackername=Trackernavn TableColumn.header.trackername.info=Beskrivelse av tracker basert p annonserings-URL ConfigView.group.override=Overstyr valg ConfigView.section.file.perf.cache.notsmallerthan=Ikke bruk mellomlagring for filer mindre enn (i %1) PeersView.menu.blockupload=Blokker opplasting PeersView.menu.kickandban=Kick og sperr PeersView.menu.kickandban.reason=Kilde sperret manuelt PeersView.state=Status PeersView.state.info=Forbindelsesstatus (til kilder) PeersView.state.pending=Venter p data PeersView.state.connecting=Kobler til PeersView.state.handshake=Venter p 'handshake' PeersView.state.established=Forbindelse opprettet ConfigView.section.tracker.processinglimits=Prosesserings-grenser ConfigView.section.tracker.maxgettime=Maks tidsforbruk for GET prosessering (sek) [0: ubegrenset] ConfigView.section.tracker.maxgettime.info=Brukes ved annonseringer og 'scrape' ConfigView.section.tracker.maxposttimemultiplier=GET-tid multiplikator for POST prosessering [0: ubegrenset] ConfigView.section.tracker.maxposttimemultiplier.info=Brukes ved 'form'-forsendelser og opplastinger ConfigView.section.tracker.maxthreads=Maks samtidige foresprsler DownloadManager.error.operationcancancelled=Operasjon avbrutt Torrent.create.progress.cancelled=Operation avbrutt sharing.progress.cancel=Avbryt wizard.maketorrents.autoopen=pne torrenten for deling nr ferdig ConfigView.section.sharing.rescanenable=Aktiver periodisk gjennomgang av delinger etter endringer ConfigView.section.sharing.rescanperiod=Intervall for gjennomgang (sek) ConfigView.section.connection.advanced=Avanserte nettverksinnstillinger ConfigView.section.connection.advanced.mtu=Linjens 'Maximum Transmission Unit' (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Maksimal pakkestrrelse som kan overfres i en 'frame' over nettverket.\nVuze bruker MTU-40 (MSS) for optimalisering av payload til opplastings-pakker.\nAnbefalte verdier:\n 576 - Oppringte-forbindelser (dial-up)\n 1492 - PPPoE bredbnds-forbindelser\n 1500 - Ethernet, DSL and Cable bredbnds-forbindelser ConfigView.section.connection.advanced.SO_RCVBUF=Socket SO_RCVBUF strrelse [0: bruk standard for OS] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Angir standard SO_RCVBUF socket verdi (i byte), dvs. TCP vindustrrelse og vekt (mottak).\nStandardinnstillinger i Vuze setter denne tom, noe som vil si at underliggende standardverdier i OS benyttes.\nNB: Linux dobbler angitt verdi. ConfigView.section.connection.advanced.SO_SNDBUF=Socket SO_SNDBUF strrelse [0: bruk standard for OS] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Angir standard SO_SNDBUF socket verdi (i byte), dvs. TCP vindustrrelse og vekt (sending).\nStandardinnstillinger i Vuze setter denne tom, noe som vil si at underliggende standardverdier i OS benyttes.\nNB: Linux dobbler angitt verdi. ConfigView.section.connection.advanced.IPTOS=Utgende pakke 'type-of-service' (TOS) ConfigView.section.connection.advanced.IPTOS.tooltip=Angir type trafikk / "type-of-service" (TOS) felt i IP header for utgende pakker.\nStandardinnstillinger i Vuze setter denne tom, noe som vil si at underliggende standardverdier i OS benyttes.\nEksempelverdier:\n0x02 for IPTOS_LOWCOST\n0x04 for IPTOS_RELIABILITY\n0x08 for IPTOS_THROUGHPUT\n0x10 for IPTOS_LOWDELAY\nNB: Unerliggende netverksimplementasjoner kan ignorere disse verdiene, s dette valget er avhengig av OS og JRE versjon. ConfigView.section.interface.confirm_torrent_removal=Vis bekreftelsesdialog ved fjerning av torrent ConfigView.section.interface.confirm_torrent_removal.tooltip=Forlanger bekreftelse ved fjerning av en torrent ifra visning i 'Mine torrenter'. MyTorrentsView.confirm_torrent_removal=Vil du virkelig fjerne torrenten? TableColumn.header.seed_to_peer_ratio.info=Forhold mellom komplette kilder og ufullstendige kilder i sverm PeersView.connected_time=Tilkoblingstid PeersView.connected_time.info=Total tid tilkoblet kilde ConfigView.section.interface.display.add_torrents_silently=Legg til torrenter automatisk (uten brukerinteraksjon) ConfigView.section.interface.display.add_torrents_silently.tooltip=Legger til nye nedlastinger uten aktivering av hovedvinduet til Azureus. TableColumn.header.maxdownspeed=Maks nedlastingshastighet TableColumn.header.maxdownspeed.info=Maks nedlastingshastighet per torrent PeersGraphicView.title=Sverm ConfigView.section.tracker.passwordwebhttpsonly=Tillat tilgang kun via HTTPS TableColumn.header.torrentpath=Torrent-sti TableColumn.header.torrentpath.info=Lokal lagringssti til torrent ConfigView.section.sharing.torrentcomment=Kommentar for genererte torrenter ConfigView.label.copyanddeleteratherthanmove=Kopier frst, for s slette originale data i stedet for gjre alt i en operasjon. Dette kan hjelpe noen filsystemer mot tap av data. ConfigView.label.openstatsonstart=pne statistikk ved start swt.install.window.title=Installasjon av programtillegg for Vuze swt.install.window.ok=Installer swt.install.window.header=Flgende komponenter er blitt valgt for installering: swt.uninstall.window.title=Fjerning av programtillegg for Vuze swt.uninstall.window.ok=Fjern swt.uninstall.window.header=Flgende komponenter er blitt valgt for fjerning: installPluginsWizard.title=Installer programtillegg installPluginsWizard.mode.title=Vennligst velg en installeringsmetode installPluginsWizard.mode.list=Ved filer listet p sourceforge.net installPluginsWizard.list.title=Liste over installerbare plugins installPluginsWizard.list.loading=Vennligst vent mens listen blir lastet... installPluginsWizard.list.loaded=Vennligst velg de programtillegg du nsker installere. installPluginsWizard.list.name=Navn installPluginsWizard.list.version=Versjon installPluginsWizard.list.description=Beskrivelse installPluginsWizard.finish.title=Installasjonens fremdrift installPluginsWizard.finish.explanation=Valgte programtillegg vil bli installert med hjelp av 'Update Assistant'.\n\nVennligst ha litt tolmodighet da det kan ta noen sekunder fr den kommer til syne.\n\nFor fremdrift-rapport, vennligst dobbelklikk til venstre for statusvisningen. installPluginsWizard.details.loading=Laster detaljer, vennligst vent... installPluginsWizard.mode.file=Etter fil installPluginsWizard.installMode.title=Vennligst velg installasjonstype installPluginsWizard.installMode.user=Installer programtillegg kun for aktuell bruker installPluginsWizard.installMode.shared=Installer programtillegg for alle brukere installPluginsWizard.file.title=Vennligst velg et programtillegg for installering installPluginsWizard.file.file=Fil: installPluginsWizard.file.invalidfile=Filen er ikke et gyldigt programtillegg for Azureus. installPluginsWizard.file.no_such_file=Ingen fil eksisterer med angitt navn. installPluginsWizard.file.browse=Utforsk... uninstallPluginsWizard.title=Avinstaller programtillegg uninstallPluginsWizard.list.title=Liste over installerte programtillegg uninstallPluginsWizard.list.loaded=Vennligst velg de programtilleggene du vil avinstallere. installPluginsWizard.list.nullversion=Ingen versjon uninstallPluginsWizard.finish.title=Avinstallasjon under fremdrift uninstallPluginsWizard.finish.explanation=Det valgte programtillegg vil bli avinstallert ved hjelp av 'Update Assistant'. MainWindow.menu.plugins.installPlugins=Veiviser for installering MainWindow.menu.plugins.uninstallPlugins=Veiviser for avinstallering ConfigView.section.ipfilter.totalIPs=Totalt sperret %1 IPer; -det er %2 av Internett. update.instance.install=Kontrollerer installering update.instance.uninstall=Kontrollerer avinstallering update.instance.update=Sker etter nye oppdateringer MainWindow.status.update.tooltip=Dobbelklikk for fremdriftsinformasjon updater.progress.window.title=Lpende installasjonsprosesser updater.progress.window.info=Trykk 'Avbryt' for avslutte alle lpende installasjonsprosesser. Button.abort=Avbryt ConfigView.section.ipfilter.enablebanning=Blokker kilder som stadig sender feilaktige data Network.alert.acceptfail=For mange pflgende feil oppsto p port %1, %2 - prosess avbrutt. Vennligst overprv brannmurinnstillinger for denne porten, og stadfest om denne porten er pnet for inngende forbindelser. MyShares.column.category=Kategori UpdateWindow.restartLater=Omstart av Vuze senere MainWindow.menu.file.restart=Omstart MainWindow.dialog.restartconfirmation.title=Starte om Vuze MainWindow.dialog.restartconfirmation.text=Vil du virkelig starte om Vuze deletetorrent.message1=Torrenten blir slettet: deletetorrent.message2=\n\u00d8nsker de fortsette? ConfigView.label.prioritizemostcompletedfiles=Prioriter ytterlige hy-prioritets filer i forhold til % ferdigstillelse og filstrrelse splash.plugin.init=Initialiserer programtillegg: ConfigView.section.style.osx_small_fonts=Bruk sm fonter [krever omstart] ConfigView.section.tracker.tcpnonblocking=Bruk 'non-blocking' I/U for TCP tracker prosessering. Denne lsningen krever at "tracker web" blir kjrt p en alternativ port. Eksperimentellt! ConfigView.section.tracker.nonblocking=Non-blocking alternativer ConfigView.section.tracker.nonblockingconcmax=Maks samtidige forbindelser [0: ubegrenset] MyTorrentsView.menu.exportmenu=Eksporter ConfigView.section.tracker.client.scrapeinfo=Deaktivasjon av scraping vil hindre mange av torrentens kregler i fungere, da disse baserer seg p sverminformasjon via scraping trackere. ConfigView.section.tracker.client.scrapeenable=Aktiviser scraping ConfigView.section.tracker.client.scrapestoppedenable=Scrape torrenter som ikke kjrer Scrape.status.disabled=Scrape deaktivert MyTorrentsView.menu.explore=Vis fil MyTorrentsView.menu.explore._mac=Vis i Finder MyTorrentsView.menu.explore._windows=Vis i Utforsker/Explorer wizard.maketorrents.autohost=Host torrenten i innebygd tracker ConfigView.label.overrideip=Overstyr trackerens annonserings-IP(er) - semikolon for skille dersom man har flere adresser mot forkjellige nettverk ConfigView.label.overrideip.tooltip=Informer tracker om annnen IP-addresse(r) enn det utgende pakker kommer fra. La st tomt for ikke benytte dette. ConfigView.section.connection.group.networks=Nettverk ConfigView.section.connection.group.networks.info=Velg de vanlige nettverk som er tillatt for 'peer-to-peer' dataoverfringer ConfigView.section.connection.networks.prompt=Spr for valg nr en legger til en nedlasting med anonym tracker ConfigView.section.connection.networks.Public=Offentlig IP-nett (ikke anonymt) ConfigView.section.connection.networks.I2P=I2P nettverk TableColumn.header.networks=Nettverk TableColumn.header.networks.info=Tillate nettverk for 'peer-to-peer' datakoverfring Scrape.status.networkdisabled=Nettverk ikke aktivert ConfigView.section.tracker.server.group.networks=Nettverk ConfigView.section.tracker.server.group.networks.info=Velg de nettverk som tracker vil akseptere kilder ifra window.networkselection.title=Valg av nettverk window.networkselection.info=Torrenten vist nedenfor har trackere som sttter flgende nettverk.\nVelg nettverk for starte kommunikasjon med andre kilder.\nDersom trackeren er anonym og sttter 'public clients', velg da bde anonymt og offentligt nettverk. \nAktivering av offentligt nettverk har den penbare egenskapen av fjerne anonymiteten din! window.networkselection.description=Torrent: plugins.basicview.clear=Tm ConfigView.section.connection.group.peersources=Kilder (peers) ConfigView.section.connection.group.peersources.info=Velg basis-kilder for kommunikasjon ConfigView.section.connection.peersource.Tracker=Fra en tracker ConfigView.section.connection.peersource.DHT=Desentralisert tracker ConfigView.section.connection.peersource.PeerExchange=Gitt av en annen kilde ConfigView.section.connection.peersource.Plugin=Lagt til av et programtillegg ConfigView.section.connection.peersource.Incoming=Innkommende forbindelse PeersView.source=Kildeadresse PeersView.source.info=Addressen til denne kilden TableColumn.header.peersources=Kildeadresser TableColumn.header.peersources.info=Nettverkskilder tillatt for initiering av forbindelser til kilder wizard.tracker.dht=Desentralisert (kun Azureus-klienter) MyTorrentsView.menu.advancedmenu=Avansert MyTorrentsView.menu.networks=Nettverk MyTorrentsView.menu.peersource=Nettverkskilder for kilder ConfigView.section.sharing.permitdht=Tillat desentralisert tracking nr tracker ikke er tilgjengelig ConfigView.section.sharing.protocol=Protokoll for delte ressurser PeersView.Messaging=Meldingsformidling PeersView.Messaging.info=Sttter "advanced messaging API". ConfigView.label.queue.newseedsmovetop=Flytt nettopp ferdigstilte torrenter til toppen av delingsliste ConfigView.label.seeding.firstPriority.ignore.info=Ver oppmerksom p at disse reglene kan fre til stansing av en torrent\ns snart at nedlastingen blir ferdigstillt. ConfigView.label.seeding.firstPriority.ignore=Ignorer ovenstende regler for frsteprioritet ved: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrenter med en "Sendere til Kilde"-forhold strre enn ConfigView.label.seeding.firstPriority.ignore0Peer=Torrenter med 0 kilder ConfigView.section.tracker.sendjavaversionandos=Send Java-versjon og OS-navn MagnetPlugin.contextmenu.exporturi=Kopier "Magnet URI" til utklippstavle ConfigView.section.plugins.dht=Distribuert DB dht.info=Programtillegget sttter blant annet desentralisert tracking - deaktivasjon av dette vil redusere din nedlastingsevne dht.enabled=Aktiver distribuert database dht.portdefault=Bruk standard port dht.port=UDP-port for datasbase dht.execute.command=Diagnose-kommando dht.execute.info=Trykk for eksekvering av denne kommando dht.execute=Kjr dht.logging=Aktiver registreing av aktivitet ConfigView.section.plugins.dhttracker=Distribuert tracker dhttracker.tracknormalwhenoffline=Track kun vanlige torrenter nr tracker ikke er tilgjengelig ConfigView.section.file.nativedelete._mac=Benytt 'Papirkurv' ved sletting av filer ConfigView.section.file.nativedelete._windows=Flytt slettede filer til operativsystemets 'Papirkurv' ConfigView.section.logging.netinfo=Generer nettverks-info ConfigView.section.logging.statsinfo=enerer stats-info ConfigView.section.logging.generatediagnostics=Generer ConfigView.section.logging.generatediagnostics.info=Opprett diagnose-informasjon og kopier dette til bde utklippstavle og loggfil. ConfigView.section.sharing.privatetorrent=Privat torrent - godkjenn kun kilder fra trackeren MainWindow.menu.tools.nattest=&NAT / brannmur-test Button.apply=Bruk Button.close=Lukk window.welcome.title=Velkommen til Vuze %1 MainWindow.menu.help.releasenotes=Versjonsmerknader dht.reseed.label=Vanligvis er ikke 'reseeding' av distribuert database ndvendig. Dersom antall kilder er lite, kan dette bli brukt til re-integrasjon.\nLa st tomt for bootstrap utenom tilkoblede kilder, eller angi IP og port for eksplisitt bootsrap ifra kjent kilde (peer). dht.reseed.ip=IP-adresse dht.reseed.info=Reseed database dht.diagnostics.group=Diagnostikk DHTView.title.full=Distribuert Database DHTView.title.fullcvs=Distribuert Database CVS DHTView.general.title=Generelt DHTView.general.uptime=Oppetid: DHTView.general.users=Brukere: DHTView.general.nodes=Noder: DHTView.general.leaves=Bladnoder: DHTView.general.contacts=Kontakter: DHTView.general.replacements=Erstattinger: DHTView.general.live=Levende: DHTView.general.unknown=Ukjent: DHTView.general.dying=Dende: DHTView.transport.title=Transport-detaljer DHTView.transport.packets=Pakker DHTView.transport.received=Mottatt DHTView.transport.sent=Sendt DHTView.transport.in=Inn: DHTView.transport.out=Ut: DHTView.operations.title=Operasjonsdetaljer DHTView.operations.sent=Sendt DHTView.operations.failed=Feilsltt DHTView.operations.received=Mottatt DHTView.operations.findNode=Finn node DHTView.operations.findValue=Finn verdi DHTView.operations.store=Lagre DHTView.activity.title=Aktivitet DHTView.activity.status.true=I k DHTView.activity.status.false=Kjrer DHTView.activity.type.1=Intern GET DHTView.activity.type.2=Ekstern GET DHTView.activity.type.3=Intern PUT DHTView.activity.type.4=Ekstern PUT DHTView.activity.target=Ml DHTView.activity.details=Detaljer DHTView.db.keys=Nkler DHTView.db.values=Verdier DHTView.db.local=Lokal DHTView.db.direct=Direkte DHTView.db.indirect=Indirekte DHTView.db.divfreq=Frekv. div. DHTView.db.divsize=Strrelse div. MainWindow.dht.status.tooltip=Nr distribuert database kjres, vises et estimert antall brukere som er pkoblet MainWindow.dht.status.disabled=DHT feaktivert MainWindow.dht.status.failed=DHT feilsltt MainWindow.dht.status.initializing=DHT initialiserer MainWindow.dht.status.users=%1 brukere MainWindow.dht.status.unreachable=DHT stoppet av brannmur MainWindow.dht.status.unreachabletooltip=Det ser ut til vre et problem med UDP portmappingen til den distribuerte databasen (NAT/brannmur) MyTorrentsView.menu.setUpSpeed=Sett opp-hastighet MyTorrentsView.menu.setDownSpeed=Sett ned-hastighet ConfigView.section.tracker.client.showwarnings=Vis varslingsbeskjeder fra tracker dht.advanced=Aktiver avanserte innstillinger dht.advanced.group=Avanserte innstillinger dht.advanced.label=Juster disser verdiene dersom du VIRKELIG vet hva du gjr dht.override.ip=Overstyr ekstern IP-adresse ConfigView.section.logging.loggerenable=Aktiviser logging ConfigView.section.ipfilter.blockbanning=Sperr hele blokken av 256 adresser nr minst dette antallet i blokken allerede er sperret MyTrackerView.passive=Passiv TableColumn.header.swarm_average_speed=Gjennomsnittshastighet til sverm TableColumn.header.swarm_average_speed.info=Den gjennomsnittlige hastigheten til kilder i svermen TableColumn.header.comment=Kommentar TableColumn.header.comment.info=Brukerdefinert kommentar for nedlasting TableColumn.header.commenticon=Kommentar-ikon TableColumn.header.commenticon.info=Ikon vises dersom nedlastingen har en brukerkommentar MyTrackerView.category=Kategori MainWindow.menu.file.open.torrentfortracking=.torrent fil (kun tracking) MyTrackerView.date_added=Lagt til ConfigView.section.tracker.portbackup=Reserveporter (adskilt med ';') ConfigView.label.playfilespeech=Talelyd idet en fil ferdigstilles ConfigView.label.playfilespeech.info="Speec Services" stttes best for engelsk ConfigView.label.playfilefinished=Spill en lyd nr en fil er ferdig ConfigView.label.backupconfigfiles=Backup konfigurasjonsfiler for bergingshensikter ConfigView.section.tracker.client.scrapesingleonly=Deaktiver per-tracker scrape aggregasjon (kan hjelpe trackere som gir 'URL too long' 414 feilmeldinger) dht.ipfilter.log=Logg overtredelser til IP-filter ConfigView.label.seeding.addForSeedingDLCopyCount=Overvei 'add for seeding' nedlastinger ved ha lastet ned dette antall kopier ActivityView.legend.limit=Grense-rate ActivityView.legend.achieved=Oppndd rate ActivityView.legend.peeraverage=Gjennomsnitt ActivityView.legend.swarmaverage=Gjennomsnitt i sverm ActivityView.legend.trimmed=Trimmet (prikket) MyTorrentsView.menu.movemenu=Flytt filer MyTorrentsView.menu.movedata=Flytt datafiler MyTorrentsView.menu.movetorrent=Flytt torrent-fil... MyTorrentsView.menu.movedata.dialog=Velg ny lokalisering DHTView.general.reachable=Tilgjengelig: DHTView.general.rendezvous=Samlingssted: ConfigView.label.queue.maxactivetorrentswhenseeding=Maks ved kun deling [0: ubegrenset] Views.plugins.IRC.title=IRC - Teknisk support online Formats.units.persec=/sek Formats.units.alot=En hel del! ConfigView.section.ipfilter.persistblocking=Husk blokkerte IP-adresser mellom hver omstart FilesView.rename.choose.path=Velg ny eller eksisterende fil FilesView.menu.rename=Gi nytt navn eller plassering FilesView.menu.rename_only=Omdp FilesView.menu.retarget=Flytt FilesView.rename.choose.path=Velg en ny eller eksisterende fil FilesView.rename.choose.path.dir=Velg en ny eller eksisterende mappe FilesView.rename.confirm.delete.title=Bekreft sletting FilesView.rename.confirm.delete.text=Bekreft sletting av originalfilen '%1' FilesView.rename.filename.title=Gi nytt filnavn FilesView.rename.filename.text=Velg nytt navn for filen ConfigView.section.mode=Modus ConfigView.section.mode.title=Brukerkyndighet ConfigView.section.mode.beginner=Nybegynner ConfigView.section.mode.beginner.wiki.definitions=BitTorrent ordliste ConfigView.section.mode.intermediate=Viderekommen ConfigView.section.mode.intermediate.wiki.host=Hvordan 'hoste' filer ConfigView.section.mode.intermediate.wiki.publish=Hvordan publisere filer ConfigView.section.mode.advanced=Avansert ConfigView.section.mode.advanced.wiki.main=Wiki hovedside ConfigView.section.mode.beginner.text=Alt du trenger for laste ned torrenter. \nBruk denne modus dersom alt du trenger er hndtere torrenter. ConfigView.section.mode.intermediate.text=pner tilgang til tracker funksjonalitet. \nBenytt denne modus dersom du vil opprette din egen tracker og hoste/publisere dine filer. ConfigView.section.mode.advanced.text=pner tilgang til nettverksinnstillinger. \nBruk denne modus dersom du vet hva MTU og non-blocking I/U innebrer... Files.column.storagetype=Lagringstype Files.column.fileext=Filtype FileItem.storage.linear=Liner FileItem.storage.compact=Kompakt MessageBoxWindow.rememberdecision=Husk mitt valg ConfigView.section.interface.cleardecisions=Fjern mellomlagrede dialogvalg ConfigView.section.interface.cleardecisionsbutton=Fjern ConfigView.section.interface.cleartrackers=Fjern mellomlagrede trackere ConfigView.section.interface.cleartrackersbutton=Fjern ConfigView.section.interface.clearsavepaths=Fjern mellomlagrede lagringsstier ConfigView.section.interface.clearsavepathsbutton=Fjern configureWizard.welcome.usermodes=Denne innstillingen tilpasses kyndighetsnivet til bruker, og bestemmer antall innstillinger vist under Verkty > Konfigurasjon. Still inn denne til hva som er riktigt niv for deg. FilesView.skip.confirm.delete.text=Kort av filen '%1' for spare plass? FilesView.rename.failed.title=Forandring av navn/sti feilet FilesView.rename.failed.text=Denne operasjonen feilet, sannsynligvis p grunn av feilaktig mlangivning diagnostics.log_found=Vuze ble ikke avsluttet p riktig mte. Vennligst overprv %1 for en diagnose av logg-filer og overvei rapportering av dem til Azureus-teamet dersom dette er et resultat av en program-feil. ManagerItem.paused=Pause Utils.link.visit=Vennligst besk ConfigView.section.connection.serverport.wiki=Gode portvalg ConfigView.section.transfer.speeds.wiki=Innstillinger for god hastighet installPluginsWizard.installMode.info.title=Informasjon installPluginsWizard.installMode.info.text=Du behver ikke noen programtillegg for at Vuze skal virke. De tilfyer derimot utfyllende innslag som underholdning, automatiskering og fjernstyring. \nVennligst studer beskrivelsen av programtilleggene nye, fr du bestemmer deg for installere. \nDe fleste tillegg er helt trygge prve ut, bare man ikke overlesser konfigurasjonen med programtillegg som ikke blir brukt. Views.plugins.Distributed.DB.title=Distribuert DB Views.plugins.Distributed.Tracker.title=Distribuert tracker Views.plugins.Plugin.Update.title=Oppdatering av programtillegg openUrl.url.info=Sttter http, https, magnet og raw hex infohash strenger TableColumn.header.swarm_average_completion=Gjennomsnittlig ferdigstillelse til kilder TableColumn.header.swarm_average_completion.info=Gjennomsnittlig ferdigstillelse til kilder i sverm GeneralView.label.swarm_average_completion=Gjennomsnittlig ferdigstillelse GeneralView.label.swarm_average_completion.tooltip=Den gjennomsnittlige ferdigstilelsen til kilder i svermen MainWindow.nat.status.tooltip.unknown=Tilgjengelighet (TCP) imellom brannmur/NAT er ikke kjent MainWindow.nat.status.tooltip.ok=Tiljengelighet i orden (TCP) MainWindow.nat.status.tooltip.probok=Tilgjengelighet i orden, men ingen nylige innkommende forbindelser (TCP) MainWindow.nat.status.bad=Blokkert av brannmur MainWindow.nat.status.tooltip.bad=Problemer med tilgjengelighet (TCP) imellom brannmur/NAT. Sttt deg til Wikin for hjelp. plugin.installer.recommended.plugin=Anbefalt programtillegg - vennligst studer og installer ved behov LoggerView.pause=Pausr logging LoggerView.clear=&Tm LoggerView.filter.uncheckAll=Nullstill kategorier LoggerView.filter.checkAll=Velg alle kategorier LoggerView.loggingDisabled=Logging ikke valgt. LoggerView.includeOnly=Vis kun linjer som matcher dette regulre uttrykket: LoggerView.excludeAll=Vis linjer som IKKE matcher dette regulre uttrykket: ConfigView.section.logging.log0type=Informasjon ConfigView.section.logging.log1type=Advarsel ConfigView.section.logging.log2type=Feil ConfigView.section.logging.filter=Filtrer ved logging til fil ConfigView.section.logging.level=Logg-niv ConfigView.section.logging.showLogsFor=Vis %1-logger for flgende kategorier: ConfigView.pluginlist.column.loadAtStartup=Last ved oppstart ConfigView.pluginlist.column.type.perUser=Per bruker ConfigView.pluginlist.column.type.shared=Delt ConfigView.pluginlist.column.type.builtIn=Innebygget ConfigView.pluginlist.column.name=Navn ConfigView.pluginlist.column.version=Versjon ConfigView.pluginlist.column.directory=Mappe ConfigView.pluginlist.column.isOperational=Klar til bruk? PeersView.BlockView.Avail.Have=Begge har PeersView.BlockView.Avail.NoHave=Kilde har; du har ikke PeersView.BlockView.NoAvail.Have=Du har; kilde har ikke PeersView.BlockView.NoAvail.NoHave=Ingen har PeersView.BlockView.Transfer=Overfrer PeersView.BlockView.NextRequest=Neste foresprsel PeersView.BlockView.title=Bruddstykkeoversikt PeersView.BlockView.AvailCount=Beregnet tilgjengelighet MyTorrentsView.dialog.NumberError.title=Ugyldig eller ugjenkjennelig tall MyTorrentsView.dialog.NumberError.text=Tallet du anga er ugyldig eller ugjenkjennelig. MyTorrentsView.dialog.setSpeed.title=Sett %1-hastighet MyTorrentsView.dialog.setNumber.text=Angi en verdi %1 for endre %2 til: MyTorrentsView.dialog.setNumber.upload=opplasting MyTorrentsView.dialog.setNumber.download=nedlasting MyTorrentsView.dialog.setNumber.inKbps=i %1 OpenTorrentWindow.torrentLocation=Torrent-filer for nedlasting: OpenTorrentWindow.addFiles.URL=Legg til &URL OpenTorrentWindow.addFiles.Folder=Legg til &mappe OpenTorrentWindow.addFiles.Clipboard=Legg til ifra utklipps&tavle OpenTorrentWindow.changeDestination=Endre mlmappe OpenTorrentWindow.fileList=Filer i torrenter: OpenTorrentWindow.torrentTable.name=Navn OpenTorrentWindow.torrentTable.saveLocation=Lagringssted OpenTorrentWindow.fileTable.fileName=Filnavn OpenTorrentWindow.fileTable.size=Strrelse OpenTorrentWindow.fileTable.destinationName=Destinasjonsfil OpenTorrentWindow.startMode.seeding=Sprer OpenTorrentWindow.fileList.changeDestination=Endre destination OpenTorrentWindow.mb.badSize.title=Inkompatibel fil OpenTorrentWindow.mb.badSize.text='%1' er ikke '%2' og kan ikke bli brukt til spreding OpenTorrentWindow.mb.alreadyExists.text=%3 er allerede blitt lagt til som '%2' OpenTorrentWindow.mb.alreadyExists.default.name=Media OpenTorrentWindow.mb.alreadyExists.title=Finnes allerede OpenTorrentWindow.mb.openError.title=Feil ved pning OpenTorrentWindow.mb.openError.text='%1' kunne ikke pnes:\n%2 OpenTorrentWindow.torrent.remove=Fjern torrenten fra liste OpenTorrentWindow.torrent.options=Flgende innstillinger vil pfres ovenforvalgte torrenter: OpenTorrentWindow.xOfTotal=(%1 av %2) iconBar.open.tooltip=pne torrent(er) LocaleUtil.column.text=Ukjent tekst Tracker.tooltip.MultiSupport=Denne tracker sttter flere 'hash scrapes' per foresprsel. Tracker.tooltip.NoMultiSupport=Denne trackeren sttter ikke flere 'hash scrapes' per foresprsel. \nDette pvirker ikke ytelsen din, men genererer strre belastning p trackeren. ConfigView.label.lazybitfield=Bruk 'lazy bitfield' (sttter deling (seeding) p nettverk som benytter bittfelt-basert blokkering/filtrering) LoggerView.realtime=Sanntids oppdatering ConfigView.section.file.perf.cache.flushpieces=Skriv ferdige bruddstykker direkte til disk. Dette gir en jevn diskaksess, men kan totalt fre til flere skriveoperasjoner. ConfigView.section.file.writemblimit=Maksimalt antall klagte skriveaksesser (mlt i %1) ConfigView.section.file.writemblimit.explain=Nr skrivehastigheten til disken er lavere enn nedlastingshastighet, begrenser dette valget hvor mye data som vil bli klagt fr nedlastingshastigheten blir stupet. ConfigView.section.file.readmblimit=Maksimalt antall klagte leseaksesser (mlt i %1) ConfigView.section.file.readmblimit.explain=Dette angir hvor mye minne som vil bli brukt til lagre lese-data i pvente av videre behandling. Button.moveUp=Flytt &opp Button.moveDown=Flytt &ned ConfigView.notAvailableForMode=Dette avsnittet er ment for modus '%1' eller hyere. Det er ikke tilgjengelig i %2 modus. PeersView.piece=Bruddstykke PeersView.piece.info=Siste bruddstykke-nummer forespurt av denne kilden PiecesView.priority=Prioritet PiecesView.priority.info=prioritet satt til fullfrelse av dette bruddstykke, men vektlegg ikke dette i strre grad PiecesView.speed=Hastighet PiecesView.speed.info=Langsomere kilder er i stor grad forhindret i blande seg inn i raskere bruddstykker TableColumn.header.AvgAvail.info=Sum av bruddstykketilgjengelighet dividert p #bruddstykker og #forbindelser TableColumn.header.AvgAvail=Gj.snitt tilgj./bruddstykker ConfigView.label.strictfilelocking=Tilstreb lsing av filer ved skriveakesess p tvers av torrenter MyTorrentsView.menu.rescanfile=Periodisk sjekk av uferdige bruddstykker MyTorrentsView.menu.clear_resume_data=Fjern 'hurtig fortsettelses'-data Plugin.localtracker.info=Programtillegget tillater flere kopier av Vuze tilknyttet et felles nettverk og bak en felles brannmur \n effektivt laste ned torrenter ved hjelp av direktekommunikasjon dem imellom. Plugin.localtracker.enable=Aktiver 'LAN peer finder' azinstancehandler.alert.portclash=Portkollisjon oppdaget p LAN: %1 er allerede ibruk av en annen Azureus-bruker. Velg andre tilfeldige porter for innkommende TCP/UDP forbindelser [mellom %2 og %3]. ConfigView.section.transfer.lan.tooltip=LAN-spesifike innstillinger ConfigView.section.transfer.lan.uploadrate=KB/s LAN maks opplastingshastighet [0: ubegrenset] ConfigView.section.transfer.lan.uploadrate.tooltip=Kildeforbindelser innen samme LAN har en egen hastighetsgrense for opplasting. ConfigView.section.transfer.lan.downloadrate=KB/s LAN maks nedlastingshastighet [0: ubegrenset] ConfigView.section.transfer.lan.downloadrate.tooltip=Kilde-forbindelser innen samme LAN har en egen hastighetsgrense for nedlasting. TorrentOptionsView.title.short=Innstillinger TorrentOptionsView.title.full=Innstillinger til torrent TorrentOptionsView.param.max.peers=Maks antall forbindelser [0: ubegrenset] ConfigView.section.connection.encryption.require_encrypted_transport=Forlang kryptert transport ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Tving bruk av krypterte forbindelser med andre kilder ConfigView.section.connection.encryption.min_encryption_level=Minste krypteringsniv ConfigView.section.connection.encryption.min_encryption_level.tooltip=pen - kun 'handshake' \nRC4 - hele streamen \nHyere krypteringsniv fordrer mere prosessorkraft Peers.column.Encryption=Kryptering Peers.column.Encryption.info=Krypteringsniv i bruk ConfigView.section.connection.encryption.encrypt.info=Ved bruk av kryptering vil du ikke vre i stand til koble til inkompatible klienter, med mindre du setter opp reservelsninger ConfigView.section.connection.encryption.encrypt.info.link=Vennligst besk dennen lenken for nmere forklaring MainWindow.sr.status.tooltip.ok=Delingsrate %1, OK! MainWindow.sr.status.tooltip.poor=Delingsrate %1, svak: < 0.9 MainWindow.sr.status.tooltip.bad=Delingsrate %1, drlig: < 0.5 ConfigView.section.style.status=Statusfelt: ConfigView.section.style.status.show_sr=Delingsrate ConfigView.section.style.status.show_nat=NAT-status ConfigView.section.style.status.show_ddb=DDB-status ConfigView.section.style.status.show_ipf=IPFilter-status ConfigView.section.connection.encryption.encrypt.group=Transport-kryptering ConfigView.section.connection.encryption.encrypt.fallback_info=Aktivasjon av en reservelsning vil tillate forbindelser til ukompatible klienter, MEN dette vil fre til ukrypterte forbindelser ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Tillat ukrypterte utgende forbindelser dersom kryptert tilkoblingsforsk feiler ConfigView.section.connection.encryption.encrypt.fallback_incoming=Tillat ukrypterte innkommende forbindelser upnp.selectedinterfaces=Valgte grensesnitt (';'-separert, eks. eth0;eth1) [tomt: alle] ConfigView.section.style.defaultSortOrder=Standard sorteringsrekkeflge ConfigView.section.style.defaultSortOrder.desc=Synkende ConfigView.section.style.defaultSortOrder.asc=Stigende ConfigView.section.style.defaultSortOrder.flip=Motsatt av tidligere rekkeflge LoggerView.autoscroll=Automatisk rulling Button.selectAll=Velg alle Button.markSelected=Merk valgte Button.unmarkSelected=Avmerk valgte plugins.basicview.config=Konfigurasjon TorrentOptionsView.param.max.uploads=Maks antall opplastings-plasser [minimum: 2] MyTorrentsView.dialog.setPosition.title=Sett posisjon MyTorrentsView.dialog.setPosition.text=Tast inn posisjonen valgte torrenter skal plasseres: MyTorrentsView.menu.reposition.manual=Reposisjonering.. ConfigView.section.connection.advanced.info.link=Vennligst besk dennen lenken for nmere forklaring ConfigView.section.connection.advanced.socket.group=Socket - innstillinger ConfigView.section.connection.advanced.bind_port=Bind til lokal port [0: deaktivert] ConfigView.section.connection.advanced.bind_port.tooltip=Utgende socket-forbindelser vil lokalt bli bundet til angitt port. \nAktivering av dette kan hjelpe med ustabilitet til NAT-router. ConfigView.section.proxy.group.tracker=Tracker-kommunikasjon ConfigView.section.proxy.group.peer=Kilde-kommunikasjon Pieces.column.Requested=Forespurt Pieces.column.Requested.info=Viser om flere foresprlser kan bli gjort vedrrende bruddstykket eller ikke (*) popup.error.hideall=Skjul alle ConfigView.section.style.dataStatsOnly=Vis kun statistikk for data (skjuler protokoll-statistikk) ConfigView.section.style.separateProtDataStats=Adskillt visning av data og protokoll p formen 'data (protokoll)' MyTorrentsView.menu.filter=Filter... ConfigView.section.file.resume.recheck.all=Ved start etter et krasj, kontroller hele filen for kompletterte bruddstykker. (Ellers vil bruddstykker som har vrt aktive siden sist lagring bli sjekket) ConfigureWizard.language.choose=Velg sprk fra listen nedenfor: popup.closing.in=Automatisk lukking om %1 sekunder popup.more.waiting=%1 beskjed(er) gjenstr.. popup.download.finished=Torrenten "%1" er ferdig nedlastet. popup.file.finished=Filen "%1" er ferdig nedlastet. Plugin.localtracker.autoadd.info=Legg disse lokale kilderne automatisk til [';'-separerte adresser, eks: 1.2.3.4;1.2.3.7] Plugin.localtracker.autoadd=Frittstende kilder Plugin.localtracker.networks.info=Betrakt flgende nettverk som lokale [';'-separerte adresser, eks: 145.227.*.*] Plugin.localtracker.networks=Lokale nettverk MainWindow.menu.view.plugins.logViews=Logg visinger SpeedView.stats.autospeed=Automatisk opp-hastighet SpeedView.stats.autospeed.disabled=Denne funksjonen er entent deaktivert (du trenger DHT) eller ikke i bruk (manuell opp-hastighet valgt) SpeedView.stats.idlePing=Idle ping: SpeedView.stats.maxPing=Maks ping: SpeedView.stats.currentPing=Current ping: SpeedView.stats.maxUp=Maks opp-hastighet: ConfigView.pluginlist.unloadSelected=Deaktiver valgte ConfigView.pluginlist.scan=Se etter nye plugins ConfigView.section.transfer.autospeed=Auto-Speed (klassisk) ConfigView.section.transfer.autospeed.tooltip=Innstillinger for Auto-speed ConfigView.section.transfer.autospeed.info=Auto-speed justerer automatisk hastighetsgensen for opplasting. Dette for unng overbelastning av nettverksforbindelsen din.\n\nDisse grensene vil kun bli satt nr automatisk opplastingshastighet er aktivert samtidig med at distribuert database er aktivert.\n ConfigView.section.transfer.autospeed.minupload=%1 min. Opplastingshastighet ConfigView.section.transfer.autospeed.minupload.tooltip=Opplastingshastighet vil normalt automatisk ikke bli senket til under denne grensen ConfigView.section.transfer.autospeed.maxupload=%1 maks. Opplastingshastighet [0: ubegrenset] ConfigView.section.transfer.autospeed.maxupload.tooltip=Opplastingshastighet vil normalt automatisk ikke bli hevet til over denne grensen ConfigView.section.transfer.autospeed.chokeping=Ping-tid ved mettning [millisekunder] ConfigView.section.transfer.autospeed.chokeping.tooltip=Ping-tider hyere enn denne verdien vil bli betraktet som en indikasjon p at nettverket er gtt i mettning ConfigView.section.transfer.autospeed.enableauto=Aktiver ved nedlasting og deling ConfigView.pluginlist.column.unloadable=Deaktiverbar ConfigView.section.transfer.lan.enable=Aktiver egne hastighetsinnstillinger for ulike LAN-tilkoblinger TableColumn.header.filesdone=Filer ferdige TableColumn.header.filesdone.info=Ferdigstilte filer/Antall filer totalt (alt.: ferdigstillelse av valgte filer/antall valgte filer totalt MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=venter p DDB initialisering... MagnetPlugin.report.searching=sker... MagnetPlugin.report.found=%1 funnet MagnetPlugin.report.alive=%1 lever MagnetPlugin.report.dead=%1 er dd MagnetPlugin.report.tunnel=tunellerer til %1 MagnetPlugin.report.downloading=laster ned ifra %1 MagnetPlugin.report.error=feil %1 MagnetURLHandler.report.no_sources=ingen kilder ble funnet for torrenten MagnetURLHandler.report.torrent_size=strrelse til torrent: %1 MagnetURLHandler.report.percent=ferdig: %1% MagnetURLHandler.report.error=feil %1 DHTTransport.report.request_all=forespr hele overfringen ifra %1 DHTTransport.report.received_bit=mottatt %1 til %2 fra %3 DHTTransport.report.complete=ferdig DHTTransport.report.timeout=timeout, intet svar fra %1 DHTTransport.report.rerequest_all=forespr hele overfringen ifra %1 p ny DHTTransport.report.rerequest_bit=forespr %1 til %2 fra %3 p ny DHTTransport.report.timeout_some=timeout, %1 pakker mottatt fra %2, men ufullstendigt DHTTransport.report.sending=sender data DHTTransport.report.resending=sender data p nytt DHTTransport.report.send_complete=sending ferdig DHTTransport.report.send_timeout=tidsoverskrivelse ved sending ConfigView.section.transfer.autospeed.enabledebug=Loggfr debug-informasjon TableColumn.header.date_added=Dato lagt til TableColumn.header.date_added.info=Datoen torrenten ble lagt til ConfigView.section.file.hashchecking.smallestfirst=Overprv de minste nedlastingene frst platform.win32.baddll.info=Vuze fastsltt at '%1' er installert. Dette er en del av '%2', og er kjent for skape store problemer som program-krasj og hy CPU-last. Dersom disse problemene oppstr, avinstaller s denne softwaren, eller konfigurer denne s den ikke pvirker Azureus. #inherit common program names -> platform.win32.baddll.xxx upnp.ignorebaddevices=Ignorer enheter som ikke svarer korrekt upnp.ignorebaddevices.info=Nverende ignorerte enheter: %1 upnp.ignorebaddevices.reset=Tilbakestill listen over ignorerte enheter upnp.ignorebaddevices.reset.action=Tilbakestill upnp.ignorebaddevices.alert=UPnP enhet med adresse %1 blir ignorert pga gjentatte feil. Kikk i konfigurasjonene til UPnP plugin for innstillinger vedrrende denne handlingen. TorrentOptionsView.param.max.uploads.when.busy=KB/s maks opplastingshastighet nr grensen for global opplastingshastighet er ndd [0: deaktivert] UpdateMonitor.messagebox.verification.failed.title=Verifikasjon av installasjonen feilsltt UpdateMonitor.messagebox.verification.failed.text=Verifikasjon av '%1' feilet: %2 UpdateMonitor.messagebox.accept.unverified.title=Aksepter ikke-verifisert installasjon UpdateMonitor.messagebox.accept.unverified.text='%1' kunne ikke bli verifisert som en offisiell plugin til Azureus.\nDersom dette er en slik plugin, burde du IKKE fortsette.\nFortsette med installasjonen? FileView.BlockView.title=Bruddstykker FileView.BlockView.Done=Ferdig FileView.BlockView.Skipped=Utelatt FileView.BlockView.Active=Aktiv FileView.BlockView.Outstanding=Gjenstende ConfigView.label.tcplistenport=Innkommende TCP-port til lytting ConfigView.label.udplistenport=UDP lytteport upnp.portchange.alert=Flgende porter har blitt endret for unng UPnP-enhetproblemer: %1 [tidligere port=%2] %3 [tidligere port=%4] ConfigView.section.proxy.username.info=Dersom proxyserver krever autentitisering, selv dersom ingen er definert, bruk da "" som brukernavn ConfigView.label.maxuploadswhenbusymin=Maks opplastingshastighet per torrent ved timer satt i opptatt modus [sek] MainWindow.menu.help.debug=Generer debug-info (havarilogg) DownloadManager.error.badsize=Uriktig strrelse #ConfigView.section.NATPMP=NAT-PMP natpmp.info=NAT-PMP er Apples svar p UPnP, og er stttet av nyere Airport-stasjoner\n\nBemerk at inntill videre m UPnP vre aktivert for kunne aktivere NAT-PMP. Dette p grunn av at enheter av type NAT-PMP blir behandlet som avledede typer av UPnP. natpmp.enable=Aktiver (merk at dersom dette skal virke, m det ogs aktiviseres i konfigurasjonene til Airport) ConfigView.section.tracker.host.addurls=Overprv at denne trackerens URLer er med i hostede torrenter ConfigView.filter=Tast inn filtrerende tekst... ConfigView.section.files.move=Klargjr for flytting ConfigView.section.file.defaultdir.section=Standard mappealternativer ConfigView.section.file.defaultdir.auto=Automatisk nedlasting til stadardmappe (uten dialog) ConfigView.section.file.defaultdir.bestguess=Bruk beste forslag ved valg av standard lagringsmappe ConfigView.section.file.defaultdir.ask=Standard mappe: ConfigView.section.file.defaultdir.lastused=Bruk sist brukte lagringsmappe som standardmappe ConfigView.section.file.config.section=Konfigurasjonsinnstillinger ConfigView.section.file.config.currentdir=Gjeldende konfigurasjonsmappe: ConfigView.section.torrent.decoding=Dekoder karaktersett ConfigView.section.logging.udptransport=Aktiviser rik sporing av UDP-transport Tracker.announce.ignorePeerSeed=Ignorerer Mottaker/Sender antall. %1 ConfigView.section.connection.encryption.use_crypto_port=Benytt tracker-utvidelsen 'cryptoport' for forhindre vanlige innkommende tilkoblingsforsk. Noen trackere aksepterer ikke dette og svarer med feilmeldinger som "Invalid Port" eller "Illegal Argument" TorrentOptionsView.param.reset.to.default=Tilbakestill innstillinger til standardverdier TorrentOptionsView.param.reset.button=Tilbakestill natpmp.routeraddress=Adresse til stasjon [tomt: auto] ConfigView.section.style.disableAlertSliding=Deaktiver glidende animasjon/p topp for viktige meldinger ConfigView.section.transfer.autospeed.maxinc=%1 maksimal kning per syklus ConfigView.section.transfer.autospeed.maxdec=%1 maksimal reduksjon per syklus ConfigView.section.transfer.autospeed.enabledownadj=Aktiviser regulering av nedlastingshastighet ConfigView.section.transfer.autospeed.downadjratio=Nedlasting:Opplasting hastighetsforhold (eks. 2.0 -> grensen for nedlastingshastighet er det dobbelte av grensen for opplastingshastighet) ConfigView.section.transfer.autospeed.latencyfactor=Faktor brukes for koble endringer i svartid til endringer i hastighet (strre verdier gir lavere sensivitet) ConfigView.section.transfer.autospeed.reset=Tilbakestill avanserte verdier ConfigView.section.transfer.autospeed.reset.button=Tilbakestill PeerColumn.activationCount=Mottakere som frsker koble til: %1 TableColumn.header.timesincedownload.info=Tid forgtt siden data sist ble lastet ned for torrenten TableColumn.header.timesincedownload=Tomgang ned TableColumn.header.timesinceupload.info=Tid forgtt siden data sist ble lastet opp for torrenten TableColumn.header.timesinceupload=Tomgang opp PeersView.incomingreqcount=Foresp. inn PeersView.incomingreqcount.info=Antall innkommende foresprseler fra kilder PeersView.outgoingreqcount=Foresp. ut PeersView.outgoingreqcount.info=Antall utgende foresprseler til klider upnp.mapping.trackerclientudp=UDP tracker klient-port upnp.mapping.dhtudp=Distribuert database ConfigView.section.connection.nondata.udp.same=Bruk samme UDP-port for distribuert database og UDP tracker ConfigView.section.connection.tcp.enable=Aktiver TCP ConfigView.section.connection.udp.enable=Aktiver UDP ConfigView.section.style.showiconbar=Vis verktylinje MainWindow.menu.view.iconbar=Verktylinje MyTorrentsView.menu.rename=Gi nytt navn MyTorrentsView.menu.rename.displayed=Omdp visningsnavn MyTorrentsView.menu.rename.save_path=Omdp lagringmappe MyTorrentsView.menu.rename.displayed_and_save_path=Omdp begge MyTorrentsView.menu.rename.displayed.enter.title=Gi nytt visningsnavn MyTorrentsView.menu.rename.displayed.enter.message=Tast inn nytt navn som vises for denne torrenten.\nDersom ingen tekst blir tastet inn, vil det orginale navnet bli brukt. MyTorrentsView.menu.rename.save_path.enter.title=Gi nytt navn til lagringsmappe MyTorrentsView.menu.rename.save_path.enter.message=Tast inn nytt mappenavn for denne nedlastingen.\nDersom ingen tekst blir tastet inn, vil det orginale navnet bli brukt. MyTorrentsView.menu.rename.displayed_and_save_path.enter.title=Gi nytt navn til nedlasting MyTorrentsView.menu.rename.displayed_and_save_path.enter.message=Tast inn nytt navn for denne nedlastingen.\nDersom ingen tekst blir tastet inn, vil det orginale navnet bli brukt. MyTorrentsView.menu.edit_comment=Rediger kommentar MyTorrentsView.menu.edit_comment.enter.title=Rediger kommentar MyTorrentsView.menu.edit_comment.enter.message=Tilfy en kommentar for denne nedlastingen. UIDebugGenerator.messageask.title=Debug Generator UIDebugGenerator.messageask.text=Vennligst tast inn en beskrivelse av programfeilen/buggen du vil rapportere UIDebugGenerator.complete.title=Generering av debug-informasjon ferdig UIDebugGenerator.complete.text=Vennligst send filen '%1'.\n\nKlikk ok for pning av et vindu til denne filen. ConfigView.section.style.showProgramIcon=Vis programikon i navnespalte ConfigView.section.style.showProgramIcon.tooltip=Fanen m muligens pnes p ny for at endringen skal vises swt.alert.cant.update=SWT-bibliotek lastet fra "%3" kan ikke automatisk bli oppdatert ifra versjon %1 til versjon %2 (m bli lastet fra "%4"). Vennligste besk Wiki for nrmere beskrivelse. authenticator.savepassword=Husk mitt passord ConfigView.section.security.clearpasswords=Slett huskede passord ConfigView.section.security.clearpasswords.button=Tilbakestill Content.alert.notuploaded.title=Ufullstendig opplasting Content.alert.notuploaded.text=Opplasting av '%1' er ikke fullstendig. Dersom du %2 n, vil andre ikke bli i stand til fullstendigt laste ned publikasjonen din.\n\nEr du sikker p at du vil %2? Content.alert.notuploaded.multi.title=Ufullstendig opplastinger Content.alert.notuploaded.multi.text=%1 av det publiserede materiale er ikke fullstendig fordelt til andre. Dersom du %2 n, vil brukere ikke vre i stand til laste ned hele det komplette materialet. Er du sikker du vil %2?\n\nInnhold ikke fullstendig fordelt:\n%3 Content.alert.notuploaded.stop=stopper Content.alert.notuploaded.quit=avslutter Vuze TorrentInfoView.torrent.encoding=Torrent-koding TorrentInfoView.columns=Kolonner fra visningen 'Mine torrenter' progress.window.title=Operasjon i fremdrift progress.window.msg.filemove=Vennligst vent mens filoperasjonen flytt/slett fullfres ConfigView.label.popup.timestamp=Tilfy tidspunkt til sprettoppmeldinger ConfigView.label.popup.autohide=Skjul automatisk sprettoppmeldinger utenom feileldinger etter x sekunder (0: deaktiverer automatisk skjuling) ConfigView.label.popup.suppress_alerts=Skjul meldinger ConfigView.label.popup.use_message_boxes=Benytt sprettoppmelding i stedet for standard meldingsboks. ConfigView.label.popup.show=Vis til n alle loggfrte sprettoppmeldinger (dersom noen finnes) ConfigView.label.popup.show.button=Vis ConfigView.label.please.visit.here=Vennligst besk denne for detaljer ConfigView.section.ipfilter.enable.descriptionCache=Lagre IP-beskrivelser i midlertidig fil ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Beskrivelser vil ikke bli husket dersom ikke aktivert OpenTorrentWindow.filesInfo=%1 av %2 vil bli lastet ned. ConfigView.label.openmytorrents=pne 'Mine torrenter' ved oppstart ConfigView.label.open_transfer_bar_on_start=pne overfringsfane ved oppstart ConfigView.section.style.DNDalwaysInIncomplete=Vis alltid torrenter med filer merket med 'ikke last ned' som ufullstendige i 'Mine torrenter' OpenTorrentWindow.mb.noGlobalDestDir.title=Mlmappe OpenTorrentWindow.mb.noGlobalDestDir.text=Mlmappen '%1' ugyldig. OpenTorrentWindow.mb.noDestDir.title=Mlmappe ikke funnet OpenTorrentWindow.mb.noDestDir.text=Mlmappen '%1' for torrenten '%2' enten s eksisterer den ikke, eller s er den ugyldig. OpenTorrentWindow.mb.notValid.title=pne torrent OpenTorrentWindow.mb.notValid.text=Kunne ikke pne torrenten '%1'. Dersom du har pner denne i sprede-modus, forsikr deg at tilhrende datafiler eksisterer. OpenTorrentWindow.mb.notTorrent.title=pne torrent OpenTorrentWindow.mb.notTorrent.text=Kunne ikke pne '%1'. Det later ikke som vre en gyldig .torrent fil.\n\nNoe motatte data:\n%2 ConfigView.label.pause.downloads.on.exit=Pausr nedlastinger ved programavslutt ConfigView.label.resume.downloads.on.start=Fortsett pausede nedlastinger ved start av programmet, etter fullfrt initieringsprosess. UIDebugGenerator.message.cancel.title=Generering av debug-info kansellert UIDebugGenerator.message.cancel.text=Du la ikke med en beskrivelse av programfeilen du prver rapportere. Feilen kan for deg virke enkel, men uten en beskrivelse ville vi kun gjette oss til hva problemet er.\n\nGenerering av debug-informasjon er blitt kansellert. ConfigView.section.connection.group.http=HTTP ConfigView.section.connection.group.http.info=Sttte for HTTP seeding. ConfigView.section.connection.http.enable=Aktiver ConfigView.section.connection.http.port=Innkommende portnummer ConfigView.section.connection.http.portoverride=Tracker HTTP Port-overstyring [0: ingen] window.update.noupdates.title=Sk etter oppdateringer - Resultater window.update.noupdates.text=Det finnes ingen nye oppdateringer tilgjengelig for deg.\n\nGratulerer! ConfigView.label.bindip.details=Eksempel: 192.168.1.5;eth0;eth1[2] vil binde spesifisert ip til alle iper i grensesnitt eth0, og den tredje ipen i eth1.\nDen frste ipen vil bli brukt for alle tjenester, mens de andre vil bli brukt ved lastbalansering.\nFlgende grensesnitt er tilgjengelige:\n%1 to all IPs of the 1st interface and the 3rd IP of the 2nd interface.\nThe 1st IP will be used for all services, all others are only used for load balancing.\nThe following interfaces are available:\n%1 ConfigView.label.mindownloads=Min. samtidige nedlastinger UI.cannot_submit_blank_text=Du m skrive inn en verdi. crypto.alert.as.warning=Nettverket '%1' er kjent for benytte 'traffic shaping', noe som kan redusere nedlastingsytelsen. Transport-koding er automatisk blitt sltt p - dette kan bli sltt av/modifisert via parametere i konfigurasjonen. ConfigView.section.interface.alerts=Meldinger ConfigView.label.popupdownloadadded=Vis sprettoppmelding nr en nedlasting blir lagt til popup.download.added="%1" har blitt lagt til din nedlastingsliste. MessageBoxWindow.nomoreprompting=Ikke spr meg om dette igjen. TorrentOptionsView.param.max.seeds=Maksimalt antall tilkoblinger til komplette kilder (seeds) [0: tilkoblings-grense] TorrentOptionsView.param.alternative.value.enable=Alternativ verdi kun ved spredning (seeding) ConfigView.section.style.SeparateFilesViewRenameRetarget=Vis egne menyvalg "Omdp" og "Flytt" under Fil-meny ConfigView.section.proxy.check.on.start=Sjekk proxystatus ved oppstart TransferStatsView.legend.pingaverage=Gjennomsnitt TransferStatsView.legend.ping1=Adresse 1 TransferStatsView.legend.ping2=Adresse 2 TransferStatsView.legend.ping3=Adresse 3 ConfigView.section.interface.enabletray._mac=Vis ikon p statuslinje/dock [trenger omstart] ConfigView.label.closetotray._mac=Lukk: minimerer til dock ConfigView.label.minimizetotray._mac=Minimer: minimerer til dock OpenTorrentWindow.mb.existingFiles.title=Fil(er) eksisterer allerede! OpenTorrentWindow.mb.existingFiles.text=Noen av filene finnes allerede i mlmappen(e) du annga:\n\n%1\nDersom du fortsetter vil Vuze sjekke de ovenstende filer for korrekt innhold og overskrive disse dersom ndvendig. splash.unloadingTorrents=Laster ut torrenter splash.unloadingTorrent=Laster ut torrent ConfigView.section.file.defaultdir.autorename=Gi automatisk nytt navn til torrent-filer dersom filer i mappen ser annerledes ut ConfigView.section.file.defaultdir.autorename.tooltip=Dette forhindrer torrenter overskrive hverandres filer med samme navne alert.raised.at.close=(Melding fra forrige lukking av Vuze) #Plugin.trackerpeerauth.name=Tracker Peer Authorization Plugin.trackerpeerauth.info=Dette programtilegget bruker trackere for verifisere at andre sendere faktisk er fullkommende medlemmerer av sverm TableColumn.header.seeds=Fullstendige kilder SpeedView.stats.total=Totalt plugins.basicview.status=Status: MyTorrentsView.menu.manual=Manuell... MyTorrentsView.menu.manual.per_torrent=Manuell (per torrent) MyTorrentsView.menu.manual.shared_torrents=Manuell (p tvers av torrenter) Plugin.extseed.name=Eksterne fullstendige kilder ConfigView.section.connection.encryption=Transportkryptering ConfigView.label.maxuploadsseeding=Alternativ verdi nr det kun spres ConfigView.section.transfer.autospeed.enableautoseeding=Aktivier bare ved spredning Peers.column.maxupspeed=Maks opp-hastighet Peers.column.maxdownspeed=Maks ned-hastighet MyTorrents.items.DownSpeedLimit.disabled=Ingen nedlasting upnp.selectedaddresses=Adresser (';'-separert, '-' prefiks=avsl, '+' =godta) [tom: alle adresser] upnp.alert.multipledevice.warning=Flere UPnP-enheter er blitt funnet - sjekk om alle trenger port-mapping (se UPnP-loggen og konfigurasjonen) UpdateMonitor.messagebox.restart.title=Softwareoppdatering UpdateMonitor.messagebox.restart.text=Vuze har nettopp lastet ned en viktig oppdatering, og m bli startet p nytt for at oppdateringen kan bli installert. PiecesView.BlockView.Have=Har PiecesView.BlockView.NoHave=Har ikke PiecesView.BlockView.Header=%1 kolonne(r), %2 rad(er), %3 brudstykker ConfigView.section.update.autodownload=Last automatisk ned oppdateringer, og gi beskjed nr installasjonen er klar Peers.column.peer_id=Kilde ID Peers.column.peer_id.info=Kilde ID lesbar fra Peers.column.peer_byte_id=Kilde ID Peers.column.peer_byte_id.info=Kilde ID i byte-form Peers.column.handshake_reserved=Reserverte bytes til 'handshake' Peers.column.handshake_reserved.info=Indikerer hvilke bits som ble sendt i BT-handshake dht.warn.user=Gi beskjed ved potensielle problemer med NAT/port-mapping ConfigView.label.openbar.incomplete=Statuslinjer: automatisk pning for hver nedlasting ConfigView.label.openbar.complete=automatisk pning av kompletterte torrenter ConfigView.label.transferbar.remember_location=Husk siste posisjon til overfringslinje ConfigView.section.transfer.autospeed.forcemin=%1 tvungen opplastingshastighet ved initialisering av forbindelsen MainWindow.menu.tools.speedtest=Hastighetstest... speedtest.wizard.title=Hastighetstest speedtest.wizard.run=Utfr en hastighetstest speedtest.wizard.test.mode.updown=opp- og nedlasting speedtest.wizard.test.mode.up=opplasting speedtest.wizard.test.mode.down=nedlasting SpeedTestWizard.test.panel.currinfo=BitTorrent bndbredde testing. SpeedTestWizard.test.panel.label=Vuze hastighetstest: SpeedTestWizard.test.panel.already.running=Testen kjres allerede! SpeedTestWizard.test.panel.not.accepted=Test-anmodning ikke akseptert: SpeedTestWizard.test.panel.abort=Avbryt SpeedTestWizard.test.panel.abort.countdown=avbryter testen om: SpeedTestWizard.test.panel.test.countdown=testen fullfres om: SpeedTestWizard.test.panel.testfailed=Test feilsltt. SpeedTestWizard.test.panel.aborted=Testen ble manuellt avbrutt. SpeedTestWizard.test.panel.enc.label=Valg av kryptering: SpeedTestWizard.test.panel.standard=standard SpeedTestWizard.test.panel.encrypted=kryptert SpeedTestWizard.set.upload.button.apply=Bruk SpeedTestWizard.set.upload.result=Siste testresultat SpeedTestWizard.set.upload.bytes.per.sec=kBytes/sek SpeedTestWizard.set.upload.bits.per.sec=bits/sek SpeedTestWizard.finish.panel.title=Fullfrt hastighetstest! SpeedTestWizard.finish.panel.click.close=Du har fullfrt hastighets-assistenten. 'Lukk' avslutter testen. SpeedTestWizard.finish.panel.max.upload=Maks opplasting: SpeedTestWizard.finish.panel.max.seeding.upload=Maks opplasting ved ren deling: SpeedTestWizard.finish.panel.max.download=Maks nedlasting: SpeedTestWizard.finish.panel.enabled=aktivert SpeedTestWizard.finish.panel.disabled=deaktivert SpeedTestWizard.abort.message.scheduled.in=testen planlagt om ... %1 sekunder" SpeedTestWizard.abort.message.unsupported.type=Ikke stttet test-type!!!! SpeedTestWizard.abort.message.manual.abort=Manuelt avbrutt SpeedTestWizard.abort.message.scheduling.failed=Planlegging av testen feilsltt SpeedTestWizard.abort.message.download.added=Nedlastingen %1 lagt til under test SpeedTestWizard.abort.message.entered.error=Test-nedlasting inntok feiltilstand '%1' SpeedTestWizard.abort.message.entered.queued=Test-nedlasting inntok klagt/stoppet tilstand SpeedTestWizard.abort.message.interrupted=Trden TorrentSpeedTestMonitorThread ble avbrutt fr testen ble ferdigstillt SpeedTestWizard.abort.message.execution.failed=Test-utfrelse feilsltt SpeedTestWizard.abort.message.failed.peers=Feilet med opprette forbindelse til kilder SpeedTestWizard.abort.message.insufficient.slots=Kunne ikke laste opp til noen av kildene - for f opplastings-slotter? SpeedTestWizard.abort.message.not.unchoked=Kunne ikke laste ned fra kilder, fikk ingen destruping-signal fra dem SpeedTestWizard.stage.message.requesting=Spr etter tester... SpeedTestWizard.stage.message.preparing=Forbereder tester... SpeedTestWizard.stage.message.starting=Starter tester... SpeedTestWizard.stage.message.connect.stats=Forbindelses-statistikk: kilder=%1, ned_ok=%2, opp_ok=%3 SpeedTestWizard.set.upload.title=Sett opp- og nedlastings-begrensninger SpeedTestWizard.set.download.label=Hastighetsgrense for nedlasting: SpeedTestWizard.set.upload.label=Hastighetsgrense for opplasting: SpeedTestWizard.name.conf.level.absolute=Absolutt SpeedTestWizard.name.conf.level.high=Hy SpeedTestWizard.name.conf.level.med=Medium SpeedTestWizard.name.conf.level.low=Lav SpeedTestWizard.name.conf.level.none=Ingen #ConfigView.section.transfer.select= #ConfigView.section.transfer.select.v2= mb.azmustclose.title=Oppstart-feil mb.azmustclose.text=Vuzem avslutte p grunn av et problet med starte om Vuze noe som sansynligvis frte til at programmet ble kjrt som en bruker med administrator-rettigheter.\n\n Etter at Vuze avslutter, vennligst start Vuze manuelt. window.uiswitcher.title=Vuze Valg av utseende window.uiswitcher.text=Vennligst velg det brukergrensesnittet (utseende) nedenfor du liker best. window.uiswitcher.NewUI.title=Vuze window.uiswitcher.NewUI.text=\ * Anbefalt for nybegynnere og ferske brukere. \n\n\ * Enkelt, intuitivt grafisk grensesnitt.\n\n\ * Gensesnittet kreves for kunne publisere p Vuze-plattformen. window.uiswitcher.AdvancedUI.title=Avansert Vuze window.uiswitcher.AdvancedUI.text=\ * Anbefalt for brukere som nsker beholde utseende til det klassiske grensesnittet, og som nsker ske, utforske og publisere innhold p Vuze-plattformen\n\n\ * Enkelt, intuitivt grafisk grensesnitt koblet med flere avanserte funksjoner og funksjonalitet. window.uiswitcher.ClassicUI.title=Klassiskt utseende window.uiswitcher.ClassicUI.text=\ * Fastholder funksjonaliteten av versjon 2.x klienten.\n\n\ * Vuze innholds-lag vil ikke bli lagt til. window.uiswitcher.bottom.text=Dine valg kan enkelt endres igjen ved klikke p 'Grensesnitt-velger' iconBar.switch.tooltip=Grensesnitt-velger VivaldiView.notAvailable=Vivaldi-visning ikke tilgjengelig restart.error=Omstart feilet:\n%1\nSe "Restarting Issues" for mere informasjon. #restart.error.url=http://www.azureuswiki.com/index.php/Restarting_Issues restart.error.oom=For lite minne restart.error.fnf='%1' ikke funnet i '%2' restart.error.pnf=Stien '%1' ikke funnet restart.error.bad=Feil filformat for '%1' restart.error.denied=Aksess ble avsltt, ved forsk starte '%1'. Forsikre deg om at du har tilstrekkelig rettigheter til kjre dette programmet. TableColumn.header.date_completed=Komplettert den TableColumn.menu.date_added.reset=Tilbakestill dato ConfigView.section.ipfilter.discardbanning=Sperr kilder hvor forholdet forkastede/gyldige data overstiger [0: deaktivert] ConfigView.section.ipfilter.discardminkb=Minimum %1 forkastede data for forholdet blir anvendt ConfigView.interface.start.advanced=Start med avansert visning (Vuze 2.x) MyTorrents.column.ColumnQuality=Kvalitet MyTorrents.column.ColumnSpeed=Hastighet MyTorrents.column.ColumnProgressETA.2ndLine=Gjenstende tid: %1 MyTorrents.column.ColumnProgressETA.StreamReady=Klar til streaming MyTorrents.column.ColumnProgressETA.PlayableIn=Avspillbar om %1 TableColumn.header.Quality=Kvalitet TableColumn.header.Speed=Hastighet TableColumn.header.RateIt=Verdsettelse TableColumn.header.Rating=Verdsetting TableColumn.header.SpeedGraphic=Hastighet TableColumn.header.AzProduct=Fra TableColumn.header.MediaThumb=Medie TableColumn.header.ProgressETA=Fremdrift TableColumn.header.name.ext=Filtype: %1 v3.MainWindow.tab.home=Dashbord v3.MainWindow.tab.browse=P Vuze v3.MainWindow.tab.library=Bibliotek v3.MainWindow.tab.publish=Publiser v3.MainWindow.tab.advanced=Avansert v3.MainWindow.menu.home=&Dashbord v3.MainWindow.menu.browse=P &Vuze v3.MainWindow.menu.library=&Bibliotek v3.MainWindow.menu.publish=&Publiser v3.MainWindow.menu.advanced=&Avansert v3.MainWindow.menu.view.searchbar=Skelinje v3.MainWindow.menu.view.tabbar=Fane-linje v3.MainWindow.currentDL=Lpende nedlastinger v3.MainWindow.button.stream=Stream v3.MainWindow.button.stop=Stopp v3.MainWindow.button.start=Start v3.MainWindow.button.pause=Pause v3.MainWindow.button.resume=Fortsett v3.MainWindow.button.delete=Slett v3.MainWindow.button.comment=Kommentar v3.MainWindow.button.viewdetails=Vis detaljer v3.MainWindow.button.play=Spill av v3.MainWindow.button.cancel=Avbryt v3.MainWindow.button.sendtofriend=Del v3.MainWindow.view.wait=Initialierer visning, vennligst vent. v3.MainWindow.xofx=%1 av %2 # v3.MainWindow.Loading=Laster... Vennligst vent. v3.filter-bar=Tittel-filter: v3.MainWindow.search.defaultText=Sk i Vuze v3.mb.delPublished.title=Stopp deling av innhold v3.mb.delPublished.text=ADVARSEL: Denne handlingen vil IKKE fjerne det publiserte innholdet '%1' fra \ %3 .\ \n\n\ Klikk p "Slett" kun dersom du vil at innholdet forblir publisert \ og nedlastbart, men nsker frigjre bndbredde. \ Forsikre deg om at opplastingsprosessen frst er ferdigstillt. \ (how?).\ \n\n\ Klikk "Avbryt" dersom du vil fjerne det publiserte innholdet fullstendigt ifra %3, \ og trykk (X)-knappen i 'Publisert innhold' p publiserings-fanen.\ \n\n\ Mer hjelp....\ \n\n v3.mb.delPublished.delete=&Slett v3.mb.delPublished.cancel=&Avbryt v3.mb.notTrusted.title=Innhold ikke plitelig v3.mb.notTrusted.text=Innholdet '%1' er blitt gjenkjent som potensiellt skadelig. Ditt operativsystem har gjenkjent dem som '%2'. v3.mb.notTrusted.noapp.text=Innholdet '%1' er blitt gjenkjent som potensielt skadelig fordi operativsystemet ditt ikke gjenkjenner filformatet (%2). v3.mb.notTrusted.button.run=Kjr uansett v3.mb.notTrusted.button.cancel=Avbryt v3.mb.UnknownContent.title=Ukjent innhold v3.mb.UnknownContent.text=Innholdet '%1' er ikke gjenkjent som et kjent filformatis not recognized as a known format. Your operating system is reporting the content as a '%2' type. The content's file extension is '%3'. v3.mb.UnknownContent.noapp.text=The content '%1' is not recognized as a known format. Operativsystemer ditt har ingen program assosiert med denne filtypen (%2). v3.mb.UnknownContent.button.run=Kjr uansett v3.mb.UnknownContent.button.cancel=Avbryt v3.mb.PlayFileNotFound.title=Fil ikke funnet v3.mb.PlayFileNotFound.text=Filene til '%1' er enten slettet eller borte. v3.mb.PlayFileNotFound.button.remove=Fjern fra Vuze v3.mb.PlayFileNotFound.button.redownload=Last ned data p nytt v3.mb.PlayFileNotFound.button.find=Finn data manuelt.. v3.mb.deletePurchased.title=Fjern kjpt innhold v3.mb.deletePurchased.text=Er du sikker p at du vil slette innholdet '%1'?\n\nDette innholdet har du enten har kjpt, eller betalt for plogging og nedlasting. v3.mb.deletePurchased.button.delete=&Slett v3.mb.deletePurchased.button.cancel=&Avbryt v3.topbar.menu.show.logo=Logo v3.topbar.menu.show.plugin=Plugin-omrde v3.topbar.menu.show.search=Sk v3.topbar.menu.show.frog=Den bl frosken splash.initializeCore=Initialiserer kjerne splash.initializeUIElements=Initialiserer brukergrensesnitt-elementer # ConfigView.section.ipfilter.peerblocking.group=Kildeblokkering ConfigView.section.ipfilter.autoload.group=Automatisk lasting ConfigView.section.ipfilter.autoload.file=IP-filterfil for automatisk innlasting ConfigView.section.ipfilter.autoload.info=Sttter flgende format: DAT (eMule), P2P (PeerGuardian, splist), og P2B v1,2,3 (PeerGuardian 2). Filen kan finnes lokalt eller som en URL, zippet, g-zippet eller som ren tekst. URLer vil automatisk bli lasted p nytt etter 7 dager, mens filer vil bli lastet p nytt innen ett minutter etter ha blitt endret. ConfigView.section.ipfilter.autoload.loadnow=Last n splash.loadIpFilters=Laster IP-filter.. network.ipv6.prefer.addresses=Foretrekk IPv6 adresser nr bde IPv6 og IPv4 er tilgjengelige DHTView.title.full_v6=Distribuert Database IPv6 ConfigView.pluginlist.loadSelected=Last valgte SpeedView.stats.asn=Nettverk: SpeedView.stats.estupcap=Opp.grense: SpeedView.stats.estdowncap=Ned.grens: SpeedView.stats.unknown=Ukjent SpeedView.stats.estimate=Estimat SpeedView.stats.measured=Mlt SpeedView.stats.measuredmin=Mlt minimum SpeedView.stats.manual=Fast ConfigView.section.transfer.autospeed.networks=Nettverk-detaljer ConfigView.section.transfer.autospeed.resetnetwork=Tilbakestill ConfigView.section.transfer.autospeed.network.info=Overenstene grenser blir normalt kalkulert automatisk ved nedlasting, eller er resultatet av en hastighetstest. Dersom du nsker sette innstillinger selv benyttes valgene under. \nAlle grenser unntatt 'fast' vil deretter automtisk bli justert om ndvendig. \nSett inn verdi og velg type. Merk at hastigheter har enheten %1. dialog.uiswitcher.restart.title=UI-veksler: Pkrevd omstart av Vuze dialog.uiswitcher.restart.text=Vuze treger bli restartet for veksle til den nye grafiske drakten. TrayWindow.menu.close=Lukk nedlastingskurv # Used for peers which we can't determine. PeerSocket.unknown=Ukjent PeerSocket.fake_client=FALSK PeerSocket.bad_peer_id=feilaktif kilde-ID PeerSocket.mismatch_id=ingen overenkomst PeerSocket.unknown_az_style=Ukjent %1/%2 PeerSocket.unknown_shadow_style=Ukjent %1/%2 OpenTorrentWindow.mb.askCreateDir.title=Mlmappe eksisterer ikke OpenTorrentWindow.mb.askCreateDir.text=Mlmappen '%1' finnes ikke.\n\nOpprette denne n? SpeedView.stats.estimatechoke=Estimat (struping) ConfigTransferAutoSpeed.upload.capacity.usage=Bruk av opplastingingskapasitet ConfigTransferAutoSpeed.mode=Modus: ConfigTransferAutoSpeed.capacity.used=% av total kapasitet ibruk ConfigTransferAutoSpeed.while.downloading=Laster ned: ConfigTransferAutoSpeed.set.dht.ping=DHT Ping -innstillinger: ConfigTransferAutoSpeed.set.point=verdi (ms) ConfigTransferAutoSpeed.set.tolerance=toleranse (ms) ConfigTransferAutoSpeed.ping.time.good=God: ConfigTransferAutoSpeed.ping.time.bad=Drlig: ConfigTransferAutoSpeed.adjustment.interval=Korringeringsintervall: ConfigTransferAutoSpeed.skip.after.adjust=Utelat etter korrigering: GeneralView.label.distributedCopies=Fordelte kopier: PiecesView.DistributionView.title=Fordeling av bruddstykker PiecesView.DistributionView.NoAvl=Ikke tilgjengelige bruddstykker PiecesView.DistributionView.SeedAvl=Andel fullstendige kilder PiecesView.DistributionView.PeerAvl=Andel ufullstendige kilder PiecesView.DistributionView.RarestAvl=Skjeldneste bruddstykker: %1 (tilgjengelighet:%2) PiecesView.DistributionView.theyHave=Bruddstykker kilde har PiecesView.DistributionView.weHave=Bruddstykker du har PiecesView.DistributionView.weDownload=Bruddstykker du laster ned PeersView.gain=Differanse PeersView.gain.info=Differansen mellom nedlastet og opplastet datamengde unix.script.new.title=Nytt oppstart-script til Vuze er tilgjengelig unix.script.new.text=Ett nytt skript for oppstart av Vuzeer tilgjengelig, og har blit lagt til '%1'.\n\nDet anbefales stenge Vuzefor s bytte til dette skriptet ('%2'). \n\nI tilfelle oppstartskriptet er sterkt modifisert, vr vennlig og les AzureusWiki: Unix Script. \n\nDersom du installerte Vuzeifra en distribusjon (yum, apt-get, etc), er det anbefalt at du re-installerer Vuze med pakkene lokalisert p Vuze sin prosjektside p Sourceforge (Det nvrende grafiske utseende blir beholdt) #unix.script.new.manual.url=http://azureuswiki.com/index.php/Unix_Startup_Script unix.script.new.button.quit=Avslutt n unix.script.new.button.continue=Utsettes til senere unix.script.new.button.asknomore=Ikke spr meg igjen unix.script.new.auto.title=Nytt oppstartskript for Vuze unix.script.new.auto.text=Et nytt skript for oppstart av Vuze er tilgjengelig.\n\nDet er anbefalt starte Vuze p nytt. ConfigView.label.checkOnSeeding=Utfr ressursbesparende fornyet sjekk av bruddstykker nr det kun blir fordelt (seeding) ConfigView.label.ui_switcher=Vis valg av Azureus-utseende ConfigView.label.ui_switcher_button=Vis SpeedTestWizard.test.panel.explain=Ml protokoll-kastigheten i Azureus. Velg test-type og kryptering. Se wiki-sidene til Vuze for detaljert informasjon om testene. En test varer typisk i mindre enn ett munitt, men stoppes automatisk dersom den bruker lengre enn to minutter. SpeedTestWizard.set.upload.hint=Sett hastighetsgrenser for opp- og nedlasting som brukes av Vuze SpeedSense-algoritme. SpeedTestWizard.set.upload.panel.explain=Grensene satt her blir kun brukt av SpeedSense-algoritmen i Azreus. Sett niver for overfring og konfidensialitet.\n\nBemerk at linje-hastigheter ofte blir betegnet som "bits per sekund" (bps) - men verdien under har benevningen "kilobytes per sekund" (kB/s). SpeedTestWizard.set.limit.conf.level=Fortrolighetsniv SpeedTestWizard.finish.panel.auto.speed=Auto-speed er: SpeedTestWizard.finish.panel.auto.speed.seeding=Auto-speed ved ren deling: ConfigTransferAutoSpeed.add.comment.to.log.group=Tilfy kommentar til logg ConfigTransferAutoSpeed.add.comment.to.log=Tilfy kommentar: ConfigTransferAutoSpeed.log.button=Logg ConfigTransferAutoSpeed.algorithm.selector=Auto-Speed velger ConfigTransferAutoSpeed.algorithm=Algoritme: ConfigTransferAutoSpeed.auto.speed.classic=Auto-Speed (klassisk) ConfigTransferAutoSpeed.auto.speed.beta=Auto-Speed (beta) ConfigTransferAutoSpeed.data.update.frequency=Oppdateringsfrekvens Alert.failed.update=Installasjon av minst n komponent feilet. Se AzureusWiki: Failed Update [%1] #Alert.failed.update.url=http://azureuswiki.com/index.php/Failed_Update OpenTorrentWindow.mb.existingFiles.partialList= (Begrenset liste. Flere filer finnes fra fr) TableColumn.header.bad_avail_time.info=Tidspunkt en komplett kilde sist var tilgjengelig TableColumn.header.bad_avail_time=Komplett kilde sett MyTorrentsView.menu.exporthttpseeds=Eksporter URLer (HTTPkilder) til utklippstavle SWT.alert.erroringuithread=En ikke hndtert feil oppstod i GUI. Flgefeil kan forekomme - ConfigView.label.minannounce=Minste tidsforlp (i sekunder) mellom tracker-annonseringer ConfigView.label.maxnumwant=Begrens antall kilder trackeren kan returnere ConfigView.label.announceport=Overstyr annonsert TCP-port for tracker-annonseringer, pex og dht\n[tomt: ingen overstyring, 0: ingen innkommende forbindelser] ConfigView.label.noportannounce=Ikke annonser lytteporten mot tracker (dette berrer ikke pex og dht) ConfigView.label.maxseedspertorrent=Maks kilder per torrent som standard [0: ubegrenset] wizard.webseed=Legg HTTPkilder til torrenten wizard.webseed.title=HTTPkilder wizard.webseed.configuration=HTTPkilder - Konfigurasjon wizard.webseed.adding=Legger til HTTPkilder GeneralView.label.private=Privat torrent: GeneralView.yes=ja GeneralView.no=nei ConfigView.label.userequestlimiting=Benytt struping av foresprsler i stedet for forsinket lesing for begrense nedlastingshastigheten [ingen effekt ved ubegrenset nedlastingshastighet] ConfigView.label.userequestlimiting.tooltip=Begrensing av foresprsler gir ikke et like glatt resultat som forsinket lesing, men muliggr for prioritering av nedlastinger basert p klagt posisjon og kan ke nettverksytelsen ConfigView.section.logging.timestamp=Utseende til tidsstempel i loggfiler Peers.column.timetocomplete=Gjenstende tid Peers.column.timetocomplete.info=Antatt gjenstende tid fr mottakeren er ferdigstillt/komplettert ConfigView.section.interface.display.suppress.file.download.dialog=Skjul popup for nedlastingsmelding ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Viser istedet alle nedlastings-fremdrifter i statuslinje i stedet for en popup-melding FileDownload.canceled=En torrent-nedlasting har blitt kansellert av en brukehandling: %1 Progress.reporting.status.canceled=Kansellert Progress.reporting.status.finished=Ferdigstillt Progress.reporting.status.retrying=Prver p ny... Progress.reporting.prompt.label.retry.tooltip=Prver handlingen p ny Progress.reporting.prompt.label.remove.tooltip=Fjerner denne fremdriftsrapporten ifra historikk Progress.reporting.prompt.label.cancel.tooltip=Avbryter handlingen Progress.reporting.prompt.label.detail.tooltip=Vis denne fremdriftsrapporten i detaljvinduet Progress.reporting.action.label.retry=Prv p ny Progress.reporting.action.label.remove=Fjern fremdriftsrapporten ifra historikk Progress.reporting.action.label.detail=Detaljer Progress.reporting.action.label.cancel=Avbryt Progress.reporting.default.error=Feilet Progress.reporting.no.reports.to.display=Ingen fremdriftsrapporter vise Progress.reporting.no.history.to.display=Ingen detaljerte meldinger vise Progress.reporting.detail.history.limit=Grense for antall meldinger (%1) er blitt overskrevet for denne fremdriftsrapporten; pflgende meldinger vil ikke bli lagt til historikk Progress.reporting.statusbar.button.tooltip=Vis vindu for fremdriftsvisning webui.bindip=Fast IP - vanligvis ikke ndvendigt (*) v3.MainWindow.text.log.in=Logg inn v3.MainWindow.text.log.out=Logg ut v3.MainWindow.text.get.started=Kom i gang v3.MainWindow.text.my.account=Min konto OpenTorrentWindow.simple.open=Torrent lokalisering (Fil, URL, Hash) MainWindow.menu.help.donate=&Doner!! #EOF azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_da_DK.properties0000644000175000017500000042215411301156004026041 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torrent Fil... MainWindow.menu.file.open.torrent.keybinding=Meta+o Main.parameter.usage=Brug : java org.gudy.azureus2.cl.Main (parametre) "fil.torrent" "lagringssti" Main.parameter.maxUploads=Maksimum antal samtidige uploads Main.parameter.maxSpeed=Maksimum upload hastighed i bytes/sek MainWindow.menu.file=&Filer MainWindow.menu.file.open=&\u00c5ben MainWindow.menu.file.create=&Opret ny torrent... MainWindow.menu.file.create.keybinding=Meta+n MainWindow.menu.file.create.fromfile=Fra en &Fil MainWindow.menu.file.create.fromdir=Fra en &Mappe MainWindow.menu.file.export=&Eksporter XML Torrent... MainWindow.menu.file.export.keybinding=Meta+e MainWindow.menu.file.export.keybinding.mac=Meta+Shift+e MainWindow.menu.file.import=&Importer XML Torrent... MainWindow.menu.file.import.keybinding=Meta+i MainWindow.menu.file.import.keybinding.mac=Meta+Shift+i MainWindow.menu.file.closetab=Luk &Faneblade MainWindow.menu.file.closetab.keybinding=Meta+w MainWindow.menu.file.closewindow=Luk &Vindue MainWindow.menu.file.closewindow.keybinding=Meta+Shift+w MainWindow.menu.file.exit=&Afslut MainWindow.menu.file.exit.keybinding=Alt+F4. MainWindow.dialog.choose.file=V\u00e6lg Torrent filen MainWindow.menu.file.folder=&Mappe... MainWindow.menu.file.folder.keybinding=Meta+Shift+o MainWindow.dialog.choose.folder=V\u00e6lg mappen med Torrent filerne MainWindow.menu.view=&Vis MainWindow.menu.view.show=Vis faner MainWindow.menu.view.mytorrents=&Mine Torrents MainWindow.menu.view.mytorrents.keybinding=Meta+1 MainWindow.menu.view.configuration=&Konfiguration MainWindow.menu.view.configuration.keybinding=Meta+, MainWindow.menu.view.console=K&onsol MainWindow.menu.view.console.keybinding=Meta+4 MainWindow.menu.view.irc=&IRc MainWindow.menu.closealldetails=Luk &Alle Faneblade MainWindow.menu.closealldownloadbars=Luk alle Download &Bj\u00e6lker MainWindow.menu.language=&Sprog ConfigView.section.language=Sprog MainWindow.menu.window=&Vindue MainWindow.menu.window.minimize=&Minimer MainWindow.menu.window.minimize.keybinding=Meta+m MainWindow.menu.window.zoom=&Zoom MainWindow.menu.window.alltofront=F\u00f8r alle frem i &Front MainWindow.menu.help=&Hj\u00e6lp MainWindow.menu.help.about=Om Vuze MainWindow.about.title=Om Vuze MainWindow.about.section.developers=Udviklere MainWindow.about.section.translators=Overs\u00e6ttere MainWindow.about.section.system=System MainWindow.about.section.internet=Internet MainWindow.about.internet.homepage=Vuze hjemmeside MainWindow.about.internet.sourceforge=Sourceforge projektside MainWindow.about.internet.sourceforgedownloads=Downloads p\u00e5 Sourceforge MainWindow.about.internet.bugreports=Fejl rapporter MainWindow.about.internet.forumdiscussion=Diskussionsforum MainWindow.about.internet.wiki=Vuze Wiki FAQ\n(ofte stillede sp\u00f8rgsm\u00e5l) MainWindow.dialog.choose.savepath=V\u00e6lg mappen til lagring MainWindow.dialog.choose.savepath_forallfiles=V\u00e6lg mappen til lagring for alle filer MainWindow.status.latestversion=Seneste MainWindow.status.latestversion.clickupdate=Klik her for at s\u00f8ge efter nyeste Opdatering MainWindow.status.unknown=ukendt MainWindow.status.checking=kontrollerer MyTorrentsView.mytorrents=Mine Torrents TableColumn.header.name=Torrentens navn TableColumn.header.size=St\u00f8rrelse TableColumn.header.done=F\u00e6rdig TableColumn.header.done.info=F\u00e6rdigg\u00f8relsen af den aktuelle opgave vist i procent TableColumn.header.status=Status TableColumn.header.status.info=Hvad laver denne Torrent TableColumn.header.seeds=Seeders TableColumn.header.seeds.info=Forbundet til antal seedere (antal seedere totalt) TableColumn.header.peers=Peers TableColumn.header.peers.info=Forbundet til antal peers (antal peers totalt) TableColumn.header.downspeed=Download hastighed TableColumn.header.upspeed=Upload hastighed TableColumn.header.eta=Resterende download tid TableColumn.header.tracker=Tracker status TableColumn.header.tracker.info=Trackerens status TableColumn.header.trackernextaccess=N\u00e6ste tracker tilgang TableColumn.header.trackernextaccess.info=Hvorn\u00e5r den n\u00e6ste tracker adgang vil finde sted TableColumn.header.priority=Prioritet TableColumn.header.priority.info=Bestemmer hvor meget upload b\u00e5ndbredde en Torrent f\u00e5r TableColumn.header.seeds.fullcopycalc=%2 hele kopier formodes for hver %1 peers MyTorrentsView.menu.showdetails=Vis &Detaljer MyTorrentsView.menu.showdownloadbar=Vis Download &Bj\u00e6lke MyTorrentsView.menu.open=&\u00c5ben MyTorrentsView.menu.setpriority=S\u00e6t &Prioritet MyTorrentsView.menu.setpriority.high=&H\u00f8j MyTorrentsView.menu.setpriority.low=&Lav MyTorrentsView.menu.start=&start MyTorrentsView.menu.stop=S&top MyTorrentsView.menu.remove=&Fjern MyTorrentsView.menu.changeTracker=&Tilf\u00f8j en tracker URL TrayWindow.menu.exit=&Afslut TrayWindow.menu.show=&Vis Vuze SystemTray.menu.exit=&Afslut SystemTray.menu.closealldownloadbars=Luk &alle Download Bj\u00e6lker SystemTray.menu.show=&Vis Vuze PeersView.ip=IP adresse : PeersView.ip.info=Peers IP PeersView.port=Port : PeersView.port.info=Porten der bruges PeersView.T=I : PeersView.T.info=L (lokal) : du har oprettet forbindelsen, I (Indg\u00e5ende) : peer har oprettet forbindelsen. PeersView.T.L.tooltip=du har oprettet forbindelsen PeersView.T.R.tooltip=peer har oprettet forbindelsen. PeersView.I1=I (Interesseret i peer) PeersView.I1.info=Er du interesseret i hvad den anden peer har? PeersView.C1=Kvalt : PeersView.C1.info=Om peer blokerer/kv\u00e6ler dig fra at downloade PeersView.pieces=Stykker : PeersView.%=Hentet : PeersView.downloadspeed=Download hastighed : PeersView.download=Ned PeersView.I2=I (Interessant for peer) PeersView.I2.info=Er peer interesseret i hvad du har? PeersView.C2=Kv\u00e6ler : PeersView.C2.info=Om du blokerer/kv\u00e6ler peer fra at downloade PeersView.uploadspeed=Upload hastighed PeersView.uploadspeed.info=Din uploadhastighed til peer PeersView.upload=Op PeersView.upload.info=Din totale upload til peer. PeersView.statup=Stat op PeersView.statup.info=Ansl\u00e5et v\u00e6rdi af peers upload-hastighed PeersView.S=Sn PeersView.S.info=Snubbed : En peer kan blive "snubbed" manuelt, eller automatisk (for ikke at levere data i en h\u00f8j nok hastighed) PeersView.downloadspeedoverall=Samlet download hastighed PeersView.optunchoke=Kv\u00e6ler ikke PeersView.client=Klient PeersView.client.info=Type af BT klient som peer bruger PeersView.title.short=Detaljer : PeersView.title.full=Detaljer ConfigView.section.files=Filer ConfigView.label.usefastresume=Aktiver hurtig fors\u00e6ttelse ConfigView.label.incrementalfile=Aktiver gradvis oprettelse af fil(er) (FAT32 p\u00e5 Linux kr\u00e6ver dette) ConfigView.label.defaultsavepath=Gem i standard data lagringsmappe ConfigView.button.browse=&Gennemse... ConfigView.dialog.choosedefaultsavepath=V\u00e6lg din standard lagringsmappe ConfigView.section.server=Forbindelse ConfigView.section.global=Generelt ConfigView.label.disconnetseed=Afbryd andre seeds n\u00e5r der seedes ConfigView.label.switchpriority=Skift automatisk til lav prioritet n\u00e5r en Torrent seedes ConfigView.label.maxdownloads=Maksimum antal samtidige downloads (0 = ubegr\u00e6nset)\n - Antallet kan og m\u00e5 ikke v\u00e6re h\u00f8jere end maksimum antal aktive Torrents ConfigView.label.maxdownloads.tooltip=Du vil altid v\u00e6re i stand til aktivt at downloade det antal du angiver her, med en undtagelse.\nEn f\u00e6rdig torrent som matcher kriteriet for f\u00f8rsteprioritet kan overtage en aktiv download plads hvis det kr\u00e6ves. ConfigView.label.maxactivetorrents=H\u00f8jeste antal af aktive Torrents p\u00e5 samme tid (0 = ubegr\u00e6nset)\n - Nye Torrents starter ikke hvis du downloader og/eller seeder flere end antallet du angiver her ConfigView.label.priorityExtensions=Prioriter automatisk filer med endelsen \n - f.eks : .txt;.nfo;.jpg;.bmp ConfigView.section.transfer=Overf\u00f8rsel ConfigView.label.maxuploads=Standard maksimum uploads Pr. Torrent ConfigView.label.maxuploadspeed=KB/s total maksimum upload hastighed (0 = ubegr\u00e6nset) ConfigView.label.saveresumeinterval=Opdater data for hurtig forts\u00e6ttelse hver ConfigView.unlimited=Ubegr\u00e6nset ConfigView.section.display=Udseende ConfigView.label.opendetails=\u00c5ben Detalje-Faneblade Automatisk ConfigView.label.openbar=\u00c5ben Downloadbj\u00e6lken Automatisk ConfigView.label.closetotray=Luk minimerer til meddelelsesomr\u00e5det ConfigView.label.minimizetotray=Minimer "Minimerer" til meddelelsesomr\u00e5det ConfigView.section.general=Generelt ConfigView.section.start=Start ConfigView.label.showsplash=Vis opstartsbillede ConfigView.label.autoupdate=Automatisk \u00e5bning af Opdateringsvinduet n\u00e5r en nyere version er tilg\u00e6ngelig ConfigView.label.openconsole=\u00c5ben Fanen "Konsol" n\u00e5r Vuze startes ConfigView.label.openconfig=\u00c5ben Fanen "Konfiguration" n\u00e5r Vuze startes ConfigView.label.startminimized=Start minimeret ConfigView.section.irc=IRc ConfigView.label.ircwiki=L\u00e6s f\u00f8lgende http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Server ConfigView.label.ircchannel=Kanal ConfigView.label.irclogin=Brugernavn ConfigView.group.irctitle=IRC Indstillinger ConfigView.boolean.ircsendinfo=Tillad at dine indstillinger bliver sendt (annonymt) til kanal administratorene for at hj\u00e6lpe dem med at hj\u00e6lpe dig ConfigView.boolean.irclog=Aktiver logfil for kanal aktivitet (til IRC_log.htm) ConfigView.section.security=Sikkerhed ConfigView.label.password=Beskyt Vuze med en adgangskode:\n - Vil blive kr\u00e6vet n\u00e5r programmet startes, samt ved aktivering fra proceslinien ConfigView.label.passwordconfirm=Adgangskode (bekr\u00e6ft) ConfigView.label.passwordmatch=Adgangskode aktiveret ConfigView.label.passwordmatchnone=Nej ConfigView.label.passwordmatchno=Nej / Adgangskoderne er ikke ens ConfigView.label.passwordmatchyes=Ja ConfigView.button.save=Gem ConfigView.title.short=Konfiguration ConfigView.title.full=Konfiguration ConsoleView.title.short=Konsol ConsoleView.title.full=Konsol FileItem.write=Skrivning FileItem.read=L\u00e6sning FileItem.normal=Normal FileItem.high=H\u00f8j FileItem.donotdownload=Download ikke FilesView.name=Navn : FilesView.size=St\u00f8rrelse : FilesView.done=F\u00e6rdig : FilesView.%=Fuldf\u00f8rt i % FilesView.firstpiece=F\u00f8rste stykke Nr : FilesView.numberofpieces=Antallet af stykker : FilesView.pieces=Stykker : FilesView.mode=Tilstand : FilesView.priority=Prioritet : FilesView.menu.open=&\u00c5ben FilesView.menu.setpriority=&S\u00e6t prioritet FilesView.menu.setpriority.high=&H\u00f8j FilesView.menu.setpriority.normal=&Normal FilesView.menu.setpriority.skipped=&Download ikke FilesView.title.short=Filer FilesView.title.full=Filer GeneralView.section.downloaded=Downloadet : GeneralView.label.status.file=Fil status GeneralView.label.status.pieces=Stykkets Status GeneralView.section.availability=Tilg\u00e6ngelighed : GeneralView.label.status.pieces_available=Stykkets Status GeneralView.section.transfer=Overf\u00f8rsel GeneralView.section.info=Information GeneralView.title.short=Generelt GeneralView.title.full=Generelt GeneralView.label.timeelapsed=Tid g\u00e5et : GeneralView.label.remaining=Tid tilbage : GeneralView.label.downloaded=Downloadet : GeneralView.label.downloadspeed=Download hastighed : GeneralView.label.maxuploads=Maksimum uploads : GeneralView.label.maxuploads.tooltip=Maksimum antal peers som fjernes p\u00e5 "kv\u00e6ler" listen af gangen. GeneralView.label.uploaded=Uploadet : GeneralView.label.uploadspeed=Upload hastighed : GeneralView.label.seeds=Seeder : GeneralView.label.peers=Peer : GeneralView.label.totalspeed=Sv\u00e6rmens hastighed : GeneralView.label.totalspeed.tooltip=Samlet (og gennemsnitlig) hastighed af alle klienter du er forbundet til. GeneralView.label.averagespeed=gennemsnit GeneralView.label.filename=Navn : GeneralView.label.totalsize=Totale st\u00f8rrelse : GeneralView.label.savein=Gem i : GeneralView.label.hash=Hash : GeneralView.label.numberofpieces=Antallet af stykker : GeneralView.label.size=St\u00f8rrelse : GeneralView.label.tracker=Tracker status : GeneralView.label.updatein=N\u00e6ste opdatering er om : GeneralView.label.trackerurl=Trackerens URL : GeneralView.label.trackerurlupdate=Manuel opdatering GeneralView.label.comment=Torrent Kommentar : GeneralView.label.user_comment=Bruger kommentar : ManagerItem.waiting=Venter ManagerItem.allocating=Klarg\u00f8rer ManagerItem.checking=Kontrollerer ManagerItem.ready=Klar ManagerItem.downloading=Downloader ManagerItem.seeding=Seeder ManagerItem.stopped=Stoppet ManagerItem.error=Fejl ManagerItem.high=H\u00f8j ManagerItem.low=Lav MinimizedWindow.name=Navn : PiecesView.#=Nr : PiecesView.size=St\u00f8rrelse : PiecesView.numberofblocks=Antallet af blokke : PiecesView.blocks=Blokke : PiecesView.completed=Komplette : PiecesView.availability=Tilg\u00e6ngelighed : PiecesView.reservedby=Reserveret : PiecesView.writers=Bloker Fordelere : PiecesView.title.short=Stykker : PiecesView.title.full=Stykker SystemTray.tooltip.seeding=%1 seeder, SystemTray.tooltip.downloading=%1 downloades, DownloadManager.error.filenotfound=Filen blev ikke fundet DownloadManager.error.fileempty=Torrent filen er tom DownloadManager.error.filetoobig=Torrent filen er for stor DownloadManager.error.filewithouttorrentinfo=Ingen Torrent information fundet i filen DownloadManager.error.unsupportedencoding=Krypteringen underst\u00f8ttes ikke DownloadManager.error.ioerror=IO fejl DownloadManager.error.sha1=Algoritmen findes ikke (SHA1) Fejl PeerManager.status.offline=Forbindelsesfejl PeerManager.status.ok=OK PeerManager.status.checking=Kontrollerer PeerManager.status.finished=F\u00e6rdig PeerManager.status.finishedin=F\u00e6rdig om MainWindow.upgrade.assistant=Opdaterings assistent MainWindow.upgrade.newerversion=Der er en nyere version af Vuze tilg\u00e6ngelig til download. MainWindow.upgrade.explanation=Denne assistent vil downloade den nye version til dit Vuze bibliotek og genstarte Vuze MainWindow.upgrade.explanation.manual=Du kan opdatere manuelt ved at afslutte Vuze downloade den nye version og derefter genstarte Vuze MainWindow.upgrade.step1=Trin 1 : Download den nye version. MainWindow.upgrade.step2=Trin 2 : Luk denne version og genstart den nye version af Azureus. MainWindow.upgrade.hint1=Tip :\tEt tryk p\u00e5 Afslut g\u00f8r det hele automatisk MainWindow.upgrade.hint2=Tip :\tHvis du vil lukke Vuze senere, klik Afbryd og\n\tomd\u00f8b filen Azureus2-new.jar til Azureus2.jar efter lukningen MainWindow.upgrade.error.downloading.hint=Fejl :\tDet var ikke muligt at downloade den nye version, opdater manuelt MainWindow.upgrade.section.info=Ny version tilg\u00e6ngelig MainWindow.upgrade.section.manual=Manuel opdatering MainWindow.upgrade.section.automatic=Automatisk opdatering MainWindow.upgrade.tooltip.progressbar=Downloadforl\u00f8bet bliver vist her Button.next=N\u00e6ste Button.finish=Udf\u00f8r Button.cancel=Annuler LocaleUtil.title=V\u00e6lg kryptering LocaleUtil.section.chooseencoding=V\u00e6lg kryptering af filnavn LocaleUtil.label.chooseencoding=V\u00e6lg den best passende kryptering LocaleUtil.label.hint.doubleclick=Tip : Ved at dobbelt-klikke p\u00e5 en linie v\u00e6lges kodningen og vinduet lukkes LocaleUtil.label.checkbox.rememberdecision=Anvend samme beslutning for de resterende filnavne LocaleUtil.column.encoding=Kryptering : IrcClient.defaultChannel=Antallet af Vuze Brugere IrcClient.copyright=Bruger PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Forbinder til IrcClient.connected=Forbundet til IrcClient.joining=Tilslutter IrcClient.channel=Kanal IrcClient.joined=tilsluttet IrcClient.error=Fejl IrcClient.hasjoined=har tilsluttet IrcClient.haskicked=har sparket IrcClient.hasleft=har forladt IrcClient.nowknown=har skiftet navn til IrcClient.topicforchannel=Emne for kanalen IrcClient.disconnected=Afbrudt fra IrcClient.noNick=Intet brugernavn angivet. G\u00e5 til V\u00e6rkt\u00f8jer/Konfiguration/tilf\u00f8jelser/IRC IrcView.actionnotsupported=Kommandoen er ikke underst\u00f8ttet. Skriv /help for hj\u00e6lp. IrcView.clientsconnected=Brugere IrcView.privateto=Til IrcView.privatefrom=Fra IrcView.noticefrom=Besked : IrcView.errormsg=Forkert syntaks for /msg: /msg IrcView.help=Gyldige kommandoer er :\n . /help : Viser denne besked\n . /nick | /name : \u00c6ndrer dit brugernavn \n . /me action : Sender en \u00f8nsket handling\n . /msg nick message : Sender en privat besked til \n . /r message : Besvar sidste private besked\n . /join #channelB (klik ikke her da dette er et eksempel) : Skifter den aktuelle kanal til channelB PasswordWindow.title=Vuze er l\u00e5st PasswordWindow.passwordprotected=Vuze er beskyttet med adgangskode.\nSkriv din adgangskode her for at f\u00e5 vist Vuze vinduet : Button.ok=Ok TrackerChangerWindow.title=Tilf\u00f8j tracker TrackerChangerWindow.newtracker=Tilf\u00f8j en ny tracker URL PeersView.discarded=Kasseret PeersView.discarded.info=Data som er blevet modtaget uden, at der var brug for det, og som derfor er blevet slettet. discarded=kasseret MyTorrentsView.#=Nr MyTorrentsView.menu.move=&Flyt MyTorrentsView.menu.moveUp=&Op MyTorrentsView.menu.moveDown=&Ned GeneralView.label.hashfails=Hash fejl : GeneralView.label.shareRatio=Delingsforhold : ConfigView.section.downloadManagement=Downloadh\u00e5ndtering ConfigView.label.startRatioPeers=Start seeding n\u00e5r der er mindre end 1 seed for : ConfigView.text.neverStop=Stop aldrig ConfigView.text.neverStart=Start aldrig ConfigView.text.peers=peers ConfigView.label.checkOncompletion=Kontroller stykkerne igen n\u00e5r downloaden er f\u00e6rdig wizard.title=Opret en torrent wizard.previous=< Tilbage wizard.next=N\u00e6ste > wizard.finish=Udf\u00f8r wizard.mode=Tracker / Tilstand wizard.tracker=Tracker wizard.invalidurl=Denne URL er ikke gyldig wizard.singlefile=Enkelt fil wizard.singlefile.help=Opret en torrent ud fra en enkelt fil wizard.directory=Mappe wizard.directory.help=Lav en torrent ud fra en mappe wizard.choosefile=V\u00e6lg filen wizard.file=Fil : wizard.browse=Gennemse... wizard.choosedirectory=V\u00e6lg en mappe wizard.invalidfile=Ugyldig fil! wizard.invaliddirectory=Ugyldig mappe! wizard.torrentFile=Torrent fil wizard.choosetorrent=V\u00e6lg Torrent filen som du vil oprette wizard.information=Info wizard.notimplemented=Ikke implementeret endnu wizard.progresstitle=Opret en Torrent fil wizard.savingfile=Gemmer filen... wizard.filesaved=Filen er blevet gemt. wizard.close=Luk Torrent.create.progress.piecelength=Styk l\u00e6ngde : Torrent.create.progress.piececount=Antal stykker : Torrent.create.progress.totalfilesize=Samlet filst\u00f8rrelse : Torrent.create.progress.totalfilecount=Samlet antal filer : Torrent.create.progress.parsingfiles=Analyserer filer Torrent.create.progress.hashing=Genererer hash-v\u00e6rdier MainWindow.upgrade.downloadingfrom=Downloader fra : MainWindow.menu.view.ipFilter=&IP Filtre ConfigView.section.ipfilter=IP filtre ConfigView.section.ipfilter.description=Beskrivelse ConfigView.section.ipfilter.start=Start fra IP ConfigView.section.ipfilter.end=Slut med IP ConfigView.section.ipfilter.add=Tilf\u00f8j... ConfigView.section.ipfilter.remove=Fjern ConfigView.section.ipfilter.edit=Rediger... ConfigView.section.ipfilter.save=Gem ConfigView.section.ipfilter.editFilter=Rediger filter ConfigView.section.ipfilter.enable=Aktiver PeersView.menu.close=&Luk seedmore.title=Denne torrent er ikke blevet seedet nok seedmore.shareratio=Delingsforholdet p\u00e5 denne Torrent er seedmore.uploadmore=At have et delingsforhold p\u00e5 en Torrent p\u00e5 under 100% er ikke godt for BitTorrent netv\u00e6rket.\nDu b\u00f8r lade denne Torrent seede lidt mere.\nEr du sikker p\u00e5 at du vil forts\u00e6tte? ConfigView.label.showpopuponclose=Bekr\u00e6ft n\u00e5r en Torrent, med et delingsforhold p\u00e5 mindre end 1, stoppes n\u00e5r du seeder ConfigView.label.startNumSeeds=Begynd at seede hvis der er f\u00e6rre end :\n - Tilsides\u00e6tter alle andre regler ConfigView.label.seeds=Seeder ConfigView.section.seeding=Seeder MyTorrentsView.menu.removeand=F&jern og MyTorrentsView.menu.removeand.deletetorrent=Slet &Torrent MyTorrentsView.menu.removeand.deletedata=Slet &Dataen MyTorrentsView.menu.removeand.deleteboth=Slet &Begge Dele deletedata.title=!!! Advarsel !!! deletedata.message1=Du er ved at slette data fra :\n MainWindow.menu.file.configure=Guiden &Konfiguration configureWizard.title=Guiden til konfiguration configureWizard.welcome.title=Velkommen til Guiden Vuze Konfiguration configureWizard.welcome.message=Denne guide vil hj\u00e6lpe dig med at konfigurere Vuze til det mest almindelige brug. Du kan senere \u00e6ndre i konfigurationens detaljer ved at v\u00e6lge menupunktet V\u00e6rkt\u00f8jer->Konfiguration. configureWizard.transfer.title=Overf\u00f8rsel og forbindelses ops\u00e6tning configureWizard.transfer.hint=Tip : Den bedste indstilling opn\u00e5s ved at v\u00e6lge en hastighed lidt LAVERE end din maksimum. configureWizard.transfer.message=V\u00e6lg en af nedenst\u00e5ende forbindelser. V\u00e6r opm\u00e6rksom p\u00e5 at hvis du s\u00e6tter en LAV upload hastighed vil det resultere i en LAV download hastighed. Da upload hastigheden kun t\u00e6lles Pr. Torrent du downloader, vil fors\u00f8g p\u00e5 at downloade for mange Torrents p\u00e5 samme tid ogs\u00e5 resultere i LAVE hastigheder. Vi anbefaler at bruge 5 kB/s Pr. Torrent som det ABSOLUTTE minimum. Des hurtigere du uploader, desto hurtigere vil du downloade. configureWizard.transfer.connection=Forbindelse configureWizard.transfer.connection.0=Brugerdefineret configureWizard.transfer.connection.1=Modem configureWizard.transfer.connection.2=ADSL / KABEL - xxx / 128 Kbps configureWizard.transfer.connection.3=ADSL / KABEL - xxx / 256 Kbps configureWizard.transfer.connection.4=ADSL / KABEL - xxx / 384 Kbps configureWizard.transfer.connection.5=ADSL / KABEL - xxx / 512 Kbps configureWizard.transfer.connection.6=ADSL / KABEL - xxx / 768 Kbps configureWizard.transfer.connection.7=ADSL / KABEL - xxx / 1024 Kbps configureWizard.transfer.maxUpSpeed=Maksimal Upload hastighed (KB/s) configureWizard.transfer.maxActiveTorrents=Max antal aktive configureWizard.transfer.maxDownloads=Max antal downloads configureWizard.transfer.maxUploadsPerTorrent=Max Uploads Pr. Torrent configureWizard.nat.title=NAT / Server port configureWizard.nat.message=For at f\u00e5 det bedste ud af Vuze m\u00e5 det st\u00e6rkt anbefales at der er fuldt tilg\u00e6ngelighed til og fra Internettet. Dette v\u00e6rkt\u00f8j lader dig teste og/eller \u00e6ndre porten til indg\u00e5ende peer forbindelser.\n\nBEM\u00c6RK : V\u00e6rkt\u00f8jet tester KUN din TCP forbindelse. En "Distribueret DB" kr\u00e6ver ogs\u00e5 en indg\u00e5ende UDP forbindelse men vil automatisk give besked hvis der opdages, at en firewall blokerer for adgangen.\n\nBEM\u00c6RK : TCP port 6880 er reserveret til internt brug og kan derfor ikke benyttes. configureWizard.nat.test=Test port configureWizard.nat.testing=Porten testes configureWizard.nat.ok=Ok ! configureWizard.nat.ko=NAT fejl configureWizard.nat.unable=Porten kan ikke testes : Ugyldig port angivet, eller test servicen fejlede.\nPorten er muligvis allerede i brug af en anden enhed. configureWizard.file.title=Torrents / Filer configureWizard.file.message1=Vuze gemmer \u00e5bnede Torrents i en specificeret mappe, v\u00e6lg selv hvilken mappen her : configureWizard.file.path=Sti configureWizard.file.browse=Gennemse configureWizard.file.message2=Vuze er i stand til at forts\u00e6tte dine filer \u00f8jeblikkeligt, ved at tilf\u00f8je nogle ekstra data til dine Torrents. Ved at bruge denne funktion vil du ogs\u00e5 kunne forts\u00e6tte delvist downloadede stykker. Vuze er i stand til \u00f8jeblikkelig genoptagelse, ved at tilf\u00f8je lidt data til dine Torrents. Brugen af denne funktion vil osse aktivere forts\u00e6ttelse af delvis downloadede stykker. configureWizard.file.fastResume=Aktiver hurtig forts\u00e6ttelse configureWizard.file.invalidPath=Ugyldig sti configureWizard.finish.title=Fuldendte configureWizard.finish.message=Vuze er nu konfigureret, god forn\u00f8jelse ! wizard.close.confirmation=Bekr\u00e6ftelse wizard.close.message=Vil du k\u00f8re denne guide\n n\u00e6ste gang Vuze startes? exportTorrentWizard.title=XML eksport af en Torrent exportTorrentWizard.torrentfile.title=Valg af Torrent fil exportTorrentWizard.torrentfile.message=V\u00e6lg Torrent filen der skal eksporteres exportTorrentWizard.torrentfile.path=Sti exportTorrentWizard.torrentfile.browse=Gennemse exportTorrentWizard.torrentfile.invalidPath=Ugyldig Torrent fil exportTorrentWizard.exportfile.title=Eksporter valgte fil exportTorrentWizard.exportfile.message=V\u00e6lg XML-filen der skal exportTorrentWizard.exportfile.path=Sti exportTorrentWizard.exportfile.browse=Gennemse exportTorrentWizard.exportfile.invalidPath=Ugyldig eksport-fil exportTorrentWizard.finish.title=Fuldf\u00f8rt exportTorrentWizard.finish.message=Eksporten afsluttede successfuldt exportTorrentWizard.process.inputfilebad.title=Ugyldig Torrent fil exportTorrentWizard.process.inputfilebad.message=Der opstod en fejl under adgangen til input filen : exportTorrentWizard.process.outputfileexists.title=Filen eksisterer allerede exportTorrentWizard.process.outputfileexists.message=Output filen eksisterer allerede - overskriv? exportTorrentWizard.process.torrentfail.title=Fejl ved l\u00e6sning af Torrent fil exportTorrentWizard.process.exportfail.title=Torrent eksporten fejlede exportTorrentWizard.process.unknownfail.title=Uventet fejl importTorrentWizard.title=XML import af en Torrent importTorrentWizard.torrentfile.title=Valg af input Torrent importTorrentWizard.torrentfile.message=V\u00e6lg Torrent filen der importeres til importTorrentWizard.torrentfile.path=Sti importTorrentWizard.torrentfile.browse=Gennemse... importTorrentWizard.torrentfile.invalidPath=Ugyldig Torrent fil importTorrentWizard.importfile.title=Importer valgte fil importTorrentWizard.importfile.message=V\u00e6lg XML filen der skal importeres fra importTorrentWizard.importfile.path=Sti importTorrentWizard.importfile.browse=Gennemse importTorrentWizard.importfile.invalidPath=Ugyldig import fil importTorrentWizard.finish.title=Fuldf\u00f8rt importTorrentWizard.finish.message=Importen afsluttede successfuldt importTorrentWizard.process.inputfilebad.title=Ugyldig import fil importTorrentWizard.process.inputfilebad.message=Der opstod en fejl under adgangen til input filen : importTorrentWizard.process.outputfileexists.title=Filen eksisterer allerede importTorrentWizard.process.outputfileexists.message=Output filen eksisterer allerede - skal den overskrives? importTorrentWizard.process.torrentfail.title=Fejl ved skrivning af Torrent fil importTorrentWizard.process.importfail.title=Torrent importen fejlede importTorrentWizard.process.unknownfail.title=Uventet fejl ConfigView.label.bindip=Bind til lokal IP adresse eller interface ConfigView.label.xfs.allocation=Lokaliser nye filer med en metode specifikt til XFS filesystemer ConfigView.label.xfs.allocation.tooltip=Tjek om /usr/sbin/xfs_io er korrekt installeret p\u00e5 dit system. I de fleste Linux udgivelser, er det inkluderet i "xfsprogs" programpakken. xfs.allocation.xfs_io.not.found=Placeringen af XFS filen mislykkedes fordi /usr/sbin/xfs_io ikke kan k\u00f8res. Kontroller at den er korrekt installeret p\u00e5 dit system. Original fejlmelding var "%1". ConfigView.label.zeronewfiles=Alloker diskplads og nulstil nye filer ved oprettelsen ConfigView.label.zeronewfiles.tooltip=Minimerer fragmentering ConfigView.section.stats=Statistikker ConfigView.section.stats.enable=Aktiver ConfigView.section.stats.defaultsavepath=Gem statistikker i denne mappe ConfigView.section.stats.choosedefaultsavepath=V\u00e6lg mappen som statistikker skal gemme i ConfigView.section.stats.savefreq=Gem hvert : ConfigView.section.stats.minutes=minutter ConfigView.section.stats.hours=timer ConfigView.section.stats.seconds=sekunder ConfigView.section.stats.savefile=Filnavn for statistikker : MyTorrentsView.menu.export=&XML Torrent.. MyTorrentsView.menu.host=&Udgiv... ManagerItem.finishing=Afslutter ConfigView.dialog.choosedefaulttorrentpath=V\u00e6lg din standard Torrent mappe ConfigView.dialog.choosemovepath=V\u00e6lg den mappe der skal flyttes til ConfigView.label.movecompleted=Flyt f\u00e6rdige filer (efter download) ConfigView.label.moveremoved=Flyt f\u00e6rdige filer (n\u00e5r de fjernes fra Vuze ConfigView.label.savetorrents=Gem Torrent filer MainWindow.menu.view.mytracker=Min &Tracker MainWindow.menu.view.mytracker.keybinding=Meta+2 MyTrackerView.title.full=Min tracker MyTrackerView.name=Navn : MyTrackerView.tracker=Tracker MyTrackerView.status=Status : MyTrackerView.status.started=K\u00f8rer MyTrackerView.status.stopped=Stoppet MyTrackerView.peers=Peers MyTrackerView.seeds=Seeder MyTrackerView.announces=Annonceringer MyTrackerView.uploaded=Uploadet MyTrackerView.downloaded=Downloadet : MyTrackerView.left=Tilbage ConfigView.section.style=Brugergr\u00e6nseflade ConfigView.label.set_ui_transfer_speeds=Overskriv valgfri overf\u00f8rsels hastighed ConfigView.label.set_ui_transfer_speeds.description=Du kan v\u00e6lge at definere din download og upload hastighed manuelt i statusbaren som du har til r\u00e5dighed i systembakken.\nV\u00e6rdierne skal v\u00e6re delt med komma (,). ConfigView.label.set_ui_transfer_speeds.description.download=Juster download hastigheden (i KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Juster upload hastigheden (i KB/s) ConfigView.section.style.useCustomTabs=Aktiver lukning af faneblade (kr\u00e6ver genstart) MainWindow.menu.view.plugins=&Tilf\u00f8jelser fileDownloadWindow.saveTorrentIn=Gem Torrent filen i fileDownloadWindow.title=Vuze - Torrent downloader fileDownloadWindow.downloading=Downloader fra : fileDownloadWindow.status=Status : fileDownloadWindow.state_initializing=Initialiserer fileDownloadWindow.state_downloading=Downloader fileDownloadWindow.state_error=Fejl : MainWindow.menu.file.open.url=&Placering... MainWindow.menu.file.open.url.keybinding=Meta+l openUrl.title=\u00c5ben placering openUrl.url=URL : MyTorrentsView.menu.host.error.title=Hosting af Torrent fejlede MyTorrentsView.menu.host.error.message=F\u00f8lgende fejl opstod under fors\u00f8g p\u00e5 at hoste Torrenten ConfigView.section.tracker=Tracker ConfigView.section.tracker.pollinterval=Klient opdateringsinterval (sekunder) ConfigView.section.tracker.publishenable=Udgiv Torrent detaljer p\u00e5 "" ConfigView.section.tracker.ip=Trackerens eksterne IP adresse : ConfigView.section.style.enableXPStyle=Aktiver Windows XP udseende (kr\u00e6ver genstart) IPChecker.external.service.dyndns.name=Dyn-DNS IPChecker.external.service.dyndns.url=http://www.dyndns.org IPChecker.external.service.dyndns.description=Dynamic DNS Network Services. LLC ConfigView.section.tracker.checkip=Find automatisk den eksterne IP adresse... ipCheckerWizard.title=Guiden IP-adresse kontrol ipCheckerWizard.service=Service : ipCheckerWizard.chooseService=V\u00e6lg en service fra listen til kontrol af IP-adresse ipCheckerWizard.explanations=Du kan bruge denne guide til at finde ud af hvad din eksterne IP adresse er. Hvis din IP adresse er dynamisk, anbefaler vi at du \u00e5bner en konto hos en Dynamisk DNS Service. Nogle af disse services er listet nedenfor, brug det anf\u00f8rte link til at oprette en konto (hvor det er underst\u00f8ttet). Udfyld s\u00e5 IP adressefeltet med dit dynamiske hostnavn (f.eks. hostnavn.dyndns.org). Du skal bruge et program til automatisk at opdatere din Dynamiske DNS Service med din IP adresse. P\u00e5 den m\u00e5de vil du v\u00e6re i stand til at udgive Torrents, selvom din IP adresse \u00e6ndres. ipCheckerWizard.service.description=Beskrivelse : ipCheckerWizard.service.url=Link : ipCheckerWizard.progresstitle=Kontrollerer IP adressen ipCheckerWizard.checkComplete=Fuldf\u00f8rte IP adresser : ipCheckerWizard.checkFailed=Fejl, grund : wizard.tracker.local=Brug Vuze indbyggede tracker wizard.tracker.external=Brug en ekstern tracker wizard.tracker.howToLocal=\tG\u00e5 til "Konfiguration->Tracker" for at sl\u00e5 den til wizard.announceUrl=Annoncerings-URL : IPChecker.external.service.discoveryvip.name=Discovery-vip IPChecker.external.service.discoveryvip.url=http://ip.discoveryvip.com IPChecker.external.service.discoveryvip.description=Discoveryvip - Kun IP adresse tjek IPChecker.external.httpinvalidresponse=Ugyldigt HTTP svar IPChecker.external.loadingwebpage=Henter webside IPChecker.external.analysingresponse=Analyserer svar IPChecker.external.addressextracted=Uddraget IP adresse IPChecker.external.httploadfail=Kunne ikke hente siden IPChecker.external.timeout=Timeout opst\u00e5et IPChecker.external.ipnotfound=IP-adressen blev ikke fundet ConfigView.section.tracker.pollintervalmin=Mindst ConfigView.section.tracker.pollintervalmax=Maksimum ConfigView.section.tracker.pollintervalincby=For\u00f8g med ConfigView.section.tracker.pollintervalincper=hver 'n' klienter splash.loadingImages=Indl\u00e6ser billeder splash.initializeGui=Initialiserer hovedvinduet splash.openViews=\u00c5bner faneblade splash.plugin=Indl\u00e6ser tilf\u00f8jelse : configureWizard.nat.tooManyPorts=For mange porte at teste (9 max) ConfigView.section.color=Farvevalg MyTorrentsView.menu.publish=&Udgiv... MyTrackerView.status.published=Udgivet MyTrackerView.completed=Fuldf\u00f8rte MainWindow.menu.file.open.torrentnodefault=Torrent Fil... (ingen standard lagring) MainWindow.menu.file.open.torrentnodefault.keybinding.mac=Meta+Opt+o wizard.comment=Kommentar : ConfigView.label.movetorrent=Flyt torrent ConfigView.label.movepartialdownloads=Flyttes n\u00e5r nogle filer er markeret "Download ikke" ConfigView.label.subdir_is_in_default=N\u00e5r der tjekkes om en download ligger i en fastlagt mappe skal der ogs\u00e5 tjekkes i undermapper ConfigView.section.file.decoder.label=Standard torrent koding n\u00e5r valg er p\u00e5kr\u00e6vet ConfigView.section.file.decoder.nodecoder=Ingen IPChecker.external.service.no-ip.name=Ingen-IP IPChecker.external.service.no-ip.url=http://www.no-ip.com IPChecker.external.service.no-ip.description=Dynamisk og statisk DNS service udbyder\n(er der ingen til r\u00e5dighed s\u00e5 "tjek adresse" service) ConfigView.section.tracker.publicenable=Tillad eksterne Torrents ConfigView.label.playdownloadspeech="Tal" n\u00e5r en dowmload er f\u00e6rdig ConfigView.label.playdownloadspeech.info=Tale servisen virker i \u00f8jeblikket bedst med engelsk # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Viser antal tilg\u00e6ngelige kopier af hvert stykke.\nHvis antallet til h\u00f8jre er lavere end 1, er der ikke en komplet kopi af filen tilg\u00e6ngelig\n(og der vil muligvis v\u00e6re problemer med at f\u00e6rdigg\u00f8re downloaden). GeneralView.label.trackerurl.tooltip=Klik for at kopiere annoncerings URL'en til udklipsholderen GeneralView.label.trackerurlopen.tooltip=Klik for at \u00e5bne trackerens hovedside # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Opdater brugergr\u00e6nsefladen (GUI) hver ConfigView.section.style.graphicsUpdate=Opdater de grafiske bj\u00e6lker for hver N GUI opdatering(er) ConfigView.section.style.reOrderDelay=Opdater tabeller for hver N GUI opdatering(er) (0 = aldrig) ConfigView.section.style.reOrderDelay.never=Aldrig ConfigView.section.logging=Logger ConfigView.section.logging.enable=Aktiver logfil ConfigView.section.logging.logdir=Mappe til logfil : ConfigView.section.logging.choosedefaultsavepath=V\u00e6lg lagringsmappe GeneralView.label.updatein.querying=Foresp\u00f8rger... configureWizard.nat.sharePort=Benyt 1 delt port til alle indg\u00e5ende Torrents ConfigView.section.logging.maxsize=Maksimal logfil st\u00f8rrelse : ConfigView.section.tracker.passwordenableweb=Aktiver adgangskode p\u00e5 tracker web-siden ConfigView.section.tracker.passwordenabletorrent=Aktiver adgangskode p\u00e5 Torrents ConfigView.section.tracker.username=Brugernavn ConfigView.section.tracker.password=Adgangskode columnChooser.title=V\u00e6lg de kolonner som skal vises columnChooser.move=Arranger r\u00e6kkef\u00f8lgen af kolonner ved brug af "Tr\u00e6k og Slip" funktionen columnChooser.apply=Anvend columnChooser.columnname=Kolonne Navn columnChooser.columndescription=Beskrivelse TableColumn.header.shareRatio=Delingsforhold MyTorrentsView.menu.editTableColumns=&V\u00e6lg dine kolonner wizard.operationfailed=Operationen mislykkedes authenticator.title=Bekr\u00e6ftigelse P\u00e5kr\u00e6vet authenticator.realm=Omr\u00e5de authenticator.tracker=Tracker : authenticator.user=Brugernavn authenticator.password=Adgangskode ConfigView.label.allowSendVersion=Tillad Vuze at sende versions nummer og tilf\u00e6ldig id anonymt, n\u00e5r der s\u00f8ges efter nye versioner wizard.hint.mode=Tip :\tDu kan v\u00e6lge en enkelt fil eller en mappe ved at\n\ttr\u00e6kke og slippe den p\u00e5 denne guide. wizard.hint.file=Tip :\tDu kan v\u00e6lge en enkelt fil ved brug af tr\u00e6k og slip. wizard.hint.directory=Tip :\tDu kan v\u00e6lge en enkelt mappe ved brug af tr\u00e6k og slip. MainWindow.menu.help.checkupdate=&S\u00f8g efter nye Opdateringer... TableColumn.header.down=Downloadet TableColumn.header.up=Uploadet ConfigView.section.tracker.passwordenabletorrent.info=Kr\u00e6ver kompatibel BitTorrent klient (f.eks. Vuze ConfigView.section.style.confirmationOnExit=Bekr\u00e6ft ved afslutning MainWindow.dialog.exitconfirmation.title=Afslut Vuze MainWindow.dialog.exitconfirmation.text=Vil du virkelig afslutte Vuze SystemTray.menu.stopalltransfers=Stop &Alle Overf\u00f8relser TrayWindow.menu.stopalldownloads=Stop &Alle downloads ConfigView.section.tracker.sslport.info=Se FAQ for yderligere information wizard.tracker.ssl=Brug SSL ConfigView.label.playdownloadfinished=Afspil en lyd n\u00e5r en download er f\u00e6rdig ConfigView.label.popupdownloadfinished=Popup en alarm n\u00e5r en download er f\u00e6rdig ConfigView.label.popupfilefinished=Popup en alarm n\u00e5r en fil er f\u00e6rdig TableColumn.header.pieces=Stykker TableColumn.header.pieces.info=Grafisk visning af hvilke stykker der er downloadet TableColumn.header.completion=Fuldf\u00f8relse TableColumn.header.completion.info=Grafisk visning af download vist i % ConfigView.section.style.showdownloadbasket=Vis download kurv (Tr\u00e6k og Slip Torrents) ConfigView.section.style.alwaysShowTorrentFiles=Vis altid Torrent filer i Detaljer/Filer wizard.multitracker=Tilf\u00f8j multi-tracker information til torrenten wizard.multitracker.title=Multi-tracker wizard.multitracker.configuration=Multi-tracker konfiguration wizard.multitracker.new=Ny... wizard.multitracker.edit=Rediger... wizard.multitracker.delete=Slet wizard.multitracker.group=Tracker gruppe wizard.multitracker.edit.title=Rediger multi-tracker information wizard.multitracker.edit.name=Navn : wizard.multitracker.edit.save=Gem wizard.multitracker.edit.newgroup=Ny gruppe wizard.multitracker.edit.deletegroup=Slet wizard.multitracker.edit.newtracker=Ny tracker wizard.multitracker.edit.deletetracker=Slet wizard.multitracker.edit.edit=Rediger wizard.addingmt=Tilf\u00f8jer multi-tracker information wizard.multitracker.noannounce=Annoncerings-URL'en findes ikke i din tracker-liste MyTorrentsView.menu.recheck=&Kontroller igen iconBar.showDownloadBar.tooltip=Vis Download Bj\u00e6lke iconBar.start.tooltip=Start iconBar.stop.tooltip=stop iconBar.remove.tooltip=Fjern iconBar.openNoDefault.tooltip=\u00c5ben en Torrent fil (ingen standard lagring) iconBar.openURL.tooltip=\u00c5ben en URL iconBar.openFolder.tooltip=\u00c5ben en mappe iconBar.new.tooltip=Opret en torrent iconBar.up.tooltip=Flyt op iconBar.down.tooltip=Flyt Ned iconBar.run.tooltip=\u00c5ben iconBar.host.tooltip=V\u00e6rt iconBar.publish.tooltip=Udgiv MyTorrentsView.menu.editTracker=&Rediger en tracker URL GeneralView.menu.selectTracker=V\u00e6lg ConfigView.section.stats.xslfile=XSL filnavn : ConfigView.section.stats.xslfiledetails=Dette vil blive inkluderet i statistikfilens header via m\u00e6rke ConfigView.label.savetorrentbackup=Gem backup ConfigView.section.tracker.forceport=Tving hostede eksterne Torrents til standard port ConfigView.section.ipfilter.allow=Tillad disse IP-adresseomr\u00e5der (standard er afvis) ConfigView.section.ipfilter.list.inrange=var i omr\u00e5de ConfigView.section.ipfilter.list.notinrange=var ikke i noget omr\u00e5de ConfigView.section.ipfilter.list.title=Blokerede IP adresser ConfigView.label.allowsameip=Tillad flere forbindelser fra den samme IP-adresse ConfigView.label.allowsameip.tooltip=Brug kun dette hvis du virkelig har brug for det.\nDette er en leecher beskyttelse (n\u00e5r det er deaktiveret) ). ManagerItem.superseeding=Super-Seeder ConfigView.label.userSuperSeeding=Aktiver Super-Seeding PeersView.uniquepiece=Stykke (Super-Seed tilstand) PeersView.uniquepiece.none=Ingen PeersView.timetosend=Tid til at sende stykke igen (Super Seed tilstand) ConfigView.section.style.addurlsilently=\u00c5ben URL i baggrunden ConfigView.section.style.addurlsilently.tooltip=Advarsel : Ved aktivering af denne indstilling vil programvinduet ikke blive gjort synligt igen!\nHvis ikonet i meddelelsesomr\u00e5det forsvinder, b\u00f8r du deaktivere denne indstilling. ConfigView.section.file.decoder.prompt=Sp\u00f8rg altid n\u00e5r valg af kryptering er tilg\u00e6ngeligt ConfigView.section.file.decoder.prompt.tooltip=Vis altid valgmulighederne n\u00e5r kryptering er tilg\u00e6ngeligt MyTorrentsView.menu.moveTop=Til &toppen MyTorrentsView.menu.moveEnd=Til &bunden ConfigView.label.moveonlyusingdefaultsave=Kun fra standard lagringsmappen ConfigView.label.moveonlyusingdefaultsave.tooltip=Flyt kun hvis de download'ede data ligger i standard data mappen ConfigView.label.watchtorrentfolder=Importer nye TorrentS filer automatisk ConfigView.label.watchtorrentfolder.tooltip=Kigger efter nye Torrents regelm\u00e6ssigt ConfigView.label.watchtorrentfolderinterval=interval ConfigView.label.watchtorrentfolderinterval.tooltip=Tiden mellem hver skanning af import-mappen ConfigView.dialog.choosewatchtorrentfolderpath=V\u00e6lg din mappe til automatisk Torrent import ConfigView.label.startwatchedtorrentsstopped=Begynd stoppet ConfigView.label.startwatchedtorrentsstopped.tooltip=Tilf\u00f8j nye Torrents med status STOPPET ConfigView.section.plugins=Tilf\u00f8jelser wizard.maketorrent.filesize=Filst\u00f8rrelse : wizard.maketorrent.piececount=Antal stykker : wizard.maketorrent.piecesize=Styk-st\u00f8rrelse : wizard.maketorrent.auto=Automatisk MainWindow.menu.view.stats=&Statistikker MainWindow.menu.view.stats.keybinding=Meta+5 SpeedView.title.full=Aktivitet SpeedView.downloadSpeed.title=Download hastighed : SpeedView.uploadSpeed.title=Upload hastighed ConfigView.section.style.useSIUnits=Brug IEC enheder (Kb -> Kib osv.) iconBar.top.tooltip=Flyt til toppen iconBar.bottom.tooltip=Flyt til bunden TableColumn.header.health=Tilstand MyTorrentsView.menu.health=Forklaring af tilstand health.explain.grey=Betyder at din Torrent ikke k\u00f8rer (downloader eller uploader). health.explain.red=Betyder at du ikke er forbundet til nogen peers mens du downloader. health.explain.blue=N\u00e5r du seeder betyder det, at du endnu ikke er forbundet til nogen peers.\nN\u00e5r du downloader, betyder det, at du er forbundet til nogle peers, men at trackeren er nede. health.explain.yellow=Betyder at trackeren er OK, du er forbundet til peers, men du har ikke nogen fjern forbindelser.\nDu har m\u00e5ske et NAT problem hvis dine Torrents forbliver p\u00e5 gul status hele tiden. health.explain.green=Betyder at alt fungerer fint. ConfigView.section.style.alwaysRefreshMyTorrents=Opdater altid Mine Torrents ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Denne indstilling vil opdatere Mine Torrents fanebladet, selv n\u00e5r det ikke er synligt (kan v\u00e6re n\u00f8dvendigt ved brug af visse mirc tilf\u00f8jelser) # #2.0.7.0 # security.certtruster.title=Certifikat Sikkerheds advarsel security.certtruster.intro=Sikkerhedscertifikatet er udstedt af et firma, som du ikke har tillid til security.certtruster.resource=Ressource : security.certtruster.issuedto=Udstedt til : security.certtruster.issuedby=Udstedt af : security.certtruster.prompt=\u00d8nsker du at have tillid til det? security.certtruster.yes=Ja security.certtruster.no=Nej ConfigView.section.tracker.torrentsperpage=Hvor mange Torrents Pr. side ? (0 = ubegr\u00e6nset) MainWindow.menu.file.share=&Del MainWindow.menu.file.share.file=&Fil... MainWindow.menu.file.share.dir=&Mappe... MainWindow.menu.file.share.dircontents=Mappe &Indhold... MainWindow.menu.file.share.dircontentsrecursive=Mappe Indhold... (&og undermapper)... MainWindow.dialog.share.sharefile=V\u00e6lg filen der skal deles MainWindow.dialog.share.sharedir=V\u00e6lg mappen der skal deles MainWindow.dialog.share.sharedircontents=V\u00e6lg mappeindhold der skal deles MainWindow.dialog.share.sharedircontents.recursive=inkl. undermapper globalmanager.download.remove.veto=Fjernelse af Torrent n\u00e6gtet plugin.sharing.download.remove.veto=Denne download er resultatet af en delt ressource.\nFor at fjerne downloaden m\u00e5 den relaterede deling fjernes: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Hoved ConfigView.section.tracker.web=web ConfigView.label.prioritizefirstpiece=Prioriter f\u00f8rste del af fil(er) ConfigView.label.prioritizefirstpiece.tooltip=Fors\u00f8ger at downloade starten af en fil f\u00f8rst.\nFor at opn\u00e5 mulighed for tidlig previewing. ConfigView.section.file.confirm_data_delete=Bekr\u00e6ft inden data slettes ConfigView.section.file.confirm_data_delete.tooltip=Bekr\u00e6ft sletning af data ved brug af "Fjern og slet..." TrayWindow.menu.startalldownloads=Start alle downloads SystemTray.menu.startalltransfers=Start Alle Overf\u00f8relser sharing.progress.title=Delingsforl\u00f8b sharing.progress.hide=Skjul MainWindow.menu.view.myshares=Mine delte filer MainWindow.menu.view.myshares.keybinding=Meta+3 MySharesView.title.full=Mine delte filer MySharesView.name=Navn : MySharesView.type=Type : MySharesView.type.file=Fil MySharesView.type.dir=Mappe MySharesView.type.dircontents=Indhold af mappe MySharesView.type.dircontentsrecursive=Indhold af mappe (inkl. undermapper) MySharesView.menu.remove=Fjern ConfigView.section.tracker.extensions=Udvidelser ConfigView.section.tracker.sendpeerids=Send peer identitet til downloadere ConfigView.section.tracker.enableudp=Aktiver UDP tracker protokol plugin.sharing.torrent.remove.veto=Denne tracker registrering er resultatet af en delt ressource.\nFjern den tilknyttede deling for at fjerne downloaden.: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Downloaden kan ikke fjernes da den ikke er stoppet plugin.sharing.remove.veto=Denne deling h\u00f8rer under en delt mappe og kan derfor ikke fjernes s\u00e6rskilt.\nFjern den overordnede deling GeneralView.label.hash.tooltip=Klik for at kopiere hash v\u00e6rdien til udklipsholderen ConfigView.section.tracker.maxpeersreturned=Maksimale antal af tilbagevendende peers (0 = ubegr\u00e6nset) ConfigView.label.serverport=Indg\u00e5ende TCP port ConfigView.label.serverport.tooltip=Porten skal ligge mellem 1-65535, dog ikke 6880 da den er reserveret til intern Vuze brug. configureWizard.nat.server.tcp_listen_port=Indg\u00e5ende TCP port der "lyttes" p\u00e5 ConfigView.section.sharing=Deling ConfigView.section.sharing.usessl=Brug SSL til delte ressourcer (kr\u00e6ver konfiguration af tracker) ConfigView.section.style.dropdiraction=Tr\u00e6k og slip handling for mapper ConfigView.section.style.dropdiraction.opentorrents=\u00c5ben Torrents ConfigView.section.style.dropdiraction.sharefolder=Dele mappe ConfigView.section.style.dropdiraction.sharefoldercontents=Del indholdet # # 2.0.7.x # Categories.all=Alle Categories.uncategorized=Ingen kategori CategoryAddWindow.message=Navnet p\u00e5 den nye kategori : CategoryAddWindow.title=Tilf\u00f8j ny kategori ConfigView.label.autoSeedingIgnoreInfo=Ignorerede Torrents flyttes til bunden af seeder-k\u00f8en. De bliver ikke startet automatisk.\nReglerne for ignorering af Torrents g\u00e6lder ikke for Torrents, der opfylder kriteriet for at f\u00e5 f\u00f8rste prioritet.\nHvis ikke andet er angivet, bruges v\u00e6rdien 0 til at deaktivere en regel. ConfigView.label.directory=Til mappen ConfigView.label.disconnetseed.tooltip=N\u00e5r der seedes p\u00e5 en torrent, afbrydes forbindelsen til andre klienter som ogs\u00e5 seeder.\nForbindelsen til dem er ikke n\u00f8dvendig. ConfigView.label.ignoreCase=Der skelnes ikke mellem STORE og eller sm\u00e5 bogstaver. ConfigView.label.ignoreSeeds=Ignorer Torrents med mindst ConfigView.label.importdirectory=Importer fra mappen ConfigView.label.minPeersToBoostNoSeeds.tooltip=Torrents uden seedere og med f\u00e6rre peers end du angiver her\nvil blive flyttet mod bunden af k\u00f8en. ConfigView.label.minPeersToBoostNoSeeds=Tildel lavere seeding rang til Torrents uden seeds og f\u00e6rre end ConfigView.label.minSeedingTime.tooltip=Seeding rangen svinger ofte i et mindre tidsperiode, hvilket kan for\u00e5rsage at en Torrent\nautomatisk bliver startet blot for straks at blive stoppet og sat i k\u00f8 igen. Denne indstilling\nminimerer problemet ved at tvinge en Torrent til mindst at seede i det angivne antalsekunder.\n Du kan dog altid stoppe den manuelt. ConfigView.label.minSeedingTime=Minimum seeding tid i sekunder ConfigView.label.minSpeedForActiveDL.tooltip=Der bliver altid brugt en download plads de f\u00f8rste 30 sekunder\nefter en ufuldst\u00e6ndig Torrent starter. ConfigView.label.minSpeedForActiveDL=Undlad at t\u00e6lle en torrent med hvis download hastigheden er under ConfigView.label.peers=Peers ConfigView.label.queue.debuglog=Log "debug" informationen ConfigView.label.queue.debuglog.info=Tilf\u00f8jer "debug" information om k\u00f8en til konsol/log-filen.\n"Debug" informationerne fort\u00e6ller, omend en smule kryptisk,\nstatus for Torrents samt hvorfor de /ikke er startetet/er i k\u00f8. ConfigView.label.queue.minQueueingShareRatio=Stop eller s\u00e6t ikke en Torrent i k\u00f8 f\u00f8r delingsforholdet n\u00e5r ConfigView.label.ratio=forhold ConfigView.label.removeOnStop=Fjern en Torrent fra listen efter at den automatisk er stoppet ConfigView.label.savedirectory=Gem i mappen ConfigView.label.seeding.autoReposition.tooltip=Er dette sl\u00e5et til, vil r\u00e6kkef\u00f8lgen af Torrents (se "Nr" kolonnen) blive \u00e6ndret til at matche rangen p\u00e5 dine seeds.\nDette er nyttigt hvis du ikke \u00f8nsker at se dine seeds rang numrene, men stadig \u00f8nsker at kende r\u00e6kkef\u00f8lgen de f\u00e6rdige Torrents vil starte i. ConfigView.label.seeding.autoReposition=Arranger automatisk Torrents baseret p\u00e5 deres seed rang ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Ofte vil Torrents med lavt seeder antal og h\u00f8jt peer antal ikke have en fuld kopi tilg\u00e6ngelig blandt til tilsluttede peers.\nDerfor \u00f8nsker du m\u00e5ske ikke at seeder reglerne lader som om, at der er en fuld kopi (og s\u00e5ledes ukorrekt reducerer dens rang) ConfigView.label.seeding.fakeFullCopySeedStart=men kun for Torrents med mindst ConfigView.label.seeding.ignore=Ignorer Regler ConfigView.label.seeding.ignore0Peers=Ignorer Torrents med 0 peers ConfigView.label.seeding.ignoreRatioPeers=Ignorer Torrents som har mindst 1 seeder for hver ConfigView.label.seeding.ignoreShareRatio=Ignorer Torrents som har et delingsforhold p\u00e5 ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorer torrent selv hvis en\nf\u00f8rsteprioritets-regel er opfyldt ConfigView.label.seeding.ignore.header.rule=Regel ConfigView.label.seeding.ignore.header.value=V\u00e6rdi ConfigView.label.seeding.firstPriority.info=Torrents med f\u00f8rsteprioritet vil altid blive placeret i toppen af k\u00f8en. Enhver Torrent der matcher kriterierne for f\u00f8rsteprioritet vil ikke automatisk blive stoppet og sat i k\u00f8. En Torrent der matcher kriterierne for f\u00f8rsteprioritet vil tage en sidel\u00f8bende download plads hvis n\u00f8dvendigt. ConfigView.label.seeding.firstPriority.FP=F\u00f8rste Prioritet ConfigView.label.seeding.firstPriority=F\u00f8rsteprioritet g\u00e5r til Torrents med ConfigView.label.seeding.firstPriority.following=af de f\u00f8lgende : ConfigView.label.seeding.firstPriority.shareRatio=Et delingsforhold under ConfigView.label.seeding.firstPriority.seedingMinutes=Den tid der er g\u00e5et siden en download blev f\u00e6rdig og skiftede til seeding ConfigView.label.seeding.firstPriority.DLMinutes=Den tid der er g\u00e5et siden downloaden blev startet ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Ved at antage at der findes 1 komplet kopi for X antal peers, reduceres rangen for Torrents med et h\u00f8jt antal peers.\nTorrents med et h\u00f8jt antal peers har som regel ogs\u00e5 en stor trafik.\nDenne indstilling \u00e6ndrer ikke ved det viste antal seeds. ConfigView.label.seeding.numPeersAsFullCopy=Antag at der findes 1 komplet kopi for hver (0 = deaktiver) ConfigView.label.seeding.preferLargerSwarms.tooltip=Hvis du hovedsageligt seeder Torrents med peers der er g\u00e5et i st\u00e5, giver det mening at prioritere st\u00f8rre sv\u00e6rme.\nHvis du hovedsageligt seeder Torrents med h\u00f8j tilg\u00e6ngelighed, giver det mere mening at prioritere mindre sv\u00e6rme. ConfigView.label.seeding.preferLargerSwarms=Prioriter st\u00f8rre sv\u00e6rme n\u00e5r flere Torrents har den samme rang ConfigView.label.seeding.rankType.none.tooltip=Arranger efter Nr kolonnen ConfigView.label.seeding.rankType.none=Ingen ConfigView.label.seeding.rankType.peerSeed.options=Indstillinger for seeds : peers forhold ConfigView.label.seeding.rankType.peerSeed.tooltip=H\u00f8jere delingsforhold = H\u00f8jere rang ConfigView.label.seeding.rankType.peerSeed=Peers : seeder forhold ConfigView.label.seeding.rankType.seed.fallback=Fald tilbage til peers : seeds forhold over\n(0 = aldrig) ConfigView.label.seeding.rankType.seed.options=Indstillinger til seeder t\u00e6lling ConfigView.label.seeding.rankType.seed.tooltip=F\u00e6rre seedere giver h\u00f8jere rang ConfigView.label.seeding.rankType.seed=Kun seeder t\u00e6lling ConfigView.label.seeding.rankType.timedRotation.tooltip=Alle f\u00e6rdige Torrents sat i k\u00f8 vil skiftes til at have seeding status.\nTiden mellem hvert skift bestemes af "Minimum seed tid" nedenfor. ConfigView.label.seeding.rankType.timedRotation=Tidsbestemt rotation ConfigView.label.seeding.rankType.tooltip=H\u00f8jest rangerende Torrents bliver startet automatisk.\nN\u00e5r en anden Torrent f\u00e5r en h\u00f8jere rang, stopper den lavere rangerende og g\u00e5r tilbage i k\u00f8en.\n\nKun Torrents i K\u00f8 status er tilg\u00e6ngelige til automatisk start.\nStoppede Torrents bliver aldrig startet automatisk. ConfigView.label.seeding.rankType=Arranger f\u00e6rdige Torrents til auto start baseret p\u00e5 : ConfigView.label.stopAfterMinutes=Stop automatisk en downloadet torrent, n\u00e5r den har seedet i et stykke tid ConfigView.label.switchpriority.tooltip=En lav prioritet reducerer st\u00f8rrelsen p\u00e5 upload b\u00e5ndbredden som er tildelt en Torrent. ConfigView.pluginlist.info=F\u00f8lgende tilf\u00f8jelser er blevet identificeret. Ikke alle tilf\u00f8jelser kan konfigureres. ConfigView.pluginlist.noplugins=Ingen tilf\u00f8jelser blev fundet. ConfigView.section.pluginslist=Liste ConfigView.section.queue.seeding=Seeder ConfigView.section.queue.seeding.autoStarting=Automatisk start ConfigView.section.queue.seeding.ignore=Ignorer Regler ConfigView.section.queue.seeding.firstPriority=F\u00f8rsteprioritet ConfigView.section.queue.main=Generelt ConfigView.section.queue=K\u00f8 ConfigView.section.torrents=Torrents ConfigView.text.all=alle ConfigView.text.hours=timer ConfigView.text.ignoreRule=Ignorer regeler ConfigView.text.ignore=Ignorer ConfigView.text.minutes=minutter ConfigView.text.neverIgnore=Ignorer aldrig ConfigView.text.any=hvilken som helst DownloadManager.error.datamissing=Data mangler MainWindow.menu.file.open.torrentforseeding=Torrent Fil... (Til seeding) MainWindow.menu.language.refresh=&Opdater ManagerItem.forced=Tvunget ManagerItem.queued=Sat i k\u00f8 MySeedersView.header=F\u00e6rdige Torrents (Seeder) TableColumn.header.availability.info=Antallet af hele kopier som er tilg\u00e6ngelige TableColumn.header.availability=Tilg\u00e6ngelighed TableColumn.header.category=Kategori MyTorrentsView.header=Uf\u00e6rdige Torrents (Downloader) TableColumn.header.maxuploads=Maksimum antal Uploads MyTorrentsView.menu.category.delete=&Slet kategori MyTorrentsView.menu.forceStart=&Tving start MyTorrentsView.menu.queue=&S\u00e6t i k\u00f8 / Start MyTorrentsView.menu.setCategory.add=&Tilf\u00f8j en kategori... MyTorrentsView.menu.setCategory=Tildel/Tilf\u00f8j en kategori TableColumn.header.savepath=Lagringsmappe TableColumn.header.SeedingRank=Seed rang TableColumn.header.totalspeed.info=Den totale hastighed for alle Torrents du er forbundet til TableColumn.header.totalspeed=Den totale hastighed splash.initializePlugins=Initialiserer plugins StartStopRules.SPratioMet=S/P Forholdet er OK StartStopRules.FP0Peers=FP / 0 Peers StartStopRules.0Peers=0 peers StartStopRules.numSeedsMet=Antallet af seedere OK StartStopRules.ratioMet=Peers/Seeder OK StartStopRules.shareRatioMet=Delingsforholdet er OK StartStopRules.waiting=Venter StartStopRules.firstPriority=1. prioritet ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Del indholdet (incl. undermapper) DownloadManager.error.unabletostartserver=Serveren kan ikke startes - kontroller konfigurationen af den indg\u00e5ende port / firewall tilladelser for at programmet kan agere som server GeneralView.label.creationdate=Oprettet den : ConfigView.section.tracker.announcescrapepercentage=Interval for opdatering af annonceringen for hver %\nf.eks. 200 = 2:1. 0 = lad peer bestemme ManagerItem.stopping=Stopper ConfigView.section.tracker.announcecacheperiod=Annoncering af cache (millisekunder) ConfigView.section.tracker.scrapecacheperiod=Opdater cache (millisekunder) ConfigView.section.tracker.scrapeandcache=Opdatering og cache ConfigView.section.tracker.announcecacheminpeers=Aktiver cache ved flere peers end : MyTrackerView.scrapes=Opdateringer fileDownloadWindow.retry=Pr\u00f8v igen MyTrackerView.bytesin=Bytes ind MyTrackerView.bytesinave=Gennemsnitligt ind MyTrackerView.bytesout=Bytes ud MyTrackerView.bytesoutave=Gennemsnitligt ud ConfigView.section.file.max_open_files=Maksimale antal \u00e5bne filer der l\u00e6ses fra og/eller skrives til\n(0 = ubegr\u00e6nset) ConfigView.section.file.max_open_files.tooltip=Nyttig hvis du downloader Torrents indeholdende hundrede/tusinder af filer, og hvis du n\u00e5r gr\u00e6nsen for operativsystemets antal af \u00e5bne filer. ConfigView.section.proxy=Proxy Instillinger ConfigView.section.proxy.enable_proxy=Aktiver proxying af tracker kommunikationer (kr\u00e6ver genstart) ConfigView.section.proxy.host=V\u00e6rt ConfigView.section.proxy.port=Port : ConfigView.section.proxy.username=Brugernavn ConfigView.section.proxy.password=Adgangskode ConfigView.section.proxy.enable_socks=SOCKS-kompatibel proxy wizard.createtorrent.extrahashes=Tilf\u00f8j hash-v\u00e6rdier for andre netv\u00e6rk (f.eks. Gnutella2, eDonkey2000) GeneralView.label.connected=tilsluttet GeneralView.label.in_swarm=i sv\u00e6rmen ManagerItem.initializing=Initialiserer AlertMessageBox.error=Fejl AlertMessageBox.warning=Advarsel AlertMessageBox.comment=Info AlertMessageBox.information=Info AlertMessageBox.unread=Du har ul\u00e6ste advarsels beskeder - klik her for at l\u00e6se den/dem. SharedPortServer.alert.selectorfailed=Der kunne ikke \u00e5bnes en port for indg\u00e5ende data.\nKontroller om firewall indstillinger tillader at java(w).exe fungerer som server. Tracker.alert.listenfail=Kunne ikke etablere en lytte port %1.\nKontroller at porten ikke bruges af andre programmer\nog tjek samtidig om der k\u00f8rer en anden kopi af Azureus. DiskManager.alert.movefileexists=Kunne ikke flytte f\u00e6rdige filer.\nFilen %1 eksisterer allerede i destinationsmappen. DiskManager.alert.movefilefails=Kunne ikke flytte f\u00e6rdige filer.\nFlytning af filen %1 mislykkedes, %2 DiskManager.alert.movefilerecoveryfails=Kunne ikke genoprette efter mislykket flytning.\nGenopretning af filen %1 mislykkedes, %2 ConfigView.section.tracker.logenable=Log periodisk statistikker til "tracker.log" SpeedView.stats.title=Statistikker SpeedView.stats.total=I alt : SpeedView.stats.session=Denne session : SpeedView.stats.session.tooltip=Total (Protokol) SpeedView.stats.downloaded=Downloadet : SpeedView.stats.uploaded=Uploadet : SpeedView.stats.ratio=Delingsforhold : SpeedView.stats.uptime=Uploadet i : SpeedView.stats.now=Nu : SpeedView.stats.now.tooltip=Total (Protokol) AutoMigration.useralert=Resultatet efter Automatisk migrering af Vuze brugers config filer/mapper :\n\n%1\nAlle auto-migreringer som mislykkedes SKAL migreres manuelt.\nHUSK AT OPDATERE LAGRINGS MAPPER OG STIER I KONFIGURATIONEN HVIS DE ER MIGRERET! # # > 2.0.8.0 # OpenTorrentWindow.title=\u00c5ben Torrent(s) OpenTorrentWindow.message=Eksperimentel OpenTorrentWindow.addFiles=&Tilf\u00f8j filer OpenTorrentWindow.dataLocation=Stien hvor data skal lagres : OpenTorrentWindow.startMode=Tilf\u00f8j tilstand OpenTorrentWindow.startMode.queued=Sat i k\u00f8 OpenTorrentWindow.startMode.stopped=Stoppet OpenTorrentWindow.startMode.forceStarted=Tvunget start OpenTorrentWindow.addPosition=Position i k\u00f8en OpenTorrentWindow.addPosition.first=F\u00f8rste OpenTorrentWindow.addPosition.last=Sidste TableColumn.header.remaining.info=Resterende m\u00e6ngde at downloade TableColumn.header.remaining=Resterende ConfigView.section.tracker.enablecompact=Aktiver kompakt annoncerings-protokol ConfigView.section.tracker.enablekey=Aktiver videresendelse af n\u00f8gler til tracker for \u00f8get sikkerhed ConfigView.section.file.perf=Ydelsesindstillinger ConfigView.section.file.perf.explain=Advarsel! \u00c6ndringer af disse parametre kan p\u00e5virke din downloadhastighed negativt. Genstart p\u00e5kr\u00e6vet.\nHvis du har problemer med "out of memory" fejl, kan du overveje at begr\u00e6nse antal forbindelser Pr. Torrent (Se Konfiguration->Overf\u00f8rsel) ConfigView.section.file.max_open_files.explain=\u00c5bning af for mange filer kan for\u00e5rsage problemer med operativsystemet pga. begr\u00e6nsede ressourcer. Denne indstilling kan begr\u00e6nse antallet af samtidige \u00e5bne filer. popup.error.hide=Skjul popup.error.details=Detaljer ConfigView.section.style.colorOverrides=Overskriv farver ConfigView.section.style.colorOverride.progressBar=Forl\u00f8b Bj\u00e6lken ConfigView.section.style.colorOverride.error=Fejl MainWindow.status.tooOld=er gammel. Opdater den venligst. ConfigView.section.style.colorOverride.warning=Advarsel ConfigView.section.style.colorOverride.altRow=Hver anden r\u00e6kke ConfigView.section.file.save.peers.enable=Gem peer forbindelser for hurtig genoprettelse ConfigView.section.file.save.peers.max=Det maksimale antal peers der gemmes (0 = ubegr\u00e6nset) ConfigView.section.file.save.peers.pertorrent=Pr. Torrent ConfigView.label.max_peers_per_torrent=Standart maksimum antal forbindelser Pr. Torrent (0 = ubegr\u00e6nset) ConfigView.label.max_peers_total=Maksimum antal forbindelser i alt (0 = ubegr\u00e6nset) ConfigView.section.style.colorOverrides.reset=Genskab farver ConfigView.section.language.info=Der s\u00f8ges efter nye opdateringer hver gang Vuze startes hvis dette er aktiveret. ConfigView.section.language.enableUpdate=Aktiver online opdatering ConfigView.section.language.UpdateURL=Opdater URL ConfigView.section.language.UpdateNow=Opdater nu! Button.revert=Gendan MyTorrentsView.menu.changeDirectory=Skift Data mappe GenericText.column=kolonne MyTorrentsView.menu.thisColumn.remove=Fjern kolonne MyTorrentsView.menu.thisColumn.toClipboard=Kopier teksten til udklipsholderen MyTorrentsView.menu.tracker=Tracker ConfigView.download.abbreviated=D:\u005c ConfigView.upload.abbreviated=U : ConfigView.complete.abbreviated=C:\u005c TableColumn.header.secondsseeding=Seedet i TableColumn.header.secondsseeding.info=Den totale tid du har seedet Torrenten i. TableColumn.header.secondsdownloading=Downloadet i TableColumn.header.secondsdownloading.info=Den totale tid Torrenten har Downloadet. ConfigView.section.tracker.udpversion=UDP protokol version (1 eller 2) window.updateswt.title=Din SWT version er for gammel! window.updateswt.text=Din SWT version er for gammel!\nSWT er det grafikbibliotek som Vuze bruger, og den version du har er for gammel til at k\u00f8re den seneste version af Azureus. Klik p\u00e5 OK for at opdatere din SWT. window.updateswt.status=Status : window.updateswt.failed=Fejl under opdateringen. Klik OK for at pr\u00f8ve igen. window.updateswt.status.downloading.updater=Downloader opdateringsmodulet window.updateswt.status.finding=S\u00f8ger efter den seneste version af SWT window.updateswt.status.downloading=Downloader den seneste version af SWT window.updateswt.status.done=Genstarter window.updateswt.ok=OK window.updateswt.cancel=Annuller swt.updater.downloader.downloading=Downloader SWT fra swt.updater.urlsgetter.downloading=Henter en server liste fra swt.updater.urlsgetter.platform=SWT til platform : window.updateswt.ignore=Ignorer ConfigView.section.style.useFancyTabs=Brug smarte faneblade splash.initializeGM=Initialiserer den globale torrent h\u00e5ndtering splash.loadingTorrents=Indl\u00e6ser Torrents splash.firstMessageNoI18N=( : Vuze : ) MyTorrentsView.menu.thisColumn.sort=&Sorter Scrape.status.ok=Opdatering OK Scrape.status.error=Fejl ved opdatering : Scrape.status.error.badURL=Annoncerings URL'en f\u00f8lger ikke specifikationerne til opdatering. Scrape.status.error.nohash=Hash mangler i svaret. Scrape.status.error.invalid=Ugyldigt svar. Scrape.status.nextScrapeAt=N\u00e6ste opdatering om %1 Scrape.status.scraping=Opdaterer... Scrape.status.initializing=Venter p\u00e5 opdatereing... Scrape.status.scraping.queued=Opdatering sat i k\u00f8... ConfigView.label.minSpeedForActiveSeeding=Undlad at t\u00e6lle f\u00e6rdige Torrents med hvis hastigheden er under ConfigView.section.stats.exportpeers=Eksporter peer detaljer MainWindow.menu.view.irc.moved=IRC er nu tilg\u00e6ngelig som et plugin, se http://azureus.sourceforge.net/plugin_list.php. Efter installationen v\u00e6lges menupunktet Vis->Plugins->IRC for at f\u00e5 adgang. MyTrackerView.webui.contextmenu.copyurl=Kopier Torrent URL til udklipsholderen ConfigView.section.file.torrent.ignorefiles=Filer der skal springes over n\u00e5r en Torrent oprettes\nf.eks .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignorerer fil ConfigView.section.style.useUnitsRateBits=Brug bits i stedet for bytes ved byte-baserede v\u00e6rdier (Kib/s->Kibit/s osv.) ConfigView.section.interface.resetassoc=Nulstil explorer fil-associeringer (Torrent) ConfigView.section.interface.resetassocbutton=Genskab ConfigView.section.interface.checkassoc=Kontroller fil-associeringer ved opstarten dialog.associations.title=Kontrol af fil-associeringer Button.yes=Ja Button.no=Nej ConfigView.label.seeding.autoStart0Peers=Start alle f\u00e6rdige Torrents uden peers automatisk ConfigView.label.seeding.autoStart0Peers.tooltip=Aktiver hvis du \u00f8nsker at trackeren altid skal vise antal seeds dialog.associations.prompt=Vuze er ikke standard program for BitTorrent filer.\n\u00d8nsker du at associere Torrent filer med Vuze dialog.associations.askagain=Kontroller ved opstart ConfigView.section.plugins.update=Plugin opdatering Plugin.pluginupdate.enablecheck=Aktiver automatisk kontrol af nye tilf\u00f8jelses versioner plugins.basicview.status=Status : plugins.basicview.activity=Aktivitet : plugins.basicview.progress=Forl\u00f8b : plugins.basicview.log=Log : ConfigView.label.maxdownloadspeed=KB/s total maksimum download hastighed (0 = ubegr\u00e6nset) splash.loadingTorrent=Indl\u00e6ser torrent splash.of=af ConfigView.section.plugins.irc=IRc UpdateWindow.title=Vuze opdaterings assistent UpdateWindow.header=F\u00f8lgende komponenter b\u00f8r opdateres : UpdateWindow.columns.install=Installer UpdateWindow.columns.name=Navn : UpdateWindow.columns.version=Version : UpdateWindow.columns.size=St\u00f8rrelse : UpdateWindow.cancel=Annuller UpdateWindow.quit=Afslut UpdateWindow.close=Luk UpdateWindow.ok=Opdater UpdateWindow.restart=Genstart Vuze nu UpdateWindow.status.downloading=Downloader UpdateWindow.status.done=F\u00e6rdig UpdateWindow.status.failed=Mislykkedes UpdateWindow.status.restartNeeded=Det er n\u00f8dvendigt at genstarte ConfigView.pluginlist.broken=Beskadiget ConfigView.pluginlist.whereToPut=Placer brugerspecifikke tilf\u00f8jelser i hver deres mappe under : ConfigView.pluginlist.whereToPutOr=Placer delte tilf\u00f8jelser under : MainWindow.statusText.checking=Der s\u00f8ges efter nye opdateringer TableColumn.header.OnlyCDing4=Kun seedet TableColumn.header.OnlyCDing4.info=Tidsrum hvor en Torrent kun har v\u00e6re seeding. Tidsrummet for download (og seeding) t\u00e6ller ikke med. ConfigView.section.style.alternateTablePainting=Brug alternativ metode til at tegne grafiske tabelkolonner (kr\u00e6ver muligvis genstart) UpdateWindow.status.restartMaybeNeeded=Det kan v\u00e6re n\u00f8dvendigt genstarte ConfigView.pluginlist.shared=Delte PeersView.host=Udbyders Navn PeersView.host.info=Peers udbyder navn, hvis det er tilg\u00e6ngeligt (kan p\u00e5virke ydeevnen) MainWindow.menu.help.whatsnew=&Hvad er nyt? ConfigView.label.checkonstart=S\u00f8g efter nye Opdateringer n\u00e5r Vuze startes ConfigView.label.periodiccheck=Kontroller periodisk om en ny version af programmet er tilg\u00e6ngeligt ConfigView.label.opendialog=Automatisk \u00e5bning af OpdateringsAssistenten n\u00e5r en ny opdatering er tilg\u00e6ngelig MainWindow.updateavail=Klik her for at hente opdateringer MainWindow.status.unofficialversion=Vuze - Beta MainWindow.status.latestversionunchecked=Kontrol for ny version er deaktiveret GeneralView.label.updatein.stopped=Stoppet StartStopRules.menu.viewDebug=Vis debug information ConfigView.section.style.doNotUseGB=Brug ikke enheden Gb (gigabyte) ConfigView.section.style.doNotUseGB.tooltip=Bruger enheden Mb (megabyte) selv for v\u00e6rdier over 1024 Mb (=1 Gb) MainWindow.menu.help.plugins=&Hent tilf\u00f8jelser ConfigView.section.plugins.TrackerWeb=Tracker web ConfigView.section.tracker.enablecategories=Opdel Torrents efter kategori health.explain.share=Betyder at en torrent enten er hosted eller udgivet p\u00e5 din tracker. ConfigView.section.tracker.createcert=Opret selvudstedt certifikat ConfigView.section.tracker.createbutton=Opret security.certcreate.title=Opret selvudstedt certifikat security.certcreate.intro=Dette vindue giver dig mulighed for at oprette et selvudstedt certifikat. security.certcreate.alias=Alias : security.certcreate.strength=Styrke : security.certcreate.firstlastname=Fornavn og efternavn : security.certcreate.orgunit=Afdeling : security.certcreate.org=Organisation : security.certcreate.city=By eller omr\u00e5de : security.certcreate.state=Landsdel : security.certcreate.country=Landekode, 2 bogstaver : security.certcreate.ok=Opret security.certcreate.cancel=Annuller security.certcreate.createok=Certifikatet blev oprettet uden fejl security.certcreate.createfail=Der opstod en fejl under oprettelsen af certifikatet ConfigView.section.plugins.webui=Swing web gr\u00e6nsefalde ConfigView.section.plugins.xml_http_if=XML/HTTP gr\u00e6nseflade webui.passwordenable=Aktiver adgangskode webui.user=Brugernavn webui.password=Adgangskode webui.port=port (*) webui.protocol=Protokol (*) webui.homepage=Startside (*) webui.rootdir=Rod mappe (*) webui.rootres=Rod ressource (*) webui.mode=Tilstand (*) webui.mode.info=Tilstand kan v\u00e6re\n\t"full"(komplet)\t = alle funktioner er tilg\u00e6ngelige (standard)\n\t"view"(l\u00e6se)\t = Kun l\u00e6sning (men opdateringsintervallet kan \u00e6ndres) webui.access=Adgang (*) webui.access.info=Adgang kan v\u00e6re\n\t"lokal"\t = Kun den lokale computer kan tilslutte\n\t"alle"\t = Uhindret adgang (stardard)\n\tIP\t = f.eks. 192.168.0.2\t\t\tkun \u00e9n IP adresse\n\tIP1-IP2\t = f.eks. 192.168.0.1-192.168.0.255\tomr\u00e5de af IP adresser GeneralView.label.maxdownloadspeed=Maksimum Ned Security.keystore.corrupt=N\u00f8glefilen "%1" kunne ikke indl\u00e6ses. Slet n\u00f8glefilen og opret/importer certifikatet igen Security.keystore.empty=N\u00f8glefilen er tom. Opret et selvudstedt certifikat (se V\u00e6rkt\u00f8jer-> Konfiguration->Sikkerhed) eller importer et eksisterende certifikat til "%1" webui.restart.info=\u00c6ndring af parametre markeret med (*) tr\u00e6der f\u00f8rst i kraft efter en genstart. GeneralView.label.maxdownloadspeed.tooltip=Maksimum download hastighed (0 = ubegr\u00e6nset) ConfigView.section.UPnP=UPnP upnp.enable=Aktiver UPnP upnp.info=Universal Plug and Play (UPnP) tillader automatisk tilslutning af porte p\u00e5 routere som underst\u00f8tter UPnP. upnp.mapping.dataport=Indg\u00e5ende peer data port upnp.mapping.tcptrackerport=TCP tracker port upnp.mapping.udptrackerport=UDP trackerens Port upnp.alert.differenthost=UPnP : "%1" er reserveret af "%2" - V\u00e6lg en anden port upnp.alert.mappingok=UPnP : "%1" oprettet upnp.alert.mappingfailed=UPnP : "%1" fejlede upnp.alertsuccess=Rapporterer om vellykket tilslutninger upnp.alert.lostdevice=UPnP : Mistede forbindelsen til service "%1" p\u00e5 UPnP enhed "%2" upnp.grabports=Tilslut port selvom den er ejet af en anden computer upnp.refresh.label=Opdater forbindelser upnp.refresh.button=Opdater upnp.alert.mappinggrabbed=UPnP : "%1" oprettet - taget fra "%2" upnp.mapping.tcpssltrackerport=TCP SSL tracker port upnp.alertothermappings=Rapporterer om porte ejet af andre computere upnp.alertdeviceproblems=Rapporterer om problemer med UPnP enhed ConfigView.pluginlist.coreplugins=F\u00f8lgende indbyggede tilf\u00f8jelser er indl\u00e6st : Peers.column.DLedFromOthers=Fra andre Peers.column.DLedFromOthers.info=Datam\u00e6ngde som er downloadet fra andre mens de var forbundet til dig Peers.column.UpDownRatio=Op/Ned Peers.column.UpDownRatio.info=Peers "Uploadet/Downloadet" forhold Peers.column.UpRatio=Upload forhold Peers.column.UpRatio.info=Peers "Uploadet fra dig/Uploadet fra andre" forhold upnp.releasemappings=Frigiv forbindelser ved afslutning webui.upnpenable=Aktiver UPnP for denne port (*) ConfigView.section.file.friendly.hashchecking=Brug mindre belastende metode til kontrol af hash-v\u00e6rdier ConfigView.section.file.friendly.hashchecking.tooltip=En anelse langsommere, men med v\u00e6sentlig mindre belastning af CPU/systemet, n\u00e5r hashfilen og filstykkerne skal tjekkes. ConfigView.section.tracker.seedretention=Det maksimale antal seedere opn\u00e5et Pr. Torrent (0 = ubegr\u00e6nset) ConfigView.section.tracker.seedretention.info=Bem\u00e6rk : Upload statistikkerne til Seeds som ikke opretholdes mistes ConfigView.section.tracker.port=Aktiver tracker p\u00e5 HTTP porten ConfigView.section.tracker.sslport=Aktiver trackeren p\u00e5 HTTPS porte ConfigView.section.tracker.publicenable.info=Dette tillader andre at oprette Torrents som bruger din tracker\nuden at du er v\u00e6rt eller udgiver dem Button.clear=Ryd MainWindow.IPs.tooltip=Seneste opdatering af IP filter listen : %1\nAntal IP filtre i listen - Antal blokerede IP adresser i denne session.\nDobbeltklik for detaljerede oplysninger. ConfigView.section.ipfilter.list.banned=er blevet bandlyst ConfigView.section.ipfilter.list.baddata=har sendt d\u00e5rlig data : hyppigheden = Button.reset=Nulstil ConfigView.section.ipfilter.bannedinfo=IP'er som har sendt d\u00e5rlig data - bandlyses hvis gr\u00e6nsen overskrides ConfigView.section.ipfilter.blockedinfo=IP'er som er blevet bandlyst grundet IP filteret download.removerules.name=Regler for fjernelse download.removerules.unauthorised.info=Torrents som ikke er tilladte er dem med en bem\u00e6rkning som indeholder enten "ikke tilladt(e)" eller "ingen tilladelse(r)" i fejlmeldingen download.removerules.unauthorised=Automatically remove unauthorised Torrents download.removerules.unauthorised.seedingonly=\tKun hvis der seedes download.removerules.removed.ok=Automatisk fjernelse af Torrenten "%1" lykkedes. Dette blev gjort af Torrentens regler for fjernelse. download.removerules.updatetorrents=Fjern Vuze opdaterings Torrent i henhold til sv\u00e6rmens krav ConfigView.label.defaultstarttorrentsstopped=Som standart tilf\u00f8j nye Torrentes i stoppet tilstand ConfigView.section.server.enableudp=Aktiver UDP trackerens klient protokol. upnp.mapping.dataportudp=UDP trackerens klient Port ConfigView.section.file.decoder.showlax=Vis mindst sansynlige krypteringsvalg ConfigView.section.file.decoder.showall=Betragt alle krypterings muligheder MainWindow.status.updowndetails.tooltip=Detaljer for Download/Upload hastigheden\nH\u00f8jre klik for at \u00e6ndre, Dobbelt-klik for at \u00e5bne statistikker TrackerClient.announce.warningmessage=Tracker til "%1" returneret advarsel "%2" ConfigView.section.tracker.natcheckenable=Tjek forbindelsesevnen p\u00e5 "indg\u00e5ende dataporte" og reporter om fejl til peers ConfigView.section.tracker.publishenabledetails=Udgiv alle Torrent detaljer ConfigView.section.tracker.publishenablepeerdetails=Udgiv peer detaljer MyTrackerView.badnat=D\u00e5rlig NAT MyTrackerView.badnat.info=Seedere/Peers som ikke bestod en NAT kontrol ConfigView.section.tracker.natchecktimeout=Tjek "timeout" (sekunder) ConfigView.section.file.perf.cache.enable=Aktiver disk cache ConfigView.section.file.perf.cache.size=St\u00f8rrelse af cache i %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=O&verf\u00f8rsler MainWindow.menu.transfers.startalltransfers=St&art Alle MainWindow.menu.transfers.stopalltransfers=St&op Alle MainWindow.menu.transfers.pausetransfers=&Pause... MainWindow.menu.transfers.pausetransfers.keybinding.mac=Meta+ MainWindow.menu.transfers.resumetransfers=&Genoptag ConfigView.label.experimental.osx.kernel.panic.fix=Eksperimental rettelse til kernel panikanfald p\u00e5 dual-cpu OSX systemer (kr\u00e6ver genstart) SystemTray.menu.pausetransfers=Pause Overf\u00f8relser SystemTray.menu.resumetransfers=Genoptag Overf\u00f8relser ConfigView.section.file.perf.cache.trace=Spor cashe operationer til diagnose form\u00e5l ConfigView.section.interface.enabletray=Aktiver System Bakken (kr\u00e6ver genstart af Vuze PeerManager.status.error=Fejl Stats.title.full=Statistikker TransferStatsView.title.full=Overf\u00f8relser CacheView.title.full=Cache fil CacheView.general.size=Total st\u00f8rrelse : CacheView.general.inUse=I brug : CacheView.general.title=Cache Information CacheView.reads.title=I/O L\u00e6sninger CacheView.reads.fromFile=Fra Fil : CacheView.reads.fromCache=Fra Cache : CacheView.reads.hits=L\u00e6sning : CacheView.writes.title=I/O Skriver CacheView.writes.toCache=Til Cache : CacheView.writes.toFile=Til Fil : CacheView.writes.hits=Gemt CacheView.speeds.title=Data Hastigheder CacheView.speeds.reads=L\u00e6ser : CacheView.speeds.writes=Skriver : CacheView.speeds.fromCache=Fra/Til Cache : CacheView.speeds.fromFile=Fra/Til Fil : CacheView.reads.#=Nr : CacheView.reads.amount=M\u00e6ngde : CacheView.reads.avgsize=Gennemsnitlig St\u00f8rrelse : openUrl.referrer=Henviser til side URL : openUrl.referrer.info=Kun kr\u00e6vet af websider som underst\u00f8tter det ConfigView.label.maxuploadspeedseeding=Den maksimale upload hastighed n\u00e5r der KUN seedes (0 = ubegr\u00e6nset) ConfigView.label.transfer.ignorepeerports=Ignorer peers med disse data porte (';' adskilte, f.eks. 0;25) ConfigView.section.proxy.enable_socks.peer=Aktiver proxying af peer kommunikation, men kun for udg\u00e5ende forbindelser (kr\u00e6ver genstart) ConfigView.section.proxy.peer.informtracker=Informer "tracker" om begr\u00e6nsning ConfigView.section.proxy.socks.version=SOCKS Version PiecesView.legend.written=Skrevet PiecesView.legend.requested=Anmodet PiecesView.legend.incache=Dataen er i Cachen PiecesView.typeItem.0=Langsom PiecesView.typeItem.1=Hurtig PiecesView.type=Type : Security.jar.tools_not_found=JAR signering mislykkedes - "tools.jar" blev ikke fundet i %1. Se V\u00e6rkt\u00f8jer->Tracker->Sikkerhed for flere detaljer. Security.jar.signfail=JAR signering mislykkedes - %1 ConfigView.section.security.toolsinfo=Signerede JAR filer bruges til at underst\u00f8tte visse tilf\u00f8jelser, F.eks "Swing web Interface" (n\u00e5r det er indstillet til det).\nFor at kunne signere en JAR fil er det n\u00f8dvendigt at have adgang til "tools.jar" filen som kommer med Sun JDK og ikke JRE installationen.\nHvis du kun har JRE skal du installere JDK.\nAzurerus kan normalt finde filen til dig men hvis dette mislykkedes kan du tilf\u00f8je mappen der indeholder filen her. ConfigView.section.security.toolsdir=Mappen som indeholder "tools.jar" ConfigView.section.security.choosetoolssavedir=V\u00e6lg mappen som indeholder "tools.jar" authenticator.torrent=Torrents ConfigView.section.proxy.peer.same=Brug de samme proxy instillinger til "tracker og peer kommunikations proxy ConfigView.section.connection.network.max.simultaneous.connect.attempts=Maksimum samtidige udg\u00e5ende forbindelses fors\u00f8g ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Maksmum antal af nye udg\u00e5ende forbindelses-etableringer som Vuze skal fors\u00f8ge ad gangen.\nOBS : WindowsXP Service Pack 2 (SP2) p\u00e5byder en system-begr\u00e6nsning p\u00e5 10 samtidige forbindelses-fors\u00f8g.\nStandart v\u00e6rdi er 8. ConfigView.section.file.perf.cache.size.explain=Cachen bruges til at reducere l\u00e6sning fra og skrivning til disken.\nMedmindre du bruger JAVAs valgmulighed "-XX:MaxDirectMemorySize" til at fastsl\u00e5 den tilg\u00e6ngelige hukommelses st\u00f8rrelse til cache og netv\u00e6rks IO brug, b\u00f8r du s\u00e6tte v\u00e6rdien mindst %1 under din maksimum VM st\u00f8rrelse.\nDin nuv\u00e6rrende maksimum st\u00f8rrelse til VM er %2. Se wiki p\u00e5 %3 for instruktioner i hvordan st\u00f8rrelsen \u00e6ndres.\nHvis ikke der bruges fornuftige instillinger vil fejlmeldingen "utilstr\u00e6kkelig hukommelse" (out of memory) vises.\nMere end 32 Mb cache er formentlig helt un\u00f8dvendigt. MyTorrentsView.menu.setSpeed.unlimit=Ingen begr\u00e6nsning MyTorrentsView.menu.setSpeed.unlimited=Ubegr\u00e6nset MyTorrentsView.menu.setSpeed.disable=Deaktiver Upload MyTorrentsView.menu.setSpeed.disabled=Deaktiveret MyTorrentsView.menu.setSpeed.in=i MyTorrentsView.menu.setSpeed.slots=slots af GeneralView.label.maxuploadspeed=Maksimum Op GeneralView.label.maxuploadspeed.tooltip=maksimum upload hastighed (0 = ubegr\u00e6nset) MyTorrents.items.UpSpeedLimit.disabled=Ingen Upload MyTorrents.items.UpSpeedLimit.unlimited=Ubegr\u00e6nset TableColumn.header.maxupspeed=Maksimum Upload Hastighed TableColumn.header.maxupspeed.info=Maksimum Upload Hastighed Pr. Torrent ConfigView.section.file.perf.cache.enable.write=Cashe downloaded data for at redusere disk-skrivning og for at neds\u00e6tte disk-l\u00e6sning som kr\u00e6ves ved tjek af stykker ConfigView.section.file.perf.cache.enable.read=Udf\u00f8r forud-l\u00e6sning for at redusere disk-l\u00e6sning n\u00e5r der uploades ConfigView.section.tracker.separatepeerids=Brug forskellige peer identiteter til tracker og data kommunikation ConfigView.section.tracker.separatepeerids.info=\u00d8ger anonymiteten, n\u00e5r der downloades og/eller seedes anonymt\nimens der bruges en ikke-anonym tracker forbindelse ConfigView.section.interface.wavlocation=Placering af .wav filen ConfigView.section.interface.wavlocation.info=V\u00e6lg .wav filen eller lad denne st\u00e5 blank for at bruge standart lyden ConfigView.section.tracker.server=Server ConfigView.section.tracker.client=Klient ConfigView.section.tracker.client.connecttimeout=Forbindelses timeout (sekunder) ConfigView.section.tracker.client.readtimeout=L\u00e6se timeout (sekunder) MainWindow.menu.tools=&V\u00e6rkt\u00f8jer FilesView.path=Sti : FilesView.fullpath=Vis den fuldst\u00e6ndige sti FilesView.remaining=Resterende stykker : TableColumn.header.trackername=Tracker Navn TableColumn.header.trackername.info=Trackerens navn baseret p\u00e5 annoncerings URL'en ConfigView.group.override=Underkende indstillinger ConfigView.section.file.perf.cache.notsmallerthan=Filer mindre end (i %1) skal ikke cashes PeersView.menu.blockupload=Bloker Upload PeersView.menu.kickandban=Spark af og Banlys PeersView.menu.kickandban.reason=Peer blev manuelt afvist PeersView.state=Tilstand : PeersView.state.info=Tilstanden af peer forbindelsen PeersView.state.connecting=Tilslutter PeersView.state.handshake=Venter p\u00e5 h\u00e5ndtryk PeersView.state.established=Fuldt etableret ConfigView.section.tracker.processinglimits=Proces begr\u00e6nsninger ConfigView.section.tracker.maxgettime=Maksimal tid til GET processen (sekunder) (0 = ubegr\u00e6nset) ConfigView.section.tracker.maxgettime.info=Bruges til annonceringer og opdateringer ConfigView.section.tracker.maxposttimemultiplier=Multiplicering af GET tid til POST processen (0 = ubegr\u00e6nset) ConfigView.section.tracker.maxposttimemultiplier.info=Bruges til skema udfyldelser og Uploads ConfigView.section.tracker.maxthreads=Maksimum vedvarende foresp\u00f8rgelser DownloadManager.error.operationcancancelled=Handling annuleret Torrent.create.progress.cancelled=Handling annuleret sharing.progress.cancel=Annuller wizard.maketorrents.autoopen=\u00c5ben Torrenten til Seeding N\u00e5r downloaden er f\u00e6rdig ConfigView.section.sharing.rescanenable=Aktiver periodisk scanning af delte filer/mapper og tjek om der er \u00e6ndringer ConfigView.section.connection.advanced=Avanceret Netv\u00e6rks instillinger ConfigView.section.connection.advanced.url=http://www.azureuswiki.com/index.php/AdvancedNetworkSettings/ ConfigView.section.connection.advanced.mtu=Forbindelses Makimum Transmitions enhed (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Maksimum st\u00f8rrelse p\u00e5 pakker som kan sendes p\u00e5 en gang over et netv\u00e6rket.\nVuze bruger MTU-40 (MSS) til upload pakke optimering.\nAnbefalede v\u00e6rdier :\n 576 - Opkalds forbindelser\n1492 - PPPoE bredb\u00e5nds forbindelser\n1500 - Ethernet, DSL og Cable bredb\u00e5nds forbindelser ConfigView.section.connection.advanced.SO_RCVBUF=Socket SO_RCVBUF st\u00f8rrelse (0 = brug operativsystemets (OS) standart) ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=S\u00e6tter standart socket SO_RCVBUF v\u00e6rdien (i bytes), i.e. TCP modtager vindus st\u00f8rrelse og skala.\nSom Vuze standart er feltet tomt, hvilket betyder at det er standarten for det underliggende operativsystem (OS) som bruges.\nOBS Linux fordobler den angivne v\u00e6rdi. ConfigView.section.connection.advanced.SO_SNDBUF=Socket SO_SNDBUF st\u00f8rrelse (0 = brug operativsystemets (OS) standart) ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=S\u00e6tter standart socket SO_SNDBUF v\u00e6rdien (i bytes), i.e. TCP sendte vindues st\u00f8rrelse.\nSom Vuze standart er feltet tomt, hvilket betyder at det er standarten for det underliggende operativsystem (OS) som bruges.\nOBS Linux fordobler den angivne v\u00e6rdi. ConfigView.section.interface.confirm_torrent_removal=Vis bekr\u00e6ftigelses dialogen inden en Torrent fjernes ConfigView.section.interface.confirm_torrent_removal.tooltip=Bekr\u00e6ft handlingen n\u00e5r der fjernes en Torrent fra Mine Torrents. MyTorrentsView.confirm_torrent_removal=Er du sikker p\u00e5 du vil fjerne?\n TableColumn.header.seed_to_peer_ratio=Seed2Peer Forhold TableColumn.header.seed_to_peer_ratio.info=Sv\u00e6rmens totale Seed2Peer Forhold PeersView.connected_time=Tilsluttet tid PeersView.connected_time.info=Den totale tid forbundet med peer ConfigView.section.interface.display.add_torrents_silently=Tilf\u00f8j Torrent uden lyd ConfigView.section.interface.display.add_torrents_silently.tooltip=Tilf\u00f8j en Torrent uden at aktivere Vuze hoved vindue. TableColumn.header.maxdownspeed=Maksimum Download Hastighed TableColumn.header.maxdownspeed.info=Maksimum Download Hastighed Pr. Torrent PeersGraphicView.title=Sv\u00e6rm ConfigView.section.tracker.passwordwebhttpsonly=Tillad kun adgang via HTTPS TableColumn.header.torrentpath=Torrentens placering TableColumn.header.torrentpath.info=Torrentens placering p\u00e5 disken ConfigView.section.sharing.torrentcomment=Kommentar til oprettet Torrent ConfigView.label.copyanddeleteratherthanmove=Kopier og derefter slet den originale data, fremfor at flytte dataen i en operation - det kan afhj\u00e6lpe data tab p\u00e5 nogle fil systemer ConfigView.label.openstatsonstart=\u00c5ben Fanen "Statistikker" n\u00e5r Vuze startes swt.install.window.title=Vuze Tilf\u00f8jelses Installering swt.install.window.ok=Installere swt.install.window.header=De f\u00f8lgene komponenter er blevet valgt til installation : swt.uninstall.window.title=Afinstallering af Vuze Tilf\u00f8jelse swt.uninstall.window.ok=Fjern swt.uninstall.window.header=F\u00f8lgende komponenter er markeret til fjernelse : installPluginsWizard.title=Installer tilf\u00f8jelser installPluginsWizard.mode.title=V\u00e6lg en installations metode installPluginsWizard.mode.list=Fra liste p\u00e5 sourceforge.net installPluginsWizard.list.title=Liste over installerbare tilf\u00f8jelser installPluginsWizard.list.loading=Vent mens tilf\u00f8jelsen indl\u00e6ses. installPluginsWizard.list.loaded=V\u00e6lg den tilf\u00f8jelse du vil installere. installPluginsWizard.list.name=Navn : installPluginsWizard.list.version=Version : installPluginsWizard.list.description=Beskrivelse af tilf\u00f8jelse installPluginsWizard.finish.title=Installationen k\u00f8rer installPluginsWizard.finish.explanation=Den valgte tilf\u00f8jelse bliver installeret med opdaterings assistenten.\n\nV\u00e6r t\u00e5lmodig, da kan tage et stykke tid f\u00f8r assistenten vises.\n\nDobbelt klik til venstre p\u00e5 statusbj\u00e6lken for at se en detaljeret raport. installPluginsWizard.details.loading=Indl\u00e6ser detaljer, vent... installPluginsWizard.mode.file=Fra Fil : installPluginsWizard.installMode.title=V\u00e6lg installations typen installPluginsWizard.installMode.user=Installer denne tilf\u00f8jelse kun til dig installPluginsWizard.installMode.shared=Installer denne tilf\u00f8jelse til alle brugere installPluginsWizard.file.title=S\u00f8g efter den tilf\u00f8jelse du vil installere installPluginsWizard.file.file=Fil : installPluginsWizard.file.invalidfile=Denne fil er ikke en gyldig Vuze tilf\u00f8jelse. installPluginsWizard.file.browse=Gennemse... uninstallPluginsWizard.title=Afinstaller tilf\u00f8jelse uninstallPluginsWizard.list.title=Liste over installerede tilf\u00f8jelser uninstallPluginsWizard.list.loaded=V\u00e6lg den tilf\u00f8jelse du \u00f8nsker at afinstallere. installPluginsWizard.list.nullversion=Ingen Version uninstallPluginsWizard.finish.title=Forl\u00f8b af afinstallationen uninstallPluginsWizard.finish.explanation=Den udvalgte tilf\u00f8jelse vil blive afinstalleret med opdaterings Assistenten MainWindow.menu.plugins.installPlugins=Installations Guiden... MainWindow.menu.plugins.uninstallPlugins=Afinstallations Guiden... ConfigView.section.ipfilter.totalIPs=%1 IP'er blokeret ialt, hvilket er %2 af internettet. update.instance.install=Kontrolerer installationen update.instance.uninstall=Kontrolerer afinstallationen update.instance.update=S\u00f8ger efter opdateringer MainWindow.status.update.tooltip=Dobbelt klik for at se status information updater.progress.window.title=Aktuelle installations opgaver updater.progress.window.info=Klik p\u00e5 "Afbryd" for at afbryde alle udest\u00e5ende opgaver Button.abort=Afbryd ConfigView.section.ipfilter.enablebanning=Bloker peers som gentagende gange sender d\u00e5rlig data Network.alert.acceptfail=Der opstod for mange efterf\u00f8lgende fejl p\u00e5 port %1, %2 - s\u00e5 processen er afbrudt. Firewallens instillinger til denne port skal v\u00e6re indstillet til at acceptere indg\u00e5ende forbindelser. MyShares.column.category=Kategori UpdateWindow.restartLater=Genstart Vuze senere MainWindow.menu.file.restart=Genstart Vuze MainWindow.dialog.restartconfirmation.title=Genstart Vuze MainWindow.dialog.restartconfirmation.text=Vil du virkelig genstarte Vuze deletetorrent.message1=Du er ved at sl\u00e6tte TORRENTEN til :\n deletetorrent.message2=\nEr du sikker p\u00e5 du vil det? ConfigView.label.prioritizemostcompletedfiles=Prioritere mest f\u00e6rdige filer splash.plugin.init=Initialiserer tilf\u00f8jelse : ConfigView.section.style.osx_small_fonts=Brug sm\u00e5 skrifttyper (Genstart kr\u00e6vet) ConfigView.section.tracker.tcpnonblocking=Brug ikke-blokerende I/O til TCP tracker processer. V\u00e6lges denne mulighed kr\u00e6ves det at trackeren k\u00f8rer p\u00e5 en alternativ port. Dette er eksperimentalt!!!l ConfigView.section.tracker.nonblocking=Ikke-blokerende valgmuligheder ConfigView.section.tracker.nonblockingconcmax=Det maksimum samtidige antal forbindelser (0 = ubegr\u00e6net) MyTorrentsView.menu.exportmenu=Exporter MyTorrentsView.menu.exporttorrent=Torrent.. ConfigView.group.scrape=Opdatering ConfigView.section.tracker.client.scrapeinfo=Deaktivering af opdateringer vil forhindre mange Torrents regler om k\u00f8 i at virke,\nda reglerne er afh\u00e6ngige af den information som modtages fra sv\u00e6rmen n\u00e5r trackeren opdateres. ConfigView.section.tracker.client.scrapeenable=Aktiver opdatering ConfigView.section.tracker.client.scrapestoppedenable=Opdater Torrents som ikke k\u00f8rer Scrape.status.disabled=Opdatering er deaktiveret MyTorrentsView.menu.explore=Vis fil MyTorrentsView.menu.explore._mac=Vis i stifinder MyTorrentsView.menu.explore._windows=Vis i Explorer wizard.maketorrents.autohost=Udgiv denne Torrent p\u00e5 den indbyggede tracker ConfigView.label.overrideip=Overskriv IP adressen der sendes til trackeren (NAT) - Brug kun hvis du er sikker p\u00e5 at du har brug for det! ConfigView.label.overrideip.tooltip=Informer trackeren om anden IP addresse(r) end den de udg\u00e5ende pakker kommer fra. For ikke at bruge denne mulighed skal den v\u00e6re blank. ConfigView.section.connection.group.networks=Netv\u00e6rk ConfigView.section.connection.group.networks.info=Standart valg af tilladte netv\u00e6rk til peer-peer data transmition ConfigView.section.connection.networks.prompt=Bekr\u00e6ft valg n\u00e5r en download med anonym tracker er tilf\u00f8jet ConfigView.section.connection.networks.Public=Offentligt IP netv\u00e6rk (ikke anonymt) ConfigView.section.connection.networks.I2P=I2P netv\u00e6rk ConfigView.section.connection.networks.Tor=The Onion Router (TOR) netv\u00e6rk TableColumn.header.networks=Netv\u00e6rk TableColumn.header.networks.info=Tilladte netv\u00e6rk til peer-peer data komunikation Scrape.status.networkdisabled=Netv\u00e6rket er ikke aktiveret ConfigView.section.tracker.server.group.networks=Netv\u00e6rk ConfigView.section.tracker.server.group.networks.info=V\u00e6lg de netv\u00e6rk hvorfra trackeren vil acceptere peers window.networkselection.title=Netv\u00e6rks Valg window.networkselection.info=Torrentlisten herunder best\u00e5r af trackers som underst\u00f8tter f\u00f8lgende netv\u00e6rk.\nV\u00e6lg dem der skal aktiveres til tracker og peer komunikation.\nHvis det er en anonym tracker som underst\u00f8tter synlige/offentlige klienter skal b\u00e5de det anonyme og synlige/offentlige netv\u00e6rk aktiveres.\n!!!OBS OBS OBS!!! Aktivering af det synlige/offentlige netv\u00e6rk har den helt \u00e5benlyse konsekvens at du ikke l\u00e6ngere vil v\u00e6re anonym! window.networkselection.description=Torrent : plugins.basicview.clear=Ryd ConfigView.section.connection.group.peersources=Peer kilder ConfigView.section.connection.group.peersources.info=Standart valg af tilladt kilde til peer forbindelser ConfigView.section.connection.peersource.Tracker=Fra en tracker ConfigView.section.connection.peersource.DHT=Decentraliseret tracking ConfigView.section.connection.peersource.PeerExchange=Leveret af en anden peer ConfigView.section.connection.peersource.Plugin=Tilf\u00f8jet af et tilf\u00f8jelsesprogram ConfigView.section.connection.peersource.Incoming=Indg\u00e5ende forbindelse PeersView.source=Kilde : PeersView.source.info=Peers kilde TableColumn.header.peersources=Peer Kilden TableColumn.header.peersources.info=Tilladte peer kilder til etablering af peer forbindelser wizard.tracker.dht=Decentraliseret (Kun For Vuze klienter) MyTorrentsView.menu.advancedmenu=Avanceret MyTorrentsView.menu.networks=Netv\u00e6rk MyTorrentsView.menu.peersource=Peers Kilde ConfigView.section.sharing.permitdht=Tillad decentraliceret tracking n\u00e5r trackeren er utilg\u00e6ngelig ConfigView.section.sharing.protocol=Protokol for delte recurser PeersView.Messaging.info=Underst\u00f8tter avancerede beskeder API. ConfigView.label.queue.newseedsmovetop=Flyt nyligt f\u00e6rdige Torrents til f\u00f8rst p\u00e5 seedinglisten ConfigView.label.seeding.firstPriority.ignore.info=V\u00e6r opm\u00e6rksom p\u00e5 at brug af disse regler KAN resultere i at en torrent\nstopper s\u00e5 snart downloaden er f\u00e6rdig ConfigView.label.seeding.firstPriority.ignore=Ignorer ovenst\u00e5ende F\u00f8rste Prioritet regler istedet for : ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents med en Seeds til Peers deling over ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents med 0 Peers ConfigView.section.tracker.sendjavaversionandos=Send Java version og operativsystemets (OS) navn MagnetPlugin.contextmenu.exporturi=Kopier URI magneten til udklipsholderen ConfigView.section.plugins.dht=Distribueret DB dht.info=Denne tilf\u00f8jelse underst\u00f8tter bl.a decentraliceret tracking, - deaktivering af dette vil reducere din evne til at downloade dht.enabled=Aktiver den distributed database dht.portdefault=Brug standart porten dht.port=UDP port til databasen dht.execute.command=Diagnose kommandoer dht.execute.info=Klik her for at udf\u00f8re kommandoen dht.execute=K\u00f8r dht.logging=Aktiver tracking af aktiviteter ConfigView.section.plugins.dhttracker=Distribrueret Tracker ConfigView.section.file.nativedelete._mac=Flyt IKKE slettede filer til papirkurven ConfigView.section.file.nativedelete._windows=Flyt slettede filer til papirkurven ConfigView.section.logging.generatediagnostics=Opret ConfigView.section.logging.generatediagnostics.info=Opret diagnose informationer og kopier til udklipsholderen og log filen, hvis dette er konfigureret ConfigView.section.sharing.privatetorrent=Privat torrent - accepter kun peers fra trackeren MainWindow.menu.tools.nattest=&NAT / Firewall Tester Button.apply=Tilf\u00f8j Button.close=Luk window.welcome.title=Velkommen til Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Udgivelsesnotater dht.reseed.group=Seed igen dht.reseed.ip=IP adrasse dht.reseed.port=Port : dht.reseed=Seed igen dht.reseed.info=Seed databasen igen dht.diagnostics.group=Diagnose DHTView.title.full=Distribueret Database DHTView.title.fullcvs=Distribueret Database CVS DHTView.general.title=Generalt DHTView.general.uptime=Uploadet i : DHTView.general.users=Brugere : DHTView.general.nodes=Noder : DHTView.general.leaves=Forlader : DHTView.general.contacts=Kontakter : DHTView.general.replacements=Omrokerede : DHTView.general.live=Lever : DHTView.general.unknown=Ukendt : DHTView.general.dying=D\u00f8ende : DHTView.transport.title=Overf\u00f8rsels Detaljer DHTView.transport.packets=Pakker : DHTView.transport.bytes=Bytes : DHTView.transport.received=Modtaget : DHTView.transport.sent=Sendt : DHTView.transport.in=Ind : DHTView.transport.out=Ud : DHTView.operations.title=Detaljer for handlingen DHTView.operations.sent=Sendt : DHTView.operations.ok=OK : DHTView.operations.failed=Mislykkede : DHTView.operations.received=Modtaget : DHTView.operations.ping=Ping : DHTView.operations.findNode=Find Node : DHTView.operations.findValue=Find V\u00e6rdi : DHTView.operations.store=Lagring : DHTView.activity.title=Aktivitet DHTView.activity.status=Status : DHTView.activity.status.true=I k\u00f8 DHTView.activity.status.false=K\u00f8rer DHTView.activity.type=Type : DHTView.activity.type.1=Hent Internt DHTView.activity.type.2=Hent Externt DHTView.activity.type.3=Anbring Internt DHTView.activity.type.4=Anbring Externt DHTView.activity.target=M\u00e5let : DHTView.activity.details=Detaljer : DHTView.db.title=Databasen DHTView.db.keys=N\u00f8gler : DHTView.db.values=V\u00e6rdier : DHTView.db.local=Lokal : DHTView.db.direct=Direkte : DHTView.db.indirect=Indirekte : DHTView.db.divfreq=Hyppige Div : DHTView.db.divsize=St\u00f8rrelse Div : MainWindow.dht.status.tooltip=N\u00e5r den distribuerede database k\u00f8rer, vises her et sk\u00f8n p\u00e5 antallet af online brugere MainWindow.dht.status.disabled=DHT Deaktiveret MainWindow.dht.status.failed=DHT Mislykkedes MainWindow.dht.status.initializing=DHT Initialiserer MainWindow.dht.status.users=%1 Online brugere MainWindow.dht.status.unreachable=Firewalled af DHT MainWindow.dht.status.unreachabletooltip=Der er tilsyneladende et problem med den Distribuerede Databases UDP og kortl\u00e6gning af porte (NAT/firewall) MyTorrentsView.menu.setUpSpeed=Juster Upload hastighed MyTorrentsView.menu.setDownSpeed=Juster Download Hastighed ConfigView.section.tracker.client.showwarnings=Vis advarsels beskeder som reporteres af trackerne dht.advanced=Aktiver avancerede instillinger dht.advanced.group=Avancerede instillinger dht.advanced.label=Brug kun disse v\u00e6rdier hvis du virkelig ved hvad du g\u00f8r ConfigView.section.logging.loggerenable=Aktiver logging ConfigView.section.ipfilter.blockbanning=Bandlys en gruppe p\u00e5 256 adresser n\u00e5r mindst dette antal i gruppen er blevet bandlyst MyTrackerView.passive=Passiv TableColumn.header.swarm_average_speed=Gennemsnitlig hastighed i sv\u00e6rmen TableColumn.header.swarm_average_speed.info=Den gennemsnitlige hastighed for peers i sv\u00e6rmen TableColumn.header.comment=Kommentar TableColumn.header.comment.info=En brugerdefineret kommentar til downloaden TableColumn.header.commenticon=Kommentar Ikon TableColumn.header.commenticon.info=Vis ikonet hvis downloaden har en brugerdefineret kommentar MyTrackerView.category=Katagori MainWindow.menu.file.open.torrentfortracking=Torrent Fil...(Kun til tracking) VivaldiView.title.full=Picasso MyTrackerView.date_added=Tilf\u00f8jet ConfigView.section.tracker.portbackup=Reserve porte (';' separerede) ConfigView.label.playfilespeech="Tal" n\u00e5r en fil er f\u00e6rdig ConfigView.label.playfilespeech.info=Tale servisen virker i \u00f8jeblikket bedst med engelsk ConfigView.label.playfilefinished=Afspil en lyd n\u00e5r en fil er f\u00e6rdig ConfigView.label.backupconfigfiles=Lav backup af konfigurations filerne til evt gendannelses form\u00e5l ConfigView.section.tracker.client.scrapesingleonly=Deaktiver Pr. tracker opdateringer (Dette kan afhj\u00e6lpe trackere som reporterer om "URL too long" (414) fejl) dht.ipfilter.log=Log brud p\u00e5 IP Filter ConfigView.label.seeding.addForSeedingDLCopyCount="tilf\u00f8j til seeding" downloads betragtes som at have downloaded dette antal kopier ActivityView.legend.limit=Begr\u00e6nsning af Hastighed ActivityView.legend.achieved=Opn\u00e5et Hastighed ActivityView.legend.peeraverage=Gennemsnit ActivityView.legend.swarmaverage=Sv\u00e6rmens Gennemsnit ActivityView.legend.trimmed=Trimmet MyTorrentsView.menu.movemenu=Flyt Filer MyTorrentsView.menu.movedata=Flyt Data Filer... MyTorrentsView.menu.movetorrent=Flyt Torrent fil... MyTorrentsView.menu.movedata.dialog=V\u00e6lg ny placering DHTView.operations.data=Data : DHTView.general.reachable=Tilg\u00e6ngelig : DHTView.general.rendezvous=Rendezvous : ConfigView.label.queue.maxactivetorrentswhenseeding=Maksimum n\u00e5r der KUN seedes (0 = ubegr\u00e6nset) IrcView.title.short=IRC Views.plugins.IRC.title=IRC - Online Teknisk Support Formats.units.persec=/s Formats.units.TiB=Tib Formats.units.Tibit=Tibit. Formats.units.TB=Tb Formats.units.Tbit=Tbit. Formats.units.GiB=Gib Formats.units.Gibit=Gibit. Formats.units.GB=Gb Formats.units.Gbit=GBit Formats.units.MiB=Mib Formats.units.Mibit=Mibit. Formats.units.MB=Mb Formats.units.Mbit=MBit Formats.units.KiB=Kib Formats.units.Kibit=Kibit. Formats.units.kB=Kb Formats.units.KB=Kb Formats.units.kbit=Kbit Formats.units.B=B Formats.units.bit=Bit Formats.units.alot=En Masse !!! ConfigView.section.ipfilter.persistblocking=Gem blokerede IP detaljer ved genstart FilesView.menu.rename=Omd\u00f8b eller Omdirriger FilesView.menu.rename_only=Omd\u00f8b FilesView.menu.retarget=Omdirriger FilesView.rename.choose.path=V\u00e6lg en ny eller eksisterende fil FilesView.rename.choose.path.dir=V\u00e6lg en ny eller eksisterende mappe FilesView.rename.confirm.delete.title=Bekr\u00e6ft sletning FilesView.rename.confirm.delete.text=Bekr\u00e6ft sletning af original fil "%1" FilesView.rename.filename.title=Omd\u00f8b fil FilesView.rename.filename.text=V\u00e6lg et nyt navn til filen ConfigView.section.mode=Tilstand ConfigView.section.mode.beginner=Begynder ConfigView.section.mode.beginner.wiki.definitions=BitTorrent ordforr\u00e5d ConfigView.section.mode.intermediate=Udvidet ConfigView.section.mode.intermediate.wiki.host=V\u00e6rt for filer ConfigView.section.mode.intermediate.wiki.publish=Offentlig\u00f8rer filer ConfigView.section.mode.advanced=Avanceret ConfigView.section.mode.advanced.wiki.main=Wiki Forside ConfigView.section.mode.beginner.text=Alt hvad du beh\u00f8ver for at downloade Torrents.\nBrug denne instilling hvis du kun vil bestyre dine Torrents. ConfigView.section.mode.intermediate.text=Adgang til Tracker funktion.\nBrug denne instilling hvis du \u00f8nsker at lave din egen Tracker og vil v\u00e6re v\u00e6rt for/offentlig\u00f8re dine filer. ConfigView.section.mode.advanced.text=Adgang til netv\u00e6rks instillinger.\nBrug denne instilling hvis du ved hvad MTU eller ingen blokering af I/O er... Files.column.storagetype=Lagrings Type : Files.column.fileext=Type : FileItem.storage.compact=Kompakt MessageBoxWindow.rememberdecision=Husk mit valg ConfigView.section.interface.cleardecisions=Ryd dialog beslutningerne i hukommelsen ConfigView.section.interface.cleardecisionsbutton=Ryd ConfigView.section.interface.cleartrackers=Ryd trackers i hukommelsen ConfigView.section.interface.cleartrackersbutton=Ryd configureWizard.welcome.usermodes=Brugergr\u00e6nsefladen afg\u00f8rer hvor mange valgmuligheder der vises i menuen V\u00e6rkt\u00f8jer > Valgmuligheder. Det er i din bedste interesse at v\u00e6lge den korrekte indstilling. FilesView.rename.failed.title=Omd\u00f8bning/Omdirrigering mislykkedes FilesView.rename.failed.text=Handlingen mislykkedes, formegentlig fordi den valgte sti/mappe er ugyldig diagnostics.log_found=Vuzeblev ikke afsluttet korrekt. Tjek for diagnose log filen og vurder om de(n) skal reporteres til Vuze teamet hvis det er en program fejl. Tjek osse p\u00e5 Wiki under "Vuze Dissapears" (se i Hj\u00e6lp menuen) ManagerItem.paused=Pauset Utils.link.visit=Bes\u00f8g ConfigView.section.connection.serverport.wiki=Gode port valg ConfigView.section.transfer.speeds.wiki=Gode indstillinger til hastigheden installPluginsWizard.installMode.info.title=Information installPluginsWizard.installMode.info.text=Du beh\u00f8ver ikke tilf\u00f8jelser for at Vuze fungerer korrekt. Tilf\u00f8jelser indeholder funktioner som er for forn\u00f8jelsens skyld og muligheder for f.eks automatisering og fjernkontrol. S\u00f8rg for at l\u00e6se tilf\u00f8jelsens beskrivelse grundigt f\u00f8r du v\u00e6lger at installere den. De fleste tilf\u00f8jelser er fuldst\u00e6ndig sikre at afpr\u00f8ve, men der er ingen grund til at overbelaste din konfigurering med tilf\u00f8jelser du alligevel ikke bruger. Views.plugins.Distributed.DB.title=Distribrueret DB Views.plugins.Distributed.Tracker.title=Distribueret tracker Views.plugins.Plugin.Update.title=Tilf\u00f8jelses opdatering Views.plugins.UPnP.title=UPnP Views.plugins.UPnP.title.tooltip=Plug and Play - Universal openUrl.url.info=Underst\u00f8tter http, https, magnet og raw hex infohash strenge TableColumn.header.swarm_average_completion=Peers gennemsnitlige f\u00e6rdigg\u00f8relse TableColumn.header.swarm_average_completion.info=Den gennemsnitlige f\u00e6rdigg\u00f8relse i % for peers i sv\u00e6rmen GeneralView.label.swarm_average_completion=Gennemsnitlig f\u00e6rdigg\u00f8relse : GeneralView.label.swarm_average_completion.tooltip=Den gennemsnitlige f\u00e6rdigg\u00f8relse, vist i procent, for peers i sv\u00e6rmen MainWindow.nat.status.unknown=NAT MainWindow.nat.status.tooltip.unknown=Firewall/NAT kontakt status ukendt (TCP) MainWindow.nat.status.ok=NAT - OK MainWindow.nat.status.tooltip.ok=Kontakt OK (TCP) MainWindow.nat.status.probok=NAT - OK? MainWindow.nat.status.tooltip.probok=Forbindelsen er OK, der er dog ingen nye Indg\u00e5ende TCP forbindelser MainWindow.nat.status.bad=Blokeret af Firewallen MainWindow.nat.status.tooltip.bad=Firewall/NAT Kontakt problemer (TCP) Referer til Wiki for hj\u00e6lp plugin.installer.recommended.plugin=Anbefalede tilf\u00f8jelser - gennemse listen og installer hvis det er p\u00e5kr\u00e6vet LoggerView.pause=Logging Pauses LoggerView.clear=&Ryd LoggerView.filter=Log Filter LoggerView.filter.uncheckAll=Fjern markeringen i alle kategorier LoggerView.filter.checkAll=Marker alle kategorier LoggerView.loggingDisabled=Logging er ikke aktiveret. ConfigView.section.logging.log0type=Info ConfigView.section.logging.log1type=Advarsel ConfigView.section.logging.log2type=Fejl ConfigView.section.logging.filter=Filtrer n\u00e5r der logges til fil ConfigView.section.logging.level=V\u00e6lg LogType ConfigView.section.logging.showLogsFor=Vis %1 log for f\u00f8lgende katagorier : ConfigView.pluginlist.column.loadAtStartup=Indl\u00e6ses ved Programstart ConfigView.pluginlist.column.type=Type : ConfigView.pluginlist.column.type.perUser=Pr. Bruger ConfigView.pluginlist.column.type.shared=Delte ConfigView.pluginlist.column.type.builtIn=Indbygget ConfigView.pluginlist.column.name=Navn : ConfigView.pluginlist.column.version=Version : ConfigView.pluginlist.column.directory=Mappe : ConfigView.pluginlist.column.isOperational=Operationsdygtig? PeersView.BlockView.Avail.Have=Haves af begge PeersView.BlockView.Avail.NoHave=Peer har - Du har ikke PeersView.BlockView.NoAvail.Have=Du har - Peer har ikke PeersView.BlockView.NoAvail.NoHave=Ingen har PeersView.BlockView.Transfer=Overf\u00f8rer PeersView.BlockView.NextRequest=N\u00e6ste anmodning PeersView.BlockView.title=Kort over stykker PeersView.BlockView.AvailCount=Opt\u00e6lling af tilg\u00e6ngeligheden MyTorrentsView.dialog.NumberError.title=Ugyldigt eller ikke genkendt nummer MyTorrentsView.dialog.NumberError.text=Nummeret du intastede er ugyldigt eller ikke genkendt MyTorrentsView.menu.manual=&Brugerdefineret... MyTorrentsView.dialog.setSpeed.title=V\u00e6lg %1 hastighed # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Skriv et nummer %1 for at \u00e6ndre %2 til : MyTorrentsView.dialog.setNumber.upload=Upload MyTorrentsView.dialog.setNumber.download=Download MyTorrentsView.dialog.setNumber.inKbps=i %1 OpenTorrentWindow.torrentLocation=Torrent fil(er) som skal downloades : OpenTorrentWindow.addFiles.URL=Tilf\u00f8j &URL OpenTorrentWindow.addFiles.Folder=Tilf\u00f8j &mappe OpenTorrentWindow.addFiles.Clipboard=Tilf\u00f8j fra udklips&holderen OpenTorrentWindow.changeDestination=Skift Destination OpenTorrentWindow.fileList=Filer i Torrenten : OpenTorrentWindow.torrentTable.name=Navn : OpenTorrentWindow.torrentTable.saveLocation=Placeringen hvor data skal gemmes OpenTorrentWindow.fileTable.fileName=Filens navn OpenTorrentWindow.fileTable.size=St\u00f8rrelse : OpenTorrentWindow.fileTable.destinationName=Destinations Navn OpenTorrentWindow.startMode.seeding=Seeder OpenTorrentWindow.fileList.changeDestination=Skift Destination OpenTorrentWindow.mb.badSize.title=Inkompatibel Fil OpenTorrentWindow.mb.badSize.text="%1" er ikke "%2" og kan ikke anvendes til seeding OpenTorrentWindow.mb.alreadyExists.text=Torrenten "%1" er allerede tilf\u00f8jet som "%2" OpenTorrentWindow.mb.alreadyExists.title=Torrenten eksisterer allerede OpenTorrentWindow.mb.openError.title=Fejl ved \u00e5bning OpenTorrentWindow.mb.openError.text="%1" kunne ikke \u00e5bnes :\t\n%2 OpenTorrentWindow.torrent.remove=Fjern Torrenten fra listen OpenTorrentWindow.torrent.options=F\u00f8lgende instillinger vil v\u00e6re g\u00e6ldende for ovenst\u00e5ende valgte Torrents : OpenTorrentWindow.xOfTotal=(%1 af %2) iconBar.open.tooltip=\u00c5ben Torrent(s) LocaleUtil.column.text=Ukendt tekst Tracker.tooltip.MultiSupport=Denne tracker underst\u00f8tter flere hash opdateringer Pr. anmodning. Tracker.tooltip.NoMultiSupport=Denne tracker underst\u00f8tter IKKE flere hash opdateringer Pr. anmodning.\nDette vil ikke p\u00e5virke din ydeevne men l\u00e6gger en ekstra belastning p\u00e5 trackeren. ConfigView.label.lazybitfield=Brug lazy bitfield (hj\u00e6lper med seeding p\u00e5 netv\u00e6rk der benytter bitfield-baseret blokering) LoggerView.realtime=Opdater i real tid ConfigView.section.file.perf.cache.flushpieces=Skriv komplette stykker til disken med det samme. Dette g\u00f8r disk adgangen lettere men kan resultere i yderligere skrive handlinger. ConfigView.section.file.writemblimit=Maksimum skrive-anmodninger i k\u00f8 (i %1) ConfigView.section.file.writemblimit.explain=N\u00e5r diskens skrive hastighed er lavere end download hastigheden begr\u00e6nser denne parameter hvor meget data som bliver sat i k\u00f8 f\u00f8r download hastigheden bliver reduceret. ConfigView.section.file.readmblimit=Maksimum l\u00e6se-anmodninger i k\u00f8 (i %1) ConfigView.section.file.readmblimit.explain=Denne instilling begr\u00e6nser hvor meget hukommelse som bliver brugt til at lagre l\u00e6sninger som venter p\u00e5 beabejdelse. Button.moveUp=Flyt &op Button.moveDown=Flyt &Ned ConfigView.notAvailableForMode=Denne sektion er beregnet til %1 tilstand eller h\u00f8jere. Den er ikke til r\u00e5dighed i %2 tilstand. health.explain.error=Der er opst\u00e5et en fejl med denne torrent. Se i statuskolonnen, eller i v\u00e6rkt\u00f8jstippet p\u00e5 fejlikonet. GeneralView.label.trackerscrapeupdate=Opdater tracker PeersView.piece=Stykke PeersView.piece.info=Nummeret p\u00e5 det sidste stykke som blev anmodet af denne peer PiecesView.priority=Prioritet : PiecesView.priority.info=Stykkernes f\u00e6rdigg\u00f8relses prioritet, men brug ikke for meget opm\u00e6rksomhed til dette PiecesView.speed=Hastighed : TableColumn.header.AvgAvail.info=Summen af stykker til r\u00e5dighed divideret med antallet af stykker, divideret med antallet af forbindelser TableColumn.header.AvgAvail=Gennemsnittet af tilg\u00e6ngeligheden ConfigView.label.strictfilelocking=Gennemtving tilgang til eksklusiv fil skrivning n\u00e5r der kigges p\u00e5 tv\u00e6rs af Torrents MyTorrentsView.menu.rescanfile=Kontroller periodisk de uf\u00e6rdige stykker Plugin.extseed.name=Eksterne Seedere Plugin.localtracker.name=LAN Peer Finder azinstancehandler.alert.portclash=Port sammenst\u00f8d registreret p\u00e5 LAN : %1 er allerede i brug af anden Vuze bruger, v\u00e6lg en ny port(e) til indg\u00e5ende TCP / UDP anmodning(er) (mellem %2 og %3). ConfigView.section.transfer.lan=LAN ConfigView.section.transfer.lan.tooltip=LAN-specifikke Indstillinger ConfigView.section.transfer.lan.uploadrate=KB/s LAN maksimum upload hastighed (0 = ubegr\u00e6nset) ConfigView.section.transfer.lan.uploadrate.tooltip=Peer forbindelser indenfor den samme interne LAN har en adskilt Upload begr\u00e6nsning p\u00e5 downloaden. ConfigView.section.transfer.lan.downloadrate=KB/s LAN maksimum download hastighed (0 = ubegr\u00e6nset) ConfigView.section.transfer.lan.downloadrate.tooltip=Peer forbindelser indenfor den samme interne LAN har en adskilt hastigheds begr\u00e6nsning p\u00e5 downloaden. TorrentOptionsView.title.short=Valgmuligheder TorrentOptionsView.title.full=Valgmuligheder TorrentOptionsView.param.max.peers=Det maximale antal af forbindelser (0 = ubegr\u00e6nset) ConfigView.section.connection.encryption.require_encrypted_transport=Kr\u00e6ver krypteret forsendelse ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Gennemtving brug af krypterede forbindelser med andre peers. ConfigView.section.connection.encryption.min_encryption_level=Minimum krypterings grad ConfigView.section.connection.encryption.min_encryption_level.tooltip=Simpelt - Kun h\u00e5ndtryk\nRC4 - fuld stream\nH\u00f8jere kryptering kr\u00e6ver st\u00f8rre CPU. Peers.column.Encryption=Kryptering : Peers.column.Encryption.info=Typen af kryptering som anvendes ConfigView.section.connection.encryption.encrypt.info=Med kryptering aktiveret vil du ikke kunne oprette forbindelse til inkompatible klienter, medmindre du har konfigureret "fallback" valgmulighederne ConfigView.section.connection.encryption.encrypt.info.link=Bes\u00f8g her for flere detaljer MainWindow.sr.status.tooltip.ok=Delingsforhold %1 OK MainWindow.sr.status.tooltip.poor=Delingsforhold %1 mangelfuldt : < 0.9 MainWindow.sr.status.tooltip.bad=Delingsforhold %1 elendigt : < 0.5 ConfigView.section.style.status=Status Omr\u00e5de : ConfigView.section.style.status.show_sr=Delingsforhold ConfigView.section.style.status.show_nat=NAT status ConfigView.section.style.status.show_ddb=DDb Status ConfigView.section.style.status.show_ipf=IP-Filter Status ConfigView.section.connection.encryption.encrypt.group=Overf\u00f8rsels kryptering ConfigView.section.connection.encryption.encrypt.fallback_info=Aktivering af begge "fallback" muligheder vil tillade forbindelser med ikke-kompatible klienter MEN dette vil resultere i ikke-krypterede forbindelser ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Tillad ikke-krypterede udg\u00e5ende forbindelser hvis fors\u00f8g p\u00e5 at oprette en krypteret forbindelse mislykkedes ConfigView.section.connection.encryption.encrypt.fallback_incoming=Tillad ikke-krypterede indg\u00e5ende forbindelser ConfigView.section.connection.encryption=Overf\u00f8rsels kryptering upnp.selectedinterfaces=Valgte "interfaces" (";" sepererede, f.eks. eth0;eth1) (blank : alle) ConfigView.section.style.defaultSortOrder=Standart sorterings r\u00e6kkef\u00f8lge ConfigView.section.style.defaultSortOrder.desc=Faldende ConfigView.section.style.defaultSortOrder.asc=Stigende ConfigView.section.style.defaultSortOrder.flip=Modsat den forrige ordre LoggerView.autoscroll=Auto rul i logfilen Button.selectAll=V\u00e6lg alt Button.markSelected=Marker valgte Button.unmarkSelected=Fjern markeringen af valgte plugins.basicview.config=Konfig TorrentOptionsView.param.max.uploads=Det maximale antal upload porte (Dog mindst 2) MyTorrentsView.dialog.setPosition.title=Angiv Position MyTorrentsView.dialog.setPosition.text=Skriv positionen, du vil ha den valgte Torrents p\u00e5 : MyTorrentsView.menu.reposition.manual=Ny position.. ConfigView.section.connection.advanced.info.link=Bes\u00f8g her for flere detaljer ConfigView.section.connection.advanced.socket.group=Socket valgmuligheder ConfigView.section.connection.advanced.bind_port=Bind til lokal port (0 = deaktiveret) ConfigView.section.connection.advanced.bind_port.tooltip=Udg\u00e5ende socket forbindelser vil v\u00e6re lokalt bundet til den valgte port.\nAktivering af dette kan hj\u00e6lpe med NAT router ustabilitet. ConfigView.section.proxy.group.tracker=Tracker kommuikation ConfigView.section.proxy.group.peer=Peer kommunikation Pieces.column.Requested=Anmodet : Pieces.column.Requested.info=Hvis der kan eller ikke kan foretages flere foresp\u00f8rgelser p\u00e5 stykket s\u00e5 vis det (*) ConfigView.label.maxuploadsseeding=Alternativ standart n\u00e5r der seedes popup.error.hideall=Skjul Alle ConfigView.section.style.dataStatsOnly=Vis kun data statistikker (skjul protokol statistikker) ConfigView.section.style.separateProtDataStats=Vis adskilte data og protokol statistikker som "data (protokol)" MyTorrentsView.dialog.setFilter.title=Modificer filter MyTorrentsView.dialog.setFilter.text=%1 sektionen bliver filtreret if\u00f8lge teksten du speciferer herunder. Brug | (pipe) symbolet til at filtrere ord med flere mulige stavelser p\u00e5. MyTorrentsView.filter.tooltip=Brug Ctrl+X for at skifte mellem RegEx og normal s\u00f8gemetode.\nBrug | (pipe) symbolet til at filtrere ord med flere mulige stavelser p\u00e5. MyTorrentsView.clearFilter.tooltip=Ryd Filter MyTorrentsView.menu.filter=Filter Liste... ConfigView.section.file.resume.recheck.all=Ved crash-genstart tjekkes hele filen for f\u00e6rdige stykker (Ellers tjekkes kun de gemte filer der sidst var aktive) ConfigureWizard.language.choose=V\u00e6lg sprog fra nedenst\u00e5ende liste : popup.closing.in=Vinduet lukkes automatisk om %1 sekunder popup.more.waiting=%1 flere besked(er)... # > 2402 popup.next=> popup.previous=< (%1) popup.download.finished="%1" er f\u00e6rdig Downloadet. popup.file.finished="%1" er f\u00e6rdig Downloadet. ConfigView.auto=Automatisk Plugin.localtracker.autoadd.info=Tilf\u00f8j automatisk disse lokale peers (";" sepererede adresser, f.eks. 1.2.3.4) Plugin.localtracker.networks.info=Betragt f\u00f8lgende netv\u00e6rk som lokale (";" separerede netv\u00e6rk, f.eks. 145.227.*.*) Plugin.localtracker.networks=Lokal netv\u00e6rk MainWindow.menu.view.plugins.logViews=Vis Loggen SpeedView.stats.autospeed=Automatisk Upload Hastighed SpeedView.stats.autospeed.disabled=Denne mulighed er enten deaktiveret (du skal bruge DHT) eller ikke i brug (Brugerdefineret upload hastighed er valgt) SpeedView.stats.maxPing=Maksimal Ping : SpeedView.stats.currentPing=Aktuelle Ping : SpeedView.stats.maxUp=Maksimal Upload Hastighed : ConfigView.pluginlist.unloadSelected=Frav\u00e6lg valgte ConfigView.pluginlist.scan=Scan efter nye tilf\u00f8jelser ConfigView.section.transfer.autospeed=Auto Hastighed ConfigView.section.transfer.autospeed.tooltip=Specifikke Auto-hastigheds indstillinger ConfigView.section.transfer.autospeed.minupload=Den mindste upload hastighed i %1 ConfigView.section.transfer.autospeed.maxupload=Den maksimale upload hastighed i %1 (0 = ubegr\u00e6nset) ConfigView.section.transfer.autospeed.chokeping=Kv\u00e6ler pingtider over (i millisekunder) ConfigView.section.transfer.autospeed.chokeping.tooltip=Pingtider som overskrider denne v\u00e6rdi vil blive betragtet som en indikation af at netv\u00e6rket er m\u00e6ttet ConfigView.section.transfer.autospeed.enableauto=Aktiver n\u00e5r der Downloades og seedes ConfigView.section.transfer.autospeed.enableautoseeding=Aktiver KUN n\u00e5r der seedes ConfigView.pluginlist.column.unloadable=Kan afl\u00e6ses ConfigView.section.transfer.lan.enable=Aktiver seperat hastigheds begr\u00e6nsning for LAN forbindelser Plugin.localtracker.wellknownlocals=Inkluder automatisk loopback/link/site lokale netv\u00e6rk (192.168 osv) TableColumn.header.filesdone=F\u00e6rdige filer TableColumn.header.filesdone.info=F\u00e6rdige filer/Totale antal filer *eller* ikke droppede f\u00e6rdige filer (F\u00e6rdige filer)/Totale antal ikke droppede filer (Totale antal filer) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=venter p\u00e5 DDB initialisering... MagnetPlugin.report.searching=S\u00f8ger... MagnetPlugin.report.found=fundet %1 MagnetPlugin.report.alive=%1 er aktiv MagnetPlugin.report.dead=%1 er d\u00f8d MagnetPlugin.report.tunnel=undergraver til %1 MagnetPlugin.report.downloading=downloader fra %1 MagnetPlugin.report.error=fejl %1 MagnetURLHandler.report.no_sources=ingen kilde fundet til Torrenten MagnetURLHandler.report.torrent_size=Torrent st\u00f8rrelse : %1 MagnetURLHandler.report.percent=fuldf\u00f8rte : %1% MagnetURLHandler.report.error=fejl %1 DHTTransport.report.request_all=anmoder om hele overf\u00f8rslen fra %1 DHTTransport.report.received_bit=modtaget %1 til %2 fra %3 DHTTransport.report.complete=Komplette : DHTTransport.report.timeout=timeout, intet svar fra %1 DHTTransport.report.rerequest_all=genanmoder om hele overf\u00f8rslen fra %1 DHTTransport.report.rerequest_bit=genanmoder %1 til %2 fra %3 DHTTransport.report.timeout_some=timeout, %1 pakke modtaget fra %2 men den er ikke hel DHTTransport.report.sending=sender data DHTTransport.report.resending=sender data igen DHTTransport.report.send_complete=send hele DHTTransport.report.send_timeout=send Timeout ConfigView.section.transfer.autospeed.enabledebug=Log "debug" informationen TableColumn.header.date_added=Tilf\u00f8jelses dato TableColumn.header.date_added.info=Datoen for Torrentens tilf\u00f8jelse ConfigView.section.file.hashchecking.smallestfirst=Tjek de mindste downloads f\u00f8rst platform.win32.baddll.info=Vuze har opdaget tilst\u00e6dev\u00e6relsen af "%1". Dette er en del af "%2" og er kendt for at forsage problemer, s\u00e5som program nedlukninger og h\u00f8jt CPU brug. Hvis du st\u00f8der p\u00e5 nogle af disse problemer b\u00f8r du afinstallere programmet eller pr\u00f8ve at konfigurere det til ikke at p\u00e5virke Azureus. platform.win32.baddll.niphk=Norman Anti Virus platform.win32.baddll.nvappfilter=NVidia Firewall. platform.win32.baddll.netdog=Armor2net Personal Firewall. platform.win32.baddll.vlsp=Venturi Firewall. platform.win32.baddll.imon=NOD-32 platform.win32.baddll.sarah=FRITZ! Application Layer Firewall. platform.win32.baddll.MxAVLsp=VCom Fix-It Redskaber platform.win32.baddll.mclsp=McAfee Privacy Service. platform.win32.baddll.radhslib=Naomi Internet Filter (Radiant!) platform.win32.baddll.nl_lsp=NetLimiter. platform.win32.baddll.winsflt=PureSight Internet Content Filter. platform.win32.baddll.AxShlex=Alcohol 120 % platform.win32.baddll.iFW_Xfilter=Iolo Personal Firewall upnp.ignorebaddevices=Ignorer enhedder som ikke svarer korrekt tilbage upnp.ignorebaddevices.info=Nuv\u00e6rende ignorerede enheder : %1 upnp.ignorebaddevices.reset=Nulstil listen med ignorerede enhedder upnp.ignorebaddevices.reset.action=Nulstil upnp.ignorebaddevices.alert=UPnP enhed p\u00e5 placering %1 bliver ignoreret pga gentagne fejl. Kig i konfigurationen til UPnP tilf\u00f8jelsen for valgmuligheder vedr\u00f8rende denne handling. TorrentOptionsView.param.max.uploads.when.busy=KB/s maksimum upload hastighed n\u00e5r den totale uploads hastighedsgr\u00e6nse er n\u00e5et (0 = deaktiveret) UpdateMonitor.messagebox.verification.failed.title=Installationen kan ikke bekr\u00e6ftes UpdateMonitor.messagebox.verification.failed.text=Bekr\u00e6ftigelse af "%1" mislykkedes : %2 UpdateMonitor.messagebox.accept.unverified.title=Accepter den uofficielle installation UpdateMonitor.messagebox.accept.unverified.text="%1" kunne ikke bekr\u00e6ftes som v\u00e6rende en officiel Vuze tilf\u00f8jelse.\nHvis det ikke er en officiel Vuze tilf\u00f8jelse b\u00f8r du IKKE forts\u00e6tte.\nVil du forts\u00e6tte med at installere? FileView.BlockView.title=Fil stykker FileView.BlockView.Done=F\u00e6rdig FileView.BlockView.Skipped=Droppet FileView.BlockView.Active=Aktiv FileView.BlockView.Outstanding=Udest\u00e5ende ConfigView.label.tcplistenport=Indg\u00e5ende TCP aflytnings port ConfigView.label.udplistenport=UDP aflytnings port upnp.portchange.alert=F\u00f8lgende porte er blevet \u00e6ndret for at afv\u00e6rge problemer med UPnP enheden : %1 (old port = %2) %3 (old port = %4) ConfigView.section.proxy.username.info=Hvis proxy serveren kr\u00e6ver bekr\u00e6ftigelse af identitet, selvom ingen er defineret, s\u00e5 brug strengen som brugernavn(e) ConfigView.label.maxuploadswhenbusymin=Maksimum upload hastighed, Pr. Torrent n\u00e5r timeren er optaget (sekunder) MainWindow.menu.help.debug=Opret "debug" information DownloadManager.error.badsize=Ukorrekt st\u00f8rrelse ConfigView.section.NATPMP=NAT - PMP natpmp.info=NAT-PMP er Apple's alternativ til UPnP som underst\u00f8ttes i alle nyere lufthavns terminaler\n\nBEM\u00c6RK at p\u00e5 nuv\u00e6rende tidspunkt skal UPnP'en v\u00e6re aktiveret for at du kan aktivere NAT-PMP da NAT-PMP enhedder bliver anset som en special type UPnP enhed ConfigView.section.tracker.host.addurls=Sikrer dig at denne trackers URL er tilstede i "hosted Torrents" ConfigView.filter=Skriv filter tekst ConfigView.section.files.move=Flytning af f\u00e6rdige ConfigView.section.file.defaultdir.section=Standart mappevalg ConfigView.section.file.defaultdir.auto=Download automatisk til standart mappen (Bekr\u00e6ft ikke) ConfigView.section.file.defaultdir.bestguess=Brug bedste g\u00e6t n\u00e5r der v\u00e6lges standart lagringsmappe ConfigView.section.file.defaultdir.ask=Standart mappe : ConfigView.section.file.defaultdir.lastused=Opdater standart mappen til placeringen der sidst blev gemt til ConfigView.section.logging.udptransport=Aktiver "verbose" UDP transport sporing Tracker.announce.ignorePeerSeed=Ignorerer Peer/Seed t\u00e6lling. %1 ConfigView.section.connection.encryption.use_crypto_port=Brug "cryptoport" tracker-udvidelsen til forhindring af simple indg\u00e5ende forbindelses-fors\u00f8g. Nogle trackers vil ikke acceptere dette og vil reportere om fejl s\u00e5som "Invalid Port" eller "Illigal Argument" TorrentOptionsView.param.reset.to.default=Gendan standart v\u00e6rdierne TorrentOptionsView.param.reset.button=Nulstil natpmp.routeraddress=Routerens adresse (blank : automatisk) ConfigView.section.style.disableAlertSliding=Deaktiver glidende animationer/p\u00e5 toppen af meddelels alarmer ConfigView.section.transfer.autospeed.maxinc=Den maksimale for\u00f8gelse pr. cyklus i %1 ConfigView.section.transfer.autospeed.maxdec=Den maksimale formindskelse pr. cyklus i %1 ConfigView.section.transfer.autospeed.enabledownadj=Aktiver justering af Download hastigheden ConfigView.section.transfer.autospeed.downadjratio=Download/Upload hastigheds forholdet (f.eks 2.0 -> Download hastigheds begr\u00e6nsningen er det dobbelte af Upload hastigheds begr\u00e6nsningen) ConfigView.section.transfer.autospeed.reset=Nulstil de avancerede instillinger og gendan standart v\u00e6rdierne ConfigView.section.transfer.autospeed.reset.button=Nulstil PeerColumn.activationCount=Peers som fors\u00f8ger at oprette forbindelse : %1 TableColumn.header.timesincedownload.info=Tiden der er g\u00e5et siden dataen til Torrenten blev downloadet TableColumn.header.timesincedownload=Down Idle TableColumn.header.timesinceupload.info=Tiden der er g\u00e5et siden dataen til Torrenten blev uploadet TableColumn.header.timesinceupload=Up Idle PeersView.incomingreqcount=Indg\u00e5ende anmodninger PeersView.incomingreqcount.info=T\u00e6lling af indg\u00e5ende anmodninger foretaget af peer PeersView.outgoingreqcount=Udg\u00e5ende anmodninger PeersView.outgoingreqcount.info=Opt\u00e6lling af udg\u00e5ende anmodninger til peer upnp.mapping.trackerclientudp=UDP Trackerens klient Port upnp.mapping.dhtudp=Distribueret Database ConfigView.section.connection.nondata.udp.same=Brug den samme UDP port til den "Distributed Database" og UDP Trackeren ConfigView.section.connection.tcp.enable=Aktiver TCP ConfigView.section.connection.udp.enable=Aktiver UDP ConfigView.section.style.showiconbar=Vis V\u00e6rkt\u00f8jslinjen MainWindow.menu.view.iconbar=V\u00e6rkt\u00f8jslinjen MyTorrentsView.menu.rename=Omd\u00f8b MyTorrentsView.menu.rename.displayed=Omd\u00f8b viste Torrent navn MyTorrentsView.menu.rename.save_path=Omd\u00f8b stien der gemmes til MyTorrentsView.menu.rename.displayed.enter.title=Omd\u00f8b viste Torrent navn MyTorrentsView.menu.rename.displayed.enter.message=Skriv et nyt navn som skal vises for denne download.\nHvis der ikke skrives en ny tekst, anvendes det originale navn. MyTorrentsView.menu.edit_comment=Rediger/Tilf\u00f8j en kommentar MyTorrentsView.menu.edit_comment.enter.title=Rediger/Tilf\u00f8j en kommentar MyTorrentsView.menu.edit_comment.enter.message=Skriv en kommentar til denne download. UIDebugGenerator.messageask.title="Debug" Opretter UIDebugGenerator.complete.title="Debug" oprettelse f\u00e6rdig UIDebugGenerator.complete.text=Send filen "%1".\n\nklik Ok for at \u00e5bne et vindue til denne fil. ConfigView.section.style.showProgramIcon=Vis program ikonet i navne kolonnen ConfigView.section.style.showProgramIcon.tooltip=Det kan v\u00e6re n\u00f8dvendigt at skulle gen\u00e5bne for at \u00e6ndringerne vil tr\u00e6de i kraft swt.alert.cant.update=SWT biblioteket som er inl\u00e6st fra "%3" kan ikke opdateres automatisk fra version %1 til %2 (Skal indl\u00e6ses fra "%4"). For flere detaljer se\nthe wiki authenticator.savepassword=Husk mit kodeord ConfigView.section.security.clearpasswords=Nulstil huskede kodeord ConfigView.section.security.clearpasswords.button=Nulstil Content.alert.notuploaded.title=Uploaden er ikke fuldendt Content.alert.notuploaded.text=Upload af "%1" er ikke komplet. Hvis du %2 nu, vil folk ikke v\u00e6re i stand til at downloade din upload.\n\nEr du sikker p\u00e5 du vil %2? Content.alert.notuploaded.multi.title=Uploaden er ikke komplet Content.alert.notuploaded.multi.text=%1 af dit uploadet indhold er ikke seedet f\u00e6rdigt. Hvis du %2 nu, vil folk ikke kunne f\u00e5 en komplet download af det du har uploadet. Er du helt sikker p\u00e5 at du vil %2???\n\nIndholdet i uploaden er ikke f\u00e6rdig seedet :\n%3 Content.alert.notuploaded.stop=Stop Content.alert.notuploaded.quit=Afslut Vuze TorrentInfoView.torrent.encoding=Torrent kryptering TorrentInfoView.columns=Kolonner fra "Mine Torrents" progress.window.title=Aktuelle handling progress.window.msg.filemove=Vent mens flytningen/omd\u00f8bningen af filen f\u00e6rdigg\u00f8res ConfigView.label.popup.timestamp=Tilf\u00f8j tidsstempler p\u00e5 popup alarmer ConfigView.label.popup.autohide=Skjul automatisk "ingen-fejl" popup alarmer efter x sekunder (0 deaktiverer auto skjul) ConfigView.label.popup.suppress_alerts=Undertryk alarmer ConfigView.label.popup.use_message_boxes=Brug popup besked bokse istedet for standart popup alarm boksen. ConfigView.label.popup.show=Vis alle loggede popup alarmer indtil nu (hvis der er nogen) ConfigView.label.popup.show.button=Vis ConfigView.label.please.visit.here=Bes\u00f8g her for flere detaljer ConfigView.section.ipfilter.enable.descriptionCache=Gem IP beskrivelser i "scratch" filen ConfigView.section.ipfilter.enable.descriptionCache.tooltip=N\u00e5r funktionen er deaktiveret, vil beskrivelser ikke blive husket OpenTorrentWindow.filesInfo=%1 af %2 vil blive downloadet. ConfigView.label.openmytorrents=\u00c5ben Fanen "Mine Torrents" n\u00e5r Vuze startes ConfigView.section.style.DNDalwaysInIncomplete=Vis altid Torrents med "Download ikke" i Mine Torrents under sektionen Uf\u00e6rdige OpenTorrentWindow.mb.noGlobalDestDir.title=Destinations mappen blev ikke fundet OpenTorrentWindow.mb.noGlobalDestDir.text=Destinations mappen "%1" eksisterer ikke eller er ugyldig. OpenTorrentWindow.mb.noDestDir.title=Destinations mappen blev ikke fundet OpenTorrentWindow.mb.noDestDir.text=Destinations mappen "%1" til Torrenten "%2" eksisterer ikke eller er ugyldig. OpenTorrentWindow.mb.notValid.title=\u00c5ben Torrent OpenTorrentWindow.mb.notValid.text=Kunne ikke \u00e5bne Torrenten "%1". Hvis du \u00e5bner i seeding tilstand skal du sikre dig at Torrentens datafiler findes. OpenTorrentWindow.mb.notTorrent.title=\u00c5ben Torrent OpenTorrentWindow.mb.notTorrent.text="%1" kunne ikke \u00e5bnes. Tilsyneladende er det ikke en Torrent fil.\n\nNoget af dataen blev modtaget :\n%2 ConfigView.label.pause.downloads.on.exit=S\u00e6t downloads p\u00e5 pause n\u00e5r der afsluttes ConfigView.label.resume.downloads.on.start=Genoptag pausede downloads efter initialitionen er f\u00e6rdig UIDebugGenerator.message.cancel.title=Oprettelse af "debug" informationen blev afbrudt ConfigView.section.connection.group.http=HTTP. ConfigView.section.connection.group.http.info=Support til HTTP seeding. ConfigView.section.connection.http.enable=Aktiver ConfigView.section.connection.http.port=Indg\u00e5ende port nummer ConfigView.section.connection.http.portoverride=Underkendelse af tracker HTTP Port (0 = ingen) window.update.noupdates.title=kontroller opdaterings resultaterne window.update.noupdates.text=Tillykke din Vuze er optimal!\n\nDer er ingen nye opdateringer tilg\u00e6ngelige. ConfigView.label.mindownloads=Minimum antal samtidige downloads UI.cannot_submit_blank_text=Du skal skrive en v\u00e6rdi. crypto.alert.as.warning=Netv\u00e6rket "%1" er kendt for at p\u00e5tvinge trafikregulering for at reducere download hastigheden. Kryptering af overf\u00f8rslen er automatisk blevet sl\u00e5et til - dette kan sl\u00e5s fra eller modificeres via konfigurations instillingerne. ConfigView.section.interface.alerts=Alarmer ConfigView.label.popupdownloadadded=Vis en Popupbesked n\u00e5r en download bliver tilf\u00f8jet popup.download.added="%1" er blevet tilf\u00f8jet til din Download liste. MessageBoxWindow.nomoreprompting=Sp\u00f8rg mig ikke igen TorrentOptionsView.param.max.seeds=Det maximale antal seed forbindelser (0 = forbindelses begr\u00e6nsning) TorrentOptionsView.param.alternative.value.enable=Alternativ v\u00e6rdi n\u00e5r der seedes ConfigView.section.proxy.check.on.start=Tjek proxy status ved start TransferStatsView.legend.pingaverage=Gennemsnit TransferStatsView.legend.ping1=Ping m\u00e5l 1 TransferStatsView.legend.ping2=Ping m\u00e5l 2 TransferStatsView.legend.ping3=Ping m\u00e5l 3 ConfigView.section.interface.enabletray._mac=Aktiver Status Linie Ikonet (kr\u00e6ver genstart) ConfigView.label.closetotray._mac=Luk minimerer til Statuslinie Icon ConfigView.label.minimizetotray._mac=Minimer "Minimerer" til Status menu Ikonet OpenTorrentWindow.mb.existingFiles.title=Filen eller filerne findes allerede! OpenTorrentWindow.mb.existingFiles.text=Nogle af filerne findes allerede i den valgte destinations mappe :\n\n%1\nHvis du forts\u00e6tter vil Vuze tjekke ovenst\u00e5ende fil(er) for korrekt data og om n\u00f8dvendigt overskrive filen/filerne. splash.unloadingTorrents=Standser Torrents splash.unloadingTorrent=Unloading torrent ConfigView.section.file.defaultdir.autorename=Omd\u00f8b automatisk torrent dataen hvis filerne i stien ser anderledes ud ConfigView.section.file.defaultdir.autorename.tooltip=Dette forhindrer en Torrent i at overskrive en anden Torrents filer n\u00e5r filnavnet er det samme alert.raised.at.close=(Besked fra sidste lukning af Vuze) Plugin.trackerpeerauth.name=Tracker Peer Tilladelser Plugin.trackerpeerauth.info=Denne tilf\u00f8jelse virker sammen med trackerne til at fastsl\u00e5 om peers er gyldige medlemmer i sv\u00e6rmen Peers.column.maxupspeed=Maksimum Upload hastighed Peers.column.maxdownspeed=Maksimum Download hastighed MyTorrents.items.DownSpeedLimit.disabled=Ingen Download Peers.column.lan=LAN upnp.selectedaddresses=Addresser (';' sepereret, '-' prefix = n\u00e6gt, '+' = tillad) (blank : hvilkensomhelst) upnp.alert.multipledevice.warning=Flere UPnP enheder er blevet registreret - unders\u00f8g om de alle kr\u00e6ver port kortl\u00e6gning (se i UPnP loggen og konfiguration) UpdateMonitor.messagebox.restart.title=Program opdatering UpdateMonitor.messagebox.restart.text=Vuze er lige blevet f\u00e6rdig med at downloade en vigtig opdatering og skal genstartes for at opdateringen kan blive installeret. PiecesView.BlockView.Have=Haves PiecesView.BlockView.NoHave=Haves ikke PiecesView.BlockView.Header=%1 Kolonner, %2 R\u00e6kker, %3 Stykker ConfigView.section.update.autodownload=Auto download opdateringer og underret n\u00e5r installationen er klar Peers.column.peer_id=Peers ID Peers.column.peer_id.info=Peers ID in readable form Peers.column.peer_byte_id=Peers ID Peers.column.peer_byte_id.info=Peers ID in byte form ConfigView.label.openbar.incomplete=Download bj\u00e6lke: auto \u00e5ben downloads ConfigView.label.openbar.complete=auto \u00e5ben seeds # Used for peers which we can't determine. PeerSocket.unknown=Ukendt ConfigView.label.announceport=Underkend tracker annoncerings port iconBar.queue.tooltip=S\u00e6t i k\u00f8 MainWindow.menu.help.faq=&Ofte stillede sp\u00f8rgsm\u00e5l (FAQ) MainWindow.menu.help.faq.keybinding.mac=Meta+? MainWindow.menu.help.donate=&Giv et bidrag!!! azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_ro_RO.properties0000644000175000017500000070011411301156004026112 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Fi\u0219ier Torent... Main.parameter.usage=Folosire: java org.gudy.azureus2.cl.Main [parametri] "fi\u0219ier.torrent" "calea de salvare" Main.parameter.maxUploads=Nr. max de \u00eenc\u0103rc\u0103ri simultane Main.parameter.maxSpeed=Viteza max de \u00eenc\u0103rcare \u00een bai\u021bi/sec MainWindow.menu.file=&Fi\u0219ier MainWindow.menu.file.open=&Deschide MainWindow.menu.file.create=Torent &Nou... MainWindow.menu.file.create.fromfile=Dintr-un &Fi\u0219ier MainWindow.menu.file.create.fromdir=Dintr-un &Dosar MainWindow.menu.file.export=&Export\u0103 Torentul \u00een XML... MainWindow.menu.file.import=&Import\u0103 Torentul din XML... MainWindow.menu.file.closetab=\u00cenchide &Tabul MainWindow.menu.file.closewindow=\u00cenchide &Fereastra MainWindow.menu.file.exit=&Ie\u0219i MainWindow.dialog.choose.file=Alege\u021bi fi\u0219ierul torent MainWindow.menu.file.folder=D&osar... MainWindow.dialog.choose.folder=Alege\u021bi dosarul ce con\u021bine fi\u0219ierele torent MainWindow.menu.view=&Vezi MainWindow.menu.view.show=Afi\u0219eaz\u0103 MainWindow.menu.view.mytorrents=Torentele &Mele MainWindow.menu.view.open_global_transfer_bar=Bara de Transferuri MainWindow.menu.view.configuration=&Op\u021biuni... MainWindow.menu.view.console=C&onsol\u0103 MainWindow.menu.view.allpeers=To\u021bi Partenerii MainWindow.menu.view.detailedlist=List\u0103 &Detaliat\u0103 MainWindow.menu.closealldetails=\u00cenchide To&ate Detaliile MainWindow.menu.closealldownloadbars=\u00cenchide Toate &Barele de Desc\u0103rcare MainWindow.menu.language=&Limb\u0103 ConfigView.section.language=Limb\u0103 MainWindow.menu.window=&Fereastr\u0103 MainWindow.menu.window.minimize=&Minimizeaz\u0103 MainWindow.menu.window.zoom=&Panorameaz\u0103 MainWindow.menu.window.alltofront=Adu Totul \u00een &Prim-Plan MainWindow.menu.help=A&jutor MainWindow.menu.help.about=Despre Vuze MainWindow.menu.torrent=Torent MainWindow.about.title=Despre MainWindow.about.section.developers=Programatori MainWindow.about.section.translators=Traduc\u0103tori MainWindow.about.section.system=Sistem MainWindow.about.section.internet=Pe Internet MainWindow.about.internet.homepage=Situl Vuze MainWindow.about.internet.sourceforge=Pagina Proiectului de la Sourceforge MainWindow.about.internet.sourceforgedownloads=Desc\u0103rc\u0103ri de la Sourceforge MainWindow.about.internet.bugreports=Raport\u0103ri de Buguri MainWindow.about.internet.forumdiscussion=Forumuri MainWindow.about.internet.wiki=Wiki \u0219i FAQ Vuze MainWindow.dialog.choose.savepath=Alege\u021bi calea de salvare MainWindow.dialog.choose.savepath_forallfiles=Alege\u021bi calea de salvare pentru TOATE fi\u0219ierele MainWindow.status.latestversion=Ultima MainWindow.status.latestversion.clickupdate=Clica\u021bi pentru actualizare MainWindow.status.unknown=necunoscut MainWindow.status.checking=verific MyTorrentsView.mytorrents=Torentele Mele TableColumn.header.name=Nume TableColumn.header.size=M\u0103rime TableColumn.header.done=Progres TableColumn.header.done.info=Procentajul de realizare a sarcinii curente TableColumn.header.status=Stare TableColumn.header.status.info=Ce face torentul TableColumn.header.seeds=Donatori TableColumn.header.seeds.info=nr. donatorilor conecta\u021bi la (nr. total donatori) TableColumn.header.peers=Parteneri TableColumn.header.peers.info=nr. parteneri conecta\u021bi la (nr. total parteneri) TableColumn.header.completed=Terminat TableColumn.header.completed.info=nr. de parteneri care au terminat de desc\u0103rcat torentul, dup\u0103 cum e raportat de c\u0103tre tracker TableColumn.header.downspeed=Desc\u0103rcare TableColumn.header.upspeed=\u00cenc\u0103rcare TableColumn.header.eta=R\u0103mas TableColumn.header.tracker=Starea Trackerului TableColumn.header.tracker.info=Starea trackerului TableColumn.header.trackernextaccess=Urm\u0103toarea Accesare a Trackerului TableColumn.header.trackernextaccess.info=C\u00eend va avea loc urm\u0103toarea accesare a trackerului TableColumn.header.priority=Prioritate TableColumn.header.priority.info=Determin\u0103 c\u00eet de mult\u0103 band\u0103 ascendent\u0103 poate utiliza torentul TableColumn.header.seeds.fullcopycalc=%2 copii complete presupuse pentru %1 parteneri MyTorrentsView.menu.showdetails=Arat\u0103 &Detaliile MyTorrentsView.menu.showdownloadbar=Arat\u0103 &Bara de Desc\u0103rcare MyTorrentsView.menu.open=Deschide MyTorrentsView.menu.setpriority=Seteaz\u0103 &Prioritatea MyTorrentsView.menu.setpriority.high=\u00ce&nalt\u0103 MyTorrentsView.menu.setpriority.low=&Joas\u0103 MyTorrentsView.menu.start=&Porne\u0219te MyTorrentsView.menu.stop=&Opre\u0219te MyTorrentsView.menu.remove=\u0218ter&ge MyTorrentsView.menu.changeTracker=&Adaug\u0103 Adresa Trackerului TrayWindow.menu.exit=&Ie\u0219i TrayWindow.menu.show=Arat\u0103 &Vuze SystemTray.menu.exit=&Ie\u0219i SystemTray.menu.closealldownloadbars=\u00cenchide &Toate Barele de Desc\u0103rcare SystemTray.menu.open_global_transfer_bar=Arat\u0103 Bara de Transferuri SystemTray.menu.show=Ara&t\u0103 Vuze PeersView.ip=Adresa IP PeersView.ip.info=IP-ul partenerului PeersView.port.info=Portul folosit PeersView.T.info=L (local): conexiune realizat\u0103 de dv., D (distant): conexiune realizat\u0103 de partener PeersView.T.L.tooltip=Conexiune realizat\u0103 de dv. PeersView.T.R.tooltip=Conexiune realizat\u0103 de partener PeersView.I1=I (Interesant la partener) PeersView.I1.info=S\u00eente\u021bi interesat de ceea ce are partenerul? PeersView.C1=L (Limitat de partener) PeersView.C1.info=Dac\u0103 partenerul v\u0103 \u00eempiedic\u0103 sau nu s\u0103 desc\u0103rca\u021bi PeersView.pieces=P\u0103r\u021bi PeersView.downloadspeed=Desc\u0103rcare PeersView.download=Desc\u0103rcat PeersView.I2=I (Partenerul e interesat) PeersView.I2.info=E interesat partenerul de ceea ce ave\u021bi? PeersView.C2=L (Limitez partenerul) PeersView.C2.info=Dac\u0103 bloca\u021bi sau nu desc\u0103rcarea de c\u0103tre partener PeersView.uploadspeed=\u00cenc\u0103rcare PeersView.uploadspeed.info=Viteza de \u00eenc\u0103rcare c\u0103tre partener. PeersView.upload=\u00cenc\u0103rcare PeersView.upload.info=Viteza de \u00eenc\u0103rcare total\u0103 c\u0103tre partener. PeersView.statup=Statistici \u00cenc\u0103rcare PeersView.statup.info=Valoare estimat\u0103 a vitezei de \u00eenc\u0103rcare a partenerului PeersView.S.info=Ignorare: Se poate ignora un partener \u00een mod manual sau automat (pentru vitez\u0103 redus\u0103 la trimiterea de date) PeersView.downloadspeedoverall=Viteza Global\u0103 de Desc\u0103rcare PeersView.optunchoke=Op\u021biune Dezlimitare PeersView.client=Soft PeersView.client.info=Programul BT folosit de partener PeersView.menu.snubbed=&Ignorat PeersView.title.short=Parteneri PeersView.title.full=Parteneri AllPeersView.title.full=To\u021bi Partenerii ConfigView.section.files=Fi\u0219iere ConfigView.label.usefastresume=Folose\u0219te Modul de Reluare Rapid\u0103 ConfigView.label.incrementalfile=Activeaz\u0103 crearea gradat\u0103 a fi\u0219ierelor (necesar pentru FAT32 sub Linux) ConfigView.label.defaultsavepath=Salveaz\u0103 \u00een dosarul implicit ConfigView.button.browse=&Exploreaz\u0103... ConfigView.dialog.choosedefaultsavepath=Alege\u021bi dosarul implicit de salvare ConfigView.section.server=Conexiune ConfigView.section.global=Generale ConfigView.label.disconnetseed=La donare, deconecteaz\u0103 ceilal\u021bi donori ConfigView.label.switchpriority=Comut\u0103 automat la prioritate sc\u0103zut\u0103 \u00een timpul don\u0103rii ConfigView.label.maxdownloads=Nr. max. de desc\u0103rc\u0103ri simultane [0:nelimitat]\n - Nu poate fi mai mare dec\u00eet num\u0103rul maxim de torente active ConfigView.label.maxdownloads.tooltip=Ve\u021bi putea desc\u0103rca \u00eentotdeauna num\u0103rul de torente specificat aici, cu o singur\u0103 excep\u021bie, anume: \nAtunci c\u00eend un torent terminat satisface criteriul de Prim\u0103 Prioritate, el ar putea prelua un slot de desc\u0103rcare activ\u0103 dac\u0103 este absolut necesar. ConfigView.label.maxactivetorrents=Nr. max. de torente active [0: nelimitat]\n - Torentele noi nu vor mai porni dac\u0103 desc\u0103rca\u021bi/dona\u021bi mai mult ConfigView.label.priorityExtensions=Prioritizeaz\u0103 automat fi\u0219ierele cu extensiile \n - de ex: .txt;.nfo;.jpg ConfigView.section.transfer=Transferuri ConfigView.label.maxuploads=Nr. max. de sloturi de \u00eenc\u0103rcare per torent ConfigView.label.maxuploadspeed=KB/s viteza max. global\u0103 de \u00eenc\u0103rcare [0: nelimitat\u0103] ConfigView.label.saveresumeinterval=Actualizeaz\u0103 datele de reluare la fiecare ConfigView.unlimited=Nelimitat ConfigView.section.display=Afi\u0219aj ConfigView.label.opendetails=Deschide automat tabelul cu detalii ConfigView.label.openbar=Deschide automat Bara de Desc\u0103rcare ConfigView.label.use_old_speed_menus=Folose\u0219te meniurile de vitez\u0103 cu stilul vechi (repornirea e necesar\u0103) ConfigView.label.closetotray=\u00cenchide \u00een Sistaler [System Tray] ConfigView.label.minimizetotray=Minimizeaz\u0103 \u00een Sistaler ConfigView.section.general=Generale ConfigView.section.start=Pornire ConfigView.label.showsplash=Arat\u0103 ecranul de prezentare ConfigView.label.autoupdate=Deschide dialogul de Promovare [Upgrade] c\u00eend e disponibil\u0103 o versiune nou\u0103 ConfigView.label.openconsole=Deschide Consola la pornire ConfigView.label.openconfig=Deschide Op\u021biunile la pornire ConfigView.label.startminimized=Porne\u0219te minimizat ConfigView.label.ircwiki=Citi\u021bi http://wiki.vuze.com/index.php/Rules_for_IRC ConfigView.label.ircchannel=Canal ConfigView.label.irclogin=Porecl\u0103 ConfigView.group.irctitle=Set\u0103ri IRC ConfigView.boolean.ircsendinfo=Permite trimiterea (anonim\u0103) a set\u0103rilor proprii c\u0103tre\n operatorii canalului pentru a-i ajuta sa-mi ofere asisten\u021b\u0103 ConfigView.boolean.irclog=Activeaz\u0103 jurnalizarea (\u00eenregistrarea) activit\u0103\u021bii canalului (\u00een IRC_log.htm) ConfigView.section.security=Securitate ConfigView.label.password=Proteja\u021bi Vuze folosind o parol\u0103\n - Va fi cerut\u0103 la restaurare (din minimizare) \u0219i la pornire. ConfigView.label.passwordconfirm=Parol\u0103 (confirmare) ConfigView.label.passwordmatch=Parola activat\u0103: ConfigView.label.passwordmatchnone=Nu ConfigView.label.passwordmatchno=Nu / Parolele nu s\u00eent identice ConfigView.label.passwordmatchyes=Da ConfigView.button.save=Salveaz\u0103 ConfigView.title.short=Op\u021biuni ConfigView.title.full=Op\u021biuni ConfigView.title.full._mac=Preferin\u021be ConsoleView.title.short=Consol\u0103 ConsoleView.title.full=Consol\u0103 FileItem.write=scriere FileItem.read=citire FileItem.normal=normal\u0103 FileItem.high=\u00eenalt\u0103 FileItem.donotdownload=Nu desc\u0103rca FileItem.delete=\u0218terge FilesView.name=Nume FilesView.name.fastRename=Redenumire Rapid\u0103 FilesView.size=M\u0103rime FilesView.done=Realizat FilesView.firstpiece=Nr. Primei P\u0103r\u021bi FilesView.numberofpieces=Nr. de P\u0103r\u021bi FilesView.pieces=P\u0103r\u021bi FilesView.mode=Mod FilesView.priority=Prioritate FilesView.menu.open=&Deschide FilesView.menu.setpriority=&Seteaz\u0103 Prioritatea FilesView.menu.setpriority.high=&\u00cenalt\u0103 FilesView.menu.setpriority.normal=&Normal\u0103 FilesView.menu.setpriority.skipped=Nu &desc\u0103rca FilesView.title.short=Fi\u0219iere FilesView.title.full=Fi\u0219iere GeneralView.section.downloaded=Desc\u0103rcat GeneralView.label.status.file=Starea Fi\u0219ierului GeneralView.label.status.pieces=Starea P\u0103r\u021bii GeneralView.section.availability=Disponibilitate GeneralView.label.status.pieces_available=Starea P\u0103r\u021bilor GeneralView.section.info=Informa\u021bii GeneralView.title.short=Generale GeneralView.title.full=Generale GeneralView.label.timeelapsed=Timp Scurs : GeneralView.label.remaining=R\u0103mas: GeneralView.label.downloaded=Desc\u0103rcat : GeneralView.label.downloadspeed=Viteza de Desc\u0103rcare : GeneralView.label.maxuploads=Sloturi de \u00cenc\u0103rcare : GeneralView.label.maxuploads.tooltip=Num\u0103rul maxim de parteneri care vor fi dezg\u00eetui\u021bi la orice moment GeneralView.label.uploaded=\u00cenc\u0103rcat : GeneralView.label.uploadspeed=Viteza de \u00cenc\u0103rcare : GeneralView.label.seeds=Donatori : GeneralView.label.peers=Parteneri: GeneralView.label.completed=Terminate : GeneralView.label.totalspeed=Viteza Roiului : GeneralView.label.totalspeed.tooltip=Viteza total\u0103 (\u0219i medie) a tuturor partenerilor la care s\u00eente\u021bi conectat. GeneralView.label.averagespeed=medie GeneralView.label.filename=Nume : GeneralView.label.totalsize=M\u0103rime Total\u0103 : GeneralView.label.savein=Salveaz\u0103 \u00een: GeneralView.label.hash=Ha\u0219 : GeneralView.label.numberofpieces=Nr. de P\u0103r\u021bi : GeneralView.label.size=M\u0103rime: GeneralView.label.tracker=Starea Trackerului : GeneralView.label.updatein=Actualizare \u00een: GeneralView.label.trackerurl=Adresa Trackerului : GeneralView.label.trackerurlupdate=Actualizeaz\u0103 Trackerul GeneralView.label.comment=Comentariul Produc\u0103torului: GeneralView.label.user_comment=Comentariul Utilizatorului: GeneralView.label.status=Stare : ManagerItem.waiting=A\u0219tept ManagerItem.allocating=Aloc ManagerItem.checking=Verific ManagerItem.ready=Gata ManagerItem.downloading=Descarc ManagerItem.seeding=Donez ManagerItem.stopped=Oprit ManagerItem.error=Eroare ManagerItem.high=\u00eenalt\u0103 ManagerItem.low=joas\u0103 MinimizedWindow.name=Nume: MinimizedWindow.all_transfers=Transferuri Vuze PiecesView.#=Nr. PiecesView.size=M\u0103rime PiecesView.numberofblocks=Nr. de Blocuri PiecesView.blocks=Blocuri PiecesView.completed=Terminate PiecesView.availability=Disponibilitate PiecesView.reservedby=Rezervat PiecesView.writers=Contribuitori la Bloc PiecesView.title.short=P\u0103r\u021bi PiecesView.title.full=P\u0103r\u021bi SystemTray.tooltip.seeding=%1 don\u0103ri, SystemTray.tooltip.downloading=%1 desc\u0103rc\u0103ri, DownloadManager.error.filenotfound=Fi\u0219ier Neg\u0103sit DownloadManager.error.fileempty=Fi\u0219ierul torent e gol DownloadManager.error.filetoobig=Fi\u0219ierul torent e prea mare DownloadManager.error.filewithouttorrentinfo=Din fi\u0219ier lipsesc informa\u021biile torentului! DownloadManager.error.unsupportedencoding=Codare Nesuportat\u0103 DownloadManager.error.ioerror=Eroare I/O DownloadManager.error.sha1=Eroare: Nu exist\u0103 un asemenea Algoritm (SHA1) PeerManager.status.offline=Eroare de Conectare PeerManager.status.checking=Verific PeerManager.status.finished=Terminat PeerManager.status.finishedin=Terminat \u00een MainWindow.upgrade.assistant=Asistent de Actualizare MainWindow.upgrade.newerversion=Exist\u0103 o versiune mai nou\u0103 de Vuze disponibil\u0103 pentru desc\u0103rcare MainWindow.upgrade.explanation=Asistentul va desc\u0103rca versiunea nou\u0103 \u00een dosarul de instalare Vuze \u0219i va reporni softul MainWindow.upgrade.explanation.manual=Pute\u021bi actualiza manual softul \u00eenchiz\u00eend Vuze, desc\u0103rc\u00eend versiunea nou\u0103 \u0219i apoi repornind softul MainWindow.upgrade.step1=Pasul 1: Desc\u0103rca\u021bi noua versiune MainWindow.upgrade.step2=Pasul 2: \u00cenchide\u021bi versiunea curent\u0103 \u0219i porni\u021bi noua versiune de Vuze MainWindow.upgrade.hint1=Pont:\tAp\u0103s\u00eend pe "Finalizeaz\u0103" duce la executarea automat\u0103 MainWindow.upgrade.hint2=Pont:\tDaca dori\u021bi s\u0103 \u00eenchide\u021bi Vuze mai t\u00eerziu, ap\u0103sa\u021bi pe "Anuleaz\u0103" \u0219i\n\t schimba\u021bi numele din Azureus2-new.jar \u00een Azureus2.jar dup\u0103 \u00eenchidere MainWindow.upgrade.error.downloading.hint=Eroare:\tNu am putut desc\u0103rca versiunea nou\u0103, actualiza\u021bi manual softul MainWindow.upgrade.section.info=Versiune Nou\u0103 Disponibil\u0103 MainWindow.upgrade.section.manual=Actualizare Manual\u0103 MainWindow.upgrade.section.automatic=Actualizare automata MainWindow.upgrade.tooltip.progressbar=Progresul desc\u0103rc\u0103rii va fi prezentat aici Button.next=Urm\u0103torul Button.finish=Finalizeaz\u0103 Button.cancel=&Anuleaz\u0103 LocaleUtil.title=Alege\u021bi Codarea LocaleUtil.section.chooseencoding=Alege\u021bi codarea pentru numele fi\u0219ierului LocaleUtil.label.chooseencoding=Selecta\u021bi codarea cea mai potrivit\u0103 LocaleUtil.label.hint.doubleclick=Pont: dublu-clic pe un r\u00eend alege codificarea \u0219i \u00eenchide dialogul LocaleUtil.label.checkbox.rememberdecision=Memoreaz\u0103 decizia pentru restul de nume de fi\u0219iere LocaleUtil.column.encoding=Codare IrcClient.defaultChannel=Canalul #Azureus-Users IrcClient.copyright=Folosesc PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Conectez la IrcClient.connected=Conectat la IrcClient.joining=Al\u0103turare IrcClient.channel=Canal IrcClient.joined=al\u0103turat IrcClient.error=Eroare IrcClient.hasjoined=s-a al\u0103turat IrcClient.haskicked=a expulzat IrcClient.hasleft=a plecat IrcClient.nowknown=e acum cunoscut ca IrcClient.topicforchannel=Topic pentru canal IrcClient.disconnected=Deconectat de la IrcClient.noNick=Nu a\u021bi specificat o porecl\u0103. Merge\u021bi la "Op\u021biuni" pentru a o face. IrcView.actionnotsupported=Ac\u021biunea nu e suportat\u0103 IrcView.clientsconnected=utilizatori IrcView.privateto=La IrcView.privatefrom=De la IrcView.noticefrom=Noti\u021b\u0103 : IrcView.errormsg=Sintax\u0103 incorect\u0103 la /msg : /msg text utilizator IrcView.help=Comenzi valide s\u00eent: \n . /help : afi\u0219eaza acest mesaj\n . /nick | /name : schimb\u0103 porecla sau numele \n . /me action : trimite o ac\u021biune \n . /msg nick message : trimite un mesaj privat c\u0103tre \n . /r message : r\u0103spunde la ultimul mesaj privat\n . /join #channel : al\u0103turare la un nou canal PasswordWindow.title=Vuze e z\u0103vor\u00eet PasswordWindow.passwordprotected=Vuze e protejat cu parol\u0103.\nPentru a ar\u0103ta fereastra Vuze, introduce\u021bi parola aici : TrackerChangerWindow.title=Adaug\u0103 Tracker TrackerChangerWindow.newtracker=Introduce\u021bi adresa noului tracker PeersView.discarded=Abandonate PeersView.discarded.info=Date primite, dar \u00eenl\u0103turate ca nefiind necesare. discarded=anula\u021bi MyTorrentsView.#=Nr MyTorrentsView.menu.move=&Mut\u0103 MyTorrentsView.menu.moveUp=&Sus MyTorrentsView.menu.moveDown=&Jos GeneralView.label.hashfails=Ha\u0219uri E\u0219uate : GeneralView.label.shareRatio=Raport de Partajare : ConfigView.section.downloadManagement=Administrarea Desc\u0103rc\u0103rii ConfigView.label.startRatioPeers=\u00cencepe donarea c\u00eend nu s\u00eent deloc donatori pentru ConfigView.text.neverStop=Nu opri niciodat\u0103 ConfigView.text.neverStart=Nu porni niciodat\u0103 ConfigView.text.peers=Parteneri ConfigView.label.checkOncompletion=Reverific\u0103 p\u0103r\u021bile dup\u0103 terminarea desc\u0103rc\u0103rii wizard.title=Creeaz\u0103 un torent wizard.previous=< \u00cenapoi wizard.next=\u00cenainte > wizard.finish=Finalizeaz\u0103 wizard.mode=Tracker / Mod wizard.invalidurl=Adresa nu este valid\u0103 wizard.singlefile=Fi\u0219ier unic wizard.singlefile.help=Creeaz\u0103 un torent dintr-un singur fi\u0219ier wizard.directory=Dosar wizard.directory.help=Creeaz\u0103 un torent dintr-un dosar wizard.choosefile=Alege\u021bi un Fi\u0219ier wizard.file=Fi\u0219ier : wizard.browse=Exploreaz\u0103... wizard.choosedirectory=Alege\u021bi un Dosar wizard.invalidfile=Fi\u0219ier Invalid! wizard.invaliddirectory=Dosar Invalid! wizard.torrentFile=Fi\u0219ier Torent wizard.choosetorrent=Alege\u021bi fi\u0219ierul torentul de creat wizard.information=Informa\u021bie wizard.notimplemented=Neimplementat \u00eenc\u0103 wizard.progresstitle=Creez Fi\u0219ierul Torent wizard.savingfile=Salvez Fi\u0219ierul... wizard.filesaved=Fi\u0219ier salvat. wizard.close=\u00cenchide Torrent.create.progress.piecelength=Lungimea p\u0103r\u021bii: Torrent.create.progress.piececount=Num\u0103rul de p\u0103r\u021bi: Torrent.create.progress.totalfilesize=M\u0103rimea total\u0103 a fi\u0219ierului: Torrent.create.progress.totalfilecount=Num\u0103rul total de fi\u0219iere: Torrent.create.progress.parsingfiles=Parsez fi\u0219ierele Torrent.create.progress.hashing=Ha\u0219ez fi\u0219ierele MainWindow.upgrade.downloadingfrom=Descarc de la : MainWindow.menu.view.ipFilter=Filtre &IP ConfigView.section.ipfilter=Filtre IP ConfigView.section.ipfilter.description=Descriere ConfigView.section.ipfilter.start=Primul IP ConfigView.section.ipfilter.end=Ultimul IP ConfigView.section.ipfilter.add=Adaug\u0103 ConfigView.section.ipfilter.remove=\u0218terge ConfigView.section.ipfilter.edit=Editeaz\u0103 ConfigView.section.ipfilter.save=Salveaz\u0103 ConfigView.section.ipfilter.editFilter=Editeaz\u0103 Filtrul ConfigView.section.ipfilter.enable=Activeaz\u0103 PeersView.menu.close=\u00cenc&hide seedmore.title=Torentul nu este donat suficient seedmore.shareratio=Raportul de partajare [share ratio] al dv. pentru acest torent este seedmore.uploadmore=Nu e bine pentru re\u021beaua BT s\u0103 ave\u021bi un raport de partajare sub 100%. \nAr trebui s\u0103 dona\u021bi acest torent \u00eenc\u0103 o perioad\u0103 de timp.\nSigur dori\u021bi s\u0103 continua\u021bi? ConfigView.label.showpopuponclose=Cere confirmare la oprirea don\u0103rii c\u00eend raportul de partajare e mai mic de 1 ConfigView.label.startNumSeeds=\nDoneaz\u0103 dac\u0103 e mai mic de\n - Ignor\u0103 celelalte reguli ConfigView.label.seeds=donatori ConfigView.section.seeding=Donare MyTorrentsView.menu.removeand=\u0218&terge MyTorrentsView.menu.removeand.deletetorrent=\u0218terge &Torentul MyTorrentsView.menu.removeand.deletedata=\u0218terge &Fi\u0219ierele Desc\u0103rcate MyTorrentsView.menu.removeand.deleteboth=\u0218terge Torentul \u0219i Fi\u0219ierele &Desc\u0103rcate deletedata.title=!!! Avertisment !!! deletedata.message1=Sigur dori\u021bi s\u0103 \u0219terge\u021bi fi\u0219ierele desc\u0103rcate ale torentului: '%1'? deletedata.noprompt=Nu m\u0103 avertiza din nou MainWindow.menu.file.configure=&Vr\u0103jitor de Configurare configureWizard.title=Vr\u0103jitor de Configurare configureWizard.welcome.title=Bine a\u021bi venit la Vr\u0103jitorul de Configurare Vuze configureWizard.welcome.message=Acest vr\u0103jitor v\u0103 va ajuta s\u0103 configura\u021bi Vuze pentru o folosire obi\u0219nuit\u0103. Pentru o configurare avansat\u0103 folosi\u021bi meniul Unelte>Op\u021biuni. configureWizard.transfer.title=Configureaz\u0103 Transferurile \u0219i Conexiunea configureWizard.transfer.hint=Pont: Un pic sub viteza maxim\u0103 suportat\u0103 de linia dv. e setarea optim\u0103. configureWizard.transfer.message=Alege\u021bi o conexiune de mai jos. Lua\u021bi aminte c\u0103 o vitez\u0103 insuficient\u0103 de \u00eenc\u0103rcare va duce la viteze de desc\u0103rcare sc\u0103zute. Datorit\u0103 faptului c\u0103 viteza de \u00eenc\u0103rcare se m\u0103soara pe FIECARE torent desc\u0103rcat, \u00eencercarea de a desc\u0103rca simultan prea multe torente va face ca vitezele de desc\u0103rcare s\u0103 fie mici. Recomand\u0103m folosirea unei viteze de 5KB/s ca un minim NECESAR. Cu c\u00eet viteza de \u00eenc\u0103rcare e mai mare, cu at\u00eet ve\u021bi putea desc\u0103rca mai rapid (depinde totu\u0219i \u0219i de viteza torentului). configureWizard.transfer.connection=Conexiune configureWizard.transfer.connection.0=Personalizat configureWizard.transfer.connection.2=adsl/cablu xxx/128 kbps configureWizard.transfer.connection.3=adsl/cablu xxx/256 kbps configureWizard.transfer.connection.4=adsl/cablu xxx/384 kbps configureWizard.transfer.connection.5=adsl/cablu xxx/512 kbps configureWizard.transfer.connection.6=adsl/cablu xxx/768 kbps configureWizard.transfer.connection.7=adsl/cablu xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Viteza Maxim\u0103 de \u00cenc\u0103rcare (KB/s) configureWizard.transfer.maxActiveTorrents=Nr. Max. Torente Active configureWizard.transfer.maxDownloads=Max Desc\u0103rc\u0103ri configureWizard.transfer.maxUploadsPerTorrent=Max \u00cenc\u0103rc\u0103ri per Torent configureWizard.nat.title=Portul NAT / Server configureWizard.nat.message=Pentru folosirea optim\u0103 a lui Vuze , este recomandat s\u0103 ave\u021bi calculatorul pe deplin accesibil dinspre internet. Aceast\u0103 unealt\u0103 v\u0103 permite s\u0103 testa\u021bi \u0219i/sau s\u0103 schimba\u021bi portul folosit pentru acceptarea conexiunilor intr\u00eende de la calculatoarele partenerilor.\n\nNOT\u0102: Aceast\u0103 unealt\u0103 testeaz\u0103 doar conexiunile TCP. Baza de Date Distribuit\u0103 [DHT] necesit\u0103 deasemenea conexiuni UDP intr\u00eende, dar v\u0103 va notifica automat dac\u0103 descoper\u0103 un paravan blocant.\n\nNOT\u0102: Portul TCP 6880 e rezervat intern, deci nu poate fi utilizat. configureWizard.nat.test=Testeaz\u0103 configureWizard.nat.testing=Testez portul configureWizard.nat.ko=Eroare NAT configureWizard.nat.unable=Imposibil de testat: Portul dat e invalid sau testarea serviciului a e\u0219uat.\nE posibil ca o alt\u0103 aplica\u021bie s\u0103 foloseasc\u0103 portul. configureWizard.file.title=Torente / Fi\u0219iere configureWizard.file.message1=Vuze va salva torentele desc\u0103rcate \u00eentr-un dosar special, pe care \u00eel pute\u021bi alege aici: configureWizard.file.path=Cale configureWizard.file.browse=Exploreaz\u0103 configureWizard.file.message2=Vuze poate relua instantaneu fi\u0219ierele prin ad\u0103ugarea unor date de reluare la torente. Cu aceast\u0103 facilitate pute\u021bi relua \u0219i p\u0103r\u021bi desc\u0103rcate incomplet. configureWizard.file.fastResume=Activeaz\u0103 reluarea rapid\u0103 configureWizard.file.invalidPath=Dosar invalid configureWizard.finish.title=Terminat configureWizard.finish.message=Vuze este acum configurat, bucura\u021bi-v\u0103 de el! wizard.close.confirmation=Confirmare wizard.close.message=Dori\u021bi \u00eenc\u0103rcarea acestui vr\u0103jitor la urm\u0103toarea pornire a programului? exportTorrentWizard.title=Export\u0103 un torent XML exportTorrentWizard.torrentfile.title=Alege\u021bi torentul de exportat exportTorrentWizard.torrentfile.message=Selecta\u021bi fi\u0219ierul torent de exportat exportTorrentWizard.torrentfile.path=Cale exportTorrentWizard.torrentfile.browse=Exploreaz\u0103 exportTorrentWizard.torrentfile.invalidPath=Fi\u0219ier torent invalid exportTorrentWizard.exportfile.title=Selectarea Fi\u0219ierului de Export exportTorrentWizard.exportfile.message=Alege\u021bi fi\u0219ierul xml \u00een care s\u0103 se exporte exportTorrentWizard.exportfile.path=Cale exportTorrentWizard.exportfile.browse=Exploreaz\u0103 exportTorrentWizard.exportfile.invalidPath=Fi\u0219ier de export invalid exportTorrentWizard.finish.title=Terminat exportTorrentWizard.finish.message=Exportare terminat\u0103 cu succes exportTorrentWizard.process.inputfilebad.title=Fi\u0219ier Torent Invalid exportTorrentWizard.process.inputfilebad.message=La accesarea fi\u0219ierului de importat a avut loc eroarea: exportTorrentWizard.process.outputfileexists.title=Fi\u0219ierul Exist\u0103 exportTorrentWizard.process.outputfileexists.message=Fi\u0219ierul \u021bint\u0103 exist\u0103 deja - \u00eel suprascriu? exportTorrentWizard.process.torrentfail.title=E\u0219ec la citirea torentului exportTorrentWizard.process.exportfail.title=Exportul torentului a e\u0219uat! exportTorrentWizard.process.unknownfail.title=Eroare Nea\u0219teptat\u0103 importTorrentWizard.title=Import\u0103 un torent din XML importTorrentWizard.torrentfile.title=Introduce\u021bi Selec\u021bia de Torente importTorrentWizard.torrentfile.message=Introduce\u021bi fi\u0219ierul torent \u00een care s\u0103 se importe importTorrentWizard.torrentfile.path=Adresa importTorrentWizard.torrentfile.browse=Exploreaz\u0103 importTorrentWizard.torrentfile.invalidPath=Fi\u0219ier torent invalid importTorrentWizard.importfile.title=Import\u0103 Fi\u0219ierele Selectate importTorrentWizard.importfile.message=Alege\u021bi fi\u0219ierul xml de importat importTorrentWizard.importfile.path=Cale importTorrentWizard.importfile.browse=Exploreaz\u0103 importTorrentWizard.importfile.invalidPath=Fi\u0219ierul de importat e invalid importTorrentWizard.finish.title=Terminat importTorrentWizard.finish.message=Import realizat cu succes importTorrentWizard.process.inputfilebad.title=Fi\u0219ier de Importat Invalid importTorrentWizard.process.inputfilebad.message=A survenit un e\u0219ec la accesarea fi\u0219ierului introdus: importTorrentWizard.process.outputfileexists.title=Fi\u0219ierul Exist\u0103 importTorrentWizard.process.outputfileexists.message=Fi\u0219ierul de ie\u0219ire exist\u0103 - \u00eel suprascriu? importTorrentWizard.process.torrentfail.title=E\u0219ec la scriere importTorrentWizard.process.importfail.title=E\u0219ec la importarea torentului importTorrentWizard.process.unknownfail.title=Eroare nea\u0219teptat\u0103 ConfigView.label.bindip=Leag\u0103 la adresa IP local\u0103 sau la interfa\u021ba de conectare ConfigView.label.xfs.allocation=Aloc\u0103 fi\u0219ierele noi folosind o metod\u0103 specific\u0103 sistemului de fi\u0219iere XFS ConfigView.label.xfs.allocation.tooltip=Asigura\u021bi-v\u0103 c\u0103 /usr/sbin/xfs_io este instalat corespunz\u0103tor pe sistemul dv. \u00cen cele mai multe distribu\u021bii Linux el este inclus \u00een pachetul "xfsprogs". xfs.allocation.xfs_io.not.found=Alocarea fi\u0219ierului prin XFS a e\u0219uat din cauz\u0103 c\u0103 /usr/sbin/xfs_io nu poate fi rulat. Asigura\u021bi-v\u0103 c\u0103 este instalat corect pe sistemul dv. Eroarea original\u0103 era : "%1". ConfigView.label.zeronewfiles=Aloc\u0103 \u0219i umple cu zero fi\u0219ierele noi la creare ConfigView.label.zeronewfiles.tooltip=Reduce fragmentarea ConfigView.section.stats=Statistici ConfigView.section.stats.enable=Activeaz\u0103 ConfigView.section.stats.defaultsavepath=Dosarul de salvare a statisticilor ConfigView.section.stats.choosedefaultsavepath=Alege\u021bi dosarul de salvare a statisticilor ConfigView.section.stats.savefreq=Frecven\u021ba salv\u0103rii ConfigView.section.stats.hours=ore ConfigView.section.stats.savefile=Numele fi\u0219ierului cu statistici ConfigView.section.stats.graph_update_dividers=Afi\u0219eaz\u0103 o linie vertical\u0103 la fiecare 60 de actualiz\u0103ri MyTorrentsView.menu.export=Torent &XML... MyTorrentsView.menu.host=&G\u0103zduie\u0219te... ManagerItem.finishing=Termin ConfigView.dialog.choosedefaulttorrentpath=Alege\u021bi dosarul implicit pentru torente ConfigView.dialog.choosemovepath=Alege\u021bi dosarul implicit \u00een care s\u0103 se fac\u0103 mutarea ConfigView.label.movecompleted=Mut\u0103 fi\u0219ierele terminate (dup\u0103 desc\u0103rcare) ConfigView.label.moveremoved=Mut\u0103 fi\u0219ierele terminate (c\u00eend s\u00eent \u00eenl\u0103turate) ConfigView.label.savetorrents=Salveaz\u0103 fi\u0219ierele torent MainWindow.menu.view.mytracker=&Trackerul Meu MyTrackerView.title.full=Trackerul Meu MyTrackerView.name=Nume MyTrackerView.status=Stare MyTrackerView.status.started=Ruleaz\u0103 MyTrackerView.status.stopped=Oprit MyTrackerView.peers=Parteneri MyTrackerView.seeds=Donatori MyTrackerView.announces=Anun\u021buri MyTrackerView.uploaded=\u00cenc\u0103rcat MyTrackerView.downloaded=Desc\u0103rcat MyTrackerView.left=R\u0103mas ConfigView.section.style=Interfa\u021b\u0103 ConfigView.label.set_ui_transfer_speeds=Ignor\u0103 vitezele de transfer selectabile ConfigView.label.set_ui_transfer_speeds.description=Pute\u021bi alege s\u0103 defini\u021bi manual vitezele de desc\u0103rcare \u0219i de \u00eenc\u0103rcare disponibile pe bara de stare din sistaler [system tray].\nValorile trebuie s\u0103 fie separate prin virgule. ConfigView.label.set_ui_transfer_speeds.description.download=Seteaz\u0103 vitezele de desc\u0103rcare (\u00een KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Seteaz\u0103 vitezele de \u00eenc\u0103rcare (\u00een KB/s) ConfigView.section.style.useCustomTabs=Folose\u0219te taburi ce pot fi \u00eenchise (necesit\u0103 repornire) MainWindow.menu.view.plugins=E&xtensii fileDownloadWindow.saveTorrentIn=Salveaz\u0103 fi\u0219ierul torent \u00een fileDownloadWindow.title=Vuze - Desc\u0103rc\u0103tor de Torente fileDownloadWindow.downloading=Descarc de la : fileDownloadWindow.status=Stare : fileDownloadWindow.state_initializing=Ini\u021bializez fileDownloadWindow.state_downloading=Descarc fileDownloadWindow.state_error=Eroare: MainWindow.menu.file.open.url=&Loca\u021bia... openUrl.title=Deschide Loca\u021bia MyTorrentsView.menu.host.error.title=G\u0103zduirea torentului a e\u0219uat MyTorrentsView.menu.host.error.message=A ap\u0103rut urm\u0103toarea eroare la g\u0103zduirea torentului ConfigView.section.tracker.pollinterval=Intervalul de sondare a clientului de c\u0103tre tracker (sec) ConfigView.section.tracker.publishenable=Public\u0103 detaliile torentului la "" ConfigView.section.tracker.ip=Adresa IP extern\u0103 a trackerului ConfigView.section.style.enableXPStyle=Activeaz\u0103 stilul XP (necesit\u0103 repornire) IPChecker.external.service.dyndns.url=www.dyndns.org/ IPChecker.external.service.dyndns.description=Dynamic DNS Network Services, SRL ConfigView.section.tracker.checkip=Descoper\u0103 automat adresa IP extern\u0103... ipCheckerWizard.title=Vr\u0103jitor de Verificare IP ipCheckerWizard.service=Serviciu ipCheckerWizard.chooseService=Alege\u021bi un serviciu de verificat IP-uri din lista afi\u0219at\u0103 ipCheckerWizard.explanations=Folosi\u021bi acest vr\u0103jitor pentru a v\u0103 descoperi adresa IP extern\u0103. Dac\u0103 ave\u021bi o adres\u0103 IP dinamic\u0103, v\u0103 recomand\u0103m s\u0103 deschide\u021bi un cont la un Serviciu de DNS dinamic. C\u00eeteva dintre aceste servicii s\u00eent trecute mai jos. Folosi\u021bi leg\u0103turile \u0219i crea\u021bi-v\u0103 un cont (\u00een cazul \u00een care se poate). Apoi completa\u021bi c\u00eempul IP cu numele gazdei dv. dinamice (de ex: gazdamea.dyndns.org). Ve\u021bi avea nevoie de un program care s\u0103 actualizeze automat Serviciul DNS dinamic cu adresa IP a dv. \u00cen acest fel ve\u021bi putea g\u0103zdui torente chiar dac\u0103 IP-ul dv. se schimb\u0103. ipCheckerWizard.service.description=Descriere: ipCheckerWizard.service.url=Leg\u0103tur\u0103 : ipCheckerWizard.progresstitle=Verific IP ipCheckerWizard.checkComplete=IP completat : ipCheckerWizard.checkFailed=E\u0219uat, motivul : wizard.tracker.local=Folose\u0219te trackerul \u00eencorporat \u00een Vuze wizard.tracker.external=Folose\u0219te un tracker extern wizard.tracker.howToLocal=\tMerge\u021bi la "Unelte">"Op\u021biuni">"Tracker" pentru activare wizard.announceUrl=Adres\u0103 de Anun\u021bare : IPChecker.external.service.discoveryvip.url=ip.discoveryvip.com/ IPChecker.external.service.discoveryvip.description=Discoveryvip - doar verificare a adresei IP IPChecker.external.httpinvalidresponse=R\u0103spuns HTTP invalid IPChecker.external.loadingwebpage=\u00cencarc pagina web IPChecker.external.analysingresponse=Analizez r\u0103spunsul IPChecker.external.addressextracted=Adresa IP extras\u0103 IPChecker.external.httploadfail=\u00cenc\u0103rcarea paginii a e\u0219uat IPChecker.external.timeout=Timp expirat IPChecker.external.ipnotfound=Adresa IP nu a fost g\u0103sit\u0103 ConfigView.section.tracker.pollintervalmin=Minim\u0103 ConfigView.section.tracker.pollintervalmax=Maxim\u0103 ConfigView.section.tracker.pollintervalincby=Cre\u0219te cu ConfigView.section.tracker.pollintervalincper=La fiecare "n" clien\u021bi splash.loadingImages=\u00cencarc Imaginile splash.initializeGui=Ini\u021bializez Fereastra Principal\u0103 splash.openViews=Deschid Vederile splash.plugin=\u00cencarc Extensia : configureWizard.nat.tooManyPorts=Prea multe porturi de testat (max 9) ConfigView.section.color=Schema de Culori MyTorrentsView.menu.publish=Pub&lic\u0103... MyTrackerView.status.published=Publicat MyTrackerView.completed=Progres MainWindow.menu.file.open.torrentnodefault=Fi\u0219ier Torent... (F\u0103r\u0103 Salvare Implicit\u0103) wizard.comment=Comentariu ConfigView.label.movetorrent=Mut\u0103 Fi\u0219ierul Torent ConfigView.label.movepartialdownloads=Mut\u0103 chiar dac\u0103 anumite fi\u0219iere s\u00eent marcate "Nu Desc\u0103rca" ConfigView.label.subdir_is_in_default=Atunci c\u00eend se investigheaz\u0103 existen\u021ba unor desc\u0103rc\u0103ri \u00eentr-un anumit dosar, trebuie luate \u00een calcul \u0219i subdosarele acestuia ConfigView.section.file.decoder.label=Codarea implicit\u0103 a torentului c\u00eend selectarea e obligatorie ConfigView.section.file.decoder.nodecoder=Nimic IPChecker.external.service.no-ip.url=www.no-ip.com/ IPChecker.external.service.no-ip.description=Furnizor al serviciului DNS dinamic \u0219i static\n(serviciul 'verific\u0103 adresa' nu e disponibil gratuit) ConfigView.section.tracker.publicenable=Activeaz\u0103 torentele externe ConfigView.label.playdownloadspeech=Vorbe\u0219te c\u00eend s-a terminat o desc\u0103rcare ConfigView.label.playdownloadspeech.info=Serviciile de Vorbire merg momentan mai bine \u00een Englez\u0103 # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Afi\u0219eaz\u0103 num\u0103rul de copii disponibile pentru fiecare parte.\n\u00cen cazul \u00een care num\u0103rul din dreapta e mai mic de 1 \u00eenseamn\u0103 c\u0103 nu s-a g\u0103sit nici o copie \u00eentreag\u0103 (\u0219i e posibil s\u0103 ave\u021bi dificult\u0103\u021bi la terminarea desc\u0103rc\u0103rii). GeneralView.label.trackerurl.tooltip=Clica\u021bi pentru copierea adresei de anun\u021bare \u00een cliplan\u0219et\u0103 GeneralView.label.trackerurlopen.tooltip=Clic pentru deschiderea paginii trackerului # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Actualizeaz\u0103 GUI la fiecare ConfigView.section.style.inactiveUpdate=Actualizeaz\u0103 fereastra principal\u0103 la fiecare N actualiz\u0103ri ale GUI c\u00eend nu este fereastr\u0103 principal\u0103 ConfigView.section.style.graphicsUpdate=Actualizeaz\u0103 barele grafice la fiecare N actualiz\u0103ri ale GUI ConfigView.section.style.reOrderDelay=Reordoneaz\u0103 tabelele la fiecare N actualiz\u0103ri ale GUI [0: niciodat\u0103] ConfigView.section.style.reOrderDelay.never=Niciodat\u0103 ConfigView.section.logging=Jurnalizare ConfigView.section.logging.enable=Activeaz\u0103 jurnalizarea \u00eentr-un fi\u0219ier ConfigView.section.logging.logdir=Dosarul fi\u0219ierului jurnal ConfigView.section.logging.choosedefaultsavepath=Alege\u021bi dosarul de salvare GeneralView.label.updatein.querying=Interoghez... configureWizard.nat.sharePort=Folose\u0219te un singur port de intrare partajat de toate torentele ConfigView.section.logging.maxsize=M\u0103rimea maxim\u0103 a fi\u0219ierului jurnal ConfigView.section.tracker.passwordenableweb=Activeaz\u0103 parol\u0103 pentru re\u021beaua trackerului ConfigView.section.tracker.passwordenabletorrent=Activeaz\u0103 parol\u0103 pentru torente ConfigView.section.tracker.username=Utilizator ConfigView.section.tracker.password=Parol\u0103 columnChooser.title=Alege\u021bi coloanele de afi\u0219at columnChooser.move=Trage\u021bi r\u00eendurile ca s\u0103 le reordona\u021bi columnChooser.apply=Aplic\u0103 columnChooser.columnname=Numele Coloanei columnChooser.columndescription=Descriere TableColumn.header.shareRatio=Raport MyTorrentsView.menu.editTableColumns=Configureaz\u0103 &Coloanele wizard.operationfailed=Opera\u021biunea a e\u0219uat authenticator.title=Necesit\u0103 Autentificare authenticator.realm=Domeniu authenticator.user=Utilizator authenticator.password=Parol\u0103 ConfigView.label.allowSendVersion=Permite\u021bi ca Vuze s\u0103 trimit\u0103 \u00een mod anonim num\u0103rul versiunii \u0219i un identificator aleator la verificarea apari\u021biei versiunilor noi. ConfigView.label.version.info.link=Afla\u021bi detalii despre ce date s\u00eent trimise la serverul de verficare a versiunii wizard.hint.mode=Point:\tPute\u021bi trage \u0219i depune un singur fi\u0219ier sau dosar \u00een acest vr\u0103jitor pentru a alege un fi\u0219ier sau un dosar wizard.hint.file=Pont:\tPute\u021bi alege un singur fi\u0219ier prin tragere-\u0219i-depunere wizard.hint.directory=Pont:\tPute\u021bi alege un singur dosar prin tragere-\u0219i-depunere MainWindow.menu.help.checkupdate=&Caut\u0103 Actualiz\u0103ri... TableColumn.header.down=Desc\u0103rcat TableColumn.header.up=\u00cenc\u0103rcat ConfigView.section.tracker.passwordenabletorrent.info=Necesit\u0103 un client BitTorrent potrivit (de ex. Vuze) ConfigView.section.style.confirmationOnExit=Arat\u0103 dialogul de confirmare la ie\u0219ire MainWindow.dialog.exitconfirmation.title=P\u0103r\u0103sesc Vuze? MainWindow.dialog.exitconfirmation.text=Sigur dori\u021bi s\u0103 p\u0103r\u0103si\u021bi Vuze? SystemTray.menu.stopalltransfers=&Opre\u0219te Transferurile TrayWindow.menu.stopalldownloads=Opre\u0219te To&ate Desc\u0103rc\u0103rile ConfigView.section.tracker.sslport.info=Vezi FAQ pentru alte informa\u021bii wizard.tracker.ssl=Folose\u0219te SSL ConfigView.label.playdownloadfinished=Emite un sunet c\u00eend desc\u0103rcarea s-a terminat ConfigView.label.popupdownloadfinished=Arat\u0103 o alert\u0103 popup la terminarea unei desc\u0103rc\u0103ri ConfigView.label.popupfilefinished=Arat\u0103 o alert\u0103 popup la terminarea unui fi\u0219ier TableColumn.header.pieces=P\u0103r\u021bi TableColumn.header.pieces.info=Bar\u0103 grafic\u0103 ar\u0103t\u00eend p\u0103r\u021bile pe care le-a\u021bi desc\u0103rcat TableColumn.header.completion=Realizare TableColumn.header.completion.info=Reprezentare grafic\u0103 a % desc\u0103rcat ConfigView.section.style.showdownloadbasket=Arat\u0103 Co\u0219ul de Desc\u0103rcare (pt. tras \u0219i depus torente) ConfigView.section.style.alwaysShowTorrentFiles=Arat\u0103 mereu fi\u0219ierele torent \u00een Detalii/Fi\u0219iere wizard.multitracker=Adaug\u0103 la torent informa\u021bia despre Multi-Tracker wizard.multitracker.title=Tracker Multiplu wizard.multitracker.configuration=Configura\u021bia Multi-Trackerului wizard.multitracker.new=Nou... wizard.multitracker.edit=Editeaz\u0103.. wizard.multitracker.delete=\u0218terge wizard.multitracker.group=Grup de Trackere wizard.multitracker.edit.title=Editorul Multi-Trackerului wizard.multitracker.edit.name=Nume wizard.multitracker.edit.save=Salveaz\u0103 wizard.multitracker.edit.newgroup=Grup Nou wizard.multitracker.edit.deletegroup=\u0218terge wizard.multitracker.edit.newtracker=Tracker Nou wizard.multitracker.edit.deletetracker=\u0218terge wizard.multitracker.edit.edit=Editeaz\u0103 wizard.addingmt=Adaug Info Multi-Tracker wizard.multitracker.noannounce=Adresa de anun\u021bare nu apare \u00een lista dv. de trackere MyTorrentsView.menu.recheck=For\u021beaz\u0103 Re&verificarea iconBar.showDownloadBar.tooltip=Arat\u0103 Bara de Desc\u0103rcare iconBar.start.tooltip=Porne\u0219te iconBar.stop.tooltip=Opre\u0219te iconBar.remove.tooltip=\u0218terge iconBar.openNoDefault.tooltip=Deschide un fi\u0219ier torent (f\u0103r\u0103 salvare implicit\u0103) iconBar.openURL.tooltip=Deschide o Adres\u0103 (URL) iconBar.openFolder.tooltip=Deschide un Dosar iconBar.new.tooltip=Creeaz\u0103 Torent iconBar.up.tooltip=Mut\u0103 \u00een Sus iconBar.down.tooltip=Mut\u0103 \u00een Jos iconBar.run.tooltip=Deschide iconBar.host.tooltip=G\u0103zduie\u0219te iconBar.publish.tooltip=Public\u0103 iconBar.editcolumns.tooltip=Alege\u021bi ce coloane s\u0103 fie afi\u0219ate MyTorrentsView.menu.editTracker=&Editeaz\u0103 Adresa Trackerului GeneralView.menu.selectTracker=Selecteaz\u0103 ConfigView.section.stats.xslfile=Numele fi\u0219ierului XSL ConfigView.section.stats.xslfiledetails=Vor fi incluse \u00een antetul fi\u0219ierului cu statistici prin tagul ConfigView.label.savetorrentbackup=Salveaz\u0103 Copie de Rezerv\u0103 ConfigView.section.tracker.forceport=For\u021beaz\u0103 torentele g\u0103zduite extern c\u0103tre portul implicit ConfigView.section.ipfilter.allow=PERMITE aceste intervale (implicit este INTERZICE) ConfigView.section.ipfilter.list.inrange=era \u00een interval ConfigView.section.ipfilter.list.notinrange=nu era \u00een nici un interval ConfigView.section.ipfilter.list.title=Adrese IP blocate ConfigView.label.allowsameip=Permite conexiuni multiple de la aceea\u0219i adres\u0103 IP ConfigView.label.allowsameip.tooltip=Bifa\u021bi numai dac\u0103 e NEVOIE.\nC\u00eend e dezactivat\u0103 e o protec\u021bie anti-lipitori (utilizatori care nu \u00eencarc\u0103 date). ManagerItem.superseeding=Superdonare ConfigView.label.userSuperSeeding=Folose\u0219te Superdonarea PeersView.uniquepiece=Parte (Mod de Superdonare) PeersView.uniquepiece.none=Nimic PeersView.timetosend=Timp p\u00een\u0103 la retrimiterea p\u0103r\u021bii (Mod de Superdonare) ConfigView.section.style.addurlsilently=Adaug\u0103 adresele (URL) \u00een mod silen\u021bios ConfigView.section.style.addurlsilently.tooltip=Descarc\u0103 automat (f\u0103r\u0103 a deschide o caset\u0103 de dialog) torentele ale c\u0103ror adrese s\u00eent trase \u0219i depuse \u00een program ConfigView.section.file.decoder.prompt=Aten\u021bioneaz\u0103 mereu c\u00eend e disponibil\u0103 o alegere pt. codare ConfigView.section.file.decoder.prompt.tooltip=Arat\u0103 mereu un dialog c\u00eend e disponibil\u0103 o alegere pt. codare MyTorrentsView.menu.moveTop=&V\u00eerf MyTorrentsView.menu.moveEnd=&Ultimul ConfigView.label.moveonlyusingdefaultsave=numai dac\u0103 s\u00eent \u00een dosarul implicit de date ConfigView.label.moveonlyusingdefaultsave.tooltip=Mut\u0103 doar dac\u0103 fi\u0219ierele desc\u0103rcate se afl\u0103 \u00een dosarul folosit implicit pt. ele ConfigView.label.watchtorrentfolder=Import\u0103 automat fi\u0219ierele torent noi ConfigView.label.watchtorrentfolder.tooltip=Caut\u0103 regulat torente noi ConfigView.label.watchtorrentfolderinterval.tooltip=Intervalul p\u00een\u0103 la scanarea urm\u0103toare a dosarului ConfigView.dialog.choosewatchtorrentfolderpath=Alege\u021bi dosarul pentru importat torente ConfigView.label.startwatchedtorrentsstopped=Porne\u0219te opritele ConfigView.label.startwatchedtorrentsstopped.tooltip=Adaug\u0103 torentele noi \u00een stare OPRIT\u0102 ConfigView.section.plugins=Extensii wizard.maketorrent.filesize=M\u0103rimea Fi\u0219ierelor wizard.maketorrent.piececount=Num\u0103rul P\u0103r\u021bilor wizard.maketorrent.piecesize=M\u0103rimea P\u0103r\u021bii wizard.maketorrent.auto=Automat MainWindow.menu.view.stats=&Statistici SpeedView.title.full=Activitate SpeedView.downloadSpeed.title=Viteza de Desc\u0103rcare SpeedView.uploadSpeed.title=Viteza de \u00cenc\u0103rcare ConfigView.section.style.useSIUnits=Folose\u0219te unit\u0103\u021bi IEC (KB -> KiB etc.) iconBar.top.tooltip=Mut\u0103 \u00een v\u00eerf iconBar.bottom.tooltip=Mut\u0103 la Sf\u00eer\u0219it TableColumn.header.health=S\u0103n\u0103tate MyTorrentsView.menu.health=Despre S\u0103n\u0103tate health.explain.grey=\u00eenseamn\u0103 c\u0103 torentul nu func\u021bioneaz\u0103 (desc\u0103rcare sau \u00eenc\u0103rcare) health.explain.red=\u00eenseamn\u0103 c\u0103 nu s\u00eente\u021bi conectat la nici un partener c\u00eend desc\u0103rca\u021bi health.explain.blue=la donare, \u00eenseamn\u0103 c\u0103 nu s\u00eente\u021bi conectat \u00eenc\u0103 la nici un partener. \nla desc\u0103rcare, \u00eenseamn\u0103 c\u0103 s\u00eente\u021bi conectat la c\u00ee\u021biva parteneri, dar trackerul este indisponibil. health.explain.yellow=\u00eenseamn\u0103 c\u0103 trackerul func\u021bioneaz\u0103 corect, s\u00eente\u021bi conectat la parteneri, dar nu ave\u021bi nici o leg\u0103tur\u0103 ini\u021biat\u0103 din exterior. \n\u00cen cazul \u00een care toate torentele s\u00eent colorate \u00een galben e posibil s\u0103 ave\u021bi o problem\u0103 cu NAT-ul. health.explain.green=\u00eenseamn\u0103 c\u0103 totul e \u00een regul\u0103. ConfigView.section.style.alwaysRefreshMyTorrents=\u00cemprosp\u0103teaz\u0103 \u00eentotdeauna Torentele Mele ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Aceast\u0103 op\u021biune va \u00eemprosp\u0103ta vederea Torentelor Mele chiar \u0219i c\u00eend aceasta e neafi\u0219at\u0103 (util pentru unele extensii mirc) # #2.0.7.0 # security.certtruster.title=Avertisment privitor la certificat security.certtruster.intro=Certificatul de securitate a fost eliberat de o companie \u00een care nu ave\u021bi \u00eencredere security.certtruster.resource=Resurs\u0103: security.certtruster.issuedto=Eliberat catre: security.certtruster.issuedby=Eliberat de: security.certtruster.prompt=\u00cei acorda\u021bi \u00eencredere? security.certtruster.yes=Da security.certtruster.no=Nu. ConfigView.section.tracker.torrentsperpage=C\u00eete torente pe fiecare pagin\u0103? [0: nelimitat] MainWindow.menu.file.share=&Partajeaz\u0103 MainWindow.menu.file.share.file=&Fi\u0219ier... MainWindow.menu.file.share.dir=D&osar... MainWindow.menu.file.share.dircontents=&Con\u021binutul Dosarului... MainWindow.menu.file.share.dircontentsrecursive=Con\u021binutul Dosarului... (&Recursiv) MainWindow.dialog.share.sharefile=Selecta\u021bi Fi\u0219ierul de Partajat MainWindow.dialog.share.sharedir=Alege\u021bi Dosarul de Partajat MainWindow.dialog.share.sharedircontents=Alege\u021bi Con\u021binutul Partajat din Dosar MainWindow.dialog.share.sharedircontents.recursive=Recursiv globalmanager.download.remove.veto=\u0218tergere refuzat\u0103 plugin.sharing.download.remove.veto=Aceast\u0103 desc\u0103rcare e rezultatul partaj\u0103rii clasice a unei resurse comune.\nPentru a \u00eenl\u0103tura desc\u0103rcarea, \u00eenl\u0103tura\u021bi partajarea clasic\u0103 asociat\u0103. ConfigView.section.tracker.main=Principal ConfigView.section.tracker.web=Re\u021bea ConfigView.label.prioritizefirstpiece=Prioritizeaz\u0103 prima \u0219i ultima parte din fi\u0219iere ConfigView.label.prioritizefirstpiece.tooltip=Se \u00eencearc\u0103 mai \u00eent\u00eei desc\u0103rcarea p\u0103r\u021bilor de \u00eenceput \u0219i de sf\u00eer\u0219it ale fi\u0219ierului.\nPentru previzionarea precoce (\u00een timp ce se descarc\u0103). ConfigView.section.file.confirm_data_delete=Cere confirmare la \u0219tergerea de fi\u0219iere ConfigView.section.file.confirm_data_delete.tooltip=Confirmare la \u0219tergere ConfigView.section.file.delete.include_files_outside_save_dir=C\u00eend se \u0219terg fi\u0219iere, permite \u0219i \u0219tergerea fi\u0219ierelor rela\u021bionate (legate) care exist\u0103 \u00een afara dosarului de salvare a torentelor TrayWindow.menu.startalldownloads=Pone\u0219te Toate Desc\u0103rc\u0103rile SystemTray.menu.startalltransfers=Porne\u0219te Transferurile sharing.progress.title=Progresul Partaj\u0103rii Clasice sharing.progress.hide=Ascunde MainWindow.menu.view.myshares=Partajul Meu MySharesView.title.full=Partajul Meu MySharesView.name=Nume MySharesView.type=Tip MySharesView.type.file=Fi\u0219ier MySharesView.type.dir=Dosar MySharesView.type.dircontents=Con\u021binutul dosarului MySharesView.type.dircontentsrecursive=Con\u021binutul dosarului (recursiv) MySharesView.menu.remove=\u0218terge ConfigView.section.tracker.extensions=Extensii ConfigView.section.tracker.sendpeerids=Trimite identitatea partenerilor la desc\u0103rc\u0103tori ConfigView.section.tracker.enableudp=Activeaz\u0103 protocolul pt. trackere UDP plugin.sharing.torrent.remove.veto=\u00cenregistrarea acestui tracker e rezultatul unei resurse partajate clasic.\nPentru a \u00eenl\u0103tura desc\u0103rcarea, \u00eenl\u0103tura\u021bi partajarea clasic\u0103 asociat\u0103. plugin.download.remove.veto.notstopped=Desc\u0103rcarea nu poate fi \u00eenl\u0103turat\u0103 dac\u0103 nu e oprit\u0103 plugin.sharing.remove.veto=Aceast\u0103 partajare clasic\u0103 e o subparte a partaj\u0103rii con\u021binutului unui dosar, deci nu se poate \u0219terge direct.\n\u0218terge\u021bi partajarea clasic\u0103 a r\u0103d\u0103cinii. GeneralView.label.hash.tooltip=Clica\u021bi pentru a copia ha\u0219ul \u00een cliplan\u0219et\u0103 ConfigView.section.tracker.maxpeersreturned=Max parteneri raporta\u021bi [0: nelimitat] ConfigView.label.serverport=Port de ascultare a conexiunilor TCP / UDP intr\u00eende ConfigView.label.serverport.tooltip=Num\u0103rul portului trebuie s\u0103 fie \u00eentre 1 \u0219i 65535, dar nu 6880 care este rezervat pentru uzul intern al lui Vuze. configureWizard.nat.server.tcp_listen_port=Port TCP de ascultare ConfigView.section.sharing=Partajare Clasic\u0103 ConfigView.section.sharing.usessl=Folose\u0219te SSL pt. resursele partajate clasic (necesit\u0103 configurarea trackerului) ConfigView.section.style.dropdiraction=Ac\u021biune de tip tragere-\u0219i-depunere pentru dosare ConfigView.section.style.dropdiraction.opentorrents=Deschide Torentele ConfigView.section.style.dropdiraction.sharefolder=Dosarul Partajului ConfigView.section.style.dropdiraction.sharefoldercontents=Con\u021binutul Partajului # # 2.0.7.x # Categories.all=Tot Categories.uncategorized=Necategorisit CategoryAddWindow.message=Introduce\u021bi numele categoriei CategoryAddWindow.title=Ad\u0103uga\u021bi o Categorie Nou\u0103 ConfigView.label.autoSeedingIgnoreInfo=Torentele ignorate merg la coada \u0219irului de donare. Ele nu vor fi pornite automat. \nRegulile de ignorare nu se aplic\u0103 torentelor care satisfac criteriile de Prim\u0103 Prioritate. \u00cen afara cazului c\u0103 se specific\u0103 altfel, folosi\u021bi valoarea 0 pentru a dezactiva o regul\u0103. ConfigView.label.directory=Catalog ConfigView.label.disconnetseed.tooltip=La donarea unui torent, deconecteaz\u0103 orice clien\u021bi care doneaz\u0103 \u0219i ei. \nNu e necesar ca ei s\u0103 fie conecta\u021bi la sistemul dv. ConfigView.label.ignoreCase=Ignor\u0103 MAJ/min ConfigView.label.ignoreSeeds=Ignor\u0103 torentele cu cel pu\u021bin ConfigView.label.importdirectory=Dosarul Importurilor ConfigView.label.minPeersToBoostNoSeeds.tooltip=Orice torent f\u0103r\u0103 donatori \u0219i cu mai pu\u021bini parteneri dec\u00eet a\u021bi specificat\nva fi mutat spre cap\u0103tul cozii. ConfigView.label.minPeersToBoostNoSeeds=Mic\u0219oreaz\u0103 Rangul de Donare pt. torentele f\u0103r\u0103 donatori \u0219i mai pu\u021bin de ConfigView.label.minSeedingTime.tooltip=Rangurile de Donare pot fluctua apreciabil pentru scurte perioade de timp, c\u00eeteodat\u0103 f\u0103c\u00eend ca torentul s\u0103 porneasc\u0103 automat, pentru ca imediat dup\u0103 aceea s\u0103 fie oprit \u0219i pus \u00een coada de a\u0219teptare.\nAceast\u0103 op\u021biune u\u0219ureaz\u0103 problema for\u021b\u00eend torentul s\u0103 r\u0103m\u00een\u0103 donat pentru o anumit\u0103 perioad\u0103 de vreme. Poate fi totu\u0219i oprit manual dac\u0103 se dore\u0219te asta. ConfigView.label.minSeedingTime=Durata minim\u0103 de donare \u00een secunde ConfigView.label.minSpeedForActiveDL.tooltip=Un slot de desc\u0103rcare e folosit mereu pt. primele 30 de secunde\ndup\u0103 pornirea torentului incomplet. ConfigView.label.minSpeedForActiveDL=Nu considera c\u0103 torentul folose\u0219te un slot de desc\u0103rcare dac\u0103 viteza sa e sub ConfigView.label.peers=parteneri ConfigView.label.queue.debuglog=\u00cenregistreaz\u0103 informa\u021biile despre debugare ConfigView.label.queue.debuglog.info=Adaug\u0103 informa\u021bii despre debugarea cozii la consol\u0103/fi\u0219ierul jurnal.\nDe\u0219i s\u00eent criptice, informa\u021biile despre debugare comunic\u0103 starea torentelor \u0219i motivul pentru care s\u00eent sau nu s\u00eent puse \u00een coada de a\u0219teptare. ConfigView.label.queue.minQueueingShareRatio=Nu pune \u00een coad\u0103 sau opri torentul p\u00een\u0103 ce raportul de partajare nu atinge ConfigView.label.ratio=raport ConfigView.label.removeOnStop=\u0218terge torentul din list\u0103 dup\u0103 ce se opre\u0219te automat ConfigView.label.savedirectory=Dosar de Salvare ConfigView.label.seeding.autoReposition.tooltip=\u00cen cazul activ\u0103rii, ordinea torentelor (coloana "#") va fi modificat\u0103 pentru a se potrivi cu Rangul de Donare.\nEste util \u00een cazul \u00een care nu dori\u021bi s\u0103 fie afi\u0219ate Rangurile de Donare, dar dori\u021bi s\u0103 \u0219ti\u021bi \u00een ce ordine vor porni torentele terminate. ConfigView.label.seeding.autoReposition=Repozi\u021bioneaz\u0103 automat torentele dup\u0103 Rangul de Donare ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u00cen cele mai multe cazuri torentele cu pu\u021bini donatori \u0219i mul\u021bi parteneri s\u00eent rezultatul faptului c\u0103 nu exist\u0103 o copie \u00eentreag\u0103 a fi\u0219ierului la vreun partener. \nA\u0219adar, e posibil s\u0103 nu dori\u021bi ca regulile de donare s\u0103 pretind\u0103 c\u0103 ar exista o copie complet\u0103 (\u0219i astfel s\u0103 fie redus rangul \u00een mod incorect) ConfigView.label.seeding.fakeFullCopySeedStart=dar numai pentru torente cu cel pu\u021bin ConfigView.label.seeding.ignore=Reguli de Ignorare ConfigView.label.seeding.ignore0Peers=Ignor\u0103 torentele cu 0 parteneri ConfigView.label.seeding.ignoreRatioPeers=Ignor\u0103 torentele care au cel pu\u021bin un donator la fiecare ConfigView.label.seeding.ignoreShareRatio=Ignor\u0103 torentele cu un raport de partajare de ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignor\u0103 torentul chiar dac\u0103\nsatisface regula de Maxim\u0103 Prioritate ConfigView.label.seeding.ignore.header.rule=Regul\u0103 ConfigView.label.seeding.ignore.header.value=Valoare ConfigView.label.seeding.firstPriority.info=Torentele de Prim\u0103 Prioritate vor fi \u00eentotdeauna \u00een v\u00eerful listei. \nTorentele ce satisfac criteriul de Prim\u0103 Prioritate nu vor fi oprite \u0219i puse \u00een coad\u0103. \nUn torent ce satisface criteriul de Prim\u0103 Prioritate va ocupa un slot de Desc\u0103rcare Simultan\u0103 dac\u0103 este nevoie. ConfigView.label.seeding.firstPriority.FP=Prima Prioritate ConfigView.label.seeding.firstPriority=Prima prioritate e pentru torentele cu ConfigView.label.seeding.firstPriority.following=din urm\u0103toarele: ConfigView.label.seeding.firstPriority.shareRatio=Raport de Partajare sub ConfigView.label.seeding.firstPriority.seedingMinutes=Timpul scurs de la schimbarea ac\u021biunii din desc\u0103rcare \u00een donare ConfigView.label.seeding.firstPriority.DLMinutes=Timp scurs de la \u00eenceputul desc\u0103rc\u0103rii ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Pretinz\u00eend c\u0103 exist\u0103 o copie complet\u0103 la fiecare X parteneri, pute\u021bi reduce rangul torentelor cu mul\u021bi parteneri.\nAproape sigur, torentele cu mul\u021bi parteneri au \u0219i trafic ridicat.\nAceasta nu schimb\u0103 \u00eens\u0103 afi\u0219area num\u0103rului de donatori. ConfigView.label.seeding.numPeersAsFullCopy=Presupune c\u0103 exist\u0103 1 copie complet\u0103 la fiecare \n(0: Nu presupune) ConfigView.label.seeding.preferLargerSwarms.tooltip=Are rost s\u0103 prefera\u021bi roiuri mai mari dac\u0103 dona\u021bi \u00een principal torente cu parteneri "stabili"\nDac\u0103 dona\u021bi \u00een special torente cu disponibilitate ridicat\u0103, e mai bine s\u0103 prefera\u021bi roiuri mai mici. ConfigView.label.seeding.preferLargerSwarms=C\u00eend torentele au rang egal, prefer\u0103 roiurile mai mari ConfigView.label.seeding.rankType.none.tooltip=Ordoneaz\u0103 dup\u0103 coloana # ConfigView.label.seeding.rankType.none=Nimic ConfigView.label.seeding.rankType.peer.tooltip=mai mul\u021bi prieteni \u0219i mai pu\u021bini donatori = rang mai mare\nAceast\u0103 ierarhizare minimizeaz\u0103 num\u0103rul de torente care trebuie \u021binute active pentru a maximiza \u00eenc\u0103rcarea ConfigView.label.seeding.rankType.peer=Num\u0103r Ponderat al Prietenilor ConfigView.label.seeding.rankType.peerSeed.options=Op\u021biuni ale Raportului Donatori:Parteneri ConfigView.label.seeding.rankType.peerSeed.tooltip=Raport \u00cenalt = Rang \u00cenalt ConfigView.label.seeding.rankType.peerSeed=Raportul Donatori:Parteneri ConfigView.label.seeding.rankType.seed.fallback=Revino la Raportul Partener:Donator dup\u0103 \n(0 : Niciodat\u0103) ConfigView.label.seeding.rankType.seed.options=Op\u021biuni Exclusive ale Num\u0103rului de Donatori ConfigView.label.seeding.rankType.seed.tooltip=Mai Pu\u021bini Donatori = Rang Mai Mare ConfigView.label.seeding.rankType.seed=Doar Num\u0103rul Donatorilor ConfigView.label.seeding.rankType.timedRotation.tooltip=Toate torentele terminate aflate \u00een coad\u0103 vor fi donate prin rota\u021bie. \nDurata don\u0103rii e setat\u0103 prin op\u021biunea "Timp Minim de Donare" ConfigView.label.seeding.rankType.timedRotation=Rota\u021bie Periodic\u0103 ConfigView.label.seeding.rankType.tooltip=Torentele de rangul cel mai \u00eenalt s\u00eent pornite automat. \nAtunci c\u00eend alt torent cap\u0103t\u0103 un rang mai \u00eenalt, cel r\u0103mas cu rangul mai mic se opre\u0219te \u0219i este pus din nou \u00een coada de a\u0219teptare.\n\n Numai torentele aflate \u00een coada de a\u0219teptare pot fi pornite automat.\n Torentele oprite nu vor fi niciodat\u0103 pornite automat. ConfigView.label.seeding.rankType=Ordoneaz\u0103 torentele terminate pentru autopornire pe baza: ConfigView.label.stopAfterMinutes=Odat\u0103 comutat pe donare, opre\u0219te dup\u0103 un anumit interval de timp ConfigView.label.switchpriority.tooltip=Prioritatea sc\u0103zut\u0103 reduce l\u0103\u021bimea de band\u0103 ascendent\u0103 alocat\u0103 torentului. ConfigView.pluginlist.info=Am g\u0103sit urm\u0103toarele extensii. Unele din ele nu au op\u021biuni de configurare. ConfigView.pluginlist.noplugins=Nu am descoperit nici o extensie. ConfigView.section.pluginslist=Lista ConfigView.section.queue.seeding=Donare ConfigView.section.queue.seeding.autoStarting=Pornire Automat\u0103 ConfigView.section.queue.seeding.ignore=Reguli de Ignorare ConfigView.section.queue.seeding.firstPriority=Prima Prioritate ConfigView.section.queue.main=Principal ConfigView.section.queue=Coad\u0103 ConfigView.section.torrents=Torente ConfigView.text.all=toate ConfigView.text.hours=ore ConfigView.text.ignoreRule=Regula de Ignorare ConfigView.text.ignore=Ignor\u0103 ConfigView.text.minutes=minute ConfigView.text.neverIgnore=Nu ignora niciodat\u0103 ConfigView.text.any=oricare DownloadManager.error.datamissing=Date Lips\u0103 MainWindow.menu.file.open.torrentforseeding=Fi\u0219ier Torent... (Pentru Donare) MainWindow.menu.language.refresh=\u00ce&mprosp\u0103teaz\u0103 ManagerItem.forced=For\u021bat ManagerItem.queued=Pus \u00een Coad\u0103 MySeedersView.header=Torente Terminate TableColumn.header.availability.info=nr. de copii complete descoperite TableColumn.header.availability=Disponibilitate TableColumn.header.category=Categorie MyTorrentsView.header=Torente Incomplete TableColumn.header.maxuploads=Nr. Max. \u00cenc\u0103rc\u0103ri MyTorrentsView.menu.category.delete=\u0218ter&ge Categoria MyTorrentsView.menu.forceStart=Porne\u0219te &For\u021bat MyTorrentsView.menu.queue=&Pune \u00een Coad\u0103 MyTorrentsView.menu.setCategory.add=&Categorie Nou\u0103... MyTorrentsView.menu.setCategory=Pune \u00een Categoria TableColumn.header.savepath=Calea de Salvare TableColumn.header.SeedingRank=Rang de Donare TableColumn.header.totalspeed.info=Viteza total\u0103 a partenerilor la care s\u00eente\u021bi conectat TableColumn.header.totalspeed=Vitez\u0103 Total\u0103 splash.initializePlugins=Ini\u021bializez Extensiile StartStopRules.SPratioMet=Raport S:P OK StartStopRules.FP0Peers=FP / 0 Parteneri StartStopRules.0Peers=0 Parteneri StartStopRules.numSeedsMet=Nr. de Surse OK StartStopRules.ratioMet=Parteneri:Surse OK StartStopRules.shareRatioMet=Raport de Partajare OK StartStopRules.waiting=A\u0219tept StartStopRules.firstPriority=1a Prioritate ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Con\u021binutul Partajului (Recursiv) DownloadManager.error.unabletostartserver=Imposibil de pornit Serverul - verifica\u021bi configurarea porturilor de intrare \u0219i permisiunile paravanului [firewall] pentru ca aplica\u021bia s\u0103 func\u021bioneze ca server. GeneralView.label.creationdate=Creat pe : ConfigView.section.tracker.announcescrapepercentage=Interval de r\u0103zuire ca procentaj din cel de anun\u021bare\nde ex. 200 = 2:1. 0 = las\u0103 partenerul s\u0103 decid\u0103 ManagerItem.stopping=Opresc ConfigView.section.tracker.announcecacheperiod=Ca\u0219ul anun\u021burilor (ms) ConfigView.section.tracker.scrapecacheperiod=Ca\u0219ul r\u0103zuirii (ms) ConfigView.section.tracker.scrapeandcache=R\u0103zuie\u0219te \u0219i ca\u0219eaz\u0103 ConfigView.section.tracker.announcecacheminpeers=Anun\u021b\u0103 pragul de parteneri ca\u0219at [cached] MyTrackerView.scrapes=R\u0103zuiri fileDownloadWindow.retry=Re\u00eencearc\u0103 MyTrackerView.bytesin=Bai\u021bi Primi\u021bi MyTrackerView.bytesinave=Medie Primit\u0103 MyTrackerView.bytesout=Bai\u021bi Trimi\u0219i MyTrackerView.bytesoutave=Medie Trimis\u0103 ConfigView.section.file.max_open_files=Nr. maxim de fi\u0219iere deschise pt. citire/scriere\n[0: nelimitat] ConfigView.section.file.max_open_files.tooltip=Util dac\u0103 desc\u0103rca\u021bi torente cu sute \u0219i mii de fi\u0219iere \u00een ele, care provoac\u0103 atingerea limitei SO pt. m\u00eenerele fi\u0219ierelor. ConfigView.section.proxy=Op\u021biuni Proxy ConfigView.section.proxy.enable_proxy=Permite proxificarea comunic\u0103rilor cu trackerul (necesit\u0103 repornire) ConfigView.section.proxy.host=Gazda ConfigView.section.proxy.username=Utilizator ConfigView.section.proxy.password=Parola ConfigView.section.proxy.enable_socks=Am un proxy de tip SOCKS wizard.createtorrent.extrahashes=Adaug\u0103 ha\u0219uri pentru alte re\u021bele (de ex. Gnutella2, eDonkey2000) GeneralView.label.connected=conecta\u021bi GeneralView.label.in_swarm=\u00een roi ManagerItem.initializing=Ini\u021bializez AlertMessageBox.error=Eroare AlertMessageBox.warning=Avertisment AlertMessageBox.comment=Informa\u021bii AlertMessageBox.information=Informa\u021bii AlertMessageBox.unread=Ave\u021bi mesaje de avertizare necitite - clica\u021bi aici pentru a le afi\u0219a. SharedPortServer.alert.selectorfailed=Nu am reu\u0219it s\u0103 stabilim un ascult\u0103tor pentru datele intr\u00eende. \nVerifica\u021bi dac\u0103 set\u0103rile paravanului [firewall] permit ca java(w).exe s\u0103 func\u021bioneze ca "server" Tracker.alert.listenfail=E\u0219ec la stabilirea ascult\u0103rii pe portul %1.\nVerifica\u021bi dac\u0103 nu exist\u0103 alte programe care \u00eel folosesc\nVerifica\u021bi dac\u0103 nu ruleaz\u0103 alt\u0103 instan\u021b\u0103 a lui Vuze. DiskManager.alert.movefileexists=Eroare la mutarea fi\u0219ierelor terminate\nFi\u0219ierul %1 exist\u0103 deja \u00een dosarul de destina\u021bie DiskManager.alert.movefilefails=Eroare la mutarea fi\u0219ierelor terminate\nMutarea fi\u0219ierului %1 a e\u0219uat, %2 DiskManager.alert.movefilerecoveryfails=Repararea erorii dup\u0103 mutare a e\u0219uat\nRestaurarea fi\u0219ierului %1 a e\u0219uat, %2 ConfigView.section.tracker.logenable=Consemneaz\u0103 periodic statisticile \u00een "tracker.log" SpeedView.stats.title=Statistici SpeedView.stats.session=Aceast\u0103 Sesiune SpeedView.stats.downloaded=Desc\u0103rcat (Protocol) SpeedView.stats.uploaded=\u00cenc\u0103rcat (Protocol) SpeedView.stats.ratio=Raport SpeedView.stats.uptime=Durata \u00cenc\u0103rc\u0103rii SpeedView.stats.now=Acum SpeedView.stats.now.tooltip=Total (pe protocol) AutoMigration.useralert=Rezultatele automigr\u0103rii fi\u0219./dos. de config. ale utilizatorului:\n\n%1\nE\u0219u\u0103rile trebuie migrate manual.\nNU UITA\u021aI S\u0102 ACTUALIZA\u021aI DESTINA\u021aIILE DE SALVARE \u00ceN CONFIGURA\u021aIE DAC\u0102 AU FOST MUTATE! # # > 2.0.8.0 # OpenTorrentWindow.title=Deschide Torentele OpenTorrentWindow.addFiles=&Adaug\u0103 Fi\u0219iere OpenTorrentWindow.dataLocation=Locul de salvare a datelor: OpenTorrentWindow.startMode=Mod de Ad\u0103ugare OpenTorrentWindow.startMode.queued=Pus \u00een Coad\u0103 OpenTorrentWindow.startMode.stopped=Oprit OpenTorrentWindow.startMode.forceStarted=Pornit For\u021bat OpenTorrentWindow.addPosition=Pozi\u021bia \u00een Coad\u0103 OpenTorrentWindow.addPosition.first=Primul OpenTorrentWindow.addPosition.last=Ultimul TableColumn.header.remaining.info=Cantitate r\u0103mas\u0103 de desc\u0103rcat TableColumn.header.remaining=R\u0103mas ConfigView.section.tracker.enablecompact=Activeaz\u0103 protocolul cu anun\u021buri compacte ConfigView.section.tracker.enablekey=Activeaz\u0103 pasarea cheilor c\u0103tre tracker pt. cre\u0219terea siguran\u021bei ConfigView.section.file.perf=Op\u021biuni de Performan\u021b\u0103 ConfigView.section.file.perf.explain=Avertisment - schimbarea \u00een necuno\u0219tin\u021b\u0103 de cauz\u0103 a acestor parametri poate afecta viteza de desc\u0103rcare. Necesit\u0103 repornirea.\nDac\u0103 ave\u021bi probleme legate de epuizarea memoriei, lua\u021bi \u00een considerare limitarea num\u0103rului de conexiuni per torent (Vezi Configura\u021bie>Transfer) ConfigView.section.file.max_open_files.explain=Deschiderea unui num\u0103r prea mare de fi\u0219iere poate crea probleme pentru sistemul de operare, din cauza limitelor unor resurse cum s\u00eent m\u00eenerele fi\u0219ierelor. Aceast\u0103 op\u021biune limiteaz\u0103 num\u0103rul de fi\u0219iere deschise \u00een acela\u0219i timp. popup.error.hide=Ascunde popup.error.details=Detalii ConfigView.section.style.colorOverrides=Supradefiniri de culori ConfigView.section.style.colorOverride.progressBar=Bara de Progres ConfigView.section.style.colorOverride.error=Eroare MainWindow.status.tooOld=e veche, v\u0103 rug\u0103m s\u0103 o actualiza\u021bi. ConfigView.section.style.colorOverride.warning=Avertisment ConfigView.section.style.colorOverride.altRow=R\u00eenduri Alternante ConfigView.section.file.save.peers.enable=Salveaz\u0103 conexiunile cu partenerii pentru reconect\u0103ri rapide ConfigView.section.file.save.peers.max=Nr. Max de parteneri de salvat [0: nelimitat] ConfigView.section.file.save.peers.pertorrent=per torent ConfigView.label.max_peers_per_torrent=Nr. max. de conexiuni (parteneri) per torent [0: nelimitat] ConfigView.label.max_peers_total=Nr. max. global de conexiuni (parteneri) [0: nelimitat] ConfigView.section.style.colorOverrides.reset=Reseteaz\u0103 Culoarea ConfigView.section.language.info=In cazul bif\u0103rii, la fiecare pornire Vuze va c\u0103uta o versiune nou\u0103. ConfigView.section.language.enableUpdate=Permite actualizarea pe net ConfigView.section.language.UpdateURL=Adresa de actualizare ConfigView.section.language.UpdateNow=Actualizeaz\u0103 Acum! Button.revert=Reverseaz\u0103 MyTorrentsView.menu.changeDirectory=Schimb\u0103 Dosarul cu Date GenericText.column=Coloan\u0103 MyTorrentsView.menu.thisColumn.remove=\u0218terge Coloana MyTorrentsView.menu.thisColumn.toClipboard=Copiaz\u0103 Textul \u00een Cliplan\u0219et\u0103 MyTorrentsView.menu.thisColumn.autoTooltip=Arat\u0103 Mereu Ponturile Flotante MyTorrentsView.menu.tracker=Tracker/Torent ConfigView.upload.abbreviated=\u00ce: TableColumn.header.secondsseeding=Donez de TableColumn.header.secondsseeding.info=Timpul total al don\u0103rii pe care a\u021bi f\u0103cut-o. TableColumn.header.secondsdownloading=Desc\u0103rcat de TableColumn.header.secondsdownloading.info=Timpul total c\u00eet a\u021bi desc\u0103rcat. ConfigView.section.tracker.udpversion=Versiunea Protocolului UDP(1 sau 2) window.updateswt.title=Versiunea existent\u0103 de SWT e prea veche! window.updateswt.text=Versiunea existent\u0103 de SWT e prea veche!\nSWT este biblioteca grafic\u0103 folosit\u0103 de Vuze, iar cea pe care o ave\u021bi este prea veche pentru rularea ultimei versiuni de Vuze. Ap\u0103sa\u021bi butonul OK pentru a actualiza SWT. window.updateswt.status=Stare window.updateswt.failed=Actualizarea a e\u0219uat, ap\u0103sa\u021bi OK din nou pentru repornire. window.updateswt.status.downloading.updater=Descarc modulul de actualizare window.updateswt.status.finding=Caut ultima versiune de SWT window.updateswt.status.downloading=Descarc ultima versiune de SWT window.updateswt.status.done=Repornesc window.updateswt.cancel=Anuleaz\u0103 swt.updater.downloader.downloading=Descarc SWT de la swt.updater.urlsgetter.downloading=Iau o list\u0103 de clone de la swt.updater.urlsgetter.platform=SWT pt. platform\u0103 : window.updateswt.ignore=Ignor\u0103 ConfigView.section.style.useFancyTabs=Folose\u0219te taburi elegante splash.initializeGM=Ini\u021bializez Managerul Global de Torente splash.loadingTorrents=\u00cencarc Torentele MyTorrentsView.menu.thisColumn.sort=&Sorteaz\u0103 Scrape.status.ok=R\u0103zuire OK Scrape.status.error=Eroare de R\u0103zuire: Scrape.status.error.badURL=Adresa de anun\u021bare nu respect\u0103 specifica\u021biile r\u0103zuirii. Scrape.status.error.nohash=Ha\u0219ul lipse\u0219te din r\u0103spuns. Scrape.status.error.invalid=R\u0103spuns incorect. Scrape.status.nextScrapeAt=Urm\u0103toarea r\u0103zuire la %1 Scrape.status.scraping=R\u0103zuiesc... Scrape.status.initializing=A\u0219tept s\u0103 r\u0103zuiesc... Scrape.status.scraping.queued=R\u0103zuire pus\u0103 \u00een coada de a\u0219teptare... ConfigView.label.minSpeedForActiveSeeding=Nu considera c\u0103 torentul terminat folose\u0219te un slot dac\u0103 viteza sa e sub ConfigView.section.stats.exportpeers=Detaliile Partenerului Exportat MainWindow.menu.view.irc.moved=IRC este acum disponibil ca extensie, vede\u021bi http://azureus.sourceforge.net/plugin_list.php. Dup\u0103 instalare, folosi\u021bi meniul Vezi > Extensii > IRC pentru accesare. MyTrackerView.webui.contextmenu.copyurl=Copiaz\u0103 \u00een cliplan\u0219et\u0103 adresa torentului ConfigView.section.file.torrent.ignorefiles=Fi\u0219iere de ignorat la crearea torentelor\nde ex. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignor fi\u0219ierul ConfigView.section.style.useUnitsRateBits=Folose\u0219te bi\u021bi \u00een loc de bai\u021bi pentru valorile \u00een bai\u021bi ale vitezei (KiB/s->Kibit/s etc.) ConfigView.section.interface.resetassoc=Reseteaz\u0103 asocierile fi\u0219ierelor (.torrent) \u00een explorator ConfigView.section.interface.resetassocbutton=Reseteaz\u0103 ConfigView.section.interface.checkassoc=Verific\u0103 asocierile la pornire dialog.associations.title=Verific\u0103 Asocierea Button.yes=&Da Button.no=&Nu ConfigView.label.seeding.autoStart0Peers=Porne\u0219te automat toate torentele terminate, chiar cu 0 parteneri ConfigView.label.seeding.autoStart0Peers.tooltip=Activa\u021bi dac\u0103 dori\u021bi ca trackerul s\u0103 listeze mereu donatorii pt. torentele cu 0 parteneri. dialog.associations.prompt=Vuze nu e aplica\u021bia implicit\u0103 pentru fi\u0219iere Bit Torrent.\nDori\u021bi s\u0103 asocia\u021bi fi\u0219ierele .torrent cu Vuze? dialog.associations.askagain=Verific\u0103 la pornire ConfigView.section.plugins.update=Actualizarea Extensiilor Plugin.pluginupdate.enablecheck=Activeaz\u0103 verificarea actualiz\u0103rilor extensiilor. plugins.basicview.status=Stare: plugins.basicview.activity=Activitate: plugins.basicview.progress=Progres: plugins.basicview.log=Jurnal: ConfigView.label.maxdownloadspeed=KB/s viteza max. global\u0103 de desc\u0103rcare [0: nelimitat\u0103] splash.loadingTorrent=\u00cencarc Torentul splash.of=din UpdateWindow.title=Actualizatorul Vuze UpdateWindow.header=Componentele urm\u0103toare necesit\u0103 actualizare : UpdateWindow.columns.install=Instaleaz\u0103 UpdateWindow.columns.name=Nume UpdateWindow.columns.version=Versiune UpdateWindow.columns.size=M\u0103rime UpdateWindow.cancel=Anuleaz\u0103... UpdateWindow.quit=Ie\u0219i UpdateWindow.close=\u00cenchide UpdateWindow.ok=Actualizeaz\u0103 UpdateWindow.restart=Reporne\u0219te Vuze Acum UpdateWindow.status.downloading=Descarc UpdateWindow.status.done=Efectuat UpdateWindow.status.failed=E\u0219uat UpdateWindow.status.restartNeeded=E necesar\u0103 repornirea! ConfigView.pluginlist.broken=Defect ConfigView.pluginlist.whereToPut=Pune extensiile exclusive utilizatorului \u00een propriul s\u0103u dosar la: ConfigView.pluginlist.whereToPutOr=Pt. extensiile comune folose\u0219te: MainWindow.statusText.checking=Caut Actualiz\u0103ri TableColumn.header.OnlyCDing4=Doar Donare TableColumn.header.OnlyCDing4.info=Timpul c\u00eet torentul a fost doar donat. Este exclus timpul c\u00eet torentul a fost folosit pentru primirea \u0219i donarea de date \u00een acela\u0219i timp. ConfigView.section.style.alternateTablePainting=Folose\u0219te metoda alternativ\u0103 pentru colorarea coloanelor tabelului (e posibil s\u0103 necesite repornirea) UpdateWindow.status.restartMaybeNeeded=Repornirea poate fi necesar\u0103 ConfigView.pluginlist.shared=partajat PeersView.host=Numele Gazdei PeersView.host.info=Numele gazdei partenerului, dac\u0103 e disponibil (poate reduce performan\u021ba) MainWindow.menu.help.whatsnew=Ce-i Nou ConfigView.label.checkonstart=Verific\u0103 la pornirea softului dac\u0103 a ap\u0103rut o versiune nou\u0103 ConfigView.label.periodiccheck=Caut\u0103 periodic versiune nou\u0103 de Vuze ConfigView.label.opendialog=Deschide automat Actualizatorul c\u00eend e disponibil\u0103 o actualizare MainWindow.updateavail=Clica\u021bi aici pentru actualizare MainWindow.status.latestversionunchecked=Verificarea versiunii e dezactivat\u0103 GeneralView.label.updatein.stopped=Oprit StartStopRules.menu.viewDebug=Vezi Informa\u021bii de Debugare ConfigView.section.style.doNotUseGB=Nu folosi unitatea GB ConfigView.section.style.doNotUseGB.tooltip=Daca e bifat\u0103, Vuze va continua s\u0103 foloseasc\u0103 MB chiar \u0219i pentru m\u0103rimi de peste 1024 MB MainWindow.menu.help.plugins=Pagina cu Extensii ConfigView.section.plugins.TrackerWeb=Adresa Trackerului ConfigView.section.tracker.enablecategories=Separ\u0103 torentele dup\u0103 categorii health.explain.share=\u00eenseamn\u0103 c\u0103 torentul e g\u0103zduit sau publicat ConfigView.section.tracker.createcert=Creeaz\u0103 Certificat Autosemnat ConfigView.section.tracker.createbutton=Creeaz\u0103 security.certcreate.title=Creeaz\u0103 Certificat Autosemnat security.certcreate.intro=Acest dialog v\u0103 permite s\u0103 crea\u021bi un certificat autosemnat security.certcreate.strength=Putere security.certcreate.firstlastname=Prenume \u0219i Nume security.certcreate.orgunit=Unitate de Organizare security.certcreate.org=Organiza\u021bie security.certcreate.city=Localitate security.certcreate.state=Statul sau Provincia security.certcreate.country=Codul din dou\u0103 litere al \u021b\u0103rii security.certcreate.ok=Creeaz\u0103 security.certcreate.cancel=Anuleaz\u0103... security.certcreate.createok=Crearea certificatului a reu\u0219it. security.certcreate.createfail=Crearea certificatului a e\u0219uat ConfigView.section.plugins.webui=Comut\u0103 Interfa\u021ba de Re\u021bea ConfigView.section.plugins.xml_http_if=Interfa\u021ba XML/HTTP webui.passwordenable=Activeaz\u0103 parola webui.user=Utilizator webui.password=Parol\u0103 webui.port=Portul (*) webui.protocol=Protocolul (*) webui.homepage=Acas\u0103 (*) webui.rootdir=Dosarul r\u0103d\u0103cin\u0103 (*) webui.rootres=Resursa r\u0103d\u0103cin\u0103 (*) webui.mode=Mod (*) webui.mode.info=Modul poate fi\n\t"full"\t= toate opera\u021biunile disponibile (predefinit)\n\t"view"\t= doar afi\u0219are (se poate actualiza frecven\u021ba \u00eemprosp\u0103t\u0103rilor) webui.access=Acces (*) webui.access.info=Accesul poate fi \n\t"local"\t= doar calculatorul local se poate conecta \n\t"all"\t= acces nerestric\u021bionat (predefinit)\n\tIP\t= ex. 192.168.0.2\t\t\tun singur IP\n\tIP1-IP2\t= ex. 192.168.0.1-192.168.0.255\t interval de IP-uri GeneralView.label.maxdownloadspeed=Viteza Maxim\u0103 de Desc\u0103rcare Security.keystore.corrupt=E\u0219ec la \u00eenc\u0103rcarea stocului de parole '%1' , \u0219tergeti-l \u0219i recrea\u021bi sau reimporta\u021bi certificatele Security.keystore.empty=Stocul de parole e gol. Crea\u021bi un certificat autosemnat (vezi Unelte>Op\u021biuni>Securitate) sau importa\u021bi unul existent in %1' webui.restart.info=Modific\u0103rile parametrilor marca\u021bi cu (*) au nevoie de repornirea softului pentru a fi activate GeneralView.label.maxdownloadspeed.tooltip=viteza max desc\u0103rcare [0: nelimitat\u0103] upnp.enable=Activeaz\u0103 UPnP upnp.info=Universal Plug and Play (UPnP) permite maparea automat\u0103 a porturilor \u00een ruterele care folosesc acest standard. upnp.mapping.dataport=Port de Intrare a Datelor Partenerilor upnp.mapping.tcptrackerport=Port al Trackerului TCP upnp.mapping.udptrackerport=Port al Trackerului UDP upnp.alert.differenthost=UPnP: Maparea '%1' a fost deja rezervat\u0103 de '%2' - selecta\u021bi un alt port upnp.alert.mappingok=UPnP: Maparea '%1' e f\u0103cut\u0103 upnp.alert.mappingfailed=UPnP: Maparea '%1' a e\u0219uat upnp.alertsuccess=Raporteaz\u0103 succesul map\u0103rilor upnp.alert.lostdevice=UPnP: Am pierdut leg\u0103tura cu serviciul '%1' pe dispozitivul UPnP '%2' upnp.grabports=Mapeaz\u0103 porturile chiar dac\u0103 s\u00eent ale altui calculator upnp.refresh.label=\u00cemprosp\u0103teaz\u0103 map\u0103rile upnp.refresh.button=\u00cemprosp\u0103teaz\u0103 upnp.alert.mappinggrabbed=UPnP: Maparea '%1' e f\u0103cut\u0103 - luat\u0103 de la '%2' upnp.mapping.tcpssltrackerport=Port al Trackerului TCP SSL upnp.alertothermappings=Raporteaz\u0103 porturile altor calculatoare upnp.alertdeviceproblems=Raporteaz\u0103 problemele cu dispozitivul UPnP upnp.trace_to_log=Trimite informa\u021bii de debugare complete \u00een jurnal upnp.wiki_link=Pagina din Wikiul Vuze despre UPnP upnp.refresh_mappings_on_bad_nat=\u00cemprosp\u0103teaz\u0103 automat map\u0103rile c\u00eend starea NAT-ului este "paravanat". ConfigView.pluginlist.coreplugins=Urm\u0103toarele extensii \u00eencorporate s\u00eent \u00eenc\u0103rcate: Peers.column.DLedFromOthers=De la Al\u021bii Peers.column.DLedFromOthers.info=Cantitatea de date desc\u0103rcate de la al\u021bii c\u00eet au fost conecta\u021bi la dv. Peers.column.UpDownRatio=Sus:Jos Peers.column.UpDownRatio.info=Rata "Sus:Jos" a partenerului Peers.column.UpRatio=Raport \u00cenc Peers.column.UpRatio.info=Raportul "Desc\u0103rcat de la mine / Desc\u0103rcat de la al\u021bii" al partenerului upnp.releasemappings=Elibereaz\u0103 map\u0103rile la ie\u0219ire webui.upnpenable=Activeaz\u0103 UPnP pentru portul acesta (*) ConfigView.section.file.friendly.hashchecking=Verificare a ha\u0219ului mai pu\u021bin solicitant\u0103 ConfigView.section.file.friendly.hashchecking.tooltip=Un mod ceva mai lent de verificare a ha\u0219urilor p\u0103r\u021bilor, dar mult mai pu\u021bin solicitant pentru CPU \u0219i sistem ConfigView.section.tracker.seedretention=Nr. max. de donatori re\u021binu\u021bi per torent [0: nelimitat] ConfigView.section.tracker.seedretention.info=Not\u0103: Statisticile de \u00eenc\u0103rcare pentru donatorii nere\u021binu\u021bi vor fi pierdute ConfigView.section.tracker.port=Permite trackerului s\u0103 foloseasc\u0103 portul HTTP ConfigView.section.tracker.sslport=Permite trackerului s\u0103 foloseasc\u0103 portul HTTPS ConfigView.section.tracker.publicenable.info=Aceasta le permite celorlal\u021bi s\u0103 creeze torente ce folosesc trackerul dv.\nf\u0103r\u0103 ca s\u0103 le g\u0103zdui\u021bi/publica\u021bi Button.clear=\u0218terge MainWindow.IPs.tooltip=Ultima actualizare a listei de IP-uri filtrate: %1\nNum\u0103rul total de IP-uri filtrate \u00een list\u0103 - Num\u0103rul de IP-uri blocate/interzise sau gre\u0219ite \u00een sesiunea actual\u0103.\nDublu-clic pentru detalii. ConfigView.section.ipfilter.list.banned=a fost blocat ConfigView.section.ipfilter.list.baddata=a trimis date nefolositoare: instan\u021be = Button.reset=Reseteaz\u0103 ConfigView.section.ipfilter.bannedinfo=Adrese IP care au trimis date false - blocate \u00een cazul dep\u0103\u0219irii limitelor ConfigView.section.ipfilter.blockedinfo=Adrese IP blocate cu filtrele IP download.removerules.name=Reguli de \u00cenl\u0103turare download.removerules.unauthorised.info=Torentele neautorizate s\u00eent cele pentru care r\u0103spunsul la anun\u021b con\u021bine termenul "neautorizat" \u00een "r\u0103spunsul de eroare" download.removerules.unauthorised=\u0218terge automat torentele neautorizate download.removerules.unauthorised.seedingonly=\tDoar la donare download.removerules.removed.ok=\u0218tergerea automat\u0103 a torentului '%1' a reu\u0219it. Aceasta s-a realizat prin aplicarea regulilor de \u00eenl\u0103turare a torentelor. download.removerules.updatetorrents=\u0218terge la cererea roiului torentele de actualizare Vuze ConfigView.label.defaultstarttorrentsstopped=Adaug\u0103 \u00een mod implicit torentele noi \u00een stare oprit\u0103 ConfigView.section.server.enableudp=Activeaz\u0103 protocolul clien\u021bilor cu trackere UDP upnp.mapping.dataportudp=Port al clientului tracker UDP ConfigView.section.file.decoder.showlax=Arat\u0103 \u0219i cod\u0103rile mai pu\u021bin probabile ConfigView.section.file.decoder.showall=Ia \u00een considerare toate cod\u0103rile posibile MainWindow.status.updowndetails.tooltip=Viteza de Desc\u0103rcare/\u00cenc\u0103rcare\nClic-dreapta pentru schimbare, dublu-clic pentru statistici TrackerClient.announce.warningmessage=Trackerul pentru '%1' a returnat avertismentul '%2' ConfigView.section.tracker.natcheckenable=Verific\u0103 dac\u0103 portul de primit date este conectabil \u0219i raporteaz\u0103 partenerilor \u00een caz de e\u0219ec ConfigView.section.tracker.publishenabledetails=Public\u0103 toate detaliile torentului ConfigView.section.tracker.publishenablepeerdetails=Public\u0103 detaliile partenerilor MyTrackerView.badnat=NAT Gre\u0219it MyTrackerView.badnat.info=Donatorii/Partenerii cu verificare e\u0219uat\u0103 a NAT-ului, dac\u0103 e activat\u0103 ConfigView.section.tracker.natchecktimeout=Expirarea verific\u0103rii (sec) ConfigView.section.file.perf.cache.enable=Activeaz\u0103 ca\u0219ul hardiscului [disk cache] ConfigView.section.file.perf.cache.size=M\u0103rimea ca\u0219ului \u00een %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=T&ransferuri MainWindow.menu.transfers.startalltransfers=Po&rne\u0219te Tot MainWindow.menu.transfers.stopalltransfers=&Opre\u0219te Tot MainWindow.menu.transfers.pausetransfers=&Pauzeaz\u0103 MainWindow.menu.transfers.resumetransfers=&Reia ConfigView.label.experimental.osx.kernel.panic.fix=Repara\u021bie experimental\u0103 pentru panicile de kernel \u00een sistemele OSX cu dou\u0103 procesoare [necesit\u0103 repornire] SystemTray.menu.pausetransfers=Pauzeaz\u0103 Transferurile SystemTray.menu.resumetransfers=Reia Transferurile ConfigView.section.file.truncate.too.large=Trunchiaz\u0103 fi\u0219ierele prea mari care exist\u0103 deja ConfigView.section.file.perf.cache.trace=Urm\u0103re\u0219te opera\u021biunile cu ca\u0219ul \u00een scopuri de diagnosticare ConfigView.section.interface.enabletray=Activeaz\u0103 Sistalerul (necesit\u0103 repornire) PeerManager.status.error=Eroare Stats.title.full=Statistici TransferStatsView.title.full=Transferuri CacheView.title.full=Ca\u0219 CacheView.general.size=M\u0103rime Total\u0103 CacheView.general.inUse=\u00cen Uz CacheView.general.title=Informa\u021bii despre Ca\u0219 CacheView.reads.title=Citiri I/O CacheView.reads.fromFile=Din Fi\u0219ier CacheView.reads.fromCache=Din Ca\u0219 CacheView.reads.hits=Reu\u0219ite CacheView.writes.title=Scrieri I/O CacheView.writes.toCache=Spre Ca\u0219 CacheView.writes.toFile=Spre Fi\u0219ier CacheView.writes.hits=Salvat CacheView.speeds.title=Vitezele Datelor CacheView.speeds.reads=Citiri CacheView.speeds.writes=Scrieri CacheView.speeds.fromCache=Din/Spre Ca\u0219 CacheView.speeds.fromFile=Din/Spre Fi\u0219ier CacheView.reads.#=Nr. CacheView.reads.amount=Cantitate CacheView.reads.avgsize=M\u0103rime medie openUrl.referrer=Adresa referentului : openUrl.referrer.info=Necesar numai pentru siturile care \u00eel cer ConfigView.label.maxuploadspeedseeding=Viteza alternativ\u0103 c\u00eend se doneaz\u0103 ConfigView.label.transfer.ignorepeerports=Ignor\u0103 partenerii cu porturile de date urm\u0103toare (separare cu ';' , de ex. 0;25) ConfigView.section.proxy.enable_socks.peer=Activeaz\u0103 proxyul la comunicarea cu partenerii (numai pt. conexiuni ie\u0219inde, necesit\u0103 repornire) ConfigView.section.proxy.peer.informtracker=Informeaz\u0103 trackerul despre limitare ConfigView.section.proxy.socks.version=Versiunea SOCKS PiecesView.legend.written=Scris PiecesView.legend.requested=Solicitat PiecesView.legend.downloaded=Desc\u0103rcat, se a\u0219teapt\u0103 scrierea PiecesView.legend.incache=Datele s\u00eent \u00een Ca\u0219 PiecesView.typeItem.0=Lent PiecesView.typeItem.1=Rapid PiecesView.type=Tip Security.jar.tools_not_found=E\u0219ec la semnarea JAR - Nu am putut g\u0103si 'tools.jar' \u00een %1. Pentru detalii consulta\u021bi Unelte>Op\u021biuni>Securitate Security.jar.signfail=Semnarea JAR a e\u0219uat - %1 ConfigView.section.security.toolsinfo=Fi\u0219ierele JAR identificate cu semn\u0103turi s\u00eent folosite pentru a asista unele extensii, de exemplu interfa\u021ba Swing Web (c\u00eend e configurat\u0103 \u00een acest scop). \nPentru a a putea semna un fi\u0219ier JAR e necesar accesul la fi\u0219ierul "tools.jar" care e primit \u00eempreun\u0103 cu pachetul de instalare Sun JDK (nu JRE!). \n\u00cen cazul \u00een care ave\u021bi instalat numai JRE, rug\u0103m instala\u021bi \u0219i JDK. \n\u00cen mod obi\u0219nuit, Vuze descoper\u0103 automat fi\u0219ierul. Cu toate acestea, \u00een caz de e\u0219ec pute\u021bi specifica aici dosarul care-l con\u021bine. ConfigView.section.security.toolsdir=Dosarul ce con\u021bine 'tools.jar' ConfigView.section.security.choosetoolssavedir=Selecta\u021bi dosarul ce con\u021bine 'tools.jar' authenticator.torrent=Torent ConfigView.section.proxy.peer.same=Folose\u0219te acelea\u0219i set\u0103ri proxy pentru comunicarea cu trackerul \u0219i cu partenerii ConfigView.section.connection.network.max.simultaneous.connect.attempts=Nr. maxim de tentative simultane de conectare \u00eenspre exterior ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Nr. maxim de conexiuni noi \u00eenspre exterior pe care Vuze trebuie s\u0103 le \u00eencerce la orice moment.\nNOT\u0102: WindowsXP Service Pack 2 (SP2) impune o limit\u0103 per sistem de 10 tentative simultane de conectare.\nValoarea implicit\u0103 este 8. ConfigView.section.file.perf.cache.size.explain=Ca\u0219ul este folosit pentru a reduce num\u0103rul de citiri \u0219i scrieri pe disc. \u00cen afar\u0103 de cazul \u00een care folosi\u021bi op\u021biunea '-XX:MaxDirectMemorySize' din Java pentru a seta \u00een mod explicit memoria disponibil\u0103 pentru ca\u0219 \u0219i pentru schimbul de informa\u021bii cu re\u021beaua, este bine s\u0103 pune\u021bi o valoare cu cel pu\u021bin %1 mai mic\u0103 dec\u00eet valoarea maxim\u0103 a memoriei virtuale. Valoarea curent\u0103 maxim\u0103 a memoriei virtuale este %2. Pentru instruc\u021biuni de schimbare, consulta\u021bi folosirea memoriei \u00een wikiul %3. Set\u0103ri necorespunz\u0103toarei pot duce la apari\u021bia de erori cauzate de deficitul de memorie. Un ca\u0219 mai mare de 32 MB este \u00een mod sigur exagerat. MyTorrentsView.menu.setSpeed.unlimit=Nelimitat\u0103 MyTorrentsView.menu.setSpeed.unlimited=Nelimitat\u0103 MyTorrentsView.menu.setSpeed.disable=Dezactiveaz\u0103 \u00cenc\u0103rcarea MyTorrentsView.menu.setSpeed.disabled=Dezactivat\u0103 MyTorrentsView.menu.setSpeed.in=\u00een MyTorrentsView.menu.setSpeed.slots=sloturi pentru GeneralView.label.maxuploadspeed=Viteza Maxim\u0103 de \u00cenc\u0103rcare GeneralView.label.maxuploadspeed.tooltip=viteza maxim\u0103 de \u00eenc\u0103rcare [0: nelimitat\u0103] MyTorrents.items.UpSpeedLimit.disabled=Nici o \u00eenc\u0103rcare MyTorrents.items.UpSpeedLimit.unlimited=Nelimitat\u0103 TableColumn.header.maxupspeed=Vit. Max. \u00cenc\u0103rcare TableColumn.header.maxupspeed.info=Viteza Maxim\u0103 de \u00cenc\u0103rcare per Torent ConfigView.section.file.perf.cache.enable.write=Ca\u0219eaz\u0103 datele desc\u0103rcate pentru a reduce num\u0103rul de scrieri pe disc \u0219i totodat\u0103 num\u0103rul de citiri pentru verificarea p\u0103r\u021bilor ConfigView.section.file.perf.cache.enable.read=Efectueaz\u0103 citiri \u00een avans pt. a reduce citirile de pe disc la \u00eenc\u0103rcare ConfigView.section.tracker.separatepeerids=Folose\u0219te identit\u0103\u021bi diferite pentru tracker \u0219i comunicarea de date ConfigView.section.tracker.separatepeerids.info=\u00cembun\u0103t\u0103\u021be\u0219te anonimatul \u00een cazul desc\u0103rc\u0103rii/don\u0103rii anonime,\n\u00een cazul folosirii unei conexiuni neanonime cu trackerul. ConfigView.section.interface.wavlocation=Adresa fi\u0219ierului .wav ConfigView.section.interface.wavlocation.info=Alege\u021bi un fi\u0219ier .wav sau l\u0103sa\u021bi gol pentru sunetul implicit ConfigView.section.tracker.client.connecttimeout=Expirarea conexiunii (sec) ConfigView.section.tracker.client.readtimeout=Expirarea citirii (sec) MainWindow.menu.tools=&Unelte FilesView.path=Cale FilesView.fullpath=Arat\u0103 Calea Complet\u0103 FilesView.remaining=P\u0103r\u021bi R\u0103mase TableColumn.header.trackername=Numele Trackerului TableColumn.header.trackername.info=Numele trackerului bazat pe adresa de anun\u021bare ConfigView.group.override=Ignor\u0103 Op\u021biunile ConfigView.section.file.perf.cache.notsmallerthan=Nu ca\u0219a fi\u0219iere mai mici de (%1) PeersView.menu.blockupload=Blocheaz\u0103 \u00cenc\u0103rcarea PeersView.menu.kickandban=Blocheaz\u0103 \u0219i Alung\u0103 PeersView.menu.kickandban.reason=Partener alungat manual PeersView.state=Stare PeersView.state.info=Starea conexiunii cu partenerul PeersView.state.pending=\u00cen a\u0219teptare PeersView.state.connecting=Conectez PeersView.state.handshake=A\u0219tept str\u00eengerea de m\u00een\u0103 PeersView.state.established=Complet stabilit\u0103 ConfigView.section.tracker.processinglimits=Limitele proces\u0103rii ConfigView.section.tracker.maxgettime=Timp maxim pentru procesare GET (sec) [0: nelimitat] ConfigView.section.tracker.maxgettime.info=Folosit pt. anun\u021buri \u0219i r\u0103zuiri [scrapes] ConfigView.section.tracker.maxposttimemultiplier=Multiplicator de timp GET pentru POST procesare [0: nelimitat] ConfigView.section.tracker.maxposttimemultiplier.info=Folosit pentru pred\u0103ri de formulare \u0219i \u00eenc\u0103rc\u0103ri ConfigView.section.tracker.maxthreads=Maxim de cereri concurente DownloadManager.error.operationcancancelled=Opera\u021biune anulat\u0103 Torrent.create.progress.cancelled=Opera\u021biune anulat\u0103 sharing.progress.cancel=Anuleaz\u0103 wizard.maketorrents.autoopen=Deschide torentul pentru donare c\u00eend e terminat ConfigView.section.sharing.rescanenable=Activeaz\u0103 rescanarea periodic\u0103 a partaj\u0103rilor clasice pt. detectarea schimb\u0103rilor ConfigView.section.sharing.rescanperiod=Interval de rescanare (sec) ConfigView.section.connection.advanced=Set\u0103ri Avansate ale Re\u021belei ConfigView.section.connection.advanced.mtu=Unitatea Maxim\u0103 de Transmisie (MTU) a Conexiunii ConfigView.section.connection.advanced.mtu.tooltip=M\u0103rimea maxim\u0103 a unui pachet transferabil \u00eentr-o singur\u0103 secven\u021b\u0103 prin re\u021bea.\nVuze folose\u0219te MTU-40 (MSS) pentru optimizarea \u00eenc\u0103rc\u0103rii pachetelor de date.\nValori recomandate:\n 576 - Conexiuni dial-up\n1492 - Conexiuni \u00een band\u0103 larg\u0103 PPPoE\n1500 - Conexiuni prin Ethernet, DSL sau Cablu ConfigView.section.connection.advanced.SO_RCVBUF=M\u0103rimea Socketului SO_RCVBUF [0: valoarea implicit\u0103 a SO] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Seteaz\u0103 valoarea standard a socketului SO_RCVBUF (\u00een bai\u021bi), de ex. dimensiunea \u0219i scala intervalului de primire folosit de protocolul TCP.\nVuze nu modific\u0103 aceste valori ini\u021bial, adic\u0103 s\u00eent preluate valorile folosite de sistemul de operare.\nNot\u0103: \u00cen Linux, valoarea folosit\u0103 este dublat\u0103. ConfigView.section.connection.advanced.SO_SNDBUF=M\u0103rimea Socketului SO_SNDBUF [0: valoarea implicit\u0103 a SO] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Seteaz\u0103 valoarea standard a socketului SO_SNDBUF (\u00een bai\u021bi), de ex. dimensiunea intervalului de trimitere folosit de protocolul TCP.\nVuze nu modific\u0103 aceste valori ini\u021bial, adic\u0103 s\u00eent preluate valorile folosite de sistemul de operare.\nNot\u0103: \u00cen Linux, valoarea folosit\u0103 este dublat\u0103. ConfigView.section.connection.advanced.IPDiffServ=Valoarea pachetului ie\u0219ind DiffServ (c\u00eemp TOS) ConfigView.section.connection.advanced.IPDiffServ.tooltip=Seteaz\u0103 partea DiffServ a c\u00eempului tip-de-serviciu (TOS) \u00een antetul IP pentru pachetele ie\u0219inde.\nValorile hexazecimale pot fi specificate prin prefixarea lor cu '0x', de ex. 0x10.\nVuze las\u0103 aceast\u0103 valooarei nesetat\u0103 \u00een mod implicit, ceea ce \u00eenseamn\u0103 c\u0103 va fi folosit\u0103 valorea implicit\u0103 a SO.\nNOT\u0102: Implement\u0103rile de re\u021bea din SO pot s\u0103 ignore aceast\u0103 valoare, deci aceast\u0103 op\u021biune este foarte dependent\u0103 de versiunile de SO \u0219i JRE. ConfigView.section.interface.confirm_torrent_removal=Arat\u0103 un dialog de confirmare la \u00eenl\u0103turarea torentelor ConfigView.section.interface.confirm_torrent_removal.tooltip=Confirmare la \u00eenl\u0103turarea unui torent din vederea "Torentele mele" MyTorrentsView.confirm_torrent_removal=Sigur dori\u021bi s\u0103 \u00eenl\u0103tura\u021bi?\n TableColumn.header.seed_to_peer_ratio=RaportDonatoriLaParteneri TableColumn.header.seed_to_peer_ratio.info=Raportul total de donatori la parteneri din roi PeersView.connected_time=Timp conectat PeersView.connected_time.info=Timp conectat cu partenerul ConfigView.section.interface.display.add_torrents_silently=Adaug\u0103 torentele \u00een mod silen\u021bios ConfigView.section.interface.display.add_torrents_silently.tooltip=Adaug\u0103 desc\u0103rc\u0103rile de torente f\u0103r\u0103 a activa fereastra principal\u0103 Vuze. TableColumn.header.maxdownspeed=Vit. Max. Desc\u0103rcare TableColumn.header.maxdownspeed.info=Viteza Maxim\u0103 de Desc\u0103rcare per Torent PeersGraphicView.title=Roi ConfigView.section.tracker.passwordwebhttpsonly=Accept\u0103 doar accesul prin HTTPS TableColumn.header.torrentpath=Loca\u021bia Torentului TableColumn.header.torrentpath.info=Locul torentului pe hardisc ConfigView.section.sharing.torrentcomment=Comentariu pentru torentele create ConfigView.label.copyanddeleteratherthanmove=Copiaz\u0103 fi\u0219ierele originale \u0219i abia apoi \u0219terge-le, \u00een loc de a le muta dintr-o singur\u0103 opera\u021bie - poate preveni pierderea datelor \u00een cazul unor sisteme de fi\u0219iere. ConfigView.label.openstatsonstart=Deschide Statisticile la pornire swt.install.window.title=Instalatorul de Extensii swt.install.window.ok=Instaleaz\u0103 swt.install.window.header=Urm\u0103toarele componente au fost selectate pentru a fi instalate : swt.uninstall.window.title=Dezinstalatorul de Extensii swt.uninstall.window.ok=\u0218terge swt.uninstall.window.header=Urm\u0103toarele componente au fost selectate pentru a fi \u00eenl\u0103turate : installPluginsWizard.title=Instaleaz\u0103 Extensiile installPluginsWizard.mode.title=Alege\u021bi o metod\u0103 de instalare installPluginsWizard.mode.list=Din lista de la sourceforge.net installPluginsWizard.list.title=Lista cu Extensii Instalabile installPluginsWizard.list.loading=A\u0219tepta\u021bi p\u00een\u0103 la afi\u0219area listei de extensii. installPluginsWizard.list.loaded=Alege\u021bi extensiile pe care dori\u021bi s\u0103 le instala\u021bi. installPluginsWizard.list.name=Nume installPluginsWizard.list.version=Versiune installPluginsWizard.list.description=Descrierea extensiei installPluginsWizard.finish.title=Instalare \u00een Curs installPluginsWizard.finish.explanation=Extensiile selectate vor fi instalate folosind asistentul de actualizare.\n\nAve\u021bi r\u0103bdare, este posibil sa dureze un timp p\u00een\u0103 la afi\u0219are.\n\nPentru afi\u0219area unui raport despre progres, dublu clic pe partea st\u00eeng\u0103 a barei de stare. installPluginsWizard.details.loading=\u00cencarc detaliile, a\u0219tepta\u021bi v\u0103 rog... installPluginsWizard.mode.file=Din fi\u0219ier installPluginsWizard.installMode.title=Alege\u021bi tipul de instalare installPluginsWizard.installMode.user=Instaleaz\u0103 extensiile doar pentru utilizatorul curent installPluginsWizard.installMode.shared=Instaleaz\u0103 extensiile pentru to\u021bi utilizatorii installPluginsWizard.file.title=C\u0103uta\u021bi extensia pe care dori\u021bi s\u0103 o instala\u021bi installPluginsWizard.file.file=Fi\u0219ier : installPluginsWizard.file.invalidfile=Fi\u0219ierul nu e o extensie valid\u0103 pentru Vuze. installPluginsWizard.file.no_such_file=Nu exist\u0103 nici un fi\u0219ier cu numele dat. installPluginsWizard.file.browse=Exploreaz\u0103... uninstallPluginsWizard.title=Dezinstaleaz\u0103 Extensii uninstallPluginsWizard.list.title=Lista de Extensii Instalate uninstallPluginsWizard.list.loaded=Alege\u021bi extensiile pe care dori\u021bi s\u0103 le dezinstala\u021bi. installPluginsWizard.list.nullversion=Nici o versiune uninstallPluginsWizard.finish.title=Dezinstalare \u00een Curs uninstallPluginsWizard.finish.explanation=Extensiile selectate vor fi dezinstalate folosind asistentul de actualizare. MainWindow.menu.plugins.installPlugins=Vr\u0103jitor de Instalare... MainWindow.menu.plugins.uninstallPlugins=Vr\u0103jitor de Dezinstalare... ConfigView.section.ipfilter.totalIPs=%1 IP-uri blocate in total, adic\u0103 %2 din tot internetul. update.instance.install=Verific Instalarea update.instance.uninstall=Verific Dezinstalarea update.instance.update=Caut Actualiz\u0103ri MainWindow.status.update.tooltip=Dublu clic pentru informatii despre progres updater.progress.window.title=Sarcini curente updater.progress.window.info=Ap\u0103sa\u021bi "\u00centrerupe" pentru a opri sarcinile aflate \u00een curs Button.abort=\u00centrerupe ConfigView.section.ipfilter.enablebanning=Blocheaz\u0103 partenerii care trimit \u00een mod repetat date nefolositoare Network.alert.acceptfail=Prea multe e\u0219ecuri succesive ap\u0103rute pe portul %1, %2 - am abandonat procesarea. Verifica\u021bi specifica\u021biile paravanului [firewall] pentru acest port, ca s\u0103 v\u0103 asigura\u021bi c\u0103 este autorizat pentru conexiunile intr\u00eende. MyShares.column.category=Categorie UpdateWindow.restartLater=Reporne\u0219te Vuze Mai T\u00eerziu MainWindow.menu.file.restart=Reporne\u0219te Vuze MainWindow.dialog.restartconfirmation.title=Repornesc Vuze? MainWindow.dialog.restartconfirmation.text=Sigur dori\u021bi sa reporni\u021bi Vuze? deletetorrent.message1=S\u00eente\u021bi pe punctul de a \u0219terge TORENTUL lui :\n deletetorrent.message2=\nSigur dori\u021bi s\u0103 continua\u021bi? ConfigView.label.prioritizemostcompletedfiles=Prioritizeaz\u0103 suplimentar fi\u0219ierele cu prioritate \u00cenalt\u0103 \u00een func\u021bie de procentul de realizare \u0219i de m\u0103rimea fi\u0219ierului splash.plugin.init=Ini\u021bializez Extensia: splash.plugin.UIinit=Ini\u021bializez Extensia GUI: %1 ConfigView.section.style.osx_small_fonts=Folose\u0219te corpuri de liter\u0103 mici (necesit\u0103 repornire) ConfigView.section.tracker.tcpnonblocking=Folose\u0219te intr\u0103ri/ie\u0219iri f\u0103r\u0103 blocare pentru procesarea de trackere TCP. Selectarea op\u021biunii necesit\u0103 ca re\u021beaua de trackere s\u0103 fie accesat\u0103 pe un port alternativ. Experimental! ConfigView.section.tracker.nonblocking=Op\u021biuni de deblocare ConfigView.section.tracker.nonblockingconcmax=Max. de conexiuni simultane [0: nelimitat] MyTorrentsView.menu.exportmenu=Export\u0103 MyTorrentsView.menu.exporttorrent=Torent... ConfigView.group.scrape=R\u0103zuie\u0219te ConfigView.section.tracker.client.scrapeinfo=Dezactivarea r\u0103zuirii \u00eempiedic\u0103 func\u021bionarea regulilor de punere a torentelor \u00een coad\u0103, pentru c\u0103 ele se bazeaz\u0103 pe informa\u021bii din roi ob\u021binute de trackerele de r\u0103zuire. ConfigView.section.tracker.client.scrapeenable=Activeaz\u0103 r\u0103zuirea [scraping] ConfigView.section.tracker.client.scrapestoppedenable=R\u0103zuie\u0219te torentele care nu s\u00eent active Scrape.status.disabled=R\u0103zuire Dezactivat\u0103 [scrape] MyTorrentsView.menu.explore=Arat\u0103 Fi\u0219ierul MyTorrentsView.menu.explore._mac=Arat\u0103 \u00een G\u0103sitor MyTorrentsView.menu.explore._windows=Arat\u0103 \u00een Explorator wizard.maketorrents.autohost=G\u0103zduie\u0219te torentul \u00een trackerul \u00eencorporat ConfigView.label.overrideip=Ignor\u0103 anun\u021b\u0103rile de adres\u0103 IP ale trackerului - separa\u021bi cu punct-\u0219i-virgul\u0103 dac\u0103 s\u00eent mai multe adrese (pt. re\u021bele diferite). ConfigView.label.overrideip.tooltip=Informeaz\u0103 trackerul despre adresele IP diferite de cea de la care vin pachetele dinspre exterior. L\u0103sa\u021bi spa\u021biul gol dac\u0103 op\u021biunea nu e folosit\u0103. ConfigView.section.connection.group.networks=Re\u021bele ConfigView.section.connection.group.networks.info=Selecta\u021bi re\u021belele permise implicit pt. transmisia de date partener-la-partener ConfigView.section.connection.networks.prompt=Aten\u021bioneaz\u0103-m\u0103 s\u0103 selectez atunci c\u00eend e ad\u0103ugat\u0103 o desc\u0103rcare cu tracker anonim ConfigView.section.connection.networks.Public=Re\u021bea IP public\u0103 (nu anonim\u0103) ConfigView.section.connection.networks.I2P=Re\u021bea I2P ConfigView.section.connection.networks.Tor=Re\u021beaua "The Onion Router" (Tor) TableColumn.header.networks=Re\u021bele TableColumn.header.networks.info=Re\u021bele permise pentru transferul de date partener-la-partener Scrape.status.networkdisabled=Re\u021beaua nu e activat\u0103 ConfigView.section.tracker.server.group.networks=Re\u021bele ConfigView.section.tracker.server.group.networks.info=Alege\u021bi re\u021belele din care trackerul va accepta parteneri window.networkselection.title=Selectarea Re\u021belei window.networkselection.info=Torentul de mai jos are un tracker care accept\u0103 re\u021belele urm\u0103toare.\nAlege\u021bi-le pe cele pe care dori\u021bi s\u0103 le activa\u021bi pentru comunic\u0103ri cu trackerul \u0219i cu partenerii.\nDac\u0103 e un tracker anonim care accept\u0103 clien\u021bi publici, activa\u021bi at\u00eet re\u021beaua anonim\u0103 c\u00eet \u0219i pe cea public\u0103.\nActivarea re\u021belei publice are drept consecin\u021b\u0103 pierderea anonimatului! window.networkselection.description=Torent : plugins.basicview.clear=Cur\u0103\u021b\u0103 ConfigView.section.connection.group.peersources=Donatorii Partenerilor ConfigView.section.connection.group.peersources.info=Selecta\u021bi sursele implicite permise pentru conect\u0103rile cu partenerii ConfigView.section.connection.peersource.Tracker=De la un tracker ConfigView.section.connection.peersource.DHT=Tracking descentralizat ConfigView.section.connection.peersource.PeerExchange=Oferit de un alt partener ConfigView.section.connection.peersource.Plugin=Ad\u0103ugat de o extensie ConfigView.section.connection.peersource.Incoming=Conexiune intr\u00eend\u0103 PeersView.source=Sursa PeersView.source.info=Sursa acestui partener TableColumn.header.peersources=Surse Partenere TableColumn.header.peersources.info=Surse partenere permise pentru stabilirea conexiunilor cu partenerii wizard.tracker.dht=Descentralizat (numai pentru clien\u021bi Vuze) MyTorrentsView.menu.advancedmenu=Avansate MyTorrentsView.menu.networks=Re\u021bele MyTorrentsView.menu.peersource=Donatorii Partenerilor ConfigView.section.sharing.permitdht=Permite urm\u0103rirea [tracking] descentralizat\u0103 c\u00eend trackerul e indisponibil ConfigView.section.sharing.protocol=Protocol pentru resurse partajate \u00een mod clasic PeersView.Messaging=Mesagerie PeersView.Messaging.info=Indic\u0103 ce sistem de mesagerie este \u00een uz. ConfigView.label.queue.newseedsmovetop=Mut\u0103 torentele recent terminate \u00een v\u00eerful listei de don\u0103ri ConfigView.label.seeding.firstPriority.ignore.info=Tine\u021bi seama c\u0103 folosirea acestor reguli poate duce la\n oprirea torentului imediat ce se termin\u0103 desc\u0103rcarea. ConfigView.label.seeding.firstPriority.ignore=Ignor\u0103 regulile de Prim\u0103 Prioritate pentru: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torente cu un raport Donatori/Parteneri peste ConfigView.label.seeding.firstPriority.ignore0Peer=Torente cu 0 parteneri ConfigView.section.tracker.sendjavaversionandos=Trimite versiunea de JAVA \u0219i numele SO MagnetPlugin.contextmenu.exporturi=Copiaz\u0103 Leg\u0103tura Magnet \u00een Cliplan\u0219et\u0103 ConfigView.section.plugins.dht=BD Distribuit\u0103 dht.info=Aceast\u0103 extensie permite urm\u0103rirea [tracking] descentralizat\u0103, printre altele. Dac\u0103 o dezactiva\u021bi, va scade capacitatea de desc\u0103rcare. dht.enabled=Activeaz\u0103 baza de date distribuit\u0103 dht.portdefault=Folose\u0219te portul implicit dht.port=Port UDP pentru baza de date dht.execute.command=Comand\u0103 de diagnosticare dht.execute.info=Ap\u0103sa\u021bi pentru a executa comanda dht.execute=Ruleaz\u0103 dht.logging=Activeaz\u0103 \u00eenregistrarea activit\u0103\u021bii ConfigView.section.plugins.dhttracker=Tracker Distribuit dhttracker.tracknormalwhenoffline=Urm\u0103re\u0219te [track] numai torentele normale atunci c\u00eend trackerul lor este indisponibil. ConfigView.section.file.nativedelete._mac=Folose\u0219te Reciclatorul pentru \u0219tergerea fi\u0219ierelor ConfigView.section.file.nativedelete._windows=Mut\u0103 fi\u0219ierele \u0219terse \u00een Reciclator ConfigView.section.logging.generatediagnostics=Genereaz\u0103 ConfigView.section.logging.netinfo=Genereaz\u0103 informa\u021bii despre re\u021bea ConfigView.section.logging.statsinfo=Genereaz\u0103 informa\u021bii statistice ConfigView.section.logging.generatediagnostics.info=Genereaz\u0103 informa\u021bii de diagnosticare \u0219i copiaz\u0103-le \u00een cliplan\u0219et\u0103 \u0219i fi\u0219ierul jurnalului, dac\u0103 e configurat. ConfigView.section.sharing.privatetorrent=Torent privat - accept\u0103 parteneri numai prin tracker MainWindow.menu.tools.nattest=Test pentru &NAT / Paravan Button.apply=Aplic\u0103 Button.close=\u00cenchide window.welcome.title=Bine a\u021bi venit la Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Note de Lansare dht.reseed.label=\u00cen mod normal nu e nevoie de repopularea bazei de date distribuite. Cu toate acestea, \u00een cazul \u00een care num\u0103rul de contacte e mic, aceasta poate fi folosit\u0103 pentru reintegrare.\nL\u0103sa\u021bi gol pentru a repopula cu date de la partenerii conecta\u021bi sau scrie\u021bi IP-ul \u0219i portul pentru a fi folosite la repopularea cu date de la un partener cunoscut. dht.reseed.group=Redoneaz\u0103 dht.reseed.ip=Adresa IP dht.reseed=Redoneaz\u0103 dht.reseed.info=Redoneaz\u0103 baza de date dht.diagnostics.group=Diagnostice DHTView.title.full=Baz\u0103 de Date Distribuit\u0103 DHTView.title.fullcvs=Baz\u0103 de Date Distribuit\u0103 CVS DHTView.general.title=Generale DHTView.general.uptime=Timp donare: DHTView.general.users=Utilizatori: DHTView.general.nodes=Noduri: DHTView.general.leaves=P\u0103r\u0103siri: DHTView.general.contacts=Contacte: DHTView.general.replacements=\u00cenlocuiri: DHTView.general.live=Active DHTView.general.unknown=Necunoscute: DHTView.general.dying=Muribunde: DHTView.transport.title=Detaliile Transportului DHTView.transport.packets=Pachete DHTView.transport.bytes=Bai\u021bi DHTView.transport.received=Primite DHTView.transport.sent=Trimise DHTView.transport.in=Intra\u021bi : DHTView.transport.out=Ie\u0219i\u021bi: DHTView.operations.title=Detaliile Opera\u021biunii DHTView.operations.sent=Trimis DHTView.operations.ok=OK DHTView.operations.failed=E\u0219uate DHTView.operations.received=Primit DHTView.operations.ping=Pinguie\u0219te DHTView.operations.findNode=G\u0103se\u0219te Nodul DHTView.operations.findValue=G\u0103se\u0219te Valoarea DHTView.operations.store=Stocheaz\u0103 DHTView.activity.title=Activitate DHTView.activity.status=Stare DHTView.activity.status.true=Puse \u00een Coad\u0103 DHTView.activity.status.false=Ruleaz\u0103 DHTView.activity.type=Tip DHTView.activity.type.1=Ia din interior DHTView.activity.type.2=Ia din exterior DHTView.activity.type.3=Pune \u00een interior DHTView.activity.type.4=Pune \u00een exterior DHTView.activity.target=\u021aint\u0103 DHTView.activity.details=Detalii DHTView.db.title=Baz\u0103 de Date DHTView.db.keys=Chei DHTView.db.values=Valori DHTView.db.divfreq=Frecv. Div. DHTView.db.divsize=M\u0103rime Div. MainWindow.dht.status.tooltip=Aici apare estimarea num\u0103rului curent de utilizatori conecta\u021bi atunci c\u00eend baza de date distribuit\u0103 este \u00een func\u021biune. MainWindow.dht.status.disabled=DHT Dezactivat MainWindow.dht.status.failed=DHT E\u0219uat MainWindow.dht.status.initializing=Ini\u021bializez DHT MainWindow.dht.status.users=%1 utilizatori MainWindow.dht.status.unreachable=DHT Paravanat MainWindow.dht.status.unreachabletooltip=Se pare c\u0103 exist\u0103 o problem\u0103 cu maparea porturilor UDP ale bazei de date distribuite (NAT/paravan) MyTorrentsView.menu.setUpSpeed=Seteaz\u0103 Viteza de \u00cenc\u0103rcare MyTorrentsView.menu.setDownSpeed=Seteaz\u0103 Viteza de Desc\u0103rcare ConfigView.section.tracker.client.showwarnings=Arat\u0103 mesajele de avertizare emise de trackere dht.advanced=Activeaz\u0103 set\u0103rile avansate dht.advanced.group=Set\u0103ri Avansate dht.advanced.label=Modifica\u021bi aceste valori numai dac\u0103 \u0219ti\u021bi cu adev\u0103rat ce face\u021bi dht.override.ip=Ignor\u0103 adresa IP extern\u0103 ConfigView.section.logging.loggerenable=Activeaz\u0103 jurnalizarea ConfigView.section.ipfilter.blockbanning=Blocheaz\u0103 un interval de 256 de adrese atunci c\u00eend cel pu\u021bin at\u00eetea din interval au fost blocate. MyTrackerView.passive=Pasiv TableColumn.header.swarm_average_speed=Viteza Medie a Roiului TableColumn.header.swarm_average_speed.info=Viteza medie a partenerilor din roi TableColumn.header.comment=Comentariu TableColumn.header.comment.info=Comentariul utilizatorului despre desc\u0103rcare TableColumn.header.commenticon=Comentariu TableColumn.header.commenticon.info=Iconi\u021ba e afi\u0219at\u0103 c\u00eend desc\u0103rcarea are un comentariu pus de utilizator MyTrackerView.category=Categorie MainWindow.menu.file.open.torrentfortracking=Fi\u0219ier Torent... (Doar Tracking) MyTrackerView.date_added=Ad\u0103ugat ConfigView.section.tracker.portbackup=Porturi de rezerv\u0103 (separate cu ';') ConfigView.label.playfilespeech=Vorbe\u0219te c\u00eend se termin\u0103 un fi\u0219ier ConfigView.label.playfilespeech.info=Serviciile de Vorbire merg momentan mai bine \u00een Englez\u0103 ConfigView.label.playfilefinished=Emite un sunet c\u00eend un fi\u0219ier este terminat ConfigView.label.backupconfigfiles=Salvgardeaz\u0103 [backup] fi\u0219ierele de configurare pentru a le folosi la restaur\u0103ri. ConfigView.section.tracker.client.scrapesingleonly=Dezactiveaz\u0103 agregarea r\u0103zuirilor pe fiecare tracker (poate ajuta cu trackerele care \u00eentorc eroarea 'URL too long' (414)) dht.ipfilter.log=Logheaz\u0103 viol\u0103rile Filtrului IP ConfigView.label.seeding.addForSeedingDLCopyCount=Consider\u0103 c\u0103 desc\u0103rc\u0103rile "ad\u0103ugate pentru donare" au fost deja desc\u0103rcate de acest num\u0103r de ori ActivityView.legend.limit=Viteza Limit\u0103 ActivityView.legend.achieved=Viteza Ob\u021binut\u0103 ActivityView.legend.overhead=Dep\u0103\u0219ire a Vitezei ActivityView.legend.peeraverage=Medie ActivityView.legend.swarmaverage=Media pe roi ActivityView.legend.trimmed=Tuns (punctat) MyTorrentsView.menu.movemenu=Mut\u0103 Fi\u0219ierele MyTorrentsView.menu.movedata=Mut\u0103 Fi\u0219ierele cu Date... MyTorrentsView.menu.movetorrent=Mut\u0103 Fi\u0219ierul Torent... MyTorrentsView.menu.movedata.dialog=Alege\u021bi un loc nou DHTView.operations.data=Date DHTView.general.reachable=Conectabile: DHTView.general.rendezvous=\u00cent\u00eelniri: ConfigView.label.queue.maxactivetorrentswhenseeding=Nr. max de torente atunci c\u00eend doar se doneaz\u0103 [0:nelimitat] Views.plugins.IRC.title=Ajutor prin IRC Formats.units.alot=Multe !!! ConfigView.section.ipfilter.persistblocking=Salveaz\u0103 adresele IP blocate \u00eentre sesiuni FilesView.menu.rename=Redenume\u0219te sau Re\u021binte\u0219te FilesView.menu.rename_only=Redenume\u0219te FilesView.menu.retarget=Re\u021binte\u0219te FilesView.rename.choose.path=Alege un fi\u0219ier nou sau unul existent FilesView.rename.choose.path.dir=Alege\u021bi un dosar nou sau pe cel existent FilesView.rename.confirm.delete.title=Confirm\u0103 \u0218tergerea FilesView.rename.confirm.delete.text=Confirm\u0103 \u0219tergerea fi\u0219ierului original '%1' FilesView.rename.filename.title=Redenume\u0219te Fi\u0219ierul FilesView.rename.filename.text=Alege\u021bi un nou nume pentru fi\u0219ier ConfigView.higher.mode.available=Mai multe op\u021biuni s\u00eent prezente \u00een modurile avansate ConfigView.section.mode=Afi\u0219area Op\u021biunilor ConfigView.section.mode.title=Utilizator ConfigView.section.mode.beginner=\u00cencep\u0103tor ConfigView.section.mode.beginner.wiki.definitions=Vocabular BitTorrent ConfigView.section.mode.intermediate=Intermediar ConfigView.section.mode.intermediate.wiki.host=G\u0103zduirea Fi\u0219ierelor ConfigView.section.mode.intermediate.wiki.publish=Publicarea Fi\u0219ierelor ConfigView.section.mode.advanced=Avansat ConfigView.section.mode.advanced.wiki.main=Pagina Principal\u0103 Wiki ConfigView.section.mode.beginner.text=Tot ce v\u0103 trebuie pentru a desc\u0103rca torente.\nFolosi\u021bi acest mod dac\u0103 dori\u021bi doar s\u0103 administra\u021bi torentele. ConfigView.section.mode.intermediate.text=Acces la func\u021biile trackerului.\nFolosi\u021bi acest nivel dac\u0103 dori\u021bi s\u0103 v\u0103 crea\u021bi propriul tracker \u0219i s\u0103 g\u0103zdui\u021bi/publica\u021bi propriile fi\u0219iere. ConfigView.section.mode.advanced.text=Set\u0103rile Re\u021belei.\nFolosi\u021bi acest nivel dac\u0103 \u0219ti\u021bi ce \u00eenseamn\u0103 MTU sau intr\u0103rile/ie\u0219irile neblocate... Files.column.storagetype=Tip de Stocare Files.column.fileext=Tip FileItem.storage.linear=Liniar FileItem.storage.compact=Compacteaz\u0103 MessageBoxWindow.rememberdecision=Memoreaz\u0103 decizia mea ConfigView.section.interface.cleardecisions=Cur\u0103\u021b\u0103 deciziile memorate din dialoguri ConfigView.section.interface.cleardecisionsbutton=Cur\u0103\u021b\u0103 ConfigView.section.interface.cleartrackers=Cur\u0103\u021b\u0103 trackerele memorate ConfigView.section.interface.cleartrackersbutton=Cur\u0103\u021b\u0103 ConfigView.section.interface.clearsavepaths=Cur\u0103\u021b\u0103 c\u0103ile de salvare memorate ConfigView.section.interface.clearsavepathsbutton=Cur\u0103\u021b\u0103 configureWizard.welcome.usermodes=Aceast\u0103 setare a Priceperii Utilizatorului va determina nivelul op\u021biunilor afi\u0219ate \u00een Unelte>Op\u021biuni. E \u00een interesul dv. s\u0103 alege\u021bi setarea potrivit\u0103. FilesView.skip.confirm.delete.text=Trunchiez fi\u0219ierul '%1' pentru a economisi spa\u021biu? FilesView.rename.failed.title=Redenumire/Redirec\u021bionare e\u0219uat\u0103 FilesView.rename.failed.text=Opera\u021biunea a e\u0219uat, probabil din cauza select\u0103rii incorecte a \u021bintei diagnostics.log_found=Vuze nu s-a \u00eenchis cum trebuie. Verifica\u021bi jurnalul de diagnosticare. De asemenea citi\u021bi articolul din wiki Vuze Dispare pt. informa\u021bii suplimentare. ManagerItem.paused=Pauzat Utils.link.visit=V\u0103 rug\u0103m s\u0103 vizita\u021bi ConfigView.section.connection.serverport.wiki=Op\u021biuni bune pt. porturi ConfigView.section.transfer.speeds.wiki=Set\u0103ri bune ale vitezei installPluginsWizard.installMode.info.title=Informa\u021bii installPluginsWizard.installMode.info.text=Nu ave\u021bi nevoie de extensii pentru a folosi Vuze, extensiile s\u00eent bune pentru facilit\u0103\u021bi suplimentare, automatizare sau control de la distan\u021b\u0103.\nA\u0219adar v\u0103 rug\u0103m s\u0103 citi\u021bi cu aten\u021bie descrierea fiec\u0103reia dintre extensii \u00eenainte de a hot\u0103r\u00ee dac\u0103 o instala\u021bi.\nMajoritatea extensiilor pot fi testate f\u0103r\u0103 probleme, dar nu supra\u00eenc\u0103rca\u021bi configura\u021bia programului cu unele pe care nu le ve\u021bi folosi. Views.plugins.Distributed.DB.title=Baz\u0103 de Date Distribuit\u0103 Views.plugins.Distributed.Tracker.title=Tracker Distribuit Views.plugins.Plugin.Update.title=Actualizarea Extensiilor openUrl.url.info=Suport\u0103 \u0219iruri http, https, magnet \u0219i infoha\u0219uri hexazecimale brute TableColumn.header.swarm_average_completion=Realizarea Medie a Partenerilor TableColumn.header.swarm_average_completion.info=Procentul mediu de realizare (terminare) al partenerilor din roi GeneralView.label.swarm_average_completion=Progres Mediu: GeneralView.label.swarm_average_completion.tooltip=Procentajul mediu de realizare a desc\u0103rc\u0103rii la partenerii din roi. MainWindow.nat.status.tooltip.unknown=Starea accesibilit\u0103\u021bii paravanului/NAT este necunoscut\u0103 (TCP) MainWindow.nat.status.tooltip.ok=Accesibilitate OK (TCP) MainWindow.nat.status.tooltip.probok=Accesibilitatea este \u00een regul\u0103, totu\u0219i nu exist\u0103 conexiuni TCP intr\u00eende MainWindow.nat.status.bad=Paravanat MainWindow.nat.status.tooltip.bad=Problem\u0103 la accesibilitatea prin paravan/NAT (TCP). Consulta\u021bi Wikiul pentru ajutor. plugin.installer.recommended.plugin=Extensie recomandat\u0103 - verifica\u021bi \u0219i instala\u021bi dac\u0103 e nevoie LoggerView.pause=Pauzeaz\u0103 Jurnalizarea LoggerView.clear=&Cur\u0103\u021b\u0103 LoggerView.filter=Filtru LoggerView.filter.uncheckAll=Debifeaz\u0103 Toate Categoriile LoggerView.filter.checkAll=Bifeaz\u0103 Toate Categoriile LoggerView.loggingDisabled=Jurnalizarea [logging] nu e activat\u0103. LoggerView.includeOnly=Afi\u0219eaz\u0103 doar liniile care se potrivesc cu aceast\u0103 expresie regulat\u0103: LoggerView.excludeAll=Nu afi\u0219a liniile care se potrivesc cu aceast\u0103 expresie regulat\u0103: ConfigView.section.logging.log0type=Informa\u021bii ConfigView.section.logging.log1type=Avertisment ConfigView.section.logging.log2type=Eroare ConfigView.section.logging.filter=Filtreaz\u0103 la jurnalizarea \u00een fi\u0219ier ConfigView.section.logging.level=Nivelul Jurnaliz\u0103rii ConfigView.section.logging.showLogsFor=Arat\u0103 %1 jurnale pentru categoriile: ConfigView.pluginlist.column.loadAtStartup=Porne\u0219te odat\u0103 cu SO ConfigView.pluginlist.column.type=Tip ConfigView.pluginlist.column.type.perUser=Per Utilizator ConfigView.pluginlist.column.type.shared=Partajat ConfigView.pluginlist.column.type.builtIn=\u00cencorporat ConfigView.pluginlist.column.name=Nume ConfigView.pluginlist.column.version=Versiune ConfigView.pluginlist.column.directory=Dosar ConfigView.pluginlist.column.isOperational=Opera\u021bional? PeersView.BlockView.Avail.Have=Ambii ave\u021bi PeersView.BlockView.Avail.NoHave=Partenerul are, Dv. nu PeersView.BlockView.NoAvail.Have=Dv. ave\u021bi, Partenerul nu PeersView.BlockView.NoAvail.NoHave=Nici unul n-are PeersView.BlockView.Transfer=Transfer PeersView.BlockView.NextRequest=Urm\u0103toarea Solicitare PeersView.BlockView.title=Harta P\u0103r\u021bilor PeersView.BlockView.AvailCount=Num\u0103rul Disponibilit\u0103\u021bilor MyTorrentsView.dialog.NumberError.title=Num\u0103r Invalid sau Nerecunoscut MyTorrentsView.dialog.NumberError.text=Num\u0103rul pe care l-a\u021bi introdus e invalid sau nerecunoscut. MyTorrentsView.menu.manual=&Manual\u0103... MyTorrentsView.menu.manual.per_torrent=Manual\u0103 (per torent) MyTorrentsView.menu.manual.shared_torrents=Manual\u0103 (pt. toate torentele) MyTorrentsView.dialog.setSpeed.title=Seteaz\u0103 viteza %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Introduce\u021bi un num\u0103r %1 pentru a schimba %2 \u00een: MyTorrentsView.dialog.setNumber.upload=\u00eenc\u0103rcare MyTorrentsView.dialog.setNumber.download=desc\u0103rcare MyTorrentsView.dialog.setNumber.inKbps=\u00een %1 OpenTorrentWindow.torrentLocation=Torente de desc\u0103rcat: OpenTorrentWindow.addFiles.URL=Adaug\u0103 &Adres\u0103 OpenTorrentWindow.addFiles.Folder=Adaug\u0103 &Dosar OpenTorrentWindow.addFiles.Clipboard=Adaug\u0103 din Clip&lan\u0219et\u0103 OpenTorrentWindow.changeDestination=Schimb\u0103 Destina\u021bia OpenTorrentWindow.fileList=Fi\u0219iere \u00een torente: OpenTorrentWindow.torrentTable.name=Nume OpenTorrentWindow.torrentTable.saveLocation=Loc de Salvare OpenTorrentWindow.fileTable.fileName=Numele Fi\u0219ierului OpenTorrentWindow.fileTable.size=M\u0103rime OpenTorrentWindow.fileTable.destinationName=Nume la Destina\u021bie OpenTorrentWindow.startMode.seeding=Donare OpenTorrentWindow.fileList.changeDestination=Schimb\u0103 Destina\u021bia OpenTorrentWindow.mb.badSize.title=Fi\u0219ier Incompatibil OpenTorrentWindow.mb.badSize.text='%1' nu e '%2' si nu e folosibil pentru sadit. OpenTorrentWindow.mb.alreadyExists.text=Torentul '%1' a fost deja ad\u0103ugat ca '%2' OpenTorrentWindow.mb.alreadyExists.title=Torentul exist\u0103 deja OpenTorrentWindow.mb.openError.title=Eroare la deschidere OpenTorrentWindow.mb.openError.text='%1' nu a putut fi deschis:\n%2 OpenTorrentWindow.torrent.remove=\u0218terge torentul din list\u0103 OpenTorrentWindow.torrent.options=Set\u0103rile urm\u0103toare se vor aplica la torentele selectate mai sus: OpenTorrentWindow.xOfTotal=(%1 din %2) iconBar.open.tooltip=Deschide Torent LocaleUtil.column.text=Text Necunoscut Tracker.tooltip.MultiSupport=Acest tracker accept\u0103 r\u0103zuiri multiple ale ha\u0219ului per solicitare. Tracker.tooltip.NoMultiSupport=Acest tracker nu accept\u0103 r\u0103zuiri multiple ale ha\u0219ului per solicitare.\nAceasta nu v\u0103 va afecta perfoman\u021ba, dar va suprasolicita trackerul. ConfigView.label.lazybitfield=Folose\u0219te c\u00eempul de bi\u021bi "lene\u0219" (ajut\u0103 la donarea \u00een re\u021belele ce folosesc blocarea bazat\u0103 pe c\u00eempul de bi\u021bi) LoggerView.realtime=Actualizeaz\u0103 \u00een timp real ConfigView.section.file.perf.cache.flushpieces=Scrie imediat pe disc p\u0103r\u021bile terminate. Accesul la disc e u\u0219urat, \u00eens\u0103 poate duce la mai multe opera\u021bii de scriere. ConfigView.section.file.writemblimit=Nr. maxim de solicit\u0103ri de scriere puse \u00een coad\u0103 (\u00een %1) ConfigView.section.file.writemblimit.explain=Atunci c\u00eend viteza de scriere pe disc e mai mic\u0103 dec\u00eet viteza de desc\u0103rcare, acest parametru limiteaz\u0103 cantitatea de date pus\u0103 \u00een coad\u0103 \u00eenainte ca viteza de desc\u0103rcare s\u0103 fie mic\u0219orat\u0103. ConfigView.section.file.readmblimit=Nr. maxim de solicit\u0103ri de citire puse \u00een coad\u0103 (\u00een %1) ConfigView.section.file.readmblimit.explain=Acest parametru limiteaz\u0103 memoria folosibil\u0103 pentru stocarea citirilor ce a\u0219teapt\u0103 procesarea. Button.moveUp=Mut\u0103 \u00een Sus Button.moveDown=Mut\u0103 \u00een Jos ConfigView.notAvailableForMode=Aceast\u0103 sec\u021biune e pentru modul %1 sau peste. Nu e disponibil\u0103 \u00een modul %2. health.explain.error=Exist\u0103 o eroare in acest torent. Verifica\u021bi coloana de Stare sau pontul de pe iconi\u021b\u0103 pentru a o vedea. GeneralView.label.trackerscrapeupdate=R\u0103zuie\u0219te Trackerul PeersView.piece=Parte PeersView.piece.info=Nr. ultimii p\u0103r\u021bi cerut\u0103 de acest partener PiecesView.priority=Prioritate PiecesView.priority.info=Prioritatea de realizare a p\u0103r\u021bii, nu-i acorda\u021bi prea mult\u0103 aten\u021bie PiecesView.speed=Viteza PiecesView.speed.info=Partenerii len\u021bi s\u00eent \u00eempiedica\u021bi s\u0103 interfereze prea mult cu p\u0103r\u021bile rapide TableColumn.header.AvgAvail.info=Suma disponibilit\u0103\u021bii p\u0103r\u021bilor \u00eemp\u0103r\u021bit\u0103 la nr. de p\u0103r\u021bi \u0219i la nr. de conexiuni TableColumn.header.AvgAvail=Disp. Medie/parte ConfigView.label.strictfilelocking=Impune blocarea accesului exclusiv la scrierea fi\u0219ierelor \u00eentre torente MyTorrentsView.menu.checkfilesexist=Controleaz\u0103 Dac\u0103 Fi\u0219ierele Exist\u0103 MyTorrentsView.menu.rescanfile=Reverific\u0103 Periodic P\u0103r\u021bile Incomplete MyTorrentsView.menu.clear_resume_data=Cur\u0103\u021b\u0103 Datele de Reluare Plugin.extseed.name=Donatori Externi Plugin.localtracker.name=C\u0103ut\u0103tor de Parteneri \u00een LAN Plugin.localtracker.info=Cautatorul de parteneri LAN permite mai multe copii Vuze aflate dupa un zid-de-foc pe o retzea comuna\n pentru o tragere eficienta prin acceptarea de legaturi directe intre ele. Plugin.localtracker.enable=Activeaz\u0103 c\u0103ut\u0103torul de parteneri \u00een LAN azinstancehandler.alert.portclash=Conflict de porturi detectat pe LAN: %1 e deja folosit de alt utilizator Vuze. Alege\u021bi un port aleator nou (sau mai multe) pentru ascultarea intr\u0103rilor TCP/UDP [\u00eentre %2 \u0219i %3]. ConfigView.section.transfer.lan.tooltip=Set\u0103ri specifice pt. LAN ConfigView.section.transfer.lan.uploadrate=KB/s viteza max de \u00eenc\u0103rcare \u00een LAN [0: nelimitat] ConfigView.section.transfer.lan.uploadrate.tooltip=Conexiunile cu partenerii din aceea\u0219i re\u021bea local\u0103 (LAN) au o limit\u0103 separat\u0103 a vitezei de \u00eenc\u0103rcare. ConfigView.section.transfer.lan.downloadrate=KB/s viteza maxim\u0103 de desc\u0103rcare \u00een LAN [0: nelimitat\u0103] ConfigView.section.transfer.lan.downloadrate.tooltip=Conexiunile cu partenerii din aceea\u0219i re\u021bea local\u0103 (LAN) au o limit\u0103 separat\u0103 a vitezei de desc\u0103rcare. TorrentOptionsView.title.short=Op\u021biuni TorrentOptionsView.title.full=Op\u021biuni TorrentOptionsView.param.max.peers=Num\u0103r maxim de conexiuni [0: nelimitat] ConfigView.section.connection.encryption.require_encrypted_transport=Necesit\u0103 transfer criptat ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=For\u021beaz\u0103 folosirea conexiunile criptate cu al\u021bi parteneri. ConfigView.section.connection.encryption.min_encryption_level=Nivelul minim de criptare ConfigView.section.connection.encryption.min_encryption_level.tooltip=Simpl\u0103 - doar str\u00eengerea de m\u00een\u0103\nRC4 - fluxul complet\nCript\u0103rile complexe folosesc mai multe resurse ale CPU. Peers.column.Encryption=Criptare Peers.column.Encryption.info=Puterea cript\u0103rii folosite ConfigView.section.connection.encryption.encrypt.info=Dac\u0103 este activat\u0103 criptarea nu v\u0103 ve\u021bi putea conecta la clien\u021bi (softuri) incompatibili p\u00een\u0103 ce nu configura\u021bi op\u021biunile de rezerv\u0103 ConfigView.section.connection.encryption.encrypt.info.link=Clica\u021bi aici pentru detalii MainWindow.sr.status.tooltip.ok=Raport de Partajare %1 OK MainWindow.sr.status.tooltip.poor=Raport de Partajare %1 slab: < 0.9 MainWindow.sr.status.tooltip.bad=Raport de Partajare %1 prost: < 0.5 ConfigView.section.style.status=Zona St\u0103rilor: ConfigView.section.style.status.show_sr=Raport de Partajare ConfigView.section.style.status.show_nat=Starea NAT ConfigView.section.style.status.show_ddb=Starea BDD ConfigView.section.style.status.show_ipf=Starea Filtrului IP ConfigView.section.connection.encryption.encrypt.group=Criptarea/Mascarea Transferului ConfigView.section.connection.encryption.encrypt.fallback_info=Activarea oric\u0103reia din op\u021biunile de rezerv\u0103 va permite conexiuni cu clien\u021bi incompatibili, \u00ceNS\u0102 conexiunile vor fi necriptate. ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Permite conexiunile ie\u0219inde necriptate dac\u0103 tentativa de conectare criptat\u0103 e\u0219ueaz\u0103 ConfigView.section.connection.encryption.encrypt.fallback_incoming=Permite conexiuni intr\u00eende necriptate ConfigView.section.connection.encryption=Criptarea Transferului upnp.selectedinterfaces=Interfe\u021be selectate (separate prin';', de ex. eth0;eth1) [gol: toate] ConfigView.section.style.defaultSortOrder=Ordinea de Sortare Implicit\u0103 ConfigView.section.style.defaultSortOrder.desc=Descresc\u0103tor ConfigView.section.style.defaultSortOrder.asc=Cresc\u0103tor ConfigView.section.style.defaultSortOrder.flip=Inversul ordon\u0103rii precedente LoggerView.autoscroll=Autoderulare Button.selectAll=Selecteaz\u0103 Tot Button.markSelected=Marcheaz\u0103 Selec\u021bia Button.unmarkSelected=Deselecteaz\u0103 Itemurile plugins.basicview.config=Configura\u021bie TorrentOptionsView.param.max.uploads=Nr. maxim de sloturi de \u00eenc\u0103rcare [minimum: 2] MyTorrentsView.dialog.setPosition.title=Seteaz\u0103 Pozi\u021bia MyTorrentsView.dialog.setPosition.text=Introduce\u021bi pozi\u021bia de setat pentru torentele alese: MyTorrentsView.menu.reposition.manual=Repozi\u021bioneaz\u0103.. ConfigView.section.connection.advanced.info.link=Clica\u021bi aici pentru detalii ConfigView.section.connection.advanced.socket.group=Op\u021biunile Socketului ConfigView.section.connection.advanced.bind_port=Leag\u0103 de portul local [0:neactivat] ConfigView.section.connection.advanced.bind_port.tooltip=Conexiunile la socket ie\u0219inde vor fi legate local de portul specificat.\nActivarea acestei op\u021biuni poate ajuta \u00een cazul instabilit\u0103\u021bii ruterului NAT. ConfigView.section.proxy.group.tracker=Comunicare cu Trackerul ConfigView.section.proxy.group.peer=Comunicare cu Partenerii Pieces.column.Requested=Solicitat Pieces.column.Requested.info=Arat\u0103 dac\u0103 se mai pot face sau nu cereri pentru parte (*) ConfigView.label.maxuploadsseeding=Implicita alternativ\u0103 c\u00eend se doneaz\u0103 MyTorrentsView.filter=Filtru: popup.error.hideall=Ascunde Tot ConfigView.section.style.dataStatsOnly=Arat\u0103 doar statisticile datelor (ascunde statisticile protocolului) ConfigView.section.style.separateProtDataStats=Arat\u0103 statisticile de date \u0219i de protocol \u00een mod separat ca 'date (protocol)' MyTorrentsView.dialog.setFilter.title=Modific\u0103 Filtrul MyTorrentsView.dialog.setFilter.text=Sec\u021biunea %1 va fi filtrat\u0103 dup\u0103 textul specificat mai jos. Folosi\u021bi semnul | (\u021beav\u0103) pentru a filtra dup\u0103 fraze multiple. MyTorrentsView.filter.tooltip=Ctrl+X pentru comutarea \u00eentre RegEx \u0219i moduri de c\u0103utare obi\u0219nuite.\nFolose\u0219te simbolul | (\u021beav\u0103) pentru a filtra cu fraze multiple. MyTorrentsView.clearFilter.tooltip=Cur\u0103\u021b\u0103 Filtrul MyTorrentsView.menu.filter=Lista de Filtre... ConfigView.section.file.resume.recheck.all=La pr\u0103bu\u0219ire-repornire verific\u0103 tot fi\u0219ierul pentru p\u0103r\u021bile terminate (altfel doar p\u0103r\u021bile active la ultima salvare s\u00eent verificate) ConfigureWizard.language.choose=Alege\u021bi o limb\u0103 din lista de mai jos: popup.closing.in=Anun\u021bul se va \u00eenchide \u00een %1 sec popup.more.waiting=%1 mesaj(e) \u00een plus.. # > 2402 popup.download.finished="%1" a fost desc\u0103rcat complet. popup.file.finished="%1" a fost desc\u0103rcat complet. Plugin.localtracker.autoadd.info=Adaug\u0103 automat ace\u0219ti parteneri locali [';' separ\u0103 adresele, de ex. 1.2.3.4] Plugin.localtracker.autoadd=Parteneri Explici\u021bi Plugin.localtracker.networks.info=Consider\u0103 re\u021belele urm\u0103toare ca fiind locale [separ\u0103 re\u021belele cu ';' de ex. 145.227.*.*] Plugin.localtracker.networks=Re\u021bele Locale MainWindow.menu.view.plugins.logViews=Jurnale de Activitate SpeedView.stats.autospeed=Vitez\u0103 Automat\u0103 de \u00cenc\u0103rcare SpeedView.stats.autospeed.disabled=Aceast\u0103 facilitate este fie dezactivat\u0103 (ave\u021bi nevoie de DHT), fie nu e \u00een uz (viteza de \u00eenc\u0103rcare e selectat\u0103 manual) SpeedView.stats.idlePing=Ping Inactiv: SpeedView.stats.maxPing=Ping Max: SpeedView.stats.currentPing=Pingul Curent: SpeedView.stats.maxUp=Viteza Max \u00cenc: ConfigView.pluginlist.unloadSelected=Opre\u0219te Selectatele ConfigView.pluginlist.scan=Scaneaz\u0103 dup\u0103 Extensii noi ConfigView.section.transfer.autospeed=Vitez\u0103 Automat\u0103 (clasic) ConfigView.section.transfer.autospeed.tooltip=Set\u0103ri specifice pt. Autovitez\u0103 ConfigView.section.transfer.autospeed.info=Autoviteza ajusteaz\u0103 automat limita superioar\u0103 a vitezei de \u00eenc\u0103rcare pentru a evita saturarea conexiunii la re\u021bea.\n\nAceast\u0103 limitare va fi aplicat\u0103 doar dac\u0103 este activat\u0103 op\u021biunea "vitez\u0103 de \u00eenc\u0103rcare automat\u0103" \u0219i de asemenea necesit\u0103 activarea bazei de date distribuit\u0103 [DHT].\n ConfigView.section.transfer.autospeed.minupload=%1 vitez\u0103 minim\u0103 de \u00eenc\u0103rcare ConfigView.section.transfer.autospeed.minupload.tooltip=Viteza de \u00eenc\u0103rcare nu va fi sc\u0103zut\u0103 automat sub aceast\u0103 limit\u0103 ConfigView.section.transfer.autospeed.maxupload=%1 vitez\u0103 maxim\u0103 de \u00eenc\u0103rcare [0: nelimitat\u0103] ConfigView.section.transfer.autospeed.maxupload.tooltip=Viteza de \u00eenc\u0103rcare nu va fi crescut\u0103 automat peste aceast\u0103 limit\u0103 ConfigView.section.transfer.autospeed.chokeping=Intervalul pingului la limitare [milisecunde] ConfigView.section.transfer.autospeed.chokeping.tooltip=Pingurile peste aceast\u0103 valoare vor fi considerate ca un indicator al satur\u0103rii re\u021belei ConfigView.section.transfer.autospeed.enableauto=Activeaz\u0103 c\u00eend se descarc\u0103 \u0219i se doneaz\u0103 ConfigView.section.transfer.autospeed.enableautoseeding=Activeaz\u0103 doar c\u00eend se doneaz\u0103 ConfigView.pluginlist.column.unloadable=Ne\u00eenc\u0103rcabil ConfigView.section.transfer.lan.enable=Activeaz\u0103 limite de vitez\u0103 separate pentru conexiunile LAN Plugin.localtracker.wellknownlocals=Include automat re\u021belele locale de tip bucl\u0103 invers\u0103/leg\u0103tur\u0103/sit (192.168 etc.) TableColumn.header.filesdone=Fi\u0219iere Terminate TableColumn.header.filesdone.info=Fi\u0219iere Terminate/Toate Fi\u0219ierele *sau* Fi\u0219iere Nes\u0103rite Terminate (Fi\u0219iere Terminate)/Toate Fi\u0219ierele Nes\u0103rite (Toate Fi\u0219ierele) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=a\u0219tept ini\u021bializarea BDD... MagnetPlugin.report.searching=caut... MagnetPlugin.report.found=g\u0103sit %1 MagnetPlugin.report.alive=%1 e viu MagnetPlugin.report.dead=%1 e mort MagnetPlugin.report.tunnel=tunelez spre %1 MagnetPlugin.report.downloading=descarc de pe %1 MagnetPlugin.report.error=eroare %1 MagnetURLHandler.report.no_sources=n-am g\u0103sit donatori pentru torent MagnetURLHandler.report.torrent_size=m\u0103rimea torentului: %1 MagnetURLHandler.report.percent=realizat: %1% MagnetURLHandler.report.error=eroare %1 DHTTransport.report.request_all=solicit tot transferul de la %1 DHTTransport.report.received_bit=primit %1 la %2 de la %3 DHTTransport.report.complete=terminat DHTTransport.report.timeout=expirat, nici un r\u0103spuns de la %1 DHTTransport.report.rerequest_all=resolicit transferul complet de la %1 DHTTransport.report.rerequest_bit=resolicit %1 p\u00een\u0103 la %2 de la %3 DHTTransport.report.timeout_some=expirat, %1 pachete primite de la %2 dar incomplete DHTTransport.report.sending=trimit datele DHTTransport.report.resending=retrimit datele DHTTransport.report.send_complete=trimitere complet\u0103 DHTTransport.report.send_timeout=expirarea trimiterii ConfigView.section.transfer.autospeed.enabledebug=F\u0103 un jurnal cu informa\u021biile de debugare TableColumn.header.date_added=Data Ad\u0103ug\u0103rii TableColumn.header.date_added.info=Data la care a fost ad\u0103ugat torentul ConfigView.section.file.hashchecking.smallestfirst=Reverific\u0103 mai \u00eent\u00eei desc\u0103rc\u0103rile mici platform.win32.baddll.info=Vuze a detectat prezen\u021ba lui '%1'. Acesta face parte din '%2' \u0219i este cunoscut a cauza probleme grave cum s\u00eent pr\u0103bu\u0219iri ale aplica\u021biei \u0219i utilizare crescut\u0103 a procesorului. Dac\u0103 le \u00eent\u00eelni\u021bi dezinstala\u021bi softul respectiv sau configura\u021bi-l pentru a nu afecta func\u021bionarea Vuze. platform.win32.baddll.radhslib=Filtru de Internet Naomi (Radiant) platform.win32.baddll.winsflt=Filtru PureSight pt. Con\u021binut de pe Internet upnp.ignorebaddevices=Ignor\u0103 dispozitivele care nu r\u0103spund corect upnp.ignorebaddevices.info=Dispozitive ignorate acum: %1 upnp.ignorebaddevices.reset=Reseteaz\u0103 lista cu dispozitive ignorate upnp.ignorebaddevices.reset.action=Reseteaz\u0103 upnp.ignorebaddevices.alert=Dispozitivul UPnP din loca\u021bia %1 e ignorat din cauza unor defec\u021biuni repetate. Vede\u021bi configurarea extensiei UPnP pentru op\u021biunile \u00een privin\u021ba acestei ac\u021biuni. TorrentOptionsView.param.max.uploads.when.busy=KB/s vitez\u0103 max de \u00eenc\u0103rcare la atingerea limitei globale de \u00eenc\u0103rcare [0: dezactivat\u0103] UpdateMonitor.messagebox.verification.failed.title=Verificarea Instal\u0103rii a E\u0219uat UpdateMonitor.messagebox.verification.failed.text=Verificarea lui '%1' a e\u0219uat: %2 UpdateMonitor.messagebox.accept.unverified.title=Accept\u0103 Instalarea Neverificat\u0103 UpdateMonitor.messagebox.accept.unverified.text='%1' nu poate fi verificat\u0103 ca fiind o extensie original\u0103 Vuze.\nDac\u0103 acest lucru e adev\u0103rat NU ar trebui s\u0103 continua\u021bi instalarea.\nContinui cu instalarea? FileView.BlockView.title=P\u0103r\u021bi de Fi\u0219iere FileView.BlockView.Done=Realizat FileView.BlockView.Skipped=S\u0103rit FileView.BlockView.Active=Activ FileView.BlockView.Outstanding=Restant ConfigView.label.tcplistenport=Portul de ascultare TCP intr\u00eend ConfigView.label.udplistenport=Portul de ascultare UDP upnp.portchange.alert=Porturile urm\u0103toare au fost schimbate pentru a evita problemele cu dispozitivele UPnP: %1 [vechiul port=%2] %3 [vechiul port=%4] ConfigView.section.proxy.username.info=Dac\u0103 serverul proxy solicit\u0103 autentificarea chiar \u0219i c\u00eend nici una nu e definit\u0103, folose\u0219te \u0219irul "" ca nume de utilizator ConfigView.label.maxuploadswhenbusymin=Viteza max. de \u00eenc\u0103rcare per torent cu temporizator ocupat [sec] MainWindow.menu.help.debug=Genereaz\u0103 Info de Debugare (Jurnalul Pr\u0103bu\u0219irii) DownloadManager.error.badsize=M\u0103rime Incorect\u0103 natpmp.info=NAT-PMP este alternativa Apple la UPnP \u0219i e suportat\u0103 de dispozitivele recente de tip Airport\n\nLua\u021bi not\u0103 de faptul c\u0103 UPnPtrebuie activat pentru ca NAT-PMP s\u0103 poat\u0103 fi la r\u00eendul s\u0103u activat, deoarece dispozitivul NAT-PMP e tratat ca un tip special de dispozitiv UPnP natpmp.enable=Activeaz\u0103 (trebuie s\u0103 fie activat \u0219i \u00een configura\u021bia Airport pentru a func\u021biona) ConfigView.section.tracker.host.addurls=Asigura\u021bi-v\u0103 c\u0103 adresele acestui tracker s\u00eent prezente \u00een torentele g\u0103zduite ConfigView.filter=tasta\u021bi textul de filtrare ConfigView.section.files.move=Mutarea la Terminare ConfigView.section.file.defaultdir.section=Op\u021biunile Implicite ale Dosarelor ConfigView.section.file.defaultdir.auto=Descarc\u0103 \u00eentotdeauna \u00een dosarul implicit (f\u0103r\u0103 avertizare) ConfigView.section.file.defaultdir.bestguess=Folose\u0219te solu\u021bia cea mai potrivit\u0103 la alegerea dosarului implicit de salvare ConfigView.section.file.defaultdir.ask=Dosarul implicit: ConfigView.section.file.defaultdir.lastused=Seteaz\u0103 dosarul implicit la locul ultimei salv\u0103ri ConfigView.section.file.config.section=Set\u0103ri de Configurare ConfigView.section.file.config.currentdir=Dosarul configura\u021biei curente: ConfigView.section.torrent.decoding=Seturi de Decodare a Caracterelor ConfigView.section.logging.udptransport=Activeaz\u0103 urm\u0103rirea detaliat\u0103 a transportului UDP Tracker.announce.ignorePeerSeed=Ignor nr. %1 de Part./Donatori ConfigView.section.connection.encryption.use_crypto_port=Folosi\u021bi extensia 'cryptoport' pentru tracker \u00een scopul prevenirii tentativelor obi\u0219nuite de conect\u0103ri intr\u00eende. Anumite trackere nu accept\u0103 asta \u0219i e\u0219ueaz\u0103 cu erori ca "Port Invalid" sau "Argument Incorect" TorrentOptionsView.param.reset.to.default=Seteaz\u0103 op\u021biunile \u00eenapoi la valorile implicite TorrentOptionsView.param.reset.button=Reseteaz\u0103 natpmp.routeraddress=Adresa sta\u021biei [gol: auto] ConfigView.section.style.disableAlertSliding=Dezactiveaz\u0103 apari\u021bia \u00een prim-plan \u0219i anima\u021bia de glisare a mesajelor de alert\u0103 ConfigView.section.transfer.autospeed.maxinc=%1 cre\u0219tere maxim\u0103 per ciclu ConfigView.section.transfer.autospeed.maxdec=%1 sc\u0103dere maxim\u0103 per ciclu ConfigView.section.transfer.autospeed.enabledownadj=Activeaz\u0103 ajustarea vitezei de desc\u0103rcare ConfigView.section.transfer.autospeed.downadjratio=Raportul Vitezelor de Desc\u0103rcare : \u00cenc\u0103rcare (de ex. 2.0 -> limita vitezei de desc\u0103rcare este dublul limitei celei de \u00eenc\u0103rcare) ConfigView.section.transfer.autospeed.latencyfactor=Factor folosit pentru a corela modific\u0103rile de laten\u021b\u0103 cu modific\u0103rile de vitez\u0103 (numerele mai mari scad senzitivitatea) ConfigView.section.transfer.autospeed.reset=Reseteaz\u0103 valorile avansate ConfigView.section.transfer.autospeed.reset.button=Reseteaz\u0103 PeerColumn.activationCount=Parteneri \u00eencerc\u00eend s\u0103 se conecteze: %1 TableColumn.header.timesincedownload.info=Timpul scurs de c\u00eend au fost desc\u0103rcate date din torent TableColumn.header.timesincedownload=Inactivitatea Desc\u0103rc\u0103rii TableColumn.header.timesinceupload.info=Timpul scurs de c\u00eend au fost \u00eenc\u0103rcate date \u00een torent TableColumn.header.timesinceupload=Inactivitatea \u00cenc\u0103rc\u0103rii PeersView.incomingreqcount=Solicit\u0103ri Primite PeersView.incomingreqcount.info=Num\u0103rul de solicit\u0103ri venite de la partener PeersView.outgoingreqcount=Solicit\u0103ri Trimise PeersView.outgoingreqcount.info=Num\u0103rul de solicit\u0103ri trimise partenerului upnp.mapping.trackerclientudp=Port al Clientului Tracker UDP upnp.mapping.dhtudp=Baz\u0103 de Date Distribuit\u0103 ConfigView.section.connection.nondata.udp.same=Folose\u0219te acela\u0219i port UDP pentru Baza de Date Distribuit\u0103 \u0219i pentru Trackerul UDP ConfigView.section.connection.tcp.enable=Activeaz\u0103 TCP ConfigView.section.connection.udp.enable=Activeaz\u0103 UDP ConfigView.section.style.showiconbar=Arat\u0103 Bara de Unelte MainWindow.menu.view.iconbar=Bara de Unelte MyTorrentsView.menu.rename=Redenume\u0219te MyTorrentsView.menu.rename.displayed=Modific\u0103 Numele Afi\u0219at MyTorrentsView.menu.rename.save_path=Redenume\u0219te Calea de Salvare AdvRenameWindow.title=Redenume\u0219te Desc\u0103rcarea AdvRenameWindow.message=Introduce\u021bi un nume nou pentru aceast\u0103 desc\u0103rcare. AdvRenameWindow.rename.torrent=Redenume\u0219te Torentul MyTorrentsView.menu.rename.displayed.enter.title=Modific\u0103 Numele Afi\u0219at MyTorrentsView.menu.rename.displayed.enter.message=Introduce\u021bi un nume nou ce va fi afi\u0219at pentru aceast\u0103 desc\u0103rcare. MyTorrentsView.menu.edit_comment=Editeaz\u0103 Comentariul MyTorrentsView.menu.edit_comment.enter.title=Editeaz\u0103 Comentariul MyTorrentsView.menu.edit_comment.enter.message=Ad\u0103uga\u021bi un comentariu pt. aceast\u0103 desc\u0103rcare. UIDebugGenerator.messageask.title=Generator de Info pt. Debugare UIDebugGenerator.messageask.text=Introduce\u021bi o descriere a bugului pe care \u00eel raporta\u021bi UIDebugGenerator.complete.title=Generarea de info pt. debugare este complet\u0103 UIDebugGenerator.complete.text=Trimite\u021bi fi\u0219ierul '%1' la adresa az-bugreports@azureus-inc.com\n\nClica\u021bi pe Ok pentru a deschide o fereastr\u0103 cu acest fi\u0219ier. ConfigView.section.style.showProgramIcon=Arat\u0103 iconi\u021ba programului \u00een coloana numelui ConfigView.section.style.showProgramIcon.tooltip=Vederea trebuie redeschis\u0103 pentru ca schimb\u0103rile s\u0103 devin\u0103 efective swt.alert.cant.update=Biblioteca SWT \u00eenc\u0103rcat\u0103 din "%3" nu poate fi actualizat\u0103 automat de la versiunea %1 la %2 (trebuie \u00eenc\u0103rcat\u0103 din "%4"). Vede\u021bi wikiul pentru detalii. authenticator.savepassword=Memoreaz\u0103-mi parola ConfigView.section.security.clearpasswords=Reseteaz\u0103 parolele memorate ConfigView.section.security.clearpasswords.button=Reseteaz\u0103 Content.alert.notuploaded.title=\u00cenc\u0103rcarea nu e complet\u0103 Content.alert.notuploaded.text=\u00cenc\u0103rcarea lui '%1' nu este complet\u0103. Dac\u0103 ve\u021bi %2 acum, lumea nu va putea s\u0103 descarce complet opera publicat\u0103 de dv.\n\nSigur dori\u021bi s\u0103 %2? Content.alert.notuploaded.multi.title=\u00cenc\u0103rc\u0103rile Nu S\u00eent Complete Content.alert.notuploaded.multi.text=%1 din con\u021binutul publicat de dv. nu s\u00eent donate complet. Dac\u0103 %2 acum, ceilal\u021bi nu vor putea s\u0103 descarce complet lucr\u0103rile pe care le-a\u021bi publicat. Sigur dori\u021bi s\u0103 %2?\n\nCon\u021binut care nu e donat complet:\n%3 Content.alert.notuploaded.quit=p\u0103r\u0103se\u0219te Vuze TorrentInfoView.torrent.encoding=Codarea Torentelor TorrentInfoView.columns=Coloane pentru vederea 'Torentele Mele' progress.window.title=Opera\u021biune \u00een Desf\u0103\u0219urare progress.window.msg.filemove=A\u0219tepta\u021bi p\u00een\u0103 se termin\u0103 mutarea/redenumirea fi\u0219ierului ConfigView.label.popup.timestamp=Adaug\u0103 marcaje de timp la alertele popup ConfigView.label.popup.autohide=Ascunde automat alertele popup dup\u0103 x secunde (seteaz\u0103 la 0 pt. a dezactiva autoascunderea) ConfigView.label.popup.suppress_alerts=Suprim\u0103 alertele ConfigView.label.popup.use_message_boxes=Folose\u0219te casete cu mesaje popup mai degrab\u0103 dec\u00eet casete de alertare obi\u0219nuite. ConfigView.label.popup.show=Arat\u0103 toate alertele popup \u00eenregistrate p\u00een\u0103 acum (dac\u0103 exist\u0103) ConfigView.label.popup.show.button=Arat\u0103 ConfigView.label.please.visit.here=Clica\u021bi aici pentru detalii suplimentare ConfigView.section.ipfilter.enable.descriptionCache=Stocheaz\u0103 descrierile IP \u00eentr-un fi\u0219ier ciorn\u0103 ConfigView.section.ipfilter.enable.descriptionCache.tooltip=\u00cen caz de dezactivare, descrierile nu vor fi memorate OpenTorrentWindow.filesInfo=%1 din %2 vor fi desc\u0103rcate. OpenTorrentWindow.diskUsage=%1 din %2 ConfigView.label.openmytorrents=Deschide 'Torentele Mele' la pornire ConfigView.label.open_transfer_bar_on_start=Deschide Bara de Transferuri la pornire ConfigView.section.style.DNDalwaysInIncomplete=Arat\u0103 mereu torentele cu fi\u0219iere 'Nu Desc\u0103rca' \u00een sec\u021biunea Incomplete din Torentele Mele OpenTorrentWindow.mb.noGlobalDestDir.title=Dosarul de Destina\u021bie OpenTorrentWindow.mb.noGlobalDestDir.text=Dosarul de Destina\u021bie '%1' este invalid. OpenTorrentWindow.mb.noDestDir.title=Dosarul de Destina\u021bie nu a fost g\u0103sit OpenTorrentWindow.mb.noDestDir.text=Dosarul de destina\u021bie '%1' pentru torentul '%2' nu exist\u0103 sau e invalid. OpenTorrentWindow.mb.notValid.title=Deschide Torentul OpenTorrentWindow.mb.notValid.text=Nu pot deschide torentul '%1'. Dac\u0103 \u00eel deschide\u021bi \u00een mod de donare, asigura\u021bi-v\u0103 c\u0103 exist\u0103 fi\u0219ierele cu date. OpenTorrentWindow.mb.notTorrent.title=Deschide Torentul OpenTorrentWindow.mb.notTorrent.text=Nu pot deschide '%1'. Nu pare a fi un fi\u0219ier torent.\n\nUnele din datele primite:\n%2 ConfigView.label.pause.downloads.on.exit=Pauzeaz\u0103 desc\u0103rc\u0103rile la ie\u0219ire ConfigView.label.resume.downloads.on.start=Reia la pornire desc\u0103rc\u0103rile pauzate, dup\u0103 ce s-a terminat ini\u021bializarea UIDebugGenerator.message.cancel.title=Generarea de info pt. debugare a fost anulat\u0103 UIDebugGenerator.message.cancel.text=Nu a\u021bi ad\u0103ugat o descriere a bugului pe care dori\u021bi s\u0103-l raporta\u021bi. Bugul poate fi evident pentru dv., dar f\u0103r\u0103 o descriere detaliat\u0103 nu vom putea dec\u00eet s\u0103 ghicim care e problema care \u00eel produce.\n\nGenerarea de info pentru debugare a fost anulat\u0103. ConfigView.section.connection.group.http.info=Suport pentru donare HTTP. ConfigView.section.connection.http.enable=Activeaz\u0103 ConfigView.section.connection.http.port=Num\u0103rul portului de intrare ConfigView.section.connection.http.portoverride=Ignor\u0103 portul Trackerului HTTP [0: nimic] window.update.noupdates.title=Rezultatul C\u0103ut\u0103rii de Actualiz\u0103ri window.update.noupdates.text=Nu exist\u0103 actualiz\u0103ri disponibile pentru program.\n\nFelicit\u0103ri! ConfigView.label.bindip.details=Exemplu: 192.168.1.5;eth0;eth1[2] vor lega adresa IP specificat\u0103 la toate adresele IP de la 1-a interfa\u021b\u0103 \u0219i la a 3-a adres\u0103 IP a celei de-a 2-a interfe\u021be.\nPrima adres\u0103 IP va fi utilizat\u0103 pentru toate serviciile, iar restul vor fi utilizate doar pentru echilibrarea sarcinii.\nS\u00eent disponibile urm\u0103toarele interfe\u021be:\n%1 ConfigView.label.mindownloads=Nr. min. de desc\u0103rc\u0103ri simultane UI.cannot_submit_blank_text=Trebuie s\u0103 introduce\u021bi o valoare. crypto.alert.as.warning=Re\u021beaua '%1' este cunoscut\u0103 ca folosind fasonarea traficului [shaping] \u00een scopul sc\u0103derii vitezei de desc\u0103rcare. Criptarea transferurilor a fost activat\u0103 automat - ea poate fi modificat\u0103/\u00eenchis\u0103 prin configurarea parametrilor. ConfigView.section.interface.alerts=Alerte ConfigView.label.popupdownloadadded=Arat\u0103 o alert\u0103 popup la ad\u0103ugarea unei desc\u0103rc\u0103ri popup.download.added="%1" a fost ad\u0103ugat la lista de desc\u0103rcare. MessageBoxWindow.nomoreprompting=Nu m\u0103 aten\u021biona din nou TorrentOptionsView.param.max.seeds=Num\u0103rul maxim de conexiuni la donatori [0: limita conexiunii] TorrentOptionsView.param.alternative.value.enable=Valoarea alternativ\u0103 \u00een timpul don\u0103rii ConfigView.section.proxy.check.on.start=Verific\u0103 starea proxyului la pornire TransferStatsView.legend.pingaverage=Medie TransferStatsView.legend.ping1=\u021ainta 1 TransferStatsView.legend.ping2=\u021ainta 2 TransferStatsView.legend.ping3=\u021ainta 3 ConfigView.section.interface.enabletray._mac=Activeaz\u0103 Iconi\u021ba din Bara de Stare (necesit\u0103 repornire) ConfigView.label.closetotray._mac=\u00cenchiderea ferestrei minimizeaz\u0103 programul \u00een sistaler ConfigView.label.minimizetotray._mac=Minimizeaz\u0103 ca iconi\u021b\u0103 \u00een sistaler OpenTorrentWindow.mb.existingFiles.title=Fi\u0219ierele exist\u0103 deja! OpenTorrentWindow.mb.existingFiles.text=Anumite fi\u0219iere exist\u0103 deja \u00een dosarul (dosarele) de destina\u021bie pe care l-a\u021bi specificat:\n\n%1\nDac\u0103 ve\u021bi continua, Vuze va verifica fi\u0219ierele \u00een cauz\u0103 pentru a vedea dac\u0103 au date valide \u0219i le va suprascrie dac\u0103 va fi necesar. splash.unloadingTorrents=Dez\u00eencarc Torentele splash.unloadingTorrent=Dez\u00eencarc Torentul ConfigView.section.file.defaultdir.autorename=Redenume\u0219te automat fi\u0219ierele torentului dac\u0103 fi\u0219ierele din cale par diferite ConfigView.section.file.defaultdir.autorename.tooltip=Aceasta previne ca un torent s\u0103 suprascrie fi\u0219ierele altui torent atunci c\u00eend numele fi\u0219ierelor s\u00eent identice alert.raised.at.close=(Mesaj de la \u00eenchiderea precedent\u0103 a lui Vuze) Plugin.trackerpeerauth.name=Autorizarea Trackerului Partenerului Plugin.trackerpeerauth.info=Aceast\u0103 extensie lucreaz\u0103 cu trackerele pentru a verifica dac\u0103 partenerii s\u00eent membri valizi ai roiului Peers.column.maxupspeed=Viteza Max \u00cenc Peers.column.maxdownspeed=Viteza Max Desc MyTorrents.items.DownSpeedLimit.disabled=Nici o desc\u0103rcare upnp.selectedaddresses=Adrese (separate prin ';' , prefix '-' =refuz\u0103, '+' =permite) [gol: oricare] upnp.alert.multipledevice.warning=Au fost detectate multiple dispozitive UPnP - verifica\u021bi dac\u0103 toate necesit\u0103 maparea porturilor (vede\u021bi jurnalul \u0219i configurarea UPnP) UpdateMonitor.messagebox.restart.title=Actualizarea Softului UpdateMonitor.messagebox.restart.text=Vuze tocmai a terminat de desc\u0103rcat o actualizare important\u0103 \u0219i trebuie repornit pentru ca aceasta s\u0103 fie instalat\u0103. PiecesView.BlockView.Have=Am PiecesView.BlockView.NoHave=Nu Am PiecesView.BlockView.Header=%1 coloane, %2 r\u00eenduri, %3 p\u0103r\u021bi ConfigView.section.update.autodownload=Descarc\u0103 automat actualiz\u0103rile \u0219i aten\u021bioneaz\u0103 c\u00eend instalarea e preg\u0103tit\u0103 Peers.column.peer_id=ID Partener Peers.column.peer_id.info=ID-ul Partenerului \u00een format citibil Peers.column.peer_byte_id=ID Partener Peers.column.peer_byte_id.info=ID-ul Partenerului \u00een format binar Peers.column.handshake_reserved=Bai\u021bi Rezerva\u021bi pt. Str\u00eengerea de M\u00een\u0103 Peers.column.handshake_reserved.info=Indic\u0103 care bi\u021bi rezerva\u021bi au fost seta\u021bi \u00een "str\u00eengerea de m\u00een\u0103" BT Peers.column.client_identification=Identificarea Clientului Peers.column.client_identification.info=Indic\u0103 numele brute de clien\u021bi primite de Vuze - util pentru debugare dht.warn.user=Aten\u021bioneaz\u0103 dac\u0103 pot apare probleme cu NAT/maparea porturilor ConfigView.label.openbar.incomplete=Barele de Desc\u0103rcare: autodeschide desc\u0103rc\u0103rile ConfigView.label.openbar.complete=autodeschide donatorii ConfigView.label.transferbar.remember_location=Memoreaz\u0103 ultima pozi\u021bie a Barei de Transfer ConfigView.section.transfer.autospeed.forcemin=%1 vitez\u0103 de \u00eenc\u0103rcare impus\u0103 for\u021bat la evaluarea func\u021bion\u0103rii conexiunii MainWindow.menu.tools.speedtest=Test de Vitez\u0103... speedtest.wizard.title=Test de Vitez\u0103 speedtest.wizard.run=Ruleaz\u0103 un test de vitez\u0103 speedtest.wizard.test.mode.updown=\u00eenc\u0103rcare \u0219i desc\u0103rcare speedtest.wizard.test.mode.up=\u00eenc\u0103rcare speedtest.wizard.test.mode.down=desc\u0103rcare SpeedTestWizard.test.panel.currinfo=Testarea l\u0103\u021bimii de band\u0103 pentru BitTorrent. SpeedTestWizard.test.panel.label=Test de vitez\u0103 Vuze: SpeedTestWizard.test.panel.already.running=Testul ruleaz\u0103 deja! SpeedTestWizard.test.panel.not.accepted=Solicitare de testare neacceptat\u0103: SpeedTestWizard.test.panel.abort=\u00centrerupe SpeedTestWizard.test.panel.abort.countdown=\u00eentrerupe testul \u00een: SpeedTestWizard.test.panel.test.countdown=test terminat \u00een: SpeedTestWizard.test.panel.testfailed=Testul a e\u0219uat SpeedTestWizard.test.panel.aborted=Test \u00eentrerupt manual. SpeedTestWizard.test.panel.enc.label=Ap\u0103sa\u021bi pentru a testa cu criptare: SpeedTestWizard.test.panel.encrypted=criptat SpeedTestWizard.set.upload.button.apply=Aplic\u0103 SpeedTestWizard.set.upload.result=Ultimul Rezultat al Testului SpeedTestWizard.set.upload.bytes.per.sec=kBai\u021bi/sec SpeedTestWizard.set.upload.bits.per.sec=bi\u021bi/sec SpeedTestWizard.finish.panel.title=Testul de Vitez\u0103 a fost Realizat! SpeedTestWizard.finish.panel.click.close=A\u021bi terminat vr\u0103jitorul de testare a vitezei. Clica\u021bi pe \u00cenchide pentru a ie\u0219i. SpeedTestWizard.finish.panel.max.upload=Max \u00eenc\u0103rcare : SpeedTestWizard.finish.panel.max.seeding.upload=Max \u00eenc\u0103rcare la donare : SpeedTestWizard.finish.panel.max.download=Max desc\u0103rcare : SpeedTestWizard.finish.panel.enabled=activat SpeedTestWizard.finish.panel.disabled=dezactivat SpeedTestWizard.abort.message.scheduled.in=test planificat \u00een ... %1 secunde" SpeedTestWizard.abort.message.unsupported.type=Tip de test nesuportat!!!! SpeedTestWizard.abort.message.manual.abort=\u00centrerupt manual SpeedTestWizard.abort.message.scheduling.failed=Planificarea testului a e\u0219uat SpeedTestWizard.abort.message.download.added=Desc\u0103rcarea %1 a fost ad\u0103ugat\u0103 \u00een timpul testului SpeedTestWizard.abort.message.entered.error=Testeaz\u0103 starea de eroare a desc\u0103rc\u0103rii ad\u0103ugate '%1' SpeedTestWizard.abort.message.entered.queued=Testeaz\u0103 starea torentelor desc\u0103rcate ad\u0103ugate puse \u00een coad\u0103 / oprite SpeedTestWizard.abort.message.interrupted=Firul de execu\u021bie al Testului de Vitez\u0103 a Torentului a fost \u00eentrerupt \u00eenainte de terminarea testului SpeedTestWizard.abort.message.execution.failed=Executarea testului a e\u0219uat SpeedTestWizard.abort.message.failed.peers=Conectarea la parteneri a e\u0219uat SpeedTestWizard.abort.message.insufficient.slots=Nu pot trimite date c\u0103tre niciunul din parteneri - sloturi insuficiente de \u00eenc\u0103rcare? SpeedTestWizard.abort.message.not.unchoked=Nu pot desc\u0103rca de la niciunul dintre parteneri pt. c\u0103 g\u00eetuirea n-a fost \u00eenl\u0103turat\u0103 de ei SpeedTestWizard.stage.message.requesting=solicit testul... SpeedTestWizard.stage.message.preparing=preg\u0103tesc testul... SpeedTestWizard.stage.message.starting=pornesc testul... SpeedTestWizard.stage.message.connect.stats=Statisticile conexiunii: parteneri=%1, desc_ok=%2, \u00eenc_ok=%3 window.uiswitcher.title=Selector de Interfa\u021b\u0103 Vuze window.uiswitcher.text=Selecta\u021bi o interfa\u021b\u0103 de mai jos care v\u0103 satisface cel mai bine necesit\u0103\u021bile. window.uiswitcher.NewUI.text=* Recomandat pentru \u00eencep\u0103tori \u0219i utilizatori noi.\n\n* Interfa\u021b\u0103 grafic\u0103 u\u0219oar\u0103 \u0219i intuitiv\u0103\n\n* Interfa\u021b\u0103 necesar\u0103 pentru publicarea pe platforma Vuze window.uiswitcher.ClassicUI.title=Interfa\u021b\u0103 Clasic\u0103 window.uiswitcher.ClassicUI.text=* P\u0103streaz\u0103 func\u021bionalitatea clientului din seria 2.x\n\n* Stratul de con\u021binut Vuze nu va fi \u00eenc\u0103rcat window.uiswitcher.bottom.text=Alegerea dv. poate fi modificat\u0103 din nou cu ajutorul butonului de selectare a interfe\u021bei Vuze iconBar.switch.tooltip=Selectorul de Interfa\u021b\u0103 Vuze VivaldiView.notAvailable=Vederea Vivaldi nu e disponibil\u0103 restart.error=Repornirea a e\u0219uat:\n%1\nVezi probleme la repornire. restart.error.oom=Memorie RAM Epuizat\u0103 restart.error.fnf='%1' nu a fost g\u0103sit \u00een '%2' restart.error.pnf=Calea '%1' nu a fost g\u0103sit\u0103 restart.error.bad=Format gre\u0219it de fi\u0219ier pentru '%1' restart.error.denied=Accesul a fost refuzat \u00een timp ce se \u00eencerca rularea lui '%1'. Asigura\u021bi-v\u0103 c\u0103 ave\u021bi permisiunile necesare pentru a rula programul respectiv. TableColumn.header.date_completed=Data Termin\u0103rii TableColumn.menu.date_added.reset=Reseteaz\u0103 Data ConfigView.section.ipfilter.discardbanning=Blocheaz\u0103 partenerii al c\u0103ror raport "date nefolositoare/date bune" dep\u0103\u0219e\u0219te [0: dezactivat] ConfigView.section.ipfilter.discardminkb=Minimum %1 nefolositori \u00eenaintea aplic\u0103rii raportului ConfigView.interface.start.advanced=Porne\u0219te cu Vederea Torentelor (AZ 2.x) MyTorrents.column.ColumnQuality=Calitate MyTorrents.column.ColumnSpeed=Vitez\u0103 MyTorrents.column.ColumnProgressETA.2ndLine=Timp R\u0103mas : %1 %2 MyTorrents.column.ColumnProgressETA.StreamReady=Fluxare Preg\u0103tit\u0103 %1 MyTorrents.column.ColumnProgressETA.PlayableIn=Redabil \u00een %1 %2 TableColumn.header.Quality=Calitate TableColumn.header.Speed=Vitez\u0103 TableColumn.header.RateIt=Not\u0103 TableColumn.header.Rating=Not\u0103 TableColumn.header.SpeedGraphic=Vitez\u0103 TableColumn.header.AzProduct=Din TableColumn.header.ProgressETA=Progres #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=Tipul de Fi\u0219ier: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=Tablou de Bord v3.MainWindow.tab.browse=Vuze v3.MainWindow.tab.library=Arhiva Torentelor v3.MainWindow.tab.publish=Publicare v3.MainWindow.tab.advanced=Torente v3.MainWindow.menu.home=&Tablou de Bord v3.MainWindow.menu.browse=&Vuze v3.MainWindow.menu.library=&Arhiva Torentelor v3.MainWindow.menu.publish=&Publicare v3.MainWindow.menu.advanced=&Torente v3.MainWindow.menu.view.searchbar=Bara de C\u0103utare v3.MainWindow.menu.view.tabbar=Bara de Taburi v3.MainWindow.currentDL=Desc\u0103rcat Acum v3.MainWindow.button.stream=Fluxeaz\u0103 v3.MainWindow.button.stop=Opre\u0219te v3.MainWindow.button.start=Porne\u0219te v3.MainWindow.button.pause=Pauzeaz\u0103 v3.MainWindow.button.resume=Reia v3.MainWindow.button.delete=\u0218terge v3.MainWindow.button.comment=Comenteaz\u0103 v3.MainWindow.button.viewdetails=Vezi Detaliile v3.MainWindow.button.play=Red\u0103 v3.MainWindow.button.cancel=Anuleaz\u0103 v3.MainWindow.button.preview=Previzioneaz\u0103 v3.MainWindow.view.wait=Ini\u021bializez vederea, a\u0219tepta\u021bi. v3.MainWindow.xofx=%1 din %2 v3.MainWindow.Loading=\u00cencarc.. A\u0219tepta\u021bi v3.filter-bar=Filtru de Titluri: v3.MainWindow.search.defaultText=Caut\u0103 \u00een Vuze v3.mb.delPublished.title=Opre\u0219te Donarea de Con\u021binut v3.mb.delPublished.text=AVERTISMENT: Aceast\u0103 ac\u021biune NU va \u00eenl\u0103tura con\u021binutul dv. publicat '%1' de la %3 .\n\nClica\u021bi pe "\u0218terge" doar dac\u0103 dori\u021bi s\u0103 r\u0103m\u00een\u0103 publicat \u0219i s\u0103 poat\u0103 fi desc\u0103rcat con\u021binutul dv., dar dori\u021bi s\u0103 v\u0103 elibera\u021bi l\u0103\u021bimea de band\u0103. Asigura\u021bi-v\u0103 c\u0103 procesul de \u00eenc\u0103rcare a fost terminat \u00eenainte de a face asta (cum?).\n\nClica\u021bi pe "Anuleaz\u0103" dac\u0103 dori\u021bi s\u0103 \u00eenl\u0103tura\u021bi complet con\u021binutul publicat de dv. de la %3, \u0219i folosi\u021bi butonul (X) \u00een panoul de Con\u021binut Publicat din tabul "Public\u0103".\n\nAjutor suplimentar.\n\n v3.mb.delPublished.delete=\u0218ter&ge v3.mb.delPublished.cancel=&Anuleaz\u0103 v3.mb.openFile.title=Deschide Fi\u0219ierul v3.mb.openFile.text.known=Acest con\u021binut nu e suportat momentan de c\u0103tre Redorul Vuze [Player]. Pentru ajutor consulta\u021bi acest Ghid de Redare alc\u0103tuit de comunitate.\n\nFi\u0219ierul pare s\u0103 fie de tipul: %2 (%3)\n v3.mb.openFile.text.unknown=Acest con\u021binut nu e suportat momentan de c\u0103tre Redorul Vuze [Player]. Pentru ajutor consulta\u021bi acest Ghid de Redare alc\u0103tuit de comunitate.\n\nExtensia Fi\u0219ierului : %2\n v3.mb.openFile.button.play=Red\u0103 v3.mb.openFile.button.cancel=Anuleaz\u0103 v3.mb.openFile.button.guide=Ghidul Red\u0103rii cu Vuze v3.mb.openFile.remember=Deschide mereu fi\u0219ierele f\u0103r\u0103 a m\u0103 \u00eentreba v3.mb.PlayFileNotFound.title=Fi\u0219ier Neg\u0103sit v3.mb.PlayFileNotFound.text=Fi\u0219ierele pentru '%1' au fost \u0219terse sau s\u00eent absente. v3.mb.PlayFileNotFound.button.remove=\u0218terge din Vuze v3.mb.PlayFileNotFound.button.redownload=Redescarc\u0103 Fi\u0219ierele v3.mb.PlayFileNotFound.button.find=G\u0103se\u0219te Manual.. v3.mb.deletePurchased.title=\u0218terge Con\u021binutul Cump\u0103rat v3.mb.deletePurchased.text=Sigur dori\u021bi s\u0103 \u0219terge\u021bi con\u021binutul '%1'?\n\nAcesta este un con\u021binut pe care fie l-a\u021bi cump\u0103rat, fie este nevoie s\u0103 v\u0103 autentifica\u021bi pentru a-l desc\u0103rca. v3.mb.deletePurchased.button.delete=\u0218ter&ge v3.mb.deletePurchased.button.cancel=&Anuleaz\u0103 v3.topbar.menu.show.plugin=Zona Extensiilor v3.topbar.menu.show.search=Caut\u0103 v3.topbar.menu.show.frog=Brotacul Albastru splash.initializeCore=Ini\u021bializez Nucleul splash.initializeUIElements=Ini\u021bializez Elementele Interfe\u021bei ConfigView.section.transfer.autospeedbeta=Autovitez\u0103-Beta # ConfigView.section.ipfilter.peerblocking.group=Blocarea Partenerilor ConfigView.section.ipfilter.autoload.group=Auto\u00eenc\u0103rcare ConfigView.section.ipfilter.autoload.file=Fi\u0219ierul cu filtre IP de auto\u00eenc\u0103rcat ConfigView.section.ipfilter.autoload.info=Suport\u0103 formatele DAT (eMule), P2P (PeerGuardian, splist) \u0219i P2B v1,2,3 (PeerGuardian 2). Fi\u0219ierul poate fi stocat local sau pe internet (URL), \u00een format arhivat (zip, gzip) sau \u00een format text simplu. Adresele (URL-urile) vor fi redesc\u0103rcate automat dup\u0103 7 zile, \u00een timp ce fi\u0219ierele locale vor fi re\u00eenc\u0103rcate la trecerea a un minut de c\u00eend au fost \u00eenlocuite/modificate. ConfigView.section.ipfilter.autoload.loadnow=\u00cencarc\u0103 Acum splash.loadIpFilters=\u00cencarc Filtrele IP.. SpeedTestWizard.set.upload.title=Seteaz\u0103 Limitele de \u00cenc\u0103rcare \u0219i Desc\u0103rcare SpeedTestWizard.set.download.label=Limita Vitezei de Desc\u0103rcare: SpeedTestWizard.set.upload.label=Limita Vitezei de \u00cenc\u0103rcare: SpeedTestWizard.name.conf.level.absolute=Absolut SpeedTestWizard.name.conf.level.high=Ridicat SpeedTestWizard.name.conf.level.med=Mediu SpeedTestWizard.name.conf.level.low=Sc\u0103zut SpeedTestWizard.name.conf.level.none=Nimic ConfigView.section.transfer.select=Autovitez\u0103 ConfigView.section.transfer.select.v2=Autovitez\u0103 (beta) mb.azmustclose.title=Eroare de Pornire mb.azmustclose.text=Azureus trebuie s\u0103 se \u00eenchid\u0103 din cauza unei probleme de (re)pornire care a f\u0103cut ca programul s\u0103 fie rulat \u00een mod Adminstrator.\n\nDup\u0103 \u00eenchiderea programului Azureus, redeschide\u021bi-l manual. network.ipv6.prefer.addresses=Prefer\u0103 adresele IPv6 c\u00eend s\u00eent disponibile at\u00eet IPv6 c\u00eet \u0219i IPv4 network.bindError=\u00cembinarea cu socketul serverului a e\u0219uat pentru c\u0103 nu s\u00eent disponibile adrese compatibile, verifica\u021bi set\u0103rile bind-to-IP. network.enforce.ipbinding=For\u021beaz\u0103 leg\u0103rile IP chiar \u0219i c\u00eend intefe\u021bele nu s\u00eent disponibile, \u00eempiedic\u0103 orice conexiuni dac\u0103 nici una dintre interfe\u021bele specificate nu este disponibil\u0103 DHTView.title.full_v6=Baz\u0103 de Date Distribuit\u0103 IPv6 ConfigView.pluginlist.loadSelected=\u00cencarc\u0103 Selectatele SpeedView.stats.asn=Re\u021bea: SpeedView.stats.estupcap=Vit. Max. \u00cenc\u0103rcare: SpeedView.stats.estdowncap=Vit. Max. Desc\u0103rcare: SpeedView.stats.unknown=Necunoscut SpeedView.stats.estimate=Estimat\u0103 SpeedView.stats.measured=M\u0103surat\u0103 SpeedView.stats.measuredmin=Min M\u0103surat\u0103 SpeedView.stats.manual=Fix\u0103 ConfigView.section.transfer.autospeed.networks=Detaliile Re\u021belei ConfigView.section.transfer.autospeed.resetnetwork=Reseteaz\u0103 detaliile re\u021belei ConfigView.section.transfer.autospeed.network.info=Limitele \u00een cauz\u0103 s\u00eent de obicei calculate automat \u00een timpul desc\u0103rc\u0103rii sau s\u00eent rezultatul unui test de vitez\u0103. Dac\u0103 dori\u021bi s\u0103 le specifica\u021bi manual utiliza\u021bi op\u021biunile de mai jos.\nToate limitele \u00een afara celor 'fixate' vor fi \u00een consecin\u021b\u0103 ajustate automat dac\u0103 e nevoie. \nIntroduce\u021bi valoarea \u0219i apoi selecta\u021bi tipul ei. Lua\u021bi aminte c\u0103 vitezele s\u00eent \u00een %1. dialog.uiswitcher.restart.title=Comutatorul de Interfa\u021b\u0103: E Necesar\u0103 Repornirea Vuze dialog.uiswitcher.restart.text=Vuze trebuie repornit pentru a se trece la noua interfa\u021b\u0103. TrayWindow.menu.close=\u00cenchide Co\u0219ul de Desc\u0103rcare # Used for peers which we can't determine. PeerSocket.unknown=Necunoscut PeerSocket.fake_client=FALS PeerSocket.bad_peer_id=ID partener gre\u0219it PeerSocket.mismatch_id=nepotrivire PeerSocket.unknown_az_style=Necunoscut %1/%2 PeerSocket.unknown_shadow_style=Necunoscut %1/%2 OpenTorrentWindow.mb.askCreateDir.title=Dosarul de Destina\u021bie nu exist\u0103 OpenTorrentWindow.mb.askCreateDir.text=Dosarul de destina\u021bie '%1' nu exist\u0103.\n\n\u00cel creez acum? SpeedView.stats.estimatechoke=Estimat\u0103 (g\u00eetuire) ConfigTransferAutoSpeed.upload.capacity.usage=Folosirea Capacit\u0103\u021bii de \u00cenc\u0103rcare ConfigTransferAutoSpeed.mode=Mod: ConfigTransferAutoSpeed.capacity.used=% Utilizat din Capacitate ConfigTransferAutoSpeed.while.downloading=Descarc: ConfigTransferAutoSpeed.set.dht.ping=Seteaz\u0103 Pingul DHT: ConfigTransferAutoSpeed.set.point=seteaz\u0103 punctul (ms) ConfigTransferAutoSpeed.set.tolerance=toleran\u021ba (ms) ConfigTransferAutoSpeed.ping.time.good=Bun: ConfigTransferAutoSpeed.ping.time.bad=R\u0103u: ConfigTransferAutoSpeed.adjustment.interval=Intervalul de ajustare: ConfigTransferAutoSpeed.skip.after.adjust=Sari dup\u0103 ajustare: GeneralView.label.distributedCopies=Copii Distribuite: PiecesView.DistributionView.title=Distribu\u021bia P\u0103r\u021bilor PiecesView.DistributionView.NoAvl=P\u0103r\u021bi Nedisponibile PiecesView.DistributionView.SeedAvl=Contribu\u021bia Donatori Disp. PiecesView.DistributionView.PeerAvl=Contribu\u021bia Disp. Parteneri PiecesView.DistributionView.RarestAvl=Cele Mai Rare P\u0103r\u021bi: %1 (Avl:%2) PiecesView.DistributionView.weHave=P\u0103r\u021bi Avute PiecesView.DistributionView.theyHave=P\u0103r\u021bi avute de partener PiecesView.DistributionView.weDownload=P\u0103r\u021bi Desc\u0103rcate PeersView.gain=C\u00ee\u0219tig PeersView.gain.info=Cantitatea de date desc\u0103rcate - \u00eenc\u0103rcate unix.script.new.title=E disponibil un nou Script de Pornire Vuze unix.script.new.text=E disponibil un nou script de pornire pt. Vuze \u0219i a fost salvat \u00een '%1'.\n\nEste recomandat s\u0103 p\u0103r\u0103si\u021bi Vuze acum \u0219i s\u0103 comuta\u021bi la acest script ('%2').\n\nDac\u0103 a\u021bi f\u0103cut modific\u0103ri importante la scriptul de pornire, vede\u021bi AzureusWiki: Unix Script.\n\nDac\u0103 a\u021bi instalat Vuze printr-o distribu\u021bie de GNU/Linux (yum, apt-get, etc), este recomandat s\u0103-l reinstala\u021bi folosind pachetul de la Pagina Vuze de la Sourceforge Page (Ve\u021bi avea aceea\u0219i interfa\u021b\u0103 ca \u0219i acum) unix.script.new.button.quit=P\u0103r\u0103se\u0219te Acum unix.script.new.button.continue=Am s\u0103-l fac mai t\u00eerziu unix.script.new.button.asknomore=Nu-mi mai spune din nou unix.script.new.auto.title=Nou Script de Pornire Vuze unix.script.new.auto.text=E disponibil un nou Script de Pornire Vuze.\n\nEste recomandat s\u0103 reporni\u021bi Vuze acum. Content.alert.notuploaded.button.stop=&Opre\u0219te Content.alert.notuploaded.button.continue=&Continu\u0103 Donarea Content.alert.notuploaded.button.abort=&Nu P\u0103r\u0103si ConfigView.label.checkOnSeeding=Efectueaz\u0103 \u00een fundal reverificarea p\u0103r\u021bilor \u00een timpul don\u0103rii ConfigView.label.ui_switcher=Arat\u0103 Selectorul de Interfe\u021be Vuze ConfigView.label.ui_switcher_button=Arat\u0103 SpeedTestWizard.test.panel.explain=M\u0103sura\u021bi viteza protocolului Vuze. Selecta\u021bi tipul testului de vitez\u0103 \u0219i modul de criptare. Vizita\u021bi pagina wiki Vuze pentru a afla detalii despre test. Testul se va opri automat dac\u0103 dureaz\u0103 mai mult de minute. De obicei durata unui test nu dep\u0103\u0219e\u0219te un minut. SpeedTestWizard.set.upload.hint=Seteaz\u0103 valorile limit\u0103 pentru desc\u0103rcare \u0219i \u00eenc\u0103rcare folosite la algoritmul de Autovitez\u0103. SpeedTestWizard.set.upload.panel.explain=Limitele setate aici s\u00eent folosite de algoritmul de Autovitez\u0103. Seta\u021bi limitele de transfer \u0219i cele de \u00eencredere.\n\nVitezele conexiunii s\u00eent de multe ori exprimate \u00een "bi\u021bi pe secund\u0103" - totu\u0219i valoarea de mai jos e exprimat\u0103 \u00een "kilobai\u021bi pe secund\u0103". SpeedTestWizard.set.limit.conf.level=\u00cencredere SpeedTestWizard.finish.panel.auto.speed=Autoviteza e : SpeedTestWizard.finish.panel.auto.speed.seeding=Autoviteza \u00een timpul don\u0103rii e : ConfigTransferAutoSpeed.add.comment.to.log.group=Adaug\u0103 comentariu la jurnalul de debugare ConfigTransferAutoSpeed.add.comment.to.log=Adaug\u0103 comentariu: ConfigTransferAutoSpeed.log.button=Jurnal ConfigTransferAutoSpeed.algorithm.selector=Selector al Autovitezei ConfigTransferAutoSpeed.algorithm=Algoritm: ConfigTransferAutoSpeed.auto.speed.classic=Autovitez\u0103(clasic) ConfigTransferAutoSpeed.auto.speed.beta=Autovitez\u0103(beta) ConfigTransferAutoSpeed.data.update.frequency=Frecven\u021ba de Actualizare Alert.failed.update=Instalarea a cel pu\u021bin o component\u0103 a e\u0219uat. Vezi AzureusWiki: Failed Update OpenTorrentWindow.mb.existingFiles.partialList=(List\u0103 par\u021bial\u0103. Mai multe fi\u0219iere exist\u0103 deja) TableColumn.header.bad_avail_time.info=Ultima oar\u0103 c\u00eend a fost disponibil\u0103 o copie complet\u0103 a desc\u0103rc\u0103rii TableColumn.header.bad_avail_time=Copie Complet\u0103 Descoperit\u0103 MyTorrentsView.menu.exporthttpseeds=Export\u0103 \u00een cliplan\u0219et\u0103 adresele (URL) donatorilor prin HTTP SWT.alert.erroringuithread=A ap\u0103rut o eroare nea\u0219teptat\u0103 \u00een interfa\u021b\u0103, ar putea apare \u0219i alte erori. ConfigView.label.minannounce=Timpul minim \u00een secunde \u00eentre anun\u021burile trackerului ConfigView.label.maxnumwant=Limiteaz\u0103 num\u0103rul de parteneri pe care \u00eel poate returna trackerul ConfigView.label.announceport=Ignor\u0103 portul TCP implicit pentru anun\u021burile despre tracker, PEX \u0219i DHT\n[l\u0103sat gol: nu ignora, 0: f\u0103r\u0103 conexiuni intr\u00eende] ConfigView.label.noportannounce=Nu anun\u021ba portul de ascultare c\u0103tre tracker (aceasta nu afecteaz\u0103 PEX, DHT) ConfigView.label.maxseedspertorrent=Nr. max. de donatori per torent [0: nelimitat] wizard.webseed=Adaug\u0103 la torent sursele HTTP wizard.webseed.title=Donatori HTTP wizard.webseed.configuration=Configureaz\u0103 Donatorii HTTP wizard.webseed.adding=Adaug Donatori HTTP GeneralView.label.private=Torent Privat: GeneralView.yes=da GeneralView.no=nu ConfigView.label.userequestlimiting=Folose\u0219te fasonarea [throttling] solicit\u0103rilor \u00een loc de citirile \u00eent\u00eerziate pt. a limita viteza de desc\u0103rcare (f\u0103r\u0103 efect dac\u0103 viteza de desc\u0103rcare e nelimitat\u0103) ConfigView.label.userequestlimiting.tooltip=Limitarea solicit\u0103rilor nu e at\u00eet de fluent\u0103 ca \u0219i citirile \u00eent\u00eerziate, dar permite prioritizarea desc\u0103rc\u0103rilor pe baza pozi\u021biei \u00een coada de a\u0219teptare \u0219i poate cre\u0219te performan\u021ba re\u021belei ConfigView.label.userequestlimitingpriorities=Focalizeaz\u0103 viteza de desc\u0103rcare pe v\u00eerful cozii de desc\u0103rcare c\u00eend a fost atins\u0103 limita vitezei de desc\u0103rcare ConfigView.section.logging.timestamp=Formatul marcajului de timp pt. fi\u0219ierele jurnal Peers.column.timetocomplete=Timp R\u0103mas Peers.column.timetocomplete.info=Timp r\u0103mas p\u00een\u0103 c\u00eend termin\u0103 partenerul ConfigView.section.interface.display.suppress.file.download.dialog=Suprim\u0103 dialogul popup despre desc\u0103rcarea fi\u0219ierului ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Arat\u0103 progresul desc\u0103rc\u0103rii fi\u0219ierelor \u00een bara de stare \u00een loc de dialogul popup FileDownload.canceled=Desc\u0103rcarea unui fi\u0219ier torent a fost anulat\u0103 cu succes de utilizator: %1 Progress.reporting.status.canceled=Anulat Progress.reporting.status.finished=Terminat Progress.reporting.status.retrying=Re\u00eencerc... Progress.reporting.action.label.retry.tooltip=Re\u00eencearc\u0103 Opera\u021bia Progress.reporting.action.label.remove.tooltip=\u0218terge acest Raport de Progres din istoric Progress.reporting.action.label.cancel.tooltip=Anuleaz\u0103 opera\u021bia Progress.reporting.action.label.detail=Detalii Progress.reporting.default.error=E\u0219uat Progress.reporting.no.reports.to.display=Nu exist\u0103 Rapoarte de Progres ce pot fi afi\u0219ate acum Progress.reporting.no.history.to.display=Nu exist\u0103 mesaje detaliate de afi\u0219at Progress.reporting.detail.history.limit=Limita de mesaje detaliate (%1) pentru acest Raportor de Progres a fost dep\u0103\u0219it\u0103; mesajele urm\u0103toare nu vor mai fi ad\u0103ugate la istoric Progress.reporting.statusbar.button.tooltip=Arat\u0103 Fereastra Raportului de Progres webui.bindip=Leag\u0103 IP-ul - nu e necesar de obicei (*) v3.MainWindow.text.log.in=Autentificare v3.MainWindow.text.log.out=Dezautentificare v3.MainWindow.text.get.started=\u00censcriere v3.MainWindow.text.my.account=Contul Meu v3.MainWindow.text.my.profile=Profil OpenTorrentWindow.simple.open=Loca\u021bia Torentului (Fi\u0219ier, Adres\u0103, Ha\u0219) Progress.reporting.window.remove.auto=\u0218terge automat itemurile inactive Progress.reporting.window.remove.auto.tooltip=\u0218terge automat din vedere toate procesele terminate, e\u0219uate sau anulate Progress.reporting.window.remove.now=\u0218terge itemurile inactive Progress.reporting.window.remove.now.tooltip=\u0218terge din vederea aceasta toate procesele terminate, e\u0219uate sau anulate dhttracker.tracklimitedwhenonline=Realizeaz\u0103 totu\u0219i urm\u0103rirea resurselor sc\u0103zute \u00een timpul conect\u0103rii pentru popularea \u00eencruci\u0219at\u0103 a roiului TorrentOptionsView.multi.title.short=Op\u021biunile Torentelor TorrentOptionsView.multi.title.full=Op\u021biunile Torentelor MyTorrentsView.menu.open_parent_folder=Deschide Dosarul Con\u021bin\u0103tor ConfigView.section.style.use_show_parent_folder=Folose\u0219te "%1" \u00een loc de "%2" \u00een meniurile torentelor ConfigView.section.style.use_show_parent_folder.tooltip=Activarea acesei op\u021biuni v\u0103 va permite s\u0103 deschide\u021bi dosarul con\u021bin\u0103tor \u00een aplica\u021bia corect\u0103 de administrare a fi\u0219ierelor.\nTotu\u0219i, asta ar putea \u00eensemna c\u0103 locul de salvare a desc\u0103rc\u0103rilor nu este selectat automat. PeerManager.status.ps_disabled=Sursa trackerului partenerilor este dezactivat\u0103 ConfigView.section.stats.exportfiles=Detaliile Fi\u0219ierului Exportat updater.cant.write.to.app.title=Nu pot scrie \u00een dosarul aplica\u021biei updater.cant.write.to.app.details=\u00cen dosarul "%1" nu se poate scrie.\n\nAceasta va \u00eempiedica aplicarea actualiz\u0103rilor softului.\n\nConsulta\u021bi wikiulpentru detalii. plugin.install.class_version_error=Aceast\u0103 extensie necesit\u0103 o versiune mai nou\u0103 de Java pentru a putea rula. v3.MainWindow.tab.minilibrary=Desc\u0103rc\u0103ri v3.MainWindow.tab.events=Activitate button.columnsetup.tooltip=Configureaz\u0103 Coloanele v3.activity.remove.title=\u0218terge Intrarea Activit\u0103\u021bii v3.activity.remove.text=Sigur dori\u021bi s\u0103 \u00eenl\u0103tura\u021bi eviden\u021ba activit\u0103\u021bii '%1'? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=\u00cenchide Menu.show.torrent.menu=Arat\u0103 Meniul Torentelor Menu.show.torrent.menu.tooltip=Arat\u0103 meniul torentelor deasupra barei de meniuri #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=Starea Re\u021belei plugin.aznetstatus.pingtarget=Ping/traceroute spre \u021bint\u0103 ConfigView.section.style.usePathFinder=Folose\u0219te "G\u0103sitorul de C\u0103i" \u00een loc de "G\u0103sitor" menu.sortByColumn=Sorteaz\u0103 dup\u0103 %1 MyTorrentsView.menu.manual.per_peer=Manual\u0103 (per partener) MyTorrentsView.menu.manual.shared_peers=Manual\u0103 (pt. to\u021bi partenerii) v3.button.removeActivityEntry=\u0218terge Intrarea Activit\u0103\u021bii v3.splash.initSkin=Ini\u021bializez Costumul Interfe\u021bei v3.splash.hookPluginUI=Activez Interfa\u021ba Extensiilor OpenTorrentWindow.mb.notTorrent.cannot.display=Nu pot afi\u0219a corect datele MainWindow.menu.window.zoom.maximize=Maximizeaz\u0103 MainWindow.menu.window.zoom.restore=Restaureaz\u0103 ImageResizer.image.too.small=Imaginea oferit\u0103 e prea mic\u0103, alege\u021bi alta (trebuie s\u0103 fie de cel pu\u021bin %1 x %2) ImageResizer.title=Aceast\u0103 unealt\u0103 v\u0103 permite s\u0103 previziona\u021bi modul \u00een care miniatura va ar\u0103ta pe Platforma Vuze ImageResizer.move.image=Muta\u021bi imaginea prin tragere ImageResizer.move.image.with.slider=Muta\u021bi imaginea prin tragere, redimensiona\u021bi-o folosind glisorul de mai jos security.crypto.title=Cheia pentru Acces Criptat security.crypto.encrypt=Introduce\u021bi o parol\u0103 pentru a proteja cheia de criptare generat\u0103. Nu uita\u021bi parola pentru c\u0103 nu exist\u0103 nici o cale pentru a o recupera! security.crypto.decrypt=Introduce\u021bi parola pentru a debloca cheia de criptare. security.crypto.reason=Motivul opera\u021biunii security.crypto.password=Parol\u0103 security.crypto.password2=Reintroduce\u021bi parola security.crypto.persist_for=Perioada de persisten\u021b\u0103 a parolei security.crypto.persist_for.dont_save=Nu salva security.crypto.persist_for.session=Aceast\u0103 sesiune security.crypto.persist_for.day=1 zi security.crypto.persist_for.week=1 s\u0103pt\u0103m\u00een\u0103 security.crypto.persist_for.30days=30 de zile security.crypto.persist_for.forever=Mereu security.crypto.password.mismatch.title=Eroare a parolei security.crypto.password.mismatch=Parolele introduse nu s\u00eent identice, reintroduce\u021bi-le. ConfigView.section.security.group.crypto=Chei Publice/Private ConfigView.section.security.resetkey=Reseteaz\u0103 cheile ConfigView.section.security.resetkey.warning.title=Avertisment despre Pierderea de Date ConfigView.section.security.resetkey.warning=Sigur dori\u021bi s\u0103 reseta\u021bi cheile de criptare? Dac\u0103 ve\u021bi face asta toate informa\u021biile criptate cu ele vor fi PIERDUTE DEFINITIV. De asemenea to\u021bi partenerii care posed\u0103 cheia dv. public\u0103 nu vor mai putea comunica cu dv. p\u00een\u0103 la primirea cheii noi. Deci nu face\u021bi asta dac\u0103 nu s\u00eente\u021bi sigur c\u0103 proceda\u021bi bine. ConfigView.section.security.unlockkey=Deblocheaz\u0103 \u00een mod explicit cheile ConfigView.section.security.unlockkey.button=Deblocheaz\u0103 ConfigView.section.security.publickey=Cheie Public\u0103 ConfigView.section.security.publickey.undef=Nedefinit\u0103 \u00eenc\u0103 ConfigView.section.security.resetkey.error.title=Opera\u021biunea a e\u0219uat ConfigView.section.security.resetkey.error=Resetarea cheilor a e\u0219uat ConfigView.section.security.unlockkey.error=Deblocarea cheii a e\u0219uat - parol\u0103 incorect\u0103 ConfigView.copy.to.clipboard.tooltip=Copiaz\u0103 \u00een Cliplan\u0219et\u0103 Views.plugins.azbuddy.title=Prieteni Browser.popup.error.no.access=S-a produs o eroare la \u00eencercarea de accesare a unei resurse distante. Re\u00eencerca\u021bi mai t\u00eerziu. ConfigView.label.queue.stoponcebandwidthmet=Nu mai porni alte torente dac\u0103 a fost atins\u0103 limita vitezei de desc\u0103rcare ConfigView.section.style.forceMozilla=For\u021beaz\u0103 Vuze s\u0103 foloseasc\u0103 Mozilla pentru gadgeturile Exploratorului [xulrunner sau firefox 3 s\u00eent necesare; repornirea e \u0219i ea necesar\u0103] ConfigView.section.style.xulRunnerPath=Specific\u0103 manual calea XulRunner / Firefox (pentru FF3; necesit\u0103 repornire) azbuddy.name=Prieteni azbuddy.enabled=Activat azbuddy.disabled=Extensia e dezactivat\u0103, schimba\u021bi setarea folosind configurarea extensiei. azbuddy.nickname=Porecl\u0103 azbuddy.msglog.title=Informa\u021bii despre Prieten azbuddy.addtorrent.title=Accepta\u021bi Desc\u0103rcarea? azbuddy.addtorrent.msg=Prietenul '%1' v-a trimis '%2'.\nDori\u021bi s\u0103 ad\u0103uga\u021bi aceast\u0103 desc\u0103rcare? azbuddy.contextmenu=Trimite Prietenului azbuddy.ui.mykey=Cheia mea: azbuddy.ui.add=Adaug\u0103 azbuddy.ui.new_buddy=Noua cheie a prietenului: azbuddy.ui.table.name=Nume azbuddy.ui.table.online=Conectat azbuddy.ui.table.last_msg=Ultimul Mesaj azbuddy.ui.menu.remove=\u0218terge azbuddy.ui.menu.copypk=Copiaz\u0103 Cheia Public\u0103 azbuddy.ui.menu.send=Trimite Mesaj azbuddy.ui.menu.send_msg=Introduce\u021bi textul de trimis prietenilor azbuddy.ui.menu.ygm=Trimite YGM azbuddy.ui.menu.enc=Cripteaz\u0103 Cliplan\u0219eta azbuddy.ui.menu.dec=Decripteaz\u0103 Cliplan\u0219eta azbuddy.ui.menu.sign=Semneaz\u0103 Cliplan\u0219eta azbuddy.ui.menu.verify=Verific\u0103 Cliplan\u0219eta azbuddy.ui.table.lastseen=Ultima Apari\u021bie Button.retry=&Re\u00eencearc\u0103 Button.ignore=&Ignor\u0103 DHTView.general.skew=Asimetrie: azbuddy.ui.table.msg_in=Msj Prim azbuddy.ui.table.msg_out=Msj Trim v3.MainWindow.menu.view.footer=Bara de Prieteni azbuddy.downspeed=KB/s max viteza de desc\u0103rcare a prietenului [0: nelimitat] security.crypto.badpw=Parola introdus\u0103 nu e corect\u0103 ConfigView.section.security.backupkeys=Salvgardeaz\u0103 cheile \u00eentr-un fi\u0219ier ConfigView.section.security.backupkeys.button=Salvgardeaz\u0103 ConfigView.section.security.restorekeys=Restaureaz\u0103 cheile dintr-un fi\u0219ier ConfigView.section.security.restorekeys.button=Restaureaz\u0103 ConfigView.section.security.op.error.title=Opera\u021biune E\u0219uat\u0103 ConfigView.section.security.op.error=Terminarea opera\u021biunii a e\u0219uat:\n %1 ConfigView.section.security.restart.title=Repornire Necesar\u0103 ConfigView.section.security.restart.msg=Vuze va reporni pentru a termina opera\u021biunea. ConfigView.section.security.system.managed=Protec\u021bie a cheii administrat\u0103 de sistem azbuddy.ui.table.msg_queued=Pus \u00een Coad\u0103 azbuddy.ui.menu.chat=Discut\u0103 azbuddy.chat.title=Taifas Vuze [Chat] azbuddy.chat.says=%1 spune: Button.bar.show=Arat\u0103 Button.bar.hide=Ascunde Button.bar.share=Partajeaz\u0103 Button.bar.add=Adaug\u0103 Prieteni Button.bar.edit=Editeaz\u0103 Button.bar.edit.cancel=Editare Terminat\u0103 v3.MainWindow.menu.view.pluginbar=Bara de Extensii MainWindow.dialog.select.vuze.file=Selecteaz\u0103 Fi\u0219ierul Vuze MainWindow.menu.file.open.vuze=Fi\u0219ier Vuze... metasearch.addtemplate.title=Instalez \u0218ablonul de C\u0103utare? metasearch.addtemplate.desc=S\u00eente\u021bi sigur c\u0103 dori\u021bi s\u0103 instala\u021bi \u0219ablonul de c\u0103utare numit '%1'? v3.share.private.title=Partajeaz\u0103 Torentul v3.share.private.text=Torentul selectat e marcat ca privat.\n\nNu pute\u021bi partaja torentele private. metasearch.addtemplate.dup.title=Duplicheaz\u0103 \u0218ablonul metasearch.addtemplate.dup.desc=\u0218ablonul de c\u0103utare %1 e deja instalat metasearch.export.select.template.file=Salveaz\u0103 \u0218ablonul metasearch.import.select.template.file=Deschide \u0218ablonul dialog.uiswitch.title=Comut\u0103 la Interfa\u021ba Vuze dialog.uiswitch.text=Trebuie s\u0103 rula\u021bi interfa\u021ba Vuze pentru a folosi aceast\u0103 facilitate.\n\nVuze trebuie repornit. dialog.uiswitch.button=Comut\u0103 la Interfa\u021ba Vuze azbuddy.tracker.enabled=Activeaz\u0103 'Accelerarea Prietenilor' pentru a prioritiza transferul cu prietenii azbuddy.protocolspeed=KB/s max dep\u0103\u0219irea protocolului de c\u0103tre prieten v3.MainWindow.button.download=Descarc\u0103 v3.MainWindow.button.run=Deschide Fi\u0219ierul Desc\u0103rcat v3.activity.header.downloads=Desc\u0103rc\u0103ri v3.activity.header.vuze.news=\u0218tiri Vuze message.taking.too.long=Se pare c\u0103 opera\u021biunea dureaz\u0103 mai mult dec\u00eet era a\u0219teptat. \nAp\u0103sa\u021bi 'ESC' dac\u0103 dori\u021bi s\u0103 o anula\u021bi. message.status.success=Succes azbuddy.tracker.bbb.status.title=Accelereaz\u0103 Prietenii azbuddy.tracker.bbb.status.title.tooltip=Dublu-clic pentru detalii azbuddy.tracker.bbb.status.idle=F\u0103r\u0103 Accelerare azbuddy.tracker.bbb.status.nli=Autentificare Necesar\u0103 azbuddy.tracker.bbb.status.in=S\u00eent Accelerat azbuddy.tracker.bbb.status.out=Prieteni Accelera\u021bi Acum v3.MainWindow.search.go.tooltip=Execut\u0103 C\u0103utarea v3.MainWindow.search.last.tooltip=\u00centoarce-te la Rezultatele C\u0103ut\u0103rii metasearch.addtemplate.done.title=\u0218ablon Ad\u0103ugat metasearch.addtemplate.done.desc=\u0218ablonul '%1' a fost ad\u0103ugat cu succes.\nVa fi utilizat la urm\u0103toarea c\u0103utare! ConfigView.section.security.nopw=Nu a fost introdus\u0103 nici o parol\u0103 ConfigView.section.security.nopw_v=Nu este disponibil\u0103 nici o parol\u0103, autentifica\u021bi-v\u0103 la Vuze fileplugininstall.install.title=Instalez Extensia? fileplugininstall.install.desc=Sigur dori\u021bi s\u0103 instala\u021bi extensia '%1', versiunea %2? fileplugininstall.duplicate.title=Extensie Duplicat\u0103 fileplugininstall.duplicate.desc=Extensia '%1', versiunea %2 e deja instalat\u0103 azbuddy.online_status=Stare azbuddy.os_online=Conectat azbuddy.os_away=Absent azbuddy.os_not_avail=Indisponibil azbuddy.os_busy=Ocupat azbuddy.os_offline=Neconectat azbuddy.ui.menu.disconnect=Deconecteaz\u0103 azbuddy.enable_chat_notif=Activeaz\u0103 notific\u0103rile \u00een taifas [chat] progress.window.msg.progress=A\u0219tepta\u021bi ca opera\u021biunea s\u0103 se termine ConfigView.section.connection.advanced.read_select=Expirarea citirii select\u0103rii (msec, implicit %1) ConfigView.section.connection.advanced.read_select_min=A\u0219teptarea minim\u0103 a citirii select\u0103rii (msec, implicit %1) ConfigView.section.connection.advanced.write_select=Expirarea scrierii select\u0103rii (msec, implicit %1) ConfigView.section.connection.advanced.write_select_min=A\u0219teptarea minim\u0103 a scrierii select\u0103rii (msec, implicit %1) DetailedListView.title=List\u0103 Detaliat\u0103 ConfigView.section.connection.network.max.outstanding.connect.attempts=Nr. max. de conexiuni ie\u0219inde existente plugins.init.force_enabled=Vuze a detectat c\u0103 extensia "%1" a fost dezactivat\u0103 - ea a fost reactivat\u0103 pentru a permite func\u021bionarea corect\u0103 a lui Vuze. ConfigView.section.connection.prefer.udp=Prefer\u0103 conexiunile UDP subscript.add.title=Instalez Abonamentul? subscript.add.desc=Sigur dori\u021bi s\u0103 instala\u021bi abonamentul '%1'? subscript.add.dup.title=Abonament Duplicat subscript.add.dup.desc=Abonamentul '%1' e deja instalat. subscript.add.upgrade.title=Supragradez Abonamentul? subscript.add.upgrade.desc=Sigur dori\u021bi s\u0103 supragrada\u021bi [upgrade] abonamentul '%1'? subscript.add.upgradeto.desc=Versiunea %1 a abonamentului '%2' e disponibil\u0103.\nDori\u021bi s\u0103 actualiza\u021bi? azsubs.contextmenu.addassoc=Adaug\u0103 asociere a abonamentului azsubs.contextmenu.lookupassoc=Vezi asocierile abonamentului iconBar.start=Porne\u0219te iconBar.stop=Opre\u0219te iconBar.remove=\u0218terge iconBar.up=Sus iconBar.down=Jos iconBar.run=Deschide iconBar.editcolumns=Configureaz\u0103 Coloanele iconBar.top=Mut\u0103 la \u00cenceput iconBar.bottom=Mut\u0103 la sf\u00eer\u0219it iconBar.queue=Porne\u0219te iconBar.open=Adaug\u0103 Torent iconBar.share=Partajeaz\u0103 iconBar.share.tooltip=Partajeaz\u0103 Con\u021binutul iconBar.details=Detalii iconBar.comment=Comentariu iconBar.play=Red\u0103 iconBar.queue.tooltip=Pune \u00een Coad\u0103 v3.MainWindow.menu.view.sidebar=Panoul Lateral v3.MainWindow.menu.view.actionbar=Bara de Ac\u021biuni v3.MainWindow.menu.view.toolbars=Bare de Unelte ump.install=Actualizare Rapid\u0103 \u00cen Curs:\nInstalez o mic\u0103 extensie de redare necesar\u0103 acestui video. subscriptions.listwindow.title=G\u0103sitor de Abonamente subscriptions.listwindow.autochecktext=Vuze poate g\u0103si abonamente similare cu con\u021binutul din Arhiv\u0103. Dori\u021bi s\u0103 activa\u021bi aceast\u0103 facilitate? subscriptions.listwindow.loadingtext=Caut abonamente corelate cu %1 subscriptions.listwindow.failed=Nu au fost g\u0103site abonamente subscriptions.listwindow.popularity=Popularitate subscriptions.listwindow.popularity.unknown=Necunoscut subscriptions.listwindow.name=Nume subscriptions.listwindow.subscribe=Aboneaz\u0103 TableColumn.header.azsubs.ui.column.subs=Abonare subscriptions.listwindow.popularity.reading=Citesc... PluginDeprecation.log.start=Aceast\u0103 fereastr\u0103 con\u021bine informa\u021bii despre extensii ce folosesc facilit\u0103\u021bi care vor fi fi \u00eenl\u0103turate din versiunile viitoare de Vuze.\nNu e nevoie s\u0103 dezinstala\u021bi extensiile, trebuie doar s\u0103 le actualiza\u021bi la ultima versiune.\nDac\u0103 rula\u021bi deja ultima versiune, atunci copia\u021bi con\u021binutul acestei ferestre \u0219i posta\u021bi-l pe forumul aflat aici:\n \t%1\n\n PluginDeprecation.log.details=---------\nIDENTIFICATOR: %1\nCONTEXT: %2\n\n*** BEGIN TRACE ***\n%3*** END TRACE ***\n\n PluginDeprecation.view=Debugheaz\u0103 Extensia PluginDeprecation.alert=O extensie a \u00eencercat s\u0103 foloseasc\u0103 o facilitate ce va fi \u00eenl\u0103turat\u0103 pe viitor - deschide\u021bi jurnalul de Debugare a Extensiilor pentru mai multe informa\u021bii. TableColumn.header.Thumbnail=Iconi\u021b\u0103 TableColumn.header.Thumbnail.info=Imagine miniaturizat\u0103 pentru con\u021binut din re\u021beaua Vuze; Pentru con\u021binutul de alt\u0103 provenien\u021b\u0103 s\u00eent folosite iconi\u021bele sistemului de operare. v3.MainWindow.menu.getting_started=&Prezentare Vuze MainWindow.menu.community=&Comunitate MainWindow.menu.help.faq=\u00centreb\u0103ri Puse &Frecvent MainWindow.menu.community.wiki=&Wikiul Vuze MainWindow.menu.community.forums=Fo&rumul Vuze MainWindow.menu.community.blog=&Blogul Vuze MainWindow.menu.help.support=A&jutor \u0219i Suport externalLogin.title=Logare Necesar\u0103 externalLogin.explanation=\u0218ablonul "%1" necesit\u0103 logare. Dup\u0103 logare, aceast\u0103 fereastr\u0103 se va \u00eenchide automat. Dac\u0103 nu se \u00eent\u00eempl\u0103 asta ap\u0103sa\u021bi pe "gata". externalLogin.explanation.capture=Trebuie s\u0103 v\u0103 loga\u021bi pentru a crea acest \u0219ablon. Dup\u0103 logare, clica\u021bi pe "Gata". Button.done=Gata GeneralView.torrent_created_on_and_by=%1 de %2 Button.continue=Continu\u0103 Button.preview=Previzioneaz\u0103 Subscription.menu.forcecheck=Actualizeaz\u0103 Acum Subscription.menu.clearall=Marcheaz\u0103 Toate Rezultatele ca Citite Subscription.menu.remove=\u0218terge sidebar.Library=Arhiva Torentelor sidebar.LibraryDL=Neterminate sidebar.LibraryCD=Terminate authenticator.location=Loca\u021bie authenticator.details=Detalii v3.MainWindow.menu.showActionBarText=Arat\u0103 Etichetele subscript.import.fail.title=Importare E\u0219uat\u0103 subscript.import.fail.desc=Detalii: %1 Subscription.menu.export=Export\u0103 subscript.export.select.template.file=Salveaz\u0103 Abonamentul Button.remove=\u00cenl\u0103tur\u0103 Button.send=Trimite Button.back=\u00cenapoi sidebar.LibraryUnopened=Nedeschise TableColumn.header.unopened=Nou Unopened.bigView.header=Nou Subscription.menu.deleteall=\u0218terge Toate Rezultatele Subscription.menu.reset=Reseteaz\u0103 la Starea Ini\u021bial\u0103 ConfigView.section.Subscriptions=Abonamente subscriptions.config.maxresults=Num\u0103rul maxim de rezultate p\u0103strate per abonament [0: nelimitat] v3.activity.button.readall=Marcheaz\u0103 Tot ca Citit TableColumn.header.activityNew=Nou TableColumn.header.activityType=Tip TableColumn.header.activityText=Mesaj TableColumn.header.activityDate=Data Ad\u0103ug\u0103rii TableColumn.header.activityActions=Ac\u021biuni Subscription.menu.resetauth=Reseteaz\u0103 Detaliile de Autentificare Search.menu.engines=\u0218abloane Wizard.Subscription.title=Aboneaz\u0103 Wizard.Subscription.optin.title=Activez Abonamentele? #what you've watched? Discover more with a single click... Wizard.Subscription.subscribe.title=Abonamente Disponibile Wizard.Subscription.create.title=Creeaz\u0103 Abonament Nou Button.search=Caut\u0103 Button.save=Salveaz\u0103 Button.add=Adaug\u0103 Button.createNewSubscription=Creeaz\u0103 Abonament Nou Button.availableSubscriptions=Abonamente Disponibile Wizard.Subscription.optin.description=Dac\u0103 activa\u021bi Abonamentele, ve\u021bi putea descoperi unele similare cu con\u021binutul din arhiva dv. Clica\u021bi: Wizard.Subscription.create.search=Caut\u0103 Wizard.Subscription.search.subtitle1=Tasta\u021bi ni\u0219te cuvinte-cheie pentru a crea abonamentul: Wizard.Subscription.search.subtitle2=Ce pot c\u0103uta? Wizard.Subscription.search.subtitle2.sub1=Filme, Spectacole TV, Prezent\u0103ri de filme existente \u00een re\u021beaua Vuze Wizard.Subscription.search.subtitle2.sub2=Torente de pe internet Wizard.Subscription.search.subtitle3=Dup\u0103 ce abonamentul a fost realizat, ve\u021bi primi \u00een panoul lateral actualiz\u0103ri referitoare la rezultatele c\u0103ut\u0103rilor f\u0103cute. Wizard.Subscription.rss.subtitle1=Tasta\u021bi sau lipi\u021bi adresa mai jos: Wizard.Subscription.rss.subtitle2=Mul\u021bi produc\u0103tori ofer\u0103 fluxuri RSS pentru con\u021binutul publicat. G\u0103si\u021bi adresa (URL) fluxului pe situl produc\u0103torului, copia\u021bi-o \u0219i lipi\u021bi-o \u00een c\u00eempul de mai sus, apoi clica\u021bi butonul Salveaz\u0103. Wizard.Subscription.rss.subtitle3=Odat\u0103 salvat, ve\u021bi primi \u00een panoul lateral actualiz\u0103ri referitoare la rezultatele c\u0103ut\u0103rilor specificate \u00een fluxurile RSS. Wizard.Subscription.subscribe.library=Con\u021binut \u00een Arhiv\u0103 Wizard.Subscription.subscribe.subscriptions=Abonamente Similare Wizard.Subscription.subscribe.library.empty=Nu s\u00eent disponibile abonamente?\n \nUita\u021bi-v\u0103 \u00een Re\u021beaua Vuze HD dup\u0103 butonul portocaliu de abonare.\n \nRead more message.confirm.delete.title=Confirma\u021bi \u0218tergerea message.confirm.delete.text=Sigur dori\u021bi s\u0103 \u0219terge\u021bi '%1'? Subscription.menu.properties=Propriet\u0103\u021bi props.window.title=Propriet\u0103\u021bi pentru '%1' subs.prop.is_auto=Autodescarc\u0103 rezultatele noi subs.prop.last_scan=Ultima actualizare reu\u0219it\u0103 subs.prop.last_result=Ultimul rezultat g\u0103sit subs.prop.last_error=Ultima eroare subs.prop.num_read=Num\u0103rul de rezultate citite subs.prop.num_unread=Num\u0103rul de rezultate necitite subs.prop.template=\u0218ablon subs.prop.auth=E necesar\u0103 autentificarea externalLogin.auth_method_proxy=Folose\u0219te metoda extins\u0103 de capturare a fursecurilor [cookies]. Dac\u0103 acest lucru e\u0219ueaz\u0103, trebuie dezactivat\u0103 op\u021biunea \u0219i re\u00eencercat. externalLogin.wait=Pagina se \u00eencarc\u0103, a\u0219tepta\u021bi... TableColumn.menu.date_added.time=Arat\u0103/Ascunde Timpul sidebar.VuzeHDNetwork=Re\u021beaua Vuze HD subs.prop.next_scan=Urm\u0103toarea scanare \u00een subs.prop.assoc=Asocieri subs.prop.version=Versiune subscriptions.column.new.info=Indic\u0103 faptul c\u0103 exist\u0103 unul sau mai multe rezultate noi subscriptions.column.name=Abonament subscriptions.column.nb-results=Total Rezultate subscriptions.column.nb-new-results=Rezultate Noi subscriptions.column.last-checked=Ultima Verificare subscriptions.view.title=Abonamente subs.prop.high_version=A fost descoperit\u0103 o versiune mai nou\u0103 Subscription.menu.upgrade=Activeaz\u0103 supragradarea [upgrade] la o versiune superioar\u0103 metasearch.template.version.bad=\u0218ablonul de c\u0103utare '%1' nu va putea fi instalat dec\u00eet dac\u0103 ve\u021bi supragrada [upgrade] Vuze metasearch.addtemplate.failed.title=Instalare E\u0219uat\u0103 metasearch.addtemplate.failed.desc=Instalare e\u0219uat\u0103 a \u0219ablonului de c\u0103utare: %1 subscription.version.bad=Abonamentul '%1' nu pote fi instalat dec\u00eet dup\u0103 ce supragrada\u021bi [upgrade] Vuze statusbar.feedback=Spune\u021bi-v\u0103 P\u0103rerea statusbar.feedback.tooltip=Clica\u021bi aici pentru a v\u0103 spune p\u0103rerea sidebar.Activity=Notific\u0103ri v3.activity.button.watchall=Marcheaz\u0103 Tot ca Citit subscriptions.view.help.1=Abonarea e disponibil\u0103 oriunde apare subscriptions.view.help.2=Ob\u021bine\u021bi actualiz\u0103ri instantanee ori de c\u00eete ori este disponibil con\u021binut nou pentru desc\u0103rcare. Read more. sidebar.sash.tooltip=F7 arat\u0103/ascunde rapid panoul lateral sidebar.expand.tooltip=Expandeaz\u0103 Panoul Lateral sidebar.dropdown.tooltip=Arat\u0103 panoul lateral \u00een format de meniu subscript.all.subscribed=S\u00eente\u021bi abonat la acest con\u021binut subscript.some.subscribed=S\u00eente\u021bi abonat la unele surse pentru acest con\u021binut.\nClica\u021bi pentru a vedea \u0219i alte surse disponibile. subscript.none.subscribed=Clica\u021bi pentru a vedea abonamentele disponibile pentru acest con\u021binut v3.iconBar.up.tooltip=Mut\u0103 \u00een Sus\n\u021aine\u021bi ap\u0103sat butonul mausului pentru a muta \u00een sus v3.iconBar.down.tooltip=Mut\u0103 \u00een Jos\n\u021aine\u021bi ap\u0103sat butonul mausului pentru a muta \u00een jos TableColumn.header.azsubs.ui.column.subs_link=Asociere TableColumn.header.azsubs.ui.column.subs_link.info=Asociat cu abonamentele Button.deleteContent.fromLibrary=\u0218terge din Arhiva Torentelor Button.deleteContent.fromComputer=\u0218terge de pe Calculator v3.deleteContent.message=\nDori\u021bi s\u0103 \u0219terge\u021bi '%1' de pe calculator sau doar s\u0103-l \u00eenl\u0103tura\u021bi din Arhiva Vuze? v3.MainWindow.menu.view.toolbartext=Text pe Bara de Unelte v3.MainWindow.menu.view.asSimpleList=List\u0103 Simpl\u0103 v3.MainWindow.menu.view.asAdvancedList=List\u0103 Avansat\u0103 v3.MainWindow.menu.view.statusbar=Bara de Stare Subscription.menu.dirtyall=Marcheaz\u0103 Toate Rezultatele ca Citite configureWizard.file.message3=Vuze va desc\u0103rca fi\u0219ierele \u00eentr-un dosar special, pe care pute\u021bi s\u0103-l alege\u021bi aici: v3.deleteContent.applyToAll=Aplic\u0103 ac\u021biunea la toate cele %1 intr\u0103ri selectate ConfigView.label.seeding.firstPriority.ignoreIdleHours=Torente care nu \u00eencarc\u0103 nimic timp de v3.MainWindow.menu.contentnetworks=&Re\u021bele HD v3.MainWindow.menu.contentnetworks.about=Despre Re\u021belele HD Peers.column.as.info=Detalii despre SA-ul partenerului (Sistemul Autonom) ConfigView.label.autoopen.downloadbars=Deschide automat Barele de Desc\u0103rcare c\u00eend ConfigView.label.autoopen=Autodeschide ConfigView.label.autoopen.detailstab=Deschide automat tabul Detalii c\u00eend ConfigView.label.systray=Sistaler ConfigView.label.systray._mac=Iconi\u021ba din Bara de Stare ConfigView.section.interface.legacy=\u00cenvechit v3.MainWindow.menu.contentnetworks.manage=Ad&ministreaz\u0103 Re\u021belele HD azbuddy.ui.menu.cat=Categorii azbuddy.ui.menu.cat.share=Activeaz\u0103 abonamentele pentru prieteni azbuddy.ui.menu.cat.set=Introduce\u021bi categoriile azbuddy.ui.menu.cat.set_msg=List\u0103 de categorii separate prin virgul\u0103, sau 'Tot' azbuddy.ui.menu.cat_subs=Aboneaz\u0103 subs.prop.update_period=Perioada de actualizare azbuddy.enable_cat_pub=Categorii publice la care se pot abona TO\u021aI prietenii dv. (separate prin ',' ) v3.dialog.cnclose.title=%1 \u00cenchis v3.dialog.cnclose.subtitle=Notificare v3.dialog.cnclose.info1=A\u021bi \u00eenchis o Re\u021bea HD v3.dialog.cnclose.info2=Dac\u0103 dori\u021bi s\u0103 redeschide\u021bi aceast\u0103 re\u021bea HD, o pute\u021bi face \u00een meniul "Re\u021bele HD" din partea de sus a ecranului. v3.dialog.cnclose.noshow=Nu ar\u0103ta din nou v3.dialog.cnmanage.title=Administreaz\u0103 Meniul Re\u021belelor HD v3.dialog.cnmanage.intro=Pute\u021bi alege din lista de mai jos re\u021belele de con\u021binut care dori\u021bi s\u0103 fie afi\u0219ate \u00een meniul "Re\u021bele HD" TableColumn.header.#=Nr. TableColumn.header.#.info=Num\u0103rul de Pozi\u021bie/Ordonare TableColumn.header.category.info=Numele categoriei c\u0103reia \u00eei apar\u021bine torentul TableColumn.header.DateCompleted.info=Data la care a fost terminat\u0103 desc\u0103rcarea torentului TableColumn.header.AzProduct.info=Re\u021beaua de con\u021binut de unde provine torentul TableColumn.header.health.info=C\u00eet de s\u0103n\u0103toas\u0103/viabil\u0103 este conexiunea dv. la roiul torentului TableColumn.header.maxuploads.info=Nr. maxim de parteneri c\u0103tre care se poate \u00eenc\u0103rca simultan TableColumn.header.name.info=Numele Torentului TableColumn.header.unopened.info=Fanion care indic\u0103 dac\u0103 torentul a fost redat (deschis) TableColumn.header.savepath.info=Dosarul sau fi\u0219ierul de destina\u021bie pentru datele din torent TableColumn.header.SeedingRank.info=Valoarea rangului sau c\u00eet de mult are nevoie un torent de donare.. O valoare mai mare \u00eenseamn\u0103 o necesitate mai mare. TableColumn.header.shareRatio.info=C\u00eet de mult a\u021bi \u00eenc\u0103rcat (partajat) comparativ cu c\u00eet de mult a\u021bi desc\u0103rcat. TableColumn.header.size.info=M\u0103rimea pe disc a con\u021binutului torentului TableColumn.header.azsubs.ui.column.subs.info=Buton care v\u0103 permite s\u0103 v\u0103 abona\u021bi la fluxul ce con\u021bine torente \u00eenrudite TableColumn.header.upspeed.info=Viteza curent\u0103 de \u00eenc\u0103rcare TableColumn.header.downspeed.info=Viteza curent\u0103 de desc\u0103rcare TableColumn.header.up.info=Cantitatea curent\u0103 de date trimise altor utilizatori TableColumn.header.down.info=Cantitatea de date curent\u0103 primit\u0103 de la ceilal\u021bi utilizatori TableColumn.header.ProgressETA.info=Combin\u0103 coloanele Stare, Progres, Timp Estimat de Terminare, \u0219i Vitez\u0103 \u00eentr-o coloan\u0103 multi-r\u00eend. TableColumn.header.eta.info=Timpul estimat de terminare a desc\u0103rc\u0103rii torentului Pieces.column.#=Nr. Pieces.column.#.info=Num\u0103rul P\u0103r\u021bii Peers.column.%.info=Procentul din torent desc\u0103rcat p\u00een\u0103 acum de partener TableColumn.header.download.info=Cantitatea de date primit\u0103 de la partener TableColumn.header.upload.info=Cantitatea de date pe care i le-am trimis partenerului TableColumn.header.downloadspeed.info=Viteza cu care se primesc date de la partener TableColumn.header.uploadspeed.info=Viteza cu care s\u00eent trimise datele c\u0103tre partener TableColumn.header.lan.info=Fanion care indic\u0103 dac\u0103 partenerul e \u00een re\u021beaua (LAN) dv. TableColumn.header.downloadspeedoverall.info=Viteza de desc\u0103rcare estimat\u0103 a partenerului Peers.column.pieces.info=Bar\u0103 grafic\u0103 care prezint\u0103 p\u0103r\u021bile desc\u0103rcate de partener TableColumn.header.TableColumnNameInfo=Numele \u0219i Descrierea Coloanei TableColumn.header.TableColumnSample=E\u0219antion TableColumn.header.TableColumnInfo=Descrierea Coloanei TableColumn.header.TableColumnChosenColumn=Coloana Aleas\u0103 subs.prop.is_auto_ok=Autodesc\u0103rcare permis\u0103 label.learnmore=Afla\u021bi mai multe ColumnSetup.title=Configurarea Coloanelor pt. '%1' ColumnSetup.explain=Explora\u021bi coloanele disponibile din st\u00eenga \u0219i ad\u0103uga\u021bi-le la lista de coloane vizibile \u00een dreapta. M\u0103ri\u021bi sau diminua\u021bi lista de coloane disponibile folosind sec\u021biunea de Filtrare din partea st\u00eeng\u0103-jos. Tragerea-\u0219i-depunerea [drag-and-drop], ca \u0219i scurt\u0103turile de tastatur\u0103 pot fi de asemenea folosite. ColumnSetup.chosencolumns=Coloane Alese ColumnSetup.proficiency=Competen\u021b\u0103: ColumnSetup.categories=Categorii: ColumnSetup.filters=Filtre ColumnSetup.availcolumns=%1 coloane disponibile ColumnSetup.availcolumns.filteredby=%1 coloane disponibile filtrate dup\u0103 %2 devices.view.title=Dispozitive device.renderer.view.title=Randatoare device.mediaserver.view.title=Servere Media device.router.view.title=Rutere device.model.desc=Descrierea Modelului device.model.name=Numele Modelului device.model.num=Num\u0103rul Modelului device.manu.desc=Produc\u0103tor device.router.is_mapping=Mapare automat\u0103 a porturilor device.router.req_map=Map\u0103ri necesare device.router.configure=Configureaz\u0103 UPnP device.mediaserver.configure=Configureaz\u0103 Serverul Meu Media device.hide=Ascunde Dispozitivul device.show=Arat\u0103 Dispozitivele Ascunse device.search=Caut\u0103 Dispozitive device.router.con_type=Conexiune: %1 device.browse=Exploreaz\u0103 device.upnp.desc_url=Descrierea Dispozitivului device.upnp.present_url=Administrarea Dispozitivului ConfigView.label.maxStalledSeeding=Nr. max. '\u00eencremenite' [0:nelimitat] device.search.auto=Caut\u0103 automat dispozitive devices.sidebar.simple=Vedere Simpl\u0103 devices.xcode.working_dir=Arie de transcodare devices.xcode.prof_def=Profilul de transcodare implicit devices.xcode.profs=Profiluri de transcodare disponibile device.lastseen=Ultima Apari\u021bie devices.contextmenu.xcode=Transcodeaz\u0103 Pentru Dispozitiv devices.device=Dispozitiv devices.profile=Profil General.percent=Procent devices.installed=Instalat devices.comp.missing=Nu a fost instalat suportul pentru Vuze devices.state=Stare MainWindow.menu.help.donate=&Face\u021bi o Dona\u021bie DonationWindow.noload.title=Donare DonationWindow.noload.text=Fereastra de donare nu a putut fi \u00eenc\u0103rcat\u0103. Re\u00eencerca\u021bi mai t\u00eerziu. devices.xcode.only.show=Arat\u0103 doar fi\u0219ierele transcodate de pe dispozitiv device.quit.transcoding.title=Transcodare \u00een curs device.quit.transcoding.text='%1' este actualmente transcodat \u00een '%2', iar %3% e complet\u0103.\nDac\u0103 \u00eenchide\u021bi programul, opera\u021biunea va trebui reluat\u0103 de la \u00eenceput la urm\u0103toarea pornire a programului. download.removerules.unauthorised.data=\t\u00cenl\u0103tur\u0103 datele device.config.xcode.maxbps=Rata de transcodare max. KB/sec [0: nelimitat] device.xcode=Transcodeaz\u0103 device.xcode.always=Mereu device.xcode.whenreq=C\u00eend e necesar device.xcode.never=Niciodat\u0103 devices.copy.pending=Copiere \u00een a\u0219teptare devices.sidebar.hide.rend.generic=Ascunde dispozitivele generice v3.devicesview.infobar.text2=Pentru a transcoda con\u021binut c\u0103tre un dispozitiv, trage\u021bi \u0219i depune\u021bi con\u021binut din arhiv\u0103 \u00een dispozitivele din panoul lateral. Pentru a vedea transcod\u0103rile terminate clica\u021bi dispozitivul individual din dreapta. iconBar.transcode=Dispozitiv iconBar.transcode.tooltip=Prepar\u0103 fi\u0219ierul media pentru redarea cu un dispozitiv device.retry.copy=Re\u00eencearc\u0103 Copierea devices.copy.fail=Copierea pe dispozitiv a e\u0219uat devices.on.demand=La cerere devices.ready=Preg\u0103tit TableColumn.header.trancode_qpos=Nr. TableColumn.header.trancode_qpos.info=Pozi\u021bia \u00een Coada de Transcodare TableColumn.header.profile=Profil TableColumn.header.profile.info=Profil de transcodare utilizat TableColumn.header.copied=Copiat TableColumn.header.device=Dispozitiv TableColumn.header.device.info=Dispozitivul \u021aint\u0103 TableColumn.header.trancode_completion=Progresul Convertirii # This is the beginning of the word "View". It's right aligned under the icon bar item v3.iconBar.view.big=Ve v3.iconBar.view.big.tooltip=List\u0103 Simpl\u0103 # This is the end of the word "View". It's left aligned under the icon bar item v3.iconBar.view.small=zi v3.iconBar.view.small.tooltip=List\u0103 Avansat\u0103 general.dont.ask.again=Nu \u00eentreba din nou v3.menu.device.exploreTranscodes=Arat\u0103 Fi\u0219ierele v3.menu.device.exploreTranscodes._windows=Arat\u0103 Fi\u0219ierele \u00een Explorator v3.menu.device.exploreTranscodes._mac=Arat\u0103 Fi\u0219ierele \u00een G\u0103sitor v3.menu.device.defaultprofile=Profil Implicit devices.button.installitunes=Instaleaz\u0103 Integrarea cu iTunes device.itunes.install=Trebuie s\u0103 instala\u021bi iTunes device.itunes.start=Trebuie s\u0103 porni\u021bi iTunes sau s\u0103 activa\u021bi autopornirea device.itunes.install_problem=Se pare c\u0103 exist\u0103 o problem\u0103 cu integrarea iTunes devices.downloading=Descarc TableColumn.header.duration=Durat\u0103 TableColumn.header.resolution=Rezolu\u021bie devices.xcode.autoStart=Porne\u0219te automat c\u00eend e necesar option.askeverytime=\u00centreab\u0103 de fiecare dat\u0103 option.rememberthis=Memoreaz\u0103 aceast\u0103 setare devices.associate=Asociaz\u0103 cu devices.associate.already=Deja asociat devices.always.cache=Ca\u0219eaz\u0103 Fi\u0219ierele Netranscodate devices.turnon.prepageload=Pentru a activa aceast\u0103 facilitate, e necesar\u0103 instalarea unor componente suplimentare. devices.turnon.itunes=Include suportul pentru iTunes (necesar pt. dispozitivele Apple) devices.turnon.qos=Trimite statistici anonimizate la Vuze devices.turnon.title=Activeaz\u0103 Suportul pt. Dispozitiv devices.choose.device.title=Selecta\u021bi un dispozitiv de redare pentru acest video: devices.choose.profile.info.text=Dup\u0103 selectare, Vuze va detecta dac\u0103 formatul video va putea sau nu s\u0103 fie redat pe dispozitivul selectat, \u0219i va crea la nevoie o copie compatibil\u0103 cu dispozitivul.\n\nDuce\u021bi cursorul mausului deasupra dispozitivului pentru a vedea detalii suplimentare. devices.choose.profile.info.title.selected=Detalii %1: devices.view.heading=Convertire media pentru redarea cu un dispozitiv device.view.heading=Media pentru %1 devices.choose.device.info.title=Pont pentru Dispozitiv devices.choose.device.info.text=Data viitoare, trage\u021bi \u0219i depune\u021bi fi\u0219ierele peste dispozitivul dorit din Panoul Lateral. label.clickone=Clica\u021bi pe unul din dispozitive Button.turnon=Activeaz\u0103 ConfigView.label.dm.dblclick=Dublu-clicheaz\u0103 \u00een vederea torentelor: ConfigView.option.dm.dblclick.play=Red\u0103 Con\u021binutul ConfigView.option.dm.dblclick.details=Deschide Vederea Detaliat\u0103 a Torentului ConfigView.option.dm.dblclick.show=Arat\u0103 Fi\u0219ierul ConfigView.option.dm.dblclick.show._mac=Arat\u0103 Fi\u0219ierele \u00een G\u0103sitor ConfigView.option.dm.dblclick.show._windows=Arat\u0103 Fi\u0219ierele \u00een Explorator subscriptions.column.auto-download=Descarc\u0103 Automat xcode.deletedata.title=\u0218terge Con\u021binutul Transcodat xcode.deletedata.message=Sigur dori\u021bi s\u0103 \u0219terge\u021bi definitiv copia lui '%1' transcodat\u0103 pentru '%2'%3? xcode.deletedata.message.2=\n(o copie ar putea s\u0103 mai existe \u00een '%1') v3.deviceview.infobar.line1=Trage\u021bi \u0219i depune\u021bi videouri din Arhiva Torentelor \u00een dispozitivul dorit. v3.deviceview.infobar.line2=Reda\u021bi videourile pe oricare din ecranele avute la dispozi\u021bie - iPhone, iPod, TV v3.deviceview.infobar.line1.generic=Trage\u021bi \u0219i depune\u021bi videouri din Arhiva Torentelor \u00een sec\u021biunea %1 din Panoul Lateral. v3.deviceview.infobar.line2.itunes=Videourile vor ap\u0103rea \u00een dosarul iTunes Movies c\u00eend vor fi gata de a fi redate. v3.deviceview.infobar.line2.xbox=Fluxeaz\u0103 [stream] videourile acces\u00eend Xbox-ul 360 \u0219i select\u00eend My XBox -> Video Library -> Vuze. v3.deviceview.infobar.line2.ps3=Fluxeaz\u0103 [stream] videourile acces\u00eend PS3-ul \u0219i select\u00eend Videos -> Vuze. devices.copy_url=Copiaz\u0103 Adresa Fluxului \u00een Cliplan\u0219et\u0103 devices.converting=Convertesc Button.reload=Re\u00eencarc\u0103 devices.auto.start=Autoporne\u0219te Subscription.menu.setcookies=Seteaz\u0103 Fursecurile [Cookies] general.enter.cookies=Fursecurile intr\u0103rii [cookies] device.config.xcode.workdir=Dosarul implicit de lucru pentru fi\u0219ierele transcodate MyTorrentsView.menu.clear_alloc_data=Cur\u0103\u021b\u0103 Starea de Alocare DiskManager.error.nospace=Spa\u021biu de stocare insuficient DiskManager.error.nospace_fat32={DiskManager.error.nospace} - citi\u021bi {wiki.fat32} ConfigView.section.file.rename.incomplete=Adaug\u0103 sufix la fi\u0219ierele incomplete subscriptions.config.auto=Autodescarc\u0103 subscriptions.config.autostartdls=Porne\u0219te automat desc\u0103rc\u0103rile la ad\u0103ugarea lor (\u00een contrast cu punerea \u00een stare oprit\u0103) subscriptions.config.autostart.min=Porne\u0219te doar dac\u0103 >= MB [0: nelimitat] subscriptions.config.autostart.max=Porne\u0219te doar dac\u0103 <= MB [0: nelimitat] dlg.corewait.title=Ini\u021bializez Nucleul dlg.corewait.text=A\u0219tepta\u021bi un moment...\n\nSolicitarea va fi procesat\u0103 dup\u0103 ce se va termina ini\u021bializarea Vuze library.core.wait=A\u0219tepta\u021bi un pic...\nClientul Vuze este ini\u021bializat ConfigView.label.StartUIBeforeCore=Porne\u0219te interfa\u021ba grafic\u0103 \u00eenaintea ini\u021bializ\u0103rii nucleului softului general.add.friends=Ad\u0103uga\u021bi ni\u0219te prieteni! general.all.friends=To\u021bi Prietenii friend.mod.subs=Clica\u021bi-dreapta pentru a modifica abonamentele TableColumn.header.class=Clas\u0103 device.rss.group=Flux RSS Local devices.xcode.rsspub=Public\u0103 Fluxul RSS device.rss.enable=Creeaz\u0103 un flux RSS din con\u021binutul transcodat - aceasta pune la dispozi\u021bie con\u021binutul pentru cititoarele RSS device.rss.port=Portul Fluxului RSS device.rss.view=Clica\u021bi pentru a vedea fluxul RSS device.rss.localonly=Restric\u021bioneaz\u0103 accesul, fiind permis doar de la acest calculator rcm.rc_tracker.tt=Clica\u021bi pentru a explora trackerul rcm.rc_hash.tt=Clica\u021bi pentru a desc\u0103rca acest con\u021binut rcm.rc_title.tt=Clica\u021bi pentru a c\u0103uta acest con\u021binut devices.xcode.autoCopy=Copiaz\u0103 Automat \u00een Dosar devices.xcode.setcopyto=Seteaz\u0103 Dosarul de Copiere... devices.xcode.setcopyto.title=Alege locul unde s\u0103 se copieze devices.copy.folder.auto=Copiaz\u0103 automat fi\u0219ierele \u00een dosar devices.copy.folder.dest=Copiaz\u0103 \u00een Dosar TableColumn.menu.maxuploads=Nr. Max \u00cenc\u0103rc\u0103ri devices.xcode.mancopy=Copiaz\u0103 Manual Fi\u0219ierele devices.xcode.show.cat=Separat dup\u0103 Categorie ConfigView.label.alwaysShowLibraryHeader=Arat\u0103 mereu antetul \u00een Arhiva Torentelor (Torentele Mele) devices.cat.show=Arat\u0103 categoriile devices.tivo.machine=Numele aparatului TiVo devices.info.copypending=%1 fi\u0219iere a\u0219teapt\u0103 s\u0103 fie copiate device.error.xcodefail=Transcodarea a e\u0219uat device.error.copyfail=Unul sau mai multe fi\u0219iere nu au putut fi copiate \u00een dosar device.error.copytonotset='Copiaz\u0103 \u00een Dosar' nu a fost setat device.error.copytomissing='Copiaz\u0103 \u00een Dosar' "%1" nu a fost g\u0103sit device.error.copytonowrite='Copiaz\u0103 \u00een Dosar' "%1" nu permite scrierea device.error.copyfail2=Unul sau mai multe fi\u0219iere nu au putut fi copiate pe dispozitiv v3.deviceview.infobar.line2.tivo=Fluxa\u021bi [stream] videouri select\u00eend Vuze \u00een Lista de Redare Curent\u0103 [Now Playing List] de la aparatul TiVo. v3.deviceview.infobar.line2.psp=Videourile vor fi copiate pe PSP c\u00eend va fi conectat. devices.info.copypending2=%1 File(s) fi\u0219iere a\u0219teapt\u0103 s\u0103 fie copiate, conecta\u021bi dispozitivul subscriptions.column.nb-subscribers=Abona\u021bi device.offlinedownloader.view.title=Desc\u0103rc\u0103toare Neconectate device.od.enable=Activeaz\u0103 dispozitivele cu desc\u0103rcare neconectat\u0103 [offline] device.odauto.enable=Administreaz\u0103 automat desc\u0103rc\u0103rile device.odpt.enable=Include torentele private devices.contextmenu.od=Desc\u0103rcare Neconectat\u0103 devices.contextmenu.od.auto= devices.contextmenu.od.enable=Activeaz\u0103 devices.contextmenu.od.enabled=Activat devices.od.view.heading=Desc\u0103rc\u0103ri programate pt. desc\u0103rcare neconectat\u0103 [offline] DevicesOD.column.od_completion=Progresul Transferului devices.od.idle=Inactiv device.od.turnon.title=Activeaz\u0103 Suportul pt. Desc\u0103rc\u0103toare Neconectate device.is.disabled=Dispozitivul este dezactivat device.configure=Configureaz\u0103... device.od.error.notfound=Dispozitivul pare a fi neconectat [offline] device.od.error.opfailstatus=Dispozitivul a e\u0219uat s\u0103 proceseze comanda %1: stare %2 device.od.error.opfailexcep=Dispozitivul a e\u0219uat s\u0103 proceseze comanda %1: excep\u021bie %2 device.od.error.nospace=Nu mai exist\u0103 spa\u021biu pe dispozitiv sau nu este conectat nici un dispozitiv extern device.od.space=Spa\u021biu Disponibil ConfigView.section.style.forceSIValues=For\u021beaz\u0103 ar\u0103tarea valorilor ca valori IEC indiferent de afi\u0219area unit\u0103\u021bilor, pentru compatibilitate m\u0103rit\u0103 (e.g. 1MB = 1MiB = 1048576B) ConfigView.label.enableSystrayToolTip=Arat\u0103 statisticile de desc\u0103rcare la planarea cu mausul devices.activation=Activarea Dispozitivului button.nothanks=Nu, Mul\u021bumesc devices.od.turnon.text1=Am observat c\u0103 s\u00eente\u021bi conectat la %1. devices.od.turnon.text2=Dori\u021bi ca %1 s\u0103 continue desc\u0103rcarea fi\u0219ierelor atunci c\u00eend calculatorul este neconectat [offline]? devices.od.turnon.text3=Conecta\u021bi un Hardisc la %1 pentru a activa aceast\u0103 facilitate. devices.od.turnon.learn=Afla\u021bi mai multe > devices.router=ruter devices.od=desc\u0103rc\u0103tor neconectat webui.pairingenable=Activeaz\u0103 cuplarea [pairing] webui.group.access=Controlul Accesului ConfigView.section.Pairing=Cuplare pairing.accesscode=Cod de Acces pairing.ac.getnew=Aloc\u0103 un cod nou de acces pairing.ac.getnew.create=Creeaz\u0103 pairing.ipv4=Adres\u0103 IPv4 pairing.ipv6=Adres\u0103 IPv6 pairing.host=Adresa gazdei (Nume DNS) pairing.group.explicit=Atribute Explicite pairing.explicit.enable=Activeaz\u0103 pairing.explicit.info=Atributele explicite IP nu trebuie specificate \u00een mod obi\u0219nuit, pentru c\u0103 pot fi deduse automat.\nAtributul 'host' poate fi utilizat de exemplu dac\u0103 ave\u021bi un cont DynDNS \u0219i soft client potrivit pentru a p\u0103stra adresa IP dinamic\u0103 \u00eenregistrat\u0103 corect. pairing.op.fail=Opera\u021bia de cuplare a e\u0219uat pairing.alloc.fail=Alocarea unui cod nou de acces a e\u0219uat\n%1 pairing.enable=Activeaz\u0103 cuplarea [pairing] softului Vuze cu aplica\u021bii/interfe\u021be distante pairing.status.info=Stare pairing.status.registered=Actualizare reu\u0219it\u0103 (%1) pairing.status.pending=Actualizarea va fi realizat\u0103 la %1 pairing.status.initialising=Ini\u021bializare pairing.status.disabled=Dezactivat\u0103 pairing.view.registered=Clica\u021bi pentru a vedea detaliile \u00eenregistr\u0103rii curente webui.pairing.info.n=Cuplarea este dezactivat\u0103, vede\u021bi op\u021biunile de la Conexiune->Cuplare pentru informa\u021bii despre aceast\u0103 facilitate. webui.pairing.info.y=Cuplarea este activat\u0103, vede\u021bi op\u021biunile de la Conexiune->Cuplare pentru detalii suplimentare. webui.enable=Activeaz\u0103 (*) ConfigView.section.rss=RSS Local etc. subscriptions.rss.enable=Creeaz\u0103 Flux RSS din abonamente device.tivo.enable=Activeaz\u0103 suportul pentru TiVo Button.removeAll=\u00cenl\u0103tur\u0103 Tot label.rename=Redenume\u0219te %1 RCM.column.rc_rank=Rang RCM.column.rc_created=Creat RCM.column.rc_hash=Ha\u0219 RCM.column.rc_lastseen=Ultima Apari\u021bie RCM.column.rc_level=Nivel rcm.view.heading=Descoperiri ale Roiului rcm.config.enabled=Activeaz\u0103 rcm.config.max_results=Nr. Maxim de Rezultate rcm.config.max_level=Nivel Maxim rcm.search.provider=Roi pairing.server.warning.title=Mesajul Serverului de Cuplare wizard.webseedseditor.edit.title=Editorul Donatorilor HTTP wizard.webseedseditor.edit.newseed=Donator Nou MyTorrentsView.menu.editWebSeeds=Editeaz\u0103 Donatorii HTTP ClientStats.title.full=Statisticile Softului ClientStats.column.count=Num\u0103r Scrape.status.cached=R\u0103zuire [scrape] ca\u0219at\u0103 azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_sr_Latin.properties0000644000175000017500000051333611232522032026656 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torent datoteku... MainWindow.menu.file.open.torrent.keybinding=Meta+O Main.parameter.usage=Upotreba : java org.gudy.azureus2.cl.Main [parametri] "datoteka.torrent" "staza za snimanje" Main.parameter.maxUploads=Maksimalan broj istovremenih slanja Main.parameter.maxSpeed=Maksimalna brzina slanja u bajtovima/s MainWindow.menu.file=&Datoteka MainWindow.menu.file.open=&Otvori MainWindow.menu.file.create=&Novi torent... MainWindow.menu.file.create.keybinding=Meta+N MainWindow.menu.file.create.fromfile=Iz &datoteke MainWindow.menu.file.create.fromdir=Iz di&rektorijuma MainWindow.menu.file.export=&Izvezi XML torent... MainWindow.menu.file.export.keybinding=Meta+E MainWindow.menu.file.export.keybinding.mac=Meta+Shift+E MainWindow.menu.file.import=&Uvezi XML torent... MainWindow.menu.file.import.keybinding=Meta+I MainWindow.menu.file.import.keybinding.mac=Meta+Shift+I MainWindow.menu.file.closetab=Zatvori &jezi\u010dak MainWindow.menu.file.closetab.keybinding=Meta+W MainWindow.menu.file.closewindow=Zatvori &prozor MainWindow.menu.file.closewindow.keybinding=Meta+Shift+W MainWindow.menu.file.exit=&Kraj MainWindow.menu.file.exit.keybinding=Alt+F4 MainWindow.dialog.choose.file=Izbor torent datoteke MainWindow.menu.file.folder=&Direktorijum... MainWindow.menu.file.folder.keybinding=Meta+Shift+O MainWindow.dialog.choose.folder=Izaberite direktorijum koji sadr\u017ei torent datoteke MainWindow.menu.view=&Pregled MainWindow.menu.view.show=Prikaz MainWindow.menu.view.mytorrents=&Moji torenti MainWindow.menu.view.mytorrents.keybinding=Meta+1 MainWindow.menu.view.open_global_transfer_bar=Traka sa prenosima MainWindow.menu.view.configuration=&Pode\u0161avanja... MainWindow.menu.view.configuration.keybinding=Meta+, MainWindow.menu.view.console=K&onzola MainWindow.menu.view.console.keybinding=Meta+4 MainWindow.menu.view.irc=&Irc MainWindow.menu.view.allpeers=Svi ra\u010dunari MainWindow.menu.closealldetails=Zatvori &sve detalje MainWindow.menu.closealldownloadbars=Zatvori sve &trake sa prijemima MainWindow.menu.language=&Jezik ConfigView.section.language=Jezik MainWindow.menu.window=&Prozor MainWindow.menu.window.minimize=&Umanji MainWindow.menu.window.minimize.keybinding=Meta+M MainWindow.menu.window.zoom=U&ve\u0107aj MainWindow.menu.window.alltofront=Prebaci sve u &prvi plan MainWindow.menu.help=&Pomo\u0107 MainWindow.menu.help.about=O Azureusu MainWindow.menu.torrent=T&orent MainWindow.about.title=O programu MainWindow.about.section.developers=Razvija\u010di MainWindow.about.section.translators=Prevodioci MainWindow.about.section.system=Sistem MainWindow.about.section.internet=Internet MainWindow.about.internet.homepage=Azureusova strana MainWindow.about.internet.sourceforge=Strana Sorsford\u017eovog projekta MainWindow.about.internet.sourceforgedownloads=Prijem sa Sorsford\u017ea MainWindow.about.internet.bugreports=Prijava gre\u0161aka MainWindow.about.internet.forumdiscussion=Forumi MainWindow.about.internet.wiki=Pitanja o Azureusu na Vikiju MainWindow.dialog.choose.savepath=Izaberite stazu za \u010duvanje MainWindow.dialog.choose.savepath_forallfiles=Izbor staze za \u010duvanje za SVE datoteke MainWindow.status.latestversion=Najsve\u017eiji MainWindow.status.latestversion.clickupdate=Pritisnite za dogradnju MainWindow.status.unknown=nepoznat MainWindow.status.checking=provera MyTorrentsView.mytorrents=Moji torenti TableColumn.header.name=Ime TableColumn.header.size=Veli\u010dina TableColumn.header.done=Gotovo TableColumn.header.done.info=Procenat ispunjenja trenutnog zadatka TableColumn.header.status=Status TableColumn.header.status.info=\u0160ta torent trenutno radi TableColumn.header.seeds=Zameci TableColumn.header.seeds.info=br. povezanih klica (uk. broj klica) TableColumn.header.peers=Ra\u010dunari TableColumn.header.peers.info=br. ra\u010dunara na vezi (uk. broj ra\u010dunara) TableColumn.header.downspeed=Prijem TableColumn.header.upspeed=Slanje TableColumn.header.eta=PVD TableColumn.header.tracker=Status pratioca TableColumn.header.tracker.info=Status pratioca TableColumn.header.trackernextaccess=Slede\u0107i pristup pratiocu TableColumn.header.trackernextaccess.info=Vreme kada se ponovo pristupa pratiocu TableColumn.header.priority=Prioritet TableColumn.header.priority.info=Odre\u0111uje koliko propusne mo\u0107i za slanje se daje ovom torentu TableColumn.header.seeds.fullcopycalc=%2 potpunih umno\u017eaka za %1 ra\u010dunara MyTorrentsView.menu.showdetails=Poka\u017ei &detalje MyTorrentsView.menu.showdownloadbar=Poka\u017ei traku za &prijem MyTorrentsView.menu.open=&Otvori datoteku MyTorrentsView.menu.setpriority=Postavi &prioritet MyTorrentsView.menu.setpriority.high=&Visok MyTorrentsView.menu.setpriority.low=&Nizak MyTorrentsView.menu.start=&Kreni MyTorrentsView.menu.stop=&Stani MyTorrentsView.menu.remove=&Ukloni MyTorrentsView.menu.changeTracker=&Dodaj URL za pratioca TrayWindow.menu.exit=&Kraj TrayWindow.menu.show=&Poka\u017ei Azureusa SystemTray.menu.exit=&Kraj SystemTray.menu.closealldownloadbars=Zatvori &sve trake za prijem SystemTray.menu.open_global_transfer_bar=Prikaz traka sa prenosima SystemTray.menu.show=&Poka\u017ei Azureusa PeersView.ip=IP PeersView.ip.info=IP adresa ra\u010dunara PeersView.port=Port PeersView.port.info=Port se koristi PeersView.T=T PeersView.T.info=l (lokal): vi ste uspostavili vezu, u (udaljen): udaljeni ra\u010dunar je uspostavio vezu. PeersView.T.L.tooltip=Vi ste uspostavili vezu PeersView.T.R.tooltip=Udaljen ra\u010dunar je uspostavio vezu PeersView.I1=Z (udaljeni ra\u010dunar je zainteresovan) PeersView.I1.info=Da li vas zanima \u0161ta udaljeni ra\u010dunar poseduje? PeersView.C1=P (Prigu\u0161en od drugog ra\u010dunara) PeersView.C1.info=Da li vas udaljeni ra\u010dunar spre\u010dava da primate PeersView.pieces=Delovi PeersView.%=% PeersView.downloadspeed=Prijem PeersView.download=Preuz. PeersView.I2=Z (udaljeni ra\u010dunar je zainteresovan) PeersView.I2.info=Da li je ra\u010dunar zainteresovan za sadr\u017eaj kog nudite? PeersView.C2=P (Prigu\u0161ivanje udaljenog ra\u010dunara) PeersView.C2.info=Da li spre\u010davate udaljeni ra\u010dunar da prima PeersView.uploadspeed=Slanje PeersView.uploadspeed.info=Brzina kojom \u0161aljete podatke udaljenom ra\u010dunaru PeersView.upload=Slanje PeersView.upload.info=Ukupna brzina slanja ka ra\u010dunaru. PeersView.statup=Stat. brzina PeersView.statup.info=Procena brzine slanja udaljenog ra\u010dunara PeersView.S=S PeersView.S.info=Opomena: ra\u010dunar mo\u017ee biti \u201eopomenut\u201c ru\u010dno ili automatski (npr. ako ne \u0161alje podatke dovoljno brzo) PeersView.downloadspeedoverall=Ukupna brzina prijema PeersView.optunchoke=Opc. odgu\u0161ivanje PeersView.client=Klijent PeersView.client.info=Vrsta BT klijenta kog koristi ra\u010dunar PeersView.menu.snubbed=&Opomenut PeersView.title.short=Ra\u010dunari PeersView.title.full=Ra\u010dunari AllPeersView.title.full=Svi ra\u010dunari ConfigView.section.files=Datoteke ConfigView.label.usefastresume=Koristi brzi oporavak ConfigView.label.incrementalfile=Dozvoli postepeno stvaranje datoteke [neophodno za FAT32 pod Linuksom] ConfigView.label.defaultsavepath=Sa\u010duvaj u podrazumevani direktorijum s podacima ConfigView.button.browse=&Pregled... ConfigView.dialog.choosedefaultsavepath=Molim izaberite podrazumevani direktorijum za \u010duvanje ConfigView.section.server=Veza ConfigView.section.global=Op\u0161te ConfigView.label.disconnetseed=Raskidanje veza sa ostalim klicama kada je ovaj ra\u010dunar klica ConfigView.label.switchpriority=Automatski prebacivanje na nizak prioritet kada je klica ConfigView.label.maxdownloads=Najve\u0107i broj istovremenih prijema [0: neograni\u010deno]\n - Ne mo\u017ee da bude vi\u0161e od najve\u0107eg broja aktivnih torenta ConfigView.label.maxdownloads.tooltip=Uvek je mogu\u0107e aktivno primati broj kog ovde upi\u0161ete, sa jednim izuzetkom.\nZavr\u0161en torent koji ima prvi prioritet mo\u017ee da preuzme aktivan prijem ukoliko je zaista neophodno. ConfigView.label.maxactivetorrents=Najvi\u0161e aktivnih torenta [0: neograni\u010deno]\n - Novi torenti se ne\u0107e pokretati ako primate ili delite vi\u0161e ConfigView.label.priorityExtensions=Automatski prioritet datotekama sa ekstenzijama\n - npr: .txt;.nfo;.jpg ConfigView.section.transfer=Prenosi ConfigView.label.maxuploads=Podrazumevani najve\u0107i broj proreza po torentu ConfigView.label.maxuploadspeed=globalna najve\u0107a brzina slanja u KB/s [0: neograni\u010deno] ConfigView.label.saveresumeinterval=Osve\u017eavanje podataka o obnovi svakih ConfigView.unlimited=Neograni\u010dena ConfigView.section.display=Prikaz ConfigView.label.opendetails=Automatski otvori jezi\u010dak sa detaljima ConfigView.label.openbar=Automatski otvori traku za prenos ConfigView.label.use_old_speed_menus=Koristi stare brze menije [tra\u017ei ponovno pokretanje] ConfigView.label.closetotray=Zatvaranje umanjuje u obave\u0161tajnu zonu ConfigView.label.minimizetotray=Umanjivanje umanjuje u obave\u0161tajnu zonu ConfigView.section.general=Op\u0161te ConfigView.section.start=Pokretanje ConfigView.label.showsplash=Poka\u017ei naslovni ekran ConfigView.label.autoupdate=Otvori prozor za dogradnju kada novo izdanje postane dostupno ConfigView.label.openconsole=Otvori konzolu pri pokretanju ConfigView.label.openconfig=Otvori pode\u0161avanja pri pokretanju ConfigView.label.startminimized=Umanji pri pokretanju ConfigView.section.irc=IRC ConfigView.label.ircwiki=Molimo da pro\u010ditate http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Server ConfigView.label.ircchannel=Kanal ConfigView.label.irclogin=Nadimak ConfigView.group.irctitle=Pode\u0161avanja IRCa ConfigView.boolean.ircsendinfo=Dozvoli (anonimno) slanje podataka operatorima\nkako bi vam lak\u0161e pomogli ConfigView.boolean.irclog=Dozvoli bele\u017eenje aktivnosti na kanalu (u IRC_log.htm) ConfigView.section.security=Bezbednost ConfigView.label.password=Za\u0161tita Azureusa lozinkom\n- Tra\u017ei se prilikom uveli\u010davanja i pokretanja. ConfigView.label.passwordconfirm=Lozinka (potvrda) ConfigView.label.passwordmatch=Lozinka je aktivna : ConfigView.label.passwordmatchnone=Ne ConfigView.label.passwordmatchno=Ne / Lozinke se ne poklapaju ConfigView.label.passwordmatchyes=Da ConfigView.button.save=Sa\u010duvaj ConfigView.title.short=Pode\u0161avanja ConfigView.title.full=Pode\u0161avanja ConsoleView.title.short=Konzola ConsoleView.title.full=Konzola FileItem.write=upis FileItem.read=\u010ditanje FileItem.normal=normalan FileItem.high=visok FileItem.donotdownload=Ne primaj FilesView.name=Ime FilesView.size=Veli\u010dina FilesView.done=Gotovo FilesView.%=% FilesView.firstpiece=Prvi deo FilesView.numberofpieces=br. delova FilesView.pieces=Delovi FilesView.mode=Na\u010din rada FilesView.priority=Prioritet FilesView.menu.open=&Otvori FilesView.menu.setpriority=&Postavi prioritet FilesView.menu.setpriority.high=&Visok FilesView.menu.setpriority.normal=&Obi\u010dan FilesView.menu.setpriority.skipped=&Ne primaj FilesView.title.short=Datoteke FilesView.title.full=Datoteke GeneralView.section.downloaded=Preuzeto GeneralView.label.status.file=Status datoteke GeneralView.label.status.pieces=Status delova GeneralView.section.availability=Dostupnost GeneralView.label.status.pieces_available=Status delova GeneralView.section.transfer=Prenosi GeneralView.section.info=Podaci GeneralView.title.short=Op\u0161te GeneralView.title.full=Op\u0161te GeneralView.label.timeelapsed=Proteklo vreme : GeneralView.label.remaining= Preostalo : GeneralView.label.downloaded=Preuzeto : GeneralView.label.downloadspeed= Brzina prijema : GeneralView.label.maxuploads=Slotovi za slanje : GeneralView.label.maxuploads.tooltip=Najve\u0107i broj ra\u010dunara koji nisu prigu\u0161eni u datom trenutku. GeneralView.label.uploaded=Predato : GeneralView.label.uploadspeed= Brzina slanja : GeneralView.label.seeds=Zameci : GeneralView.label.peers= Ra\u010dunari : GeneralView.label.totalspeed=Brzina roja : GeneralView.label.totalspeed.tooltip=Ukupna (i srednja) brzina svih priklju\u010denih klijenata. GeneralView.label.averagespeed=srednja GeneralView.label.filename=Ime : GeneralView.label.totalsize= Uk. veli\u010dina: GeneralView.label.savein=\u010cuvanje u : GeneralView.label.hash= He\u0161 : GeneralView.label.numberofpieces=Br. delova GeneralView.label.size= Veli\u010dina : GeneralView.label.tracker=Stanje pratioca : GeneralView.label.updatein= Osve\u017eavanje za: GeneralView.label.trackerurl=URL pratioca: GeneralView.label.trackerurlupdate = Osve\u017ei pratioca GeneralView.label.comment=Komentar za torent : GeneralView.label.user_comment=Korisnikov komentar : GeneralView.label.status=Status : ManagerItem.waiting=\u010cekanje ManagerItem.allocating=Sme\u0161tanje ManagerItem.checking=Provera ManagerItem.ready=\u010cekanje da se drugi torenti ubace u red ManagerItem.downloading=Prijem ManagerItem.seeding=Zametanje ManagerItem.stopped=Zaustavljen ManagerItem.error=Gre\u0161ka ManagerItem.high=visok ManagerItem.low=nizak MinimizedWindow.name=Ime: MinimizedWindow.all_transfers=Azureusovi prenosi PiecesView.#=br. PiecesView.size=Veli\u010dina PiecesView.numberofblocks=br. blokova PiecesView.blocks=Blokovi PiecesView.completed=Preuzeto PiecesView.availability=Dostupnost PiecesView.reservedby=Rezervisano PiecesView.writers=Prilo\u017enici za blok PiecesView.title.short=Delovi PiecesView.title.full=Delovi SystemTray.tooltip.seeding=zametanja: %1, SystemTray.tooltip.downloading=prijema: %1, DownloadManager.error.filenotfound=Datoteka nije na\u0111ena DownloadManager.error.fileempty=Torent datoteka je prazna DownloadManager.error.filetoobig=Torent datoteka je prevelika DownloadManager.error.filewithouttorrentinfo=U datoteci nema podataka o torentu DownloadManager.error.unsupportedencoding=Kodiranje nije podr\u017eano DownloadManager.error.ioerror=U/I gre\u0161ka DownloadManager.error.sha1=Gre\u0161ka: nedostaje algoritam (SHA1) PeerManager.status.offline=Gre\u0161ka pri povezivanju PeerManager.status.ok=U redu PeerManager.status.checking=Provera PeerManager.status.finished=Zavr\u0161eno PeerManager.status.finishedin=Zavr\u0161ava za MainWindow.upgrade.assistant=Dogradi saradnika MainWindow.upgrade.newerversion=Postoji novo izdanje Azureusa spremno za prijem MainWindow.upgrade.explanation=Ovaj saradnik \u0107e preuzeti novo izdanje u Azureusov direktorijum i ponovo pokrenuti Vuze MainWindow.upgrade.explanation.manual=Dogradnju mo\u017eete pokrenuti ru\u010dno tako \u0161to ugasite Vuze preuzmete novo izdanje i pokrenete ga ponovo MainWindow.upgrade.step1=Korak 1: Prijem novog izdanja MainWindow.upgrade.step2=Korak 2: Zatvaranje ovog izdanja i pokretanje novog izdanja Azureusa MainWindow.upgrade.hint1=Savet: Pritisak na \u201eZavr\u0161i\u201c automatski odra\u0111uje sve MainWindow.upgrade.hint2=Savet: Ako \u017eelite da kasnije zatvorite Vuze pritisnite \u201eOtka\u017ei\u201c i\n preimenujte Azureus2-new.jar u Azureus2.jar po zatvaranju MainWindow.upgrade.error.downloading.hint=Gre\u0161ka: Nije mogu\u0107e preuzeti novo izdanje, molimo da dogradite ru\u010dno MainWindow.upgrade.section.info=Dostupno je novo izdanje MainWindow.upgrade.section.manual=Ru\u010dna dogradnja MainWindow.upgrade.section.automatic=Automatska dogradnja MainWindow.upgrade.tooltip.progressbar=Tok dogradnje je prikazan ovde Button.next=Slede\u0107i Button.finish=Zavr\u0161i Button.cancel=Otka&\u017ei LocaleUtil.title=Izbor kodiranja LocaleUtil.section.chooseencoding=Izaberite kodiranje za ime datoteke LocaleUtil.label.chooseencoding=Molimo izaberite najpodesnije kodiranje LocaleUtil.label.hint.doubleclick=Savet: dvostruki pritisak na red bira kodiranje i zatvara prozor\u010di\u0107 LocaleUtil.label.checkbox.rememberdecision=Zapamti odluku za preostala imena datoteka LocaleUtil.column.encoding=Kodiranje IrcClient.defaultChannel=#Azureus-Users IrcClient.copyright=Koristi se PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Povezivanje sa IrcClient.connected=Povezan sa IrcClient.joining=Pridru\u017eivanje IrcClient.channel=Kanal IrcClient.joined=pridru\u017een IrcClient.error=Gre\u0161ka IrcClient.hasjoined=se pridru\u017eio IrcClient.haskicked=je izbacio IrcClient.hasleft=je napustio IrcClient.nowknown=od sada ima ime IrcClient.topicforchannel=Tema za kanal IrcClient.disconnected=Isklju\u010den sa IrcClient.noNick=Korisni\u010dko ime nije upisano. Molimo da ga dodate u pogledu \u201ePode\u0161avanja\u201c IrcView.actionnotsupported=Ovo dejstvo nije podr\u017eano IrcView.clientsconnected=korisnika IrcView.privateto=Za IrcView.privatefrom=Od IrcView.noticefrom=Obave\u0161tenje : IrcView.errormsg=Pogre\u0161na sintaksa za /msg : /msg korisnik tekst IrcView.help=Va\u017ee\u0107e komande su :\n . /help : prikazuje ovu poruku\n . /nick | /name : menja ime\n . /me action : \u0161alje dejstvo\n . /msg ime poruka : slanje privatne poruke za \n . /r poruka : odgovor na poslednju privatnu poruku\n . /join #kanalB (nemojte pritiskati ovde jer to je samo primer): menja trenutni kanal na \u201ekanalB\u201c\n . /whois ime : dobavi podatke o PasswordWindow.title=Vuze je zaklju\u010dan PasswordWindow.passwordprotected=Da bi bio prikazan Azureusov prozor, molimo da uneset ovde Va\u0161u lozinku : Button.ok=&U redu TrackerChangerWindow.title=Dodaj pratioca TrackerChangerWindow.newtracker=Dodaj nov URL za pratioca PeersView.discarded=Odba\u010deno PeersView.discarded.info=Podaci koje ste nekako primili iako Vam nisu bili potrebni, pa ste ih se otarasili. discarded=odba\u010deno MyTorrentsView.#=br. MyTorrentsView.menu.move=&Pomeri MyTorrentsView.menu.moveUp=&Gore MyTorrentsView.menu.moveDown=&Dole GeneralView.label.hashfails=Gre\u0161ke he\u0161a : GeneralView.label.shareRatio=Odnos deljenja : ConfigView.section.downloadManagement=Upravljanje prenosom ConfigView.label.startRatioPeers=Po\u010dni zametanje ako postoji manje od 1 zametka za ConfigView.text.neverStop=Nikada ne staj ConfigView.text.neverStart=Nikada ne po\u010dinji ConfigView.text.peers=Ra\u010dunari ConfigView.label.checkOncompletion=Proveri delove kada se prenos zavr\u0161i wizard.title=Napravi torent wizard.previous= wizard.finish=Zavr\u0161i wizard.mode=Pratilac / Na\u010din wizard.tracker=Pratilac: wizard.invalidurl=Ovaj URL nije ispravan wizard.singlefile=Jedna datoteka wizard.singlefile.help=Napravi torent od jedne datoteke wizard.directory=Direktorijum wizard.directory.help=Napravi torent od direktorijuma wizard.choosefile=Napravi datoteku wizard.file=Datoteka : wizard.browse=Pregled... wizard.choosedirectory=Izbor direktorijuma wizard.invalidfile=Neispravna datoteka! wizard.invaliddirectory=Neispravan direktorijum! wizard.torrentFile=Torent datoteka wizard.choosetorrent=Molimo izaberite torent datoteku koju treba napraviti wizard.information=Podaci wizard.notimplemented=Jo\u0161 nije ugra\u0111eno wizard.progresstitle=Pravljenje torent datoteke wizard.savingfile=\u010cuvanje datoteke... wizard.filesaved=Datoteka je sa\u010duvana. wizard.close=Zatvori Torrent.create.progress.piecelength=Du\u017eina dela: Torrent.create.progress.piececount=Broj dela: Torrent.create.progress.totalfilesize=Ukupna veli\u010dina datoteke: Torrent.create.progress.totalfilecount=Ukupan broj datoteka: Torrent.create.progress.parsingfiles=Ra\u0161\u010dlanjivanje datoteka Torrent.create.progress.hashing=He\u0161iranje datoteka MainWindow.upgrade.downloadingfrom=Prijem sa : MainWindow.menu.view.ipFilter=&IP filteri ConfigView.section.ipfilter=IP filteri ConfigView.section.ipfilter.description=Opis ConfigView.section.ipfilter.start=Po\u010detni IP ConfigView.section.ipfilter.end=Krajnji IP ConfigView.section.ipfilter.add=Dodaj ConfigView.section.ipfilter.remove=Ukloni ConfigView.section.ipfilter.edit=Uredi ConfigView.section.ipfilter.save=Sa\u010duvaj ConfigView.section.ipfilter.editFilter=Uredi filter ConfigView.section.ipfilter.enable=Uklju\u010deno PeersView.menu.close=&Zatvori seedmore.title=Torent nije dobro zametnut seedmore.shareratio=Va\u0161 odnos deljenja za ovaj torent je seedmore.uploadmore=Odnos deljenja ispod 1 nije dobar za torent mre\u017eu.\nNeophodno je da ostavite da se torent deli jo\u0161 neko vreme.\nDa li sigurno \u017eelite da nastavite? ConfigView.label.showpopuponclose=Poka\u017ei prozor\u010di\u0107 za potvrdu kada se obustavlja zametanje sa odnosom deljenja manjim od 1 ConfigView.label.startNumSeeds=\nPokreni zametanje ako ima manje od\n - preina\u010duje sva ostala pravila ConfigView.label.seeds=zametaka ConfigView.section.seeding=Zametanje MyTorrentsView.menu.removeand=&Ukloni i MyTorrentsView.menu.removeand.deletetorrent=Ukloni &torent datoteku MyTorrentsView.menu.removeand.deletedata=Ukloni &podatke MyTorrentsView.menu.removeand.deleteboth=Ukloni &oboje deletedata.title=Upozorenje deletedata.message1=Samo \u0161to niste uklonili PODATKE sa :\n deletedata.message2=\nDa li sigurno da \u017eelite da nastavite? MainWindow.menu.file.configure=&\u010carobnjak za pode\u0161avanja... configureWizard.title=\u010carobnjak za pode\u0161avanja configureWizard.welcome.title=Dobrodo\u0161li kod Azureusovog \u010darobnjaka za pode\u0161avanja configureWizard.welcome.message=Ovaj \u010darobnjak \u0107e Vam pomo\u0107i da podesite Vuze za uobi\u010dajenu upotrebu. Detalje pode\u0161avanja mo\u017eete promeniti koriste\u0107i meni \u201eAlati->Opcije\u201c. configureWizard.transfer.title=Pode\u0161avanja prenosa i veze configureWizard.transfer.hint=Savet: kori\u0161\u0107enje ne\u0161to malo manje brzine nego \u0161to je kapacitet veze je najbolji izbor. configureWizard.transfer.message=Molimo izaberite vezu iz dole datog spiska. Imajte na umu da ako ne dozvolite dovoljnu brzinu slanja to \u0107e imati za posledicu i spor prijem. Kako se brzine prenosa ra\u010dunaju po pojedina\u010dnom torentu, poku\u0161aj prijema previ\u0161e torenta u isto vreme mo\u017ee biti uzrok maloj brzini prenosa. Preporu\u010dujemo da koristite 5KB/s kao STROGI minimum. \u0160to br\u017ee \u0161aljete, br\u017ee \u0107ete primati (u odnosu na brzinu torenta). configureWizard.transfer.connection=Veza configureWizard.transfer.connection.0=Proizvoljna configureWizard.transfer.connection.1=modemska configureWizard.transfer.connection.2=adsl/kabl xxx/128 kbps configureWizard.transfer.connection.3=adsl/kabl xxx/256 kbps configureWizard.transfer.connection.4=adsl/kabl xxx/384 kbps configureWizard.transfer.connection.5=adsl/kabl xxx/512 kbps configureWizard.transfer.connection.6=adsl/kabl xxx/768 kbps configureWizard.transfer.connection.7=adsl/kabl xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Najve\u0107a brzina slanja (KB/s) configureWizard.transfer.maxActiveTorrents=Najvi\u0161e aktivnih configureWizard.transfer.maxDownloads=Najvi\u0161e prijema configureWizard.transfer.maxUploadsPerTorrent=Najvi\u0161e slanja po torentu configureWizard.nat.title=NAT / port servera configureWizard.nat.message=Kako biste izvukli maksimum iz Bit Torenta, preporu\u010duje se da ra\u010dunar bude potpuno dostupan sa interneta. Ovaj alat vam dopu\u0161ta da proverite i promenite broj porta koji se koristi za prihvat dolaznih veza.\n\nPRIMEDBA: Ovaj alat samo proverava TCP veze. Raspodeljena baza podataka tra\u017ei i UDP veze, ali \u0107e Vas automatski obavestit ako otkrije blokiraju\u0107i vatrobran.\n\nPRIMEDBA: TCP port 6880 je rezervisann i ne mo\u017ee se koristiti. configureWizard.nat.test=Proba configureWizard.nat.testing=Port za probu configureWizard.nat.ok=U redu ! configureWizard.nat.ko=NAT Gre\u0161ka configureWizard.nat.unable=Nije mogu\u0107e proveriti: Zadat je neva\u017ee\u0107i port, ili servis za proveru ne radi.\nDruga aplikacija mo\u017eda ve\u0107 koristi ovaj port configureWizard.file.title=Torenti / Datoteke configureWizard.file.message1=Vuze \u0107e sa\u010duvati otvorene torente u ozna\u010den direktorijum, direktorijum se mo\u017ee odabrati ovde: configureWizard.file.path=Staza configureWizard.file.browse=Pregled configureWizard.file.message2=Vuze mo\u017ee da odmah nastavi prenos datoteka, tako \u0161to dodaje izvesnu koli\u010dinu podataka koji u tome poma\u017eu. Ako koristite ovu mogu\u0107nost, nastavak delimi\u010dno prenesenih delova je tako\u0111e mogu\u0107. configureWizard.file.fastResume=Uklju\u010di brzi nastavak configureWizard.file.invalidPath=Neva\u017ee\u0107i direktorijum configureWizard.finish.title=Preuzeto configureWizard.finish.message=Vuze je sada pode\u0161en. U\u017eivajte ! wizard.close.confirmation=Potvrda wizard.close.message=Da li \u017eelite da se \u010darobnjak u\u010dita naredni put kada se Vuze pokrene? exportTorrentWizard.title=Izvoz torenta u XML format exportTorrentWizard.torrentfile.title=Izbor ulaznog torenta exportTorrentWizard.torrentfile.message=Izaberite torent datoteku za izvoz exportTorrentWizard.torrentfile.path=Staza exportTorrentWizard.torrentfile.browse=Pregled exportTorrentWizard.torrentfile.invalidPath=Neispravna torent datoteka exportTorrentWizard.exportfile.title=Izbor datoteke exportTorrentWizard.exportfile.message=Odredite XML datoteku za izvoz exportTorrentWizard.exportfile.path=Staza exportTorrentWizard.exportfile.browse=Pregled exportTorrentWizard.exportfile.invalidPath=Neispravna datoteka za izvoz exportTorrentWizard.finish.title=Preuzeto exportTorrentWizard.finish.message=Izvoz je uspe\u0161no obavljen exportTorrentWizard.process.inputfilebad.title=Torent datoteka je neispravna exportTorrentWizard.process.inputfilebad.message=Do\u0161lo je do gre\u0161ke pri pristupu ulaznoj datoteci: exportTorrentWizard.process.outputfileexists.title=Datoteka postoji exportTorrentWizard.process.outputfileexists.message=Izlazna datoteka postoji? Da li da je prebri\u0161em? exportTorrentWizard.process.torrentfail.title=\u010citanje torenta nije uspelo exportTorrentWizard.process.exportfail.title=Izvoz torenta nije uspeo exportTorrentWizard.process.unknownfail.title=Neo\u010dekivana gre\u0161ka importTorrentWizard.title=Uvoz XML torenta importTorrentWizard.torrentfile.title=Izbor ulaznog torenta importTorrentWizard.torrentfile.message=Izaberite torent datoteku u koju se uvozi importTorrentWizard.torrentfile.path=Staza importTorrentWizard.torrentfile.browse=Pregled importTorrentWizard.torrentfile.invalidPath=Neispravna torent datoteka importTorrentWizard.importfile.title=Izbor datoteke za uvoz importTorrentWizard.importfile.message=Izaberite xml datoteku za uvoz importTorrentWizard.importfile.path=Staza importTorrentWizard.importfile.browse=Pregled importTorrentWizard.importfile.invalidPath=Neispravna datoteka za uvoz importTorrentWizard.finish.title=Preuzeto importTorrentWizard.finish.message=Uvoz je uspe\u0161no obavljen importTorrentWizard.process.inputfilebad.title=Datoteka za uvoz je neispravna importTorrentWizard.process.inputfilebad.message=Do\u0161lo je do gre\u0161ke pri pristupu ulaznoj datoteci: importTorrentWizard.process.outputfileexists.title=Datoteka postoji importTorrentWizard.process.outputfileexists.message=Izlazna datoteka postoji? Da li da je prebri\u0161em? importTorrentWizard.process.torrentfail.title=Upis u torent nije uspeo importTorrentWizard.process.importfail.title=Uvoz torenta nije uspeo importTorrentWizard.process.unknownfail.title=Neo\u010dekivana gre\u0161ka ConfigView.label.bindip=Prive\u017ei za lokalnu IP adresu ili su\u010delje ConfigView.label.xfs.allocation=Osloba\u0111anje mesta za nove datoteke na na\u010din specifi\u010dan za sistem datoteka XFS ConfigView.label.xfs.allocation.tooltip=Molimo da proverite da je program /usr/sbin/xfs_io ispravno postavljen na Va\u0161 sistem. Na mnogim distribucijama zasnovanim na Linuksu, nalazi se u paketu \u201exfsprogs\u201f. xfs.allocation.xfs_io.not.found=Rezaervacija datoteka po metodu XFS nije uspela jer program /usr/sbin/xfs_io nije mogao da bude pokrenut. Proverite da je ispravno postavljen na Va\u0161em sistemu. Izvorna gre\u0161ka je bila: \u201e%1\u201f. ConfigView.label.zeronewfiles=Rezervi\u0161i i anuliraj nove datoteke pri stvaranju ConfigView.label.zeronewfiles.tooltip=Smanjuje rascepkanost ConfigView.section.stats=Statistike ConfigView.section.stats.enable=Uklju\u010deno ConfigView.section.stats.defaultsavepath=Direktorijum za zapis statistika ConfigView.section.stats.choosedefaultsavepath=Molimo izaberite direktorijum za zapis statistika ConfigView.section.stats.savefreq=U\u010destanost zapisivanja ConfigView.section.stats.minutes=min ConfigView.section.stats.hours=sat ConfigView.section.stats.seconds=sek ConfigView.section.stats.savefile=Ime datoteke sa statistikom ConfigView.section.stats.graph_update_dividers=Prika\u017ei vertikalnu liniju na svakih 60 osve\u017eenja MyTorrentsView.menu.export=&XML torent... MyTorrentsView.menu.host=&Ra\u010dunar... ManagerItem.finishing=Okon\u010davanje ConfigView.dialog.choosedefaulttorrentpath=Molimo da izaberete podrazumevani direktorijum za torente ConfigView.dialog.choosemovepath=Molimo da izaberete direktorjum u koga treba prebaciti ConfigView.label.movecompleted=Pomeri zavr\u0161ene datoteke (posle prijema) ConfigView.label.moveremoved=Pomeri zavr\u0161ene datoteke (pri uklanjanju) ConfigView.label.savetorrents=Sa\u010duvaj torent datoteke MainWindow.menu.view.mytracker=Moj &pratilac MainWindow.menu.view.mytracker.keybinding=Meta+2 MyTrackerView.title.full=Moj pratilac MyTrackerView.name=Ime MyTrackerView.tracker=Pratilac MyTrackerView.status=Status MyTrackerView.status.started=Radi MyTrackerView.status.stopped=Zaustavljen MyTrackerView.peers=Ra\u010dunari MyTrackerView.seeds=Zameci MyTrackerView.announces=Najave MyTrackerView.uploaded=Poslato MyTrackerView.downloaded=Preuzeto MyTrackerView.left=Preostalo ConfigView.section.style=Su\u010delje ConfigView.label.set_ui_transfer_speeds=Preina\u010di izabrane brzine prenosa ConfigView.label.set_ui_transfer_speeds.description=Mo\u017eete da ru\u010dno odredite podrazumevane brzine prijema i slanja koje su dostupne u statusnoj traci u obave\u0161tajnoj zoni.\nVrednosti moraju biti odvojene zapetama. ConfigView.label.set_ui_transfer_speeds.description.download=Postavka brzina prijema (u KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Najve\u0107a brzina slanja (u KB/s) ConfigView.section.style.useCustomTabs=Koristi jezi\u010dke koji se mogu zatvoriti (neophodno ponovno pokretanje) MainWindow.menu.view.plugins=&Pro\u0161irenja fileDownloadWindow.saveTorrentIn=Sa\u010duvaj torent datoteku u fileDownloadWindow.title=Vuze - Prijem torenta fileDownloadWindow.downloading=Prijem od : fileDownloadWindow.status=Status : fileDownloadWindow.state_initializing=Pokretanje fileDownloadWindow.state_downloading=Prijem fileDownloadWindow.state_error=Gre\u0161ka : MainWindow.menu.file.open.url=&Mesto... MainWindow.menu.file.open.url.keybinding=Meta+L openUrl.title=Otvori mesto openUrl.url=URL : MyTorrentsView.menu.host.error.title=Ugo\u0161\u0107enje torenta nije uspelo MyTorrentsView.menu.host.error.message=Naredna gre\u0161ka se dogodila pri ugo\u0161\u0107avanju torenta ConfigView.section.tracker=Pratilac ConfigView.section.tracker.pollinterval=Vremenski interval provere pratioca (sekunde) ConfigView.section.tracker.publishenable=Objava detalja o torentu na \u201e\u201c ConfigView.section.tracker.ip=Spolja\u0161nja IP adresa pratioca MainWindow.menu.help.faq=&\u010cesto postavljana pitanja MainWindow.menu.help.faq.keybinding.mac=Meta+? ConfigView.section.style.enableXPStyle=Dozvoli Iks-pe stil (zahteva restart) IPChecker.external.service.dyndns.name=DynDNS IPChecker.external.service.dyndns.url=http://www.dyndns.org/ IPChecker.external.service.dyndns.description=Dynamic DNS Network Services, LLC ConfigView.section.tracker.checkip=Automatski otkrij eksternu IP adresu... ipCheckerWizard.title=\u010carobnjak za proveru IP adresa ipCheckerWizard.service=Usluga ipCheckerWizard.chooseService=Molimo da izaberete uslugu za proveru IP adrese sa datog spiska ipCheckerWizard.explanations=Mo\u017eete upotrebiti ovog \u010darobnjaka da saznate koja je spolja\u0161nja IP adresa ovog ra\u010dunara. Ako je IP adresa dinami\u010dka, preporu\u010dujemo da otvorite nalog kod nekog dinami\u010dkog DNS servera. Neke od poslu\u017eitelja koji daju ovu uslugu navedeni su ispod. Koristite datu vezu kako biste otvorili nalog (tamo gde je to mogu\u0107e). Zatim ispunite IP adresu polja sa dinami\u010dkim imenom (npr. myhostname.dyndns.org). Bi\u0107e Vam potreban program koji \u0107e automatski obave\u0161tavati dinami\u010dki DNS o IP adresi. Na taj na\u010din \u0107ete mo\u0107i da ugostite torente \u010dak i sa promenljivom IP adresom. ipCheckerWizard.service.description=Opis : ipCheckerWizard.service.url=Veza ipCheckerWizard.progresstitle=Provera IPa ipCheckerWizard.checkComplete=Odre\u0111en IP : ipCheckerWizard.checkFailed=Nije uspelo, razlog: wizard.tracker.local=Koristi Azureusov ugra\u0111en pratilac wizard.tracker.external=Koristi spolja\u0161nji pratilac wizard.tracker.howToLocal= Izaberite \u201eAlati->Pode\u0161avanja->Pratilac\u201c kako biste ga uklju\u010dili wizard.announceUrl=URL za objavu : IPChecker.external.service.discoveryvip.name=Discoveryvip IPChecker.external.service.discoveryvip.url=http://ip.discoveryvip.com/ IPChecker.external.service.discoveryvip.description=Discoveryvip - samo provera IP adrese IPChecker.external.httpinvalidresponse=Neispravan odgovor na HTTP upit IPChecker.external.loadingwebpage= U\u010ditavanje mre\u017ene strane IPChecker.external.analysingresponse=Obrada odgovora IPChecker.external.addressextracted=Izvu\u010dena IP adresa IPChecker.external.httploadfail=U\u010ditavanje strane nije uspelo IPChecker.external.timeout=Vreme je isteklo IPChecker.external.ipnotfound=IP adresa nije prona\u0111ena ConfigView.section.tracker.pollintervalmin=Najmanji ConfigView.section.tracker.pollintervalmax=Najve\u0107i ConfigView.section.tracker.pollintervalincby=Pove\u0107anje ConfigView.section.tracker.pollintervalincper=Svakih n klijenata splash.loadingImages=U\u010ditavanje slika splash.initializeGui=Postavljanje glavnog prozora splash.openViews=Otvaranje pogleda splash.plugin=U\u010ditavanje dodataka : configureWizard.nat.tooManyPorts=Suvi\u0161e portova je ozna\u010deno za proveru (najvi\u0161e 9) ConfigView.section.color=Boje MyTorrentsView.menu.publish=&Objavi... MyTrackerView.status.published=Objavljeno MyTrackerView.completed=Preuzeto MainWindow.menu.file.open.torrentnodefault=Torent datoteka (bez podrazumevanog \u010duvanja) MainWindow.menu.file.open.torrentnodefault.keybinding.mac=Meta+Opt+O wizard.comment=Komentar ConfigView.label.movetorrent=Premesti torent ConfigView.label.movepartialdownloads=Premesti kada su neke datoteke ozna\u010dene sa \u201eNe primaj\u201f ConfigView.label.subdir_is_in_default=Pri odre\u0111ivanju da li postoje preuzete datoteke u podrazumevanom diraktorijumu, pregledaj tako\u0111e i podrazumevane poddirektorijume ConfigView.section.file.decoder.label=Podrazumevano kodiranje torenta kada se tra\u017ei izbor ConfigView.section.file.decoder.nodecoder=Nijedan IPChecker.external.service.no-ip.name=No-IP IPChecker.external.service.no-ip.url=http://www.no-ip.com/ IPChecker.external.service.no-ip.description=Dobavlja\u010d dinami\u010dke i stati\u010dke DNS adrese\n(ne postoji besplatna usluga provere adrese) ConfigView.section.tracker.publicenable=Uklju\u010di spolja\u0161nje torente ConfigView.label.playdownloadspeech=Obavesti glasom o kraju prijema ConfigView.label.playdownloadspeech.info=Govorne usluge trenutno najbolje rade na engleskom jeziku # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Prikazuje broj dostupnih umno\u017eaka svakog dela. Ako je broj zdesna manji od 1, to zna\u010di da cela datoteka nije vidljiva (pa \u0107ete verovatno imati problema da dovr\u0161ite prijem). GeneralView.label.trackerurl.tooltip=Pritisnite da umno\u017eite URL za objavu na klipbord GeneralView.label.trackerurlopen.tooltip=Pritisnite da biste otvorili glavnu stranu pratioca # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Osve\u017ei prikaz svakih ConfigView.section.style.graphicsUpdate=Osve\u017eavanje grafi\u010dkih traka svakih n osve\u017eavanja su\u010delja ConfigView.section.style.reOrderDelay=Preuredi tabele svakih n osve\u017eavanja su\u010delja [0: nikada] ConfigView.section.style.reOrderDelay.never=Nikada ConfigView.section.logging=Bele\u017eenje ConfigView.section.logging.enable=Uklju\u010di bele\u017eenje u datoteku ConfigView.section.logging.logdir=Direktorijum za bele\u0161ke ConfigView.section.logging.choosedefaultsavepath=Molimo da izaberete direktorijum za \u010duvanje GeneralView.label.updatein.querying=Upiti... configureWizard.nat.sharePort=Koristi jedan deljeni ulazni port za sve torente ConfigView.section.logging.maxsize=Najve\u0107a veli\u010dina bele\u0161ki ConfigView.section.tracker.passwordenableweb=Uklju\u010di lozinku za mre\u017eu pratilaca ConfigView.section.tracker.passwordenabletorrent=Uklju\u010di lozinku za torente ConfigView.section.tracker.username=Korisni\u010dko ime ConfigView.section.tracker.password=Lozinka columnChooser.title=Izbor kolona za prikaz columnChooser.move=Prevucite redove kako biste ih preuredili columnChooser.apply=Primeni columnChooser.columnname=Ime kolone columnChooser.columndescription=Opis TableColumn.header.shareRatio=Odnos deljenja MyTorrentsView.menu.editTableColumns=&Pode\u0161avanje kolona wizard.operationfailed=Dejstvo nije uspelo authenticator.title=Potrebna autorizacija authenticator.realm=Oblast authenticator.tracker=Pratilac authenticator.user=Korisni\u010dko ime authenticator.password=Lozinka ConfigView.label.allowSendVersion=Dozvoli Azureusu da \u0161alje anonimni broj izdanja i anonimni identifikator pri proveri novog izdanja ConfigView.label.version.info.link=Posetite ovu vezu za detalje o podacima koji se \u0161alju serveru za proveru izdanja wizard.hint.mode=Savet: Mo\u017eete da prevu\u010dete i pustite datoteku po datoteku na ovog \u010darobnjaka\n kako biste izabrali datoteku ili direktorijum wizard.hint.file=Savet: Mo\u017eete izabrati datoteku prevla\u010denjem i pu\u0161tanjem wizard.hint.directory=Savet: Mo\u017eete da izaberete direktorijum prevla\u010denjem i pu\u0161tanjem MainWindow.menu.help.checkupdate=&Proveri dogradnje... TableColumn.header.down=Preuzeto TableColumn.header.up=Poslato ConfigView.section.tracker.passwordenabletorrent.info=Zahteva podesan Bit Torent klijent (npr. Vuze ConfigView.section.style.confirmationOnExit=Poka\u017ei prozor\u010de za potvrdu pri izlasku MainWindow.dialog.exitconfirmation.title=Izlazak iz Azureusa? MainWindow.dialog.exitconfirmation.text=Da li zaista \u017eelite da zavr\u0161ite rad sa Azureusom? SystemTray.menu.stopalltransfers=Zaustavi &sve prenose TrayWindow.menu.stopalldownloads=Zaustavi sve &prijeme ConfigView.section.tracker.sslport.info=Pogledajte \u010cPP za vi\u0161e podataka wizard.tracker.ssl=Koristi SSL ConfigView.label.playdownloadfinished=Pusti zvuk kada se prenos zavr\u0161i ConfigView.label.popupdownloadfinished=Prika\u017ei obave\u0161tenje o kraju prijema ConfigView.label.popupfilefinished=Obavesti o kraju prijema TableColumn.header.pieces=Delovi TableColumn.header.pieces.info=Grafi\u010dke trake koje predstavljaju preuzete delove TableColumn.header.completion=Zavr\u0161eno TableColumn.header.completion.info=Grafi\u010dki procentualni prikaz prijema ConfigView.section.style.showdownloadbasket=Prika\u017ei korpu za torente (za prevla\u010denje i pu\u0161tanje) ConfigView.section.style.alwaysShowTorrentFiles=Uvek prika\u017ei detalje o torentu wizard.multitracker=Dodaj vi\u0161e pratilaca u torent wizard.multitracker.title=Vi\u0161e pratilaca wizard.multitracker.configuration=Pode\u0161avanje vi\u0161e pratilaca wizard.multitracker.new=Nov... wizard.multitracker.edit=Uredi... wizard.multitracker.delete=Ukloni wizard.multitracker.group=Grupa pratilaca wizard.multitracker.edit.title=Urednik vi\u0161e pratilaca wizard.multitracker.edit.name=Ime wizard.multitracker.edit.save=Sa\u010duvaj wizard.multitracker.edit.newgroup=Nova grupa wizard.multitracker.edit.deletegroup=Ukloni wizard.multitracker.edit.newtracker=Novi pratilac wizard.multitracker.edit.deletetracker=Ukloni wizard.multitracker.edit.edit=Uredi wizard.addingmt=Dodavanje podataka o vi\u0161e pratilaca wizard.multitracker.noannounce=Objava URLa koji nije u Va\u0161em spisku pratilaca MyTorrentsView.menu.recheck=Prinudna &provera iconBar.showDownloadBar.tooltip=Prika\u017ei traku za prijem iconBar.start.tooltip=Pokretanje iconBar.stop.tooltip=Zaustavi iconBar.remove.tooltip=Ukloni iconBar.openNoDefault.tooltip=Otvori torent datoteku (bez podrazumevanog \u010duvanja) iconBar.openURL.tooltip=Otvori URL iconBar.openFolder.tooltip=Otvori direktorijum iconBar.new.tooltip=Napravi torent iconBar.up.tooltip=Pomeri na gore iconBar.down.tooltip=Pomeri na dole iconBar.run.tooltip=Otvori iconBar.host.tooltip=Doma\u0107in iconBar.publish.tooltip=Objavi MyTorrentsView.menu.editTracker=&Uredi URL pratioca GeneralView.menu.selectTracker=Izbor ConfigView.section.stats.xslfile=Ime XSL datoteke ConfigView.section.stats.xslfiledetails=Ovo \u0107e biti uklju\u010deno u zaglavlje sa statistikama pomo\u0107u oznake ConfigView.label.savetorrentbackup=Sa\u010duvaj rezervni umno\u017eak ConfigView.section.tracker.forceport=Prinudna upotreba podrazumevanog porta za spolja\u0161nje torente ConfigView.section.ipfilter.allow=DOZVOLI ove opsege (podrazumeva se ZABRANI) ConfigView.section.ipfilter.list.inrange=je u opsegu ConfigView.section.ipfilter.list.notinrange=nije ni u jednom opsegu ConfigView.section.ipfilter.list.title=Zabranjeni IPovi ConfigView.label.allowsameip=Dozvoli vi\u0161estruku vezu sa istim IPom ConfigView.label.allowsameip.tooltip=Samo uklju\u010dite ako vam ZAISTA treba.\nOvo je za\u0161tita od pijavica (kada je isklju\u010deno). ManagerItem.superseeding=Nad-zametak ConfigView.label.userSuperSeeding=Koristi nad-zametak PeersView.uniquepiece=Deo (kada radi kao nad-zametak) PeersView.uniquepiece.none=Nijedan PeersView.timetosend=Vreme za ponovno slanje dela (kao nad-zametak) ConfigView.section.style.addurlsilently=Pre\u0107utno otvori dostavljeni URL ConfigView.section.style.addurlsilently.tooltip=Automatski prijem prosle\u0111enih ili spu\u0161tenih URLova sa torentima, bez otvaranja prozor\u010deta sa upitom. ConfigView.section.file.decoder.prompt=Uvek pitaj kada postoji izbor kodiranja ConfigView.section.file.decoder.prompt.tooltip=Uvek prika\u017ei prozor\u010de sa izborom kodiranja kada je dostupan MyTorrentsView.menu.moveTop=&Vrh MyTorrentsView.menu.moveEnd=&Dno ConfigView.label.moveonlyusingdefaultsave=samo ako je u podrazumevanom direktorijumu sa podacima ConfigView.label.moveonlyusingdefaultsave.tooltip=Premesti samo ako su preuzeti podaci u podrazumevanom direktorijumu sa podacima ConfigView.label.watchtorrentfolder=Automatski uvezi nove torente ConfigView.label.watchtorrentfolder.tooltip=Redovno pretra\u017euj nove torente ConfigView.label.watchtorrentfolderinterval=Period ConfigView.label.watchtorrentfolderinterval.tooltip=Pauza posle koje \u0107e direktorijum ponovo biti pretra\u017een ConfigView.dialog.choosewatchtorrentfolderpath=Molimo da izaberete direktorijum za uvoz torenta ConfigView.label.startwatchedtorrentsstopped=Pokretanje je obustavljeno ConfigView.label.startwatchedtorrentsstopped.tooltip=Dodaj nove torente u ZAUSTAVLJENOM stanju ConfigView.section.plugins=Dodaci wizard.maketorrent.filesize=Veli\u010dine datoteka wizard.maketorrent.piececount=Broj delova wizard.maketorrent.piecesize=Veli\u010dina delova wizard.maketorrent.auto=Automatski MainWindow.menu.view.stats=&Statistike MainWindow.menu.view.stats.keybinding=Meta+5 SpeedView.title.full=Aktivnost SpeedView.downloadSpeed.title=Prijem SpeedView.uploadSpeed.title=Slanje ConfigView.section.style.useSIUnits=Koristi IEC jedinice (KiB umesto KB itd.) iconBar.top.tooltip=Pomeri na vrh iconBar.bottom.tooltip=Pomeri na dno TableColumn.header.health=Zdravlje MyTorrentsView.menu.health=O zdravlju health.explain.grey=zna\u010di da torent nije pokrenut (i za slanje i za prijem) health.explain.red=zna\u010di da niste povezani ni za jedan udaljeni ra\u010dunar, pri prijemu health.explain.blue=pri zametanju, zna\u010di da jo\u0161 niste povezani ni na jedan ra\u010dunar\npri prijemu, zna\u010di da ste povezani na neke ra\u010dunare, ali da je pratilac oboren health.explain.yellow=zna\u010di da je pratilac u redu, da ste povezani sa ra\u010dunarima, ali nemate nijednu udaljenu vezu.\nMo\u017eda imate problem sa NATom ako svi torenti sve vreme ostaju u \u017eutom stanju health.explain.green=zna\u010di da je sve u redu ConfigView.section.style.alwaysRefreshMyTorrents=Uvek osve\u017ei moje torente ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Ova opcija \u0107e osve\u017eiti prikaz Mojih torenta \u010dak i kada nije prikazan (korisno za neke dodatke za mirc) # #2.0.7.0 # ConfigView.section.style.verticaloffset=Vertikalni grafi\u010dki pomak (zakrpa za GTK) security.certtruster.title=Upozorenje o sigurnosnom serifikatu security.certtruster.intro=Sigurnosni sertifikat je izdala kompanija u koju nemate poverenja security.certtruster.resource=Resurs: security.certtruster.issuedto=Izdat za: security.certtruster.issuedby=Izdao: security.certtruster.prompt=Da li \u017eelite da verujete ovom sertifikatu? security.certtruster.yes=Da security.certtruster.no=Ne ConfigView.section.tracker.torrentsperpage=Koliko torenta po strani ? [0: neograni\u010deno] MainWindow.menu.file.share=&Deljenje MainWindow.menu.file.share.file=&Datoteka... MainWindow.menu.file.share.dir=D&irektorijum... MainWindow.menu.file.share.dircontents=&Sadr\u017eaj direktorijuma... MainWindow.menu.file.share.dircontentsrecursive=Sadr\u017eaj direktorijuma... (rekurzivan) MainWindow.dialog.share.sharefile=Izbor datoteke za deljenje MainWindow.dialog.share.sharedir=Izbor direktorijuma za deljenje MainWindow.dialog.share.sharedircontents=Izbor sadr\u017eaja direktorijuma za deljenje MainWindow.dialog.share.sharedircontents.recursive=Rekurzivno globalmanager.download.remove.veto=Uklanjanje je zabranjeno plugin.sharing.download.remove.veto=Ovaj prijem je rezultat deljenog resursa.\nDa uklonite prijem, uklonite pridru\u017eeno deljenje: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Glavni ConfigView.section.tracker.web=Mre\u017ea ConfigView.label.prioritizefirstpiece=Stavi prioritet na prvi i poslednji deo datoteka ConfigView.label.prioritizefirstpiece.tooltip=Poku\u0161ava da prvo preuzme sam po\u010detak i sam kraj svake datoteke.\nSlu\u017ei da podr\u017ei rani pregled sadr\u017eaja. ConfigView.section.file.confirm_data_delete=Tra\u017ei potvrdu pre uklanjanja podataka ConfigView.section.file.confirm_data_delete.tooltip=Potvrdi uklanjanje podataka pri upotrebi \u201eUkloni i obri\u0161i...\u201c TrayWindow.menu.startalldownloads=Pokreni sve prijeme SystemTray.menu.startalltransfers=Pokreni sve prenose sharing.progress.title=Tok deljenja sharing.progress.hide=Sakrij MainWindow.menu.view.myshares=Deljeno MainWindow.menu.view.myshares.keybinding=Meta+3 MySharesView.title.full=Deljeno MySharesView.name=Ime MySharesView.type=Vrsta MySharesView.type.file=Datoteke MySharesView.type.dir=Direktorijum MySharesView.type.dircontents=Sadr\u017eaja direktorijuma MySharesView.type.dircontentsrecursive=Sadr\u017eaja direktorijuma (rekurzivno) MySharesView.menu.remove=Ukloni ConfigView.section.tracker.extensions=Pro\u0161irenja ConfigView.section.tracker.sendpeerids=Po\u0161alji identitet ra\u010dunara svim prijemnicima ConfigView.section.tracker.enableudp=Dozvoli UDP protokol za pratioce plugin.sharing.torrent.remove.veto=Ova registracija pratioca je posledica deljenja nekog resursa.\nDa biste uklonili prenos uklonite pridru\u017eeno deljenje.: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Prijem se ne mo\u017ee ukloniti po\u0161to nije zaustavljen plugin.sharing.remove.veto=Ovo deljenje je pod-deljenje nekog sadr\u017eaja direktorijuma i ne mo\u017ee se eksplicitno obrisati.\nObri\u0161ite nadre\u0111eno deljenje. GeneralView.label.hash.tooltip=Pritisnite da umno\u017eite identifikator he\u0161a na klipbord ConfigView.section.tracker.maxpeersreturned=Najvi\u0161e vra\u0107enih ra\u010dunara [0: neograni\u010deno] ConfigView.label.serverport=Port za prihvatanje TCP ili UDP veze ConfigView.label.serverport.tooltip=Port mora biti u opsegu 1-65535, i ne sme biti 6880 po\u0161to je taj port odre\u0111en za internu upotrebu Azureusa. configureWizard.nat.server.tcp_listen_port=Dolazni port za slu\u0161anje TCP veze ConfigView.section.sharing=Deljenje ConfigView.section.sharing.usessl=Koristi SSL za deljene resurse (zahteva pode\u0161avanje pratioca) ConfigView.section.style.dropdiraction=Dejstvo pri dovla\u010danju direktorijuma ConfigView.section.style.dropdiraction.opentorrents=Otvaranje torenta ConfigView.section.style.dropdiraction.sharefolder=Deljenje direktorijuma ConfigView.section.style.dropdiraction.sharefoldercontents=Deljenje sadr\u017eaja # # 2.0.7.x # Categories.all=Sve Categories.uncategorized=Bez kategorije CategoryAddWindow.message=Unesite novo ime kategorije CategoryAddWindow.title=Dodaj novu kategoriju ConfigView.label.autoSeedingIgnoreInfo=Zanemareni torenti idu na dno reda za zametanje. Oni se ne pokre\u0107u automatski.\nPravila za zanemarivanje se ne primenjuju na torente koji odgovaraju kriterijumu Prvog prioriteta.\nOsim ako nije druga\u010dije nagla\u0161eno, koristite vrednost 0 da isklju\u010dite ovo pravilo. ConfigView.label.directory=Direktorijum ConfigView.label.disconnetseed.tooltip=Pri zametanju torenta, isklju\u010di sve klijente koji tako\u0111e zame\u0107u.\nOni ne treba da razgovaraju s vama. ConfigView.label.ignoreCase=Zanemari veli\u010dinu slova ConfigView.label.ignoreSeeds=Zanemari torente sa najmanje ConfigView.label.importdirectory=Uvezi direktorijum ConfigView.label.minPeersToBoostNoSeeds.tooltip=Svi torenti bez zametka i sa manje ra\u010dunara od broja kog ste zadali\nbi\u0107e pomereni ka dnu reda. ConfigView.label.minPeersToBoostNoSeeds=Umanji rang zametanja za torente sa manje od ConfigView.label.minSeedingTime.tooltip=Rang zametanja mo\u017ee \u010desto da osciluje u kratkom vremenskom periodu, \u0161to ponekad dovede do automatskog startovanja torenta, kako bi se kasnije samo zaustavili i ponovo postavili u red.\nOvo sre\u0111uje problem forsiranja torenta da nastave da zame\u0107u odre\u0111eni vremenski period. Pa ipak, mo\u017eete zaustaviti ru\u010dno ako \u017eelite. ConfigView.label.minSeedingTime=Najmanje vreme zametanja u sekundama ConfigView.label.minSpeedForActiveDL.tooltip=Prorez za prijem se uvek koristi za prvih 30 sekundi kada se zapo\u010dne nepotpuni torent. ConfigView.label.minSpeedForActiveDL=Ne ra\u010dunaj da torent koristi prorez za prijem ako je brzina manja od ConfigView.label.peers=ra\u010dunara ConfigView.label.queue.debuglog=Zapisuj podatke o gre\u0161kama ConfigView.label.queue.debuglog.info=Dodaje red sa podacima o gre\u0161kama u konzolni ili zapisnik u datoteku.\nIako je kripti\u010dan, ovaj red sa podacima govori o stanju torenta i za\u0161to rade ili ne rade. ConfigView.label.queue.minQueueingShareRatio=Ne stavljaj torente u red niti ih zaustavljaj dok odnos deljenja ne postane ConfigView.label.ratio=odnos ConfigView.label.removeOnStop=Ukloni torent sa spiska po\u0161to se automatski zaustavi ConfigView.label.savedirectory=Sa\u010duvaj direktorijum ConfigView.label.seeding.autoReposition.tooltip=Ako je uklju\u010den, redosled torenta (kolona \u201eBr.\u201c) \u0107e biti promenjena tako da odgovara redosledu zametanja\nOvo je korisno ako ne volite da vidite redosled zametanja, ali i dalje \u017eelite da znate redosled po kome \u0107e torenti biti pokretani. ConfigView.label.seeding.autoReposition=Automatski premesti torente prema redosledu zametanja ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u010cesto se de\u0161ava da ako torenti imaju sa mali broje zametaka i velikim broje ra\u010dunara, da ceo primerak nije dostupan za prijem.\nPrema tome, mo\u017eda ne \u017eelite da postavite pravila prave\u0107i se da postoji potpuna kopija, \u0161to bi neispravno smanjilo redosled ConfigView.label.seeding.fakeFullCopySeedStart=ali samo za torente sa bar ConfigView.label.seeding.ignore=Zanemari pravila ConfigView.label.seeding.ignore0Peers=Zanemari torente sa 0 ra\u010dunara ConfigView.label.seeding.ignoreRatioPeers=Zanemari torente sa bar jednim zametkom na svakih ConfigView.label.seeding.ignoreShareRatio=Zanemari torente sa odnosom deljenja ConfigView.label.seeding.ignore.header.evenFirstPriority=Primeni pravila Prvog prioriteta ConfigView.label.seeding.ignore.header.rule=Pravilo ConfigView.label.seeding.ignore.header.value=Vrednost ConfigView.label.seeding.firstPriority.info=Torenti Prvog prioriteta \u0107e biti uvek na vrhu reda.\nMa koji torent koji ima Prvi prioritet ne\u0107e biti automatski zaustavljan i stavljan u red.\nTorent Prvog prioriteta \u0107e zauzeti prorez za istovremeni prijem ako je neophodno. ConfigView.label.seeding.firstPriority.FP=Prvi prioritet ConfigView.label.seeding.firstPriority=Prvi prioritet ide torentima sa ConfigView.label.seeding.firstPriority.following=od narednih: ConfigView.label.seeding.firstPriority.shareRatio=Odnos deljenja ispod ConfigView.label.seeding.firstPriority.seedingMinutes=Proteklo vreme od promene sa prijema na zametanje ConfigView.label.seeding.firstPriority.DLMinutes=Proteklo vreme od po\u010detka prijema ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Ako se pretvarate da postoji 1 puna kopija na X ra\u010dunara, onda smanjujete redosled torenta sa velikim brojem ra\u010dunara.\nTorenti sa velikim brojem ra\u010dunara najverovatnije ostvaruju i veliki protok.\nTo ne menja nijedan prikaz o broju zametaka. ConfigView.label.seeding.numPeersAsFullCopy=Pretvaranje da postoji 1 puna kopija za svakih\n[0: bez pretvaranja] ConfigView.label.seeding.preferLargerSwarms.tooltip=Ako uglavnom zame\u0107ete torente sa ra\u010dunarima koji su \u201ezaglavljeni\u201c, biranje ve\u0107ih rojeva ima smisla\nKada uglavnom zame\u0107ete torente koji su \u0161iroko dostupni, biranje manjih rojeva ima vi\u0161e smisla. ConfigView.label.seeding.preferLargerSwarms=Kada torenti imaju isti red, biraj manje ve\u0107e rojeve ConfigView.label.seeding.rankType.none.tooltip=Redosled je zasnovan na koloni Br. ConfigView.label.seeding.rankType.none=Nijedan ConfigView.label.seeding.rankType.peerSeed.options=Pode\u0161avanje odnosa zameci:ra\u010dunari ConfigView.label.seeding.rankType.peerSeed.tooltip=Ve\u0107i odnos = ve\u0107i rang ConfigView.label.seeding.rankType.peerSeed=Odnos ra\u010dunari:zameci ConfigView.label.seeding.rankType.seed.fallback=Prebacivanje na odnos ra\u010dunari:zameci posle\n[0: nikad ne prebacuj] ConfigView.label.seeding.rankType.seed.options=Opcije u vezi sa prebrajanjem zametaka ConfigView.label.seeding.rankType.seed.tooltip=Manje zametaka = ve\u0107i redosled ConfigView.label.seeding.rankType.seed=Samo prebrajanje zametaka ConfigView.label.seeding.rankType.timedRotation.tooltip=Svi uvr\u0161\u0107eni potpuni torenti \u0107e se rotirati u zametanju.\nTrajanje vremena zametanja odgovara pode\u0161avanju \u201enajmanje vreme zametanja\u201c ConfigView.label.seeding.rankType.timedRotation=Vremenska rotacija ConfigView.label.seeding.rankType.tooltip=Torenti sa najvi\u0161im redosledom se automatski pokre\u0107u.\nKada neki drugi torent dobije ve\u0107i redosled, torent ni\u017eeg redosleda se zaustavlja i vra\u0107a u red.\n\nSamo torenti u redu su dostupni za automatsko pokretanje.\nZaustavljeni torenti se nikada ne pokre\u0107u automatski. ConfigView.label.seeding.rankType=Pore\u0111aj potpune torente za automatsko pokretanje prema: ConfigView.label.stopAfterMinutes=Jednom preba\u010den na zametanje, obustavi posle ovoliko vremena ConfigView.label.switchpriority.tooltip=Nizak prioritet smanjuje koli\u010dinu propusne mo\u0107i koja je dodeljena torentu. ConfigView.pluginlist.info=Navedeni dodaci su prona\u0111eni. Neki dodaci ne moraju imati jezi\u010dke sa pode\u0161avanjima. ConfigView.pluginlist.noplugins=Nijedan dodatak nije prona\u0111en. ConfigView.section.pluginslist=Spisak ConfigView.section.queue.seeding=Zametanje ConfigView.section.queue.seeding.autoStarting=Automatsko pokretanje ConfigView.section.queue.seeding.ignore=Zanemari pravila ConfigView.section.queue.seeding.firstPriority=Prvi prioritet ConfigView.section.queue.main=Glavni ConfigView.section.queue=Red ConfigView.section.torrents=Torenti ConfigView.text.all=sve ConfigView.text.hours=sati ConfigView.text.ignoreRule=Zanemari pravilo ConfigView.text.ignore=Zanemari ConfigView.text.minutes=minuta ConfigView.text.neverIgnore=Nikada ne zanemaruj ConfigView.text.any=bilo koji DownloadManager.error.datamissing=Nedostaju podaci iconBar.queue.tooltip=Red MainWindow.menu.file.open.torrentforseeding=Torent daoteka... (za zametanje) MainWindow.menu.language.refresh=&Osve\u017ei ManagerItem.forced=Prinu\u0111en ManagerItem.queued=Zakazano MySeedersView.header=Zavr\u0161eni torenti TableColumn.header.availability.info=br. prime\u0107enih kopija TableColumn.header.availability=Dostupnost TableColumn.header.category=Kategorija MyTorrentsView.header=Nepotpuni torenti TableColumn.header.maxuploads=Najve\u0107i broj slanja MyTorrentsView.menu.category.delete=&Ukloni kategoriju MyTorrentsView.menu.forceStart=&Prinudno pokretanje MyTorrentsView.menu.queue=&Red MyTorrentsView.menu.setCategory.add=&Dodaj kategoriju... MyTorrentsView.menu.setCategory=Dodeli kategoriju TableColumn.header.savepath=Sa\u010duvaj stazu TableColumn.header.SeedingRank=Redosled zametanja TableColumn.header.totalspeed.info=Ukupna brzina svih ra\u010dunara s kojim ste u vezi TableColumn.header.totalspeed=Ukupna brzina splash.initializePlugins=Pokretanje dodataka StartStopRules.SPratioMet=Z:R odnos u redu StartStopRules.FP0Peers=FP / 0 ra\u010dunara StartStopRules.0Peers=0 ra\u010dunara StartStopRules.numSeedsMet=Broj zametaka je u redu StartStopRules.ratioMet=Ra\u010d:Zameci u redu StartStopRules.shareRatioMet=Odnos deljenja je u redu StartStopRules.waiting=\u010cekanje StartStopRules.firstPriority=1. prioritet ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Deljenje sadr\u017eaja (i pod-dirova) DownloadManager.error.unabletostartserver=Nije mogu\u0107e pokrenuti server - pregledajte pode\u0161avanja dolaznog porta i dozvole pristupa vatrobranu za program koji treba da bude server GeneralView.label.creationdate=Napravljeno : ConfigView.section.tracker.announcescrapepercentage=Period \u010di\u0161\u0107enja kao procenat najave\nnpr. 200 = 2:1. 0 = neka udaljeni ra\u010d. odlu\u010di ManagerItem.stopping=Zaustavljanje ConfigView.section.tracker.announcecacheperiod=Ke\u0161iraj najavu (milisekunde) ConfigView.section.tracker.scrapecacheperiod=O\u010disti ke\u0161 (milisekunde) ConfigView.section.tracker.scrapeandcache=O\u010disti i ke\u0161iraj ConfigView.section.tracker.announcecacheminpeers=Najavi ke\u0161 MyTrackerView.scrapes=\u010ci\u0161\u0107enja fileDownloadWindow.retry=Ponovni poku\u0161aj MyTrackerView.bytesin=Ul. bajtova MyTrackerView.bytesinave=Sr. ulaz MyTrackerView.bytesout=Izl. bajtova MyTrackerView.bytesoutave=Sr. izlaz ConfigView.section.file.max_open_files=Najvi\u0161e otvorenih datoteka za upis ili \u010ditanje\n[0: neograni\u010deno] ConfigView.section.file.max_open_files.tooltip=Korisno ako primate torente sa stotinama ili hiljadama datoteka i ako dostignete ograni\u010denje u broju otvorenih datoteka operativnog sistema. ConfigView.section.proxy=Pode\u0161avanja zastupnika (proxy) ConfigView.section.proxy.enable_proxy=Uklju\u010di zastupanje (proxying) razgovora sa pratiocima [tra\u017ei restart] ConfigView.section.proxy.host=Doma\u0107in ConfigView.section.proxy.port=Port ConfigView.section.proxy.username=Korisni\u010dko ime ConfigView.section.proxy.password=Lozinka ConfigView.section.proxy.enable_socks=Koristi se SOCKS zastupnik (proxy) wizard.createtorrent.extrahashes=Dodaj he\u0161eve za druge mre\u017ee (npr. Gnutela2, eDonkey2000) GeneralView.label.connected=povezan GeneralView.label.in_swarm=u roju ManagerItem.initializing=Pokretanje AlertMessageBox.error=Gre\u0161ka AlertMessageBox.warning=Upozorenje AlertMessageBox.comment=Podaci AlertMessageBox.information=Podaci AlertMessageBox.unread=Postoje nepro\u010ditana upozorenja - pritisnite ovde da ih pogledate. SharedPortServer.alert.selectorfailed=Nije mogu\u0107e uspostaviti slu\u0161a\u010d za dolazne podatke.\nProverite da li pode\u0161avanja vatrobrana dozvoljavaju programu java(w).exe da radi kao server Tracker.alert.listenfail=Nije mogu\u0107e slu\u0161ati port %1.\nProverite da li postoji neki drugi program koji ve\u0107 koristi ovaj port.\nTako\u0111e proverite da slu\u010dajno ne postoji i radi druga kopija Azureusa. DiskManager.alert.movefileexists=Gre\u0161ka pri preme\u0161tanju gotovih datoteka\nDatoteka %1 ve\u0107 postoji u odredi\u0161nom direktorujumu DiskManager.alert.movefilefails=Gre\u0161ka pri preme\u0161tanju zavr\u0161enih datoteka\nPreme\u0161tanje datoteke %1 nije uspelo, %2 DiskManager.alert.movefilerecoveryfails=Gre\u0161ka pri oporavku posle neuspelog preme\u0161tanja\nOporavak datoteke %1 nije uspeo, %2 ConfigView.section.tracker.logenable=Zapisuj statistike periodi\u010dno u \u201etracker.log\u201c SpeedView.stats.title=Statistike SpeedView.stats.total=Ukupno SpeedView.stats.session=Ova sesija SpeedView.stats.session.tooltip=Ukupno (protokol) SpeedView.stats.downloaded=Primljeno (protokol) SpeedView.stats.uploaded=Poslato (protokol) SpeedView.stats.ratio=Odnos SpeedView.stats.uptime=Vreme rada SpeedView.stats.now=Sada SpeedView.stats.now.tooltip=Ukupno (protokol) AutoMigration.useralert=Rezultat automatske migracije konfiguracionih datoteka i direktorijuma\n\n%1\nSve gre\u0161ke se moraju ru\u010dno obraditi\nNE ZABORAVITE DA OSVE\u017dITE STAZE ZA KONFIGURACIJU AKO SU MIGRIRANE! # # > 2.0.8.0 # OpenTorrentWindow.title=Otvori torente OpenTorrentWindow.message=Eksperimentalno OpenTorrentWindow.addFiles=&Dodaj datoteke OpenTorrentWindow.dataLocation=Mesto za zapis podataka: OpenTorrentWindow.startMode=Dodavanje OpenTorrentWindow.startMode.queued=Zakazano OpenTorrentWindow.startMode.stopped=Zaustavljen OpenTorrentWindow.startMode.forceStarted=Prinudni po\u010detak OpenTorrentWindow.addPosition=Mesto u redu OpenTorrentWindow.addPosition.first=Prvo OpenTorrentWindow.addPosition.last=Poslednje TableColumn.header.remaining.info=Preostala koli\u010dina za prijem TableColumn.header.remaining=Preostalo ConfigView.section.tracker.enablecompact=Dozvoli koncizan protokol za najavu ConfigView.section.tracker.enablekey=Uklju\u010di prosle\u0111ivanje klju\u010da pratiocu za bolju sigurnost ConfigView.section.file.perf=Pode\u0161avanja brzine rada ConfigView.section.file.perf.explain=Upozorenje - neodgovorne izmene ovih parametara mogu ozbiljno da ugroze brzinu prijema. Potreban je i restart.\nAko imate problema sa nedostatkom memorije, razmislite o ograni\u010denju broja veza po torentu (pogledajte pode\u0161avanja prenosa) ConfigView.section.file.max_open_files.explain=Otvaranje suvi\u0161e datoteka mo\u017ee da uzrokuje probleme operativnom sistemu usled ograni\u010denog broja resursa za rad sa datotekama. Ovo ograni\u010dava broj istovremeno otvorenih datoteka. popup.error.hide=Sakrij popup.error.details=Detalji ConfigView.section.style.colorOverrides=Izmena boja ConfigView.section.style.colorOverride.progressBar=Traka napretka ConfigView.section.style.colorOverride.error=Gre\u0161ka MainWindow.status.tooOld=je prestar, molimo da ga dogradite. ConfigView.section.style.colorOverride.warning=Upozorenje ConfigView.section.style.colorOverride.altRow=Naizmeni\u010dni redovi ConfigView.section.file.save.peers.enable=Sa\u010duvaj veze sa ra\u010dunarima za brzo ponovno povezivanje ConfigView.section.file.save.peers.max=Najvi\u0161e brojeva ra\u010dunara koji se \u010duva [0: neograni\u010deno] ConfigView.section.file.save.peers.pertorrent=po torentu ConfigView.label.max_peers_per_torrent=Najve\u0107i podrazumevani broj veza po torentu [0: neograni\u010deno] ConfigView.label.max_peers_total=Najve\u0107i ukupan broj veza [0: neograni\u010deno] ConfigView.section.style.colorOverrides.reset=Vrati boje ConfigView.section.language.info=Kada je uklju\u010deno, Vuze \u0107e potra\u017eiti dogradnje svaki put kada se pokrene. ConfigView.section.language.enableUpdate=Dozvoli mre\u017enu dogradnju ConfigView.section.language.UpdateURL=Osve\u017ei URL ConfigView.section.language.UpdateNow=Dogradi odmah! Button.revert=Vrati MyTorrentsView.menu.changeDirectory=Promeni direktorijum sa podacima GenericText.column=kolona MyTorrentsView.menu.thisColumn.remove=Ukloni kolonu MyTorrentsView.menu.thisColumn.toClipboard=Umno\u017ei tekst na klipbord MyTorrentsView.menu.thisColumn.autoTooltip=Uvek prikazuj obla\u010di\u0107 sa obja\u0161njenjima MyTorrentsView.menu.tracker=Pratilac ConfigView.download.abbreviated=P: ConfigView.upload.abbreviated=S: ConfigView.complete.abbreviated=G: TableColumn.header.secondsseeding=Zametanje za TableColumn.header.secondsseeding.info=Ukupna koli\u010dina vremena koja je provedena u zametanju. TableColumn.header.secondsdownloading=Prijem za TableColumn.header.secondsdownloading.info=Koli\u010dina vremena koja je provedena u prijemu. ConfigView.section.tracker.udpversion=Izdanje UDP protokola (1 ili 2) window.updateswt.title=Izdanje SWT je prestaro! window.updateswt.text=Va\u0161e izdanje biblioteke SWT je prestaro!\nSWT je grafi\u010dka biblioteka koju koristi Vuze a izdanje koje imate je prestaro da bi pokretalo poslednje izdanje Azureusa. Pritisnite dugme \u201eU redu\u201c da biste dogradili SWT. window.updateswt.status=Status window.updateswt.failed=Dogradnja nije uspela, pritisnite ponovo \u201eU redu\u201c da poku\u0161ate ponovo. window.updateswt.status.downloading.updater=Prijem modula za dogradnju window.updateswt.status.finding=Tra\u017eenje poslednjeg izdanja biblioteke SWT window.updateswt.status.downloading=Prijem poslednjeg izdanja SWT window.updateswt.status.done=Ponovno pokretanje window.updateswt.ok=U redu window.updateswt.cancel=Otka\u017ei swt.updater.downloader.downloading=Prijem SWTa sa swt.updater.urlsgetter.downloading=Dobavljanje spiska ogledala sa swt.updater.urlsgetter.platform=SWT za platformu : window.updateswt.ignore=Zanemari ConfigView.section.style.useFancyTabs=Koristi ukrasne jezi\u010dke splash.initializeGM=Pokratenje globalnog upravnika torentima splash.loadingTorrents=U\u010ditavanje torenta splash.firstMessageNoI18N=(: Vuze :) MyTorrentsView.menu.thisColumn.sort=&Re\u0111aj Scrape.status.ok=\u010ci\u0161\u0107enje je u redu Scrape.status.error=Gre\u0161ka pri \u010di\u0161\u0107enju: Scrape.status.error.badURL=URL za najavu ne po\u0161tuje specifikacije o \u010di\u0161\u0107enju Scrape.status.error.nohash=He\u0161 nedostaje u odgovoru. Scrape.status.error.invalid=Odgovor je neispravan. Scrape.status.nextScrapeAt=Slede\u0107e \u010di\u0161\u0107enje u %1 Scrape.status.scraping=\u010ci\u0161\u0107enje... Scrape.status.initializing=\u010cekanje na \u010di\u0161\u0107enje... Scrape.status.scraping.queued=\u010ci\u0161\u0107enje je zakazano... ConfigView.label.minSpeedForActiveSeeding=Ne ra\u010dunaj da zavr\u0161eni torenti koriste prorez ako je brzina ispod ConfigView.section.stats.exportpeers=Izvoz podataka o udaljenom ra\u010dunaru MainWindow.menu.view.irc.moved=Irc je sada dostupan kao dodatak, pogledajte adresu http://azureus.sf.net/plugin_list.php. Kada je postavljen, koristite meni \u201ePregled->Dodaci->IRC\u201c za pristup. MyTrackerView.webui.contextmenu.copyurl=Umno\u017ei URL torenta na klipbord ConfigView.section.file.torrent.ignorefiles=Datoteke koje se zanemaruju pri pravljenju torenta\nnpr. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Zanemarena datoteka ConfigView.section.style.useUnitsRateBits=Upotreba bitova umesto bajtova za protok (KiB/s->Kibit/s itd) ConfigView.section.interface.resetassoc=Resetovanje eksplorerovih povezivanja sa ekstenzijama (.torrent) ConfigView.section.interface.resetassocbutton=Vrati ConfigView.section.interface.checkassoc=Proveri povezivanja na po\u010detku dialog.associations.title=Provera povezivanja Button.yes=&Da Button.no=&Ne ConfigView.label.seeding.autoStart0Peers=Automatsko povezivanje svih gotovih torenta sa 0 ra\u010dunara ConfigView.label.seeding.autoStart0Peers.tooltip=Uklju\u010dite ako \u017eelite da pratilac uvek prijavljuje 0 zametaka za torente sa 0 ra\u010dunara. dialog.associations.prompt=Vuze nije podrazumevani program za obradu Bit Torent datoteka.\nDa li \u017eelite da pove\u017eete .torrent datoteke sa Azureuseom? dialog.associations.askagain=Proveri na po\u010detku ConfigView.section.plugins.update=Dogradnja dodataka Plugin.pluginupdate.enablecheck=Uklju\u010di proveru dogradnji za dodatke plugins.basicview.status=Status: plugins.basicview.activity=Aktivnost plugins.basicview.progress=Napredak: plugins.basicview.log=Zapisnik: ConfigView.label.maxdownloadspeed=Najve\u0107a brzina prijema u KB/s [0: neograni\u010deno] splash.loadingTorrent=Prijem torenta splash.of =od ConfigView.section.plugins.irc=IRC UpdateWindow.title=Dogradnja Azureusa UpdateWindow.header=Slede\u0107e komponente moraju da se dograde : UpdateWindow.columns.install=Postavi UpdateWindow.columns.name=Ime UpdateWindow.columns.version=Izdanje UpdateWindow.columns.size=Veli\u010dina UpdateWindow.cancel=Otka\u017ei UpdateWindow.quit=Kraj UpdateWindow.close=Zatvori UpdateWindow.ok=Osve\u017ei UpdateWindow.restart=Pokreni Azureusa ponovo UpdateWindow.status.downloading=Prijem UpdateWindow.status.done=Gotovo UpdateWindow.status.failed=Neuspelo UpdateWindow.status.restartNeeded=Potrebno je ponovo pokrenuti program! ConfigView.pluginlist.broken=Pokvareno ConfigView.pluginlist.whereToPut=Postavite sve korisni\u010dke dodatke u odgovaraju\u0107i direktorijum ispod: ConfigView.pluginlist.whereToPutOr=Za deljene dodatke koristite: MainWindow.statusText.checking=Proveravanje dogradnji... TableColumn.header.OnlyCDing4=OnlyCDing4 TableColumn.header.OnlyCDing4.info=Vreme koje je torent proveo samo u zametanju. Nije ura\u010dunato vreme kada je torent priman (i zametan u isto vreme). ConfigView.section.style.alternateTablePainting=Koristi drugi na\u010din za crtanje kolona u tabelama (mo\u017ee da tra\u017ei restart) UpdateWindow.status.restartMaybeNeeded=Mo\u017eda \u0107ete morati da ponovo pokrenete program ConfigView.pluginlist.shared=deljeno PeersView.host=Ime ra\u010dunara PeersView.host.info=Ime udaljenog ra\u010dunara, ako je dostupno (mo\u017ee uticati na preformanse) MainWindow.menu.help.whatsnew=\u0160ta ima novo ConfigView.label.checkonstart=Proveri koje je poslednje izdanje pri po\u010detku rada ConfigView.label.periodiccheck=Periodi\u010dno proveri da li postoje nova izdanja ConfigView.label.opendialog=Automatski otvori Saradnika za dogradnju ako dogradnja postoji MainWindow.updateavail=Pritisnite ovde za dogradnju MainWindow.status.unofficialversion=Vuze Beta MainWindow.status.latestversionunchecked=Provera izdanja je isklju\u010dena GeneralView.label.updatein.stopped=Zaustavljen StartStopRules.menu.viewDebug=Pregledaj podatke za ispravljanje gre\u0161aka ConfigView.section.style.doNotUseGB=Ne koristi jedinicu GB ConfigView.section.style.doNotUseGB.tooltip=Ako je uklju\u010deno, Vuze \u0107e nastviti da koristi jedinicu MB \u010dak i za veli\u010dine koje prema\u0161uju 1024MB MainWindow.menu.help.plugins=Dobavi dodatke ConfigView.section.plugins.TrackerWeb=Mre\u017ea pratilaca ConfigView.section.tracker.enablecategories=Razdvoj torente po kategorijama health.explain.share=zna\u010di da je torent ili hostovan ili objavljen ConfigView.section.tracker.createcert=Napravi samopotpisan sertifikat ConfigView.section.tracker.createbutton=Napravljeno security.certcreate.title=Napravi samo potpisan sertifikat security.certcreate.intro=Ovaj prozor\u010di\u0107 vam dozvoljava da napravite samopotpisan sertifikat security.certcreate.alias=Alias security.certcreate.strength=Snaga security.certcreate.firstlastname=Ime i prezime security.certcreate.orgunit=Organizaciona jedinica security.certcreate.org=Organizacija security.certcreate.city=Grad ili mesto security.certcreate.state=Dr\u017eava ili pokrajina security.certcreate.country=Dvoslovni k\u00f4d dr\u017eave security.certcreate.ok=Napravljeno security.certcreate.cancel=Otka\u017ei security.certcreate.createok=Sertifikat je uspe\u0161no napravljen security.certcreate.createfail=Pravljenje sertifikata nije uspelo ConfigView.section.plugins.webui=Svingovo mre\u017eno su\u010delje ConfigView.section.plugins.xml_http_if=XML/HTTP su\u010delje webui.passwordenable=Uklju\u010di lozinku webui.user=Korisni\u010dko ime webui.password=Lozinka webui.port=Port (*) webui.protocol=Protokol (*) webui.homepage=Doma\u0107a strana (*) webui.rootdir=Koreni direktorijum (*) webui.rootres=Koreni resurs (*) webui.mode=Na\u010din (*) webui.mode.info=Na\u010din mo\u017ee biti\n\t\u201epotpun\u201c = dostupna su sva dejstva (podrazumevano)\n\t\u201epogled\u201c = samo pogledi (ali mo\u017ee da pobolj\u0161a u\u010destanost osve\u017eavanja) webui.access=Pristup (*) webui.access.info=Pristup mo\u017ee biti\n\t\u201elokalni\u201c = samo lokalni ra\u010dunar mo\u017ee da se pove\u017ee\n\t\u201esve\u201c = neograni\u010den pristup (podrazumevano)\n\tIP = npr 192.168.0.2\t\t\tsamo jedan IP broj\n\tIP1-IP2 = npr 192.168.0.1-192.168.0.255\tinkluzivan opseg brojeva GeneralView.label.maxdownloadspeed=Brz. prijema Security.keystore.corrupt=Ostava za klju\u010deve \u201e%1\u201c nije u\u010ditana, molimo da je obri\u0161ete i ponovo napravite ili ponovo uvezete sertifikate Security.keystore.empty=Ostava za klju\u010deve je prazna. Molimo da napravite samo-potpisani sertifikat (pogledajte \u201eAlati->Pode\u0161avanja->Bezbednost\u201c) ili uvezite postoje\u0107e sertifikate u \u201e%1\u201c webui.restart.info=Promene parametara sa oznakom (*) tra\u017ee restart kako bi po\u010deli da va\u017ee GeneralView.label.maxdownloadspeed.tooltip=Najve\u0107a brzina prijema [0: neograni\u010dena] ConfigView.section.UPnP=UPnP upnp.enable=Uklju\u010di UPnP upnp.info=Univerzalni PnP (UPnP) omogu\u0107uje automatsko preslikavanje portova na ruterima koji to podr\u017eavaju. upnp.mapping.dataport=Dolazni port za podatke sa ra\u010dunara upnp.mapping.tcptrackerport=Port za TCP pratioca upnp.mapping.udptrackerport=Port za UDP pratioca upnp.alert.differenthost=UPnP: Preslikavanje \u201e%1\u201c je rezervisao ra\u010dunar \u201e%2\u201c - molimo da izaberete drugi port upnp.alert.mappingok=UPnP: Preslikavanje \u201e%1\u201c je omogu\u0107eno upnp.alert.mappingfailed=UPnP: Preslikavanje \u201e%1\u201c nije uspelo upnp.alertsuccess=Objavi uspe\u0161na preslikavanja upnp.alert.lostdevice=UPnP: Izgubljena veza do usluke \u201e%1\u201c na UPnP ure\u0111aju \u201e%2\u201c upnp.grabports=Preslikaj portove \u010dak i ako ih koristi drugi ra\u010dunar upnp.refresh.label=Osve\u017ei preslikavanja upnp.refresh.button=Osve\u017ei upnp.alert.mappinggrabbed=UPnP: Preslikavanje \u201e%1\u201c je uspostavljeno - oteto od \u201e%2\u201c upnp.mapping.tcpssltrackerport=Pratio\u010dev TCP SSL port upnp.alertothermappings=Prijavi portove koje koriste drugi ra\u010dunari upnp.alertdeviceproblems=Prijavi probleme sa UPnP ure\u0111ajem upnp.trace_to_log=Zapisuj detaljne podatke o gre\u0161kama upnp.wiki_link=Strana o UPnPu na Azureusovom vikiju blank.resource=_: blank.resource\n ConfigView.pluginlist.coreplugins=U\u010ditani su naredni ugra\u0111eni dodaci: Peers.column.DLedFromOthers=Od ostalih Peers.column.DLedFromOthers.info=Koli\u010dina podataka preuzeta od drugih dok su bili povezani sa vama Peers.column.UpDownRatio=Sl:Pr Peers.column.UpDownRatio.info=Odnos \u201eprimljeno:poslato\u201c udaljenog ra\u010dunara Peers.column.UpRatio=Odnos prijema Peers.column.UpRatio.info=Odnos \u201epreuzeto od vas : poslato od drugih\u201c udaljenog ra\u010dunara upnp.releasemappings=Otpusni preslikavanja pri kraju rada webui.upnpenable=Dozvoli UPnP za ovaj port (*) ConfigView.section.file.friendly.hashchecking=Prijateljska provera he\u0161a ConfigView.section.file.friendly.hashchecking.tooltip=Ne\u0161to sporija provera ke\u0161a, ali mnogo prijateljskije nastrojena prema procesoru ili sistemu. ConfigView.section.tracker.seedretention=Najvi\u0161e zadr\u017eanih zametaka po torentu [0: neograni\u010deno] ConfigView.section.tracker.seedretention.info=Primedba: Statistike o prijemu bi\u0107e izgubljene za nezadr\u017eane zametke ConfigView.section.tracker.port=Uklju\u010di pratioca na HTTP portu ConfigView.section.tracker.sslport=Uklju\u010di pratioca na HTTPS portu ConfigView.section.tracker.publicenable.info=Ovo dozvoljava drugima da prave torente koji koriste va\u0161eg pratioca dok ga vi ne hostujete niti objavljujete Button.clear=O\u010disti MainWindow.IPs.tooltip=Poslednje osve\u017eenje spiska filtera: %1\nUkupno IP filtera u spisku - Broj blokiranih/zabranjenih/lo\u0161ih IPova za ovu sesiju.\nDupli klik za detalje. ConfigView.section.ipfilter.list.banned=je zabranjen ConfigView.section.ipfilter.list.baddata=je poslao lo\u0161e podatke: ponavljanja = Button.reset=Vrati ConfigView.section.ipfilter.bannedinfo=IPovi koji su slali lo\u0161e podatke - zabranjeni ako se prevr\u0161i mera ConfigView.section.ipfilter.blockedinfo=IPovi koji su blokirani zbog IP filtera download.removerules.name=Pravila za uklanjanje download.removerules.unauthorised.info=Neovla\u0161\u0107eni torenti su oni \u010dija najava sadr\u017ei tekst \u201eneovla\u0161\u0107eno\u201c u odgovoru na gre\u0161ku download.removerules.unauthorised=Automatski ukloni neovla\u0161\u0107ene torente download.removerules.unauthorised.seedingonly= Samo pri zametanju download.removerules.removed.ok=Automatsko uklanjanje torenta \u201e%1\u201c je uspelo. Uzrok ovome su pravila za uklanjanje torenta. download.removerules.updatetorrents=Ukloni Azureusove torente sa dogradnjama kako roj zahteva ConfigView.label.defaultstarttorrentsstopped=Kada se torent doda, dodeljuje mu se stanje \u201eZaustavljeno\u201f ConfigView.section.server.enableudp=Dozvoli klijentski UDP protokol za pratioce upnp.mapping.dataportudp=Klijentski port UDP pratioca ConfigView.section.file.decoder.showlax=Prika\u017ei i manje verovatna kodiranja ConfigView.section.file.decoder.showall=Razmotri sva mogu\u0107a kodiranja MainWindow.status.updowndetails.tooltip=Brzina prijema ili slanja\nDesnim dugmetom se menja, duplim pritiskom se prikazuju statistike TrackerClient.announce.warningmessage=Pratilac za \u201e%1\u201c vratio je upozorenje \u201e%2\u201c ConfigView.section.tracker.natcheckenable=Proveti svu povezivost za \u201eulazni port za podatke\u201c i prijavi gre\u0161ke udaljenim ra\u010dunarima ConfigView.section.tracker.publishenabledetails=Objavi sve detalje torenta ConfigView.section.tracker.publishenablepeerdetails=Objavi detalje o ra\u010dunarima MyTrackerView.badnat=Lo\u0161 NAT MyTrackerView.badnat.info=Zameci i ra\u010dunari koji ne prolaze NAT provere, ako je uklju\u010deno ConfigView.section.tracker.natchecktimeout=Proveri rokove (sekunde) ConfigView.section.file.perf.cache.enable=Uklju\u010di disk ke\u0161 ConfigView.section.file.perf.cache.size=Veli\u010dina ke\u0161a u %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=&Prenosi MainWindow.menu.transfers.startalltransfers=Po&kreni sve MainWindow.menu.transfers.stopalltransfers=&Zaustavi sve MainWindow.menu.transfers.pausetransfers=Pa&uziraj MainWindow.menu.transfers.pausetransfers.keybinding.mac=Meta+. MainWindow.menu.transfers.resumetransfers=&Nastavi ConfigView.label.experimental.osx.kernel.panic.fix=Eksperimentalna zakrpa za gre\u0161ke u jezgru na dvoprocesorskom OS Iks sistemima [tra\u017ei restart] SystemTray.menu.pausetransfers=Pauziraj prenose SystemTray.menu.resumetransfers=Nastavi prenose ConfigView.section.file.truncate.too.large=Odseci postoje\u0107e datoteke koje su prevelike ConfigView.section.file.perf.cache.trace=Prati dejstva na ke\u0161u za potrebe tra\u017eenja gre\u0161aka ConfigView.section.interface.enabletray=Uklju\u010di statusnu traku [tra\u017ei restart] PeerManager.status.error=Gre\u0161ka Stats.title.full=Statistike TransferStatsView.title.full=Prenosi CacheView.title.full=Ke\u0161 CacheView.general.size=Ukupna veli\u010dina CacheView.general.inUse=Koristi se CacheView.general.title=Podaci o ke\u0161u CacheView.reads.title=U/I \u010ditanja CacheView.reads.fromFile=Iz datoteke CacheView.reads.fromCache=Iz ke\u0161a CacheView.reads.hits=Pogoci CacheView.writes.title=U/I upisi CacheView.writes.toCache=U ke\u0161 CacheView.writes.toFile=U datoteku CacheView.writes.hits=Sa\u010duvano CacheView.speeds.title=Brzina CacheView.speeds.reads=\u010citanja CacheView.speeds.writes=Upisi CacheView.speeds.fromCache=Iz/u ke\u0161 CacheView.speeds.fromFile=Iz/u datoteku CacheView.reads.#=br. CacheView.reads.amount=Iznos CacheView.reads.avgsize=Sr. veli\u010dina openUrl.referrer=URL strane za obra\u0107anje : openUrl.referrer.info=Potrebno je samo za el. mesta koja to zahtevaju ConfigView.label.maxuploadspeedseeding=Druga brzina pri zametanju ConfigView.label.transfer.ignorepeerports=Zanemari ra\u010dunare sa ovim portovima (razdvojeno sa \u201e;\u201c npr 0;25) ConfigView.section.proxy.enable_socks.peer=Dozvoli zastupanje (proxying) komunikacije sa ra\u010dunarima (samo odlazne veze) [neophodan restart] ConfigView.section.proxy.peer.informtracker=Obavesti pratioca o ograni\u010denju ConfigView.section.proxy.socks.version=Izdanje SOCKSa PiecesView.legend.written=Zapisano PiecesView.legend.requested=Potra\u017eeno PiecesView.legend.downloaded=Preuzeto, \u010deka se na zapis PiecesView.legend.incache=Podaci su u ke\u0161u PiecesView.typeItem.0=Brz PiecesView.typeItem.1=Spor PiecesView.type=Vrsta Security.jar.tools_not_found=Potpisivanje JAR datoteke nije uspelo - \u201etools.jar\u201c nije na\u0111ena %1. Pogledajte \u201eAlati->Pode\u0161avanja->Bezbednost\u201c za detalje. Security.jar.signfail=Potpis JAR arhive nije uspeo - %1 ConfigView.section.security.toolsinfo=Potpisane JAR datoteke se koriste da podr\u017ee neke dodatke, na primer Svingovo mre\u017eno su\u010delje (kada je pode\u0161en da tako uradi).\nDa bi JAR datoteke bile potpisane potrebno je da imate pristup \u201etools.jar\u201c koji dolazi sa Sanovim JDKom (ne JRE).\nAko imate samo JRE, onda molimo da dodate i JDK.\nVuze obi\u010dno mo\u017ee da prona\u0111e ovu datoteku za vas. Me\u0111utim, ako ovo ne uspe, mo\u017eete eksplicitno da postavite direktorijum za pretragu. ConfigView.section.security.toolsdir=Direktor koji sadr\u017ei \u201etools.jar\u201c ConfigView.section.security.choosetoolssavedir=Izaberite direktorijum koji sadr\u017ei \u201etools.jar\u201c authenticator.torrent=Torent ConfigView.section.proxy.peer.same=Koristite ista pode\u0161avanja zastupnika (proxy) za pratioca i za komunikaciju sa ra\u010dunarima ConfigView.section.connection.network.max.simultaneous.connect.attempts=Najvi\u0161e istovremenih odlaze\u0107ih veza ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Najve\u0107i broj poku\u0161aja odlaznih veza koje Vuze poku\u0161ava u dato vreme.\nPRIMEDBA: Vindovs Iks-pe, servisni paket 2 (SP2) postavlja sistemsko ograni\u010denje od 10 istovremenih poku\u0161aja veza.\nPodrazumevana vrednost je 8. ConfigView.section.file.perf.cache.size.explain=Ke\u0161 se koristi da umanji broj \u010ditanja i upisa na disk. Osim ako koristite javinu opciju \u201e-XX:MaxDirectMemorySize\u201c da eksplicitno postavite koli\u010dinu dostupne memorije za veli\u010dinu ke\u0161a i memorije za u/i potrebe, treba da dr\u017eite ovo pode\u0161avanje bar %1 ispod trenutne maksimalne veli\u010dine VM. Trenutna maksimalna veli\u010dina VM je %2. Za uputstvo kako da to uradite, vidite stranu MemoryUsage na vikiju na adresi %3. Nemogu\u0107nost da se naprave smislena pode\u0161avanja da\u0107e gre\u0161ke o nedostatku memorije. Vi\u0161e od 32MB ke\u0161a je verovatno suvi\u0161e. MyTorrentsView.menu.setSpeed.unlimit=Neograni\u010dena MyTorrentsView.menu.setSpeed.unlimited=Neograni\u010dena MyTorrentsView.menu.setSpeed.disable=Zabrani slanje MyTorrentsView.menu.setSpeed.disabled=Isklju\u010deno MyTorrentsView.menu.setSpeed.in=u MyTorrentsView.menu.setSpeed.slots=proreza od GeneralView.label.maxuploadspeed=Brz. slanja GeneralView.label.maxuploadspeed.tooltip=Najve\u0107a brzina slanja [0: neograni\u010deno] MyTorrents.items.UpSpeedLimit.disabled=Nema slanja MyTorrents.items.UpSpeedLimit.unlimited=Neograni\u010dena TableColumn.header.maxupspeed=Najve\u0107a brzina slanja TableColumn.header.maxupspeed.info=Najve\u0107a brzina slanja po torentu ConfigView.section.file.perf.cache.enable.write=Ke\u0161iraj podatke o pristupu kako bi se umanjio broj upisan na disk i tako\u0111e umanjio broj upisa potrebnih za proveru delova ConfigView.section.file.perf.cache.enable.read=\u010citaj unapred kako bi se pri slanju umanjio broj \u010ditanja diska ConfigView.section.tracker.separatepeerids=Koristi razli\u010dite identitete ra\u010dunara za pratioca i promet podataka ConfigView.section.tracker.separatepeerids.info=Pove\u0107ava anonimnost pri slanju i anonimnom zametanju\npri upotrebi ne-anonimnih pratilaca ConfigView.section.interface.wavlocation=Mesto .wav datoteke ConfigView.section.interface.wavlocation.info=Izaberite .wav datoteku ili ostavi prazno za podrazumevani zvuk ConfigView.section.tracker.server=Server ConfigView.section.tracker.client=Klijent ConfigView.section.tracker.client.connecttimeout=Vreme za povezivanje (sekundi) ConfigView.section.tracker.client.readtimeout=Vreme \u010ditanja (sekundi) MainWindow.menu.tools=&Alati FilesView.path=Staza FilesView.fullpath=Prika\u017ei punu stazu FilesView.remaining=Preostali delovi TableColumn.header.trackername=Ime pratioca TableColumn.header.trackername.info=Ime pratioca zasnovano na URLu za najavu ConfigView.group.override=Pode\u0161avanja za preina\u010denje ConfigView.section.proxy=Pode\u0161avanja zastupnika (proxy) ConfigView.section.file.perf.cache.notsmallerthan=Ne ke\u0161iraj datoteke manje od ovog (u %1) PeersView.menu.blockupload=Blokovsko slanje PeersView.menu.kickandban=Izbaci i u\u0107utkaj PeersView.menu.kickandban.reason=Ru\u010dno u\u0107utkani ra\u010dunari PeersView.state=Stanje PeersView.state.info=Stanje veze sa ra\u010dunarima PeersView.state.pending=Na \u010dekanju PeersView.state.connecting=Povezivanje PeersView.state.handshake=\u010cekanje na susret PeersView.state.established=Potpuno uspostavljeno ConfigView.section.tracker.processinglimits=Granice obrade ConfigView.section.tracker.maxgettime=Najve\u0107e vreme za obradu GET (sekundi) [0: neograni\u010deno] ConfigView.section.tracker.maxgettime.info=Koristi se za najave i \u010di\u0161\u0107enje ConfigView.section.tracker.maxposttimemultiplier=Mno\u017eilac za GET koji se koristi za obradu POST [0: neograni\u010deno] ConfigView.section.tracker.maxposttimemultiplier.info=Koristi se za podno\u0161enje formulara i slanje ConfigView.section.tracker.maxthreads=Najvi\u0161e istovremenih zahteva DownloadManager.error.operationcancancelled=Dejstvo je otkazano Torrent.create.progress.cancelled=Dejstvo je otkazano sharing.progress.cancel=Otka\u017ei wizard.maketorrents.autoopen=Otvori torent za zametanje na kraju ConfigView.section.sharing.rescanenable=Dozvoli periodi\u010dnu proveru deljenja kako bi se videle promene ConfigView.section.sharing.rescanperiod=Period provere (sekunde) ConfigView.section.connection.advanced=Napredna pode\u0161avanja mre\u017ee ConfigView.section.connection.advanced.url=http://www.azureuswiki.com/index.php/AdvancedNetworkSettings ConfigView.section.connection.advanced.mtu=Najve\u0107a jedinica slanja za liniju (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Najve\u0107a veli\u010dina paketa koja se prenosi u jednom ramu preko mre\u017ee.\nAzurezus koristi MTU-40 (MSS) za optimizaciju veli\u010dine podataka u paketu\nPreporu\u010dene vrednosti:\n 576 - Modemska veza\n1492 - PPPoE veza visoke propusne mo\u0107i\n1500 - Eternet, DSL i kablovska veza ConfigView.section.connection.advanced.SO_RCVBUF=Veli\u010dina SO_RCVBUF uti\u010dnice [0: koristi podrazumevanu vrednost] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Postavlja standardnu veli\u010dinu SO_RCVBUF (u bajtovima), tj. veli\u010dinu prijemnog prozora i skaliranje TCPa.\nVuze podrazumevano ne menja ovu vrednost, \u0161to zna\u010di da se koriste vrednosti zadate u operativnom sistemu.\nPrimedba: Linuks udvostru\u010duje ovu vrednost. ConfigView.section.connection.advanced.SO_SNDBUF=Veli\u010dina SO_SNDBUF za uti\u010dnicu [0: koristi podrazumevano za operativni sistem] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Postavlja standarnu veli\u010dinu SO_SNDBUF (u bajtovima), tj. veli\u010dinu TCPovog prozora za slanje.\nAuzreus ostavlja ovo nepode\u0161eno, \u0161to zna\u010di da se koriste vrednosti zadate u operativnom sistemu.\nPrimedba:Linuks udvostru\u010duje ovu vrednost. ConfigView.section.connection.advanced.IPTOS=Vrsta usluge u odlaznim paketima (TOS) ConfigView.section.connection.advanced.IPTOS.tooltip=Postavlja vrstu saobra\u0107aja (TOS) u zaglavlju odlaze\u0107ih IP paketa.\nVuze ostavlja ovu vrednost nepode\u0161enu \u0161to zna\u010di da se koriste podrazumevane vrednosti u oprativnom sistemu.\nPrimeri vrednosti su:\n0x02 za IPTOS_LOWCOST\n0x04 za IPTOS_RELIABILITY\n0x08 za IPTOS_THROUGHPUT\n0x10 za IPTOS_LOWDELAY\nPRIMEDBA: implementacije mre\u017ee mogu da zanemare ovu vrednost, tako da ona jako zavisi od izdanja operativnog sistema i JRE. ConfigView.section.interface.confirm_torrent_removal=Prika\u017ei prozor za potvrdu za uklanjanje torenta ConfigView.section.interface.confirm_torrent_removal.tooltip=Potvrdi uklanjale torenta iz pregleda Mojih torenta. MyTorrentsView.confirm_torrent_removal=Da li sigurno \u017eelite da uklonite?\n TableColumn.header.seed_to_peer_ratio=Odnos broja zametaka i ra\u010dunara TableColumn.header.seed_to_peer_ratio.info=Odnos broja zametaka u roju i broja ra\u010dunara PeersView.connected_time=Vreme veze PeersView.connected_time.info=Ukupno vreme veze sa ra\u010dunarima ConfigView.section.interface.display.add_torrents_silently=Tiho dodavanje torenta ConfigView.section.interface.display.add_torrents_silently.tooltip=Dodaj torente ne pokazuju\u0107i glavni Azureusov prozor TableColumn.header.maxdownspeed=Najve\u0107a brzina prijema TableColumn.header.maxdownspeed.info=Najve\u0107a brzina prijema po torentu PeersGraphicView.title=Roj ConfigView.section.tracker.passwordwebhttpsonly=Dozvoli pristup samo kroz HTTPS TableColumn.header.torrentpath=Mesto torenta TableColumn.header.torrentpath.info=Mesto gde se Torenti \u010duvaju na disku ConfigView.section.sharing.torrentcomment=Komentari za na\u010dinjene torente ConfigView.label.copyanddeleteratherthanmove=Razdvajanje umno\u017eavanja i uklanjanja podataka u dve operacije, umesto pomeranja u jednom potezu - ovo mo\u017ee da spre\u010di gubitak podataka na nekim sistemima datoteka ConfigView.label.openstatsonstart=Otvori statistike pri pokretanju swt.install.window.title=Azureusov postavlja\u010d dodataka swt.install.window.ok=Postavi swt.install.window.header=Naredne komponente su izabrane za postavljanje : swt.uninstall.window.title=Azureusov uklanja\u010d dodataka swt.uninstall.window.ok=Ukloni swt.uninstall.window.header=Naredne komponente su izabrane za uklanjanje : installPluginsWizard.title=Postavi dodatke installPluginsWizard.mode.title=Molimo da izaberete na\u010din postavljanja installPluginsWizard.mode.list=Prema spisku sa sourceforge.net installPluginsWizard.list.title=Spisak dodataka koji se mogu postaviti installPluginsWizard.list.loading=Molimo Vas da sa\u010dekate dok se spisak dodataka u\u010dita. installPluginsWizard.list.loaded=Molimo da izaberete dodatke koje \u017eelite da postavite. installPluginsWizard.list.name=Ime installPluginsWizard.list.version=Izdanje installPluginsWizard.list.description=Opis dodatka installPluginsWizard.finish.title=Postavljanje je u toku installPluginsWizard.finish.explanation=Izabrani dodaci \u010de biti postavljeni upotrebom saradnika za dogradnju.\n\nMolimo Vas za malo strpljenja, bi\u0107e potrebno malo vremena da se prika\u017eu.\n\nZa izve\u0161taj o napretku, dvaput pritisnite statusnu traku. installPluginsWizard.details.loading=Detalji se u\u010ditavaju, molimo da sa\u010dekate... installPluginsWizard.mode.file=Po datoteci installPluginsWizard.installMode.title=Molimo da odaberete vrstu postavljanja installPluginsWizard.installMode.user=Postavi dodatke samo za Vas installPluginsWizard.installMode.shared=Postavi dodatke za sve korisnike installPluginsWizard.file.title=Molimo da izaberete dodatke koje \u017eelite da postavite installPluginsWizard.file.file=Datoteka : installPluginsWizard.file.invalidfile=Ova datoteka nije ispravan dodatak za Azureus. installPluginsWizard.file.no_such_file=Nema nijedne datoteke sa navedenim imenom. installPluginsWizard.file.browse=Pregled... uninstallPluginsWizard.title=Ukloni dodatak uninstallPluginsWizard.list.title=Spisak postavljenih dodataka uninstallPluginsWizard.list.loaded=Molimo da izaberete dodatke koje \u017eelite da uklonite. installPluginsWizard.list.nullversion=Nema oznake izdanja uninstallPluginsWizard.finish.title=Uklanjanje je u toku uninstallPluginsWizard.finish.explanation=Izabrani dodaci bi\u0107e uklonjeni pomo\u0107u saradnika za dodatke. MainWindow.menu.plugins.installPlugins=\u010carobnjak za dodatke... MainWindow.menu.plugins.uninstallPlugins=\u010carobnjak za uklanjanje dodataka... ConfigView.section.ipfilter.totalIPs=Blokiranih adresa %1 , \u0161to \u010dini %2 celog interneta. update.instance.install=Provera postavljanja update.instance.uninstall=Provera uklanjanja update.instance.update=Proveravanje dogradnji... MainWindow.status.update.tooltip=Dvaput pritisnite za podatke o napretku updater.progress.window.title=Trenutno aktivne dogradnje updater.progress.window.info=Pritisnite \u201eOtka\u017ei\u201c kako biste zaustavili sve aktivne dogradnje Button.abort=Otka\u017ei ConfigView.section.ipfilter.enablebanning=U\u0107utkaj ra\u010dunare koji stalno \u0161alju lo\u0161e podatke Network.alert.acceptfail=Suvi\u0161e uzastopnih gre\u0161aka na portu %1, %2 - obrada je napu\u0161tena. Molimo da proverite pode\u0161avanja vatrobrana za ovaj port kako biste bili sigurni da je uklju\u010den za primljene veze. MyShares.column.category=Kategorija UpdateWindow.restartLater=Pokreni Azureusa ponovo, ali kasnije MainWindow.menu.file.restart=Pokreni ponovo MainWindow.dialog.restartconfirmation.title=Da li da ponovo pokrenem Azureusa? MainWindow.dialog.restartconfirmation.text=Da li zaista \u017eelite da restartujete Azureusa? deletetorrent.message1=Samo \u0161to niste uklonili TORENT za :\n deletetorrent.message2=\nDa li sigurno da \u017eelite da nastavite? ConfigView.label.prioritizemostcompletedfiles=Uredi datoteke sa visokom prioritetom prema procentu zavr\u0161etka i veli\u010dini datoteke splash.plugin.init=Pokretanje dodatka: ConfigView.section.style.osx_small_fonts=Koristi sitna slova [tra\u017ei ponovno pokretanje] ConfigView.section.tracker.tcpnonblocking=Koristi ne-blokiraju\u0107i UI za obradu TCP pratilaca. Biranje ove mogu\u0107nost tra\u017ei da se za mre\u017eu pratilaca koristi drugi port. Eksperimentalno! ConfigView.section.tracker.nonblocking=Neblokiraju\u0107a pode\u0161avanja ConfigView.section.tracker.nonblockingconcmax=Najve\u0107i broj istovremenih veza [0: neograni\u010deno] MyTorrentsView.menu.exportmenu=Izvoz MyTorrentsView.menu.exporttorrent=Torent... ConfigView.group.scrape=\u010ci\u0161\u0107enje ConfigView.section.tracker.client.scrapeinfo=Isklju\u010divanje \u010di\u0161\u0107enja \u0107e spre\u010diti mnoga pravila za ure\u0111ivanje torenta da rade po\u0161to se oslanjaju na podatke koje dobavljaju od \u010di\u0161\u0107enih pratilaca. ConfigView.section.tracker.client.scrapeenable=Dozvoli \u010di\u0161\u0107enje ConfigView.section.tracker.client.scrapestoppedenable=O\u010disti torente koji nisu pokrenuti Scrape.status.disabled=\u010ci\u0161\u0107enje je isklju\u010deno MyTorrentsView.menu.explore=Poka\u017ei datoteku MyTorrentsView.menu.explore._mac=Poka\u017ei u pretrazi MyTorrentsView.menu.explore._windows=Poka\u017ei u istra\u017eiva\u010du wizard.maketorrents.autohost=Ugosti torent na ugra\u0111enom pratiocu ConfigView.label.overrideip=Zanemari objavljene IPove pratilaca - spisak razdvojen ta\u010dka-zapetama ukoliko ih ima vi\u0161e za razli\u010dite mre\u017ee ConfigView.label.overrideip.tooltip=Obavesti pratioca o razli\u010ditim IP adresama sa kojih dolazi neki paket. Ostavite prazno da ne koristite ovu mogu\u0107nost. ConfigView.section.connection.group.networks=Mre\u017ee ConfigView.section.connection.group.networks.info=Izaberite podrazumevane dozvoljene mre\u017ee za prenos ConfigView.section.connection.networks.prompt=Upitaj za izbor pri prijemu anonimnog pratioca ConfigView.section.connection.networks.Public=Javna IP mre\u017ea (nije anonimna) ConfigView.section.connection.networks.I2P=I2P mre\u017ea ConfigView.section.connection.networks.Tor=Mre\u017ea lukovice (Tor) TableColumn.header.networks=Mre\u017ee TableColumn.header.networks.info=Mre\u017ee sa kojih je dozvoljena komunikacija Scrape.status.networkdisabled=Mre\u017ea nije uklju\u010dena ConfigView.section.tracker.server.group.networks=Mre\u017ee ConfigView.section.tracker.server.group.networks.info=Izaberite mre\u017ee sa kojih \u0107e pratilac dozvoljavati pristup ra\u010dunarima window.networkselection.title=Izbor mre\u017ee window.networkselection.info=Navedni torenti podr\u017eavaju naredne mre\u017ee.\nIzaberite one koji dozvoljavaju pratioce i komunikaciju.\nAko je ovo anonimni pratilac koji podr\u017eava javne klijente, onda uklju\u010dite i javne i privatne mre\u017ee.\nDozvoljavanje javnih mre\u017ea o\u010digledno uklanja anonimnost! window.networkselection.description=Torent : plugins.basicview.clear=O\u010disti ConfigView.section.connection.group.peersources=Izvori ra\u010dunara ConfigView.section.connection.group.peersources.info=Izaberite podrazumevane izvore za veze sa ra\u010dunarima ConfigView.section.connection.peersource.Tracker=Sa pratioca ConfigView.section.connection.peersource.DHT=Decentralizovano pra\u0107enje ConfigView.section.connection.peersource.PeerExchange=Od drugih ra\u010dunara ConfigView.section.connection.peersource.Plugin=Sa nekog dodatka ConfigView.section.connection.peersource.Incoming=Dolaze\u0107a veza PeersView.source=Izvor PeersView.source.info=Izvor ovog ra\u010dunara TableColumn.header.peersources=Izvori ra\u010dunara TableColumn.header.peersources.info=Izvori ra\u010dunara koji su dozvoljeni za veze sa ra\u010dunarima wizard.tracker.dht=Decentralizovano (samo Azureusovi klijenti) MyTorrentsView.menu.advancedmenu=Napredno MyTorrentsView.menu.networks=Mre\u017ee MyTorrentsView.menu.peersource=Izvori ra\u010dunara ConfigView.section.sharing.permitdht=Dozvoli decentralizovano pra\u0107enje kada je pratilac nedostupan ConfigView.section.sharing.protocol=Protokol za deljene resurse PeersView.Messaging=Poruke PeersView.Messaging.info=Pokazuje koji se sistem za poruke koristi. ConfigView.label.queue.newseedsmovetop=Pomeri nove zavr\u0161ene torente na vrh spiska za zametanje ConfigView.label.seeding.firstPriority.ignore.info=Imajte na umu da upotreba ovih pravila mo\u017ee zaustaviti torente\n\u010dim se prijiem zavr\u0161i. ConfigView.label.seeding.firstPriority.ignore=Zanemari Prve prioritete iznad za: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torente sa odnosom zametaka prema ra\u010dunarima preko ConfigView.label.seeding.firstPriority.ignore0Peer=Torente sa 0 ra\u010dunara ConfigView.section.tracker.sendjavaversionandos=Po\u0161alji izdanje Jave i ime operativnog sistema MagnetPlugin.contextmenu.exporturi=Umno\u017ei Magnet URI na klipbord ConfigView.section.plugins.dht=Distribuirana baza podataka dht.info=Ovaj dodatak podr\u017eava decentralizovano pra\u0107enje izme\u0111u ostalog - isklju\u010divanje \u0107e pogor\u0161ati prijem dht.enabled=Uklju\u010di distribuiranu bazu podataka dht.portdefault=Koristi podrazumevani port dht.port=UDP port za bazu podataka dht.execute.command=Dijagnosti\u010dka komanda dht.execute.info=Pritisnite da izvr\u0161ite komandu dht.execute=Pokreni dht.logging=Uklju\u010di pra\u0107enje dejstava ConfigView.section.plugins.dhttracker=Distribuirani pratilac dhttracker.tracknormalwhenoffline=Samo prati normalne torente kada pratilac nije dostupan ConfigView.section.file.nativedelete._mac=Koristi Kantu pri uklanjanju datoteka ConfigView.section.file.nativedelete._windows=Pomeri obrisane datoteke u Kantu ConfigView.section.logging.generatediagnostics=Napravi ConfigView.section.logging.netinfo=Napravi detalje o mre\u017ei ConfigView.section.logging.statsinfo=Napravi podatke o statistici ConfigView.section.logging.generatediagnostics.info=Napravi dijagnosti\u010dke podatke i umno\u017ei ih na klipbord i u zapisnik, ako je to dozvoljeno ConfigView.section.sharing.privatetorrent=Privatni torent - prihvata samo ra\u010dunare sa pratioca MainWindow.menu.tools.nattest=&Provera NATa / vatrobrana Button.apply=Primeni Button.close=Zatvori window.welcome.title=Dobrodo\u0161li u Vuze %1 #file can be a URL or a path in the jar window.welcome.file=/changelog.txt MainWindow.menu.help.releasenotes=Bele\u0161ke o izdanju dht.reseed.label=Obi\u010dno, ponovno zametanje distribuirane baze nije potrebno. Me\u0111utim, ako je broj kontakata nizak, ovo se mo\u017ee koristiti za ponovno uklju\u010denje u mre\u017eu.\nOstavite prazno kako bi se za pokretanje koristili priklju\u010deni ra\u010dunari ili eksplicitno unesite IP broj i port za pokretanje pomo\u0107u poznatog ra\u010dunara. dht.reseed.group=Opet zametak dht.reseed.ip=IP adrese dht.reseed.port=Port dht.reseed=Opet zametak dht.reseed.info=Ponovo zametni bazu podataka dht.diagnostics.group=Dijagnoza DHTView.title.full=Distribuirana baza podataka DHTView.title.fullcvs=SUV za distribuiranu bazu podataka DHTView.general.title=Op\u0161te DHTView.general.uptime=Vreme od po\u010detka: DHTView.general.users=Korisnika: DHTView.general.nodes=Ra\u010dunara: DHTView.general.leaves=Listova: DHTView.general.contacts=Kontakata: DHTView.general.replacements=Zamena: DHTView.general.live=\u017divih: DHTView.general.unknown=Nepoznatih: DHTView.general.dying=Mrtvih: DHTView.transport.title=Detalji o transportu DHTView.transport.packets=Paketa DHTView.transport.bytes=Bajtova DHTView.transport.received=Primljeno DHTView.transport.sent=Poslato DHTView.transport.in=Dospelo: DHTView.transport.out=Poslato: DHTView.operations.title=Detalji o operaciji DHTView.operations.sent=Poslato DHTView.operations.ok=U redu DHTView.operations.failed=Neuspelo DHTView.operations.received=Primljeno DHTView.operations.ping=Ping DHTView.operations.findNode=Na\u0111i ra\u010dunar DHTView.operations.findValue=Na\u0111i vrednost DHTView.operations.store=Zapamti DHTView.activity.title=Aktivnost DHTView.activity.status=Status DHTView.activity.status.true=Zakazano DHTView.activity.status.false=Radi DHTView.activity.type=Vrsta DHTView.activity.type.1=Interna dobavka DHTView.activity.type.2=Eksterna dobavka DHTView.activity.type.3=Interna nabavka DHTView.activity.type.4=Eksterna nabavka DHTView.activity.target=Odredi\u0161te DHTView.activity.details=Detalji DHTView.db.title=Baza podataka DHTView.db.keys=Klju\u010devi DHTView.db.values=Vrednosti DHTView.db.local=Lokalno DHTView.db.direct=Direktno DHTView.db.indirect=Indirektno DHTView.db.divfreq=Frekv. podela DHTView.db.divsize=Veli\u010dina podele MainWindow.dht.status.tooltip=Kada distribuirana baza podataka radi, pokazuje procenjeni broj aktivnih korisnika MainWindow.dht.status.disabled=DHT isklju\u010dena MainWindow.dht.status.failed=DHT nije ispravna MainWindow.dht.status.initializing=Pokretanje DHT MainWindow.dht.status.users=korisnika: %1 MainWindow.dht.status.unreachable=DHT je pod vatrobranom MainWindow.dht.status.unreachabletooltip=Izgleda postoji problem sa preslikavanjem UDP porta distribuirane baze podataka (NAT/vatrobran) MyTorrentsView.menu.setUpSpeed=Postavi brzinu slanja MyTorrentsView.menu.setDownSpeed=Postavi brzinu prijema ConfigView.section.tracker.client.showwarnings=Prika\u017ei upozorenja koje pokazuju pratioci dht.advanced=Uklju\u010di napredna pode\u0161avanja dht.advanced.group=Napredna pode\u0161avanja dht.advanced.label=Menjajte ove vrednosti samo ako dobro znate \u0161ta radite dht.override.ip=Preina\u010di spolja\u0161nju IP adresu ConfigView.section.logging.loggerenable=Uklju\u010di bele\u017eenje ConfigView.section.ipfilter.blockbanning=Zabrani blok od 256 adresa kada je bar ovoliko u bloku zabranjeno MyTrackerView.passive=Pasivno TableColumn.header.swarm_average_speed=Sr. brzina roja TableColumn.header.swarm_average_speed.info=Srednja brzina ra\u010dunara u roju TableColumn.header.comment=Komentar TableColumn.header.comment.info=Korisnikov komentar za prijem TableColumn.header.commenticon=Sli\u010dica za komentar TableColumn.header.commenticon.info=Prikazuje sli\u010dicu ako prijem ima korisni\u010dki definisan komentar MyTrackerView.category=Kategorija MainWindow.menu.file.open.torrentfortracking=Torent datoteku (samo za pra\u0107enje) VivaldiView.title.full=Vivaldi MyTrackerView.date_added=Dodato ConfigView.section.tracker.portbackup=Rezervni portovi (\u201e;\u201c za razdvajanje) ConfigView.label.playfilespeech=Obavesti glasom o kraju prijema ConfigView.label.playfilespeech.info=Govorne usluge trenutno najbolje rade na engleskom jeziku ConfigView.label.playfilefinished=Pusti zvuk kada se prenos datoteke zavr\u0161i ConfigView.label.backupconfigfiles=Pri svakom dejstvu napravi rezervni umno\u017eak datoteka sa pode\u0161avanjima ConfigView.section.tracker.client.scrapesingleonly=Zabrani udru\u017eivanje \u010dista\u010da po pratiocu (mo\u017ee da pomogne oko pratilaca koji javljaju da je URL preduga\u010dak (gre\u0161ka 414)) dht.ipfilter.log=Bele\u017ei prekr\u0161aje IP filtriranja ConfigView.label.seeding.addForSeedingDLCopyCount=Razmislite o upotrebi \u201edodaj za zametanje\u201c za prijem ovoliko umno\u017eaka ActivityView.legend.limit=Ograni\u010denje protoka ActivityView.legend.achieved=Ostvaren protok ActivityView.legend.peeraverage=Srednja ActivityView.legend.swarmaverage=Prosek roja ActivityView.legend.trimmed=Opse\u010dena (ta\u010dke) MyTorrentsView.menu.movemenu=Pomeri datoteke MyTorrentsView.menu.movedata=Pomeri datoteke sa podacima... MyTorrentsView.menu.movetorrent=Pomeri torent datoteku... MyTorrentsView.menu.movedata.dialog=Izbor novog mesta DHTView.operations.data=Podaci DHTView.general.reachable=Dostupni: DHTView.general.rendezvous=Susret: ConfigView.label.queue.maxactivetorrentswhenseeding=Najve\u0107a brzina zametanja [0: neograni\u010dena] IrcView.title.short=IRC Views.plugins.IRC.title=IRC - tehni\u010dka podr\u0161ka na mre\u017ei Formats.units.persec=/s Formats.units.TiB=TiB Formats.units.Tibit=Tibit Formats.units.TB=TB Formats.units.Tbit=Tbit Formats.units.GiB=GiB Formats.units.Gibit=Gibit Formats.units.GB=GB Formats.units.Gbit=Gbit Formats.units.MiB=MiB Formats.units.Mibit=Mibit Formats.units.MB=MB Formats.units.Mbit=Mbit Formats.units.KiB=KiB Formats.units.Kibit=Kibit Formats.units.kB=kB Formats.units.KB=KB Formats.units.kbit=kbit Formats.units.B=B Formats.units.bit=bit Formats.units.alot=Mnogo !!! ConfigView.section.ipfilter.persistblocking=\u010cuvaj podatke o blokiranim IP brojevima FilesView.menu.rename=Preimenuj ili promeni cilj FilesView.menu.rename_only=Preimenuj FilesView.menu.retarget=Preusmeri FilesView.rename.choose.path=Izbor nove ili postoje\u0107e datoteke FilesView.rename.choose.path.dir=Izbor novog ili postoje\u0107eg direktorijuma FilesView.rename.confirm.delete.title=Potvrda brisanja FilesView.rename.confirm.delete.text=POtvrdi brisanje izvorne datoteke \u201e%1\u201c FilesView.rename.filename.title=Preimenuj FilesView.rename.filename.text=Izbor novog imena za datoteku ConfigView.section.mode=Na\u010din rada ConfigView.section.mode.title=Korisnikovo znanje ConfigView.section.mode.beginner=Po\u010detnik ConfigView.section.mode.beginner.wiki.definitions=Re\u010dnik Bit Torenta ConfigView.section.mode.intermediate=Prose\u010dan ConfigView.section.mode.intermediate.wiki.host=Ugo\u0161\u0107avanje datoteka ConfigView.section.mode.intermediate.wiki.publish=Objava datoteka ConfigView.section.mode.advanced=Napredno ConfigView.section.mode.advanced.wiki.main=Glavna strana na vikiju ConfigView.section.mode.beginner.text=Sve \u0161to Vam treba za prijem torenta.\nKoristite ovaj na\u010din rada ako samo \u017eelite da upravljate torentima. ConfigView.section.mode.intermediate.text=Pristup funkcijama pratioca.\nKoristite ovaj na\u010din rada ako \u017eelite da napravite sopstvenog pratioca i hostujete ili objavljujete svoje datoteke. ConfigView.section.mode.advanced.text=Pristup mre\u017enim pode\u0161avanjima\nKoristite ovaj na\u010din rada ako znate koje su vrednosti za MTU ili mre\u017eno blokiranje. Files.column.storagetype=Vrsta skladi\u0161ta Files.column.fileext=Vrsta FileItem.storage.linear=Linearan FileItem.storage.compact=Kompaktan MessageBoxWindow.rememberdecision=Zapamti moju odluku ConfigView.section.interface.cleardecisions=Ukloni zapam\u0107ene odluke u prozor\u010detu ConfigView.section.interface.cleardecisionsbutton=O\u010disti ConfigView.section.interface.cleartrackers=Ukloni zapam\u0107ene pratioce ConfigView.section.interface.cleartrackersbutton=O\u010disti ConfigView.section.interface.clearsavepaths=Ukloni zapam\u0107ene staze za \u010duvanje ConfigView.section.interface.clearsavepathsbutton=O\u010disti configureWizard.welcome.usermodes=Pode\u0161avanje ve\u0161tine korisnika odre\u0111uje nivo detalja koji se prikazuje u \u201eAlati->Pode\u0161avanja\u201c. U Va\u0161em je interesu da ovo ispravno postavite. FilesView.skip.confirm.delete.text=Da li treba skratiti datoteku \u201e%1\u201c za u\u0161tedu prostora? FilesView.rename.failed.title=Promena imena ili cilja nije uspela FilesView.rename.failed.text=Dejstvo nije uspelo, mogu\u0107e zbog neispravnog izbora cilja diagnostics.log_found=Vuze nije ispravno isklju\u010den pro\u0161li put. Molimo da proverite i u njemu poruke o gre\u0161kama i razmislite o tome da ih prijavite Azureusivim timu ukoliko su nastale usled gre\u0161ke u programu. Tako\u0111e proverite viki (vidite meni za pomo\u0107) i stavku \u201eVuze nestaje\u201c ManagerItem.paused=Pauzirano Utils.link.visit=Molimo da posetite ConfigView.section.connection.serverport.wiki=Dobri izbori za portove ConfigView.section.transfer.speeds.wiki=Dobra pode\u0161avanja brzine installPluginsWizard.installMode.info.title=Podaci installPluginsWizard.installMode.info.text=Dodaci nisu neophodni da bi Vuze ispravno radio. Oni daju\nposebne mogu\u0107nosti za zabavu, automatizaciju rada ili daljinsko upravljanje.\nZato molimo da pro\u010ditate pa\u017eljivo opis svakog dodatka pre nego \u0161to \nodlu\u010dite da ga postavite.\nVe\u0107ina dodataka su bezbedni za probanje, ali nemojte preoptere\u0107ivati\ninstalaciju dodacima koje ne koristite. Views.plugins.Distributed.DB.title=Distribuirana baza podataka Views.plugins.Distributed.Tracker.title=Distribuirani pratilac Views.plugins.Plugin.Update.title=Dogradnja dodataka Views.plugins.UPnP.title=UPnP Views.plugins.UPnP.title.tooltip=Univerzalni PnP openUrl.url.info=Podr\u017eava http, https, magnet i sirove heksa nizove TableColumn.header.swarm_average_completion=Usrednjena kompletnost TableColumn.header.swarm_average_completion.info=Srednja gotovost kod ra\u010dunara u roju GeneralView.label.swarm_average_completion=Srednja gotovost: GeneralView.label.swarm_average_completion.tooltip=Srednja gotovost kod ra\u010dunara u roju MainWindow.nat.status.unknown=NAT MainWindow.nat.status.tooltip.unknown=Status NATa i vatrobrana je nepoznat (TCP) MainWindow.nat.status.ok=NAT je u redu MainWindow.nat.status.tooltip.ok=Ra\u010dunar je dostupan (TCP) MainWindow.nat.status.probok=NAT je u redu? MainWindow.nat.status.tooltip.probok=Ra\u010dunar je dostupan, ali odavno niko nije uspostavio TCP vezu MainWindow.nat.status.bad=Pod vatrobranom MainWindow.nat.status.tooltip.bad=Mogu\u0107i problem sa NATom ili vatrobranom. (TCP). Potra\u017eite pomo\u0107 na vikiju plugin.installer.recommended.plugin=Preporu\u010deni dodatak - molimo da pogledate i postavite ako je potrebno LoggerView.pause=Pauziraj bele\u017eenje LoggerView.clear=&O\u010disti LoggerView.filter=Filter LoggerView.filter.uncheckAll=Ukloni oznaku sa svih kategorija LoggerView.filter.checkAll=Proveri sve kategorije LoggerView.loggingDisabled=Bele\u017eenje nije uklju\u010deno. LoggerView.includeOnly=Prikaz samo linija koje se uklapaju u regularni izraz: LoggerView.excludeAll=Prikaz samo linija koje se ne uklapaju u regularni izraz ConfigView.section.logging.log0type=Podaci ConfigView.section.logging.log1type=Upozorenje ConfigView.section.logging.log2type=Gre\u0161ka ConfigView.section.logging.filter=Filtriranje pri bele\u017eenju u datoteku ConfigView.section.logging.level=Detaljnost bele\u017eenja ConfigView.section.logging.showLogsFor=Prika\u017ei ovoliko dnevnika (%1) za naredne kategorije: ConfigView.pluginlist.column.loadAtStartup=U\u010ditaj na po\u010detku ConfigView.pluginlist.column.type=Vrsta ConfigView.pluginlist.column.type.perUser=Po korisniku ConfigView.pluginlist.column.type.shared=Deljeno ConfigView.pluginlist.column.type.builtIn=Ugra\u0111eno ConfigView.pluginlist.column.name=Ime ConfigView.pluginlist.column.version=Izdanje ConfigView.pluginlist.column.directory=Direktorijum ConfigView.pluginlist.column.isOperational=Da li radi? PeersView.BlockView.Avail.Have=Oba imaju PeersView.BlockView.Avail.NoHave=Udaljeni ima; Vi ne PeersView.BlockView.NoAvail.Have=Vi imate; udaljeni ima PeersView.BlockView.NoAvail.NoHave=Niko nema PeersView.BlockView.Transfer=Prenos PeersView.BlockView.NextRequest=Naredni zahtev PeersView.BlockView.title=Karta delova PeersView.BlockView.AvailCount=Dostupnost MyTorrentsView.dialog.NumberError.title=Neispravan ili neprepoznat broj MyTorrentsView.dialog.NumberError.text=Broj kog ste uneli nije ispravan ili nije prepoznat. MyTorrentsView.menu.manual=&Ru\u010dno... MyTorrentsView.menu.manual.per_torrent=Ru\u010dno (po torentu) MyTorrentsView.menu.manual.shared_torrents=Ru\u010dno (za sve torente) MyTorrentsView.dialog.setSpeed.title=Postavi brzinu %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Unesi broj %1 da se promeni %2 u: MyTorrentsView.dialog.setNumber.upload=slanje MyTorrentsView.dialog.setNumber.download=prijem MyTorrentsView.dialog.setNumber.inKbps=prijem: %1 OpenTorrentWindow.torrentLocation=Torenti za prijem: OpenTorrentWindow.addFiles.URL=Dodaj &URL OpenTorrentWindow.addFiles.Folder=Dodaj &direktorijum OpenTorrentWindow.addFiles.Clipboard=Dodaj sa &klipborda OpenTorrentWindow.changeDestination=Promena odredi\u0161ta OpenTorrentWindow.fileList=Datoteke u torentima: OpenTorrentWindow.torrentTable.name=Ime OpenTorrentWindow.torrentTable.saveLocation=Sa\u010duvaj mesto OpenTorrentWindow.fileTable.fileName=Ime datoteke OpenTorrentWindow.fileTable.size=Veli\u010dina OpenTorrentWindow.fileTable.destinationName=Ime odredi\u0161ta OpenTorrentWindow.startMode.seeding=Zametanje OpenTorrentWindow.fileList.changeDestination=Promena odredi\u0161ta OpenTorrentWindow.mb.badSize.title=Nekompatibilna datoteka OpenTorrentWindow.mb.badSize.text=\u201e%1\u201c nije \u201e%2\u201c i ne mo\u017ee biti kori\u0161\u0107eno za zametanje OpenTorrentWindow.mb.alreadyExists.text=\u201e%3\u201f je ve\u0107 dodat kao \u201e%2\u201f OpenTorrentWindow.mb.alreadyExists.default.name=Medijum OpenTorrentWindow.mb.alreadyExists.title=Ve\u0107 postoji OpenTorrentWindow.mb.openError.title=Gre\u0161ka pri otvaranju OpenTorrentWindow.mb.openError.text=\u201e%1\u201c nije mogao biti otvoren: \n%2 OpenTorrentWindow.torrent.remove=Ukloni torente sa spiska OpenTorrentWindow.torrent.options=Slede\u0107a pode\u0161avanja \u0107e biti primenjena samo na torente izabrane iznad: OpenTorrentWindow.xOfTotal=(%1 od %2) iconBar.open.tooltip=Otvori torente LocaleUtil.column.text=Nepoznat tekst Tracker.tooltip.MultiSupport=Ovaj pratilac podr\u017eava vi\u0161estruka \u010di\u0161\u0107enja he\u0161eva po zahtevu. Tracker.tooltip.NoMultiSupport=Ovaj pratilac ne podr\u017eava vi\u0161estruka \u010di\u0161\u0107enja he\u0161eva po zahtevu.\nBrzina prenosa nije ugro\u017eena, ali dodatno optere\u0107uje pratioca. ConfigView.label.lazybitfield=Koristi lenjo polje bitova (poma\u017ee zametanje na mre\u017eama koje koriste polje bitova za blokiranje) LoggerView.realtime=Osve\u017eavanje u realnom vremenu ConfigView.section.file.perf.cache.flushpieces=Zapisuj zavr\u0161ene delove odmah na disk. Ovo re\u0161ava problem pristupa disku ali mo\u017ee da ima za posledicu pove\u0107anje broja upisa. ConfigView.section.file.writemblimit=Najve\u0107i broj zapisa koji \u010dekaju (u %1) ConfigView.section.file.writemblimit.explain=Kada je brzina zapisa na disk ni\u017ea od brzine prijema, ovaj parametar ograni\u010dava koliko \u0107e podataka biti stavljeno na \u010dekanje pre nego \u0161to se brzine prijema smanje. ConfigView.section.file.readmblimit=Najve\u0107i broj zahteva za \u010ditanje na \u010dekanju (u %1) ConfigView.section.file.readmblimit.explain=Ovaj parametar ograni\u010dava koli\u010dinu memorije koja se koristi za \u010duvanje \u010ditanja koja \u010dekaju na obradu. Button.moveUp=Pomeri na &gore Button.moveDown=Pomeri na &dole ConfigView.notAvailableForMode=Ovaj odeljak je namenjen za na\u010din rada %1 ili vi\u0161i. Nije dostupan u na\u010dinu rada %2. health.explain.error=Ovaj torent sadr\u017ei gre\u0161ku. Pogledajte kolonu \u201eStatus\u201c ili balon\u010di\u0107 na sli\u010dici koja prikazuje gre\u0161ku. GeneralView.label.trackerscrapeupdate=O\u010disti pratioca PeersView.piece=Deo PeersView.piece.info=Poslednji broj dela kog je tra\u017eio ovaj ra\u010dunar PiecesView.priority=Prioritet PiecesView.priority.info=Prioritet za zavr\u0161etak ovog dela; ne obra\u0107ajte preterano pa\u017enju na njega PiecesView.speed=Brzina PiecesView.speed.info=Sporiji ra\u010dunari nemaju priliku da mnogo operi\u0161u sa br\u017eim delovima TableColumn.header.AvgAvail.info=Zbir dostupnosti delova podeljen brojem delova, podeljen brojem veza TableColumn.header.AvgAvail=Sr. dostupnost/delu ConfigView.label.strictfilelocking=Prinudi na ekskluzivno zaklju\u010davanje datoteka pri upisu za sve torente MyTorrentsView.menu.rescanfile=Periodi\u010dno proveri nezavr\u0161ene delove MyTorrentsView.menu.clear_resume_data=O\u010disti podatke o ponovnom pokretanju Plugin.extseed.name=Spolja\u0161nji zameci Plugin.localtracker.name=Pretraga lokalnih ra\u010dunara Plugin.localtracker.info=Pronalaza\u010d ra\u010dunara u lokalnoj mre\u017ei poku\u0161ava da na\u0111e vi\u0161e kopija Azureusa koji rade iza istog vatrobrana na zajedni\u010dkoj mre\u017ei\nkako bi pove\u0107ao efikasnost prenosa uspostavljanjem saradnje izme\u0111u njih Plugin.localtracker.enable=Uklju\u010di pronalaza\u010d ra\u010dunara u lokalnoj mre\u017ei azinstancehandler.alert.portclash=Sukob portova je otkriven u lokalnoj mre\u017ei: %1 ve\u0107 koristi neki drugi korisnik Azureusa. Izaberite nove (slu\u010dajne) portove za prihvatanje TCP i UDP veza [izme\u0111u %2 i %3]. ConfigView.section.transfer.lan=LAN ConfigView.section.transfer.lan.tooltip=Pode\u0161avanja posebno za LAN ConfigView.section.transfer.lan.uploadrate=Najve\u0107a brzina slanja u KB/s za LAN [0: neograni\u010deno] ConfigView.section.transfer.lan.uploadrate.tooltip=Veze sa ra\u010dunarima u LANu imaju odvojene granice za slanje. ConfigView.section.transfer.lan.downloadrate=Najve\u0107a brzina prijema u KB/s za LAN [0: neograni\u010deno] ConfigView.section.transfer.lan.downloadrate.tooltip=Veze sa ra\u010dunarima u istom LANu imaju odvojene granice za brzinu prijema. TorrentOptionsView.title.short=Pode\u0161avanja TorrentOptionsView.title.full=Pode\u0161avanja TorrentOptionsView.param.max.peers=Najve\u0107i ukupan broj veza [0: neograni\u010deno] ConfigView.section.connection.encryption.require_encrypted_transport=Zahtevaj \u0161ifrovan prenos ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Zahtevaj upotrebu \u0161ifrovanih veza sa drugim ra\u010dunarima. ConfigView.section.connection.encryption.min_encryption_level=Najmanji nivo \u0161ifrovanja ConfigView.section.connection.encryption.min_encryption_level.tooltip=Obi\u010dan - samo pozdrav\nRC4 - ceo tok\n\u0160to ve\u0107i nivo \u0161ifrovanja, ve\u0107i su i procesorski zahtevi. Peers.column.Encryption=\u0160ifrovanje Peers.column.Encryption.info=Nivo \u0161ifrovanja koji se koristi ConfigView.section.connection.encryption.encrypt.info=Ako je \u0161ifrovanje uklju\u010deno, ne\u0107ete mo\u0107i da se pove\u017eete sa nekompatibilnim klijentima osim ako ne napravite rezervna pode\u0161avanja ConfigView.section.connection.encryption.encrypt.info.link=Molimo da posetite ovu vezu za vi\u0161e podataka MainWindow.sr.status.tooltip.ok=Odnos deljenja %1 je u redu MainWindow.sr.status.tooltip.poor=Odnos deljenja %1 je slab: < 0.9 MainWindow.sr.status.tooltip.bad=Odnos deljenja %1 je lo\u0161: < 0.5 ConfigView.section.style.status=Statusna traka: ConfigView.section.style.status.show_sr=Odnos deljenja ConfigView.section.style.status.show_nat=Stanje NATa ConfigView.section.style.status.show_ddb=Stanje DDBa ConfigView.section.style.status.show_ipf=Status IPFiltra (IPFilter) ConfigView.section.connection.encryption.encrypt.group=\u0160ifrovanje i skrivanje prenosa ConfigView.section.connection.encryption.encrypt.fallback_info=Uklju\u010divanje bilo kojeg rezervnog pode\u0161avanja \u0107e dozvoliti vezu sa nekompatibilnim klijentima ali ne\u0107e koristiti \u0161ifrovane veze ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Dozvoli ne\u0161ifrovane odlazne veze ako \u0161ifrovan prenos ne uspe ConfigView.section.connection.encryption.encrypt.fallback_incoming=Dozvoli dolazne veze koje nisu \u0161ifrovane ConfigView.section.connection.encryption=\u0160ifrovanje prenosa upnp.selectedinterfaces=Izabrana mre\u017ena su\u010delja (razdvojite sa \u201e;\u201c, npr. eth0;eth1) [prazno: sve] ConfigView.section.style.defaultSortOrder=Podrazumevani poredak ConfigView.section.style.defaultSortOrder.desc=Opadaju\u0107i ConfigView.section.style.defaultSortOrder.asc=Rastu\u0107i ConfigView.section.style.defaultSortOrder.flip=Suprotno od prethodnog poretka LoggerView.autoscroll=Automatsko pomeranje Button.selectAll=Izaberi sve Button.markSelected=Ozna\u010di izabrane Button.unmarkSelected=Ukloni oznaku za izabrane plugins.basicview.config=Pode\u0161avanje TorrentOptionsView.param.max.uploads=Najve\u0107i broj proreza za slanje [najmanje: 2] MyTorrentsView.dialog.setPosition.title=Postavi mesto MyTorrentsView.dialog.setPosition.text=Unesite mesto za izabrane torente: MyTorrentsView.menu.reposition.manual=Premesti... ConfigView.section.connection.advanced.info.link=Molimo da posetite ovu vezu za vi\u0161e podataka ConfigView.section.connection.advanced.socket.group=Pode\u0161avanja priklju\u010daka ConfigView.section.connection.advanced.bind_port=Prive\u017ei za lokalni port [0: isklju\u010deno] ConfigView.section.connection.advanced.bind_port.tooltip=Odlazne veze \u0107e u lokalu biti povezane sa datim portom.\nUklju\u010divanje ovoga mo\u017ee da pomogne sa nestabilnostima kod NAT rutera. ConfigView.section.proxy.group.tracker=Razgovor sa pratiocima ConfigView.section.proxy.group.peer=Razgovor sa ra\u010dunarima Pieces.column.Requested=Potra\u017eeno Pieces.column.Requested.info=Prikazuje da li vi\u0161e zahteva mogu da se odnose na isti deo ili ne (*) ConfigView.label.maxuploadsseeding=Drugo pode\u0161avanje za zametanje MyTorrentsView.filter=Filter: popup.error.hideall=Sakrij sve ConfigView.section.style.dataStatsOnly=Prika\u017ei statistike samo za podatke (sakrij statistike za protokol) ConfigView.section.style.separateProtDataStats=Prika\u017ei razdvojene statistike za podatke i protokol MyTorrentsView.dialog.setFilter.title=Izmeni filter MyTorrentsView.dialog.setFilter.text=Odeljak %1 \u0107e biti filtriran po tekstu kog ovde unesete. Koristite znak \u201e|\u201c (cev) da filtrirate po vi\u0161e fraza. MyTorrentsView.filter.tooltip=Ctrl+X za prebacivanje izme\u0111u obi\u010dne pretrage i pretrage po regularnim izrazima.\nKoristite znak \u201e|\u201c (cev) da biste filtrirali po vi\u0161e fraza. MyTorrentsView.clearFilter.tooltip=O\u010disti filter MyTorrentsView.menu.filter=Spisak filtera... ConfigView.section.file.resume.recheck.all=Kod oporavka posle ru\u0161enja, proveri celu datoteku i zavr\u0161ene delove (u suprotnom samo one delove koji su bili aktivni pri poslednjem \u010duvanju) ConfigureWizard.language.choose=Izaberite jezik sa dole navedenog spiska: popup.closing.in=Zatvaranje prozora: %1 s popup.more.waiting=Broj poruka: %1 # > 2402 popup.next=> popup.previous=< (%1) popup.download.finished=\u201e%1\u201f je zavr\u0161io sa prijemom. popup.file.finished=\u201e%1\u201f je zavr\u0161io sa prijemom. ConfigView.auto=Automatski Plugin.localtracker.autoadd.info=Automatski dodaj ove lokalne ra\u010dunare [\u201e;\u201f odvaja adrese, npr. 1.2.3.4] Plugin.localtracker.autoadd= Eksplicitni ra\u010dunari Plugin.localtracker.networks.info=Smatraj da su navedene mre\u017ee lokalne [\u201e;\u201f odvaja mre\u017ee, npr. 145.227.*.*] Plugin.localtracker.networks= Lokalne mre\u017ee MainWindow.menu.view.plugins.logViews=Pregledi dnevnika SpeedView.stats.autospeed=Automatska brzina slanja SpeedView.stats.autospeed.disabled=Ova mogu\u0107nost je ili isklju\u010dena (potreban je DHT) ili se ne koristi (brzina slanja je ru\u010dno pode\u0161ena) SpeedView.stats.idlePing=Ping: SpeedView.stats.maxPing=Najv. ping: SpeedView.stats.currentPing=Trenutni ping: SpeedView.stats.maxUp=Najve\u0107a brzina slanja: ConfigView.pluginlist.unloadSelected=Ukloni izabrane ConfigView.pluginlist.scan=Potra\u017ei nove dodatke ConfigView.section.transfer.autospeed=Autom. brzina (klasi\u010dna) ConfigView.section.transfer.autospeed.tooltip=Pode\u0161avanja za automatsku regulaciju brzine ConfigView.section.transfer.autospeed.info=Automatsko pode\u0161avanje brzine pode\u0161ava gornju granicu brzine prenosa kako bi se izbeglo preoptere\u0107enje mre\u017ene veze.\n\nOve granice se primenjuju samo ako je uklju\u010dena automatska regulacija brzine slanja, i tako\u0111e zahteva da je uklju\u010dena distribuirana baza podataka.\n ConfigView.section.transfer.autospeed.minupload=%1 najmanja brzina slanja ConfigView.section.transfer.autospeed.minupload.tooltip=Brzina slanja ne\u0107e biti postavljena ispod ove granice ConfigView.section.transfer.autospeed.maxupload=%1 najve\u0107a brzina slanja [0: neograni\u010deno] ConfigView.section.transfer.autospeed.maxupload.tooltip=Brzina slanja ne\u0107e biti postavljena iznad ove granice ConfigView.section.transfer.autospeed.chokeping=Vreme za ping za prigu\u0161enje [ms] ConfigView.section.transfer.autospeed.chokeping.tooltip=Vremena pingovanja koja su ve\u0107a od ove vrednosti bi\u0107e uzeta kao znak da je mre\u017ea zasi\u0107ena ConfigView.section.transfer.autospeed.enableauto=Uklju\u010di pri prijemu i zametanju ConfigView.section.transfer.autospeed.enableautoseeding=Uklju\u010di samo pri zametanju ConfigView.pluginlist.column.unloadable=Isklju\u010div ConfigView.section.transfer.lan.enable=Dozvoli odvojena ograni\u010denja brzine za LAN veze Plugin.localtracker.wellknownlocals=Automatski uklju\u010di povratne i sli\u010dne lokalne mre\u017ee (192.168...) TableColumn.header.filesdone=Gotovo datoteka TableColumn.header.filesdone.info=Preuzetih datoteka/ukupno datoteka ili nepresko\u010denih daotteka (ukupno datoteka)/ukupno nepresko\u010denih datoteka (ukupno datoteka) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=\u010deka se na pokretanje DDB... MagnetPlugin.report.searching=tra\u017eenje... MagnetPlugin.report.found=na\u0111eno: %1 MagnetPlugin.report.alive=\u017eiv: %1 MagnetPlugin.report.dead=mrtav: %1 MagnetPlugin.report.tunnel=tunelovanje do %1 MagnetPlugin.report.downloading=prijem sa %1 MagnetPlugin.report.error=gre\u0161ka %1 MagnetURLHandler.report.no_sources=nijedan izvor nije na\u0111en za torent MagnetURLHandler.report.torrent_size=veli\u010dina torenta: %1 MagnetURLHandler.report.percent=gotovo: %1% MagnetURLHandler.report.error=gre\u0161ka %1 DHTTransport.report.request_all=tra\u017eenje celog prenosa od %1 DHTTransport.report.received_bit=primljeno %1 do %2 od %3 DHTTransport.report.complete=gotovo DHTTransport.report.timeout=vreme je isteklo, nema odgovora od %1 DHTTransport.report.rerequest_all=ponovno tra\u017eenje celog prenosa od %1 DHTTransport.report.rerequest_bit=ponovo tra\u017eenje %1 do %2 od %3 DHTTransport.report.timeout_some=vreme je isteklo, primeljnih paketa: %1 od %2, ali nekompletnih DHTTransport.report.sending=slanje podataka DHTTransport.report.resending=ponovno slanje DHTTransport.report.send_complete=poslato DHTTransport.report.send_timeout=vreme je isteklo ConfigView.section.transfer.autospeed.enabledebug=Zapisuj podatke o gre\u0161kama TableColumn.header.date_added=Datum dodavanja TableColumn.header.date_added.info=Datum kada je torent dodat ConfigView.section.file.hashchecking.smallestfirst=Proveri prvo najmanje prijeme platform.win32.baddll.info=Vuze je primeti prisustvo '%1'. To je deo '%2' i poznato je da mo\u017ee bude uzrok ozbiljnih prpoblema poput ru\u0161enja programa i velike zauzetosti procesora. Ako se suo\u010dite sa nekim od ovih problema, molimo da ukllonite program ili ga podesite da ne uti\u010de na Azureusa. platform.win32.baddll.niphk=Normanov Anti-virus platform.win32.baddll.nvappfilter=NVidijin vatrobran platform.win32.baddll.netdog=Li\u010dni vatrobran Armor2net platform.win32.baddll.vlsp=Venturi vatrobran platform.win32.baddll.imon=NOD32 platform.win32.baddll.sarah=Vatrobran na aplikacijskom nivou, FRITZ! platform.win32.baddll.MxAVLsp=VKom-ovi (VCom) alati za opravku (Fix-It) platform.win32.baddll.mclsp=Mekefijeva (McAfee) slu\u017eba za privatnost platform.win32.baddll.radhslib=Naomi Internet filter (Radijant) platform.win32.baddll.nl_lsp=NetLimiter platform.win32.baddll.winsflt=PjurSajt (PureSight), filter Internet sadr\u017eaja platform.win32.baddll.AxShlex=120% alkohol platform.win32.baddll.iFW_Xfilter=Li\u010dni vatrobran Iolo (iolo) platform.win32.baddll.WSOCKHK=Mre\u017ena dadilja upnp.ignorebaddevices=Zanemari ure\u0111aje koji ne odgovore kako treba upnp.ignorebaddevices.info=Zanemareni ure\u0111aji: %1 upnp.ignorebaddevices.reset=O\u010disti spisak zanemarenih ure\u0111aja upnp.ignorebaddevices.reset.action=Vrati upnp.ignorebaddevices.alert=Ure\u0111aj UPnP na mestu %1 je zanemaren usled u\u010destalih gre\u0161aka. Pogledajte pode\u0161avanja za UPnP dodatak za dostupne mogu\u0107nosti u vezi s ovim dejstvom. TorrentOptionsView.param.max.uploads.when.busy=KB/s najve\u0107e brzine slanja kada je dostignuto globalno ograni\u010denje brzine slanja [0: neograni\u010deno] UpdateMonitor.messagebox.verification.failed.title=Provera postavke nije uspela UpdateMonitor.messagebox.verification.failed.text=Provera \u201e%1\u201f nije uspela: %2 UpdateMonitor.messagebox.accept.unverified.title=Prihvati neproverenu dogradnju UpdateMonitor.messagebox.accept.unverified.text='%1' izgleda nije zvani\u010dni Azureusov dodatak.\nAko zaista nije zvani\u010dan dodatak, NE BISTE trebali da nastavite.\nDa li da nastavim postavljanje? FileView.BlockView.title=Delovi datoteke FileView.BlockView.Done=Gotovo FileView.BlockView.Skipped=Presko\u010den FileView.BlockView.Active=Aktivan FileView.BlockView.Outstanding=Preostalo ConfigView.label.tcplistenport=Dolazni port za slu\u0161anje TCP veze ConfigView.label.udplistenport=UDP port za slu\u0161anje upnp.portchange.alert=Naredni portovi su promenjeni kako bi se izbegli problemi sa UPnP ure\u0111ajem: %1 [stari port=%2] %3 [stari port=%4] ConfigView.section.proxy.username.info=Ako zastupnik (proxy) tra\u017ei autentifikaciju \u010dak i ako nije definisana, koristite nisku \u201e\u201f za korisni\u010dko ime. ConfigView.label.maxuploadswhenbusymin=Najve\u0107a brzina slanja kada je mera\u010d vremena pokrenut [s] MainWindow.menu.help.debug=Zapi\u0161i podatke za ispravljanje gre\u0161aka (dnevnik ru\u0161enja) DownloadManager.error.badsize=Neispravna veli\u010dina ConfigView.section.NATPMP=NAT-PMP natpmp.info=NAT-PMP je Eplova (Apple) zamena za UPnP koju podr\u017eavaju nove Erport (Airport) stanice.\n\nTrenutno je neophodno da UPnP bude uklju\u010den kako bi i NAT-PMP bio dostupan, po\u0161to se NAT-PMP ure\u0111aj tretita kao posebna vrsta UPnP ure\u0111aja. natpmp.enable=Uklju\u010di (i Erportovo pode\u0161avanje mora biti uklju\u010deno kako bi ovo radilo) ConfigView.section.tracker.host.addurls=Obezbedi da je URL ovog pratioca prisutan u torentima koji se dele ConfigView.filter=unesite tekst za filtriranje ConfigView.section.files.move=Preme\u0161tanje posle prijema ConfigView.section.file.defaultdir.section=Izvorne opcije za direktorijum ConfigView.section.file.defaultdir.auto=Automatski prijem u direktorijum za prijem (bez pitanja) ConfigView.section.file.defaultdir.bestguess=Koristi najbolju pretpostavku za direktorijum za prijem ConfigView.section.file.defaultdir.ask=Izvorni direktorijum: ConfigView.section.file.defaultdir.lastused=Postavi podrazumevani direktorijum za prijem na mesto gde je poslednji put snimano ConfigView.section.file.config.section=Pode\u0161avanja ConfigView.section.file.config.currentdir=Trenutni direktorijum za pode\u0161avanja: ConfigView.section.torrent.decoding=Dekodiranje skupa znakova ConfigView.section.logging.udptransport=Uklju\u010di iscrpan izve\u0161taj o UDP prenosu Tracker.announce.ignorePeerSeed=Zanemaruje se broj ra\u010dunara/zametaka. %1 ConfigView.section.connection.encryption.use_crypto_port=Koristite pro\u0161irenje za pratioca pod imenom \u201ekriptoport\u201f kako biste spre\u010dili poku\u0161aje obi\u010dnih veza. Neki pratioci ne podr\u017eavaju ovu mogu\u0107nost pa \u0107e javiti gre\u0161ku poput \u201eneva\u017ee\u0107i port\u201f ili \u201eneispravan parametar\u201f TorrentOptionsView.param.reset.to.default=Vrati nazad na izvorne vrednosti TorrentOptionsView.param.reset.button=Vrati natpmp.routeraddress=Adresa stanice [prazno: automatski] ConfigView.section.style.disableAlertSliding=Isklju\u010di animaciju i postavljanje na vrh za hitne poruke ConfigView.section.transfer.autospeed.maxinc=najve\u0107e pove\u0107anje po ciklusu %1 ConfigView.section.transfer.autospeed.maxdec=najve\u0107e umanjenje po ciklusu %1 ConfigView.section.transfer.autospeed.enabledownadj=Uklju\u010di pode\u0161avanje brzine prijema ConfigView.section.transfer.autospeed.downadjratio=Prijem : Odnos brzina (npr. 2.0 -> granica za brzinu prijema je dvostruko ve\u0107a od brzine slanja) ConfigView.section.transfer.autospeed.latencyfactor=Faktor koji se koristi kao veza izme\u0111u ka\u0161njenja i promene brzine (ve\u0107i broj zna\u010di manju osetljivost) ConfigView.section.transfer.autospeed.reset=Vrati izvorne vrednosti ConfigView.section.transfer.autospeed.reset.button=Vrati PeerColumn.activationCount=Broj ra\u010dunara koji \u017eele da se pove\u017eu: %1 TableColumn.header.timesincedownload.info=Proteklo vreme od prijema podataka za torent TableColumn.header.timesincedownload=Prijem stoji TableColumn.header.timesinceupload.info=Proteklo vreme od slanja podataka za torent TableColumn.header.timesinceupload=Slanje stoji PeersView.incomingreqcount=Dolazni zahtevi PeersView.incomingreqcount.info=Broj dolaznih zahteva koje je ra\u010dunar poslao PeersView.outgoingreqcount=Odlazni zahtevi PeersView.outgoingreqcount.info=Broj odlaznih zahteva poslatih udaljenom ra\u010dunaru upnp.mapping.trackerclientudp=Klijentski port UDP pratioca upnp.mapping.dhtudp=Distribuirana baza podataka ConfigView.section.connection.nondata.udp.same=Koristi isti UDP port za distribuiranu bazu podataka i UDP pratilac ConfigView.section.connection.tcp.enable=Uklju\u010di TCP ConfigView.section.connection.udp.enable=Uklju\u010di UDP ConfigView.section.style.showiconbar=Prika\u017ei alatnu traku MainWindow.menu.view.iconbar=Alatna traka MyTorrentsView.menu.rename=Preimenuj MyTorrentsView.menu.rename.displayed=Promeni prikazano ime MyTorrentsView.menu.rename.save_path=Preimenuj stazu za \u010duvanje MyTorrentsView.menu.rename.displayed_and_save_path=Preimenuj oba MyTorrentsView.menu.rename.displayed.enter.title=Promeni prikazano ime MyTorrentsView.menu.rename.displayed.enter.message=Unesite novo ime za ovaj prijem.\nAko se ne unese nikakav tekst, koristi se izvorno ime. MyTorrentsView.menu.rename.save_path.enter.title=Preimenuj stazu za \u010duvanje MyTorrentsView.menu.rename.save_path.enter.message=Unesite novo ime staze za \u010duvanje ovog prijema.\nAko se ne unese nikakav tekst, koristi se prikazano ime. MyTorrentsView.menu.rename.displayed_and_save_path.enter.title=Preimenuj prijem MyTorrentsView.menu.rename.displayed_and_save_path.enter.message=Unesite novo ime za ovaj prijem.\nAko se ne unese nikakav tekst, koriste se izvorne vrednosti. MyTorrentsView.menu.edit_comment=Uredi komentar MyTorrentsView.menu.edit_comment.enter.title=Uredi komentar MyTorrentsView.menu.edit_comment.enter.message=Unesite novi komentar za ovaj prijem. UIDebugGenerator.messageask.title=Generator prijave za gre\u0161ku UIDebugGenerator.messageask.text=Molimo da unesete opis gre\u0161ke koju prijavljujete UIDebugGenerator.complete.title=Zavr\u0161eno je generisanje izve\u0161taja o gre\u0161ci UIDebugGenerator.complete.text=Molimo da po\u0161aljete datoteku \u201e%1\u201f \n\nPritisnite \u201eU redu\u201f da biste otvorili ovu datoteku u prozoru. ConfigView.section.style.showProgramIcon=Prikazuj sli\u010dicu za program u koloni za ime ConfigView.section.style.showProgramIcon.tooltip=Mo\u017eda \u0107ete morati da ponovo otvorite pregled kako bi izmene bile uva\u017eene swt.alert.cant.update=SWT biblioteka u\u010ditana sa "%3" ne mo\u017ee se automatski dograditi sa izdanja %1 na %2 (mora se dobaviti sa "%4"). Molimo da pogledate viki za vi\u0161e podataka. authenticator.savepassword=Zapamti lozinku ConfigView.section.security.clearpasswords=Ukloni spisak zapam\u0107enih lozinki ConfigView.section.security.clearpasswords.button=Vrati Content.alert.notuploaded.title=Slanje nije dovr\u0161eno Content.alert.notuploaded.text=Prenos za \u201e%1\u201f nije dovr\u0161en. Ako sada %2, drugi ne\u0107e mo\u0107i da preuzmu Va\u0161u datoteku.\n\nDa li ste sigurni da \u017eelite da %2? Content.alert.notuploaded.multi.title=Slanje nije potpuno Content.alert.notuploaded.multi.text=%1 sadr\u017eaja kog ste objavili nije zametnuto. Ako sada %2, ljudi ne\u0107e mo\u0107i da preuzmu Va\u0161e datoteke u celini. Da li sigurno \u017eelite da %2?\n\nSadr\u017eaj koji nije zametnut:\n%3 Content.alert.notuploaded.stop=zaustavi Content.alert.notuploaded.quit=kraj rada TorrentInfoView.torrent.encoding=Kodiranje torenta TorrentInfoView.columns=Kolone iz pogleda \u201eMy Torrents\u201f progress.window.title=Dejstvo je u toku progress.window.msg.filemove=Molimo Vas da sa\u010dekate da se pomeranje ili promena imena dovr\u0161i ConfigView.label.popup.timestamp=Dodavanje vremenske oznake na uzbune ConfigView.label.popup.autohide=Automatsko sakrivanje uzbuna koje ne sadr\u017ee gre\u0161ke, posle X sekundi (postavite na 0 da ukinete automatsko sakrivanje) ConfigView.label.popup.suppress_alerts=U\u0107utkaj uzbune ConfigView.label.popup.use_message_boxes=Koristi iska\u010du\u0107e poruke radije nego standardne poruke sa upozorenjima. ConfigView.label.popup.show=Prika\u017ei sve dosad zabele\u017eene uzbune (ako ih ima) ConfigView.label.popup.show.button=Prikaz ConfigView.label.please.visit.here=Molimo da posetite ovu vezu za vi\u0161e podataka ConfigView.section.ipfilter.enable.descriptionCache=\u010cuvanje opisa IP adresa u privremenoj datoteci ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Kada je isklju\u010deno, opisi ne\u0107e biti \u010duvani OpenTorrentWindow.filesInfo=%1 od %2 \u0107e biti preuzeto. OpenTorrentWindow.diskUsage=%1 od %2 ConfigView.label.openmytorrents=Otvori \u201eMoje torente\u201f pri pokretanju ConfigView.label.open_transfer_bar_on_start=Otvori traku za prenos pri pokretanju ConfigView.section.style.DNDalwaysInIncomplete=Uvek prikazuj torente ozna\u010dene kao \u201eNe primaj\u201f u odeljku za nezavr\u0161ene torente OpenTorrentWindow.mb.noGlobalDestDir.title=Odredi\u0161ni direktorijum OpenTorrentWindow.mb.noGlobalDestDir.text=Odredi\u0161ni direktorijum \u201e%1\u201f nije ispravan. OpenTorrentWindow.mb.noDestDir.title=Odredi\u0161ni direktorijum nije prona\u0111en OpenTorrentWindow.mb.noDestDir.text=Odredi\u0161ni direktorijum \u201e%1\u201f za torent \u201e%2\u201f ne postoji ili nije ispravan. OpenTorrentWindow.mb.notValid.title=Otvori torent OpenTorrentWindow.mb.notValid.text=Torent \u201e%1\u201f nije mogu\u0107e otvoriti. Ako otvarate za zametanje, proverite da su podaci prisutni. OpenTorrentWindow.mb.notTorrent.title=Otvori torent OpenTorrentWindow.mb.notTorrent.text=Nije mogu\u0107e otvoriti \u201e%1\u201f. Izgleda da nije datoteka sa podacima za torent.\n\n\u0160ta je od podataka primljeno:\n%2 ConfigView.label.pause.downloads.on.exit=Pauziraj prijem pre kraja rada ConfigView.label.resume.downloads.on.start=Nastavi pauzirane prijeme pri pokretanju kada je program spreman za rad UIDebugGenerator.message.cancel.title=Otkazano je pravljenje podataka za ispravku gre\u0161aka UIDebugGenerator.message.cancel.text=Niste uneli opis gre\u0161ke koju poku\u0161avate da prijavite. Gre\u0161ka koja se desila je mo\u017eda o\u010digledna vama, ali bez opisa, mi bismo morali da naga\u0111amo u \u010demu je problem.\n\nPravljenje podataka sa izve\u0161tajem o gre\u0161ci je otkazano. ConfigView.section.connection.group.http=HTTP ConfigView.section.connection.group.http.info=Podr\u0161ka za zametanje putem HTTPa. ConfigView.section.connection.http.enable=Uklju\u010deno ConfigView.section.connection.http.port=Broj dolaznog porta ConfigView.section.connection.http.portoverride=HTTP port za pratioca [0: nijedan] window.update.noupdates.title=Rezultat provere dogradnji window.update.noupdates.text=Za vas nema novih dostupnih dogradnji.\n\n\u010cestitamo! ConfigView.label.bindip.details=Primer: 192.168.1.5;eth0;eth1[2] \u0107e da rezervi\u0161e navedeni IP broj, za sve brojeve do prvog su\u010delja i tre\u0107i IP broj drugog su\u010delja IP of the 2nd interface.\nPrvi IP broj \u0107e biti kori\u0161\u0107en za sve usluge, ostali IP brojevi \u0107e da se koriste za sve usluge, svi ostali se koriste za balansiranje optere\u0107enja.\nDostupni su ovde navedeni servisi:\n%1 ConfigView.label.mindownloads=Minimalan broj istovremenih prijema UI.cannot_submit_blank_text=Morate da unesete neku vrednost. crypto.alert.as.warning=Za mre\u017eu \u201e%1\u201f se zna da koristi oblikovanje saobra\u0107aja kako bi usporila prenos datoteka. \u0160ifrovanje transporta je automatski uklju\u010deno. Ovo pona\u0161anje se mo\u017ee isklju\u010diti ili promeniti u pode\u0161avanjima. ConfigView.section.interface.alerts=Uzbune ConfigView.label.popupdownloadadded=Prika\u017ei uzbunu kada se doda novi prijem popup.download.added=\u201e%1\u201f je dodat u spisak prijema. MessageBoxWindow.nomoreprompting=Ne pitaj opet TorrentOptionsView.param.max.seeds=Najve\u0107i ukupan broj zametaka [0: ograni\u010denje veze] TorrentOptionsView.param.alternative.value.enable=Drugo pode\u0161avanje pri zametanju ConfigView.section.style.SeparateFilesViewRenameRetarget=Prika\u017ei razdvojene opcije \u201ePreimenuj\u201f i \u201ePreusmeri\u201f u jezi\u010dku Datoteke ConfigView.section.proxy.check.on.start=Provera statusa zastupnika (proxy) na po\u010detku TransferStatsView.legend.pingaverage=Srednja TransferStatsView.legend.ping1=Odredi\u0161te 1 TransferStatsView.legend.ping2=Odredi\u0161te 2 TransferStatsView.legend.ping3=Odredi\u0161te 3 ConfigView.section.interface.enabletray._mac=Uklju\u010di sli\u010dicu na statusnoj traci [tra\u017ei restart] ConfigView.label.closetotray._mac=Zatvaranje umanjuje u statusnu traku ConfigView.label.minimizetotray._mac=Umanjivanje umanjuje u sli\u010dicu na statusnoj traci OpenTorrentWindow.mb.existingFiles.title=Datoteke ve\u0107 postoje! OpenTorrentWindow.mb.existingFiles.text=Neke od datoteka ve\u0107 postoje u odredi\u0161nom direktorijumu kog ste zadali:\n\n%1\nAko nastavite, Vuze \u0107e proveriti da li ove datoteke imaju o\u010dekivan sadr\u017eaj i prepisiva\u0107e ih ako bude potrebno. splash.unloadingTorrents=Istovar torenta splash.unloadingTorrent=Istovar torenta ConfigView.section.file.defaultdir.autorename=Automatska promena imena torenta ako podaci izgledaju razli\u010dito ConfigView.section.file.defaultdir.autorename.tooltip=Ovo spre\u010dava da jedan torent preina\u010di datoteke drugog ako su imena ista alert.raised.at.close=(Poruke od prethodnog pokretanja Azureusa) Plugin.trackerpeerauth.name=Autorizacija udaljenog pratioca Plugin.trackerpeerauth.info=Ovaj dodatak radi sa pratiocima i proverava da li su ra\u010dunari zaista \u010dlanovi roja Peers.column.maxupspeed=Najve\u0107a brzina slanja Peers.column.maxdownspeed=Najve\u0107a brzina prijema MyTorrents.items.DownSpeedLimit.disabled=Nema prijema Peers.column.lan=LAN upnp.selectedaddresses=Adrese (\u201e;\u201f za odvajanje, prefiks \u201e-\u201f=zabrana, \u201e+\u201f =doznola) [prazno: bilo koja] upnp.alert.multipledevice.warning=Prona\u0111eno je nekoliko UPnP ure\u0111aja - proverite da li je svima potrebno preslikavanje portova (pogledajte dnevnik i pode\u0161avanja za UPnP) UpdateMonitor.messagebox.restart.title=Dogradnja programa UpdateMonitor.messagebox.restart.text=Vuze je upravo zavr\u0161io sa prijemom va\u017ene dogradnje i mora da se ponovo pokrene kako bi dogradnja bila postavljena. PiecesView.BlockView.Have=Ima PiecesView.BlockView.NoHave=Nema PiecesView.BlockView.Header=kolona: %1, redova: %2, delova: %3 ConfigView.section.update.autodownload=Automatski prijem dogradnji i upit kada je postavljanje spremno Peers.column.peer_id=ID ra\u010dunara Peers.column.peer_id.info=Oznake ra\u010dunara u \u010ditljivom obliku Peers.column.peer_byte_id=ID ra\u010dunara Peers.column.peer_byte_id.info=Oznake ra\u010dunara kao niz bajtova Peers.column.handshake_reserved=Bajtovi rezervisani za randevu Peers.column.handshake_reserved.info=Pokazuje koji rezervisani bitovi su postavljeni u BT randevuu Peers.column.client_identification=Identivikacija klijenta Peers.column.client_identification.info=Pokazuje ime klijenta kog je dobio Vuze - korisno za tra\u017eenje gre\u0161aka dht.warn.user=Upozori u slu\u010daju problema sa NAT-om i preslikavanjem portova ConfigView.label.openbar.incomplete=Trake za prijem: automatski otvori prijeme ConfigView.label.openbar.complete=Automatski otvori zametke ConfigView.label.transferbar.remember_location=Zapamti poslednje mesto trake za prenose ConfigView.section.transfer.autospeed.forcemin=%1 brzina prijema primorana za osnovnu vezu MainWindow.menu.tools.speedtest=Provera brzine... speedtest.wizard.title=Provera brzine speedtest.wizard.run=Pokreni proveru brzine speedtest.wizard.test.mode.updown=slanje i prijem speedtest.wizard.test.mode.up=slanje speedtest.wizard.test.mode.down=prijem SpeedTestWizard.test.panel.currinfo=Provera propusnog opsega. SpeedTestWizard.test.panel.label=Azureusova provera brzine: SpeedTestWizard.test.panel.already.running=Provera ve\u0107 radi! SpeedTestWizard.test.panel.not.accepted=Zahtev za proveru je odbijen: SpeedTestWizard.test.panel.abort=Otka\u017ei SpeedTestWizard.test.panel.abort.countdown=otka\u017ei proveru za: SpeedTestWizard.test.panel.test.countdown=Provera zavr\u0161ava za: SpeedTestWizard.test.panel.testfailed=Provera nije uspela SpeedTestWizard.test.panel.aborted=Provera je ru\u010dno otkazana. SpeedTestWizard.test.panel.enc.label=Pritisnite za proveru sa \u0161ifrovanjem: SpeedTestWizard.test.panel.standard=stadardni SpeedTestWizard.test.panel.encrypted=\u0161ifrovan SpeedTestWizard.set.upload.button.apply=Primeni SpeedTestWizard.set.upload.result=Rezultat poslednje provere SpeedTestWizard.set.upload.bytes.per.sec=kiB/s SpeedTestWizard.set.upload.bits.per.sec=b/s SpeedTestWizard.finish.panel.title=Provera brzine je gotova! SpeedTestWizard.finish.panel.click.close=Zavr\u0161ili ste proveru brzine. Pritisnite \u201eZatvori\u201f da zatvorite. SpeedTestWizard.finish.panel.max.upload=Najbr\u017ee slanje : SpeedTestWizard.finish.panel.max.seeding.upload=Najbr\u017ee slanje pri zametanju : SpeedTestWizard.finish.panel.max.download=Najbr\u017ei prijem : SpeedTestWizard.finish.panel.enabled=uklju\u010deno SpeedTestWizard.finish.panel.disabled=isklju\u010deno SpeedTestWizard.abort.message.scheduled.in=provera je zakazana za ... %1 s SpeedTestWizard.abort.message.unsupported.type=Ova provera nije podr\u017eana! SpeedTestWizard.abort.message.manual.abort=Ru\u010dno otkazano SpeedTestWizard.abort.message.scheduling.failed=Zakazivanje provere nije uspelo SpeedTestWizard.abort.message.download.added=Prilikom provere dodat je prenos za %1 SpeedTestWizard.abort.message.entered.error=Probni prenos je imao gre\u0161ku: %1 SpeedTestWizard.abort.message.entered.queued=Probni prenos je u\u0161ao u stanje: zakazan/zaustavljen SpeedTestWizard.abort.message.interrupted=Provera TorrentSpeedTestMonitorThread je prekinuta pre nego \u0161to je provera zavr\u0161ena SpeedTestWizard.abort.message.execution.failed=Provera nije uspela SpeedTestWizard.abort.message.failed.peers=Nije mogu\u0107e povezati se ni na jedan ra\u010dunar SpeedTestWizard.abort.message.insufficient.slots=Nije mogu\u0107e poslati ni na jedan udaljen ra\u010dunar - mo\u017eda nema dovoljno proreza za slanje? SpeedTestWizard.abort.message.not.unchoked=Nije mogu\u0107e primiti ni sa jednog ra\u010dunara usled udaljenog ograni\u010denja brzine SpeedTestWizard.stage.message.requesting=zahtev za proverz... SpeedTestWizard.stage.message.preparing=priprema provere... SpeedTestWizard.stage.message.starting=pokretanje provere... SpeedTestWizard.stage.message.connect.stats=Statistike provere: ra\u010dunara=%1, prijem_u_redu=%2, slanje_u_redu=%3 window.uiswitcher.title=Izbor korisni\u010dkog su\u010delja window.uiswitcher.text=Molimo da ispod izaberete korisni\u010dko su\u010delje koje najbolje odgovara Va\u0161im potrebama. window.uiswitcher.NewUI.title=Vjuz (Vuze ) window.uiswitcher.NewUI.text=* Preporu\u010duje se za po\u010detnike i nove korisnike.\n\n* Jednostavno, intuitivno korisni\u010dko su\u010delje\n\n* Neophodno su\u010delje za objavljivanje na platformi Vjuz (Vuze ) window.uiswitcher.AdvancedUI.title=Napredni Vjuz (Vuze ) window.uiswitcher.AdvancedUI.text=* Preporu\u010duje se za korisnike koji \u017eele da zadr\u017ee staro su\u010delje, ali \u017eele da pretra\u017euju, pregledaju i objavljuju sadr\u017eaj na platformi Vjuz\n\n* Jednostavno, intuitivno grafi\u010dko su\u010delje sa naprednim mogu\u0107nostima i funkcijama window.uiswitcher.ClassicUI.title=Klasi\u010dno su\u010delje window.uiswitcher.ClassicUI.text=* Zadr\u017eava funkcionalnost klijenata u izdanju 2.x\n\n* Vjuzov sloj sa sadr\u017eajem ne\u0107e biti u\u010ditan window.uiswitcher.bottom.text=Va\u0161 izbor mo\u017eete ponovo da promenite izborom dugmeta \u201eIzbor korisni\u010dkog su\u010delja\u201f iconBar.switch.tooltip=Izbor korisni\u010dkog su\u010delja VivaldiView.notAvailable=Vivaldi nije dostupan restart.error=Ponovo pokretanje nije uspelo:\n%1\nPogledajte probleme pri ponovnom pokretanju. restart.error.url=http://www.azureuswiki.com/index.php/AdvancedNetworkSettings restart.error.oom=Nema memorije restart.error.fnf=\u201e%1\u201f nije prona\u0111en u \u201e%2\u201f restart.error.pnf=Staza \u201e%1\u201f nije prona\u0111ena restart.error.bad=Neispravan format datoteke za \u201e%1\u201f restart.error.denied=Pristup nije dozvoljen pri pokretanju \u201e%1\u201f. Proverite da li smete da pokre\u0107ete ovaj program. TableColumn.header.date_completed=Gotovo u TableColumn.menu.date_added.reset=Datum reseta ConfigView.section.ipfilter.discardbanning=Blokiraj ra\u010dunare za koje odnos odba\u010denih i dobrih paketa prema\u0161uje: [0: isklju\u010deno] ConfigView.section.ipfilter.discardminkb=Najmanje %1 odba\u010denih pre nego \u0161to se primeni odnos ConfigView.interface.start.advanced=Pokreni sa naprednim su\u010deljem (AZ 2.x) MyTorrents.column.ColumnQuality=Kvalitet MyTorrents.column.ColumnSpeed=Brzina MyTorrents.column.ColumnProgressETA.2ndLine=PVD: %1 MyTorrents.column.ColumnProgressETA.StreamReady=Tok je spreman MyTorrents.column.ColumnProgressETA.PlayableIn=Pu\u0161tanje u %1 TableColumn.header.Quality=Kvalitet TableColumn.header.Speed=Brzina TableColumn.header.RateIt=Odnos TableColumn.header.Rating=Ocena TableColumn.header.SpeedGraphic=Brzina TableColumn.header.AzProduct=Od TableColumn.header.MediaThumb=Medijum TableColumn.header.ProgressETA=Napredak TableColumn.header.size={MyTorrentsView.size} TableColumn.header.up={MyTorrentsView.up} TableColumn.header.date_added={MyTorrentsView.date_added} TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=Vrsta: %1 TableColumn.header.shareRatio={MyTorrentsView.shareRatio} TableColumn.header.DateCompleted={MyTorrentsView.date_completed} v3.MainWindow.tab.home=Glavni panel v3.MainWindow.tab.browse=Na Vjuzu (Vuze ) v3.MainWindow.tab.library=Biblioteka v3.MainWindow.tab.publish=Objavi v3.MainWindow.tab.advanced=Napredno v3.MainWindow.menu.home=&Glavni panel v3.MainWindow.menu.browse=Na Vjuzu (Vuze ) v3.MainWindow.menu.library=&Biblioteka v3.MainWindow.menu.publish=&Objavi v3.MainWindow.menu.advanced=&Napredno v3.MainWindow.menu.view.searchbar=Traka za pretragu v3.MainWindow.menu.view.tabbar=Traka sa jezi\u010dcima v3.MainWindow.currentDL=Trenutni prijem v3.MainWindow.button.stream=Tok v3.MainWindow.button.stop=Zaustavi v3.MainWindow.button.start=Pokretanje v3.MainWindow.button.pause=Pauza v3.MainWindow.button.resume=Nastavi v3.MainWindow.button.delete=Ukloni v3.MainWindow.button.comment=Komentar v3.MainWindow.button.viewdetails=Detalji v3.MainWindow.button.play=Pusti v3.MainWindow.button.cancel=Otka\u017ei v3.MainWindow.button.sendtofriend=Deli v3.MainWindow.view.wait=Pogled se u\u010ditava, molimo da sa\u010dekate... v3.MainWindow.xofx=%1 od %2 v3.MainWindow.Loading=U\u010ditavanje, molimo da sa\u010dekate... v3.filter-bar=Filter naslova: v3.MainWindow.search.defaultText=Pretra\u017ei Vjuz v3.mb.delPublished.title=Prekini zametanje sadr\u017eaja v3.mb.delPublished.text=UPOZORENJE: Ovo dejstvo NE\u0106E ukloniti objavljen sadr\u017eaj \u201e%1\u201f sa %3 .\n\nPritisnite \u201eUkloni\u201f samo ako \u017eelite da va\u0161 sadr\u017eaj ostane objavljen i spreman za prijem, ali \u017eelite da oslobodite svoj propusni opseg. Proverite da je prenos gotov pre nego \u0161to to uradite (kako?).\n\nPritisnite \u201eOtka\u017ei\u201f ako \u017eelite da potpuno uklonite objavljen sadr\u017eaj sa %3, i koristite dugme (X) na panelu \u201eObjavljen sadr\u017eaj\u201f na jezi\u010dku sa objavljenim sadr\u017eajima.\n\nVi\u0161e pomo\u0107i.\n\n v3.mb.delPublished.delete=&Ukloni v3.mb.delPublished.cancel=Otka&\u017ei v3.mb.notTrusted.title=Sadr\u017eaj nije od poverenja v3.mb.notTrusted.text=Sadr\u017eaj \u201e%1\u201f se smatra potencijalno opasnim. Va\u0161 operativni sistem ka\u017ee da je vrsta sadr\u017eaja: \u201e%2\u201f. v3.mb.notTrusted.noapp.text=Sadr\u017eaj \u201e%1\u201f se smatra potencijalno opasnim jer je Va\u0161 operativni sistem prijavio da format nije prepoznat (%2). v3.mb.notTrusted.button.run=Ipak pokreni v3.mb.notTrusted.button.cancel=Otka\u017ei v3.mb.UnknownContent.title=Nepoznat sadr\u017eaj v3.mb.UnknownContent.text=Sadr\u017eaj \u201e%1\u201f nije prona\u0111en u me\u0111u poznatim formatima. Va\u0161 operativni sistem prijavljuje sadr\u017eaj kao vrstu \u201e%2\u201f. Nastavak imena datoteke je \u201e%3\u201f. v3.mb.UnknownContent.noapp.text=Sadr\u017eaj \u201e%1\u201f nije u prepoznatom formatu. Va\u0161 operativni sistem nema pridru\u017een program za ovu vrstu datoteka (%2). v3.mb.UnknownContent.button.run=Ipak pokreni v3.mb.UnknownContent.button.cancel=Otka\u017ei v3.mb.PlayFileNotFound.title=Datoteka nije na\u0111ena v3.mb.PlayFileNotFound.text=Datoteke za \u201e%1\u201f su ili uklonjene ili nedostaju. v3.mb.PlayFileNotFound.button.remove=Ukloni iz Azureusa v3.mb.PlayFileNotFound.button.redownload=Ponovni prijem v3.mb.PlayFileNotFound.button.find=Ru\u010dno tra\u017eenje... v3.mb.deletePurchased.title=Ukloni kupljeni sadr\u017eaj v3.mb.deletePurchased.text=Da li sigurno \u0111elite da uklonite sadr\u017eaj \u201e%1\u201f?\n\nOvaj ste sadr\u017eaj ili kupili ili je potrebna prijava da biste ga preuzeli. v3.mb.deletePurchased.button.delete=&Ukloni v3.mb.deletePurchased.button.cancel=Otka&\u017ei v3.topbar.menu.show.logo=Logotip v3.topbar.menu.show.plugin=Oblast sa dodacima v3.topbar.menu.show.search=Pretraga v3.topbar.menu.show.frog=Plava \u017eaba splash.initializeCore=Pokretanje jezgra splash.initializeUIElements=Pokretanje delova kor. su\u010delja ConfigView.section.transfer.autospeedbeta=Auto-Speed-Beta # ConfigView.section.ipfilter.peerblocking.group=Blokiranje ra\u010dunara ConfigView.section.ipfilter.autoload.group=Automatsko u\u010ditavanje ConfigView.section.ipfilter.autoload.file=Datoteka sa IP filtrima za prijem ConfigView.section.ipfilter.autoload.info=Podr\u017eava formate DAT (eMule), P2P (PeerGuardian, splist), i P2B v1,2,3 (PeerGuardian 2). Datoteka mo\u017ee da bude lokalna ili data kao URL, komprimovana (zip, gzip) ili nekomprimovana. URLovi \u0107e biti automatski preuzimani na svakih 7 dana, a datoteke \u0107e da budu preuzimane odmah po izmeni. ConfigView.section.ipfilter.autoload.loadnow=U\u010ditaj odmah splash.loadIpFilters=U\u010ditavanje IP filtera... SpeedTestWizard.set.upload.title=Postavka brzina prijema i slanja SpeedTestWizard.set.download.label=Brzina prijema: SpeedTestWizard.set.upload.label=Brzina slanja: SpeedTestWizard.name.conf.level.absolute=Apsolutan SpeedTestWizard.name.conf.level.high=Visok SpeedTestWizard.name.conf.level.med=Srednji SpeedTestWizard.name.conf.level.low=Nizak SpeedTestWizard.name.conf.level.none=Nijedan ConfigView.section.transfer.select=Autom. brzina ConfigView.section.transfer.select.v2=Autom. brzina (beta) mb.azmustclose.title=Gre\u0161ka pri pokretanju mb.azmustclose.text=Vuzeje morao da bude zatvoren usled problema pri pokretanju, koji je najverovatnije uzrokovao da se Vuze pokrene sa administratorskim pravima pristupa.\n\nPo\u0161to se Vuze zatvori, molimo da ga ru\u010dno ponovo pokrenete. network.ipv6.prefer.addresses=Biraj adresu u IPv6 formatu kada su dostupne i IPv6 i IPv4 DHTView.title.full_v6=Distribuirana baza podataka IPv6 ConfigView.pluginlist.loadSelected=U\u010ditaj izabrane SpeedView.stats.asn=Mre\u017ea: SpeedView.stats.estupcap=Brzina slanja: SpeedView.stats.estdowncap=Brzina prijema: SpeedView.stats.unknown=Nepoznat SpeedView.stats.estimate=Procena SpeedView.stats.measured=Mereno SpeedView.stats.measuredmin=Mereni min. SpeedView.stats.manual=Ispravljeno ConfigView.section.transfer.autospeed.networks=Detalji o mre\u017ei ConfigView.section.transfer.autospeed.resetnetwork=Ponovo postavi detalje o mre\u017ei ConfigView.section.transfer.autospeed.network.info=Gore navedene granice se obi\u010dno ra\u010dunaju automatski tokom prijema ili su posledica provere brzine prenosa. Ako \u017eelite da ih zadate ru\u010dno, koristite opcije ispod.\nSva ograni\u010denja osim \u201efiksno\u201f \u0107e biti automatski pode\u0161avana ako je potrebno.\nUnesite vrednost i izaberite vrstu. Brzine su izra\u017eene u %1. dialog.uiswitcher.restart.title=Promena kor. su\u010delja: potreban je restart Azureusa dialog.uiswitcher.restart.text=Vuze mora da se ponovo pokrene da bi se korisni\u010dko su\u010delje promenilo. TrayWindow.menu.close=Zatvori korpu sa prijemima # Used for peers which we can't determine. PeerSocket.unknown=Nepoznat PeerSocket.fake_client=LA\u017dNI PeerSocket.bad_peer_id=neispravan ID ra\u010dunara PeerSocket.mismatch_id=nesaglasno PeerSocket.unknown_az_style=Nepoznat %1/%2 PeerSocket.unknown_shadow_style=Nepoznat %1/%2 OpenTorrentWindow.mb.askCreateDir.title=Odredi\u0161ni direktorijum ne postoji OpenTorrentWindow.mb.askCreateDir.text=Odredi\u0161ni direktorijum \u201e%1\u201f ne postoji.\n\nDa li da ga napravim? SpeedView.stats.estimatechoke=Procena (gas) ConfigTransferAutoSpeed.upload.capacity.usage=Upotreba kapaciteta za slanje ConfigTransferAutoSpeed.mode=Na\u010din rada: ConfigTransferAutoSpeed.capacity.used=% kapaciteta u upotrebi ConfigTransferAutoSpeed.while.downloading=Prijem: ConfigTransferAutoSpeed.set.dht.ping=Pode\u0161avanje DHT pinga: ConfigTransferAutoSpeed.set.point=postavljena ta\u010dka (ms) ConfigTransferAutoSpeed.set.tolerance=tolerancija (ms) ConfigTransferAutoSpeed.ping.time.good=Dobri: ConfigTransferAutoSpeed.ping.time.bad=Lo\u0161i: ConfigTransferAutoSpeed.adjustment.interval=Vreme pode\u0161avanja: ConfigTransferAutoSpeed.skip.after.adjust=Presko\u010di posle pode\u0161avanja: GeneralView.label.distributedCopies=Distribuirani umno\u0161ci: PiecesView.DistributionView.title=Raspodela delova PiecesView.DistributionView.NoAvl=Nedostupni delovi PiecesView.DistributionView.SeedAvl=Prilog avl-u zametka PiecesView.DistributionView.PeerAvl=Prilog avl-u od ra\u010dunara PiecesView.DistributionView.RarestAvl=Najre\u0111i delovi: %1 (dost.:%2) PiecesView.DistributionView.weHave=Delovi koje imate PiecesView.DistributionView.theyHave=Delovi koje ima udaljeni ra\u010dunar PiecesView.DistributionView.weDownload=Delovi koje primate PeersView.gain = Poja\u010danje PeersView.gain.info = Koli\u010dina primljenih - poslatih podataka unix.script.new.title=Dostupni su novi skriptovi za pokretanje Azureusa unix.script.new.text=Dostupan je novi skript za pokretanje Azureusa, a sa\u010duvan je u \u201e%1\u201f.\n\nPreporu\u010duje se da odmah zatvorite Azureusa i da se prebacite na ovaj skript. (\u201e%2\u201f).\n\nAko ste menjali skript za pokretanje, molimo da pro\u010ditate \u010dlanak AzureusWiki: Unix Script.\n\nAko ste Azureusa instalirali iz neke distribucije (yum, apt-get, itd.), preporu\u010duje se da ga ponovo instalirate upotrebom paketa sa adrese: Azureusova strana na Sorsford\u017eu (i dalje \u0107ete imati isto su\u010delje kao i sada) unix.script.new.manual.url=http://azureuswiki.com/index.php/AdvancedNetworkSettings unix.script.new.button.quit=Kraj rada unix.script.new.button.continue=Uradi\u0107u to kasnije unix.script.new.button.asknomore=Ne obave\u0161tavaj me vi\u0161e unix.script.new.auto.title=Novi skript za pokretanje Azureusa unix.script.new.auto.text=Dostupan je novi skript za pokretanje Azureusa.\n\nPreporu\u010duje se da odmah ponovo pokrenete Azureusa. Content.alert.notuploaded.button.stop=&Stani Content.alert.notuploaded.button.continue=Nastavi &zametanje Content.alert.notuploaded.button.abort=&Ne zavr\u0161avaj ConfigView.label.checkOnSeeding=Brzo proveri delove pri zametanju ConfigView.label.ui_switcher=Izbor korisni\u010dkog su\u010delja ConfigView.label.ui_switcher_button=Prikaz SpeedTestWizard.test.panel.explain=Izmerite brzinu Azureusovog protokola. Izaberite vrstu provere brzine i na\u010din \u0161ifrovanja. Posetite Azureusovu viki stranu za detalje ove provere. Provera \u0107e se zavr\u0161iti automatski ako potraje du\u017ee od dva minuta. Tipi\u010dno se provera brzine sama zavr\u0161i za manje od minuta. SpeedTestWizard.set.upload.hint=Postavi ograni\u010denja za prijem i slanje prema Azureusovom algoritmu za automatsku regulaciju. SpeedTestWizard.set.upload.panel.explain=Granice koje se ovde pode\u0161avaju koriste se u algoritmu za automatsku regulaciju brzine. Postavite grani\u010dne brzine prenosa i intervale poverenja.\n\nBrzine prenosa se obi\u010dno navode u \u201ebitima u sekundi\u201f, dok su ovde prikazani \u201ekilobajti u sekundi\u201f. SpeedTestWizard.set.limit.conf.level=Poverenje SpeedTestWizard.finish.panel.auto.speed=Autom. brzina je : SpeedTestWizard.finish.panel.auto.speed.seeding=Automatska brzina pri zametanju je : ConfigTransferAutoSpeed.add.comment.to.log.group=Dodaj komentar u dnevnik ConfigTransferAutoSpeed.add.comment.to.log=Dodaj komentar: ConfigTransferAutoSpeed.log.button=Dnevnik ConfigTransferAutoSpeed.algorithm.selector=Izbor autom. brzine ConfigTransferAutoSpeed.algorithm=Algoritam: ConfigTransferAutoSpeed.auto.speed.classic=Autom. brzina (klasi\u010dna) ConfigTransferAutoSpeed.auto.speed.beta=Autom. brzina (beta) ConfigTransferAutoSpeed.data.update.frequency=U\u010destanost osve\u017eavanja Alert.failed.update=Bar jedna komponenta nije ispravno postavljena. Vidite AzureusWiki: Failed Update [%1] Alert.failed.update.url=http://azureuswiki.com/index.php/Failed_Update OpenTorrentWindow.mb.existingFiles.partialList= (Delimi\u010dan spisak. Ve\u0107 ima jo\u0161 datoteka) TableColumn.header.bad_avail_time.info=Poslednji put kada je ceo primerak prijema bio dostupan TableColumn.header.bad_avail_time=Prona\u0111en je ceo primerak MyTorrentsView.menu.exporthttpseeds=Umno\u017ei URL zametka na klipbord SWT.alert.erroringuithread=Desila se neobra\u0111ena gre\u0161ka u korisni\u010dkom su\u010delju. Mogu da se jave druge vezane gre\u0161ke ConfigView.label.minannounce=Najmanje vreme izme\u0111u zahteva pratiocu, u sekundama ConfigView.label.maxnumwant=Ograni\u010di broj ra\u010dunara koji pratilac mo\u017ee da dostavi ConfigView.label.announceport=Preina\u010di najavljeni TCP port za pratioca, pex i DHT.\n[prazno: ne preina\u010duj, 0: nema dolaznih veza] ConfigView.label.noportannounce=Ne najavljuj port za slu\u0161anje pratiocu (ovo ne uti\u010de na DHT i ostalo) ConfigView.label.maxseedspertorrent=Najve\u0107i broj zametaka po torentu [0: neograni\u010deno] wizard.webseed=Dodaj HTTP zametke u torent wizard.webseed.title=HTTP zameci wizard.webseed.configuration=Pode\u0161avanje HTTP zametanja wizard.webseed.adding=Dodavanje HTTP zametaka GeneralView.label.private=Privatni torent: GeneralView.yes=da GeneralView.no=ne ConfigView.label.userequestlimiting=Koristi ograni\u010denje broja zahteva umesto ka\u0161njenja \u010ditanja za ograni\u010denje brzine prijema [nema efekta kada je brzina prijema neograni\u010dena] ConfigView.label.userequestlimiting.tooltip=Ograni\u010denje broja zahteva ne radi tako glatko kao ka\u0161njenje \u010ditanja, ali dozvoljava ure\u0111ivanje prijema po prioritetu prema mestu u redu za prijem, i mo\u017eda pobolj\u0161a protok na mre\u017ei ConfigView.section.logging.timestamp=Format ispisa vremena za dnevnik Peers.column.timetocomplete=Preostalo vreme Peers.column.timetocomplete.info=Preostalo vreme dok drugi ra\u010dunar ne zavr\u0161i ConfigView.section.interface.display.suppress.file.download.dialog=Prikrij prozor za prijem datoteka ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Prika\u017ei napredak svih prijema u statusnoj traci, umesto iska\u010du\u0107eg prozora FileDownload.canceled=Torent datoteka je uspe\u0161no otkazana na korisnikov zahtev: %1 Progress.reporting.status.canceled=Otkazan Progress.reporting.status.finished=Zavr\u0161eno Progress.reporting.status.retrying=Opet... Progress.reporting.action.label.retry.tooltip=Ponovi ovo dejstvo Progress.reporting.action.label.remove.tooltip=Ukloni ovaj izve\u0161taj o napretku iz istorijata Progress.reporting.action.label.cancel.tooltip=Otka\u017ei ovo dejstvo Progress.reporting.action.label.detail=Detalji Progress.reporting.default.error=Neuspelo Progress.reporting.no.reports.to.display=Za sada nema izve\u0161taja o napretku Progress.reporting.no.history.to.display=Nema detaljnih poruka za prikaz Progress.reporting.detail.history.limit=Ograni\u010denje za broj detaljnih poruka (%1) za ovaj ProgressReporter he prema\u0161eno; naredne poruke ne\u0107e biti dodavane u istorijat Progress.reporting.statusbar.button.tooltip=Prika\u017ei prozor za pra\u0107enje napretka webui.bindip=Koristi IP broj - normalno nije potrebno (*) v3.MainWindow.text.log.in=Prijava v3.MainWindow.text.log.out=Odjava v3.MainWindow.text.get.started=Uvod v3.MainWindow.text.my.account=Moj nalog OpenTorrentWindow.simple.open=Mesto torenta (datoteka, URL, he\u0161) MainWindow.menu.help.donate=&Dajte prilog #PLEASE LEAVE ME AT VERY BOTTOM! azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_gl_ES.properties0000644000175000017500000010741111301156004026064 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Arquivo .torrent Main.parameter.usage=Uso : java org.gudy.azureus2.cl.Main [par\u00e1metros] "arquivo.torrent" "ruta descarga" Main.parameter.maxUploads=N\u00famero m\u00e1ximo de env\u00edos simult\u00e1neos Main.parameter.maxSpeed=Velocidade m\u00e1xima de subida en bytes/seg MainWindow.menu.file=Arquivo MainWindow.menu.file.open=Abrir MainWindow.menu.file.create=Crear un .torrent MainWindow.menu.file.create.fromfile=Dende un arquivo MainWindow.menu.file.create.fromdir=Dende unha carpeta MainWindow.menu.file.export=Exportar un .torrent... MainWindow.menu.file.import=Importar un .torrent... MainWindow.menu.file.exit=Sair MainWindow.dialog.choose.file=Escolla o arquivo .torrent MainWindow.menu.file.folder=Carpeta MainWindow.dialog.choose.folder=Escolla a carpeta MainWindow.menu.view=Vista MainWindow.menu.view.mytorrents=Os meus Torrents MainWindow.menu.view.configuration=Configuraci\u00f3n MainWindow.menu.view.console=Consola MainWindow.menu.view.irc=Cliente IRC MainWindow.menu.closealldetails=Pechar t\u00f3dolos detalles MainWindow.menu.closealldownloadbars=Pechar as barras de descarga MainWindow.menu.language=Lingua ConfigView.section.language=Lingua MainWindow.menu.help=Axuda MainWindow.menu.help.about=Cr\u00e9ditos do Vuze MainWindow.about.title=Cr\u00e9ditos MainWindow.about.section.developers=Desenvolvedores MainWindow.about.section.translators=Traductores MainWindow.about.section.internet=Internet MainWindow.about.internet.homepage=P\u00e1xina do Vuze MainWindow.about.internet.sourceforge=P\u00e1xina do proxecto en Sourceforge MainWindow.about.internet.sourceforgedownloads=Descargas dende Sourceforge MainWindow.about.internet.bugreports=Informe de erros MainWindow.about.internet.forumdiscussion=Foro xeral MainWindow.dialog.choose.savepath=Escolla a carpeta para a descarga MainWindow.dialog.choose.savepath_forallfiles=Escolla a carpeta para as descargas MainWindow.status.latestversion=\u00daltima versi\u00f3n MainWindow.status.latestversion.clickupdate=Clic para actualizar MainWindow.status.unknown=Desco\u00f1ecido MainWindow.status.checking=Comprobando MyTorrentsView.mytorrents=Os meus Torrents TableColumn.header.name=Nome TableColumn.header.size=Tama\u00f1o TableColumn.header.done=Completado TableColumn.header.status=Estado TableColumn.header.seeds=Sementes TableColumn.header.peers=Clientes TableColumn.header.downspeed=Vel. descarga TableColumn.header.upspeed=Vel. subida TableColumn.header.eta=Tempo estimado TableColumn.header.tracker=Rastreador TableColumn.header.priority=Prioridade MyTorrentsView.menu.showdetails=Amosar detalles MyTorrentsView.menu.showdownloadbar=Amosar barra de descarga MyTorrentsView.menu.open=Abrir MyTorrentsView.menu.setpriority=Establecer prioridade MyTorrentsView.menu.setpriority.high=Alta MyTorrentsView.menu.setpriority.low=Baixa MyTorrentsView.menu.start=Comezar MyTorrentsView.menu.stop=Deter MyTorrentsView.menu.remove=Eliminar MyTorrentsView.menu.changeTracker=Cambia-la URL do Tracker TrayWindow.menu.exit=Sair TrayWindow.menu.show=Amosar Vuze SystemTray.menu.exit=Sair SystemTray.menu.closealldownloadbars=Pechar barras de descarga SystemTray.menu.show=Amosar Vuze PeersView.ip=IP PeersView.port=Porto PeersView.T=T PeersView.I1=I PeersView.C1=C PeersView.pieces=Pezas PeersView.%=% PeersView.downloadspeed=Vel. descarga PeersView.download=Recibido PeersView.I2=I PeersView.C2=C PeersView.uploadspeed=Vel. subida PeersView.upload=Enviado PeersView.statup=Subida media PeersView.S=S PeersView.downloadspeedoverall=Descarga media PeersView.optunchoke=Preferencia PeersView.client=Cliente PeersView.menu.snubbed=Snubbed PeersView.title.short=Detalles PeersView.title.full=Detalles ConfigView.section.files=Arquivos ConfigView.label.usefastresume=Usar modo resumir r\u00e1pido ConfigView.label.defaultsavepath=Ruta de descarga por defecto ConfigView.button.browse=Examinar... ConfigView.dialog.choosedefaultsavepath=Escolla a carpeta para as descargas ConfigView.section.server=Servidor ConfigView.section.global=Global ConfigView.label.disconnetseed=Desconectar sementes ao compartir ConfigView.label.switchpriority=Establecer prioridade baixa automaticamente ao servir ConfigView.label.maxdownloads=Descargas m\u00e1ximas simult\u00e1neas ConfigView.label.maxactivetorrents=Torrents m\u00e1ximos activos (0 : sen l\u00edmite)\nOs novos torrents non se iniciar\u00e1n se est\u00e1 descargando/servindo m\u00e1is de ConfigView.label.priorityExtensions=Pasar automaticamente a alta prioridade ficheiros de extensi\u00f3n\n (ex: .txt;.nfo;.jpg) ConfigView.section.transfer=Transferencia ConfigView.label.maxuploads=Env\u00edos m\u00e1ximos por torrent ConfigView.label.maxuploadspeed=Velocidade m\u00e1xima de subida (global) ConfigView.label.saveresumeinterval=Gardar copia automaticamente cada ConfigView.unlimited=Sen l\u00edmite ConfigView.section.display=Visualizaci\u00f3n ConfigView.label.opendetails=Abrir automaticamente barra de detalles ConfigView.label.openbar=Abrir automaticamente barra de descarga ConfigView.label.closetotray=Po\u00f1er icono na bandexa (System Tray) ao pechar ConfigView.label.minimizetotray=Po\u00f1er icono na bandexa (System Tray) ao minimizar ConfigView.section.general=Xeral ConfigView.section.start=Comezar ConfigView.label.showsplash=Amosar pantalla ao inicio ConfigView.label.autoupdate=Abrir o di\u00e1logo de actualizaci\u00f3ns para ver se hai algunha dispo\u00f1\u00edbel ConfigView.label.openconsole=Abrir a consola no inicio ConfigView.label.openconfig=Abri-la configuraci\u00f3n no inicio ConfigView.label.startminimized=Comezar minimizado ConfigView.section.irc=Cliente Irc ConfigView.label.ircserver=Servidor ConfigView.label.ircchannel=Canle ConfigView.label.irclogin=Sobrenome ConfigView.section.security=Seguridade ConfigView.label.password=Protexer Vuze usando contrasinal\nAo restaurar Vuze pedir\u00e1se o contrasinal ConfigView.label.passwordconfirm=Contrasinal (confirmar) ConfigView.label.passwordmatch=Contrasinal activado : ConfigView.label.passwordmatchnone=Non ConfigView.label.passwordmatchno=Non / Os contrasinais non coinciden ConfigView.label.passwordmatchyes=Si ConfigView.button.save=Gardar ConfigView.title.short=Configuraci\u00f3n ConfigView.title.full=Configuraci\u00f3n ConsoleView.title.short=Consola ConsoleView.title.full=Consola FileItem.write=Escritura FileItem.read=Lectura FileItem.normal=Normal FileItem.high=Alta FileItem.donotdownload=Non baixar FilesView.name=Nome FilesView.size=Tama\u00f1o FilesView.done=Completado FilesView.%=% FilesView.firstpiece=# primeira peza FilesView.numberofpieces=# de pezas FilesView.pieces=Pezas FilesView.mode=Modo FilesView.priority=Prioridade FilesView.menu.open=Abrir FilesView.menu.setpriority=Establecer prioridade FilesView.menu.setpriority.high=Alta FilesView.menu.setpriority.normal=Normal FilesView.menu.setpriority.skipped=Non baixar FilesView.title.short=Arquivos FilesView.title.full=Arquivos GeneralView.section.downloaded=Baixado GeneralView.label.status.file=Estado arquivo GeneralView.label.status.pieces=Estado pezas GeneralView.section.availability=Dispo\u00f1ibilidade GeneralView.label.status.pieces_available=Estado pezas GeneralView.section.transfer=Transferencia GeneralView.section.info=Informaci\u00f3n GeneralView.title.short=Xeral GeneralView.title.full=Xeral GeneralView.label.timeelapsed=Tempo activo : GeneralView.label.remaining=Restante : GeneralView.label.downloaded=Baixado : GeneralView.label.downloadspeed=Vel. descarga : GeneralView.label.maxuploads=Envios m\u00e1ximos : GeneralView.label.uploaded=Enviado : GeneralView.label.uploadspeed=Vel. subida : GeneralView.label.seeds=Sementes : GeneralView.label.peers=Clientes : GeneralView.label.totalspeed=Velocidade total : GeneralView.label.filename=Nome : GeneralView.label.totalsize=Tama\u00f1o total : GeneralView.label.savein=Gardado en : GeneralView.label.numberofpieces=# de pezas : GeneralView.label.size=Tama\u00f1o peza : GeneralView.label.tracker=Rastreador : GeneralView.label.updatein=Actualizado en : GeneralView.label.trackerurl=URL do rastreador : GeneralView.label.trackerurlupdate=Actualizacion manual GeneralView.label.comment=Comentarios : ManagerItem.waiting=Agardando ManagerItem.allocating=Establecendo ManagerItem.checking=Comprobando ManagerItem.ready=Preparado ManagerItem.downloading=Baixando ManagerItem.seeding=Compartindo ManagerItem.stopped=Detido ManagerItem.error=Erro ManagerItem.high=Alta ManagerItem.low=Baixa MinimizedWindow.name=Nome: PiecesView.#=# PiecesView.size=Tama\u00f1o PiecesView.numberofblocks=# de bloques PiecesView.blocks=Bloques PiecesView.completed=Completados PiecesView.availability=Dispo\u00f1ibilidade PiecesView.title.short=Pezas PiecesView.title.full=Pezas SystemTray.tooltip.seeding=%1 compartindo, SystemTray.tooltip.downloading=%1 baixando, DownloadManager.error.filenotfound=Non se atopa o arquivo DownloadManager.error.fileempty=O arquivo .torrent est\u00e1 baleiro DownloadManager.error.filetoobig=O arquivo .torrent \u00e9 moi grande DownloadManager.error.filewithouttorrentinfo=Non hai informaci\u00f3n no arquivo .torrent DownloadManager.error.unsupportedencoding=Codificaci\u00f3n non soportada DownloadManager.error.ioerror=Erro E/S DownloadManager.error.sha1=Erro de algoritmo (SHA1) PeerManager.status.offline=Desconectado PeerManager.status.ok=Activo PeerManager.status.checking=Comprobando PeerManager.status.finished=Completado PeerManager.status.finishedin=Completado MainWindow.upgrade.assistant=Asistente de actualizaci\u00f3n MainWindow.upgrade.newerversion=Hai dispo\u00f1\u00edbel unha nova versi\u00f3n do Vuze para baixar MainWindow.upgrade.explanation=Este asistente baixar\u00e1 a nova versi\u00f3n na carpeta do Vuze e despois reiniciar\u00e1 Vuze MainWindow.upgrade.explanation.manual=Vostede pode actualizar manualmente pechando Vuze baixando a nova versi\u00f3n e reiniciando Vuze MainWindow.upgrade.step1=Paso 1: Descarga da nova versi\u00f3n MainWindow.upgrade.step2=Paso 2: Pechar esta versi\u00f3n para reiniciar na nova versi\u00f3n do Vuze MainWindow.upgrade.hint1=Tip:\tSe mant\u00e9s premido alg\u00fans segundos Rematar e despois o soltas, o proceso ser\u00e1 autom\u00e1tico MainWindow.upgrade.hint2=Tip:\tSe vostede desexa pechar o Vuze m\u00e1is tarde, prema Cancelar e\n\trenomee Azureus2-new.jar a Azureus2.jar despois de pechar MainWindow.upgrade.error.downloading.hint=Error:\tImpos\u00edbel baixar a nova versi\u00f3n, pr\u00e9gase actualice manualmente MainWindow.upgrade.section.info=Nova versi\u00f3n dispo\u00f1\u00edbel MainWindow.upgrade.section.manual=Actualizacion manual MainWindow.upgrade.section.automatic=Actualizaci\u00f3n autom\u00e1tica MainWindow.upgrade.tooltip.progressbar=O progreso da descarga am\u00f3sase aqu\u00ed Button.next=Seguinte Button.finish=Rematar Button.cancel=Cancelar LocaleUtil.title=Escolla a codificaci\u00f3n LocaleUtil.section.chooseencoding=Escolla a codificaci\u00f3n para o arquivo LocaleUtil.label.chooseencoding=Pr\u00e9gase escolla a mellor codificaci\u00f3n correspondente LocaleUtil.label.hint.doubleclick=Tip: dobre-clic nunha fileira escolle a codificaci\u00f3n e pecha o cadro de di\u00e1logo LocaleUtil.label.checkbox.rememberdecision=Lembrar decisi\u00f3ns para os arquivos restantes LocaleUtil.column.encoding=Codificaci\u00f3n IrcClient.copyright=Usando PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Conectando a IrcClient.connected=Conectado a IrcClient.joining=Un\u00edndose a IrcClient.channel=Canle IrcClient.joined=unido axeitadamente IrcClient.error=Erro IrcClient.hasjoined=uniuse IrcClient.haskicked=foi botado IrcClient.hasleft=foise IrcClient.nowknown=\u00e9 agora co\u00f1ecido coma IrcClient.topicforchannel=Tema para a canle IrcClient.disconnected=Desconectado de IrcClient.noNick=Non tes un sobrenome especificado. Pr\u00e9gase vaias \u00e1 pantalla de 'Configuracion' IrcView.actionnotsupported=Esta acci\u00f3n non est\u00e1 soportada IrcView.clientsconnected=Usuarios IrcView.privateto=Para IrcView.privatefrom=De IrcView.noticefrom=Aviso : IrcView.errormsg=Sintaxe incorrecta en /msg : /msg usuario mensaxe IrcView.help=Os comandos v\u00e1lidos son :\n . /help : amosa esta mensaxe\n . /nick | /name : muda de sobrenome \n . /me acci\u00f3n : envia unha acci\u00f3n \n ./ msg sobrenome mensaxe : envia unha mensaxe privada \n . /r mensaxe : resposta \u00e1 \u00faltima mensaxe privada \n . /join #canle : troca de canle PasswordWindow.title=Vuze est\u00e1 protexido con contrasinal PasswordWindow.passwordprotected=Vuze est\u00e1 protexido con contrasinal.\nPara restaurar Vuze pr\u00e9gase escriba o seu contrasinal aqu\u00ed : Button.ok=Ok TrackerChangerWindow.title=Cambiar Tracker TrackerChangerWindow.newtracker=Introduza a nova url do Tracker PeersView.discarded=Descartado discarded=descartado MyTorrentsView.#=# MyTorrentsView.menu.move=Mover MyTorrentsView.menu.moveUp=Arriba MyTorrentsView.menu.moveDown=Abaixo GeneralView.label.hashfails=Erra o Hash : GeneralView.label.shareRatio=Promedio compartido : ConfigView.section.downloadManagement=Administrador de descargas ConfigView.label.startRatioPeers=Comezar a compartir cando haxa menos de 1 semente ConfigView.text.neverStop=Non deter nunca ConfigView.text.neverStart=Non comezar nunca ConfigView.text.peers=Pares ConfigView.label.checkOncompletion=Comprobar pezas unha vez baixadas wizard.title=Crear un .torrent wizard.previous=< Anterior wizard.next=Seguinte > wizard.finish=Rematado wizard.mode=Tracker / Modo wizard.tracker=Tracker: wizard.invalidurl=Esta URL non \u00e9 v\u00e1lida wizard.singlefile=Arquivo wizard.singlefile.help=Crear un .torrent dende un arquivo wizard.directory=Carpeta wizard.directory.help=Crear un .torrent dende unha carpeta wizard.choosefile=Escolle o arquivo wizard.file=Arquivo : wizard.browse=Examinar... wizard.choosedirectory=Escolle a carpeta wizard.invalidfile=Arquivo inv\u00e1lido! wizard.invaliddirectory=Carpeta inv\u00e1lida! wizard.torrentFile=Arquivo .torrent wizard.choosetorrent=Pr\u00e9gase escollas o arquivo .torrent para crear wizard.information=Informaci\u00f3n wizard.notimplemented=Non implementado a\u00ednda wizard.progresstitle=Creando arquivo .torrent wizard.savingfile=Gardando arquivo... wizard.filesaved=Arquivo gardado. wizard.close=Pechar Torrent.create.progress.piecelength=Lonxitude da peza: Torrent.create.progress.piececount=Cantidade de pezas: Torrent.create.progress.totalfilesize=Tama\u00f1o total do arquivo: Torrent.create.progress.totalfilecount=Cantidade total de arquivos: Torrent.create.progress.parsingfiles=Analizando arquivos Torrent.create.progress.hashing=Hashing arquivos MainWindow.upgrade.downloadingfrom=Baixando dende : MainWindow.menu.view.ipFilter=Filtros de Ip ConfigView.section.ipfilter=Filtros de Ip ConfigView.section.ipfilter.description=Descripci\u00f3n ConfigView.section.ipfilter.start=Ip inicial ConfigView.section.ipfilter.end=Ip final ConfigView.section.ipfilter.add=Engadir ConfigView.section.ipfilter.remove=Eliminar ConfigView.section.ipfilter.edit=Editar ConfigView.section.ipfilter.save=Gardar ConfigView.section.ipfilter.editFilter=Editar filtros ConfigView.section.ipfilter.enable=Activar PeersView.menu.close=Pechar seedmore.title=Non hai sementes dabondo para este .torrent seedmore.shareratio=O teu promedio compartido para este .torrent \u00e9 de seedmore.uploadmore=Ter un promedio compartido menor do 100% non \u00e9 algo b\u00f3 na rede bittorrent.\nDeber\u00edas servir m\u00e1is este torrent.\nDesexas proceder de todos xeitos? ConfigView.label.showpopuponclose=Pedir confirmaci\u00f3n ao deter compartindo cun promedio compartido menor de 1 ConfigView.label.startNumSeeds=Comezar compartindo se hai menos de ConfigView.label.seeds=sementes ConfigView.section.seeding=compartindo MyTorrentsView.menu.removeand=Eliminar e MyTorrentsView.menu.removeand.deletetorrent=Borrar .torrent MyTorrentsView.menu.removeand.deletedata=Borrar datos MyTorrentsView.menu.removeand.deleteboth=Borrar ambos deletedata.title=Precauci\u00f3n!!! deletedata.message1=Vostede est\u00e1 a piques de borra-los datos contidos en :\n MainWindow.menu.file.configure=Asistente de configuraci\u00f3n configureWizard.title=Asistente de configuraci\u00f3n configureWizard.welcome.title=Benvido ao asistente de configuraci\u00f3n do Vuze configureWizard.welcome.message=Este asistente axudar\u00e1te a configura-las opci\u00f3ns m\u00e1is com\u00fans do Azureus. Podes modificar con maior profundidade estas opci\u00f3ns no men\u00fa Vistas>Configuraci\u00f3n. configureWizard.transfer.title=Configuraci\u00f3n da conexi\u00f3n e as transferencias configureWizard.transfer.hint=Tip : po\u00f1er un pouco menos da velocidade real da li\u00f1a \u00e9 a mellor opci\u00f3n. configureWizard.transfer.message=Pr\u00e9gase elixas unha conexi\u00f3n da lista a continuaci\u00f3n. Ten en conta que ao non permitires suficiente velocidade de subida a t\u00faa velocidade de descarga ver\u00e1se diminuida. Se intentas baixar demasiados torrents \u00e1 vez tam\u00e9n ter\u00e1s como resultado velocidades m\u00e1is baixas. Recomend\u00e1mosche usar 5kB/s por torrent coma un m\u00ednimo estricto. Canto m\u00e1is r\u00e1pido sirvas, m\u00e1is r\u00e1pido baixar\u00e1s. configureWizard.transfer.connection=L\u00ed\u00f1a configureWizard.transfer.connection.0=Persoalizado configureWizard.transfer.connection.1=modem/rdsi configureWizard.transfer.connection.2=adsl/cable xxx/128 kbps configureWizard.transfer.connection.3=adsl/cable xxx/256 kbps configureWizard.transfer.connection.4=adsl/cable xxx/384 kbps configureWizard.transfer.maxUpSpeed=Velocidade m\u00e1xima de envios (kB/s) configureWizard.transfer.maxActiveTorrents=M\u00e1x. Activos configureWizard.transfer.maxDownloads=M\u00e1x. Descargas configureWizard.transfer.maxUploadsPerTorrent=M\u00e1x. envios por Torrent configureWizard.nat.title=NAT / Portos do servidor configureWizard.nat.message=Se desexas obter o mellor de BitTorrent, \u00e9 moi recomend\u00e1bel que poidas conectar directamente dende Internet. O rango de portos por defecto de BitTorrent vai dende 6881 ata 6889. Esta ferramenta perm\u00edteche probar e/ou mudar de portos. Se tes algunha descarga activa, \u00e9 pos\u00edbel que alg\u00fans portos non sexan acces\u00edbeis. configureWizard.nat.test=Probar configureWizard.nat.testing=Probando portos configureWizard.nat.ok=Ok configureWizard.nat.ko=Erro de NAT configureWizard.nat.unable=Non se puido comprobar configureWizard.file.title=Torrents / Arquivos configureWizard.file.message1=Vuze gardar\u00e1 os .torrent abertos nunha carpeta espec\u00edfica, podes escoller esta carpeta aqu\u00ed: configureWizard.file.path=Ruta configureWizard.file.browse=Examinar configureWizard.file.message2=Vuze \u00e9 capaz de resumir instantaneamente os teus arquivos engadindo alg\u00fans datos de resumo aos teus .torrents. Usando esta caracter\u00edstica, tambien podr\u00e1s resumir piezas de archivos parcialmente descargados. configureWizard.file.fastResume=Activar resumo r\u00e1pido configureWizard.file.invalidPath=Carpeta inv\u00e1lida configureWizard.finish.title=Completado configureWizard.finish.message=Vuze est\u00e1 agora configurado, disfruta del! wizard.close.confirmation=Confirmaci\u00f3n wizard.close.message=Desexas que o Asistente se cargue a vindeira vez que inicie-lo Vuze exportTorrentWizard.title=Exportar un .torrent exportTorrentWizard.torrentfile.title=Selecci\u00f3n do arquivo .torrent exportTorrentWizard.torrentfile.message=Escolle o arquivo .torrent a exportar exportTorrentWizard.torrentfile.path=Ruta exportTorrentWizard.torrentfile.browse=Examinar exportTorrentWizard.torrentfile.invalidPath=Arquivo .torrent inv\u00e1lido exportTorrentWizard.exportfile.title=Exportar arquivos seleccionados exportTorrentWizard.exportfile.message=Ingresa-la carpeta onde se vai exportar exportTorrentWizard.exportfile.path=Ruta exportTorrentWizard.exportfile.browse=Examinar exportTorrentWizard.exportfile.invalidPath=Arquivo .torrent inv\u00e1lido exportTorrentWizard.finish.title=Completado exportTorrentWizard.finish.message=O proceso de exportaci\u00f3n completouse axeitadamente exportTorrentWizard.process.inputfilebad.title=Arquivo .torrent inv\u00e1lido exportTorrentWizard.process.inputfilebad.message=Un erro ocurriu cando se estaba a acceder aos arquivos: exportTorrentWizard.process.outputfileexists.title=O archivo existe exportTorrentWizard.process.outputfileexists.message=O arquivo de sa\u00edda existe - sobreescribir? exportTorrentWizard.process.torrentfail.title=Fallou a lectura do .torrent exportTorrentWizard.process.exportfail.title=O proceso de exportaci\u00f3n fallou exportTorrentWizard.process.unknownfail.title=Erro non agardado importTorrentWizard.title=Importar un .torrent importTorrentWizard.torrentfile.title=Selecci\u00f3n do arquivo .torrent importTorrentWizard.torrentfile.message=Escolle o arquivo .torrent a importar importTorrentWizard.torrentfile.path=Ruta importTorrentWizard.torrentfile.browse=Examinar importTorrentWizard.torrentfile.invalidPath=Arquivo .torrent inv\u00e1lido importTorrentWizard.importfile.title=Importar arquivos seleccionados importTorrentWizard.importfile.message=Ingresa-lo arquivo a importar importTorrentWizard.importfile.path=Ruta importTorrentWizard.importfile.browse=Examinar importTorrentWizard.importfile.invalidPath=Arquivo a importar inv\u00e1lido importTorrentWizard.finish.title=Completado importTorrentWizard.finish.message=O proceso de importaci\u00f3n completouse axeitadamente importTorrentWizard.process.inputfilebad.title=Arquivo a importar inv\u00e1lido importTorrentWizard.process.inputfilebad.message=Un erro ocurriu cando se estaba a acceder aos arquivos: importTorrentWizard.process.outputfileexists.title=O arquivo existe importTorrentWizard.process.outputfileexists.message=O arquivo de sa\u00edda existe - sobreescribir? importTorrentWizard.process.torrentfail.title=Fallou a creaci\u00f3n do torrent importTorrentWizard.process.importfail.title=Fallou a importaci\u00f3n do torrent importTorrentWizard.process.unknownfail.title=Erro non agardado ConfigView.label.zeronewfiles=Ning\u00fan arquivo novo ConfigView.section.stats=Estat\u00edsticas ConfigView.section.stats.enable=Activado ConfigView.section.stats.defaultsavepath=Carpeta para garda-las estat\u00edsticas ConfigView.section.stats.choosedefaultsavepath=Pr\u00e9gase escolla a carpeta para garda-las estat\u00edsticas ConfigView.section.stats.savefreq=Gardar frecuencia ConfigView.section.stats.minutes=min ConfigView.section.stats.hours=hr ConfigView.section.stats.seconds=sec ConfigView.section.stats.savefile=Nome do arquivo das estat\u00edsticas MyTorrentsView.menu.export=Exportar... MyTorrentsView.menu.host=Host... ManagerItem.finishing=Rematando ConfigView.dialog.choosedefaulttorrentpath=Pr\u00e9gase escolla a carpeta por defecto dos torrents ConfigView.dialog.choosemovepath=Pr\u00e9gase escolla a carpeta \u00e1 que desexa cambiar ConfigView.label.movecompleted=Mover arquivos completados ConfigView.label.savetorrents=Gardar arquivos torrent MainWindow.menu.view.mytracker=O meu Tracker MyTrackerView.title.full=O meu Tracker MyTrackerView.name=Nome MyTrackerView.tracker=Tracker MyTrackerView.status=Estado MyTrackerView.status.started=Executando MyTrackerView.status.stopped=Detido MyTrackerView.peers=Pares MyTrackerView.seeds=Sementes MyTrackerView.announces=Anuncios MyTrackerView.uploaded=Subido MyTrackerView.downloaded=Baixado MyTrackerView.left=Resta ConfigView.section.style=Interface ConfigView.section.style.useCustomTabs=Usar barras pechables (precisa reiniciar) MainWindow.menu.view.plugins=Plugins fileDownloadWindow.saveTorrentIn=Gardar arquivo torrent en fileDownloadWindow.title=Vuze - Torrent Downloader fileDownloadWindow.downloading=Baixando de : fileDownloadWindow.status=Estado : fileDownloadWindow.state_initializing=Iniciando fileDownloadWindow.state_downloading=Baixando fileDownloadWindow.state_error=Erro : MainWindow.menu.file.open.url=URL openUrl.title=Vuze - Abrir Url openUrl.url=URL : MyTorrentsView.menu.host.error.title=Fallou o hosting do torrent MyTorrentsView.menu.host.error.message=O seguinte erro ocurriu mentres serv\u00eda o torrent ConfigView.section.tracker=Tracker ConfigView.section.tracker.pollinterval=Tracker client poll interval (secs) ConfigView.section.tracker.publishenable=Publica-los detalles do torrent en "/" ConfigView.section.tracker.ip=Direcci\u00f3n IP do tracker externo IPChecker.external.service.dyndns.name=DynDNS IPChecker.external.service.dyndns.url=http://www.dyndns.org/ IPChecker.external.service.dyndns.description=Dynamic DNS Network Services, LLC ConfigView.section.tracker.checkip=Comprobar direcci\u00f3n... ipCheckerWizard.title=Asistente para comproba-la t\u00faa direcci\u00f3n IP ipCheckerWizard.service=Servizo ipCheckerWizard.chooseService=Pr\u00e9gase escolla un comprobador de direcci\u00f3ns IP dos seguintes listados ipCheckerWizard.explanations=Podes usa-lo asistente para acha-la t\u00faa direcci\u00f3n IP externa. Se a t\u00faa direcci\u00f3n IP \u00e9 din\u00e1mica, recomendamos que abras unha conta cun proveedor de DNS din\u00e1mico. Alg\u00fans dos proveedores destes servizos est\u00e1n listados a continuaci\u00f3n, usa a ligaz\u00f3n para abrir unha nova conta. Despois rechea o campo 'IP address' co teu servidor din\u00e1mico (ex. myhostname.dyndns.org). Precisar\u00e1s dun programa que automaticamente actualice o teu proveedor de DNS din\u00e1mico coa t\u00faa direcci\u00f3n IP. Deste xeito poder\u00e1s ofrecer Torrents, inclusive se a t\u00faa direcci\u00f3n IP cambia. ipCheckerWizard.service.description=Descripci\u00f3n : ipCheckerWizard.service.url=Ligaz\u00f3n : ipCheckerWizard.progresstitle=Comprobando IP ipCheckerWizard.checkComplete=IP completada : ipCheckerWizard.checkFailed=Fallou, raz\u00f3n : wizard.tracker.local=Usa-lo Tracker embebido de Vuze wizard.tracker.external=Usar un Tracker externo wizard.tracker.howToLocal=\tIr a 'Configuraci\u00f3n>Tracker' para habilitalo wizard.announceUrl=Direcci\u00f3n URL do anuncio : IPChecker.external.service.discoveryvip.name=Discoveryvip IPChecker.external.service.discoveryvip.url=http://ip.discoveryvip.com/ IPChecker.external.service.discoveryvip.description=Discoveryvip - Chequeo de direcci\u00f3n IP unicamente IPChecker.external.httpinvalidresponse=Resposta HTTP inv\u00e1lida IPChecker.external.loadingwebpage=Cargando p\u00e1xina web IPChecker.external.analysingresponse=Analizando resposta IPChecker.external.addressextracted=Direcci\u00f3ns IP extra\u00eddas IPChecker.external.httploadfail=Erro ao carga-la p\u00e1xina IPChecker.external.timeout=F\u00f3ra de tempo IPChecker.external.ipnotfound=Direcci\u00f3n IP non atopada ConfigView.section.tracker.pollintervalmin=M\u00ednimo ConfigView.section.tracker.pollintervalmax=M\u00e1ximo ConfigView.section.tracker.pollintervalincby=Incrementar por ConfigView.section.tracker.pollintervalincper=Every 'n' Clients splash.loadingImages=Cargando imaxes splash.initializeGui=Iniciando fiestra principal splash.openViews=Abrindo vistas splash.plugin=Cargando plugin : configureWizard.nat.tooManyPorts=Demasiados portos para probar (9 m\u00e1x) MyTorrentsView.menu.publish=Publicar... MyTrackerView.status.published=Publicado MyTrackerView.completed=Completado MainWindow.menu.file.open.torrentnodefault=Arquivo .torrent (sen gardar por defecto) wizard.comment=Comentarios ConfigView.label.movetorrent=Mover .torrent ConfigView.section.file.decoder.label=Default torrent encoding when\nselection required ConfigView.section.file.decoder.nodecoder=Ning\u00fan IPChecker.external.service.no-ip.name=No-IP IPChecker.external.service.no-ip.url=http://www.no-ip.com/ IPChecker.external.service.no-ip.description=Dynamic and Static DNS service provider\n(no freely available 'check address' service) ConfigView.section.tracker.publicenable=Activar .torrents externos # # Tooltips # # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Update GUI every ConfigView.section.style.graphicsUpdate=Update Graphical bars every N GUI update(s) ConfigView.section.style.reOrderDelay=Re Order tables every N GUI update(s) ConfigView.section.style.reOrderDelay.never=Nunca ConfigView.section.logging=Rexistrando... ConfigView.section.logging.enable=Enable logging to file ConfigView.section.logging.logdir=Log file directory ConfigView.section.logging.choosedefaultsavepath=Pr\u00e9gase escolla a carpeta a gardar GeneralView.label.updatein.querying=preguntando... configureWizard.nat.sharePort=Usar un s\u00f3 porto compartido para todos os .torrent ConfigView.section.logging.maxsize=Maximum log file size ConfigView.section.tracker.passwordenableweb=Enable password on tracker web ConfigView.section.tracker.passwordenabletorrent=Enable password on torrents ConfigView.section.tracker.username=User name ConfigView.section.tracker.password=Password columnChooser.title=Choose the columns to display columnChooser.move=Drag rows to re-order them columnChooser.apply=Apply TableColumn.header.shareRatio=Share Ratio MyTorrentsView.menu.editTableColumns=Choose the columns to display wizard.operationfailed=Operation failed authenticator.title=Authentication Required authenticator.realm=Realm authenticator.tracker=Tracker authenticator.user=User name authenticator.password=Password ConfigView.label.allowSendVersion=Allow Vuze to send anonymous version number and random id while checking for new version wizard.hint.mode=Hint:\tYou can Drag and Drop a single file or directory on this wizard\n\tto choose a file or directory wizard.hint.file=Hint:\tYou can choose a single file with Drag and Drop wizard.hint.directory=Hint:\tYou can choose a single directory with Drag and Drop MainWindow.menu.help.checkupdate=Check for program update TableColumn.header.down=Downloaded TableColumn.header.up=Uploaded ConfigView.section.tracker.passwordenabletorrent.info=Requires suitable BitTorrent client (e.g. Vuze ConfigView.section.style.confirmationOnExit=Show confirmation dialog on exit MainWindow.dialog.exitconfirmation.title=Exit Vuze MainWindow.dialog.exitconfirmation.text=Do you really want to exit Vuze TrayWindow.menu.stopalldownloads=Stop All Downloads ConfigView.section.tracker.sslport.info=See the FAQ for further information wizard.tracker.ssl=Use SSL ConfigView.label.playdownloadfinished=Play a sound when a download is finished TableColumn.header.pieces=Pieces TableColumn.header.completion=Completion ConfigView.section.style.showdownloadbasket=Show Download Basket (Drag and Drop .torrents) ConfigView.section.style.alwaysShowTorrentFiles=Always show Torrent files in Details/Files wizard.multitracker=Add Multi-Tracker information to the torrent wizard.multitracker.title=Multi-Tracker wizard.multitracker.configuration=Multi-Tracker Configuration wizard.multitracker.new=New... wizard.multitracker.edit=Edit.. wizard.multitracker.delete=Delete wizard.multitracker.group=Tracker Group wizard.multitracker.edit.title=Multi-Tracker Editor wizard.multitracker.edit.name=Name wizard.multitracker.edit.save=Save wizard.multitracker.edit.newgroup=New Group wizard.multitracker.edit.deletegroup=Delete wizard.multitracker.edit.newtracker=New Tracker wizard.multitracker.edit.deletetracker=Delete wizard.multitracker.edit.edit=Edit wizard.addingmt=Adding Multi-Tracker info wizard.multitracker.noannounce=Announce URL isn't present in your trackers list MyTorrentsView.menu.recheck=Force Re-check iconBar.showDownloadBar.tooltip=Show Download Bar iconBar.start.tooltip=Start iconBar.stop.tooltip=Stop iconBar.remove.tooltip=Remove iconBar.openNoDefault.tooltip=Open a .torrent file (no default save) iconBar.openURL.tooltip=Open an URL iconBar.openFolder.tooltip=Open a Folder iconBar.new.tooltip=Create a torrent iconBar.up.tooltip=Move up iconBar.down.tooltip=Move Down iconBar.run.tooltip=Open iconBar.host.tooltip=Host iconBar.publish.tooltip=Publish MyTorrentsView.menu.editTracker=Edit Tracker URL(s) GeneralView.menu.selectTracker=Select ConfigView.section.stats.xslfile=XSL file name ConfigView.section.stats.xslfiledetails=This will be included in stats file header via tag ConfigView.label.savetorrentbackup=Save Backup ConfigView.section.tracker.forceport=Force hosted external torrents to default port ConfigView.section.ipfilter.allow=ALLOW these ranges (default is DENY) ConfigView.section.ipfilter.list.notinrange=was not in any range ConfigView.section.ipfilter.list.title=Blocked IPs List ConfigView.label.allowsameip=Allow Multiple connections from the same IP ConfigView.label.allowsameip.tooltip=Only check if you NEED it.\nThis is a leecher protection (when disabled). ManagerItem.superseeding=Super-Seeding ConfigView.label.userSuperSeeding=Use Super Seeding PeersView.uniquepiece=Piece (Super-Seed Mode) PeersView.uniquepiece.none=None PeersView.timetosend=Time to resend Piece (Super-Seed Mode) ConfigView.section.style.addurlsilently=Open URL silently (without dialog) ConfigView.section.style.addurlsilently.tooltip=Warning: the main window will not made visible again if activated!\nIf you loose the tray icon, you should deactivate this option. ConfigView.section.file.decoder.prompt=Always prompt when encoding choice available ConfigView.section.file.decoder.prompt.tooltip=Always show dialog when encoding choice is available MyTorrentsView.menu.moveTop=Top MyTorrentsView.menu.moveEnd=Bottom ConfigView.label.moveonlyusingdefaultsave=if in default data dir ConfigView.label.moveonlyusingdefaultsave.tooltip=Move only if the .torrent is in the default data dir ConfigView.label.watchtorrentfolder=Import new .torrents automatically ConfigView.label.watchtorrentfolder.tooltip=Looks for new .torrents regularly ConfigView.label.watchtorrentfolderinterval=Interval ConfigView.label.watchtorrentfolderinterval.tooltip=The pause until the folder will be scanned again ConfigView.dialog.choosewatchtorrentfolderpath=Please choose the .torrent import directory ConfigView.label.startwatchedtorrentsstopped=Begin stopped ConfigView.label.startwatchedtorrentsstopped.tooltip=Add new .torrents in STOPPED state ConfigView.section.plugins=Plugins wizard.maketorrent.filesize=File(s) Size wizard.maketorrent.piececount=Piece Count wizard.maketorrent.piecesize=Piece Size wizard.maketorrent.auto=Auto MainWindow.menu.view.stats=Statistics SpeedView.title.full=Activity SpeedView.downloadSpeed.title=Download Speed SpeedView.uploadSpeed.title=Upload Speed ConfigView.section.style.useSIUnits=Use IEC Units (KB -> KiB etc.) iconBar.top.tooltip=Move to top iconBar.bottom.tooltip=Move to bottom TableColumn.header.health=Health MyTorrentsView.menu.health=About Health health.explain.grey=means that your torrent is not running (downloading or uploading) health.explain.red=means that you're not connected to any peer while downloading health.explain.blue=when seeding, it means that you're not yet connected to any peer\nwhen downloading, it means that you are connected to some peers but the tracker is down health.explain.yellow=means that the tracker is ok, you're connected to peers, but you don't have any remote connection.\nYou may have a NAT problem if your torrents stay on yellow status all the time health.explain.green=means that everything is going fine. ConfigView.section.style.alwaysRefreshMyTorrents=Always refresh My Torrents # #2.0.7.0 # # # 2.0.7.x # TableColumn.header.availability=Dispo\u00f1ibilidade # # > 2.0.8.0 # ConfigView.section.tracker.publishenabledetails=Publish torrent file and peer details #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed ConfigView.label.overrideip=Establecer IP enviada ao rastreador (NAT) #file can be a URL or a path in the jar # %1 = "in kbps" or ""; %2 = "upload" or "download" # > 2402 # Used for peers which we can't determine. PeerSocket.unknown=Desco\u00f1ecido MainWindow.menu.help.faq=FAQ MainWindow.menu.help.donate=Fai unha doaz\u00f3n ($2,$5,...) azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle.properties0000644000175000017500000057343611307672740025051 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torrent File... MainWindow.menu.file.open.torrent.keybinding=Meta+O Main.parameter.usage=Usage : java org.gudy.azureus2.cl.Main [parameters] \"file.torrent\" \"save path" Main.parameter.maxUploads=Max number of simultaneous uploads Main.parameter.maxSpeed=Max upload speed in bytes/sec MainWindow.menu.file=&File MainWindow.menu.file.open=&Open MainWindow.menu.file.create=&New Torrent... MainWindow.menu.file.create.keybinding=Meta+N MainWindow.menu.file.create.fromfile=From a &File MainWindow.menu.file.create.fromdir=From a &Directory MainWindow.menu.file.export=&Export XML Torrent... MainWindow.menu.file.export.keybinding=Meta+E MainWindow.menu.file.export.keybinding.mac=Meta+Shift+E MainWindow.menu.file.import=&Import XML Torrent... MainWindow.menu.file.import.keybinding=Meta+I MainWindow.menu.file.import.keybinding.mac=Meta+Shift+I MainWindow.menu.file.closetab=Close &Tab MainWindow.menu.file.closetab.keybinding=Meta+W MainWindow.menu.file.closewindow=Close &Window MainWindow.menu.file.closewindow.keybinding=Meta+Shift+W MainWindow.menu.file.exit=E&xit MainWindow.menu.file.exit.keybinding=Alt+F4 MainWindow.dialog.choose.file=Choose the torrent file MainWindow.menu.file.folder=&Folder... MainWindow.menu.file.folder.keybinding=Meta+Shift+O MainWindow.dialog.choose.folder=Choose the directory containing the torrent files MainWindow.menu.view=&View MainWindow.menu.view.show=Show MainWindow.menu.view.mytorrents=&My Torrents MainWindow.menu.view.mytorrents.keybinding=Meta+1 MainWindow.menu.view.open_global_transfer_bar=Transfers Bar MainWindow.menu.view.configuration=&Options... MainWindow.menu.view.configuration.keybinding=Meta+, MainWindow.menu.view.console=C&onsole MainWindow.menu.view.console.keybinding=Meta+4 MainWindow.menu.view.irc=&IRC MainWindow.menu.view.allpeers=All Peers MainWindow.menu.view.detailedlist=&Detailed List MainWindow.menu.closealldetails=Close &All Details MainWindow.menu.closealldownloadbars=Close All Download &Bars MainWindow.menu.language=&Language ConfigView.section.language=Language MainWindow.menu.window=&Window MainWindow.menu.window.minimize=&Minimize MainWindow.menu.window.minimize.keybinding=Meta+M MainWindow.menu.window.zoom=&Zoom MainWindow.menu.window.alltofront=Bring All to &Front MainWindow.menu.help=&Help MainWindow.menu.help.about=About Vuze MainWindow.menu.torrent=T&orrent MainWindow.about.title=About MainWindow.about.section.developers=Developers MainWindow.about.section.translators=Translators MainWindow.about.section.system=System MainWindow.about.section.internet=Internet MainWindow.about.internet.homepage=Vuze Homepage MainWindow.about.internet.sourceforge=Sourceforge Project Page MainWindow.about.internet.sourceforgedownloads=Sourceforge Downloads MainWindow.about.internet.bugreports=Bug Reports MainWindow.about.internet.forumdiscussion=Forums MainWindow.about.internet.wiki=Vuze Wiki FAQ MainWindow.dialog.choose.savepath=Choose the save path MainWindow.dialog.choose.savepath_forallfiles=Choose the save path for ALL files MainWindow.status.latestversion=Latest MainWindow.status.latestversion.clickupdate=Click to update MainWindow.status.unknown=unknown MainWindow.status.checking=checking MyTorrentsView.mytorrents=My Torrents TableColumn.header.name=Name TableColumn.header.size=Size TableColumn.header.done=Done TableColumn.header.done.info=Percentage done of current task TableColumn.header.status=Status TableColumn.header.status.info=What the torrent is doing TableColumn.header.seeds=Seeds TableColumn.header.seeds.info=# seeds connected to (# seeds total) TableColumn.header.peers=Peers TableColumn.header.peers.info=# peers connected to (# peers total) TableColumn.header.completed=Completed TableColumn.header.completed.info=# of peers that finished downloading the torrent as reported by the tracker TableColumn.header.downspeed=Down Speed TableColumn.header.upspeed=Up Speed TableColumn.header.eta=ETA TableColumn.header.tracker=Tracker Status TableColumn.header.tracker.info=Status of tracker TableColumn.header.trackernextaccess=Next Tracker Access TableColumn.header.trackernextaccess.info=When the next tracker access will occur TableColumn.header.priority=Priority TableColumn.header.priority.info=Determines how much upload bandwidth the torrent is given TableColumn.header.seeds.fullcopycalc=%2 full copies assumed for %1 peers MyTorrentsView.menu.showdetails=Show &Details MyTorrentsView.menu.showdownloadbar=Show Download &Bar MyTorrentsView.menu.open=&Open File MyTorrentsView.menu.setpriority=Set &Priority MyTorrentsView.menu.setpriority.high=&High MyTorrentsView.menu.setpriority.low=&Low MyTorrentsView.menu.start=&Start MyTorrentsView.menu.stop=Sto&p MyTorrentsView.menu.remove=&Remove MyTorrentsView.menu.changeTracker=&Add Tracker URL TrayWindow.menu.exit=E&xit TrayWindow.menu.show=&Show Vuze SystemTray.menu.exit=E&xit SystemTray.menu.closealldownloadbars=Close &All Download Bars SystemTray.menu.open_global_transfer_bar=Show Transfers Bar SystemTray.menu.show=&Show Vuze PeersView.ip=IP PeersView.ip.info=IP of the peer PeersView.port=Port PeersView.port.info=Port being used PeersView.T=T PeersView.T.info=L (local): you established the connection, R (remote): the peer established the connection. PeersView.T.L.tooltip=You established the connection PeersView.T.R.tooltip=The peer established the connection PeersView.I1=I (Interested by the peer) PeersView.I1.info=Are you interested in what the other peer has? PeersView.C1=C (Choked by the peer) PeersView.C1.info=Whether the peer is stopping you from downloading PeersView.pieces=Pieces PeersView.%=% PeersView.downloadspeed=Down Speed PeersView.download=Down PeersView.download.info=Your overall download from the peer. PeersView.I2=I (Interesting for the peer) PeersView.I2.info=Is the peer interested in what you have? PeersView.C2=C (Choking the peer) PeersView.C2.info=Whether you are blocking the peer from downloading PeersView.uploadspeed=Up Speed PeersView.uploadspeed.info=Your uploading speed to the peer PeersView.upload=Up PeersView.upload.info=Your overall upload to the peer. PeersView.statup=Stat Up PeersView.statup.info=An estimated value of the upload speed of the peer PeersView.S=S PeersView.S.info=Snubbed: A peer can be "snubbed" manually, or automatically (for not delivering data at a high enough rate) PeersView.downloadspeedoverall=Overall Down Speed PeersView.optunchoke=Opt. Unchoke PeersView.client=Client PeersView.client.info=Type of BT client the peer is using PeersView.menu.snubbed=&Snubbed PeersView.title.short=Peers PeersView.title.full=Peers AllPeersView.title.full=All Peers ConfigView.section.files=Files ConfigView.label.usefastresume=Use Fast Resume mode ConfigView.label.incrementalfile=Enable incremental file creation [Required for FAT32 under Linux] ConfigView.label.defaultsavepath=Save to default data directory ConfigView.button.browse=&Browse... ConfigView.dialog.choosedefaultsavepath=Please choose the default save directory ConfigView.section.server=Connection ConfigView.section.global=General ConfigView.label.disconnetseed=Disconnect seeds when seeding ConfigView.label.switchpriority=Auto-switch to low-priority when seeding ConfigView.label.maxdownloads=Max simultaneous downloads [0: unlimited]\n - Cannot be higher than the number of max active torrents ConfigView.label.maxdownloads.tooltip=You will always be able to actively download the number you provide here, with one exception.\nA completed torrent matching First Priority may take over an active download slot if absolutely required. ConfigView.label.maxactivetorrents=Max active torrents [0: unlimited]\n - New torrents won\'t start if you are downloading/seeding more ConfigView.label.priorityExtensions=Auto-prioritize files with \n - eg: .txt;.nfo;.jpg ConfigView.section.transfer=Transfer ConfigView.label.maxuploads=Max upload slots per torrent default ConfigView.label.maxuploadspeed=KB/s global max upload speed [0: unlimited] ConfigView.label.saveresumeinterval=Update resume data every ConfigView.unlimited=Unlimited ConfigView.section.display=Display ConfigView.label.opendetails=Auto open details tab ConfigView.label.openbar=Auto open download bar ConfigView.label.use_old_speed_menus=Use old style speed menus [restart required] ConfigView.label.closetotray=Close minimizes to System Tray ConfigView.label.minimizetotray=Minimize minimizes to System Tray ConfigView.section.general=General ConfigView.section.start=Start ConfigView.label.showsplash=Show splash screen ConfigView.label.autoupdate=Open Upgrade dialog when newer version is available ConfigView.label.openconsole=Open Console on startup ConfigView.label.openconfig=Open Options on startup ConfigView.label.startminimized=Start minimized ConfigView.section.irc=IRC ConfigView.label.ircwiki=Please read http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Server ConfigView.label.ircchannel=Channel ConfigView.label.irclogin=Nickname ConfigView.group.irctitle=IRC Settings ConfigView.boolean.ircsendinfo=Allow sending your settings (anonymous) to\n the channel operators to help them help you ConfigView.boolean.irclog=Enable logging of channel activity (in IRC_log.htm) ConfigView.section.security=Security ConfigView.label.password=Protect Vuze using a password\n - Will be asked when de-iconifying and when started. ConfigView.label.passwordconfirm=Password (confirm) ConfigView.label.passwordmatch=Password activated : ConfigView.label.passwordmatchnone=No ConfigView.label.passwordmatchno=No / Passwords don't match ConfigView.label.passwordmatchyes=Yes ConfigView.button.save=Save ConfigView.title.short=Options ConfigView.title.full=Options ConfigView.title.full._mac=Preferences ConsoleView.title.short=Console ConsoleView.title.full=Console FileItem.write=write FileItem.read=read FileItem.normal=normal FileItem.high=high FileItem.donotdownload=Do not download FileItem.delete=Delete FilesView.name=Name FilesView.name.fastRename=Fast Renaming FilesView.size=Size FilesView.done=Done FilesView.%=% FilesView.firstpiece=First piece \# FilesView.numberofpieces=\# of pieces FilesView.pieces=Pieces FilesView.mode=Mode FilesView.priority=Priority FilesView.menu.open=&Open FilesView.menu.setpriority=&Set Priority FilesView.menu.setpriority.high=&High FilesView.menu.setpriority.normal=&Normal FilesView.menu.setpriority.skipped=&Do not download FilesView.title.short=Files FilesView.title.full=Files GeneralView.section.downloaded=Downloaded GeneralView.label.status.file=File Status GeneralView.label.status.pieces=Pieces Status GeneralView.section.availability=Availability GeneralView.label.status.pieces_available=Pieces Status GeneralView.section.transfer=Transfer GeneralView.section.info=Info GeneralView.title.short=General GeneralView.title.full=General GeneralView.label.timeelapsed=Time Elapsed : GeneralView.label.remaining=Remaining : GeneralView.label.downloaded=Downloaded : GeneralView.label.downloadspeed=Download Speed : GeneralView.label.maxuploads=Upload Slots : GeneralView.label.maxuploads.tooltip=Maximum number of peers that will be unchoked at any given time. GeneralView.label.uploaded=Uploaded : GeneralView.label.uploadspeed=Upload Speed : GeneralView.label.seeds=Seeds : GeneralView.label.peers=Peers : GeneralView.label.completed=Completed : GeneralView.label.totalspeed=Swarm Speed : GeneralView.label.totalspeed.tooltip=Total (and average) speed of all clients you are connected to. GeneralView.label.averagespeed=average GeneralView.label.filename=Name : GeneralView.label.totalsize=Total Size : GeneralView.label.savein=Save In : GeneralView.label.hash=Hash : GeneralView.label.numberofpieces=\# of Pieces : GeneralView.label.size=Size : GeneralView.label.tracker=Tracker Status : GeneralView.label.updatein= Update In : GeneralView.label.trackerurl=Tracker URL : GeneralView.label.trackerurlupdate = Update Tracker GeneralView.label.comment=Torrent Comment : GeneralView.label.user_comment=User Comment : GeneralView.label.status=Status : ManagerItem.waiting=Waiting ManagerItem.allocating=Allocating ManagerItem.checking=Checking ManagerItem.ready=Waiting for other torrent(s) to Queue ManagerItem.downloading=Downloading ManagerItem.seeding=Seeding ManagerItem.stopped=Stopped ManagerItem.error=Error ManagerItem.high=high ManagerItem.low=low MinimizedWindow.name=Name: MinimizedWindow.all_transfers=Vuze Transfers PiecesView.#=# PiecesView.size=Size PiecesView.numberofblocks=\# of Blocks PiecesView.blocks=Blocks PiecesView.completed=Completed PiecesView.availability=Availability PiecesView.reservedby=Reserved PiecesView.writers=Block Contributors PiecesView.title.short=Pieces PiecesView.title.full=Pieces SystemTray.tooltip.seeding=%1 seeding, SystemTray.tooltip.downloading=%1 downloading, DownloadManager.error.filenotfound=File Not Found DownloadManager.error.fileempty=Torrent file is empty DownloadManager.error.filetoobig=Torrent file is too big DownloadManager.error.filewithouttorrentinfo=No Torrent information found in file DownloadManager.error.unsupportedencoding=Unsupported Encoding DownloadManager.error.ioerror=IO Error DownloadManager.error.sha1=No such Algorithm (SHA1) Error PeerManager.status.offline=Connection Error PeerManager.status.ok=OK PeerManager.status.checking=Checking PeerManager.status.finished=Finished PeerManager.status.finishedin=Finished in MainWindow.upgrade.assistant=Upgrade Assistant MainWindow.upgrade.newerversion=There is a newer version of Vuze available for download MainWindow.upgrade.explanation=This assistant will download the new version into your Vuze folder and restart Vuze MainWindow.upgrade.explanation.manual=You can update manually by closing Vuze downloading the new Version and restarting Vuze MainWindow.upgrade.step1=Step 1: Download the new version MainWindow.upgrade.step2=Step 2: Close this version and restart the new version of Vuze MainWindow.upgrade.hint1=Hint:\tPressing Finish does everything automatic MainWindow.upgrade.hint2=Hint:\tIf you want to close Vuze later, press Cancel and\n\trename Azureus2-new.jar to Azureus2.jar after closing MainWindow.upgrade.error.downloading.hint=Error:\tUnable to download new version, please update manually MainWindow.upgrade.section.info=New Version Available MainWindow.upgrade.section.manual=Manual Update MainWindow.upgrade.section.automatic=Automatic Update MainWindow.upgrade.tooltip.progressbar=The download progress is shown here Button.next=Next Button.finish=Finish Button.cancel=&Cancel LocaleUtil.title=Choose Encoding LocaleUtil.section.chooseencoding=Choose encoding for filename LocaleUtil.label.chooseencoding=Please select the best matching encoding LocaleUtil.label.hint.doubleclick=Hint: double-clicking on a row chooses encoding and closes the dialog LocaleUtil.label.checkbox.rememberdecision=Remember decision for remaining filenames LocaleUtil.column.encoding=Encoding IrcClient.defaultChannel=#Azureus-Users IrcClient.copyright=Using the PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Connecting to IrcClient.connected=Connected to IrcClient.joining=Joining IrcClient.channel=Channel IrcClient.joined=joined IrcClient.error=Error IrcClient.hasjoined=has joined IrcClient.haskicked=has kicked IrcClient.hasleft=has left IrcClient.nowknown=is now known as IrcClient.topicforchannel=Topic for channel IrcClient.disconnected=Disconnected from IrcClient.noNick=No Nickname Specified. Please go to \'Options\' View IrcView.actionnotsupported=This action isn't supported IrcView.clientsconnected=users IrcView.privateto=To IrcView.privatefrom=From IrcView.noticefrom=Notice : IrcView.errormsg=Wrong Syntax on /msg : /msg user text IrcView.help=Valid commands are :\n . /help : displays this message\n . /nick | /name : changes your name \n . /me action : sends an action \n . /msg nick message : sends a private message to \n . /r message : reply to last private message\n . /join #channelB (do not click here, it's an example) : changes current channel to channelB PasswordWindow.title=Vuze is locked PasswordWindow.passwordprotected=Vuze is password protected.\nTo show Vuze window, please enter your password here : Button.ok=&OK TrackerChangerWindow.title=Add Tracker TrackerChangerWindow.newtracker=Enter new tracker url PeersView.discarded=Discarded PeersView.discarded.info=Data you somehow received although you didn't need it, so you got rid of it. discarded=discarded MyTorrentsView.#=# MyTorrentsView.menu.move=&Move MyTorrentsView.menu.moveUp=&Up MyTorrentsView.menu.moveDown=&Down GeneralView.label.hashfails=Hash Fails : GeneralView.label.shareRatio=Share Ratio : ConfigView.section.downloadManagement=Download Management ConfigView.label.startRatioPeers=Start seeding when there is less than 1 seed for ConfigView.text.neverStop=Never Stop ConfigView.text.neverStart=Never Start ConfigView.text.peers=Peers ConfigView.label.checkOncompletion=Re-check pieces when download is done wizard.title=Make a torrent wizard.previous=< Back wizard.next=Next > wizard.finish=Finish wizard.mode=Tracker / Mode wizard.tracker=Tracker: wizard.invalidurl=This URL isn't valid wizard.singlefile=Single file wizard.singlefile.help=Create a torrent from a single file wizard.directory=Directory wizard.directory.help=Create a torrent from a directory wizard.choosefile=Choose the file wizard.file=File : wizard.browse=Browse... wizard.choosedirectory=Choose a directory wizard.invalidfile=Invalid File! wizard.invaliddirectory=Invalid Directory! wizard.torrentFile=Torrent File wizard.choosetorrent=Please choose the torrent file to create wizard.information=Information wizard.notimplemented=Not yet implemented wizard.progresstitle=Creating Torrent File wizard.savingfile=Saving File... wizard.filesaved=File saved. wizard.close=Close Torrent.create.progress.piecelength=Piece length: Torrent.create.progress.piececount=Piece count: Torrent.create.progress.totalfilesize=Total file size: Torrent.create.progress.totalfilecount=Total file count: Torrent.create.progress.parsingfiles=Parsing files Torrent.create.progress.hashing=Hashing files MainWindow.upgrade.downloadingfrom=Downloading from : MainWindow.menu.view.ipFilter=&IP Filters ConfigView.section.ipfilter=IP Filters ConfigView.section.ipfilter.description=Description ConfigView.section.ipfilter.start=Start IP ConfigView.section.ipfilter.end=End IP ConfigView.section.ipfilter.add=Add ConfigView.section.ipfilter.remove=Remove ConfigView.section.ipfilter.edit=Edit ConfigView.section.ipfilter.save=Save ConfigView.section.ipfilter.editFilter=Edit Filter ConfigView.section.ipfilter.enable=Enable PeersView.menu.close=&Close seedmore.title=Torrent is not seeded enough seedmore.shareratio=Your share ratio on this torrent is of seedmore.uploadmore=Having a share ratio under 100 percent is not a good thing for the bittorrent network.\nYou should let this torrent seed a little bit more.\nAre you sure you want to proceed? ConfigView.label.showpopuponclose=Show confirmation popup when stopping seeding with a share ratio lower than 1 ConfigView.label.startNumSeeds=\nStart seeding if there is less than\n - Overrides all other rules ConfigView.label.seeds=seeds ConfigView.section.seeding=Seeding MyTorrentsView.menu.removeand=Remo&ve and MyTorrentsView.menu.removeand.deletetorrent=Delete &Torrent File MyTorrentsView.menu.removeand.deletedata=Delete &Data MyTorrentsView.menu.removeand.deleteboth=Delete &Both deletedata.title=Delete Content deletedata.message1=Are you sure you want to permanently delete '%1'? deletedata.noprompt=Don't prompt me again MainWindow.menu.file.configure=Configuration &Wizard... configureWizard.title=Configuration Wizard configureWizard.welcome.title=Welcome to the Vuze Configuration Wizard configureWizard.welcome.message=This wizard will help you configure Vuze for most common use. You can modify the configuration in depth using the Tools->Options menu. configureWizard.transfer.title=Transfer and Connection setup configureWizard.transfer.hint=Hint : Using a little bit less than your line speed is the best setting. configureWizard.transfer.message=Please choose a connection below. Be aware that not allowing enough upload speed will result in slow download speeds. As upload speed only counts PER torrent you\'re downloading, trying to download too many torrents at the same time will also result in slow speeds. We recommend using 5KB/s per torrent as a STRICT minimum. The faster you upload, the faster you'll download (with respect to the torrent speed). configureWizard.transfer.connection=Line configureWizard.transfer.connection.0=Custom configureWizard.transfer.connection.1=modem configureWizard.transfer.connection.2=adsl/cable xxx/128 kbps configureWizard.transfer.connection.3=adsl/cable xxx/256 kbps configureWizard.transfer.connection.4=adsl/cable xxx/384 kbps configureWizard.transfer.connection.5=adsl/cable xxx/512 kbps configureWizard.transfer.connection.6=adsl/cable xxx/768 kbps configureWizard.transfer.connection.7=adsl/cable xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Max Up Speed (KB/s) configureWizard.transfer.maxActiveTorrents=Max Active configureWizard.transfer.maxDownloads=Max Downloads configureWizard.transfer.maxUploadsPerTorrent=Max Uploads per Torrent configureWizard.nat.title=NAT / Server Port configureWizard.nat.message=In order to get the best out of Vuze it's highly recommended to be fully accessible from the internet. \ This tool lets you test and / or change the port used to accept incoming peer connections.\n\nNOTE: This tool only tests for TCP connections. \ The Distributed DB requires incoming UDP connections as well, but will automatically notify you if it discovers a blocking firewall.\n\nNOTE: TCP port 6880 \ is reserved internally, so it cannot be used. configureWizard.nat.test=Test configureWizard.nat.testing=Testing port configureWizard.nat.ok=OK ! configureWizard.nat.ko=NAT Error configureWizard.nat.unable=Unable to test: Invalid port given, or test service failed.\nAnother application may already be using this port. configureWizard.file.title=Torrents / Files configureWizard.file.message1=Vuze will save opened torrents in a specific folder, you can choose this folder here: configureWizard.file.path=Path configureWizard.file.browse=Browse configureWizard.file.message2=Vuze is able to resume your files instantly, by adding some resume data to your torrents. Using this feature, you'll also resume partially downloaded pieces. configureWizard.file.fastResume=Enable fast Resume configureWizard.file.invalidPath=Invalid directory configureWizard.finish.title=Completed configureWizard.finish.message=Vuze is now configured, have fun ! wizard.close.confirmation=Confirmation wizard.close.message=Do you want this wizard to load next time Vuze is started? exportTorrentWizard.title=Export a XML torrent exportTorrentWizard.torrentfile.title=Input Torrent Selection exportTorrentWizard.torrentfile.message=Select the torrent file to export exportTorrentWizard.torrentfile.path=Path exportTorrentWizard.torrentfile.browse=Browse exportTorrentWizard.torrentfile.invalidPath=Invalid torrent file exportTorrentWizard.exportfile.title=Export File Selection exportTorrentWizard.exportfile.message=Enter the xml file to export to exportTorrentWizard.exportfile.path=Path exportTorrentWizard.exportfile.browse=Browse exportTorrentWizard.exportfile.invalidPath=Invalid export file exportTorrentWizard.finish.title=Completed exportTorrentWizard.finish.message=Export completed successfully exportTorrentWizard.process.inputfilebad.title=Torrent File Invalid exportTorrentWizard.process.inputfilebad.message=A failure occurred accessing the input file: exportTorrentWizard.process.outputfileexists.title=File Exists exportTorrentWizard.process.outputfileexists.message=Output file exists - overwrite? exportTorrentWizard.process.torrentfail.title=Torrent Read Fails exportTorrentWizard.process.exportfail.title=Torrent Export Fails exportTorrentWizard.process.unknownfail.title=Unexpected Error importTorrentWizard.title=Import a XML torrent importTorrentWizard.torrentfile.title=Input Torrent Selection importTorrentWizard.torrentfile.message=Enter the torrent file to import into importTorrentWizard.torrentfile.path=Path importTorrentWizard.torrentfile.browse=Browse importTorrentWizard.torrentfile.invalidPath=Invalid torrent file importTorrentWizard.importfile.title=Import File Selection importTorrentWizard.importfile.message=Select the xml file to import importTorrentWizard.importfile.path=Path importTorrentWizard.importfile.browse=Browse importTorrentWizard.importfile.invalidPath=Invalid import file importTorrentWizard.finish.title=Completed importTorrentWizard.finish.message=Import completed successfully importTorrentWizard.process.inputfilebad.title=Import File Invalid importTorrentWizard.process.inputfilebad.message=A failure occurred accessing the input file: importTorrentWizard.process.outputfileexists.title=File Exists importTorrentWizard.process.outputfileexists.message=Output file exists - overwrite? importTorrentWizard.process.torrentfail.title=Torrent Write Fails importTorrentWizard.process.importfail.title=Torrent Import Fails importTorrentWizard.process.unknownfail.title=Unexpected Error ConfigView.label.bindip=Bind to local IP address or interface ConfigView.label.xfs.allocation=Allocate new files using a method specific to XFS filesystem ConfigView.label.xfs.allocation.tooltip=Please make sure /usr/sbin/xfs_io is properly installed on your system. On most Linux distributions, it's included in the "xfsprogs" package. xfs.allocation.xfs_io.not.found=XFS file allocation failed because /usr/sbin/xfs_io can't be run. Make sure it's properly installed on your system. Original error was : "%1". ConfigView.label.zeronewfiles=Allocate and zero new files on creation ConfigView.label.zeronewfiles.tooltip=Minimizes fragmentation ConfigView.section.stats=Statistics ConfigView.section.stats.enable=Enable ConfigView.section.stats.defaultsavepath=Statistics save directory ConfigView.section.stats.choosedefaultsavepath=Please choose the statistics save directory ConfigView.section.stats.savefreq=Save frequency ConfigView.section.stats.minutes=min ConfigView.section.stats.hours=hr ConfigView.section.stats.seconds=sec ConfigView.section.stats.savefile=Statistics file name ConfigView.section.stats.graph_update_dividers=Display vertical line every 60 updates MyTorrentsView.menu.export=&XML Torrent... MyTorrentsView.menu.host=&Host... ManagerItem.finishing=Finishing ConfigView.dialog.choosedefaulttorrentpath=Please choose the default torrent directory ConfigView.dialog.choosemovepath=Please choose the directory to move to ConfigView.label.movecompleted=Move completed files (after download) ConfigView.label.moveremoved=Move completed files (when being removed) ConfigView.label.savetorrents=Save .torrent files MainWindow.menu.view.mytracker=My &Tracker MainWindow.menu.view.mytracker.keybinding=Meta+2 MyTrackerView.title.full=My Tracker MyTrackerView.name=Name MyTrackerView.tracker=Tracker MyTrackerView.status=Status MyTrackerView.status.started=Running MyTrackerView.status.stopped=Stopped MyTrackerView.peers=Peers MyTrackerView.seeds=Seeds MyTrackerView.announces=Announces MyTrackerView.uploaded=Uploaded MyTrackerView.downloaded=Downloaded MyTrackerView.left=Left ConfigView.section.style=Interface ConfigView.label.set_ui_transfer_speeds=Override selectable transfer speeds ConfigView.label.set_ui_transfer_speeds.description=You can choose to manually define the default available download and upload speeds available on the status bar on the system tray.\nThe values must be comma-separated. ConfigView.label.set_ui_transfer_speeds.description.download=Set download speeds (in KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Set upload speeds (in KB/s) ConfigView.section.style.useCustomTabs=Use closeable tabs (needs restart) MainWindow.menu.view.plugins=&Plugins fileDownloadWindow.saveTorrentIn=Save Torrent File In fileDownloadWindow.title=Vuze - Torrent Downloader fileDownloadWindow.downloading=Downloading From : fileDownloadWindow.status=Status : fileDownloadWindow.state_initializing=Initializing fileDownloadWindow.state_downloading=Downloading fileDownloadWindow.state_error=Error : MainWindow.menu.file.open.url=&Location... MainWindow.menu.file.open.url.keybinding=Meta+L openUrl.title=Open Location openUrl.url=URL : MyTorrentsView.menu.host.error.title=Torrent Hosting Failed MyTorrentsView.menu.host.error.message=The following error occurred when hosting the torrent ConfigView.section.tracker=Tracker ConfigView.section.tracker.pollinterval=Tracker client poll interval (secs) ConfigView.section.tracker.publishenable=Publish torrent details to "" ConfigView.section.tracker.ip=Tracker external IP address ConfigView.section.style.enableXPStyle=Enable XP style (needs restart) IPChecker.external.service.dyndns.name=DynDNS IPChecker.external.service.dyndns.url=http://www.dyndns.org/ IPChecker.external.service.dyndns.description=Dynamic DNS Network Services, LLC ConfigView.section.tracker.checkip=Auto-discover external IP address... ipCheckerWizard.title=IP Checker Wizard ipCheckerWizard.service=Service ipCheckerWizard.chooseService=Please Choose an IP Checker Service from the services listed ipCheckerWizard.explanations=You can use this wizard to find out what your external IP address is. If your IP address is dynamic, we recommend that you open an account with a Dynamic DNS Service. Some such services are listed below, use the link provided to create an account (where supported). Then fill the IP address field with your dynamic hostname (e.g. myhostname.dyndns.org). You'll need a program to automatically update your Dynamic DNS Service with your IP address. That way, you'll be able to host torrents, even if your IP changes. ipCheckerWizard.service.description=Description : ipCheckerWizard.service.url=Link : ipCheckerWizard.progresstitle=Checking IP ipCheckerWizard.checkComplete=Completed IP : ipCheckerWizard.checkFailed=Failed, reason : wizard.tracker.local=Use Vuze Embedded Tracker wizard.tracker.external=Use an external Tracker wizard.tracker.howToLocal=\tGo to 'Tools->Options->Tracker' to enable it wizard.announceUrl=Announce URL : IPChecker.external.service.discoveryvip.name=Discoveryvip IPChecker.external.service.discoveryvip.url=http://ip.discoveryvip.com/ IPChecker.external.service.discoveryvip.description=Discoveryvip - IP address checking only IPChecker.external.httpinvalidresponse=Invalid HTTP response IPChecker.external.loadingwebpage= Loading web page IPChecker.external.analysingresponse=Analysing response IPChecker.external.addressextracted=Extracted IP address IPChecker.external.httploadfail=Failed to load page IPChecker.external.timeout=Timeout occurred IPChecker.external.ipnotfound=IP address not found ConfigView.section.tracker.pollintervalmin=Minimum ConfigView.section.tracker.pollintervalmax=Maximum ConfigView.section.tracker.pollintervalincby=Increase by ConfigView.section.tracker.pollintervalincper=Every 'n' clients splash.loadingImages=Loading Images splash.initializeGui=Initializing Main Window splash.openViews=Opening Views splash.plugin=Loading Plugin: configureWizard.nat.tooManyPorts=Too many ports to test (9 max) ConfigView.section.color=Color Scheme MyTorrentsView.menu.publish=Pub&lish... MyTrackerView.status.published=Published MyTrackerView.completed=Completed MainWindow.menu.file.open.torrentnodefault=Torrent File... (No Default Save) MainWindow.menu.file.open.torrentnodefault.keybinding.mac=Meta+Opt+O wizard.comment=Comment ConfigView.label.movetorrent=Move .torrent ConfigView.label.movepartialdownloads=Move even if some files are flagged "Do Not Download" ConfigView.label.subdir_is_in_default=When considering if downloads exist in a default directory, also consider subdirectories ConfigView.section.file.decoder.label=Default torrent encoding when selection required ConfigView.section.file.decoder.nodecoder=None IPChecker.external.service.no-ip.name=No-IP IPChecker.external.service.no-ip.url=http://www.no-ip.com/ IPChecker.external.service.no-ip.description=Dynamic and Static DNS service provider\n(no freely available 'check address' service) ConfigView.section.tracker.publicenable=Enable external torrents ConfigView.label.playdownloadspeech=Speak when a download is finished ConfigView.label.playdownloadspeech.info=Speech Services currently works best with English # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Displays the number of available copies of each piece.\nShould the number on the right be less than 1, you are not seeing one entire copy of the file (and may have trouble completing the download). GeneralView.label.trackerurl.tooltip=Click to copy the announce url to the clipboard GeneralView.label.trackerurlopen.tooltip=Click to open the tracker main page # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Update GUI every ConfigView.section.style.inactiveUpdate=Update main window every N GUI update(s) when it is not the active window ConfigView.section.style.graphicsUpdate=Update Graphical bars every N GUI update(s) ConfigView.section.style.reOrderDelay=Re Order tables every N GUI update(s) [0: never] ConfigView.section.style.reOrderDelay.never=Never ConfigView.section.logging=Logging ConfigView.section.logging.enable=Enable logging to file ConfigView.section.logging.logdir=Log file directory ConfigView.section.logging.choosedefaultsavepath=Please choose the save directory GeneralView.label.updatein.querying=Querying... configureWizard.nat.sharePort=Use a single shared incoming port for all torrents ConfigView.section.logging.maxsize=Maximum log file size ConfigView.section.tracker.passwordenableweb=Enable password on tracker web ConfigView.section.tracker.passwordenabletorrent=Enable password on torrents ConfigView.section.tracker.username=User name ConfigView.section.tracker.password=Password columnChooser.title=Choose the columns to display columnChooser.move=Drag rows to re-order them columnChooser.apply=Apply columnChooser.columnname=Column Name columnChooser.columndescription=Description TableColumn.header.shareRatio=Share Ratio MyTorrentsView.menu.editTableColumns=&Column Setup wizard.operationfailed=Operation failed authenticator.title=Authentication Required authenticator.realm=Realm authenticator.tracker=Tracker authenticator.user=User name authenticator.password=Password ConfigView.label.allowSendVersion=Allow Vuze to send anonymous version number and random id while checking for new version ConfigView.label.version.info.link=Visit here for details on what data is sent to the version check server wizard.hint.mode=Hint:\tYou can Drag and Drop a single file or directory on this wizard\n\tto choose a file or directory wizard.hint.file=Hint:\tYou can choose a single file with Drag and Drop wizard.hint.directory=Hint:\tYou can choose a single directory with Drag and Drop MainWindow.menu.help.checkupdate=&Check for Updates... TableColumn.header.down=Downloaded TableColumn.header.up=Uploaded ConfigView.section.tracker.passwordenabletorrent.info=Requires suitable BitTorrent client (e.g. Vuze) ConfigView.section.style.confirmationOnExit=Show confirmation dialog on exit MainWindow.dialog.exitconfirmation.title=Exit Vuze MainWindow.dialog.exitconfirmation.text=Do you really want to exit Vuze SystemTray.menu.stopalltransfers=Stop &All Transfers TrayWindow.menu.stopalldownloads=Stop &All Downloads ConfigView.section.tracker.sslport.info=See the FAQ for further information wizard.tracker.ssl=Use SSL ConfigView.label.playdownloadfinished=Play a sound when a download is finished ConfigView.label.popupdownloadfinished=Popup an alert when a download is finished ConfigView.label.popupfilefinished=Popup an alert when a file is finished TableColumn.header.pieces=Pieces TableColumn.header.pieces.info=Graphical bar representing which pieces you have downloaded TableColumn.header.completion=Completion TableColumn.header.completion.info=Graphical representation of % downloaded ConfigView.section.style.showdownloadbasket=Show Download Basket (Drag and Drop .torrents) ConfigView.section.style.alwaysShowTorrentFiles=Always show Torrent files in Details/Files wizard.multitracker=Add Multi-Tracker information to the torrent wizard.multitracker.title=Multi-Tracker wizard.multitracker.configuration=Multi-Tracker Configuration wizard.multitracker.new=New... wizard.multitracker.edit=Edit... wizard.multitracker.delete=Delete wizard.multitracker.group=Tracker Group wizard.multitracker.edit.title=Multi-Tracker Editor wizard.multitracker.edit.name=Name wizard.multitracker.edit.save=Save wizard.multitracker.edit.newgroup=New Group wizard.multitracker.edit.deletegroup=Delete wizard.multitracker.edit.newtracker=New Tracker wizard.multitracker.edit.deletetracker=Delete wizard.multitracker.edit.edit=Edit wizard.addingmt=Adding Multi-Tracker info wizard.multitracker.noannounce=Announce URL isn't present in your trackers list MyTorrentsView.menu.recheck=Force Re-chec&k iconBar.showDownloadBar.tooltip=Show Download Bar iconBar.start.tooltip=Start selected torrent(s) iconBar.stop.tooltip=Stop selected torrent(s) iconBar.remove.tooltip=Remove selected torrent(s) iconBar.openNoDefault.tooltip=Open a .torrent file (no default save) iconBar.openURL.tooltip=Open an URL iconBar.openFolder.tooltip=Open a Folder iconBar.new.tooltip=Create a torrent iconBar.up.tooltip=Move up iconBar.down.tooltip=Move Down iconBar.run.tooltip=Open using default application iconBar.host.tooltip=Host iconBar.publish.tooltip=Publish iconBar.editcolumns.tooltip=Column Setup MyTorrentsView.menu.editTracker=&Edit Tracker URL(s) GeneralView.menu.selectTracker=Select ConfigView.section.stats.xslfile=XSL file name ConfigView.section.stats.xslfiledetails=This will be included in stats file header via tag ConfigView.label.savetorrentbackup=Save Backup ConfigView.section.tracker.forceport=Force hosted external torrents to default port ConfigView.section.ipfilter.allow=ALLOW these ranges (default is DENY) ConfigView.section.ipfilter.list.inrange=was in range ConfigView.section.ipfilter.list.notinrange=was not in any range ConfigView.section.ipfilter.list.title=Blocked IPs ConfigView.label.allowsameip=Allow multiple connections from the same IP ConfigView.label.allowsameip.tooltip=Only check if you NEED it.\nThis is a leecher protection (when disabled). ManagerItem.superseeding=Super-Seeding ConfigView.label.userSuperSeeding=Use Super Seeding PeersView.uniquepiece=Piece (Super-Seed Mode) PeersView.uniquepiece.none=None PeersView.timetosend=Time to resend Piece (Super-Seed Mode) ConfigView.section.style.addurlsilently=Open passed URLs silently ConfigView.section.style.addurlsilently.tooltip=Automatically download passed/dropped .torrent URLs without opening prompt dialog box. ConfigView.section.file.decoder.prompt=Always prompt when encoding choice available ConfigView.section.file.decoder.prompt.tooltip=Always show dialog when encoding choice is available MyTorrentsView.menu.moveTop=&Top MyTorrentsView.menu.moveEnd=&Bottom ConfigView.label.moveonlyusingdefaultsave=only if in default data dir ConfigView.label.moveonlyusingdefaultsave.tooltip=Move only if downloaded data is in the default data dir ConfigView.label.watchtorrentfolder=Import new .torrents automatically ConfigView.label.watchtorrentfolder.tooltip=Looks for new .torrents regularly ConfigView.label.watchtorrentfolderinterval=Interval ConfigView.label.watchtorrentfolderinterval.tooltip=The pause until the folder will be scanned again ConfigView.dialog.choosewatchtorrentfolderpath=Please choose the .torrent import directory ConfigView.label.startwatchedtorrentsstopped=Begin stopped ConfigView.label.startwatchedtorrentsstopped.tooltip=Add new .torrents in STOPPED state ConfigView.section.plugins=Plugins wizard.maketorrent.filesize=File(s) Size wizard.maketorrent.piececount=Piece Count wizard.maketorrent.piecesize=Piece Size wizard.maketorrent.auto=Auto MainWindow.menu.view.stats=&Statistics MainWindow.menu.view.stats.keybinding=Meta+5 SpeedView.title.full=Activity SpeedView.downloadSpeed.title=Download Speed SpeedView.uploadSpeed.title=Upload Speed ConfigView.section.style.useSIUnits=Use IEC Units (KB -> KiB etc.) iconBar.top.tooltip=Move to top iconBar.bottom.tooltip=Move to bottom TableColumn.header.health=Health MyTorrentsView.menu.health=About Health health.explain.grey=means that your torrent is not running (downloading or uploading) health.explain.red=means that you're not connected to any peer while downloading health.explain.blue=when seeding, it means that you're not yet connected to any peer\nwhen downloading, it means that you are connected to some peers but the tracker is down health.explain.yellow=means that the tracker is ok, you're connected to peers, but you don't have any remote connection.\nYou may have a NAT problem if your torrents stay on yellow status all the time health.explain.green=means that everything is going fine. ConfigView.section.style.alwaysRefreshMyTorrents=Always refresh My Torrents ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=This option will refresh the My Torrents view even if not displayed (useful for some mirc plugins) # #2.0.7.0 # security.certtruster.title=Security Certificate Warning security.certtruster.intro=The security certificate was issued by a company you do not trust security.certtruster.resource=Resource: security.certtruster.issuedto=Issued To: security.certtruster.issuedby=Issued By: security.certtruster.prompt=Do you want to trust it? security.certtruster.yes=Yes security.certtruster.no=No ConfigView.section.tracker.torrentsperpage=How many torrents per page ? [0: unlimited] MainWindow.menu.file.share=Classic-&Share MainWindow.menu.file.share.file=&File... MainWindow.menu.file.share.dir=F&older... MainWindow.menu.file.share.dircontents=Folder &Contents... MainWindow.menu.file.share.dircontentsrecursive=Folder Contents... (&Recursive) MainWindow.dialog.share.sharefile=Select File To Share MainWindow.dialog.share.sharedir=Select Folder To Share MainWindow.dialog.share.sharedircontents=Select Folder Contents To Share MainWindow.dialog.share.sharedircontents.recursive=Recursive globalmanager.download.remove.veto=Removal Action Vetoed plugin.sharing.download.remove.veto=This download is the result of a resource being classically-shared.\nTo remove the download remove the associated classic-share: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Main ConfigView.section.tracker.web=Web ConfigView.label.prioritizefirstpiece=Prioritize first and last piece of file(s) ConfigView.label.prioritizefirstpiece.tooltip=Attempts to download the very beginning and very end of a file first.\nFor support of early previewing. ConfigView.section.file.confirm_data_delete=Confirm when deleting data ConfigView.section.file.confirm_data_delete.tooltip=Confirm data deletion when using 'Remove and Delete...' ConfigView.section.file.delete.include_files_outside_save_dir=When deleting data, allow files linked outside torrent save directory to be removed also TrayWindow.menu.startalldownloads=Start All Downloads SystemTray.menu.startalltransfers=Start All Transfers sharing.progress.title=Classic-Sharing Progress sharing.progress.hide=Hide MainWindow.menu.view.myshares=My Classic-Shares MainWindow.menu.view.myshares.keybinding=Meta+3 MySharesView.title.full=My Classic Shares MySharesView.name=Name MySharesView.type=Type MySharesView.type.file=File MySharesView.type.dir=Directory MySharesView.type.dircontents=Directory contents MySharesView.type.dircontentsrecursive=Directory contents (recursive) MySharesView.menu.remove=Remove ConfigView.section.tracker.extensions=Extensions ConfigView.section.tracker.sendpeerids=Send peer identity to downloaders ConfigView.section.tracker.enableudp=Enable UDP tracker protocol plugin.sharing.torrent.remove.veto=This tracker registration is the result of a resource being classically-shared.\nTo remove the download remove the associated classic-share: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Download can't be removed as it is not stopped plugin.sharing.remove.veto=This classic-share is a sub-share of a 'directory contents' share and can't be explicitly deleted.\n Delete the root classic-share GeneralView.label.hash.tooltip=Click to copy the hash to the clipboard ConfigView.section.tracker.maxpeersreturned=Maximum peers returned [0: unlimited] ConfigView.label.serverport=Incoming TCP / UDP listen port ConfigView.label.serverport.tooltip=Port must within 1-65535 range, and not 6880 as that is reserved for internal Vuze use. configureWizard.nat.server.tcp_listen_port=Incoming TCP Listen Port ConfigView.section.sharing=Classic-Sharing ConfigView.section.sharing.usessl=Use SSL for classic-shared resources (requires Tracker configuration) ConfigView.section.style.dropdiraction=Drag and Drop action for directories ConfigView.section.style.dropdiraction.opentorrents=Open Torrents ConfigView.section.style.dropdiraction.sharefolder=Classically-Share Directory ConfigView.section.style.dropdiraction.sharefoldercontents=Classically-Share Contents # # 2.0.7.x # Categories.all=All Categories.uncategorized=Uncategorized CategoryAddWindow.message=Enter a new category name CategoryAddWindow.title=Add New Category ConfigView.label.autoSeedingIgnoreInfo=Ignored torrents go to the bottom of the seeding queue. They do not get automatically started.\nIgnore rules do not apply to torrents that match the First Priority criteria.\nUnless otherwise stated, use a value of 0 to disable a rule. ConfigView.label.directory=Directory ConfigView.label.disconnetseed.tooltip=When seeding a torrent, disconnect any clients that are also seeding.\nThey don't need to be talking to you. ConfigView.label.ignoreCase=Ignore Case ConfigView.label.ignoreSeeds=Ignore torrents with at least ConfigView.label.importdirectory=Import Directory ConfigView.label.minPeersToBoostNoSeeds.tooltip=Any torrents with no seeds and having less peers than you specify\nwill be moved towards the bottom of the queue. ConfigView.label.minPeersToBoostNoSeeds=Lower Seeding Rank for torrents with no seeds and less than ConfigView.label.minSeedingTime.tooltip=Seeding Ranks can fluctuate often in a short period time, sometimes causing the torrent to automatically start, only to be stopped & queued immediately afterwards.\nThis alleviates the problem by forcing the torrent to stay seeding for a given period of time. You can still stop it manually if you want. ConfigView.label.minSeedingTime=Minimum seeding time in seconds ConfigView.label.minSpeedForActiveDL.tooltip=A download slot is always used for the initial 30 seconds\nafter the incomplete torrent starts. ConfigView.label.minSpeedForActiveDL=Don't count torrent as using a download slot if speed is below ConfigView.label.peers=peers ConfigView.label.queue.debuglog=Log debug information ConfigView.label.queue.debuglog.info=Adds queue debug info to the console/log file.\nAlthough cryptic, the debug info tells you the state of the torrents and why they are/aren't starting/queueing. ConfigView.label.queue.minQueueingShareRatio=Don't queue or stop torrent until its share ratio reaches ConfigView.label.ratio=ratio ConfigView.label.removeOnStop=Remove torrent from list after it automatically stops ConfigView.label.savedirectory=Save Directory ConfigView.label.seeding.autoReposition.tooltip=If enabled, the order of the torrents (the '#' column) will be altered to match that of the Seeding Rank\nThis is usefully if you don't like seeing the Seeding Rank numbers, but still want to know the order that the completed torrents will start in. ConfigView.label.seeding.autoReposition=Automatically reposition torrents based on Seeding Rank ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Often, torrents with low seed counts and high peer counts means that there probably isn't a full copy amongst the peers.\nTherefore, you may not want the seeding rules pretending there's a full copy (and thus incorrectly reducing its rank) ConfigView.label.seeding.fakeFullCopySeedStart=but only for torrents with at least ConfigView.label.seeding.ignore=Ignore Rules ConfigView.label.seeding.ignore0Peers=Ignore torrents with 0 peers ConfigView.label.seeding.ignoreRatioPeers=Ignore torrents that have at least 1 seed for every ConfigView.label.seeding.ignoreShareRatio=Ignore torrents that have a share ratio of ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignore torrent even if\nFirst Priority rules apply ConfigView.label.seeding.ignore.header.rule=Rule ConfigView.label.seeding.ignore.header.value=Value ConfigView.label.seeding.firstPriority.info=First Priority torrents will always be at the top of the queue.\nAny torrents matching the First Priority criteria will not be automatically stopped and queued.\nA torrent matching First Priority criteria will take a Simultaneous Download slot if it needs to. ConfigView.label.seeding.firstPriority.FP=First Priority ConfigView.label.seeding.firstPriority=First priority goes to torrents with ConfigView.label.seeding.firstPriority.following=of the following: ConfigView.label.seeding.firstPriority.shareRatio=A share ratio under ConfigView.label.seeding.firstPriority.seedingMinutes=An elapsed time since changing from downloading to seeding ConfigView.label.seeding.firstPriority.DLMinutes=An elapsed time since the start of downloading ConfigView.label.seeding.numPeersAsFullCopy.tooltip=By pretending there is 1 full copy per X peers, you reduce the rank of torrents with high peer counts.\nMost likely, torrents with high peer counts also have high traffic.\nThis does not change any '# of seeds' displays. ConfigView.label.seeding.numPeersAsFullCopy=Pretend there's 1 full copy for every\n(0 : No Pretending) ConfigView.label.seeding.preferLargerSwarms.tooltip=If you are mainly seeding torrents with peers that are "stuck", preferring larger swarms makes sense\nWhen you are mainly seeding torrents with high availability, preferring smaller swarms makes sense. ConfigView.label.seeding.preferLargerSwarms=When torrents have the same rank, prefer larger swarms ConfigView.label.seeding.rankType.none.tooltip=Order based on # column ConfigView.label.seeding.rankType.none=None ConfigView.label.seeding.rankType.peer.tooltip=more peers and fewer seeds = higher rank\nThis ranking minimizes the number of torrents that need to be kept active to maximize the upload ConfigView.label.seeding.rankType.peer=Weighted Peer Count ConfigView.label.seeding.rankType.peerSeed.options=Peers:Seeds Ratio Options ConfigView.label.seeding.rankType.peerSeed.tooltip=Higher Ratio = Higher Rank ConfigView.label.seeding.rankType.peerSeed=Peers:Seed Ratio ConfigView.label.seeding.rankType.seed.fallback=Fallback to Peers:Seed Ratio after\n(0 : Never Fallback) ConfigView.label.seeding.rankType.seed.options=Seed Count Only Options ConfigView.label.seeding.rankType.seed.tooltip=Less Seeds = Higher Rank ConfigView.label.seeding.rankType.seed=Seed Count Only ConfigView.label.seeding.rankType.timedRotation.tooltip=All queued completed torrents will rotate into seeding mode.\nDuration of seeding time is set by 'Minimum Seeding Time' ConfigView.label.seeding.rankType.timedRotation=Timed Rotation ConfigView.label.seeding.rankType.tooltip=Highest ranked torrents are automatically started.\nWhen another torrent gets a higher ranking, the lower ranking one stops and goes back into the queue.\n\nOnly torrents in a Queued state are available for automatic starting.\nStopped torrents are never automatically started. ConfigView.label.seeding.rankType=Rank completed torrents for auto-starting based on: ConfigView.label.stopAfterMinutes=Once switched to seeding, stop after a duration of time ConfigView.label.switchpriority.tooltip=Low priority reduces the amount of upload bandwidth allotted to the torrent. ConfigView.pluginlist.info=The following plugins have been identified. Some plugins may not have configuration tabs. ConfigView.pluginlist.noplugins=No plugins have been found. ConfigView.section.pluginslist=List ConfigView.section.queue.seeding=Seeding ConfigView.section.queue.seeding.autoStarting=Auto Starting ConfigView.section.queue.seeding.ignore=Ignore Rules ConfigView.section.queue.seeding.firstPriority=First Priority ConfigView.section.queue.main=Main ConfigView.section.queue=Queue ConfigView.section.torrents=Torrents ConfigView.text.all=all ConfigView.text.hours=hours ConfigView.text.ignoreRule=Ignore Rule ConfigView.text.ignore=Ignore ConfigView.text.minutes=minutes ConfigView.text.neverIgnore=Never Ignore ConfigView.text.any=any DownloadManager.error.datamissing=Data Missing MainWindow.menu.file.open.torrentforseeding=Torrent File... (For Seeding) MainWindow.menu.language.refresh=&Refresh ManagerItem.forced=Forced ManagerItem.queued=Queued MySeedersView.header=Complete Torrents TableColumn.header.availability.info=# full copies being seen TableColumn.header.availability=Availability TableColumn.header.category=Category MyTorrentsView.header=Incomplete Torrents TableColumn.header.maxuploads=Max # Uploads MyTorrentsView.menu.category.delete=&Delete Category MyTorrentsView.menu.forceStart=&Force Start MyTorrentsView.menu.queue=&Queue MyTorrentsView.menu.setCategory.add=&Add Category... MyTorrentsView.menu.setCategory=Assign Category TableColumn.header.savepath=Save Path TableColumn.header.SeedingRank=Seeding Rank TableColumn.header.totalspeed.info=Total Speed of all peers you are connected to TableColumn.header.totalspeed=Total Speed splash.initializePlugins=Initializing Plugins StartStopRules.SPratioMet=S:P Ratio OK StartStopRules.FP0Peers=FP / 0 Peers StartStopRules.0Peers=0 Peers StartStopRules.numSeedsMet=# Seeds OK StartStopRules.ratioMet=Peers:Seed OK StartStopRules.shareRatioMet=Share Ratio OK StartStopRules.waiting=Waiting StartStopRules.firstPriority=1st Priority ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Classically-Share Contents (Recursive) DownloadManager.error.unabletostartserver=Unable to Start Server - check incoming port configuration / firewall permissions for application to act as server GeneralView.label.creationdate=Created On : ConfigView.section.tracker.announcescrapepercentage=Scrape interval as %age of announce\ne.g. 200 = 2:1. 0 = let peer decide ManagerItem.stopping=Stopping ConfigView.section.tracker.announcecacheperiod=Announce cache (millis) ConfigView.section.tracker.scrapecacheperiod=Scrape cache (millis) ConfigView.section.tracker.scrapeandcache=Scrape and cache ConfigView.section.tracker.announcecacheminpeers=Announce cache enable peer threshold MyTrackerView.scrapes=Scrapes fileDownloadWindow.retry=Retry MyTrackerView.bytesin=Bytes In MyTrackerView.bytesinave=Ave In MyTrackerView.bytesout=Bytes Out MyTrackerView.bytesoutave=Ave Out ConfigView.section.file.max_open_files=Maximum files opened for read/write\n[0: unlimited] ConfigView.section.file.max_open_files.tooltip=Useful if you download torrents with hundreds/thousands of files in them, and you if you're reaching file handle limits of the OS. ConfigView.section.proxy=Proxy ConfigView.section.proxy.enable_proxy=Enable proxying of tracker communications [restart required] ConfigView.section.proxy.host=Host ConfigView.section.proxy.port=Port ConfigView.section.proxy.username=Username ConfigView.section.proxy.password=Password ConfigView.section.proxy.enable_socks=I have a SOCKS proxy wizard.createtorrent.extrahashes=Add hashes for other networks (e.g. Gnutella2, eDonkey2000) GeneralView.label.connected=connected GeneralView.label.in_swarm=in swarm ManagerItem.initializing=Initializing AlertMessageBox.error=Error AlertMessageBox.warning=Warning AlertMessageBox.comment=Comment AlertMessageBox.information=Information AlertMessageBox.unread=You have unread alert messages - click here to display them. SharedPortServer.alert.selectorfailed=Failed to establish listener for incoming data.\nCheck firewall settings are permitting java(w).exe to act as a 'server' Tracker.alert.listenfail=Failed to establish listen on port %1.\nCheck that other applications aren't already using this port.\nAlso check for another copy of Vuze running. DiskManager.alert.movefileexists=Error moving completed files\nFile %1 already exists in MoveTo destination dir DiskManager.alert.movefilefails=Error moving completed files\nMove of file %1 failed, %2 DiskManager.alert.movefilerecoveryfails=Error recovering after move failed\nRestore of file %1 failed, %2 ConfigView.section.tracker.logenable=Log periodic statistics to 'tracker.log' SpeedView.stats.title=Stats SpeedView.stats.total=Total SpeedView.stats.session=This Session SpeedView.stats.session.tooltip=Total (Protocol) SpeedView.stats.downloaded=Downloaded (Protocol) SpeedView.stats.uploaded=Uploaded (Protocol) SpeedView.stats.ratio=Ratio SpeedView.stats.uptime=Up Time SpeedView.stats.now=Now SpeedView.stats.now.tooltip=Total (Protocol) AutoMigration.useralert=Vuze user config files/dirs auto-migration results:\n\n%1\nAny failures must be migrated manually.\nDON'T FORGET TO UPDATE YOUR SAVE PATHS IN CONFIGURATION IF THEY'VE BEEN MIGRATED! # # > 2.0.8.0 # OpenTorrentWindow.title=Open Torrent(s) OpenTorrentWindow.message=Experimental OpenTorrentWindow.addFiles=&Add Files OpenTorrentWindow.dataLocation=Location to save data: OpenTorrentWindow.startMode=Add Mode OpenTorrentWindow.startMode.queued=Queued OpenTorrentWindow.startMode.stopped=Stopped OpenTorrentWindow.startMode.forceStarted=Force Started OpenTorrentWindow.addPosition=Queue Position OpenTorrentWindow.addPosition.first=First OpenTorrentWindow.addPosition.last=Last TableColumn.header.remaining.info=Amount remaining to download TableColumn.header.remaining=Remaining ConfigView.section.tracker.enablecompact=Enable compact announce protocol ConfigView.section.tracker.enablekey=Enable key passing to tracker for enhanced security ConfigView.section.file.perf=Performance Options ConfigView.section.file.perf.explain=Warning - unqualified changes to these parameters may adversely affect download performance. Restart required.\nIf you have "out of memory" problems consider limiting connections per torrent (See Transfer config) ConfigView.section.file.max_open_files.explain=Opening too many files can cause operating system problems due to limited resources such as file handles. This limits the number of concurrently opened files. popup.error.hide=Hide popup.error.details=Details ConfigView.section.style.colorOverrides=Color Overrides ConfigView.section.style.colorOverride.progressBar=Progress Bar ConfigView.section.style.colorOverride.error=Error MainWindow.status.tooOld=is old, please update it. ConfigView.section.style.colorOverride.warning=Warning ConfigView.section.style.colorOverride.altRow=Alternate Rows ConfigView.section.file.save.peers.enable=Save peer connections for quick reconnects ConfigView.section.file.save.peers.max=Maximum peers to save [0: unlimited] ConfigView.section.file.save.peers.pertorrent=per torrent ConfigView.label.max_peers_per_torrent=Max connections per torrent default [0: unlimited] ConfigView.label.max_peers_total=Max connections globally [0: unlimited] ConfigView.section.style.colorOverrides.reset=Reset Color ConfigView.section.language.info=When enabled, an update check will occur every time Vuze starts. ConfigView.section.language.enableUpdate=Enable Web Update ConfigView.section.language.UpdateURL=Update URL ConfigView.section.language.UpdateNow=Update Now! Button.revert=Revert MyTorrentsView.menu.changeDirectory=Change Data Directory GenericText.column=column MyTorrentsView.menu.thisColumn.remove=Remove Column MyTorrentsView.menu.thisColumn.toClipboard=Copy Text To Clipboard MyTorrentsView.menu.thisColumn.autoTooltip=Always display tooltip MyTorrentsView.menu.tracker=Tracker/Torrent ConfigView.download.abbreviated=D: ConfigView.upload.abbreviated=U: ConfigView.complete.abbreviated=C: TableColumn.header.secondsseeding=Seeding For TableColumn.header.secondsseeding.info=Total amount of time you have been seeding. TableColumn.header.secondsdownloading=DLing For TableColumn.header.secondsdownloading.info=Amount of time you have been downloading. ConfigView.section.tracker.udpversion=UDP Protocol Version (1 or 2) window.updateswt.title=Your SWT Version is too old! window.updateswt.text=Your SWT Version is too old!\nSWT is the graphic library used by Vuze and the version you have is too old to run the latest Vuze version. Click the OK button to update your SWT. window.updateswt.status=Status window.updateswt.failed=Update failed, press OK again to restart. window.updateswt.status.downloading.updater=Downloading the Updater Module window.updateswt.status.finding=Finding latest SWT Version window.updateswt.status.downloading=Downloading Latest SWT Version window.updateswt.status.done=Restarting window.updateswt.ok=OK window.updateswt.cancel=Cancel swt.updater.downloader.downloading=Downloading SWT from swt.updater.urlsgetter.downloading=Getting a list of mirrors from swt.updater.urlsgetter.platform=SWT for platform : window.updateswt.ignore=Ignore ConfigView.section.style.useFancyTabs=Use Fancy Tabs splash.initializeGM=Initializing Global Torrent Manager splash.loadingTorrents=Loading Torrents splash.firstMessageNoI18N=(: Vuze :) MyTorrentsView.menu.thisColumn.sort=&Sort Scrape.status.ok=Scrape OK Scrape.status.error=Scrape Error: Scrape.status.error.badURL=Announce URL doesn't follow scrape specifications. Scrape.status.error.nohash=Hash missing from reply. Scrape.status.error.invalid=Invalid reply. Scrape.status.nextScrapeAt=Next scrape at %1 Scrape.status.scraping=Scraping... Scrape.status.initializing=Waiting to scrape... Scrape.status.scraping.queued=Scraping queued... ConfigView.label.minSpeedForActiveSeeding=Don't count completed torrent as using a slot if speed is below ConfigView.section.stats.exportpeers=Export peer details MainWindow.menu.view.irc.moved=Irc is now available as a plugin, see http://azureus.sourceforge.net/plugin_list.php. When installed use the view->plugins->IRC menu to access it. MyTrackerView.webui.contextmenu.copyurl=Copy torrent URL to clipboard ConfigView.section.file.torrent.ignorefiles=Files to ignore when creating/deleting torrents\n - e.g. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignoring file ConfigView.section.style.useUnitsRateBits=Use bits instead of bytes for byte-based rate values (KiB/s->Kibit/s etc.) ConfigView.section.interface.resetassoc=Reset explorer file associations (.torrent) ConfigView.section.interface.resetassocbutton=Reset ConfigView.section.interface.checkassoc=Check associations on startup dialog.associations.title=Association Check Button.yes=&Yes Button.no=&No ConfigView.label.seeding.autoStart0Peers=Auto Start all completed torrents with 0 peers ConfigView.label.seeding.autoStart0Peers.tooltip=Turn on if you want the tracker to always list seeds for 0 peer torrents. dialog.associations.prompt=Vuze isn't the default application for BitTorrent files.\nWould you like to associate .torrent files with Vuze dialog.associations.askagain=Check on startup ConfigView.section.plugins.update=Plugin Update Plugin.pluginupdate.enablecheck=Enable plugin update checking plugins.basicview.status=Status: plugins.basicview.activity=Activity: plugins.basicview.progress=Progress: plugins.basicview.log=Log: ConfigView.label.maxdownloadspeed=KB/s global max download speed [0: unlimited] splash.loadingTorrent=Loading Torrent splash.of =of ConfigView.section.plugins.irc=IRC UpdateWindow.title=Vuze Updater UpdateWindow.header=The following components need an update : UpdateWindow.columns.install=Install UpdateWindow.columns.name=Name UpdateWindow.columns.version=Version UpdateWindow.columns.size=Size UpdateWindow.cancel=Cancel UpdateWindow.quit=Quit UpdateWindow.close=Close UpdateWindow.ok=Update UpdateWindow.restart=Restart Vuze Now UpdateWindow.status.downloading=Downloading UpdateWindow.status.done=Done UpdateWindow.status.failed=Failed UpdateWindow.status.restartNeeded=Restart will be required! ConfigView.pluginlist.broken=Broken ConfigView.pluginlist.whereToPut=Place any user-specific plugins in their own directory under: ConfigView.pluginlist.whereToPutOr=For shared plugins use: MainWindow.statusText.checking=Checking for Updates TableColumn.header.OnlyCDing4=OnlyCDing4 TableColumn.header.OnlyCDing4.info=Amount of time the torrent has been only seeding. Excludes the time the torrent was downloading (and seeding). ConfigView.section.style.alternateTablePainting=Use alternate method to paint graphic table columns (may require a restart) UpdateWindow.status.restartMaybeNeeded=Restart may be required ConfigView.pluginlist.shared=shared PeersView.host=Host Name PeersView.host.info=The host name of the peer, where available (may affect performance) MainWindow.menu.help.whatsnew=What's New ConfigView.label.checkonstart=Check for latest version when Vuze starts ConfigView.label.periodiccheck=Check for latest version periodically ConfigView.label.opendialog=Automatically open the Update Assistant when an update is available MainWindow.updateavail=Click here for updates MainWindow.status.unofficialversion=Vuze Beta MainWindow.status.latestversionunchecked=Version checking disabled GeneralView.label.updatein.stopped=Stopped StartStopRules.menu.viewDebug=View Debug Info ConfigView.section.style.doNotUseGB=Do not use GB unit ConfigView.section.style.doNotUseGB.tooltip=If checked, Vuze will continue to use MB even for sizes greater than 1024MB MainWindow.menu.help.plugins=Get Plugins ConfigView.section.plugins.TrackerWeb=Tracker Web ConfigView.section.tracker.enablecategories=Separate torrents by category health.explain.share=means that the torrent is either hosted or published ConfigView.section.tracker.createcert=Create self-signed certificate ConfigView.section.tracker.createbutton=Create security.certcreate.title=Create Self-Signed Certificate security.certcreate.intro=This dialog lets you create a self-signed certificate security.certcreate.alias=Alias security.certcreate.strength=Strength security.certcreate.firstlastname=First and last name security.certcreate.orgunit=Organisational Unit security.certcreate.org=Organisation security.certcreate.city=City or Locality security.certcreate.state=State or Province security.certcreate.country=Two-letter country code security.certcreate.ok=Create security.certcreate.cancel=Cancel security.certcreate.createok=Certificate created successfully security.certcreate.createfail=Certificate creation failed ConfigView.section.plugins.webui=Swing Web Interface ConfigView.section.plugins.xml_http_if=XML/HTTP Interface webui.passwordenable=Enable password webui.user=User name webui.password=Password webui.port=Port (*) webui.protocol=Protocol (*) webui.homepage=Home page (*) webui.rootdir=Root directory (*) webui.rootres=Root resource (*) webui.mode=Mode (*) webui.mode.info=Mode can be\n\t"full"\t= all operations available (default)\n\t"view"\t= view only (but can update refresh frequency) webui.access=Access (*) webui.access.info=Access can be\n\t\"local"\t= meaning only the local machine can connect\n\t"all"\t= unrestricted access (default)\n\tIP\t= e.g. 192.168.0.2\t\t\tone IP only\n\tIP1-IP2\t= e.g. 192.168.0.1-192.168.0.255\tinclusive range of IPs GeneralView.label.maxdownloadspeed=Down Limit Security.keystore.corrupt=Keystore '%1' failed to load, please delete it and recreate/re-import the certificates Security.keystore.empty=Keystore is empty. Please create a self-signed certificate (see Tools->Options->Security) or import an existing certificate into '%1' webui.restart.info=Changes to parameters marked with a (*) require a restart to take effect GeneralView.label.maxdownloadspeed.tooltip=max download speed [0: unlimited] ConfigView.section.UPnP=UPnP upnp.enable=Enable UPnP upnp.info=Universal Plug and Play (UPnP) allows the automatic mapping of ports on UPnP enabled routers. upnp.mapping.dataport=Incoming Peer Data Port upnp.mapping.tcptrackerport=TCP Tracker Port upnp.mapping.udptrackerport=UDP Tracker Port upnp.alert.differenthost=UPnP: Mapping '%1' has been reserved by '%2' - please select a different port upnp.alert.mappingok=UPnP: Mapping '%1' established upnp.alert.mappingfailed=UPnP: Mapping '%1' failed upnp.alertsuccess=Report successful mappings upnp.alert.lostdevice=UPnP: Lost connection to service '%1' on UPnP device '%2' upnp.grabports=Map ports even if owned by another computer upnp.refresh.label=Refresh the mappings upnp.refresh.button=Refresh upnp.alert.mappinggrabbed=UPnP: Mapping '%1' established - grabbed from '%2' upnp.mapping.tcpssltrackerport=TCP SSL Tracker Port upnp.alertothermappings=Report ports owned by other computers upnp.alertdeviceproblems=Report problems with the UPnP device upnp.trace_to_log=Output full debug information to log upnp.wiki_link=Vuze Wiki page on UPnP upnp.refresh_mappings_on_bad_nat=Automatically refresh mappings when NAT status is "firewalled" blank.resource= ConfigView.pluginlist.coreplugins=The following built-in plugins are loaded: Peers.column.DLedFromOthers=From Others Peers.column.DLedFromOthers.info=Amount of data downloaded from others while connected to you Peers.column.UpDownRatio=Up:Down Peers.column.UpDownRatio.info=Peer's "Uploaded : Downloaded" Ratio Peers.column.UpRatio=Up Ratio Peers.column.UpRatio.info=Peer's "Upload from you : Uploaded from other" ratio upnp.releasemappings=Release mappings on closedown webui.upnpenable=Enable UPnP for this port (*) ConfigView.section.file.friendly.hashchecking=Friendly hash checking ConfigView.section.file.friendly.hashchecking.tooltip=A slightly slower, but much less stressful on cpu/system, piece hashchecking mode. ConfigView.section.tracker.seedretention=Max seeds retained per torrent [0: unlimited] ConfigView.section.tracker.seedretention.info=Note: Upload statistics will be lost for non-retained seeds ConfigView.section.tracker.port=Enable tracker on HTTP port ConfigView.section.tracker.sslport=Enable tracker on HTTPS port ConfigView.section.tracker.publicenable.info=This permits others to create torrents that use your tracker\nwithout you hosting/publishing them Button.clear=Clear MainWindow.IPs.tooltip=Last update of filter list: %1\nTotal IPFilters in list - Number of blocked/banned/bad IPs this session.\nDouble-click for details. ConfigView.section.ipfilter.list.banned=has been banned ConfigView.section.ipfilter.list.baddata=has sent bad data: occurrences = Button.reset=Reset ConfigView.section.ipfilter.bannedinfo=IPs that have sent bad data - banned if limits exceeded ConfigView.section.ipfilter.blockedinfo=IPs that have been blocked due to IP filters download.removerules.name=Removal Rules download.removerules.unauthorised.info=Unauthorized torrents are those where the announce response contains either "not authoris(z)ed" or "unauthoris(z)ed" in the "failure response" download.removerules.unauthorised=Automatically remove unauthorized torrents download.removerules.unauthorised.seedingonly=\tOnly if seeding download.removerules.removed.ok=Automatic removal of torrent '%1' succeeded. This was caused by the torrent removal rules. download.removerules.updatetorrents=Remove Vuze update torrents as the swarm requires ConfigView.label.defaultstarttorrentsstopped=By default add new torrents in a stopped state ConfigView.section.server.enableudp=Enable UDP tracker client protocol upnp.mapping.dataportudp=UDP tracker client port ConfigView.section.file.decoder.showlax=Show less likely encodings ConfigView.section.file.decoder.showall=Consider all possible encodings MainWindow.status.updowndetails.tooltip=Download/Upload speed details\nRight-click to change, Double-Click to open statistics TrackerClient.announce.warningmessage=Tracker for '%1' returned warning '%2' ConfigView.section.tracker.natcheckenable=Check 'incoming data port' connectability and report failures to peers ConfigView.section.tracker.publishenabledetails=Publish all torrent details ConfigView.section.tracker.publishenablepeerdetails=Publish peer details MyTrackerView.badnat=Bad NAT MyTrackerView.badnat.info=Seeds/Peers that have failed a NAT check, if enabled ConfigView.section.tracker.natchecktimeout=Check timeout (secs) ConfigView.section.file.perf.cache.enable=Enable disk cache ConfigView.section.file.perf.cache.size=Size of cache in %1 MainWindow.menu.transfers=T&ransfers MainWindow.menu.transfers.startalltransfers=St&art All MainWindow.menu.transfers.stopalltransfers=St&op All MainWindow.menu.transfers.pausetransfers=&Pause MainWindow.menu.transfers.pausetransfers.keybinding.mac=Meta+. MainWindow.menu.transfers.resumetransfers=&Resume ConfigView.label.experimental.osx.kernel.panic.fix=Experimental fix for kernel panics on dual-cpu OSX systems [requires restart] SystemTray.menu.pausetransfers=Pause Transfers SystemTray.menu.resumetransfers=Resume Transfers ConfigView.section.file.truncate.too.large=Truncate existing files that are too large ConfigView.section.file.perf.cache.trace=Trace cache operations for diagnostic purposes ConfigView.section.interface.enabletray=Enable System Tray [restart required] PeerManager.status.error=Error Stats.title.full=Statistics TransferStatsView.title.full=Transfers CacheView.title.full=Cache CacheView.general.size=Total Size CacheView.general.inUse=In Use CacheView.general.title=Cache Info CacheView.reads.title=I/O Reads CacheView.reads.fromFile=From File CacheView.reads.fromCache=From Cache CacheView.reads.hits=Hits CacheView.writes.title=I/O Writes CacheView.writes.toCache=To Cache CacheView.writes.toFile=To File CacheView.writes.hits=Saved CacheView.speeds.title=Data Rates CacheView.speeds.reads=Reads CacheView.speeds.writes=Writes CacheView.speeds.fromCache=From/To Cache CacheView.speeds.fromFile=From/To File CacheView.reads.#=# CacheView.reads.amount=Amount CacheView.reads.avgsize=Avg Size openUrl.referrer=Referring page URL : openUrl.referrer.info=Only required for web sites that mandate it ConfigView.label.maxuploadspeedseeding=Alternate rate when only seeding ConfigView.label.transfer.ignorepeerports=Ignore peers with these data ports (';' separated, e.g. 0;25) ConfigView.section.proxy.enable_socks.peer=Enable proxying of peer communications (outgoing connections only) [restart required] ConfigView.section.proxy.peer.informtracker=Inform tracker of limitation ConfigView.section.proxy.socks.version=SOCKS version PiecesView.legend.written=Written PiecesView.legend.requested=Requested PiecesView.legend.downloaded=Downloaded, write pending PiecesView.legend.incache=Data is in Cache PiecesView.typeItem.0=Slow PiecesView.typeItem.1=Fast PiecesView.type=Type Security.jar.tools_not_found=JAR signing fails - 'tools.jar' not found in %1. See Tools->Options->Security for details. Security.jar.signfail=JAR signing fails - %1 ConfigView.section.security.toolsinfo=Signed JAR files are used to support some plugins, for example the Swing Web Interface (when configured to do so).\nIn order to sign JAR files it is necessary to have access to the 'tools.jar' file that comes with the Sun JDK (not JRE) install.\nIf you have only installed the JRE then please install the JDK.\nVuze can normally find the file for you. However, if this fails you can explicitly set the containing directory here. ConfigView.section.security.toolsdir=Directory containing 'tools.jar' ConfigView.section.security.choosetoolssavedir=Select folder containing 'tools.jar' authenticator.torrent=Torrent ConfigView.section.proxy.peer.same=Use same proxy settings for tracker and peer communications proxy ConfigView.section.connection.network.max.simultaneous.connect.attempts=Max simultaneous outbound connection attempts ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Max number of new outbound connection establishments Vuze should attempt any given time.\nNOTE: WindowsXP Service Pack 2 (SP2) imposes a system-wide limit of 10 simultaneous connect attempts.\nDefault value is 8. ConfigView.section.file.perf.cache.size.explain=The cache is used to reduce reads from/writes to disk. Unless you are using the java option '-XX:MaxDirectMemorySize' to explicitly set the memory available for cache and network IO use, you should keep this value at least %1 below your maximum VM size. The current maximum VM size is %2. For instructions on how to change this, see MemoryUsage in the wiki on %3. Failure to use sensible settings will result in 'out of memory' errors. More than 32MB of cache is probably overkill. MyTorrentsView.menu.setSpeed.unlimit=No limit MyTorrentsView.menu.setSpeed.unlimited=Unlimited MyTorrentsView.menu.setSpeed.disable=Disable Upload MyTorrentsView.menu.setSpeed.disabled=Disabled MyTorrentsView.menu.setSpeed.in=in MyTorrentsView.menu.setSpeed.slots=slots of GeneralView.label.maxuploadspeed=Up Limit GeneralView.label.maxuploadspeed.tooltip=max upload speed [0 : unlimited] MyTorrents.items.UpSpeedLimit.disabled=No upload MyTorrents.items.UpSpeedLimit.unlimited=Unlimited TableColumn.header.maxupspeed=Max Up Speed TableColumn.header.maxupspeed.info=Max Upload Speed per torrent ConfigView.section.file.perf.cache.enable.write=Cache download data to reduce disk writes and also decrease disk reads required for piece checking ConfigView.section.file.perf.cache.enable.read=Perform read-aheads to reduce disk reads when uploading ConfigView.section.tracker.separatepeerids=Use different peer identities for tracker and data communication ConfigView.section.tracker.separatepeerids.info=Increases anonymity if downloading/seeding anonymously\nwhile using a non-anonymous tracker connection ConfigView.section.interface.wavlocation=Location of .wav file ConfigView.section.interface.wavlocation.info=Select .wav file or leave blank for default sound ConfigView.section.tracker.server=Server ConfigView.section.tracker.client=Client ConfigView.section.tracker.client.connecttimeout=Connect timeout (secs) ConfigView.section.tracker.client.readtimeout=Read timeout (secs) MainWindow.menu.tools=&Tools FilesView.path=Path FilesView.fullpath=Show Full Path FilesView.remaining=Remaining pieces TableColumn.header.trackername=Tracker Name TableColumn.header.trackername.info=Name of the tracker based on announce URL ConfigView.group.override=Override Options ConfigView.section.proxy=Proxy Options ConfigView.section.file.perf.cache.notsmallerthan=Do not cache files smaller than this (in %1) PeersView.menu.blockupload=Block Upload PeersView.menu.kickandban=Kick and Ban PeersView.menu.kickandban.reason=Peer manually banned PeersView.state=State PeersView.state.info=State of the peer connection PeersView.state.pending=Pending PeersView.state.connecting=Connecting PeersView.state.handshake=Waiting for handshake PeersView.state.established=Fully established ConfigView.section.tracker.processinglimits=Processing limits ConfigView.section.tracker.maxgettime=Max time for GET processing (secs) [0: unlimited] ConfigView.section.tracker.maxgettime.info=Used for announces and scrapes ConfigView.section.tracker.maxposttimemultiplier=GET time multiplier for POST processing [0: unlimited] ConfigView.section.tracker.maxposttimemultiplier.info=Used for form submissions and uploads ConfigView.section.tracker.maxthreads=Max concurrent requests DownloadManager.error.operationcancancelled=Operation cancelled Torrent.create.progress.cancelled=Operation cancelled sharing.progress.cancel=Cancel wizard.maketorrents.autoopen=Open the torrent for seeding when done ConfigView.section.sharing.rescanenable=Enable periodic rescanning of classic-shares for changes ConfigView.section.sharing.rescanperiod=Rescan period (secs) ConfigView.section.connection.advanced=Advanced Network Settings ConfigView.section.connection.advanced.url=http://www.azureuswiki.com/index.php/AdvancedNetworkSettings ConfigView.section.connection.advanced.mtu=Line Maximum Transmission Unit (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Maximum size of a packet that can be transferred in one frame over a network.\nVuze uses MTU-40 (MSS) for upload packet-payload optimizations.\nRecommended values:\n 576 - Dial-up connections\n1492 - PPPoE broadband connections\n1500 - Ethernet, DSL and Cable broadband connections ConfigView.section.connection.advanced.SO_RCVBUF=Socket SO_RCVBUF size [0: use OS default] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Sets the standard socket SO_RCVBUF value (in bytes), i.e. TCP receive window size and scale.\nVuze leaves this unset by default, meaning the defaults for the underlying OS are used.\nNOTE: Linux doubles the given value. ConfigView.section.connection.advanced.SO_SNDBUF=Socket SO_SNDBUF size [0: use OS default] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Sets the standard socket SO_SNDBUF value (in bytes), i.e. the TCP send window size.\nVuze leaves this unset by default, meaning the defaults for the underlying OS are used.\nNOTE: Linux doubles the given value. ConfigView.section.connection.advanced.IPDiffServ=Outgoing packet DiffServ value (TOS field) ConfigView.section.connection.advanced.IPDiffServ.tooltip=Sets the DiffServ part of the type-of-service (TOS) field in the IP header for outgoing packets.\nHexadecimal values can be specified by prefixing them with '0x', e.g. 0x10.\nVuze leaves this unset by default, meaning the defaults for the underlying OS are used.\nNOTE: Underlying network implementations may ignore this value, so this option is highly dependent on OS and JRE versions. ConfigView.section.interface.confirm_torrent_removal=Show confirmation dialog on torrent removal ConfigView.section.interface.confirm_torrent_removal.tooltip=Confirm when Removing a torrent from the MyTorrents view. MyTorrentsView.confirm_torrent_removal=Are you sure you want to remove?\n TableColumn.header.seed_to_peer_ratio=Seed2PeerRatio TableColumn.header.seed_to_peer_ratio.info=Total swarm seeds to peers ratio PeersView.connected_time=Connected Time PeersView.connected_time.info=Total time connected with peer ConfigView.section.interface.display.add_torrents_silently=Add torrents silently ConfigView.section.interface.display.add_torrents_silently.tooltip=Add torrent downloads without activating main Vuze window. TableColumn.header.maxdownspeed=Max Down Speed TableColumn.header.maxdownspeed.info=Max Download Speed per torrent PeersGraphicView.title=Swarm ConfigView.section.tracker.passwordwebhttpsonly=Only allow access via HTTPS TableColumn.header.torrentpath=Torrent Location TableColumn.header.torrentpath.info=Location of the Torrent on disk ConfigView.section.sharing.torrentcomment=Comment for generated torrents ConfigView.label.copyanddeleteratherthanmove=Copy and then delete the original data rather than move it in one operation - can help avoid data loss on some file systems ConfigView.label.openstatsonstart=Open Statistics on startup swt.install.window.title=Vuze Component/Plugin Installer swt.install.window.ok=Install swt.install.window.header=The following components have been selected for installation : swt.uninstall.window.title=Vuze Component/Plugin Remover swt.uninstall.window.ok=Remove swt.uninstall.window.header=The following components have been selected for removal : installPluginsWizard.title=Install Plugins installPluginsWizard.mode.title=Please choose an installation method installPluginsWizard.mode.list=By list from sourceforge.net installPluginsWizard.list.title=Installable Plugin List installPluginsWizard.list.loading=Please wait while the Plugin list is loaded. installPluginsWizard.list.loaded=Please choose the plugins you want to install. installPluginsWizard.list.name=Name installPluginsWizard.list.version=Version installPluginsWizard.list.description=Plugin's description installPluginsWizard.finish.title=Installation in Progress installPluginsWizard.finish.explanation=The selected Plugins will be installed using the Update Assistant.\n\nPlease be patient, this can take a short while to appear.\n\nFor a progress report, double click on the left of the status bar. installPluginsWizard.details.loading=Details loading, please wait... installPluginsWizard.mode.file=By file installPluginsWizard.installMode.title=Please choose the installation type installPluginsWizard.installMode.user=Install the plugin(s) for you only installPluginsWizard.installMode.shared=Install the plugin(s) for all users installPluginsWizard.file.title=Please browse for the plugin you want to install installPluginsWizard.file.file=File : installPluginsWizard.file.invalidfile=The file isn't a valid Vuze plugin. installPluginsWizard.file.no_such_file=No file exists with the given name. installPluginsWizard.file.browse=Browse... uninstallPluginsWizard.title=Uninstall Plugins uninstallPluginsWizard.list.title=Installed Plugin List uninstallPluginsWizard.list.loaded=Please choose the plugins you want to uninstall. installPluginsWizard.list.nullversion=No Version uninstallPluginsWizard.finish.title=Uninstallation in Progress uninstallPluginsWizard.finish.explanation=The selected Plugins will be uninstalled using the Update Assistant. MainWindow.menu.plugins.installPlugins=Installation Wizard... MainWindow.menu.plugins.uninstallPlugins=Uninstallation Wizard... ConfigView.section.ipfilter.totalIPs=%1 IPs blocked in total, which is %2 of the internet. update.instance.install=Checking Install update.instance.uninstall=Checking Uninstall update.instance.update=Checking for Updates MainWindow.status.update.tooltip=Double click for progress information updater.progress.window.title=Current Installation Tasks updater.progress.window.info=Press 'Abort' to terminate all outstanding tasks Button.abort=Abort ConfigView.section.ipfilter.enablebanning=Block peers that consistently send bad data Network.alert.acceptfail=Too many successive failures occurred on port %1, %2 - processing abandoned. Please check firewall settings for this port to ensure that it is enabled for receiving connections. MyShares.column.category=Category UpdateWindow.restartLater=Restart Vuze Later MainWindow.menu.file.restart=Restart Vuze MainWindow.dialog.restartconfirmation.title=Restart Vuze MainWindow.dialog.restartconfirmation.text=Do you really want to restart Vuze deletetorrent.message1=You are about to delete the TORRENT for :\n deletetorrent.message2=\nAre you sure you want to proceed? ConfigView.label.prioritizemostcompletedfiles=Further prioritize High priority files according to % complete and size of file splash.plugin.init=Initializing Plugin: splash.plugin.UIinit=Initializing Plugin GUI: %1 ConfigView.section.style.osx_small_fonts=Use small fonts [restart required] ConfigView.section.tracker.tcpnonblocking=Use non-blocking I/O for TCP tracker processing. Selecting this option requires the tracker web to be run on an alternative port. Experimental! ConfigView.section.tracker.nonblocking=Non-blocking options ConfigView.section.tracker.nonblockingconcmax=Max concurrent connections [0: unlimited] MyTorrentsView.menu.exportmenu=Export MyTorrentsView.menu.exporttorrent=Torrent... ConfigView.group.scrape=Scrape ConfigView.section.tracker.client.scrapeinfo=Disabling scraping will prevent many of the torrent queueing rules from working as they rely on swarm information retrieved by scraping trackers. ConfigView.section.tracker.client.scrapeenable=Enable scraping ConfigView.section.tracker.client.scrapestoppedenable=Scrape torrents that aren't running Scrape.status.disabled=Scrape Disabled MyTorrentsView.menu.explore=Show File MyTorrentsView.menu.explore._mac=Show In Finder MyTorrentsView.menu.explore._windows=Show In Explorer wizard.maketorrents.autohost=Host the torrent on the built-in tracker ConfigView.label.overrideip=Override tracker announce IP(s) - semicolon separate if more than one for different networks ConfigView.label.overrideip.tooltip=Inform the tracker of different IP address(es) than the one outgoing packets come from. Leave blank not to use the option. ConfigView.section.connection.group.networks=Networks ConfigView.section.connection.group.networks.info=Select the default permitted networks for peer-peer data transmission ConfigView.section.connection.networks.prompt=Prompt for selection when a download with an anonymous tracker is added ConfigView.section.connection.networks.Public=Public IP network (not anonymous) ConfigView.section.connection.networks.I2P=I2P network ConfigView.section.connection.networks.Tor=The Onion Router (Tor) network TableColumn.header.networks=Networks TableColumn.header.networks.info=Networks permitted for peer-peer data communication Scrape.status.networkdisabled=Network not enabled ConfigView.section.tracker.server.group.networks=Networks ConfigView.section.tracker.server.group.networks.info=Select the networks for which the tracker will accept peers window.networkselection.title=Network Selection window.networkselection.info=The torrent listed below has tracker(s) that support the following networks.\nSelect the ones to enable for tracker and peer communication.\nIf it is an anonymous tracker that supports public clients enable both the anonymous and public networks.\nEnabling the public network has the obvious consequence of removing anonymity! window.networkselection.description=Torrent : plugins.basicview.clear=Clear ConfigView.section.connection.group.peersources=Peer Sources ConfigView.section.connection.group.peersources.info=Select the default permitted sources for peer connections ConfigView.section.connection.peersource.Tracker=From a tracker ConfigView.section.connection.peersource.DHT=Decentralized tracking ConfigView.section.connection.peersource.PeerExchange=Supplied by another peer ConfigView.section.connection.peersource.Plugin=Added by a plugin ConfigView.section.connection.peersource.Incoming=Incoming connection PeersView.source=Source PeersView.source.info=The source of this peer TableColumn.header.peersources=Peer Sources TableColumn.header.peersources.info=Peer sources permitted for the establishment of peer connections wizard.tracker.dht=Decentralized (Vuze clients only) MyTorrentsView.menu.advancedmenu=Advanced MyTorrentsView.menu.networks=Networks MyTorrentsView.menu.peersource=Peers Sources ConfigView.section.sharing.permitdht=Allow decentralized tracking when tracker is unavailable ConfigView.section.sharing.protocol=Protocol for classically-shared resources PeersView.Messaging=Messaging PeersView.Messaging.info=Indicates what messaging system is in use. ConfigView.label.queue.newseedsmovetop=Move newly completed torrents to the front of the seeding list ConfigView.label.seeding.firstPriority.ignore.info=Be aware that using these rules may result in stopping a torrent\nas soon as the download finishes. ConfigView.label.seeding.firstPriority.ignore=Ignore First Priority rules above for: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents with a Seeds to Peers ratio over ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents with 0 Peers ConfigView.section.tracker.sendjavaversionandos=Send Java version and OS name MagnetPlugin.contextmenu.exporturi=Copy Magnet URI to Clipboard ConfigView.section.plugins.dht=Distributed DB dht.info=This plugin supports decentralized tracking, amongst other things, - disabling it will reduce your ability to download dht.enabled=Enable the distributed database dht.portdefault=Use the default port dht.port=UDP port for the database dht.execute.command=Diagnostic command dht.execute.info=Press to execute the command dht.execute=Run dht.logging=Enable tracing of activity ConfigView.section.plugins.dhttracker=Distributed Tracker dhttracker.tracknormalwhenoffline=Only track normal torrents when their tracker is unavailable ConfigView.section.file.nativedelete._mac=Use Trash when deleting files ConfigView.section.file.nativedelete._windows=Move deleted files to the Recycle Bin ConfigView.section.logging.generatediagnostics=Generate ConfigView.section.logging.netinfo=Generate network info ConfigView.section.logging.statsinfo=Generate stats info ConfigView.section.logging.generatediagnostics.info=Generate diagnostic information and copy to the clipboard and log file, if configured ConfigView.section.sharing.privatetorrent=Private torrent - only accept peers from the tracker MainWindow.menu.tools.nattest=&NAT / Firewall Test Button.apply=Apply Button.close=Close window.welcome.title=Welcome to Vuze %1 #file can be a URL or a path in the jar window.welcome.file=/changelog.txt MainWindow.menu.help.releasenotes=Release Notes dht.reseed.label=Normally reseeding of the Distributed Database is not necessary. However, if the number of contacts is low this can be used for re-integration.\nLeave blank to bootstrap off connected peers or enter IP and port to explicitly bootstrap from a known peer. dht.reseed.group=Reseed dht.reseed.ip=IP address dht.reseed.port=Port dht.reseed=Reseed dht.reseed.info=Reseed the database dht.diagnostics.group=Diagnostics DHTView.title.full=Distributed Database DHTView.title.fullcvs=Distributed Database CVS DHTView.general.title=General DHTView.general.uptime=Uptime: DHTView.general.users=Users: DHTView.general.nodes=Nodes: DHTView.general.leaves=Leaves: DHTView.general.contacts=Contacts: DHTView.general.replacements=Replacements: DHTView.general.live=Live: DHTView.general.unknown=Unknown: DHTView.general.dying=Dying: DHTView.transport.title=Transport Details DHTView.transport.packets=Packets DHTView.transport.bytes=Bytes DHTView.transport.received=Received DHTView.transport.sent=Sent DHTView.transport.in=In : DHTView.transport.out=Out : DHTView.operations.title=Operation Details DHTView.operations.sent=Sent DHTView.operations.ok=Ok DHTView.operations.failed=Failed DHTView.operations.received=Received DHTView.operations.ping=Ping DHTView.operations.findNode=Find Node DHTView.operations.findValue=Find Value DHTView.operations.store=Store DHTView.activity.title=Activity DHTView.activity.status=Status DHTView.activity.status.true=Queued DHTView.activity.status.false=Running DHTView.activity.type=Type DHTView.activity.type.1=Internal Get DHTView.activity.type.2=External Get DHTView.activity.type.3=Internal Put DHTView.activity.type.4=External Put DHTView.activity.target=Target DHTView.activity.details=Details DHTView.db.title=Database DHTView.db.keys=Keys DHTView.db.values=Values DHTView.db.local=Local DHTView.db.direct=Direct DHTView.db.indirect=Indirect DHTView.db.divfreq=Freq. Div. DHTView.db.divsize=Size Div. MainWindow.dht.status.tooltip=When the Distributed Database is running this shows the estimated number of users currently online MainWindow.dht.status.disabled=DHT Disabled MainWindow.dht.status.failed=DHT Failed MainWindow.dht.status.initializing=DHT Initializing MainWindow.dht.status.users=%1 users MainWindow.dht.status.unreachable=DHT Firewalled MainWindow.dht.status.unreachabletooltip=There appears to be a problem with the Distributed Database's UDP port mapping (NAT/firewall) MyTorrentsView.menu.setUpSpeed=Set Up Speed MyTorrentsView.menu.setDownSpeed=Set Down Speed ConfigView.section.tracker.client.showwarnings=Show warning messages reported by trackers dht.advanced=Enable advanced settings dht.advanced.group=Advanced settings dht.advanced.label=Only amend these values if you really know what you're doing dht.override.ip=Override external IP address ConfigView.section.logging.loggerenable=Enable logging ConfigView.section.ipfilter.blockbanning=Ban a block of 256 addresses when at least this many in the block have been banned MyTrackerView.passive=Passive TableColumn.header.swarm_average_speed=Swarm Average Speed TableColumn.header.swarm_average_speed.info=The average speed of peers in the swarm TableColumn.header.comment=Comment TableColumn.header.comment.info=User-defined comment for download TableColumn.header.commenticon=Comment Icon TableColumn.header.commenticon.info=Displays icon if the download has a user-defined comment MyTrackerView.category=Category MainWindow.menu.file.open.torrentfortracking=Torrent File... (Tracking Only) VivaldiView.title.full=Vivaldi VivaldiView.title.fullcvs=Vivaldi CVS VivaldiView.title.full_v6=Vivaldi IPv6 MyTrackerView.date_added=Added ConfigView.section.tracker.portbackup=Backup ports (';' separated) ConfigView.label.playfilespeech=Speak when a file is finished ConfigView.label.playfilespeech.info=Speech Services currently works best with English ConfigView.label.playfilefinished=Play a sound when a file is finished ConfigView.label.backupconfigfiles=Backup configuration files for recovery purposes ConfigView.section.tracker.client.scrapesingleonly=Disable per-tracker scrape aggregation (can help with trackers that report 'URL too long' (414) errors) dht.ipfilter.log=Log IP Filter violations ConfigView.label.seeding.addForSeedingDLCopyCount=Consider 'add for seeding' downloads to have downloaded this number of copies ActivityView.legend.limit=Rate limit ActivityView.legend.achieved=Rate achieved ActivityView.legend.overhead=Rate overhead ActivityView.legend.peeraverage=Average ActivityView.legend.swarmaverage=Swarm average ActivityView.legend.trimmed=Trimmed (dotted) MyTorrentsView.menu.movemenu=Move Files MyTorrentsView.menu.movedata=Move Data Files... MyTorrentsView.menu.movetorrent=Move Torrent File... MyTorrentsView.menu.movedata.dialog=Choose new location DHTView.operations.data=Data DHTView.general.reachable=Reachable: DHTView.general.rendezvous=Rendezvous: ConfigView.label.queue.maxactivetorrentswhenseeding=Max when only seeding [0:unlimited] IrcView.title.short=IRC Views.plugins.IRC.title=IRC - Online Technical Support Formats.units.persec=/s Formats.units.TiB=TiB Formats.units.Tibit=Tibit Formats.units.TB=TB Formats.units.Tbit=Tbit Formats.units.GiB=GiB Formats.units.Gibit=Gibit Formats.units.GB=GB Formats.units.Gbit=Gbit Formats.units.MiB=MiB Formats.units.Mibit=Mibit Formats.units.MB=MB Formats.units.Mbit=Mbit Formats.units.KiB=KiB Formats.units.Kibit=Kibit Formats.units.kB=kB Formats.units.KB=KB Formats.units.kbit=kbit Formats.units.B=B Formats.units.bit=bit Formats.units.alot=A lot !!! ConfigView.section.ipfilter.persistblocking=Save blocked IP details across restarts FilesView.menu.rename=Rename or Retarget FilesView.menu.rename_only=Quick Rename FilesView.menu.retarget=Move Files FilesView.rename.choose.path=Choose new or existing file FilesView.rename.choose.path.dir=Choose new or existing directory FilesView.rename.confirm.delete.title=Confirm Delete FilesView.rename.confirm.delete.text=Confirm deletion of original file '%1' FilesView.rename.filename.title=Rename file FilesView.rename.filename.text=Choose a new name for the file ConfigView.higher.mode.available=Further options are available in higher user modes ConfigView.section.mode=Mode ConfigView.section.mode.title=User Proficiency ConfigView.section.mode.beginner=Beginner ConfigView.section.mode.beginner.wiki.definitions=BitTorrent vocabulary ConfigView.section.mode.intermediate=Intermediate ConfigView.section.mode.intermediate.wiki.host=Hosting Files ConfigView.section.mode.intermediate.wiki.publish=Publishing Files ConfigView.section.mode.advanced=Advanced ConfigView.section.mode.advanced.wiki.main=Wiki Main Page ConfigView.section.mode.beginner.text=All you need to download torrents.\nUse this mode if all you want is manage your torrents. ConfigView.section.mode.intermediate.text=Access to tracker functions.\nUse this mode if you want to create your own tracker and host/publish your files. ConfigView.section.mode.advanced.text=Access to network settings.\nUse this mode if you know what MTU or non blocking I/O are... Files.column.storagetype=Storage Type Files.column.fileext=Type FileItem.storage.linear=Linear FileItem.storage.compact=Compact MessageBoxWindow.rememberdecision=Remember my decision ConfigView.section.interface.cleardecisions=Clear remembered dialog decisions ConfigView.section.interface.cleardecisionsbutton=Clear ConfigView.section.interface.cleartrackers=Clear remembered trackers ConfigView.section.interface.cleartrackersbutton=Clear ConfigView.section.interface.clearsavepaths=Clear remembered save paths ConfigView.section.interface.clearsavepathsbutton=Clear configureWizard.welcome.usermodes=This User Proficiency setting will determine the level of the options displayed in Tools > Options. It is in your best interest to set it properly. FilesView.skip.confirm.delete.text=Truncate file '%1' to save space? FilesView.rename.failed.title=Rename/Retarget failed FilesView.rename.failed.text=The operation failed, probably due to invalid target selection diagnostics.log_found=Vuze did not shutdown tidily. Check for any diagnostic log files. Also read the wiki article Vuze Disappears for more information. ManagerItem.paused=Paused Utils.link.visit=Please visit ConfigView.section.connection.serverport.wiki=Good ports choices ConfigView.section.transfer.speeds.wiki=Good speed settings installPluginsWizard.installMode.info.title=Info installPluginsWizard.installMode.info.text=You do not need plugins for Vuze to work properly, they bring complementary features for fun, automation or remote control.\nSo please read each plugin's description carefully before deciding to install it.\nMost plugins are safe to try out, just don't overload your configuration with plugins you will not use. Views.plugins.Distributed.DB.title=Distributed DB Views.plugins.Distributed.Tracker.title=Distributed Tracker Views.plugins.Plugin.Update.title=Plugin Update Views.plugins.UPnP.title=UPnP Views.plugins.UPnP.title.tooltip=Universal Plug and Play openUrl.url.info=Supports http, https, magnet and raw hex infohash strings TableColumn.header.swarm_average_completion=Peer Average Completion TableColumn.header.swarm_average_completion.info=The average completion percentage of peers in the swarm GeneralView.label.swarm_average_completion=Average Completion: GeneralView.label.swarm_average_completion.tooltip=The average completion percentage of peers in the swarm MainWindow.nat.status.unknown=NAT MainWindow.nat.status.tooltip.unknown=Firewall/NAT reachability status unknown (TCP) MainWindow.nat.status.ok=NAT OK MainWindow.nat.status.tooltip.ok=Reachability OK (TCP) MainWindow.nat.status.probok=NAT OK? MainWindow.nat.status.tooltip.probok=Reachability was OK, however no recent incoming TCP connections MainWindow.nat.status.bad=Firewalled MainWindow.nat.status.tooltip.bad=Firewall/NAT (TCP) reachability problem. Refer to the Wiki for help plugin.installer.recommended.plugin=Recommended plugin - please review and install if required LoggerView.pause=Pause Logging LoggerView.clear=&Clear LoggerView.filter=Filter LoggerView.filter.uncheckAll=Uncheck All Categories LoggerView.filter.checkAll=Check All Categories LoggerView.loggingDisabled=Logging is not enabled. LoggerView.includeOnly=Only display lines matching this regular expression: LoggerView.excludeAll=Do not display lines matching this regular expression: ConfigView.section.logging.log0type=Information ConfigView.section.logging.log1type=Warning ConfigView.section.logging.log2type=Error ConfigView.section.logging.filter=Filter when logging to file ConfigView.section.logging.level=Log Level ConfigView.section.logging.showLogsFor=Show %1 logs for the following categories: ConfigView.pluginlist.column.loadAtStartup=Load at Startup ConfigView.pluginlist.column.type=Type ConfigView.pluginlist.column.type.perUser=Per User ConfigView.pluginlist.column.type.shared=Shared ConfigView.pluginlist.column.type.builtIn=Built In ConfigView.pluginlist.column.name=Name ConfigView.pluginlist.column.version=Version ConfigView.pluginlist.column.directory=Directory ConfigView.pluginlist.column.isOperational=Operational? PeersView.BlockView.Avail.Have=Both have PeersView.BlockView.Avail.NoHave=Peer has; You don't PeersView.BlockView.NoAvail.Have=You have; Peer doesn't PeersView.BlockView.NoAvail.NoHave=Neither has PeersView.BlockView.Transfer=Transferring PeersView.BlockView.NextRequest=Next Request PeersView.BlockView.title=Piece Map PeersView.BlockView.AvailCount=Availability Count MyTorrentsView.dialog.NumberError.title=Invalid or Unrecognized Number MyTorrentsView.dialog.NumberError.text=The number you entered is invalid or unrecognized. MyTorrentsView.menu.manual=&Manual... MyTorrentsView.menu.manual.per_torrent=Manual (per torrent) MyTorrentsView.menu.manual.shared_torrents=Manual (across torrents) MyTorrentsView.dialog.setSpeed.title=Set %1 speed # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Enter a number %1 to change %2 to: MyTorrentsView.dialog.setNumber.upload=upload MyTorrentsView.dialog.setNumber.download=download MyTorrentsView.dialog.setNumber.inKbps=in %1 OpenTorrentWindow.torrentLocation=Torrent(s) to be downloaded: OpenTorrentWindow.addFiles.URL=Add &URL OpenTorrentWindow.addFiles.Folder=Add &Folder OpenTorrentWindow.addFiles.Clipboard=Add From Clip&board OpenTorrentWindow.changeDestination=Change Destination OpenTorrentWindow.fileList=Files in torrents: OpenTorrentWindow.torrentTable.name=Name OpenTorrentWindow.torrentTable.saveLocation=Save Location OpenTorrentWindow.fileTable.fileName=File Name OpenTorrentWindow.fileTable.size=Size OpenTorrentWindow.fileTable.destinationName=Dest. Name OpenTorrentWindow.startMode.seeding=Seeding OpenTorrentWindow.fileList.changeDestination=Change Destination OpenTorrentWindow.mb.badSize.title=Incompatible File OpenTorrentWindow.mb.badSize.text='%1' is not '%2' and can not be used for seeding OpenTorrentWindow.mb.alreadyExists.text=%3 has already been added as '%2' OpenTorrentWindow.mb.alreadyExists.default.name=Media OpenTorrentWindow.mb.alreadyExists.title=Already exists OpenTorrentWindow.mb.openError.title=Open Error OpenTorrentWindow.mb.openError.text='%1' could not be opened:\r\n%2 OpenTorrentWindow.torrent.remove=Remove torrent from list OpenTorrentWindow.torrent.options=The following settings will apply to the torrents selected above: OpenTorrentWindow.xOfTotal=(%1 of %2) iconBar.open.tooltip=Open Torrent(s) LocaleUtil.column.text=Unknown Text Tracker.tooltip.MultiSupport=This tracker supports multiple hash scrapes per request. Tracker.tooltip.NoMultiSupport=This tracker does not support multiple hash scrapes per request.\nThis will not affect your performance, but it does put extra load on the tracker. ConfigView.label.lazybitfield=Use lazy bitfield (helps seeding on networks employing bitfield-based blocking) LoggerView.realtime=Update in real time ConfigView.section.file.perf.cache.flushpieces=Write complete pieces to disk immediately. This smoothes disk access but can result in more write operations. ConfigView.section.file.writemblimit=Maximum write requests queued (in %1) ConfigView.section.file.writemblimit.explain=When disk write speed is lower than download speed this parameter limits how much data will be queued before download speeds are reduced. ConfigView.section.file.readmblimit=Maximum read requests queued (in %1) ConfigView.section.file.readmblimit.explain=This parameter limits how much memory will be used to store reads that are pending processing. Button.moveUp=Move &Up Button.moveDown=Move &Down ConfigView.notAvailableForMode=This section is intended for %1 mode or higher. It is not available in %2 mode. health.explain.error=There is an error with this torrent. See the Status column, or the tooltip on the icon for the error. GeneralView.label.trackerscrapeupdate=Scrape Tracker PeersView.piece=Piece PeersView.piece.info=Last piece # requested from this peer PiecesView.priority=Priority PiecesView.priority.info=this piece's completion priority, but don't pay too much attention to it PiecesView.speed=Speed PiecesView.speed.info=Slower peers are prevented from interfering with faster pieces very much TableColumn.header.AvgAvail.info=Sum of pieces availability divided by # pieces, divided by # connections TableColumn.header.AvgAvail=Avg Avail/piece ConfigView.label.strictfilelocking=Enforce exclusive file write access locking across torrents MyTorrentsView.menu.checkfilesexist=Check Files Exist MyTorrentsView.menu.rescanfile=Periodically Recheck Incomplete Pieces MyTorrentsView.menu.clear_resume_data=Clear Resume Data Plugin.extseed.name=External Seeds Plugin.localtracker.name=LAN Peer Finder Plugin.localtracker.info=The LAN peer finder permits multiple copies of Vuze behind a firewall and on a common network\nto efficiently download torrents by enabling direct connections between them Plugin.localtracker.enable=Enable the LAN peer finder azinstancehandler.alert.portclash=Port clash detected on LAN: %1 already in use by another Vuze user, select new random port(s) for incoming TCP / UDP listen [between %2 and %3]. ConfigView.section.transfer.lan=LAN ConfigView.section.transfer.lan.tooltip=LAN-specific Settings ConfigView.section.transfer.lan.uploadrate=KB/s LAN max upload speed [0: unlimited] ConfigView.section.transfer.lan.uploadrate.tooltip=Peers connections within the same internal LAN have a separate upload rate limit. ConfigView.section.transfer.lan.downloadrate=KB/s LAN max download speed [0: unlimited] ConfigView.section.transfer.lan.downloadrate.tooltip=Peers connections within the same internal LAN have a separate download rate limit. TorrentOptionsView.title.short=Options TorrentOptionsView.title.full=Options TorrentOptionsView.param.max.peers=Maximum number of connections [0: unlimited] ConfigView.section.connection.encryption.require_encrypted_transport=Require encrypted transport ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Force use of encrypted connections with other peers. ConfigView.section.connection.encryption.min_encryption_level=Minimum encryption level ConfigView.section.connection.encryption.min_encryption_level.tooltip=Plain - handshake only\nRC4 - full stream\nHigher encryption requires more CPU. Peers.column.Encryption=Encryption Peers.column.Encryption.info=Level of encryption in use ConfigView.section.connection.encryption.encrypt.info=If encryption is enabled you won't be able to connect to incompatible clients unless you configure fallback options ConfigView.section.connection.encryption.encrypt.info.link=Please visit here for details MainWindow.sr.status.tooltip.ok=Share Ratio %1 OK MainWindow.sr.status.tooltip.poor=Share Ratio %1 poor: < 0.9 MainWindow.sr.status.tooltip.bad=Share Ratio %1 bad: < 0.5 ConfigView.section.style.status=Status Area: ConfigView.section.style.status.show_sr=Share Ratio ConfigView.section.style.status.show_nat=NAT Status ConfigView.section.style.status.show_ddb=DDB Status ConfigView.section.style.status.show_ipf=IPFilter Status ConfigView.section.connection.encryption.encrypt.group=Transport Encryption/Obfuscation ConfigView.section.connection.encryption.encrypt.fallback_info=Enabling either fallback option will allow connections to incompatible clients BUT will result in non-encrypted connections ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Allow non-encrypted outgoing connections if encrypted connection attempt fails ConfigView.section.connection.encryption.encrypt.fallback_incoming=Allow non-encrypted incoming connections ConfigView.section.connection.encryption=Transport Encryption upnp.selectedinterfaces=Selected interfaces (';' seperated, e.g. eth0;eth1) [blank: all] ConfigView.section.style.defaultSortOrder=Default Sort Order ConfigView.section.style.defaultSortOrder.desc=Descending ConfigView.section.style.defaultSortOrder.asc=Ascending ConfigView.section.style.defaultSortOrder.flip=Opposite of previous order LoggerView.autoscroll=Auto-scroll Button.selectAll=Select All Button.markSelected=Mark Selected Button.unmarkSelected=Unmark Selected plugins.basicview.config=Config TorrentOptionsView.param.max.uploads=Maximum number of upload slots [minimum: 2] MyTorrentsView.dialog.setPosition.title=Set Position MyTorrentsView.dialog.setPosition.text=Enter position to set selected torrents to: MyTorrentsView.menu.reposition.manual=Reposition.. ConfigView.section.connection.advanced.info.link=Please visit here for details ConfigView.section.connection.advanced.socket.group=Socket Options ConfigView.section.connection.advanced.bind_port=Bind to local port [0: disabled] ConfigView.section.connection.advanced.bind_port.tooltip=Outgoing socket connections will be locally bound to the given port.\nEnabling this may help with NAT router instability. ConfigView.section.proxy.group.tracker=Tracker Communications ConfigView.section.proxy.group.peer=Peer Communications Pieces.column.Requested=Requested Pieces.column.Requested.info=Shows if more requests can be made on the piece or not (*) ConfigView.label.maxuploadsseeding=Alternate default when seeding MyTorrentsView.filter=Filter popup.error.hideall=Hide All ConfigView.section.style.dataStatsOnly=Show data statistics only (hide protocol statistics) ConfigView.section.style.separateProtDataStats=Show separate data and protocol statistics as 'data (protocol)' MyTorrentsView.dialog.setFilter.title=Modify Filter MyTorrentsView.dialog.setFilter.text=The %1 section will be filtered by the text you specify below. Use the | (pipe) symbol to filter on multiple phrases. MyTorrentsView.filter.tooltip=Ctrl+X to switch between RegEx and normal search modes.\nUse the | (pipe) symbol to filter on multiple phrases. MyTorrentsView.clearFilter.tooltip=Clear Filter MyTorrentsView.menu.filter=Filter List... ConfigView.section.file.resume.recheck.all=On crash-restart check entire file for completed pieces (Otherwise only pieces active at last save are checked) ConfigureWizard.language.choose=Choose a language from the list below: popup.closing.in=Auto-closing window in %1 seconds popup.more.waiting=%1 more message(s).. # > 2402 popup.next=> popup.previous=< (%1) popup.download.finished="%1" has finished downloading. popup.file.finished="%1" has finished downloading. ConfigView.auto=Auto Plugin.localtracker.autoadd.info=Automatically add these local peers [';' separated addresses, e.g. 1.2.3.4] Plugin.localtracker.autoadd=\ \ \ \ Explicit peers Plugin.localtracker.networks.info=Consider the following networks to be local [';' separated networks, e.g. 145.227.*.*] Plugin.localtracker.networks=\ \ \ \ Local networks MainWindow.menu.view.plugins.logViews=Log Views SpeedView.stats.autospeed=Automatic Upload Speed SpeedView.stats.autospeed.disabled=This Feature is either disabled (you need the DHT) or not in use (manual upload speed selected) SpeedView.stats.idlePing=Idle Ping: SpeedView.stats.maxPing=Max Ping: SpeedView.stats.currentPing=Current Ping: SpeedView.stats.maxUp=Max Up Speed: ConfigView.pluginlist.unloadSelected=Unload Selected ConfigView.pluginlist.scan=Scan for new Plugins ConfigView.section.transfer.autospeed=Auto-Speed (classic) ConfigView.section.transfer.autospeed.tooltip=Auto-speed specific settings ConfigView.section.transfer.autospeed.info=Auto-speed automatically adjusts the upload speed limit to avoid overloading the network connection.\n\nThese limits will only be applied when automatic upload speed is enabled and also require the distributed database to be enabled.\n ConfigView.section.transfer.autospeed.minupload=%1 minimum upload speed ConfigView.section.transfer.autospeed.minupload.tooltip=Upload speed will not normally be automatically decreased below this limit ConfigView.section.transfer.autospeed.maxupload=%1 maximum upload speed [0: unlimited] ConfigView.section.transfer.autospeed.maxupload.tooltip=Upload speed will not be automatically increased above this limit ConfigView.section.transfer.autospeed.chokeping=Choking ping time [milliseconds] ConfigView.section.transfer.autospeed.chokeping.tooltip=Ping times in excess of this value will be considered as an indicator of network saturation ConfigView.section.transfer.autospeed.enableauto=Enable when downloading and seeding ConfigView.section.transfer.autospeed.enableautoseeding=Enable when only seeding ConfigView.pluginlist.column.unloadable=Unloadable ConfigView.section.transfer.lan.enable=Enable separate speed limits for LAN connections Plugin.localtracker.wellknownlocals=Automatically include loopback/link/site local networks (192.168 etc) TableColumn.header.filesdone=Files Done TableColumn.header.filesdone.info=Files done/Total files *or* Non-skipped files done (Files done)/Total non-skipped files (Total files) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=waiting for DDB initialization... MagnetPlugin.report.searching=searching... MagnetPlugin.report.found=found %1 MagnetPlugin.report.alive=%1 is alive MagnetPlugin.report.dead=%1 is dead MagnetPlugin.report.tunnel=tunnelling to %1 MagnetPlugin.report.downloading=downloading from %1 MagnetPlugin.report.error=error %1 MagnetURLHandler.report.no_sources=no sources found for torrent MagnetURLHandler.report.torrent_size=torrent size: %1 MagnetURLHandler.report.percent=completed: %1% MagnetURLHandler.report.error=error %1 DHTTransport.report.request_all=requesting entire transfer from %1 DHTTransport.report.received_bit=received %1 to %2 from %3 DHTTransport.report.complete=complete DHTTransport.report.timeout=timeout, no replies from %1 DHTTransport.report.rerequest_all=re-requesting entire transfer from %1 DHTTransport.report.rerequest_bit=re-requesting %1 to %2 from %3 DHTTransport.report.timeout_some=timeout, %1 packets received from %2 but incomplete DHTTransport.report.sending=sending data DHTTransport.report.resending=resending data DHTTransport.report.send_complete=send complete DHTTransport.report.send_timeout=send timeout ConfigView.section.transfer.autospeed.enabledebug=Log debug information TableColumn.header.date_added=Date added TableColumn.header.date_added.info=Date the torrent was added ConfigView.section.file.hashchecking.smallestfirst=Recheck smallest downloads first platform.win32.baddll.info=Vuze has detected the presence of '%1'. This is part of '%2' and has been known to cause severe problems such as application crashes and high CPU usage. If you encounter these then please uninstall the software or configure it to not affect Vuze. platform.win32.baddll.niphk=Norman Anti-Virus platform.win32.baddll.nvappfilter=NVidia Firewall platform.win32.baddll.netdog=Armor2net Personal Firewall platform.win32.baddll.vlsp=Venturi Firewall platform.win32.baddll.imon=NOD32 platform.win32.baddll.sarah=FRITZ! Application Layer Firewall platform.win32.baddll.MxAVLsp=VCom Fix-It Utilities platform.win32.baddll.mclsp=McAfee Privacy Service platform.win32.baddll.radhslib=Naomi Internet Filter (Radiant) platform.win32.baddll.nl_lsp=NetLimiter platform.win32.baddll.winsflt=PureSight Internet Content Filter platform.win32.baddll.AxShlex=Alcohol 120% platform.win32.baddll.iFW_Xfilter=iolo Personal Firewall platform.win32.baddll.gapsp=Neoteris platform.win32.baddll.WSOCKHK=Net Nanny upnp.ignorebaddevices=Ignore devices that fail to respond correctly upnp.ignorebaddevices.info=Currently ignored devices: %1 upnp.ignorebaddevices.reset=Reset the ignored device list upnp.ignorebaddevices.reset.action=Reset upnp.ignorebaddevices.alert=UPnP device at location %1 is being ignored due to repeated failures. See the UPnP plugin configuration for options regarding this action. TorrentOptionsView.param.max.uploads.when.busy=KB/s max upload speed when global upload limit reached [0: disabled] UpdateMonitor.messagebox.verification.failed.title=Install Verification Failed UpdateMonitor.messagebox.verification.failed.text=Verification of '%1' failed: %2 UpdateMonitor.messagebox.accept.unverified.title=Accept Unverified Installation UpdateMonitor.messagebox.accept.unverified.text='%1' could not be verified as an official Vuze plugin.\nIf it is such a plugin you should NOT continue.\nProceed with installation? FileView.BlockView.title=File Pieces FileView.BlockView.Done=Done FileView.BlockView.Skipped=Skipped FileView.BlockView.Active=Active FileView.BlockView.Outstanding=Outstanding ConfigView.label.tcplistenport=Incoming TCP listen port ConfigView.label.udplistenport=UDP listen port upnp.portchange.alert=The following ports have been changed to avoid UPnP device problems: %1 [old port=%2] %3 [old port=%4] ConfigView.section.proxy.username.info=If the proxy server demands authentication even when none is defined, use the string "" as the username(s) ConfigView.label.maxuploadswhenbusymin=Per torrent max upload speed when busy timer [sec] MainWindow.menu.help.debug=Generate Debug Info (Crash Log) DownloadManager.error.badsize=Incorrect Size ConfigView.section.NATPMP=NAT-PMP natpmp.info=NAT-PMP is Apple's alternative to UPnP and is supported by recent Airport stations\n\nNote that currently UPnP has to be enabled to enable NAT-PMP as the NAT-PMP device is treated as a special type of UPnP device natpmp.enable=Enable (note that it must also be enabled in the Airport configuration to work) ConfigView.section.tracker.host.addurls=Ensure this tracker's URLs are present in hosted torrents ConfigView.filter=search for options here ConfigView.section.files.move=Completion Moving ConfigView.section.file.defaultdir.section=Default Directory Options ConfigView.section.file.defaultdir.auto=Automatically download to default directory (No Prompt) ConfigView.section.file.defaultdir.bestguess=Use best guess when choosing default save directory ConfigView.section.file.defaultdir.ask=Default directory: ConfigView.section.file.defaultdir.lastused=Update default directory to location last saved to ConfigView.section.file.config.section=Configuration Settings ConfigView.section.file.config.currentdir=Current configuration directory: ConfigView.section.torrent.decoding=Decoding Character Sets ConfigView.section.logging.udptransport=Enable verbose UDP transport trace Tracker.announce.ignorePeerSeed=Ignoring Peer/Seed count. %1 ConfigView.section.connection.encryption.use_crypto_port=Use the 'cryptoport' tracker extension to prevent plain incoming connection attempts. Some trackers don't accept this and fail with errors such as "Invalid Port" or "Illegal Argument" TorrentOptionsView.param.reset.to.default=Set options back to their default values TorrentOptionsView.param.reset.button=Reset natpmp.routeraddress=Station address [blank: auto] ConfigView.section.style.disableAlertSliding=Disable sliding animation/on top style for alert messages ConfigView.section.transfer.autospeed.maxinc=%1 maximum increase per cycle ConfigView.section.transfer.autospeed.maxdec=%1 maximum decrease per cycle ConfigView.section.transfer.autospeed.enabledownadj=Enable download speed adjustment ConfigView.section.transfer.autospeed.downadjratio=Download : Upload speed ratio (e.g. 2.0 -> download speed limit is double upload limit) ConfigView.section.transfer.autospeed.latencyfactor=Factor used to link latency changes to speed changes (larger numbers decrease sensitivity) ConfigView.section.transfer.autospeed.reset=Reset advanced values ConfigView.section.transfer.autospeed.reset.button=Reset PeerColumn.activationCount=Peers trying to connect: %1 TableColumn.header.timesincedownload.info=The time elapsed since data was downloaded for the torrent TableColumn.header.timesincedownload=Down Idle TableColumn.header.timesinceupload.info=The time elapsed since data was uploaded for the torrent TableColumn.header.timesinceupload=Up Idle PeersView.incomingreqcount=In Reqs PeersView.incomingreqcount.info=Count of the incoming requests made by peer PeersView.outgoingreqcount=Out Reqs PeersView.outgoingreqcount.info=Count of the outgoing requests made to peer upnp.mapping.trackerclientudp=UDP Tracker Client Port upnp.mapping.dhtudp=Distributed Database ConfigView.section.connection.nondata.udp.same=Use the same UDP port for the Distributed Database and UDP Tracker ConfigView.section.connection.tcp.enable=Enable TCP ConfigView.section.connection.udp.enable=Enable UDP ConfigView.section.style.showiconbar=Show Toolbar MainWindow.menu.view.iconbar=Toolbar MyTorrentsView.menu.rename=Rename... MyTorrentsView.menu.rename.displayed=Rename Displayed Name MyTorrentsView.menu.rename.save_path=Rename Save Path AdvRenameWindow.title=Rename Download AdvRenameWindow.message=Enter a new name for this download. AdvRenameWindow.rename.torrent=Rename Torrent MyTorrentsView.menu.rename.displayed.enter.title=Rename Displayed Name MyTorrentsView.menu.rename.displayed.enter.message=Enter a new name to display for this download. MyTorrentsView.menu.edit_comment=Edit Comment MyTorrentsView.menu.edit_comment.enter.title=Edit Comment MyTorrentsView.menu.edit_comment.enter.message=Enter a comment for this download. UIDebugGenerator.messageask.title=Debug Generator UIDebugGenerator.messageask.text=Please enter a description of the bug you are reporting UIDebugGenerator.complete.title=Debug Generation Complete UIDebugGenerator.complete.text=The debug file can be found at '%1'.\n\nClick OK to open a filesystem window to this file. ConfigView.section.style.showProgramIcon=Show program icon in name column ConfigView.section.style.showProgramIcon.tooltip=View may need re-opening for changes to take effect swt.alert.cant.update=SWT library loaded from "%3" can't be automatically updated from version %1 to %2 (must be loaded from "%4"). Please see the wiki for details. authenticator.savepassword=Remember my password ConfigView.section.security.clearpasswords=Reset remembered passwords ConfigView.section.security.clearpasswords.button=Reset Content.alert.notuploaded.title=Upload Not Complete Content.alert.notuploaded.text=Upload of '%1' is not complete. If you %2 now, people will not be able to completely download your published work.\n\nAre you sure you want to %2? Content.alert.notuploaded.multi.title=Uploads Not Complete Content.alert.notuploaded.multi.text=%1 of your published content are not completely seeded. If you %2 now, people will not be able to completely download your published work. Are you sure you want to %2?\n\nContent not completely seeded:\n%3 Content.alert.notuploaded.stop=stop Content.alert.notuploaded.quit=quit Vuze TorrentInfoView.torrent.encoding=Torrent encoding TorrentInfoView.columns=Columns from 'My Torrents' view progress.window.title=Operation In Progress progress.window.msg.filemove=Please wait while the file move/rename completes ConfigView.label.popup.timestamp=Add timestamps to popup alerts ConfigView.label.popup.autohide=Automatically hide non-error popup alerts after x seconds (set to 0 to disable auto hiding) ConfigView.label.popup.suppress_alerts=Suppress alerts ConfigView.label.popup.use_message_boxes=Use popup message boxes rather than the standard popup alert box. ConfigView.label.popup.show=Show all popup alerts logged so far (if any) ConfigView.label.popup.show.button=Show ConfigView.label.please.visit.here=Please visit here for details ConfigView.section.ipfilter.enable.descriptionCache=Store IP descriptions in scratch file ConfigView.section.ipfilter.enable.descriptionCache.tooltip=When disabled, descriptions will not be remembered OpenTorrentWindow.filesInfo=%1 of %2 will be downloaded. OpenTorrentWindow.diskUsage=%1 of %2 ConfigView.label.openmytorrents=Open 'My Torrents' on startup ConfigView.label.open_transfer_bar_on_start=Open Transfer Bar on startup ConfigView.section.style.DNDalwaysInIncomplete=Always show torrents with 'Do Not Download' files in Incomplete section of My Torrents OpenTorrentWindow.mb.noGlobalDestDir.title=Destination Directory not found OpenTorrentWindow.mb.noGlobalDestDir.text=The destination directory '%1' is invalid. OpenTorrentWindow.mb.noDestDir.title=Destination Directory not found OpenTorrentWindow.mb.noDestDir.text=The destination directory '%1' for torrent '%2' does not exist or is invalid. OpenTorrentWindow.mb.notValid.title=Open Torrent Failed OpenTorrentWindow.mb.notValid.text=Could not open torrent '%1'. If you are opening in seeding mode, please make sure the torrent data files exist. OpenTorrentWindow.mb.notTorrent.title=Open Torrent Failed OpenTorrentWindow.mb.notTorrent.text=Could not open '%1'. It doesn't appear to be a .torrent file.\n\nSome of the data received:\n%2 ConfigView.label.pause.downloads.on.exit=Pause downloads on exit ConfigView.label.resume.downloads.on.start=Resume paused downloads on start after initialisation completes UIDebugGenerator.message.cancel.title=Generate Debug Info Canceled UIDebugGenerator.message.cancel.text=You did not enter a description of the bug you are trying to report. Your bug may be obvious to you, but without a description, we would only be guessing as to your problem.\n\nGeneration of Debug Information has been cancelled. ConfigView.section.connection.group.http=HTTP ConfigView.section.connection.group.http.info=Support for HTTP seeding. ConfigView.section.connection.http.enable=Enable ConfigView.section.connection.http.port=Incoming port number ConfigView.section.connection.http.portoverride=Tracker HTTP Port override [0: none] window.update.noupdates.title=Check for Updates Results window.update.noupdates.text=There are no new updates available for you.\n\nCongratulations! ConfigView.label.bindip.details=Example: 192.168.1.5;eth0;eth1[2] will bind the specified IP, to all IPs of the 1st interface and the 3rd IP of the 2nd interface.\nThe 1st IP will be used for all services, all others are only used for load balancing.\nThe following interfaces are available:\n%1 ConfigView.label.mindownloads=Min simultaneous downloads UI.cannot_submit_blank_text=You must enter a value. crypto.alert.as.warning=Network '%1' is known to impose traffic shaping to reduce download performance. Transport encryption has automatically been turned on - this can be turned off/modified via configuration parameters. ConfigView.section.interface.alerts=Alerts ConfigView.label.popupdownloadadded=Popup an alert when a download is added popup.download.added="%1" has been added to your download list. MessageBoxWindow.nomoreprompting=Don't prompt me again TorrentOptionsView.param.max.seeds=Maximum number of seed connections [0: connection limit] TorrentOptionsView.param.alternative.value.enable=Alternate value when seeding ConfigView.section.proxy.check.on.start=Check proxy status on startup TransferStatsView.legend.pingaverage=Average TransferStatsView.legend.ping1=Target 1 TransferStatsView.legend.ping2=Target 2 TransferStatsView.legend.ping3=Target 3 ConfigView.section.interface.enabletray._mac=Enable Status Bar Icon [restart required] ConfigView.label.closetotray._mac=Close minimizes to Status Bar Icon ConfigView.label.minimizetotray._mac=Minimize minimizes to Status Bar Icon OpenTorrentWindow.mb.existingFiles.title=File(s) already exist! OpenTorrentWindow.mb.existingFiles.text=Some of the files already exist in the destination folder(s) you specified:\n\n%1\nIf you continue, Vuze will check the above file(s) for correct data and overwrite if necessary. splash.unloadingTorrents=Unloading Torrents splash.unloadingTorrent=Unloading Torrent ConfigView.section.file.defaultdir.autorename=Auto rename torrent data if files in path look different ConfigView.section.file.defaultdir.autorename.tooltip=This prevents one torrent from overwriting another torrent's files when the file names are the same alert.raised.at.close=(Message from previous close of Vuze) Plugin.trackerpeerauth.name=Tracker Peer Authorization Plugin.trackerpeerauth.info=This plugin works with trackers to verify that peers are valid swarm members Peers.column.maxupspeed=Max Up Speed Peers.column.maxdownspeed=Max Down Speed MyTorrents.items.DownSpeedLimit.disabled=No download Peers.column.lan=LAN upnp.selectedaddresses=Addresses (';' seperated, '-' prefix=deny, '+' =allow) [blank: any] upnp.alert.multipledevice.warning=Multiple UPnP devices have been detected - check if all require port mapping (see UPnP log and configuration) UpdateMonitor.messagebox.restart.title=Software Update UpdateMonitor.messagebox.restart.text=Vuze just completed downloading an important update and must now be restarted so that the update can be installed. PiecesView.BlockView.Have=Have PiecesView.BlockView.NoHave=Don't Have PiecesView.BlockView.Header=%1 column(s), %2 row(s), %3 pieces ConfigView.section.update.autodownload=Auto download updates and prompt when installation is ready Peers.column.peer_id=Peer ID Peers.column.peer_id.info=Peer ID in readable form Peers.column.peer_byte_id=Peer ID Peers.column.peer_byte_id.info=Peer ID in byte form Peers.column.handshake_reserved=Handshake Reserved Bytes Peers.column.handshake_reserved.info=Indicates what reserved bits were set in the BT handshake Peers.column.client_identification=Client Identification Peers.column.client_identification.info=Indicates the raw client names received by Vuze - useful for debugging dht.warn.user=Warn of potential NAT/port mapping problems ConfigView.label.openbar.incomplete=Download bars: auto open downloads ConfigView.label.openbar.complete=auto open seeds ConfigView.label.transferbar.remember_location=Remember last location of transfer bar ConfigView.section.transfer.autospeed.forcemin=%1 upload speed forced when baselining connection MainWindow.menu.tools.speedtest=Speed Test... speedtest.wizard.title=Speed Test speedtest.wizard.run=Run a speed test speedtest.wizard.test.mode.updown=upload and download speedtest.wizard.test.mode.up=upload speedtest.wizard.test.mode.down=download SpeedTestWizard.test.panel.currinfo=BitTorrent bandwidth testing. SpeedTestWizard.test.panel.label=Vuze speed test: SpeedTestWizard.test.panel.already.running=Test already running! SpeedTestWizard.test.panel.not.accepted=Test request not accepted: SpeedTestWizard.test.panel.abort=Abort SpeedTestWizard.test.panel.abort.countdown=abort test in: SpeedTestWizard.test.panel.test.countdown=test finish in: SpeedTestWizard.test.panel.testfailed=Test failed SpeedTestWizard.test.panel.aborted=Test aborted manually. SpeedTestWizard.test.panel.enc.label=Press to test with encryption: SpeedTestWizard.test.panel.standard=standard SpeedTestWizard.test.panel.encrypted=encrypted SpeedTestWizard.set.upload.button.apply=Apply SpeedTestWizard.set.upload.result=Last Test Result SpeedTestWizard.set.upload.bytes.per.sec=kBytes/sec SpeedTestWizard.set.upload.bits.per.sec=bits/sec SpeedTestWizard.finish.panel.title=Speed Test Finished! SpeedTestWizard.finish.panel.click.close=You have finished the speed test wizard. Click close to exit. SpeedTestWizard.finish.panel.max.upload=Max upload : SpeedTestWizard.finish.panel.max.seeding.upload=Max upload while seeding : SpeedTestWizard.finish.panel.max.download=Max download : SpeedTestWizard.finish.panel.enabled=enabled SpeedTestWizard.finish.panel.disabled=disabled SpeedTestWizard.abort.message.scheduled.in=test scheduled in ... %1 seconds SpeedTestWizard.abort.message.unsupported.type=Unsupported test type!!!! SpeedTestWizard.abort.message.manual.abort=Manually aborted SpeedTestWizard.abort.message.scheduling.failed=Scheduling of the test failed SpeedTestWizard.abort.message.download.added=Download %1 added during test SpeedTestWizard.abort.message.entered.error=Test download entered error state '%1' SpeedTestWizard.abort.message.entered.queued=Test downloaded entered queued/stopped state SpeedTestWizard.abort.message.interrupted=TorrentSpeedTestMonitorThread was interrupted before test completed SpeedTestWizard.abort.message.execution.failed=Test execution failed SpeedTestWizard.abort.message.failed.peers=Failed to connect to any peers SpeedTestWizard.abort.message.insufficient.slots=Could not upload to any of the peers - insufficient upload slots? SpeedTestWizard.abort.message.not.unchoked=Could not download from any of the peers as never unchoked by them SpeedTestWizard.stage.message.requesting=requesting test... SpeedTestWizard.stage.message.preparing=preparing test... SpeedTestWizard.stage.message.starting=starting test... SpeedTestWizard.stage.message.connect.stats=Connection stats: peers=%1, down_ok=%2, up_ok=%3 window.uiswitcher.title=Vuze UI Chooser window.uiswitcher.text=Please select a user interface below that best suits your needs. window.uiswitcher.NewUI.title=Vuze window.uiswitcher.NewUI.text=* Recommended for beginners and new users.\n\n* Easy, intuitive graphical interface\n\n* Required interface to publish on Vuze platform window.uiswitcher.ClassicUI.title=Classic Interface window.uiswitcher.ClassicUI.text=* Retains functionality of 2.x series client\n\n* Vuze content layer will not be loaded window.uiswitcher.bottom.text=Your selection can easily be changed again by selecting the Vuze UI Chooser button iconBar.switch.tooltip=Vuze UI Chooser VivaldiView.notAvailable=Vivaldi View not available restart.error=Restart failed:\n%1\nSee restarting issues. restart.error.url=http://www.azureuswiki.com/index.php/Restarting_Issues restart.error.oom=Out of Memory restart.error.fnf='%1' not found in '%2' restart.error.pnf=Path '%1' not found restart.error.bad=Bad file format for '%1' restart.error.denied=Access was denied when trying to run '%1'. Make sure you have rights to run this program. TableColumn.header.date_completed=Completed On TableColumn.menu.date_added.reset=Reset Date ConfigView.section.ipfilter.discardbanning=Block peers whose discarded data/good data ratio exceeds [0: disabled] ConfigView.section.ipfilter.discardminkb=Minimum %1 discarded before applying ratio ConfigView.interface.start.advanced=Start in Advanced View (AZ 2.x) MyTorrents.column.ColumnQuality=Quality MyTorrents.column.ColumnSpeed=Speed MyTorrents.column.ColumnProgressETA.2ndLine=ETA: %1 MyTorrents.column.ColumnProgressETA.StreamReady=Streaming Ready MyTorrents.column.ColumnProgressETA.PlayableIn=Playable in %1 TableColumn.header.Quality=Quality TableColumn.header.Speed=Speed TableColumn.header.RateIt=Rate TableColumn.header.Rating=Rating TableColumn.header.SpeedGraphic=Speed TableColumn.header.AzProduct=From TableColumn.header.MediaThumb=Media TableColumn.header.ProgressETA=Progress TableColumn.header.name.ext=File Type: %1 TableColumn.header.DateCompleted={TableColumn.header.date_completed} v3.MainWindow.tab.home=Dashboard v3.MainWindow.tab.browse=On Vuze v3.MainWindow.tab.library=Library v3.MainWindow.tab.publish=Publish v3.MainWindow.tab.advanced=Advanced v3.MainWindow.menu.home=&Dashboard v3.MainWindow.menu.browse=&On Vuze v3.MainWindow.menu.library=&Library v3.MainWindow.menu.publish=&Publish v3.MainWindow.menu.advanced=&Advanced v3.MainWindow.menu.view.searchbar=Search Bar v3.MainWindow.menu.view.tabbar=Tab Bar v3.MainWindow.currentDL=Currently Downloading v3.MainWindow.button.stream=Stream v3.MainWindow.button.stop=Stop v3.MainWindow.button.start=Start v3.MainWindow.button.pause=Pause v3.MainWindow.button.resume=Resume v3.MainWindow.button.delete=Delete v3.MainWindow.button.comment=Comment v3.MainWindow.button.viewdetails=View Details v3.MainWindow.button.play=Play v3.MainWindow.button.cancel=Cancel v3.MainWindow.button.preview=Preview v3.MainWindow.view.wait=Initializing view, please wait. v3.MainWindow.xofx=%1 of %2 v3.MainWindow.Loading=Loading.. Please Wait v3.filter-bar=Title Filter: v3.MainWindow.search.defaultText=find... v3.mb.delPublished.title=Stop Seeding Content v3.mb.delPublished.text=WARNING: This action will NOT remove your published content '%1' from \ %3 .\ \n\n\ Click "Delete" only if you want your content to remain published \ and downloadable, but want to free up your bandwidth. \ Make sure the upload process has been completed before you do so \ (how?).\ \n\n\ Click "Cancel" if you want to completely remove your published content from %3, \ and use the (X) button on the Published Content panel in the Publish tab.\ \n\n\ More help.\ \n\n v3.mb.delPublished.delete=&Delete v3.mb.delPublished.cancel=&Cancel v3.mb.openFile.title=Open File v3.mb.openFile.text.known=This content is not currently supported by the Vuze Player. Check the community-created Playback Guide for help.\n\nFile Type Appears to be: %2 (%3)\n v3.mb.openFile.text.unknown=This content is not currently supported by the Vuze Player. Check the community-created Playback Guide for help.\n\nFile Extension : %2\n v3.mb.openFile.button.play=Play v3.mb.openFile.button.cancel=Cancel v3.mb.openFile.button.guide=Read Playback Guide v3.mb.openFile.remember=Always open files without asking me v3.mb.openFile.guideurl=http://www.azureuswiki.com/index.php/Playback_Guide v3.mb.PlayFileNotFound.title=File Not Found v3.mb.PlayFileNotFound.text=The files for '%1' are either deleted or missing. v3.mb.PlayFileNotFound.button.remove=Remove from Vuze v3.mb.PlayFileNotFound.button.redownload=Redownload Data v3.mb.PlayFileNotFound.button.find=Manually Find.. v3.mb.deletePurchased.title=Remove Purchased Content v3.mb.deletePurchased.text=Are you sure you want to delete the content '%1'?\ \n\n\ This is content you either purchased, or you were required to login to download. v3.mb.deletePurchased.button.delete=&Delete v3.mb.deletePurchased.button.cancel=&Cancel v3.topbar.menu.show.logo=Logo v3.topbar.menu.show.plugin=Plugin Area v3.topbar.menu.show.search=Search v3.topbar.menu.show.frog=Da Blue Frog splash.initializeCore=Initializing Core splash.initializeUIElements=Initializing UI Elements ConfigView.section.transfer.autospeedbeta=Auto-Speed-Beta ConfigView.section.ipfilter.peerblocking.group=Peer Blocking ConfigView.section.ipfilter.autoload.group=Auto Loading ConfigView.section.ipfilter.autoload.file=IP filter file to autoload ConfigView.section.ipfilter.autoload.info=Supports DAT (eMule), P2P (PeerGuardian, splist), and P2B v1,2,3 (PeerGuardian 2) formats. \ File can be local or URL, zip'd, gzip'd or plain text. \ URLs will automatically redownload after 7 days, whereas files will reload within a minute of being replaced/touched. ConfigView.section.ipfilter.autoload.loadnow=Load Now splash.loadIpFilters=Loading IP Filters.. SpeedTestWizard.set.upload.title=Set Upload and Download Limits SpeedTestWizard.set.download.label=Download Speed Limit: SpeedTestWizard.set.upload.label=Upload Speed Limit: SpeedTestWizard.name.conf.level.absolute=Absolute SpeedTestWizard.name.conf.level.high=High SpeedTestWizard.name.conf.level.med=Medium SpeedTestWizard.name.conf.level.low=Low SpeedTestWizard.name.conf.level.none=None ConfigView.section.transfer.select=Auto-Speed ConfigView.section.transfer.select.v2=Auto-Speed (beta) mb.azmustclose.title=Startup Error mb.azmustclose.text=Vuze must quit due to a problem (re)starting Vuze that \ most likely caused the program to be run as an Administrator user.\n\n\ After Vuze closes, please re-open manually. network.ipv6.prefer.addresses=Prefer IPv6 addresses when both IPv6 and IPv4 are available network.bindError=Binding server socket failed as no compatible addresses are available, please check your bind-to-IP settings. network.enforce.ipbinding=Enforce IP bindings even when interfaces are not available, prevents any connections if none of the specified interfaces are available DHTView.title.full_v6=Distributed Database IPv6 ConfigView.pluginlist.loadSelected=Load Selected SpeedView.stats.asn=Network: SpeedView.stats.estupcap=Upload limit: SpeedView.stats.estdowncap=Download limit: SpeedView.stats.unknown=Unknown SpeedView.stats.estimate=Estimate SpeedView.stats.measured=Measured SpeedView.stats.measuredmin=Measured Min SpeedView.stats.manual=Fixed ConfigView.section.transfer.autospeed.networks=Network Details ConfigView.section.transfer.autospeed.resetnetwork=Reset network details ConfigView.section.transfer.autospeed.network.info=The above limits are normally calculated automatically during download or are the result of a speed test. If you want to manually specify them use the options below.\nAll limits other than 'fixed' will subsequently be automatically adjusted if needed. \nEnter the value and then select its type. Note that speeds are in %1. dialog.uiswitcher.restart.title=UI Switcher: Vuze Restart Required dialog.uiswitcher.restart.text=Vuze needs to restart in order to switch to the new UI mode. TrayWindow.menu.close=Close Download Basket # Used for peers which we can't determine. PeerSocket.unknown=Unknown PeerSocket.fake_client=FAKE PeerSocket.bad_peer_id=bad peer ID PeerSocket.mismatch_id=mismatch PeerSocket.unknown_az_style=Unknown %1 %2 PeerSocket.unknown_shadow_style=Unknown %1 %2 OpenTorrentWindow.mb.askCreateDir.title=Destination Directory does not exist OpenTorrentWindow.mb.askCreateDir.text=The destination directory '%1' does not exist.\n\nCreate now? SpeedView.stats.estimatechoke=Estimate (choke) ConfigTransferAutoSpeed.upload.capacity.usage=Upload Capacity Usage ConfigTransferAutoSpeed.mode=Mode: ConfigTransferAutoSpeed.capacity.used=% Capacity Used ConfigTransferAutoSpeed.while.downloading=Downloading: ConfigTransferAutoSpeed.set.dht.ping=DHT Ping Setting: ConfigTransferAutoSpeed.set.point=set point (ms) ConfigTransferAutoSpeed.set.tolerance=tolerance (ms) ConfigTransferAutoSpeed.ping.time.good=Good: ConfigTransferAutoSpeed.ping.time.bad=Bad: ConfigTransferAutoSpeed.adjustment.interval=Adjustment interval: ConfigTransferAutoSpeed.skip.after.adjust=Skip after adjustment: GeneralView.label.distributedCopies=Distributed Copies: PiecesView.DistributionView.title=Piece Distribution PiecesView.DistributionView.NoAvl=Unavailable Pieces PiecesView.DistributionView.SeedAvl=Seed Avl Contribution PiecesView.DistributionView.PeerAvl=Peer Avl Contribution PiecesView.DistributionView.RarestAvl=Rarest Pieces: %1 (Avl:%2) PiecesView.DistributionView.weHave=Pieces you have PiecesView.DistributionView.theyHave=Pieces peer has PiecesView.DistributionView.weDownload=Pieces you're downloading PeersView.gain = Gain PeersView.gain.info = Amount of downloaded - uploaded data unix.script.new.title=New Vuze Startup Script available unix.script.new.text=A new Vuze startup script is available, and has been saved to '%1'.\n\n\ It is highly recommended that you quit Vuze now and switch to this script \ ('%2').\ \n\n\ If you have heavily modified your Vuze startup script, please see \ AzureusWiki: Unix Script.\ \n\n\ If you installed Vuze from a distro (yum, apt-get, etc), \ it's recommended you re-install Vuze using the package on \ Vuze Sourceforge Page \ (You will still get the same UI you have now) unix.script.new.manual.url=http://azureuswiki.com/index.php/Unix_Startup_Script unix.script.new.button.quit=Quit Now unix.script.new.button.continue=I'll Do It Later unix.script.new.button.asknomore=Don't Tell Me Again unix.script.new.auto.title=New Vuze Startup Script unix.script.new.auto.text=A new Vuze Startup Script is available.\n\n\ It is highly recommended that you restart Vuze now. Content.alert.notuploaded.button.stop=&Stop Content.alert.notuploaded.button.continue=&Continue Seeding Content.alert.notuploaded.button.abort=&Don't Quit ConfigView.label.checkOnSeeding=Perform low resource re-check of pieces when seeding ConfigView.label.ui_switcher=Display Vuze UI Chooser ConfigView.label.ui_switcher_button=Show SpeedTestWizard.test.panel.explain=Measure your Vuze protocol speed. Select the speed test type and the encryption mode. Visit the Vuze wiki page for details about this test. The test will stop automatically if it takes longer than two minutes. Typical tests finish in less than a minute. SpeedTestWizard.set.upload.hint=Set the upload and download limits used by Vuze AutoSpeed algorithm. SpeedTestWizard.set.upload.panel.explain=The limits set here are used by the Vuze AutoSpeed algorithm. Set the transfer limits and the confidence limits.\n\nNote that line speeds are often quoted in "bits per second" - however the value below is shown in "kilobytes per second". SpeedTestWizard.set.limit.conf.level=Confidence SpeedTestWizard.finish.panel.auto.speed=AutoSpeed is : SpeedTestWizard.finish.panel.auto.speed.seeding=AutoSpeed while seeding is : ConfigTransferAutoSpeed.add.comment.to.log.group=Add comment to debug log ConfigTransferAutoSpeed.add.comment.to.log=Add comment: ConfigTransferAutoSpeed.log.button=Log ConfigTransferAutoSpeed.algorithm.selector=Auto-Speed selector ConfigTransferAutoSpeed.algorithm=Algorithm: ConfigTransferAutoSpeed.auto.speed.classic=Auto-Speed(classic) ConfigTransferAutoSpeed.auto.speed.beta=Auto-Speed(beta) ConfigTransferAutoSpeed.data.update.frequency=Update Frequency Alert.failed.update=Installation of at least one component failed. See AzureusWiki: Failed Update [%1] Alert.failed.update.url=http://azureuswiki.com/index.php/Failed_Update OpenTorrentWindow.mb.existingFiles.partialList= (Partial list. More files already exist) TableColumn.header.bad_avail_time.info=Last time that a full copy of the download was available TableColumn.header.bad_avail_time=Full Copy Seen MyTorrentsView.menu.exporthttpseeds=Export HTTP seed URLs to clipboard SWT.alert.erroringuithread=An unhandled error occurred in the GUI, further errors may be reported. ConfigView.label.minannounce=Minimum time between tracker announces in seconds ConfigView.label.maxnumwant=Limit the number of peers the tracker may return ConfigView.label.announceport=Override announced TCP port for tracker announces, pex and dht\n[leave empty: no override, 0: no incoming connections] ConfigView.label.noportannounce=Do not announce the listening port to the tracker (this does not affect pex, dht) ConfigView.label.maxseedspertorrent=Max seeds per torrent default [0: unlimited] wizard.webseed=Add HTTP Seeds to the torrent wizard.webseed.title=HTTP Seeds wizard.webseed.configuration=HTTP Seed Configuration wizard.webseed.adding=Adding HTTP Seeds GeneralView.label.private=Private Torrent: GeneralView.yes=Yes GeneralView.no=No ConfigView.label.userequestlimiting=Use request throttling instead of delayed reads to limit download speed [no effect when download speed is unlimited] ConfigView.label.userequestlimiting.tooltip=Request limiting is not as smooth as delayed reads, but allows for download priorization based on the download queue position and might improve network performance ConfigView.label.userequestlimitingpriorities=Focus download speed on the head of the downloading queue when download speed limit reached ConfigView.section.logging.timestamp=Timestamp format for log files Peers.column.timetocomplete=Time Remaining Peers.column.timetocomplete.info=Time remaining until the peer is complete ConfigView.section.interface.display.suppress.file.download.dialog=Suppress File Download popup dialog ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Show all file download progress in the status bar instead of a popup dialog FileDownload.canceled=A torrent file download has been successfully canceled by a user action: %1 Progress.reporting.status.canceled=Canceled Progress.reporting.status.finished=Finished Progress.reporting.status.retrying=Retrying... Progress.reporting.action.label.retry.tooltip=Retry the operation Progress.reporting.action.label.remove.tooltip=Remove this Progress Report from history Progress.reporting.action.label.cancel.tooltip=Cancel the operation Progress.reporting.action.label.detail=Details Progress.reporting.default.error=Failed Progress.reporting.no.reports.to.display=There are no progress reports to display at this time. Progress.reporting.no.history.to.display=There are no detail messages to display. Progress.reporting.detail.history.limit=The detail message limit (%1) for this ProgressReporter has been exceeded; subsequent messages will not be added to history Progress.reporting.statusbar.button.tooltip=Show the Progress Reporting Window webui.bindip=Bind IP - normally not required (*) v3.MainWindow.text.log.in=Sign In v3.MainWindow.text.log.out=Sign Out v3.MainWindow.text.get.started=Sign Up v3.MainWindow.text.my.account=Account Info v3.MainWindow.text.my.profile=Profile OpenTorrentWindow.simple.open=Torrent Location (File, URL, Hash) Progress.reporting.window.remove.auto=Automatically remove inactive items Progress.reporting.window.remove.auto.tooltip=Automatically remove all completed, failed, or canceled processes from the view Progress.reporting.window.remove.now=Remove inactive items Progress.reporting.window.remove.now.tooltip=Remove all completed, failed, or canceled processes from the view dhttracker.tracklimitedwhenonline=However, perform low resource tracking when online for swarm cross-population TorrentOptionsView.multi.title.short=Torrent Options TorrentOptionsView.multi.title.full=Torrent Options MyTorrentsView.menu.open_parent_folder=Open Containing Folder ConfigView.section.style.use_show_parent_folder=Use "%1" instead of "%2" in torrent menus ConfigView.section.style.use_show_parent_folder.tooltip=Enabling this option will allow you to open the containing folder in the correct file manager application.\nHowever, it may mean that the download save location isn't automatically selected. PeerManager.status.ps_disabled=Tracker peer source is disabled ConfigView.section.stats.exportfiles=Export file details updater.cant.write.to.app.title=Can't Write To Application Folder updater.cant.write.to.app.details=The folder "%1" is not writable.\n\nThis will prevent future software updates from being applied.\n\nPlease see the wiki for details. plugin.install.class_version_error=This plugin requires a newer version of Java to run. v3.MainWindow.tab.minilibrary=Downloads v3.MainWindow.tab.events=Notifications button.columnsetup.tooltip=Column Setup v3.activity.remove.title=Delete Notification v3.activity.remove.text=Are you sure you want to delete this Notification?\n%1 v3.MainWindow.menu.file.closewindow=Close v3.MainWindow.menu.file.closewindow.keybinding=Meta+W Menu.show.torrent.menu=Show the Torrents menu Menu.show.torrent.menu.tooltip=Shows the Torrents menu on the top application menu bar Views.plugins.aznetstatus.title=Network Status plugin.aznetstatus.pingtarget=Ping/trace route target ConfigView.section.style.usePathFinder=Use 'Path Finder' instead of 'Finder' menu.sortByColumn=Sort By %1 MyTorrentsView.menu.manual.per_peer=Manual (per peer) MyTorrentsView.menu.manual.shared_peers=Manual (across peers) v3.button.removeActivityEntry=Remove Notification v3.splash.initSkin=Initializing UI Skin v3.splash.hookPluginUI=Hooking in Plugin UI OpenTorrentWindow.mb.notTorrent.cannot.display=Unable to properly display the data MainWindow.menu.window.zoom.maximize=Maximize MainWindow.menu.window.zoom.restore=Restore ImageResizer.image.too.small=The image provided is too small, please choose a different one (has to be at least %1 x %2) ImageResizer.title=This tool lets you preview how your thumbnail is going to look like on the Vuze Platform ImageResizer.move.image=Move the image by dragging it ImageResizer.move.image.with.slider=Move the image by dragging it, resize it by using the slider below security.crypto.title=Encryption Key Access security.crypto.encrypt=Please enter a password to protect your newly generated encryption key. Please do not forget this password, there is no way of recovering it if you do! security.crypto.decrypt=Please enter the password to unlock your encryption key. security.crypto.reason=Reason for operation security.crypto.password=Password security.crypto.password2=Re-enter password security.crypto.persist_for=Password persistence period security.crypto.persist_for.dont_save=Don't save security.crypto.persist_for.session=This session security.crypto.persist_for.day=1 day security.crypto.persist_for.week=1 week security.crypto.persist_for.30days=30 days security.crypto.persist_for.forever=Forever security.crypto.password.mismatch.title=Password Error security.crypto.password.mismatch=Password values entered do not match, please re-enter. ConfigView.section.security.group.crypto=Public/Private Keys ConfigView.section.security.resetkey=Reset keys ConfigView.section.security.resetkey.warning.title=Data Loss Warning ConfigView.section.security.resetkey.warning=Are you sure you want to reset your encryption keys? If you do all information encrypted using them will be PERMANENTLY LOST. Also any other peers in possesion of your public key will no longer be able to communicate with you without them obtaining your new key. So, unless you really know what you are doing, don't do this. ConfigView.section.security.unlockkey=Explicitly unlock keys ConfigView.section.security.unlockkey.button=Unlock ConfigView.section.security.publickey=Public key ConfigView.section.security.publickey.undef=Not yet defined ConfigView.section.security.resetkey.error.title=Operation Failed ConfigView.section.security.resetkey.error=Failed to reset keys ConfigView.section.security.unlockkey.error=Failed to unlock key - password incorrect ConfigView.copy.to.clipboard.tooltip=Copy to clipboard Views.plugins.azbuddy.title=Friends Browser.popup.error.no.access=An error has occurred while attempting to access a remote resource.\nPlease try again at a later time.\n ConfigView.label.queue.stoponcebandwidthmet=Don't start any more torrents when upload/download speed limit is reached ConfigView.section.style.forceMozilla=Force Vuze to use Mozilla for Browser widgets [xulrunner or firefox 3 required; restart required] ConfigView.section.style.xulRunnerPath=Specify XulRunner / Firefox path manually [required for FF3; restart required] azbuddy.name=Friends azbuddy.enabled=Enabled azbuddy.disabled=Plugin is disabled, see plugin config to change. azbuddy.nickname=Your Nickname azbuddy.msglog.title=Friend Information azbuddy.addtorrent.title=Accept Download? azbuddy.addtorrent.msg=Friend '%1' has sent you '%2'.\nDo you want to add this download? azbuddy.contextmenu=Send To Friend azbuddy.ui.mykey=My key: azbuddy.ui.add=Add azbuddy.ui.new_buddy=New friend key: azbuddy.ui.table.name=Name azbuddy.ui.table.online=Online azbuddy.ui.table.last_ygm=YGM azbuddy.ui.table.last_msg=Last Message azbuddy.ui.menu.remove=Remove azbuddy.ui.menu.copypk=Copy Public Key azbuddy.ui.menu.send=Send Message azbuddy.ui.menu.send_msg=Enter the text to send to your friend(s) azbuddy.ui.menu.ping=Ping azbuddy.ui.menu.ygm=Send YGM azbuddy.ui.menu.enc=Encrypt Clipboard azbuddy.ui.menu.dec=Decrypt Clipboard azbuddy.ui.menu.sign=Sign Clipboard azbuddy.ui.menu.verify=Verify Clipboard azbuddy.ui.table.lastseen=Last Seen Button.retry=&Retry Button.ignore=&Ignore DHTView.general.skew=Skew: azbuddy.ui.table.msg_in=Msg In azbuddy.ui.table.msg_out=Msg Out v3.MainWindow.menu.view.footer=Footer azbuddy.downspeed=KB/s max friend download speed [0: unlimited] azbuddy.ui.table.con=Con azbuddy.ui.table.ss=SS security.crypto.badpw=The password supplied was incorrect ConfigView.section.security.backupkeys=Backup keys to a file ConfigView.section.security.backupkeys.button=Backup ConfigView.section.security.restorekeys=Restore keys from a file ConfigView.section.security.restorekeys.button=Restore ConfigView.section.security.op.error.title=Operation Failed ConfigView.section.security.op.error=Failed to complete the operation:\n %1 ConfigView.section.security.restart.title=Restart Required ConfigView.section.security.restart.msg=Vuze will now restart to complete the operation. ConfigView.section.security.system.managed=System managed key protection azbuddy.ui.table.msg_queued=Queued azbuddy.ui.menu.chat=Chat azbuddy.chat.title=Vuze Chat azbuddy.chat.says=%1 says: Button.bar.show=Show Button.bar.hide=Hide Button.bar.share=Share Button.bar.add=Add Button.bar.edit=Edit Button.bar.edit.cancel=Done Editing v3.MainWindow.menu.view.pluginbar=Plugin Bar MainWindow.dialog.select.vuze.file=Select Vuze File MainWindow.menu.file.open.vuze=Vuze File... metasearch.addtemplate.title=Install Search Template? metasearch.addtemplate.desc=Are you sure you want to install a search template named '%1'? v3.share.private.title=Sharing Torrent v3.share.private.text=The selected torrent is marked as a Private Torrent.\n\nYou can not share private torrents. metasearch.addtemplate.dup.title=Duplicate Template metasearch.addtemplate.dup.desc=Search template %1 is already installed metasearch.export.select.template.file=Save Template metasearch.import.select.template.file=Open Template dialog.uiswitch.title=Switch to Vuze UI dialog.uiswitch.text=You need to be running the Vuze UI to use this feature.\n\nVuze will need to restart. dialog.uiswitch.button=Switch to the Vuze UI azbuddy.tracker.enabled=Enable 'Friends Boost' to prioritise downloading with your friends azbuddy.protocolspeed=KB/s max friend protocol overhead v3.MainWindow.button.download=Download v3.MainWindow.button.run=Launch Downloaded File v3.activity.header.downloads=Downloads v3.activity.header.vuze.news=Vuze News message.taking.too.long=It appears that this is taking longer than expected\nPress 'ESC' if you wish to cancel this operation message.status.success=Success azbuddy.tracker.bbb.status.title=Friend Boost azbuddy.tracker.bbb.status.title.tooltip=Double-click for details azbuddy.tracker.bbb.status.idle=No Boosting azbuddy.tracker.bbb.status.nli=Login Required azbuddy.tracker.bbb.status.in=I'm Being Boosted azbuddy.tracker.bbb.status.out=Currently Boosting Friends v3.MainWindow.search.go.tooltip=Execute Search v3.MainWindow.search.last.tooltip=Return to search results metasearch.addtemplate.done.title=Template Added metasearch.addtemplate.done.desc=Template '%1' added successfully.\nIt will be used when you next search! ConfigView.section.security.nopw=No password was supplied ConfigView.section.security.nopw_v=No password available, please sign into Vuze fileplugininstall.install.title=Install Plugin? fileplugininstall.install.desc=Are you sure you want to install plugin '%1', version %2? fileplugininstall.duplicate.title=Duplicate Plugin fileplugininstall.duplicate.desc=Plugin '%1', version %2 is already installed azbuddy.online_status=Online Status azbuddy.os_online=Online azbuddy.os_away=Away azbuddy.os_not_avail=Not Available azbuddy.os_busy=Busy azbuddy.os_offline=Offline azbuddy.ui.menu.disconnect=Disconnect azbuddy.enable_chat_notif=Enable chat notifications progress.window.msg.progress=Please wait while the operation completes ConfigView.section.connection.advanced.read_select=Read select timeout (millis, default %1) ConfigView.section.connection.advanced.read_select_min=Read select minimum wait (millis, default %1) ConfigView.section.connection.advanced.write_select=Write select timeout (millis, default %1) ConfigView.section.connection.advanced.write_select_min=Write select minimum wait (millis, default %1) DetailedListView.title=Detailed List ConfigView.section.connection.network.max.outstanding.connect.attempts=Max outstanding outbound connections plugins.init.force_enabled=Vuze has detected the plugin "%1" was disabled - it has been re-enabled to allow Vuze to work properly. ConfigView.section.connection.prefer.udp=Prefer UDP connections subscript.add.title=Install Subscription? subscript.add.desc=Are you sure you want to install subscription '%1'? subscript.add.dup.title=Duplicate Subscription subscript.add.dup.desc=Subscription '%1' is already installed. subscript.add.upgrade.title=Upgrade Subscription? subscript.add.upgrade.desc=Are you sure you want to upgrade subscription '%1'? subscript.add.upgradeto.desc=Version %1 of subscription '%2' is available.\nDo you want to update? azsubs.contextmenu.addassoc=Add subscription association azsubs.contextmenu.lookupassoc=Lookup subscription associations iconBar.start=Start iconBar.stop=Stop iconBar.remove=Delete iconBar.up=Up iconBar.down=Down iconBar.run=Launch iconBar.editcolumns=Column Setup iconBar.top=Move top iconBar.bottom=Move bottom iconBar.queue=Start iconBar.open=Add Torrent iconBar.share=Share iconBar.share.tooltip=Share Content iconBar.details=Details iconBar.comment=Comment iconBar.play=Play iconBar.queue.tooltip=Start (queue) selected torrents v3.MainWindow.menu.view.sidebar=Side Bar v3.MainWindow.menu.view.sidebar.keybinding=F7 v3.MainWindow.menu.view.actionbar=Action Bar v3.MainWindow.menu.view.toolbars=Tool Bars ump.install=Quick Update In Progress:\nInstalling a small playback add-on required for this video. subscriptions.listwindow.title=Subscriptions Finder subscriptions.listwindow.autochecktext=Vuze can find subscriptions related to content in your Library. Do you want to enable this feature? subscriptions.listwindow.loadingtext=Looking for subscriptions related to %1 subscriptions.listwindow.failed=No subscription Found subscriptions.listwindow.popularity=Popularity subscriptions.listwindow.popularity.unknown=Unknown subscriptions.listwindow.name=Name subscriptions.listwindow.subscribe=Subscribe TableColumn.header.azsubs.ui.column.subs=Subscribe subscriptions.listwindow.popularity.reading=Reading... PluginDeprecation.log.start=This window contains information about plugins using functionality that will be \ removed in future versions of Vuze.\nYou don't need to uninstall the plugins, you should just update to the \ plugin to the latest version.\nIf you are running the latest version, then please copy the contents of this \ window and post it in the forum located here:\n \ \t%1\n\n PluginDeprecation.log.details=---------\nIDENTIFIER: %1\nCONTEXT: %2\n\n*** BEGIN TRACE ***\n%3*** END TRACE ***\n\n PluginDeprecation.view=Plugin Debug PluginDeprecation.alert=A plugin has tried to use functionality which will be removed in future - \ please open the Plugin Debug log view for more information. TableColumn.header.Thumbnail=Icon TableColumn.header.Thumbnail.info=The thumbnail image for Vuze content; for all other content the operating system is providing these icons. v3.MainWindow.menu.getting_started=&Getting Started MainWindow.menu.community=&Community MainWindow.menu.help.faq=&Frequently Asked Questions (FAQ) MainWindow.menu.help.faq.keybinding.mac=Meta+? MainWindow.menu.community.wiki=Community &Wiki MainWindow.menu.community.forums=Community Fo&rums MainWindow.menu.community.blog=Vuze &Blog MainWindow.menu.help.support=&Help and Support externalLogin.title=Login Required externalLogin.explanation=The template "%1" requires you to login. Once logged-in this window will automatically close. If it doesn't please click on "done". externalLogin.explanation.capture=You need to Login in order to create this template. Once you are, please click on "Done". Button.done=Done GeneralView.torrent_created_on_and_by=%1 by %2 Button.continue=Continue Button.preview=Preview Subscription.menu.forcecheck=Update Now Subscription.menu.clearall=Mark All Results As Read Subscription.menu.remove=Delete sidebar.Library=My Library sidebar.LibraryDL=Downloading sidebar.LibraryCD=Completed MySeeders.bigView.header={sidebar.LibraryCD} MyTorrents.bigView.header={sidebar.LibraryDL} authenticator.location=Location authenticator.details=Details v3.MainWindow.menu.showActionBarText=Show Text subscript.import.fail.title=Import Failed subscript.import.fail.desc=Details: %1 Subscription.menu.export=Export subscript.export.select.template.file=Save Subscription Button.remove=Remove Button.send=Send Button.back=Back sidebar.LibraryUnopened=Unwatched TableColumn.header.unopened=New Unopened.bigView.header=New Subscription.menu.deleteall=Delete All Results Subscription.menu.reset=Reset To Initial State ConfigView.section.Subscriptions=Subscriptions subscriptions.config.maxresults=Maximum number of results retained per subscription [0: unlimited] v3.activity.button.readall=Mark All Read TableColumn.header.activityNew=New TableColumn.header.activityType=Type TableColumn.header.activityText=Message TableColumn.header.activityDate=Date Added TableColumn.header.activityActions=Actions Subscription.menu.resetauth=Reset Authentication Details Search.menu.engines=Templates Wizard.Subscription.title=Subscribe Wizard.Subscription.optin.title=Enable Subscriptions Wizard.Subscription.subscribe.title=Available Subscriptions Wizard.Subscription.create.title=Create New Subscription Button.search=Search Button.save=Save Button.add=Add Button.createNewSubscription=Create New Subscription Button.availableSubscriptions=Available Subscriptions Wizard.Subscription.optin.description=With Subscriptions enabled, Vuze will show you subscriptions related to the content in your Library, and will let you know when your subscribed content is available for download.\n\nWould you like to turn on Subscriptions? Wizard.Subscription.create.rss=RSS Wizard.Subscription.create.search=Search Wizard.Subscription.search.subtitle1=Type in a search to start creating your subscription : Wizard.Subscription.search.subtitle2=What can I search for? Wizard.Subscription.search.subtitle2.sub1=HD Movies, TV Shows, Films, Trailers on the Vuze Network Wizard.Subscription.search.subtitle2.sub2=Torrents from across the Web Wizard.Subscription.search.subtitle3=Once your subscription is completed, you'll receive live updates in your sidebar whenever new results are available for your search. Wizard.Subscription.rss.subtitle1=Type or paste the URL below: Wizard.Subscription.rss.subtitle2=Many publishers provide RSS feeds of their content. Locate URL on the publisher website, copy and paste the URL into the field above, then click Save. Wizard.Subscription.rss.subtitle3=Once saved, you'll receive live updates in your sidebar whenever new results are available via your RSS feed. Wizard.Subscription.subscribe.library=Content in your Library Wizard.Subscription.subscribe.subscriptions=Related Subscriptions Wizard.Subscription.subscribe.library.empty=No subscriptions available?\n \nLook for the bright orange subscribe button on the Vuze HD Network.\n \nRead more message.confirm.delete.title=Confirm Delete message.confirm.delete.text=Are you sure you want to delete '%1'?\ Subscription.menu.properties=Properties props.window.title=Properties for '%1' subs.prop.enabled={azbuddy.enabled} subs.prop.is_auto=Auto-download new results subs.prop.last_scan=Last successful update subs.prop.last_result=Last new result found subs.prop.last_error=Last error subs.prop.num_read=Number of read results subs.prop.num_unread=Number of unread results subs.prop.template=Template subs.prop.auth=Authentication required externalLogin.auth_method_proxy=Use extended cookie capture method. If this fails to work, disable the option and retry externalLogin.wait=Page loading, please wait... TableColumn.menu.date_added.time=Show/Hide Time MyLibrary.bigView.header={sidebar.Library} sidebar.VuzeHDNetwork=Vuze HD Network subs.prop.next_scan=Next scan due subs.prop.assoc=Associations subs.prop.version=Version subscriptions.column.new= subscriptions.column.new.info=Indicates if there are one or more new results subscriptions.column.name=Subscription subscriptions.column.nb-results=Total Results subscriptions.column.nb-new-results=New Results subscriptions.column.last-checked=Last Checked subscriptions.view.title=Subscriptions subs.prop.is_public=Public subs.prop.high_version=Highest version encountered Subscription.menu.upgrade=Enable Upgrade To Higher Version metasearch.template.version.bad=Search template '%1' can't be installed until you upgrade Vuze metasearch.addtemplate.failed.title=Install Failed metasearch.addtemplate.failed.desc=Failed to install search template: %1 subscription.version.bad=Subscription '%1' can't be installed until you upgrade Vuze statusbar.feedback=Send Feedback statusbar.feedback.tooltip=Click here to send feedback UnopenedView.header={Unopened.bigView.header} sidebar.Activity=Notifications v3.activity.button.watchall=Mark All Watched subscriptions.view.help.1=Add Subscriptions wherever you see subscriptions.view.help.2=Get free live updates whenever new content is available for download. Learn More. sidebar.sash.tooltip=F7 to quicky hide/show sidebar sidebar.expand.tooltip=Expand the Sidebar sidebar.dropdown.tooltip=Show sidebar in menu format subscript.all.subscribed=You are subscribed to this content subscript.some.subscribed=You are subscribed to some of the subscriptions for this content.\nClick to see other available ones subscript.none.subscribed=Click to see the available subscriptions for this content v3.iconBar.up={iconBar.up} v3.iconBar.up.tooltip=Move Up\nHold mouse button to move to top v3.iconBar.down={iconBar.down} v3.iconBar.down.tooltip=Move Down\nHold mouse button to move to bottom TableColumn.header.azsubs.ui.column.subs_link=Association TableColumn.header.azsubs.ui.column.subs_link.info=Associated with subscriptions Button.deleteContent.fromLibrary=Remove from Library Button.deleteContent.fromComputer=Delete from Computer v3.deleteContent.message=\nWould you like to delete '%1' from your computer, or just remove it from your Vuze Library? v3.MainWindow.menu.view.toolbartext=Toolbar Text v3.MainWindow.menu.view.asSimpleList=Simple List v3.MainWindow.menu.view.asAdvancedList=Advanced List v3.MainWindow.menu.view.statusbar=Status Bar Subscription.menu.dirtyall=Mark All Results As Unread configureWizard.file.message3=Vuze will download files in a specific folder, you can choose this folder here: v3.deleteContent.applyToAll=Apply action to all %1 selected entries ConfigView.label.seeding.firstPriority.ignoreIdleHours=Torrents that do not upload anything for v3.MainWindow.menu.contentnetworks=HD &Networks v3.MainWindow.menu.contentnetworks.about=About HD Networks Peers.column.as=AS/ASN Peers.column.as.info=Peer's AS (Autonomous System) details ConfigTransferAutoSpeed.auto.speed.neural=Neural (Gudy Alpha) ConfigView.label.autoopen.downloadbars=Auto open Download Bars when ConfigView.label.autoopen=Auto Open ConfigView.label.autoopen.detailstab=Auto open Details Tab when ConfigView.label.autoopen.dl={ManagerItem.downloading} ConfigView.label.autoopen.cd={ManagerItem.seeding} ConfigView.label.systray=System Tray ConfigView.label.systray._mac=Status Bar Icon ConfigView.section.interface.legacy=Legacy v3.MainWindow.menu.contentnetworks.manage=&Manage HD Networks azbuddy.ui.table.loc_cat=Cats out azbuddy.ui.table.rem_cat=Cats in azbuddy.ui.menu.cat=Categories azbuddy.ui.menu.cat.share=Enable subscriptions with friend(s) azbuddy.ui.menu.cat.set=Enter categories azbuddy.ui.menu.cat.set_msg=Comma separated list of categories, or 'All' azbuddy.ui.menu.cat_subs=Subscribe subs.prop.update_period=Update period azbuddy.enable_cat_pub=Public categories that ALL your friends can subscribe to (',' separated) v3.dialog.cnclose.title=%1 Closed v3.dialog.cnclose.subtitle=Notification v3.dialog.cnclose.info1=You have closed an HD Network v3.dialog.cnclose.info2=If you would like to reopen this HD Network, you may do so in the "HD Networks" menu at the top of your screen. v3.dialog.cnclose.noshow=Do not show again v3.dialog.cnmanage.title=Manage HD Networks Menu v3.dialog.cnmanage.intro=You can choose from the list below which content networks you wish to display in the "HD Networks" menu azbuddy.ui.table.read_cat=Cat read TableColumn.header.#=# TableColumn.header.#.info=Position/Ordering Number TableColumn.header.category.info=Name of the category that the torrent belongs to TableColumn.header.DateCompleted.info=Date that the torrent downloading was completed TableColumn.header.AzProduct.info=Content Network that the torrent originated from TableColumn.header.health.info=How healthy your connection to the torrent's swarm is TableColumn.header.maxuploads.info=Maximum # of peers to simultaneously upload to TableColumn.header.name.info=Name of torrent TableColumn.header.unopened.info=Flag to indicate whether the torrent has been played (opened) TableColumn.header.savepath.info=The destination folder or file for the torrent's data TableColumn.header.SeedingRank.info=Ranking value of how badly the torrent needs seeding. Higher value means higher need. TableColumn.header.shareRatio.info=How much you've upload (shared) in comparison to how much you downloaded. TableColumn.header.size.info=Size of torrent's content on disk TableColumn.header.azsubs.ui.column.subs.info=Button that allows you to subscribe to feed containing related torrents TableColumn.header.upspeed.info=Current upload speed TableColumn.header.downspeed.info=Current download speed TableColumn.header.up.info=Current amount of data sent to other users TableColumn.header.down.info=Current amount of data received from other users TableColumn.header.ProgressETA.info=Combines Status, Completion, ETA, and Down Speed columns into one multi-lined column. TableColumn.header.eta.info=Estimated time before torrent is done downloaded Pieces.column.#=# Pieces.column.#.info=Piece Number Peers.column.%=% Peers.column.%.info=Percentage of the torrent the peer has downloaded so far TableColumn.header.download.info=Amount of data received from the peer TableColumn.header.upload.info=Amount of data we have sent to the peer TableColumn.header.downloadspeed.info=Rate at which we are are getting from the peer TableColumn.header.uploadspeed.info=Rate at which we are sending data to the peer TableColumn.header.lan.info=Flag indicating if the peer is on your LAN TableColumn.header.maxdownspeed.info=Download speed limit set on peer TableColumn.header.maxupspeed.info=Upload speed limit set on peer TableColumn.header.downloadspeedoverall.info=Estimated download rate of peer Peers.column.pieces.info=Graphical bar representing which pieces the peer has downloaded TableColumn.header.TableColumnNameInfo=Column Name and Description TableColumn.header.TableColumnSample=Sample TableColumn.header.TableColumnInfo=Column Description TableColumn.header.TableColumnChosenColumn=Chosen Column subs.prop.is_auto_ok=Auto-download permitted label.learnmore=Learn More ColumnSetup.title=Column Setup for '%1' ColumnSetup.explain=Explore the available columns on the left, and add them to the list of visible columns on the right. \ Expand or narrow down the list of available columns by using the Filter section on the bottom left. \ Drag and Drop and keyboard shortcuts are also supported. ColumnSetup.chosencolumns=Chosen Columns ColumnSetup.proficiency=Proficiency: ColumnSetup.categories=Categories: ColumnSetup.filters=Filters ColumnSetup.availcolumns=Available %1 columns ColumnSetup.availcolumns.filteredby=Available %1 columns filtered by %2 devices.view.title=Devices device.renderer.view.title=Renderers device.mediaserver.view.title=Media Servers device.router.view.title=Routers device.model.desc=Model description device.model.name=Model name device.model.num=Model number device.manu.desc=Manufacturer device.router.is_mapping=Automatic port mapping device.router.req_map=Required mappings device.router.configure=Configure UPnP device.mediaserver.configure=Configure My Media Server device.hide=Hide Device device.show=Show Hidden Devices device.search=Search For Devices device.router.con_type=Connection: %1 device.browse=Browse device.upnp.desc_url=Device Description device.upnp.present_url=Device Administration ConfigView.label.maxStalledSeeding=Maximum 'stalled' [0:unlimited] ConfigView.section.Devices={devices.view.title} device.search.auto=Automatically search for devices devices.sidebar.simple=Simple View devices.xcode.working_dir=Transcode area devices.xcode.prof_def=Default transcode profile devices.xcode.profs=Available transcode profiles device.lastseen=Last seen devices.contextmenu.xcode=Transcode For Device devices.device=Device devices.profile=Profile General.percent=Percent devices.installed=Installed devices.comp.missing=Vuze support not installed devices.state=State MainWindow.menu.help.donate=&Make a Donation DonationWindow.noload.title=Donation DonationWindow.noload.text=The donation window failed to load. Please try again at a later time. devices.xcode.only.show=Only Show Transcoded Files on Device device.quit.transcoding.title=Transcode in progress device.quit.transcoding.text='%1' is currently transcoding for '%2' and is %3% complete.\nIf you quit now this will need to be restarted from the beginning on next startup. download.removerules.unauthorised.data=\tRemove data device.config.xcode.maxbps=Max KB/sec transcode rate [0: unlimited] device.xcode=Transcode device.xcode.always=Always device.xcode.whenreq=When required device.xcode.never=Never devices.copy.pending=File copy pending devices.sidebar.hide.rend.generic=Hide generic devices v3.devicesview.infobar.text1= v3.devicesview.infobar.text2=To transcode content to a device, simply drag content from your library to the devices on the sidebar. To see completed transcodes, click the individual device on the right. iconBar.transcode=Device iconBar.transcode.tooltip=Make media available to a device device.retry.copy=Retry Copy devices.copy.fail=Failed to copy to device devices.on.demand=On demand devices.ready=Ready TableColumn.header.trancode_qpos=# TableColumn.header.trancode_qpos.info=Position in Transcode Queue TableColumn.header.profile=Device TableColumn.header.profile.info=Transcode profile used TableColumn.header.copied=Copied TableColumn.header.device=Device TableColumn.header.device.info=Target Device TableColumn.header.trancode_completion=Conversion Progress TableColumn.header.transcode_name={TableColumn.header.name} TableColumn.header.transcode_status={TableColumn.header.status} # This is the beginning of the word "View". It's right aligned under the icon bar item v3.iconBar.view.big=Vi v3.iconBar.view.big.tooltip=View as Simple List # This is the end of the word "View". It's left aligned under the icon bar item v3.iconBar.view.small=ew v3.iconBar.view.small.tooltip=View as Advanced List general.dont.ask.again=Don't ask again general.na.short=N/A v3.menu.device.exploreTranscodes=Show Files v3.menu.device.exploreTranscodes._windows=Show Files in Explorer v3.menu.device.exploreTranscodes._mac=Show Files In Finder v3.menu.device.defaultprofile=Default Profile devices.button.installitunes=Install iTunes Integration device.itunes.install=You need to install iTunes device.itunes.start=You need to start iTunes or enable auto-start device.itunes.install_problem=There appears to be a problem with iTunes integration devices.downloading=Downloading TableColumn.header.duration=Duration TableColumn.header.resolution=Resolution devices.xcode.autoStart=Automatically Start When Needed option.askeverytime=Ask every time option.rememberthis=Remember this setting devices.associate=Associate With devices.associate.already=Already associated devices.always.cache=Cache Non-transcoded Files devices.turnon.prepageload=To turn on this feature, installation of extra components is required. devices.turnon.itunes=Include support for iTunes (required for Apple devices) devices.turnon.qos=Share anonymous device statistics with Vuze devices.turnon.title=Turn On Device Support devices.choose.device.title=Select a playback device for this video: devices.choose.profile.title={devices.choose.device.title} devices.choose.profile.info.title= devices.choose.profile.info.text=After your selection, Vuze will detect whether or not the video format will playback on your selected device, and create a device-compatible copy if necessary.\n\nHover over selected device to see more details. devices.choose.profile.info.title.selected=%1 details: devices.view.heading=Media converting for device playback device.view.heading=Media for %1 devices.choose.device.info.title=Device Tip devices.choose.device.info.text=Next time, simply drag-and-drop files to the device of your choice in the Sidebar. label.clickone=Click one Button.turnon=Turn On ConfigView.section.interface.password={ConfigView.section.tracker.password} ConfigView.label.dm.dblclick=Double click in torrent views: ConfigView.option.dm.dblclick.play=Play Content ConfigView.option.dm.dblclick.details=Open Torrent Details View ConfigView.option.dm.dblclick.show=Show File ConfigView.option.dm.dblclick.show._mac=Show File(s) In Finder ConfigView.option.dm.dblclick.show._windows=Show File(s) In Explorer subscriptions.column.auto-download=Auto Download xcode.deletedata.title=Delete Transcoded Content xcode.deletedata.message=Are you sure you want to permanently delete the copy of '%1' transcoded for '%2'%3? xcode.deletedata.message.2=\n(a copy may still exist in '%1') v3.deviceview.infobar.line1=Drag-and-drop videos from your Library to the device of your choice. v3.deviceview.infobar.line2=Play your videos on any of your screens - iPhone, iPod, TV v3.deviceview.infobar.line1.generic=Drag-and-drop videos from your Library to %1 in your Sidebar. v3.deviceview.infobar.line2.itunes=Videos will appear in your iTunes Movies folder when they're ready to play. v3.deviceview.infobar.line2.xbox=Stream videos by going to your Xbox 360 and selecting My XBox -> Video Library -> Vuze. v3.deviceview.infobar.line2.ps3=Stream videos by going to your PS3 and selecting Videos -> Vuze. devices.copy_url=Copy Stream URL to Clipboard devices.converting=Converting Button.reload=Reload devices.auto.start=Auto-start Subscription.menu.setcookies=Set Cookies general.enter.cookies=Entry Cookies device.config.xcode.workdir=Default working directory for transcoded files MyTorrentsView.menu.clear_alloc_data=Clear Allocation State DiskManager.error.nospace=Insufficient disk space DiskManager.error.nospace_fat32={DiskManager.error.nospace} - check {wiki.fat32} wiki.fat32=http://www.azureuswiki.com/index.php/FAT32_file_size_limit ConfigView.section.file.rename.incomplete=Add suffix to incomplete files subscriptions.config.auto=Auto-download subscriptions.config.autostartdls=Automatically start downloads when added (as opposed to putting them into a stopped state) subscriptions.config.autostart.min=Only start if >= MB [0: unlimited] subscriptions.config.autostart.max=Only start if <= MB [0: unlimited] dlg.corewait.title=Initializing Core dlg.corewait.text=One Moment Please...\n\nYour request will be processed after Vuze has completed initialization library.core.wait=One Moment Please...\nThe Vuze Client is Initializing ConfigView.label.StartUIBeforeCore=Start UI before Core Initialization general.add.friends=Add some friends! general.all.friends=All Friends friend.mod.subs=Right-click to amend subscriptions TableColumn.header.class=Class device.rss.group=Local RSS Feed devices.xcode.rsspub=Publish RSS feed device.rss.enable=Create an RSS feed from transcoded content - this makes the content available to RSS feed readers device.rss.port=RSS feed port device.rss.view=Click to view RSS feed device.rss.localonly=Restrict access to this computer only rcm.rc_tracker.tt=Click to browser the tracker rcm.rc_hash.tt=Click to download this content rcm.rc_title.tt=Click to search for this content devices.xcode.autoCopy=Automatically Copy to Folder devices.xcode.setcopyto=Set Copy to Folder... devices.xcode.setcopyto.title=Choose copy-to location devices.copy.folder.auto=Automatically copy files to folder devices.copy.folder.dest=Copy to folder TableColumn.menu.maxuploads=# Max Uploads devices.xcode.mancopy=Manually Copy Files devices.xcode.show.cat=Separate By Category ConfigView.label.alwaysShowLibraryHeader=Always show header/filter bar in Library (My Torrents) devices.cat.show=Show categories devices.tivo.machine=TiVo machine name devices.info.copypending=%1 File(s) Waiting To Be Copied device.error.xcodefail=Transcode Failed device.error.copyfail=One Or More Files Failed To Copy To Folder device.error.copytonotset='Copy To Folder' Not Set device.error.copytomissing='Copy To Folder' "%1" Not Found device.error.copytonowrite='Copy To Folder' "%1" Not Writable device.error.copyfail2=One Or More Files Failed To Copy To Device v3.deviceview.infobar.line2.tivo=Stream videos by going to your TiVo and selecting Vuze in your Now Playing List. v3.deviceview.infobar.line2.psp=Videos will be copied to your PSP when it is connected. devices.info.copypending2=%1 File(s) Waiting To Be Copied, Connect Your Device subscriptions.column.nb-subscribers=Subscribers subscriptions.column.category={TableColumn.header.category} device.offlinedownloader.view.title=Offline Downloaders device.xcode.group={device.xcode} device.od.group={device.offlinedownloader.view.title} device.od.enable=Enable offline download devices device.odauto.enable=Automatically manage downloads device.odpt.enable=Include private torrents devices.contextmenu.od=Offline Downloading devices.contextmenu.od.auto= devices.contextmenu.od.enable=Enable devices.contextmenu.od.enabled=Enabled devices.od.view.heading=Downloads scheduled for offline downloading DevicesOD.column.od_name={TableColumn.header.name} DevicesOD.column.od_status={MyTrackerView.status} DevicesOD.column.od_completion=Transfer Progress DevicesOD.column.od_remaining={TableColumn.header.remaining} devices.od.xfering={PeersView.BlockView.Transfer} devices.od.idle=Idle device.od.turnon.title=Turn On Offline Downloader Support device.is.disabled=Device is disabled device.configure=Configure... device.od.error.notfound=Device appears to be offline device.od.error.opfailstatus=Device failed to process command %1: status %2 device.od.error.opfailexcep=Device failed to process command %1: exception %2 device.od.error.nospace=No space left on device or no external drive connected device.od.space=Available Space ConfigView.section.style.forceSIValues=Force values to be shown as IEC values regardless of display unit for legacy purposes (e.g. 1MB = 1MiB = 1048576B) ConfigView.label.enableSystrayToolTip=Show download stats on hover devices.activation=Device Activation button.nothanks=No Thanks devices.od.turnon.text1=We have noticed that you are connected to a %1. devices.od.turnon.text2=Would you like the %1 to continue to download your files when your computer is offline? devices.od.turnon.text3=Please connect a Hard Drive to the %1 to turn on this feature. devices.od.turnon.learn=Learn more > devices.router=router devices.od=offline downloader webui.pairingenable=Enable pairing webui.group.access=Access Control ConfigView.section.Pairing=Pairing pairing.accesscode=Access code pairing.ac.getnew=Allocate a new access code pairing.ac.getnew.create=Create pairing.ipv4=IPv4 address pairing.ipv6=IPv6 address pairing.host=Host address (DNS name) pairing.group.explicit=Explicit Attributes pairing.explicit.enable=Enable pairing.explicit.info=Normally explicit IP attributes do not need to be specified as these can be automatically derived.\nThe 'host' attribute can be used, for example, if you have a DynDNS account and appropriate client software to keep your dynamic IP correctly registered. pairing.op.fail=Pairing Operation Failed pairing.alloc.fail=Failed to allocate a new access code\n%1 pairing.enable=Enable pairing of Vuze and remote applications/interfaces pairing.status.info=Status pairing.status.registered=Update successful (%1) pairing.status.pending=Update will be performed at %1 pairing.status.initialising=Initialising pairing.status.disabled=Disabled pairing.view.registered=Click to view current registration details webui.pairing.info.n=Pairing is disabled, see the Connection->Pairing options for information on this feature webui.pairing.info.y=Pairing is enabled, see the Connection->Pairing options for more details. webui.enable=Enable (*) ConfigView.section.rss=Local RSS etc. subscriptions.rss.enable=Create RSS Feeds from subscrptions device.tivo.enable=Enable TiVo support Button.removeAll=Remove All label.rename=Rename %1 RCM.column.rc_new={TableColumn.header.unopened} RCM.column.rc_rank=Rank RCM.column.rc_actions={TableColumn.header.activityActions} RCM.column.rc_created=Created RCM.column.rc_hash=Hash RCM.column.rc_lastseen=Last Seen RCM.column.rc_level=Level RCM.column.rc_peers={TableColumn.header.peers} RCM.column.rc_seeds={TableColumn.header.seeds} RCM.column.rc_size={TableColumn.header.size} RCM.column.rc_tracker=Tracker RCM.column.rc_title={TableColumn.header.name} rcm.view.heading=Swarm Discoveries rcm.view.title={rcm.view.heading} rcm.contextmenu.lookupassoc={rcm.view.heading} ConfigView.section.Associations={rcm.view.heading} rcm.config.enabled=Enable rcm.config.max_results=Maximum results rcm.config.max_level=Maximum level rcm.search.provider=Swarm pairing.server.warning.title=Pairing Server Message wizard.webseedseditor.edit.title=HTTP Seeds Editor wizard.webseedseditor.edit.newseed=New Seed MyTorrentsView.menu.editWebSeeds=Edit HTTP Seeds ClientStats.title.full=Client Stats ClientStats.column.count=Count ClientStats.column.discarded={PeersView.discarded} ClientStats.column.received={DHTView.transport.received} ClientStats.column.sent={DHTView.transport.sent} ClientStats.column.percent=% ClientStats.column.name={TableColumn.header.name} MainWindow.menu.view.clientstats={ClientStats.title.full} Scrape.status.cached=Cached scrape network.ipv6.enable.support=Enable IPv6 support ConfigView.section.plugins.magnetplugin=Magnet URI Handler MagnetPlugin.use.lookup.service=Use the Vuze secondary lookup service if magnet lookup via DHT fails MagnetPlugin.report.secondarylookup=Trying secondary lookup service MagnetPlugin.report.secondarylookup.ok=Secondary lookup succeeded MagnetPlugin.report.secondarylookup.fail=Secondary lookup failed: no sources found #PLEASE LEAVE ME AT VERY BOTTOM! azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_uk_UA.properties0000644000175000017500000222672511301156004026113 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=\u0422\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b... Main.parameter.usage=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f : java org.gudy.azureus2.cl.Main [\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438] "\u0444\u0430\u0439\u043b.torrent" "\u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f" Main.parameter.maxUploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447 Main.parameter.maxSpeed=\u041c\u0430\u043a\u0441. \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0411\u0430\u0439\u0442/\u0441 MainWindow.menu.file=&\u0424\u0430\u0439\u043b MainWindow.menu.file.open=\u0412&\u0456\u0434\u043a\u0440\u0438\u0442\u0438 MainWindow.menu.file.create=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 &\u0442\u043e\u0440\u0435\u043d\u0442 MainWindow.menu.file.create.fromfile=\u0437 &\u0444\u0430\u0439\u043b\u0443 MainWindow.menu.file.create.fromdir=\u0437 &\u0442\u0435\u043a\u0438 MainWindow.menu.file.export=&\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 MainWindow.menu.file.import=&\u0406\u043c\u043f\u043e\u0440\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 MainWindow.menu.file.closetab=&\u0417\u0430\u043a\u0440\u0438\u0442\u0438 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 MainWindow.menu.file.closewindow=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 &\u0432\u0456\u043a\u043d\u043e MainWindow.menu.file.exit=\u0412\u0438&\u0445\u0456\u0434 MainWindow.dialog.choose.file=\u0412\u0438\u0431\u0456\u0440 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 MainWindow.menu.file.folder=\u0422\u0435&\u043a\u0430 MainWindow.dialog.choose.folder=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0442\u0435\u043a\u0443 \u0437 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438 MainWindow.menu.view=&\u0412\u0438\u0433\u043b\u044f\u0434 MainWindow.menu.view.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 MainWindow.menu.view.mytorrents=&\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 MainWindow.menu.view.open_global_transfer_bar=\u041f\u0430\u043d\u0435\u043b\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447 MainWindow.menu.view.configuration=&\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f... MainWindow.menu.view.console=&\u041a\u043e\u043d\u0441\u043e\u043b\u044c MainWindow.menu.view.allpeers=\u0412\u0441\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438 MainWindow.menu.view.detailedlist=&\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a MainWindow.menu.closealldetails=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 \u0432\u0441\u0456 &\u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 MainWindow.menu.closealldownloadbars=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 \u0432\u0441\u0456 &\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f MainWindow.menu.language=&\u041c\u043e\u0432\u0430 ConfigView.section.language=\u041c\u043e\u0432\u0430 MainWindow.menu.window=\u0412\u0456\u043a&\u043d\u043e MainWindow.menu.window.minimize=&\u0417\u0433\u043e\u0440\u043d\u0443\u0442\u0438 MainWindow.menu.window.zoom=&\u0417\u0431\u0456\u043b\u044c\u0448\u0438\u0442\u0438 MainWindow.menu.window.alltofront=\u0417\u0433\u043e\u0440\u0438 \u0432\u0441\u0456\u0445 MainWindow.menu.help=&\u0414\u043e\u0432\u0456\u0434\u043a\u0430 MainWindow.menu.help.about=\u041f\u0440\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443 Vuze MainWindow.menu.torrent=T&\u043e\u0440\u0435\u043d\u0442 MainWindow.about.title=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u043f\u0440\u043e MainWindow.about.section.developers=\u0420\u043e\u0437\u0440\u043e\u0431\u043d\u0438\u043a\u0438 MainWindow.about.section.translators=\u041f\u0435\u0440\u0435\u043a\u043b\u0430\u0434\u0430\u0447\u0456 MainWindow.about.section.system=\u0421\u0438\u0441\u0442\u0435\u043c\u0430 MainWindow.about.section.internet=\u0406\u043d\u0442\u0435\u0440\u043d\u0435\u0442 MainWindow.about.internet.homepage=\u0421\u0442\u043e\u0440\u0456\u043d\u043a\u0430 Vuze MainWindow.about.internet.sourceforge=\u0421\u0442\u043e\u0440\u0456\u043d\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u043d\u0430 Sourceforge MainWindow.about.internet.sourceforgedownloads=\u0421\u0442\u043e\u0440\u0456\u043d\u043a\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437 Sourceforge MainWindow.about.internet.bugreports=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u0438\u0442\u0438 \u043f\u0440\u043e \u043f\u043e\u043c\u0438\u043b\u043a\u0443 MainWindow.about.internet.forumdiscussion=\u0424\u043e\u0440\u0443\u043c\u0438 MainWindow.about.internet.wiki=Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0430 \u0437 FAQ \u043f\u0440\u043e Vuze MainWindow.dialog.choose.savepath=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0442\u0435\u043a\u0443 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f MainWindow.dialog.choose.savepath_forallfiles=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0443 \u0442\u0435\u043a\u0443 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f MainWindow.status.latestversion=\u041e\u0441\u0442\u0430\u043d\u043d\u044f \u0432\u0435\u0440\u0441\u0456\u044f MainWindow.status.latestversion.clickupdate=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 MainWindow.status.unknown=\u043d\u0435\u0432\u0456\u0434\u043e\u043c\u043e MainWindow.status.checking=\u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 MyTorrentsView.mytorrents=\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.name=\u041d\u0430\u0437\u0432\u0430 TableColumn.header.size=\u0420\u043e\u0437\u043c\u0456\u0440 TableColumn.header.done=\u0413\u043e\u0442\u043e\u0432\u043e TableColumn.header.done.info=\u0412\u0456\u0434\u0441\u043e\u0442\u043e\u043a \u0433\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u0456 \u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0434\u0430\u043d\u043d\u044f TableColumn.header.status=\u0421\u0442\u0430\u0442\u0443\u0441 TableColumn.header.status.info=\u0429\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u0440\u043e\u0431\u0438\u0442\u044c TableColumn.header.seeds=\u0421\u0456\u0434\u0435\u0440\u0456\u0432 TableColumn.header.seeds.info=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0432'\u044f\u0437\u043a\u0456\u0432 \u0434\u043e \u0441\u0456\u0434\u0435\u0440\u0456\u0432 (\u0457\u0445\u043d\u044f \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c) TableColumn.header.peers=\u0423\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 TableColumn.header.peers.info=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437'\u0454\u0434\u043d\u0430\u043d\u044c \u0434\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 (\u0457\u0445\u043d\u044f \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c) TableColumn.header.completed=\u0412\u0438\u043a\u043e\u043d\u0430\u043d\u0438\u0439 TableColumn.header.completed.info=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0437\u0430\u043a\u0456\u043d\u0447\u0443\u044e\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443, \u044f\u043a \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u0454\u0442\u044c\u0441\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u043c TableColumn.header.downspeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f TableColumn.header.upspeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 TableColumn.header.eta=\u0417\u0430\u043b\u0438\u0448\u0438\u043b\u043e\u0441\u044f TableColumn.header.tracker=\u0422\u0440\u0435\u043a\u0435\u0440 TableColumn.header.tracker.info=\u0421\u0442\u0430\u0442\u0443\u0441 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 TableColumn.header.trackernextaccess=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0435 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u043c TableColumn.header.trackernextaccess.info=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0437\u0430\u043f\u0438\u0442 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0432\u0456\u0434 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 TableColumn.header.priority=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 TableColumn.header.priority.info=\u0412\u0438\u0437\u043d\u0430\u0447\u0430\u0454 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 TableColumn.header.seeds.fullcopycalc=%2 \u043f\u043e\u0432\u043d\u0438\u0445 \u043a\u043e\u043f\u0456\u0439 \u043f\u0435\u0440\u0435\u0431\u0443\u0432\u0430\u044e\u0442\u044c \u0432 %1 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 MyTorrentsView.menu.showdetails=\u041f\u043e&\u0434\u0440\u043e\u0431\u0438\u0446\u0456 MyTorrentsView.menu.showdownloadbar=\u041f\u0430\u043d\u0435\u043b\u044c &\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f MyTorrentsView.menu.open=&\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 MyTorrentsView.menu.setpriority=\u0417\u0430\u0434\u0430\u0442\u0438 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 MyTorrentsView.menu.setpriority.high=&\u0412\u0438\u0441\u043e\u043a\u0438\u0439 MyTorrentsView.menu.setpriority.low=&\u041d\u0438\u0437\u044c\u043a\u0438\u0439 MyTorrentsView.menu.start=&\u041f\u043e\u0447\u0430\u0442\u0438 MyTorrentsView.menu.stop=&\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 MyTorrentsView.menu.remove=\u0412\u0438&\u043b\u0443\u0447\u0438\u0442\u0438 MyTorrentsView.menu.changeTracker=&\u0414\u043e\u0434\u0430\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 TrayWindow.menu.exit=&\u0412\u0438\u0439\u0442\u0438 TrayWindow.menu.show=\u041f\u043e&\u043a\u0430\u0437\u0430\u0442\u0438 Vuze SystemTray.menu.exit=\u0412\u0438\u0439\u0442\u0438 SystemTray.menu.closealldownloadbars=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 \u0432\u0441\u0456 \u043f\u0430\u043d\u0435\u043b\u0456 SystemTray.menu.open_global_transfer_bar=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447 SystemTray.menu.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 Vuze PeersView.ip=IP-\u0430\u0434\u0440\u0435\u0441\u0430 PeersView.ip.info=IP \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 PeersView.port=\u041f\u043e\u0440\u0442 PeersView.port.info=\u041f\u043e\u0440\u0442, \u044f\u043a\u0438\u0439 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f PeersView.T.info=l (local - \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0435): \u0412\u0438 \u0437'\u0454\u0434\u043d\u0430\u043b\u0438\u0441\u044f, r (remote - \u0432\u0456\u0434\u0434\u0430\u043b\u0435\u043d\u0435): \u0443\u0447\u0430\u0441\u043d\u0438\u043a \u0437'\u0454\u0434\u043d\u0430\u0432\u0441\u044f. PeersView.T.L.tooltip=\u0412\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f PeersView.T.R.tooltip=\u0423\u0447\u0430\u0441\u043d\u0438\u043a \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0432 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f PeersView.I1=\u042f \u0437\u0430\u0446\u0456\u043a\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c PeersView.I1.info=\u0412\u0438 \u0437\u0430\u0446\u0456\u043a\u0430\u0432\u043b\u0435\u043d\u0456 \u0432 \u0442\u043e\u043c\u0443, \u0449\u043e \u043c\u0430\u0454 \u0456\u043d\u0448\u0438\u0439 \u0443\u0447\u0430\u0441\u043d\u0438\u043a? PeersView.C1=C (\u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0439 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c) PeersView.C1.info=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c PeersView.pieces=\u0427\u0430\u0441\u0442\u0438\u043d PeersView.downloadspeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f PeersView.download=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043e PeersView.I2=\u0423\u0447\u0430\u0441\u043d\u0438\u043a \u0437\u0430\u0446\u0456\u043a\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0412\u0430\u043c\u0438 PeersView.I2.info=\u0427\u0438 \u0437\u0430\u0446\u0456\u043a\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0456\u043d\u0448\u0438\u0439 \u0443\u0447\u0430\u0441\u043d\u0438\u043a \u0432 \u0442\u043e\u043c\u0443, \u0449\u043e \u043c\u0430\u044e \u044f? PeersView.C2=C (\u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0439 \u0441\u0456\u0434\u0435\u0440\u043e\u043c) PeersView.C2.info=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c PeersView.uploadspeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 PeersView.uploadspeed.info=\u0412\u0430\u0448\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 PeersView.upload=\u0420\u043e\u0437\u0434\u0430\u043d\u043e PeersView.upload.info=\u0412\u0430\u043c\u0438 \u0440\u043e\u0437\u0434\u0430\u043d\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0443. PeersView.statup=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 PeersView.statup.info=\u041e\u0440\u0456\u0454\u043d\u0442\u043e\u0432\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 PeersView.S=\u0412\u0438\u043d\u044f\u0442\u043e\u043a PeersView.S.info=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u043d\u043d\u044f: \u0423\u0447\u0430\u0441\u043d\u0438\u043a \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0439 \u0432\u0438\u043d\u044f\u0442\u043a\u043e\u043c \u0432\u0440\u0443\u0447\u043d\u0443 \u0430\u0431\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e (\u0437\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u043d\u0430 \u0437\u0430\u043d\u0438\u0437\u044c\u043a\u0456\u0439 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456) PeersView.downloadspeedoverall=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f PeersView.optunchoke=\u0420\u043e\u0437\u0431\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438 PeersView.client=\u041a\u043b\u0456\u0454\u043d\u0442 PeersView.client.info=\u041d\u0430\u0437\u0432\u0430 BT-\u043a\u043b\u0456\u0454\u043d\u0442\u0430, \u044f\u043a\u0438\u0439 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c PeersView.menu.snubbed=\u041f\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 PeersView.title.short=\u0423\u0447\u0430\u0441\u043d\u0438\u043a\u0438 PeersView.title.full=\u0423\u0447\u0430\u0441\u043d\u0438\u043a\u0438 AllPeersView.title.full=\u0412\u0441\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438 ConfigView.section.files=\u0424\u0430\u0439\u043b\u0438 ConfigView.label.usefastresume=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u043c\u0435\u0442\u043e\u0434 "\u0448\u0432\u0438\u0434\u043a\u043e\u0433\u043e" \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0435\u043d\u043d\u044f ConfigView.label.incrementalfile=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0456\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0435 \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0456\u0432 ConfigView.label.defaultsavepath=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456\u0439 \u0442\u0435\u0446\u0456 ConfigView.button.browse=&\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434... ConfigView.dialog.choosedefaultsavepath=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u0435\u043a\u0443 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0441\u0456\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 ConfigView.section.server=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f ConfigView.section.global=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0435 ConfigView.label.disconnetseed=\u0412\u0456\u0434\u2019\u0454\u0434\u043d\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u0432\u0456\u0434 \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0443 \u0447\u0430\u0441 \u0432\u043b\u0430\u0441\u043d\u043e\u0457 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 ConfigView.label.switchpriority=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 ConfigView.label.maxdownloads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] ConfigView.label.maxdownloads.tooltip=\u0412\u0438 \u0437\u0430\u0432\u0436\u0434\u0438 \u0437\u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 \u0446\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437 \u043e\u0434\u043d\u0438\u043c \u0432\u0438\u043d\u044f\u0442\u043a\u043e\u043c.\n\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 \u0437 \u0432\u0438\u0449\u0438\u043c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u043c\u043e\u0436\u0435 \u0442\u0430\u043a\u043e\u0436 \u0437\u0430\u0439\u043c\u0430\u0442\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0439 \u0441\u043b\u043e\u0442 \u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u043f\u043e\u0442\u0440\u0435\u0431\u0438. ConfigView.label.maxactivetorrents=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439]\n\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0430\u0431\u043e \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u043d\u043e\u0432\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u043d\u0435 \u043f\u043e\u0447\u0438\u043d\u0430\u0454\u0442\u044c\u0441\u044f,\n\u044f\u043a\u0449\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043f\u0435\u0440\u0435\u0432\u0438\u0449\u0435\u043d\u0438\u0439. ConfigView.label.priorityExtensions=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0440\u043e\u0437\u0442\u0430\u0448\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0437\u0430 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0444\u0430\u0439\u043b\u0438 \u0437 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043d\u044f\u043c\u0438 (\u043d\u0430\u043f\u0440.: .txt;.nfo;.jpg) ConfigView.section.transfer=\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 ConfigView.label.maxuploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 ConfigView.label.maxuploadspeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u041a\u0431\u0456\u0442/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] ConfigView.label.saveresumeinterval=\u0417\u0430\u043f\u0438\u0441 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0434\u043b\u044f "\u0448\u0432\u0438\u0434\u043a\u043e\u0433\u043e" \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0435\u043d\u043d\u044f \u043a\u043e\u0436\u043d\u0456 ConfigView.unlimited=\u041d\u0435 \u043e\u0431\u043c\u0435\u0436\u0443\u0432\u0430\u0442\u0438 ConfigView.section.display=\u0417\u043e\u0432\u043d\u0456\u0448\u043d\u0456\u0439 \u0432\u0438\u0433\u043b\u044f\u0434 ConfigView.label.opendetails=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0437 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044f\u043c\u0438 ConfigView.label.openbar=\u0412\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e ConfigView.label.use_old_speed_menus=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0430\u0440\u0438\u0439 \u0441\u0442\u0438\u043b\u044c \u0448\u0432\u0438\u0434\u043a\u0438\u0445 \u043c\u0435\u043d\u044e [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443] ConfigView.label.closetotray=\u041f\u0440\u0438 \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u0456 \u0437\u0433\u043e\u0440\u043d\u0443\u0442\u0438 \u0432 \u0442\u0440\u0435\u0439 ConfigView.label.minimizetotray=\u0417\u0433\u043e\u0440\u0442\u0430\u0442\u0438 \u0432 \u0442\u0440\u0435\u0439 ConfigView.section.general=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0435 ConfigView.section.start=\u0417\u0430\u043f\u0443\u0441\u043a ConfigView.label.showsplash=\u041f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0443 ConfigView.label.autoupdate=\u0412\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u0434\u0456\u0430\u043b\u043e\u0433 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0437 \u043f\u043e\u044f\u0432\u043e\u044e \u043d\u043e\u0432\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 ConfigView.label.openconsole=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 ConfigView.label.openconfig=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 ConfigView.label.startminimized=\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u0432 \u0437\u0433\u043e\u0440\u043d\u0443\u0442\u043e\u043c\u0443 \u0432\u0456\u043a\u043d\u0456 ConfigView.section.irc=\u041c\u0435\u0440\u0435\u0436\u0430 IRC ConfigView.label.ircwiki=\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0439\u0442\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430: http://www.azureuswiki.com/index.php/IRC#Rules_for_IRC ConfigView.label.ircserver=\u0421\u0435\u0440\u0432\u0435\u0440 ConfigView.label.ircchannel=\u041a\u0456\u043c\u043d\u0430\u0442\u0430 ConfigView.label.irclogin=\u041d\u0456\u043a\u043d\u0435\u0439\u043c ConfigView.group.irctitle=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f IRC ConfigView.boolean.ircsendinfo=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u0435 \u043f\u043e\u0448\u0438\u0440\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u0438\u0445 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c \n \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0449\u043e\u0431 \u0430\u0434\u043c\u0456\u043d\u0456\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0438 \u043a\u0430\u043d\u0430\u043b\u0443 \u043c\u043e\u0433\u043b\u0438 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u0442\u0438 \u0432\u0430\u043c ConfigView.boolean.irclog=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043b\u043e\u0433 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0456 IRC ( \u0443 \u0444\u0430\u0439\u043b IRC_log.htm) ConfigView.section.security=\u0411\u0435\u0437\u043f\u0435\u043a\u0430 ConfigView.label.password=\u0417\u0430\u0445\u0438\u0441\u0442\u0438\u0442\u0438 Vuze, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0447\u0438 \u043f\u0430\u0440\u043e\u043b\u044c.\n - \u0432\u0456\u043d \u0431\u0443\u0434\u0435 \u0437\u0430\u043f\u0438\u0442\u0430\u043d\u0438\u0439 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0430\u0431\u043e \u0437\u043c\u0456\u043d\u0456. ConfigView.label.passwordconfirm=\u041f\u0430\u0440\u043e\u043b\u044c (\u043f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f) ConfigView.label.passwordmatch=\u041f\u0430\u0440\u043e\u043b\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0439 : ConfigView.label.passwordmatchnone=\u041d\u0456 ConfigView.label.passwordmatchno=\u041d\u0435\u043c\u0430 \u0430\u0431\u043e \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 ConfigView.label.passwordmatchyes=\u0422\u0430\u043a ConfigView.button.save=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 ConfigView.title.short=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f ConfigView.title.full=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f ConfigView.title.full._mac=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f ConsoleView.title.short=\u041a\u043e\u043d\u0441\u043e\u043b\u044c ConsoleView.title.full=\u041a\u043e\u043d\u0441\u043e\u043b\u044c FileItem.write=\u0437\u0430\u043f\u0438\u0441 FileItem.read=\u0447\u0438\u0442\u0430\u043d\u043d\u044f FileItem.normal=\u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u0438\u0439 FileItem.high=\u0432\u0438\u0441\u043e\u043a\u0438\u0439 FileItem.donotdownload=\u041d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 FileItem.delete=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 FilesView.name=\u041d\u0430\u0437\u0432\u0430 FilesView.name.fastRename=\u0428\u0432\u0438\u0434\u043a\u0435 \u043f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u043d\u044f FilesView.size=\u0420\u043e\u0437\u043c\u0456\u0440 FilesView.done=\u0413\u043e\u0442\u043e\u0432\u043e FilesView.firstpiece=\u041f\u0435\u0440\u0448\u0430 \u0447\u0430\u0441\u0442\u0438\u043d\u0430 # FilesView.numberofpieces=\u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0447\u0430\u0441\u0442\u0438\u043d FilesView.pieces=\u0427\u0430\u0441\u0442\u0438\u043d\u0438 FilesView.mode=\u0420\u0435\u0436\u0438\u043c FilesView.priority=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 FilesView.menu.open=&\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 FilesView.menu.setpriority=\u0417\u0430\u0434\u0430\u0442\u0438 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 FilesView.menu.setpriority.high=&\u0412\u0438\u0441\u043e\u043a\u0438\u0439 FilesView.menu.setpriority.normal=&\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 FilesView.menu.setpriority.skipped=&\u041d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 FilesView.title.short=\u0424\u0430\u0439\u043b\u0438 FilesView.title.full=\u0424\u0430\u0439\u043b\u0438 GeneralView.section.downloaded=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 GeneralView.label.status.file=\u0421\u0442\u0430\u0442\u0443\u0441 \u0444\u0430\u0439\u043b\u0443 GeneralView.label.status.pieces=\u0421\u0442\u0430\u0442\u0443\u0441 \u0447\u0430\u0441\u0442\u0438\u043d GeneralView.section.availability=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456\u0441\u0442\u044c GeneralView.label.status.pieces_available=\u0421\u0442\u0430\u0442\u0443\u0441 \u0447\u0430\u0441\u0442\u0438\u043d GeneralView.section.transfer=\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 GeneralView.section.info=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f GeneralView.title.short=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0435 GeneralView.title.full=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0435 GeneralView.label.timeelapsed=\u041f\u0440\u043e\u0439\u0448\u043b\u043e \u0447\u0430\u0441\u0443 : GeneralView.label.remaining=\u0417\u0430\u043b\u0438\u0448\u0438\u043b\u043e\u0441\u044f: GeneralView.label.downloaded=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043e : GeneralView.label.downloadspeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f : GeneralView.label.maxuploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0440\u043e\u0437\u0434\u0430\u0447: GeneralView.label.maxuploads.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u044f\u043a\u0456 \u043c\u043e\u0436\u0443\u0442\u044c \u0431\u0443\u0442\u0438 \u043f\u0456\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0456 \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u043e. GeneralView.label.uploaded=\u0420\u043e\u0437\u0434\u0430\u043d\u043e : GeneralView.label.uploadspeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 : GeneralView.label.seeds=\u0421\u0456\u0434\u0435\u0440\u0438: GeneralView.label.peers=\u0423\u0447\u0430\u0441\u043d\u0438\u043a\u0438: GeneralView.label.completed=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043e: GeneralView.label.totalspeed=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c : GeneralView.label.totalspeed.tooltip=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 (\u0456 \u0441\u0435\u0440\u0435\u0434\u043d\u044f) \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0432\u0441\u0456\u0445 \u043a\u043b\u0456\u0454\u043d\u0442\u0456\u0432, \u0437 \u044f\u043a\u0438\u043c\u0438 \u0412\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u0456. GeneralView.label.averagespeed=\u0441\u0435\u0440\u0435\u0434\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c GeneralView.label.filename=\u0406\u043c'\u044f \u0444\u0430\u0439\u043b\u0443: GeneralView.label.totalsize=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440 : GeneralView.label.savein=\u0417\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0432 : GeneralView.label.hash=\u0425\u0435\u0448 : GeneralView.label.numberofpieces=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0447\u0430\u0441\u0442\u0438\u043d: GeneralView.label.size=\u0420\u043e\u0437\u043c\u0456\u0440 : GeneralView.label.tracker=\u0421\u0442\u0430\u0442\u0443\u0441 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 : GeneralView.label.updatein=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 : GeneralView.label.trackerurl=\u0410\u0434\u0440\u0435\u0441\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 : GeneralView.label.trackerurlupdate=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 GeneralView.label.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 : GeneralView.label.user_comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 : GeneralView.label.status=\u0421\u0442\u0430\u0442\u0443\u0441 : ManagerItem.waiting=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f ManagerItem.allocating=\u0420\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f \u043d\u0430 \u0434\u0438\u0441\u043a\u0443 ManagerItem.checking=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 ManagerItem.ready=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0456\u043d\u0448\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443(\u0456\u0432) \u0432 \u0447\u0435\u0440\u0437\u0456 ManagerItem.downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ManagerItem.seeding=\u0420\u043e\u0437\u0434\u0430\u0447\u0430 ManagerItem.stopped=\u0417\u0443\u043f\u0438\u043d\u043a\u0430 ManagerItem.error=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 ManagerItem.high=\u0432\u0438\u0441\u043e\u043a\u0438\u0439 ManagerItem.low=\u043d\u0438\u0437\u044c\u043a\u0438\u0439 MinimizedWindow.name=\u041d\u0430\u0437\u0432\u0430: MinimizedWindow.all_transfers=\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0456 Vuze PiecesView.size=\u0420\u043e\u0437\u043c\u0456\u0440 PiecesView.numberofblocks=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0431\u043b\u043e\u043a\u0456\u0432 PiecesView.blocks=\u0411\u043b\u043e\u043a\u0438 PiecesView.completed=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0430 PiecesView.availability=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u043e PiecesView.reservedby=\u0417\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043e\u0432\u0430\u043d\u0438\u0439 PiecesView.writers=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u043c\u0456\u0447\u043d\u0438\u043a\u0456\u0432 PiecesView.title.short=\u0427\u0430\u0441\u0442\u0438\u043d\u0438 PiecesView.title.full=\u0427\u0430\u0441\u0442\u0438\u043d\u0438 SystemTray.tooltip.seeding=\u0420\u043e\u0437\u0434\u0430\u0447\u0430: %1, SystemTray.tooltip.downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f: %1, DownloadManager.error.filenotfound=\u0424\u0430\u0439\u043b \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439 DownloadManager.error.fileempty=\u041f\u043e\u0440\u043e\u0436\u043d\u0456\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 DownloadManager.error.filetoobig=\u0422\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b \u0437\u0430\u043d\u0430\u0434\u0442\u043e \u0432\u0435\u043b\u0438\u043a\u0438\u0439 DownloadManager.error.filewithouttorrentinfo=\u041d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442-\u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0432 \u0444\u0430\u0439\u043b\u0456 DownloadManager.error.unsupportedencoding=\u041a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454\u0442\u044c\u0441\u044f DownloadManager.error.ioerror=IO-\u043f\u043e\u043c\u0438\u043b\u043a\u0430 DownloadManager.error.sha1="\u0410\u043b\u0433o\u0440\u0438\u0442\u043c (SHA1) \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439"- \u043f\u043e\u043c\u0438\u043b\u043a\u0430 PeerManager.status.offline=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f PeerManager.status.ok=\u0413\u0430\u0440\u0430\u0437\u0434 PeerManager.status.checking=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 PeerManager.status.finished=\u0413\u043e\u0442\u043e\u0432\u043e PeerManager.status.finishedin=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043e \u0437\u0430 MainWindow.upgrade.assistant=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 MainWindow.upgrade.newerversion=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0456\u044f, \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438? MainWindow.upgrade.explanation=Vuze \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u044c \u043d\u043e\u0432\u0443 \u0432\u0435\u0440\u0441\u0456\u044e \u0456 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f MainWindow.upgrade.explanation.manual=\u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e: \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0442\u0435 \u043d\u043e\u0432\u0443 \u0432\u0435\u0440\u0441\u0456\u044e \u0456 \u0437\u0430\u043f\u0443\u0441\u0442\u0456\u0442\u044c \u0437\u043d\u043e\u0432\u0443 Vuze MainWindow.upgrade.step1=\u041a\u0440\u043e\u043a 1: \u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0442\u0435 \u043d\u043e\u0432\u0443 \u0432\u0435\u0440\u0441\u0456\u044e MainWindow.upgrade.step2=\u041a\u0440\u043e\u043a 2: \u0417\u0430\u043f\u0443\u0441\u0442\u0456\u0442\u044c \u0437\u043d\u043e\u0432\u0443 Vuze MainWindow.upgrade.hint1=\u041f\u043e\u0440\u0430\u0434\u0430:\t\u041f\u0440\u0438 \u043d\u0430\u0442\u0438\u0441\u043a\u0430\u043d\u043d\u0456 \u0417\u0430\u043a\u0456\u043d\u0447\u0438\u0442\u0438 \u0432\u0441\u0435 \u0431\u0443\u0434\u0435 \u0437\u0440\u043e\u0431\u043b\u0435\u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e MainWindow.upgrade.hint2=\u041f\u043e\u0440\u0430\u0434\u0430:\t\u042f\u043a\u0449\u043e \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0430\u043a\u0440\u0438\u0442\u0438 Vuze \u043f\u0456\u0437\u043d\u0456\u0448\u0435, \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u0456\n\t\u043f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0439\u0442\u0435 \u0444\u0430\u0439\u043b Azureus2-new.jar \u0432 Azureus2.jar \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 MainWindow.upgrade.error.downloading.hint=\u041f\u043e\u043c\u0438\u043b\u043a\u0430:\t\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u043d\u0435 \u0437\u043c\u043e\u0433\u043b\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u043d\u043e\u0432\u0443 \u0432\u0435\u0440\u0441\u0456\u044e MainWindow.upgrade.section.info=\u041d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0456\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 MainWindow.upgrade.section.manual=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e MainWindow.upgrade.section.automatic=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e MainWindow.upgrade.tooltip.progressbar=\u041f\u0440\u043e\u0433\u0440\u0435\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043f\u043e\u043a\u0430\u0437\u0443\u0454\u0442\u044c\u0441\u044f \u0442\u0443\u0442 Button.next=\u0414\u0430\u043b\u0456 Button.finish=\u0413\u043e\u0442\u043e\u0432\u043e Button.cancel=&\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 LocaleUtil.title=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f LocaleUtil.section.chooseencoding=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0443 LocaleUtil.label.chooseencoding=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u0430\u0439\u043a\u0440\u0430\u0449\u0435 \u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f LocaleUtil.label.hint.doubleclick=\u041f\u043e\u0440\u0430\u0434\u0430: \u041f\u043e\u0434\u0432\u0456\u0439\u043d\u0435 \u043a\u043b\u0430\u0446\u0430\u043d\u043d\u044f \u0432\u0438\u0431\u0438\u0440\u0430\u0454 \u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f \u0456 \u0437\u0430\u043a\u0440\u0438\u0432\u0430\u0454 \u0434\u0456\u0430\u043b\u043e\u0433 LocaleUtil.label.checkbox.rememberdecision=\u0417\u0430\u043f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u0432\u0438\u0431\u0456\u0440 \u0434\u043b\u044f \u0456\u043d\u0448\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 LocaleUtil.column.encoding=\u041a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f IrcClient.copyright=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 IrcClient.connected=\u0417'\u0454\u0434\u043d\u0430\u043d\u0438\u0439 \u0437 IrcClient.joining=\u0417'\u0454\u0434\u043d\u0443\u0454\u0442\u044c\u0441\u044f IrcClient.channel=\u041a\u0430\u043d\u0430\u043b IrcClient.joined=\u0437'\u0454\u0434\u043d\u0430\u0432\u0441\u044f IrcClient.error=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 IrcClient.hasjoined=\u043f\u0440\u0438\u0454\u0434\u043d\u0430\u0432\u0441\u044f IrcClient.haskicked=\u0432\u0438\u043a\u0438\u043d\u0443\u0432\u0441\u044f IrcClient.hasleft=\u043f\u0456\u0448\u043e\u0432 IrcClient.nowknown=\u0437\u0430\u0440\u0430\u0437 \u0432\u0456\u0434\u043e\u043c\u0438\u0439 \u044f\u043a IrcClient.topicforchannel=\u0422\u0435\u043c\u0430 \u043a\u0430\u043d\u0430\u043b\u0443 IrcClient.disconnected=\u0412\u0456\u0434\u2019\u0454\u0434\u043d\u0430\u043d\u0438\u0439 \u0432\u0456\u0434 IrcClient.noNick=\u0412\u0438 \u0437\u0430\u0431\u0443\u043b\u0438 \u0432\u0438\u0431\u0440\u0430\u0442\u0438 \u0456\u043c'\u044f. \u0412\u0456\u0434\u043a\u0440\u0438\u0439\u0442\u0435 \u0432\u0456\u043a\u043d\u043e \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c \u0456 \u0432\u043a\u0430\u0436\u0456\u0442\u044c \u0456\u043c'\u044f IrcView.actionnotsupported=\u0426\u044f \u0444\u0443\u043d\u043a\u0446\u0456\u044f \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454\u0442\u044c\u0441\u044f IrcView.clientsconnected=\u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456 IrcView.privateto=\u0414\u043b\u044f IrcView.privatefrom=\u0412\u0456\u0434 IrcView.noticefrom=\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430 : IrcView.errormsg=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0432 /msg : /msg \u0432\u0430\u0448 \u0442\u0435\u043a\u0441\u0442 IrcView.help=\u0427\u0438\u043d\u043d\u0456 \u043a\u043e\u043c\u0430\u043d\u0434\u0438: \n/help : \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0446\u0435\u0439 \u0442\u0435\u043a\u0441\u0442\n/nick | /name : \u0437\u043c\u0456\u043d\u0438\u0442\u0438 \u0441\u0432\u0456\u0439 \u043d\u0456\u043a\n/me action : \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 \u043f\u0440\u0438\u043c\u0456\u0442\u043a\u0443\n/msg: \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 \u043e\u0441\u043e\u0431\u0438\u0441\u0442\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f <\u043d\u0456\u043a>\n/r message : \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0441\u0442\u0438 \u043d\u0430 \u043e\u0441\u043e\u0431\u0438\u0441\u0442\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f\n/join #channelB (\u043d\u0435 \u043a\u043b\u0430\u0446\u0430\u0439\u0442\u0435, \u0446\u0435 \u043f\u0440\u0438\u043a\u043b\u0430\u0434) : \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u0456\u043d\u0448\u0443 \u043a\u0456\u043c\u043d\u0430\u0442\u0443 PasswordWindow.title=Vuze \u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0439 PasswordWindow.passwordprotected=Vuze \u0437\u0430\u0445\u0438\u0449\u0435\u043d\u0438\u0439 \u043f\u0430\u0440\u043e\u043b\u0435\u043c.\n\u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0443 \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0432\u043a\u0430\u0436\u0456\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c : Button.ok=&O\u041a TrackerChangerWindow.title=\u0417\u0430\u043c\u0456\u043d\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 TrackerChangerWindow.newtracker=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0443 \u043d\u043e\u0432\u043e\u0433\u043e \u0442\u0440\u0435\u043a\u0435\u0440\u0443 PeersView.discarded=\u0412\u0456\u0434\u0445\u0438\u043b\u0435\u043d\u0438\u0439 PeersView.discarded.info=\u0421\u0442\u0435\u0440\u0442\u0456 \u0434\u0430\u043d\u0456, \u044f\u043a\u0456 \u0412\u0430\u043c \u043d\u0435 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0456 discarded=\u0432\u0456\u0434\u0445\u0438\u043b\u0435\u043d\u043e MyTorrentsView.menu.move=&\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 MyTorrentsView.menu.moveUp=\u0414\u043e&\u0433\u043e\u0440\u0438 MyTorrentsView.menu.moveDown=&\u0414\u043e\u043d\u0438\u0437\u0443 GeneralView.label.hashfails=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0445\u0435\u0448\u0443: GeneralView.label.shareRatio=\u041a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456: ConfigView.section.downloadManagement=\u041c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ConfigView.label.startRatioPeers=\u041f\u043e\u0447\u0430\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u043f\u0440\u0438 \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u043c\u0435\u043d\u0448\u0435 1 ConfigView.text.neverStop=\u041d\u0456\u043a\u043e\u043b\u0438 \u043d\u0435 \u0437\u0443\u043f\u0438\u043d\u044f\u0442\u0438 ConfigView.text.neverStart=\u041d\u0456\u043a\u043e\u043b\u0438 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438 ConfigView.text.peers=\u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 ConfigView.label.checkOncompletion=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0438\u0439 \u043e\u0433\u043b\u044f\u0434 \u0447\u0430\u0441\u0442\u0438\u043d \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f wizard.title=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 wizard.previous=< \u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438\u0441\u044f wizard.next=\u0414\u0430\u043b\u0456 > wizard.finish=\u0413\u043e\u0442\u043e\u0432\u043e wizard.mode=\u0422\u0440\u0435\u043a\u0435\u0440 / \u0420\u0435\u0436\u0438\u043c wizard.tracker=\u0422\u0440\u0435\u043a\u0435\u0440: wizard.invalidurl=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0430 \u0430\u0434\u0440\u0435\u0441\u0430 wizard.singlefile=\u041e\u0434\u0438\u043d \u0444\u0430\u0439\u043b wizard.singlefile.help=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0443 wizard.directory=\u0422\u0435\u043a\u0430 wizard.directory.help=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 wizard.choosefile=\u0412\u0438\u0431\u0456\u0440 \u0444\u0430\u0439\u043b\u0443 wizard.file=\u0424\u0430\u0439\u043b: wizard.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434... wizard.choosedirectory=\u0412\u0438\u0431\u0456\u0440 \u0442\u0435\u043a\u0438 wizard.invalidfile=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 \u0444\u0430\u0439\u043b! wizard.invaliddirectory=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430 \u0442\u0435\u043a\u0430! wizard.torrentFile=\u0422\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b wizard.choosetorrent=\u0412\u0438\u0431\u0456\u0440 torrent-\u0444\u0430\u0439\u043b\u0443 \u0434\u043b\u044f \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f wizard.information=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f wizard.notimplemented=\u0429\u0435 \u0432 \u0440\u043e\u0437\u0440\u043e\u0431\u0446\u0456 wizard.progresstitle=\u0421\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 wizard.savingfile=\u0417\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443... wizard.filesaved=\u0424\u0430\u0439\u043b \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0439. wizard.close=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 Torrent.create.progress.piecelength=\u0414\u043e\u0432\u0436\u0438\u043d\u0430 \u0447\u0430\u0441\u0442\u0438\u043d: Torrent.create.progress.piececount=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0447\u0430\u0441\u0442\u0438\u043d: Torrent.create.progress.totalfilesize=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440 \u0444\u0430\u0439\u043b\u0443: Torrent.create.progress.totalfilecount=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0444\u0430\u0439\u043b\u0456\u0432: Torrent.create.progress.parsingfiles=\u041f\u0430\u0440\u0441\u0456\u043d\u0433 \u0444\u0430\u0439\u043b\u0443 Torrent.create.progress.hashing=\u0425\u0435\u0448\u0443\u0432\u0430\u043d\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0456\u0432 MainWindow.upgrade.downloadingfrom=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437 : MainWindow.menu.view.ipFilter=&\u0424\u0456\u043b\u044c\u0442\u0440\u0438 IP ConfigView.section.ipfilter=\u0424\u0456\u043b\u044c\u0442\u0440\u0438 IP ConfigView.section.ipfilter.description=\u041e\u043f\u0438\u0441 ConfigView.section.ipfilter.start=\u041f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0430 IP ConfigView.section.ipfilter.end=\u041a\u0456\u043d\u0446\u0435\u0432\u0430 IP ConfigView.section.ipfilter.add=\u0414\u043e\u0434\u0430\u0442\u0438 ConfigView.section.ipfilter.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 ConfigView.section.ipfilter.edit=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 ConfigView.section.ipfilter.save=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 ConfigView.section.ipfilter.editFilter=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u0444\u0456\u043b\u044c\u0442\u0440 ConfigView.section.ipfilter.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 PeersView.menu.close=&\u0417\u0430\u043a\u0440\u0438\u0442\u0438 seedmore.title=\u0420\u043e\u0437\u0434\u0430\u0447\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043d\u044f seedmore.shareratio=\u0412\u0430\u0448\u0435 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0446\u044c\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0430 seedmore.uploadmore=\u0424\u0430\u043a\u0442\u043e\u0440 \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u043c\u0435\u043d\u0448\u0438\u0439 \u0437\u0430 100%, \u043f\u043e\u0433\u0430\u043d\u043e \u0432\u0456\u0434\u0431\u0438\u0432\u0430\u0454\u0442\u044c\u0441\u044f \u043d\u0430 bittorrent-\u043c\u0435\u0440\u0435\u0436\u0456.\n\u0412\u0438 \u043c\u0443\u0441\u0438\u0442\u0435 \u043d\u0435\u043d\u0430\u0434\u043e\u0432\u0433\u043e \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443.\n\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456 \u0432 \u0441\u0432\u043e\u0457\u0445 \u043d\u0430\u043c\u0456\u0440\u0430\u0445? ConfigView.label.showpopuponclose=\u041f\u0440\u0438 \u0437\u0443\u043f\u0438\u043d\u0446\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0437 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f\u043c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0438\u0436\u0447\u0435, \u043d\u0456\u0436 1, \u0437\u0430\u043f\u0438\u0442\u0430\u0442\u0438 \u043f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f ConfigView.label.startNumSeeds=\n\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u043f\u0440\u0438 \u043c\u0435\u043d\u0448 \u043d\u0456\u0436\n - \u0412\u0441\u0456 \u0456\u043d\u0448\u0456 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0456\u0433\u043d\u043e\u0440\u0443\u044e\u0442\u044c\u0441\u044f ConfigView.label.seeds=\u0441\u0456\u0434\u0435\u0440\u0456\u0432 ConfigView.section.seeding=\u0420\u043e\u0437\u0434\u0430\u0447\u0430 MyTorrentsView.menu.removeand=\u0412\u0438\u043b\u0443&\u0447\u0438\u0442\u0438 \u0456 MyTorrentsView.menu.removeand.deletetorrent=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 &\u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b MyTorrentsView.menu.removeand.deletedata=&\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 MyTorrentsView.menu.removeand.deleteboth=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0456 \u0437\u0430\u0432\u0430\u043d\u0442., \u0456 \u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b\u0438 deletedata.title=\u0412\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 deletedata.message1=\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0412\u0438 \u0437\u0431\u0438\u0440\u0430\u0454\u0442\u0435\u0441\u044f \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 '%1'? deletedata.noprompt=\u0411\u0456\u043b\u044c\u0448\u0435 \u043c\u0435\u043d\u0435 \u043d\u0435 \u0442\u0443\u0440\u0431\u0443\u0432\u0430\u0442\u0438 MainWindow.menu.file.configure=&\u041c\u0430\u0439\u0441\u0442\u0435\u0440 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c configureWizard.title=\u041c\u0430\u0439\u0441\u0442\u0435\u0440 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c configureWizard.welcome.title=\u041b\u0430\u0441\u043a\u0430\u0432\u043e \u043f\u0440\u043e\u0441\u0438\u043c\u043e \u0432 \u043c\u0430\u0439\u0441\u0442\u0435\u0440 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c Vuze configureWizard.welcome.message=\u0426\u0435\u0439 \u043c\u0430\u0439\u0441\u0442\u0435\u0440 \u0434\u043e\u043f\u043e\u043c\u043e\u0436\u0435 \u0412\u0430\u043c \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0438\u0442\u0438 Vuze \u0434\u043b\u044f \u0437\u0440\u0443\u0447\u043d\u0456\u0448\u043e\u0433\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f. \u0414\u043b\u044f \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u0456\u0448\u043e\u0433\u043e \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u043c\u0435\u043d\u044e \u0421\u0435\u0440\u0432\u0456\u0441 > \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f... configureWizard.transfer.title=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0434\u0430\u043d\u0438\u0445 \u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c configureWizard.transfer.hint=\u041f\u043e\u0440\u0430\u0434\u0430: \t\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456, \u0442\u0440\u043e\u0445\u0438 \u043c\u0435\u043d\u0448\u043e\u0457 \u0437\u0430 \u0432\u0430\u0448\u0443 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f configureWizard.transfer.message=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f. \u0412\u0456\u0437\u044c\u043c\u0456\u0442\u044c \u0434\u043e \u0443\u0432\u0430\u0433\u0438, \u0449\u043e \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432\u0456\u0434\u0431\u0438\u0432\u0430\u0454\u0442\u044c\u0441\u044f \u0432 \u043f\u043e\u0432\u0456\u043b\u044c\u043d\u0456\u0448\u0456\u0439 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. \u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432\u0440\u0430\u0445\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0437 \u043a\u043e\u0436\u043d\u0438\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u043c, \u044f\u043a\u0438\u0439 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u044c\u0441\u044f: \u0441\u043f\u0440\u043e\u0431\u0430 \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u043d\u0430\u0434\u0442\u043e \u0432\u0435\u043b\u0438\u043a\u043e\u0457 \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u044f\u0454 \u043f\u043e\u0432\u0456\u043b\u044c\u043d\u0443 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 5 \u041a\u0431\u0456\u0442/\u0441 \u043d\u0430 \u043a\u043e\u0436\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442 \u044f\u043a \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u0438\u0439 \u043c\u0456\u043d\u0456\u043c\u0443\u043c. \u0427\u0438\u043c \u0432\u0438\u0449\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0442\u0438\u043c \u0431\u0456\u043b\u044c\u0448\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f (\u0437\u0430\u043b\u0435\u0436\u043d\u043e \u0432\u0456\u0434 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0430). configureWizard.transfer.connection=\u0417\u0432'\u044f\u0437\u043e\u043a configureWizard.transfer.connection.0=\u0421\u043f\u0435\u0446\u0456\u0430\u043b\u044c\u043d\u0438\u0439 configureWizard.transfer.connection.1=\u043c\u043e\u0434\u0435\u043c configureWizard.transfer.connection.2=\u0410\u0414\u0421\u041b/\u041a\u0430\u0431\u0435\u043b\u044c xxx/128 \u041a\u0431\u0456\u0442/\u0441 configureWizard.transfer.connection.3=\u0410\u0414\u0421\u041b/\u041a\u0430\u0431\u0435\u043b\u044c xxx/256 \u041a\u0431\u0456\u0442/\u0441 configureWizard.transfer.connection.4=\u0410\u0414\u0421\u041b/\u041a\u0430\u0431\u0435\u043b\u044c xxx/384 \u041a\u0431\u0456\u0442/\u0441 configureWizard.transfer.connection.5=\u0410\u0414\u0421\u041b/\u041a\u0430\u0431\u0435\u043b\u044c xxx/512 \u041a\u0431\u0456\u0442/\u0441 configureWizard.transfer.connection.6=\u0410\u0414\u0421\u041b/\u041a\u0430\u0431\u0435\u043b\u044c xxx/768 \u041a\u0431\u0456\u0442/\u0441 configureWizard.transfer.connection.7=\u0410\u0414\u0421\u041b/\u041a\u0430\u0431\u0435\u043b\u044c xxx/1024 \u041a\u0431\u0456\u0442/\u0441 configureWizard.transfer.maxUpSpeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u041a\u0431\u0456\u0442/\u0441 configureWizard.transfer.maxActiveTorrents=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a-\u0442\u044c \u0447\u0438\u043d\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 configureWizard.transfer.maxDownloads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c configureWizard.transfer.maxUploadsPerTorrent=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 configureWizard.nat.title=NAT / \u041f\u043e\u0440\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 configureWizard.nat.message=\u0414\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0435\u0439 Vuze \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u043e\u0432\u043d\u0438\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u0406\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0443. \u0417\u0432\u0438\u0447\u0430\u0439\u043d\u043e \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0431\u0435\u0440\u0443\u0442\u044c\u0441\u044f \u043f\u043e\u0440\u0442\u0438 \u0437 6881 \u0434\u043e 6889. \u0426\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u043c\u043e\u0436\u0435 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u0456, \u044f\u043a\u0449\u043e \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e, \u0437\u043c\u0456\u043d\u0438\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456 \u043f\u043e\u0440\u0442\u0438. \u041f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u0435\u044f\u043a\u0456 \u043f\u043e\u0440\u0442\u0438 \u043c\u043e\u0436\u0443\u0442\u044c \u0431\u0443\u0442\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456, \u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434, 6880. configureWizard.nat.test=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 configureWizard.nat.testing=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043e\u0440\u0442\u0443 configureWizard.nat.ko=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 NAT configureWizard.nat.unable=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e. \u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0456 \u043f\u043e\u0440\u0442 \u0430\u0431\u043e \u0441\u043b\u0443\u0436\u0431\u0430 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438. configureWizard.file.title=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 / \u0424\u0430\u0439\u043b\u0438 configureWizard.file.message1=\u0417\u0430\u043f\u0438\u0441 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0443 \u0437\u0430\u0434\u0430\u043d\u0456\u0439 \u0442\u0435\u0446\u0456. \u0412\u0438\u0431\u0456\u0440: configureWizard.file.path=\u0422\u0435\u043a\u0430 configureWizard.file.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 configureWizard.file.message2=Vuze \u043c\u0430\u0454 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u043d\u0435\u0433\u0430\u0439\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0435\u043d\u043d\u044f \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u0434\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0432\u043d\u0438\u0445 \u0434\u0430\u043d\u0438\u0445 \u0434\u043e \u0432\u0430\u0448\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432. \u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0447\u0438 \u0446\u044e \u0444\u0443\u043d\u043a\u0446\u0456\u044e, \u0454 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u0434\u043e\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043d\u0435 \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 \u0447\u0430\u0441\u0442\u0438\u043d. configureWizard.file.fastResume=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 "\u0448\u0432\u0438\u0434\u043a\u0435" \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0435\u043d\u043d\u044f configureWizard.file.invalidPath=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430 \u0442\u0435\u043a\u0430 configureWizard.finish.title=\u0413\u043e\u0442\u043e\u0432\u043e configureWizard.finish.message=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u043e\u0441\u044f. \u0411\u0430\u0436\u0430\u0454\u043c\u043e \u0412\u0430\u043c \u0432\u0434\u0430\u043b\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0447\u0430\u0441! wizard.close.confirmation=\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f wizard.close.message=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u043c\u0430\u0439\u0441\u0442\u0435\u0440 \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438? exportTorrentWizard.title=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0432 \u0444\u0430\u0439\u043b XML exportTorrentWizard.torrentfile.title=\u0412\u0438\u0431\u0456\u0440 \u0432\u0445\u0456\u0434\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 exportTorrentWizard.torrentfile.message=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u043b\u044f \u0435\u043a\u0441\u043f\u043e\u0440\u0442\u0443 exportTorrentWizard.torrentfile.path=\u0428\u043b\u044f\u0445 exportTorrentWizard.torrentfile.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 exportTorrentWizard.torrentfile.invalidPath=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 exportTorrentWizard.exportfile.title=\u0412\u0438\u0431\u0456\u0440 \u0444\u0430\u0439\u043b\u0443 \u0434\u043b\u044f \u0435\u043a\u0441\u043f\u043e\u0440\u0442\u0443 exportTorrentWizard.exportfile.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0444\u0430\u0439\u043b XML \u0434\u043b\u044f \u0435\u043a\u0441\u043f\u043e\u0440\u0442\u0443 exportTorrentWizard.exportfile.path=\u0428\u043b\u044f\u0445 exportTorrentWizard.exportfile.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 exportTorrentWizard.exportfile.invalidPath=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0443 \u0444\u0430\u0439\u043b\u0456 \u0435\u043a\u0441\u043f\u043e\u0440\u0442\u0443 exportTorrentWizard.finish.title=\u0413\u043e\u0442\u043e\u0432\u043e exportTorrentWizard.finish.message=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0439 \u0443\u0441\u043f\u0456\u0448\u043d\u043e exportTorrentWizard.process.inputfilebad.title=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 exportTorrentWizard.process.inputfilebad.message=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u0443 \u0434\u043e \u0432\u0445\u0456\u0434\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0443: exportTorrentWizard.process.outputfileexists.title=\u0424\u0430\u0439\u043b \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454 exportTorrentWizard.process.outputfileexists.message=\u0424\u0430\u0439\u043b \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454 - \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u0438? exportTorrentWizard.process.torrentfail.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0447\u0438\u0442\u0430\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 exportTorrentWizard.process.exportfail.title=\u041d\u0435\u0432\u0434\u0430\u043b\u0438\u0439 \u0435\u043a\u0441\u043f\u043e\u0440\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 exportTorrentWizard.process.unknownfail.title=\u041d\u0435\u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 importTorrentWizard.title=\u0406\u043c\u043f\u043e\u0440\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 XML importTorrentWizard.torrentfile.title=\u0412\u0438\u0431\u0456\u0440 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 importTorrentWizard.torrentfile.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0456\u043c\u2019\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0434\u043b\u044f \u0456\u043c\u043f\u043e\u0440\u0442\u0443 importTorrentWizard.torrentfile.path=\u0428\u043b\u044f\u0445 importTorrentWizard.torrentfile.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 importTorrentWizard.torrentfile.invalidPath=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 importTorrentWizard.importfile.title=\u0412\u0438\u0431\u0456\u0440 \u0444\u0430\u0439\u043b\u0443 \u0456\u043c\u043f\u043e\u0440\u0442\u0443 importTorrentWizard.importfile.message=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0456\u043c\u043f\u043e\u0440\u0442\u0443 importTorrentWizard.importfile.path=\u0428\u043b\u044f\u0445 importTorrentWizard.importfile.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 importTorrentWizard.importfile.invalidPath=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0444\u0430\u0439\u043b\u0443 \u0456\u043c\u043f\u043e\u0440\u0442\u0443 importTorrentWizard.finish.title=\u041f\u0440\u043e\u0446\u0435\u0441 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0439 importTorrentWizard.finish.message=\u0406\u043c\u043f\u043e\u0440\u0442 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0439 \u0432\u0434\u0430\u043b\u043e importTorrentWizard.process.inputfilebad.title=\u0406\u043c\u043f\u043e\u0440\u0442\u043e\u0432\u0430\u043d\u0438\u0439 \u0444\u0430\u0439\u043b \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0439 importTorrentWizard.process.inputfilebad.message=\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0456: importTorrentWizard.process.outputfileexists.title=\u0424\u0430\u0439\u043b \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454 importTorrentWizard.process.outputfileexists.message=\u0424\u0430\u0439\u043b \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454 - \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u0438? importTorrentWizard.process.torrentfail.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 importTorrentWizard.process.importfail.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u043e \u0456\u043c\u043f\u043e\u0440\u0442\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 importTorrentWizard.process.unknownfail.title=\u041d\u0435\u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 ConfigView.label.bindip=\u041f\u0440\u0438\u0432'\u044f\u0437\u0430\u0442\u0438 \u0434\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0457 IP-\u0430\u0434\u0440\u0435\u0441\u0438 ConfigView.label.xfs.allocation=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u044f\u0442\u0438 \u043d\u043e\u0432\u0456 \u0444\u0430\u0439\u043b\u0438, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0447\u0438 \u043c\u0435\u0442\u043e\u0434, \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u043d\u0438\u0439 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c XFS ConfigView.label.xfs.allocation.tooltip=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u043f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0439\u0442\u0435\u0441\u044f \u0449\u043e /usr/sbin/xfs_io \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0443 \u0432\u0430\u0448\u0456\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0456. \u041d\u0430 \u0431\u0430\u0433\u0430\u0442\u044c\u043e\u0445 Linux'\u0430\u0445 \u0432\u0436\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u043d\u0456\u0439 \u0432 \u043f\u0430\u043a\u0435\u0442\u0456 "xfsprogs". xfs.allocation.xfs_io.not.found=XFS-\u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 \u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435, \u0442\u043e\u043c\u0443 \u0449\u043e /usr/sbin/xfs_io \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u043d\u0438\u043c. \u041f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0439\u0441\u044f, \u0449\u043e \u0432\u043e\u043d\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0456. \u041a\u0456\u043d\u0446\u0435\u0432\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430: "%1". ConfigView.label.zeronewfiles=\u041f\u0456\u0434\u0433\u043e\u0442\u0443\u0432\u0430\u0442\u0438 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0456 \u0441\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043d\u043e\u0432\u0438\u0439 \u0437\u0430\u043f\u043e\u0432\u043d\u0435\u043d\u0438\u0439 \u043d\u0443\u043b\u044f\u043c\u0438 \u0444\u0430\u0439\u043b ConfigView.label.zeronewfiles.tooltip=\u0417\u043c\u0435\u043d\u0448\u0443\u0454 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430\u0446\u0456\u044e ConfigView.section.stats=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 ConfigView.section.stats.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 ConfigView.section.stats.defaultsavepath=\u0422\u0435\u043a\u0430 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 ConfigView.section.stats.choosedefaultsavepath=\u0412\u0438\u0431\u0456\u0440 \u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 ConfigView.section.stats.savefreq=\u0427\u0430\u0441\u0442\u043e\u0442\u0430 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f ConfigView.section.stats.minutes=\u0445\u0432 ConfigView.section.stats.hours=\u0433\u043e\u0434 ConfigView.section.stats.seconds=\u0441 ConfigView.section.stats.savefile=\u0406\u043c'\u044f \u0444\u0430\u0439\u043b\u0443 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 ConfigView.section.stats.graph_update_dividers=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u0443 \u043b\u0456\u043d\u0456\u044e \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0436\u043d\u0456 60 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c MyTorrentsView.menu.export=&\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 XML... MyTorrentsView.menu.host=&\u0425\u043e\u0441\u0442... ManagerItem.finishing=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f ConfigView.dialog.choosedefaulttorrentpath=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 ConfigView.dialog.choosemovepath=\u0412\u0438\u0431\u0435\u0440\u0435\u0442\u0435 \u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0443 ConfigView.label.movecompleted=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 (\u043f\u0456\u0441\u043b\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f) ConfigView.label.moveremoved=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 (\u043a\u043e\u043b\u0438 \u043d\u0435 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u0456) ConfigView.label.savetorrents=\u0417\u0431\u0435\u0440\u0456\u0433\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 MainWindow.menu.view.mytracker=\u041c\u043e\u0457 &\u0442\u0440\u0435\u043a\u0435\u0440\u0438 MyTrackerView.title.full=\u041c\u043e\u0457 \u0442\u0440\u0435\u043a\u0435\u0440\u0438 MyTrackerView.name=\u041d\u0430\u0437\u0432\u0430 MyTrackerView.tracker=\u0422\u0440\u0435\u043a\u0435\u0440 MyTrackerView.status=\u0421\u0442\u0430\u0442\u0443\u0441 MyTrackerView.status.started=\u0412\u0438\u043a\u043e\u043d\u0443\u0454\u0442\u044c\u0441\u044f MyTrackerView.status.stopped=\u0417\u0443\u043f\u0438\u043d\u0435\u043d\u0438\u0439 MyTrackerView.peers=\u0423\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 MyTrackerView.seeds=\u0421\u0456\u0434\u0435\u0440\u0438 MyTrackerView.announces=\u0410\u043d\u043e\u043d\u0441\u0438 MyTrackerView.uploaded=\u0420\u043e\u0437\u0434\u0430\u043d\u0438\u0439 MyTrackerView.downloaded=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439 MyTrackerView.left=\u0417\u0430\u043b\u0438\u0448\u0438\u043b\u043e\u0441\u044f ConfigView.section.style=\u0412\u0438\u0433\u043b\u044f\u0434 ConfigView.label.set_ui_transfer_speeds=\u041f\u0456\u0434\u043c\u0456\u043d\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0456 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456 ConfigView.label.set_ui_transfer_speeds.description=\u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0438\u0431\u0440\u0430\u0442\u0438 \u0432\u0440\u0443\u0447\u043d\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432 \u0440\u044f\u0434\u043a\u0443 \u0441\u0442\u0430\u0442\u0443\u0441\u0443 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0442\u0440\u0435\u044e.\n\u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043c\u0430\u044e\u0442\u044c \u0440\u043e\u0437\u0434\u0456\u043b\u044f\u0442\u0438\u0441\u044f \u043a\u043e\u043c\u043e\u044e. ConfigView.label.set_ui_transfer_speeds.description.download=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f (\u041a\u0431\u0456\u0442/c) ConfigView.label.set_ui_transfer_speeds.description.upload=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 (\u041a\u0431\u0456\u0442/c) ConfigView.section.style.useCustomTabs=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0438, \u044f\u043a\u0456 \u0437\u0430\u043a\u0440\u0438\u0432\u0430\u044e\u0442\u044c\u0441\u044f (\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443) MainWindow.menu.view.plugins=\u0414\u043e&\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f fileDownloadWindow.saveTorrentIn=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0432 fileDownloadWindow.title=Vuze - \u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 fileDownloadWindow.downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0437 : fileDownloadWindow.status=\u0421\u0442\u0430\u0442\u0443\u0441 : fileDownloadWindow.state_initializing=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f fileDownloadWindow.state_downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f fileDownloadWindow.state_error=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 : MainWindow.menu.file.open.url=&\u0420\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f openUrl.title=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f openUrl.url=\u0410\u0434\u0440\u0435\u0441\u0430 : MyTorrentsView.menu.host.error.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0445\u043e\u0441\u0442\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 MyTorrentsView.menu.host.error.message=\u041f\u0440\u0438 \u0445\u043e\u0441\u0442\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0432\u0438\u043d\u0438\u043a\u043b\u0430 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 ConfigView.section.tracker=\u0422\u0440\u0435\u043a\u0435\u0440\u0438 ConfigView.section.tracker.pollinterval=\u0406\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u0434\u043b\u044f \u043f\u0456\u0434\u0440\u0430\u0445\u0443\u043d\u043a\u0443 \u0433\u043e\u043b\u043e\u0441\u0456\u0432 (\u0441\u0435\u043a\u0443\u043d\u0434\u0438) ConfigView.section.tracker.publishenable=\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 \u0434\u0435\u0442\u0430\u043b\u0456 \u043f\u0440\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0430 "/" ConfigView.section.tracker.ip=\u0417\u043e\u0432\u043d\u0456\u0448\u043d\u0456\u0439 IP \u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.style.enableXPStyle=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0441\u0442\u0438\u043b\u044c XP (\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443) IPChecker.external.service.dyndns.name=\u0414\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0438\u0439 DNS IPChecker.external.service.dyndns.description=\u0414\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0456 \u0441\u0435\u0440\u0432\u0456\u0441\u0438 \u043c\u0435\u0440\u0435\u0436\u0456 DNS, LLC ConfigView.section.tracker.checkip=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0432\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u044c\u043e\u0457 \u0430\u0434\u0440\u0435\u0441\u0438... ipCheckerWizard.title=\u041c\u0430\u0439\u0441\u0442\u0435\u0440 "\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 IP" ipCheckerWizard.service=\u0421\u0435\u0440\u0432\u0456\u0441 ipCheckerWizard.chooseService=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0441\u0435\u0440\u0432\u0456\u0441 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 IP \u0437 \u043d\u0438\u0436\u0447\u0435 \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0445 ipCheckerWizard.explanations=\u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0446\u0435\u0439 \u043c\u0430\u0439\u0441\u0442\u0435\u0440 \u0434\u043b\u044f \u0432\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u044c\u043e\u0457 IP-\u0430\u0434\u0440\u0435\u0441\u0438. \u042f\u043a\u0449\u043e \u0432\u0430\u0448 IP \u0434\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0438\u0439, \u043c\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u043c\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0441\u0435\u0440\u0432\u0456\u0441 "\u0414\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0456 \u0441\u0435\u0440\u0432\u0456\u0441\u0438 DNS". \u041d\u0438\u0436\u0447\u0435 \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0456 \u0434\u0435\u044f\u043a\u0456 \u0441\u043b\u0443\u0436\u0431\u0438, \u0449\u043e \u043f\u0440\u043e\u043f\u043e\u043d\u0443\u044e\u0442\u044c \u0446\u0435\u0439 \u0441\u0435\u0440\u0432\u0456\u0441, \u0430\u0434\u0440\u0435\u0441\u0438 \u044f\u043a\u0438\u0445 \u0432\u0435\u0434\u0443\u0442\u044c \u0434\u043e \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u0457 (\u044f\u043a\u0449\u043e \u0432\u043e\u043d\u0430 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0430). \u041f\u043e\u0442\u0456\u043c \u0432\u043a\u0430\u0436\u0456\u0442\u044c \u0432 \u043f\u043e\u043b\u0456 IP-\u0430\u0434\u0440\u0435\u0441\u0438 \u0456\u043c'\u044f \u0432\u0430\u0448\u043e\u0433\u043e \u0445\u043e\u0441\u0442\u0443 (\u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434: myhostname.dyndns.org). \u0412\u0430\u043c \u0437\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0433\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0433\u043e "\u0414\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0456\u0441\u0443 DNS\u201d \u043d\u043e\u0432\u043e\u044e IP-\u0430\u0434\u0440\u0435\u0441\u043e\u044e. \u0423 \u0446\u044c\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u0412\u0438 \u0437\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u043f\u043e\u043d\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u043d\u0430\u0432\u0456\u0442\u044c \u044f\u043a\u0449\u043e \u0432\u0430\u0448 IP \u0437\u043c\u0456\u043d\u044e\u0454\u0442\u044c\u0441\u044f. ipCheckerWizard.service.description=\u041e\u043f\u0438\u0441 : ipCheckerWizard.service.url=\u041b\u0430\u043d\u043a\u0430: ipCheckerWizard.progresstitle=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 IP ipCheckerWizard.checkComplete=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0435\u043d\u0456 IP : ipCheckerWizard.checkFailed=\u041f\u043e\u043c\u0438\u043b\u043a\u0430! \u041f\u0440\u0438\u0447\u0438\u043d\u0430 : wizard.tracker.local=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 Vuze wizard.tracker.external=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u0456\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 wizard.tracker.howToLocal=\t\u0414\u043b\u044f \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c '\u0421\u0435\u0440\u0432\u0456\u0441 > \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f > \u0422\u0440\u0435\u043a\u0435\u0440\u0438' wizard.announceUrl=\u0410\u0434\u0440\u0435\u0441\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 : IPChecker.external.service.discoveryvip.name=\u0421\u0435\u0440\u0432\u0456\u0441 Discoveryvip IPChecker.external.service.discoveryvip.description=Discoveryvip - \u043b\u0438\u0448\u0435 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 IP-\u0430\u0434\u0440\u0435\u0441\u0438 IPChecker.external.httpinvalidresponse=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0432 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0456 HTTP IPChecker.external.loadingwebpage=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438 \u0406\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0443 IPChecker.external.analysingresponse=\u0410\u043d\u0430\u043b\u0456\u0437 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0456 IPChecker.external.addressextracted=\u0414\u043e\u0431\u0443\u0442\u0456 \u0430\u0434\u0440\u0435\u0441\u0438 IP IPChecker.external.httploadfail=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u0456 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438 IPChecker.external.timeout=\u0427\u0430\u0441 \u043c\u0438\u043d\u0443\u0432 IPChecker.external.ipnotfound=IP-\u0430\u0434\u0440\u0435\u0441\u0430 \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0430 ConfigView.section.tracker.pollintervalmin=\u041c\u0456\u043d\u0456\u043c\u0443\u043c ConfigView.section.tracker.pollintervalmax=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c ConfigView.section.tracker.pollintervalincby=\u041f\u0456\u0434\u0432\u0438\u0449\u0443\u0432\u0430\u0442\u0438 \u043d\u0430 ConfigView.section.tracker.pollintervalincper=\u041a\u043e\u0436\u043d\u0456 N \u043a\u043b\u0456\u0454\u043d\u0442\u0456\u0432 splash.loadingImages=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c splash.initializeGui=\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0454\u0442\u044c\u0441\u044f \u0433\u043e\u043b\u043e\u0432\u043d\u0435 \u0432\u0456\u043a\u043d\u043e splash.openViews=\u0412\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u044e\u0442\u044c\u0441\u044f \u0432\u0438\u0433\u043b\u044f\u0434\u0438 splash.plugin=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f: configureWizard.nat.tooManyPorts=\u0417\u0430\u043d\u0430\u0434\u0442\u043e \u0431\u0430\u0433\u0430\u0442\u043e \u043f\u043e\u0440\u0442\u0456\u0432 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 (\u043c\u0430\u043a\u0441. 9) ConfigView.section.color=\u0421\u0445\u0435\u043c\u0430 \u043a\u043e\u043b\u044c\u043e\u0440\u0456\u0432 MyTorrentsView.menu.publish=&\u041f\u0443\u0431\u043b\u0456\u043a\u0430\u0446\u0456\u044f... MyTrackerView.status.published=\u041e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0438\u0439 MyTrackerView.completed=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439 MainWindow.menu.file.open.torrentnodefault=\u0422\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b... (\u0431\u0435\u0437 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f) wizard.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 ConfigView.label.movetorrent=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.label.movepartialdownloads=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438, \u043d\u0430\u0432\u0456\u0442\u044c \u043a\u043e\u043b\u0438 \u0434\u0435\u044f\u043a\u0456 \u0444\u0430\u0439\u043b\u0438 \u0432\u0456\u0434\u0437\u043d\u0430\u0447\u0435\u043d\u0456 "\u041d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438" ConfigView.label.subdir_is_in_default=\u0412\u0440\u0430\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438, \u0449\u043e \u044f\u043a\u0449\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456\u0441\u043d\u0443\u044e\u0442\u044c \u0443 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456\u0439 \u0442\u0435\u0446\u0456, \u0442\u043e \u0446\u0435 \u0441\u0442\u043e\u0441\u0443\u0454\u0442\u044c\u0441\u044f \u0456 \u043f\u0456\u0434\u0442\u0435\u043a ConfigView.section.file.decoder.label=C\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443,\n \u044f\u043a\u0449\u043e \u043f\u043e\u0442\u0440\u0456\u0431\u0435\u043d \u0432\u0438\u0431\u0456\u0440 ConfigView.section.file.decoder.nodecoder=\u041d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442. IPChecker.external.service.no-ip.name=\u041d\u0435 IP IPChecker.external.service.no-ip.description=\u0421\u043b\u0443\u0436\u0431\u0438 \u0441\u0435\u0440\u0432\u0456\u0441\u0456\u0432 \u0434\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0438\u0445 \u0456 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u0438\u0445 DNS\n (\u0431\u0435\u0437 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0456\u0441\u0443 '\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0406\u0420') ConfigView.section.tracker.publicenable=\u0414\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.label.playdownloadspeech=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 \u0441\u0438\u043d\u0442\u0435\u0437\u0430\u0442\u043e\u0440 \u043c\u043e\u0432\u0438 \u043f\u0440\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ConfigView.label.playdownloadspeech.info=\u0421\u0438\u043d\u0442\u0435\u0437\u0430\u0442\u043e\u0440 \u043c\u043e\u0432\u0438 \u043d\u0430\u0439\u043a\u0440\u0430\u0449\u0435 \u043f\u0440\u0430\u0446\u044e\u0454 \u0437 \u0430\u043d\u0433\u043b\u0456\u0439\u0441\u044c\u043a\u043e\u044e \u043c\u043e\u0432\u043e\u044e # # Tooltips # GeneralView.label.status.pieces_available.tooltip=\u041f\u043e\u043a\u0430\u0437\u0443\u0454 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u043a\u043e\u043f\u0456\u0439 \u043a\u043e\u0436\u043d\u043e\u0457 \u0447\u0430\u0441\u0442\u0438\u043d\u0438.\n\u042f\u043a\u0449\u043e \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043c\u0435\u043d\u0448\u0435 1, \u0442\u043e\u0434\u0456 \u0432\u0435\u0441\u044c \u0444\u0430\u0439\u043b \u043d\u0430 \u0434\u0430\u043d\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439, \u0446\u0435 \u043c\u043e\u0436\u0435 \u0437\u0440\u043e\u0431\u0438\u0442\u0438 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u0438\u043c \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. GeneralView.label.trackerurl.tooltip=\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0437\u0430\u043f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443 \u0430\u043d\u043e\u043d\u0441\u0430 GeneralView.label.trackerurlopen.tooltip=\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 # # 2.0.4.4 # ConfigView.section.style.guiUpdate=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0433\u0440\u0430\u0444\u0456\u0447\u043d\u043e\u0433\u043e \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f \u043a\u043e\u0436\u043d\u0456 ConfigView.section.style.inactiveUpdate=\u041f\u043e\u043d\u043e\u0432\u043b\u044e\u0432\u0430\u0442\u0438 \u0433\u043e\u043b\u043e\u0432\u043d\u0435 \u0432\u0456\u043a\u043d\u043e \u043a\u043e\u0436\u043d\u0456 N \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u0433\u0440\u0430\u0444\u0456\u0447\u043d\u043e\u0433\u043e \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f, \u043a\u043e\u043b\u0438 \u0432\u0456\u043a\u043d\u043e \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u0435 ConfigView.section.style.graphicsUpdate=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0433\u0440\u0430\u0444\u0456\u0447\u043d\u0438\u0445 \u043b\u043e\u0433\u0456\u0432 \u043a\u043e\u0436\u043d\u0456 N \u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u0433\u0440\u0430\u0444\u0456\u0447\u043d\u043e\u0433\u043e \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f ConfigView.section.style.reOrderDelay=\u041f\u0435\u0440\u0435\u0433\u0440\u0443\u043f\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044c \u043a\u043e\u0436\u043d\u0456 N \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u0433\u0440\u0430\u0444\u0456\u0447\u043d\u043e\u0433\u043e \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f [0: \u043d\u0456\u043a\u043e\u043b\u0438] ConfigView.section.style.reOrderDelay.never=\u041d\u0456\u043a\u043e\u043b\u0438 ConfigView.section.logging=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0432 \u0444\u0430\u0439\u043b .log ConfigView.section.logging.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0432 \u0444\u0430\u0439\u043b .log ConfigView.section.logging.logdir=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 .log \u0432 \u0442\u0435\u043a\u0443 ConfigView.section.logging.choosedefaultsavepath=\u0412\u0438\u0431\u0456\u0440 \u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f GeneralView.label.updatein.querying=\u0417'\u0454\u0434\u043d\u0443\u044e\u0441\u044f... configureWizard.nat.sharePort=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043e\u0434\u0438\u043d \u0432\u0445\u0456\u0434\u043d\u0438\u0439 \u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0432\u0441\u0456\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 ConfigView.section.logging.maxsize=\u041c\u0430\u043a\u0441. \u0440\u043e\u0437\u043c\u0456\u0440 \u0444\u0430\u0439\u043b\u0443 \u043b\u043e\u0433\u0443 ConfigView.section.tracker.passwordenableweb=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u0432 \u043c\u0435\u0440\u0435\u0436\u0456 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 ConfigView.section.tracker.passwordenabletorrent=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.section.tracker.username=\u0406\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 ConfigView.section.tracker.password=\u041f\u0430\u0440\u043e\u043b\u044c columnChooser.title=\u0412\u0438\u0431\u0456\u0440 \u0441\u0442\u043e\u0432\u043f\u0446\u0456\u0432 columnChooser.move=\u041f\u0435\u0440\u0435\u0442\u044f\u0433\u043d\u0456\u0442\u044c \u0434\u043b\u044f \u0437\u043c\u0456\u043d\u0438 \u0447\u0435\u0440\u0433\u043e\u0432\u043e\u0441\u0442\u0456 columnChooser.apply=\u0417\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438 columnChooser.columnname=\u041d\u0430\u0437\u0432\u0430 \u0441\u0442\u043e\u0432\u043f\u0446\u044f columnChooser.columndescription=\u041e\u043f\u0438\u0441 TableColumn.header.shareRatio=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 MyTorrentsView.menu.editTableColumns=&\u0412\u0438\u0431\u0456\u0440 \u0441\u0442\u043e\u0432\u043f\u0446\u0456\u0432 wizard.operationfailed=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u044f \u043d\u0435 \u043f\u0440\u043e\u0439\u0448\u043b\u0430 \u0443\u0441\u043f\u0456\u0448\u043d\u043e authenticator.title=\u041f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u043f\u0430\u0440\u043e\u043b\u044c authenticator.realm=\u0414\u0456\u043b\u044f\u043d\u043a\u0430 authenticator.tracker=\u0422\u0440\u0435\u043a\u0435\u0440 authenticator.user=\u0406\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 authenticator.password=\u041f\u0430\u0440\u043e\u043b\u044c ConfigView.label.allowSendVersion=\u0414\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 Vuze \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u0435 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u043d\u043e\u043c\u0435\u0440\u0430 \u0432\u0435\u0440\u0441\u0456\u0457 \u0456 \u0432\u0438\u0431\u0456\u0440\u043a\u043e\u0432\u043e\u0457 \u0456\u0434\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u0457 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438. ConfigView.label.version.info.link=\u0412\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 \u0434\u043b\u044f \u0431\u0456\u043b\u044c\u0448 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u043f\u0440\u043e \u0442\u0435, \u044f\u043a\u0456 \u0434\u0430\u043d\u0456 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0456 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u0432\u0435\u0440\u0441\u0456\u0457 wizard.hint.mode=\u041f\u043e\u0440\u0430\u0434\u0430:\t\u041c\u043e\u0436\u043d\u0430 \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u043d\u0443\u0442\u0438 \u0443 \u0432\u0456\u043a\u043d\u043e \u043c\u0430\u0439\u0441\u0442hf\n\t\u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0456 \u0444\u0430\u0439\u043b \u0430\u0431\u043e \u0442\u0435\u043a\u0443 wizard.hint.file=\u041f\u043e\u0440\u0430\u0434\u0430:\t\u041c\u043e\u0436\u043b\u0438\u0432\u0438\u0439 \u0432\u0438\u0431\u0456\u0440 \u0444\u0430\u0439\u043b\u0443 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 wizard.hint.directory=\u041f\u043e\u0440\u0430\u0434\u0430:\t\u041c\u043e\u0436\u043b\u0438\u0432\u0438\u0439 \u0432\u0438\u0431\u0456\u0440 \u0442\u0435\u043a\u0438 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u0443\u0432\u0430\u043d\u043d\u044f MainWindow.menu.help.checkupdate=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043f\u043e&\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f TableColumn.header.down=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 TableColumn.header.up=\u0420\u043e\u0437\u0434\u0430\u043d\u0456 ConfigView.section.tracker.passwordenabletorrent.info=\u041f\u043e\u0442\u0440\u0456\u0431\u043d\u0438\u0439 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u043d\u0438\u0439 BitTorrent-\u043a\u043b\u0456\u0454\u043d\u0442 (\u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434: Vuze) ConfigView.section.style.confirmationOnExit=\u0417\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 \u043f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f, \u043a\u043e\u043b\u0438 \u0412\u0438 \u0432\u0438\u0445\u043e\u0434\u0438\u0442\u0435 MainWindow.dialog.exitconfirmation.title=\u0412\u0438\u0439\u0442\u0438 \u0437 Vuze MainWindow.dialog.exitconfirmation.text=\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u043f\u043e\u043a\u0438\u043d\u0443\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443 SystemTray.menu.stopalltransfers=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f TrayWindow.menu.stopalldownloads=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0432\u0441&\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ConfigView.section.tracker.sslport.info=\u0414\u0438\u0432. FAQ \u0434\u043b\u044f \u043f\u043e\u0434\u0430\u043b\u044c\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 wizard.tracker.ssl=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 SSL ConfigView.label.playdownloadfinished=\u041f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043c\u0443\u0437. \u0444\u0430\u0439\u043b ConfigView.label.popupdownloadfinished=\u0412\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043f\u0440\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ConfigView.label.popupfilefinished=\u0412\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043f\u0440\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439 \u0444\u0430\u0439\u043b TableColumn.header.pieces=\u0427\u0430\u0441\u0442\u0438\u043d TableColumn.header.pieces.info=\u0413\u0440\u0430\u0444\u0456\u0447\u043d\u0438\u0439 \u043f\u043e\u043a\u0430\u0437\u043d\u0438\u043a \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 \u0447\u0430\u0441\u0442\u0438\u043d TableColumn.header.completion=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f TableColumn.header.completion.info=\u0421\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432 % ConfigView.section.style.showdownloadbasket=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 "\u043a\u043e\u0448\u0438\u043a \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c" (\u0443 \u044f\u043a\u0438\u0439 \u043c\u043e\u0436\u043d\u0430 \u0437\u0430\u043a\u0438\u0434\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432) ConfigView.section.style.alwaysShowTorrentFiles=\u0417\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u0443 (\u0444\u0430\u0439\u043b\u043e\u0432\u0443) \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438 wizard.multitracker=\u0414\u043e\u0434\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0437 \u043c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440\u0443 wizard.multitracker.title=\u041c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440 wizard.multitracker.configuration=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440\u0430 wizard.multitracker.new=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438... wizard.multitracker.edit=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438... wizard.multitracker.delete=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 wizard.multitracker.group=\u0413\u0440\u0443\u043f\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0456\u0432 wizard.multitracker.edit.title=\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440\u0430 wizard.multitracker.edit.name=\u041d\u0430\u0437\u0432\u0430 wizard.multitracker.edit.save=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 wizard.multitracker.edit.newgroup=\u041d\u043e\u0432\u0430 \u0433\u0440\u0443\u043f\u0430 wizard.multitracker.edit.deletegroup=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 wizard.multitracker.edit.newtracker=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 wizard.multitracker.edit.deletetracker=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 wizard.multitracker.edit.edit=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 wizard.addingmt=\u0414\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0437 \u043c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440\u0443 wizard.multitracker.noannounce=\u0410\u0434\u0440\u0435\u0441\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0435 \u0456\u0441\u043d\u0443\u0454 \u0432 \u0441\u043f\u0438\u0441\u043a\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0456\u0432 MyTorrentsView.menu.recheck=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043f\u0440\u0438&\u0441\u043a\u043e\u0440\u0435\u043d\u043e iconBar.showDownloadBar.tooltip=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f iconBar.start.tooltip=\u041f\u043e\u0447\u0430\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0439(\u0456) \u0442\u043e\u0440\u0435\u043d\u0442(\u0438) iconBar.stop.tooltip=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0439(\u0456) \u0442\u043e\u0440\u0435\u043d\u0442(\u0438) iconBar.remove.tooltip=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 iconBar.openNoDefault.tooltip=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b (\u0431\u0435\u0437 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f) iconBar.openURL.tooltip=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443 iconBar.openFolder.tooltip=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u0435\u043a\u0443 iconBar.new.tooltip=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 iconBar.up.tooltip=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0434\u043e\u0433\u043e\u0440\u0438 iconBar.down.tooltip=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0434\u043e\u043d\u0438\u0437\u0443 iconBar.run.tooltip=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 iconBar.host.tooltip=\u0425\u043e\u0441\u0442 iconBar.publish.tooltip=\u041e\u043f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 iconBar.editcolumns.tooltip=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0441\u0442\u043e\u0432\u043f\u0446\u044f MyTorrentsView.menu.editTracker=&\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443(\u0438) \u0442\u0440\u0435\u043a\u0435\u0440\u0443 GeneralView.menu.selectTracker=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 ConfigView.section.stats.xslfile=\u0406\u043c'\u044f XSL-\u0444\u0430\u0439\u043b\u0443 ConfigView.section.stats.xslfiledetails=\u0414\u043e\u0434\u0430\u0454\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0444\u0430\u0439\u043b\u0443 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0437 \u0442\u0435\u0433\u043e\u043c ConfigView.label.savetorrentbackup=\u0417\u0431\u0435\u0440\u0456\u0433\u0430\u0442\u0438 \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u0443 \u043a\u043e\u043f\u0456\u044e ConfigView.section.tracker.forceport=\u041f\u0440\u0438\u043c\u0443\u0441\u043e\u0432\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0443 \u0434\u043b\u044f \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u0456\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 ConfigView.section.ipfilter.allow=\u0414\u041e\u0417\u0412\u041e\u041b\u0418\u0422\u0418 \u0446\u0456 \u0434\u0456\u0430\u043f\u0430\u0437\u043e\u043d\u0438 (\u0437\u0432\u0438\u0447\u0430\u0439\u043d\u043e \u0417\u0410\u0411\u041e\u0420\u041e\u041d\u0415\u041d\u0406) ConfigView.section.ipfilter.list.inrange=\u0431\u0443\u0432 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443 ConfigView.section.ipfilter.list.notinrange=\u043d\u0435 \u0431\u0443\u0432 \u0443 \u0436\u043e\u0434\u043d\u043e\u043c\u0443 \u0441\u043f\u0438\u0441\u043a\u0443 ConfigView.section.ipfilter.list.title=\u0421\u043f\u0438\u0441\u043e\u043a \u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0445 IP ConfigView.label.allowsameip=\u0414\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0437\u0432'\u044f\u0437\u043a\u0443 \u0437 \u043e\u0434\u043d\u0456\u0454\u0457 \u0456 \u0442\u0456\u0454\u0457 \u0436 IP ConfigView.label.allowsameip.tooltip=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u043f\u043e\u0442\u0440\u0435\u0431\u0438.\n\u0412 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u043d\u0456 \u0454 \u0437\u0430\u0445\u0438\u0441\u0442\u043e\u043c \u0432\u0456\u0434 \u043b\u0456\u0447\u0435\u0440\u0456\u0432 ManagerItem.superseeding=\u0421\u0443\u043f\u0435\u0440-\u0440\u043e\u0437\u0434\u0430\u0447\u0430 ConfigView.label.userSuperSeeding=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0443\u043f\u0435\u0440-\u0440\u043e\u0437\u0434\u0430\u0447\u0443 PeersView.uniquepiece=\u0427\u0430\u0441\u0442\u0438\u043d\u0430 (\u0440\u0435\u0436\u0438\u043c \u0441\u0443\u043f\u0435\u0440-\u0440\u043e\u0437\u0434\u0430\u0447\u0456) PeersView.uniquepiece.none=\u041d\u0435\u043c\u0430 PeersView.timetosend=\u041f\u0440\u0438\u0439\u0448\u043e\u0432 \u0447\u0430\u0441 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u0438 \u0447\u0430\u0441\u0442\u0438\u043d\u0443 \u0437\u0430\u043d\u043e\u0432\u043e (\u0420\u0435\u0436\u0438\u043c \u0441\u0443\u043f\u0435\u0440-\u0440\u043e\u0437\u0434\u0430\u0447\u0456) ConfigView.section.style.addurlsilently=\u0412\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0438 \u0431\u0435\u0437 \u0434\u0456\u0430\u043b\u043e\u0433\u0443 ConfigView.section.style.addurlsilently.tooltip=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0438\u0439\u043d\u044f\u0442\u0456 \u0430\u0431\u043e \u0432\u0456\u0434\u0445\u0438\u043b\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u0430\u0434\u0440\u0435\u0441 \u0431\u0435\u0437 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0442\u044f \u0432\u0456\u043a\u043d\u0430 \u0437\u0430\u043f\u0438\u0442\u0443. ConfigView.section.file.decoder.prompt=\u0417\u0430 \u0437\u043c\u043e\u0433\u0438 \u0432\u0438\u0431\u043e\u0440\u0443 \u0437\u0430\u0432\u0436\u0434\u0438 \u0437\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 ConfigView.section.file.decoder.prompt.tooltip=\u0417\u0430 \u0437\u043c\u043e\u0433\u0438 \u0432\u0438\u0431\u043e\u0440\u0443 \u0437\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0434\u0456\u0430\u043b\u043e\u0433 MyTorrentsView.menu.moveTop=\u0414\u043e \u0441\u0430&\u043c\u043e\u0433\u043e \u0432\u0435\u0440\u0445\u0443 MyTorrentsView.menu.moveEnd=\u0414\u043e &\u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0438\u0437\u0443 ConfigView.label.moveonlyusingdefaultsave=\u041b\u0438\u0448\u0435 \u044f\u043a\u0449\u043e \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456\u0439 \u0442\u0435\u0446\u0456 ConfigView.label.moveonlyusingdefaultsave.tooltip=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u044f\u043a\u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u0431\u0443\u0432\u0430\u0454 \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456\u0439 \u043f\u0430\u043f\u0446\u0456 ConfigView.label.watchtorrentfolder=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438\u0439 \u0456\u043c\u043f\u043e\u0440\u0442 \u043d\u043e\u0432\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 ConfigView.label.watchtorrentfolder.tooltip=\u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0430 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043d\u043e\u0432\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 ConfigView.label.watchtorrentfolderinterval=\u0427\u0430\u0441\u043e\u0432\u0438\u0439 \u043f\u0440\u043e\u043c\u0456\u0436\u043e\u043a ConfigView.label.watchtorrentfolderinterval.tooltip=\u0422\u0440\u0438\u0432\u0430\u043b\u0456\u0441\u0442\u044c \u043f\u0430\u0443\u0437\u0438 \u0434\u043e \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u0457 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u0442\u0435\u043a\u0438 ConfigView.dialog.choosewatchtorrentfolderpath=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0456\u043c\u043f\u043e\u0440\u0442\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 ConfigView.label.startwatchedtorrentsstopped=\u0417\u0430\u043f\u0443\u0441\u043a \u0437\u0443\u043f\u0438\u043d\u0435\u043d\u0438\u0439 ConfigView.label.startwatchedtorrentsstopped.tooltip=\u0414\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u044f \u043d\u043e\u0432\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0443 \u0437\u0443\u043f\u0438\u043d\u0435\u043d\u043e\u043c\u0443 \u0440\u0435\u0436\u0438\u043c\u0456 ConfigView.section.plugins=\u0414\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f wizard.maketorrent.filesize=\u0420\u043e\u0437\u043c\u0456\u0440 \u0444\u0430\u0439\u043b\u0443(-\u0456\u0432) wizard.maketorrent.piececount=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0447\u0430\u0441\u0442\u0438\u043d wizard.maketorrent.piecesize=\u0420\u043e\u0437\u043c\u0456\u0440 \u0447\u0430\u0441\u0442\u0438\u043d wizard.maketorrent.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e MainWindow.menu.view.stats=&\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 SpeedView.title.full=\u0410\u043a\u0442\u0438\u0432\u043d\u0456\u0441\u0442\u044c SpeedView.downloadSpeed.title=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f SpeedView.uploadSpeed.title=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 ConfigView.section.style.useSIUnits=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043e\u0434\u0438\u043d\u0438\u0446\u0456 IEC (K\u0431\u0430\u0439\u0442 -> Ki\u0411 \u0456 \u0456\u043d.) iconBar.top.tooltip=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0434\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u0432\u0435\u0440\u0445\u0443 iconBar.bottom.tooltip=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0434\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0438\u0437\u0443 TableColumn.header.health=\u0421\u0442\u0430\u043d MyTorrentsView.menu.health=\u0420\u043e\u0437\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c health.explain.grey=\u043e\u0437\u043d\u0430\u0447\u0430\u0454 \u0442\u0435, \u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0435 \u043f\u0440\u0430\u0446\u044e\u0454 (\u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u044c\u0441\u044f \u0430\u0431\u043e \u043d\u0435 \u0440\u043e\u0437\u0434\u0430\u0454\u0442\u044c\u0441\u044f) health.explain.red=\u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0412\u0438 \u043d\u0435 \u0437'\u0454\u0434\u043d\u0430\u043d\u0456 \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f health.explain.blue=\u043f\u0440\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0412\u0438 \u043d\u0435 \u0437'\u0454\u0434\u043d\u0430\u043d\u0456 \u0437 \u0436\u043e\u0434\u043d\u0438\u043c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c\n\u043f\u0440\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u0456 - \u0449\u043e \u0412\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u0456 \u0437 \u0434\u0435\u043a\u0438\u043c \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u0430\u043b\u0435 \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435 \u043f\u0440\u0430\u0446\u044e\u0454 health.explain.yellow=\u043e\u0437\u043d\u0430\u0447\u0430\u0454 \u043f\u0440\u043e \u0442\u0435, \u0449\u043e \u0442\u0440\u0435\u043a\u0435\u0440 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0443, \u0412\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u0456 \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438, \u0430\u043b\u0435 \u0437\u0432'\u044f\u0437\u043a\u0443 \u043a\u0435\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435\u043c\u0430.\n\u0419\u043c\u043e\u0432\u0456\u0440\u043d\u043e, \u0432 \u0432\u0430\u0441 NAT-\u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u044f\u043a\u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432\u0432\u0435\u0441\u044c \u0447\u0430\u0441 \u0436\u043e\u0432\u0442\u0456 health.explain.green=\u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0432\u0441\u0435 \u0433\u0430\u0440\u0430\u0437\u0434 ConfigView.section.style.alwaysRefreshMyTorrents=\u0417\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u044e\u0432\u0430\u0442\u0438 "\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438" ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=\u0426\u044f \u0444\u0443\u043d\u043a\u0446\u0456\u044f \u043f\u043e\u043d\u043e\u0432\u043b\u044e\u0454 \u043f\u043e\u043a\u0430\u0437\u043d\u0438\u043a "\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438", \u043d\u0430\u0432\u0456\u0442\u044c \u044f\u043a\u0449\u043e \u0432\u0456\u043d \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u0438\u0439 (\u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u0435\u044f\u043a\u0456 mIRC-\u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f\u043c\u0438) # #2.0.7.0 # security.certtruster.title=\u041f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 \u0431\u0435\u0437\u043f\u0435\u043a\u0438 security.certtruster.intro=\u0426\u0435\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 \u0431\u0435\u0437\u043f\u0435\u043a\u0438 \u0431\u0443\u0432 \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0439 \u0444\u0456\u0440\u043c\u043e\u044e, \u044f\u043a\u0456\u0439 \u0412\u0438 \u043d\u0435 \u0434\u043e\u0432\u0456\u0440\u044f\u0454\u0442\u0435 security.certtruster.resource=\u0414\u0436\u0435\u0440\u0435\u043b\u043e: security.certtruster.issuedto=\u0412\u0438\u0434\u0430\u043d\u0438\u0439 \u0434\u043b\u044f: security.certtruster.issuedby=\u0412\u0438\u0434\u0430\u0432\u0435\u0446\u044c: security.certtruster.prompt=\u0412\u0438 \u0434\u043e\u0432\u0456\u0440\u044f\u0454\u0442\u0435 \u0439\u043e\u043c\u0443? security.certtruster.yes=\u0422\u0430\u043a security.certtruster.no=\u041d\u0456 ConfigView.section.tracker.torrentsperpage=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u043d\u0430 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] MainWindow.menu.file.share=&\u0420\u043e\u0437\u0434\u0430\u0442\u0438 MainWindow.menu.file.share.file=&\u0424\u0430\u0439\u043b... MainWindow.menu.file.share.dir=&\u0422\u0435\u043a\u0443... MainWindow.menu.file.share.dircontents=&\u0412\u043c\u0456\u0441\u0442 \u0442\u0435\u043a\u0438 MainWindow.menu.file.share.dircontentsrecursive=\u0412&\u043c\u0456\u0441\u0442 \u0442\u0435\u043a\u0438 \u0456 \u0432\u0441\u0456\u0445 \u0457\u0457 \u043f\u0456\u0434\u0442\u0435\u043a... MainWindow.dialog.share.sharefile=\u0412\u0438\u0431\u0456\u0440 \u0444\u0430\u0439\u043b\u0443 \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 MainWindow.dialog.share.sharedir=\u0412\u0438\u0431\u0456\u0440 \u0442\u0435\u043a\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 MainWindow.dialog.share.sharedircontents=\u0412\u0438\u0431\u0456\u0440 \u0432\u043c\u0456\u0441\u0442\u0443 \u0442\u0435\u043a\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 MainWindow.dialog.share.sharedircontents.recursive=\u0406 \u0432\u043c\u0456\u0441\u0442\u0443 \u0432\u0441\u0456\u0445 \u0457\u0457 \u043f\u0456\u0434\u0442\u0435\u043a globalmanager.download.remove.veto=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0431\u043e\u0440\u043e\u043d\u0435\u043d\u0430 plugin.sharing.download.remove.veto=\u0426\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u0432\u0456\u0434\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u0434\u043e \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447.\n\u0414\u043b\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0457\u0457 \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0435 \u0434\u0436\u0435\u0440\u0435\u043b\u043e ConfigView.section.tracker.main=\u0413\u043e\u043b\u043e\u0432\u043d\u0430 ConfigView.section.tracker.web=\u041c\u0435\u0440\u0435\u0436\u0430 ConfigView.label.prioritizefirstpiece=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u043f\u0435\u0440\u0448\u0438\u043c \u0456 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u043c \u0447\u0430\u0441\u0442\u0438\u043d\u0430\u043c \u0444\u0430\u0439\u043b\u0443 ConfigView.label.prioritizefirstpiece.tooltip=\u0412 \u043f\u0435\u0440\u0448\u0443 \u0447\u0435\u0440\u0433\u0443 \u043d\u0430\u043c\u0430\u0433\u0430\u0442\u0438\u0441\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u043f\u043e\u0447\u0430\u0442\u043e\u043a \u0456 \u043a\u0456\u043d\u0435\u0446\u044c \u0444\u0430\u0439\u043b\u0443.\n\u0414\u043b\u044f \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0438 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u043d\u044c\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434\u0443. ConfigView.section.file.confirm_data_delete=\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u0456 ConfigView.section.file.confirm_data_delete.tooltip=\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445 \u043f\u0440\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u0456 "\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0456 \u0441\u0442\u0435\u0440\u0442\u0438" ConfigView.section.file.delete.include_files_outside_save_dir=\u041f\u0440\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u0456 \u0434\u0430\u043d\u0438\u0445, \u0434\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 \u0442\u0430\u043a\u043e\u0436 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 , \u0437\u0432'\u044f\u0437\u0430\u043d\u0456 \u043f\u043e\u0437\u0430 \u0442\u0435\u043a\u043e\u044e \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 TrayWindow.menu.startalldownloads=\u0417\u0430\u043f\u0443\u0441&\u0442\u0438\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f SystemTray.menu.startalltransfers=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 sharing.progress.title=\u0406\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0443 sharing.progress.hide=\u0421\u0445\u043e\u0432\u0430\u0442\u0438 MainWindow.menu.view.myshares=\u041c\u043e\u0457 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 MySharesView.title.full=M\u043e\u0457 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 MySharesView.name=\u041d\u0430\u0437\u0432\u0430 MySharesView.type=\u0422\u0438\u043f MySharesView.type.file=\u0424\u0430\u0439\u043b MySharesView.type.dir=\u0422\u0435\u043a\u0430 MySharesView.type.dircontents=\u0412\u043c\u0456\u0441\u0442 \u0442\u0435\u043a\u0438 MySharesView.type.dircontentsrecursive=\u0412\u043c\u0456\u0441\u0442 \u0442\u0435\u043a\u0438 \u0456 \u0432\u0441\u0456\u0445 \u0457\u0457 \u043f\u0456\u0434\u0442\u0435\u043a MySharesView.menu.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 ConfigView.section.tracker.extensions=\u0420\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043d\u044f ConfigView.section.tracker.sendpeerids=\u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u0438 \u0456\u0434\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0442\u043e\u0440 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u044e\u0447\u0438\u043c ConfigView.section.tracker.enableudp=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b UDP \u0442\u0440\u0435\u043a\u0435\u0440\u0443 plugin.sharing.torrent.remove.veto=\u0426\u044f \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u0432\u0456\u0434\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u0434\u043e \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u043e\u0457 \u0440\u043e\u0437\u0434\u0430\u0447\u0456.\n\u0414\u043b\u044f \u0457\u0457 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0432\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0443. plugin.download.remove.veto.notstopped=\u0414\u043b\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u043f\u0430\u043a\u0435\u0442\u0430 \u0437\u0443\u043f\u0438\u043d\u0456\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. plugin.sharing.remove.veto=\u0426\u044f \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u043d\u0430\u043b\u0435\u0436\u0438\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 "\u0412\u043c\u0456\u0441\u0442 \u0442\u0435\u043a\u0438" \u0456 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u0430.\n\u0412\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0442\u0435\u043a\u0443 \u0437 \u0440\u043e\u0437\u0434\u0430\u0447\u0456. GeneralView.label.hash.tooltip=\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0437\u0430\u043f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u0445\u0435\u0448 ConfigView.section.tracker.maxpeersreturned=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u044f\u043a\u0456 \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u043b\u0438\u0441\u044f [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] ConfigView.label.serverport=TCP / UDP-\u043f\u043e\u0440\u0442 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c ConfigView.label.serverport.tooltip=\u041d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0443 \u043f\u043e\u0432\u0438\u043d\u0435\u043d \u0431\u0443\u0442\u0438 \u0432 \u0434\u0456\u0430\u043f\u0430\u0437\u043e\u043d\u0456 \u0432\u0456\u0434 1 \u0434\u043e 65535, \u043a\u0440\u0456\u043c 6880, \u044f\u043a\u0438\u0439 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e \u0434\u043b\u044f \u0432\u043b\u0430\u0441\u043d\u0438\u0445 \u0446\u0456\u043b\u0435\u0439. configureWizard.nat.server.tcp_listen_port=TCP-\u043f\u043e\u0440\u0442 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c ConfigView.section.sharing=\u041a\u043b\u0430\u0441\u0438\u0447\u043d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0430 ConfigView.section.sharing.usessl=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 SSL \u0434\u043b\u044f \u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447 (\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0443) ConfigView.section.style.dropdiraction=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 "Drag and Drop" \u0434\u043b\u044f \u0442\u0435\u043a ConfigView.section.style.dropdiraction.opentorrents=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.section.style.dropdiraction.sharefolder=\u0422\u0435\u043a\u0430 \u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447 ConfigView.section.style.dropdiraction.sharefoldercontents=\u0412\u043c\u0456\u0441\u0442 \u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447 # # 2.0.7.x # Categories.all=\u0412\u0441\u0456 Categories.uncategorized=\u0411\u0435\u0437 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0439 CategoryAddWindow.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043d\u0430\u0437\u0432\u0443 \u043d\u043e\u0432\u043e\u0457 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457 CategoryAddWindow.title=\u0414\u043e\u0434\u0430\u0442\u0438 \u043d\u043e\u0432\u0443 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044e ConfigView.label.autoSeedingIgnoreInfo=\u0406\u0433\u043d\u043e\u0440\u043e\u0432\u0430\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u043a\u0456\u043d\u0435\u0446\u044c \u0447\u0435\u0440\u0433\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0456 \u043d\u0435 \u0441\u0442\u0430\u0440\u0442\u0443\u044e\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e. \u0426\u0456 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0435 \u043f\u043e\u0448\u0438\u0440\u044e\u044e\u0442\u044c\u0441\u044f \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0437\u0456 \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u043c "\u0412\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442". \u042f\u043a\u0449\u043e \u0432\u043e\u043d\u0438 \u043d\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0456, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f "0" \u0434\u043b\u044f \u0432\u0438\u043d\u044f\u0442\u043a\u0443 \u0437 \u043f\u0440\u0430\u0432\u0438\u043b\u0430. ConfigView.label.directory=\u0422\u0435\u043a\u0430 ConfigView.label.disconnetseed.tooltip=\u041f\u0440\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u043f\u0435\u0440\u0435\u0440\u0432\u0430\u0442\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0441\u0456\u0434\u0435\u0440\u0430\u043c\u0438.\n\u0417\u0432\u2019\u044f\u0437\u043e\u043a \u0437 \u043d\u0438\u043c\u0438 \u043d\u0435 \u043e\u0431\u043e\u0432'\u044f\u0437\u043a\u043e\u0432\u0438\u0439. ConfigView.label.ignoreCase=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0440\u0435\u0433\u0456\u0441\u0442\u0440\u043e\u043c ConfigView.label.ignoreSeeds=\u041a\u0440\u0456\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u043c\u0435\u043d\u0448 \u044f\u043a ConfigView.label.importdirectory=\u0422\u0435\u043a\u0430 \u0456\u043c\u043f\u043e\u0440\u0442\u0443 ConfigView.label.minPeersToBoostNoSeeds.tooltip=\u0412\u0441\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0431\u0435\u0437 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u044e\u0447\u0438\u0445 \u0441\u0456\u0434\u0435\u0440\u0456\u0432, \u0430\u0431\u043e \u0437 \u043c\u0435\u043d\u0448 \u044f\u043a\n\u0440\u0443\u0445\u0430\u0442\u0438 \u0434\u043e\u0433\u043e\u0440\u0438 \u0447\u0435\u0440\u0433\u0438 ConfigView.label.minPeersToBoostNoSeeds=\u0417\u0430\u043d\u0438\u0436\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0431\u0435\u0437 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u044e\u0447\u0438\u0445 \u0430\u0431\u043e \u0457\u0445\u043d\u044c\u043e\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u043c\u0435\u043d\u0448 \u043d\u0456\u0436 ConfigView.label.minSeedingTime.tooltip=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043c\u043e\u0436\u0443\u0442\u044c \u0437\u0430 \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 \u0447\u0430\u0441 \u0447\u0430\u0441\u0442\u043e \u0432\u0430\u0440\u0456\u044e\u0432\u0430\u0442\u0438\u0441\u044c, \u0449\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435 \u0434\u043e \u0447\u0430\u0441\u0442\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0456 \u0437\u0443\u043f\u0438\u043d\u043a\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0443.\n\u0426\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043c\u043e\u0436\u043d\u0430 \u0432\u0438\u0440\u0456\u0448\u0438\u0442\u0438 \u0442\u0430\u043a, \u0449\u043e \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u043d\u0430 \u0437\u0430\u0434\u0430\u043d\u0438\u0439 \u043f\u0435\u0440\u0456\u043e\u0434 \u0447\u0430\u0441\u0443 \u043d\u0435 \u0437\u0443\u043f\u0438\u043d\u044f\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f.\n\u041e\u0434\u043d\u0430\u043a \u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432 \u0431\u0443\u0434\u044c-\u044f\u043a\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. ConfigView.label.minSeedingTime=\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445 ConfigView.label.minSpeedForActiveDL.tooltip=\u0421\u043b\u043e\u0442 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u0439\u043c\u0430\u0454\u0442\u044c\u0441\u044f \u043d\u0430 30 \u0441\u0435\u043a\u0443\u043d\u0434 \u0434\u043b\u044f \u0456\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u0457 \n\u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u043d\u0435\u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 ConfigView.label.minSpeedForActiveDL=\u0422\u043e\u0440\u0435\u043d\u0442 \u043d\u0435 \u0437\u0430\u0439\u043c\u0430\u0454 \u0441\u043b\u043e\u0442 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u044f\u043a\u0449\u043e \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u043d\u0438\u0436\u0447\u0435 \u043d\u0456\u0436 ConfigView.label.peers=\u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 ConfigView.label.queue.debuglog=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f ConfigView.label.queue.debuglog.info=\u0412\u0438\u0434\u0430\u0432\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u043e \u043f\u043e\u043c\u0438\u043b\u043a\u0438 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0456 \u0444\u0430\u0439\u043b \u043b\u043e\u0433\u0443.\n\u041d\u0430\u0432\u0456\u0442\u044c \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0430, \u0446\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0432\u0438\u0440\u0430\u0436\u0430\u0454 \u0441\u0442\u0430\u043d \u0442\u043e\u0440\u0435\u043d\u0442\u0443, \u0456 \u0447\u043e\u043c\u0443 \u0432\u043e\u043d\u0438 (\u043d\u0435)\u0431\u0443\u043b\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0456 \u0430\u0431\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0456 \u0432 \u0447\u0435\u0440\u0433\u0443. ConfigView.label.queue.minQueueingShareRatio=\u041d\u0435 \u0441\u0442\u0430\u0432\u0438\u0442\u0438 \u0432 \u0447\u0435\u0440\u0433\u0443 \u0456 \u043d\u0435 \u0437\u0443\u043f\u0438\u043d\u044f\u0442\u0438 \u0434\u043e \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u043e \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432\u0438\u0449\u0435 ConfigView.label.ratio=\u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f ConfigView.label.removeOnStop=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443 \u043f\u0456\u0441\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0437\u0443\u043f\u0438\u043d\u043a\u0438 ConfigView.label.savedirectory=\u0422\u0435\u043a\u0430 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f ConfigView.label.seeding.autoReposition.tooltip=\u042f\u043a\u0449\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0430, \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 (\u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c '#') \u043f\u0440\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0443 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u043d\u0456\u0441\u0442\u044c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0456.\n\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435, \u044f\u043a\u0449\u043e \u0412\u0438 \u0432\u0438\u043c\u043a\u043d\u0443\u043b\u0438 \u043f\u043e\u043a\u0430\u0437 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0430\u043b\u0435 \u0431\u0430\u0436\u0430\u0454\u0442\u0435 \u0437\u043d\u0430\u0442\u0438 \u043f\u0440\u043e \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432. ConfigView.label.seeding.autoReposition=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0440\u043e\u0437\u043c\u0456\u0449\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0437\u0430 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u0427\u0430\u0441\u0442\u0430 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u043c\u0430\u043b\u043e\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0456 \u0432\u0435\u043b\u0438\u043a\u043e\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0432\u043a\u0430\u0437\u0443\u0454 \u043d\u0430 \u0442\u0435, \u0449\u043e \u0441\u0435\u0440\u0435\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u043d\u0430 \u0446\u0435\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435\u043c\u0430 \u043f\u043e\u0432\u043d\u043e\u0457 \u043a\u043e\u043f\u0456\u0457.\n\u0422\u043e\u043c\u0443 \u043d\u0435 \u0432\u0430\u0440\u0442\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0449\u043e \u043f\u0440\u0438\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u044c \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u043f\u043e\u0432\u043d\u043e\u0457 \u043a\u043e\u043f\u0456\u0457 \u0456 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0437\u043d\u0438\u0436\u0443\u044e\u0442\u044c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456. ConfigView.label.seeding.fakeFullCopySeedStart=\u043a\u0440\u0456\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u043c\u0435\u043d\u0448\u0435, \u043d\u0456\u0436 ConfigView.label.seeding.ignore=\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0435\u0445\u0442\u0443\u0432\u0430\u043d\u043d\u044f ConfigView.label.seeding.ignore0Peers=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438, \u044f\u043a\u0456 \u043d\u0435 \u043c\u0430\u044e\u0442\u044c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 ConfigView.label.seeding.ignoreRatioPeers=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438, \u044f\u043a\u0456 \u043c\u0430\u044e\u0442\u044c \u0431\u0456\u043b\u044c\u0448\u0435 1 \u0441\u0456\u0434\u0435\u0440\u0430 \u043d\u0430 \u043a\u043e\u0436\u043d\u0456 ConfigView.label.seeding.ignoreShareRatio=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438, \u044f\u043a\u0456 \u043c\u0430\u044e\u0442\u044c \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 ConfigView.label.seeding.ignore.header.evenFirstPriority=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438, \u043d\u0430\u0432\u0456\u0442\u044c\n\u044f\u043a\u0449\u043e \u0434\u0456\u044e\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0432\u0438\u0449\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 ConfigView.label.seeding.ignore.header.rule=\u041f\u0440\u0430\u0432\u0438\u043b\u043e ConfigView.label.seeding.ignore.header.value=\u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f ConfigView.label.seeding.firstPriority.info=\u0412\u0438\u0449\u0438\u043c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0437\u0430\u0432\u0436\u0434\u0438 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u044e\u0442\u044c\u0441\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0456 \u043f\u0435\u0440\u0435\u0431\u0443\u0432\u0430\u044e\u0442\u044c \u043d\u0430 \u043f\u043e\u0447\u0430\u0442\u043a\u0443 \u0447\u0435\u0440\u0433\u0438. \u0422\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0456 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0430\u044e\u0442\u044c \u043a\u0440\u0438\u0442\u0435\u0440\u0456\u044f\u043c \u0432\u0438\u0449\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443, \u043d\u0435 \u0437\u0443\u043f\u0438\u043d\u044f\u044e\u0442\u044c\u0441\u044f \u0456 \u043d\u0435 \u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0447\u0435\u0440\u0433\u0443 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e. \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e\u0441\u0442\u0456 \u0457\u043c \u0432\u0438\u0431\u0438\u0440\u0430\u0454\u0442\u044c\u0441\u044f \u0441\u043b\u043e\u0442 \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. ConfigView.label.seeding.firstPriority.FP=\u0412\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.label.seeding.firstPriority=\u041f\u0440\u0438\u0432\u043b\u0430\u0441\u043d\u044e\u0432\u0430\u0442\u0438 \u0432\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c ConfigView.label.seeding.firstPriority.following=\u0434\u043b\u044f \u044f\u043a\u0438\u0445 \u0434\u0456\u0439\u0441\u043d\u0456 \u043d\u0438\u0436\u0447\u0435\u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0456 \u0443\u043c\u043e\u0432\u0438: ConfigView.label.seeding.firstPriority.shareRatio=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043c\u0435\u043d\u0448 \u043d\u0456\u0436 ConfigView.label.seeding.firstPriority.seedingMinutes=\u0427\u0430\u0441, \u044f\u043a\u0438\u0439 \u043c\u0438\u043d\u0443\u0432 \u0437 \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u0437\u043c\u0456\u043d\u0438 \u0440\u0435\u0436\u0438\u043c\u0443 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043d\u0430 \u0440\u0435\u0436\u0438\u043c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 ConfigView.label.seeding.firstPriority.DLMinutes=\u0427\u0430\u0441, \u044f\u043a\u0438\u0439 \u043c\u0438\u043d\u0443\u0432 \u0437 \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u043f\u043e\u0447\u0430\u0442\u043a\u0443 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ConfigView.label.seeding.numPeersAsFullCopy.tooltip=\u0420\u043e\u0437\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u043f\u043e\u0432\u043d\u0443 \u043a\u043e\u043f\u0456\u044e \u043d\u0430 \u043a\u043e\u0436\u043d\u0456 \u0425 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u0412\u0438 \u0437\u043d\u0438\u0436\u0443\u0454\u0442\u0435 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u0431\u0456\u043b\u044c\u0448\u043e\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432.\n\u0428\u0432\u0438\u0434\u0448\u0435 \u0437\u0430 \u0432\u0441\u0435, \u0442\u0430\u043a\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0442\u0430\u043a\u043e\u0436 \u043c\u0430\u044e\u0442\u044c \u0432\u0435\u043b\u0438\u043a\u0438\u0439 \u0442\u0440\u0430\u0444\u0456\u043a. \u0426\u044f \u0444\u0443\u043d\u043a\u0446\u0456\u044f \u043d\u0435 \u0437\u043c\u0456\u043d\u044e\u0454 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447 \u0432 \u0441\u0442\u043e\u0432\u043f\u0446\u0456 '# \u0440\u043e\u0437\u0434\u0430\u0447\u0456' ConfigView.label.seeding.numPeersAsFullCopy=\u0420\u043e\u0437\u0440\u0430\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u043f\u043e\u0432\u043d\u043e\u0457 \u043a\u043e\u043f\u0456\u0457 \u043d\u0430 \u043a\u043e\u0436\u043d\u0456\n[0 : \u0431\u0435\u0437 \u043f\u0440\u0438\u043f\u0443\u0449\u0435\u043d\u044c] ConfigView.label.seeding.preferLargerSwarms.tooltip=\u042f\u043a\u0449\u043e \u0412\u0438 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c\u0443 \u0440\u043e\u0437\u0434\u0430\u0454\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043d\u0435 \u0431\u0430\u0433\u0430\u0442\u044c\u043e\u043c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f "\u043f\u0435\u0440\u0435\u0432\u0430\u0433\u0430 \u0432\u0435\u043b\u0438\u043a\u0438\u0445 \u0433\u0440\u0443\u043f".\n\u0412 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0440\u043e\u0437\u043f\u043e\u0432\u0441\u044e\u0434\u0436\u0435\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 - "\u043f\u0435\u0440\u0435\u0432\u0430\u0433\u0430 \u043c\u0430\u043b\u0438\u0445 \u0433\u0440\u0443\u043f". ConfigView.label.seeding.preferLargerSwarms=\u0421\u0435\u0440\u0435\u0434 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u043e\u0434\u043d\u0430\u043a\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0432\u0456\u0434\u0434\u0430\u0432\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u0430\u0433\u0438 \u043d\u0430\u0439\u043f\u043e\u0448\u0438\u0440\u0435\u043d\u0456\u0448\u0438\u043c. ConfigView.label.seeding.rankType.none.tooltip=\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0437\u0430 \u0441\u0442\u043e\u0432\u043f\u0446\u0435\u043c # ConfigView.label.seeding.rankType.none=\u041d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 ConfigView.label.seeding.rankType.peer.tooltip=\u0427\u0438\u043c \u0431\u0456\u043b\u044c\u0448\u0435 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0456 \u043c\u0435\u043d\u0448\u0435 \u0441\u0456\u0434\u0435\u0440\u0456\u0432, \u0442\u0438\u043c \u0432\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\n\u0426\u0435\u0439 \u0442\u0438\u043f \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0437\u043c\u0435\u043d\u0448\u0443\u0454 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432, \u044f\u043a\u0438\u0439 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0431\u0443\u0442\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u043c\u0438 \u0434\u043b\u044f \u0437\u0431\u0456\u043b\u044c\u0448\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 ConfigView.label.seeding.rankType.peer=\u0417\u0430 \u043d\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f\u043c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 ConfigView.label.seeding.rankType.peerSeed.options=\u0417\u0430 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f\u043c \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0434\u043e \u0443\u0447\u0430\u043d\u0438\u043a\u0456\u0432 (\u043e\u043f\u0446\u0456\u0457) ConfigView.label.seeding.rankType.peerSeed.tooltip=\u0427\u0438\u043c \u0432\u0438\u0449\u0435 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f, \u0442\u0438\u043c \u0432\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.label.seeding.rankType.peerSeed=\u0417\u0430 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f\u043c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0434\u043e \u0441\u0456\u0434\u0435\u0440\u0456\u0432 ConfigView.label.seeding.rankType.seed.fallback=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438\u0441\u044f \u0434\u043e \u043a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0447\u0435\u0440\u0435\u0437\n [0 : \u043d\u0456\u043a\u043e\u043b\u0438 \u043d\u0435 \u043f\u043e\u0432\u0435\u0440\u0442\u0430\u0442\u0438\u0441\u044f] ConfigView.label.seeding.rankType.seed.options=\u041b\u0438\u0448\u0435 \u0437\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0441\u0456\u0434\u0435\u0440\u0456\u0432 (\u043e\u043f\u0446\u0456\u0457) ConfigView.label.seeding.rankType.seed.tooltip=\u0427\u0438\u043c \u043c\u0435\u043d\u0448\u0435 \u0441\u0456\u0434\u0435\u0440\u0456\u0432, \u0442\u0438\u043c \u043d\u0438\u0436\u0447\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.label.seeding.rankType.seed=\u041b\u0438\u0448\u0435 \u0437\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0441\u0456\u0434\u0435\u0440\u0456\u0432 ConfigView.label.seeding.rankType.timedRotation.tooltip=\u0412\u0441\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0437\u0430 \u0447\u0435\u0440\u0433\u043e\u044e \u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c \u0440\u043e\u0437\u0434\u0430\u0447\u0456.\n\u0427\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432 \u043e\u043f\u0446\u0456\u0457 '\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456' ConfigView.label.seeding.rankType.timedRotation=\u0420\u0456\u0432\u043d\u043e\u043c\u0456\u0440\u043d\u043e \u0437\u043c\u0456\u043d\u044e\u0454\u0442\u044c\u0441\u044f \u0437 \u0447\u0430\u0441\u043e\u043c ConfigView.label.seeding.rankType.tooltip=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u0437 \u043d\u0430\u0439\u0432\u0438\u0449\u0438\u043c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0441\u0442\u0430\u0440\u0442\u0443\u044e\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.\n\u042f\u043a\u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u043e\u0442\u0440\u0438\u043c\u0443\u0454 \u0432\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442, \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0438\u0436\u0447\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0437\u0443\u043f\u0438\u043d\u044f\u0454\u0442\u044c\u0441\u044f \u0456 \u043f\u043e\u0432\u0435\u0440\u0442\u0430\u0454\u0442\u044c\u0441\u044f \u0432 \u0447\u0435\u0440\u0433\u0443.\n\n\u041b\u0438\u0448\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0456 \u0441\u0442\u043e\u044f\u0442\u044c \u0432 \u0447\u0435\u0440\u0437\u0456, \u043c\u043e\u0436\u0443\u0442\u044c \u0441\u0442\u0430\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.\n\u0417\u0443\u043f\u0438\u043d\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043d\u0456\u043a\u043e\u043b\u0438 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e. ConfigView.label.seeding.rankType=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0432\u0438\u0437\u043d\u0430\u0447\u0430\u0454\u0442\u044c\u0441\u044f: ConfigView.label.stopAfterMinutes=\u0427\u0438\u043d\u043d\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u0437\u0443\u043f\u0438\u043d\u044f\u0442\u0438 \u043b\u0438\u0448\u0435 \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0447\u0430\u0441\u0443 ConfigView.label.switchpriority.tooltip=\u041d\u0438\u0437\u044c\u043a\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0437\u043d\u0438\u0436\u0443\u0454 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0432\u0438\u0431\u0440\u0430\u043d\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0443. ConfigView.pluginlist.info=\u041d\u0438\u0436\u0447\u0435 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0456 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0456 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f. \u0414\u0435\u044f\u043a\u0456 \u0437 \u043d\u0438\u0445 \u043c\u043e\u0436\u0443\u0442\u044c \u043d\u0435 \u043c\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c. ConfigView.pluginlist.noplugins=\u041d\u0456\u044f\u043a\u0438\u0445 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e. ConfigView.section.pluginslist=\u0421\u043f\u0438\u0441\u043e\u043a ConfigView.section.queue.seeding=\u0420\u043e\u0437\u0434\u0430\u0447\u0430 ConfigView.section.queue.seeding.autoStarting=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a ConfigView.section.queue.seeding.ignore=\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0456\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u043d\u043d\u044f ConfigView.section.queue.seeding.firstPriority=\u0412\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.section.queue.main=\u0413\u043e\u043b\u043e\u0432\u043d\u0430 ConfigView.section.queue=\u0427\u0435\u0440\u0433\u0430 ConfigView.section.torrents=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.text.all=\u0432\u0441\u0456 ConfigView.text.hours=\u0433\u043e\u0434\u0438\u043d ConfigView.text.ignoreRule=\u041f\u0440\u0430\u0432\u0438\u043b\u043e \u043d\u0435\u0445\u0442\u0443\u0432\u0430\u043d\u043d\u044f ConfigView.text.ignore=\u041d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 ConfigView.text.minutes=\u0445\u0432\u0438\u043b\u0438\u043d ConfigView.text.neverIgnore=\u041d\u0456\u043a\u043e\u043b\u0438 \u043d\u0435 \u0456\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 ConfigView.text.any=\u0431\u0443\u0434\u044c-\u044f\u043a\u0456 DownloadManager.error.datamissing=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0432\u0442\u0440\u0430\u0447\u0435\u043d\u0430 MainWindow.menu.file.open.torrentforseeding=\u0422\u043e\u0440\u0435\u043d\u0442 (\u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456) MainWindow.menu.language.refresh=&\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 ManagerItem.forced=\u041f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u0430 ManagerItem.queued=\u0423 \u0447\u0435\u0440\u0437\u0456 MySeedersView.header=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.availability.info=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u043a\u043e\u043f\u0456\u0439 TableColumn.header.availability=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456\u0441\u0442\u044c TableColumn.header.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044f MyTorrentsView.header=\u041d\u0435\u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0456 \u0430\u0431\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u044e\u0442\u044c\u0441\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.maxuploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447 MyTorrentsView.menu.category.delete=&\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044e MyTorrentsView.menu.forceStart=&\u041f\u0440\u0438\u0448\u0432\u0438\u0434\u0448\u0435\u043d\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a MyTorrentsView.menu.queue=&\u0427\u0435\u0440\u0433\u0430 MyTorrentsView.menu.setCategory.add=&\u0414\u043e\u0434\u0430\u0442\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044e... MyTorrentsView.menu.setCategory=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044e TableColumn.header.savepath=\u0422\u0435\u043a\u0430 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f TableColumn.header.SeedingRank=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 TableColumn.header.totalspeed.info=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0432\u0441\u0456\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 TableColumn.header.totalspeed=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c splash.initializePlugins=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c StartStopRules.SPratioMet=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f S:P OK StartStopRules.FP0Peers=FP / 0 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 StartStopRules.0Peers=0 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 StartStopRules.numSeedsMet=# \u0441\u0456\u0434\u0435\u0440\u0456\u0432 OK StartStopRules.ratioMet=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0434\u043e \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0432 \u043d\u043e\u0440\u043c\u0456 StartStopRules.shareRatioMet=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 O\u041a StartStopRules.waiting=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f StartStopRules.firstPriority=\u0412\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\u0412\u043c\u0456\u0441\u0442 \u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447 (\u0432\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u043f\u0456\u0434\u0442\u0435\u043a\u0438) DownloadManager.error.unabletostartserver=\u0417\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0435 \u0432\u0456\u0434\u0431\u0443\u0432\u0441\u044f - \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0445\u0456\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0443 / \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043d\u0438\u0445 Firewall-\u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c \u0434\u043b\u044f \u0440\u043e\u0431\u043e\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 GeneralView.label.creationdate=\u0421\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0439: ConfigView.section.tracker.announcescrapepercentage=\u0406\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0441\u0445\u043e\u0432\u0438\u0449\u0430 \u044f\u043a % \u0432\u0456\u043a\u0443 \u0430\u043d\u043e\u043d\u0441\u0443\n\u0422\u043e\u0431\u0442\u043e 200 = 2:1. [0 : \u0432\u0438\u0437\u043d\u0430\u0447\u0430\u0454\u0442\u044c\u0441\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0435\u043c] ManagerItem.stopping=\u0417\u0443\u043f\u0438\u043d\u043a\u0430 ConfigView.section.tracker.announcecacheperiod=\u041a\u0435\u0448 \u0430\u043d\u043e\u043d\u0441\u0430 (\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434) ConfigView.section.tracker.scrapecacheperiod=\u041a\u0435\u0448 \u0441\u0445\u043e\u0432\u0438\u0449\u0430 (\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434) ConfigView.section.tracker.scrapeandcache=\u0421\u0445\u043e\u0432\u0438\u0449\u0435 \u0456 \u043a\u0435\u0448 ConfigView.section.tracker.announcecacheminpeers=\u041a\u0435\u0448 \u0430\u043d\u043e\u043d\u0441\u0456\u0432, \u0432\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u043f\u043e\u0440\u0456\u0433 \u0434\u043b\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 MyTrackerView.scrapes=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0439 fileDownloadWindow.retry=\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438 MyTrackerView.bytesin=\u0412 \u0431\u0430\u0439\u0442\u0430\u0445 MyTrackerView.bytesinave=\u0421\u0435\u0440\u0435\u0434\u043d\u0454 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0438\u0445 \u0431\u0430\u0439\u0442\u0456\u0432 MyTrackerView.bytesout=\u0412\u0438\u0441\u043b\u0430\u043d\u0456 \u0431\u0430\u0439\u0442\u0438 MyTrackerView.bytesoutave=\u0421\u0435\u0440\u0435\u0434\u043d\u0454 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0438\u0441\u043b\u0430\u043d\u0438\u0445 \u0431\u0430\u0439\u0442\u0456\u0432 ConfigView.section.file.max_open_files=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 \u0434\u043b\u044f \u0447\u0438\u0442\u0430\u043d\u043d\u044f \u0430\u0431\u043e \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f\n[0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439] ConfigView.section.file.max_open_files.tooltip=\u041a\u043e\u0440\u0438\u0441\u043d\u043e \u043f\u0440\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u0441\u043e\u0442\u043d\u044f\u043c\u0438, \u0442\u0438\u0441\u044f\u0447\u0430\u043c\u0438 \u0444\u0430\u0439\u043b\u0456\u0432 \u0430\u0431\u043e \u044f\u043a\u0449\u043e \u0434\u043e\u0441\u044f\u0433\u043d\u0443\u0442\u0456 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u041e\u0421 \u0449\u043e\u0434\u043e \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 ConfigView.section.proxy=\u041f\u0440\u043e\u043a\u0441\u0456 ConfigView.section.proxy.enable_proxy=\u0414\u043e\u0441\u0442\u0443\u043f \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u043a\u0441\u0456-\u0441\u0435\u0440\u0432\u0435\u0440 ConfigView.section.proxy.host=\u0425\u043e\u0441\u0442 ConfigView.section.proxy.port=\u041f\u043e\u0440\u0442 ConfigView.section.proxy.username=\u0406\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 ConfigView.section.proxy.password=\u041f\u0430\u0440\u043e\u043b\u044c ConfigView.section.proxy.enable_socks=\u0423 \u043c\u0435\u043d\u0435 SOCKS-\u0441\u0443\u043c\u0456\u0441\u043d\u0438\u0439 \u043f\u0440\u043e\u043a\u0441\u0456-\u0441\u0435\u0440\u0432\u0435\u0440 wizard.createtorrent.extrahashes=\u0414\u043e\u0434\u0430\u0442\u0438 \u0445\u0435\u0448-\u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0434\u043b\u044f \u0456\u043d\u0448\u0438\u0445 \u043c\u0435\u0440\u0435\u0436 (\u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434 Gnutella2, eDonkey2000) GeneralView.label.connected=\u0437\u0432\u2019\u044f\u0437\u043e\u043a \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 GeneralView.label.in_swarm=\u0432 \u0433\u0440\u0443\u043f\u0430\u0445 ManagerItem.initializing=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f AlertMessageBox.error=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 AlertMessageBox.warning=\u0423\u0432\u0430\u0433\u0430 AlertMessageBox.comment=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f AlertMessageBox.information=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f AlertMessageBox.unread=\u041d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0456 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f - \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438 \u0457\u0445. SharedPortServer.alert.selectorfailed=\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0440\u0438\u0439\u043e\u043c \u0434\u0430\u043d\u0438\u0445.\n\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0432\u0430\u0448 \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440, \u0449\u043e\u0431 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 java(w).exe \u043c\u0430\u043b\u0430 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u043e\u0442\u0440\u0438\u043c\u0443\u0432\u0430\u0442\u0438 \u0456 \u0432\u0456\u0434\u0434\u0430\u0432\u0430\u0442\u0438 \u0434\u0430\u043d\u0456. Tracker.alert.listenfail=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0456 \u043f\u043e\u0440\u0442\u0443 \u0437\u0432'\u044f\u0437\u043a\u0443 %1.\n\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435, \u0447\u0438 \u043d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0446\u0435\u0439 \u043f\u043e\u0440\u0442 \u0456\u043d\u0448\u0438\u043c\u0438 \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u043d\u043a\u0430\u043c\u0438,\n\u0437\u043e\u043a\u0440\u0435\u043c\u0430 \u0456 \u0456\u043d\u0448\u043e\u044e \u043a\u043e\u043f\u0456\u0454\u044e Vuze. DiskManager.alert.movefileexists=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u043d\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043ba.\n\u0424\u0430\u0439\u043b %1 \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454 \u0432 \u043a\u0456\u043d\u0446\u0435\u0432\u0456\u0439 \u0442\u0435\u0446\u0456. DiskManager.alert.movefilefails=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u043d\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0443.\n\u041f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 %1 \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f, %2 DiskManager.alert.movefilerecoveryfails=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f \u043d\u0435\u0432\u0434\u0430\u043b\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 %1, %2 ConfigView.section.tracker.logenable=\u041f\u0435\u0440\u0456\u043e\u0434\u0438\u0447\u043d\u0435 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0432 'tracker.log' SpeedView.stats.title=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 SpeedView.stats.total=\u0412\u0441\u044c\u043e\u0433\u043e SpeedView.stats.session=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u0441\u0435\u0441\u0456\u044f SpeedView.stats.session.tooltip=\u0412\u0441\u044c\u043e\u0433\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) SpeedView.stats.downloaded=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) SpeedView.stats.uploaded=\u0420\u043e\u0437\u0434\u0430\u043d\u0438\u0445 (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) SpeedView.stats.ratio=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f SpeedView.stats.uptime=\u0427\u0430\u0441 \u0431\u0435\u0437\u043f\u0435\u0440\u0435\u0440\u0432\u043d\u043e\u0457 \u0440\u043e\u0431\u043e\u0442\u0438 (\u0443 \u0433\u043e\u0434\u0438\u043d\u0430\u0445) SpeedView.stats.now=\u0417\u0430\u0440\u0430\u0437 SpeedView.stats.now.tooltip=\u0412\u0441\u044c\u043e\u0433\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) AutoMigration.useralert=\u0406\u043c\u043f\u043e\u0440\u0442 \u0444\u0430\u0439\u043b\u0456\u0432 \u0456 \u0442\u0435\u043a \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457:\n\n%1\n\u0412 \u0440\u0430\u0437\u0456 \u043d\u0435\u0432\u0434\u0430\u0447\u0456 \u0456\u043c\u043f\u043e\u0440\u0442 \u043c\u0430\u0454 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u0438\u0441\u044f \u0432\u0440\u0443\u0447\u043d\u0443.\n\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0432 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u0456\u043c\u043f\u043e\u0440\u0442\u0443! # # > 2.0.8.0 # OpenTorrentWindow.title=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442(\u0438) OpenTorrentWindow.message=\u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e OpenTorrentWindow.addFiles=&\u0414\u043e\u0434\u0430\u0442\u0438 \u0444\u0430\u0439\u043b OpenTorrentWindow.dataLocation=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445: OpenTorrentWindow.startMode=\u0420\u0435\u0436\u0438\u043c \u0434\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u044f OpenTorrentWindow.startMode.queued=\u0423 \u0447\u0435\u0440\u0437\u0456 OpenTorrentWindow.startMode.stopped=\u0417\u0443\u043f\u0438\u043d\u0435\u043d\u0438\u0439 OpenTorrentWindow.startMode.forceStarted=\u041f\u0440\u0438\u0448\u0432\u0438\u0434\u0448\u0435\u043d\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a OpenTorrentWindow.addPosition=\u041f\u043e\u0437\u0438\u0446\u0456\u044f \u0432 \u0447\u0435\u0440\u0437\u0456 OpenTorrentWindow.addPosition.first=\u041f\u0435\u0440\u0448\u0430 OpenTorrentWindow.addPosition.last=\u041e\u0441\u0442\u0430\u043d\u043d\u044f TableColumn.header.remaining.info=\u0417\u0430\u043b\u0438\u0448\u0438\u043b\u043e\u0441\u044f \u0434\u043e\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 TableColumn.header.remaining=\u0417\u0430\u043b\u0438\u0448\u0438\u043b\u043e\u0441\u044f ConfigView.section.tracker.enablecompact=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043e\u043f\u043e\u0432\u0456\u0449\u0435\u043d\u043d\u044f ConfigView.section.tracker.enablekey=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0443 \u043a\u043b\u044e\u0447\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u0434\u043b\u044f \u043f\u0456\u0434\u0432\u0438\u0449\u0435\u043d\u043e\u0457 \u0431\u0435\u0437\u043f\u0435\u043a\u0438 ConfigView.section.file.perf=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0456 ConfigView.section.file.perf.explain=\u041e\u0431\u0435\u0440\u0435\u0436\u043d\u043e - \u043d\u0435\u043e\u0431\u0434\u0443\u043c\u0430\u043d\u0456 \u0437\u043c\u0456\u043d\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0456\u0432 \u043c\u043e\u0436\u0443\u0442\u044c \u043c\u0430\u0442\u0438 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u0438\u0439 \u0435\u0444\u0435\u043a\u0442 \u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.\n\u0412\u0438\u043c\u0430\u0433\u0430\u0454\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a. \u041f\u0440\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043d\u0456\u0439 \u043f\u0430\u043c'\u044f\u0442\u0456 \u043f\u043e\u0434\u0443\u043c\u0430\u0439\u0442\u0435 \u043f\u0440\u043e \u0437\u043d\u0438\u0436\u0435\u043d\u043d\u044f \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0437\u0432'\u044f\u0437\u043a\u0456\u0432 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 (\u0434\u0438\u0432. \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447). ConfigView.section.file.max_open_files.explain=\u041f\u0440\u0438 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u0445 \u0432\u0435\u043b\u0438\u043a\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 \u043c\u043e\u0436\u0435 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438. \u0422\u0443\u0442 \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0431\u043c\u0435\u0436\u0438\u0442\u0438 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432. popup.error.hide=\u0421\u0445\u043e\u0432\u0430\u0442\u0438 popup.error.details=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e ConfigView.section.style.colorOverrides=\u041f\u0456\u0434\u043c\u0456\u043d\u0430 \u043a\u043e\u043b\u044c\u043e\u0440\u0456\u0432 ConfigView.section.style.colorOverride.progressBar=\u0406\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u043d\u044f ConfigView.section.style.colorOverride.error=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 MainWindow.status.tooOld=\u0437\u0430\u0441\u0442\u0430\u0440\u0456\u043b\u0430, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u043f\u043e\u043d\u043e\u0432\u0456\u0442\u044c. ConfigView.section.style.colorOverride.warning=\u0423\u0432\u0430\u0433\u0430 ConfigView.section.style.colorOverride.altRow=\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0438\u0439 \u0440\u044f\u0434\u043e\u043a ConfigView.section.file.save.peers.enable=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0437\u0432'\u044f\u0437\u043e\u043a \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438 \u0434\u043b\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0433\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f ConfigView.section.file.save.peers.max=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0445 \u0437\u0432'\u044f\u0437\u043a\u0456\u0432 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439] ConfigView.section.file.save.peers.pertorrent=\u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 ConfigView.label.max_peers_per_torrent=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437'\u0454\u0434\u043d\u0430\u043d\u044c \u0434\u043b\u044f \u043a\u043e\u0436\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] ConfigView.label.max_peers_total=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0432\u0441\u0456\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] ConfigView.section.style.colorOverrides.reset=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0456 \u043a\u043e\u043b\u044c\u043e\u0440\u0438 ConfigView.section.language.info=\u042f\u043a\u0449\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0438\u0439 \u0446\u0435\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u0431\u0443\u0434\u0435 \u0432\u0456\u0434\u0431\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u043f\u0440\u0438 \u043a\u043e\u0436\u043d\u043e\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 ConfigView.section.language.enableUpdate=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0440\u0435\u0436\u0443 ConfigView.section.language.UpdateURL=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 URL ConfigView.section.language.UpdateNow=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0437\u0430\u0440\u0430\u0437! Button.revert=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 MyTorrentsView.menu.changeDirectory=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u0442\u0435\u043a\u0438 \u0434\u0430\u043d\u0438\u0445 GenericText.column=\u0421\u0442\u043e\u0432\u043f\u0435\u0446\u044c MyTorrentsView.menu.thisColumn.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c MyTorrentsView.menu.thisColumn.toClipboard=\u0412 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443 MyTorrentsView.menu.thisColumn.autoTooltip=\u0417\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0435 \u0432\u0456\u043a\u043d\u043e MyTorrentsView.menu.tracker=\u0422\u0440\u0435\u043a\u0435\u0440 ConfigView.download.abbreviated=\u0417\u0430\u0432\u0430\u043d\u0442.: ConfigView.upload.abbreviated=\u0420\u043e\u0437\u0434.: ConfigView.complete.abbreviated=\u0413\u0430\u0440\u0430\u0437\u0434: TableColumn.header.secondsseeding=\u0420\u043e\u0437\u0434\u0430\u0454\u043c\u043e \u0432\u0436\u0435 TableColumn.header.secondsseeding.info=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0439 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 TableColumn.header.secondsdownloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u043c\u043e \u0432\u0436\u0435 TableColumn.header.secondsdownloading.info=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0439 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ConfigView.section.tracker.udpversion=\u0412\u0435\u0440\u0441\u0456\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 UDP (1 \u0430\u0431\u043e 2) window.updateswt.title=\u0412\u0430\u0448\u0430 \u0432\u0435\u0440\u0441\u0456\u044f \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 SWT \u0437\u0430\u0441\u0442\u0430\u0440\u0456\u043b\u0430! window.updateswt.text=\u0412\u0430\u0448\u0430 \u0432\u0435\u0440\u0441\u0456\u044f \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 SWT \u0437\u0430\u0441\u0442\u0430\u0440\u0456\u043b\u0430!\nVuze \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 SWT \u0434\u043b\u044f \u0432\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0433\u0440\u0430\u0444\u0456\u043a\u0438. \u041e\u0441\u0442\u0430\u043d\u043d\u044f \u0432\u0435\u0440\u0441\u0456\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043d\u043e\u0432\u0456\u0448\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 SWT.\n\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u0413\u0430\u0440\u0430\u0437\u0434 \u0434\u043b\u044f \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f SWT. window.updateswt.status=\u0421\u0442\u0430\u0442\u0443\u0441 window.updateswt.failed=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435, \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u0413\u0430\u0440\u0430\u0437\u0434 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443. window.updateswt.status.downloading.updater=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043c\u043e\u0434\u0443\u043b\u044f \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c window.updateswt.status.finding=\u041f\u043e\u0448\u0443\u043a \u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 SWT window.updateswt.status.downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 SWT window.updateswt.status.done=\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a window.updateswt.ok=\u0413\u0430\u0440\u0430\u0437\u0434 window.updateswt.cancel=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 swt.updater.downloader.downloading=\u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0430 SWT \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u044c\u0441\u044f swt.updater.urlsgetter.downloading=\u041e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u0441\u043f\u0438\u0441\u043a\u0443 \u043b\u044e\u0441\u0442\u0435\u0440\u043e\u043a swt.updater.urlsgetter.platform=\u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0430 SWT \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0438 : window.updateswt.ignore=\u041f\u0440\u043e\u0456\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 ConfigView.section.style.useFancyTabs=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043e\u0441\u043e\u0431\u043b\u0438\u0432\u0438\u0439 \u0432\u0438\u0433\u043b\u044f\u0434 \u0437\u0430\u043a\u043b\u0430\u0434\u043e\u043a splash.initializeGM=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f Global Torrent Manager splash.loadingTorrents=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 MyTorrentsView.menu.thisColumn.sort=&\u0421\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438 Scrape.status.ok=\u0428\u043a\u0440\u044f\u0431\u0430\u043d\u043d\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435. Scrape.status.error=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0448\u043a\u0440\u044f\u0431\u0430\u043d\u043d\u044f: Scrape.status.error.badURL=\u0417\u0430\u0434\u0430\u043d\u0430 \u0430\u0434\u0440\u0435\u0441\u0430 \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u0441\u043f\u0435\u0446\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u0457 \u0448\u043a\u0440\u044f\u0431\u0430\u043d\u044c. Scrape.status.error.nohash=\u0412\u0456\u0434\u0441\u0443\u0442\u043d\u0456\u0441\u0442\u044c \u0445\u0435\u0448\u0443 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0456. Scrape.status.error.invalid=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0430 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u044c. Scrape.status.nextScrapeAt=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0435 \u0448\u043a\u0440\u044f\u0431\u0430\u043d\u043d\u044f %1 Scrape.status.scraping=\u0428\u043a\u0440\u044f\u0431\u0430\u043d\u043d\u044f.. Scrape.status.initializing=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u043a\u0440\u044f\u0431\u0430\u043d\u043d\u044f... Scrape.status.scraping.queued=\u0428\u043a\u0440\u044f\u0431\u0430\u043d\u043d\u044f \u0432 \u0447\u0435\u0440\u0437\u0456... ConfigView.label.minSpeedForActiveSeeding=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0435 \u0437\u0430\u0439\u043c\u0430\u0454 \u0441\u043b\u043e\u0442, \u044f\u043a\u0449\u043e \u0439\u043e\u0433\u043e \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u043d\u0438\u0436\u0447\u0435 \u043d\u0456\u0436 ConfigView.section.stats.exportpeers=\u0415\u043a\u0441\u043f\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043f\u0440\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 MainWindow.menu.view.irc.moved=IRC \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0432 \u044f\u043a\u043e\u0441\u0442\u0456 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043d\u0430 http://azureus.sourceforge.net/plugin_list.php. \u042f\u043a\u0449\u043e \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0435 - \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u043c\u0435\u043d\u044e \u0421\u0435\u0440\u0432\u0456\u0441 > \u0414\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f > IRC MyTrackerView.webui.contextmenu.copyurl=\u0421\u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443 ConfigView.section.file.torrent.ignorefiles=\u041f\u0440\u0438 \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0456\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438\n(\u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434 DS_Store;Thumbs.db) Torrent.create.progress.ignoringfile=\u0424\u0430\u0439\u043b \u0456\u0433\u043d\u043e\u0440\u0443\u0454\u0442\u044c\u0441\u044f ConfigView.section.style.useUnitsRateBits=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0431\u0456\u0442\u0438 \u0437\u0430\u043c\u0456\u0441\u0442\u044c \u0431\u0430\u0439\u0442\u0456\u0432 \u0434\u043b\u044f \u0432\u0438\u043c\u0456\u0440\u044e\u0432\u0430\u043d\u0438\u0445 \u0432 \u0431\u0430\u0439\u0442\u0430\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f\u0445 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 (\u041a\u0431\u0456\u0442/\u0441 > \u041a\u0456\u0431\u0456\u0442/\u0441 \u0456 \u0456\u043d.) ConfigView.section.interface.resetassoc=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u0432 \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0438\u0439 \u0441\u0442\u0430\u043d \u0430\u0441\u043e\u0446\u0456\u0430\u0446\u0456\u0457\n\u0437 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043d\u044f\u043c\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 (.torrent) ConfigView.section.interface.resetassocbutton=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u0434\u043e \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0443 ConfigView.section.interface.checkassoc=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u044c, \u043f\u043e\u0432'\u044f\u0437\u0430\u043d\u0438\u0445 \u0437 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e dialog.associations.title=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0430\u0441\u043e\u0446\u0456\u0430\u0446\u0456\u0439 Button.yes=&\u0422\u0430\u043a Button.no=&\u041d\u0456 ConfigView.label.seeding.autoStart0Peers=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0449\u043e \u043d\u0435\u043c\u0430 \u0441\u0456\u0434\u0435\u0440\u0456\u0432 ConfigView.label.seeding.autoStart0Peers.tooltip=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0440\u0438 \u0431\u0430\u0436\u0430\u043d\u043d\u0456, \u0449\u043e\u0431 \u0441\u0435\u0440\u0432\u0435\u0440 \u0437\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0432 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0431\u0435\u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432. dialog.associations.prompt=Vuze \u043d\u0435 \u0454 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0456\u0432 BitTorrent.\n\u0411\u0430\u0436\u0430\u0454\u0442\u0435 \u043f\u0440\u0438\u0432\u043b\u0430\u0441\u043d\u0438\u0442\u0438 Vuze \u0446\u0435\u0439 \u0441\u0442\u0430\u0442\u0443\u0441? dialog.associations.askagain=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 ConfigView.section.plugins.update=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c Plugin.pluginupdate.enablecheck=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c plugins.basicview.status=\u0421\u0442\u0430\u0442\u0443\u0441: plugins.basicview.activity=\u0414\u0456\u044f\u043b\u044c\u043d\u0456\u0441\u0442\u044c: plugins.basicview.progress=\u041f\u0440\u043e\u0433\u0440\u0435\u0441: plugins.basicview.log=\u0416\u0443\u0440\u043d\u0430\u043b: ConfigView.label.maxdownloadspeed=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u041a\u0431\u0456\u0442/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] splash.loadingTorrent=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 splash.of=\u0437 ConfigView.section.plugins.irc=\u041a\u0430\u043d\u0430\u043b IRC UpdateWindow.title=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f Vuze UpdateWindow.header=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0435 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f: UpdateWindow.columns.install=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 UpdateWindow.columns.name=\u0406\u043c'\u044f UpdateWindow.columns.version=\u0412\u0435\u0440\u0441\u0456\u044f UpdateWindow.columns.size=\u0420\u043e\u0437\u043c\u0456\u0440 UpdateWindow.cancel=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 UpdateWindow.quit=\u0412\u0438\u0445\u0456\u0434 UpdateWindow.close=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 UpdateWindow.ok=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f UpdateWindow.restart=\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0437\u0430\u0440\u0430\u0437 UpdateWindow.status.downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f UpdateWindow.status.done=\u0412\u0438\u043a\u043e\u043d\u0430\u043d\u0435 UpdateWindow.status.failed=\u041d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435 UpdateWindow.status.restartNeeded=\u0412\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443! ConfigView.pluginlist.broken=\u041f\u043e\u0448\u043a\u043e\u0434\u0436\u0435\u043d\u0438\u0439 ConfigView.pluginlist.whereToPut=\u041f\u043e\u043c\u0456\u0441\u0442\u0456\u0442\u044c \u0432\u0438\u0431\u0440\u0430\u043d\u0435 \u0412\u0430\u043c\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0437 \u0432\u043b\u0430\u0441\u043d\u043e\u0457 \u0442\u0435\u043a\u0438 \u0432: ConfigView.pluginlist.whereToPutOr=\u0414\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u043d\u0438\u0445 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438: MainWindow.statusText.checking=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043d\u043e\u0432\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 TableColumn.header.OnlyCDing4=\u041d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 TableColumn.header.OnlyCDing4.info=\u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u0438\u0439 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0430, \u043d\u0435 \u0432\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ConfigView.section.style.alternateTablePainting=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0443 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0441\u0442\u043e\u0432\u043f\u0446\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0456 (\u043c\u043e\u0436\u0435 \u0432\u0438\u043c\u0430\u0433\u0430\u0442\u0438\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a) UpdateWindow.status.restartMaybeNeeded=\u041c\u043e\u0436\u043b\u0438\u0432\u043e, \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0438\u0439 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a. ConfigView.pluginlist.shared=\u0440\u043e\u0437\u0434\u0430\u043d\u0438\u0439 PeersView.host=\u0406\u043c'\u044f \u0445\u043e\u0441\u0442\u0430 PeersView.host.info=\u0406\u043c'\u044f \u043f\u0440\u0438\u0439\u043c\u0430\u044e\u0447\u043e\u0433\u043e \u0445\u043e\u0441\u0442\u0430, \u044f\u043a\u0449\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e (\u0432\u043f\u043b\u0438\u0432\u0430\u0454 \u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c) MainWindow.menu.help.whatsnew=\u0429\u043e \u043d\u043e\u0432\u043e\u0433\u043e ConfigView.label.checkonstart=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 ConfigView.label.periodiccheck=\u041f\u0435\u0440\u0456\u043e\u0434\u0438\u0447\u043d\u0430 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c ConfigView.label.opendialog=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u041c\u0430\u0439\u0441\u0442\u0435\u0440 \u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u043f\u0440\u0438 \u043d\u0430\u044f\u0432\u043d\u043e\u0441\u0442\u0456 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c MainWindow.updateavail=\u0406\u0441\u043d\u0443\u0454 \u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0456\u044f MainWindow.status.unofficialversion=Vuze-\u0431\u0435\u0442\u0430 MainWindow.status.latestversionunchecked=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0430 GeneralView.label.updatein.stopped=\u0417\u0443\u043f\u0438\u043d\u043a\u0430 StartStopRules.menu.viewDebug=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f ConfigView.section.style.doNotUseGB=\u041d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0413\u0411\u0430\u0439\u0442 \u044f\u043a \u043e\u0434\u0438\u043d\u0438\u0446\u044e ConfigView.section.style.doNotUseGB.tooltip=\u042f\u043a\u0449\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0438\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u0431\u0443\u0434\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442\u0438 (M\u0411\u0430\u0439\u0442), \u043d\u0430\u0432\u0456\u0442\u044c \u044f\u043a\u0449\u043e \u0440\u043e\u0437\u043c\u0456\u0440 \u043f\u0435\u0440\u0435\u0432\u0438\u0449\u0443\u0454 1024 \u041c\u0411\u0430\u0439\u0442 MainWindow.menu.help.plugins=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f ConfigView.section.plugins.TrackerWeb=\u0422\u0440\u0435\u043a\u0435\u0440 \u043c\u0435\u0440\u0435\u0436\u0456 ConfigView.section.tracker.enablecategories=\u0421\u043e\u0440\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044f\u043c\u0438 health.explain.share=\u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0435 \u0440\u043e\u0437\u0434\u0430\u0454\u0442\u044c\u0441\u044f \u0456 \u043d\u0435 \u043f\u0443\u0431\u043b\u0456\u043a\u0443\u0454\u0442\u044c\u0441\u044f ConfigView.section.tracker.createcert=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u043d\u0438\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 ConfigView.section.tracker.createbutton=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 security.certcreate.title=\u0421\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442\u0430 security.certcreate.intro=\u0426\u0435\u0439 \u0434\u0456\u0430\u043b\u043e\u0433 \u0434\u043e\u043f\u043e\u043c\u0430\u0433\u0430\u0454 \u043f\u0440\u0438 \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u0456 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442\u0430 security.certcreate.alias=\u042f\u0440\u043b\u0438\u043a security.certcreate.strength=\u0421\u0442\u0456\u0439\u043a\u0456\u0441\u0442\u044c security.certcreate.firstlastname=\u0406\u043c'\u044f, \u043f\u0440\u0456\u0437\u0432\u0438\u0449\u0435 security.certcreate.orgunit=\u0412\u0456\u0434\u0434\u0456\u043b\u0435\u043d\u043d\u044f \u043e\u0440\u0433\u0430\u043d\u0456\u0437\u0430\u0446\u0456\u0457 security.certcreate.org=\u041e\u0440\u0433\u0430\u043d\u0456\u0437\u0430\u0446\u0456\u044f security.certcreate.city=\u041c\u0456\u0441\u0442\u043e \u0430\u0431\u043e \u043c\u0456\u0441\u0446\u0435\u0437\u043d\u0430\u0445\u043e\u0434\u0436\u0435\u043d\u043d\u044f security.certcreate.state=\u041e\u0431\u043b\u0430\u0441\u0442\u044c \u0430\u0431\u043e \u0440\u0430\u0439\u043e\u043d security.certcreate.country=\u0414\u0432\u043e\u0437\u043d\u0430\u0447\u043d\u0438\u0439 \u043a\u043e\u0434 \u043a\u0440\u0430\u0457\u043d\u0438 security.certcreate.ok=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 security.certcreate.cancel=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 security.certcreate.createok=\u0421\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442\u0430 \u043f\u0440\u043e\u0439\u0448\u043b\u043e \u0443\u0441\u043f\u0456\u0448\u043d\u043e security.certcreate.createfail=\u0421\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442\u0430 \u043f\u0440\u043e\u0439\u0448\u043b\u043e \u043d\u0435 \u0443\u0441\u043f\u0456\u0448\u043d\u043e ConfigView.section.plugins.webui=\u0417\u043c\u0456\u043d\u0435\u043d\u043d\u044f \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u043c\u0435\u0440\u0435\u0436\u0456 ConfigView.section.plugins.xml_http_if=\u0406\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 XML/HTTP webui.passwordenable=\u0410\u043a\u0442\u0438\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u0430\u0440\u043e\u043b\u044c webui.user=\u0406\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 webui.password=\u041f\u0430\u0440\u043e\u043b\u044c webui.port=\u041f\u043e\u0440\u0442 * webui.protocol=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b * webui.homepage=\u0414\u043e\u043c\u0430\u0448\u043d\u044f \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0430 * webui.rootdir=\u0413\u043e\u043b\u043e\u0432\u043d\u0430 \u0442\u0435\u043a\u0430 * webui.rootres=\u0413\u043e\u043b\u043e\u0432\u043d\u0438\u0439 \u0440\u0435\u0441\u0443\u0440\u0441 * webui.mode=\u0420\u0435\u0436\u0438\u043c * webui.mode.info=\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u0440\u0435\u0436\u0438\u043c\n\t"\u041f\u043e\u0432\u043d\u0438\u0439"\t= \u0432\u0441\u0456 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 (\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 \u0440\u0435\u0436\u0438\u043c)\n\t"\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434"\t= \u043b\u0438\u0448\u0435 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434\u0430\u043d\u043d\u044f (\u043c\u043e\u0436\u043b\u0438\u0432\u0435 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0435 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f) webui.access=\u0414\u043e\u0441\u0442\u0443\u043f * webui.access.info=\u0414\u043e\u0441\u0442\u0443\u043f \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438\n\t"\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0438\u0439"\t= \u043b\u0438\u0448\u0435 \u0446\u0435\u0439 \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440 \u043c\u0430\u0454 \u0434\u043e\u0441\u0442\u0443\u043f\n\t"\u0412\u0441\u0456"\t= \u0434\u043e\u0441\u0442\u0443\u043f \u0431\u0435\u0437 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u044c (\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439)\n\tIP\t= \u043d\u0430\u043f\u0440. 192.168.0.2\t\t \u043b\u0438\u0448\u0435 \u043e\u0434\u043d\u0430 IP-\u0430\u0434\u0440\u0435\u0441\u0430\n\tIP1-IP2\t= \u043d\u0430\u043f\u0440. 192.168.0.1-192.168.0.255\t\u0432\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u043c\u0435\u0436\u0456 \u0430\u0434\u0440\u0435\u0441\u0438 GeneralView.label.maxdownloadspeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f Security.keystore.corrupt=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043a\u043b\u044e\u0447\u0430 '%1', \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0439\u043e\u0433\u043e \u0456 \u0441\u0442\u0432\u043e\u0440\u0456\u0442\u044c \u0447\u0438 \u0456\u043c\u043f\u043e\u0440\u0442\u0443\u0439\u0442\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 \u043d\u0430\u043d\u043e\u0432\u043e Security.keystore.empty=\u041a\u043b\u044e\u0447 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u043d\u0435 \u0456\u0441\u043d\u0443\u0454. \u0421\u0442\u0432\u043e\u0440\u0456\u0442\u044c \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u043d\u0438\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 (\u0434\u0438\u0432. \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f > \u0411\u0435\u0437\u043f\u0435\u043a\u0430) \u0430\u0431\u043e \u0456\u043c\u043f\u043e\u0440\u0442\u0443\u0439\u0442\u0435 \u043d\u0430\u044f\u0432\u043d\u0438\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 \u0432 '%1' webui.restart.info=* \u0417\u043c\u0456\u043d\u0438 \u0446\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0456\u0432 \u0434\u0456\u044f\u0442\u0438\u043c\u0443\u0442\u044c \u043f\u0456\u0441\u043b\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f GeneralView.label.maxdownloadspeed.tooltip=, \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] upnp.enable=\u0410\u043a\u0442\u0438\u0432\u0443\u0432\u0430\u0442\u0438 UPn upnp.info=\u0423\u043d\u0456\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0438\u0439 Plug and Play (UPn) \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u044f\u0454 \u043f\u043e\u0440\u0442\u0438 \u043d\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0430\u0445 \u0437 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u043e\u044e UPn. upnp.mapping.dataport=\u041f\u043e\u0440\u0442 \u0434\u043b\u044f \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u0434\u0430\u043d\u0438\u0445 upnp.mapping.tcptrackerport=TCP \u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 upnp.mapping.udptrackerport=UDP \u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 upnp.alert.differenthost=UPn: \u041f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043e\u0432\u0430\u043d\u0435 '%2' - \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0456\u043d\u0448\u0438\u0439 \u043f\u043e\u0440\u0442 upnp.alert.mappingok=UPn: \u041f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435 upnp.alert.mappingfailed=UPn: \u041f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u0442\u0438 upnp.alertsuccess=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0432\u0434\u0430\u043b\u0456 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f upnp.alert.lostdevice=UPn: \u0412\u0442\u0440\u0430\u0447\u0435\u043d\u0435 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0441\u0435\u0440\u0432\u0456\u0441\u043e\u043c '%1' \u043d\u0430 Upn-\u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457 '%2' upnp.grabports=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0438\u0442\u0438 \u043f\u043e\u0440\u0442\u0438, \u043d\u0430\u0432\u0456\u0442\u044c \u044f\u043a\u0449\u043e \u0432\u043e\u043d\u0438 \u043d\u0430\u043b\u0435\u0436\u0430\u0442\u044c \u0456\u043d\u0448\u043e\u043c\u0443 \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440\u0443 upnp.refresh.label=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b \u043f\u043e\u0440\u0442\u0456\u0432 upnp.refresh.button=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 upnp.alert.mappinggrabbed=UPn: \u041f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435 - \u0432\u0437\u044f\u0442\u043e \u0437 '%2' upnp.mapping.tcpssltrackerport=TCP SSL-\u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 upnp.alertothermappings=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u0440\u0442\u0438, \u0437\u0430\u0439\u043d\u044f\u0442\u0456 \u0456\u043d\u0448\u0438\u043c\u0438 \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440\u0430\u043c\u0438 upnp.alertdeviceproblems=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u0442\u0438 \u043f\u0440\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 \u0437 Upn-\u043f\u0440\u0438\u0441\u0442\u0440\u043e\u044f\u043c\u0438 upnp.trace_to_log=\u0417\u0430\u043f\u0438\u0441\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0432 \u043b\u043e\u0433 upnp.wiki_link=Vuze Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0430 \u043f\u0440\u043e UPnP upnp.refresh_mappings_on_bad_nat=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u044e\u0432\u0430\u0442\u0438 \u043c\u0430\u043f\u043f\u0456\u043d\u0433, \u043a\u043e\u043b\u0438 \u0441\u0442\u0430\u0442\u0443\u0441 NAT \u0431\u0443\u0434\u0435 "\u043f\u0456\u0434 \u0444\u0430\u0439\u0435\u0440\u0432\u043e\u043b\u043e\u043c" blank.resource=\u0420\u0435\u0441\u0443\u0440\u0441 ConfigView.pluginlist.coreplugins=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u0432\u0431\u0443\u0434\u043e\u0432\u0430\u043d\u0456 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f: Peers.column.DLedFromOthers=\u0412\u0456\u0434 \u0456\u043d\u0448\u0438\u0445 Peers.column.DLedFromOthers.info=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u0430\u043d\u0438\u0445, \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 \u0432\u0456\u0434 \u0456\u043d\u0448\u0438\u0445, \u043f\u0456\u0434 \u0447\u0430\u0441 \u0457\u0445\u043d\u044c\u043e\u0433\u043e \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0432\u0430\u043c\u0438 Peers.column.UpDownRatio=\u0420\u043e\u0437\u0434\u0430\u043d\u0438\u0445/\u041f\u0440\u0438\u0439\u043d\u044f\u0442\u0438\u0445 Peers.column.UpDownRatio.info=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 "\u0420\u043e\u0437\u0434\u0430\u043d\u0438\u0445/\u041f\u0440\u0438\u0439\u043d\u044f\u0442\u0438\u0445" Peers.column.UpRatio=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 Peers.column.UpRatio.info=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 "\u041e\u0442\u0440\u0438\u043c\u0430\u043d\u0435 \u0432\u0456\u0434 \u0432\u0430\u0441/\u041e\u0442\u0440\u0438\u043c\u0430\u043d\u0435 \u0432\u0456\u0434 \u0456\u043d\u0448\u0438\u0445" upnp.releasemappings=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 webui.upnpenable=\u0414\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 UPn \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0443 * ConfigView.section.file.friendly.hashchecking=\u0414\u0440\u0443\u0436\u043d\u044f \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0445\u0435\u0448\u0443 ConfigView.section.file.friendly.hashchecking.tooltip=\u0422\u0440\u043e\u0445\u0438 \u043f\u043e\u0432\u0456\u043b\u044c\u043d\u0438\u0439, \u0430\u043b\u0435 \u0456\u0441\u0442\u043e\u0442\u043d\u043e \u0440\u043e\u0437\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454 \u0426\u041f\u0423 \u0442\u0430 \u0447\u0430\u0441\u0442\u043a\u043e\u0432\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u0445\u0435\u0448\u0443. ConfigView.section.tracker.seedretention=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043a\u043b\u0456\u0454\u043d\u0442\u0456\u0432, \u044f\u043a\u0430 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0454\u0442\u044c\u0441\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u043c [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] ConfigView.section.tracker.seedretention.info=\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u043d\u0435\u0443\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 \u043a\u043b\u0456\u0454\u043d\u0442\u0456\u0432 \u0431\u0443\u0434\u0435 \u0432\u0442\u0440\u0430\u0447\u0435\u043d\u043e\u044e ConfigView.section.tracker.port=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043e\u0440\u0442 HTTP \u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.tracker.sslport=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 \u043f\u043e\u0440\u0442 SSL \u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.tracker.publicenable.info=\u0426\u0435 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u0456\u043d\u0448\u0438\u043c \u0441\u0442\u0432\u043e\u0440\u044e\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u0449\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c \u0412\u0430\u0448 \u0442\u0440\u0435\u043a\u0435\u0440,\n\u0430\u043b\u0435 \u0431\u0435\u0437 \u0412\u0430\u0448\u043e\u0433\u043e \u043f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f Button.clear=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 MainWindow.IPs.tooltip={\u041e\u0441\u0442\u0430\u043d\u043d\u0454 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0441\u043f\u0438\u0441\u043a\u0443 \u0444\u0456\u043b\u044c\u0442\u0440\u0430\u0446\u0456\u0457} \u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0432\u0456\u0434\u0444\u0456\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u043d\u0438\u0445 IP - \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0445/\u0437\u0430\u0431\u0430\u043d\u0435\u043d\u0438\u0445/\u043d\u0435\u0432\u0434\u0430\u043b\u0438\u0445 IP \u0434\u043b\u044f \u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0457 \u0441\u0435\u0441\u0456\u0457.\n\u0414\u0432\u0456\u0447\u0456 \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043b\u0456\u0432\u043e\u044e \u0434\u043b\u044f \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457. ConfigView.section.ipfilter.list.banned=\u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0456 \u0437\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0445 \u0434\u0430\u043d\u0438\u0445 ConfigView.section.ipfilter.list.baddata=\u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0456 \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0456 \u0434\u0430\u043d\u0456: \u0432\u0438\u043f\u0430\u0434\u043a\u0456\u0432: Button.reset=\u0421\u043a\u0438\u043d\u0443\u0442\u0438 ConfigView.section.ipfilter.bannedinfo=\u0410\u0434\u0440\u0435\u0441\u0438 IP, \u0449\u043e \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043b\u0438 \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0456 \u0434\u0430\u043d\u0456 \u0456 \u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0456 ConfigView.section.ipfilter.blockedinfo=\u0410\u0434\u0440\u0435\u0441\u0438, \u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0456 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u0444\u0456\u043b\u044c\u0442\u0440\u0456\u0432 IP download.removerules.name=\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f download.removerules.unauthorised.info=\u041d\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u0438\u043c\u0438 \u0454 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432 \u0442\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u044f\u043a\u0449\u043e \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u044c \u043d\u0430 \u0437\u0430\u043f\u0438\u0442 \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u0432 "\u041f\u043e\u043c\u0438\u043b\u0446\u0456 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0456" \u0440\u044f\u0434\u043a\u0438 "not authoris(z)ed" \u0430\u0431\u043e "unauthoris(z)ed" download.removerules.unauthorised=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u043d\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 download.removerules.unauthorised.seedingonly=\t\u041b\u0438\u0448\u0435 \u043f\u0440\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 download.removerules.removed.ok=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f '%1' \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432. \u0426\u0435 \u0432\u0456\u0434\u0431\u0443\u043b\u043e\u0441\u044f \u0437\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432. download.removerules.updatetorrents=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c Vuze, \u044f\u043a\u0449\u043e \u0446\u0435 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044e ConfigView.label.defaultstarttorrentsstopped=\u0414\u043e\u0434\u0430\u0432\u0430\u0442\u0438 \u043d\u043e\u0432\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0431\u0435\u0437 \u0457\u0445\u043d\u044c\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0443 ConfigView.section.server.enableudp=\u0410\u043a\u0442\u0438\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b UDP upnp.mapping.dataportudp=UDP-\u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.file.decoder.showlax=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0433\u0456\u0440\u0448\u0456 \u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f ConfigView.section.file.decoder.showall=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0432\u0441\u0456 \u043c\u043e\u0436\u043b\u0438\u0432\u0456 \u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f MainWindow.status.updowndetails.tooltip=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e \u043f\u0440\u043e \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0430\u0431\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f - \u0434\u0432\u0456\u0447\u0456 \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043f\u0440\u0430\u0432\u043e\u044e, \u0449\u043e\u0431 \u0437\u043c\u0456\u043d\u0438\u0442\u0438 TrackerClient.announce.warningmessage=\u0422\u0440\u0435\u043a\u0435\u0440 \u0434\u043b\u044f '%1' \u0432\u0438\u0434\u0430\u0432 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u043d\u044f '%2' ConfigView.section.tracker.natcheckenable=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u044f\u0442\u0438 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u043f\u0440\u0438\u0439\u043e\u043c\u0443 \u0434\u0430\u043d\u0438\u0445 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0435\u043c \u0456 \u0432\u0438\u0434\u0430\u0432\u0430\u0442\u0438 \u043f\u043e\u043c\u0438\u043b\u043a\u0438, \u044f\u043a\u0449\u043e \u0446\u0435 \u043d\u0435 \u0432\u0434\u0430\u0454\u0442\u044c\u0441\u044f ConfigView.section.tracker.publishenabledetails=\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 \u0432\u0441\u0456 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043f\u0440\u043e \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.section.tracker.publishenablepeerdetails=\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 \u0432\u0441\u0456 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043f\u0440\u043e \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 MyTrackerView.badnat=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0430\u043d\u0438\u0439 NAT MyTrackerView.badnat.info=\u0421\u0456\u0434\u0435\u0440\u0438 \u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438, \u044f\u043a\u0456 \u043d\u0435 \u043f\u0440\u043e\u0439\u0448\u043b\u0438 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0443 NAT, \u044f\u043a\u0449\u043e \u0446\u0435 \u0434\u043e\u0437\u0432\u043e\u043b\u0435\u043d\u043e ConfigView.section.tracker.natchecktimeout=\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u0447\u0430\u0441 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 (\u0441\u0435\u043a\u0443\u043d\u0434) ConfigView.section.file.perf.cache.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043a\u0435\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0434\u0438\u0441\u043a\u0443 ConfigView.section.file.perf.cache.size=\u0420\u043e\u0437\u043c\u0456\u0440 \u043a\u0435\u0448\u0443 \u0432 %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 MainWindow.menu.transfers.startalltransfers=&\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0432\u0441\u0456 MainWindow.menu.transfers.stopalltransfers=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 &\u0432\u0441\u0456 MainWindow.menu.transfers.pausetransfers=&\u041f\u0430\u0443\u0437\u0430 MainWindow.menu.transfers.resumetransfers=&\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 ConfigView.label.experimental.osx.kernel.panic.fix=\u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0430 \u043b\u0430\u0442\u043a\u0430 \u0434\u043b\u044f \u0432\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u043f\u043e\u043c\u0438\u043b\u043a\u0438 kernel panics \u043d\u0430 \u0434\u0432\u043e\u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u043d\u0438\u0445 \u043c\u0430\u0448\u0438\u043d\u0430\u0445 \u0437 Mac OS X [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443] SystemTray.menu.pausetransfers=\u041f\u0440\u0438\u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 SystemTray.menu.resumetransfers=\u041e\u043d\u043e\u0432\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 ConfigView.section.file.truncate.too.large=\u0420\u043e\u0437\u0440\u0456\u0437\u0430\u0442\u0438 \u043d\u0430\u0434\u0442\u043e \u0432\u0435\u043b\u0438\u043a\u0456 \u0444\u0430\u0439\u043b\u0438 \u043d\u0430 \u043c\u0435\u043d\u0448\u0456 ConfigView.section.file.perf.cache.trace=\u041f\u0440\u043e\u0441\u0442\u0435\u0436\u0443\u0432\u0430\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u043a\u0435\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0437 \u043c\u0435\u0442\u043e\u044e \u0434\u0456\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438 ConfigView.section.interface.enabletray=\u0412\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c\u0443 \u0442\u0440\u0435\u0457 [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443] PeerManager.status.error=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 Stats.title.full=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 TransferStatsView.title.full=\u041f\u0435\u0440\u0435\u0434\u0430\u043d\u043e CacheView.title.full=\u041a\u0435\u0448 CacheView.general.size=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440 CacheView.general.inUse=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f CacheView.general.title=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u043f\u0440\u043e \u043a\u0435\u0448 CacheView.reads.title=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044f-\u0432\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044f: \u0437\u0447\u0438\u0442\u0443\u0432\u0430\u043d\u044c CacheView.reads.fromFile=\u0417 \u0444\u0430\u0439\u043b\u0443 CacheView.reads.fromCache=\u0417 \u043a\u0435\u0448\u0443 CacheView.reads.hits=\u0417\u0432\u0435\u0440\u0442\u0430\u043d\u044c CacheView.writes.title=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044f-\u0432\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044f: \u0437\u0430\u043f\u0438\u0441\u0456\u0432 CacheView.writes.toCache=\u0412 \u043a\u0435\u0448 CacheView.writes.toFile=\u0412 \u0444\u0430\u0439\u043b CacheView.writes.hits=\u0417\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0445 CacheView.speeds.title=\u0428\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0434\u0430\u043d\u0438\u0445 CacheView.speeds.reads=\u0427\u0438\u0442\u0430\u043d\u043d\u044f CacheView.speeds.writes=\u0417\u0430\u043f\u0438\u0441 CacheView.speeds.fromCache=\u0417 \u043a\u0435\u0448\u0443 \u0456 \u0432 \u043a\u0435\u0448 CacheView.speeds.fromFile=\u0417 \u0444\u0430\u0439\u043b\u0443 \u0456 \u0432 \u0444\u0430\u0439\u043b CacheView.reads.amount=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c CacheView.reads.avgsize=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 \u0440\u043e\u0437\u043c\u0456\u0440 openUrl.referrer=\u0410\u0434\u0440\u0435\u0441\u0430 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438, \u044f\u043a\u0430 \u043f\u043e\u0441\u0438\u043b\u0430\u0454\u0442\u044c\u0441\u044f: openUrl.referrer.info=\u041f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u043b\u0438\u0448\u0435 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u0456\u0432, \u044f\u043a\u0456 \u043e\u0442\u0440\u0438\u043c\u0430\u043b\u0438 \u0457\u0457 ConfigView.label.maxuploadspeedseeding=\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u043f\u0440\u0438 \u043b\u0438\u0448\u0435 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 ConfigView.label.transfer.ignorepeerports=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438 \u0437 \u0446\u0438\u043c\u0438 \u043f\u043e\u0440\u0442\u0430\u043c\u0438 (\u0440\u043e\u0437\u0434\u0456\u043b\u044f\u0442\u0438 ';', \u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434 0;25) ConfigView.section.proxy.enable_socks.peer=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0440\u043e\u043a\u0441\u0456\u043c\u0430\u0446\u0456\u044e \u0434\u043b\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 (\u043b\u0438\u0448\u0435 \u0432\u0438\u0445\u0456\u0434\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f) [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443] ConfigView.section.proxy.peer.informtracker=\u0406\u043d\u0444\u043e\u0440\u043c\u0443\u0432\u0430\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 \u043f\u0440\u043e \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f ConfigView.section.proxy.socks.version=\u0412\u0435\u0440\u0441\u0456\u044f SOCKS PiecesView.legend.written=\u0417\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0439 PiecesView.legend.requested=\u0417\u0430\u043f\u0438\u0442\u0430\u043d\u0438\u0439 PiecesView.legend.downloaded=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0435, \u0437\u0430\u043f\u0438\u0441\u0443\u0454\u0442\u044c\u0441\u044f PiecesView.legend.incache=\u0414\u0430\u043d\u0438\u0445 \u0443 \u043a\u0435\u0448\u0456 PiecesView.typeItem.0=\u041f\u043e\u0432\u0456\u043b\u044c\u043d\u0438\u0439 PiecesView.typeItem.1=\u0428\u0432\u0438\u0434\u043a\u0438\u0439 PiecesView.type=\u0422\u0438\u043f Security.jar.tools_not_found=\u041f\u0456\u0434\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f JAR \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f - \u0444\u0430\u0439\u043b 'tools.jar' \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439 \u0432 %1. \u0414\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u0421\u0435\u0440\u0432\u0456\u0441->\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f->\u0411\u0435\u0437\u043f\u0435\u043a\u0430 \u0434\u043b\u044f \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457. Security.jar.signfail=\u041f\u0456\u0434\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f JAR \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f - %1 ConfigView.section.security.toolsinfo=\u041f\u0456\u0434\u043f\u0438\u0441\u0430\u043d\u0456 JAR-\u0444\u0430\u0439\u043b\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0434\u0435\u044f\u043a\u0438\u0445 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c, \u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434, \u0434\u043b\u044f \u0417\u043c\u0456\u043d\u0438 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u043c\u0435\u0440\u0435\u0436\u0456 (\u043a\u043e\u043b\u0438 \u0432\u043e\u043d\u043e \u043d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0430\u043d\u0435).\n\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0449\u043e\u0431 \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438 JAR-\u0444\u0430\u0439\u043b, \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e \u043c\u0430\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u0444\u0430\u0439\u043b\u0443 'tools.jar', \u044f\u043a\u0438\u0439 \u043f\u043e\u0448\u0438\u0440\u044e\u0454\u0442\u044c\u0441\u044f \u0437 \u043f\u0430\u043a\u0435\u0442\u043e\u043c \u0440\u043e\u0437\u0440\u043e\u0431\u043a\u0438 Sun JDK (\u043d\u0435 \u043f\u043b\u0443\u0442\u0430\u0442\u0438 \u0437 JRE).\n\u042f\u043a\u0449\u043e \u0443 \u0432\u0430\u0441 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u043b\u0438\u0448\u0435 JRE, \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c \u0449\u0435 \u0456 JDK.\nVuze \u043f\u043e\u0432\u0438\u043d\u0435\u043d \u0437\u043d\u0430\u0439\u0442\u0438 \u0446\u0435\u0439 \u0444\u0430\u0439\u043b \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0456 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e. \u041e\u0434\u043d\u0430\u043a, \u044f\u043a\u0449\u043e \u0446\u0435 \u0439\u043e\u043c\u0443 \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f, \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0440\u0443\u0447\u043d\u0443 \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u0442\u0435\u043a\u0443, \u044f\u043a\u0430 \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0438\u0439 \u0444\u0430\u0439\u043b. ConfigView.section.security.toolsdir=\u0422\u0435\u043a\u0430, \u044f\u043a\u0430 \u043c\u0456\u0441\u0442\u0438\u0442\u044c 'tools.jar' ConfigView.section.security.choosetoolssavedir=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0442\u0435\u043a\u0443, \u044f\u043a\u0430 \u043c\u0456\u0441\u0442\u0438\u0442\u044c 'tools.jar' authenticator.torrent=\u0422\u043e\u0440\u0435\u043d\u0442 ConfigView.section.proxy.peer.same=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u043e\u043a\u0441\u0456 \u0456 \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0443, \u0456 \u0434\u043b\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438 ConfigView.section.connection.network.max.simultaneous.connect.attempts=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0447\u0430\u043d\u0438\u0445 \u0432\u0438\u0445\u0456\u0434\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0432\u0438\u0445\u0456\u0434\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c, \u044f\u043a\u0456 \u0432\u0438\u043a\u043e\u043d\u0443\u044e\u0442\u044c\u0441\u044f Vuze \u0432 \u0431\u0443\u0434\u044c-\u044f\u043a\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0447\u0430\u0441\u0443.\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: Windows XP SP2 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u044e\u0454 \u0432\u043d\u0443\u0442\u0440\u0456\u0448\u043d\u0454 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u0435 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0432 10 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f - 8. \u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f 0 \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u0432\u0438\u043c\u0438\u043a\u0430\u0454 \u0432\u0438\u0445\u0456\u0434\u043d\u0438\u0439 \u0442\u0440\u0430\u0444\u0456\u043a. ConfigView.section.file.perf.cache.size.explain=\u041a\u0435\u0448 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u043d\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439 \u0437\u0447\u0438\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0437 \u0434\u0438\u0441\u043a\u0430. \u042f\u043a\u0449\u043e \u0412\u0438 \u043d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 java '-XX:MaxDirectMemorySize', \u0449\u043e\u0431 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0443 \u043f\u0430\u043c'\u044f\u0442\u044c \u0434\u043b\u044f \u043a\u0435\u0448\u0443 \u0456 \u043c\u0435\u0440\u0435\u0436\u0435\u0432\u043e\u0433\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f, \u0412\u0438 \u043c\u0430\u0454\u0442\u0435 \u0437\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0446\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u0440\u0438\u043d\u0430\u0439\u043c\u043d\u0456 \u043d\u0430 %1 \u043d\u0438\u0436\u0447\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u0432\u0456\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0457 \u043c\u0430\u0448\u0438\u043d\u0438. \u041f\u043e\u0442\u043e\u0447\u043d\u0438\u0439 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440 \u0434\u043b\u044f \u0432\u0456\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0457 \u043c\u0430\u0448\u0438\u043d\u0438 %2. \u0414\u043b\u044f \u0456\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0456\u0439, \u044f\u043a \u0437\u043c\u0456\u043d\u044e\u0432\u0430\u0442\u0438 \u0446\u0435\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u0434\u0438\u0432. MemoryUsage \u043d\u0430 Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u0446\u0456: %3. \u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0446\u0438\u0445 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u044c \u043f\u043e\u043c\u0438\u043b\u043a\u0443 '\u043d\u0430\u0434\u043b\u0438\u0448\u043a\u0443 \u043f\u0430\u043c'\u044f\u0442\u0456'. \u0414\u043e\u0441\u0442\u0430\u0442\u043d\u0456\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f\u043c \u0454 32 \u041c\u0411\u0430\u0439\u0442. MyTorrentsView.menu.setSpeed.unlimit=\u0411\u0435\u0437 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u044c MyTorrentsView.menu.setSpeed.unlimited=\u041d\u0435 \u043e\u0431\u043c\u0435\u0436\u0443\u0432\u0430\u0442\u0438 MyTorrentsView.menu.setSpeed.disable=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 MyTorrentsView.menu.setSpeed.disabled=\u0412\u0438\u043c\u043a\u043d\u0443\u0442\u043e MyTorrentsView.menu.setSpeed.in=\u0432 MyTorrentsView.menu.setSpeed.slots=\u0441\u043b\u043e\u0442\u0430\u0445 GeneralView.label.maxuploadspeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 GeneralView.label.maxuploadspeed.tooltip=, \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 [0 : \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] MyTorrents.items.UpSpeedLimit.disabled=\u041d\u0435\u043c\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 MyTorrents.items.UpSpeedLimit.unlimited=\u041d\u0435 \u043e\u0431\u043c\u0435\u0436\u0443\u0432\u0430\u0442\u0438 TableColumn.header.maxupspeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 TableColumn.header.maxupspeed.info=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 ConfigView.section.file.perf.cache.enable.write=\u041a\u0435\u0448\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0434\u0430\u043d\u0456 \u0434\u043b\u044f \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u043d\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0430 \u0434\u0438\u0441\u043a, \u0430 \u0442\u0430\u043a\u043e\u0436 \u0437\u043c\u0435\u043d\u0448\u0443\u0432\u0430\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u0447\u0438\u0442\u0430\u043d\u043d\u044f \u0437 \u0434\u0438\u0441\u043a\u0443, \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0456 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 \u0447\u0430\u0441\u0442\u0438\u043d ConfigView.section.file.perf.cache.enable.read=\u0412\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u043d\u0454 \u0447\u0438\u0442\u0430\u043d\u043d\u044f \u0434\u043b\u044f \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u043d\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439 \u0437\u0432\u0435\u0440\u0442\u0430\u043d\u044c \u0434\u043e \u0434\u0438\u0441\u043a\u0443 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 ConfigView.section.tracker.separatepeerids=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0440\u0456\u0437\u043d\u0456 \u0456\u0434\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0442\u043e\u0440\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445 ConfigView.section.tracker.separatepeerids.info=\u0417\u0431\u0456\u043b\u044c\u0448\u0443\u0454 \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0430\u0431\u043e \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \n\u043f\u0456\u0434 \u0447\u0430\u0441 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u043d\u0435 \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u043e\u0433\u043e \u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.interface.wavlocation=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 *.wav ConfigView.section.interface.wavlocation.info=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0444\u0430\u0439\u043b * .wav \u0430\u0431\u043e \u0437\u0430\u043b\u0438\u0448\u0456\u0442\u044c \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u043c \u0434\u043b\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u0437\u0432\u0443\u043a\u0443 ConfigView.section.tracker.server=\u0421\u0435\u0440\u0432\u0435\u0440 ConfigView.section.tracker.client=\u041a\u043b\u0456\u0454\u043d\u0442 ConfigView.section.tracker.client.connecttimeout=\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u0447\u0430\u0441 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f (\u0441\u0435\u043a\u0443\u043d\u0434) ConfigView.section.tracker.client.readtimeout=\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u0447\u0430\u0441 \u0447\u0438\u0442\u0430\u043d\u043d\u044f (\u0441\u0435\u043a\u0443\u043d\u0434) MainWindow.menu.tools=&\u0421\u0435\u0440\u0432\u0456\u0441 FilesView.path=\u0428\u043b\u044f\u0445 FilesView.fullpath=\u0412\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u0438 \u043f\u043e\u0432\u043d\u0438\u0439 \u0448\u043b\u044f\u0445 FilesView.remaining=\u0427\u0430\u0441\u0442\u0438\u043d\u0438, \u044f\u043a\u0456 \u0437\u0430\u043b\u0438\u0448\u0438\u043b\u0438\u0441\u044f TableColumn.header.trackername=\u041d\u0430\u0437\u0432\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 TableColumn.header.trackername.info=\u041d\u0430\u0437\u0432\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443, \u0437\u0430\u0434\u0430\u043d\u0430 \u0430\u0434\u0440\u0435\u0441\u043e\u044e ConfigView.group.override=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u043f\u0456\u0434\u043c\u0456\u043d\u0438 ConfigView.section.file.perf.cache.notsmallerthan=\u041d\u0435 \u043a\u0435\u0448\u0443\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438, \u043c\u0435\u043d\u0448\u0456 \u043d\u0456\u0436 (\u0432 %1) PeersView.menu.blockupload=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 PeersView.menu.kickandban=\u0417\u0430\u0431\u0430\u043d\u0438\u0442\u0438 PeersView.menu.kickandban.reason=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u044f\u0442\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0432\u0440\u0443\u0447\u043d\u0443 PeersView.state=\u0421\u0442\u0430\u043d PeersView.state.info=\u0421\u0442\u0430\u043d \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 PeersView.state.pending=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f PeersView.state.connecting=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f PeersView.state.handshake=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0432'\u044f\u0437\u043a\u0443 PeersView.state.established=\u041f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u0437'\u0454\u0434\u043d\u0430\u043d\u0438\u0439 ConfigView.section.tracker.processinglimits=\u041e\u0431\u0440\u043e\u0431\u043a\u0430 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u044c ConfigView.section.tracker.maxgettime=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0447\u0430\u0441 \u043e\u0431\u0440\u043e\u0431\u043a\u0438 \u0437\u0430\u043f\u0438\u0442\u0443 GET (\u0441\u0435\u043a\u0443\u043d\u0434) [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439] ConfigView.section.tracker.maxgettime.info=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0430\u043d\u043e\u043d\u0441\u0456\u0432 \u0456 \u0437\u0430\u043f\u0438\u0442\u0456\u0432 \u0441\u0445\u043e\u0432\u0438\u0449 ConfigView.section.tracker.maxposttimemultiplier=\u041c\u043d\u043e\u0436\u043d\u0438\u043a \u0447\u0430\u0441\u0443 \u0437\u0430\u043f\u0438\u0442\u0456\u0432 GET \u0434\u043b\u044f \u043e\u0431\u0440\u043e\u0431\u043a\u0438 \u0437\u0430\u043f\u0438\u0442\u0456\u0432 POST [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439] ConfigView.section.tracker.maxposttimemultiplier.info=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u043e\u0431\u043a\u0438 \u0444\u043e\u0440\u043c \u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 ConfigView.section.tracker.maxthreads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u0438\u0445 \u0437\u0430\u043f\u0438\u0442\u0456\u0432 DownloadManager.error.operationcancancelled=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u044f \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0430 Torrent.create.progress.cancelled=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u044f \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0430 sharing.progress.cancel=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 wizard.maketorrents.autoopen=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f ConfigView.section.sharing.rescanenable=\u0414\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 \u043f\u0435\u0440\u0456\u043e\u0434\u0438\u0447\u043d\u0443 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0443 \u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447 \u0449\u043e\u0434\u043e \u043c\u043e\u0436\u043b\u0438\u0432\u0438\u0445 \u0437\u043c\u0456\u043d ConfigView.section.sharing.rescanperiod=\u0427\u0430\u0441\u043e\u0432\u0438\u0439 \u043f\u0440\u043e\u043c\u0456\u0436\u043e\u043a \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0457 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 (\u0441\u0435\u043a\u0443\u043d\u0434) ConfigView.section.connection.advanced=\u0414\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u0456 \u043c\u0435\u0440\u0435\u0436\u0435\u0432\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f ConfigView.section.connection.advanced.mtu=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043e\u0434\u0438\u043d\u0438\u0446\u044f \u0432\u0438\u043c\u0456\u0440\u0443 \u043b\u0456\u043d\u0456\u0457 (MTU) ConfigView.section.connection.advanced.mtu.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440 \u043f\u0430\u043a\u0435\u0442\u0430, \u044f\u043a\u0438\u0439 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u0438\u0439 \u0432 \u043e\u0434\u043d\u043e\u043c\u0443 \u043a\u0430\u0434\u0440\u0456 \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0440\u0435\u0436\u0443.\nVuze \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454 MTU-40 (MSS) \u0434\u043b\u044f \u043f\u0430\u043a\u0435\u0442\u0456\u0432 \u043d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0443.\n\u0411\u0430\u0436\u0430\u043d\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f:\n 576 - \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043c\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c\n1492 - \u0437'\u0454\u0434\u043d\u0430\u043d\u044c PPPo \n1500 - Ethernet, DSL \u0456 \u0448\u0438\u0440\u043e\u043a\u043e\u0433\u043e \u043a\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f ConfigView.section.connection.advanced.SO_RCVBUF=\u0420\u043e\u0437\u043c\u0456\u0440 \u0441\u043e\u043a\u0435\u0442\u0430 SO_RCVBUF [0: \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u041e\u0421] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=\u041d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0443\u0454 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f SO_RCVBUF (\u0432 \u0431\u0430\u0439\u0442\u0430\u0445), \u0442\u043e\u0431\u0442\u043e TCP \u043e\u0442\u0440\u0438\u043c\u0443\u0454 \u0440\u043e\u0437\u043c\u0456\u0440 \u0432\u0456\u043a\u043d\u0430.\nVuze \u0437\u0430\u043b\u0438\u0448\u0430\u0454 \u0446\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043d\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0430\u043d\u0438\u043c, \u0449\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0430\u0441\u0442\u043e\u0441\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438.\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: Linux \u043f\u043e\u0434\u0432\u043e\u044e\u0454 \u0432\u043a\u0430\u0437\u0430\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f. ConfigView.section.connection.advanced.SO_SNDBUF=\u0420\u043e\u0437\u043c\u0456\u0440 \u0441\u043e\u043a\u0435\u0442\u0430 SO_SNDBUF [0: \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u041e\u0421] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=\u041d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0443\u0454 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f SO_SNDBUF (\u0432 \u0431\u0430\u0439\u0442\u0430\u0445), \u0442\u043e\u0431\u0442\u043e TCP \u0432\u0456\u0434\u0441\u0438\u043b\u0430\u0454 \u0440\u043e\u0437\u043c\u0456\u0440 \u0432\u0456\u043a\u043d\u0430.\nVuze \u0437\u0430\u043b\u0438\u0448\u0430\u0454 \u0446\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043d\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0430\u043d\u0438\u043c, \u0449\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0430\u0441\u0442\u043e\u0441\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438.\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: Linux \u043f\u043e\u0434\u0432\u043e\u044e\u0454 \u0432\u043a\u0430\u0437\u0430\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f. ConfigView.section.connection.advanced.IPDiffServ=\u041d\u0435\u0437\u0432\u0438\u0447\u043d\u0435 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u0430\u043a\u0435\u0442\u0443, \u044f\u043a\u0438\u0439 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u044f\u0454\u0442\u044c\u0441\u044f (\u043f\u043e\u043b\u0435 TOS) ConfigView.section.connection.advanced.IPDiffServ.tooltip=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u044e\u0454 \u043d\u0435\u0437\u0432\u0438\u0447\u043d\u0456\u0439 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0447\u0430\u0441\u0442\u0438\u043d\u0456 \u043f\u043e\u043b\u0435 \u0442\u0438\u043f\u0443 \u0441\u0435\u0440\u0432\u0456\u0441\u0443 (TOS) \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0443 IP \u043f\u0430\u043a\u0435\u0442\u0456\u0432, \u044f\u043a\u0456 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u044c\u0441\u044f.\n\u0428\u0456\u0441\u0442\u043d\u0430\u0434\u0446\u044f\u0442\u0438\u0437\u043d\u0430\u0447\u043d\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043c\u043e\u0436\u0443\u0442\u044c \u0431\u0443\u0442\u0438 \u0432\u043a\u0430\u0437\u0430\u043d \u0437 \u043f\u0440\u0435\u0444\u0456\u043a\u0441\u043e\u043c '0x', \u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434 0x10.\nVuze \u0437\u0430\u043b\u0438\u0448\u0430\u0454 \u0446\u0456 \u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f, \u0432\u043a\u0430\u0437\u0443\u044e\u0447\u0438, \u0449\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0457 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438.\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u041e\u0441\u043d\u043e\u0432\u043d\u0456 \u043c\u0435\u0440\u0435\u0436\u0456 \u043c\u043e\u0436\u0443\u0442\u044c \u0437\u043d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0446\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f\u043c, \u0430\u043b\u0435 \u0446\u0435\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0432\u0430\u0436\u043b\u0438\u0432\u0438\u0439 \u0432 \u0437\u0430\u043b\u0435\u0436\u043d\u043e\u0441\u0442\u0456 \u0432\u0456\u0434 \u0432\u0435\u0440\u0441\u0456\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438 \u0456 JRE. ConfigView.section.interface.confirm_torrent_removal=\u0417\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 \u043f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 ConfigView.section.interface.confirm_torrent_removal.tooltip=\u0417\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 \u043f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0437 "\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438" MyTorrentsView.confirm_torrent_removal=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438?\n TableColumn.header.seed_to_peer_ratio=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0434\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 TableColumn.header.seed_to_peer_ratio.info=\u041f\u0456\u0434\u0441\u0443\u043c\u043a\u043e\u0432\u0435 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0434\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 PeersView.connected_time=\u0427\u0430\u0441 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f PeersView.connected_time.info=\u041f\u0456\u0434\u0441\u0443\u043c\u043a\u043e\u0432\u0438\u0439 \u0447\u0430\u0441 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c ConfigView.section.interface.display.add_torrents_silently=\u0414\u043e\u0434\u0430\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043d\u0430 \u0442\u043b\u0456 ConfigView.section.interface.display.add_torrents_silently.tooltip=\u0414\u043e\u0434\u0430\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432 \u0437\u0430\u0432\u0434\u0430\u043d\u043d\u044f \u0431\u0435\u0437 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0456\u0457 \u0433\u043e\u043b\u043e\u0432\u043d\u043e\u0433\u043e \u0432\u0456\u043a\u043d\u0430 Vuze. TableColumn.header.maxdownspeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f TableColumn.header.maxdownspeed.info=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0446\u044c\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 PeersGraphicView.title=\u041e\u0442\u043e\u0447\u0435\u043d\u043d\u044f ConfigView.section.tracker.passwordwebhttpsonly=\u0414\u043e\u0437\u0432\u043e\u043b\u044f\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u043b\u0438\u0448\u0435 \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u0445\u0438\u0449\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b HTTPS TableColumn.header.torrentpath=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 TableColumn.header.torrentpath.info=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u043d\u0430 \u0434\u0438\u0441\u043a\u0443 ConfigView.section.sharing.torrentcomment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0434\u043b\u044f \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 ConfigView.label.copyanddeleteratherthanmove=\u0421\u043a\u043e\u043f\u0456\u044e\u0439\u0442\u0435, \u0430 \u043f\u043e\u0442\u0456\u043c \u0432\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0434\u0430\u043d\u0456 \u0437\u0430\u043c\u0456\u0441\u0442\u044c \u0442\u043e\u0433\u043e, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u043c\u0456\u0449\u0443\u0432\u0430\u0442\u0438 \u0437\u0430 \u043e\u0434\u043d\u0443 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u044e - \u0446\u0435 \u0434\u043e\u043f\u043e\u043c\u043e\u0436\u0435 \u0437\u0430\u043f\u043e\u0431\u0456\u0433\u0442\u0438 \u0432\u0442\u0440\u0430\u0442\u0456 \u0434\u0430\u043d\u0438\u0445 \u0443 \u0434\u0435\u044f\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 ConfigView.label.openstatsonstart=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 swt.install.window.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f Vuze swt.install.window.ok=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 swt.install.window.header=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0456 \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f: swt.uninstall.window.title=\u0412\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c Vuze swt.uninstall.window.ok=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 swt.uninstall.window.header=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0456 \u0434\u043b\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f : installPluginsWizard.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c installPluginsWizard.mode.title=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0441\u043f\u043e\u0441\u0456\u0431 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f installPluginsWizard.mode.list=\u0417 \u0441\u043f\u0438\u0441\u043a\u0443 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c \u0441\u0430\u0439\u0442\u0443 sourceforge.net installPluginsWizard.list.title=\u0421\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c, \u0433\u043e\u0442\u043e\u0432\u0438\u0445 \u0434\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f installPluginsWizard.list.loading=\u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u043f\u043e\u043a\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u044e\u0454\u0442\u044c\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c. installPluginsWizard.list.loaded=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f, \u044f\u043a\u0435 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438. installPluginsWizard.list.name=\u041d\u0430\u0437\u0432\u0430 installPluginsWizard.list.version=\u0412\u0435\u0440\u0441\u0456\u044f installPluginsWizard.list.description=\u041e\u043f\u0438\u0441 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f installPluginsWizard.finish.title=\u0422\u0440\u0438\u0432\u0430\u0454 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f installPluginsWizard.finish.explanation=\u0412\u0438\u0431\u0440\u0430\u043d\u0456 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0431\u0443\u0434\u0443\u0442\u044c \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0456 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u041c\u0430\u0439\u0441\u0442\u0440\u0430 \u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c\n\n\u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u043f\u043e\u043a\u0438 \u0432\u0456\u043d \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u044c\u0441\u044f\n\n\u0414\u043b\u044f \u0432\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0456\u043d\u0441\u0442\u0430\u043b\u044f\u0446\u0456\u0457, \u0434\u0432\u0456\u0447\u0456 \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043b\u0456\u0432\u043e\u044e \u043f\u043e\n\u0440\u044f\u0434\u043a\u0443 \u0441\u0442\u0430\u043d\u0443. installPluginsWizard.details.loading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u044e\u0442\u044c\u0441\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0437\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435... installPluginsWizard.mode.file=\u0412 \u0432\u0430\u0441 \u0432\u0436\u0435 \u0454 \u0444\u0430\u0439\u043b \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f installPluginsWizard.installMode.title=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0441\u043f\u043e\u0441\u0456\u0431 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f installPluginsWizard.installMode.user=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043b\u0438\u0448\u0435 \u0434\u043b\u044f \u0412\u0430\u0441 installPluginsWizard.installMode.shared=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043b\u044f \u0432\u0441\u0456\u0445 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 installPluginsWizard.file.title=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f, \u044f\u043a\u0435 \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 installPluginsWizard.file.file=\u0424\u0430\u0439\u043b : installPluginsWizard.file.invalidfile=\u0426\u0435\u0439 \u0444\u0430\u0439\u043b \u043d\u0435 \u0454 \u0444\u0430\u0439\u043b\u043e\u043c \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f Vuze. installPluginsWizard.file.no_such_file=\u041d\u0435 \u0456\u0441\u043d\u0443\u0454 \u043d\u0456\u044f\u043a\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0443 \u0437 \u0442\u0430\u043a\u0438\u043c \u0456\u043c'\u044f\u043c. installPluginsWizard.file.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434... uninstallPluginsWizard.title=\u0412\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c uninstallPluginsWizard.list.title=\u0421\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0445 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c uninstallPluginsWizard.list.loaded=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f, \u044f\u043a\u0435 \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438. installPluginsWizard.list.nullversion=\u0412\u0435\u0440\u0441\u0456\u044f \u043d\u0435 \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 uninstallPluginsWizard.finish.title=\u0422\u0440\u0438\u0432\u0430\u0454 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f uninstallPluginsWizard.finish.explanation=\u0412\u0438\u0431\u0440\u0430\u043d\u0456 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0431\u0443\u0434\u0443\u0442\u044c \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u0456 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u041c\u0430\u0439\u0441\u0442\u0440\u0430 \u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c. MainWindow.menu.plugins.installPlugins=\u041c\u0430\u0439\u0441\u0442\u0435\u0440 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f... MainWindow.menu.plugins.uninstallPlugins=\u041c\u0430\u0439\u0441\u0442\u0435\u0440 \u0434\u0435\u0456\u043d\u0441\u0442\u0430\u043b\u044f\u0446\u0456\u0457... ConfigView.section.ipfilter.totalIPs=\u0412\u0441\u044c\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u043e %1 IP, \u0437 \u044f\u043a\u0438\u0445 %2 \u0437 \u0406\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0443. update.instance.install=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f update.instance.uninstall=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 update.instance.update=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c MainWindow.status.update.tooltip=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u0434\u0432\u0456\u0447\u0456 \u043b\u0456\u0432\u043e\u044e \u0434\u043b\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u043f\u0440\u043e \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u044e updater.progress.window.title=\u0417\u0430\u0432\u0434\u0430\u043d\u043d\u044f \u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0433\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f updater.progress.window.info=\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c '\u041f\u0435\u0440\u0435\u0440\u0432\u0430\u0442\u0438' \u0434\u043b\u044f \u043f\u0440\u0438\u043f\u0438\u043d\u0435\u043d\u043d\u044f \u0432\u0441\u0456\u0445 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0438\u0445 \u0437\u0430\u0432\u0434\u0430\u043d\u044c Button.abort=\u041f\u0435\u0440\u0435\u0440\u0432\u0430\u0442\u0438 ConfigView.section.ipfilter.enablebanning=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u044f\u043a\u0456 \u043f\u043e\u0441\u0442\u0456\u0439\u043d\u043e \u043d\u0430\u0434\u0441\u0438\u043b\u0430\u044e\u0442\u044c \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0456 \u0434\u0430\u043d\u0456 Network.alert.acceptfail=\u0417\u0430\u043d\u0430\u0434\u0442\u043e \u0431\u0430\u0433\u0430\u0442\u043e \u043d\u0435\u0432\u0434\u0430\u043b\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c \u0437\u0430 \u043f\u043e\u0440\u0442\u043e\u043c %1, %2 - \u043e\u0431\u0440\u043e\u0431\u043a\u0430 \u043f\u0440\u0438\u043f\u0438\u043d\u0435\u043d\u0430. \u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0433\u043e \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u0430 \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0443, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0442\u0438\u0441\u044f \u0449\u043e \u0432\u0456\u043d \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u044c. MyShares.column.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044f UpdateWindow.restartLater=\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0437\u0433\u043e\u0434\u043e\u043c MainWindow.menu.file.restart=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0437\u043d\u043e\u0432\u0443 Vuze MainWindow.dialog.restartconfirmation.title=\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 Vuze MainWindow.dialog.restartconfirmation.text=\u0412\u0438 \u0434\u0456\u0439\u0441\u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0437\u043d\u043e\u0432\u0443 Vuze deletetorrent.message1=\u0412\u0438 \u0437\u0431\u0438\u0440\u0430\u0454\u0442\u0435\u0441\u044f \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0422\u041e\u0420\u0415\u041d\u0422 \u0434\u043b\u044f :\n deletetorrent.message2=\n\u0412\u0438 \u0434\u0456\u0439\u0441\u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0438\u0442\u0438? ConfigView.label.prioritizemostcompletedfiles=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0432 \u0437\u0430\u043b\u0435\u0436\u043d\u043e\u0441\u0442\u0456 \u0432\u0456\u0434 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 (\u0432 % \u0430\u0431\u043e \u0432\u0456\u0434 \u0440\u043e\u0437\u043c\u0456\u0440\u0443) splash.plugin.init=\u0417\u0430\u043f\u0443\u0441\u043a \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f: splash.plugin.UIinit=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u0432\u0438\u0433\u043b\u044f\u0434\u0443 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f: %1 ConfigView.section.style.osx_small_fonts=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0434\u0440\u0456\u0431\u043d\u0456 \u0448\u0440\u0438\u0444\u0442\u0438 [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443] ConfigView.section.tracker.tcpnonblocking=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044f-\u0432\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044f, \u044f\u043a\u0435 \u043d\u0435 \u0431\u043b\u043e\u043a\u0443\u0454\u0442\u044c\u0441\u044f, \u0434\u043b\u044f \u0440\u043e\u0431\u043e\u0442\u0438 TCP-\u0442\u0440\u0435\u043a\u0435\u0440\u0443. \u0412\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0446\u044c\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0432\u0438\u043c\u0430\u0433\u0430\u0454, \u0449\u043e\u0431 \u0442\u0440\u0435\u043a\u0435\u0440-\u0441\u0430\u0439\u0442 \u0431\u0443\u0432 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 \u0456\u043d\u0448\u0438\u0439 \u043f\u043e\u0440\u0442. \u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0430 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c! ConfigView.section.tracker.nonblocking=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438, \u044f\u043a\u0456 \u043d\u0435 \u0431\u043b\u043e\u043a\u0443\u044e\u0442\u044c\u0441\u044f ConfigView.section.tracker.nonblockingconcmax=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] MyTorrentsView.menu.exportmenu=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 MyTorrentsView.menu.exporttorrent=\u0422\u043e\u0440\u0435\u043d\u0442... ConfigView.group.scrape=\u0421\u0445\u043e\u0432\u0438\u0449\u0435 ConfigView.section.tracker.client.scrapeinfo=\u0412\u0438\u043c\u0438\u043a\u0430\u043d\u043d\u044f \u0441\u0445\u043e\u0432\u0438\u0449\u0430 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u044c \u0432\u0456\u0434\u043c\u043e\u0432\u0443 \u0431\u0430\u0433\u0430\u0442\u044c\u043e\u0445 \u043f\u0440\u0430\u0432\u0438\u043b \u043e\u0431\u0441\u043b\u0443\u0433\u043e\u0432\u0443\u0432\u0430\u043d\u043d\u044f \u0447\u0435\u0440\u0433\u0438, \u0442\u043e\u043c\u0443 \u0449\u043e \u0432\u043e\u043d\u0438 \u043f\u043e\u043a\u043b\u0430\u0434\u0430\u044e\u0442\u044c\u0441\u044f \u043d\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f, \u044f\u043a\u0430 \u0437\u0431\u0435\u0440\u0456\u0433\u0430\u0454\u0442\u044c\u0441\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438-\u0441\u0445\u043e\u0432\u0438\u0449\u0430\u043c\u0438. ConfigView.section.tracker.client.scrapeenable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0441\u0445\u043e\u0432\u0438\u0449\u0435 ConfigView.section.tracker.client.scrapestoppedenable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0441\u0445\u043e\u0432\u0438\u0449\u0435 \u0434\u043b\u044f \u043d\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 Scrape.status.disabled=\u0421\u0445\u043e\u0432\u0438\u0449\u0435 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0435 MyTorrentsView.menu.explore=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b MyTorrentsView.menu.explore._mac=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0432 \u043f\u043e\u0448\u0443\u043a\u0443 MyTorrentsView.menu.explore._windows=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0432 \u043f\u0440\u043e\u0432\u0456\u0434\u043d\u0438\u043a\u0443 Windows wizard.maketorrents.autohost=\u041d\u0430\u0434\u0430\u0442\u0438 \u0445\u043e\u0441\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u043d\u0430 \u0432\u0431\u0443\u0434\u043e\u0432\u0430\u043d\u043e\u043c\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0456 ConfigView.label.overrideip=\u041f\u0456\u0434\u043c\u0456\u043d\u0438\u0442\u0438 \u0430\u043d\u043e\u043d\u0441\u043e\u0432\u0430\u043d\u0438\u0439 IP \u0442\u0440\u0435\u043a\u0435\u0440\u0430. \u0420\u043e\u0437\u0434\u0456\u043b\u044f\u0442\u0438 \u043a\u043e\u043c\u0430\u043c\u0438 \u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u044f\u043a\u0449\u043e \u0457\u0445 \u043a\u0456\u043b\u044c\u043a\u0430 \u0434\u043b\u044f \u0440\u0456\u0437\u043d\u0438\u0445 \u043c\u0435\u0440\u0435\u0436 ConfigView.label.overrideip.tooltip=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u043f\u0440\u043e \u0440\u0456\u0437\u043d\u0456 IP-\u0430\u0434\u0440\u0435\u0441\u0438, \u0432\u0456\u0434 \u044f\u043a\u0438\u0445 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442\u044c \u0432\u0438\u0445\u0456\u0434\u043d\u0456 \u043f\u0430\u043a\u0435\u0442\u0438. \u0417\u0430\u043b\u0438\u0448\u0456\u0442\u044c \u043f\u043e\u043b\u0435 \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u043c, \u0449\u043e\u0431 \u043d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0446\u044e \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c. ConfigView.section.connection.group.networks=\u041c\u0435\u0440\u0435\u0436\u0456 ConfigView.section.connection.group.networks.info=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u0438\u043f\u0438 \u043c\u0435\u0440\u0435\u0436\u0435\u0432\u0438\u0445 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0456\u0432, \u044f\u043a\u0456 \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0434\u0430\u043d\u0438\u0445 ConfigView.section.connection.networks.prompt=\u0417\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0438 \u0434\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u0456 \u0437\u0430\u0432\u0434\u0430\u043d\u043d\u044f \u0437 \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u0438\u043c \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u043c ConfigView.section.connection.networks.Public=\u041f\u0443\u0431\u043b\u0456\u0447\u043d\u0430 IP-\u043c\u0435\u0440\u0435\u0436\u0430 (\u0430\u043d\u043e\u043d\u0456\u043c\u043d\u0456\u0441\u0442\u044c \u043d\u0435 \u0434\u043e\u0442\u0440\u0438\u043c\u0443\u0454\u0442\u044c\u0441\u044f) ConfigView.section.connection.networks.I2P=\u0410\u043d\u043e\u043d\u0456\u043c\u043d\u0430 \u043c\u0435\u0440\u0435\u0436\u0430 I2P ConfigView.section.connection.networks.Tor=\u0410\u043d\u043e\u043d\u0456\u043c\u043d\u0430 \u043c\u0435\u0440\u0435\u0436\u0430 The Onion Router (Tor) TableColumn.header.networks=\u041c\u0435\u0440\u0435\u0436\u0456 TableColumn.header.networks.info=\u041c\u0435\u0440\u0435\u0436\u0456, \u0434\u043e\u0437\u0432\u043e\u043b\u0435\u043d\u0456 \u0434\u043b\u044f \u043e\u0431\u043c\u0456\u043d\u0443 \u0434\u0430\u043d\u0438\u043c\u0438 \u0442\u0438\u043f\u0443 \u0443\u0447\u0430\u0441\u043d\u0438\u043a-\u0443\u0447\u0430\u0441\u043d\u0438\u043a Scrape.status.networkdisabled=\u041c\u0435\u0440\u0435\u0436\u0430 \u043d\u0435 \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0430 ConfigView.section.tracker.server.group.networks=\u041c\u0435\u0440\u0435\u0436\u0456 ConfigView.section.tracker.server.group.networks.info=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043c\u0435\u0440\u0435\u0436\u0456, \u0432 \u044f\u043a\u0438\u0445 \u0442\u0440\u0435\u043a\u0435\u0440 \u0431\u0443\u0434\u0435 \u043f\u0440\u0438\u0439\u043c\u0430\u0442\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 window.networkselection.title=\u0412\u0438\u0431\u0456\u0440 \u043c\u0435\u0440\u0435\u0436\u0456 window.networkselection.info=\u0422\u043e\u0440\u0435\u043d\u0442, \u043d\u0430\u044f\u0432\u043d\u0438\u0439 \u0432 \u0441\u043f\u0438\u0441\u043a\u0443, \u0432\u043e\u043b\u043e\u0434\u0456\u0454 \u043e\u0434\u043d\u0438\u043c \u0430\u0431\u043e \u0434\u0435\u043a\u0456\u043b\u044c\u043a\u043e\u043c\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438, \u044f\u043a\u0456 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u044e\u0442\u044c \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043c\u0435\u0440\u0435\u0436\u0456.\n\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043e\u0434\u043d\u0443 \u0434\u043b\u044f \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u0456 \u0441\u043f\u0456\u043b\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430.\n\u042f\u043a\u0449\u043e \u0442\u0440\u0435\u043a\u0435\u0440 \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u0438\u0439, \u043a\u043e\u0442\u0440\u0438\u0439 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u043f\u0443\u0431\u043b\u0456\u0447\u043d\u0438\u0445 \u043a\u043b\u0456\u0454\u043d\u0442\u0456\u0432 \u0456 \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u0456 \u043c\u0435\u0440\u0435\u0436\u0456,\n\u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u043f\u0443\u0431\u043b\u0456\u0447\u043d\u043e\u0457 \u043c\u0435\u0440\u0435\u0436\u0456 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u044c \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u043e\u0441\u0442\u0456! window.networkselection.description=\u0422\u043e\u0440\u0435\u043d\u0442 : plugins.basicview.clear=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 ConfigView.section.connection.group.peersources=\u0421\u043f\u043e\u0436\u0438\u0432\u0447\u0456 \u0434\u0436\u0435\u0440\u0435\u043b\u0430 ConfigView.section.connection.group.peersources.info=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u0434\u0436\u0435\u0440\u0435\u043b\u043e \u0434\u043b\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 ConfigView.section.connection.peersource.Tracker=\u0412\u0456\u0434 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.connection.peersource.DHT=\u0414\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0456\u043d\u0433 ConfigView.section.connection.peersource.PeerExchange=\u041d\u0430\u0434\u0430\u043d\u0438\u0439 \u0456\u043d\u0448\u0438\u043c \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0435\u043c ConfigView.section.connection.peersource.Plugin=\u0414\u043e\u0434\u0430\u043d\u0438\u0439 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f ConfigView.section.connection.peersource.Incoming=\u0412\u0445\u0456\u0434\u043d\u0435 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f PeersView.source=\u0414\u0436\u0435\u0440\u0435\u043b\u043e PeersView.source.info=\u0414\u0436\u0435\u0440\u0435\u043b\u043e \u0446\u044c\u043e\u0433\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 TableColumn.header.peersources=\u0421\u043f\u043e\u0436\u0438\u0432\u0447\u0456 \u0434\u0436\u0435\u0440\u0435\u043b\u0430 TableColumn.header.peersources.info=\u0421\u043f\u043e\u0436\u0438\u0432\u0447\u0456 \u0434\u0436\u0435\u0440\u0435\u043b\u0430, \u0434\u043e\u0437\u0432\u043e\u043b\u0435\u043d\u0456 \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c wizard.tracker.dht=\u0414\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 (\u043b\u0438\u0448\u0435 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u043a\u043b\u0456\u0454\u043d\u0442\u0430 Vuze) MyTorrentsView.menu.advancedmenu=\u0414\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e MyTorrentsView.menu.networks=\u041c\u0435\u0440\u0435\u0436\u0456 MyTorrentsView.menu.peersource=\u0414\u0436\u0435\u0440\u0435\u043b\u0430 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 ConfigView.section.sharing.permitdht=\u0414\u043e\u0437\u0432\u043e\u043b\u044f\u0442\u0438 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0456\u043d\u0433, \u043a\u043e\u043b\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 ConfigView.section.sharing.protocol=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0434\u043b\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u0456\u0432 \u043d\u0430 \u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0456\u0439 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 PeersView.Messaging=\u041e\u0431\u043c\u0456\u043d \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f\u043c\u0438 PeersView.Messaging.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0454 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043e\u0431\u043c\u0456\u043d\u0443 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f\u043c\u0438. ConfigView.label.queue.newseedsmovetop=\u041f\u0435\u0440\u0435\u043c\u0456\u0449\u0443\u0432\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u0449\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0434\u043e\u0433\u043e\u0440\u0438 \u0441\u043f\u0438\u0441\u043a\u0443 \u0441\u0456\u0434\u0435\u0440\u0456\u0432 ConfigView.label.seeding.firstPriority.ignore.info=\u041f\u0430\u043c\u2019\u044f\u0442\u0430\u0439\u0442\u0435, \u0449\u043e \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0446\u0438\u0445 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c \u043c\u043e\u0436\u0435 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u0438 \u0437\u0443\u043f\u0438\u043d\u043a\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0430,\n\u044f\u043a \u043b\u0438\u0448\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0442\u044c\u0441\u044f. ConfigView.label.seeding.firstPriority.ignore=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u0441\u043e\u043a\u0438\u043c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0434\u043b\u044f: ConfigView.label.seeding.firstPriority.ignoreSPRatio=\u0422\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437\u0456 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f\u043c \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0434\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0432\u0438\u0449\u0435 ConfigView.label.seeding.firstPriority.ignore0Peer=\u0422\u043e\u0440\u0435\u043d\u0442\u0456\u0432, \u044f\u043a\u0456 \u043d\u0435 \u043c\u0430\u044e\u0442\u044c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 ConfigView.section.tracker.sendjavaversionandos=\u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u0432\u0435\u0440\u0441\u0456\u0457 Java \u0456 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438 MagnetPlugin.contextmenu.exporturi=\u0421\u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 Magnet URI \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443 ConfigView.section.plugins.dht=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0411\u0414 dht.info=\u0426\u0435 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0456\u043d\u0433 - \u0439\u043e\u0433\u043e \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0437\u043c\u0435\u043d\u0448\u0438\u0442\u044c \u0432\u0430\u0448\u0456 \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f dht.enabled=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0443 \u0411\u0414 dht.portdefault=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 \u043f\u043e\u0440\u0442 dht.port=\u041f\u043e\u0440\u0442 UDP \u0434\u043b\u044f \u0411\u0414 dht.execute.command=\u0414\u0456\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u043d\u0456 \u043a\u043e\u043c\u0430\u043d\u0434\u0438 dht.execute.info=\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u0434\u043b\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u043d\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0438 dht.execute=\u0412\u0438\u043a\u043e\u043d\u0430\u0442\u0438 dht.logging=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0432\u0456\u0434\u0441\u0442\u0435\u0436\u0435\u043d\u043d\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0456 ConfigView.section.plugins.dhttracker=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 dhttracker.tracknormalwhenoffline=\u041f\u0440\u043e\u0441\u0442\u0435\u0436\u0443\u0432\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u0437\u0432\u0438\u0447\u0430\u0439\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u043a\u043e\u043b\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439. ConfigView.section.file.nativedelete._mac=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043a\u043e\u0448\u0438\u043a ConfigView.section.file.nativedelete._windows=\u0412\u0438\u043b\u0443\u0447\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u0438\u0439 \u043a\u043e\u0448\u0438\u043a ConfigView.section.logging.generatediagnostics=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 ConfigView.section.logging.netinfo=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u043c\u0435\u0440\u0435\u0436\u0443 ConfigView.section.logging.statsinfo=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 ConfigView.section.logging.generatediagnostics.info=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0434\u0456\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u043d\u0443 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0456 \u0441\u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0457\u0457 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443, \u0437\u0430\u043f\u0438\u0441\u0430\u0432\u0448\u0438 \u0432 \u0444\u0430\u0439\u043b .log ConfigView.section.sharing.privatetorrent=\u041e\u0441\u043e\u0431\u0438\u0441\u0442\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 - \u043f\u0440\u0438\u0439\u043c\u0430\u0454 \u0441\u043f\u0456\u0432\u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u043b\u0438\u0448\u0435 \u0432\u0456\u0434 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 MainWindow.menu.tools.nattest=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 NAT \u0456 &\u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u0430 Button.apply=\u0417\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438 Button.close=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 window.welcome.title=\u041b\u0430\u0441\u043a\u0430\u0432\u043e \u043f\u0440\u043e\u0441\u0438\u043c\u043e \u0432 Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e \u043f\u0440\u043e \u0440\u0435\u043b\u0456\u0437 dht.reseed.label=\u0417\u0430\u0437\u0432\u0438\u0447\u0430\u0439 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u043e\u0457 \u0411\u0414 \u043d\u0435 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0430. \u041e\u0434\u043d\u0430\u043a, \u044f\u043a\u0449\u043e \u0437'\u0454\u0434\u043d\u0430\u043d\u044c \u043d\u0435\u0431\u0430\u0433\u0430\u0442\u043e, \u0446\u044f \u0444\u0443\u043d\u043a\u0446\u0456\u044f \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u0430 \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0457 \u0456\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0456\u0457.\n\u0417\u0430\u043b\u0438\u0448\u0442\u0435 \u043f\u043e\u043b\u0435 \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u043c, \u0449\u043e\u0431 \u0432\u0438\u043a\u043e\u043d\u0430\u0442\u0438 \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0456\u0434 \u043f\u0456\u0434'\u0454\u0434\u043d\u0430\u043d\u043d\u0438\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0430\u0431\u043e \u0432\u043a\u0430\u0436\u0456\u0442\u044c IP \u0456 \u043f\u043e\u0440\u0442, \u0449\u043e\u0431 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438\u0441\u044f \u043f\u0440\u044f\u043c\u043e \u0432\u0456\u0434 \u0432\u0456\u0434\u043e\u043c\u043e\u0433\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430. dht.reseed.group=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0440\u043e\u0437\u0434\u0430\u0442\u0438 dht.reseed.ip=IP-\u0430\u0434\u0440\u0435\u0441\u0430 dht.reseed.port=\u041f\u043e\u0440\u0442 dht.reseed=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0440\u043e\u0437\u0434\u0430\u0442\u0438 dht.reseed.info=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0440\u043e\u0437\u0434\u0430\u0442\u0438 \u0411\u0414 dht.diagnostics.group=\u0414\u0456\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 DHTView.title.full=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0411\u0414 DHTView.title.fullcvs=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0411\u0414 CVS DHTView.general.title=\u041e\u0441\u043d\u043e\u0432\u043d\u0456 DHTView.general.uptime=\u0427\u0430\u0441 \u0440\u043e\u0431\u043e\u0442\u0438: DHTView.general.users=\u041a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432: DHTView.general.nodes=\u0412\u0443\u0437\u043b\u0456\u0432: DHTView.general.leaves=\u041f\u043e\u043a\u0438\u0434\u0430\u044e\u0447\u0438\u0445: DHTView.general.contacts=\u0417'\u0454\u0434\u043d\u0430\u043d\u044c: DHTView.general.replacements=\u0417\u0430\u043c\u0456\u043d\u043d\u0438\u043a\u0438: DHTView.general.live=\u0416\u0438\u0432\u0438\u0445: DHTView.general.unknown=\u041d\u0435\u0432\u0456\u0434\u043e\u043c\u0438\u0445: DHTView.general.dying=\u041c\u0435\u0440\u0442\u0432\u0438\u0445: DHTView.transport.title=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0434\u0430\u043d\u0438\u0445 DHTView.transport.packets=\u041f\u0430\u043a\u0435\u0442\u0456\u0432 DHTView.transport.bytes=\u0411\u0430\u0439\u0442 DHTView.transport.received=\u041e\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 DHTView.transport.sent=\u0412\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0445 DHTView.transport.in=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f : DHTView.transport.out=\u0420\u043e\u0437\u0434\u0430\u0447\u0430 : DHTView.operations.title=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 DHTView.operations.sent=\u0412\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0445 DHTView.operations.ok=\u0413\u0430\u0440\u0430\u0437\u0434 DHTView.operations.failed=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 DHTView.operations.received=\u041e\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 DHTView.operations.ping=\u041f\u0456\u043d\u0433 DHTView.operations.findNode=\u041f\u043e\u0448\u0443\u043a \u0432\u0443\u0437\u043b\u0430 DHTView.operations.findValue=\u041f\u043e\u0448\u0443\u043a \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f DHTView.operations.store=\u0417\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0445 DHTView.activity.title=\u0410\u043a\u0442\u0438\u0432\u043d\u0456\u0441\u0442\u044c DHTView.activity.status=\u0421\u0442\u0430\u0442\u0443\u0441 DHTView.activity.status.true=\u0423 \u0447\u0435\u0440\u0437\u0456 DHTView.activity.status.false=\u0412\u0438\u043a\u043e\u043d\u0443\u0454\u0442\u044c\u0441\u044f DHTView.activity.type=\u0422\u0438\u043f DHTView.activity.type.1=\u0412\u043d\u0443\u0442\u0440\u0456\u0448\u043d\u0456\u0439 \u043f\u0440\u0438\u0439\u043e\u043c DHTView.activity.type.2=\u0417\u043e\u0432\u043d\u0456\u0448\u043d\u0456\u0439 \u043f\u0440\u0438\u0439\u043e\u043c DHTView.activity.type.3=\u0412\u043d\u0443\u0442\u0440\u0456\u0448\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0430 DHTView.activity.type.4=\u0417\u043e\u0432\u043d\u0456\u0448\u043d\u0456\u0439 \u0440\u043e\u0437\u0434\u0430\u0447\u0430 DHTView.activity.target=\u041c\u0435\u0442\u0430 DHTView.activity.details=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e DHTView.db.title=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u0438\u0445 DHTView.db.keys=\u041a\u043b\u044e\u0447\u0456 DHTView.db.values=\u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f DHTView.db.local=\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u043e DHTView.db.direct=\u041f\u0440\u044f\u043c\u043e DHTView.db.indirect=\u041f\u043e\u0431\u0456\u0447\u043d\u043e DHTView.db.divfreq=\u0427\u0430\u0441\u0442\u043e\u0442\u0430. Div. DHTView.db.divsize=\u0420\u043e\u0437\u043c\u0456\u0440 Div. MainWindow.dht.status.tooltip=\u041a\u043e\u043b\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430 \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0411\u0414, \u043f\u043e\u043a\u0430\u0437\u0443\u0454\u0442\u044c\u0441\u044f \u043e\u0440\u0456\u0454\u043d\u0442\u043e\u0432\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043f\u0456\u0434'\u0454\u0434\u043d\u0430\u043d\u0438\u0445 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 MainWindow.dht.status.disabled=DHT \u0412\u0438\u043c\u043a\u043d\u0443\u0442\u043e MainWindow.dht.status.failed=DHT \u041f\u043e\u043c\u0438\u043b\u043a\u0430 MainWindow.dht.status.initializing=DHT \u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f MainWindow.dht.status.users=\u041a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456: %1 MainWindow.dht.status.unreachable=DHT \u0437\u0430\u043a\u0440\u0438\u0442\u0435 \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u043e\u043c MainWindow.dht.status.unreachabletooltip=\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0437 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f\u043c \u043f\u043e\u0440\u0442\u0456\u0432 UDP \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u043e\u0457 \u0411\u0414 (\u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440 \u0430\u0431\u043e NAT) MyTorrentsView.menu.setUpSpeed=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 MyTorrentsView.menu.setDownSpeed=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ConfigView.section.tracker.client.showwarnings=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u043d\u044f, \u044f\u043a\u0456 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u044e\u0442\u044c\u0441\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438 dht.advanced=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f dht.advanced.group=\u0414\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f dht.advanced.label=\u0417\u043c\u0456\u043d\u044e\u0439\u0442\u0435 \u0446\u0456 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438, \u043b\u0438\u0448\u0435, \u044f\u043a\u0449\u043e \u0440\u043e\u0437\u0443\u043c\u0456\u0454\u0442\u0435, \u0449\u043e \u0412\u0438 \u0440\u043e\u0431\u0438\u0442\u0435 dht.override.ip=\u041f\u0456\u0434\u043c\u0456\u043d\u044e\u0432\u0430\u0442\u0438 \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u044e IP-\u0430\u0434\u0440\u0435\u0441\u0443 ConfigView.section.logging.loggerenable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 .log ConfigView.section.ipfilter.blockbanning=\u0417\u0430\u0431\u0430\u043d\u0438\u0442\u0438 \u0431\u043b\u043e\u043a \u0437 256 \u0430\u0434\u0440\u0435\u0441, \u044f\u043a\u0449\u043e \u0432 \u0446\u044c\u043e\u043c\u0443 \u0431\u043b\u043e\u0446\u0456 \u0437\u0430\u0431\u0430\u043d\u0435\u043d\u0456 \u0431\u0456\u043b\u044c\u0448\u0435 \u044f\u043a MyTrackerView.passive=\u041f\u0430\u0441\u0438\u0432\u043d\u0438\u0439 TableColumn.header.swarm_average_speed=\u0421\u0435\u0440\u0435\u0434\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f TableColumn.header.swarm_average_speed.info=\u0421\u0435\u0440\u0435\u0434\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f TableColumn.header.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 TableColumn.header.comment.info=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0434\u043b\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f TableColumn.header.commenticon=\u041f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0430 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440\u044e TableColumn.header.commenticon.info=\u0412\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u0438 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0443, \u044f\u043a\u0449\u043e \u0432 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0454 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 MyTrackerView.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044f MainWindow.menu.file.open.torrentfortracking=\u0422\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b... (\u043b\u0438\u0448\u0435 \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430) VivaldiView.title.full=\u0412\u0456\u0432\u0430\u043b\u044c\u0434\u0456 MyTrackerView.date_added=\u0414\u043e\u0434\u0430\u043d\u0438\u0439 ConfigView.section.tracker.portbackup=\u0420\u0435\u0437\u0435\u0440\u0432\u043d\u0456 \u043f\u043e\u0440\u0442\u0438 (\u0440\u043e\u0437\u0434\u0456\u043b\u0435\u043d\u0456 ';') ConfigView.label.playfilespeech=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u0442\u0438 \u0441\u0438\u043d\u0442\u0435\u0437\u0430\u0442\u043e\u0440\u043e\u043c \u0433\u043e\u043b\u043e\u0441\u0443 \u043f\u0440\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 ConfigView.label.playfilespeech.info=\u0421\u0438\u043d\u0442\u0435\u0437\u0430\u0442\u043e\u0440 \u0433\u043e\u043b\u043e\u0441\u0443 \u043f\u043e\u043a\u0438 \u0449\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0430\u0446\u044e\u0454 \u043b\u0438\u0448\u0435 \u0437 \u0430\u043d\u0433\u043b\u0456\u0439\u0441\u044c\u043a\u043e\u044e \u043c\u043e\u0432\u043e\u044e ConfigView.label.playfilefinished=\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u044e\u0432\u0430\u0442\u0438 \u0437\u0432\u0443\u043a \u043f\u0440\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 ConfigView.label.backupconfigfiles=\u0420\u043e\u0431\u0438\u0442\u0438 \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u0456 \u043a\u043e\u043f\u0456\u0457 \u0444\u0430\u0439\u043b\u0456\u0432 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457 \u043d\u0430 \u0432\u0438\u043f\u0430\u0434\u043e\u043a \u0432\u0456\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f \u0430\u0432\u0430\u0440\u0456\u0457 ConfigView.section.tracker.client.scrapesingleonly=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0441\u0445\u043e\u0432\u0438\u0449 \u0437\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438 (\u043c\u043e\u0436\u0435 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u0442\u0438 \u0437 \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438, \u044f\u043a\u0456 \u0432\u0438\u0434\u0430\u044e\u0442\u044c \u043f\u043e\u043c\u0438\u043b\u043a\u0443 414 '\u0430\u0434\u0440\u0435\u0441\u0430 \u0437\u0430\u043d\u0430\u0434\u0442\u043e \u0434\u043e\u0432\u0433\u0430') dht.ipfilter.log=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u0432 .log \u043f\u043e\u0440\u0443\u0448\u0435\u043d\u043d\u044f IP-\u0444\u0456\u043b\u044c\u0442\u0440\u0430 ConfigView.label.seeding.addForSeedingDLCopyCount=\u0412\u0440\u0430\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438 '\u0434\u043e\u0434\u0430\u043d\u0456 \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456' \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0432 \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u043a\u043e\u043f\u0456\u0439 ActivityView.legend.limit=\u041e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 ActivityView.legend.achieved=\u0414\u043e\u0441\u044f\u0433\u043d\u0443\u0442\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c ActivityView.legend.overhead=\u0412\u0435\u0440\u0445\u043d\u0454 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f ActivityView.legend.peeraverage=\u0421\u0435\u0440\u0435\u0434\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c ActivityView.legend.swarmaverage=\u0421\u0435\u0440\u0435\u0434\u043d\u044f \u0437\u0430 \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f\u043c ActivityView.legend.trimmed=\u0412\u043f\u043e\u0440\u044f\u0434\u043a\u043e\u0432\u0430\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c (\u043f\u0443\u043d\u043a\u0442\u0438\u0440) MyTorrentsView.menu.movemenu=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 MyTorrentsView.menu.movedata=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438... MyTorrentsView.menu.movetorrent=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b... MyTorrentsView.menu.movedata.dialog=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u043e\u0432\u0435 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f DHTView.operations.data=\u0414\u0430\u043d\u0456 DHTView.general.reachable=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439: DHTView.general.rendezvous=\u0412\u0437\u0430\u0454\u043c\u043e\u0434\u0456\u0439: ConfigView.label.queue.maxactivetorrentswhenseeding=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0432 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u043b\u0438\u0448\u0435 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 [0:\u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439] Views.plugins.IRC.title=IRC Formats.units.persec=/\u0441 Formats.units.TiB=\u0422\u0456\u0431 Formats.units.Tibit=\u0422\u0456\u0411\u0456\u0442 Formats.units.TB=\u0422\u0411\u0430\u0439\u0442 Formats.units.Tbit=\u0422\u0431\u0456\u0442 Formats.units.GiB=\u0413\u0456\u0431 Formats.units.Gibit=\u0413\u0456\u0411\u0456\u0442 Formats.units.GB=\u0413\u0411\u0430\u0439\u0442 Formats.units.Gbit=\u0413\u0431\u0456\u0442 Formats.units.MiB=\u041c\u0456\u0431 Formats.units.Mibit=\u041c\u0456\u0411\u0456\u0442 Formats.units.MB=\u041c\u0411\u0430\u0439\u0442 Formats.units.Mbit=\u041c\u0431\u0456\u0442 Formats.units.KiB=\u041a\u0456\u0431 Formats.units.Kibit=K\u0456\u0411\u0456\u0442 Formats.units.kB=\u041a\u0431 Formats.units.KB=\u041a\u0411\u0430\u0439\u0442 Formats.units.kbit=\u041a\u0431\u0456\u0442 Formats.units.B=\u0411\u0430\u0439\u0442 Formats.units.bit=\u0431\u0456\u0442 Formats.units.alot=\u0414\u043e\u0441\u0438\u0442\u044c !!! ConfigView.section.ipfilter.persistblocking=\u0417\u0431\u0435\u0440\u0456\u0433\u0430\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043f\u0440\u043e \u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0439 IP \u043c\u0456\u0436 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043c\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 FilesView.menu.rename=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0430\u0431\u043e \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 FilesView.menu.rename_only=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 FilesView.menu.retarget=\u041f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u0438 FilesView.rename.choose.path=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u043e\u0432\u0438\u0439 \u0430\u0431\u043e \u043d\u0430\u044f\u0432\u043d\u0438\u0439 \u0444\u0430\u0439\u043b FilesView.rename.choose.path.dir=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u043e\u0432\u0443 \u0430\u0431\u043e \u043d\u0430\u044f\u0432\u043d\u0443 \u0442\u0435\u043a\u0443 FilesView.rename.confirm.delete.title=\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f FilesView.rename.confirm.delete.text=\u0412\u0438 \u043f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0443\u0454\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u043e\u0440\u0438\u0433\u0456\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0443 '%1'? FilesView.rename.filename.title=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b FilesView.rename.filename.text=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043d\u043e\u0432\u0435 \u0456\u043c'\u044f \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0443 ConfigView.higher.mode.available=\u041f\u043e\u0434\u0430\u043b\u044c\u0448\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043b\u0438\u0448\u0435 \u0432 \u0456\u043d\u0448\u0438\u0445 \u0440\u0435\u0436\u0438\u043c\u0430\u0445 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 ConfigView.section.mode=\u0420\u0435\u0436\u0438\u043c ConfigView.section.mode.title=\u0421\u0442\u0443\u043f\u0456\u043d\u044c \u043f\u0456\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 ConfigView.section.mode.beginner=\u041d\u043e\u0432\u0430\u0447\u043e\u043a ConfigView.section.mode.beginner.wiki.definitions=\u0421\u043b\u043e\u0432\u043d\u0438\u043a BitTorrent ConfigView.section.mode.intermediate=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 ConfigView.section.mode.intermediate.wiki.host=\u0420\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0456\u0432 ConfigView.section.mode.intermediate.wiki.publish=\u041f\u0443\u0431\u043b\u0456\u043a\u0430\u0446\u0456\u044f \u0444\u0430\u0439\u043b\u0456\u0432 ConfigView.section.mode.advanced=\u0420\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u0439 ConfigView.section.mode.advanced.wiki.main=\u0413\u043e\u043b\u043e\u0432\u043d\u0430 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0430 Wiki ConfigView.section.mode.beginner.text=\u0412\u0441\u0435, \u0449\u043e \u043c\u0435\u043d\u0456 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0434\u043b\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432.\n\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u0446\u0435\u0439 \u0440\u0435\u0436\u0438\u043c, \u044f\u043a\u0449\u043e \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u043a\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438 ConfigView.section.mode.intermediate.text=\u0414\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u0444\u0443\u043d\u043a\u0446\u0456\u0439 \u0442\u0440\u0435\u043a\u0435\u0440\u0430.\n\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u0446\u0435\u0439 \u0440\u0435\u0436\u0438\u043c, \u044f\u043a\u0449\u043e \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0441\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u0432\u0456\u0439 \u0432\u043b\u0430\u0441\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0444\u0430\u0439\u043b\u0456\u0432. ConfigView.section.mode.advanced.text=\u0414\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u043c\u0435\u0440\u0435\u0436\u0435\u0432\u0438\u0445 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c.\n\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u0446\u0435\u0439 \u0440\u0435\u0436\u0438\u043c, \u044f\u043a\u0449\u043e \u0412\u0438 \u0437\u043d\u0430\u0454\u0442\u0435 \u0449\u043e \u0442\u0430\u043a\u0435 MTU \u0430\u0431\u043e \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044f-\u0432\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044f, \u044f\u043a\u0435 \u043d\u0435 \u0431\u043b\u043e\u043a\u0443\u0454\u0442\u044c\u0441\u044f... Files.column.storagetype=\u0422\u0438\u043f \u0441\u0445\u043e\u0432\u0438\u0449\u0430 Files.column.fileext=\u0422\u0438\u043f FileItem.storage.linear=\u041b\u0456\u043d\u0456\u0439\u043d\u0438\u0439 FileItem.storage.compact=\u041a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u0438\u0439 MessageBoxWindow.rememberdecision=\u0417\u0430\u043f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u043c\u0456\u0439 \u0432\u0438\u0431\u0456\u0440 ConfigView.section.interface.cleardecisions=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0456 \u0432\u0438\u0431\u043e\u0440\u0438 \u0434\u0456\u0430\u043b\u043e\u0433\u0456\u0432 ConfigView.section.interface.cleardecisionsbutton=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 ConfigView.section.interface.cleartrackers=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0456 \u0442\u0440\u0435\u043a\u0435\u0440\u0438 ConfigView.section.interface.cleartrackersbutton=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 ConfigView.section.interface.clearsavepaths=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0456 \u0448\u043b\u044f\u0445\u0438 ConfigView.section.interface.clearsavepathsbutton=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 configureWizard.welcome.usermodes=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0441\u0442\u0443\u043f\u0435\u043d\u044f \u0434\u043e\u0441\u0432\u0456\u0434\u0447\u0435\u043d\u043e\u0441\u0442\u0456 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0437\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0421\u0435\u0440\u0432\u0456\u0441 > \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f. \u0412\u043e\u043d\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u044e\u044e\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u0435\u0433\u0448\u0435\u043d\u043d\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e. FilesView.skip.confirm.delete.text=\u041e\u0431\u0440\u0456\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b '%1' \u0434\u043b\u044f \u0435\u043a\u043e\u043d\u043e\u043c\u0456\u0457 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f? FilesView.rename.failed.title=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0430\u0431\u043e \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f FilesView.rename.failed.text=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u044f \u043f\u0435\u0440\u0435\u0440\u0432\u0430\u043d\u0430, \u043c\u043e\u0436\u043b\u0438\u0432\u043e \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u0438\u0431\u0440\u0430\u043d\u0443 \u043c\u0435\u0442\u0443 diagnostics.log_found=Vuze \u043d\u0435 \u0431\u0443\u0432 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438\u0439 \u043a\u043e\u0440\u0435\u043a\u0442\u043d\u043e. \u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0437\u0430\u043f\u0438\u0441 \u0432 \u043b\u043e\u0437\u0456 , \u044f\u043a\u0449\u043e \u0446\u0435 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438, \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u0442\u0435 \u0444\u0430\u0439\u043b .log \u043a\u043e\u043c\u0430\u043d\u0434\u0456 \u0440\u043e\u0437\u0440\u043e\u0431\u043d\u0438\u043a\u0456\u0432. \u0422\u0430\u043a\u043e\u0436 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0439\u0442\u0435 Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443 \u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0440\u043e\u0431\u043e\u0442\u0438 Vuze \u0434\u043b\u044f \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457. ManagerItem.paused=\u041f\u0440\u0438\u043f\u0438\u043d\u0435\u043d\u043e Utils.link.visit=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 ConfigView.section.connection.serverport.wiki=\u0413\u0430\u0440\u043d\u0438\u0439 \u0432\u0438\u0431\u0456\u0440 \u043f\u043e\u0440\u0442\u0456\u0432 ConfigView.section.transfer.speeds.wiki=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0433\u0430\u0440\u043d\u043e\u0457 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 installPluginsWizard.installMode.info.title=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f installPluginsWizard.installMode.info.text=\u0414\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043d\u0435\u043e\u0431\u043e\u0432'\u044f\u0437\u043a\u043e\u0432\u0456 \u0434\u043b\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u0457 \u0440\u043e\u0431\u043e\u0442\u0438 Vuze, \u0432\u043e\u043d\u0438 \u043d\u0435 \u0437\u0430\u0432\u0436\u0434\u0438 \u0434\u043e\u0434\u0430\u044e\u0442\u044c \u043a\u043e\u0440\u0438\u0441\u043d\u0456 \u0444\u0443\u043d\u043a\u0446\u0456\u0457, \u0430 \u043d\u0430\u0439\u0447\u0430\u0441\u0442\u0456\u0448\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f, \u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434, \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0456\u0457 \u0440\u0443\u0442\u0438\u043d\u043d\u0438\u0445 \u0440\u043e\u0431\u0456\u0442.\n\u0422\u043e\u043c\u0443 \u043e\u0437\u043d\u0430\u0439\u043e\u043c\u0442\u0435\u0441\u044f \u0437 \u043e\u043f\u0438\u0441\u043e\u043c \u043a\u043e\u0436\u043d\u043e\u0433\u043e \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f, \u043f\u0435\u0440\u0448 \u043d\u0456\u0436 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0439\u043e\u0433\u043e.\n\u0411\u0456\u043b\u044c\u0448\u0456\u0441\u0442\u044c \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c \u043c\u043e\u0436\u043d\u0430 \u0441\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u0442\u0438, \u043d\u0435 \u0441\u0442\u0432\u043e\u0440\u044e\u044e\u0447\u0438 \u043d\u0435\u0431\u0435\u0437\u043f\u0435\u043a\u0443 \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438, \u0430\u043b\u0435 \u0432\u0441\u0435-\u0442\u0430\u043a\u0438 \u043d\u0435 \u043f\u0435\u0440\u0435\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0439\u0442\u0435 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044e \u043d\u0435\u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0438\u043c\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f\u043c\u0438. Views.plugins.Distributed.DB.title=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0411\u0414 Views.plugins.Distributed.Tracker.title=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 Views.plugins.Plugin.Update.title=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f Views.plugins.UPnP.title.tooltip=\u0423\u043d\u0456\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0438\u0439 Plug and Play openUrl.url.info=\u041f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0430 http, https, magnet \u0456 \u043d\u0435\u043e\u043f\u0440\u0430\u0446\u044c\u043e\u0432\u0430\u043d\u0438\u0445 \u0448\u0456\u0441\u0442\u043d\u0430\u0434\u0446\u044f\u0442\u0438\u0437\u043d\u0430\u0447\u043d\u0438\u0445 \u0456\u043d\u0444\u043e\u0445\u0435\u0448\u043e\u0432\u0438\u0445 \u0440\u044f\u0434\u043a\u0456\u0432 TableColumn.header.swarm_average_completion=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 \u0432\u0456\u0434\u0441\u043e\u0442\u043e\u043a \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f TableColumn.header.swarm_average_completion.info=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 \u0432\u0456\u0434\u0441\u043e\u0442\u043e\u043a \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0441\u0435\u0440\u0435\u0434 \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f GeneralView.label.swarm_average_completion=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 % \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f: GeneralView.label.swarm_average_completion.tooltip=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 % \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0441\u0435\u0440\u0435\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f MainWindow.nat.status.tooltip.unknown=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u043f\u0440\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456\u0441\u0442\u044c \u0431\u0440\u0430\u0443\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u0443 \u0430\u0431\u043e NAT \u043d\u0435\u0432\u0456\u0434\u043e\u043c\u0430 (TCP) MainWindow.nat.status.tooltip.ok=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456\u0441\u0442\u044c \u0432 \u043d\u043e\u0440\u043c\u0456 (TCP) MainWindow.nat.status.tooltip.probok=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456\u0441\u0442\u044c \u0432 \u043d\u043e\u0440\u043c\u0456, \u043e\u0434\u043d\u0430\u043a \u043f\u043e\u043a\u0438 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c TCP \u043d\u0435 \u0431\u0443\u043b\u043e MainWindow.nat.status.bad=\u0417\u0430\u0445\u0438\u0449\u0435\u043d\u0456 \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u043e\u043c MainWindow.nat.status.tooltip.bad=\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0437 \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u043e\u043c \u0430\u0431\u043e NAT. \u0417\u0430\u0433\u043b\u044f\u043d\u044c\u0442\u0435 \u0432 Wiki \u0434\u043b\u044f \u0434\u043e\u0432\u0456\u0434\u043a\u0438 plugin.installer.recommended.plugin=\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u0435 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f - \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u043e\u0446\u0456\u043d\u0456\u0442\u044c \u0456 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c, \u044f\u043a\u0449\u043e \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e LoggerView.pause=\u041f\u0440\u0438\u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0432 \u0444\u0430\u0439\u043b .log LoggerView.clear=&\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 LoggerView.filter=\u0424\u0456\u043b\u044c\u0442\u0440 LoggerView.filter.uncheckAll=\u0417\u043d\u044f\u0442\u0438 \u043f\u043e\u0437\u043d\u0430\u0447\u043a\u0443 \u0443 \u0432\u0441\u0456\u0445 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0439 LoggerView.filter.checkAll=\u041f\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457 LoggerView.loggingDisabled=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0432 .log \u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0443\u0454\u0442\u044c\u0441\u044f. LoggerView.includeOnly=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u043b\u0456\u043d\u0456\u0457, \u044f\u043a\u0456 \u0441\u043f\u0456\u0432\u043f\u0430\u0434\u0430\u044e\u0442\u044c \u0437 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0438\u043c \u0432\u0438\u0440\u0430\u0437\u043e\u043c LoggerView.excludeAll=\u041d\u0435 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043b\u0456\u043d\u0456\u0457, \u044f\u043a\u0456 \u0441\u043f\u0456\u0432\u043f\u0430\u0434\u0430\u044e\u0442\u044c \u0437 \u0446\u0438\u043c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0438\u043c \u0432\u0438\u0440\u0430\u0437\u043e\u043c: ConfigView.section.logging.log0type=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f ConfigView.section.logging.log1type=\u041f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u044c ConfigView.section.logging.log2type=\u041f\u043e\u043c\u0438\u043b\u043e\u043a ConfigView.section.logging.filter=\u0424\u0456\u043b\u044c\u0442\u0440\u0443\u0432\u0430\u0442\u0438 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0432 \u0444\u0430\u0439\u043b .log ConfigView.section.logging.level=\u0421\u0442\u0443\u043f\u0456\u043d\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c \u0444\u0430\u0439\u043b\u0443 .log ConfigView.section.logging.showLogsFor=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 .log %1 \u0437\u0430 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u043c\u0438 \u043a\u0440\u0438\u0442\u0435\u0440\u0456\u044f\u043c\u0438: ConfigView.pluginlist.column.loadAtStartup=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 ConfigView.pluginlist.column.type=\u0422\u0438\u043f ConfigView.pluginlist.column.type.perUser=\u041a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 ConfigView.pluginlist.column.type.shared=\u0420\u043e\u0437\u0434\u0430\u043d\u0438\u0439 ConfigView.pluginlist.column.type.builtIn=\u0412\u0431\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0439 ConfigView.pluginlist.column.name=\u0406\u043c'\u044f ConfigView.pluginlist.column.version=\u0412\u0435\u0440\u0441\u0456\u044f ConfigView.pluginlist.column.directory=\u0422\u0435\u043a\u0430 ConfigView.pluginlist.column.isOperational=\u041f\u0440\u0430\u0446\u044e\u0454? PeersView.BlockView.Avail.Have=\u0404 \u0432 \u043e\u0431\u043e\u0445 PeersView.BlockView.Avail.NoHave=\u0412 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0454; \u0432 \u0412\u0430\u0441 \u043d\u0435\u043c\u0430 PeersView.BlockView.NoAvail.Have=\u0412 \u0412\u0430\u0441 \u0454; \u0432 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u043d\u0435\u043c\u0430 PeersView.BlockView.NoAvail.NoHave=\u0412 \u043e\u0431\u043e\u0445 \u043d\u0435\u043c\u0430 PeersView.BlockView.Transfer=\u041f\u0435\u0440\u0435\u0434\u0430\u0454\u0442\u044c\u0441\u044f \u0437\u0430\u0440\u0430\u0437 PeersView.BlockView.NextRequest=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0437\u0430\u043f\u0438\u0442 PeersView.BlockView.title=\u041a\u0430\u0440\u0442\u0430 \u0447\u0430\u0441\u0442\u0438\u043d PeersView.BlockView.AvailCount=\u0406\u043d\u0434\u0435\u043a\u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0456 MyTorrentsView.dialog.NumberError.title=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435 \u0430\u0431\u043e \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u0435 \u0447\u0438\u0441\u043b\u043e MyTorrentsView.dialog.NumberError.text=\u0412\u043a\u0430\u0437\u0430\u043d\u0435 \u0447\u0438\u0441\u043b\u043e \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435 \u0430\u0431\u043e \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u0435. MyTorrentsView.menu.manual=&\u0412\u0440\u0443\u0447\u043d\u0443.. MyTorrentsView.menu.manual.per_torrent=\u0412\u0440\u0443\u0447\u043d\u0443 (\u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443) MyTorrentsView.menu.manual.shared_torrents=\u0412\u0440\u0443\u0447\u043d\u0443 (\u0447\u0435\u0440\u0435\u0437 \u0442\u043e\u0440\u0435\u043d\u0442\u0438) MyTorrentsView.dialog.setSpeed.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0447\u0438\u0441\u043b\u043e %1, \u0449\u043e\u0431 \u0437\u043c\u0456\u043d\u0438\u0442\u0438 %2 \u043d\u0430: MyTorrentsView.dialog.setNumber.upload=\u0440\u043e\u0437\u0434\u0430\u0447\u0430 MyTorrentsView.dialog.setNumber.download=\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f MyTorrentsView.dialog.setNumber.inKbps=\u0432 %1 OpenTorrentWindow.torrentLocation=\u0424\u0430\u0439\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432: OpenTorrentWindow.addFiles.URL=\u0414\u043e\u0434\u0430\u0442\u0438 &\u0430\u0434\u0440\u0435\u0441\u0443 OpenTorrentWindow.addFiles.Folder=\u0414\u043e\u0434\u0430\u0442\u0438 &\u0442\u0435\u043a\u0443 OpenTorrentWindow.addFiles.Clipboard=\u0414\u043e\u0434\u0430\u0442\u0438 \u0437 \u0431\u0443\u0444\u0435\u0440\u0430 \u043e\u0431\u043c\u0456\u043d\u0443 OpenTorrentWindow.changeDestination=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u043c\u0456\u0441\u0446\u0435 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f OpenTorrentWindow.fileList=\u0424\u0430\u0439\u043b\u0456\u0432 \u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u0445: OpenTorrentWindow.torrentTable.name=\u041d\u0430\u0437\u0432\u0430 OpenTorrentWindow.torrentTable.saveLocation=\u041c\u0456\u0441\u0446\u0435 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f OpenTorrentWindow.fileTable.fileName=\u0406\u043c'\u044f \u0444\u0430\u0439\u043b\u0443 OpenTorrentWindow.fileTable.size=\u0420\u043e\u0437\u043c\u0456\u0440 OpenTorrentWindow.fileTable.destinationName=\u041a\u0456\u043d\u0446\u0435\u0432\u0430 \u043d\u0430\u0437\u0432\u0430 OpenTorrentWindow.startMode.seeding=\u0420\u043e\u0437\u0434\u0430\u0447\u0430 OpenTorrentWindow.fileList.changeDestination=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f OpenTorrentWindow.mb.badSize.title=\u0424\u0430\u0439\u043b \u043d\u0435\u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u043d\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0443 OpenTorrentWindow.mb.badSize.text='%1' \u043d\u0435 '%2' \u0456 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u0438\u0439 \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 OpenTorrentWindow.mb.alreadyExists.text=%3 \u0432\u0436\u0435 \u0431\u0443\u0432 \u0434\u043e\u0434\u0430\u043d\u0438\u0439 \u043f\u0456\u0434 \u0456\u043c'\u044f\u043c '%2' OpenTorrentWindow.mb.alreadyExists.default.name=\u041c\u0435\u0434\u0456\u0430 OpenTorrentWindow.mb.alreadyExists.title=\u0422\u0430\u043a\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454 OpenTorrentWindow.mb.openError.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 OpenTorrentWindow.mb.openError.text='%1' \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438:\n%2 OpenTorrentWindow.torrent.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0437 \u0441\u043f\u0438\u0441\u043a\u0443 OpenTorrentWindow.torrent.options=\u0414\u043e \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0430\u0441\u0442\u043e\u0441\u043e\u0432\u0430\u043d\u0456 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f: OpenTorrentWindow.xOfTotal=(%1 \u0437 %2) iconBar.open.tooltip=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b LocaleUtil.column.text=\u041d\u0435\u0432\u0456\u0434\u043e\u043c\u0438\u0439 \u0442\u0435\u043a\u0441\u0442 Tracker.tooltip.MultiSupport=\u0426\u0435\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u043c\u043d\u043e\u0436\u0438\u043d\u043d\u0456 \u0445\u0435\u0448-\u0447\u0430\u0441\u0442\u0438\u043d\u0438 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u0437\u0430\u043f\u0438\u0442\u0443. Tracker.tooltip.NoMultiSupport=\u0426\u0435\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u043c\u043d\u043e\u0436\u0438\u043d\u043d\u0456 \u0445\u0435\u0448-\u0447\u0430\u0441\u0442\u0438\u043d\u0438 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u0437\u0430\u043f\u0438\u0442\u0443. ConfigView.label.lazybitfield=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 '\u043b\u0435\u0434\u0430\u0447\u0443' \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 (\u0434\u043e\u043f\u043e\u043c\u0430\u0433\u0430\u0454 \u043f\u043e\u0448\u0438\u0440\u0435\u043d\u043d\u044e \u0432 \u043c\u0435\u0440\u0435\u0436\u0430\u0445, \u044f\u043a\u0456 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c \u0431\u043b\u043e\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043e\u0433\u043e \u0431\u0456\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f) LoggerView.realtime=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0447\u0430\u0441\u0456 ConfigView.section.file.perf.cache.flushpieces=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0447\u0430\u0441\u0442\u0438\u043d\u0438 \u043d\u0435\u0433\u0430\u0439\u043d\u043e. \u0426\u0435 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u044c \u043f\u043e\u0441\u0442\u0456\u0439\u043d\u0438\u0439, \u0431\u0435\u0437\u043f\u0435\u0440\u0435\u0440\u0432\u043d\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f. ConfigView.section.file.writemblimit=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u043f\u0438\u0442\u0456\u0432 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441 \u0432 \u0447\u0435\u0440\u0437\u0456 (\u0432 %1) ConfigView.section.file.writemblimit.explain=\u042f\u043a\u0449\u043e \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0430 \u0434\u0438\u0441\u043a \u043c\u0435\u043d\u0448\u0435 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u0446\u0435\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043e\u0431\u043c\u0435\u0436\u0443\u0454 \u0440\u043e\u0437\u043c\u0456\u0440 \u0431\u0443\u0444\u0435\u0440\u0443, \u043f\u0435\u0440\u0448 \u043d\u0456\u0436 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u0434\u0435 \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e ConfigView.section.file.readmblimit=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u043f\u0438\u0442\u0456\u0432 \u043d\u0430 \u0447\u0438\u0442\u0430\u043d\u043d\u044f \u0432 \u0447\u0435\u0440\u0437\u0456 (\u0432 %1) ConfigView.section.file.readmblimit.explain=\u0426\u0435\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043e\u0431\u043c\u0435\u0436\u0443\u0454 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043f\u0430\u043c'\u044f\u0442\u0456, \u044f\u043a\u0430 \u0437\u0431\u0435\u0440\u0456\u0433\u0430\u0454 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u0447\u0438\u0442\u0430\u043d\u043d\u044f. Button.moveUp=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 &\u043d\u0430\u0433\u043e\u0440\u0443 Button.moveDown=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 &\u0432\u043d\u0438\u0437 ConfigView.notAvailableForMode=\u0426\u044f \u0441\u0435\u043a\u0446\u0456\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0440\u0456\u0432\u043d\u044f \u0434\u043e\u0441\u0432\u0456\u0434\u0447\u0435\u043d\u043e\u0441\u0442\u0456 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 %1 \u0430\u0431\u043e \u0432\u0438\u0449\u0435. \u0412 \u0440\u0435\u0436\u0438\u043c\u0456 %2 \u0446\u0456 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u044e\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e. health.explain.error=\u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0432\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u0437 \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u043c, \u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c \u0441\u0442\u0430\u0442\u0443\u0441\u0443, \u0430\u0431\u043e \u043f\u0456\u0434\u043a\u0430\u0437\u043a\u0443 \u043d\u0430 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0456 \u043f\u0440\u043e \u0446\u044e \u043f\u043e\u043c\u0438\u043b\u043a\u0443. GeneralView.label.trackerscrapeupdate=\u041e\u0447\u0438\u0449\u0443\u0432\u0430\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 PeersView.piece=\u0427\u0430\u0441\u0442\u0438\u043d\u0430 PeersView.piece.info=\u041e\u0441\u0442\u0430\u043d\u043d\u044f \u0447\u0430\u0441\u0442\u0438\u043d\u0430, \u0437\u0430\u043f\u0438\u0442\u0430\u043d\u0430 \u0432 \u0446\u044c\u043e\u0433\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 PiecesView.priority=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 PiecesView.priority.info=\u0426\u0435 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0446\u0456\u043b\u0456\u0441\u043d\u043e\u0441\u0442\u0456 \u0447\u0430\u0441\u0442\u0438\u043d\u0438, \u0430\u043b\u0435 \u043d\u0435 \u0437\u0432\u0435\u0440\u0442\u0430\u0439\u0442\u0435 \u0443\u0432\u0430\u0433\u0438 \u043d\u0430 \u043d\u044c\u043e\u0433\u043e PiecesView.speed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c PiecesView.speed.info=\u041f\u043e\u0432\u0456\u043b\u044c\u043d\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438 \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u044c\u0441\u044f \u0437\u0456 \u0448\u0432\u0438\u0434\u043a\u0438\u043c\u0438 \u0447\u0430\u0441\u0442\u0438\u043d\u0430\u043c\u0438 TableColumn.header.AvgAvail.info=\u0421\u0443\u043c\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0456 \u0447\u0430\u0441\u0442\u0438\u043d \u0440\u043e\u0437\u0434\u0456\u043b\u0435\u043d\u0430 \u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0447\u0430\u0441\u0442\u0438\u043d, \u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0438\u0445 \u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437'\u0454\u0434\u043d\u0430\u043d\u044c TableColumn.header.AvgAvail=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456/\u0447\u0430\u0441\u0442\u0438\u043d\u0443, \u0441\u0435\u0440\u0435\u0434\u043d\u0454 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f ConfigView.label.strictfilelocking=\u041f\u0440\u0438\u0448\u0432\u0438\u0434\u0448\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u043f\u0438\u0441 \u0435\u043a\u0441\u043a\u043b\u044e\u0437\u0438\u0432\u043d\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 MyTorrentsView.menu.checkfilesexist=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u0456\u0441\u043d\u0443\u0432\u0430\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0456\u0432 MyTorrentsView.menu.rescanfile=\u041f\u0435\u0440\u0456\u043e\u0434\u0438\u0447\u043d\u043e \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u044f\u0442\u0438 \u043d\u0435\u0434\u043e\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0447\u0430\u0441\u0442\u0438\u043d\u0438 MyTorrentsView.menu.clear_resume_data=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0434\u0430\u043d\u0456 \u043f\u0456\u0434\u0441\u0443\u043c\u043a\u0443 Plugin.extseed.name=\u0417\u043e\u0432\u043d\u0456\u0448\u043d\u0456 \u0441\u0456\u0434\u0435\u0440\u0438 Plugin.localtracker.name=\u041f\u043e\u0448\u0443\u043a \u043f\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456 Plugin.localtracker.info=\u041f\u043e\u0448\u0443\u043a \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0457 \u043c\u0435\u0440\u0435\u0436\u0456 \u0434\u0430\u0454 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 \u0447\u0438\u0441\u043b\u0435\u043d\u043d\u0438\u043c \u043a\u043e\u043f\u0456\u044f\u043c Vuze \u0447\u0435\u0440\u0435\u0437 \u0444\u0430\u0454\u0440\u0432\u043e\u043b \u0456 \u043c\u0435\u0440\u0435\u0436\u0443\n\u0432 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u0445, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f \u0435\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0456\u0448\u0435 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u043f\u0440\u044f\u043c\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c \u043c\u0456\u0436 \u043d\u0438\u043c\u0438 Plugin.localtracker.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043e\u0448\u0443\u043a \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0457 \u043c\u0435\u0440\u0435\u0436\u0456 azinstancehandler.alert.portclash=\u0412\u0438\u044f\u0432\u043b\u0435\u043d\u0438\u0439 \u043a\u043e\u043d\u0444\u043b\u0456\u043a\u0442 \u043f\u043e\u0440\u0442\u0456\u0432 \u0443 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456: %1 \u0432\u0436\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0456\u043d\u0448\u0438\u043c \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0435\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 Vuze, \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0431\u0443\u0434\u044c-\u044f\u043a\u0438\u0439 \u0456\u043d\u0448\u0438\u0439 \u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0432\u0445\u0456\u0434\u043d\u043e\u0433\u043e TCP / UDP [\u0443 \u0434\u0456\u0430\u043f\u0430\u0437\u043e\u043d\u0456 \u0432\u0456\u0434 %2 \u0434\u043e %3]. ConfigView.section.transfer.lan=\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0430 \u043c\u0435\u0440\u0435\u0436\u0430 ConfigView.section.transfer.lan.tooltip=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0432\u043d\u043e\u0457 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0457 \u043c\u0435\u0440\u0435\u0436\u0456 ConfigView.section.transfer.lan.uploadrate=- \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456, \u041a\u0431\u0456\u0442/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] ConfigView.section.transfer.lan.uploadrate.tooltip=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0432 \u0442\u0456\u0439 \u0441\u0430\u043c\u0456\u0439 \u0432\u043d\u0443\u0442\u0440\u0456\u0448\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456 \u043c\u0430\u044e\u0442\u044c \u0440\u0456\u0437\u043d\u0456 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456. ConfigView.section.transfer.lan.downloadrate=- \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456, \u041a\u0431\u0456\u0442/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] ConfigView.section.transfer.lan.downloadrate.tooltip=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0432 \u0442\u0456\u0439 \u0441\u0430\u043c\u0456\u0439 \u0432\u043d\u0443\u0442\u0440\u0456\u0448\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456 \u043c\u0430\u044e\u0442\u044c \u0440\u0456\u0437\u043d\u0456 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. TorrentOptionsView.title.short=\u041e\u043f\u0446\u0456\u0457 TorrentOptionsView.title.full=\u041e\u043f\u0446\u0456\u0457 TorrentOptionsView.param.max.peers=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437'\u0454\u0434\u043d\u0430\u043d\u044c [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] ConfigView.section.connection.encryption.require_encrypted_transport=\u0412\u0438\u043c\u0430\u0433\u0430\u0442\u0438 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0430\u0444\u0456\u043a\u0443 ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=\u041f\u0440\u0438\u043c\u0443\u0448\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0456\u043d\u0448\u0438\u043c\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438 ConfigView.section.connection.encryption.min_encryption_level=\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u0456\u0432\u0435\u043d\u044c \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f ConfigView.section.connection.encryption.min_encryption_level.tooltip=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 - \u043b\u0438\u0448\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a\nRC4 - \u043f\u043e\u0432\u043d\u0438\u0439 \u043f\u043e\u0442\u0456\u043a\n\u0412\u0438\u0449\u0438\u0439 \u0440\u0456\u0432\u0435\u043d\u044c \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043c\u043e\u0433\u0443\u0442\u043d\u0456\u0448\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u0430 Peers.column.Encryption=\u0428\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f Peers.column.Encryption.info=\u0420\u0456\u0432\u0435\u043d\u044c \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f, \u044f\u043a\u0438\u0439 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f ConfigView.section.connection.encryption.encrypt.info=\u042f\u043a\u0449\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0435 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f, \u0412\u0438 \u043d\u0435 \u0437\u043c\u043e\u0436\u0435\u0442\u0435 \u0437'\u0454\u0434\u043d\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u0437 \u043d\u0435\u0441\u0443\u043c\u0456\u0441\u043d\u0438\u043c\u0438 \u043a\u043b\u0456\u0454\u043d\u0442\u0430\u043c\u0438, \u043f\u043e\u043a\u0438 \u043d\u0435 \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u0442\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0440\u0435\u0437\u0435\u0440\u0432\u0443\u0432\u0430\u043d\u043d\u044f ConfigView.section.connection.encryption.encrypt.info.link=\u0412\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 \u0441\u0430\u0439\u0442 \u0434\u043b\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c MainWindow.sr.status.tooltip.ok=\u041a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 %1 \u0433\u0430\u0440\u043d\u0438\u0439 MainWindow.sr.status.tooltip.poor=\u041a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 %1 \u0437\u0430\u0434\u043e\u0432\u0456\u043b\u044c\u043d\u0438\u0439: < 0.5 MainWindow.sr.status.tooltip.bad=\u041a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 %1 \u043f\u043e\u0433\u0430\u043d\u0438\u0439: < 0.5 ConfigView.section.style.status=\u0414\u0456\u043b\u044f\u043d\u043a\u0430 \u0441\u0442\u0430\u043d\u0443: ConfigView.section.style.status.show_sr=\u041a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 ConfigView.section.style.status.show_nat=\u0421\u0442\u0430\u043d NAT ConfigView.section.style.status.show_ddb=\u0421\u0442\u0430\u043d \u0420\u0411\u0414 ConfigView.section.style.status.show_ipf=\u0421\u0442\u0430\u043d \u0444\u0456\u043b\u044c\u0442\u0440\u0443 IP ConfigView.section.connection.encryption.encrypt.group=\u0428\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0456 \u043f\u0440\u0438\u0445\u043e\u0432\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0430\u0444\u0456\u043a\u0443 ConfigView.section.connection.encryption.encrypt.fallback_info=\u0412\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0440\u0435\u0437\u0435\u0440\u0432\u0443\u0432\u0430\u043d\u043d\u044f \u0434\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u044c \u0437'\u0454\u0434\u043d\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u0437 \u043d\u0435\u0441\u0443\u043c\u0456\u0441\u043d\u0438\u043c\u0438 \u043a\u043b\u0456\u0454\u043d\u0442\u0430\u043c\u0438, \u0442\u0430 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u044c \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f ConfigView.section.connection.encryption.encrypt.fallback_outgoing=\u0414\u043e\u0437\u0432\u043e\u043b\u044f\u0442\u0438 \u043d\u0435\u0437\u0430\u0445\u0438\u0449\u0435\u043d\u0456 \u0432\u0438\u0445\u0456\u0434\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f, \u044f\u043a\u0449\u043e \u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0456 \u0437\u0430\u0445\u0438\u0449\u0435\u043d\u0456 ConfigView.section.connection.encryption.encrypt.fallback_incoming=\u0414\u043e\u0437\u0432\u043e\u043b\u044f\u0442\u0438 \u043d\u0435\u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0456 \u0432\u0445\u0456\u0434\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f ConfigView.section.connection.encryption=\u0428\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0430\u0444\u0456\u043a\u0443 upnp.selectedinterfaces=\u0412\u0438\u0431\u0440\u0430\u043d\u0456 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0438 (';' =\u0440\u043e\u0437\u0434\u0456\u043b\u0435\u043d\u0456, \u0442\u043e\u0431\u0442\u043e, eth0;eth1) [\u043f\u043e\u0440\u043e\u0436\u043d\u0454: \u0432\u0441\u0456] ConfigView.section.style.defaultSortOrder=\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0441\u043e\u0440\u0442\u0443\u0432\u0430\u043d\u043d\u044f, \u044f\u043a\u0438\u0439 \u0437\u0432\u0438\u0447\u0430\u0439\u043d\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f ConfigView.section.style.defaultSortOrder.desc=\u0417\u043c\u0435\u043d\u0448\u0443\u0432\u0430\u043d\u0438\u0439 ConfigView.section.style.defaultSortOrder.asc=\u0417\u0431\u0456\u043b\u044c\u0448\u0443\u0432\u0430\u043d\u0438\u0439 ConfigView.section.style.defaultSortOrder.flip=\u041f\u0440\u043e\u0442\u0438\u043b\u0435\u0436\u043d\u0438\u0439 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u043d\u044c\u043e\u043c\u0443 LoggerView.autoscroll=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u043f\u0440\u043e\u043a\u0440\u0443\u0447\u0443\u0432\u0430\u043d\u043d\u044f Button.selectAll=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0432\u0441\u0435 Button.markSelected=\u041f\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0435 Button.unmarkSelected=\u0417\u043d\u044f\u0442\u0438 \u043f\u043e\u0437\u043d\u0430\u0447\u043a\u0443 \u0437 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0445 plugins.basicview.config=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f TorrentOptionsView.param.max.uploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0441\u043b\u043e\u0442\u0456\u0432 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 [\u043c\u0456\u043d\u0456\u043c\u0443\u043c: 2] MyTorrentsView.dialog.setPosition.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u043e\u0437\u0438\u0446\u0456\u044e MyTorrentsView.dialog.setPosition.text=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c \u043f\u043e\u0437\u0438\u0446\u0456\u044e \u0434\u043b\u044f \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432, \u0432\u043a\u0430\u0437\u0430\u0432\u0448\u0438 \u0457\u0457: MyTorrentsView.menu.reposition.manual=\u0412\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f.. ConfigView.section.connection.advanced.info.link=\u0412\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 \u0441\u0430\u0439\u0442 \u0434\u043b\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c ConfigView.section.connection.advanced.socket.group=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0441\u043e\u043a\u0435\u0442\u0443 ConfigView.section.connection.advanced.bind_port=\u0417\u0432'\u044f\u0437\u0430\u0442\u0438 \u0437 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0438\u043c \u043f\u043e\u0440\u0442\u043e\u043c [0: \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438] ConfigView.section.connection.advanced.bind_port.tooltip=\u0412\u0438\u0445\u0456\u0434\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0431\u0443\u0434\u0443\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0432'\u044f\u0437\u0430\u043d\u0456 \u0437 \u0437\u0430\u0434\u0430\u043d\u0438\u043c \u043f\u043e\u0440\u0442\u043e\u043c.\n\u0412\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u043c\u043e\u0436\u0435 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u0438 \u043d\u0435\u0441\u0442\u0430\u0431\u0456\u043b\u044c\u043d\u0443 \u0440\u043e\u0431\u043e\u0442\u0443 \u0440\u043e\u0443\u0442\u0435\u0440\u0430 NAT. ConfigView.section.proxy.group.tracker=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u043c ConfigView.section.proxy.group.peer=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438 Pieces.column.Requested=\u0417\u0430\u043f\u0438\u0442 Pieces.column.Requested.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438, \u0447\u0438 \u0431\u0456\u043b\u044c\u0448\u0435 \u0437\u0430\u043f\u0438\u0442\u0456\u0432 \u043c\u043e\u0433\u043b\u0438 \u0432\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u0434\u043e \u0447\u0430\u0441\u0442\u0438\u043d\u0438 (*) ConfigView.label.maxuploadsseeding=\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0438\u0439 \u0432\u0430\u0440\u0456\u0430\u043d\u0442 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 MyTorrentsView.filter=\u0424\u0456\u043b\u044c\u0442\u0440: popup.error.hideall=\u0421\u0445\u043e\u0432\u0430\u0442\u0438 \u0432\u0441\u0435 ConfigView.section.style.dataStatsOnly=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e \u0434\u0430\u043d\u0438\u043c (\u043f\u0440\u0438\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443) ConfigView.section.style.separateProtDataStats=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0456\u0432 \u0456 \u0434\u0430\u043d\u0438\u0445 \u044f\u043a '\u0434\u0430\u043d\u0456 (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b)' MyTorrentsView.dialog.setFilter.title=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u0444\u0456\u043b\u044c\u0442\u0440 MyTorrentsView.dialog.setFilter.text=%1 \u0441\u0435\u043a\u0446\u0456\u044f \u0444\u0456\u043b\u044c\u0442\u0440\u0443\u0432\u0430\u0442\u0438\u043c\u0435 \u0442\u0435\u043a\u0441\u0442, \u044f\u043a\u0438\u0439 \u0432\u0438 \u0432\u043a\u0430\u0436\u0435\u0442\u0435 \u043d\u0438\u0436\u0447\u0435 . \u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u0441\u0438\u043c\u0432\u043e\u043b | , \u0449\u043e\u0431 \u0440\u043e\u0437\u0434\u0456\u043b\u0438\u0442\u0438 \u043a\u0456\u043b\u044c\u043a\u0430 \u0444\u0440\u0430\u0437. MyTorrentsView.filter.tooltip=Ctrl+X \u043f\u0435\u0440\u0435\u043c\u0438\u043a\u0430\u0454 \u0440\u0435\u0436\u0438\u043c\u0438 \u043f\u043e\u0448\u0443\u043a\u0443 \u043c\u0456\u0436 RegEx \u0456 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u0438\u043c.\n\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u0441\u0438\u043c\u0432\u043e\u043b | \u0449\u043e\u0431 \u0444\u0456\u043b\u044c\u0442\u0440\u0443\u0432\u0430\u0442\u0438 \u0444\u0440\u0430\u0437\u0438, \u044f\u043a\u0456 \u0441\u043a\u043b\u0430\u0434\u0430\u044e\u0442\u044c\u0441\u044f \u0437 \u0434\u0435\u043a\u0456\u043b\u044c\u043a\u043e\u0445 \u0441\u043b\u0456\u0432. MyTorrentsView.clearFilter.tooltip=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0444\u0456\u043b\u044c\u0442\u0440 MyTorrentsView.menu.filter=\u0421\u043f\u0438\u0441\u043e\u043a \u0444\u0456\u043b\u044c\u0442\u0440\u0456\u0432... ConfigView.section.file.resume.recheck.all=\u041f\u0440\u0438 \u0437\u0431\u043e\u0457 \u0456 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u0432\u0435\u0441\u044c \u0444\u0430\u0439\u043b \u043d\u0430 \u0446\u0456\u043b\u0456\u0441\u043d\u0456\u0441\u0442\u044c \u0447\u0430\u0441\u0442\u0438\u043d (\u0412 \u0456\u043d\u0448\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u043b\u0438\u0448\u0435 \u043e\u0441\u0442\u0430\u043d\u043d\u0456 \u0430\u043a\u0442\u0438\u0432\u043d\u0456 \u0447\u0430\u0441\u0442\u0438\u043d\u0438 \u0431\u0443\u0434\u0443\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0435\u043d\u0456) ConfigureWizard.language.choose=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043c\u043e\u0432\u0443 \u0437 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u043e\u0433\u043e \u043d\u0438\u0436\u0447\u0435 \u0441\u043f\u0438\u0441\u043a\u0443: popup.closing.in=\u0412\u0456\u043a\u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u043a\u0440\u0438\u0454\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 %1 \u0441\u0435\u043a\u0443\u043d\u0434(\u0443) popup.more.waiting=%1 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f(\u044c).. # > 2402 popup.download.finished="%1" \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0432 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. popup.file.finished="%1" \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0435. ConfigView.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e Plugin.localtracker.autoadd.info=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0434\u043e\u0434\u0430\u0432\u0430\u0442\u0438 \u0446\u0438\u0445 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0438\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 [';' \u0440\u043e\u0437\u0434\u0456\u043b\u0435\u043d\u0438\u0445 \u0430\u0434\u0440\u0435\u0441\u0430\u043c\u0438, \u0442\u043e\u0431\u0442\u043e, 1.2.3.4] Plugin.localtracker.autoadd=\u041e\u0441\u043e\u0431\u043b\u0438\u0432\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438 Plugin.localtracker.networks.info=\u0406\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0443\u0432\u0430\u0442\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043c\u0435\u0440\u0435\u0436\u0456 \u044f\u043a \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456 [';' \u0440\u043e\u0437\u0434\u0456\u043b\u044f\u0442\u0438 \u043c\u0435\u0440\u0435\u0436\u0456, \u0442\u043e\u0431\u0442\u043e, 145.227.*.*] Plugin.localtracker.networks=\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0456 \u043c\u0435\u0440\u0435\u0436\u0456 MainWindow.menu.view.plugins.logViews=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 \u0444\u0430\u0439\u043b\u0456\u0432 .log SpeedView.stats.autospeed=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 SpeedView.stats.autospeed.disabled=\u0426\u044f \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u0442\u0435\u0436 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0430 (\u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0438\u0439 DHT), \u0430\u0431\u043e \u0457\u0457 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438 (\u0432\u0438\u0431\u0440\u0430\u043d\u0430 \u0440\u0443\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456) SpeedView.stats.idlePing=\u0412\u0456\u043b\u044c\u043d\u0438\u0439 \u043f\u0456\u043d\u0433: SpeedView.stats.maxPing=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u043f\u0456\u043d\u0433: SpeedView.stats.currentPing=\u041f\u043e\u0442\u043e\u0447\u043d\u0438\u0439 \u043f\u0456\u043d\u0433: SpeedView.stats.maxUp=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043c\u0435\u0436\u0430 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456: ConfigView.pluginlist.unloadSelected=\u0412\u0438\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0456 ConfigView.pluginlist.scan=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u043d\u043e\u0432\u0438\u0445 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c ConfigView.section.transfer.autospeed=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c (\u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0430) ConfigView.section.transfer.autospeed.tooltip=\u0421\u043f\u0435\u0446\u0456\u0430\u043b\u044c\u043d\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 ConfigView.section.transfer.autospeed.info=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0440\u0435\u0433\u0443\u043b\u044e\u0454 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0449\u043e\u0431 \u0443\u043d\u0438\u043a\u043d\u0443\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f.\n\n\u0426\u0456 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0430\u0441\u0442\u043e\u0441\u043e\u0432\u0430\u043d\u0456, \u043b\u0438\u0448\u0435 \u043a\u043e\u043b\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0430 \u0456 \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u043e\u0457 \u0431\u0430\u0437\u0438 \u0434\u0430\u043d\u0438\u0445 \u0434\u043b\u044f \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f.\n ConfigView.section.transfer.autospeed.minupload=\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, %1 ConfigView.section.transfer.autospeed.minupload.tooltip=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0435 \u0431\u0443\u0434\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u0430 \u043d\u0438\u0436\u0447\u0435 \u0446\u044c\u043e\u0433\u043e \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f ConfigView.section.transfer.autospeed.maxupload=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, %1 [0: \u043d\u0435 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] ConfigView.section.transfer.autospeed.maxupload.tooltip=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0435 \u0431\u0443\u0434\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0431\u0456\u043b\u044c\u0448\u0435\u043d\u0430 \u0431\u0456\u043b\u044c\u0448\u0435 \u0446\u044c\u043e\u0433\u043e \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f ConfigView.section.transfer.autospeed.chokeping=\u0427\u0430\u0441 \u0437\u0430\u0442\u0443\u0445\u0430\u043d\u043d\u044f \u043f\u0456\u043d\u0433\u0443 [\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434] ConfigView.section.transfer.autospeed.chokeping.tooltip=\u041d\u0430\u0434\u043b\u0438\u0448\u043e\u043a \u043f\u0456\u043d\u0433\u0443 \u0446\u044c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0431\u0443\u0434\u0435 \u0432\u0432\u0430\u0436\u0430\u0442\u0438\u0441\u044f, \u044f\u043a \u0456\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u043c\u0435\u0440\u0435\u0436\u0435\u0432\u043e\u0457 \u043d\u0430\u0441\u0438\u0447\u0435\u043d\u043e\u0441\u0442\u0456 ConfigView.section.transfer.autospeed.enableauto=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438, \u043a\u043e\u043b\u0438 \u0442\u0440\u0438\u0432\u0430\u0454 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0430 ConfigView.section.transfer.autospeed.enableautoseeding=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438, \u043b\u0438\u0448\u0435 \u043a\u043e\u043b\u0438 \u0442\u0440\u0438\u0432\u0430\u0454 \u0440\u043e\u0437\u0434\u0430\u0447\u0430 ConfigView.pluginlist.column.unloadable=\u041d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u044c\u0441\u044f ConfigView.section.transfer.lan.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043e\u043a\u0440\u0435\u043c\u0435 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0434\u043b\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u044c \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456 Plugin.localtracker.wellknownlocals=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0432 \u0441\u043e\u0431\u0456 \u043a\u043e\u043d\u0442\u0443\u0440 \u0437\u0432\u043e\u0440\u043e\u0442\u043d\u043e\u0433\u043e \u0437\u0432'\u044f\u0437\u043a\u0443/\u0437\u0432'\u044f\u0437\u043e\u043a/\u0441\u0430\u0439\u0442\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0438\u0445 \u043c\u0435\u0440\u0435\u0436 (192.168 \u0442\u043e\u0449\u043e) TableColumn.header.filesdone=\u0424\u0430\u0439\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 TableColumn.header.filesdone.info=\u0424\u0430\u0439\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456/\u0432\u0441\u044c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0456\u0432 *\u0430\u0431\u043e* \u043d\u0435 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 (\u0444\u0430\u0439\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456)/\u0432\u0441\u044c\u043e\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 (\u0432\u0441\u044c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0456\u0432) MagnetPlugin.private_torrent=<\u043e\u0441\u043e\u0431\u0438\u0441\u0442\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442> MagnetPlugin.decentral_disabled=<\u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0456\u043d\u0433 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438\u0439> MagnetPlugin.decentral_backup_disabled=< \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0440\u0435\u0437\u0435\u0440\u0432 \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438\u0439 > MagnetPlugin.report.waiting_ddb=\u0447\u0435\u043a\u0430\u0454 \u0434\u043b\u044f \u0456\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u0457 DDB... MagnetPlugin.report.searching=\u043f\u043e\u0448\u0443\u043a... MagnetPlugin.report.found=\u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e %1 MagnetPlugin.report.alive=%1 \u0436\u0438\u0432\u0438\u0445 MagnetPlugin.report.dead=%1 \u043c\u0435\u0440\u0442\u0432\u0438\u0445 MagnetPlugin.report.tunnel=\u0442\u0443\u043d\u0435\u043b\u044e\u0432\u0430\u043d\u043d\u044f \u0432 %1 MagnetPlugin.report.downloading=\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u044c\u0441\u044f \u0437 %1 MagnetPlugin.report.error=\u043f\u043e\u043c\u0438\u043b\u043a\u0430 %1 MagnetURLHandler.report.no_sources=\u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0434\u0436\u0435\u0440\u0435\u043b \u0442\u043e\u0440\u0435\u043d\u0442\u0443 MagnetURLHandler.report.torrent_size=\u0440\u043e\u0437\u043c\u0456\u0440 \u0442\u043e\u0440\u0435\u043d\u0442\u0443: %1 MagnetURLHandler.report.percent=\u0432\u0438\u043a\u043e\u043d\u0430\u043d\u043e: %1% MagnetURLHandler.report.error=\u043f\u043e\u043c\u0438\u043b\u043a\u0430 %1 DHTTransport.report.request_all=\u0437\u0430\u043f\u0438\u0442 \u043f\u043e\u0432\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437 %1 DHTTransport.report.received_bit=\u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043e %1 \u0432 %2 \u0437 %3 DHTTransport.report.complete=\u043a\u0456\u043d\u0435\u0446\u044c DHTTransport.report.timeout=\u0447\u0430\u0441 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f, \u043d\u0435\u043c\u0430 \u0432\u0456\u0434\u0433\u0443\u043a\u0456\u0432 \u0432\u0456\u0434 %1 DHTTransport.report.rerequest_all=\u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0438\u0439 \u0437\u0430\u043f\u0438\u0442 \u043f\u043e\u0432\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437 %1 DHTTransport.report.rerequest_bit=\u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0438\u0439 \u0437\u0430\u043f\u0438\u0442 %1 \u0432 %2 \u0437 %3 DHTTransport.report.timeout_some=\u0447\u0430\u0441 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f, %1 \u043f\u0430\u043a\u0435\u0442\u0456\u0432 \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043e \u0432\u0456\u0434 %2, \u0430\u043b\u0435 \u0446\u0435 \u043d\u0435 \u043a\u0456\u043d\u0435\u0446\u044c DHTTransport.report.sending=\u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445 DHTTransport.report.resending=\u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0435 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445 DHTTransport.report.send_complete=\u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435 DHTTransport.report.send_timeout=\u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0447\u0430\u0441\u0443 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f ConfigView.section.transfer.autospeed.enabledebug=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u0432 .log \u043f\u043e\u043c\u0438\u043b\u043a\u0438 \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f TableColumn.header.date_added=\u0414\u0430\u0442\u0430 \u0434\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u044f TableColumn.header.date_added.info=\u0414\u0430\u0442\u0430 \u0434\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 ConfigView.section.file.hashchecking.smallestfirst=\u0421\u043f\u043e\u0447\u0430\u0442\u043a\u0443 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043d\u0430\u0439\u043c\u0435\u043d\u0448\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f platform.win32.baddll.info=Vuze \u0432\u0438\u044f\u0432\u0438\u0432 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c '%1'. \u0426\u0435 \u0447\u0430\u0441\u0442\u0438\u043d\u0430 '%2' \u0456 \u043c\u043e\u0436\u0435 \u0432\u0438\u043a\u043b\u0438\u043a\u0430\u0442\u0438 \u0441\u0435\u0440\u0439\u043e\u0437\u043d\u0456 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438, \u0442\u0430\u043a\u0456 \u044f\u043a \u043a\u0440\u0430\u0445 \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u043d\u043a\u0443 \u0456 \u0432\u0438\u0441\u043e\u043a\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0426\u041f\u0423. \u042f\u043a\u0449\u043e \u0412\u0438 \u0437\u0456\u0448\u0442\u043e\u0432\u0445\u043d\u0435\u0448\u0441\u044f \u0437 \u043d\u0438\u043c\u0438, \u0442\u043e\u0434\u0456 \u0432\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0430\u0431\u043e \u0457\u0445 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f, \u0449\u043e\u0431 \u043d\u0435 \u0437\u0456\u043f\u0441\u0443\u0432\u0430\u0442\u0438 Vuze. upnp.ignorebaddevices=\u0406\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457, \u044f\u043a\u0456 \u0432\u0456\u0434\u043c\u043e\u0432\u043b\u044f\u044e\u0442\u044c\u0441\u044f \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0430\u0442\u0438 \u043a\u043e\u0440\u0435\u043a\u0442\u043d\u043e upnp.ignorebaddevices.info=\u041f\u043e\u0442\u043e\u0447\u043d\u0456 \u0456\u0433\u043d\u043e\u0440\u043e\u0432\u0430\u043d\u0456 \u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457: %1 upnp.ignorebaddevices.reset=\u0421\u043a\u0438\u0434\u0430\u043d\u043d\u044f \u0441\u043f\u0438\u0441\u043a\u0443 \u0456\u0433\u043d\u043e\u0440\u043e\u0432\u0430\u043d\u0438\u0445 \u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457\u0432 upnp.ignorebaddevices.reset.action=\u0421\u043a\u0438\u0434\u0430\u043d\u043d\u044f upnp.ignorebaddevices.alert=Upn-\u043f\u0440\u0438\u0441\u0442\u0440\u0456\u0439 \u043d\u0430 \u043c\u0456\u0441\u0446\u0456 %1 \u0431\u0443\u0432 \u0456\u0433\u043d\u043e\u0440\u043e\u0432\u0430\u043d\u0438\u0439 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0438\u043c\u0438 \u0432\u0456\u0434\u043c\u043e\u0432\u0430\u043c\u0438. \u041e\u0437\u043d\u0430\u0439\u043e\u043c\u0442\u0435\u0441\u044f \u0437 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0454\u044e Upn-\u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c \u0434\u043b\u044f \u043e\u043f\u0446\u0456\u0439, \u044f\u043a\u0456 \u0432\u0456\u0434\u043d\u043e\u0441\u044f\u0442\u044c\u0441\u044f \u0434\u043e \u0434\u0456\u0457. TorrentOptionsView.param.max.uploads.when.busy=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u043a\u043e\u043b\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0435 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0434\u043e\u0441\u044f\u0433\u043d\u0443\u0442\u0435, \u041a\u0431\u0456\u0442/\u0441 [0: \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0430] UpdateMonitor.messagebox.verification.failed.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043d\u0435 \u043f\u0440\u043e\u0439\u0448\u043b\u043e \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 UpdateMonitor.messagebox.verification.failed.text=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 '%1' \u043d\u0435\u0432\u0434\u0430\u043b\u0430 : %2 UpdateMonitor.messagebox.accept.unverified.title=\u0417\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438 \u043d\u0435\u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0435\u043d\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f UpdateMonitor.messagebox.accept.unverified.text='%1' \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u043d\u0435 \u043e\u0444\u0456\u0446\u0456\u0439\u043d\u0438\u043c \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f Vuze .\n\u042f\u043a\u0449\u043e \u0446\u0435 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0442\u0430\u043a\u0435 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f, \u0412\u0430\u043c \u043d\u0435 \u0441\u043b\u0456\u0434 \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0443\u0432\u0430\u0442\u0438.\n\u041f\u0440\u043e\u0434\u043e\u0432\u0436\u0438\u0442\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f? FileView.BlockView.title=\u0427\u0430\u0441\u0442\u0438\u043d\u0438 \u0444\u0430\u0439\u043b\u0443 FileView.BlockView.Done=\u0412\u0438\u043a\u043e\u043d\u0430\u043d\u0438\u0445 FileView.BlockView.Skipped=\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u0438\u0445 FileView.BlockView.Active=\u0410\u043a\u0442\u0438\u0432\u043d\u0438\u0445 FileView.BlockView.Outstanding=\u041d\u0435\u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0438\u0445 ConfigView.label.tcplistenport=TCP-\u043f\u043e\u0440\u0442 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c ConfigView.label.udplistenport=UDP-\u043f\u043e\u0440\u0442 upnp.portchange.alert=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u043e\u0440\u0442\u0438 \u0437\u043c\u0456\u043d\u0435\u043d\u0456, \u0449\u043e\u0431 \u0443\u043d\u0438\u043a\u043d\u0443\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 UPn -\u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457\u0432: %1 [\u0441\u0442\u0430\u0440\u0438\u0439 \u043f\u043e\u0440\u0442=%2] %3 [\u0441\u0442\u0430\u0440\u0438\u0439 \u043f\u043e\u0440\u0442=%4] ConfigView.section.proxy.username.info=\u042f\u043a\u0449\u043e \u043f\u0440\u043e\u043a\u0441\u0456-\u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0456\u0457, \u043d\u0430\u0432\u0456\u0442\u044c \u043a\u043e\u043b\u0438 \u043d\u0435 \u0432\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0439\u0442\u0435 \u0440\u044f\u0434\u043e\u043a "" \u044f\u043a \u0406\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 ConfigView.label.maxuploadswhenbusymin=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443, \u043a\u043e\u043b\u0438 \u0437\u0430\u0439\u043d\u044f\u0442\u0438\u0439. \u0422\u0430\u0439\u043c\u0435\u0440, \u0441 MainWindow.menu.help.debug=\u0413\u0435\u043d\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f DownloadManager.error.badsize=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440 natpmp.info=NAT-PMP - \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 Apple \u0434\u043b\u044f UPn\u0420 \u0456 \u0434\u043b\u044f \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0438 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u043c\u0438 \u0441\u0442\u0430\u043d\u0446\u0456\u044f\u043c\u0438 Airport \n\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0437\u0430\u0440\u0430\u0437 UPn \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0435, \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438\u0439 NAT-PMP \u044f\u043a \u043d\u043e\u0441\u0456\u0439 NAT-PMP \u0440\u043e\u0437\u0433\u043b\u044f\u043d\u0443\u0442\u0438\u0439 \u044f\u043a \u043e\u0441\u043e\u0431\u043b\u0438\u0432\u0438\u0439 \u0442\u0438\u043f \u043d\u043e\u0441\u0456\u044f Upn natpmp.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 (\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0442\u0430\u043a\u043e\u0436 \u043f\u043e\u0432\u0438\u043d\u043d\u0438\u0439 \u0431\u0443\u0442\u0438 \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0438\u043c \u0443 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457 Airport, \u0449\u043e\u0431 \u043f\u0440\u0430\u0446\u044e\u0432\u0430\u0442\u0438) ConfigView.section.tracker.host.addurls=\u0412\u043f\u0435\u0432\u043d\u0438\u0442\u0438\u0441\u044f, \u0449\u043e \u043b\u0456\u043d\u043a\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u043d\u0430\u044f\u0432\u043d\u0456 \u0432 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u0445, \u044f\u043a\u0456 \u043f\u0440\u0438\u0439\u043c\u0430\u044e\u0442\u044c\u0441\u044f ConfigView.filter=\u0444\u0456\u043b\u044c\u0442\u0440 ConfigView.section.files.move=\u041f\u0435\u0440\u0435\u043c\u0456\u0449\u0435\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0445 ConfigView.section.file.defaultdir.section=\u041e\u043f\u0446\u0456\u0457 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0457 \u0442\u0435\u043a\u0438 ConfigView.section.file.defaultdir.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443 \u0442\u0435\u043a\u0443 (\u0431\u0435\u0437 \u0448\u043b\u044f\u0445\u0443) ConfigView.section.file.defaultdir.bestguess=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u043a\u0440\u0430\u0449\u0438\u0439 \u0432\u0430\u0440\u0456\u0430\u043d\u0442 \u043f\u0440\u0438 \u0432\u0438\u0431\u043e\u0440\u0456 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0457 \u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f ConfigView.section.file.defaultdir.ask=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430 \u0442\u0435\u043a\u0430: ConfigView.section.file.defaultdir.lastused=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443 \u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f \u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0433\u043e \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f ConfigView.section.file.config.section=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457 ConfigView.section.file.config.currentdir=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u0442\u0435\u043a\u0430 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457: ConfigView.section.torrent.decoding=\u0414\u0435\u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0430\u0431\u043e\u0440\u0443 \u0441\u0438\u043c\u0432\u043e\u043b\u0456\u0432 ConfigView.section.logging.udptransport=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u0435 \u0442\u0440\u0430\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456 UDP Tracker.announce.ignorePeerSeed=\u0406\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 \u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0434\u043e \u0441\u0456\u0434\u0435\u0440\u0456\u0432. %1 ConfigView.section.connection.encryption.use_crypto_port=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u0440\u0442 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430, \u0449\u043e\u0431 \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u043f\u0440\u044f\u043c\u0438\u0445 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u0441\u043f\u0440\u043e\u0431 \u0437\u2019\u0454\u0434\u043d\u0430\u043d\u043d\u044f. \n\n\u0414\u0435\u044f\u043a\u0456 \u0442\u0440\u0435\u043a\u0435\u0440\u0438 \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u044c \u0446\u044c\u043e\u0433\u043e \u0456 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u044e\u0442\u044c \u043f\u0440\u043e \u0442\u0430\u043a\u0456 \u043f\u043e\u043c\u0438\u043b\u043a\u0438, \u044f\u043a "\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 \u043f\u043e\u0440\u0442" \u0430\u0431\u043e "\u041d\u0435\u043f\u0440\u0438\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440" TorrentOptionsView.param.reset.to.default=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0456 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 TorrentOptionsView.param.reset.button=\u0421\u043a\u0438\u043d\u0443\u0442\u0438 natpmp.routeraddress=\u0410\u0434\u0440\u0435\u0441\u0430 \u0441\u0442\u0430\u043d\u0446\u0456\u0457 [\u043f\u043e\u0440\u043e\u0436\u043d\u0454: \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e] ConfigView.section.style.disableAlertSliding=\u0412\u0438\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043b\u0430\u0432\u043d\u0443 \u0430\u043d\u0456\u043c\u0430\u0446\u0456\u044e \u0456 \u0440\u0435\u0436\u0438\u043c '\u0437\u0433\u043e\u0440\u0438 \u0432\u0441\u0456\u0445' \u0434\u043b\u044f \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c ConfigView.section.transfer.autospeed.maxinc=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0435 \u0437\u0431\u0456\u043b\u044c\u0448\u0435\u043d\u043d\u044f \u043d\u0430 \u0446\u0438\u043a\u043b, %1 ConfigView.section.transfer.autospeed.maxdec=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0435 \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u043d\u044f \u043d\u0430 \u0446\u0438\u043a\u043b, %1 ConfigView.section.transfer.autospeed.enabledownadj=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043a\u043e\u0440\u0435\u043a\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ConfigView.section.transfer.autospeed.downadjratio=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f : \u041a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456\n(\u0442\u043e\u0431\u0442\u043e, 2.0 - \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0434\u0432\u0456\u0447\u0456\n\u0431\u0456\u043b\u044c\u0448\u0435 \u0437\u0430 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456) ConfigView.section.transfer.autospeed.latencyfactor=\u041f\u043e\u043a\u0430\u0437\u043d\u0438\u043a \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0437\u043c\u0456\u043d\u0438 \u043b\u0430\u0442\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u0456 \u043c\u0435\u0440\u0435\u0436\u0456 \u0434\u043b\u044f \u0437\u043c\u0456\u043d\u0438 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456\n(\u0431\u0456\u043b\u044c\u0448\u0435 \u0447\u0438\u0441\u043b\u043e \u0437\u043c\u0435\u043d\u0448\u0443\u0454 \u0447\u0443\u0442\u043b\u0438\u0432\u0456\u0441\u0442\u044c) ConfigView.section.transfer.autospeed.reset=\u0421\u043a\u0438\u0434\u0430\u043d\u043d\u044f \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u044c ConfigView.section.transfer.autospeed.reset.button=\u0421\u043a\u0438\u043d\u0443\u0442\u0438 PeerColumn.activationCount=\u0423\u0447\u0430\u0441\u043d\u0438\u043a\u0438 \u043d\u0430\u043c\u0430\u0433\u0430\u044e\u0442\u044c\u0441\u044f \u0437'\u0454\u0434\u043d\u0430\u0442\u0438\u0441\u044f: %1 TableColumn.header.timesincedownload.info=\u0427\u0430\u0441, \u044f\u043a\u0438\u0439 \u043c\u0438\u043d\u0443\u0432 \u0437 \u0442\u0438\u0445 \u043f\u0456\u0440, \u044f\u043a \u0434\u0430\u043d\u0456 \u0431\u0443\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 TableColumn.header.timesincedownload=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f TableColumn.header.timesinceupload.info=\u0427\u0430\u0441, \u044f\u043a\u0438\u0439 \u043c\u0438\u043d\u0443\u0432 \u0437 \u0442\u0456\u0454\u0457 \u043f\u043e\u0440\u0438, \u044f\u043a \u0434\u0430\u043d\u0456 \u0431\u0443\u043b\u0438 \u0440\u043e\u0437\u0434\u0430\u043d\u0456 \u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 TableColumn.header.timesinceupload=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 PeersView.incomingreqcount=\u0412\u0445\u0456\u0434\u043d\u0456 \u0437\u0430\u043f\u0438\u0442\u0438 PeersView.incomingreqcount.info=\u041f\u0456\u0434\u0440\u0430\u0445\u0443\u043d\u043e\u043a \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u0437\u0430\u043f\u0438\u0442\u0456\u0432, \u0437\u0440\u043e\u0431\u043b\u0435\u043d\u0438\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c PeersView.outgoingreqcount=\u0412\u0438\u0445\u0456\u0434\u043d\u0456 \u0437\u0430\u043f\u0438\u0442\u0438 PeersView.outgoingreqcount.info=\u041f\u0456\u0434\u0440\u0430\u0445\u0443\u043d\u043e\u043a \u0432\u0438\u0445\u0456\u0434\u043d\u0438\u0445 \u0437\u0430\u043f\u0438\u0442\u0456\u0432, \u0437\u0440\u043e\u0431\u043b\u0435\u043d\u0438\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c upnp.mapping.trackerclientudp=\u041f\u043e\u0440\u0442 \u043a\u043b\u0456\u0454\u043d\u0442\u0430 UDP-\u0442\u0440\u0435\u043a\u0435\u0440\u0443 upnp.mapping.dhtudp=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u0438\u0445 ConfigView.section.connection.nondata.udp.same=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043e\u0434\u0438\u043d UDP-\u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u043e\u0457 \u0431\u0430\u0437\u0438 \u0434\u0430\u043d\u0438\u0445 \u0456 UDP-\u0442\u0440\u0435\u043a\u0435\u0440\u0443 ConfigView.section.connection.tcp.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 TCP ConfigView.section.connection.udp.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 UDP ConfigView.section.style.showiconbar=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432 MainWindow.menu.view.iconbar=\u041f\u0430\u043d\u0435\u043b\u044c \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432 MyTorrentsView.menu.rename=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 MyTorrentsView.menu.rename.displayed=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0432\u043a\u0430\u0437\u0430\u043d\u0435 \u0456\u043c'\u044f MyTorrentsView.menu.rename.save_path=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0448\u043b\u044f\u0445 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f MyTorrentsView.menu.rename.displayed.enter.title=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0432\u043a\u0430\u0437\u0430\u043d\u0435 \u0456\u043c'\u044f MyTorrentsView.menu.rename.displayed.enter.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043d\u043e\u0432\u0435 \u0456\u043c'\u044f, \u044f\u043a\u0435 \u0434\u0456\u044f\u0442\u0438\u043c\u0435 \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. MyTorrentsView.menu.edit_comment=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 MyTorrentsView.menu.edit_comment.enter.title=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 MyTorrentsView.menu.edit_comment.enter.message=\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. UIDebugGenerator.messageask.title=\u0413\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f UIDebugGenerator.messageask.text=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u043e\u043f\u0438\u0448\u0456\u0442\u044c \u043f\u043e\u043c\u0438\u043b\u043a\u0443 UIDebugGenerator.complete.title=\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0456\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u0430\u0441\u044f UIDebugGenerator.complete.text=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u0442\u0435 \u0444\u0430\u0439\u043b '%1' \u043d\u0430 az-bugreports@azureus-inc.com\n\n\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c O\u041a, \u0449\u043e\u0431 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0446\u0435\u0439 \u0444\u0430\u0439\u043b \u0432 \u0432\u0456\u043a\u043d\u0456. ConfigView.section.style.showProgramIcon=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0432 \u043d\u0430\u0437\u0432\u0456 \u0441\u0442\u043e\u0432\u043f\u0446\u044f ConfigView.section.style.showProgramIcon.tooltip=\u0412\u0438\u0433\u043b\u044f\u0434 \u043c\u043e\u0436\u0435 \u0432\u0438\u043c\u0430\u0433\u0430\u0442\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0442\u044f \u0434\u043b\u044f \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u043c\u0456\u043d swt.alert.cant.update=SWT-\u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0430, \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0430 \u0437 "%3" \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u0430 \u0437 \u0432\u0435\u0440\u0441\u0456\u0457 %1 \u0434\u043e %2 (\u043f\u043e\u0432\u0438\u043d\u043d\u0430 \u0431\u0443\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0430 \u0437 "%4"). \u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443 \u0434\u043b\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457. authenticator.savepassword=\u0417\u0430\u043f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u043c\u0456\u0439 \u043f\u0430\u0440\u043e\u043b\u044c ConfigView.section.security.clearpasswords=\u0421\u043a\u0438\u0434\u0430\u043d\u043d\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0445 \u043f\u0430\u0440\u043e\u043b\u0456\u0432 ConfigView.section.security.clearpasswords.button=\u0421\u043a\u0438\u043d\u0443\u0442\u0438 Content.alert.notuploaded.title=\u0420\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0435 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0456 Content.alert.notuploaded.text=\u0420\u043e\u0437\u0434\u0430\u0447\u0430 '%1' \u043d\u0435 \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u0430\u0441\u044f. \u042f\u043a\u0449\u043e \u0412\u0438 %2 \u0437\u0430\u0440\u0430\u0437, \u043b\u044e\u0434\u0438 \u043d\u0435 \u0437\u043c\u043e\u0436\u0443\u0442\u044c \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0432\u0430\u0448\u0443 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0443 \u0440\u043e\u0431\u043e\u0442\u0443.\n\n\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 %2? Content.alert.notuploaded.multi.title=\u0420\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0435 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0456 Content.alert.notuploaded.multi.text=%1 \u0432\u0430\u0448\u043e\u0457 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u043d\u0435 \u0432\u0456\u0434\u0434\u0430\u043d\u043e. \u042f\u043a\u0449\u043e \u0412\u0438 %2 \u0437\u0430\u0440\u0430\u0437, \u043b\u044e\u0434\u0438 \u043d\u0435 \u0437\u043c\u043e\u0436\u0443\u0442\u044c \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0432\u0430\u0448\u0443 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0443 \u0440\u043e\u0431\u043e\u0442\u0443. \u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 %2?\n\n\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0440\u043e\u0437\u0434\u0430\u043d\u0430 \u043d\u0435 \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e:\n%3 Content.alert.notuploaded.stop=\u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 Content.alert.notuploaded.quit=\u0432\u0438\u0439\u0442\u0438 TorrentInfoView.torrent.encoding=\u0428\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 TorrentInfoView.columns=\u0421\u0442\u043e\u0432\u043f\u0447\u0438\u043a\u0438 \u0437 \u0432\u0438\u0433\u043b\u044f\u0434\u0443 '\u041c\u043e\u0457 \u0422\u043e\u0440\u0435\u043d\u0442\u0438' progress.window.title=\u0422\u0440\u0438\u0432\u0430\u0454 progress.window.msg.filemove=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0437\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u043f\u043e\u043a\u0438 \u0444\u0430\u0439\u043b \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u043f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u044c\u0441\u044f \u0430\u0431\u043e \u043f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0454\u0442\u044c\u0441\u044f ConfigView.label.popup.timestamp=\u0414\u043e\u0434\u0430\u0442\u0438 \u0442\u0430\u0439\u043c\u0435\u0440 \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u043e\u0433\u043e \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f ConfigView.label.popup.autohide=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u0438\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0435\u0440\u0432\u0456\u0441\u043d\u0456 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f x \u0441\u0435\u043a\u0443\u043d\u0434 (0 \u0434\u043b\u044f \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u0445\u043e\u0432\u0443\u0432\u0430\u043d\u043d\u044f) ConfigView.label.popup.suppress_alerts=\u041f\u0440\u0438\u0441\u0456\u043a\u0442\u0438 \u0442\u0440\u0438\u0432\u043e\u0433\u0438 ConfigView.label.popup.use_message_boxes=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0456 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u0437\u0430\u043c\u0456\u0441\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043d\u0435\u0431\u0435\u0437\u043f\u0435\u043a\u0438. ConfigView.label.popup.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u043e\u0432\u0430\u043d\u0456 \u0434\u043e \u0446\u044c\u043e\u0433\u043e \u0447\u0430\u0441\u0443 \u0442\u0440\u0438\u0432\u043e\u0433\u0438 (\u044f\u043a\u0449\u043e \u0432\u043e\u043d\u0438 \u0431\u0443\u043b\u0438) ConfigView.label.popup.show.button=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 ConfigView.label.please.visit.here=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 \u0446\u0435 \u0434\u043b\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 ConfigView.section.ipfilter.enable.descriptionCache=\u0417\u0430\u043f\u0430\u043c'\u044f\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043e\u043f\u0438\u0441 IP \u0432 \u0442\u0438\u043c\u0447\u0430\u0441\u043e\u0432\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0456 ConfigView.section.ipfilter.enable.descriptionCache.tooltip=\u041a\u043e\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438\u0439, \u043e\u043f\u0438\u0441\u0438 \u043d\u0435 \u0437\u0430\u043f\u0430\u043c'\u044f\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0443\u0442\u044c\u0441\u044f OpenTorrentWindow.filesInfo=%1 \u0437 %2 \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456. OpenTorrentWindow.diskUsage=%1 \u0437 %2 ConfigView.label.openmytorrents=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 '\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438' \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0443 ConfigView.label.open_transfer_bar_on_start=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 ConfigView.section.style.DNDalwaysInIncomplete=\u0417\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0437 '\u043d\u0435\u0434\u043e\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u043c\u0438' \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u0432 \u0440\u043e\u0437\u0434\u0456\u043b\u0456 \u043d\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 '\u041c\u043e\u0457\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432' OpenTorrentWindow.mb.noGlobalDestDir.title=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f OpenTorrentWindow.mb.noGlobalDestDir.text=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u043d\u0435 \u0456\u0441\u043d\u0443\u0454 \u0430\u0431\u043e \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430. OpenTorrentWindow.mb.noDestDir.title=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0430 OpenTorrentWindow.mb.noDestDir.text=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 '%2' \u043d\u0435 \u0456\u0441\u043d\u0443\u0454 \u0430\u0431\u043e \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430. OpenTorrentWindow.mb.notValid.title=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 OpenTorrentWindow.mb.notValid.text=\u041d\u0435 \u043c\u043e\u0436\u0443 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 '%1'. \u042f\u043a\u0449\u043e \u0412\u0438 \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0454\u0442\u0435 \u0432 \u0440\u0435\u0436\u0438\u043c\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u043f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0439\u0442\u0435\u0441\u044f, \u0449\u043e \u0444\u0430\u0439\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0456\u0441\u043d\u0443\u044e\u0442\u044c. OpenTorrentWindow.mb.notTorrent.title=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 OpenTorrentWindow.mb.notTorrent.text=\u041d\u0435 \u043c\u043e\u0436\u0443 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 '%1'. \u0412\u0456\u043d \u043d\u0435 \u0437'\u044f\u0432\u043b\u044f\u0454\u0442\u044c\u0441\u044f \u0443 \u0432\u0438\u0433\u043b\u044f\u0434\u0456 \u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b\u0443.\n\n\u0414\u0435\u044f\u043a\u0456 \u0434\u0430\u043d\u0456 \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u0456:\n%2 ConfigView.label.pause.downloads.on.exit=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u0456 ConfigView.label.resume.downloads.on.start=\u0412\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 \u0437\u0443\u043f\u0438\u043d\u0435\u043d\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0456\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u0457 UIDebugGenerator.message.cancel.title=\u0417\u0431\u0456\u0440 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0438\u0439 UIDebugGenerator.message.cancel.text=\u0412\u0438 \u043d\u0435 \u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u043f\u043e\u043c\u0438\u043b\u043a\u0443, \u043f\u0440\u043e \u044f\u043a\u0443 \u0412\u0438 \u043d\u0430\u043c\u0430\u0433\u0430\u0454\u0442\u0435\u0441\u044f \u0440\u043e\u0437\u043f\u043e\u0432\u0456\u0441\u0442\u0438. \u0412\u0430\u0448\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u044e \u0434\u043b\u044f \u0412\u0430\u0441, \u0430\u043b\u0435 \u0431\u0435\u0437 \u043e\u043f\u0438\u0441\u0443 \u043c\u0438 \u0437\u043c\u043e\u0436\u0435\u043c\u043e \u043b\u0438\u0448\u0435 \u043b\u0430\u043c\u0430\u0442\u0438 \u0433\u043e\u043b\u043e\u0432\u0443, \u0432 \u0447\u043e\u043c\u0443 \u0436 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430.\n\n\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0456\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0430. ConfigView.section.connection.group.http.info=\u041f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0430 HTTP-\u0440\u043e\u0437\u0434\u0430\u0447\u0456. ConfigView.section.connection.http.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 ConfigView.section.connection.http.port=\u041d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0443 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c ConfigView.section.connection.http.portoverride=\u0417\u0430\u043c\u0456\u043d\u0438\u0442\u0438 HTTP-\u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u043d\u0430 [0: \u043d\u0456\u044f\u043a\u0438\u0439] window.update.noupdates.title=\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c window.update.noupdates.text=\u041d\u0435\u043c\u0430 \u043d\u043e\u0432\u0438\u0445 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c.\n\n ConfigView.label.bindip.details=\u0414\u043b\u044f \u043f\u0440\u0438\u043a\u043b\u0430\u0434\u0443: 192.168.1.5;eth0;eth1[2] \u0437\u0432'\u044f\u0436\u0435 \u0432\u043a\u0430\u0437\u0430\u043d\u0456 IP - \u0432\u0441\u0456 IP \u0437 1-\u0433\u043e \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u0456 3-\u0442\u0454 IP 2-\u0433\u043e \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443.\n1-\u0439 IP \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0432\u0441\u0456\u0445 \u043f\u043e\u0441\u043b\u0443\u0433, \u0432\u0441i \u0456\u043d\u0448\u0456 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0443\u0442\u044c\u0441\u044f \u043b\u0438\u0448\u0435 \u0434\u043b\u044f \u0431\u0430\u043b\u0430\u043d\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.\n\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456:\n%1 ConfigView.label.mindownloads=\u041c\u0456\u043d\u0456\u043c\u0443\u043c \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u0438\u0445 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c UI.cannot_submit_blank_text=\u0412\u0438 \u043c\u0430\u0454\u0442\u0435 \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f. crypto.alert.as.warning=\u041c\u0435\u0440\u0435\u0436\u0456 '%1' \u0432\u0456\u0434\u043e\u043c\u043e, \u0449\u043e\u0431 \u0444\u0456\u043a\u0441\u0443\u0432\u0430\u0442\u0438 \u0444\u043e\u0440\u043c\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0430\u0444\u0456\u043a\u0443, \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0441\u043a\u043e\u0440\u043e\u0442\u0438\u0442\u0438 \u0435\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. \u0428\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0431\u0443\u043b\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438\u043c - \u0456 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0435/\u0437\u043c\u0456\u043d\u0435\u043d\u0435 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0456\u0432 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457. ConfigView.section.interface.alerts=\u041f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u043d\u044f ConfigView.label.popupdownloadadded=\u0412\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f, \u043a\u043e\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u043e\u0434\u0430\u043d\u0435 popup.download.added="%1" \u0431\u0443\u0432 \u0434\u043e\u0434\u0430\u043d\u0438\u0439 \u0443 \u0442\u0432\u0456\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. MessageBoxWindow.nomoreprompting=\u041d\u0435 \u043d\u0430\u0433\u0430\u0434\u0443\u0432\u0430\u0442\u0438 \u043c\u0435\u043d\u0456 \u0437\u043d\u043e\u0432\u0443 TorrentOptionsView.param.max.seeds=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437'\u0454\u0434\u043d\u0430\u043d\u044c \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] TorrentOptionsView.param.alternative.value.enable=\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u0456\u0434 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 ConfigView.section.proxy.check.on.start=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u044f\u0442\u0438 \u0441\u0442\u0430\u0442\u0443\u0441 \u043f\u0440\u043e\u043a\u0441\u0456 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 TransferStatsView.legend.pingaverage=\u0421\u0435\u0440\u0435\u0434\u043d\u0454 TransferStatsView.legend.ping1=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f 1 TransferStatsView.legend.ping2=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f 1 TransferStatsView.legend.ping3=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f 3 ConfigView.section.interface.enabletray._mac=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0443 \u0432 \u0440\u044f\u0434\u043a\u0443 \u0441\u0442\u0430\u0442\u0443\u0441\u0443 [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443] ConfigView.label.closetotray._mac=\u041f\u0440\u0438 \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u0456 \u0437\u0433\u043e\u0440\u043d\u0443\u0442\u0438 \u0432 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0443 \u0440\u044f\u0434\u043a\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u0443 ConfigView.label.minimizetotray._mac=\u0417\u0433\u043e\u0440\u0442\u0430\u0442\u0438 \u0432 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0443 \u0440\u044f\u0434\u043a\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u0443 OpenTorrentWindow.mb.existingFiles.title=\u0424\u0430\u0439\u043b(\u0438) \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u044e\u0442\u044c! OpenTorrentWindow.mb.existingFiles.text=\u0414\u0435\u044f\u043a\u0456 \u0437 \u0444\u0430\u0439\u043b\u0456\u0432 \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u044e\u0442\u044c \u0443 \u0442\u0435\u0446\u0456(\u043a\u0430\u0445) \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f :\n\n%1\n\u042f\u043a\u0449\u043e \u0412\u0438 \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0438\u0442\u0435, Vuze \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u0438 \u043d\u0430 \u0441\u043f\u0456\u0432\u043f\u0430\u0434\u0430\u043d\u043d\u044f \u0456 \u0437\u0430\u043c\u0456\u043d\u0438\u0442\u044c, \u044f\u043a\u0449\u043e \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e. splash.unloadingTorrents=\u041d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 splash.unloadingTorrent=\u041d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.section.file.defaultdir.autorename=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u043f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0456\u0434\u043e\u043c\u043e\u0441\u0442\u0435\u0439 \u043f\u0440\u043e \u0442\u043e\u0440\u0435\u043d\u0442, \u044f\u043a\u0449\u043e \u0448\u043b\u044f\u0445 \u0434\u043e \u0444\u0430\u0439\u043b\u0456\u0432 \u0456\u043d\u0448\u0438\u0439 ConfigView.section.file.defaultdir.autorename.tooltip=\u0426\u0435 \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0454 \u0437\u0430\u043c\u0456\u043d\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u0456\u043d\u0448\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0430, \u044f\u043a\u0449\u043e \u0456\u043c\u0435\u043d\u0430 \u0444\u0430\u0439\u043b\u0456\u0432 \u043e\u0434\u043d\u0430\u043a\u043e\u0432\u0456 alert.raised.at.close=(\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u0432\u0456\u0434 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u043d\u044c\u043e\u0433\u043e \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u044f Vuze) Plugin.trackerpeerauth.name=\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0456\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 Plugin.trackerpeerauth.info=\u0426\u0435 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043f\u0440\u0430\u0446\u044e\u0454 \u0437 \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438, \u0434\u0435 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438 \u0454 \u0447\u0438\u043d\u043d\u0438\u043c\u0438 \u0447\u043b\u0435\u043d\u0430\u043c\u0438 Peers.column.maxupspeed=\u041c\u0430\u043a\u0441. \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442. Peers.column.maxdownspeed=\u041c\u0430\u043a\u0441. \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 MyTorrents.items.DownSpeedLimit.disabled=\u041d\u0435\u043c\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f upnp.selectedaddresses=\u0410\u0434\u0440\u0435\u0441\u0438 (';' =\u0440\u043e\u0437\u0434\u0456\u043b\u0435\u043d\u0456, '-' =\u0432\u0456\u0434\u043c\u043e\u0432\u0430, '+' =\u0434\u043e\u0437\u0432\u0456\u043b) [\u043f\u043e\u0440\u043e\u0436\u043d\u0454: \u0431\u0443\u0434\u044c-\u044f\u043a\u0456] upnp.alert.multipledevice.warning=\u0417\u043d\u0430\u0439\u0434\u0435\u043d\u0456 \u0431\u0430\u0433\u0430\u0442\u043e\u0440\u0430\u0437\u043e\u0432\u0456 \u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457 UPnP - \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043d\u0430 \u0432\u0438\u043c\u043e\u0433\u0443 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043f\u043e\u0440\u0442\u0443 (\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u043b\u043e\u0433\u0438 \u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f UPnP) UpdateMonitor.messagebox.restart.title=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043d\u043e\u0433\u043e \u0437\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0435\u043d\u043d\u044f UpdateMonitor.messagebox.restart.text=Vuze \u043b\u0438\u0448\u0435 \u0449\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0432 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0430\u0436\u043b\u0438\u0432\u043e\u0433\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f, \u044f\u043a\u0435 \u0434\u043b\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438. PiecesView.BlockView.Have=\u041d\u0430\u044f\u0432\u043d\u043e PiecesView.BlockView.NoHave=\u041d\u0435 \u043d\u0430\u044f\u0432\u043d\u043e PiecesView.BlockView.Header=%1 \u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c(\u0446\u0456\u0432), %2 \u0440\u044f\u0434\u043e\u043a(\u043a\u0456\u0432), %3 \u0447\u0430\u0441\u0442\u0438\u043d ConfigView.section.update.autodownload=\u041f\u0456\u0441\u043b\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f Peers.column.peer_id=ID \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 Peers.column.peer_id.info=ID \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0432 \u0447\u0438\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u0456\u0439 \u0444\u043e\u0440\u043c\u0456 Peers.column.peer_byte_id=ID \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 Peers.column.peer_byte_id.info=ID \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0432 \u0431\u0430\u0439\u0442\u043e\u0432\u0456\u0439 \u0444\u043e\u0440\u043c\u0456 Peers.column.handshake_reserved=\u0417\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043e\u0432\u0430\u043d\u0456 \u0431\u0430\u0439\u0442\u0438 \u0434\u043b\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f Peers.column.handshake_reserved.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0454, \u0441\u043a\u0456\u043b\u044c\u043a\u0438 \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043e\u0432\u0430\u043d\u043e \u0431\u0456\u0442\u0456\u0432 \u0434\u043b\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f BT Peers.column.client_identification=\u041e\u0442\u043e\u0442\u043e\u0436\u043d\u0435\u043d\u043d\u044f \u043a\u043b\u0456\u0454\u043d\u0442\u0430 Peers.column.client_identification.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0454 \u043d\u0435\u043e\u043f\u0440\u0430\u0446\u044c\u043e\u0432\u0430\u043d\u0435 \u0456\u043c'\u044f \u043a\u043b\u0456\u0454\u043d\u0442\u0430 Vuze - \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f dht.warn.user=\u041f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u043e \u043f\u043e\u0442\u0435\u043d\u0446\u0456\u0439\u043d\u0456 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 NAT \u0430\u0431\u043e \u043f\u043e\u0440\u0442\u0443 ConfigView.label.openbar.incomplete=\u041f\u0430\u043d\u0435\u043b\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c: \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ConfigView.label.openbar.complete=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0441\u0456\u0434\u0435\u0440\u0456\u0432 ConfigView.label.transferbar.remember_location=\u041f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u043e\u0441\u0442\u0430\u043d\u043d\u0454 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0430\u043d\u0435\u043b\u0456 \u043f\u0435\u0440\u0435\u0434\u0430\u0447 ConfigView.section.transfer.autospeed.forcemin=\u041f\u0440\u0438\u0448\u0432\u0438\u0434\u0448\u0435\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043f\u0440\u0438 \u0432\u0438\u0440\u0456\u0432\u043d\u044e\u0432\u0430\u043d\u043d\u0456 \u0437\u0432'\u044f\u0437\u043a\u0443, %1 MainWindow.menu.tools.speedtest=\u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456... speedtest.wizard.title=\u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 speedtest.wizard.run=\u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 speedtest.wizard.test.mode.updown=\u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f speedtest.wizard.test.mode.up=\u0440\u043e\u0437\u0434\u0430\u0447\u0430 speedtest.wizard.test.mode.down=\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f SpeedTestWizard.test.panel.currinfo=\u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u043e\u0457 \u0441\u043f\u0440\u043e\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0456 BitTorrent. SpeedTestWizard.test.panel.label=\u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 Vuze : SpeedTestWizard.test.panel.already.running=\u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0436\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0435! SpeedTestWizard.test.panel.not.accepted=\u041d\u0435 \u0437\u0430\u0441\u0442\u043e\u0441\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0437\u0430\u043f\u0438\u0442 \u0432\u0438\u043f\u043e\u0431\u043e\u0432\u0443\u0432\u0430\u043d\u043d\u044f: SpeedTestWizard.test.panel.abort=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 SpeedTestWizard.test.panel.abort.countdown=\u043f\u0440\u0438\u043f\u0438\u043d\u0438\u0442\u0438 \u0432: SpeedTestWizard.test.panel.test.countdown=\u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0432: SpeedTestWizard.test.panel.testfailed=\u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f SpeedTestWizard.test.panel.aborted=\u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u0438\u043f\u0438\u043d\u0438\u043d\u0435 \u0432\u0440\u0443\u0447\u043d\u0443. SpeedTestWizard.test.panel.enc.label=\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u0437 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f\u043c: SpeedTestWizard.test.panel.standard=\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 SpeedTestWizard.test.panel.encrypted=\u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f SpeedTestWizard.set.upload.button.apply=\u0417\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438 SpeedTestWizard.set.upload.result=\u041e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f SpeedTestWizard.set.upload.bytes.per.sec=\u041a\u0411\u0430\u0439\u0442/\u0441 SpeedTestWizard.set.upload.bits.per.sec=\u0431\u0456\u0442/\u0441 SpeedTestWizard.finish.panel.title=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0435 \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456! SpeedTestWizard.finish.panel.click.close=\u0412\u0438 \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u0438 \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456. \u0422\u0435\u043f\u0435\u0440 \u043c\u043e\u0436\u043d\u0430 \u0432\u0438\u0445\u043e\u0434\u0438\u0442\u0438. SpeedTestWizard.finish.panel.max.upload=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0440\u043e\u0437\u0434\u0430\u0447: SpeedTestWizard.finish.panel.max.seeding.upload=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0440\u043e\u0437\u0434\u0430\u0447 \u0441\u0456\u0434\u0435\u0440\u0430: SpeedTestWizard.finish.panel.max.download=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c SpeedTestWizard.finish.panel.enabled=\u0443\u0432\u0456\u043c\u043a. SpeedTestWizard.finish.panel.disabled=\u0432\u0438\u043c\u043a. SpeedTestWizard.abort.message.scheduled.in=\u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043b\u0430\u043d\u0443\u0454\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437... %1 \u0441\u0435\u043a\u0443\u043d\u0434(\u0438)" SpeedTestWizard.abort.message.unsupported.type=\u0422\u0438\u043f \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454\u0442\u044c\u0441\u044f!!!! SpeedTestWizard.abort.message.manual.abort=\u0412\u0440\u0443\u0447\u043d\u0443 \u043f\u0440\u0438\u043f\u0438\u043d\u0435\u043d\u0438\u0439 SpeedTestWizard.abort.message.scheduling.failed=\u041f\u043b\u0430\u043d\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435\u0432\u0434\u0430\u043b\u0435 SpeedTestWizard.abort.message.download.added=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f %1 \u0434\u043e\u0434\u0430\u043d\u0435 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f SpeedTestWizard.abort.message.entered.error=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0439 \u0441\u0442\u0430\u043d \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f '%1' SpeedTestWizard.abort.message.entered.queued=\u0421\u0442\u0430\u043d \u0437\u0443\u043f\u0438\u043d\u043a\u0438 \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f SpeedTestWizard.abort.message.interrupted=TorrentSpeedTestMonitorThread \u0431\u0443\u0432 \u043f\u0435\u0440\u0435\u0440\u0432\u0430\u043d\u0438\u0439 \u043f\u0435\u0440\u0435\u0434 \u0442\u0438\u043c, \u044f\u043a \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u043e\u0441\u044f SpeedTestWizard.abort.message.execution.failed=\u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435\u0432\u0434\u0430\u043b\u0435 SpeedTestWizard.abort.message.failed.peers=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u043d\u0456 \u0437 \u043a\u0438\u043c \u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435 SpeedTestWizard.abort.message.insufficient.slots=\u041d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c - \u0441\u043b\u043e\u0442\u0438 \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0437\u0430\u0439\u043d\u044f\u0442\u0456? SpeedTestWizard.abort.message.not.unchoked=\u041d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438 SpeedTestWizard.stage.message.requesting=\u0432\u0438\u043c\u043e\u0433\u0430 \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f... SpeedTestWizard.stage.message.preparing=\u043f\u0456\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f... SpeedTestWizard.stage.message.starting=\u043f\u043e\u0447\u0430\u0442\u043e\u043a \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f... SpeedTestWizard.stage.message.connect.stats=\u041f\u043e\u043a\u0430\u0437\u043d\u0438\u043a\u0438 \u0437\u0432'\u044f\u0437\u043a\u0443: \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432=%1, down_ok=%2, up_ok=%3 window.uiswitcher.title=\u0412\u0438\u0431\u0456\u0440 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 Vuze window.uiswitcher.text=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u043e\u0439 \u0432\u0438\u0433\u043b\u044f\u0434 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438, \u044f\u043a\u0438\u0439 \u0437\u0430\u0434\u043e\u0432\u0456\u043b\u044c\u043d\u044f\u0442\u0438\u043c\u0435 \u0432\u0430\u0448\u0456 \u043f\u043e\u0442\u0440\u0435\u0431\u0438. window.uiswitcher.NewUI.text=* \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u0447\u0430\u0442\u043a\u0456\u0432\u0446\u0456\u0432 \u0456 \u043d\u043e\u0432\u0438\u0445 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432.\n\n* \u041b\u0435\u0433\u043a\u0435, \u0456\u043d\u0442\u0443\u0457\u0442\u0438\u0432\u043d\u0435 \u0433\u0440\u0430\u0444\u0456\u0447\u043d\u0435 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f\n\n* \u041e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0432\u0438\u0433\u043b\u044f\u0434 \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0456 Vuze window.uiswitcher.ClassicUI.title=\u041a\u043b\u0430\u0441\u0438\u0447\u043d\u0438\u0439 \u0432\u0438\u0433\u043b\u044f\u0434 window.uiswitcher.ClassicUI.text=* \u0417\u0431\u0435\u0440\u0456\u0433\u0430\u0454 \u0444\u0443\u043d\u043a\u0446\u0456\u043e\u043d\u0430\u043b\u044c\u043d\u0456\u0441\u0442\u044c \u043a\u043b\u0456\u0454\u043d\u0442\u0430 \u0432\u0435\u0440\u0441\u0456\u0439 2.x \n* \u0428\u0430\u043f\u043a\u0430 Vuze \u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f window.uiswitcher.bottom.text=\u0412\u0430\u0448 \u0432\u0438\u0431\u0456\u0440 \u043c\u043e\u0436\u0435 \u043b\u0435\u0433\u043a\u043e \u0431\u0443\u0442\u0438 \u0437\u043c\u0456\u043d\u0435\u043d\u0438\u043c \u0437\u043d\u043e\u0432\u0443 \u043d\u0430\u0442\u0438\u0441\u043a\u043e\u043c \u043a\u043d\u043e\u043f\u043a\u0438 UI , \u0456 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u044e \u0437\u043c\u0456\u043d\u043e\u044e \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 iconBar.switch.tooltip=\u041f\u0435\u0440\u0435\u043c\u0438\u043a\u0430\u0447 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 Vuze VivaldiView.notAvailable=\u041d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0432\u0438\u0433\u043b\u044f\u0434 Vivaldi restart.error=\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0438\u0439:\n%1\n\u041f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u043e\u0431\u043b\u0435\u043c. restart.error.oom=\u041f\u0435\u0440\u0435\u0432\u0438\u0449\u0435\u043d\u043d\u044f \u0431\u0443\u0444\u0435\u0440\u0443 \u043f\u0430\u043c'\u044f\u0442\u0456 restart.error.fnf='%1' \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439 \u0432 '%2' restart.error.pnf=\u0428\u043b\u044f\u0445 '%1' \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439 restart.error.bad=\u041f\u043e\u0433\u0430\u043d\u0438\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0444\u0430\u0439\u043b\u0443 \u0434\u043b\u044f '%1' restart.error.denied=\u0414\u043e\u0441\u0442\u0443\u043f \u043a\u0435\u0440\u0443\u0432\u0430\u043d\u043d\u044f '%1' \u043d\u0435 \u043d\u0430\u0434\u0430\u043d\u0438\u0439. \u041f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0439\u0442\u0435\u0441\u044f, \u0449\u043e \u0432\u0438 \u043c\u0430\u0454\u0442\u0435 \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0456 \u043f\u0440\u0430\u0432\u0430, \u0449\u043e\u0431 \u043a\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u0446\u0456\u0454\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e. TableColumn.header.date_completed=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0439 TableColumn.menu.date_added.reset=\u0421\u0442\u0435\u0440\u0442\u0438 \u0434\u0430\u0442\u0443 ConfigView.section.ipfilter.discardbanning=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u0432 \u044f\u043a\u0438\u0445 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0432\u0456\u0434\u0445\u0438\u043b\u0435\u043d\u0438\u0445 \u0434\u0430\u043d\u0438\u0445 \u0434\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u0434\u0430\u043d\u0438\u0445 \u043c\u0435\u043d\u0448\u0435\n[0: \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438] ConfigView.section.ipfilter.discardminkb=\u041c\u0456\u043d\u0456\u043c\u0443\u043c %1 \u0437\u0431\u043e\u0457\u0432 \u043f\u0435\u0440\u0435\u0434 \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u043d\u043d\u044f\u043c \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f ConfigView.interface.start.advanced=\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u0432 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043e\u043c\u0443 \u0432\u0438\u0433\u043b\u044f\u0434\u0456(AZ 2.x) MyTorrents.column.ColumnQuality=\u042f\u043a\u0456\u0441\u0442\u044c MyTorrents.column.ColumnSpeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c MyTorrents.column.ColumnProgressETA.2ndLine=\u0417\u0430\u043b\u0438\u0448\u0438\u043b\u043e\u0441\u044f: %1 MyTorrents.column.ColumnProgressETA.StreamReady=\u0413\u043e\u0442\u043e\u0432\u0438\u0439 \u0434\u043e \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0457 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456 MyTorrents.column.ColumnProgressETA.PlayableIn=\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u044e\u0432\u0430\u043d\u0438\u0439 \u0432 %1 TableColumn.header.Quality=\u042f\u043a\u0456\u0441\u0442\u044c TableColumn.header.Speed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c TableColumn.header.RateIt=\u041d\u043e\u0440\u043c\u0430 TableColumn.header.Rating=\u0420\u0435\u0439\u0442\u0438\u043d\u0433 TableColumn.header.SpeedGraphic=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c TableColumn.header.AzProduct=\u0412\u0456\u0434 TableColumn.header.MediaThumb=\u041c\u0435\u0434\u0456\u0430 TableColumn.header.ProgressETA=\u041f\u0440\u043e\u0433\u0440\u0435\u0441 #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=\u0422\u0438\u043f \u0444\u0430\u0439\u043b\u0443: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=\u041f\u0430\u043d\u0435\u043b\u044c \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432 v3.MainWindow.tab.browse=\u041d\u0430 Vuze v3.MainWindow.tab.library=\u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0430 v3.MainWindow.tab.publish=\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 v3.MainWindow.tab.advanced=\u0414\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e v3.MainWindow.menu.home=&\u041f\u0430\u043d\u0435\u043b\u044c \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432 v3.MainWindow.menu.browse=&\u041d\u0430 Vuze v3.MainWindow.menu.library=&\u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0430 v3.MainWindow.menu.publish=&\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 v3.MainWindow.menu.advanced=&\u0414\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e v3.MainWindow.menu.view.searchbar=\u041f\u0430\u043d\u0435\u043b\u044c \u043f\u043e\u0448\u0443\u043a\u0443 v3.MainWindow.menu.view.tabbar=\u0420\u044f\u0434\u043e\u043a \u043f\u0430\u043d\u0435\u043b\u0456 v3.MainWindow.currentDL=\u0417\u0430\u0440\u0430\u0437 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u044c\u0441\u044f v3.MainWindow.button.stream=\u041f\u043e\u0442\u0456\u043a v3.MainWindow.button.stop=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 v3.MainWindow.button.start=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 v3.MainWindow.button.pause=\u041f\u0430\u0443\u0437\u0430 v3.MainWindow.button.resume=\u041f\u0456\u0434\u0441\u0443\u043c\u043e\u043a v3.MainWindow.button.delete=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 v3.MainWindow.button.comment=\u0414\u043e\u0434\u0430\u0442\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 v3.MainWindow.button.viewdetails=\u0414\u0438\u0432\u0438\u0442\u0438\u0441\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 v3.MainWindow.button.play=\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u0438\u0442\u0438 v3.MainWindow.button.cancel=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 v3.MainWindow.button.preview=\u041f\u043e\u043f\u0435\u0440\u0435\u0434\u043d\u0456\u0439 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 v3.MainWindow.view.wait=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0443\u0454\u0442\u044c\u0441\u044f \u0432\u0438\u0433\u043b\u044f\u0434, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0437\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435. v3.MainWindow.xofx=%1 \u0437 %2 v3.MainWindow.Loading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.. \u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0437\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435 v3.filter-bar=\u0424\u0456\u043b\u044c\u0442\u0440 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430: v3.MainWindow.search.defaultText=Vuze , \u0448\u0443\u043a\u0430\u0439! v3.mb.delPublished.title=\u041f\u0440\u0438\u043f\u0438\u043d\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e v3.mb.delPublished.text=\u0423\u0412\u0410\u0413\u0410: \u0426\u044f \u0434\u0456\u044f \u043d\u0435 \u0437\u043d\u0438\u0449\u0438\u0442\u044c \u0432\u0430\u0448\u0443 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0443 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e '%1' \u0437 %3 .\n\n\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c "\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438" \u043b\u0438\u0448\u0435 \u0432 \u0442\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u044f\u043a\u0449\u043e \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435, \u0449\u043e\u0431 \u0432\u0430\u0448\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0437\u0430\u043b\u0438\u0448\u0430\u043b\u0430\u0441\u044f \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u044e \u0456 \u0457\u0457 \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438, \u0430\u043b\u0435 \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0432\u0456\u043b\u044c\u043d\u0438\u0442\u0438 \u0432\u0430\u0448\u0443 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0443 \u0441\u043f\u0440\u043e\u043c\u043e\u0436\u043d\u0456\u0441\u0442\u044c. \u041f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0439\u0442\u0435\u0441\u044f, \u0449\u043e \u043f\u0440\u043e\u0446\u0435\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0432\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u0442\u0438\u043c, \u044f\u043a \u0412\u0438 \u0437\u0440\u043e\u0431\u0438\u0442\u0435 \u0442\u0430\u043a (\u042f\u043a?).\n\n\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c "\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438", \u044f\u043a\u0449\u043e \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0446\u0456\u043b\u043a\u043e\u043c \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0432\u0430\u0448\u0443 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0443 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e %3, \u0456 \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 (X) \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0456 \u043f\u0443\u0431\u043b\u0456\u043a\u0430\u0446\u0456\u0457.\n\n\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435.\n\n v3.mb.delPublished.delete=&\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 v3.mb.delPublished.cancel=&\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 v3.mb.openFile.title=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0444\u0430\u0439\u043b v3.mb.openFile.text.known=\u0426\u0435\u0439 \u0432\u043c\u0456\u0441\u0442 \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u0432\u0430\u0447\u0435\u043c Vuze Player. \u0417\u0432\u0456\u0440\u0442\u0435\u0441\u044f \u0437 \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043e\u044e \u043d\u0430\u0448\u0438\u043c \u0441\u0443\u0441\u043f\u0456\u043b\u044c\u0441\u0442\u0432\u043e\u043c \u0414\u043e\u0432\u0456\u0434\u043a\u043e\u044e \u043f\u043e \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044e.\n\n\u0422\u0438\u043f \u0444\u0430\u0439\u043b\u0443: %2 (%3)\n v3.mb.openFile.text.unknown=\u0426\u0435\u0439 \u0432\u043c\u0456\u0441\u0442 \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u0432\u0430\u0447\u0435\u043c Vuze Player. \u0417\u0432\u0456\u0440\u0442\u0435\u0441\u044f \u0437 \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043e\u044e \u043d\u0430\u0448\u0438\u043c \u0441\u0443\u0441\u043f\u0456\u043b\u044c\u0441\u0442\u0432\u043e\u043c \u0414\u043e\u0432\u0456\u0434\u043a\u043e\u044e \u043f\u043e \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044e for help.\n\n\u0420\u043e\u0448\u0438\u0440\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 : %2\n v3.mb.openFile.button.play=\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u0438\u0442\u0438 v3.mb.openFile.button.cancel=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 v3.mb.openFile.button.guide=\u0414\u043e\u0432\u0456\u0434\u043a\u0430 \u043f\u043e \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044e v3.mb.openFile.remember=\u0417\u0430\u0432\u0436\u0434\u0438 \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0431\u0435\u0437 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0438\u0442\u0430\u043d\u043d\u044f v3.mb.PlayFileNotFound.title=\u0424\u0430\u0439\u043b \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e v3.mb.PlayFileNotFound.text=\u0424\u0430\u0439\u043b\u0438 \u0434\u043b\u044f '%1' \u0430\u0431\u043e \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u0456, \u0430\u0431\u043e \u0432\u0456\u0434\u0441\u0443\u0442\u043d\u0456. v3.mb.PlayFileNotFound.button.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0437 Vuze v3.mb.PlayFileNotFound.button.redownload=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0434\u0430\u043d\u0456 v3.mb.PlayFileNotFound.button.find=\u041f\u043e\u0448\u0443\u043a \u0432\u0440\u0443\u0447\u043d\u0443.. v3.mb.deletePurchased.title=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043a\u0443\u043f\u043b\u0435\u043d\u0443 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e v3.mb.deletePurchased.text=\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 '%1'?\n\n\u0426\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u043e\u043a\u0443\u043f\u043a\u0438 \u0430\u0431\u043e \u0432\u043a\u0430\u0437\u0430\u043d\u043d\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0456\u043d\u0443. v3.mb.deletePurchased.button.delete=&\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 v3.mb.deletePurchased.button.cancel=&\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 v3.topbar.menu.show.logo=\u0424\u0456\u0440\u043c\u043e\u0432\u0438\u0439 \u0437\u043d\u0430\u043a v3.topbar.menu.show.plugin=\u0414\u0456\u043b\u044f\u043d\u043a\u0430 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c v3.topbar.menu.show.search=\u041f\u043e\u0448\u0443\u043a splash.initializeCore=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u044f\u0434\u0440\u0430 splash.initializeUIElements=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0456\u0432 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 ConfigView.section.transfer.autospeedbeta=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c (beta) # ConfigView.section.ipfilter.peerblocking.group=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 ConfigView.section.ipfilter.autoload.group=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ConfigView.section.ipfilter.autoload.file=\u0424\u0430\u0439\u043b \u0444\u0456\u043b\u044c\u0442\u0440\u0443 IP \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f ConfigView.section.ipfilter.autoload.info=\u041f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u0444\u043e\u0440\u043c\u0430\u0442\u0438 DAT (eMule), P2P (PeerGuardian, splist), and P2B v1,2,3 (PeerGuardian 2). \u0424\u0430\u0439\u043b \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u043c\u0456\u0441\u0446\u0435\u0432\u0438\u043c \u0430\u0431\u043e \u0430\u0434\u0440\u0435\u0441\u043e\u044e, zip'\u043e\u043c, gzip'\u043e\u043c \u0430\u0431\u043e \u0442\u0435\u043a\u0441\u0442\u043e\u043c. \u0430\u0434\u0440\u0435\u0441\u0430-\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 7 \u0434\u043d\u0456\u0432, \u0442\u043e\u0434\u0456 \u044f\u043a \u0444\u0430\u0439\u043b\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438\u043c\u0443\u0442\u044c\u0441\u044f \u0432 \u043c\u0435\u0436\u0430\u0445 \u0445\u0432\u0438\u043b\u0438\u043d\u0438. ConfigView.section.ipfilter.autoload.loadnow=\u0417\u0430\u0432\u0430\u0442\u043d\u0430\u0436\u0438\u0442\u0438 \u0437\u0430\u0440\u0430\u0437 splash.loadIpFilters=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0456\u043b\u044c\u0442\u0440\u0456\u0432 IP... SpeedTestWizard.set.upload.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043c\u0435\u0436\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456: SpeedTestWizard.set.download.label=\u041e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f: SpeedTestWizard.set.upload.label=\u041e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456: SpeedTestWizard.name.conf.level.absolute=\u041f\u043e\u0432\u043d\u0430 SpeedTestWizard.name.conf.level.high=\u0412\u0438\u0441\u043e\u043a\u0430 SpeedTestWizard.name.conf.level.med=\u0421\u0435\u0440\u0435\u0434\u043d\u044f SpeedTestWizard.name.conf.level.low=\u041d\u0438\u0437\u044c\u043a\u0430 SpeedTestWizard.name.conf.level.none=\u041d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 ConfigView.section.transfer.select=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c ConfigView.section.transfer.select.v2=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c (beta) mb.azmustclose.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 mb.azmustclose.text=Vuze \u043f\u043e\u0432\u0438\u043d\u0435\u043d \u0437\u0430\u043a\u0440\u0438\u0442\u0438\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 (\u043f\u0435\u0440\u0435)\u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze \u0432\u0456\u0434 \u0456\u043c\u0435\u043d\u0456 \u0410\u0434\u043c\u0456\u043d\u0456\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430.\n\n\u041f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u044f Vuze \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0456\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443 \u0432\u0440\u0443\u0447\u043d\u0443. network.ipv6.prefer.addresses=\u0412\u0456\u0434\u0434\u0430\u0432\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u0430\u0433\u0443 \u0430\u0434\u0440\u0435\u0441\u0430\u043c IPv6, \u043a\u043e\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u044f\u043a IPv6, \u0442\u0430\u043a \u0456 IPv4 network.bindError=\u0417\u0430\u043a\u0440\u0456\u043f\u043b\u0435\u043d\u043d\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0433\u043d\u0456\u0437\u0434\u0430 \u043d\u0435\u0432\u0434\u0430\u043b\u0435, \u0430\u0434\u0440\u0435\u0441, \u044f\u043a\u0456 \u0431 \u043f\u0456\u0434\u0445\u043e\u0434\u0438\u043b\u0438, \u043d\u0435 \u0437\u043d\u0430\u0439\u0448\u043b\u043e\u0441\u044f, \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0441\u0432\u043e\u0457 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u0437\u0430\u043a\u0440\u0456\u043f\u043b\u0435\u043d\u043d\u044f \u0437\u0430 IP. network.enforce.ipbinding=\u041f\u0440\u0438\u0448\u0432\u0438\u0434\u0448\u0443\u0432\u0430\u0442\u0438 \u0432\u043a\u0430\u0437\u0430\u043d\u0456 IP \u043d\u0430\u0432\u0456\u0442\u044c, \u043a\u043e\u043b\u0438 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0438 \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456; \u0437\u0430\u043f\u043e\u0431\u0456\u0433\u0430\u0454 \u0431\u0443\u0434\u044c-\u044f\u043a\u0438\u043c \u0437\u0432'\u044f\u0437\u043a\u0430\u043c, \u044f\u043a\u0449\u043e \u0436\u043e\u0434\u0435\u043d \u0437 \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u0445 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0456\u0432 \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 DHTView.title.full_v6=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u0438\u0445 IPv6 ConfigView.pluginlist.loadSelected=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0456 SpeedView.stats.asn=\u041c\u0435\u0440\u0435\u0436\u0430: SpeedView.stats.estupcap=\u041c\u0435\u0436\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456: SpeedView.stats.estdowncap=\u041c\u0435\u0436\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f: SpeedView.stats.unknown=\u043d\u0435\u0432\u0456\u0434\u043e\u043c\u043e SpeedView.stats.estimate=\u043e\u0446\u0456\u043d\u043e\u0447\u043d\u0430 SpeedView.stats.measured=\u0437\u0432\u0430\u0436\u0435\u043d\u0430 SpeedView.stats.measuredmin=\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0435 \u0437\u0432\u0430\u0436\u0435\u043d\u043d\u044f SpeedView.stats.manual=\u0432\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 ConfigView.section.transfer.autospeed.networks=\u041c\u0435\u0440\u0435\u0436\u0435\u0432\u0456 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 ConfigView.section.transfer.autospeed.resetnetwork=\u0421\u043a\u0438\u043d\u0443\u0442\u0438 \u043c\u0435\u0440\u0435\u0436\u0435\u0432\u0456 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 ConfigView.section.transfer.autospeed.network.info=\u041c\u0435\u0436\u0456 \u0437\u0432\u0438\u0447\u0430\u0439\u043d\u043e \u043e\u0431\u0447\u0438\u0441\u043b\u044e\u044e\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u043e\u0442\u044f\u0433\u043e\u043c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0430\u0431\u043e \u0454 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456. \u042f\u043a\u0449\u043e \u0432\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0440\u0443\u0447\u043d\u0443 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u0438\u0437\u0443\u0432\u0430\u0442\u0438 \u0457\u0445, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u043d\u0438\u0436\u0447\u0435 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0443 \u043e\u043f\u0446\u0456\u044e.\n\u0412\u0441\u0456 \u043c\u0435\u0436\u0456, \u043e\u043a\u0440\u0456\u043c '\u0432\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e\u0457', \u0437\u0433\u043e\u0434\u043e\u043c \u0431\u0443\u0434\u0443\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0441\u043a\u043e\u0440\u0435\u043a\u0442\u043e\u0432\u0430\u043d\u0456, \u044f\u043a\u0449\u043e \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e. \n\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f, \u0430 \u043f\u043e\u0442\u0456\u043c \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0439\u043e\u0433\u043e \u0442\u0438\u043f. \u0417\u0430\u0443\u0432\u0430\u0436\u0442\u0435, \u0449\u043e \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u043d\u0430\u0445\u043e\u0434\u044f\u0442\u044c\u0441\u044f \u0432 %1. dialog.uiswitcher.restart.title=\u041f\u0435\u0440\u0435\u043c\u0438\u043a\u0430\u0447 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443: \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0438\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a Vuze dialog.uiswitcher.restart.text=Vuze \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u043c\u043a\u043d\u0443\u0442\u0438\u0441\u044f \u0432 \u043d\u043e\u0432\u0438\u0439 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. TrayWindow.menu.close=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 \u043a\u043e\u0448\u0438\u043a \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c # Used for peers which we can't determine. PeerSocket.unknown=\u041d\u0435\u0432\u0456\u0434\u043e\u043c\u0438\u0439 PeerSocket.fake_client=\u0424\u0410\u041b\u042c\u0428\u0418\u0412\u041a\u0410 PeerSocket.bad_peer_id=\u043f\u043e\u0433\u0430\u043d\u0438\u0439 ID \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 PeerSocket.mismatch_id=\u043d\u0435\u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u043d\u0456\u0441\u0442\u044c PeerSocket.unknown_az_style=\u041d\u0435\u0432\u0456\u0434\u043e\u043c\u0438\u0439 %1/%2 PeerSocket.unknown_shadow_style=\u041d\u0435\u0432\u0456\u0434\u043e\u043c\u0438\u0439 %1/%2 OpenTorrentWindow.mb.askCreateDir.title=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043d\u0435 \u0456\u0441\u043d\u0443\u0454. OpenTorrentWindow.mb.askCreateDir.text=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u043d\u0435 \u0456\u0441\u043d\u0443\u0454.\n\n\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0457\u0457 \u0437\u0430\u0440\u0430\u0437? SpeedView.stats.estimatechoke=\u041e\u0446\u0456\u043d\u043a\u0430 ConfigTransferAutoSpeed.upload.capacity.usage=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u0443 \u043c\u0456\u0441\u0442\u043a\u0456\u0441\u0442\u044c ConfigTransferAutoSpeed.mode=\u0420\u0435\u0436\u0438\u043c: ConfigTransferAutoSpeed.capacity.used=% \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f ConfigTransferAutoSpeed.while.downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f: ConfigTransferAutoSpeed.set.dht.ping=\u0420\u0435\u0433\u0443\u043b\u044e\u0432\u0430\u043d\u043d\u044f \u043f\u0456\u043d\u0433\u0443 DHT: ConfigTransferAutoSpeed.set.point=\u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0443\u043d\u043a\u0442 (\u043c\u0441) ConfigTransferAutoSpeed.set.tolerance=\u0442\u043e\u043b\u0435\u0440\u0430\u043d\u0442\u043d\u0456\u0441\u0442\u044c (\u043c\u0441) ConfigTransferAutoSpeed.ping.time.good=\u0414\u043e\u0431\u0440\u0438\u0439: ConfigTransferAutoSpeed.ping.time.bad=\u041f\u043e\u0433\u0430\u043d\u0438\u0439: ConfigTransferAutoSpeed.adjustment.interval=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0456\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0443: ConfigTransferAutoSpeed.skip.after.adjust=\u041f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u043f\u0456\u0441\u043b\u044f \u043a\u043e\u0440\u0435\u043a\u0442\u0443\u0432\u0430\u043d\u043d\u044f: GeneralView.label.distributedCopies=\u0420\u043e\u0437\u043f\u043e\u0432\u0441\u044e\u0434\u0436\u0435\u043d\u043e \u043a\u043e\u043f\u0456\u0439: PiecesView.DistributionView.title=\u0420\u043e\u0437\u043f\u043e\u0432\u0441\u044e\u0434\u0436\u0435\u043d\u043d\u044f \u0447\u0430\u0441\u0442\u0438\u043d\u0438 PiecesView.DistributionView.NoAvl=\u041d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u0447\u0430\u0441\u0442\u0438\u043d\u0438 PiecesView.DistributionView.SeedAvl=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0432\u043a\u043b\u0430\u0434 \u0441\u0456\u0434\u0435\u0440\u0430 PiecesView.DistributionView.PeerAvl=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0432\u043a\u043b\u0430\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 PiecesView.DistributionView.RarestAvl=\u041d\u0430\u0439\u0440\u0456\u0434\u043a\u0456\u0441\u043d\u0456\u0448\u0456 \u0447\u0430\u0441\u0442\u0438\u043d\u0438: %1 (\u0434\u043e\u0441\u0442.:%2) PiecesView.DistributionView.weHave=\u0427\u0430\u0441\u0442\u0438\u043d\u0438, \u044f\u043a\u0456 \u0432\u0438 \u043c\u0430\u0454\u0442\u0435 PiecesView.DistributionView.theyHave=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0447\u0430\u0441\u0442\u0438\u043d, \u044f\u043a\u0456 \u043c\u0430\u0454 \u0443\u0447\u0430\u0441\u043d\u0438\u043a PiecesView.DistributionView.weDownload=\u0427\u0430\u0441\u0442\u0438\u043d\u0438, \u044f\u043a\u0456 \u0432\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u0435 PeersView.gain=\u0412\u0438\u0433\u043e\u0434\u0430 PeersView.gain.info=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 - \u0440\u043e\u0437\u0434\u0430\u043d\u0438\u0445 \u0434\u0430\u043d\u0438\u0445 unix.script.new.title=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u043d\u043e\u0432\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze unix.script.new.text=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439, \u0456 \u0431\u0443\u0432 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0439 \u0432 '%1'.\n\n\u041c\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u043c\u043e \u0412\u0430\u043c \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u0438 Vuze \u0437\u0430\u0440\u0430\u0437 \u0456 \u043f\u0435\u0440\u0435\u043c\u043a\u043d\u0443\u043b\u0438\u0441\u044f \u0432 \u0446\u0435\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 ('%2').\n\n\u042f\u043a\u0449\u043e \u0432\u0438 \u0441\u0438\u043b\u044c\u043d\u043e \u0437\u043c\u0456\u043d\u0438\u043b\u0438 \u0432\u0430\u0448 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze \u043f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443: \u0421\u0446\u0435\u043d\u0430\u0440\u0456\u0439 Unix.\n\n\u042f\u043a\u0449\u043e \u0432\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 Vuze \u0432\u0456\u0434 distro (yum, apt-get, \u0442\u043e\u0449\u043e), \u0431\u0430\u0436\u0430\u043d\u043e, \u0449\u043e\u0431 \u0432\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 Vuze, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0432\u0448\u0438 \u043f\u0430\u043a\u0435\u0442 \u0421\u0442\u043e\u0440\u0456\u043d\u043a\u0438 Vuze \u043d\u0430 Sourceforge (\u0412\u0430\u0448 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u044c\u0441\u044f \u0442\u0438\u043c \u0436\u0435). unix.script.new.button.quit=\u0412\u0438\u0439\u0442\u0438 \u0437\u0430\u0440\u0430\u0437 unix.script.new.button.continue=\u042f \u0437\u0440\u043e\u0431\u043b\u044e \u0446\u0435 \u043f\u0456\u0437\u043d\u0456\u0448\u0435 unix.script.new.button.asknomore=\u041d\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u0442\u0438 \u043c\u0435\u043d\u0456 \u0437\u043d\u043e\u0432\u0443 unix.script.new.auto.title=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze unix.script.new.auto.text=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439.\n\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 Vuze \u0437\u0430\u0440\u0430\u0437. Content.alert.notuploaded.button.stop=&\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 Content.alert.notuploaded.button.continue=&\u041f\u0440\u043e\u0434\u043e\u0432\u0436\u0443\u0432\u0430\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 Content.alert.notuploaded.button.abort=&\u041d\u0435 \u0432\u0438\u0445\u043e\u0434\u0438\u0442\u0438 ConfigView.label.checkOnSeeding=\u0412\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u0442\u0438 \u043d\u0438\u0437\u044c\u043a\u043e\u0440\u0456\u0432\u043d\u0435\u0432\u0443 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0443 \u0447\u0430\u0441\u0442\u0438\u043d \u0440\u0435\u0441\u0443\u0440\u0441\u0443 ConfigView.label.ui_switcher=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u0431\u0456\u0440 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 Vuze ConfigView.label.ui_switcher_button=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 SpeedTestWizard.test.panel.explain=\u0412\u0438\u043c\u0456\u0440\u044f\u0439\u0442\u0435 \u0441\u0432\u043e\u044e \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443. \u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u0438\u043f \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0456\n\u043c\u0435\u0442\u043e\u0434 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f. \u0412\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443 Vuze \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u043f\u0440\u043e \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f. \u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0443\u043f\u0438\u043d\u0438\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e, \u044f\u043a\u0449\u043e \u0442\u0440\u0438\u0432\u0430\u0442\u0438\u043c\u0435 \u0434\u043e\u0432\u0448\u0435, \u043d\u0456\u0436 \u0434\u0432\u0456 \u0445\u0432\u0438\u043b\u0438\u043d\u0438. \u0417\u0432\u0438\u0447\u0430\u0439\u043d\u043e \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0443\u044e\u0442\u044c\u0441\u044f \u0448\u0432\u0438\u0434\u0448\u0435, \u043d\u0456\u0436 \u0437\u0430 \u0445\u0432\u0438\u043b\u0438\u043d\u0443. SpeedTestWizard.set.upload.hint=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c \u043c\u0435\u0436\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u044f\u043a\u0456 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456. SpeedTestWizard.set.upload.panel.explain=\u041d\u0430\u0431\u0456\u0440 \u043c\u0435\u0436, \u044f\u043a\u0456 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 Vuze. \u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c \u043c\u0435\u0436\u0456 \u043f\u0435\u0440\u0435\u0434\u0430\u0447 \u0456 \u043c\u0435\u0436\u0456 \u0434\u043e\u0432\u0456\u0440\u0438.\n\n\u0417\u0430\u0443\u0432\u0430\u0436\u0442\u0435, \u0449\u043e \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0447\u0430\u0441\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u0443\u044e\u0442\u044c\u0441\u044f \u0432 "\u0431\u0456\u0442 \u0437\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u0443" - \u043f\u0440\u043e\u0442\u0435 \u0442\u0443\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u043e\u043a\u0430\u0437\u0443\u0454\u0442\u044c\u0441\u044f \u0432 "\u043a\u0456\u043b\u043e\u0431\u0430\u0439\u0442\u0456\u0432 \u0437\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u0443". SpeedTestWizard.set.limit.conf.level=\u0414\u043e\u0432\u0456\u0440\u0430 SpeedTestWizard.finish.panel.auto.speed=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c : SpeedTestWizard.finish.panel.auto.speed.seeding=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c : ConfigTransferAutoSpeed.add.comment.to.log.group=\u0414\u043e\u0434\u0430\u0442\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0434\u043e \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f ConfigTransferAutoSpeed.add.comment.to.log=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440: ConfigTransferAutoSpeed.log.button=\u041b\u043e\u0433 ConfigTransferAutoSpeed.algorithm.selector=\u0412\u0438\u0431\u0456\u0440 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 ConfigTransferAutoSpeed.algorithm=\u041c\u0435\u0442\u043e\u0434: ConfigTransferAutoSpeed.auto.speed.classic=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c (\u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0430) ConfigTransferAutoSpeed.auto.speed.beta=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c (\u0434\u043e\u0441\u043b\u0456\u0434\u043d\u0430) ConfigTransferAutoSpeed.data.update.frequency=\u0427\u0430\u0441\u0442\u043e\u0442\u0430 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f Alert.failed.update=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u044f\u043a \u043c\u0456\u043d\u0456\u043c\u0443\u043c \u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443 \u043d\u0435\u0432\u0434\u0430\u043b\u0435. \u041f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f AzureusWiki: \u041d\u0435\u0432\u0434\u0430\u043b\u0435 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f [%1] OpenTorrentWindow.mb.existingFiles.partialList=(\u0427\u0430\u0441\u0442\u043a\u043e\u0432\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a. \u0406\u0441\u043d\u0443\u0454 \u0431\u0456\u043b\u044c\u0448\u0435 \u0444\u0430\u0439\u043b\u0456\u0432) TableColumn.header.bad_avail_time.info=\u041e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u0447\u0430\u0441, \u043a\u043e\u043b\u0438 \u043f\u043e\u0432\u043d\u0430 \u043a\u043e\u043f\u0456\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u044e TableColumn.header.bad_avail_time=\u041f\u043e\u0432\u043d\u0430 \u043a\u043e\u043f\u0456\u044f MyTorrentsView.menu.exporthttpseeds=\u0415\u043a\u0441\u043f\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438 HTTP-\u0430\u0434\u0440\u0435\u0441\u0443 \u0441\u0456\u0434\u0435\u0440\u0430 \u0434\u043e \u0431\u0443\u0444\u0435\u0440\u0430 \u043e\u0431\u043c\u0456\u043d\u0443 SWT.alert.erroringuithread=\u041d\u0435\u043a\u0435\u0440\u043e\u0432\u0430\u043d\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u0432\u0456\u0434\u0431\u0443\u0432\u0430\u043b\u0430\u0441\u044f \u0432 GUI, \u043f\u043e\u0434\u0430\u043b\u044c\u0448\u0456 \u043f\u043e\u043c\u0438\u043b\u043a\u0438, \u043c\u043e\u0436\u043b\u0438\u0432\u043e, \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u0456. ConfigView.label.minannounce=\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0447\u0430\u0441 \u043c\u0456\u0436 \u0430\u043d\u043e\u043d\u0441\u0430\u043c\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u0443, \u0441 ConfigView.label.maxnumwant=\u041e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u044f\u043a\u0456 \u043c\u0430\u044e\u0442\u044c \u0437\u043c\u043e\u0433\u0443 \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438\u0441\u044f ConfigView.label.announceport=\u041f\u0456\u0434\u043c\u0456\u043d\u044e\u0432\u0430\u0442\u0438 \u043f\u043e\u0440\u0442 \u0430\u043d\u043e\u043d\u0441\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.label.noportannounce=\u041d\u0435 \u0430\u043d\u043e\u043d\u0441\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 (\u0446\u0435 \u043d\u0435 \u0432\u043f\u043b\u0438\u0432\u0430\u0454 \u043d\u0430 pex, dht) ConfigView.label.maxseedspertorrent=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439] wizard.webseed=\u0414\u043e\u0434\u0430\u0442\u0438 HTTP-\u0441\u0456\u0434\u0435\u0440\u0456\u0432 wizard.webseed.title=HTTP-\u0441\u0456\u0434\u0435\u0440\u0438 wizard.webseed.configuration=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f HTTP-\u0441\u0456\u0434\u0435\u0440\u0456\u0432 wizard.webseed.adding=\u0414\u043e\u0434\u0430\u0442\u0438 HTTP-\u0441\u0456\u0434\u0435\u0440\u0456\u0432 GeneralView.label.private=\u041e\u0441\u043e\u0431\u0438\u0441\u0442\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442: GeneralView.yes=\u0422\u0430\u043a GeneralView.no=\u041d\u0456 ConfigView.label.userequestlimiting=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0439 \u0437\u0430\u043f\u0438\u0442, \u043a\u043e\u043b\u0438 \u043c\u0435\u0436\u0430 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0434\u043e\u0441\u044f\u0433\u043d\u0435\u043d\u0430 [\u043d\u0435 \u0434\u0456\u0454 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0456\u0439 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f] ConfigView.label.userequestlimiting.tooltip=\u041e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u043f\u0438\u0442\u0443 \u043d\u0435 \u043d\u0430\u0441\u0442\u0456\u043b\u044c\u043a\u0438 \u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u0435, \u044f\u043a \u0437\u0434\u0430\u0454\u0442\u044c\u0441\u044f, \u0430\u043b\u0435 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u0437\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043d\u0430 \u043f\u043e\u0437\u0438\u0446\u0456\u0457 \u0447\u0435\u0440\u0433\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456, \u043c\u043e\u0436\u043b\u0438\u0432\u043e, \u043f\u043e\u043b\u0456\u043f\u0448\u0443\u0454 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u043d\u0456\u0441\u0442\u044c \u043c\u0435\u0440\u0435\u0436\u0456 ConfigView.label.userequestlimitingpriorities=\u041a\u043e\u043b\u0438 \u043c\u0435\u0436\u0430 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0434\u043e\u0441\u044f\u0433\u043d\u0435\u043d\u0430, \u0437\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u0442\u0438 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043d\u0430 \u0432\u0435\u0440\u0445\u0456\u0432\u0446\u0456 \u0447\u0435\u0440\u0433\u0438 ConfigView.section.logging.timestamp=\u0424\u043e\u0440\u043c\u0430\u0442 \u0447\u0430\u0441\u0443 Peers.column.timetocomplete=\u0417\u0430\u043b\u0438\u0448\u043e\u043a \u0447\u0430\u0441\u0443 Peers.column.timetocomplete.info=\u0427\u0430\u0441, \u044f\u043a\u0438\u0439 \u0437\u0430\u043b\u0438\u0448\u0430\u0454\u0442\u044c\u0441\u044f \u0434\u043e \u0433\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 ConfigView.section.interface.display.suppress.file.download.dialog=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u0430 \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u043e\u0433\u043e \u0432\u0456\u043a\u043d\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0433\u0440\u0435\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0456 \u0441\u0442\u0430\u0442\u0443\u0441\u0443 \u0437\u0430\u043c\u0456\u0441\u0442\u044c \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u043e\u0433\u043e \u0432\u0456\u043a\u043d\u0430 FileDownload.canceled=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0431\u0443\u043b\u043e \u0443\u0441\u043f\u0456\u0448\u043d\u043e \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u043e \u0434\u0456\u0454\u044e \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430: %1 Progress.reporting.status.canceled=\u0421\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0438\u0439 Progress.reporting.status.finished=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0439 Progress.reporting.status.retrying=\u041f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u043d\u044f... Progress.reporting.action.label.retry.tooltip=\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438 \u0434\u0456\u044e Progress.reporting.action.label.remove.tooltip=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0446\u0435\u0439 \u043f\u0440\u043e\u043c\u0456\u0436\u043d\u0438\u0439 \u0437\u0432\u0456\u0442 \u0437 \u0456\u0441\u0442\u043e\u0440\u0456\u0457 Progress.reporting.action.label.cancel.tooltip=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u0434\u0456\u044e Progress.reporting.action.label.detail=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e Progress.reporting.default.error=\u041d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u043e Progress.reporting.no.reports.to.display=\u041d\u0435\u043c\u0430 \u043d\u0456\u044f\u043a\u0438\u0445 \u043f\u0440\u043e\u043c\u0456\u0436\u043d\u0438\u0445 \u0437\u0432\u0456\u0442\u0456\u0432, \u0449\u043e\u0431 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0432 \u0446\u0435\u0439 \u0447\u0430\u0441. Progress.reporting.no.history.to.display=\u041d\u0435\u043c\u0430 \u043d\u0456\u044f\u043a\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0443. Progress.reporting.detail.history.limit=\u041c\u0435\u0436\u0430 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f (%1) \u0434\u043b\u044f \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0443 \u0431\u0443\u043b\u0430 \u043f\u0435\u0440\u0435\u0432\u0438\u0449\u0435\u043d\u0430; \u043f\u043e\u0434\u0430\u043b\u044c\u0448\u0456 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442\u044c \u0434\u043e\u0434\u0430\u043d\u0456 \u0432 \u0456\u0441\u0442\u043e\u0440\u0456\u044e Progress.reporting.statusbar.button.tooltip=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0432\u0456\u043a\u043d\u043e \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0443 webui.bindip=\u0417\u0430\u0445\u043e\u043f\u043b\u0435\u043d\u043d\u044f IP - \u043a\u043e\u043b\u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u0437\u0430\u043f\u0438\u0442\u0430\u043d\u0438\u0439 * v3.MainWindow.text.log.in=\u0412\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438 v3.MainWindow.text.log.out=\u041f\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438 v3.MainWindow.text.get.started=\u041f\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438\u0441\u044f v3.MainWindow.text.my.account=\u041c\u0456\u0439 \u0430\u043a\u0430\u0443\u043d\u0442 v3.MainWindow.text.my.profile=\u041f\u0440\u043e\u0444\u0456\u043b\u044c OpenTorrentWindow.simple.open=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 (\u0444\u0430\u0439\u043b, \u0430\u0434\u0440\u0435\u0441\u0430, \u0445\u0435\u0448) Progress.reporting.window.remove.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043d\u0435\u0447\u0438\u043d\u043d\u0456 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0438 Progress.reporting.window.remove.auto.tooltip=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0456, \u043d\u0435\u0432\u0434\u0430\u043b\u0456 \u0442\u0430 \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0456 \u043f\u0440\u043e\u0446\u0435\u0441\u0438 Progress.reporting.window.remove.now=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043d\u0435\u0447\u0438\u043d\u043d\u0456 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0438 Progress.reporting.window.remove.now.tooltip=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0456, \u043d\u0435\u0432\u0434\u0430\u043b\u0456 \u0442\u0430 \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0456 \u043f\u0440\u043e\u0446\u0435\u0441\u0438 dhttracker.tracklimitedwhenonline=\u0412\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u0442\u0438 \u043d\u0438\u0437\u044c\u043a\u043e\u0440\u0456\u0432\u043d\u0435\u0432\u0438\u0439 \u0442\u0440\u0435\u043a\u0456\u043d\u0433 \u0440\u0435\u0441\u0443\u0440\u0441\u0443 \u0432 \u043e\u043d\u043b\u0430\u0439\u043d\u0456, \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0445\u0440\u0435\u0441\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f TorrentOptionsView.multi.title.short=\u041e\u043f\u0446\u0456\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 TorrentOptionsView.multi.title.full=\u041e\u043f\u0446\u0456\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 MyTorrentsView.menu.open_parent_folder=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u0435\u043a\u0443, \u044f\u043a\u0430 \u043c\u0456\u0441\u0442\u0438\u0442\u044c ConfigView.section.style.use_show_parent_folder=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 "%1" \u0437\u0430\u043c\u0456\u0441\u0442\u044c "%2" \u0432 \u043c\u0435\u043d\u044e \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 ConfigView.section.style.use_show_parent_folder.tooltip=\u0412\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0446\u0456\u0454\u0457 \u043e\u043f\u0446\u0456\u0457 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u0412\u0430\u043c \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0443 \u0442\u0435\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u043d\u043e\u043a.\n\u041f\u0440\u043e\u0442\u0435, \u0446\u0435, \u043c\u043e\u0436\u043b\u0438\u0432\u043e, \u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043d\u0435 \u0432\u0438\u0431\u0440\u0430\u043d\u0435. PeerManager.status.ps_disabled=\u0414\u0436\u0435\u0440\u0435\u043b\u043e \u0443\u0447\u0430\u043d\u0438\u043a\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0435 ConfigView.section.stats.exportfiles=\u0415\u043a\u0441\u043f\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043f\u0440\u043e \u0444\u0430\u0439\u043b updater.cant.write.to.app.title=\u041d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u0438 \u0442\u0435\u043a\u0443 \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u043d\u043a\u0443 updater.cant.write.to.app.details=\u0422\u0435\u043a\u0430"%1" \u043d\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0443\u0454\u0442\u044c\u0441\u044f.\n\n\u0426\u0435 \u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0436\u0430\u0442\u0438\u043c\u0435 \u043c\u0430\u0439\u0431\u0443\u0442\u043d\u0456\u043c \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043d\u043e\u0433\u043e \u0437\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0435\u043d\u043d\u044f \u0431\u0443\u0442\u0438 \u0437\u0430\u0441\u0442\u043e\u0441\u043e\u0432\u0430\u043d\u0438\u043c\u0438.\n\n\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u043f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f Wiki \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457. plugin.install.class_version_error=\u0414\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043d\u043e\u0432\u0456\u0448\u0443 \u0432\u0435\u0440\u0441\u0456\u044e Java. v3.MainWindow.tab.minilibrary=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c v3.MainWindow.tab.events=\u0414\u0456\u044f\u043b\u044c\u043d\u0456\u0441\u0442\u044c button.columnsetup.tooltip=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0441\u0442\u043e\u0432\u043f\u0446\u0456\u0432 v3.activity.remove.title=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043f\u043e\u0434\u0456\u044e \u0434\u0456\u044f\u043b\u044c\u043d\u043e\u0441\u0442\u0456 v3.activity.remove.text=\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u043f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u043f\u043e\u0434\u0456\u044e \u0434\u0456\u044f\u043b\u044c\u043d\u043e\u0441\u0442\u0456 '%1'? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 Menu.show.torrent.menu=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043c\u0435\u043d\u044e \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 Menu.show.torrent.menu.tooltip=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043c\u0435\u043d\u044e \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u043d\u0430 \u0432\u0438\u0449\u043e\u043c\u0443 \u0440\u044f\u0434\u043a\u0443 \u043f\u0430\u043d\u0435\u043b\u0456 \u043c\u0435\u043d\u044e #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=\u0421\u0442\u0430\u0442\u0443\u0441 \u043c\u0435\u0440\u0435\u0436\u0456 plugin.aznetstatus.pingtarget=\u041c\u0435\u0442\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0443 \u043f\u0456\u043d\u0433\u0443 \u0430\u0431\u043e \u0441\u043b\u0456\u0434\u0443 ConfigView.section.style.usePathFinder=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 '\u0428\u0443\u043a\u0430\u0447\u0430 \u0448\u043b\u044f\u0445\u0443' \u0437\u0430\u043c\u0456\u0441\u0442\u044c '\u0428\u0443\u043a\u0430\u0447\u0430' menu.sortByColumn=\u0421\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u0437\u0430 %1 MyTorrentsView.menu.manual.per_peer=\u0412\u0440\u0443\u0447\u043d\u0443 (\u0434\u043b\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430) MyTorrentsView.menu.manual.shared_peers=\u0412\u0440\u0443\u0447\u043d\u0443 (\u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438) v3.button.removeActivityEntry=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043f\u043e\u0434\u0456\u044e \u0434\u0456\u044f\u043b\u044c\u043d\u043e\u0441\u0442\u0456 v3.splash.initSkin=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 v3.splash.hookPluginUI=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0432\u0438\u0433\u043b\u044f\u0434\u0443 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c OpenTorrentWindow.mb.notTorrent.cannot.display=\u041d\u0435 \u0432 \u0437\u043c\u043e\u0437\u0456 \u043d\u0430\u043b\u0435\u0436\u043d\u0438\u043c \u0447\u0438\u043d\u043e\u043c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0434\u0430\u043d\u0456 MainWindow.menu.window.zoom.maximize=\u0420\u043e\u0437\u0433\u043e\u0440\u043d\u0443\u0442\u0438 MainWindow.menu.window.zoom.restore=\u0417\u043c\u0435\u043d\u0448\u0438\u0442\u0438 \u0434\u043e \u0432\u0456\u043a\u043d\u0430 ImageResizer.image.too.small=\u0417\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u0443\u0436\u0435 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0435, \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0456\u043d\u0448\u0435 (\u044f\u043a \u043c\u0456\u043d\u0456\u043c\u0443\u043c %1 x %2) ImageResizer.title=\u0426\u0435\u0439 \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u0412\u0430\u043c \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438, \u044f\u043a \u0432\u0430\u0448 thumbnail \u0432\u0438\u0433\u043b\u044f\u0434\u0430\u0442\u0438\u043c\u0435 \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0456 Vuze ImageResizer.move.image=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0456\u0442\u044c \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f, \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u0443\u044e\u0447\u0438 \u0446\u0435 ImageResizer.move.image.with.slider=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0456\u0442\u044c \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f, \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u0443\u044e\u0447\u0438 \u0446\u0435, \u0437\u043c\u0456\u043d\u044e\u0439\u0442\u0435 \u0440\u043e\u0437\u043c\u0456\u0440 \u0446\u044c\u043e\u0433\u043e, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0447\u0438 \u0441\u043b\u0430\u0439\u0434\u0435\u0440 security.crypto.title=\u0414\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u043a\u043b\u044e\u0447\u0430 \u0434\u043b\u044f \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f security.crypto.encrypt=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c, \u0449\u043e\u0431 \u0437\u0430\u0445\u0438\u0441\u0442\u0438\u0442\u0438 \u0432\u0430\u0448 \u043d\u0435\u0449\u043e\u0434\u0430\u0432\u043d\u043e \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0439 \u043a\u043b\u044e\u0447 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f. \u041d\u0435 \u0437\u0430\u0431\u0443\u0432\u0430\u0439\u0442\u0435 \u0446\u0435\u0439 \u043f\u0430\u0440\u043e\u043b\u044c, \u043d\u0435\u043c\u0430 \u043d\u0456\u044f\u043a\u043e\u0457 \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0456 \u0432\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 \u0439\u043e\u0433\u043e! security.crypto.decrypt=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c, \u0449\u043e\u0431 \u0440\u043e\u0437\u0431\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438 \u0432\u0430\u0448 \u043a\u043b\u044e\u0447 \u0434\u043e \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f. security.crypto.reason=\u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u0434\u043b\u044f \u0434\u0456\u0457 security.crypto.password=\u041f\u0430\u0440\u043e\u043b\u044c security.crypto.password2=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0430\u0440\u043e\u043b\u044c security.crypto.persist_for=\u041f\u0435\u0440\u0456\u043e\u0434 \u0434\u0456\u0439\u0441\u043d\u043e\u0441\u0442\u0456 \u043f\u0430\u0440\u043e\u043b\u044f security.crypto.persist_for.dont_save=\u041d\u0435 \u0437\u0431\u0435\u0440\u0456\u0433\u0430\u0442\u0438 security.crypto.persist_for.session=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u0441\u0435\u0441\u0456\u044f security.crypto.persist_for.day=1 \u0434\u0435\u043d\u044c security.crypto.persist_for.week=1 \u0442\u0438\u0436\u0434\u0435\u043d\u044c security.crypto.persist_for.30days=30 \u0434\u043d\u0456\u0432 security.crypto.persist_for.forever=\u041d\u0430\u0437\u0430\u0432\u0436\u0434\u0438 security.crypto.password.mismatch.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0430\u0440\u043e\u043b\u044f security.crypto.password.mismatch=\u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u043d\u0456, \u0432\u043a\u0430\u0436\u0456\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e. ConfigView.section.security.group.crypto=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0456 \u0456 \u043e\u0441\u043e\u0431\u0438\u0441\u0442\u0456 \u043a\u043b\u044e\u0447\u0456 ConfigView.section.security.resetkey=\u0421\u043a\u0438\u043d\u0443\u0442\u0438 \u043a\u043b\u044e\u0447\u0456 ConfigView.section.security.resetkey.warning.title=\u041d\u0435\u0431\u0435\u0437\u043f\u0435\u043a\u0430 \u0432\u0442\u0440\u0430\u0442\u0438 \u0434\u0430\u043d\u0438\u0445 ConfigView.section.security.resetkey.warning=\u0412\u0438 \u0437\u0430\u043f\u0435\u0432\u043d\u044f\u0454\u0442\u0435, \u0449\u043e \u0432\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0441\u043a\u0438\u043d\u0443\u0442\u0438 \u043a\u043b\u044e\u0447\u0456 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f? \u042f\u043a\u0449\u043e \u0432\u0438 \u0446\u0435 \u0437\u0440\u043e\u0431\u0438\u0442\u0435, \u0432\u0441\u044f \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0412\u0422\u0420\u0410\u0422\u0418\u0422\u042c\u0421\u042f. \u0422\u0430\u043a\u043e\u0436 \u0456\u043d\u0448\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438 \u043d\u0435 \u0437\u043c\u043e\u0436\u0443\u0442\u044c \u043d\u0430\u0434\u0430\u043b\u0456 \u0437\u0432'\u044f\u0437\u0430\u0442\u0438\u0441\u044f \u0437 \u0412\u0430\u043c\u0438, \u043d\u0435 \u043e\u0442\u0440\u0438\u043c\u0430\u0432\u0448\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430. \u0422\u043e\u0436 \u0434\u043e\u0431\u0440\u0435 \u043f\u043e\u0434\u0443\u043c\u0430\u0439\u0442\u0435 \u0456 \u043b\u0438\u0448\u0435 \u0442\u043e\u0434\u0456 \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0443\u0439\u0442\u0435. ConfigView.section.security.unlockkey=\u0412\u0456\u0434\u043c\u0438\u043a\u0430\u043d\u043d\u044f \u043a\u043b\u044e\u0447\u0456\u0432 ConfigView.section.security.unlockkey.button=\u0412\u0456\u0434\u0456\u043c\u043a\u043d\u0443\u0442\u0438 ConfigView.section.security.publickey=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0439 \u043a\u043b\u044e\u0447 ConfigView.section.security.publickey.undef=\u0429\u0435 \u043d\u0435 \u0432\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 ConfigView.section.security.resetkey.error.title=\u0414\u0456\u044f \u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0430 ConfigView.section.security.resetkey.error=\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0441\u043a\u0438\u043d\u0443\u0442\u0438 \u043a\u043b\u044e\u0447\u0456 ConfigView.section.security.unlockkey.error=\u041d\u0435\u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0432\u0456\u0434\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043a\u043b\u044e\u0447 - \u043d\u0435\u043a\u043e\u0440\u0435\u043a\u0442\u043d\u0438\u0439 \u043f\u0430\u0440\u043e\u043b\u044c ConfigView.copy.to.clipboard.tooltip=\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443 Views.plugins.azbuddy.title=\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0456 Browser.popup.error.no.access=\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0438\u0442\u0456 \u0440\u0435\u0441\u0443\u0440\u0441\u0443.\n\u0421\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u043d\u043e\u0432\u0443 \u043f\u0456\u0437\u043d\u0456\u0448\u0435. ConfigView.label.queue.stoponcebandwidthmet=\u041d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u0436\u043e\u0434\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432, \u043a\u043e\u043b\u0438 \u043c\u0435\u0436\u0430 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0430\u0431\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u043e\u0441\u044f\u0433\u043d\u0443\u0442\u0430 ConfigView.section.style.forceMozilla=\u0417\u043c\u0443\u0441\u0438\u0442\u0438 Vuze \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0432\u0456\u0434\u0436\u0435\u0442\u0438 Mozilla \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434\u0430\u0447\u0430 [\u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0456 xulrunner \u0430\u0431\u043e firefox 3; \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0438\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a] ConfigView.section.style.xulRunnerPath=\u0412\u043a\u0430\u0437\u0430\u0442\u0438 \u0432\u0440\u0443\u0447\u043d\u0443 \u0448\u043b\u044f\u0445 \u0434\u043e XulRunner \u0430\u0431\u043e Firefox [\u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0434\u043b\u044f FF3; \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443] azbuddy.name=\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0456 azbuddy.enabled=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f azbuddy.disabled=\u0414\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0435, \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u044c\u0442\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0456 \u0437\u043c\u0456\u043d\u0456\u0442\u044c \u0457\u0445. azbuddy.nickname=\u0412\u0430\u0448 \u043d\u0456\u043a azbuddy.msglog.title=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u043f\u0440\u043e \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f azbuddy.addtorrent.title=\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f? azbuddy.addtorrent.msg=\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u044c '%1' \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u0438\u0432 \u0412\u0430\u043c '%2'.\n\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0434\u043e\u0434\u0430\u0442\u0438 \u0446\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f? azbuddy.contextmenu=\u0412\u0456\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044e azbuddy.ui.mykey=\u041c\u0456\u0439 \u043a\u043b\u044e\u0447: azbuddy.ui.add=\u0414\u043e\u0434\u0430\u0442\u0438 azbuddy.ui.new_buddy=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043a\u043b\u044e\u0447 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f: azbuddy.ui.table.name=\u0406\u043c'\u044f azbuddy.ui.table.online=\u0412 \u043c\u0435\u0440\u0435\u0436\u0456 azbuddy.ui.table.last_msg=\u041e\u0441\u0442\u0430\u043d\u043d\u0454 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f azbuddy.ui.menu.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 azbuddy.ui.menu.copypk=\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0439 \u043a\u043b\u044e\u0447 azbuddy.ui.menu.send=\u041d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f azbuddy.ui.menu.send_msg=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0442\u0435\u043a\u0441\u0442, \u044f\u043a\u0438\u0439 \u0412\u0438 \u0445\u043e\u0447\u0435\u0442 \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044e(\u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f\u043c) azbuddy.ui.menu.ping=\u041f\u0456\u043d\u0433 azbuddy.ui.menu.ygm=\u041d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 YGM azbuddy.ui.menu.enc=\u0417\u0430\u0448\u0438\u0444\u0440\u0443\u0432\u0430\u0442\u0438 \u0411\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443 azbuddy.ui.menu.dec=\u0420\u043e\u0437\u0448\u0438\u0444\u0440\u0443\u0432\u0430\u0442\u0438 \u0411\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443 azbuddy.ui.menu.sign=\u041f\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438 \u0411\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443 azbuddy.ui.menu.verify=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u0411\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443 azbuddy.ui.table.lastseen=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0435 Button.retry=&\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438 Button.ignore=&\u0406\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 DHTView.general.skew=\u041d\u0430\u0445\u0438\u043b: azbuddy.ui.table.msg_in=\u0412\u0445\u0456\u0434\u043d\u0435 azbuddy.ui.table.msg_out=\u041d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0435 v3.MainWindow.menu.view.footer=\u041f\u0430\u043d\u0435\u043b\u044c \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432 azbuddy.downspeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f, K\u0431\u0456\u0442/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] security.crypto.badpw=\u0417\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0443\u0432\u0430\u043d\u0438\u0439 \u043f\u0430\u0440\u043e\u043b\u044c \u0431\u0443\u0432 \u043d\u0435\u043a\u043e\u0440\u0435\u043a\u0442\u043d\u0438\u0439 ConfigView.section.security.backupkeys=\u041f\u0440\u043e\u0434\u0443\u0431\u043b\u044c\u043e\u0432\u0430\u043d\u0456 \u043a\u043b\u044e\u0447\u0456 \u0434\u043e \u0444\u0430\u0439\u043b\u0443 ConfigView.section.security.backupkeys.button=\u0414\u0443\u0431\u043b\u044e\u0432\u0430\u0442\u0438 ConfigView.section.security.restorekeys=\u0412\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 \u043a\u043b\u044e\u0447\u0456 \u0432\u0456\u0434 \u0444\u0430\u0439\u043b\u0443 ConfigView.section.security.restorekeys.button=\u0412\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 ConfigView.section.security.op.error.title=\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u0442\u0438 \u0434\u0456\u044e ConfigView.section.security.op.error=\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0442\u0438 \u0434\u0456\u044e:\n %1 ConfigView.section.security.restart.title=\u041d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443 ConfigView.section.security.restart.msg=Vuze \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u043d\u044f \u0434\u0456\u0457. ConfigView.section.security.system.managed=\u041a\u0435\u0440\u043e\u0432\u0430\u043d\u0438\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u044e \u0437\u0430\u0445\u0438\u0441\u0442 \u043a\u043b\u044e\u0447\u0456\u0432 azbuddy.ui.table.msg_queued=\u0427\u0435\u0440\u0433\u043e\u0432\u0435 azbuddy.ui.menu.chat=\u0427\u0430\u0442 azbuddy.chat.title=\u0427\u0430\u0442 Vuze azbuddy.chat.says=%1 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u0438\u043b\u043e: Button.bar.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 Button.bar.hide=\u0421\u0445\u043e\u0432\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c Button.bar.share=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 Button.bar.add=\u0414\u043e\u0434\u0430\u0442\u0438 Button.bar.edit=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 Button.bar.edit.cancel=\u0417\u0430\u043a\u0456\u043d\u0447\u0438\u0442\u0438 \u0440\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u043d\u043d\u044f v3.MainWindow.menu.view.pluginbar=\u041f\u0430\u043d\u0435\u043b\u044c \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f MainWindow.dialog.select.vuze.file=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0444\u0430\u0439\u043b Vuze MainWindow.menu.file.open.vuze=\u0424\u0430\u0439\u043b Vuze... metasearch.addtemplate.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u043e\u0448\u0443\u043a\u043e\u0432\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d? metasearch.addtemplate.desc=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u043e\u0448\u0443\u043a\u043e\u0432\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d '%1'? v3.share.private.title=\u0420\u043e\u0437\u0434\u0430\u0447\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 v3.share.private.text=\u0412\u0438\u0431\u0440\u0430\u043d\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 \u043f\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u044f\u043a "\u041e\u0441\u043e\u0431\u0438\u0441\u0442\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442".\n\n\u0412\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043a\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u043e\u0441\u043e\u0431\u0438\u0441\u0442\u0438\u043c\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438. metasearch.addtemplate.dup.title=\u0414\u0443\u0431\u043b\u044e\u0432\u0430\u0442\u0438 \u0448\u0430\u0431\u043b\u043e\u043d metasearch.addtemplate.dup.desc=\u041f\u043e\u0448\u0443\u043a\u043e\u0432\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d %1 \u0432\u0436\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 metasearch.export.select.template.file=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0448\u0430\u0431\u043b\u043e\u043d metasearch.import.select.template.file=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0448\u0430\u0431\u043b\u043e\u043d dialog.uiswitch.title=\u041f\u0435\u0440\u0435\u043c\u0438\u043a\u0430\u043d\u043d\u044f \u0432 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f Vuze dialog.uiswitch.text=\u0414\u043b\u044f \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0446\u0456\u0454\u0457 \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0456 \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Vuze.\n\nVuze \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f. dialog.uiswitch.button=\u041f\u0435\u0440\u0435\u043c\u043a\u043d\u0443\u0442\u0438 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f Vuze azbuddy.tracker.enabled=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 '\u041f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u043d\u044f \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432' \u0434\u043b\u044f \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u043e\u0431\u043c\u0456\u043d\u0443 \u0437 \u0412\u0430\u0448\u0438\u043c\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f\u043c\u0438 azbuddy.protocolspeed=\u0412\u0435\u0440\u0445\u043d\u044f \u043c\u0435\u0436\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f, \u041a\u0431\u0456\u0442/\u0441 v3.MainWindow.button.download=\u0417\u0430\u0431\u0440\u0430\u0442\u0438 v3.MainWindow.button.run=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439 \u0444\u0430\u0439\u043b v3.activity.header.downloads=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c v3.activity.header.vuze.news=\u041d\u043e\u0432\u0438\u043d\u0438 Vuze message.taking.too.long=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043b\u043e\u0441\u044f, \u0449\u043e \u0432\u0441\u0435 \u0432\u0456\u0434\u0431\u0443\u0434\u0435\u0442\u044c\u0441\u044f \u043d\u0430\u0431\u0430\u0433\u0430\u0442\u043e \u0448\u0432\u0438\u0434\u0448\u0435\n\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c 'ESC', \u0449\u043e\u0431 \u0441\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u0446\u044e \u0434\u0456\u044e message.status.success=\u0423\u0441\u043f\u0456\u0448\u043d\u043e azbuddy.tracker.bbb.status.title=\u041f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u043d\u044f \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432 azbuddy.tracker.bbb.status.title.tooltip=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u0434\u0432\u0456\u0447\u0456 \u0434\u043b\u044f \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 azbuddy.tracker.bbb.status.idle=\u041d\u0435\u043c\u0430 \u043f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u043d\u044f azbuddy.tracker.bbb.status.nli=\u041d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u043b\u043e\u0433\u0456\u043d azbuddy.tracker.bbb.status.in=\u042f \u043f\u043e\u0447\u0430\u0432 \u043f\u0440\u0438\u0441\u043a\u043e\u0440\u044e\u0432\u0430\u0442\u0438 azbuddy.tracker.bbb.status.out=\u041f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u0456 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456 v3.MainWindow.search.go.tooltip=\u0412\u0438\u043a\u043e\u043d\u0430\u0442\u0438 \u043f\u043e\u0448\u0443\u043a v3.MainWindow.search.last.tooltip=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438\u0441\u044f \u0434\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0456\u0432 \u043f\u043e\u0448\u0443\u043a\u0443 metasearch.addtemplate.done.title=\u0428\u0430\u0431\u043b\u043e\u043d \u0434\u043e\u0434\u0430\u043d\u0438\u0439 metasearch.addtemplate.done.desc=\u0428\u0430\u0431\u043b\u043e\u043d '%1' \u0432\u0434\u0430\u043b\u043e \u0434\u043e\u0434\u0430\u043d\u0438\u0439.\n\u0412\u0456\u043d \u0432\u0440\u0430\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u043c\u0443 \u043f\u043e\u0448\u0443\u043a\u0443! ConfigView.section.security.nopw=\u041f\u0430\u0440\u043e\u043b\u044c \u043d\u0435 \u0437\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0443\u0454\u0442\u044c\u0441\u044f ConfigView.section.security.nopw_v=\u041f\u0430\u0440\u043e\u043b\u0456 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456, \u0437\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u0443\u0439\u0442\u0435\u0441\u044f \u0432 Vuze fileplugininstall.install.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f? fileplugininstall.install.desc=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f '%1', \u0432\u0435\u0440\u0441\u0456\u044f %2? fileplugininstall.duplicate.title=\u0414\u0443\u0431\u043b\u044e\u0432\u0430\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f fileplugininstall.duplicate.desc=\u0412\u0435\u0440\u0441\u0456\u044f %2 \u0434\u043b\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f '%1' \u0432\u0436\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430 azbuddy.online_status=\u0421\u0442\u0430\u0442\u0443\u0441 azbuddy.os_online=\u0412 \u043c\u0435\u0440\u0435\u0436\u0456 azbuddy.os_away=\u0412\u0456\u0434\u0441\u0443\u0442\u043d\u0456\u0439 azbuddy.os_not_avail=\u041d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 azbuddy.os_busy=\u0417\u0430\u0439\u043d\u044f\u0442\u0438\u0439 azbuddy.os_offline=\u041f\u043e\u0437\u0430 \u043c\u0435\u0440\u0435\u0436\u0435\u044e azbuddy.ui.menu.disconnect=\u0412\u0456\u0434'\u0454\u0434\u043d\u0430\u0442\u0438 azbuddy.enable_chat_notif=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u0447\u0430\u0442\u0443 progress.window.msg.progress=\u0414\u043e\u0447\u0435\u043a\u0430\u0439\u0442\u0435\u0441\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0434\u0456\u0457 ConfigView.section.connection.advanced.read_select=\u0417\u0430\u0442\u0440\u0438\u043c\u043a\u0430 \u0447\u0438\u0442\u0430\u043d\u043d\u044f (\u043c\u0441, \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e: %1) ConfigView.section.connection.advanced.read_select_min=\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0435 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0447\u0438\u0442\u0430\u043d\u043d\u044f (\u043c\u0441, \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e: %1) ConfigView.section.connection.advanced.write_select=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f (\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434\u0438, \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e %1) ConfigView.section.connection.advanced.write_select_min=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0435 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f (\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434, \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e %1) DetailedListView.title=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u0438\u0439 \u0437\u0432\u0456\u0442 ConfigView.section.connection.network.max.outstanding.connect.attempts=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0447\u0430\u043d\u0438\u0445 \u0432\u0438\u0445\u0456\u0434\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c plugins.init.force_enabled=Vuze \u0432\u0438\u044f\u0432\u0438\u0432 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f "%1", \u044f\u043a\u0438\u0439 \u0431\u0443\u043b\u043e \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u043e - \u0446\u0435 \u0434\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e Vuze \u043f\u0440\u0430\u0446\u044e\u0432\u0430\u0442\u0438 \u043d\u0430\u043b\u0435\u0436\u043d\u0438\u043c \u0447\u0438\u043d\u043e\u043c. ConfigView.section.connection.prefer.udp=\u041f\u0435\u0440\u0435\u0432\u0430\u0433\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f\u043c UDP subscript.add.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443? subscript.add.desc=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443 '%1'? subscript.add.dup.title=\u0414\u0443\u0431\u043b\u044e\u0432\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443 subscript.add.dup.desc=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430 '%1' \u0432\u0436\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430. subscript.add.upgrade.title=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443? subscript.add.upgrade.desc=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443 '%1'? subscript.add.upgradeto.desc=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0432\u0435\u0440\u0441\u0456\u044f %1 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438'%2'.\n\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438? azsubs.contextmenu.addassoc=\u0410\u0441\u043e\u0446\u0456\u044e\u0432\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438 azsubs.contextmenu.lookupassoc=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 \u0430\u0441\u043e\u0446\u0456\u0430\u0446\u0456\u0439 iconBar.start=\u041f\u043e\u0447\u0430\u0442\u0438 iconBar.stop=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 iconBar.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 iconBar.up=\u0414\u043e\u0433\u043e\u0440\u0438 iconBar.down=\u0414\u043e\u043d\u0438\u0437\u0443 iconBar.run=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 iconBar.editcolumns=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0441\u0442\u043e\u0432\u043f\u0446\u044f iconBar.top=\u0420\u0443\u0445\u0430\u0442\u0438 \u043d\u0430 \u0432\u0435\u0440\u0448\u0438\u043d\u0443 iconBar.bottom=\u0420\u0443\u0445\u0430\u0442\u0438 \u043d\u0430 \u0434\u043d\u043e iconBar.queue=\u041f\u043e\u0447\u0430\u0442\u0438 iconBar.open=\u0414\u043e\u0434\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 iconBar.share=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 iconBar.share.tooltip=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e iconBar.details=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e iconBar.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 iconBar.play=\u0413\u0440\u0430\u0442\u0438 iconBar.queue.tooltip=B \u0447\u0435\u0440\u0433\u0443 v3.MainWindow.menu.view.sidebar=\u0411\u043e\u043a\u043e\u0432\u0430 \u043f\u0430\u043d\u0435\u043b\u044c v3.MainWindow.menu.view.actionbar=\u041f\u0430\u043d\u0435\u043b\u044c \u0434\u0456\u0439 v3.MainWindow.menu.view.toolbars=\u041f\u0430\u043d\u0435\u043b\u0456 \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432 ump.install=\u0412\u0456\u0434\u0435\u043e \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0456\u0432 \u0434\u043b\u044f \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f. \u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430. subscriptions.listwindow.title=\u0428\u0443\u043a\u0430\u0447 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442 subscriptions.listwindow.autochecktext=Vuze \u043c\u043e\u0436\u0435 \u0437\u043d\u0430\u0439\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438, \u043f\u043e\u0432'\u044f\u0437\u0430\u043d\u0456 \u0437 \u0432\u043c\u0456\u0441\u0442\u043e\u043c \u0432\u0430\u0448\u043e\u0457 \u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438. \u0423\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0446\u044e \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c? subscriptions.listwindow.loadingtext=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443, \u043f\u043e\u0432'\u044f\u0437\u0430\u043d\u0438\u0445 \u0437 %1 subscriptions.listwindow.failed=\u041d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442 subscriptions.listwindow.popularity=\u041f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0456\u0441\u0442\u044c subscriptions.listwindow.popularity.unknown=\u041d\u0435\u0432\u0456\u0434\u043e\u043c\u043e subscriptions.listwindow.name=\u0406\u043c'\u044f subscriptions.listwindow.subscribe=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430 TableColumn.header.azsubs.ui.column.subs=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430 subscriptions.listwindow.popularity.reading=\u0427\u0438\u0442\u0430\u043d\u043d\u044f... PluginDeprecation.log.start=\u0426\u0435 \u0432\u0456\u043a\u043d\u043e \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438, \u044f\u043a\u0456 \u0441\u0442\u0432\u043e\u0440\u044e\u044e\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0456\u043e\u043d\u0430\u043b\u044c\u043d\u0456\u0441\u0442\u044c, \u044f\u043a\u043e\u0457 \u043d\u0435 \u0431\u0443\u0434\u0435 \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0456 \u043c\u0430\u0439\u0431\u0443\u0442\u043d\u0456\u0445 \u0432\u0435\u0440\u0441\u0456\u0439 Vuze.\n\u0412\u0430\u043c \u043d\u0435 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0432\u0438\u043b\u0443\u0447\u0430\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438, \u0432\u0438 \u043f\u043e\u0432\u0438\u043d\u043d\u0456 \u043b\u0438\u0448\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u043d\u0430 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0434\u043e \u043d\u0430\u0439\u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0448\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457.\n\u042f\u043a\u0449\u043e \u0432 \u0412\u0430\u0441 \u043d\u0430\u0439\u043d\u043e\u0432\u0456\u0448\u0430 \u0432\u0435\u0440\u0441\u0456\u044f, \u0441\u043a\u043e\u043f\u0456\u044e\u0439\u0442\u0435 \u0432\u043c\u0456\u0441\u0442 \u0446\u044c\u043e\u0433\u043e \u0432\u0456\u043a\u043d\u0430 \u0456 \u0440\u043e\u0437\u043c\u0456\u0441\u0442\u0456\u0442\u044c \u0446\u0435 \u043d\u0430 \u043e\u0441\u044c \u0446\u044c\u043e\u043c\u0443 \u0444\u043e\u0440\u0443\u043c\u0456:\n \t%1\n\n PluginDeprecation.log.details=---------\n\u0406\u0414\u0415\u041d\u0422\u0418\u0424\u0406\u041a\u0410\u0422\u041e\u0420: %1\n\u0417\u041c\u0406\u0421\u0422: %2\n\n*** \u041f\u041e\u0427\u0410\u0422\u041e\u041a ***\n%3*** \u041a\u0406\u041d\u0415\u0426\u042c ***\n\n PluginDeprecation.view=\u0412\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c PluginDeprecation.alert=\u0414\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043b\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c, \u044f\u043a\u0430 \u0431\u0443\u0434\u0435 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u0430 \u043d\u0430\u0434\u0430\u043b\u0456, - \u0432\u0456\u0434\u043a\u0440\u0438\u0439\u0442\u0435 \u043b\u043e\u0433 \u0412\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457. TableColumn.header.Thumbnail=\u041f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0430 TableColumn.header.Thumbnail.info=\u041f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0430, \u044f\u043a\u0430 \u043f\u043e\u043a\u0430\u0437\u0443\u0454 \u0432\u043c\u0456\u0441\u0442 \u043d\u0430 Vuze; \u0434\u043b\u044f \u0432\u0441\u044c\u043e\u0433\u043e \u0456\u043d\u0448\u043e\u0433\u043e \u0432\u043c\u0456\u0441\u0442\u0443 \u0437\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0443\u0454 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0438 \u041e\u0421. v3.MainWindow.menu.getting_started=&\u041b\u0435\u0433\u043a\u0438\u0439 \u043f\u043e\u0447\u0430\u0442\u043e\u043a MainWindow.menu.community=\u0421\u0443\u0441\u043f\u0456&\u043b\u044c\u0441\u0442\u0432\u043e MainWindow.menu.help.faq=&FAQ MainWindow.menu.community.wiki=\u0421\u0443\u0441\u043f\u0456\u043b\u044c\u043d\u0430 &\u0432\u0456\u043a\u0456-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0430 MainWindow.menu.community.forums=\u0421\u0443\u0441\u043f\u0456\u043b\u044c\u043d\u0456 \u0444\u043e&\u0440\u0443\u043c\u0438 MainWindow.menu.community.blog=&\u0411\u043b\u043e\u0433 Vuze MainWindow.menu.help.support=&\u0414\u043e\u0432\u0456\u0434\u043a\u0430 \u0456 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0430 externalLogin.title=\u0417\u0430\u043f\u0438\u0442 \u043b\u043e\u0433\u0456\u043d\u0443 externalLogin.explanation=\u0428\u0430\u0431\u043b\u043e\u043d "%1" \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u043b\u043e\u0433\u0456\u043d. \u041f\u0456\u0441\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043b\u043e\u0433\u0456\u043d\u0443 \u0432\u0456\u043a\u043d\u043e \u0437\u0430\u043a\u0440\u0438\u0454\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e. externalLogin.explanation.capture=\u0412\u0430\u043c \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u043f\u0441\u0435\u0432\u0434\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0449\u043e\u0431 \u0441\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0446\u0435\u0439 \u0448\u0430\u0431\u043b\u043e\u043d. Button.done=\u0412\u0438\u043a\u043e\u043d\u0430\u043d\u043e GeneralView.torrent_created_on_and_by=%1 \u0437\u0430 %2 Button.continue=\u041f\u0440\u043e\u0434\u043e\u0432\u0436\u0438\u0442\u0438 Button.preview=\u041f\u043e\u043f\u0435\u0440\u0435\u0434\u043d\u0456\u0439 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 Subscription.menu.forcecheck=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0437\u0430\u0440\u0430\u0437 Subscription.menu.clearall=\u041f\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0438 \u044f\u043a \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0456 Subscription.menu.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 sidebar.Library=\u041c\u043e\u044f \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0430 sidebar.LibraryDL=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f sidebar.LibraryCD=\u0412\u0438\u043a\u043e\u043d\u0430\u043d\u0456 authenticator.location=\u041c\u0456\u0441\u0446\u0435\u0437\u043d\u0430\u0445\u043e\u0434\u0436\u0435\u043d\u043d\u044f authenticator.details=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e v3.MainWindow.menu.showActionBarText=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0442\u0435\u043a\u0441\u0442 subscript.import.fail.title=\u041d\u0435\u0432\u0434\u0430\u043b\u0438\u0439 \u0456\u043c\u043f\u043e\u0440\u0442 subscript.import.fail.desc=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e: %1 Subscription.menu.export=\u0415\u043a\u0441\u043f\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438 subscript.export.select.template.file=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443 Button.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 Button.send=\u041d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 Button.back=\u041d\u0430\u0437\u0430\u0434 sidebar.LibraryUnopened=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 TableColumn.header.unopened=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 Unopened.bigView.header=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 Subscription.menu.deleteall=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0438 Subscription.menu.reset=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438\u0441\u044f \u0434\u043e \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0443 ConfigView.section.Subscriptions=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438 subscriptions.config.maxresults=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0456\u0432, \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0445 \u0437\u0430 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043e] v3.activity.button.readall=\u041f\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u044f\u043a \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0456 TableColumn.header.activityNew=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 TableColumn.header.activityType=\u0422\u0438\u043f TableColumn.header.activityText=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f TableColumn.header.activityDate=\u0414\u0430\u0442\u0430 \u0434\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044f TableColumn.header.activityActions=\u0414\u0456\u0457 Subscription.menu.resetauth=\u0421\u043a\u0438\u043d\u0443\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u0456\u0434\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u0457 Search.menu.engines=\u0428\u0430\u0431\u043b\u043e\u043d\u0438 Wizard.Subscription.title=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u0442\u0438 Wizard.Subscription.optin.title=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443 #what you've watched? Discover more with a single click... Wizard.Subscription.subscribe.title=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438 Wizard.Subscription.create.title=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043d\u043e\u0432\u0443 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443 Button.search=\u041f\u043e\u0448\u0443\u043a Button.save=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 Button.add=\u0414\u043e\u0434\u0430\u0442\u0438 Button.createNewSubscription=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043d\u043e\u0432\u0443 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443 Button.availableSubscriptions=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438 Wizard.Subscription.optin.description=\u0417 \u0443\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0438\u043c\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430\u043c\u0438, Vuze \u043f\u043e\u043a\u0430\u0436\u0435 \u0412\u0430\u043c \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438, \u044f\u043a\u0456 \u043c\u0430\u043b\u0438 \u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0434\u043e \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0443 \u0432\u0430\u0448\u0456\u0439 \u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u0446\u0456, \u0456 \u0434\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u044c \u0412\u0430\u043c \u0437\u043d\u0430\u0442\u0438, \u043a\u043e\u043b\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f, \u044f\u043a\u0443 \u0412\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u043b\u0438, \u0441\u0442\u0430\u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u044e \u0434\u043b\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.\n\n\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0443\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438? Wizard.Subscription.create.rss=RSS-\u0440\u043e\u0437\u0441\u0438\u043b\u043a\u0430 Wizard.Subscription.create.search=\u041f\u043e\u0448\u0443\u043a Wizard.Subscription.search.subtitle1=\u0414\u043b\u044f \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0432\u043b\u0430\u0441\u043d\u043e\u0457 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438 \u0432\u043a\u0430\u0436\u0456\u0442\u044c \u0457\u0457 \u0432 \u043f\u043e\u0448\u0443\u043a\u0443: Wizard.Subscription.search.subtitle2=\u0429\u043e \u043c\u043e\u0436\u0443 \u044f \u0437\u043d\u0430\u0439\u0442\u0438? Wizard.Subscription.search.subtitle2.sub1=\u0424\u0456\u043b\u044c\u043c\u0438 \u0432 \u0432\u0438\u0441\u043e\u043a\u043e\u043c\u0443 \u0434\u043e\u0437\u0432\u043e\u043b\u0456, \u0441\u0435\u0440\u0456\u0430\u043b\u0438, \u0448\u043e\u0443, \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u0438 \u0432 \u043c\u0435\u0440\u0435\u0436\u0456 Vuze Network Wizard.Subscription.search.subtitle2.sub2=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u0437 \u0443\u0441\u0456\u0445 \u0422\u0435\u043d\u0435\u0442 Wizard.Subscription.search.subtitle3=\u041a\u043e\u043b\u0438 \u0432\u0430\u0448\u0430 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f, \u0432\u0438 \u043e\u0442\u0440\u0438\u043c\u0430\u0454\u0442\u0435 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u0456 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0431\u043e\u043a\u043e\u0432\u043e\u0457 \u043f\u0430\u043d\u0435\u043b\u0456 \u0449\u043e\u0440\u0430\u0437\u0443, \u043f\u0440\u0438 \u043d\u043e\u0432\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u0445, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u0434\u043b\u044f \u043f\u043e\u0448\u0443\u043a\u0443. Wizard.Subscription.rss.subtitle1=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0443: Wizard.Subscription.rss.subtitle2=\u0411\u0430\u0433\u0430\u0442\u043e \u043f\u0443\u0431\u043b\u0456\u043a\u0443\u044e\u0447\u0438\u0445 \u0437\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0443\u044e\u0442\u044c \u0440\u043e\u0437\u0441\u0438\u043b\u043a\u0443 RSS \u0457\u0445\u043d\u044c\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457. \u0417\u043d\u0430\u0439\u0434\u0456\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0443 \u043d\u0430 \u0441\u0430\u0439\u0442\u0456 \u043f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u043b\u044c\u043d\u043e\u0433\u043e, \u0441\u043a\u043e\u043f\u0456\u044e\u0439\u0442\u0435 \u0457\u0457 \u0456 \u0432\u0441\u0442\u0430\u0432\u0442\u0435 \u0432 \u043f\u043e\u043b\u0435, \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438. Wizard.Subscription.rss.subtitle3=\u0417\u0431\u0435\u0440\u0456\u0433\u0448\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0443, \u0432\u0438 \u043e\u0442\u0440\u0438\u043c\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0449\u043e\u0440\u0430\u0437\u0443, \u043a\u043e\u043b\u0438 \u043d\u043e\u0432\u0456 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0438 \u043e\u0442\u0440\u0438\u043c\u0443\u0432\u0430\u0442\u0438\u043c\u0443\u0442\u044c\u0441\u044f \u0443 \u0440\u043e\u0437\u0441\u0438\u043b\u0446\u0456 RSS. Wizard.Subscription.subscribe.library=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0432 \u0412\u0430\u0448\u0456\u0439 \u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u0446\u0456 Wizard.Subscription.subscribe.subscriptions=\u041f\u043e\u0432'\u044f\u0437\u0430\u043d\u0456 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438 Wizard.Subscription.subscribe.library.empty=\u041d\u0435\u043c\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u043f\u0456\u0434\u043f\u0438\u0441\u043e\u043a?\n \n\u041f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u043d\u0430 \u044f\u0441\u043a\u0440\u0430\u0432\u0443 \u043f\u043e\u043c\u0430\u0440\u0430\u043d\u0447\u0435\u0432\u0443 \u043a\u043e\u043d\u043f\u043a\u0443 \u043c\u0435\u0440\u0435\u0436\u0456 Vuze HD Network.\n \nRead more message.confirm.delete.title=\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f message.confirm.delete.text=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 '%1'? Subscription.menu.properties=\u0412\u043b\u0430\u0441\u0442\u0438\u0432\u043e\u0441\u0442\u0456 props.window.title=\u0412\u043b\u0430\u0441\u0442\u0438\u0432\u043e\u0441\u0442\u0456 \u0434\u043b\u044f '%1' subs.prop.is_auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043d\u043e\u0432\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0456\u0432 subs.prop.last_scan=\u041e\u0441\u0442\u0430\u043d\u043d\u0454 \u0443\u0441\u043f\u0456\u0448\u043d\u0435 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f subs.prop.last_result=\u041e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u043d\u043e\u0432\u0438\u0439 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 subs.prop.last_error=\u041e\u0441\u0442\u0430\u043d\u043d\u044f \u043f\u043e\u043c\u0438\u043b\u043a\u0430 subs.prop.num_read=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0456\u0432 subs.prop.num_unread=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0456\u0432 subs.prop.template=\u0428\u0430\u0431\u043b\u043e\u043d subs.prop.auth=\u041d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0430 \u0456\u0434\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u044f externalLogin.auth_method_proxy=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 \u0437\u0430\u0445\u043e\u043f\u043b\u0435\u043d\u043d\u044f cookie. \u042f\u043a\u0449\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043d\u0435 \u043f\u0440\u0430\u0446\u044e\u0454, \u0432\u0438\u043c\u043a\u043d\u0456\u0442\u044c \u0439\u043e\u0433\u043e \u0456 \u0443\u0432\u0456\u043c\u043a\u043d\u0456\u0442\u044c \u0437\u043d\u043e\u0432\u0443 externalLogin.wait=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u0437\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430... TableColumn.menu.date_added.time=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0447\u0438 \u043f\u0440\u0438\u0445\u043e\u0432\u0430\u0442\u0438 \u0447\u0430\u0441 sidebar.VuzeHDNetwork=\u041c\u0435\u0440\u0435\u0436\u0430 Vuze HD Network subs.prop.next_scan=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0435 \u0441\u043a\u0430\u043d\u0443\u0432\u0430\u043d\u043d\u044f subs.prop.assoc=\u0410\u0441\u043e\u0446\u0456\u0430\u0446\u0456\u0457 subs.prop.version=\u0412\u0435\u0440\u0441\u0456\u044f subscriptions.column.new.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0454 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0433\u043e \u0430\u0431\u043e \u0431\u0456\u043b\u044c\u0448\u043e\u0457 \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u043d\u043e\u0432\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0456\u0432 subscriptions.column.name=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430 subscriptions.column.nb-results=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0456 subscriptions.column.nb-new-results=\u041d\u043e\u0432\u0456 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0438 subscriptions.column.last-checked=\u041e\u0441\u0442\u0430\u043d\u043d\u0456 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0435\u043d\u0456 subscriptions.view.title=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438 subs.prop.is_public=\u0421\u0443\u0441\u043f\u0456\u043b\u044c\u043d\u0438\u0439 subs.prop.high_version=\u0414\u043e\u0434\u0430\u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043d\u044f \u0432\u0435\u0440\u0441\u0456\u044f Subscription.menu.upgrade=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e \u043d\u043e\u0432\u0456\u0448\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 metasearch.template.version.bad=\u041f\u043e\u0448\u0443\u043a\u043e\u0432\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d '%1' \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439, \u043f\u043e\u043a\u0438 \u0432\u0438 \u043d\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0435 Vuze metasearch.addtemplate.failed.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0456 metasearch.addtemplate.failed.desc=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0456 \u043f\u043e\u0448\u0443\u043a\u043e\u0432\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0443: %1 subscription.version.bad=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430 '%1' \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430, \u043f\u043e\u043a\u0438 \u0432\u0438 \u043d\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0435 Vuze statusbar.feedback=\u041d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 \u0437\u0432\u043e\u0440\u043e\u0442\u043d\u0454 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f statusbar.feedback.tooltip=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u0442\u0443\u0442, \u0449\u043e\u0431 \u043f\u043e\u0441\u043b\u0430\u0442\u0438 \u0437\u0432\u043e\u0440\u043e\u0442\u043d\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f sidebar.Activity=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f v3.activity.button.watchall=\u041f\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438\u043c\u0438 subscriptions.view.help.1=\u0414\u043e\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438 subscriptions.view.help.2=\u041e\u0442\u0440\u0438\u043c\u0443\u0439\u0442\u0435 \u0431\u0435\u0437\u043a\u043e\u0448\u0442\u043e\u0432\u043d\u0456 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432\u0456\u0434\u0440\u0430\u0437\u0443, \u043a\u043e\u043b\u0438 \u043d\u043e\u0432\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. \u0427\u0438\u0442\u0430\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435. sidebar.sash.tooltip=F7 \u043f\u043e\u043a\u0430\u0437\u0443\u0454 \u0456 \u0441\u043f\u0440\u0438\u0445\u043e\u0432\u0443\u0454 \u0431\u043e\u043a\u043e\u0432\u0443 \u043f\u0430\u043d\u0435\u043b\u044c sidebar.expand.tooltip=\u0420\u043e\u0437\u0448\u0438\u0440\u0438\u0442\u0438 \u0431\u043e\u043a\u043e\u0432\u0443 \u043f\u0430\u043d\u0435\u043b\u044c sidebar.dropdown.tooltip=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0431\u043e\u043a\u043e\u0432\u0443 \u043f\u0430\u043d\u0435\u043b\u044c \u044f\u043a \u043c\u0435\u043d\u044e subscript.all.subscribed=\u0412\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u043b\u0438 \u0446\u044e \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e subscript.some.subscribed=\u0412\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u043d\u0456 \u043d\u0430 \u0434\u0435\u044f\u043a\u0456 \u0437 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442 \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0432\u043c\u0456\u0441\u0442\u0443.\n\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0431\u0430\u0447\u0438\u0442\u0438 \u043d\u0448\u0456 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438 subscript.none.subscribed=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0431\u0430\u0447\u0438\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438 \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0432\u043c\u0456\u0441\u0442\u0443 v3.iconBar.up.tooltip=\u0414\u043e\u0433\u043e\u0440\u0438\n\u0417\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u043c\u0438\u0448\u0456 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043c\u0456\u0449\u0435\u043d\u043d\u044f \u0434\u043e\u0433\u043e\u0440\u0438 v3.iconBar.down.tooltip=\u0414\u043e\u043d\u0438\u0437\u0443\n\u0417\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u043c\u0438\u0448\u0456 \u0434\u043b\u044f \u0440\u0443\u0445\u0443 \u0434\u043e\u043d\u0438\u0437\u0443 TableColumn.header.azsubs.ui.column.subs_link=\u0410\u0441\u043e\u0446\u0456\u0430\u0446\u0456\u044f TableColumn.header.azsubs.ui.column.subs_link.info=\u0410\u0441\u043e\u0446\u0456\u044e\u0432\u0430\u0442\u0438 \u0437 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430\u043c\u0438 Button.deleteContent.fromLibrary=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0437 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 Button.deleteContent.fromComputer=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0437 \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440\u0430 v3.deleteContent.message=\n\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 '%1' \u0437 \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440\u0430, \u0447\u0438 \u043b\u0438\u0448\u0435 \u0437 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 Vuze? v3.MainWindow.menu.view.toolbartext=\u041f\u0456\u0434\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0438 v3.MainWindow.menu.view.asSimpleList=\u041f\u0440\u043e\u0441\u0442\u0438\u0439 \u043f\u0435\u0440\u0435\u043b\u0456\u043a v3.MainWindow.menu.view.asAdvancedList=\u0420\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u043f\u0435\u0440\u0435\u043b\u0456\u043a v3.MainWindow.menu.view.statusbar=\u0420\u044f\u0434\u043e\u043a \u0441\u0442\u0430\u043d\u0443 Subscription.menu.dirtyall=\u041f\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0438 \u044f\u043a \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0456 configureWizard.file.message3=Vuze \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438\u043c\u0435 \u0444\u0430\u0439\u043b\u0438 \u0432 \u043f\u0435\u0432\u043d\u0443 \u0442\u0435\u043a\u0443, \u044f\u043a\u0443 \u043c\u043e\u0436\u043d\u0430 \u0432\u0438\u0431\u0440\u0430\u0442\u0438 \u0442\u0443\u0442: v3.deleteContent.applyToAll=\u0417\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438 \u0434\u0456\u044e \u0434\u043e \u0443\u0441\u0456\u0445 %1 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0445 \u0437\u0430\u043f\u0438\u0441\u0456\u0432 ConfigView.label.seeding.firstPriority.ignoreIdleHours=\u0422\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0456 \u043d\u0435 \u0440\u043e\u0437\u0434\u0430\u044e\u0442\u044c\u0441\u044f v3.MainWindow.menu.contentnetworks=&\u041c\u0435\u0440\u0435\u0436\u0456 HD Networks v3.MainWindow.menu.contentnetworks.about=\u041f\u0440\u043e \u043c\u0435\u0440\u0435\u0436\u0456 HD Networks Peers.column.as=A\u0421/A\u0421\u041d Peers.column.as.info=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 A\u0421 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 (\u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438) ConfigTransferAutoSpeed.auto.speed.neural=\u041d\u0435\u0440\u0432\u043e\u0432\u0430 (\u0410\u043b\u044c\u0444\u0430\u0433\u0443\u0434\u0456) ConfigView.label.autoopen.downloadbars=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u043a\u043e\u043b\u0438 ConfigView.label.autoopen=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0442\u044f ConfigView.label.autoopen.detailstab=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u041f\u0430\u043d\u0435\u043b\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c, \u043a\u043e\u043b\u0438 ConfigView.label.systray=\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u0438\u0439 \u0442\u0440\u0435\u0439 ConfigView.label.systray._mac=\u041f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0430 \u0440\u044f\u0434\u043a\u0430 \u0441\u0442\u0430\u043d\u0443 ConfigView.section.interface.legacy=\u0421\u043f\u0430\u0434\u043e\u043a v3.MainWindow.menu.contentnetworks.manage=&\u041a\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u043c\u0435\u0440\u0435\u0436\u0430\u043c\u0438 HD Networks azbuddy.ui.table.loc_cat=\u041a\u0430\u0442. \u0432\u0456\u0434\u043a. azbuddy.ui.table.rem_cat=\u041a\u0430\u0442. \u043f\u0440. azbuddy.ui.menu.cat=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457 azbuddy.ui.menu.cat.share=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u0442\u0438 \u0437 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0435\u043c azbuddy.ui.menu.cat.set=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457 azbuddy.ui.menu.cat.set_msg=\u0421\u043f\u0438\u0441\u043e\u043a \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0439 \u0440\u043e\u0437\u0434\u0456\u043b\u044f\u0454\u0442\u044c\u0441\u044f \u043a\u043e\u043c\u0430\u043c\u0438 azbuddy.ui.menu.cat_subs=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430 subs.prop.update_period=\u041f\u0435\u0440\u0456\u043e\u0434 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f azbuddy.enable_cat_pub=\u0421\u0443\u0441\u043f\u0456\u043b\u044c\u043d\u0456 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457, \u043d\u0430 \u044f\u043a\u0456 \u0412\u0421\u0406 \u0432\u0430\u0448\u0456 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456 \u043c\u043e\u0436\u0443\u0442\u044c \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438\u0441\u044f (\u0440\u043e\u0437\u0434\u0456\u043b\u044f\u0442\u0438 ',') v3.dialog.cnclose.title=%1 \u0437\u0430\u043a\u0440\u0438\u0442\u0438\u0439 v3.dialog.cnclose.subtitle=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f v3.dialog.cnclose.info1=\u0412\u0438 \u0437\u0430\u043a\u0440\u0438\u043b\u0438 \u043c\u0435\u0440\u0435\u0436\u0443 HD Network v3.dialog.cnclose.info2=\u042f\u043a\u0449\u043e \u0412\u0438 \u0437\u0430\u0431\u0430\u0436\u0430\u0454\u0442\u0435 \u0437\u043d\u043e\u0432\u0443 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0446\u044e \u043c\u0435\u0440\u0435\u0436\u0443 HD Network, \u0441\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0439\u0442\u0435\u0441\u044f \u043c\u0435\u043d\u044e "\u041c\u0435\u0440\u0435\u0436\u0456 HD Networks" v3.dialog.cnclose.noshow=\u0411\u0456\u043b\u044c\u0448\u0435 \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 v3.dialog.cnmanage.title=\u041c\u0435\u043d\u044e \u043a\u0435\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u043c\u0435\u0440\u0435\u0436\u0430\u043c\u0438 HD Networks v3.dialog.cnmanage.intro=\u0423 \u0441\u043f\u0438\u0441\u043a\u0443, \u044f\u043a\u0438\u0439 \u0437\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043d\u0438\u0436\u0447\u0435, \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0438\u0431\u0440\u0430\u0442\u0438 \u043c\u0435\u0440\u0435\u0436\u0456, \u044f\u043a\u0456 \u0431\u0430\u0436\u0430\u0454\u0442\u0435 \u0431\u0430\u0447\u0438\u0442\u0438 \u0432 \u043c\u0435\u043d\u044e "\u041c\u0435\u0440\u0435\u0436\u0456 HD Networks" azbuddy.ui.table.read_cat=\u0427\u0438\u0442. \u043a\u0430\u0442. TableColumn.header.#.info=\u041f\u043e\u0437\u0438\u0446\u0456\u044f \u0430\u0431\u043e \u043d\u043e\u043c\u0435\u0440 \u0437\u0430\u043c\u043e\u0432\u043b\u0435\u043d\u043d\u044f TableColumn.header.category.info=\u041d\u0430\u0437\u0432\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457, \u0434\u043e \u044f\u043a\u043e\u0457 \u043d\u0430\u043b\u0435\u0436\u0438\u0442\u044c \u0442\u043e\u0440\u0435\u043d\u0442 TableColumn.header.DateCompleted.info=\u0414\u0430\u0442\u0430 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 TableColumn.header.AzProduct.info=\u0422\u043e\u0440\u0435\u043d\u0442 \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043e \u0437 \u043c\u0435\u0440\u0435\u0436\u0456 TableColumn.header.health.info=\u041d\u0430\u0441\u043a\u0456\u043b\u044c\u043a\u0438 \u0436\u0438\u0442\u0442\u0454\u0437\u0434\u0430\u0442\u043d\u0435 \u0432\u0430\u0448\u0435 \u043f\u0456\u0434'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0434\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 TableColumn.header.maxuploads.info=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c # \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u043e\u0457 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 TableColumn.header.name.info=\u0406\u043c'\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0430 TableColumn.header.unopened.info=\u041f\u043e\u0437\u043d\u0430\u0447\u043a\u0430, \u044f\u043a\u0430 \u0432\u043a\u0430\u0437\u0443\u0454, \u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u044e\u0432\u0430\u0432\u0441\u044f (\u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0432\u0441\u044f) TableColumn.header.savepath.info=\u0422\u0435\u043a\u0430 \u0430\u0431\u043e \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 TableColumn.header.SeedingRank.info=\u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f, \u043d\u0430\u0441\u043a\u0456\u043b\u044c\u043a\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0456 \u0441\u0456\u0434\u0435\u0440\u0438. \u0427\u0438\u043c \u0432\u0438\u0449\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f, \u0442\u0438\u043c \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0456\u0448\u0435. TableColumn.header.shareRatio.info=\u0421\u043a\u0456\u043b\u044c\u043a\u0438 \u0432\u0438 \u0440\u043e\u0437\u0434\u0430\u043b\u0438 \u0432 \u043f\u043e\u0440\u0456\u0432\u043d\u044f\u043d\u043d\u0456 \u0437 \u0442\u0438\u043c, \u0441\u043a\u0456\u043b\u044c\u043a\u0438 \u0432\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u043b\u0438. TableColumn.header.size.info=\u0420\u043e\u0437\u043c\u0456\u0440 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u043d\u0430 \u0434\u0438\u0441\u043a\u0443 TableColumn.header.azsubs.ui.column.subs.info=\u041a\u043d\u043e\u043f\u043a\u0430, \u044f\u043a\u0430 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u0442\u0438 \u0440\u043e\u0437\u0441\u0438\u043b\u043a\u0438, \u044f\u043a\u0456 \u043c\u0456\u0441\u0442\u044f\u0442\u044c \u043f\u043e\u0432'\u044f\u0437\u0430\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.upspeed.info=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 TableColumn.header.downspeed.info=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f TableColumn.header.up.info=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u0430\u043d\u0438\u0445, \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0445 \u0456\u043d\u0448\u0438\u043c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c TableColumn.header.down.info=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u0430\u043d\u0438\u0445, \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 \u0432\u0456\u0434 \u0456\u043d\u0448\u0438\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 TableColumn.header.ProgressETA.info=\u041f\u043e\u0454\u0434\u043d\u0443\u0454 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u0441\u0442\u0430\u043d, \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f, \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u043d\u0438\u0439 \u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0438\u0439 \u0447\u0430\u0441 \u0456 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432 \u043e\u0434\u043d\u043e\u043c\u0443 \u0431\u0430\u0433\u0430\u0442\u043e\u0440\u044f\u0434\u043a\u043e\u0432\u043e\u043c\u0443 \u0441\u0442\u043e\u0432\u043f\u0446\u0456. TableColumn.header.eta.info=\u041f\u0440\u0438\u0431\u043b\u0438\u0437\u043d\u0438\u0439 \u0447\u0430\u0441 \u0434\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f Pieces.column.#.info=\u041d\u043e\u043c\u0435\u0440 \u0447\u0430\u0441\u0442\u0438\u043d\u0438 Peers.column.%.info=\u0412\u0456\u0434\u0441\u043e\u0442\u043e\u043a \u0442\u043e\u0440\u0435\u043d\u0442\u0443, \u044f\u043a\u0438\u0439 \u043f\u043e\u043a\u0438 \u0449\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0432 \u0443\u0447\u0430\u0441\u043d\u0438\u043a TableColumn.header.download.info=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u0430\u043d\u0438\u0445, \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 \u0432\u0456\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 TableColumn.header.upload.info=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u0430\u043d\u0438\u0445, \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0443 TableColumn.header.downloadspeed.info=\u0427\u0430\u0441\u0442\u043e\u0442\u0430, \u0437 \u044f\u043a\u043e\u044e \u043c\u0438 \u043e\u0442\u0440\u0438\u043c\u0443\u0454\u043c\u043e \u0434\u0430\u043d\u0456 \u0432\u0456\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 TableColumn.header.uploadspeed.info=\u0427\u0430\u0441\u0442\u043e\u0442\u0430, \u0437 \u044f\u043a\u043e\u044e \u0432\u0456\u0434\u043f\u0440\u0430\u043b\u044f\u044e\u0442\u044c\u0441\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0443 \u0434\u0430\u043d\u0456 TableColumn.header.lan.info=\u041f\u043e\u0437\u043d\u0430\u0447\u043a\u0430, \u044f\u043a\u0430 \u0432\u043a\u0430\u0437\u0443\u0454, \u0449\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a \u0437\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0412\u0430\u0448\u0456\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456 TableColumn.header.downloadspeedoverall.info=\u0421\u0435\u0440\u0435\u0434\u043d\u044f \u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0456\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 Peers.column.pieces.info=\u0413\u0440\u0430\u0444\u0456\u0447\u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u044c, \u044f\u043a\u0430 \u043f\u043e\u043a\u0430\u0437\u0443\u0454, \u044f\u043a\u0456 \u0447\u0430\u0441\u0442\u0438\u043d\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 TableColumn.header.TableColumnNameInfo=\u0406\u043c'\u044f \u0441\u0442\u043e\u0432\u043f\u0446\u044f \u0456 \u043e\u043f\u0438\u0441 TableColumn.header.TableColumnSample=\u0417\u0440\u0430\u0437\u043e\u043a TableColumn.header.TableColumnInfo=\u041e\u043f\u0438\u0441 \u0441\u0442\u043e\u0432\u043f\u0446\u044f TableColumn.header.TableColumnChosenColumn=\u0412\u0438\u0431\u0440\u0430\u043d\u0438\u0439 \u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c subs.prop.is_auto_ok=\u0414\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f label.learnmore=\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435 ColumnSetup.title=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0441\u0442\u043e\u0432\u043f\u0446\u0456\u0432 \u0434\u043b\u044f '%1' ColumnSetup.explain=\u041f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u043b\u0456\u0432\u043e\u0440\u0443\u0447 \u0456 \u0434\u043e\u0434\u0430\u0439\u0442\u0435 \u0457\u0445 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0438\u0434\u0438\u043c\u0438\u0445 \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u043f\u0440\u0430\u0432\u043e\u0440\u0443\u0447. \u0420\u043e\u0437\u0448\u0438\u0440\u0442\u0435 \u0430\u0431\u043e \u0437\u043c\u0435\u043d\u0448\u0456\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u0444\u0456\u043b\u044c\u0442\u0440\u0443 \u0432 \u043b\u0456\u0432\u043e\u043c\u0443 \u043d\u0438\u0436\u043d\u044c\u043e\u043c\u0443 \u043a\u0443\u0442\u043a\u0443. \u0422\u0430\u043a\u043e\u0436 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u044e\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u0443\u0432\u0430\u043d\u043d\u044f \u0456 \u043a\u043e\u043c\u0431\u0456\u043d\u0430\u0446\u0456\u0457 \u043a\u043b\u0430\u0432\u0456\u0448. ColumnSetup.chosencolumns=\u0412\u0438\u0431\u0440\u0430\u043d\u0456 \u0441\u0442\u043e\u0432\u043f\u0446\u0456 ColumnSetup.proficiency=\u041c\u0430\u0439\u0441\u0442\u0435\u0440\u043d\u0456\u0441\u0442\u044c: ColumnSetup.categories=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457: ColumnSetup.filters=\u0424\u0456\u043b\u044c\u0442\u0440\u0438 ColumnSetup.availcolumns=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456 %1 \u0441\u0442\u043e\u0432\u043f\u0446\u0456 ColumnSetup.availcolumns.filteredby=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456 %1 \u0441\u0442\u043e\u0432\u043f\u0446\u0456, \u044f\u043a\u0456 \u0444\u0456\u043b\u044c\u0442\u0440\u0443\u044e\u0442\u044c\u0441\u044f \u0437\u0430 %2 devices.view.title=\u041d\u043e\u0441\u0456\u0457 device.renderer.view.title=\u041e\u0431\u0440\u043e\u0431\u043a\u0430 device.mediaserver.view.title=\u041c\u0435\u0434\u0456\u0430-\u0441\u0435\u0440\u0432\u0435\u0440\u0438 device.router.view.title=\u041c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0438 device.model.desc=\u041e\u043f\u0438\u0441 \u043c\u043e\u0434\u0435\u043b\u0456 device.model.name=\u041d\u0430\u0437\u0432\u0430 \u043c\u043e\u0434\u0435\u043b\u0456 device.model.num=\u041d\u043e\u043c\u0435\u0440 \u043c\u043e\u0434\u0435\u043b\u0456 device.manu.desc=\u0412\u0438\u0440\u043e\u0431\u043d\u0438\u043a device.router.is_mapping=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0456\u044f device.router.req_map=\u041f\u043e\u0442\u0440\u0456\u0431\u043d\u0430 \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0456\u044f device.router.configure=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f Upnp device.mediaserver.configure=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u0442\u0438 \u043c\u0456\u0439 \u043c\u0435\u0434\u0456\u0430-\u0441\u0435\u0440\u0432\u0435\u0440 device.hide=C\u0445\u043e\u0432\u0430\u0442\u0438 \u043d\u043e\u0441\u0456\u0439 device.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043f\u0440\u0438\u0445\u043e\u0432\u0430\u043d\u0456 \u043d\u043e\u0441\u0456\u0457 device.search=\u041f\u043e\u0448\u0443\u043a \u043d\u043e\u0441\u0456\u0457\u0432 device.router.con_type=\u0417\u0432'\u044f\u0437\u043e\u043a: %1 device.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 device.upnp.desc_url=\u041e\u043f\u0438\u0441 \u043d\u043e\u0441\u0456\u044f device.upnp.present_url=\u0410\u0434\u043c\u0456\u043d\u0456\u0441\u0442\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u043e\u0441\u0456\u044f ConfigView.label.maxStalledSeeding=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c '\u0437\u0430\u0441\u0442\u0440\u044f\u0433\u043b\u0438\u0445' [0:\u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439] device.search.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438\u0439 \u043f\u043e\u0448\u0443\u043a \u043d\u043e\u0441\u0456\u0457\u0432 devices.sidebar.simple=\u041f\u0440\u043e\u0441\u0442\u0438\u0439 \u0432\u0438\u0433\u043b\u044f\u0434 devices.xcode.working_dir=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u0434\u0456\u043b\u044f\u043d\u043a\u0443 devices.xcode.prof_def=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 \u043f\u0440\u043e\u0444\u0456\u043b\u044c \u0437\u043c\u0456\u043d\u0438 devices.xcode.profs=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0440\u043e\u0444\u0456\u043b\u0456 \u0437\u043c\u0456\u043d\u0438 device.lastseen=\u041e\u0441\u0442\u0430\u043d\u043d\u0456 \u0432\u0456\u0434\u0432\u0456\u0434\u0438\u043d\u0438 devices.contextmenu.xcode=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u0434\u043b\u044f \u043d\u043e\u0441\u0456\u044f devices.device=\u041d\u043e\u0441\u0456\u0439 devices.profile=\u041f\u0440\u043e\u0444\u0456\u043b\u044c General.percent=\u0412\u0456\u0434\u0441\u043e\u0442\u043a\u0456\u0432 devices.installed=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 devices.comp.missing=\u041d\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u044e\u0432\u0430\u043d\u0430 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0430 Vuze devices.state=\u0421\u0442\u0430\u043d MainWindow.menu.help.donate=&\u0417\u0440\u043e\u0431\u0438\u0442\u0438 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u0443 DonationWindow.noload.title=\u041f\u043e\u0436\u0435\u0440\u0442\u0432\u0430 DonationWindow.noload.text=\u041d\u0435 \u0432\u0434\u0430\u0454\u0442\u044c\u0441\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0432\u0456\u043a\u043d\u043e \u043f\u043e\u0436\u0435\u0440\u0442\u0432. \u0421\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u043d\u043e\u0432\u0443 \u043f\u0456\u0437\u043d\u0456\u0448\u0435. devices.xcode.only.show=\u041b\u0438\u0448\u0435 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0437\u043c\u0456\u043d\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 \u043d\u0430 \u043d\u043e\u0441\u0456\u044e device.quit.transcoding.title=\u0417\u043c\u0456\u043d\u0430 \u0442\u0440\u0438\u0432\u0430\u0454 device.quit.transcoding.text=\u0412 \u0446\u0435\u0439 \u0447\u0430\u0441 '%1' \u0437\u043c\u0456\u043d\u044e\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f '%2', \u0437\u043c\u0456\u043d\u0435\u043d\u043e %3%.\n\u042f\u043a\u0449\u043e \u0412\u0438 \u0432\u0438\u0439\u0434\u0435\u0442\u0435 \u0437\u0430\u0440\u0430\u0437, \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0432\u0441\u044e \u0434\u0456\u044e \u0434\u043e\u0432\u0435\u0434\u0435\u0442\u044c\u0441\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438 \u0441\u043f\u043e\u0447\u0430\u0442\u043a\u0443. download.removerules.unauthorised.data=\t\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0434\u0430\u043d\u0456 device.config.xcode.maxbps=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u0437\u043c\u0456\u043d\u0438, \u041a\u0431/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430] device.xcode=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 device.xcode.always=\u0417\u0430\u0432\u0436\u0434\u0438 device.xcode.whenreq=\u041a\u043e\u043b\u0438 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e device.xcode.never=\u041d\u0456\u043a\u043e\u043b\u0438 devices.copy.pending=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 devices.sidebar.hide.rend.generic=\u041f\u0440\u0438\u0445\u043e\u0432\u0430\u0442\u0438 \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0456 \u043d\u043e\u0441\u0456\u0457 v3.devicesview.infobar.text2=\u0414\u043b\u044f \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u043d\u0456\u0442\u044c \u0432\u043c\u0456\u0441\u0442 \u0412\u0430\u0448\u043e\u0457 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 \u0434\u043e \u043d\u043e\u0441\u0456\u0457\u0432 \u043d\u0430 \u0411\u043e\u043a\u043e\u0432\u0456\u0439 \u043f\u0430\u043d\u0435\u043b\u0456. \u0429\u043e\u0431 \u043f\u043e\u0431\u0430\u0447\u0438\u0442\u0438, \u0447\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u043e\u0432\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u043e\u0441\u044f, \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u043e\u0441\u0456\u0439 \u0441\u043f\u0440\u0430\u0432\u0430. iconBar.transcode=\u041d\u043e\u0441\u0456\u0439 iconBar.transcode.tooltip=\u0417\u0440\u043e\u0431\u0438\u0442\u0438 \u0434\u0430\u043d\u0456 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u043c\u0438 \u0434\u043b\u044f \u043d\u043e\u0441\u0456\u044f device.retry.copy=\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438 \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f devices.copy.fail=\u041d\u0435\u0432\u0434\u0430\u043b\u0435 \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u043d\u0430 \u043d\u043e\u0441\u0456\u0439 devices.on.demand=\u0417\u0430 \u0437\u0430\u043f\u0438\u0442\u043e\u043c devices.ready=\u0413\u043e\u0442\u043e\u0432\u0438\u0439 TableColumn.header.trancode_qpos.info=\u041f\u043e\u0437\u0438\u0446\u0456\u044f \u0432 \u0447\u0435\u0440\u0437\u0456 \u0437\u043c\u0456\u043d\u0438 TableColumn.header.profile=\u041d\u043e\u0441\u0456\u0439 TableColumn.header.profile.info=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0444\u0456\u043b\u044c \u0437\u043c\u0456\u043d\u0438 TableColumn.header.copied=\u041a\u043e\u043f\u0456\u044e\u0454\u0442\u044c\u0441\u044f TableColumn.header.device=\u041d\u043e\u0441\u0456\u0439 TableColumn.header.device.info=\u0426\u0456\u043b\u044c\u043e\u0432\u0438\u0439 \u043d\u043e\u0441\u0456\u0439 TableColumn.header.trancode_completion=\u0412\u0456\u0434\u0441\u043e\u0442\u043e\u043a \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f # This is the beginning of the word "View". It's right aligned under the icon bar item v3.iconBar.view.big=\u0412\u0438\u0433 v3.iconBar.view.big.tooltip=\u041f\u0440\u043e\u0441\u0442\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a # This is the end of the word "View". It's left aligned under the icon bar item v3.iconBar.view.small=\u043b\u044f\u0434 v3.iconBar.view.small.tooltip=\u0420\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043d\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a general.dont.ask.again=\u0411\u0456\u043b\u044c\u0448\u0435 \u043d\u0435 \u0437\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 v3.menu.device.exploreTranscodes=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 v3.menu.device.exploreTranscodes._windows=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0432 \u041f\u0440\u043e\u0432\u0456\u0434\u043d\u0438\u043a\u0443 v3.menu.device.exploreTranscodes._mac=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0432 \u043f\u043e\u043b\u0456 \u041f\u043e\u0448\u0443\u043a\u0443 v3.menu.device.defaultprofile=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 \u043f\u0440\u043e\u0444\u0456\u043b\u044c devices.button.installitunes=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043e\u0431'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 iTunes device.itunes.install=\u0412\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 iTunes device.itunes.start=\u0412\u0430\u043c \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 iTunes \u0430\u0431\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a device.itunes.install_problem=\u0404 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 \u0437 \u043e\u0431'\u0454\u0434\u043d\u0430\u043d\u043d\u044f\u043c \u0437 iTunes devices.downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f TableColumn.header.duration=\u0422\u0440\u0438\u0432\u0430\u043b\u0456\u0441\u0442\u044c TableColumn.header.resolution=\u0420\u043e\u0437\u0434\u0456\u043b\u044c\u043d\u0430 \u0437\u0434\u0430\u0442\u043d\u0456\u0441\u0442\u044c devices.xcode.autoStart=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u043f\u0440 \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e\u0441\u0442\u0456 option.askeverytime=\u0417\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 \u0449\u043e\u0440\u0430\u0437\u0443 option.rememberthis=\u0417\u0430\u043f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f devices.associate=\u0417\u0432'\u044f\u0437\u0430\u0442\u0438 \u0437 devices.associate.already=\u0412\u0436\u0435 \u0437\u0432'\u044f\u0437\u0430\u043d\u043e devices.always.cache=\u0417\u0430\u043f\u0430\u043c'\u044f\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043d\u0435\u0437\u043c\u0456\u043d\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 devices.turnon.prepageload=\u0429\u043e\u0431 \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0446\u044e \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c, \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0456\u0432. devices.turnon.itunes=\u0412\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0443 iTunes (\u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0430 \u0434\u043b\u044f \u043d\u043e\u0441\u0456\u0457\u0432 Apple) devices.turnon.qos=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 Vuze devices.turnon.title=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0443 \u043d\u043e\u0441\u0456\u0457\u0432 devices.choose.device.title=\u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043f\u0440\u0438\u0441\u0442\u0440\u0456\u0439, \u043d\u0430 \u044f\u043a\u043e\u043c\u0443 \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u044e\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f \u0446\u0435 \u0432\u0456\u0434\u0435\u043e: devices.choose.profile.info.text=\u041f\u0456\u0441\u043b\u044f \u0432\u0430\u0448\u043e\u0433\u043e \u0432\u0438\u0431\u043e\u0440\u0443, Vuze \u0432\u0438\u044f\u0432\u0438\u0442\u044c, \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454\u0442\u044c\u0441\u044f \u0447\u0438 \u043d\u0456 \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0433\u043e \u0432\u0456\u0434\u0435\u043e\u0444\u043e\u0440\u043c\u0430\u0442\u0443 \u043d\u0430 \u0432\u0430\u0448\u043e\u043c\u0443 \u043d\u043e\u0441\u0456\u044e, \u0456 \u0441\u0442\u0432\u043e\u0440\u0438\u0442\u044c \u0441\u0443\u043c\u0456\u0441\u043d\u0443 \u0434\u043b\u044f \u043d\u043e\u0441\u0456\u044f \u043a\u043e\u043f\u0456\u044e, \u044f\u043a\u0449\u043e \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e.\n\n\u041f\u0440\u043e\u0432\u0435\u0434\u0456\u0442\u044c \u043c\u0438\u0448\u0435\u044e \u043d\u0430\u0434 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u043c \u043d\u043e\u0441\u0456\u0454\u043c \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434\u0443 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c. devices.choose.profile.info.title.selected=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 %1: devices.view.heading=\u041f\u0435\u0440\u0435\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445 \u0434\u043b\u044f \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u043d\u0430 \u043d\u043e\u0441\u0456\u044e device.view.heading=\u0414\u0430\u043d\u0456 \u0434\u043b\u044f %1 devices.choose.device.info.title=\u041f\u0456\u0434\u043a\u0430\u0437\u043a\u0430 \u043d\u043e\u0441\u0456\u044f devices.choose.device.info.text=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0443, \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u043d\u0456\u0442\u044c \u0444\u0430\u0439\u043b\u0438 \u0434\u043e\u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e\u0433\u043e \u043d\u043e\u0441\u0456\u044f \u043d\u0430 \u0411\u043e\u043a\u043e\u0432\u0456\u0439 \u043f\u0430\u043d\u0435\u043b\u0456. label.clickone=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u0440\u0430\u0437 Button.turnon=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 ConfigView.label.dm.dblclick=\u0414\u0432\u0456\u0447\u0456 \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443: ConfigView.option.dm.dblclick.play=\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0432\u043c\u0456\u0441\u0442 ConfigView.option.dm.dblclick.details=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 ConfigView.option.dm.dblclick.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b ConfigView.option.dm.dblclick.show._mac=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b(\u0438) \u0432 \u0432\u0456\u043a\u043d\u0456 \u041f\u043e\u0448\u0443\u043a\u0443 ConfigView.option.dm.dblclick.show._windows=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b(\u0438) \u0432 \u041f\u0440\u043e\u0432\u0456\u0434\u043d\u0438\u043a\u0443 subscriptions.column.auto-download=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f xcode.deletedata.title=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0437\u043c\u0456\u043d\u0435\u043d\u0438\u0439 \u0432\u043c\u0456\u0441\u0442 xcode.deletedata.message=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u043d\u0435\u0433\u0430\u0439\u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043a\u043e\u043f\u0456\u044e '%1', \u0437\u043c\u0456\u043d\u0435\u043d\u0443 \u0434\u043b\u044f '%2'%3? xcode.deletedata.message.2=\n(\u043a\u043e\u043f\u0456\u044f \u043c\u043e\u0436\u0435 \u0434\u043e\u0441\u0456 \u0456\u0441\u043d\u0443\u0432\u0430\u0442\u0438 \u0432 '%1') v3.deviceview.infobar.line1=\u041f\u0435\u0440\u0435\u0442\u044f\u0433\u043d\u0456\u0442\u044c \u0432\u0456\u0434\u0435\u043e \u0437 \u0412\u0430\u0448\u043e\u0457 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u043a\u0438 \u0434\u043e \u0431\u0430\u0436\u0430\u043d\u043e\u0433\u043e \u043d\u043e\u0441\u0456\u044f. v3.deviceview.infobar.line2=\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u044e\u0439\u0442\u0435 \u0412\u0430\u0448\u0435 \u0432\u0456\u0434\u0435\u043e \u0431\u0443\u0434\u044c-\u0434\u0435 - \u043d\u0430 iPhone, iPod, TV v3.deviceview.infobar.line1.generic=\u041f\u0435\u0440\u0435\u0442\u044f\u0433\u043d\u0456\u0442\u044c \u0432\u0456\u0434\u0435\u043e \u0437 \u0412\u0430\u0448\u043e\u0457 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u043a\u0438 \u0434\u043e %1 \u043d\u0430 \u0412\u0430\u0448\u0456\u0439 \u0411\u043e\u043a\u043e\u0432\u0456\u0439 \u043f\u0430\u043d\u0435\u043b\u0456. v3.deviceview.infobar.line2.itunes=\u0412\u0456\u0434\u0435\u043e \u0437'\u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0442\u0435\u0446\u0456 iTunes Movies, \u043a\u043e\u043b\u0438 \u0431\u0443\u0434\u0443\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u0438\u043c\u0438 \u0434\u043e \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f. v3.deviceview.infobar.line2.xbox=\u041f\u043e\u0442\u043e\u043a\u043e\u0432\u0435 \u0432\u0456\u0434\u0435\u043e \u0434\u043b\u044f \u0412\u0430\u0448\u043e\u0433\u043e Xbox 360 \u0432\u0438\u0431\u0438\u0440\u0430\u0454\u0442\u044c\u0441\u044f: My XBox -> Video Library -> Vuze. v3.deviceview.infobar.line2.ps3=\u041f\u043e\u0442\u043e\u043a\u043e\u0432\u0435 \u0432\u0456\u0434\u0435\u043e \u0434\u043b\u044f \u0412\u0430\u0448\u043e\u0433\u043e PS3 \u0432\u0438\u0431\u0438\u0440\u0430\u0454\u0442\u044c\u0441\u044f: Videos -> Vuze. devices.copy_url=\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0443 \u0430\u0434\u0440\u0435\u0441\u0443 \u0434\u043e \u0411\u0443\u0444\u0435\u0440\u0443 \u043e\u0431\u043c\u0456\u043d\u0443 devices.converting=\u041f\u0435\u0440\u0435\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f Button.reload=\u041f\u0435\u0440\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 devices.auto.start=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a Subscription.menu.setcookies=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043a\u0443\u043a\u0456\u0441\u0438 general.enter.cookies=\u041a\u0443\u043a\u0456\u0441\u0438 \u0432\u0445\u043e\u0434\u0443 device.config.xcode.workdir=\u0422\u0435\u043a\u0430 \u0434\u043b\u044f \u0437\u043c\u0456\u043d\u0435\u043d\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 MyTorrentsView.menu.clear_alloc_data=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f DiskManager.error.nospace=\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043d\u044c\u043e \u0434\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0440\u0443 ConfigView.section.file.rename.incomplete=\u0414\u043e\u0434\u0430\u0432\u0430\u0442\u0438 \u0441\u0443\u0444\u0456\u043a\u0441 \u0434\u043e \u043d\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 subscriptions.config.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f subscriptions.config.autostartdls=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u0447\u0438\u043d\u0430\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u0438 \u0434\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u0456 subscriptions.config.autostart.min=\u041f\u043e\u0447\u0438\u043d\u0430\u0442\u0438, \u044f\u043a\u0449\u043e >= MB [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043e] subscriptions.config.autostart.max=\u041f\u043e\u0447\u0438\u043d\u0430\u0442\u0438, \u044f\u043a\u0449\u043e <= MB [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043e] dlg.corewait.title=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u044f\u0434\u0440\u0430 dlg.corewait.text=\u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430...\n\n\u0412\u0430\u0448 \u0437\u0430\u043f\u0438\u0442 \u0431\u0443\u0434\u0435 \u043e\u0431\u0440\u043e\u0431\u043b\u0435\u043d\u0438\u043c \u043f\u0456\u0441\u043b\u044f \u0442\u043e\u0433\u043e, \u044f\u043a Vuze \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0456\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044e library.core.wait=\u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430...\n\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u043a\u043b\u0456\u0454\u043d\u0442\u0430 Vuze ConfigView.label.StartUIBeforeCore=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0433\u0440\u0430\u0444\u0456\u043a\u0443 \u043f\u0435\u0440\u0435\u0434 \u0456\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u0454\u044e \u044f\u0434\u0440\u0430 general.add.friends=\u0414\u043e\u0434\u0430\u0439\u0442\u0435 \u0434\u0440\u0443\u0437\u0456\u0432! general.all.friends=\u0412\u0441\u0456 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456 friend.mod.subs=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043f\u0440\u0430\u0432\u043e\u044e \u043a\u043d\u043e\u043f\u043a\u043e\u044e \u0434\u043b\u044f \u0437\u043c\u0456\u043d\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043e\u043a TableColumn.header.class=\u041a\u043b\u0430\u0441 device.rss.group=\u041c\u0456\u0441\u0446\u0435\u0432\u0430 \u0441\u0442\u0440\u0456\u0447\u043a\u0430 RSS devices.xcode.rsspub=\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0440\u0456\u0447\u043a\u0443 RSS device.rss.enable=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u0442\u0440\u0456\u0447\u043a\u0443 RSS \u0437 \u0437\u043c\u0456\u043d\u0435\u043d\u043e\u0433\u043e \u0432\u043c\u0456\u0441\u0442\u0443 - \u0446\u0435 \u0437\u0440\u043e\u0431\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u043c \u0432\u043c\u0456\u0441\u0442 \u0434\u043b\u044f \u0447\u0438\u0442\u0430\u0447\u0456\u0432 \u0441\u0442\u0440\u0456\u0447\u043e\u043a RSS device.rss.port=\u041f\u043e\u0440\u0442 \u0441\u0442\u0440\u0456\u0447\u043a\u0438 RSS device.rss.view=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438 \u0441\u0442\u0440\u0456\u0447\u043a\u0443 RSS device.rss.localonly=\u041e\u0431\u043c\u0435\u0436\u0438\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u043b\u0438\u0448\u0435 \u0434\u043e \u0446\u044c\u043e\u0433\u043e \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440\u0430 rcm.rc_tracker.tt=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 rcm.rc_hash.tt=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0446\u0435\u0439 \u0432\u043c\u0456\u0441\u0442 rcm.rc_title.tt=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0437\u043d\u0430\u0439\u0442\u0438 \u0446\u0435\u0439 \u0432\u043c\u0456\u0441\u0442 devices.xcode.autoCopy=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0434\u043e \u0442\u0435\u043a\u0438 devices.xcode.setcopyto=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0434\u043e \u0442\u0435\u043a\u0438... devices.xcode.setcopyto.title=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043a\u0456\u043d\u0446\u0435\u0432\u0443 \u0442\u0435\u043a\u0443 devices.copy.folder.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0432 \u0442\u0435\u043a\u0443 devices.copy.folder.dest=\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0432 \u0442\u0435\u043a\u0443 TableColumn.menu.maxuploads=\u041a-\u0441\u0442\u044c \u043c\u0430\u043a\u0441. \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c devices.xcode.mancopy=\u0412\u0440\u0443\u0447\u043d\u0443 \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 devices.xcode.show.cat=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0438\u0442\u0438 \u043f\u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044f\u043c ConfigView.label.alwaysShowLibraryHeader=\u0417\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0432 \u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u0446\u0456 (\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438) devices.cat.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457 devices.tivo.machine=TiVo devices.info.copypending=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f %1 \u0444\u0430\u0439\u043b\u0430(\u0456\u0432) device.error.xcodefail=\u041d\u0435\u0432\u0434\u0430\u043b\u0430 \u0437\u043c\u0456\u043d\u0430 device.error.copyfail=\u041e\u0434\u0438\u043d \u0430\u0431\u043e \u043a\u0456\u043b\u044c\u043a\u0430 \u0444\u0430\u0439\u043b\u0456\u0432 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e \u0441\u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0434\u043e \u0442\u0435\u043a\u0438 device.error.copytonotset='\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0434\u043e \u0442\u0435\u043a\u0438' "%1", \u044f\u043a\u0430 \u043d\u0435 \u0432\u043a\u0430\u0430\u0437\u043d\u0430 device.error.copytomissing='\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0434\u043e \u0442\u0435\u043a\u0438' "%1", \u044f\u043a\u0443 \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e device.error.copytonowrite='\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0434\u043e \u0442\u0435\u043a\u0438' "%1", \u0432 \u044f\u043a\u0443 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u0438 device.error.copyfail2=\u041e\u0434\u0438\u043d \u0430\u0431\u043e \u043a\u0456\u043b\u044c\u043a\u0430 \u0444\u0430\u0439\u043b\u0456\u0432 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e \u0441\u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0434\u043e \u043d\u043e\u0441\u0456\u044f v3.deviceview.infobar.line2.tivo=\u041f\u043e\u0442\u043e\u043a\u043e\u0432\u0435 \u0432\u0456\u0434\u0435\u043e \u0434\u043b\u044f \u0412\u0430\u0448\u043e\u0433\u043e TiVo \u0432\u0438\u0431\u0438\u0440\u0430\u0454\u0442\u044c\u0441\u044f \u0432 Vuze \u0432 \u043f\u043e\u0442\u043e\u0447\u043d\u043e\u043c\u0443 \u0441\u043f\u0438\u0441\u043a\u0443 \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f. v3.deviceview.infobar.line2.psp=\u0412\u0456\u0434\u0435\u043e \u0441\u043a\u043e\u043f\u0456\u044e\u0454\u0442\u044c\u0441\u044f \u0434\u043e PSP, \u043a\u043e\u043b\u0438 \u043d\u043e\u0441\u0456\u0439 \u0431\u0443\u0434\u0435 \u043f\u0456\u0434'\u0454\u0434\u043d\u0430\u043d\u043e. devices.info.copypending2=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f %1 \u0444\u0430\u0439\u043b\u0430(\u0456\u0432), \u043f\u0456\u0434'\u0454\u0434\u043d\u0430\u0439\u0442\u0435 \u0412\u0430\u0448 \u043d\u043e\u0441\u0456\u0439 subscriptions.column.nb-subscribers=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0447\u0443\u044e\u0447\u0456 azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_el_GR.properties0000644000175000017500000052027711301156004026074 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=\u0391\u03c1\u03c7\u03b5\u03af\u03bf .torrent Main.parameter.usage=\u03a7\u03c1\u03ae\u03c3\u03b7 : java org.gudy.azureus2.cl.Main [\u03bf\u03c1\u03af\u03c3\u03bc\u03b1\u03c4\u03b1] "\u03b1\u03c1\u03c7\u03b5\u03af\u03bf.torrent" "\u03c6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2 \u03b1\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7\u03c2" Main.parameter.maxUploads=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc\u03c2 \u03c4\u03b1\u03c5\u03c4\u03cc\u03c7\u03c1\u03bf\u03bd\u03c9\u03bd \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ce\u03bd \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd Main.parameter.maxSpeed=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03b7 \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 \u03c3\u03b5 bytes/\u03b4\u03b5\u03c5\u03c4\u03b5\u03c1\u03cc\u03bb\u03b5\u03c0\u03c4\u03bf MainWindow.menu.file=&\u0391\u03c1\u03c7\u03b5\u03af\u03bf MainWindow.menu.file.open=\u0386\u03bd&\u03bf\u03b9\u03b3\u03bc\u03b1 MainWindow.menu.file.create=&\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 Torrent MainWindow.menu.file.create.fromfile=\u0391\u03c0\u03cc &\u0391\u03c1\u03c7\u03b5\u03af\u03bf MainWindow.menu.file.create.fromdir=\u0391\u03c0\u03cc &\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf MainWindow.menu.file.export=&\u0395\u03be\u03b1\u03b3\u03c9\u03b3\u03ae Torrent... MainWindow.menu.file.import=&\u0395\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae Torrent... MainWindow.menu.file.exit=\u0388&\u03be\u03bf\u03b4\u03bf\u03c2 MainWindow.dialog.choose.file=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf torrent MainWindow.menu.file.folder=&\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2 MainWindow.dialog.choose.folder=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03c0\u03bf\u03c5 \u03c0\u03b5\u03c1\u03b9\u03ad\u03c7\u03b5\u03b9 \u03c4\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03b1 torrent MainWindow.menu.view=\u03a0&\u03c1\u03bf\u03b2\u03bf\u03bb\u03ae MainWindow.menu.view.mytorrents=&\u03a4\u03b1 \u03a4orrent \u03bc\u03bf\u03c5 MainWindow.menu.view.configuration=&\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ad\u03c2 MainWindow.menu.view.console=\u039a&\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1 MainWindow.menu.closealldetails=&\u039a\u03bb\u03b5\u03af\u03c3\u03b9\u03bc\u03bf \u03cc\u03bb\u03c9\u03bd \u03c4\u03c9\u03bd \u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03b5\u03c1\u03b5\u03b9\u03ce\u03bd MainWindow.menu.closealldownloadbars=\u039a\u03bb\u03b5\u03af\u03c3\u03b9\u03bc\u03bf \u03cc\u03bb\u03c9\u03bd \u03c4\u03c9\u03bd &\u03a1\u03ac\u03b2\u03b4\u03c9\u03bd \u039b\u03ae\u03c8\u03b7\u03c2 MainWindow.menu.language=&\u0393\u03bb\u03ce\u03c3\u03c3\u03b1 ConfigView.section.language=\u0393\u03bb\u03ce\u03c3\u03c3\u03b1 MainWindow.menu.help=&\u0392\u03bf\u03ae\u03b8\u03b5\u03b9\u03b1 MainWindow.menu.help.about=&\u03a0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 \u03b3\u03b9\u03b1 \u03c4\u03bf Vuze MainWindow.about.title=\u03a0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 \u03b3\u03b9\u03b1 \u03c4\u03bf Vuze MainWindow.about.section.developers=\u03a0\u03c1\u03bf\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03b9\u03c3\u03c4\u03ad\u03c2 MainWindow.about.section.translators=\u039c\u03b5\u03c4\u03b1\u03c6\u03c1\u03b1\u03c3\u03c4\u03ad\u03c2 MainWindow.about.section.internet=\u0394\u03b9\u03b1\u03b4\u03af\u03ba\u03c4\u03c5\u03bf MainWindow.about.internet.homepage=\u0394\u03b9\u03ba\u03c4\u03c5\u03b1\u03ba\u03cc\u03c2 \u03c4\u03cc\u03c0\u03bf\u03c2 Vuze MainWindow.about.internet.sourceforge=\u03a3\u03b5\u03bb\u03af\u03b4\u03b1 \u03c4\u03bf\u03c5 \u03c0\u03c1\u03bf\u03b3\u03c1\u03ac\u03bc\u03bc\u03b1\u03c4\u03bf\u03c2 \u03c3\u03c4\u03bf Sourceforge MainWindow.about.internet.sourceforgedownloads=\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u03b3\u03b9\u03b1 \u03ba\u03b1\u03c4\u03ad\u03b2\u03b1\u03c3\u03bc\u03b1 \u03c3\u03c4\u03bf Sourceforge MainWindow.about.internet.bugreports=\u0391\u03bd\u03b1\u03c6\u03bf\u03c1\u03ad\u03c2 \u03a3\u03c6\u03b1\u03bb\u03bc\u03ac\u03c4\u03c9\u03bd MainWindow.about.internet.forumdiscussion=\u039f\u03bc\u03ac\u03b4\u03b1 \u03c3\u03c5\u03b6\u03b7\u03c4\u03ae\u03c3\u03b5\u03c9\u03bd \u03b3\u03b5\u03bd\u03b9\u03ba\u03bf\u03cd \u03b5\u03bd\u03b4\u03b9\u03b1\u03c6\u03ad\u03c1\u03bf\u03bd\u03c4\u03bf\u03c2 MainWindow.about.internet.wiki=\u03a3\u03c5\u03c7\u03bd\u03ad\u03c2 \u03b5\u03c1\u03c9\u03c4\u03ae\u03c3\u03b5\u03b9\u03c2 \u03b3\u03b9\u03b1 \u03c4\u03bf Vuze MainWindow.dialog.choose.savepath=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03b7 \u03b4\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae \u03b1\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7\u03c2 MainWindow.dialog.choose.savepath_forallfiles=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03b7 \u03b4\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae \u03b1\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7\u03c2 \u03b3\u03b9\u03b1 \u039f\u039b\u0391 \u03c4\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03b1 MainWindow.status.latestversion=\u03a4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03b1 \u03b5\u03ba\u03b4\u03bf\u03c3\u03b7 MainWindow.status.latestversion.clickupdate=\u039a\u03ac\u03bd\u03c4\u03b5 \u03ba\u03bb\u03b9\u03ba \u03b3\u03b9\u03b1 \u03b1\u03bd\u03b1\u03b2\u03ac\u03b8\u03bc\u03b9\u03c3\u03b7 MainWindow.status.unknown=\u03ac\u03b3\u03bd\u03c9\u03c3\u03c4\u03b7 MainWindow.status.checking=\u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03ad\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 MyTorrentsView.mytorrents=\u03a4\u03b1 torrent \u03bc\u03bf\u03c5 TableColumn.header.name=\u038c\u03bd\u03bf\u03bc\u03b1 TableColumn.header.size=\u039c\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 TableColumn.header.done=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 TableColumn.header.done.info=\u03a0\u03bf\u03c3\u03bf\u03c3\u03c4\u03bf \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03c9\u03c3\u03b7\u03c2 \u03c4\u03b7\u03c2 \u03b4\u03b9\u03b1\u03b4\u03b9\u03ba\u03b1\u03c3\u03b9\u03b1\u03c2 TableColumn.header.status=\u039a\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7 TableColumn.header.status.info=\u03a4\u03b9 \u03ba\u03b1\u03bd\u03b5\u03b9 \u03c4\u03bf torrent TableColumn.header.seeds=\u0393\u03bf\u03bd\u03bf\u03b9 TableColumn.header.seeds.info=# \u03a3\u03c5\u03bd\u03b4\u03b5\u03b4\u03b5\u03bc\u03b5\u03bd\u03bf\u03b9 \u03b3\u03bf\u03bd\u03bf\u03b9 (# \u03c3\u03c5\u03bd\u03bf\u03bb\u03bf \u03b3\u03bf\u03bd\u03c9\u03bdl) TableColumn.header.peers=\u03a3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03b9\u03c2 TableColumn.header.downspeed=\u03a4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u03bb\u03ae\u03c8\u03b7\u03c2 TableColumn.header.upspeed=\u03a4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 TableColumn.header.eta=\u03a7\u03c1\u03cc\u03bd\u03bf\u03c2 \u03c0\u03bf\u03c5 \u03b1\u03c0\u03b1\u03b9\u03c4\u03b5\u03af\u03c4\u03b1\u03b9 TableColumn.header.tracker=\u039a\u03b1\u03c4\u03b1\u03c3\u03c4\u03b1\u03c3\u03b7 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 TableColumn.header.tracker.info=\u039a\u03b1\u03c4\u03b1\u03c3\u03c4\u03b1\u03c3\u03b7 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 TableColumn.header.trackernextaccess=\u0395\u03c0\u03cc\u03bc\u03b5\u03bd\u03b7 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7 \u03c3\u03c4\u03bf\u03bd \u03b9\u03c7\u03bd\u03b7\u03bb\u03ac\u03c4\u03b7 TableColumn.header.trackernextaccess.info=\u03a0\u03bf\u03c4\u03b5 \u03b8\u03b1 \u03c3\u03c5\u03bc\u03b2\u03b5\u03b9 \u03b7 \u03b5\u03c0\u03cc\u03bc\u03b5\u03bd\u03b7 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7 \u03c3\u03c4\u03bf\u03bd \u03b9\u03c7\u03bd\u03b7\u03bb\u03ac\u03c4\u03b7 TableColumn.header.priority=\u03a0\u03c1\u03bf\u03c4\u03b5\u03c1\u03b1\u03b9\u03cc\u03c4\u03b7\u03c4\u03b1 MyTorrentsView.menu.showdetails=\u03a0\u03c1\u03bf\u03b2\u03bf\u03bb\u03ae &\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03b5\u03c1\u03b9\u03ce\u03bd MyTorrentsView.menu.showdownloadbar=\u03a0\u03c1\u03bf\u03b2\u03bf\u03bb\u03ae &\u03a1\u03ac\u03b2\u03b4\u03bf\u03c5 \u039b\u03ae\u03c8\u03b7\u03c2 MyTorrentsView.menu.open=\u0386\u03bd&\u03bf\u03b9\u03b3\u03bc\u03b1 MyTorrentsView.menu.setpriority=\u039f\u03c1\u03b9\u03c3\u03bc\u03cc\u03c2 &\u03a0\u03c1\u03bf\u03c4\u03b5\u03c1\u03b1\u03b9\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2 MyTorrentsView.menu.setpriority.high=&\u03a5\u03c8\u03b7\u03bb\u03ae MyTorrentsView.menu.setpriority.low=&\u03a7\u03b1\u03bc\u03b7\u03bb\u03ae MyTorrentsView.menu.start=&\u0395\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 MyTorrentsView.menu.stop=\u0394\u03b9\u03b1&\u03ba\u03bf\u03c0\u03ae MyTorrentsView.menu.remove=&\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae MyTorrentsView.menu.changeTracker=&\u0395\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae \u03b4\u03b9\u03b5\u03c5\u03b8\u03c5\u03bd\u03c3\u03b7\u03c2 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 TrayWindow.menu.exit=\u0388\u03be\u03bf\u03b4\u03bf\u03c2 TrayWindow.menu.show=\u0395\u03bc\u03c6\u03ac\u03bd\u03b9&\u03c3\u03b7 \u03c4\u03bf\u03c5 Vuze SystemTray.menu.exit=\u0388&\u03be\u03bf\u03b4\u03bf\u03c2 SystemTray.menu.closealldownloadbars=\u039a\u03bb\u03b5\u03af\u03c3\u03b9\u03bc\u03bf \u03cc\u03bb\u03c9\u03bd \u03c4\u03c9\u03bd \u03a1\u03ac&\u03b2\u03b4\u03c9\u03bd \u039b\u03ae\u03c8\u03b7\u03c2 SystemTray.menu.show=\u0395&\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 Vuze PeersView.ip=\u0394\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 IP PeersView.port=\u0398\u03cd\u03c1\u03b1 PeersView.I1=I (\u0395\u03bd\u03b4\u03b9\u03b1\u03c6\u03ad\u03c1\u03bf\u03bd \u03b3\u03b9\u03b1 \u03a3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03b9\u03c2) PeersView.C1=C (\u03a6\u03c1\u03b1\u03b3\u03bc\u03cc\u03c2 \u03b1\u03c0\u03cc \u03a3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03b9\u03c2) PeersView.pieces=\u039a\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9\u03b1 PeersView.%=% PeersView.downloadspeed=\u03a4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u039b\u03ae\u03c8\u03b7\u03c2 PeersView.download=\u039b\u03ae\u03c8\u03b7 PeersView.I2=I (\u0395\u03bd\u03b4\u03b9\u03b1\u03c6\u03ad\u03c1\u03bf\u03bd \u03b1\u03c0\u03cc \u03a3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03b9\u03c2) PeersView.C2=C (\u03a6\u03c1\u03b1\u03b3\u03bc\u03cc\u03c2 \u03a3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03c9\u03bd) PeersView.uploadspeed=\u03a4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 PeersView.upload=\u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae PeersView.statup=\u03a3\u03c4\u03b1\u03c4\u03b9\u03c3\u03c4\u03b9\u03ba\u03ac \u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 PeersView.S=S PeersView.downloadspeedoverall=\u0393\u03b5\u03bd\u03b9\u03ba\u03ae \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u039b\u03ae\u03c8\u03b7\u03c2 PeersView.optunchoke=\u0391\u03c0\u03bf\u03c6\u03c1\u03b1\u03b3\u03bc\u03cc\u03c2 PeersView.client=\u03a0\u03b5\u03bb\u03ac\u03c4\u03b7\u03c2 PeersView.menu.snubbed=&\u0391\u03c0\u03bf\u03bc\u03ac\u03ba\u03c1\u03c5\u03bd\u03c3\u03b7 PeersView.title.short=\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2 PeersView.title.full=\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2 ConfigView.section.files=\u0391\u03c1\u03c7\u03b5\u03af\u03b1 ConfigView.label.usefastresume=\u0393\u03c1\u03ae\u03b3\u03bf\u03c1\u03b7 \u0395\u03c0\u03b1\u03bd\u03b1\u03c6\u03bf\u03c1\u03ac ConfigView.label.incrementalfile=\u0391\u03c5\u03be\u03b1\u03bd\u03bf\u03bc\u03b5\u03bd\u03b7 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 ConfigView.label.defaultsavepath=\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c3\u03c4\u03bf\u03bd \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03b5\u03b3\u03bc\u03ad\u03bd\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd ConfigView.button.browse=\u0391\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7... ConfigView.dialog.choosedefaultsavepath=\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf\u03bd \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03b5\u03b3\u03bc\u03ad\u03bd\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03b1\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7\u03c2 ConfigView.section.server=\u0394\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae\u03c2 ConfigView.section.global=\u0393\u03b5\u03bd\u03b9\u03ba\u03ac ConfigView.label.disconnetseed=\u0391\u03c0\u03bf\u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7 \u03b3\u03bf\u03bd\u03c9\u03bd \u03ba\u03b1\u03c4\u03ac \u03c4\u03bf \u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf ConfigView.label.switchpriority=\u0391\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03bf\u03c2 \u03bf\u03c1\u03b9\u03c3\u03bc\u03cc\u03c2 \u03c0\u03c1\u03bf\u03c4\u03b5\u03c1\u03b1\u03b9\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2 \u03c3\u03b5 \u03c7\u03b1\u03bc\u03b7\u03bb\u03ae \u03cc\u03c4\u03b1\u03bd \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03b1\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7 ConfigView.label.maxdownloads=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc\u03c2 \u03c4\u03b1\u03c5\u03c4\u03cc\u03c7\u03c1\u03bf\u03bd\u03c9\u03bd \u03bb\u03ae\u03c8\u03b5\u03c9\u03bd ConfigView.label.maxactivetorrents=\u039c\u03b5\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03bf\u03c2 \u03b5\u03bd\u03b5\u03c1\u03b3\u03c9\u03bd torrents [0: \u03b1\u03c0\u03b5\u03c1\u03b9\u03bf\u03c1\u03b9\u03c3\u03c4\u03bf\u03c2]\n - \u03a4\u03b1 \u03bd\u03b5\u03b1 torrents \u03b4\u03b5\u03bd 8\u03b1 \u03be\u03b5\u03ba\u03b9\u03bd\u03b7\u03c3\u03bf\u03c5\u03bd \u03b5\u03b1\u03bd \u03bb\u03b1\u03bc\u03b2\u03b1\u03bd\u03b5\u03c4\u03b5/\u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03b6\u03b5\u03c4\u03b5 \u03c0\u03b5\u03c1\u03b9\u03c3\u03c3\u03bf\u03c4\u03b5\u03c1\u03b1 ConfigView.label.priorityExtensions=\u0391\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b7 \u03c0\u03b1\u03c1\u03b1\u03c7\u03ce\u03c1\u03b7\u03c3\u03b7 \u03c0\u03c1\u03bf\u03c4\u03b5\u03c1\u03b1\u03b9\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2 \u03c3\u03b5 \u03b1\u03c1\u03c7\u03b5\u03af\u03b1 \u03bc\u03b5 \u03b5\u03c0\u03ad\u03ba\u03c4\u03b1\u03c3\u03b7\n - \u03c0\u03b1\u03c1\u03ac\u03b4\u03b5\u03b9\u03b3\u03bc\u03b1: .txt;.nfo;.jpg ConfigView.section.transfer=\u039c\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ac ConfigView.label.maxuploads=\u03a0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03b5\u03b3\u03bc\u03ad\u03bd\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc\u03c2 \u03bc\u03ad\u03b3\u03b9\u03c3\u03c4\u03c9\u03bd \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ce\u03bd \u03b1\u03bd\u03ac torrent ConfigView.label.maxuploadspeed=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03b7 \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 (\u03b3\u03b5\u03bd\u03b9\u03ba\u03ae) ConfigView.label.saveresumeinterval=\u0395\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd \u03b5\u03c0\u03b1\u03bd\u03b1\u03c6\u03bf\u03c1\u03ac\u03c2 \u03ba\u03ac\u03b8\u03b5 ConfigView.unlimited=\u03a7\u03c9\u03c1\u03af\u03c2 \u038c\u03c1\u03b9\u03bf ConfigView.section.display=\u0395\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 ConfigView.label.opendetails=\u0391\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03bf \u03ac\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03c4\u03b7\u03c2 \u03ba\u03b1\u03c1\u03c4\u03ad\u03bb\u03b1\u03c2 \u03bb\u03b5\u03c0\u03c4\u03bf\u03bc\u03b5\u03c1\u03b9\u03ce\u03bd ConfigView.label.openbar=\u0391\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03bf \u03ac\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03c4\u03b7\u03c2 \u03c1\u03ac\u03b2\u03b4\u03bf\u03c5 \u03bb\u03ae\u03c8\u03b7\u03c2 ConfigView.label.closetotray=\u03a4\u03bf \u03ba\u03bb\u03b5\u03af\u03c3\u03b9\u03bc\u03bf \u03b5\u03bb\u03b1\u03c7\u03b9\u03c3\u03c4\u03bf\u03c0\u03bf\u03b9\u03b5\u03af \u03c3\u03c4\u03bf Tray \u03c3\u03c5\u03c3\u03c4\u03ae\u03bc\u03b1\u03c4\u03bf\u03c2 ConfigView.label.minimizetotray=\u0397 \u03b5\u03bb\u03b1\u03c7\u03b9\u03c3\u03c4\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03b5\u03bb\u03b1\u03c7\u03b9\u03c3\u03c4\u03bf\u03c0\u03bf\u03b9\u03b5\u03af \u03c3\u03c4\u03bf Tray \u03c3\u03c5\u03c3\u03c4\u03ae\u03bc\u03b1\u03c4\u03bf\u03c2 ConfigView.section.general=\u0393\u03b5\u03bd\u03b9\u03ba\u03ac ConfigView.section.start=\u0395\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 ConfigView.label.showsplash=\u0395\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 \u03c0\u03b1\u03c1\u03b1\u03b8\u03cd\u03c1\u03bf\u03c5 \u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7\u03c2 ConfigView.label.autoupdate=\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03c0\u03b1\u03c1\u03b1\u03b8\u03cd\u03c1\u03bf\u03c5 \u0391\u03bd\u03b1\u03b2\u03ac\u03b8\u03bc\u03b9\u03c3\u03b7\u03c2 \u03cc\u03c4\u03b1\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03bc\u03af\u03b1 \u03ba\u03b1\u03b9\u03bd\u03bf\u03cd\u03c1\u03b3\u03b9\u03b1 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7 ConfigView.label.openconsole=\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u039a\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1\u03c2 \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03b5\u03ba\u03ba\u03af\u03bd\u03b9\u03c3\u03b7 ConfigView.label.openconfig=\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ce\u03bd \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03b5\u03ba\u03ba\u03af\u03bd\u03b9\u03c3\u03b7 ConfigView.label.startminimized=\u0395\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u0395\u03bb\u03b1\u03c7\u03b9\u03c3\u03c4\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03bf ConfigView.section.irc=Irc ConfigView.label.ircserver=\u0394\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae\u03c2 ConfigView.label.ircchannel=\u039a\u03b1\u03bd\u03ac\u03bb\u03b9 ConfigView.label.irclogin=\u03a8\u03b5\u03c5\u03b4\u03c9\u03bd\u03c5\u03bc\u03bf ConfigView.section.security=\u0391\u03c3\u03c6\u03ac\u03bb\u03b5\u03b9\u03b1 ConfigView.label.password=\u03a0\u03c1\u03bf\u03c3\u03c4\u03b1\u03c3\u03af\u03b1 \u03c4\u03bf\u03c5 Vuze \u03bc\u03b5 \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc\n - \u0398\u03b1 \u03b6\u03b7\u03c4\u03b7\u03b8\u03b5\u03af \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03b1\u03c0\u03bf-\u03b5\u03b9\u03ba\u03bf\u03bd\u03b9\u03b4\u03b9\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03ba\u03b1\u03b9 \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7. ConfigView.label.passwordconfirm=\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 (\u03b5\u03c0\u03b9\u03b2\u03b5\u03b2\u03b1\u03b9\u03ce\u03c3\u03c4\u03b5) ConfigView.label.passwordmatch=\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u0395\u03bd\u03b5\u03c1\u03b3\u03cc\u03c2 : ConfigView.label.passwordmatchnone=\u038c\u03c7\u03b9 ConfigView.label.passwordmatchno=\u038c\u03c7\u03b9 / \u039f\u03b9 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03af \u03b4\u03b5\u03bd \u03c4\u03b1\u03b9\u03c1\u03b9\u03ac\u03b6\u03bf\u03c5\u03bd ConfigView.label.passwordmatchyes=\u039d\u03b1\u03b9 ConfigView.button.save=\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 ConfigView.title.short=\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ad\u03c2 ConfigView.title.full=\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ad\u03c2 ConsoleView.title.short=\u039a\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1 ConsoleView.title.full=\u039a\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1 FileItem.write=\u03b5\u03b3\u03b3\u03c1\u03b1\u03c6\u03ae FileItem.read=\u03b1\u03bd\u03ac\u03b3\u03bd\u03c9\u03c3\u03b7 FileItem.normal=\u03ba\u03b1\u03bd\u03bf\u03bd\u03b9\u03ba\u03ae FileItem.high=\u03c5\u03c8\u03b7\u03bb\u03ae FileItem.donotdownload=\u039d\u03b1 \u03bc\u03b7 \u03b3\u03af\u03bd\u03b5\u03b9 \u03bb\u03ae\u03c8\u03b7 FilesView.name=\u038c\u03bd\u03bf\u03bc\u03b1 FilesView.size=\u039c\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 FilesView.done=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 FilesView.%=% FilesView.firstpiece=\u03a0\u03c1\u03ce\u03c4\u03bf \u039a\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9 # FilesView.numberofpieces=# \u03ba\u03bf\u03bc\u03bc\u03b1\u03c4\u03b9\u03ce\u03bd FilesView.pieces=\u039a\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9\u03b1 FilesView.mode=\u039b\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 FilesView.priority=\u03a0\u03c1\u03bf\u03c4\u03b5\u03c1\u03b1\u03b9\u03cc\u03c4\u03b7\u03c4\u03b1 FilesView.menu.open=\u0386\u03bd&\u03bf\u03b9\u03b3\u03bc\u03b1 FilesView.menu.setpriority=&\u039f\u03c1\u03b9\u03c3\u03bc\u03cc\u03c2 \u03a0\u03c1\u03bf\u03c4\u03b5\u03c1\u03b1\u03b9\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2 FilesView.menu.setpriority.high=&\u03a5\u03c8\u03b7\u03bb\u03ae FilesView.menu.setpriority.normal=&\u039a\u03b1\u03bd\u03bf\u03bd\u03b9\u03ba\u03ae FilesView.menu.setpriority.skipped=\u039d\u03b1 &\u03bc\u03b7 \u03b3\u03af\u03bd\u03b5\u03b9 \u039b\u03ae\u03c8\u03b7 FilesView.title.short=\u0391\u03c1\u03c7\u03b5\u03af\u03b1 FilesView.title.full=\u0391\u03c1\u03c7\u03b5\u03af\u03b1 GeneralView.section.downloaded=\u03a0\u03bf\u03c3\u03bf\u03c3\u03c4\u03cc \u03bb\u03ae\u03c8\u03b7\u03c2 GeneralView.label.status.file=\u0391\u03c1\u03c7\u03b5\u03af\u03bf GeneralView.label.status.pieces=\u039a\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9\u03b1 GeneralView.section.availability=\u0394\u03b9\u03b1\u03b8\u03b5\u03c3\u03b9\u03bc\u03cc\u03c4\u03b7\u03c4\u03b1 GeneralView.label.status.pieces_available=\u039a\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9\u03b1 GeneralView.section.transfer=\u039c\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ac GeneralView.section.info=\u03a0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 GeneralView.title.short=\u0393\u03b5\u03bd\u03b9\u03ba\u03ac GeneralView.title.full=\u0393\u03b5\u03bd\u03b9\u03ba\u03ac GeneralView.label.timeelapsed=\u03a7\u03c1\u03cc\u03bd\u03bf\u03c2 \u03c0\u03bf\u03c5 \u03c0\u03ad\u03c1\u03b1\u03c3\u03b5 : GeneralView.label.remaining=\u0391\u03c0\u03bf\u03bc\u03ad\u03bd\u03bf\u03c5\u03bd: GeneralView.label.downloaded=\u0388\u03c7\u03bf\u03c5\u03bd \u03bb\u03b7\u03c6\u03b8\u03b5\u03af : GeneralView.label.downloadspeed=\u03a4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u039b\u03ae\u03c8\u03b7\u03c2 : GeneralView.label.maxuploads=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03b5\u03c2 \u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ad\u03c2 : GeneralView.label.uploaded=\u0388\u03b3\u03b9\u03bd\u03b5 \u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae : GeneralView.label.uploadspeed=\u03a4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 : GeneralView.label.seeds=\u0391\u03bd\u03b1\u03b6\u03b7\u03c4\u03ae\u03c3\u03b5\u03b9\u03c2 : GeneralView.label.peers=\u03a3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03b9\u03c2 : GeneralView.label.totalspeed=\u03a3\u03c5\u03bd\u03bf\u03bb\u03b9\u03ba\u03ae \u03a4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 : GeneralView.label.totalspeed.tooltip=\u03a4\u03bf \u03c3\u03cd\u03bd\u03bf\u03bb\u03bf \u03c4\u03b7\u03c2 \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1\u03c2 \u03cc\u03bb\u03c9\u03bd \u03c4\u03c9\u03bd \u03b5\u03bd\u03b5\u03c1\u03b3\u03ce\u03bd \u03c3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03c9\u03bd. GeneralView.label.filename=\u038c\u03bd\u03bf\u03bc\u03b1 : GeneralView.label.totalsize=\u03a3\u03c5\u03bd\u03bf\u03bb\u03b9\u03ba\u03cc \u039c\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 : GeneralView.label.savein=\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c3\u03b5 : GeneralView.label.hash=\u0391\u03bd\u03b1\u03b3\u03bd\u03c9\u03c1\u03b9\u03c3\u03c4\u03b9\u03ba\u03cc : GeneralView.label.numberofpieces=# \u03ba\u03bf\u03bc\u03bc\u03b1\u03c4\u03b9\u03ce\u03bd : GeneralView.label.size=\u039c\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 : GeneralView.label.tracker=\u039a\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7 \u0399\u03c7\u03bd\u03b7\u03bb\u03ac\u03c4\u03b7: GeneralView.label.updatein=\u0395\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u03c3\u03b5 : GeneralView.label.trackerurl=\u0394\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 \u0399\u03c7\u03bd\u03b7\u03bb\u03ac\u03c4\u03b7 : GeneralView.label.trackerurlupdate=\u0395\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u0399\u03c7\u03bd\u03b7\u03bb\u03ac\u03c4\u03b7 GeneralView.label.comment=\u03a3\u03c7\u03cc\u03bb\u03b9\u03bf : ManagerItem.waiting=\u0391\u03bd\u03b1\u03bc\u03bf\u03bd\u03ae ManagerItem.allocating=\u0394\u03ad\u03c3\u03bc\u03b5\u03c5\u03c3\u03b7 \u03c7\u03ce\u03c1\u03bf\u03c5 ManagerItem.checking=\u0388\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 ManagerItem.ready=\u0388\u03c4\u03bf\u03b9\u03bc\u03bf ManagerItem.downloading=\u0393\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03bb\u03ae\u03c8\u03b7 ManagerItem.seeding=\u0394\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03ac\u03b6\u03b5\u03c4\u03b1\u03b9 ManagerItem.stopped=\u03a3\u03c4\u03b1\u03bc\u03b1\u03c4\u03b7\u03bc\u03ad\u03bd\u03bf ManagerItem.error=\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1 ManagerItem.high=\u03c5\u03c8\u03b7\u03bb\u03ae ManagerItem.low=\u03c7\u03b1\u03bc\u03b7\u03bb\u03ae MinimizedWindow.name=\u038c\u03bd\u03bf\u03bc\u03b1: PiecesView.#=# PiecesView.size=\u039c\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 PiecesView.numberofblocks=# \u03c4\u03bc\u03b7\u03bc\u03b1\u03c4\u03c9\u03bd PiecesView.blocks=\u03a4\u03bc\u03b7\u03bc\u03b1\u03c4\u03b1 PiecesView.completed=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 PiecesView.availability=\u0394\u03b9\u03b1\u03b8\u03b5\u03c3\u03b9\u03bc\u03bf\u03c4\u03b7\u03c4\u03b1 PiecesView.title.short=\u039a\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9\u03b1 PiecesView.title.full=\u039a\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9\u03b1 SystemTray.tooltip.seeding=%1 \u00a0\u03c3\u03b5 \u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03cc, SystemTray.tooltip.downloading=%1 \u00a0\u03c3\u03b5 \u03bb\u03ae\u03c8\u03b7, DownloadManager.error.filenotfound=\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b4\u03b5\u03bd \u03b2\u03c1\u03ad\u03b8\u03b7\u03ba\u03b5 DownloadManager.error.fileempty=\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf torrent \u03b5\u03af\u03bd\u03b1\u03b9 \u03ac\u03b4\u03b5\u03b9\u03bf DownloadManager.error.filetoobig=\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf torrent \u03b5\u03af\u03bd\u03b1\u03b9 \u03c5\u03c0\u03b5\u03c1\u03b2\u03bf\u03bb\u03b9\u03ba\u03ac \u03bc\u03b5\u03b3\u03ac\u03bb\u03bf DownloadManager.error.filewithouttorrentinfo=\u0394\u03b5\u03bd \u03b2\u03c1\u03ad\u03b8\u03b7\u03ba\u03b1\u03bd \u03c0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 torrent \u03c3\u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf DownloadManager.error.unsupportedencoding=\u0397 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03b4\u03b5\u03bd \u03c5\u03c0\u03bf\u03c3\u03c4\u03b7\u03c1\u03af\u03b6\u03b5\u03c4\u03b1\u03b9 DownloadManager.error.ioerror=\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1 \u0391\u03bd\u03ac\u03b3\u03bd\u03c9\u03c3\u03b7\u03c2/\u0395\u03b3\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2 DownloadManager.error.sha1=\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1: \u0394\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03c4\u03ad\u03c4\u03b5\u03b9\u03bf\u03c2 \u03b1\u03bb\u03b3\u03cc\u03c1\u03b9\u03b8\u03bc\u03bf\u03c2 (SHA1) PeerManager.status.offline=\u03a3\u03c6\u03b1\u03bb\u03bc\u03b1 \u03c3\u03c5\u03bd\u03b4\u03b5\u03c3\u03b7\u03c2 PeerManager.status.ok=\u039f\u039a PeerManager.status.checking=\u03ad\u03bb\u03b5\u03c7\u03b3\u03bf\u03c2 PeerManager.status.finished=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 PeerManager.status.finishedin=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 \u03c3\u03b5 MainWindow.upgrade.assistant=\u039f\u03b4\u03b7\u03b3\u03cc\u03c2 \u0391\u03bd\u03b1\u03b2\u03ac\u03b8\u03bc\u03b9\u03c3\u03b7\u03c2 MainWindow.upgrade.newerversion=\u03a5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03bc\u03b9\u03b1 \u03bd\u03ad\u03b1 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7 \u03c4\u03bf\u03c5 Vuze \u03c0\u03bf\u03c5 \u03bc\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03ba\u03b1\u03c4\u03b5\u03b2\u03ac\u03c3\u03b5\u03c4\u03b5 MainWindow.upgrade.explanation=\u0391\u03c5\u03c4\u03cc\u03c2 \u03bf \u03bf\u03b4\u03b7\u03b3\u03cc\u03c2 \u03b8\u03b1 \u03ba\u03b1\u03c4\u03b5\u03b2\u03ac\u03c3\u03b5\u03b9 \u03c4\u03b7\u03bd \u03ba\u03b1\u03b9\u03bd\u03bf\u03cd\u03c1\u03b3\u03b9\u03b1 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7 \u03c3\u03c4\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf Vuze \u03ba\u03b1\u03b9 \u03ad\u03c0\u03b5\u03b9\u03c4\u03b1 \u03b8\u03b1 \u03b5\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03b9\u03bd\u03ae\u03c3\u03b5\u03b9 \u03c4\u03bf Vuze MainWindow.upgrade.explanation.manual=\u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03b1\u03bd\u03b1\u03b2\u03b1\u03b8\u03bc\u03af\u03c3\u03b5\u03c4\u03b5 \u03bc\u03b7 \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b1 \u03ba\u03bb\u03b5\u03af\u03bd\u03bf\u03bd\u03c4\u03b1\u03c2 \u03c4\u03bf Vuze \u03ba\u03b1\u03c4\u03b5\u03b2\u03ac\u03b6\u03bf\u03bd\u03c4\u03b1\u03c2 \u03c4\u03b7\u03bd \u03bd\u03ad\u03b1 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7 \u03ba\u03b1\u03b9 \u03b5\u03c0\u03b1\u03bd\u03bd\u03b5\u03ba\u03b9\u03bd\u03cc\u03bd\u03c4\u03b1\u03c2 \u03c4\u03bf Vuze MainWindow.upgrade.step1=\u0392\u03ae\u03bc\u03b1 1: \u039b\u03ae\u03c8\u03b7 \u03bd\u03ad\u03b1\u03c2 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7\u03c2 MainWindow.upgrade.step2=\u0392\u03ae\u03bc\u03b1 2: \u039a\u03bb\u03b5\u03af\u03c3\u03b9\u03bc\u03bf \u03c4\u03b7\u03c2 \u03c0\u03b1\u03c1\u03bf\u03cd\u03c3\u03b1\u03c2 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7\u03c2 \u03ba\u03b1\u03b9 \u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03c4\u03b7\u03c2 \u03bd\u03ad\u03b1\u03c2. MainWindow.upgrade.hint1=\u03a3\u03c5\u03bc\u03b2\u03bf\u03c5\u03bb\u03ae:\t\u03a0\u03b1\u03c4\u03ce\u03bd\u03c4\u03b1\u03c2 \u03a4\u03ad\u03bb\u03bf\u03c2 \u03cc\u03bb\u03b1 \u03b3\u03af\u03bd\u03bf\u03bd\u03c4\u03b1\u03b9 \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b1 MainWindow.upgrade.hint2=\u03a3\u03c5\u03bc\u03b2\u03bf\u03c5\u03bb\u03ae:\t\u0391\u03bd \u03b8\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03ba\u03bb\u03b5\u03af\u03c3\u03b5\u03c4\u03b5 \u03c4\u03bf Vuze \u03b1\u03c1\u03b3\u03cc\u03c4\u03b5\u03c1\u03b1, \u03c0\u03b1\u03c4\u03ae\u03c3\u03c4\u03b5 \u0386\u03ba\u03c5\u03c1\u03bf \u03ba\u03b1\u03b9\n\t\u03bc\u03b5\u03c4\u03bf\u03bd\u03bf\u03bc\u03ac\u03c3\u03c4\u03b5 \u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf Azureus2-new.jar \u03c3\u03b5 Azureus2.jar \u03bc\u03b5\u03c4\u03ac \u03c4\u03bf \u03ba\u03bb\u03b5\u03af\u03c3\u03b9\u03bc\u03bf MainWindow.upgrade.error.downloading.hint=\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1:\t\u0394\u03b5\u03bd \u03ae\u03c4\u03b1\u03bd \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae \u03b7 \u03bb\u03ae\u03c8\u03b7 \u03c4\u03b7\u03c2 \u03bd\u03ad\u03b1\u03c2 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7\u03c2, \u03c0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03b1\u03bd\u03b1\u03b2\u03b1\u03b8\u03bc\u03af\u03c3\u03c4\u03b5 \u03c4\u03bf \u03c0\u03c1\u03cc\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1 \u03bc\u03b7 \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b1 MainWindow.upgrade.section.info=\u03a5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03bc\u03af\u03b1 \u039d\u03ad\u03b1 \u0388\u03ba\u03b4\u03bf\u03c3\u03b7 MainWindow.upgrade.section.manual=\u039c\u03b7 \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b7 \u03b1\u03bd\u03b1\u03b2\u03ac\u03b8\u03bc\u03b9\u03c3\u03b7 MainWindow.upgrade.section.automatic=\u0391\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b7 \u03b1\u03bd\u03b1\u03b2\u03ac\u03b8\u03bc\u03b9\u03c3\u03b7 MainWindow.upgrade.tooltip.progressbar=\u0397 \u03c0\u03c1\u03cc\u03bf\u03b4\u03bf\u03c2 \u03bb\u03ae\u03c8\u03b7\u03c2 \u03b5\u03bc\u03c6\u03b1\u03bd\u03af\u03b6\u03b5\u03c4\u03b1\u03b9 \u03b5\u03b4\u03ce Button.next=\u0395\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf Button.finish=\u03a4\u03ad\u03bb\u03bf\u03c2 Button.cancel=\u0386\u03ba\u03c5\u03c1\u03bf LocaleUtil.title=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u039a\u03c9\u03b4\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 LocaleUtil.section.chooseencoding=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03b3\u03b9\u03b1 \u03c4\u03bf \u03cc\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 LocaleUtil.label.chooseencoding=\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03b7\u03bd \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03c0\u03bf\u03c5 \u03c4\u03b1\u03b9\u03c1\u03af\u03b1\u03b6\u03b5\u03b9 \u03c0\u03b5\u03c1\u03b9\u03c3\u03c3\u03cc\u03c4\u03b5\u03c1\u03bf LocaleUtil.label.hint.doubleclick=\u03a3\u03c5\u03bc\u03b2\u03bf\u03c5\u03bb\u03ae: \u039a\u03ac\u03bd\u03bf\u03bd\u03c4\u03b1\u03c2 \u03b4\u03b9\u03c0\u03bb\u03cc \u03ba\u03bb\u03b9\u03ba \u03c3\u03b5 \u03bc\u03af\u03b1 \u03b3\u03c1\u03b1\u03bc\u03bc\u03ae \u03b5\u03c0\u03b9\u03bb\u03ad\u03b3\u03b5\u03c4\u03b5 \u03c4\u03b7\u03bd \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03ba\u03b1\u03b9 \u03ba\u03bb\u03b5\u03af\u03bd\u03b5\u03c4\u03b5 \u03c4\u03bf \u03c0\u03b1\u03c1\u03ac\u03b8\u03c5\u03c1\u03bf LocaleUtil.label.checkbox.rememberdecision=\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae\u03c2 \u03ba\u03b1\u03b9 \u03b3\u03b9\u03b1 \u03c4\u03b1 \u03c5\u03c0\u03cc\u03bb\u03bf\u03b9\u03c0\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03b1 LocaleUtil.column.encoding=\u039a\u03c9\u03b4\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 IrcClient.copyright=\u03a7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ce\u03bd\u03c4\u03b1\u03c2 \u03c4\u03bf PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=\u0393\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7 \u03bc\u03b5 IrcClient.connected=\u0388\u03b3\u03b9\u03bd\u03b5 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7 \u03bc\u03b5 IrcClient.joining=\u0395\u03af\u03c3\u03bf\u03b4\u03bf\u03c2 \u03c3\u03c4\u03bf IrcClient.channel=\u039a\u03b1\u03bd\u03ac\u03bb\u03b9 IrcClient.joined=\u03ad\u03b3\u03b9\u03bd\u03b5 \u03b5\u03af\u03c3\u03bf\u03b4\u03bf\u03c2 \u03c3\u03c4\u03bf IrcClient.error=\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1 IrcClient.hasjoined=\u03bc\u03c0\u03ae\u03ba\u03b5 \u03c3\u03c4\u03bf IrcClient.haskicked=\u03ad\u03b4\u03b9\u03c9\u03be\u03b5 \u03c4\u03bf\u03bd/\u03c4\u03b7\u03bd IrcClient.hasleft=\u03b2\u03b3\u03ae\u03ba\u03b5 \u03b1\u03c0\u03cc \u03c4\u03bf IrcClient.nowknown=\u03ac\u03bb\u03bb\u03b1\u03be\u03b5 \u03c4\u03bf \u03c8\u03b5\u03c5\u03b4\u03ce\u03bd\u03c5\u03bc\u03cc \u03c4\u03bf\u03c5/\u03c4\u03b7\u03c2 \u03c3\u03b5 IrcClient.topicforchannel=\u0398\u03ad\u03bc\u03b1 \u03c3\u03c5\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7\u03c2 \u03ba\u03b1\u03bd\u03b1\u03bb\u03b9\u03bf\u03cd IrcClient.disconnected=\u0388\u03b3\u03b9\u03bd\u03b5 \u03b1\u03c0\u03bf\u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7 \u03b1\u03c0\u03cc IrcClient.noNick=\u0394\u03b5\u03bd \u03ad\u03c7\u03b5\u03b9 \u03bf\u03c1\u03b9\u03c3\u03c4\u03b5\u03af \u03c8\u03b5\u03c5\u03b4\u03ce\u03bd\u03c5\u03bc\u03bf. \u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03bc\u03b5\u03c4\u03b1\u03b2\u03b5\u03af\u03c4\u03b5 \u03c3\u03c4\u03b9\u03c2 '\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ad\u03c2' IrcView.actionnotsupported=\u0391\u03c5\u03c4\u03ae \u03b7 \u03b5\u03bd\u03ad\u03c1\u03b3\u03b5\u03b9\u03b1 \u03b4\u03b5\u03bd \u03c5\u03c0\u03bf\u03c3\u03c4\u03b7\u03c1\u03af\u03b6\u03b5\u03c4\u03b1\u03b9 IrcView.clientsconnected=\u03c7\u03c1\u03ae\u03c3\u03c4\u03b5\u03c2 IrcView.privateto=\u03a0\u03c1\u03bf\u03c2 IrcView.privatefrom=\u0391\u03c0\u03cc IrcView.noticefrom=\u039c\u03ae\u03bd\u03c5\u03bc\u03b1 : IrcView.errormsg=\u0395\u03c3\u03c6\u03b1\u03bb\u03bc\u03ad\u03bd\u03b7 \u03c3\u03cd\u03bd\u03c4\u03b1\u03be\u03b7 \u03c4\u03bf\u03c5 /msg. \u03a7\u03c1\u03b7\u03c3\u03b7 : /msg \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2 \u03ba\u03b5\u03af\u03bc\u03b5\u03bd\u03bf IrcView.help=\u039f\u03b9 \u03b5\u03c0\u03b9\u03c4\u03c1\u03b5\u03c0\u03cc\u03bc\u03b5\u03bd\u03b5\u03c2 \u03b5\u03bd\u03c4\u03bf\u03bb\u03ad\u03c2 \u03b5\u03af\u03bd\u03b1\u03b9 :\n . /help : \u03b5\u03bc\u03c6\u03b1\u03bd\u03af\u03b6\u03b5\u03b9 \u03b1\u03c5\u03c4\u03cc \u03c4\u03bf \u03bc\u03ae\u03bd\u03c5\u03bc\u03b1\n . /nick | /name : \u03b1\u03bb\u03bb\u03ac\u03b6\u03b5\u03b9 \u03c4\u03bf \u03c8\u03b5\u03c5\u03b4\u03cc\u03bd\u03c5\u03bc\u03cc \u03c3\u03b1\u03c2 \n . /me \u03b5\u03bd\u03ad\u03c1\u03b3\u03b5\u03b9\u03b1 : \u03c3\u03c4\u03ad\u03bb\u03bd\u03b5\u03b9 \u03bc\u03af\u03b1 \u03b5\u03bd\u03ad\u03c1\u03b3\u03b5\u03b9\u03b1 \u03ae \u03c0\u03c1\u03ac\u03be\u03b7 \n . /msg \u03c8\u03b5\u03c5\u03b4\u03cc\u03bd\u03c5\u03bc\u03bf \u03bc\u03ae\u03bd\u03c5\u03bc\u03b1 : \u03c3\u03c4\u03ad\u03bb\u03bd\u03b5\u03b9 \u03ad\u03bd\u03b1 \u03c0\u03c1\u03bf\u03c3\u03c9\u03c0\u03b9\u03ba\u03cc \u03bc\u03ae\u03bd\u03c5\u03bc\u03b1 \n . /r \u03bc\u03ae\u03bd\u03c5\u03bc\u03b1 : \u03b1\u03c0\u03b1\u03bd\u03c4\u03ac\u03b5\u03b9 \u03c3\u03c4\u03bf \u03c4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03bf \u03c0\u03c1\u03bf\u03c3\u03c9\u03c0\u03b9\u03ba\u03cc \u03c3\u03b1\u03c2 \u03bc\u03ae\u03bd\u03c5\u03bc\u03b1 \n . /join #\u03ba\u03b1\u03bd\u03ac\u03bb\u03b9 : \u03b1\u03bb\u03bb\u03ac\u03b6\u03b5\u03b9 \u03c4\u03bf \u03b5\u03bd\u03b5\u03c1\u03b3\u03cc \u03ba\u03b1\u03bd\u03ac\u03bb\u03b9 PasswordWindow.title=\u03a4\u03bf Vuze \u03b5\u03af\u03bd\u03b1\u03b9 \u03ba\u03bb\u03b5\u03b9\u03b4\u03c9\u03bc\u03ad\u03bd\u03bf PasswordWindow.passwordprotected=\u03a4\u03bf Vuze \u03c0\u03c1\u03bf\u03c3\u03c4\u03b1\u03c4\u03b5\u03cd\u03b5\u03c4\u03b1\u03b9 \u03bc\u03b5 \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc.\n\u0393\u03b9\u03b1 \u03bd\u03b1 \u03b5\u03bc\u03c6\u03b1\u03bd\u03b9\u03c3\u03c4\u03b5\u03af \u03c4\u03bf \u03c0\u03b1\u03c1\u03ac\u03b8\u03c5\u03c1\u03bf \u03c4\u03bf\u03c5 Vuze \u03c0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03c0\u03bb\u03b7\u03ba\u03c4\u03c1\u03bf\u03bb\u03bf\u03b3\u03b5\u03af\u03c3\u03c4\u03b5 \u03c4\u03bf\u03bd \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c3\u03b1\u03c2 \u03b5\u03b4\u03ce : Button.ok=\u039f\u039a TrackerChangerWindow.title=\u03a0\u03c1\u03bf\u03c3\u03b8\u03b7\u03ba\u03b7 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 TrackerChangerWindow.newtracker=\u03a0\u03bb\u03b7\u03ba\u03c4\u03c1\u03bf\u03bb\u03bf\u03b3\u03b5\u03af\u03c3\u03c4\u03b5 \u03c4\u03b7 \u03b4\u03b9\u03b5\u03c5\u03b8\u03c5\u03bd\u03c3\u03b7 \u03c4\u03bf\u03c5 \u03bd\u03b5\u03bf\u03c5 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 PeersView.discarded=\u0391\u03b3\u03bd\u03bf\u03ae\u03b8\u03b7\u03ba\u03b5 discarded=\u03b1\u03b3\u03bd\u03bf\u03ae\u03b8\u03b7\u03ba\u03b1\u03bd MyTorrentsView.#=# MyTorrentsView.menu.move=&\u039c\u03b5\u03c4\u03b1\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 MyTorrentsView.menu.moveUp=&\u03a0\u03ac\u03bd\u03c9 MyTorrentsView.menu.moveDown=&\u039a\u03ac\u03c4\u03c9 GeneralView.label.hashfails=\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b5\u03c2 \u03b1\u03bd\u03b1\u03b3\u03bd\u03c9\u03c1\u03b9\u03c3\u03c4\u03b9\u03ba\u03bf\u03cd : GeneralView.label.shareRatio=\u0391\u03bd\u03b1\u03bb\u03bf\u03b3\u03af\u03b1 \u03a3\u03c5\u03bc\u03bc\u03b5\u03c4\u03bf\u03c7\u03ae\u03c2 : ConfigView.section.downloadManagement=\u0394\u03b9\u03b1\u03c7\u03b5\u03af\u03c1\u03b9\u03c3\u03b7 \u039b\u03ae\u03c8\u03b5\u03c9\u03bd ConfigView.label.startRatioPeers=\u0395\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03b1\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7\u03c2 \u03cc\u03c4\u03b1\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03bf\u03c5\u03bd \u03bb\u03b9\u03b3\u03cc\u03c4\u03b5\u03c1\u03b5\u03c2 \u03b1\u03c0\u03cc 1 \u03b1\u03bd\u03b1\u03b6\u03b7\u03c4\u03ae\u03c3\u03b5\u03b9\u03c2 \u03b3\u03b9\u03b1 ConfigView.text.neverStop=\u039d\u03b1 \u03bc\u03b7 \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03c0\u03bf\u03c4\u03ad \u03b4\u03b9\u03b1\u03ba\u03bf\u03c0\u03ae ConfigView.text.neverStart=\u039d\u03b1 \u03bc\u03b7 \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03c0\u03bf\u03c4\u03ad \u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 ConfigView.text.peers=\u03a3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03b9\u03c2 ConfigView.label.checkOncompletion=\u0395\u03c0\u03b1\u03bb\u03ae\u03b8\u03b5\u03c5\u03c3\u03b7 \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd \u03cc\u03c4\u03b1\u03bd \u03bc\u03af\u03b1 \u03bb\u03ae\u03c8\u03b7 \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03cc\u03bd\u03b5\u03c4\u03b1\u03b9 wizard.title=\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03b5\u03bd\u03cc\u03c2 torrent wizard.previous=< \u03a0\u03af\u03c3\u03c9 wizard.next=\u0395\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf > wizard.finish=\u03a4\u03ad\u03bb\u03bf\u03c2 wizard.mode=\u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7\u03c2 / \u039b\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 wizard.tracker=\u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7\u03c2: wizard.invalidurl=\u0397 \u03b4\u03b9\u03b5\u03c5\u03b8\u03c5\u03bd\u03c3\u03b7 \u03b4\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03ad\u03b3\u03ba\u03c5\u03c1\u03b7 wizard.singlefile=\u0388\u03bd\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf wizard.singlefile.help=\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03b5\u03bd\u03cc\u03c2 torrent \u03b1\u03c0\u03cc \u03ad\u03bd\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf wizard.directory=\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2 wizard.directory.help=\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03b5\u03bd\u03cc\u03c2 torrent \u03b1\u03c0\u03cc \u03ad\u03bd\u03b1 \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf wizard.choosefile=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf wizard.file=\u0391\u03c1\u03c7\u03b5\u03af\u03bf : wizard.browse=\u0391\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7... wizard.choosedirectory=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf wizard.invalidfile=\u039c\u03b7 \u03ad\u03b3\u03ba\u03c5\u03c1\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf! wizard.invaliddirectory=\u039c\u03b7 \u03ad\u03b3\u03ba\u03c5\u03c1\u03bf\u03c2 \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2! wizard.torrentFile=\u0391\u03c1\u03c7\u03b5\u03af\u03bf Torrent wizard.choosetorrent=\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf torrent \u03c0\u03c1\u03bf\u03c2 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 wizard.information=\u03a0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 wizard.notimplemented=\u0394\u03b5\u03bd \u03ad\u03c7\u03b5\u03b9 \u03c5\u03bb\u03bf\u03c0\u03bf\u03b9\u03b7\u03b8\u03b5\u03b9 \u03b1\u03ba\u03cc\u03bc\u03b7 wizard.progresstitle=\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03b5\u03af\u03c4\u03b1\u03b9 \u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf Torrent wizard.savingfile=\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u0391\u03c1\u03c7\u03b5\u03af\u03bf\u03c5... wizard.filesaved=\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b1\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c4\u03b7\u03ba\u03b5. wizard.close=\u039a\u03bb\u03b5\u03af\u03c3\u03b9\u03bc\u03bf Torrent.create.progress.piecelength=\u039c\u03b7\u03ba\u03bf\u03c2 \u03ba\u03bf\u03bc\u03bc\u03b1\u03c4\u03b9\u03bf\u03cd: Torrent.create.progress.piececount=\u0391\u03c1\u03b9\u03b8\u03bc\u03bf\u03c2 \u03ba\u03bf\u03bc\u03bc\u03b1\u03c4\u03b9\u03ce\u03bd: Torrent.create.progress.totalfilesize=\u03a3\u03c5\u03bd\u03bf\u03bb\u03b9\u03ba\u03cc \u03bc\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd: Torrent.create.progress.totalfilecount=\u03a3\u03c5\u03bd\u03bf\u03bb\u03b9\u03ba\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03bf\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd: Torrent.create.progress.parsingfiles=\u0391\u03bd\u03ac\u03bb\u03c5\u03c3\u03b7 \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd Torrent.create.progress.hashing=\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03b9\u03b1 \u03b1\u03bd\u03b1\u03b3\u03bd\u03c9\u03c1\u03b9\u03c3\u03c4\u03b9\u03ba\u03bf\u03cd \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd MainWindow.upgrade.downloadingfrom=\u0393\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03bb\u03ae\u03c8\u03b7 \u03b1\u03c0\u03cc : MainWindow.menu.view.ipFilter=\u03a6\u03af\u03bb\u03c4\u03c1\u03b1 &Ip ConfigView.section.ipfilter=\u03a6\u03af\u03bb\u03c4\u03c1\u03b1 Ip ConfigView.section.ipfilter.description=\u03a0\u03b5\u03c1\u03b9\u03b3\u03c1\u03b1\u03c6\u03ae ConfigView.section.ipfilter.start=\u0395\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 Ip ConfigView.section.ipfilter.end=\u03a4\u03ad\u03bb\u03bf\u03c2 Ip ConfigView.section.ipfilter.add=\u0395\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae ConfigView.section.ipfilter.remove=\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae ConfigView.section.ipfilter.edit=\u0395\u03c0\u03b5\u03be\u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1 ConfigView.section.ipfilter.save=\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 ConfigView.section.ipfilter.editFilter=\u0395\u03c0\u03b5\u03be\u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1 \u03a6\u03af\u03bb\u03c4\u03c1\u03bf\u03c5 ConfigView.section.ipfilter.enable=\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 PeersView.menu.close=&\u039a\u03bb\u03b5\u03af\u03c3\u03b9\u03bc\u03bf seedmore.title=\u0394\u03b5\u03bd \u03ad\u03c7\u03b5\u03b9 \u03b3\u03af\u03bd\u03b5\u03b9 \u03b1\u03c1\u03ba\u03b5\u03c4\u03bf\u03c2 \u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf\u03c2 \u03c4\u03bf\u03c5 torrent seedmore.shareratio=\u0397 \u03b1\u03bd\u03b1\u03bb\u03bf\u03b3\u03af\u03b1 \u03c3\u03c5\u03bc\u03bc\u03b5\u03c4\u03bf\u03c7\u03ae\u03c2 \u03c3\u03b5 \u03b1\u03c5\u03c4\u03cc \u03c4\u03bf torrent \u03b5\u03af\u03bd\u03b1\u03b9 seedmore.uploadmore=\u03a4\u03bf \u03bd\u03b1 \u03ad\u03c7\u03b5\u03c4\u03b5 \u03c0\u03bf\u03c3\u03bf\u03c3\u03c4\u03cc \u03c3\u03c5\u03bc\u03bc\u03b5\u03c4\u03bf\u03c7\u03ae\u03c2 \u03ba\u03ac\u03c4\u03c9 \u03c4\u03bf\u03c5 100% \u03b4\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03ba\u03b1\u03bb\u03cc \u03b3\u03b9\u03b1 \u03c4\u03b1 \u03b4\u03af\u03ba\u03c4\u03c5\u03b1 BitTorrent.\n\u038a\u03c3\u03c9\u03c2 \u03b8\u03b1 \u03ad\u03c0\u03c1\u03b5\u03c0\u03b5 \u03bd\u03b1 \u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03b5\u03c4\u03b5 \u03b1\u03c5\u03c4\u03cc \u03c4\u03bf torrent \u03bb\u03b9\u03b3\u03bf \u03c0\u03b5\u03c1\u03b9\u03c3\u03c3\u03bf\u03c4\u03b5\u03c1\u03bf.\n\u0398\u03ad\u03bb\u03b5\u03c4\u03b5 \u03c3\u03af\u03b3\u03bf\u03c5\u03c1\u03b1 \u03bd\u03b1 \u03c3\u03c5\u03bd\u03b5\u03c7\u03af\u03c3\u03b5\u03c4\u03b5? ConfigView.label.showpopuponclose=\u03a0\u03c1\u03bf\u03c4\u03c1\u03bf\u03c0\u03ae \u03cc\u03c4\u03b1\u03bd \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03b4\u03b9\u03b1\u03ba\u03bf\u03c0\u03ae \u03b1\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7\u03c2 \u03bc\u03b5 \u03c0\u03bf\u03c3\u03bf\u03c3\u03c4\u03cc \u03c3\u03c5\u03bc\u03bc\u03b5\u03c4\u03bf\u03c7\u03ae\u03c2 \u03ba\u03ac\u03c4\u03c9 \u03c4\u03bf\u03c5 1 ConfigView.label.startNumSeeds=\n\u0395\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03b1\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7\u03c2 \u03cc\u03c4\u03b1\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03bb\u03b9\u03b3\u03cc\u03c4\u03b5\u03c1\u03bf \u03b1\u03c0\u03cc\n - \u03a5\u03c0\u03b5\u03c1\u03b9\u03c3\u03c7\u03cd\u03b5\u03b9 \u03cc\u03bb\u03c9\u03bd \u03c4\u03c9\u03bd \u03c5\u03c0\u03bf\u03bb\u03bf\u03af\u03c0\u03c9\u03bd \u03ba\u03b1\u03bd\u03cc\u03bd\u03c9\u03bd ConfigView.label.seeds=\u03b3\u03bf\u03bd\u03bf\u03b9 ConfigView.section.seeding=\u0391\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7 MyTorrentsView.menu.removeand=&\u0391\u03c6\u03b1\u03af\u03c1\u03b5\u03c3\u03b7 \u03ba\u03b1\u03b9 MyTorrentsView.menu.removeand.deletetorrent=\u0394\u03b9\u03b1\u03b3\u03c1\u03b1&\u03c6\u03ae .&torrent MyTorrentsView.menu.removeand.deletedata=\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae \u0394&\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd MyTorrentsView.menu.removeand.deleteboth=\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae &\u03ba\u03b1\u03b9 \u03c4\u03c9\u03bd \u03b4\u03cd\u03bf deletedata.title=!!! \u03a0\u03c1\u03bf\u03c3\u03bf\u03c7\u03ae !!! deletedata.message1=\u03a0\u03c1\u03cc\u03ba\u03b5\u03b9\u03c4\u03b1\u03b9 \u03bd\u03b1 \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03b5\u03c4\u03b5 \u03c4\u03b1 \u0394\u0395\u0394\u039f\u039c\u0395\u039d\u0391 \u03b1\u03c0\u03cc \u03c4\u03bf :\n MainWindow.menu.file.configure=&\u039f\u03b4\u03b7\u03b3\u03cc\u03c2 \u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03c9\u03bd configureWizard.title=\u039f\u03b4\u03b7\u03b3\u03cc\u03c2 \u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03c9\u03bd configureWizard.welcome.title=\u039a\u03b1\u03bb\u03c9\u03c3\u03ae\u03c1\u03b8\u03b1\u03c4\u03b5 \u03c3\u03c4\u03bf\u03bd \u039f\u03b4\u03b7\u03b3\u03cc \u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03c9\u03bd \u03c4\u03bf\u03c5 Vuze configureWizard.welcome.message=\u0391\u03c5\u03c4\u03cc\u03c2 \u03bf \u03bf\u03b4\u03b7\u03b3\u03cc\u03c2 \u03b8\u03b1 \u03c3\u03b1\u03c2 \u03b2\u03bf\u03b7\u03b8\u03ae\u03c3\u03b5\u03b9 \u03bd\u03b1 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03c4\u03b5 \u03c4\u03bf Vuze \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd \u03c0\u03b9\u03bf \u03c3\u03c5\u03bd\u03b7\u03b8\u03b9\u03c3\u03bc\u03ad\u03bd\u03b7 \u03c7\u03c1\u03ae\u03c3\u03b7. \u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03b1\u03bb\u03bb\u03ac\u03be\u03b5\u03c4\u03b5 \u03c0\u03b5\u03c1\u03b9\u03c3\u03c3\u03cc\u03c4\u03b5\u03c1\u03b5\u03c2 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u03bc\u03b5\u03c4\u03b1\u03b2\u03b1\u03af\u03bd\u03bf\u03bd\u03c4\u03b1\u03c2 \u03c3\u03c4\u03bf \u0395\u03c1\u03b3\u03b1\u03bb\u03b5\u03b9\u03b1->\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ad\u03c2 \u03b1\u03c0\u03cc \u03c4\u03bf \u03bc\u03b5\u03bd\u03bf\u03cd. configureWizard.transfer.title=\u03a1\u03cd\u03b8\u03bc\u03b9\u03c3\u03b7 \u039c\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ce\u03bd \u03ba\u03b1\u03b9 \u03a3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03c9\u03bd configureWizard.transfer.hint=\u03a3\u03c5\u03bc\u03b2\u03bf\u03c5\u03bb\u03ae : \u03a7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03c4\u03b5 \u03bb\u03af\u03b3\u03bf \u03bc\u03b9\u03ba\u03c1\u03cc\u03c4\u03b5\u03c1\u03b7 \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u03b1\u03c0\u03cc \u03cc\u03c4\u03b9 \u03c3\u03b1\u03c2 \u03c0\u03c1\u03bf\u03c3\u03c6\u03ad\u03c1\u03b5\u03b9 \u03b7 \u03b3\u03c1\u03b1\u03bc\u03bc\u03ae \u03c3\u03b1\u03c2 \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03ad\u03c7\u03b5\u03c4\u03b5 \u03c4\u03b1 \u03ba\u03b1\u03bb\u03cd\u03c4\u03b5\u03c1\u03b1 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ac \u03b1\u03c0\u03bf\u03c4\u03b5\u03bb\u03ad\u03c3\u03bc\u03b1\u03c4\u03b1. configureWizard.transfer.message=\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03bc\u03af\u03b1 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7. \u03a3\u03b7\u03bc\u03b5\u03b9\u03ce\u03c3\u03c4\u03b5 \u03cc\u03c4\u03b9 \u03b1\u03bd \u03bc\u03b5\u03b9\u03ce\u03c3\u03b5\u03c4\u03b5 \u03c4\u03b7\u03bd \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 \u03b8\u03b1 \u03bc\u03b5\u03b9\u03c9\u03b8\u03b5\u03af \u03ba\u03b1\u03b9 \u03b7 \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u03bb\u03ae\u03c8\u03b7\u03c2. \u039a\u03b1\u03b8\u03ce\u03c2 \u03b7 \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 \u03c5\u03c0\u03bf\u03bb\u03bf\u03b3\u03af\u03b6\u03b5\u03c4\u03b1\u03b9 \u03b1\u03bd\u03ac torrent \u03c0\u03bf\u03c5 \u03ba\u03b1\u03c4\u03b5\u03b2\u03ac\u03b6\u03b5\u03c4\u03b5, \u03c4\u03bf \u03bd\u03b1 \u03ba\u03b1\u03c4\u03b5\u03b2\u03ac\u03c3\u03b5\u03c4\u03b5 \u03c0\u03bf\u03bb\u03bb\u03ac torrents \u03c4\u03b1\u03c5\u03c4\u03cc\u03c7\u03c1\u03bf\u03bd\u03b1 \u03b8\u03b1 \u03bf\u03b4\u03b7\u03b3\u03af\u03c3\u03b5\u03b9 \u03b5\u03c0\u03af\u03c3\u03b7\u03c2 \u03c3\u03b5 \u03bc\u03b9\u03ba\u03c1\u03cc\u03c4\u03b5\u03c1\u03b7 \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1. \u03a0\u03c1\u03bf\u03c4\u03b5\u03af\u03bd\u03bf\u03c5\u03bc\u03b5 \u03bd\u03b1 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03c4\u03b1 5KB/\u03b4\u03b5\u03c5\u03c4\u03b5\u03c1\u03cc\u03bb\u03b5\u03c0\u03c4\u03bf \u03b1\u03bd\u03ac torrent \u03c9\u03c2 \u03c4\u03bf \u039c\u0399\u039a\u03a1\u039f\u03a4\u0395\u03a1\u039f \u03b4\u03c5\u03bd\u03b1\u03c4\u03cc \u03b5\u03bb\u03ac\u03c7\u03b9\u03c3\u03c4\u03bf. \u038c\u03c3\u03bf \u03c0\u03b9\u03bf \u03b3\u03c1\u03ae\u03b3\u03bf\u03c1\u03b1 \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae, \u03c4\u03cc\u03c3\u03bf \u03c0\u03b9\u03bf \u03b3\u03c1\u03ae\u03b3\u03bf\u03c1\u03b1 \u03b8\u03b1 \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03ba\u03b1\u03b9 \u03bb\u03ae\u03c8\u03b7 (\u03c5\u03c0\u03bf\u03bb\u03bf\u03b3\u03af\u03b6\u03bf\u03bd\u03c4\u03b1\u03c2 \u03b2\u03ad\u03b2\u03b1\u03b9\u03b1 \u03ba\u03b1\u03b9 \u03c4\u03b7\u03bd \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u03c4\u03bf\u03c5 \u03b5\u03ba\u03b1\u03c3\u03c4\u03bf\u03c4\u03b5 torrent). configureWizard.transfer.connection=\u0393\u03c1\u03b1\u03bc\u03bc\u03ae configureWizard.transfer.connection.0=\u03a0\u03c1\u03bf\u03c3\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae configureWizard.transfer.connection.1=modem configureWizard.transfer.connection.2=ADSL/Cable xxx/128 kbps configureWizard.transfer.connection.3=ADSL/Cable xxx/256 kbps configureWizard.transfer.connection.4=ADSL/Cable xxx/384 kbps configureWizard.transfer.connection.5=ADSL/Cable xxx/512 kbps configureWizard.transfer.connection.6=ADSL/Cable xxx/768 kbps configureWizard.transfer.connection.7=ADSL/Cable xxx/1024 kbps configureWizard.transfer.maxUpSpeed=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03b7 \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 (KB/\u03b4\u03b5\u03c5\u03c4\u03b5\u03c1\u03cc\u03bb\u03b5\u03c0\u03c4\u03bf) configureWizard.transfer.maxActiveTorrents=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03b1 \u0395\u03bd\u03b5\u03c1\u03b3\u03ac configureWizard.transfer.maxDownloads=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc\u03c2 \u039b\u03ae\u03c8\u03b5\u03c9\u03bd configureWizard.transfer.maxUploadsPerTorrent=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc\u03c2 \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ce\u03bd \u03b1\u03bd\u03ac Torrent configureWizard.nat.title=NAT / \u0398\u03cd\u03c1\u03b1 \u0394\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae configureWizard.nat.message=\u0393\u03b9\u03b1 \u03bd\u03b1 \u03ad\u03c7\u03b5\u03c4\u03b5 \u03c4\u03b1 \u03ba\u03b1\u03bb\u03cd\u03c4\u03b5\u03c1\u03b1 \u03b1\u03c0\u03bf\u03c4\u03b5\u03bb\u03ad\u03c3\u03bc\u03b1\u03c4\u03b1 \u03bc\u03b5 \u03c4\u03bf BitTorrent, \u03c0\u03c1\u03bf\u03c4\u03b5\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03bd\u03b1 \u03b5\u03af\u03c3\u03c4\u03b5 \u03c0\u03bb\u03ae\u03c1\u03c9\u03c2 \u03c0\u03c1\u03bf\u03c3\u03b2\u03ac\u03c3\u03b9\u03bc\u03bf\u03c2 \u03bc\u03ad\u03c3\u03c9 internet. \u0397 \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03b5\u03b3\u03bc\u03ad\u03bd\u03b7 bittorrent \u03b8\u03cd\u03c1\u03b1 \u03b5\u03af\u03bd\u03b1\u03b9 \u03b7 6881. \u0391\u03c5\u03c4\u03cc \u03c4\u03bf \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf \u03c3\u03b1\u03c2 \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03b4\u03bf\u03ba\u03b9\u03bc\u03ac\u03c3\u03b5\u03c4\u03b5 \u03ba\u03b1\u03b9 / \u03ae \u03bd\u03b1 \u03b1\u03bb\u03bb\u03ac\u03be\u03b5\u03c4\u03b5 \u03c4\u03b7\u03bd \u03b8\u03cd\u03c1\u03b1. configureWizard.nat.test=\u0394\u03bf\u03ba\u03b9\u03bc\u03ae configureWizard.nat.testing=\u0393\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03b4\u03bf\u03ba\u03b9\u03bc\u03ae \u03c4\u03b7\u03c2 \u03b8\u03cd\u03c1\u03b1\u03c2 configureWizard.nat.ok=OK ! configureWizard.nat.ko=\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1 NAT configureWizard.nat.unable=\u0394\u03b5\u03bd \u03ae\u03c4\u03b1\u03bd \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae \u03b7 \u03b4\u03bf\u03ba\u03b9\u03bc\u03ae configureWizard.file.title=Torrents / \u0391\u03c1\u03c7\u03b5\u03af\u03b1 configureWizard.file.message1=\u03a4\u03bf Vuze \u03b8\u03b1 \u03b1\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c3\u03b5\u03b9 \u03c4\u03b1 \u03b1\u03bd\u03bf\u03b9\u03c7\u03c4\u03ac torrents \u03c3\u03b5 \u03ad\u03bd\u03b1 \u03c3\u03c5\u03b3\u03ba\u03b5\u03ba\u03c1\u03b9\u03bc\u03ad\u03bd\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf, \u03c0\u03bf\u03c5 \u03bc\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03b5\u03c4\u03b5 \u03b5\u03b4\u03ce: configureWizard.file.path=\u0394\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae configureWizard.file.browse=\u0391\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7 configureWizard.file.message2=\u03a4\u03bf Vuze \u03bc\u03c0\u03bf\u03c1\u03b5\u03af \u03bd\u03b1 \u03c3\u03c5\u03bd\u03b5\u03c7\u03af\u03c3\u03b5\u03b9 \u03c4\u03b7 \u03bc\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ac \u03c4\u03c9\u03bd \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd \u03c3\u03b1\u03c2, \u03b5\u03b9\u03c3\u03ac\u03b3\u03bf\u03bd\u03c4\u03b1\u03c2 \u03ba\u03ac\u03c0\u03bf\u03b9\u03b1 \u03b5\u03c0\u03b9\u03c0\u03bb\u03ad\u03bf\u03bd \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1 \u03c3\u03c4\u03b1 torrents \u03c3\u03b1\u03c2. \u03a7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ce\u03bd\u03c4\u03b1\u03c2 \u03b1\u03c5\u03c4\u03cc \u03c4\u03bf \u03c7\u03b1\u03c1\u03b1\u03ba\u03c4\u03b7\u03c1\u03b9\u03c3\u03c4\u03b9\u03ba\u03cc, \u03bc\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03b5\u03c0\u03af\u03c3\u03b7\u03c2 \u03bd\u03b1 \u03c3\u03c5\u03bd\u03b5\u03c7\u03af\u03c3\u03b5\u03c4\u03b5 \u03c4\u03b7 \u03bc\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ac \u03b7\u03bc\u03b9\u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03c9\u03bc\u03ad\u03bd\u03c9\u03bd \u03ba\u03bf\u03bc\u03bc\u03b1\u03c4\u03b9\u03ce\u03bd. configureWizard.file.fastResume=\u0393\u03c1\u03ae\u03b3\u03bf\u03c1\u03b7 \u0395\u03c0\u03b1\u03bd\u03b1\u03c6\u03bf\u03c1\u03ac configureWizard.file.invalidPath=\u039c\u03b7 \u03ad\u03b3\u03ba\u03c5\u03c1\u03bf\u03c2 \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2 configureWizard.finish.title=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 configureWizard.finish.message=\u03a4\u03bf Vuze \u03ad\u03c7\u03b5\u03b9 \u03c1\u03c5\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af, \u03ba\u03b1\u03bb\u03ae \u03b4\u03b9\u03b1\u03c3\u03ba\u03ad\u03b4\u03b1\u03c3\u03b7 ! wizard.close.confirmation=\u03a0\u03c1\u03bf\u03c4\u03c1\u03bf\u03c0\u03ae wizard.close.message=\u0398\u03ad\u03bb\u03b5\u03c4\u03b5 \u03b1\u03c5\u03c4\u03cc\u03c2 \u03bf \u03bf\u03b4\u03b7\u03b3\u03cc\u03c2 \u03bd\u03b1 \u03be\u03b5\u03ba\u03b9\u03bd\u03ae\u03c3\u03b5\u03b9 \u03c4\u03b7\u03bd \u03b5\u03c0\u03cc\u03bc\u03b5\u03bd\u03b7 \u03c6\u03bf\u03c1\u03ac \u03c0\u03bf\u03c5 \u03c4\u03bf Vuze \u03b8\u03b1 \u03be\u03b5\u03ba\u03b9\u03bd\u03ae\u03c3\u03b5\u03b9; exportTorrentWizard.title=\u0395\u03be\u03b1\u03b3\u03c9\u03b3\u03ae torrent exportTorrentWizard.torrentfile.title=\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae Torrent exportTorrentWizard.torrentfile.message=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf torrent \u03c0\u03bf\u03c5 \u03b8\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b5\u03be\u03ac\u03b3\u03b5\u03c4\u03b5 exportTorrentWizard.torrentfile.path=\u0394\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae exportTorrentWizard.torrentfile.browse=\u0391\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7 exportTorrentWizard.torrentfile.invalidPath=\u039c\u03b7 \u03ad\u03b3\u03b3\u03c5\u03c1\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf torrent exportTorrentWizard.exportfile.title=\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u0391\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \u0395\u03be\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2 exportTorrentWizard.exportfile.message=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c3\u03c4\u03bf \u03bf\u03c0\u03bf\u03af\u03bf \u03b8\u03b1 \u03b3\u03af\u03bd\u03b5\u03b9 \u03b5\u03be\u03b1\u03b3\u03c9\u03b3\u03ae exportTorrentWizard.exportfile.path=\u0394\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae exportTorrentWizard.exportfile.browse=\u0391\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7 exportTorrentWizard.exportfile.invalidPath=\u039c\u03b7 \u03ad\u03b3\u03b3\u03c5\u03c1\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b5\u03be\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2 exportTorrentWizard.finish.title=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 exportTorrentWizard.finish.message=\u0397 \u03b5\u03be\u03b1\u03b3\u03c9\u03b3\u03ae \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 \u03b5\u03c0\u03b9\u03c4\u03c5\u03c7\u03ce\u03c2 exportTorrentWizard.process.inputfilebad.title=\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf Torrent \u03b4\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03ad\u03b3\u03b3\u03c5\u03c1\u03bf exportTorrentWizard.process.inputfilebad.message=\u0388\u03bd\u03b1 \u03c3\u03c6\u03ac\u03bb\u03bc\u03b1 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03b8\u03b7\u03ba\u03b5 \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03c3\u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b1\u03bd\u03ac\u03b3\u03bd\u03c9\u03c3\u03b7\u03c2: exportTorrentWizard.process.outputfileexists.title=\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 exportTorrentWizard.process.outputfileexists.message=\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b5\u03b3\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 - \u03b1\u03bd\u03c4\u03b9\u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7; exportTorrentWizard.process.torrentfail.title=\u0397 \u03b1\u03bd\u03ac\u03b3\u03bd\u03c9\u03c3\u03b7 \u03c4\u03bf\u03c5 Torrent \u03b1\u03c0\u03ad\u03c4\u03c5\u03c7\u03b5 exportTorrentWizard.process.exportfail.title=\u0397 \u03b5\u03be\u03b1\u03b3\u03c9\u03b3\u03ae \u03c4\u03bf\u03c5 Torrent \u03b1\u03c0\u03ad\u03c4\u03c5\u03c7\u03b5 exportTorrentWizard.process.unknownfail.title=\u039c\u03b7 \u03b1\u03bd\u03b1\u03bc\u03b5\u03bd\u03cc\u03bc\u03b5\u03bd\u03bf \u03c3\u03c6\u03ac\u03bb\u03bc\u03b1 importTorrentWizard.title=\u0395\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae torrent importTorrentWizard.torrentfile.title=\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae torrent importTorrentWizard.torrentfile.message=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf torrent \u03c3\u03c4\u03bf \u03bf\u03c0\u03bf\u03af\u03bf \u03b8\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b3\u03af\u03bd\u03b5\u03b9 \u03b5\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae importTorrentWizard.torrentfile.path=\u0394\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae importTorrentWizard.torrentfile.browse=\u0391\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7 importTorrentWizard.torrentfile.invalidPath=\u039c\u03b7 \u03ad\u03b3\u03b3\u03c5\u03c1\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf torrent importTorrentWizard.importfile.title=\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u0391\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \u0395\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2 importTorrentWizard.importfile.message=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c0\u03c1\u03bf\u03c2 \u03b5\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae importTorrentWizard.importfile.path=\u0394\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae importTorrentWizard.importfile.browse=\u0391\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7 importTorrentWizard.importfile.invalidPath=\u039c\u03b7 \u03ad\u03b3\u03b3\u03c5\u03c1\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b5\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2 importTorrentWizard.finish.title=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 importTorrentWizard.finish.message=\u0397 \u03b5\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 \u03b5\u03c0\u03b9\u03c4\u03c5\u03c7\u03ce\u03c2 importTorrentWizard.process.inputfilebad.title=\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b5\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2 \u03b4\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03ad\u03b3\u03b3\u03c5\u03c1\u03bf importTorrentWizard.process.inputfilebad.message=\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03b8\u03b7\u03ba\u03b5 \u03ad\u03bd\u03b1 \u03c3\u03c6\u03ac\u03bb\u03bc\u03b1 \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03b1\u03bd\u03ac\u03b3\u03bd\u03c9\u03c3\u03b7 \u03c4\u03bf\u03c5 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \u03b1\u03bd\u03ac\u03b3\u03bd\u03c9\u03c3\u03b7\u03c2: importTorrentWizard.process.outputfileexists.title=\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 importTorrentWizard.process.outputfileexists.message=\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c0\u03c1\u03bf\u03c2 \u03b5\u03b3\u03b3\u03c1\u03b1\u03c6\u03ae \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 - \u03b1\u03bd\u03c4\u03b9\u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7? importTorrentWizard.process.torrentfail.title=\u0397 \u03b5\u03b3\u03b3\u03c1\u03b1\u03c6\u03ae Torrent \u03b1\u03c0\u03ad\u03c4\u03c5\u03c7\u03b5 importTorrentWizard.process.importfail.title=\u0397 \u03b5\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae Torrent \u03b1\u03c0\u03ad\u03c4\u03c5\u03c7\u03b5 importTorrentWizard.process.unknownfail.title=\u039c\u03b7 \u03b1\u03bd\u03b1\u03bc\u03b5\u03bd\u03cc\u03bc\u03b5\u03bd\u03bf \u03c3\u03c6\u03ac\u03bb\u03bc\u03b1 ConfigView.label.bindip=\u03a3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7 \u03bc\u03b5 \u03c4\u03bf\u03c0\u03b9\u03ba\u03ae \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 IP or interface ConfigView.label.zeronewfiles=\u0394\u03ad\u03c3\u03bc\u03b5\u03c5\u03c3\u03b7 \u03c7\u03c9\u03c1\u03bf\u03c5 \u03ba\u03b1\u03b9 \u03bc\u03b7\u03b4\u03b5\u03bd\u03b9\u03c3\u03bc\u03cc\u03c2 \u03bd\u03ad\u03c9\u03bd \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 ConfigView.label.zeronewfiles.tooltip=\u0395\u03bb\u03b1\u03c7\u03b9\u03c3\u03c4\u03bf\u03c0\u03bf\u03b9\u03b5\u03af \u03c4\u03bf\u03bd \u03ba\u03b1\u03c4\u03b1\u03ba\u03b5\u03c1\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd ConfigView.section.stats=\u03a3\u03c4\u03b1\u03c4\u03b9\u03c3\u03c4\u03b9\u03ba\u03ac ConfigView.section.stats.enable=\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 ConfigView.section.stats.defaultsavepath=\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2 \u03b1\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7\u03c2 \u03c3\u03c4\u03b1\u03c4\u03b9\u03c3\u03c4\u03b9\u03ba\u03ce\u03bd ConfigView.section.stats.choosedefaultsavepath=\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03b1\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7\u03c2 \u03c3\u03c4\u03b1\u03c4\u03b9\u03c3\u03c4\u03b9\u03ba\u03ce\u03bd ConfigView.section.stats.savefreq=\u03a3\u03c5\u03c7\u03bd\u03cc\u03c4\u03b7\u03c4\u03b1 \u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7\u03c2 ConfigView.section.stats.minutes=\u03bb\u03b5\u03c0\u03c4\u03ac ConfigView.section.stats.hours=\u03ce\u03c1\u03b5\u03c2 ConfigView.section.stats.seconds=\u03b4\u03b5\u03cd\u03c4\u03b5\u03c1\u03b1 ConfigView.section.stats.savefile=\u038c\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \u03c3\u03c4\u03b1\u03c4\u03b9\u03c3\u03c4\u03b9\u03ba\u03ce\u03bd MyTorrentsView.menu.export=\u0395&\u03be\u03b1\u03b3\u03c9\u03b3\u03ae... MyTorrentsView.menu.host=\u0395&\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae... ManagerItem.finishing=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03bd\u03b5\u03c4\u03b1\u03b9 ConfigView.dialog.choosedefaulttorrentpath=\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf\u03bd \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03b5\u03b3\u03bc\u03ad\u03bd\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf torrent ConfigView.dialog.choosemovepath=\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03c3\u03c4\u03bf\u03bd \u03bf\u03c0\u03bf\u03af\u03bf \u03b8\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03bc\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ac ConfigView.label.movecompleted=\u039c\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ac \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03c9\u03bc\u03ad\u03bd\u03c9\u03bd \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd ConfigView.label.savetorrents=\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd .torrent MainWindow.menu.view.mytracker=\u039f\u03b9 &\u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b5\u03c2 \u03bc\u03bf\u03c5 MyTrackerView.title.full=\u039f\u03b9 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b5\u03c2 \u03bc\u03bf\u03c5 MyTrackerView.name=\u038c\u03bd\u03bf\u03bc\u03b1 MyTrackerView.tracker=\u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7\u03c2 MyTrackerView.status=\u039a\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7 MyTrackerView.status.started=\u039b\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03b5\u03af MyTrackerView.status.stopped=\u0388\u03c7\u03b5\u03b9 \u03a3\u03c4\u03b1\u03bc\u03b1\u03c4\u03ae\u03c3\u03b5\u03b9 MyTrackerView.peers=\u039f\u03bc\u03bf\u03c4\u03b9\u03bc\u03bf\u03b9 MyTrackerView.seeds=\u0393\u03bf\u03bd\u03bf\u03b9 MyTrackerView.announces=\u0391\u03bd\u03b1\u03ba\u03bf\u03b9\u03bd\u03ce\u03c3\u03b5\u03b9\u03c2 MyTrackerView.uploaded=\u0395\u03c7\u03bf\u03c5\u03bd \u03c3\u03c4\u03b1\u03bb\u03b5\u03b9 MyTrackerView.downloaded=\u039b\u03ae\u03c8\u03b5\u03b9\u03c2 MyTrackerView.left=\u0391\u03c0\u03bf\u03bc\u03ad\u03bd\u03bf\u03c5\u03bd ConfigView.section.style=\u03a0\u03b5\u03c1\u03b9\u03b2\u03ac\u03bb\u03bb\u03bf\u03bd ConfigView.section.style.useCustomTabs=\u03a7\u03c1\u03ae\u03c3\u03b7 \u03ba\u03b1\u03c1\u03c4\u03ad\u03bb\u03c9\u03bd \u03bc\u03b5 \u03b4\u03c5\u03bd\u03b1\u03c4\u03cc\u03c4\u03b7\u03c4\u03b1 \u03ba\u03bb\u03b5\u03b9\u03c3\u03af\u03bc\u03b1\u03c4\u03bf\u03c2 (\u03c7\u03c1\u03b5\u03b9\u03ac\u03b6\u03b5\u03c4\u03b1\u03b9 \u03b5\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7) MainWindow.menu.view.plugins=&\u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03b1 fileDownloadWindow.saveTorrentIn=\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c4\u03bf\u03c5 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 Torrent \u03c3\u03b5 fileDownloadWindow.title=Vuze - \u039b\u03ae\u03c8\u03b7 Torrent fileDownloadWindow.downloading=\u039b\u03ae\u03c8\u03b7 \u03b1\u03c0\u03cc : fileDownloadWindow.status=\u039a\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7 : fileDownloadWindow.state_initializing=\u0391\u03c1\u03c7\u03b9\u03ba\u03bf\u03c0\u03bf\u03b9\u03b7\u03c3\u03b7 fileDownloadWindow.state_downloading=\u039b\u03ae\u03c8\u03b7 fileDownloadWindow.state_error=\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1 : MainWindow.menu.file.open.url=&\u0394\u03b9\u03b5\u03c5\u03b8\u03c5\u03bd\u03c3\u03b7 openUrl.title=Vuze - \u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 Url openUrl.url=URL : MyTorrentsView.menu.host.error.title=\u0397 \u03c6\u03b9\u03bb\u03bf\u03be\u03b5\u03bd\u03af\u03b1 Torrent \u03b1\u03c0\u03ad\u03c4\u03c5\u03c7\u03b5 MyTorrentsView.menu.host.error.message=\u03a4\u03bf \u03b1\u03ba\u03cc\u03bb\u03bf\u03c5\u03b8\u03bf \u03c3\u03c6\u03ac\u03bb\u03bc\u03b1 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03b8\u03b7\u03ba\u03b5 \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7 \u03c6\u03b9\u03bb\u03bf\u03be\u03b5\u03bd\u03af\u03b1 \u03c4\u03bf\u03c5 torrent ConfigView.section.tracker=\u03a0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03cd\u03b8\u03b7\u03c3\u03b7 \u0391\u03bb\u03bb\u03b1\u03b3\u03ce\u03bd ConfigView.section.tracker.pollinterval=\u03a7\u03c1\u03cc\u03bd\u03bf\u03c2 \u03b1\u03bd\u03b1\u03bd\u03ad\u03c9\u03c3\u03b7\u03c2 \u03c0\u03b5\u03bb\u03ac\u03c4\u03b7 \u03c0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03cd\u03b8\u03b7\u03c3\u03b7\u03c2 \u03b1\u03bb\u03bb\u03b1\u03b3\u03ce\u03bd (\u03b4\u03b5\u03c5\u03c4\u03b5\u03c1\u03cc\u03bb\u03b5\u03c0\u03c4\u03b1) ConfigView.section.tracker.publishenable=\u0394\u03b7\u03bc\u03bf\u03c3\u03af\u03b5\u03c5\u03c3\u03b7 \u03bb\u03b5\u03c0\u03c4\u03bf\u03bc\u03b5\u03c1\u03b9\u03ce\u03bd torrent \u03c3\u03c4\u03bf "" ConfigView.section.tracker.ip=\u03a0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03cd\u03b8\u03b7\u03c3\u03b7 \u0391\u03bb\u03bb\u03b1\u03b3\u03ce\u03bd: \u0391\u03c0\u03bf\u03bc\u03b1\u03ba\u03c1\u03c5\u03c3\u03bc\u03ad\u03bd\u03b7 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 IP ConfigView.section.style.enableXPStyle=\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03c3\u03c4\u03c5\u03bb XP (\u03c7\u03c1\u03b5\u03b9\u03ac\u03b6\u03b5\u03c4\u03b1\u03b9 \u03b5\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7) IPChecker.external.service.dyndns.name=DynDNS IPChecker.external.service.dyndns.url=http://www.dyndns.org/ IPChecker.external.service.dyndns.description=\u03a5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b5\u03c2 \u03b4\u03c5\u03bd\u03b1\u03bc\u03b9\u03ba\u03bf\u03cd DNS, LLC ConfigView.section.tracker.checkip=\u0388\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u0394\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7\u03c2... ipCheckerWizard.title=\u039f\u03b4\u03b7\u03b3\u03cc\u03c2 \u0395\u03bb\u03ad\u03b3\u03c7\u03bf\u03c5 IP ipCheckerWizard.service=\u03a5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 ipCheckerWizard.chooseService=\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03bc\u03af\u03b1 \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 \u03b5\u03bb\u03ad\u03b3\u03c7\u03bf\u03c5 IP \u03b1\u03c0\u03cc \u03c4\u03b9\u03c2 \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b5\u03c2 \u03c3\u03c4\u03b7 \u03bb\u03af\u03c3\u03c4\u03b1 ipCheckerWizard.explanations=\u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03b1\u03c5\u03c4\u03cc\u03bd \u03c4\u03bf\u03bd \u03bf\u03b4\u03b7\u03b3\u03cc \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b2\u03c1\u03b5\u03af\u03c4\u03b5 \u03c4\u03b7\u03bd \u03b5\u03be\u03c9\u03c4\u03b5\u03c1\u03b9\u03ba\u03ae \u03c3\u03b1\u03c2 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 IP. \u0391\u03bd \u03b7 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 IP \u03c3\u03b1\u03c2 \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03bc\u03b9\u03ba\u03ae, \u03c3\u03b1\u03c2 \u03c0\u03c1\u03bf\u03c4\u03af\u03bd\u03bf\u03c5\u03bc\u03b5 \u03bd\u03b1 \u03b1\u03bd\u03bf\u03af\u03be\u03b5\u03c4\u03b5 \u03ad\u03bd\u03b1 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03cc \u03bc\u03b5 \u03bc\u03af\u03b1 \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 \u03b4\u03c5\u03bd\u03b1\u03bc\u03b9\u03ba\u03bf\u03cd DNS. \u039a\u03ac\u03c0\u03bf\u03b9\u03b5\u03c2 \u03c4\u03ad\u03c4\u03bf\u03b9\u03b5\u03c2 \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b5\u03c2 \u03b5\u03bc\u03c6\u03b1\u03bd\u03af\u03b6\u03bf\u03bd\u03c4\u03b1\u03b9 \u03c0\u03b1\u03c1\u03b1\u03ba\u03ac\u03c4\u03c9, \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03c4\u03b5 \u03c4\u03bf\u03c5\u03c2 \u03c5\u03c0\u03b5\u03c1\u03c3\u03c5\u03bd\u03b4\u03ad\u03c3\u03bc\u03bf\u03c5\u03c2 \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03c3\u03b5\u03c4\u03b5 \u03ad\u03bd\u03b1 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03cc (\u03cc\u03c0\u03bf\u03c5 \u03b1\u03c5\u03c4\u03cc \u03c5\u03c0\u03bf\u03c3\u03c4\u03b7\u03c1\u03af\u03b6\u03b5\u03c4\u03b1\u03b9). \u0388\u03c0\u03b5\u03b9\u03c4\u03b1, \u03c3\u03c5\u03bc\u03c0\u03bb\u03b7\u03c1\u03ce\u03c3\u03c4\u03b5 \u03c4\u03bf \u03c0\u03b5\u03b4\u03af\u03bf \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 IP \u03bc\u03b5 \u03c4\u03bf \u03b4\u03c5\u03bd\u03b1\u03bc\u03b9\u03ba\u03cc \u03c3\u03b1\u03c2 \u03cc\u03bd\u03bf\u03bc\u03b1 \u03c0\u03b5\u03bb\u03ac\u03c4\u03b7 (\u03b3\u03b9\u03b1 \u03c0\u03b1\u03c1\u03ac\u03b4\u03b5\u03b9\u03b3\u03bc\u03b1 myhostname.dyndns.org). \u0398\u03b1 \u03c7\u03c1\u03b5\u03b9\u03b1\u03c3\u03c4\u03b5\u03af\u03c4\u03b5 \u03ad\u03bd\u03b1 \u03c0\u03c1\u03cc\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1 \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b5\u03bd\u03b7\u03bc\u03b5\u03c1\u03ce\u03bd\u03b5\u03c4\u03b5 \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b1 \u03c4\u03b7\u03bd \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 \u03b4\u03c5\u03bd\u03b1\u03bc\u03b9\u03ba\u03bf\u03cd DNS \u03bc\u03b5 \u03c4\u03b7\u03bd IP \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03ae \u03c3\u03b1\u03c2. \u039c\u03b5 \u03b1\u03c5\u03c4\u03cc\u03bd \u03c4\u03bf\u03bd \u03c4\u03c1\u03cc\u03c0\u03bf, \u03b8\u03b1 \u03bc\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03c6\u03b9\u03bb\u03bf\u03be\u03b5\u03bd\u03b5\u03af\u03c4\u03b5 torrents, \u03b1\u03ba\u03cc\u03bc\u03b7 \u03ba\u03b1\u03b9 \u03b1\u03bd \u03c4\u03bf IP \u03c3\u03b1\u03c2 \u03b1\u03bb\u03bb\u03ac\u03be\u03b5\u03b9. ipCheckerWizard.service.description=\u03a0\u03b5\u03c1\u03b9\u03b3\u03c1\u03b1\u03c6\u03ae : ipCheckerWizard.service.url=\u0394\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 : ipCheckerWizard.progresstitle=\u0388\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 IP ipCheckerWizard.checkComplete=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 IP : ipCheckerWizard.checkFailed=\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1, \u03b1\u03b9\u03c4\u03af\u03b1 : wizard.tracker.local=\u03a7\u03c1\u03ae\u03c3\u03b7 \u03c4\u03bf\u03c5 \u03b5\u03bd\u03c3\u03c9\u03bc\u03b1\u03c4\u03c9\u03bc\u03ad\u03bd\u03bf\u03c5 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 \u03c4\u03bf\u03c5 Vuze wizard.tracker.external=\u03a7\u03c1\u03ae\u03c3\u03b7 \u03b5\u03be\u03c9\u03c4\u03b5\u03c1\u03b9\u03ba\u03bf\u03cd \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 wizard.tracker.howToLocal=\t\u039c\u03b5\u03c4\u03b1\u03b2\u03b5\u03af\u03c4\u03b5 \u03c3\u03c4\u03bf '\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ad\u03c2>\u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7\u03c2' \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03c4\u03bf \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 wizard.announceUrl=\u0394\u03b9\u03b5\u03c5\u03b8\u03c5\u03bd\u03c3\u03b7 \u0391\u03bd\u03b1\u03ba\u03bf\u03b9\u03bd\u03ce\u03c3\u03b5\u03c9\u03bd : IPChecker.external.service.discoveryvip.name=Discoveryvip IPChecker.external.service.discoveryvip.url=http://ip.discoveryvip.com/ IPChecker.external.service.discoveryvip.description=Discoveryvip - \u0388\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03bc\u03cc\u03bd\u03bf \u03c4\u03b7\u03c2 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7\u03c2 IP IPChecker.external.httpinvalidresponse=\u039c\u03b7 \u03ad\u03b3\u03ba\u03c5\u03c1\u03b7 \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03b7 HTTP IPChecker.external.loadingwebpage=\u03a6\u03cc\u03c1\u03c4\u03c9\u03c3\u03b7 \u0399\u03c3\u03c4\u03bf\u03c3\u03b5\u03bb\u03af\u03b4\u03b1\u03c2 IPChecker.external.analysingresponse=\u0393\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03b1\u03bd\u03ac\u03bb\u03c5\u03c3\u03b7\u03c2 \u03c4\u03b7\u03c2 \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03b7\u03c2 IPChecker.external.addressextracted=\u0397 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 IP \u03b2\u03c1\u03ad\u03b8\u03b7\u03ba\u03b5 IPChecker.external.httploadfail=\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03c6\u03cc\u03c1\u03c4\u03c9\u03c3\u03b7\u03c2 \u03c3\u03b5\u03bb\u03af\u03b4\u03b1\u03c2 IPChecker.external.timeout=\u039f \u03bc\u03ad\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 \u03c7\u03c1\u03cc\u03bd\u03bf\u03c2 \u03b5\u03be\u03b1\u03bd\u03c4\u03bb\u03ae\u03b8\u03b7\u03ba\u03b5 IPChecker.external.ipnotfound=\u0397 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 IP \u03b4\u03b5\u03bd \u03b2\u03c1\u03ad\u03b8\u03b7\u03ba\u03b5 ConfigView.section.tracker.pollintervalmin=\u0395\u03bb\u03ac\u03c7\u03b9\u03c3\u03c4\u03bf ConfigView.section.tracker.pollintervalmax=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03bf ConfigView.section.tracker.pollintervalincby=\u0391\u03cd\u03be\u03b7\u03c3\u03b7 \u03ba\u03b1\u03c4\u03ac ConfigView.section.tracker.pollintervalincper=\u039a\u03ac\u03b8\u03b5 'n' \u03c0\u03b5\u03bb\u03ac\u03c4\u03b5\u03c2 splash.loadingImages=\u03a6\u03cc\u03c1\u03c4\u03c9\u03c3\u03b7 \u0395\u03b9\u03ba\u03cc\u03bd\u03c9\u03bd splash.initializeGui=\u0391\u03c1\u03c7\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u039a\u03c5\u03c1\u03af\u03bf\u03c5 \u03a0\u03b1\u03c1\u03b1\u03b8\u03cd\u03c1\u03bf\u03c5 splash.openViews=\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03a0\u03c1\u03bf\u03b2\u03bf\u03bb\u03ce\u03bd splash.plugin=\u03a6\u03cc\u03c1\u03c4\u03c9\u03c3\u03b7 \u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03bf\u03c5 : configureWizard.nat.tooManyPorts=\u03a5\u03c0\u03b5\u03c1\u03b2\u03bf\u03bb\u03b9\u03ba\u03ad\u03c2 \u03b8\u03cd\u03c1\u03b5\u03c2 \u03c0\u03c1\u03bf\u03c2 \u03b4\u03bf\u03ba\u03b9\u03bc\u03ae (\u03bc\u03ad\u03b3\u03b9\u03c3\u03c4\u03bf 9) MyTorrentsView.menu.publish=&\u0394\u03b7\u03bc\u03bf\u03c3\u03af\u03b5\u03c5\u03c3\u03b7... MyTrackerView.status.published=\u0394\u03b7\u03bc\u03bf\u03c3\u03b9\u03b5\u03cd\u03c4\u03b7\u03ba\u03b5 MyTrackerView.completed=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 MainWindow.menu.file.open.torrentnodefault=\u0391\u03c1\u03c7\u03b5\u03af\u03bf .torrent (\u03a7\u03c9\u03c1\u03af\u03c2 \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03b5\u03b3\u03bc\u03ad\u03bd\u03b7 \u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7) wizard.comment=\u03a3\u03c7\u03cc\u03bb\u03b9\u03bf ConfigView.label.movetorrent=\u039c\u03b5\u03c4\u03b1\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 .torrent ConfigView.section.file.decoder.label=\u03a0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03b5\u03b3\u03bc\u03ad\u03bd\u03b7 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 torrent \u03cc\u03c4\u03b1\u03bd \u03b1\u03c0\u03b1\u03b9\u03c4\u03b5\u03af\u03c4\u03b1\u03b9 \u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae ConfigView.section.file.decoder.nodecoder=\u039a\u03b1\u03bd\u03ad\u03bd\u03b1 IPChecker.external.service.no-ip.name=No-IP IPChecker.external.service.no-ip.url=http://www.no-ip.com/ IPChecker.external.service.no-ip.description=\u03a5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 \u0394\u03c5\u03bd\u03b1\u03bc\u03b9\u03ba\u03bf\u03cd \u03ba\u03b1\u03b9 \u03a3\u03c4\u03b1\u03c4\u03b9\u03ba\u03bf\u03cd DNS\n(\u03b4\u03b5\u03bd \u03c0\u03c1\u03bf\u03c3\u03c6\u03ad\u03c1\u03b5\u03c4\u03b1\u03b9 \u03b4\u03c9\u03c1\u03b5\u03ac\u03bd \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 '\u03b5\u03bb\u03ad\u03b3\u03c7\u03bf\u03c5 \u03b4\u03b9\u03ad\u03c5\u03b8\u03c5\u03bd\u03c3\u03b7\u03c2') ConfigView.section.tracker.publicenable=\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03b5\u03be\u03c9\u03c4\u03b5\u03c1\u03b9\u03ba\u03ce\u03bd torrents # # Tooltips # GeneralView.label.status.pieces_available.tooltip=\u0395\u03bc\u03c6\u03b1\u03bd\u03af\u03b6\u03b5\u03b9 \u03c4\u03bf\u03bd \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc \u03c5\u03c0\u03ac\u03c1\u03c7\u03bf\u03bd\u03c4\u03c9\u03bd \u03b1\u03bd\u03c4\u03b9\u03b3\u03c1\u03ac\u03c6\u03c9\u03bd \u03ba\u03ac\u03b8\u03b5 \u03ba\u03bf\u03bc\u03bc\u03b1\u03c4\u03b9\u03bf\u03cd.\n\u0391\u03bd \u03c4\u03c5\u03c7\u03cc\u03bd \u03bf \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc\u03c2 \u03c3\u03c4\u03b1 \u03b1\u03c1\u03b9\u03c3\u03c4\u03b5\u03c1\u03ac \u03b5\u03af\u03bd\u03b1\u03b9 \u03bc\u03b9\u03ba\u03c1\u03cc\u03c4\u03b5\u03c1\u03bf\u03c2 \u03c4\u03bf\u03c5 1, \u03b4\u03b5\u03bd \u03ad\u03c7\u03b5\u03c4\u03b5 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03c3\u03b5 \u03ad\u03bd\u03b1 \u03bf\u03bb\u03cc\u03ba\u03bb\u03b7\u03c1\u03c9\u03bc\u03ad\u03bd\u03bf \u03b1\u03bd\u03c4\u03af\u03b3\u03c1\u03b1\u03c6\u03bf \u03c4\u03bf\u03c5 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 (\u03ba\u03b1\u03b9 \u03af\u03c3\u03c9\u03c2 \u03ad\u03c7\u03b5\u03c4\u03b5 \u03c0\u03c1\u03bf\u03b2\u03bb\u03ae\u03bc\u03b1\u03c4\u03b1 \u03bd\u03b1 \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03c3\u03b5\u03c4\u03b1\u03b9 \u03c4\u03b7 \u03bb\u03ae\u03c8\u03b7). GeneralView.label.trackerurl.tooltip=\u039a\u03ac\u03bd\u03c4\u03b5 \u03ba\u03bb\u03b9\u03ba \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b1\u03bd\u03c4\u03b9\u03b3\u03c1\u03ac\u03c8\u03b5\u03c4\u03b5 \u03c4\u03bf URL \u03b1\u03bd\u03b1\u03ba\u03bf\u03b9\u03bd\u03ce\u03c3\u03b5\u03c9\u03bd \u03c3\u03c4\u03bf \u03c0\u03c1\u03cc\u03c7\u03b5\u03b9\u03c1\u03bf GeneralView.label.trackerurlopen.tooltip=\u039a\u03ac\u03bd\u03c4\u03b5 \u03ba\u03bb\u03b9\u03ba \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b1\u03bd\u03bf\u03af\u03be\u03b5\u03c4\u03b5 \u03c4\u03b7\u03bd \u03ba\u03b5\u03bd\u03c4\u03c1\u03b9\u03ba\u03ae \u03c3\u03b5\u03bb\u03af\u03b4\u03b1 \u03a0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03cd\u03b8\u03b7\u03c3\u03b7\u03c2 \u0391\u03bb\u03bb\u03b1\u03b3\u03ce\u03bd # # 2.0.4.4 # ConfigView.section.style.guiUpdate=\u0391\u03bd\u03b1\u03bd\u03ad\u03c9\u03c3\u03b7 \u03c4\u03bf\u03c5 GUI \u03ba\u03b1\u03b8\u03b5 ConfigView.section.style.graphicsUpdate=\u0391\u03bd\u03b1\u03bd\u03ad\u03c9\u03c3\u03b7 \u0393\u03c1\u03b1\u03c6\u03b9\u03ba\u03ce\u03bd \u03c1\u03ac\u03b2\u03b4\u03c9\u03bd \u03ba\u03ac\u03b8\u03b5 N \u03b1\u03bd\u03b1\u03bd\u03b5\u03ce\u03c3\u03b5\u03b9\u03c2 GUI ConfigView.section.style.reOrderDelay=\u0391\u03bd\u03b1\u03ba\u03b1\u03c4\u03ac\u03c4\u03b1\u03be\u03b7 \u03c0\u03b9\u03bd\u03ac\u03ba\u03c9\u03bd \u03ba\u03ac\u03b8\u03b5 N \u03b1\u03bd\u03b1\u03bd\u03b5\u03ce\u03c3\u03b5\u03b9\u03c2 GUI ConfigView.section.style.reOrderDelay.never=\u03a0\u03bf\u03c4\u03ad ConfigView.section.logging=\u039a\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae ConfigView.section.logging.enable=\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2 \u03c3\u03b5 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf ConfigView.section.logging.logdir=\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2 ConfigView.section.logging.choosedefaultsavepath=\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03b1\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7\u03c2 GeneralView.label.updatein.querying=\u03b5\u03c1\u03ce\u03c4\u03b7\u03bc\u03b1... configureWizard.nat.sharePort=\u03a7\u03c1\u03ae\u03c3\u03b7 \u03bc\u03af\u03b1\u03c2 \u03ba\u03bf\u03b9\u03bd\u03ae\u03c2 \u03b8\u03cd\u03c1\u03b1\u03c2 \u03b5\u03b9\u03c3\u03b5\u03c1\u03c7\u03cc\u03bc\u03b5\u03bd\u03c9\u03bd \u03b1\u03b9\u03c4\u03ae\u03c3\u03b5\u03c9\u03bd \u03b3\u03b9\u03b1 \u03cc\u03bb\u03b1 \u03c4\u03b1 torrents ConfigView.section.logging.maxsize=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03bf \u03bc\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2 ConfigView.section.tracker.passwordenableweb=\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03cd \u03c3\u03c4\u03b9\u03c2 \u03b9\u03c3\u03c4\u03bf\u03c3\u03b5\u03bb\u03af\u03b4\u03b5\u03c2 \u039a\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2 \u0391\u03bb\u03bb\u03b1\u03b3\u03ce\u03bd ConfigView.section.tracker.passwordenabletorrent=\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03cd \u03c3\u03c4\u03b1 torrents ConfigView.section.tracker.username=\u038c\u03bd\u03bf\u03bc\u03b1 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7 ConfigView.section.tracker.password=\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 columnChooser.title=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03b9\u03c2 \u03c3\u03c4\u03ae\u03bb\u03b5\u03c2 \u03c0\u03c1\u03bf\u03c2 \u03b5\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 columnChooser.move=\u03a3\u03cd\u03c1\u03b5\u03c4\u03b5 \u03c4\u03b9\u03c2 \u03b3\u03c1\u03b1\u03bc\u03bc\u03ad\u03c2 \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03c4\u03b9\u03c2 \u03b1\u03bd\u03b1\u03ba\u03b1\u03c4\u03b1\u03c4\u03ac\u03be\u03b5\u03c4\u03b5 columnChooser.apply=\u0395\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae columnChooser.columnname=\u038c\u03bd\u03bf\u03bc\u03b1 \u03c3\u03c4\u03ae\u03bb\u03b7\u03c2 columnChooser.columndescription=\u03a0\u03b5\u03c1\u03b9\u03b3\u03c1\u03b1\u03c6\u03ae TableColumn.header.shareRatio=\u0391\u03bd\u03b1\u03bb\u03bf\u03b3\u03af\u03b1 \u03a3\u03c5\u03bc\u03bc\u03b5\u03c4\u03bf\u03c7\u03ae\u03c2 MyTorrentsView.menu.editTableColumns=\u03a1\u03cd\u03b8\u03bc\u03b9\u03c3\u03b7 &\u03a3\u03c4\u03ae\u03bb\u03b7\u03c2 wizard.operationfailed=\u0397 \u03bb\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03b1\u03c0\u03ad\u03c4\u03c5\u03c7\u03b5 authenticator.title=\u0391\u03c0\u03b1\u03b9\u03c4\u03b5\u03af\u03c4\u03b1\u03b9 \u03a0\u03b9\u03c3\u03c4\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 authenticator.realm=\u03a0\u03b5\u03c1\u03b9\u03bf\u03c7\u03ae authenticator.tracker=\u0399\u03c7\u03bd\u03b7\u03bb\u03ac\u03c4\u03b7\u03c2 authenticator.user=\u038c\u03bd\u03bf\u03bc\u03b1 \u03a7\u03c1\u03ae\u03c3\u03c4\u03b7 authenticator.password=\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 ConfigView.label.allowSendVersion=\u039d\u03b1 \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03b5\u03c4\u03b1\u03b9 \u03c3\u03c4\u03bf Vuze \u03bd\u03b1 \u03c3\u03c4\u03ad\u03bb\u03bd\u03b5\u03b9 \u03b1\u03bd\u03ce\u03bd\u03c5\u03bc\u03b5\u03c2 \u03c0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7 \u03ba\u03b1\u03b9 \u03ad\u03bd\u03b1 \u03c4\u03c5\u03c7\u03b1\u03af\u03bf \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc \u03cc\u03c4\u03b1\u03bd \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03ad\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03bd\u03ad\u03c9\u03bd \u03b5\u03ba\u03b4\u03cc\u03c3\u03b5\u03c9\u03bd wizard.hint.mode=\u03a3\u03c5\u03bc\u03b2\u03bf\u03c5\u03bb\u03ae:\t\u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03c3\u03cd\u03c1\u03b5\u03c4\u03b5 \u03ad\u03bd\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03ae \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03c3\u03b5 \u03b1\u03c5\u03c4\u03cc\u03bd \u03c4\u03bf\u03bd \u03bf\u03b4\u03b7\u03b3\u03cc\n\t\u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03b5\u03c4\u03b5 \u03ad\u03bd\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03ae \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf wizard.hint.file=\u03a3\u03c5\u03bc\u03b2\u03bf\u03c5\u03bb\u03ae:\t\u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03b5\u03c4\u03b5 \u03ad\u03bd\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c3\u03ad\u03c1\u03bd\u03bf\u03bd\u03c4\u03ac\u03c2 \u03c4\u03bf wizard.hint.directory=Hint:\t\u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03b5\u03c4\u03b5 \u03ad\u03bd\u03b1 \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03c3\u03ad\u03c1\u03bd\u03bf\u03bd\u03c4\u03ac\u03c2 \u03c4\u03bf\u03bd MainWindow.menu.help.checkupdate=&\u0388\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03b3\u03b9\u03b1 \u03b5\u03bd\u03b7\u03bc\u03b5\u03c1\u03ce\u03c3\u03b5\u03b9\u03c2 \u03c4\u03bf\u03c5 \u03a0\u03c1\u03bf\u03b3\u03c1\u03ac\u03bc\u03bc\u03b1\u03c4\u03bf\u03c2 TableColumn.header.down=\u0388\u03c7\u03bf\u03c5\u03bd \u03bb\u03b7\u03c6\u03b8\u03b5\u03af TableColumn.header.up=\u0395\u03c7\u03bf\u03c5\u03bd \u03b1\u03c0\u03bf\u03c3\u03c4\u03b1\u03bb\u03b5\u03af ConfigView.section.tracker.passwordenabletorrent.info=\u0391\u03c0\u03b1\u03b9\u03c4\u03b5\u03af\u03c4\u03b1\u03b9 \u03ad\u03bd\u03b1 \u03c3\u03c5\u03bc\u03b2\u03b1\u03c4\u03cc \u03c0\u03c1\u03cc\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1 \u03c0\u03b5\u03bb\u03ac\u03c4\u03b7 BitTorrent (\u03c0.\u03c7. Vuze ConfigView.section.style.confirmationOnExit=\u03a0\u03c1\u03bf\u03c4\u03c1\u03bf\u03c0\u03ae \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03ad\u03be\u03bf\u03b4\u03bf MainWindow.dialog.exitconfirmation.title=\u0388\u03be\u03bf\u03b4\u03bf\u03c2 \u03b1\u03c0\u03cc \u03c4\u03bf Vuze MainWindow.dialog.exitconfirmation.text=\u0398\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bf\u03c0\u03c9\u03c3\u03b4\u03ae\u03c0\u03bf\u03c4\u03b5 \u03bd\u03b1 \u03b2\u03b3\u03b5\u03af\u03c4\u03b5 \u03b1\u03c0\u03cc \u03c4\u03bf Vuze SystemTray.menu.stopalltransfers=\u0394\u03b9\u03b1\u03ba\u03bf&\u03c0\u03ae \u038c\u03bb\u03c9\u03bd \u03c4\u03c9\u03bd \u039b\u03ae\u03c8\u03b5\u03c9\u03bd TrayWindow.menu.stopalldownloads=\u0394\u03b9\u03b1\u03ba\u03bf\u03c0\u03ae &\u038c\u03bb\u03c9\u03bd \u03c4\u03c9\u03bd \u039b\u03ae\u03c8\u03b5\u03c9\u03bd ConfigView.section.tracker.sslport.info=\u0394\u03b5\u03af\u03c4\u03b5 \u03c4\u03b9\u03c2 \u03a3\u03c5\u03c7\u03bd\u03ad\u03c2 \u0395\u03c1\u03c9\u03c4\u03ae\u03c3\u03b5\u03b9\u03c2 \u03b3\u03b9\u03b1 \u03c0\u03b5\u03c1\u03b9\u03c3\u03c3\u03cc\u03c4\u03b5\u03c1\u03b5\u03c2 \u03c0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 wizard.tracker.ssl=\u03a7\u03c1\u03ae\u03c3\u03b7 SSL ConfigView.label.playdownloadfinished=\u0391\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03ae \u03ae\u03c7\u03bf\u03c5 \u03cc\u03c4\u03b1\u03bd \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03bd\u03b5\u03c4\u03b1\u03b9 \u03bc\u03af\u03b1 \u03bb\u03ae\u03c8\u03b7 TableColumn.header.pieces=\u039a\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9\u03b1 TableColumn.header.completion=\u039f\u03bb\u03bf\u03ba\u03bb\u03ae\u03c1\u03c9\u03c3\u03b7 TableColumn.header.completion.info=\u0393\u03c1\u03b1\u03c6\u03b9\u03ba\u03b7 \u03b1\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03c3\u03c4\u03b1\u03c3\u03b7 \u03c4\u03bf\u03c5 % \u03bb\u03b7\u03c8\u03b7\u03c2 ConfigView.section.style.showdownloadbasket=\u0395\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 \u03c4\u03bf\u03c5 \u039a\u03b1\u03bb\u03b1\u03b8\u03b9\u03bf\u03cd \u039b\u03ae\u03c8\u03b5\u03c9\u03bd (\u03a3\u03cd\u03c1\u03b5\u03c4\u03b5 \u03c4\u03b1 .torrents) ConfigView.section.style.alwaysShowTorrentFiles=\u03a0\u03ac\u03bd\u03c4\u03b1 \u03bd\u03b1 \u03b5\u03bc\u03c6\u03b1\u03bd\u03af\u03b6\u03bf\u03bd\u03c4\u03b1\u03b9 \u03c4\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03b1 Torrent \u03c3\u03b5 \u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b9\u03b5\u03c2/\u0391\u03c1\u03c7\u03b5\u03af\u03b1 wizard.multitracker=\u0395\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae \u03c0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03b9\u03ce\u03bd \u03b3\u03b9\u03b1 \u03c0\u03bf\u03bb\u03bb\u03b1\u03c0\u03bb\u03bf\u03c5\u03c2 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b5\u03c2 \u03c3\u03c4\u03b1 torrent wizard.multitracker.title=\u03a0\u03bf\u03bb\u03bb\u03b1\u03c0\u03bb\u03bf\u03b9 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b5\u03c2 wizard.multitracker.configuration=\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u03a0\u03bf\u03bb\u03bb\u03b1\u03c0\u03bb\u03ce\u03bd \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03c9\u03bd wizard.multitracker.new=\u039d\u03ad\u03bf... wizard.multitracker.edit=\u0395\u03c0\u03b5\u03be\u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1.. wizard.multitracker.delete=\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae wizard.multitracker.group=\u039f\u03bc\u03ac\u03b4\u03b1 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03c9\u03bd wizard.multitracker.edit.title=\u0391\u03bb\u03bb\u03b1\u03b3\u03ae \u03a0\u03bf\u03bb\u03bb\u03b1\u03c0\u03bb\u03ce\u03bd \u03a0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03c5\u03b8\u03ae\u03c3\u03b5\u03c9\u03bd \u0391\u03bb\u03bb\u03b1\u03b3\u03ce\u03bd wizard.multitracker.edit.name=\u038c\u03bd\u03bf\u03bc\u03b1 wizard.multitracker.edit.save=\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 wizard.multitracker.edit.newgroup=\u039d\u03ad\u03b1 \u039f\u03bc\u03ac\u03b4\u03b1 wizard.multitracker.edit.deletegroup=\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae wizard.multitracker.edit.newtracker=\u039d\u03ad\u03b1 \u03a0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03cd\u03b8\u03b7\u03c3\u03b7 wizard.multitracker.edit.deletetracker=\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae wizard.multitracker.edit.edit=\u0395\u03c0\u03b5\u03be\u03b5\u03c1\u03b3\u03c1\u03b1\u03c6\u03af\u03b1 wizard.addingmt=\u0393\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03b5\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae \u03c0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03b9\u03ce\u03bd \u03c4\u03c9\u03bd \u03a0\u03bf\u03bb\u03bb\u03b1\u03c0\u03bb\u03ce\u03bd \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03c9\u03bd wizard.multitracker.noannounce=\u0397 \u03b4\u03b9\u03b5\u03c5\u03b8\u03c5\u03bd\u03c3\u03b7 \u03b1\u03bd\u03b1\u03ba\u03bf\u03af\u03bd\u03c9\u03c3\u03b7\u03c2 \u03b4\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03c3\u03c4\u03b7 \u03bb\u03af\u03c3\u03c4\u03b1 \u03b9\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03c9\u03bd \u03c3\u03b1\u03c2 MyTorrentsView.menu.recheck=\u0395\u03c0\u03b1\u03bd\u03ad\u03bb\u03b5\u03b3&\u03c7\u03bf\u03c2 iconBar.showDownloadBar.tooltip=\u0395\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 \u03a1\u03ac\u03b2\u03b4\u03bf\u03c5 \u039b\u03ae\u03c8\u03b7\u03c2 iconBar.start.tooltip=\u0395\u03ba\u03ba\u03af\u03bd\u03b9\u03c3\u03b7 iconBar.stop.tooltip=\u0394\u03b9\u03b1\u03ba\u03bf\u03c0\u03ae iconBar.remove.tooltip=\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae iconBar.openNoDefault.tooltip=\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03b5\u03bd\u03cc\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 .torrent (\u03c7\u03c9\u03c1\u03af\u03c2 \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03b5\u03b3\u03bc\u03ad\u03bd\u03b7 \u03b1\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7) iconBar.openURL.tooltip=\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7\u03c2 iconBar.openFolder.tooltip=\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03a6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5 iconBar.new.tooltip=\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03b5\u03bd\u03cc\u03c2 torrent iconBar.up.tooltip=\u039c\u03b5\u03c4\u03b1\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03a0\u03ac\u03bd\u03c9 iconBar.down.tooltip=\u039c\u03b5\u03c4\u03b1\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u039a\u03ac\u03c4\u03c9 iconBar.run.tooltip=\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 iconBar.host.tooltip=\u03a6\u03b9\u03bb\u03bf\u03be\u03b5\u03bd\u03af\u03b1 iconBar.publish.tooltip=\u0394\u03b7\u03bc\u03bf\u03c3\u03af\u03b5\u03c5\u03c3\u03b7 MyTorrentsView.menu.editTracker=\u0395\u03c0\u03b5\u03be\u03b5\u03c1\u03b3\u03b1&\u03c3\u03af\u03b1 \u0394\u03b9\u03b5\u03b8\u03c5\u03bd\u03c3\u03b7\u03c2 \u0399\u03c7\u03bd\u03b7\u03bb\u03ac\u03c4\u03b7 GeneralView.menu.selectTracker=\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u0399\u03c7\u03bd\u03b7\u03bb\u03ac\u03c4\u03b7 ConfigView.section.stats.xslfile=\u038c\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 XSL ConfigView.section.stats.xslfiledetails=\u0391\u03c5\u03c4\u03cc \u03b8\u03b1 \u03b5\u03b9\u03c3\u03b1\u03c7\u03b8\u03b5\u03af \u03c3\u03c4\u03bf header \u03c4\u03bf\u03c5 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c3\u03c4\u03b1\u03c4\u03b9\u03c3\u03c4\u03b9\u03ba\u03ce\u03bd \u03bc\u03ad\u03c3\u03c9 \u03c4\u03b7\u03c2 \u03b5\u03c4\u03b9\u03ba\u03ad\u03c4\u03b1\u03c2 tag ConfigView.label.savetorrentbackup=\u0391\u03c0\u03bf\u03b8\u03ae\u03b5\u03c5\u03c3\u03b7 \u0391\u03bd\u03c4\u03b9\u03b3\u03c1\u03ac\u03c6\u03bf\u03c5 \u0391\u03c3\u03c6\u03b1\u03bb\u03b5\u03af\u03b1\u03c2 ConfigView.section.tracker.forceport=\u03a4\u03b1 \u03c6\u03b9\u03bb\u03bf\u03be\u03b5\u03bd\u03bf\u03cd\u03bc\u03b5\u03bd\u03b1 \u03b5\u03be\u03c9\u03c4\u03b5\u03c1\u03b9\u03ba\u03ac \u03b1\u03c1\u03c7\u03b5\u03af\u03b1 torrents \u03c3\u03c4\u03b7\u03bd \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03b5\u03b3\u03bc\u03ad\u03bd\u03b7 \u03b8\u03cd\u03c1\u03b1 ConfigView.section.ipfilter.allow=\u039d\u03b1 \u0395\u03a0\u0399\u03a4\u0395\u03a1\u03a0\u039f\u039d\u03a4\u0391\u0399 \u03b1\u03c5\u03c4\u03ac \u03c4\u03b1 \u03c0\u03b5\u03b4\u03af\u03b1 (\u03b7 \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u03b5\u03af\u03bd\u03b1\u03b9 \u03bd\u03b1 \u039c\u0397\u039d \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03bf\u03bd\u03c4\u03b1\u03b9) ConfigView.section.ipfilter.list.inrange=\u03ae\u03c4\u03b1\u03bd \u03c3\u03c4\u03bf \u03c0\u03b5\u03b4\u03af\u03bf ConfigView.section.ipfilter.list.notinrange=\u03b4\u03b5\u03bd \u03ae\u03c4\u03b1\u03bd \u03c3\u03c4\u03bf \u03c0\u03b5\u03b4\u03af\u03bf ConfigView.section.ipfilter.list.title=\u039b\u03af\u03c3\u03c4\u03b1 \u03bc\u03c0\u03bb\u03bf\u03ba\u03b1\u03c1\u03b9\u03c3\u03bc\u03ad\u03bd\u03c9\u03bd IP ConfigView.label.allowsameip=\u039d\u03b1 \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03bf\u03bd\u03c4\u03b1\u03b9 \u03c0\u03bf\u03bb\u03bb\u03b1\u03c0\u03bb\u03ad\u03c2 \u03c3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03b9\u03c2 \u03b1\u03c0\u03cc \u03c4\u03bf \u03af\u03b4\u03b9\u03bf IP ConfigView.label.allowsameip.tooltip=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03bc\u03cc\u03bd\u03bf \u03b1\u03bd \u03c4\u03bf \u03a7\u03a1\u0395\u0399\u0391\u0396\u0395\u03a3\u03a4\u0395.\n\u03a0\u03c1\u03cc\u03ba\u03b5\u03b9\u03c4\u03b1\u03b9 \u03b3\u03b9\u03b1 \u03c0\u03c1\u03bf\u03c3\u03c4\u03b1\u03c3\u03af\u03b1 (\u03cc\u03c4\u03b1\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b1\u03c0\u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03bf). ManagerItem.superseeding=\u03a5\u03c0\u03b5\u03c1-\u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03cc\u03c2 ConfigView.label.userSuperSeeding=\u03a7\u03c1\u03ae\u03c3\u03b7 \u03a5\u03c0\u03b5\u03c1-\u0394\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf\u03cd PeersView.uniquepiece=\u039a\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9 (\u039b\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03a5\u03c0\u03b5\u03c1-\u0394\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf\u03c5) PeersView.uniquepiece.none=\u039a\u03b1\u03bd\u03ad\u03bd\u03b1 PeersView.timetosend=\u03a7\u03c1\u03cc\u03bd\u03bf\u03c2 \u03b3\u03b9\u03b1 \u03b5\u03c0\u03b1\u03bd\u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae \u039a\u03bf\u03bc\u03bc\u03b1\u03c4\u03b9\u03bf\u03cd (\u039b\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03a5\u03c0\u03b5\u03c1-\u0394\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf\u03c5) ConfigView.section.style.addurlsilently=\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03c4\u03bf\u03c5 URL \u03c3\u03c4\u03bf \u03c0\u03b1\u03c1\u03b1\u03c3\u03ba\u03ae\u03bd\u03b9\u03bf (\u03c7\u03c9\u03c1\u03af\u03c2 \u03c0\u03b1\u03c1\u03ac\u03b8\u03c5\u03c1\u03bf) ConfigView.section.style.addurlsilently.tooltip=\u03a0\u03c1\u03bf\u03c3\u03bf\u03c7\u03ae: \u03c4\u03bf \u03ba\u03cd\u03c1\u03b9\u03bf \u03c0\u03b1\u03c1\u03ac\u03b8\u03c5\u03c1\u03bf \u03b4\u03b5\u03bd \u03b8\u03b1 \u03b5\u03c0\u03b1\u03bd\u03b5\u03bc\u03c6\u03b1\u03bd\u03af\u03b6\u03b5\u03c4\u03b1\u03b9 \u03b1\u03c6\u03bf\u03cd \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03b7\u03b8\u03b5\u03af!\n\u0391\u03bd \u03c7\u03ac\u03bd\u03b5\u03c4\u03b1\u03b9 \u03c4\u03b1 \u03b5\u03b9\u03ba\u03bf\u03bd\u03af\u03b4\u03b9\u03b1 \u03c4\u03bf\u03c5 tray, \u03af\u03c3\u03c9\u03c2 \u03b8\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b1\u03c0\u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03b1\u03c5\u03c4\u03ae\u03bd \u03c4\u03b7\u03bd \u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae. ConfigView.section.file.decoder.prompt=\u039d\u03b1 \u03b5\u03bc\u03c6\u03b1\u03bd\u03af\u03b6\u03b5\u03c4\u03b1\u03b9 \u03c0\u03c1\u03bf\u03c4\u03c1\u03bf\u03c0\u03ae \u03c3\u03b5 \u03c0\u03b5\u03c1\u03af\u03c0\u03c4\u03c9\u03c3\u03b7 \u03c0\u03bf\u03c5 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03b7 \u03b4\u03c5\u03bd\u03b1\u03c4\u03cc\u03c4\u03b7\u03c4\u03b1 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7\u03c2 ConfigView.section.file.decoder.prompt.tooltip=\u03a0\u03ac\u03bd\u03c4\u03b1 \u03bd\u03b1 \u03b5\u03bc\u03c6\u03b1\u03bd\u03af\u03b6\u03b5\u03c4\u03b1\u03b9 \u03c0\u03b1\u03c1\u03ac\u03b8\u03c5\u03c1\u03bf \u03c3\u03b5 \u03c0\u03b5\u03c1\u03af\u03c0\u03c4\u03c9\u03c3\u03b7 \u03c0\u03bf\u03c5 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03b7 \u03b4\u03c5\u03bd\u03b1\u03c4\u03cc\u03c4\u03b7\u03c4\u03b1 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7\u03c2 MyTorrentsView.menu.moveTop=\u039a\u03bf&\u03c1\u03c5\u03c6\u03ae MyTorrentsView.menu.moveEnd=&\u0392\u03ac\u03c3\u03b7 ConfigView.label.moveonlyusingdefaultsave=\u03b1\u03bd \u03b2\u03c1\u03af\u03c3\u03ba\u03b5\u03c4\u03b1\u03b9 \u03c3\u03c4\u03bf\u03bd \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03b5\u03b3\u03bc\u03ad\u03bd\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd ConfigView.label.moveonlyusingdefaultsave.tooltip=\u039d\u03b1 \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03bc\u03b5\u03c4\u03b1\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03bc\u03cc\u03bd\u03bf \u03b1\u03bd \u03c4\u03b1 \u03bb\u03b7\u03c6\u03b8\u03ad\u03bd\u03c4\u03b1 \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1 \u03b2\u03c1\u03af\u03c3\u03ba\u03bf\u03bd\u03c4\u03b1\u03b9 \u03c3\u03c4\u03bf\u03bd \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03b5\u03b3\u03bc\u03ad\u03bd\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd ConfigView.label.watchtorrentfolder=\u0395\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae \u03bd\u03ad\u03c9\u03bd .torrent \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b1 ConfigView.label.watchtorrentfolder.tooltip=\u0391\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7 \u03b3\u03b9\u03b1 \u03bd\u03ad\u03b1 .torrent \u03c0\u03b5\u03c1\u03b9\u03bf\u03b4\u03b9\u03ba\u03ac ConfigView.label.watchtorrentfolderinterval=\u03a0\u03b5\u03c1\u03af\u03bf\u03b4\u03bf\u03c2 ConfigView.label.watchtorrentfolderinterval.tooltip=\u0397 \u03c0\u03b5\u03c1\u03af\u03bf\u03b4\u03bf\u03c2 \u03bc\u03ad\u03c7\u03c1\u03b9 \u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2 \u03bd\u03b1 \u03b5\u03c0\u03b1\u03bd\u03b5\u03be\u03b5\u03c4\u03b1\u03c3\u03c4\u03b5\u03af \u03b3\u03b9\u03b1 \u03bd\u03ad\u03b1 torrents ConfigView.dialog.choosewatchtorrentfolderpath=\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf\u03bd \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03b5\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2 .torrent ConfigView.label.startwatchedtorrentsstopped=\u0395\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03c3\u03b5 \u03c3\u03c4\u03b1\u03bc\u03b1\u03c4\u03b7\u03bc\u03ad\u03bd\u03b1 torrents ConfigView.label.startwatchedtorrentsstopped.tooltip=\u0395\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae \u03bd\u03ad\u03c9\u03bd .torrents \u03c3\u03b5 \u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7 \u0394\u0399\u0391\u039a\u039f\u03a0\u0397\u03a3 ConfigView.section.plugins=\u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03b1 wizard.maketorrent.filesize=\u039c\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 \u0391\u03c1\u03c7\u03b5\u03af\u03c9\u03bd wizard.maketorrent.piececount=\u03a3\u03cd\u03bd\u03bf\u03bb\u03bf \u039a\u03bf\u03bc\u03bc\u03b1\u03c4\u03b9\u03ce\u03bd wizard.maketorrent.piecesize=\u039c\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 \u039a\u03bf\u03bc\u03bc\u03b1\u03c4\u03b9\u03bf\u03cd wizard.maketorrent.auto=\u0391\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b1 MainWindow.menu.view.stats=&\u03a3\u03c4\u03b1\u03c4\u03b9\u03c3\u03c4\u03b9\u03ba\u03ac SpeedView.title.full=\u0394\u03c1\u03b1\u03c3\u03c4\u03b7\u03c1\u03b9\u03cc\u03c4\u03b7\u03c4\u03b1 SpeedView.downloadSpeed.title=\u03a4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u039b\u03ae\u03c8\u03b7\u03c2 SpeedView.uploadSpeed.title=\u03a4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 ConfigView.section.style.useSIUnits=\u03a7\u03c1\u03ae\u03c3\u03b7 \u03bc\u03bf\u03bd\u03ac\u03b4\u03c9\u03bd IEC (KB -> KiB \u03ba\u03bb\u03c0.) iconBar.top.tooltip=\u039c\u03b5\u03c4\u03b1\u03ba\u03af\u03bd\u03b9\u03c3\u03b7 \u03c3\u03c4\u03b7\u03bd \u03ba\u03bf\u03c1\u03c5\u03c6\u03ae iconBar.bottom.tooltip=\u039c\u03b5\u03c4\u03b1\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03c3\u03c4\u03b7 \u03b2\u03ac\u03c3\u03b7 TableColumn.header.health=\u03a5\u03b3\u03b5\u03af\u03b1 MyTorrentsView.menu.health=&\u0393\u03b9\u03b1 \u03c4\u03b7\u03bd \u03a5\u03b3\u03b5\u03af\u03b1 health.explain.grey=\u03a3\u03b7\u03bc\u03b1\u03af\u03bd\u03b5\u03b9 \u03c0\u03c9\u03c2 \u03c4\u03bf torrent \u03c3\u03b1\u03c2 \u03b4\u03b5\u03bd \u03bb\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03b5\u03af (\u038c\u03c5\u03c4\u03b5 \u03bb\u03b1\u03bc\u03b2\u03ac\u03bd\u03b5\u03b9 \u03bf\u03cd\u03c4\u03b5 \u03c3\u03c4\u03ad\u03bb\u03bd\u03b5\u03b9) health.explain.red=\u03a3\u03b7\u03bc\u03b1\u03af\u03bd\u03b5\u03b9 \u03c0\u03c9\u03c2 \u03b4\u03b5\u03bd \u03b5\u03af\u03c3\u03c4\u03b5 \u03c3\u03c5\u03bd\u03b4\u03b5\u03b4\u03b5\u03bc\u03ad\u03bd\u03bf\u03c2/\u03b7 \u03bc\u03b5 \u03ac\u03bb\u03bb\u03bf\u03c5\u03c2 \u03ba\u03b1\u03b8\u03ce\u03c2 \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03bb\u03ae\u03c8\u03b7. health.explain.blue=\u039a\u03b1\u03c4\u03ac \u03c4\u03bf \u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03cc \u03c3\u03b7\u03bc\u03b1\u03af\u03bd\u03b5\u03b9 \u03c0\u03c9\u03c2 \u03b4\u03b5\u03bd \u03b5\u03af\u03c3\u03c4\u03b5 \u03c3\u03c5\u03bd\u03b4\u03b5\u03b4\u03b5\u03bc\u03ad\u03bd\u03bf\u03c2/\u03b7 \u03c0\u03bf\u03c5\u03b8\u03b5\u03bd\u03ac.\n\u038c\u03c4\u03b1\u03bd \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03bb\u03ae\u03c8\u03b7, \u03c3\u03b7\u03bc\u03b1\u03af\u03bd\u03b5\u03b9 \u03c0\u03c9\u03c2 \u03b5\u03af\u03c3\u03c4\u03b5 \u03c3\u03c5\u03bd\u03b4\u03b5\u03b4\u03b5\u03bc\u03ad\u03bd\u03bf\u03c2/\u03b7 \u03bc\u03b5 \u03ba\u03ac\u03c0\u03bf\u03b9\u03bf\u03c5\u03c2 \u03b1\u03bb\u03bb\u03ac \u03bf \u03b9\u03c7\u03bd\u03b7\u03bb\u03ac\u03c4\u03b7\u03c2 \u03b4\u03b5\u03bd \u03bb\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03b5\u03af. health.explain.yellow=\u03a3\u03b7\u03bc\u03b1\u03af\u03bd\u03b5\u03b9 \u03c0\u03c9\u03c2 \u03b7 \u03bf \u03b9\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7\u03c2 \u03b5\u03af\u03bd\u03b1\u03b9 \u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9, \u03ba\u03b1\u03b9 \u03b5\u03af\u03c3\u03c4\u03b5 \u03c3\u03c5\u03bd\u03b4\u03b5\u03b4\u03b5\u03bc\u03ad\u03bd\u03bf\u03b9, \u03b1\u03bb\u03bb\u03ac \u03b4\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03ba\u03b1\u03bc\u03af\u03b1 \u03b1\u03c0\u03bf\u03bc\u03b1\u03ba\u03c1\u03c5\u03c3\u03bc\u03ad\u03bd\u03b7 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7.\n\u038a\u03c3\u03c9\u03c2 \u03ad\u03c7\u03b5\u03c4\u03b5 \u03c0\u03c1\u03cc\u03b2\u03bb\u03b7\u03bc\u03b1 NAT \u03b1\u03bd \u03c4\u03b1 torrents \u03c3\u03b1\u03c2 \u03c0\u03b1\u03c1\u03b1\u03bc\u03ad\u03bd\u03bf\u03c5\u03bd \u03ba\u03af\u03c4\u03c1\u03b9\u03bd\u03b1 \u03c3\u03c5\u03bd\u03b5\u03c7\u03ce\u03c2. health.explain.green=\u03a3\u03b7\u03bc\u03b1\u03af\u03bd\u03b5\u03b9 \u03c0\u03c9\u03c2 \u03cc\u03bb\u03b1 \u03c0\u03ac\u03bd\u03b5 \u03ba\u03b1\u03bb\u03ac. ConfigView.section.style.alwaysRefreshMyTorrents=\u03a0\u03ac\u03bd\u03c4\u03b1 \u03bd\u03b1 \u03b5\u03bd\u03b7\u03bc\u03b5\u03c1\u03ce\u03bd\u03bf\u03bd\u03c4\u03b1\u03b9 \u03a4\u03b1 Torrent \u03bc\u03bf\u03c5 ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=\u0391\u03c5\u03c4\u03ae \u03b7 \u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u03b5\u03bd\u03b7\u03bc\u03b5\u03c1\u03ce\u03bd\u03b5\u03b9 \u03c4\u03b7\u03bd \u03c0\u03c1\u03bf\u03b2\u03bf\u03bb\u03ae \u03c4\u03c9\u03bd Torrent \u03bc\u03bf\u03c5 \u03b1\u03ba\u03cc\u03bc\u03b7 \u03ba\u03b1\u03b9 \u03b1\u03bd \u03b4\u03b5\u03bd \u03b5\u03bc\u03c6\u03b1\u03bd\u03af\u03b6\u03b5\u03c4\u03b1\u03b9 (\u03c7\u03c1\u03ae\u03c3\u03b9\u03bc\u03bf \u03b3\u03b9\u03b1 \u03ba\u03ac\u03c0\u03bf\u03b9\u03b1 \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03b1 mIRC) # #2.0.7.0 # security.certtruster.title=\u03a0\u03c1\u03bf\u03b5\u03b9\u03b4\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03a0\u03b9\u03c3\u03c4\u03bf\u03c0\u03bf\u03b9\u03b7\u03c4\u03b9\u03ba\u03bf\u03cd \u0391\u03c3\u03c6\u03b1\u03bb\u03b5\u03af\u03b1\u03c2 security.certtruster.intro=\u03a4\u03bf \u03c0\u03b9\u03c3\u03c4\u03bf\u03c0\u03bf\u03b9\u03b7\u03c4\u03b9\u03ba\u03cc \u03b1\u03c3\u03c6\u03b1\u03bb\u03b5\u03af\u03b1\u03c2 \u03ad\u03c7\u03b5\u03b9 \u03b5\u03ba\u03b4\u03bf\u03b8\u03b5\u03af \u03b1\u03c0\u03cc \u03bc\u03af\u03b1 \u03b5\u03c4\u03b1\u03b9\u03c1\u03af\u03b1 \u03c0\u03bf\u03c5 \u03b4\u03b5\u03bd \u03b5\u03bc\u03c0\u03b9\u03c3\u03c4\u03b5\u03cd\u03b5\u03c3\u03c4\u03b5 security.certtruster.resource=\u03a0\u03cc\u03c1\u03bf\u03c2: security.certtruster.issuedto=\u03a0\u03b1\u03c1\u03b1\u03c7\u03c9\u03c1\u03ae\u03b8\u03b7\u03ba\u03b5 \u03a3\u03b5: security.certtruster.issuedby=\u03a0\u03b1\u03c1\u03b1\u03c7\u03c9\u03c1\u03ae\u03b8\u03b7\u03ba\u03b5 \u0391\u03c0\u03cc: security.certtruster.prompt=\u0398\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03c4\u03bf \u03b5\u03bc\u03c0\u03b9\u03c3\u03c4\u03b5\u03c5\u03b8\u03b5\u03af\u03c4\u03b5? security.certtruster.yes=\u039d\u03b1\u03b9 security.certtruster.no=\u038c\u03c7\u03b9 ConfigView.section.tracker.torrentsperpage=\u03a0\u03cc\u03c3\u03b1 torrents \u03b1\u03bd\u03ac \u03c3\u03b5\u03bb\u03af\u03b4\u03b1 ? (0 : \u03c7\u03c9\u03c1\u03af\u03c2 \u03cc\u03c1\u03b9\u03bf) MainWindow.menu.file.share=&\u0394\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf\u03c2 MainWindow.menu.file.share.file=&\u0391\u03c1\u03c7\u03b5\u03af\u03bf\u03c5... MainWindow.menu.file.share.dir=&\u03a6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5... MainWindow.menu.file.share.dircontents=&\u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03b1 \u03a6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5... MainWindow.menu.file.share.dircontentsrecursive=\u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03b1 \u03a6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5 (\u03ba\u03b1\u03b9 &\u03a5\u03c0\u03bf\u03c6\u03b1\u03ba\u03ad\u03bb\u03c9\u03bd)... MainWindow.dialog.share.sharefile=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u0391\u03c1\u03c7\u03b5\u03af\u03bf \u03c0\u03c1\u03bf\u03c2 \u0394\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf MainWindow.dialog.share.sharedir=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03a6\u03ac\u03ba\u03b5\u03bb\u03bf \u03c0\u03c1\u03bf\u03c2 \u0394\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf MainWindow.dialog.share.sharedircontents=\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03b1 \u03a6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5 \u03c0\u03c1\u03bf\u03c2 \u0394\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf MainWindow.dialog.share.sharedircontents.recursive=\u03ba\u03b1\u03b9 \u03a5\u03c0\u03bf\u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5\u03c2 globalmanager.download.remove.veto=\u0397 \u03bb\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03b4\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2 \u03ad\u03c7\u03b5\u03b9 \u03b1\u03c0\u03b1\u03b3\u03bf\u03c1\u03b5\u03c5\u03b8\u03b5\u03af plugin.sharing.download.remove.veto=\u0391\u03c5\u03c4\u03ae \u03b7 \u03bb\u03ae\u03c8\u03b7 \u03b5\u03af\u03bd\u03b1\u03b9 \u03c4\u03bf \u03b1\u03c0\u03bf\u03c4\u03ad\u03bb\u03b5\u03c3\u03bc\u03b1 \u03b5\u03bd\u03cc\u03c2 \u03ba\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03bf\u03c5 \u03c0\u03cc\u03c1\u03bf\u03c5.\n\u0393\u03b9\u03b1 \u03bd\u03b1 \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03b5\u03c4\u03b5 \u03c4\u03b7 \u03bb\u03ae\u03c8\u03b7, \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03c4\u03b5 \u03c4\u03bf\u03bd \u03c3\u03c7\u03b5\u03c4\u03b9\u03ba\u03cc \u03ba\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03bf \u03c0\u03cc\u03c1\u03bf: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=\u039a\u03cd\u03c1\u03b9\u03bf ConfigView.section.tracker.web=\u0394\u03b9\u03b1\u03b4\u03af\u03ba\u03c4\u03c5\u03bf ConfigView.label.prioritizefirstpiece=\u03a0\u03c1\u03bf\u03c4\u03b5\u03c1\u03b1\u03b9\u03cc\u03c4\u03b7\u03c4\u03b1 \u03c3\u03c4\u03bf \u03c0\u03c1\u03ce\u03c4\u03bf \u03ba\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9 \u03c4\u03c9\u03bd \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd ConfigView.label.prioritizefirstpiece.tooltip=\u039d\u03b1 \u03b3\u03af\u03bd\u03b5\u03b9 \u03c0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b5\u03b9\u03b1 \u03bd\u03b1 \u03ba\u03b1\u03c4\u03b5\u03b2\u03b5\u03af \u03c4\u03bf \u03b1\u03c1\u03c7\u03b9\u03ba\u03cc \u03bc\u03ad\u03c1\u03bf\u03c2 \u03c4\u03bf\u03c5 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \u03c3\u03c4\u03b7\u03bd \u03b1\u03c1\u03c7\u03ae.\n\u0393\u03b9\u03b1 \u03c5\u03c0\u03bf\u03c3\u03c4\u03ae\u03c1\u03b9\u03be\u03b7 \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03c3\u03ba\u03cc\u03c0\u03b9\u03c3\u03b7\u03c2 \u03b1\u03c0\u03cc \u03bd\u03c9\u03c1\u03af\u03c2. ConfigView.section.file.confirm_data_delete=\u0395\u03c0\u03b9\u03b2\u03b5\u03b2\u03b1\u03b9\u03c9\u03c3\u03b7 \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7 \u03b4\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd ConfigView.section.file.confirm_data_delete.tooltip=\u0395\u03c0\u03b9\u03b2\u03b5\u03b2\u03b1\u03b9\u03c9\u03c3\u03b7 \u03b4\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2 \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd \u03cc\u03c4\u03b1\u03bd \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03c7\u03c1\u03ae\u03c3\u03b7 \u03c4\u03bf\u03c5 '\u0391\u03c6\u03b1\u03af\u03c1\u03b5\u03c3\u03b7 \u03ba\u03b1\u03b9 \u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae...' TrayWindow.menu.startalldownloads=\u0395\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u038c\u03bb\u03c9\u03bd \u03c4\u03c9\u03bd \u039b\u03ae\u03c8\u03b5\u03c9\u03bd SystemTray.menu.startalltransfers=\u0395&\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u038c\u03bb\u03c9\u03bd \u03c4\u03c9\u03bd \u039b\u03ae\u03c8\u03b5\u03c9\u03bd sharing.progress.title=\u03a0\u03c1\u03cc\u03bf\u03b4\u03bf\u03c2 \u0394\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf\u03c5 sharing.progress.hide=\u0391\u03c0\u03cc\u03ba\u03c1\u03c5\u03c8\u03b7 MainWindow.menu.view.myshares=\u0394\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03b5\u03bd\u03bf\u03b9 \u03a0\u03bf\u03c1\u03bf\u03b9 MySharesView.title.full=\u0394\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03b6\u03cc\u03bc\u03b5\u03bd\u03b1 \u0391\u03c1\u03c7\u03b5\u03af\u03b1 MySharesView.name=\u038c\u03bd\u03bf\u03bc\u03b1 MySharesView.type=\u03a4\u03cd\u03c0\u03bf\u03c2 MySharesView.type.file=\u0391\u03c1\u03c7\u03b5\u03af\u03bf MySharesView.type.dir=\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2 MySharesView.type.dircontents=\u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03b1 \u03a6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5 MySharesView.type.dircontentsrecursive=\u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03b1 \u03a6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5 (\u03ba\u03b1\u03b9 \u03a5\u03c0\u03bf\u03c6\u03b1\u03ba\u03ad\u03bb\u03c9\u03bd) MySharesView.menu.remove=\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae ConfigView.section.tracker.extensions=\u0395\u03c0\u03b5\u03ba\u03c4\u03ac\u03c3\u03b5\u03b9\u03c2 ConfigView.section.tracker.sendpeerids=\u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae \u03c4\u03b1\u03c5\u03c4\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2 \u03c3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03c9\u03bd \u03c3\u03b5 \u03ac\u03c4\u03bf\u03bc\u03b1 \u03c0\u03bf\u03c5 \u03ba\u03b1\u03c4\u03b5\u03b2\u03ac\u03b6\u03bf\u03c5\u03bd ConfigView.section.tracker.enableudp=\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03a0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03cd\u03b8\u03b7\u03c3\u03b7\u03c2 \u0391\u03bb\u03bb\u03b1\u03b3\u03ce\u03bd \u03bc\u03ad\u03c3\u03c9 UDP plugin.sharing.torrent.remove.veto=\u0391\u03c5\u03c4\u03b7 \u03b7 \u03ba\u03b1\u03c4\u03b1\u03c7\u03c9\u03c1\u03b7\u03c3\u03b7 \u03b9\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 \u03b5\u03af\u03bd\u03b1\u03b9 \u03c4\u03bf \u03b1\u03c0\u03bf\u03c4\u03ad\u03bb\u03b5\u03c3\u03bc\u03b1 \u03b5\u03bd\u03cc\u03c2 \u03ba\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03bf\u03c5 \u03c0\u03cc\u03c1\u03bf\u03c5.\n\u0393\u03b9\u03b1 \u03bd\u03b1 \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03b5\u03c4\u03b5 \u03c4\u03b7 \u03bb\u03ae\u03c8\u03b7, \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03c4\u03b5 \u03c4\u03b7 \u03c3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ae \u03ba\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=\u0397 \u03bb\u03ae\u03c8\u03b7 \u03b4\u03b5\u03bd \u03bc\u03c0\u03bf\u03c1\u03b5\u03af \u03bd\u03b1 \u03b1\u03c6\u03b1\u03b9\u03c1\u03b5\u03b8\u03b5\u03af \u03b5\u03c0\u03b5\u03b9\u03b4\u03ae \u03b4\u03b5\u03bd \u03ad\u03c7\u03b5\u03b9 \u03b4\u03b9\u03b1\u03ba\u03bf\u03c0\u03b5\u03af plugin.sharing.remove.veto=\u0391\u03c5\u03c4\u03ae \u03b7 \u03ba\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03b5\u03af\u03bd\u03b1\u03b9 \u03bc\u03af\u03b1 \u03c5\u03c0\u03bf-\u03ba\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03bc\u03af\u03b1\u03c2 \u03ba\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7\u03c2 '\u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd \u03a6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5' \u03ba\u03b1\u03b9 \u03b4\u03b5\u03bd \u03bc\u03c0\u03bf\u03c1\u03b5\u03af \u03bd\u03b1 \u03b4\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03b5\u03af \u03be\u03b5\u03c7\u03c9\u03c1\u03b9\u03c3\u03c4\u03ac.\n\u0394\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03c4\u03b5 \u03c4\u03b7\u03bd \u03b1\u03c1\u03c7\u03b9\u03ba\u03ae \u03ba\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 GeneralView.label.hash.tooltip=\u039a\u03ac\u03bd\u03c4\u03b5 \u03ba\u03bb\u03b9\u03ba \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b1\u03bd\u03c4\u03b9\u03b3\u03c1\u03ac\u03c8\u03b5\u03c4\u03b5 \u03c4\u03bf \u03b1\u03bd\u03b1\u03b3\u03bd\u03c9\u03c1\u03b9\u03c3\u03c4\u03b9\u03ba\u03cc \u03c3\u03c4\u03bf \u03c0\u03c1\u03cc\u03c7\u03b5\u03b9\u03c1\u03bf ConfigView.section.tracker.maxpeersreturned=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc\u03c2 \u03b5\u03c0\u03b9\u03c3\u03c4\u03c1\u03b5\u03c6\u03cc\u03bc\u03b5\u03bd\u03c9\u03bd \u03c3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03c9\u03bd (0: \u03c7\u03c9\u03c1\u03af\u03c2 \u03cc\u03c1\u03b9\u03bf) ConfigView.label.serverport=\u0398\u03cd\u03c1\u03b1 TCP \u03b5\u03b9\u03c3\u03b5\u03c1\u03c7\u03cc\u03bc\u03b5\u03bd\u03c9\u03bd \u03b1\u03b9\u03c4\u03ae\u03c3\u03b5\u03c9\u03bd configureWizard.nat.server.tcp_listen_port=\u0398\u03cd\u03c1\u03b1 TCP \u03b5\u03b9\u03c3\u03b5\u03c1\u03c7\u03cc\u03bc\u03b5\u03bd\u03c9\u03bd \u03b1\u03b9\u03c4\u03ae\u03c3\u03b5\u03c9\u03bd ConfigView.section.sharing=\u039a\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 ConfigView.section.sharing.usessl=\u03a7\u03c1\u03ae\u03c3\u03b7 SSL \u03b3\u03b9\u03b1 \u03ba\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03bf\u03c5\u03c2 \u03c0\u03cc\u03c1\u03bf\u03c5\u03c2 (\u03b1\u03c0\u03b1\u03b9\u03c4\u03b5\u03af\u03c4\u03b1\u03b9 \u03c1\u03cd\u03b8\u03bc\u03b9\u03c3\u03b7 \u03c4\u03b7\u03c2 \u03a0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03cd\u03b8\u03b7\u03c3\u03b7\u03c2 \u0391\u03bb\u03bb\u03b1\u03b3\u03ce\u03bd) ConfigView.section.style.dropdiraction=\u0394\u03c5\u03bd\u03b1\u03c4\u03cc\u03c4\u03b7\u03c4\u03b1 \u03c3\u03cd\u03c1\u03c3\u03b9\u03bc\u03b1\u03c4\u03bf\u03c2 \u03c3\u03b5 \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5\u03c2 ConfigView.section.style.dropdiraction.opentorrents=\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 Torrents ConfigView.section.style.dropdiraction.sharefolder=\u039a\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03a6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5 ConfigView.section.style.dropdiraction.sharefoldercontents=\u039a\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd # # 2.0.7.x # Categories.all=\u038c\u03bb\u03b5\u03c2 Categories.uncategorized=\u03a7\u03c9\u03c1\u03af\u03c2 \u039a\u03b1\u03c4\u03b7\u03b3\u03bf\u03c1\u03af\u03b1 CategoryAddWindow.message=\u0394\u03c9\u03c3\u03c4\u03b5 \u03b5\u03bd\u03b1 \u03bd\u03b5\u03bf \u03bf\u03bd\u03bf\u03bc\u03b1 \u03ba\u03b1\u03c4\u03b7\u03b3\u03bf\u03c1\u03b9\u03b1\u03c2 CategoryAddWindow.title=\u03a0\u03c1\u03bf\u03c3\u03b8\u03b7\u03ba\u03b7 \u03bd\u03b5\u03b1\u03c2 \u03ba\u03b1\u03c4\u03b7\u03b3\u03bf\u03c1\u03b9\u03b1\u03c2 ConfigView.label.autoSeedingIgnoreInfo=\u03a4\u03b1 \u03b1\u03b3\u03bd\u03bf\u03b7\u03b8\u03b5\u03bd\u03c4\u03b1 torrent \u03c4\u03bf\u03c0\u03bf\u03b8\u03b5\u03c4\u03bf\u03c5\u03bd\u03c4\u03b1\u03b9 \u03c3\u03c4\u03bf \u03c4\u03b5\u03bb\u03bf\u03c2 \u03c4\u03b7\u03c2 \u03bf\u03c5\u03c1\u03b1\u03c2 \u03b4\u03b9\u03b1\u03bc\u03bf\u03c1\u03b1\u03c3\u03bc\u03bf\u03c5. \u0394\u03b5\u03bd \u03be\u03b5\u03ba\u03b9\u03bd\u03b1\u03bd\u03b5 \u03b1\u03c5\u03c4\u03bf\u03bc\u03b1\u03c4\u03b1. \u039f\u03b9 \u03ba\u03b1\u03bd\u03bf\u03bd\u03b5\u03c2 \u03b1\u03b3\u03bd\u03bf\u03b7\u03c3\u03b7\u03c2 \u03b4\u03b5\u03bd \u03b9\u03c3\u03c7\u03c5\u03bf\u03c5\u03bd \u03b3\u03b9\u03b1 torrents \u03c0\u03bf\u03c5 \u03b9\u03ba\u03bf\u03bd\u03bf\u03c0\u03bf\u03b9\u03bf\u03c5\u03bd \u03c4\u03b1 \u03ba\u03c1\u03b9\u03c4\u03b7\u03c1\u03b9\u03b1 \u03c0\u03c1\u03c9\u03c4\u03b7\u03c2 \u03c0\u03c1\u03bf\u03c4\u03b5\u03c1\u03b1\u03b9\u03bf\u03c4\u03b7\u03c4\u03b1\u03c2. \u0395\u03ba\u03c4\u03bf\u03c2 \u03b1\u03bd \u03b1\u03bd\u03b1\u03c6\u03b5\u03c1\u03b5\u03c4\u03b1\u03b9 \u03ba\u03b1\u03c4\u03b9 \u03b1\u03bb\u03bb\u03bf,\u03b7 \u03c7\u03c1\u03b7\u03c3\u03b7 \u03c4\u03b7\u03c2 \u03c4\u03b9\u03bc\u03b7\u03c2 0 \u03b1\u03c0\u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03b5\u03b9 \u03c4\u03bf\u03bd \u03ba\u03b1\u03bd\u03bf\u03bd\u03b1. ConfigView.label.directory=\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2 ConfigView.label.disconnetseed.tooltip=\u038c\u03c4\u03b1\u03bd \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf\u03c2 \u03b5\u03bd\u03cc\u03c2 torrent, \u03b1\u03c0\u03bf\u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7 \u03cc\u03c3\u03c9\u03bd \u03c0\u03b5\u03bb\u03b1\u03c4\u03c9\u03bd \u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03b6\u03bf\u03c5\u03bd \u03b5\u03c0\u03af\u03c3\u03b7\u03c2.\n\u0394\u03b5\u03bd \u03c7\u03c1\u03b5\u03b9\u03ac\u03b6\u03b5\u03c4\u03b1\u03b9 \u03bd\u03b1 \u03bc\u03b9\u03bb\u03bf\u03cd\u03bd \u03bc\u03b1\u03b6\u03af \u03c3\u03b1\u03c2. ConfigView.label.ignoreSeeds=\u0391\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7 torrents \u03bc\u03b5 \u03c4\u03bf\u03c5\u03bb\u03ac\u03c7\u03b9\u03c3\u03c4\u03bf\u03bd ConfigView.label.importdirectory=\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2 \u0395\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2 ConfigView.label.minSeedingTime.tooltip=\u039f\u03b9 \u03b8\u03ad\u03c3\u03b5\u03b9\u03c2 \u03bc\u03c0\u03bf\u03c1\u03bf\u03cd\u03bd \u03bd\u03b1 \u03ba\u03c5\u03bc\u03b1\u03af\u03bd\u03bf\u03bd\u03c4\u03b1\u03b9 \u03c3\u03c5\u03c7\u03bd\u03ac \u03c3\u03b5 \u03bc\u03b9\u03ba\u03c1\u03cc \u03c7\u03c1\u03bf\u03bd\u03b9\u03ba\u03cc \u03b4\u03b9\u03ac\u03c3\u03c4\u03b7\u03bc\u03b1, \u03c0\u03c1\u03bf\u03ba\u03b1\u03bb\u03ce\u03bd\u03c4\u03b1\u03c2 \u03bc\u03b5\u03c1\u03b9\u03ba\u03ad\u03c2 \u03c6\u03bf\u03c1\u03ad\u03c2 \u03c3\u03c4\u03bf torrent \u03c4\u03b7\u03bd \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b7 \u03b5\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b9\u03c3\u03b7, \u03ba\u03b1\u03b9 \u03ad\u03c0\u03b5\u03b9\u03c4\u03b1 \u03bc\u03cc\u03bd\u03bf \u03c4\u03b7 \u03b4\u03b9\u03b1\u03ba\u03bf\u03c0\u03ae \u03ba\u03b1\u03b9 \u03c4\u03b7 \u03bc\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ac \u03c3\u03c4\u03b7 \u03bb\u03af\u03c3\u03c4\u03b1.\n\u0391\u03c5\u03c4\u03cc \u03bc\u03b5\u03b9\u03ce\u03bd\u03b5\u03b9 \u03c4\u03bf \u03c0\u03c1\u03cc\u03b2\u03bb\u03b7\u03bc\u03b1 \u03ba\u03ac\u03bd\u03bf\u03bd\u03c4\u03b1\u03c2 \u03c4\u03bf torrent \u03bd\u03b1 \u03c3\u03c5\u03bd\u03b5\u03c7\u03af\u03c3\u03b5\u03b9 \u03c4\u03b7\u03bd \u03b1\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7 \u03b3\u03b9\u03b1 \u03ba\u03ac\u03c0\u03bf\u03b9\u03b1 \u03c7\u03c1\u03bf\u03bd\u03b9\u03ba\u03ae \u03c0\u03b5\u03c1\u03af\u03bf\u03b4\u03bf. \u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03c4\u03bf \u03c3\u03c4\u03b1\u03bc\u03b1\u03c4\u03ae\u03c3\u03b5\u03c4\u03b5 \u03ba\u03b1\u03b9 \u03b5\u03c3\u03b5\u03af\u03c2 \u03bf\u03c0\u03bf\u03b9\u03b1\u03b4\u03ae\u03c0\u03bf\u03c4\u03b5 \u03c3\u03c4\u03b9\u03b3\u03bc\u03ae \u03b5\u03c0\u03b9\u03b8\u03c5\u03bc\u03b5\u03af\u03c4\u03b5. ConfigView.label.minSeedingTime=\u0395\u03bb\u03ac\u03c7\u03b9\u03c3\u03c4\u03bf\u03c2 \u03c7\u03c1\u03cc\u03bd\u03bf\u03c2 \u03b1\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7\u03c2 \u03c3\u03b5 \u03b4\u03b5\u03c5\u03c4\u03b5\u03c1\u03cc\u03bb\u03b5\u03c0\u03c4\u03b1 ConfigView.label.minSpeedForActiveDL.tooltip=\u039c\u03af\u03b1 \u03c5\u03c0\u03bf\u03b4\u03bf\u03c7\u03ae \u03bb\u03ae\u03c8\u03b7\u03c2 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c4\u03b1\u03b9 \u03c0\u03ac\u03bd\u03c4\u03b1 \u03c4\u03b1 \u03c0\u03c1\u03ce\u03c4\u03b1 30 \u03b4\u03b5\u03c5\u03c4\u03b5\u03c1\u03cc\u03bb\u03b5\u03c0\u03c4\u03b1\n\u03cc\u03c4\u03b1\u03bd \u03ad\u03bd\u03b1 \u03bc\u03b7 \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03c9\u03bc\u03ad\u03bd\u03bf torrent \u03b5\u03ba\u03ba\u03b9\u03bd\u03ae\u03c4\u03b1\u03b9. ConfigView.label.minSpeedForActiveDL=\u039d\u03b1 \u03bc\u03b7\u03bd \u03c0\u03c1\u03bf\u03c3\u03bc\u03b5\u03c4\u03c1\u03ac\u03c4\u03b1\u03b9 \u03ad\u03bd\u03b1 torrent \u03c3\u03b1\u03bd \u03bd\u03b1 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03b5\u03af \u03bc\u03af\u03b1 \u03c5\u03c0\u03bf\u03b4\u03bf\u03c7\u03ae \u03bb\u03ae\u03c8\u03b7\u03c2 \u03b1\u03bd \u03b7 \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u03b5\u03af\u03bd\u03b1\u03b9 \u03ba\u03ac\u03c4\u03c9 \u03b1\u03c0\u03cc ConfigView.label.ratio=\u03b1\u03bd\u03b1\u03bb\u03bf\u03b3\u03af\u03b1 ConfigView.label.removeOnStop=\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae torrent \u03b1\u03c0\u03cc \u03c4\u03b7 \u03bb\u03af\u03c3\u03c4\u03b1 \u03cc\u03c4\u03b1\u03bd \u03c4\u03bf torrent \u03c3\u03c4\u03b1\u03bc\u03b1\u03c4\u03ac \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b1 ConfigView.label.savedirectory=\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2 \u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7\u03c2 ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Often, torrents with low seed counts and high peer counts means that there probably isn't a full copy amoungst the peers.\nTherefore, you may not want the seeding rules pretending there's a full copy (and thus incorrectly reducing its rank) ConfigView.label.seeding.ignoreRatioPeers=\u0394\u03b9\u03b1\u03ba\u03bf\u03c0\u03ae \u03b1\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7\u03c2 \u03ba\u03b1\u03b9 \u03b1\u03bd\u03b1\u03ba\u03b1\u03c4\u03ac\u03c4\u03b1\u03be\u03b7 \u03c3\u03c4\u03b7 \u03b2\u03ac\u03c3\u03b7 \u03c4\u03b7\u03c2 \u03bb\u03af\u03c3\u03c4\u03b1\u03c2\n\u03cc\u03c4\u03b1\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03c4\u03bf\u03c5\u03bb\u03ac\u03c7\u03b9\u03c3\u03c4\u03bf\u03bd 1 \u03b1\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7 ConfigView.label.seeding.firstPriority.info=First Priority torrents will always be at the top of the queue. Any torrents matching the First Priority criteria will not be automatically stopped and queued. A torrent matching First Priority criteria will take a Simultaneous Download slot if it needs to. ConfigView.label.stopAfterMinutes=(NI) \u038c\u03c4\u03b1\u03bd \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03b1\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7, \u03b4\u03b9\u03b1\u03ba\u03bf\u03c0\u03ae \u03bc\u03b5\u03c4\u03ac \u03b1\u03c0\u03cc\n (0 = \u0391\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7 \u03b1\u03c5\u03c4\u03bf\u03cd \u03c4\u03bf\u03c5 \u03ba\u03b1\u03bd\u03cc\u03bd\u03b1) ConfigView.label.switchpriority.tooltip=\u0397 \u03c7\u03b1\u03bc\u03b7\u03bb\u03ae \u03c0\u03c1\u03bf\u03c4\u03b5\u03c1\u03b1\u03b9\u03cc\u03c4\u03b7\u03c4\u03b1 \u03bc\u03b5\u03b9\u03ce\u03bd\u03b5\u03b9 \u03c4\u03bf\u03c5\u03c2 \u03c0\u03cc\u03c1\u03bf\u03c5\u03c2 \u03c4\u03bf\u03c5 \u03b4\u03b9\u03ba\u03c4\u03cd\u03bf\u03c5 \u03c0\u03bf\u03c5 \u03c0\u03b1\u03c1\u03b1\u03c7\u03c9\u03c1\u03bf\u03cd\u03bd\u03c4\u03b1\u03b9 \u03c3\u03c4\u03bf torrent. ConfigView.pluginlist.info=\u0392\u03c1\u03ad\u03b8\u03b7\u03ba\u03b1\u03bd \u03c4\u03b1 \u03c0\u03b1\u03c1\u03b1\u03ba\u03ac\u03c4\u03c9 \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03b1. \u039c\u03b5\u03c1\u03b9\u03ba\u03ac \u03b1\u03c0\u03cc \u03b1\u03c5\u03c4\u03ac \u03af\u03c3\u03c9\u03c2 \u03b4\u03b5\u03bd \u03ad\u03c7\u03bf\u03c5\u03bd \u03ba\u03b1\u03c1\u03c4\u03ad\u03bb\u03b5\u03c2 \u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ce\u03bd. ConfigView.pluginlist.noplugins=\u0394\u03b5\u03bd \u03b2\u03c1\u03ad\u03b8\u03b7\u03ba\u03b1\u03bd \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03b1. ConfigView.section.pluginslist=\u039b\u03af\u03c3\u03c4\u03b1 ConfigView.section.queue.main=\u039a\u03cd\u03c1\u03b9\u03b1 ConfigView.section.queue=\u0391\u03bd\u03b1\u03bc\u03bf\u03bd\u03ae ConfigView.section.torrents=Torrents ConfigView.text.ignoreRule=\u039a\u03b1\u03bd\u03cc\u03bd\u03b1\u03c2 \u0391\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7\u03c2 ConfigView.text.minutes=\u03bb\u03b5\u03c0\u03c4\u03ac ConfigView.text.neverIgnore=\u039d\u03b1 \u03bc\u03b7 \u03b3\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03c0\u03bf\u03c4\u03ad \u03b1\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7 DownloadManager.error.datamissing=\u0391\u03bd\u03cd\u03c0\u03b1\u03c1\u03ba\u03c4\u03b1 \u0394\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1 MainWindow.menu.file.open.torrentforseeding=\u0391\u03c1\u03c7\u03b5\u03af\u03bf .torrent (\u0393\u03b9\u03b1 \u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf) MainWindow.menu.language.refresh=&\u0391\u03bd\u03b1\u03bd\u03b5\u03c9\u03c3\u03b7 ManagerItem.forced=\u0395\u03be\u03b1\u03bd\u03b1\u03b3\u03ba\u03b1\u03c3\u03bc\u03cc\u03c2 ManagerItem.queued=\u0391\u03bd\u03b1\u03bc\u03bf\u03bd\u03ae \u03c3\u03b5 \u03bf\u03c5\u03c1\u03ac MySeedersView.header=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03c9\u03bc\u03ad\u03bd\u03b1/\u0394\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03b6\u03cc\u03bc\u03b5\u03bd\u03b1 Torrents TableColumn.header.availability.info=# \u03c0\u03bb\u03ae\u03c1\u03c9\u03bd \u03b1\u03bd\u03c4\u03b9\u03b3\u03c1\u03ac\u03c6\u03c9\u03bd \u03c0\u03bf\u03c5 \u03b5\u03c7\u03bf\u03c5\u03bd \u03b2\u03c1\u03b5\u03b8\u03b5\u03b9 TableColumn.header.availability=\u0394\u03b9\u03b1\u03b8\u03b5\u03c3\u03b9\u03bc\u03cc\u03c4\u03b7\u03c4\u03b1 TableColumn.header.category=\u039a\u03b1\u03c4\u03b7\u03b3\u03bf\u03c1\u03af\u03b1 MyTorrentsView.header=\u0391\u03bd\u03bf\u03bb\u03bf\u03ba\u03bb\u03ae\u03c1\u03c9\u03c4\u03b1/\u039b\u03b1\u03bc\u03b2\u03b1\u03bd\u03cc\u03bc\u03b5\u03bd\u03b1 Torrents TableColumn.header.maxuploads=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 # \u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ce\u03bd MyTorrentsView.menu.category.delete=&\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03b7 \u03ba\u03b1\u03c4\u03b7\u03b3\u03bf\u03c1\u03b9\u03b1\u03c2 MyTorrentsView.menu.forceStart=\u0395\u03be\u03b1&\u03bd\u03b1\u03b3\u03ba\u03b1\u03c3\u03bc\u03ad\u03bd\u03b7 \u0395\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 MyTorrentsView.menu.queue=&\u0391\u03bd\u03b1\u03bc\u03bf\u03bd\u03ae MyTorrentsView.menu.setCategory.add=&\u03a0\u03c1\u03bf\u03c3\u03b8\u03b7\u03ba\u03b7 \u039a\u03b1\u03c4\u03b7\u03b3\u03bf\u03c1\u03af\u03b1\u03c2... MyTorrentsView.menu.setCategory=\u039f\u03c1\u03b9\u03c3\u03bc\u03bf\u03c2 \u039a\u03b1\u03c4\u03b7\u03b3\u03bf\u03c1\u03af\u03b1\u03c2 TableColumn.header.savepath=\u0394\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae \u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7\u03c2 TableColumn.header.SeedingRank=\u039a\u03b1\u03c4\u03ac\u03c4\u03b1\u03be\u03b7 \u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03bf\u03cd TableColumn.header.totalspeed.info=\u03a3\u03c5\u03bd\u03bf\u03bb\u03b9\u03ba\u03b7 \u03c4\u03b1\u03c7\u03c5\u03c4\u03b7\u03c4\u03b1 \u03bf\u03bb\u03c9\u03bd \u03c4\u03c9\u03bd \u03bf\u03bc\u03bf\u03c4\u03b9\u03bc\u03c9\u03bd \u03c0\u03bf\u03c5 \u03b5\u03c7\u03b5\u03c4\u03b5 \u03c3\u03c5\u03bd\u03b4\u03b5\u03b8\u03b5\u03b9 TableColumn.header.totalspeed=\u03a3\u03c5\u03bd\u03bf\u03bb\u03b9\u03ba\u03ae \u03a4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 splash.initializePlugins=\u0391\u03c1\u03c7\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03c9\u03bd StartStopRules.0Peers=0 \u039f\u03bc\u03bf\u03c4\u03b9\u03bc\u03bf\u03b9 StartStopRules.numSeedsMet=# \u0393\u03bf\u03bd\u03c9\u03bd OK StartStopRules.ratioMet=\u0393\u03bf\u03bd\u03bf\u03b9:\u039f\u03bc\u03bf\u03c4\u03b9\u03bc\u03bf\u03b9 OK StartStopRules.shareRatioMet=\u0391\u03bd\u03b1\u03bb\u03bf\u03b3\u03af\u03b1 \u03c3\u03c5\u03bc\u03bc\u03b5\u03c4\u03bf\u03c7\u03ae\u03c2 OK StartStopRules.waiting=\u0391\u03bd\u03b1\u03bc\u03bf\u03bd\u03b7 StartStopRules.firstPriority=1\u03b7 \u03a0\u03c1\u03bf\u03c4\u03b5\u03c1\u03b1\u03b9\u03bf\u03c4\u03b7\u03c4\u03b1 ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03b1 \u039a\u03bf\u03b9\u03bd\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7\u03c2 (\u03ba\u03b1\u03b9 \u03a5\u03c0\u03bf\u03c6\u03ac\u03ba\u03b5\u03bb\u03bf\u03b9) DownloadManager.error.unabletostartserver=\u0394\u03b5\u03bd \u03ae\u03c4\u03b1\u03bd \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae \u03b7 \u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03c4\u03bf\u03c5 \u0394\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae - \u03b5\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03b9\u03c2 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u03b8\u03cd\u03c1\u03b1\u03c2 \u03b5\u03b9\u03c3\u03b5\u03c1\u03c7\u03cc\u03bc\u03b5\u03bd\u03c9\u03bd \u03b1\u03b9\u03c4\u03ae\u03c3\u03b5\u03c9\u03bd / \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 firewall \u03ce\u03c3\u03c4\u03b5 \u03bd\u03b1 \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03b5\u03c4\u03b1\u03b9 \u03b7 \u03b5\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae \u03bd\u03b1 \u03bb\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03b5\u03af \u03c9\u03c2 \u03b4\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae\u03c2 GeneralView.label.creationdate=\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03b8\u03b7\u03ba\u03b5 \u03c3\u03c4\u03b9\u03c2 : ManagerItem.stopping=\u0394\u03b9\u03b1\u03ba\u03cc\u03c0\u03c4\u03b5\u03c4\u03b1\u03b9 MyTrackerView.scrapes=\u0399\u03c7\u03bd\u03b7 ConfigView.section.file.max_open_files=\u039c\u03b5\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03bf\u03c2 \u03b1\u03bd\u03bf\u03b9\u03c7\u03c4\u03c9\u03bd \u03b1\u03c1\u03c7\u03b5\u03b9\u03c9\u03bd \u03b3\u03b9\u03b1 \u03b5\u03b3\u03b3\u03c1\u03b1\u03c6\u03b7/\u03b1\u03bd\u03b1\u03b3\u03bd\u03c9\u03c3\u03b7\n[0: \u03b1\u03c0\u03b5\u03c1\u03b9\u03bf\u03c1\u03b9\u03c3\u03c4\u03bf\u03c2] ConfigView.section.proxy=\u03a1\u03c5\u03b8\u03bc\u03b9\u03c3\u03b5\u03b9\u03c2 Proxy GeneralView.label.connected=\u03c3\u03c5\u03bd\u03b4\u03b5\u03b4\u03b5\u03bc\u03ad\u03bd\u03bf\u03b9 GeneralView.label.in_swarm=\u03c3\u03c4\u03bf \u03c3\u03bc\u03ae\u03bd\u03bf\u03c2 ManagerItem.initializing=\u0391\u03c1\u03c7\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 AlertMessageBox.error=\u039b\u03ac\u03b8\u03bf\u03c2 AlertMessageBox.warning=\u03a0\u03c1\u03bf\u03b5\u03b9\u03b4\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 AlertMessageBox.comment=\u03a0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b1 AlertMessageBox.information=\u03a0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b1 SharedPortServer.alert.selectorfailed=\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03b9\u03b1 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03b9\u03b1\u03c2 \u03b1\u03ba\u03c1\u03bf\u03b1\u03c4\u03b7 \u03b5\u03b9\u03c3\u03b5\u03c1\u03c7\u03bf\u03bc\u03b5\u03bd\u03c9\u03bd.\n\u0395\u03bb\u03b5\u03b3\u03be\u03c4\u03b5 \u03c3\u03c4\u03b9\u03c2 \u03c1\u03c5\u03b8\u03bc\u03b9\u03c3\u03b5\u03b9\u03c2 \u03c4\u03bf\u03c5 firewall \u03b5\u03b1\u03bd \u03b5\u03c0\u03b9\u03c4\u03c1\u03b5\u03c0\u03b5\u03c4\u03b5 \u03c4\u03bf java(w).exe \u03bd\u03b1 \u03bb\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03b5\u03b9 \u03c9\u03c2 'server' Tracker.alert.listenfail=\u0391\u03c0\u03b5\u03c4\u03c5\u03c7\u03b5 \u03b7 \u03c3\u03c5\u03b4\u03b5\u03c3\u03b7 \u03bc\u03b5 \u03c4\u03b7\u03bd \u03b8\u03c5\u03c1\u03b1 %1.\n\u0395\u03bb\u03b5\u03b3\u03be\u03c4\u03b5 \u03bf\u03c4\u03b9 \u03b4\u03b5\u03bd \u03c4\u03b7\u03bd \u03c7\u03c1\u03b7\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03bf\u03c5\u03bd \u03b7\u03b4\u03b7 \u03b1\u03bb\u03bb\u03b5\u03c2 \u03b5\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03b5\u03c2.\n\u0395\u03c0\u03b9\u03c3\u03b7\u03c2 \u03b5\u03bb\u03b5\u03b3\u03be\u03c4\u03b5 \u03bf\u03c4\u03b9 \u03b4\u03b5\u03bd \u03b5\u03ba\u03c4\u03b5\u03bb\u03b5\u03b9\u03c4\u03b5 \u03b7\u03b4\u03b7 \u03c4\u03bf Azureus. SpeedView.stats.title=\u03a3\u03c4\u03b1\u03c4\u03b9\u03c3\u03c4\u03b9\u03ba\u03b1 SpeedView.stats.total=\u03a3\u03c5\u03bd\u03bf\u03bb\u03bf SpeedView.stats.session=\u03a4\u03c9\u03c1\u03b9\u03bd\u03b7 \u03a3\u03c5\u03bd\u03bf\u03b4\u03bf\u03c2 SpeedView.stats.downloaded=\u0395\u03c7\u03bf\u03c5\u03bd \u03c0\u03b1\u03c1\u03b1\u03bb\u03b7\u03c6\u03b8\u03b5\u03b9 SpeedView.stats.uploaded=\u0395\u03c7\u03bf\u03c5\u03bd \u03b1\u03c0\u03bf\u03c3\u03c4\u03b1\u03bb\u03b5\u03b9 SpeedView.stats.uptime=\u03a7\u03c1\u03bf\u03bd\u03bf\u03c2 \u03bb\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03b9\u03b1\u03c2 # # > 2.0.8.0 # OpenTorrentWindow.title=\u0395\u03bd\u03b5\u03c1\u03b3\u03b1 Torrent(s) OpenTorrentWindow.message=\u03a0\u03b5\u03b9\u03c1\u03b1\u03bc\u03b1\u03c4\u03b9\u03ba\u03bf OpenTorrentWindow.addFiles=&\u03a0\u03c1\u03bf\u03c3\u03b8\u03b7\u03ba\u03b7 \u03b1\u03c1\u03c7\u03b5\u03b9\u03c9\u03bd OpenTorrentWindow.dataLocation=\u0398\u03b5\u03c3\u03b7 \u03b1\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03c5\u03c3\u03b7\u03c2 \u03b4\u03b5\u03b4\u03bf\u03bc\u03b5\u03bd\u03c9\u03bd: OpenTorrentWindow.startMode=\u039a\u03b1\u03c4\u03b1\u03c3\u03c4\u03b1\u03c3\u03b7 \u03a0\u03c1\u03bf\u03c3\u03b8\u03b7\u03ba\u03b7\u03c2 OpenTorrentWindow.startMode.queued=\u03a3\u03b5 \u03b1\u03bd\u03b1\u03bc\u03bf\u03bd\u03b7 OpenTorrentWindow.startMode.stopped=\u03a3\u03c4\u03b1\u03bc\u03b1\u03c4\u03b7\u03bc\u03b5\u03bd\u03bf OpenTorrentWindow.startMode.forceStarted=\u0395\u03be\u03b1\u03bd\u03b1\u03b3\u03ba\u03b1\u03c3\u03bc\u03bf\u03c2 \u03b5\u03ba\u03ba\u03b9\u03bd\u03b7\u03c3\u03b7\u03c2 OpenTorrentWindow.addPosition=\u0398\u03b5\u03c3\u03b7 \u03c3\u03c4\u03b7 \u03bb\u03b9\u03c3\u03c4\u03b1 OpenTorrentWindow.addPosition.first=\u03a3\u03c4\u03b7\u03bd \u03b1\u03c1\u03c7\u03b7 OpenTorrentWindow.addPosition.last=\u03a3\u03c4\u03bf \u03c4\u03b5\u03bb\u03bf\u03c2 TableColumn.header.remaining=\u0395\u03bd\u03b1\u03c0\u03bf\u03bc\u03ad\u03bd\u03bf\u03bd\u03c4\u03b1 ConfigView.section.file.perf=\u03a1\u03c5\u03b8\u03bc\u03b9\u03c3\u03b5\u03b9\u03c2 \u0391\u03c0\u03bf\u03b4\u03bf\u03c3\u03b7\u03c2 popup.error.hide=\u0391\u03c0\u03bf\u03ba\u03c1\u03c5\u03c8\u03b7 popup.error.details=\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2 MainWindow.status.tooOld=\u03b5\u03b9\u03bd\u03b1\u03b9 \u03c0\u03b1\u03bb\u03b9\u03bf,\u03c0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03c9 \u03b5\u03bd\u03b7\u03bc\u03b5\u03c1\u03c9\u03c3\u03c4\u03b5 \u03c4\u03bf. ConfigView.label.max_peers_per_torrent=\u039c\u03b5\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03bf\u03c2 \u03c3\u03c5\u03bd\u03b4\u03b5\u03c3\u03c9\u03bd \u03b1\u03bd\u03b1 torrent [0: \u03b1\u03c0\u03b5\u03c1\u03b9\u03bf\u03c1\u03b9\u03c3\u03c4\u03bf\u03c2] ConfigView.label.max_peers_total=\u039c\u03b5\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03bf\u03c2 \u03c3\u03c5\u03bd\u03b4\u03b5\u03c3\u03c9\u03bd \u03c3\u03c5\u03bd\u03bf\u03bb\u03b9\u03ba\u03b1 [0: \u03b1\u03c0\u03b5\u03c1\u03b9\u03bf\u03c1\u03b9\u03c3\u03c4\u03bf\u03c2] Button.revert=\u0395\u03c0\u03b1\u03bd\u03b1\u03c6\u03bf\u03c1\u03ac MyTorrentsView.menu.changeDirectory=\u0391\u03bb\u03bb\u03b1&\u03b3\u03ae \u03a6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5 \u0394\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd GenericText.column=\u03c3\u03c4\u03ae\u03bb\u03b7 MyTorrentsView.menu.thisColumn.remove=\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03b7 \u03c3\u03c4\u03b7\u03bb\u03b7\u03c2 MyTorrentsView.menu.thisColumn.toClipboard=\u0391\u03bd\u03c4\u03b9\u03b3\u03c1\u03b1\u03c6\u03b7 \u03c3\u03c4\u03bf \u03a0\u03c1\u03bf\u03c7\u03b5\u03b9\u03c1\u03bf MyTorrentsView.menu.tracker=\u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7\u03c2 swt.updater.downloader.downloading=\u0391\u03bd\u03b1\u03ba\u03c4\u03b7\u03c3\u03b7 \u03c4\u03bf\u03c5 SWT \u03b1\u03c0\u03bf swt.updater.urlsgetter.downloading=\u0391\u03bd\u03b1\u03ba\u03c4\u03b7\u03c3\u03b7 \u03bb\u03b9\u03c3\u03c4\u03b1\u03c2 \u03b1\u03bd\u03c4\u03b9\u03b3\u03c1\u03ac\u03c6\u03c9\u03bd \u03b1\u03c0\u03bf swt.updater.urlsgetter.platform=SWT \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd \u03c0\u03bb\u03b1\u03c4\u03c6\u03bf\u03c1\u03bc\u03b1 : splash.initializeGM=\u0391\u03c1\u03c7\u03b9\u03ba\u03bf\u03c0\u03bf\u03b9\u03b7\u03c3\u03b7 \u0393\u03b5\u03bd\u03b9\u03ba\u03bf\u03c5 \u0394\u03b9\u03b1\u03c7\u03b5\u03b9\u03c1\u03b9\u03c3\u03c4\u03b7 Torrents splash.loadingTorrents=\u0391\u03bd\u03ac\u03b3\u03bd\u03c9\u03c3\u03b7 \u03c4\u03c9\u03bd Torrents MyTorrentsView.menu.thisColumn.sort=\u03a4\u03b1&\u03be\u03b9\u03bd\u03bf\u03bc\u03b7\u03c3\u03b7 Scrape.status.ok=\u038a\u03c7\u03bd\u03bf\u03c2 OK Scrape.status.error=\u03a3\u03c6\u03b1\u03bb\u03bc\u03b1 \u03af\u03c7\u03bd\u03bf\u03c5\u03c2: Scrape.status.error.badURL=\u0397 \u03b4\u03b9\u03b5\u03c5\u03b8\u03c5\u03bd\u03c3\u03b7 \u03b1\u03bd\u03b1\u03ba\u03bf\u03b9\u03bd\u03c9\u03c3\u03b7\u03c2 \u03b4\u03b5\u03bd \u03b1\u03ba\u03bf\u03bb\u03bf\u03c5\u03b8\u03b5\u03b9 \u03c4\u03b1 \u03c0\u03c1\u03bf\u03c4\u03c5\u03c0\u03b1 \u03b9\u03c7\u03bd\u03bf\u03c5\u03c2. Scrape.status.error.nohash=\u03a4\u03bf \u03b1\u03bd\u03b1\u03b3\u03bd\u03c9\u03c1\u03b9\u03c3\u03c4\u03b9\u03ba\u03bf \u03bb\u03b5\u03b9\u03c0\u03b5\u03b9 \u03b1\u03c0\u03bf \u03c4\u03b7\u03bd \u03b1\u03c0\u03b1\u03bd\u03c4\u03b7\u03c3\u03b7. Scrape.status.error.invalid=\u039c\u03b7 \u03b5\u03b3\u03ba\u03c5\u03c1\u03b7 \u03b1\u03c0\u03b1\u03bd\u03c4\u03b7\u03c3\u03b7. Scrape.status.nextScrapeAt=\u0395\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf \u03af\u03c7\u03bd\u03bf\u03c2 \u03c3\u03b5 %1 Scrape.status.scraping=\u0399\u03c7\u03bd\u03b7\u03bb\u03ac\u03c4\u03b7\u03c3\u03b7... Scrape.status.initializing=\u0391\u03bd\u03b1\u03bc\u03bf\u03bd\u03ae \u03af\u03c7\u03bd\u03bf\u03c5\u03c2 MyTrackerView.webui.contextmenu.copyurl=\u0391\u03bd\u03c4\u03b9\u03b3\u03c1\u03b1\u03c6\u03b7 \u03b4\u03b9\u03b5\u03c5\u03b8\u03c5\u03bd\u03c3\u03b7\u03c2 \u03c4\u03bf\u03c5 torrent \u03c3\u03c4\u03bf \u03a0\u03c1\u03bf\u03c7\u03b5\u03b9\u03c1\u03bf Torrent.create.progress.ignoringfile=\u0391\u03b3\u03bd\u03bf\u03b7\u03c3\u03b7 \u03b1\u03c1\u03c7\u03b5\u03b9\u03bf\u03c5 Button.yes=\u039d\u03b1\u03b9 Button.no=\u038c\u03c7\u03b9 Plugin.pluginupdate.enablecheck=\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03b7\u03c3\u03b7 \u03b5\u03bb\u03b5\u03b3\u03c7\u03bf\u03c5 \u03b3\u03b9\u03b1 \u03b5\u03bd\u03b7\u03bc\u03b5\u03c1\u03c9\u03c3\u03b5\u03b9\u03c2 \u03c0\u03c1\u03bf\u03c3\u03b8\u03b5\u03c4\u03c9\u03bd plugins.basicview.status=\u039a\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7: plugins.basicview.activity=\u0394\u03c1\u03b1\u03c3\u03c4\u03b7\u03c1\u03b9\u03cc\u03c4\u03b7\u03c4\u03b1: plugins.basicview.progress=\u03a0\u03c1\u03cc\u03bf\u03b4\u03bf\u03c2: plugins.basicview.log=\u039a\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae: ConfigView.label.maxdownloadspeed=KB/s \u03c3\u03c5\u03bd\u03bf\u03bb\u03b9\u03ba\u03b7l\u03bc\u03b5\u03b3\u03b9\u03c3\u03c4\u03b7 \u03c4\u03b1\u03c7\u03c5\u03c4\u03b7\u03c4\u03b1 \u03bb\u03b7\u03c8\u03b7\u03c2 [0: \u03b1\u03c0\u03b5\u03c1\u03b9\u03bf\u03c1\u03b9\u03c3\u03c4\u03b7] splash.loadingTorrent=\u0391\u03bd\u03ac\u03b3\u03bd\u03c9\u03c3\u03b7 Torrent splash.of=\u03b1\u03c0\u03bf UpdateWindow.title=\u0395\u03bd\u03b7\u03bc\u03b5\u03c1\u03c9\u03c3\u03b7 \u03c4\u03bf\u03c5 Vuze UpdateWindow.header=\u03a4\u03b1 \u03c0\u03b1\u03c1\u03b1\u03ba\u03b1\u03c4\u03c9 \u03c3\u03c4\u03bf\u03b9\u03c7\u03b5\u03b9\u03b1 \u03c7\u03c1\u03b5\u03b9\u03b1\u03b6\u03bf\u03bd\u03c4\u03b1\u03b9 \u03b5\u03bd\u03b7\u03bc\u03b5\u03c1\u03c9\u03c3\u03b7 : UpdateWindow.columns.install=\u0395\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03b1\u03c3\u03b7 UpdateWindow.columns.name=\u039f\u03bd\u03bf\u03bc\u03b1 UpdateWindow.columns.version=\u0395\u03ba\u03b4\u03bf\u03c3\u03b7 UpdateWindow.columns.size=\u039c\u03b5\u03b3\u03b5\u03b8\u03bf\u03c2 UpdateWindow.cancel=\u0391\u03ba\u03c5\u03c1\u03c9\u03c3\u03b7 UpdateWindow.quit=\u0395\u03be\u03bf\u03b4\u03bf\u03c2 UpdateWindow.close=\u039a\u03bb\u03b5\u03b9\u03c3\u03b9\u03bc\u03bf UpdateWindow.ok=\u0395\u03bd\u03b7\u03bc\u03b5\u03c1\u03c9\u03c3\u03b7 UpdateWindow.restart=\u0395\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03b9\u03bd\u03b7\u03c3\u03b7 UpdateWindow.status.downloading=\u0391\u03bd\u03b1\u03ba\u03c4\u03b7\u03c3\u03b7 UpdateWindow.status.done=\u0395\u03c4\u03bf\u03b9\u03bc\u03bf UpdateWindow.status.failed=\u0391\u03c0\u03b5\u03c4\u03c5\u03c7\u03b5 UpdateWindow.status.restartNeeded=\u0398\u03b1 \u03c7\u03c1\u03b5\u03b9\u03b1\u03c3\u03c4\u03b5\u03b9 \u03b5\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03b9\u03bd\u03b7\u03c3\u03b7! ConfigView.pluginlist.broken=\u03a7\u03b1\u03bb\u03b1\u03c3\u03bc\u03ad\u03bd\u03bf ConfigView.pluginlist.whereToPut=\u03a4\u03bf\u03c0\u03bf\u03b8\u03b5\u03c4\u03b7\u03c3\u03c4\u03b5 \u03bf\u03c0\u03bf\u03b9\u03b1\u03b4\u03b7\u03c0\u03bf\u03c4\u03b5 \u03b1\u03c4\u03bf\u03bc\u03b9\u03ba\u03b1 \u03c3\u03b1\u03c2 \u03c0\u03c1\u03bf\u03c3\u03b8\u03b5\u03c4\u03b1 \u03c3\u03c4\u03bf \u03b4\u03b9\u03ba\u03bf \u03c4\u03bf\u03c5\u03c2 \u03c6\u03b1\u03ba\u03b5\u03bb\u03bf \u03c3\u03c4\u03bf: ConfigView.pluginlist.whereToPutOr=\u0393\u03b9\u03b1 \u03ba\u03bf\u03b9\u03bd\u03bf\u03c7\u03c1\u03b7\u03c3\u03c4\u03b1 \u03c0\u03c1\u03bf\u03c3\u03b8\u03b5\u03c4\u03b1 \u03c7\u03c1\u03b7\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03b7\u03c3\u03b5: MainWindow.statusText.checking=\u0395\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03b3\u03b9\u03b1 \u03bd\u03b5\u03b1 \u03b5\u03ba\u03b4\u03bf\u03c3\u03b7 TableColumn.header.OnlyCDing4=\u039c\u03cc\u03bd\u03bf \u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03bc\u03cc\u03c2 UpdateWindow.status.restartMaybeNeeded=\u0399\u03c3\u03c9\u03c2 \u03c7\u03c1\u03b5\u03b9\u03b1\u03c3\u03c4\u03b5\u03b9 \u03b5\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03b9\u03bd\u03b7\u03c3\u03b7 ConfigView.pluginlist.shared=\u039a\u03bf\u03b9\u03bd\u03bf\u03c7\u03c1\u03b7\u03c3\u03c4\u03bf MainWindow.menu.help.whatsnew=\u03a4\u03b9 \u03bd\u03b5\u03bf \u03c5\u03c0\u03b1\u03c1\u03c7\u03b5\u03b9 ConfigView.label.checkonstart=\u0395\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03b3\u03b9\u03b1 \u03b5\u03bd\u03b7\u03bc\u03b5\u03c1\u03c9\u03bc\u03b5\u03bd\u03b7 \u03b5\u03ba\u03b4\u03bf\u03c3\u03b7 \u03c4\u03bf\u03c5 Vuze \u03ba\u03b1\u03c4\u03b1 \u03c4\u03b7\u03bd \u03b5\u03ba\u03ba\u03b9\u03bd\u03b7\u03c3\u03b7 ConfigView.label.periodiccheck=\u03a0\u03b5\u03c1\u03b9\u03bf\u03b4\u03b9\u03ba\u03bf\u03c2 \u03b5\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03c4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03b9\u03b1\u03c2 \u03b5\u03ba\u03b4\u03bf\u03c3\u03b7\u03c2 MainWindow.updateavail=(\u0394\u03b9\u03b1\u03b8\u03ad\u03c3\u03b9\u03bc\u03b7 \u03bd\u03ad\u03b1 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7) MainWindow.status.latestversionunchecked=\u039f \u03b5\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03b5\u03ba\u03b4\u03bf\u03c3\u03b5\u03c9\u03bd \u03b5\u03c7\u03b5\u03b9 \u03b1\u03c0\u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03b7\u03b8\u03b5\u03b9 StartStopRules.menu.viewDebug=\u03a0\u03c1\u03bf\u03b2\u03bf\u03bb\u03b7 \u03c0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03b9\u03c9\u03bd \u03b5\u03ba\u03c3\u03c6\u03b1\u03bb\u03bc\u03b1\u03c4\u03c9\u03c3\u03b7\u03c2 MainWindow.menu.help.plugins=\u03a0\u03c1\u03bf\u03c3\u03b8\u03b5\u03c4\u03b1 health.explain.share=\u03a3\u03b7\u03bc\u03b1\u03b9\u03bd\u03b5\u03b9 \u03bf\u03c4\u03b9 \u03c4\u03bf torrent \u03b5\u03af\u03c4\u03b5 \u03c4\u03bf \u03c6\u03b9\u03bb\u03bf\u03be\u03b5\u03bd\u03b5\u03af\u03c4\u03b5 \u03b5\u03af\u03c4\u03b5 \u03c4\u03bf \u03ad\u03c7\u03b5\u03c4\u03b5 \u03b4\u03b7\u03bc\u03bf\u03c3\u03b9\u03b5\u03cd\u03b5\u03b9. GeneralView.label.maxdownloadspeed=\u039c\u03b5\u03b3. \u03a4\u03b1\u03c7. \u039b\u03ae\u03c8\u03b7\u03c2 GeneralView.label.maxdownloadspeed.tooltip=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03b7 \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u03bb\u03ae\u03c8\u03b7\u03c2 [0: \u03b1\u03c0\u03b5\u03c1\u03b9\u03cc\u03c1\u03b9\u03c3\u03c4\u03b7] upnp.enable=\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03b7\u03c3\u03b7 \u03c4\u03bf\u03c5 UPnP upnp.info=\u03a4\u03bf Universal Plug and Play (UPnP) \u03b5\u03c0\u03b9\u03c4\u03c1\u03b5\u03c0\u03b5\u03b9 \u03c4\u03b7\u03bd \u03b1\u03c5\u03c4\u03bf\u03bc\u03b1\u03c4\u03b7 \u03b1\u03bd\u03c4\u03b9\u03c3\u03c4\u03bf\u03b9\u03c7\u03b9\u03c3\u03b7 \u03b8\u03c5\u03c1\u03c9\u03bd \u03c3\u03b5 \u03c3\u03c5\u03c3\u03ba\u03b5\u03c5\u03b5\u03c2 \u03c0\u03bf\u03c5 \u03c4\u03bf \u03c5\u03c0\u03bf\u03c3\u03c4\u03b7\u03c1\u03b9\u03b6\u03bf\u03c5\u03bd. upnp.mapping.dataport=\u0395\u03b9\u03c3\u03b5\u03c1\u03c7\u03bf\u03bc\u03b5\u03bd\u03b7 \u03b8\u03c5\u03c1\u03b1 \u0394\u03b5\u03b4\u03bf\u03bc\u03b5\u03bd\u03c9\u03bd upnp.mapping.tcptrackerport=TCP \u0398\u03c5\u03c1\u03b1 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 upnp.mapping.udptrackerport=UDP \u0398\u03c5\u03c1\u03b1 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 upnp.alert.differenthost=UPnP: \u0397 \u03b1\u03bd\u03c4\u03b9\u03c3\u03c4\u03bf\u03b9\u03c7\u03b9\u03c3\u03b7 \u03b8\u03c5\u03c1\u03b1\u03c2 '%1' \u03c3\u03bd\u03b7\u03ba\u03b5\u03b9 \u03c4\u03bf\u03bd '%2' - \u03c0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03c9 \u03b4\u03b9\u03b1\u03bb\u03b5\u03be\u03c4\u03b5 \u03b1\u03bb\u03bb\u03b7 \u03b8\u03c5\u03c1\u03b1 upnp.alert.mappingok=UPnP: \u0391\u03bd\u03c4\u03b9\u03c3\u03c4\u03bf\u03b9\u03c7\u03b9\u03c3\u03b7 \u03b8\u03c5\u03c1\u03b1\u03c2 '%1' \u03b5\u03c0\u03b9\u03c4\u03c5\u03c7\u03ae\u03c2 upnp.alert.mappingfailed=UPnP: \u0391\u03bd\u03c4\u03b9\u03c3\u03c4\u03bf\u03b9\u03c7\u03b9\u03c3\u03b7 \u03b8\u03c5\u03c1\u03b1\u03c2 '%1' \u03b1\u03c0\u03b5\u03c4\u03c5\u03c7\u03b5 upnp.alertsuccess=\u0391\u03bd\u03b1\u03c6\u03bf\u03c1\u03b1 \u03b5\u03c0\u03b9\u03c4\u03c5\u03c7\u03c9\u03bd \u03b1\u03bd\u03c4\u03b9\u03c3\u03c4\u03bf\u03b9\u03c7\u03b9\u03c3\u03b5\u03c9\u03bd upnp.alert.lostdevice=UPnP: \u03a7\u03b1\u03b8\u03b7\u03ba\u03b5 \u03b7 \u03c3\u03c5\u03bd\u03b4\u03b5\u03c3\u03b7 \u03bc\u03b5 \u03c4\u03b7\u03bd \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03b9\u03b1 '%1' \u03c3\u03c4\u03b7 \u03c3\u03c5\u03c3\u03ba\u03b5\u03c5\u03b7 UPnP '%2' upnp.grabports=\u0391\u03bd\u03c4\u03b9\u03c3\u03c4\u03bf\u03b9\u03c7\u03b9\u03c3\u03b7 \u03b8\u03c5\u03c1\u03c9\u03bd \u03b1\u03ba\u03bf\u03bc\u03b1 \u03ba\u03b1\u03b9 \u03b1\u03bd \u03b1\u03bd\u03b7\u03ba\u03bf\u03c5\u03bd \u03c3\u03b5 \u03b1\u03bb\u03bb\u03bf \u03c5\u03c0\u03bf\u03bb\u03bf\u03b3\u03b9\u03c3\u03c4\u03b7 upnp.refresh.label=\u0391\u03bd\u03b1\u03bd\u03b5\u03c9\u03c3\u03b7 \u03c4\u03c9\u03bd \u03b1\u03bd\u03c4\u03b9\u03c3\u03c4\u03bf\u03b9\u03c7\u03b9\u03c3\u03b5\u03c9\u03bd upnp.refresh.button=\u0391\u03bd\u03b1\u03bd\u03b5\u03c9\u03c3\u03b7 upnp.alert.mappinggrabbed=UPnP: \u0391\u03bd\u03c4\u03b9\u03c3\u03c4\u03bf\u03b9\u03c7\u03b9\u03c3\u03b7 \u03b8\u03c5\u03c1\u03b1\u03c2 '%1' \u03b5\u03c0\u03b9\u03c4\u03c5\u03c7\u03ae\u03c2 - \u0391\u03bd\u03b7\u03ba\u03b5 \u03c3\u03c4\u03bf\u03bd '%2' upnp.mapping.tcpssltrackerport=TCP SSL \u0398\u03c5\u03c1\u03b1 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 upnp.alertothermappings=\u0391\u03bd\u03b1\u03c6\u03bf\u03c1\u03b1 \u03b8\u03c5\u03c1\u03c9\u03bd \u03c0\u03bf\u03c5 \u03b1\u03bd\u03b7\u03ba\u03bf\u03c5\u03bd \u03c3\u03b5 \u03b1\u03bb\u03bb\u03bf \u03c5\u03c0\u03bf\u03bb\u03bf\u03b3\u03b9\u03c3\u03c4\u03b7 upnp.alertdeviceproblems=\u0391\u03bd\u03b1\u03c6\u03bf\u03c1\u03b1 \u03c0\u03c1\u03bf\u03b2\u03bb\u03b7\u03bc\u03b1\u03c4\u03c9\u03bd \u03bc\u03b5 \u03c4\u03b7 \u03c3\u03c5\u03c3\u03ba\u03b5\u03c5\u03b7 UPnP ConfigView.pluginlist.coreplugins=\u03a4\u03b1 \u03b1\u03ba\u03bf\u03bb\u03bf\u03c5\u03b8\u03b1 \u03c0\u03c1\u03bf\u03c3\u03b8\u03b5\u03c4\u03b1 \u03b5\u03b9\u03bd\u03b1\u03b9 \u03b5\u03bd\u03b5\u03c1\u03b3\u03b1: upnp.releasemappings=\u0391\u03c0\u03b5\u03bb\u03b5\u03c5\u03b8\u03ad\u03c1\u03c9\u03c3\u03b7 \u03c4\u03c9\u03bd \u03b1\u03bd\u03c4\u03b9\u03c3\u03c4\u03bf\u03b9\u03c7\u03b9\u03c3\u03b5\u03c9\u03bd \u03ba\u03b1\u03c4\u03b1 \u03c4\u03b7\u03bd \u03b5\u03be\u03bf\u03b4\u03bf ConfigView.section.file.friendly.hashchecking=\u03a6\u03b9\u03bb\u03b9\u03ba\u03bf\u03c2 \u03b5\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03b1\u03bd\u03b1\u03b3\u03bd\u03c9\u03c1\u03b9\u03c3\u03c4\u03b9\u03ba\u03c9\u03bd ConfigView.section.file.friendly.hashchecking.tooltip=\u0395\u03bd\u03b1\u03c2 \u03bb\u03b9\u03b3\u03bf \u03c0\u03b9\u03bf \u03b1\u03c1\u03b3\u03bf\u03c2 \u03b1\u03bb\u03bb\u03b1 \u03ba\u03b1\u03b9 \u03bb\u03b9\u03b3\u03bf\u03c4\u03b5\u03c1\u03bf \u03b5\u03c0\u03b9\u03b2\u03b1\u03c1\u03c5\u03bd\u03c4\u03b9\u03ba\u03bf\u03c2 \u03b3\u03b9\u03b1 \u03c4\u03bf \u03c3\u03c5\u03c3\u03c4\u03b7\u03bc\u03b1 \u03c4\u03c1\u03bf\u03c0\u03bf\u03c2 \u03b5\u03bb\u03b5\u03b3\u03c7\u03bf\u03c5 \u03c4\u03c9\u03bd \u03b1\u03bd\u03b1\u03b3\u03bd\u03c9\u03c1\u03b9\u03c3\u03c4\u03b9\u03ba\u03c9\u03bd. Button.clear=\u039a\u03b1\u03b8\u03b1\u03c1\u03b9\u03c3\u03bc\u03cc\u03c2 MainWindow.IPs.tooltip=\u0391\u03c1\u03b9\u03b8\u03bc\u03cc\u03c2 \u03c0\u03b5\u03b4\u03af\u03c9\u03bd \u03c3\u03c4\u03b7 \u03bb\u03af\u03c3\u03c4\u03b1 \u03c6\u03af\u03bb\u03c4\u03c1\u03bf\u03c5 IP - \u0391\u03c1\u03b9\u03b8\u03bc\u03cc\u03c2 \u03c4\u03c9\u03bd \u03c0\u03c1\u03b1\u03b3\u03bc\u03b1\u03c4\u03b9\u03ba\u03ac \u03bc\u03c0\u03bb\u03bf\u03ba\u03b1\u03c1\u03b9\u03c3\u03bc\u03ad\u03bd\u03c9\u03bd IP.\n\u0394\u03b9\u03c0\u03bb\u03cc \u03ba\u03bb\u03b9\u03ba \u03b3\u03b9\u03b1 \u03bb\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2. ConfigView.section.ipfilter.list.banned=has been banned for sending bad data Button.reset=\u0391\u03c1\u03c7\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 download.removerules.unauthorised.info=Unauthorised torrents are those where the announce response contains either "not authoris(z)ed" or "unauthoris(z)ed" in the "failure response" download.removerules.unauthorised=Automatically remove unauthorised torrents ConfigView.label.defaultstarttorrentsstopped=\u03a0\u03c1\u03bf\u03c3\u03b8\u03b7\u03ba\u03b7 \u03bd\u03b5\u03c9\u03bd torrents \u03c3\u03b5 \u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03b1\u03c3\u03b7 \u03bc\u03b7 \u03b5\u03bd\u03b5\u03c1\u03b3\u03b7 ConfigView.section.server.enableudp=Enable UDP tracker client protocol. upnp.mapping.dataportudp=UDP \u0398\u03c5\u03c1\u03b1 \u03a0\u03b5\u03bb\u03b1\u03c4\u03b7 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 MainWindow.status.updowndetails.tooltip=\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03b5\u03c1\u03b5\u03b9\u03b5\u03c2 \u03c4\u03b1\u03c7\u03c5\u03c4\u03b7\u03c4\u03b1\u03c2 \u039b\u03b7\u03c8\u03b7\u03c2/\u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03b7\u03c2 - \u0391\u03bb\u03bb\u03b1\u03be\u03c4\u03b5 \u03c4\u03b9\u03c2 \u03bc\u03b5 \u03b4\u03b5\u03be\u03b9 \u03ba\u03bb\u03b9\u03ba TrackerClient.announce.warningmessage=\u039f \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7\u03c2 \u03c4\u03bf\u03c5 '%1' \u03b5\u03c0\u03b5\u03c3\u03c4\u03c1\u03b5\u03c8\u03b5 \u03c0\u03c1\u03bf\u03b5\u03b9\u03b4\u03bf\u03c0\u03bf\u03b9\u03b7\u03c3\u03b7 '%2' ConfigView.section.tracker.publishenabledetails=\u0394\u03b7\u03bc\u03bf\u03c3\u03af\u03b5\u03c5\u03c3\u03b7 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 torrent \u03ba\u03b1\u03b9 \u03bb\u03b5\u03c0\u03c4\u03bf\u03bc\u03b5\u03c1\u03b9\u03ce\u03bd \u03c3\u03c5\u03bd\u03b4\u03ad\u03c3\u03b5\u03c9\u03bd #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=&\u039c\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ad\u03c2 MainWindow.menu.transfers.startalltransfers=&\u0395\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03b9\u03bd\u03b7\u03c3\u03b7 \u03bf\u03bb\u03c9\u03bd MainWindow.menu.transfers.stopalltransfers=&\u0394\u03b9\u03b1\u03ba\u03bf\u03c0\u03b7 \u03bf\u03bb\u03c9\u03bd MainWindow.menu.transfers.pausetransfers=\u03a0&\u03b1\u03c5\u03c3\u03b7 MainWindow.menu.transfers.resumetransfers=\u0395&\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03b9\u03bd\u03b7\u03c3\u03b7 SystemTray.menu.pausetransfers=\u03a0\u03b1\u03cd&\u03c3\u03b7 \u039b\u03ae\u03c8\u03b5\u03c9\u03bd SystemTray.menu.resumetransfers=\u0395\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af&\u03bd\u03b7\u03c3\u03b7 \u039b\u03ae\u03c8\u03b5\u03c9\u03bd PeerManager.status.error=\u03a3\u03c6\u03b1\u03bb\u03bc\u03b1 Stats.title.full=\u03a3\u03c4\u03b1\u03c4\u03b9\u03c3\u03c4\u03b9\u03ba\u03ac TransferStatsView.title.full=\u039c\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ad\u03c2 CacheView.title.full=\u039c\u03bd\u03ae\u03bc\u03b7 Cache CacheView.general.size=\u03a3\u03c5\u03bd\u03bf\u03bb\u03b9\u03ba\u03cc \u039c\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 CacheView.general.inUse=\u03a3\u03b5 \u03c7\u03c1\u03ae\u03c3\u03b7 CacheView.general.title=\u03a0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 \u03bc\u03bd\u03ae\u03bc\u03b7\u03c2 cache CacheView.reads.title=\u0391\u03bd\u03b1\u03b3\u03bd\u03ce\u03c3\u03b5\u03b9\u03c2 I/O CacheView.reads.fromFile=\u0391\u03c0\u03bf \u0391\u03c1\u03c7\u03b5\u03af\u03bf CacheView.reads.fromCache=\u0391\u03c0\u03bf Cache CacheView.reads.hits=\u0395\u03c0\u03b9\u03c4\u03c5\u03c7\u03af\u03b1 CacheView.writes.title=\u0395\u03b3\u03b3\u03c1\u03b1\u03c6\u03ad\u03c2 I/O CacheView.writes.toCache=\u03a0\u03c1\u03bf\u03c2 Cache CacheView.writes.toFile=\u03a0\u03c1\u03cc\u03c2 \u0391\u03c1\u03c7\u03b5\u03af\u03bf CacheView.writes.hits=\u0395\u03c0\u03b9\u03c4\u03c5\u03c7\u03af\u03b1 CacheView.speeds.title=\u03a1\u03c5\u03b8\u03bc\u03bf\u03af \u039c\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ac\u03c2 CacheView.speeds.reads=\u0391\u03bd\u03b1\u03b3\u03bd\u03ce\u03c3\u03b7 CacheView.speeds.writes=\u0395\u03b3\u03b3\u03c1\u03b1\u03c6\u03ae CacheView.speeds.fromCache=\u0391\u03c0\u03bf/\u03a0\u03c1\u03bf\u03c2 Cache CacheView.speeds.fromFile=\u0391\u03c0\u03bf/\u03a0\u03c1\u03bf\u03c2 \u0391\u03c1\u03c7\u03b5\u03af\u03bf CacheView.reads.amount=\u03a0\u03bf\u03c3\u03cc\u03c4\u03b7\u03c4\u03b1 CacheView.reads.avgsize=\u039c\u03ad\u03c3\u03bf \u03bc\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 ConfigView.label.maxuploadspeedseeding=KB/s \u03c3\u03c5\u03bd\u03bf\u03bb\u03b9\u03ba\u03b7l\u03bc\u03b5\u03b3\u03b9\u03c3\u03c4\u03b7 \u03c4\u03b1\u03c7\u03c5\u03c4\u03b7\u03c4\u03b1 \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03b7\u03c2 \u03bf\u03c4\u03b1\u03bd \u03bc\u03bf\u03bd\u03bf \u03b4\u03b9\u03b1\u03bc\u03bf\u03b9\u03c1\u03b1\u03b6\u03b5\u03c4\u03b5 [0: \u03b1\u03c0\u03b5\u03c1\u03b9\u03bf\u03c1\u03b9\u03c3\u03c4\u03b7] PiecesView.legend.written=\u0391\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03c5\u03c4\u03b7\u03ba\u03b1\u03bd PiecesView.legend.requested=\u0396\u03b7\u03c4\u03b7\u03b8\u03b7\u03ba\u03b1\u03bd PiecesView.legend.downloaded=\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03c9\u03b8\u03b7\u03ba\u03b5, \u03b1\u03bd\u03b1\u03bc\u03b5\u03bd\u03b5\u03c4\u03b1\u03b9 \u03b7 \u03b5\u03b3\u03b3\u03c1\u03b1\u03c6\u03b7 PiecesView.legend.incache=\u03a4\u03b1 \u03b4\u03b5\u03b4\u03bf\u03bc\u03b5\u03bd\u03b1 \u03b5\u03b9\u03bd\u03b1\u03b9 \u03c3\u03c4\u03b7\u03bd Cache PiecesView.typeItem.0=\u0391\u03c1\u03b3\u03bf PiecesView.typeItem.1=\u0393\u03c1\u03b7\u03b3\u03bf\u03c1\u03bf PiecesView.type=\u03a4\u03c5\u03c0\u03bf\u03c2 ConfigView.section.connection.network.max.simultaneous.connect.attempts=\u039c\u03b5\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03bf\u03c2 \u03b5\u03be\u03b5\u03c1\u03c7\u03bf\u03bc\u03b5\u03bd\u03c9\u03bd \u03c0\u03c1\u03bf\u03c3\u03c0\u03b1\u03b8\u03b5\u03b9\u03c9\u03bd \u03c3\u03c5\u03bd\u03b4\u03b5\u03c3\u03b7\u03c2 ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=\u039c\u03b5\u03b3\u03b9\u03c3\u03c4\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03bf\u03c2 \u03b5\u03be\u03b5\u03c1\u03c7\u03bf\u03bc\u03b5\u03bd\u03c9\u03bd \u03c0\u03c1\u03bf\u03c3\u03c0\u03b1\u03b8\u03b5\u03b9\u03c9\u03bd \u03c3\u03c5\u03bd\u03b4\u03b5\u03c3\u03b7\u03c2 \u03c0\u03bf\u03c5 \u03b8\u03b1 \u03ba\u03b1\u03bd\u03b5\u03b9 \u03c4\u03bf Vuze \u03bf\u03c0\u03bf\u03b9\u03b1\u03b4\u03b7\u03c0\u03bf\u03c4\u03b5 \u03c3\u03c4\u03b9\u03b3\u03bc\u03b7.\n\u03a3\u0397\u039c\u0395\u0399\u03a9\u03a3\u0397:\u03a4\u03bf Service Pack 2 (SP2) \u03c4\u03c9\u03bd Windows XP \u03b2\u03b1\u03b6\u03b5\u03b9 \u03b5\u03bd\u03b1 \u03bf\u03c1\u03b9\u03bf \u03c4\u03c9\u03bd 10 \u03c4\u03b1\u03c5\u03c4\u03bf\u03c7\u03c1\u03bf\u03bd\u03c9\u03bd \u03c0\u03c1\u03bf\u03c3\u03c0\u03b1\u03b8\u03b5\u03b9\u03c9\u03bd \u03c3\u03c5\u03bd\u03b4\u03b5\u03c3\u03b7\u03c2.\n\u0397 \u03b5\u03be \u03bf\u03c1\u03b9\u03c3\u03bc\u03bf\u03c5 \u03c4\u03b9\u03bc\u03b7 \u03b5\u03b9\u03bd\u03b1\u03b9 8. ConfigView.section.file.perf.cache.size.explain=The cache is used to reduce reads from/writes to disk. Unless you are using the java option '-XX:MaxDirectMemorySize' to explicitly set the memory available for cache and network IO use, you should keep this value at least %1 below your maximum VM size. The current maximum VM size is %2. For instructions on how to change this, see MemoryUsage in the wiki on %3. Failure to use sensible settings will result on 'out of memory' errors. More than 32MB of cache is probably overkill. GeneralView.label.maxuploadspeed=\u039c\u03b5\u03b3. \u03a4\u03b1\u03c7. \u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 GeneralView.label.maxuploadspeed.tooltip=\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03b7 \u03c4\u03b1\u03c7\u03cd\u03c4\u03b7\u03c4\u03b1 \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 [0: \u03b1\u03c0\u03b5\u03c1\u03b9\u03cc\u03c1\u03b9\u03c3\u03c4\u03b7] MyTorrents.items.UpSpeedLimit.disabled=\u03a7\u03c9\u03c1\u03af\u03c2 \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae MyTorrents.items.UpSpeedLimit.unlimited=\u0391\u03c0\u03b5\u03c1\u03b9\u03cc\u03c1\u03b9\u03c3\u03c4\u03b7 TableColumn.header.maxupspeed=\u039c\u03b5\u03b3.\u03a4\u03b1\u03c7.\u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 TableColumn.header.maxupspeed.info=\u039c\u03b5\u03b3.\u03a4\u03b1\u03c7.\u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2 \u03b1\u03bd\u03b1 torrent MainWindow.menu.tools=&\u0395\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03b1 FilesView.path=\u0394\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae FilesView.fullpath=\u0395\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 \u03c0\u03bb\u03ae\u03c1\u03bf\u03c5\u03c2 \u03b4\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae\u03c2 FilesView.remaining=\u0391\u03c0\u03bf\u03bc\u03ad\u03bd\u03bf\u03bd\u03c4\u03b1 \u03ba\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9\u03b1 TableColumn.header.trackername=\u038c\u03bd\u03bf\u03bc\u03b1 \u03b9\u03c7\u03bd\u03b7\u03bb\u03ac\u03c4\u03b7 TableColumn.header.trackername.info=\u039f\u03bd\u03bf\u03bc\u03b1 \u0399\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 \u03bc\u03b5 \u03b2\u03b1\u03c3\u03b7 \u03c4\u03b7 \u03b4\u03b9\u03b5\u03c5\u03b8\u03c5\u03bd\u03c3\u03b7 \u03b1\u03bd\u03b1\u03ba\u03bf\u03b9\u03bd\u03c9\u03c3\u03b7\u03c2 ConfigView.group.override=\u0391\u03b3\u03bd\u03bf\u03b7\u03c3\u03b7 \u03c1\u03c5\u03b8\u03bc\u03b9\u03c3\u03b5\u03c9\u03bd ConfigView.label.overrideip=\u0391\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7\u03c2 IP \u03c0\u03bf\u03c5 \u03b1\u03c0\u03bf\u03c3\u03c4\u03ac\u03bb\u03b8\u03b7\u03ba\u03b5 \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03c0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03cd\u03b8\u03b7\u03c3\u03b7 \u03b1\u03bb\u03bb\u03b1\u03b3\u03ce\u03bd\n - \u03a7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03c4\u03b5 \u03c4\u03bf \u03bc\u03cc\u03bd\u03bf \u03b1\u03bd \u03c0\u03c1\u03b1\u03b3\u03bc\u03b1\u03c4\u03b9\u03ba\u03ac \u03be\u03ad\u03c1\u03b5\u03c4\u03b5 \u03b3\u03b9\u03b1 \u03c0\u03b9\u03bf \u03bb\u03cc\u03b3\u03bf \u03c4\u03bf \u03c7\u03c1\u03b5\u03b9\u03ac\u03b6\u03b5\u03c3\u03c4\u03b5! ConfigView.label.overrideip.tooltip=Inform the tracker of a different IP address than the one outgoing packets come from. Leave blank not to use the option. #file can be a URL or a path in the jar diagnostics.log_found=Vuze did not shutdown tidily. Please check %1 for diagnostic log files and consider reporting them to the Vuze team if this is the result of an application error. # %1 = "in kbps" or ""; %2 = "upload" or "download" OpenTorrentWindow.torrentLocation=\u0391\u03c1\u03c7\u03b5\u03b9\u03b1 Torrent: Button.moveUp=\u039c\u03b5\u03c4\u03b1\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03a0\u03ac\u03bd\u03c9 Button.moveDown=\u039c\u03b5\u03c4\u03b1\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u039a\u03ac\u03c4\u03c9 # > 2402 #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} # # Used for peers which we can't determine. PeerSocket.unknown=\u0386\u03b3\u03bd\u03c9\u03c3\u03c4\u03bf ConfigView.label.announceport=\u0391\u03bb\u03bb\u03b1\u03b3\u03b7 \u03b8\u03c5\u03c1\u03b1\u03c2 \u03b1\u03bd\u03b1\u03ba\u03bf\u03b9\u03bd\u03c9\u03c3\u03b5\u03c9\u03bd \u03b9\u03c7\u03bd\u03b7\u03bb\u03b1\u03c4\u03b7 #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences iconBar.queue.tooltip=\u039b\u03af\u03c3\u03c4\u03b1 MainWindow.menu.help.faq=&\u03a3\u03c5\u03c7\u03bd\u03ad\u03c2 \u0395\u03c1\u03c9\u03c4\u03ae\u03c3\u03b5\u03b9\u03c2 #what you've watched? Discover more with a single click... MainWindow.menu.help.donate=&\u039a\u03ac\u03bd\u03c4\u03b5 \u03bc\u03af\u03b1 \u0394\u03c9\u03c1\u03b5\u03b1(2\u20ac,5\u20ac,...) azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_pt_BR.properties0000644000175000017500000061064211301156004026106 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Arquivo Torrent... Main.parameter.usage=Uso : java org.gudy.azureus2.cl.Main [par\u00e2metros] "arquivo.torrent" "caminho para salvar" Main.parameter.maxUploads=N\u00ba m\u00e1ximo de uploads simult\u00e2neos Main.parameter.maxSpeed=Velocidade m\u00e1xima de upload em bytes/seg MainWindow.menu.file=&Arquivo MainWindow.menu.file.open=&Abrir MainWindow.menu.file.create=&Novo Torrent... MainWindow.menu.file.create.fromfile=De um &Arquivo MainWindow.menu.file.create.fromdir=De um &Diret\u00f3rio MainWindow.menu.file.export=&Exportar Torrent XML... MainWindow.menu.file.import=&Importar Torrent XML... MainWindow.menu.file.closetab=Fechar &Aba MainWindow.menu.file.closewindow=Fechar &Janela MainWindow.menu.file.exit=Sai&r MainWindow.dialog.choose.file=Escolha o arquivo torrent MainWindow.menu.file.folder=&Pasta... MainWindow.dialog.choose.folder=Escolha o diret\u00f3rio contendo os arquivos torrent MainWindow.menu.view=&Visualizar MainWindow.menu.view.show=Mostrar MainWindow.menu.view.mytorrents=&Meus Torrents MainWindow.menu.view.open_global_transfer_bar=Barra de Transfer\u00eancias MainWindow.menu.view.configuration=&Op\u00e7\u00f5es... MainWindow.menu.view.console=C&onsole MainWindow.menu.view.allpeers=Todos os Peers MainWindow.menu.view.detailedlist=&Lista Detalhada MainWindow.menu.closealldetails=Fechar &Todos os Detalhes MainWindow.menu.closealldownloadbars=Fechar Todas as &Barras de Download MainWindow.menu.language=&Idioma ConfigView.section.language=Idioma MainWindow.menu.window=&Janela MainWindow.menu.window.minimize=&Minimizar MainWindow.menu.window.alltofront=Trazer Todos para a &Frente MainWindow.menu.help=&Ajuda MainWindow.menu.help.about=Sobre o Vuze MainWindow.about.title=Sobre MainWindow.about.section.developers=Desenvolvedores MainWindow.about.section.translators=Tradutores MainWindow.about.section.system=Sistema MainWindow.about.section.internet=Internet MainWindow.about.internet.homepage=Home page do Vuze MainWindow.about.internet.sourceforge=P\u00e1gina do Projeto no Sourceforge MainWindow.about.internet.sourceforgedownloads=Downloads do Sourceforge MainWindow.about.internet.bugreports=Relatar Bugs MainWindow.about.internet.forumdiscussion=F\u00f3runs MainWindow.about.internet.wiki=FAQ e Wiki do Vuze MainWindow.dialog.choose.savepath=Escolha o caminho para salvar MainWindow.dialog.choose.savepath_forallfiles=Escolha o caminho para salvar TODOS os arquivos MainWindow.status.latestversion=Mais Recentes MainWindow.status.latestversion.clickupdate=Clique para atualizar MainWindow.status.unknown=desconhecido MainWindow.status.checking=verificando MyTorrentsView.mytorrents=Meus Torrents TableColumn.header.name=Nome TableColumn.header.size=Tamanho TableColumn.header.done=Feito TableColumn.header.done.info=Porcentagem feita da tarefa atual TableColumn.header.status.info=O que o torrent est\u00e1 fazendo TableColumn.header.seeds.info=# seeds conectados para (# seeds no total) TableColumn.header.peers.info=# peers conectados a (# peers no total) TableColumn.header.completed=Completados TableColumn.header.completed.info=# dos peers que terminaram de baixar o torrent como reportado pelo tracker TableColumn.header.downspeed=Velocidade de Down TableColumn.header.upspeed=Velocidade de Up TableColumn.header.eta=TEC TableColumn.header.tracker=Status do Tracker TableColumn.header.tracker.info=Status do tracker TableColumn.header.trackernextaccess=Pr\u00f3ximo Acesso do Tracker TableColumn.header.trackernextaccess.info=Quando o pr\u00f3ximo acesso do tracker ocorrer\u00e1 TableColumn.header.priority=Prioridade TableColumn.header.priority.info=Determina quanta banda de upload \u00e9 dada ao torrent TableColumn.header.seeds.fullcopycalc=%2 c\u00f3pias completas assumidas para %1 peers MyTorrentsView.menu.showdetails=Mostrar &Detalhes MyTorrentsView.menu.showdownloadbar=Mostrar a Barra de &Download MyTorrentsView.menu.open=&Abrir Arquivo MyTorrentsView.menu.setpriority=Definir &Prioridade MyTorrentsView.menu.setpriority.high=&Alta MyTorrentsView.menu.setpriority.low=&Baixa MyTorrentsView.menu.start=&Iniciar MyTorrentsView.menu.stop=Par&ar MyTorrentsView.menu.remove=&Remover MyTorrentsView.menu.changeTracker=&Adicionar a URL do Tracker TrayWindow.menu.exit=S&air TrayWindow.menu.show=&Mostrar o Vuze SystemTray.menu.exit=S&air SystemTray.menu.closealldownloadbars=Fechar &Todas as Barras de Download SystemTray.menu.open_global_transfer_bar=Mostrar a Barra de Transfer\u00eancias SystemTray.menu.show=&Mostrar o Vuze PeersView.ip.info=IP do peer PeersView.port=Porta PeersView.port.info=Porta sendo usada PeersView.T.info=L (local): voc\u00ea estabeleceu a conex\u00e3o, R (remota): o peer estabeleceu a conex\u00e3o. PeersView.T.L.tooltip=Voc\u00ea estabeleceu a conex\u00e3o PeersView.T.R.tooltip=O peer estabeleceu a conex\u00e3o PeersView.I1=I (Interessado pelo peer) PeersView.I1.info=Voc\u00ea est\u00e1 interessado no que o outro peer tem? PeersView.C1=O (Obstru\u00eddo pelo peer) PeersView.C1.info=Ou o peer est\u00e1 impedindo voc\u00ea de baixar PeersView.pieces=Peda\u00e7os PeersView.%=% PeersView.downloadspeed=Velocidade de Download PeersView.download=Download PeersView.I2=I (Interessante para o peer) PeersView.I2.info=O peer est\u00e1 interessado no que voc\u00ea tem? PeersView.C2=O (Obstruindo o peer) PeersView.C2.info=Se voc\u00ea est\u00e1 impedindo o peer de baixar PeersView.uploadspeed=Velocidade de Upload PeersView.uploadspeed.info=A sua velocidade de upload para o peer PeersView.upload=Upload PeersView.upload.info=Seu upload total para o peer. PeersView.statup=Estat\u00edsticas do Upload PeersView.statup.info=Um valor estimado da velocidade de upload do peer PeersView.S=D PeersView.S.info=Desprezado: Um peer pode ser "desprezado" manualmente ou automaticamente (por n\u00e3o entregar os dados a uma taxa alta o bastante) PeersView.downloadspeedoverall=Velocidade Global de Download PeersView.optunchoke=Desobstru\u00e7\u00e3o Otimista PeersView.client=Cliente PeersView.client.info=Tipo de cliente BT que o peer est\u00e1 usando PeersView.menu.snubbed=&Desprezado AllPeersView.title.full=Todos os Peers ConfigView.section.files=Arquivos ConfigView.label.usefastresume=Usar modo de Resumo R\u00e1pido ConfigView.label.incrementalfile=Ativar cria\u00e7\u00e3o incremental de arquivo [Requerido para FAT32 no Linux] ConfigView.label.defaultsavepath=Salvar no diret\u00f3rio de dados padr\u00e3o ConfigView.button.browse=&Procurar... ConfigView.dialog.choosedefaultsavepath=Por favor, escolha o diret\u00f3rio padr\u00e3o para salvar ConfigView.section.server=Conex\u00e3o ConfigView.section.global=Geral ConfigView.label.disconnetseed=Desconectar seeds quando estiver ficando de seed ConfigView.label.switchpriority=Auto-trocar para prioridade baixa quando estiver ficando de seed ConfigView.label.maxdownloads=M\u00e1ximo de downloads simult\u00e2neos [0: ilimitados]\n - N\u00e3o pode ser maior do que o n\u00famero m\u00e1x. de torrents ativos ConfigView.label.maxdownloads.tooltip=Voc\u00ea sempre ser\u00e1 capaz de baixar ativamente o n\u00famero que voc\u00ea p\u00f4r aqui, com uma exce\u00e7\u00e3o.\nUma combina\u00e7\u00e3o de Primeira Prioridade do torrent completado pode tomar o controle de um slot de download ativo se absolutamente necess\u00e1rio. ConfigView.label.maxactivetorrents=M\u00e1ximo de torrents ativos [0: ilimitados]\n - Novos torrents n\u00e3o come\u00e7ar\u00e3o se voc\u00ea estiver baixando/ou ficando mais de seed ConfigView.label.priorityExtensions=Auto-priorizar os arquivos com - ex: .txt;.nfo;.jpg ConfigView.section.transfer=Transfer\u00eancias ConfigView.label.maxuploads=M\u00e1ximo de slots de upload padr\u00e3o por torrent ConfigView.label.maxuploadspeed=Velocidade m\u00e1xima global de upload em KB/s [0: ilimitada] ConfigView.label.saveresumeinterval=Atualizar os dados de resumo a cada ConfigView.unlimited=Ilimitado ConfigView.section.display=Exibir ConfigView.label.opendetails=Auto-abrir a aba de detalhes ConfigView.label.openbar=Auto-abrir a barra de download ConfigView.label.use_old_speed_menus=Usar menus de velocidade do estilo antigo [requer reiniciar] ConfigView.label.closetotray=Fechar minimiza para o Tray do Sistema ConfigView.label.minimizetotray=Minimizar minimiza para o Tray do Sistema ConfigView.section.general=Geral ConfigView.section.start=Iniciar ConfigView.label.showsplash=Mostrar a tela de abertura ConfigView.label.autoupdate=Abrir o di\u00e1logo de atualiza\u00e7\u00e3o quando uma vers\u00e3o mais nova estiver dispon\u00edvel ConfigView.label.openconsole=Abrir o console na inicializa\u00e7\u00e3o ConfigView.label.openconfig=Abrir as op\u00e7\u00f5es na inicializa\u00e7\u00e3o ConfigView.label.startminimized=Iniciar minimizado ConfigView.section.irc=IRC ConfigView.label.ircwiki=Por favor leia http://azureuswiki.com/index.php/Rules_para o_IRC ConfigView.label.ircserver=Servidor ConfigView.label.ircchannel=Canal ConfigView.label.irclogin=Apelido ConfigView.group.irctitle=Configura\u00e7\u00f5es do IRC ConfigView.boolean.ircsendinfo=Permite enviar as suas configura\u00e7\u00f5es (an\u00f4nimo) para\n os operadores do canal para ajud\u00e1-los a ajudar voc\u00ea ConfigView.boolean.irclog=Ativar registro da atividade no canal (em IRC_log.htm) ConfigView.section.security=Seguran\u00e7a ConfigView.label.password=Proteger o Vuze usando uma senha\n- Ser\u00e1 perguntado(a) quando des-iconificar e quando iniciado. ConfigView.label.passwordconfirm=Senha (confirmar) ConfigView.label.passwordmatch=Senha ativada : ConfigView.label.passwordmatchnone=N\u00e3o ConfigView.label.passwordmatchno=N\u00e3o / As senhas n\u00e3o combinam ConfigView.label.passwordmatchyes=Sim ConfigView.button.save=Salvar ConfigView.title.short=Op\u00e7\u00f5es ConfigView.title.full=Op\u00e7\u00f5es ConfigView.title.full._mac=Prefer\u00eancias ConsoleView.title.short=Console ConsoleView.title.full=Console FileItem.write=escrita FileItem.read=leitura FileItem.normal=Normal FileItem.high=alta FileItem.donotdownload=N\u00e3o baixar FileItem.delete=Apagar FilesView.name=Nome FilesView.name.fastRename=Renomeamento R\u00e1pido FilesView.size=Tamanho FilesView.done=Conclu\u00eddo FilesView.%=% FilesView.firstpiece=Primeiro peda\u00e7o # FilesView.numberofpieces=# de peda\u00e7os FilesView.pieces=Peda\u00e7os FilesView.mode=Modo FilesView.priority=Prioridade FilesView.menu.open=&Abrir FilesView.menu.setpriority=&Definir Prioridade FilesView.menu.setpriority.high=&Alta FilesView.menu.setpriority.normal=&Normal FilesView.menu.setpriority.skipped=&N\u00e3o baixar FilesView.title.short=Arquivos FilesView.title.full=Arquivos GeneralView.section.downloaded=Baixados GeneralView.label.status.file=Status do Arquivo GeneralView.label.status.pieces=Status dos Peda\u00e7os GeneralView.section.availability=Disponibilidade GeneralView.label.status.pieces_available=Status dos Peda\u00e7os GeneralView.section.transfer=Transfer\u00eancias GeneralView.section.info=Informa\u00e7\u00f5es GeneralView.title.short=Geral GeneralView.title.full=Geral GeneralView.label.timeelapsed=Tempo Decorrido : GeneralView.label.remaining=Tempo Restante : GeneralView.label.downloaded=Baixados : GeneralView.label.downloadspeed=Velocidade de Download : GeneralView.label.maxuploads=Slots de Upload : GeneralView.label.maxuploads.tooltip=N\u00famero m\u00e1ximo de peers que ser\u00e3o desobstru\u00eddos a qualquer tempo dado. GeneralView.label.uploaded=Enviados : GeneralView.label.uploadspeed=Velocidade de Upload : GeneralView.label.seeds=Seeds: GeneralView.label.peers=Peers: GeneralView.label.completed=Completado : GeneralView.label.totalspeed=Velocidade Total : GeneralView.label.totalspeed.tooltip=Velocidade total (e m\u00e9dia) de todos os clientes aos quais voc\u00ea est\u00e1 conectado. GeneralView.label.averagespeed=m\u00e9dia GeneralView.label.filename=Nome: GeneralView.label.totalsize=Tamanho Total : GeneralView.label.savein=Salvar em : GeneralView.label.hash=Hash : GeneralView.label.numberofpieces=# de Peda\u00e7os : GeneralView.label.size=Tamanho : GeneralView.label.tracker=Status do Tracker : GeneralView.label.updatein=Atualizar em : GeneralView.label.trackerurl=URL do tracker : GeneralView.label.trackerurlupdate=Atualizar Tracker GeneralView.label.comment=Coment\u00e1rio sobre o Torrent : GeneralView.label.user_comment=Coment\u00e1rio do Usu\u00e1rio : ManagerItem.waiting=Esperando ManagerItem.allocating=Alocando ManagerItem.checking=Verificando ManagerItem.ready=Esperando por outro(s) torrent(s) para requisitar ManagerItem.downloading=Baixando ManagerItem.seeding=Ficando de seed ManagerItem.stopped=Parado ManagerItem.error=Erro ManagerItem.high=alta ManagerItem.low=baixa MinimizedWindow.name=Nome: MinimizedWindow.all_transfers=Transfer\u00eancias do Vuze PiecesView.#=# PiecesView.size=Tamanho PiecesView.numberofblocks=# de Blocos PiecesView.blocks=Blocos PiecesView.completed=Completos PiecesView.availability=Disponibilidade PiecesView.reservedby=Reservado PiecesView.writers=Bloquear Contribuidores PiecesView.title.short=Peda\u00e7os PiecesView.title.full=Peda\u00e7os SystemTray.tooltip.seeding=%1 ficando de seed, SystemTray.tooltip.downloading=%1 baixando, DownloadManager.error.filenotfound=Arquivo N\u00e3o Encontrado DownloadManager.error.fileempty=Arquivo torrent est\u00e1 vazio DownloadManager.error.filetoobig=Arquivo Torrent \u00e9 muito grande DownloadManager.error.filewithouttorrentinfo=Nenhuma informa\u00e7\u00e3o de Torrent encontrada no arquivo DownloadManager.error.unsupportedencoding=Codifica\u00e7\u00e3o N\u00e3o Suportada DownloadManager.error.ioerror=Erro de Entrada/Sa\u00edda de Dados DownloadManager.error.sha1=Erro: Algor\u00edtmo n\u00e3o encontrado (SHA1) PeerManager.status.offline=Erro de Conex\u00e3o PeerManager.status.checking=Verificando PeerManager.status.finished=Terminado PeerManager.status.finishedin=Terminado em MainWindow.upgrade.assistant=Assistente de Atualiza\u00e7\u00e3o MainWindow.upgrade.newerversion=Existe uma vers\u00e3o mais nova do Vuze dispon\u00edvel para download MainWindow.upgrade.explanation=Este assistente baixar\u00e1 a nova vers\u00e3o na sua pasta do Vuze e reiniciar\u00e1 o Vuze MainWindow.upgrade.explanation.manual=Voc\u00ea pode atualizar manualmente fechando o Vuze, baixando a nova vers\u00e3o e reiniciando o Vuze MainWindow.upgrade.step1=Passo 1: Baixar a nova vers\u00e3o MainWindow.upgrade.step2=Passo 2: Fechar esta vers\u00e3o e reiniciar a nova vers\u00e3o do Vuze MainWindow.upgrade.hint1=Dica:\tPressionando Terminar faz tudo automaticamente MainWindow.upgrade.hint2=Dica:\tSe voc\u00ea deseja fechar o Vuze mais tarde, pressione Cancelar e\n\trenomeie Azureus2-new.jar para Azureus2.jar ap\u00f3s fechar MainWindow.upgrade.error.downloading.hint=Erro:\tIncapaz de baixar a nova vers\u00e3o, por favor atualize manualmente MainWindow.upgrade.section.info=Nova Vers\u00e3o Dispon\u00edvel MainWindow.upgrade.section.manual=Atualiza\u00e7\u00e3o Manual MainWindow.upgrade.section.automatic=Atualiza\u00e7\u00e3o Autom\u00e1tica MainWindow.upgrade.tooltip.progressbar=O progresso do download \u00e9 mostrado aqui Button.next=Pr\u00f3ximo Button.finish=Terminar Button.cancel=&Cancelar LocaleUtil.title=Escolher Codifica\u00e7\u00e3o LocaleUtil.section.chooseencoding=Escolher codifica\u00e7\u00e3o para o nome do arquivo LocaleUtil.label.chooseencoding=Por favor selecione a codifica\u00e7\u00e3o mais apropriada LocaleUtil.label.hint.doubleclick=Dica: um duplo clique em uma linha escolhe a codifica\u00e7\u00e3o e fecha a janela LocaleUtil.label.checkbox.rememberdecision=Lembrar a decis\u00e3o para os nomes de arquivos restantes LocaleUtil.column.encoding=Codifica\u00e7\u00e3o IrcClient.defaultChannel=#Usu\u00e1rios-do-Azureus IrcClient.copyright=Usando o PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Conectando a IrcClient.connected=Conectado a IrcClient.joining=Entrando IrcClient.channel=Canal IrcClient.joined=entrou IrcClient.error=Erro IrcClient.hasjoined=entrou IrcClient.haskicked=foi chutado IrcClient.hasleft=saiu IrcClient.nowknown=\u00e9 agora conhecido como IrcClient.topicforchannel=T\u00f3pico do canal IrcClient.disconnected=Desconectado de IrcClient.noNick=Nenhum Apelido Especificado. Por favor v\u00e1 para Visualiza\u00e7\u00e3o 'Op\u00e7\u00f5es' IrcView.actionnotsupported=Esta a\u00e7\u00e3o n\u00e3o \u00e9 suportada IrcView.clientsconnected=usu\u00e1rios IrcView.privateto=Para IrcView.privatefrom=De IrcView.noticefrom=Notifica\u00e7\u00e3o : IrcView.errormsg=Sintaxe Errada em /msg : /msg usu\u00e1rio texto IrcView.help=Os comandos v\u00e1lidos s\u00e3o :\n . /help : exibe esta mensagem\n . /nick | /name : muda o seu nome\n . /me a\u00e7\u00e3o : envia uma a\u00e7\u00e3o\n . /msg mensagem sobre o apelido : envia uma mensagem privada para \n . /r mensagem : responde a \u00faltima mensagem privada\n . /join #canalB (n\u00e3o clique aqui,\u00e9 uma exemplo) : muda o canal atual\tpara o canalB PasswordWindow.title=O Vuze est\u00e1 trancado PasswordWindow.passwordprotected=O Vuze est\u00e1 protegido por senha.\nPara mostrar a janela do Vuze, por favor insira a sua senha aqui : Button.ok=OK TrackerChangerWindow.title=Adicionar Tracker TrackerChangerWindow.newtracker=Insira a nova URL do tracker PeersView.discarded=Descartado PeersView.discarded.info=Dados que voc\u00ea de alguma forma recebeu embora voc\u00ea n\u00e3o precisasse deles, ent\u00e3o voc\u00ea se livrou deles. discarded=descartado MyTorrentsView.#=# MyTorrentsView.menu.move=&Mover MyTorrentsView.menu.moveUp=&Para Cima MyTorrentsView.menu.moveDown=&Para Baixo GeneralView.label.hashfails=Falhas no Hash : GeneralView.label.shareRatio=Propor\u00e7\u00e3o de Compartilhamento: ConfigView.section.downloadManagement=Gerenciamento de Download ConfigView.label.startRatioPeers=Come\u00e7ar a ficar de seed quando houver menos de 1 seed para ConfigView.text.neverStop=Nunca Parar ConfigView.text.neverStart=Nunca Iniciar ConfigView.label.checkOncompletion=Verificar novamente os peda\u00e7os quando o download for conclu\u00eddo wizard.title=Criar um torrent wizard.previous=< Voltar wizard.next=Pr\u00f3ximo > wizard.finish=Terminar wizard.mode=Tracker / Modo wizard.tracker=Tracker: wizard.invalidurl=Esta URL n\u00e3o \u00e9 v\u00e1lida wizard.singlefile=Arquivo \u00fanico wizard.singlefile.help=Criar um torrent de um arquivo \u00fanico wizard.directory=Diret\u00f3rio wizard.directory.help=Criar um torrent de um diret\u00f3rio wizard.choosefile=Escolha o arquivo wizard.file=Arquivo : wizard.browse=Navegar... wizard.choosedirectory=Escolha uma diret\u00f3rio wizard.invalidfile=Arquivo Inv\u00e1lido! wizard.invaliddirectory=Diret\u00f3rio Inv\u00e1lido! wizard.torrentFile=Arquivo Torrent wizard.choosetorrent=Por favor escolha o arquivo torrent a criar wizard.information=Informa\u00e7\u00e3o wizard.notimplemented=Ainda n\u00e3o implementado wizard.progresstitle=Criando Arquivo Torrent wizard.savingfile=Salvando Arquivo... wizard.filesaved=Arquivo Salvo. wizard.close=Fechar Torrent.create.progress.piecelength=Comprimento do peda\u00e7o: Torrent.create.progress.piececount=Contagem dos peda\u00e7os: Torrent.create.progress.totalfilesize=Tamanho total do arquivo: Torrent.create.progress.totalfilecount=Contagem total de arquivos: Torrent.create.progress.parsingfiles=Analizando arquivos Torrent.create.progress.hashing=Hasheando arquivos MainWindow.upgrade.downloadingfrom=Baixando de : MainWindow.menu.view.ipFilter=&Filtros de IP ConfigView.section.ipfilter=Filtros de IP ConfigView.section.ipfilter.description=Descri\u00e7\u00e3o ConfigView.section.ipfilter.start=IP Inicial ConfigView.section.ipfilter.end=IP Final ConfigView.section.ipfilter.add=Adicionar ConfigView.section.ipfilter.remove=Remover ConfigView.section.ipfilter.edit=Editar ConfigView.section.ipfilter.save=Salvar ConfigView.section.ipfilter.editFilter=Editar Filtro ConfigView.section.ipfilter.enable=Ativar PeersView.menu.close=&Fechar seedmore.title=O Torrent n\u00e3o est\u00e1 com seeds o bastante seedmore.shareratio=Sua propor\u00e7\u00e3o de compartilhamento neste torrent \u00e9 de seedmore.uploadmore=Ter uma propor\u00e7\u00e3o de compartilhamento inferior a 100% n\u00e3o \u00e9 uma boa coisa para a rede BitTorrent.\nVoc\u00ea deveria deixar este torrente ficar de seed um pouco mais.\nVoc\u00ea tem certeza que voc\u00ea quer prosseguir? ConfigView.label.showpopuponclose=Mostrar janela de confirma\u00e7\u00e3o quando parar de ficar de seed com uma propor\u00e7\u00e3o de compartilhamento menor que 1 ConfigView.label.startNumSeeds=\nCome\u00e7ar a ficar de seed se houver menos de\n - N\u00e3o leva em conta todas as outras regras ConfigView.section.seeding=Ficar de seed MyTorrentsView.menu.removeand=Remo&ver e MyTorrentsView.menu.removeand.deletetorrent=Apagar &Arquivo Torrent MyTorrentsView.menu.removeand.deletedata=Apagar &Dados MyTorrentsView.menu.removeand.deleteboth=Apagar &Ambos deletedata.title=Aten\u00e7\u00e3o deletedata.message1=Voc\u00ea est\u00e1 para apagar os DADOS de :\n deletedata.noprompt=N\u00e3o me alertar de novo MainWindow.menu.file.configure=Assistente de &Configura\u00e7\u00e3o... configureWizard.title=Assistente de Configura\u00e7\u00e3o configureWizard.welcome.title=Bem-vindo ao Assistente de Configura\u00e7\u00e3o do Vuze configureWizard.welcome.message=Este assistente ajudar\u00e1 voc\u00ea a configurar o Vuze para o uso mais comum. Voc\u00ea pode modificar a configura\u00e7\u00e3o em profundidade usando o menu Ferramentas->Op\u00e7\u00f5es. configureWizard.transfer.title=Configura\u00e7\u00f5es de Transfer\u00eancia e Conex\u00e3o configureWizard.transfer.hint=Dica : Usar um pouco menos do que a velocidade da sua linha \u00e9 a melhor configura\u00e7\u00e3o. configureWizard.transfer.message=Por favor escolha uma conex\u00e3o abaixo. Esteja ciente que n\u00e3o permitir uma velocidade de upload boa resultar\u00e1 em baixas velocidades de download. Como a velocidade de upload s\u00f3 conta POR torrent que voc\u00ea est\u00e1 baixando, tentar baixar muitos torrents ao mesmo tempo tamb\u00e9m resultar\u00e1 em baixas velocidades. N\u00f3s recomendadmos usar 5 KB/s por torrent como um m\u00ednimo ESTRITO. Quanto mais r\u00e1pido o seu upload, mais r\u00e1pido voc\u00ea baixar\u00e1 (com respeito a velocidade do torrent). configureWizard.transfer.connection=Linha configureWizard.transfer.connection.0=Personalizado configureWizard.transfer.connection.2=adsl/cabo xxx/128 kbps configureWizard.transfer.connection.3=adsl/cabo xxx/256 kbps configureWizard.transfer.connection.4=adsl/cabo xxx/384 kbps configureWizard.transfer.connection.5=adsl/cabo xxx/512 kbps configureWizard.transfer.connection.6=adsl/cabo xxx/768 kbps configureWizard.transfer.connection.7=adsl/cabo xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Velocidade M\u00e1xima de Upload (KB/s) configureWizard.transfer.maxActiveTorrents=M\u00e1ximo de Ativos configureWizard.transfer.maxDownloads=M\u00e1ximo de Downloads configureWizard.transfer.maxUploadsPerTorrent=M\u00e1ximo de Uploads por Torrent configureWizard.nat.title=Porta do NAT / Servidor configureWizard.nat.message=De modo a obter o melhor do Vuze, \u00e9 altamente recomendado estar completamente acess\u00edvel a internet. Esta ferramenta deixa voc\u00ea testar e / ou mudar a porta usada para aceitar as conex\u00f5es de entrada dos peers.\n\nNOTA: Esta ferramenta apenas testa conex\u00f5es TCP. A Base de Dados Distribu\u00edda requer conex\u00f5es de entrada UDP tamb\u00e9m, mas automaticamente notificar\u00e1 voc\u00ea se descobrir um firewall bloqueando.\n\nNOTA: Porta TCP 6880 est\u00e1 reservada internamente, ent\u00e3o, n\u00e3o pode ser usada. configureWizard.nat.test=Teste configureWizard.nat.testing=Testando porta configureWizard.nat.ok=OK! configureWizard.nat.ko=Erro do NAT configureWizard.nat.unable=Incapaz de testar: Porta inv\u00e1lida dada, ou o teste do servi\u00e7o falhou.\nOutro aplicativo j\u00e1 pode estar usando esta porta. configureWizard.file.title=Torrents / Arquivos configureWizard.file.message1=O Vuze salvar\u00e1 os torrents abertos em uma pasta espec\u00edfica, voc\u00ea pode escolher esta pasta aqui: configureWizard.file.path=Caminho configureWizard.file.browse=Procurar configureWizard.file.message2=O Vuze \u00e9 capaz de resumir seus arquivos instant\u00e2neamente, adicionando alguns dados de resumo aos seus torrents. Usando esta fun\u00e7\u00e3o, voc\u00ea ser\u00e1 tamb\u00e9m resumir\u00e1 peda\u00e7os parcialmente baixados. configureWizard.file.fastResume=Ativar resumo r\u00e1pido configureWizard.file.invalidPath=Diret\u00f3rio inv\u00e1lido configureWizard.finish.title=Completado configureWizard.finish.message=O Vuze est\u00e1 agora configurado, divirta-se! wizard.close.confirmation=Confirma\u00e7\u00e3o wizard.close.message=Voc\u00ea quer que este assistente seja executado na pr\u00f3xima vez que o Vuze for iniciado? exportTorrentWizard.title=Exportar um torrent XML exportTorrentWizard.torrentfile.title=Sele\u00e7\u00e3o da Entrada de Dados do Torrent exportTorrentWizard.torrentfile.message=Selecione o arquivo torrent para exportar exportTorrentWizard.torrentfile.path=Caminho exportTorrentWizard.torrentfile.browse=Navegar exportTorrentWizard.torrentfile.invalidPath=Arquivo torrent inv\u00e1lido exportTorrentWizard.exportfile.title=Exportar Sele\u00e7\u00e3o de Arquivos exportTorrentWizard.exportfile.message=Insira o arquivo XML para exportar para exportTorrentWizard.exportfile.path=Caminho exportTorrentWizard.exportfile.browse=Navegar exportTorrentWizard.exportfile.invalidPath=Arquivo de exporta\u00e7\u00e3o inv\u00e1lido exportTorrentWizard.finish.title=Conclu\u00eddo exportTorrentWizard.finish.message=Exporta\u00e7\u00e3o conclu\u00edda com sucesso exportTorrentWizard.process.inputfilebad.title=Arquivo Torrent Inv\u00e1lido exportTorrentWizard.process.inputfilebad.message=Uma falha ocorreu ao acessar o arquivo de entrada de dados: exportTorrentWizard.process.outputfileexists.title=O Arquivo Existe exportTorrentWizard.process.outputfileexists.message=O arquivo de sa\u00edda de dados existe - sobrescrever? exportTorrentWizard.process.torrentfail.title=Falha na Leitura do Torrent exportTorrentWizard.process.exportfail.title=Falha na Exporta\u00e7\u00e3o do Torrent exportTorrentWizard.process.unknownfail.title=Erro Inesperado importTorrentWizard.title=Importar um torrent XML importTorrentWizard.torrentfile.title=Sele\u00e7\u00e3o da Entrada de Dados do Torrent importTorrentWizard.torrentfile.message=Insira o arquivo torrent para o qual importar importTorrentWizard.torrentfile.path=Caminho importTorrentWizard.torrentfile.browse=Navegar importTorrentWizard.torrentfile.invalidPath=Arquivo torrent inv\u00e1lido importTorrentWizard.importfile.title=Sele\u00e7\u00e3o do Arquivo para Importa\u00e7\u00e3o importTorrentWizard.importfile.message=Selecione o arquivo XML para importar importTorrentWizard.importfile.path=Caminho importTorrentWizard.importfile.browse=Navegar importTorrentWizard.importfile.invalidPath=Arquivo de importa\u00e7\u00e3o inv\u00e1lido importTorrentWizard.finish.title=Conclu\u00eddo importTorrentWizard.finish.message=Importa\u00e7\u00e3o conclu\u00edda com sucesso importTorrentWizard.process.inputfilebad.title=Arquivo de Importa\u00e7\u00e3o Inv\u00e1lido importTorrentWizard.process.inputfilebad.message=Uma falha ocorreu ao acessar o arquivo de entrada de dados: importTorrentWizard.process.outputfileexists.title=O Arquivo Existe importTorrentWizard.process.outputfileexists.message=O arquivo de sa\u00edda de dados existe - sobrescrever? importTorrentWizard.process.torrentfail.title=Falha na Escrita do Torrent importTorrentWizard.process.importfail.title=Falha na Importa\u00e7\u00e3o do Torrent importTorrentWizard.process.unknownfail.title=Erro Inesperado ConfigView.label.bindip=Prender ao endere\u00e7o IP local ConfigView.label.xfs.allocation=Alocar novos arquivos usando um m\u00e9todo espec\u00edfico para o sistema de arquivos XFS ConfigView.label.xfs.allocation.tooltip=Por favor tenha certeza /usr/sbin/xfs_io est\u00e1 apropriadamente instalado no seu sistema. Na maioria das distribui\u00e7\u00f5es Linux, est\u00e1 inclu\u00eddo no pacote "xfsprogs". xfs.allocation.xfs_io.not.found=A aloca\u00e7\u00e3o do arquivo XFS falhou porque /usr/sbin/xfs_io n\u00e3o p\u00f4de ser executado. Tenha certeza de que est\u00e1 apropriadamente instalado no seu sistema. O erro original foi : "%1". ConfigView.label.zeronewfiles=Alocar e zerar novos arquivos na cria\u00e7\u00e3o ConfigView.label.zeronewfiles.tooltip=Minimiza a fragmenta\u00e7\u00e3o ConfigView.section.stats=Estat\u00edsticas ConfigView.section.stats.enable=Ativar ConfigView.section.stats.defaultsavepath=Diret\u00f3rio para salvar as estat\u00edsticas ConfigView.section.stats.choosedefaultsavepath=Por favor escolha o diret\u00f3rio para salvar as estat\u00edsticas ConfigView.section.stats.savefreq=Freq\u00fc\u00eancia de salvamento ConfigView.section.stats.minutes=min ConfigView.section.stats.hours=h ConfigView.section.stats.seconds=s ConfigView.section.stats.savefile=Nome do arquivo de estat\u00edsticas ConfigView.section.stats.graph_update_dividers=Exibir linha vertical a cada 60 segundos MyTorrentsView.menu.export=&Torrent XML... MyTorrentsView.menu.host=&Servidor... ManagerItem.finishing=Terminando ConfigView.dialog.choosedefaulttorrentpath=Por favor, escolha o diret\u00f3rio padr\u00e3o dos torrents ConfigView.dialog.choosemovepath=Por favor, escolha o diret\u00f3rio para o qual mover ConfigView.label.movecompleted=Mover arquivos completados (ap\u00f3s o download) ConfigView.label.moveremoved=Mover arquivos completados (quando sendo removidos) ConfigView.label.savetorrents=Salvar arquivos .torrent MainWindow.menu.view.mytracker=Meu &Tracker MyTrackerView.title.full=Meu Tracker MyTrackerView.name=Nome MyTrackerView.status.started=Rodando MyTrackerView.status.stopped=Parado MyTrackerView.announces=An\u00fancios MyTrackerView.uploaded=Enviados MyTrackerView.downloaded=Baixados MyTrackerView.left=Restante ConfigView.section.style=Interface ConfigView.label.set_ui_transfer_speeds=N\u00e3o levar em conta as velocidades de transfer\u00eancia selecion\u00e1veis ConfigView.label.set_ui_transfer_speeds.description=Voc\u00ea pode escolher definir manualmente as velocidades de download e upload dispon\u00edveis na barra de status no tray do sistema.\nOs valores devem estar separados por v\u00edrgula. ConfigView.label.set_ui_transfer_speeds.description.download=Definir as velocidades de download (em KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Definir as velocidades de upload (em KB/s) ConfigView.section.style.useCustomTabs=Usar abas que fecham (precisa reiniciar) MainWindow.menu.view.plugins=&Plugins fileDownloadWindow.saveTorrentIn=Salvar Arquivo Torrent Em fileDownloadWindow.title=Vuze \u2013 Baixador de Torrents fileDownloadWindow.downloading=Baixando de : fileDownloadWindow.status=Status: fileDownloadWindow.state_initializing=Inicializando fileDownloadWindow.state_downloading=Baixando fileDownloadWindow.state_error=Erro: MainWindow.menu.file.open.url=&Local... openUrl.title=Abrir Local openUrl.url=URL: MyTorrentsView.menu.host.error.title=Falha na Hospedagem do Torrent MyTorrentsView.menu.host.error.message=O seguinte erro ocorreu durante a hospedagem do torrent ConfigView.section.tracker=Tracker ConfigView.section.tracker.pollinterval=Intervalo de apura\u00e7\u00e3o dos clientes no tracker (segs) ConfigView.section.tracker.publishenable=Publicar detalhes do torrent para "" ConfigView.section.tracker.ip=Endere\u00e7o IP externo do tracker ConfigView.section.style.enableXPStyle=Ativar estilo XP (precisa reiniciar) IPChecker.external.service.dyndns.name=DynDNS IPChecker.external.service.dyndns.url=http://www.dyndns.org/ IPChecker.external.service.dyndns.description=Dynamic DNS Network Services, LLC ConfigView.section.tracker.checkip=Auto-descobrir endere\u00e7o IP externo... ipCheckerWizard.title=Assistente do Verificador de IP ipCheckerWizard.service=Servi\u00e7o ipCheckerWizard.chooseService=Por favor escolha um servi\u00e7o de verifica\u00e7\u00e3o IP dos servi\u00e7os listados ipCheckerWizard.explanations=Voc\u00ea pode usar este assistente para descobrir qual \u00e9 o seu endere\u00e7o IP externo. Se o seu endere\u00e7o IP \u00e9 din\u00e2mico, n\u00f3s recomendamos que voc\u00ea abra uma conta com um Servi\u00e7o de DNS Din\u00e3mico. Alguns destes servi\u00e7os est\u00e3o listados abaixo, use o link fornecido para criar uma conta (quando suportado). Ent\u00e3o preencha o campo do endere\u00e7o IP com o nome do seu servidor din\u00e2mico (ex: nomedomeuhost.dyndns.org). Voc\u00ea precisar\u00e1 de um programa para atualizar automaticamente o seu servi\u00e7o de DNS din\u00e2mico com seu endere\u00e7o de IP. Assim, voc\u00ea ser\u00e1 capaz de hospedar torrents, mesmo se o seu IP mudar. ipCheckerWizard.service.description=Descri\u00e7\u00e3o : ipCheckerWizard.service.url=Link: ipCheckerWizard.progresstitle=Verificando IP ipCheckerWizard.checkComplete=IP Completado: ipCheckerWizard.checkFailed=Falhou, raz\u00e3o : wizard.tracker.local=Usar o Tracker Embutido do Vuze wizard.tracker.external=Usar um tracker externo wizard.tracker.howToLocal=\tV\u00e1 em 'Ferramentas->Op\u00e7\u00f5es->Tracker' para ativ\u00e1-lo wizard.announceUrl=URL de An\u00fancio : IPChecker.external.service.discoveryvip.name=Discoveryvip IPChecker.external.service.discoveryvip.url=http://ip.discoveryvip.com/ IPChecker.external.service.discoveryvip.description=Discoveryvip \u2013 Apenas verifica\u00e7\u00e3o de Endere\u00e7o IP IPChecker.external.httpinvalidresponse=Resposta HTTP inv\u00e1lida IPChecker.external.loadingwebpage=Carregando p\u00e1gina da web IPChecker.external.analysingresponse=Analisando resposta IPChecker.external.addressextracted=Endere\u00e7o IP extra\u00eddo IPChecker.external.httploadfail=Falha ao carregar a p\u00e1gina IPChecker.external.timeout=Ocorreu um esgotamento do tempo IPChecker.external.ipnotfound=Endere\u00e7o IP n\u00e3o encontrado ConfigView.section.tracker.pollintervalmin=M\u00ednimo ConfigView.section.tracker.pollintervalmax=M\u00e1ximo ConfigView.section.tracker.pollintervalincby=Aumentar em ConfigView.section.tracker.pollintervalincper=A cada 'n' clientes splash.loadingImages=Carregando Imagens splash.initializeGui=Inicializando a Janela Principal splash.openViews=Abrindo as Visualiza\u00e7\u00f5es splash.plugin=Carregando o Plugin: configureWizard.nat.tooManyPorts=Muitas portas para testar (m\u00e1x. 9) ConfigView.section.color=Esquema de Cores MyTorrentsView.menu.publish=Pub&licar... MyTrackerView.status.published=Publicado MyTrackerView.completed=Completo MainWindow.menu.file.open.torrentnodefault=Arquivo Torrent... (Sem Save Padr\u00e3o) wizard.comment=Coment\u00e1rio ConfigView.label.movetorrent=Mover .torrent ConfigView.label.movepartialdownloads=Mover mesmo se alguns arquivos est\u00e3o marcados para "N\u00e3o Baixar" ConfigView.label.subdir_is_in_default=Quando considerando se os downloads existem em um diret\u00f3rio padr\u00e3o, tamb\u00e9m considerar os sub-diret\u00f3rios ConfigView.section.file.decoder.label=Codifica\u00e7\u00e3o padr\u00e3o do torrent quando requerido pela sele\u00e7\u00e3o ConfigView.section.file.decoder.nodecoder=Nenhum IPChecker.external.service.no-ip.description=Provedor de servi\u00e7o DNS din\u00e2mico e est\u00e1tico\n(nenhum servi\u00e7o de 'verificar o endre\u00e7o' dispon\u00edvel gratuitamente) ConfigView.section.tracker.publicenable=Ativar torrents externos ConfigView.label.playdownloadspeech=Falar quando um download est\u00e1 terminado ConfigView.label.playdownloadspeech.info=Os servi\u00e7os de discurso atualmente funcionam melhor com o ingl\u00eas # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Exibe o n\u00famero de c\u00f3pias dispon\u00edveis de cada peda\u00e7o.\nSe o n\u00famero a direita for menor que 1, voc\u00ea n\u00e3o est\u00e1 vendo uma c\u00f3pia completa do arquivo (e pode ter problemas para completar o download). GeneralView.label.trackerurl.tooltip=Clique para copiar a URL de an\u00fancio para a \u00e1rea de transfer\u00eancia GeneralView.label.trackerurlopen.tooltip=Clicar para abrir a p\u00e1gina principal do tracker # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Atualizar a GUI a cada ConfigView.section.style.inactiveUpdate=Atualizar a janela principal a cada atualiza\u00e7\u00e3o(\u00f5es) da N GUI quando n\u00e3o \u00e9 a janela ativa ConfigView.section.style.graphicsUpdate=Atualizar as barras gr\u00e1ficas a cada N atualiza\u00e7\u00f5e(s) da GUI ConfigView.section.style.reOrderDelay=Reordenar tabelas a cada N atualiza\u00e7\u00f5e(s) da GUI [0: nunca] ConfigView.section.style.reOrderDelay.never=Nunca ConfigView.section.logging=Registro ConfigView.section.logging.enable=Ativar registro para o arquivo ConfigView.section.logging.logdir=Diret\u00f3rio do arquivo de log ConfigView.section.logging.choosedefaultsavepath=Por favor, escolha o diret\u00f3rio para salvar GeneralView.label.updatein.querying=Requisitando... configureWizard.nat.sharePort=Usar uma \u00fanica porta de entrada compartilhada para todos os torrents ConfigView.section.logging.maxsize=Tamanho m\u00e1ximo do arquivo de log ConfigView.section.tracker.passwordenableweb=Ativar senha na rede do tracker ConfigView.section.tracker.passwordenabletorrent=Ativar senha nos torrents ConfigView.section.tracker.username=Nome de usu\u00e1rio ConfigView.section.tracker.password=Senha columnChooser.title=Escolher as colunas a exibir columnChooser.move=Arraste as linhas para re-orden\u00e1-las columnChooser.apply=Aplicar columnChooser.columnname=Nome da Coluna columnChooser.columndescription=Descri\u00e7\u00e3o TableColumn.header.shareRatio=Propor\u00e7\u00e3o do Compartilhamento MyTorrentsView.menu.editTableColumns=&Configura\u00e7\u00e3o das Colunas wizard.operationfailed=A opera\u00e7\u00e3o falhou authenticator.title=Autentica\u00e7\u00e3o Requerida authenticator.realm=Dom\u00ednio authenticator.user=Nome de Usu\u00e1rio authenticator.password=Senha ConfigView.label.allowSendVersion=Permitir ao Vuze o envio an\u00f4nimo do n\u00famero da vers\u00e3o e ID aleat\u00f3ria enquanto procura por nova vers\u00e3o ConfigView.label.version.info.link=Visite aqui para detalhes sobre quais dados s\u00e3o enviados para o servidor de verifica\u00e7\u00e3o da vers\u00e3o wizard.hint.mode=Dica:\tVoc\u00ea pode Arrastar e Soltar um \u00fanico arquivo ou diret\u00f3rio neste assistente\n\tpara escolher um arquivo ou diret\u00f3rio wizard.hint.file=Dica:\tVoc\u00ea pode escolher um \u00fanico arquivo com Arrastar e Soltar wizard.hint.directory=Dica:\tVoc\u00ea pode escolher um \u00fanico diret\u00f3rio com Arrastar e Soltar MainWindow.menu.help.checkupdate=&Procurar por Atualiza\u00e7\u00f5es... TableColumn.header.down=Baixado TableColumn.header.up=Enviado ConfigView.section.tracker.passwordenabletorrent.info=Requer cliente BitTorrent adequado (ex: Vuze) ConfigView.section.style.confirmationOnExit=Mostrar janela de confirma\u00e7\u00e3o ao sair MainWindow.dialog.exitconfirmation.title=Sair do Vuze? MainWindow.dialog.exitconfirmation.text=Voc\u00ea quer realmente sair do Vuze? SystemTray.menu.stopalltransfers=Parar &Todas as Transfer\u00eancias TrayWindow.menu.stopalldownloads=Parar &Todos os Downloads ConfigView.section.tracker.sslport.info=Veja o FAQ para mais informa\u00e7\u00f5es wizard.tracker.ssl=Usar SSL ConfigView.label.playdownloadfinished=Tocar um som quando um download est\u00e1 terminado ConfigView.label.popupdownloadfinished=Mostrar um alerta quando um download estiver conclu\u00eddo ConfigView.label.popupfilefinished=Mostrar um alerta quando um arquivo estiver conclu\u00eddo TableColumn.header.pieces=Peda\u00e7os TableColumn.header.pieces.info=Barra gr\u00e1fica representando quais peda\u00e7os voc\u00ea baixou TableColumn.header.completion=Conclus\u00e3o TableColumn.header.completion.info=Representa\u00e7\u00e3o gr\u00e1fica dos % baixados ConfigView.section.style.showdownloadbasket=Mostrar Cesta de Downloads (Arrastar e Soltar .torrents) ConfigView.section.style.alwaysShowTorrentFiles=Sempre mostrar os arquivos Torrent em Detalhes/Arquivos wizard.multitracker=Adicionar informa\u00e7\u00e3o Multi-Tracker ao torrent wizard.multitracker.configuration=Configura\u00e7\u00e3o do Multi-Tracker wizard.multitracker.new=Novo... wizard.multitracker.edit=Editar... wizard.multitracker.delete=Apagar wizard.multitracker.group=Grupo de Trackers wizard.multitracker.edit.title=Editor Multi-Tracker wizard.multitracker.edit.name=Nome wizard.multitracker.edit.save=Salvar wizard.multitracker.edit.newgroup=Novo Grupo wizard.multitracker.edit.deletegroup=Apagar wizard.multitracker.edit.newtracker=Novo Tracker wizard.multitracker.edit.deletetracker=Apagar wizard.multitracker.edit.edit=Editar wizard.addingmt=Adicionando informa\u00e7\u00e3o Multi-Tracker wizard.multitracker.noannounce=A URL de an\u00fancio n\u00e3o est\u00e1 presente em sua lista de trackers MyTorrentsView.menu.recheck=For\u00e7ar Re-chec&agem iconBar.showDownloadBar.tooltip=Mostrar a Barra de Downloads iconBar.start.tooltip=Iniciar iconBar.stop.tooltip=Interromper iconBar.remove.tooltip=Remover iconBar.openNoDefault.tooltip=Abrir um arquivo .torrent (sem save padr\u00e3o) iconBar.openURL.tooltip=Abrir uma URL iconBar.openFolder.tooltip=Abrir uma Pasta iconBar.new.tooltip=Criar um torrent iconBar.up.tooltip=Mover para cima iconBar.down.tooltip=Mover para baixo iconBar.run.tooltip=Abrir iconBar.host.tooltip=Hospedeiro iconBar.publish.tooltip=Publicar iconBar.editcolumns.tooltip=Configura\u00e7\u00e3o da Coluna MyTorrentsView.menu.editTracker=&Editar URL(s) do Tracker GeneralView.menu.selectTracker=Selecionar ConfigView.section.stats.xslfile=Nome do arquivo XSL ConfigView.section.stats.xslfiledetails=Isto ser\u00e1 inclu\u00eddo no cabe\u00e7alho do arquivo de estat\u00edsticas via tag ConfigView.label.savetorrentbackup=Salvar Backup ConfigView.section.tracker.forceport=For\u00e7ar torrents externos hospedados para a porta padr\u00e3o ConfigView.section.ipfilter.allow=PERMITIR estes intervalos (o padr\u00e3o \u00e9 NEGAR) ConfigView.section.ipfilter.list.inrange=estava no intervalo ConfigView.section.ipfilter.list.notinrange=n\u00e3o estava em qualquer intervalo ConfigView.section.ipfilter.list.title=Lista de IPs Bloqueados ConfigView.label.allowsameip=Permitir m\u00faltiplas conex\u00f5es do mesmo IP ConfigView.label.allowsameip.tooltip=S\u00f3 marque se voc\u00ea PRECISA.\nEsta \u00e9 uma prote\u00e7\u00e3o contra leechers (quando desativado). ConfigView.label.userSuperSeeding=Usar Super Seeding PeersView.uniquepiece=Peda\u00e7o (modo Super-Seed) PeersView.uniquepiece.none=Nenhum PeersView.timetosend=Tempo para re-enviar o Peda\u00e7o (Modo Super-Seed) ConfigView.section.style.addurlsilently=Abrir URLs passadas silenciosamente ConfigView.section.style.addurlsilently.tooltip=Automaticamente baixar URLs dos .torrent passadas/soltas sem abrir a caixa de di\u00e1logo. ConfigView.section.file.decoder.prompt=Sempre alertar quando houver uma escolha de codifica\u00e7\u00e3o dispon\u00edvel ConfigView.section.file.decoder.prompt.tooltip=Sempre mostrar uma janela quando houver uma escolha de codifica\u00e7\u00e3o estiver dispon\u00edvel MyTorrentsView.menu.moveTop=&Topo MyTorrentsView.menu.moveEnd=&Fundo ConfigView.label.moveonlyusingdefaultsave=apenas se estiver no diret\u00f3rio de dados padr\u00e3o ConfigView.label.moveonlyusingdefaultsave.tooltip=Mover apenas se os dados baixados estiverem no diret\u00f3rio de dados padr\u00e3o ConfigView.label.watchtorrentfolder=Importar novos .torrents automaticamente ConfigView.label.watchtorrentfolder.tooltip=Procurar por novos .torrents regularmente ConfigView.label.watchtorrentfolderinterval=Intervalo ConfigView.label.watchtorrentfolderinterval.tooltip=Pausa at\u00e9 que a pasta seja verificada novamente ConfigView.dialog.choosewatchtorrentfolderpath=Por favor, escolha o diret\u00f3rio de importa\u00e7\u00e3o dos .torrents ConfigView.label.startwatchedtorrentsstopped=Iniciar parado ConfigView.label.startwatchedtorrentsstopped.tooltip=Adiciona novos .torrents no estado PARADO ConfigView.section.plugins=Plugins wizard.maketorrent.filesize=Tamanho do(s) Arquivo(s) wizard.maketorrent.piececount=Contagem de Peda\u00e7os wizard.maketorrent.piecesize=Tamanho do Peda\u00e7os wizard.maketorrent.auto=Autom\u00e1tico MainWindow.menu.view.stats=&Estat\u00edsticas SpeedView.title.full=Atividade SpeedView.downloadSpeed.title=Velocidade de Download SpeedView.uploadSpeed.title=Velocidade de Upload ConfigView.section.style.useSIUnits=Usar Unidades IEC (KB -> KiB etc.) iconBar.top.tooltip=Mover para o topo iconBar.bottom.tooltip=Mover para baixo TableColumn.header.health=Sa\u00fade MyTorrentsView.menu.health=Sobre a Qualidade health.explain.grey=significa que o seu torrent n\u00e3o est\u00e1 rodando (baixando ou enviando) health.explain.red=significa que voc\u00ea n\u00e3o est\u00e1 conectado a nenhum peer enquanto baixa health.explain.blue=quando ficando de seed, significa que voc\u00ea ainda n\u00e3o est\u00e1 conectado a qualquer peer\nquando baixando, significa que voc\u00ea est\u00e1 conectado a alguns peers mas o tracker est\u00e1 inativo health.explain.yellow=significa que o tracker est\u00e1 OK, voc\u00ea est\u00e1 conectado a peers, mas voc\u00ea n\u00e3o tem nenhuma conex\u00e3o remota.\nVoc\u00ea pode ter um problema de NAT se seus torrents ficam no estado amarelo o tempo todo health.explain.green=significa que tudo vai bem. ConfigView.section.style.alwaysRefreshMyTorrents=Sempre atualizar Meus Torrents ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Esta op\u00e7\u00e3o atualizar\u00e1 a guia Meus Torrents mesmo se n\u00e3o exibida (\u00fatil para alguns plugins mirc) # #2.0.7.0 # security.certtruster.title=Alerta do Certificado de Seguran\u00e7a security.certtruster.intro=O certificado de seguran\u00e7a foi emitido por uma empresa na qual voc\u00ea n\u00e3o confia security.certtruster.resource=Recurso: security.certtruster.issuedto=Emitido Para: security.certtruster.issuedby=Emitido Por: security.certtruster.prompt=Voc\u00ea quer confiar nela? security.certtruster.yes=Sim security.certtruster.no=N\u00e3o ConfigView.section.tracker.torrentsperpage=Quantos torrents por p\u00e1gina? [0: ilimitados] MainWindow.menu.file.share=&Compartilhar MainWindow.menu.file.share.file=&Arquivo... MainWindow.menu.file.share.dir=P&asta... MainWindow.menu.file.share.dircontents=Conte\u00fado &da Pasta... MainWindow.menu.file.share.dircontentsrecursive=Conte\u00fados da Pasta... (&Recursivo) MainWindow.dialog.share.sharefile=Selecionar Arquivo para Compartilhar MainWindow.dialog.share.sharedir=Selecionar Pasta para Compartilhar MainWindow.dialog.share.sharedircontents=Selecionar Conte\u00fados da Pasta para Compartilhar MainWindow.dialog.share.sharedircontents.recursive=Recursivo globalmanager.download.remove.veto=A\u00e7\u00e3o de Remo\u00e7\u00e3o Vetada plugin.sharing.download.remove.veto=Este download \u00e9 o resultado de um recurso sendo compartilhado.\nPara remover o download remova o compartilhamento associado: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Principal ConfigView.section.tracker.web=Web ConfigView.label.prioritizefirstpiece=Priorizar o primeiro e o \u00faltimo peda\u00e7o do(s) arquivo(s) ConfigView.label.prioritizefirstpiece.tooltip=Tenta baixar o come\u00e7o e o fim de um arquivo primeiro.\nPara o suporte de pr\u00e9-visualiza\u00e7\u00e3o. ConfigView.section.file.confirm_data_delete=Confirmar antes de apagar os dados ConfigView.section.file.confirm_data_delete.tooltip=Confirmar a exclus\u00e3o dos dados quando usar 'Remover e Apagar...' ConfigView.section.file.delete.include_files_outside_save_dir=Quando apagando os dados, permitir aos arquivos ligados fora do diret\u00f3rio para salvar torrents serem removidos tamb\u00e9m TrayWindow.menu.startalldownloads=Iniciar Todos os Downloads SystemTray.menu.startalltransfers=Iniciar Todas as Transfer\u00eancias sharing.progress.title=Progresso do Compartilhamento sharing.progress.hide=Esconder MainWindow.menu.view.myshares=Meus Compartilhamentos MySharesView.title.full=Meus Compartilhamentos MySharesView.name=Nome MySharesView.type=Tipo MySharesView.type.file=Arquivo MySharesView.type.dir=Diret\u00f3rio MySharesView.type.dircontents=Conte\u00fado do Diret\u00f3rio MySharesView.type.dircontentsrecursive=Conte\u00fado do diret\u00f3rio (recursivo) MySharesView.menu.remove=Remover ConfigView.section.tracker.extensions=Extens\u00f5es ConfigView.section.tracker.sendpeerids=Enviar as identidades dos peers aos que baixam ConfigView.section.tracker.enableudp=Ativar o protocolo do tracker UDP plugin.sharing.torrent.remove.veto=Este registro de tracker \u00e9 o resultado de um recurso que est\u00e1 sendo compartilhado.\nPara remover o download remova o compartilhamento associado: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=O download n\u00e3o pode ser removido se n\u00e3o for parado plugin.sharing.remove.veto=Este compartilhamento \u00e9 um sub-compartilhamento de um 'conte\u00fado de diret\u00f3rio' e n\u00e3o pode ser explicitamente apagado.\n Apague o compartilhamento raiz GeneralView.label.hash.tooltip=Clique para copiar o hash para a \u00e1rea de transfer\u00eancia ConfigView.section.tracker.maxpeersreturned=M\u00e1ximo de peers retornados [0: ilimitados] ConfigView.label.serverport=Porta de escuta TCP / UDP de entrada ConfigView.label.serverport.tooltip=A porta deve estar dentro de 1-65535, e nunca a 6880 como essa est\u00e1 reservada para o uso interno do Vuze. configureWizard.nat.server.tcp_listen_port=Porta de Escuta da Entrada TCP ConfigView.section.sharing=Compartilhamento ConfigView.section.sharing.usessl=Usar SSL para recursos compartilhados (requer a configura\u00e7\u00e3o do Tracker) ConfigView.section.style.dropdiraction=A\u00e7\u00e3o ao Arrastar e Soltar para diret\u00f3rios ConfigView.section.style.dropdiraction.opentorrents=Abrir Torrents ConfigView.section.style.dropdiraction.sharefolder=Compartilhar Diret\u00f3rio ConfigView.section.style.dropdiraction.sharefoldercontents=Compartilhar Conte\u00fado # # 2.0.7.x # Categories.all=Todas Categories.uncategorized=Sem categoria CategoryAddWindow.message=Insira um novo nome de categoria CategoryAddWindow.title=Adicionar Nova Categoria ConfigView.label.autoSeedingIgnoreInfo=Torrents ignorados v\u00e3o para o final da fila de seeds. Eles n\u00e3o s\u00e3o automaticamente iniciados.\nIgnorar regras n\u00e3o se aplica a torrents que entrem no crit\u00e9rio da Primeira Prioridade.\nA menos que declarado de outro modo, use um valor de 0 para desativar uma regra. ConfigView.label.directory=Diret\u00f3rio ConfigView.label.disconnetseed.tooltip=Quando estiver ficando de seed com um torrent, desconectar quaisquer clientes que tamb\u00e9m est\u00e3o ficando de seed.\nEles n\u00e3o precisam estar falando com voc\u00ea. ConfigView.label.ignoreCase=Ignorar Mai\u00fasculas/Min\u00fasculas ConfigView.label.ignoreSeeds=Ignorar torrents com pelo menos ConfigView.label.importdirectory=Diret\u00f3rio de Importa\u00e7\u00e3o ConfigView.label.minPeersToBoostNoSeeds.tooltip=Quaisquer torrents sem seeds e tendo menos peers do que voc\u00ea especificar\nir\u00e3o para o final da fila. ConfigView.label.minPeersToBoostNoSeeds=Rank da Prioridade para Ficar de Seed menor para torrents sem seeds e com menos de ConfigView.label.minSeedingTime.tooltip=Os Ranks de Seeding podem flutuar frequentemente em um curto per\u00edodo de tempo, as vezes fazendo o torrent iniciar automaticamente, apenas para ser parado & e posto no fila imediatamente ap\u00f3s isso.\nIsto alivia o problema for\u00e7ando o torrent a ficar de seed por um per\u00edodo dado de tempo. Voc\u00ea ainda pode par\u00e1-lo manualmente se voc\u00ea quiser. ConfigView.label.minSeedingTime=Tempo m\u00ednimo para ficar de seed em segundos ConfigView.label.minSpeedForActiveDL.tooltip=Um slot de download \u00e9 sempre usado para os 30 segundos iniciais\nap\u00f3s o torrent incompleto iniciar. ConfigView.label.minSpeedForActiveDL=N\u00e3o contar o torrent como usando um slot de download se a velocidade for inferior a ConfigView.label.queue.debuglog=Registrar a informa\u00e7\u00e3o de debug ConfigView.label.queue.debuglog.info=Adiciona informa\u00e7\u00f5es de debug da fila ao arquivo de console/log.\nEmbora cifradas, as informa\u00e7\u00f5es de debug dizem a voc\u00ea o estado dos torrents e porque eles est\u00e3o/n\u00e3o est\u00e3o iniciando/requerindo. ConfigView.label.queue.minQueueingShareRatio=N\u00e3o requerer ou parar um torrent at\u00e9 que a sua propor\u00e7\u00e3o de compartilhamento atinja ConfigView.label.ratio=propor\u00e7\u00e3o ConfigView.label.removeOnStop=Remover o torrent da lista ap\u00f3s automaticamente parar ConfigView.label.savedirectory=Diret\u00f3rio para Salvar ConfigView.label.seeding.autoReposition.tooltip=Se ativado, a ordem dos torrents (a coluna '#') ser\u00e1 alterada para combinar com aquela do Rank do Seeding\nIsto \u00e9 \u00fatil se voc\u00ea n\u00e3o gosta de ver os n\u00fameros do Rank de Seeding, mas ainda quer saber a ordem na qual os torrents completados ser\u00e3o iniciados. ConfigView.label.seeding.autoReposition=Automaticamente reposicionar torrents baseado no Rank do Seeding ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Freq\u00fcentemente, torrents com poucas contagens de seeds e muitas contagens de peers querem dizer que provavelmente n\u00e3o s\u00e3o uma c\u00f3pia completa entre os peers.\nPortanto, voc\u00ea pode n\u00e3o querer que as regras de seeding finjam que h\u00e1 uma c\u00f3pia completa (e assim incorretamente reduzindo o seu rank) ConfigView.label.seeding.fakeFullCopySeedStart=mas apenas para os torrents com pelo menos ConfigView.label.seeding.ignore=Ignorar Regras ConfigView.label.seeding.ignore0Peers=Ignorar torrents com 0 peers ConfigView.label.seeding.ignoreRatioPeers=Ignorar torrents que tenham pelo menos 1 seed para cada ConfigView.label.seeding.ignoreShareRatio=Ignorar torrents que tenham uma propor\u00e7\u00e3o de compartilhamento de ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorar o torrent mesmo se\nas regras de Primeira Prioridade se apliquem ConfigView.label.seeding.ignore.header.rule=Regra ConfigView.label.seeding.ignore.header.value=Valor ConfigView.label.seeding.firstPriority.info=Torrents com Primeira Prioridade sempre estar\u00e3o no topo da fila.\nQuaisquer torrents combinando com o Crit\u00e9rio de Primeira Prioridade n\u00e3o ser\u00e3o automaticamente parados e enfileirados.\nUm torrent combinando com o crit\u00e9rio de Primeira Prioridade tomar\u00e1 um slot de download simult\u00e2neo se ele precisar. ConfigView.label.seeding.firstPriority.FP=Primeira Prioridade ConfigView.label.seeding.firstPriority=A primeira prioridade vai para os torrents com ConfigView.label.seeding.firstPriority.following=os/dos seguintes: ConfigView.label.seeding.firstPriority.shareRatio=Uma propor\u00e7\u00e3o de compartilhamento inferior a ConfigView.label.seeding.firstPriority.seedingMinutes=Tempo decorrido desde que mudou de baixando para seeding ConfigView.label.seeding.firstPriority.DLMinutes=Um tempo decorrido desde o come\u00e7o do download ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Fingindo que h\u00e1 1 c\u00f3pia completa por X peers, voc\u00ea reduz o rank dos torrents com alta contagem de peers.\n\u00c9 prov\u00e1vel que os torrents com contagem alta de peers tamb\u00e9m possuam alto tr\u00e1fego.\nIsto n\u00e3o muda quaisquer das exibi\u00e7\u00f5es '# de seeds'. ConfigView.label.seeding.numPeersAsFullCopy=Fingir que h\u00e1 1 c\u00f3pia completa para cada\n(0 : N\u00e3o Fingir) ConfigView.label.seeding.preferLargerSwarms.tooltip=Se voc\u00ea est\u00e1 ficando de seed principalmente com torrents com peers que est\u00e3o "travados", preferir multid\u00f5es maiores faz sentido\nQuando voc\u00ea est\u00e1 ficando de seed principalmente com torrents com alta disponibilidade, preferir multid\u00f5es menores faz sentido. ConfigView.label.seeding.preferLargerSwarms=Quando os torrents tem o mesmo rank, preferir as multid\u00f5es maiores ConfigView.label.seeding.rankType.none.tooltip=Ordem baseada na coluna # ConfigView.label.seeding.rankType.none=Nenhum ConfigView.label.seeding.rankType.peer.tooltip=mais peers e menos seeds = higher rank\nEste ranking minimiza o n\u00famero de torrents que precisam ser mantidos ativos para maximizar o upload ConfigView.label.seeding.rankType.peer=Contagem de Peers Pesados ConfigView.label.seeding.rankType.peerSeed.options=Op\u00e7\u00f5es da Propor\u00e7\u00e3o dos Peers:Seeds ConfigView.label.seeding.rankType.peerSeed.tooltip=Maior Propor\u00e7\u00e3o = Maior Rank ConfigView.label.seeding.rankType.peerSeed=Propor\u00e7\u00e3o de Peers:Seed ConfigView.label.seeding.rankType.seed.fallback=Reverter para a Propor\u00e7\u00e3o de Peers:Seeds ap\u00f3s\n(0 : Nunca Reverter) ConfigView.label.seeding.rankType.seed.options=S\u00f3 Op\u00e7\u00f5es de Contagem dos Seeds ConfigView.label.seeding.rankType.seed.tooltip=Menos Seeds = Maior Rank ConfigView.label.seeding.rankType.seed=Apenas Contagem de Seeds ConfigView.label.seeding.rankType.timedRotation.tooltip=Todos os torrents completados na fila ir\u00e3o para o modo seeding.\nA dura\u00e7\u00e3o do tempo de seeding \u00e9 definida em 'Tempo M\u00ednimo de Seeding' ConfigView.label.seeding.rankType.timedRotation=Rota\u00e7\u00e3o Temporarizada ConfigView.label.seeding.rankType.tooltip=Torrents mais altos no ranking s\u00e3o iniciados automaticamente.\nQuando outro torrent obt\u00eam um rank maior, o de menor rank para e volta pra fila.\n\nApenas torrents em um estado Na Fila est\u00e3o dispon\u00edveis para in\u00edcio autom\u00e1tico.\nTorrents parados nunca s\u00e3o iniciados automaticamente. ConfigView.label.seeding.rankType=Colocar os torrents completados para auto-iniciar baseado em: ConfigView.label.stopAfterMinutes=Uma vez trocado para ficar de seed, parar ap\u00f3s uma dura\u00e7\u00e3o de tempo ConfigView.label.switchpriority.tooltip=Baixa prioridade reduz a largura de banda de upload fornecida ao torrent. ConfigView.pluginlist.info=Os seguintes plugins foram identificados. Alguns plugins podem n\u00e3o ter abas de configura\u00e7\u00e3o. ConfigView.pluginlist.noplugins=Nenhum plugin foi encontrado. ConfigView.section.pluginslist=Lista\t ConfigView.section.queue.seeding=Ficar de Seed ConfigView.section.queue.seeding.autoStarting=In\u00edcio Autom\u00e1tico ConfigView.section.queue.seeding.ignore=Ignorar Regras ConfigView.section.queue.seeding.firstPriority=Primeira Prioridade ConfigView.section.queue.main=Principal ConfigView.section.queue=Filas ConfigView.text.all=todos ConfigView.text.hours=horas ConfigView.text.ignoreRule=Ignorar Regra ConfigView.text.ignore=Ignorar ConfigView.text.minutes=minutos ConfigView.text.neverIgnore=Nunca Ignorar ConfigView.text.any=qualquer DownloadManager.error.datamissing=Dados Ausentes MainWindow.menu.file.open.torrentforseeding=Arquivo Torrent... (Para Ficar de Seed) MainWindow.menu.language.refresh=&Atualizar ManagerItem.forced=For\u00e7ado ManagerItem.queued=Na Fila MySeedersView.header=Torrents Completos TableColumn.header.availability.info=# de c\u00f3pias completas sendo vistas TableColumn.header.availability=Disponibilidade TableColumn.header.category=Categoria MyTorrentsView.header=Torrents Incompletos TableColumn.header.maxuploads=M\u00e1x de # Uploads MyTorrentsView.menu.category.delete=&Apagar Categoria MyTorrentsView.menu.forceStart=&For\u00e7ar In\u00edcio MyTorrentsView.menu.queue=&Fila MyTorrentsView.menu.setCategory.add=&Adicionar Categoria... MyTorrentsView.menu.setCategory=Designar Categoria TableColumn.header.savepath=Caminho para Salvar TableColumn.header.SeedingRank=Rank do Seeding TableColumn.header.totalspeed.info=Velocidade Total de todos os peers aos quais voc\u00ea est\u00e1 conectado TableColumn.header.totalspeed=Velocidade Total splash.initializePlugins=Inicializando os Plugins StartStopRules.SPratioMet=Propor\u00e7\u00e3o de S:P OK StartStopRules.shareRatioMet=Propor\u00e7\u00e3o de Compartilhamento OK StartStopRules.waiting=Aguardando StartStopRules.firstPriority=1a Prioridade ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Compartilhar Conte\u00fados (Recursivo) DownloadManager.error.unabletostartserver=Incapaz de iniciar o servidor - verifique a configura\u00e7\u00e3o da porta de entrada / e permiss\u00f5es no firewall para que o aplicativo aja como servidor GeneralView.label.creationdate=Criado Em : ConfigView.section.tracker.announcescrapepercentage=Intervalo do scrape com % da idade do an\u00fancio\nex: 200 = 2:1. 0 = deixar o peer decidir ManagerItem.stopping=Parando ConfigView.section.tracker.announcecacheperiod=Anunciar o cache (ms) ConfigView.section.tracker.scrapecacheperiod=Cache do scrape (ms) ConfigView.section.tracker.scrapeandcache=Scrape e cache ConfigView.section.tracker.announcecacheminpeers=Anunciar cache e ativar in\u00edcio do peer fileDownloadWindow.retry=Tentar Novamente MyTrackerView.bytesin=Bytes Recebidos MyTrackerView.bytesinave=M\u00e9dia de Entrada MyTrackerView.bytesout=Bytes Enviados MyTrackerView.bytesoutave=M\u00e9dia de Sa\u00edda ConfigView.section.file.max_open_files=M\u00e1ximo de arquivos abertos para leitura/escrita\n[0: ilimitados] ConfigView.section.file.max_open_files.tooltip=\u00datil se voc\u00ea baixa torrents com centenas/milhares de arquivos neles, e se voc\u00ea est\u00e1 atingindo o limite de gerenciamento de arquivos do SO. ConfigView.section.proxy=Op\u00e7\u00f5es do Proxy ConfigView.section.proxy.enable_proxy=Ativar Proxying de comunica\u00e7\u00f5es com o tracker [requer reiniciar] ConfigView.section.proxy.host=Servidor ConfigView.section.proxy.port=Porta ConfigView.section.proxy.username=Nome de Usu\u00e1rio ConfigView.section.proxy.password=Senha ConfigView.section.proxy.enable_socks=Eu tenho um Proxy SOCKS wizard.createtorrent.extrahashes=Adicionar hashes para as outras redes (ex: Gnutella2, eDonkey2000) GeneralView.label.connected=conectado(s) GeneralView.label.in_swarm=na multid\u00e3o ManagerItem.initializing=Inicializando AlertMessageBox.error=Erro AlertMessageBox.warning=Aviso AlertMessageBox.comment=Informa\u00e7\u00f5es AlertMessageBox.information=Informa\u00e7\u00e3o AlertMessageBox.unread=Voc\u00ea n\u00e3o leu as mensagens de alerta - clique aqui para exib\u00ed-las. SharedPortServer.alert.selectorfailed=Falhou em estabelecer um ouvidor para os dados de entrada.\nVerifique se as configura\u00e7\u00f5es de firewall est\u00e3o permitindo que o java(w).exe ajam como um 'servidor' Tracker.alert.listenfail=Falhou em estabelecer a escuta na porta %1.\nVerifique se outros aplicativos j\u00e1 n\u00e3o est\u00e3o usando esta porta.\nVerifique tamb\u00e9m se h\u00e1 outra c\u00f3pia do Vuze rodando. DiskManager.alert.movefileexists=Erro ao mover arquivos completos\nO arquivo %1 j\u00e1 existe no diret\u00f3rio de destino MoveTo DiskManager.alert.movefilefails=Erro ao mover arquivos completos\nA movimenta\u00e7\u00e3o do arquivo %1 falhou, %2 DiskManager.alert.movefilerecoveryfails=Erro ao recuperar ap\u00f3s uma falha de movimenta\u00e7\u00e3o\nRestaura\u00e7\u00e3o do arquivo %1 falhou, %2 ConfigView.section.tracker.logenable=Registrar as estat\u00edsticas per\u00edodicas em 'tracker.log' SpeedView.stats.title=Estat\u00edsticas SpeedView.stats.session=Esta Sess\u00e3o SpeedView.stats.session.tooltip=Total (Protocolo) SpeedView.stats.downloaded=Baixado (Protocolo) SpeedView.stats.uploaded=Enviado (Protocolo) SpeedView.stats.ratio=Propor\u00e7\u00e3o SpeedView.stats.uptime=Tempo de Upload SpeedView.stats.now=Agora SpeedView.stats.now.tooltip=Total (Protocolo) AutoMigration.useralert=Arquivos da configura\u00e7\u00e3o do usu\u00e1rio do Vuze/resultados da auto-migra\u00e7\u00e3o dos diret\u00f3rios:\n\n%1\nQuaisquer falhas devem ser migradas manualmente.\nN\u00c3O SE ESQUE\u00c7A DE ATUALIZAR OS CAMINHOS PARA SALVAR NA SUA CONFIGURA\u00c7\u00c3O SE ELES FORAM MIGRADOS! # # > 2.0.8.0 # OpenTorrentWindow.title=Abrir Torrent(s) OpenTorrentWindow.addFiles=&Adicionar Arquivos OpenTorrentWindow.dataLocation=Local para salvar os dados: OpenTorrentWindow.startMode=Adicionar Modo OpenTorrentWindow.startMode.queued=Na Fila OpenTorrentWindow.startMode.stopped=Parado OpenTorrentWindow.startMode.forceStarted=For\u00e7ar In\u00edcio OpenTorrentWindow.addPosition=Posi\u00e7\u00e3o na Fila OpenTorrentWindow.addPosition.first=Primeiro OpenTorrentWindow.addPosition.last=\u00daltimo TableColumn.header.remaining.info=Quantia restante para baixar TableColumn.header.remaining=Restando ConfigView.section.tracker.enablecompact=Ativar o protocolo de an\u00fancio compacto ConfigView.section.tracker.enablekey=Ativar a entrega da chave ao tracker para seguran\u00e7a melhorada ConfigView.section.file.perf=Op\u00e7\u00f5es de Performance ConfigView.section.file.perf.explain=Aviso - Mudan\u00e7as inadequadas destes par\u00e2metros podem afetar adversamente o desempenho do download. Requer reiniciar.\nSe voc\u00ea tem problemas com "falta de mem\u00f3ria" considere limitar as conex\u00f5es por torrent (Veja as configura\u00e7\u00f5es das Transfer\u00eancias) ConfigView.section.file.max_open_files.explain=Abrir muitos arquivos pode causar problemas no sistema operacional devido aos recursos limitados dos gerenciadores de arquivos. Isto limita o n\u00famero de arquivos abertos coincidentes. popup.error.hide=Esconder popup.error.details=Detalhes ConfigView.section.style.colorOverrides=N\u00e3o Levar em Conta as Cores ConfigView.section.style.colorOverride.progressBar=Barra de Progresso ConfigView.section.style.colorOverride.error=Erro MainWindow.status.tooOld=\u00e9 antiga, por favor atualize-a. ConfigView.section.style.colorOverride.warning=Aviso ConfigView.section.style.colorOverride.altRow=Linhas Alternadas ConfigView.section.file.save.peers.enable=Salvar as conex\u00f5es com o peer para reconex\u00f5es r\u00e1pidas ConfigView.section.file.save.peers.max=M\u00e1ximo de peers a salvar [0: ilimitados] ConfigView.section.file.save.peers.pertorrent=por torrent ConfigView.label.max_peers_per_torrent=M\u00e1ximo de conex\u00f5es padr\u00e3o por torrent [0: ilimitadas] ConfigView.label.max_peers_total=M\u00e1ximo de conex\u00f5es globais [0: ilimitadas] ConfigView.section.style.colorOverrides.reset=Redefinir Cor ConfigView.section.language.info=Quando ativada, uma verifica\u00e7\u00e3o de atualiza\u00e7\u00e3o ocorrer\u00e1 toda vez que o Vuze iniciar. ConfigView.section.language.enableUpdate=Ativar Atualiza\u00e7\u00e3o via Web ConfigView.section.language.UpdateURL=URL da Atualiza\u00e7\u00e3o ConfigView.section.language.UpdateNow=Atualizar Agora! Button.revert=Inverter MyTorrentsView.menu.changeDirectory=Mudar o Diret\u00f3rio de Dados GenericText.column=coluna MyTorrentsView.menu.thisColumn.remove=Remover Coluna MyTorrentsView.menu.thisColumn.toClipboard=Copiar o Texto para a \u00c1rea de Transfer\u00eancia MyTorrentsView.menu.thisColumn.autoTooltip=Sempre exibir dicas TableColumn.header.secondsseeding=Fazendo Seed Por TableColumn.header.secondsseeding.info=Quantia total de tempo que voc\u00ea esteve fazendo see. TableColumn.header.secondsdownloading=Baixando Para TableColumn.header.secondsdownloading.info=Quantia de tempo que voc\u00ea esteve baixando. ConfigView.section.tracker.udpversion=Vers\u00e3o do Protocolo UDP (1 ou 2) window.updateswt.title=Sua vers\u00e3o da SWT \u00e9 muito antiga! window.updateswt.text=Sua vers\u00e3o do SWT \u00e9 muito antiga!\nA SWT \u00e9 a biblioteca gr\u00e1fica usada pelo Vuze, e a vers\u00e3o que voc\u00ea tem \u00e9 muito antiga para rodar a \u00faltima vers\u00e3o do Vuze. Clique no bot\u00e3o OK para atualizar sua SWT. window.updateswt.failed=A atualiza\u00e7\u00e3o falhou, pressione OK de novo para reiniciar. window.updateswt.status.downloading.updater=Baixando o M\u00f3dulo de Atualiza\u00e7\u00e3o window.updateswt.status.finding=Procurando a \u00faltima vers\u00e3o da SWT window.updateswt.status.downloading=Baixando a \u00daltima Vers\u00e3o da SWT window.updateswt.status.done=Reiniciando window.updateswt.cancel=Cancelar swt.updater.downloader.downloading=Baixando o SWT de swt.updater.urlsgetter.downloading=Obtendo uma lista de mirrors de swt.updater.urlsgetter.platform=SWT para a plataforma : window.updateswt.ignore=Ignorar ConfigView.section.style.useFancyTabs=Usar Abas Extravagantes splash.initializeGM=Inicializando o Gerenciador Global de Torrents splash.loadingTorrents=Carregando Torrents MyTorrentsView.menu.thisColumn.sort=&Ordenar Scrape.status.ok=Scrape Ok Scrape.status.error=Erro de Scrape: Scrape.status.error.badURL=A URL de an\u00fancio n\u00e3o obedece \u00e0s especifica\u00e7\u00f5es de scrape. Scrape.status.error.nohash=Hash inexistente na resposta. Scrape.status.error.invalid=Reposta inv\u00e1lida. Scrape.status.nextScrapeAt=Pr\u00f3xima scrape em %1 Scrape.status.scraping=Scraping.. Scrape.status.initializing=Aguardando para Scrape Scrape.status.scraping.queued=Scraping na fila... ConfigView.label.minSpeedForActiveSeeding=N\u00e3o contar torrent completo como usando um slot se a velocidade for inferior a ConfigView.section.stats.exportpeers=Exportar os detalhes dos peers MainWindow.menu.view.irc.moved=O Irc est\u00e1 agora dispon\u00edvel como um plugin, veja http://azureus.sourceforge.net/plugin_list.php. Quando instalado, use o menu visualizar->plugins->menu IRC para acess\u00e1-lo MyTrackerView.webui.contextmenu.copyurl=Copia a URL do torrent para a \u00c1rea de Transfer\u00eancia ConfigView.section.file.torrent.ignorefiles=Arquivos a ignorar quando criar torrents\nex: .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignorando arquivo ConfigView.section.style.useUnitsRateBits=Usar bits em vez de bytes para os valores das taxas baseadas em bytes (KiB/s->Kibit/s etc.) ConfigView.section.interface.resetassoc=Redefinir associa\u00e7\u00f5es de arquivos do explorer (.torrent) ConfigView.section.interface.resetassocbutton=Redefinir ConfigView.section.interface.checkassoc=Verificar associa\u00e7\u00f5es ao iniciar dialog.associations.title=Verifica\u00e7\u00e3o de Associa\u00e7\u00e3o Button.yes=Sim Button.no=N\u00e3o ConfigView.label.seeding.autoStart0Peers=Auto-Iniciar todos os torrents completados com 0 peers ConfigView.label.seeding.autoStart0Peers.tooltip=Marque se voc\u00ea quer que o tracker sempre liste os seeds para torrents com 0 Peers. dialog.associations.prompt=O Vuze n\u00e3o \u00e9 o aplicativo padr\u00e3o para arquivos BitTorrent.\nVoc\u00ea gostaria de associar os arquivos .torrent com o Vuze? dialog.associations.askagain=Verificar ao iniciar ConfigView.section.plugins.update=Atualiza\u00e7\u00e3o dos Plugins Plugin.pluginupdate.enablecheck=Ativar a verifica\u00e7\u00e3o por atualiza\u00e7\u00f5es dos plugins plugins.basicview.activity=Atividade: plugins.basicview.progress=Progresso: plugins.basicview.log=Registro: ConfigView.label.maxdownloadspeed=Velocidade m\u00e1xima global de download em KB/s [0: ilimitada] splash.loadingTorrent=Carregando Torrent splash.of=de UpdateWindow.title=Atualizador do Vuze UpdateWindow.header=Os seguintes componentes precisam de uma atualiza\u00e7\u00e3o : UpdateWindow.columns.install=Instalar UpdateWindow.columns.name=Nome UpdateWindow.columns.version=Vers\u00e3o UpdateWindow.columns.size=Tamanho UpdateWindow.cancel=Cancelar UpdateWindow.quit=Sair UpdateWindow.close=Fechar UpdateWindow.ok=Atualizar UpdateWindow.restart=Reiniciar UpdateWindow.status.downloading=Baixando UpdateWindow.status.done=Pronto UpdateWindow.status.failed=Falha UpdateWindow.status.restartNeeded=Reiniciar ser\u00e1 necess\u00e1rio! ConfigView.pluginlist.broken=Quebrado ConfigView.pluginlist.whereToPut=Colocar quaisquer plugins espec\u00edficos-para-o-usu\u00e1rio em seu pr\u00f3prio diret\u00f3rio: ConfigView.pluginlist.whereToPutOr=Para plugins compartilhados usar: MainWindow.statusText.checking=Procurando por Atualiza\u00e7\u00f5es TableColumn.header.OnlyCDing4=S\u00f3FazendoSeed4 TableColumn.header.OnlyCDing4.info=Quantia de tempo que o torrent esteve fazendo seed. Exclui o tempo que o torrent estava baixando (e fazendo seed). ConfigView.section.style.alternateTablePainting=Usar m\u00e9todo alternativo para desenhar os gr\u00e1ficos de tabela das colunas (pode ser necess\u00e1rio reiniciar) UpdateWindow.status.restartMaybeNeeded=Pode ser necess\u00e1rio reiniciar ConfigView.pluginlist.shared=compartilhado PeersView.host=Nome do Servidor PeersView.host.info=O nome do servidor do peer, quando dispon\u00edvel (pode afetar a performance) MainWindow.menu.help.whatsnew=O que h\u00e1 de novo? ConfigView.label.checkonstart=Procurar pela \u00faltima vers\u00e3o quando o Vuze iniciar ConfigView.label.periodiccheck=Procurar pela \u00faltima vers\u00e3o periodicamente ConfigView.label.opendialog=Abrir automaticamente o Assistente de Atualiza\u00e7\u00e3o quando uma atualiza\u00e7\u00e3o estiver dispon\u00edvel MainWindow.updateavail=Clique aqui para atualiza\u00e7\u00f5es MainWindow.status.unofficialversion=Beta do Vuze MainWindow.status.latestversionunchecked=Verifica\u00e7\u00e3o de vers\u00e3o desativada GeneralView.label.updatein.stopped=Parado StartStopRules.menu.viewDebug=Ver Informa\u00e7\u00f5es de Debug ConfigView.section.style.doNotUseGB=N\u00e3o usar a unidade GB ConfigView.section.style.doNotUseGB.tooltip=Se marcado, o Vuze continuar\u00e1 a usar MB mesmo para tamanhos maiores do que 1024MB MainWindow.menu.help.plugins=Plugins ConfigView.section.plugins.TrackerWeb=Web Tracker ConfigView.section.tracker.enablecategories=Separar os torrents por categoria health.explain.share=significa que o torrent ou est\u00e1 hospedado ou publicado ConfigView.section.tracker.createcert=Criar certificado auto-assinado ConfigView.section.tracker.createbutton=Criar security.certcreate.title=Criar um Certificado Auto-Assinado security.certcreate.intro=Este di\u00e1logo permite a voc\u00ea criar um certificado auto-assinado security.certcreate.alias=Apelido security.certcreate.strength=For\u00e7a security.certcreate.firstlastname=Primeiro e \u00faltimo nome security.certcreate.orgunit=Unidade Organizacional security.certcreate.org=Organiza\u00e7\u00e3o security.certcreate.city=Cidade ou Localidade security.certcreate.state=Estado ou Prov\u00edncia security.certcreate.country=C\u00f3digo do pa\u00eds com duas letras security.certcreate.ok=Criar security.certcreate.cancel=Cancelar security.certcreate.createok=Certificado criado com sucesso security.certcreate.createfail=Cria\u00e7\u00e3o do certificado falhou ConfigView.section.plugins.webui=Interface Swing Web ConfigView.section.plugins.xml_http_if=Interface XML/HTTP webui.passwordenable=Ativar senha webui.user=Nome de usu\u00e1rio webui.password=Senha webui.port=Porta (*) webui.protocol=Protocolo (*) webui.homepage=Home Page (*) webui.rootdir=Diret\u00f3rio Raiz (*) webui.rootres=Recurso Raiz (*) webui.mode=Modo (*) webui.mode.info=O modo pode ser\n\t"full"\t= todas as opera\u00e7\u00f5es dispon\u00edveis (padr\u00e3o)\n\t"view"\t= ver apenas (mas pode atualizar a freq\u00fc\u00eancia de atualiza\u00e7\u00e3o) webui.access=Accesso (*) webui.access.info=O acesso pode ser\n\t"local"\t= significando que apenas a m\u00e1quina local pode conectar-se\n\t"all"\t= acesso irrestrito (default)\n\tIP\t= e.x. 192.168.0.2\t\t\tapenas um IP\n\tIP1-IP2\t= e.x. 192.168.0.1-192.168.0.255\tfaixa de IP inclusiva GeneralView.label.maxdownloadspeed=Limite de Down Security.keystore.corrupt=Keystore '%1' falhou ao carregar, por favor apague-a e recrie/re-importe os certificados Security.keystore.empty=O keystore est\u00e1 vazio. Por favor, crie um certificado auto-assinado (veja Ferramentas->Op\u00e7\u00f5es->Seguran\u00e7a) ou importe um certificado existente para '%1' webui.restart.info=Altera\u00e7\u00f5es nos par\u00e2metros marcados com um (*) requerem reiniciar para terem efeito GeneralView.label.maxdownloadspeed.tooltip=Velocidade M\u00e1xima de Download [0: ilimitada] upnp.enable=Ativar UPnP upnp.info=Universal Plug and Play (UPnP) permite o mapeamento autom\u00e1tico de portas nos roteadores com UPnP ativado. upnp.mapping.dataport=Porta de Entrada dos Dados do Peer upnp.mapping.tcptrackerport=Porta do Tracker TCP upnp.mapping.udptrackerport=Porta do Tracker UDP upnp.alert.differenthost=UPnP: O Mapeamento '%1' foi reservado por '%2' - por favor selecione uma porta\tdiferente upnp.alert.mappingok=UPnP: Mapeamento '%1' estabelecido upnp.alert.mappingfailed=UPnP: Falha no mapeamento '%1' upnp.alertsuccess=Relatar mapeamentos bem-sucedidos upnp.alert.lostdevice=UPnP: Conex\u00e3o com o servi\u00e7o '%1' no dispositivo UPnP '%2' perdida upnp.grabports=Mapear portas mesmo se possu\u00eddas por outro computador upnp.refresh.label=Atualizar os mapeamentos upnp.refresh.button=Atualizar upnp.alert.mappinggrabbed=UPnP: Mapeamento '%1' estabelecido - obtido de '%2' upnp.mapping.tcpssltrackerport=Porta do Tracker TCP SSL upnp.alertothermappings=Relatar portas possu\u00eddas por outros computadores upnp.alertdeviceproblems=Relatar problemas com o dispositivo UPnP upnp.trace_to_log=Informa\u00e7\u00e3o de debug completa da sa\u00edda de dados no log upnp.wiki_link=P\u00e1gina do wiki do Vuze sobre o UPnP upnp.refresh_mappings_on_bad_nat=Automaticamente atualizar os mapeamentos quando o status do NAT \u00e9 "firewalled" ConfigView.pluginlist.coreplugins=Os seguintes plugins embutidos est\u00e3o carregados: Peers.column.DLedFromOthers=De Outros Peers.column.DLedFromOthers.info=Quantidade de dados recebidos de outros enquanto conectados a voc\u00ea Peers.column.UpDownRatio.info=A Propor\u00e7\u00e3o "Enviados : Baixados" do Peer Peers.column.UpRatio=Propor\u00e7\u00e3o de Upload Peers.column.UpRatio.info=A propor\u00e7\u00e3o "Enviar por voc\u00ea : Enviado por outros" do Peer upnp.releasemappings=Liberar os mapeamentos ao fechar webui.upnpenable=Ativar UPnP para esta porta (*) ConfigView.section.file.friendly.hashchecking=Verifica\u00e7\u00e3o de hash amig\u00e1vel ConfigView.section.file.friendly.hashchecking.tooltip=Um levemente mais lento, mais muito menos stressante no cpu/sistema, modo de checagem de hash por peda\u00e7o. ConfigView.section.tracker.seedretention=M\u00e1ximo de seeds retidos por torrent [0: ilimitados] ConfigView.section.tracker.seedretention.info=Nota: As estat\u00edsticas de upload ser\u00e3o perdidas para seeds n\u00e3o retidos ConfigView.section.tracker.port=Ativar tracker na porta HTTP ConfigView.section.tracker.sslport=Ativar tracker na porta HTTPS ConfigView.section.tracker.publicenable.info=Isto permite que outros criem torrents que usem o seu tracker\nsem que voc\u00ea os hospede/publique Button.clear=Limpar MainWindow.IPs.tooltip=\u00daltima atualiza\u00e7\u00e3o da lista de filtros: %1\nTotal de Filtros IP na lista - N\u00ba de IPs bloqueados/banidos/ruins nesta sess\u00e3o.\nClique duas vezes para detalhes. ConfigView.section.ipfilter.list.banned=foi banido ConfigView.section.ipfilter.list.baddata=enviou dados ruins: ocorr\u00eancias = Button.reset=Resetar ConfigView.section.ipfilter.bannedinfo=IPs que enviaram dados ruins - banidos se os limites excederam ConfigView.section.ipfilter.blockedinfo=IPs que foram bloqueados pelos filtros de IP download.removerules.name=Regras de Remo\u00e7\u00e3o download.removerules.unauthorised.info=Torrents n\u00e3o-autorizados s\u00e3o aqueles nos quais a resposta ao an\u00fancio cont\u00e9m "n\u00e3o-autorizado" ou "desautorizado" na "falha na resposta" download.removerules.unauthorised=Remover torrents n\u00e3o-autorizados automaticamente download.removerules.unauthorised.seedingonly=\tApenas se ficar de seed download.removerules.removed.ok=Remo\u00e7\u00e3o autom\u00e1tica do torrent '%1' bem-sucedida. Isto foi causado pelas regras de remo\u00e7\u00e3o de torrents download.removerules.updatetorrents=Remover os torrents de atualiza\u00e7\u00e3o conforme a multid\u00e3o requerir ConfigView.label.defaultstarttorrentsstopped=Por padr\u00e3o adicionar novos torrents no estado parado ConfigView.section.server.enableudp=Ativar o protocolo do cliente tracker UDP. upnp.mapping.dataportudp=Porta do cliente tracker UDP ConfigView.section.file.decoder.showlax=Mostrar menos codifica\u00e7\u00f5es ConfigView.section.file.decoder.showall=Considerar todas as codifica\u00e7\u00f5es poss\u00edveis MainWindow.status.updowndetails.tooltip=Detalhes da velocidade de Download/Upload\nClique com o bot\u00e3o direito para mudar, clique 2 vezes para abrir as estat\u00edsticas TrackerClient.announce.warningmessage=O tracker '%1' retornou o aviso '%2' ConfigView.section.tracker.natcheckenable=Verifica a conectividade da 'porta de entrada de dados' e reporta as falhas para os peers ConfigView.section.tracker.publishenabledetails=Publicar todos os detalhes do torrent ConfigView.section.tracker.publishenablepeerdetails=Publica os detalhes do peer MyTrackerView.badnat=NAT Ruim MyTrackerView.badnat.info=Seeds/Peers que falharam a uma checagem do NAT, se ativados ConfigView.section.tracker.natchecktimeout=Verifica o esgotamento do tempo (segs) ConfigView.section.file.perf.cache.enable=Ativar cache de disco ConfigView.section.file.perf.cache.size=Tamanho do cache em %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=T&ransfer\u00eancias MainWindow.menu.transfers.startalltransfers=C&ome\u00e7ar Todos MainWindow.menu.transfers.stopalltransfers=P&arar Todos MainWindow.menu.transfers.pausetransfers=&Pausar MainWindow.menu.transfers.resumetransfers=&Resumir ConfigView.label.experimental.osx.kernel.panic.fix=Corre\u00e7\u00e3o experimental para os p\u00e2nicos do kernel em sistemas dual-cpu OSX [requer reiniciar] SystemTray.menu.pausetransfers=Pausar Transfer\u00eancias SystemTray.menu.resumetransfers=Resumir Transfer\u00eancias ConfigView.section.file.truncate.too.large=Cortar os arquivos existentes que s\u00e3o muito grandes ConfigView.section.file.perf.cache.trace=Rastrear opera\u00e7\u00f5es de cache para fins de diagn\u00f3stico ConfigView.section.interface.enabletray=Ativar o Tray do sistema [requer reiniciar] PeerManager.status.error=Erro Stats.title.full=Estat\u00edsticas TransferStatsView.title.full=Transfer\u00eancias CacheView.general.size=Total CacheView.general.inUse=Em Uso CacheView.general.title=Info sobre o Cache CacheView.reads.title=Leituras E/S CacheView.reads.fromFile=Do Arquivo CacheView.reads.fromCache=Do Cache CacheView.reads.hits=Acertos CacheView.writes.title=Escritas E/S CacheView.writes.toCache=Para o Cache CacheView.writes.toFile=Para o Arquivo CacheView.writes.hits=Salvos CacheView.speeds.title=Taxa de Dados CacheView.speeds.reads=Leituras CacheView.speeds.writes=Escritas CacheView.speeds.fromCache=Do/Para o Cache CacheView.speeds.fromFile=Do/Para o Arquivo CacheView.reads.amount=Quantidade CacheView.reads.avgsize=Tamanho M\u00e9dio openUrl.referrer=URL da p\u00e1gina de refer\u00eancia: openUrl.referrer.info=Requerido apenas para sites da web que os pe\u00e7am ConfigView.label.maxuploadspeedseeding=Alternar a taxa apenas quando ficando de seed ConfigView.label.transfer.ignorepeerports=Ignorar peers com estas portas de dados (';' separadas, ex: 0;25) ConfigView.section.proxy.enable_socks.peer=Ativar o proxying das comunica\u00e7\u00f5es com os peers (apenas para conex\u00f5es de sa\u00edda) [requer reiniciar] ConfigView.section.proxy.peer.informtracker=Informar a limita\u00e7\u00e3o ao tracker ConfigView.section.proxy.socks.version=Vers\u00e3o do SOCKS PiecesView.legend.written=Escritos PiecesView.legend.requested=Requeridos PiecesView.legend.downloaded=Baixados, escrita pendente PiecesView.legend.incache=Dados est\u00e3o no Cache PiecesView.typeItem.0=Lento PiecesView.typeItem.1=R\u00e1pido PiecesView.type=Tipo Security.jar.tools_not_found=Assinatura JAR falhou - 'tools.jar' n\u00e3o encontrado em %1. Veja Ferramentas->Op\u00e7\u00f5es->Seguran\u00e7a para detalhes. Security.jar.signfail=Assinatura JAR falhou - %1 ConfigView.section.security.toolsinfo=Arquivos JAR assinados s\u00e3o usados para ajudar alguns plugins, por exemplo o Swing Web Interface (quando configurado para faz\u00ea-lo).\nPara assinar arquivos JAR \u00e9 necess\u00e1rio ter accesso ao arquivo 'tools.jar' que vem com a instala\u00e7\u00e3o do Sun JDK (n\u00e3o do JRE).\nSe voc\u00ea s\u00f3 tiver instalado o JRE ent\u00e3o por favor instale o JDK.\nNormalmente o Vuze pode achar o arquivo para voc\u00ea. Entretanto, se isto falhar, voc\u00ea pode explicitamente definir o diret\u00f3rio contendo-o aqui. ConfigView.section.security.toolsdir=Diret\u00f3rio contendo o arquivo 'tools.jar' ConfigView.section.security.choosetoolssavedir=Selecione a pasta contendo o arquivo 'tools.jar' ConfigView.section.proxy.peer.same=Usar as mesmas configura\u00e7\u00f5es de proxy para o tracker e para as comunica\u00e7\u00f5es com os peers ConfigView.section.connection.network.max.simultaneous.connect.attempts=M\u00e1x. de tentativas de conex\u00f5es de sa\u00edda simult\u00e2neas ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=N\u00famero m\u00e1ximo de novos estabelecimentos de conex\u00f5es de sa\u00edda que o Vuze deve tentar a qualquer tempo dado.\nNOTA: O Service Pack 2 do Windows XP (SP2) imp\u00f5e um limite para o sistema de apenas 10 tentativas para conectar simult\u00e2neas.\nO valor padr\u00e3o \u00e9 8. ConfigView.section.file.perf.cache.size.explain=O cache \u00e9 usado para reduzir as leituras do/escritas ao disco. A menos que voc\u00ea esteja usando a op\u00e7\u00e3o java '-XX:MaxDirectMemorySize' para explicitamente definir a mem\u00f3ria dispon\u00edvel para ser o cache e a rede IO usar, voc\u00ea deve manter esse valor a pelo menos %1 abaixo do tamanho m\u00e1ximo do seu VM. O tamanho atual m\u00e1ximo do VM \u00e9 %2. Para instru\u00e7\u00f5es sobre como mudar isto, veja MemoryUsage no Wiki sobre %3. Falha em usar as configura\u00e7\u00f5es sens\u00edveis resultar\u00e3o em erros de 'falta de mem\u00f3ria'. Mais de 32MB de cache \u00e9 provavelmente uma dose excessiva. MyTorrentsView.menu.setSpeed.unlimit=Sem limite MyTorrentsView.menu.setSpeed.unlimited=Ilimitado MyTorrentsView.menu.setSpeed.disable=Desativar Upload MyTorrentsView.menu.setSpeed.disabled=Desativado MyTorrentsView.menu.setSpeed.in=entrada MyTorrentsView.menu.setSpeed.slots=slots de GeneralView.label.maxuploadspeed=Limite de Up GeneralView.label.maxuploadspeed.tooltip=velocidade m\u00e1x. de upload [0 : ilimitada] MyTorrents.items.UpSpeedLimit.disabled=Sem upload MyTorrents.items.UpSpeedLimit.unlimited=Ilimitado TableColumn.header.maxupspeed=M\u00e1x de Velocidadde de Up TableColumn.header.maxupspeed.info=M\u00e1x de Velocidade de Upload por torrent ConfigView.section.file.perf.cache.enable.write=Armazenar os dados de download no cache para reduzir as escritas em disco e tamb\u00e9m diminuir as leituras do disco requeridas para a checagem dos peda\u00e7os ConfigView.section.file.perf.cache.enable.read=Realizar leituras adiantadas para reduzir as leituras do disco enquanto faz upload ConfigView.section.tracker.separatepeerids=Usar diferentes identidades de peer para o tracker e para a comunica\u00e7\u00e3o de dados ConfigView.section.tracker.separatepeerids.info=Aumenta a anonimidade se estiver baixando/enviando anonimamente\nenquanto estiver usando um conex\u00e3o com o tracker n\u00e3o-an\u00f4nima ConfigView.section.interface.wavlocation=Localiza\u00e7\u00e3o do arquivo .wav ConfigView.section.interface.wavlocation.info=Selecione o arquivo .wav ou deixe em branco para o som padr\u00e3o ConfigView.section.tracker.server=Servidor ConfigView.section.tracker.client=Cliente ConfigView.section.tracker.client.connecttimeout=A conex\u00e3o expira em (segs) ConfigView.section.tracker.client.readtimeout=A leitura expira em (secs) MainWindow.menu.tools=&Ferramentas FilesView.path=Caminho FilesView.fullpath=Mostrar Caminho Completo FilesView.remaining=Peda\u00e7os Restantes TableColumn.header.trackername=Nome do Tracker TableColumn.header.trackername.info=Nome do tracker baseado na URL de an\u00fancio ConfigView.group.override=N\u00e3o Levar as Op\u00e7\u00f5es em Conta ConfigView.section.file.perf.cache.notsmallerthan=N\u00e3o colocar no cache arquivos menores que isto (em %1) PeersView.menu.blockupload=Bloquear Upload PeersView.menu.kickandban=Chutar e Banir PeersView.menu.kickandban.reason=Peer banido manualmente PeersView.state=Estado PeersView.state.info=Estado da conex\u00e3o com o peer PeersView.state.pending=Pendente PeersView.state.connecting=Conectando PeersView.state.handshake=Esperando pelo handshake PeersView.state.established=Completamente estabelecida ConfigView.section.tracker.processinglimits=Limites de processamento ConfigView.section.tracker.maxgettime=Tempo m\u00e1x. para processamento GET (segundos) [0:ilimitado] ConfigView.section.tracker.maxgettime.info=Usado para an\u00fancio e limpezas ConfigView.section.tracker.maxposttimemultiplier=Multiplicador de tempo para processamento POST [0:ilimitado] ConfigView.section.tracker.maxposttimemultiplier.info=Usado para formar submiss\u00f5es e uploads ConfigView.section.tracker.maxthreads=M\u00e1x. de pedidos coincidentes DownloadManager.error.operationcancancelled=Opera\u00e7\u00e3o cancelada Torrent.create.progress.cancelled=Opera\u00e7\u00e3o cancelada sharing.progress.cancel=Cancelar wizard.maketorrents.autoopen=Abrir o torrent para ficar de seed quando completo ConfigView.section.sharing.rescanenable=Ativar re-escaneamento peri\u00f3dico dos compartilhados por mudan\u00e7as ConfigView.section.sharing.rescanperiod=Per\u00edodo de re-escaneamento (segs) ConfigView.section.connection.advanced=Configura\u00e7\u00f5es de Rede Avan\u00e7adas ConfigView.section.connection.advanced.url=http://azureuswiki.com/index.php/AdvancedNetworkSettings ConfigView.section.connection.advanced.mtu=Unidade de Transmiss\u00e3o M\u00e1xima da Linha (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Tamanho m\u00e1ximo de um pacote que pode ser transferido em um frame na rede.\nO Vuze usa MTU-40 (MSS) para otimiza\u00e7\u00f5es de packet-payload de upload.\nValores recomendados:\n 576 - Conex\u00f5es Dial-up\n1492 - Conex\u00f5es de banda larga PPPoE\n1500 - conex\u00f5es de banda larga a Cabo,Ethernet e DSL ConfigView.section.connection.advanced.SO_RCVBUF=Tamanho do Socket SO_RCVBUF [0: usar o padr\u00e3o do SO] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Define o valor do socket padr\u00e3o SO_RCVBUF (em bytes), i.e. tamanho e escala da janela de recebimento TCP.\nO Vuze deixa isto n\u00e3o definido por padr\u00e3o, significando que os padr\u00f5es para o SO b\u00e1sico s\u00e3o usados.\nNOTA: O linux dobra o valor dado. ConfigView.section.connection.advanced.SO_SNDBUF=Tamanho do Socket SO_SNDBUF [0: usar o padr\u00e3o do SO] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Define o valor do socket padr\u00e3o SO_SNDBUF (em bytes), i.e. o tamanho da janela de envio TCP.\nO Vuze deixa isto n\u00e3o definido por padr\u00e3o, siginificando que os padr\u00f5es para o SO b\u00e1sico s\u00e3o usados.\nNOTA: O linux dobra o valor dado. ConfigView.section.connection.advanced.IPDiffServ=Valor do DiffServ do pacote de sa\u00edda (campo do TOS) ConfigView.section.connection.advanced.IPDiffServ.tooltip=Define a parte do DiffServ do campo do tipo-de-servi\u00e7o (TOS) no cabe\u00e7alho do IP para os pacotes de sa\u00edda.\nValores hexadecimais podem ser especificados prefixando eles com '0x', ex: 0x10.\nO Vuze deixa isto n\u00e3o definido por padr\u00e3o, significando que os padr\u00f5es para o SO b\u00e1sico s\u00e3o usados.\nNOTA: As implementa\u00e7\u00e3o da rede b\u00e1sica pode ignorar este valor, ent\u00e3o esta op\u00e7\u00e3o \u00e9 altamente dependente das vers\u00f5es do SO e do JRE. ConfigView.section.interface.confirm_torrent_removal=Mostrar dialogo de comfirma\u00e7\u00e3o sobre a remo\u00e7\u00e3o de torrent ConfigView.section.interface.confirm_torrent_removal.tooltip=Confirmar quando estiver removendo um torrent de MeusTorrents. MyTorrentsView.confirm_torrent_removal=Voc\u00ea tem certeza que voc\u00ea quer remover?\n TableColumn.header.seed_to_peer_ratio=Propor\u00e7\u00e3oSeed2Peer TableColumn.header.seed_to_peer_ratio.info=Total da propor\u00e7a\u00f5 de seeds para peers na multid\u00e3o PeersView.connected_time=Tempo Conectado PeersView.connected_time.info=Tempo total que est\u00e1 conectado com o peer ConfigView.section.interface.display.add_torrents_silently=Adicionar torrents silenciosamente ConfigView.section.interface.display.add_torrents_silently.tooltip=Adicionar downloads de torrent sem ativar a janela principal do Vuze. TableColumn.header.maxdownspeed=M\u00e1x de Velocidade de Down TableColumn.header.maxdownspeed.info=M\u00e1x de Velocidade de Download por torrent PeersGraphicView.title=Multid\u00e3o ConfigView.section.tracker.passwordwebhttpsonly=S\u00f3 permitir o acesso via HTTPS TableColumn.header.torrentpath=Local do Torrent TableColumn.header.torrentpath.info=Local do Torrent no disco ConfigView.section.sharing.torrentcomment=Coment\u00e1rio para torrents gerados ConfigView.label.copyanddeleteratherthanmove=Copia e ent\u00e3o apaga os dados originais en vez de mov\u00ea-los em uma opera\u00e7\u00e3o - pode ajudar a evitar a perda de dados em alguns sistemas de arquivos ConfigView.label.openstatsonstart=Abrir as estat\u00edsticas ao iniciar swt.install.window.title=Instalador de Plugins do Vuze swt.install.window.ok=Instalar swt.install.window.header=Os seguintes componentes foram selecionados para a instala\u00e7\u00e3o : swt.uninstall.window.title=Removedor de Plugins do Vuze swt.uninstall.window.ok=Remover swt.uninstall.window.header=Os seguintes componentes foram selecionados para a remo\u00e7\u00e3o : installPluginsWizard.title=Instalar Plugins installPluginsWizard.mode.title=Por favor, escolha um m\u00e9todo de instala\u00e7\u00e3o installPluginsWizard.mode.list=Pela lista do sourceforge.net installPluginsWizard.list.title=Lista dos Plugins Instal\u00e1veis installPluginsWizard.list.loading=Por favor, espere enquanto a lista de plugins \u00e9 carregada. installPluginsWizard.list.loaded=Por favor, escolha os plugins que voc\u00ea quer instalar. installPluginsWizard.list.name=Nome installPluginsWizard.list.version=Vers\u00e3o installPluginsWizard.list.description=Descri\u00e7\u00e3o do plugin installPluginsWizard.finish.title=Instala\u00e7\u00e3o em Progresso installPluginsWizard.finish.explanation=Os plugins selecionados ser\u00e3o instalados usando o Assistente de Atualiza\u00e7\u00e3o.\n\nPor favor seja paciente, isto pode demorar um pouco para aparecer.\n\nPara um relat\u00f3rio do progresso, clique duas vezes a esquerda da barra de status. installPluginsWizard.details.loading=Carregando detalhes, aguarde por favor... installPluginsWizard.mode.file=Por arquivo installPluginsWizard.installMode.title=Por favor, escolha o tipo de instala\u00e7\u00e3o installPluginsWizard.installMode.user=Instalar o(s) plugin(s) somente para voc\u00ea installPluginsWizard.installMode.shared=Instalar o(s) plugin(s) para todos os usu\u00e1rios installPluginsWizard.file.title=Por favor procure o plugin que voc\u00ea quer instalar installPluginsWizard.file.file=Arquivo : installPluginsWizard.file.invalidfile=O arquivo n\u00e3o \u00e9 um plugin v\u00e1lido do Vuze. installPluginsWizard.file.no_such_file=Nenhum arquivo existe com o nome dado. installPluginsWizard.file.browse=Navegar... uninstallPluginsWizard.title=Desinstalar Plugins uninstallPluginsWizard.list.title=Lista dos Plugins Instalados uninstallPluginsWizard.list.loaded=Por favor, escolha os plugins que voc\u00ea quer desinstalar. installPluginsWizard.list.nullversion=N\u00ba da Vers\u00e3o uninstallPluginsWizard.finish.title=Desinstala\u00e7\u00e3o em Progresso uninstallPluginsWizard.finish.explanation=Os plugins selecionados ser\u00e3o desinstalados usando o Assistente de Atualiza\u00e7\u00e3o. MainWindow.menu.plugins.installPlugins=Assistente de Instala\u00e7\u00e3o... MainWindow.menu.plugins.uninstallPlugins=Assistente de Desinstala\u00e7\u00e3o... ConfigView.section.ipfilter.totalIPs=%1 IPs bloqueados no total, que s\u00e3o %2 da internet. update.instance.install=Checando a Instala\u00e7\u00e3o update.instance.uninstall=Checando a Desinstala\u00e7\u00e3o update.instance.update=Checando por Atualiza\u00e7\u00f5es MainWindow.status.update.tooltip=Duplo clique para informa\u00e7\u00e3o sobre o progresso updater.progress.window.title=Tarefas de Instala\u00e7\u00e3o Atuais updater.progress.window.info=Pressione 'Abortar' para terminar todas tarefas pendentes Button.abort=Abortar ConfigView.section.ipfilter.enablebanning=Bloquear peers que consistentemente mandam dados ruins Network.alert.acceptfail=Muitas falhas sucessivas ocorridas na porta %1, %2 - processamento abandonado. Por favor, cheque as configura\u00e7\u00f5es do firewall para esta porta para garantir que est\u00e1 habilitada para receber conex\u00f5es. MyShares.column.category=Categoria UpdateWindow.restartLater=Reiniciar Mais Tarde MainWindow.menu.file.restart=Reiniciar o Vuze MainWindow.dialog.restartconfirmation.title=Reiniciar o Vuze? MainWindow.dialog.restartconfirmation.text=Voc\u00ea realmente quer reiniciar o Vuze? deletetorrent.message1=Voc\u00ea est\u00e1 pra exclu\u00edr o TORRENT para :\n deletetorrent.message2=\nVoc\u00ea tem certeza que voc\u00ea quer prosseguir? ConfigView.label.prioritizemostcompletedfiles=Priorizar mais os arquivos de alta prioridade de acordo com a % completada e o tamanho do arquivo splash.plugin.init=Inicializando o Plugin: splash.plugin.UIinit=Inicializando a GUI do Plugin: %1 ConfigView.section.style.osx_small_fonts=Usar fontes pequenas [requer reiniciar] ConfigView.section.tracker.tcpnonblocking=Usar I/O n\u00e3o-bloqueador para processamento do tracker TCP. Selecionar esta op\u00e7\u00e3o requer que o tracker seja executado numa porta alternativa. Experimental! ConfigView.section.tracker.nonblocking=Op\u00e7\u00f5es n\u00e3o-bloqueadoras ConfigView.section.tracker.nonblockingconcmax=M\u00e1x. de conex\u00f5es coincidentes [0: ilimitadas] MyTorrentsView.menu.exportmenu=Exportar\t\t\t\t\t\t\t\t\t\t\t\t\t ConfigView.section.tracker.client.scrapeinfo=Desativar o scraping impedir\u00e1 que muitas das regras das filas dos torrents de funcionarem como elas confiam na informa\u00e7\u00e3o da multid\u00e3o obtida pelos trackers de scraping. ConfigView.section.tracker.client.scrapeenable=Ativar scraping ConfigView.section.tracker.client.scrapestoppedenable=Scrape torrents que n\u00e3o est\u00e3o rodando Scrape.status.disabled=Scrape Desativado MyTorrentsView.menu.explore=Mostrar Arquivo MyTorrentsView.menu.explore._mac=Mostrar no Descobridor MyTorrentsView.menu.explore._windows=Mostrar no Explorer wizard.maketorrents.autohost=Hospedar o torrent no tracker embutido ConfigView.label.overrideip=N\u00e3o levar em conta o(s) IP(s) de an\u00fancio do tracker - semi-v\u00edrgula os separa se h\u00e1 mais de um para diferentes redes ConfigView.label.overrideip.tooltip=Informar o tracker de diferentes endere\u00e7o(s) de IP do que aquele de onde os pacotes de sa\u00edda vem. Deixe em branco para n\u00e3o usar a op\u00e7\u00e3o. ConfigView.section.connection.group.networks=Redes ConfigView.section.connection.group.networks.info=Selecione as redes padr\u00e3o permitidas para a transmiss\u00e3o de dados peer-peer ConfigView.section.connection.networks.prompt=Alertar para a sele\u00e7\u00e3o quando um download com um tracker an\u00f4nimo \u00e9 adicionado ConfigView.section.connection.networks.Public=Rede de IP p\u00fablica (n\u00e3o an\u00f4nima) ConfigView.section.connection.networks.I2P=Rede I2P ConfigView.section.connection.networks.Tor=A rede do Onion Router (Tor) TableColumn.header.networks=Redes TableColumn.header.networks.info=Redes permitidas para a comunica\u00e7\u00e3o de dados peer-peer Scrape.status.networkdisabled=Rede n\u00e3o ativada ConfigView.section.tracker.server.group.networks=Redes ConfigView.section.tracker.server.group.networks.info=Selecione as redes para as quais o tracker aceitar\u00e1 peers window.networkselection.title=Sele\u00e7\u00e3o de Rede window.networkselection.info=O torrent listado abaixo tem tracker(s) que suportam as seguintes redes.\nSelecione aqueles a ativar para a comunica\u00e7\u00e3o com o tracker e peer.\nSe \u00e9 um tracker an\u00f4nimo que suporta clientes p\u00fablicos ative ambas as redes an\u00f4nima e p\u00fablica.\nAtivar a rede p\u00fablica tem a consequ\u00eancia \u00f3bvia de remover a anonimidade! plugins.basicview.clear=Limpar ConfigView.section.connection.group.peersources=Fontes Peer ConfigView.section.connection.group.peersources.info=Selecione as fontes padr\u00e3o permitidas para a conex\u00e3o com o peer ConfigView.section.connection.peersource.Tracker=De um tracker ConfigView.section.connection.peersource.DHT=Tracking descentralizado ConfigView.section.connection.peersource.PeerExchange=Supridas por outro peer ConfigView.section.connection.peersource.Plugin=Adicionadas por um plugin ConfigView.section.connection.peersource.Incoming=Conex\u00e3o de entrada PeersView.source=Fonte PeersView.source.info=A fonte deste peer TableColumn.header.peersources=Fontes Peer TableColumn.header.peersources.info=Fontes peer permitidas para o estabelecimento das conex\u00f5es com peers wizard.tracker.dht=Decentralizado (s\u00f3 clientes Vuze) MyTorrentsView.menu.advancedmenu=Avan\u00e7ado MyTorrentsView.menu.networks=Redes MyTorrentsView.menu.peersource=Fontes Peer ConfigView.section.sharing.permitdht=Permitir tracking descentralizado quando o tracker est\u00e1 indispon\u00edvel ConfigView.section.sharing.protocol=Protocolo para recursos compartilhados PeersView.Messaging=Enviando Mensagens PeersView.Messaging.info=Suporta o envio de mensagens avana\u00e7ado API. ConfigView.label.queue.newseedsmovetop=Mover torrents completados recentemente para a frente da lista de seeding ConfigView.label.seeding.firstPriority.ignore.info=Esteja ciente que usar estas regras pode resultar em parar um torrent\nt\u00e3o r\u00e1pido quanto o download terminar. ConfigView.label.seeding.firstPriority.ignore=Ignorar as regras de Primeira Prioridade acima para: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents com uma propor\u00e7\u00e3o de Seeds para Peers de ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents com 0 Peers ConfigView.section.tracker.sendjavaversionandos=Enviar a vers\u00e3o do Java e o nome do SO MagnetPlugin.contextmenu.exporturi=Copiar a URI do Magnet para a \u00c1rea de Transfer\u00eancia ConfigView.section.plugins.dht=Base de Dados Distribu\u00edda dht.info=Este plugin suporta tracking descentralizado, entre outras coisas, - desativando-o reduzir\u00e1 a sua habilidade de baixar dht.enabled=Ativar a base de dados distribu\u00edda dht.portdefault=Usar a porta padr\u00e3o dht.port=Porta UDP para a base de dados dht.execute.command=Comando de diagn\u00f3stico dht.execute.info=Pressione para executar o comando dht.execute=Executar dht.logging=Ativar o rastreamento da atividade ConfigView.section.plugins.dhttracker=Tracker Distribu\u00eddo dhttracker.tracknormalwhenoffline=S\u00f3 rastrear torrents normais quando o tracker deles est\u00e1 indispon\u00edvel ConfigView.section.file.nativedelete._mac=Usar a Lixeira quando apagar os arquivos ConfigView.section.file.nativedelete._windows=Mover os arquivos apagados para o Recycle Bin ConfigView.section.logging.generatediagnostics=Gerar ConfigView.section.logging.netinfo=Gerar info sobre a rede ConfigView.section.logging.statsinfo=Gerar info das estat\u00edsticas ConfigView.section.logging.generatediagnostics.info=Gerar informa\u00e7\u00e3o de diagn\u00f3stico e copiar para a \u00e1rea de transfer\u00eancia e arquivo log, se configurado ConfigView.section.sharing.privatetorrent=Torrent privado - s\u00f3 aceitar peers do tracker MainWindow.menu.tools.nattest=&Teste do NAT / Firewall Button.apply=Aplicar Button.close=Fechar window.welcome.title=Bem-Vindo ao Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Notas do Lan\u00e7amento dht.reseed.label=Normalmente ficar de seed de novo da Base de Dados Distribu\u00edda n\u00e3o \u00e9 necess\u00e1rio. Contudo, se o n\u00famero de contatos \u00e9 baixo, isto pode ser usado para a re-integra\u00e7\u00e3o.\nDeixe em branco para bootstrap off peers conectados ou insira o IP e porta para explicitamente bootstrap de um peer conhecido. dht.reseed.group=Ficar de seed de novo dht.reseed.ip=Endere\u00e7o IP dht.reseed.port=Porta dht.reseed=Ficar de seed de novo dht.reseed.info=Ficar de seed da base de dados de novo dht.diagnostics.group=Diagn\u00f3sticos DHTView.title.full=Base de Dados Distribu\u00edda DHTView.title.fullcvs=CVS da Base de Dados Distribu\u00edda DHTView.general.title=Geral DHTView.general.uptime=Tempo de Upload: DHTView.general.users=Usu\u00e1rios: DHTView.general.contacts=Contatos: DHTView.general.replacements=Substitui\u00e7\u00f5es: DHTView.general.live=Ao vivo: DHTView.general.unknown=Desconhecido: DHTView.general.dying=Morrendo: DHTView.transport.title=Detalhes do Transporte DHTView.transport.packets=Pacotes DHTView.transport.received=Recebidos DHTView.transport.sent=Enviados DHTView.transport.in=Entrou : DHTView.transport.out=Saiu : DHTView.operations.title=Detalhes da Opera\u00e7\u00e3o DHTView.operations.sent=Enviados DHTView.operations.failed=Falhou DHTView.operations.received=Recebidos DHTView.operations.findNode=Achar Node DHTView.operations.findValue=Achar Valor DHTView.operations.store=Armazenar DHTView.activity.title=Atividade DHTView.activity.status.true=Requisitado DHTView.activity.status.false=Rodando DHTView.activity.type=Tipo DHTView.activity.type.1=Get Interno DHTView.activity.type.2=Get Externo DHTView.activity.type.3=Put Interno DHTView.activity.type.4=Put Externo DHTView.activity.target=Alvo DHTView.activity.details=Detalhes DHTView.db.title=Base de Dados DHTView.db.keys=Teclas DHTView.db.values=Valores DHTView.db.direct=Direto DHTView.db.indirect=Indireto DHTView.db.divsize=Tamanho Div MainWindow.dht.status.tooltip=Quando a Base de Dados Distribu\u00edda est\u00e1 rodando isto mostra o n\u00ba estimado de usu\u00e1rios atualmente online MainWindow.dht.status.disabled=DHT Desativado MainWindow.dht.status.failed=O DHT Falhou MainWindow.dht.status.initializing=DHT Inicializando MainWindow.dht.status.users=%1 Usu\u00e1rios MainWindow.dht.status.unreachable=DHT Atr\u00e1s de Firewall MainWindow.dht.status.unreachabletooltip=Aparenta haver um problema com o mapeamento da porta UDP da Base de Dados Distribu\u00edda (NAT/firewall) MyTorrentsView.menu.setUpSpeed=Definir Velocidade de Upload MyTorrentsView.menu.setDownSpeed=Definir Velocidade de Download ConfigView.section.tracker.client.showwarnings=Mostrar mensagens de aviso reportadas pelos trackers dht.advanced=Ativar configura\u00e7\u00f5es avan\u00e7adas dht.advanced.group=Configura\u00e7\u00f5es avan\u00e7adas dht.advanced.label=S\u00f3 corrigir estes valores se voc\u00ea realmente sabe o que voc\u00ea est\u00e1 fazendo dht.override.ip=N\u00e3o levar em conta o endere\u00e7o IP externo ConfigView.section.logging.loggerenable=Ativar logging ConfigView.section.ipfilter.blockbanning=Banir um bloco de 256 endere\u00e7os quando pelo menos muitos no bloco forem banidos MyTrackerView.passive=Passivo TableColumn.header.swarm_average_speed=Velocidade M\u00e9dia da Multid\u00e3o TableColumn.header.swarm_average_speed.info=A velocidade m\u00e9dia dos peers na multid\u00e3o TableColumn.header.comment=Coment\u00e1rio TableColumn.header.comment.info=Coment\u00e1rio definido-pelo-usu\u00e1rio para o download TableColumn.header.commenticon=\u00cdcone do Coment\u00e1rio TableColumn.header.commenticon.info=Exibe o \u00edcone se o download tem um coment\u00e1rio definido-pelo-usu\u00e1rio MyTrackerView.category=Categoria MainWindow.menu.file.open.torrentfortracking=Arquivo Torrent... (Apenas Tracking) MyTrackerView.date_added=Adicionado ConfigView.section.tracker.portbackup=Fazer backup das portas (';' separadas) ConfigView.label.playfilespeech=Falar quando um arquivo est\u00e1 terminado ConfigView.label.playfilespeech.info=Os servi\u00e7os de discurso atualmente funcionam melhor com o ingl\u00eas ConfigView.label.playfilefinished=Tocar um som quando um arquivo est\u00e1 terminado ConfigView.label.backupconfigfiles=Fazer backup dos arquivos de configura\u00e7\u00e3o para prop\u00f3sitos de recupera\u00e7\u00e3o ConfigView.section.tracker.client.scrapesingleonly=Desativar agrega\u00e7\u00e3o de scrape por tracker (pode ajudar com os trackers que reportam os erros de 'URL muito longa' (414) ) dht.ipfilter.log=Registrar as viola\u00e7\u00f5es do Filtro de IP ConfigView.label.seeding.addForSeedingDLCopyCount=Considerar para 'adicionar para ficar de seed' downloads que baixaram este n\u00famero de c\u00f3pias ActivityView.legend.limit=Taxa limite ActivityView.legend.achieved=Taxa obtida ActivityView.legend.overhead=Taxa elevada ActivityView.legend.peeraverage=M\u00e9dia ActivityView.legend.swarmaverage=M\u00e9dia da multid\u00e3o ActivityView.legend.trimmed=Arrumado (pontuado) MyTorrentsView.menu.movemenu=Mover Arquivos MyTorrentsView.menu.movedata=Mover Arquivos de Dados... MyTorrentsView.menu.movetorrent=Mover Arquivo Torrent... MyTorrentsView.menu.movedata.dialog=Escolher novo local DHTView.operations.data=Dados DHTView.general.reachable=Alcan\u00e7\u00e1vel: DHTView.general.rendezvous=Encontro: ConfigView.label.queue.maxactivetorrentswhenseeding=M\u00e1x. s\u00f3 quando ficando de seed [0:ilimitados] Views.plugins.IRC.title=IRC - Suporte T\u00e9cnico Online Formats.units.alot=Muito !!! ConfigView.section.ipfilter.persistblocking=Salvar detalhes dos IPs bloqueados durante os rein\u00edcios FilesView.menu.rename=Renomear ou Refazer o Alvo FilesView.menu.rename_only=Renomear FilesView.menu.retarget=Refazer o Alvo FilesView.rename.choose.path=Escolher arquivo novo ou existente FilesView.rename.choose.path.dir=Escolher diret\u00f3rio novo ou existente FilesView.rename.confirm.delete.title=Confirmar Exclus\u00e3o FilesView.rename.confirm.delete.text=Confirmar exclus\u00e3o do arquivo original '%1' FilesView.rename.filename.title=Renomea arquivo FilesView.rename.filename.text=Escolher um novo nome para o arquivo ConfigView.higher.mode.available=Mais op\u00e7\u00f5es est\u00e3o dispon\u00edveis em modos de usu\u00e1rios mais altos ConfigView.section.mode=Modo ConfigView.section.mode.title=Profici\u00eancia do Usu\u00e1rio ConfigView.section.mode.beginner=Iniciante ConfigView.section.mode.beginner.wiki.definitions=Vocabul\u00e1rio BitTorrent ConfigView.section.mode.intermediate=Intermedi\u00e1rio ConfigView.section.mode.intermediate.wiki.host=Hospedar Arquivos ConfigView.section.mode.intermediate.wiki.publish=Publicar Arquivos ConfigView.section.mode.advanced=Avan\u00e7ado ConfigView.section.mode.advanced.wiki.main=P\u00e1gina Principal do Wiki ConfigView.section.mode.beginner.text=Tudo que voc\u00ea precisa para baixar torrents.\nUse este modo se tudo que voc\u00ea quer \u00e9 gerenciar seus torrents. ConfigView.section.mode.intermediate.text=Acesso as fun\u00e7\u00f5es do tracker.\nUse este modo se voc\u00ea quer criar seu pr\u00f3prio tracker e hospedar/publicar seus arquivos. ConfigView.section.mode.advanced.text=Acesso as configura\u00e7\u00f5es de rede.\nUse este modo se voc\u00ea sabe o que MTU ou I/O n\u00e3o-bloqueadores s\u00e3o... Files.column.storagetype=Tipo de Armazenagem Files.column.fileext=Tipo FileItem.storage.compact=Compacta MessageBoxWindow.rememberdecision=Lembrar minha decis\u00e3o ConfigView.section.interface.cleardecisions=Limpar os di\u00e1logos de decis\u00e3o lembrados ConfigView.section.interface.cleardecisionsbutton=Limpar ConfigView.section.interface.cleartrackers=Limpar os trackers lembrados ConfigView.section.interface.cleartrackersbutton=Limpar ConfigView.section.interface.clearsavepaths=Limpar os caminhos para salvar recordados ConfigView.section.interface.clearsavepathsbutton=Limpar configureWizard.welcome.usermodes=Esta configura\u00e7\u00e3o de profici\u00eancia do usu\u00e1rio determinar\u00e1 o n\u00edvel das op\u00e7\u00f5es exibidas em Ferramentas > Op\u00e7\u00f5es. \u00c9 do seu melhor interesse defin\u00ed-la apropriadamente. FilesView.skip.confirm.delete.text=Cortar o arquivo '%1' para salvar espa\u00e7o? FilesView.rename.failed.title=Renomear/Refazer o Alvo falhou FilesView.rename.failed.text=A opera\u00e7\u00e3o falhou, provavelmente devido a sele\u00e7\u00e3o de alvo inv\u00e1lida diagnostics.log_found=O Vuze n\u00e3o fechou apropriadamente. Verifique por quaisquer arquivos log de diagn\u00f3stico. Tamb\u00e9m leia o artigo do wiki Vuze Disappears para mais informa\u00e7\u00e3o. ManagerItem.paused=Pausado Utils.link.visit=Por favor visite ConfigView.section.connection.serverport.wiki=Escolhas de boas portas ConfigView.section.transfer.speeds.wiki=Boas configura\u00e7\u00f5es de velocidade installPluginsWizard.installMode.info.text=Voc\u00ea n\u00e3o precisa de plugins para o Vuze funcionar apropriadamente, eles trazem op\u00e7\u00f5es complementares para divers\u00e3o, automa\u00e7\u00e3o ou controle remoto.\nEnt\u00e3o por favor leia cada descri\u00e7\u00e3o do plugin cuidadosamente antes de decidir instal\u00e1-lo.\nA maioria dos plugins s\u00e3o seguros para testar, apenas n\u00e3o sobrecarregue a sua configura\u00e7\u00e3o com plugins que voc\u00ea n\u00e3o usar\u00e1. Views.plugins.Distributed.DB.title=Base de Dados Distribu\u00edda Views.plugins.Distributed.Tracker.title=Tracker Distribu\u00eddo Views.plugins.Plugin.Update.title=Atualiza\u00e7\u00e3o do Plugin openUrl.url.info=Suporta http, https, magnet e strings de infohash raw hex TableColumn.header.swarm_average_completion=Conclus\u00e3o da M\u00e9dia dos Peers TableColumn.header.swarm_average_completion.info=A porcentagem da conclus\u00e3o m\u00e9dia dos peers na multid\u00e3o GeneralView.label.swarm_average_completion=Conclus\u00e3o em M\u00e9dia: GeneralView.label.swarm_average_completion.tooltip=A porcentagem da conclus\u00e3o dos peers em m\u00e9dia na multid\u00e3o MainWindow.nat.status.tooltip.unknown=Status para alcan\u00e7ar Firewall/NAT desconhecido (TCP) MainWindow.nat.status.tooltip.ok=OK para Alcan\u00e7ar (TCP) MainWindow.nat.status.tooltip.probok=Para alcan\u00e7ar foi OK, contudo sem conex\u00f5es de entrada TCP recentes MainWindow.nat.status.bad=Atr\u00e1s de Firewall MainWindow.nat.status.tooltip.bad=Problema para alcan\u00e7ar Firewall/NAT (TCP). V\u00e1 at\u00e9 o Wiki por ajuda plugin.installer.recommended.plugin=Plugin recomendado - por favor reveja e instale se requerido LoggerView.pause=Pausar Logging LoggerView.clear=&Limpar LoggerView.filter=Filtro LoggerView.filter.uncheckAll=Desmarcar Todas as Categorias LoggerView.filter.checkAll=Marcar Todas as Categorias LoggerView.loggingDisabled=Logging n\u00e3o est\u00e1 ativado. LoggerView.includeOnly=S\u00f3 exibir linhas combinando esta express\u00e3o regular: LoggerView.excludeAll=N\u00e3o exibir linhas combinando esta express\u00e3o regular: ConfigView.section.logging.log0type=Informa\u00e7\u00e3o ConfigView.section.logging.log1type=Aviso ConfigView.section.logging.log2type=Erro ConfigView.section.logging.filter=Filtrar quando registrando no arquivo ConfigView.section.logging.level=N\u00edvel do Log ConfigView.section.logging.showLogsFor=Mostrar os logs das %1 para as seguintes categorias: ConfigView.pluginlist.column.loadAtStartup=Carregar ao@Iniciar ConfigView.pluginlist.column.type=Tipo ConfigView.pluginlist.column.type.perUser=Por Usu\u00e1rio ConfigView.pluginlist.column.type.shared=Compartilhado ConfigView.pluginlist.column.type.builtIn=Embutido ConfigView.pluginlist.column.name=Nome ConfigView.pluginlist.column.version=Vers\u00e3o ConfigView.pluginlist.column.directory=Diret\u00f3rio ConfigView.pluginlist.column.isOperational=Operacional? PeersView.BlockView.Avail.Have=Ambos tem PeersView.BlockView.Avail.NoHave=O peer tem; Voc\u00ea n\u00e3o PeersView.BlockView.NoAvail.Have=Voc\u00ea tem; O peer n\u00e3o PeersView.BlockView.NoAvail.NoHave=Ningu\u00e9m tem PeersView.BlockView.Transfer=Transferindo PeersView.BlockView.NextRequest=Pr\u00f3ximo Pedido PeersView.BlockView.title=Mapa dos Peda\u00e7os PeersView.BlockView.AvailCount=Contagem da Disponibilidade MyTorrentsView.dialog.NumberError.title=N\u00famero Inv\u00e1lido ou N\u00e3o Reconhecido MyTorrentsView.dialog.NumberError.text=O n\u00famero que voc\u00ea inseriu \u00e9 inv\u00e1lido ou n\u00e3o reconhecido. MyTorrentsView.menu.manual.per_torrent=Manual (por torrent) MyTorrentsView.menu.manual.shared_torrents=Manual (pelos torrents) MyTorrentsView.dialog.setSpeed.title=Definir %1 velocidade # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Insira um n\u00famero %1 para mudar %2 para: MyTorrentsView.dialog.setNumber.inKbps=em %1 OpenTorrentWindow.torrentLocation=Arquivos Torrent: OpenTorrentWindow.addFiles.URL=Adicionar &URL OpenTorrentWindow.addFiles.Folder=Adicionar &Pasta OpenTorrentWindow.addFiles.Clipboard=Adicionar da \u00c1rea de Transfer\u00eancia OpenTorrentWindow.changeDestination=Mudar o Destino OpenTorrentWindow.fileList=Arquivos nos torrents: OpenTorrentWindow.torrentTable.name=Nome OpenTorrentWindow.torrentTable.saveLocation=Salvar o Local OpenTorrentWindow.fileTable.fileName=Nome do Arquivo OpenTorrentWindow.fileTable.size=Tamanho OpenTorrentWindow.fileTable.destinationName=Nome do Destino OpenTorrentWindow.startMode.seeding=Ficando de Seed OpenTorrentWindow.fileList.changeDestination=Mudar o Destino OpenTorrentWindow.mb.badSize.title=Arquivo Incompat\u00edvel OpenTorrentWindow.mb.badSize.text='%1' n\u00e3o \u00e9 '%2' e n\u00e3o pode ser usado para ficar de seed OpenTorrentWindow.mb.alreadyExists.text=%3 j\u00e1 foi adicionado como '%2' OpenTorrentWindow.mb.alreadyExists.default.name=M\u00eddia OpenTorrentWindow.mb.alreadyExists.title=O torrent j\u00e1 existe OpenTorrentWindow.mb.openError.title=Erro ao Abrir OpenTorrentWindow.mb.openError.text='%1' n\u00e3o p\u00f4de ser aberto: OpenTorrentWindow.torrent.remove=Remover torrent da lista OpenTorrentWindow.torrent.options=As seguintes configura\u00e7\u00f5es se aplicar\u00e3o aos torrents selecionados abaixo: OpenTorrentWindow.xOfTotal=(%1 de %2) iconBar.open.tooltip=Abrir Torrent(s) LocaleUtil.column.text=Texto Desconhecido Tracker.tooltip.MultiSupport=Este tracker suporta m\u00faltiplos hash scrapes por pedido. Tracker.tooltip.NoMultiSupport=Este tracker n\u00e3o suporta m\u00faltiplos hash scrapes por pedido. ConfigView.label.lazybitfield=Usar lazy bitfield (ajuda a ficar de seed nas redes empregando o bloqueamento baseado no bitfield) LoggerView.realtime=Atualizar em tempo real ConfigView.section.file.perf.cache.flushpieces=Escrever peda\u00e7os completos no disco imediatamente. Isto suaviza o acesso ao disco mas pode resultar em mais opera\u00e7\u00f5es de escrita. ConfigView.section.file.writemblimit=M\u00e1ximo de pedidos de escrita requeridos (em %1) ConfigView.section.file.writemblimit.explain=Quando a velocidade de escrita no disco \u00e9 menor do que a velocidade de download este par\u00e2metro limita quantos dados ser\u00e3o requeridos antes que as velocidades de download sejam reduzidas. ConfigView.section.file.readmblimit=M\u00e1ximo de pedidos de leitura requeridos (em %1) ConfigView.section.file.readmblimit.explain=Este par\u00e2metro limita quanta mem\u00f3ria ser\u00e1 usada para armazenar leituras que ainda est\u00e3o pendentes no processamento. Button.moveUp=Mover &pra Cima Button.moveDown=Mover &pra Baixo ConfigView.notAvailableForMode=Esta se\u00e7\u00e3o \u00e9 destinada para o modo %1 ou mais alto. N\u00e3o est\u00e1 dispon\u00edvel no modo %2. health.explain.error=H\u00e1 um erro com este torrent. Veja a coluna Status, ou a dica no \u00edcone para o erro. GeneralView.label.trackerscrapeupdate=Limpar Tracker PeersView.piece=Peda\u00e7o PeersView.piece.info=\u00daltimo peda\u00e7o # requesitado deste peer PiecesView.priority=Prioridade PiecesView.priority.info=a prioridade da conclus\u00e3o deste peda\u00e7o, mas n\u00e3o preste muita aten\u00e7\u00e3o a ele PiecesView.speed=Velociade PiecesView.speed.info=Peers mais lento s\u00e3o impedidos de interferir muito com os peda\u00e7os mais r\u00e1pidos TableColumn.header.AvgAvail.info=Soma da disponibilidade dos peda\u00e7os divididos por # peda\u00e7os, divididos por # conex\u00f5es TableColumn.header.AvgAvail=M\u00e9dia de Disp/peda\u00e7os ConfigView.label.strictfilelocking=Refor\u00e7ar a tranca do acesso de escrita exclusivo do arquivo pelos torrents MyTorrentsView.menu.checkfilesexist=Arquivos de Verifica\u00e7\u00e3o Existem MyTorrentsView.menu.rescanfile=Periodicamente Re-verifcar os Peda\u00e7os Incompletos MyTorrentsView.menu.clear_resume_data=Limmpar Dados de Resumo Plugin.extseed.name=Seeds Externos Plugin.localtracker.name=Descobridor de Peers em LAN Plugin.localtracker.info=O descobridor de peers na LAN permite m\u00faltiplas c\u00f3pias do Vuze atr\u00e1s de um firewall e em uma rede comum para baixar com efici\u00eancia torrents ativando a conex\u00e3o direta entre eles Plugin.localtracker.enable=Ativar o descobridor de peers na LAN azinstancehandler.alert.portclash=Conflito de portas detectado na LAN: %1 j\u00e1 em uso por outro usu\u00e1rio do Vuze, selecione nova(s) porta(s) aleat\u00f3ria(s) para a escuta TCP / UDP de entrada [entre %2 e %3]. ConfigView.section.transfer.lan.tooltip=Configura\u00e7\u00f5es espec\u00edficias-pra-LAN ConfigView.section.transfer.lan.uploadrate=Velocidade m\u00e1xima de upload na LAN em KB/s [0: ilimitada] ConfigView.section.transfer.lan.uploadrate.tooltip=Conex\u00f5es com os peers dentro da mesma LAN interna tem um limite de taxa de upload separado. ConfigView.section.transfer.lan.downloadrate=Velocidade m\u00e1xima de download na LAN em KB/s [0: ilimitada] ConfigView.section.transfer.lan.downloadrate.tooltip=Conex\u00f5es com os peers dentro da mesma LAN interna tem um limite de taxa de download separado. TorrentOptionsView.title.short=Op\u00e7\u00f5es TorrentOptionsView.title.full=Op\u00e7\u00f5es TorrentOptionsView.param.max.peers=N\u00famero m\u00e1ximo de conex\u00f5es [0: ilimitadas] ConfigView.section.connection.encryption.require_encrypted_transport=Requer transporte encriptado ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=For\u00e7ar o uso de conex\u00f5es encriptadas com outros peers. ConfigView.section.connection.encryption.min_encryption_level=N\u00edvel m\u00ednimo da encripta\u00e7\u00e3o ConfigView.section.connection.encryption.min_encryption_level.tooltip=Simples - s\u00f3 handshake\nRC4 - corrente completa\nMaior encripta\u00e7\u00e3o requer mais CPU. Peers.column.Encryption=Encripta\u00e7\u00e3o Peers.column.Encryption.info=N\u00edvel da encripta\u00e7\u00e3o em uso ConfigView.section.connection.encryption.encrypt.info=Se a encripta\u00e7\u00e3o est\u00e1 ativada voc\u00ea n\u00e3o ser\u00e1 capaz de conectar a clientes incompat\u00edveis a menos que voc\u00ea configure as op\u00e7\u00f5es de retorno ConfigView.section.connection.encryption.encrypt.info.link=Por favor visite aqui para detalhes MainWindow.sr.status.tooltip.ok=Taxa de Compartilhamento %1 OK MainWindow.sr.status.tooltip.poor=Taxa de Compartilhamento %1 pobre: < 0.9 MainWindow.sr.status.tooltip.bad=Taxa de Compartilhamento %1 ruim: < 0.5 ConfigView.section.style.status=\u00c1rea do Status: ConfigView.section.style.status.show_sr=Taxa de Compartilhamento ConfigView.section.style.status.show_nat=Status do NAT ConfigView.section.style.status.show_ddb=Status do DDB ConfigView.section.style.status.show_ipf=Status do IPFilter ConfigView.section.connection.encryption.encrypt.group=Encripta\u00e7\u00e3o/Ofusca\u00e7\u00e3o do Transporte ConfigView.section.connection.encryption.encrypt.fallback_info=Ativando-a a op\u00e7\u00e3o de retorno permitir\u00e1 conex\u00f5es com clientes incompat\u00edveis MAS resultar\u00e1 em conex\u00f5es n\u00e3o encriptadas ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Permitir conex\u00f5es de sa\u00edda n\u00e3o encriptadas se a tentativa de encriptar a conex\u00e3o falhar ConfigView.section.connection.encryption.encrypt.fallback_incoming=Permitir conex\u00f5es de entrada n\u00e3o encriptadas ConfigView.section.connection.encryption=Encripta\u00e7\u00e3o do Transporte upnp.selectedinterfaces=Interfaces selecionadas (';' separadas, ex: eth0;eth1) [em branco: todas] ConfigView.section.style.defaultSortOrder=Ordem de Organiza\u00e7\u00e3o Padr\u00e3o ConfigView.section.style.defaultSortOrder.desc=Descendente ConfigView.section.style.defaultSortOrder.asc=Ascendente ConfigView.section.style.defaultSortOrder.flip=Oposto da ordem anterior LoggerView.autoscroll=Auto-rolar Button.selectAll=Selecionar Todos Button.markSelected=Marcar os Selecionados Button.unmarkSelected=Desmarcar os Selecionados TorrentOptionsView.param.max.uploads=N\u00famero m\u00e1ximo de slots de upload [m\u00ednimo: 2] MyTorrentsView.dialog.setPosition.title=Definir Posi\u00e7\u00e3o MyTorrentsView.dialog.setPosition.text=Insira a posi\u00e7\u00e3o para definir os torrents selecionados: MyTorrentsView.menu.reposition.manual=Reposi\u00e7\u00e3o.. ConfigView.section.connection.advanced.info.link=Por favor visite aqui para detalhes ConfigView.section.connection.advanced.socket.group=Op\u00e7\u00f5es do Socket ConfigView.section.connection.advanced.bind_port=Prender a porta local [0: desativado] ConfigView.section.connection.advanced.bind_port.tooltip=Conex\u00f5es de socket de sa\u00edda ser\u00e3o localmente presas a porta dada.\nAtivar isto pode ajudar com a instabilidade do roteador NAT. ConfigView.section.proxy.group.tracker=Comunica\u00e7\u00f5es do Tracker ConfigView.section.proxy.group.peer=Comunica\u00e7\u00f5es do Peer Pieces.column.Requested=Requesitado Pieces.column.Requested.info=Mostra se mais pedidos podem ser feitos no peda\u00e7o ou n\u00e3o (*) ConfigView.label.maxuploadsseeding=Alternar para o padr\u00e3o quando ficando de seed MyTorrentsView.filter=Filtro: popup.error.hideall=Esconder Todos ConfigView.section.style.dataStatsOnly=Mostrar apenas os dados das estat\u00edsticas (esconder as estat\u00edsticas do protocolo) ConfigView.section.style.separateProtDataStats=Mostrar dados separados e estat\u00edsticas do protocolo como '(protocolo) de dados' MyTorrentsView.dialog.setFilter.title=Modificar Filtro MyTorrentsView.dialog.setFilter.text=A se\u00e7\u00e3o %1 ser\u00e1 filtrada pelo texto que voc\u00ea especificar abaixo. Usar o | s\u00edmbolo (cano) para filtrar m\u00faltiplas frases. MyTorrentsView.filter.tooltip=Ctrl+X para trocar entre RegEx e modos de busca normal.\nUsar o | s\u00edmbolo (cano) para filtrar m\u00faltiplas frases. MyTorrentsView.clearFilter.tooltip=Limpar o Filtro MyTorrentsView.menu.filter=Lista de Filtros... ConfigView.section.file.resume.recheck.all=Quando der pau-reiniciar verificar o arquivo inteiro por peda\u00e7os completados (De outro modo apenas peda\u00e7os ativos do \u00faltimo salvamento s\u00e3o verificados) ConfigureWizard.language.choose=Escolha um idioma da lista abaixo: popup.closing.in=Auto-fechando a janela em %1 segundos popup.more.waiting=%1 mais mensagem(ns).. # > 2402 popup.download.finished="%1" terminou de baixar. popup.file.finished="%1" terminou de baixar. Plugin.localtracker.autoadd.info=Automaticamente adicionar estes peers locais [';' endere\u00e7os separados, ex: 1.2.3.4] Plugin.localtracker.autoadd=Peers expl\u00edcitos Plugin.localtracker.networks.info=Considere as seguintes redes serem locais [';' redes separadas, ex: 145.227.*.*] Plugin.localtracker.networks=Redes locais MainWindow.menu.view.plugins.logViews=Visualiza\u00e7\u00f5es do Log SpeedView.stats.autospeed=Velocidade de Upload Autom\u00e1tica SpeedView.stats.autospeed.disabled=Esta op\u00e7\u00e3o ou est\u00e1 desativada (voc\u00ea precisa do DHT) ou n\u00e3o est\u00e1 em uso (velocidade manual de upload selecionada) SpeedView.stats.idlePing=Ping Inativo: SpeedView.stats.maxPing=Ping M\u00e1x: SpeedView.stats.currentPing=Ping Atual: SpeedView.stats.maxUp=Velocidade M\u00e1x de Upload: ConfigView.pluginlist.unloadSelected=Descarregar o Selecionado ConfigView.pluginlist.scan=Escanear por novos Plugins ConfigView.section.transfer.autospeed=Auto-Velocidade (cl\u00e1ssica) ConfigView.section.transfer.autospeed.tooltip=Configura\u00e7\u00f5es espec\u00edficas da Auto-velocidade ConfigView.section.transfer.autospeed.info=A auto-velocidade ajusta automaticamente o limite da velocidade de upload para evitar sobrecarregar a conex\u00e3o de rede.\n\nEstes limites s\u00f3 ser\u00e3o aplicados quando a velocidade autom\u00e1tica de upload estiver ativada e tamb\u00e9m requer que a base de dados distribu\u00edda esteja ativada.\n ConfigView.section.transfer.autospeed.minupload=Velocidade m\u00ednima de upload em %1 ConfigView.section.transfer.autospeed.minupload.tooltip=A velocidade de upload n\u00e3o ser\u00e1 normalmente diminu\u00edda abaixo deste limite ConfigView.section.transfer.autospeed.maxupload=Velocidade m\u00e1xima de upload em %1 [0: ilimitada] ConfigView.section.transfer.autospeed.maxupload.tooltip=A velocidade de upload n\u00e3o ser\u00e1 aumentada automaticamente acima deste limite ConfigView.section.transfer.autospeed.chokeping=Tempo para silenciar o ping [milisegundos] ConfigView.section.transfer.autospeed.chokeping.tooltip=Os tempos do Ping em excesso deste valor ser\u00e1 considerado como um indicador de satura\u00e7\u00e3o de rede ConfigView.section.transfer.autospeed.enableauto=Ativar quando baixando e ficando de seed ConfigView.section.transfer.autospeed.enableautoseeding=Ativar apenas quando ficando de seed ConfigView.pluginlist.column.unloadable=Descarreg\u00e1vel ConfigView.section.transfer.lan.enable=Ativar os limites de velocidade separados para as conex\u00f5es LAN Plugin.localtracker.wellknownlocals=Automaticamente incluir loopback/link/redes locais de site (192.168 etc) TableColumn.header.filesdone=Arquivos Feitos TableColumn.header.filesdone.info=Arquivos feitos/Total dos arquivos *ou* arquivos n\u00e3o-ignorados feitos (Arquivos feitos)/Total de arquivos n\u00e3o-ignorados (Total de arquivos) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=esperando pela inicializa\u00e7\u00e3o do DDB... MagnetPlugin.report.searching=buscando... MagnetPlugin.report.found=achado(s) %1 MagnetPlugin.report.alive=%1 est\u00e1 vivo MagnetPlugin.report.dead=%1 est\u00e1 morto MagnetPlugin.report.tunnel=abrindo para %1 MagnetPlugin.report.downloading=baixando de %1 MagnetPlugin.report.error=erro %1 MagnetURLHandler.report.no_sources=nenhuma(s) fonte(s) achada(s) para o torrent MagnetURLHandler.report.torrent_size=tamanho do torrent: %1 MagnetURLHandler.report.percent=completado: %1% MagnetURLHandler.report.error=erro %1 DHTTransport.report.request_all=requisitando a transfer\u00eancia inteira de %1 DHTTransport.report.received_bit=recebeu %1 para %2 de %3 DHTTransport.report.complete=completo DHTTransport.report.timeout=tempo esgotado, sem respostas de %1 DHTTransport.report.rerequest_all=re-requisitando transfer\u00eancia inteira de %1 DHTTransport.report.rerequest_bit=re-requisitando %1 para %2 de %3 DHTTransport.report.timeout_some=tempo esgotado, %1 pacotes recebidos de %2 mas incompletos DHTTransport.report.sending=enviando dados DHTTransport.report.resending=re-enviando dados DHTTransport.report.send_complete=enviar completados DHTTransport.report.send_timeout=tempo de enviar esgotado ConfigView.section.transfer.autospeed.enabledebug=Informa\u00e7\u00e3o de debug no Log TableColumn.header.date_added=Data adicionada TableColumn.header.date_added.info=Data que o torrent foi adicionado ConfigView.section.file.hashchecking.smallestfirst=Re-verificar os downloads menores primeiro platform.win32.baddll.info=O Vuze detectou a presen\u00e7a de '%1'. Isto \u00e9 parte de '%2' e \u00e9 sabido que causa problemas severos tais como crash no aplicativo e alto uso da CPU. Se voc\u00ea encontrar estes ent\u00e3o por favor desinstale o software ou configure-o para n\u00e3o afetar o Vuze. upnp.ignorebaddevices=Ignorar dispositivos que falham em responder corretamente upnp.ignorebaddevices.info=Dispositivos atualmente ignorados: %1 upnp.ignorebaddevices.reset=Resetar a lista de dispositivos ignorados upnp.ignorebaddevices.reset.action=Resetar upnp.ignorebaddevices.alert=O dispositivo UPnP no local %1 est\u00e1 sendo ignorado devido a repetidas falhas. Veja a configura\u00e7\u00e3o do plugin UPnP para op\u00e7\u00f5es com respeit a esta a\u00e7\u00e3o. TorrentOptionsView.param.max.uploads.when.busy=Velocidade m\u00e1xima de upload em KB/s quando o limite global de upload alcan\u00e7ar [0: desativado] UpdateMonitor.messagebox.verification.failed.title=Verifica\u00e7\u00e3o da Instala\u00e7\u00e3o Falhou UpdateMonitor.messagebox.verification.failed.text=Verifica\u00e7\u00e3o da '%1' falhou: %2 UpdateMonitor.messagebox.accept.unverified.title=Aceitar Instala\u00e7\u00e3o N\u00e3o-Verificada UpdateMonitor.messagebox.accept.unverified.text='%1' n\u00e3o p\u00f4de ser verificado como um plugin oficial do Vuze.\nSe \u00e9 tal plugin voc\u00ea N\u00c3O deve continuar.\nProsseguir com a instala\u00e7\u00e3o? FileView.BlockView.title=Peda\u00e7os do Arquivo FileView.BlockView.Done=Conclu\u00eddo FileView.BlockView.Skipped=Pulado FileView.BlockView.Active=Ativo FileView.BlockView.Outstanding=Pendente ConfigView.label.tcplistenport=Porta de escuta da entrada TCP ConfigView.label.udplistenport=Porta de escuta UDP upnp.portchange.alert=As seguintes portas foram mudadas para evitar problemas com dispositivos UPnP: %1 [porta antiga=%2] %3 [porta antiga=%4] ConfigView.section.proxy.username.info=Se o servidor proxy exige autentica\u00e7\u00e3o mesmo quando nenhuma est\u00e1 definida, use a string "" como nome de usu\u00e1rio ConfigView.label.maxuploadswhenbusymin=Velocidade m\u00e1xima de upload por torrent quando o timer est\u00e1 ocupado [seg] MainWindow.menu.help.debug=Gerar Info de Debug (Crash Log) DownloadManager.error.badsize=Tamanho incorreto natpmp.info=NAT-PMP \u00e9 a alternativa da Apple para o UPnP e \u00e9 suportada por recentes esta\u00e7\u00f5es de aeroportos\n\nNote que o UPnP tem que estar ativado para ativar o NAT-PMP ja que o dispositivo NAT-PMP \u00e9 tratado como um tipo de dispositivo UPnP especial natpmp.enable=Ativar (note que deve tamb\u00e9m estar ativado na configura\u00e7\u00e3o do aeroporto para funcionar) ConfigView.section.tracker.host.addurls=Garante que as URLs do tracker est\u00e3o presentes nos torrents hospedados ConfigView.filter=procurar op\u00e7\u00f5es aqui ConfigView.section.files.move=Conclus\u00e3o da Movimenta\u00e7\u00e3o ConfigView.section.file.defaultdir.section=Op\u00e7\u00f5es Padr\u00e3o do Diret\u00f3rio ConfigView.section.file.defaultdir.auto=Automaticamente baixar para o diret\u00f3rio padr\u00e3o (Sem Alertar) ConfigView.section.file.defaultdir.bestguess=Usar o melhor palpite quando escolher o diret\u00f3rio padr\u00e3o para salvar ConfigView.section.file.defaultdir.ask=Diret\u00f3rio padr\u00e3o: ConfigView.section.file.defaultdir.lastused=Atualizar o diret\u00f3rio padr\u00e3o para o local onde salvou pela \u00faltima vez ConfigView.section.file.config.section=Configura\u00e7\u00f5es da Configura\u00e7\u00e3o ConfigView.section.file.config.currentdir=Diret\u00f3rio da configura\u00e7\u00e3o atual: ConfigView.section.torrent.decoding=Decodificar as Defini\u00e7\u00f5es de Caracteres ConfigView.section.logging.udptransport=Ativar tra\u00e7o de transporte verboso UDP Tracker.announce.ignorePeerSeed=Ignorar Contagem de Peers/Seeds. %1 ConfigView.section.connection.encryption.use_crypto_port=Usar a extens\u00e3o do tracker 'cryptoport' para impedir tentativas de conex\u00e3o de entrada simples. Alguns trackers n\u00e3o aceitam isto e falham com erros tais como "Porta Inv\u00e1lida" ou "Argumento Ilegal" TorrentOptionsView.param.reset.to.default=Definir as op\u00e7\u00f5es de volta aos seus valores padr\u00e3o TorrentOptionsView.param.reset.button=Resetar natpmp.routeraddress=Endere\u00e7o da esta\u00e7\u00e3o [em branco: auto] ConfigView.section.style.disableAlertSliding=Desativar anima\u00e7\u00e3o de sliding/em alto estilo para mensagens de alerta ConfigView.section.transfer.autospeed.maxinc=Aumento m\u00e1ximo em %1 por ciclo ConfigView.section.transfer.autospeed.maxdec=Diminui\u00e7\u00e3o m\u00e1xima em %1 por ciclo ConfigView.section.transfer.autospeed.enabledownadj=Ativar ajuste da velocidade de download ConfigView.section.transfer.autospeed.downadjratio=Taxa da velocidade de Download:Upload (ex: 2.0-> o limite da velocidade de download \u00e9 o dobro do limite de upload) ConfigView.section.transfer.autospeed.latencyfactor=Fator usado para ligar as mudan\u00e7as de lat\u00eancia as mudan\u00e7as de velocidade (n\u00bas maiores diminuem a sensitividade) ConfigView.section.transfer.autospeed.reset=Resetar valores avan\u00e7ados ConfigView.section.transfer.autospeed.reset.button=Resetar PeerColumn.activationCount=Peers tentando se conectar: %1 TableColumn.header.timesincedownload.info=O tempo decorrido desde que os dados foram baixados para o torrent TableColumn.header.timesincedownload=Inativo pra Baixo TableColumn.header.timesinceupload.info=O tempo decorrido desde que os dados foram enviados para o torrent TableColumn.header.timesinceupload=Inativo pra Cima PeersView.incomingreqcount=Reqs de Entrada PeersView.incomingreqcount.info=Contagem dos pedidos de entrada feitos pelo peer PeersView.outgoingreqcount=Reqs de Sa\u00edda PeersView.outgoingreqcount.info=Contagem dos pedidos de sa\u00edda feitos pelo peer upnp.mapping.trackerclientudp=Porta do Cliente Tracker UDP upnp.mapping.dhtudp=Base de Dados Distribu\u00edda ConfigView.section.connection.nondata.udp.same=Usar a mesma porta UDP para a Base de Dados Distribu\u00edda e o Tracker UDP ConfigView.section.connection.tcp.enable=Ativar TCP ConfigView.section.connection.udp.enable=Ativar UDP ConfigView.section.style.showiconbar=Mostrar a Barra de Ferramentas MainWindow.menu.view.iconbar=Barra de Ferramentas MyTorrentsView.menu.rename=Renomear MyTorrentsView.menu.rename.displayed=Renomear o Nome Exibido MyTorrentsView.menu.rename.save_path=Renomearo Caminho para Salvar MyTorrentsView.menu.rename.displayed.enter.title=Renomear o Nome Exibido MyTorrentsView.menu.rename.displayed.enter.message=Inserir um novo nome para exibir para este download.\nSe nenhum texto \u00e9 inserido, o nome original ser\u00e1 usado. MyTorrentsView.menu.edit_comment=Editar Coment\u00e1rio MyTorrentsView.menu.edit_comment.enter.title=Editar Coment\u00e1rio MyTorrentsView.menu.edit_comment.enter.message=Inserir um coment\u00e1rio para este download. UIDebugGenerator.messageask.title=Gerador de Debug UIDebugGenerator.messageask.text=Por favor insira uma descri\u00e7\u00e3o do bug que voc\u00ea est\u00e1 reportando UIDebugGenerator.complete.title=Gera\u00e7\u00e3o de Debug Completa UIDebugGenerator.complete.text=Por favor envie o arquivo '%1' para az-bugreports@azureus-inc.com\n\nClique em Ok para abrir uma janela para este arquivo. ConfigView.section.style.showProgramIcon=Mostrar o \u00edcone do programa no nome da coluna ConfigView.section.style.showProgramIcon.tooltip=A visualiza\u00e7\u00e3o pode precisar de re-abrir para as mudan\u00e7as acontecerem swt.alert.cant.update=biblioteca SWT carregada de "%3" n\u00e3o p\u00f4de ser automaticamente atualizada da vers\u00e3o %1 para a %2 (deve ser carregada de "%4"). Por favor veja no wiki para detalhes. authenticator.savepassword=Lembrar da minha senha ConfigView.section.security.clearpasswords=Resetar as senhas lembradas ConfigView.section.security.clearpasswords.button=Resetar Content.alert.notuploaded.title=Upload N\u00e3o Completado Content.alert.notuploaded.text=O Upload de '%1' n\u00e3o est\u00e1 completado. Se voc\u00ea %2 agora, as pessoas n\u00e3o ser\u00e3o capazes de baixar completamente o seu trabalho publicado.\n\nVoc\u00ea tem certeza de que voc\u00ea quer faz\u00ea-lo %2? Content.alert.notuploaded.multi.title=Uploads N\u00e3o Completados Content.alert.notuploaded.multi.text=%1 do seu conte\u00fado publicado n\u00e3o est\u00e1 completamente de seed. Se voc\u00ea %2 agora, as pessoas n\u00e3o ser\u00e3o capazes de baixar completamente o seu trabalho publicado.\n\nVoc\u00ea tem certeza de que voc\u00ea quer faz\u00ea-lo %2?\n\nConte\u00fado n\u00e3o completamente de seed:\n%3 Content.alert.notuploaded.stop=parar Content.alert.notuploaded.quit=sair do Vuze TorrentInfoView.torrent.encoding=Codifica\u00e7\u00e3o do torrent TorrentInfoView.columns=Colunas da visualiza\u00e7\u00e3o 'Meus Torrents' progress.window.title=Opera\u00e7\u00e3o em Progresso progress.window.msg.filemove=Por favor espere enquanto a movimenta\u00e7\u00e3o/renomeamento do arquivo se completa ConfigView.label.popup.timestamp=Adicionar estampas de tempo aos alertas popup ConfigView.label.popup.autohide=Automaticamente esconder alertas popup que n\u00e3o s\u00e3o sobre erros ap\u00f3s x segundos (definir em 0 para desativar o auto-esconder) ConfigView.label.popup.suppress_alerts=Suprimir alertas ConfigView.label.popup.use_message_boxes=Usar caixa de mensagem em vez da caixa de alerta popup padr\u00e3o. ConfigView.label.popup.show=Mostrar todos os alertas popup registrados at\u00e9 agora (se h\u00e1 algum) ConfigView.label.popup.show.button=Mostrar ConfigView.label.please.visit.here=Por favor visite aqui para detalhes ConfigView.section.ipfilter.enable.descriptionCache=Armazenar as descri\u00e7\u00f5es de IP em arquivo de rascunho ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Quando desatida, as descri\u00e7\u00f5es n\u00e3o ser\u00e3o lembradas OpenTorrentWindow.filesInfo=%1 de %2 ser\u00e3o baixados. OpenTorrentWindow.diskUsage=%1 de %2 ConfigView.label.openmytorrents=Abrir 'Meus Torrents' ao iniciar ConfigView.label.open_transfer_bar_on_start=Abrir a Barra de Transfer\u00eancia ao iniciar ConfigView.section.style.DNDalwaysInIncomplete=Sempre mostrar torrents com arquivos para 'N\u00e3o Baixar' na se\u00e7\u00e3o Incompletos de Meus Torrents OpenTorrentWindow.mb.noGlobalDestDir.title=Diret\u00f3rio Destino OpenTorrentWindow.mb.noGlobalDestDir.text=O diret\u00f3rio destino '%1' \u00e9 inv\u00e1lido. OpenTorrentWindow.mb.noDestDir.title=Diret\u00f3rio Destino n\u00e3o achado OpenTorrentWindow.mb.noDestDir.text=O diret\u00f3rio destino '%1' para o torrent '%2' n\u00e3o existe ou \u00e9 inv\u00e1lido. OpenTorrentWindow.mb.notValid.title=Abrir Torrent OpenTorrentWindow.mb.notValid.text=N\u00e3o p\u00f4de abrir o torrent '%1'. Se voc\u00ea est\u00e1 abrindo no modo ficar de seed, por favor tenha certeza de que os arquivos de dados do torrent existem. OpenTorrentWindow.mb.notTorrent.title=Abrir Torrent OpenTorrentWindow.mb.notTorrent.text=N\u00e3o p\u00f4de abrir '%1'. N\u00e3o aparenta ser um arquivo .torrent.\n\nAlguns dos dados recebidos:\n%2 ConfigView.label.pause.downloads.on.exit=Pausar downloads ao sair ConfigView.label.resume.downloads.on.start=Resumir downloads pausados ao iniciar ap\u00f3s a inicializa\u00e7\u00e3o completar UIDebugGenerator.message.cancel.title=Gerar Info de Debug Info Cancelado UIDebugGenerator.message.cancel.text=Voc\u00ea n\u00e3o inseriu uma descri\u00e7\u00e3o do bug que voc\u00ea est\u00e1 tentando reportar. O seu bug pode ser \u00f3bvio pra voc\u00ea, mas sem uma descri\u00e7\u00e3o, n\u00f3s s\u00f3 estar\u00edamos tentando advinhar o seu problema.\n\nA Gera\u00e7\u00e3o de Informa\u00e7\u00e3o sobre o Debug foi cancelada. ConfigView.section.connection.group.http.info=Suporte para seeding HTTP. ConfigView.section.connection.http.enable=Ativar ConfigView.section.connection.http.port=N\u00famero da porta de entrada ConfigView.section.connection.http.portoverride=N\u00e3o Levar em Conta a Porta HTTP do Tracker [0: nenhuma] window.update.noupdates.title=Procurar pelos Resultados das Atualiza\u00e7\u00f5es window.update.noupdates.text=N\u00e3o h\u00e1 novas atualiza\u00e7\u00f5es dispon\u00edveis para voc\u00ea.\n\nParab\u00e9ns! ConfigView.label.bindip.details=Exemplo: 192.168.1.5;eth0;eth1[2] prender\u00e1 o IP especificado a todos os IPs da 1\u00aa interface e ao 3\u00ba IP da 2\u00aa interface.\nO 1\u00ba IP ser\u00e1 usado para todos os servi\u00e7os, todos os outros s\u00e3o usados s\u00f3 para o balan\u00e7o da carga.\nAs seguintes interfaces est\u00e3o dispon\u00edveis:\n%1 ConfigView.label.mindownloads=M\u00edn. de downloads simult\u00e2neos UI.cannot_submit_blank_text=Voc\u00ea deve inserir um valor. crypto.alert.as.warning=Rede '%1' \u00e9 conhecida por imp\u00f4r traffic shaping para reduzir a performance de download. A encripta\u00e7\u00e3o do transporte foi automaticamente ligada - isto pode ser desligado/modificado via par\u00e2metros de configura\u00e7\u00e3o. ConfigView.section.interface.alerts=Alertas ConfigView.label.popupdownloadadded=Mostrar um alerta quando um download \u00e9 adicionado popup.download.added="%1" foi adicionado a sua lista de downloads. MessageBoxWindow.nomoreprompting=N\u00e3o me alertar de novo TorrentOptionsView.param.max.seeds=N\u00famero m\u00e1ximo de conex\u00f5es de seed [0: limite de conex\u00f5es] TorrentOptionsView.param.alternative.value.enable=Alternar o valor quando ficando de seed ConfigView.section.proxy.check.on.start=Verificar o status do proxy ao iniciar TransferStatsView.legend.pingaverage=M\u00e9dia TransferStatsView.legend.ping1=Alvo 1 TransferStatsView.legend.ping2=Alvo 2 TransferStatsView.legend.ping3=Alvo 3 ConfigView.section.interface.enabletray._mac=Ativar o \u00cdcone da Barra de Status [requer reiniciar] ConfigView.label.closetotray._mac=Fechar minimiza para o \u00cdcone da Barra de Status ConfigView.label.minimizetotray._mac=Minimizar minimiza para o \u00cdcone da Barra de Status OpenTorrentWindow.mb.existingFiles.title=O(s) Arquivo(s) j\u00e1 existe(m)! OpenTorrentWindow.mb.existingFiles.text=Alguns dos arquivos j\u00e1 existem na(s) pasta(s) destino que voc\u00ea especificou:\n\n%1\nSe voc\u00ea continuar, o Vuze verificar\u00e1 o(s) arquivo(s) acima pelos dados corretos e sobrescrever\u00e1 se necess\u00e1rio. splash.unloadingTorrents=Descarregando Torrents splash.unloadingTorrent=Descarregando Torrent ConfigView.section.file.defaultdir.autorename=Auto renomear os dados do torrent se os arquivos no caminho parecem diferentes ConfigView.section.file.defaultdir.autorename.tooltip=Isto impede um torrent de sobrescrever os arquivos de outro torrent quando os nomes dos arquivos s\u00e3o os mesmos alert.raised.at.close=(Mensagem do fechamento anterior do Vuze) Plugin.trackerpeerauth.name=Autoriza\u00e7\u00e3o do Peer do Tracker Plugin.trackerpeerauth.info=Este plugin trabalha com os trackers para verificar que os peers s\u00e3o membros v\u00e1lidos da multid\u00e3o Peers.column.maxupspeed=Velocidade M\u00e1x. de Upload Peers.column.maxdownspeed=Velocidade M\u00e1x. de Download MyTorrents.items.DownSpeedLimit.disabled=Nenhum download upnp.selectedaddresses=Endere\u00e7os (';' separados, '-' prefixo=negar, '+' =permitir) [em branco: qualquer um] upnp.alert.multipledevice.warning=M\u00faltiplos dispositivos UPnP foram detectados - verifique se todos requerem mapeamento de porta (veja o log e a configura\u00e7\u00e3o do UPnP) UpdateMonitor.messagebox.restart.title=Atualiza\u00e7\u00e3o do Software UpdateMonitor.messagebox.restart.text=O Vuze completou o download de uma atualiza\u00e7\u00e3o importante e agora deve ser reiniciado para que a atualiza\u00e7\u00e3o possa ser instalada. PiecesView.BlockView.Have=Tem PiecesView.BlockView.NoHave=N\u00e3o Tem PiecesView.BlockView.Header=%1 coluna(s), %2 fileira(s), %3 peda\u00e7os ConfigView.section.update.autodownload=Auto-baixar atualiza\u00e7\u00f5es e alertar quando a instala\u00e7\u00e3o estiver pronta Peers.column.peer_id=ID do Peer Peers.column.peer_id.info=A ID do Peer em formul\u00e1rio leg\u00edvel Peers.column.peer_byte_id=ID do Peer Peers.column.peer_byte_id.info=ID do Peer em formul\u00e1rio em bytes Peers.column.handshake_reserved=Bytes Reservados para o Handshake Peers.column.handshake_reserved.info=Indica quais bits reservados foram definidos no handshake BT Peers.column.client_identification=Identifica\u00e7\u00e3o do Cliente Peers.column.client_identification.info=Indica os nomes naturais dos clientes recebidos pelo Vuze - \u00fatil para debugging dht.warn.user=Avisar sobre problemas de mapeamento de NAT/portas em potencial ConfigView.label.openbar.incomplete=Barras de download: auto-abrir downloads ConfigView.label.openbar.complete=auto-abrir seeds ConfigView.label.transferbar.remember_location=Lembrar do \u00faltimo local da barra de transfer\u00eancia ConfigView.section.transfer.autospeed.forcemin=Velocidade de upload em %1 for\u00e7ada quando baselining a conex\u00e3o MainWindow.menu.tools.speedtest=Teste de Velocidade... speedtest.wizard.title=Teste de Velocidade speedtest.wizard.run=Executar um teste de velocidade speedtest.wizard.test.mode.updown=upload e download SpeedTestWizard.test.panel.currinfo=Teste de banda BitTorrent. SpeedTestWizard.test.panel.label=Teste de velocidade do Vuze: SpeedTestWizard.test.panel.already.running=O teste j\u00e1 est\u00e1 rodando! SpeedTestWizard.test.panel.not.accepted=Pedido de teste n\u00e3o aceito: SpeedTestWizard.test.panel.abort=Abortar SpeedTestWizard.test.panel.abort.countdown=abortar teste em: SpeedTestWizard.test.panel.test.countdown=o teste termina em: SpeedTestWizard.test.panel.testfailed=O teste falhou SpeedTestWizard.test.panel.aborted=Teste abortado manualmente. SpeedTestWizard.test.panel.enc.label=Pressionar o teste com encripta\u00e7\u00e3o: SpeedTestWizard.test.panel.standard=padr\u00e3o SpeedTestWizard.test.panel.encrypted=encriptado SpeedTestWizard.set.upload.button.apply=Aplicar SpeedTestWizard.set.upload.result=\u00daltimo Resultado do Teste SpeedTestWizard.set.upload.bytes.per.sec=kBytes/seg SpeedTestWizard.set.upload.bits.per.sec=bits/seg SpeedTestWizard.finish.panel.title=O Teste de Velocidade Terminou! SpeedTestWizard.finish.panel.click.close=Voc\u00ea fechou o assitente do teste de velocidade. Clique em fechar para sair. SpeedTestWizard.finish.panel.max.upload=Upload m\u00e1x: SpeedTestWizard.finish.panel.max.seeding.upload=M\u00e1x. de upload enquanto ficando de seed : SpeedTestWizard.finish.panel.max.download=Download m\u00e1x: SpeedTestWizard.finish.panel.enabled=ativado SpeedTestWizard.finish.panel.disabled=desativado SpeedTestWizard.abort.message.scheduled.in=teste agendado em ... %1 segundos" SpeedTestWizard.abort.message.unsupported.type=Tipo de teste n\u00e3o suportado!!!! SpeedTestWizard.abort.message.manual.abort=Manualmente abortado SpeedTestWizard.abort.message.scheduling.failed=O agendamento do teste falhou SpeedTestWizard.abort.message.download.added=Download %1 adicionado durante o teste SpeedTestWizard.abort.message.entered.error=Teste de download entrou em estado de erro '%1' SpeedTestWizard.abort.message.entered.queued=Teste baixado entrou em estado requerido/parado SpeedTestWizard.abort.message.interrupted=TorrentSpeedTestMonitorThread foi interrompido antes que o teste completasse SpeedTestWizard.abort.message.execution.failed=A execu\u00e7\u00e3o do teste falhou SpeedTestWizard.abort.message.failed.peers=Falhou em conectar a quaisquer peers SpeedTestWizard.abort.message.insufficient.slots=N\u00e3o p\u00f4de fazer upload a quaisquer dos peers - slots de upload insuficientes? SpeedTestWizard.abort.message.not.unchoked=N\u00e3o p\u00f4de baixar de quaisquer dos peers como nunca foi desobstru\u00eddo por eles SpeedTestWizard.stage.message.requesting=requesitando teste... SpeedTestWizard.stage.message.preparing=preparando teste... SpeedTestWizard.stage.message.starting=iniciando o teste... SpeedTestWizard.stage.message.connect.stats=Estat\u00edsticas da conex\u00e3o: peers=%1, down_ok=%2, up_ok=%3 window.uiswitcher.title=Escolhedor de IU do Vuze window.uiswitcher.text=Por favor selecione uma interface de usu\u00e1rio abaixo que melhor se ajusta as suas necessidades. window.uiswitcher.NewUI.text=* Recomendado para iniciantes e novos usu\u00e1rios.\n\n* Interface gr\u00e1fica f\u00e1cil, intuitiva\n\n* Interface requerida para publicar na plataforma Vuze window.uiswitcher.ClassicUI.title=Interface Cl\u00e1ssica window.uiswitcher.ClassicUI.text=* Ret\u00e9m a funcionalidade do cliente da s\u00e9rie 2.x\n\n* O layer de conte\u00fado Vuze n\u00e3o ser\u00e1 carregado window.uiswitcher.bottom.text=Sua sele\u00e7\u00e3o pode ser mudada facilmente de novo selecionando o bot\u00e3o do Escolhedor de IU do Vuze iconBar.switch.tooltip=Escolher a Interface de Usu\u00e1rio do Vuze VivaldiView.notAvailable=Visualiza\u00e7\u00e3o Vivaldi n\u00e3o dispon\u00edvel restart.error=Reiniciar falhou:\n%1\nVeja problemas ao reiniciar. restart.error.oom=Mem\u00f3ria Esgotada restart.error.fnf='%1' n\u00e3o encontrado em '%2' restart.error.pnf=Path '%1' n\u00e3o encontrado restart.error.bad=Arquivo de formato ruim para '%1' restart.error.denied=O acesso foi negado quando tentando executar '%1'. Tenha certeza de que voc\u00ea tem os direitos para rodar este programa. TableColumn.header.date_completed=Completado Em TableColumn.menu.date_added.reset=Data do Reset ConfigView.section.ipfilter.discardbanning=Bloquear peers cuja propor\u00e7\u00e3o de dados descartados ruins/bons exceder [0: desativado] ConfigView.section.ipfilter.discardminkb=M\u00ednimo de %1 descartados antes de aplicar a propor\u00e7\u00e3o ConfigView.interface.start.advanced=Iniciar na Visualiza\u00e7\u00e3o Avan\u00e7ada (AZ 2.x) MyTorrents.column.ColumnQuality=Qualidade MyTorrents.column.ColumnSpeed=Velocidade MyTorrents.column.ColumnProgressETA.2ndLine=TEC: %1 MyTorrents.column.ColumnProgressETA.StreamReady=Streaming Pronto MyTorrents.column.ColumnProgressETA.PlayableIn=Toc\u00e1vel em %1 TableColumn.header.Quality=Qualidade TableColumn.header.Speed=Velocidade TableColumn.header.RateIt=Taxa TableColumn.header.Rating=Classifica\u00e7\u00e3o TableColumn.header.SpeedGraphic=Velocidade TableColumn.header.AzProduct=De TableColumn.header.MediaThumb=M\u00eddia TableColumn.header.ProgressETA=Progresso #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=Tipo de Arquivo: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.browse=No Vuze v3.MainWindow.tab.library=Biblioteca v3.MainWindow.tab.publish=Publicar v3.MainWindow.tab.advanced=Avan\u00e7ado v3.MainWindow.menu.browse=&No Vuze v3.MainWindow.menu.library=&Biblioteca v3.MainWindow.menu.publish=&Publicar v3.MainWindow.menu.advanced=&Avan\u00e7ado v3.MainWindow.menu.view.searchbar=Barra de Busca v3.MainWindow.menu.view.tabbar=Barra de Abas v3.MainWindow.currentDL=Atualmente Baixando v3.MainWindow.button.stop=Parar v3.MainWindow.button.start=Iniciar v3.MainWindow.button.pause=Pausar v3.MainWindow.button.resume=Resumir v3.MainWindow.button.delete=Apagar v3.MainWindow.button.comment=Comentar v3.MainWindow.button.viewdetails=Ver Detalhes v3.MainWindow.button.play=Tocar v3.MainWindow.button.cancel=Cancelar v3.MainWindow.button.preview=Pr\u00e9-visualiza\u00e7\u00e3o v3.MainWindow.view.wait=Inicializando a visualiza\u00e7\u00e3o, por favor espere. v3.MainWindow.xofx=%1 de %2 v3.MainWindow.Loading=Carregando.. Por favor espere v3.filter-bar=T\u00edtulo do Filtro: v3.MainWindow.search.defaultText=Procurar no Vuze v3.mb.delPublished.title=Parar de Ficar de Seed com este Conte\u00fado v3.mb.delPublished.text=AVISO: Esta a\u00e7\u00e3o N\u00c3O remover\u00e1 seu conte\u00fado publicado '%1' de %3 .\n\nClique em "Apagar" apenas se voc\u00ea quer que o seu conte\u00fado permane\u00e7a publicado e baix\u00e1vel, mas quer liberar a sua banda. Tenha certeza de que o processo de upload foi completado antes de faz\u00ea-lo (how?).\n\nClique em "Cancelar" se voc\u00ea quer remover completamente seu conte\u00fado publicado de %3, e usar o bot\u00e3o (X) no painel de Conte\u00fado Publicado na aba Publicar.\n\nMais ajuda.\n\n v3.mb.delPublished.delete=&Apagar v3.mb.delPublished.cancel=&Cancelar v3.mb.openFile.title=Abrir o Arquivo v3.mb.openFile.text.known=Este conte\u00fado n\u00e3o \u00e9 atualmente suportado pelo player do Vuze. Verifique a comunidade criada Guia do Playback por ajuda.\n\nO Tipo do Arquivo Aparenta ser: %2 (%3)\n v3.mb.openFile.text.unknown=Este conte\u00fado n\u00e3o \u00e9 atualmente suportado pelo player do Vuze. Verifique a comunidade criada Guia do Playback por ajuda.\n\nExtens\u00e3o do Arquivo : %2\n v3.mb.openFile.button.play=Reproduzir v3.mb.openFile.button.cancel=Cancelar v3.mb.openFile.button.guide=Leia o Guia do Playback v3.mb.openFile.remember=Sempre abrir os arquivos sem me perguntar v3.mb.PlayFileNotFound.title=Arquivo N\u00e3o Encontrado v3.mb.PlayFileNotFound.text=Os arquivos para '%1' est\u00e3o ou apagados ou desaparecidos. v3.mb.PlayFileNotFound.button.remove=Remover do Vuze v3.mb.PlayFileNotFound.button.redownload=Baixar Dados de Novo v3.mb.PlayFileNotFound.button.find=Achar Manualmente.. v3.mb.deletePurchased.title=Remover o Conte\u00fado Comprado v3.mb.deletePurchased.text=Voc\u00ea tem certeza de que voc\u00ea quer apagar o conte\u00fado '%1'?\n\nIsto \u00e9 conte\u00fado que voc\u00ea ou comprou, ou voc\u00e9 \u00e9 requerido logar para baixar. v3.mb.deletePurchased.button.delete=&Apagar v3.mb.deletePurchased.button.cancel=&Cancelar v3.topbar.menu.show.plugin=\u00c1rea dos Plugins v3.topbar.menu.show.search=Busca v3.topbar.menu.show.frog=O Sapo Azul splash.initializeCore=Iniiciando o Core splash.initializeUIElements=Inicializando os Elementos da Interface do Usu\u00e1rio ConfigView.section.transfer.autospeedbeta=Auto-Velocidade-Beta # ConfigView.section.ipfilter.peerblocking.group=Bloqueio de Peers ConfigView.section.ipfilter.autoload.group=Auto Carregar ConfigView.section.ipfilter.autoload.file=Arquivo de filtro de IP para auto-carregar ConfigView.section.ipfilter.autoload.info=Suporta DAT (eMule), P2P (PeerGuardian, splist), e P2B v1,2,3 formatos do (PeerGuardian 2). O arquivo pode ser local ou URL, zip'd, gzip'd ou texto simples. As URLs automaticamente ser\u00e3o baixadas de novo ap\u00f3s 7 dias, enquanto que os arquivos recarregar\u00e3o dentro de um minuto a serem substitu\u00eddos/tocados. ConfigView.section.ipfilter.autoload.loadnow=Carregar Agora splash.loadIpFilters=Carregando os Filtros de IP.. SpeedTestWizard.set.upload.title=Definir Limites de Upload e Download SpeedTestWizard.set.download.label=Limite da Velocidade de Download: SpeedTestWizard.set.upload.label=Limite da Velocidade de Upload: SpeedTestWizard.name.conf.level.absolute=Absoluto SpeedTestWizard.name.conf.level.high=Alta SpeedTestWizard.name.conf.level.med=M\u00e9dia SpeedTestWizard.name.conf.level.low=Baixa SpeedTestWizard.name.conf.level.none=Nenhum ConfigView.section.transfer.select=Auto-Velocidade ConfigView.section.transfer.select.v2=Auto-Velocidade (beta) mb.azmustclose.title=Erro de Inicializa\u00e7\u00e3o mb.azmustclose.text=O Vuze deve fechar devido a um problema ao (re)iniciar o Vuze, isso provavelmente fez o programa ser executado como um usu\u00e1rio Administrador.\n\nAp\u00f3s o Vuze fechar, por favor re-abra-o manualmente. network.ipv6.prefer.addresses=Preferir os endere\u00e7os IPv6 quando ambos IPv6 e IPv4 est\u00e3o dispon\u00edveis network.bindError=Falhou em prender o socket do servidor como nenhum dos endere\u00e7os compat\u00edveis est\u00e3o dispon\u00edveis, por favor verifique suas configura\u00e7\u00f5es de prender-ao-IP. network.enforce.ipbinding=Refor\u00e7ar as amarras ao IP mesmo quando as interfaces n\u00e3o est\u00e3o dispon\u00edveis, impede quaisquer conex\u00f5es se nenhuma das interfaces especificadas est\u00e3o dispon\u00edveis DHTView.title.full_v6=Base de Dados Distribu\u00edda IPv6 ConfigView.pluginlist.loadSelected=Carregar os Selecionados SpeedView.stats.asn=Rede: SpeedView.stats.estupcap=Limite de Upload: SpeedView.stats.estdowncap=Limite de Download: SpeedView.stats.unknown=Desconhecido SpeedView.stats.estimate=Estimativa SpeedView.stats.measured=Medido SpeedView.stats.measuredmin=M\u00edn. medido SpeedView.stats.manual=Consertado ConfigView.section.transfer.autospeed.networks=Detalhes da Rede ConfigView.section.transfer.autospeed.resetnetwork=Resetar detalhes da rede ConfigView.section.transfer.autospeed.network.info=Os limites acima s\u00e3o normalmente calculados automaticamente durante o download ou s\u00e3o o resultado de um teste de velocidade. Se voc\u00ea quer especific\u00e1-los manualmente use a op\u00e7\u00e3o abaixo.\nTodos os limites al\u00e9m dos 'consertados' ser\u00e3o subsequencialmente ajustados se necess\u00e1rio. \nInsira o valor e ent\u00e3o selecione seu tipo. Note que as velocidades est\u00e3o em %1. dialog.uiswitcher.restart.title=Trocador de Interface do Usu\u00e1rio: Requerido Reiniciar o Vuze dialog.uiswitcher.restart.text=O Vuze precisa reiniciar para trocar para o modo da nova Interface do Usu\u00e1rio. TrayWindow.menu.close=Fechar a Cesta de Download # Used for peers which we can't determine. PeerSocket.unknown=Desconhecido PeerSocket.fake_client=FALSO PeerSocket.bad_peer_id=ID do peer ruim PeerSocket.mismatch_id=n\u00e3o combinam PeerSocket.unknown_az_style=Desconhecido %1/%2 PeerSocket.unknown_shadow_style=Desconhecido %1/%2 OpenTorrentWindow.mb.askCreateDir.title=O Diret\u00f3rio Destino n\u00e3o existe OpenTorrentWindow.mb.askCreateDir.text=O diret\u00f3rio destino '%1' n\u00e3o existe.\n\nCriar agora? SpeedView.stats.estimatechoke=Estimativa (desobstru\u00e7\u00e3o) ConfigTransferAutoSpeed.upload.capacity.usage=Uso da Capacidade de Upload ConfigTransferAutoSpeed.mode=Modo: ConfigTransferAutoSpeed.capacity.used=% da Capacidade Usada ConfigTransferAutoSpeed.while.downloading=Baixando: ConfigTransferAutoSpeed.set.dht.ping=Configura\u00e7\u00e3o do Ping DHT: ConfigTransferAutoSpeed.set.point=definir ponto (ms) ConfigTransferAutoSpeed.set.tolerance=toler\u00e2ncia (ms) ConfigTransferAutoSpeed.ping.time.good=Bom: ConfigTransferAutoSpeed.ping.time.bad=Ruim: ConfigTransferAutoSpeed.adjustment.interval=Intervalo do ajuste: ConfigTransferAutoSpeed.skip.after.adjust=Pular ap\u00f3s o ajuste: GeneralView.label.distributedCopies=C\u00f3pias Distribu\u00eddas: PiecesView.DistributionView.title=Distribui\u00e7\u00e3o dos Peda\u00e7os PiecesView.DistributionView.NoAvl=Peda\u00e7os Indispon\u00edveis PiecesView.DistributionView.SeedAvl=Contribui\u00e7\u00e3o Avl do Seed PiecesView.DistributionView.PeerAvl=Contribui\u00e7\u00e3o Avl do Peer PiecesView.DistributionView.RarestAvl=Peda\u00e7os Mais Raros: %1 (Avl:%2) PiecesView.DistributionView.weHave=Peda\u00e7os que voc\u00ea tem PiecesView.DistributionView.theyHave=Peda\u00e7os que o peer tem PiecesView.DistributionView.weDownload=Peda\u00e7os que voc\u00ea est\u00e1 baixando PeersView.gain=Ganho PeersView.gain.info=Quantidade de dados baixados - enviados unix.script.new.title=Novo Script de Inicializa\u00e7\u00e3o do Vuze dispon\u00edvel unix.script.new.text=Um novo script de inicializa\u00e7\u00e3o do Vuze est\u00e1 dispon\u00edvel, e foi salvo em '%1'.\n\n\u00c9 altamente recomendado que voc\u00ea saia do Vuze e troque para este script ('%2').\n\nSe voc\u00ea modificou seu script de inicializa\u00e7\u00e3o do Vuze pesadamente, por favor veja AzureusWiki: Unix Script.\n\nSe voc\u00ea instalou o Vuze de uma distro (yum, apt-get, etc), \u00e9 recomendado que voc\u00ea reinstale o Vuze usando o pacote em P\u00e1gina do Vuze no Sourceforge (Voc\u00ea ainda obter\u00e1 a mesma IU que voc\u00ea tem agora) unix.script.new.button.quit=Sair Agora unix.script.new.button.continue=Eu o farei depois unix.script.new.button.asknomore=N\u00e3o me diga de novo unix.script.new.auto.title=Novo Script de Inicializa\u00e7\u00e3o do Vuze unix.script.new.auto.text=Um Novo Script de Inicializa\u00e7\u00e3o do Vuze est\u00e1 dispon\u00edvel.\n\n\u00c9 altamente recomendado que voc\u00ea reinicie o Vuze agora. Content.alert.notuploaded.button.stop=&Parar Content.alert.notuploaded.button.continue=&Continuar Ficando de Seed Content.alert.notuploaded.button.abort=&N\u00e3o Sair ConfigView.label.checkOnSeeding=Realizar re-verifica\u00e7\u00e3o de baixo recurso de peda\u00e7os quando ficando de seed ConfigView.label.ui_switcher=Exibir o Escolhedor de Interface Gr\u00e1fica do Vuze ConfigView.label.ui_switcher_button=Mostrar SpeedTestWizard.test.panel.explain=Mede sua velocidade no protocolo do Vuze. Selecione o tipo de teste de velocidade e o modo de encripta\u00e7\u00e3o. Visite a p\u00e1gina do wiki do Vuze para detalhes sobre este teste. O teste parar\u00e1 automaticamente se ele levar mais do que 2 minutos. Testes t\u00edpicos terminam em menos de 1 minuto. SpeedTestWizard.set.upload.hint=Definir os limites de upload e download usados pelo algor\u00edtmo de AutoVelocidade do Vuze. SpeedTestWizard.set.upload.panel.explain=Os limites definidos aqui s\u00e3o usados pelo algor\u00edtmo de AutoVelocidade do Vuze. Defina os limites de transfer\u00eancia e os limites de confian\u00e7a.\n\nNote que as velocidades da linha s\u00e3o frequentemente quotadas em "bits por segundo" - contudo o valor abaixo \u00e9 mostrado em "kilobytes por segundo". SpeedTestWizard.set.limit.conf.level=Confian\u00e7a SpeedTestWizard.finish.panel.auto.speed=AutoVelocidade \u00e9 : SpeedTestWizard.finish.panel.auto.speed.seeding=AutoVelocidade enquanto ficando de seed \u00e9 : ConfigTransferAutoSpeed.add.comment.to.log.group=Adicionar coment\u00e1rio ao log de debug ConfigTransferAutoSpeed.add.comment.to.log=Coment\u00e1rio: ConfigTransferAutoSpeed.algorithm.selector=Seletor de Auto-Velocidade ConfigTransferAutoSpeed.algorithm=Algor\u00edtmo: ConfigTransferAutoSpeed.auto.speed.classic=Auto-Velocidade(cl\u00e1ssica) ConfigTransferAutoSpeed.auto.speed.beta=Auto-Velocidade(beta) ConfigTransferAutoSpeed.data.update.frequency=Frequ\u00eancia da Atualiza\u00e7\u00e3o Alert.failed.update=A instala\u00e7\u00e3o de pelo menos um componente falhou. Veja AzureusWiki: A Atualiza\u00e7\u00e3o Falhou OpenTorrentWindow.mb.existingFiles.partialList=(Lista Parcial. Mais arquivos j\u00e1 existem) TableColumn.header.bad_avail_time.info=\u00daltima vez que uma c\u00f3pia completa do download estava dispon\u00edvel TableColumn.header.bad_avail_time=C\u00f3pia Completa Vista MyTorrentsView.menu.exporthttpseeds=Export URLs de seed HTTP para a \u00c1rea de Transfer\u00eancia SWT.alert.erroringuithread=Um erro n\u00e3o manejado ocorreu na GUI, mais erros podem ser reportados. ConfigView.label.minannounce=Tempo m\u00ednimo entre an\u00fancios de tracker em segundos ConfigView.label.maxnumwant=Limitar o n\u00famero de peers que o tracker pode retornar ConfigView.label.announceport=N\u00e3o levar em conta a porta TCP anunciada para os an\u00fancios do tracker, pex e dht\n[deixar vazio: sem levar em conta, 0: sem conex\u00f5es de entrada] ConfigView.label.noportannounce=N\u00e3o anunciar a porta de escuta para o tracker (isto n\u00e3o afeta o pex, dht) ConfigView.label.maxseedspertorrent=M\u00e1x. de seeds por torrent padr\u00e3o [0: ilimitados] wizard.webseed=Adicionar Seeds HTTP ao torrent wizard.webseed.title=Seeds HTTP wizard.webseed.configuration=Configur\u00e3\u00e7\u00e3o de Seed HTTP wizard.webseed.adding=Adicionar Seeds HTTP GeneralView.label.private=Torrent Privado: GeneralView.yes=sim GeneralView.no=n\u00e3o ConfigView.label.userequestlimiting=Usar pedido de throttling em vez de leituras atrasadas para limitar a velocidade de download [sem efeito quando a velocidade de download \u00e9 ilimitada] ConfigView.label.userequestlimiting.tooltip=Limitar Pedidos n\u00e3o \u00e9 t\u00e3o leve como as leituras atrasadas, mas permite a prioriza\u00e7\u00e3o do download baseado no posi\u00e7\u00e3o da fila do download e poderia melhorar a performance da rede ConfigView.label.userequestlimitingpriorities=Focar a velocidade do download no come\u00e7o da fila de download quando o limite da velocidade de download foi alcan\u00e7ado ConfigView.section.logging.timestamp=Formato da estampa de tempo para arquivos log Peers.column.timetocomplete=Tempo Restante Peers.column.timetocomplete.info=Tempo restante at\u00e9 o peer estar completo ConfigView.section.interface.display.suppress.file.download.dialog=Suprimir o di\u00e1logo popup do Download do Arquivo ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Mostrar todo o progresso do download do arquivo na barra de status em vez de um di\u00e1logo popup FileDownload.canceled=Um download de arquivo torrent foi cancelado com sucesso por uma a\u00e7\u00e3o do usu\u00e1rio: %1 Progress.reporting.status.canceled=Cancelado Progress.reporting.status.finished=Terminou Progress.reporting.status.retrying=Tentando de Novo... Progress.reporting.action.label.retry.tooltip=Tentar de novo a opera\u00e7\u00e3o Progress.reporting.action.label.remove.tooltip=Remover este Relat\u00f3rio de Progresso do hist\u00f3rico Progress.reporting.action.label.cancel.tooltip=Cancelar a opera\u00e7\u00e3o Progress.reporting.action.label.detail=Detalhes Progress.reporting.default.error=Falhou Progress.reporting.no.reports.to.display=N\u00e3o h\u00e1 Relat\u00f3rios de Progresso para exibir desta vez Progress.reporting.no.history.to.display=N\u00e3o h\u00e1 mensagens detalhadas a exibir Progress.reporting.detail.history.limit=O limite de mensagens detalhadas (%1) para este ProgressReporter foi excedido; mensagens subsequentes ser\u00e3o adicionadas ao hist\u00f3rico Progress.reporting.statusbar.button.tooltip=Mostrar a Janela de Relat\u00f3rio do Progresso webui.bindip=Prender IP - normalmente n\u00e3o requerido (*) v3.MainWindow.text.log.in=Assinar pra entrar v3.MainWindow.text.log.out=Assinar pra sair v3.MainWindow.text.get.started=Se Inicie v3.MainWindow.text.my.account=Minha Conta v3.MainWindow.text.my.profile=Perfil OpenTorrentWindow.simple.open=Local do Torrent (Arquivo, URL, Hash) Progress.reporting.window.remove.auto=Automaticalmente remover itens inativos Progress.reporting.window.remove.auto.tooltip=Automaticalmente remover todos os processos completados, falhos ou cancelados da visualiza\u00e7\u00e3o Progress.reporting.window.remove.now=Remover itens inativos Progress.reporting.window.remove.now.tooltip=Remover todos os processos completados, falhos ou cancelados da visualiza\u00e7\u00e3o dhttracker.tracklimitedwhenonline=Contudo, realize rastreamento de baixo recurso quando online para cruzamento da popula\u00e7\u00e3o na multid\u00e3o TorrentOptionsView.multi.title.short=Op\u00e7\u00f5es do Torrent TorrentOptionsView.multi.title.full=Op\u00e7\u00f5es do Torrent MyTorrentsView.menu.open_parent_folder=Abrir a Pasta Contendo ConfigView.section.style.use_show_parent_folder=Usar "%1" em vez de "%2" nos menus do torrent ConfigView.section.style.use_show_parent_folder.tooltip=Ativar esta op\u00e7\u00e3o permitir\u00e1 a voc\u00ea abrir a pasta de conten\u00e7\u00e3o no aplicativo gerenciador de arquivos correto.\nContudo, pode significar que o local para salvar o download n\u00e3o \u00e9 selecionado automaticamente. PeerManager.status.ps_disabled=A fonte peer do Tracker est\u00e1 desativada ConfigView.section.stats.exportfiles=Exportar os detalhes do arquivo updater.cant.write.to.app.title=N\u00e3o P\u00f4de Escrever na Pasta do Aplicativo updater.cant.write.to.app.details=A pasta "%1" n\u00e3o pode ser escrita.\n\nIsto impedir\u00e1 que atualiza\u00e7\u00f5es futuras do software sejam aplicadas.\n\nPor favor veja o wiki para detalhes. plugin.install.class_version_error=Este plugin requer uma vers\u00e3o mais nova do Java para rodar. v3.MainWindow.tab.events=Atividade button.columnsetup.tooltip=Configura\u00e7\u00e3o da Coluna v3.activity.remove.title=Remover a Entrada da Atividade v3.activity.remove.text=Voc\u00ea tem certeza de que voc\u00ea quer remover o evento da atividade '%1'? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=Fechar Menu.show.torrent.menu=Mostrar o menu Torrents Menu.show.torrent.menu.tooltip=Mostra o menu Torrents na barra do menu do aplicativo no topo #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=Status da Rede plugin.aznetstatus.pingtarget=Ping/trace a rota do alvo ConfigView.section.style.usePathFinder=Usar 'Descobridor de Caminhos' em vez do 'Descobridor' menu.sortByColumn=Organizar Por %1 MyTorrentsView.menu.manual.per_peer=Manual (por peer) MyTorrentsView.menu.manual.shared_peers=Manual (pelos peers) v3.button.removeActivityEntry=Remover a Entrada da Atividade v3.splash.initSkin=Inicializando a Skin da UI v3.splash.hookPluginUI=Enganchando na UI do Plugin OpenTorrentWindow.mb.notTorrent.cannot.display=Incapaz de exibir os dados apropriadamente MainWindow.menu.window.zoom.maximize=Maximizar MainWindow.menu.window.zoom.restore=Restaurar ImageResizer.image.too.small=A imagem fornecida \u00e9 muito pequena, por favor escolha uma imagem diferene (tem que ser pelo menos %1 x %2) ImageResizer.title=Esta ferramenta deixa voc\u00ea pr\u00e9-visualizar como o seu thumbnail vai parecer na Plataforma Vuze ImageResizer.move.image=Mova a imagem arrastando-a ImageResizer.move.image.with.slider=Mova a imagem arrastando-a, redimensione-a usando o slider abaixo security.crypto.title=Acesso a Chave de Encripta\u00e7\u00e3o security.crypto.encrypt=Por favor insira uma senha para proteger sua chave de encripta\u00e7\u00e3o gerada recentemente. Por favor n\u00e3o esque\u00e7a esta senha, n\u00e3o h\u00e1 meio de recuper\u00e1-loa se voc\u00ea esquecer! security.crypto.decrypt=Por favor insira sua senha para destrancar sua chave de encripta\u00e7\u00e3o. security.crypto.reason=Motivo para a opera\u00e7\u00e3o security.crypto.password=Senha security.crypto.password2=Re-inserir a senha security.crypto.persist_for=Per\u00edodo de persist\u00eancia da senha security.crypto.persist_for.dont_save=N\u00e3o salvar security.crypto.persist_for.session=Esta sess\u00e3o security.crypto.persist_for.day=1 dia security.crypto.persist_for.week=1 semana security.crypto.persist_for.30days=30 dias security.crypto.persist_for.forever=Pra sempre security.crypto.password.mismatch.title=Erro com a Senha security.crypto.password.mismatch=Os valores inseridos da senha n\u00e3o combinam, por favor re-insira-os. ConfigView.section.security.group.crypto=Chaves P\u00fablicas/Privadas ConfigView.section.security.resetkey=Resetar as chaves ConfigView.section.security.resetkey.warning.title=Aviso sobre a Perda de Dados ConfigView.section.security.resetkey.warning=Voc\u00ea tem certeza que voc\u00ea quer resetar suas chaves de encripta\u00e7\u00e3o? Se voc\u00ea o fizer toda a informa\u00e7\u00e3o encriptada usando elas ser\u00e1 PERMANENTEMENTE PERDIDA. Tamb\u00e9m quaisquer outros peers em possess\u00e3o da sua chave p\u00fablica n\u00e3o mais ser\u00e3o capazes de comunicar com voc\u00ea sem eles obterem sua nova chave. Ent\u00e3o, a menos que voc\u00ea realmente saiba o que voc\u00ea est\u00e1 fazendo, n\u00e3o fa\u00e7a isto. ConfigView.section.security.unlockkey=Destrancar as chaves explicitamente ConfigView.section.security.unlockkey.button=Destrancar ConfigView.section.security.publickey=Chave p\u00fablica ConfigView.section.security.publickey.undef=N\u00e3o definida ainda ConfigView.section.security.resetkey.error.title=A Opera\u00e7\u00e3o Falhou ConfigView.section.security.resetkey.error=Falhou em resetar as chaves ConfigView.section.security.unlockkey.error=Falhou em destrancar a chave - senha incorreta ConfigView.copy.to.clipboard.tooltip=Copiar para a \u00e1rea de transfer\u00eancia Views.plugins.azbuddy.title=Amigos Browser.popup.error.no.access=Um ocorreu enquanto tentava acessar um recurso remoto.\nPor favor tente de novo mais tarde.\n ConfigView.label.queue.stoponcebandwidthmet=N\u00e3o iniciar mais quaisquer torrents quando o limite da velocidade de upload/download for alcan\u00e7ado ConfigView.section.style.forceMozilla=For\u00e7ar o Vuze a usar o Mozilla para os widgets do Navegador [xulrunner ou firefox 3 requeridos; requer reiniciar] ConfigView.section.style.xulRunnerPath=Especificar o caminho do XulRunner / Firefox manualmente [requerido para o FF3; requer reiniciar] azbuddy.name=Amigos azbuddy.enabled=Ativado azbuddy.disabled=O plugin est\u00e1 desativado, veja a config do plugin para mudar. azbuddy.nickname=Seu Apelido azbuddy.msglog.title=Informa\u00e7\u00e3o sobre o Amigo azbuddy.addtorrent.title=Aceitar o Download? azbuddy.addtorrent.msg=O amigo '%1' enviou para voc\u00ea o '%2'.\nVoc\u00ea quer adicionar este download? azbuddy.contextmenu=Enviar para um Amigo azbuddy.ui.mykey=Minha chave: azbuddy.ui.add=Adicionar azbuddy.ui.new_buddy=Nova chave do amigo: azbuddy.ui.table.name=Nome azbuddy.ui.table.last_msg=\u00daltima Mensagem azbuddy.ui.menu.remove=Remover azbuddy.ui.menu.copypk=Copiar a Chave P\u00fablica azbuddy.ui.menu.send=Enviar Mensagem azbuddy.ui.menu.send_msg=Insira o texto a enviar para seu(s) amigo(s) azbuddy.ui.menu.ygm=Enviar o YGM azbuddy.ui.menu.enc=Encriptar a \u00c1rea de Transferencia azbuddy.ui.menu.dec=Decriptar a \u00c1rea de Transfer\u00eancia azbuddy.ui.menu.sign=Sinalizar a \u00c1rea de Transfer\u00eancia azbuddy.ui.menu.verify=Verificar a \u00c1rea de Transfer\u00eancia azbuddy.ui.table.lastseen=Visto pela \u00daltima Vez Button.retry=&Tentar de Novo Button.ignore=&Ignorar DHTView.general.skew=\u00c2ngulo: azbuddy.ui.table.msg_in=Msg Entra azbuddy.ui.table.msg_out=Msg Sai v3.MainWindow.menu.view.footer=Barra dos Amigos azbuddy.downspeed=M\u00e1x da velocidade de download em KB/s do amigo [0: ilimitada] security.crypto.badpw=A senha suprima estava incorreta ConfigView.section.security.backupkeys=Fazer backup das chave em um arquivo ConfigView.section.security.restorekeys=Restaurar as chaves de um arquivo ConfigView.section.security.restorekeys.button=Restaurar ConfigView.section.security.op.error.title=A Opera\u00e7\u00e3o Falhou ConfigView.section.security.op.error=Falhou em completar a opera\u00e7\u00e3o:\n %1 ConfigView.section.security.restart.title=Requer Reiniciar ConfigView.section.security.restart.msg=O Vuze reiniciar\u00e1 agora para completar a opera\u00e7\u00e3o. ConfigView.section.security.system.managed=Prote\u00e7\u00e3o da chave gerenciada pelo sistema azbuddy.ui.table.msg_queued=Na Fila azbuddy.chat.title=Chat do Vuze azbuddy.chat.says=%1 diz: Button.bar.show=Mostrar Button.bar.hide=Esconder Button.bar.share=Compartilhar Button.bar.add=Adicionar Amigos Button.bar.edit=Editar Button.bar.edit.cancel=Edi\u00e7\u00e3o Feita v3.MainWindow.menu.view.pluginbar=Barra dos Plugins MainWindow.dialog.select.vuze.file=Selecionar o Arquivo do Vuze MainWindow.menu.file.open.vuze=Arquivo do Vuze... metasearch.addtemplate.title=Instalar o Modelo de Busca? metasearch.addtemplate.desc=Voc\u00ea tem certeza que voc\u00ea quer instalar um modelo de busca chamdo '%1'? v3.share.private.title=Compartilhando o Torrent v3.share.private.text=O torrent selecionado est\u00e1 marcado como Torrent Privado.\n\nVoc\u00ea n\u00e3o pode compartilhar torrents privados. metasearch.addtemplate.dup.title=Modelo Duplicado metasearch.addtemplate.dup.desc=O modelo de busca %1 j\u00e1 est\u00e1 instalado metasearch.export.select.template.file=Salvar o Modelo metasearch.import.select.template.file=Abrir o Modelo dialog.uiswitch.title=Trocar para a IU do Vuze dialog.uiswitch.text=Voc\u00ea precisa estar executando a IU do Vuze para usar esta fun\u00e7\u00e3o.\n\nO Vuze precisar\u00e1 reiniciar. dialog.uiswitch.button=Trocar para a IU do Vuze azbuddy.tracker.enabled=Ativar a 'Acelera\u00e7\u00e3o do Amigo' para priorizar o download com seus amigos azbuddy.protocolspeed=Eleva\u00e7\u00e3o m\u00e1xima do protocolo em KB/s do amigo v3.MainWindow.button.run=Executar o Arquivo Baixado v3.activity.header.vuze.news=Not\u00edcias do Vuze message.taking.too.long=Aparenta que isto est\u00e1 tomando mais tempo do que o esperado\nPressione 'ESC' se voc\u00ea deseja cancelar esta opera\u00e7\u00e3o message.status.success=Sucesso azbuddy.tracker.bbb.status.title=Acelera\u00e7\u00e3o do Amigo azbuddy.tracker.bbb.status.title.tooltip=Clique duplo para detalhes azbuddy.tracker.bbb.status.idle=Sem acelera\u00e7\u00e3o azbuddy.tracker.bbb.status.nli=Login Requerido azbuddy.tracker.bbb.status.in=Eu Estou Sendo Acelerado azbuddy.tracker.bbb.status.out=Atualmente Acelerando os Amigos v3.MainWindow.search.go.tooltip=Executar a Busca v3.MainWindow.search.last.tooltip=Retornar para os resultados da busca metasearch.addtemplate.done.title=Modelo Adicionado metasearch.addtemplate.done.desc=Modelo '%1' adicionado com sucesso.\nEle ser\u00e1 usado quando voc\u00ea fizer a pr\u00f3xima busca! ConfigView.section.security.nopw=Nenhuma senha foi fornecida ConfigView.section.security.nopw_v=Nenhuma senha dispon\u00edvel, por favor logue no Vuze fileplugininstall.install.title=Instalar o Plugin? fileplugininstall.install.desc=Voc\u00ea tem certeza que voc\u00ea quer instalar o plugin '%1', vers\u00e3o %2? fileplugininstall.duplicate.title=Plugin Duplicado fileplugininstall.duplicate.desc=O Plugin '%1', vers\u00e3o %2 j\u00e1 est\u00e1 instalado azbuddy.online_status=Status Online azbuddy.os_away=Distante azbuddy.os_not_avail=N\u00e3o Dispon\u00edvel azbuddy.os_busy=Ocupado azbuddy.ui.menu.disconnect=Desconectar azbuddy.enable_chat_notif=Ativar as notifica\u00e7\u00f5es do chat progress.window.msg.progress=Por favor espere enquanto a opera\u00e7\u00e3o completa ConfigView.section.connection.advanced.read_select=Ler o tempo pra encerrar selecionado (milis, padr\u00e3o %1) ConfigView.section.connection.advanced.read_select_min=Ler a espera m\u00ednima selecionada (milis, padr\u00e3o %1) ConfigView.section.connection.advanced.write_select=Gravar o tempo pra encerrar selecionado (milis, padr\u00e3o %1) ConfigView.section.connection.advanced.write_select_min=Gravar a espera m\u00ednima selecionada (milis, padr\u00e3o %1) DetailedListView.title=Lista Detalhada ConfigView.section.connection.network.max.outstanding.connect.attempts=M\u00e1x de conex\u00f5es de longo curso destacadas plugins.init.force_enabled=O Vuze detectou que o plugin "%1" foi desativado - ele foi reativado para permitir que o Vuze trabalhe apropriadamente. ConfigView.section.connection.prefer.udp=Preferir conex\u00f5es UDP subscript.add.title=Instalar a Subscri\u00e7\u00e3o? subscript.add.desc=Voc\u00ea tem certeza que voc\u00ea quer instalar a subscri\u00e7\u00e3o '%1'? subscript.add.dup.title=Duplicar a Subscri\u00e7\u00e3o subscript.add.dup.desc=A subscri\u00e7\u00e3o '%1' j\u00e1 est\u00e1 instalada. subscript.add.upgrade.title=Atualizar a Subscri\u00e7\u00e3o? subscript.add.upgrade.desc=Voc\u00ea tem certeza que voc\u00ea quer atualizar a subscri\u00e7\u00e3o '%1'? subscript.add.upgradeto.desc=A vers\u00e3o %1 da subscri\u00e7\u00e3o '%2' est\u00e1 dispon\u00edvel.\nVoc\u00ea quer atualizar? azsubs.contextmenu.addassoc=Adicionar a associa\u00e7\u00e3o de subscri\u00e7\u00e3o azsubs.contextmenu.lookupassoc=Procurar as associa\u00e7\u00f5es das subscri\u00e7\u00f5es iconBar.start=Iniciar iconBar.stop=Parar iconBar.remove=Apagar iconBar.up=Pra cima iconBar.down=Pra baixo iconBar.run=Executar iconBar.editcolumns=Configura\u00e7\u00e3o da Coluna iconBar.top=Mover pro topo iconBar.bottom=Mover pro fundo iconBar.queue=Iniciar iconBar.open=Adicionar Torrent iconBar.share=Compartilhar iconBar.share.tooltip=Compartilhar Conte\u00fado iconBar.details=Detalhes iconBar.comment=Coment\u00e1rio iconBar.play=Tocar iconBar.queue.tooltip=Enfileirar v3.MainWindow.menu.view.sidebar=Barra Lateral v3.MainWindow.menu.view.actionbar=Barra da A\u00e7\u00e3o v3.MainWindow.menu.view.toolbars=Barras de Ferramentas ump.install=Atualiza\u00e7\u00e3o R\u00e1pida em Progresso:\nInstalando um pequeno add-on de playback requerido para este v\u00eddeo. subscriptions.listwindow.title=Descobridor de Subscri\u00e7\u00f5es subscriptions.listwindow.autochecktext=O Vuze pode achar subscri\u00e7\u00f5es relacionadas ao conte\u00fado na sua biblioteca. Voc\u00ea quer ativar esta fun\u00e7\u00e3o? subscriptions.listwindow.loadingtext=Procurando subscri\u00e7\u00f5es relacionadas com %1 subscriptions.listwindow.failed=Nenhuma subscri\u00e7\u00e3o Achada subscriptions.listwindow.popularity=Popularidade subscriptions.listwindow.popularity.unknown=Desconhecido subscriptions.listwindow.name=Nome subscriptions.listwindow.subscribe=Subscrever TableColumn.header.azsubs.ui.column.subs=Subscrever subscriptions.listwindow.popularity.reading=Lendo... PluginDeprecation.log.start=Esta janela cont\u00e9m informa\u00e7\u00e3o sobre plugins usando funcionalidades que ser\u00e3o removidas em futuras vers\u00f5es do Vuze.\nVoc\u00ea n\u00e3o precisa desinstalar os plugins, voc\u00ea deve apenas atualizar o plugin para a \u00faltima vers\u00e3o.\nSe voc\u00ea est\u00e1 rodando a \u00faltima vers\u00e3o, ent\u00e3o por favor copie o conte\u00fado desta janela e poste-o no f\u00f3rum localizado aqui:\n\t%1\n\n PluginDeprecation.log.details=---------\nIDENTIFICADOR: %1\nCONTE\u00daDO: %2\n\n*** COME\u00c7AR A RASTREAR ***\n%3*** FINALIZAR O RASTREAMENTO ***\n\n PluginDeprecation.view=Debug do Plugin PluginDeprecation.alert=Um plugin tentou usar uma funcionalidade a qual ser\u00e1 removida no futuro - por favor abra a visualiza\u00e7\u00e3o do Log do Debug do Plugin para mais informa\u00e7\u00e3o. TableColumn.header.Thumbnail=\u00cdcone TableColumn.header.Thumbnail.info=A imagem do thumbnail para o conte\u00fado do Vuze; para todos os outros conte\u00fados o sistema operacional est\u00e1 fornecendo estes \u00edcones. v3.MainWindow.menu.getting_started=&Sendo Iniciado MainWindow.menu.community=&Comunidade MainWindow.menu.help.faq=&Perguntas Feitas Frequentemente MainWindow.menu.community.wiki=Wiki da &Comunidade MainWindow.menu.community.forums=F\u00f3runs da Co&munidade MainWindow.menu.community.blog=Blog do &Vuze MainWindow.menu.help.support=&Ajuda e Suporte externalLogin.title=Login Requerido externalLogin.explanation=O modelo "%1" requer que voc\u00ea logue. Uma vez logado esta janela automaticamente fechar\u00e1. Se ela n\u00e3o fechar por favor clique em "feito". externalLogin.explanation.capture=Voc\u00ea precisa logar para criar este modelo. Uma vez que voc\u00ea est\u00e1, por favor clique em "Feito". Button.done=Feito GeneralView.torrent_created_on_and_by=%1 por %2 Button.continue=Continuar Button.preview=Pr\u00e9-visualizar Subscription.menu.forcecheck=Atualizar Agora Subscription.menu.clearall=Marcar Todos Os Resultados Como Lidos Subscription.menu.remove=Apagar sidebar.Library=Minha Biblioteca sidebar.LibraryDL=Baixando sidebar.LibraryCD=Completados authenticator.location=Local authenticator.details=Detalhes v3.MainWindow.menu.showActionBarText=Mostrar o Texto subscript.import.fail.title=Falhou em Importar subscript.import.fail.desc=Detalhes: %1 Subscription.menu.export=Exportar subscript.export.select.template.file=Salvar a Subscri\u00e7\u00e3o Button.remove=Remover Button.send=Enviar Button.back=Voltar sidebar.LibraryUnopened=N\u00e3o Observado TableColumn.header.unopened=Novo Unopened.bigView.header=Novo Subscription.menu.deleteall=Apagar Todos os Resultados Subscription.menu.reset=Resetar Ao Estado Inicial ConfigView.section.Subscriptions=Subscri\u00e7\u00f5es subscriptions.config.maxresults=N\u00famero m\u00e1ximo de resultados retidos por subscri\u00e7\u00e3o [0: ilimitados] v3.activity.button.readall=Marcar Todos os Lidos TableColumn.header.activityNew=Novo TableColumn.header.activityType=Tipo TableColumn.header.activityText=Mensagem TableColumn.header.activityDate=Data Adicionada TableColumn.header.activityActions=A\u00e7\u00f5es Subscription.menu.resetauth=Resetar os Detalhes da Autentica\u00e7\u00e3o Search.menu.engines=Modelos Wizard.Subscription.title=Subscrever Wizard.Subscription.optin.title=Ativar Subscri\u00e7\u00f5es #what you've watched? Discover more with a single click... Wizard.Subscription.subscribe.title=Subscri\u00e7\u00f5es Dispon\u00edveis Wizard.Subscription.create.title=Criar Nova Subscri\u00e7\u00e3o Button.search=Procurar Button.save=Salvar Button.add=Adicionar Button.createNewSubscription=Criar Nova Subscri\u00e7\u00e3o Button.availableSubscriptions=Subscri\u00e7\u00f5es Dispon\u00edveis Wizard.Subscription.optin.description=Com as Subscri\u00e7\u00f5es ativadas, o Vuze mostrar\u00e1 a voc\u00ea subscri\u00e7\u00f5es relacionadas ao conte\u00fado na sua Biblioteca e deixar\u00e1 voc\u00ea saber quando seu conte\u00fado subscrito est\u00e1 dispon\u00edvel para download.\n\nVoc\u00ea gostaria de ativar as Subscri\u00e7\u00f5es? Wizard.Subscription.create.search=Busca Wizard.Subscription.search.subtitle1=Digite uma busca para come\u00e7ar a criar sua subscri\u00e7\u00e3o : Wizard.Subscription.search.subtitle2=O que eu posso procurar? Wizard.Subscription.search.subtitle2.sub1=Filmes em HD, Shows da TV, Filmes, Trailers na Rede Vuze Wizard.Subscription.search.subtitle2.sub2=Torrents da Web Wizard.Subscription.search.subtitle3=Uma vez que a sua subscri\u00e7\u00e3o \u00e9 completada, voc\u00ea receber\u00e1 atualiza\u00e7\u00f5es ao vivo na sua barra lateral sempre que novos resultados est\u00e3o dispon\u00edveis para sua busca. Wizard.Subscription.rss.subtitle1=Digite ou cole a URL abaixo: Wizard.Subscription.rss.subtitle2=Muitos editores fornecem feeds RSS do conte\u00fado deles, Localize a URL no website do editor, copie e cole a URL no campo acima, ent\u00e3o clique em Salvar. Wizard.Subscription.rss.subtitle3=Uma vez salvo, voc\u00ea receber\u00e1 atualiza\u00e7\u00f5es ao vivo na sua barra lateral sempre que novos resultados est\u00e3o dispon\u00edveis via seu feed RSS. Wizard.Subscription.subscribe.library=Conte\u00fado na sua Biblioteca Wizard.Subscription.subscribe.subscriptions=Subscri\u00e7\u00f5es Relacionadas Wizard.Subscription.subscribe.library.empty=Sem subscri\u00e7\u00f5es dispon\u00edveis?\n \nProcure pelo bot\u00e3o para subscrever laranja brilhante na Rede HD do Vuze.\n \nLeia mais message.confirm.delete.title=Confirmar a Exclus\u00e3o message.confirm.delete.text=Voc\u00ea tem certeza que voc\u00ea quer apagar o '%1'? Subscription.menu.properties=Propriedades props.window.title=Propriedades para o '%1' subs.prop.is_auto=Auto-baixar os novos resultados subs.prop.last_scan=\u00daltima atualiza\u00e7\u00e3o bem sucedida subs.prop.last_result=\u00daltimo novo resultado achado subs.prop.last_error=\u00daltimo erro subs.prop.num_read=N\u00famero dos resultados de leitura subs.prop.num_unread=N\u00famero de resultados n\u00e3o lidos subs.prop.template=Modelo subs.prop.auth=Autentica\u00e7\u00e3o requerida externalLogin.auth_method_proxy=Usar m\u00e9todo de captura de cookies extendido. Se isto falhar em funcionar, desative a op\u00e7\u00e3o e tente de novo externalLogin.wait=Carregando a p\u00e1gina, por favor espere... TableColumn.menu.date_added.time=Mostrar/Esconder o Tempo sidebar.VuzeHDNetwork=Rede HD do Vuze subs.prop.next_scan=Pr\u00f3ximo scan em subs.prop.assoc=Associa\u00e7\u00f5es subs.prop.version=Vers\u00e3o subscriptions.column.new.info=Indica se h\u00e1 um ou mais resultados novos subscriptions.column.name=Subscri\u00e7\u00e3o subscriptions.column.nb-results=Total de Resultados subscriptions.column.nb-new-results=Novos Resultados subscriptions.column.last-checked=Verificado Pela \u00daltima Vez subscriptions.view.title=Subscri\u00e7\u00f5es subs.prop.is_public=P\u00fablico subs.prop.high_version=Maior vers\u00e3o encontrada Subscription.menu.upgrade=Ativar A Atualiza\u00e7\u00e3o Para A Vers\u00e3o Maior metasearch.template.version.bad=O modelo da busca '%1' n\u00e3o pode ser instalado at\u00e9 que voc\u00ea atualize o Vuze metasearch.addtemplate.failed.title=A Instala\u00e7\u00e3o Falhou metasearch.addtemplate.failed.desc=Falhou em instalar o modelo da busca: %1 subscription.version.bad=A subscri\u00e7\u00e3o '%1' n\u00e3o pode ser instalado at\u00e9 que voc\u00ea atualize o Vuze statusbar.feedback=Enviar Feedback statusbar.feedback.tooltip=Clique aqui para enviar feedback sidebar.Activity=Notifica\u00e7\u00f5es v3.activity.button.watchall=Marcar Todos os Observados subscriptions.view.help.1=Adicionar Subscri\u00e7\u00f5es onde quer que voc\u00ea veja subscriptions.view.help.2=Obtenha atualiza\u00e7\u00f5es ao vivo gr\u00e1tis sempre que novo conte\u00fado est\u00e1 dispon\u00edvel para baixar. Leia mais. sidebar.sash.tooltip=F7 para rapidamente esconder/mostrar a barra lateral sidebar.expand.tooltip=Expandir a Barra Lateral sidebar.dropdown.tooltip=Mostrar a barra lateral no formato do menu subscript.all.subscribed=Voc\u00ea est\u00e1 subscrito a este conte\u00fado subscript.some.subscribed=Voc\u00ea est\u00e1 subscrito a algumas das subscri\u00e7\u00f5es para este conte\u00fado.\nClique para ver as outras dispon\u00edveis subscript.none.subscribed=Clique para ver as subscri\u00e7\u00f5es dispon\u00edveis para este conte\u00fado v3.iconBar.up.tooltip=Mover pra Cima\nSegure o bot\u00e3o do mouse para mover pro topo v3.iconBar.down.tooltip=Mover pra Baixo\nSegure o bot\u00e3o do mouse para mover para o fundo TableColumn.header.azsubs.ui.column.subs_link=Associa\u00e7\u00e3o TableColumn.header.azsubs.ui.column.subs_link.info=Associados com as subscri\u00e7\u00f5es Button.deleteContent.fromLibrary=Remover da Biblioteca Button.deleteContent.fromComputer=Apagar do Computador v3.deleteContent.message=\nVoc\u00ea gostaria de apagar o '%1' do seu computador ou apenas remov\u00ea-lo da sua Biblioteca do Vuze? v3.MainWindow.menu.view.toolbartext=Texto da Barra de Ferramentas v3.MainWindow.menu.view.asSimpleList=Lista Simples v3.MainWindow.menu.view.asAdvancedList=Lista Avan\u00e7ada v3.MainWindow.menu.view.statusbar=Barra de Status Subscription.menu.dirtyall=Marcar Todos Os Resultados Como N\u00e3o Lidos configureWizard.file.message3=O Vuze baixar\u00e1 os arquivos em uma pasta espec\u00edfica, voc\u00ea pode escolher esta pasta aqui: v3.deleteContent.applyToAll=Aplicar a a\u00e7\u00e3o a todas as %1 entradas selecionadas ConfigView.label.seeding.firstPriority.ignoreIdleHours=Torrents que n\u00e3o fazem upload de nada v3.MainWindow.menu.contentnetworks=Redes &HD v3.MainWindow.menu.contentnetworks.about=Sobre as Redes HD Peers.column.as.info=Detalhes do AS do PEER (Sistema Aut\u00f4nomo) ConfigView.label.autoopen.downloadbars=Auto-abrir as Barras de Download quando ConfigView.label.autoopen=Auto-Abrir ConfigView.label.autoopen.detailstab=Auto-abrir a Aba de Detalhes quando ConfigView.label.systray=Tray do Sistema ConfigView.label.systray._mac=\u00cdcone da Barra de Status v3.MainWindow.menu.contentnetworks.manage=&Gerenciar as Redes HD azbuddy.ui.table.rem_cat=Gatos dentro azbuddy.ui.menu.cat=Categorias azbuddy.ui.menu.cat.share=Ativar as subscri\u00e7\u00f5es com amigo(s) azbuddy.ui.menu.cat.set=Inserir categorias azbuddy.ui.menu.cat.set_msg=Lista das categorias separadas por v\u00edrgula, ou 'Todas' azbuddy.ui.menu.cat_subs=Subscrever subs.prop.update_period=Per\u00eddo de atualiza\u00e7\u00f5es azbuddy.enable_cat_pub=Categorias p\u00fablicas nas quais todos os seus amigos podem subscrever (separadas por ',' ) v3.dialog.cnclose.title=%1 Fechado v3.dialog.cnclose.subtitle=Notifica\u00e7\u00e3o v3.dialog.cnclose.info1=Voc\u00ea fechou um Rede HD v3.dialog.cnclose.info2=Se voc\u00ea quiser reabrir esta Rede HD, voc\u00ea pode faz\u00ea-lo no menu "Redes HD" no topo da sua tela. v3.dialog.cnclose.noshow=N\u00e3o mostrar de novo v3.dialog.cnmanage.title=Gerenciar o Menu das Redes HD v3.dialog.cnmanage.intro=Voc\u00ea pode escolher da lista abaixo quais redes com conte\u00fado voc\u00ea deseja exibir no menu "Redes HD" azbuddy.ui.table.read_cat=Leitura do gato TableColumn.header.#.info=N\u00famero da Posi\u00e7\u00e3o/Ordenamento TableColumn.header.category.info=Nome da categoria a qual o torrent pertence TableColumn.header.DateCompleted.info=Data em que o download do torrent foi completado TableColumn.header.AzProduct.info=Rede de Conte\u00fado da qual o torrent se originou TableColumn.header.health.info=Qu\u00e3o saud\u00e1vel sua conex\u00e3o com a multid\u00e3o do torrent \u00e9 TableColumn.header.maxuploads.info=# m\u00e1ximo de peers aos quais faz upload simult\u00e2neamente TableColumn.header.name.info=Nome do torrent TableColumn.header.unopened.info=Bandeira para indicar se o torrent foi reproduzido (aberto) TableColumn.header.savepath.info=A pasta ou arquivo destino para os dados do torrent TableColumn.header.SeedingRank.info=Valor do ranking de qu\u00e3o terrivelmente o torrent precisa de seeding. Valor mais alto quer dizer maior necessidade. TableColumn.header.shareRatio.info=Quanto voc\u00ea fez de upload (compartilhou) em compara\u00e7\u00e3o a quanto voc\u00ea baixou. TableColumn.header.size.info=Tamanho do conte\u00fado do torrent no disco TableColumn.header.azsubs.ui.column.subs.info=Bot\u00e3o que permite a voc\u00ea subscrever ao feed contendo os torrents relacionados TableColumn.header.upspeed.info=Velocidade de upload atual TableColumn.header.downspeed.info=Velocidade de download atual TableColumn.header.up.info=Quantia de dados atuais enviada para outros usu\u00e1rios TableColumn.header.down.info=Quantia de dados atuais recebida dos outros usu\u00e1rios TableColumn.header.ProgressETA.info=Combina as colunas de Status, Completamento, TEC e Velocidade de Download em uma coluna multi-alinhada. TableColumn.header.eta.info=Tempo estimado antes que seja feito o download do torrent Pieces.column.#.info=N\u00famero de Peda\u00e7os Peers.column.%.info=Porcentagem do torrent que o peer baixou at\u00e9 agora TableColumn.header.download.info=Quantia de dados recebida do peer TableColumn.header.upload.info=Quantia de dados que n\u00f3s enviamos para o epeer TableColumn.header.downloadspeed.info=Taxa da qual n\u00f3s estamos recebendo do peer TableColumn.header.uploadspeed.info=Taxa na qual n\u00f3s estamos enviando dados para o peer TableColumn.header.lan.info=Bandeira indicando se o peer est\u00e1 na sua LAN TableColumn.header.downloadspeedoverall.info=Taxa de download estimada do peer Peers.column.pieces.info=Barra gr\u00e1fica representando quais peda\u00e7os o peer baixou TableColumn.header.TableColumnNameInfo=Nome e Descri\u00e7\u00e3o da Coluna TableColumn.header.TableColumnSample=Amostra TableColumn.header.TableColumnInfo=Descri\u00e7\u00e3o da Coluna TableColumn.header.TableColumnChosenColumn=Escolher a Coluna subs.prop.is_auto_ok=Auto-download permitido ColumnSetup.title=Configura\u00e7\u00e3o das Colunas para '%1' ColumnSetup.explain=Explorar as colunas dispon\u00edveis a esquerda e adicion\u00e1-las a lista de colunas vis\u00edveis a direita. Expandir ou retrair a lista de colunas dispon\u00edveis usando a se\u00e7\u00e3o dos Filtros no parte de baixo a esquerda. Arrastar e Soltar e os atalhos do teclado tamb\u00e9m s\u00e3o suportados. ColumnSetup.chosencolumns=Colunas Escolhidas ColumnSetup.proficiency=Profici\u00eancia: ColumnSetup.categories=Categorias: ColumnSetup.filters=Filtros ColumnSetup.availcolumns=Dispon\u00edveis %1 colunas ColumnSetup.availcolumns.filteredby=Dispon\u00edveis %1 colunas filtradas por %2 MainWindow.menu.help.donate=&Fa\u00e7a uma Doa\u00e7\u00e3o !!! azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_lt_LT.properties0000644000175000017500000047010011301156004026107 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torrent fail\u0105... MainWindow.menu.file.open.torrent.keybinding=Meta+T Main.parameter.usage=Naudojimas: java org.gudy.azureus2.cl.Main [parametrai] "failas.torrent" "i\u0161saugojimo kelias" Main.parameter.maxUploads=Did\u017eiausias vienalaiki\u0173 i\u0161siuntim\u0173 kiekis Main.parameter.maxSpeed=Did\u017eiausias i\u0161siuntimo greitis baitais/sek MainWindow.menu.file=&Failas MainWindow.menu.file.open=&Atidaryti MainWindow.menu.file.create=&Naujas Torrentas... MainWindow.menu.file.create.fromfile=I\u0161 &Failo MainWindow.menu.file.create.fromdir=I\u0161 &Katalogo MainWindow.menu.file.export=&Eksportuoti Torrent\u0105 \u012f XML... MainWindow.menu.file.import=&Importuoti Torrent\u0105 i\u0161 XML... MainWindow.menu.file.closetab=U\u017edaryti &kortel\u0119 MainWindow.menu.file.closewindow=U\u017edaryti &lang\u0105 MainWindow.menu.file.exit=&Baigti MainWindow.dialog.choose.file=I\u0161rinkite Torrent fail\u0105 MainWindow.menu.file.folder=&Aplank\u0105... MainWindow.menu.file.folder.keybinding=Meta+Shift+A MainWindow.dialog.choose.folder=I\u0161rinkite katalog\u0105 su Torrent failais MainWindow.menu.view=&Rodyti MainWindow.menu.view.show=Rodyti MainWindow.menu.view.mytorrents=&Mano Torrentai MainWindow.menu.view.open_global_transfer_bar=Siuntim\u0173 juosta MainWindow.menu.view.configuration=&Nustatymai... MainWindow.menu.view.console=&Konsol\u0117 MainWindow.menu.closealldetails=U\u017edaryti &vis\u0105 Torrent\u0173 informacij\u0105 MainWindow.menu.closealldownloadbars=U\u017edaryti visas Atsiuntimo &juostas MainWindow.menu.language=&Kalba ConfigView.section.language=Kalba MainWindow.menu.window=&Langas MainWindow.menu.window.minimize=&Suskleisti MainWindow.menu.window.zoom=&Pritraukti MainWindow.menu.window.alltofront=I\u0161kviesti visus \u012f p&riek\u012f MainWindow.menu.help=&Pagalba MainWindow.menu.help.about=Apie Vuze MainWindow.menu.torrent=Torrentas MainWindow.about.title=Apie MainWindow.about.section.developers=K\u016br\u0117jai MainWindow.about.section.translators=Vert\u0117jai MainWindow.about.section.system=Sistema MainWindow.about.section.internet=Internete MainWindow.about.internet.homepage=Vuze pagrindinis tinklalapis MainWindow.about.internet.sourceforge=Sourceforge projekto tinklalapis MainWindow.about.internet.sourceforgedownloads=Sourceforge atsiuntimai MainWindow.about.internet.bugreports=Rikt\u0173 raportavimas MainWindow.about.internet.forumdiscussion=Forumai MainWindow.about.internet.wiki=Vuze Wiki DUK MainWindow.dialog.choose.savepath=I\u0161rinkite i\u0161saugojimo keli\u0105 MainWindow.dialog.choose.savepath_forallfiles=I\u0161rinkite i\u0161saugojimo keli\u0105 VISIEMS failams MainWindow.status.latestversion=Naujausias MainWindow.status.latestversion.clickupdate=Spustel\u0117kite, kad atnaujintum\u0117te MainWindow.status.unknown=ne\u017einoma MainWindow.status.checking=tikrinama MyTorrentsView.mytorrents=Mano Torrentai TableColumn.header.name=Pavadinimas TableColumn.header.size=Dydis TableColumn.header.done=Baigta TableColumn.header.done.info=Dabartin\u0117s u\u017eduoties baigtumas TableColumn.header.status=B\u016bsena TableColumn.header.status.info=Kas vykdoma su Torrentu TableColumn.header.seeds=Skleid\u0117jai TableColumn.header.seeds.info=# prisijungusi\u0173 (# i\u0161 viso) TableColumn.header.peers=Siunt\u0117jai TableColumn.header.peers.info=# prisijungusi\u0173 (# i\u0161 viso) TableColumn.header.downspeed=Atsiunt. greitis TableColumn.header.upspeed=I\u0161siunt. greitis TableColumn.header.eta=NBL TableColumn.header.tracker=Trackerio b\u016bsena TableColumn.header.tracker.info=Trackerio b\u016bsena TableColumn.header.trackernextaccess=Kitas Trackerio tikrinimas TableColumn.header.trackernextaccess.info=Kada kit\u0105 kart\u0105 bus tikrinamas Trackeris TableColumn.header.priority=Prioritetas TableColumn.header.priority.info=Parodo, kiek i\u0161siuntimo pralaidumo skirta Torrentui TableColumn.header.seeds.fullcopycalc=tariama, kad yra %2 piln\u0173 kopij\u0173 %1 Siunt\u0117jams MyTorrentsView.menu.showdetails=Rodyti &Informacij\u0105 MyTorrentsView.menu.showdownloadbar=Rodyti siuntimo &juost\u0105 MyTorrentsView.menu.open=&Atidaryti fail\u0105 MyTorrentsView.menu.setpriority=Nustatyti &prioritet\u0105 MyTorrentsView.menu.setpriority.high=&Auk\u0161tas MyTorrentsView.menu.setpriority.low=\u017d&emas MyTorrentsView.menu.start=&Prad\u0117ti MyTorrentsView.menu.stop=&Stabdyti MyTorrentsView.menu.remove=&\u0160alinti MyTorrentsView.menu.changeTracker=&Prid\u0117ti Trackerio URL TrayWindow.menu.exit=I\u0161eiti TrayWindow.menu.show=&Rodyti Vuze SystemTray.menu.exit=&I\u0161eiti SystemTray.menu.closealldownloadbars=U\u017edaryti &VISAS siuntimo juostas SystemTray.menu.open_global_transfer_bar=Atidaryti siuntim\u0173 juost\u0105 SystemTray.menu.show=&Rodyti Vuze PeersView.ip.info=Siunt\u0117jo IP PeersView.port=Prievadas PeersView.port.info=Naudojamas prievadas PeersView.T=S PeersView.T.info=V (vietinis): j\u016bs inicijavote susijungim\u0105, N (nutol\u0119s): siunt\u0117jas inicijavo susijungim\u0105. PeersView.T.L.tooltip=J\u016bs inicijavote susijungim\u0105 PeersView.T.R.tooltip=Siunt\u0117jas inicijavo susijungim\u0105 PeersView.I1=S (susidom\u0117j\u0119 Siunt\u0117ju) PeersView.I1.info=Ar esate susidom\u0117j\u0119 Siunt\u0117jo turimais duomenimis? PeersView.C1=S (slopinamas Siunt\u0117jo) PeersView.C1.info=Ar Siunt\u0117jas stabdo atsiuntim\u0105 i\u0161 J\u016bs\u0173 PeersView.pieces=Dalys PeersView.downloadspeed=Ats. greitis PeersView.download=Atsi\u0173sta PeersView.I2=\u012e (\u012fdomus Siunt\u0117jui) PeersView.I2.info=Ar Siunt\u0117jas susidom\u0117j\u0119s J\u016bs\u0173 turimais duomenimis? PeersView.C2=S (slopinamas Siunt\u0117jas) PeersView.C2.info=Ar stabdote Siunt\u0117jo atsiuntim\u0105 PeersView.uploadspeed=I\u0161s. greitis PeersView.uploadspeed.info=I\u0161siuntimo greitis Siunt\u0117jui PeersView.upload=I\u0161si\u0173sta PeersView.upload.info=I\u0161 viso Siunt\u0117jui i\u0161si\u0173sta. PeersView.statup=Apsk. ats. PeersView.statup.info=Apytikris Siunt\u0117jo i\u0161siuntimo greitis PeersView.S=A PeersView.S.info=Atkirstas: Siunt\u0117jas gali b\u016bti "atkirstas" rankiniu b\u016bdu arba automati\u0161kai (nes siun\u010dia duomenis nepakankamu grei\u010diu) PeersView.downloadspeedoverall=Suminis atsiuntimo greitis PeersView.optunchoke=Opt. atslopinimas PeersView.client=Klientas PeersView.client.info=Siunt\u0117jo naudojamas BT klientas PeersView.menu.snubbed=&Atkirstas PeersView.title.short=Siunt\u0117jai PeersView.title.full=Siunt\u0117jai ConfigView.section.files=Failai ConfigView.label.usefastresume=Naudoti greito prat\u0119simo re\u017eim\u0105 ConfigView.label.incrementalfile=\u012ejungti did\u0117jan\u010di\u0173 fail\u0173 k\u016brim\u0105 [B\u016btinas FAT32 sistemai Linuxe] ConfigView.label.defaultsavepath=I\u0161saugoti \u012f numatyt\u0105 duomen\u0173 katalog\u0105 ConfigView.button.browse=&Parinkti... ConfigView.dialog.choosedefaultsavepath=Pra\u0161ome pasirinkti numatyt\u0105 saugojimo katalog\u0105 ConfigView.section.server=Ry\u0161ys ConfigView.section.global=Pagrindinis ConfigView.label.disconnetseed=Atjungti Skleid\u0117jus, kai skleid\u017eiama ConfigView.label.switchpriority=Automati\u0161kai persijungti \u012f \u017eem\u0105 prioritet\u0105, kai skleid\u017eiama ConfigView.label.maxdownloads=Daugiausia vienalaiki\u0173 atsiuntim\u0173 [0: neribojama]\n - Negali b\u016bti didesnis u\u017e 'Did\u017eiausi\u0105 aktyvi\u0173 Torrent\u0173 skai\u010di\u0173' ConfigView.label.maxdownloads.tooltip=J\u016bs visada gal\u0117site aktyviai si\u0173sti tiek, kiek \u010dia nurod\u0117te, su viena i\u0161imtimi.\nBaigtas Torrentas atitinkantis Pirmo prioriteto taisykl\u0119 gali perimti atsiuntimo lizd\u0105, jei neabejotinai to reikia. ConfigView.label.maxactivetorrents=Did\u017eiausias aktyvi\u0173 Torrent\u0173 skai\u010dius [0: neribojama]\n - Nauji Torrentai nestartuos, jei atsiun\u010diate/i\u0161siun\u010diate daugiau nei ConfigView.label.priorityExtensions=Automati\u0161kai suteikti prioritet\u0105 failams\n (pvz., .txt;.nfo;.jpg) ConfigView.section.transfer=Siuntimas ConfigView.label.maxuploads=Did\u017e. i\u0161siuntimo lizd\u0173 skai\u010dius Torrentui ConfigView.label.maxuploadspeed=KB/s did\u017e. globalus i\u0161siuntimo greitis [0: neribojama] ConfigView.label.saveresumeinterval=Atnaujinti prat\u0119simo duomenis kas ConfigView.unlimited=Neribojamas ConfigView.section.display=Rodymas ConfigView.label.opendetails=Automati\u0161kai atidaryti informacijos kortel\u0119 ConfigView.label.openbar=Automati\u0161kai atidaryti siuntim\u0173 juost\u0105 ConfigView.label.closetotray='U\u017edaryti' suskleid\u017eia \u012f sistemin\u0119 juostel\u0119 ConfigView.label.minimizetotray='Sutraukti' suskleid\u017eia \u012f sistemin\u0119 juostel\u0119 ConfigView.section.general=Pagrindinis ConfigView.section.start=Paleidimas ConfigView.label.showsplash=Rodyti paveiksliuk\u0105 paleid\u017eant ConfigView.label.autoupdate=Atidaryti atnaujinimo dialog\u0105, kai pasirodo nauja versija ConfigView.label.openconsole=Paleidus atidaryti konsol\u0119 ConfigView.label.openconfig=Paleidus atidaryti nustatymus ConfigView.label.startminimized=Paleisti suskleist\u0105 ConfigView.label.ircwiki=Pra\u0161ome skaityti http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Serveris ConfigView.label.ircchannel=Kanalas ConfigView.label.irclogin=Slapyvardis ConfigView.group.irctitle=IRC nustatymai ConfigView.boolean.ircsendinfo=Leisti si\u0173sti J\u016bs\u0173 nustatymus (anonimi\u0161kai)\n kanalo operatoriams, kad pad\u0117tum\u0117te jiems pad\u0117ti Jums ConfigView.boolean.irclog=\u012ejungti kanalo aktyvumo registravim\u0105 (\u012f IRC_log.htm) ConfigView.section.security=Saugumas ConfigView.label.password=Apsaugoti Vuze slapta\u017eod\u017eiu\n - Bus paklausta paleid\u017eiant ir i\u0161skleid\u017eiant lang\u0105. ConfigView.label.passwordconfirm=Slapta\u017eodis (patvirtinkite) ConfigView.label.passwordmatch=Slapta\u017eodis aktyvuotas: ConfigView.label.passwordmatchnone=Ne ConfigView.label.passwordmatchno=Ne / Slapta\u017eod\u017eiai neatitinka ConfigView.label.passwordmatchyes=Taip ConfigView.button.save=I\u0161saugoti ConfigView.title.short=Nustatymai ConfigView.title.full=Nustatymai ConsoleView.title.short=Konsol\u0117 ConsoleView.title.full=Konsol\u0117 FileItem.write=ra\u0161ymas FileItem.read=skaitymas FileItem.normal=normalus FileItem.high=auk\u0161tas FileItem.donotdownload=Nesi\u0173sti FilesView.name=Vardas FilesView.size=Dydis FilesView.done=Baigta FilesView.firstpiece=Pirmos dalies nr. FilesView.numberofpieces=Dali\u0173 skai\u010dius FilesView.pieces=Dalys FilesView.mode=Re\u017eimas FilesView.priority=Prioritetas FilesView.menu.open=&Atidaryti FilesView.menu.setpriority=Nustatyti &prioritet\u0105 FilesView.menu.setpriority.high=&Auk\u0161tas FilesView.menu.setpriority.normal=&Normalus FilesView.menu.setpriority.skipped=Ne&si\u0173sti FilesView.title.short=Failai FilesView.title.full=Failai GeneralView.section.downloaded=Atsi\u0173sta GeneralView.label.status.file=Failo b\u016bsena GeneralView.label.status.pieces=Dali\u0173 b\u016bsena GeneralView.section.availability=Pasiekiamumas GeneralView.label.status.pieces_available=Dali\u0173 b\u016bsena GeneralView.section.transfer=Siuntimas GeneralView.section.info=Informacija GeneralView.title.short=Bendras GeneralView.title.full=Bendras GeneralView.label.timeelapsed=Prab\u0117go laiko: GeneralView.label.remaining=Liko: GeneralView.label.downloaded=Atsi\u0173sta: GeneralView.label.downloadspeed=Atsiuntimo greitis: GeneralView.label.maxuploads=I\u0161siuntim\u0173 skai\u010dius: GeneralView.label.maxuploads.tooltip=Did\u017eiausias skai\u010dius siunt\u0117j\u0173, kurie bus atslopinti bet kuriuo laiko momentu. GeneralView.label.uploaded=I\u0161si\u0173sta: GeneralView.label.uploadspeed=I\u0161siuntimo greitis: GeneralView.label.seeds=Skleid\u0117jai: GeneralView.label.peers=Siunt\u0117jai: GeneralView.label.totalspeed=Grup\u0117s greitis: GeneralView.label.totalspeed.tooltip=Suminis (ir vidutinis) greitis vis\u0173 klient\u0173, prie kuri\u0173 esate prisijung\u0119. GeneralView.label.averagespeed=vidutinis GeneralView.label.filename=Failo pavadinimas: GeneralView.label.totalsize=Visas dydis: GeneralView.label.savein=Saugoma \u012f: GeneralView.label.hash=Raktas: GeneralView.label.numberofpieces=Dali\u0173 skai\u010dius: GeneralView.label.size=Dydis: GeneralView.label.tracker=Trackerio b\u016bsena: GeneralView.label.updatein=Atnaujinama po: GeneralView.label.trackerurl=Trackerio URL: GeneralView.label.trackerurlupdate=Atnaujinti Tracker\u012f GeneralView.label.comment=Komentaras: GeneralView.label.user_comment=Naudotojo komentaras: ManagerItem.waiting=Laukiama ManagerItem.allocating=I\u0161skiriama ManagerItem.checking=Tikrinama ManagerItem.ready=Laukiama, kol Torrentas(ai) pateks \u012f eil\u0119 ManagerItem.downloading=Siun\u010diama ManagerItem.seeding=Skleid\u017eiama ManagerItem.stopped=Sustabdyta ManagerItem.error=Klaida ManagerItem.high=auk\u0161tas ManagerItem.low=\u017eemas MinimizedWindow.name=Pavadinimas: MinimizedWindow.all_transfers=Vuze siuntimai PiecesView.#=Nr. PiecesView.size=Dydis PiecesView.numberofblocks=Blok\u0173 skai\u010dius PiecesView.blocks=Blokai PiecesView.completed=Baigta PiecesView.availability=Pasiekiamumas PiecesView.reservedby=Rezervuota PiecesView.writers=Prie bloko prisideda PiecesView.title.short=Dalys PiecesView.title.full=Dalys SystemTray.tooltip.seeding=%1 skleid\u017eiama, SystemTray.tooltip.downloading=%1 atsiun\u010diama, DownloadManager.error.filenotfound=Failas nerastas DownloadManager.error.fileempty=Torrento failas tu\u0161\u010dias DownloadManager.error.filetoobig=Torrento failas per didelis DownloadManager.error.filewithouttorrentinfo=Faile nerasta Torrento informacija DownloadManager.error.unsupportedencoding=Nepalaikomas kodavimas DownloadManager.error.ioerror=\u012e/I klaida DownloadManager.error.sha1=Ne\u017einomo algoritmo (SHA1) klaida PeerManager.status.offline=Susijungimo klaida PeerManager.status.ok=Gerai PeerManager.status.checking=Tikrinama PeerManager.status.finished=Baigta PeerManager.status.finishedin=Baigta per MainWindow.upgrade.assistant=Atnaujinimo asistentas MainWindow.upgrade.newerversion=Yra nauja Vuze versija parsisiuntimui MainWindow.upgrade.explanation=\u0160is asistentas atsi\u0173s nauj\u0105 versij\u0105 \u012f Vuze aplank\u0105 ir perkraus program\u0105 MainWindow.upgrade.explanation.manual=J\u016bs galite atnaujinti patys u\u017edarydami Vuze parsi\u0173sdami nauj\u0105 versij\u0105 ir perkraudami program\u0105 MainWindow.upgrade.step1=Pirmas \u017eingsnis: Parsi\u0173sti nauj\u0105 versij\u0105 MainWindow.upgrade.step2=Antras \u017eingsnis: U\u017edaryti \u0161i\u0105 versij\u0105 ir perkraut\u012f nauj\u0105 Vuze versij\u0105 MainWindow.upgrade.hint1=Patarimas:\tNuspaudus 'U\u017ebaigti' viskas padaroma automati\u0161kai MainWindow.upgrade.hint2=Patarimas:\tJei norite u\u017edaryti Vuze v\u0117liau - spauskite 'Atsisakyti' ir\n\tpervardinkite Azureus2-new.jar \u012f Azureus2.jar MainWindow.upgrade.error.downloading.hint=Klaida:\tNe\u012fmanoma atsi\u0173sti naujos versijos, pra\u0161ome atnaujinti rankiniu b\u016bdu MainWindow.upgrade.section.info=Pasirod\u0117 nauja versija MainWindow.upgrade.section.manual=Rankinis atnaujinimas MainWindow.upgrade.section.automatic=Automatinis atnaujinimas MainWindow.upgrade.tooltip.progressbar=Siuntimo progresas rodomas \u010dia Button.next=Kitas Button.finish=Baigti Button.cancel=Atsisakyti LocaleUtil.title=Pasirinkite kodavim\u0105 LocaleUtil.section.chooseencoding=Pasirinkite failo pavadinimo kodavim\u0105 LocaleUtil.label.chooseencoding=Pra\u0161ome pasirinkti geriausiai tinkant\u012f kodavim\u0105 LocaleUtil.label.hint.doubleclick=Patarimas: dvigubas paspaudimas ant eilut\u0117s parenka kodavim\u0105 ir u\u017edaro dialog\u0105 LocaleUtil.label.checkbox.rememberdecision=Prisiminti sprendim\u0105 likusiems failams LocaleUtil.column.encoding=Kodavimas IrcClient.copyright=Naudojama PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Jungiamasi prie IrcClient.connected=Prisijungta prie IrcClient.joining=Jungiamasi IrcClient.channel=Kanalas IrcClient.joined=prisijungta IrcClient.error=Klaida IrcClient.hasjoined=prisijung\u0117 IrcClient.haskicked=i\u0161mestas IrcClient.hasleft=i\u0161\u0117jo IrcClient.nowknown=\u017einomas kaip IrcClient.topicforchannel=Kanalo tema IrcClient.disconnected=Atsijungta nuo IrcClient.noNick=Nenurodytas slapyvardis. Pra\u0161om eiti \u012f 'Nustatym\u0173' lang\u0105 IrcView.actionnotsupported=\u0160is veiksmas nepalaikomas IrcView.clientsconnected=naudotojai IrcView.privateto=\u012e IrcView.privatefrom=I\u0161 IrcView.noticefrom=\u012esp\u0117jimas: IrcView.errormsg=Klaidinga sintaks\u0117 /msg: /msg user text IrcView.help=Galimos komandos yra:\n . /help - parodo \u0161i\u0105 \u017einut\u0119\n . /nick | /name - pakei\u010dia J\u016bs\u0173 slapyvard\u012f\n . /me action - siun\u010dia veiksm\u0105\n . /msg nick message - siun\u010dia priva\u010di\u0105 \u017einut\u0119 naudotojui \n . /r message - atsako \u012f paskutin\u0119 priva\u010di\u0105 \u017einut\u0119\n . /join #kanalasB (nespauskite, tai pavyzdys) - pakei\u010dia dabartin\u012f kanal\u0105 \u012f kanal\u0105 kanalasB PasswordWindow.title=Vuze u\u017erakintas PasswordWindow.passwordprotected=Vuze yra apsaugotas slapta\u017eod\u017eiu.\nKad pamatytum\u0117te Vuze lang\u0105, \u012fveskite slapta\u017eod\u012f \u010dia: Button.ok=Gerai TrackerChangerWindow.title=Prid\u0117ti Tracker\u012f TrackerChangerWindow.newtracker=\u012eveskite naujo Trackerio url PeersView.discarded=Atmesta PeersView.discarded.info=Duomenys, kurie kaip nors buvo gauti, bet nereikalingi, tod\u0117l atmesti. discarded=atmesta MyTorrentsView.#=Nr. MyTorrentsView.menu.move=&Slinkti MyTorrentsView.menu.moveUp=&Auk\u0161tyn MyTorrentsView.menu.moveDown=\u017de&myn GeneralView.label.hashfails=Klaidingi raktai: GeneralView.label.shareRatio=Dalinimosi santykis: ConfigView.section.downloadManagement=Atsiuntim\u0173 tvarkymas ConfigView.label.startRatioPeers=Prad\u0117ti skleisti, kai yra ma\u017eiau nei 1 Skleid\u0117jas kiekvienam ConfigView.text.neverStop=Niekada nestabdyti ConfigView.text.neverStart=Niekada nestartuoti ConfigView.text.peers=Siunt\u0117jai ConfigView.label.checkOncompletion=Pertikrinti dalis, kai atsiuntimas baigtas wizard.title=Sukurti Torrent\u0105 wizard.previous=< Atgal wizard.next=Kitas > wizard.finish=Baigti wizard.mode=Trackeris / Re\u017eimas wizard.tracker=Trackeris: wizard.invalidurl=\u0160is URL yra klaidingas wizard.singlefile=Failas wizard.singlefile.help=Sukurti Torrent\u0105 i\u0161 failo wizard.directory=Katalogas wizard.directory.help=Sukurti Torrent\u0105 i\u0161 katalogo wizard.choosefile=Pasirinkite fail\u0105 wizard.file=Failas: wizard.browse=Parinkti... wizard.choosedirectory=Pasirinkite katalog\u0105 wizard.invalidfile=Klaidingas failas! wizard.invaliddirectory=Klaidingas katalogas! wizard.torrentFile=Torrento failas wizard.choosetorrent=Pra\u0161ome pasirinkti Torrento fail\u0105 k\u016brimui wizard.information=Informacija wizard.notimplemented=Vis dar nerealizuota wizard.progresstitle=Kuriamas Torrento failas wizard.savingfile=I\u0161saugomas failas... wizard.filesaved=Failas i\u0161saugotas. wizard.close=U\u017edaryti Torrent.create.progress.piecelength=Dalies Ilgis: Torrent.create.progress.piececount=Dali\u0173 skai\u010dius: Torrent.create.progress.totalfilesize=Bendras fail\u0173 dydis: Torrent.create.progress.totalfilecount=Bendras fail\u0173 skai\u010dius: Torrent.create.progress.parsingfiles=Nagrin\u0117jami failai Torrent.create.progress.hashing=Koduojami failai MainWindow.upgrade.downloadingfrom=siun\u010diama i\u0161: MainWindow.menu.view.ipFilter=Ip &filtrai ConfigView.section.ipfilter=IP filtrai ConfigView.section.ipfilter.description=Apra\u0161ymas ConfigView.section.ipfilter.start=Pradinis IP ConfigView.section.ipfilter.end=Galinis IP ConfigView.section.ipfilter.add=Prid\u0117ti ConfigView.section.ipfilter.remove=\u0160alinti ConfigView.section.ipfilter.edit=Redaguoti ConfigView.section.ipfilter.save=I\u0161saugoti ConfigView.section.ipfilter.editFilter=Redaguoti filtr\u0105 ConfigView.section.ipfilter.enable=\u012ejungti PeersView.menu.close=&U\u017edaryti seedmore.title=Torrentas nepakankamai skleistas seedmore.shareratio=J\u016bs\u0173 dalinimosi santykis \u0161iam Torrentui yra seedmore.uploadmore=Tur\u0117ti dalinimosi santyk\u012f ma\u017eesn\u012f nei 100 procent\u0173 yra negerai BitTorrent tinklui.\nJ\u016bs tur\u0117tum\u0117te skleisti \u0161\u012f Torrent\u0105 truput\u012f ilgiau.\nAr tikrai norite t\u0119sti? ConfigView.label.showpopuponclose=Rodyti patvirtinimo lang\u0105, kai stabdomas skleidimas su dalinimosi santykiu ma\u017eesniu u\u017e 1 ConfigView.label.startNumSeeds=\nPrad\u0117ti skleisti, jei yra ma\u017eiau nei\n - Panaikina kitas taisykles ConfigView.label.seeds=Skleid\u0117jai ConfigView.section.seeding=Skleidimas MyTorrentsView.menu.removeand=\u0160alinti &ir MyTorrentsView.menu.removeand.deletetorrent=I\u0161trinti &Torrent fail\u0105 MyTorrentsView.menu.removeand.deletedata=I\u0161trinti &duomenis MyTorrentsView.menu.removeand.deleteboth=I\u0161trinti &visk\u0105 deletedata.title=\u012esp\u0117jimas deletedata.message1=J\u016bs tuoj i\u0161trinsite DUOMENIS i\u0161:\n MainWindow.menu.file.configure=Nustatym\u0173 &vedlys... configureWizard.title=Nustatym\u0173 vedlys configureWizard.welcome.title=Sveiki \u012fsijung\u0119 Vuze Nustatym\u0173 vedl\u012f configureWizard.welcome.message=\u0160is vedlys pad\u0117s Jums nustatyti Vuze bendriausiam naudojimui. J\u016bs galite nuodugniai nustatyti naudodami meniu \u012erankiai->Nustatymai. configureWizard.transfer.title=Siuntim\u0173 ir prisijungimo nustatymai configureWizard.transfer.hint=Patarimas: naudoti truput\u012f \u017eemesn\u012f, nei J\u016bs\u0173 linijos pralaidumas, yra geriausia. configureWizard.transfer.message=Pra\u0161ome pasirinkti prisijungimo b\u016bd\u0105. \u017dinokite - ma\u017eas i\u0161siuntimo greitis lemia ma\u017eus atsiuntimo grei\u010dius. Kadangi i\u0161siuntimo greitis skai\u010diuojamas kiekvienam Torrentui ATSKIRAI, bandymas tuo pa\u010diu metu si\u0173stis daug Torrent\u0173 taip pat lems ma\u017eus grei\u010dius. Rekomenduojame naudoti 5KB/s greit\u012f Torrentui kaip GRIE\u017dT\u0104 minimum\u0105. Kuo spar\u010diau J\u016bs i\u0161siun\u010diate duomenis, tuo spar\u010diau ir atsisiun\u010diate (\u017einoma atsi\u017evelgiant \u012f Torrento greit\u012f). configureWizard.transfer.connection=Linija configureWizard.transfer.connection.0=Priderintas configureWizard.transfer.connection.1=modemas configureWizard.transfer.connection.2=dsl/kabelinis xxx/128 kbps configureWizard.transfer.connection.3=dsl/kabelinis xxx/256 kbps configureWizard.transfer.connection.4=dsl/kabelinis xxx/384 kbps configureWizard.transfer.connection.5=dsl/kabelinis xxx/512 kbps configureWizard.transfer.connection.6=dsl/kabelinis xxx/768 kbps configureWizard.transfer.connection.7=dsl/kabelinis xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Did\u017e. i\u0161siuntimo greitis (KB/s) configureWizard.transfer.maxActiveTorrents=Daugiausia aktyvi\u0173 configureWizard.transfer.maxDownloads=Daugiausia atsiuntim\u0173 configureWizard.transfer.maxUploadsPerTorrent=Daugiausia i\u0161siuntim\u0173 Torrentui configureWizard.nat.title=NAT / Serverio prievadai configureWizard.nat.message=Norint naudotis visais Vuze privalumais rekomenduojama b\u016bti visi\u0161kai prieinamu i\u0161 Interneto. \u0160is \u012frankis leid\u017eia testuoti ir / arba keisti prievad\u0105, naudojam\u0105 \u012feinantiems Siunt\u0117j\u0173 susijungimams.\n\nPASTABA: \u0160is \u012frankis testuoja tik TCP susijungimus. Paskirstytai DB reikia UDP susijungim\u0173, J\u016bs b\u016bsite automati\u0161kai persp\u0117ti, jei bus pasteb\u0117ti ugniasien\u0117s blokavimai.\n\nPASTABA: 6880 TCP prievadas yra rezervuotas, taigi, negali b\u016bti naudojamas. configureWizard.nat.test=Testuoti configureWizard.nat.testing=Testuojamas prievadas configureWizard.nat.ok=Gerai! configureWizard.nat.ko=NAT klaida configureWizard.nat.unable=Testas nepavyko: nurodytas netinkamas prievadas arba klaida test\u0173 servise.\nKita programa galb\u016bt naudoj\u0105 \u0161\u012f prievad\u0105. configureWizard.file.title=Torrentai / Failai configureWizard.file.message1=Vuze i\u0161saugos atidarytus Torrentus \u012f nurodyt\u0105 aplank\u0105, kur\u012f J\u016bs galite pasirinkti \u010dia: configureWizard.file.path=Kelias configureWizard.file.browse=Parinkti configureWizard.file.message2=Vuze gali prat\u0119sti fail\u0173 siuntim\u0105 tu\u010dtuojau, prid\u0117damas papildom\u0173 duomen\u0173 \u012f .torrent failus. Naudodami \u0161i\u0105 savyb\u0119 J\u016bs taip pat prat\u0119site i\u0161 dalies atsi\u0173stas dalis. configureWizard.file.fastResume=\u012ejungti greit\u0105 prat\u0119sim\u0105 configureWizard.file.invalidPath=Klaidingas katalogas configureWizard.finish.title=Baigtas configureWizard.finish.message=Vuze nustatytas, S\u0117km\u0117s! wizard.close.confirmation=Patvirtinimas wizard.close.message=Ar norite, kad \u0161is vedlys b\u016bt\u0173 \u012fkeltas kit\u0105 kart\u0105 paleid\u017eiant Vuze exportTorrentWizard.title=Eksportuoti Torrent\u0105 \u012f XML exportTorrentWizard.torrentfile.title=\u012eveskite Torrento pasirinkim\u0105 exportTorrentWizard.torrentfile.message=Parinkite Torrent\u0105 eksportavimui exportTorrentWizard.torrentfile.path=Kelias exportTorrentWizard.torrentfile.browse=Parinkti exportTorrentWizard.torrentfile.invalidPath=Klaidingas Torrento failas exportTorrentWizard.exportfile.title=Eksportuojamo failo pasirinkimas exportTorrentWizard.exportfile.message=\u012eveskite xml failo pavadinim\u0105 eksportavimui exportTorrentWizard.exportfile.path=Kelias exportTorrentWizard.exportfile.browse=Parinkti exportTorrentWizard.exportfile.invalidPath=Klaidingas eksportavimo failas exportTorrentWizard.finish.title=Baigta exportTorrentWizard.finish.message=Eksportavimas s\u0117kmingai baigtas exportTorrentWizard.process.inputfilebad.title=Klaidingas Torrento failas exportTorrentWizard.process.inputfilebad.message=\u012evyko klaida kreipiantis \u012f \u012fvedimo fail\u0105: exportTorrentWizard.process.outputfileexists.title=Failas egzistuoja exportTorrentWizard.process.outputfileexists.message=I\u0161\u0117jimo failas egzistuoja - pakeisti? exportTorrentWizard.process.torrentfail.title=Nepavyko nuskaityti Torrento exportTorrentWizard.process.exportfail.title=Nepavyko eksportuoti Torrento exportTorrentWizard.process.unknownfail.title=Netik\u0117ta klaida importTorrentWizard.title=Importuoti Torrent\u0105 i\u0161 XML importTorrentWizard.torrentfile.title=\u012evedamo Torrento pasirinkimas importTorrentWizard.torrentfile.message=\u012eveskite Torrent\u0105 importavimui importTorrentWizard.torrentfile.path=Kelias importTorrentWizard.torrentfile.browse=Parinkti importTorrentWizard.torrentfile.invalidPath=Klaidingas Torrento failas importTorrentWizard.importfile.title=Importuojamo failo pasirinkimas importTorrentWizard.importfile.message=Pasirinkite importuojam\u0105 xml fail\u0105 importTorrentWizard.importfile.path=Kelias importTorrentWizard.importfile.browse=Parinkti importTorrentWizard.importfile.invalidPath=Klaidingas importavimo failas importTorrentWizard.finish.title=Baigta importTorrentWizard.finish.message=Importavimas s\u0117kmingai baigtas importTorrentWizard.process.inputfilebad.title=Klaidingas importavimo failas importTorrentWizard.process.inputfilebad.message=\u012evyko klaida kreipiantis \u012f \u012fvedimo fail\u0105: importTorrentWizard.process.outputfileexists.title=Failas egzistuoja importTorrentWizard.process.outputfileexists.message=I\u0161\u0117jimo failas egzistuoja - pakeisti? importTorrentWizard.process.torrentfail.title=Nepavyko \u012fra\u0161yti Torrento importTorrentWizard.process.importfail.title=Nepavyko importuoti Torrento importTorrentWizard.process.unknownfail.title=Netik\u0117ta klaida ConfigView.label.bindip=Susieti su vietiniu IP adresu ar s\u0105saja ConfigView.label.xfs.allocation=I\u0161skirti naujus failus naudojant metod\u0105 b\u016bding\u0105 XFS fail\u0173 sistemai ConfigView.label.xfs.allocation.tooltip=Pra\u0161ome \u012fsitikinti, kad /usr/sbin/xfs_io J\u016bs\u0173 sistemoje \u012fdiegtas teisingai. Daugelyje Linux distribucij\u0173, tai yra "xfsprogs" pakete. xfs.allocation.xfs_io.not.found=XFS failo alokacija nepavyko, nes /usr/sbin/xfs_io negali b\u016bti paleistas. \u012esitikinkite, kad tai J\u016bs\u0173 sistemoje \u012fdiegta teisingai. Klaida buvo: "%1". ConfigView.label.zeronewfiles=I\u0161skirti ir nulinti kuriamus failus ConfigView.label.zeronewfiles.tooltip=Suma\u017eina fragmentacij\u0105 ConfigView.section.stats=Statistika ConfigView.section.stats.enable=\u012ejungti ConfigView.section.stats.defaultsavepath=Statistikos saugojimo katalogas ConfigView.section.stats.choosedefaultsavepath=Pra\u0161om pasirinkti statistikos saugojimo katalog\u0105 ConfigView.section.stats.savefreq=Saugojimo da\u017enis ConfigView.section.stats.hours=val ConfigView.section.stats.seconds=sek ConfigView.section.stats.savefile=Statistikos failo pavadinimas ConfigView.section.stats.graph_update_dividers=Rodyti vertikali\u0105 linij\u0105 kas 60 sekund\u017ei\u0173 MyTorrentsView.menu.export=&Eksportuoti \u012f XML... MyTorrentsView.menu.host=&Tiekti... ManagerItem.finishing=Baigiama ConfigView.dialog.choosedefaulttorrentpath=Pra\u0161ome pasirinkti numatyt\u0105 Torrent\u0173 katalog\u0105 ConfigView.dialog.choosemovepath=Pra\u0161ome pasirinkti katalog\u0105, \u012f kur\u012f perkelti ConfigView.label.movecompleted=Perkelti baigtus failus (po atsiuntimo) ConfigView.label.moveremoved=Perkelti baigtus failus (kai \u0161alinama) ConfigView.label.savetorrents=I\u0161saugoti .torrent failus MainWindow.menu.view.mytracker=Mano &Trackeris MyTrackerView.title.full=Mano Trackeris MyTrackerView.name=Pavadinimas MyTrackerView.tracker=Trackeris MyTrackerView.status=B\u016bsena MyTrackerView.status.started=Veikiantis MyTrackerView.status.stopped=Sustabdytas MyTrackerView.peers=Siunt\u0117jai MyTrackerView.seeds=Skleid\u0117jai MyTrackerView.announces=Prane\u0161imai MyTrackerView.uploaded=I\u0161si\u0173sta MyTrackerView.downloaded=Atsi\u0173sti MyTrackerView.left=Liko ConfigView.section.style=S\u0105saja ConfigView.label.set_ui_transfer_speeds=Keisti parenkamus siuntimo grei\u010dius ConfigView.label.set_ui_transfer_speeds.description=Galite rankiniu b\u016bdu apibr\u0117\u017eti numatytus atsiuntimo ir i\u0161siuntimo grei\u010dius prieinamus per b\u016bsenos juost\u0105 sistemin\u0117je juostel\u0117je.\nReik\u0161m\u0117s turi b\u016bti atskirtos kableliais. ConfigView.label.set_ui_transfer_speeds.description.download=Nustatyti atsiuntimo grei\u010dius (KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Nustatyti i\u0161siuntimo grei\u010dius (KB/s) ConfigView.section.style.useCustomTabs=Naudoti u\u017edaromas korteles [reikia perkrauti] MainWindow.menu.view.plugins=&Intarpai fileDownloadWindow.saveTorrentIn=I\u0161saugoti Torrento fail\u0105 \u012f fileDownloadWindow.title=Vuze Torrent\u0173 atsiunt\u0117jas fileDownloadWindow.downloading=Siun\u010diama i\u0161: fileDownloadWindow.status=B\u016bsena: fileDownloadWindow.state_initializing=Ruo\u0161iamasi fileDownloadWindow.state_downloading=Siun\u010diama fileDownloadWindow.state_error=Klaida: MainWindow.menu.file.open.url=&Nuorod\u0105... MainWindow.menu.file.open.url.keybinding=Meta+U openUrl.title=Atverti nuorod\u0105 openUrl.url=Nuoroda: MyTorrentsView.menu.host.error.title=Nepavyko tiekti Torrento MyTorrentsView.menu.host.error.message=\u012evyko klaida tiekiant Torrent\u0105 ConfigView.section.tracker=Trackeris ConfigView.section.tracker.pollinterval=Trackerio klient\u0173 apklausos intervalas (sek.) ConfigView.section.tracker.publishenable=Skelbti Torrento informacij\u0105 \u012f "" ConfigView.section.tracker.ip=I\u0161orinis Trackerio IP adresas ConfigView.section.style.enableXPStyle=\u012ejungti XP stili\u0173 [reikia perkrauti] ConfigView.section.tracker.checkip=Automati\u0161kai rasti i\u0161orin\u012f IP adres\u0105... ipCheckerWizard.title=IP tikrinimo vedlys ipCheckerWizard.service=Tiek\u0117jas ipCheckerWizard.chooseService=Pra\u0161au pasirinkti IP tikrinimo tiek\u0117j\u0105 i\u0161 pateikt\u0173 tiek\u0117j\u0173 ipCheckerWizard.explanations=J\u016bs galite naudoti \u0161\u012f vedl\u012f, nor\u0117dami su\u017einoti, koks yra J\u016bs\u0173 i\u0161orinis IP adresas. Jei IP yra dinaminis, mes rekomenduojame susikurti paskyr\u0105 dinaminio DNS servise. Keletas toki\u0173 paslaug\u0173 tiek\u0117j\u0173 yra pateikta s\u0105ra\u0161e, naudokite pateikt\u0105 nuorod\u0105 paskyrai sukurti (kur tai palaikoma). Tada \u012f IP adreso laukel\u012f \u012fveskite savo dinamin\u012f adres\u0105 (pvz., manokomp.dyndns.org). Jums reik\u0117s programos, kuri gali automati\u0161kai atnaujinti J\u016bs\u0173 dinaminio DNS serviso paskyr\u0105 su nauju IP. Taip J\u016bs gal\u0117site tiekti Torrentus, net jei J\u016bs\u0173 IP kei\u010diasi. ipCheckerWizard.service.description=Apra\u0161ymas: ipCheckerWizard.service.url=Nuoroda: ipCheckerWizard.progresstitle=Tikrinamas IP ipCheckerWizard.checkComplete=Baigta, IP: ipCheckerWizard.checkFailed=Nepavyko, prie\u017eastis: wizard.tracker.local=Naudoti Vuze vidin\u012f Tracker\u012f wizard.tracker.external=Naudoti i\u0161orin\u012f Tracker\u012f wizard.tracker.howToLocal=\tEikite \u012f '\u012erankiai->Nustatymai->Trackeris' nor\u0117dami \u012fjungti wizard.announceUrl=Prane\u0161imo URL: IPChecker.external.service.discoveryvip.description=Discoveryvip - Tik IP adreso tikrinimas IPChecker.external.httpinvalidresponse=Klaidingas HTTP atsakymas IPChecker.external.loadingwebpage=\u012ekeliamas tinklalapis IPChecker.external.analysingresponse=Analizuojamas atsakymas IPChecker.external.addressextracted=Rastas IP adresas IPChecker.external.httploadfail=Nepavyko \u012fkelti puslapio IPChecker.external.timeout=Baig\u0117si laikas IPChecker.external.ipnotfound=IP adresas nerastas ConfigView.section.tracker.pollintervalmin=Ma\u017eiausias ConfigView.section.tracker.pollintervalmax=Did\u017eiausias ConfigView.section.tracker.pollintervalincby=Didinti ConfigView.section.tracker.pollintervalincper=Kas kiekvienus 'n' klient\u0173 splash.loadingImages=\u012ekeliami atvaizdai splash.initializeGui=Ruo\u0161iamas pagrindinis langas splash.openViews=Atidaromi langai splash.plugin=\u012ekeliamas intarpas: configureWizard.nat.tooManyPorts=Per daug prievad\u0173 testavimui (daugiausia 9) ConfigView.section.color=Spalv\u0173 schema MyTorrentsView.menu.publish=&Skelbti... MyTrackerView.status.published=Paskelbtas MyTrackerView.completed=Baigti MainWindow.menu.file.open.torrentnodefault=Torrent fail\u0105... (ne numatytasis i\u0161saugojimas) wizard.comment=Komentaras ConfigView.label.movetorrent=Perkelti .torrent ConfigView.label.movepartialdownloads=Perkelti, kai kai kurie failai pa\u017eym\u0117ti "Nesi\u0173sti" ConfigView.label.subdir_is_in_default=Kai svarstoma, ar atsiuntimas egzistuoja numatytame kataloge, taip pat svarstyti numatytus pakatalogius ConfigView.section.file.decoder.label=Numatytas Torrento kodavimas, kai yra pasirinkimas ConfigView.section.file.decoder.nodecoder=joks IPChecker.external.service.no-ip.description=Dinaminio ir statinio DNS serviso tiek\u0117jas\n(n\u0117ra laisvai prieinamos adreso tikrinimo paslaugos) ConfigView.section.tracker.publicenable=\u012ejungti i\u0161orinius Torrentus ConfigView.label.playdownloadspeech=Kalb\u0117ti, kai atsiuntimas baigtas ConfigView.label.playdownloadspeech.info=Kalbos servisas dabar geriausiai veikia angl\u0173 kalba # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Parodo kiekvienos dalies pasiekiam\u0173 kopij\u0173 skai\u010di\u0173.\n Jei skai\u010dius de\u0161in\u0117je yra ma\u017eesnis u\u017e 1, J\u016bs nematote visos failo kopijos (ir galite tur\u0117ti problem\u0173 u\u017ebaigdami atsiuntim\u0105). GeneralView.label.trackerurl.tooltip=Spustel\u0117kite, nor\u0117dami nukopijuoti prane\u0161imo nuorod\u0105 \u012f i\u0161karpin\u0119 GeneralView.label.trackerurlopen.tooltip=Spustel\u0117kite, nor\u0117dami atidaryti pagrindin\u012f Trackerio puslap\u012f # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Atnaujinti GS kas ConfigView.section.style.graphicsUpdate=Atnaujinti grafines juostas kiekvienus N GS atnaujinim\u0173 ConfigView.section.style.reOrderDelay=Rikiuoti lenteles kas N GS atnaujinim\u0173 [0: niekada] ConfigView.section.style.reOrderDelay.never=Niekada ConfigView.section.logging=Registravimas ConfigView.section.logging.enable=\u012ejungti registravim\u0105 \u012f fail\u0105 ConfigView.section.logging.logdir=Registracijos failo katalogas ConfigView.section.logging.choosedefaultsavepath=Pasirinkite i\u0161saugojimo katalog\u0105 GeneralView.label.updatein.querying=klausiama... configureWizard.nat.sharePort=Naudoti vien\u0105 bendr\u0105 prievad\u0105 visiems Torrentams ConfigView.section.logging.maxsize=Did\u017eiausias registracijos failo dydis ConfigView.section.tracker.passwordenableweb=\u012ejungti Trackerio tinklalapio slapta\u017eod\u012f ConfigView.section.tracker.passwordenabletorrent=\u012ejungti Torrent\u0173 slapta\u017eod\u012f ConfigView.section.tracker.username=Naudotojo vardas ConfigView.section.tracker.password=Slapta\u017eodis columnChooser.title=Pasirinkite stulpelius rodymui columnChooser.move=Vilkite eilutes tvarkai pakeisti columnChooser.apply=Vykdyti columnChooser.columnname=Stulpelio pavadinimas columnChooser.columndescription=Apra\u0161ymas TableColumn.header.shareRatio=Dalinimosi santykis MyTorrentsView.menu.editTableColumns=&Stulpeli\u0173 nustatymai wizard.operationfailed=Veiksmas nepavyko authenticator.title=Reikalingas atpa\u017einimas authenticator.realm=Sritis authenticator.tracker=Trackeris authenticator.user=Naudotojo vardas authenticator.password=Slapta\u017eodis ConfigView.label.allowSendVersion=Leisti Vuze anonimi\u0161kai si\u0173sti versijos numer\u012f ir atsitiktin\u012f id tikrinant ar n\u0117ra naujos versijos ConfigView.label.version.info.link=Apsilankykite \u010dia nor\u0117dami su\u017einoti kokie duomenys yra siun\u010diami \u012f versijos tikrinimo server\u012f wizard.hint.mode=Patarimas:\tNuvilkite fail\u0105 arba katalog\u0105 ant \u0161io vedlio\n\tnor\u0117dami pasirinkti fail\u0105 ar katalog\u0105 wizard.hint.file=Patarimas:\tJ\u016bs galite parinkti vien\u0105 fail\u0105, nuvilkdami j\u012f pele wizard.hint.directory=Patarimas:\tJ\u016bs galite parinkti vien\u0105 katalog\u0105, nuvilkdami j\u012f pele MainWindow.menu.help.checkupdate=&Ie\u0161koti programos atnaujinim\u0173 TableColumn.header.down=Atsi\u0173sta TableColumn.header.up=I\u0161si\u0173sta ConfigView.section.tracker.passwordenabletorrent.info=Reikalingas tinkamas BitTorrent klientas (pvz., Vuze ConfigView.section.style.confirmationOnExit=Rodyti patvirtinimo dialog\u0105 i\u0161jungiant MainWindow.dialog.exitconfirmation.title=I\u0161jungti Vuze MainWindow.dialog.exitconfirmation.text=Ar tikrai norite i\u0161jungti Vuze SystemTray.menu.stopalltransfers=Stabdyti visus siuntimus TrayWindow.menu.stopalldownloads=Stabdyti visus atsiuntimus ConfigView.section.tracker.sslport.info=I\u0161samesn\u0117s informacijos ie\u0161kokite DUK wizard.tracker.ssl=Naudoti SSL ConfigView.label.playdownloadfinished=Sugroti gars\u0105, kai atsiuntimas baigtas ConfigView.label.popupdownloadfinished=Parodyti persp\u0117jim\u0105, kai atsiuntimas baigtas ConfigView.label.popupfilefinished=Parodyti persp\u0117jim\u0105, kai failas baigtas TableColumn.header.pieces=Dalys TableColumn.header.pieces.info=Grafin\u0117 juosta, rodanti kurios dalys jau parsi\u0173stos TableColumn.header.completion=Baigtumas TableColumn.header.completion.info=Grafinis atsi\u0173sto kiekio vaizdavimas ConfigView.section.style.showdownloadbasket=Rodyti Atsiuntim\u0173 krep\u0161el\u012f (Torrentams nuvilkti) ConfigView.section.style.alwaysShowTorrentFiles=Visada rodyti Torrent\u0173 failus 'Detal\u0117se'/'Failuose' wizard.multitracker=Prid\u0117ti daugelio Trackeri\u0173 informacij\u0105 \u012f Torrent\u0105 wizard.multitracker.title=Daugelis Trackeri\u0173 wizard.multitracker.configuration=Daugelio Trackeri\u0173 nustatymas wizard.multitracker.new=Naujas... wizard.multitracker.edit=Redaguoti... wizard.multitracker.delete=\u0160alinti wizard.multitracker.group=Trackerio grup\u0117 wizard.multitracker.edit.title=Daugelio Trackeri\u0173 redaktorius wizard.multitracker.edit.name=Pavadinimas wizard.multitracker.edit.save=I\u0161saugoti wizard.multitracker.edit.newgroup=Nauja grup\u0117 wizard.multitracker.edit.deletegroup=\u0160alinti wizard.multitracker.edit.newtracker=Naujas Trackeris wizard.multitracker.edit.deletetracker=\u0160alinti wizard.multitracker.edit.edit=Redaguoti wizard.addingmt=Pridedama daugelio Trackeri\u0173 informacija wizard.multitracker.noannounce=Prane\u0161imo URL n\u0117ra J\u016bs\u0173 Trackeri\u0173 s\u0105ra\u0161e MyTorrentsView.menu.recheck=Priverstinai per&tikrinti iconBar.showDownloadBar.tooltip=Rodyti Atsiuntim\u0173 juost\u0105 iconBar.start.tooltip=Prad\u0117ti iconBar.stop.tooltip=Stabdyti iconBar.remove.tooltip=\u0160alinti iconBar.openNoDefault.tooltip=Atidaryti .torrent fail\u0105 (ne numatytas i\u0161saugojimas) iconBar.openURL.tooltip=Atidaryti URL iconBar.openFolder.tooltip=Atidaryti aplank\u0105 iconBar.new.tooltip=Kurti Torrent\u0105 iconBar.up.tooltip=Slinkti auk\u0161tyn iconBar.down.tooltip=Slinkti \u017eemyn iconBar.run.tooltip=Atidaryti iconBar.host.tooltip=Tiekti iconBar.publish.tooltip=Skelbti MyTorrentsView.menu.editTracker=&Redaguoti Trackerio URL(s) GeneralView.menu.selectTracker=Rinktis ConfigView.section.stats.xslfile=XSL failo pavadinimas ConfigView.section.stats.xslfiledetails=Tai bus \u012ftraukta \u012f statistikos fail\u0105 per \u017eym\u0119 ConfigView.label.savetorrentbackup=I\u0161saugoti atsargin\u0119 kopij\u0105 ConfigView.section.tracker.forceport=Priversti skelbiamus i\u0161orinius torrentus naudoti numatyt\u0105 prievad\u0105 ConfigView.section.ipfilter.allow=LEISTI \u0161iuos intervalus (numatyta reik\u0161m\u0117 - DRAUSTI) ConfigView.section.ipfilter.list.inrange=buvo intervale ConfigView.section.ipfilter.list.notinrange=nebuvo jokiame intervale ConfigView.section.ipfilter.list.title=Blokuot\u0173 IP s\u0105ra\u0161as ConfigView.label.allowsameip=Leisti daugel\u012f prisijungim\u0173 i\u0161 to pa\u010dio IP ConfigView.label.allowsameip.tooltip=\u017dym\u0117ti tik jei REIKIA.\nTai yra apsauga nuo Siurb\u0117li\u0173 (kai i\u0161jungta). ManagerItem.superseeding=Super skleid\u017eiama ConfigView.label.userSuperSeeding=Naudoti Super skleidim\u0105 PeersView.uniquepiece=Dalis (Super skleidimo re\u017eimas) PeersView.uniquepiece.none=N\u0117ra PeersView.timetosend=Laikas daliai persi\u0173sti (Super skleidimo re\u017eimas) ConfigView.section.style.addurlsilently=Atidaryti perduotas nuorodas tyliai ConfigView.section.style.addurlsilently.tooltip=Automati\u0161kai atsi\u0173sti Torrentus pagal perduotas/u\u017emestas nuorodas neatidarant dialogo lango. ConfigView.section.file.decoder.prompt=Visada klausti, kai galimas kodavimo pasirinkimas ConfigView.section.file.decoder.prompt.tooltip=Visada rodyti dialog\u0105, kai galimas kodavimo pasirinkimas MyTorrentsView.menu.moveTop=&Vir\u0161un MyTorrentsView.menu.moveEnd=A&pa\u010dion ConfigView.label.moveonlyusingdefaultsave=tik kai numatytame kataloge ConfigView.label.moveonlyusingdefaultsave.tooltip=Perkelti tik tada, jei duomenys yra numatytame kataloge ConfigView.label.watchtorrentfolder=Importuoti naujus .torrent failus automati\u0161kai ConfigView.label.watchtorrentfolder.tooltip=Reguliariai ie\u0161ko nauj\u0173 .torrent fail\u0173 ConfigView.label.watchtorrentfolderinterval=Intervalas ConfigView.label.watchtorrentfolderinterval.tooltip=Pauz\u0117 tarp aplanko tikrinim\u0173 ConfigView.dialog.choosewatchtorrentfolderpath=Pra\u0161ome pasirinkti .torrent \u012fk\u0117limo katalog\u0105 ConfigView.label.startwatchedtorrentsstopped=Prad\u0117ti sustabdytus ConfigView.label.startwatchedtorrentsstopped.tooltip=Prid\u0117ti naujus Torrentus SUSTABDYTUS ConfigView.section.plugins=Intarpai wizard.maketorrent.filesize=Failo(\u0173) dydis wizard.maketorrent.piececount=Dali\u0173 skai\u010dius wizard.maketorrent.piecesize=Dalies dydis wizard.maketorrent.auto=Automati\u0161kai MainWindow.menu.view.stats=&Statistika SpeedView.title.full=Aktyvumas SpeedView.downloadSpeed.title=Atsiuntimo greitis SpeedView.uploadSpeed.title=I\u0161siuntimo greitis ConfigView.section.style.useSIUnits=Naudoti IEC vienetus (pvz., KB -> KiB) iconBar.top.tooltip=Slinkti \u012f vir\u0161\u0173 iconBar.bottom.tooltip=Slinkti \u012f apa\u010di\u0105 TableColumn.header.health=Gerov\u0117 MyTorrentsView.menu.health=Apie gerov\u0119 health.explain.grey=rei\u0161kia, kad \u0161is Torrentas neaktyvus (nei atsiun\u010diamas, nei i\u0161siun\u010diamas) health.explain.red=rei\u0161kia, kad J\u016bs nesate susijung\u0119 su jokiu Siunt\u0117ju, kai atsiun\u010diate health.explain.blue=kai skleid\u017eiate, tai rei\u0161kia, kad dar nesate susijung\u0119 su n\u0117 vienu Siunt\u0117ju\nkai atsiun\u010diate, tai rei\u0161kia, kad esate susijung\u0119 su keletu Siunt\u0117j\u0173, bet Trackeris yra nepasiekiamas health.explain.yellow=rei\u0161kia, kad su Trackeriu viskas tvarkoje, esate susijung\u0119 su Siunt\u0117jais, bet neturite n\u0117 vieno nutolusio prisijungimo.\nGalb\u016bt turite problem\u0173 su NAT, jei Torrent\u0173 geltona b\u016bsena i\u0161lieka vis\u0105 laik\u0105 health.explain.green=rei\u0161kia, kad viskas vyksta gerai. ConfigView.section.style.alwaysRefreshMyTorrents=Visada atnaujinti 'Mano Torrentus' ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=\u0160is nustatymas atnaujins 'Mano Torrent\u0173' lang\u0105, net jei jis nerodomas (naudinga kai kuriems Irc intarpams) # #2.0.7.0 # security.certtruster.title=Saugumo sertifikato persp\u0117jimas security.certtruster.intro=\u0160is saugumo sertifikatas buvo i\u0161duotas kompanijos, kuria J\u016bs nepasitikite security.certtruster.resource=I\u0161teklius: security.certtruster.issuedto=Kam i\u0161duotas: security.certtruster.issuedby=Kieno i\u0161duotas: security.certtruster.prompt=Ar norite pasitik\u0117ti? security.certtruster.yes=Taip security.certtruster.no=Ne ConfigView.section.tracker.torrentsperpage=Kiek Torrent\u0173 1 lape? [0: neribojama] MainWindow.menu.file.share=&Vie\u0161inti MainWindow.menu.file.share.file=&Fail\u0105... MainWindow.menu.file.share.dir=&Katalog\u0105... MainWindow.menu.file.share.dircontents=Apalnk\u0105 ir jo &turin\u012f... MainWindow.menu.file.share.dircontentsrecursive=Aplanko turin\u012f... (&rekursi\u0161kai) MainWindow.dialog.share.sharefile=I\u0161rinkite fail\u0105 vie\u0161inimui MainWindow.dialog.share.sharedir=I\u0161rinkite aplank\u0105 vie\u0161inimui MainWindow.dialog.share.sharedircontents=I\u0161rinkite aplanko turin\u012f vie\u0161inimui MainWindow.dialog.share.sharedircontents.recursive=Rekursi\u0161kai globalmanager.download.remove.veto=\u0160alinimo veiksmas vetuotas plugin.sharing.download.remove.veto=\u0160is atsiuntimas yra resurs\u0173 vie\u0161inimo rezultatas.\nNor\u0117dami pa\u0161alinti atsiuntim\u0105, pa\u0161alinkite susijus\u012f vie\u0161in\u012f: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Pagrindinis ConfigView.section.tracker.web=Tinklalapis ConfigView.label.prioritizefirstpiece=Suteikti prioritet\u0105 pirmoms ir paskutin\u0117ms fail\u0173 dalims ConfigView.label.prioritizefirstpiece.tooltip=Pirmiausia bando parsi\u0173sti pa\u010di\u0105 failo prad\u017ei\u0105 ir pabaig\u0105.\nAnkstyvai per\u017ei\u016brai palaikyti. ConfigView.section.file.confirm_data_delete=Patvirtinti duomen\u0173 trynim\u0105 ConfigView.section.file.confirm_data_delete.tooltip=Patvirtinti duomen\u0173 trynim\u0105, kai naudojama '\u0160alinti ir trinti...' TrayWindow.menu.startalldownloads=Prad\u0117ti visus atsiuntimus SystemTray.menu.startalltransfers=Prad\u0117ti visus siuntimus sharing.progress.title=Dalinimosi progresas sharing.progress.hide=Sl\u0117pti MainWindow.menu.view.myshares=Mano &vie\u0161iniai MySharesView.title.full=Mano vie\u0161iniai MySharesView.name=Pavadinimas MySharesView.type=Tipas MySharesView.type.file=Failas MySharesView.type.dir=Katalogas MySharesView.type.dircontents=Katalogo turinys MySharesView.type.dircontentsrecursive=Katalogo turinys (rekursi\u0161kas) MySharesView.menu.remove=\u0160alinti ConfigView.section.tracker.extensions=I\u0161pl\u0117timai ConfigView.section.tracker.sendpeerids=Si\u0173sti Siunt\u0117jo tapatyb\u0119 klientams ConfigView.section.tracker.enableudp=\u012ejungti UDP Trackerio protokol\u0105 plugin.sharing.torrent.remove.veto=\u0160is Trackerio \u012fra\u0161as yra resurs\u0173 vie\u0161inimo rezultatas.\nNor\u0117dami pa\u0161alinti atsiuntim\u0105, pa\u0161alinkite susijus\u012f vie\u0161in\u012f: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Atsiuntimai negali b\u016bti \u0161alinami, nes nesustabdyti plugin.sharing.remove.veto=\u0160is vie\u0161inys yra dalis 'katalogo turinio' vie\u0161inys ir negali b\u016bti laisvai i\u0161trintas.\nI\u0161trinkite \u0161aknin\u012f vie\u0161in\u012f GeneralView.label.hash.tooltip=Spauskite, nor\u0117dami nukopijuoti rakt\u0105 \u012f i\u0161karpin\u0119 ConfigView.section.tracker.maxpeersreturned=Daugiausia gr\u0105\u017eint\u0173 Siunt\u0117j\u0173 [0: neribojama] ConfigView.label.serverport=\u012eeinantis TCP/UDP klausymosi prievadas ConfigView.label.serverport.tooltip=Prievadas turi b\u016bti tarp 1-65535 ir neb\u016bti 6880, nes \u0161is yra rezervuotas vidiniam Vuze naudojimui. configureWizard.nat.server.tcp_listen_port=\u012eeinantis TCP klausymosi prievadas ConfigView.section.sharing=Vie\u0161inimas ConfigView.section.sharing.usessl=Naudoti SSL bendriesiems resursams (reikalingi Trackerio nustatymai) ConfigView.section.style.dropdiraction=Nuvilkimo veiksmai katalogams ConfigView.section.style.dropdiraction.opentorrents=Atidaryti Torrentus ConfigView.section.style.dropdiraction.sharefolder=Vie\u0161inti katalog\u0105 ConfigView.section.style.dropdiraction.sharefoldercontents=Vie\u0161inti turin\u012f # # 2.0.7.x # Categories.all=Visi Categories.uncategorized=Nesugrupuoti CategoryAddWindow.message=\u012eveskite naujos kategorijos pavadinim\u0105 CategoryAddWindow.title=Prid\u0117ti nauj\u0105 kategorij\u0105 ConfigView.label.autoSeedingIgnoreInfo=Ignoruojami Torrentai perkeliami \u012f skleidimo eil\u0117s gal\u0105. Jie n\u0117ra automati\u0161kai startuojami.\nIgnoravimo taisykl\u0117s netaikomos Torrentams, kurie atitinka Pirmo prioriteto kriterij\u0173.\nJei nenurodyta kitaip, naudokite 0 taisyklei i\u0161jungti. ConfigView.label.directory=Katalogas ConfigView.label.disconnetseed.tooltip=Kai skleid\u017eiamas Torrentas, atjungti bet kuriuos klientus, kurie taip pat skleid\u017eia.\nJiems neb\u016btina su Jumis komunikuoti. ConfigView.label.ignoreCase=Ignoruoti didum\u0105 ConfigView.label.ignoreSeeds=Ignoruoti Torrentus su ma\u017eiausiai ConfigView.label.importdirectory=\u012ek\u0117limo katalogas ConfigView.label.minPeersToBoostNoSeeds.tooltip=Kiekvienas Torrentas be Skleid\u0117j\u0173 ir turintis ma\u017eiau Siunt\u0117j\u0173 negu nurodyta\nbus perkeliamas eil\u0117s galo link. ConfigView.label.minPeersToBoostNoSeeds=Suma\u017einti skleidimo rang\u0105 Torrentams be Skleid\u0117j\u0173 ir ma\u017eiau nei ConfigView.label.minSeedingTime.tooltip=Skleidimo rangas trumpais laiko periodais gali da\u017enai svyruoti, kartais priversdamas Torrent\u0105 automati\u0161kai startuoti, tik tam, kad b\u016bt\u0173 sustabdytas ir tuoj pat \u012ftrauktas \u012f eil\u0119.\n\u0160is nustatymas suma\u017eina problem\u0105 priversdamas Torrent\u0105 likti skleidimo re\u017eime duot\u0105 laiko period\u0105. J\u016bs vis tiek galite sustabdyti rankiniu b\u016bdu, jei norite. ConfigView.label.minSeedingTime=Ma\u017eiausias skleidimo laikas sekund\u0117mis ConfigView.label.minSpeedForActiveDL.tooltip=Atsiuntimo lizdas yra visada naudojamas pradines 30 sekund\u017ei\u0173\npo to, kai nebaigtas Torrentas startuoja. ConfigView.label.minSpeedForActiveDL=Neskai\u010diuoti Torrento, kaip naudojan\u010dio atsiuntimo lizd\u0105, jei greitis ma\u017eesnis nei ConfigView.label.peers=Siunt\u0117jai ConfigView.label.queue.debuglog=Registruoti derinimo informacij\u0105 ConfigView.label.queue.debuglog.info=Prideda eil\u0117s derinimo informacij\u0105 \u012f konsol\u0119/registravimo fail\u0105.\nNors paslaptinga, derinimo informacija parodo Torrent\u0173 b\u016bsen\u0105 ir kod\u0117l jie yra/n\u0117ra startuojami/traukiami \u012f eil\u0119. ConfigView.label.queue.minQueueingShareRatio=Netraukti \u012f eil\u0119 ar stabdyti Torrento, kol dalinimosi santykis nepasiek\u0117 ConfigView.label.ratio=santykis ConfigView.label.removeOnStop=Pa\u0161alinti Torrent\u0105 i\u0161 s\u0105ra\u0161o, kai jis automati\u0161kai sustabdomas ConfigView.label.savedirectory=I\u0161saugojimo katalogas ConfigView.label.seeding.autoReposition.tooltip=Jei \u012fjungta, Torrent\u0173 tvarka ('Nr.' stulpelis) bus pakeista, kad atitikt\u0173 skleidimo rang\u0105\nTai yra naudinga, jei nenorite matyti skleidimo rango skai\u010diaus, bet norite \u017einoti tvark\u0105, kuria baigti Torrentai startuos. ConfigView.label.seeding.autoReposition=Automati\u0161kai perstatyti Torrentus, atsi\u017evelgiant \u012f skleidimo rang\u0105 ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Da\u017enai Torrentai su \u017eemu Skleid\u0117j\u0173 skai\u010diumi ir auk\u0161tu Siunt\u0117j\u0173 skai\u010diumi rei\u0161kia, kad tikriausiai n\u0117ra visos kopijos tarp Siunt\u0117j\u0173.\nTod\u0117l J\u016bs galite nenor\u0117ti, kad skleidimo taisykl\u0117s apsimest\u0173, jog yra visa kopija (ir taip suma\u017eint\u0173 rang\u0105) ConfigView.label.seeding.fakeFullCopySeedStart=bet tik Torrentams su ma\u017eiausiai ConfigView.label.seeding.ignore=Ignoravimo taisykl\u0117s ConfigView.label.seeding.ignore0Peers=Ignoruoti Torrentus be Siunt\u0117j\u0173 ConfigView.label.seeding.ignoreRatioPeers=Ignoruoti Torrentus, kurie turi bent 1 Skleid\u0117j\u0105 kiekvienam ConfigView.label.seeding.ignoreShareRatio=Ignoruoti Torrentus, kurie turi dalinimosi santyk\u012f ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignoruoti Torrent\u0105 net jeigu\ntaikomos pirmenyb\u0117s taisykl\u0117s ConfigView.label.seeding.ignore.header.rule=Taisykl\u0117 ConfigView.label.seeding.ignore.header.value=Reik\u0161m\u0117 ConfigView.label.seeding.firstPriority.info=Pirmo prioriteto Torrentai bus visada eil\u0117s vir\u0161uje.\nBet kurie Torrentai, atitinkantys pirmenyb\u0117s kriterij\u0173 nebus automati\u0161kai stabdomi ar traukiami \u012f eil\u0119.\nTorrentas atitinkantis pirmenyb\u0117s kriterij\u0173 naudos vienalaik\u012f atsiuntimo lizd\u0105, jei to reik\u0117s. ConfigView.label.seeding.firstPriority.FP=Pirmas prioritetas ConfigView.label.seeding.firstPriority=Pirmenyb\u0117 teikiama Torrentams su ConfigView.label.seeding.firstPriority.following=i\u0161 \u0161it\u0173: ConfigView.label.seeding.firstPriority.shareRatio=Dalinimosi santykis ma\u017eesnis nei ConfigView.label.seeding.firstPriority.seedingMinutes=Prab\u0117g\u0119s laikas nuo pasikeitimo i\u0161 atsiuntimo \u012f skleidim\u0105 ConfigView.label.seeding.firstPriority.DLMinutes=Prab\u0117g\u0119s laikas nuo atsiuntimo prad\u017eios ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Apsimesdami, kad yra visa kopija kiekvieniems X Siunt\u0117j\u0173, J\u016bs suma\u017einate Torrent\u0173 su dideliu Siunt\u0117j\u0173 skai\u010diumi rang\u0105.\nLabiausiai tik\u0117tina, kad Torrentai su dideliu Siunt\u0117j\u0173 skai\u010diumi taip pat turi didel\u012f duomen\u0173 sraut\u0105.\nTai nepakei\u010dia 'Skleid\u0117j\u0173' rodymo. ConfigView.label.seeding.numPeersAsFullCopy=Apsimesti, kad yra visa kopija kiekvienam\n[0: neapsimesti] ConfigView.label.seeding.preferLargerSwarms.tooltip=Jei J\u016bs daugiausia skleid\u017eiate Torrentus su "u\u017estrigusiais" Siunt\u0117jais, pirmenyb\u0117s teikimams didesn\u0117ms grup\u0117ms yra prasmingas\nKai daugiausia skleid\u017eiate pla\u010diai paplitusius Torrentus, pirmenyb\u0117 ma\u017eesn\u0117ms grup\u0117ms yra prasminga. ConfigView.label.seeding.preferLargerSwarms=Kai Torrentai yra to paties rango, teikti pirmenyb\u0119 didesn\u0117ms grup\u0117ms ConfigView.label.seeding.rankType.none.tooltip=Pagal 'Nr.' stulpel\u012f ConfigView.label.seeding.rankType.none=Niek\u0105 ConfigView.label.seeding.rankType.peerSeed.options=Siunt\u0117jai:Skleid\u0117jai santykio nustatymai ConfigView.label.seeding.rankType.peerSeed.tooltip=Didesnis santykis = Didesnis rangas ConfigView.label.seeding.rankType.peerSeed=Siunt\u0117jai:Skleid\u0117jai santyk\u012f ConfigView.label.seeding.rankType.seed.fallback=Gr\u012f\u017eti prie Siunt\u0117jai:Skleid\u0117jai santykio po\n[0: niekada negr\u012f\u017eti] ConfigView.label.seeding.rankType.seed.options=Tik Skleid\u0117j\u0173 skai\u010diaus nustatymai ConfigView.label.seeding.rankType.seed.tooltip=Ma\u017eiau Skleid\u0117j\u0173 = Didesnis rangas ConfigView.label.seeding.rankType.seed=Tik Skleid\u0117j\u0173 skai\u010di\u0173 ConfigView.label.seeding.rankType.timedRotation.tooltip=Visi eil\u0117je esantys Torrentai bus periodi\u0161kai perkeliami \u012f skleidimo re\u017eim\u0105.\nSkleidimo laikas nustatomas 'Ma\u017eiausiu skleidimo laiku' ConfigView.label.seeding.rankType.timedRotation=Periodin\u012f keitim\u0105 ConfigView.label.seeding.rankType.tooltip=Auk\u0161\u010diausio rango Torrentai yra automati\u0161kai startuojami.\nKai kitas Torrentas pasiekia auk\u0161tesn\u012f rang\u0105, \u017eemesnio rango Torrentas sustabdomas ir \u012ftraukiamas \u012f eil\u0119.\n\nTik Torrentai esantys eil\u0117je gali b\u016bti automati\u0161kai startuojami.\nSustabdyti Torrentai niekada automati\u0161kai nestartuojami. ConfigView.label.seeding.rankType=Rikiuoti u\u017ebaigtus Torrentus automati\u0161kai startuoti pagal: ConfigView.label.stopAfterMinutes=Kai persijungiama \u012f skleidim\u0105, sustoti po tam tikro laiko ConfigView.label.switchpriority.tooltip=\u017demas prioritetas suma\u017eina i\u0161siuntimo pralaidumo i\u0161skyrim\u0105 Torrentui. ConfigView.pluginlist.info=\u0160ie intarpai buvo atpa\u017einti. Kai kurie intarpai gali netur\u0117ti nustatymo korteli\u0173. ConfigView.pluginlist.noplugins=Nerastas n\u0117 vienas intarpas. ConfigView.section.pluginslist=S\u0105ra\u0161as ConfigView.section.queue.seeding=Skleidimas ConfigView.section.queue.seeding.autoStarting=Automatinis startavimas ConfigView.section.queue.seeding.ignore=Ignoravimo taisykl\u0117s ConfigView.section.queue.seeding.firstPriority=Pirmas prioritetas ConfigView.section.queue.main=Pagrindin\u0117 ConfigView.section.queue=Eil\u0117 ConfigView.section.torrents=Torrentai ConfigView.text.all=visais ConfigView.text.hours=val ConfigView.text.ignoreRule=Ignoravimo taisykl\u0117 ConfigView.text.ignore=ignoruoti ConfigView.text.minutes=min ConfigView.text.neverIgnore=Niekada neignoruok ConfigView.text.any=bet kuriuo DownloadManager.error.datamissing=Tr\u016bksta duomen\u0173 MainWindow.menu.file.open.torrentforseeding=Torrent fail\u0105... (Skleidimui) MainWindow.menu.language.refresh=&At\u0161vie\u017einti ManagerItem.forced=Priverstinai ManagerItem.queued=Eil\u0117je MySeedersView.header=Baigti Torrentai TableColumn.header.availability.info=Kiek matoma piln\u0173 kopij\u0173 TableColumn.header.availability=Pasiekiamumas TableColumn.header.category=Kategorija MyTorrentsView.header=Nebaigti Torrentai TableColumn.header.maxuploads=Did\u017e. i\u0161siuntim\u0173 sk. MyTorrentsView.menu.category.delete=&Trinti kategorij\u0105 MyTorrentsView.menu.forceStart=&Priverstinai prad\u0117ti MyTorrentsView.menu.queue=\u012e &eil\u0119 MyTorrentsView.menu.setCategory.add=&Prid\u0117ti kategorij\u0105... MyTorrentsView.menu.setCategory=Priskirti kategorij\u0105 TableColumn.header.savepath=I\u0161saugojimo kelias TableColumn.header.SeedingRank=Skleidimo rangas TableColumn.header.totalspeed.info=Greitis vis\u0173 Siunt\u0117j\u0173, prie kuri\u0173 esate prisijung\u0119 TableColumn.header.totalspeed=Visas greitis splash.initializePlugins=Ruo\u0161iami intarpai StartStopRules.SPratioMet=S:S santykis geras StartStopRules.FP0Peers=PP / 0 Siunt\u0117j\u0173 StartStopRules.0Peers=0 Siunt\u0117j\u0173 StartStopRules.numSeedsMet=Skleid\u0117j\u0173 skai\u010dius geras StartStopRules.ratioMet=Skleid\u0117jai:Siunt\u0117jai santykis geras StartStopRules.shareRatioMet=Dalinimosi santykis geras StartStopRules.waiting=Laukiama StartStopRules.firstPriority=Pirmas prioritetas ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Vie\u0161inti turin\u012f (rekursi\u0161kai) DownloadManager.error.unabletostartserver=Nepavyko paleisti serverio - patikrinkite klausymosi prievad\u0173 nustatymus, ugniasien\u0117s leidimus programai veikti serverio re\u017eimu GeneralView.label.creationdate=Sukurta: ConfigView.section.tracker.announcescrapepercentage=S\u0105rankos intervalas kaip %prane\u0161imo am\u017eius\npvz., 200 = 2:1. 0 = leisti spr\u0119sti Siunt\u0117jui ManagerItem.stopping=Stabdoma ConfigView.section.tracker.announcecacheperiod=Prane\u0161imo ke\u0161as (milisek.) ConfigView.section.tracker.scrapecacheperiod=S\u0105rankos ke\u0161as (milisek.) ConfigView.section.tracker.scrapeandcache=Surinkti ir ke\u0161inti ConfigView.section.tracker.announcecacheminpeers=Prane\u0161imo ke\u0161o \u012fjungimo Siunt\u0117j\u0173 slenkstis MyTrackerView.scrapes=S\u0105rankos fileDownloadWindow.retry=Kartoti MyTrackerView.bytesin=Gauta bait\u0173 MyTrackerView.bytesinave=Vid. gauta MyTrackerView.bytesout=Si\u0173sta bait\u0173 MyTrackerView.bytesoutave=Vid. si\u0173sta ConfigView.section.file.max_open_files=Daugiausia atidaryt\u0173 fail\u0173 skaitymui/ra\u0161ymui\n[0: neribojama] ConfigView.section.file.max_open_files.tooltip=Naudinga, kai siun\u010diate Torrentus su \u0161imtais/t\u016bkstan\u010diais fail\u0173 ir pasiekiate OS ranken\u0117li\u0173 limit\u0105. ConfigView.section.proxy=Tarpinio serverio nustatymai ConfigView.section.proxy.enable_proxy=\u012ejungti tarpin\u012f server\u012f Trackerio susijungimams [reikia perkrauti] ConfigView.section.proxy.host=Serveris ConfigView.section.proxy.port=Prievadas ConfigView.section.proxy.username=Naudotojas ConfigView.section.proxy.password=Slapta\u017eodis ConfigView.section.proxy.enable_socks=Tarpinis serveris yra SOCKS wizard.createtorrent.extrahashes=Prid\u0117ti raktus kitiems tinklams (pvz., Gnutella2, ed2k) GeneralView.label.connected=susijungta GeneralView.label.in_swarm=grup\u0117je ManagerItem.initializing=Ruo\u0161iamasi AlertMessageBox.error=Klaida AlertMessageBox.warning=\u012esp\u0117jimas AlertMessageBox.comment=Informacija AlertMessageBox.information=Informacija AlertMessageBox.unread=J\u016bs turite neperskaityt\u0173 persp\u0117jimo \u017einu\u010di\u0173 - spauskite \u010dia joms parodyti. SharedPortServer.alert.selectorfailed=Nepavyko sukurti klausytojo \u012feinantiems duomenims.\nPatikrinkite, ar ugniasien\u0117s nustatymai leid\u017eia java(w).exe veikti serverio re\u017eimu Tracker.alert.listenfail=Nepavyko klausytis prievadu %1.\nPatikrinkite, ar kitos programos jau nenaudoja \u0161io prievado. Taip pat patikrinkite ar neveikia kita Vuze kopija. DiskManager.alert.movefileexists=Klaida keliant u\u017ebaigtus failus\nFailas %1 jau egzistuoja nurodytame kataloge DiskManager.alert.movefilefails=Klaida keliant u\u017ebaigtus failus\nFailo %1 k\u0117limas nepavyko, %2 DiskManager.alert.movefilerecoveryfails=Klaid\u0173 atstatymas po perk\u0117limo nepavyko\nFailo %1 atstatymas nepavyko, %2 ConfigView.section.tracker.logenable=Periodi\u0161kai registruoti Trackerio statistik\u0105 \u012f 'tracker.log' SpeedView.stats.title=Statistika SpeedView.stats.total=I\u0161 viso SpeedView.stats.session=\u0160i\u0105 sesij\u0105 SpeedView.stats.session.tooltip=I\u0161 viso (protokolas) SpeedView.stats.downloaded=Atsi\u0173sta (protokolas) SpeedView.stats.uploaded=I\u0161si\u0173sta (protokolas) SpeedView.stats.ratio=Santykis SpeedView.stats.uptime=Veikimo laikas SpeedView.stats.now=Dabar SpeedView.stats.now.tooltip=I\u0161 viso (protokolas) AutoMigration.useralert=Vuze naudotojo nustatymo fail\u0173/katalog\u0173 automatinio perk\u0117limo rezultatai:\n\n%1\nNepavyk\u0119 perk\u0117limai turi b\u016bti atlikti rankiniu b\u016bdu.\nNEU\u017dMIR\u0160KITE ATNAUJINTI J\u016aS\u0172 I\u0160SAUGOJIMO KELI\u0172, JEI JIE BUVO PERKELTI! # # > 2.0.8.0 # OpenTorrentWindow.title=Atidaryti Torrent\u0105(-us) OpenTorrentWindow.message=Eksperimentinis OpenTorrentWindow.addFiles=&Prid\u0117ti fail\u0173 OpenTorrentWindow.dataLocation=Duomen\u0173 i\u0161saugojimo vieta: OpenTorrentWindow.startMode=Prid\u0117jimo re\u017eimas OpenTorrentWindow.startMode.queued=Eil\u0117je OpenTorrentWindow.startMode.stopped=Sustabdytas OpenTorrentWindow.startMode.forceStarted=Priverstinis startas OpenTorrentWindow.addPosition=Pozicija eil\u0117je OpenTorrentWindow.addPosition.first=Pirmas OpenTorrentWindow.addPosition.last=Paskutinis TableColumn.header.remaining.info=Kiek liko parsi\u0173sti TableColumn.header.remaining=Liko ConfigView.section.tracker.enablecompact=\u012ejungti glaust\u0105 prane\u0161imo protokol\u0105 ConfigView.section.tracker.enablekey=\u012ejungti rakto perdavim\u0105 Trackeriui didesniam saugumui u\u017etikrinti ConfigView.section.file.perf=Na\u0161umo nustatymai ConfigView.section.file.perf.explain=\u012esp\u0117jimas - nekvalifikuoti \u0161i\u0173 parametr\u0173 pakeitimai gali neigiamai paveikti atsiuntimo na\u0161um\u0105. Reikalingas perkrovimas.\nJei turite "atmintis baig\u0117si" problem\u0173 svarstykite susijungim\u0173 Torrentui ribojim\u0105 (\u017ei\u016br\u0117kite Siuntimo nustatymus) ConfigView.section.file.max_open_files.explain=Daugelio fail\u0173 atidarymas gali sukelti operacin\u0117s sistemos problem\u0173 d\u0117l ribot\u0173 resurs\u0173 toki\u0173 kaip fail\u0173 ranken\u0117l\u0117s. Tai riboja vienalaiki\u0161kai atidaryt\u0173 fail\u0173 skai\u010di\u0173. popup.error.hide=Sl\u0117pti popup.error.details=Informacija ConfigView.section.style.colorOverrides=Spalv\u0173 pakeitimas ConfigView.section.style.colorOverride.progressBar=Progreso juosta ConfigView.section.style.colorOverride.error=Klaida MainWindow.status.tooOld=yra senas, pra\u0161au atnaujinti. ConfigView.section.style.colorOverride.warning=\u012esp\u0117jimas ConfigView.section.style.colorOverride.altRow=Kitos eilut\u0117s ConfigView.section.file.save.peers.enable=I\u0161saugoti Siunt\u0117jus greitiems prisijungimams i\u0161 naujo ConfigView.section.file.save.peers.max=Daugiausia Siunt\u0117j\u0173 i\u0161saugoti [0: neribojama] ConfigView.section.file.save.peers.pertorrent=Torrentui ConfigView.label.max_peers_per_torrent=Daugiausia susijungim\u0173 Torrentui [0: neribojama] ConfigView.label.max_peers_total=I\u0161 viso daugiausia susijungim\u0173 [0: neribojama] ConfigView.section.style.colorOverrides.reset=Atstatyti spalvas ConfigView.section.language.info=Kai \u012fjungta, atnaujinimo tikrinimas vyks kiekvien\u0105 kart\u0105 paleid\u017eiant Azureus. ConfigView.section.language.enableUpdate=\u012ejungti atnaujinim\u0105 Internetu ConfigView.section.language.UpdateURL=Atnaujinimo nuoroda ConfigView.section.language.UpdateNow=Atnaujinti dabar! Button.revert=Atstatyti MyTorrentsView.menu.changeDirectory=Keisti duomen\u0173 katalog\u0105 GenericText.column=stulpelis MyTorrentsView.menu.thisColumn.remove=\u0160alinti stulpel\u012f MyTorrentsView.menu.thisColumn.toClipboard=Kopijuoti tekst\u0105 \u012f i\u0161karpin\u0119 MyTorrentsView.menu.tracker=Trackeris ConfigView.download.abbreviated=A: ConfigView.upload.abbreviated=I: ConfigView.complete.abbreviated=B: TableColumn.header.secondsseeding=Skleid\u017eiama TableColumn.header.secondsseeding.info=Visas Torrento skleidimo laikas. TableColumn.header.secondsdownloading=Atsiun\u010diama TableColumn.header.secondsdownloading.info=Siuntimo laikas. ConfigView.section.tracker.udpversion=UDP protokolo versija (1 ar 2) window.updateswt.title=J\u016bs\u0173 SWT versija per sena! window.updateswt.text=J\u016bs\u0173 SWT versija per sena!\nSWT yra Vuze naudojama grafin\u0117 biblioteka, o J\u016bs\u0173 turima versija yra per sena, kad veikt\u0173 naujausia Vuze versija. Spauskite mygtuk\u0105 'Gerai' SWT atnaujinimui. window.updateswt.status=B\u016bsena window.updateswt.failed=Nepavyko atnaujinti, pakartojimui spauskite Gerai. window.updateswt.status.downloading.updater=Atsiun\u010diamas atnaujinimo modulis window.updateswt.status.finding=Ie\u0161koma naujausios SWT versijos window.updateswt.status.downloading=Atsiun\u010diama naujausia SWT versija window.updateswt.status.done=Perkraunama window.updateswt.ok=Gerai window.updateswt.cancel=Atsisakyti swt.updater.downloader.downloading=Atsiun\u010diamas SWT i\u0161 swt.updater.urlsgetter.downloading=Gaunamas kopij\u0173 s\u0105ra\u0161as i\u0161 swt.updater.urlsgetter.platform=SWT platformai: window.updateswt.ignore=Ignoruoti ConfigView.section.style.useFancyTabs=Naudoti \u012fmantrias korteles splash.initializeGM=Ruo\u0161iamas Torrent\u0173 valdytojas splash.loadingTorrents=\u012ekeliami Torrentai MyTorrentsView.menu.thisColumn.sort=&Rikiuoti Scrape.status.ok=S\u0105ranka s\u0117kminga Scrape.status.error=S\u0105rankos klaida: Scrape.status.error.badURL=Prane\u0161imo URL neatitinka s\u0105rankos specifikacij\u0173. Scrape.status.error.nohash=Atsakyme nerastas raktas. Scrape.status.error.invalid=Klaidingas atsakymas. Scrape.status.nextScrapeAt=Kita s\u0105ranka %1 Scrape.status.scraping=Surinkin\u0117jama... Scrape.status.initializing=Laukiama s\u0105rankos... Scrape.status.scraping.queued=S\u0105ranka eil\u0117je... ConfigView.label.minSpeedForActiveSeeding=Neskai\u010diuoti u\u017ebaigto Torrento kaip naudojan\u010dio lizd\u0105, jei greitis ma\u017eesnis nei ConfigView.section.stats.exportpeers=I\u0161saugoti Siunt\u0117j\u0173 informacij\u0105 MainWindow.menu.view.irc.moved=Irc dabar gaunamas kaip intarpas, \u017ei\u016br\u0117kite http://azureus.sourceforge.net/plugin_list.php (ang.). Kai \u012fdieg\u0117te, naudokite meniu Intarpai->IRC. MyTrackerView.webui.contextmenu.copyurl=Kopijuoti Torrento URL \u012f i\u0161karpin\u0119 ConfigView.section.file.torrent.ignorefiles=Kuriant Torrentus ignoruoti failus\n pvz., .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignoruojamas failas ConfigView.section.style.useUnitsRateBits=Naudoti bitus vietoj bait\u0173 baitais paremtoms reik\u0161m\u0117ms (pvz., KiB/s -> Kibit/s) ConfigView.section.interface.resetassoc=Atstatyti nar\u0161ykl\u0117s fail\u0173 susiejim\u0105 (.torrent) ConfigView.section.interface.resetassocbutton=Atstatyti ConfigView.section.interface.checkassoc=Tikrinti fail\u0173 susiejim\u0105 paleid\u017eiant dialog.associations.title=Susiejimo tikrinimas Button.yes=Taip Button.no=Ne ConfigView.label.seeding.autoStart0Peers=Automati\u0161kai startuoti visus u\u017ebaigtus Torrentus be Siunt\u0117j\u0173 ConfigView.label.seeding.autoStart0Peers.tooltip=\u012ejunkite, jei norite, kad Trackeris visada rodyt\u0173 Skleid\u0117jus Torrentams be Siunt\u0117j\u0173. dialog.associations.prompt=Vuze n\u0117ra numatyta programa BitTorrent failams.\nAr nor\u0117tum\u0117te susieti .torrent failus su Vuze dialog.associations.askagain=Tikrinti paleid\u017eiant ConfigView.section.plugins.update=Intarp\u0173 atnaujinimas Plugin.pluginupdate.enablecheck=\u012ejungti intarp\u0173 atnaujinimo tikrinim\u0105 plugins.basicview.status=B\u016bsena: plugins.basicview.activity=Aktyvumas: plugins.basicview.progress=Progresas: plugins.basicview.log=Registras: ConfigView.label.maxdownloadspeed=KB/s globalus did\u017e. atsiuntimo greitis [0: neribojama] splash.loadingTorrent=\u012ekeliamas Torrentas splash.of=i\u0161 ConfigView.section.plugins.irc=Irc UpdateWindow.title=Vuze atnaujintojas UpdateWindow.header=\u0160iuos komponentus reikia atnaujinti: UpdateWindow.columns.install=\u012ediegti UpdateWindow.columns.name=Pavadinimas UpdateWindow.columns.version=Versija UpdateWindow.columns.size=Dydis UpdateWindow.cancel=Atsisakyti UpdateWindow.quit=I\u0161eiti UpdateWindow.close=U\u017edaryti UpdateWindow.ok=Atnaujinti UpdateWindow.restart=Perkrauti UpdateWindow.status.downloading=Atsiun\u010diama UpdateWindow.status.done=Baigta UpdateWindow.status.failed=Nepavyko UpdateWindow.status.restartNeeded=Reik\u0117s perkrauti! ConfigView.pluginlist.broken=Neveikiantis ConfigView.pluginlist.whereToPut=D\u0117kite bet kuriuos intarpus su katalogais \u010dia: ConfigView.pluginlist.whereToPutOr=Vie\u0161iesiems intarpams naudokite: MainWindow.statusText.checking=Ie\u0161koma atnaujinim\u0173 TableColumn.header.OnlyCDing4=Tik skleid\u017eiama TableColumn.header.OnlyCDing4.info=Torrento skleidimo laikas. Neskai\u010diuojamas laikas, kai Torrentas buvo atsiun\u010diamas (ir skleid\u017eiamas). ConfigView.section.style.alternateTablePainting=Naudoti kit\u0105 grafini\u0173 lentel\u0117s stulpeli\u0173 pie\u0161imo metod\u0105 (gali reik\u0117ti perkrauti) UpdateWindow.status.restartMaybeNeeded=Gali reik\u0117ti perkrauti ConfigView.pluginlist.shared=vie\u0161asis PeersView.host=Kompiuterio vardas PeersView.host.info=Siunt\u0117jo kompiuterio vardas, kai galimas (gali paveikti veikim\u0105) MainWindow.menu.help.whatsnew=Kas naujo ConfigView.label.checkonstart=Tikrinti ar n\u0117ra naujesn\u0117s versijos, kai Vuze paleistas ConfigView.label.periodiccheck=Periodi\u0161kai tikrinti, ar n\u0117ra naujos versijos ConfigView.label.opendialog=Automati\u0161kai atidaryti atnaujinimo asistent\u0105, kai yra atnaujinim\u0173 MainWindow.updateavail=Spauskite \u010dia atnaujinimams gauti MainWindow.status.unofficialversion=Vuze beta MainWindow.status.latestversionunchecked=Versijos tikrinimas i\u0161jungtas GeneralView.label.updatein.stopped=Sustabdyta StartStopRules.menu.viewDebug=\u017di\u016br\u0117ti derinimo informacij\u0105 ConfigView.section.style.doNotUseGB=Nenaudoti GB vieneto ConfigView.section.style.doNotUseGB.tooltip=Jei pa\u017eym\u0117ta, Vuze toliau naudos MB, net dyd\u017eiams didesniems u\u017e 1024MB MainWindow.menu.help.plugins=Gauti intrap\u0173 ConfigView.section.plugins.TrackerWeb=Trackerio tinklalapis ConfigView.section.tracker.enablecategories=Skirti Torrentus pagal kategorij\u0105 health.explain.share=rei\u0161kia, kad Torrentas yra arba tiekiamas arba skelbiamas ConfigView.section.tracker.createcert=Sukurti pasira\u0161yt\u0105 sertifikat\u0105 ConfigView.section.tracker.createbutton=Sukurti security.certcreate.title=Pasira\u0161yto sertifikato k\u016brimas security.certcreate.intro=\u0160is dialogas leid\u017eia sukurti pasira\u0161yt\u0105 sertifikat\u0105 security.certcreate.alias=Kitaip \u017einomas kaip security.certcreate.strength=Stiprumas security.certcreate.firstlastname=Vardas, pavard\u0117 security.certcreate.orgunit=Organizacinis vienetas security.certcreate.org=Organizacija security.certcreate.city=Miestas ar vietov\u0117 security.certcreate.state=Valstija arba sritis security.certcreate.country=Dviej\u0173 raid\u017ei\u0173 \u0161alies kodas security.certcreate.ok=Sukurti security.certcreate.cancel=Atsisakyti security.certcreate.createok=Sertifikatas sukurtas s\u0117kmingai security.certcreate.createfail=Nepavyko sukurti sertifikato ConfigView.section.plugins.webui=Swing tinklin\u0117 s\u0105saja ConfigView.section.plugins.xml_http_if=XML/HTTP s\u0105saja webui.passwordenable=\u012ejungti slapta\u017eod\u012f webui.user=Naudotojas webui.password=Slapta\u017eodis webui.port=Prievadas (*) webui.protocol=Protokolas (*) webui.homepage=Pradinis puslapis (*) webui.rootdir=\u0160akninis katalogas (*) webui.rootres=\u0160akninis resursas (*) webui.mode=Re\u017eimas (*) webui.mode.info=Re\u017eimas gali b\u016bti\n\t"full"\t= visi veiksmai galimi (numatytas)\n\t"view"\t= tik \u017ei\u016br\u0117ti (bet galima reguliuoti atnaujinimo da\u017enum\u0105) webui.access=Prieiga (*) webui.access.info=Prieiga gali b\u016bti\n\t"local"\t= galima jungtis tik i\u0161 vietinio kompiuterio\n\t"all"\t= prieiga neribojama (numatyta)\n\tIP\t= pvz., 192.168.0.2\t\t\ttik vienas Ip\n\tIP1-IP2\t= pvz., 192.168.0.1-192.168.0.255\tIP intervalas GeneralView.label.maxdownloadspeed=Did\u017e. atsiuntimas Security.keystore.corrupt=Nepavyko \u012fkelti rakt\u0173 saugyklos '%1', pra\u0161ome j\u0105 i\u0161trinti ir perkurti/i\u0161 naujo importuoti sertifikatus Security.keystore.empty=Rakt\u0173 saugykla tu\u0161\u010dia. Pra\u0161ome sukurti pasira\u0161yt\u0105 sertifikat\u0105 (\u017ei\u016br\u0117ti \u012erankiai->Nustatymai->Saugumas) arba importuoti egzistuojant\u012f \u012f '%1' webui.restart.info=Parametr\u0173 pa\u017eym\u0117t\u0173 (*) keitimas reikalauja programos perkrovimo GeneralView.label.maxdownloadspeed.tooltip=Did\u017e. atsiuntimo greitis [0: neribojama] ConfigView.section.UPnP=U\u012eiD upnp.enable=\u012ejungti U\u012eiD upnp.info=Universalus \u012ejunk ir Dirbk (U\u012eiD) leid\u017eia automati\u0161kai pa\u017eym\u0117ti prievadus mar\u0161rutizatoriuose, kurie palaiko U\u012eiD. upnp.mapping.dataport=\u012eeinantis Siunt\u0117jo duomen\u0173 prievadas upnp.mapping.tcptrackerport=TCP Trackerio prievadas upnp.mapping.udptrackerport=UDP Trackerio prievadas upnp.alert.differenthost=U\u012eiD: \u017dym\u0117jimas '%1' yra rezervuotas '%2' - pra\u0161ome i\u0161sirinkti kit\u0105 prievad\u0105 upnp.alert.mappingok=U\u012eiD: \u017dym\u0117jimas '%1' padarytas upnp.alert.mappingfailed=U\u012eiD: \u017dym\u0117jimas '%1' nepavyko upnp.alertsuccess=Prane\u0161ti apie s\u0117kmingus \u017eym\u0117jimus upnp.alert.lostdevice=U\u012eiD: Prarastas ry\u0161ys su '%1' U\u012eiD \u012frenginyje '%2' upnp.grabports=\u017dym\u0117ti prievadus, net jei valdomi kit\u0173 kompiuteri\u0173 upnp.refresh.label=Atnaujinti \u017eym\u0117jimus upnp.refresh.button=Atnaujinti upnp.alert.mappinggrabbed=U\u012eiD: \u017dym\u0117jimas '%1' padarytas - perimtas i\u0161 '%2' upnp.mapping.tcpssltrackerport=TCP SSL Trackerio prievadas upnp.alertothermappings=Prane\u0161ti apie prievadus, valdomus kit\u0173 kompiuteri\u0173 upnp.alertdeviceproblems=Prane\u0161ti apie U\u012eiD \u012frenginio problemas upnp.trace_to_log=I\u0161vesti vis\u0105 derinimo informacij\u0105 \u012f registr\u0105 upnp.wiki_link=Vuze Wiki puslapis apie U\u012eiD ConfigView.pluginlist.coreplugins=\u0160ie standartiniai intarpai yra \u012fkelti: Peers.column.DLedFromOthers=I\u0161 kit\u0173 Peers.column.DLedFromOthers.info=Atsi\u0173st\u0173 duomen\u0173 kiekis, parsi\u0173stas i\u0161 kit\u0173, kol susijungta su Jumis Peers.column.UpDownRatio=I\u0161s:Ats Peers.column.UpDownRatio.info=Siunt\u0117jo "I\u0161si\u0173sta:Atsi\u0173sta" santykis Peers.column.UpRatio=I\u0161s. santykis Peers.column.UpRatio.info=Siunt\u0117jo "I\u0161si\u0173sta i\u0161 J\u016bs\u0173:I\u0161si\u0173sta i\u0161 kit\u0173" santykis upnp.releasemappings=Atsisakyti \u017eym\u0117jim\u0173 u\u017edarant webui.upnpenable=\u012ejungti U\u012eiD \u0161iam prievadui (*) ConfigView.section.file.friendly.hashchecking=Draugi\u0161kas rakt\u0173 tikrinimas ConfigView.section.file.friendly.hashchecking.tooltip=\u0160iek tiek l\u0117tesnis, bet ma\u017eiau \u012ftemptas procesoriui/sistemai, dali\u0173 rakt\u0173 tikrinimo re\u017eimas. ConfigView.section.tracker.seedretention=Daugiausia Skleid\u0117j\u0173 i\u0161saugoma Torrentui [0: neribojama] ConfigView.section.tracker.seedretention.info=Pastaba: I\u0161siuntimo statistika bus prarasta nei\u0161saugotiems Skleid\u0117jams ConfigView.section.tracker.port=Numatytas Trackerio HTTP prievadas ConfigView.section.tracker.sslport=Numatytas Trackerio HTTPS prievadas ConfigView.section.tracker.publicenable.info=Tai leid\u017eia kitiems kurti Torrentus, kurie naudoja J\u016bs\u0173 Tracker\u012f\nnors J\u016bs ir netiekiate/neskelbiate j\u0173 Button.clear=Valyti MainWindow.IPs.tooltip=Paskutinis filtro atnaujinimas: %1\nIP filtr\u0173 kiekis - Blokuot\u0173/u\u017edraust\u0173/blog\u0173 IP adres\u0173 skai\u010dius \u0161i\u0105 sesij\u0105.\nSpustel\u0117kite dukart informacijai su\u017einoti. ConfigView.section.ipfilter.list.banned=buvo u\u017edraustas ConfigView.section.ipfilter.list.baddata=siunt\u0117 blogus duomenis: \u012fvyki\u0173 = Button.reset=Atstatyti ConfigView.section.ipfilter.bannedinfo=IP, kurie siunt\u0117 blogus duomenis - u\u017edraud\u017eiami, jei vir\u0161ija limit\u0105 ConfigView.section.ipfilter.blockedinfo=IP, kurie buvo u\u017edrausti d\u0117l IP filtr\u0173 download.removerules.name=\u0160alinimo taisykl\u0117s download.removerules.unauthorised.info=Neleistini Torrentai yra tie, kuri\u0173 prane\u0161imo atsakymai turi arba "not authoris(z)ed", arba "unauthoris(z)ed" "klaidos atsakyme" download.removerules.unauthorised=Automati\u0161kai \u0161alinti neleistinus Torrentus download.removerules.unauthorised.seedingonly=\tTik jei Skleid\u017eiama download.removerules.removed.ok=Automatinis Torrento '%1' \u0161alinimas pavyko. Tai Torrent\u0173 \u0161alinimo taisykli\u0173 pasekm\u0117. download.removerules.updatetorrents=\u0160alinti Vuze atnaujinimo Torrentus, kai reikalinga grupei ConfigView.label.defaultstarttorrentsstopped=Pagal numatym\u0105 prid\u0117ti naujus Torrentus sustabdytus ConfigView.section.server.enableudp=\u012ejungti UDP Trackerio klient\u0173 protokol\u0105 upnp.mapping.dataportudp=UDP Trackerio klient\u0173 prievadas ConfigView.section.file.decoder.showlax=Rodyti ma\u017eiau tik\u0117tinus kodavimus ConfigView.section.file.decoder.showall=Atsi\u017evelgti \u012f visus galimus kodavimus MainWindow.status.updowndetails.tooltip=Atsiuntimo/i\u0161siuntimo grei\u010di\u0173 informacija\nnustatymai - keisti de\u0161iniu klavi\u0161u, statistika - dvigubas paspaudimas TrackerClient.announce.warningmessage='%1' Trackeris gr\u0105\u017eino persp\u0117jim\u0105 '%2' ConfigView.section.tracker.natcheckenable=Tikrinti 'klausymosi prievado' sujungiamum\u0105 ir prane\u0161ti apie klaidas Siunt\u0117jams ConfigView.section.tracker.publishenabledetails=Skelbti vis\u0105 Torrento informacij\u0105 ConfigView.section.tracker.publishenablepeerdetails=Skelbti Siunt\u0117j\u0173 duomenis MyTrackerView.badnat=Netinkamas NAT MyTrackerView.badnat.info=Skleid\u0117jai/Siunt\u0117jai, kurie nei\u0161laik\u0117 NAT tikrinimo, jei \u012fjungta ConfigView.section.tracker.natchecktimeout=Tikrinimo laikas (sek.) ConfigView.section.file.perf.cache.enable=\u012ejungti disko spartina\u010di\u0105j\u0105 atmintin\u0119 ConfigView.section.file.perf.cache.size=Spartinan\u010diosios atmintin\u0117s dydis (%1) #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=&Siuntimai MainWindow.menu.transfers.startalltransfers=P&rad\u0117ti visus MainWindow.menu.transfers.stopalltransfers=St&abdyti visus MainWindow.menu.transfers.pausetransfers=Pris&tabdyti MainWindow.menu.transfers.resumetransfers=&T\u0119sti ConfigView.label.experimental.osx.kernel.panic.fix=Eksperimentin\u0117 'kernelio panikos' pataisa dviprocesorin\u0117ms OSX sistemoms [reikia perkrauti] SystemTray.menu.pausetransfers=Pristabdyti siuntimus SystemTray.menu.resumetransfers=T\u0119sti siuntimus ConfigView.section.file.truncate.too.large=Suma\u017einti per didelius egzistuojan\u010dius failus ConfigView.section.file.perf.cache.trace=Sekti spartinan\u010diosios atmintin\u0117s operacijas diagnostiniais tikslais ConfigView.section.interface.enabletray=\u012ejungti sistemin\u0119 juostel\u0119 [reikia perkrauti] PeerManager.status.error=Klaida Stats.title.full=Statistika TransferStatsView.title.full=Siuntimai CacheView.title.full=Spartinan\u010dioji atmintin\u0117 CacheView.general.size=Dydis CacheView.general.inUse=Naudojama CacheView.general.title=Spartinan\u010diosios atmintin\u0117s informacija CacheView.reads.title=\u012e/I skaitymai CacheView.reads.fromFile=I\u0161 failo CacheView.reads.fromCache=I\u0161 spart. atm. CacheView.reads.hits=Pataikymai CacheView.writes.title=\u012e/I ra\u0161ymai CacheView.writes.toCache=\u012e spart. atm. CacheView.writes.toFile=\u012e fail\u0105 CacheView.writes.hits=I\u0161saugota CacheView.speeds.title=Duomen\u0173 perdavimo greitis CacheView.speeds.reads=Skaitymai CacheView.speeds.writes=Ra\u0161ymai CacheView.speeds.fromCache=I\u0161/\u012e spart. atm. CacheView.speeds.fromFile=I\u0161/\u012e fail\u0105 CacheView.reads.#=Skai\u010dius CacheView.reads.amount=Dydis CacheView.reads.avgsize=Vid. dydis openUrl.referrer=Nurodan\u010dio puslapio URL: openUrl.referrer.info=Reikia tik puslapiams, kurie tai tikrina ConfigView.label.maxuploadspeedseeding=Alternatyvus greitis, kai Skleid\u017eiama ConfigView.label.transfer.ignorepeerports=Ignoruoti Siunt\u0117jus su \u0161iais prievadais (atskirti ';', pvz., 0;25) ConfigView.section.proxy.enable_socks.peer=\u012ejungti tarpin\u012f server\u012f ry\u0161iui tarp Siunt\u0117j\u0173 (tik i\u0161einantiems susijungimams) [reikia perkrauti] ConfigView.section.proxy.peer.informtracker=Informuoti Tracker\u012f apie apribojimus ConfigView.section.proxy.socks.version=SOCKS versija PiecesView.legend.written=\u012era\u0161yta PiecesView.legend.requested=Papra\u0161yta PiecesView.legend.downloaded=Atsi\u0173sta, laukiama ra\u0161ymo PiecesView.legend.incache=Duomenys yra spart. atm. PiecesView.typeItem.0=L\u0117ta PiecesView.typeItem.1=Greita PiecesView.type=Tipas Security.jar.tools_not_found=JAR pasira\u0161ymas nes\u0117kmingas - 'tools.jar' nerastas %1. Informacijos ie\u0161kokite \u012erankiai->Nustatymai->Saugumas. Security.jar.signfail=JAR pasira\u0161ymas nes\u0117kmingas - %1 ConfigView.section.security.toolsinfo=Pasira\u0161yti JAR failai yra naudojami kai kuri\u0173 intarp\u0173 palaikymui, pavyzd\u017eiui, Swing tinklinei s\u0105sajai (kai tai nustatyta).\nNorint pasira\u0161yti JAR failus b\u016btina tur\u0117ti prieig\u0105 prie 'tools.jar' failo, kuris gaunamas kartu su Sun JDK (ne JRE) \u012fdiegimu.\nJei \u012fdieg\u0117te tik JRE, pra\u0161ome \u012fdiegti JDK.\nVuze paprastai suras fail\u0105 u\u017e jus, ta\u010diau, jei nepavyko, galite nustatyti katalog\u0105 \u010dia. ConfigView.section.security.toolsdir=Katalogas su 'tools.jar' ConfigView.section.security.choosetoolssavedir=I\u0161rinkite aplank\u0105, kuriame yra 'tools.jar' authenticator.torrent=Torrentas ConfigView.section.proxy.peer.same=Naudoti tuos pa\u010dius tarpinio serverio nustatymus ir Trackerio, ir Siunt\u0117j\u0173 ry\u0161iui ConfigView.section.connection.network.max.simultaneous.connect.attempts=Daugiausia vienalaiki\u0173 i\u0161einan\u010di\u0173 susijungim\u0173 bandym\u0173 ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Did\u017eiausias skai\u010dius i\u0161einan\u010di\u0173 susijungim\u0173 Vuze tur\u0117t\u0173 m\u0117ginti bet kuriuo laiku.\n\u012esp\u0117jimas: WindowsXP Service Pack 2 (SP2) primeta visai sistemai 10 vienalaiki\u0173 susijungim\u0173 bandym\u0173 limit\u0105.\nNumatytas limitas yra 8. ConfigView.section.file.perf.cache.size.explain=Spartinan\u010dioji atmintin\u0117 yra naudojama skaitymo i\u0161/ra\u0161ymo \u012f disk\u0105 suma\u017einimui. Tur\u0117tum\u0117te laikyti \u0161\u012f dyd\u012f ma\u017eiausiai %1 ma\u017eesn\u012f u\u017e did\u017eiausi\u0105 VM dyd\u012f, nebent J\u016bs naudojate java parametr\u0105 '-XX:MaxDirectMemorySize' atminties kiekiui nurodyti, prieinam\u0105 spartinan\u010diajai atmintinei ir tinklo \u012e/I naudojimui. Dabartinis did\u017eiausias VM dydis yra %2. Nor\u0117dami tai pakeisti, \u017ei\u016br\u0117kite 'MemoryUsage' wiki esan\u010dioje %3. Neprotingi nustatymai bus 'out of memory' klaid\u0173 prie\u017eastis. Daugiau nei 32MB ke\u0161as grei\u010diausiai yra pernelyg didelis. MyTorrentsView.menu.setSpeed.unlimit=Neriboti MyTorrentsView.menu.setSpeed.unlimited=Neribojamas MyTorrentsView.menu.setSpeed.disable=I\u0161jungti i\u0161siuntim\u0105 MyTorrentsView.menu.setSpeed.disabled=I\u0161jungta MyTorrentsView.menu.setSpeed.in=- MyTorrentsView.menu.setSpeed.slots=lizdai po GeneralView.label.maxuploadspeed=Did\u017e. i\u0161s. GeneralView.label.maxuploadspeed.tooltip=Did\u017eiausias i\u0161siuntimo greitis [0: neribojama] MyTorrents.items.UpSpeedLimit.disabled=Nei\u0161siuntin\u0117ti MyTorrents.items.UpSpeedLimit.unlimited=Neribojamas TableColumn.header.maxupspeed=Did\u017e. i\u0161s. greitis TableColumn.header.maxupspeed.info=Did\u017e. i\u0161s. greitis Torrentui ConfigView.section.file.perf.cache.enable.write=Naudoti spartinan\u010di\u0105j\u0105 atmintin\u0119 atsiun\u010diamiems duomenims taip suma\u017einant disko ra\u0161ymus ir skaitymus dali\u0173 tikrinimui ConfigView.section.file.perf.cache.enable.read=Vykdyti skaitymus-pirmyn disko skaitymams suma\u017einti i\u0161siun\u010diant ConfigView.section.tracker.separatepeerids=Naudoti skirtingus Siunt\u0117jo tapatumus Trackerio ir duomen\u0173 susijungimams ConfigView.section.tracker.separatepeerids.info=Padidina anonimi\u0161kum\u0105 jei atsiun\u010diama/Skleid\u017eiama,\nkai naudojamas neanonimi\u0161kas Trackerio susijungimas ConfigView.section.interface.wavlocation=Garso failo vieta ConfigView.section.interface.wavlocation.info=I\u0161rinkite .wav fail\u0105 arba palikite tu\u0161\u010di\u0105 numatytam garsui ConfigView.section.tracker.server=Serveris ConfigView.section.tracker.client=Klientas ConfigView.section.tracker.client.connecttimeout=Susijungimo laikas (sek.) ConfigView.section.tracker.client.readtimeout=Skaitymo laikas (sek.) MainWindow.menu.tools=\u012era&nkiai FilesView.path=Kelias FilesView.fullpath=Rodyti vis\u0105 keli\u0105 FilesView.remaining=Liko dali\u0173 TableColumn.header.trackername=Trackerio vardas TableColumn.header.trackername.info=Trackerio vardas pagal prane\u0161imo URL ConfigView.group.override=Rankiniai nustatymai ConfigView.section.file.perf.cache.notsmallerthan=Nekelti \u012f spartinan\u010di\u0105j\u0105 atmintin\u0119 fail\u0173, ma\u017eesni\u0173 nei (%1) PeersView.menu.blockupload=Blokuoti i\u0161siuntim\u0105 PeersView.menu.kickandban=Atjungti ir drausti PeersView.menu.kickandban.reason=Siunt\u0117jas u\u017edraustas (rank.) PeersView.state=B\u016bsena PeersView.state.info=Siunt\u0117jo sujungimo b\u016bsena PeersView.state.pending=Laukiama PeersView.state.connecting=Jungiamasi PeersView.state.handshake=Laukiama pasisveikinimo PeersView.state.established=Viskas \u017einoma ConfigView.section.tracker.processinglimits=Apdorojimo apribojimai ConfigView.section.tracker.maxgettime=Did\u017e. laikas GET apdorojimui (sek.) [0: neribojama] ConfigView.section.tracker.maxgettime.info=Naudojama prane\u0161imams ir s\u0105rankoms ConfigView.section.tracker.maxposttimemultiplier=GET laiko daugiklis POST apdorojimui [0: neribojama] ConfigView.section.tracker.maxposttimemultiplier.info=Naudojama \u012fk\u0117limams ir i\u0161siuntimams ConfigView.section.tracker.maxthreads=Daugiausia vienalaiki\u0173 u\u017eklaus\u0173 DownloadManager.error.operationcancancelled=Operacija nutraukta Torrent.create.progress.cancelled=Operacija nutraukta sharing.progress.cancel=Atsisakyti wizard.maketorrents.autoopen=Baigus atidaryti Torrent\u0105 Skleidimui ConfigView.section.sharing.rescanenable=\u012ejungti periodin\u0119 vie\u0161ini\u0173 ap\u017ei\u016br\u0105 pasikeitimams aptikti ConfigView.section.sharing.rescanperiod=Ap\u017ei\u016bros periodas (sek.) ConfigView.section.connection.advanced=I\u0161pl\u0117stiniai ry\u0161io nustatymai ConfigView.section.connection.advanced.mtu=Linijos did\u017eiausias perdavimo vienetas (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Did\u017eiausias paketo dydis, kuris gali b\u016bti persiun\u010diamas tinklu viename kadre.\nVuze naudoja MTU-40 (MSS) i\u0161siuntimo paket\u0173 naudingajai apkrovai optimizuoti.\nRekomenduojamos reik\u0161m\u0117s:\n 576 - Modeminiui ry\u0161iui\n1492 - PPPoE pla\u010diajuos\u010diui ry\u0161iui\n1500 - Ethernet, DSL ir kabeliniui pla\u010diajuos\u010diui ry\u0161iui ConfigView.section.connection.advanced.SO_RCVBUF=Jungties SO_RCVBUF dydis [0: naudoti OS numatyt\u0105] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Nustato standartin\u0119 jungties SO_RCVBUF reik\u0161m\u0119 (baitais), tai yra TCP pri\u0117mino lango dyd\u012f ir mast\u0105.\nVuze pagal numatym\u0105 jos nenustato, tai rei\u0161kia, kad yra panaudojami OS numatymai.\nPASTABA: Linux dvigubina duot\u0105 reik\u0161m\u0119. ConfigView.section.connection.advanced.SO_SNDBUF=Jungties SO_SNDBUF dydis [0: naudoti OS numatyt\u0105] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Nustato standartin\u0119 jungties SO_SNDBUF reik\u0161m\u0119 (baitais), tai yra TCP siuntimo lango dyd\u012f.\nVuze pagal numatym\u0105 jos nenustato, tai rei\u0161kia, kad yra panaudojami OS numatymai.\nPASTABA: Linux dvigubina duot\u0105 reik\u0161m\u0119. ConfigView.section.interface.confirm_torrent_removal=Rodyti patvirtinimo dialog\u0105 \u0161alinant Torrent\u0105 ConfigView.section.interface.confirm_torrent_removal.tooltip=Patvirtinti, kai \u0161alinamas Torrentas i\u0161 Mano Torrent\u0173 lango. MyTorrentsView.confirm_torrent_removal=Ar tikrai norite \u0161alinti?\n TableColumn.header.seed_to_peer_ratio=Skleid\u0117jai:Siunt\u0117jai TableColumn.header.seed_to_peer_ratio.info=Visos grup\u0117s Skleid\u0117j\u0173:Siunt\u0117j\u0173 santykis PeersView.connected_time=Susijungta laiko PeersView.connected_time.info=Visas susijungimo su Siunt\u0117ju laikas ConfigView.section.interface.display.add_torrents_silently=Prid\u0117ti Torrentus tyliai ConfigView.section.interface.display.add_torrents_silently.tooltip=Prid\u0117ti Torrent\u0173 atsiuntimus neaktyvuojant pagrindinio Vuze lango. TableColumn.header.maxdownspeed=Did\u017e. ats. greitis TableColumn.header.maxdownspeed.info=Did\u017eiausias atsiuntimo greitis Torrentui PeersGraphicView.title=Grup\u0117 ConfigView.section.tracker.passwordwebhttpsonly=Leisti prisijungti tik per HTTPS TableColumn.header.torrentpath=Torrento vieta TableColumn.header.torrentpath.info=Torrento buvimo vieta diske ConfigView.section.sharing.torrentcomment=Komentaras sukurtiems Torrentams ConfigView.label.copyanddeleteratherthanmove=Kopijuoti ir i\u0161trinti original\u0105, o ne perkelti viena operacija - gali pad\u0117ti i\u0161vengti duomen\u0173 praradimo kai kuriose fail\u0173 sistemose ConfigView.label.openstatsonstart=Paleidus atidaryti statistik\u0105 swt.install.window.title=Vuze intarp\u0173 dieg\u0117jas swt.install.window.ok=Diegti swt.install.window.header=\u0160ie komponentai buvo pasirinkti diegimui: swt.uninstall.window.title=Vuze intarp\u0173 \u0161alintojas swt.uninstall.window.ok=\u0160alinti swt.uninstall.window.header=\u0160ie komponentai buvo pasirinkti \u0161alinimui: installPluginsWizard.title=Intarp\u0173 diegimas installPluginsWizard.mode.title=Pra\u0161ome pasirinkti diegimo metod\u0105 installPluginsWizard.mode.list=Pagal s\u0105ra\u0161\u0105 i\u0161 sourceforge.net installPluginsWizard.list.title=Intarp\u0173 s\u0105ra\u0161as installPluginsWizard.list.loading=Pra\u0161ome palaukti kol bus \u012fkeltas intarp\u0173 s\u0105ra\u0161as. installPluginsWizard.list.loaded=Pra\u0161ome pasirinkti intarpus, kuriuos norite \u012fdiegti. installPluginsWizard.list.name=Pavadinimas installPluginsWizard.list.version=Versija installPluginsWizard.list.description=Intarpo apra\u0161ymas installPluginsWizard.finish.title=Vyksta diegimas installPluginsWizard.finish.explanation=Pa\u017eym\u0117ti intarpai bus \u012fdiegti naudojant atnaujinimo asistent\u0105.\n\nPra\u0161ome b\u016bti kantr\u016bs, gali u\u017etrukti kol pasirodys.\n\nProgreso ataskaitai gauti, spauskite dukart kair\u0117je b\u016bsenos juostos pus\u0117je. installPluginsWizard.details.loading=Apra\u0161ymas \u012fkeliamas, pra\u0161ome palaukti... installPluginsWizard.mode.file=I\u0161 failo installPluginsWizard.installMode.title=Pasirinkite diegimo tip\u0105 installPluginsWizard.installMode.user=Diegti intarp\u0105(us) tik jums installPluginsWizard.installMode.shared=Diegti intarp\u0105(us) visiems naudotojams installPluginsWizard.file.title=Pra\u0161ome parinkti intrap\u0105, kur\u012f norite \u012fdiegti installPluginsWizard.file.file=Failas: installPluginsWizard.file.invalidfile=Failas n\u0117ra tinkamas Vuze intarpas. installPluginsWizard.file.browse=Nar\u0161yti... uninstallPluginsWizard.title=Intarp\u0173 \u0161alinimas uninstallPluginsWizard.list.title=\u012ediegt\u0173 intarp\u0173 s\u0105ra\u0161as uninstallPluginsWizard.list.loaded=Pra\u0161ome parinkti intarpus, kuriuos norite \u0161alinti. installPluginsWizard.list.nullversion=Be versiojos uninstallPluginsWizard.finish.title=Vyksta \u0161alinimas uninstallPluginsWizard.finish.explanation=Parinkti intarpai bus pa\u0161alinti naudojant atnaujinimo asistent\u0105. MainWindow.menu.plugins.installPlugins=Diegimo vedlys... MainWindow.menu.plugins.uninstallPlugins=\u0160alinimo vedlys... ConfigView.section.ipfilter.totalIPs=%1 IP blokuota i\u0161 viso, tai yra %2 interneto. update.instance.install=Tikrinamas diegimas update.instance.uninstall=Tikrinamas \u0161alinimas update.instance.update=Ie\u0161koma atnaujinim\u0173 MainWindow.status.update.tooltip=Spauskite dukart progreso informacijai gauti updater.progress.window.title=Dabartin\u0117s diegimo u\u017eduotys updater.progress.window.info=Spauskite 'Nutraukti' visoms neatliktoms u\u017eduotims nutraukti Button.abort=Nutraukti ConfigView.section.ipfilter.enablebanning=Blokuoti Siunt\u0117jus, kurie nuolat siun\u010dia blogus duomenis Network.alert.acceptfail=Kelis kartus i\u0161 eil\u0117s nepavyko prisijungti %1 prievadu, %2 - apdorojimas nutrauktas. Pra\u0161ome patikrinti ugniasien\u0117s nustatymus \u0161iam prievadaui, kad \u012fsitikintum\u0117te, jog juo galimas i\u0161orinis prisijungimas. MyShares.column.category=Kategorija UpdateWindow.restartLater=Perkrauti v\u0117liau MainWindow.menu.file.restart=Perkrauti Vuze MainWindow.dialog.restartconfirmation.title=Perkrauti Vuze MainWindow.dialog.restartconfirmation.text=Ar tikrai norite perkrauti Vuze deletetorrent.message1=J\u016bs norite i\u0161trinti TORRENT\u0104 susiet\u0105 su:\n deletetorrent.message2=\nAr tikrai norite t\u0119sti? ConfigView.label.prioritizemostcompletedfiles=Dar labiau didinti auk\u0161to prioriteto fail\u0173 prioritet\u0105 atsi\u017evelgiant \u012f u\u017ebaigtum\u0105 ir failo dyd\u012f splash.plugin.init=Ruo\u0161iamas intarpas ConfigView.section.style.osx_small_fonts=Naudoti smulkius \u0161riftus [reikia perkrauti] ConfigView.section.tracker.tcpnonblocking=Naudoti neblokuojam\u0105 \u012e/I Trackerio TCP apdorojimui. \u0160io nustatymo \u012fjungimas reikalauja, kad trackerio puslapis naudot\u0173 kit\u0105 prievad\u0105. Eksperimentinis! ConfigView.section.tracker.nonblocking=Neblokavimo nustatymai ConfigView.section.tracker.nonblockingconcmax=Daugiausia vienalaiki\u0173 susijungim\u0173 [0: neribojama] MyTorrentsView.menu.exportmenu=Eksportuoti MyTorrentsView.menu.exporttorrent=Torrent\u0105... ConfigView.group.scrape=S\u0105ranka ConfigView.section.tracker.client.scrapeinfo=S\u0105rankos i\u0161jungimas deaktyvuos daugel\u012f Torrent\u0173 eil\u0117s taisykli\u0173, nes jos remiasi grup\u0117s informacija, gauta s\u0105rankos metu. ConfigView.section.tracker.client.scrapeenable=\u012ejungti s\u0105rank\u0105 ConfigView.section.tracker.client.scrapestoppedenable=Vykdyti s\u0105rank\u0105 neaktyviems Torrentams Scrape.status.disabled=S\u0105ranka i\u0161jungta MyTorrentsView.menu.explore=Rodyti fail\u0105 MyTorrentsView.menu.explore._mac=Rodyti fail\u0173 nar\u0161ykl\u0117je MyTorrentsView.menu.explore._windows=Rodyti tinklo nar\u0161ykl\u0117je wizard.maketorrents.autohost=Tiekti Torrent\u0105 \u012ftaisytame Trackeryje ConfigView.label.overrideip=Keisti Trackerio prane\u0161imo IP adresas(ai) - jei daugiau, nei vienam tinklui, atskirkite kabliata\u0161kiais ConfigView.label.overrideip.tooltip=Informuoti Tracker\u012f apie kit\u0105 IP adres\u0105(us), negu tas i\u0161 kurio gaunami paketai. Nor\u0117dami nenaudoti palikite nenustatyt\u0105. ConfigView.section.connection.group.networks=Tinklai ConfigView.section.connection.group.networks.info=I\u0161rinkite numatytus leid\u017eiamus tinklus Siunt\u0117jas-Siunt\u0117jas duomen\u0173 perdavimui ConfigView.section.connection.networks.prompt=Klausti pasirinkimo, kai pridedamas atsisiuntimas su anonimi\u0161ku Trackeriu ConfigView.section.connection.networks.Public=Vie\u0161asis IP tinklas (ne anoniminis) ConfigView.section.connection.networks.I2P=I2P tinklas ConfigView.section.connection.networks.Tor=The Onion Router (Tor) tinklas TableColumn.header.networks=Tinklai TableColumn.header.networks.info=Leid\u017eiami tinklai Siunt\u0117jas-Siunt\u0117jas duomen\u0173 perdavimui Scrape.status.networkdisabled=Tinklas ne\u012fjungtas ConfigView.section.tracker.server.group.networks=Tinklai ConfigView.section.tracker.server.group.networks.info=I\u0161rinkite tinklus, i\u0161 kuri\u0173 Trackeris priims Siunt\u0117j\u0173 u\u017eklausas window.networkselection.title=Tinklo pasirinkimas window.networkselection.info=\u017demiau nurodytas Torrentas turi Tracker\u012f(ius), kurie palaiko \u0161iuos tinklus.\nI\u0161rinkite, kuriuos \u012fjungti Trackerio ir Siunt\u0117j\u0173 komunikacijai.\nJei tai yra anoniminis Trakeris palaikantis vie\u0161us klientus, \u012fjunkite abu - anonimin\u012f ir vie\u0161\u0105 tinklus.\nVie\u0161o tinklo \u012fjungimas turi ai\u0161kias pasekmes - anonimi\u0161kumo pa\u0161alinim\u0105! window.networkselection.description=Torrentas: plugins.basicview.clear=Valyti ConfigView.section.connection.group.peersources=Siunt\u0117j\u0173 \u0161altiniai ConfigView.section.connection.group.peersources.info=I\u0161rinkite numatytus leid\u017eiamus \u0161altinius Siunt\u0117j\u0173 susijungimams ConfigView.section.connection.peersource.Tracker=I\u0161 Trackerio ConfigView.section.connection.peersource.DHT=Decentralizuotas Trackeris ConfigView.section.connection.peersource.PeerExchange=Gauti i\u0161 kito Siunt\u0117jo ConfigView.section.connection.peersource.Plugin=Prid\u0117ti intarpo ConfigView.section.connection.peersource.Incoming=\u012eeinantys susijungimai PeersView.source=\u0160altinis PeersView.source.info=Siunt\u0117jo \u0161altinis TableColumn.header.peersources=Siunt\u0117j\u0173 \u0161altiniai TableColumn.header.peersources.info=Siunt\u0117j\u0173 \u0161altiniai leid\u017eiami siunt\u0117j\u0173 susijungimams wizard.tracker.dht=Decentralizuotas (tik Vuze klientams) MyTorrentsView.menu.advancedmenu=I\u0161pl\u0117stinis meniu MyTorrentsView.menu.networks=Tinklai MyTorrentsView.menu.peersource=Siunt\u0117j\u0173 \u0161altiniai ConfigView.section.sharing.permitdht=Leisti decentralizuot\u0105 Tracker\u012f, kai Trackeris nepasiekiamas ConfigView.section.sharing.protocol=Protokolas vie\u0161intiems resursams PeersView.Messaging=Komunikacija PeersView.Messaging.info=Palaiko i\u0161pl\u0117stin\u012f komunikacijos API. ConfigView.label.queue.newseedsmovetop=Perkelti neseniai atsi\u0173stus Torrentus \u012f skleidimo eil\u0117s prad\u017ei\u0105 ConfigView.label.seeding.firstPriority.ignore.info=\u017dinokite, kad \u0161i\u0173 taisykli\u0173 naudojimas gali sustabdyti Torrent\u0105\ni\u0161 karto, kai tik jo atsiuntimas baigtas. ConfigView.label.seeding.firstPriority.ignore=Ignoruoti Pirmo prioriteto taisykles kai: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrento Skleid\u0117j\u0173:Siunt\u0117j\u0173 santykis didesnis u\u017e ConfigView.label.seeding.firstPriority.ignore0Peer=Torrentas be Siunt\u0117j\u0173 ConfigView.section.tracker.sendjavaversionandos=Si\u0173sti Javos versij\u0105 ir OS pavadinim\u0105 MagnetPlugin.contextmenu.exporturi=Kopijuoti Magnet nuorod\u0105 \u012f i\u0161karpin\u0119 ConfigView.section.plugins.dht=Paskirstyta DB dht.info=\u0160is intarpas palaiko decentralizuot\u0105 skelbim\u0105, be kit\u0173 dalyk\u0173, jo i\u0161jungimas suma\u017eins J\u016bs\u0173 atsisiuntimo galimybes dht.enabled=\u012ejungti paskirstyt\u0105 duomen\u0173 baz\u0119 dht.portdefault=Naudoti numatyt\u0105 prievad\u0105 dht.port=Duomen\u0173 baz\u0117s UDP prievadas dht.execute.command=Diagnostin\u0117 komanda dht.execute.info=Spauskite komandai \u012fvykdyti dht.execute=Vykdyti dht.logging=\u012ejungti veiklos registravim\u0105 ConfigView.section.plugins.dhttracker=Paskirstytas Trackeris dhttracker.tracknormalwhenoffline=Steb\u0117ti tik normalius Torrentus, kai j\u0173 Trackeris nepasiekiamas ConfigView.section.file.nativedelete._mac=Trinant failus naudoti \u0160iuk\u0161lin\u0119 ConfigView.section.file.nativedelete._windows=Perkelti i\u0161trintus failus \u012f \u0161iuk\u0161liad\u0117\u017e\u0119 ConfigView.section.logging.generatediagnostics=Generuoti ConfigView.section.logging.generatediagnostics.info=Generuoti diagnostin\u0119 informacij\u0105 ir kopijuoti j\u0105 \u012f i\u0161karpin\u0119 bei registracijos fail\u0105, jei nustatytas ConfigView.section.sharing.privatetorrent=Privatus Torrentas - Siunt\u0117jus priimti tik i\u0161 Trackerio MainWindow.menu.tools.nattest=&NAT / ugniasien\u0117s testas Button.apply=Vykdyti Button.close=U\u017edaryti window.welcome.title=Sveiki \u012fsijung\u0119 Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Leidimo pastabos (ang.) dht.reseed.label=Paprastai n\u0117ra b\u016btina i\u0161 naujo paskleisti paskirstytos duomen\u0173 baz\u0117s. Jeigu kontakt\u0173 skai\u010dius yra ma\u017eas, tai gali b\u016bti panaudota vientisumui atkurti.\nPalikite tu\u0161\u010di\u0105, nor\u0117dami atlikti \u012fk\u0117l\u0105 i\u0161 prisijungusi\u0173 Siunt\u0117j\u0173 arba \u012fveskite IP ir prievad\u0105, nor\u0117dami atlikti \u012fk\u0117l\u0105 i\u0161 \u017einomo Siunt\u0117jo. dht.reseed.group=I\u0161 naujo skleisti dht.reseed.ip=IP adresas dht.reseed.port=Prievadas dht.reseed=I\u0161 naujo skleisti dht.reseed.info=I\u0161 naujo skleisti DB dht.diagnostics.group=Diagnostika DHTView.title.full=Paskirstyta duomen\u0173 baz\u0117 DHTView.title.fullcvs=Paskirstyta duomen\u0173 baz\u0117 CVS DHTView.general.title=Bendra DHTView.general.uptime=Veikimo laikas: DHTView.general.users=Naudotojai: DHTView.general.nodes=Mazgai: DHTView.general.leaves=Lapai: DHTView.general.contacts=Kontaktai: DHTView.general.replacements=Pakaitalai: DHTView.general.live=Veikl\u016bs: DHTView.general.unknown=Ne\u017einomi: DHTView.general.dying=Mir\u0161tantys: DHTView.transport.title=Siuntimo informacija DHTView.transport.packets=Paketai DHTView.transport.bytes=Baitai DHTView.transport.received=Gauta DHTView.transport.sent=I\u0161si\u0173sta DHTView.transport.in=Atsiuntimas: DHTView.transport.out=I\u0161siuntimas: DHTView.operations.title=Veiksm\u0173 informacija DHTView.operations.sent=I\u0161si\u0173sta DHTView.operations.ok=Gerai DHTView.operations.failed=Klaida DHTView.operations.received=Gauta DHTView.operations.findNode=Rasti mazg\u0105 DHTView.operations.findValue=Rasti reik\u0161m\u0119 DHTView.operations.store=I\u0161saugoti DHTView.activity.title=Veikla DHTView.activity.status=B\u016bsena DHTView.activity.status.true=Eil\u0117je DHTView.activity.status.false=Vykdoma DHTView.activity.type=Tipas DHTView.activity.type.1=Vidinis gavimas DHTView.activity.type.2=I\u0161orinis gavimas DHTView.activity.type.3=Vidinis \u012fd\u0117jimas DHTView.activity.type.4=I\u0161orinis \u012fd\u0117jimas DHTView.activity.target=Tikslas DHTView.activity.details=Informacija DHTView.db.title=Duomen\u0173 baz\u0117 DHTView.db.keys=Raktai DHTView.db.values=Reik\u0161m\u0117s DHTView.db.local=Vietiniai DHTView.db.direct=Tiesiogin\u0117s DHTView.db.indirect=Netiesiogin\u0117s MainWindow.dht.status.tooltip=Kai paskirstyta duomen\u0173 baz\u0117 aktyvi, \u010dia rodomas apytikslis prisijungusi\u0173 naudotoj\u0173 skai\u010dius MainWindow.dht.status.disabled=DHT i\u0161jungta MainWindow.dht.status.failed=DHT klaida MainWindow.dht.status.initializing=DHT ruo\u0161iama MainWindow.dht.status.users=%1 naudotojai MainWindow.dht.status.unreachable=DHT u\u017e ugniasien\u0117s MainWindow.dht.status.unreachabletooltip=Atrodo, kad yra problema su Paskirstytos DB prievad\u0173 pa\u017eym\u0117jimu MyTorrentsView.menu.setUpSpeed=Nustatyti i\u0161s. greit\u012f MyTorrentsView.menu.setDownSpeed=Nustatyti ats. greit\u012f ConfigView.section.tracker.client.showwarnings=Rodyti persp\u0117jimo \u017einutes gautas i\u0161 Trackerio dht.advanced=\u012ejungti i\u0161pl\u0117stinius nustatymus dht.advanced.group=I\u0161pl\u0117stiniai nustatymai dht.advanced.label=Taisykite \u0161ias reik\u0161mes tik jei tikrai \u017einote k\u0105 darote dht.override.ip=Keisti i\u0161orin\u012f IP adres\u0105 ConfigView.section.logging.loggerenable=\u012ejungti registravim\u0105 ConfigView.section.ipfilter.blockbanning=Blokuoti 256 adres\u0173 blok\u0105, kai yra u\u017eblokuojama ma\u017eiausiai tiek adres\u0173 bloke MyTrackerView.passive=Pasyvus TableColumn.header.swarm_average_speed=Vidutinis grup\u0117s greitis TableColumn.header.swarm_average_speed.info=Vidutinis Siunt\u0117j\u0173 greitis grup\u0117je TableColumn.header.comment=Komentaras TableColumn.header.comment.info=Naudotojo \u012fvestas atsiuntimo komentaras TableColumn.header.commenticon=Komentaro piktograma TableColumn.header.commenticon.info=Rodo piktogram\u0105, jei atsiuntimas turi naudotojo \u012fvest\u0105 komentar\u0105 MyTrackerView.category=Kategorija MainWindow.menu.file.open.torrentfortracking=Torrent fail\u0105... (tik sekimui) MyTrackerView.date_added=Prid\u0117ta ConfigView.section.tracker.portbackup=Atsarginiai prievadai (atskirti ';') ConfigView.label.playfilespeech=Kalb\u0117ti, kai failas baigtas ConfigView.label.playfilespeech.info=Kalbos servisas dabar geriausiai veikia angl\u0173 kalba ConfigView.label.playfilefinished=Sugroti gars\u0105, kai failas baigtas ConfigView.label.backupconfigfiles=I\u0161saugoti nustatym\u0173 failus atstatymo tikslais ConfigView.section.tracker.client.scrapesingleonly=I\u0161jungti s\u0105rankos apjungim\u0105 Trackeriui (gali pad\u0117ti su Trackeriais, kurie gr\u0105\u017eina klaidas 'URL per ilgas' (414)) dht.ipfilter.log=Registruoti IP filtro pa\u017eeidimus ConfigView.label.seeding.addForSeedingDLCopyCount=Laikyti, kad 'prid\u0117ti Skleidimui' siuntimai jau yra atsiunt\u0119 tiek kopij\u0173 ActivityView.legend.limit=Grei\u010dio limitas ActivityView.legend.achieved=Pasiektas greitis ActivityView.legend.peeraverage=Vidutinis ActivityView.legend.swarmaverage=Grup\u0117s vidutinis ActivityView.legend.trimmed=Nukirpta (ta\u0161keliai) MyTorrentsView.menu.movemenu=Perkelti failus MyTorrentsView.menu.movedata=Perkelti duomen\u0173 failus... MyTorrentsView.menu.movetorrent=Perkelti Torrent fail\u0105... MyTorrentsView.menu.movedata.dialog=I\u0161rinkit\u0119 nauj\u0105 viet\u0105 DHTView.operations.data=Duomenys DHTView.general.reachable=Pasiekiami: ConfigView.label.queue.maxactivetorrentswhenseeding=Daugiausia, kai tik Skleid\u017eiama [0: neribojama] Views.plugins.IRC.title=IRC - Techninis palaikymas Formats.units.alot=Daug!!! ConfigView.section.ipfilter.persistblocking=I\u0161saugoti blokuojam\u0173 IP informacij\u0105 tarp perkrovim\u0173 FilesView.menu.rename=Pervadinti arba i\u0161 naujo nukreipti FilesView.menu.rename_only=Pervadinti FilesView.menu.retarget=I\u0161 naujo nukreipti FilesView.rename.choose.path=Parinkite nauj\u0105 ar egzistuojant\u012f fail\u0105 FilesView.rename.choose.path.dir=Parinkite nauj\u0105 ar egzistuojant\u012f katalog\u0105 FilesView.rename.confirm.delete.title=Patvirtinti trynim\u0105 FilesView.rename.confirm.delete.text=Patvirtinti originalaus failo '%1' trynim\u0105 FilesView.rename.filename.title=Pervadinti fail\u0105 FilesView.rename.filename.text=Parinkite nauj\u0105 failo vard\u0105 ConfigView.section.mode=Re\u017eimas ConfigView.section.mode.title=Naudotojo \u012fgudimas ConfigView.section.mode.beginner=Pradedantysis ConfigView.section.mode.beginner.wiki.definitions=BitTorrent \u017eodynas ConfigView.section.mode.intermediate=Labiau pa\u017eeng\u0119s ConfigView.section.mode.intermediate.wiki.host=Fail\u0173 tiekimas ConfigView.section.mode.intermediate.wiki.publish=Fail\u0173 skelbimas ConfigView.section.mode.advanced=Specialistas ConfigView.section.mode.advanced.wiki.main=Pagrindinis Wiki puslapis ConfigView.section.mode.beginner.text=Viskas, ko reikia Torrent\u0173 siuntimui.\nNaudokite \u0161\u012f re\u017eim\u0105, jei viskas ko norite, tai tvarkyti Torrentus. ConfigView.section.mode.intermediate.text=Prieiga prie Trackerio funkcij\u0173.\nNaudokite \u0161\u012f re\u017eim\u0105, jei viskas ko norite, tai sukurti savo Tracker\u012f ir tiekti/skelbti savo failus. ConfigView.section.mode.advanced.text=Prieiga prie tinklo nustatym\u0173.\nNaudokite \u0161\u012f re\u017eim\u0105, jei \u017einote kas yra MTU ar nesiblokuojantis \u012e/I... Files.column.storagetype=Saugojimo tipas Files.column.fileext=Tipas FileItem.storage.linear=Tiesinis FileItem.storage.compact=Kompakti\u0161kas MessageBoxWindow.rememberdecision=Prisiminti mano sprendim\u0105 ConfigView.section.interface.cleardecisions=Valyti prisimintus dialog\u0173 sprendimus ConfigView.section.interface.cleardecisionsbutton=Valyti ConfigView.section.interface.cleartrackers=I\u0161valyti prisimintus Trackerius ConfigView.section.interface.cleartrackersbutton=Valyti configureWizard.welcome.usermodes=\u0160is naudotojo \u012fgudimo nustatymas apibr\u0117\u0161 rodom\u0173 nustatym\u0173 lyg\u012f (\u012erankiai > Nustatymai). J\u016bs tur\u0117tum\u0117te b\u016bti suinteresuoti teisingai i\u0161sirinkti. FilesView.skip.confirm.delete.text=Sutrumpinti fail\u0105 '%1' vietai atlaisvinti? FilesView.rename.failed.title=Pervadinimas/nukreipimas nepavyko FilesView.rename.failed.text=Operacija nepavyko, tikriausiai d\u0117l neteisingai i\u0161rinkto tikslo diagnostics.log_found=Vuzesaugiai nei\u0161sijung\u0117. Pra\u0161ome pa\u017ei\u016br\u0117ti \u012f diagnostinio registro failus ir apsvarstyti galimyb\u0119 nusi\u0173sti juos Vuze komandai, jei tai buvo programos klaidos pasekm\u0117. Taip pat \u017ei\u016br\u0117kite Wiki (\u017er. Pagalbos meniu), jei 'Vuze dingsta' ManagerItem.paused=Pristabdyta Utils.link.visit=Pra\u0161ome aplankyti ConfigView.section.connection.serverport.wiki=Ger\u0173 prievad\u0173 pasirinkimas ConfigView.section.transfer.speeds.wiki=Geras grei\u010dio nustatymas installPluginsWizard.installMode.info.title=Informacija installPluginsWizard.installMode.info.text=Jums nereikia intarp\u0173, kad Vuze gerai veikt\u0173. Intarpai prideda papildom\u0173 galimybi\u0173 d\u0117l juoko, automatizavimo ar nutolusio valdymo.\nPra\u0161ome atid\u017eiai perskaityti kiekvieno intarpo apra\u0161ym\u0105 prie\u0161 nusprend\u017eiant ar j\u012f \u012fdiegti.\nDauguma intarp\u0173 yra saug\u016bs pabandymui, ta\u010diau neperkraukite programos intarpais, kuri\u0173 nenaudosite. Views.plugins.Distributed.DB.title=Paskirstyta DB Views.plugins.Distributed.Tracker.title=Paskirstytas Trackeris Views.plugins.Plugin.Update.title=Intarp\u0173 atnaujinimas Views.plugins.UPnP.title=U\u012eiD Views.plugins.UPnP.title.tooltip=Universalus \u012ejunk ir Dirbk openUrl.url.info=Palaiko http, https, magnet ir vien tik \u0161e\u0161ioliktain\u012f inforakt\u0105 TableColumn.header.swarm_average_completion=Siunt\u0117jo vidutinis u\u017ebaigtumas TableColumn.header.swarm_average_completion.info=Vidutinis Siunt\u0117j\u0173 u\u017ebaigtumo procentas grup\u0117je GeneralView.label.swarm_average_completion=Vidutinis u\u017ebaigtumas: GeneralView.label.swarm_average_completion.tooltip=Vidutinis Siunt\u0117j\u0173 u\u017ebaigtumo procentas grup\u0117je MainWindow.nat.status.tooltip.unknown=Ugniasien\u0117s/NAT pasiekiamumo b\u016bsena ne\u017einoma (TCP) MainWindow.nat.status.ok=NAT tvarkoje MainWindow.nat.status.tooltip.ok=Pasiekiamumas geras (TCP) MainWindow.nat.status.probok=NAT tvarkoje? MainWindow.nat.status.tooltip.probok=Pasiekiamumas buvo geras, ta\u010diau paskutiniu metu nebuvo \u012feinan\u010di\u0173 TCP susijungim\u0173 MainWindow.nat.status.bad=U\u017e ugniasien\u0117s MainWindow.nat.status.tooltip.bad=Ugniasien\u0117s/NAT (TCP) pasiekiamumo problema. Pagalbos ie\u0161kokite Wiki plugin.installer.recommended.plugin=Rekomenduojamas intarpas - pra\u0161ome per\u017ei\u016br\u0117ti apra\u0161ym\u0105 ir jei reikia \u012fdiegti LoggerView.pause=Pristabdyti registravim\u0105 LoggerView.clear=&I\u0161valyti LoggerView.filter=Filtras LoggerView.filter.uncheckAll=At\u017eym\u0117ti visas kategorijas LoggerView.filter.checkAll=Pa\u017eym\u0117ti visas kategorijas LoggerView.loggingDisabled=Registravimas ne\u012fjungtas. ConfigView.section.logging.log0type=Informacija ConfigView.section.logging.log1type=\u012esp\u0117jimas ConfigView.section.logging.log2type=Klaida ConfigView.section.logging.filter=Filtruoti, kai registruojama \u012f fail\u0105 ConfigView.section.logging.level=Registravimo lygis ConfigView.section.logging.showLogsFor=%1 - rodyti ira\u0161us \u0161ioms kategorijoms: ConfigView.pluginlist.column.loadAtStartup=\u012ekelti paleid\u017eiant ConfigView.pluginlist.column.type=Tipas ConfigView.pluginlist.column.type.perUser=Naudotojo ConfigView.pluginlist.column.type.shared=Vie\u0161as ConfigView.pluginlist.column.type.builtIn=Vidinis ConfigView.pluginlist.column.name=Pavadinimas ConfigView.pluginlist.column.version=Versija ConfigView.pluginlist.column.directory=Katalogas ConfigView.pluginlist.column.isOperational=Veikiantis? PeersView.BlockView.Avail.Have=Abu turite PeersView.BlockView.Avail.NoHave=Siunt\u0117jas turi; J\u016bs ne PeersView.BlockView.NoAvail.Have=J\u016bs turite; Siunt\u0117jas ne PeersView.BlockView.NoAvail.NoHave=Abu neturite PeersView.BlockView.Transfer=Siun\u010diama PeersView.BlockView.NextRequest=Kita u\u017eklausa PeersView.BlockView.title=Dali\u0173 \u017eem\u0117lapis PeersView.BlockView.AvailCount=Pasiekiamumas MyTorrentsView.dialog.NumberError.title=Klaidingas arba neatpa\u017e\u012fstamas skai\u010dius MyTorrentsView.dialog.NumberError.text=\u012evestas skai\u010dius klaidingas arba neatpa\u017e\u012fstamas. MyTorrentsView.menu.manual=&Rankinis... MyTorrentsView.dialog.setSpeed.title=Nustatyti %1 greit\u012f # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=\u012eveskite skai\u010di\u0173 %1 skai\u010diui %2 pakeisti: MyTorrentsView.dialog.setNumber.upload=i\u0161siuntimas MyTorrentsView.dialog.setNumber.download=atsiuntimas MyTorrentsView.dialog.setNumber.inKbps=%1 OpenTorrentWindow.torrentLocation=Torrentai atsiuntimui: OpenTorrentWindow.addFiles.URL=Prid\u0117ti &URL OpenTorrentWindow.addFiles.Folder=Prid\u0117ti &aplank\u0105 OpenTorrentWindow.addFiles.Clipboard=Prid\u0117ti i\u0161 i\u0161ka&rpin\u0117s OpenTorrentWindow.changeDestination=Pervadinti/i\u0161 naujo nukreipti OpenTorrentWindow.fileList=Torrento failai: OpenTorrentWindow.torrentTable.name=Vardas OpenTorrentWindow.torrentTable.saveLocation=I\u0161saugojimo vieta OpenTorrentWindow.fileTable.fileName=Failo vardas OpenTorrentWindow.fileTable.size=Dydis OpenTorrentWindow.fileTable.destinationName=Vietos vardas OpenTorrentWindow.startMode.seeding=Skleid\u017eiamas OpenTorrentWindow.fileList.changeDestination=Pervadinti/i\u0161 naujo nukreipti OpenTorrentWindow.mb.badSize.title=Nesuderinamas failas OpenTorrentWindow.mb.badSize.text='%1' n\u0117ra '%2', tod\u0117l negali b\u016bti naudojamas skleidimui OpenTorrentWindow.mb.alreadyExists.text=Torrentas '%1' buvo prid\u0117tas kaip '%2' OpenTorrentWindow.mb.alreadyExists.title=Torrentas jau egzistuoja OpenTorrentWindow.mb.openError.title=Atidarymo klaida OpenTorrentWindow.mb.openError.text=Nepavyko atidaryti '%1':\n%2 OpenTorrentWindow.torrent.remove=\u0160alinti Torrent\u0105 i\u0161 s\u0105ra\u0161o OpenTorrentWindow.torrent.options=\u0160ie nustatymai bus taikomi auk\u0161\u010diau i\u0161rinktiems Torrentams: OpenTorrentWindow.xOfTotal=(%1 i\u0161 %2) iconBar.open.tooltip=Atidaryti Torrent\u0105(us) LocaleUtil.column.text=Ne\u017einomas tekstas Tracker.tooltip.MultiSupport=\u0160is Trackeris palaiko sud\u0117tines rakt\u0173 s\u0105rankas pageidaujant. Tracker.tooltip.NoMultiSupport=\u0160is Trackeris nepalaiko sud\u0117tin\u0117s rakt\u0173 s\u0105rankos pageidaujant.\nTai nepaveiks J\u016bs\u0173 grei\u010dio, bet padidins Trackerio apkrov\u0105. ConfigView.label.lazybitfield=Naudoti ting\u0173 bit\u0173 lauk\u0105 (padeda skleisti tinkluose, naudojan\u010diuose bit\u0173 lauku paremt\u0105 blokavim\u0105) LoggerView.realtime=Atnaujinti realiu laiku ConfigView.section.file.perf.cache.flushpieces=Ra\u0161yti u\u017ebaigtas dalis \u012f disk\u0105 tuoj pat. Tai suvienodina kreipim\u0105si \u012f disk\u0105, bet gali sukelti daugiau ra\u0161ymo operacij\u0173. ConfigView.section.file.writemblimit=Daugiausia skaitymo u\u017eklaus\u0173 eil\u0117je (%1) ConfigView.section.file.writemblimit.explain=Kai disko ra\u0161ymo greitis yra ma\u017eesnis u\u017e atsiuntimo greit\u012f, \u0161is parametras riboja kiek duomen\u0173 bus eil\u0117je, kol atsiuntimo greitis bus suma\u017eintas. ConfigView.section.file.readmblimit=Daugiausia skaitymo u\u017eklaus\u0173 eil\u0117je (%1) ConfigView.section.file.readmblimit.explain=\u0160is parametras apriboja atmint\u012f, skirt\u0105 laikyti skaitymams, kurie laukia apdorojimo. Button.moveUp=Slinkti a&uk\u0161tyn Button.moveDown=Slinkti \u017e&emyn ConfigView.notAvailableForMode=\u0160i sekcija yra numatyta \u0161iam ar auk\u0161tesniam re\u017eimui - %1. Ji n\u0117ra pasiekiama re\u017eime - %2. health.explain.error=Yra klaida su \u0161iuo Torrentu. \u017di\u016br\u0117kite b\u016bsenos stulpel\u012f arba prane\u0161im\u0105 vir\u0161 klaidos piktogramos. GeneralView.label.trackerscrapeupdate=Trackerio s\u0105ranka PeersView.piece=Dalis PeersView.piece.info=Paskutin\u0117s dalies, pra\u0161ytos i\u0161 siunt\u0117jo nr. PiecesView.priority=Prioritetas PiecesView.priority.info=\u0161ios dalies u\u017ebaigimo prioritetas, ta\u010diau nekreipkite \u012f tai per daug d\u0117mesio PiecesView.speed=Greitis PiecesView.speed.info=L\u0117tesni siunt\u0117jai yra sulaikomi nuo intensyvaus prisid\u0117jimo prie greit\u0173 dali\u0173 TableColumn.header.AvgAvail.info=Dali\u0173 pasiekiamumas padalintas i\u0161 dali\u0173 skai\u010diaus, padalintas i\u0161 susijungim\u0173 skai\u010diaus TableColumn.header.AvgAvail=Vid. pasiek./dalis ConfigView.label.strictfilelocking=U\u017etikrinti i\u0161imtin\u012f ra\u0161ymo \u012f failus blokavim\u0105 tarp Torrent\u0173 MyTorrentsView.menu.rescanfile=Periodi\u0161kai tikrinti nebaigtas dalis MyTorrentsView.menu.clear_resume_data=Valyti prat\u0119simo duomenis Plugin.extseed.name=I\u0161oriniai Skleid\u0117jai Plugin.localtracker.name=LAN siunt\u0117j\u0173 ie\u0161kiklis Plugin.localtracker.info=LAN siunt\u0117j\u0173 ie\u0161iklis leid\u017eia kelioms Vuze kopijoms, esan\u010dioms u\u017e ugniasien\u0117s vietiniame tinkle,\n efektyviai si\u0173stis Torrentus sudarant tarp j\u0173 tiesiogin\u012f ry\u0161\u012f Plugin.localtracker.enable=\u012ejungti LAN siunt\u0117j\u0173 paie\u0161k\u0105 azinstancehandler.alert.portclash=Vietiniame tinkle nustatytas prievad\u0173 konfliktas: %1 yra naudojamas kito Vuze naudotojo, i\u0161rinkite nauj\u0105 atsitiktin\u012f prievad\u0105 \u012feinantiems TCP / UDP susijungimams [tarp %2 ir %3]. ConfigView.section.transfer.lan.tooltip=Specifiniai LAN nustatymai ConfigView.section.transfer.lan.uploadrate=KB/s LAN did\u017eiausias i\u0161siuntimo greitis [0: neribojama] ConfigView.section.transfer.lan.uploadrate.tooltip=Siunt\u0117j\u0173 susijungimai tame pa\u010diame vietiniame tinkle (LAN) turi atskir\u0105 i\u0161siuntimo grei\u010dio lmit\u0105. ConfigView.section.transfer.lan.downloadrate=KB/s LAN did\u017eiausias atsiuntimo greitis [0: neribojama] ConfigView.section.transfer.lan.downloadrate.tooltip=Siunt\u0117j\u0173 susijungimai tame pa\u010diame vietiniame tinkle (LAN) turi atskir\u0105 atsiuntimo grei\u010dio lmit\u0105. TorrentOptionsView.title.short=Nustatymai TorrentOptionsView.title.full=Nustatymai TorrentOptionsView.param.max.peers=Did\u017eiausiais susijungim\u0173 skai\u010dius [0: neribojama] ConfigView.section.connection.encryption.require_encrypted_transport=Reikalauti \u0161ifruoto ry\u0161io kanalo ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Priverstinai naudoti \u0161ifruot\u0105 ry\u0161\u012f su kitais Siunt\u0117jais. ConfigView.section.connection.encryption.min_encryption_level=Ma\u017eiausias \u0161ifravimo lygis ConfigView.section.connection.encryption.min_encryption_level.tooltip=Plain - tik pasisveikinimui\nRC4 - visam srautui\nAuk\u0161tesnis \u0161ifravimo lygis reikalauja dagiau procesoriaus resurs\u0173. Peers.column.Encryption=\u0160ifravimas Peers.column.Encryption.info=Naudojamas \u0161ifravimo lygis ConfigView.section.connection.encryption.encrypt.info=Jei \u0161ifravimas \u012fjungtas, J\u016bs negal\u0117site susijungti su nesuderinamais klientais, nebent \u012fjungsite atsargines priemones. ConfigView.section.connection.encryption.encrypt.info.link=Daugiau informacijos MainWindow.sr.status.tooltip.ok=Dalinimosi santykis %1 geras MainWindow.sr.status.tooltip.poor=Dalinimosi santykis %1 menkas: < 0,9 MainWindow.sr.status.tooltip.bad=Dalinimosi santykis %1 blogas: < 0,5 ConfigView.section.style.status=B\u016bsenos juosta: ConfigView.section.style.status.show_sr=Dalinimosi santykis ConfigView.section.style.status.show_nat=NAT b\u016bsena ConfigView.section.style.status.show_ddb=Paskirstytos DB b\u016bsena ConfigView.section.style.status.show_ipf=IP filtr\u0173 b\u016bsena ConfigView.section.connection.encryption.encrypt.group=Ry\u0161io \u0161ifravimas/maskavimas ConfigView.section.connection.encryption.encrypt.fallback_info=Bet kurios atsargin\u0117s priemon\u0117s \u012fjungimas leis susijungimus su nesuderinamais klientais, BET ry\u0161ys su jais nebus \u0161ifruotas ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Leisti ne\u0161ifruotus i\u0161einan\u010dius susijungimus, jei nepavyksta naudoti \u0161ifruot\u0173 susijungim\u0173 ConfigView.section.connection.encryption.encrypt.fallback_incoming=Leisti ne\u0161ifruotus \u012feinan\u010dius susijungimus ConfigView.section.connection.encryption=Ry\u0161io \u0161ifravimas upnp.selectedinterfaces=I\u0161rinktos s\u0105sajos (atskirtos ';', pvz., eth0;eth1) [tu\u0161\u010dia: visos] ConfigView.section.style.defaultSortOrder=Numatyta rikiavimo tvarka ConfigView.section.style.defaultSortOrder.desc=Ma\u017e\u0117janti ConfigView.section.style.defaultSortOrder.asc=Did\u0117janti ConfigView.section.style.defaultSortOrder.flip=Prie\u0161inga ankstesniam rikiavimui LoggerView.autoscroll=Automati\u0161kai slinkti Button.selectAll=I\u0161rinkti visus Button.markSelected=Pa\u017eym\u0117ti i\u0161rinktus Button.unmarkSelected=At\u017eym\u0117ti i\u0161rinktus plugins.basicview.config=Nustatymai TorrentOptionsView.param.max.uploads=Did\u017eiausias i\u0161siuntimo lizd\u0173 skai\u010dius [ma\u017eiausiai: 2] MyTorrentsView.dialog.setPosition.title=Nustatyti pozicij\u0105 MyTorrentsView.dialog.setPosition.text=Keisti pa\u017eym\u0117t\u0173 torrent\u0173 pozicij\u0105 \u012f \u012fvest\u0105: MyTorrentsView.menu.reposition.manual=Keisti pozicij\u0105.. ConfigView.section.connection.advanced.info.link=Daugiau informacijos ConfigView.section.connection.advanced.socket.group=Lizd\u0173 nustatymai ConfigView.section.connection.advanced.bind_port=Priri\u0161ti prie lokalaus prievado [0: i\u0161jungta] ConfigView.section.connection.advanced.bind_port.tooltip=I\u0161einantys lizd\u0173 susijungimai bus lokaliai suri\u0161ti su nurodytu prievadu.\n\u012ejungimas gali pad\u0117ti i\u0161spr\u0119sti NAT mar\u0161rutizatoriaus nestabilum\u0105. ConfigView.section.proxy.group.tracker=Trackerio susijungimai ConfigView.section.proxy.group.peer=Siunt\u0117j\u0173 susijungimai Pieces.column.Requested=U\u017eklausta Pieces.column.Requested.info=Rodo, ar daugiau dalies u\u017eklaus\u0173 gali b\u016bti padaryta ar ne (*) ConfigView.label.maxuploadsseeding=Alternatyvus numatytas, kai Skleid\u017eiama MyTorrentsView.filter=Filtras: popup.error.hideall=Sl\u0117pti visus ConfigView.section.style.dataStatsOnly=Rodyti tik duomen\u0173 statistik\u0105 (sl\u0117pti protokolo statistik\u0105) ConfigView.section.style.separateProtDataStats=Duomen\u0173 ir protokolo statistik\u0105 rodyti atskirai kaip 'duomenys (protokolas)' MyTorrentsView.dialog.setFilter.title=Modifikuoti filtr\u0105 MyTorrentsView.dialog.setFilter.text=Sekcija "%1" bus filtruojama pagal \u012fvest\u0105 tekst\u0105. Naudokite simbol\u012f | kelioms fraz\u0117ms filtruoti. MyTorrentsView.filter.tooltip=Ctrl+X kei\u010dia paie\u0161kos re\u017eim\u0105 tarp RegEx ir normalaus.\nNaudokite simbol\u012f | kelioms fraz\u0117ms filtruoti. MyTorrentsView.clearFilter.tooltip=Valyti filtr\u0105 MyTorrentsView.menu.filter=Filtras... ConfigView.section.file.resume.recheck.all=Po l\u016b\u017eimo-perkrovimo pertikrinti vis\u0105 fail\u0105 baigtoms dalims rasti (kitu atveju tikrinamos tik paskutin\u0117s aktyvios dalys) ConfigureWizard.language.choose=I\u0161sirinkite kalb\u0105 i\u0161 apa\u010dioje esan\u010dio s\u0105ra\u0161o: popup.closing.in=Automati\u0161kai u\u017edaroma po %1 sek. popup.more.waiting=yra \u017einu\u010di\u0173: %1.. # > 2402 popup.download.finished="%1" atsiuntimas baigtas. popup.file.finished="%1" atsiuntimas baigtas. Plugin.localtracker.autoadd.info=Automati\u0161kai prid\u0117ti \u0161iuos vietinius Siunt\u0117jus [';' atskirti adresai, pvz., 1.2.3.4] Plugin.localtracker.autoadd=Tiksl\u016bs siunt\u0117jai Plugin.localtracker.networks.info=Laikyti, kad \u0161ie tinklai yra vietiniai [';' atskirti tinklai, pvz., 145.227.*.*] Plugin.localtracker.networks=Vietiniai tinklai MainWindow.menu.view.plugins.logViews=Registravimo vaizdai SpeedView.stats.autospeed=Automatinis i\u0161siuntimo greitis SpeedView.stats.autospeed.disabled=\u0160i savyb\u0117 yra arba i\u0161jungta (reikia DHT), arba nenaudojama (i\u0161siuntimo greitis parinktas) SpeedView.stats.idlePing=Neutralus ping: SpeedView.stats.maxPing=Maks. ping: SpeedView.stats.currentPing=Dabartinis ping: SpeedView.stats.maxUp=Maks. i\u0161s. greitis: ConfigView.pluginlist.unloadSelected=I\u0161kelti pa\u017eym\u0117tus ConfigView.pluginlist.scan=Ie\u0161koti nauj\u0173 intarp\u0173 ConfigView.section.transfer.autospeed=Auto-greitis (klasikinis) ConfigView.section.transfer.autospeed.tooltip=Auto-grei\u010dio nustatymai ConfigView.section.transfer.autospeed.info=Auto-greitis automati\u0161kai reguliuoja i\u0161siuntimo greit\u012f, kad b\u016bt\u0173 i\u0161vengta tinklo ry\u0161io perkrovos.\n\n\u0160ie limitai bus taikomi tik tada, kai automatinis i\u0161siuntimo greitis yra \u012fjungtas. Tam reikia, kad b\u016bt\u0173 \u012fjungta paskirstyta DB. ConfigView.section.transfer.autospeed.minupload=%1 ma\u017eiausiais i\u0161siuntimo greitis ConfigView.section.transfer.autospeed.minupload.tooltip=I\u0161siuntimo greitis nebus automati\u0161kai suma\u017eintas \u017eemiau \u0161io limito ConfigView.section.transfer.autospeed.maxupload=%1 maksimalus i\u0161siuntimo greitis [0: neribojama] ConfigView.section.transfer.autospeed.maxupload.tooltip=I\u0161siuntimo greitis nebus automati\u0161kai padidintas vir\u0161 \u0161io limito ConfigView.section.transfer.autospeed.chokeping=Slopinimo ping laikas [milisekund\u0117mis] ConfigView.section.transfer.autospeed.chokeping.tooltip=Ping laikai, vir\u0161yjantys \u0161i\u0105 reik\u0161m\u0119, bus laikomi tinklo perkrovos indikatoriumi ConfigView.section.transfer.autospeed.enableauto=\u012ejungti, kai atsiun\u010diama ir Skleid\u017eiama ConfigView.section.transfer.autospeed.enableautoseeding=\u012ejungti, kai tik Sklaid\u017eiama ConfigView.pluginlist.column.unloadable=I\u0161keliami ConfigView.section.transfer.lan.enable=\u012ejungti atskirus limitus LAN susijungimams Plugin.localtracker.wellknownlocals=Automati\u0161kai \u012ftraukti loopback/link/site vietinius tinklus (192.168 ir pan.) TableColumn.header.filesdone=Baigti failai TableColumn.header.filesdone.info=Baigti failai/Baigta vis\u0173 *ar* nepraleist\u0173 fail\u0173 (Baigti failai)/I\u0161 viso nepraleist\u0173 fail\u0173 (I\u0161 viso fail\u0173) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=laukiama PDB inicializacijos... MagnetPlugin.report.searching=ie\u0161koma... MagnetPlugin.report.found=rasta %1 MagnetPlugin.report.alive=%1 yra gyvas MagnetPlugin.report.dead=%1 yra mir\u0119s MagnetPlugin.report.tunnel=jungiama su %1 MagnetPlugin.report.downloading=siun\u010diama i\u0161 %1 MagnetPlugin.report.error=klaida %1 MagnetURLHandler.report.no_sources=Torrentui nerasta \u0161altini\u0173 MagnetURLHandler.report.torrent_size=Torrento dydis: %1 MagnetURLHandler.report.percent=baigta: %1% MagnetURLHandler.report.error=klaida %1 DHTTransport.report.request_all=pra\u0161oma viso siuntimo i\u0161 %1 DHTTransport.report.received_bit=atsi\u0173sta %1 iki %2 i\u0161 %3 DHTTransport.report.complete=baigta DHTTransport.report.timeout=baig\u0117si laikas, negauta atsakymo i\u0161 %1 DHTTransport.report.rerequest_all=i\u0161 naujo pra\u0161oma viso siuntimo i\u0161 %1 DHTTransport.report.rerequest_bit=i\u0161 naujo pra\u0161oma %1 iki %2 i\u0161 %3 DHTTransport.report.timeout_some=baig\u0117si laikas, %1 paket\u0173 atsi\u0173sta i\u0161 %2, bet nebaigta DHTTransport.report.sending=siun\u010diami duomenys DHTTransport.report.resending=persiun\u010diami duomenys DHTTransport.report.send_complete=siuntimas baigtas DHTTransport.report.send_timeout=siuntimui baig\u0117si laiko limitas ConfigView.section.transfer.autospeed.enabledebug=Registruoti derinimo informacij\u0105 TableColumn.header.date_added=Prid\u0117jimo data TableColumn.header.date_added.info=Data, kada Torrentas buvo prid\u0117tas ConfigView.section.file.hashchecking.smallestfirst=Pirmiausia pertikrinti ma\u017eiausius atsiuntimus platform.win32.baddll.info=Vuze aptiko '%1'. Tai yra '%2' dalis kelianti problem\u0173, toki\u0173 kaip programos l\u016b\u017eimas ir didelis procesoriaus apkrovimas. Jei pasirei\u0161kia tokie simptomai, pra\u0161ome pa\u0161alinti \u0161i\u0105 programin\u0119 \u012frang\u0105 arba nustatykite, kad ji neveikt\u0173 Azureus. upnp.ignorebaddevices=Ignoruoti \u012frenginius, kurie atsako nekorekti\u0161kai upnp.ignorebaddevices.info=Dabar ignoruojami \u012frenginiai: %1 upnp.ignorebaddevices.reset=I\u0161valyti ignoruot\u0173 \u012frengini\u0173 s\u0105ra\u0161\u0105 upnp.ignorebaddevices.reset.action=I\u0161valyti upnp.ignorebaddevices.alert=U\u012eiD \u012frenginys esantis %1 yra ignoruojamas d\u0117l pasikartojan\u010di\u0173 problem\u0173. \u017di\u016br\u0117kite U\u012eiD intarpo konfiguracij\u0105 nuostatoms susijusioms su \u0161iuo veiksmu. TorrentOptionsView.param.max.uploads.when.busy=KB/s did\u017e. i\u0161siuntimo greitis, kai pasiektas globalus i\u0161siuntimo greitis [0: i\u0161jungta] UpdateMonitor.messagebox.verification.failed.title=Diegimo tikrinimas nepavyko UpdateMonitor.messagebox.verification.failed.text='%1' tikrinimas nepavyko: %2 UpdateMonitor.messagebox.accept.unverified.title=Sutikti su nepatikrintu diegimu UpdateMonitor.messagebox.accept.unverified.text='%1' - nepavyko patikrinti kaip oficialaus Vuze intarpo.\nNetur\u0117tum\u0117te t\u0119sti toki\u0173 intarp\u0173 diegimo.\nT\u0119sti diegim\u0105? FileView.BlockView.title=Failo dalys FileView.BlockView.Done=Baigta FileView.BlockView.Skipped=Praleista FileView.BlockView.Active=Aktyvi FileView.BlockView.Outstanding=Nebaigta ConfigView.label.tcplistenport=TCP klausymosi prievadas ConfigView.label.udplistenport=UDP klausymosi prievadas upnp.portchange.alert=\u0160ie prievadai buvo pakesti, norint i\u0161vengti U\u012eiD \u012frengini\u0173 problem\u0173: %1 [anks\u010diau=%2] %3 [anks\u010diau=%4] ConfigView.section.proxy.username.info=Jei tarpinis serveris reikalauja atpa\u017einimo, kai jis n\u0117ra nurodytas, naudokite tekst\u0105 "" kaip naudotoj\u0105 ConfigView.label.maxuploadswhenbusymin=Did\u017e. i\u0161siuntimo greitis Torrentui, kai taimeris u\u017eimtas [sek.] MainWindow.menu.help.debug=Generuoti derinimo informacij\u0105 (l\u016b\u017eimo registravimas) DownloadManager.error.badsize=Neteisingas dydis natpmp.info=NAT-PMP yra Apple alternatyva U\u012eiD ir yra palaikoma nauj\u0173 Airport stoteli\u0173\n\nPastaba, U\u012eiD turi b\u016bti \u012fjungtas norint \u012fjungti NAT-PMP, nes NAT-PMP \u012frenginys yra laikomas specialiu U\u012eiD \u012frenginiu natpmp.enable=\u012ejungti (kad veikt\u0173, taip pat turi b\u016bti \u012fjungta Airport nustatymuose) ConfigView.section.tracker.host.addurls=U\u017etikrinti, kad \u0161io Trackerio URL yra tiekiamuose Torrentuose ConfigView.filter=\u012fveskite filtro tekst\u0105 ConfigView.section.files.move=Baigt\u0173 fail\u0173 perk\u0117limas ConfigView.section.file.defaultdir.section=Numatyto katalogo nustatymai ConfigView.section.file.defaultdir.auto=Automati\u0161kai si\u0173sti \u012f numatyt\u0105 katalog\u0105 (neklausti) ConfigView.section.file.defaultdir.bestguess=Naudoti geriausi\u0105 sp\u0117jim\u0105, kai parenkamas numatytas katalogas ConfigView.section.file.defaultdir.ask=Numatytas katalogas: ConfigView.section.file.defaultdir.lastused=Pakeisti numatyt\u0105 katalog\u0105 \u012f paskutinio i\u0161saugojimo katalog\u0105 ConfigView.section.torrent.decoding=Simboli\u0173 kodavimas ConfigView.section.logging.udptransport=\u012ejungti i\u0161sam\u0173 UDP transporto sekim\u0105 Tracker.announce.ignorePeerSeed=Ignoruoti Siunt\u0117j\u0173/Skleid\u0117j\u0173 skai\u010di\u0173. %1 ConfigView.section.connection.encryption.use_crypto_port=Naudoti 'cryptoport' Trackerio i\u0161pl\u0117tim\u0105 paprastiems \u012feinantiems susijungimams i\u0161vengti. Kai kurie Trackeriai to nepalaiko ir prane\u0161a apie tai klaidomis "Invalid Port" arba "Illegal Argument" TorrentOptionsView.param.reset.to.default=Atstatyti nustatymus \u012f numatytas reik\u0161mes TorrentOptionsView.param.reset.button=Atstatyti natpmp.routeraddress=Stotel\u0117s adresas [tu\u0161\u010dia: automatinis] ConfigView.section.style.disableAlertSliding=I\u0161jungti slydimo animacij\u0105/visada vir\u0161uje stili\u0173 persp\u0117jim\u0173 \u017einut\u0117ms ConfigView.section.transfer.autospeed.maxinc=%1 maksimalus padid\u0117jimas per cikl\u0105 ConfigView.section.transfer.autospeed.maxdec=%1 maksimalus suma\u017e\u0117jimas per cikl\u0105 ConfigView.section.transfer.autospeed.enabledownadj=\u012ejungti atsiuntimo grei\u010dio reguliavim\u0105 ConfigView.section.transfer.autospeed.downadjratio=Atsiuntimo:I\u0161siuntimo grei\u010dio santykis (pvz., 2.0 -> atsiuntimo greitis dvigubai didesnis u\u017e i\u0161siuntimo) ConfigView.section.transfer.autospeed.latencyfactor=Koeficientas, naudojamas susieti v\u0117lavimo poky\u010dius su grei\u010dio poky\u010diais (didesni skai\u010diai ma\u017eina jautrum\u0105) ConfigView.section.transfer.autospeed.reset=Atstatyti i\u0161pl\u0117stines reik\u0161mes ConfigView.section.transfer.autospeed.reset.button=Atstatyti PeerColumn.activationCount=Siunt\u0117jai, bandantys prisijungti: %1 TableColumn.header.timesincedownload.info=Pra\u0117j\u0119s laikas nuo paskutinio Torrento duomen\u0173 atsiuntimo TableColumn.header.timesincedownload=Pask. ats. TableColumn.header.timesinceupload.info=Pra\u0117j\u0119s laikas nuo paskutinio Torrento duomen\u0173 i\u0161siuntimo TableColumn.header.timesinceupload=Pask. i\u0161s. PeersView.incomingreqcount=\u012e. u\u017ekl. PeersView.incomingreqcount.info=Siunt\u0117jo padaryt\u0173 \u012feinan\u010di\u0173 u\u017eklaus\u0173 skai\u010dius PeersView.outgoingreqcount=I\u0161. u\u017ekl. PeersView.outgoingreqcount.info=Siunt\u0117jui padaryt\u0173 i\u0161einan\u010di\u0173 u\u017eklaus\u0173 skai\u010dius upnp.mapping.trackerclientudp=UDP Trackerio kliento prievadas upnp.mapping.dhtudp=Paskirstyta DB ConfigView.section.connection.nondata.udp.same=Naudoti t\u0105 pat\u012f UDP prievad\u0105 paskirstytai DB ir UDP Trackeriui ConfigView.section.connection.tcp.enable=\u012ejungti TCP ConfigView.section.connection.udp.enable=\u012ejungti UDP ConfigView.section.style.showiconbar=Rodyti \u012frankin\u0119 MainWindow.menu.view.iconbar=\u012erankin\u0117 MyTorrentsView.menu.rename=Pervadinti MyTorrentsView.menu.rename.displayed=Pakeisti rodom\u0105 vard\u0105 MyTorrentsView.menu.rename.save_path=Pervadinti i\u0161saugojimo keli\u0105 MyTorrentsView.menu.rename.displayed.enter.title=Pakeisti rodom\u0105 vard\u0105 MyTorrentsView.menu.rename.displayed.enter.message=\u012era\u0161ykite nauj\u0105 vard\u0105, kuris bus rodomas \u0161iam atsiuntimui.\nJei joks tekstas ne\u012fvestas, bus panaudotas originalus vardas. MyTorrentsView.menu.edit_comment=Redaguoti komentar\u0105 MyTorrentsView.menu.edit_comment.enter.title=Redaguoti komentar\u0105 MyTorrentsView.menu.edit_comment.enter.message=\u012eveskite komentar\u0105 \u0161iam atsiuntimui UIDebugGenerator.messageask.title=Derinimo informacijos generatorius UIDebugGenerator.messageask.text=Pra\u0161ome apra\u0161yti rikt\u0105, apie kur\u012f prane\u0161ate UIDebugGenerator.complete.title=Derinimo informacijos generavimas baigtas. UIDebugGenerator.complete.text=Pra\u0161ome i\u0161si\u0173sti fail\u0105 '%1'.\n\nSpauskite Gerai langui su failu atidaryti. ConfigView.section.style.showProgramIcon=Rodyti programos piktogram\u0105 vardo stulpelyje ConfigView.section.style.showProgramIcon.tooltip=Kad pakeitimai \u012fsigaliot\u0173, gali reik\u0117ti i\u0161 naujo atidaryti lang\u0105 swt.alert.cant.update=SWT biblioteka \u012fkelta i\u0161 "%3" negali b\u016bti automati\u0161kai atnaujinta i\u0161 %1 \u012f %2 (turi b\u016bti \u012fkelta i\u0161 "%4"). Pra\u0161ome \u017ei\u016br\u0117ti wiki i\u0161samesnei informacijai gauti. authenticator.savepassword=Prisiminti mano slapta\u017eod\u012f ConfigView.section.security.clearpasswords=I\u0161valyti atsimintus slapta\u017eod\u017eius ConfigView.section.security.clearpasswords.button=I\u0161valyti Content.alert.notuploaded.title=I\u0161siuntimas nebaigtas Content.alert.notuploaded.text='%1' i\u0161siuntimas nebaigtas. Jei J\u016bs %2 dabar, tai \u017emon\u0117s negal\u0117s baigti atsisi\u0173sti J\u016bs\u0173 paskelbto darbo.\n\nAr tikrai norite tai padaryti? Content.alert.notuploaded.multi.title=I\u0161siuntimas nebaigtas Content.alert.notuploaded.multi.text=%1 J\u016bs\u0173 paskelbto turinio yra nevisi\u0161kai paskleistas. Jei J\u016bs %2 dabar, tai \u017emon\u0117s negal\u0117s baigti atsisi\u0173sti J\u016bs\u0173 paskelbto darbo. Ar tikrai norite tai padaryti?\n\nNevisi\u0161kai paskleistas turinys:\n%3 Content.alert.notuploaded.stop=sustabdysite Content.alert.notuploaded.quit=i\u0161jungsite Vuze TorrentInfoView.torrent.encoding=Torrento kodavimas TorrentInfoView.columns='Mano Torrent\u0173' vaizdo stulpeliai progress.window.title=Operacija vykdoma progress.window.msg.filemove=Pra\u0161ome palaukti, kol baigsis failo perk\u0117limas/pervadinimas ConfigView.label.popup.timestamp=Prid\u0117ti laik\u0105 i\u0161kylan\u010diuose persp\u0117jimuose ConfigView.label.popup.autohide=Automati\u0161kai sl\u0117pti ne klaidos i\u0161kylan\u010dius persp\u0117jimus po x sekund\u017ei\u0173 (0 i\u0161jungia automatin\u012f sl\u0117pim\u0105) ConfigView.label.popup.suppress_alerts=Nusl\u0117pti persp\u0117jimus ConfigView.label.popup.use_message_boxes=Naudoti i\u0161kylan\u010dias persp\u0117jimo \u017einutes vietoj standartini\u0173 i\u0161kylan\u010di\u0173 persp\u0117jim\u0173. ConfigView.label.popup.show=Rodo visus iki \u0161iol registruotus persp\u0117jimus (jei yra) ConfigView.label.popup.show.button=Rodyti ConfigView.label.please.visit.here=Daugiau informacijos rasite \u010dia ConfigView.section.ipfilter.enable.descriptionCache=Saugoti IP apra\u0161ymus laikiname faile ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Kai i\u0161jungta, apra\u0161ymai nebus prisimenami OpenTorrentWindow.filesInfo=%1 i\u0161 %2 bus atsi\u0173sta. ConfigView.label.openmytorrents=Paleidus atidaryti Mano Torrentus ConfigView.section.style.DNDalwaysInIncomplete=Visada rodyti Torrentus su failais, pa\u017eym\u0117tais 'Nesi\u0173sti', nebaigt\u0173 Torrent\u0173 dalyje Mano Torrentuose OpenTorrentWindow.mb.noGlobalDestDir.title=Duomen\u0173 i\u0161saugojimo katalogas nerastas OpenTorrentWindow.mb.noGlobalDestDir.text=Duomen\u0173 i\u0161saugojimo katalogas '%1' neegzistuoja arba yra klaidingas. OpenTorrentWindow.mb.noDestDir.title=Duomen\u0173 i\u0161saugojimo katalogas nerastas OpenTorrentWindow.mb.noDestDir.text=Duomen\u0173 i\u0161saugojimo katalogas '%1' Torrentui '%2' neegzistuoja arba yra klaidingas. OpenTorrentWindow.mb.notValid.title=Atidaryti Torrent\u0105 OpenTorrentWindow.mb.notValid.text=Nepavyko atidaryti Torrento '%1'. Jei atidarin\u0117jate skleidimui, \u012fsitikinkite, kad Torrento duomenys egzistuoja. OpenTorrentWindow.mb.notTorrent.title=Atidaryti Torrent\u0105 OpenTorrentWindow.mb.notTorrent.text=Nepavyko atidaryti '%1'. Neatrodo, kad tai .torrent failas.\n\nKai kurie gauti duomenys:\n%2 ConfigView.label.pause.downloads.on.exit=I\u0161einant pristabdyti atsiuntimus ConfigView.label.resume.downloads.on.start=T\u0119sti pristabdytus atsiuntimus po paleidimo ir pradini\u0173 nustatym\u0173 \u012fk\u0117limo UIDebugGenerator.message.cancel.title=Derinimo informacijos generavimas at\u0161auktas UIDebugGenerator.message.cancel.text=J\u016bs neived\u0117te rikto, apie kur\u012f m\u0117ginate prane\u0161ti, apra\u0161ymo. \u0160is riktas gali b\u016bti Jums akivaizdus, bet be apra\u0161ymo, mes galime apie j\u012f tik sp\u0117ti.\n\nDerinimo informacijos generavimas buvo at\u0161auktas. ConfigView.section.connection.group.http.info=HTTP Skleidimo palaikymas ConfigView.section.connection.http.enable=\u012ejungti ConfigView.section.connection.http.port=\u012eeinan\u010dio prievado numeris ConfigView.section.connection.http.portoverride=Keisti trackerio HTTP prievad\u0105 [0: nekeisti] window.update.noupdates.title=Atnaujinim\u0173 tikrinimo rezultatai window.update.noupdates.text=\u0160iuo metu n\u0117ra joki\u0173 nauj\u0173 atnaujinim\u0173.\n\nSveikiname! ConfigView.label.mindownloads=Ma\u017eiausiai vienalaiki\u0173 atsiuntim\u0173 UI.cannot_submit_blank_text=J\u016bs turite \u012fvesti reik\u0161m\u0119. crypto.alert.as.warning=Yra \u017einoma, kad tinklas '%1' primeta duomen\u0173 srauto ribojimus atsiuntimo grei\u010diui suma\u017einti. Ry\u0161io \u0161ifravimas buvo automati\u0161kai \u012fjungtas - j\u012f galima i\u0161jungti/pakeisti nustatymuose. ConfigView.section.interface.alerts=Persp\u0117jimai ConfigView.label.popupdownloadadded=Parodyti persp\u0117jim\u0105, kai atsiuntimas prid\u0117tas popup.download.added="%1" buvo prid\u0117tas \u012f atsiuntim\u0173 s\u0105ra\u0161\u0105. MessageBoxWindow.nomoreprompting=Daugiau nebeklausti TorrentOptionsView.param.max.seeds=Did\u017eiausiais susijungim\u0173 skai\u010dius su Skleid\u0117jais [0: susijungim\u0173 skai\u010dius] TorrentOptionsView.param.alternative.value.enable=Alternatyvi reik\u0161m\u0117 skleid\u017eiant ConfigView.section.proxy.check.on.start=Paleid\u017eiant tikrinti tarpinio serverio b\u016bsen\u0105 TransferStatsView.legend.pingaverage=Vidurkis TransferStatsView.legend.ping1=Tikslas 1 TransferStatsView.legend.ping2=Tikslas 2 TransferStatsView.legend.ping3=Tikslas 3 ConfigView.section.interface.enabletray._mac=\u012ejungti b\u016bsenos juostos piktogram\u0105 [reikia perkrauti] ConfigView.label.closetotray._mac='U\u017edaryti' suskleid\u017eia \u012f b\u016bsenos juostos piktogram\u0105 ConfigView.label.minimizetotray._mac='Sutraukti' suskleid\u017eia \u012f b\u016bsenos juostos piktogram\u0105 OpenTorrentWindow.mb.existingFiles.title=Failas jau egzistuoja! OpenTorrentWindow.mb.existingFiles.text=Kai kurie failai jau egzistuoja i\u0161rinktame aplanke:\n\n%1\nJei t\u0119site, Vuze patikrins auk\u0161\u010diau i\u0161vardintus failus ir juos pakeis, jei reik\u0117s. splash.unloadingTorrents=I\u0161keliami Torrentai splash.unloadingTorrent=I\u0161keliamas Torrentas ConfigView.section.file.defaultdir.autorename=Automati\u0161kai pervadinti Torrento duomenis, jei failai kelyje atrodo kitaip ConfigView.section.file.defaultdir.autorename.tooltip=Tai neleid\u017eia vienam Torrentui pakeisti kito Torrento fail\u0173, kai fail\u0173 vardai vienodi alert.raised.at.close=(Paskutinio Vuze u\u017edarymo \u017einut\u0117) Plugin.trackerpeerauth.name=Trackerio Siunt\u0117j\u0173 pripa\u017einimas Plugin.trackerpeerauth.info=\u0160is intarpas dirba su Trackeriais, kad patikrint\u0173 jog Siunt\u0117jai yra teis\u0117ti grup\u0117s nariai Peers.column.maxupspeed=Did\u017e. i\u0161s. greitis Peers.column.maxdownspeed=Did\u017e. ats. greitis MyTorrents.items.DownSpeedLimit.disabled=Neatsiuntin\u0117ti upnp.selectedaddresses=Adresai (atskirti ';', prie\u0161d\u0117lis '-'=drausti, '+' =leisti) [tu\u0161\u010dia: visi] upnp.alert.multipledevice.warning=Aptikti keli U\u012eiD \u012frenginiai - patikrinkite, ar visiems \u012frenginiams reikalingas prievad\u0173 \u017eym\u0117jimas (\u017ei\u016br\u0117kite U\u012eiD registr\u0105 ir nustatymus) UpdateMonitor.messagebox.restart.title=Programos atnaujinimas UpdateMonitor.messagebox.restart.text=Vuze k\u0105 tik baig\u0117 si\u0173sti svarb\u0173 atnaujinim\u0105 ir dabar privalo b\u016bti perkrautas, kad atnaujinimas b\u016bt\u0173 \u012fdiegtas. PiecesView.BlockView.Have=Turite PiecesView.BlockView.NoHave=Neturite PiecesView.BlockView.Header=stulpeli\u0173: %1, eilu\u010di\u0173: %2, dali\u0173: %3 ConfigView.section.update.autodownload=Automati\u0161kai atsi\u0173sti atnaujinimus ir klausti, kai pasiruo\u0161ta diegimui Peers.column.peer_id=Siunt\u0117jo ID Peers.column.peer_id.info=Siunt\u0117jo ID perskaitoma forma Peers.column.peer_byte_id=Siunt\u0117jo ID Peers.column.peer_byte_id.info=Siunt\u0117jo ID baitine forma dht.warn.user=\u012esp\u0117ti apie galimas NAT/prievad\u0173 \u017eym\u0117jimo klaidas ConfigView.label.openbar.incomplete=Siuntim\u0173 juosta: automati\u0161kai atidaryti siuntimus ConfigView.label.openbar.complete=automati\u0161kai atidaryti skleidimus ConfigView.section.transfer.autospeed.forcemin=Priverstinis i\u0161siuntimo greitis, kai pradedamas susijungimas (%1) MainWindow.menu.tools.speedtest=Grei\u010dio testas... speedtest.wizard.title=Grei\u010dio testas speedtest.wizard.run=Vykdyti grei\u010dio test\u0105 speedtest.wizard.test.mode.updown=atsiuntimas ir i\u0161siuntimas speedtest.wizard.test.mode.up=i\u0161siuntimas speedtest.wizard.test.mode.down=atsiuntimas SpeedTestWizard.test.panel.currinfo=BitTorrent pralaidumo testavimas. SpeedTestWizard.test.panel.label=Vuze grei\u010dio testas: SpeedTestWizard.test.panel.already.running=Testas jau vykdomas! SpeedTestWizard.test.panel.not.accepted=Testo pra\u0161ymas nepriimtas: SpeedTestWizard.test.panel.abort=Nutraukti SpeedTestWizard.test.panel.abort.countdown=testas bus nutrauktas po: SpeedTestWizard.test.panel.test.countdown=testas baigsis po: SpeedTestWizard.test.panel.testfailed=Testo klaida SpeedTestWizard.test.panel.aborted=Testas nutrauktas rankiniu b\u016bdu. SpeedTestWizard.test.panel.enc.label=Testo \u0161ifravimo re\u017eimas: SpeedTestWizard.test.panel.standard=standartinis SpeedTestWizard.test.panel.encrypted=\u0161ifruotas SpeedTestWizard.set.upload.button.apply=Vykdyti SpeedTestWizard.set.upload.result=Paskutinio testo rezultatas SpeedTestWizard.set.upload.bytes.per.sec=baitai/sek SpeedTestWizard.set.upload.bits.per.sec=bitai/sek SpeedTestWizard.finish.panel.title=Grei\u010dio testas baigtas! SpeedTestWizard.finish.panel.click.close=J\u016bs baig\u0117te grei\u010dio testo vedl\u012f. Spauskite 'Baigti' nor\u0117dami u\u017edaryti. SpeedTestWizard.finish.panel.max.upload=Did\u017e. i\u0161siuntimas : SpeedTestWizard.finish.panel.max.seeding.upload=Did\u017e. i\u0161siuntimas skleid\u017eiant : SpeedTestWizard.finish.panel.max.download=Did\u017e. atsiuntimas : SpeedTestWizard.finish.panel.enabled=\u012fjungtas SpeedTestWizard.finish.panel.disabled=i\u0161jungtas SpeedTestWizard.abort.message.scheduled.in=testas suplanuotas po ... %1 sek." SpeedTestWizard.abort.message.unsupported.type=Nepalaikomas testo tipas!!!! SpeedTestWizard.abort.message.manual.abort=Nutrauktas rankiniu b\u016bdu SpeedTestWizard.abort.message.scheduling.failed=Nepavyko suplanuoti testo SpeedTestWizard.abort.message.download.added=Atsiuntimas %1 prid\u0117tas testo metu SpeedTestWizard.abort.message.entered.error=Testo atsiuntimo klaida '%1' SpeedTestWizard.abort.message.entered.queued=Atsi\u0173stas testas pateko \u012f eil\u0119/buvo sustabdytas SpeedTestWizard.abort.message.interrupted=TorrentSpeedTestMonitorThread buvo nutraukta prie\u0161 testo baigim\u0105 SpeedTestWizard.abort.message.execution.failed=Testo vykdymo klaida SpeedTestWizard.abort.message.failed.peers=Nepavyko susijungti su n\u0117 vienu siunt\u0117ju SpeedTestWizard.abort.message.insufficient.slots=Nepavyko i\u0161si\u0173sti n\u0117 vienam siunt\u0117jui - nepakanka i\u0161siuntimo lizd\u0173? SpeedTestWizard.abort.message.not.unchoked=Nepavyko atsi\u0173sti i\u0161 n\u0117 vieno siunt\u0117jo, nes jie niekada neatslopino SpeedTestWizard.stage.message.requesting=pra\u0161oma testo... SpeedTestWizard.stage.message.preparing=ruo\u0161iamasi testui... SpeedTestWizard.stage.message.starting=pradedamas testas... SpeedTestWizard.stage.message.connect.stats=Ry\u0161io statistika: siunt\u0117jai=%1, atsiunt_gerai=%2, i\u0161siutn_gerai=%3 window.uiswitcher.title=Vuze naudotojo s\u0105sajos parinkimas window.uiswitcher.text=Pra\u0161ome \u017eemiau i\u0161sirinkti labiausiai tinkan\u010di\u0105 naudotojo s\u0105saj\u0105. window.uiswitcher.NewUI.text=Suteikia labiausiai nu\u0161lifuot\u0105 s\u0105saj\u0105.\n\nRekomenduojama naujiems ir pradedantiems naudotojams. window.uiswitcher.ClassicUI.title=Klasikin\u0117 s\u0105saja window.uiswitcher.ClassicUI.text=Skirta tiems, kurie nenori naujos s\u0105sajos. Vuze elgsis lygiai taip pat, kaip elg\u0117si 2.x versijose. VivaldiView.notAvailable=Vivaldi vaizdas neprieinamas restart.error=Nepavyko perkrauti:\n%1\n\u017di\u016br\u0117kite perkrovimo problemas. restart.error.oom=Neu\u017etenka atminties restart.error.fnf='%1' buvo nerastas '%2' restart.error.pnf=Kelias '%1' nerastas restart.error.bad='%1' - blogas failo formatas restart.error.denied=Prieiga atmesta m\u0117ginant vykdyti '%1'. \u012esitikinkite, kad turite teisi\u0173 \u0161iai programai vykdyti. TableColumn.header.date_completed=Baigta TableColumn.menu.date_added.reset=Atstatyti dat\u0105 MyTorrents.column.ColumnProgressETA.2ndLine=NBL: %1 TableColumn.header.Speed=Greitis TableColumn.header.SpeedGraphic=Greitis #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=Pagrindinis v3.MainWindow.tab.library=Mano biblioteka v3.MainWindow.tab.publish=Skelbti v3.MainWindow.tab.advanced=I\u0161pl\u0117stinis v3.MainWindow.menu.home=&Pagrindinis v3.MainWindow.menu.browse=&Nar\u0161yti turin\u012f v3.MainWindow.menu.library=Mano &biblioteka v3.MainWindow.menu.publish=&Skelbti v3.MainWindow.menu.advanced=&I\u0161pl\u0117stinis v3.MainWindow.currentDL=\u0160iuo metu siun\u010diama v3.MainWindow.button.pause=Pristabdyti v3.MainWindow.button.resume=T\u0119sti v3.MainWindow.button.delete=Trinti v3.MainWindow.button.comment=Komentuoti v3.MainWindow.button.viewdetails=Rodyti informacij\u0105 v3.MainWindow.button.play=Paleisti v3.MainWindow.button.cancel=Atsisakyti v3.MainWindow.xofx=%1 i\u0161 %2 v3.MainWindow.Loading=\u012ekeliama.. Pra\u0161ome palaukti v3.filter-bar=Pavadinimo filtras: v3.mb.delPublished.title=Stabdyti turinio skleidim\u0105 v3.mb.delPublished.delete=&Trinti v3.mb.delPublished.cancel=&Atsisakyti v3.mb.PlayFileNotFound.title=Failas nerastas v3.mb.PlayFileNotFound.button.remove=\u0160alinti i\u0161 Vuze v3.mb.deletePurchased.title=\u0160alinti nupirkt\u0105 turin\u012f v3.mb.deletePurchased.text=Ar tikrai norite trinti \u0161\u012f turin\u012f '%1'?\n\n\u0160\u012f turin\u012f J\u016bs arba nupirkote, arba Jums reik\u0117jo prisijungti, norint j\u012f atsisi\u0173sti. v3.mb.deletePurchased.button.delete=&Trinti v3.mb.deletePurchased.button.cancel=&Atsisakyti # splash.loadIpFilters=\u012ekeliami IP filtrai.. SpeedTestWizard.set.upload.title=Nustatyti i\u0161siuntimo ir atsiuntimo limitus SpeedTestWizard.set.download.label=Atsiuntimo grei\u010dio limitas: SpeedTestWizard.set.upload.label=I\u0161siuntimo grei\u010dio limitas: SpeedTestWizard.name.conf.level.absolute=Absoliutus SpeedTestWizard.name.conf.level.high=Auk\u0161tas SpeedTestWizard.name.conf.level.med=Vidutinis SpeedTestWizard.name.conf.level.low=\u017demas SpeedTestWizard.name.conf.level.none=N\u0117ra ConfigView.section.transfer.autospeed.networks=Tinklo informacija ConfigView.section.transfer.autospeed.resetnetwork=Atstatyti tinklo informacij\u0105 # Used for peers which we can't determine. PeerSocket.unknown=Ne\u017einomas ConfigTransferAutoSpeed.while.downloading=Siun\u010diama: PiecesView.DistributionView.title=Dali\u0173 pasiskirstymas PiecesView.DistributionView.NoAvl=Nepasiekiamos dalys PiecesView.DistributionView.RarestAvl=Re\u010diausios dalys: %1 (Avl:%2) PiecesView.DistributionView.weHave=Dalys, kurias turite PiecesView.DistributionView.weDownload=Dalys, kurias siun\u010diate SpeedTestWizard.test.panel.explain=I\u0161matuokite savo i\u0161siuntimo ir atsiuntimo grei\u010dius naudodami BT protokol\u0105. I\u0161rinkite grei\u010dio testo tip\u0105 ir \u0161ifravimo re\u017eim\u0105 ir tada spauskite 'Vykdyti' mygtuk\u0105 testui prad\u0117ti. Paspauskite mygtuk\u0105 'Nutraukti', kol vykdomas testas. Testas bus automati\u0161kai sustabdytas, jei truks ilgiau kaip dvi minutes. Tipinis testas u\u017etruks ne ilgiau kaip minut\u0119. Baigus testavim\u0105 bus rekomenduotas maksimalus i\u0161siuntimo greitis. Spauskite 'Kitas >' i\u0161siuntimo grei\u010diui nustatyti. SpeedTestWizard.set.upload.hint=Nustatyti i\u0161siuntimo ir atsiuntimo limitus, kuriuos naudoja Vuze SpeedSense algoritmas esantis beta stadijoje. SpeedTestWizard.set.upload.panel.explain=\u010cia nustatyti limitai yra naudojami Azreus SpeedSense algoritme. Nustatykite siuntimo ir pasitik\u0117jimo limitus.\n\nPasteb\u0117kite, kad linijos grei\u010diai da\u017enai nusakomi "bitais per sekund\u0119", o \u017eemiau rodomos reik\u0161m\u0117s - "kilobaitais per sekund\u0119". SpeedTestWizard.set.limit.conf.level=Pasitik\u0117jimo lygis SpeedTestWizard.finish.panel.auto.speed=Automatinis greitis yra : SpeedTestWizard.finish.panel.auto.speed.seeding=Automatinis greitis skleid\u017eiant yra : ConfigView.label.announceport=Keisti Trackerio prane\u0161im\u0173 prievad\u0105 iconBar.queue.tooltip=\u012e eil\u0119 MainWindow.menu.help.faq=&Da\u017eniausiai u\u017eduodami klausimai MainWindow.menu.help.donate=&Aukoti azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_bg_BG.properties0000644000175000017500000214314211301156004026036 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=\u0422\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u0085\u2026 Main.parameter.usage=\u0423\u043f\u043e\u0442\u0440\u0435\u0431\u0430: java org.gudy.azureus2.cl.Main [\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438] "file.torrent" "\u043f\u044a\u0442 \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435" Main.parameter.maxUploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u0435\u043d \u0431\u0440\u043e\u0439 \u0435\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0438 \u043a\u0430\u0447\u0432\u0430\u043d\u0438\u044f Main.parameter.maxSpeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 B/s MainWindow.menu.file=&\u0424\u0430\u0439\u043b MainWindow.menu.file.open=&\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 MainWindow.menu.file.create=&\u041d\u043e\u0432 \u0442\u043e\u0440\u0435\u043d\u0442\u0085\u2026 MainWindow.menu.file.create.fromfile=\u041e\u0442 &\u0444\u0430\u0439\u043b MainWindow.menu.file.create.fromdir=\u041e\u0442 &\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f MainWindow.menu.file.export=&\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u043d\u0430 XML \u0442\u043e\u0440\u0435\u043d\u0442\u0085\u2026 MainWindow.menu.file.import=&\u0418\u043c\u043f\u043e\u0440\u0442 \u043d\u0430 XML \u0442\u043e\u0440\u0435\u043d\u0442\u0085\u2026 MainWindow.menu.file.closetab=\u0417\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 &\u0441\u0435\u043a\u0446\u0438\u044f MainWindow.menu.file.closewindow=\u0417\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 &\u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 MainWindow.menu.file.exit=\u0418\u0437&\u0445\u043e\u0434 MainWindow.dialog.choose.file=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b MainWindow.menu.file.folder=&\u041f\u0430\u043f\u043a\u0430\u0085\u2026 MainWindow.dialog.choose.folder=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f, \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u0449\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 MainWindow.menu.view=\u0418&\u0437\u0433\u043b\u0435\u0434 MainWindow.menu.view.show=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 MainWindow.menu.view.mytorrents=&\u041c\u0435\u0441\u0442\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 MainWindow.menu.view.open_global_transfer_bar=\u041b\u0435\u043d\u0442\u0430 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 MainWindow.menu.view.configuration=\u041a&\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0085\u2026 MainWindow.menu.view.console=\u041a&\u043e\u043d\u0437\u043e\u043b\u0430 MainWindow.menu.view.irc=&IRC \u043c\u0440\u0435\u0436\u0430 MainWindow.menu.view.allpeers=\u0412\u0441\u0438\u0447\u043a\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 MainWindow.menu.view.detailedlist=&\u041f\u043e\u0434\u0440\u043e\u0431\u0435\u043d \u0441\u043f\u0438\u0441\u044a\u043a MainWindow.menu.closealldetails=\u0417&\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u0432\u0441\u0438\u0447\u043a\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 MainWindow.menu.closealldownloadbars=\u0417\u0430\u0442&\u0432\u0430\u0440\u044f\u043d\u0435 \u0432\u0441\u0438\u0447\u043a\u0438 \u043b\u0435\u043d\u0442\u0438 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 MainWindow.menu.language=&\u0415\u0437\u0438\u043a ConfigView.section.language=\u0415\u0437\u0438\u043a MainWindow.menu.window=\u041f\u0440\u043e\u0437\u043e\u0440\u0435&\u0446 MainWindow.menu.window.minimize=&\u041c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0430\u043d\u0435 MainWindow.menu.window.zoom=&\u0423\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 MainWindow.menu.window.alltofront=&\u0412\u0441\u0438\u0447\u043a\u043e \u043d\u0430 \u043f\u0440\u0435\u0434\u0435\u043d \u043f\u043b\u0430\u043d MainWindow.menu.help=\u041f&\u043e\u043c\u043e\u0449 MainWindow.menu.help.about=\u0417\u0430 Vuze MainWindow.menu.torrent=\u0422\u043e\u0440\u0435\u043d\u0442 MainWindow.about.title=\u041e\u0442\u043d\u043e\u0441\u043d\u043e MainWindow.about.section.developers=\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u0446\u0438 MainWindow.about.section.translators=\u041f\u0440\u0435\u0432\u043e\u0434\u0430\u0447\u0438 MainWindow.about.section.system=\u0421\u0438\u0441\u0442\u0435\u043c\u0430 MainWindow.about.section.internet=\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 MainWindow.about.internet.homepage=\u041d\u0430\u0447\u0430\u043b\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430 Vuze MainWindow.about.internet.sourceforge=\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430 Sourceforge \u0437\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0438 MainWindow.about.internet.sourceforgedownloads=\u0417\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043e\u0442 Sourceforge MainWindow.about.internet.bugreports=\u0414\u043e\u043a\u043b\u0430\u0434\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 MainWindow.about.internet.forumdiscussion=\u0424\u043e\u0440\u0443\u043c\u0438 MainWindow.about.internet.wiki=\u0427\u0417\u0412 Vuze Wiki MainWindow.dialog.choose.savepath=\u041f\u044a\u0442 \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 MainWindow.dialog.choose.savepath_forallfiles=\u041f\u044a\u0442 \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0412\u0421\u0418\u0427\u041a\u0418 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 MainWindow.status.latestversion=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044f MainWindow.status.latestversion.clickupdate=\u041f\u043e\u0441\u043e\u0447\u0432\u0430\u043d\u0435 \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f MainWindow.status.unknown=\u043d\u0435\u043f\u043e\u0437\u043d\u0430\u0442 MainWindow.status.checking=\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 MyTorrentsView.mytorrents=\u041c\u0435\u0441\u0442\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.name=\u0418\u043c\u0435 TableColumn.header.size=\u0420\u0430\u0437\u043c\u0435\u0440 TableColumn.header.done=\u0413\u043e\u0442\u043e\u0432\u043e TableColumn.header.done.info=% \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e\u0441\u0442 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 TableColumn.header.status=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 TableColumn.header.status.info=\u041a\u0430\u043a\u0432\u043e \u043f\u0440\u0430\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u044a\u0442 TableColumn.header.seeds=\u041f\u043e\u0441\u044f\u0432\u043a\u0438 TableColumn.header.seeds.info=\u0411\u0440. \u043f\u043e\u0441\u044f\u0432\u043a\u0438 \u0441 \u043a\u043e\u0438\u0442\u043e \u0438\u043c\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 (\u043e\u0431\u0449 \u0431\u0440. \u043f\u043e\u0441\u044f\u0432\u043a\u0438) TableColumn.header.peers=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 TableColumn.header.peers.info=\u0411\u0440. \u0441\u0432\u044a\u0440\u0437\u0430\u043d\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 (\u043e\u0431\u0449 \u0431\u0440. \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438) TableColumn.header.completed=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e TableColumn.header.completed.info=\u0411\u0440\u043e\u0439 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0438\u043b\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0434\u043e\u043a\u043b\u0430\u0434\u0432\u0430\u043d\u043e \u043e\u0442 \u0442\u0440\u0430\u043a\u0435\u0440\u0430 TableColumn.header.downspeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 TableColumn.header.upspeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 TableColumn.header.eta=\u041e\u0412\u0417 TableColumn.header.tracker=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440 TableColumn.header.tracker.info=\u041a\u0430\u043a\u0432\u043e \u0435 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430 TableColumn.header.trackernextaccess=\u0421\u043b\u0435\u0434\u0432\u0430\u0449 \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 \u0434\u043e\u0441\u0442\u044a\u043f TableColumn.header.trackernextaccess.info=\u041a\u043e\u0433\u0430 \u0449\u0435 \u0441\u0435 \u0441\u043b\u0443\u0447\u0438 \u0441\u043b\u0435\u0434\u0432\u0430\u0449 \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 \u0434\u043e\u0441\u0442\u044a\u043f TableColumn.header.priority=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 TableColumn.header.priority.info=\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f \u043a\u043e\u043b\u043a\u043e \u0433\u043e\u043b\u044f\u043c\u0430 \u043b\u0435\u043d\u0442\u0430 \u0437\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u0435 \u0434\u0430\u0434\u0435\u043d\u0430 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 TableColumn.header.seeds.fullcopycalc=%2 \u043f\u044a\u043b\u043d\u0438 \u043a\u043e\u043f\u0438\u044f \u0434\u043e\u043f\u0443\u0441\u043d\u0430\u0442\u0438 \u0437\u0430 %1 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 MyTorrentsView.menu.showdetails=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e&\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 MyTorrentsView.menu.showdownloadbar=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043b\u0435\u043d\u0442\u0430 \u0437\u0430 \u0441&\u0432\u0430\u043b\u044f\u043d\u0435 MyTorrentsView.menu.open=&\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b MyTorrentsView.menu.setpriority=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430 &\u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 MyTorrentsView.menu.setpriority.high=&\u0412\u0438\u0441\u043e\u043a MyTorrentsView.menu.setpriority.low=&\u041d\u0438\u0441\u044a\u043a MyTorrentsView.menu.start=&\u0421\u0442\u0430\u0440\u0442 MyTorrentsView.menu.stop=\u0421\u0442\u043e&\u043f MyTorrentsView.menu.remove=\u041f&\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 MyTorrentsView.menu.changeTracker=\u0414\u043e\u0431&\u0430\u0432\u044f\u043d\u0435 URL \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440 TrayWindow.menu.exit=\u0418\u0437&\u0445\u043e\u0434 TrayWindow.menu.show=&\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 Vuze SystemTray.menu.exit=\u0418\u0437&\u0445\u043e\u0434 SystemTray.menu.closealldownloadbars=\u0417&\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u0432\u0441\u0438\u0447\u043a\u0438 \u043b\u0435\u043d\u0442\u0438 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f SystemTray.menu.open_global_transfer_bar=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u043b\u0435\u043d\u0442\u0430 \u0437\u0430 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 SystemTray.menu.show=&\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 Vuze PeersView.ip.info=IP \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d PeersView.port=\u041f\u043e\u0440\u0442 PeersView.port.info=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0440\u0442 PeersView.T=\u0422 PeersView.T.info=\u041b (\u043b\u043e\u043a\u0430\u043b\u043d\u043e): \u043c\u0435\u0441\u0442\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0435\u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430, \u041e (\u043e\u0442\u0434\u0430\u043b\u0435\u0447\u0435\u043d\u043e): \u0432\u0440\u044a\u0437\u043a\u0430\u0442\u0430 \u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0435\u043d\u0430 \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f. PeersView.T.L.tooltip=\u041c\u0435\u0441\u0442\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0435\u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 PeersView.T.R.tooltip=\u0412\u0440\u044a\u0437\u043a\u0430\u0442\u0430 \u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0435\u043d\u0430 \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f PeersView.I1=\u0418 (\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f) PeersView.I1.info=\u0414\u0430\u043b\u0438 \u0435 \u043e\u0442 \u043c\u0435\u0441\u0442\u0435\u043d \u0438\u043d\u0442\u0435\u0440\u0435\u0441 \u0442\u043e\u0432\u0430, \u043a\u043e\u0435\u0442\u043e \u0438\u043c\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f? PeersView.C1=C (\u0440\u0430\u0437\u043e\u0447\u0430\u0440\u043e\u0432\u0430\u043d \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f) PeersView.C1.info=\u041d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0441\u0432\u0430\u043b\u044f \u043c\u0435\u0441\u0442\u043d\u043e \u0437\u0430\u0440\u0430\u0434\u0438 \u0441\u043f\u0438\u0440\u0430\u043d\u0435 \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f PeersView.pieces=\u041f\u0430\u0440\u0447\u0435\u0442\u0430 PeersView.%=\u0412 % \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 PeersView.downloadspeed=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 \u0441 PeersView.download=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 PeersView.I2=\u0418 (\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0437\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f) PeersView.I2.info=\u0414\u0430\u043b\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f\u0442 \u0441\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0432\u0430 \u043e\u0442 \u043c\u0435\u0441\u0442\u043d\u043e \u043d\u0430\u043b\u0438\u0447\u043d\u043e\u0442\u043e? PeersView.C2=C (\u0440\u0430\u0437\u043e\u0447\u0430\u0440\u043e\u0432\u0430\u043d\u0435 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f) PeersView.C2.info=\u041c\u0435\u0441\u0442\u043d\u043e \u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u043d \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f\u0442 \u0434\u0430 \u043d\u0435 \u0441\u0432\u0430\u043b\u044f PeersView.uploadspeed=\u041a\u0430\u0447\u0432\u0430\u043d\u0435 \u0441 PeersView.uploadspeed.info=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u043a\u044a\u043c \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f PeersView.upload=\u041a\u0430\u0447\u0432\u0430\u043d\u0435 PeersView.upload.info=\u041e\u0431\u043e\u0431\u0449\u0435\u043d\u043e \u043a\u0430\u0447\u0435\u043d\u043e\u0442\u043e \u043a\u044a\u043c \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f. PeersView.statup=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 PeersView.statup.info=\u0418\u0437\u0447\u0438\u0441\u043b\u0435\u043d\u0430 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f PeersView.S=\u0421 PeersView.S.info=\u0421\u043a\u0430\u0441\u0442\u0440\u0435\u043d: \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u0441\u043a\u0430\u0441\u0442\u0440\u0435\u043d \u0440\u044a\u0447\u043d\u043e \u0438\u043b\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e (\u0437\u0430 \u0442\u043e\u0432\u0430, \u0447\u0435 \u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0432\u044f \u0434\u0430\u043d\u043d\u0438 \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u044a\u0447\u043d\u043e \u0432\u0438\u0441\u043e\u043a\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435) PeersView.downloadspeedoverall=\u041e\u0431\u0449\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 PeersView.optunchoke=\u041e\u0442\u043c\u044f\u043d\u0430 \u043d\u0430 \u0440\u0430\u0437\u043e\u0447\u0430\u0440\u043e\u0432\u0430\u043d\u0435 PeersView.client=\u041a\u043b\u0438\u0435\u043d\u0442 PeersView.client.info=\u0422\u0438\u043f \u043d\u0430 BT \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f PeersView.menu.snubbed=&\u0421\u043a\u0430\u0441\u0442\u0440\u0435\u043d PeersView.title.short=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 PeersView.title.full=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 AllPeersView.title.full=\u0412\u0441\u0438\u0447\u043a\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.section.files=\u0424\u0430\u0439\u043b\u043e\u0432\u0435 ConfigView.label.usefastresume=\u0420\u0435\u0436\u0438\u043c \u0437\u0430 \u0431\u044a\u0440\u0437\u043e \u043f\u0440\u043e\u0434\u044a\u043b\u0436\u0435\u043d\u0438\u0435 ConfigView.label.incrementalfile=\u0418\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0430\u043b\u043d\u043e \u0441\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 [\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0435 \u043f\u0440\u0438 FAT32 \u043f\u043e\u0434 \u041b\u0438\u043d\u0443\u043a\u0441] ConfigView.label.defaultsavepath=\u0417\u0430\u043f\u0438\u0441 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f\u0442\u0430 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u0437\u0430 \u0434\u0430\u043d\u043d\u0438 ConfigView.button.browse=&\u041f\u0440\u0435\u0433\u043b\u0435\u0434\u0085\u2026 ConfigView.dialog.choosedefaultsavepath=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 ConfigView.section.server=\u0412\u0440\u044a\u0437\u043a\u0430 ConfigView.section.global=\u041e\u0431\u0449\u043e ConfigView.label.disconnetseed=\u041f\u0440\u0435\u043a\u044a\u0441\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0441\u044f\u0432\u043a\u0438\u0442\u0435 \u043f\u0440\u0438 \u0441\u0435\u0435\u043d\u0435 ConfigView.label.switchpriority=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u0432\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435 \u043a\u044a\u043c \u043d\u0438\u0441\u044a\u043a \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043f\u0440\u0438 \u0441\u0435\u0435\u043d\u0435 ConfigView.label.maxdownloads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u043e \u0435\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e]\n - \u041d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0435 \u043f\u043e-\u0432\u0438\u0441\u043e\u043a\u043e \u043e\u0442 \u0431\u0440\u043e\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u043e \u0430\u043a\u0442\u0438\u0432\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.label.maxdownloads.tooltip=\u0412\u044a\u0437\u043c\u043e\u0436\u043d\u043e \u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0442\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043d\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0442\u0443\u043a \u0431\u0440\u043e\u0439 \u0441 \u0435\u0434\u043d\u043e \u0438\u0437\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435.\n\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442, \u043e\u0442\u0433\u043e\u0432\u0430\u0440\u044f\u0449 \u043d\u0430 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u0437\u0430 \u041d\u0412\u041f, \u043c\u043e\u0436\u0435 \u0434\u0430 \u043f\u0440\u0435\u0432\u0437\u0435\u043c\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0433\u043d\u0435\u0437\u0434\u043e \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435, \u0430\u043a\u043e \u0435 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e. ConfigView.label.maxactivetorrents=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u0435\u043d \u0431\u0440\u043e\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e]\n\u041d\u043e\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043d\u044f\u043c\u0430 \u0434\u0430 \u0437\u0430\u043f\u043e\u0447\u0432\u0430\u0442 \u043f\u0440\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0435/\u043a\u0430\u0447\u0432\u0430\u0442\u0435 \u043d\u0430 \u043f\u043e\u0432\u0435\u0447\u0435 ConfigView.label.priorityExtensions=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u0432\u0438\u0448\u0430\u0432\u0430\u043d\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0441 \u0440\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u0435\n - \u043f\u0440.: .txt;.nfo;.jpg ConfigView.section.transfer=\u0422\u0440\u0430\u043d\u0441\u0444\u0435\u0440 ConfigView.label.maxuploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0433\u043d\u0435\u0437\u0434\u0430 \u0437\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.label.maxuploadspeed=KB/s \u0433\u043b\u043e\u0431\u0430\u043b\u043d\u0430 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.label.saveresumeinterval=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438\u0442\u0435 \u0437\u0430 \u043f\u0440\u043e\u0434\u044a\u043b\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0432\u0441\u0435\u043a\u0438 ConfigView.unlimited=\u041d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e ConfigView.section.display=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 ConfigView.label.opendetails=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0435\u043a\u0446\u0438\u044f '\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438' ConfigView.label.openbar=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 ConfigView.label.use_old_speed_menus=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0442\u0430\u0440\u0438\u0442\u0435 \u043c\u0435\u043d\u044e\u0442\u0430 \u0437\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 (\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442) ConfigView.label.closetotray=\u0417\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0430 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 ConfigView.label.minimizetotray=\u041c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0430\u043d\u0435\u0442\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 ConfigView.section.general=\u041e\u0431\u0449\u043e ConfigView.section.start=\u0421\u0442\u0430\u0440\u0442 ConfigView.label.showsplash=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0437\u0430\u0433\u043b\u0430\u0432\u0435\u043d \u0435\u043a\u0440\u0430\u043d ConfigView.label.autoupdate=\u0414\u0430 \u0441\u0435 \u043e\u0442\u0432\u043e\u0440\u0438 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432 \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 '\u041d\u0430\u0434\u0433\u0440\u0430\u0436\u0434\u0430\u043d\u0435' \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043d\u0430 \u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0438\u044f ConfigView.label.openconsole=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 '\u041a\u043e\u043d\u0437\u043e\u043b\u0430' \u043f\u0440\u0438 \u043d\u0430\u0447\u0430\u043b\u043d\u043e \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 ConfigView.label.openconfig=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 '\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f' \u043f\u0440\u0438 \u043d\u0430\u0447\u0430\u043b\u043d\u043e \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 ConfigView.label.startminimized=\u0421\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0430\u043d ConfigView.section.irc=\u041c\u0440\u0435\u0436\u0430 IRC ConfigView.label.ircwiki=\u0414\u0430 \u0441\u0435 \u043f\u0440\u043e\u0447\u0435\u0442\u0435 http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=\u0421\u044a\u0440\u0432\u044a\u0440 ConfigView.label.ircchannel=\u041a\u0430\u043d\u0430\u043b ConfigView.label.irclogin=\u041f\u0440\u044f\u043a\u043e\u0440 ConfigView.group.irctitle=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 IRC ConfigView.boolean.ircsendinfo=\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u0438\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u043b\u0438\u0447\u043d\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 (\u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e) \u0434\u043e\n \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0438\u0442\u0435 \u043d\u0430 \u043a\u0430\u043d\u0430\u043b, \u0437\u0430 \u0434\u0430 \u0438\u043c \u0441\u0435 \u043f\u043e\u043c\u043e\u0433\u043d\u0435 \u0434\u0430 \u043e\u043a\u0430\u0436\u0430\u0442 \u043f\u043e\u043c\u043e\u0449 ConfigView.boolean.irclog=\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u0434\u043d\u0435\u0432\u043d\u0438\u043a \u043d\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0442\u0430 \u043f\u043e \u043a\u0430\u043d\u0430\u043b (\u0432 IRC_log.htm) ConfigView.section.security=\u0421\u0438\u0433\u0443\u0440\u043d\u043e\u0441\u0442 ConfigView.label.password=\u0417\u0430\u0449\u0438\u0442\u0430 \u043d\u0430 Vuze \u0441 \u043f\u0430\u0440\u043e\u043b\u0430\n\u0429\u0435 \u0441\u0435 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u043f\u0440\u0438 \u043c\u0430\u043a\u0441\u0438\u043c\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043e\u0442 \u0438\u043a\u043e\u043d\u0430 \u0438 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435. ConfigView.label.passwordconfirm=\u041f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u0440\u043e\u043b\u0430 ConfigView.label.passwordmatch=\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0430 \u043f\u0430\u0440\u043e\u043b\u0430: ConfigView.label.passwordmatchnone=\u041d\u0435 ConfigView.label.passwordmatchno=\u041d\u0435/\u041f\u0430\u0440\u043e\u043b\u0438\u0442\u0435 \u043d\u0435 \u0441\u044a\u0432\u043f\u0430\u0434\u0430\u0442 ConfigView.label.passwordmatchyes=\u0414\u0430 ConfigView.button.save=\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 ConfigView.title.short=\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f ConfigView.title.full=\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f ConfigView.title.full._mac=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 ConsoleView.title.short=\u041a\u043e\u043d\u0437\u043e\u043b\u0430 ConsoleView.title.full=\u041a\u043e\u043d\u0437\u043e\u043b\u0430 FileItem.write=\u0437\u0430\u043f\u0438\u0441 FileItem.read=\u0447\u0435\u0442\u0435\u043d\u0435 FileItem.normal=\u043d\u043e\u0440\u043c\u0430\u043b\u0435\u043d FileItem.high=\u0432\u0438\u0441\u043e\u043a FileItem.donotdownload=\u0414\u0430 \u043d\u0435 \u0441\u0435 \u0441\u0432\u0430\u043b\u044f FileItem.delete=\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 FilesView.name=\u0418\u043c\u0435 FilesView.name.fastRename=\u0411\u044a\u0440\u0437\u043e \u043f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u0435 FilesView.size=\u0420\u0430\u0437\u043c\u0435\u0440 FilesView.done=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e FilesView.%=\u0412 % \u0444\u0430\u0439\u043b\u043e\u0432\u0435 FilesView.firstpiece=\u041f\u044a\u0440\u0432\u043e \u043f\u0430\u0440\u0447\u0435 \u2116 FilesView.numberofpieces=\u0411\u0440. \u043f\u0430\u0440\u0447\u0435\u0442\u0430 FilesView.pieces=\u041f\u0430\u0440\u0447\u0435\u0442\u0430 FilesView.mode=\u0420\u0435\u0436\u0438\u043c FilesView.priority=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 FilesView.menu.open=&\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 FilesView.menu.setpriority=&\u0417\u0430\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 FilesView.menu.setpriority.high=&\u0412\u0438\u0441\u043e\u043a FilesView.menu.setpriority.normal=&\u041d\u043e\u0440\u043c\u0430\u043b\u0435\u043d FilesView.menu.setpriority.skipped=&\u0414\u0430 \u043d\u0435 \u0441\u0435 \u0441\u0432\u0430\u043b\u044f FilesView.title.short=\u0424\u0430\u0439\u043b\u043e\u0432\u0435 FilesView.title.full=\u0424\u0430\u0439\u043b\u043e\u0432\u0435 GeneralView.section.downloaded=\u0421\u0432\u0430\u043b\u0435\u043d\u043e GeneralView.label.status.file=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b GeneralView.label.status.pieces=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 GeneralView.section.availability=\u041d\u0430\u043b\u0438\u0447\u043d\u043e\u0441\u0442 GeneralView.label.status.pieces_available=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 GeneralView.section.transfer=\u0422\u0440\u0430\u043d\u0441\u0444\u0435\u0440 GeneralView.section.info=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f GeneralView.title.short=\u0413\u043b\u0430\u0432\u0435\u043d GeneralView.title.full=\u0413\u043b\u0430\u0432\u0435\u043d GeneralView.label.timeelapsed=\u0418\u0437\u043c\u0438\u043d\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u0435: GeneralView.label.remaining=\u041e\u0441\u0442\u0430\u0432\u0430: GeneralView.label.downloaded=\u0421\u0432\u0430\u043b\u0435\u043d\u043e: GeneralView.label.downloadspeed=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 \u043f\u0440\u0438: GeneralView.label.maxuploads=\u0413\u043d\u0435\u0437\u0434\u0430 \u0437\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435: GeneralView.label.maxuploads.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u0435\u043d \u0431\u0440\u043e\u0439 \u043d\u0435\u0440\u0430\u0437\u043e\u0447\u0430\u0440\u043e\u0432\u0430\u043d\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u043f\u043e \u0432\u0441\u044f\u043a\u043e \u0432\u0440\u0435\u043c\u0435. GeneralView.label.uploaded=\u041a\u0430\u0447\u0435\u043d\u043e: GeneralView.label.uploadspeed=\u041a\u0430\u0447\u0432\u0430\u043d\u0435 \u043f\u0440\u0438: GeneralView.label.seeds=\u041f\u043e\u0441\u044f\u0432\u043a\u0438: GeneralView.label.peers=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438: GeneralView.label.completed=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e: GeneralView.label.totalspeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0440\u043e\u044f\u043a\u0430: GeneralView.label.totalspeed.tooltip=\u041e\u0431\u0449\u0430 (\u0438 \u0441\u0440\u0435\u0434\u043d\u0430) \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0438 \u0441 \u043a\u043e\u0438\u0442\u043e \u0438\u043c\u0430 \u0432\u0440\u044a\u0437\u043a\u0438. GeneralView.label.averagespeed=\u0441\u0440\u0435\u0434\u043d\u043e GeneralView.label.filename=\u0418\u043c\u0435: GeneralView.label.totalsize=\u041e\u0431\u0449 \u0440\u0430\u0437\u043c\u0435\u0440: GeneralView.label.savein=\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u0432: GeneralView.label.hash=\u0420\u0430\u0437\u0431\u044a\u0440\u043a\u0432\u0430\u043d\u0435: GeneralView.label.numberofpieces=\u0411\u0440. \u043f\u0430\u0440\u0447\u0435\u0442\u0430: GeneralView.label.size=\u0420\u0430\u0437\u043c\u0435\u0440: GeneralView.label.tracker=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430: GeneralView.label.updatein=\u041e\u043f\u0440\u0435\u0441\u043d\u044f\u0432\u0430\u043d\u0435 \u0441\u043b\u0435\u0434: GeneralView.label.trackerurl=URL \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430: GeneralView.label.trackerurlupdate=\u041e\u043f\u0440\u0435\u0441\u043d\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430 GeneralView.label.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440: GeneralView.label.user_comment=\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440: GeneralView.label.status=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435: ManagerItem.waiting=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 ManagerItem.allocating=\u0417\u0430\u0434\u0435\u043b\u044f\u043d\u0435 ManagerItem.checking=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 ManagerItem.ready=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u0437\u0430 \u0434\u0440\u0443\u0433(\u0438) \u0442\u043e\u0440\u0435\u043d\u0442(\u0438) \u0437\u0430 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430 ManagerItem.downloading=\u0421\u0432\u0430\u043b\u044f\u0449 ManagerItem.seeding=\u0421\u0435\u0435\u0449 ManagerItem.stopped=\u0421\u043f\u0440\u044f\u043d ManagerItem.error=\u0413\u0440\u0435\u0448\u043a\u0430 ManagerItem.high=\u0432\u0438\u0441\u043e\u043a ManagerItem.low=\u043d\u0438\u0441\u044a\u043a MinimizedWindow.name=\u0418\u043c\u0435: MinimizedWindow.all_transfers=\u0412\u0441\u0438\u0447\u043a\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 PiecesView.#=\u2116 PiecesView.size=\u0420\u0430\u0437\u043c\u0435\u0440 PiecesView.numberofblocks=\u0431\u0440. \u0431\u043b\u043e\u043a\u043e\u0432\u0435 PiecesView.blocks=\u0411\u043b\u043e\u043a\u043e\u0432\u0435 PiecesView.completed=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e PiecesView.availability=\u041d\u0430\u043b\u0438\u0447\u043d\u043e\u0441\u0442 PiecesView.reservedby=\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0430\u043d\u043e PiecesView.writers=\u0414\u043e\u043f\u0440\u0438\u043d\u0435\u0441\u043b\u0438 \u0437\u0430 \u0431\u043b\u043e\u043a PiecesView.title.short=\u041f\u0430\u0440\u0447\u0435\u0442\u0430 PiecesView.title.full=\u041f\u0430\u0440\u0447\u0435\u0442\u0430 SystemTray.tooltip.seeding=%1 \u0441\u0435\u0435\u043d\u0435, SystemTray.tooltip.downloading=%1 \u0441\u0432\u0430\u043b\u044f\u043d\u0435, DownloadManager.error.filenotfound=\u0424\u0430\u0439\u043b\u044a\u0442 \u043d\u0435 \u0435 \u043d\u0430\u043c\u0435\u0440\u0435\u043d DownloadManager.error.fileempty=\u041f\u0440\u0430\u0437\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b DownloadManager.error.filetoobig=\u0424\u0430\u0439\u043b\u044a\u0442 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0435 \u0442\u0432\u044a\u0440\u0434\u0435 \u0433\u043e\u043b\u044f\u043c DownloadManager.error.filewithouttorrentinfo=\u041d\u044f\u043c\u0430 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0432\u044a\u0432 \u0444\u0430\u0439\u043b\u0430 DownloadManager.error.unsupportedencoding=\u041d\u0435\u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430\u043d\u0430 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 DownloadManager.error.ioerror=\u0412/\u0418 \u0433\u0440\u0435\u0448\u043a\u0430 DownloadManager.error.sha1=\u0413\u0440\u0435\u0448\u043a\u0430 (SHA1), \u043d\u044f\u043c\u0430 \u0442\u0430\u043a\u044a\u0432 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u044a\u043c PeerManager.status.offline=\u0413\u0440\u0435\u0448\u043a\u0430 \u0432\u044a\u0432 \u0432\u0440\u044a\u0437\u043a\u0430\u0442\u0430 PeerManager.status.ok=\u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e PeerManager.status.checking=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 PeerManager.status.finished=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e PeerManager.status.finishedin=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e \u0437\u0430 MainWindow.upgrade.assistant=\u041f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f MainWindow.upgrade.newerversion=\u0418\u043c\u0430 \u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430 Vuze \u043d\u0430 \u0440\u0430\u0437\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 MainWindow.upgrade.explanation=\u0422\u043e\u0437\u0438 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u0449\u0435 \u0441\u0432\u0430\u043b\u0438 \u043d\u043e\u0432\u0430\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u0432 \u043c\u0435\u0441\u0442\u043d\u0430\u0442\u0430 \u043f\u0430\u043f\u043a\u0430 \u043d\u0430 Vuze \u0438 \u0449\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 Vuze MainWindow.upgrade.explanation.manual=\u0420\u044a\u0447\u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u0438 \u043a\u0430\u0442\u043e \u0441\u0435 \u0437\u0430\u0442\u0432\u043e\u0440\u0438 Vuze, \u0441\u0432\u0430\u043b\u0438 \u043d\u043e\u0432\u0430\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u0438 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 Vuze MainWindow.upgrade.step1=\u0421\u0442\u044a\u043f\u043a\u0430 1: \u0421\u0432\u0430\u043b\u044f \u0441\u0435 \u043d\u043e\u0432\u0430\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f MainWindow.upgrade.step2=\u0421\u0442\u044a\u043f\u043a\u0430 2: \u0417\u0430\u0442\u0432\u0430\u0440\u044f \u0441\u0435 \u0442\u0435\u043a\u0443\u0449\u0430\u0442\u0430 \u0438 \u0441\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 \u043d\u043e\u0432\u0430\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430 Vuze MainWindow.upgrade.hint1=\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430:\t\u0421 \u041d\u0430\u0442\u0438\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 '\u0413\u043e\u0442\u043e\u0432\u043e' \u0432\u0441\u0438\u0447\u043a\u043e \u0449\u0435 \u0441\u0442\u0430\u043d\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e MainWindow.upgrade.hint2=\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430:\t\u0410\u043a\u043e Vuze \u0449\u0435 \u0431\u044a\u0434\u0435 \u0437\u0430\u0442\u0432\u043e\u0440\u0435\u043d \u043f\u043e-\u043a\u044a\u0441\u043d\u043e, \u0434\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 '\u041e\u0442\u043a\u0430\u0437' \u0438\n\t \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430 Azureus-new.jar \u043d\u0430 Azureus2.jar \u0441\u043b\u0435\u0434 \u0437\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435\u0442\u043e MainWindow.upgrade.error.downloading.hint=\u0413\u0440\u0435\u0448\u043a\u0430:\t\u041d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0441\u0432\u0430\u043b\u0438 \u043d\u043e\u0432\u0430\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f, \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430 \u0440\u044a\u0447\u043d\u043e MainWindow.upgrade.section.info=\u041d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430 \u0440\u0430\u0437\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 MainWindow.upgrade.section.manual=\u0420\u044a\u0447\u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f MainWindow.upgrade.section.automatic=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f MainWindow.upgrade.tooltip.progressbar=\u0420\u0430\u0437\u0432\u0438\u0442\u0438\u0435\u0442\u043e \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e \u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u0442\u0443\u043a Button.next=\u0421\u043b\u0435\u0434\u0432\u0430\u0449\u043e Button.finish=\u041a\u0440\u0430\u0439 Button.cancel=\u041e\u0442\u043a\u0430\u0437 LocaleUtil.title=\u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 LocaleUtil.section.chooseencoding=\u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u0437\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0442\u043e \u0438\u043c\u0435 LocaleUtil.label.chooseencoding=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043d\u0430\u0439-\u0431\u043b\u0438\u0437\u043a\u0430 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 LocaleUtil.label.hint.doubleclick=\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430: \u0418\u0437\u0431\u043e\u0440 \u0432\u044a\u0440\u0445\u0443 \u0434\u0430\u0434\u0435\u043d \u0440\u0435\u0434 \u0438\u0437\u0431\u0438\u0440\u0430 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u0438 \u0437\u0430\u0442\u0432\u0430\u0440\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u0430 LocaleUtil.label.checkbox.rememberdecision=\u0417\u0430\u043f\u043e\u043c\u043d\u044f\u043d\u0435 \u043d\u0430 \u0438\u0437\u0431\u043e\u0440\u0430 \u0437\u0430 \u043e\u0441\u0442\u0430\u043d\u0430\u043b\u0438\u0442\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u0438 \u0438\u043c\u0435\u043d\u0430 LocaleUtil.column.encoding=\u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 IrcClient.copyright=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0441\u0435 PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=\u0421\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435 \u043a\u044a\u043c IrcClient.connected=\u0421\u0432\u044a\u0440\u0437\u0430\u043d \u043a\u044a\u043c IrcClient.joining=\u041f\u0440\u0438\u0441\u044a\u0435\u0434\u0438\u043d\u044f\u0432\u0430\u043d\u0435 IrcClient.channel=\u041a\u0430\u043d\u0430\u043b IrcClient.joined=\u043f\u0440\u0438\u0441\u044a\u0435\u0434\u0438\u043d\u0435\u043d IrcClient.error=\u0413\u0440\u0435\u0448\u043a\u0430 IrcClient.hasjoined=\u0441\u0435 \u043f\u0440\u0438\u0441\u044a\u0435\u0434\u0438\u043d\u0438 IrcClient.haskicked=\u0438\u0437\u0433\u043e\u043d\u0438 IrcClient.hasleft=\u043d\u0430\u043f\u0443\u0441\u043d\u0430 IrcClient.nowknown=\u0432\u0435\u0447\u0435 \u0435 \u043f\u043e\u0437\u043d\u0430\u0442 \u043a\u0430\u0442\u043e IrcClient.topicforchannel=\u0422\u0435\u043c\u0430 \u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0430 IrcClient.disconnected=\u041f\u0440\u0435\u043a\u044a\u0441\u043d\u0430\u0442 \u043e\u0442 IrcClient.noNick=\u041d\u044f\u043c\u0430 \u043f\u0440\u044f\u043a\u043e\u0440. \u0414\u0430 \u0441\u0435 \u043e\u0442\u0432\u043e\u0440\u0438 \u0438\u0437\u0433\u043b\u0435\u0434 '\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f' IrcView.actionnotsupported=\u0422\u043e\u0432\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043d\u0435 \u0441\u0435 \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430 IrcView.clientsconnected=\u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 IrcView.privateto=\u0414\u043e IrcView.privatefrom=\u041e\u0442 IrcView.noticefrom=\u0411\u0435\u043b\u0435\u0436\u043a\u0430: IrcView.errormsg=\u0413\u0440\u0435\u0448\u0435\u043d \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0432 /msg - /msg user text IrcView.help=\u0412\u0430\u043b\u0438\u0434\u043d\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0438 \u0441\u0430:\n . /help \u043f\u043e\u043a\u0430\u0437\u0432\u0430 \u0442\u043e\u0432\u0430 \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u0435\n . /nick | /name \u043f\u0440\u043e\u043c\u0435\u043d\u044f \u0438\u043c\u0435\u0442\u043e \n . /me action \u0438\u0437\u043f\u0440\u0430\u0449\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \n . /msg nick message \u0438\u0437\u043f\u0440\u0430\u0449\u0430 \u043b\u0438\u0447\u043d\u043e \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0434\u043e \n . /r message \u043e\u0442\u0433\u043e\u0432\u043e\u0440 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u043e\u0442\u043e \u043b\u0438\u0447\u043d\u043e \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \n . /join #channelB (\u0434\u0430 \u043d\u0435 \u0441\u0435 \u043f\u043e\u0441\u043e\u0447\u0432\u0430 \u0442\u0443\u043a, \u0442\u043e\u0432\u0430 \u0435 \u043f\u0440\u0438\u043c\u0435\u0440) \u043f\u0440\u043e\u043c\u0435\u043d\u044f \u0442\u0435\u043a\u0443\u0449\u0438\u044f \u043a\u0430\u043d\u0430\u043b \u043d\u0430 channelB PasswordWindow.title=Vuze \u0435 \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d PasswordWindow.passwordprotected=Vuze \u0435 \u0437\u0430\u0449\u0438\u0442\u0435\u043d \u0441 \u043f\u0430\u0440\u043e\u043b\u0430.\n\u0417\u0430 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446\u0430 \u043d\u0430 \u0410zureus \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0432\u044a\u0432\u0435\u0434\u0435 \u043f\u0430\u0440\u043e\u043b\u0430: Button.ok=&\u0414\u0430 TrackerChangerWindow.title=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440 TrackerChangerWindow.newtracker=\u041d\u043e\u0432 URL \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440 PeersView.discarded=\u0418\u0437\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u043e PeersView.discarded.info=\u0414\u0430\u043d\u043d\u0438, \u043a\u043e\u0438\u0442\u043e \u043d\u044f\u043a\u0430\u043a \u0441\u0438 \u0441\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438, \u043d\u043e \u043d\u0435 \u0441\u0430 \u0431\u0438\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0438 \u0438 \u0441\u0430 \u043c\u0430\u0445\u043d\u0430\u0442\u0438. discarded=\u0438\u0437\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u043e MyTorrentsView.#=\u2116 MyTorrentsView.menu.move=\u041f\u0440\u0435&\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 MyTorrentsView.menu.moveUp=\u041d\u0430&\u0433\u043e\u0440\u0435 MyTorrentsView.menu.moveDown=\u041d\u0430&\u0434\u043e\u043b\u0443 GeneralView.label.hashfails=\u041f\u0440\u043e\u0432\u0430\u0301\u043b\u0438 \u0432 \u0440\u0430\u0437\u0431\u044a\u0440\u043a\u0432\u0430\u043d\u0435\u0442\u043e: GeneralView.label.shareRatio=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435\u0442\u043e: ConfigView.section.downloadManagement=\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f\u0442\u0430 ConfigView.label.startRatioPeers=\u0417\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0435\u0435\u043d\u0435 \u043f\u0440\u0438 <1 \u043f\u043e\u0441\u044f\u0432\u043a\u0430 \u0437\u0430 ConfigView.text.neverStop=\u0414\u0430 \u043d\u0435 \u0441\u0435 \u0441\u043f\u0438\u0440\u0430 ConfigView.text.neverStart=\u0414\u0430 \u043d\u0435 \u0441\u0435 \u0437\u0430\u043f\u043e\u0447\u0432\u0430 ConfigView.text.peers=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.label.checkOncompletion=\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435 \u043e\u0442\u043d\u043e\u0432\u043e \u043d\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u0430\u0442\u0430 \u043f\u0440\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 wizard.title=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 wizard.previous=\u2190 \u041d\u0430\u0437\u0430\u0434 wizard.next=\u041d\u0430\u043f\u0440\u0435\u0434 \u2192 wizard.finish=\u0413\u043e\u0442\u043e\u0432\u043e wizard.mode=\u0422\u0440\u0430\u043a\u0435\u0440/\u041d\u0430\u0447\u0438\u043d wizard.tracker=\u0422\u0440\u0430\u043a\u0435\u0440: wizard.invalidurl=\u0422\u043e\u0437\u0438 URL \u043d\u0435 \u0435 \u0432\u0430\u043b\u0438\u0434\u0435\u043d wizard.singlefile=\u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d \u0444\u0430\u0439\u043b wizard.singlefile.help=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u043e\u0442 \u0435\u0434\u0438\u043d \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d \u0444\u0430\u0439\u043b wizard.directory=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f wizard.directory.help=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u043e\u0442 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f wizard.choosefile=\u0424\u0430\u0439\u043b wizard.file=\u0424\u0430\u0439\u043b: wizard.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434\u0085\u2026 wizard.choosedirectory=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f wizard.invalidfile=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u0444\u0430\u0439\u043b! wizard.invaliddirectory=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f! wizard.torrentFile=\u0422\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b wizard.choosetorrent=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b \u0437\u0430 \u0441\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 wizard.information=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f wizard.notimplemented=\u041d\u0435 \u0435 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u043e \u043e\u0449\u0435 wizard.progresstitle=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b wizard.savingfile=\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u0085\u2026 wizard.filesaved=\u0424\u0430\u0439\u043b\u044a\u0442 \u0435 \u0437\u0430\u043f\u0430\u0437\u0435\u043d. wizard.close=\u0417\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 Torrent.create.progress.piecelength=\u0414\u044a\u043b\u0436\u0438\u043d\u0430 \u043d\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u0430\u0442\u0430: Torrent.create.progress.piececount=\u0411\u0440\u043e\u0439 \u043d\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u0430\u0442\u0430: Torrent.create.progress.totalfilesize=\u041e\u0431\u0449 \u0440\u0430\u0437\u043c\u0435\u0440 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435: Torrent.create.progress.totalfilecount=\u041e\u0431\u0449 \u0431\u0440\u043e\u0439 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435: Torrent.create.progress.parsingfiles=\u0420\u0430\u0437\u0431\u043e\u0440 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 Torrent.create.progress.hashing=\u0420\u0430\u0437\u0431\u044a\u0440\u043a\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 MainWindow.upgrade.downloadingfrom=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 \u043e\u0442: MainWindow.menu.view.ipFilter=&IP \u0424\u0438\u043b\u0442\u0440\u0438 ConfigView.section.ipfilter=IP \u0444\u0438\u043b\u0442\u0440\u0438 ConfigView.section.ipfilter.description=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 ConfigView.section.ipfilter.start=\u041d\u0430\u0447\u0430\u043b\u0435\u043d IP ConfigView.section.ipfilter.end=\u041a\u0440\u0430\u0435\u043d IP ConfigView.section.ipfilter.add=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 ConfigView.section.ipfilter.remove=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 ConfigView.section.ipfilter.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u043d\u0435 ConfigView.section.ipfilter.save=\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 ConfigView.section.ipfilter.editFilter=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0444\u0438\u043b\u0442\u044a\u0440 ConfigView.section.ipfilter.enable=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 PeersView.menu.close=&\u0417\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 seedmore.title=\u0422\u043e\u0440\u0435\u043d\u0442\u044a\u0442 \u043d\u0435 \u0435 \u0441\u044f\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u044a\u0447\u043d\u043e seedmore.shareratio=\u041c\u0435\u0441\u0442\u043d\u043e\u0442\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435\u0442\u043e \u0437\u0430 \u0442\u043e\u0437\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0435 seedmore.uploadmore=\u041a\u043e\u0435\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u0437\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435\u0442\u043e <100% \u043d\u0435 \u0435 \u0434\u043e\u0431\u0440\u043e \u043d\u0435\u0449\u043e \u0437\u0430 BitTorrent \u043c\u0440\u0435\u0436\u0430\u0442\u0430.\n\u0422\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u043e\u0441\u0442\u0430\u0432\u0438 \u0442\u043e\u0437\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0437\u0430 \u0441\u0435\u0435\u043d\u0435 \u043e\u0449\u0435 \u043c\u0430\u043b\u043a\u043e.\n\u0414\u0430 \u0441\u0435 \u0437\u0430\u0432\u044a\u0440\u0448\u0438 \u043b\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435\u0442\u043e? ConfigView.label.showpopuponclose=\u0414\u0438\u0430\u043b\u043e\u0433 \u0437\u0430 \u043f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0441\u043f\u0438\u0440\u0430\u043d\u0435 \u0441\u0435\u0435\u043d\u0435\u0442\u043e \u0441 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435\u0442\u043e <1 ConfigView.label.startNumSeeds=\n\u0417\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0435\u0435\u043d\u0435 \u043f\u0440\u0438 \u043f\u043e-\u043c\u0430\u043b\u043a\u043e \u043e\u0442\n - \u043f\u0440\u0435\u0432\u044a\u0437\u043c\u043e\u0433\u0432\u0430 \u043e\u0441\u0442\u0430\u043d\u0430\u043b\u0438\u0442\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 ConfigView.label.seeds=\u043f\u043e\u0441\u044f\u0432\u043a\u0438 ConfigView.section.seeding=\u0421\u0435\u0435\u043d\u0435 MyTorrentsView.menu.removeand=\u041f\u0440\u0435\u043c\u0430\u0445&\u0432\u0430\u043d\u0435 \u0438 MyTorrentsView.menu.removeand.deletetorrent=\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 &\u0442\u043e\u0440\u0435\u043d\u0442 MyTorrentsView.menu.removeand.deletedata=\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 &\u0434\u0430\u043d\u043d\u0438 MyTorrentsView.menu.removeand.deleteboth=\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434&\u0432\u0430\u0442\u0430 deletedata.title=\u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435 deletedata.message1=\u041f\u0440\u0435\u0434 \u0438\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0414\u0410\u041d\u041d\u0418 \u043e\u0442:\n deletedata.noprompt=\u0411\u0435\u0437 \u043d\u043e\u0432\u043e \u043f\u043e\u0434\u0441\u0435\u0449\u0430\u043d\u0435 MainWindow.menu.file.configure=\u0421\u044a\u0432\u0435\u0442\u043d\u0438\u043a \u0437\u0430 &\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u0085\u2026 configureWizard.title=\u0421\u044a\u0432\u0435\u0442\u043d\u0438\u043a \u0437\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 configureWizard.welcome.title=\u041f\u043e\u0437\u0434\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442 \u0421\u044a\u0432\u0435\u0442\u043d\u0438\u043a\u0430 \u0437\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430 Vuze configureWizard.welcome.message=\u0421\u044a\u0432\u0435\u0442\u043d\u0438\u043a \u0437\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u0442\u0435 \u043d\u0430 Vuze \u0437\u0430 \u043d\u0430\u0439-\u043e\u0431\u0449\u0430 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0430. \u0412\u044a\u0437\u043c\u043e\u0436\u043d\u0430 \u0435 \u043f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u0442\u0435 \u0432 \u0434\u0435\u0442\u0430\u0439\u043b\u0438 \u0447\u0440\u0435\u0437 \u043c\u0435\u043d\u044e '\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 \u2192 \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f'. configureWizard.transfer.title=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440 \u0438 \u0432\u0440\u044a\u0437\u043a\u0430 configureWizard.transfer.hint=\u041f\u0440\u0435\u043f\u043e\u0440\u044a\u043a\u0430: \u043f\u043e-\u0434\u043e\u0431\u0440\u0435 \u0434\u0430 \u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438 \u043f\u043e-\u0432\u0438\u0441\u043e\u043a\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043e\u0442 \u043d\u0430\u043b\u0438\u0447\u043d\u0430\u0442\u0430. configureWizard.transfer.message=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 \u043f\u043e-\u0434\u043e\u043b\u0443. \u0410\u043a\u043e \u043d\u0435 \u0441\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u044a\u0447\u043d\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435, \u0449\u0435 \u0441\u0435 \u043d\u0430\u043c\u0430\u043b\u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435. \u0421\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u0441\u0435 \u0441\u0447\u0438\u0442\u0430 \u0437\u0430 \u041e\u0422\u0414\u0415\u041b\u0415\u041d \u0442\u043e\u0440\u0435\u043d\u0442, \u043f\u0440\u0438 \u043e\u043f\u0438\u0442\u0438 \u0434\u0430 \u0441\u0435 \u0441\u0432\u0430\u043b\u044f\u0442 \u043c\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0435\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e, \u0442\u043e\u0432\u0430 \u0441\u044a\u0449\u043e \u0432\u043e\u0434\u0438 \u0434\u043e \u043f\u043e-\u043d\u0438\u0441\u043a\u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438. \u041f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u0441\u0435 \u0434\u0430 \u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438 5 kB/s \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u043a\u0430\u0442\u043e \u0422\u041e\u0427\u0415\u041d \u043c\u0438\u043d\u0438\u043c\u0443\u043c. \u041a\u043e\u043b\u043a\u043e\u0442\u043e \u043f\u043e-\u0432\u0438\u0441\u043e\u043a\u0430 \u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435, \u0442\u043e\u043b\u043a\u043e\u0432\u0430 \u043f\u043e-\u0431\u044a\u0440\u0437\u0438 \u0449\u0435 \u0431\u044a\u0434\u0430\u0442 \u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f\u0442\u0430 (\u0441 \u043e\u0442\u0447\u0438\u0442\u0430\u043d\u0435 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430). configureWizard.transfer.connection=\u041b\u0438\u043d\u0438\u044f configureWizard.transfer.connection.0=\u0414\u0440\u0443\u0433\u0430 configureWizard.transfer.connection.1=\u043c\u043e\u0434\u0435\u043c configureWizard.transfer.connection.2=adsl/cable xxx/128 kb/s configureWizard.transfer.connection.3=adsl/cable xxx/256 kb/s configureWizard.transfer.connection.4=adsl/cable xxx/384 kb/s configureWizard.transfer.connection.5=adsl/cable xxx/512 kb/s configureWizard.transfer.connection.6=adsl/cable xxx/768 kb/s configureWizard.transfer.connection.7=adsl/cable xxx/1024 kb/s configureWizard.transfer.maxUpSpeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 (KB/s) configureWizard.transfer.maxActiveTorrents=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0430\u043a\u0442\u0438\u0432\u043d\u0438 configureWizard.transfer.maxDownloads=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f configureWizard.transfer.maxUploadsPerTorrent=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u043e \u043a\u0430\u0447\u0432\u0430\u043d\u0438\u044f \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 configureWizard.nat.title=NAT/\u0441\u044a\u0440\u0432\u044a\u0440\u0435\u043d \u043f\u043e\u0440\u0442 configureWizard.nat.message=\u0417\u0430 \u043d\u0430\u0439-\u0434\u043e\u0431\u0440\u0438 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 \u043e\u0442 Vuze, \u0441\u0435 \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u0434\u0430 \u0438\u043c\u0430 \u043f\u044a\u043b\u0435\u043d \u0434\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430\u0442\u0430 \u043e\u0442 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442. \u0422\u043e\u0437\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430 \u0442\u0435\u0441\u0442 \u0438/\u0438\u043b\u0438 \u043f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442 \u0437\u0430 \u043f\u0440\u0438\u0435\u043c\u0430\u043d\u0435 \u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0438 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438.\n\n\u0417\u0430\u0431\u0435\u043b\u0435\u0436\u043a\u0430: \u0442\u043e\u0437\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0442\u0435\u0441\u0442\u0432\u0430 \u0437\u0430 TCP \u0432\u0440\u044a\u0437\u043a\u0438. \u0420\u0430\u0437\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430\u0442\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u0438 \u0441\u044a\u0449\u043e \u0442\u0430\u043a\u0430 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0432\u0445\u043e\u0434\u044f\u0449\u0438 UDP \u0432\u0440\u044a\u0437\u043a\u0438 \u0438 \u0449\u0435 \u0434\u0430\u0434\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0438\u0437\u0432\u0435\u0441\u0442\u0438\u0435, \u0430\u043a\u043e \u043e\u0442\u043a\u0440\u0438\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0435 \u043e\u0442 \u0437\u0430\u0449\u0438\u0442\u043d\u0430 \u0441\u0442\u0435\u043d\u0430.\n\n\u0417\u0430\u0431\u0435\u043b\u0435\u0436\u043a\u0430: TCP \u043f\u043e\u0440\u0442 6880 \u0435 \u0432\u044a\u0442\u0440\u0435\u0448\u043d\u043e \u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0430\u043d \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430. configureWizard.nat.test=\u0422\u0435\u0441\u0442 configureWizard.nat.testing=\u0422\u0435\u0441\u0442 \u043d\u0430 \u043f\u043e\u0440\u0442 configureWizard.nat.ok=\u0414\u0430! configureWizard.nat.ko=\u0413\u0440\u0435\u0448\u043a\u0430 \u0432 NAT configureWizard.nat.unable=\u041d\u0435\u0432\u044a\u0437\u043c\u043e\u0436\u0435\u043d \u0442\u0435\u0441\u0442: \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u043f\u043e\u0440\u0442 \u0438\u043b\u0438 \u0443\u0441\u043b\u0443\u0433\u0430\u0442\u0430 \u0437\u0430 \u0442\u0435\u0441\u0442 \u043d\u0435 \u0443\u0441\u043f\u044f.\n\u0412\u044a\u0437\u043c\u043e\u0436\u043d\u043e \u0435 \u0434\u0440\u0443\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u0430 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0432\u0435\u0447\u0435 \u0442\u043e\u0437\u0438 \u043f\u043e\u0440\u0442. configureWizard.file.title=\u0422\u043e\u0440\u0435\u043d\u0442\u0438/\u0444\u0430\u0439\u043b\u043e\u0432\u0435 configureWizard.file.message1=Vuze \u0449\u0435 \u0437\u0430\u043f\u0438\u0448\u0435 \u043e\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u0430 \u043f\u0430\u043f\u043a\u0430, \u043a\u043e\u044f\u0442\u043e \u0441\u0435 \u0438\u0437\u0431\u0438\u0440\u0430 \u0442\u0443\u043a: configureWizard.file.path=\u041f\u044a\u0442 configureWizard.file.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 configureWizard.file.message2=Vuze \u043c\u043e\u0436\u0435 \u0434\u0430 \u043f\u0440\u043e\u0434\u044a\u043b\u0436\u0438 \u0441 \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435 \u0432\u0435\u0434\u043d\u0430\u0433\u0430, \u0430\u043a\u043e \u043c\u0443 \u0431\u044a\u0434\u0430\u0442 \u0434\u043e\u0431\u0430\u0432\u0435\u043d\u0438 \u043a\u0440\u0430\u0442\u043a\u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u044a\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u0442\u0435. \u0421 \u0442\u043e\u0437\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043c\u043e\u0436\u0435 \u0441\u044a\u0449\u043e \u0434\u0430 \u0441\u0435 \u043f\u0440\u043e\u0434\u044a\u043b\u0436\u0438 \u0438 \u0441 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u0441\u0432\u0430\u043b\u0435\u043d\u0438 \u043f\u0430\u0440\u0447\u0435\u0442\u0430. configureWizard.file.fastResume=\u0414\u0430 \u043c\u043e\u0436\u0435 \u0431\u044a\u0440\u0437\u043e \u0434\u0430 \u043f\u0440\u043e\u0434\u044a\u043b\u0436\u0438 configureWizard.file.invalidPath=\u0413\u0440\u0435\u0448\u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f configureWizard.finish.title=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e configureWizard.finish.message=Vuze \u0432\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d, \u043f\u0440\u0438\u044f\u0442\u043d\u043e \u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435! wizard.close.confirmation=\u041f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435 wizard.close.message=\u0422\u043e\u0437\u0438 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u0434\u0430 \u0441\u0435 \u0437\u0430\u0440\u0435\u0434\u0438 \u043b\u0438\n \u0441\u043b\u0435\u0434\u0432\u0430\u0449\u0438\u044f \u043f\u044a\u0442, \u043a\u043e\u0433\u0430\u0442\u043e \u0441\u0435 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 Vuze? exportTorrentWizard.title=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u043d\u0430 XML \u0442\u043e\u0440\u0435\u043d\u0442 exportTorrentWizard.torrentfile.title=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 exportTorrentWizard.torrentfile.message=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b \u0437\u0430 \u0435\u043a\u0441\u043f\u043e\u0440\u0442 exportTorrentWizard.torrentfile.path=\u041f\u044a\u0442 exportTorrentWizard.torrentfile.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 exportTorrentWizard.torrentfile.invalidPath=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b exportTorrentWizard.exportfile.title=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0444\u0430\u0439\u043b \u0437\u0430 \u0435\u043a\u0441\u043f\u043e\u0440\u0442 exportTorrentWizard.exportfile.message=XML \u0444\u0430\u0439\u043b, \u0432 \u043a\u043e\u0439\u0442\u043e \u0434\u0430 \u0441\u0435 \u0435\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0430 exportTorrentWizard.exportfile.path=\u041f\u044a\u0442 exportTorrentWizard.exportfile.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 exportTorrentWizard.exportfile.invalidPath=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u0444\u0430\u0439\u043b \u0437\u0430 \u0435\u043a\u0441\u043f\u043e\u0440\u0442 exportTorrentWizard.finish.title=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e exportTorrentWizard.finish.message=\u0415\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0430\u043d\u0435\u0442\u043e \u0437\u0430\u0432\u044a\u0440\u0448\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e exportTorrentWizard.process.inputfilebad.title=\u0422\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u044a\u0442 \u0435 \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d exportTorrentWizard.process.inputfilebad.message=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u044f \u0444\u0430\u0439\u043b: exportTorrentWizard.process.outputfileexists.title=\u0421\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449 \u0444\u0430\u0439\u043b exportTorrentWizard.process.outputfileexists.message=\u0414\u0430 \u0441\u0435 \u043f\u0440\u0435\u0437\u0430\u043f\u0438\u0448\u0435 \u043b\u0438 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0438\u044f\u0442 \u0444\u0430\u0439\u043b? exportTorrentWizard.process.torrentfail.title=\u041f\u0440\u043e\u0432\u0430\u043b\u0435\u043d\u0438 \u043f\u0440\u043e\u0447\u0438\u0442\u0438 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 exportTorrentWizard.process.exportfail.title=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 exportTorrentWizard.process.unknownfail.title=\u041d\u0435\u043e\u0447\u0430\u043a\u0432\u0430\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 importTorrentWizard.title=\u0418\u043c\u043f\u043e\u0440\u0442 \u043d\u0430 XML \u0442\u043e\u0440\u0435\u043d\u0442 importTorrentWizard.torrentfile.title=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442 importTorrentWizard.torrentfile.message=\u0422\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b, \u0432 \u043a\u043e\u0439\u0442\u043e \u0434\u0430 \u0441\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0430 importTorrentWizard.torrentfile.path=\u041f\u044a\u0442 importTorrentWizard.torrentfile.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 importTorrentWizard.torrentfile.invalidPath=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b importTorrentWizard.importfile.title=\u0418\u043c\u043f\u043e\u0440\u0442 \u043d\u0430 \u0438\u0437\u0431\u0440\u0430\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 importTorrentWizard.importfile.message=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 XML \u0444\u0430\u0439\u043b \u0437\u0430 \u0438\u043c\u043f\u043e\u0440\u0442 importTorrentWizard.importfile.path=\u041f\u044a\u0442 importTorrentWizard.importfile.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 importTorrentWizard.importfile.invalidPath=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u0444\u0430\u0439\u043b \u0437\u0430 \u0438\u043c\u043f\u043e\u0440\u0442 importTorrentWizard.finish.title=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e importTorrentWizard.finish.message=\u0423\u0441\u043f\u0435\u0448\u0435\u043d \u0438\u043c\u043f\u043e\u0440\u0442 importTorrentWizard.process.inputfilebad.title=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u0444\u0430\u0439\u043b \u0437\u0430 \u0438\u043c\u043f\u043e\u0440\u0442 importTorrentWizard.process.inputfilebad.message=\u041f\u0440\u043e\u0432\u0430\u043b \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u0432\u0445\u043e\u0434\u0435\u043d \u0444\u0430\u0439\u043b: importTorrentWizard.process.outputfileexists.title=\u0424\u0430\u0439\u043b\u044a\u0442 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430 importTorrentWizard.process.outputfileexists.message=\u0418\u0437\u0445\u043e\u0434\u043d\u0438\u044f\u0442 \u0444\u0430\u0439\u043b \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430 - \u043f\u0440\u0435\u0437\u0430\u043f\u0438\u0441? importTorrentWizard.process.torrentfail.title=\u041f\u0440\u043e\u0432\u0430\u043b \u043f\u0440\u0438 \u0437\u0430\u043f\u0438\u0441 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 importTorrentWizard.process.importfail.title=\u041f\u0440\u043e\u0432\u0430\u043b \u043f\u0440\u0438 \u0438\u043c\u043f\u043e\u0440\u0442 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 importTorrentWizard.process.unknownfail.title=\u041d\u0435\u043e\u0447\u0430\u043a\u0432\u0430\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 ConfigView.label.bindip=\u041f\u0440\u0438\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435 \u043a\u044a\u043c \u043b\u043e\u043a\u0430\u043b\u0435\u043d IP \u0430\u0434\u0440\u0435\u0441 ConfigView.label.xfs.allocation=\u0417\u0430\u0434\u0435\u043b\u044f\u043d\u0435 \u043d\u0430 \u043d\u043e\u0432\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u043f\u043e \u043c\u0435\u0442\u043e\u0434 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u043d \u0437\u0430 XFS ConfigView.label.xfs.allocation.tooltip=\u0414\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u043d\u0430\u0442\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f \u043d\u0430 /usr/sbin/xfs_io \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0442\u0430. \u0412 \u043f\u043e\u0432\u0435\u0447\u0435\u0442\u043e Linux \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0446\u0438\u0438 \u0435 \u0447\u0430\u0441\u0442 \u043e\u0442 \u043f\u0430\u043a\u0435\u0442\u0430 "xfsprogs". xfs.allocation.xfs_io.not.found=\u0417\u0430\u0434\u0435\u043b\u044f\u043d\u0435\u0442\u043e \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0432 XFS \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438, /usr/sbin/xfs_io \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u044a\u043b\u043d\u0438. \u0414\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u0437\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u043d\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0442\u0430. \u0418\u0437\u0445\u043e\u0434\u043d\u0430\u0442\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 \u0435: "%1". ConfigView.label.zeronewfiles=\u041d\u0430\u0437\u043d\u0430\u0447\u0430\u0432\u0430\u043d\u0435 \u0438 \u043d\u0443\u043b\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043d\u043e\u0432\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u043f\u0440\u0438 \u0441\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 ConfigView.label.zeronewfiles.tooltip=\u041d\u0430\u043c\u0430\u043b\u044f\u0432\u0430 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0438\u0440\u0430\u043d\u0435\u0442\u043e ConfigView.section.stats=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 ConfigView.section.stats.enable=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 ConfigView.section.stats.defaultsavepath=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0437\u0430 \u0437\u0430\u043f\u0438\u0441 \u043d\u0430 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438\u0442\u0435 ConfigView.section.stats.choosedefaultsavepath=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0437\u0430 \u0437\u0430\u043f\u0438\u0441 \u043d\u0430 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438\u0442\u0435 ConfigView.section.stats.savefreq=\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0447\u0435\u0441\u0442\u043e\u0442\u0430 ConfigView.section.stats.minutes=\u043c\u0438\u043d ConfigView.section.stats.hours=\u0447\u0430\u0441 ConfigView.section.stats.seconds=\u0441\u0435\u043a ConfigView.section.stats.savefile=\u0418\u043c\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b \u0441\u044a\u0441 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 ConfigView.section.stats.graph_update_dividers=\u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u043d\u0430 \u043b\u0438\u043d\u0438\u044f \u043f\u0440\u0438 \u0432\u0441\u0435\u043a\u0438 60 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 MyTorrentsView.menu.export=&XML \u0442\u043e\u0440\u0435\u043d\u0442\u0085 MyTorrentsView.menu.host=&\u041f\u043e\u0434\u0441\u043b\u043e\u043d\u2026 ManagerItem.finishing=\u041f\u0440\u0438\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435 ConfigView.dialog.choosedefaulttorrentpath=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.dialog.choosemovepath=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0432 \u043a\u043e\u044f\u0442\u043e \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u043c\u0435\u0441\u0442\u0438 ConfigView.label.movecompleted=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438\u0442\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 ConfigView.label.moveremoved=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438\u0442\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 (\u043a\u043e\u0433\u0430\u0442\u043e \u0441\u0435 \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u0442) ConfigView.label.savetorrents=\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 .torrent \u0444\u0430\u0439\u043b\u043e\u0432\u0435 MainWindow.menu.view.mytracker=\u041c\u0435\u0441\u0442\u0435\u043d &\u0442\u0440\u0430\u043a\u0435\u0440 MyTrackerView.title.full=\u041c\u0435\u0441\u0442\u0435\u043d \u0422\u0440\u0430\u043a\u0435\u0440 MyTrackerView.name=\u0418\u043c\u0435 MyTrackerView.tracker=\u0422\u0440\u0430\u043a\u0435\u0440 MyTrackerView.status=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 MyTrackerView.status.started=\u0420\u0430\u0431\u043e\u0442\u0435\u0449\u043e MyTrackerView.status.stopped=\u0421\u043f\u0440\u044f\u043d\u043e MyTrackerView.peers=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 MyTrackerView.seeds=\u041f\u043e\u0441\u044f\u0432\u043a\u0438 MyTrackerView.announces=\u041e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0438\u044f MyTrackerView.uploaded=\u041a\u0430\u0447\u0435\u043d\u043e MyTrackerView.downloaded=\u0421\u0432\u0430\u043b\u0435\u043d\u043e MyTrackerView.left=\u041b\u044f\u0432\u043e ConfigView.section.style=\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 ConfigView.label.set_ui_transfer_speeds=\u041f\u0440\u0435\u0432\u044a\u0437\u043c\u043e\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u0431\u0438\u0440\u0430\u0435\u043c\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u043d\u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 ConfigView.label.set_ui_transfer_speeds.description=\u041c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u0431\u0435\u0440\u0435 \u0440\u044a\u0447\u043d\u043e \u0434\u0435\u0444\u0438\u043d\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0449\u0438\u0442\u0435 \u0441\u0435 \u043d\u0430\u043b\u0438\u0447\u043d\u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0438 \u043a\u0430\u0447\u0432\u0430\u043d\u0435, \u043a\u043e\u0438\u0442\u043e \u0441\u0435 \u043d\u0430\u043c\u0438\u0440\u0430\u0442 \u0432\u044a\u0440\u0445\u0443 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u043d\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440.\n\u0421\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0438\u0442\u0435 \u0434\u0430 \u0441\u0430 \u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b ",". ConfigView.label.set_ui_transfer_speeds.description.download=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 (KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 (KB/s) ConfigView.section.style.useCustomTabs=\u0417\u0430\u0442\u0432\u0430\u0440\u044f\u0449\u0438 \u0441\u0435 \u0441\u0435\u043a\u0446\u0438\u0438 (\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442) MainWindow.menu.view.plugins=&\u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 fileDownloadWindow.saveTorrentIn=\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b \u0432 fileDownloadWindow.title=Vuze - \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 fileDownloadWindow.downloading=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 \u043e\u0442: fileDownloadWindow.status=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435: fileDownloadWindow.state_initializing=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 fileDownloadWindow.state_downloading=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 fileDownloadWindow.state_error=\u0413\u0440\u0435\u0448\u043a\u0430: MainWindow.menu.file.open.url=&\u041c\u0435\u0441\u0442\u043e\u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435\u0085\u2026 openUrl.title=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u043c\u044f\u0441\u0442\u043e openUrl.url=URL: MyTorrentsView.menu.host.error.title=\u041f\u043e\u0434\u0441\u043b\u043e\u043d\u044f\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438 MyTorrentsView.menu.host.error.message=\u0418\u043c\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u0434\u0441\u043b\u043e\u043d\u044f\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.section.tracker=\u0422\u0440\u0430\u043a\u0435\u0440 ConfigView.section.tracker.pollinterval=\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0437\u0430 \u0431\u0440\u043e\u0435\u043d\u0435 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0438 \u043e\u0442 \u0442\u0440\u0430\u043a\u0435\u0440\u0430 [s] ConfigView.section.tracker.publishenable=\u041f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438\u0442\u0435 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0432 '' ConfigView.section.tracker.ip=\u0412\u044a\u043d\u0448\u0435\u043d IP \u0430\u0434\u0440\u0435\u0441 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440 ConfigView.section.style.enableXPStyle=\u041a\u0430\u043a\u0442\u043e \u0435 \u0432 XP (\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442) IPChecker.external.service.dyndns.name=\u0423\u0441\u043b\u0443\u0433\u0430 \u043e\u0442 "DynDNS" IPChecker.external.service.dyndns.description=\u0423\u0441\u043b\u0443\u0433\u0430 \u043e\u0442 "Dynamic DNS Network Services, LLC" ConfigView.section.tracker.checkip=\u0410\u0432\u0442\u043e-\u0440\u0430\u0437\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u044a\u043d\u0448\u043d\u0438\u044f \u0418\u041f (IP) \u0430\u0434\u0440\u0435\u0441\u0085\u2026 ipCheckerWizard.title=\u0421\u044a\u0432\u0435\u0442\u043d\u0438\u043a \u0437\u0430 IP \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 ipCheckerWizard.service=\u0423\u0441\u043b\u0443\u0433\u0430 ipCheckerWizard.chooseService=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0443\u0441\u043b\u0443\u0433\u0430 \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 IP \u043e\u0442 \u0441\u043f\u0438\u0441\u044a\u043a\u0430 \u0441 \u0443\u0441\u043b\u0443\u0433\u0438 ipCheckerWizard.explanations=\u0422\u043e\u0437\u0438 \u0441\u044a\u0432\u0435\u0442\u043d\u0438\u043a \u043c\u043e\u0436\u0435 \u0434\u0430 \u0440\u0430\u0437\u0431\u0435\u0440\u0435 \u043a\u0430\u043a\u044a\u0432 \u0435 \u043c\u0435\u0441\u0442\u043d\u0438\u044f\u0442 \u0432\u044a\u043d\u0448\u0435\u043d IP \u0430\u0434\u0440\u0435\u0441. \u0410\u043a\u043e IP \u0430\u0434\u0440\u0435\u0441\u044a\u0442 \u0435 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u043d, \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u0441\u0435 \u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0441\u043c\u0435\u0442\u043a\u0430 \u0441 \u0443\u0441\u043b\u0443\u0433\u0430 \u0437\u0430 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u043d DNS. \u041d\u044f\u043a\u043e\u0438 \u0442\u0430\u043a\u0438\u0432\u0430 \u0443\u0441\u043b\u0443\u0433\u0438 \u0441\u0430 \u0432 \u0441\u043f\u0438\u0441\u044a\u043a\u0430 \u043f\u043e-\u0434\u043e\u043b\u0443, \u0438 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u043f\u043e\u043b\u0437\u0432\u0430\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u0442\u0435 \u0432\u0440\u044a\u0437\u043a\u0438 \u0437\u0430 \u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0441\u043c\u0435\u0442\u043a\u0430 (\u043a\u044a\u0434\u0435\u0442\u043e \u0435 \u0432\u044a\u0437\u043c\u043e\u0436\u043d\u043e). \u0421\u043b\u0435\u0434 \u0442\u043e\u0432\u0430 \u0432 \u043f\u043e\u043b\u0435\u0442\u043e \u0437\u0430 IP \u0430\u0434\u0440\u0435\u0441 \u0434\u0430 \u0441\u0435 \u0432\u044a\u0432\u0435\u0434\u0435 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u043d\u043e\u0442\u043e \u0438\u043c\u0435 \u043d\u0430 \u043f\u043e\u0434\u0441\u043b\u043e\u043d (\u043f\u0440. myhostname.dyndns.org). \u0429\u0435 \u0435 \u043d\u0443\u0436\u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u0437\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0443\u0441\u043b\u0443\u0433\u0430\u0442\u0430 \u0437\u0430 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u043d DNS \u0441 \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u0438\u044f IP \u0430\u0434\u0440\u0435\u0441. \u0422\u0430\u043a\u0430 \u0449\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0441\u044a\u0445\u0440\u0430\u043d\u044f\u0432\u0430\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043c\u0435\u0441\u0442\u043d\u043e \u0434\u043e\u0440\u0438, \u0430\u043a\u043e IP \u0430\u0434\u0440\u0435\u0441\u044a\u0442 \u0441\u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u0438. ipCheckerWizard.service.description=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435: ipCheckerWizard.service.url=\u0412\u0440\u044a\u0437\u043a\u0430: ipCheckerWizard.progresstitle=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 IP ipCheckerWizard.checkComplete=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d IP: ipCheckerWizard.checkFailed=\u041f\u0440\u043e\u0432\u0430\u043b, \u043f\u0440\u0438\u0447\u0438\u043d\u0430: wizard.tracker.local=\u041c\u0435\u0441\u0442\u0435\u043d Vuze \u0432\u0433\u0440\u0430\u0434\u0435\u043d \u0442\u0440\u0430\u043a\u0435\u0440 wizard.tracker.external=\u0421 \u0432\u044a\u043d\u0448\u0435\u043d \u0442\u0440\u0430\u043a\u0435\u0440 wizard.tracker.howToLocal=\t\u0414\u0430 \u0441\u0435 \u043e\u0442\u0432\u043e\u0440\u0438 '\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 \u2192 \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u2192 \u0422\u0440\u0430\u043a\u0435\u0440' \u0437\u0430 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0443\u0441\u043b\u0443\u0433\u0430\u0442\u0430 wizard.announceUrl=URL \u0437\u0430 \u043e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0435: IPChecker.external.service.discoveryvip.name=\u0423\u0441\u043b\u0443\u0433\u0430 \u043e\u0442 "Discoveryvip" IPChecker.external.service.discoveryvip.description=Discoveryvip - \u0441\u0430\u043c\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 IP \u0430\u0434\u0440\u0435\u0441 IPChecker.external.httpinvalidresponse=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d HTTP \u043e\u0442\u0433\u043e\u0432\u043e\u0440 IPChecker.external.loadingwebpage=\u0417\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0443\u0435\u0431 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 IPChecker.external.analysingresponse=\u0410\u043d\u0430\u043b\u0438\u0437 \u043d\u0430 \u043e\u0442\u0433\u043e\u0432\u043e\u0440\u0430 IPChecker.external.addressextracted=\u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d \u0418\u041f (IP) \u0430\u0434\u0440\u0435\u0441 IPChecker.external.httploadfail=\u041f\u0440\u043e\u0432\u0430\u043b\u0435\u043d\u043e \u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 IPChecker.external.timeout=\u0418\u043c\u0430 \u043f\u0440\u043e\u0441\u0440\u043e\u0447\u0432\u0430\u043d\u0435 IPChecker.external.ipnotfound=IP \u0430\u0434\u0440\u0435\u0441\u044a\u0442 \u043d\u0435 \u0435 \u043d\u0430\u043c\u0435\u0440\u0435\u043d ConfigView.section.tracker.pollintervalmin=\u041c\u0438\u043d\u0438\u043c\u0443\u043c ConfigView.section.tracker.pollintervalmax=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c ConfigView.section.tracker.pollintervalincby=\u0423\u0432\u0435\u043b\u0438\u0447\u0430\u0432\u0430\u043d\u0435 \u0441 ConfigView.section.tracker.pollintervalincper=\u0412\u0441\u0435\u043a\u0438 'n' \u043a\u043b\u0438\u0435\u043d\u0442\u0438 splash.loadingImages=\u0417\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u043e\u0431\u0440\u0430\u0437\u0438 splash.initializeGui=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u0438\u044f \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 splash.openViews=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0438\u0437\u0433\u043b\u0435\u0434\u0438\u0442\u0435 splash.plugin=\u0417\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430: configureWizard.nat.tooManyPorts=\u041d\u0430\u0434\u0432\u0438\u0448\u0435\u043d \u0431\u0440\u043e\u0439 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 \u0437\u0430 \u0442\u0435\u0441\u0442 (\u22649) ConfigView.section.color=\u0426\u0432\u0435\u0442\u043e\u0432\u0430 \u0441\u0445\u0435\u043c\u0430 MyTorrentsView.menu.publish=\u041f\u0443&\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u0435\u0085 MyTrackerView.status.published=\u041f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u043e MyTrackerView.completed=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e MainWindow.menu.file.open.torrentnodefault=\u0422\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u2026\u0085 (\u0431\u0435\u0437 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435) wizard.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 ConfigView.label.movetorrent=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 .torrent ConfigView.label.movepartialdownloads=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435, \u043a\u043e\u0433\u0430\u0442\u043e \u0438\u043c\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0441 \u0444\u043b\u0430\u0433 "\u041d\u0435 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435" ConfigView.label.subdir_is_in_default=\u041f\u0440\u0438 \u043f\u0440\u0438\u0435\u043c\u0430\u043d\u0435, \u0447\u0435 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f\u0442\u0430 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0442 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f\u0442\u0430 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435, \u0434\u0430 \u0441\u0435 \u0438\u043c\u0430\u0442 \u043f\u0440\u0435\u0434\u0432\u0438\u0434 \u0438 \u043f\u043e\u0434\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438\u0442\u0435 ConfigView.section.file.decoder.label=\u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442, \u043a\u043e\u0433\u0430\u0442\u043e \u0441\u0435 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0438\u0437\u0431\u043e\u0440 ConfigView.section.file.decoder.nodecoder=\u041d\u044f\u043c\u0430 IPChecker.external.service.no-ip.name=\u0423\u0441\u043b\u0443\u0433\u0430 \u043e\u0442 "No-IP" IPChecker.external.service.no-ip.description=\u0414\u043e\u0441\u0442\u0430\u0432\u0447\u0438\u043a \u043d\u0430 \u0443\u0441\u043b\u0443\u0433\u0430 \u0437\u0430 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u043d \u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u043d DNS\n(\u0443\u0441\u043b\u0443\u0433\u0430\u0442\u0430 'check address' \u043d\u0435 \u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e \u0434\u043e\u0441\u0442\u044a\u043f\u043d\u0430) ConfigView.section.tracker.publicenable=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u044a\u043d\u0448\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.label.playdownloadspeech=\u0413\u043b\u0430\u0441\u043e\u0432\u043e \u0438\u0437\u0432\u0435\u0441\u0442\u0438\u0435 \u043f\u0440\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 ConfigView.label.playdownloadspeech.info=\u0423\u0441\u043b\u0443\u0433\u0438\u0442\u0435 \u0437\u0430 \u0440\u0435\u0447 \u043d\u0430\u0439-\u0434\u043e\u0431\u0440\u0435 \u0440\u0430\u0431\u043e\u0442\u044f\u0442 \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438 \u0432 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 # # Tooltips # GeneralView.label.status.pieces_available.tooltip=\u041f\u043e\u043a\u0430\u0437\u0432\u0430 \u0431\u0440\u043e\u044f \u043d\u0430\u043b\u0438\u0447\u043d\u0438 \u043a\u043e\u043f\u0438\u044f \u043d\u0430 \u0432\u0441\u044f\u043a\u043e \u043f\u0430\u0440\u0447\u0435.\n\u0410\u043a\u043e \u0447\u0438\u0441\u043b\u043e\u0442\u043e \u0432\u0434\u044f\u0441\u043d\u043e \u0435 <1, \u0437\u043d\u0430\u0447\u0438 \u043d\u0435 \u0441\u0435 \u0432\u0438\u0436\u0434\u0430 \u043f\u044a\u043b\u043d\u043e \u043a\u043e\u043f\u0438\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u0430 (\u0438 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u043e\u0447\u0430\u043a\u0432\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043d\u043e \u0437\u0430\u0432\u044a\u0440\u0448\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e). GeneralView.label.trackerurl.tooltip=\u0421 \u043f\u043e\u0441\u043e\u0447\u0432\u0430\u043d\u0435 \u0441\u0435 \u043a\u043e\u043f\u0438\u0440\u0430 URL \u043d\u0430 \u043e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0435\u0442\u043e \u0432 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434\u0430 GeneralView.label.trackerurlopen.tooltip=\u0421 \u043f\u043e\u0441\u043e\u0447\u0432\u0430\u043d\u0435 \u0441\u0435 \u043e\u0442\u0432\u0430\u0440\u044f \u0437\u0430\u0433\u043b\u0430\u0432\u043d\u0430\u0442\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430 # # 2.0.4.4 # ConfigView.section.style.guiUpdate=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 \u0413\u041f\u0418 \u043d\u0430 \u0432\u0441\u0435\u043a\u0438 ConfigView.section.style.inactiveUpdate=\u041e\u0431\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u0438\u044f \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 \u043d\u0430 \u0432\u0441\u0435\u043a\u0438 N \u043e\u043f\u0440\u0435\u0441\u043d\u044f\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0413\u041f\u0418, \u043a\u043e\u0433\u0430\u0442\u043e \u0435 \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u0435\u043d ConfigView.section.style.graphicsUpdate=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 \u0433\u0440\u0430\u0444\u0438\u0447\u043d\u0438\u0442\u0435 \u043b\u0435\u043d\u0442\u0438 \u0432\u0441\u0435\u043a\u0438 N \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f/\u0438 \u043d\u0430 \u0413\u041f\u0418 ConfigView.section.style.reOrderDelay=\u041f\u0440\u0435\u043f\u043e\u0434\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0438\u0442\u0435 \u043d\u0430 \u0432\u0441\u0435\u043a\u0438 N \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f/\u0438 \u043d\u0430 \u0413\u041f\u0418 [0: \u043d\u0438\u043a\u043e\u0433\u0430] ConfigView.section.style.reOrderDelay.never=\u041d\u0438\u043a\u043e\u0433\u0430 ConfigView.section.logging=\u0417\u0430\u043f\u0438\u0441\u0432\u0430\u043d\u0435 \u0432 \u0434\u043d\u0435\u0432\u043d\u0438\u043a ConfigView.section.logging.enable=\u0417\u0430\u043f\u0438\u0441 \u0432 \u0434\u043d\u0435\u0432\u043d\u0438\u043a ConfigView.section.logging.logdir=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u043d\u0430 \u0434\u043d\u0435\u0432\u043d\u0438\u043a\u0430 ConfigView.section.logging.choosedefaultsavepath=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 GeneralView.label.updatein.querying=\u0422\u044a\u0440\u0441\u0435\u043d\u0435\u0085\u2026 configureWizard.nat.sharePort=\u0412\u0441\u0438\u0447\u043a\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0434\u0430 \u0441\u0430 \u043f\u0440\u0435\u0437 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d \u0441\u043f\u043e\u0434\u0435\u043b\u0435\u043d \u0432\u0445\u043e\u0434\u044f\u0449 \u043f\u043e\u0440\u0442 ConfigView.section.logging.maxsize=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u0430 \u0433\u043e\u043b\u0435\u043c\u0438\u043d\u0430 \u043d\u0430 \u0434\u043d\u0435\u0432\u043d\u0438\u043a\u0430 ConfigView.section.tracker.passwordenableweb=\u0421 \u043f\u0430\u0440\u043e\u043b\u0430 \u0437\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0430\u0442\u0430 \u043c\u0440\u0435\u0436\u0430 ConfigView.section.tracker.passwordenabletorrent=\u0421 \u043f\u0430\u0440\u043e\u043b\u0430 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.section.tracker.username=\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u043e \u0438\u043c\u0435 ConfigView.section.tracker.password=\u041f\u0430\u0440\u043e\u043b\u0430 columnChooser.title=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u0438 \u0437\u0430 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 columnChooser.move=\u041f\u0440\u0435\u043f\u043e\u0434\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0440\u0435\u0434\u043e\u0432\u0435 \u0441\u0442\u0430\u0432\u0430 \u0441 \u0432\u043b\u0430\u0447\u0435\u043d\u0435 columnChooser.apply=\u041f\u0440\u0438\u043b\u0430\u0433\u0430\u043d\u0435 columnChooser.columnname=\u0418\u043c\u0435 \u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u0430 columnChooser.columndescription=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 TableColumn.header.shareRatio=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 MyTorrentsView.menu.editTableColumns=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430 &\u043a\u043e\u043b\u043e\u043d\u0438 wizard.operationfailed=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0442\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438 authenticator.title=\u0418\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0435 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435 authenticator.realm=\u041e\u0431\u043b\u0430\u0441\u0442 authenticator.tracker=\u0422\u0440\u0430\u043a\u0435\u0440 authenticator.user=\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u043e \u0438\u043c\u0435 authenticator.password=\u041f\u0430\u0440\u043e\u043b\u0430 ConfigView.label.allowSendVersion=Vuze \u0434\u0430 \u0438\u0437\u043f\u0440\u0430\u0449\u0430 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0438 \u0432\u0435\u0440\u0441\u0438\u044f \u0438 \u0441\u043b\u0443\u0447\u0430\u0435\u043d \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430 \u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0438\u044f ConfigView.label.version.info.link=\u0414\u0430 \u0441\u0435 \u043f\u043e\u0441\u0435\u0442\u0438 \u0442\u0443\u043a \u0437\u0430 \u0442\u043e\u0432\u0430 \u043a\u0430\u043a\u0432\u0438 \u0434\u0430\u043d\u043d\u0438 \u0441\u0435 \u0438\u0437\u043f\u0440\u0430\u0449\u0430\u0442 \u0434\u043e \u0441\u044a\u0440\u0432\u044a\u0440\u0430 \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044f wizard.hint.mode=\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430:\t\u041c\u043e\u0436\u0435 \u0434\u0430 \u0432\u043b\u0430\u0447\u0438-\u043f\u0443\u0441\u043d\u0435 \u0444\u0430\u0439\u043b \u0438\u043b\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0432 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a\u0430\n\t\u0437\u0430 \u0438\u0437\u0431\u043e\u0440 \u043d\u0430 \u0444\u0430\u0439\u043b \u0438\u043b\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f wizard.hint.file=\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430:\t\u041c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u0431\u0435\u0440\u0435 \u0444\u0430\u0439\u043b \u0441 \u0432\u043b\u0430\u0447\u0435\u043d\u0435-\u043f\u0443\u0441\u043a\u0430\u043d\u0435 wizard.hint.directory=\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430:\t\u041c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u0431\u0435\u0440\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0441 \u0432\u043b\u0430\u0447\u0435\u043d\u0435-\u043f\u0443\u0441\u043a\u0430\u043d\u0435 MainWindow.menu.help.checkupdate=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430&\u0446\u0438\u0438\u0085 TableColumn.header.down=\u0421\u0432\u0430\u043b\u0435\u043d\u043e TableColumn.header.up=\u041a\u0430\u0447\u0435\u043d\u043e ConfigView.section.tracker.passwordenabletorrent.info=\u0418\u0437\u0438\u0441\u043a\u0432\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449 BitTorrent \u043a\u043b\u0438\u0435\u043d\u0442 (\u043f\u0440. Vuze) ConfigView.section.style.confirmationOnExit=\u0414\u0438\u0430\u043b\u043e\u0433 \u0437\u0430 \u043f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0438\u0437\u0445\u043e\u0434 MainWindow.dialog.exitconfirmation.title=\u0418\u0437\u0445\u043e\u0434 \u043e\u0442 Vuze? MainWindow.dialog.exitconfirmation.text=\u041d\u0430\u0438\u0441\u0442\u0438\u043d\u0430 \u043b\u0438 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043b\u0435\u0437\u0435 \u043e\u0442 Vuze? SystemTray.menu.stopalltransfers=\u0421\u043f\u0438\u0440\u0430\u043d\u0435 \u0432\u0441\u0438\u0447\u043a\u0438 \u0442\u0440&\u0430\u043d\u0441\u0444\u0435\u0440\u0438 TrayWindow.menu.stopalldownloads=\u0421\u043f\u0438\u0440\u0430\u043d\u0435 \u0432\u0441\u0438\u0447\u043a\u0438 \u0441\u0432&\u0430\u043b\u044f\u043d\u0438\u044f ConfigView.section.tracker.sslport.info=\u0427\u0417\u0412 \u0437\u0430 \u0434\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f wizard.tracker.ssl=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 SSL ConfigView.label.playdownloadfinished=\u0417\u0432\u0443\u043a\u043e\u0432 \u0441\u0438\u0433\u043d\u0430\u043b \u043f\u0440\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 ConfigView.label.popupdownloadfinished=\u0418\u0437\u0441\u043a\u0430\u0447\u0430\u0449\u043e \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 ConfigView.label.popupfilefinished=\u0418\u0437\u0441\u043a\u0430\u0447\u0430\u0449\u043e \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d \u0444\u0430\u0439\u043b TableColumn.header.pieces=\u041f\u0430\u0440\u0447\u0435\u0442\u0430 TableColumn.header.pieces.info=\u0413\u0440\u0430\u0444\u0438\u0447\u043d\u0430 \u043b\u0435\u043d\u0442\u0430, \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u0449\u0430 \u043a\u043e\u0438 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 \u0441\u0430 \u0441\u0432\u0430\u043b\u0435\u043d\u0438 TableColumn.header.completion=\u0417\u0430\u0432\u044a\u0440\u0448\u0432\u0430\u043d\u0435 TableColumn.header.completion.info=\u0413\u0440\u0430\u0444\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 % \u0441\u0432\u0430\u043b\u0435\u043d\u043e ConfigView.section.style.showdownloadbasket=\u041a\u043e\u0448\u043d\u0438\u0446\u0430 \u0441\u044a\u0441 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f (\u0432\u043b\u0430\u0447\u0435\u043d\u0435-\u043f\u0443\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438) ConfigView.section.style.alwaysShowTorrentFiles=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435 \u0432 \u0414\u0435\u0442\u0430\u0439\u043b\u0438/\u0424\u0430\u0439\u043b\u043e\u0432\u0435 \u0432\u0438\u043d\u0430\u0433\u0438 wizard.multitracker=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u043c\u0443\u043b\u0442\u0438-\u0442\u0440\u0430\u043a\u0435\u0440 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043a\u044a\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0430 wizard.multitracker.title=\u041c\u0443\u043b\u0442\u0438-\u0442\u0440\u0430\u043a\u0435\u0440 wizard.multitracker.configuration=\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0437\u0430 \u043c\u0443\u043b\u0442\u0438-\u0442\u0440\u0430\u043a\u0435\u0440 wizard.multitracker.new=\u041d\u043e\u0432\u0085\u2026 wizard.multitracker.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u043d\u0435\u0085\u2026 wizard.multitracker.delete=\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 wizard.multitracker.group=\u0413\u0440\u0443\u043f\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0438 wizard.multitracker.edit.title=\u041c\u0443\u043b\u0442\u0438-\u0442\u0440\u0430\u043a\u0435\u0440 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 wizard.multitracker.edit.name=\u0418\u043c\u0435 wizard.multitracker.edit.save=\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 wizard.multitracker.edit.newgroup=\u041d\u043e\u0432\u0430 \u0433\u0440\u0443\u043f\u0430 wizard.multitracker.edit.deletegroup=\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 wizard.multitracker.edit.newtracker=\u041d\u043e\u0432 \u0442\u0440\u0430\u043a\u0435\u0440 wizard.multitracker.edit.deletetracker=\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 wizard.multitracker.edit.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u043d\u0435 wizard.addingmt=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u043c\u0443\u043b\u0442\u0438-\u0442\u0440\u0430\u043a\u0435\u0440 \u0434\u043e\u0431\u0430\u0432\u044f\u043d\u0435 wizard.multitracker.noannounce=URL \u0437\u0430 \u043e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0435 \u043d\u0435 \u0435 \u0432 \u0441\u043f\u0438\u0441\u044a\u043a\u0430 \u0441 \u0442\u0440\u0430\u043a\u0435\u0440\u0438 MyTorrentsView.menu.recheck=\u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440&\u043a\u0430 iconBar.showDownloadBar.tooltip=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f iconBar.start.tooltip=\u0421\u0442\u0430\u0440\u0442 iconBar.stop.tooltip=\u0421\u0442\u043e\u043f iconBar.remove.tooltip=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 iconBar.openNoDefault.tooltip=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b (\u0431\u0435\u0437 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435) iconBar.openURL.tooltip=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 URL iconBar.openFolder.tooltip=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u043f\u0430\u043f\u043a\u0430 iconBar.new.tooltip=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 iconBar.up.tooltip=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043f\u043e-\u0433\u043e\u0440\u0435 iconBar.down.tooltip=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043f\u043e-\u0434\u043e\u043b\u0443 iconBar.run.tooltip=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 iconBar.host.tooltip=\u041f\u043e\u0434\u0441\u043b\u043e\u043d iconBar.publish.tooltip=\u041f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u0435 iconBar.editcolumns.tooltip=\u0420\u0435\u0434\u0430\u043a\u0446\u0438\u044f \u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u0438 MyTorrentsView.menu.editTracker=\u0420&\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043d\u0435 URL(\u0442\u0430) \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440 GeneralView.menu.selectTracker=\u0418\u0437\u0431\u043e\u0440 ConfigView.section.stats.xslfile=\u0418\u043c\u0435 \u043d\u0430 XSL \u0444\u0430\u0439\u043b ConfigView.section.stats.xslfiledetails=\u0422\u043e\u0432\u0430 \u0449\u0435 \u0431\u044a\u0434\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0432 \u0437\u0430\u0433\u043b\u0430\u0432\u043a\u0430\u0442\u0430 \u043d\u0430 \u0444\u0430\u0439\u043b\u0430 \u0441\u044a\u0441 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0441 \u0435\u0442\u0438\u043a\u0435\u0442 ConfigView.label.savetorrentbackup=\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0437\u0430\u043f\u0430\u0300\u0441 ConfigView.section.tracker.forceport=\u041d\u0430\u0441\u0438\u043b\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0434\u0441\u043b\u043e\u043d\u0435\u043d\u0438\u0442\u0435 \u0432\u044a\u043d\u0448\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043a\u044a\u043c \u043f\u043e\u0440\u0442 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 ConfigView.section.ipfilter.allow=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u0435\u0437\u0438 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0438 (\u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u0441\u0435 \u043e\u0442\u043a\u0430\u0437\u0432\u0430\u0442) ConfigView.section.ipfilter.list.inrange=\u0435 \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d ConfigView.section.ipfilter.list.notinrange=\u043d\u0435 \u0435 \u0432 \u043a\u043e\u0439\u0442\u043e \u0438 \u0434\u0430 \u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d ConfigView.section.ipfilter.list.title=\u0411\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0438 IP-\u0442\u0430 ConfigView.label.allowsameip=\u041d\u044f\u043a\u043e\u043b\u043a\u043e \u0432\u0440\u044a\u0437\u043a\u0438 \u043e\u0442 \u0435\u0434\u0438\u043d IP \u0430\u0434\u0440\u0435\u0441 ConfigView.label.allowsameip.tooltip=\u0414\u0430 \u0441\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0438 \u0421\u0410\u041c\u041e \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442.\n\u0417\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u043f\u0438\u044f\u0432\u0438\u0446\u0438 (\u043a\u043e\u0433\u0430\u0442\u043e \u0435 \u0438\u0437\u043a\u043b\u044e\u0447\u0435\u043d\u043e). ManagerItem.superseeding=\u0421\u0443\u043f\u0435\u0440-\u0441\u0435\u0435\u043d\u0435 ConfigView.label.userSuperSeeding=\u0420\u0435\u0436\u0438\u043c \u0441\u0443\u043f\u0435\u0440-\u0441\u0435\u0435\u043d\u0435 PeersView.uniquepiece=\u041f\u0430\u0440\u0447\u0435\u0442\u0430 (\u0440\u0435\u0436\u0438\u043c \u0441\u0443\u043f\u0435\u0440-\u0441\u0435\u0435\u043d\u0435) PeersView.uniquepiece.none=\u041d\u044f\u043c\u0430 PeersView.timetosend=\u0412\u0440\u0435\u043c\u0435 \u0437\u0430 \u043f\u0440\u0435\u043f\u0440\u0430\u0449\u0430\u043d\u0435 \u043d\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 (\u0440\u0435\u0436\u0438\u043c \u0441\u0443\u043f\u0435\u0440-\u0441\u0435\u0435\u043d\u0435) ConfigView.section.style.addurlsilently=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 URL \u0442\u0438\u0445\u043e\u043c\u044a\u043b\u043a\u043e\u043c ConfigView.section.style.addurlsilently.tooltip=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043f\u0440\u0435\u043c\u0438\u043d\u0430\u043b\u0438\u0442\u0435/\u0438\u0437\u043f\u0443\u0441\u043d\u0430\u0442\u0438\u0442\u0435 .torrent URL-\u0442\u0430 \u0431\u0435\u0437 \u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u043d\u0430\u043f\u043e\u043c\u043d\u044f\u0449 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432 \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446. ConfigView.section.file.decoder.prompt=\u041f\u043e\u0434\u0441\u0435\u0449\u0430\u043d\u0435 \u0437\u0430 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u0432\u0438\u043d\u0430\u0433\u0438, \u043a\u043e\u0433\u0430\u0442\u043e \u0438\u043c\u0430 \u0438\u0437\u0431\u043e\u0440 ConfigView.section.file.decoder.prompt.tooltip=\u0414\u0438\u0430\u043b\u043e\u0433\u043e\u0432 \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 \u0437\u0430 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u0432\u0438\u043d\u0430\u0433\u0438, \u043a\u043e\u0433\u0430\u0442\u043e \u0438\u043c\u0430 \u0438\u0437\u0431\u043e\u0440 MyTorrentsView.menu.moveTop=&\u041d\u0430\u0439-\u0433\u043e\u0440\u0435 MyTorrentsView.menu.moveEnd=\u041d\u0430\u0439-\u0434\u043e\u043b&\u0443 ConfigView.label.moveonlyusingdefaultsave=\u0441\u0430\u043c\u043e \u0430\u043a\u043e \u0435 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f\u0442\u0430 \u0437\u0430 \u0434\u0430\u043d\u043d\u0438 \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 ConfigView.label.moveonlyusingdefaultsave.tooltip=\u0414\u0430 \u0441\u0435 \u043f\u0440\u0435\u043c\u0435\u0441\u0442\u0438 \u0441\u0430\u043c\u043e \u0430\u043a\u043e \u0441\u0432\u0430\u043b\u0435\u043d\u0438\u0442\u0435 \u0434\u0430\u043d\u043d\u0438 \u0441\u0430 \u0432 \u043f\u0430\u043f\u043a\u0430\u0442\u0430 \u0437\u0430 \u0434\u0430\u043d\u043d\u0438 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 ConfigView.label.watchtorrentfolder=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u043d \u0438\u043c\u043f\u043e\u0440\u0442 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.label.watchtorrentfolder.tooltip=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430 \u043d\u043e\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0440\u0435\u0434\u043e\u0432\u043d\u043e ConfigView.label.watchtorrentfolderinterval=\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b ConfigView.label.watchtorrentfolderinterval.tooltip=\u041f\u0430\u0443\u0437\u0430\u0442\u0430 \u0434\u043e \u043d\u043e\u0432\u043e \u0441\u043a\u0430\u043d\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u0430\u043f\u043a\u0430\u0442\u0430 ConfigView.dialog.choosewatchtorrentfolderpath=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0437\u0430 \u0438\u043c\u043f\u043e\u0440\u0442 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.label.startwatchedtorrentsstopped=\u0417\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u043f\u0440\u0435\u043d\u0438\u0442\u0435 ConfigView.label.startwatchedtorrentsstopped.tooltip=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u043d\u043e\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432 \u0421\u041f\u0420\u042f\u041d\u041e \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 ConfigView.section.plugins=\u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 wizard.maketorrent.filesize=\u0424\u0430\u0439\u043b(\u043e\u0432\u0435) \u0440\u0430\u0437\u043c\u0435\u0440 wizard.maketorrent.piececount=\u0411\u0440\u043e\u0439 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 wizard.maketorrent.piecesize=\u041f\u0430\u0440\u0447\u0435\u0442\u0430 \u0440\u0430\u0437\u043c\u0435\u0440 wizard.maketorrent.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e MainWindow.menu.view.stats=&\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 SpeedView.title.full=\u0414\u0435\u0439\u043d\u043e\u0441\u0442 SpeedView.downloadSpeed.title=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 \u0441 SpeedView.uploadSpeed.title=\u041a\u0430\u0447\u0432\u0430\u043d\u0435 \u0441 ConfigView.section.style.useSIUnits=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 SI \u0435\u0434\u0438\u043d\u0438\u0446\u0438 (KB \u2192 KiB \u0438 \u0434\u0440.) iconBar.top.tooltip=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430\u0439-\u0433\u043e\u0440\u0435 iconBar.bottom.tooltip=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430\u0439-\u0434\u043e\u043b\u0443 TableColumn.header.health=\u0417\u0434\u0440\u0430\u0432\u0438\u043d\u0430 MyTorrentsView.menu.health=\u0417\u0430 \u0437\u0434\u0440\u0430\u0432\u0438\u043d\u0430\u0442\u0430 health.explain.grey=\u043e\u0437\u043d\u0430\u0447\u0430\u0432\u0430, \u0447\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u044a\u0442 \u043d\u0435 \u0435 \u0430\u043a\u0442\u0438\u0432\u0435\u043d (\u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0438\u043b\u0438 \u043a\u0430\u0447\u0432\u0430\u043d\u0435) health.explain.red=\u043e\u0437\u043d\u0430\u0447\u0430\u0432\u0430, \u0447\u0435 \u043d\u044f\u043c\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d \u043f\u0440\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 health.explain.blue=\u043f\u0440\u0438 \u0441\u0435\u0435\u043d\u0435, \u043e\u0437\u043d\u0430\u0447\u0430\u0432\u0430 \u0447\u0435 \u043d\u044f\u043c\u0430 \u043e\u0449\u0435 \u0432\u0440\u044a\u0437\u043a\u0430 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\n\u043f\u0440\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0435, \u043e\u0437\u043d\u0430\u0447\u0430\u0432\u0430, \u0447\u0435 \u0438\u043c\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438, \u043d\u043e \u0442\u0440\u0430\u043a\u0435\u0440\u044a\u0442 \u0435 \u0438\u0437\u0447\u0435\u0437\u043d\u0430\u043b health.explain.yellow=\u043e\u0437\u043d\u0430\u0447\u0430\u0432\u0430, \u0447\u0435 \u0442\u0440\u0430\u043a\u0435\u0440\u044a\u0442 \u0435 \u0434\u043e\u0431\u0440\u0435, \u0438\u043c\u0430 \u0432\u0440\u044a\u0437\u043a\u0438 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438, \u043d\u043e \u043d\u044f\u043c\u0430 \u043e\u0442\u0434\u0430\u043b\u0435\u0447\u0435\u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430.\n\u0412\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u0438\u043c\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 NAT, \u0430\u043a\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u044a\u0442 \u0435 \u0441 \u0436\u044a\u043b\u0442 \u0446\u0432\u044f\u0442 \u043f\u0440\u0435\u0437 \u0446\u044f\u043b\u043e\u0442\u043e \u0432\u0440\u0435\u043c\u0435 health.explain.green=\u043e\u0437\u043d\u0430\u0447\u0430\u0432\u0430, \u0447\u0435 \u0432\u0441\u0438\u0447\u043a\u043e \u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e ConfigView.section.style.alwaysRefreshMyTorrents=\u041e\u043f\u0440\u0435\u0441\u043d\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 '\u041c\u0435\u0441\u0442\u043d\u0438 \u0422\u043e\u0440\u0435\u043d\u0442\u0438' \u0432\u0438\u043d\u0430\u0433\u0438 ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=\u0422\u043e\u0432\u0430 \u0449\u0435 \u043e\u043f\u0440\u0435\u0441\u043d\u044f\u0432\u0430 \u0438\u0437\u0433\u043b\u0435\u0434\u0430 \u0441 '\u041c\u0435\u0441\u0442\u043d\u0438 \u0422\u043e\u0440\u0435\u043d\u0442\u0438' \u0434\u043e\u0440\u0438 \u0434\u0430 \u043d\u0435 \u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d (\u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0437\u0430 \u043d\u044f\u043a\u043e\u0438 mIRC \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438) # #2.0.7.0 # security.certtruster.title=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u0437\u0430 \u0441\u0438\u0433\u0443\u0440\u043d\u043e\u0441\u0442\u0442\u0430 \u0437\u0430 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 security.certtruster.intro=\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044a\u0442 \u0435 \u0438\u0437\u0434\u0430\u0434\u0435\u043d \u043e\u0442 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f, \u043d\u0430 \u043a\u043e\u044f\u0442\u043e \u0441\u0435 \u043d\u044f\u043c\u0430 \u0434\u043e\u0432\u0435\u0440\u0438\u0435 security.certtruster.resource=\u0420\u0435\u0441\u0443\u0440\u0441: security.certtruster.issuedto=\u0418\u0437\u0434\u0430\u0434\u0435\u043d \u043d\u0430: security.certtruster.issuedby=\u0418\u0437\u0434\u0430\u0434\u0435\u043d \u043e\u0442: security.certtruster.prompt=\u0414\u0430 \u043c\u0443 \u0441\u0435 \u0438\u043c\u0430 \u043b\u0438 \u0434\u043e\u0432\u0435\u0440\u0438\u0435? security.certtruster.yes=\u0414\u0430 security.certtruster.no=\u041d\u0435 ConfigView.section.tracker.torrentsperpage=\u0411\u0440\u043e\u0439 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430? [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] MainWindow.menu.file.share=&\u0421\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 MainWindow.menu.file.share.file=&\u0424\u0430\u0439\u043b\u0085\u2026 MainWindow.menu.file.share.dir=&\u041f\u0430\u043f\u043a\u0430\u0085\u2026 MainWindow.menu.file.share.dircontents=\u0421&\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u043f\u043a\u0430\u0085\u2026 MainWindow.menu.file.share.dircontentsrecursive=\u0421\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u043f\u043a\u0430\u2026 (&\u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e) MainWindow.dialog.share.sharefile=\u0424\u0430\u0439\u043b \u0437\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 MainWindow.dialog.share.sharedir=\u041f\u0430\u043f\u043a\u0430 \u0437\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 MainWindow.dialog.share.sharedircontents=\u0421\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u043f\u043a\u0430 \u0437\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 MainWindow.dialog.share.sharedircontents.recursive=\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e globalmanager.download.remove.veto=\u0412\u0435\u0442\u043e \u043d\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043f\u043e \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 plugin.sharing.download.remove.veto=\u0422\u043e\u0432\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0435 \u0432 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435\u0442\u043e \u043d\u0430 \u0440\u0435\u0441\u0443\u0440\u0441.\n\u0417\u0430 \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e, \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u043c\u0430\u0445\u043d\u0435 \u0441\u044a\u043e\u0442\u0432\u0435\u0442\u043d\u043e\u0442\u043e \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=\u0413\u043b\u0430\u0432\u043d\u043e ConfigView.section.tracker.web=\u0423\u0435\u0431 ConfigView.label.prioritizefirstpiece=\u041f\u043e-\u0432\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0437\u0430 \u043f\u044a\u0440\u0432\u043e \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u043e \u043f\u0430\u0440\u0447\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b(\u043e\u0432\u0435) ConfigView.label.prioritizefirstpiece.tooltip=\u041e\u043f\u0438\u0442\u0432\u0430 \u0441\u0435 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043f\u044a\u0440\u0432\u043e \u043d\u0430 \u0441\u0430\u043c\u0438\u0442\u0435 \u043d\u0430\u0447\u0430\u043b\u043e \u0438 \u043a\u0440\u0430\u0439 \u043d\u0430 \u0444\u0430\u0439\u043b.\n\u0417\u0430 \u0432\u044a\u0437\u043c\u043e\u0436\u0435\u043d \u043f\u0440\u0435\u0433\u043b\u0435\u0434 \u0432 \u0440\u0430\u043d\u0435\u043d \u0441\u0442\u0430\u0434\u0438\u0439. ConfigView.section.file.confirm_data_delete=\u041f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0442\u0440\u0438\u0435\u043d\u0435 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438 ConfigView.section.file.confirm_data_delete.tooltip=\u041f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0442\u0440\u0438\u0435\u043d\u0435 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438 \u0441 '\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u0438 \u0438\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435\u0085\u2026' ConfigView.section.file.delete.include_files_outside_save_dir=\u041f\u0440\u0438 \u0438\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438 \u0434\u0430 \u0441\u0435 \u0442\u0440\u0438\u044f\u0442 \u0438 \u0441\u0432\u044a\u0440\u0437\u0430\u043d\u0438\u0442\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0438\u0437\u0432\u044a\u043d \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f\u0442\u0430 \u0437\u0430 \u0437\u0430\u043f\u0438\u0441 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 TrayWindow.menu.startalldownloads=\u0417\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 \u0432\u0441\u0438\u0447\u043a\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f SystemTray.menu.startalltransfers=\u0417\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 \u0432\u0441\u0438\u0447\u043a\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 sharing.progress.title=\u0420\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435\u0442\u043e sharing.progress.hide=\u0421\u043a\u0440\u0438\u0432\u0430\u043d\u0435 MainWindow.menu.view.myshares=\u041c\u0435\u0441\u0442\u043d\u043e \u0441\u043f\u043e\u0434\u0435\u043b\u0435\u043d\u0438 MySharesView.title.full=\u041c\u0435\u0441\u0442\u043d\u043e \u0441\u043f\u043e\u0434\u0435\u043b\u0435\u043d\u0438 MySharesView.name=\u0418\u043c\u0435 MySharesView.type=\u0422\u0438\u043f MySharesView.type.file=\u0424\u0430\u0439\u043b MySharesView.type.dir=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f MySharesView.type.dircontents=\u0421\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f MySharesView.type.dircontentsrecursive=\u0421\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f (\u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e) MySharesView.menu.remove=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 ConfigView.section.tracker.extensions=\u0420\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u044f ConfigView.section.tracker.sendpeerids=\u0418\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435 \u0441\u0430\u043c\u043e\u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d \u043a\u044a\u043c \u0441\u0432\u0430\u043b\u044f\u0449\u0438\u0442\u0435 ConfigView.section.tracker.enableudp=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 UDP \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b plugin.sharing.torrent.remove.veto=\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f\u0442\u0430 \u043d\u0430 \u0442\u043e\u0437\u0438 \u0442\u0440\u0430\u043a\u0435\u0440 \u0435 \u0432 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435\u0442\u043e \u043d\u0430 \u0440\u0435\u0441\u0443\u0440\u0441.\n\u0417\u0430 \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e, \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u043c\u0430\u0445\u043d\u0435 \u0441\u044a\u043e\u0442\u0432\u0435\u0442\u043d\u043e\u0442\u043e \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=\u0421\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u043c\u0430\u0445\u043d\u0435, \u0437\u0430\u0449\u043e\u0442\u043e \u043d\u0435 \u0435 \u0441\u043f\u0440\u044f\u043d\u043e plugin.sharing.remove.veto=\u0422\u043e\u0432\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 \u0435 \u043f\u043e\u0434-\u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 '\u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f' \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u0442\u0440\u0438\u0435.\n \u0414\u0430 \u0441\u0435 \u0438\u0437\u0442\u0440\u0438\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0442\u043e \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 GeneralView.label.hash.tooltip=\u0421 \u043f\u043e\u0441\u043e\u0447\u0432\u0430\u043d\u0435 \u0441\u0435 \u043a\u043e\u043f\u0438\u0440\u0430 \u0440\u0430\u0437\u0431\u044a\u0440\u043a\u0432\u0430\u043d\u0435\u0442\u043e \u0432 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434\u0430 ConfigView.section.tracker.maxpeersreturned=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0432\u044a\u0440\u043d\u0430\u0442\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.label.serverport=\u0412\u0445\u043e\u0434\u044f\u0449 TCP/UDP \u043f\u043e\u0440\u0442 \u0437\u0430 \u0441\u043b\u0443\u0448\u0430\u043d\u0435 ConfigView.label.serverport.tooltip=\u041f\u043e\u0440\u0442\u044a\u0442 \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0435 \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430 1-65535, \u043d\u043e \u043d\u0435 \u0438 6880, \u0437\u0430\u043f\u0430\u0437\u0435\u043d \u0437\u0430 \u0432\u044a\u0442\u0440\u0435\u0448\u043d\u0438 \u043d\u0443\u0436\u0434\u0438 \u043d\u0430 Vuze. configureWizard.nat.server.tcp_listen_port=\u0412\u0445\u043e\u0434\u044f\u0449 TCP \u043f\u043e\u0440\u0442 \u0437\u0430 \u0441\u043b\u0443\u0448\u0430\u043d\u0435 ConfigView.section.sharing=\u0421\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 ConfigView.section.sharing.usessl=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 SSL \u0437\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u0435\u043d\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0438 (\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430) ConfigView.section.style.dropdiraction=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043f\u0440\u0438 \u0432\u043b\u0430\u0447\u0435\u043d\u0435-\u043f\u0443\u0441\u043a\u0430\u043d\u0435 \u0437\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 ConfigView.section.style.dropdiraction.opentorrents=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.section.style.dropdiraction.sharefolder=\u0421\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 \u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f ConfigView.section.style.dropdiraction.sharefoldercontents=\u0421\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 \u043d\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435\u0442\u043e # # 2.0.7.x # Categories.all=\u0412\u0441\u0438\u0447\u043a\u043e Categories.uncategorized=\u0411\u0435\u0437 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f CategoryAddWindow.message=\u0418\u043c\u0435 \u043d\u0430 \u043d\u043e\u0432\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f CategoryAddWindow.title=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u043d\u043e\u0432\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f ConfigView.label.autoSeedingIgnoreInfo=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u043d\u0430\u0442\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043e\u0442\u0438\u0432\u0430\u0442 \u0432 \u043a\u0440\u0430\u044f \u043d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430 \u043e\u0442 \u043f\u043e\u0441\u044f\u0432\u043a\u0438. \u0422\u0435 \u043d\u0435 \u0441\u0435 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.\n\u041f\u0440\u0430\u0432\u0438\u043b\u0430\u0442\u0430 \u0437\u0430 \u043f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043d\u0435 \u043e\u0431\u0445\u0432\u0430\u0449\u0430\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u043e\u0442\u0433\u043e\u0432\u0430\u0440\u044f\u0449\u0438 \u043d\u0430 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0438\u0442\u0435 \u0437\u0430 \u041d\u0412\u041f.\n\u0410\u043a\u043e \u043d\u0435 \u0435 \u043f\u043e\u0441\u043e\u0447\u0435\u043d\u043e \u0434\u0440\u0443\u0433\u043e, \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 0 \u043d\u0435 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u043e. ConfigView.label.directory=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f ConfigView.label.disconnetseed.tooltip=\u041f\u0440\u0438 \u043f\u043e\u0441\u044f\u0432\u043a\u0430 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u043a\u044a\u0441\u043d\u0430\u0442 \u0432\u0441\u0438\u0447\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0438, \u043a\u043e\u0438\u0442\u043e \u0441\u0435\u044f\u0442.\n\u041d\u044f\u043c\u0430 \u043d\u0443\u0436\u0434\u0430 \u0434\u0430 \u043e\u0442 \u043a\u043e\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u044f \u0441 \u0442\u044f\u0445. ConfigView.label.ignoreCase=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u044a\u0440\u0430 ConfigView.label.ignoreSeeds=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441 \u043d\u0430\u0439-\u043c\u0430\u043b\u043a\u043e ConfigView.label.importdirectory=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0437\u0430 \u0438\u043c\u043f\u043e\u0440\u0442 ConfigView.label.minPeersToBoostNoSeeds.tooltip=\u0412\u0441\u0435\u043a\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0431\u0435\u0437 \u043f\u043e\u0441\u044f\u0432\u043a\u0438 \u0438\u043b\u0438 \u0441 \u043f\u043e-\u043c\u0430\u043b\u043a\u043e \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u043e\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043e\u0442\u043e\n\u0449\u0435 \u0431\u044a\u0434\u0435 \u043a\u044a\u043c \u043a\u0440\u0430\u044f \u043d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430. ConfigView.label.minPeersToBoostNoSeeds=\u041f\u043e-\u043d\u0438\u0441\u044a\u043a \u043f\u043e\u0441\u044f\u0432\u043a\u043e\u0432 \u0440\u0430\u043d\u0433 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0431\u0435\u0437 \u043f\u043e\u0441\u044f\u0432\u043a\u0438 \u0438\u043b\u0438 \u0441 \u043f\u043e-\u043c\u0430\u043b\u043a\u043e \u043e\u0442 ConfigView.label.minSeedingTime.tooltip=\u041f\u043e\u0441\u044f\u0432\u043a\u043e\u0432\u0438\u0442\u0435 \u0440\u0430\u043d\u0433\u043e\u0432\u0435 \u0441\u0435 \u043a\u043e\u043b\u0435\u0431\u0430\u044f\u0442 \u0447\u0435\u0441\u0442\u043e \u0432 \u043a\u0440\u0430\u0442\u044a\u043a \u043f\u0435\u0440\u0438\u043e\u0434 \u043a\u0430\u0442\u043e \u043f\u043e\u043d\u044f\u043a\u043e\u0433\u0430 \u043a\u0430\u0440\u0430\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0434\u0430 \u0437\u0430\u043f\u043e\u0447\u043d\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0432\u0430\u0449\u043e \u0434\u0430 \u0441\u043f\u0440\u0435 \u0438 \u0434\u0430 \u043e\u0442\u0438\u0434\u0435 \u043d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430 \u0432\u0435\u0434\u043d\u0430\u0433\u0430.\n\u041d\u0430\u0441\u0438\u043b\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0434\u0430 \u0441\u0442\u043e\u0438 \u0437\u0430 \u0441\u0435\u0435\u043d\u0435 \u0437\u0430 \u0434\u0430\u0434\u0435\u043d \u043f\u0435\u0440\u0438\u043e\u0434 \u043e\u0431\u043b\u0435\u043a\u0447\u0430\u0432\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430. \u041c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u0441\u043f\u0440\u044f\u043d \u0440\u044a\u0447\u043d\u043e \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0435. ConfigView.label.minSeedingTime=\u041c\u0438\u043d\u0438\u043c\u0443\u043c \u0432\u0440\u0435\u043c\u0435 \u0437\u0430 \u0441\u0435\u0435\u043d\u0435 [s] ConfigView.label.minSpeedForActiveDL.tooltip=\u0413\u043d\u0435\u0437\u0434\u043e \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0432\u0438\u043d\u0430\u0433\u0438 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0437\u0430 \u043d\u0430\u0447\u0430\u043b\u043d\u0438\u0442\u0435 30 \u0441\u0435\u043a\u0443\u043d\u0434\u0438\n\u0441\u043b\u0435\u0434 \u0437\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u043d\u0435\u043f\u044a\u043b\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442. ConfigView.label.minSpeedForActiveDL=\u0414\u0430 \u043d\u0435 \u0441\u0435 \u0441\u0447\u0438\u0442\u0430, \u0447\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u044a\u0442 \u043f\u043e\u043b\u0437\u0432\u0430 \u0433\u043d\u0435\u0437\u0434\u043e \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435, \u0430\u043a\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u0435 \u043f\u043e\u0434 ConfigView.label.peers=\u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.label.queue.debuglog=\u0414\u043d\u0435\u0432\u043d\u0438\u043a \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u043e\u0442\u0441\u0442\u0440\u0430\u043d\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 ConfigView.label.queue.debuglog.info=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u043e\u0442\u0441\u0442\u0440\u0430\u043d\u044f\u0432\u0430\u043d\u0435 \u0437\u0430 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430 \u043a\u044a\u043c \u043a\u043e\u043d\u0437\u043e\u043b\u0430/\u0434\u043d\u0435\u0432\u043d\u0438\u043a.\n\u041c\u0430\u043a\u0430\u0440 \u0438 \u0442\u0440\u0443\u0434\u043d\u0430 \u0437\u0430 \u0447\u0435\u0442\u0435\u043d\u0435, \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f\u0442\u0430 \u0437\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u043e\u0442\u0441\u0442\u0440\u0430\u043d\u044f\u0432\u0430\u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0432\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u0442\u0435 \u0438 \u0437\u0430\u0449\u043e \u0442\u0435 \u0441\u0430/\u043d\u0435 \u0441\u0430 \u0437\u0430\u043f\u043e\u0447\u043d\u0430\u0442\u0438/\u043d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430. ConfigView.label.queue.minQueueingShareRatio=\u0414\u0430 \u043d\u0435 \u0435 \u0432 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430 \u0438\u043b\u0438 \u0441\u043f\u0440\u0435 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u043e\u043a\u0430\u0442\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435\u0442\u043e \u043c\u0443 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 \u043d\u0435 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0435 ConfigView.label.ratio=\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 ConfigView.label.removeOnStop=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u043e\u0442 \u0441\u043f\u0438\u0441\u044a\u043a\u0430 \u0441\u043b\u0435\u0434 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0442\u043e \u043c\u0443 \u0441\u043f\u0438\u0440\u0430\u043d\u0435 ConfigView.label.savedirectory=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 ConfigView.label.seeding.autoReposition.tooltip=\u041f\u0440\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435, \u0440\u0435\u0434\u044a\u0442 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u0442\u0435 (\u043a\u043e\u043b\u043e\u043d\u0430 '\u2116') \u0449\u0435 \u0431\u044a\u0434\u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u0435\u043d \u0434\u0430 \u0441\u044a\u0432\u043f\u0430\u0434\u0430 \u0441 \u0442\u043e\u0437\u0438 \u043d\u0430 \u043f\u043e\u0441\u044f\u0432\u043a\u043e\u0432\u0438\u044f \u0440\u0430\u043d\u0433\n\u041f\u043e\u043b\u0435\u0437\u043d\u043e, \u0430\u043a\u043e \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f\u0442\u0430 \u043d\u0430 \u0447\u0438\u0441\u043b\u0430\u0442\u0430 \u043d\u0430 \u043f\u043e\u0441\u044f\u0432\u043a\u043e\u0432\u0438\u044f \u0440\u0430\u043d\u0433 \u0435 \u043d\u0435\u0436\u0435\u043b\u0430\u043d\u0430, \u043d\u043e \u0435 \u0436\u0435\u043b\u0430\u043d \u0440\u0435\u0434\u044a\u0442, \u0432 \u043a\u043e\u0439\u0442\u043e \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0449\u0435 \u0437\u0430\u043f\u043e\u0447\u0432\u0430\u0442. ConfigView.label.seeding.autoReposition=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u043f\u043e\u0434\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441\u043f\u043e\u0440\u0435\u0434 \u043f\u043e\u0441\u044f\u0432\u043a\u043e\u0432\u0438\u044f \u0440\u0430\u043d\u0433 ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u0427\u0435\u0441\u0442\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u0438\u043c\u0430\u0449\u0438 \u043d\u0438\u0441\u044a\u043a \u043f\u043e\u0441\u044f\u0432\u043a\u043e\u0432 \u0431\u0440\u043e\u0439 \u0438 \u0433\u043e\u043b\u044f\u043c \u0431\u0440\u043e\u0439 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438, \u0437\u043d\u0430\u0447\u0438, \u0447\u0435 \u043d\u044f\u043c\u0430 \u043f\u044a\u043b\u043d\u043e \u043a\u043e\u043f\u0438\u0435 \u0441\u0440\u0435\u0434 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u0442\u0435.\n\u041c\u043e\u0436\u0435 \u0434\u0430 \u043d\u0435 \u0435 \u0436\u0435\u043b\u0430\u043d\u043e \u043f\u0440\u0438\u043b\u0430\u0433\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u043f\u043e\u0441\u044f\u0432\u043a\u043e\u0432\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043a\u0430\u0442\u043e \u0441\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430, \u0447\u0435 \u0438\u043c\u0430 \u043f\u044a\u043b\u043d\u043e \u043a\u043e\u043f\u0438\u0435 (\u043f\u043e \u0442\u043e\u0437\u0438 \u043d\u0430\u0447\u0438\u043d \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u043d\u043e \u0441\u0435 \u0441\u0432\u0430\u043b\u044f \u0440\u0430\u043d\u0433\u0430) ConfigView.label.seeding.fakeFullCopySeedStart=\u043d\u043e \u0441\u0430\u043c\u043e \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441 \u043d\u0430\u0439-\u043c\u0430\u043b\u043a\u043e ConfigView.label.seeding.ignore=\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0437\u0430 \u043f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 ConfigView.label.seeding.ignore0Peers=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441 0 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.label.seeding.ignoreRatioPeers=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441 \u043d\u0430\u0439-\u043c\u0430\u043b\u043a\u043e 1 \u043f\u043e\u0441\u044f\u0432\u043a\u0430 \u0437\u0430 \u0432\u0441\u0435\u043a\u0438 ConfigView.label.seeding.ignoreShareRatio=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435\u0442\u043e \u043e\u0442 ConfigView.label.seeding.ignore.header.evenFirstPriority=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442, \u0434\u043e\u0440\u0438 \u043a\u043e\u0433\u0430\u0442\u043e\n\u0434\u0435\u0439\u0441\u0442\u0432\u0430\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u0442\u0430 \u0437\u0430 \u043d\u0430\u0439-\u0432\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.label.seeding.ignore.header.rule=\u041f\u0440\u0430\u0432\u0438\u043b\u043e ConfigView.label.seeding.ignore.header.value=\u0421\u0442\u043e\u0439\u043d\u043e\u0441\u0442 ConfigView.label.seeding.firstPriority.info=\u041d\u0430\u0439-\u0432\u0438\u0441\u043e\u043a\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043d\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0449\u0435 \u0441\u0430 \u0432\u0438\u043d\u0430\u0433\u0438 \u043d\u0430\u0439-\u043e\u0442\u043f\u0440\u0435\u0434 \u0432 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430.\n\u041d\u0438\u043a\u043e\u0439 \u043e\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u0442\u0435, \u043e\u0442\u0433\u043e\u0432\u0430\u0440\u044f\u0449\u0438 \u043d\u0430 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f \u0437\u0430 \u041d\u0412\u041f \u043d\u044f\u043c\u0430 \u0434\u0430 \u0431\u044a\u0434\u0430\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0441\u043f\u0438\u0440\u0430\u043d\u0438 \u0438 \u0441\u043b\u0430\u0433\u0430\u043d\u0438 \u0432 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430.\n\u0422\u043e\u0440\u0435\u043d\u0442, \u043e\u0442\u0433\u043e\u0432\u0430\u0440\u044f\u0449 \u043d\u0430 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f \u0437\u0430 \u041d\u0412\u041f \u0449\u0435 \u0437\u0430\u0435\u043c\u0435 \u0433\u043d\u0435\u0437\u0434\u043e \u0437\u0430 \u0435\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435, \u0430\u043a\u043e \u043c\u0443 \u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e. ConfigView.label.seeding.firstPriority.FP=\u041d\u0430\u0439-\u0432\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.label.seeding.firstPriority=\u041d\u0430\u0439-\u0432\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0441\u0435 \u0434\u0430\u0432\u0430 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441 ConfigView.label.seeding.firstPriority.following=\u043e\u0442 \u0441\u043b\u0435\u0434\u043d\u043e\u0442\u043e: ConfigView.label.seeding.firstPriority.shareRatio=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435\u0442\u043e \u043f\u043e\u0434 ConfigView.label.seeding.firstPriority.seedingMinutes=\u0418\u0437\u043c\u0438\u043d\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u0435 \u043e\u0442\u043a\u0430\u043a\u0442\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e \u0441\u0435 \u0435 \u0441\u043c\u0435\u043d\u0438\u043b\u043e \u0441\u044a\u0441 \u0441\u0435\u0435\u043d\u0435 ConfigView.label.seeding.firstPriority.DLMinutes=\u0418\u0437\u043c\u0438\u043d\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u0435 \u043e\u0442 \u043d\u0430\u0447\u0430\u043b\u043e\u0442\u043e \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 ConfigView.label.seeding.numPeersAsFullCopy.tooltip=\u0421 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u043d\u0435\u0442\u043e, \u0447\u0435 \u0438\u043c\u0430 1 \u043f\u044a\u043b\u043d\u043e \u043a\u043e\u043f\u0438\u0435 \u0437\u0430 \u0425 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438, \u0441\u0435 \u043d\u0430\u043c\u0430\u043b\u044f\u0432\u0430 \u0440\u0430\u043d\u0433\u0430 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u0442\u0435 \u0441 \u043c\u043d\u043e\u0433\u043e\u0431\u0440\u043e\u0439\u043d\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438.\n\u041d\u0430\u0439-\u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u0432\u0438\u0441\u043e\u043a\u0438\u044f \u0431\u0440\u043e\u0439 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0438\u043c\u0430\u0442 \u0438 \u0433\u043e\u043b\u044f\u043c \u0442\u0440\u0430\u0444\u0438\u043a.\n\u0422\u043e\u0432\u0430 \u043d\u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u044f \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0438\u0442\u0435 '\u0431\u0440. \u043f\u043e\u0441\u044f\u0432\u043a\u0438'. ConfigView.label.seeding.numPeersAsFullCopy=\u0414\u043e\u043f\u0443\u0441\u043a\u0430\u043d\u0435, \u0447\u0435 \u0438\u043c\u0430 1 \u043f\u044a\u043b\u043d\u043e \u043a\u043e\u043f\u0438\u0435 \u0437\u0430 \u0432\u0441\u0435\u043a\u0438\n[0: \u0431\u0435\u0437 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u043d\u0435] ConfigView.label.seeding.preferLargerSwarms.tooltip=\u0410\u043a\u043e \u0441\u0435 \u0441\u0435\u044f\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043f\u0440\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438, \u043a\u043e\u0438\u0442\u043e \u0441\u0430 "\u0437\u0430\u0431\u0438\u043b\u0438", \u0438\u043c\u0430 \u0441\u043c\u0438\u0441\u044a\u043b \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0442 \u043f\u043e-\u0433\u043e\u043b\u0435\u043c\u0438 \u0440\u043e\u044f\u0446\u0438\n\u0410\u043a\u043e \u0441\u0435 \u0441\u0435\u044f\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441 \u0433\u043e\u043b\u044f\u043c\u0430 \u043d\u0430\u043c\u0438\u0440\u0430\u0435\u043c\u043e\u0441\u0442, \u0438\u043c\u0430 \u0441\u043c\u0438\u0441\u044a\u043b \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0442 \u043f\u043e-\u043c\u0430\u043b\u043a\u0438 \u0440\u043e\u044f\u0446\u0438. ConfigView.label.seeding.preferLargerSwarms=\u041a\u043e\u0433\u0430\u0442\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u0442\u0435 \u0438\u043c\u0430\u0442 \u0435\u0434\u043d\u0430\u043a\u044a\u0432 \u0440\u0430\u043d\u0433, \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0442 \u043f\u043e-\u0433\u043e\u043b\u0435\u043c\u0438\u0442\u0435 \u0440\u043e\u044f\u0446\u0438 ConfigView.label.seeding.rankType.none.tooltip=\u041f\u043e\u0434\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043f\u043e \u043a\u043e\u043b\u043e\u043d\u0430 "\u2116" ConfigView.label.seeding.rankType.none=\u041d\u044f\u043c\u0430 ConfigView.label.seeding.rankType.peer.tooltip=\u043f\u043e\u0432\u0435\u0447\u0435 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0438 \u043f\u043e-\u043c\u0430\u043b\u043a\u043e \u043f\u043e\u0441\u044f\u0432\u043a\u0438 = \u043f\u043e-\u0432\u0438\u0441\u043e\u043a \u0440\u0430\u043d\u0433\n\u0422\u043e\u0432\u0430 \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0430 \u0431\u0440\u043e\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u043a\u043e\u0438\u0442\u043e \u0434\u0430 \u0441\u0435 \u0434\u044a\u0440\u0436\u0430\u0442 \u0430\u043a\u0442\u0438\u0432\u043d\u0438 \u0437\u0430 \u043c\u0430\u043a\u0441\u0438\u043c\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435\u0442\u043e ConfigView.label.seeding.rankType.peer=\u041f\u0440\u0435\u0442\u0435\u0433\u043b\u0435\u043d \u0431\u0440\u043e\u0439 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.label.seeding.rankType.peerSeed.options=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435\u0442\u043e \u041f\u043e\u0441\u044f\u0432\u043a\u0438:\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.label.seeding.rankType.peerSeed.tooltip=\u041f\u043e-\u0432\u0438\u0441\u043e\u043a\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 = \u043f\u043e-\u0432\u0438\u0441\u043e\u043a \u0440\u0430\u043d\u0433 ConfigView.label.seeding.rankType.peerSeed=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438:\u041f\u043e\u0441\u044f\u0432\u043a\u0438 ConfigView.label.seeding.rankType.seed.fallback=\u041e\u0442\u0441\u0442\u044a\u043f\u043b\u0435\u043d\u0438\u0435 \u043a\u044a\u043c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438:\u041f\u043e\u0441\u044f\u0432\u043a\u0438 \u0441\u043b\u0435\u0434\n[0: \u0431\u0435\u0437 \u043e\u0442\u0441\u0442\u044a\u043f\u043b\u0435\u043d\u0438\u0435] ConfigView.label.seeding.rankType.seed.options=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u0431\u0440\u043e\u0439 \u0441\u0430\u043c\u043e \u043f\u043e\u0441\u044f\u0432\u043a\u0438 ConfigView.label.seeding.rankType.seed.tooltip=\u041f\u043e-\u043c\u0430\u043b\u043a\u043e \u043f\u043e\u0441\u044f\u0432\u043a\u0438 = \u043f\u043e-\u0432\u0438\u0441\u043e\u043a \u0440\u0430\u043d\u0433 ConfigView.label.seeding.rankType.seed=\u0411\u0440\u043e\u0439 \u0441\u0430\u043c\u043e \u043f\u043e\u0441\u044f\u0432\u043a\u0438 ConfigView.label.seeding.rankType.timedRotation.tooltip=\u0412\u0441\u0438\u0447\u043a\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430 \u0449\u0435 \u0441\u0435 \u0432\u044a\u0440\u0442\u044f\u0442 \u0432 \u0440\u0435\u0436\u0438\u043c \u043d\u0430 \u0441\u0435\u0435\u043d\u0435.\n\u041f\u0440\u043e\u0434\u044a\u043b\u0436\u0438\u0442\u0435\u043b\u043d\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u0432\u0440\u0435\u043c\u0435\u0442\u043e \u0437\u0430 \u0441\u0435\u0435\u043d\u0435 \u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u0432\u0430 \u043e\u0442 '\u041c\u0438\u043d\u0438\u043c\u0443\u043c \u0432\u0440\u0435\u043c\u0435 \u0437\u0430 \u0441\u0435\u0435\u043d\u0435' ConfigView.label.seeding.rankType.timedRotation=\u0420\u043e\u0442\u0430\u0446\u0438\u044f \u043f\u043e \u0433\u0440\u0430\u0444\u0438\u043a ConfigView.label.seeding.rankType.tooltip=\u0422\u043e\u0440\u0435\u043d\u0442\u0438\u0442\u0435 \u0441 \u043d\u0430\u0439-\u0432\u0438\u0441\u043e\u043a \u0440\u0430\u043d\u0433 \u0437\u0430\u043f\u043e\u0447\u0432\u0430\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.\n\u041a\u043e\u0433\u0430\u0442\u043e \u043d\u044f\u043a\u043e\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 \u043f\u0440\u0438\u0434\u043e\u0431\u0438\u0435 \u043f\u043e-\u0432\u0438\u0441\u043e\u043a \u0440\u0430\u043d\u0433, \u0442\u043e\u0437\u0438 \u0441 \u043f\u043e-\u043d\u0438\u0441\u044a\u043a \u0441\u043f\u0438\u0440\u0430 \u0438 \u043e\u0442\u0438\u0432\u0430 \u043d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430.\n\n\u0421\u0430\u043c\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0447\u0430\u043a\u0430\u0449\u0438 \u0432 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430 \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u0437\u0430\u043f\u043e\u0447\u043d\u0430\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.\n\u0421\u043f\u0440\u0435\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043d\u0438\u043a\u043e\u0433\u0430 \u043d\u0435 \u0437\u0430\u043f\u043e\u0447\u0432\u0430\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e. ConfigView.label.seeding.rankType=\u0414\u0430 \u0441\u0435 \u0434\u0430\u0432\u0430 \u0440\u0430\u043d\u0433 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0437\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u0442\u0430 \u043d\u0430: ConfigView.label.stopAfterMinutes=\u0412\u0435\u0434\u043d\u044a\u0436 \u043f\u0440\u0435\u0432\u043a\u043b\u044e\u0447\u0435\u043d \u043a\u044a\u043c \u0441\u0435\u0435\u043d\u0435, \u0434\u0430 \u0441\u043f\u0440\u0435 \u0441\u043b\u0435\u0434 \u043f\u0435\u0440\u0438\u043e\u0434 \u043e\u0442 \u0432\u0440\u0435\u043c\u0435 ConfigView.label.switchpriority.tooltip=\u041d\u0438\u0441\u043a\u0438\u044f\u0442 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043d\u0430\u043c\u0430\u043b\u044f\u0432\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u0442\u043e \u0448\u0438\u0440\u043e\u0447\u0438\u043d\u0430 \u043d\u0430 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u0437\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435, \u043f\u0430\u0434\u0430\u0449\u0430 \u0441\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430. ConfigView.pluginlist.info=\u0421\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0441\u0430 \u0440\u0430\u0437\u043f\u043e\u0437\u043d\u0430\u0442\u0438. \u041d\u044f\u043a\u043e\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u043c\u043e\u0436\u0435 \u0434\u0430 \u043d\u044f\u043c\u0430\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0438 \u0441\u0435\u043a\u0446\u0438\u0438. ConfigView.pluginlist.noplugins=\u041d\u044f\u043c\u0430 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438. ConfigView.section.pluginslist=\u0421\u043f\u0438\u0441\u044a\u043a ConfigView.section.queue.seeding=\u0421\u0435\u0435\u043d\u0435 ConfigView.section.queue.seeding.autoStarting=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 ConfigView.section.queue.seeding.ignore=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u0442\u0430 ConfigView.section.queue.seeding.firstPriority=\u041d\u0430\u0439-\u0432\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.section.queue.main=\u0413\u043b\u0430\u0432\u043d\u043e ConfigView.section.queue=\u041d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430 ConfigView.section.torrents=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.text.all=\u0432\u0441\u0438\u0447\u043a\u043e ConfigView.text.hours=\u0447\u0430\u0441\u0430 ConfigView.text.ignoreRule=\u041f\u0440\u0430\u0432\u0438\u043b\u043e \u0437\u0430 \u043f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 ConfigView.text.ignore=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 ConfigView.text.minutes=\u043c\u0438\u043d\u0443\u0442\u0438 ConfigView.text.neverIgnore=\u0414\u0430 \u043d\u0435 \u0441\u0435 \u043f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430 ConfigView.text.any=\u0432\u0441\u044f\u043a\u043e DownloadManager.error.datamissing=\u041b\u0438\u043f\u0441\u0432\u0430\u0449\u0438 \u0434\u0430\u043d\u043d\u0438 MainWindow.menu.file.open.torrentforseeding=\u0422\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u2026\u0085 (\u0437\u0430 \u0441\u0435\u0435\u043d\u0435) MainWindow.menu.language.refresh=\u041e\u043f&\u0440\u0435\u0441\u043d\u044f\u0432\u0430\u043d\u0435 ManagerItem.forced=\u041d\u0430\u0441\u0438\u043b\u0435\u043d ManagerItem.queued=\u041d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430 MySeedersView.header=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.availability.info=\u0411\u0440. \u0432\u0438\u0436\u0434\u0430\u0449\u0438 \u0441\u0435 \u043f\u044a\u043b\u043d\u0438 \u043a\u043e\u043f\u0438\u044f TableColumn.header.availability=\u041d\u0430\u043b\u0438\u0447\u043d\u043e\u0441\u0442 TableColumn.header.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f MyTorrentsView.header=\u041d\u0435\u043f\u044a\u043b\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.maxuploads=\u041c\u0430\u043a\u0441. \u0431\u0440. \u043a\u0430\u0447\u0432\u0430\u043d\u0438\u044f MyTorrentsView.menu.category.delete=&\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f MyTorrentsView.menu.forceStart=&\u041d\u0430\u0441\u0438\u043b\u0435\u043d\u043e \u0437\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 MyTorrentsView.menu.queue=\u041d\u0430 &\u043e\u043f\u0430\u0448\u043a\u0430 MyTorrentsView.menu.setCategory.add=&\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f\u0085\u2026 MyTorrentsView.menu.setCategory=\u0412\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435 \u0432 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f TableColumn.header.savepath=\u041f\u044a\u0442 \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 TableColumn.header.SeedingRank=\u041f\u043e\u0441\u044f\u0432\u043a\u043e\u0432 \u0440\u0430\u043d\u0433 TableColumn.header.totalspeed.info=\u041e\u0431\u0449\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u0437\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438, \u0441 \u043a\u043e\u0438\u0442\u043e \u0438\u043c\u0430 \u0432\u0440\u044a\u0437\u043a\u0438 TableColumn.header.totalspeed=\u041e\u0431\u0449\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 splash.initializePlugins=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438\u0442\u0435 StartStopRules.SPratioMet=\u0421:\u0420 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e StartStopRules.FP0Peers=\u041d\u0412\u041f/0 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 StartStopRules.0Peers=0 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 StartStopRules.numSeedsMet=\u0411\u0440. \u043f\u043e\u0441\u044f\u0432\u043a\u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e StartStopRules.ratioMet=\u0420:\u0421 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e StartStopRules.shareRatioMet=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e StartStopRules.waiting=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 StartStopRules.firstPriority=\u041d\u0412\u041f ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\u0421\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 \u043d\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435\u0442\u043e (\u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e) DownloadManager.error.unabletostartserver=\u041d\u0435\u0432\u044a\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u0430 - \u0434\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0442\u0430 \u0437\u0430 \u0432\u0445\u043e\u0434\u044f\u0449 \u043f\u043e\u0440\u0442/\u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430 \u0437\u0430\u0449\u0438\u0442\u043d\u0430\u0442\u0430 \u0441\u0442\u0435\u043d\u0430, \u0437\u0430 \u0434\u0430 \u0441\u043b\u0443\u0436\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430\u0442\u0430 \u043a\u0430\u0442\u043e \u0441\u044a\u0440\u0432\u044a\u0440 GeneralView.label.creationdate=\u0421\u044a\u0437\u0434\u0430\u0434\u0435\u043d \u043d\u0430: ConfigView.section.tracker.announcescrapepercentage=\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0437\u0430 \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 \u043a\u0430\u0442\u043e % \u043e\u0442 \u043e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0435\u0442\u043e\n\u043f\u0440. 200 = 2:1. 0 = \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f\u0442 \u0440\u0435\u0448\u0430\u0432\u0430 ManagerItem.stopping=\u0421\u043f\u0438\u0440\u0430\u043d\u0435 ConfigView.section.tracker.announcecacheperiod=\u041e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u043a\u0435\u0448 (\u043c\u0441\u0435\u043a) ConfigView.section.tracker.scrapecacheperiod=\u041e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u043a\u0435\u0448\u0430 [ms] ConfigView.section.tracker.scrapeandcache=\u041e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 \u0438 \u043a\u0435\u0448\u0438\u0440\u0430\u043d\u0435 ConfigView.section.tracker.announcecacheminpeers=\u041e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0435 \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u0442\u0430 \u0437\u0430 \u0437\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u043a\u0435\u0448 \u0437\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 MyTrackerView.scrapes=\u041e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0438\u044f fileDownloadWindow.retry=\u041e\u0442\u043d\u043e\u0432\u043e MyTrackerView.bytesin=\u0412\u0445. \u0431\u0430\u0439\u0442\u043e\u0432\u0435 MyTrackerView.bytesinave=\u0412\u0445. \u0441\u0440. MyTrackerView.bytesout=\u0418\u0437\u0445. \u0431\u0430\u0439\u0442\u043e\u0432\u0435 MyTrackerView.bytesoutave=\u0418\u0437\u0445. \u0441\u0440. ConfigView.section.file.max_open_files=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043e\u0442\u0432\u043e\u0440\u0435\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0437\u0430 \u0447\u0435\u0442\u0435\u043d\u0435/\u0437\u0430\u043f\u0438\u0441\n[0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.file.max_open_files.tooltip=\u041f\u043e\u043b\u0435\u0437\u043d\u043e, \u0430\u043a\u043e \u0441\u0435 \u0441\u0432\u0430\u043b\u044f\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441\u044a\u0441 \u0441\u0442\u043e\u0442\u0438\u0446\u0438/\u0445\u0438\u043b\u044f\u0434\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0432 \u0442\u044f\u0445 \u0438, \u0430\u043a\u043e \u0435 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0430\u0442\u0430 \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u0442\u0430 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0438 \u0434\u0440\u044a\u0436\u043a\u0438 \u043d\u0430 \u041e\u0421-\u0430. ConfigView.section.proxy=\u0412\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u043f\u044a\u043b\u043d\u043e\u043c\u043e\u0449\u043d\u0438\u043a ConfigView.section.proxy.enable_proxy=\u0422\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438\u0442\u0435 \u043a\u043e\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u0430 \u0441\u0430 \u043f\u0440\u0435\u0437 \u043f\u044a\u043b\u043d\u043e\u043c\u043e\u0449\u043d\u0438\u043a (\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442) ConfigView.section.proxy.host=\u041f\u043e\u0434\u0441\u043b\u043e\u043d ConfigView.section.proxy.port=\u041f\u043e\u0440\u0442 ConfigView.section.proxy.username=\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u043e \u0438\u043c\u0435 ConfigView.section.proxy.password=\u041f\u0430\u0440\u043e\u043b\u0430 ConfigView.section.proxy.enable_socks=\u041f\u043e\u043b\u0437\u0432\u0430 \u0441\u0435 SOCKS \u043f\u044a\u043b\u043d\u043e\u043c\u043e\u0449\u043d\u0438\u043a wizard.createtorrent.extrahashes=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u0440\u0430\u0437\u0431\u044a\u0440\u043a\u0432\u0430\u043d\u0438\u044f \u0437\u0430 \u0434\u0440\u0443\u0433\u0438 \u043c\u0440\u0435\u0436\u0438 (\u043f\u0440. Gnutella2, eDonkey2000) GeneralView.label.connected=\u0441\u0432\u044a\u0440\u0437\u0430\u043d(\u0438) GeneralView.label.in_swarm=\u0432 \u0440\u043e\u044f\u043a\u0430 ManagerItem.initializing=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 AlertMessageBox.error=\u0413\u0440\u0435\u0448\u043a\u0430 AlertMessageBox.warning=\u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435 AlertMessageBox.comment=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f AlertMessageBox.information=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f AlertMessageBox.unread=\u0418\u043c\u0430 \u043d\u0435\u043f\u0440\u043e\u0447\u0435\u0442\u0435\u043d\u0438 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0449\u0436\u0435\u043d\u0438\u044f - \u0434\u0430 \u0441\u0435 \u043f\u043e\u0441\u043e\u0447\u0438 \u0442\u0443\u043a \u0437\u0430 \u043f\u0440\u0435\u0433\u043b\u0435\u0434. SharedPortServer.alert.selectorfailed=\u041f\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0432\u0430\u0447 \u0437\u0430 \u0432\u0445\u043e\u0434\u044f\u0449\u0438 \u0434\u0430\u043d\u043d\u0438.\n\u0414\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u0434\u0430\u043b\u0438 \u0437\u0430\u0449\u0438\u0442\u043d\u0430\u0442\u0430 \u0441\u0442\u0435\u043d\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430 \u043d\u0430 java(w).exe \u0434\u0430 \u0431\u044a\u0434\u0435 '\u0441\u044a\u0440\u0432\u044a\u0440' Tracker.alert.listenfail=\u041f\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0441\u043b\u0443\u0448\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0440\u0442 %1.\n\u0414\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u0434\u0430\u043b\u0438 \u0434\u0440\u0443\u0433\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u043d\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0442 \u0442\u043e\u0437\u0438 \u043f\u043e\u0440\u0442.\n\u0414\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u0438 \u0437\u0430 \u043f\u0430\u0440\u0430\u043b\u0435\u043b\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0435\u0449 Vuze. DiskManager.alert.movefileexists=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438\u0442\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u0435\n\u0424\u0430\u0439\u043b %1 \u0432\u0435\u0447\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430 \u0432 \u043a\u0440\u0430\u0439\u043d\u0430\u0442\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f DiskManager.alert.movefilefails=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438\u0442\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u0435\n\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0444\u0430\u0439\u043b %1 \u043d\u0435 \u0443\u0441\u043f\u044f, %2 DiskManager.alert.movefilerecoveryfails=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u0432\u044a\u0437\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u0441\u043b\u0435\u0434 \u043d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435\n\u0412\u044a\u0437\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0444\u0430\u0439\u043b %1 \u043d\u0435 \u0443\u0441\u043f\u044f, %2 ConfigView.section.tracker.logenable=\u0417\u0430\u043f\u0438\u0441 \u043d\u0430 \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u043d\u0430 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0432 \u0434\u043d\u0435\u0432\u043d\u0438\u043a 'tracker.log' SpeedView.stats.title=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 SpeedView.stats.total=\u041e\u0431\u0449\u043e SpeedView.stats.session=\u0422\u0430\u0437\u0438 \u0441\u0435\u0441\u0438\u044f SpeedView.stats.session.tooltip=\u041e\u0431\u0449\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) SpeedView.stats.downloaded=\u0421\u0432\u0430\u043b\u0435\u043d\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) SpeedView.stats.uploaded=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) SpeedView.stats.ratio=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 SpeedView.stats.uptime=\u0412\u0440\u0435\u043c\u0435 \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430 SpeedView.stats.now=\u0412 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 SpeedView.stats.now.tooltip=\u041e\u0431\u0449\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) AutoMigration.useralert=\u0420\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 \u043e\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430\u0442\u0430 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043d\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435/\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438:\n\n%1\n\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u0438\u0442\u0435 \u0438\u0437\u0438\u0441\u043a\u0432\u0430\u0442 \u0440\u044a\u0447\u043d\u0430 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f.\n\u0417\u0430\u0434\u044a\u043b\u0436\u0438\u0442\u0435\u043b\u043d\u043e \u0434\u0430 \u0441\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u0442 \u043f\u044a\u0442\u0438\u0449\u0430\u0442\u0430 \u0437\u0430 \u0437\u0430\u043f\u0438\u0441 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0442\u0430, \u0430\u043a\u043e \u0441\u0430 \u043c\u0438\u0433\u0440\u0438\u0440\u0430\u043d\u0438! # # > 2.0.8.0 # OpenTorrentWindow.title=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442(\u0438) OpenTorrentWindow.message=\u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u043d\u043e OpenTorrentWindow.addFiles=\u0414\u043e\u0431&\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 OpenTorrentWindow.dataLocation=\u041c\u044f\u0441\u0442\u043e \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438: OpenTorrentWindow.startMode=\u0420\u0435\u0436\u0438\u043c \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u044f\u043d\u0435 OpenTorrentWindow.startMode.queued=\u041d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430 OpenTorrentWindow.startMode.stopped=\u0421\u043f\u0440\u044f\u043d OpenTorrentWindow.startMode.forceStarted=\u041d\u0430\u0441\u0438\u043b\u0441\u0442\u0432\u0435\u043d\u043e \u0437\u0430\u043f\u043e\u0447\u043d\u0430\u0442 OpenTorrentWindow.addPosition=\u041c\u044f\u0441\u0442\u043e \u0432 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430 OpenTorrentWindow.addPosition.first=\u041f\u044a\u0440\u0432\u0438 OpenTorrentWindow.addPosition.last=\u041f\u043e\u0441\u043b\u0435\u0434\u0435\u043d TableColumn.header.remaining.info=\u041e\u0441\u0442\u0430\u0432\u0430\u0449\u043e \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 TableColumn.header.remaining=\u041e\u0441\u0442\u0430\u0432\u0430 ConfigView.section.tracker.enablecompact=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0437\u0430 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u043e \u043e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0435 ConfigView.section.tracker.enablekey=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043f\u0440\u0435\u0434\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u043a\u043b\u044e\u0447 \u043a\u044a\u043c \u0442\u0440\u0430\u043a\u0435\u0440\u0430 \u0437\u0430 \u043f\u043e\u0434\u043e\u0431\u0440\u044f\u0432\u0430\u043d\u0435 \u0441\u0438\u0433\u0443\u0440\u043d\u043e\u0441\u0442\u0442\u0430 ConfigView.section.file.perf=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044f\u043d\u0435 ConfigView.section.file.perf.explain=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 - \u043d\u0435\u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u043d\u0438 \u043f\u0440\u043e\u043c\u0435\u043d\u0438 \u043d\u0430 \u0442\u0435\u0437\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u0449\u0435 \u0441\u0435 \u043e\u0442\u0440\u0430\u0437\u0438 \u0431\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043e \u043d\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044f\u043d\u0435\u0442\u043e \u043f\u0440\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0435. \u0418\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442.\n\u0410\u043a\u043e \u0441\u0435 \u043f\u043e\u044f\u0432\u044f\u0442 'out of memory' \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438, \u0441\u0435 \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0438\u0442\u0435 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 (\u0432\u0436. \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043d\u0430 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0430) ConfigView.section.file.max_open_files.explain=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435\u0442\u043e \u043d\u0430 \u043f\u0440\u0435\u043a\u0430\u043b\u0435\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u043f\u0440\u0435\u0434\u0438\u0437\u0432\u0438\u043a\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 \u0441 \u041e\u0421 \u043f\u043e\u0440\u0430\u0434\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0438 \u043a\u0430\u0442\u043e \u0444\u0430\u0439\u043b\u043e\u0432\u0438 \u0434\u0440\u044a\u0436\u043a\u0438. \u0422\u043e\u0432\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0430\u0432\u0430 \u0431\u0440\u043e\u044f \u043d\u0430 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e \u043e\u0442\u0432\u043e\u0440\u0435\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435. popup.error.hide=\u0421\u043a\u0440\u0438\u0432\u0430\u043d\u0435 popup.error.details=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 ConfigView.section.style.colorOverrides=\u041f\u0440\u0435\u0432\u044a\u0437\u043c\u043e\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0446\u0432\u0435\u0442\u043e\u0432\u0435 ConfigView.section.style.colorOverride.progressBar=\u041b\u0435\u043d\u0442\u0430 \u0437\u0430 \u043f\u0440\u043e\u0433\u0440\u0435\u0441 ConfigView.section.style.colorOverride.error=\u0413\u0440\u0435\u0448\u043a\u0430 MainWindow.status.tooOld=\u0435 \u0441\u0442\u0430\u0440\u043e, \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430. ConfigView.section.style.colorOverride.warning=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 ConfigView.section.style.colorOverride.altRow=\u041f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 \u0440\u0435\u0434\u043e\u0432\u0435\u0442\u0435 ConfigView.section.file.save.peers.enable=\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0438\u0442\u0435 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0437\u0430 \u0431\u044a\u0440\u0437\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435 ConfigView.section.file.save.peers.max=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.file.save.peers.pertorrent=\u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.label.max_peers_per_torrent=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0432\u0440\u044a\u0437\u043a\u0438 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.label.max_peers_total=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0432\u0440\u044a\u0437\u043a\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u043d\u043e [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.style.colorOverrides.reset=\u041f\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430 \u0446\u0432\u044f\u0442 ConfigView.section.language.info=\u041f\u0440\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u0449\u0435 \u0441\u0435 \u043f\u0440\u0430\u0432\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0438\u043d\u0430\u0433\u0438, \u043a\u043e\u0433\u0430\u0442\u043e Vuze \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430. ConfigView.section.language.enableUpdate=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u0435\u0437 \u0443\u0435\u0431 ConfigView.section.language.UpdateURL=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 URL ConfigView.section.language.UpdateNow=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0435\u0434\u043d\u0430\u0433\u0430! Button.revert=\u041f\u0440\u0435\u0434\u0438\u0448\u043d\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 MyTorrentsView.menu.changeDirectory=\u0421\u043c\u044f\u043d\u0430 \u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0437\u0430 \u0434\u0430\u043d\u043d\u0438 GenericText.column=\u043a\u043e\u043b\u043e\u043d\u0430 MyTorrentsView.menu.thisColumn.remove=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u0430 MyTorrentsView.menu.thisColumn.toClipboard=\u041a\u043e\u043f\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0442\u0435\u043a\u0441\u0442 \u0432 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434\u0430 MyTorrentsView.menu.thisColumn.autoTooltip=\u0421 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430 \u0432\u0438\u043d\u0430\u0433\u0438 MyTorrentsView.menu.tracker=\u0422\u0440\u0430\u043a\u0435\u0440 ConfigView.download.abbreviated=\u0421\u0432: ConfigView.upload.abbreviated=\u041a\u0447: ConfigView.complete.abbreviated=\u0417\u0432: TableColumn.header.secondsseeding=\u0421\u0435\u0435\u043d\u0435 \u0437\u0430 TableColumn.header.secondsseeding.info=\u0412\u0440\u0435\u043c\u0435 \u043f\u0440\u0435\u0437 \u043a\u043e\u0435\u0442\u043e \u0435 \u0441\u044f\u0442\u043e. TableColumn.header.secondsdownloading=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 \u0437\u0430 TableColumn.header.secondsdownloading.info=\u0412\u0440\u0435\u043c\u0435 \u043f\u0440\u0435\u0437 \u043a\u043e\u0435\u0442\u043e \u0435 \u0441\u0432\u0430\u043b\u044f\u043d\u043e. ConfigView.section.tracker.udpversion=\u0412\u0435\u0440\u0441\u0438\u044f \u043d\u0430 UDP \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b (1 \u0438\u043b\u0438 2) window.updateswt.title=\u0412\u0435\u0440\u0441\u0438\u044f\u0442\u0430 \u043d\u0430 SWT \u0435 \u043c\u043d\u043e\u0433\u043e \u0441\u0442\u0430\u0440\u0430! window.updateswt.text=\u0412\u0435\u0440\u0441\u0438\u044f\u0442\u0430 \u043d\u0430 SWT \u0435 \u043c\u043d\u043e\u0433\u043e \u0441\u0442\u0430\u0440\u0430!\nSWT \u0435 \u0433\u0440\u0430\u0444\u0438\u0447\u043d\u0430\u0442\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043d\u0430 Vuze \u0438 \u043d\u0430\u043b\u0438\u0447\u043d\u0430\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u0435 \u043c\u043d\u043e\u0433\u043e \u0441\u0442\u0430\u0440\u0430, \u0437\u0430 \u0434\u0430 \u0440\u0430\u0431\u043e\u0442\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0430\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430 Vuze. \u0414\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 '\u0414\u0430' \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 SWT. window.updateswt.status=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 window.updateswt.failed=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f\u0442\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438, \u0434\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 '\u0414\u0430' \u0437\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442. window.updateswt.status.downloading.updater=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 \u043d\u0430 \u043c\u043e\u0434\u0443\u043b\u0430 \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f window.updateswt.status.finding=\u041d\u0430\u043c\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0430 SWT \u0432\u0435\u0440\u0441\u0438\u044f window.updateswt.status.downloading=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0430\u0442\u0430 SWT \u0432\u0435\u0440\u0441\u0438\u044f window.updateswt.status.done=\u0420\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 window.updateswt.ok=\u0414\u0430 window.updateswt.cancel=\u041e\u0442\u043a\u0430\u0437 swt.updater.downloader.downloading=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 \u043d\u0430 SWT \u043e\u0442 swt.updater.urlsgetter.downloading=\u041f\u043e\u043b\u0443\u0447\u0430\u0432\u0430\u043d\u0435 \u0441\u043f\u0438\u0441\u044a\u043a \u0441 \u043e\u0433\u043b\u0435\u0434\u0430\u043b\u043d\u0438 \u043e\u0442 swt.updater.urlsgetter.platform=SWT \u0437\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430: window.updateswt.ignore=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 ConfigView.section.style.useFancyTabs=\u041f\u044a\u0441\u0442\u0440\u0438 \u0441\u0435\u043a\u0446\u0438\u0438 splash.initializeGM=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u0433\u043b\u043e\u0431\u0430\u043b\u043d\u043e\u0442\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 splash.loadingTorrents=\u0417\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 MyTorrentsView.menu.thisColumn.sort=&\u041f\u043e\u0434\u0440\u0435\u0436\u0434\u0430\u043d\u0435 Scrape.status.ok=\u041e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e Scrape.status.error=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435: Scrape.status.error.badURL=URL \u043d\u0430 \u043e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0435 \u0441\u043b\u0435\u0434\u0432\u0430 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438\u0442\u0435 \u043d\u0430 \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435\u0442\u043e. Scrape.status.error.nohash=\u041b\u0438\u043f\u0441\u0432\u0430 \u0440\u0430\u0437\u0431\u044a\u0440\u043a\u0432\u0430\u043d\u0435 \u0432 \u043e\u0442\u0433\u043e\u0432\u043e\u0440\u0430. Scrape.status.error.invalid=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u043e\u0442\u0433\u043e\u0432\u043e\u0440. Scrape.status.nextScrapeAt=\u0421\u043b\u0435\u0434\u0432\u0430\u0449\u043e \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 \u0432 %1 Scrape.status.scraping=\u041e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435\u0085\u2026 Scrape.status.initializing=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u0437\u0430 \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 Scrape.status.scraping.queued=\u041e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430\u2026 ConfigView.label.minSpeedForActiveSeeding=\u0414\u0430 \u043d\u0435 \u0441\u0435 \u0441\u0447\u0438\u0442\u0430, \u0447\u0435 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0433\u043d\u0435\u0437\u0434\u043e, \u0430\u043a\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u0435 \u043f\u043e\u0434 ConfigView.section.stats.exportpeers=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u043d\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438\u0442\u0435 \u0437\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d MainWindow.menu.view.irc.moved=IRC \u0435 \u043d\u0430 \u0440\u0430\u0437\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u0430\u0442\u043e \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430, \u0432\u0436. http://azureus.sourceforge.net/plugin_list.php. \u0421\u043b\u0435\u0434 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u043c\u0435\u043d\u044e '\u0418\u0437\u0433\u043b\u0435\u0434 \u2192 \u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u2192 IRC\u2026' \u0437\u0430 \u0434\u043e\u0441\u0442\u044a\u043f. MyTrackerView.webui.contextmenu.copyurl=\u041a\u043e\u043f\u0438\u0440\u0430\u043d\u0435 URL \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0432 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434\u0430 ConfigView.section.file.torrent.ignorefiles=\u0424\u0430\u0439\u043b\u043e\u0432\u0435 \u0437\u0430 \u043f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043f\u0440\u0438 \u0441\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\n\u043f\u0440. .DS_Store;Thumbs.db;Desktop.ini Torrent.create.progress.ignoringfile=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b ConfigView.section.style.useUnitsRateBits=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0431\u0438\u0442\u043e\u0432\u0435 \u0432\u043c\u0435\u0441\u0442\u043e \u0431\u0430\u0439\u0442\u043e\u0432\u0435 \u0437\u0430 \u0431\u0430\u0439\u0442\u043e\u0432\u043e-\u0431\u0430\u0437\u0438\u0440\u0430\u043d\u0438 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0438 (KiB/s \u2192 Kibit/s \u0438 \u0434\u0440.) ConfigView.section.interface.resetassoc=\u041f\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0438\u0442\u0435 \u0430\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u0438 \u043d\u0430 Explorer (.torrent) ConfigView.section.interface.resetassocbutton=\u041f\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 ConfigView.section.interface.checkassoc=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0430\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u0438\u0442\u0435 \u043f\u0440\u0438 \u043f\u0443\u0441\u043a\u0430\u043d\u0435 \u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 dialog.associations.title=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0430\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u0438 Button.yes=&\u0414\u0430 Button.no=&\u041d\u0435 ConfigView.label.seeding.autoStart0Peers=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441 0 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.label.seeding.autoStart0Peers.tooltip=\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e, \u0442\u0440\u0430\u043a\u0435\u0440\u044a\u0442 \u0432\u0438\u043d\u0430\u0433\u0438 \u043f\u043e\u043a\u0430\u0437\u0432\u0430 \u043f\u043e\u0441\u044f\u0432\u043a\u0438 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441 0 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438. dialog.associations.prompt=Vuze \u043d\u0435 \u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430\u0442\u0430 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u0437\u0430 BitTorrent \u0444\u0430\u0439\u043b\u043e\u0432\u0435.\n\u0414\u0430 \u0441\u0435 \u0430\u0441\u043e\u0446\u0438\u0438\u0440\u0430\u0442 \u043b\u0438 .torrent \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435 \u0441 Vuze? dialog.associations.askagain=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 ConfigView.section.plugins.update=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 Plugin.pluginupdate.enablecheck=\u0421 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430\u0442\u0430 plugins.basicview.status=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435: plugins.basicview.activity=\u0414\u0435\u0439\u043d\u043e\u0441\u0442: plugins.basicview.progress=\u0420\u0430\u0437\u0432\u0438\u0442\u0438\u0435: plugins.basicview.log=\u0414\u043d\u0435\u0432\u043d\u0438\u043a: ConfigView.label.maxdownloadspeed=KB/s \u0433\u043b\u043e\u0431\u0430\u043b\u043d\u0430 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] splash.loadingTorrent=\u0417\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 splash.of=\u043e\u0442 ConfigView.section.plugins.irc=\u041c\u0440\u0435\u0436\u0430 IRC UpdateWindow.title=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043d\u0430 Vuze UpdateWindow.header=\u0421\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0438 \u0438\u0437\u0438\u0441\u043a\u0432\u0430\u0442 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f: UpdateWindow.columns.install=\u0418\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 UpdateWindow.columns.name=\u0418\u043c\u0435 UpdateWindow.columns.version=\u0412\u0435\u0440\u0441\u0438\u044f UpdateWindow.columns.size=\u0420\u0430\u0437\u043c\u0435\u0440 UpdateWindow.cancel=\u041e\u0442\u043a\u0430\u0437 UpdateWindow.quit=\u0418\u0437\u0445\u043e\u0434 UpdateWindow.close=\u0417\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 UpdateWindow.ok=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f UpdateWindow.restart=\u0420\u0435\u0441\u0442\u0430\u0440\u0442 \u043d\u0430 Vuze UpdateWindow.status.downloading=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 UpdateWindow.status.done=\u0413\u043e\u0442\u043e\u0432\u043e UpdateWindow.status.failed=\u041f\u0440\u043e\u0432\u0430\u043b UpdateWindow.status.restartNeeded=\u0429\u0435 \u0431\u044a\u0434\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0440\u0435\u0441\u0442\u0430\u0440\u0442! ConfigView.pluginlist.broken=\u0421\u0447\u0443\u043f\u0435\u043d ConfigView.pluginlist.whereToPut=\u0421\u043b\u0430\u0433\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u0438 \u0437\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b \u0432 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u043f\u043e\u0434: ConfigView.pluginlist.whereToPutOr=\u0417\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u0435\u043d\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430: MainWindow.statusText.checking=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 TableColumn.header.OnlyCDing4=\u0421\u0430\u043c\u043e \u0441\u0435\u0435\u043d\u0435 \u0437\u0430 TableColumn.header.OnlyCDing4.info=\u0412\u0440\u0435\u043c\u0435\u0442\u043e \u043f\u0440\u0435\u0437 \u043a\u043e\u0435\u0442\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u044a\u0442 \u0441\u0430\u043c\u043e \u0435 \u0441\u044f\u0442. \u041d\u0435 \u0432\u043a\u043b\u044e\u0447\u0432\u0430 \u0432\u0440\u0435\u043c\u0435\u0442\u043e \u043f\u0440\u0435\u0437 \u043a\u043e\u0435\u0442\u043e \u0435 \u0441\u0432\u0430\u043b\u044f\u043d \u0438 \u0441\u044f\u0442. ConfigView.section.style.alternateTablePainting=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434\u0440\u0443\u0433 \u043c\u0435\u0442\u043e\u0434 \u0437\u0430 \u0438\u0437\u0440\u0438\u0441\u0443\u0432\u0430\u043d\u0435 \u043a\u043e\u043b\u043e\u043d\u0438\u0442\u0435 \u043d\u0430 \u0433\u0440\u0430\u0444\u0438\u0447\u043d\u0430\u0442\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0430 (\u043c\u043e\u0436\u0435 \u0434\u0430 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442) UpdateWindow.status.restartMaybeNeeded=\u041c\u043e\u0436\u0435 \u0434\u0430 \u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0440\u0435\u0441\u0442\u0430\u0440\u0442 ConfigView.pluginlist.shared=\u0441\u043f\u043e\u0434\u0435\u043b\u0435\u043d PeersView.host=\u0418\u043c\u0435 \u043d\u0430 \u043f\u043e\u0434\u0441\u043b\u043e\u043d PeersView.host.info=\u0418\u043c\u0435 \u043d\u0430 \u043f\u043e\u0434\u0441\u043b\u043e\u043d\u0430 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f, \u0430\u043a\u043e \u0438\u043c\u0430 (\u0432\u043b\u0438\u044f\u0435 \u043d\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044f\u043d\u0435\u0442\u043e) MainWindow.menu.help.whatsnew=\u041a\u0430\u043a\u0432\u043e \u043d\u043e\u0432\u043e ConfigView.label.checkonstart=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 Vuze ConfigView.label.periodiccheck=\u041f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044f ConfigView.label.opendialog=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435, \u043a\u043e\u0433\u0430\u0442\u043e \u0438\u043c\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f MainWindow.updateavail=\u0414\u0430 \u0441\u0435 \u043f\u043e\u0441\u043e\u0447\u0438 \u0442\u0443\u043a \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 MainWindow.status.unofficialversion=Vuze \u0431\u0435\u0442\u0430 MainWindow.status.latestversionunchecked=\u0411\u0435\u0437 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044f GeneralView.label.updatein.stopped=\u0421\u043f\u0440\u044f\u043d\u043e StartStopRules.menu.viewDebug=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 \u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 ConfigView.section.style.doNotUseGB=\u0411\u0435\u0437 \u0435\u0434\u0438\u043d\u0438\u0446\u0438 \u0432 GB ConfigView.section.style.doNotUseGB.tooltip=\u041f\u0440\u0438 \u043e\u0442\u043c\u0435\u0442\u043a\u0430 Vuze \u0434\u0430 \u043f\u043e\u043b\u0437\u0432\u0430 MB \u0435\u0434\u0438\u043d\u0438\u0446\u0438, \u0434\u043e\u0440\u0438 \u043a\u043e\u0433\u0430\u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0438\u0442\u0435 \u0441\u0430 >1024 MB MainWindow.menu.help.plugins=\u041f\u043e\u043b\u0443\u0447\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 ConfigView.section.plugins.TrackerWeb=\u0422\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0430 \u043c\u0440\u0435\u0436\u0430 ConfigView.section.tracker.enablecategories=\u041e\u0442\u0434\u0435\u043b\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043f\u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f health.explain.share=\u043e\u0437\u043d\u0430\u0447\u0430\u0432\u0430, \u0447\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u044a\u0442 \u0435 \u0438\u043b\u0438 \u043f\u043e\u0434\u0441\u043b\u043e\u043d\u0435\u043d, \u0438\u043b\u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d ConfigView.section.tracker.createcert=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0430\u043c\u043e\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 ConfigView.section.tracker.createbutton=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 security.certcreate.title=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0430\u043c\u043e\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 security.certcreate.intro=\u0412 \u0442\u043e\u0437\u0438 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432 \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0441\u044a\u0437\u0434\u0430\u0434\u0435 \u0441\u0430\u043c\u043e\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 security.certcreate.alias=\u041f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c security.certcreate.strength=\u0421\u043b\u043e\u0436\u043d\u043e\u0441\u0442 security.certcreate.firstlastname=\u0418\u043c\u0435 \u0438 \u0444\u0430\u043c\u0438\u043b\u0438\u044f security.certcreate.orgunit=\u041e\u0442\u0434\u0435\u043b security.certcreate.org=\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f security.certcreate.city=\u0413\u0440\u0430\u0434 \u0438\u043b\u0438 \u043c\u0435\u0441\u0442\u043d\u043e\u0441\u0442 security.certcreate.state=\u0421\u0442\u0440\u0430\u043d\u0430 \u0438\u043b\u0438 \u043f\u0440\u043e\u0432\u0438\u043d\u0446\u0438\u044f security.certcreate.country=\u0414\u0432\u0443\u0431\u0443\u043a\u0432\u0435\u043d \u043a\u043e\u0434 \u043d\u0430 \u0434\u044a\u0440\u0436\u0430\u0432\u0430 security.certcreate.ok=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 security.certcreate.cancel=\u041e\u0442\u043a\u0430\u0437 security.certcreate.createok=\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044a\u0442 \u0435 \u0441\u044a\u0437\u0434\u0430\u0434\u0435\u043d \u0443\u0441\u043f\u0435\u0448\u043d\u043e security.certcreate.createfail=\u041f\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0435 \u0441\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 ConfigView.section.plugins.webui=\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430 Swing Web ConfigView.section.plugins.xml_http_if=\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430 XML/HTTP webui.passwordenable=\u0421 \u043f\u0430\u0440\u043e\u043b\u0430 webui.user=\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u043e \u0438\u043c\u0435 webui.password=\u041f\u0430\u0440\u043e\u043b\u0430 webui.port=\u041f\u043e\u0440\u0442 (*) webui.protocol=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b (*) webui.homepage=\u041d\u0430\u0447\u0430\u043b\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 (*) webui.rootdir=\u0413\u043b\u0430\u0432\u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f (*) webui.rootres=\u0413\u043b\u0430\u0432\u0435\u043d \u0440\u0435\u0441\u0443\u0440\u0441 (*) webui.mode=\u0420\u0435\u0436\u0438\u043c (*) webui.mode.info=\u0420\u0435\u0436\u0438\u043c\u044a\u0442 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0435\n\t"full"\t= \u0414\u043e\u0441\u0442\u044a\u043f\u043d\u0438 \u0441\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 (\u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435)\n\t"view"\t= \u0441\u0430\u043c\u043e \u0437\u0430 \u0433\u043b\u0435\u0434\u0430\u043d\u0435 (\u043d\u043e \u0441 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 \u0447\u0435\u0441\u0442\u043e\u0442\u0430\u0442\u0430 \u043d\u0430 \u043e\u043f\u0440\u0435\u0441\u043d\u044f\u0432\u0430\u043d\u0435) webui.access=\u0414\u043e\u0441\u0442\u044a\u043f (*) webui.access.info=\u0414\u043e\u0441\u0442\u044a\u043f\u044a\u0442 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0435\n\t"local"\t= \u0441\u0430\u043c\u043e \u043c\u0435\u0441\u0442\u043d\u0430\u0442\u0430 \u043c\u0430\u0448\u0438\u043d\u0430 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0441\u0432\u044a\u0440\u0437\u0432\u0430\n\t"all"\t= \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d \u0434\u043e\u0441\u0442\u044a\u043f (\u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435)\n\tIP\t= \u043f\u0440. 192.168.0.2\t\t\t\u0441\u0430\u043c\u043e \u0435\u0434\u043d\u043e IP\n\tIP1-IP2\t= \u043f\u0440. 192.168.0.1-192.168.0.255\t\u0432\u043a\u043b\u044e\u0447\u0432\u0430\u0449 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u043e\u0442 IP-\u0442\u0430 GeneralView.label.maxdownloadspeed=\u041c\u0430\u043a\u0441. \u0421\u0432. Security.keystore.corrupt=\u041f\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0435 \u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u0442\u043e \u0437\u0430 \u043a\u043b\u044e\u0447\u043e\u0432\u0435 '%1', \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0438\u0437\u0442\u0440\u0438\u0435 \u0438 \u0434\u0430 \u0441\u0435 \u0441\u044a\u0437\u0434\u0430\u0434\u0430\u0442 \u043e\u0442\u043d\u043e\u0432\u043e/\u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0430\u0442 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0438\u0442\u0435 Security.keystore.empty=\u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u0442\u043e \u0437\u0430 \u043a\u043b\u044e\u0447\u043e\u0432\u0435 \u0435 \u043f\u0440\u0430\u0437\u043d\u043e. \u0422\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0441\u044a\u0437\u0434\u0430\u0434\u0435 \u0441\u0430\u043c\u043e\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 (\u0434\u0430 \u0441\u0435 \u0432\u0438\u0434\u0438 '\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 \u2192 \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u2192 \u0421\u0438\u0433\u0443\u0440\u043d\u043e\u0441\u0442'), \u0438\u043b\u0438 \u0434\u0430 \u0441\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0430 \u043d\u0430\u043b\u0438\u0447\u0435\u043d \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u0432 '%1' webui.restart.info=\u041f\u0440\u043e\u043c\u044f\u043d\u0430\u0442\u0430 \u043d\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u043e\u0442\u0431\u0435\u043b\u044f\u0437\u0430\u043d\u0438 \u0441 (*) \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u0437\u0430 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 GeneralView.label.maxdownloadspeed.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.UPnP=UPnP \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 upnp.enable=\u0421 UPnP upnp.info=\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u043d\u043e \u041f\u0440\u0438\u0441\u044a\u0435\u0434\u0438\u043d\u044f\u0432\u0430\u043d\u0435 \u0438 \u041f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 - (Universal Plug and Play - UPnP) \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 \u043d\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0438 \u0441 UPnP \u043f\u043e\u0434\u0434\u0440\u044a\u0436\u043a\u0430. upnp.mapping.dataport=\u041f\u043e\u0440\u0442 \u0437\u0430 \u0432\u0445\u043e\u0434\u044f\u0449\u0438 \u0434\u0430\u043d\u043d\u0438 \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d upnp.mapping.tcptrackerport=TCP \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 \u043f\u043e\u0440\u0442 upnp.mapping.udptrackerport=UDP \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 \u043f\u043e\u0440\u0442 upnp.alert.differenthost=UPnP: \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 '%1' \u0435 \u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0430\u043d\u043e \u043e\u0442 '%2' - \u0434\u0430 \u0441\u0435 \u0438\u0437\u0431\u0435\u0440\u0435 \u0434\u0440\u0443\u0433 \u043f\u043e\u0440\u0442 upnp.alert.mappingok=UPnP: \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 '%1' \u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0435\u043d\u043e upnp.alert.mappingfailed=UPnP: \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 '%1' \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438 upnp.alertsuccess=\u0414\u043e\u043a\u043b\u0430\u0434\u0432\u0430\u043d\u0435 \u043d\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u0438 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f upnp.alert.lostdevice=UPnP: \u0437\u0430\u0433\u0443\u0431\u0435\u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 \u0441 \u0443\u0441\u043b\u0443\u0433\u0430\u0442\u0430 '%1' \u043d\u0430 UPnP \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e '%2' upnp.grabports=\u041d\u0430\u0437\u043d\u0430\u0447\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 \u0434\u043e\u0440\u0438, \u043a\u043e\u0433\u0430\u0442\u043e \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0442 \u043d\u0430 \u0434\u0440\u0443\u0433 \u043a\u043e\u043c\u043f\u044e\u0442\u044a\u0440 upnp.refresh.label=\u041e\u0431\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0442\u0430 upnp.refresh.button=\u041e\u0431\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 upnp.alert.mappinggrabbed=UPnP: \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 '%1' \u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0435\u043d\u043e - \u0438\u0437\u0437\u0435\u0442\u043e \u043e\u0442 '%2' upnp.mapping.tcpssltrackerport=TCP SSL \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 \u043f\u043e\u0440\u0442 upnp.alertothermappings=\u0414\u043e\u043a\u043b\u0430\u0434\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0440\u0442\u043e\u0432\u0435, \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0449\u0438 \u043d\u0430 \u0434\u0440\u0443\u0433\u0438 \u043a\u043e\u043c\u043f\u044e\u0442\u0440\u0438 upnp.alertdeviceproblems=\u0414\u043e\u043a\u043b\u0430\u0434\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 \u0441 UPnP \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u0442\u043e upnp.trace_to_log=\u041f\u043e\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043f\u044a\u043b\u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 \u0432 \u0434\u043d\u0435\u0432\u043d\u0438\u043a\u0430 upnp.wiki_link=\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0432 Vuze Wiki \u0437\u0430 UPnP upnp.refresh_mappings_on_bad_nat=\u0410\u0432\u0442\u043e-\u043e\u043f\u0440\u0435\u0441\u043d\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0442\u0430 \u043f\u0440\u0438 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 NAT "\u0437\u0430\u0434 \u0437\u0430\u0449\u0438\u0442\u043d\u0430 \u0441\u0442\u0435\u043d\u0430" ConfigView.pluginlist.coreplugins=\u0421\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u0432\u0433\u0440\u0430\u0434\u0435\u043d\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0441\u0430 \u0437\u0430\u0440\u0435\u0434\u0435\u043d\u0438: Peers.column.DLedFromOthers=\u041e\u0442 \u0434\u0440\u0443\u0433\u0438 Peers.column.DLedFromOthers.info=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0430\u043d\u043d\u0438, \u0441\u0432\u0430\u043b\u0435\u043d\u0430 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438, \u0434\u043e\u043a\u0430\u0442\u043e \u0441\u0430 \u0438\u043c\u0430\u043b\u0438 \u043c\u0435\u0441\u0442\u043d\u0438 \u0432\u0440\u044a\u0437\u043a\u0438 Peers.column.UpDownRatio=\u041a\u0430\u0447\u0432\u0430\u043d\u0435:\u0441\u0432\u0430\u043b\u044f\u043d\u0435 Peers.column.UpDownRatio.info=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 "\u041a\u0430\u0447\u0435\u043d\u043e:\u0441\u0432\u0430\u043b\u0435\u043d\u043e" \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d Peers.column.UpRatio=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 Peers.column.UpRatio.info=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 "\u041a\u0430\u0447\u0435\u043d\u043e \u043c\u0435\u0441\u0442\u043d\u043e:\u043a\u0430\u0447\u0435\u043d\u043e \u043e\u0442 \u0434\u0440\u0443\u0433" \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d upnp.releasemappings=\u041e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0442\u0430 \u043f\u0440\u0438 \u0437\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 webui.upnpenable=\u0421 UPnP \u0437\u0430 \u0442\u043e\u0437\u0438 \u043f\u043e\u0440\u0442 (*) ConfigView.section.file.friendly.hashchecking=\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0441\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0440\u0430\u0437\u0431\u044a\u0440\u043a\u0432\u0430\u043d\u0435 ConfigView.section.file.friendly.hashchecking.tooltip=\u041c\u0430\u043b\u043a\u043e \u043f\u043e-\u0431\u0430\u0432\u0435\u043d, \u043d\u043e \u0434\u043e\u0441\u0442\u0430 \u043f\u043e-\u043d\u0435\u043d\u0430\u0442\u043e\u0432\u0430\u0440\u0432\u0430\u0449 \u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u0430/\u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0442\u0430 \u0440\u0435\u0436\u0438\u043c \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0440\u0430\u0437\u0431\u044a\u0440\u043a\u0432\u0430\u043d\u0435\u0442\u043e \u0437\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u0430\u0442\u0430 ConfigView.section.tracker.seedretention=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043f\u043e\u0441\u044f\u0432\u043a\u0438 \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430\u043d\u0438 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.tracker.seedretention.info=\u0417\u0430\u0431\u0435\u043b\u0435\u0436\u043a\u0430: \u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438\u0442\u0435 \u0437\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u0449\u0435 \u0441\u0435 \u0437\u0430\u0433\u0443\u0431\u044f\u0442 \u0437\u0430 \u043d\u0435\u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0442\u0435 \u043f\u043e\u0441\u044f\u0432\u043a\u0438 ConfigView.section.tracker.port=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u0442\u0440\u0430\u043a\u0435\u0440 \u043d\u0430 HTTP \u043f\u043e\u0440\u0442 ConfigView.section.tracker.sslport=\u0422\u0440\u0430\u043a\u0435\u0440\u044a\u0442 \u0434\u0430 \u0435 \u043f\u0440\u0435\u0437 HTTPS \u043f\u043e\u0440\u0442 ConfigView.section.tracker.publicenable.info=\u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430 \u043d\u0430 \u0434\u0440\u0443\u0433\u0438 \u0434\u0430 \u0441\u044a\u0437\u0434\u0430\u0432\u0430\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0449\u0438 \u043c\u0435\u0441\u0442\u043d\u0438\u044f \u0442\u0440\u0430\u043a\u0435\u0440\n\u0431\u0435\u0437 \u0434\u0430 \u0441\u0435 \u0441\u044a\u0445\u0440\u0430\u043d\u044f\u0432\u0430\u0442/\u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u0442 \u043c\u0435\u0441\u0442\u043d\u043e Button.clear=\u0418\u0437\u0447\u0438\u0441\u0442\u0432\u0430\u043d\u0435 MainWindow.IPs.tooltip={\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 \u0441\u043f\u0438\u0441\u044a\u043a\u0430 \u0441 \u0444\u0438\u043b\u0442\u0440\u0438} \u043e\u0431\u0449\u043e IPFilters \u0432 \u0441\u043f\u0438\u0441\u044a\u043a\u0430 - \u0431\u0440. \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0438/\u0437\u0430\u0431\u0440\u0430\u043d\u0435\u043d\u0438/\u043b\u043e\u0448\u0438 IP-\u0442\u0430 \u0432 \u0442\u0435\u043a\u0443\u0449\u0430\u0442\u0430 \u0441\u0435\u0441\u0438\u044f.\n\u0414\u0430 \u0441\u0435 \u0438\u0437\u0431\u0435\u0440\u0435 \u0437\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438. ConfigView.section.ipfilter.list.banned=\u0435 \u0437\u0430\u0431\u0440\u0430\u043d\u0435\u043d ConfigView.section.ipfilter.list.baddata=\u0438\u0437\u043f\u0440\u0430\u0449\u0430 \u043b\u043e\u0448\u0438 \u0434\u0430\u043d\u043d\u0438: \u0441\u043b\u0443\u0447\u0430\u0438 = Button.reset=\u041f\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 ConfigView.section.ipfilter.bannedinfo=IP-\u0442\u0430 \u0438\u0437\u043f\u0440\u0430\u0442\u0438\u043b\u0438 \u043b\u043e\u0448\u0438 \u0434\u0430\u043d\u043d\u0438 - \u0437\u0430\u0431\u0440\u0430\u043d\u0430, \u0430\u043a\u043e \u0433\u0440\u0430\u043d\u0438\u0446\u0438\u0442\u0435 \u0441\u0435 \u043d\u0430\u0434\u0445\u0432\u044a\u0440\u043b\u044f\u0442 ConfigView.section.ipfilter.blockedinfo=IP-\u0442\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0438 \u0437\u0430\u0440\u0430\u0434\u0438 IP \u0444\u0438\u043b\u0442\u0440\u0438 download.removerules.name=\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0437\u0430 \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 download.removerules.unauthorised.info=\u041d\u0435\u043e\u0442\u043e\u0440\u0438\u0437\u0438\u0440\u0430\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441\u0430 \u0442\u0435\u0437\u0438, \u0432 \u043a\u043e\u0438\u0442\u043e \u043e\u0442\u0433\u043e\u0432\u043e\u0440\u044a\u0442 \u043d\u0430 \u043e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0435\u0442\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430 \u0438\u043b\u0438 "not authoris(z)ed", \u0438\u043b\u0438 "unauthoris(z)ed" \u0432\u044a\u0432 "failure response" download.removerules.unauthorised=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u0435\u043e\u0442\u043e\u0440\u0438\u0437\u0438\u0440\u0430\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 download.removerules.unauthorised.seedingonly=\t\u0421\u0430\u043c\u043e \u043f\u0440\u0438 \u0441\u0435\u0435\u043d\u0435 download.removerules.removed.ok=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0442\u043e \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 '%1' \u0443\u0441\u043f\u044f. \u041f\u0440\u0438\u0447\u0438\u043d\u0430\u0442\u0430 \u0435 \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u0442\u0430 \u0437\u0430 \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442. download.removerules.updatetorrents=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u0442\u0435 \u0441 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 Vuze \u043f\u043e \u0438\u0437\u0438\u0441\u043a\u0432\u0430\u043d\u0435 \u043d\u0430 \u0440\u043e\u044f\u043a\u0430 ConfigView.label.defaultstarttorrentsstopped=\u041f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u0434\u0430 \u0441\u0435 \u0434\u043e\u0431\u0430\u0432\u044f\u0442 \u043d\u043e\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432 \u0441\u043f\u0440\u044f\u043d\u043e \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 ConfigView.section.server.enableudp=\u0422\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043f\u0440\u0435\u0437 UDP. \u0422\u043e\u0432\u0430 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0441\u044a\u0449\u0438\u044f \u043d\u043e\u043c\u0435\u0440 \u043d\u0430 \u043f\u043e\u0440\u0442 \u043a\u0430\u0442\u043e TCP \u0441\u044a\u0440\u0432\u044a\u0440\u0430 upnp.mapping.dataportudp=\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438 UDP \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 \u043f\u043e\u0440\u0442 ConfigView.section.file.decoder.showlax=\u041f\u043e-\u043c\u0430\u043b\u043a\u043e \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u0438 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438 ConfigView.section.file.decoder.showall=\u0412\u0437\u0435\u043c\u0430\u043d\u0435 \u043f\u0440\u0435\u0434\u0432\u0438\u0434 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u0432\u044a\u0437\u043c\u043e\u0436\u043d\u0438 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438 MainWindow.status.updowndetails.tooltip=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435/\u043a\u0430\u0447\u0432\u0430\u043d\u0435\n\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0437\u0430 \u043f\u0440\u043e\u043c\u044f\u043d\u0430, \u0438\u0437\u0431\u043e\u0440 \u0437\u0430 \u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 TrackerClient.announce.warningmessage=\u0422\u0440\u0430\u043a\u0435\u0440\u044a\u0442 \u0437\u0430 '%1' \u0432\u044a\u0440\u043d\u0430 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 '%2' ConfigView.section.tracker.natcheckenable=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0442\u0430 \u0437\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 \u043d\u0430 '\u0432\u0445\u043e\u0434\u044f\u0449 \u043f\u043e\u0440\u0442 \u0437\u0430 \u0434\u0430\u043d\u043d\u0438' \u0438 \u0441\u044a\u043e\u0431\u0449\u0430\u0432\u0430\u043d\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438\u0442\u0435 \u043a\u044a\u043c \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u0442\u0435 ConfigView.section.tracker.publishenabledetails=\u041f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.section.tracker.publishenablepeerdetails=\u041f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d MyTrackerView.badnat=\u041b\u043e\u0448 NAT MyTrackerView.badnat.info=\u041f\u043e\u0441\u044f\u0432\u043a\u0438/\u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438, \u0437\u0430 \u043a\u043e\u0438\u0442\u043e \u0441\u0435 \u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438\u043b\u0430 NAT \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0430\u043a\u043e \u0438\u043c\u0430 ConfigView.section.tracker.natchecktimeout=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 [s] ConfigView.section.file.perf.cache.enable=\u041f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434\u0438\u0441\u043a\u043e\u0432 \u043a\u0435\u0448 ConfigView.section.file.perf.cache.size=\u0420\u0430\u0437\u043c\u0435\u0440 \u043d\u0430 \u043a\u0435\u0448\u0430 \u0432 %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u0422&\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 MainWindow.menu.transfers.startalltransfers=&\u0417\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 MainWindow.menu.transfers.stopalltransfers=&\u0421\u043f\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 MainWindow.menu.transfers.pausetransfers=&\u041f\u0430\u0443\u0437\u0430 MainWindow.menu.transfers.resumetransfers=\u041f\u043e\u0434&\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 ConfigView.label.experimental.osx.kernel.panic.fix=\u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u043d\u0430 \u043f\u043e\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0440\u0438 \u043f\u0430\u043d\u0438\u043a\u0430 \u043d\u0430 \u044f\u0434\u0440\u043e\u0442\u043e \u0432 \u0434\u0432\u0443\u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u043d\u0438 OSX \u0441\u0438\u0441\u0442\u0435\u043c\u0438 [\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442] SystemTray.menu.pausetransfers=\u041f\u0430\u0443\u0437\u0430 \u043d\u0430 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 SystemTray.menu.resumetransfers=\u041f\u043e\u0434\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 ConfigView.section.file.truncate.too.large=\u041f\u0440\u0435\u043a\u044a\u0441\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435, \u043a\u043e\u0438\u0442\u043e \u0437\u0430 \u043f\u0440\u0435\u043a\u0430\u043b\u0435\u043d\u043e \u0433\u043e\u043b\u0435\u043c\u0438 ConfigView.section.file.perf.cache.trace=\u041f\u0440\u043e\u0441\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u043a\u0435\u0448\u0438\u0440\u0430\u0449\u0438\u0442\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0437\u0430 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 ConfigView.section.interface.enabletray=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 (\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442) PeerManager.status.error=\u0413\u0440\u0435\u0448\u043a\u0430 Stats.title.full=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 TransferStatsView.title.full=\u0422\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 CacheView.title.full=\u0411\u0443\u0444\u0435\u0440 CacheView.general.size=\u041f\u044a\u043b\u0435\u043d \u0440\u0430\u0437\u043c\u0435\u0440 CacheView.general.inUse=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0441\u0435 CacheView.general.title=\u041a\u0435\u0448 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f CacheView.reads.title=\u0412/\u0418 \u043f\u0440\u043e\u0447\u0438\u0442\u0438 CacheView.reads.fromFile=\u041e\u0442 \u0444\u0430\u0439\u043b CacheView.reads.fromCache=\u041e\u0442 \u043a\u0435\u0448 CacheView.reads.hits=\u041f\u043e\u043f\u0430\u0434\u0435\u043d\u0438\u044f CacheView.writes.title=\u0412/\u0418 \u0437\u0430\u043f\u0438\u0441\u0438 CacheView.writes.toCache=\u0412 \u0431\u0443\u0444\u0435\u0440 CacheView.writes.toFile=\u0412\u044a\u0432 \u0444\u0430\u0439\u043b CacheView.writes.hits=\u0417\u0430\u043f\u0438\u0441\u0430\u043d\u043e CacheView.speeds.title=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u0437\u0430 \u0434\u0430\u043d\u043d\u0438\u0442\u0435 CacheView.speeds.reads=\u041f\u0440\u043e\u0447\u0438\u0442\u0438 CacheView.speeds.writes=\u0417\u0430\u043f\u0438\u0441\u0438 CacheView.speeds.fromCache=\u041e\u0442/\u0432 \u0431\u0443\u0444\u0435\u0440 CacheView.speeds.fromFile=\u041e\u0442/\u0432\u044a\u0432 \u0444\u0430\u0439\u043b CacheView.reads.#=\u0431\u0440. CacheView.reads.amount=\u0414\u044f\u043b CacheView.reads.avgsize=\u0421\u0440\u0435\u0434\u0435\u043d \u0440\u0430\u0437\u043c\u0435\u0440 openUrl.referrer=URL \u043d\u0430 \u0440\u0435\u0444\u0435\u0440\u0435\u043d\u0442\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430: openUrl.referrer.info=\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0435 \u0441\u0430\u043c\u043e \u0437\u0430 \u0443\u0435\u0431-\u043c\u0435\u0441\u0442\u0430, \u043a\u043e\u0438\u0442\u043e \u0433\u043e \u0438\u0437\u0438\u0441\u043a\u0432\u0430\u0442 ConfigView.label.maxuploadspeedseeding=\u041f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435\u0442\u043e \u043a\u043e\u0433\u0430\u0442\u043e \u0441\u0430\u043c\u043e \u0441\u0435 \u0441\u0435\u0435 ConfigView.label.transfer.ignorepeerports=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0441\u044a\u0441 \u0441\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 \u0437\u0430 \u0434\u0430\u043d\u043d\u0438 (\u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b ';', \u043f\u0440. 0;25) ConfigView.section.proxy.enable_socks.peer=\u041a\u043e\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0438\u0442\u0435 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 (\u0441\u0430\u043c\u043e \u0438\u0437\u0445\u043e\u0434\u044f\u0449\u0438\u0442\u0435 \u0432\u0440\u044a\u0437\u043a\u0438) \u0434\u0430 \u0441\u0430 \u043f\u0440\u0435\u0437 \u043f\u044a\u043b\u043d\u043e\u043c\u043e\u0449\u043d\u0438\u043a (\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442) ConfigView.section.proxy.peer.informtracker=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043a\u044a\u043c \u0442\u0440\u0430\u043a\u0435\u0440\u0430 \u0437\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 ConfigView.section.proxy.socks.version=SOCKS \u0432\u0435\u0440\u0441\u0438\u044f PiecesView.legend.written=\u0417\u0430\u043f\u0438\u0441\u0430\u043d\u043e PiecesView.legend.requested=\u0417\u0430\u044f\u0432\u0435\u043d\u043e PiecesView.legend.downloaded=\u0421\u0432\u0430\u043b\u0435\u043d\u043e, \u0438\u0437\u0447\u0430\u043a\u0432\u0430 \u0441\u0435 \u0437\u0430\u043f\u0438\u0441 PiecesView.legend.incache=\u0414\u0430\u043d\u043d\u0438\u0442\u0435 \u0441\u0430 \u0432 \u043a\u0435\u0448\u0430 PiecesView.typeItem.0=\u0411\u0430\u0432\u043d\u043e PiecesView.typeItem.1=\u0411\u044a\u0440\u0437\u043e PiecesView.type=\u0422\u0438\u043f Security.jar.tools_not_found=\u041f\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 JAR - 'tools.jar' \u0433\u043e \u043d\u044f\u043c\u0430 \u0432 %1. \u0414\u0430 \u0441\u0435 \u0432\u0438\u0434\u0438 '\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 \u2192 \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u2192 \u0421\u0438\u0433\u0443\u0440\u043d\u043e\u0441\u0442' \u0437\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438. Security.jar.signfail=\u041f\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 JAR - %1 ConfigView.section.security.toolsinfo=\u041f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u0438\u0442\u0435 JAR \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0442 \u0437\u0430 \u043f\u043e\u0434\u0434\u0440\u044a\u0436\u043a\u0430 \u043d\u0430 \u043d\u044f\u043a\u043e\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430 Swing \u043c\u0440\u0435\u0436\u0430 (\u0430\u043a\u043e \u0441\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0438 \u0437\u0430 \u0442\u043e\u0432\u0430).\n\u0417\u0430 \u0434\u0430 \u0441\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u0432\u0430\u0442 JAR \u0444\u0430\u0439\u043b\u043e\u0432\u0435, \u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u0430 \u0435 \u0434\u043e\u0441\u0442\u044a\u043f\u0435\u043d 'tools.jar', \u043a\u043e\u0439\u0442\u043e \u0435 \u0447\u0430\u0441\u0442 \u043e\u0442 Sun JDK (\u043d\u0435 JRE) \u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f\u0442\u0430.\n\u0410\u043a\u043e \u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d \u0441\u0430\u043c\u043e JRE, \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430 JDK.\nVuze \u043c\u043e\u0436\u0435 \u0441\u0430\u043c \u0434\u0430 \u043d\u0430\u043c\u0435\u0440\u0438 \u0444\u0430\u0439\u043b\u0430. \u041d\u043e, \u0430\u043a\u043e \u043d\u0435 \u0443\u0441\u043f\u0435\u0435, \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u0449\u0430\u0442\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u0438\u0437\u0431\u0440\u0430\u043d\u0430 \u0442\u0443\u043a. ConfigView.section.security.toolsdir=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f, \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u0449\u0430 'tools.jar' ConfigView.section.security.choosetoolssavedir=\u041f\u0430\u043f\u043a\u0430, \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u0449\u0430 'tools.jar' authenticator.torrent=\u0422\u043e\u0440\u0435\u043d\u0442 ConfigView.section.proxy.peer.same=\u0415\u0434\u043d\u0438 \u0438 \u0441\u044a\u0449\u0438 \u043f\u0440\u043e\u043a\u0441\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 \u043a\u043e\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0442\u0435\u0437\u0438 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.section.connection.network.max.simultaneous.connect.attempts=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0435\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0438 \u043e\u043f\u0438\u0442\u0438 \u0437\u0430 \u0438\u0437\u0445\u043e\u0434\u044f\u0449\u0438 \u0432\u0440\u044a\u0437\u043a\u0438 ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u0435\u043d \u0431\u0440\u043e\u0439 \u043d\u043e\u0432\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0438\u0437\u0445\u043e\u0434\u044f\u0449\u0438 \u0432\u0440\u044a\u0437\u043a\u0438, \u043a\u043e\u0438\u0442\u043e Vuze \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u043f\u0440\u0430\u0432\u0438 \u043f\u043e \u0432\u0441\u044f\u043a\u043e \u0432\u0440\u0435\u043c\u0435.\n\u0417\u0430\u0431\u0435\u043b\u0435\u0436\u043a\u0430: Windows XP Service Pack 2 (SP2) \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0434\u043e 10 \u0435\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0438 \u043e\u043f\u0438\u0442\u0430 \u0437\u0430 \u0432\u0440\u044a\u0437\u043a\u0430.\n\u0421\u0442\u043e\u0439\u043d\u043e\u0441\u0442 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 8. ConfigView.section.file.perf.cache.size.explain=\u041a\u0435\u0448\u044a\u0442 \u0441\u0435 \u043f\u043e\u043b\u0437\u0432\u0430 \u0437\u0430 \u043d\u0430\u043c\u0430\u043b\u044f\u0432\u0430\u043d\u0435 \u0447\u0435\u0442\u0435\u043d\u0438\u044f\u0442\u0430/\u0437\u0430\u043f\u0438\u0441\u0438\u0442\u0435 \u043e\u0442/\u0434\u043e \u0434\u0438\u0441\u043a\u0430. \u041e\u0441\u0432\u0435\u043d, \u043a\u043e\u0433\u0430\u0442\u043e \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 java \u043e\u043f\u0446\u0438\u044f\u0442\u0430 '-XX:MaxDirectMemorySize' \u0437\u0430 \u0437\u0430\u0434\u044a\u043b\u0436\u0438\u0442\u0435\u043b\u043d\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u043d\u0430\u0442\u0430 \u043f\u0430\u043c\u0435\u0442 \u0437\u0430 \u043a\u0435\u0448 \u0438 \u043c\u0440\u0435\u0436\u043e\u0432\u0430 \u0412/\u0418 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0430, \u0442\u0430\u0437\u0438 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0435 \u043d\u0430\u0439-\u043c\u0430\u043b\u043a\u043e %1 \u043f\u043e\u0434 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440 \u043d\u0430 \u0412\u041f. \u0422\u0435\u043a\u0443\u0449\u0438\u044f\u0442 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u0435\u043d \u0440\u0430\u0437\u043c\u0435\u0440 \u043d\u0430 \u0412\u041f \u0435 %2. \u0417\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u043a\u0430\u043a \u0434\u0430 \u0441\u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u0438 \u0442\u043e\u0432\u0430, \u0434\u0430 \u0441\u0435 \u0432\u0438\u0434\u0438 MemoryUsage \u0432\u044a\u0432 wiki \u043d\u0430 %3. \u0410\u043a\u043e \u043d\u0435 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0442 \u0441\u043c\u0438\u0441\u043b\u0435\u043d\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u0449\u0435 \u0441\u0435 \u043f\u043e\u044f\u0432\u044f\u0442 'out of memory' \u0433\u0440\u0435\u0448\u043a\u0438. \u041f\u043e\u0432\u0435\u0447\u0435 \u043e\u0442 32MB \u043a\u0435\u0448 \u0431\u0438 \u0431\u0438\u043b\u043e \u0431\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043e. MyTorrentsView.menu.setSpeed.unlimit=\u0411\u0435\u0437 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 MyTorrentsView.menu.setSpeed.unlimited=\u041d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e MyTorrentsView.menu.setSpeed.disable=\u0411\u0435\u0437 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 MyTorrentsView.menu.setSpeed.disabled=\u0411\u0435\u0437 MyTorrentsView.menu.setSpeed.in=\u0432 MyTorrentsView.menu.setSpeed.slots=\u0433\u043d\u0435\u0437\u0434\u0430 \u043f\u043e GeneralView.label.maxuploadspeed=\u041c\u0430\u043a\u0441. \u041a\u0447. GeneralView.label.maxuploadspeed.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] MyTorrents.items.UpSpeedLimit.disabled=\u041d\u044f\u043c\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 MyTorrents.items.UpSpeedLimit.unlimited=\u041d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e TableColumn.header.maxupspeed=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 TableColumn.header.maxupspeed.info=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.section.file.perf.cache.enable.write=\u0414\u0430\u043d\u043d\u0438\u0442\u0435 \u043e\u0442 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f\u0442\u0430 \u0437\u0430 \u0434\u0430 \u0432 \u043a\u0435\u0448, \u0437\u0430 \u043d\u0430\u043c\u0430\u043b\u044f\u0432\u0430\u043d\u0435 \u0437\u0430\u043f\u0438\u0441\u0438\u0442\u0435 \u0432\u044a\u0440\u0445\u0443 \u0434\u0438\u0441\u043a\u0430 \u0438 \u0447\u0435\u0442\u0435\u043d\u0438\u044f\u0442\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0438 \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u0430\u0442\u0430 ConfigView.section.file.perf.cache.enable.read=\u0418\u0437\u043f\u0440\u0435\u0432\u0430\u0440\u0432\u0430\u0449\u043e \u0447\u0435\u0442\u0435\u043d\u0435 \u0437\u0430 \u043d\u0430\u043c\u0430\u043b\u044f\u0432\u0430\u043d\u0435 \u0447\u0435\u0442\u0435\u043d\u0438\u044f\u0442\u0430 \u043e\u0442 \u0434\u0438\u0441\u043a\u0430 \u043f\u0440\u0438 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 ConfigView.section.tracker.separatepeerids=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u0430 \u0441\u0430\u043c\u043e\u043b\u0438\u0447\u043d\u043e\u0441\u0442 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d \u0437\u0430 \u043a\u043e\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0438 \u0441 \u0442\u0440\u0430\u043a\u0435\u0440\u0430 \u0438 \u0437\u0430 \u0434\u0430\u043d\u043d\u0438 ConfigView.section.tracker.separatepeerids.info=\u041f\u043e\u0432\u0438\u0448\u0430\u0432\u0430\u043d\u0435 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e\u0441\u0442\u0442\u0430, \u0430\u043a\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e/\u0441\u0435\u0435\u043d\u0435\u0442\u043e \u0435 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e,\n\u0434\u043e\u043a\u0430\u0442\u043e \u0441\u0435 \u043f\u043e\u043b\u0437\u0432\u0430 \u043d\u0435-\u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 \u0441 \u0442\u0440\u0430\u043a\u0435\u0440 ConfigView.section.interface.wavlocation=\u041c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 .wav \u0444\u0430\u0439\u043b ConfigView.section.interface.wavlocation.info=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 .wav \u0444\u0430\u0439\u043b \u0438\u043b\u0438 \u043f\u0440\u0430\u0437\u043d\u043e \u0437\u0430 \u0437\u0432\u0443\u043a \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 ConfigView.section.tracker.server=\u0421\u044a\u0440\u0432\u044a\u0440 ConfigView.section.tracker.client=\u041a\u043b\u0438\u0435\u043d\u0442 ConfigView.section.tracker.client.connecttimeout=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u0437\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 (\u0441\u0435\u043a) ConfigView.section.tracker.client.readtimeout=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u0437\u0430 \u0447\u0435\u0442\u0435\u043d\u0435 (\u0441\u0435\u043a) MainWindow.menu.tools=&\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 FilesView.path=\u041f\u044a\u0442 FilesView.fullpath=\u0426\u044f\u043b\u043e\u0441\u0442\u0435\u043d \u043f\u044a\u0442 FilesView.remaining=\u041e\u0441\u0442\u0430\u0432\u0430\u0449\u0438 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 TableColumn.header.trackername=\u0418\u043c\u0435 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440 TableColumn.header.trackername.info=\u0418\u043c\u0435\u0442\u043e \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430 \u0441\u043f\u043e\u0440\u0435\u0434 URL \u043d\u0430 \u043e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0435\u0442\u043e ConfigView.group.override=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u043f\u0440\u0435\u0432\u044a\u0437\u043c\u043e\u0433\u0432\u0430\u043d\u0435 ConfigView.section.file.perf.cache.notsmallerthan=\u0414\u0430 \u043d\u0435 \u0441\u0435 \u043f\u043e\u043b\u0437\u0432\u0430 \u043a\u0435\u0448 \u0437\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u043f\u043e-\u043c\u0430\u043b\u043a\u0438 \u043e\u0442 \u0442\u043e\u0432\u0430 (\u0432 %1) PeersView.menu.blockupload=\u0411\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435\u0442\u043e PeersView.menu.kickandban=\u0418\u0437\u0445\u0432\u044a\u0440\u043b\u044f\u043d\u0435 \u0438 \u0437\u0430\u0431\u0440\u0430\u043d\u0430 PeersView.menu.kickandban.reason=\u0420\u044a\u0447\u043d\u043e \u0437\u0430\u0431\u0440\u0430\u043d\u0435\u043d \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d PeersView.state=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 PeersView.state.info=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430\u0442\u0430 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f PeersView.state.pending=\u0427\u0430\u043a\u0430\u0449\u043e PeersView.state.connecting=\u0421\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435 PeersView.state.handshake=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u0437\u0430 \u0440\u044a\u043a\u043e\u0441\u0442\u0438\u0441\u043a\u0430\u043d\u0435 PeersView.state.established=\u041d\u0430\u043f\u044a\u043b\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0435\u043d\u043e ConfigView.section.tracker.processinglimits=\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043d\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u0442\u0430 ConfigView.section.tracker.maxgettime=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0432\u0440\u0435\u043c\u0435 \u0437\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043d\u0430 GET [s] [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.tracker.maxgettime.info=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0441\u0435 \u0437\u0430 \u043e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0438\u044f \u0438 \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0438\u044f ConfigView.section.tracker.maxposttimemultiplier=\u0412\u0440\u0435\u043c\u0435-\u043c\u043d\u043e\u0436\u0438\u0442\u0435\u043b \u043d\u0430 GET \u0437\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043d\u0430 POST [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.tracker.maxposttimemultiplier.info=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0441\u0435 \u0437\u0430 \u043f\u043e\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u043e\u0440\u043c\u0443\u043b\u044f\u0440\u0438 \u0438 \u043a\u0430\u0447\u0432\u0430\u043d\u0438\u044f ConfigView.section.tracker.maxthreads=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u0438 \u0437\u0430\u044f\u0432\u043a\u0438 DownloadManager.error.operationcancancelled=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0442\u0430 \u0435 \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u0430 Torrent.create.progress.cancelled=\u041e\u0442\u043c\u0435\u043d\u0435\u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f sharing.progress.cancel=\u041e\u0442\u043a\u0430\u0437 wizard.maketorrents.autoopen=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0437\u0430 \u0441\u0435\u0435\u043d\u0435 \u0441\u043b\u0435\u0434 \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435 ConfigView.section.sharing.rescanenable=\u041f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u043d\u043e \u0434\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0432\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u0435\u043d\u043e\u0442\u043e \u0437\u0430 \u043f\u0440\u043e\u043c\u0435\u043d\u0438 ConfigView.section.sharing.rescanperiod=\u041f\u0435\u0440\u0438\u043e\u0434 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 [s] ConfigView.section.connection.advanced=\u0420\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u043c\u0440\u0435\u0436\u0430 ConfigView.section.connection.advanced.mtu=\u041d\u0430\u0439-\u0433\u043e\u043b\u044f\u043c \u043f\u0440\u0435\u043d\u0430\u0441\u044f\u043d \u043f\u0430\u043a\u0435\u0442 (MTU) \u0437\u0430 \u043b\u0438\u043d\u0438\u044f ConfigView.section.connection.advanced.mtu.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u0435\u043d \u0440\u0430\u0437\u043c\u0435\u0440 \u043d\u0430 \u043f\u0430\u043a\u0435\u0442, \u043a\u043e\u0439\u0442\u043e \u0441\u0435 \u043f\u0440\u0435\u043d\u0430\u0441\u044f \u043e\u0442 1 \u0440\u0430\u043c\u043a\u0430 \u043f\u043e \u043c\u0440\u0435\u0436\u0430\u0442\u0430.\nVuze \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 MTU-40 (MSS) \u0437\u0430 \u043f\u0430\u043a\u0435\u0442\u043d\u043e-\u0442\u043e\u0432\u0430\u0440\u043d\u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438 \u043a\u0430\u0447\u0432\u0430\u043d\u0435.\n\u041f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0438\u0442\u0435\u043b\u043d\u0438 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0438:\n 576 - \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430\n1492 - PPPoE \u0448\u0438\u0440\u043e\u043a\u043e\u043b\u0435\u043d\u0442\u043e\u0432\u0438 \u0432\u0440\u044a\u0437\u043a\u0438\n1500 - Ethernet, DSL \u0438 Cable \u0448\u0438\u0440\u043e\u043a\u043e\u043b\u0435\u043d\u0442\u043e\u0432\u0438 \u0432\u0440\u044a\u0437\u043a\u0438 ConfigView.section.connection.advanced.SO_RCVBUF=\u0420\u0430\u0437\u043c\u0435\u0440 \u043d\u0430 \u0446\u043e\u043a\u044a\u043b SO_RCVBUF [0: \u043f\u043e \u043f\u043e\u0434\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u043d\u0435 \u043e\u0442 \u041e\u0421-\u0430] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0432\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 \u0437\u0430 \u0446\u043e\u043a\u044a\u043b SO_RCVBUF (\u0432 \u0431\u0430\u0439\u0442\u043e\u0432\u0435), \u0442.\u0435. \u0440\u0430\u0437\u043c\u0435\u0440 \u0438 \u043c\u0430\u0449\u0430\u0431 \u043d\u0430 TCP \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 \u0437\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0432\u0430\u043d\u0435.\nVuze \u043e\u0441\u0442\u0430\u0432\u044f \u0442\u043e\u0432\u0430 \u043f\u0440\u0430\u0437\u043d\u043e \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435, \u043a\u043e\u0435\u0442\u043e \u0437\u043d\u0430\u0447\u0438, \u0447\u0435 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0449\u043e\u0442\u043e \u0441\u0435 \u043e\u0442 \u041e\u0421-\u0430.\n\u0417\u0430\u0431\u0435\u043b\u0435\u0436\u043a\u0430: \u041b\u0438\u043d\u0443\u043a\u0441 \u0443\u0434\u0432\u043e\u044f\u0432\u0430 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0442\u0430. ConfigView.section.connection.advanced.SO_SNDBUF=\u0420\u0430\u0437\u043c\u0435\u0440 \u043d\u0430 \u0446\u043e\u043a\u044a\u043b SO_SNDBUF [0: \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u043e\u0442 \u041e\u0421-\u0430] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0432\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 \u0437\u0430 \u0446\u043e\u043a\u044a\u043b SO_SNDBUF (\u0432 \u0431\u0430\u0439\u0442\u043e\u0432\u0435), \u0442.\u0435. \u0440\u0430\u0437\u043c\u0435\u0440\u044a\u0442 \u043d\u0430 TCP \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 \u0437\u0430 \u0438\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435.\nVuze \u043e\u0441\u0442\u0430\u0432\u044f \u0442\u043e\u0432\u0430 \u043f\u0440\u0430\u0437\u043d\u043e \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435, \u043a\u043e\u0435\u0442\u043e \u0437\u043d\u0430\u0447\u0438, \u0447\u0435 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0449\u043e\u0442\u043e \u0441\u0435 \u043e\u0442 \u041e\u0421-\u0430.\n\u0417\u0430\u0431\u0435\u043b\u0435\u0436\u043a\u0430: \u041b\u0438\u043d\u0443\u043a\u0441 \u0443\u0434\u0432\u043e\u044f\u0432\u0430 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0442\u0430. ConfigView.section.connection.advanced.IPDiffServ=\u0421\u0442\u043e\u0439\u043d\u043e\u0441\u0442 \u0437\u0430 DiffServ \u043d\u0430 \u0438\u0437\u0445\u043e\u0434\u044f\u0449\u0438 \u043f\u0430\u043a\u0435\u0442\u0438 (TOS \u043f\u043e\u043b\u0435) ConfigView.section.connection.advanced.IPDiffServ.tooltip=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430 DiffServ \u0447\u0430\u0441\u0442\u0442\u0430 \u043e\u0442 TOS \u043f\u043e\u043b\u0435\u0442\u043e \u0432 IP \u0437\u0430\u0433\u043b\u0430\u0432\u043a\u0430\u0442\u0430 \u043d\u0430 \u0438\u0437\u0445\u043e\u0434\u044f\u0449\u0438\u0442\u0435 \u043f\u0430\u043a\u0435\u0442\u0438.\n\u0428\u0435\u0441\u0442\u043d\u0430\u0434\u0435\u0441\u0435\u0442\u0438\u0447\u043d\u0438 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0438 \u0441\u0435 \u0437\u0430\u0434\u0430\u0432\u0430\u0442 \u0441 \u043f\u0440\u0435\u0444\u0438\u043a\u0441 '0x', \u043d\u0430\u043f\u0440. 0x10.\nVuze \u043d\u0435 \u0433\u043e \u0437\u0430\u0434\u0430\u0432\u0430 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435, \u0442.\u0435. \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0442 \u0441\u0435 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0438\u0442\u0435 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u043e\u0442 \u043f\u043e\u0434\u043b\u0435\u0436\u0430\u0449\u0430\u0442\u0430 OS.\n\u0412\u0430\u0436\u043d\u043e: \u041f\u043e\u0434\u043b\u0435\u0436\u0430\u0449\u0438\u0442\u0435 \u043c\u0440\u0435\u0436\u043e\u0432\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u0435 \u0434\u0430 \u043f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u043d\u0430\u0442 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0442\u0430, \u0442\u0430\u043a\u0430 \u0447\u0435 \u0442\u0430\u0437\u0438 \u0432\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442 \u043c\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0438\u0441\u0438 \u043e\u0442 OS \u0438 JRE \u0432\u0435\u0440\u0441\u0438\u0438\u0442\u0435. ConfigView.section.interface.confirm_torrent_removal=\u0414\u0438\u0430\u043b\u043e\u0433 \u0437\u0430 \u043f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.section.interface.confirm_torrent_removal.tooltip=\u041f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u043e\u0442 \u0438\u0437\u0433\u043b\u0435\u0434 \u041c\u0435\u0441\u0442\u043d\u0438 \u0422\u043e\u0440\u0435\u043d\u0442\u0438 MyTorrentsView.confirm_torrent_removal=\u0414\u0430 \u0441\u0435 \u043f\u0440\u0435\u043c\u0430\u0445\u043d\u0435 \u043b\u0438?\n TableColumn.header.seed_to_peer_ratio=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0441\u0435\u0435\u043d\u0435/\u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 TableColumn.header.seed_to_peer_ratio.info=\u041e\u0431\u0449\u043e \u0437\u0430 \u0440\u043e\u044f\u043a\u0430 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0441\u0435\u0435\u043d\u0435/\u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 PeersView.connected_time=\u041f\u0440\u043e\u0434\u044a\u043b\u0436\u0438\u0442\u0435\u043b\u043d\u043e\u0441\u0442 \u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 PeersView.connected_time.info=\u041e\u0431\u0449\u043e\u0442\u043e \u0432\u0440\u0435\u043c\u0435 \u043d\u0430 \u0441\u0432\u044a\u0440\u0437\u0430\u043d\u043e\u0441\u0442 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f ConfigView.section.interface.display.add_torrents_silently=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0442\u0438\u0445\u043e\u043c\u044a\u043b\u043a\u043e\u043c ConfigView.section.interface.display.add_torrents_silently.tooltip=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0431\u0435\u0437 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u0438\u044f \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 \u043d\u0430 Vuze. TableColumn.header.maxdownspeed=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 TableColumn.header.maxdownspeed.info=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 PeersGraphicView.title=\u0420\u043e\u044f\u043a ConfigView.section.tracker.passwordwebhttpsonly=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 \u0441\u0430\u043c\u043e \u0447\u0440\u0435\u0437 HTTPS TableColumn.header.torrentpath=\u041c\u044f\u0441\u0442\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 TableColumn.header.torrentpath.info=\u041c\u044f\u0441\u0442\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0432\u044a\u0440\u0445\u0443 \u0434\u0438\u0441\u043a\u0430 ConfigView.section.sharing.torrentcomment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0437\u0430 \u0441\u044a\u0437\u0434\u0430\u0434\u0435\u043d\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.label.copyanddeleteratherthanmove=\u041a\u043e\u043f\u0438\u0440\u0430\u043d\u0435 \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u0432\u0430\u0449\u043e \u0438\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u043d\u0438\u0442\u0435 \u0434\u0430\u043d\u043d\u0438, \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u0441 \u0435\u0434\u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f - \u043f\u0440\u0435\u0434\u043f\u0430\u0437\u0432\u0430 \u043e\u0442 \u0437\u0430\u0433\u0443\u0431\u0430 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438 \u043f\u0440\u0438 \u043d\u044f\u043a\u043e\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0438 ConfigView.label.openstatsonstart=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0434\u0430 \u0441\u0435 \u043e\u0442\u0432\u0430\u0440\u044f \u043f\u0440\u0438 \u043d\u0430\u0447\u0430\u043b\u043d\u043e \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 swt.install.window.title=\u0418\u043d\u0441\u0442\u0430\u043b\u0430\u0442\u043e\u0440 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0437\u0430 Vuze swt.install.window.ok=\u0418\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 swt.install.window.header=\u0421\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0438 \u0441\u0430 \u0438\u0437\u0431\u0440\u0430\u043d\u0438 \u0437\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435: swt.uninstall.window.title=\u0427\u0438\u0441\u0442\u0430\u0447 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0437\u0430 Vuze swt.uninstall.window.ok=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 swt.uninstall.window.header=\u0421\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0438 \u0441\u0430 \u0438\u0437\u0431\u0440\u0430\u043d\u0438 \u0437\u0430 \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435: installPluginsWizard.title=\u0418\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 installPluginsWizard.mode.title=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043c\u0435\u0442\u043e\u0434 \u0437\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 installPluginsWizard.mode.list=\u041f\u043e \u0441\u043f\u0438\u0441\u044a\u043a \u043e\u0442 sourceforge.net installPluginsWizard.list.title=\u0421\u043f\u0438\u0441\u044a\u043a \u0441 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0443\u0435\u043c\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 installPluginsWizard.list.loading=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u0437\u0430 \u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0441\u043f\u0438\u0441\u044a\u043a \u0441 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438. installPluginsWizard.list.loaded=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0437\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435. installPluginsWizard.list.name=\u0418\u043c\u0435 installPluginsWizard.list.version=\u0412\u0435\u0440\u0441\u0438\u044f installPluginsWizard.list.description=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 installPluginsWizard.finish.title=\u0418\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f \u0432 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 installPluginsWizard.finish.explanation=\u0418\u0437\u0431\u0440\u0430\u043d\u0438\u0442\u0435 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0449\u0435 \u0441\u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u0442 \u0441 \u041f\u043e\u043c\u043e\u0449\u043d\u0438\u043a\u0430 \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.\n\n\u0418\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0435 \u0442\u044a\u0440\u043f\u0435\u043d\u0438\u0435, \u043c\u043e\u0436\u0435 \u0434\u0430 \u043e\u0442\u043d\u0435\u043c\u0435 \u043c\u0430\u043b\u043a\u043e \u0432\u0440\u0435\u043c\u0435, \u0437\u0430 \u0434\u0430 \u0441\u0435 \u043f\u043e\u043a\u0430\u0436\u0435.\n\n\u0417\u0430 \u0434\u043e\u043a\u043b\u0430\u0434 \u0437\u0430 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435\u0442\u043e \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u0431\u0435\u0440\u0435 \u0432\u043b\u044f\u0432\u043e \u043d\u0430 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u043d\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e. installPluginsWizard.details.loading=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u0437\u0430 \u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438\u0085\u2026 installPluginsWizard.mode.file=\u041f\u043e \u0444\u0430\u0439\u043b installPluginsWizard.installMode.title=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0432\u0438\u0434\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f installPluginsWizard.installMode.user=\u0418\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430\u0442\u0430(\u0438\u0442\u0435) \u0437\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b installPluginsWizard.installMode.shared=\u0418\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430\u0442\u0430(\u0438\u0442\u0435) \u0437\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 installPluginsWizard.file.title=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 \u0437\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430, \u043a\u043e\u044f\u0442\u043e \u0434\u0430 \u0441\u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430 installPluginsWizard.file.file=\u0424\u0430\u0439\u043b: installPluginsWizard.file.invalidfile=\u0424\u0430\u0439\u043b\u044a\u0442 \u043d\u0435 \u0435 \u0432\u0430\u043b\u0438\u0434\u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 \u0437\u0430 Vuze. installPluginsWizard.file.no_such_file=\u041d\u044f\u043c\u0430 \u0444\u0430\u0439\u043b \u0441 \u0442\u0430\u043a\u043e\u0432\u0430 \u0438\u043c\u0435. installPluginsWizard.file.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434\u0085\u2026 uninstallPluginsWizard.title=\u0418\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 uninstallPluginsWizard.list.title=\u0421\u043f\u0438\u0441\u044a\u043a \u0441 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 uninstallPluginsWizard.list.loaded=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0436\u0435\u043b\u0430\u043d\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0437\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435. installPluginsWizard.list.nullversion=\u041d\u044f\u043c\u0430 \u0432\u0435\u0440\u0441\u0438\u044f uninstallPluginsWizard.finish.title=\u0412 \u043f\u0440\u043e\u0446\u0435\u0441 \u043d\u0430 \u0434\u0435\u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f uninstallPluginsWizard.finish.explanation=\u0418\u0437\u0431\u0440\u0430\u043d\u0438\u0442\u0435 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0449\u0435 \u0441\u0435 \u0434\u0435\u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u0442 \u0447\u0440\u0435\u0437 \u0421\u044a\u0432\u0435\u0442\u043d\u0438\u043a\u0430 \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435. MainWindow.menu.plugins.installPlugins=\u0421\u044a\u0432\u0435\u0442\u043d\u0438\u043a \u0437\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f\u0085\u2026 MainWindow.menu.plugins.uninstallPlugins=\u0421\u044a\u0432\u0435\u0442\u043d\u0438\u043a \u0437\u0430 \u0434\u0435\u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f\u0085\u2026 ConfigView.section.ipfilter.totalIPs=%1 IP-\u0442\u0430 \u043e\u0431\u0449\u043e \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0438, \u043a\u043e\u0435\u0442\u043e \u0435 %2 \u043e\u0442 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442. update.instance.install=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f\u0442\u0430 update.instance.uninstall=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0434\u0435\u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f\u0442\u0430 update.instance.update=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 MainWindow.status.update.tooltip=\u0418\u0437\u0431\u043e\u0440 \u0437\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435\u0442\u043e updater.progress.window.title=\u0422\u0435\u043a\u0443\u0449\u0438 \u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u043e\u043d\u043d\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 updater.progress.window.info=\u0414\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 '\u0418\u0437\u043e\u0441\u0442\u0430\u0432\u044f\u043d\u0435' \u0437\u0430 \u043f\u0440\u0435\u043a\u044a\u0441\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u043e\u0441\u0442\u0430\u043d\u0430\u043b\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 Button.abort=\u0418\u0437\u043e\u0441\u0442\u0430\u0432\u044f\u043d\u0435 ConfigView.section.ipfilter.enablebanning=\u0411\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438, \u043a\u043e\u0438\u0442\u043e \u043d\u0435\u043f\u0440\u0435\u043a\u044a\u0441\u043d\u0430\u0442\u043e \u043f\u0440\u0430\u0449\u0430\u0442 \u043b\u043e\u0448\u0438 \u0434\u0430\u043d\u043d\u0438 Network.alert.acceptfail=\u041c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u043d\u0438 \u043f\u0440\u043e\u0432\u0430\u0301\u043b\u0438 \u043d\u0430 \u043f\u043e\u0440\u0442 %1, %2 - \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430\u0442\u0430 \u0435 \u0438\u0437\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0430. \u0414\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0442\u0430 \u043d\u0430 \u0437\u0430\u0449\u0438\u0442\u043d\u0430\u0442\u0430 \u0441\u0442\u0435\u043d\u0430, \u0434\u0430\u043b\u0438 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430 \u0432\u0445\u043e\u0434\u044f\u0449\u0438 \u0432\u0440\u044a\u0437\u043a\u0438. MyShares.column.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f UpdateWindow.restartLater=\u041f\u043e-\u043a\u044a\u0441\u0435\u043d \u0440\u0435\u0441\u0442\u0430\u0440\u0442 \u043d\u0430 Vuze MainWindow.menu.file.restart=\u0420\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 Vuze MainWindow.dialog.restartconfirmation.title=\u0420\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 Vuze? MainWindow.dialog.restartconfirmation.text=\u041d\u0430\u0438\u0441\u0442\u0438\u043d\u0430 \u043b\u0438 \u0434\u0430 \u0441\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 Vuze? deletetorrent.message1=\u041f\u0440\u0435\u0434 \u0438\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0422\u041e\u0420\u0415\u041d\u0422 \u0437\u0430:\n deletetorrent.message2=\n\u0414\u0430 \u0431\u044a\u0434\u0435 \u043b\u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u0435\u043d\u043e? ConfigView.label.prioritizemostcompletedfiles=\u041f\u043e\u0441\u043b\u0435\u0434\u0432\u0430\u0449\u043e \u043f\u043e\u0432\u0438\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0441 \u0432\u0438\u0441\u043e\u043a \u0442\u0430\u043a\u044a\u0432 \u0441\u043f\u043e\u0440\u0435\u0434 % \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e\u0441\u0442 \u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u043d\u0430 \u0444\u0430\u0439\u043b splash.plugin.init=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430: splash.plugin.UIinit=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0413\u041f\u0418 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430: %1 ConfigView.section.style.osx_small_fonts=\u0414\u0440\u0435\u0431\u043d\u0438 \u0448\u0440\u0438\u0444\u0442\u043e\u0432\u0435 (\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442) ConfigView.section.tracker.tcpnonblocking=\u0414\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u043d\u0435-\u0431\u043b\u043e\u043a\u0438\u0440\u0430\u0449 \u0412/\u0418 \u0437\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440 \u043f\u043e TCP. \u0418\u0437\u0431\u043e\u0440\u044a\u0442 \u043d\u0430 \u0442\u043e\u0432\u0430 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0430\u0442\u0430 \u043c\u0440\u0435\u0436\u0430 \u0434\u0430 \u0432\u044a\u0440\u0432\u0438 \u043d\u0430 \u0434\u0440\u0443\u0433 \u043f\u043e\u0440\u0442. \u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u043d\u043e! ConfigView.section.tracker.nonblocking=\u041d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0430\u0449\u0438 \u043e\u043f\u0446\u0438\u0438 ConfigView.section.tracker.nonblockingconcmax=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u0438 \u0432\u0440\u044a\u0437\u043a\u0438 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] MyTorrentsView.menu.exportmenu=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 MyTorrentsView.menu.exporttorrent=\u0422\u043e\u0440\u0435\u043d\u0442\u0085 ConfigView.group.scrape=\u041e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 ConfigView.section.tracker.client.scrapeinfo=\u0417\u0430\u0431\u0440\u0430\u043d\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435\u0442\u043e \u0449\u0435 \u0441\u043f\u0440\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u0430 \u043d\u0430 \u043c\u043d\u043e\u0433\u043e \u043e\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u0442\u0430 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430, \u0442\u044a\u0439 \u043a\u0430\u0442\u043e \u0438\u0437\u0438\u0441\u043a\u0432\u0430\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0442 \u0440\u043e\u044f\u043a\u0430, \u043f\u043e\u043b\u0443\u0447\u0430\u0432\u0430\u043d\u0430 \u0447\u0440\u0435\u0437 \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0438\u0442\u0435. ConfigView.section.tracker.client.scrapeenable=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 ConfigView.section.tracker.client.scrapestoppedenable=\u041e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u043a\u043e\u0438\u0442\u043e \u043d\u0435 \u0441\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u0438 Scrape.status.disabled=\u0411\u0435\u0437 \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 MyTorrentsView.menu.explore=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b MyTorrentsView.menu.explore._mac=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u0432\u044a\u0432 Finder MyTorrentsView.menu.explore._windows=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u0432 Explorer wizard.maketorrents.autohost=\u041f\u043e\u0434\u0441\u043b\u043e\u043d\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0432\u044a\u0440\u0445\u0443 \u0432\u0433\u0440\u0430\u0434\u0435\u043d\u0438\u044f \u0442\u0440\u0430\u043a\u0435\u0440 ConfigView.label.overrideip=\u041f\u0440\u0435\u0432\u044a\u0437\u043c\u043e\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 IP-\u0442\u0430\u0442\u0430 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430 \u0437\u0430 \u043e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0435 - ';' \u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b \u0430\u043a\u043e \u0441\u0430 \u043f\u043e\u0432\u0435\u0447\u0435 \u043e\u0442 1 \u0437\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u0438 \u043c\u0440\u0435\u0436\u0438 ConfigView.label.overrideip.tooltip=\u0418\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430 \u043f\u0440\u0438 IP \u0430\u0434\u0440\u0435\u0441/\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u0438 \u043e\u0442 \u0442\u043e\u0437\u0438/\u0442\u0435\u0437\u0438, \u043e\u0442 \u043a\u043e\u0438\u0442\u043e \u043f\u0440\u0438\u0441\u0442\u0438\u0433\u0430\u0442 \u0438\u0437\u0445\u043e\u0434\u044f\u0449\u0438\u0442\u0435 \u043f\u0430\u043a\u0435\u0442\u0438. \u041f\u0440\u0430\u0437\u043d\u043e \u043d\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u043e\u043f\u0446\u0438\u044f\u0442\u0430. ConfigView.section.connection.group.networks=\u041c\u0440\u0435\u0436\u0438 ConfigView.section.connection.group.networks.info=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438 \u043c\u0440\u0435\u0436\u0438 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u0437\u0430 \u043f\u0440\u0435\u043d\u043e\u0441 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d-\u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d ConfigView.section.connection.networks.prompt=\u041f\u043e\u0434\u0441\u0435\u0449\u0430\u043d\u0435 \u0437\u0430 \u0438\u0437\u0431\u043e\u0440, \u043a\u043e\u0433\u0430\u0442\u043e \u0441\u0435 \u0434\u043e\u0431\u0430\u0432\u044f \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0441 \u0430\u043d\u043e\u043d\u0438\u043c\u0435\u043d \u0442\u0440\u0430\u043a\u0435\u0440 ConfigView.section.connection.networks.Public=\u041e\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u0430 IP \u043c\u0440\u0435\u0436\u0430 (\u043d\u0435 \u0435 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0430) ConfigView.section.connection.networks.I2P=\u041c\u0440\u0435\u0436\u0430 I2P ConfigView.section.connection.networks.Tor=\u041c\u0440\u0435\u0436\u0430 The Onion Router (Tor) TableColumn.header.networks=\u041c\u0440\u0435\u0436\u0438 TableColumn.header.networks.info=\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438 \u043c\u0440\u0435\u0436\u0438 \u0437\u0430 \u043e\u0431\u043c\u0435\u043d \u043d\u0430 \u0434\u0430\u043d\u043d\u0438 \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 Scrape.status.networkdisabled=\u041d\u044f\u043c\u0430 \u043c\u0440\u0435\u0436\u0430 ConfigView.section.tracker.server.group.networks=\u041c\u0440\u0435\u0436\u0438 ConfigView.section.tracker.server.group.networks.info=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043c\u0440\u0435\u0436\u0438, \u0437\u0430 \u043a\u043e\u0438\u0442\u043e \u0442\u0440\u0430\u043a\u0435\u0440\u044a\u0442 \u0449\u0435 \u043f\u0440\u0438\u0435\u043c\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 window.networkselection.title=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043c\u0440\u0435\u0436\u0430 window.networkselection.info=\u041f\u043e\u043a\u0430\u0437\u0430\u043d\u0438\u044f\u0442 \u043f\u043e-\u0434\u043e\u043b\u0443 \u0442\u043e\u0440\u0435\u043d\u0442 \u0438\u043c\u0430 \u0442\u0440\u0430\u043a\u0435\u0440(\u0438), \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430\u0449(\u0438) \u0441\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043c\u0440\u0435\u0436\u0438.\n\u0414\u0430 \u0441\u0435 \u0438\u0437\u0431\u0435\u0440\u0430\u0442 \u0442\u0435\u0437\u0438 \u0437\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0430 \u0438 \u043a\u043e\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u044f \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438.\n\u0410\u043a\u043e \u0442\u0440\u0430\u043a\u0435\u0440\u044a\u0442 \u0435 \u0430\u043d\u043e\u043d\u0438\u043c\u0435\u043d \u0438 \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430\u0449 \u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0438, \u0434\u0430 \u0441\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0442 \u0438 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0430\u0442\u0430 \u0438 \u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u0430\u0442\u0430 \u043c\u0440\u0435\u0436\u0438.\n\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u0430 \u043c\u0440\u0435\u0436\u0430 \u0438\u043c\u0430 \u043a\u0430\u0442\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0435 \u043e\u0442\u043f\u0430\u0434\u0430\u043d\u0435 \u043d\u0430 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e\u0441\u0442\u0442\u0430! window.networkselection.description=\u0422\u043e\u0440\u0435\u043d\u0442: plugins.basicview.clear=\u0418\u0437\u0447\u0438\u0441\u0442\u0432\u0430\u043d\u0435 ConfigView.section.connection.group.peersources=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0438\u0437\u0442\u043e\u0447\u043d\u0438\u0446\u0438 ConfigView.section.connection.group.peersources.info=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438 \u0438\u0437\u0442\u043e\u0447\u043d\u0438\u0446\u0438 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u0437\u0430 \u0432\u0440\u044a\u0437\u043a\u0438 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.section.connection.peersource.Tracker=\u041e\u0442 \u0442\u0440\u0430\u043a\u0435\u0440 ConfigView.section.connection.peersource.DHT=\u0414\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u043e \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435 ConfigView.section.connection.peersource.PeerExchange=\u0414\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u043e \u043e\u0442 \u0434\u0440\u0443\u0433 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d ConfigView.section.connection.peersource.Plugin=\u0414\u043e\u0431\u0430\u0432\u0435\u043d\u043e \u043e\u0442 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 ConfigView.section.connection.peersource.Incoming=\u0412\u0445\u043e\u0434\u044f\u0449\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 PeersView.source=\u0418\u0437\u0442\u043e\u0447\u043d\u0438\u043a PeersView.source.info=\u0418\u0437\u0442\u043e\u0447\u043d\u0438\u043a\u044a\u0442 \u043d\u0430 \u0442\u043e\u0437\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d TableColumn.header.peersources=\u0418\u0437\u0442\u043e\u0447\u043d\u0438\u0446\u0438 \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 TableColumn.header.peersources.info=\u0418\u0437\u0442\u043e\u0447\u043d\u0438\u0446\u0438 \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438 \u0437\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0438 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 wizard.tracker.dht=\u0414\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u043e (\u0441\u0430\u043c\u043e \u0437\u0430 Vuze \u043a\u043b\u0438\u0435\u043d\u0442\u0438) MyTorrentsView.menu.advancedmenu=\u0420\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438 MyTorrentsView.menu.networks=\u041c\u0440\u0435\u0436\u0438 MyTorrentsView.menu.peersource=\u0418\u0437\u0442\u043e\u0447\u043d\u0438\u0446\u0438 \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.section.sharing.permitdht=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u043e \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435, \u043a\u043e\u0433\u0430\u0442\u043e \u043d\u044f\u043c\u0430 \u0442\u0440\u0430\u043a\u0435\u0440 ConfigView.section.sharing.protocol=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0437\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u0435\u043d\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0438 (\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430) PeersView.Messaging=\u0421\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u044f PeersView.Messaging.info=\u041f\u043e\u043a\u0430\u0437\u0432\u0430 \u043a\u0430\u043a\u0432\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0437\u0430 \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0435 \u0432 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0430. ConfigView.label.queue.newseedsmovetop=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u0443\u043a\u0443-\u0449\u043e \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432 \u043d\u0430\u0447\u0430\u043b\u043e\u0442\u043e \u043d\u0430 \u0441\u043f\u0438\u0441\u044a\u043a\u0430 \u0441 \u043f\u043e\u0441\u044f\u0432\u043a\u0438 ConfigView.label.seeding.firstPriority.ignore.info=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u0435\u0437\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u043f\u0440\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\n\u0432 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043d\u0430 \u0437\u0430\u0432\u044a\u0440\u0448\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e. ConfigView.label.seeding.firstPriority.ignore=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u0442\u0430 \u0437\u0430 \u041d\u0412\u041f \u0437\u0430: ConfigView.label.seeding.firstPriority.ignoreSPRatio=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u0441 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u043e\u0441\u044f\u0432\u043a\u0438\u0442\u0435 \u043a\u044a\u043c \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u0442\u0435 \u043d\u0430\u0434 ConfigView.label.seeding.firstPriority.ignore0Peer=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u0441 0 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.section.tracker.sendjavaversionandos=\u0418\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435 \u0432\u0435\u0440\u0441\u0438\u044f\u0442\u0430 \u043d\u0430 Java \u0438 \u0438\u043c\u0435\u0442\u043e \u043d\u0430 \u041e\u0421 MagnetPlugin.contextmenu.exporturi=\u041a\u043e\u043f\u0438\u0440\u0430\u043d\u0435 \u0432 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434\u0430 \u043d\u0430 Magnet URI ConfigView.section.plugins.dht=\u0420\u0430\u0437\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u0411\u0430\u0437\u0430 \u0414\u0430\u043d\u043d\u0438 dht.info=\u0422\u0430\u0437\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430, \u043c\u0435\u0436\u0434\u0443 \u0434\u0440\u0443\u0433\u043e\u0442\u043e, \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u043e \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435 - \u0438\u0437\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435\u0442\u043e \u043c\u0443 \u0449\u0435 \u043d\u0430\u043c\u0430\u043b\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0442\u0430 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 dht.enabled=\u0421 \u0440\u0430\u0437\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u0438 dht.portdefault=\u041f\u0440\u0435\u0437 \u043f\u043e\u0440\u0442 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 dht.port=UDP \u043f\u043e\u0440\u0442 \u0437\u0430 \u0431\u0430\u0437\u0430\u0442\u0430 \u0434\u0430\u043d\u043d\u0438 dht.execute.command=\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u0437\u0430 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 dht.execute.info=\u0421 \u043d\u0430\u0442\u0438\u0441\u043a\u0430\u043d\u0435 \u0441\u0435 \u0438\u0437\u043f\u044a\u043b\u043d\u044f\u0432\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0442\u0430 dht.execute=\u0418\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 dht.logging=\u0421 \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434\u0435\u0439\u043d\u043e\u0441\u0442\u0442\u0430 ConfigView.section.plugins.dhttracker=\u0420\u0430\u0437\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0442\u0440\u0430\u043a\u0435\u0440 dhttracker.tracknormalwhenoffline=\u041f\u0440\u043e\u0441\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435 \u0441\u0430\u043c\u043e \u043d\u0430 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u043a\u043e\u0433\u0430\u0442\u043e \u0442\u0440\u0430\u043a\u0435\u0440\u044a\u0442 \u0438\u043c \u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u044a\u043f\u0435\u043d ConfigView.section.file.nativedelete._mac=\u0414\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u043a\u043e\u0448\u0430 \u043f\u0440\u0438 \u0442\u0440\u0438\u0435\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 ConfigView.section.file.nativedelete._windows=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u0442\u0440\u0438\u0442\u0438\u0442\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0432 \u043a\u043e\u0448\u0447\u0435\u0442\u043e ConfigView.section.logging.generatediagnostics=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 ConfigView.section.logging.netinfo=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u043c\u0440\u0435\u0436\u0430 ConfigView.section.logging.statsinfo=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 ConfigView.section.logging.generatediagnostics.info=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 \u0438 \u043a\u043e\u043f\u0438\u0440\u0430\u043d\u0435 \u0432 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434\u0430 \u0438 \u0434\u043d\u0435\u0432\u043d\u0438\u043a\u0430, \u0430\u043a\u043e \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e ConfigView.section.sharing.privatetorrent=\u0427\u0430\u0441\u0442\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442 - \u043f\u0440\u0438\u0435\u043c\u0430\u043d\u0435 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0441\u0430\u043c\u043e \u043e\u0442 \u0442\u0440\u0430\u043a\u0435\u0440\u0430 MainWindow.menu.tools.nattest=\u0422\u0435\u0441\u0442 \u043d\u0430 &NAT/\u0437\u0430\u0449\u0438\u0442\u043d\u0430 \u0441\u0442\u0435\u043d\u0430 Button.apply=\u041f\u0440\u0438\u043b\u0430\u0433\u0430\u043d\u0435 Button.close=\u0417\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 window.welcome.title=\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u043e\u0442 Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=\u0411\u0435\u043b\u0435\u0436\u043a\u0438 \u0437\u0430 \u0438\u0437\u0434\u0430\u043d\u0438\u0435\u0442\u043e dht.reseed.label=\u041d\u043e\u0440\u043c\u0430\u043b\u043d\u043e, \u0441\u0435\u0435\u043d\u0435 \u043d\u0430\u043d\u043e\u0432\u043e \u043d\u0430 \u0420\u0411\u0414 \u043d\u0435 \u0435 \u043d\u0443\u0436\u043d\u043e. \u0410\u043a\u043e, \u043e\u0431\u0430\u0447\u0435 \u0431\u0440\u043e\u044f\u0442 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u0438 \u0435 \u043c\u0430\u043b\u044a\u043a, \u0442\u043e\u0432\u0430 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0437\u0430 \u0440\u0435\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f.\n\u041f\u0440\u0438 \u043f\u0440\u0430\u0437\u043d\u043e, \u0441\u0435 \u043f\u0440\u0430\u0432\u0438 \u0441\u0430\u043c\u043e\u0438\u0437\u043c\u044a\u043a\u0432\u0430\u043d\u0435 \u043e\u0442 \u0441\u0432\u044a\u0440\u0437\u0430\u043d\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438, \u0430 \u043f\u0440\u0438 \u0432\u044a\u0432\u0435\u0434\u0435\u043d\u0438 IP \u0438 \u043f\u043e\u0440\u0442, \u0438\u0437\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u043d\u043e \u0441\u0430\u043c\u043e\u0438\u0437\u043c\u044a\u043a\u0432\u0430\u043d\u0435 \u043e\u0442 \u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d. dht.reseed.group=\u0421\u0435\u0435\u043d\u0435 \u043d\u0430\u043d\u043e\u0432\u043e dht.reseed.ip=IP \u0430\u0434\u0440\u0435\u0441 dht.reseed.port=\u041f\u043e\u0440\u0442 dht.reseed=\u0421\u0435\u0435\u043d\u0435 \u043d\u0430\u043d\u043e\u0432\u043e dht.reseed.info=\u0421\u0435\u0435\u043d\u0435 \u043d\u0430\u043d\u043e\u0432\u043e \u043d\u0430 \u0431\u0430\u0437\u0430\u0442\u0430 \u0434\u0430\u043d\u043d\u0438 dht.diagnostics.group=\u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438 DHTView.title.full=\u0420\u0430\u0437\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u0438 DHTView.title.fullcvs=CVS \u043d\u0430 \u0440\u0430\u0437\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430\u0442\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u0438 DHTView.general.title=\u041e\u0431\u0449\u043e DHTView.general.uptime=\u0410\u043a\u0442\u0438\u0432\u043d\u043e \u0432\u0440\u0435\u043c\u0435: DHTView.general.users=\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438: DHTView.general.nodes=\u0412\u044a\u0437\u043b\u0438: DHTView.general.leaves=\u041e\u0441\u0442\u0430\u0432\u043a\u0438: DHTView.general.contacts=\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0438: DHTView.general.replacements=\u0417\u0430\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0438\u044f: DHTView.general.live=\u0416\u0438\u0432\u0438: DHTView.general.unknown=\u041d\u0435\u043f\u043e\u0437\u043d\u0430\u0442\u0438: DHTView.general.dying=\u0423\u043c\u0438\u0440\u0430\u0449\u0438: DHTView.transport.title=\u0422\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 DHTView.transport.packets=\u041f\u0430\u043a\u0435\u0442\u0438 DHTView.transport.bytes=B DHTView.transport.received=\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043e DHTView.transport.sent=\u0418\u0437\u043f\u0440\u0430\u0442\u0435\u043d\u043e DHTView.transport.in=\u0412\u0445\u043e\u0434\u044f\u0449\u043e: DHTView.transport.out=\u0418\u0437\u0445\u043e\u0434\u044f\u0449\u043e: DHTView.operations.title=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0442\u0430 DHTView.operations.sent=\u0418\u0437\u043f\u0440\u0430\u0442\u0435\u043d\u0438 DHTView.operations.ok=\u0414\u0430 DHTView.operations.failed=\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u0438 DHTView.operations.received=\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438 DHTView.operations.ping=\u041f\u0438\u043d\u0433 DHTView.operations.findNode=\u0422\u044a\u0440\u0441\u0435\u043d\u0435 \u043d\u0430 \u0432\u044a\u0437\u0435\u043b DHTView.operations.findValue=\u0422\u044a\u0440\u0441\u0435\u043d\u0435 \u043d\u0430 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 DHTView.operations.store=\u0421\u044a\u0445\u0440\u0430\u043d\u0435\u043d\u0438 DHTView.activity.title=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 DHTView.activity.status=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 DHTView.activity.status.true=\u041d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430 DHTView.activity.status.false=\u0412 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 DHTView.activity.type=\u0422\u0438\u043f DHTView.activity.type.1=\u0412\u044a\u0442\u0440\u0435\u0448\u0435\u043d Get DHTView.activity.type.2=\u0412\u044a\u043d\u0448\u0435\u043d Get DHTView.activity.type.3=\u0412\u044a\u0442\u0440\u0435\u0448\u0435\u043d Put DHTView.activity.type.4=\u0412\u044a\u043d\u0448\u0435\u043d Put DHTView.activity.target=\u0426\u0435\u043b DHTView.activity.details=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 DHTView.db.title=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u0438 DHTView.db.keys=\u041a\u043b\u044e\u0447\u043e\u0432\u0435 DHTView.db.values=\u0421\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0438 DHTView.db.local=\u041b\u043e\u043a\u0430\u043b\u043d\u043e DHTView.db.direct=\u0414\u0438\u0440\u0435\u043a\u0442\u043d\u043e DHTView.db.indirect=\u0418\u043d\u0434\u0438\u0440\u0435\u043a\u0442\u043d\u043e DHTView.db.divfreq=\u0427\u0435\u0441\u0442. Div. DHTView.db.divsize=\u0420\u0430\u0437\u043c. Div. MainWindow.dht.status.tooltip=\u041a\u043e\u0433\u0430\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0438 \u0420\u0411\u0414, \u0442\u043e\u0432\u0430 \u043f\u043e\u043a\u0430\u0437\u0432\u0430 \u0438\u0437\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0431\u0440\u043e\u0439 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u0442\u0435\u043a\u0443\u0449\u043e \u043d\u0430 \u043b\u0438\u043d\u0438\u044f MainWindow.dht.status.disabled=\u0411\u0435\u0437 DHT MainWindow.dht.status.failed=DHT \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438 MainWindow.dht.status.initializing=DHT \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 MainWindow.dht.status.users=%1 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 MainWindow.dht.status.unreachable=DHT \u0437\u0430\u0434 \u0437\u0430\u0449\u0438\u0442\u043d\u0430 \u0441\u0442\u0435\u043d\u0430 MainWindow.dht.status.unreachabletooltip=\u0418\u043c\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 UDP \u043f\u043e\u0440\u0442 \u043d\u0430 \u0420\u0411\u0414 (NAT/\u0437\u0430\u0449\u0438\u0442\u043d\u0430 \u0441\u0442\u0435\u043d\u0430) MyTorrentsView.menu.setUpSpeed=\u0417\u0430\u0434\u0430\u0432\u0430\u043d\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 MyTorrentsView.menu.setDownSpeed=\u0417\u0430\u0434\u0430\u0432\u0430\u043d\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 ConfigView.section.tracker.client.showwarnings=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f \u0438\u0437\u0434\u0430\u0432\u0430\u043d\u0438 \u043e\u0442 \u0442\u0440\u0430\u043a\u0435\u0440\u0438\u0442\u0435 dht.advanced=\u0421 \u0440\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 dht.advanced.group=\u0420\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 dht.advanced.label=\u041f\u0440\u043e\u043c\u044f\u043d\u0430\u0442\u0430 \u043d\u0430 \u0442\u0435\u0437\u0438 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430 \u0434\u043e\u0431\u0440\u043e \u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u044f\u0442\u0430 dht.override.ip=\u041f\u0440\u0435\u0432\u044a\u0437\u043c\u043e\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u044a\u043d\u0448\u0435\u043d IP \u0430\u0434\u0440\u0435\u0441 ConfigView.section.logging.loggerenable=\u0412\u043e\u0434\u0435\u043d\u0435 \u043d\u0430 \u0434\u043d\u0435\u0432\u043d\u0438\u043a ConfigView.section.ipfilter.blockbanning=\u0417\u0430\u0431\u0440\u0430\u043d\u0430 \u043d\u0430 \u0431\u043b\u043e\u043a \u043e\u0442 256 \u0430\u0434\u0440\u0435\u0441\u0430, \u043a\u043e\u0433\u0430\u0442\u043e \u043d\u0430\u0439-\u043c\u0430\u043b\u043a\u043e \u0442\u043e\u043b\u043a\u043e\u0432\u0430 \u043e\u0442 \u0442\u044f\u0445 \u0432 \u0431\u043b\u043e\u043a\u0430 \u0441\u0430 \u0432\u0435\u0447\u0435 \u0437\u0430\u0431\u0440\u0430\u043d\u0435\u043d\u0438 MyTrackerView.passive=\u041f\u0430\u0441\u0438\u0432\u043d\u043e TableColumn.header.swarm_average_speed=\u0421\u0440\u0435\u0434\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u0437\u0430 \u0440\u043e\u044f\u043a\u0430 TableColumn.header.swarm_average_speed.info=\u0421\u0440\u0435\u0434\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u0442\u0435 \u0432 \u0440\u043e\u044f\u043a\u0430 TableColumn.header.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 TableColumn.header.comment.info=\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e TableColumn.header.commenticon=\u0418\u043a\u043e\u043d\u0430 \u043d\u0430 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 TableColumn.header.commenticon.info=\u041f\u043e\u043a\u0430\u0437\u0432\u0430 \u0438\u043a\u043e\u043d\u0430, \u0430\u043a\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e \u0438\u043c\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 MyTrackerView.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f MainWindow.menu.file.open.torrentfortracking=\u0422\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u0085\u2026 (\u0437\u0430 \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435 \u0441\u0430\u043c\u043e) VivaldiView.title.full=\u0412\u0438\u0432\u0430\u043b\u0434\u0438 MyTrackerView.date_added=\u0414\u043e\u0431\u0430\u0432\u0435\u043d\u043e ConfigView.section.tracker.portbackup=\u0417\u0430\u043f\u0430\u0300\u0441 \u043d\u0430 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 (';' \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b) ConfigView.label.playfilespeech=\u0413\u043b\u0430\u0441\u043e\u0432\u043e \u0438\u0437\u0432\u0435\u0441\u0442\u0438\u0435 \u043f\u0440\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d \u0444\u0430\u0439\u043b ConfigView.label.playfilespeech.info=\u0423\u0441\u043b\u0443\u0433\u0438\u0442\u0435 \u0437\u0430 \u0440\u0435\u0447 \u043d\u0430\u0439-\u0434\u043e\u0431\u0440\u0435 \u0440\u0430\u0431\u043e\u0442\u044f\u0442 \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438 \u0432 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 ConfigView.label.playfilefinished=\u0417\u0432\u0443\u043a\u043e\u0432 \u0441\u0438\u0433\u043d\u0430\u043b \u043f\u0440\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d \u0444\u0430\u0439\u043b ConfigView.label.backupconfigfiles=\u0417\u0430\u043f\u0430\u0441 \u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0438\u0442\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0437\u0430 \u0432\u044a\u0437\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u043f\u0440\u0438 \u043d\u0443\u0436\u0434\u0430 ConfigView.section.tracker.client.scrapesingleonly=\u0417\u0430\u0431\u0440\u0430\u043d\u044f\u0432\u0430\u043d\u0435 \u043d\u0430\u0442\u0440\u0443\u043f\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0438\u044f \u0437\u0430 \u0442\u0440\u0430\u043a\u0435\u0440 \u043f\u043e\u043e\u0442\u0434\u0435\u043b\u043d\u043e (\u043f\u043e\u043c\u0430\u0433\u0430 \u043f\u0440\u0438 \u0442\u0440\u0430\u043a\u0435\u0440\u0438 \u0438\u0437\u0434\u0430\u0432\u0430\u0449\u0438 'URL too long (414)' \u0433\u0440\u0435\u0448\u043a\u0438) dht.ipfilter.log=\u0414\u043d\u0435\u0432\u043d\u0438\u043a \u0437\u0430 \u043f\u0440\u0435\u0441\u0442\u044a\u043f\u0432\u0430\u043d\u0438\u044f\u0442\u0430 \u043d\u0430 IP \u0444\u0438\u043b\u0442\u044a\u0440\u0430 ConfigView.label.seeding.addForSeedingDLCopyCount=\u0421\u0447\u0438\u0442\u0430\u043d\u0435 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f \u0442\u0438\u043f '\u0434\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u0437\u0430 \u0441\u0435\u0435\u043d\u0435' \u0434\u0430 \u0441\u0430 \u0441\u0432\u0430\u043b\u0438\u043b\u0438 \u0441\u043b\u0435\u0434\u043d\u0438\u044f \u0431\u0440\u043e\u0439 \u043a\u043e\u043f\u0438\u044f ActivityView.legend.limit=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 ActivityView.legend.achieved=\u0414\u043e\u0441\u0442\u0438\u0433\u043d\u0430\u0442\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 ActivityView.legend.overhead=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0431\u0430\u043b\u0430\u0441\u0442\u0430 ActivityView.legend.peeraverage=\u0421\u0440\u0435\u0434\u043d\u043e ActivityView.legend.swarmaverage=\u0421\u0440\u0435\u0434\u043d\u043e \u0437\u0430 \u0440\u043e\u044f\u043a\u0430 ActivityView.legend.trimmed=\u0427\u0430\u0441\u0442\u0438\u0447\u043d\u043e MyTorrentsView.menu.movemenu=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 MyTorrentsView.menu.movedata=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0441 \u0434\u0430\u043d\u043d\u0438\u0085 MyTorrentsView.menu.movetorrent=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u0085 MyTorrentsView.menu.movedata.dialog=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043d\u043e\u0432\u043e \u043c\u044f\u0441\u0442\u043e DHTView.operations.data=\u0414\u0430\u043d\u043d\u0438 DHTView.general.reachable=\u0414\u043e\u0441\u0442\u0438\u0436\u0438\u043c\u0438: DHTView.general.rendezvous=\u0420\u0430\u043d\u0434\u0435\u0432\u0443: ConfigView.label.queue.maxactivetorrentswhenseeding=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u043e \u043f\u0440\u0438 \u0441\u0435\u0435\u043d\u0435 \u0441\u0430\u043c\u043e [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] IrcView.title.short=IRC \u041c\u0440\u0435\u0436\u0430 Views.plugins.IRC.title=IRC - \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0430 \u043f\u043e\u0434\u0434\u0440\u044a\u0436\u043a\u0430 \u043d\u0430 \u043b\u0438\u043d\u0438\u044f Formats.units.alot=\u041c\u043d\u043e\u0433\u043e!!! ConfigView.section.ipfilter.persistblocking=\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0438\u0442\u0435 IP \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0432\u0430\u0449\u0438 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438 FilesView.menu.rename=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u0435 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0430 \u0446\u0435\u043b FilesView.menu.rename_only=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u0435 FilesView.menu.retarget=\u041d\u043e\u0432\u0430 \u0446\u0435\u043b FilesView.rename.choose.path=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043d\u043e\u0432 \u0438\u043b\u0438 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449 \u0444\u0430\u0439\u043b FilesView.rename.choose.path.dir=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043d\u043e\u0432\u0430 \u0438\u043b\u0438 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f FilesView.rename.confirm.delete.title=\u041f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u0440\u0438\u0435\u043d\u0435\u0442\u043e FilesView.rename.confirm.delete.text=\u041f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0430\u0432\u0430\u043d\u0435 \u0442\u0440\u0438\u0435\u043d\u0435\u0442\u043e \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u043d\u0438\u044f \u0444\u0430\u0439\u043b '%1' FilesView.rename.filename.title=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b FilesView.rename.filename.text=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043d\u043e\u0432\u043e \u0438\u043c\u0435 \u0437\u0430 \u0444\u0430\u0439\u043b ConfigView.higher.mode.available=\u041f\u043e\u0432\u0435\u0447\u0435 \u0432\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u043c\u0430 \u0432 \u043f\u043e-\u0432\u0438\u0441\u043e\u043a\u0438\u0442\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u0438 \u0440\u0435\u0436\u0438\u043c\u0438 ConfigView.section.mode=\u0420\u0435\u0436\u0438\u043c ConfigView.section.mode.title=\u041e\u043f\u0438\u0442 \u043d\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f ConfigView.section.mode.beginner=\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u0449 ConfigView.section.mode.beginner.wiki.definitions=\u0420\u0435\u0447\u043d\u0438\u043a \u043d\u0430 BitTorrent ConfigView.section.mode.intermediate=\u041d\u0430\u043f\u0440\u0435\u0434\u043d\u0430\u043b ConfigView.section.mode.intermediate.wiki.host=\u041f\u043e\u0434\u0441\u043b\u043e\u043d\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 ConfigView.section.mode.intermediate.wiki.publish=\u041f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 ConfigView.section.mode.advanced=\u0417\u0430\u043f\u043e\u0437\u043d\u0430\u0442 ConfigView.section.mode.advanced.wiki.main=\u0413\u043b\u0430\u0432\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430 Wiki ConfigView.section.mode.beginner.text=\u0412\u0441\u0438\u0447\u043a\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438.\n\u0410\u043a\u043e \u0441\u0430\u043c\u043e \u0449\u0435 \u0441\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0432\u0430\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u0434\u0430 \u0441\u0435 \u0438\u0437\u0431\u0435\u0440\u0435 \u0442\u043e\u0437\u0438 \u0440\u0435\u0436\u0438\u043c. ConfigView.section.mode.intermediate.text=\u0414\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430.\n\u0410\u043a\u043e \u0449\u0435 \u0441\u0435 \u0441\u044a\u0437\u0434\u0430\u0432\u0430 \u043c\u0435\u0441\u0442\u0435\u043d \u0442\u0440\u0430\u043a\u0435\u0440 \u0438 \u0449\u0435 \u0441\u0435 \u043f\u043e\u0434\u0441\u043b\u043e\u043d\u044f\u0432\u0430\u0442/\u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u0442 \u043c\u0435\u0441\u0442\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435, \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0442\u043e\u0437\u0438 \u0440\u0435\u0436\u0438\u043c. ConfigView.section.mode.advanced.text=\u0414\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u043c\u0440\u0435\u0436\u043e\u0432\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438.\n\u0414\u0430 \u0441\u0435 \u043f\u043e\u043b\u0437\u0432\u0430 \u043f\u0440\u0438 \u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 MTU \u0438\u043b\u0438 \u043d\u0435-\u0431\u043b\u043e\u043a\u0438\u0440\u0430\u0449 \u0412/\u0418\u0085\u2026 Files.column.storagetype=\u0422\u0438\u043f \u0441\u044a\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 Files.column.fileext=\u0422\u0438\u043f FileItem.storage.linear=\u041b\u0438\u043d\u0435\u0439\u043d\u043e FileItem.storage.compact=\u0421\u0431\u0438\u0442\u043e MessageBoxWindow.rememberdecision=\u0417\u0430\u043f\u043e\u043c\u043d\u044f\u043d\u0435 \u043d\u0430 \u0438\u0437\u0431\u043e\u0440\u0430 ConfigView.section.interface.cleardecisions=\u0418\u0437\u0447\u0438\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0437\u0430\u043f\u043e\u043c\u043d\u0435\u043d\u0438\u0442\u0435 \u0438\u0437\u0431\u043e\u0440\u0438 \u0432 \u0434\u0438\u0430\u043b\u043e\u0437\u0438\u0442\u0435 ConfigView.section.interface.cleardecisionsbutton=\u0418\u0437\u0447\u0438\u0441\u0442\u0432\u0430\u043d\u0435 ConfigView.section.interface.cleartrackers=\u0418\u0437\u0447\u0438\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0437\u0430\u043f\u043e\u043c\u043d\u0435\u043d\u0438 \u0442\u0440\u0430\u043a\u0435\u0440\u0438 ConfigView.section.interface.cleartrackersbutton=\u0418\u0437\u0447\u0438\u0441\u0442\u0432\u0430\u043d\u0435 ConfigView.section.interface.clearsavepaths=\u0418\u0437\u0447\u0438\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0437\u0430\u043f\u043e\u043c\u043d\u0435\u043d\u0438\u0442\u0435 \u043f\u044a\u0442\u0438\u0449\u0430 \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 ConfigView.section.interface.clearsavepathsbutton=\u0418\u0437\u0447\u0438\u0441\u0442\u0432\u0430\u043d\u0435 configureWizard.welcome.usermodes=\u041e\u043f\u0438\u0442\u044a\u0442 \u043d\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u0442\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u0438 \u043e\u0442 '\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 \u2192 \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f'. \u041f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u0441\u0435 \u043d\u0438\u0432\u043e\u0442\u043e \u0434\u0430 \u0441\u0435 \u0438\u0437\u0431\u0435\u0440\u0435 \u0432 \u0441\u044a\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435. FilesView.skip.confirm.delete.text=\u041f\u0440\u0435\u043a\u044a\u0441\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b '%1' \u0437\u0430 \u0438\u043a\u043e\u043d\u043e\u043c\u0438\u044f \u043d\u0430 \u043c\u044f\u0441\u0442\u043e? FilesView.rename.failed.title=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u0435\u0442\u043e/\u0441\u043c\u044f\u043d\u0430\u0442\u0430 \u043d\u0430 \u0446\u0435\u043b\u0442\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438 FilesView.rename.failed.text=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0442\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438, \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u0437\u0430\u0440\u0430\u0434\u0438 \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u0438\u0437\u0431\u043e\u0440 \u043d\u0430 \u0446\u0435\u043b diagnostics.log_found=\u0420\u0430\u0431\u043e\u0442\u0430\u0442\u0430 \u0441 Vuze \u043d\u0435 \u0435 \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u043d\u043e. \u0414\u0430 \u0441\u0435 \u043f\u043e\u0433\u043b\u0435\u0434\u043d\u0435 \u0437\u0430 \u0434\u043d\u0435\u0432\u043d\u0438\u0446\u0438 \u0441 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430. \u0414\u0430 \u0441\u0435 \u043f\u0440\u043e\u0447\u0435\u0442\u0435 \u0441\u044a\u0449\u043e \u0443\u0438\u043a\u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f\u0442\u0430 Vuze \u0438\u0437\u0447\u0435\u0437\u0432\u0430 ManagerItem.paused=\u0412 \u043f\u0430\u0443\u0437\u0430 Utils.link.visit=\u0414\u0430 \u0441\u0435 \u043f\u043e\u0441\u0435\u0442\u0438 ConfigView.section.connection.serverport.wiki=\u0418\u0437\u0431\u0440\u0430\u043d\u0438 \u0434\u043e\u0431\u0440\u0438 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 ConfigView.section.transfer.speeds.wiki=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u0434\u043e\u0431\u0440\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 installPluginsWizard.installMode.info.title=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f installPluginsWizard.installMode.info.text=\u041d\u0435 \u0441\u0430 \u043d\u0443\u0436\u043d\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438, \u0437\u0430 \u0434\u0430 \u0440\u0430\u0431\u043e\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u043d\u043e Vuze, \u043d\u043e \u0442\u0435 \u043f\u0440\u0438\u0431\u0430\u0432\u044f\u0442 \u0434\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u043d\u0438 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0438 \u0437\u0430 \u0437\u0430\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u043b\u0438 \u043e\u0442\u0434\u0430\u043b\u0435\u0447\u0435\u043d \u0434\u043e\u0441\u0442\u044a\u043f.\n\u041f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u0441\u0435 \u0437\u0430\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043d\u0435 \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u0432\u0441\u044f\u043a\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 \u043f\u0440\u0435\u0434\u0438 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435.\n\u041f\u043e\u0432\u0435\u0447\u0435\u0442\u043e \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0441\u0430 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0438 \u0437\u0430 \u043f\u0440\u043e\u0431\u0430, \u043d\u043e \u0432\u0441\u0435 \u043f\u0430\u043a \u0434\u0430 \u043d\u0435 \u0441\u0435 \u043f\u0440\u0435\u0442\u043e\u0432\u0430\u0440\u0432\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0442\u0430 \u0441 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438, \u043a\u043e\u0438\u0442\u043e \u043d\u044f\u043c\u0430 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0442. Views.plugins.Distributed.DB.title=\u0420\u0430\u0437\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u0411\u0414 Views.plugins.Distributed.Tracker.title=\u0420\u0430\u0437\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0442\u0440\u0430\u043a\u0435\u0440 Views.plugins.Plugin.Update.title=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 Views.plugins.UPnP.title=UPnP \u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 Views.plugins.UPnP.title.tooltip=\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u0435\u043d\u043e \u041f\u0440\u0438\u0441\u044a\u0435\u0434\u0438\u043d\u044f\u0432\u0430\u043d\u0435 \u0438 \u041f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 openUrl.url.info=\u041f\u043e\u0434\u0434\u044a\u0440\u0436\u0430 HTTP, HTTPS, magnet \u0438 raw hex infohash \u043d\u0438\u0437\u043e\u0432\u0435 TableColumn.header.swarm_average_completion=\u0421\u0440\u0435\u0434\u043d\u0430 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e\u0441\u0442 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d TableColumn.header.swarm_average_completion.info=\u0421\u0440\u0435\u0434\u043d\u0438\u044f\u0442 % \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e\u0441\u0442 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u0442\u0435 \u0432 \u0440\u043e\u044f\u043a\u0430 GeneralView.label.swarm_average_completion=\u0421\u0440\u0435\u0434\u043d\u043e \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e: GeneralView.label.swarm_average_completion.tooltip=\u0421\u0440\u0435\u0434\u043d\u043e \u0437\u0430\u0432\u044a\u0440\u0448\u0432\u0430\u043d\u0435 \u0432 % \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u0442\u0435 \u0432 \u0440\u043e\u044f\u043a\u0430 MainWindow.nat.status.tooltip.unknown=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u0434\u043e\u0301\u0441\u0435\u0433\u0430 \u043f\u0440\u0438 \u0437\u0430\u0449\u0438\u0442\u043d\u0430 \u0441\u0442\u0435\u043d\u0430/NAT \u0435 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d \u043f\u0440\u0435\u0437 TCP MainWindow.nat.status.ok=NAT \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e MainWindow.nat.status.tooltip.ok=\u0414\u043e\u0441\u0435\u0433 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u043d TCP MainWindow.nat.status.probok=NAT \u043f\u0440\u043e\u0431\u0430 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e MainWindow.nat.status.tooltip.probok=\u0414\u043e\u0441\u0435\u0433\u044a\u0442 \u0431\u0435\u0448\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u043d, \u043d\u043e \u043d\u044f\u043c\u0430 \u0441\u043a\u043e\u0440\u043e\u0448\u043d\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0438 TCP \u0432\u0440\u044a\u0437\u043a\u0438 MainWindow.nat.status.bad=\u0417\u0430\u0434 \u0437\u0430\u0449\u0438\u0442\u043d\u0430 \u0441\u0442\u0435\u043d\u0430 MainWindow.nat.status.tooltip.bad=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u0434\u043e\u0301\u0441\u0435\u0433\u0430 \u043f\u0440\u0438 \u0437\u0430\u0449\u0438\u0442\u043d\u0430 \u0441\u0442\u0435\u043d\u0430/NAT \u043f\u0440\u0435\u0437 TCP. \u0414\u0430 \u0441\u0435 \u0432\u0438\u0434\u0438 Wiki \u0437\u0430 \u043f\u043e\u043c\u043e\u0449 plugin.installer.recommended.plugin=\u041f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0438\u0442\u0435\u043b\u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 - \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u0433\u043b\u0435\u0434\u0430 \u0438 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430, \u0430\u043a\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e LoggerView.pause=\u041f\u0430\u0443\u0437\u0430 \u043d\u0430 \u0434\u043d\u0435\u0432\u043d\u0438\u043a\u0430 LoggerView.clear=\u0418\u0437&\u0447\u0438\u0441\u0442\u0432\u0430\u043d\u0435 LoggerView.filter=\u0424\u0438\u043b\u0442\u044a\u0440 LoggerView.filter.uncheckAll=\u0412\u0441\u0438\u0447\u043a\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u043d\u0435\u043e\u0442\u043c\u0435\u0442\u043d\u0430\u0442\u0438 LoggerView.filter.checkAll=\u0412\u0441\u0438\u0447\u043a\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u043e\u0442\u043c\u0435\u0442\u043d\u0430\u0442\u0438 LoggerView.loggingDisabled=\u0411\u0435\u0437 \u0434\u043d\u0435\u0432\u043d\u0438\u043a. LoggerView.includeOnly=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u0441\u0430\u043c\u043e \u043d\u0430 \u0440\u0435\u0434\u043e\u0432\u0435 \u043e\u0442\u0433\u043e\u0432\u0430\u0440\u044f\u0449\u0438 \u043d\u0430 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0438\u044f \u0438\u0437\u0440\u0430\u0437: LoggerView.excludeAll=\u0411\u0435\u0437 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0440\u0435\u0434\u043e\u0432\u0435 \u043e\u0442\u0433\u043e\u0432\u0430\u0440\u044f\u0449\u0438 \u043d\u0430 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0438\u044f \u0438\u0437\u0440\u0430\u0437: ConfigView.section.logging.log0type=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f ConfigView.section.logging.log1type=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 ConfigView.section.logging.log2type=\u0413\u0440\u0435\u0448\u043a\u0430 ConfigView.section.logging.filter=\u0424\u0438\u043b\u0442\u0440\u0438\u0440\u0430\u043d\u0435 \u043f\u0440\u0438 \u0437\u0430\u043f\u0438\u0441 \u0432 \u0434\u043d\u0435\u0432\u043d\u0438\u043a ConfigView.section.logging.level=\u041d\u0438\u0432\u043e \u043d\u0430 \u0437\u0430\u043f\u0438\u0441 \u0437\u0430 \u0434\u043d\u0435\u0432\u043d\u0438\u043a\u0430 ConfigView.section.logging.showLogsFor=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 %1 \u0434\u043d\u0435\u0432\u043d\u0438\u0446\u0438 \u0437\u0430 \u0441\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438: ConfigView.pluginlist.column.loadAtStartup=\u0417\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 ConfigView.pluginlist.column.type=\u0422\u0438\u043f ConfigView.pluginlist.column.type.perUser=\u0417\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b ConfigView.pluginlist.column.type.shared=\u0421\u043f\u043e\u0434\u0435\u043b\u0435\u043d ConfigView.pluginlist.column.type.builtIn=\u0412\u0433\u0440\u0430\u0434\u0435\u043d ConfigView.pluginlist.column.name=\u0418\u043c\u0435 ConfigView.pluginlist.column.version=\u0412\u0435\u0440\u0441\u0438\u044f ConfigView.pluginlist.column.directory=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f ConfigView.pluginlist.column.isOperational=\u0420\u0430\u0431\u043e\u0442\u0438? PeersView.BlockView.Avail.Have=\u0418 \u0434\u0432\u0430\u043c\u0430\u0442\u0430 \u0438\u043c\u0430\u0442 PeersView.BlockView.Avail.NoHave=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f\u0442 \u0438\u043c\u0430; \u043c\u0435\u0441\u0442\u043d\u043e \u043d\u044f\u043c\u0430 PeersView.BlockView.NoAvail.Have=\u041c\u0435\u0441\u0442\u043d\u043e \u0438\u043c\u0430; \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f\u0442 \u043d\u044f\u043c\u0430 PeersView.BlockView.NoAvail.NoHave=\u0418 \u0434\u0432\u0430\u043c\u0430\u0442\u0430 \u043d\u044f\u043c\u0430\u0442 PeersView.BlockView.Transfer=\u041f\u0440\u0435\u043d\u0430\u0441\u044f\u043d\u0435 PeersView.BlockView.NextRequest=\u0421\u043b\u0435\u0434\u0432\u0430\u0449\u0430 \u0437\u0430\u044f\u0432\u043a\u0430 PeersView.BlockView.title=\u041a\u0430\u0440\u0442\u0430 \u043d\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u0430\u0442\u0430 PeersView.BlockView.AvailCount=\u0411\u0440\u043e\u044f\u0447 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u043d\u043e MyTorrentsView.dialog.NumberError.title=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0430 \u0438\u043b\u0438 \u043d\u0435\u0440\u0430\u0437\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u0435\u043c\u0430 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 MyTorrentsView.dialog.NumberError.text=\u0412\u044a\u0432\u0435\u0434\u0435\u043d\u0430\u0442\u0430 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 \u0435 \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0430 \u0438\u043b\u0438 \u043d\u0435\u0440\u0430\u0437\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u0435\u043c\u0430. MyTorrentsView.menu.manual=&\u0420\u044a\u0447\u043d\u043e\u0085 MyTorrentsView.menu.manual.per_torrent=\u0420\u044a\u0447\u043d\u043e (\u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442) MyTorrentsView.menu.manual.shared_torrents=\u0420\u044a\u0447\u043d\u043e (\u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438) MyTorrentsView.dialog.setSpeed.title=\u0417\u0430\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u0437\u0430 %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=\u0412\u044a\u0432\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 %1 \u0437\u0430 \u043f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 %2: MyTorrentsView.dialog.setNumber.upload=\u043a\u0430\u0447\u0432\u0430\u043d\u0435 MyTorrentsView.dialog.setNumber.download=\u0441\u0432\u0430\u043b\u044f\u043d\u0435 MyTorrentsView.dialog.setNumber.inKbps=\u0432 %1 OpenTorrentWindow.torrentLocation=\u0422\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u043e\u0432\u0435: OpenTorrentWindow.addFiles.URL=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 &URL OpenTorrentWindow.addFiles.Folder=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 &\u043f\u0430\u043f\u043a\u0430 OpenTorrentWindow.addFiles.Clipboard=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043e\u0442 \u043a\u043b\u0438\u043f&\u0431\u043e\u0440\u0434\u0430 OpenTorrentWindow.changeDestination=\u041f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 \u043c\u0435\u0441\u0442\u043e\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u0442\u043e OpenTorrentWindow.fileList=\u0424\u0430\u0439\u043b\u043e\u0432\u0435 \u0432 \u0442\u043e\u0440\u0435\u043d\u0442\u0438: OpenTorrentWindow.torrentTable.name=\u0418\u043c\u0435 OpenTorrentWindow.torrentTable.saveLocation=\u041c\u044f\u0441\u0442\u043e \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 OpenTorrentWindow.fileTable.fileName=\u0418\u043c\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b OpenTorrentWindow.fileTable.size=\u0420\u0430\u0437\u043c\u0435\u0440 OpenTorrentWindow.fileTable.destinationName=\u0418\u043c\u0435 \u043d\u0430 \u043c\u0435\u0441\u0442\u043e\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 OpenTorrentWindow.startMode.seeding=\u0421\u0435\u0435\u043d\u0435 OpenTorrentWindow.fileList.changeDestination=\u041f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 \u043c\u0435\u0441\u0442\u043e\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u0442\u043e OpenTorrentWindow.mb.badSize.title=\u041d\u0435\u0441\u044a\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0444\u0430\u0439\u043b OpenTorrentWindow.mb.badSize.text='%1' \u043d\u0435 \u0435 '%2' \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0437\u0430 \u0441\u0435\u0435\u043d\u0435 OpenTorrentWindow.mb.alreadyExists.text=\u0422\u043e\u0440\u0435\u043d\u0442 '%1' \u0432\u0435\u0447\u0435 \u0435 \u0434\u043e\u0431\u0430\u0432\u0435\u043d \u043a\u0430\u0442\u043e '%2' OpenTorrentWindow.mb.alreadyExists.default.name=\u041d\u043e\u0441\u0438\u0442\u0435\u043b OpenTorrentWindow.mb.alreadyExists.title=\u0422\u043e\u0440\u0435\u043d\u0442\u044a\u0442 \u0432\u0435\u0447\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430 OpenTorrentWindow.mb.openError.title=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 OpenTorrentWindow.mb.openError.text='%1' \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u043e\u0442\u0432\u043e\u0440\u0438:\n%2 OpenTorrentWindow.torrent.remove=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043e\u0442 \u0441\u043f\u0438\u0441\u044a\u043a\u0430 OpenTorrentWindow.torrent.options=\u0421\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0449\u0435 \u0441\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0430\u0442 \u043d\u0430 \u0433\u043e\u0440\u0435\u0438\u0437\u0431\u0440\u0430\u043d\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438: OpenTorrentWindow.xOfTotal=(%1 \u043e\u0442 %2) iconBar.open.tooltip=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442(\u0438) LocaleUtil.column.text=\u041d\u0435\u043f\u043e\u0437\u043d\u0430\u0442 \u0442\u0435\u043a\u0441\u0442 Tracker.tooltip.MultiSupport=\u0422\u043e\u0437\u0438 \u0442\u0440\u0430\u043a\u0435\u0440 \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0440\u0430\u0437\u0431\u044a\u0440\u043a\u0432\u0430\u043d\u0435\u0442\u043e \u0437\u0430 \u0437\u0430\u044f\u0432\u043a\u0430. Tracker.tooltip.NoMultiSupport=\u0422\u043e\u0437\u0438 \u0442\u0440\u0430\u043a\u0435\u0440 \u043d\u0435 \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0440\u0430\u0437\u0431\u044a\u0440\u043a\u0432\u0430\u043d\u0435\u0442\u043e \u0437\u0430 \u0437\u0430\u044f\u0432\u043a\u0430. ConfigView.label.lazybitfield=\u041c\u044a\u0440\u0437\u0435\u043b\u0438\u0432\u043e \u0431\u0438\u0442-\u043f\u043e\u043b\u0435 (\u043f\u043e\u043c\u0430\u0433\u0430 \u0441\u0435\u0435\u043d\u0435\u0442\u043e \u0432 \u043c\u0440\u0435\u0436\u0438, \u0432 \u043a\u043e\u0438\u0442\u043e \u0438\u043c\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0435 \u043f\u043e \u0431\u0438\u0442-\u043f\u043e\u043b\u0435) LoggerView.realtime=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432 \u0440\u0435\u0430\u043b\u043d\u043e \u0432\u0440\u0435\u043c\u0435 ConfigView.section.file.perf.cache.flushpieces=\u041c\u043e\u043c\u0435\u043d\u0442\u0430\u043b\u0435\u043d \u0437\u0430\u043f\u0438\u0441 \u043d\u0430 \u0446\u0435\u043b\u0438 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 \u043d\u0430 \u0434\u0438\u0441\u043a\u0430. \u0423\u043b\u0435\u0441\u043d\u044f\u0432\u0430 \u0434\u043e\u0441\u0442\u044a\u043f\u0430 \u0434\u043e \u0434\u0438\u0441\u043a\u0430, \u043d\u043e \u043c\u043e\u0436\u0435 \u0434\u0430 \u0443\u0432\u0435\u043b\u0438\u0447\u0438 \u0437\u0430\u043f\u0438\u0441\u0432\u0430\u0449\u0438\u0442\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438. ConfigView.section.file.writemblimit=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0437\u0430\u044f\u0432\u043a\u0438 \u0437\u0430 \u0437\u0430\u043f\u0438\u0441 \u0432 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430 (\u0432 %1) ConfigView.section.file.writemblimit.explain=\u041a\u043e\u0433\u0430\u0442\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441 \u0432\u044a\u0440\u0445\u0443 \u0434\u0438\u0441\u043a\u0430 \u0435 \u043f\u043e-\u043d\u0438\u0441\u043a\u0430 \u043e\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435, \u0442\u043e\u0437\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u044a\u0440 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0430\u0432\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u0442\u043e \u0434\u0430\u043d\u043d\u0438, \u043a\u043e\u0438\u0442\u043e \u043e\u0442\u0438\u0432\u0430\u0442 \u0432 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430, \u043f\u0440\u0435\u0434\u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438\u0442\u0435 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0434\u0430 \u0441\u0435 \u043d\u0430\u043c\u0430\u043b\u044f\u0442. ConfigView.section.file.readmblimit=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u043e \u0437\u0430\u044f\u0432\u043a\u0438 \u0437\u0430 \u0447\u0435\u0442\u0435\u043d\u0435 \u0432 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430 (\u0432 %1) ConfigView.section.file.readmblimit.explain=\u0422\u043e\u0437\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u044a\u0440 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0430\u0432\u0430 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u043f\u0430\u043c\u0435\u0442, \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0430 \u0437\u0430 \u0441\u044a\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0447\u0438\u0442\u0438, \u0447\u0430\u043a\u0430\u0449\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430. Button.moveUp=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430&\u0433\u043e\u0440\u0435 Button.moveDown=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430&\u0434\u043e\u043b\u0443 ConfigView.notAvailableForMode=\u0422\u0430\u0437\u0438 \u0441\u0435\u043a\u0446\u0438\u044f \u0435 \u043f\u0440\u0435\u0434\u0432\u0438\u0434\u0435\u043d\u0430 \u0437\u0430 %1 \u0440\u0435\u0436\u0438\u043c \u0438\u043b\u0438 \u043f\u043e-\u0432\u0438\u0441\u043e\u043a. \u041d\u0435 \u0435 \u0434\u043e\u0441\u0442\u044a\u043f\u043d\u0430 \u0437\u0430 %2 \u0440\u0435\u0436\u0438\u043c. health.explain.error=\u0418\u043c\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u0442\u043e\u0437\u0438 \u0442\u043e\u0440\u0435\u043d\u0442. \u0414\u0430 \u0441\u0435 \u0432\u0438\u0434\u0438 \u043a\u043e\u043b\u043e\u043d\u0430\u0442\u0430 '\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435' \u0438\u043b\u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430\u0442\u0430 \u0432\u044a\u0440\u0445\u0443 \u0438\u043a\u043e\u043d\u0430\u0442\u0430 \u0437\u0430 \u0442\u0430\u0437\u0438 \u0433\u0440\u0435\u0448\u043a\u0430. GeneralView.label.trackerscrapeupdate=\u041e\u0441\u0442\u044a\u0440\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430 PeersView.piece=\u041f\u0430\u0440\u0447\u0435 PeersView.piece.info=\u2116 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u043e \u043f\u0430\u0440\u0447\u0435 \u043f\u043e\u0438\u0441\u043a\u0430\u043d\u043e \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f PiecesView.priority=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 PiecesView.priority.info=\u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043d\u0430 \u0437\u0430\u0432\u044a\u0440\u0448\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0432\u0430 \u043f\u0430\u0440\u0447\u0435, \u043d\u043e \u043d\u0435 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u043e\u0441\u043e\u0431\u0435\u043d\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 PiecesView.speed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442 PiecesView.speed.info=\u041f\u043e-\u0431\u0430\u0432\u043d\u0438\u0442\u0435 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u043d\u0435 \u043c\u043e\u0433\u0430\u0442 \u043c\u043d\u043e\u0433\u043e \u0434\u0430 \u0441\u0435 \u0431\u044a\u0440\u043a\u0430\u0442 \u0432 \u043f\u043e-\u0431\u044a\u0440\u0437\u0438 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 TableColumn.header.AvgAvail.info=\u0421\u0443\u043c\u0430 \u043e\u0442 \u043d\u0430\u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438 \u043d\u0430 \u0431\u0440. \u043f\u0430\u0440\u0447\u0435\u0442\u0430 \u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438 \u043d\u0430 \u0431\u0440. \u0432\u0440\u044a\u0437\u043a\u0438 TableColumn.header.AvgAvail=\u0421\u0440. \u043d\u0430\u043b./\u043f\u0430\u0440\u0447\u0435 ConfigView.label.strictfilelocking=\u0412\u044a\u0432\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435 \u0437\u0430 \u0438\u0437\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u0435\u043d \u0434\u043e\u0441\u0442\u044a\u043f \u0437\u0430 \u0437\u0430\u043f\u0438\u0441 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0441\u0440\u0435\u0434 \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u0442\u0435 MyTorrentsView.menu.checkfilesexist=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 MyTorrentsView.menu.rescanfile=\u041f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043d\u0435\u043f\u044a\u043b\u043d\u0438\u0442\u0435 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 MyTorrentsView.menu.clear_resume_data=\u0418\u0437\u0447\u0438\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438\u0442\u0435 \u0437\u0430 \u043f\u0440\u043e\u0434\u044a\u043b\u0436\u0430\u0432\u0430\u043d\u0435 Plugin.extseed.name=\u0412\u044a\u043d\u0448\u043d\u0438 \u043f\u043e\u0441\u044f\u0432\u043a\u0438 Plugin.localtracker.name=\u0422\u044a\u0440\u0441\u0430\u0447 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0432 \u043b\u043e\u043a\u0430\u043b\u043d\u0430 \u043c\u0440\u0435\u0436\u0430 Plugin.localtracker.info=\u0422\u044a\u0440\u0441\u0430\u0447\u044a\u0442 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0432 \u043b\u043e\u043a\u0430\u043b\u043d\u0430 \u043c\u0440\u0435\u0436\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043f\u0438\u044f \u043d\u0430 Vuze \u0437\u0430\u0434 \u0437\u0430\u0449\u0438\u0442\u043d\u0430 \u0441\u0442\u0435\u043d\u0430 \u0438 \u0432 \u043e\u0431\u0449\u0430 \u043c\u0440\u0435\u0436\u0430\n\u0437\u0430 \u0435\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043a\u0430\u0442\u043e \u043e\u0442\u0432\u0430\u0440\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u043d\u0438 \u0432\u0440\u044a\u0437\u043a\u0438 \u043f\u043e\u043c\u0435\u0436\u0434\u0443 \u0438\u043c Plugin.localtracker.enable=\u0421 \u0442\u044a\u0440\u0441\u0430\u0447 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0432 \u043b\u043e\u043a\u0430\u043b\u043d\u0430 \u043c\u0440\u0435\u0436\u0430 azinstancehandler.alert.portclash=\u041a\u043e\u043d\u0444\u043b\u0438\u043a\u0442 \u043d\u0430 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 \u0432 \u043b\u043e\u043a\u0430\u043b\u043d\u0430\u0442\u0430 \u043c\u0440\u0435\u0436\u0430: %1 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u043e\u0442 \u0434\u0440\u0443\u0433 Vuze \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b, \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0435 \u043d\u043e\u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u0435\u043d \u0438\u0437\u0431\u043e\u0440 \u043d\u0430 \u043f\u043e\u0440\u0442(\u043e\u0432\u0435) \u0437\u0430 \u0432\u0445\u043e\u0434\u044f\u0449\u043e TCP/UDP \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0432\u0430\u043d\u0435 [\u043c\u0435\u0436\u0434\u0443 %2 \u0438 %3]. ConfigView.section.transfer.lan=\u041b\u043e\u043a\u0430\u043b\u043d\u0430 \u043c\u0440\u0435\u0436\u0430 ConfigView.section.transfer.lan.tooltip=\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u043b\u043e\u043a\u0430\u043b\u043d\u0430 \u043c\u0440\u0435\u0436\u0430 ConfigView.section.transfer.lan.uploadrate=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u0437\u0430 \u043b\u043e\u043a\u0430\u043b\u043d\u0430 \u043c\u0440\u0435\u0436\u0430 KB/s [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.transfer.lan.uploadrate.tooltip=\u0412\u0440\u044a\u0437\u043a\u0438\u0442\u0435 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0432 \u0441\u044a\u0449\u0430\u0442\u0430 \u043b\u043e\u043a\u0430\u043b\u043d\u0430 \u043c\u0440\u0435\u0436\u0430 \u0438\u043c\u0430\u0442 \u043e\u0442\u0434\u0435\u043b\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435. ConfigView.section.transfer.lan.downloadrate=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0437\u0430 \u043b\u043e\u043a\u0430\u043b\u043d\u0430 \u043c\u0440\u0435\u0436\u0430 KB/s [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.transfer.lan.downloadrate.tooltip=\u0412\u0440\u044a\u0437\u043a\u0438\u0442\u0435 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0432 \u0441\u044a\u0449\u0430\u0442\u0430 \u043b\u043e\u043a\u0430\u043b\u043d\u0430 \u043c\u0440\u0435\u0436\u0430 \u0438\u043c\u0430\u0442 \u043e\u0442\u0434\u0435\u043b\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435. TorrentOptionsView.title.short=\u0412\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 TorrentOptionsView.title.full=\u0412\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 TorrentOptionsView.param.max.peers=\u041c\u0430\u0441\u043a\u0438\u043c\u0443\u043c \u0431\u0440\u043e\u0439 \u0432\u0440\u044a\u0437\u043a\u0438 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.connection.encryption.require_encrypted_transport=\u0418\u0437\u0438\u0441\u043a\u0432\u0430\u043d\u0435 \u043d\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442 ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=\u041d\u0430\u0441\u0438\u043b\u0441\u0442\u0432\u0435\u043d\u0430 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0430 \u043d\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438 \u0432\u0440\u044a\u0437\u043a\u0438 \u0441 \u0434\u0440\u0443\u0433\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438. ConfigView.section.connection.encryption.min_encryption_level=\u041d\u0430\u0439-\u043d\u0438\u0441\u043a\u043e \u043d\u0438\u0432\u043e \u043d\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 ConfigView.section.connection.encryption.min_encryption_level.tooltip=\u041f\u0440\u043e\u0441\u0442\u043e - \u0441\u0430\u043c\u043e \u0437\u0430 \u0440\u044a\u043a\u043e\u0441\u0442\u0438\u0441\u043a\u0430\u043d\u0435\nRC4 - \u043f\u044a\u043b\u0435\u043d \u043f\u043e\u0442\u043e\u043a\n\u041f\u043e-\u0432\u0438\u0441\u043e\u043a\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u043f\u043e\u0432\u0435\u0447\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u0435\u043d \u0440\u0435\u0441\u0443\u0440\u0441. Peers.column.Encryption=\u0428\u0438\u0444\u0440\u043e\u0432\u043a\u0430 Peers.column.Encryption.info=\u041d\u0438\u0432\u043e \u043d\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 \u0442\u0435\u043a\u0443\u0449\u043e ConfigView.section.connection.encryption.encrypt.info=\u0410\u043a\u043e \u0435 \u0432 \u0441\u0438\u043b\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430, \u043d\u044f\u043c\u0430 \u0434\u0430 \u0435 \u0432\u044a\u0437\u043c\u043e\u0436\u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430\u0442\u0430 \u0441 \u043d\u0435\u0441\u044a\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0438, \u043e\u0441\u0432\u0435\u043d \u0430\u043a\u043e \u043d\u0435 \u0441\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u043e\u0442\u0441\u0442\u044a\u043f\u043b\u0435\u043d\u0438\u0435 ConfigView.section.connection.encryption.encrypt.info.link=\u0417\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0434\u0430 \u0441\u0435 \u043f\u043e\u0441\u0435\u0442\u0438 MainWindow.sr.status.tooltip.ok=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 %1 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e MainWindow.sr.status.tooltip.poor=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 %1 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u044a\u0447\u043d\u043e: <0,9 MainWindow.sr.status.tooltip.bad=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 %1 \u043b\u043e\u0448\u043e: <0,5 ConfigView.section.style.status=\u0417\u043e\u043d\u0430 \u043d\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e: ConfigView.section.style.status.show_sr=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 ConfigView.section.style.status.show_nat=NAT \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 ConfigView.section.style.status.show_ddb=\u0420\u0411\u0414 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 ConfigView.section.style.status.show_ipf=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 IPFilter ConfigView.section.connection.encryption.encrypt.group=\u0422\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0435/\u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 ConfigView.section.connection.encryption.encrypt.fallback_info=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0432\u0441\u044f\u043a\u0430 \u043e\u043f\u0446\u0438\u044f \u0437\u0430 \u043e\u0442\u0441\u0442\u044a\u043f\u043b\u0435\u043d\u0438\u0435 \u0449\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438 \u0432\u0440\u044a\u0437\u043a\u0438 \u0434\u043e \u043d\u0435\u0441\u044a\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0438, \u043d\u043e \u0432\u0440\u044a\u0437\u043a\u0438\u0442\u0435 \u0449\u0435 \u0441\u0430 \u043d\u0435\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438 ConfigView.section.connection.encryption.encrypt.fallback_outgoing=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u0435\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438 \u0438\u0437\u0445\u043e\u0434\u044f\u0449\u0438 \u0432\u0440\u044a\u0437\u043a\u0438, \u0430\u043a\u043e \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438 \u043e\u043f\u0438\u0442 \u0437\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 ConfigView.section.connection.encryption.encrypt.fallback_incoming=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u0435\u0448\u0438\u0444\u0440\u0438\u0440\u0430\u043d\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0438 \u0432\u0440\u044a\u0437\u043a\u0438 ConfigView.section.connection.encryption=\u0422\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0435 upnp.selectedinterfaces=\u0418\u0437\u0431\u0440\u0430\u043d\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0438 (\u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b ';', \u043f\u0440. eth0;eth1) [\u043f\u0440\u0430\u0437\u043d\u043e: \u0432\u0441\u0438\u0447\u043a\u0438] ConfigView.section.style.defaultSortOrder=\u041f\u043e\u0434\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 ConfigView.section.style.defaultSortOrder.desc=\u041d\u0438\u0437\u0445\u043e\u0434\u044f\u0449\u043e ConfigView.section.style.defaultSortOrder.asc=\u0412\u044a\u0437\u0445\u043e\u0434\u044f\u0449\u043e ConfigView.section.style.defaultSortOrder.flip=\u041e\u0431\u0440\u0430\u0442\u043d\u043e \u043d\u0430 \u043f\u0440\u0435\u0434\u0438\u0448\u043d\u0438\u044f \u0440\u0435\u0434 LoggerView.autoscroll=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u0432\u044a\u0440\u0442\u0430\u043d\u0435 Button.selectAll=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u043e Button.markSelected=\u041c\u0430\u0440\u043a\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u0431\u0440\u0430\u043d\u043e\u0442\u043e Button.unmarkSelected=\u0414\u0435\u043c\u0430\u0440\u043a\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u0431\u0440\u0430\u043d\u043e\u0442\u043e plugins.basicview.config=\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f TorrentOptionsView.param.max.uploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0431\u0440\u043e\u0439 \u0433\u043d\u0435\u0437\u0434\u0430 \u0437\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 [\u043c\u0438\u043d\u0438\u043c\u0443\u043c: 2] MyTorrentsView.dialog.setPosition.title=\u041f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 \u043f\u043e\u0437\u0438\u0446\u0438\u044f MyTorrentsView.dialog.setPosition.text=\u0412\u044a\u0432\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0437\u0430 \u043f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 \u0438\u0437\u0431\u0440\u0430\u043d\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438: MyTorrentsView.menu.reposition.manual=\u041f\u0440\u0435\u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u0430\u043d\u0435\u0085\u2026 ConfigView.section.connection.advanced.info.link=\u0417\u0430 \u0434\u0435\u0442\u0430\u0439\u043b\u0438 \u0434\u0430 \u0441\u0435 \u043f\u043e\u0441\u0435\u0442\u0438 ConfigView.section.connection.advanced.socket.group=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u0446\u043e\u043a\u044a\u043b ConfigView.section.connection.advanced.bind_port=\u041f\u0440\u0438\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435 \u043a\u044a\u043c \u043b\u043e\u043a\u0430\u043b\u0435\u043d \u043f\u043e\u0440\u0442 [0: \u0431\u0435\u0437] ConfigView.section.connection.advanced.bind_port.tooltip=\u0412\u0440\u044a\u0437\u043a\u0438\u0442\u0435 \u043d\u0430 \u0438\u0437\u0445\u043e\u0434\u044f\u0449\u0438\u044f \u0446\u043e\u043a\u044a\u043b \u0449\u0435 \u0441\u0430 \u043b\u043e\u043a\u0430\u043b\u043d\u043e \u043f\u0440\u0438\u0432\u044a\u0440\u0437\u0430\u043d\u0438 \u043a\u044a\u043c \u0434\u0430\u0434\u0435\u043d \u043f\u043e\u0440\u0442.\n\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043f\u043e\u043c\u0430\u0433\u0430 \u043f\u0440\u0438 \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u043d\u043e\u0441\u0442 \u043d\u0430 NAT \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440. ConfigView.section.proxy.group.tracker=\u0422\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 \u043a\u043e\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0438 ConfigView.section.proxy.group.peer=\u041a\u043e\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0438 \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 Pieces.column.Requested=\u0417\u0430\u044f\u0432\u0435\u043d\u043e Pieces.column.Requested.info=\u041f\u043e\u043a\u0430\u0437\u0432\u0430 \u043c\u043e\u0436\u0435 \u043b\u0438 \u043f\u043e\u0432\u0435\u0447\u0435 \u0437\u0430\u044f\u0432\u043a\u0438 \u0434\u0430 \u0441\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u044f\u0442 \u0437\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u043e \u0438\u043b\u0438 \u043d\u0435 (*) ConfigView.label.maxuploadsseeding=\u041f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0449\u043e\u0442\u043e \u0441\u0435 \u043f\u0440\u0438 \u0441\u0435\u0435\u043d\u0435 MyTorrentsView.filter=\u0424\u0438\u043b\u0442\u044a\u0440: popup.error.hideall=\u0421\u043a\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u043e ConfigView.section.style.dataStatsOnly=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u0441\u0430\u043c\u043e \u043d\u0430 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0437\u0430 \u0434\u0430\u043d\u043d\u0438 (\u0441\u043a\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u0435\u0437\u0438 \u0437\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) ConfigView.section.style.separateProtDataStats=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0437\u0430 \u0434\u0430\u043d\u043d\u0438 \u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043a\u0430\u0442\u043e '\u0434\u0430\u043d\u043d\u0438 (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b)' MyTorrentsView.dialog.setFilter.title=\u041f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 \u0444\u0438\u043b\u0442\u044a\u0440\u0430 MyTorrentsView.dialog.setFilter.text=\u0421\u0435\u043a\u0446\u0438\u044f %1 \u0449\u0435 \u0431\u044a\u0434\u0435 \u0444\u0438\u043b\u0442\u0440\u0438\u0440\u0430\u043d\u0430 \u0441\u043f\u043e\u0440\u0435\u0434 \u0432\u044a\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442. \u0414\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0441\u0438\u043c\u0432\u043e\u043b | (pipe) \u0437\u0430 \u0444\u0438\u043b\u0442\u0440\u0438\u0440\u0430\u043d\u0435 \u043f\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0444\u0440\u0430\u0437\u0438. MyTorrentsView.filter.tooltip=Ctrl+X \u043f\u0440\u0435\u0432\u043a\u043b\u044e\u0447\u0432\u0430 \u043c\u0435\u0436\u0434\u0443 RegEx \u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u0438 \u043d\u0430\u0447\u0438\u043d\u0438 \u0437\u0430 \u0442\u044a\u0440\u0441\u0435\u043d\u0435.\n\u0414\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0441\u0438\u043c\u0432\u043e\u043b | (pipe) \u0437\u0430 \u0444\u0438\u043b\u0442\u0440\u0438\u0440\u0430\u043d\u0435 \u043f\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0444\u0440\u0430\u0437\u0438. MyTorrentsView.clearFilter.tooltip=\u0411\u0435\u0437 \u0444\u0438\u043b\u0442\u044a\u0440 MyTorrentsView.menu.filter=\u0421\u043f\u0438\u0441\u044a\u043a \u0441 \u0444\u0438\u043b\u0442\u0440\u0438\u0085 ConfigView.section.file.resume.recheck.all=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u0438 \u043d\u0435\u043f\u0440\u0435\u0434\u0432\u0438\u0434\u0435\u043d \u0440\u0435\u0441\u0442\u0430\u0440\u0442 \u043d\u0430 \u0446\u0435\u043b\u0438\u044f \u0444\u0430\u0439\u043b \u0437\u0430 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438 \u043f\u0430\u0440\u0447\u0435\u0442\u0430\n(\u0438\u043d\u0430\u0447\u0435 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u0442 \u0441\u0430\u043c\u043e \u043f\u0430\u0440\u0447\u0435\u0442\u0430\u0442\u0430, \u043a\u043e\u0438\u0442\u043e \u0441\u0430 \u0431\u0438\u043b\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u0438 \u043f\u0440\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441) ConfigureWizard.language.choose=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0435\u0437\u0438\u043a \u043e\u0442 \u0441\u043b\u0435\u0434\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u044a\u043a: popup.closing.in=\u0421\u0430\u043c\u043e\u0437\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446\u0430 \u0441\u043b\u0435\u0434 %1 \u0441\u0435\u043a. popup.more.waiting=\u041e\u0449\u0435 %1 \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u0435(\u044f)\u0085\u2026 # > 2402 popup.next=\u2192 popup.previous=\u2190 (%1) popup.download.finished=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0437\u0430 "%1". popup.file.finished=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0437\u0430 "%1". ConfigView.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e Plugin.localtracker.autoadd.info=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u0441\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043c\u0435\u0441\u0442\u043d\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 (';' \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438 \u0430\u0434\u0440\u0435\u0441\u0438, \u043f\u0440. 1.2.3.4) Plugin.localtracker.autoadd=\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 Plugin.localtracker.networks.info=\u0421\u0447\u0438\u0442\u0430\u043d\u0435 \u043d\u0430 \u0441\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043c\u0440\u0435\u0436\u0438 \u0437\u0430 \u043b\u043e\u043a\u0430\u043b\u043d\u0438 (';' \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438 \u043c\u0440\u0435\u0436\u0438, \u043f\u0440. 145.227.*.*) Plugin.localtracker.networks=\u041b\u043e\u043a\u0430\u043b\u043d\u0438 \u043c\u0440\u0435\u0436\u0438 MainWindow.menu.view.plugins.logViews=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 \u043d\u0430 \u0434\u043d\u0435\u0432\u043d\u0438\u0446\u0438 SpeedView.stats.autospeed=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 SpeedView.stats.autospeed.disabled=\u0422\u0430\u0437\u0438 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0430 \u0435 \u0438\u043b\u0438 \u0441\u043f\u0440\u044f\u043d\u0430 (\u0442\u0440\u044f\u0431\u0432\u0430 \u0420\u0411\u0414), \u0438\u043b\u0438 \u043d\u0435 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 (\u0440\u044a\u0447\u043d\u043e \u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0435\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435) SpeedView.stats.idlePing=\u041d\u0435\u043d\u0430\u0442\u043e\u0432\u0430\u0440\u0435\u043d \u043f\u0438\u043d\u0433: SpeedView.stats.maxPing=\u041c\u0430\u043a\u0441. \u043f\u0438\u043d\u0433: SpeedView.stats.currentPing=\u0422\u0435\u043a\u0443\u0449 \u043f\u0438\u043d\u0433: SpeedView.stats.maxUp=\u041c\u0430\u043a\u0441. \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u0441: ConfigView.pluginlist.unloadSelected=\u0420\u0430\u0437\u0442\u043e\u0432\u0430\u0440\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u0431\u0440\u0430\u043d\u0438\u0442\u0435 ConfigView.pluginlist.scan=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430 \u043d\u043e\u0432\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 ConfigView.section.transfer.autospeed=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 ConfigView.section.transfer.autospeed.tooltip=\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 ConfigView.section.transfer.autospeed.info=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430\u0442\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u043e\u043c\u0435\u043d\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u0437\u0430 \u0438\u0437\u0431\u044f\u0433\u0432\u0430\u043d\u0435 \u043f\u0440\u0435\u043d\u0430\u0442\u043e\u0432\u0430\u0440\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u043c\u0440\u0435\u0436\u043e\u0432\u0430\u0442\u0430 \u0432\u0440\u044a\u0437\u043a\u0430.\n\n\u0422\u0435\u0437\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0449\u0435 \u0431\u044a\u0434\u0430\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438 \u0441\u0430\u043c\u043e \u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u0438 \u0438\u0437\u0438\u0441\u043a\u0432\u0430\u0442 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u0438 \u043d\u0430 \u0420\u0411\u0414.\n ConfigView.section.transfer.autospeed.minupload=%1 \u043c\u0438\u043d. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 ConfigView.section.transfer.autospeed.minupload.tooltip=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e \u043d\u044f\u043c\u0430 \u0434\u0430 \u0441\u0435 \u043d\u0430\u043c\u0430\u043b\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u0434 \u0442\u0430\u0437\u0438 \u0433\u0440\u0430\u043d\u0438\u0446\u0430 ConfigView.section.transfer.autospeed.maxupload=%1 \u043c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.transfer.autospeed.maxupload.tooltip=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e \u043d\u044f\u043c\u0430 \u0434\u0430 \u0441\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043d\u0430\u0434 \u0442\u0430\u0437\u0438 \u0433\u0440\u0430\u043d\u0438\u0446\u0430 ConfigView.section.transfer.autospeed.chokeping=Ping \u0432\u0440\u0435\u043c\u0435 \u043f\u0440\u0438 \u0441\u043f\u043e\u0434\u0430\u0432\u044f\u043d\u0435 [ms] ConfigView.section.transfer.autospeed.chokeping.tooltip=Ping \u0432\u0440\u0435\u043c\u0435\u043d\u0430 \u0432 \u0434\u043e\u0431\u0430\u0432\u043a\u0430 \u043a\u044a\u043c \u0442\u0430\u0437\u0438 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 \u0449\u0435 \u0441\u0435 \u0441\u0447\u0438\u0442\u0430\u0442 \u043a\u0430\u0442\u043e \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430 \u043c\u0440\u0435\u0436\u043e\u0432\u043e \u043d\u0430\u0441\u0438\u0449\u0430\u043d\u0435 ConfigView.section.transfer.autospeed.enableauto=\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u043f\u0440\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0438 \u0441\u0435\u0435\u043d\u0435 ConfigView.section.transfer.autospeed.enableautoseeding=\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u0441\u0430\u043c\u043e \u043f\u0440\u0438 \u0441\u0435\u0435\u043d\u0435 ConfigView.pluginlist.column.unloadable=\u041c\u043e\u0436\u0435 \u0434\u0430 \u043d\u0435 \u0441\u0435 \u0437\u0430\u0440\u0435\u0436\u0434\u0430 ConfigView.section.transfer.lan.enable=\u0421 \u043e\u0442\u0434\u0435\u043b\u043d\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u0437\u0430 \u043b\u043e\u043a\u0430\u043b\u043d\u0438\u0442\u0435 \u043c\u0440\u0435\u0436\u043e\u0432\u0438 \u0432\u0440\u044a\u0437\u043a\u0438 Plugin.localtracker.wellknownlocals=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 loopback/link/site \u043b\u043e\u043a\u0430\u043b\u043d\u0438 \u043c\u0440\u0435\u0436\u0438 (192.168 \u0438 \u0442.\u043d.) TableColumn.header.filesdone=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 TableColumn.header.filesdone.info=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435/\u043e\u0431\u0449\u043e \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0418\u041b\u0418 \u043d\u0435-\u043f\u0440\u043e\u043f\u0443\u0441\u043d\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 (\u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435)/\u043e\u0431\u0449\u043e \u043d\u0435-\u043f\u0440\u043e\u043f\u0443\u0441\u043d\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 (\u043e\u0431\u0449\u043e \u0444\u0430\u0439\u043b\u043e\u0432\u0435) MagnetPlugin.private_torrent=<\u0447\u0430\u0441\u0442\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442> MagnetPlugin.decentral_disabled=<\u0431\u0435\u0437 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u043e \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435> MagnetPlugin.decentral_backup_disabled=<\u0431\u0435\u0437 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d \u0437\u0430\u043f\u0430\u0300\u0441> MagnetPlugin.report.waiting_ddb=\u0438\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u0437\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 \u0420\u0411\u0414\u2026 MagnetPlugin.report.searching=\u0442\u044a\u0440\u0441\u0435\u043d\u0435\u2026 MagnetPlugin.report.found=\u043d\u0430\u043c\u0435\u0442\u0435\u043d %1 MagnetPlugin.report.alive=%1 \u0435 \u0436\u0438\u0432 MagnetPlugin.report.dead=%1 \u0435 \u043c\u044a\u0440\u0442\u044a\u0432 MagnetPlugin.report.tunnel=\u043f\u043e \u0442\u0443\u043d\u0435\u043b \u0434\u043e %1 MagnetPlugin.report.downloading=\u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043e\u0442 %1 MagnetPlugin.report.error=\u0433\u0440\u0435\u0448\u043a\u0430 %1 MagnetURLHandler.report.no_sources=\u043d\u044f\u043c\u0430 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u0438 \u0438\u0437\u0442\u043e\u0447\u043d\u0438\u0446\u0438 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 MagnetURLHandler.report.torrent_size=\u0440\u0430\u0437\u043c\u0435\u0440 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442: %1 MagnetURLHandler.report.percent=\u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e: %1% MagnetURLHandler.report.error=\u0433\u0440\u0435\u0448\u043a\u0430 %1 DHTTransport.report.request_all=\u0438\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 \u0446\u0435\u043b\u0438\u044f \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440 \u043e\u0442 %1 DHTTransport.report.received_bit=\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043e %1 \u0434\u043e %2 \u043e\u0442 %3 DHTTransport.report.complete=\u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e DHTTransport.report.timeout=\u043f\u0440\u043e\u0441\u0440\u043e\u0447\u0432\u0430\u043d\u0435, \u043d\u044f\u043c\u0430 \u043e\u0442\u0433\u043e\u0432\u043e\u0440\u0438 \u043e\u0442 %1 DHTTransport.report.rerequest_all=\u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 \u0446\u0435\u043b\u0438\u044f \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440 \u043e\u0442 %1 DHTTransport.report.rerequest_bit=\u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 %1 \u0434\u043e %2 \u043e\u0442 %3 DHTTransport.report.timeout_some=\u043f\u0440\u043e\u0441\u0440\u043e\u0447\u0432\u0430\u043d\u0435, %1 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438 \u043f\u0430\u043a\u0435\u0442\u0438 \u043e\u0442 %2, \u043d\u043e \u043d\u0435\u043f\u044a\u043b\u043d\u0438 DHTTransport.report.sending=\u0438\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438 DHTTransport.report.resending=\u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438 DHTTransport.report.send_complete=\u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e \u0438\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435 DHTTransport.report.send_timeout=\u043f\u0440\u043e\u0441\u0440\u043e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435\u0442\u043e ConfigView.section.transfer.autospeed.enabledebug=\u0417\u0430\u043f\u0438\u0441 \u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 \u0432 \u0434\u043d\u0435\u0432\u043d\u0438\u043a TableColumn.header.date_added=\u0414\u0430\u0442\u0430 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u044f\u043d\u0435 TableColumn.header.date_added.info=\u0414\u0430\u0442\u0430 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.section.file.hashchecking.smallestfirst=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043d\u0430\u0439-\u043c\u0430\u043b\u043a\u0438\u0442\u0435 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f \u043f\u044a\u0440\u0432\u043e platform.win32.baddll.info=Vuze \u043e\u0442\u043a\u0440\u0438 \u043f\u0440\u0438\u0441\u044a\u0441\u0442\u0432\u0438\u0435\u0442\u043e \u043d\u0430 '%1'. \u0422\u043e\u0432\u0430 \u0435 \u0447\u0430\u0441\u0442 \u043e\u0442 '%2' \u0438 \u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0447\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u044f\u0432\u0430 \u0442\u0440\u0430\u0439\u043d\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 \u043a\u0430\u0442\u043e \u0441\u043f\u0438\u0440\u0430\u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u0430 \u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0438\u043b\u0438 \u0441\u0432\u0440\u044a\u0445\u043d\u0430\u0442\u043e\u0432\u0430\u0440\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u0430. \u0410\u043a\u043e \u0432\u044a\u0437\u043d\u0438\u043a\u043d\u0430\u0442 \u0442\u0430\u043a\u0438\u0432\u0430, \u0434\u0430 \u0441\u0435 \u0434\u0435\u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430 \u0441\u043e\u0444\u0442\u0443\u0435\u0440\u044a\u0442 \u0438\u043b\u0438 \u0434\u0430 \u0441\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430 \u0442\u0430\u043a\u0430, \u0447\u0435 \u0434\u0430 \u043d\u0435 \u0437\u0430\u0441\u044f\u0433\u0430 Vuze. platform.win32.baddll.niphk=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 Norman Anti-Virus platform.win32.baddll.nvappfilter=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 NVidia Firewall platform.win32.baddll.netdog=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 Armor2net Personal Firewall platform.win32.baddll.vlsp=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 Venturi Firewall platform.win32.baddll.imon=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 NOD32 platform.win32.baddll.sarah=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 FRITZ! Application Layer Firewall platform.win32.baddll.MxAVLsp=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 VCom Fix-It Utilities platform.win32.baddll.mclsp=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 McAfee Privacy Service platform.win32.baddll.radhslib=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 Naomi Internet Filter (Radiant) platform.win32.baddll.nl_lsp=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 NetLimiter platform.win32.baddll.winsflt=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 PureSight Internet Content Filter platform.win32.baddll.AxShlex=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 Alcohol 120% platform.win32.baddll.iFW_Xfilter=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 iolo Personal Firewall platform.win32.baddll.gapsp=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 Neoteris platform.win32.baddll.WSOCKHK=\u041f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 Net Nanny upnp.ignorebaddevices=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430, \u043a\u043e\u0438\u0442\u043e \u043d\u0435 \u043e\u0442\u0433\u043e\u0432\u0430\u0440\u044f\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u043d\u043e upnp.ignorebaddevices.info=\u0422\u0435\u043a\u0443\u0449\u043e \u043f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u043d\u0430\u0442\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430: %1 upnp.ignorebaddevices.reset=\u041f\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430 \u0441\u043f\u0438\u0441\u044a\u043a\u0430 \u0441 \u043f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u043d\u0430\u0442\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 upnp.ignorebaddevices.reset.action=\u041f\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 upnp.ignorebaddevices.alert=UPnP \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e, \u043d\u0430\u043c\u0438\u0440\u0430\u0449\u043e \u0441\u0435 \u043d\u0430 %1 \u0435 \u043f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u043d\u0430\u0442\u043e \u043f\u043e\u0440\u0430\u0434\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0438 \u043f\u0440\u043e\u0432\u0430\u043b\u0438. \u0414\u0430 \u0441\u0435 \u0432\u0438\u0434\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0442\u0430 \u043d\u0430 UPnP \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 \u0437\u0430 \u0432\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u043e\u0442\u043d\u0430\u0441\u044f\u0449\u0438 \u0441\u0435 \u0437\u0430 \u0442\u043e\u0432\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435. TorrentOptionsView.param.max.uploads.when.busy=KB/s \u043c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u0438\u0433\u0430\u043d\u0435 \u043d\u0430 \u0433\u043b\u043e\u0431\u0430\u043b\u043d\u043e\u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 [0: \u0438\u0437\u043a\u043b\u044e\u0447\u0435\u043d\u043e] UpdateMonitor.messagebox.verification.failed.title=\u041f\u0440\u043e\u0432\u0430\u043b \u0432 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f\u0442\u0430 UpdateMonitor.messagebox.verification.failed.text=\u0423\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 '%1' \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438: %2 UpdateMonitor.messagebox.accept.unverified.title=\u041f\u0440\u0438\u0435\u043c\u0430\u043d\u0435 \u043d\u0430 \u043d\u0435\u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f UpdateMonitor.messagebox.accept.unverified.text=\u041d\u0435 \u043c\u043e\u0436\u0430 \u0434\u0430 \u0441\u0435 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0438, \u0447\u0435 '%1' \u0435 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 \u0437\u0430 Vuze.\n\u0410\u043a\u043e \u043d\u0430\u0438\u0441\u0442\u0438\u043d\u0430 \u0435 \u0442\u0430\u043a\u0430, \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u0441\u0435 \u041e\u0422\u041a\u0410\u0417.\n\u0414\u0430 \u043f\u0440\u043e\u0434\u044a\u043b\u0436\u0438 \u043b\u0438 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435\u0442\u043e? FileView.BlockView.title=\u0424\u0430\u0439\u043b\u043e\u0432\u0438 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 FileView.BlockView.Done=\u0413\u043e\u0442\u043e\u0432\u0438 FileView.BlockView.Skipped=\u041f\u0440\u043e\u043f\u0443\u0441\u043d\u0430\u0442\u0438 FileView.BlockView.Active=\u0410\u043a\u0442\u0438\u0432\u043d\u0438 FileView.BlockView.Outstanding=\u041e\u0441\u0442\u0430\u043d\u0430\u043b\u0438 ConfigView.label.tcplistenport=\u0412\u0445\u043e\u0434\u044f\u0449 TCP \u043f\u043e\u0440\u0442 \u0437\u0430 \u0441\u043b\u0443\u0448\u0430\u043d\u0435 ConfigView.label.udplistenport=UDP \u043f\u043e\u0440\u0442 \u0437\u0430 \u0441\u043b\u0443\u0448\u0430\u043d\u0435 upnp.portchange.alert=\u0421\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 \u0441\u0430 \u043f\u0440\u043e\u043c\u0435\u043d\u0435\u043d\u0438 \u0437\u0430 \u0438\u0437\u0431\u044f\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 \u0441 UPnP \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e: %1 [\u0441\u0442\u0430\u0440 \u043f\u043e\u0440\u0442=%2] %3 [\u0441\u0442\u0430\u0440 \u043f\u043e\u0440\u0442=%4] ConfigView.section.proxy.username.info=\u0410\u043a\u043e \u0441\u044a\u0440\u0432\u044a\u0440\u044a\u0442-\u043f\u044a\u043b\u043d\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0430\u043c\u043e\u043b\u0438\u0447\u043d\u043e\u0441\u0442, \u0442\u043e \u0434\u043e\u0440\u0438, \u043a\u043e\u0433\u0430\u0442\u043e \u0435 \u0434\u0435\u0444\u0438\u043d\u0438\u0440\u0430\u043d\u043e , \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 "" \u043a\u0430\u0442\u043e \u0438\u043c\u0435 \u043d\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b ConfigView.label.maxuploadswhenbusymin=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u043f\u0440\u0438 \u0437\u0430\u0435\u0442\u043e \u0442\u0430\u0439\u043c\u0435\u0440 [s] MainWindow.menu.help.debug=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 DownloadManager.error.badsize=\u041d\u0435\u0432\u0435\u0440\u0435\u043d \u0440\u0430\u0437\u043c\u0435\u0440 ConfigView.section.NATPMP=NAT-PMP \u0437\u0430 \u041c\u0430\u043a natpmp.info=NAT-PMP \u0435 \u0430\u043b\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430\u0442\u0430 \u043d\u0430 Apple \u0437\u0430 UPnP \u0438 \u0441\u0435 \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430 \u043e\u0442 \u043f\u043e-\u043d\u043e\u0432\u0438\u0442\u0435 Airport \u0441\u0442\u0430\u043d\u0446\u0438\u0438\n\nUPnP \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0431\u044a\u0434\u0435 \u043f\u0443\u0441\u043d\u0430\u0442\u043e, \u0437\u0430 \u0434\u0430 \u0441\u0435 \u043f\u0443\u0441\u043d\u0435 \u0438 NAT-PMP, \u0442\u044a\u0439 \u043a\u0430\u0442\u043e NAT-PMP \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u0442\u043e \u0441\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430 \u043a\u0430\u0442\u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u043d\u043e UPnP \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e natpmp.enable=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 (\u0449\u0435 \u0440\u0430\u0431\u043e\u0442\u0438, \u0430\u043a\u043e \u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043e \u0438 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0442\u0430 \u043d\u0430 Airport \u0441\u0442\u0430\u043d\u0446\u0438\u044f\u0442\u0430) ConfigView.section.tracker.host.addurls=\u0423\u0442\u0432\u044a\u0440\u0436\u0434\u0430\u0432\u0430\u043d\u0435, \u0447\u0435 \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438\u0442\u0435 URL-\u0442\u0430 \u043f\u0440\u0438\u0441\u044a\u0441\u0442\u0432\u0430\u0442 \u0432 \u043f\u043e\u0434\u0441\u043b\u043e\u043d\u0435\u043d\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.filter=\u0432\u044a\u0432\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0442\u0435\u043a\u0441\u0442 \u0437\u0430 \u0444\u0438\u043b\u0442\u044a\u0440 ConfigView.section.files.move=\u0418\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435\u0442\u043e ConfigView.section.file.defaultdir.section=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f\u0442\u0430 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 ConfigView.section.file.defaultdir.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f\u0442\u0430 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 (\u0431\u0435\u0437 \u043f\u043e\u0434\u0441\u0435\u0449\u0430\u043d\u0435) ConfigView.section.file.defaultdir.bestguess=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u0430\u0439-\u0434\u043e\u0431\u0440\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0438\u0437\u0431\u043e\u0440 \u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 ConfigView.section.file.defaultdir.ask=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435: ConfigView.section.file.defaultdir.lastused=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f\u0442\u0430 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 \u0434\u0430 \u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u043e\u0442\u043e \u043c\u044f\u0441\u0442\u043e, \u0432 \u043a\u043e\u0435\u0442\u043e \u0435 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u043e ConfigView.section.file.config.section=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f ConfigView.section.file.config.currentdir=\u0422\u0435\u043a\u0443\u0449\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0441 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f: ConfigView.section.torrent.decoding=\u0414\u0435\u043a\u043e\u0434\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u043d\u0438 \u043d\u0430\u0431\u043e\u0440\u0438 ConfigView.section.logging.udptransport=\u0421 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 UDP \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u0430 Tracker.announce.ignorePeerSeed=\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 \u0431\u0440\u043e\u044f \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438/\u043f\u043e\u0441\u044f\u0432\u043a\u0438. %1 ConfigView.section.connection.encryption.use_crypto_port=\u0414\u0430 \u0441\u0435 \u043f\u043e\u043b\u0437\u0432\u0430 'cryptoport' \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u043e \u0440\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0437\u0430 \u0434\u0430 \u043d\u044f\u043c\u0430 \u043e\u043f\u0438\u0442\u0438 \u0437\u0430 \u043f\u0440\u043e\u0441\u0442\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0438 \u0432\u0440\u044a\u0437\u043a\u0438. \u041d\u044f\u043a\u043e\u0438 \u0442\u0440\u0430\u043a\u0435\u0440\u0438 \u043d\u0435 \u043f\u0440\u0438\u0435\u043c\u0430\u0442 \u0442\u043e\u0432\u0430 \u0438 \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u044f\u0442 \u0441 \u0433\u0440\u0435\u0448\u043a\u0438 \u043a\u0430\u0442\u043e "Invalid Port" \u0438\u043b\u0438 "Illegal Argument" TorrentOptionsView.param.reset.to.default=\u0412\u0440\u044a\u0449\u0430\u043d\u0435 \u043d\u0430 \u0432\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438\u0442\u0435 \u043a\u044a\u043c \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0438\u0442\u0435 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 TorrentOptionsView.param.reset.button=\u041f\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 natpmp.routeraddress=\u0410\u0434\u0440\u0435\u0441 \u043d\u0430 \u0441\u0442\u0430\u043d\u0446\u0438\u044f [\u043f\u0440\u0430\u0437\u043d\u043e: \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e] ConfigView.section.style.disableAlertSliding=\u0411\u0435\u0437 \u043f\u0440\u0438\u043f\u043b\u044a\u0437\u0432\u0430\u0449\u0430 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0438 \u043f\u0440\u0438\u043f\u043e\u043a\u0440\u0438\u0432\u0430\u043d\u0435 \u0437\u0430 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0438\u0442\u0435\u043b\u043d\u0438\u0442\u0435 \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u044f ConfigView.section.transfer.autospeed.maxinc=%1 \u043c\u0430\u043a\u0441. \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430 \u0446\u0438\u043a\u044a\u043b ConfigView.section.transfer.autospeed.maxdec=%1 \u043c\u0430\u043a\u0441. \u043d\u0430\u043c\u0430\u043b\u0435\u043d\u0438\u0435 \u0437\u0430 \u0446\u0438\u043a\u044a\u043b ConfigView.section.transfer.autospeed.enabledownadj=\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043a\u043e\u0440\u0435\u043a\u0446\u0438\u044f \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 ConfigView.section.transfer.autospeed.downadjratio=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435:\u043a\u0430\u0447\u0432\u0430\u043d\u0435\n(\u043f\u0440. 2.0 \u2192 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u0442\u043e \u043f\u0440\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0435 \u0443\u0434\u0432\u043e\u0435\u043d\u043e\u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043a\u0430\u0447\u0432\u0430\u043d\u0435) ConfigView.section.transfer.autospeed.latencyfactor=\u0424\u0430\u043a\u0442\u043e\u0440 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d \u0437\u0430 \u0432\u0440\u044a\u0437\u043a\u0430 \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u043e\u043c\u044f\u043d\u0430\u0442\u0430 \u043d\u0430 \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0442\u0430 \u0438 \u043f\u0440\u043e\u043c\u044f\u043d\u0430\u0442\u0430 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430\n(\u043f\u043e-\u0432\u0438\u0441\u043e\u043a\u0438 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u043c\u0430\u043b\u044f\u0432\u0430\u0442 \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u043d\u043e\u0441\u0442\u0442\u0430) ConfigView.section.transfer.autospeed.reset=\u041f\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430 \u0440\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0438 ConfigView.section.transfer.autospeed.reset.button=\u041f\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 PeerColumn.activationCount=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u043e\u043f\u0438\u0442\u0432\u0430\u0449\u0438 \u0434\u0430 \u0441\u0435 \u0441\u0432\u044a\u0440\u0436\u0430\u0442: %1 TableColumn.header.timesincedownload.info=\u0412\u0440\u0435\u043c\u0435 \u043e\u0442\u043a\u0430\u043a\u0442\u043e \u0434\u0430\u043d\u043d\u0438\u0442\u0435 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0441\u0430 \u0441\u0432\u0430\u043b\u0435\u043d\u0438 TableColumn.header.timesincedownload=\u0412\u0440\u0435\u043c\u0435 \u0441\u043b\u0435\u0434 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 TableColumn.header.timesinceupload.info=\u0412\u0440\u0435\u043c\u0435\u0442\u043e \u043e\u0442\u043a\u0430\u043a\u0442\u043e \u0434\u0430\u043d\u043d\u0438\u0442\u0435 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0441\u0430 \u043a\u0430\u0447\u0435\u043d\u0438 TableColumn.header.timesinceupload=\u0412\u0440\u0435\u043c\u0435 \u0441\u043b\u0435\u0434 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 PeersView.incomingreqcount=\u0412\u0445. \u0437\u0430\u044f\u0432\u043a\u0438 PeersView.incomingreqcount.info=\u0411\u0440\u043e\u0439 \u0432\u0445\u043e\u0434\u044f\u0449\u0438 \u0437\u0430\u044f\u0432\u043a\u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u0435\u043d\u0438 \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f PeersView.outgoingreqcount=\u0418\u0437\u0445. \u0437\u0430\u044f\u0432\u043a\u0438 PeersView.outgoingreqcount.info=\u0411\u0440\u043e\u0439 \u0438\u0437\u0445\u043e\u0434\u044f\u0449\u0438 \u0437\u0430\u044f\u0432\u043a\u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u0435\u043d\u0438 \u043a\u044a\u043c \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f upnp.mapping.trackerclientudp=UDP \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438 \u043f\u043e\u0440\u0442 upnp.mapping.dhtudp=\u0420\u0430\u0437\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u0438 ConfigView.section.connection.nondata.udp.same=\u0415\u0434\u0438\u043d \u0438 \u0441\u044a\u0449 UDP \u043f\u043e\u0440\u0442 \u0437\u0430 \u0420\u0411\u0414 \u0438 UDP \u0442\u0440\u0430\u043a\u0435\u0440 ConfigView.section.connection.tcp.enable=\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 TCP ConfigView.section.connection.udp.enable=\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 UDP ConfigView.section.style.showiconbar=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u043b\u0435\u043d\u0442\u0430 \u0441 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 MainWindow.menu.view.iconbar=\u041b\u0435\u043d\u0442\u0430 \u0441 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 MyTorrentsView.menu.rename=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u0435 MyTorrentsView.menu.rename.displayed=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e\u0442\u043e \u0438\u043c\u0435 MyTorrentsView.menu.rename.save_path=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u044a\u0442\u044f \u0437\u0430 \u0437\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 MyTorrentsView.menu.rename.displayed.enter.title=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e\u0442\u043e \u0438\u043c\u0435 MyTorrentsView.menu.rename.displayed.enter.message=\u0412\u044a\u0432\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u043d\u043e\u0432\u043e \u0438\u043c\u0435 \u0437\u0430 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u0437\u0430 \u0442\u043e\u0432\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435.\n\u041f\u0440\u0438 \u043d\u0435\u0432\u044a\u0432\u0435\u0434\u0435\u043d \u0442\u0435\u043a\u0441\u0442 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u043d\u043e\u0442\u043e \u0438\u043c\u0435. MyTorrentsView.menu.edit_comment=\u0420\u0435\u0434\u0430\u043a\u0446\u0438\u044f \u043d\u0430 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 MyTorrentsView.menu.edit_comment.enter.title=\u0420\u0435\u0434\u0430\u043a\u0446\u0438\u044f \u043d\u0430 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 MyTorrentsView.menu.edit_comment.enter.message=\u0412\u044a\u0432\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0437\u0430 \u0442\u043e\u0432\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435. UIDebugGenerator.messageask.title=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u0434\u043e\u043a\u043b\u0430\u0434 \u0437\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 UIDebugGenerator.messageask.text=\u0414\u0430 \u0441\u0435 \u0432\u044a\u0432\u0435\u0434\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0437\u0430 \u0434\u043e\u043a\u043b\u0430\u0434\u0432\u0430\u043d\u0430\u0442\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442 UIDebugGenerator.complete.title=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0434\u043e\u043a\u043b\u0430\u0434 \u0437\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0438 UIDebugGenerator.complete.text=\u0414\u0430 \u0441\u0435 \u0438\u0437\u043f\u0440\u0430\u0442\u0438 \u0444\u0430\u0439\u043b '%1' \u0434\u043e az-bugreports@Vuze-inc.com\n\n\u0414\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 '\u0414\u0430' \u0437\u0430 \u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 \u043a\u044a\u043c \u0442\u043e\u0437\u0438 \u0444\u0430\u0439\u043b. ConfigView.section.style.showProgramIcon=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043d\u0430 \u0438\u043a\u043e\u043d\u0430 \u0432 \u043a\u043e\u043b\u043e\u043d\u0430\u0442\u0430 \u0437\u0430 \u0438\u043c\u0435 ConfigView.section.style.showProgramIcon.tooltip=\u0418\u0437\u0433\u043b\u0435\u0434\u044a\u0442 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043e\u0442\u043d\u043e\u0432\u043e, \u0437\u0430 \u0434\u0430 \u0432\u043b\u044f\u0437\u0430\u0442 \u0432 \u0441\u0438\u043b\u0430 \u043f\u0440\u043e\u043c\u0435\u043d\u0438\u0442\u0435 swt.alert.cant.update=SWT \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0442\u0430 \u0437\u0430\u0440\u0435\u0434\u0435\u043d\u0430 \u043e\u0442 "%3" \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043e\u0442 \u0432\u0435\u0440\u0441\u0438\u044f %1 \u043a\u044a\u043c %2 (\u0434\u0430 \u0441\u0435 \u0437\u0430\u0440\u0435\u0434\u0438 \u043e\u0442 "%4"). \u0414\u0430 \u0441\u0435 \u043f\u0440\u043e\u0447\u0435\u0442\u0435 \u0443\u0438\u043a\u0438 \u0437\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438. authenticator.savepassword=\u0417\u0430\u043f\u043e\u043c\u043d\u044f\u043d\u0435 \u043d\u0430 \u043f\u0430\u0440\u043e\u043b\u0430\u0442\u0430 ConfigView.section.security.clearpasswords=\u041f\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430 \u0437\u0430\u043f\u043e\u043c\u043d\u0435\u043d\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u0438 ConfigView.section.security.clearpasswords.button=\u041f\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Content.alert.notuploaded.title=\u041d\u0435\u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e \u043a\u0430\u0447\u0432\u0430\u043d\u0435 Content.alert.notuploaded.text=%1 \u043e\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u043e\u0442\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0435 \u0441\u0430 \u043d\u0430\u043f\u044a\u043b\u043d\u043e \u043f\u043e\u0441\u044f\u0442\u0438. \u0410\u043a\u043e \u0441\u0435 %2 \u0441\u0435\u0433\u0430, \u0434\u0440\u0443\u0433\u0438\u0442\u0435 \u043d\u044f\u043c\u0430 \u0434\u0430 \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u0441\u0432\u0430\u043b\u044f\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u0438\u044f \u0442\u0440\u0443\u0434 \u043d\u0430\u043f\u044a\u043b\u043d\u043e. \u0414\u0430 \u0441\u0435 %2 \u043b\u0438? Content.alert.notuploaded.multi.title=\u041d\u0435\u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438 \u043a\u0430\u0447\u0432\u0430\u043d\u0438\u044f Content.alert.notuploaded.multi.text=%1 \u043e\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u043e\u0442\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0435 \u0441\u0430 \u043d\u0430\u043f\u044a\u043b\u043d\u043e \u043f\u043e\u0441\u044f\u0442\u0438. \u0410\u043a\u043e \u0441\u0435 %2 \u0441\u0435\u0433\u0430, \u0434\u0440\u0443\u0433\u0438\u0442\u0435 \u043d\u044f\u043c\u0430 \u0434\u0430 \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u0441\u0432\u0430\u043b\u044f\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u0438\u044f \u0442\u0440\u0443\u0434 \u043d\u0430\u043f\u044a\u043b\u043d\u043e. \u0414\u0430 \u0441\u0435 %2 \u043b\u0438?\n\n\u0421\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435, \u043a\u043e\u0435\u0442\u043e \u043d\u0435 \u0435 \u043d\u0430\u043f\u044a\u043b\u043d\u043e \u043f\u043e\u0441\u044f\u0442\u043e:\n%3 Content.alert.notuploaded.stop=\u043f\u0440\u0435\u043a\u0440\u0430\u0442\u0438 Content.alert.notuploaded.quit=\u0438\u0437\u043b\u0435\u0437\u0435 \u043e\u0442 Vuze TorrentInfoView.torrent.encoding=\u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 TorrentInfoView.columns=\u041a\u043e\u043b\u043e\u043d\u0438 \u043e\u0442 \u0438\u0437\u0433\u043b\u0435\u0434 '\u041c\u0435\u0441\u0442\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438' progress.window.title=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0432 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 progress.window.msg.filemove=\u0414\u0430 \u0441\u0435 \u0438\u0437\u0447\u0430\u043a\u0430 \u0434\u043e \u0437\u0430\u0432\u044a\u0440\u0448\u0432\u0430\u043d\u0435 \u043f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435\u0442\u043e/\u043f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0444\u0430\u0439\u043b\u0430 ConfigView.label.popup.timestamp=\u0421 \u0432\u0440\u0435\u043c\u0435-\u043e\u0442\u043f\u0435\u0447\u0430\u0442\u044a\u043a \u0432\u044a\u0440\u0445\u0443 \u0438\u0437\u0441\u043a\u0430\u0447\u0430\u0449\u0438\u0442\u0435 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f ConfigView.label.popup.autohide=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0441\u043a\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u0441\u043a\u0430\u0447\u0430\u0449\u0438 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f, \u043a\u043e\u0438\u0442\u043e \u043d\u0435 \u0441\u0430 \u0433\u0440\u0435\u0448\u043a\u0438 [s] [0: \u0438\u0437\u043a\u043b\u044e\u0447\u0435\u043d\u043e] ConfigView.label.popup.suppress_alerts=\u041f\u043e\u0442\u0438\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f ConfigView.label.popup.use_message_boxes=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u0441\u043a\u0430\u0447\u0430\u0449\u0438 \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u0434\u0438\u0430\u043b\u043e\u0433 \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438 \u0438\u0437\u0441\u043a\u0430\u0447\u0430\u0449\u0438 \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u044f. ConfigView.label.popup.show=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u0438 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f (\u0430\u043a\u043e \u0438\u043c\u0430) ConfigView.label.popup.show.button=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 ConfigView.label.please.visit.here=\u0414\u0430 \u0441\u0435 \u043f\u043e\u0441\u0435\u0442\u0438 \u0442\u0443\u043a \u0437\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 ConfigView.section.ipfilter.enable.descriptionCache=\u0421\u044a\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043d\u0430 IP \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f\u0442\u0430 \u0432\u044a\u0432 \u0444\u0430\u0439\u043b ConfigView.section.ipfilter.enable.descriptionCache.tooltip=\u0410\u043a\u043e \u043d\u0435 \u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u043e, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f\u0442\u0430 \u043d\u044f\u043c\u0430 \u0434\u0430 \u0441\u0435 \u043f\u043e\u043c\u043d\u044f\u0442 OpenTorrentWindow.filesInfo=\u0429\u0435 \u0441\u0435 \u0441\u0432\u0430\u043b\u0438 %1 \u043e\u0442 %2. OpenTorrentWindow.diskUsage=%1 \u043e\u0442 %2 ConfigView.label.openmytorrents=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 '\u041c\u0435\u0441\u0442\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438' \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 ConfigView.label.open_transfer_bar_on_start=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u0437\u0430 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 ConfigView.section.style.DNDalwaysInIncomplete=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u0432\u0438\u043d\u0430\u0433\u0438 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 '\u041d\u0435 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435' \u0432 \u0441\u0435\u043a\u0446\u0438\u044f \u041d\u0435\u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e \u043d\u0430 '\u041c\u0435\u0441\u0442\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438' OpenTorrentWindow.mb.noGlobalDestDir.title=\u041a\u0440\u0430\u0439\u043d\u0430\u0442\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u043d\u0435 \u0435 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u0430 OpenTorrentWindow.mb.noGlobalDestDir.text=\u041a\u0440\u0430\u0439\u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f '%1' \u043d\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430 \u0438\u043b\u0438 \u0435 \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0430. OpenTorrentWindow.mb.noDestDir.title=\u041a\u0440\u0430\u0439\u043d\u0430\u0442\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u043d\u0435 \u0435 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u0430 OpenTorrentWindow.mb.noDestDir.text=\u041a\u0440\u0430\u0439\u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f '%1' \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 '%2' \u043d\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430 \u0438\u043b\u0438 \u0435 \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0430. OpenTorrentWindow.mb.notValid.title=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 OpenTorrentWindow.mb.notValid.text=\u0422\u043e\u0440\u0435\u043d\u0442 '%1' \u043d\u0435 \u0441\u0435 \u043e\u0442\u0432\u0430\u0440\u044f. \u0410\u043a\u043e \u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435\u0442\u043e \u0435 \u0432 \u0440\u0435\u0436\u0438\u043c \u0441\u0435\u0435\u043d\u0435, \u0434\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u0434\u0430\u043b\u0438 \u0441\u0430 \u043d\u0430\u043b\u0438\u0447\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435 \u0441 \u0434\u0430\u043d\u043d\u0438 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430. OpenTorrentWindow.mb.notTorrent.title=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 OpenTorrentWindow.mb.notTorrent.text='%1' \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u043e\u0442\u0432\u043e\u0440\u0438. \u041d\u0435 \u043f\u0440\u0438\u043b\u0438\u0447\u0430 \u043d\u0430 .torrent \u0444\u0430\u0439\u043b.\n\n\u0427\u0430\u0441\u0442 \u043e\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0442\u0435 \u0434\u0430\u043d\u043d\u0438:\n%2 ConfigView.label.pause.downloads.on.exit=\u041f\u0430\u0443\u0437\u0430 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f\u0442\u0430 \u043f\u0440\u0438 \u0438\u0437\u0445\u043e\u0434 ConfigView.label.resume.downloads.on.start=\u041f\u043e\u0434\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f\u0442\u0430 \u0432 \u043f\u0430\u0443\u0437\u0430 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u0441\u043b\u0435\u0434 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f UIDebugGenerator.message.cancel.title=\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442 \u0435 \u043e\u0442\u043c\u0435\u043c\u0435\u043d\u043e UIDebugGenerator.message.cancel.text=\u041d\u0435 \u0435 \u0432\u044a\u0432\u0435\u0434\u0435\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0437\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442, \u043a\u043e\u044f\u0442\u043e \u0441\u0435 \u0434\u043e\u043a\u043b\u0430\u0434\u0432\u0430. \u0422\u0430\u0437\u0438 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u0430, \u043d\u043e \u0431\u0435\u0437 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435, \u043c\u043e\u0436\u0435 \u0441\u0430\u043c\u043e \u0434\u0430 \u0441\u0435 \u0433\u0430\u0434\u0430\u0435 \u043a\u0430\u043a\u044a\u0432 \u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044a\u0442.\n\n\u0421\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442 \u0435 \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u0430. ConfigView.section.connection.group.http=\u041f\u043e HTTP ConfigView.section.connection.group.http.info=\u041f\u043e\u0434\u0434\u0440\u044a\u0436\u043a\u0430 \u043d\u0430 HTTP \u0441\u0435\u0435\u043d\u0435. ConfigView.section.connection.http.enable=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 ConfigView.section.connection.http.port=\u0412\u0445\u043e\u0434\u044f\u0449 \u043f\u043e\u0440\u0442 ConfigView.section.connection.http.portoverride=\u0422\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 HTTP \u043f\u043e\u0440\u0442 \u0437\u0430 \u043f\u0440\u0435\u0432\u044a\u0437\u043c\u043e\u0433\u0432\u0430\u043d\u0435 [0: \u0431\u0435\u0437] window.update.noupdates.title=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438\u0442\u0435 \u043e\u0442 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 window.update.noupdates.text=\u041d\u044f\u043c\u0430 \u043d\u0430\u043b\u0438\u0447\u043d\u0438 \u043d\u043e\u0432\u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430 \u043c\u0435\u0441\u0442\u043d\u0430\u0442\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f.\n\n\u041f\u043e\u0437\u0434\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f! ConfigView.label.bindip.details=\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: 192.168.1.5;eth0;eth1[2] \u0449\u0435 \u043f\u0440\u0438\u0432\u044a\u0440\u0436\u0435 \u0443\u043a\u0430\u0300\u0437\u0430\u043d\u0438\u044f IP \u043a\u044a\u043c \u0432\u0441\u0438\u0447\u043a\u0438 IP-\u0442\u0430 \u043d\u0430 1-\u0432\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438 3-\u0442\u0438\u044f IP \u043d\u0430 2-\u0440\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.\n1-\u0432\u0438\u044f\u0442 IP \u0449\u0435 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0437\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u0443\u0441\u043b\u0443\u0433\u0438, \u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u043e\u0441\u0442\u0430\u043d\u0430\u043b\u0438 \u0441\u0430\u043c\u043e \u0437\u0430 \u0431\u0430\u043b\u0430\u043d\u0441 \u043d\u0430 \u043d\u0430\u0442\u043e\u0432\u0430\u0440\u0432\u0430\u043d\u0435\u0442\u043e.\n\u0421\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0438 \u0441\u0430 \u043d\u0430\u043b\u0438\u0447\u043d\u0438:\n%1 ConfigView.label.mindownloads=\u041c\u0438\u043d\u0438\u043c\u0443\u043c \u0435\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f UI.cannot_submit_blank_text=\u0422\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0432\u044a\u0432\u0435\u0434\u0435 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442. crypto.alert.as.warning=\u041c\u0440\u0435\u0436\u0430 '%1' \u0435 \u0441 \u043d\u0430\u043b\u043e\u0436\u0435\u043d \u043e\u0444\u043e\u0440\u043c\u0435\u043d \u0442\u0440\u0430\u0444\u0438\u043a \u0437\u0430 \u043d\u0430\u043c\u0430\u043b\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044f\u043d\u0435\u0442\u043e \u043f\u0440\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0435. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0435 - \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u0438\u0437\u043a\u043b\u044e\u0447\u0435\u043d\u043e/\u043f\u0440\u043e\u043c\u0435\u043d\u0435\u043d\u043e \u0447\u0440\u0435\u0437 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0438\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438. ConfigView.section.interface.alerts=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f ConfigView.label.popupdownloadadded=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u0435\u043d\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 popup.download.added="%1" \u0432\u0435\u0447\u0435 \u0435 \u0434\u043e\u0431\u0430\u0432\u0435\u043d \u043a\u044a\u043c \u0441\u043f\u0438\u0441\u044a\u043a\u0430 \u0441\u044a\u0441 \u0441\u0432\u0430\u043b\u0430\u043d\u0438\u044f. MessageBoxWindow.nomoreprompting=\u0411\u0435\u0437 \u0441\u043b\u0435\u0434\u0432\u0430\u0449\u043e \u043d\u0430\u043f\u043e\u043c\u043d\u044f\u043d\u0435 TorrentOptionsView.param.max.seeds=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u0435\u043d \u0431\u0440\u043e\u0439 \u0432\u0440\u044a\u0437\u043a\u0438 \u0437\u0430 \u0441\u0435\u0435\u043d\u0435 [0: \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430 \u0432\u0440\u044a\u0437\u043a\u0430] TorrentOptionsView.param.alternative.value.enable=\u041f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 \u043f\u0440\u0438 \u0441\u0435\u0435\u043d\u0435 ConfigView.section.proxy.check.on.start=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u043f\u044a\u043b\u043d\u043e\u043c\u043e\u0449\u043d\u0438\u043a\u0430 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 TransferStatsView.legend.pingaverage=\u0421\u0440\u0435\u0434\u043d\u043e TransferStatsView.legend.ping1=\u0426\u0435\u043b 1 TransferStatsView.legend.ping2=\u0426\u0435\u043b 2 TransferStatsView.legend.ping3=\u0426\u0435\u043b 3 ConfigView.section.interface.enabletray._mac=\u0412\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u043a\u043e\u043d\u0430 \u043d\u0430 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u043d\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e (\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442) ConfigView.label.closetotray._mac=\u0417\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0430 \u0432 \u0438\u043a\u043e\u043d\u0430 \u043d\u0430 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u043d\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e ConfigView.label.minimizetotray._mac=\u041c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0430 \u0432 \u0438\u043a\u043e\u043d\u0430 \u043d\u0430 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u043d\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e OpenTorrentWindow.mb.existingFiles.title=\u0418\u043c\u0430 \u0432\u0435\u0447\u0435 \u0442\u0430\u043a\u044a\u0432(\u0438\u0432\u0430) \u0444\u0430\u0439\u043b(\u043e\u0432\u0435)! OpenTorrentWindow.mb.existingFiles.text=\u041d\u044f\u043a\u043e\u0438 \u043e\u0442 \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435 \u0432\u0435\u0447\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0442 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u0430\u0442\u0430(\u0438\u0442\u0435) \u043a\u0440\u0430\u0439\u043d\u0430(\u0438) \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f(\u0438)\n\n%1\n\u041f\u0440\u0438 \u043f\u0440\u043e\u0434\u044a\u043b\u0436\u0435\u043d\u0438\u0435, Vuze \u0449\u0435 \u043f\u0440\u043e\u0432\u0435\u0442\u0438 \u0442\u0435\u0437\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0437\u0430 \u043a\u043e\u0440\u0435\u043a\u0442\u043d\u0438 \u0434\u0430\u043d\u043d\u0438 \u0438 \u0449\u0435 \u043f\u0440\u0435\u0437\u0430\u043f\u0438\u0448\u0435 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442. splash.unloadingTorrents=\u041d\u0435\u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 splash.unloadingTorrent=\u041d\u0435\u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.section.file.defaultdir.autorename=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438\u0442\u0435 \u043e\u0442 \u0442\u043e\u0440\u0435\u043d\u0442, \u0430\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435 \u0432 \u043f\u044a\u0442\u044f \u043f\u0440\u0438\u043b\u0438\u0447\u0430\u0442 \u043d\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u0438 ConfigView.section.file.defaultdir.autorename.tooltip=\u0422\u043e\u0432\u0430 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430 \u043f\u0440\u0435\u0437\u0430\u043f\u0438\u0448\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435 \u043d\u0430 \u0434\u0440\u0443\u0433 \u0442\u043e\u0440\u0435\u043d\u0442, \u043a\u043e\u0433\u0430\u0442\u043e \u0438\u043c\u0435\u043d\u0430\u0442\u0430 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435 \u0441\u0430 \u0441\u044a\u0449\u0438\u0442\u0435 alert.raised.at.close=(\u0421\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 \u043f\u0440\u0435\u0434\u0438\u0448\u043d\u043e \u0437\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 Vuze) Plugin.trackerpeerauth.name=\u041e\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0432 \u0442\u0440\u0430\u043a\u0435\u0440 Plugin.trackerpeerauth.info=\u0422\u0430\u0437\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u0438 \u0441 \u0442\u0440\u0430\u043a\u0435\u0440\u0438 \u0437\u0430 \u0443\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435, \u0447\u0435 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u0442\u0435 \u0441\u0430 \u043a\u043e\u0440\u0435\u043a\u0442\u043d\u0438 \u0447\u043b\u0435\u043d\u043e\u0432\u0435 \u043d\u0430 \u044f\u0442\u043e\u0442\u043e Peers.column.maxupspeed=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 Peers.column.maxdownspeed=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 MyTorrents.items.DownSpeedLimit.disabled=\u0411\u0435\u0437 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 Peers.column.lan=\u041b\u043e\u043a\u0430\u043b\u043d\u0430 \u043c\u0440\u0435\u0436\u0430 upnp.selectedaddresses=\u0410\u0434\u0440\u0435\u0441\u0438 (';' \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b, '-' \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043a\u0430=\u043e\u0442\u043a\u0430\u0437, '+' =\u043f\u0440\u0438\u0435\u043c\u0430\u043d\u0435) [\u043f\u0440\u0430\u0437\u043d\u043e: \u0432\u0441\u0438\u0447\u043a\u043e] upnp.alert.multipledevice.warning=\u041c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e UPnP \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0441\u0430 \u043e\u0442\u043a\u0440\u0438\u0442\u0438 - \u0434\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u0434\u0430\u043b\u0438 \u0432\u0441\u0438\u0447\u043a\u0438 \u0438\u0441\u043a\u0430\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 (\u0434\u0430 \u0441\u0435 \u0432\u0438\u0434\u0438 UPnP \u0434\u043d\u0435\u0432\u043d\u0438\u043a \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f) UpdateMonitor.messagebox.restart.title=\u0421\u043e\u0444\u0442\u0443\u0435\u0440\u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f UpdateMonitor.messagebox.restart.text=Vuze \u0442\u043e\u043a\u0443-\u0449\u043e \u0437\u0430\u0432\u044a\u0440\u0448\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e \u043d\u0430 \u0432\u0430\u0436\u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 \u0437\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435\u0442\u043e \u0438\u0300. PiecesView.BlockView.Have=\u0418\u043c\u0430 PiecesView.BlockView.NoHave=\u041d\u044f\u043c\u0430 PiecesView.BlockView.Header=%1 \u043a\u043e\u043b\u043e\u043d\u0430/\u0438, %2 \u0440\u0435\u0434/\u0430, %3 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 ConfigView.section.update.autodownload=\u0421\u0430\u043c\u043e\u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043f\u043e\u0434\u0441\u0435\u0449\u0430\u043d\u0435 \u043f\u0440\u0438 \u0433\u043e\u0442\u043e\u0432\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f Peers.column.peer_id=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d \u0418\u0434. Peers.column.peer_id.info=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d \u0418\u0434. \u0447\u0438\u0442\u0430\u0435\u043c\u043e Peers.column.peer_byte_id=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d \u0418\u0434. Peers.column.peer_byte_id.info=\u0420\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d \u0418\u0434. \u0432 \u0431\u0430\u0439\u0442\u0438 Peers.column.handshake_reserved=\u0417\u0430\u043f\u0430\u0437\u0435\u043d\u0438 \u0431\u0430\u0439\u0442\u043e\u0432\u0435 \u0437\u0430 \u0440\u044a\u043a\u043e\u0441\u0442\u0438\u0441\u043a\u0430\u043d\u0435 Peers.column.handshake_reserved.info=\u041f\u043e\u043a\u0430\u0437\u0432\u0430 \u043a\u0430\u043a\u0432\u0438 \u0437\u0430\u043f\u0430\u0437\u0435\u043d\u0438 \u0431\u0438\u0442\u043e\u0432\u0435 \u0441\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0438 \u0432 \u0440\u044a\u043a\u043e\u0441\u0442\u0438\u0441\u043a\u0430\u043d\u0435\u0442\u043e \u043d\u0430 BitTorrent Peers.column.client_identification=\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 Peers.column.client_identification.info=\u041f\u043e\u043a\u0430\u0437\u0432\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0442\u0435 \u0438\u043c\u0435\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438 \u043e\u0442 Vuze - \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0437\u0430 \u043e\u0442\u0441\u0442\u0440\u0430\u043d\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 dht.warn.user=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 \u0441 NAT/\u043f\u043e\u0440\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0432\u0430\u043d\u0435 ConfigView.label.openbar.incomplete=\u041b\u0435\u043d\u0442\u0438 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435: \u0441\u0430\u043c\u043e\u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f ConfigView.label.openbar.complete=\u0441\u0430\u043c\u043e\u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u043f\u043e\u0441\u044f\u0432\u043a\u0438 ConfigView.label.transferbar.remember_location=\u0417\u0430\u043f\u043e\u043c\u043d\u044f\u043d\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u0437\u0430 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 ConfigView.section.transfer.autospeed.forcemin=\u0421\u043a\u043e\u0440\u043e\u0441\u0442 %1 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u0435 \u043d\u0430\u0441\u0438\u043b\u0435\u043d\u0430 \u043f\u0440\u0438 \u043f\u0440\u0438\u0440\u0430\u0432\u043d\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430\u0442\u0430 MainWindow.menu.tools.speedtest=\u0422\u0435\u0441\u0442 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u2026 speedtest.wizard.title=\u0422\u0435\u0441\u0442 \u0437\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 speedtest.wizard.run=\u0418\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442 \u0437\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 speedtest.wizard.test.mode.updown=\u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0438 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 speedtest.wizard.test.mode.up=\u043a\u0430\u0447\u0432\u0430\u043d\u0435 speedtest.wizard.test.mode.down=\u0441\u0432\u0430\u043b\u044f\u043d\u0435 SpeedTestWizard.test.panel.currinfo=\u0422\u0435\u0441\u0442 \u0437\u0430 \u0448\u0438\u0440\u043e\u0447\u0438\u043d\u0430\u0442\u0430 \u043d\u0430 BitTorrent \u043b\u0435\u043d\u0442\u0430. SpeedTestWizard.test.panel.label=\u0422\u0435\u0441\u0442 \u0437\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 Vuze: SpeedTestWizard.test.panel.already.running=\u0422\u0435\u0441\u0442\u044a\u0442 \u0432\u0435\u0447\u0435 \u0441\u0435 \u0438\u0437\u043f\u044a\u043b\u043d\u044f\u0432\u0430! SpeedTestWizard.test.panel.not.accepted=\u041d\u0435\u043f\u0440\u0438\u0435\u0442\u0430 \u0437\u0430\u044f\u0432\u043a\u0430 \u0437\u0430 \u0442\u0435\u0441\u0442: SpeedTestWizard.test.panel.abort=\u041e\u0442\u043a\u0430\u0437 SpeedTestWizard.test.panel.abort.countdown=\u043e\u0442\u043a\u0430\u0437 \u043e\u0442 \u0442\u0435\u0441\u0442 \u0441\u043b\u0435\u0434: SpeedTestWizard.test.panel.test.countdown=\u043a\u0440\u0430\u0439 \u043d\u0430 \u0442\u0435\u0441\u0442\u0430 \u0441\u043b\u0435\u0434: SpeedTestWizard.test.panel.testfailed=\u041f\u043e\u0440\u043e\u0432\u0430\u043b \u043d\u0430 \u0442\u0435\u0441\u0442\u0430 SpeedTestWizard.test.panel.aborted=\u0420\u044a\u0447\u043d\u043e \u043e\u0442\u043a\u0430\u0437\u0430\u043d \u0442\u0435\u0441\u0442. SpeedTestWizard.test.panel.enc.label=\u0414\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 \u0437\u0430 \u0442\u0435\u0441\u0442 \u0441 \u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430: SpeedTestWizard.test.panel.standard=\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e SpeedTestWizard.test.panel.encrypted=\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043e SpeedTestWizard.set.upload.button.apply=\u041f\u0440\u0438\u043b\u0430\u0433\u0430\u043d\u0435 SpeedTestWizard.set.upload.result=\u0420\u0435\u0437\u0443\u043b\u0442\u0430\u0442 \u043e\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u044f \u0442\u0435\u0441\u0442 SpeedTestWizard.set.upload.bytes.per.sec=B/s SpeedTestWizard.set.upload.bits.per.sec=b/s SpeedTestWizard.finish.panel.title=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d \u0442\u0435\u0441\u0442 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430! SpeedTestWizard.finish.panel.click.close=\u041f\u043e\u043c\u043e\u0449\u043d\u0438\u043a\u044a\u0442 \u0437\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u0435 \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0438. \u0414\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 '\u0417\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435' \u0437\u0430 \u0438\u0437\u0445\u043e\u0434. SpeedTestWizard.finish.panel.max.upload=\u041c\u0430\u043a\u0441. \u043a\u0430\u0447\u0432\u0430\u043d\u0435: SpeedTestWizard.finish.panel.max.seeding.upload=\u041c\u0430\u043a\u0441. \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u043f\u0440\u0438 \u0441\u0435\u0435\u043d\u0435: SpeedTestWizard.finish.panel.max.download=\u041c\u0430\u043a\u0441. \u0441\u0432\u0430\u043b\u044f\u043d\u0435: SpeedTestWizard.finish.panel.enabled=\u0432\u043a\u043b\u044e\u0447\u0435\u043d SpeedTestWizard.finish.panel.disabled=\u0438\u0437\u043a\u043b\u044e\u0447\u0435\u043d SpeedTestWizard.abort.message.scheduled.in=\u041f\u043b\u0430\u043d\u0438\u0440\u0430\u043d \u0442\u0435\u0441\u0442 \u0441\u043b\u0435\u0434\u2026 %1 \u0441\u0435\u043a\u0443\u043d\u0434\u0438" SpeedTestWizard.abort.message.unsupported.type=\u041d\u0435\u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430\u043d \u0442\u0438\u043f \u0442\u0435\u0441\u0442! SpeedTestWizard.abort.message.manual.abort=\u041e\u0442\u0445\u0432\u044a\u0440\u043b\u0435\u043d \u0440\u044a\u0447\u043d\u043e SpeedTestWizard.abort.message.scheduling.failed=\u041f\u043b\u0430\u043d\u0438\u0440\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u0435\u0441\u0442 \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438 SpeedTestWizard.abort.message.download.added=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 %1 \u0434\u043e\u0431\u0430\u0432\u0435\u043d\u043e \u043f\u043e \u0432\u0440\u0435\u043c\u0435 \u043d\u0430 \u0442\u0435\u0441\u0442 SpeedTestWizard.abort.message.entered.error=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 '%1' \u043f\u0440\u0438 \u0442\u0435\u0441\u0442 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 SpeedTestWizard.abort.message.entered.queued=\u0422\u0435\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u0435\u043d\u043e\u0442\u043e \u043f\u0440\u0435\u043c\u0438\u043d\u0430 \u0432 \u0441\u043f\u0440\u044f\u043d\u043e/\u043d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 SpeedTestWizard.abort.message.interrupted=TorrentSpeedTestMonitorThread \u043f\u0440\u0435\u043a\u044a\u0441\u043d\u0430 \u043f\u0440\u0435\u0434\u0438 \u043a\u0440\u0430\u044f \u043d\u0430 \u0442\u0435\u0441\u0442\u0430 SpeedTestWizard.abort.message.execution.failed=\u0418\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u0442\u0435\u0441\u0442\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438 SpeedTestWizard.abort.message.failed.peers=\u041f\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0435 \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435\u0442\u043e \u0441 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 SpeedTestWizard.abort.message.insufficient.slots=\u041d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u043a\u0430\u0447\u0432\u0430 \u0434\u043e \u043d\u0438\u043a\u043e\u0439 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d - \u043d\u0435\u0434\u043e\u0441\u0442\u0438\u0433 \u043d\u0430 \u0433\u043d\u0435\u0437\u0434\u0430 \u0437\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435? SpeedTestWizard.abort.message.not.unchoked=\u041d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0441\u0432\u0430\u043b\u044f \u043e\u0442 \u043d\u0438\u043a\u043e\u0439 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d - \u043d\u0435 \u0441\u0430 \u043f\u0440\u0435\u043c\u0430\u0445\u043d\u0430\u043b\u0438 \u0441\u043f\u043e\u0434\u0430\u0432\u044f\u043d\u0435\u0442\u043e SpeedTestWizard.stage.message.requesting=\u0437\u0430\u044f\u0432\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u0435\u0441\u0442\u2026 SpeedTestWizard.stage.message.preparing=\u043f\u043e\u0434\u0433\u043e\u0442\u0432\u044f\u043d\u0435 \u043d\u0430 \u0442\u0435\u0441\u0442\u2026 SpeedTestWizard.stage.message.starting=\u0437\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u0435\u0441\u0442\u2026 SpeedTestWizard.stage.message.connect.stats=\u0421\u0442\u0430\u0442. \u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0430: \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438=%1, \u0434\u043e\u0431\u0440\u0435 \u0441\u0432.=%2, \u0434\u043e\u0431\u0440\u0435 \u043a\u0447.=%3 window.uiswitcher.title=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0413\u041f\u0418 \u0437\u0430 Vuze window.uiswitcher.text=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043d\u0430\u0439-\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449 \u0413\u041f\u0418. window.uiswitcher.NewUI.text=\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u044f \u043d\u0430\u0439-\u0440\u0430\u0444\u0438\u043d\u0438\u0440\u0430\u043d \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.\n\n\u041f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u0441\u0435 \u0437\u0430 \u043d\u043e\u0432\u0438 \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0449\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438. window.uiswitcher.ClassicUI.title=\u041a\u043b\u0430\u0441\u0438\u0447\u0435\u0441\u043a\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 window.uiswitcher.ClassicUI.text=\u0417\u0430 \u043d\u0435\u0436\u0435\u043b\u0430\u0435\u0449\u0438\u0442\u0435 \u0434\u0430 \u043f\u043e\u043b\u0437\u0432\u0430\u0442 \u043d\u043e\u0432\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, Vuze \u0449\u0435 \u0440\u0430\u0431\u043e\u0442\u0438 \u043f\u043e \u0441\u044a\u0449\u0438\u044f \u043d\u0430\u0447\u0438\u043d, \u043a\u0430\u043a\u0442\u043e \u043f\u0440\u0438 \u0432\u0435\u0440\u0441\u0438\u0438\u0442\u0435 \u043e\u0442 \u0441\u0435\u0440\u0438\u0438 2.\u0445. window.uiswitcher.bottom.text=\u0418\u0437\u0431\u043e\u0440\u044a\u0442 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u0435\u043d \u0447\u0440\u0435\u0437 \u0431\u0443\u0442\u043e\u043d\u0430 "UI" \u0437\u0430 \u0438\u0437\u0431\u043e\u0440 \u043d\u0430 \u0413\u041f\u0418 \u043d\u0430 Vuze iconBar.switch.tooltip=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0413\u041f\u0418 \u0437\u0430 Vuze VivaldiView.notAvailable=\u041d\u044f\u043c\u0430 Vivaldi \u0438\u0437\u0433\u043b\u0435\u0434 restart.error=\u041f\u0440\u043e\u0432\u0430\u043b \u043f\u0440\u0438 \u0440\u0435\u0441\u0442\u0430\u0440\u0442:\n%1\n\u0414\u0430 \u0441\u0435 \u0432\u0438\u0434\u0438 restarting issues. restart.error.oom=\u041d\u0435\u0434\u043e\u0441\u0442\u0438\u0433 \u043d\u0430 \u043f\u0430\u043c\u0435\u0442 restart.error.fnf='%1' \u043d\u0435 \u0435 \u043d\u0430\u043c\u0435\u0440\u0435\u043d \u0432 '%2' restart.error.pnf=\u041d\u0435 \u0435 \u043d\u0430\u043c\u0435\u0440\u0435\u043d \u043f\u044a\u0442 '%1' restart.error.bad=\u041f\u043e\u0432\u0440\u0435\u0434\u0435\u043d \u0444\u043e\u0440\u043c\u0430\u0442 \u0437\u0430 '%1' restart.error.denied=\u0414\u043e\u0441\u0442\u044a\u043f \u043e\u0442\u043a\u0430\u0437\u0430\u043d \u043f\u0440\u0438 \u043e\u043f\u0438\u0442 \u0437\u0430 \u0438\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0430 '%1'. \u0414\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u0434\u0430\u043b\u0438 \u0438\u043c\u0430 \u043f\u0440\u0430\u0432\u0430 \u0437\u0430 \u0438\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430\u0442\u0430. TableColumn.header.date_completed=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e \u043d\u0430 TableColumn.menu.date_added.reset=\u041d\u0430\u0447\u0430\u043b\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434\u0430\u0442\u0430 ConfigView.section.ipfilter.discardbanning=\u0411\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0441 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043e\u0442\u0445\u0432\u044a\u0440\u043b\u0435\u043d\u0438/\u0434\u043e\u0431\u0440\u0438 \u0434\u0430\u043d\u043d\u0438 \u043d\u0430\u0434 [0: \u0438\u0437\u043a\u043b\u044e\u0447\u0435\u043d\u043e] ConfigView.section.ipfilter.discardminkb=\u041c\u0438\u043d\u0438\u043c\u0443\u043c %1 \u043e\u0442\u0445\u0432\u044a\u0440\u043b\u0435\u043d\u043e \u043f\u0440\u0435\u0434\u0438 \u043f\u0440\u0438\u043b\u0430\u0433\u0430\u043d\u0435 ConfigView.interface.start.advanced=\u0421\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u0432 \u0440\u0430\u0437\u0448\u0438\u0440\u0435\u043d \u0438\u0437\u0433\u043b\u0435\u0434 (2.x) MyTorrents.column.ColumnQuality=\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e MyTorrents.column.ColumnSpeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442 MyTorrents.column.ColumnProgressETA.2ndLine=\u041e\u0412\u041f: %1 %2 MyTorrents.column.ColumnProgressETA.StreamReady=\u041f\u043e\u0442\u043e\u043a \u0433\u043e\u0442\u043e\u0432 %1 MyTorrents.column.ColumnProgressETA.PlayableIn=\u0418\u0437\u043f\u044a\u043b\u043d\u0438\u043c\u043e \u0441\u043b\u0435\u0434 %1 %2 TableColumn.header.Quality=\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e TableColumn.header.Speed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442 TableColumn.header.RateIt=\u0413\u043b\u0430\u0441\u0443\u0432\u0430\u043d\u0435 TableColumn.header.Rating=\u041f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442 TableColumn.header.SpeedGraphic=\u0421\u043a\u043e\u0440\u043e\u0441\u0442 TableColumn.header.AzProduct=\u041e\u0442 TableColumn.header.MediaThumb=\u041d\u043e\u0441\u0438\u0442\u0435\u043b TableColumn.header.ProgressETA=\u0420\u0430\u0437\u0432\u0438\u0442\u0438\u0435 #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=\u0422\u0438\u043f \u043d\u0430 \u0444\u0430\u0439\u043b: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=\u041d\u0430\u0447\u0430\u043b\u043e v3.MainWindow.tab.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 \u043d\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 v3.MainWindow.tab.library=\u041c\u0435\u0441\u0442\u043d\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 v3.MainWindow.tab.publish=\u041f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u0435 v3.MainWindow.tab.advanced=\u0420\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438 v3.MainWindow.menu.home=&\u041d\u0430\u0447\u0430\u043b\u043e v3.MainWindow.menu.browse=&\u041f\u0440\u0435\u0433\u043b\u0435\u0434 \u043d\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 v3.MainWindow.menu.library=\u041c\u0435\u0441\u0442\u043d\u0430 \u0411\u0438\u0431&\u043b\u0438\u043e\u0442\u0435\u043a\u0430 v3.MainWindow.menu.publish=&\u041f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u0435 v3.MainWindow.menu.advanced=\u0420&\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438 v3.MainWindow.menu.view.searchbar=\u041b\u0435\u043d\u0442\u0430 \u0437\u0430 \u0442\u044a\u0440\u0441\u0435\u043d\u0435 v3.MainWindow.menu.view.tabbar=\u041b\u0435\u043d\u0442\u0430 \u0437\u0430 \u0440\u0430\u0437\u0434\u0435\u0300\u043b\u0438 v3.MainWindow.currentDL=\u0422\u0435\u043a\u0443\u0449\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 v3.MainWindow.button.stream=\u041f\u043e\u0442\u043e\u043a v3.MainWindow.button.stop=\u0421\u043f\u0438\u0440\u0430\u043d\u0435 v3.MainWindow.button.start=\u0417\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 v3.MainWindow.button.pause=\u041f\u0430\u0443\u0437\u0430 v3.MainWindow.button.resume=\u041f\u043e\u0434\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 v3.MainWindow.button.delete=\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 v3.MainWindow.button.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 v3.MainWindow.button.viewdetails=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 v3.MainWindow.button.play=\u0418\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 v3.MainWindow.button.cancel=\u041e\u0442\u043a\u0430\u0437 v3.MainWindow.button.preview=\u041e\u043d\u0430\u0433\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435 v3.MainWindow.view.wait=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u0437\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u0433\u043b\u0435\u0434. v3.MainWindow.xofx=%1 \u043e\u0442 %2 v3.MainWindow.Loading=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u0437\u0430 \u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435\u2026 v3.filter-bar=\u0424\u0438\u043b\u0442\u044a\u0440 \u043f\u043e \u0437\u0430\u0433\u043b\u0430\u0432\u0438\u0435: v3.MainWindow.search.defaultText=Vuze \u0442\u044a\u0440\u0441\u0435\u043d\u0435 v3.mb.delPublished.title=\u0421\u043f\u0438\u0440\u0430\u043d\u0435 \u0441\u0435\u0435\u043d\u0435\u0442\u043e \u043d\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 v3.mb.delPublished.text=\u0412\u041d\u0418\u041c\u0410\u041d\u0418\u0415: \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435\u0442\u043e \u041d\u0415 \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u043e\u0442\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 '%1' \u043e\u0442 %3 .\n\n\u0414\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 '\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435', \u0437\u0430 \u0434\u0430 \u043e\u0441\u0442\u0430\u043d\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u043e \u0438 \u0441\u0432\u0430\u043b\u044f\u0435\u043c\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435\u0442\u043e, \u043d\u043e \u0434\u0430 \u0441\u0435 \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438 \u0448\u0438\u0440\u043e\u0447\u0438\u043d\u0430 \u043d\u0430 \u043b\u0435\u043d\u0442\u0430\u0442\u0430. \u0414\u0430 \u0441\u0435 \u0438\u0437\u0447\u0430\u043a\u0430 \u043f\u044a\u043b\u043d\u043e \u0437\u0430\u0432\u044a\u0440\u0448\u0432\u0430\u043d\u0435 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435\u0442\u043e \u043f\u0440\u0435\u0434\u0438 \u0442\u043e\u0432\u0430 (how?).\n\n\u0414\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 '\u041e\u0442\u043a\u0430\u0437' \u0437\u0430 \u043f\u044a\u043b\u043d\u043e \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u043e\u0442\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u043e\u0442 www.GetVuze, \u0438 \u0431\u0443\u0442\u043e\u043d 'X' \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0430 \u0437\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b \u041f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u0435.\n\nMore help.\n\n v3.mb.delPublished.delete=&\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 v3.mb.delPublished.cancel=&\u041e\u0442\u043a\u0430\u0437 v3.mb.openFile.title=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b v3.mb.openFile.text.known=\u0421\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435\u0442\u043e \u043d\u0435 \u0441\u0435 \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430 \u0437\u0430\u0441\u0435\u0433\u0430 \u043e\u0442 Vuze \u0438\u0437\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u044f. \u0414\u0430 \u0441\u0435 \u0432\u0438\u0434\u0438 \u0434\u0440\u0443\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u0438\u044f\u041d\u0430\u0440\u044a\u0447\u043d\u0438\u043a \u0437\u0430 \u0438\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430 \u043f\u043e\u043c\u043e\u0449.\n\n\u0422\u0438\u043f\u044a\u0442 \u043d\u0430 \u0444\u0430\u0439\u043b\u0430 \u0441\u0435 \u043e\u043a\u0430\u0437\u0432\u0430: %2 (%3)\n v3.mb.openFile.text.unknown=\u0421\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435\u0442\u043e \u043d\u0435 \u0441\u0435 \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430 \u0437\u0430\u0441\u0435\u0433\u0430 \u043e\u0442 Vuze \u0438\u0437\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u044f. \u0414\u0430 \u0441\u0435 \u0432\u0438\u0434\u0438 \u0434\u0440\u0438\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u0438\u044f \u041d\u0430\u0440\u044a\u0447\u043d\u0438\u043a \u0437\u0430 \u0438\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430 \u043f\u043e\u043c\u043e\u0449.\n\n\u0424\u0430\u0439\u043b\u043e\u0432\u043e \u0440\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u0435: %2 (%3)\n v3.mb.openFile.button.play=\u0418\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 v3.mb.openFile.button.cancel=\u041e\u0442\u043a\u0430\u0437 v3.mb.openFile.button.guide=\u041f\u0440\u043e\u0447\u0438\u0442 \u043d\u0430 \u043d\u0430\u0440\u044a\u0447\u043d\u0438\u043a\u0430 \u0437\u0430 \u0438\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 v3.mb.openFile.remember=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0431\u0435\u0437 \u0437\u0430\u043f\u0438\u0442\u0432\u0430\u043d\u0435 v3.mb.PlayFileNotFound.title=\u041d\u0435\u043d\u0430\u043c\u0435\u0440\u0435\u043d \u0444\u0430\u0439\u043b v3.mb.PlayFileNotFound.text=\u0424\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435 \u0437\u0430 '%1' \u0441\u0430 \u0438\u0437\u0442\u0440\u0438\u0442\u0438 \u0438\u043b\u0438 \u043b\u0438\u043f\u0441\u0432\u0430\u0442. v3.mb.PlayFileNotFound.button.remove=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043e\u0442 Vuze v3.mb.PlayFileNotFound.button.redownload=\u041d\u0430\u043d\u043e\u0432\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438 v3.mb.PlayFileNotFound.button.find=\u0420\u044a\u0447\u043d\u043e \u043d\u0430\u043c\u0438\u0440\u0430\u043d\u0435\u2026 v3.mb.deletePurchased.title=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0440\u044a\u0447\u0430\u043d\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 v3.mb.deletePurchased.text=\u0414\u0430 \u0441\u0435 \u0438\u0437\u0442\u0440\u0438\u0435 \u043b\u0438 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435\u0442\u043e '%1' \u043d\u0430\u0438\u0441\u0442\u0438\u043d\u0430?\n\n\u0422\u043e\u0432\u0430 \u0435 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435, \u043a\u043e\u0435\u0442\u043e \u0435 \u043f\u043e\u0440\u044a\u0447\u0430\u043d\u043e \u0438\u043b\u0438 \u0435 \u0438\u0437\u0438\u0441\u043a\u0430\u043d\u043e \u0432\u043f\u0438\u0441\u0432\u0430\u043d\u0435 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435. v3.mb.deletePurchased.button.delete=&\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 v3.mb.deletePurchased.button.cancel=&\u041e\u0442\u043a\u0430\u0437 v3.topbar.menu.show.logo=Vuze \u043b\u043e\u0433\u043e v3.topbar.menu.show.plugin=\u0417\u043e\u043d\u0430 \u0437\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 v3.topbar.menu.show.search=\u0422\u044a\u0440\u0441\u0435\u043d\u0435 v3.topbar.menu.show.frog=Vuze \u043b\u043e\u0433\u043e splash.initializeCore=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u044f\u0434\u0440\u043e\u0442\u043e splash.initializeUIElements=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u0413\u041f\u0418 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0438 ConfigView.section.transfer.autospeedbeta=\u0410\u0432\u0442\u043e-\u0421\u043a\u043e\u0440\u043e\u0441\u0442-\u0411\u0435\u0442\u0430 # ConfigView.section.ipfilter.peerblocking.group=\u0411\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.section.ipfilter.autoload.group=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 ConfigView.section.ipfilter.autoload.file=IP \u0444\u0438\u043b\u0442\u044a\u0440 \u043e\u0442 \u0444\u0430\u0439\u043b \u0437\u0430 \u0430\u0432\u0442\u043e-\u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 ConfigView.section.ipfilter.autoload.info=\u041f\u043e\u0434\u0434\u044a\u0440\u0436\u0430 DAT (eMule), P2P (PeerGuardian, splist) \u0438 P2B v1,2,3 (PeerGuardian 2) \u0444\u043e\u0440\u043c\u0430\u0442\u0438. \u0424\u0430\u0439\u043b\u044a\u0442 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0435 \u043b\u043e\u043a\u0430\u043b\u0435\u043d \u0438\u043b\u0438 URL, zip-\u043d\u0430\u0442, gzip-\u043d\u0430\u0442 \u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442 \u0442\u0435\u043a\u0441\u0442. URL-\u0442\u0430\u0442\u0430 \u0449\u0435 \u0441\u0435 \u0441\u0432\u0430\u043b\u044f\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043e\u0442\u043d\u043e\u0432\u043e \u0441\u043b\u0435\u0434 7 \u0434\u043d\u0438, \u0434\u043e\u043a\u0430\u0442\u043e \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435 \u0449\u0435 \u0441\u0435 \u043f\u0440\u0435\u0437\u0430\u0440\u0435\u0434\u044f\u0442 \u0437\u0430 \u043c\u0438\u043d\u0443\u0442\u0430 \u0441\u043b\u0435\u0434 \u043f\u043e\u0434\u043c\u044f\u043d\u0430/\u043f\u0438\u043f\u0432\u0430\u043d\u0435. ConfigView.section.ipfilter.autoload.loadnow=\u0417\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u0441\u0435\u0433\u0430 splash.loadIpFilters=\u0417\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 IP \u0444\u0438\u043b\u0442\u0440\u0438\u2026 SpeedTestWizard.set.upload.title=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 SpeedTestWizard.set.download.label=\u041f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0438\u0442\u0435\u043b\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435: SpeedTestWizard.set.upload.label=\u041f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0430\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 - %1 SpeedTestWizard.name.conf.level.absolute=\u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e SpeedTestWizard.name.conf.level.high=\u0412\u0438\u0441\u043e\u043a\u043e SpeedTestWizard.name.conf.level.med=\u0421\u0440\u0435\u0434\u043d\u043e SpeedTestWizard.name.conf.level.low=\u041d\u0438\u0441\u043a\u043e SpeedTestWizard.name.conf.level.none=\u0411\u0435\u0437 ConfigView.section.transfer.select=\u0410\u0432\u0442\u043e-\u0441\u043a\u043e\u0440\u043e\u0441\u0442 ConfigView.section.transfer.select.v2=\u0410\u0432\u0442\u043e-\u0441\u043a\u043e\u0440\u043e\u0441\u0442 (\u0431\u0435\u0442\u0430) mb.azmustclose.title=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 mb.azmustclose.text=Vuze \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0437\u0430\u0442\u0432\u043e\u0440\u0438 \u0437\u0430\u0440\u0430\u0434\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 (\u0440\u0435-)\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430\u0442\u0430, \u043d\u0430\u0439-\u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u043f\u043e\u0440\u0430\u0434\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u043a\u0430\u0442\u043e Administrator.\n\n\u0421\u043b\u0435\u0434 \u0437\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 Vuze, \u0434\u0430 \u0441\u0435 \u043e\u0442\u0432\u043e\u0440\u0438 \u043e\u0442\u043d\u043e\u0432\u043e \u0440\u044a\u0447\u043d\u043e. network.ipv6.prefer.addresses=\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u043d\u0438\u044f \u0437\u0430 IPv6 \u0430\u0434\u0440\u0435\u0441\u0438 \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u043d\u0438 IPv6 \u0438 IPv4 network.bindError=\u041f\u0440\u043e\u0432\u0430\u043b \u0432 \u043f\u0440\u0438\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u0435\u043d \u0446\u043e\u043a\u044a\u043b \u043f\u043e\u0440\u0430\u0434\u0438 \u043d\u0435 \u043d\u0430\u043b\u0438\u0447\u043d\u0438 \u0441\u044a\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u0438 \u0430\u0434\u0440\u0435\u0441\u0438. \u0414\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u043f\u0440\u0438\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435\u0442\u043e \u043a\u044a\u043c IP \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u0442\u0435. network.enforce.ipbinding=\u041d\u0430\u043b\u0430\u0433\u0430\u043d\u0435 \u043d\u0430 IP \u0441\u0432\u044a\u0440\u0437\u0430\u043d\u043e\u0441\u0442\u0438 \u0434\u043e\u0440\u0438 \u0431\u0435\u0437 \u043d\u0430\u043b\u0438\u0447\u043d\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0438 - \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430 \u043d\u0438\u043a\u0430\u043a\u0432\u0438 \u0432\u0440\u044a\u0437\u043a\u0438 \u0430\u043a\u043e \u043d\u0438\u043a\u043e\u0439 \u043e\u0442 \u043f\u043e\u0441\u043e\u0447\u0435\u043d\u0438\u0442\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0438 \u043d\u0435 \u0435 \u043d\u0430\u043b\u0438\u0447\u0435\u043d DHTView.title.full_v6=\u0420\u0430\u0437\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u0411\u0414 IPv6 ConfigView.pluginlist.loadSelected=\u0417\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u0431\u0440\u0430\u043d\u043e\u0442\u043e SpeedView.stats.asn=\u041c\u0440\u0435\u0436\u0430: SpeedView.stats.estupcap=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435: SpeedView.stats.estdowncap=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435: SpeedView.stats.unknown=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e SpeedView.stats.estimate=\u041e\u0447\u0430\u043a\u0432\u0430\u043d\u043e SpeedView.stats.measured=\u0418\u0437\u043c\u0435\u0440\u0435\u043d\u043e SpeedView.stats.measuredmin=\u0418\u0437\u043c\u0435\u0440\u0435\u043d\u043e \u043c\u0438\u043d. SpeedView.stats.manual=\u0417\u0430\u0434\u0430\u0434\u0435\u043d\u043e ConfigView.section.transfer.autospeed.networks=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u043c\u0440\u0435\u0436\u0430 ConfigView.section.transfer.autospeed.resetnetwork=\u041e\u043f\u0440\u0435\u0441\u043d\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u043c\u0440\u0435\u0436\u043e\u0432\u0438\u0442\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 ConfigView.section.transfer.autospeed.network.info=\u0413\u043e\u0440\u043d\u0438\u0442\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0441\u0435 \u043f\u0440\u0435\u0441\u043c\u044f\u0442\u0430\u0442 \u043f\u043e \u0432\u0440\u0435\u043c\u0435 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0438\u043b\u0438 \u0441\u0430 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442 \u043e\u0442 \u0442\u0435\u0441\u0442 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430. \u0417\u0430 \u0443\u043a\u0430\u0437\u0432\u0430\u043d\u0435\u0442\u043e \u0438\u043c \u0440\u044a\u0447\u043d\u043e, \u0434\u0430 \u0441\u0435 \u043f\u043e\u043b\u0437\u0432\u0430\u0442 \u0432\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438\u0442\u0435 \u043f\u043e-\u0434\u043e\u043b\u0443.\n\u0412\u0441\u0438\u0447\u043a\u0438 \u043e\u0431\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f, \u043a\u043e\u0438\u0442\u043e \u043d\u0435 \u0441\u0430 \u0444\u0438\u043a\u0441\u0438\u0440\u0430\u043d\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0449\u0435 \u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u044f\u0442 \u0435\u0434\u043d\u043e \u0441\u043b\u0435\u0434 \u0434\u0440\u0443\u0433\u043e, \u0430\u043a\u043e \u0441\u0435 \u043d\u0430\u043b\u0430\u0433\u0430. \n\u0414\u0430 \u0441\u0435 \u0432\u044a\u0432\u0435\u0434\u0435 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 \u0438 \u0441\u044a\u043e\u0442\u0432\u0435\u0442\u043d\u0438\u044f \u0438\u0300 \u0442\u0438\u043f. \u0421\u043a\u043e\u0440\u043e\u0441\u0442\u0438\u0442\u0435 \u0441\u0430 \u0432 %1. dialog.uiswitcher.restart.title=\u0413\u041f\u0418 \u0441\u043c\u044f\u043d\u0430: Vuze \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 dialog.uiswitcher.restart.text=Vuze \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430, \u0437\u0430 \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u0432\u043a\u043b\u044e\u0447\u0438 \u0413\u041f\u0418. TrayWindow.menu.close=\u0417\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u043a\u043e\u0448\u043d\u0438\u0446\u0430\u0442\u0430 \u0441\u044a\u0441 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f # Used for peers which we can't determine. PeerSocket.unknown=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d PeerSocket.fake_client=\u041f\u043e\u0434\u043f\u0440\u0430\u0432\u0435\u043d PeerSocket.bad_peer_id=\u041b\u043e\u0448 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d PeerSocket.mismatch_id=\u041d\u0435\u0441\u044a\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0430\u0449 PeerSocket.unknown_az_style=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d %1/%2 PeerSocket.unknown_shadow_style=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d %1/%2 OpenTorrentWindow.mb.askCreateDir.title=\u0426\u0435\u043b\u0435\u0432\u0430\u0442\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u043d\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430 OpenTorrentWindow.mb.askCreateDir.text=\u0426\u0435\u043b\u0435\u0432\u0430\u0442\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f '%1' \u043d\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430.\n\n\u0414\u0430 \u0441\u0435 \u0441\u044a\u0437\u0434\u0430\u0434\u0435 \u043b\u0438? SpeedView.stats.estimatechoke=\u041e\u0447\u0430\u043a\u0432\u0430\u043d\u043e (\u043f\u043e\u0442\u0438\u0441\u043a\u0430\u043d\u0435) ConfigTransferAutoSpeed.upload.capacity.usage=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043a\u0430\u043f\u0430\u0446\u0438\u0442\u0435\u0442\u0430 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 ConfigTransferAutoSpeed.mode=\u0420\u0435\u0436\u0438\u043c: ConfigTransferAutoSpeed.capacity.used=% \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d \u043a\u0430\u043f\u0430\u0446\u0438\u0442\u0435\u0442 ConfigTransferAutoSpeed.while.downloading=\u0421\u0432\u0430\u043b\u044f\u043d\u0435: ConfigTransferAutoSpeed.set.dht.ping=DHT \u043f\u0438\u043d\u0433 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430: ConfigTransferAutoSpeed.set.point=\u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b (ms) ConfigTransferAutoSpeed.set.tolerance=\u0442\u043e\u043b\u0435\u0440\u0430\u043d\u0441 (ms) ConfigTransferAutoSpeed.ping.time.good=\u0414\u043e\u0431\u044a\u0440: ConfigTransferAutoSpeed.ping.time.bad=\u041b\u043e\u0448: ConfigTransferAutoSpeed.adjustment.interval=\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043d\u0430 \u043f\u0440\u043e\u043c\u044f\u043d\u0430: ConfigTransferAutoSpeed.skip.after.adjust=\u041f\u0440\u0435\u0441\u043a\u0430\u0447\u0430\u043d\u0435 \u0441\u043b\u0435\u0434 \u043f\u0440\u043e\u043c\u044f\u043d\u0430: GeneralView.label.distributedCopies=\u0420\u0430\u0437\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438 \u043a\u043e\u043f\u0438\u044f: PiecesView.DistributionView.title=\u0420\u0430\u0437\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 PiecesView.DistributionView.NoAvl=\u041f\u0430\u0440\u0447\u0435\u0442\u0430, \u043a\u043e\u0438\u0442\u043e \u0433\u0438 \u043d\u044f\u043c\u0430 PiecesView.DistributionView.SeedAvl=\u041f\u0440\u0438\u043d\u043e\u0441 \u043d\u0430\u043b\u0438\u0447\u0435\u043d \u043e\u0442 \u043f\u043e\u0441\u044f\u0432\u043a\u0438 PiecesView.DistributionView.PeerAvl=\u041f\u0440\u0438\u043d\u043e\u0441 \u043d\u0430\u043b\u0438\u0447\u0435\u043d \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d PiecesView.DistributionView.RarestAvl=\u0420\u044f\u0434\u043a\u043e \u0441\u0440\u0435\u0449\u0430\u043d\u0438 \u043f\u0430\u0440\u0447\u0435\u0442\u0430: %1 (\u043d\u0430\u043b\u0438\u0447\u043d\u0438:%2) PiecesView.DistributionView.weHave=\u0412\u0435\u0447\u0435 \u043d\u0430\u043b\u0438\u0447\u043d\u0438 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 PiecesView.DistributionView.theyHave=\u041f\u0430\u0440\u0447\u0435\u0442\u0430 \u0443 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f PiecesView.DistributionView.weDownload=\u041f\u0430\u0440\u0447\u0435\u0442\u0430, \u043a\u043e\u0438\u0442\u043e \u0441\u0435 \u0441\u0432\u0430\u043b\u044f\u0442 PeersView.gain=\u0414\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0435 PeersView.gain.info=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u0442\u043e \u0441\u0432\u0430\u043b\u0435\u043d\u0438 - \u043a\u0430\u0447\u0435\u043d\u0438 \u0434\u0430\u043d\u043d\u0438 unix.script.new.title=\u0418\u043c\u0430 \u043d\u043e\u0432 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u0449 \u0441\u043a\u0440\u0438\u043f\u0442 \u0437\u0430 Vuze unix.script.new.text=\u0418\u043c\u0430 \u043d\u043e\u0432 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u0449 \u0441\u043a\u0440\u0438\u043f\u0442 \u0437\u0430 Vuze \u0438 \u0435 \u0437\u0430\u043f\u0438\u0441\u0430\u043d \u043a\u0430\u0442\u043e '%1'.\n\n\u0421\u0438\u043b\u043d\u043e \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0438\u0442\u0435\u043b\u043d\u043e \u0435 \u0438\u0437\u043b\u0438\u0437\u0430\u043d\u0435\u0442\u043e \u043e\u0442 Vuze \u0432\u0435\u0434\u043d\u0430\u0433\u0430 \u0438 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u043e\u0437\u0438 \u0441\u043a\u0440\u0438\u043f\u0442 ('%2').\n\n\u0410\u043a\u043e \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0438\u044f\u0442 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u0449 \u0441\u043a\u0440\u0438\u043f\u0442 \u0435 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u043d\u043e \u043f\u0440\u043e\u043c\u0435\u043d\u044f\u043d, \u0434\u0430 \u0441\u0435 \u043f\u043e\u0441\u0435\u0442\u0438 AzureusWiki: Unix Script.\n\n\u0410\u043a\u043e Vuze \u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d \u0447\u0440\u0435\u0437 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0446\u0438\u044f (yum, apt-get \u0438 \u0442.\u043d.), \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u0441\u0435 \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430 \u043e\u0442 \u043f\u0430\u043a\u0435\u0442 Vuze Sourceforge \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 (\u0413\u041f\u0418 \u0449\u0435 \u043e\u0441\u0442\u0430\u043d\u0435 \u0441\u044a\u0449\u0438\u044f\u0442 \u043a\u0430\u0442\u043e \u0441\u0435\u0433\u0430) unix.script.new.button.quit=\u0418\u0437\u043b\u0438\u0437\u0430\u043d\u0435 \u0441\u0435\u0433\u0430 unix.script.new.button.continue=\u041f\u043e-\u043a\u044a\u0441\u043d\u043e unix.script.new.button.asknomore=\u0411\u0435\u0437 \u043f\u043e\u0432\u0442\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u0442\u043e unix.script.new.auto.title=\u041d\u043e\u0432 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u0449 \u0441\u043a\u0440\u0438\u043f\u0442 \u0437\u0430 Vuze unix.script.new.auto.text=\u0418\u043c\u0430 \u043d\u043e\u0432 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u0449 \u0441\u043a\u0440\u0438\u043f\u0442 \u0437\u0430 Vuze.\n\n\u0421\u0438\u043b\u043d\u043e \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0438\u0442\u0435\u043b\u043d\u043e \u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435\u0442\u043e \u043d\u0430 Vuze \u0432\u0435\u0434\u043d\u0430\u0433\u0430. Content.alert.notuploaded.button.stop=&\u0421\u0442\u043e\u043f Content.alert.notuploaded.button.continue=&\u041f\u0440\u043e\u0434\u044a\u043b\u0436\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0435\u0435\u043d\u0435 Content.alert.notuploaded.button.abort=&\u0414\u0430 \u043d\u0435 \u0441\u0435 \u043e\u0442\u043a\u0430\u0437\u0432\u0430 ConfigView.label.checkOnSeeding=\u0421 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 \u043f\u0440\u0438 \u043c\u0430\u043b\u043a\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u0438 \u043f\u0440\u0438 \u0441\u0435\u0435\u043d\u0435 ConfigView.label.ui_switcher=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u0431\u043e\u0440 \u043d\u0430 \u0413\u041f\u0418 \u0437\u0430 Vuze ConfigView.label.ui_switcher_button=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 SpeedTestWizard.test.panel.explain=\u0418\u0437\u043c\u0435\u0440\u0432\u0430\u043d\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438\u0442\u0435 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0438 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u0447\u0440\u0435\u0437 BT \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b. \u0418\u0437\u0431\u0438\u0440\u0430 \u0441\u0435 \u0442\u0438\u043f \u043d\u0430 \u0442\u0435\u0441\u0442 \u0437\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u0438 \u0440\u0435\u0436\u0438\u043c \u043d\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0435, \u0441\u043b\u0435\u0434 \u0442\u043e\u0432\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043a\u0430 \u0431\u0443\u0442\u043e\u043d '\u0418\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435'. \u041f\u0440\u0438 \u0437\u0430\u043f\u043e\u0447\u043d\u0430\u043b \u0442\u0435\u0441\u0442, \u0431\u0443\u0442\u043e\u043d '\u041e\u0442\u043a\u0430\u0437' \u0441\u043f\u0438\u0440\u0430 \u0438\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435\u0442\u043e. \u0422\u0435\u0441\u0442\u044a\u0442 \u0441\u043f\u0438\u0440\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e, \u0430\u043a\u043e \u043e\u0442\u043d\u0435\u043c\u0430 \u043f\u043e\u0432\u0435\u0447\u0435 \u043e\u0442 2 \u043c\u0438\u043d. \u0422\u0438\u043f\u0438\u0447\u0435\u043d \u0442\u0435\u0441\u0442 \u0441\u0432\u044a\u0440\u0448\u0432\u0430 \u0437\u0430 \u043f\u043e-\u043c\u0430\u043b\u043a\u043e \u043e\u0442 \u043c\u0438\u043d\u0443\u0442\u0430. \u0412\u0435\u0434\u043d\u044a\u0436 \u0437\u0430\u0432\u044a\u0440\u0448\u0438\u043b, \u0442\u0435\u0441\u0442\u044a\u0442 \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u043c\u0430\u043a\u0441. \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435. \u041d\u0430\u0442\u0438\u0441\u043a\u0430 \u0441\u0435 '\u041d\u0430\u043f\u0440\u0435\u0434' \u0437\u0430 \u043f\u0440\u0438\u043b\u0430\u0433\u0430\u043d\u0435 \u043d\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u0442\u043e. SpeedTestWizard.set.upload.hint=\u0414\u0430 \u0441\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438 \u043a\u0430\u0447\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 80% \u043e\u0442 \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0430\u0442\u0430 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442. SpeedTestWizard.set.upload.panel.explain=\u0417\u0430 \u043d\u0430\u0439-\u0434\u043e\u0431\u0440\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 Vuze \u0441\u0435 \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u0442\u043e \u0437\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 \u0434\u0430 \u0435 80% \u043e\u0442 \u0434\u043e\u0441\u0442\u0438\u0436\u0438\u043c\u0438\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c.\n\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u0438\u0442\u0435 \u043d\u0430 \u043b\u0438\u043d\u0438\u044f \u0447\u0435\u0441\u0442\u043e \u0441\u0430 \u0438\u0437\u0440\u0430\u0437\u0435\u043d\u0438 \u0432 "\u0431\u0438\u0442\u0430 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430", \u0434\u043e\u043a\u0430\u0442\u043e \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442\u0442\u0430 \u0434\u043e\u043b\u0443 \u0435 \u0432 "\u043a\u0438\u043b\u043e\u0431\u0438\u0442\u0430 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430". SpeedTestWizard.set.limit.conf.level=\u041d\u0438\u0432\u043e \u043d\u0430 \u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u043d\u043e\u0441\u0442 SpeedTestWizard.finish.panel.auto.speed=\u0410\u0432\u0442\u043e-\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u0435: SpeedTestWizard.finish.panel.auto.speed.seeding=\u0410\u0432\u0442\u043e-\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043f\u0440\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0435: ConfigTransferAutoSpeed.add.comment.to.log.group=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0432 \u0434\u043d\u0435\u0432\u043d\u0438\u043a \u0437\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 ConfigTransferAutoSpeed.add.comment.to.log=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440: ConfigTransferAutoSpeed.log.button=\u0414\u043d\u0435\u0432\u043d\u0438\u043a ConfigTransferAutoSpeed.algorithm.selector=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0430\u0432\u0442\u043e-\u0441\u043a\u043e\u0440\u043e\u0441\u0442 ConfigTransferAutoSpeed.algorithm=\u0410\u043b\u0433\u043e\u0440\u0438\u0442\u044a\u043c: ConfigTransferAutoSpeed.auto.speed.classic=\u0410\u0432\u0442\u043e-\u0441\u043a\u043e\u0440\u043e\u0441\u0442 (\u043a\u043b\u0430\u0441\u0438\u043a) ConfigTransferAutoSpeed.auto.speed.beta=\u0410\u0432\u0442\u043e-\u0441\u043a\u043e\u0440\u043e\u0441\u0442 (\u0431\u0435\u0442\u0430) ConfigTransferAutoSpeed.data.update.frequency=\u0427\u0435\u0441\u0442\u043e\u0442\u0430 \u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f Alert.failed.update=\u0418\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f\u0442\u0430 \u043d\u0430 \u043d\u0430\u0439-\u043c\u0430\u043b\u043a\u043e 1 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043d\u0435 \u0443\u0441\u043f\u044f. \u0414\u0430 \u0441\u0435 \u043f\u043e\u0441\u0435\u0442\u0438 AzureusWiki: Failed Update OpenTorrentWindow.mb.existingFiles.partialList=(\u041d\u0435\u043f\u044a\u043b\u0435\u043d \u0441\u043f\u0438\u0441\u044a\u043a. \u041e\u0449\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0432\u0435\u0447\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0442) TableColumn.header.bad_avail_time.info=\u041a\u043e\u0433\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u043e \u0435 \u0431\u0438\u043b\u043e \u043d\u0430\u043b\u0438\u0447\u043d\u043e \u043f\u044a\u043b\u043d\u043e \u043a\u043e\u043f\u0438\u0435 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 TableColumn.header.bad_avail_time=\u0412\u0438\u0434\u044f\u043d\u043e \u043f\u044a\u043b\u043d\u043e \u043a\u043e\u043f\u0438\u0435 MyTorrentsView.menu.exporthttpseeds=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u043d\u0430 HTTP \u043f\u043e\u0441\u044f\u0432\u043a\u043e\u0432\u0438 URL \u0432 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434\u0430 SWT.alert.erroringuithread=\u041d\u0435\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0432\u0430\u0435\u043c\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 \u0432 \u0413\u041f\u0418. \u041c\u043e\u0436\u0435 \u0434\u0430 \u0438\u043c\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u0432\u0430\u0449\u0438 \u043f\u0440\u043e\u0432\u0430\u043b\u0438 - ConfigView.label.minannounce=\u041c\u0438\u043d. \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043c\u0435\u0436\u0434\u0443 \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438\u0442\u0435 \u043e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0438\u044f [s]. ConfigView.label.maxnumwant=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430 \u0431\u0440\u043e\u044f \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438, \u043a\u043e\u0438\u0442\u043e \u0442\u0440\u0430\u043a\u0435\u0440\u044a\u0442 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0432\u044a\u0440\u043d\u0435 ConfigView.label.announceport=\u041f\u0440\u0435\u0432\u044a\u0437\u043c\u043e\u0433\u0432\u0430\u043d\u0435 \u043d\u0430 \u043e\u0431\u044f\u0432\u0435\u043d\u0438\u044f TCP \u043f\u043e\u0440\u0442 \u0437\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0441\u043a\u0438 \u043e\u0431\u044f\u0432\u044f\u0432\u0430\u043d\u0438\u044f, PEX \u0438 DHT\n[\u043f\u0440\u0430\u0437\u043d\u043e: \u0431\u0435\u0437 \u043f\u0440\u0435\u0432\u044a\u0437\u043c\u043e\u0433\u0432\u0430\u043d\u0435, 0: \u0431\u0435\u0437 \u0432\u0445\u043e\u0434\u044f\u0449\u0438 \u0432\u0440\u044a\u0437\u043a\u0438] ConfigView.label.noportannounce=\u0414\u0430 \u043d\u0435 \u0441\u0435 \u043e\u0431\u044f\u0432\u044f\u0432\u0430 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u0430 \u043f\u043e\u0440\u0442\u0430 \u0437\u0430 \u0441\u043b\u0443\u0448\u0430\u043d\u0435 (\u043d\u0435 \u0432\u043b\u0438\u044f\u0435 \u043d\u0430 PEX, DHT) ConfigView.label.maxseedspertorrent=\u041c\u0430\u043a\u0441. \u043f\u043e\u0441\u044f\u0432\u043a\u0438 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] wizard.webseed=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 HTTP \u043f\u043e\u0441\u044f\u0432\u043a\u0438 \u043a\u044a\u043c \u0442\u043e\u0440\u0435\u043d\u0442 wizard.webseed.title=HTTP \u043f\u043e\u0441\u044f\u0432\u043a\u0438 wizard.webseed.configuration=\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043d\u0430 HTTP \u043f\u043e\u0441\u044f\u0432\u043a\u0438 wizard.webseed.adding=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 HTTP \u043f\u043e\u0441\u044f\u0432\u043a\u0438 GeneralView.label.private=\u0427\u0430\u0441\u0442\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442: GeneralView.yes=\u0434\u0430 GeneralView.no=\u043d\u0435 ConfigView.label.userequestlimiting=\u0421 \u0440\u0435\u0433\u0443\u043b\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0437\u0430\u044f\u0432\u043a\u0438\u0442\u0435 \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0442\u043b\u0430\u0433\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u043e\u0447\u0438\u0442\u0438\u0442\u0435 \u0437\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0430\u0432\u0430\u043d\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 (\u043d\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u0438 \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435) ConfigView.label.userequestlimiting.tooltip=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0437\u0430\u044f\u0432\u043a\u0438\u0442\u0435 \u0435 \u043f\u043e-\u0433\u0440\u0443\u0431\u043e \u043e\u0442 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u0438\u0442\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0438, \u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0438\u0437\u0438\u0440\u0430\u043d\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0441\u043f\u0440\u044f\u043c\u043e \u043f\u043e\u0437\u0438\u0446\u0438\u044f\u0442\u0430 \u0432 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430 \u0441\u044a\u0441 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f \u0438 \u043c\u043e\u0436\u0435 \u0434\u0430 \u043f\u043e\u0434\u043e\u0431\u0440\u0438 \u043c\u0440\u0435\u0436\u043e\u0432\u043e\u0442\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044f\u043d\u0435 ConfigView.label.userequestlimitingpriorities=\u0421 \u0444\u043e\u043a\u0443\u0441 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043a\u044a\u043c \u043d\u0430\u0447\u0430\u043b\u043e\u0442\u043e \u043d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430\u0442\u0430 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0438\u044f\u0442\u0430, \u043a\u043e\u0433\u0430\u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u0442\u043e \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0435 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0430\u0442\u043e ConfigView.section.logging.timestamp=\u0424\u043e\u0440\u043c\u0430\u0442 \u043d\u0430 \u0432\u0440\u0435\u043c\u0435\u043e\u0442\u043f\u0435\u0447\u0430\u0442\u044a\u043a\u0430 \u0437\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0434\u043d\u0435\u0432\u043d\u0438\u0446\u0438 Peers.column.timetocomplete=\u041e\u0441\u0442\u0430\u0432\u0430\u0449\u043e \u0432\u0440\u0435\u043c\u0435 Peers.column.timetocomplete.info=\u041e\u0441\u0442\u0430\u0432\u0430\u0449\u043e \u0432\u0440\u0435\u043c\u0435 \u0437\u0430 \u0437\u0430\u0432\u044a\u0440\u0448\u0432\u0430\u043d\u0435 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f ConfigView.section.interface.display.suppress.file.download.dialog=\u041f\u043e\u0442\u0438\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 \u0434\u0438\u0430\u043b\u043e\u0433\u0430 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435\u0442\u043e \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0442\u043e \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0432 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u043d\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u0432 \u0434\u0438\u0430\u043b\u043e\u0433 FileDownload.canceled=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b \u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u043e \u0447\u0440\u0435\u0437 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435: %1 Progress.reporting.status.canceled=\u041e\u0442\u043c\u0435\u043d\u0435\u043d\u043e Progress.reporting.status.finished=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e Progress.reporting.status.retrying=\u041e\u043f\u0438\u0442 \u043e\u0442\u043d\u043e\u0432\u043e\u2026 Progress.reporting.action.label.retry.tooltip=\u041e\u043f\u0438\u0442 \u043e\u0442\u043d\u043e\u0432\u043e \u0437\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0442\u0430 Progress.reporting.action.label.remove.tooltip=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u043e\u0442\u0447\u0435\u0442\u0430 \u0437\u0430 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u043e\u0442 \u0445\u0440\u043e\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u0442\u0430 Progress.reporting.action.label.cancel.tooltip=\u041e\u0442\u043c\u044f\u043d\u0430 \u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0442\u0430 Progress.reporting.action.label.detail=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 Progress.reporting.default.error=\u041f\u0440\u043e\u0432\u0430\u043b\u0435\u043d\u043e Progress.reporting.no.reports.to.display=\u0412 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043d\u044f\u043c\u0430 \u043e\u0442\u0447\u0435\u0442\u0438 \u0437\u0430 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435\u0442\u043e \u0437\u0430 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 Progress.reporting.no.history.to.display=\u041d\u044f\u043c\u0430 \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 Progress.reporting.detail.history.limit=\u041d\u0430\u0434\u0432\u0438\u0448\u0435\u043d \u0435 \u043b\u0438\u043c\u0438\u0442\u044a\u0442 \u0437\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0438 \u0442\u043e\u0437\u0438 \u043e\u0442\u0447\u0435\u0442 \u0437\u0430 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0432\u0430\u0449\u0438\u0442\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043d\u044f\u043c\u0430 \u0434\u0430 \u0441\u0435 \u0434\u043e\u0431\u0430\u0432\u044f\u0442 \u043a\u044a\u043c \u0445\u0440\u043e\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u0442\u0430. Progress.reporting.statusbar.button.tooltip=\u041f\u043e\u043a\u0437\u0430\u0432\u0430\u043d\u0435 \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446\u0430 \u0437\u0430 \u043e\u0442\u0447\u0435\u0442\u0438 \u0437\u0430 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435\u0442\u043e webui.bindip=\u041f\u0440\u0438\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0418\u041f (IP) - \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e \u043d\u0435 \u0441\u0435 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 (*) v3.MainWindow.text.log.in=\u0412\u043f\u0438\u0441\u0432\u0430\u043d\u0435 v3.MainWindow.text.log.out=\u041e\u0442\u043f\u0438\u0441\u0432\u0430\u043d\u0435 v3.MainWindow.text.get.started=\u0417\u0430 \u043d\u0430\u0447\u0430\u043b\u043e v3.MainWindow.text.my.account=\u0421\u043c\u0435\u0442\u043a\u0430 v3.MainWindow.text.my.profile=\u041f\u0440\u043e\u0444\u0438\u043b OpenTorrentWindow.simple.open=\u041c\u044f\u0441\u0442\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 (\u0444\u0430\u0439\u043b, URL, \u0440\u0430\u0437\u0431\u044a\u0440\u043a\u0432\u0430\u043d\u0435) Progress.reporting.window.remove.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0442\u0435 Progress.reporting.window.remove.auto.tooltip=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438, \u043f\u0440\u043e\u0432\u0430\u043b\u0435\u043d\u0438 \u0438\u043b\u0438 \u043e\u0442\u043a\u0430\u0437\u0430\u043d\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0438 \u043e\u0442 \u0438\u0437\u0433\u043b\u0435\u0434\u0430 Progress.reporting.window.remove.now=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0442\u0435 Progress.reporting.window.remove.now.tooltip=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438, \u043f\u0440\u043e\u0432\u0430\u043b\u0435\u043d\u0438 \u0438\u043b\u0438 \u043e\u0442\u043a\u0430\u0437\u0430\u043d\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0438 \u043e\u0442 \u0438\u0437\u0433\u043b\u0435\u0434\u0430 dhttracker.tracklimitedwhenonline=\u0421 \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435 \u0437\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0438\u0433 \u043d\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u0438 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0430 \u043d\u0430 \u043b\u0438\u043d\u0438\u044f \u0437\u0430 \u043a\u0440\u044a\u0441\u0442\u043e\u0441\u0430\u043d\u043e \u043d\u0430\u0441\u0438\u0449\u0430\u043d\u0435 \u043d\u0430 \u0440\u043e\u044f\u043a\u0430 TorrentOptionsView.multi.title.short=\u0412\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 TorrentOptionsView.multi.title.full=\u0412\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 MyTorrentsView.menu.open_parent_folder=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u0449\u0430\u0442\u0430 \u043f\u0430\u043f\u043a\u0430 ConfigView.section.style.use_show_parent_folder=\u0418\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 "%1" \u0432\u043c\u0435\u0441\u0442\u043e "%2" \u0432 \u0442\u043e\u0440\u0435\u043d\u0442 \u043c\u0435\u043d\u044e\u0442\u0430\u0442\u0430 ConfigView.section.style.use_show_parent_folder.tooltip=\u0412\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u0430\u0437\u0438 \u0432\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430 \u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u0449\u0430\u0442\u0430 \u043f\u0430\u043f\u043a\u0430 \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u043d\u043e\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432\u0438\u044f \u043c\u0435\u043d\u0438\u0434\u0436\u044a\u0440.\n\u041c\u043e\u0436\u0435 \u043e\u0431\u0430\u0447\u0435 \u043c\u044f\u0441\u0442\u043e\u0442\u043e \u0437\u0430 \u0437\u0430\u043f\u0438\u0441 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e \u0434\u0430 \u043d\u0435 \u0441\u0435 \u0438\u0437\u0431\u0435\u0440\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e. PeerManager.status.ps_disabled=\u0418\u0437\u043a\u043b\u044e\u0447\u0435\u043d \u0442\u0440\u0430\u043a\u0435\u0440 \u043d\u0430 \u0438\u0437\u0442\u043e\u0447\u043d\u0438\u0446\u0438 \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 ConfigView.section.stats.exportfiles=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u043d\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u0444\u0430\u0439\u043b updater.cant.write.to.app.title=\u041d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0432\u0430 \u0432 \u043f\u0430\u043f\u043a\u0430\u0442\u0430 \u043d\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u0442\u043e updater.cant.write.to.app.details=\u0412 \u043f\u0430\u043f\u043a\u0430 "%1" \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0432\u0430.\n\n\u0422\u043e\u0432\u0430 \u0449\u0435 \u043f\u043e\u043f\u0440\u0435\u0447\u0438 \u0431\u044a\u0434\u0435\u0449\u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0430 \u0431\u044a\u0434\u0430\u0442 \u043f\u0440\u0438\u043b\u0430\u0433\u0430\u043d\u0438.\n\n\u0414\u0430 \u0441\u0435 \u043f\u043e\u0441\u0435\u0442\u0438 \u0443\u0438\u043a\u0438 \u0437\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438. plugin.install.class_version_error=\u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430\u0442\u0430 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0430 \u043f\u043e-\u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430 Java. v3.MainWindow.tab.minilibrary=\u0421\u0432\u0430\u043b\u044f\u043d\u0438\u044f v3.MainWindow.tab.events=\u0410\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442 button.columnsetup.tooltip=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043a\u043e\u043b\u043e\u043d\u0438 v3.activity.remove.title=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 v3.activity.remove.text=\u0414\u0430 \u0441\u0435 \u043f\u0440\u0435\u043c\u0430\u0445\u043d\u0435 \u043b\u0438 \u043d\u0430\u0438\u0441\u0442\u0438\u043d\u0430 \u0441\u044a\u0431\u0438\u0442\u0438\u0435 '%1'? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=\u0417\u0430\u0442\u0432\u0430\u0440\u044f\u043d\u0435 Menu.show.torrent.menu=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u043c\u0435\u043d\u044e '\u0422\u043e\u0440\u0435\u043d\u0442\u0438' Menu.show.torrent.menu.tooltip=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u043c\u0435\u043d\u044e '\u0422\u043e\u0440\u0435\u043d\u0442\u0438' \u0432 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0442\u043e \u043c\u0435\u043d\u044e #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u043c\u0440\u0435\u0436\u0430 plugin.aznetstatus.pingtarget=Ping/trace route \u043d\u0430 \u0446\u0435\u043b ConfigView.section.style.usePathFinder=\u0421 '\u0422\u044a\u0440\u0441\u0430\u0447 \u043d\u0430 \u043f\u044a\u0442' \u0432\u043c\u0435\u0441\u0442\u043e '\u0422\u044a\u0440\u0441\u0430\u0447' menu.sortByColumn=\u041f\u043e\u0434\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043f\u043e %1 MyTorrentsView.menu.manual.per_peer=\u0420\u044a\u0447\u043d\u043e (\u043f\u043e \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d) MyTorrentsView.menu.manual.shared_peers=\u0420\u044a\u0447\u043d\u043e (\u0432\u0441\u0438\u0447\u043a\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438) v3.button.removeActivityEntry=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043d\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 v3.splash.initSkin=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 \u0413\u041f\u0418 \u043c\u0430\u0441\u043a\u0430 v3.splash.hookPluginUI=\u0417\u0430\u043a\u0430\u0447\u0430\u043d\u0435 \u0437\u0430 \u0413\u041f\u0418 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 OpenTorrentWindow.mb.notTorrent.cannot.display=\u0414\u0430\u043d\u043d\u0438\u0442\u0435 \u043d\u0435 \u043c\u043e\u0436\u0430\u0445\u0430 \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044f\u0442 \u043a\u0430\u043a\u0442\u043e \u0442\u0440\u044f\u0431\u0432\u0430 MainWindow.menu.window.zoom.maximize=\u041c\u0430\u043a\u0441\u0438\u043c\u0438\u0437\u0438\u0440\u0430\u043d\u0435 MainWindow.menu.window.zoom.restore=\u0412\u044a\u0437\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 ImageResizer.image.too.small=\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u0442\u043e \u0435 \u0442\u0432\u044a\u0440\u0434\u0435 \u043c\u0430\u043b\u043a\u043e, \u0434\u0430 \u0441\u0435 \u0438\u0437\u0431\u0435\u0440\u0435 \u0434\u0440\u0443\u0433\u043e (\u0434\u0430 \u0431\u044a\u0434\u0435 \u043f\u043e\u043d\u0435 %1 x %2) ImageResizer.title=\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430\u0449 \u043f\u0440\u0435\u0433\u043b\u0435\u0434 \u043d\u0430 \u0443\u043c\u0430\u043b\u0435\u043d\u0438\u044f \u0438\u0437\u0433\u043b\u0435\u0434 \u0432\u044a\u0432 \u0432\u0438\u0434\u0430, \u0432 \u043a\u043e\u0439\u0442\u043e \u0441\u0435 \u043f\u043e\u043a\u0430\u0437\u0432\u0430 \u0432\u044a\u0432 Vuze ImageResizer.move.image=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u0442\u043e \u0441\u0442\u0430\u0432\u0430 \u0441 \u0432\u043b\u0430\u0447\u0435\u043d\u0435 ImageResizer.move.image.with.slider=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u0442\u043e \u0441\u0442\u0430\u0432\u0430 \u0441 \u0432\u043b\u0430\u0447\u0435\u043d\u0435, \u0430 \u043c\u0430\u0449\u0430\u0431\u0438\u0440\u0430\u043d\u0435 \u0441 \u043f\u043b\u044a\u0437\u0433\u0430\u0447\u0430 \u043e\u0442\u0434\u043e\u043b\u0443 security.crypto.title=\u0414\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u043a\u043b\u044e\u0447 \u0437\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0435 security.crypto.encrypt=\u0414\u0430 \u0441\u0435 \u0432\u044a\u0432\u0435\u0434\u0435 \u043f\u0430\u0440\u043e\u043b\u0430 \u0437\u0430 \u0437\u0430\u0449\u0438\u0442\u0430 \u043d\u0430 \u043d\u043e\u0432\u043e\u0441\u044a\u0437\u0434\u0430\u0434\u0435\u043d\u0438\u044f \u043a\u043b\u044e\u0447 \u0437\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0435. \u0414\u0430 \u043d\u0435 \u0441\u0435 \u0437\u0430\u0431\u0440\u0430\u0432\u044f \u043f\u0430\u0440\u043e\u043b\u0430\u0442\u0430, \u0437\u0430\u0449\u043e\u0442\u043e \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0432\u044a\u0437\u0441\u0442\u0430\u043d\u043e\u0432\u0438! security.crypto.decrypt=\u0414\u0430 \u0441\u0435 \u0432\u044a\u0432\u0435\u0434\u0435 \u043f\u0430\u0440\u043e\u043b\u0430 \u0437\u0430 \u0434\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u043a\u043b\u044e\u0447\u0430 \u0437\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0435. security.crypto.reason=\u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u0437\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 security.crypto.password=\u041f\u0430\u0440\u043e\u043b\u0430 security.crypto.password2=\u041f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u0440\u043e\u043b\u0430 security.crypto.persist_for=\u041f\u0440\u043e\u0434\u044a\u043b\u0436\u0438\u0442\u0435\u043b\u043d\u043e\u0441\u0442 \u043d\u0430 \u043f\u0430\u0440\u043e\u043b\u0430\u0442\u0430 security.crypto.persist_for.dont_save=\u0411\u0435\u0437 \u0437\u0430\u043f\u0438\u0441 security.crypto.persist_for.session=\u0422\u0435\u043a\u0443\u0449\u0430 \u0441\u0435\u0441\u0438\u044f security.crypto.persist_for.day=1 \u0434\u0435\u043d security.crypto.persist_for.week=1 \u0441\u0435\u0434\u043c\u0438\u0446\u0430 security.crypto.persist_for.30days=30 \u0434\u043d\u0438 security.crypto.persist_for.forever=\u0417\u0430\u0432\u0438\u043d\u0430\u0433\u0438 security.crypto.password.mismatch.title=\u0413\u0440\u0435\u0448\u043a\u0430 \u0432 \u043f\u0430\u0440\u043e\u043b\u0430\u0442\u0430 security.crypto.password.mismatch=\u0414\u0430 \u0441\u0435 \u0432\u044a\u0432\u0435\u0434\u0435 \u043e\u0442\u043d\u043e\u0432\u043e, \u043f\u0430\u0440\u043e\u043b\u0438\u0442\u0435 \u043d\u0435 \u0441\u044a\u0432\u043f\u0430\u0434\u0430\u0442. ConfigView.section.security.group.crypto=\u041e\u0431\u0449\u0438/\u043b\u0438\u0447\u043d\u0438 \u043a\u043b\u044e\u0447\u043e\u0432\u0435 ConfigView.section.security.resetkey=\u041f\u0440\u0435\u0441\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043a\u043b\u044e\u0447\u043e\u0432\u0435 ConfigView.section.security.resetkey.warning.title=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u0437\u0430 \u0437\u0430\u0433\u0443\u0431\u0430 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438 ConfigView.section.security.resetkey.warning=\u0414\u0430 \u0441\u0435 \u043f\u0440\u0435\u0441\u044a\u0437\u0434\u0430\u0434\u0430\u0442 \u043b\u0438 \u043a\u043b\u044e\u0447\u043e\u0432\u0435\u0442\u0435 \u0437\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0435? \u0426\u044f\u043b\u0430\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0430 \u0441 \u0442\u044f\u0445 \u0449\u0435 \u0431\u044a\u0434\u0435 \u0417\u0410\u0413\u0423\u0411\u0415\u041d\u0410 \u0417\u0410\u0412\u0418\u041d\u0410\u0413\u0418. \u0412\u0441\u0438\u0447\u043a\u0438 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438 \u0438\u043c\u0430\u0449\u0438 \u043e\u0431\u0449\u0438\u044f \u043a\u043b\u044e\u0447 \u043d\u044f\u043c\u0430 \u0434\u0430 \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u043e\u0431\u0449\u0443\u0432\u0430\u0442 \u043d\u0430\u0441\u0430\u043c, \u0430\u043a\u043e \u043d\u0435 \u043f\u0440\u0438\u0434\u043e\u0431\u0438\u044f\u0442 \u043d\u043e\u0432\u0438\u044f \u043a\u043b\u044e\u0447. \u0410\u043a\u043e \u043d\u0435 \u0435 \u044f\u0441\u043d\u043e \u043a\u0430\u043a\u0432\u043e \u0441\u0442\u0430\u0432\u0430, \u0434\u0430 \u043d\u0435 \u0441\u0435 \u0438\u0437\u0432\u044a\u0440\u0448\u0432\u0430 \u0442\u043e\u0432\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435. ConfigView.section.security.unlockkey=\u0418\u0437\u0440\u0438\u0447\u0435\u043d \u0434\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u043a\u043b\u044e\u0447\u043e\u0432\u0435 ConfigView.section.security.unlockkey.button=\u0414\u043e\u0441\u0442\u044a\u043f ConfigView.section.security.publickey=\u041e\u0431\u0449 \u043a\u043b\u044e\u0447 ConfigView.section.security.publickey.undef=\u0411\u0435\u0437 \u0434\u0435\u0444\u0438\u043d\u0438\u0446\u0438\u044f \u0432\u0441\u0435 \u043e\u0449\u0435 ConfigView.section.security.resetkey.error.title=\u041f\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435\u0442\u043e ConfigView.section.security.resetkey.error=\u041f\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0435 \u043f\u0440\u0435\u0441\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u043a\u043b\u044e\u0447\u043e\u0432\u0435\u0442\u0435 ConfigView.section.security.unlockkey.error=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0430 \u043f\u0430\u0440\u043e\u043b\u0430 - \u043f\u0440\u043e\u0432\u0430\u043b\u0435\u043d \u0434\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u043a\u043b\u044e\u0447 ConfigView.copy.to.clipboard.tooltip=\u041a\u043e\u043f\u0438\u0440\u0430\u043d\u0435 \u0432 \u043a\u043b\u0438\u043f-\u0431\u043e\u0440\u0434\u0430 Views.plugins.azbuddy.title=\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0438 Browser.popup.error.no.access=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043e\u043f\u0438\u0442 \u0437\u0430 \u0434\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u043e\u0442\u0434\u0430\u043b\u0435\u0447\u0435\u043d \u0440\u0435\u0441\u0443\u0440\u0441.\n\u0414\u0430 \u0441\u0435 \u043e\u043f\u0438\u0442\u0430 \u043f\u043e-\u043a\u044a\u0441\u043d\u043e.\n ConfigView.label.queue.stoponcebandwidthmet=\u0414\u0430 \u043d\u0435 \u0441\u0435 \u0437\u0430\u043f\u043e\u0447\u0432\u0430\u0442 \u043f\u043e\u0432\u0435\u0447\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0430\u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435/\u0441\u0432\u0430\u043b\u044f\u043d\u0435 ConfigView.section.style.forceMozilla=Vuze \u0434\u0430 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 Mozilla \u0437\u0430 \u0431\u0440\u0430\u0443\u0437\u044a\u0440\u0441\u043a\u0438 \u043f\u0440\u0438\u0441\u043f\u043e\u0441\u043e\u0431\u043b\u0435\u043d\u0438\u044f [\u0438\u0437\u0438\u0441\u043a\u0432\u0430 XULRunner \u0438\u043b\u0438 Firefox 3; \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442] ConfigView.section.style.xulRunnerPath=\u0412\u044a\u0432\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u043f\u044a\u0442 \u0434\u043e XULRunner/Firefox \u0440\u044a\u0447\u043d\u043e [\u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0435 \u0437\u0430 Firefox 3; \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442] azbuddy.name=\u0414\u0440\u0443\u0436\u043a\u0438 azbuddy.enabled=\u0410\u043a\u0442\u0438\u0432\u043d\u0430 azbuddy.disabled=\u041d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430, \u0437\u0430 \u043f\u0440\u043e\u043c\u044f\u043d\u0430 - \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430. azbuddy.nickname=\u041f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c azbuddy.msglog.title=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u0434\u0440\u0443\u0436\u043a\u0430 azbuddy.addtorrent.title=\u041f\u0440\u0438\u0435\u043c\u0430\u043d\u0435 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e? azbuddy.addtorrent.msg=\u0414\u0440\u0443\u0436\u043a\u0430 '%1' \u0438\u0437\u043f\u0440\u0430\u0449\u0430 '%2'.\n\u0414\u0430 \u0441\u0435 \u0434\u043e\u0431\u0430\u0432\u0438 \u043b\u0438 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e? azbuddy.contextmenu=\u0418\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435 \u043a\u044a\u043c \u0434\u0440\u0443\u0436\u043a\u0430 azbuddy.ui.mykey=\u041c\u0435\u0441\u0442\u0435\u043d \u043a\u043b\u044e\u0447: azbuddy.ui.add=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 azbuddy.ui.new_buddy=\u041d\u043e\u0432 \u043a\u043b\u044e\u0447 \u043d\u0430 \u0434\u0440\u0443\u0436\u043a\u0430: azbuddy.ui.table.name=\u0418\u043c\u0435 azbuddy.ui.table.online=\u041d\u0430 \u043b\u0438\u043d\u0438\u044f azbuddy.ui.table.last_msg=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u043e \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u0435 azbuddy.ui.menu.remove=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 azbuddy.ui.menu.copypk=\u041a\u043e\u043f\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043e\u0431\u0449 \u043a\u043b\u044e\u0447 azbuddy.ui.menu.send=\u0421\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u0435 azbuddy.ui.menu.send_msg=\u0422\u0435\u043a\u0441\u0442 \u0437\u0430 \u0438\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435 \u043a\u044a\u043c \u0434\u0440\u0443\u0436\u043a\u0430(\u0438) azbuddy.ui.menu.ping=\u041f\u0438\u043d\u0433 azbuddy.ui.menu.ygm=\u0418\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435 \u043d\u0430 YGM azbuddy.ui.menu.enc=\u0428\u0438\u0444\u0440\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434\u0430 azbuddy.ui.menu.dec=\u0414\u0435\u0448\u0438\u0444\u0440\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043a\u043b\u0438\u043f-\u0431\u043e\u0440\u0434\u0430 azbuddy.ui.menu.sign=\u041f\u043e\u0434\u043f\u0438\u0441\u0432\u0430\u043d\u0435 \u043d\u0430 \u043a\u043b\u0438\u043f-\u0431\u043e\u0440\u0434 azbuddy.ui.menu.verify=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043a\u043b\u0438\u043f-\u0431\u043e\u0440\u0434\u0430 azbuddy.ui.table.lastseen=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u043e \u0432\u0438\u0434\u044f\u043d Button.retry=&\u041e\u0442\u043d\u043e\u0432\u043e Button.ignore=&\u041f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0433\u0432\u0430\u043d\u0435 DHTView.general.skew=\u041d\u0430\u043a\u043b\u043e\u043d: azbuddy.ui.table.msg_in=\u0412\u0445\u043e\u0434\u044f\u0449\u0438 azbuddy.ui.table.msg_out=\u0418\u0437\u0445\u043e\u0434\u044f\u0449\u0438 v3.MainWindow.menu.view.footer=\u041b\u0435\u043d\u0442\u0430 \u0441 \u0434\u0440\u0443\u0436\u043a\u0438 azbuddy.downspeed=KB/s \u043c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0437\u0430 \u0434\u0440\u0443\u0436\u043a\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] security.crypto.badpw=\u0412\u044a\u0432\u0435\u0434\u0435\u043d\u0430\u0442\u0430 \u043f\u0430\u0440\u043e\u043b\u0430 \u0435 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u043d\u0430 ConfigView.section.security.backupkeys=\u0417\u0430\u043f\u0430\u0300\u0441 \u043d\u0430 \u043a\u043b\u044e\u0447\u043e\u0432\u0435 \u0432\u044a\u0432 \u0444\u0430\u0439\u043b ConfigView.section.security.backupkeys.button=\u0417\u0430\u043f\u0430\u0300\u0441 ConfigView.section.security.restorekeys=\u0412\u044a\u0437\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u043a\u043b\u044e\u0447\u043e\u0432\u0435 \u043e\u0442 \u0444\u0430\u0439\u043b ConfigView.section.security.restorekeys.button=\u0412\u044a\u0437\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 ConfigView.section.security.op.error.title=\u041f\u0440\u043e\u0432\u0430\u043b \u0432 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f ConfigView.section.security.op.error=\u041f\u0440\u043e\u0432\u0430\u043b \u0432 \u0437\u0430\u0432\u044a\u0440\u0448\u0432\u0430\u043d\u0435 \u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f:\n %1 ConfigView.section.security.restart.title=\u0418\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442 ConfigView.section.security.restart.msg=Vuze \u0449\u0435 \u0441\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 \u0437\u0430 \u0437\u0430\u0432\u044a\u0440\u0448\u0432\u0430\u043d\u0435 \u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0442\u0430. ConfigView.section.security.system.managed=\u041f\u0440\u0435\u0434\u043f\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u043a\u043b\u044e\u0447\u043e\u0432\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0432\u0430\u043d\u043e \u043e\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0442\u0430 azbuddy.ui.table.msg_queued=\u041d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430 azbuddy.ui.menu.chat=\u041b\u0430\u0444\u0447\u0435 azbuddy.chat.title=Vuze \u043b\u0430\u0444\u0447\u0435 azbuddy.chat.says=%1 \u043a\u0430\u0437\u0432\u0430: Button.bar.show=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 Button.bar.hide=\u0421\u043a\u0440\u0438\u0432\u0430\u043d\u0435 Button.bar.share=\u0421\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 Button.bar.add=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 Button.bar.edit=\u0420\u0435\u0434\u0430\u043a\u0446\u0438\u044f Button.bar.edit.cancel=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u043d\u043e v3.MainWindow.menu.view.pluginbar=\u041b\u0435\u043d\u0442\u0430 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 MainWindow.dialog.select.vuze.file=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 Vuze \u0444\u0430\u0439\u043b MainWindow.menu.file.open.vuze=Vuze \u0444\u0430\u0439\u043b\u2026 metasearch.addtemplate.title=\u0418\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0448\u0430\u0431\u043b\u043e\u043d \u0437\u0430 \u0442\u044a\u0440\u0441\u0435\u043d\u0435? metasearch.addtemplate.desc=\u041d\u0430\u0438\u0441\u0442\u0438\u043d\u0430 \u043b\u0438 \u0434\u0430 \u0441\u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430 \u0448\u0430\u0431\u043b\u043e\u043d \u0437\u0430 \u0442\u044a\u0440\u0441\u0435\u043d\u0435 \u0441 \u0438\u043c\u0435 '%1'? v3.share.private.title=\u0421\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 v3.share.private.text=\u0418\u0437\u0431\u0440\u0430\u043d\u0438\u044f\u0442 \u0442\u043e\u0440\u0435\u043d\u0442 \u0435 \u043c\u0430\u0440\u043a\u0438\u0440\u0430\u043d \u043a\u0430\u0442\u043e \u0447\u0430\u0441\u0442\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442.\n\n\u041d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0441\u043f\u043e\u0434\u0435\u043b\u044f\u0442 \u0447\u0430\u0441\u0442\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438. metasearch.addtemplate.dup.title=\u0414\u0443\u0431\u043b\u0438\u0440\u0430\u043d \u0448\u0430\u0431\u043b\u043e\u043d metasearch.addtemplate.dup.desc=\u0428\u0430\u0431\u043b\u043e\u043d \u0437\u0430 \u0442\u044a\u0440\u0441\u0435\u043d\u0435 %1 \u0432\u0435\u0447\u0435 \u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d metasearch.export.select.template.file=\u0417\u0430\u043f\u0438\u0441 \u043d\u0430 \u0448\u0430\u0431\u043b\u043e\u043d metasearch.import.select.template.file=\u041e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0448\u0430\u0431\u043b\u043e\u043d dialog.uiswitch.title=\u041f\u0440\u0435\u0432\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435 \u043a\u044a\u043c Vuze \u0413\u041f\u0418 dialog.uiswitch.text=\u0422\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0435 \u0430\u043a\u0442\u0438\u0432\u0435\u043d Vuze \u0413\u041f\u0418 \u0437\u0430 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u0430\u0437\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f.\n\nVuze \u0449\u0435 \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430. dialog.uiswitch.button=\u041f\u0440\u0435\u0432\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435 \u043a\u044a\u043c Vuze \u0413\u041f\u0418 azbuddy.tracker.enabled=\u0421 '\u041b\u0430\u043d\u0441\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0434\u0440\u0443\u0436\u043a\u0430' \u0441\u0435 \u0434\u0430\u0432\u0430 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e \u0441 \u0434\u0440\u0443\u0436\u043a\u0438 azbuddy.protocolspeed=KB/s \u043c\u0430\u043a\u0441. \u0431\u0430\u043b\u0430\u0441\u0442 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0437\u0430 \u0434\u0440\u0443\u0436\u043a\u0430 v3.MainWindow.button.download=\u0421\u0432\u0430\u043b\u044f\u043d\u0435 v3.MainWindow.button.run=\u0421\u0442\u0430\u0440\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b v3.activity.header.downloads=\u0421\u0432\u0430\u043b\u044f\u043d\u0438\u044f v3.activity.header.vuze.news=Vuze \u043d\u043e\u0432\u0438\u043d\u0438 message.taking.too.long=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0442\u0430 \u0441\u0435 \u0431\u0430\u0432\u0438 \u043f\u043e\u0432\u0435\u0447\u0435 \u043e\u0442 \u043e\u0447\u0430\u043a\u0432\u0430\u043d\u043e\u0442\u043e\n\u041f\u0440\u0438 \u0436\u0435\u043b\u0430\u0436\u0438\u0435 \u0434\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 'ESC' \u0437\u0430 \u043f\u0440\u0435\u043a\u0440\u0430\u0442\u044f\u0432\u0430\u043d\u0435 message.status.success=\u0423\u0441\u043f\u0435\u0448\u043d\u043e azbuddy.tracker.bbb.status.title=\u041b\u0430\u043d\u0441\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0434\u0440\u0443\u0436\u043a\u0430 azbuddy.tracker.bbb.status.title.tooltip=\u0418\u0437\u0431\u043e\u0440 \u0437\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 azbuddy.tracker.bbb.status.idle=\u0411\u0435\u0437 \u043b\u0430\u043d\u0441\u0438\u0440\u0430\u043d\u0435 azbuddy.tracker.bbb.status.nli=\u0418\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0435 \u0432\u043f\u0438\u0441\u0432\u0430\u043d\u0435 azbuddy.tracker.bbb.status.in=\u041c\u0435\u0441\u0442\u043d\u043e \u043b\u0430\u043d\u0441\u0438\u0440\u0430\u043d\u0435 azbuddy.tracker.bbb.status.out=\u041b\u0430\u043d\u0441\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0434\u0440\u0443\u0436\u043a\u0438 v3.MainWindow.search.go.tooltip=\u0418\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0430 \u0442\u044a\u0440\u0441\u0435\u043d\u0435\u0442\u043e v3.MainWindow.search.last.tooltip=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u043e \u0442\u044a\u0440\u0441\u0435\u043d\u0435 metasearch.addtemplate.done.title=\u0414\u043e\u0431\u0430\u0432\u0435\u043d \u0448\u0430\u0431\u043b\u043e\u043d metasearch.addtemplate.done.desc=\u0428\u0430\u0431\u043b\u043e\u043d '%1' \u0435 \u0434\u043e\u0431\u0430\u0432\u0435\u043d \u0443\u0441\u043f\u0435\u0448\u043d\u043e.\n\u0429\u0435 \u0431\u044a\u0434\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d \u043f\u0440\u0438 \u0441\u043b\u0435\u0434\u0432\u0430\u0449\u043e \u0442\u044a\u0440\u0441\u0435\u043d\u0435. ConfigView.section.security.nopw=\u041d\u0435 \u0435 \u043f\u043e\u0434\u0430\u0434\u0435\u043d\u0430 \u043f\u0430\u0440\u043e\u043b\u0430 ConfigView.section.security.nopw_v=\u041d\u044f\u043c\u0430 \u043f\u0430\u0440\u043e\u043b\u0430, \u0442\u0440\u044f\u0431\u0432\u0430 \u0432\u043f\u0438\u0441\u0432\u0430\u043d\u0435 \u0432\u044a\u0432 Vuze fileplugininstall.install.title=\u0418\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430? fileplugininstall.install.desc=\u041d\u0430\u0438\u0441\u0442\u0438\u043d\u0430 \u043b\u0438 \u0434\u0430 \u0441\u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 '%1', \u0432\u0435\u0440\u0441\u0438\u044f %2? fileplugininstall.duplicate.title=\u0414\u0443\u0431\u043b\u0438\u0440\u0430\u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 fileplugininstall.duplicate.desc=\u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 '%1', \u0432\u0435\u0440\u0441\u0438\u044f %2 \u0432\u0435\u0447\u0435 \u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0430 azbuddy.online_status=\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u0441\u0432\u044a\u0440\u0437\u0430\u043d\u043e\u0441\u0442 azbuddy.os_online=\u041d\u0430 \u043b\u0438\u043d\u0438\u044f azbuddy.os_away=\u041e\u0442\u0441\u044a\u0441\u0442\u0432\u0430\u0449 azbuddy.os_not_avail=\u041d\u0435\u0434\u043e\u0441\u0442\u044a\u043f\u0435\u043d azbuddy.os_busy=\u0417\u0430\u0435\u0442 azbuddy.os_offline=\u041d\u0435 \u043d\u0430 \u043b\u0438\u043d\u0438\u044f azbuddy.ui.menu.disconnect=\u041f\u0440\u0435\u043a\u044a\u0441\u0432\u0430\u043d\u0435 azbuddy.enable_chat_notif=\u0421 \u0438\u0437\u0432\u0435\u0441\u0442\u044f\u0432\u0430\u043d\u0438\u044f \u0432 \u043b\u0430\u0444\u0447\u0435\u0442\u043e progress.window.msg.progress=\u0414\u0430 \u0441\u0435 \u0438\u0437\u0447\u0430\u043a\u0430 \u0437\u0430\u0432\u044a\u0440\u0448\u0432\u0430\u043d\u0435 \u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0442\u0430 ConfigView.section.connection.advanced.read_select=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0437\u0430\u043a\u044a\u0441\u043d\u0435\u043d\u0438\u0435 \u0437\u0430 \u0447\u0435\u0442\u0435\u043d\u0435 (m, \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 %1) ConfigView.section.connection.advanced.read_select_min=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043c\u0438\u043d. \u0447\u0430\u043a\u0430\u043d\u0435 \u0437\u0430 \u0447\u0435\u0442\u0435\u043d\u0435 (m, \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 %1) ConfigView.section.connection.advanced.write_select=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u0437\u0430\u043a\u044a\u0441\u043d\u0435\u043d\u0438\u0435 \u0437\u0430 \u0437\u0430\u043f\u0438\u0441 (m, \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 %1) ConfigView.section.connection.advanced.write_select_min=\u0418\u0437\u0431\u043e\u0440 \u043d\u0430 \u043c\u0438\u043d. \u0447\u0430\u043a\u0430\u043d\u0435 \u0437\u0430 \u0437\u0430\u043f\u0438\u0441 (m, \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 %1) DetailedListView.title=\u041f\u043e\u0434\u0440\u043e\u0431\u0435\u043d \u0441\u043f\u0438\u0441\u044a\u043a ConfigView.section.connection.network.max.outstanding.connect.attempts=\u041c\u0430\u043a\u0441. \u043e\u0441\u0442\u0430\u043d\u0430\u043b\u0438 \u0438\u0437\u0445\u043e\u0434\u044f\u0449\u0438 \u0432\u0440\u044a\u0437\u043a\u0438 plugins.init.force_enabled=Vuze \u043e\u0442\u043a\u0440\u0438, \u0447\u0435 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430\u0442\u0430 "%1" \u0435 \u0441\u043f\u0440\u044f\u043d\u0430, \u043d\u043e \u0437\u0430 \u0434\u0430 \u0440\u0430\u0431\u043e\u0442\u0438 Vuze \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e, \u0442\u044f \u0435 \u043f\u0443\u0441\u043d\u0430\u0442\u0430 \u043e\u0442\u043d\u043e\u0432\u043e. ConfigView.section.connection.prefer.udp=\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u043d\u0435 \u043d\u0430 UDP \u0432\u0440\u044a\u0437\u043a\u0438 subscript.add.title=\u0418\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442? subscript.add.desc=\u0414\u0430 \u0441\u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430 \u043b\u0438 \u043d\u0430\u0438\u0441\u0442\u0438\u043d\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 '%1'? subscript.add.dup.title=\u041f\u043e\u0432\u0442\u043e\u0440\u0435\u043d \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 subscript.add.dup.desc=\u0410\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 '%1' \u0435 \u0432\u0435\u0447\u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d. subscript.add.upgrade.title=\u041d\u0430\u0434\u0433\u0440\u0430\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442? subscript.add.upgrade.desc=\u0414\u0430 \u0441\u0435 \u043d\u0430\u0434\u0433\u0440\u0430\u0434\u0438 \u043b\u0438 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 '%1'? subscript.add.upgradeto.desc=\u0412\u0435\u0440\u0441\u0438\u044f %1 \u043d\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 '%2' \u0435 \u043d\u0430\u043b\u0438\u0447\u043d\u0430.\n\u0414\u0430 \u0441\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430 \u043b\u0438? azsubs.contextmenu.addassoc=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u0430\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u044f \u0437\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 azsubs.contextmenu.lookupassoc=\u0422\u044a\u0440\u0441\u0435\u043d\u0435 \u043d\u0430 \u0430\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u044f \u0437\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 iconBar.start=\u0421\u0442\u0430\u0440\u0442 iconBar.stop=\u0421\u0442\u043e\u043f iconBar.remove=\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 iconBar.up=\u041d\u0430\u0433\u043e\u0440\u0435 iconBar.down=\u041d\u0430\u0434\u043e\u043b\u0443 iconBar.run=\u041f\u0443\u0441\u043a\u0430\u043d\u0435 iconBar.editcolumns=\u0420\u0435\u0434\u0430\u043a\u0446\u0438\u044f \u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u0438 iconBar.top=\u041d\u0430\u0439-\u043e\u0442\u0433\u043e\u0440\u0435 iconBar.bottom=\u041d\u0430\u0439-\u043e\u0442\u0434\u043e\u043b\u0443 iconBar.queue=\u0421\u0442\u0430\u0440\u0442 iconBar.open=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 iconBar.share=\u0421\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 iconBar.share.tooltip=\u0421\u043f\u043e\u0434\u0435\u043b\u044f\u043d\u0435 \u043d\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 iconBar.details=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 iconBar.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 iconBar.play=\u0418\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 iconBar.queue.tooltip=\u041d\u0430 \u043e\u043f\u0430\u0448\u043a\u0430 v3.MainWindow.menu.view.sidebar=\u0421\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u0430 \u043b\u0435\u043d\u0442\u0430 v3.MainWindow.menu.view.actionbar=\u041b\u0435\u043d\u0442\u0430 \u043d\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u0442\u0430 v3.MainWindow.menu.view.toolbars=\u041b\u0435\u043d\u0442\u0438 \u0441 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 ump.install=\u0411\u044a\u0440\u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f:\n\u0421 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u043c\u0430\u043b\u043a\u0430 \u0434\u043e\u0431\u0430\u0432\u043a\u0430 \u0437\u0430 \u0438\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 \u0449\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0433\u043b\u0435\u0434\u0430 \u0442\u043e\u0432\u0430 \u0432\u0438\u0434\u0435\u043e. subscriptions.listwindow.title=\u0422\u044a\u0440\u0441\u0430\u0447 \u043d\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 subscriptions.listwindow.autochecktext=Vuze \u043c\u043e\u0436\u0435 \u0434\u0430 \u043d\u0430\u043c\u0438\u0440\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 \u0441\u0432\u044a\u0440\u0437\u0430\u043d\u0438 \u0441\u044a\u0441 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u0432 \u043c\u0435\u0441\u0442\u043d\u0430\u0442\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430. \u0414\u0430 \u0441\u0435 \u0432\u043a\u043b\u044e\u0447\u0438 \u043b\u0438 \u0442\u043e\u0432\u0430? subscriptions.listwindow.loadingtext=\u0422\u044a\u0440\u0441\u0435\u043d\u0435 \u043d\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 \u0441\u0432\u044a\u0440\u0437\u0430\u043d\u0438 \u0441 %1 subscriptions.listwindow.failed=\u041d\u0435 \u0441\u0430 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u0438 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 subscriptions.listwindow.popularity=\u041f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442 subscriptions.listwindow.popularity.unknown=\u041d\u0435\u043f\u043e\u0437\u043d\u0430\u0442\u043e subscriptions.listwindow.name=\u0418\u043c\u0435 subscriptions.listwindow.subscribe=\u0410\u0431\u043e\u043d\u0438\u0440\u0430\u043d\u0435 TableColumn.header.azsubs.ui.column.subs=\u0410\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 subscriptions.listwindow.popularity.reading=\u0427\u0435\u0442\u0435\u043d\u0435\u2026 PluginDeprecation.log.start=\u0422\u0443\u043a \u0438\u043c\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0449\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043d\u043e\u0441\u0442, \u043a\u043e\u044f\u0442\u043e \u0449\u0435 \u043e\u0442\u043f\u0430\u0434\u043d\u0435 \u043f\u0440\u0438 \u0441\u043b\u0435\u0434\u0432\u0430\u0449\u0438 \u0432\u0435\u0440\u0441\u0438\u0438 \u043d\u0430 Vuze.\n\u041d\u0435 \u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0434\u0435\u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438, \u0430 \u0442\u044f\u0445\u043d\u0430\u0442\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f.\n\u0410\u043a\u043e \u043e\u0431\u0430\u0447\u0435 \u0432\u0435\u0447\u0435 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0430\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f, \u0434\u0430 \u0441\u0435 \u043a\u043e\u043f\u0438\u0440\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u0442\u043e\u0437\u0438 \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 \u0438 \u0434\u0430 \u0441\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430 \u0432\u044a\u0432 \u0444\u043e\u0440\u0443\u043c\u0430: \n \t%1\n\n PluginDeprecation.view=\u041d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 PluginDeprecation.alert=\u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 \u0441\u0435 \u0435 \u043e\u043f\u0438\u0442\u0430\u043b\u0430 \u0434\u0430 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043d\u043e\u0441\u0442, \u043a\u043e\u044f\u0442\u043e \u0449\u0435 \u043e\u0442\u043f\u0430\u0434\u043d\u0435 \u043f\u0440\u0438 \u0441\u043b\u0435\u0434\u0432\u0430\u0449\u0438 \u0432\u0435\u0440\u0441\u0438\u0438. \u0414\u0430 \u0441\u0435 \u043e\u0442\u0432\u043e\u0440\u0438 \u0438\u0437\u0433\u043b\u0435\u0434\u0430 \u0441 \u0434\u043d\u0435\u0432\u043d\u0438\u043a\u0430 \u043d\u0430 \u043d\u0435\u0438\u0437\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0437\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f. TableColumn.header.Thumbnail=\u0418\u043a\u043e\u043d\u0430 TableColumn.header.Thumbnail.info=\u041d\u0430\u043c\u0430\u043b\u0435\u043d \u0438\u0437\u0433\u043b\u0435\u0434 \u043d\u0430 Vuze \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435. \u0417\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u0434\u0440\u0443\u0433\u0438 \u043d\u0430\u043c\u0430\u043b\u0435\u043d\u0438\u0442\u0435 \u0438\u0437\u0433\u043b\u0435\u0434\u0438 \u0441\u0435 \u0434\u0430\u0432\u0430\u0442 \u043e\u0442 \u041e\u0421-\u0430. v3.MainWindow.menu.getting_started=&\u0417\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430 MainWindow.menu.community=&\u0414\u0440\u0443\u0436\u0435\u0441\u0442\u0432\u043e MainWindow.menu.help.faq=&\u0427\u0417\u0412 MainWindow.menu.community.wiki=\u0414\u0440\u0443\u0436\u0435\u0441\u0442\u0432\u0435\u043d &\u0423\u0438\u043a\u0438 MainWindow.menu.community.forums=\u0414\u0440\u0443\u0436\u0435\u0441\u0442\u0432\u0435\u043d &\u0444\u043e\u0440\u0443\u043c MainWindow.menu.community.blog=Vuze &\u0415\u043c\u0438\u0441\u0438\u044f MainWindow.menu.help.support=&\u041f\u043e\u043c\u043e\u0449 \u0438 \u043f\u043e\u0434\u0434\u0440\u044a\u0436\u043a\u0430 externalLogin.title=\u0418\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0435 \u0432\u043f\u0438\u0441\u0432\u0430\u043d\u0435 externalLogin.explanation=\u0428\u0430\u0431\u043b\u043e\u043d "%1" \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0432\u043f\u0438\u0441\u0432\u0430\u043d\u0435. \u0421\u043b\u0435\u0434 \u0432\u043f\u0438\u0441\u0432\u0430\u043d\u0435 \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446\u044a\u0442 \u0449\u0435 \u0441\u0435 \u0437\u0430\u0442\u0432\u043e\u0440\u0438. \u0410\u043a\u043e \u043d\u0435 \u0441\u0435 \u0437\u0430\u0442\u0432\u043e\u0442, \u0434\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 "\u0413\u043e\u0442\u043e\u0432\u043e". externalLogin.explanation.capture=\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0435 \u0432\u043f\u0438\u0441\u0432\u0430\u043d\u0435 \u0437\u0430 \u0441\u044a\u0437\u0434\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u043e\u0437\u0438 \u0448\u0430\u0431\u043b\u043e\u043d. \u0421\u043b\u0435\u0434 \u0432\u043f\u0438\u0441\u0432\u0430\u043d\u0435 \u0434\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 "\u0413\u043e\u0442\u043e\u0432\u043e". Button.done=\u0413\u043e\u0442\u043e\u0432\u043e GeneralView.torrent_created_on_and_by=%1 \u043e\u0442 %2 Button.continue=\u041d\u0430\u043f\u0440\u0435\u0434 Button.preview=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 Subscription.menu.forcecheck=\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f Subscription.menu.clearall=\u041e\u0442\u043c\u044f\u0442\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 \u043a\u0430\u0442\u043e \u043f\u0440\u043e\u0447\u0435\u0442\u0435\u043d\u0438 Subscription.menu.remove=\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 sidebar.Library=\u041c\u0435\u0441\u0442\u043d\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 sidebar.LibraryDL=\u0421\u0432\u0430\u043b\u044f\u0449\u0438 \u0441\u0435 sidebar.LibraryCD=\u0417\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u0438 authenticator.location=\u041c\u044f\u0441\u0442\u043e authenticator.details=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 v3.MainWindow.menu.showActionBarText=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u0435\u043a\u0441\u0442 subscript.import.fail.title=\u041f\u0440\u043e\u0432\u0430\u043b \u043d\u0430 \u0438\u043c\u043f\u043e\u0440\u0442 subscript.import.fail.desc=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438: %1 Subscription.menu.export=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 subscript.export.select.template.file=\u0417\u0430\u043f\u0438\u0441 \u043d\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 Button.remove=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 Button.send=\u0418\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435 Button.back=\u041d\u0430\u0437\u0430\u0434 sidebar.LibraryUnopened=\u041d\u0435 \u0441\u043b\u0435\u0434\u0435\u043d\u0438 TableColumn.header.unopened=\u041d\u043e\u0432\u043e Unopened.bigView.header=\u041d\u043e\u0432\u043e Subscription.menu.deleteall=\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 Subscription.menu.reset=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u0432 \u043d\u0430\u0447\u0430\u043b\u043d\u043e \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 ConfigView.section.Subscriptions=\u0410\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 subscriptions.config.maxresults=\u041c\u0430\u043a\u0441. \u0431\u0440\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 \u0437\u0430 \u0437\u0430\u0434\u044a\u0440\u0436\u0430\u043d\u0435 \u0437\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] v3.activity.button.readall=\u041c\u0430\u0440\u043a\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u043e \u043a\u0430\u0442\u043e \u043f\u0440\u043e\u0447\u0435\u0442\u0435\u043d\u043e TableColumn.header.activityNew=\u041d\u043e\u0432\u043e TableColumn.header.activityType=\u0422\u0438\u043f TableColumn.header.activityText=\u0421\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u0435 TableColumn.header.activityDate=\u0414\u0430\u0442\u0430 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u044f\u043d\u0435 TableColumn.header.activityActions=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f Subscription.menu.resetauth=\u041d\u0430\u043d\u043e\u0432\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435 Search.menu.engines=\u0428\u0430\u0431\u043b\u043e\u043d\u0438 Wizard.Subscription.title=\u0410\u0431\u043e\u043d\u0438\u0440\u0430\u043d\u0435 Wizard.Subscription.optin.title=\u0414\u0430 \u0438\u043c\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 #what you've watched? Discover more with a single click... Wizard.Subscription.subscribe.title=\u041d\u0430\u043b\u0438\u0447\u043d\u0438 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 Wizard.Subscription.create.title=\u041d\u043e\u0432 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 Button.search=\u0422\u044a\u0440\u0441\u0435\u043d\u0435 Button.save=\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435 Button.add=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 Button.createNewSubscription=\u041d\u043e\u0432 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 Button.availableSubscriptions=\u0421\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0438 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 Wizard.Subscription.optin.description=\u0410\u043a\u043e \u0441\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0442 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438\u0442\u0435, Vuze \u0449\u0435 \u043f\u043e\u043a\u0430\u0437\u0432\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 \u0441\u0432\u044a\u0440\u0437\u0430\u043d\u0438 \u0441\u044a\u0441 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435\u0442\u043e \u0432 \u043c\u0435\u0441\u0442\u043d\u0430\u0442\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0438 \u0449\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u044f\u0432\u0430 \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u043d\u043e\u0441\u0442 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043f\u043e \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442.\n\n\u0414\u0430 \u0438\u043c\u0430 \u043b\u0438 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438? Wizard.Subscription.create.rss=\u0415\u043c\u0438\u0441\u0438\u044f Wizard.Subscription.create.search=\u0422\u044a\u0440\u0441\u0435\u043d\u0435 Wizard.Subscription.search.subtitle1=\u0414\u0430 \u0441\u0435 \u0432\u044a\u0432\u0435\u0434\u0435 \u0442\u044a\u0440\u0441\u0435\u043d\u0435, \u0437\u0430 \u0434\u0430 \u0441\u0435 \u0441\u044a\u0437\u0434\u0430\u0434\u0435 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442: Wizard.Subscription.search.subtitle2=\u041a\u0430\u043a\u0432\u043e \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0442\u044a\u0440\u0441\u0438? Wizard.Subscription.search.subtitle2.sub1=HD \u0444\u0438\u043b\u043c\u0438, TV \u0448\u043e\u0443\u0442\u0430, \u0444\u0438\u043b\u043c\u0438, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044f\u043d\u0438\u044f \u0432\u044a\u0432 Vuze \u043c\u0440\u0435\u0436\u0430\u0442\u0430 Wizard.Subscription.search.subtitle2.sub2=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u043e\u0442 \u0446\u0435\u043b\u0438\u044f \u0443\u0435\u0431 Wizard.Subscription.search.subtitle3=\u041f\u0440\u0438 \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 \u0449\u0435 \u0441\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0432\u0430\u0442 \u0436\u0438\u0432\u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u0430\u0442\u0430 \u043b\u0435\u043d\u0442\u0430, \u0430\u043a\u043e \u0438\u043c\u0430 \u043d\u043e\u0432\u0438 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 \u0437\u0430 \u0442\u044a\u0440\u0441\u0435\u043d\u0435\u0442\u043e. Wizard.Subscription.rss.subtitle1=\u0412\u044a\u0432\u0435\u0436\u0434\u0430\u043d\u0435 \u0438\u043b\u0438 \u043f\u0443\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 URL: Wizard.Subscription.rss.subtitle2=\u041c\u043d\u043e\u0433\u043e \u0438\u0437\u0434\u0430\u0442\u0435\u043b\u0438 \u0438\u043c\u0430\u0442 \u0435\u043c\u0438\u0441\u0438\u0438 \u043a\u044a\u043c \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435\u0442\u043e. \u0414\u0430 \u0441\u0435 \u043d\u0430\u043c\u0435\u0440\u0438 \u0432 \u0438\u0437\u0434\u0430\u0442\u0435\u043b\u0441\u043a\u0430\u0442\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 URL \u043d\u0430 \u0435\u043c\u0438\u0441\u0438\u044f\u0442\u0430 \u0438 \u043a\u043e\u043f\u0438\u0440\u0430/\u043f\u0443\u0441\u043d\u0435 \u0432 URL \u043f\u043e\u043b\u0435\u0442\u043e \u0433\u043e\u0440\u0435, \u043f\u043e\u0441\u043b\u0435 \u0434\u0430 \u0441\u0435 \u0437\u0430\u043f\u0438\u0448\u0435. Wizard.Subscription.rss.subtitle3=\u0421\u043b\u0435\u0434 \u0437\u0430\u043f\u0438\u0441, \u0449\u0435 \u0441\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0432\u0430\u0442 \u0436\u0438\u0432\u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u0430\u0442\u0430 \u043b\u0435\u043d\u0442\u0430, \u0430\u043a\u043e \u0438\u043c\u0430 \u043d\u043e\u0432\u0438 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 \u0447\u0440\u0435\u0437 \u0435\u043c\u0438\u0441\u0438\u044f\u0442\u0430. Wizard.Subscription.subscribe.library=\u0421\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u0432 \u043c\u0435\u0441\u0442\u043d\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 Wizard.Subscription.subscribe.subscriptions=\u0421\u0432\u044a\u0440\u0437\u0430\u043d\u0438 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 Wizard.Subscription.subscribe.library.empty=\u041d\u044f\u043c\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438?\n \n\u0414\u0430 \u0441\u0435 \u0441\u043b\u0435\u0434\u0438 \u044f\u0440\u043a\u043e \u043e\u0440\u0430\u043d\u0436\u0435\u0432\u0438\u044f \u0431\u0443\u0442\u043e\u043d \u0437\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0432\u044a\u0432 Vuze HD \u043c\u0440\u0435\u0436\u0430\u0442\u0430.\n \n\u041f\u043e-\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u2026 message.confirm.delete.title=\u041f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043d\u0430 \u0438\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 message.confirm.delete.text=\u0414\u0430 \u0441\u0435 \u0438\u0437\u0442\u0440\u0438\u0435 \u043b\u0438 \u043d\u0430\u0438\u0441\u0442\u0438\u043d\u0430 '%1'? Subscription.menu.properties=\u0425\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0438 props.window.title=\u0425\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0438 \u043d\u0430 '%1' subs.prop.is_auto=\u0410\u0432\u0442\u043e-\u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043d\u0430 \u043d\u043e\u0432\u0438 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 subs.prop.last_scan=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f subs.prop.last_result=\u041f\u043e\u0441\u043b\u0435\u0434\u0435\u043d \u043d\u0430\u043c\u0435\u0440\u0435\u043d \u043d\u043e\u0432 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442 subs.prop.last_error=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 subs.prop.num_read=\u0411\u0440\u043e\u0439 \u043f\u0440\u043e\u0447\u0435\u0442\u0435\u043d\u0438 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 subs.prop.num_unread=\u0411\u0440\u043e\u0439 \u043d\u0435\u043f\u0440\u043e\u0447\u0435\u0442\u0435\u043d\u0438 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 subs.prop.template=\u0428\u0430\u0431\u043b\u043e\u043d subs.prop.auth=\u0418\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0435 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435 externalLogin.auth_method_proxy=\u0421 \u043c\u0435\u0442\u043e\u0434 \u0437\u0430 \u0440\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u043e \u043f\u0440\u0438\u0445\u0432\u0430\u0449\u0430\u043d\u0435 \u043d\u0430 \u0431\u0438\u0441\u043a\u0432\u0438\u0442\u043a\u0438. \u0410\u043a\u043e \u0442\u043e\u0432\u0430 \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438, \u0434\u0430 \u0441\u0435 \u043e\u0442\u043c\u0435\u043d\u0438 \u0438 \u043e\u043f\u0438\u0442\u0430 \u043e\u0442\u043d\u043e\u0432\u043e externalLogin.wait=\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u0437\u0430 \u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u2026 TableColumn.menu.date_added.time=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435/\u0441\u043a\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0447\u0430\u0441 sidebar.VuzeHDNetwork=Vuze HD \u043c\u0440\u0435\u0436\u0430 subs.prop.next_scan=\u0421\u043b\u0435\u0434\u0432\u0430\u0449\u043e \u043f\u0440\u043e\u0443\u0447\u0432\u0430\u043d\u0435 subs.prop.assoc=\u0410\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u0438 subs.prop.version=\u0412\u0435\u0440\u0441\u0438\u044f subscriptions.column.new=\u041d\u043e\u0432 subscriptions.column.new.info=\u041f\u043e\u043a\u0430\u0437\u0432\u0430 \u0434\u0430\u043b\u0438 \u0438\u043c\u0430 \u0435\u0434\u0438\u043d \u0438\u043b\u0438 \u043f\u043e\u0432\u0435\u0447\u0435 \u043d\u043e\u0432\u0438 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 subscriptions.column.name=\u0410\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 subscriptions.column.nb-results=\u041e\u0431\u0449\u043e \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 subscriptions.column.nb-new-results=\u041d\u043e\u0432\u0438 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 subscriptions.column.last-checked=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043e subscriptions.view.title=\u0410\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 subs.prop.is_public=\u041e\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043e subs.prop.high_version=\u041d\u0430\u043b\u0438\u0447\u043d\u0430 \u0435 \u043d\u0430\u0439-\u0432\u0438\u0441\u043e\u043a\u0430\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f Subscription.menu.upgrade=\u0421 \u043d\u0430\u0434\u0433\u0440\u0430\u0436\u0434\u0430\u043d\u0435 \u0434\u043e \u043f\u043e-\u0432\u0438\u0441\u043e\u043a\u0430 \u0432\u0435\u0440\u0441\u0438\u044f metasearch.template.version.bad=\u0428\u0430\u0431\u043b\u043e\u043d \u0437\u0430 \u0442\u044a\u0440\u0441\u0435\u043d\u0435 '%1' \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430 \u0431\u0435\u0437 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 Vuze metasearch.addtemplate.failed.title=\u041f\u0440\u043e\u0432\u0430\u043b\u0435\u043d\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f metasearch.addtemplate.failed.desc=\u041f\u0440\u043e\u0432\u0430\u043b \u043f\u0440\u0438 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0448\u0430\u0431\u043b\u043e\u043d \u0437\u0430 \u0442\u044a\u0440\u0441\u0435\u043d\u0435: %1 subscription.version.bad=\u0410\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 '%1' \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430 \u0434\u043e\u043a\u0430\u0442\u043e \u043d\u0435 \u0441\u0435 \u043d\u0430\u0434\u0433\u0440\u0430\u0434\u0438 Vuze statusbar.feedback=\u041f\u0440\u0430\u0449\u0430\u043d\u0435 \u043d\u0430 \u043e\u0442\u0437\u0438\u0432 statusbar.feedback.tooltip=\u0414\u0430 \u0441\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435 \u0442\u0443\u043a \u0437\u0430 \u043f\u0440\u0430\u0449\u0430\u043d\u0435 \u043d\u0430 \u043e\u0442\u0437\u0438\u0432 sidebar.Activity=\u0418\u0437\u0432\u0435\u0441\u0442\u0438\u044f v3.activity.button.watchall=\u041c\u0430\u0440\u043a\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u043e \u043a\u0430\u0442\u043e \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0432\u0430\u043d\u043e subscriptions.view.help.1=\u0414\u043e\u0431\u0430\u0432\u044f\u043d\u0435 \u043d\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 \u043a\u044a\u0434\u0435\u0442\u043e \u0433\u0438 \u0438\u043c\u0430 subscriptions.view.help.2=\u041f\u043e\u043b\u0443\u0447\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0431\u0435\u0437\u043f\u043b\u0430\u0442\u043d\u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438 \u043d\u043e\u0432\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0430\u043b\u0438\u0447\u043d\u043e \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435. \u041e\u0449\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f. sidebar.sash.tooltip=F7 \u0431\u044a\u0440\u0437\u043e \u043f\u043e\u043a\u0430\u0437\u0432\u0430/\u0441\u043a\u0440\u0438\u0432\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u0430\u0442\u0430 \u043b\u0435\u043d\u0442\u0430 sidebar.expand.tooltip=\u0423\u0432\u0435\u043b\u0438\u0447\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u0430\u0442\u0430 \u043b\u0435\u043d\u0442\u0430 sidebar.dropdown.tooltip=\u0421\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u0430\u0442\u0430 \u043b\u0435\u043d\u0442\u0430 \u0434\u0430 \u0441\u0435 \u043f\u043e\u043a\u0430\u0437\u0432\u0430 \u043a\u0430\u0442\u043e \u043c\u0435\u043d\u044e subscript.all.subscribed=\u0418\u043c\u0430 \u043c\u0435\u0441\u0442\u0435\u043d \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 \u0437\u0430 \u0442\u043e\u0432\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 subscript.some.subscribed=\u0418\u043c\u0430 \u043c\u0435\u0441\u0442\u0435\u043d \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 \u0437\u0430 \u043d\u044f\u043a\u043e\u0438 \u043e\u0442 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438\u0442\u0435 \u0437\u0430 \u0442\u043e\u0432\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435.\n\u0414\u0430 \u0441\u0435 \u043f\u043e\u0441\u043e\u0447\u0438 \u0437\u0430 \u043f\u0440\u0435\u0433\u043b\u0435\u0434 \u043d\u0430 \u0434\u0440\u0443\u0433\u0438 \u043d\u0430\u043b\u0438\u0447\u043d\u0438 subscript.none.subscribed=\u0414\u0430 \u0441\u0435 \u043f\u043e\u0441\u043e\u0447\u0438 \u0437\u0430 \u043d\u0430\u043b\u0438\u0447\u043d\u0438 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 \u0437\u0430 \u0442\u043e\u0432\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 v3.iconBar.up.tooltip=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430\u0433\u043e\u0440\u0435\n\u0417\u0430\u0434\u044a\u0440\u0436\u0430\u043d\u0435 \u043d\u0430 \u0431\u0443\u0442\u043e\u043d\u0430 \u043d\u0430 \u043c\u0438\u0448\u043a\u0430\u0442\u0430 \u043f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430 \u0432 \u043d\u0430\u0447\u0430\u043b\u043e\u0442\u043e v3.iconBar.down.tooltip=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430\u0434\u043e\u043b\u0443\n\u0417\u0430\u0434\u044a\u0440\u0436\u0430\u043d\u0435 \u043d\u0430 \u0431\u0443\u0442\u043e\u043d\u0430 \u043d\u0430 \u043c\u0438\u0448\u043a\u0430\u0442\u0430 \u043f\u0440\u0435\u043c\u0435\u0441\u0442\u0432\u0430 \u043d\u0430\u043a\u0440\u0430\u044f TableColumn.header.azsubs.ui.column.subs_link=\u0410\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u044f TableColumn.header.azsubs.ui.column.subs_link.info=\u0410\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u044f \u0441 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 Button.deleteContent.fromLibrary=\u041f\u0440\u0435\u043c\u0430\u0445\u0432\u0430\u043d\u0435 \u043e\u0442 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0442\u0430 Button.deleteContent.fromComputer=\u0418\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435 \u043e\u0442 \u043a\u043e\u043c\u043f\u044e\u0442\u044a\u0440\u0430 v3.deleteContent.message=\n\u0414\u0430 \u0441\u0435 \u0438\u0437\u0442\u0440\u0438\u0435 \u043b\u0438 '%1' \u043e\u0442 \u043a\u043e\u043c\u043f\u044e\u0442\u044a\u0440\u0430 \u0438\u043b\u0438 \u0441\u0430\u043c\u043e \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u043c\u0430\u0445\u043d\u0435 \u043e\u0442 \u043c\u0435\u0441\u0442\u043d\u0430\u0442\u0430 Vuze \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430? v3.MainWindow.menu.view.toolbartext=\u0422\u0435\u043a\u0441\u0442 \u043d\u0430 \u043b\u0435\u043d\u0442\u0438\u0442\u0435 \u0441 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 v3.MainWindow.menu.view.asSimpleList=\u041e\u043f\u0440\u043e\u0441\u0442\u0435\u043d \u0441\u043f\u0438\u0441\u044a\u043a v3.MainWindow.menu.view.asAdvancedList=\u0420\u0430\u0437\u0448\u0438\u0440\u0435\u043d \u0441\u043f\u0438\u0441\u044a\u043a v3.MainWindow.menu.view.statusbar=\u041b\u0435\u043d\u0442\u0430 \u043d\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e Subscription.menu.dirtyall=\u041e\u0442\u043c\u044f\u0442\u0430\u043d\u0435 \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438 \u043a\u0430\u0442\u043e \u043d\u0435\u043f\u0440\u043e\u0447\u0435\u0442\u0435\u043d\u0438 configureWizard.file.message3=Vuze \u0449\u0435 \u0441\u0432\u0430\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u043f\u0430\u043f\u043a\u0430, \u043a\u043e\u044f\u0442\u043e \u0441\u0435 \u0438\u0437\u0431\u0438\u0440\u0430 \u0442\u0443\u043a: v3.deleteContent.applyToAll=\u041f\u0440\u0438\u043b\u0430\u0433\u0430\u043d\u0435 \u043d\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435\u0442\u043e \u0437\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 %1 \u0438\u0437\u0431\u0440\u0430\u043d\u0438 \u043d\u0435\u0449\u0430 ConfigView.label.seeding.firstPriority.ignoreIdleHours=\u0422\u043e\u0440\u0435\u043d\u0442\u0438, \u043a\u043e\u0438\u0442\u043e \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u0442 \u043d\u0438\u0449\u043e \u0437\u0430 v3.MainWindow.menu.contentnetworks=HD &\u041c\u0440\u0435\u0436\u0438 v3.MainWindow.menu.contentnetworks.about=\u0417\u0430 HD \u043c\u0440\u0435\u0436\u0438\u0442\u0435 Peers.column.as.info=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u0410\u0421 (\u0410\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u0430 \u0421\u0438\u0441\u0442\u0435\u043c\u0430) \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d ConfigTransferAutoSpeed.auto.speed.neural=\u041d\u0435\u0432\u0440\u0430\u043b\u0433\u0438\u0447\u0435\u043d \u043c\u0435\u0442\u043e\u0434 (Gudy \u0430\u043b\u0444\u0430) ConfigView.label.autoopen.downloadbars=\u0410\u0432\u0442\u043e-\u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u043b\u0435\u043d\u0442\u0438 \u0437\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043f\u0440\u0438 ConfigView.label.autoopen=\u0410\u0432\u0442\u043e-\u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 ConfigView.label.autoopen.detailstab=\u0410\u0432\u0442\u043e-\u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 '\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438' \u043f\u0440\u0438 ConfigView.label.systray=\u0421\u0438\u0441\u0442\u0435\u043c\u0435\u043d \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 ConfigView.label.systray._mac=\u0418\u043a\u043e\u043d\u0430 \u0432 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u043d\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e ConfigView.section.interface.legacy=\u041f\u0440\u0435\u0434\u0438\u0448\u0435\u043d v3.MainWindow.menu.contentnetworks.manage=&\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 HD \u043c\u0440\u0435\u0436\u0438 azbuddy.ui.table.loc_cat=\u0418\u0437\u0445. \u043a\u0430\u0442. azbuddy.ui.table.rem_cat=\u0412\u0445. \u043a\u0430\u0442. azbuddy.ui.menu.cat=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 azbuddy.ui.menu.cat.share=\u0412\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 \u0441 \u0434\u0440\u0443\u0436\u043a\u0438 azbuddy.ui.menu.cat.set=\u0412\u044a\u0432\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 azbuddy.ui.menu.cat.set_msg=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438 \u0441\u044a\u0441 \u0437\u0430\u043f\u0435\u0442\u0430\u0438, \u0438\u043b\u0438 '\u0432\u0441\u0438\u0447\u043a\u0438' azbuddy.ui.menu.cat_subs=\u0410\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442 subs.prop.update_period=\u041f\u0435\u0440\u0438\u043e\u0434 \u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f azbuddy.enable_cat_pub=\u041e\u0431\u0449\u043e\u0434\u043e\u0441\u0442\u044a\u043f\u043d\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0437\u0430 \u043a\u043e\u0438\u0442\u043e \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u0441\u0435 \u0430\u0431\u043e\u043d\u0438\u0440\u0430\u0442 \u0432\u0441\u0438\u0447\u043a\u0438 \u0434\u0440\u0443\u0436\u043a\u0438 (',' \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438) v3.dialog.cnclose.title=%1 \u0435 \u0437\u0430\u0442\u0432\u043e\u0440\u0435\u043d\u0430 v3.dialog.cnclose.subtitle=\u0418\u0437\u0432\u0435\u0441\u0442\u0438\u0435 v3.dialog.cnclose.info1=\u0417\u0430\u0442\u0432\u043e\u0440\u0435\u043d\u0430 \u0435 HD \u043c\u0440\u0435\u0436\u0430 v3.dialog.cnclose.info2=\u0417\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043e\u0442\u0432\u0430\u0440\u044f\u043d\u0435 \u043d\u0430 \u0442\u0430\u0437\u0438 HD \u043c\u0440\u0435\u0436\u0430 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u043c\u0435\u043d\u044e\u0442\u043e 'HD \u041c\u0440\u0435\u0436\u0438'. v3.dialog.cnclose.noshow=\u0411\u0435\u0437 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043e\u0442\u043d\u043e\u0432\u043e v3.dialog.cnmanage.title=\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 \u043c\u0435\u043d\u044e 'HD \u041c\u0440\u0435\u0436\u0438' v3.dialog.cnmanage.intro=\u041e\u0442 \u0434\u043e\u043b\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u044a\u043a \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u0431\u0435\u0440\u0435 \u043a\u043e\u0438 \u043c\u0440\u0435\u0436\u0438 \u0437\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u0430 \u0441\u0435 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u0442 \u0432 \u043c\u0435\u043d\u044e 'HD \u041c\u0440\u0435\u0436\u0438' azbuddy.ui.table.read_cat=\u041f\u0440\u043e\u0447\u0435\u0442\u0435\u043d\u0438 \u043a\u0430\u0442. TableColumn.header.#=\u2116 TableColumn.header.#.info=\u2116 \u043d\u0430 \u043f\u043e\u0437\u0438\u0446\u0438\u044f/\u043f\u043e\u0434\u0440\u0435\u0436\u0434\u0430\u043d\u0435 TableColumn.header.category.info=\u0418\u043c\u0430 \u043d\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f, \u043a\u044a\u043c \u043a\u043e\u044f\u0442\u043e \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u044a\u0442 TableColumn.header.DateCompleted.info=\u0414\u0430\u0442\u0430 \u043d\u0430 \u0437\u0430\u0432\u044a\u0440\u0448\u0432\u0430\u043d\u0435 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 TableColumn.header.AzProduct.info=\u0421\u044a\u0434\u044a\u0440\u0436\u0430\u0442\u0435\u043b\u043d\u0430 \u043c\u0440\u0435\u0436\u0430, \u043e\u0442 \u043a\u043e\u044f\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u0445\u043e\u0436\u0434\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u044a\u0442 TableColumn.header.health.info=\u041a\u043e\u043b\u043a\u043e \u0437\u0434\u0440\u0430\u0432\u0430 \u0435 \u0432\u0440\u044a\u0437\u043a\u0430\u0442\u0430 \u0434\u043e \u0440\u043e\u044f\u043a\u0430 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 TableColumn.header.maxuploads.info=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u0435\u043d \u0431\u0440\u043e\u0439 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438, \u043a\u044a\u043c \u043a\u043e\u0438\u0442\u043e \u0435\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0441\u0435 \u043a\u0430\u0447\u0432\u0430 TableColumn.header.name.info=\u0418\u043c\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 TableColumn.header.unopened.info=\u0424\u043b\u0430\u0433 \u0437\u0430 \u0438\u043d\u0434\u0438\u043a\u0430\u0446\u0438\u044f \u0434\u0430\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u044a\u0442 \u0435 \u0438\u0437\u043f\u044a\u043b\u043d\u044f\u0432\u0430\u043d (\u043e\u0442\u0432\u0430\u0440\u044f\u043d) TableColumn.header.savepath.info=\u0426\u0435\u043b\u0435\u0432\u0430\u0442\u0430 \u043f\u0430\u043f\u043a\u0430 \u0438\u043b\u0438 \u0444\u0430\u0439\u043b \u0437\u0430 \u0434\u0430\u043d\u043d\u0438\u0442\u0435 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 TableColumn.header.SeedingRank.info=\u0420\u0430\u043d\u0433, \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u0449 \u043a\u043e\u043b\u043a\u043e \u043c\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u044a\u0442 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u0441\u0435\u0435\u043d\u0435. \u041f\u043e-\u0432\u0438\u0441\u043e\u043a\u0430 \u0441\u0442\u043e\u0439\u043d\u043e\u0441\u0442 \u0437\u043d\u0430\u0447\u0438 \u043f\u043e-\u0433\u043e\u043b\u044f\u043c\u0430 \u043d\u0443\u0436\u0434\u0430. TableColumn.header.shareRatio.info=\u041a\u043e\u043b\u043a\u043e \u0435 \u043a\u0430\u0447\u0435\u043d\u043e (\u0441\u043f\u043e\u0434\u0435\u043b\u0435\u043d\u043e) \u0441\u043f\u0440\u044f\u043c\u043e \u0441\u0432\u0430\u043b\u0435\u043d\u043e\u0442\u043e. TableColumn.header.size.info=\u0420\u0430\u0437\u043c\u0435\u0440 \u043d\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0432\u044a\u0440\u0445\u0443 \u0434\u0438\u0441\u043a\u0430 TableColumn.header.azsubs.ui.column.subs.info=\u0411\u0443\u0442\u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430\u0449 \u0430\u0431\u043e\u043d\u0438\u0440\u0430\u043d\u0435 \u0437\u0430 \u0435\u043c\u0438\u0441\u0438\u044f \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u0449\u0430 \u0441\u0432\u044a\u0440\u0437\u0430\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.upspeed.info=\u0422\u0435\u043a\u0443\u0449\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 TableColumn.header.downspeed.info=\u0422\u0435\u043a\u0443\u0449\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 TableColumn.header.up.info=\u0422\u0435\u043a\u0443\u0449\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0430\u043d\u043d\u0438 \u0438\u0437\u043f\u0440\u0430\u0442\u0435\u043d\u0438 \u043d\u0430 \u0434\u0440\u0443\u0433\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 TableColumn.header.down.info=\u0422\u0435\u043a\u0443\u0449\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0430\u043d\u043d\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 TableColumn.header.ProgressETA.info=\u041a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u0430 \u043a\u043e\u043b\u043e\u043d\u0438 \u0437\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u0437\u0430\u0432\u044a\u0440\u0448\u0435\u043d\u043e\u0441\u0442, \u041e\u0412\u0417 \u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u0432 \u0435\u0434\u043d\u0430 \u043c\u043d\u043e\u0433\u043e\u0440\u0435\u0434\u043e\u0432\u0430 \u043a\u043e\u043b\u043e\u043d\u0430. TableColumn.header.eta.info=\u041e\u0447\u0430\u043a\u0432\u0430\u043d\u043e \u0432\u0440\u0435\u043c\u0435 \u043f\u0440\u0435\u0434\u0438 \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 Pieces.column.#=\u2116 Pieces.column.#.info=\u2116 \u043d\u0430 \u043f\u0430\u0440\u0447\u0435 Peers.column.%.info=% \u043e\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0441\u0432\u0430\u043b\u0435\u043d \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0435\u0433\u0430 TableColumn.header.download.info=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0430\u043d\u043d\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438 \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d TableColumn.header.upload.info=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0430\u043d\u043d\u0438 \u043c\u0435\u0441\u0442\u043d\u043e \u0438\u0437\u043f\u0440\u0430\u0442\u0435\u043d\u0438 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d TableColumn.header.downloadspeed.info=\u041f\u043e \u043a\u043e\u043b\u043a\u043e \u0441\u0435 \u0432\u0437\u0438\u043c\u0430 \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f TableColumn.header.uploadspeed.info=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435, \u0441 \u043a\u043e\u0435\u0442\u043e \u0441\u0435 \u0438\u0437\u043f\u0440\u0430\u0449\u0430\u0442 \u0434\u0430\u043d\u043d\u0438 \u043d\u0430 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f TableColumn.header.lan.info=\u0424\u043b\u0430\u0433 \u0437\u0430 \u0438\u043d\u0434\u0438\u043a\u0430\u0446\u0438\u044f, \u0447\u0435 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f\u0442 \u0435 \u0432 \u043b\u043e\u043a\u0430\u043b\u043d\u0430\u0442\u0430 \u043c\u0440\u0435\u0436\u0430 TableColumn.header.downloadspeedoverall.info=\u041e\u0447\u0430\u043a\u0432\u0430\u043d\u043e \u0442\u0435\u043c\u043f\u043e \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435 \u043e\u0442 \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d Peers.column.pieces.info=\u0413\u0440\u0430\u0444\u0438\u0447\u043d\u0430 \u043b\u0435\u043d\u0442\u0430, \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u0449\u0430 \u043a\u043e\u0438 \u043f\u0430\u0440\u0447\u0435\u0442\u0430 \u0435 \u0441\u0432\u0430\u043b\u0438\u043b \u0440\u0430\u0432\u043d\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0435\u043d\u0438\u044f\u0442 TableColumn.header.TableColumnNameInfo=\u0418\u043c\u0435 \u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u0430 \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 TableColumn.header.TableColumnSample=\u041f\u0440\u0438\u043c\u0435\u0440 TableColumn.header.TableColumnInfo=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u0430 TableColumn.header.TableColumnChosenColumn=\u0418\u0437\u0431\u0440\u0430\u043d\u0438 \u043a\u043e\u043b\u043e\u043d\u0438 subs.prop.is_auto_ok=\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043e \u0435 \u0430\u0432\u0442\u043e-\u0441\u0432\u0430\u043b\u044f\u043d\u0435 label.learnmore=\u041e\u0449\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f ColumnSetup.title=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u0430 \u0437\u0430 '%1' ColumnSetup.explain=\u041e\u0442 \u043d\u0430\u043b\u0438\u0447\u043d\u0438\u0442\u0435 \u043a\u043e\u043b\u043e\u043d\u0438 \u0432\u043b\u044f\u0432\u043e \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0434\u043e\u0431\u0430\u0432\u044f\u0442 \u0432\u0438\u0434\u0438\u043c\u0438 \u043a\u043e\u043b\u043e\u043d\u0438 \u0432\u0434\u044f\u0441\u043d\u043e. \u0420\u0430\u0437\u0433\u0440\u044a\u0449\u0430\u043d\u0435 \u0438\u043b\u0438 \u0441\u044a\u043a\u0440\u0430\u0449\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u043f\u0438\u0441\u044a\u043a\u0430 \u0441 \u043d\u0430\u043b\u0438\u0447\u043d\u0438 \u043a\u043e\u043b\u043e\u043d\u0438 \u0441\u0442\u0430\u0432\u0430 \u0447\u0440\u0435\u0437 \u0440\u0430\u0437\u0434\u0435\u043b \u0424\u0438\u043b\u0442\u044a\u0440 \u0434\u043e\u043b\u0443 \u0432\u043b\u044f\u0432\u043e. \u0412\u043b\u0430\u0447\u0435\u043d\u0435/\u043f\u0443\u0441\u043a\u0430\u043d\u0435 \u0438 \u0431\u044a\u0440\u0437\u0438 \u043a\u043b\u0430\u0432\u0438\u0448\u0438 \u0441\u044a\u0449\u043e \u0441\u0435 \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430\u0442. ColumnSetup.chosencolumns=\u0418\u0437\u0431\u0440\u0430\u043d\u0438 \u043a\u043e\u043b\u043e\u043d\u0438 ColumnSetup.proficiency=\u041f\u043e\u0434\u0433\u043e\u0442\u0432\u0435\u043d\u043e\u0441\u0442: ColumnSetup.categories=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438: ColumnSetup.filters=\u0424\u0438\u043b\u0442\u0440\u0438 ColumnSetup.availcolumns=\u041d\u0430\u043b\u0438\u0447\u043d\u0438 %1 \u043a\u043e\u043b\u043e\u043d\u0438 ColumnSetup.availcolumns.filteredby=\u041d\u0430\u043b\u0438\u0447\u043d\u0438 %1 \u043a\u043e\u043b\u043e\u043d\u0438 \u0444\u0438\u043b\u0442\u0440\u0438\u0440\u0430\u043d\u0438 \u043f\u043e %2 devices.view.title=\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 device.renderer.view.title=\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0438 device.mediaserver.view.title=\u041c\u0435\u0434\u0438\u0439\u043d\u0438 \u0441\u044a\u0440\u0432\u044a\u0440\u0438 device.router.view.title=\u041c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0438 device.model.desc=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u0430 \u043c\u043e\u0434\u0435\u043b device.model.name=\u0418\u043c\u0435 \u043d\u0430 \u043c\u043e\u0434\u0435\u043b device.model.num=\u041d\u043e\u043c\u0435\u0440 \u043d\u0430 \u043c\u043e\u0434\u0435\u043b device.manu.desc=\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b device.router.is_mapping=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 device.router.req_map=\u0418\u0437\u0438\u0441\u043a\u0432\u0430\u043d\u0438 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f device.router.configure=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430 UPnP device.mediaserver.configure=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430 \u043c\u0435\u0434\u0438\u0439\u043d\u0438\u044f \u0441\u044a\u0440\u0432\u044a\u0440 device.hide=\u0421\u043a\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e device.show=\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u0441\u043a\u0440\u0438\u0442\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 device.search=\u0422\u044a\u0440\u0441\u0435\u043d\u0435 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 device.router.con_type=\u0412\u0440\u044a\u0437\u043a\u0430: %1 device.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 device.upnp.desc_url=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e device.upnp.present_url=\u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e ConfigView.label.maxStalledSeeding=\u041c\u0430\u043a\u0441. '\u0437\u0430\u043f\u044a\u043d\u0430\u0442\u0438' [0:\u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] device.search.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0442\u044a\u0440\u0441\u0435\u043d\u0435 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 devices.sidebar.simple=\u041e\u043f\u0440\u043e\u0441\u0442\u0435\u043d \u0438\u0437\u0433\u043b\u0435\u0434 devices.xcode.working_dir=\u0417\u043e\u043d\u0430 \u0437\u0430 \u043a\u0440\u044a\u0441\u0442\u043e\u0441\u0430\u043d\u0438 \u043a\u043e\u0434\u043e\u0432\u0435 devices.xcode.prof_def=\u041a\u0440\u044a\u0441\u0442\u043e\u0441\u0430\u043d \u043a\u043e\u0434 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435 devices.xcode.profs=\u041d\u0430\u043b\u0438\u0447\u043d\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u0437\u0430 \u043a\u0440\u044a\u0441\u0442\u043e\u0441\u0430\u043d\u0438 \u043a\u043e\u0434\u043e\u0432\u0435 device.lastseen=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u043e \u0432\u0438\u0434\u044f\u043d\u043e devices.contextmenu.xcode=\u041a\u0440\u044a\u0441\u0442\u043e\u0441\u0430\u043d \u043a\u043e\u0434 \u0437\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e devices.device=\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e devices.profile=\u041f\u0440\u043e\u0444\u0438\u043b General.percent=% devices.installed=\u0418\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u043e devices.comp.missing=\u041d\u0435 \u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0430 Vuze \u043f\u043e\u0434\u0434\u0440\u044a\u0436\u043a\u0430 devices.state=\u041a\u0430\u043a \u0435 i18n.bg_BG.Contact=Andrey Marinov andreshko@hotmail.bg azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_bs_BA.properties0000644000175000017500000020461011301156004026040 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Fajl .torrent Main.parameter.usage=Upotreba : java org.gudy.azureus2.cl.Main [parametri] "file.torrent" "put snimanja" Main.parameter.maxUploads=Max broj slanja Main.parameter.maxSpeed=Max slanje bytes/sek MainWindow.menu.file=Fajl MainWindow.menu.file.open=Otvori MainWindow.menu.file.create=Novi .torrent MainWindow.menu.file.create.fromfile=Od fajla MainWindow.menu.file.create.fromdir=Od foldera MainWindow.menu.file.export=Iznesi XML .torrent... MainWindow.menu.file.import=Unesi XML .torrent... MainWindow.menu.file.exit=Zatvori MainWindow.dialog.choose.file=Odaberite .torrent fajl MainWindow.menu.file.folder=Folder MainWindow.dialog.choose.folder=Odaberite folder u kojem se nalaze .torrent fajlovi MainWindow.menu.view=Izgled MainWindow.menu.view.mytorrents=Moji .torrent MainWindow.menu.view.configuration=Konfiguracija MainWindow.menu.view.console=Konzola MainWindow.menu.view.irc=Irc MainWindow.menu.closealldetails=Zatvori sve detalje MainWindow.menu.closealldownloadbars=Zatvori sve Download &Bars MainWindow.menu.language=Jezik ConfigView.section.language=Jezik MainWindow.menu.help=Pomoc MainWindow.menu.help.about=O Vuze MainWindow.about.title=O MainWindow.about.section.developers=Programeri MainWindow.about.section.translators=Prevodioci MainWindow.about.internet.sourceforge=Sourceforge Project Stranica MainWindow.about.internet.sourceforgedownloads=Download sa Sourceforge MainWindow.about.internet.bugreports=Posalji Bug MainWindow.about.internet.forumdiscussion=Forum MainWindow.about.internet.wiki=Wiki FAQ Vuze MainWindow.dialog.choose.savepath=Odaberite folder za snimanje MainWindow.dialog.choose.savepath_forallfiles=Odaberite folder za snimanje SVIH fajlova MainWindow.status.latestversion=Zadnja MainWindow.status.latestversion.clickupdate=Klliknite za update MainWindow.status.unknown=Nepoznata MainWindow.status.checking=provijera MyTorrentsView.mytorrents=Moji .torrent TableColumn.header.name=Ime TableColumn.header.size=Velicina TableColumn.header.done=Zavrseno TableColumn.header.done.info=% uradjen od sadasnjeg posla TableColumn.header.status=Stanje TableColumn.header.status.info=Sta radi Torrent TableColumn.header.seeds=Izvori TableColumn.header.seeds.info=Broj izvora prikljuceni (ukupnih izvora) TableColumn.header.peers=Klijenti TableColumn.header.peers.info=Broj povezani klijenti (Ukupni broj klijenta) TableColumn.header.downspeed=Brzina Preuzimanja TableColumn.header.upspeed=Br. Slanja TableColumn.header.eta=Ostalo TableColumn.header.tracker=Tracker TableColumn.header.tracker.info=Status trackera TableColumn.header.trackernextaccess=Sledeci Pristup Tracker-a TableColumn.header.trackernextaccess.info=Kada sledeci pristup tracker-a TableColumn.header.priority=Prioritet TableColumn.header.priority.info=Koliko je dato brzine za slanje Torrenta MyTorrentsView.menu.showdetails=Pokazi detalje MyTorrentsView.menu.showdownloadbar=Pokazi traku preuzimanja MyTorrentsView.menu.open=Otvori MyTorrentsView.menu.setpriority=Prioritet MyTorrentsView.menu.setpriority.high=Visoko MyTorrentsView.menu.setpriority.low=Nisko MyTorrentsView.menu.start=Start MyTorrentsView.menu.stop=Zaustavi MyTorrentsView.menu.remove=Brisi MyTorrentsView.menu.changeTracker=Dodaj URL Trackera TrayWindow.menu.exit=Izlaz TrayWindow.menu.show=Pokazi Vuze SystemTray.menu.exit=Izlaz SystemTray.menu.closealldownloadbars=Zatvori sve trake preuzimanja SystemTray.menu.show=Pokazi Vuze PeersView.ip=Ip PeersView.ip.info=IP klijenta PeersView.port.info=Koristen port PeersView.T.info=l (lokal): vi radite prikljucak, r (spoljno): klijent radi prikljucak. PeersView.T.L.tooltip=vi radite prikljucak PeersView.T.R.tooltip=klijent radi prikljucak. PeersView.I1=I (Interesuje klijenta) PeersView.I1.info=Dali vas interesuje sta drugi klijent ima? PeersView.C1=C (Blokirao klijent) PeersView.C1.info=Klijent zabranjuje preuzimanje PeersView.pieces=Delovi PeersView.downloadspeed=Br. Preuzimanja PeersView.download=Skinuto PeersView.I2=I (Interesantno za klijenta) PeersView.I2.info=Da li je se klijent interesuje u sta imate? PeersView.C2=C (Blokiraj klijenta) PeersView.C2.info=Blokirate klijenta za preuzimanje PeersView.uploadspeed=Brzina Up PeersView.uploadspeed.info=Brzina slanja klijentu PeersView.upload.info=Prosecno slanje klijentu. PeersView.statup=Stat Slanja PeersView.statup.info=Estimacija brzine slanja klijenta PeersView.S.info=Pretnja: Klijent moze da se "Preti" rucno ili automatsko (ako ne daje dovoljno podataka ili mnogo sporo) PeersView.downloadspeedoverall=Ukupna Br. Preuzimanja PeersView.client=Klijent PeersView.client.info=Tip programa sto klijent koristi PeersView.menu.snubbed=Pretnja PeersView.title.short=Detalji PeersView.title.full=Detalji ConfigView.section.files=Fajlovi ConfigView.label.usefastresume=Koristi Brzi nastavak ConfigView.label.incrementalfile=Inkrementalna kreacija fajla ConfigView.label.defaultsavepath=Glavni folder za snimanje ConfigView.button.browse=Pretrazi... ConfigView.dialog.choosedefaultsavepath=Odaberite glavni folder za download ConfigView.section.server=Server ConfigView.section.global=Generalno ConfigView.label.disconnetseed=Iskljuciti se sa Seed-a kada si Seed ConfigView.label.switchpriority=Predji na nizi prioritet kada seed-am ConfigView.label.maxdownloads=Istovremenih preuzimanja (0 : neograniceno) ConfigView.label.maxdownloads.tooltip=Uvijek cete preuzimati koliko stavite ovdje, sa jednim izuzetkom.\nZavrsen Prvi Prioritet Torrenta ce moci da predje preko aktivnog preuzimanja ako je absolutno potrebno. ConfigView.label.maxactivetorrents=Max aktivnih Torrent-a (0 : neograniceno)\n - Novi Torrent nece poceti ako preuzimate/saljete vise ConfigView.label.priorityExtensions=Veci prioritet za fajlove :\n(npr: .txt;.nfo;.jpg) ConfigView.label.maxuploads=Standardna brzina slanja po Torrent ConfigView.label.maxuploadspeed=Brzina slanja (globalna) ConfigView.label.saveresumeinterval=Snimi podatke 'nastavka' svaki ConfigView.unlimited=Neograniceno ConfigView.section.display=Izgled ConfigView.label.opendetails=Auto otvori detalje ConfigView.label.openbar=Auto otvaranje male-trake ConfigView.label.closetotray=Spusti u System Tray kada kliknem na X ConfigView.label.minimizetotray=Minimiziraj salje u System Tray ConfigView.section.general=Generalno ConfigView.section.start=Pokreni ConfigView.label.showsplash=Pokazi pocetni ekran ConfigView.label.autoupdate=Otvori Upgrade dijalog kada je nova verzija dostupna ConfigView.label.openconsole=Otvoriti konzolu pri startu ConfigView.label.openconfig=Otvoriti Konfiguraciju pri startu ConfigView.label.startminimized=Pokreni minimiziran ConfigView.section.irc=Irc ConfigView.label.ircwiki=Molim citaj http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=server ConfigView.label.ircchannel=Kanal ConfigView.label.irclogin=Ime ConfigView.section.security=Sigurnost ConfigView.label.password=Zastiti Vuze sa lozinkom\nPotrebno za podizanje sa System Tray i pokretanje. ConfigView.label.passwordconfirm=Sifra (potvrda) ConfigView.label.passwordmatch=Aktivirana Sifra : ConfigView.label.passwordmatchnone=Ne ConfigView.label.passwordmatchno=Ne / Sifra nije ista ConfigView.label.passwordmatchyes=Da ConfigView.button.save=Snimi ConfigView.title.short=Konfiguracija ConfigView.title.full=Konfiguracija ConsoleView.title.short=Konzola ConsoleView.title.full=Konzola FileItem.write=pisanje FileItem.read=citanje FileItem.normal=normalno FileItem.high=visoko FileItem.donotdownload=Ne preuzimati FilesView.name=Ime FilesView.size=Velicina FilesView.done=Uradjeno FilesView.firstpiece=Broj prvog parceta FilesView.numberofpieces=Broj parceta FilesView.pieces=Parceta FilesView.mode=Mod FilesView.priority=Prioritet FilesView.menu.open=&Otvori FilesView.menu.setpriority=&Prioritet FilesView.menu.setpriority.high=&Visoko FilesView.menu.setpriority.normal=&Normalno FilesView.menu.setpriority.skipped=Ne S&kidati FilesView.title.short=Fajlovi FilesView.title.full=Fajlovi GeneralView.section.downloaded=Skinuto GeneralView.label.status.file=Fajl Status GeneralView.label.status.pieces=Parcici GeneralView.section.availability=Dostupno GeneralView.label.status.pieces_available=Parcici GeneralView.title.short=Generalno GeneralView.title.full=Generalno GeneralView.label.timeelapsed=Proslo : GeneralView.label.remaining=Ostalo: GeneralView.label.downloaded=Skinuto : GeneralView.label.downloadspeed=Brzina preuzimanja: GeneralView.label.maxuploads=Max brzina upload-a : GeneralView.label.uploaded=Slano : GeneralView.label.uploadspeed=Brzina slanja : GeneralView.label.seeds=Izvori : GeneralView.label.peers=Klijenti : GeneralView.label.totalspeed=Ukupna Brzina : GeneralView.label.totalspeed.tooltip=Ukupna brzina od klijenta koji su prikljuceni. GeneralView.label.filename=Ime : GeneralView.label.totalsize=Ukupna velicina : GeneralView.label.savein=Snimi u : GeneralView.label.hash=Hash : GeneralView.label.numberofpieces=Broj parceta : GeneralView.label.size=Velicina : GeneralView.label.tracker=Tracker : GeneralView.label.updatein=Obnova za : GeneralView.label.trackerurl=URL Tracker : GeneralView.label.trackerurlupdate=Rucna obnova GeneralView.label.comment=Komentar : ManagerItem.waiting=Ceka ManagerItem.allocating=Rasporedjivanje ManagerItem.checking=Provijera ManagerItem.ready=Spreman ManagerItem.downloading=Preuzimanje ManagerItem.seeding=Seed-a ManagerItem.stopped=Zaustavljen ManagerItem.error=Greska ManagerItem.high=visoko ManagerItem.low=nisko MinimizedWindow.name=Ime: PiecesView.#=Broj PiecesView.size=Velicina PiecesView.numberofblocks=Broj Bloka PiecesView.blocks=Blokova PiecesView.completed=Zavrseno PiecesView.availability=Dostupnost PiecesView.title.short=Dijelovi PiecesView.title.full=Dijelovi SystemTray.tooltip.seeding=%1 seeding, SystemTray.tooltip.downloading=%1 preuzimanja, DownloadManager.error.filenotfound=Fajl nije pronadjen DownloadManager.error.fileempty=.torrent prazan DownloadManager.error.filetoobig=.torrent fajl je prevelik DownloadManager.error.filewithouttorrentinfo=Nema "Torrent" info u fajlu DownloadManager.error.unsupportedencoding=Enkodiranje nije podrzano DownloadManager.error.ioerror=Greska IO DownloadManager.error.sha1=Greska: nema SHA1 algoritam PeerManager.status.offline=Nije dostupan PeerManager.status.ok=Ok PeerManager.status.checking=provijera PeerManager.status.finished=Zavrsen PeerManager.status.finishedin=Zavrsava za MainWindow.upgrade.assistant=Update pomocnik MainWindow.upgrade.newerversion=Nova verzija je dostupna MainWindow.upgrade.explanation=Pomocnik ce skinuti novu verziju u folder Azureus-a i restartovati program MainWindow.upgrade.explanation.manual=Mozete obnoviti rucno sa zatvaranjem Azureus-a, preuzimanjem nove verzije i restartovanje programa MainWindow.upgrade.step1=1: Skini novu verziju MainWindow.upgrade.step2=2: Zatvori ovu verziju i startuj novu MainWindow.upgrade.hint1=Savijet:\tKliknite na Zavrsi i sve ce se zavrsiti automaticki MainWindow.upgrade.hint2=Savijet:\tAko zelite da zatvorite Vuze kasnije, kliknite na Anuliraj i\n\tpromijeniti ime azureus2-new.jar u Azureus2.jar posle zatvaranja MainWindow.upgrade.error.downloading.hint=Greska:\tNemoguce skinuti novu verziju, uraditi rucno MainWindow.upgrade.section.info=Nova verzija dostupna MainWindow.upgrade.section.manual=Rucni Update MainWindow.upgrade.section.automatic=Automatska obnova MainWindow.upgrade.tooltip.progressbar=Naprijedak preuzimanja Button.next=Sljedece Button.finish=Zavrsi Button.cancel=Obustani LocaleUtil.title=Odaberi kodiranje LocaleUtil.section.chooseencoding=Odaberite kodiranje za fajl LocaleUtil.label.chooseencoding=Molimo vas izaberite najbolje kodiranje LocaleUtil.label.hint.doubleclick=Savijet: Dupli klik na kolonu odabira kodiranje i zatvara prozor LocaleUtil.label.checkbox.rememberdecision=Zapamti odluku za ostale fajlove LocaleUtil.column.encoding=Kodiranje IrcClient.copyright=Upotrebi API Java IRC PircBot - http://www.jibble.org/pircbot.php IrcClient.connecting=Prikljucuje se na IrcClient.connected=Prikljucen na IrcClient.joining=Prikljucuje se IrcClient.channel=Kanal IrcClient.joined=prikljucen IrcClient.error=Greska IrcClient.hasjoined=se prikljucio IrcClient.haskicked=je izbacio IrcClient.hasleft=je otisao IrcClient.nowknown=je sad poznat kao IrcClient.topicforchannel=Ime za kanal IrcClient.disconnected=Iskljucen sa IrcClient.noNick=Ime vam je prazno. Popunite zonu u meni "Konfiguracija" IrcView.actionnotsupported=Akcija nije podrzana IrcView.clientsconnected=korisnici IrcView.privateto=Za IrcView.privatefrom=Od IrcView.noticefrom=Uputstvo : IrcView.errormsg=Greska pisanja /msg : /msg user text IrcView.help=Dostupne komande :\n . /help : pokazi ovu poruku\n . /nick | /name : menja ime \n . /me action : salje akciju \n . /msg pseudo poruka : salje privatnu poruku \n . /r poruka : adgovor na zadnju provatnu poruku\n . /join #kanal : menja kanal PasswordWindow.title=Vuze je zakljucan PasswordWindow.passwordprotected=Vuze je zasticen sa sifrom.\nUnesi sifru : Button.ok=Ok TrackerChangerWindow.title=Dodaj tracker TrackerChangerWindow.newtracker=Unesite novi URL trackera PeersView.discarded=Odbacen PeersView.discarded.info=Podatci koji su primljeni ali ne trebaju, tako da su izbrisani. discarded=Odbijeno MyTorrentsView.#=Broj MyTorrentsView.menu.move=Pomijeri MyTorrentsView.menu.moveUp=Gore MyTorrentsView.menu.moveDown=Dole GeneralView.label.hashfails=Hash nevazno : GeneralView.label.shareRatio=Ratio dijeljenja : ConfigView.section.downloadManagement=Menadzer Preuzimanja ConfigView.label.startRatioPeers=Pokreni seed kada je tu manje od 1 seed za ConfigView.text.neverStop=Nikada zaustaviti ConfigView.text.neverStart=Nikada pokrenuti ConfigView.text.peers=Klijenti ConfigView.label.checkOncompletion=Provjeri fajl na kraju preuzimanja wizard.title=Kreiraj Torrent wizard.previous=< Nazad wizard.next=Slijedece > wizard.finish=Zavrseno wizard.mode=Tracker / Nacin wizard.tracker=Tracker: wizard.invalidurl=URL nije dobar wizard.singlefile=Jedan fajl wizard.singlefile.help=Kreirati .torrent od jednog fajla wizard.directory=Folder wizard.directory.help=Kreirati .torrent od direktorijuma wizard.choosefile=Odaberi fajl wizard.file=Fajl: wizard.browse=Pretrazi... wizard.choosedirectory=Odaberi folder wizard.invalidfile=Nevazan fajl! wizard.invaliddirectory=Nevazan folder! wizard.torrentFile=Torrent fajl wizard.choosetorrent=Odabrite .torrent za kreiranje wizard.information=Informacije wizard.notimplemented=Nije jos implementirano wizard.progresstitle=Kreacija Torrent fajla wizard.savingfile=Snimanje fajla... wizard.filesaved=Fajl snimljen. wizard.close=Zatvori Torrent.create.progress.piecelength=Velicina dijelova: Torrent.create.progress.piececount=Broj dijelova: Torrent.create.progress.totalfilesize=Ukupna velicina fajla: Torrent.create.progress.totalfilecount=Ukupan broj fajla: Torrent.create.progress.parsingfiles=Analiza fajla Torrent.create.progress.hashing=Racun hash od fajla MainWindow.upgrade.downloadingfrom=Preuzimanje sa : MainWindow.menu.view.ipFilter=Filtri Ip ConfigView.section.ipfilter=IP filter ConfigView.section.ipfilter.description=Opis ConfigView.section.ipfilter.start=Pocetni IP ConfigView.section.ipfilter.end=Zadnji IP ConfigView.section.ipfilter.add=Dodaj ConfigView.section.ipfilter.remove=Skini ConfigView.section.ipfilter.edit=Editiraj ConfigView.section.ipfilter.save=Snimi ConfigView.section.ipfilter.editFilter=Editiraj filter ConfigView.section.ipfilter.enable=Ukljuci PeersView.menu.close=Zatvori seedmore.title=Torrent nije dovoljno dijeljen seedmore.shareratio=Vase dijeljenje na ovaj fajl je seedmore.uploadmore=Dijeljenje nize od 100% ugrozava BitTorrent mrezu.\nTrebali bi da nastavite dijeljenje.\nNastavak? ConfigView.label.showpopuponclose=Pokazi potvdru kada se zaustavi seed torrent-a\n sa ratio manji od 1. ConfigView.label.startNumSeeds=\nPokreni seed ako ima manje od\n - Ispred svih ostalih pravila ConfigView.label.seeds=izvora ConfigView.section.seeding=Seed-anje MyTorrentsView.menu.removeand=Brisi i MyTorrentsView.menu.removeand.deletetorrent=Izbrisi .torrent MyTorrentsView.menu.removeand.deletedata=Izbrisi podatke MyTorrentsView.menu.removeand.deleteboth=Sve izbrisi deletedata.title=!!! Paznja !!! deletedata.message1=Brisete PODATKE od :\n MainWindow.menu.file.configure=Pomocnik konfiguracije configureWizard.title=Pomocnik Konfiguracije configureWizard.welcome.title=Dobrodosli na Pomocnicku Konfiguraciju Azureus-a configureWizard.welcome.message=Pomocnik ce vam omoguctii konfiguraciju Vuze za normalnu upotrebu. Mozete uraditi precizniju konfiguraciju u meni\n Izgled > Konfiguracija. configureWizard.transfer.title=Transfer i Veza configureWizard.transfer.hint=Savijet : Odaberite brzinu malo manju od vase. configureWizard.transfer.message=Odaberite vasu vezu. Budite upozoreni da manja brzina upload-a rezultira u manjoj brzini download-a. Posto se upload brzina broji samo za SVAKI torrent koji vi download-irate mnogo torrent-a ce dati lose odrzavanje. Preporucujemo NAJMANJE 5kB/s po Torrent-u. Sto brze upload-irate sto prije ce te download-irati torrent. configureWizard.transfer.connection=Tip veze configureWizard.transfer.connection.0=Prilagodjena configureWizard.transfer.connection.1=modem/isdn configureWizard.transfer.connection.2=adsl/kabal xxx/128 kbps configureWizard.transfer.connection.3=adsl/kabal xxx/256 kbps configureWizard.transfer.connection.4=adsl/kabal xxx/384 kbps configureWizard.transfer.connection.5=adsl/kabal xxx/512 kbps configureWizard.transfer.connection.6=adsl/kabal xxx/768 kbps configureWizard.transfer.connection.7=adsl/kabal xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Maks brzina upload-a (kB/s) configureWizard.transfer.maxActiveTorrents=Max Aktivni configureWizard.transfer.maxDownloads=Max brzina download-a configureWizard.transfer.maxUploadsPerTorrent=Max brzina Upload-a po Torrent-u configureWizard.nat.title=NAT / Port od Servera configureWizard.nat.message=Za optimalnu upotrebu BitTorrent-a, morate biti totalno dostupni Internet-u. BitTorrent upotrebljava standardni port 6881-6889. Ovo omogucava probu ili promijenu tih portova. Ako imate preuzimanje u toku neki portovi nece moci da se probaju. configureWizard.nat.test=Proba configureWizard.nat.testing=Proba port-a configureWizard.nat.ok=Ok configureWizard.nat.ko=Greska NAT configureWizard.nat.unable=Proba nemoguca configureWizard.file.title=Torrent / Fajlovi configureWizard.file.message1=Vuze ce snimiti otvorene Torrent-e u folder koji se moze odabrati ovdje: configureWizard.file.path=Put configureWizard.file.browse=Trazi configureWizard.file.message2=Vuze moze nastaviti preuzimanje fajlova istog momenta, sa dodavanjem informacija za nastavak u vas Torrent fajl. To omogucava nastavak nezavrsenih dijelova. configureWizard.file.fastResume=Omoguci brz nastavak configureWizard.file.invalidPath=Direktorijum nevazan configureWizard.finish.title=Zavrseno configureWizard.finish.message=Vuze je konfiguriran, uzivajte ! wizard.close.confirmation=Potvrdi wizard.close.message=Da se pokaze ovaj pomocnik ne sledece startovanje Azureusa? exportTorrentWizard.title=Iznos Torrent exportTorrentWizard.torrentfile.title=Izaberite Torrent exportTorrentWizard.torrentfile.message=Odaberi Torrent za iznos exportTorrentWizard.torrentfile.path=Put exportTorrentWizard.torrentfile.browse=Pretrazi exportTorrentWizard.torrentfile.invalidPath=Torrent nevazan exportTorrentWizard.exportfile.title=Odabranje iznosnog fajla exportTorrentWizard.exportfile.message=Uneti unosni fajl exportTorrentWizard.exportfile.path=Put exportTorrentWizard.exportfile.browse=Potrazi exportTorrentWizard.exportfile.invalidPath=Iznos fajl nevazan exportTorrentWizard.finish.title=Zavrseno exportTorrentWizard.finish.message=Iznos uspijesan exportTorrentWizard.process.inputfilebad.title=Torrent nevazan exportTorrentWizard.process.inputfilebad.message=Greska dostupa fajla: exportTorrentWizard.process.outputfileexists.title=Fajl vec postoji exportTorrentWizard.process.outputfileexists.message=Cilj vec postoji - prepisati? exportTorrentWizard.process.torrentfail.title=Citanje Torrenta pogresno exportTorrentWizard.process.exportfail.title=Iznos Torrenta nemoguc exportTorrentWizard.process.unknownfail.title=Nepoznata greska importTorrentWizard.title=Unesi XML Torrent importTorrentWizard.torrentfile.title=Odabranje Torrent importTorrentWizard.torrentfile.message=Odabrati Torrent za unos importTorrentWizard.torrentfile.path=Put importTorrentWizard.torrentfile.browse=Pretrazi importTorrentWizard.torrentfile.invalidPath=Nevazan Torrent importTorrentWizard.importfile.title=Ubacite unosni fajl importTorrentWizard.importfile.message=Izaberite fajl za unos importTorrentWizard.importfile.path=Put importTorrentWizard.importfile.browse=Potrazi importTorrentWizard.importfile.invalidPath=Unosni fajl nevazan importTorrentWizard.finish.title=Zavrseno importTorrentWizard.finish.message=Unos uspijesno zavrsen importTorrentWizard.process.inputfilebad.title=Pogresan unosni fajl importTorrentWizard.process.inputfilebad.message=Greska pristupa unosnog fajla: importTorrentWizard.process.outputfileexists.title=Fajl postoji importTorrentWizard.process.outputfileexists.message=Cilj vec postoji - prepisati? importTorrentWizard.process.torrentfail.title=Pisanje Torrent pogrijesno importTorrentWizard.process.importfail.title=Unos Torrent-a pogrijesan importTorrentWizard.process.unknownfail.title=Nepoznata greska ConfigView.label.bindip=Asociraj za lokalnu IP or interface ConfigView.label.zeronewfiles=Novi fajlovi sa nulama\n - Smanjuje fragmentaciju ConfigView.label.zeronewfiles.tooltip=Smanjuj fragmentaciju ConfigView.section.stats=Statistike ConfigView.section.stats.enable=Omoguci ConfigView.section.stats.defaultsavepath=Folder snimanja Statistike ConfigView.section.stats.choosedefaultsavepath=Odaberite folder za snimanje Statistike ConfigView.section.stats.savefreq=Snimi svakih ConfigView.section.stats.minutes=minuta ConfigView.section.stats.hours=sate ConfigView.section.stats.seconds=sek ConfigView.section.stats.savefile=Ime fajla statistike MyTorrentsView.menu.host=Host... ManagerItem.finishing=Zavrsavanje ConfigView.dialog.choosedefaulttorrentpath=Odaberite glavni folder za torrent fajlove ConfigView.dialog.choosemovepath=Odaberite glavni folder za premjestanje ConfigView.label.movecompleted=Premijesti zavrsene fajlove ConfigView.label.savetorrents=Snimi .torrent fajlove MainWindow.menu.view.mytracker=Moj Tracker MyTrackerView.title.full=Moj Tracker MyTrackerView.name=Ime MyTrackerView.status=Stanje MyTrackerView.status.started=U toku MyTrackerView.status.stopped=Zaustavljeno MyTrackerView.peers=Klijenti MyTrackerView.seeds=Seed-ovi MyTrackerView.announces=Objavljenje MyTrackerView.uploaded=Poslano MyTrackerView.downloaded=Skinuto MyTrackerView.left=Ostalo ConfigView.section.style=Interfejs ConfigView.section.style.useCustomTabs=Upotrebi zatvorljive tipke (potreban restart) MainWindow.menu.view.plugins=Dodatci fileDownloadWindow.saveTorrentIn=Snimi Torrent u fileDownloadWindow.title=Vuze - Preuzimanje Torrenta fileDownloadWindow.downloading=Skinuti od : fileDownloadWindow.status=Stanje : fileDownloadWindow.state_initializing=Inicijalizacija fileDownloadWindow.state_downloading=Preuzimanje fileDownloadWindow.state_error=Greska : MainWindow.menu.file.open.url=URL openUrl.title=Vuze - Otvoir URL openUrl.url=URL: MyTorrentsView.menu.host.error.message=Sljedeca grijeska se desila prije Hosta od torrent-a ConfigView.section.tracker.pollinterval=Interval veze trackera (sek) ConfigView.section.tracker.publishenable=Posalji detalje o torrent-u na "" ConfigView.section.tracker.ip=Eksterna IP trackera ConfigView.section.style.enableXPStyle=Aktiviraj XP stil (potrebno restart) ConfigView.section.tracker.checkip=Provera adrese... ipCheckerWizard.title=Pomocnik provere IP ipCheckerWizard.service=Servis ipCheckerWizard.chooseService=Odaberite IP service provere ipCheckerWizard.explanations=Mozete koristiti ovaj "Pomocnik" za pronalazenje vase spoljasne IP adrese. Ako je vasa IP adresa dinamicna, preporuceno vam da otvorite racun kod Dinamicnog DNS provajdera. Imate listu ispod, upotrebite taj link za otvaranje racuna. Onda popunite vasu IP sa dinamicnom imenom (npr. myhostname.dyndns.org). Trebace vam program koji se automatski mijenjati vasu IP adresu kod tog provajdera. Tako cete moci cuvati Torrent-e i ako se vasa IP adresa promijeni. ipCheckerWizard.service.description=Opis : ipCheckerWizard.progresstitle=Provera IP ipCheckerWizard.checkComplete=Pronadjene IP : ipCheckerWizard.checkFailed=Greska, razlog : wizard.tracker.local=Upotrebi Tracker od Azureusa wizard.tracker.external=Upotrebi spoljasni Tracker wizard.tracker.howToLocal=\tIci u 'Konfiguracija>Tracker' da se startuje wizard.announceUrl=URL objave : IPChecker.external.service.discoveryvip.description=Discoveryvip - IP adresa provera IPChecker.external.httpinvalidresponse=HTTP odgovor nevazan IPChecker.external.loadingwebpage=Ucitavanje web lista IPChecker.external.analysingresponse=Analiza odgovora IPChecker.external.addressextracted=Uzeta IP adresa IPChecker.external.httploadfail=Ucitavanje nemoguce IPChecker.external.timeout=Proslo vreme IPChecker.external.ipnotfound=IP adresa nije pronadjena ConfigView.section.tracker.pollintervalincby=Povecaj od ConfigView.section.tracker.pollintervalincper=Svaki 'n' klijenta splash.loadingImages=Citanje Slika splash.initializeGui=Inicijalizacija glavnog prozora splash.openViews=Otvaranje Izgleda splash.plugin=Otvaranje dodatka : configureWizard.nat.tooManyPorts=Previse portova za probu (max 9) ConfigView.section.color=Boja Tema MyTorrentsView.menu.publish=&Publish... MyTrackerView.status.published=Postavljeno MyTrackerView.completed=Zavrseno MainWindow.menu.file.open.torrentnodefault=Fajl .torrent (bez standardnog snimanja) wizard.comment=Komentar ConfigView.label.movetorrent=Premijesti .torrent ConfigView.section.file.decoder.label=Standardno kodiranje kada treba odabranje ConfigView.section.file.decoder.nodecoder=Nijedan IPChecker.external.service.no-ip.description=Provajder DNS dinamicnih i staticnih\n(ni jedan besplatan servise provere IP) ConfigView.section.tracker.publicenable=Omoguci eksterni Torrent # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Pokazuje broj dostupnih kopija.\nAko je desni broj manji od 1, ne vidite celu kopiju. GeneralView.label.trackerurl.tooltip=Kliknuti za kopiju url u clipboard GeneralView.label.trackerurlopen.tooltip=Kliknuti za otvaranje glavnog lista trackera # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Obnovi GUI svakih ConfigView.section.style.graphicsUpdate=Obnovi graficke trake svaki N GUI obnove ConfigView.section.style.reOrderDelay=Uredi kolone svake N GUI obnove [0: nikada] ConfigView.section.style.reOrderDelay.never=Nikada ConfigView.section.logging=Izvijestaj ConfigView.section.logging.enable=Omoguci izvijestaj u fajl ConfigView.section.logging.logdir=Folder izvijestaja ConfigView.section.logging.choosedefaultsavepath=Molimo vas izaberite folder za snimanje GeneralView.label.updatein.querying=pitanje... configureWizard.nat.sharePort=Koristi jedan dolazeci port za sve Torrent-e ConfigView.section.logging.maxsize=Velicina izvijestaja ConfigView.section.tracker.passwordenableweb=Omoguci sifru na web tracker ConfigView.section.tracker.passwordenabletorrent=Omoguci sifru na Torrent ConfigView.section.tracker.username=Ime korisnika ConfigView.section.tracker.password=Sifra columnChooser.title=Odabrati kolone za pokazati columnChooser.move=Mrdati linije za reorganizaciju columnChooser.apply=Uradi columnChooser.columnname=Ime Kolone columnChooser.columndescription=Opis TableColumn.header.shareRatio=Ratio Dijeljenja wizard.operationfailed=Pogrijesna operacija authenticator.title=Prijava Potrebna authenticator.realm=Oblast authenticator.tracker=Tracker authenticator.user=Ime korisnika authenticator.password=Sifra ConfigView.label.allowSendVersion=Vuze salje anonimni broj verzije i mijesani id pri\ntrazenju nove verzije (za statistike). wizard.hint.mode=Pomoc:\tMozete Dovuci/Spusti fajl ili direktorijum na pomocnika\n\tda bi se odabrao wizard.hint.file=Pomoc:\tMozete odabrati jedan fajl sa Dovuci i Spusti wizard.hint.directory=Pomoc:\tMozete odabrati jedan direktorijum sa Dovuci i Spusti MainWindow.menu.help.checkupdate=Proveriti obnovu programa TableColumn.header.down=Skinuto TableColumn.header.up=Poslano ConfigView.section.tracker.passwordenabletorrent.info=Potrebno adaptiran BitTorrent klijent (Npr Vuze ConfigView.section.style.confirmationOnExit=Pokazi potvrdu prije zatvaranja MainWindow.dialog.exitconfirmation.title=Zatvori Vuze MainWindow.dialog.exitconfirmation.text=Dali zelite zatvoriti Vuze TrayWindow.menu.stopalldownloads=Zaustavi sva preuzimanja ConfigView.section.tracker.sslport.info=Videti FAQ za informacije wizard.tracker.ssl=Upotrebi SSL ConfigView.label.playdownloadfinished=Odsvirati zvuk kada je preuzimanje zavrseno TableColumn.header.pieces=Dijelovi TableColumn.header.pieces.info=Graficka traka pokazuje delove koji su skinuti TableColumn.header.completion=Zavrsavanje TableColumn.header.completion.info=Graficka representacija od % skinutih ConfigView.section.style.showdownloadbasket=Pokazi korpu preuzimanja (Drag and Drop .torrents) ConfigView.section.style.alwaysShowTorrentFiles=Uvijek pokazi torrent fajlove u Detalji/Fajlovi wizard.multitracker=Dodaj Multi-Tracker info Torrentu wizard.multitracker.title=Multi-Tracker wizard.multitracker.configuration=Konfiguracija Multi-Tracker wizard.multitracker.new=Nov... wizard.multitracker.edit=Editiraj... wizard.multitracker.delete=Izbrisi wizard.multitracker.group=Grupa Trackera wizard.multitracker.edit.title=Editor Multi-Tracker wizard.multitracker.edit.name=Ime wizard.multitracker.edit.save=Snimi wizard.multitracker.edit.newgroup=Nova grupa wizard.multitracker.edit.deletegroup=Izbrisi wizard.multitracker.edit.newtracker=Nov Tracker wizard.multitracker.edit.deletetracker=Izbrisi wizard.multitracker.edit.edit=Editiraj wizard.addingmt=Dodavanje Multi-Tracker info wizard.multitracker.noannounce=URL objavljenja nije u vasoj listi trackera MyTorrentsView.menu.recheck=Natijeraj Provijeru iconBar.showDownloadBar.tooltip=Pokazi traku preuzimanja iconBar.start.tooltip=Pokreni iconBar.stop.tooltip=Zaustavi iconBar.remove.tooltip=Brisi iconBar.openNoDefault.tooltip=Otvori .torrent (bez standardnog snimanja) iconBar.openURL.tooltip=Otvori URL iconBar.openFolder.tooltip=Otvori folder iconBar.new.tooltip=Napravi Torrent iconBar.up.tooltip=Premijesti gore iconBar.down.tooltip=Premijesti dole iconBar.run.tooltip=Otvori iconBar.publish.tooltip=Publikacija MyTorrentsView.menu.editTracker=Editiraj URL trackera GeneralView.menu.selectTracker=Odabrati ConfigView.section.stats.xslfile=Ime XLS fajla ConfigView.section.stats.xslfiledetails=Dodati u statistike sa ConfigView.label.savetorrentbackup=Bekap Fajla ConfigView.section.tracker.forceport=Natijeraj spoljasne torrent-e na standardni port ConfigView.section.ipfilter.allow=OMOGUCI IP domasaj (standardno je BLOKIRANO) ConfigView.section.ipfilter.list.inrange=je u podrucje ConfigView.section.ipfilter.list.notinrange=nije ni u jedno podrucje ConfigView.section.ipfilter.list.title=Lista blokiranih IP ConfigView.label.allowsameip=Dozvoli vise konekcija sa iste IP ConfigView.label.allowsameip.tooltip=Omoguciti samo ako POTREBNO.\nZastita protiv leecher (kada onemoguceno). ManagerItem.superseeding=Super-Seed ConfigView.label.userSuperSeeding=Koristi Super Seed uzorak PeersView.uniquepiece=Dijelovi (Super-Seed Mode) PeersView.uniquepiece.none=Nula PeersView.timetosend=Vreme za ponovo slanje delova (Mod Super-Izvor) ConfigView.section.style.addurlsilently=Otvoriti tiho URL (bez potvrde) ConfigView.section.style.addurlsilently.tooltip=Paznja: ako aktivno glaavni prozor nece se pojaviti!\nAko izgubite ikonu Azureusa, onemoguciti opciju. ConfigView.section.file.decoder.prompt=Uvek pitati kada je kodiranje potrebno ConfigView.section.file.decoder.prompt.tooltip=Pokazati prozor kada je kodiranje potrebno MyTorrentsView.menu.moveTop=Prvi MyTorrentsView.menu.moveEnd=Zadnji ConfigView.label.moveonlyusingdefaultsave=samo ako u glavnom data folderu ConfigView.label.moveonlyusingdefaultsave.tooltip=Premestiti samo ako je preuziman fajl u standardnom direktorijumu ConfigView.label.watchtorrentfolder=Automatski unesi nove .torrent fajlove ConfigView.label.watchtorrentfolder.tooltip=Gledaj za nove .torrent fajlove regularno ConfigView.label.watchtorrentfolderinterval=interval ConfigView.label.watchtorrentfolderinterval.tooltip=Interval izmedju pretrage ConfigView.dialog.choosewatchtorrentfolderpath=Odaberite glavni folder za unos .torrent fajlova ConfigView.label.startwatchedtorrentsstopped=Pokretanje zaustavljeno ConfigView.label.startwatchedtorrentsstopped.tooltip=Dodaj nove .torrente u ZAUSTAVLJENOM statusu ConfigView.section.plugins=Dodatci wizard.maketorrent.filesize=Velicina fajla wizard.maketorrent.piececount=Broj Dijelova wizard.maketorrent.piecesize=Velicina dijela wizard.maketorrent.auto=automatski MainWindow.menu.view.stats=Statistike SpeedView.title.full=Statistike SpeedView.downloadSpeed.title=Brzina preuzimanja SpeedView.uploadSpeed.title=Brzina Slanja ConfigView.section.style.useSIUnits=Upotrebi IEC meru (KB -> KiB itd.) iconBar.top.tooltip=Premijesti na vrh iconBar.bottom.tooltip=Premijesti na kraj TableColumn.header.health=Zdravlje MyTorrentsView.menu.health=O Zdravlju health.explain.grey=Torrent nije pokrenut (download ili upload) health.explain.red=Download, znaci da niste prikljuceni na nijedan klijent health.explain.blue=Ako ste seed, znaci da nijedan klijent nije prikljucen, ako preuzimate prikljuceni\n ste ali tracker ne odgovara health.explain.yellow=Tracker ok, klijenti su prikljuceni, ali ni jedna ulazna veze. Moguce je da imate NAT problem\nako se nastavi health.explain.green=Sve funkcionise kako treba. ConfigView.section.style.alwaysRefreshMyTorrents=Uvijek obnovi 'Moji .torrent' ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Opcija obnavlja 'Moji .torrent' i ako prozor nije pokaza (korisno za neki mirc dodatci) # #2.0.7.0 # security.certtruster.title=Upozorenje certifikata sigurnosti security.certtruster.intro=Certifikat je od firme kojoj ne vijerujete security.certtruster.resource=Resurs: security.certtruster.issuedto=Za: security.certtruster.issuedby=Od: security.certtruster.prompt=Dali zelite da povijerujete? security.certtruster.yes=Da security.certtruster.no=Ne ConfigView.section.tracker.torrentsperpage=Koliko torrent-a na listi ? (0 neograniceno) MainWindow.menu.file.share=Dijeli MainWindow.menu.file.share.file=Fajl... MainWindow.menu.file.share.dir=Folder... MainWindow.menu.file.share.dircontents=Sadrzaj foldera... MainWindow.menu.file.share.dircontentsrecursive=Sadrzaj foldera (rekursivno)... MainWindow.dialog.share.sharefile=Odaberite fajlove za dijeljenje MainWindow.dialog.share.sharedir=Odaberite folder za dijeljenje MainWindow.dialog.share.sharedircontents=Odaberite sadrzaj za dijeljenje MainWindow.dialog.share.sharedircontents.recursive=Rekursivno plugin.sharing.download.remove.veto=Preuzimanje je razdvojeno. Ako se zaustavi treba\nda se izbrisu pogrami koje dijele to preuzimanje: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Glavno ConfigView.label.prioritizefirstpiece=Prioritet za prva parcica fajla ConfigView.label.prioritizefirstpiece.tooltip=Proba da preuzima prvo pocetak fajla.\nMoze da omoguci pregled fajla. ConfigView.section.file.confirm_data_delete=Potrvdi pre brisanja podataka ConfigView.section.file.confirm_data_delete.tooltip=Potvrdi kada je korisceno "Skini i izbrisi..." TrayWindow.menu.startalldownloads=Start sva preuzimanja sharing.progress.title=Napredak dijeljenja sharing.progress.hide=Sakri MainWindow.menu.view.myshares=Moje Dijeljenje MySharesView.title.full=Moje dijeljenje MySharesView.name=Ime MySharesView.type=Tip MySharesView.type.file=Fajl MySharesView.type.dir=Folder MySharesView.type.dircontents=Sadrzaj foldera MySharesView.type.dircontentsrecursive=Sadrzaj foldera (rekursivno) MySharesView.menu.remove=Brisi ConfigView.section.tracker.extensions=Ekstenzije ConfigView.section.tracker.sendpeerids=Posalji broj klijenta kojim preuzimaju ConfigView.section.tracker.enableudp=Omoguci UDP za protokol trackera plugin.sharing.torrent.remove.veto=Registracija Trackera je rezultat deljenja.\nDa se skine preuzimanje, potrebno je skinuti asocirano dijeljenje: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Preuzimanje nemoze da se zaustavi posto nije zavrseno plugin.sharing.remove.veto=Ovo dijeljenje je sadrzaj od podeljenog foldera, i nemoze da se izbrise.\n Treba da se izbrise glavno dijeljenje GeneralView.label.hash.tooltip=Kopirati hash u clipboard ConfigView.section.tracker.maxpeersreturned=Max peers ponovo poslano (0: neograniceno) ConfigView.label.serverport=Ulazni TCP port configureWizard.nat.server.tcp_listen_port=Incomming TCP Port ConfigView.section.sharing=Dijeljenje ConfigView.section.sharing.usessl=Upotrebi SSL za deljenje (potrebno konfiguracije trackera) ConfigView.section.style.dropdiraction=Klizaj-pomeri za direktorijume ConfigView.section.style.dropdiraction.opentorrents=Otvori Torrent ConfigView.section.style.dropdiraction.sharefolder=Folder dijeljenja ConfigView.section.style.dropdiraction.sharefoldercontents=Dijeljen sadrzaj # # 2.0.7.x # Categories.all=Sve Categories.uncategorized=Bez kategorije CategoryAddWindow.message=Unesi ime nove kategorije CategoryAddWindow.title=Dodaj novu kategoriju ConfigView.label.autoSeedingIgnoreInfo=Ignorirani torrent-i idu na kraj liste. Nisu pokrenuti automatski. Pravila "Ignorirati" ne vaze za Torrent "Prvi Prioritet".\nOsim suprotno, koristite cifru 0 za ignoriranje pravila. ConfigView.label.directory=Folder ConfigView.label.disconnetseed.tooltip=Kada seedam torrent, iskljuci svaki klijent koji su takodje seed.\nNemoraju da se prikljuce kod vas. ConfigView.label.ignoreCase=Ignorisati "Case" ConfigView.label.ignoreSeeds=Ignorisati Torrent sa najmanje od ConfigView.label.importdirectory=Folder Unosa ConfigView.label.minPeersToBoostNoSeeds.tooltip=Torrent bez seed-a ili sa manje nego unijetog ce biti postavljen na\n kraju reda. ConfigView.label.minPeersToBoostNoSeeds=Smanji "Mijesto seed-a" za Torrent bez seeda ili manje od ConfigView.label.minSeedingTime.tooltip="Mesto Izvora" moze se puno menjati za kratko vreme, ponakada sa pokretanjem Torrent pa zaustavljenje odma posle. To olaksava problem sa nateranjem\nda Torrent ostaje izvor za neko vreme. Moze se rucno zaustaviti. ConfigView.label.minSeedingTime=Minimalni broj seed-a u sekundama ConfigView.label.minSpeedForActiveDL.tooltip=Red preuzimanja je upotrebljeno u prvih 30 sekunde posle\npokretanja nezavrsenog Torrent. ConfigView.label.minSpeedForActiveDL=Ne racunaj Torrent koji upotrebljava red preuzimanja sa brzinom ispod ConfigView.label.peers=klijenta ConfigView.label.queue.debuglog=Izvestaj debag informacije ConfigView.label.queue.debuglog.info=Doda debug info u konzoli/izvestajni fajl.\nSifra debug info za stanjem Torrent i zasto je/nije poceo/stavljen u red. ConfigView.label.queue.minQueueingShareRatio=Ne zaustavljati ili staviti u cekanje Torrent dok deljenje nije ConfigView.label.ratio=odnos ConfigView.label.removeOnStop=Skinuti Torrent sa liste kada se zavrsi automatski ConfigView.label.savedirectory=Direktorijum snimanja ConfigView.label.seeding.autoReposition.tooltip=Ako aktivno, red Torrent (kolona Broj) ce se promeniti da bude ista kao "Red Izvora". Korisno ako\nne zelite da vidite broj reda ali zelite da znate koji je red pokretanja zavrsenih Torrent. ConfigView.label.seeding.autoReposition=Namesti Torrent zavisnosti od "Red Izvora" ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Cesto Torrent sa malo izvora ali puno klijenta nemaju celu kopiju u klijentima. Onda nemoze da se kaze da ima\ncela kopija ( i tako smanjiti prioritet Torrent) ConfigView.label.seeding.fakeFullCopySeedStart=samo za Torrent sa najmanje ConfigView.label.seeding.ignore=Ignorisati Pravilo ConfigView.label.seeding.ignore0Peers=Ignorisati Torrent sa 0 klijenta ConfigView.label.seeding.ignoreRatioPeers=Ignorisati Torrent sa najmanje 1 izvor za ConfigView.label.seeding.ignoreShareRatio=Ignorisati Torrent sa deljenjem od ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorisati Torrent i\nako "Prvi Prioritet" vazi ConfigView.label.seeding.ignore.header.rule=Pravilo ConfigView.label.seeding.ignore.header.value=Vrednost ConfigView.label.seeding.firstPriority.info=Torrent "Prvi Prioritet" su uvek na pocetku liste. Torrent stavljeni kao "Nijedan" ili "Privremena Rotacija" koji odgovaraju na osobine\n "Prvi Prioritet" nece biti zaustavljeni i pauzirani automatski. Torrent "Prvi Prioritet" uzece mesto preuzimanja u isto vreme ako je potrebno. ConfigView.label.seeding.firstPriority.FP=Prva prednost ConfigView.label.seeding.firstPriority=Prvi Prioritet za Torrent sa ConfigView.label.seeding.firstPriority.following=sledeceg: ConfigView.label.seeding.firstPriority.shareRatio=Deljenje manje od ConfigView.label.seeding.firstPriority.seedingMinutes=Proslo vreme od "Preuzimanje" na "Izvor" ConfigView.label.seeding.firstPriority.DLMinutes=Vreme proslo od preuzimanje ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Kada se postavi da imao kao cela kopija svakih X klijenta, smanjuje se mesto Torrent sa puno klijenta.\nTi Torrent imaju generalno puno trafike.\nTo ne menja prikaz izvora. ConfigView.label.seeding.numPeersAsFullCopy=Kao da ima cela kopija svakih\n(0 : nikada) ConfigView.label.seeding.preferLargerSwarms.tooltip=Ako delite Torrenti sa "Blokirani" klijenti, koristite naj koriscene. Ako delite Torrenti sa velikom dostupnosti\nupotrebite manje koriscene. ConfigView.label.seeding.preferLargerSwarms=Kada Torrenti imaju isto mesto, koristiti vise upotrebljen. ConfigView.label.seeding.rankType.none.tooltip=Broj od kolone 'Broj' ConfigView.label.seeding.rankType.none=Nista ConfigView.label.seeding.rankType.peerSeed.options=Opcije "postotak klijent:izvor" ConfigView.label.seeding.rankType.peerSeed.tooltip=Veci postotak = Vece mesto ConfigView.label.seeding.rankType.peerSeed=Postotak klijent:izvor ConfigView.label.seeding.rankType.seed.fallback=Vratiti na postotak klijent:izvor posle\n(0 : nikada) ConfigView.label.seeding.rankType.seed.options=Opcije "broj izvora samo" ConfigView.label.seeding.rankType.seed.tooltip=Malo izvora = vece mesto ConfigView.label.seeding.rankType.seed=Broj izvora samo ConfigView.label.seeding.rankType.timedRotation.tooltip=Torrenti zavrseni i pauzirani postace izvor jedan po jedan.\nVreme izvora zavisi od 'Minimalno Vreme Izvora' ConfigView.label.seeding.rankType.timedRotation=Povremena Rotacija ConfigView.label.seeding.rankType.tooltip=Torrenti sa najvece mesto su pokrenuti automatski.\nAko Torrent uzme vece mesto, drugi Torrent se zaustavi i stavi se u cekanje.\n\nSamo Torrenti "Ceka" mogu se automatsko pokrenuti.\nNikada zaustavljen Torrent neci biti automatski pokrenut. ConfigView.label.seeding.rankType=Za automatsko pokretanje, namesti zavrseni Torrenti zavisnosti od: ConfigView.label.stopAfterMinutes=Kada postanem seed, zaustavi posle ConfigView.label.switchpriority.tooltip=Manji prioritet smanjuje brzinu slanja za torrent. ConfigView.pluginlist.info=Sledeci dodatci su nadjeni. Neki dodatci mogu da nemaju tipke za konfiguraciju. ConfigView.pluginlist.noplugins=Nijedan dodatak nije pronadjen. ConfigView.section.pluginslist=Lista ConfigView.section.queue.seeding=Seed-anje ConfigView.section.queue.seeding.autoStarting=Auto pokretanje ConfigView.section.queue.seeding.ignore=Pravila "Ignorisati" ConfigView.section.queue.seeding.firstPriority=Prvi Prioritet ConfigView.section.queue.main=Glavno ConfigView.section.queue=Red ConfigView.section.torrents=Torrenti ConfigView.text.all=svakih ConfigView.text.hours=sati ConfigView.text.ignoreRule=Ignorisi Pravila ConfigView.text.ignore=Ignorisi ConfigView.text.minutes=minuta ConfigView.text.neverIgnore=Nikada Ignorisati ConfigView.text.any=nijedan DownloadManager.error.datamissing=Fali podatke MainWindow.menu.file.open.torrentforseeding=Fajl .torrent (za izvor) MainWindow.menu.language.refresh=Obnovi ManagerItem.forced=Natijerano ManagerItem.queued=U redu MySeedersView.header=Zavrseni Torrenti TableColumn.header.availability.info=Broj cijelih kopija vidjeno TableColumn.header.availability=Dostupno TableColumn.header.category=Kategorija MyTorrentsView.header=Torrent Nezavrsen TableColumn.header.maxuploads=Max broj upload-a MyTorrentsView.menu.category.delete=Izbrisati Kategoriju MyTorrentsView.menu.forceStart=Natijeraj start MyTorrentsView.menu.queue=Red MyTorrentsView.menu.setCategory.add=Dodaj kategoriju.. MyTorrentsView.menu.setCategory=Postavi kategoriju TableColumn.header.savepath=Put snimanja TableColumn.header.SeedingRank=Red izvora TableColumn.header.totalspeed.info=Brzina od svih klijenti koji su prikljuceni TableColumn.header.totalspeed=Ukupna brzina splash.initializePlugins=Inicijalizacija dodatka StartStopRules.0Peers=0 klijenta StartStopRules.waiting=Ceka StartStopRules.firstPriority=Prvi Prioritet ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Dijeli sadrzaj (rekursivno) DownloadManager.error.unabletostartserver=Nemoguce pokrenuti server - provijeri konfiguraciju ulaznog port-a / prava firewall-a da bi program radio kao server. GeneralView.label.creationdate=Kreiran : ConfigView.section.tracker.announcescrapepercentage=Interval "Scrape" kao %godine objave\ne.g. 200 = 2:1. 0 = klijent odlucuje ManagerItem.stopping=Zaustavljanje ConfigView.section.tracker.announcecacheperiod=Kes objave (ms) ConfigView.section.tracker.scrapecacheperiod=Kes od "Scrape" (ms) ConfigView.section.tracker.scrapeandcache="Scrape" i kes ConfigView.section.tracker.announcecacheminpeers=Nivo klijenta za aktiviranje kesa za objavu MyTrackerView.scrapes="Scrapes" fileDownloadWindow.retry=Ponovi MyTrackerView.bytesinave=Average In MyTrackerView.bytesoutave=Average Out ConfigView.section.file.max_open_files=Maks fajla otvoreni za citanje/pisanje\n0 = neograniceno ConfigView.section.file.max_open_files.tooltip=Korisno ako preuzimate Torrenti sa puno fajlova, i postizete granicu upotrebe fajlova od vaseg sistema. ConfigView.section.proxy=Proxy Opcije ConfigView.section.proxy.enable_proxy=Aktiviraj proxy ConfigView.section.proxy.host=host ConfigView.section.proxy.port=Prikljucak ConfigView.section.proxy.username=Korisnik ConfigView.section.proxy.password=Sifra ConfigView.section.proxy.enable_socks=Imam proxy SOCKS wizard.createtorrent.extrahashes=Dodati "hash" za druge mreze (npr. Gnutella2, eDonkey2000) GeneralView.label.connected=Prikljuceno GeneralView.label.in_swarm=Ukupno ManagerItem.initializing=Inicijalizacija AlertMessageBox.error=Greska AlertMessageBox.warning=Paznja AlertMessageBox.comment=Komentar AlertMessageBox.information=Informacije SharedPortServer.alert.selectorfailed=Nemoguce slusanje ulaznih podataka.\nProvijerite da firewall propusta da java(w).exe se pokrece kao 'server' Tracker.alert.listenfail=Nemoguca konekcija na port-u %1.\nProvijerite da drugi program ne koristi ovaj port.\nProvijerite da drugi Vuze nije vec startovan. DiskManager.alert.movefileexists=Grijeska premijestanja zavrsenih fajla\nFajl %1 vec postoji u folderu DiskManager.alert.movefilefails=Grijeska premijestanja zavrsenih fajla\nPremestanje %1 fajla pogrijesno, %2 DiskManager.alert.movefilerecoveryfails=Grijeska nastavka posle pogrijesnog premijestanja\nPovracenje fajla %1 nemoguce, %2 ConfigView.section.tracker.logenable=Upisi periodicne statistike u 'tracker.log' SpeedView.stats.title=Stat SpeedView.stats.total=Ukupno SpeedView.stats.session=Ova sesija SpeedView.stats.downloaded=Skinuto SpeedView.stats.uploaded=Poslano SpeedView.stats.uptime=Radi vec (sati) AutoMigration.useralert=Rezultat automatske promijene fajlova i foldera od Vuze \n\n%1\n%2POGRIJESNE PROMIJENE TREBAJU DA SE URADE RUCNO U KONFIGURACIJI. # # > 2.0.8.0 # OpenTorrentWindow.title=Otvori .torrent OpenTorrentWindow.message=Eksperimentalno OpenTorrentWindow.addFiles=Dodaj fajl OpenTorrentWindow.dataLocation=Put snimanja podataka: OpenTorrentWindow.startMode=Dodaj mode OpenTorrentWindow.startMode.queued=Ceka OpenTorrentWindow.startMode.stopped=Zaustavljen OpenTorrentWindow.startMode.forceStarted=Natijeraj Start OpenTorrentWindow.addPosition=Mijesto reda OpenTorrentWindow.addPosition.first=Prvi OpenTorrentWindow.addPosition.last=Zadnji TableColumn.header.remaining.info=Ostalo za Preuzimanje TableColumn.header.remaining=Ostalo ConfigView.section.tracker.enablecompact=Omoguci kompaktni protokol objave ConfigView.section.tracker.enablekey=Omoguci slanje kljuca trackeru za vecu sigurnost ConfigView.section.file.perf=Opcije Performanse ConfigView.section.file.perf.explain=Paznja - Lose promene parametra moze promeniti performanse preuzimanja. Restart potrebno.\nAko imate "out of memory" ograniciti konekcije po Torrent (Konfig Transfer) ConfigView.section.file.max_open_files.explain=Otvoriti mnogo fajla u isto vreme moze uraditi problema zavisno od granice sistema.\nOvo ogranicava broj otvorenih fajla istovremeno popup.error.hide=Sakrij popup.error.details=Detalji ConfigView.section.style.colorOverrides=Promijena boja ConfigView.section.style.colorOverride.progressBar=Traka naprednosti ConfigView.section.style.colorOverride.error=Greska MainWindow.status.tooOld=je stari, update ga. ConfigView.section.style.colorOverride.warning=Paznja ConfigView.section.style.colorOverride.altRow=Linije ConfigView.section.file.save.peers.enable=Snimi Izvor veze za brz nastavak ConfigView.section.file.save.peers.max=Maks Izvor za snimljenje [0: neograniceno] ConfigView.section.file.save.peers.pertorrent=po Torrent ConfigView.label.max_peers_per_torrent=Max broj prikljucka po Torrent-u [0: neograniceno] ConfigView.label.max_peers_total=Max broj globalnih prikljucka [0: neograniceno] ConfigView.section.style.colorOverrides.reset=Povrati Boju ConfigView.section.language.info=Ako je omoguceno, provijera update-a ce se vrsiti na svako pokretanje Azureusa. ConfigView.section.language.enableUpdate=Omoguci Web Update ConfigView.section.language.UpdateNow=Update sada! Button.revert=Povrati MyTorrentsView.menu.changeDirectory=Promijeni Data folder GenericText.column=kolone MyTorrentsView.menu.thisColumn.remove=Skini Kolonu MyTorrentsView.menu.thisColumn.toClipboard=Kopiraj Tekst u 'Clipborad' ConfigView.download.abbreviated=Sk: ConfigView.complete.abbreviated=Z: TableColumn.header.secondsseeding=Vr.Dijeljenja TableColumn.header.secondsseeding.info=vreme koliko ste bili izvor. TableColumn.header.secondsdownloading=Vr.Preuzimanja TableColumn.header.secondsdownloading.info=vreme koji ste preuzimali. ConfigView.section.tracker.udpversion=UDP verzija (1 ili 2) window.updateswt.title=SWT je prestari! window.updateswt.text=SWT verzija je stara!\nSWT je grafika upotrebljena od Azureusa, i verzija je stara za pokretanje zadnje verzije Azureusa. OK za obnovu SWT. window.updateswt.status=Stanje window.updateswt.failed=Obnova pogrijesna, klikni OK da se ponovi. window.updateswt.status.downloading.updater=Preuzimanje modula obnove window.updateswt.status.finding=Nalazak zadnje SWT verzije window.updateswt.status.downloading=Preuzimanje zadnje SWT verzije window.updateswt.status.done=Ponovi Start window.updateswt.ok=Ok window.updateswt.cancel=Anuliraj swt.updater.downloader.downloading=Skinuti SWT sa swt.updater.urlsgetter.downloading=Dobiti Ogledala sa swt.updater.urlsgetter.platform=SWT za : window.updateswt.ignore=Ignorisi ConfigView.section.style.useFancyTabs=Lepsi Tipci splash.initializeGM=Inicijalizacija Globalni Torrent Menadzer splash.firstMessageNoI18N=(: Vuze :) MyTorrentsView.menu.thisColumn.sort=Uredi Scrape.status.ok=Scrape Ok Scrape.status.error=Scrape Greska: Scrape.status.error.nohash=Nedostaje Hash odgovora. Scrape.status.error.invalid=Pogresan Odgovor. Scrape.status.nextScrapeAt=Sledeci scrape u %1 Scrape.status.initializing=Cekanje 'Scrape' ConfigView.label.minSpeedForActiveSeeding=Ne broj zavrseni .torrent kao da koristi slot ako je brzina ispod MainWindow.menu.view.irc.moved=Irc nije dodatak, videti http://azureus.sourceforge.net/plugin_list.php MyTrackerView.webui.contextmenu.copyurl=Kopiraj URL torrent u clipboard ConfigView.section.file.torrent.ignorefiles=Fajlove da se ignorisu pri kreaciji torrenta\nnpr .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignorisanje fajla ConfigView.section.style.useUnitsRateBits=Koristi bits umijesto bytes (KiB/s->Kibit/s itd.) ConfigView.section.interface.resetassoc=Resetuj asocijacije (.torrent) ConfigView.section.interface.resetassocbutton=Resetuj ConfigView.section.interface.checkassoc=Provijeri asocijacije na startu dialog.associations.title=Provijera asocijacije Button.yes=Da Button.no=Ne ConfigView.label.seeding.autoStart0Peers=Auto Start zavrseni torrent sa 0 deljenja ConfigView.label.seeding.autoStart0Peers.tooltip=Ukljuci da tracker uvek lista izvora za 0 deljenja. dialog.associations.prompt=Vuze nije standardni program za BitTorrent fajlove.\nDali zelite da asocirate .torrent fajlove sa Vuze dialog.associations.askagain=Provijeri na startu ConfigView.section.plugins.update=Update Dodatka Plugin.pluginupdate.enablecheck=Omoguci provijeru update dodatka plugins.basicview.status=Status plugins.basicview.activity=Aktivnost plugins.basicview.progress=Napredak plugins.basicview.log=Izvijestaj ConfigView.label.maxdownloadspeed=Max brzina preuzimanja KB/S [0: noegraniceno] splash.loadingTorrent=Loading Torrent splash.of=od ConfigView.section.plugins.irc=Irc UpdateWindow.title=Vuze Obnova UpdateWindow.header=Sledeci komponenti su potrebni obnova : UpdateWindow.columns.install=Instal UpdateWindow.columns.name=Ime UpdateWindow.columns.version=Verzija UpdateWindow.columns.size=Velicina UpdateWindow.cancel=Anuliraj UpdateWindow.quit=Izlaz UpdateWindow.close=Zatvori UpdateWindow.ok=Ok UpdateWindow.restart=Pokreni ponovo UpdateWindow.status.downloading=Preuzimanje UpdateWindow.status.done=Uradjeno UpdateWindow.status.failed=Pogresno UpdateWindow.status.restartNeeded=Restart je potreban ! ConfigView.pluginlist.broken=Slomljen ConfigView.pluginlist.whereToPut=Stavi bilo koji dodatak u njihov folder ispod: ConfigView.pluginlist.whereToPutOr=Za podijeljenje dodatka upotrebi: MainWindow.statusText.checking=Provijeri za Updates TableColumn.header.OnlyCDing4.info=Koliko puta je torrent samo deljen. Izkljuceno kada je preuzimat (i deljen). ConfigView.section.style.alternateTablePainting=Upotrebi drugu metodu za farbanje grafike (restart potreban) UpdateWindow.status.restartMaybeNeeded=Potrebno ponovo pokretanje ConfigView.pluginlist.shared=dijeljeno PeersView.host=Host Ime PeersView.host.info=Host ime izvora, kada dostupno (moze usporiti performanse) MainWindow.menu.help.whatsnew=Sta Novo ConfigView.label.checkonstart=Provijeri dali postoji nova verzija kada se Vuze pokrene ConfigView.label.periodiccheck=Periodicno provijeri za novu verziju ConfigView.label.opendialog=Automatski otvori "Pomocnik" kada je update dostupan MainWindow.updateavail=Klikni ovdje za updates MainWindow.status.latestversionunchecked=Provijera verzije iskljucena GeneralView.label.updatein.stopped=Zaustavljeno StartStopRules.menu.viewDebug=Vidi Info Debaga ConfigView.section.style.doNotUseGB=Ne upotrebi GB velicinu ConfigView.section.style.doNotUseGB.tooltip=Ako unijeto, Vuze ce koristiti MB i ako je velicina veca od 1024MB MainWindow.menu.help.plugins=Dodatci ConfigView.section.plugins.TrackerWeb=Web Tracker ConfigView.section.tracker.enablecategories=Podijeli torrent po kategoriji health.explain.share=Znaci da je torrent ili Host ili izdat ConfigView.section.tracker.createcert=Kreiraj Certifikat ConfigView.section.tracker.createbutton=Kreiraj security.certcreate.title=Kreiraj Certifikat security.certcreate.intro=Dijalog za kreiraje Certifikata security.certcreate.alias=Alijas security.certcreate.strength=Jacina security.certcreate.firstlastname=Prezime i Ime security.certcreate.orgunit=Posao security.certcreate.org=Firma security.certcreate.city=Grad ili Lokacija security.certcreate.state=Drzava ili Provincija security.certcreate.country=2 slova kod zemlje security.certcreate.ok=Kreiraj security.certcreate.cancel=Anuliraj security.certcreate.createok=Kreacija Certifikata uspesno security.certcreate.createfail=Kreacija Certifikata pogresna ConfigView.section.plugins.webui=Swing Web Interfejs ConfigView.section.plugins.xml_http_if=XML/HTTP Interfejs webui.passwordenable=Omoguci sifru webui.user=Korisnik webui.password=Sifra webui.port=Ulaz (*) webui.protocol=Protokol webui.homepage=Glavni List (*) webui.rootdir=Direktorijum Koren (*) webui.rootres=Resursa Korena (*) webui.mode=Nacin (*) webui.mode.info=Mode moze biti\n\t"pun"\t= sve je dozvoljeno (standardno)\n\t"pregled"\t= samo gledanje (i menjanje frekvencije obnove) webui.access=Pristup (*) webui.access.info=Pristup moze biti\n\t"lokalno"\t= prikljucak samo lokalnoj masini\n\t"Svi"\t= pristup bez granice (standardno)\n\tIP\t= npr 192.168.0.2\t\tsamo taj IP\n\tIP1-IP2\t= npr 192.168.0.1-192.168.0.25\tgranice IP GeneralView.label.maxdownloadspeed=Max Preuzimanje Security.keystore.corrupt=Kljuc '%1' nemoguce citati, izbrisati ga i kreirati ponovo/unos certifikat Security.keystore.empty=Kljuc je prazan. Kreirati certifikat (Konfiguracija->Sigurnost) ili uneti postojeci u '%1' webui.restart.info=Promijena parametra sa (*) zahtjeva restart za efekt GeneralView.label.maxdownloadspeed.tooltip=Maks Br Preuzimanja [0: neograniceno] upnp.enable=Omoguci UPnP upnp.info=Universal Plug and Play (UPnP) omogucava automatsko preslikavanje port-a na UPnP usmijerivac. upnp.mapping.dataport=Ulazni port klijentnih podataka upnp.mapping.tcptrackerport=TCP tracker prikljucak upnp.mapping.udptrackerport=UDP tracker prikljucak upnp.alert.differenthost=UPnP: '%1' je rezervisao '%2' - odabrati drugi prikljucak upnp.alert.mappingok=UPnP: Preslikavanje '%1' uradjeno upnp.alert.mappingfailed=UPnP: Preslikavanje '%1' pogresno upnp.alertsuccess=Prijavi uspijesno preslikavanje upnp.alert.lostdevice=UPnP: Izgubljena veza na servisu '%1' na uredjaju UPnP '%2' upnp.grabports=Preslikuj port i ako je vec koristen od strane drugog kompjutera upnp.refresh.label=Obnovi mapazu upnp.refresh.button=Obnovi upnp.alert.mappinggrabbed=UPnP: Preslikavanje '%1' uradjeno - uzeto od '%2' upnp.mapping.tcpssltrackerport=TCP SSL tracker prikljucak upnp.alertothermappings=Prijavi port drugog racunara upnp.alertdeviceproblems=Prijavi probleme sa UPnP uredjajem ConfigView.pluginlist.coreplugins=Dodatci ukljuceni: Peers.column.DLedFromOthers=Od Ostalih Peers.column.DLedFromOthers.info=Kolicina podataka preuzeta od ostalih pri prikljucku Peers.column.UpDownRatio.info=Ratio "Uploaded : Downloaded" Peers.column.UpRatio.info=Ratio "Upload od vas : Upload od ostalih" upnp.releasemappings=Pusti preslikavanje na closedown webui.upnpenable=Omoguci UPnP za ovaj prikljucak (*) ConfigView.section.file.friendly.hashchecking=Lepsa provera hash ConfigView.section.file.friendly.hashchecking.tooltip=Malo sporije, ali bolje za sistem. ConfigView.section.tracker.seedretention=Max deljenja po torrent [0: neograniceno] ConfigView.section.tracker.seedretention.info=Nota: Slanje statistike ce biti izgubljeno za ne-prihvacena dijeljenja ConfigView.section.tracker.port=Omoguci tracker na HTTP port ConfigView.section.tracker.sslport=Omoguci tracker na HTTPS port ConfigView.section.tracker.publicenable.info=Omogucava da drugi kreiraju torrent na vas tracker\nbez hostinga/slanja Button.clear=Brisi MainWindow.IPs.tooltip=Zadnja obnova liste: %1\nBroj filtriranih IP - IP blokirane za sesiju\nDupli klik da se vidi lista. ConfigView.section.ipfilter.list.banned=blokirano zbog slanja pogresnih podataka ConfigView.section.ipfilter.list.baddata=poslao pogresni podatci Button.reset=Resetuj ConfigView.section.ipfilter.bannedinfo=IP koji su poslali pogresni podatci - blokirani ako su prekoracili granicu ConfigView.section.ipfilter.blockedinfo=IP blokirani zbog IP filtera download.removerules.name=Pravila Brisanja download.removerules.unauthorised.info=Torrenti nedozvoljeni su oni kozi sadrze "nije dozvoljeno" ili "nedozvoljeno" u "pogresan odgovor" download.removerules.unauthorised=Auto skini nedozvoljene torrent-e download.removerules.unauthorised.seedingonly=\tSamo ako deli download.removerules.removed.ok=Auto brisanje torrent-a '%1' uspesno. Uradjeno zbog pravila brisanja torrenta. download.removerules.updatetorrents=Skini torrent-i uradi update Azureus-a ako je to potrebno ConfigView.label.defaultstarttorrentsstopped=Svaki novi torrent ubaci u zaustavljenom statusu ConfigView.section.server.enableudp=Omoguci UDP klijentni protokol tracker-a. upnp.mapping.dataportudp=Klijentni UDP tracker port ConfigView.section.file.decoder.showlax=Pokazi najmanja moguca kodiranja ConfigView.section.file.decoder.showall=Razmotri sva moguca kodiranja MainWindow.status.updowndetails.tooltip=Slanje/preuzimanje detalja - desni klik za promijenu TrackerClient.announce.warningmessage=Tracker za '%1' prijavio paznju '%2' ConfigView.section.tracker.natcheckenable=Provijeri 'ulazni prikljucak podatak' i prijavi grijeske Klijentu ConfigView.section.tracker.publishenabledetails=Posalji sve detalje o torrentu ConfigView.section.tracker.publishenablepeerdetails=Posalji peer detalje MyTrackerView.badnat=Losi NAT MyTrackerView.badnat.info=Deljenja/Izvora pogresno proverili NAT, ako omoguceno ConfigView.section.tracker.natchecktimeout=Provijeri Tajmout (sek) ConfigView.section.file.perf.cache.enable=Omoguci Kes Diska ConfigView.section.file.perf.cache.size=Velicina Kesa u %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed ConfigView.label.experimental.osx.kernel.panic.fix=Probni lepak za paniku procesora na 2 cpu OSX [potrebno pokretanje] ConfigView.section.file.truncate.too.large=Iseci postojeci fajlovi koji su preveliki ConfigView.section.file.perf.cache.trace=Prati operacije kesa za dijagnostik ConfigView.section.interface.enabletray=Omoguci System Tray PeerManager.status.error=Greska Stats.title.full=Statistike TransferStatsView.title.full=Transferi CacheView.title.full=Kes CacheView.general.size=Velicina CacheView.general.inUse=Upotrebljeno CacheView.general.title=Info Predmemori CacheView.reads.title=Citano I/O CacheView.reads.fromFile=Od Fajla CacheView.reads.fromCache=Od Kesa CacheView.reads.hits=Udarca CacheView.writes.title=I/O sacuvano CacheView.writes.toCache=Do Kesa CacheView.writes.toFile=Do Fajla CacheView.writes.hits=Udarca CacheView.speeds.title=Brzina Podataka CacheView.speeds.reads=Citano CacheView.speeds.writes=Sacuvano CacheView.speeds.fromCache=Od/Do Kesa CacheView.speeds.fromFile=Od/Do fajla CacheView.reads.#=# CacheView.reads.amount=Kolicina CacheView.reads.avgsize=\u00d8 Velicina openUrl.referrer=Referentni list: openUrl.referrer.info=Potrebno samo za sajtove koji ga traze ConfigView.label.maxuploadspeedseeding=Max KB/S brzina slanja kada seedam [0: neograniceno] ConfigView.label.transfer.ignorepeerports=Ignorisi klijenti sa ovim port-om '(';' odvaja, npr 0;25) ConfigView.section.proxy.enable_socks.peer=Omoguci proxy za izvor (Samo izlaz) ConfigView.section.proxy.peer.informtracker=Informisi tracker za granice ConfigView.section.proxy.socks.version=Verzija SOCKS PiecesView.legend.written=Pisano PiecesView.legend.requested=Pitano PiecesView.legend.downloaded=Preuzeto, ceka pisanje PiecesView.legend.incache=Podatke u kesu PiecesView.typeItem.0=Sporo PiecesView.typeItem.1=Brzo PiecesView.type=Tip authenticator.torrent=torrent ConfigView.section.connection.network.max.simultaneous.connect.attempts=Max simultaneous outbound connection attempts [0: outbound disabled] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Max number of new outbound connection establishments Vuze should attempt any given time.\nNOTE: WindowsXP Service Pack 2 (SP2) imposes a system-wide limit of 10 simultaneous connect attempts.\nDefault value is 8. Value of 0 disables outbound connects entirely. ConfigView.section.file.perf.cache.size.explain=The cache is used to reduce reads from/writes to disk. Unless you are using the java option '-XX:MaxDirectMemorySize' to explicitly set the memory available for cache and network IO use, you should keep this value at least %1 below your maximum VM size. The current maximum VM size is %2. For instructions on how to change this, see MemoryUsage in the wiki on %3. Failure to use sensible settings will result on 'out of memory' errors. More than 32MB of cache is probably overkill. ConfigView.section.tracker.client=Klijent ConfigView.group.override=Prebrisati Opcije ConfigView.section.connection.advanced=Napredno Postavljanje Mreze ConfigView.label.openstatsonstart=Otvori Statistiku pri startu installPluginsWizard.details.loading=Opis se puni, molimo vas pricekajte... Button.abort=prekinuti MainWindow.dialog.restartconfirmation.text=Dali zelite da restart Vuze deletetorrent.message1=Brisete TORRENT od :\n deletetorrent.message2=\nJeste sigurni da zelite nastavi? ConfigView.label.prioritizemostcompletedfiles=Prioritize most completed files ConfigView.section.style.osx_small_fonts=Upotreba mali slova [restartovanje programa potrebno] ConfigView.group.scrape=scrape MyTorrentsView.menu.explore=Prikazi Fajl ConfigView.label.overrideip=Prepisi IP slanu traker-u - Upotrebiti samo\nako znate da vam to treba ! ConfigView.section.connection.group.networks=Mreze ConfigView.section.connection.networks.I2P=I2P mreze window.networkselection.title=biranje mreze window.networkselection.description=Torent : ConfigView.section.connection.peersource.Tracker=Od jednog tracker ConfigView.section.connection.peersource.Plugin=dodato od dodatka ConfigView.section.connection.peersource.Incoming=ulazna veza ConfigView.section.logging.generatediagnostics=Proizvoditi Button.apply=Primeniti Button.close=zatvori window.welcome.title=Dobrodosao kod Vuze %1 #file can be a URL or a path in the jar dht.reseed.label=Normally reseeding of the Distributed Database is not necessary. However, if the number of contacts is low this can be used for re-integratation.\nLeave blank to bootrap off connected peers or enter IP and port to explicitly bootstrap from a known peer. MainWindow.dht.status.disabled=Disabled MainWindow.dht.status.failed=Failed MainWindow.dht.status.initializing=Initializing MainWindow.dht.status.users=%1 Users MainWindow.dht.status.unreachabletooltip=There appears to be a problem with the Distributed Database's port mapping ConfigView.section.logging.loggerenable=dozvoliti protokolisanje VivaldiView.title.full=vivaldi ConfigView.label.backupconfigfiles=Sigurnosna kopija konfiguracijeza vracanje u prvobitno stanje ActivityView.legend.limit=Ograniciti Odnos ActivityView.legend.achieved=Dostici Odnos ActivityView.legend.peeraverage=prosek ActivityView.legend.swarmaverage=Jato Prosek ConfigView.section.mode=nacin rada ConfigView.section.mode.beginner=Pocetnik ConfigView.section.mode.advanced=Napredan ConfigView.section.mode.advanced.wiki.main=Wiki naslovna stranica diagnostics.log_found=Vuze se nije zatvorio kako treba. Proveri %1 zurnal fajl i posaljite Vuze ekipi ako je greska aplikacije. ConfigView.section.connection.serverport.wiki=Dobro odabrane ports Views.plugins.UPnP.title=UPnP ConfigView.section.logging.log0type=Informacije # %1 = "in kbps" or ""; %2 = "upload" or "download" OpenTorrentWindow.torrentLocation=Torrent fajl: Button.moveUp=Premijesti gore Button.moveDown=Premijesti dole # > 2402 # Used for peers which we can't determine. PeerSocket.unknown=Nepoznat ConfigView.label.announceport=Prebrisati tracker obznaniti port iconBar.queue.tooltip=Red MainWindow.menu.help.faq=FAQ MainWindow.menu.help.donate=Dati donaciju ($2,$5,...) azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_zh_CN.properties0000644000175000017500000070740411301156004026104 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=.torrent \u6587\u4ef6 Main.parameter.usage=\u7528\u6cd5\uff1a java org.gudy.azureus2.cl.Main\uff3b\u53c2\u6570\uff3d "\u6587\u4ef6\u540d.torrent" "\u4fdd\u5b58\u76ee\u5f55" Main.parameter.maxUploads=\u6700\u5927\u540c\u65f6\u4e0a\u4f20\u6570\u76ee Main.parameter.maxSpeed=\u6700\u5927\u4e0a\u4f20\u901f\u5ea6 B/s MainWindow.menu.file=\u6587\u4ef6\uff08&F\uff09 MainWindow.menu.file.open=\u6253\u5f00\uff08&O\uff09 MainWindow.menu.file.create=\u65b0\u5efa Torrent \u6587\u4ef6\uff08&C\uff09 MainWindow.menu.file.create.fromfile=\u4ece\u4e00\u4e2a\u6587\u4ef6\uff08&F\uff09 MainWindow.menu.file.create.fromdir=\u4ece\u4e00\u4e2a\u76ee\u5f55\uff08&D\uff09 MainWindow.menu.file.export=\u5bfc\u51fa XML Torrent \u6587\u4ef6\uff08&E\uff09\u2026 MainWindow.menu.file.import=\u5bfc\u5165 XML Torrent \u6587\u4ef6\uff08&I\uff09\u2026 MainWindow.menu.file.closetab=\u5173\u95ed\u6807\u7b7e\u9875\uff08&T\uff09 MainWindow.menu.file.closewindow=\u5173\u95ed\u7a97\u53e3\uff08&W\uff09 MainWindow.menu.file.exit=\u9000\u51fa\uff08&X\uff09 MainWindow.dialog.choose.file=\u9009\u62e9 Torrent \u6587\u4ef6 MainWindow.menu.file.folder=\u76ee\u5f55\uff08&F\uff09 MainWindow.dialog.choose.folder=\u9009\u62e9 Torrent \u6587\u4ef6\u6240\u5728\u76ee\u5f55 MainWindow.menu.view=\u67e5\u770b\uff08&V\uff09 MainWindow.menu.view.show=\u663e\u793a MainWindow.menu.view.mytorrents=\u6211\u7684 Torrent\uff08&M\uff09 MainWindow.menu.view.open_global_transfer_bar=\u4f20\u8f93\u6761 MainWindow.menu.view.configuration=\u9009\u9879\uff08&O\uff09... MainWindow.menu.view.console=\u63a7\u5236\u53f0\uff08&C\uff09 MainWindow.menu.view.irc=IRC\uff08&I\uff09 MainWindow.menu.view.allpeers=\u6240\u6709\u7528\u6237 MainWindow.menu.view.detailedlist=\u8be6\u60c5\u5217\u8868(D) MainWindow.menu.closealldetails=\u5173\u95ed\u6240\u6709\u8be6\u7ec6\u4fe1\u606f\uff08&A\uff09 MainWindow.menu.closealldownloadbars=\u5173\u95ed\u6240\u6709\u8ff7\u4f60\u4efb\u52a1\u6761\uff08&B\uff09 MainWindow.menu.language=\u8bed\u8a00\uff08&L\uff09 ConfigView.section.language=\u8bed\u8a00 MainWindow.menu.window=\u7a97\u53e3\uff08&W\uff09 MainWindow.menu.window.minimize=\u6700\u5c0f\u5316\uff08&M\uff09 MainWindow.menu.window.zoom=\u7f29\u653e\uff08&Z\uff09 MainWindow.menu.window.alltofront=\u6240\u6709\u7a97\u53e3\u7f6e\u524d\uff08&F\uff09 MainWindow.menu.help=\u5e2e\u52a9\uff08&H\uff09 MainWindow.menu.help.about=\u5173\u4e8e Vuze MainWindow.menu.torrent=Torrent\uff08&o\uff09 MainWindow.about.title=\u5173\u4e8e MainWindow.about.section.developers=\u5f00\u53d1\u8005 MainWindow.about.section.translators=\u7ffb\u8bd1\u8005 MainWindow.about.section.system=\u7cfb\u7edf MainWindow.about.section.internet=\u56fd\u9645\u4e92\u8054\u7f51 MainWindow.about.internet.homepage=Vuze \u7684\u4e3b\u9875 MainWindow.about.internet.sourceforge=\u5728 Sourceforge \u9879\u76ee\u4e3b\u9875 MainWindow.about.internet.sourceforgedownloads=Sourceforge \u4e0b\u8f7d MainWindow.about.internet.bugreports=\u9519\u8bef\u62a5\u544a MainWindow.about.internet.forumdiscussion=\u8bba\u575b MainWindow.about.internet.wiki=Vuze Wiki FAQ MainWindow.dialog.choose.savepath=\u9009\u62e9\u4fdd\u5b58\u76ee\u5f55 MainWindow.dialog.choose.savepath_forallfiles=\u9009\u62e9\u6240\u6709\u6587\u4ef6\u7684\u4fdd\u5b58\u76ee\u5f55 MainWindow.status.latestversion=\u6700\u65b0\u7248\u672c MainWindow.status.latestversion.clickupdate=\u70b9\u51fb\u8fd9\u91cc\u66f4\u65b0 MainWindow.status.unknown=\u672a\u77e5 MainWindow.status.checking=\u9a8c\u8bc1\u4e2d MyTorrentsView.mytorrents=\u6211\u7684 Torrents TableColumn.header.name=\u540d\u79f0 TableColumn.header.size=\u5927\u5c0f TableColumn.header.done=\u5b8c\u6210\u7387 TableColumn.header.done.info=\u5f53\u524d\u4efb\u52a1\u5b8c\u6210\u767e\u5206\u5ea6 TableColumn.header.status=\u72b6\u6001 TableColumn.header.status.info=\u76ee\u524d Torrent \u5728\u505a\u7684\u4e8b\u60c5 TableColumn.header.seeds=\u79cd\u5b50 TableColumn.header.seeds.info=# \u5df2\u8fde\u63a5\u5230\u79cd\u5b50\u4e2a\u6570\uff08# \u603b\u79cd\u5b50\u6570\uff09 TableColumn.header.peers=\u7528\u6237 TableColumn.header.peers.info=# \u5df2\u7ecf\u8fde\u63a5\u5230\u7528\u6237\u4e2a\u6570\uff08# \u603b\u7528\u6237\u6570\uff09 TableColumn.header.completed=\u5df2\u5b8c\u6210\u4e0b\u8f7d\u4efb\u52a1\u7684\u7528\u6237\u6570 TableColumn.header.completed.info=# \u4e2a \u88ab tracker \u62a5\u544a\u7684\u5df2\u5b8c\u6210\u8be5 torrent \u4e0b\u8f7d\u7684\u7528\u6237 TableColumn.header.downspeed=\u4e0b\u8f7d\u901f\u5ea6 TableColumn.header.upspeed=\u4e0a\u4f20\u901f\u5ea6 TableColumn.header.eta=\u5269\u4f59\u65f6\u95f4 TableColumn.header.tracker=Tracker \u72b6\u6001 TableColumn.header.tracker.info=Tracker \u72b6\u6001 TableColumn.header.trackernextaccess=\u4e0b\u4e00\u6b21 Tracker \u8bbf\u95ee TableColumn.header.trackernextaccess.info=\u5f53\u4e0b\u4e00\u6b21 Tracker \u8bbf\u95ee\u65f6 TableColumn.header.priority=\u4f18\u5148\u7ea7 TableColumn.header.priority.info=\u51b3\u5b9a\u8be5 Torrent \u53ef\u4ee5\u4f7f\u7528\u591a\u5c11\u4e0a\u4f20\u5e26\u5bbd TableColumn.header.seeds.fullcopycalc=\u5047\u5b9a %1 \u4e2a\u7528\u6237 %2 \u4efd\u5b8c\u6574\u526f\u672c MyTorrentsView.menu.showdetails=\u663e\u793a\u7ec6\u8282\uff08&D\uff09 MyTorrentsView.menu.showdownloadbar=\u663e\u793a\u8ff7\u4f60\u4efb\u52a1\u6761\uff08&B\uff09 MyTorrentsView.menu.open=\u6253\u5f00\u6587\u4ef6\uff08&O\uff09 MyTorrentsView.menu.setpriority=\u8bbe\u7f6e\u4f18\u5148\u7ea7\uff08&P\uff09 MyTorrentsView.menu.setpriority.high=\u9ad8\uff08&H\uff09 MyTorrentsView.menu.setpriority.low=\u4f4e\uff08&L\uff09 MyTorrentsView.menu.start=\u5f00\u59cb\uff08&S\uff09 MyTorrentsView.menu.stop=\u505c\u6b62\uff08&P\uff09 MyTorrentsView.menu.remove=\u5220\u9664\uff08&R\uff09 MyTorrentsView.menu.changeTracker=\u6dfb\u52a0 Tracker \u5730\u5740\uff08&A\uff09 TrayWindow.menu.exit=\u9000\u51fa\uff08&x\uff09 TrayWindow.menu.show=\u663e\u793a\uff08&S\uff09 SystemTray.menu.exit=\u9000\u51fa\uff08&X\uff09 SystemTray.menu.closealldownloadbars=\u5173\u95ed\u8ff7\u4f60\u4efb\u52a1\u6761\uff08&A\uff09 SystemTray.menu.open_global_transfer_bar=\u663e\u793a\u4f20\u8f93\u6761 SystemTray.menu.show=\u663e\u793a Vuze \uff08&S\uff09 PeersView.ip.info=\u7528\u6237 IP PeersView.port=\u7aef\u53e3 PeersView.port.info=\u4f7f\u7528\u7684\u7aef\u53e3 PeersView.T=\u53d1\u8d77\u8fde\u63a5\u65b9 PeersView.T.info=L\uff08\u672c\u5730\uff09\uff1a\u4f60\u53d1\u8d77\u7684\u8fde\u63a5\uff0c R\uff08\u8fdc\u7a0b\uff09\uff1a\u5bf9\u65b9\u53d1\u8d77\u7684\u8fde\u63a5 PeersView.T.L.tooltip=\u4f60\u53d1\u8d77\u7684\u8fde\u63a5 PeersView.T.R.tooltip=\u5bf9\u65b9\u53d1\u8d77\u7684\u8fde\u63a5 PeersView.I1=\u4f60\u5bf9\u7528\u6237\u7684\u5174\u8da3 PeersView.I1.info=\u4f60\u5bf9\u5176\u4ed6\u7528\u6237\u7684\u4e1c\u897f\u611f\u5174\u8da3\uff1f PeersView.C1=\u8be5\u7528\u6237\u963b\u6b62\u4f60 PeersView.C1.info=\u8fd9\u4e2a\u7528\u6237\u662f\u5426\u7981\u6b62\u4e86\u4f60\u4ece\u4ed6\u90a3\u91cc\u4e0b\u8f7d PeersView.pieces=\u533a\u5757 PeersView.downloadspeed=\u4e0b\u8f7d\u901f\u5ea6 PeersView.download=\u4e0b\u8f7d\u91cf PeersView.I2=\u7528\u6237\u5bf9\u4f60\u7684\u5174\u8da3 PeersView.I2.info=\u8fd9\u4e2a\u7528\u6237\u5bf9\u4f60\u7684\u4e1c\u897f\u611f\u5174\u8da3\uff1f PeersView.C2=\u4f60\u51b7\u843d\u8be5\u7528\u6237 PeersView.C2.info=\u4f60\u662f\u5426\u7981\u6b62\u4e86\u8be5\u7528\u6237\u4ece\u4f60\u8fd9\u91cc\u4e0b\u8f7d PeersView.uploadspeed=\u4e0a\u4f20\u901f\u5ea6 PeersView.uploadspeed.info=\u4f60\u4e0a\u4f20\u7ed9\u7528\u6237\u7684\u901f\u5ea6 PeersView.upload=\u4e0a\u4f20\u91cf PeersView.upload.info=\u4f60\u7ed9\u7528\u6237\u4e0a\u4f20\u7684\u5168\u90e8\u6570\u636e\u91cf PeersView.statup=\u4e0a\u4f20\u7edf\u8ba1 PeersView.statup.info=\u4e00\u4e2a\u4f30\u8ba1\u51fa\u7684\u8be5\u7528\u6237\u4e0a\u4f20\u901f\u5ea6 PeersView.S.info=\u88ab\u51b7\u843d\uff1a\u4e00\u4e2a\u7528\u6237\u53ef\u4ee5\u88ab\u624b\u52a8\u6216\u8005\u81ea\u52a8\u201c\u51b7\u843d\u201d\uff08\u6ca1\u6709\u8fbe\u5230\u8db3\u591f\u7684\u4f20\u8f93\u6bd4\u7387\uff09 PeersView.downloadspeedoverall=\u5bf9\u65b9\u4e0b\u8f7d\u901f\u5ea6 PeersView.optunchoke=\u9009\u62e9\u89e3\u9664\u963b\u6b62 PeersView.client=\u5ba2\u6237\u7aef PeersView.client.info=\u7528\u6237\u4f7f\u7528\u7684 BT \u5ba2\u6237\u7aef\u7c7b\u578b PeersView.menu.snubbed=\u5df2\u5ffd\u7565\uff08&S\uff09 PeersView.title.short=\u7528\u6237 PeersView.title.full=\u7528\u6237 AllPeersView.title.full=\u6240\u6709\u7528\u6237 ConfigView.section.files=\u6587\u4ef6 ConfigView.label.usefastresume=\u4f7f\u7528\u5feb\u901f\u7eed\u4f20 ConfigView.label.incrementalfile=\u4e0b\u8f7d\u8fc7\u7a0b\u4e2d\u9010\u6e10\u589e\u52a0\u6587\u4ef6\u5927\u5c0f ConfigView.label.defaultsavepath=\u9ed8\u8ba4\u4fdd\u5b58\u76ee\u5f55 ConfigView.button.browse=\u6d4f\u89c8\u2026\uff08&B\uff09 ConfigView.dialog.choosedefaultsavepath=\u8bf7\u9009\u62e9\u9ed8\u8ba4\u4fdd\u5b58\u76ee\u5f55 ConfigView.section.server=\u8fde\u63a5 ConfigView.section.global=\u5e38\u89c4 ConfigView.label.disconnetseed=\u4f5c\u79cd\u5b50\u65f6\u65ad\u5f00\u548c\u5176\u5b83\u79cd\u5b50\u7684\u8fde\u63a5 ConfigView.label.switchpriority=\u4f5c\u79cd\u5b50\u65f6\u81ea\u52a8\u8f6c\u5165\u4f4e\u4f18\u5148\u7ea7 ConfigView.label.maxdownloads=\u6700\u5927\u7684\u6d3b\u52a8\u4e0b\u8f7d\u6570\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.label.maxdownloads.tooltip=\u4f60\u53ef\u4ee5\u4f7f\u7528\u4f60\u6307\u5b9a\u6d3b\u52a8\u4e0b\u8f7d\u6570\n\u9664\u975e\u4e00\u4e2a\u5df2\u7ecf\u5b8c\u6210\u7684 Torrent \u6ee1\u8db3\u201c\u6700\u9ad8\u4f18\u5148\u7ea7\u201d\uff0c\u5b83\u5c06\u5728\u5fc5\u8981\u65f6\u5360\u7528\u4e00\u4e2a\u6d3b\u52a8\u7684\u4e0b\u8f7d\u4f4d\u3002 ConfigView.label.maxactivetorrents=\u6700\u5927\u7684\u6d3b\u52a8\u4efb\u52a1\u6570\uff08\u4e0a\u4f20\u6216\u4e0b\u8f7d\uff09\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.label.priorityExtensions=\u81ea\u52a8\u5207\u6362\u81f3\u9ad8\u4f18\u5148\u7ea7\u6587\u4ef6\u7c7b\u578b \n\uff08\u4f8b\u5982\uff1a .txt\uff1b.nfo\uff1b.jpg\uff09 ConfigView.section.transfer=\u4f20\u8f93 ConfigView.label.maxuploads=\u6bcf\u4e2a Torrent \u7684\u4e0a\u4f20\u901a\u9053\u6570 ConfigView.label.maxuploadspeed=\u5168\u5c40\u6700\u5927\u4e0a\u4f20\u901f\u5ea6\uff08KB/s\uff09\uff1a\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.label.saveresumeinterval=\u4fdd\u5b58\u201c\u5feb\u901f\u7eed\u4f20\u4fe1\u606f\u201d\u6bcf ConfigView.unlimited=\u65e0\u9650\u5236 ConfigView.section.display=\u663e\u793a ConfigView.label.opendetails=\u81ea\u52a8\u663e\u793a\u4efb\u52a1\u7ec6\u8282 ConfigView.label.openbar=\u81ea\u52a8\u6253\u5f00\u8ff7\u4f60\u4efb\u52a1\u6761 ConfigView.label.use_old_speed_menus=\u4f7f\u7528\u65e7\u5f0f\u901f\u5ea6\u83dc\u5355\uff3b\u9700\u8981\u91cd\u542f\uff3d ConfigView.label.closetotray=\u5173\u95ed\u65f6\u6700\u5c0f\u5316\u5230\u7cfb\u7edf\u6258\u76d8 ConfigView.label.minimizetotray=\u6700\u5c0f\u5316\u5230\u7cfb\u7edf\u6258\u76d8 ConfigView.section.general=\u5e38\u89c4 ConfigView.section.start=\u5f00\u59cb ConfigView.label.showsplash=\u663e\u793a\u6b22\u8fce\u753b\u9762 ConfigView.label.autoupdate=\u5f53\u6709\u66f4\u65b0\u53ef\u7528\u7684\u65f6\u5019\u6253\u5f00\u66f4\u65b0\u5bf9\u8bdd\u6846 ConfigView.label.openconsole=\u542f\u52a8\u65f6\u6253\u5f00\u63a7\u5236\u53f0 ConfigView.label.openconfig=\u542f\u52a8\u65f6\u663e\u793a\u9009\u9879\u9875 ConfigView.label.startminimized=\u542f\u52a8\u65f6\u6700\u5c0f\u5316 ConfigView.label.ircwiki=\u8bf7\u9605\u8bfb http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=\u670d\u52a1\u5668 ConfigView.label.ircchannel=\u9891\u9053 ConfigView.label.irclogin=\u6635\u79f0 ConfigView.group.irctitle=IRC \u8bbe\u7f6e ConfigView.boolean.ircsendinfo=\u5141\u8bb8\uff08\u533f\u540d\uff09 \u53d1\u9001\u60a8\u7684\u8bbe\u7f6e\u5230\n\u9891\u9053\u7ba1\u7406\u5458\uff0c\u8ba9\u4ed6\u4eec\u5e2e\u52a9\u60a8 ConfigView.boolean.irclog=\u542f\u7528\u9891\u9053\u6d3b\u52a8\u65e5\u5fd7\uff08\u8bb0\u5f55\u5230 IRC_log.htm\uff09 ConfigView.section.security=\u5b89\u5168 ConfigView.label.password=\u4f7f\u7528\u5bc6\u7801\u4fdd\u62a4 Vuze n\u5c06\u518d\u542f\u52a8\u65f6\u8981\u6c42\u8ba4\u8bc1 ConfigView.label.passwordconfirm=\u5bc6\u7801\uff08\u786e\u8ba4\uff09 ConfigView.label.passwordmatch=\u5bc6\u7801\u6fc0\u6d3b\uff1a ConfigView.label.passwordmatchnone=\u65e0 ConfigView.label.passwordmatchno=\u9519\u8bef / \u5bc6\u7801\u4e0d\u5339\u914d ConfigView.label.passwordmatchyes=\u6b63\u786e ConfigView.button.save=\u4fdd\u5b58 ConfigView.title.short=\u9009\u9879 ConfigView.title.full=\u9009\u9879 ConfigView.title.full._mac=\u9996\u9009\u9879 ConsoleView.title.short=\u63a7\u5236\u53f0 ConsoleView.title.full=\u63a7\u5236\u53f0 FileItem.write=\u5199\u5165 FileItem.read=\u8bfb\u53d6 FileItem.normal=\u666e\u901a FileItem.high=\u9ad8 FileItem.donotdownload=\u4e0d\u4e0b\u8f7d FileItem.delete=\u5220\u9664 FilesView.name=\u540d\u79f0 FilesView.name.fastRename=\u5feb\u901f\u91cd\u547d\u540d FilesView.size=\u5927\u5c0f FilesView.done=\u5b8c\u6210 FilesView.firstpiece=\u9996\u533a\u5757\u53f7\u6570# FilesView.numberofpieces=\u533a\u5757\u603b\u6570 # FilesView.pieces=\u533a\u5757 FilesView.mode=\u6a21\u5f0f FilesView.priority=\u4f18\u5148\u7ea7 FilesView.menu.open=\u6253\u5f00\uff08&O\uff09 FilesView.menu.setpriority=\u8bbe\u7f6e\u4f18\u5148\u7ea7\uff08&S\uff09 FilesView.menu.setpriority.high=\u9ad8\uff08&H\uff09 FilesView.menu.setpriority.normal=\u666e\u901a\uff08&N\uff09 FilesView.menu.setpriority.skipped=\u4e0d\u4e0b\u8f7d\uff08&D\uff09 FilesView.title.short=\u6587\u4ef6 FilesView.title.full=\u6587\u4ef6 GeneralView.section.downloaded=\u5df2\u4e0b\u8f7d GeneralView.label.status.file=\u6587\u4ef6\u72b6\u6001 GeneralView.label.status.pieces=\u533a\u5757\u72b6\u6001 GeneralView.section.availability=\u53ef\u7528\u6027 GeneralView.label.status.pieces_available=\u533a\u5757\u72b6\u6001 GeneralView.section.transfer=\u4f20\u8f93 GeneralView.section.info=\u4fe1\u606f GeneralView.title.short=\u5e38\u89c4 GeneralView.title.full=\u5e38\u89c4 GeneralView.label.timeelapsed=\u5df2\u7528\u65f6\u95f4\uff1a GeneralView.label.remaining=\u5269\u4f59\u65f6\u95f4\uff1a GeneralView.label.downloaded=\u5df2\u4e0b\u8f7d\uff1a GeneralView.label.downloadspeed=\u4e0b\u8f7d\u901f\u5ea6\uff1a GeneralView.label.maxuploads=\u6700\u5927\u4e0a\u4f20\u8fde\u63a5\uff1a GeneralView.label.maxuploads.tooltip=\u4efb\u610f\u65f6\u95f4\u6700\u5927\u89e3\u9664\u963b\u6b62\u4f20\u8f93\u7684\u7528\u6237\u6570\u76ee GeneralView.label.uploaded=\u5df2\u4e0a\u4f20\uff1a GeneralView.label.uploadspeed=\u4e0a\u4f20\u901f\u5ea6\uff1a GeneralView.label.seeds=\u79cd\u5b50\uff1a GeneralView.label.peers=\u7528\u6237\uff1a GeneralView.label.completed=\u5df2\u5b8c\u6210\u4e0b\u8f7d : GeneralView.label.totalspeed=\u7fa4\u4f53\u901f\u5ea6\uff1a GeneralView.label.totalspeed.tooltip=\u4f60\u8fde\u63a5\u5230\u7684\u6240\u6709\u5ba2\u6237\u7aef\u7684\u4e0b\u8f7d\u901f\u5ea6\u603b\u548c\uff08\u5e73\u5747\u503c\uff09 GeneralView.label.averagespeed=\u5e73\u5747 GeneralView.label.filename=\u540d\u79f0 GeneralView.label.totalsize=\u6587\u4ef6\u5927\u5c0f\uff1a GeneralView.label.savein=\u4fdd\u5b58\u4e8e\uff1a GeneralView.label.hash=Hash \u503c\uff1a GeneralView.label.numberofpieces=\u533a\u5757\u6570\u91cf#\uff1a GeneralView.label.size=\u5927\u5c0f\uff1a GeneralView.label.tracker=Tracker \u72b6\u6001\uff1a GeneralView.label.updatein=\u66f4\u65b0\u65f6\u95f4\uff1a GeneralView.label.trackerurl=Tracker \u5730\u5740\uff1a GeneralView.label.trackerurlupdate=\u624b\u52a8\u66f4\u65b0 GeneralView.label.comment=\u6ce8\u89e3\uff1a GeneralView.label.user_comment=\u7528\u6237\u8bc4\u8bba\uff1a GeneralView.label.status=\u72b6\u51b5\uff1a ManagerItem.waiting=\u7b49\u5f85 ManagerItem.allocating=\u5206\u914d\u4e2d ManagerItem.checking=\u9a8c\u8bc1\u4e2d ManagerItem.ready=\u5c31\u7eea ManagerItem.downloading=\u4e0b\u8f7d\u4e2d ManagerItem.seeding=\u6b63\u5728\u4f5c\u79cd ManagerItem.stopped=\u5df2\u505c\u6b62 ManagerItem.error=\u9519\u8bef ManagerItem.high=\u9ad8 ManagerItem.low=\u4f4e MinimizedWindow.name=\u540d\u79f0\uff1a MinimizedWindow.all_transfers=Vuze \u4f20\u8f93 PiecesView.size=\u5927\u5c0f PiecesView.numberofblocks=\u5206\u5757\u6570\u76ee# PiecesView.blocks=\u5206\u5757 PiecesView.completed=\u5df2\u5b8c\u6210 PiecesView.availability=\u53ef\u7528\u6027 PiecesView.reservedby=\u88ab\u4fdd\u7559 PiecesView.writers=\u5757\u8d21\u732e\u8005 PiecesView.title.short=\u533a\u5757 PiecesView.title.full=\u533a\u5757 SystemTray.tooltip.seeding=%1 \u2191\uff0c SystemTray.tooltip.downloading=%1 \u2193\uff0c DownloadManager.error.filenotfound=\u627e\u4e0d\u5230\u6587\u4ef6 DownloadManager.error.fileempty=Torrent \u6587\u4ef6\u4e3a\u7a7a DownloadManager.error.filetoobig=Torrent \u6587\u4ef6\u8fc7\u5927 DownloadManager.error.filewithouttorrentinfo=\u672a\u5728\u6587\u4ef6\u4e2d\u627e\u5230 Torrent \u4fe1\u606f DownloadManager.error.unsupportedencoding=\u4e0d\u652f\u6301\u7684\u7f16\u7801 DownloadManager.error.ioerror=IO \u9519\u8bef DownloadManager.error.sha1=\u627e\u4e0d\u5230\uff0c \u7b97\u6cd5\uff08SHA1\uff09 \u9519\u8bef PeerManager.status.offline=\u79bb\u7ebf PeerManager.status.ok=\u6b63\u5e38 PeerManager.status.checking=\u9a8c\u8bc1\u4e2d PeerManager.status.finished=\u5b8c\u6210 PeerManager.status.finishedin=\u5c06\u7ed3\u675f\u4e8e MainWindow.upgrade.assistant=\u5347\u7ea7\u52a9\u624b MainWindow.upgrade.newerversion=\u6709\u65b0\u7248 Vuze \u53ef\u4ee5\u4e0b\u8f7d MainWindow.upgrade.explanation=\u5347\u7ea7\u52a9\u624b\u5c06\u4e0b\u8f7d\u65b0\u7248\u672c\u5230 Vuze \u76ee\u5f55\uff0c\u7136\u540e\u4f1a\u91cd\u542f Vuze MainWindow.upgrade.explanation.manual=\u4f60\u53ef\u4ee5\u624b\u52a8\u66f4\u65b0 Vuzeuff0c\u65b9\u6cd5\u662f\u5173\u95ed Vuze uff0c\u4e0b\u8f7d\u5b89\u88c5\u6700\u65b0\u7248\u672c\uff0c\u7136\u540e\u542f\u52a8 Vuze u3002 MainWindow.upgrade.step1=\u7b2c\u4e00\u6b65\uff1a\u4e0b\u8f7d\u65b0\u7248\u672c MainWindow.upgrade.step2=\u7b2c\u4e8c\u6b652\uff1a\u5173\u95ed\u8fd9\u4e2a\u7248\u672c\u5e76\u91cd\u542f\u65b0\u7248\u7684 Vuze MainWindow.upgrade.hint1=\u63d0\u793a Hint \uff1a\t\u6309\u4e0b\u5b8c\u6210\u8fdb\u5165\u81ea\u52a8\u7a0b\u5e8f MainWindow.upgrade.hint2=\u63d0\u793a Hint\uff1a\t\u5982\u679c\u4f60\u8981\u7a0d\u540e\u540e\u5173\u95ed Vuze uff0c\u70b9\u51fb\u53d6\u6d88\n\t\u5e76\u5728\u5173\u95ed\u540e\u628a Azureus2-new.jar \u6539\u540d\u4e3a Azureus2.jar MainWindow.upgrade.error.downloading.hint=\u9519\u8bef\uff1a\t\u65e0\u6cd5\u4e0b\u8f7d\u65b0\u7248\u672c MainWindow.upgrade.section.info=\u6709\u65b0\u7248\u672c\u5566 MainWindow.upgrade.section.manual=\u624b\u52a8\u5347\u7ea7 MainWindow.upgrade.section.automatic=\u81ea\u52a8\u5347\u7ea7 MainWindow.upgrade.tooltip.progressbar=\u4e0b\u8f7d\u4fe1\u606f\u5728\u8fd9\u91cc\u663e\u793a Button.next=\u4e0b\u4e00\u6b65 Button.finish=\u5b8c\u6210 Button.cancel=\u53d6\u6d88\uff08&C\uff09 LocaleUtil.title=\u9009\u62e9\u7f16\u7801 LocaleUtil.section.chooseencoding=\u4e3a\u6587\u4ef6\u540d\u9009\u62e9\u7f16\u7801 LocaleUtil.label.chooseencoding=\u8bf7\u9009\u62e9\u6700\u5339\u914d\u7684\u7f16\u7801 LocaleUtil.label.hint.doubleclick=\u63d0\u793a\uff1a\u53cc\u51fb\u4e00\u884c\u540e\u9009\u62e9\u7f16\u7801\u7136\u540e\u518d\u5173\u95ed\u5bf9\u8bdd\u6846 LocaleUtil.label.checkbox.rememberdecision=\u4e3a\u5269\u4e0b\u7684\u6587\u4ef6\u540d\u8bb0\u4f4f\u7ed3\u679c LocaleUtil.column.encoding=\u7f16\u7801 IrcClient.copyright=\u4f7f\u7528 PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=\u6b63\u5728\u8fde\u63a5\u5230 IrcClient.connected=\u5df2\u8fde\u63a5\u5230 IrcClient.joining=\u52a0\u5165 IrcClient.channel=\u9891\u9053 IrcClient.joined=\u5df2\u52a0\u5165 IrcClient.error=\u9519\u8bef IrcClient.hasjoined=\u52a0\u5165\u4e86 IrcClient.haskicked=\u88ab\u8e22\u51fa IrcClient.hasleft=\u79bb\u5f00 IrcClient.nowknown=\u6539\u540d\u5230 IrcClient.topicforchannel=\u9891\u9053\u7684\u4e3b\u9898\u662f\uff1a IrcClient.disconnected=\u65ad\u5f00\u8fde\u63a5\u4ece IrcClient.noNick=\u6ca1\u6709\u6307\u5b9a\u6635\u79f0\u3002\u8bf7\u5230\u201c\u9009\u9879\u201d\u4e2d\u5199\u4e0a\u4f60\u7684\u6635\u79f0\u3002 IrcView.actionnotsupported=\u8fd9\u4e2a\u52a8\u4f5c\u6ca1\u6709\u88ab\u652f\u6301 IrcView.clientsconnected=\u7528\u6237 IrcView.privateto=\u5230 IrcView.privatefrom=\u4ece IrcView.noticefrom=\u901a\u77e5\uff1a IrcView.errormsg=\u4f7f\u7528 /msg \u53d1\u751f\u8bed\u6cd5\u9519\u8bef\uff1a/msg <\u7528\u6237\u540d> <\u4fe1\u606f> IrcView.help=\u5408\u6cd5\u7684\u547d\u4ee4\u5305\u62ec\uff1a\n . /help\uff1a\u663e\u793a\u5f53\u524d\u4fe1\u606f\n . /nick | /name\uff1a\u6539\u53d8\u4f60\u7684\u540d\u5b57\n . /me action\uff1a\u53d1\u9001\u4e00\u4e2a\u52a8\u4f5c \n . /msg <\u7528\u6237\u540d> <\u4fe1\u606f>\uff1a\u53d1\u9001\u4e00\u4e2a\u79c1\u4eba\u4fe1\u606f\u5230\u7528\u6237 \n . /r message\uff1a\u91cd\u65b0\u53d1\u9001\u6700\u540e\u4e00\u4e2a\u79c1\u4eba\u4fe1\u606f\n . /join #channel\uff1a\u6539\u53d8\u5f53\u524d\u9891\u9053 PasswordWindow.title=Vuze \u5df2\u88ab\u9501\u5b9a PasswordWindow.passwordprotected=Vuze \u5df2\u88ab\u5bc6\u7801\u4fdd\u62a4\u3002\n\u8bf7\u8f93\u5165\u4f60\u7684\u5bc6\u7801\u4ee5\u663e\u793a Vuze \u7a97\u53e3\uff1a Button.ok=\u786e\u5b9a\uff08&O\uff09 TrackerChangerWindow.title=\u6dfb\u52a0 Tracker TrackerChangerWindow.newtracker=\u8f93\u5165\u65b0\u7684 Tracker \u7684\u94fe\u63a5 PeersView.discarded=\u5df2\u629b\u5f03 PeersView.discarded.info=\u4f60\u63a5\u6536\u5230\u7684\u6570\u636e\u5e76\u4e0d\u662f\u4f60\u6240\u9700\u8981\u7684\uff0c\u6240\u4ee5\u629b\u5f03\u3002 discarded=\u6570\u636e\u5df2\u88ab\u629b\u5f03 MyTorrentsView.menu.move=\u79fb\u52a8\uff08&M\uff09 MyTorrentsView.menu.moveUp=\u5411\u4e0a\uff08&U\uff09 MyTorrentsView.menu.moveDown=\u5411\u4e0b\uff08&D\uff09 GeneralView.label.hashfails=Hash \u5931\u8d25\uff1a GeneralView.label.shareRatio=\u5206\u4eab\u7387\uff1a ConfigView.section.downloadManagement=\u4e0b\u8f7d\u7ba1\u7406 ConfigView.label.startRatioPeers=\u5f00\u59cb\u505a\u79cd\uff0c\u5982\u679c\u4e0d\u8d85\u8fc7\u4e00\u4e2a\u79cd\u5b50\u5bf9 ConfigView.text.neverStop=\u6c38\u8fdc\u4e0d\u505c\u6b62 ConfigView.text.neverStart=\u6c38\u8fdc\u4e0d\u5f00\u59cb ConfigView.text.peers=\u7528\u6237 ConfigView.label.checkOncompletion=\u5f53\u4e0b\u8f7d\u5b8c\u6210\u65f6\uff0c\u91cd\u65b0\u68c0\u67e5\u6587\u4ef6\u5b8c\u6574\u6027 wizard.title=\u5236\u4f5c\u4e00\u4e2a Torrent \u6587\u4ef6 wizard.previous=< \u4e0a\u4e00\u6b65 wizard.next=\u4e0b\u4e00\u6b65 > wizard.finish=\u5b8c\u6210 wizard.mode=Tracker / \u6a21\u5f0f wizard.tracker=Tracker\uff1a wizard.invalidurl=\u6b64\u5730\u5740\u65e0\u6548 wizard.singlefile=\u5355\u4e00\u6587\u4ef6 wizard.singlefile.help=\u4ece\u5355\u4e00\u6587\u4ef6\u751f\u6210 Torrent wizard.directory=\u76ee\u5f55 wizard.directory.help=\u4ece\u4e00\u4e2a\u76ee\u5f55\u751f\u6210 Torrent wizard.choosefile=\u9009\u62e9\u6587\u4ef6 wizard.file=\u6587\u4ef6\uff1a wizard.browse=\u6d4f\u89c8\u2026 wizard.choosedirectory=\u9009\u62e9\u4e00\u4e2a\u76ee\u5f55 wizard.invalidfile=\u65e0\u6548\u6587\u4ef6 wizard.invaliddirectory=\u65e0\u6548\u76ee\u5f55 wizard.torrentFile=Torrent \u6587\u4ef6 wizard.choosetorrent=\u8bf7\u9009\u62e9\u9700\u8981\u521b\u5efa\u7684 Torrent \u6587\u4ef6 wizard.information=\u4fe1\u606f wizard.notimplemented=\u6ca1\u6709\u5b9e\u73b0 wizard.progresstitle=\u751f\u6210 Torrent \u6587\u4ef6 wizard.savingfile=\u4fdd\u5b58\u6587\u4ef6\u2026 wizard.filesaved=\u6587\u4ef6\u5df2\u4fdd\u5b58\u3002 wizard.close=\u5173\u95ed Torrent.create.progress.piecelength=\u533a\u5757\u5927\u5c0f\uff1a Torrent.create.progress.piececount=\u533a\u5757\u8ba1\u6570\uff1a Torrent.create.progress.totalfilesize=\u603b\u6587\u4ef6\u5927\u5c0f\uff1a Torrent.create.progress.totalfilecount=\u603b\u6587\u4ef6\u4e2a\u6570\uff1a Torrent.create.progress.parsingfiles=\u6b63\u5728\u5206\u6790\u6587\u4ef6 Torrent.create.progress.hashing=\u6b63\u5728\u8ba1\u7b97\u6587\u4ef6 Hash \u503c MainWindow.upgrade.downloadingfrom=\u6b63\u5728\u4e0b\u8f7d\uff0c\u4ece\u7ad9\u70b9\uff1a MainWindow.menu.view.ipFilter=Ip \u8fc7\u6ee4\uff08&I\uff09 ConfigView.section.ipfilter=IP \u8fc7\u6ee4 ConfigView.section.ipfilter.description=\u63cf\u8ff0 ConfigView.section.ipfilter.start=\u8d77\u59cb IP ConfigView.section.ipfilter.end=\u7ec8\u6b62 IP ConfigView.section.ipfilter.add=\u6dfb\u52a0 ConfigView.section.ipfilter.remove=\u9664\u53bb ConfigView.section.ipfilter.edit=\u7f16\u8f91 ConfigView.section.ipfilter.save=\u4fdd\u5b58 ConfigView.section.ipfilter.editFilter=\u7f16\u8f91\u8fc7\u6ee4 ConfigView.section.ipfilter.enable=\u542f\u7528 PeersView.menu.close=\u5173\u95ed\uff08&C\uff09 seedmore.title=\u5e94\u8be5\u505a\u957f\u65f6\u95f4\u7684\u79cd\u5b50 seedmore.shareratio=\u4f60\u5728\u8fd9\u4e2a Torrent \u7684\u5206\u4eab\u7387\u662f seedmore.uploadmore=\u62e5\u6709\u4e00\u4e2a\u5c0f\u4e8e100%\u7684\u5206\u4eab\u7387\u5728 BT \u4e0a\u662f\u4e0d\u597d\u7684\u884c\u4e3a\u3002\n\u4f60\u5e94\u8be5\u5728\u8fd9\u4e2a Torrent \u505a\u66f4\u957f\u65f6\u95f4\u7684\u79cd\u5b50\u3002\n\u4f60\u786e\u5b9a\u8981\u7ee7\u7eed\u5417\uff1f ConfigView.label.showpopuponclose=\u5f53\u505c\u6b62\u505a\u79cd\u65f6\uff0c\u5982\u679c\u5206\u4eab\u7387\u5c0f\u4e8e1\uff0c\u5219\u5f39\u51fa\u786e\u8ba4\u7a97\u53e3\u3002 ConfigView.label.startNumSeeds=\u5f00\u59cb\u505a\u79cd\u5b50\uff0c\u5f53\u79cd\u5b50\u6570\u5c0f\u4e8e ConfigView.label.seeds=\u79cd\u5b50 ConfigView.section.seeding=\u6b63\u5728\u505a\u79cd MyTorrentsView.menu.removeand=\u5220\u9664\u5e76\uff08&V\uff09 MyTorrentsView.menu.removeand.deletetorrent=\u5220\u9664 .torrent \u6587\u4ef6\uff08&T\uff09 MyTorrentsView.menu.removeand.deletedata=\u5220\u9664\u6570\u636e\uff08&D\uff09 MyTorrentsView.menu.removeand.deleteboth=\u5220\u9664\u6570\u636e\u548c .torrent \u6587\u4ef6\uff08&B\uff09 deletedata.title=\uff01\uff01\uff01 \u8b66\u544a \uff01\uff01\uff01 deletedata.message1=\u4f60\u5c06\u8981\u4ece\uff1a\n\u5220\u9664\u6570\u636e deletedata.noprompt=\u4e0d\u8981\u518d\u63d0\u9192\u6211 MainWindow.menu.file.configure=\u914d\u7f6e\u5411\u5bfc\uff08&W\uff09 configureWizard.title=\u914d\u7f6e\u5411\u5bfc configureWizard.welcome.title=\u6b22\u8fce\u6765\u5230 Vuze \u914d\u7f6e\u5411\u5bfc configureWizard.welcome.message=\u8fd9\u4e2a\u5411\u5bfc\u5c06\u5e2e\u52a9\u4f60\u914d\u7f6e Vuze \u7684\u4e00\u822c\u529f\u80fd\u3002\u4f60\u53ef\u4ee5\u5728\u5de5\u5177->\u9009\u9879\u91cc\u9762\u4fee\u6539\u66f4\u9ad8\u7ea7\u7684\u914d\u7f6e\u3002 configureWizard.transfer.title=\u4f20\u8f93\u548c\u8fde\u63a5\u8bbe\u7f6e configureWizard.transfer.hint=\u63d0\u793a\uff1a\u6700\u597d\u4f7f\u7528\u4e00\u4e2a\u7565\u5fae\u5c0f\u4e8e\u4f60\u7ebf\u8def\u901f\u5ea6\u7684\u503c\u3002 configureWizard.transfer.message=\u8bf7\u4ece\u4e0b\u9762\u9009\u62e9\u4e00\u4e2a\u8fde\u63a5\u3002\u6ce8\u610f\uff0c\u8fc7\u591a\u9650\u5236\u4e0a\u4f20\u901f\u5ea6\u5c06\u5bfc\u81f4\u4e0b\u8f7d\u901f\u5ea6\u964d\u4f4e\u3002\u56e0\u4e3a\u4e0a\u4f20\u901f\u5ea6\u662f\u5728\u4f60\u6b63\u5728\u4e0b\u8f7d\u7684\u6bcf\u4e2a Torrent \u4e2d\u8ba1\u7b97\u7684\uff0c\u540c\u65f6\u4e0b\u8f7d\u8fc7\u591a\u7684 Torrent \u5c06\u4f7f\u901f\u5ea6\u964d\u4f4e\u3002\u6211\u4eec\u5efa\u8bae\u6bcf\u4e2a Torrent \u6700\u5c0f\u9650\u5236\u4e3a 5KB/s\u3002 \u4f60\u4e0a\u8f7d\u7684\u8d8a\u5feb\uff0c\u4e0b\u8f7d\u7684\u4e5f\u8d8a\u5feb\uff08\u548c Torrent \u6210\u6b63\u6bd4\uff09\u3002 configureWizard.transfer.connection=\u7ebf\u8def configureWizard.transfer.connection.0=\u81ea\u5b9a\u4e49 configureWizard.transfer.connection.1=\u8c03\u5236\u89e3\u8c03\u5668 configureWizard.transfer.connection.2=ADSL/\u6709\u7ebf\u7535\u89c6\u7f51\u7edc/128 kbps configureWizard.transfer.connection.3=ADSL/\u6709\u7ebf\u7535\u89c6\u7f51\u7edc/256 kbps configureWizard.transfer.connection.4=ADSL/\u6709\u7ebf\u7535\u89c6\u7f51\u7edc/384 kbps configureWizard.transfer.connection.5=ADSL/\u6709\u7ebf\u7535\u89c6\u7f51\u7edc/512 kbps configureWizard.transfer.connection.6=ADSL/\u6709\u7ebf\u7535\u89c6\u7f51\u7edc/768 kbps configureWizard.transfer.connection.7=ADSL/\u6709\u7ebf\u7535\u89c6\u7f51\u7edc/1024 kbps configureWizard.transfer.maxUpSpeed=\u6700\u5927\u4e0a\u4f20\u901f\u5ea6\uff08KB/s\uff09 configureWizard.transfer.maxActiveTorrents=\u6700\u5927\u7684\u6d3b\u52a8\u4efb\u52a1\u6570 configureWizard.transfer.maxDownloads=\u6700\u5927\u7684\u6d3b\u52a8\u4e0b\u8f7d\u6570 configureWizard.transfer.maxUploadsPerTorrent=\u6bcf\u4e2a Torrent \u6587\u4ef6\u6700\u5927\u4e0a\u4f20\u6570\u91cf configureWizard.nat.title=NAT / \u670d\u52a1\u5668\u7aef\u53e3 configureWizard.nat.message=\u4e3a\u4e86\u66f4\u597d\u5730\u4f7f\u7528 Vuze uff0c\u5f3a\u70c8\u5efa\u8bae\u4f60\u80fd\u5904\u4e8e\u5916\u7f51\u72b6\u6001\u3002\u8fd9\u4e2a\u5de5\u5177\u4f7f\u4f60\u80fd\u6d4b\u8bd5/\u6539\u53d8\u8fd9\u4e9b\u9ed8\u8ba4\u7aef\u53e3\u3002\n\n\u6ce8\u610f\uff1a\u8fd9\u4e2a\u5de5\u5177\u4ec5\u6d4b\u8bd5 TCP \u8fde\u63a5\u3002 DHT \u529f\u80fd\u4f7f\u7528 UDP \u8fde\u63a5\uff0c\u4f46\u5982\u679c\u53d1\u73b0\u7aef\u53e3\u963b\u585e\uff0cVuze \u4f1a\u81ea\u52a8\u901a\u77e5\u4f60\u3002\n\nTCP \u7aef\u53e3 6880 \u662f\u4f5c\u4e3a\u4fdd\u7559\u7aef\u53e3\uff0c\u6240\u4ee5\u4e0d\u53ef\u4f7f\u7528\u3002 configureWizard.nat.test=\u6d4b\u8bd5 configureWizard.nat.testing=\u6b63\u5728\u6d4b\u8bd5\u7aef\u53e3 configureWizard.nat.ok=\u6b63\u5e38 configureWizard.nat.ko=NAT \u9519\u8bef configureWizard.nat.unable=\u65e0\u6cd5\u6d4b\u8bd5 configureWizard.file.title=Torrent / \u6587\u4ef6 configureWizard.file.message1=Vuze \u5c06\u628a\u6253\u5f00\u7684\u6240\u6709 Torrent \u6587\u4ef6\u4fdd\u5b58\u5728\u4e00\u4e2a\u6587\u4ef6\u5939\uff0c\u4f60\u53ef\u4ee5\u5728\u8fd9\u91cc\u9009\u62e9\u8fd9\u4e2a\u6587\u4ef6\u5939\uff1a configureWizard.file.path=\u76ee\u5f55 configureWizard.file.browse=\u6d4f\u89c8 configureWizard.file.message2=Vuze \u53ef\u4ee5\u901a\u8fc7\u5f80 Torrent \u4e2d\u6dfb\u52a0\u4e00\u4e9b\u4fe1\u606f\u4ece\u800c\u76f4\u63a5\u7eed\u4f20 Torrent\u3002\u4f7f\u7528\u8fd9\u4e2a\u529f\u80fd\u4f60\u4e5f\u53ef\u4ee5\u7eed\u4f20\u672a\u5b8c\u6210\u4e0b\u8f7d\u7684\u533a\u5757\u3002 configureWizard.file.fastResume=\u542f\u7528\u5feb\u901f\u7eed\u4f20 configureWizard.file.invalidPath=\u65e0\u6548\u7684\u76ee\u5f55 configureWizard.finish.title=\u5b8c\u6210 configureWizard.finish.message=Vuze \u5df2\u7ecf\u5b8c\u6210\u914d\u7f6e\uff0c\u795d\u4f60\u4f7f\u7528\u6109\u5feb\uff01 wizard.close.confirmation=\u786e\u8ba4 wizard.close.message=\u4f60\u5e0c\u671b\u4e0b\u6b21\u542f\u52a8 Vuze n\u65f6\u6253\u5f00\u5411\u5bfc\u5417\uff1f exportTorrentWizard.title=\u5bfc\u51fa\u4e00\u4e2a Torrent exportTorrentWizard.torrentfile.title=\u9009\u62e9 Torrent exportTorrentWizard.torrentfile.message=\u9009\u62e9\u9700\u8981\u5bfc\u51fa\u7684 Torrent \u6587\u4ef6 exportTorrentWizard.torrentfile.path=\u76ee\u5f55 exportTorrentWizard.torrentfile.browse=\u6d4f\u89c8 exportTorrentWizard.torrentfile.invalidPath=\u65e0\u6548\u7684 Torrent \u6587\u4ef6 exportTorrentWizard.exportfile.title=\u5bfc\u51fa\u6587\u4ef6\u9009\u62e9 exportTorrentWizard.exportfile.message=\u8f93\u5165\u9700\u8981\u5bfc\u51fa\u7684\u6587\u4ef6 exportTorrentWizard.exportfile.path=\u76ee\u5f55 exportTorrentWizard.exportfile.browse=\u6d4f\u89c8 exportTorrentWizard.exportfile.invalidPath=\u65e0\u6548\u7684\u5bfc\u51fa\u6587\u4ef6 exportTorrentWizard.finish.title=\u5b8c\u6210 exportTorrentWizard.finish.message=\u5df2\u7ecf\u6210\u529f\u5bfc\u51fa exportTorrentWizard.process.inputfilebad.title=\u65e0\u6548\u7684 Torrent \u6587\u4ef6 exportTorrentWizard.process.inputfilebad.message=\u5728\u8bbf\u95ee\u8f93\u5165\u7684\u6587\u4ef6\u65f6\u53d1\u751f\u9519\u8bef\uff1a exportTorrentWizard.process.outputfileexists.title=\u6587\u4ef6\u5df2\u5b58\u5728 exportTorrentWizard.process.outputfileexists.message=\u8f93\u51fa\u6587\u4ef6\u5df2\u5b58\u5728 \uff0d \u662f\u5426\u8986\u76d6\uff1f exportTorrentWizard.process.torrentfail.title=Torrent \u8bfb\u53d6\u9519\u8bef exportTorrentWizard.process.exportfail.title=Torrent \u5bfc\u51fa\u5931\u8d25 exportTorrentWizard.process.unknownfail.title=\u672a\u77e5\u9519\u8bef importTorrentWizard.title=\u5bfc\u5165\u4e00\u4e2a XML Torrent importTorrentWizard.torrentfile.title=\u9009\u62e9 Torrent importTorrentWizard.torrentfile.message=\u8f93\u5165\u9700\u8981\u5bfc\u5165\u7684 Torrent \u6587\u4ef6 importTorrentWizard.torrentfile.path=\u76ee\u5f55 importTorrentWizard.torrentfile.browse=\u6d4f\u89c8 importTorrentWizard.torrentfile.invalidPath=\u65e0\u6548\u7684 Torrent \u6587\u4ef6 importTorrentWizard.importfile.title=\u5bfc\u5165\u6587\u4ef6\u9009\u62e9 importTorrentWizard.importfile.message=\u9009\u62e9\u9700\u8981\u5bfc\u5165\u7684\u6587\u4ef6 importTorrentWizard.importfile.path=\u76ee\u5f55 importTorrentWizard.importfile.browse=\u6d4f\u89c8 importTorrentWizard.importfile.invalidPath=\u65e0\u6548\u7684\u5bfc\u5165\u6587\u4ef6 importTorrentWizard.finish.title=\u5b8c\u6210 importTorrentWizard.finish.message=\u5df2\u7ecf\u6210\u529f\u5bfc\u5165 importTorrentWizard.process.inputfilebad.title=\u65e0\u6548\u7684\u5bfc\u5165\u6587\u4ef6 importTorrentWizard.process.inputfilebad.message=\u5728\u8bbf\u95ee\u8f93\u5165\u7684\u6587\u4ef6\u65f6\u53d1\u751f\u9519\u8bef\uff1a importTorrentWizard.process.outputfileexists.title=\u6587\u4ef6\u5df2\u5b58\u5728 importTorrentWizard.process.outputfileexists.message=\u8f93\u51fa\u6587\u4ef6\u5df2\u5b58\u5728 \uff0d \u662f\u5426\u8986\u76d6\uff1f importTorrentWizard.process.torrentfail.title=Torrent \u5199\u5165\u9519\u8bef importTorrentWizard.process.importfail.title=Torrent \u5bfc\u5165\u5931\u8d25 importTorrentWizard.process.unknownfail.title=\u672a\u77e5\u9519\u8bef ConfigView.label.bindip=\u7ed1\u5b9a\u5230\u672c\u5730 IP \u5730\u5740\u6216\u7aef\u53e3 ConfigView.label.xfs.allocation=\u5206\u914d\u6587\u4ef6\u65f6\u4f7f\u7528 XFS \u6587\u4ef6\u7cfb\u7edf ConfigView.label.xfs.allocation.tooltip=\u8bf7\u786e\u8ba4\u4f60\u7684\u7cfb\u7edf\u4e0a\u5df2\u5b89\u88c5 /usr/sbin/xfs_io . \u5728\u5927\u591a\u6570 Linux \u53d1\u884c\u7248\u4e2d\uff0c \u5b83\u4f4d\u4e8e "xfsprogs" \u5305\u4e2d. xfs.allocation.xfs_io.not.found=XFS \u6587\u4ef6\u5206\u914d\u5931\u8d25\uff0c\u539f\u56e0\u662f /usr/sbin/xfs_io \u65e0\u6cd5\u542f\u52a8. \u8bf7\u786e\u8ba4\u4f60\u7684\u7cfb\u7edf\u4e2d\u5df2\u6b63\u786e\u5b89\u88c5. \u539f\u59cb\u9519\u8bef\u662f\uff1a "%1". ConfigView.label.zeronewfiles=\u5206\u914d\u7a7a\u95f4\u65f6\u5c06\u7a7a\u95f4\u4ee5\u4e8c\u8fdb\u5236\u7801 0 \u6dfb\u6ee1 ConfigView.label.zeronewfiles.tooltip=\u4f7f\u788e\u7247\u51cf\u5230\u6700\u5c11 ConfigView.section.stats=\u7edf\u8ba1 ConfigView.section.stats.enable=\u542f\u7528 ConfigView.section.stats.defaultsavepath=\u7edf\u8ba1\u4fe1\u606f\u4fdd\u5b58\u76ee\u5f55 ConfigView.section.stats.choosedefaultsavepath=\u8bf7\u9009\u62e9\u4e00\u4e2a\u4fdd\u5b58\u7edf\u8ba1\u4fe1\u606f\u7684\u76ee\u5f55 ConfigView.section.stats.savefreq=\u4fdd\u5b58\u9891\u7387 ConfigView.section.stats.minutes=\u5206\u949f ConfigView.section.stats.hours=\u5c0f\u65f6 ConfigView.section.stats.seconds=\u79d2 ConfigView.section.stats.savefile=\u7edf\u8ba1\u4fe1\u606f\u6587\u4ef6\u540d ConfigView.section.stats.graph_update_dividers=\u6bcf\u66f4\u65b060\u6b21\uff0c\u663e\u793a\u5782\u76f4\u7ebf MyTorrentsView.menu.export=XML Torrent\uff08&E\uff09\u2026 MyTorrentsView.menu.host=\u5750\u5e84\uff08&H\uff09\u2026 ManagerItem.finishing=\u6b63\u5728\u5b8c\u6210 ConfigView.dialog.choosedefaulttorrentpath=\u8bf7\u9009\u62e9\u7f3a\u7701\u7684 Torrent \u76ee\u5f55 ConfigView.dialog.choosemovepath=\u9009\u62e9\u79fb\u52a8\u7684\u76ee\u6807\u76ee\u5f55 ConfigView.label.movecompleted=\u4efb\u52a1\u5b8c\u6210\u540e\u5c06\u4efb\u52a1\u6587\u4ef6\u79fb\u52a8\u5230 ConfigView.label.moveremoved=\u5220\u9664\u4efb\u52a1\u540e\u5c06\u4efb\u52a1\u6587\u4ef6\u79fb\u52a8\u5230 ConfigView.label.savetorrents=\u4fdd\u5b58 .torrent \u6587\u4ef6 MainWindow.menu.view.mytracker=\u6211\u7684 Tracker\uff08&T\uff09 MyTrackerView.title.full=\u6211\u7684 Tracker MyTrackerView.name=\u59d3\u540d MyTrackerView.status=\u72b6\u6001 MyTrackerView.status.started=\u8fd0\u884c\u4e2d MyTrackerView.status.stopped=\u5df2\u505c\u6b62 MyTrackerView.peers=\u7528\u6237 MyTrackerView.seeds=\u79cd\u5b50 MyTrackerView.announces=\u516c\u544a MyTrackerView.uploaded=\u5df2\u4e0a\u4f20 MyTrackerView.downloaded=\u5df2\u4e0b\u8f7d MyTrackerView.left=\u5269\u4f59 ConfigView.section.style=\u754c\u9762 ConfigView.label.set_ui_transfer_speeds=\u901f\u5ea6\u5f39\u51fa\u5217\u8868 ConfigView.label.set_ui_transfer_speeds.description=\u7528\u9017\u53f7\u5206\u9694\u591a\u91cd\u6570\u503c ConfigView.label.set_ui_transfer_speeds.description.download=\u8bbe\u7f6e\u4e0b\u8f7d\u901f\u5ea6\uff08KB/s\uff09 ConfigView.label.set_ui_transfer_speeds.description.upload=\u8bbe\u7f6e\u4e0a\u4f20\u901f\u5ea6\uff08KB/s\uff09 ConfigView.section.style.useCustomTabs=\u4f7f\u7528\u53ef\u5173\u95ed\u7684\u6807\u7b7e\uff08\u9700\u8981\u91cd\u542f\uff09 MainWindow.menu.view.plugins=\u63d2\u4ef6\uff08&P\uff09 fileDownloadWindow.saveTorrentIn=\u4fdd\u5b58 Torrent \u6587\u4ef6\u5230 fileDownloadWindow.title=Vuze - Torrent \u6587\u4ef6\u4e0b\u8f7d fileDownloadWindow.downloading=\u6b63\u5728\u4e0b\u8f7d\uff0c\u4ece\uff1a fileDownloadWindow.status=\u72b6\u6001\uff1a fileDownloadWindow.state_initializing=\u521d\u59cb\u5316 fileDownloadWindow.state_downloading=\u4e0b\u8f7d\u4e2d fileDownloadWindow.state_error=\u9519\u8bef\uff1a MainWindow.menu.file.open.url=URL\uff08&U\uff09 openUrl.title=Vuze - \u6253\u5f00\u4e00\u4e2a Url openUrl.url=URL\uff1a MyTorrentsView.menu.host.error.title=\u5750\u5e84 Torrent \u5931\u8d25 MyTorrentsView.menu.host.error.message=\u5750\u5e84\u65f6\u53d1\u751f\u4ee5\u4e0b\u9519\u8bef\uff1a ConfigView.section.tracker.pollinterval=Tracker \u5ba2\u6237\u7aef Poll \u65f6\u95f4\u95f4\u9694\uff08\u79d2\uff09 ConfigView.section.tracker.publishenable=\u5c06 Torrent \u6587\u4ef6\u4fe1\u606f\u53d1\u5e03\u5230 "/" ConfigView.section.tracker.ip=Tracker \u5bf9\u5916 IP \u5730\u5740 ConfigView.section.style.enableXPStyle=\u542f\u7528 XP \u98ce\u683c\u754c\u9762\uff08\u9700\u8981\u91cd\u542f\uff09 IPChecker.external.service.dyndns.description=\u52a8\u6001 DNS \u7f51\u7edc\u670d\u52a1\uff0c LLC ConfigView.section.tracker.checkip=\u81ea\u52a8\u68c0\u67e5\u5916\u90e8\u5730\u5740\u2026 ipCheckerWizard.title=IP \u68c0\u67e5\u5411\u5bfc ipCheckerWizard.service=\u670d\u52a1 ipCheckerWizard.chooseService=\u8bf7\u4ece\u670d\u52a1\u5546\u5217\u8868\u4e2d\u9009\u62e9\u4e00\u4e2a IP \u68c0\u67e5\u670d\u52a1\u5546 ipCheckerWizard.explanations=\u4f60\u53ef\u4ee5\u4f7f\u7528\u8fd9\u4e2a\u5411\u5bfc\u627e\u5230\u4f60\u5bf9\u5916\u7684 IP \u5730\u5740\u3002\u5982\u679c\u4f60\u7684 IP \u5730\u5740\u662f\u52a8\u6001\u7684\uff0c\u6211\u4eec\u5efa\u8bae\u4f60\u5728\u52a8\u6001 DNS \u670d\u52a1\u4e0a\u5f00\u4e00\u4e2a\u5e10\u53f7\u3002\u4e0b\u9762\u662f\u4e00\u4e9b\u5217\u51fa\u7684\u670d\u52a1\u63d0\u4f9b\u5546\uff0c\u4f7f\u7528\u7ed9\u51fa\u7684\u94fe\u63a5\u5efa\u7acb\u5e10\u6237\u3002\u7136\u540e\u5c06 IP \u5730\u5740\u533a\u57df\u586b\u5199\u4e0a\u4f60\u7684\u52a8\u6001\u4e3b\u673a\u540d\uff08\u4f8b\u5982 myhostname.dyndns.org \uff09\u3002\u4f60\u5c06\u4f1a\u9700\u8981\u4e00\u4e2a\u7a0b\u5e8f\u81ea\u52a8\u5c06\u4f60\u7684 IP \u66f4\u65b0\u5230\u52a8\u6001 DNS \u670d\u52a1\u3002\u8fd9\u6837\uff0c\u751a\u81f3\u4f60\u7684 IP \u5730\u5740\u53d8\u5316\uff0c\u4e5f\u53ef\u4ee5\u4f7f\u7528\u5750\u5e84 Torrent \u6587\u4ef6\u4e86\u3002 ipCheckerWizard.service.description=\u63cf\u8ff0\uff1a ipCheckerWizard.service.url=\u8fde\u63a5\uff1a ipCheckerWizard.progresstitle=\u6b63\u5728\u68c0\u67e5 IP ipCheckerWizard.checkComplete=\u68c0\u67e5\u5b8c\u6210\u7684 IP\uff1a ipCheckerWizard.checkFailed=\u5931\u8d25\uff0c \u539f\u56e0\u662f\uff1a wizard.tracker.local=\u4f7f\u7528 Vuze \u5185\u7f6e\u7684 Tracker wizard.tracker.external=\u4f7f\u7528\u4e00\u4e2a\u5916\u90e8\u7684 Tracker wizard.tracker.howToLocal=\t\u6253\u5f00\u201c\u5de5\u5177>\u9009\u9879>Tracker \u201d\u6765\u542f\u7528 wizard.announceUrl=Announce \u5730\u5740\uff1a IPChecker.external.service.discoveryvip.description=Discoveryvip - \u4ec5\u68c0\u67e5 IP \u5730\u5740 IPChecker.external.httpinvalidresponse=\u65e0\u6548\u7684 HTTP \u8fd4\u56de IPChecker.external.loadingwebpage=\u6b63\u5728\u52a0\u8f7d Web \u9875\u9762 IPChecker.external.analysingresponse=\u6b63\u5728\u5206\u6790\u8fd4\u56de\u4fe1\u606f IPChecker.external.addressextracted=\u63d0\u53d6\u51fa\u7684 IP \u5730\u5740 IPChecker.external.httploadfail=\u52a0\u8f7d\u9875\u9762\u5931\u8d25 IPChecker.external.timeout=\u53d1\u751f\u8d85\u65f6 IPChecker.external.ipnotfound=IP \u5730\u5740\u672a\u627e\u5230 ConfigView.section.tracker.pollintervalmin=\u6700\u77ed ConfigView.section.tracker.pollintervalmax=\u6700\u957f ConfigView.section.tracker.pollintervalincby=\u589e\u52a0 ConfigView.section.tracker.pollintervalincper=\u6bcf "N" \u4e2a\u5ba2\u6237\u7aef splash.loadingImages=\u52a0\u8f7d\u56fe\u7247 splash.initializeGui=\u521d\u59cb\u5316\u4e3b\u7a97\u53e3 splash.openViews=\u6253\u5f00\u89c6\u56fe splash.plugin=\u52a0\u8f7d\u63d2\u4ef6\uff1a configureWizard.nat.tooManyPorts=\u6d4b\u8bd5\u4e86\u8fc7\u591a\u7684\u7aef\u53e3\uff08\u6700\u591a9\u4e2a\uff09 ConfigView.section.color=\u989c\u8272\u6837\u5f0f MyTorrentsView.menu.publish=\u53d1\u5e03\uff08&P\uff09\u2026 MyTrackerView.status.published=\u5df2\u53d1\u5e03 MyTrackerView.completed=\u5df2\u5b8c\u6210 MainWindow.menu.file.open.torrentnodefault=.torrent \u6587\u4ef6\uff08\u4e0d\u4f7f\u7528\u9ed8\u8ba4\u4fdd\u5b58\u4f4d\u7f6e\uff09 wizard.comment=\u6ce8\u91ca ConfigView.label.movetorrent=\u540c\u65f6\u79fb\u52a8 .torrent \u6587\u4ef6 ConfigView.label.movepartialdownloads=\u6807\u8bb0\u4e3a"\u4e0d\u4e0b\u8f7d"\u7684\u6587\u4ef6\u4e5f\u79fb\u52a8 ConfigView.label.subdir_is_in_default=\u5224\u5b9a\u201c\u9ed8\u8ba4\u76ee\u5f55\u201d\u6761\u4ef6\u65f6\uff0c\u9664\u4e86\u8be5\u4efb\u52a1\u5305\u542b\u7684\u6587\u4ef6\u5916\uff0c\u8fd8\u9700\u786e\u8ba4\u4efb\u52a1\u5305\u542b\u7684\u5b50\u76ee\u5f55 ConfigView.section.file.decoder.label=\u9ed8\u8ba4\u7f16\u7801 ConfigView.section.file.decoder.nodecoder=\u65e0 IPChecker.external.service.no-ip.description=Dynamic and Static DNS service provider\n\uff08no freely available "check address" service\uff09 ConfigView.section.tracker.publicenable=\u542f\u7528\u5916\u90e8\u7684 Torrent ConfigView.label.playdownloadspeech=\u4e0b\u8f7d\u5b8c\u6210\u540e\u8bed\u97f3\u63d0\u793a ConfigView.label.playdownloadspeech.info=\u8bed\u97f3\u670d\u52a1\u76ee\u524d\u5bf9\u82f1\u8bed\u652f\u6301\u662f\u6700\u597d\u7684 # # Tooltips # GeneralView.label.status.pieces_available.tooltip=\u5c55\u73b0\u6bcf\u4e2a\u533a\u5757\u53ef\u7528\u7684\u62f7\u8d1d\u6570\u3002\n\u5982\u679c\u53f3\u8fb9\u7684\u6570\u5b57\u5c0f\u4e8e1\uff0c\u8868\u793a\u4f60\u6ca1\u6709\u770b\u89c1\u4e00\u4e2a\u5b8c\u6574\u7684\u6587\u4ef6\u62f7\u8d1d\uff08\u56e0\u6b64\u53ef\u80fd\u96be\u4ee5\u5b8c\u6210\u4e0b\u8f7d\uff09. GeneralView.label.trackerurl.tooltip=\u70b9\u51fb\u8fd9\u91cc\u62f7\u8d1d Announce URL \u5230\u526a\u8d34\u677f GeneralView.label.trackerurlopen.tooltip=\u70b9\u51fb\u6253\u5f00 Tracker \u4e3b\u9875 # # 2.0.4.4 # ConfigView.section.style.guiUpdate=\u754c\u9762\u66f4\u65b0\u95f4\u9694 ConfigView.section.style.inactiveUpdate=\u5f53\u4e0d\u5728\u6d3b\u52a8\u7a97\u53e3\u65f6\uff0c\u6bcfN\u6b21\u754c\u9762\u66f4\u65b0\u540e\u66f4\u65b0\u4e00\u6b21\u4e3b\u7a97\u53e3 ConfigView.section.style.graphicsUpdate=\u6bcfN\u6b21\u754c\u9762\u66f4\u65b0\u540e\u66f4\u65b0\u56fe\u5f62\u6761 ConfigView.section.style.reOrderDelay=\u6bcfN\u6b21\u754c\u9762\u66f4\u65b0\u540e\u91cd\u65b0\u6392\u5e8f ConfigView.section.style.reOrderDelay.never=\u4ece\u4e0d ConfigView.section.logging=\u65e5\u5fd7 ConfigView.section.logging.enable=\u542f\u7528\u6587\u4ef6\u8bb0\u5f55\u65e5\u5fd7 ConfigView.section.logging.logdir=\u65e5\u5fd7\u6587\u4ef6\u76ee\u5f55 ConfigView.section.logging.choosedefaultsavepath=\u8bf7\u9009\u62e9\u4fdd\u5b58\u76ee\u5f55 GeneralView.label.updatein.querying=\u6b63\u5728\u67e5\u8be2\u2026 configureWizard.nat.sharePort=\u6240\u6709\u7684 Torrent \u4f7f\u7528\u4e00\u4e2a\u5171\u4eab\u7684\u7aef\u53e3 ConfigView.section.logging.maxsize=\u65e5\u5fd7\u6587\u4ef6\u6700\u5927\u78c1\u76d8\u9650\u989d ConfigView.section.tracker.passwordenableweb=\u5bf9 Tracker \u7f51\u7ad9\u4f7f\u7528\u5bc6\u7801 ConfigView.section.tracker.passwordenabletorrent=\u5bf9\u53d1\u5e03\u7684 Torrent \u4f7f\u7528\u5bc6\u7801 ConfigView.section.tracker.username=\u7528\u6237\u540d ConfigView.section.tracker.password=\u5bc6\u7801 columnChooser.title=\u9009\u62e9\u8981\u663e\u793a\u7684\u5217 columnChooser.move=\u79fb\u52a8\u884c\u4ee5\u4fbf\u91cd\u65b0\u6392\u5217 columnChooser.apply=\u5e94\u7528 columnChooser.columnname=\u5217\u540d columnChooser.columndescription=\u63cf\u8ff0 TableColumn.header.shareRatio=\u5206\u4eab\u7387 MyTorrentsView.menu.editTableColumns=\u9009\u62e9\u663e\u793a\u7684\u5217\uff08&C\uff09 wizard.operationfailed=\u64cd\u4f5c\u5931\u8d25 authenticator.title=\u9700\u8981\u8ba4\u8bc1 authenticator.realm=\u9886\u57df authenticator.user=\u7528\u6237\u540d authenticator.password=\u5bc6\u7801 ConfigView.label.allowSendVersion=\u51c6\u8bb8 Vuze \u5728\u68c0\u67e5\u65b0\u7248\u672c\u65f6 \u53d1\u9001\u533f\u540d\u7684\u7248\u672c\u53f7\u548c\u968f\u673a\u7684 ID ConfigView.label.version.info.link=\u5230\u8fd9\u91cc\u67e5\u770b\u68c0\u67e5\u7248\u672c\u65f6\u5411\u670d\u52a1\u5668\u63d0\u4ea4\u4e86\u4ec0\u4e48\u6570\u636e wizard.hint.mode=\u63d0\u793a\uff1a\t\u4f60\u53ef\u4ee5\u62d6\u653e\u4e00\u4e2a\u6587\u4ef6\u6216\u8005\u76ee\u5f55\u5230\u8fd9\u4e2a\u5411\u5bfc \t\u4ee5\u9009\u62e9\u4e00\u4e2a\u6587\u4ef6\u548c\u76ee\u5f55 wizard.hint.file=\u63d0\u793a\uff1a\t\u4f60\u4f7f\u7528\u62d6\u653e\u4e00\u4e2a\u6587\u4ef6\u6765\u9009\u62e9 wizard.hint.directory=\u63d0\u793a\uff1a\t\u4f60\u4f7f\u7528\u62d6\u653e\u4e00\u4e2a\u76ee\u5f55\u6765\u9009\u62e9 MainWindow.menu.help.checkupdate=\u68c0\u67e5\u7a0b\u5e8f\u66f4\u65b0\uff08&C\uff09 TableColumn.header.down=\u5df2\u4e0b\u8f7d TableColumn.header.up=\u5df2\u4e0a\u4f20 ConfigView.section.tracker.passwordenabletorrent.info=\u9700\u8981\u652f\u6301\u5bc6\u7801\u7684 BitTorrent \u5ba2\u6237\u7aef\uff08\u4f8b\u5982\uff1a Vuze uff09 ConfigView.section.style.confirmationOnExit=\u9000\u51fa\u65f6\u663e\u793a\u63d0\u793a\u5bf9\u8bdd\u6846 MainWindow.dialog.exitconfirmation.title=\u9000\u51fa Vuze uff1f MainWindow.dialog.exitconfirmation.text=\u4f60\u60f3\u9000\u51fa Vuze uff1f SystemTray.menu.stopalltransfers=\u505c\u6b62\u6240\u6709\u4f20\u8f93\uff08&A\uff09 TrayWindow.menu.stopalldownloads=\u505c\u6b62\u6240\u6709\u7684\u4e0b\u8f7d\uff08&A\uff09 ConfigView.section.tracker.sslport.info=\u67e5\u770b FAQ \u4ee5\u83b7\u5f97\u66f4\u591a\u4fe1\u606f wizard.tracker.ssl=\u542f\u7528 SSL ConfigView.label.playdownloadfinished=\u5f53\u4e0b\u8f7d\u5b8c\u6210\u65f6\u64ad\u653e\u58f0\u97f3 ConfigView.label.popupdownloadfinished=\u5f53\u5b8c\u6210\u4e00\u4e2a\u4e0b\u8f7d\u4efb\u52a1\u65f6\u5f39\u51fa\u63d0\u793a ConfigView.label.popupfilefinished=\u5f53\u5b8c\u6210\u4e00\u4e2a\u6587\u4ef6\u65f6\u5f39\u51fa\u63d0\u793a TableColumn.header.pieces=\u533a\u5757 TableColumn.header.pieces.info=\u663e\u793a\u4f60\u5df2\u7ecf\u4e0b\u8f7d\u7684\u533a\u5757\u7684\u56fe\u5f62\u6761 TableColumn.header.completion=\u5b8c\u6210 TableColumn.header.completion.info=\u7528\u56fe\u5f62\u8868\u73b0\u4e0b\u8f7d\u767e\u5206\u6bd4 ConfigView.section.style.showdownloadbasket=\u663e\u793a\u4e0b\u8f7d\u7bee\uff08\u62d6\u653e Torrent \u6587\u4ef6\uff09 ConfigView.section.style.alwaysShowTorrentFiles=\u603b\u662f\u5728\u8be6\u7ec6\u4fe1\u606f/\u6587\u4ef6\u4e2d\u663e\u793a Torrent \u6587\u4ef6 wizard.multitracker=\u5411 Torrent \u52a0\u5165\u591a Tracker \u4fe1\u606f wizard.multitracker.title=\u591a Tracker wizard.multitracker.configuration=\u591a Tracker \u914d\u7f6e wizard.multitracker.new=\u65b0\u5efa\u2026 wizard.multitracker.edit=\u7f16\u8f91.. wizard.multitracker.delete=\u5220\u9664 wizard.multitracker.group=Tracker \u7ec4 wizard.multitracker.edit.title=\u591a Tracker \u7f16\u8f91\u5668 wizard.multitracker.edit.name=\u540d\u79f0 wizard.multitracker.edit.save=\u4fdd\u5b58 wizard.multitracker.edit.newgroup=\u65b0\u7ec4 wizard.multitracker.edit.deletegroup=\u5220\u9664 wizard.multitracker.edit.newtracker=\u65b0 Tracker wizard.multitracker.edit.deletetracker=\u5220\u9664 wizard.multitracker.edit.edit=\u7f16\u8f91 wizard.addingmt=\u52a0\u5165\u591a Tracker \u4fe1\u606f wizard.multitracker.noannounce=Announce \u5730\u5740\u6ca1\u6709\u51fa\u73b0\u5728\u4f60\u7684 Tracker \u5217\u8868\u4e2d MyTorrentsView.menu.recheck=\u5f3a\u5236\u91cd\u65b0\u68c0\u67e5\uff08&K\uff09 iconBar.showDownloadBar.tooltip=\u663e\u793a\u8ff7\u4f60\u4efb\u52a1\u6761 iconBar.start.tooltip=\u5f00\u59cb iconBar.stop.tooltip=\u505c\u6b62 iconBar.remove.tooltip=\u9664\u53bb iconBar.openNoDefault.tooltip=\u6253\u5f00 .torrent \u6587\u4ef6\uff08\u4e0d\u4f7f\u7528\u9ed8\u8ba4\u4fdd\u5b58\u4f4d\u7f6e\uff09 iconBar.openURL.tooltip=\u6253\u5f00\u4e00\u4e2a URL iconBar.openFolder.tooltip=\u6253\u5f00\u4e00\u4e2a\u76ee\u5f55 iconBar.new.tooltip=\u751f\u6210\u4e00\u4e2a Torrent iconBar.up.tooltip=\u5411\u4e0a\u79fb\u52a8 iconBar.down.tooltip=\u5411\u4e0b\u79fb\u52a8 iconBar.run.tooltip=\u6253\u5f00 iconBar.host.tooltip=\u4f5c\u4e3a\u4e3b\u673a iconBar.publish.tooltip=\u53d1\u5e03 iconBar.editcolumns.tooltip=\u5217\u8bbe\u7f6e MyTorrentsView.menu.editTracker=\u7f16\u8f91 Tracker \u5730\u5740\uff08&E\uff09 GeneralView.menu.selectTracker=\u9009\u62e9 ConfigView.section.stats.xslfile=XSL \u6587\u4ef6\u540d ConfigView.section.stats.xslfiledetails=\u8fd9\u5c06\u88ab\u5305\u542b\u5728\u7edf\u8ba1\u6587\u4ef6\u7684 head \u6807\u7b7e ConfigView.label.savetorrentbackup=\u4fdd\u5b58\u5907\u4efd ConfigView.section.tracker.forceport=\u5f3a\u5236\u5750\u5e84\u7684\u5916\u90e8 Torrent \u4f7f\u7528\u9ed8\u8ba4\u7aef\u53e3 ConfigView.section.ipfilter.allow=\u51c6\u8bb8\u8fd9\u4e9b\u8303\u56f4\uff08\u9ed8\u8ba4\u503c\u4e3a\u62d2\u7edd\uff09 ConfigView.section.ipfilter.list.inrange=\u5728\u8303\u56f4 ConfigView.section.ipfilter.list.notinrange=\u4e0d\u5728\u4efb\u4f55\u8303\u56f4 ConfigView.section.ipfilter.list.title=\u88ab\u963b\u6321\u7684 IP \u5217\u8868 ConfigView.label.allowsameip=\u51c6\u8bb8\u540c\u4e00\u4e2a IP \u7684\u591a\u4e2a\u8fde\u63a5 ConfigView.label.allowsameip.tooltip=\u8bf7\u5728\u4f60\u786e\u5b9e\u9700\u8981\u65f6\u9009\u62e9\n\u7981\u6b62\u65f6\u662f\u5bf9\u4e0b\u8f7d\u8005\u7684\u4fdd\u62a4 ManagerItem.superseeding=\u8d85\u7ea7\u79cd\u5b50 ConfigView.label.userSuperSeeding=\u4f7f\u7528\u8d85\u7ea7\u79cd\u5b50 PeersView.uniquepiece=\u533a\u5757\uff08\u8d85\u7ea7\u79cd\u5b50\u6a21\u5f0f\uff09 PeersView.uniquepiece.none=\u65e0 PeersView.timetosend=\u91cd\u65b0\u53d1\u9001\u533a\u5757\u7684\u65f6\u95f4\uff08\u8d85\u7ea7\u79cd\u5b50\u6a21\u5f0f\uff09 ConfigView.section.style.addurlsilently=\u5b89\u9759\u5730\u6253\u5f00\u4e00\u4e2a URL \uff08\u4e0d\u663e\u793a\u5bf9\u8bdd\u6846\uff09 ConfigView.section.style.addurlsilently.tooltip=\u8b66\u544a\uff1a\u5982\u679c\u542f\u7528\uff0c\u4e3b\u7a97\u53e3\u5c06\u4e0d\u4f1a\u518d\u88ab\u6fc0\u6d3b\uff01\n\u5982\u679c\u4f60\u6ca1\u6709\u4efb\u52a1\u680f\u56fe\u6807\uff0c\u4f60\u5e94\u8be5\u53d6\u6d88\u8fd9\u4e2a\u9009\u9879\u3002 ConfigView.section.file.decoder.prompt=\u5f53\u7f16\u7801\u9009\u62e9\u53ef\u7528\u65f6\uff0c\u603b\u662f\u5f39\u51fa\u9009\u62e9\u5bf9\u8bdd\u6846\u3002 ConfigView.section.file.decoder.prompt.tooltip=\u5f53\u7f16\u7801\u9009\u62e9\u53ef\u7528\u65f6\uff0c\u603b\u662f\u5f39\u51fa\u9009\u62e9\u5bf9\u8bdd\u6846 MyTorrentsView.menu.moveTop=\u9876\u90e8\uff08&T\uff09 MyTorrentsView.menu.moveEnd=\u672b\u7aef\uff08&B\uff09 ConfigView.label.moveonlyusingdefaultsave=\u4ec5\u4ece\u9ed8\u8ba4\u4e0b\u8f7d\u76ee\u5f55\u79fb\u52a8 ConfigView.label.moveonlyusingdefaultsave.tooltip=\u4ec5\u4e0b\u8f7d\u4efb\u52a1\u4fdd\u5b58\u5728\u9ed8\u8ba4\u6570\u636e\u76ee\u5f55\u65f6\u79fb\u52a8 ConfigView.label.watchtorrentfolder=\u81ea\u52a8\u5bfc\u5165\u65b0\u7684 .torrent \u6587\u4ef6 ConfigView.label.watchtorrentfolder.tooltip=\u7ecf\u5e38\u67e5\u770b\u65b0\u7684 .torrent \u6587\u4ef6 ConfigView.label.watchtorrentfolderinterval=\u95f4\u9694 ConfigView.label.watchtorrentfolderinterval.tooltip=\u76ee\u5f55\u88ab\u518d\u6b21\u626b\u63cf\u7684\u65f6\u95f4\u95f4\u9694 ConfigView.dialog.choosewatchtorrentfolderpath=\u8bf7\u9009\u62e9 .torrent \u5bfc\u5165\u76ee\u5f55 ConfigView.label.startwatchedtorrentsstopped=\u5f00\u59cb\u65f6\u505c\u6b62 ConfigView.label.startwatchedtorrentsstopped.tooltip=\u65b0\u52a0\u5165\u7684 .torrent \u6587\u4ef6\u8fdb\u5165\u505c\u6b62\u72b6\u6001 ConfigView.section.plugins=\u63d2\u4ef6 wizard.maketorrent.filesize=\u6587\u4ef6\u5927\u5c0f wizard.maketorrent.piececount=\u533a\u5757\u6570\u76ee wizard.maketorrent.piecesize=\u533a\u5757\u5927\u5c0f wizard.maketorrent.auto=\u81ea\u52a8 MainWindow.menu.view.stats=\u7edf\u8ba1\uff08&S\uff09 SpeedView.title.full=\u6d3b\u52a8 SpeedView.downloadSpeed.title=\u4e0b\u8f7d\u901f\u5ea6 SpeedView.uploadSpeed.title=\u4e0a\u4f20\u901f\u5ea6 ConfigView.section.style.useSIUnits=\u4f7f\u7528 IEC \u5355\u4f4d\uff08\u5982 KB -> KiB\uff09 iconBar.top.tooltip=\u79fb\u52a8\u5230\u9876\u7aef iconBar.bottom.tooltip=\u79fb\u52a8\u5230\u6700\u5e95\u90e8 TableColumn.header.health=\u5065\u5eb7\u72b6\u6001 MyTorrentsView.menu.health=\u5173\u4e8e\u5065\u5eb7\u72b6\u6001 health.explain.grey=\u8868\u793a\u4f60\u7684 Torrent \u6ca1\u6709\u5728\u8fd0\u884c\uff08\u4e0b\u8f7d\u6216\u8005\u4e0a\u4f20\uff09 health.explain.red=\u8868\u793a\u4f60\u4e0b\u8f7d\u65f6\u6ca1\u6709\u8fde\u63a5\u5230\u4efb\u4f55\u7528\u6237 health.explain.blue=\u505a\u79cd\u65f6\uff0c\u5b83\u8868\u793a\u4f60\u6ca1\u6709\u8fde\u63a5\u5230\u4efb\u4f55\u7528\u6237\n\u4e0b\u8f7d\u65f6\uff0c\u5b83\u8868\u660e\u4f60\u8fde\u63a5\u5230\u4e00\u4e9b\u7528\u6237\uff0c\u4f46\u662f Tracker \u5f53\u4e86 health.explain.yellow=\u8868\u793a Tracker \u5de5\u4f5c\u6b63\u5e38\uff0c\u4f60\u5df2\u7ecf\u8fde\u63a5\u5230\u7528\u6237\u4e0a\u4e86\uff0c\u4f46\u662f\u6ca1\u6709\u4efb\u4f55\u8fdc\u7a0b\u7684\u8fde\u63a5\u8fde\u5230\u4f60\n\u5982\u679c\u4f60\u7684 Torrent \u4fdd\u6301\u5728\u9ec4\u8272\u72b6\u6001\uff0c\u8bc1\u660e\u4f60\u7684 NAT \u8bbe\u7f6e\u4e0a\u53ef\u80fd\u6709\u95ee\u9898 health.explain.green=\u8868\u793a\u4e00\u5207\u6b63\u5e38 ConfigView.section.style.alwaysRefreshMyTorrents=\u603b\u662f\u5237\u65b0 "\u6211\u7684 Torrents" ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=\u8fd9\u4e2a\u9009\u9879\u5c06\u5237\u65b0 "\u6211\u7684 Torrents" \u89c6\u56fe\u751a\u81f3\u4ed6\u6ca1\u6709\u663e\u793a\uff08\u5bf9\u4e00\u4e9b mIRC \u63d2\u4ef6\u6709\u6548\uff09 # #2.0.7.0 # security.certtruster.title=\u5b89\u5168\u8bc1\u4e66\u8b66\u544a security.certtruster.intro=\u8fd9\u4e2a\u5b89\u5168\u8bc1\u4e66\u662f\u7531\u4e00\u4e2a\u4f60\u4e0d\u4fe1\u4efb\u7684\u516c\u53f8\u9881\u53d1\u7684 security.certtruster.resource=\u8d44\u6e90\uff1a security.certtruster.issuedto=\u9881\u53d1\u7ed9\uff1a security.certtruster.issuedby=\u9881\u53d1\u673a\u6784\uff1a security.certtruster.prompt=\u4f60\u662f\u5426\u60f3\u76f8\u4fe1\uff1f security.certtruster.yes=\u662f security.certtruster.no=\u5426 ConfigView.section.tracker.torrentsperpage=\u6bcf\u9875\u663e\u793a\u591a\u5c11 Torrent\uff1f\uff3b0\uff1a\u65e0\u9650\u5236\uff3d MainWindow.menu.file.share=\u5171\u4eab\uff08&S\uff09 MainWindow.menu.file.share.file=\u6587\u4ef6\uff08&F\uff09\u2026 MainWindow.menu.file.share.dir=\u6587\u4ef6\u5939\uff08&F\uff09\u2026 MainWindow.menu.file.share.dircontents=\u6587\u4ef6\u5939\u5185\u5bb9\uff08&C\uff09\u2026 MainWindow.menu.file.share.dircontentsrecursive=\u6587\u4ef6\u5939\u5185\u5bb9\uff08\u5305\u542b\u5b50\u6587\u4ef6\u5939&R\uff09\u2026 MainWindow.dialog.share.sharefile=\u9009\u62e9\u8981\u5171\u4eab\u7684\u6587\u4ef6 MainWindow.dialog.share.sharedir=\u9009\u62e9\u8981\u5171\u4eab\u7684\u6587\u4ef6\u5939 MainWindow.dialog.share.sharedircontents=\u9009\u62e9\u8981\u5171\u4eab\u7684\u6587\u4ef6\u5939\u5185\u5bb9 MainWindow.dialog.share.sharedircontents.recursive=\u9012\u5f52\u7684 globalmanager.download.remove.veto=\u5df2\u5426\u51b3\u5220\u9664\u64cd\u4f5c plugin.sharing.download.remove.veto=\u6b64\u4e0b\u8f7d\u662f\u7531\u8d44\u6e90\u88ab\u5171\u4eab\u6240\u9020\u6210\u3002\n\u8981\u5220\u9664\u4e0b\u8f7d\uff0c\u8bf7\u5220\u9664\u5171\u4eab\u5173\u8054: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=\u4e3b\u8981 ConfigView.label.prioritizefirstpiece=\u4f18\u5148\u4e0b\u8f7d\u6587\u4ef6\u7684\u7b2c\u4e00\u4e2a\u533a\u5757 ConfigView.label.prioritizefirstpiece.tooltip=\u8bd5\u56fe\u4e0b\u8f7d\u6bcf\u4e00\u4e2a\u6587\u4ef6\u7684\u6587\u4ef6\u5934\u90e8\u5206\n\u4e3a\u4e86\u652f\u6301\u65e9\u671f\u9884\u89c8\u3002 ConfigView.section.file.confirm_data_delete=\u5220\u9664\u6570\u636e\u65f6\u663e\u793a\u786e\u8ba4\u7a97\u53e3 ConfigView.section.file.confirm_data_delete.tooltip=\u5f53\u4f7f\u7528\u201c\u5220\u9664\u201d\u65f6\u663e\u793a\u786e\u8ba4\u7a97\u53e3 ConfigView.section.file.delete.include_files_outside_save_dir=\u5f53\u5220\u9664\u6570\u636e\u65f6\uff0c\u5141\u8bb8\u79fb\u9664\u5728 torrent \u4fdd\u5b58\u76ee\u5f55\u5916\u7684\u6587\u4ef6 TrayWindow.menu.startalldownloads=\u542f\u52a8\u6240\u6709\u7684\u4e0b\u8f7d SystemTray.menu.startalltransfers=\u5f00\u59cb\u6240\u6709\u4f20\u8f93 sharing.progress.title=\u5171\u4eab\u8fdb\u5ea6 sharing.progress.hide=\u9690\u85cf MainWindow.menu.view.myshares=\u6211\u7684\u5171\u4eab MySharesView.title.full=\u6211\u7684\u5171\u4eab MySharesView.name=\u540d\u79f0 MySharesView.type=\u7c7b\u578b MySharesView.type.file=\u6587\u4ef6 MySharesView.type.dir=\u6587\u4ef6\u5939 MySharesView.type.dircontents=\u6587\u4ef6\u5939\u5185\u5bb9 MySharesView.type.dircontentsrecursive=\u6587\u4ef6\u5939\u5185\u5bb9\uff08\u5305\u542b\u5b50\u6587\u4ef6\u5939\uff09 MySharesView.menu.remove=\u5220\u9664 ConfigView.section.tracker.extensions=\u6269\u5c55 ConfigView.section.tracker.sendpeerids=\u5411\u4e0b\u8f7d\u8005\u53d1\u9001\u7528\u6237\u8ba4\u8bc1 ConfigView.section.tracker.enableudp=\u542f\u7528 UDP Tracker \u534f\u8bae plugin.sharing.torrent.remove.veto=\u8fd9\u4e2a Tracker \u6ce8\u518c\u5c06\u4f7f\u8d44\u6e90\u88ab\u5171\u4eab\n\u8981\u5220\u9664\u4e0b\u8f7d\uff0c\u8bf7\u5220\u9664\u76f8\u5173\u5171\u4eab: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=\u4e0b\u8f7d\u4e0d\u80fd\u88ab\u5220\u9664\uff0c\u56e0\u4e3a\u5b83\u6ca1\u6709\u88ab\u505c\u6b62 plugin.sharing.remove.veto=\u8fd9\u4e2a\u5171\u4eab\u662f\u4e00\u4e2a\u201c\u6587\u4ef6\u5939\u5185\u5bb9\u201d\u7684\u5b50\u5171\u4eab\u3002\u5b83\u4e0d\u80fd\u88ab\u76f4\u63a5\u5220\u9664\n\u8bf7\u5220\u9664\u6839\u5171\u4eab GeneralView.label.hash.tooltip=\u70b9\u51fb\u8fd9\u91cc\u5c06 Hash \u503c\u62f7\u8d1d\u5230\u526a\u8d34\u677f ConfigView.section.tracker.maxpeersreturned=\u6700\u5927\u8fd4\u56de\u7684\u7528\u6237\u6570\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.label.serverport=\u4f20\u5165 TCP/UDP \u76d1\u542c\u7aef\u53e3 ConfigView.label.serverport.tooltip=\u7aef\u53e3\u53f7\u5fc5\u987b\u5728 1-65535 \u8303\u56f4\u5185\uff0c\u5e76\u4e14\u4e0d\u80fd\u4e3a 6880\u3002\u56e0\u4e3a\u5b83\u662f Vuze \u5185\u90e8\u4f7f\u7528\u7aef\u53e3\u3002 configureWizard.nat.server.tcp_listen_port=\u4f20\u5165 TCP \u76d1\u542c\u7aef\u53e3 ConfigView.section.sharing=\u5171\u4eab ConfigView.section.sharing.usessl=\u4e3a\u5171\u4eab\u8d44\u6e90\u4f7f\u7528 SSL \uff08\u9700\u8981\u914d\u7f6e tracker\uff09 ConfigView.section.style.dropdiraction=\u76ee\u5f55\u62d6\u653e ConfigView.section.style.dropdiraction.opentorrents=\u6253\u5f00 Torrent ConfigView.section.style.dropdiraction.sharefolder=\u5171\u4eab\u76ee\u5f55 ConfigView.section.style.dropdiraction.sharefoldercontents=\u5171\u4eab\u76ee\u5f55\u5185\u5bb9 # # 2.0.7.x # Categories.all=\u5168\u90e8 Categories.uncategorized=\u672a\u5206\u7c7b CategoryAddWindow.message=\u8f93\u5165\u65b0\u5206\u7c7b\u540d CategoryAddWindow.title=\u6dfb\u52a0\u65b0\u5206\u7c7b ConfigView.label.autoSeedingIgnoreInfo=\u88ab\u5ffd\u7565\u7684 Torrent \u4f1a\u8fdb\u5165\u961f\u5217\u7684\u6700\u4e0b\u7aef\u3002\u5b83\u4eec\u4e0d\u4f1a\u88ab\u81ea\u52a8\u542f\u52a8\u3002\u5ffd\u7565\u89c4\u5219\u4e0d\u4f1a\u5f71\u54cd\u5230\u90a3\u4e9b\u6ee1\u8db3\u6700\u9ad8\u4f18\u5148\u7ea7\u6761\u4ef6\u7684 Torrent\u3002 ConfigView.label.directory=\u76ee\u5f55 ConfigView.label.disconnetseed.tooltip=\u5f53\u505a\u79cd\u65f6\uff0c\u65ad\u5f00\u548c\u5176\u4ed6\u79cd\u5b50\u7684\u8fde\u63a5\u3002\n\u4ed6\u4eec\u4e0d\u9700\u8981\u548c\u4f60\u901a\u8baf\u3002 ConfigView.label.ignoreCase=\u5ffd\u7565\u6587\u4ef6\u7c7b\u578b ConfigView.label.ignoreSeeds=\u8d85\u8fc7 ConfigView.label.importdirectory=\u5bfc\u5165\u76ee\u5f55 ConfigView.label.minPeersToBoostNoSeeds.tooltip=\u4efb\u4f55 Torrent \u6ca1\u6709\u79cd\u5b50\u5e76\u4e14\u62e5\u6709\u5c11\u4e8e\u4f60\u6307\u5b9a\u7528\u6237\u7684\u4e2a\u6570\uff0c\n\u5c06\u88ab\u79fb\u52a8\u5230\u961f\u5217\u7684\u6700\u540e\u3002 ConfigView.label.minPeersToBoostNoSeeds=\u964d\u4f4e\u4f18\u5148\u7ea7\uff0c\u5f53\u4e00\u4e2a Torrent \u6ca1\u6709\u79cd\u5b50\u5e76\u4e14\u7528\u6237\u6570\u5c11\u4e8e ConfigView.label.minSeedingTime.tooltip=\u505a\u79cd\u7684\u4f18\u5148\u7ea7\u53ef\u80fd\u5728\u5f88\u77ed\u7684\u65f6\u95f4\u5185\u4e0a\u4e0b\u6d6e\u52a8\uff0c\u6709\u7684\u65f6\u5019\u5bfc\u81f4 Torrent \u521a\u521a\u505c\u6b62\u6216\u6392\u961f\u540e\u5c31\u7acb\u5373\u81ea\u52a8\u542f\u52a8\u3002\n\u8fd9\u4e2a\u53c2\u6570\u901a\u8fc7\u5f3a\u5236 Torrent \u4fdd\u6301\u505a\u79cd\u4e00\u6bb5\u65f6\u95f4\u6765\u7f13\u89e3\u8fd9\u4e2a\u95ee\u9898\u3002\u4f60\u53ef\u4ee5\u624b\u5de5\u505c\u6b62\u5b83\u7684\u64cd\u4f5c\u3002 ConfigView.label.minSeedingTime=\u6700\u77ed\u505a\u79cd\u65f6\u95f4\uff3b\u79d2\uff3d ConfigView.label.minSpeedForActiveDL.tooltip=\u542f\u52a8\u4e00\u4e2a\u672a\u5b8c\u6210\u7684\u4e00\u4e2a\u4e0b\u8f7d\u4f4d\u4e00\u822c\u5728\u5f00\u59cb\u4f1a\u521d\u59cb\u531630\u79d2\u3002 ConfigView.label.minSpeedForActiveDL=\u901f\u5ea6\u4f4e\u4e8e\u8be5\u503c\u65f6\uff0c\u4e0d\u8ba1\u4e0b\u8f7d\u4efb\u52a1\u6570 ConfigView.label.peers=\u7528\u6237 ConfigView.label.queue.debuglog=\u8bb0\u5f55\u8c03\u8bd5\u4fe1\u606f ConfigView.label.queue.debuglog.info=\u6dfb\u52a0\u961f\u5217\u8c03\u8bd5\u4fe1\u606f\u5230\u63a7\u5236\u53f0/\u65e5\u5fd7\u6587\u4ef6\u3002\n\u867d\u7136\u53ef\u8bfb\u6027\u4e0d\u5f3a\uff0c\u8c03\u8bd5\u4fe1\u606f\u6254\u53ef\u4ee5\u544a\u8bc9\u4f60\u4f60\u7684 Torrent \u7684\u72b6\u6001\uff0c\u4ee5\u53ca\u4ed6\u4e3a\u4ec0\u4e48\u542f\u52a8/\u6392\u961f\uff0c\u6216\u4e3a\u4ec0\u4e48\u6ca1\u6709\u542f\u52a8/\u6392\u961f\u3002 ConfigView.label.queue.minQueueingShareRatio=\u4e0d\u8981 Torrent \u505c\u6b62/\u6392\u961f\uff0c\u76f4\u5230\u5206\u4eab\u7387\u8fbe\u5230 ConfigView.label.ratio=\u5206\u4eab\u7387 ConfigView.label.removeOnStop=\u5f53 Torrent \u81ea\u52a8\u505c\u6b62\u65f6\uff0c\u4ece\u5217\u8868\u4e2d\u5220\u9664\u5b83\u3002 ConfigView.label.savedirectory=\u4fdd\u5b58\u76ee\u5f55 ConfigView.label.seeding.autoReposition.tooltip=\u5982\u679c\u542f\u7528\uff0cTorrent \u7684\u987a\u5e8f\uff08#\u5217\uff09\u5c06\u88ab\u66f4\u6539\u5230\u7b26\u5408\u505a\u79cd\u7ea7\u522b\n\u8fd9\u5728\u5982\u679c\u4f60\u4e0d\u60f3\u770b\u89c1\u505a\u79cd\u7b49\u7ea7\uff0c\u53c8\u5e0c\u671b\u77e5\u9053\u5df2\u7ecf\u5b8c\u6210\u7684 Torrent \u7684\u542f\u52a8\u987a\u5e8f\u7684\u65f6\u5019\u975e\u5e38\u6709\u7528\u3002 ConfigView.label.seeding.autoReposition=\u81ea\u52a8\u6839\u636e\u7ea7\u522b\u5bf9 Torrent \u6392\u5e8f ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u4e00\u822c\u6765\u8bf4\uff0c\u4e00\u4e2a\u62e5\u6709\u79cd\u5b50\u5f88\u5c11\u800c\u7528\u6237\u5f88\u591a\u7684 Torrent \u4e00\u822c\u610f\u5473\u7740\u7528\u6237\u4e2d\u53ef\u80fd\u6ca1\u6709\u4e00\u4e2a\u5b8c\u6574\u7684\u6863\u6848\n\u56e0\u6b64\uff0c\u4f60\u53ef\u80fd\u4e0d\u5e0c\u671b\u505a\u79cd\u89c4\u5219\u5047\u88c5\u8fd9\u91cc\u6709\u4e00\u4e2a\u5b8c\u6574\u7684\u62f7\u8d1d\u3002\uff08\u6240\u4ee5\u4e0d\u6b63\u786e\u7684\u964d\u4f4e\u5b83\u7684\u7ea7\u522b\uff09 ConfigView.label.seeding.fakeFullCopySeedStart=\u524d\u63d0\uff1a\u79cd\u5b50\u6570\u76ee\u8d85\u8fc7 ConfigView.label.seeding.ignore=\u5ffd\u7565\u89c4\u5219 ConfigView.label.seeding.ignore0Peers=\u5ffd\u7565\u5e26\u6709 0 \u4e2a\u7528\u6237\u7684 Torrent ConfigView.label.seeding.ignoreRatioPeers=\u79cd\u5b50\uff1a\u7528\u6237 > 1\u79cd\u5b50\uff1a ConfigView.label.seeding.ignoreShareRatio=\u5206\u4eab\u7387\u4e3a ConfigView.label.seeding.ignore.header.evenFirstPriority=\u5ffd\u7565 Torrent\uff0c\u5373\u4f7f\u6700\u9ad8\u4f18\u5148\u7ea7\u89c4\u5219\u5df2\u7ecf\u751f\u6548\u3002 ConfigView.label.seeding.ignore.header.rule=\u89c4\u5219 ConfigView.label.seeding.ignore.header.value=\u503c ConfigView.label.seeding.firstPriority.info=\u6700\u9ad8\u4f18\u5148\u7ea7\u7684 Torrent \u5c06\u4e00\u76f4\u5904\u4e8e\u961f\u5217\u7684\u6700\u4e0a\u8fb9\u3002\u5bf9\u4e8e\u201c\u65e0\u201d\u548c\u201c\u8ba1\u65f6\u5207\u6362\u201d\u7684\u7b49\u7ea7\u7c7b\u578b\uff0c\u4efb\u4f55\u6ee1\u8db3\u6700\u9ad8\u4f18\u5148\u6761\u4ef6\u7684 Torrent \u5c06\u4e0d\u4f1a\u88ab\u81ea\u52a8\u505c\u6b62\u548c\u6392\u961f\u3002\u4e00\u4e2a\u6700\u9ad8\u4f18\u5148\u6761\u4ef6\u7684 Torrent \u5c06\u4f1a\u6839\u636e\u9700\u8981\u5360\u7528\u4e00\u4e2a\u4e0b\u8f7d\u4f4d\u3002 ConfigView.label.seeding.firstPriority.FP=\u7b2c\u4e00\u4f18\u5148\u7ea7 ConfigView.label.seeding.firstPriority=\u6700\u9ad8\u4f18\u5148\u7ea7\u89e6\u53d1\u6761\u4ef6 ConfigView.label.seeding.firstPriority.following=\u6761\u4ef6\u65f6\u751f\u6548 ConfigView.label.seeding.firstPriority.shareRatio=\u5206\u4eab\u7387\u4f4e\u4e8e ConfigView.label.seeding.firstPriority.seedingMinutes=\u505a\u79cd\u65f6\u95f4 ConfigView.label.seeding.firstPriority.DLMinutes=\u4e0b\u8f7d\u65f6\u95f4 ConfigView.label.seeding.numPeersAsFullCopy.tooltip=\u901a\u8fc7\u5047\u5b9a\u5bf9\u6bcfX\u4e2a\u7528\u6237\u6709\u4e00\u4e2a\u5b8c\u6574\u62f7\u8d1d\uff0c\u4f60\u964d\u4f4e\u4e86\u90a3\u4e9b\u62e5\u6709\u5f88\u591a\u7528\u6237\u7684 Torrent \u7684\u7b49\u7ea7\n\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u4e00\u4e2a\u7528\u6237\u5f88\u591a\u7684 Torrent \u4f1a\u62e5\u6709\u5f88\u9ad8\u7684\u901a\u8baf\u91cf\u3002\n\u8fd9\u4e0d\u4f1a\u6539\u53d8\u4efb\u4f55\u201c\u79cd\u5b50\u6570\u76ee\u201d\u663e\u793a\u3002 ConfigView.label.seeding.numPeersAsFullCopy=\u5047\u5b9a\u8fd9\u91cc\u6709\u4e00\u4e2a\u5b8c\u6574\u7684\u62f7\u8d1d\uff0c\u5728\u6bcf\n\uff080\uff1a\u4e0d\u5047\u5b9a\uff09 ConfigView.label.seeding.preferLargerSwarms.tooltip=\u5982\u679c\u4f60\u505a\u79cd\u65f6\uff0c\u7528\u6237\u5927\u591a\u662f\u505c\u7559\u5728\u67d0\u4e00\u8fdb\u5ea6\u72b6\u6001\uff0c\u9009\u62e9\u7528\u6237\u7fa4\u8f83\u5927\u7684 Torrent \u4f18\u5148\u6bd4\u8f83\u5408\u7406\n\u5982\u679c\u8be5\u7528\u6237\u7fa4\u53ef\u7528\u6027\u8f83\u9ad8\uff0c\u9009\u62e9\u7528\u6237\u7fa4\u8f83\u5c0f\u7684 Torrent \u8f83\u597d\u3002 ConfigView.label.seeding.preferLargerSwarms=\u5982\u679c Torrent \u6c38\u8fdc\u76f8\u540c\u7684\u7ea7\u522b\uff0c\u7528\u6237\u7fa4\u8f83\u5927\u8005\u4f18\u5148\u3002 ConfigView.label.seeding.rankType.none.tooltip=\u6839\u636e # \u5217\u6392\u5e8f ConfigView.label.seeding.rankType.none=\u65e0 ConfigView.label.seeding.rankType.peer.tooltip=\u66f4\u591a\u7684\u7528\u6237\u53ca\u66f4\u5c11\u7684\u79cd\u5b50 = \u66f4\u9ad8\u7ea7\u522b\n\u8fd9\u4e2a\u7ea7\u522b\u6700\u5c0f\u5316\u6d3b\u52a8\u7684torrents \u6570\u91cf\u6765\u4fdd\u8bc1\u6700\u5927\u5316\u7684\u4e0a\u4f20 ConfigView.label.seeding.rankType.peer=\u52a0\u6743\u7528\u6237\u8ba1\u6570 ConfigView.label.seeding.rankType.peerSeed.options=\u79cd\u5b50\uff1a\u7528\u6237\u6bd4\u7387\u9009\u9879 ConfigView.label.seeding.rankType.peerSeed.tooltip=\u66f4\u9ad8\u7684\u6bd4\u7387\u8868\u793a\u66f4\u9ad8\u7684\u7ea7\u522b ConfigView.label.seeding.rankType.peerSeed=\u7528\u6237\uff1a\u79cd\u5b50\u6bd4\u7387 ConfigView.label.seeding.rankType.seed.fallback=\u6539\u53d8\u5230\u7528\u6237\uff1a\u79cd\u5b50\u6bd4\u7387\u89c4\u5219\uff0c\u5f53\u79cd\u5b50\u6570\u8fbe\u5230\n\uff080\uff1a\u6c38\u8fdc\u4e0d\u6539\u53d8\uff09 ConfigView.label.seeding.rankType.seed.options=\u4ec5\u4f7f\u7528\u79cd\u5b50\u6570\u7684\u9009\u9879 ConfigView.label.seeding.rankType.seed.tooltip=\u79cd\u5b50\u8f83\u5c11\u7684 Torrent \u5c06\u88ab\u63d0\u9ad8\u7b49\u7ea7 ConfigView.label.seeding.rankType.seed=\u79cd\u5b50\u6570 ConfigView.label.seeding.rankType.timedRotation.tooltip=\u6240\u6709\u961f\u5217\u4e2d\u5df2\u7ecf\u5b8c\u6210\u7684 Torrent \u5c06\u4f1a\u5207\u6362\u5230\u505a\u79cd\u6a21\u5f0f\u3002\n\u505a\u79cd\u65f6\u95f4\u7531\u201c\u6700\u5c0f\u505a\u79cd\u65f6\u95f4\u201d\u8bbe\u5b9a\u3002 ConfigView.label.seeding.rankType.timedRotation=\u8ba1\u65f6\u5207\u6362 ConfigView.label.seeding.rankType.tooltip=\u6700\u9ad8\u7b49\u7ea7\u7684 Torrent \u4f1a\u88ab\u81ea\u52a8\u542f\u52a8\u3002\n\u5f53\u5176\u4ed6\u7684 Torrent \u5f97\u5230\u66f4\u9ad8\u7684\u7ea7\u522b\u65f6\uff0c\u4f4e\u7ea7\u522b\u7684 Torrent \u5c06\u505c\u6b62\u5e76\u8fd4\u56de\u961f\u5217\u3002\n\n\u4ec5\u6392\u961f\u72b6\u6001\u7684 Torrent \u53ef\u4ee5\u81ea\u52a8\u542f\u52a8\u3002\n\u88ab\u505c\u6b62\u7684 Torrent \u6c38\u8fdc\u4e0d\u4f1a\u88ab\u81ea\u52a8\u542f\u52a8\u3002 ConfigView.label.seeding.rankType=\u4f7f\u7528\u4e0b\u9762\u7684\u89c4\u5219\u8bc4\u5b9a\u505a\u79cd\u7b49\u7ea7\uff1a ConfigView.label.stopAfterMinutes=\u4e00\u65e6\u5f00\u59cb\u505a\u79cd\uff0c\u5728\u4e00\u6bb5\u65f6\u95f4\u540e\u505c\u6b62\u3002 ConfigView.label.switchpriority.tooltip=\u4f4e\u4f18\u5148\u7ea7\u7684 Torrent \u5c06\u964d\u4f4e\u5360\u7528\u7684\u4e0a\u4f20\u5e26\u5bbd ConfigView.pluginlist.info=\u8bc6\u522b\u51fa\u4e0b\u5217\u63d2\u4ef6\u3002\u67d0\u4e9b\u63d2\u4ef6\u53ef\u80fd\u6ca1\u6709\u914d\u7f6e\u6807\u7b7e\u3002 ConfigView.pluginlist.noplugins=\u6ca1\u6709\u627e\u5230\u4efb\u4f55\u63d2\u4ef6 ConfigView.section.pluginslist=\u5217\u8868 ConfigView.section.queue.seeding=\u6b63\u5728\u505a\u79cd ConfigView.section.queue.seeding.autoStarting=\u6b63\u5728\u81ea\u52a8\u542f\u52a8 ConfigView.section.queue.seeding.ignore=\u5ffd\u7565\u89c4\u5219 ConfigView.section.queue.seeding.firstPriority=\u6700\u9ad8\u4f18\u5148\u7ea7 ConfigView.section.queue.main=\u4e3b ConfigView.section.queue=\u961f\u5217 ConfigView.section.torrents=Torrent ConfigView.text.all=\u5168\u90e8 ConfigView.text.hours=\u5c0f\u65f6 ConfigView.text.ignoreRule=\u5ffd\u7565\u89c4\u5219 ConfigView.text.ignore=\u5ffd\u7565 ConfigView.text.minutes=\u5206\u949f ConfigView.text.neverIgnore=\u4ece\u4e0d\u5ffd\u7565 ConfigView.text.any=\u4efb\u4f55 DownloadManager.error.datamissing=\u6570\u636e\u4e22\u5931 MainWindow.menu.file.open.torrentforseeding=.torrent \u6587\u4ef6\uff08\u4e3a\u505a\u79cd\uff09 MainWindow.menu.language.refresh=\u5237\u65b0\uff08&R\uff09 ManagerItem.forced=\u5f3a\u5236\u7684 ManagerItem.queued=\u6392\u961f\u4e2d MySeedersView.header=\u5df2\u5b8c\u6210\u7684 Torrent TableColumn.header.availability.info=\u5df2\u89c1\u7684\u5b8c\u6574\u62f7\u8d1d\u6570 TableColumn.header.availability=\u53ef\u7528\u6027 TableColumn.header.category=\u5206\u7c7b MyTorrentsView.header=\u672a\u5b8c\u6210\u7684 Torrent TableColumn.header.maxuploads=\u6700\u5927\u4e0a\u4f20\u6570 MyTorrentsView.menu.category.delete=\u5220\u9664\u5206\u7c7b\uff08&D\uff09 MyTorrentsView.menu.forceStart=\u5f3a\u5236\u542f\u52a8\uff08&F\uff09 MyTorrentsView.menu.queue=\u961f\u5217\uff08&Q\uff09 MyTorrentsView.menu.setCategory.add=\u6dfb\u52a0\u5206\u7c7b\uff08&A\uff09 MyTorrentsView.menu.setCategory=\u8bbe\u5b9a\u5206\u7c7b TableColumn.header.savepath=\u4fdd\u5b58\u76ee\u5f55 TableColumn.header.SeedingRank=\u505a\u79cd\u7ea7\u522b TableColumn.header.totalspeed.info=\u4f60\u6240\u5728\u7fa4\u7684\u6240\u6709\u7528\u6237\u4e0b\u8f7d\u901f\u5ea6\u603b\u548c TableColumn.header.totalspeed=\u7fa4\u4f53\u901f\u5ea6 splash.initializePlugins=\u521d\u59cb\u5316\u63d2\u4ef6 StartStopRules.SPratioMet=S\uff1aP \u6bd4\u7387\u6b63\u5e38 StartStopRules.FP0Peers=FP / 0 \u7528\u6237 StartStopRules.0Peers=0 \u7528\u6237 StartStopRules.numSeedsMet=# \u79cd\u5b50 OK StartStopRules.ratioMet=\u7528\u6237\uff1a\u79cd\u5b50 OK StartStopRules.shareRatioMet=\u5206\u4eab\u7387 OK StartStopRules.waiting=\u7b49\u5f85\u4e2d StartStopRules.firstPriority=\u6700\u9ad8\u4f18\u5148\u7ea7 ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\u5171\u4eab\u5185\u5bb9\uff08\u5305\u62ec\u5185\u542b\u6587\u4ef6\u5939\uff09 DownloadManager.error.unabletostartserver=\u65e0\u6cd5\u542f\u52a8\u670d\u52a1\u5668 - \u68c0\u6d4b\u4f20\u5165\u7aef\u53e3\u8bbe\u7f6e\u6216\u9632\u706b\u5899\u662f\u5426\u51c6\u8bb8\u5e94\u7528\u6210\u4e3a\u670d\u52a1\u5668\u3002 GeneralView.label.creationdate=\u521b\u5efa\u4e8e\uff1a ConfigView.section.tracker.announcescrapepercentage=\u67e5\u8be2\u95f4\u9694\u4e0e Announce \u65f6\u95f4\u7684\u767e\u5206\u6bd4\n\u4f8b\u5982 200 = 2\uff1a1. 0 = \u7531\u7528\u6237\u51b3\u5b9a ManagerItem.stopping=\u6b63\u5728\u505c\u6b62 ConfigView.section.tracker.announcecacheperiod=\u901a\u544a\u7f13\u5b58\uff08\u6beb\u79d2\uff09 ConfigView.section.tracker.scrapecacheperiod=\u67e5\u8be2\u7f13\u5b58\uff08\u6beb\u79d2\uff09 ConfigView.section.tracker.scrapeandcache=\u67e5\u8be2\u548c\u7f13\u5b58 ConfigView.section.tracker.announcecacheminpeers=\u542f\u7528\u901a\u544a\u7f13\u5b58\uff0c\u5f53\u7528\u6237\u6570\u8fbe\u5230 MyTrackerView.scrapes=\u67e5\u8be2 fileDownloadWindow.retry=\u91cd\u8bd5 MyTrackerView.bytesin=\u4f20\u5165\u7684\u5b57\u8282 MyTrackerView.bytesinave=\u5e73\u5747\u4f20\u5165\u7684\u5b57\u8282 MyTrackerView.bytesout=\u53d1\u9001\u7684\u5b57\u8282 MyTrackerView.bytesoutave=\u5e73\u5747\u53d1\u9001\u7684\u5b57\u8282 ConfigView.section.file.max_open_files=\u6700\u5927\u7684\u8bfb\u5199\u6587\u4ef6\u6570\n\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.section.file.max_open_files.tooltip=\u8fd9\u4e2a\u9009\u9879\u5bf9\u4e8e\u4e0b\u8f7d\u7684 Torrent \u6709\u4e0a\u767e\u3001\u4e0a\u5343\u4e2a\u6587\u4ef6\uff0c\u800c\u4f60\u8fbe\u5230\u4e86\u64cd\u4f5c\u7cfb\u7edf\u6587\u4ef6\u5904\u7406\u4e0a\u9650\u7684\u60c5\u51b5\u65f6\u6709\u7528\u3002 ConfigView.section.proxy=\u4ee3\u7406\u670d\u52a1\u5668 ConfigView.section.proxy.enable_proxy=\u542f\u7528\u4ee3\u7406\u670d\u52a1\u5668 ConfigView.section.proxy.host=\u4e3b\u673a ConfigView.section.proxy.port=\u7aef\u53e3 ConfigView.section.proxy.username=\u7528\u6237\u540d ConfigView.section.proxy.password=\u5bc6\u7801 ConfigView.section.proxy.enable_socks=\u6211\u6709\u4e00\u4e2a SOCKS \u4ee3\u7406 wizard.createtorrent.extrahashes=\u589e\u52a0\u4e3a\u5176\u4ed6 P2P \u7cfb\u7edf\u4f7f\u7528\u7684 Hash \u503c\uff08\u4f8b\u5982 Gnutella2\uff0c eDonkey2000\uff09 GeneralView.label.connected=\u5df2\u8fde\u63a5 GeneralView.label.in_swarm=\u7fa4\u4f53 ManagerItem.initializing=\u521d\u59cb\u5316 AlertMessageBox.error=\u9519\u8bef AlertMessageBox.warning=\u8b66\u544a AlertMessageBox.comment=\u4fe1\u606f AlertMessageBox.information=\u4fe1\u606f AlertMessageBox.unread=\u4f60\u8fd8\u6ca1\u6709\u9605\u8bfb\u63d0\u793a\u4fe1\u606f - \u8bf7\u70b9\u51fb\u8fd9\u91cc\u67e5\u770b. SharedPortServer.alert.selectorfailed=\u4f20\u5165\u6570\u636e\u76d1\u542c\u5931\u8d25\u3002\n\u8bf7\u68c0\u67e5\u9632\u706b\u5899\u8bbe\u7f6e\u662f\u5426\u51c6\u8bb8 java \uff08w\uff09.exe\u6210\u4e3a\u201c\u670d\u52a1\u5668\u201d\u3002 Tracker.alert.listenfail==\u4e0d\u80fd\u5efa\u7acb\u5728 %1 \u7aef\u53e3\u4e0a\u7684\u76d1\u542c\u3002\n\u68c0\u67e5\u5176\u4ed6\u5e94\u7528\u7a0b\u5e8f\u4e0d\u8981\u5360\u7528\u8fd9\u4e2a\u7aef\u53e3\n\u5e76\u4e14\u68c0\u67e5\u662f\u5426\u6709\u53e6\u4e00\u4e2a Vuze \u6b63\u5728\u8fd0\u884c\u3002 DiskManager.alert.movefileexists=\u79fb\u52a8\u5df2\u5b8c\u6210\u6587\u4ef6\u51fa\u9519\n\u6587\u4ef6 %1 \u5df2\u7ecf\u5b58\u5728\u4e0e\u76ee\u6807\u76ee\u5f55\u4e0b\u4e86\u3002 DiskManager.alert.movefilefails=\u79fb\u52a8\u5df2\u5b8c\u6210\u6587\u4ef6\u51fa\u9519\n\u79fb\u52a8 %1 \u5931\u8d25\uff0c %2 DiskManager.alert.movefilerecoveryfails=\u79fb\u52a8\u51fa\u9519\u7684\u6062\u590d\u5931\u8d25\n\u6062\u590d\u6587\u4ef6 %1 \u5931\u8d25\uff0c %2 ConfigView.section.tracker.logenable=\u8bb0\u5f55\u5468\u671f\u6027\u7684\u7edf\u8ba1\u4fe1\u606f\u5230 \u201c tracker.log \u201d SpeedView.stats.title=\u72b6\u6001 SpeedView.stats.total=\u5408\u8ba1 SpeedView.stats.session=\u672c\u6b21\u4f1a\u8bdd SpeedView.stats.session.tooltip=\u603b\u8ba1\uff08\u534f\u8bae\uff09 SpeedView.stats.downloaded=\u5df2\u4e0b\u8f7d SpeedView.stats.uploaded=\u5df2\u4e0a\u4f20 SpeedView.stats.ratio=\u6bd4\u7387 SpeedView.stats.uptime=\u8fd0\u884c\u65f6\u95f4 SpeedView.stats.now=\u5f53\u524d SpeedView.stats.now.tooltip=\u603b\u8ba1\uff08\u534f\u8bae\uff09 AutoMigration.useralert=Vuze \u7528\u6237\u914d\u7f6e\u6587\u4ef6/\u76ee\u5f55\u81ea\u52a8\u8fc1\u79fb\u7ed3\u679c\uff1a\n\n%1\n\u4efb\u4f55\u5931\u8d25\u7684\u64cd\u4f5c\u90fd\u5fc5\u987b\u624b\u52a8\u5b8c\u6210\u3002\n\u5f53\u6210\u529f\u8fc1\u79fb\u540e\uff0c\u8bf7\u4e0d\u8981\u5fd8\u8bb0\u5728\u8bbe\u7f6e\u4e2d\u66f4\u65b0\u7684\u4f60\u6587\u4ef6\u50a8\u5b58\u76ee\u5f55\uff01 # # > 2.0.8.0 # OpenTorrentWindow.title=\u6253\u5f00 Torrent OpenTorrentWindow.message=\u5b9e\u9a8c\u7684 OpenTorrentWindow.addFiles=\u6dfb\u52a0\u6587\u4ef6\uff08&A\uff09 OpenTorrentWindow.dataLocation=\u4fdd\u5b58\u6570\u636e\u7684\u4f4d\u7f6e OpenTorrentWindow.startMode=\u6dfb\u52a0\u6a21\u5f0f OpenTorrentWindow.startMode.queued=\u6392\u961f\u4e2d OpenTorrentWindow.startMode.stopped=\u5df2\u505c\u6b62 OpenTorrentWindow.startMode.forceStarted=\u5f3a\u5236\u505c\u6b62 OpenTorrentWindow.addPosition=\u961f\u5217\u4f4d\u7f6e OpenTorrentWindow.addPosition.first=\u7b2c\u4e00 OpenTorrentWindow.addPosition.last=\u6700\u540e TableColumn.header.remaining.info=\u5269\u4f59\u4e0b\u8f7d\u91cf TableColumn.header.remaining=\u5269\u4f59\u4e0b\u8f7d\u91cf ConfigView.section.tracker.enablecompact=\u542f\u7528\u7cbe\u7b80 Announce \u534f\u8bae ConfigView.section.tracker.enablekey=\u4e3a\u589e\u5f3a\u5b89\u5168\u542f\u7528\u4f20\u9012\u952e\u7ed9 Tracker ConfigView.section.file.perf=\u6027\u80fd\u9009\u9879 ConfigView.section.file.perf.explain=\u8b66\u544a - \u65e0\u9650\u5236\u7684\u66f4\u6539\u8fd9\u4e9b\u53c2\u6570\u53ef\u80fd\u5bf9\u4e0b\u8f7d\u6027\u80fd\u9020\u6210\u76f8\u53cd\u7684\u5f71\u54cd\u3002\u9700\u8981\u91cd\u542f\u3002\n\u5982\u679c\u4f60\u9047\u5230 "out of memory" \u9519\u8bef\uff0c\u8bf7\u9650\u5236\u6bcf\u4e2a Torrent \u7684\u8fde\u63a5\u6570\uff08\u67e5\u770b\u4f20\u8f93\u914d\u7f6e\uff09\u3002 ConfigView.section.file.max_open_files.explain=\u6253\u5f00\u8fc7\u591a\u6587\u4ef6\u53ef\u80fd\u56e0\u4e3a\u5982\u6587\u4ef6\u53e5\u67c4\u7b49\u8d44\u6e90\u9650\u5236\u9020\u6210\u64cd\u4f5c\u7cfb\u7edf\u95ee\u9898\u3002\u8fd9\u4e2a\u8bbe\u5b9a\u9650\u5236\u4e86\u540c\u65f6\u6253\u5f00\u6587\u4ef6\u7684\u6570\u76ee\u3002 popup.error.hide=\u9690\u85cf popup.error.details=\u7ec6\u8282 ConfigView.section.style.colorOverrides=\u989c\u8272\u8986\u76d6 ConfigView.section.style.colorOverride.progressBar=\u8fdb\u5ea6\u6761 ConfigView.section.style.colorOverride.error=\u9519\u8bef MainWindow.status.tooOld=\u7248\u672c\u592a\u65e7\uff0c\u8bf7\u66f4\u65b0\u3002 ConfigView.section.style.colorOverride.warning=\u8b66\u544a ConfigView.section.style.colorOverride.altRow=\u5176\u4ed6\u884c ConfigView.section.file.save.peers.enable=\u4e3a\u5feb\u901f\u8fde\u63a5\u4fdd\u5b58\u7528\u6237\u7684\u8fde\u63a5 ConfigView.section.file.save.peers.max=\u6700\u591a\u4fdd\u5b58\u7684\u7528\u6237\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.section.file.save.peers.pertorrent=\u6bcf Torrent ConfigView.label.max_peers_per_torrent=\u6bcf\u4e2a Torrent \u7684\u6700\u5927\u8fde\u63a5\u6570\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.label.max_peers_total=\u5168\u5c40\u6700\u5927\u8fde\u63a5\u6570\u91cf\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.section.style.colorOverrides.reset=\u91cd\u7f6e\u989c\u8272 ConfigView.section.language.info=\u5982\u679c\u542f\u7528\uff0c\u6bcf\u6b21 Vuze \u542f\u52a8\u90fd\u4f1a\u68c0\u67e5\u66f4\u65b0\u3002 ConfigView.section.language.enableUpdate=\u542f\u7528\u7f51\u7ad9\u66f4\u65b0 ConfigView.section.language.UpdateURL=\u66f4\u65b0 URL ConfigView.section.language.UpdateNow=\u7acb\u5373\u66f4\u65b0\uff01 Button.revert=\u6062\u590d MyTorrentsView.menu.changeDirectory=\u6539\u53d8\u6570\u636e\u76ee\u5f55 GenericText.column=\u5217 MyTorrentsView.menu.thisColumn.remove=\u79fb\u9664\u5217 MyTorrentsView.menu.thisColumn.toClipboard=\u62f7\u8d1d\u6587\u672c\u5230\u526a\u8d34\u677f MyTorrentsView.menu.thisColumn.autoTooltip=\u603b\u662f\u663e\u793a\u63d0\u793a MyTorrentsView.menu.tracker=Tracker \u72b6\u6001 ConfigView.download.abbreviated=\u2193\uff1a ConfigView.upload.abbreviated=\u2191\uff1a ConfigView.complete.abbreviated=\u5b8c\uff1a TableColumn.header.secondsseeding=\u505a\u79cd\u65f6\u95f4 TableColumn.header.secondsseeding.info=\u4f60\u5df2\u7ecf\u505a\u79cd\u7684\u65f6\u95f4 TableColumn.header.secondsdownloading=\u5df2\u4e0b\u8f7d TableColumn.header.secondsdownloading.info=\u4f60\u5df2\u7ecf\u4e0b\u8f7d\u7684\u65f6\u95f4 ConfigView.section.tracker.udpversion=UDP \u534f\u8bae\u7248\u672c\uff081 \u6216 2\uff09 window.updateswt.title=\u4f60\u7684 SWT \u7248\u672c\u592a\u8001\u4e86\uff01 window.updateswt.text=\u4f60\u7684 SWT \u7248\u672c\u592a\u8001\u4e86\uff01\nSWT \u662f Vuze \u4f7f\u7528\u7684\u56fe\u5f62\u5e93\uff0c\u4f60\u6b63\u5728\u4f7f\u7528\u7248\u672c\u6bd4\u6700\u65b0\u7684 Vuze \u8fd0\u884c\u4f7f\u7528\u7684\u7248\u672c\u8981\u8001\u3002\u70b9\u51fb\u786e\u5b9a\u66f4\u65b0\u4f60\u7684 SWT\u3002 window.updateswt.status=\u72b6\u6001 window.updateswt.failed=\u66f4\u65b0\u5931\u8d25\uff0c\u70b9\u51fb\u786e\u5b9a\u91cd\u65b0\u5f00\u59cb\u3002 window.updateswt.status.downloading.updater=\u6b63\u5728\u4e0b\u8f7d\u66f4\u65b0\u6a21\u5757 window.updateswt.status.finding=\u67e5\u627e\u6700\u65b0\u7684 SWT \u7248\u672c window.updateswt.status.downloading=\u6b63\u5728\u4e0b\u8f7d\u6700\u65b0\u7684 SWT \u7248\u672c window.updateswt.status.done=\u6b63\u5728\u91cd\u542f window.updateswt.ok=\u786e\u5b9a window.updateswt.cancel=\u53d6\u6d88 swt.updater.downloader.downloading=\u6b63\u5728\u4e0b\u8f7d SWT \uff0c\u4ece swt.updater.urlsgetter.downloading=\u83b7\u53d6\u955c\u50cf\u5217\u8868\uff0c\u4ece swt.updater.urlsgetter.platform=SWT \u4e3a\u5e73\u53f0\uff1a window.updateswt.ignore=\u5ffd\u7565 ConfigView.section.style.useFancyTabs=\u4f7f\u7528\u4f18\u7f8e\u7684\u6807\u7b7e splash.initializeGM=\u521d\u59cb\u5316\u5168\u5c40 Torrent \u7ba1\u7406\u5668 splash.loadingTorrents=\u52a0\u8f7d\u591a\u4e2a Torrent MyTorrentsView.menu.thisColumn.sort=\u6392\u5e8f\uff08&S\uff09 Scrape.status.ok=\u67e5\u8be2\u6210\u529f. Scrape.status.error=\u67e5\u8be2\u5931\u8d25\uff1a Scrape.status.error.badURL=Announce URL\u4e0d\u9075\u5faa\u67e5\u8be2\u6807\u51c6\u3002 Scrape.status.error.nohash=\u8fd4\u56de\u4e22\u5931 Hash\u3002 Scrape.status.error.invalid=\u65e0\u6548\u7684\u8fd4\u56de Scrape.status.nextScrapeAt=\u4e0b\u4e00\u6b21\u67e5\u8be2\u5728 %1 Scrape.status.scraping=\u6b63\u5728\u67e5\u8be2.. Scrape.status.initializing=\u7b49\u5f85\u67e5\u8be2 Scrape.status.scraping.queued=\u5df2\u8bf7\u6c42\u67e5\u8be2\u2026 ConfigView.label.minSpeedForActiveSeeding=\u901f\u5ea6\u4f4e\u4e8e\u8be5\u503c\u65f6\uff0c\u4e0d\u8ba1\u5165\u603b\u4efb\u52a1\u6570 ConfigView.section.stats.exportpeers=\u5bfc\u51fa\u7528\u6237\u7ec6\u8282 MainWindow.menu.view.irc.moved=Irc \u76ee\u524d\u505a\u4e3a\u63d2\u4ef6\u63d0\u4f9b\uff0c \u8bf7\u67e5\u770b http://azureus.sourceforge.net/plugin_list.php\u3002 \u5f53\u5b89\u88c5\u540e\uff0c\u4f7f\u7528\u89c6\u56fe->\u63d2\u4ef6->IRC \u7684\u83dc\u5355\u53bb\u8bbf\u95ee\u5b83 MyTrackerView.webui.contextmenu.copyurl=\u62f7\u8d1d Torrent URL \u5230\u526a\u8d34\u677f ConfigView.section.file.torrent.ignorefiles=\u5f53\u5efa\u7acb Torrent \u65f6\u5ffd\u7565\u7684\u6587\u4ef6\n\u4f8b\u5982\uff1a.DS_Store\uff1bThumbs.db Torrent.create.progress.ignoringfile=\u5ffd\u7565\u6587\u4ef6 ConfigView.section.style.useUnitsRateBits=\u4ee5 bit/s \u4e3a\u5355\u4f4d ConfigView.section.interface.resetassoc=\u91cd\u7f6e\u6587\u4ef6\u5173\u8054\uff08.torrent\uff09 ConfigView.section.interface.resetassocbutton=\u91cd\u7f6e ConfigView.section.interface.checkassoc=\u542f\u52a8\u65f6\u68c0\u6d4b\u6587\u4ef6\u5173\u8054 dialog.associations.title=\u6587\u4ef6\u5173\u8054\u68c0\u67e5 Button.yes=\u53ef\u4ee5\uff08&Y\uff09 Button.no=\u5426\uff08&N\uff09 ConfigView.label.seeding.autoStart0Peers=\u81ea\u52a8\u542f\u52a8\u6240\u6709 0 \u7528\u6237\u7684\u5df2\u5b8c\u6210 Torrent ConfigView.label.seeding.autoStart0Peers.tooltip=\u6253\u5f00\u8fd9\u4e2a\u9009\u9879\uff0c\u5982\u679c\u4f60\u5e0c\u671b Tracker \u53ef\u4ee5\u4fdd\u6301\u5bf90\u7528\u6237\u7684 Torrent \u663e\u793a\u79cd\u5b50\u3002 dialog.associations.prompt=Vuze \u4e0d\u662f\u9ed8\u8ba4\u7684\u6253\u5f00 BitTorrent \u6587\u4ef6\u7684\u5e94\u7528\u7a0b\u5e8f\u3002\n\u4f60\u5e0c\u671b\u5173\u8054 .torrent \u5230 Vuze \u5417\uff1f dialog.associations.askagain=\u542f\u52a8\u65f6\u68c0\u67e5 ConfigView.section.plugins.update=\u63d2\u4ef6\u66f4\u65b0 Plugin.pluginupdate.enablecheck=\u542f\u7528\u63d2\u4ef6\u66f4\u65b0\u68c0\u67e5 plugins.basicview.status=\u72b6\u6001\uff1a plugins.basicview.activity=\u6d3b\u52a8\uff1a plugins.basicview.progress=\u8fdb\u5ea6\uff1a plugins.basicview.log=\u65e5\u5fd7\uff1a ConfigView.label.maxdownloadspeed=\u5168\u5c40\u6700\u5927\u4e0b\u8f7d\u901f\u5ea6\uff08KB/s\uff09\uff1a\uff3b0\uff1a\u65e0\u9650\u5236\uff3d splash.loadingTorrent=\u88c5\u8f7d Torrent splash.of=\u7684 UpdateWindow.title=Vuze \u66f4\u65b0\u5668 UpdateWindow.header=\u4ee5\u4e0b\u7ec4\u4ef6\u9700\u8981\u66f4\u65b0\uff1a UpdateWindow.columns.install=\u5b89\u88c5 UpdateWindow.columns.name=\u540d\u79f0 UpdateWindow.columns.version=\u7248\u672c UpdateWindow.columns.size=\u5927\u5c0f UpdateWindow.cancel=\u53d6\u6d88 UpdateWindow.quit=\u9000\u51fa UpdateWindow.close=\u5173\u95ed UpdateWindow.ok=\u66f4\u65b0 UpdateWindow.restart=\u7acb\u5373\u91cd\u542f UpdateWindow.status.downloading=\u6b63\u5728\u4e0b\u8f7d UpdateWindow.status.done=\u5b8c\u6210 UpdateWindow.status.failed=\u5931\u8d25 UpdateWindow.status.restartNeeded=\u5fc5\u987b\u91cd\u542f\uff01 ConfigView.pluginlist.broken=\u635f\u574f\u4e86 ConfigView.pluginlist.whereToPut=\u5c06\u4efb\u4f55\u7528\u6237\u6307\u5b9a\u7684\u63d2\u4ef6\u653e\u7f6e\u5728\u7528\u6237\u81ea\u5df1\u7684\u76ee\u5f55\u4e0b\uff1a ConfigView.pluginlist.whereToPutOr=\u5bf9\u4e8e\u5171\u4eab\u7684\u63d2\u4ef6\uff0c\u4f7f\u7528\uff1a MainWindow.statusText.checking=\u68c0\u67e5\u66f4\u65b0 TableColumn.header.OnlyCDing4=\u5355\u72ec\u505a\u79cd\u65f6\u95f4 TableColumn.header.OnlyCDing4.info=Torrent \u5355\u72ec\u505a\u79cd\u7684\u603b\u65f6\u95f4\u3002 \u4e0d\u5305\u62ec Torrent \u4e0b\u8f7d\u65f6\u9644\u5e26\u505a\u79cd\u7684\u65f6\u95f4\u3002 ConfigView.section.style.alternateTablePainting=\u4f7f\u7528\u4ea4\u66ff\u7684\u65b9\u5f0f\u7ed8\u5236\u56fe\u5f62\u8868\u884c\uff08\u53ef\u80fd\u9700\u8981\u91cd\u542f\uff09 UpdateWindow.status.restartMaybeNeeded=\u53ef\u80fd\u9700\u8981\u91cd\u542f ConfigView.pluginlist.shared=\u5171\u4eab PeersView.host=\u4e3b\u673a\u540d PeersView.host.info=\u8bbe\u7f6e\u53ef\u7528\u7684\u7528\u6237\u4e3b\u673a\u540d\u79f0\uff08\u53ef\u80fd\u4f1a\u5f71\u54cd\u6027\u80fd\uff09 MainWindow.menu.help.whatsnew=\u66f4\u65b0\u4fe1\u606f ConfigView.label.checkonstart=Vuze \u542f\u52a8\u65f6\u68c0\u67e5\u7a0b\u5e8f\u6700\u65b0\u7248\u672c ConfigView.label.periodiccheck=\u5468\u671f\u6027\u68c0\u67e5\u6700\u65b0\u7248\u672c ConfigView.label.opendialog=\u5f53\u6709\u66f4\u65b0\u65f6\u81ea\u52a8\u6253\u5f00\u66f4\u65b0\u52a9\u624b MainWindow.updateavail=\uff08\u6709\u53ef\u7528\u66f4\u65b0\uff09 MainWindow.status.unofficialversion=Vuze \u6d4b\u8bd5\u7248 MainWindow.status.latestversionunchecked=\u7248\u672c\u68c0\u67e5\u5df2\u88ab\u7981\u6b62 GeneralView.label.updatein.stopped=\u5df2\u505c\u6b62 StartStopRules.menu.viewDebug=\u67e5\u770b\u8c03\u8bd5\u4fe1\u606f ConfigView.section.style.doNotUseGB=\u4e0d\u4f7f\u7528 GB \u5355\u4f4d ConfigView.section.style.doNotUseGB.tooltip=\u5982\u679c\u9009\u4e2d\uff0c\u5373\u4f7f\u6587\u4ef6\u5927\u4e8e1024MB\uff0cVuze \u5c06\u4ecd\u7136\u4f7f\u7528 MB \u4f5c\u4e3a\u5355\u4f4d MainWindow.menu.help.plugins=\u83b7\u53d6\u63d2\u4ef6 ConfigView.section.plugins.TrackerWeb=Tracker \u7f51\u7ad9 ConfigView.section.tracker.enablecategories=\u6309\u7c7b\u522b\u4e3a Torrent \u5206\u7ec4 health.explain.share=\u8868\u793a Torrent \u662f\u4e3b\u673a\u6216\u8005\u53d1\u5e03\u8005 ConfigView.section.tracker.createcert=\u5efa\u7acb\u4e2a\u4eba\u7535\u5b50\u8bc1\u4e66 ConfigView.section.tracker.createbutton=\u521b\u5efa security.certcreate.title=\u521b\u5efa\u4e2a\u4eba\u7535\u5b50\u8bc1\u4e66 security.certcreate.intro=\u6b64\u5bf9\u8bdd\u6846\u8ba9\u4f60\u521b\u5efa\u4e00\u4efd\u4e2a\u4eba\u7535\u5b50\u8bc1\u4e66 security.certcreate.alias=\u522b\u540d security.certcreate.strength=\u4eba\u6570 security.certcreate.firstlastname=\u540d\u5b57\u548c\u59d3\u6c0f security.certcreate.orgunit=\u7ec4\u7ec7\u7684\u5355\u4f4d security.certcreate.org=\u56e2\u4f53\u6216\u7ec4\u7ec7 security.certcreate.city=\u57ce\u5e02\u6216\u5730\u70b9 security.certcreate.state=\u5dde\u6216\u7701 security.certcreate.country=\u4e24\u4e2a\u5b57\u6bcd\u7684\u56fd\u5bb6\u4ee3\u7801 security.certcreate.ok=\u521b\u5efa security.certcreate.cancel=\u53d6\u6d88 security.certcreate.createok=\u521b\u5efa\u8bc1\u4e66\u6210\u529f security.certcreate.createfail=\u521b\u5efa\u8bc1\u4e66\u5931\u8d25 ConfigView.section.plugins.webui=Swing \u7f51\u7edc\u754c\u9762 ConfigView.section.plugins.xml_http_if=XML/HTTP \u754c\u9762 webui.passwordenable=\u542f\u7528\u5bc6\u7801 webui.user=\u7528\u6237\u540d webui.password=\u5bc6\u7801 webui.port=\u7aef\u53e3\uff08*\uff09 webui.protocol=\u534f\u8bae\uff08*\uff09 webui.homepage=\u4e3b\u9875\uff08*\uff09 webui.rootdir=\u6839\u76ee\u5f55\uff08*\uff09 webui.rootres=\u6839\u8d44\u6e90\uff08*\uff09 webui.mode=\u6a21\u5f0f\uff08*\uff09 webui.mode.info=\u6a21\u5f0f\u53ef\u4ee5\u662f\n\t"full"\t= \u6240\u6709\u64cd\u4f5c\u53ef\u7528\uff08\u9ed8\u8ba4\u503c\uff09\n\t"view"\t= \u4ec5\u80fd\u770b\uff08\u4f46\u53ef\u4ee5\u591a\u6b21\u66f4\u65b0\u5237\u65b0\uff09 webui.access=\u8bbf\u95ee\uff08*\uff09 webui.access.info=\u8bbf\u95ee\u53ef\u4ee5\u662f\n\t"local"\t= \u610f\u601d\u662f\u4ec5\u6709\u672c\u5730\u7684\u673a\u5668\u53ef\u4ee5\u8fde\u63a5\n\t"all"\t= \u4e0d\u53d7\u9650\u5236\u7684\u8bbf\u95ee\uff08\u9ed8\u8ba4\u503c\uff09\n\tIP\t= \u4f8b\u5982\uff1a192.168.0.2\t\t\t\u4ec5\u6709\u6307\u5b9a\u7684 IP \u53ef\u4ee5\u8fde\u63a5\n\tIP1-IP2\t= \u4f8b\u5982\uff1a192.168.0.1-192.168.0.255\t\u5305\u62ec\u8303\u56f4\u5185\u7684\u6240\u6709 IP GeneralView.label.maxdownloadspeed=\u6700\u5927\u4e0b\u8f7d\u901f\u5ea6 Security.keystore.corrupt=Keystore "%1" \u52a0\u8f7d\u9519\u8bef\uff0c\u8bf7\u5220\u9664\u5b83\u5e76\u91cd\u65b0\u521b\u5efa/\u91cd\u65b0\u8f93\u5165\u8bc1\u4e66 Security.keystore.empty=Keystore \u4e3a\u7a7a\u3002\u8bf7\u521b\u5efa\u81ea\u6211\u7b7e\u7f72\u8bc1\u4e66\uff08\u53c2\u89c1 \u5de5\u5177->\u9009\u9879->\u5b89\u5168\uff09\u6216\u8f93\u5165\u4e00\u4e2a\u5b58\u5728\u7684\u8bc1\u4e66\u5230 "%1" webui.restart.info=\u5e26\uff08*\uff09\u7684\u9879\u76ee\u88ab\u6539\u53d8\u540e\u9700\u8981\u91cd\u542f\u624d\u80fd\u8d77\u4f5c\u7528 GeneralView.label.maxdownloadspeed.tooltip=\u6700\u5927\u4e0b\u8f7d\u901f\u5ea6\uff3b0\uff1a\u65e0\u9650\u5236\uff3d upnp.enable=\u542f\u7528 UPnP upnp.info=\u901a\u7528\u5373\u63d2\u5373\u7528\uff08UPnP\uff09 \u5141\u8bb8\u5728\u5df2\u542f\u7528 UPnP \u7684\u8def\u7531\u5668\u4e0a\u81ea\u52a8\u7aef\u53e3\u6620\u5c04\u3002 upnp.mapping.dataport=\u4f20\u5165\u7528\u6237\u6570\u636e\u7aef\u53e3 upnp.mapping.tcptrackerport=TCP Tracker \u7aef\u53e3 upnp.mapping.udptrackerport=UDP Tracker \u7aef\u53e3 upnp.alert.differenthost=UPnP\uff1a\u7aef\u53e3 "%1" \u5df2\u7ecf\u88ab "%2" \u5360\u7528 - \u8bf7\u9009\u62e9\u53e6\u4e00\u4e2a\u7aef\u53e3 upnp.alert.mappingok=UPnP\uff1a\u7aef\u53e3 "%1" \u6620\u5c04\u5df2\u5efa\u7acb upnp.alert.mappingfailed=UPnP\uff1a\u6620\u5c04 "%1" \u5931\u8d25 upnp.alertsuccess=\u62a5\u544a\u6210\u529f\u6620\u5c04 upnp.alert.lostdevice=UPnP\uff1a\u5728 UPnP \u8bbe\u5907 "%2" \u4e0a\u548c "%1" \u5931\u53bb\u8fde\u63a5 upnp.grabports=\u5373\u4f7f\u7aef\u53e3\u88ab\u5176\u4ed6\u673a\u5668\u5360\u7528\u4f9d\u7136\u4f7f\u7528\u6620\u5c04 upnp.refresh.label=\u5237\u65b0\u6620\u5c04 upnp.refresh.button=\u5237\u65b0 upnp.alert.mappinggrabbed=UPnP\uff1a\u7aef\u53e3 "%1"\u6620\u5c04\u5df2\u5efa\u7acb - \u88ab "%2"\u5360\u6709 upnp.mapping.tcpssltrackerport=TCP SSL Tracker \u7aef\u53e3 upnp.alertothermappings=\u7aef\u53e3\u88ab\u5176\u4ed6\u8ba1\u7b97\u673a\u5360\u7528 upnp.alertdeviceproblems=\u62a5\u544a UPnP \u8bbe\u5907\u95ee\u9898 upnp.trace_to_log=\u8f93\u51fa\u5b8c\u6574\u7684 Debug \u4fe1\u606f\u5230\u65e5\u5fd7 upnp.wiki_link=Vuze \u7ef4\u57fa\u4e0a\u5173\u4e8e UPnP \u7684\u5185\u5bb9 upnp.refresh_mappings_on_bad_nat=\u5f53 NAT \u72b6\u6001\u4e3a \u201c\u9632\u706b\u5899\u540e\u201d\u65f6\u81ea\u52a8\u5237\u65b0\u6620\u5c04\u3002 ConfigView.pluginlist.coreplugins=\u5df2\u52a0\u8f7d\u4ee5\u4e0b\u5185\u7f6e\u63d2\u4ef6\uff1a Peers.column.DLedFromOthers=\u6765\u81ea\u4ed6\u4eba Peers.column.DLedFromOthers.info=\u8fde\u63a5\u5230\u81ea\u5df1\u7684\u4ed6\u4eba\u5df2\u4e0b\u8f7d\u603b\u6570\u636e Peers.column.UpDownRatio=\u4e0a\u4f20\uff1a\u4e0b\u8f7d Peers.column.UpDownRatio.info=\u7528\u6237\u7684"\u4e0a\u4f20\uff1a\u4e0b\u8f7d"\u6bd4\u7387 Peers.column.UpRatio=\u4e0a\u4f20\u6bd4\u7387 Peers.column.UpRatio.info=\u7528\u6237\u7684"\u6765\u81ea\u4f60\u7684\u4e0a\u4f20\uff1a\u6765\u81ea\u4ed6\u4eba\u7684\u4e0a\u4f20"\u6bd4\u7387 upnp.releasemappings=\u5728\u5173\u95ed\u65f6\u53d6\u6d88\u6620\u5c04 webui.upnpenable=\u4e3a\u6b64\u7aef\u53e3\u542f\u7528\u81ea\u52a8\u7aef\u53e3\u6620\u5c04\uff08*\uff09 ConfigView.section.file.friendly.hashchecking=\u8282\u7701\u8d44\u6e90\u6a21\u5f0f Hash \u68c0\u67e5 ConfigView.section.file.friendly.hashchecking.tooltip=\u6709\u70b9\u6162\uff0c\u4f46\u51cf\u5c11 CPU/\u7cfb\u7edf\u538b\u529b\uff0c\u5206\u7247 Hash \u68c0\u67e5\u6a21\u5f0f ConfigView.section.tracker.seedretention=\u6bcf\u4e2a Torrent \u4fdd\u7559\u6700\u591a\u79cd\u5b50\u6570\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.section.tracker.seedretention.info=\u6ce8\u610f\uff1a\u672a\u4fdd\u7559\u7684\u79cd\u5b50\u7684\u4e0a\u4f20\u7edf\u8ba1\u6570\u636e\u5c06\u4e22\u5931 ConfigView.section.tracker.port=\u5728 HTTP \u7aef\u53e3\u542f\u52a8 Tracker ConfigView.section.tracker.sslport=\u542f\u7528\u5728 HTTPS \u7aef\u53e3\u7684 Tracker ConfigView.section.tracker.publicenable.info=\u5373\u4f7f\u4f60\u4e0d\u5750\u5e84/\u53d1\u5e03\n\u4ed6\u4eba\u4e5f\u53ef\u4ee5\u6210\u529f\u53d1\u5e03\u4e00\u4e2a\u542b\u6709\u4f60\u7684 Tracker \u7684 Torrent Button.clear=\u6e05\u9664 MainWindow.IPs.tooltip=IP \u8fc7\u6ee4\u4e2d\u7684\u6761\u76ee\u6570 - \u88ab\u963b\u6b62\u7684 IP \u6570\u76ee ConfigView.section.ipfilter.list.banned=\u5df2\u88ab\u7981\u6b62 ConfigView.section.ipfilter.list.baddata=\u66fe\u7ecf\u53d1\u9001\u9519\u8bef\u6570\u636e\uff1a\u51fa\u73b0\u6b21\u6570 = Button.reset=\u91cd\u7f6e ConfigView.section.ipfilter.bannedinfo=\u53d1\u9001\u9519\u8bef\u6570\u636e\u7684 IP - \u8d85\u8fc7\u9650\u5236\u5219\u7981\u6b62 ConfigView.section.ipfilter.blockedinfo=\u7531\u4e8e IP \u8fc7\u6ee4\u5668\u800c\u963b\u6b62\u7684 IP download.removerules.name=\u5220\u9664\u89c4\u5219 download.removerules.unauthorised.info=\u672a\u7ecf\u6388\u6743\u7684 Torrent \u662f\u6307 Tracker \u5728\u56de\u590d "failure response" \u65f6\uff0c\n\u663e\u793a "not authoris(z)ed" \u6216 "unauthoris(z)ed" \u7684 Torrent download.removerules.unauthorised=\u81ea\u52a8\u79fb\u9664\u672a\u7ecf\u6388\u6743\u7684 Torrent download.removerules.unauthorised.seedingonly=\t\u4ec5\u5728\u505a\u79cd\u65f6 download.removerules.removed.ok="%1"\u6210\u529f\u540e\u81ea\u52a8\u5220\u9664 Torrent\u3002\u7531 Torrent \u5220\u9664\u89c4\u5219\u51b3\u5b9a\u3002 download.removerules.updatetorrents=Vuze \u66f4\u65b0\u5b8c\u6bd5\u540e\uff0c\u6839\u636e\u7fa4\u4f53\u4fe1\u606f\u5220\u9664 Vuze \u66f4\u65b0\u4efb\u52a1 ConfigView.label.defaultstarttorrentsstopped=\u6dfb\u52a0\u65b0 Torrent \u65f6\u4e3a\u505c\u6b62\u72b6\u6001\uff08\u4e0d\u81ea\u52a8\u5f00\u59cb\u4e0b\u8f7d\uff09 ConfigView.section.server.enableudp=\u542f\u7528 UDP Tracker upnp.mapping.dataportudp=UDP Tracker \u7528\u6237\u7aef\u53e3 ConfigView.section.file.decoder.showlax=\u5217\u51fa\u4e0d\u592a\u53ef\u80fd\u7684\u7f16\u7801 ConfigView.section.file.decoder.showall=\u5217\u51fa\u5168\u90e8\u53ef\u80fd\u7684\u7f16\u7801 MainWindow.status.updowndetails.tooltip=\u4e0a\u4f20/\u4e0b\u8f7d\u901f\u5ea6\u7ec6\u8282 - \u70b9\u51fb\u53f3\u952e\u66f4\u6539 TrackerClient.announce.warningmessage=Tracker \u56e0\u4e3a"%1"\u56de\u62a5\u8b66\u544a"%2" ConfigView.section.tracker.natcheckenable=\u68c0\u67e5"\u4f20\u5165\u6570\u636e\u7aef\u53e3"\u662f\u5426\u53ef\u8054\u901a\u5e76\u628a\u9519\u8bef\u62a5\u544a\u7ed9\u7528\u6237 ConfigView.section.tracker.publishenabledetails=\u53d1\u5e03 Torrent \u6587\u4ef6\u548c\u7528\u6237\u8be6\u7ec6\u4fe1\u606f ConfigView.section.tracker.publishenablepeerdetails=\u53d1\u5e03\u7528\u6237\u8be6\u7ec6\u8d44\u6599 MyTrackerView.badnat=NAT\u9519\u8bef MyTrackerView.badnat.info=\u5982\u679c\u542f\u7528\uff0c\u663e\u793a NAT \u68c0\u67e5\u5931\u8d25\u7684\u79cd\u5b50/\u7528\u6237 ConfigView.section.tracker.natchecktimeout=\u68c0\u67e5\u8d85\u65f6\uff08\u79d2\uff09 ConfigView.section.file.perf.cache.enable=\u542f\u7528\u78c1\u76d8\u7f13\u5b58 ConfigView.section.file.perf.cache.size=\u7f13\u5b58\u7684\u5927\u5c0f\uff0c\u4ee5%1\u8ba1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u4f20\u8f93\uff08&R\uff09 MainWindow.menu.transfers.startalltransfers=\u5168\u90e8\u5f00\u59cb\uff08&A\uff09 MainWindow.menu.transfers.stopalltransfers=\u5168\u90e8\u505c\u6b62\uff08&O\uff09 MainWindow.menu.transfers.pausetransfers=\u6682\u505c\uff08&P\uff09 MainWindow.menu.transfers.resumetransfers=\u7ee7\u7eed\uff08&R\uff09 ConfigView.label.experimental.osx.kernel.panic.fix=\u5728\u53cc CPU \u7684 OSX \u7cfb\u7edf\u4e0a\u5b9e\u9a8c\u4fee\u590d\u5185\u6838\u5d29\u6e83\uff08kernel panics\uff09\uff3b\u9700\u8981\u91cd\u542f\uff3d SystemTray.menu.pausetransfers=\u6682\u505c\u4f20\u8f93 SystemTray.menu.resumetransfers=\u7ee7\u7eed\u4f20\u8f93 ConfigView.section.file.truncate.too.large=\u79fb\u9664\u6587\u4ef6\u672b\u5c3e\u591a\u4f59\u5b57\u8282\uff08\u5982\u5bfc\u5165\u522b\u7684\u5ba2\u6237\u7aef\u4e0b\u8f7d\u672a\u5b8c\u6210\u7684\u4efb\u52a1\uff09 ConfigView.section.file.perf.cache.trace=\u4ee5\u8bca\u65ad\u4e3a\u76ee\u7684\u7684\u8ffd\u8e2a\u9ad8\u901f\u7f13\u5b58\u64cd\u4f5c ConfigView.section.interface.enabletray=\u663e\u793a\u7cfb\u7edf\u6258\u76d8\uff3b\u9700\u8981\u91cd\u542f\uff3d PeerManager.status.error=\u9519\u8bef Stats.title.full=\u7edf\u8ba1 TransferStatsView.title.full=\u4f20\u8f93 CacheView.title.full=\u7f13\u5b58 CacheView.general.size=\u603b\u5bb9\u91cf CacheView.general.inUse=\u5df2\u4f7f\u7528 CacheView.general.title=\u7f13\u5b58\u4fe1\u606f CacheView.reads.title=I/O \u8bfb\u53d6 CacheView.reads.fromFile=\u6587\u4ef6 CacheView.reads.fromCache=\u7f13\u5b58 CacheView.reads.hits=\u547d\u4e2d\u7387 CacheView.writes.title=I/O \u5199\u5165 CacheView.writes.toCache=\u7f13\u5b58 CacheView.writes.toFile=\u6587\u4ef6 CacheView.writes.hits=\u8282\u7701\u7387 CacheView.speeds.title=\u6570\u636e\u4f20\u8f93\u901f\u7387 CacheView.speeds.reads=\u8bfb\u53d6 CacheView.speeds.writes=\u5199\u5165 CacheView.speeds.fromCache=\u7f13\u5b58 CacheView.speeds.fromFile=\u6587\u4ef6 CacheView.reads.#=\u6b21\u6570 CacheView.reads.amount=\u603b\u8ba1 CacheView.reads.avgsize=\u5e73\u5747\u5927\u5c0f openUrl.referrer=\u5f15\u7528\u9875\u9762\u5730\u5740\uff1a openUrl.referrer.info=\u4ec5\u6709\u7f51\u9875\u8981\u6c42\u65f6\u624d\u9700\u8981 ConfigView.label.maxuploadspeedseeding=\u4ec5\u505a\u79cd\u65f6\uff0c\u66ff\u4ee3\u503c ConfigView.label.transfer.ignorepeerports=\u5ffd\u7565\u4f7f\u7528\u8fd9\u4e9b\u7aef\u53e3\u7684\u4e0b\u8f7d\u8005\uff08\u4ee5\u201c\uff1b\u201c \u9694\u5f00\uff0c\u4f8b\u5982 0\uff1b25\uff09 ConfigView.section.proxy.enable_socks.peer=\u542f\u7528\u4ee3\u7406\u7528\u6237\u901a\u8baf\uff08\u4ec5\u7528\u4e8e\u5bf9\u5916\u8fde\u63a5\uff09\uff3b\u9700\u8981\u91cd\u542f\uff3d ConfigView.section.proxy.peer.informtracker=\u628a\u9650\u5236\u901a\u77e5 Tracker ConfigView.section.proxy.socks.version=SOCKS \u7248\u672c PiecesView.legend.written=\u5df2\u5199\u5165 PiecesView.legend.requested=\u5df2\u8bf7\u6c42 PiecesView.legend.downloaded=\u5df2\u4e0b\u8f7d\uff0c\u7b49\u5f85\u5199\u5165 PiecesView.legend.incache=\u7f13\u5b58\u4e2d\u7684\u6570\u636e PiecesView.typeItem.0=\u4f4e\u901f PiecesView.typeItem.1=\u9ad8\u901f PiecesView.type=\u7c7b\u578b Security.jar.tools_not_found=JAR \u7b7e\u7f72\u5931\u8d25 - \u5728%1\u4e2d\u6ca1\u627e\u5230 "tools.jar"\u3002\u8be6\u60c5\u8bf7\u53c2\u89c1 \u5de5\u5177->\u9009\u9879->\u5b89\u5168\u3002 Security.jar.signfail=JAR \u7b7e\u7f72\u5931\u8d25 - %1 ConfigView.section.security.toolsinfo=\u6709\u7b7e\u540d\u7684 JAR \u6587\u4ef6\u7528\u4e8e\u652f\u6301\u67d0\u4e9b\u63d2\u4ef6\uff0c\u4f8b\u5982\uff1a Swing \u7f51\u7edc\u4ecb\u9762\uff08\u5f53\u5b89\u88c5\u914d\u7f6e\u540e\uff09\u3002\n\u4e3a\u4e86\u7b7e\u7f72 JAR \u6587\u4ef6\uff0c\u5fc5\u987b\u8bbf\u95ee "tools.jar" \u6587\u4ef6\u3002\u6b64\u6587\u4ef6\u968f Sun JDK\uff08\u4e0d\u662f JRE\uff09 \u4e00\u8d77\u5b89\u88c5\u3002 \n\u5982\u679c\u4f60\u4ec5\u5b89\u88c5\u4e86 JRE\uff0c\u8bf7\u518d\u5b89\u88c5 JDK\u3002\nVuze \u901a\u5e38\u80fd\u5e2e\u4f60\u627e\u5230\u8fd9\u4e2a\u6587\u4ef6\u3002\u4f46\u5982\u679c\u6ca1\u627e\u5230\uff0c\u4f60\u53ef\u4ee5\u5728\u6b64\u8bbe\u7f6e\u5b83\u6240\u5728\u7684\u76ee\u5f55\u3002 ConfigView.section.security.toolsdir=\u5305\u542b "tools.jar" \u7684\u76ee\u5f55 ConfigView.section.security.choosetoolssavedir=\u9009\u62e9\u5305\u542b "tools.jar" \u7684\u6587\u4ef6\u5939 ConfigView.section.proxy.peer.same=\u4e3a Tracker \u548c\u7528\u6237\u8fde\u63a5\u4f7f\u7528\u76f8\u540c\u7684\u4ee3\u7406\u670d\u52a1\u5668 ConfigView.section.connection.network.max.simultaneous.connect.attempts=\u6700\u5927\u540c\u65f6\u5bf9\u5916\u8fde\u63a5\u5c1d\u8bd5\uff3b0\uff1a\u7981\u6b62\u5bf9\u5916\u8fde\u63a5\uff3d ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=\u6700\u5927\u7684\u65b0\u589e\u5411\u5916\u8fde\u63a5\u6570\uff0c\u6307\u5b9a Vuze \u5728\u4efb\u4f55\u65f6\u95f4\u7684\u5c1d\u8bd5\u6b21\u6570\u3002\n\u6ce8\u610f\uff1a WindowsXP Service Pack 2\uff08SP2\uff09 \u5f3a\u5236\u7cfb\u7edf\u540c\u65f6\u8fde\u63a5\u5c1d\u8bd5\u4e3a10\u6b21\u3002\n\u9ed8\u8ba4\u503c\u4e3a8\u6b21\u30020\u4e3a\u5b8c\u5168\u7981\u6b62\u5411\u5916\u8fde\u63a5\u3002 ConfigView.section.file.perf.cache.size.explain=\u7f13\u5b58\u7528\u4e8e\u51cf\u4f4e\u8bfb/\u5199\u78c1\u76d8\u7684\u6b21\u6570\u3002\u9664\u975e\u60a8\u6b63\u5728\u4f7f\u7528 java \u8bbe\u7f6e "-XX\uff1aMaxDirectMemorySize" \u660e\u786e\u5730\u8bbe\u7f6e\u7f13\u5b58\u548c\u7f51\u7edc IO \u4f7f\u7528\u7684\u5185\u5b58\uff0c\u60a8\u5e94\u8be5\u4fdd\u6301\u6b64\u6570\u503c\u81f3\u5c11%1\u4f4e\u4e8e\u60a8\u7684\u6700\u5927 VM \u5927\u5c0f\u3002\n\u5f53\u524d\u6700\u5927 VM \u5927\u5c0f\u662f%2\u3002\n\u5982\u679c\u9700\u8981\u5982\u4f55\u6539\u53d8\u7684\u6307\u5bfc\uff0c\u53c2\u89c1%3\u7684 MemoryUsage\u3002\n\u9519\u8bef\u4f7f\u7528\u8bbe\u7f6e\u5c06\u5bfc\u81f4"\u5185\u5b58\u4e0d\u8db3"\u9519\u8bef\u3002\u8d85\u8fc732MB\u7684\u7f13\u5b58\u53ef\u80fd\u8fc7\u91cf\u3002 MyTorrentsView.menu.setSpeed.unlimit=\u4e0d\u9650 MyTorrentsView.menu.setSpeed.unlimited=\u65e0\u9650\u5236 MyTorrentsView.menu.setSpeed.disable=\u7981\u6b62\u4e0a\u4f20 MyTorrentsView.menu.setSpeed.disabled=\u7981\u6b62 MyTorrentsView.menu.setSpeed.in=\u5206 MyTorrentsView.menu.setSpeed.slots=\u4efd\uff0c\u6bcf\u4efd GeneralView.label.maxuploadspeed=\u6700\u5927\u4e0a\u4f20\u901f\u5ea6 GeneralView.label.maxuploadspeed.tooltip=\u6700\u5927\u4e0a\u4f20\u901f\u5ea6\uff3b0\uff1a\u65e0\u9650\u5236\uff3d MyTorrents.items.UpSpeedLimit.disabled=\u65e0\u4e0a\u4f20 MyTorrents.items.UpSpeedLimit.unlimited=\u65e0\u9650\u5236 TableColumn.header.maxupspeed=\u6700\u5927\u4e0a\u4f20\u901f\u5ea6 TableColumn.header.maxupspeed.info=\u6bcf\u4e2a Torrent \u7684\u6700\u5927\u4e0a\u4f20\u901f\u5ea6 ConfigView.section.file.perf.cache.enable.write=\u9ad8\u901f\u7f13\u5b58\u4e0b\u8f7d\u6570\u636e\u4ee5\u964d\u4f4e\u78c1\u76d8\u5199\u6b21\u6570\uff0c\u4ee5\u53ca\u51cf\u5c11\u5206\u7247\u68c0\u67e5\u7684\u78c1\u76d8\u8bfb\u9700\u6c42 ConfigView.section.file.perf.cache.enable.read=\u6267\u884c\u9884\u8bfb\u53d6\u4ee5\u964d\u4f4e\u4e0a\u8f7d\u65f6\u78c1\u76d8\u8bfb\u53d6\u6b21\u6570 ConfigView.section.tracker.separatepeerids=\u4e3a Tracker \u548c\u6570\u636e\u901a\u8baf\u4f7f\u7528\u4e0d\u540c\u7684\u7528\u6237\u8eab\u4efd ConfigView.section.tracker.separatepeerids.info=\u4e0a\u4f20/\u505a\u79cd\u65f6\uff0c\u4e3a\u975e\u533f\u540d\u7684 Tracker \u8fde\u63a5\u63d0\u9ad8\u533f\u540d\u5ea6 ConfigView.section.interface.wavlocation=.wav \u6587\u4ef6\u7684\u4f4d\u7f6e ConfigView.section.interface.wavlocation.info=\u9009\u62e9 .wav \u6587\u4ef6\u6216\u8005\u7559\u7a7a\u4fdd\u6301\u9ed8\u8ba4 ConfigView.section.tracker.server=\u670d\u52a1\u5668 ConfigView.section.tracker.client=\u5ba2\u6237\u7aef ConfigView.section.tracker.client.connecttimeout=\u8fde\u63a5\u8d85\u65f6\uff08\u79d2\uff09 ConfigView.section.tracker.client.readtimeout=\u8bfb\u53d6\u8d85\u65f6\uff08\u79d2\uff09 MainWindow.menu.tools=\u5de5\u5177\uff08&T\uff09 FilesView.path=\u76ee\u5f55 FilesView.fullpath=\u663e\u793a\u5b8c\u6574\u76ee\u5f55 FilesView.remaining=\u5269\u4f59\u533a\u5757 TableColumn.header.trackername=Tracker \u540d\u79f0 TableColumn.header.trackername.info=\u53d1\u5e03\u7684 URL \u4e0a Tracker \u7684\u540d\u5b57 ConfigView.group.override=\u8986\u76d6\u9009\u9879 ConfigView.section.file.perf.cache.notsmallerthan=\u4e0d\u8981\u7f13\u5b58\u6bd4\u6b64\u5c0f\u7684\u6587\u4ef6\uff08\u4ee5%1\u8ba1\uff09 PeersView.menu.blockupload=\u963b\u6b62\u4e0a\u4f20 PeersView.menu.kickandban=\u62d2\u7edd\u8fde\u63a5 PeersView.menu.kickandban.reason=\u624b\u52a8\u7981\u6b62\u7528\u6237 PeersView.state=\u72b6\u6001 PeersView.state.info=\u7528\u6237\u8fde\u63a5\u72b6\u6001 PeersView.state.pending=\u7b49\u5f85\u4e2d PeersView.state.connecting=\u8fde\u63a5\u4e2d PeersView.state.handshake=\u6b63\u7b49\u5f85\u540c\u6b65 PeersView.state.established=\u8fde\u63a5\u5df2\u5efa\u7acb ConfigView.section.tracker.processinglimits=\u5904\u7406\u9650\u5236 ConfigView.section.tracker.maxgettime=GET \u5904\u7406\u6700\u957f\u65f6\u95f4\uff08\u79d2\uff09\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.section.tracker.maxgettime.info=\u7528\u4e8e Announces \u548c \u67e5\u8be2 ConfigView.section.tracker.maxposttimemultiplier=POST \u5904\u7406\u7684 GET \u65f6\u95f4\u500d\u6570\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.section.tracker.maxposttimemultiplier.info=\u7528\u4e8e\u8868\u5355\u7684\u9012\u4ea4\u548c\u4e0a\u4f20 ConfigView.section.tracker.maxthreads=\u6700\u5927\u5e76\u53d1\u8bf7\u6c42\u6570 DownloadManager.error.operationcancancelled=\u64cd\u4f5c\u53d6\u6d88 Torrent.create.progress.cancelled=\u5df2\u53d6\u6d88\u64cd\u4f5c sharing.progress.cancel=\u53d6\u6d88 wizard.maketorrents.autoopen=\u5728\u4f20\u8f93\u7ed3\u675f\u4e4b\u540e\u505a\u79cd ConfigView.section.sharing.rescanenable=\u542f\u7528\u91cd\u65b0\u626b\u63cf\u5468\u671f\uff0c\u4ee5\u9632\u6b62\u5171\u4eab\u6587\u4ef6\u6539\u53d8 ConfigView.section.sharing.rescanperiod=\u91cd\u65b0\u68c0\u6d4b\u5468\u671f\uff08\u79d2\uff09 ConfigView.section.connection.advanced=\u9ad8\u7ea7\u7f51\u7edc\u8bbe\u7f6e ConfigView.section.connection.advanced.mtu=\u7ebf\u8def\u6700\u5927\u4f20\u8f93\u5355\u5143\uff08MTU\uff09 ConfigView.section.connection.advanced.mtu.tooltip=\u5355\u4e00\u5e27\u901a\u8fc7\u7f51\u7edc\u53ef\u4ee5\u4f20\u8f93\u7684\u6700\u5927\u6570\u636e\u5305\u5927\u5c0f\u3002\nVuze \u4f7f\u7528 MTU-40\uff08MSS\uff09 \u4f18\u5316\u4e0a\u4f20\u6570\u636e\u5305\u8d1f\u8f7d\u3002\n\u63a8\u8350\u503c\uff1a\n576 - \u62e8\u53f7\u8fde\u63a5\n1492 - PPPoE \u5bbd\u5e26\u8fde\u63a5\n1500 - \u4ee5\u592a\u7f51\u3001 DSL \u548c Cable \u5bbd\u5e26\u8fde\u63a5 ConfigView.section.connection.advanced.SO_RCVBUF=Socket SO_RCVBUF \u5927\u5c0f\uff3b0\uff1a\u4f7f\u7528\u64cd\u4f5c\u7cfb\u7edf\u9ed8\u8ba4\uff3d ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=\u8bbe\u7f6e\u6807\u51c6 socket SO_RCVBUF \u503c\uff08\u4ee5\u5b57\u8282\u8ba1\uff09\uff0c\u5982\uff1a TCP \u63a5\u6536\u7a97\u7684\u5927\u5c0f\u548c\u6bd4\u4f8b\u5c3a\u3002\n\u4e0d\u8bbe\u7f6e\u7684\u60c5\u51b5\u4e0b Vuze \u4f7f\u7528\u9ed8\u8ba4\u503c\uff0c\u8868\u793a\u4f18\u5148\u4f7f\u7528\u7cfb\u7edf\u9ed8\u8ba4\u503c\u3002\n\u6ce8\u610f\uff1a Linux \u628a\u8d4b\u4e88\u7684\u503c\u53cc\u500d\u8ba1\u7b97\u3002 ConfigView.section.connection.advanced.SO_SNDBUF=Socket SO_SNDBUF \u5927\u5c0f\uff3b0\uff1a\u4f7f\u7528\u64cd\u4f5c\u7cfb\u7edf\u9ed8\u8ba4\uff3d ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=\u8bbe\u7f6e\u6807\u51c6 socket SO_SNDBUF \u503c\uff08\u4ee5\u5b57\u8282\u8ba1\uff09\uff0c\u5982\uff1a TCP \u63a5\u6536\u7a97\u7684\u5927\u5c0f\u548c\u6bd4\u4f8b\u5c3a\u3002\n\u4e0d\u8bbe\u7f6e\u7684\u60c5\u51b5\u4e0b Vuze \u4f7f\u7528\u9ed8\u8ba4\u503c\uff0c\u8868\u793a\u4f18\u5148\u4f7f\u7528\u7cfb\u7edf\u9ed8\u8ba4\u503c\u3002\n\u6ce8\u610f\uff1a Linux \u628a\u8d4b\u4e88\u7684\u503c\u53cc\u500d\u8ba1\u7b97\u3002 ConfigView.section.interface.confirm_torrent_removal=\u5f53\u5220\u9664 Torrent \u65f6\u663e\u793a\u786e\u8ba4\u5bf9\u8bdd\u6846 ConfigView.section.interface.confirm_torrent_removal.tooltip=\u4ece "\u6211\u7684 Torrents" \u7a97\u53e3\u5220\u9664 torrent \u65f6\u8981\u6c42\u786e\u8ba4\u3002 MyTorrentsView.confirm_torrent_removal=\u4f60\u786e\u5b9a\u60f3\u79fb\u9664\u5417\uff1f\n TableColumn.header.seed_to_peer_ratio=\u79cd\u5b50\u4e0e\u7528\u6237\u6bd4\u7387 TableColumn.header.seed_to_peer_ratio.info=\u7fa4\u4f53\u79cd\u5b50\u4e0e\u7528\u6237\u7684\u6bd4\u7387 PeersView.connected_time=\u8fde\u63a5\u65f6\u95f4 PeersView.connected_time.info=\u4e0e\u7528\u6237\u8fde\u63a5\u7684\u603b\u65f6\u95f4 ConfigView.section.interface.display.add_torrents_silently=\u5b89\u9759\u5730\u6dfb\u52a0 Torrent ConfigView.section.interface.display.add_torrents_silently.tooltip=\u6dfb\u52a0 Torrent \u4e0b\u8f7d\u4e0d\u663e\u793a Vuze \u4e3b\u7a97\u53e3\u3002 TableColumn.header.maxdownspeed=\u6700\u5927\u4e0b\u8f7d\u901f\u5ea6 TableColumn.header.maxdownspeed.info=\u6bcf\u4e2a Torrent \u7684\u6700\u5927\u4e0b\u8f7d\u901f\u5ea6 PeersGraphicView.title=\u7fa4\u4f53 ConfigView.section.tracker.passwordwebhttpsonly=\u4ec5\u5141\u8bb8\u901a\u8fc7 HTTPS \u7684\u8fde\u63a5 TableColumn.header.torrentpath=Torrent \u5730\u5740 TableColumn.header.torrentpath.info=Torrent \u5728\u78c1\u76d8\u4e0a\u7684\u4f4d\u7f6e ConfigView.section.sharing.torrentcomment=\u5bf9\u5df2\u751f\u6210 Torrent \u7684\u6ce8\u91ca ConfigView.label.copyanddeleteratherthanmove=\u590d\u5236\u540e\u5220\u9664\u539f\u59cb\u6570\u636e\uff0c\u800c\u4e0d\u662f\u5728\u64cd\u4f5c\u4e2d\u79fb\u52a8\u5b83 - \u80fd\u5e2e\u52a9\u67d0\u4e9b\u6587\u4ef6\u7cfb\u7edf\u907f\u514d\u6570\u636e\u635f\u5931 ConfigView.label.openstatsonstart=\u542f\u52a8\u65f6\u663e\u793a\u7edf\u8ba1\u4fe1\u606f swt.install.window.title=Vuze \u63d2\u4ef6\u5b89\u88c5\u5de5\u5177 swt.install.window.ok=\u5b89\u88c5 swt.install.window.header=\u4ee5\u4e0b\u88ab\u9009\u62e9\u7684\u7ec4\u4ef6\u5c06\u88ab\u5b89\u88c5\uff1a swt.uninstall.window.title=Vuze \u63d2\u4ef6\u5378\u8f7d\u5de5\u5177 swt.uninstall.window.ok=\u5378\u8f7d swt.uninstall.window.header=\u5df2\u9009\u62e9\u5378\u8f7d\u4ee5\u4e0b\u7ec4\u4ef6\uff1a installPluginsWizard.title=\u5b89\u88c5\u63d2\u4ef6 installPluginsWizard.mode.title=\u8bf7\u9009\u62e9\u4e00\u79cd\u5b89\u88c5\u65b9\u5f0f installPluginsWizard.mode.list=\u6309 sourceforge.net \u7684\u5217\u8868 installPluginsWizard.list.title=\u53ef\u5b89\u88c5\u7684\u63d2\u4ef6\u5217\u8868 installPluginsWizard.list.loading=\u8bf7\u7b49\u5f85\u63d2\u4ef6\u5217\u8868\u52a0\u8f7d\u5b8c\u6bd5\u3002 installPluginsWizard.list.loaded=\u8bf7\u9009\u62e9\u4f60\u60f3\u5b89\u88c5\u7684\u63d2\u4ef6 installPluginsWizard.list.name=\u540d\u5b57 installPluginsWizard.list.version=\u7248\u672c installPluginsWizard.list.description=\u63d2\u4ef6\u63cf\u8ff0 installPluginsWizard.finish.title=\u5b89\u88c5\u8fdb\u884c\u4e2d installPluginsWizard.finish.explanation=\u88ab\u9009\u62e9\u7684\u63d2\u4ef6\u5c06\u88ab\u66f4\u65b0\u52a9\u624b\u5b89\u88c5\u3002\n\n\u8bf7\u8010\u5fc3\u7b49\u5f85\uff0c\u8fd9\u53ef\u80fd\u9700\u8981\u4e00\u6bb5\u65f6\u95f4\u3002\n\n\u53cc\u51fb\u72b6\u6001\u680f\u5de6\u90e8\u53ef\u4ee5\u83b7\u5f97\u8fdb\u7a0b\u62a5\u544a\u3002 installPluginsWizard.details.loading=\u6b63\u5728\u52a0\u8f7d\u8be6\u7ec6\u8d44\u6599\uff0c\u8bf7\u7b49\u5f85\u2026 installPluginsWizard.mode.file=\u6309\u6587\u4ef6 installPluginsWizard.installMode.title=\u8bf7\u9009\u62e9\u5b89\u88c5\u7c7b\u578b installPluginsWizard.installMode.user=\u4ec5\u4e3a\u5f53\u524d\u7528\u6237\u5b89\u88c5\u63d2\u4ef6 installPluginsWizard.installMode.shared=\u4e3a\u6240\u6709\u7528\u6237\u5b89\u88c5\u63d2\u4ef6 installPluginsWizard.file.title=\u8bf7\u9009\u62e9\u4f60\u60f3\u5b89\u88c5\u7684\u63d2\u4ef6 installPluginsWizard.file.file=\u6587\u4ef6\uff1a installPluginsWizard.file.invalidfile=\u6b64\u6587\u4ef6\u4e0d\u662f\u4e00\u4e2a\u5408\u6cd5\u7684 Vuze \u63d2\u4ef6\u3002 installPluginsWizard.file.no_such_file=\u6240\u7ed9\u540d\u79f0\u7684\u6587\u4ef6\u4e0d\u5b58\u5728 installPluginsWizard.file.browse=\u6d4f\u89c8\u2026 uninstallPluginsWizard.title=\u5378\u8f7d\u63d2\u4ef6 uninstallPluginsWizard.list.title=\u5df2\u5b89\u88c5\u7684\u63d2\u4ef6\u5217\u8868 uninstallPluginsWizard.list.loaded=\u8bf7\u9009\u62e9\u4f60\u9700\u8981\u5378\u8f7d\u7684\u63d2\u4ef6 installPluginsWizard.list.nullversion=\u6ca1\u6709\u7248\u672c uninstallPluginsWizard.finish.title=\u5378\u8f7d\u8fdb\u884c\u4e2d uninstallPluginsWizard.finish.explanation=\u88ab\u9009\u4e2d\u7684\u63d2\u4ef6\u5c06\u88ab\u66f4\u65b0\u52a9\u624b\u5378\u8f7d\u3002 MainWindow.menu.plugins.installPlugins=\u5b89\u88c5\u5411\u5bfc MainWindow.menu.plugins.uninstallPlugins=\u5378\u8f7d\u5411\u5bfc ConfigView.section.ipfilter.totalIPs=\u603b\u5171 %1 \u4e2a IP \u88ab\u963b\u6b62\uff0c\u5360 Internet \u603b\u91cf\u7684 %2\u3002 update.instance.install=\u6b63\u5728\u68c0\u67e5\u5b89\u88c5 update.instance.uninstall=\u6b63\u5728\u68c0\u67e5\u5378\u8f7d update.instance.update=\u68c0\u67e5\u7a0b\u5e8f\u66f4\u65b0 MainWindow.status.update.tooltip=\u53cc\u51fb\u4ee5\u53d6\u5f97\u8fdb\u5c55\u4fe1\u606f updater.progress.window.title=\u5f53\u524d\u7684\u5b89\u88c5\u4efb\u52a1 updater.progress.window.info=\u6309"\u653e\u5f03"\u7ec8\u6b62\u6240\u6709\u672a\u5b8c\u6210\u7684\u4efb\u52a1 Button.abort=\u653e\u5f03 ConfigView.section.ipfilter.enablebanning=\u963b\u6b62\u59cb\u7ec8\u53d1\u9001\u9519\u8bef\u6570\u636e\u7684\u7528\u6237 Network.alert.acceptfail=\u5728\u7aef\u53e3 %1 \u4e0a\u4ea7\u751f\u8fc7\u591a\u7684\u9519\u8bef\uff0c%2 - \u5904\u7406\u88ab\u629b\u5f03\u3002\u8bf7\u68c0\u67e5\u6b64\u7aef\u53e3\u7684\u9632\u706b\u5899\u8bbe\u7f6e\uff0c\u786e\u4fdd\u5b83\u542f\u52a8\u4e86\u63a5\u6536\u8fde\u63a5\u3002 MyShares.column.category=\u7c7b\u522b UpdateWindow.restartLater=\u7a0d\u4faf\u91cd\u542f MainWindow.menu.file.restart=\u91cd\u542f MainWindow.dialog.restartconfirmation.title=\u91cd\u542f Vuze uff1f MainWindow.dialog.restartconfirmation.text=\u4f60\u60f3\u91cd\u542f Vuze \u5417\uff1f deletetorrent.message1=\u4f60\u5c06\u8981\u4ece\uff1a\n\u5220\u9664 TORRENT deletetorrent.message2=\n\u4f60\u786e\u5b9a\u8981\u7ee7\u7eed\u5417\uff1f ConfigView.label.prioritizemostcompletedfiles=\u4f18\u5148\u5373\u5c06\u4e0b\u8f7d\u5b8c\u6210\u7684\u6587\u4ef6 splash.plugin.init=\u521d\u59cb\u5316\u63d2\u4ef6\uff1a splash.plugin.UIinit=\u521d\u59cb\u5316\u63d2\u4ef6 GUI: %1 ConfigView.section.style.osx_small_fonts=\u4f7f\u7528\u5c0f\u5b57\u4f53\uff3b\u9700\u8981\u91cd\u542f\uff3d ConfigView.section.tracker.tcpnonblocking=\u4f7f\u7528\u975e\u963b\u585e I/O \u8fdb\u884c TCP Tracker \u5904\u7406\u3002\u9009\u62e9\u8be5\u9009\u9879\u9700\u8981 Tracker \u7f51\u7ad9\u8fd0\u884c\u5728\u53e6\u4e00\u4e2a\u7aef\u53e3\u3002\u8bd5\u9a8c\u4e2d\uff01 ConfigView.section.tracker.nonblocking=\u975e\u963b\u585e\u9009\u9879 ConfigView.section.tracker.nonblockingconcmax=\u6700\u5927\u540c\u65f6\u8fde\u63a5\u6570\uff3b0\uff1a\u65e0\u9650\u5236\uff3d MyTorrentsView.menu.exportmenu=\u5bfc\u51fa ConfigView.group.scrape=\u67e5\u8be2 ConfigView.section.tracker.client.scrapeinfo=\u7981\u7528\u67e5\u8be2\u4f1a\u4f7f\u5f88\u591a Torrent \u961f\u5217\u89c4\u5219\u4e0d\u80fd\u5de5\u4f5c\uff0c\u56e0\u4e3a\u5b83\u4eec\u4f9d\u8d56\u4e8e\u67e5\u8be2 Tracker \u83b7\u5f97\u7684\u7fa4\u4f53\u4fe1\u606f\u3002 ConfigView.section.tracker.client.scrapeenable=\u542f\u7528\u67e5\u8be2 ConfigView.section.tracker.client.scrapestoppedenable=\u67e5\u8be2\u5f53\u524d\u505c\u6b62\u7684 Torrent \u4fe1\u606f Scrape.status.disabled=\u67e5\u8be2\u5df2\u7981\u7528 MyTorrentsView.menu.explore=\u663e\u793a\u6587\u4ef6 MyTorrentsView.menu.explore._mac=\u5728 Finder \u4e2d\u663e\u793a MyTorrentsView.menu.explore._windows=\u5728\u8d44\u6e90\u7ba1\u7406\u5668\u4e2d\u663e\u793a wizard.maketorrents.autohost=\u4f7f\u7528\u5185\u5efa\u7684 Tracker \u5750\u5e84\u8be5 Torrent ConfigView.label.overrideip=\u8986\u76d6 Tracker Announce IP - \u5982\u679c\u591a\u4e8e\u4e00\u4e2a\u7f51\u7edc\uff0c\u8bf7\u7528\u5206\u53f7\u5206\u9694 ConfigView.label.overrideip.tooltip=\u901a\u77e5 Tracker \u4f7f\u7528\u4e0d\u540c\u4e8e\u8f93\u51fa\u5305\u7684 IP \u5730\u5740\u3002\u4e0d\u4f7f\u7528\u9009\u9879\u65f6\u7559\u7a7a\u3002 ConfigView.section.connection.group.networks=\u7f51\u7edc ConfigView.section.connection.group.networks.info=\u5141\u8bb8\u7684\u7f51\u7edc ConfigView.section.connection.networks.prompt=\u5305\u542b\u533f\u540d Tracker \u65f6\u63d0\u793a\u9009\u62e9\u7f51\u7edc ConfigView.section.connection.networks.Public=\u516c\u5171 IP \u7f51\u7edc\uff08\u4e0d\u533f\u540d\uff09 ConfigView.section.connection.networks.I2P=I2P \u533f\u540d\u7f51\u7edc ConfigView.section.connection.networks.Tor=Tor \u7279\u6b8a\u7f51\u7edc TableColumn.header.networks=\u7f51\u7edc TableColumn.header.networks.info=\u5141\u8bb8\u70b9\u5bf9\u70b9\u6570\u636e\u901a\u8baf\u7684\u7f51\u7edc Scrape.status.networkdisabled=\u7f51\u7edc\u6ca1\u6709\u542f\u7528 ConfigView.section.tracker.server.group.networks=\u7f51\u7edc ConfigView.section.tracker.server.group.networks.info=\u9009\u62e9 Tracker \u6240\u63a5\u53d7\u7528\u6237\u4f4d\u4e8e\u7684\u7f51\u7edc window.networkselection.title=\u7f51\u7edc\u9009\u62e9 window.networkselection.info=\u4e0b\u9762\u5217\u51fa\u7684 Torrent \u6240\u7528\u7684 Tracker \u4e2d\u6709\u7684\u652f\u6301\u5982\u4e0b\u7f51\u7edc\u3002\n\u9009\u62e9\u4e00\u4e2a\u4ee5\u542f\u7528 Tracker \u548c\u7528\u6237\u7684\u901a\u8baf\u3002\n\u5982\u679c\u5b83\u662f\u4e00\u4e2a\u533f\u540d Tracker\uff0c\u652f\u6301\u516c\u7528\u5ba2\u6237\u7aef\uff0c\u8bf7\u5c06\u533f\u540d\u548c\u516c\u7528\u7f51\u7edc\u90fd\u542f\u7528\u3002\n\u542f\u7528\u516c\u7528\u7f51\u7edc\u4f1a\u5bfc\u81f4\u60a8\u5931\u53bb\u533f\u540d\u6027\uff01 plugins.basicview.clear=\u6e05\u9664 ConfigView.section.connection.group.peersources=\u7528\u6237\u6765\u6e90 ConfigView.section.connection.group.peersources.info=\u5141\u8bb8\u7684\u7528\u6237\u6765\u6e90 ConfigView.section.connection.peersource.Tracker=Tracker ConfigView.section.connection.peersource.DHT=DHT ConfigView.section.connection.peersource.PeerExchange=\u6765\u6e90\u4ea4\u6362 ConfigView.section.connection.peersource.Plugin=\u63d2\u4ef6\u6dfb\u52a0 ConfigView.section.connection.peersource.Incoming=\u4f20\u5165\u8fde\u63a5 PeersView.source=\u6765\u6e90 PeersView.source.info=\u8be5\u7528\u6237\u7684\u6765\u6e90 TableColumn.header.peersources=\u7528\u6237\u6765\u6e90 TableColumn.header.peersources.info=\u5141\u8bb8\u5efa\u7acb\u7528\u6237\u8fde\u63a5\u7684\u7528\u6237\u6765\u6e90 wizard.tracker.dht=\u5206\u5e03\u5f0f\uff08\u4ec5\u652f\u6301 Vuze \u5ba2\u6237\u7aef\uff09 MyTorrentsView.menu.advancedmenu=\u9ad8\u7ea7 MyTorrentsView.menu.networks=\u7f51\u7edc MyTorrentsView.menu.peersource=\u7528\u6237\u6765\u6e90 ConfigView.section.sharing.permitdht=\u5728\u666e\u901a Tracker \u4e0d\u53ef\u7528\u65f6\u5141\u8bb8\u4f7f\u7528 DHT ConfigView.section.sharing.protocol=\u5171\u4eab\u8d44\u6e90\u534f\u8bae\uff08\u9700\u8981\u914d\u7f6e Tracker\uff09 PeersView.Messaging=\u6b63\u5728\u4f20\u8f93\u6d88\u606f PeersView.Messaging.info=\u652f\u6301\u9ad8\u7ea7\u6d88\u606f API\u3002 ConfigView.label.queue.newseedsmovetop=\u79fb\u52a8\u6700\u65b0\u5b8c\u6210\u7684 Torrent \u4e0b\u8f7d\u5230\u505a\u79cd\u5217\u8868\u7684\u6700\u9876\u7aef ConfigView.label.seeding.firstPriority.ignore.info=\u8bf7\u6ce8\u610f\u4f7f\u7528\u8fd9\u4e9b\u89c4\u5219\u53ef\u80fd\u5bfc\u81f4\u67d0\u4e2a Torrent \u6587\u4ef6\u5728\u4e0b\u8f7d\n\u5b8c\u6210\u540e\u7acb\u5373\u505c\u6b62\u4e0a\u4f20\u3002 ConfigView.label.seeding.firstPriority.ignore=\u4e3a\u4e4b\u5ffd\u7565\u7b2c\u4e00\u4f18\u5148\u7ea7\u89c4\u5219\uff1a ConfigView.label.seeding.firstPriority.ignoreSPRatio=\u79cd\u5b50\uff1a\u7528\u6237 > ConfigView.label.seeding.firstPriority.ignore0Peer=0 \u7528\u6237\u7684 Torrent \u6587\u4ef6 ConfigView.section.tracker.sendjavaversionandos=\u53d1\u9001 Java \u7248\u672c\u548c\u64cd\u4f5c\u7cfb\u7edf\u540d\u79f0 MagnetPlugin.contextmenu.exporturi=\u590d\u5236 Magnet URI \u5230\u526a\u8d34\u677f ConfigView.section.plugins.dht=\u5206\u5e03\u5f0f\u6570\u636e\u5e93 dht.info=\u8fd9\u4e2a\u63d2\u4ef6\u652f\u6301\u5206\u5e03\u5f0f\u8ddf\u8e2a\u548c\u5176\u5b83\u4e00\u4e9b\u529f\u80fd\u3002\u7981\u7528\u5b83\u4f1a\u964d\u4f4e\u60a8\u7684\u4e0b\u8f7d\u80fd\u529b dht.enabled=\u542f\u7528\u5206\u5e03\u5f0f\u6570\u636e\u5e93 dht.portdefault=\u4f7f\u7528\u9ed8\u8ba4\u7aef\u53e3 dht.port=\u6570\u636e\u5e93\u7684 UDP \u7aef\u53e3 dht.execute.command=\u8bca\u65ad\u547d\u4ee4 dht.execute.info=\u70b9\u51fb\u4ee5\u6267\u884c\u8be5\u547d\u4ee4 dht.execute=\u8fd0\u884c dht.logging=\u542f\u7528\u6d3b\u8dc3\u6027\u8ddf\u8e2a ConfigView.section.plugins.dhttracker=DHT dhttracker.tracknormalwhenoffline=\u4ec5\u5728\u666e\u901a Tracker \u4e0d\u53ef\u7528\u65f6\u624d\u8ddf\u8e2a Torrent ConfigView.section.file.nativedelete._mac=\u5220\u9664\u6587\u4ef6\u65f6\u4f7f\u7528\u56de\u6536\u7ad9 ConfigView.section.file.nativedelete._windows=\u79fb\u52a8\u5220\u9664\u7684\u6587\u4ef6\u5230\u56de\u6536\u7ad9 ConfigView.section.logging.generatediagnostics=\u751f\u6210 ConfigView.section.logging.netinfo=\u751f\u6210\u7f51\u7edc\u4fe1\u606f ConfigView.section.logging.statsinfo=\u751f\u6210\u72b6\u6001\u4fe1\u606f ConfigView.section.logging.generatediagnostics.info=\u5982\u679c\u542f\u7528\uff0c\u5219\u751f\u6210\u8bca\u65ad\u4fe1\u606f\u5e76\u590d\u5236\u5230\u526a\u8d34\u677f\u548c\u65e5\u5fd7\u6587\u4ef6\u3002 ConfigView.section.sharing.privatetorrent=\u79c1\u4e0b\u7684 Torrent - \u4ec5\u4ece\u666e\u901a Tracker \u63a5\u6536\u7528\u6237\u4fe1\u606f MainWindow.menu.tools.nattest=NAT / \u9632\u706b\u5899\u6d4b\u8bd5\uff08&N\uff09 Button.apply=\u5e94\u7528 Button.close=\u5173\u95ed window.welcome.title=\u6b22\u8fce\u6765\u5230 Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=\u53d1\u884c\u6ce8\u8bb0 dht.reseed.label=\u901a\u5e38\u60c5\u51b5\u4e0b\u65e0\u9700\u91cd\u65b0\u5f15\u5bfc\u6570\u636e\u5e93\u3002\u4f46\u662f\uff0c\u5982\u679c\u8054\u7cfb\u4eba\u6570\u91cf\u8fc7\u4f4e\uff0c\u4fbf\u9700\u91cd\u65b0\u6574\u5408\u3002\n\u7559\u7a7a\u4ee5\u4ece\u5df2\u8fde\u63a5\u7684\u7528\u6237\u5f15\u5bfc\uff0c\u6216\u662f\u8f93\u5165 IP \u548c\u7aef\u53e3\u4ee5\u4ece\u67d0\u4e2a\u5df2\u77e5\u7528\u6237\u5f15\u5bfc\u3002 dht.reseed.group=\u91cd\u65b0\u5f15\u5bfc dht.reseed.ip=IP \u5730\u5740 dht.reseed.port=\u7aef\u53e3 dht.reseed=\u91cd\u65b0\u5f15\u5bfc dht.reseed.info=\u91cd\u65b0\u5f15\u5bfc\u6570\u636e\u5e93 dht.diagnostics.group=\u8bca\u65ad DHTView.title.full=\u5206\u5e03\u5f0f\u6570\u636e\u5e93 DHTView.title.fullcvs=\u5206\u5e03\u5f0f\u6570\u636e\u5e93 CVS DHTView.general.title=\u5e38\u89c4 DHTView.general.uptime=\u751f\u5b58\u65f6\u95f4\uff1a DHTView.general.users=\u7528\u6237\uff1a DHTView.general.nodes=\u8282\u70b9\uff1a DHTView.general.leaves=\u53f6\u5b50\uff1a DHTView.general.contacts=\u8054\u7cfb\u4eba\uff1a DHTView.general.replacements=\u66ff\u4ee3\u8005\uff1a DHTView.general.live=\u5b58\u6d3b\uff1a DHTView.general.unknown=\u672a\u77e5\uff1a DHTView.general.dying=\u5c06\u6b7b\uff1a DHTView.transport.title=\u4f20\u8f93\u7ec6\u8282 DHTView.transport.packets=\u5305 DHTView.transport.bytes=\u5b57\u8282 DHTView.transport.received=\u5df2\u63a5\u6536 DHTView.transport.sent=\u5df2\u53d1\u9001 DHTView.transport.in=\u5165\uff1a DHTView.transport.out=\u51fa\uff1a DHTView.operations.title=\u64cd\u4f5c\u7ec6\u8282 DHTView.operations.sent=\u5df2\u53d1\u9001 DHTView.operations.ok=\u786e\u5b9a DHTView.operations.failed=\u5931\u8d25 DHTView.operations.received=\u5df2\u63a5\u6536 DHTView.operations.findNode=\u67e5\u627e\u8282\u70b9 DHTView.operations.findValue=\u67e5\u627e\u503c DHTView.operations.store=\u50a8\u5b58 DHTView.activity.title=\u6d3b\u8dc3\u6027 DHTView.activity.status=\u72b6\u6001 DHTView.activity.status.true=\u6392\u961f\u4e2d DHTView.activity.status.false=\u6b63\u5728\u8fd0\u884c DHTView.activity.type=\u7c7b\u578b DHTView.activity.type.1=\u5185\u90e8 Get DHTView.activity.type.2=\u5916\u90e8 Get DHTView.activity.type.3=\u5185\u90e8 Put DHTView.activity.type.4=\u5916\u90e8 Put DHTView.activity.target=\u76ee\u6807 DHTView.activity.details=\u8be6\u7ec6\u4fe1\u606f DHTView.db.title=\u6570\u636e\u5e93 DHTView.db.keys=\u952e DHTView.db.values=\u503c DHTView.db.local=\u672c\u5730 DHTView.db.direct=\u76f4\u63a5 DHTView.db.indirect=\u975e\u76f4\u63a5 DHTView.db.divfreq=\u9891\u7387 Div. DHTView.db.divsize=\u5927\u5c0f Div. MainWindow.dht.status.tooltip=\u5f53\u5206\u5e03\u5f0f\u6570\u636e\u5e93\u6b63\u5728\u8fd0\u884c\u65f6\uff0c\u8fd9\u91cc\u663e\u793a\u4f30\u8ba1\u7684\u5f53\u524d\u5728\u7ebf\u7684\u7528\u6237\u6570 MainWindow.dht.status.disabled=DHT \u5df2\u7981\u7528 MainWindow.dht.status.failed=DHT \u5931\u8d25 MainWindow.dht.status.initializing=DHT \u6b63\u5728\u521d\u59cb\u5316 MainWindow.dht.status.users=%1 \u7528\u6237 MainWindow.dht.status.unreachable=DHT \u5728\u9632\u706b\u5899\u540e MainWindow.dht.status.unreachabletooltip=\u5206\u5e03\u5f0f\u6570\u636e\u5e93 UDP \u7aef\u53e3\u6620\u5c04\u53ef\u80fd\u51fa\u73b0\u95ee\u9898\uff08NAT/\u9632\u706b\u5899\uff09 MyTorrentsView.menu.setUpSpeed=\u8bbe\u7f6e\u4e0a\u4f20\u901f\u5ea6 MyTorrentsView.menu.setDownSpeed=\u8bbe\u7f6e\u4e0b\u8f7d\u901f\u5ea6 ConfigView.section.tracker.client.showwarnings=\u663e\u793a Tracker \u62a5\u544a\u7684\u8b66\u544a\u4fe1\u606f dht.advanced=\u542f\u7528\u9ad8\u7ea7\u8bbe\u7f6e dht.advanced.group=\u9ad8\u7ea7\u8bbe\u7f6e dht.advanced.label=\u5982\u679c\u60a8\u77e5\u9053\u81ea\u5df1\u5728\u505a\u4ec0\u4e48\uff0c\u8bf7\u4ec5\u4fee\u6539\u8fd9\u4e9b\u503c dht.override.ip=\u8986\u76d6\u5916\u90e8 IP \u5730\u5740 ConfigView.section.logging.loggerenable=\u542f\u7528\u65e5\u5fd7 ConfigView.section.ipfilter.blockbanning=\u5728\u67d0\u4e2a IP \u6bb5\u5185\u5c01\u7981\u8d85\u8fc7\u8fd9\u4e2a\u6570\u76ee\u7684 IP \u5730\u5740\u540e\uff0c\u5c01\u7981\u8fd9\u4e2a IP \u6bb5\u7684\u6240\u6709 256 \u4e2a\u5730\u5740 MyTrackerView.passive=\u88ab\u52a8 TableColumn.header.swarm_average_speed=\u7fa4\u4f53\u5e73\u5747\u901f\u5ea6 TableColumn.header.swarm_average_speed.info=\u7fa4\u4f53\u7528\u6237\u5e73\u5747\u901f\u5ea6 TableColumn.header.comment=\u8bc4\u4ef7 TableColumn.header.comment.info=\u4e0b\u8f7d\u8005\u5bf9\u8be5\u4e0b\u8f7d\u7684\u8bc4\u8bba TableColumn.header.commenticon=\u8bc4\u8bba\u56fe\u6807 TableColumn.header.commenticon.info=\u5982\u679c\u7528\u6237\u5bf9\u8be5\u4e0b\u8f7d\u6709\u8bc4\u8bba\u5219\u663e\u793a\u8bc4\u8bba\u56fe\u6807 MyTrackerView.category=\u5206\u7c7b MainWindow.menu.file.open.torrentfortracking=.torrent \u6587\u4ef6\u2026\uff08\u4ec5\u6dfb\u52a0\u5230\u5185\u7f6e Tracker \u4ee5\u4fbf\u8ddf\u8e2a\uff09 VivaldiView.title.full=\u7528\u6237\u865a\u62df\u5206\u5e03 MyTrackerView.date_added=\u6dfb\u52a0\u65e5\u671f ConfigView.section.tracker.portbackup=\u5907\u7528\u7aef\u53e3\uff08\u7528\u201c\uff1b\u201d\u5206\u9694\uff09 ConfigView.label.playfilespeech=\u6587\u4ef6\u4e0b\u8f7d\u5b8c\u6210\u540e\u8bed\u97f3\u63d0\u793a ConfigView.label.playfilespeech.info=\u8bed\u97f3\u670d\u52a1\u76ee\u524d\u5bf9\u82f1\u8bed\u652f\u6301\u662f\u6700\u597d\u7684 ConfigView.label.playfilefinished=\u6587\u4ef6\u4e0b\u8f7d\u5b8c\u6210\u540e\u64ad\u653e\u58f0\u97f3 ConfigView.label.backupconfigfiles=\u5907\u4efd\u914d\u7f6e\u6587\u4ef6 ConfigView.section.tracker.client.scrapesingleonly=\u7981\u6b62\u6bcf\u6b21\u8bf7\u6c42\u5411 Tracker \u67e5\u8be2\u591a\u4e2a Hash \u503c\uff08\u53ef\u4ee5\u89e3\u51b3\u67d0\u4e9b Tracker \u62a5\u544a \u201c URL \u8fc7\u957f\u201d\uff08414\uff09 \u7684\u9519\u8bef\uff09 dht.ipfilter.log=\u8bb0\u5f55\u8fdd\u53cd IP \u8fc7\u6ee4\u5668\u89c4\u5219\u7684\u884c\u4e3a ConfigView.label.seeding.addForSeedingDLCopyCount=\u8003\u8651\u201c\u6dfb\u52a0\u5230\u505a\u79cd\u201d\u4efb\u52a1\u5df2\u4e0b\u8f7d\u4e86\u5982\u4e0b\u6570\u76ee\u7684\u526f\u672c ActivityView.legend.limit=\u9650\u5236 ActivityView.legend.achieved=\u5f53\u524d ActivityView.legend.overhead=\u603b\u5f00\u9500 ActivityView.legend.peeraverage=\u5e73\u5747 ActivityView.legend.swarmaverage=\u7fa4\u4f53\u5e73\u5747 ActivityView.legend.trimmed=\u524a\u51cf\uff08\u70b9\u72b6\uff09 MyTorrentsView.menu.movemenu=\u79fb\u52a8\u6587\u4ef6 MyTorrentsView.menu.movedata=\u79fb\u52a8\u6570\u636e\u6587\u4ef6\u2026 MyTorrentsView.menu.movetorrent=\u79fb\u52a8 Torrent \u6587\u4ef6\u2026 MyTorrentsView.menu.movedata.dialog=\u9009\u62e9\u65b0\u4f4d\u7f6e DHTView.operations.data=\u6570\u636e DHTView.general.reachable=\u53ef\u5230\u8fbe\uff1a DHTView.general.rendezvous=\u96c6\u5408\u70b9\uff1a ConfigView.label.queue.maxactivetorrentswhenseeding=\u4ec5\u505a\u79cd\u65f6\u7684\u6700\u5927\u4efb\u52a1\u6570\uff3b0\uff1a\u65e0\u9650\u5236\uff3d Views.plugins.IRC.title=IRC - \u5728\u7ebf\u6280\u672f\u652f\u6301 Formats.units.kB=KB Formats.units.kbit=Kbit Formats.units.alot=\u5f88\u591a \uff01\uff01\uff01 ConfigView.section.ipfilter.persistblocking=\u4e0b\u6b21\u542f\u52a8\u7684\u65f6\u5019\u4fdd\u7559\u4e0a\u6b21\u5c01\u7981\u7684 IP \u5730\u5740 FilesView.menu.rename=\u4fee\u6539\u76ee\u6807 FilesView.menu.rename_only=\u91cd\u547d\u540d FilesView.menu.retarget=\u79fb\u52a8\u76ee\u6807 FilesView.rename.choose.path=\u9009\u62e9\u65b0\u7684\u6216\u5b58\u5728\u7684\u6587\u4ef6 FilesView.rename.choose.path.dir=\u9009\u62e9\u91cd\u65b0\u4e0b\u8f7d\u6216\u8005\u7eed\u4f20\u4e0b\u8f7d\u7684\u76ee\u5f55 FilesView.rename.confirm.delete.title=\u786e\u8ba4\u5220\u9664 FilesView.rename.confirm.delete.text=\u786e\u8ba4\u5220\u9664\u539f\u6587\u4ef6\u201c%1\u201d FilesView.rename.filename.title=\u91cd\u547d\u540d\u6587\u4ef6 FilesView.rename.filename.text=\u4e3a\u8be5\u6587\u4ef6\u9009\u62e9\u4e00\u4e2a\u65b0\u540d\u79f0 ConfigView.higher.mode.available=\u66f4\u591a\u9009\u9879\u5728\u9ad8\u7ea7\u7528\u6237\u6a21\u5f0f\u4e0b\u53ef\u7528 ConfigView.section.mode=\u6a21\u5f0f ConfigView.section.mode.title=\u7528\u6237\u719f\u7ec3\u7a0b\u5ea6 ConfigView.section.mode.beginner=\u521d\u7ea7 ConfigView.section.mode.beginner.wiki.definitions=BitTorrent \u8bcd\u6c47\u8868 ConfigView.section.mode.intermediate=\u4e2d\u7ea7 ConfigView.section.mode.intermediate.wiki.host=\u5750\u5e84\u6587\u4ef6 ConfigView.section.mode.intermediate.wiki.publish=\u53d1\u5e03\u6587\u4ef6 ConfigView.section.mode.advanced=\u9ad8\u7ea7 ConfigView.section.mode.advanced.wiki.main=Wiki \u4e3b\u9875 ConfigView.section.mode.beginner.text=\u4e0b\u8f7d Torrent \u662f\u60a8\u7684\u5168\u90e8\u9700\u8981\u3002\n\u5982\u679c\u60a8\u7684\u5168\u90e8\u9700\u8981\u662f\u4e0b\u8f7d\u548c\u7ba1\u7406 Torrent \u6587\u4ef6\uff0c\u8bf7\u4f7f\u7528\u8fd9\u4e2a\u6a21\u5f0f\u3002 ConfigView.section.mode.intermediate.text=\u53ef\u4ee5\u4f7f\u7528 Tracker \u529f\u80fd\u3002\n\u5982\u679c\u60a8\u60f3\u521b\u5efa\u81ea\u5df1\u7684 Tracker \u6765\u5750\u5e84/\u53d1\u5e03\u60a8\u7684\u6587\u4ef6\uff0c\u8bf7\u4f7f\u7528\u8fd9\u4e2a\u6a21\u5f0f\u3002 ConfigView.section.mode.advanced.text=\u8be5\u6a21\u5f0f\u53ef\u4ee5\u8bbf\u95ee\u7f51\u7edc\u8bbe\u7f6e\u3002\n\u5982\u679c\u60a8\u77e5\u9053 MTU \u6216\u975e\u963b\u585e I/O \u662f\u4ec0\u4e48\uff0c\u60a8\u53ef\u4ee5\u542f\u7528\u8fd9\u4e2a\u6a21\u5f0f\u3002 Files.column.storagetype=\u50a8\u5b58\u7c7b\u578b Files.column.fileext=\u7c7b\u522b FileItem.storage.linear=\u7ebf\u6027 FileItem.storage.compact=\u7d27\u51d1 MessageBoxWindow.rememberdecision=\u8bb0\u4f4f\u6211\u7684\u9009\u62e9 ConfigView.section.interface.cleardecisions=\u6e05\u9664\u8bb0\u5fc6\u7684\u5bf9\u8bdd\u6846\u9009\u9879 ConfigView.section.interface.cleardecisionsbutton=\u6e05\u9664 ConfigView.section.interface.cleartrackers=\u6e05\u9664 Tracker \u8bb0\u5f55 ConfigView.section.interface.cleartrackersbutton=\u6e05\u9664 ConfigView.section.interface.clearsavepaths=\u6e05\u9664\u5b58\u50a8\u76ee\u5f55\u8bb0\u5f55 ConfigView.section.interface.clearsavepathsbutton=\u6e05\u9664 configureWizard.welcome.usermodes=\u7528\u6237\u719f\u7ec3\u7a0b\u5ea6\u8bbe\u7f6e\u51b3\u5b9a\u201c\u5de5\u5177->\u9009\u9879\u201d\u4e2d\u663e\u793a\u7684\u9009\u9879\u7684\u7ea7\u522b\u3002\u60a8\u53ef\u4ee5\u6839\u636e\u81ea\u5df1\u7684\u5b9e\u9645\u60c5\u51b5\u6765\u8bbe\u7f6e\u3002 FilesView.skip.confirm.delete.text=\u5220\u9664\u6587\u4ef6\u201c%1\u201d\u4ee5\u8282\u7ea6\u7a7a\u95f4\uff1f FilesView.rename.failed.title=\u91cd\u547d\u540d/\u79fb\u52a8\u76ee\u6807\u5931\u8d25 FilesView.rename.failed.text=\u64cd\u4f5c\u5931\u8d25\uff0c\u53ef\u80fd\u56e0\u4e3a\u9009\u62e9\u4e86\u65e0\u6548\u7684\u76ee\u6807 diagnostics.log_found=Vuze \u6ca1\u6709\u6b63\u786e\u5173\u95ed\u3002\u8bf7\u68c0\u67e5%1\u7684\u8bca\u65ad\u65e5\u5fd7\uff0c\u5982\u679c\u662f\u7a0b\u5e8f\u9519\u8bef\u9020\u6210\u7684\u95ee\u9898\uff0c\u8bf7\u628a\u60c5\u51b5\u62a5\u544a\u7ed9 Vuze \u5de5\u4f5c\u7ec4\u3002 ManagerItem.paused=\u5df2\u6682\u505c Utils.link.visit=\u8bf7\u8bbf\u95ee ConfigView.section.connection.serverport.wiki=\u7aef\u53e3\u7684\u9009\u62e9 ConfigView.section.transfer.speeds.wiki=\u901f\u5ea6\u8bbe\u7f6e\u65b9\u6cd5 installPluginsWizard.installMode.info.title=\u4fe1\u606f installPluginsWizard.installMode.info.text=\u60a8\u4e0d\u9700\u8981\u63d2\u4ef6\u6765\u8ba9 Vuze \u5de5\u4f5c\uff0c\u4f46\u662f\u5b83\u4eec\u4f1a\u5728\u5a31\u4e50\u3001\u81ea\u52a8\u5316\u6216\u8fdc\u7a0b\u63a7\u5236\u4e0a\u5e26\u6765\u529f\u80fd\u4e0a\u7684\u8865\u5145\u3002\n\u56e0\u6b64\u5728\u5b89\u88c5\u63d2\u4ef6\u4e4b\u524d\u8bf7\u4ed4\u7ec6\u9605\u8bfb\u63d2\u4ef6\u7684\u4ecb\u7ecd\u3002\n\u5b89\u88c5\u5927\u591a\u6570\u7684\u63d2\u4ef6\u662f\u5b89\u5168\u7684\uff0c\u4e0d\u8fc7\u65e0\u7528\u7684\u63d2\u4ef6\u4f1a\u589e\u52a0\u60a8\u7684\u914d\u7f6e\u8d1f\u62c5\u3002 Views.plugins.Distributed.DB.title=\u5206\u5e03\u5f0f\u6570\u636e\u5e93 Views.plugins.Distributed.Tracker.title=DHT Views.plugins.Plugin.Update.title=\u63d2\u4ef6\u66f4\u65b0 Views.plugins.UPnP.title.tooltip=\u5168\u5c40\u5373\u63d2\u5373\u7528 openUrl.url.info=\u652f\u6301 http\u3001https\u3001magnet \u548c\u7eaf\u5341\u516d\u8fdb\u5236 infohash \u5b57\u7b26\u4e32 TableColumn.header.swarm_average_completion=\u7528\u6237\u5e73\u5747\u5b8c\u6210\u5ea6 TableColumn.header.swarm_average_completion.info=\u7fa4\u4f53\u7528\u6237\u7684\u5e73\u5747\u4e0b\u8f7d\u5b8c\u6210\u7387 GeneralView.label.swarm_average_completion=\u5e73\u5747\u5b8c\u6210\u5ea6\uff1a GeneralView.label.swarm_average_completion.tooltip=\u7fa4\u4f53\u7528\u6237\u7684\u5e73\u5747\u4e0b\u8f7d\u5b8c\u6210\u7387 MainWindow.nat.status.tooltip.unknown=\u9632\u706b\u5899/NAT\uff08TCP\uff09 \u53ef\u5230\u8fbe\u6027\u72b6\u6001\u672a\u77e5 MainWindow.nat.status.ok=NAT \u6b63\u5e38 MainWindow.nat.status.tooltip.ok=\u53ef\u5230\u8fbe\u6027\u6b63\u5e38\uff08TCP\uff09 MainWindow.nat.status.probok=NAT \u6b63\u5e38\uff1f MainWindow.nat.status.tooltip.probok=\u53ef\u5230\u8fbe\u6027\u6b63\u5e38\uff0c\u4f46\u662f\u6700\u8fd1\u6ca1\u6709\u4f20\u5165\u7684 TCP \u8fde\u63a5 MainWindow.nat.status.bad=\u88ab\u9632\u706b\u5899\u963b\u6321 MainWindow.nat.status.tooltip.bad=\u9632\u706b\u5899/NAT\uff08TCP\uff09 \u53ef\u5230\u8fbe\u6027\u95ee\u9898\u3002\u8bf7\u67e5\u770b Wiki \u83b7\u53d6\u5e2e\u52a9 plugin.installer.recommended.plugin=\u63a8\u8350\u7684\u63d2\u4ef6 - \u8bf7\u6d4f\u89c8\u4e00\u4e0b\uff0c\u5982\u679c\u60a8\u6709\u9700\u8981\u53ef\u4ee5\u5b89\u88c5 LoggerView.pause=\u6682\u505c\u8bb0\u5f55 LoggerView.clear=\u6e05\u9664\uff08&C\uff09 LoggerView.filter=\u8fc7\u6ee4\u5668 LoggerView.filter.uncheckAll=\u53d6\u6d88\u9009\u62e9\u5168\u90e8\u5206\u7c7b LoggerView.filter.checkAll=\u9009\u62e9\u5168\u90e8\u5206\u7c7b LoggerView.loggingDisabled=\u65e5\u5fd7\u6ca1\u6709\u542f\u7528\u3002 LoggerView.includeOnly=\u53ea\u663e\u793a\u6ee1\u8db3\u8fd9\u4e2a\u6b63\u5219\u8868\u8fbe\u7684\u884c\uff1a LoggerView.excludeAll=\u4e0d\u663e\u793a\u6ee1\u8db3\u8fd9\u4e2a\u6b63\u5219\u8868\u8fbe\u7684\u884c\uff1a ConfigView.section.logging.log0type=\u6d88\u606f ConfigView.section.logging.log1type=\u8b66\u544a ConfigView.section.logging.log2type=\u9519\u8bef ConfigView.section.logging.filter=\u8bb0\u5f55\u5230\u6587\u4ef6\u65f6\u8fc7\u6ee4 ConfigView.section.logging.level=\u8bb0\u5f55\u7ea7\u522b ConfigView.section.logging.showLogsFor=\u663e\u793a\u5982\u4e0b\u5206\u7c7b\u7684 %1 \u65e5\u5fd7\uff1a ConfigView.pluginlist.column.loadAtStartup=\u542f\u52a8\u65f6\u88c5\u8f7d ConfigView.pluginlist.column.type=\u7c7b\u578b ConfigView.pluginlist.column.type.perUser=\u5355\u7528\u6237 ConfigView.pluginlist.column.type.shared=\u5171\u4eab ConfigView.pluginlist.column.type.builtIn=\u5185\u5efa ConfigView.pluginlist.column.name=\u540d\u79f0 ConfigView.pluginlist.column.version=\u7248\u672c ConfigView.pluginlist.column.directory=\u76ee\u5f55 ConfigView.pluginlist.column.isOperational=\u53ef\u7528\uff1f PeersView.BlockView.Avail.Have=\u5747\u62e5\u6709 PeersView.BlockView.Avail.NoHave=\u7528\u6237\u62e5\u6709\uff0c\u4f46\u60a8\u6ca1\u6709 PeersView.BlockView.NoAvail.Have=\u60a8\u62e5\u6709\uff0c\u7528\u6237\u6ca1\u6709 PeersView.BlockView.NoAvail.NoHave=\u5747\u6ca1\u6709 PeersView.BlockView.Transfer=\u6b63\u5728\u4f20\u8f93 PeersView.BlockView.NextRequest=\u4e0b\u4e00\u4e2a\u8bf7\u6c42 PeersView.BlockView.title=\u533a\u5757\u6620\u5c04 PeersView.BlockView.AvailCount=\u53ef\u7528\u6027\u8ba1\u6570 MyTorrentsView.dialog.NumberError.title=\u65e0\u6548\u6216\u4e0d\u88ab\u627f\u8ba4\u7684\u6570\u5b57 MyTorrentsView.dialog.NumberError.text=\u60a8\u8f93\u5165\u7684\u6570\u5b57\u65e0\u6548\u6216\u4e0d\u88ab\u627f\u8ba4\u3002 MyTorrentsView.menu.manual=\u624b\u52a8\uff08&M\uff09\u2026 MyTorrentsView.menu.manual.per_torrent=\u624b\u52a8\uff08\u6bcf Torrent\uff09 MyTorrentsView.menu.manual.shared_torrents=\u624b\u52a8\uff08\u5168\u90e8 torrents\uff09 MyTorrentsView.dialog.setSpeed.title=\u8bbe\u7f6e %1 \u901f\u5ea6 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=\u8f93\u5165\u4e00\u4e2a\u6570\u5b57 %1 \u4ee5\u4fee\u6539 %2 \u4e3a\uff1a MyTorrentsView.dialog.setNumber.upload=\u4e0a\u4f20 MyTorrentsView.dialog.setNumber.download=\u4e0b\u8f7d MyTorrentsView.dialog.setNumber.inKbps=\u5355\u4f4d\uff1a %1 OpenTorrentWindow.torrentLocation=Torrent \u6587\u4ef6\uff1a OpenTorrentWindow.addFiles.URL=\u4ece URL \u6dfb\u52a0\uff08&U\uff09 OpenTorrentWindow.addFiles.Folder=\u4ece\u6587\u4ef6\u5939\u6dfb\u52a0\uff08&F\uff09 OpenTorrentWindow.addFiles.Clipboard=\u4ece\u526a\u8d34\u677f\u6dfb\u52a0\uff08&B\uff09 OpenTorrentWindow.changeDestination=\u4fee\u6539\u76ee\u6807 OpenTorrentWindow.fileList=Torrent \u4e2d\u7684\u6587\u4ef6\uff1a OpenTorrentWindow.torrentTable.name=\u540d\u79f0 OpenTorrentWindow.torrentTable.saveLocation=\u4fdd\u5b58\u4f4d\u7f6e OpenTorrentWindow.fileTable.fileName=\u6587\u4ef6\u540d OpenTorrentWindow.fileTable.size=\u6587\u4ef6\u5927\u5c0f OpenTorrentWindow.fileTable.destinationName=\u76ee\u6807\u6587\u4ef6\u540d OpenTorrentWindow.startMode.seeding=\u505a\u79cd OpenTorrentWindow.fileList.changeDestination=\u4fee\u6539\u76ee\u6807 OpenTorrentWindow.mb.badSize.title=\u4e0d\u517c\u5bb9\u6587\u4ef6 OpenTorrentWindow.mb.badSize.text=\u201c%1\u201d \u4e0d\u662f \u201c%2\u201d\uff0c\u56e0\u6b64\u4e0d\u80fd\u7528\u6765\u505a\u79cd OpenTorrentWindow.mb.alreadyExists.text=Torrent \u201c%1\u201d \u5df2\u7ecf\u88ab\u4f5c\u4e3a \u201c%2\u201d \u6dfb\u52a0 OpenTorrentWindow.mb.alreadyExists.default.name=\u5a92\u4f53 OpenTorrentWindow.mb.alreadyExists.title=Torrent \u5df2\u7ecf\u5b58\u5728 OpenTorrentWindow.mb.openError.title=\u6253\u5f00\u9519\u8bef OpenTorrentWindow.mb.openError.text=\u201c%1\u201d \u65e0\u6cd5\u88ab\u6253\u5f00\uff1a OpenTorrentWindow.torrent.remove=\u4ece\u5217\u8868\u4e2d\u79fb\u9664 Torrent OpenTorrentWindow.torrent.options=\u4e0b\u9762\u7684\u8bbe\u7f6e\u5c06\u5e94\u7528\u5230\u4e0a\u9762\u9009\u62e9\u7684 Torrent \u4e2d\uff1a OpenTorrentWindow.xOfTotal=\uff08\u7b2c %1 \u4e2a\uff0c\u5171\u8ba1 %2 \u4e2a\uff09 iconBar.open.tooltip=\u6253\u5f00 Torrent \u6587\u4ef6 LocaleUtil.column.text=\u672a\u77e5\u6587\u672c Tracker.tooltip.MultiSupport=\u8be5 Tracker \u652f\u6301\u6bcf\u6b21\u8bf7\u6c42\u67e5\u8be2\u591a\u4e2a Hash \u503c\u3002 Tracker.tooltip.NoMultiSupport=\u8be5 Tracker \u4e0d\u652f\u6301\u6bcf\u6b21\u8bf7\u6c42\u67e5\u8be2\u591a\u4e2a Hash \u503c\u3002 ConfigView.label.lazybitfield=\u4f7f\u7528\u61d2\u6563 bitfield\uff08\u5e2e\u52a9\u89e3\u51b3 ISP \u7981\u6b62\u7528\u6237\u505a\u79cd\u7684\u95ee\u9898\uff09 LoggerView.realtime=\u5b9e\u65f6\u66f4\u65b0 ConfigView.section.file.perf.cache.flushpieces=\u7acb\u5373\u5c06\u5b8c\u6210\u7684\u5757\u5199\u5165\u786c\u76d8\u3002\u8fd9\u53ef\u4ee5\u4f7f\u786c\u76d8\u8bbf\u95ee\u66f4\u5e73\u6ed1\uff0c\u4f46\u4f1a\u589e\u52a0\u5199\u64cd\u4f5c\uff0c\u52a0\u91cd\u786c\u76d8\u7684\u8d1f\u62c5\u3002 ConfigView.section.file.writemblimit=\u6700\u5927\u5199\u8bf7\u6c42\u7f13\u5b58\uff08\u5355\u4f4d\uff1a %1\uff09 ConfigView.section.file.writemblimit.explain=\u5728\u78c1\u76d8\u5199\u901f\u5ea6\u4f4e\u4e8e\u4e0b\u8f7d\u901f\u5ea6\u65f6\uff0c\u8be5\u53c2\u6570\u9650\u5236\u5728\u964d\u4f4e\u4e0b\u8f7d\u901f\u5ea6\u524d\uff0c\u591a\u5c11\u6570\u636e\u88ab\u7f13\u5b58\u5728\u5185\u5b58\u4e2d\u3002 ConfigView.section.file.readmblimit=\u6700\u5927\u8bfb\u8bf7\u6c42\u7f13\u5b58\uff08\u5355\u4f4d\uff1a %1\uff09 ConfigView.section.file.readmblimit.explain=\u8be5\u53c2\u6570\u9650\u5236\u4e3a\u50a8\u5b58\u7b49\u5f85\u5904\u7406\u7684\u8bfb\u8bf7\u6c42\u800c\u4f7f\u7528\u7684\u5185\u5b58\u6570\u3002 Button.moveUp=\u5411\u4e0a\u79fb\u52a8\uff08&U\uff09 Button.moveDown=\u5411\u4e0b\u79fb\u52a8\uff08&D\uff09 ConfigView.notAvailableForMode=\u8fd9\u4e2a\u90e8\u5206\u662f\u63d0\u4f9b\u7ed9 %1 \u6a21\u5f0f\u4f7f\u7528\u7684\uff0c\u5728 %2 \u6a21\u5f0f\u4e2d\u65e0\u6548\u3002 health.explain.error=\u8be5 Torrent \u6709\u9519\u8bef\u3002\u53c2\u89c1\u72b6\u6001\u5217\uff0c\u6216\u662f\u56fe\u6807\u4e0a\u7684\u5e2e\u52a9\u63d0\u793a\u4ee5\u4e86\u89e3\u9519\u8bef\u4fe1\u606f\u3002 GeneralView.label.trackerscrapeupdate=\u67e5\u8be2 Tracker PeersView.piece=\u533a\u5757 PeersView.piece.info=\u4ece\u8be5\u7528\u6237\u6700\u540e\u8bf7\u6c42\u7684\u533a\u5757\u6570 PiecesView.priority=\u4f18\u5148\u7ea7 PiecesView.priority.info=\u8be5\u533a\u5757\u7684\u5b8c\u6210\u4f18\u5148\u7ea7\uff0c\u4f46\u662f\u522b\u592a\u5728\u610f\u8fd9\u4e00\u4fe1\u606f PiecesView.speed=\u901f\u5ea6 PiecesView.speed.info=\u4f4e\u901f\u7528\u6237\u88ab\u963b\u6b62\u5e72\u6d89\u5feb\u901f\u533a\u5757\u7684\u5b8c\u6210 TableColumn.header.AvgAvail.info=\u533a\u5757\u53ef\u7528\u6027\u603b\u6570\u9664\u4ee5\u533a\u5757\u6570\uff0c\u9664\u4ee5\u8fde\u63a5\u6570 TableColumn.header.AvgAvail=\u5e73\u5747\u53ef\u7528\u6027/\u533a\u5757 ConfigView.label.strictfilelocking=\u5f3a\u5236\u8de8 Torrent \u6587\u4ef6\u72ec\u5360\u6587\u4ef6\u5199\u6743\u9650\u9501 MyTorrentsView.menu.checkfilesexist=\u68c0\u67e5\u6587\u4ef6\u5b58\u5728 MyTorrentsView.menu.rescanfile=\u5468\u671f\u6027\u91cd\u65b0\u68c0\u67e5\u672a\u5b8c\u6210\u7684\u533a\u5757 MyTorrentsView.menu.clear_resume_data=\u6e05\u9664\u7eed\u4f20\u6570\u636e Plugin.extseed.name=\u5916\u90e8\u79cd\u5b50 Plugin.localtracker.name=\u5c40\u57df\u7f51\u7528\u6237\u67e5\u627e\u5668 Plugin.localtracker.info=\u5c40\u57df\u7f51\u7528\u6237\u67e5\u627e\u5668\u5141\u8bb8\u540c\u4e00\u9632\u706b\u5899\u540e\u6216\u662f\u67d0\u4e2a\u666e\u901a\u7f51\u7edc\u4e2d\u7684\u591a\u4e2a Vuze n\u901a\u8fc7\u542f\u7528\u5b83\u4eec\u4e4b\u95f4\u7684\u76f4\u63a5\u8fde\u63a5\uff0c\u6765\u9ad8\u6548\u4e0b\u8f7d Torrent \u6587\u4ef6 Plugin.localtracker.enable=\u542f\u7528\u5c40\u57df\u7f51\u7528\u6237\u67e5\u627e\u5668 azinstancehandler.alert.portclash=\u5c40\u57df\u7f51\u4e2d\u4fa6\u6d4b\u5230\u7aef\u53e3\u51b2\u7a81\uff1a%1 \u5df2\u7ecf\u88ab\u53e6\u4e00\u4e2a Vuze \u7528\u6237\u4f7f\u7528\uff0c\u8bf7\u9009\u62e9\u4e00\u4e2a\u65b0\u7684\u968f\u673a\u7aef\u53e3\uff0c\u7528\u6765\u76d1\u542c\u4f20\u5165\u7684 TCP / UDP \u8fde\u63a5\uff3b\u5728 %2 \u5230 %3 \u4e4b\u95f4\uff3d\u3002 ConfigView.section.transfer.lan=\u5c40\u57df\u7f51 ConfigView.section.transfer.lan.tooltip=\u5c40\u57df\u7f51\u4e13\u95e8\u7684\u8bbe\u7f6e ConfigView.section.transfer.lan.uploadrate=\u5c40\u57df\u7f51\u6700\u5927\u4e0a\u4f20\u901f\u5ea6\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.section.transfer.lan.uploadrate.tooltip=\u5728\u540c\u4e00\u4e2a\u5c40\u57df\u7f51\u7edc\u4e2d\u7684\u7528\u6237\u8fde\u63a5\u53ef\u4ee5\u6709\u4e00\u4e2a\u5355\u72ec\u7684\u4e0a\u4f20\u901f\u5ea6\u9650\u5236\u3002 ConfigView.section.transfer.lan.downloadrate=\u5c40\u57df\u7f51\u6700\u5927\u4e0b\u8f7d\u901f\u5ea6\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.section.transfer.lan.downloadrate.tooltip=\u5728\u540c\u4e00\u4e2a\u5c40\u57df\u7f51\u7edc\u4e2d\u7684\u7528\u6237\u8fde\u63a5\u53ef\u4ee5\u6709\u4e00\u4e2a\u5355\u72ec\u7684\u4e0b\u8f7d\u901f\u5ea6\u9650\u5236\u3002 TorrentOptionsView.title.short=\u9009\u9879 TorrentOptionsView.title.full=\u9009\u9879 TorrentOptionsView.param.max.peers=\u6700\u5927\u8fde\u63a5\u6570\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.section.connection.encryption.require_encrypted_transport=\u542f\u7528\u534f\u8bae\u52a0\u5bc6 ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=\u5f3a\u5236\u7528\u6237\u4f7f\u7528\u52a0\u5bc6\u8fde\u63a5 ConfigView.section.connection.encryption.min_encryption_level=\u52a0\u5bc6\u7ea7\u522b ConfigView.section.connection.encryption.min_encryption_level.tooltip=Plain - \u4ec5\u52a0\u5bc6\u63e1\u624b\u90e8\u5206\nRC4 - \u52a0\u5bc6\u5168\u90e8\u6570\u636e\u6d41\n\u9ad8\u7ea7\u52a0\u5bc6\u9700\u8981\u66f4\u591a\u7684 CPU \u8d44\u6e90\u3002 Peers.column.Encryption=\u52a0\u5bc6 Peers.column.Encryption.info=\u4f7f\u7528\u7684\u52a0\u5bc6\u7ea7\u522b ConfigView.section.connection.encryption.encrypt.info=\u542f\u7528\u52a0\u5bc6\u540e\uff0c\u5fc5\u987b\u542f\u7528\u517c\u5bb9\u9009\u9879\u624d\u80fd\u591f\u8fde\u63a5\u5230\u4e0d\u652f\u6301\u52a0\u5bc6\u7684\u5ba2\u6237\u7aef ConfigView.section.connection.encryption.encrypt.info.link=\u8bf7\u70b9\u51fb\u8fd9\u91cc\u4e86\u89e3\u8be6\u7ec6\u4fe1\u606f MainWindow.sr.status.tooltip.ok=\u5206\u4eab\u7387 %1 \u8f83\u597d MainWindow.sr.status.tooltip.poor=\u5206\u4eab\u7387 %1 \u4e00\u822c\uff1a < 0.9 MainWindow.sr.status.tooltip.bad=\u5206\u4eab\u7387 %1 \u8f83\u5dee\uff1a < 0.5 ConfigView.section.style.status=\u72b6\u6001\u533a\u57df\uff1a ConfigView.section.style.status.show_sr=\u5206\u4eab\u7387 ConfigView.section.style.status.show_nat=NAT \u72b6\u6001 ConfigView.section.style.status.show_ddb=DDB \u72b6\u6001 ConfigView.section.style.status.show_ipf=IP \u8fc7\u6ee4\u4fe1\u606f ConfigView.section.connection.encryption.encrypt.group=\u534f\u8bae\u52a0\u5bc6 ConfigView.section.connection.encryption.encrypt.fallback_info=\u542f\u7528\u4e0b\u9762\u7684\u67d0\u4e2a\u9009\u9879\u540e\uff0c\u53ef\u4ee5\u8fde\u63a5\u5230\u4e0d\u517c\u5bb9\u52a0\u5bc6\u534f\u8bae\u7684\u5ba2\u6237\u7aef\u3002 ConfigView.section.connection.encryption.encrypt.fallback_outgoing=\u5bf9\u5916\u8fde\u63a5\u4f7f\u7528\u534f\u8bae\u52a0\u5bc6\u5931\u8d25\u65f6\uff0c\u5141\u8bb8\u65e7\u5f0f\u8fde\u63a5 ConfigView.section.connection.encryption.encrypt.fallback_incoming=\u5141\u8bb8\u4f20\u5165\u65e7\u5f0f\u8fde\u63a5 ConfigView.section.connection.encryption=\u534f\u8bae\u52a0\u5bc6 upnp.selectedinterfaces=\u9009\u62e9\u7f51\u5361\uff08\u7528 \u201c\uff1b\u201d \u5206\u9694\uff0c\u4f8b\u5982 eth0\uff1beth1\uff09\uff3b\u7559\u7a7a\uff1a\u5168\u90e8\uff3d ConfigView.section.style.defaultSortOrder=\u9ed8\u8ba4\u6392\u5217\u987a\u5e8f ConfigView.section.style.defaultSortOrder.desc=\u9012\u51cf ConfigView.section.style.defaultSortOrder.asc=\u9012\u589e ConfigView.section.style.defaultSortOrder.flip=\u76f8\u53cd\u987a\u5e8f LoggerView.autoscroll=\u81ea\u52a8\u6eda\u52a8 Button.selectAll=\u5168\u9009 Button.markSelected=\u5c06\u9009\u62e9\u5185\u5bb9\u8bbe\u7f6e\u4e3a\u4e0b\u8f7d Button.unmarkSelected=\u5c06\u9009\u62e9\u5185\u5bb9\u8bbe\u7f6e\u4e3a\u4e0d\u4e0b\u8f7d plugins.basicview.config=\u914d\u7f6e TorrentOptionsView.param.max.uploads=\u4e0a\u4f20\u901a\u9053\u6570\uff3b\u6700\u5c0f\uff1a 2\uff3d MyTorrentsView.dialog.setPosition.title=\u8bbe\u7f6e\u4f4d\u7f6e MyTorrentsView.dialog.setPosition.text=\u8f93\u5165\u9009\u62e9\u7684 Torrent \u4fdd\u5b58\u5230\u7684\u4f4d\u7f6e\uff1a MyTorrentsView.menu.reposition.manual=\u91cd\u65b0\u914d\u7f6e.. ConfigView.section.connection.advanced.info.link=\u8bf7\u70b9\u51fb\u8fd9\u91cc\u4e86\u89e3\u8be6\u7ec6\u4fe1\u606f ConfigView.section.connection.advanced.socket.group=Socket \u9009\u9879 ConfigView.section.connection.advanced.bind_port=\u7ed1\u5b9a\u5230\u672c\u5730\u7aef\u53e3\uff3b0\uff1a\u7981\u7528\uff3d ConfigView.section.connection.advanced.bind_port.tooltip=\u5bf9\u5916 socket \u8fde\u63a5\u5c06\u88ab\u672c\u5730\u7ed1\u5b9a\u5230\u6307\u5b9a\u7aef\u53e3\u3002\n\u542f\u7528\u8be5\u529f\u80fd\u53ef\u4ee5\u5e2e\u52a9\u89e3\u51b3 NAT \u8def\u7531\u7684\u4e0d\u7a33\u5b9a\u95ee\u9898\u3002 ConfigView.section.proxy.group.tracker=Tracker \u901a\u8baf ConfigView.section.proxy.group.peer=\u7528\u6237\u901a\u8baf Pieces.column.Requested=\u5df2\u8bf7\u6c42 Pieces.column.Requested.info=\u663e\u793a\u5bf9\u8be5\u533a\u5757\u662f\u5426\u80fd\u591f\u53d1\u51fa\u66f4\u591a\u7684\u8bf7\u6c42\uff08*\uff09 ConfigView.label.maxuploadsseeding=\u505a\u79cd\u65f6\uff0c\u66ff\u4ee3\u503c MyTorrentsView.filter=\u8fc7\u6ee4\u5668\uff1a popup.error.hideall=\u9690\u85cf\u5168\u90e8 ConfigView.section.style.dataStatsOnly=\u4ec5\u663e\u793a\u6570\u636e\u7edf\u8ba1\uff08\u9690\u85cf\u534f\u8bae\u7edf\u8ba1\uff09 ConfigView.section.style.separateProtDataStats=\u6570\u636e\u548c\u534f\u8bae\u7edf\u8ba1\u4fe1\u606f\u5206\u5f00\u663e\u793a\u4e3a\u201c\u6570\u636e\uff08\u534f\u8bae\uff09\u201d MyTorrentsView.dialog.setFilter.title=\u4fee\u6539\u8fc7\u6ee4\u5668 MyTorrentsView.dialog.setFilter.text=%1 \u90e8\u5206\u5c06\u88ab\u60a8\u5728\u4e0b\u9762\u6307\u5b9a\u7684\u6587\u672c\u8fc7\u6ee4\u3002\u4f7f\u7528 |\uff08\u7ba1\u9053\uff09 \u7b26\u53f7\u4ee5\u8fc7\u6ee4\u591a\u4e2a\u77ed\u8bed\u3002 MyTorrentsView.filter.tooltip=\u4f7f\u7528 Ctrl+X \u5728 RegEx \u548c\u666e\u901a\u641c\u7d22\u6a21\u5f0f\u4e2d\u5207\u6362\u3002\n\u4f7f\u7528 |\uff08\u7ba1\u9053\uff09 \u7b26\u53f7\u8fc7\u6ee4\u591a\u4e2a\u77ed\u8bed\u3002 MyTorrentsView.clearFilter.tooltip=\u6e05\u9664\u8fc7\u6ee4\u5668 MyTorrentsView.menu.filter=\u8fc7\u6ee4\u5217\u8868\u2026 ConfigView.section.file.resume.recheck.all=\u4ece\u5d29\u6e83\u4e2d\u6062\u590d\u65f6\u91cd\u65b0\u68c0\u67e5\u6574\u4e2a\u6587\u4ef6\u7684\u5b8c\u6574\u6027\uff08\u5982\u4e0d\u542f\u7528\uff0c\u5219\u4ec5\u68c0\u67e5\u6700\u540e\u4fdd\u5b58\u65f6\u6b63\u5728\u5904\u7406\u7684\u533a\u5757\uff09 ConfigureWizard.language.choose=\u4ece\u4e0b\u9762\u7684\u5217\u8868\u4e2d\u9009\u62e9\u4e00\u4e2a\u8bed\u8a00\uff1a popup.closing.in=%1 \u79d2\u540e\u81ea\u52a8\u5173\u95ed\u7a97\u53e3 popup.more.waiting=%1 \u4e2a\u66f4\u591a\u7684\u6d88\u606f.. # > 2402 popup.download.finished="%1" \u5df2\u7ecf\u5b8c\u6210\u4e0b\u8f7d. popup.file.finished="%1" \u5b8c\u6210\u4e0b\u8f7d. ConfigView.auto=\u81ea\u52a8 Plugin.localtracker.autoadd.info=\u81ea\u52a8\u6dfb\u52a0\u8fd9\u4e9b\u672c\u5730\u7528\u6237\uff3b\u201c\uff1b\u201d\u5206\u9694\u7684\u5730\u5740\uff0c\u4f8b\u5982 1.2.3.4\uff3d Plugin.localtracker.autoadd=\u5916\u90e8\u7528\u6237 Plugin.localtracker.networks.info=\u5982\u4e0b\u7684\u7f51\u7edc\u4e3a\u672c\u5730\u7f51\u7edc\uff3b\u201c\uff1b\u201d \u5206\u9694\u7f51\u7edc\uff0c\u4f8b\u5982 145.227.*.*\uff3d Plugin.localtracker.networks=\u672c\u5730\u7f51\u7edc MainWindow.menu.view.plugins.logViews=\u65e5\u5fd7\u67e5\u770b SpeedView.stats.autospeed=\u81ea\u52a8\u4e0a\u4f20\u901f\u5ea6 SpeedView.stats.autospeed.disabled=\u6b64\u529f\u80fd\u88ab\u7981\u7528\uff08DHT \u5fc5\u987b\u542f\u7528\uff09\uff0c\u6216\u662f\u672a\u4f7f\u7528\uff08\u9009\u7528\u4e86\u624b\u52a8\u8bbe\u7f6e\uff09\u3002 SpeedView.stats.idlePing=\u7a7a\u95f2 Ping\uff1a SpeedView.stats.maxPing=\u6700\u5927 Ping\uff1a SpeedView.stats.currentPing=\u5f53\u524d Ping\uff1a SpeedView.stats.maxUp=\u6700\u5927\u4e0a\u4f20\u901f\u5ea6\uff1a ConfigView.pluginlist.unloadSelected=\u5378\u8f7d\u9009\u5b9a ConfigView.pluginlist.scan=\u626b\u63cf\u65b0\u63d2\u4ef6 ConfigView.section.transfer.autospeed=\u81ea\u52a8\u8c03\u8282\u901f\u5ea6 ConfigView.section.transfer.autospeed.tooltip=\u81ea\u52a8\u8c03\u8282\u901f\u5ea6\u53c2\u6570\u8bbe\u7f6e ConfigView.section.transfer.autospeed.info=\u81ea\u52a8\u8c03\u8282\u901f\u5ea6\u6a21\u5f0f\u4f1a\u81ea\u52a8\u8c03\u8282\u4e0a\u4f20\u901f\u5ea6\u4ee5\u907f\u514d\u7f51\u7edc\u8fc7\u8f7d\u3002\n\n\u4ec5\u5728\u81ea\u52a8\u4e0a\u4f20\u901f\u5ea6\u4ee5\u53ca DHT \u542f\u7528\u540e\u8fd9\u4e9b\u9650\u5236\u624d\u4f1a\u751f\u6548\u3002\n ConfigView.section.transfer.autospeed.minupload=%1 \u6700\u5c0f\u4e0a\u4f20\u901f\u5ea6 ConfigView.section.transfer.autospeed.minupload.tooltip=\u4e0a\u4f20\u901f\u5ea6\u4e0d\u4f1a\u81ea\u52a8\u4f4e\u4e8e\u8fd9\u4e2a\u503c ConfigView.section.transfer.autospeed.maxupload=%1 \u6700\u5927\u4e0a\u4f20\u901f\u5ea6\uff3b0\uff1a\u65e0\u9650\u5236\uff3d ConfigView.section.transfer.autospeed.maxupload.tooltip=\u4e0a\u4f20\u901f\u5ea6\u4e0d\u4f1a\u81ea\u52a8\u8d85\u8fc7\u8fd9\u4e2a\u503c ConfigView.section.transfer.autospeed.chokeping=\u963b\u585e ping \u503c\uff3b\u6beb\u79d2\uff3d ConfigView.section.transfer.autospeed.chokeping.tooltip=Ping \u503c\u8d85\u8fc7\u8fd9\u4e2a\u6570\u503c\u5c06\u88ab\u8ba4\u4e3a\u662f\u7f51\u7edc\u9971\u548c ConfigView.section.transfer.autospeed.enableauto=\u4e0b\u8f7d\u4e0e\u505a\u79cd\u65f6\u542f\u7528 ConfigView.section.transfer.autospeed.enableautoseeding=\u4ec5\u5728\u505a\u79cd\u65f6\u542f\u7528 ConfigView.pluginlist.column.unloadable=\u53ef\u5378\u8f7d ConfigView.section.transfer.lan.enable=\u542f\u7528 LAN \u591a\u4e2a\u901f\u5ea6\u9650\u5236 Plugin.localtracker.wellknownlocals=\u81ea\u52a8\u5305\u542b\u5404\u79cd\u672c\u5730\u5185\u7f51\uff08192.168 etc\uff09 TableColumn.header.filesdone=\u5df2\u5b8c\u6210\u7684\u6587\u4ef6 TableColumn.header.filesdone.info=\u5df2\u5b8c\u6210/\u603b\u5171 *or* \u5b8c\u6210\u9009\u62e9\u90e8\u5206\uff08\u5df2\u5b8c\u6210\uff09/\u6240\u6709\u9009\u62e9\u90e8\u5206\uff08\u603b\u5171\uff09 MagnetPlugin.private_torrent=<\u79c1\u4e0b\u7684 Torrent> MagnetPlugin.decentral_disabled=<\u5206\u5e03\u5f0f\u8ddf\u8e2a\u5df2\u5173\u95ed> MagnetPlugin.decentral_backup_disabled=<\u5206\u5e03\u5f0f\u5907\u4efd\u5df2\u5173\u95ed> MagnetPlugin.report.waiting_ddb=\u7b49\u5f85 DDB \u521d\u59cb\u5316\u2026 MagnetPlugin.report.searching=\u5bfb\u627e\u2026 MagnetPlugin.report.found=\u53d1\u73b0 %1 MagnetPlugin.report.alive=%1 \u6d3b\u8dc3 MagnetPlugin.report.dead=%1 \u65e0\u6548 MagnetPlugin.report.tunnel=\u8f6c\u5165\u96a7\u9053 %1 MagnetPlugin.report.downloading=\u4ece %1 \u4e0b\u8f7d MagnetPlugin.report.error=\u9519\u8bef %1 MagnetURLHandler.report.no_sources=\u6ca1\u6709\u627e\u5230 Torrent \u6765\u6e90 MagnetURLHandler.report.torrent_size=Torrent \u5927\u5c0f\uff1a %1 MagnetURLHandler.report.percent=\u5df2\u5b8c\u6210\uff1a %1% MagnetURLHandler.report.error=\u9519\u8bef %1 DHTTransport.report.request_all=\u5411 %1 \u8bf7\u6c42\u5b8c\u6574\u4f20\u8f93 DHTTransport.report.received_bit=\u4ece %3\u83b7\u53d6 %1\u81f3 %2 DHTTransport.report.complete=\u5b8c\u6210 DHTTransport.report.timeout=\u8d85\u65f6\uff0c\u6ca1\u6709 %1 \u7684\u56de\u5e94 DHTTransport.report.rerequest_all=\u5411 %1 \u91cd\u65b0\u8bf7\u6c42\u5b8c\u6574\u4f20\u8f93 DHTTransport.report.rerequest_bit=\u5411 %3\u91cd\u8bf7\u6c42 %1 \u81f3 %2 DHTTransport.report.timeout_some=\u8d85\u65f6\uff0c %1 \u6570\u636e\u5305\u4ece %2 \u83b7\u53d6\u4f46\u4e0d\u5b8c\u6574 DHTTransport.report.sending=\u6b63\u5728\u53d1\u9001\u6570\u636e DHTTransport.report.resending=\u6b63\u5728\u91cd\u53d1\u6570\u636e DHTTransport.report.send_complete=\u53d1\u9001\u6210\u529f DHTTransport.report.send_timeout=\u53d1\u9001\u8d85\u65f6 ConfigView.section.transfer.autospeed.enabledebug=\u8bb0\u5f55 Debug \u4fe1\u606f TableColumn.header.date_added=\u52a0\u5165\u65e5\u671f TableColumn.header.date_added.info=\u8be5\u79cd\u5b50\u88ab\u52a0\u5165\u7684\u65e5\u671f ConfigView.section.file.hashchecking.smallestfirst=\u9996\u5148 Hash \u6700\u5c0f\u533a\u5757 platform.win32.baddll.info=Vuze \u68c0\u6d4b\u5230 "%1" \u7684\u5b58\u5728. \u8fd9\u662f "%2" \u7684\u4e00\u90e8\u5206\u5e76\u4e14\u5df2\u77e5\u4f1a\u5bfc\u81f4\u4e00\u4e9b\u95ee\u9898\u6bd4\u5982\u7a0b\u5e8f\u5d29\u6e83\u4ee5\u53ca\u9ad8 CPU \u5360\u7528\u7387\u3002\u5982\u679c\u4f60\u9047\u5230\u8fd9\u4e9b\u95ee\u9898\u8bf7\u5378\u8f7d\u8fd9\u4e9b\u8f6f\u4ef6\u6216\u8005\u8bbe\u7f6e\u8fd9\u4e9b\u8f6f\u4ef6\u4e0d\u5e72\u6270 Vuze u3002 upnp.ignorebaddevices=\u5ffd\u7565\u6ca1\u6709\u6b63\u786e\u54cd\u5e94\u7684\u8bbe\u5907 upnp.ignorebaddevices.info=\u5f53\u524d\u88ab\u5ffd\u7565\u7684\u8bbe\u5907\uff1a %1 upnp.ignorebaddevices.reset=\u91cd\u7f6e\u5ffd\u7565\u8bbe\u5907\u5217\u8868 upnp.ignorebaddevices.reset.action=\u91cd\u7f6e upnp.ignorebaddevices.alert=\u4f4d\u4e8e %1 \u7684 UPNP \u8bbe\u5907\u56e0\u91cd\u590d\u9519\u8bef\u800c\u88ab\u5ffd\u7565\u3002\u8bf7\u67e5\u770b UPNP \u63d2\u4ef6\u8bbe\u7f6e\u3002 TorrentOptionsView.param.max.uploads.when.busy=KB/s \u5168\u5c40\u4e0a\u4f20\u901f\u5ea6\u5230\u8fbe\u4e0a\u9650\u65f6\u6700\u5927\u4e0a\u4f20\u901f\u5ea6\uff3b0\uff1a\u7981\u7528\uff3d UpdateMonitor.messagebox.verification.failed.title=\u5b89\u88c5\u68c0\u67e5\u5931\u8d25 UpdateMonitor.messagebox.verification.failed.text="%1" \u7684\u68c0\u67e5\u5931\u8d25\uff1a %2 UpdateMonitor.messagebox.accept.unverified.title=\u63a5\u53d7\u5df2\u786e\u8ba4\u7684\u5b89\u88c5 UpdateMonitor.messagebox.accept.unverified.text="%1" \u4e0d\u662f Vuze \u63d2\u4ef6\u3002\nIf \u4f60\u80fd\u4f7f\u7528\u8fd9\u4e2a\u63d2\u4ef6\u3002\n\u7ee7\u7eed\u5b89\u88c5\u5417\uff1f FileView.BlockView.title=\u533a\u5757 FileView.BlockView.Done=\u5df2\u5b8c\u6210 FileView.BlockView.Skipped=\u5ffd\u7565\u7684 FileView.BlockView.Active=\u5f53\u524d\u8fdb\u884c\u4e2d FileView.BlockView.Outstanding=\u5c1a\u672a\u5b8c\u6210 ConfigView.label.tcplistenport=\u4f20\u5165 TCP \u8fde\u63a5\u7684\u76d1\u542c\u7aef\u53e3 ConfigView.label.udplistenport=UDP \u8fde\u63a5\u7684\u76d1\u542c\u7aef\u53e3 upnp.portchange.alert=\u4e3a\u4e86\u907f\u514d UPNP \u8bbe\u5907\u6545\u969c\uff0c\u4ee5\u4e0b\u7aef\u53e3\u5df2\u7ecf\u88ab\u66f4\u6539\uff1a %1\uff3bold port=%2\uff3d %3\uff3bold port=%4\uff3d ConfigView.section.proxy.username.info=\u5982\u679c\u4ee3\u7406\u670d\u52a1\u5668\u8981\u6c42\u9a8c\u8bc1\uff0c\u5e76\u4e14\u7528\u6237\u540d none \u53ef\u7528\uff0c\u4f7f\u7528 \u4f5c\u4e3a\u7528\u6237\u540d ConfigView.label.maxuploadswhenbusymin=\u4efb\u52a1\u7e41\u5fd9\u65f6\u5355\u4efb\u52a1\u5168\u901f\u4e0a\u4f20\u65f6\u95f4\uff3b\u79d2\uff3d MainWindow.menu.help.debug=\u751f\u6210 Debug \u4fe1\u606f DownloadManager.error.badsize=\u6587\u4ef6\u5927\u5c0f\u9519\u8bef natpmp.info=NAT-PMP \u662f\u82f9\u679c\u673a\u4e0a UPnP \u7684\u66ff\u4ee3\u534f\u8bae\uff0c\u76ee\u524d Airport stations \u5df2\u7ecf\u652f\u6301\u8be5\u534f\u8bae\n\n\u6ce8\u610f UPnP \u5fc5\u987b\u542f\u7528\u540e\u624d\u80fd\u542f\u7528 NAT-PMP\uff0c\u56e0\u4e3a NAT-PMP \u8bbe\u5907\u88ab\u5f53\u4f5c\u4e00\u79cd\u7279\u522b\u7684 UPnP \u8bbe\u5907 natpmp.enable=\u542f\u7528\uff08\u6ce8\u610f\u5fc5\u987b\u5728 Airport \u8bbe\u7f6e\u4e2d\u542f\u7528\u624d\u80fd\u6b63\u5e38\u4f7f\u7528\uff09 ConfigView.section.tracker.host.addurls=\u4fdd\u8bc1\u8fd9\u4e2a Tracker \u7684\u8fde\u63a5\u4f4d\u4e8e\u5750\u5e84\u79cd\u5b50\u4e2d ConfigView.filter=\u8f93\u5165\u8fc7\u6ee4\u6587\u672c ConfigView.section.files.move=\u5b8c\u6210\u4efb\u52a1\u79fb\u52a8 ConfigView.section.file.defaultdir.section=\u9ed8\u8ba4\u76ee\u5f55\u9009\u9879 ConfigView.section.file.defaultdir.auto=\u4e0d\u786e\u8ba4\uff0c\u76f4\u63a5\u4e0b\u8f7d\u5230\u9ed8\u8ba4\u76ee\u5f55 ConfigView.section.file.defaultdir.bestguess=\u9009\u62e9\u9ed8\u8ba4\u4e0b\u8f7d\u76ee\u5f55\u65f6\u5206\u6790\u6700\u5408\u7406\u7684\u72b6\u51b5 ConfigView.section.file.defaultdir.ask=\u9ed8\u8ba4\u76ee\u5f55\uff1a ConfigView.section.file.defaultdir.lastused=\u81ea\u52a8\u66f4\u65b0\u9ed8\u8ba4\u4e0b\u8f7d\u76ee\u5f55 ConfigView.section.file.config.section=\u8bbe\u7f6e ConfigView.section.file.config.currentdir=\u5f53\u524d\u8bbe\u7f6e\u76ee\u5f55\uff1a ConfigView.section.torrent.decoding=\u7f16\u7801\u8bbe\u7f6e ConfigView.section.logging.udptransport=\u542f\u7528 verbose UDP \u4f20\u8f93\u8ddf\u8e2a Tracker.announce.ignorePeerSeed=\u5ffd\u7565 \u7528\u6237/\u79cd\u5b50 \u503c. %1 ConfigView.section.connection.encryption.use_crypto_port=\u4f7f\u7528 cryptoport \u6a21\u5f0f Tracker \u6269\u5c55\u4ee5\u4fbf\u963b\u6b62 Plain \u6a21\u5f0f\u4f20\u5165\u7684\u5c1d\u8bd5\u8fde\u63a5 TorrentOptionsView.param.reset.to.default=\u5c06\u9009\u9879\u91cd\u7f6e\u4e3a\u9ed8\u8ba4\u503c TorrentOptionsView.param.reset.button=\u91cd\u7f6e natpmp.routeraddress=Station \u5730\u5740\uff3b\u7559\u7a7a\uff1a\u81ea\u52a8\uff3d ConfigView.section.style.disableAlertSliding=\u7981\u7528\u63d0\u793a\u6d88\u606f\u7684\u52a8\u753b\u6a21\u5f0f ConfigView.section.transfer.autospeed.maxinc=%1 \u6bcf\u5468\u671f\u6700\u5927\u589e\u52a0 ConfigView.section.transfer.autospeed.maxdec=%1 \u6bcf\u5468\u671f\u6700\u5927\u51cf\u5c11 ConfigView.section.transfer.autospeed.enabledownadj=\u542f\u7528\u4e0b\u8f7d\u901f\u5ea6\u8c03\u8282 ConfigView.section.transfer.autospeed.downadjratio=\u4e0b\u8f7d\uff1a\u4e0a\u4f20\uff08\u4e0a\u9650\uff09 ConfigView.section.transfer.autospeed.latencyfactor=\u901f\u5ea6\u6f5c\u4f0f\u53d8\u5316\u5173\u8054\u56e0\u7d20\uff08\u8fc7\u5927\u7684\u6570\u5b57\u5c06\u51cf\u5c11\u7075\u654f\u5ea6\uff09 ConfigView.section.transfer.autospeed.reset=\u91cd\u7f6e\u9ad8\u7ea7\u8bbe\u7f6e\u6570\u503c ConfigView.section.transfer.autospeed.reset.button=\u91cd\u7f6e PeerColumn.activationCount=\u7528\u6237\u6b63\u5728\u5c1d\u8bd5\u8fde\u63a5\uff1a %1 TableColumn.header.timesincedownload.info=Torrent \u4e0b\u8f7d\u5df2\u7ecf\u8fc7\u7684\u65f6\u95f4 TableColumn.header.timesincedownload=\u4e0b\u8f7d\u95f2\u7f6e TableColumn.header.timesinceupload.info=Torrent \u4e0a\u4f20\u5df2\u7ecf\u8fc7\u7684\u65f6\u95f4 TableColumn.header.timesinceupload=\u4e0a\u4f20\u95f2\u7f6e PeersView.incomingreqcount=\u4f20\u5165\u8bf7\u6c42\u6570 PeersView.incomingreqcount.info=\u8ba1\u7b97\u4f20\u5165\u8bf7\u6c42\u6570 PeersView.outgoingreqcount=\u5bf9\u5916\u8bf7\u6c42\u6570 PeersView.outgoingreqcount.info=\u8ba1\u7b97\u5bf9\u5916\u8bf7\u6c42\u6570 upnp.mapping.trackerclientudp=UDP Tracker \u5ba2\u6237\u7aef\u7aef\u53e3 upnp.mapping.dhtudp=\u5206\u5e03\u5f0f\u6570\u636e\u5e93 ConfigView.section.connection.nondata.udp.same=DHT \u4e0e UDP Tracker \u4f7f\u7528\u76f8\u540c\u7684 UDP \u7aef\u53e3\u53f7 ConfigView.section.connection.tcp.enable=\u542f\u7528 TCP ConfigView.section.connection.udp.enable=\u542f\u7528 UDP ConfigView.section.style.showiconbar=\u663e\u793a\u5de5\u5177\u6761 MainWindow.menu.view.iconbar=\u5de5\u5177\u6761 MyTorrentsView.menu.rename=\u91cd\u547d\u540d MyTorrentsView.menu.rename.displayed=\u91cd\u547d\u540d\u663e\u793a\u540d\u79f0 MyTorrentsView.menu.rename.save_path=\u91cd\u547d\u540d\u4fdd\u5b58\u76ee\u5f55 MyTorrentsView.menu.rename.displayed.enter.title=\u91cd\u547d\u540d\u663e\u793a\u540d\u79f0 MyTorrentsView.menu.rename.displayed.enter.message=\u4e3a\u8be5\u4e0b\u8f7d\u8f93\u5165\u4e00\u4e2a\u65b0\u7684\u663e\u793a\u540d\u79f0\u3002\n\u5982\u679c\u6ca1\u6709\u8f93\u5165\u6587\u672c\uff0c\u5c06\u4f7f\u7528\u539f\u59cb\u540d\u79f0\u3002 MyTorrentsView.menu.edit_comment=\u7f16\u8f91\u8bc4\u8bba MyTorrentsView.menu.edit_comment.enter.title=\u7f16\u8f91\u8bc4\u8bba MyTorrentsView.menu.edit_comment.enter.message=\u4e3a\u8be5\u4e0b\u8f7d\u8f93\u5165\u4e00\u4e2a\u8bc4\u8bba\u3002 UIDebugGenerator.messageask.title=Debug \u751f\u6210 UIDebugGenerator.messageask.text=\u8bf7\u63cf\u8ff0\u4f60\u8981\u62a5\u544a\u7684 BUG UIDebugGenerator.complete.title=\u751f\u6210 Debug \u6210\u529f UIDebugGenerator.complete.text=\u8bf7\u53d1\u9001\u6587\u4ef6 "%1".\n\n\u70b9\u51fb Ok \u4ee5\u6d4f\u89c8\u8be5\u6587\u4ef6. ConfigView.section.style.showProgramIcon=\u5728\u540d\u79f0\u5217\u4e2d\u663e\u793a\u7a0b\u5e8f\u56fe\u6807 ConfigView.section.style.showProgramIcon.tooltip=\u89c6\u56fe\u9700\u8981\u91cd\u542f\u4ee5\u4fbf\u751f\u6548 swt.alert.cant.update=\u4ece "%3" \u8f7d\u5165\u7684 SWT \u8fd0\u884c\u5e93\u4e0d\u80fd\u5b9e\u73b0\u7248\u672c %1 \u81f3 %2 \u7684\u81ea\u52a8\u66f4\u65b0\uff08\u5fc5\u987b\u4ece "%4"\u8f7d\u5165\uff09\u3002\u8bf7\u6d4f\u89c8 the wiki \u67e5\u770b\u8be6\u7ec6\u5185\u5bb9\u3002 authenticator.savepassword=\u8bb0\u4f4f\u6211\u7684\u5bc6\u7801 ConfigView.section.security.clearpasswords=\u91cd\u7f6e\u5df2\u8bb0\u4f4f\u7684\u5bc6\u7801 ConfigView.section.security.clearpasswords.button=\u91cd\u7f6e Content.alert.notuploaded.title=\u4e0a\u4f20\u6ca1\u6709\u5b8c\u6210 Content.alert.notuploaded.text="%1" \u7684\u4e0a\u4f20\u6ca1\u6709\u5b8c\u6210\u3002 \u5982\u679c\u4f60\u73b0\u5728 %2 \uff0c\u522b\u4eba\u5c31\u4e0d\u80fd\u4e0b\u8f7d\u5230\u4f60\u8981\u53d1\u5e03\u7684\u4e1c\u897f\u3002\n\n\u4f60\u786e\u8ba4\u8981 %2\u5417\uff1f Content.alert.notuploaded.multi.title=\u4e0a\u4f20\u6ca1\u6709\u5b8c\u6210 Content.alert.notuploaded.multi.text=%1 \u4f60\u53d1\u5e03\u7684\u5185\u5bb9\u6ca1\u6709\u5b8c\u5168\u4f20\u51fa. \u5982\u679c\u4f60\u73b0\u5728 %2 \uff0c\u522b\u4eba\u5c31\u4e0d\u80fd\u4e0b\u8f7d\u5230\u4f60\u8981\u53d1\u5e03\u7684\u4e1c\u897f\u3002 \u4f60\u786e\u8ba4\u8981 %2\u5417\uff1f\n\n\u5185\u5bb9\u6ca1\u6709\u5b8c\u5168\u4f20\u51fa\uff1a\n%3 Content.alert.notuploaded.stop=\u505c\u6b62 Content.alert.notuploaded.quit=\u9000\u51fa Vuze TorrentInfoView.torrent.encoding=Torrent \u7f16\u7801 TorrentInfoView.columns="\u6211\u7684 Torrents" \u9875\u9762\u4e2d\u7684\u680f\u76ee progress.window.title=\u64cd\u4f5c\u8fdb\u884c\u4e2d progress.window.msg.filemove=\u8bf7\u7b49\u5f85\u6587\u4ef6\u79fb\u52a8/\u91cd\u547d\u540d\u5b8c\u6210 ConfigView.label.popup.timestamp=\u4e3a\u5f39\u51fa\u63d0\u793a\u6dfb\u52a0\u65f6\u95f4\u6233 ConfigView.label.popup.autohide=\u975e\u9519\u8bef\u6027\u8d28\u7684\u5f39\u51fa\u63d0\u793a\u81ea\u52a8\u9690\u85cf\u7b49\u5f85\u65f6\u95f4\uff08\u8bbe\u7f6e\u4e3a 0 \u65f6\u7981\u7528\u81ea\u52a8\u9690\u85cf\uff09 ConfigView.label.popup.suppress_alerts=\u7981\u6b62\u63d0\u793a ConfigView.label.popup.use_message_boxes=\u4f7f\u7528\u5f39\u51fa\u4fe1\u606f\u6846\u800c\u4e0d\u662f\u4f20\u7edf\u7684\u63d0\u793a\u7a97\u53e3 ConfigView.label.popup.show=\u663e\u793a\u76ee\u524d\u4e3a\u6b62\u6240\u6709\u5f39\u51fa\u63d0\u793a\uff08\u5982\u679c\u5b58\u5728\u7684\u8bdd\uff09 ConfigView.label.popup.show.button=\u663e\u793a ConfigView.label.please.visit.here=\u8bf7\u81f3\u8be5\u5904\u83b7\u53d6\u8be6\u7ec6\u4fe1\u606f ConfigView.section.ipfilter.enable.descriptionCache=\u5728\u6293\u53d6\u6587\u4ef6\u4e2d\u50a8\u5b58 IP \u63cf\u8ff0 ConfigView.section.ipfilter.enable.descriptionCache.tooltip=\u5f53\u7981\u7528\u65f6\uff0c\u63cf\u8ff0\u4e0d\u4f1a\u88ab\u8bb0\u4f4f OpenTorrentWindow.filesInfo=%1 of %2 \u5c06\u88ab\u4e0b\u8f7d. OpenTorrentWindow.diskUsage=\u5df2\u7528 %1 \u603b\u5171 %2 ConfigView.label.openmytorrents=\u542f\u52a8\u65f6\u6253\u5f00 "\u6211\u7684 Torrents" \u9875\u9762 ConfigView.label.open_transfer_bar_on_start=\u542f\u52a8\u65f6\u663e\u793a\u4f20\u8f93\u6761 ConfigView.section.style.DNDalwaysInIncomplete=\u603b\u662f\u5c06\u9009\u62e9\u4e0b\u8f7d\u7684\u4efb\u52a1\u653e\u5728 "\u6211\u7684 Torrents" \u9875\u9762\u7684\u672a\u5b8c\u6210\u7a97\u683c\u4e2d OpenTorrentWindow.mb.noGlobalDestDir.title=\u76ee\u7684\u76ee\u5f55\u6ca1\u6709\u627e\u5230 OpenTorrentWindow.mb.noGlobalDestDir.text=\u76ee\u7684\u76ee\u5f55 "%1" \u4e0d\u5b58\u5728\u6216\u8005\u65e0\u6548\u3002 OpenTorrentWindow.mb.noDestDir.title=\u76ee\u7684\u76ee\u5f55\u6ca1\u6709\u627e\u5230 OpenTorrentWindow.mb.noDestDir.text=\u4f5c\u4e3a "%2" \u79cd\u5b50\u7684\u76ee\u7684\u76ee\u5f55 "%1" \u4e0d\u5b58\u5728\u6216\u8005\u65e0\u6548\u3002 OpenTorrentWindow.mb.notValid.title=\u6253\u5f00 Torrent OpenTorrentWindow.mb.notValid.text=\u65e0\u6cd5\u6253\u5f00 "%1". \u5982\u679c\u4f60\u6253\u5f00\u4e8e\u505a\u79cd\u6a21\u5f0f\uff0c\u8bf7\u786e\u8ba4\u79cd\u5b50\u6570\u636e\u5b58\u5728\u3002 OpenTorrentWindow.mb.notTorrent.title=\u6253\u5f00 Torrent OpenTorrentWindow.mb.notTorrent.text=\u65e0\u6cd5\u6253\u5f00 "%1". \u8fd9\u4e0d\u662f\u4e00\u4e2a .torrent \u6587\u4ef6\u3002\n\n\u6536\u5230\u90e8\u5206\u6570\u636e\uff1a\n%2 ConfigView.label.pause.downloads.on.exit=\u9000\u51fa\u65f6\u6682\u505c\u4e0b\u8f7d\u4efb\u52a1 ConfigView.label.resume.downloads.on.start=\u542f\u52a8\u5e76\u521d\u59cb\u5316\u5b8c\u6210\u540e\u8fdb\u884c\u6682\u505c\u7684\u4e0b\u8f7d\u4efb\u52a1 UIDebugGenerator.message.cancel.title=\u5df2\u53d6\u6d88\u751f\u6210 Debug \u4fe1\u606f UIDebugGenerator.message.cancel.text=\u4f60\u6ca1\u6709\u63cf\u8ff0\u4f60\u8981\u62a5\u544a\u7684 BUG\u3002 BUG \u5bf9\u4f60\u6765\u8bf4\u5f88\u660e\u663e\uff0c\u4f46\u6ca1\u6709\u63cf\u8ff0\u6211\u4eec\u4ec5\u80fd\u731c\u6d4b\u662f\u4f60\u4e2a\u4eba\u7684\u95ee\u9898\u3002\n\n\u5df2\u53d6\u6d88\u751f\u6210 Debug \u4fe1\u606f\u3002 ConfigView.section.connection.group.http.info=HTTP \u505a\u79cd\u6a21\u5f0f ConfigView.section.connection.http.enable=\u542f\u7528 ConfigView.section.connection.http.port=\u4f20\u5165\u7aef\u53e3\u53f7 ConfigView.section.connection.http.portoverride=Tracker HTTP \u7aef\u53e3\u8bbe\u7f6e\uff3b0\uff1a\u65e0\uff3d window.update.noupdates.title=\u68c0\u67e5\u66f4\u65b0\u7ed3\u679c window.update.noupdates.text=\u4f60\u7684\u7cfb\u7edf\u65e0\u9700\u66f4\u65b0\u3002\n\n\u606d\u559c\uff01 ConfigView.label.bindip.details=\u4f8b\u5982\uff1a192.168.1.5;eth0;eth1[2]\u5c06\u7ed1\u5b9a\u6307\u5b9a\u7684 IP \uff0c\u5177\u4f53\u6765\u8bf4\u7b2c1\u4e2a\u754c\u9762\u7684\u6240\u6709 IP \u4ee5\u53ca\u7b2c2\u4e2a\u754c\u9762\u7684\u7b2c3\u4e2a IP \u3002\n\u7b2c1\u4e2a IP \u5c06\u88ab\u7528\u4e8e\u6240\u6709\u670d\u52a1\uff0c\u6240\u6709\u5176\u4ed6 IP \u7528\u4e8e\u5e73\u8861\u3002\n\u4ee5\u4e0b\u754c\u9762\u53ef\u7528\uff1a\n%1 ConfigView.label.mindownloads=\u6700\u5c0f\u7684\u6d3b\u52a8\u4e0b\u8f7d\u6570 UI.cannot_submit_blank_text=\u4f60\u5fc5\u987b\u8f93\u5165\u4e00\u4e2a\u503c. crypto.alert.as.warning=\u5df2\u77e5\u7f51\u7edc "%1" \u65bd\u52a0 traffic shaping \u6765\u9650\u5236\u4e0b\u8f7d\u901f\u5ea6. \u4f20\u8f93\u52a0\u5bc6\u5df2\u81ea\u52a8\u6253\u5f00 - \u8fd9\u53ef\u4ee5\u901a\u8fc7\u76f8\u5173\u53c2\u6570\u6765\u5173\u95ed/\u8bbe\u7f6e\u3002 ConfigView.section.interface.alerts=\u63d0\u793a ConfigView.label.popupdownloadadded=\u5f53\u6dfb\u52a0\u4e00\u4e2a\u4e0b\u8f7d\u4efb\u52a1\u65f6\u5f39\u51fa\u63d0\u793a popup.download.added="%1" \u5df2\u6dfb\u52a0\u5230\u4f60\u7684\u4e0b\u8f7d\u5217\u8868\u4e2d. MessageBoxWindow.nomoreprompting=\u4e0d\u8981\u518d\u95ee\u6211\u7b2c\u4e8c\u904d TorrentOptionsView.param.max.seeds=\u6700\u5927\u79cd\u5b50\u8fde\u63a5\u6570\uff3b0\uff1a\u65e0\u9650\u5236\uff3d TorrentOptionsView.param.alternative.value.enable=\u505a\u79cd\u65f6\uff0c\u66ff\u4ee3\u503c ConfigView.section.proxy.check.on.start=\u542f\u52a8\u65f6\u68c0\u67e5\u4ee3\u7406\u72b6\u6001 TransferStatsView.legend.pingaverage=\u5e73\u5747 TransferStatsView.legend.ping1=\u76ee\u6807 1 TransferStatsView.legend.ping2=\u76ee\u6807 2 TransferStatsView.legend.ping3=\u76ee\u6807 3 ConfigView.section.interface.enabletray._mac=\u542f\u7528\u7cfb\u7edf\u6258\u76d8\u56fe\u6807\uff3b\u9700\u8981\u91cd\u542f\uff3d ConfigView.label.closetotray._mac=\u70b9\u51fb\u5173\u95ed\u6309\u7ebd\u65f6\u6700\u5c0f\u5316\u5230\u7cfb\u7edf\u6258\u76d8 ConfigView.label.minimizetotray._mac=\u70b9\u51fb\u6700\u5c0f\u5316\u6309\u7ebd\u65f6\u6700\u5c0f\u5316\u5230\u6258\u76d8 OpenTorrentWindow.mb.existingFiles.title=\u6587\u4ef6\u5df2\u5b58\u5728\uff01 OpenTorrentWindow.mb.existingFiles.text=\u4f60\u6307\u5b9a\u7684\u76ee\u5f55\u4e2d\u5df2\u7ecf\u5b58\u5728\u76f8\u540c\u6587\u4ef6\uff1a\n\n%1\n\u5982\u679c\u4f60\u7ee7\u7eed\uff0cVuze \u5c06\u68c0\u67e5\u8fd9\u4e9b\u6587\u4ef6\u4ee5\u4fbf\u786e\u8ba4\u6b63\u786e\u6570\u636e\u4ee5\u53ca\u5fc5\u8981\u65f6\u8986\u76d6\u3002 splash.unloadingTorrents=\u9000\u51fa Torrents splash.unloadingTorrent=\u9000\u51fa Torrent ConfigView.section.file.defaultdir.autorename=\u5f53\u4efb\u52a1\u6587\u4ef6\u4e0e\u76ee\u5f55\u4e2d\u5df2\u5b58\u5728\u7684\u6587\u4ef6\u91cd\u540d\u4f46\u4e0d\u540c\u65f6\uff0c\u81ea\u52a8\u4e3a\u4efb\u52a1\u6587\u4ef6\u91cd\u547d\u540d ConfigView.section.file.defaultdir.autorename.tooltip=\u8fd9\u53ef\u4ee5\u9884\u9632\u6587\u4ef6\u540d\u76f8\u540c\u65f6\u4e00\u4e2a\u79cd\u5b50\u4efb\u52a1\u8986\u76d6\u53e6\u4e00\u4e2a\u79cd\u5b50\u4efb\u52a1 alert.raised.at.close=\uff08\u4e0a\u6b21\u5173\u95ed Vuze \u65f6\u7684\u6d88\u606f\uff09 Plugin.trackerpeerauth.name=Tracker \u7528\u6237\u8ba4\u8bc1 Plugin.trackerpeerauth.info=\u8fd9\u4e2a\u63d2\u4ef6\u7528\u6765\u8ba4\u8bc1\u7528\u6237\u662f\u5426\u662f\u53ef\u7528\u7fa4\u4f53 Peers.column.maxupspeed=\u6700\u5927\u4e0a\u4f20\u901f\u5ea6 Peers.column.maxdownspeed=\u6700\u5927\u4e0b\u8f7d\u901f\u5ea6 MyTorrents.items.DownSpeedLimit.disabled=\u65e0\u4e0b\u8f7d Peers.column.lan=\u5c40\u57df\u7f51 upnp.selectedaddresses=\u5730\u5740\uff08"\uff1b" \u5206\u5f00\u7684\uff0c "-" prefix=\u62d2\u7edd\uff0c "+" =\u5141\u8bb8\uff09\uff3b\u7a7a\u767d\uff1a\u4efb\u610f\uff3d upnp.alert.multipledevice.warning=\u68c0\u6d4b\u5230\u591a\u91cd UPnP \u8bbe\u5907 - \u8bf7\u786e\u8ba4\u662f\u5426\u90fd\u9700\u8981\u7aef\u53e3\u6620\u5c04\uff08\u67e5\u770b UPnP \u65e5\u5fd7\u548c\u8bbe\u7f6e\uff09 UpdateMonitor.messagebox.restart.title=\u8f6f\u4ef6\u66f4\u65b0 UpdateMonitor.messagebox.restart.text=Vuze \u4e0b\u8f7d\u5b8c\u6210\u4e86\u4e00\u4e2a\u91cd\u8981\u66f4\u65b0\uff0c\u8fd9\u4e2a\u66f4\u65b0\u5fc5\u987b\u91cd\u542f\u624d\u80fd\u5b89\u88c5\u3002 PiecesView.BlockView.Have=\u62e5\u6709 PiecesView.BlockView.NoHave=\u6ca1\u6709 PiecesView.BlockView.Header=%1 \u5217\uff0c %2 \u884c\uff0c %3 \u5757 ConfigView.section.update.autodownload=\u81ea\u52a8\u4e0b\u8f7d\u66f4\u65b0\u7a0b\u5e8f\uff0c\u5e76\u63d0\u793a\u5b89\u88c5 Peers.column.peer_id=\u7528\u6237 ID Peers.column.peer_id.info=\u53ef\u9605\u8bfb\u6a21\u5f0f Peer ID Peers.column.peer_byte_id=\u7528\u6237 ID Peers.column.peer_byte_id.info=\u5b57\u8282\u6a21\u5f0f Peer ID Peers.column.handshake_reserved=\u63e1\u624b\u9884\u7559\u5b57\u8282 Peers.column.handshake_reserved.info=\u663e\u793a\u591a\u5c11\u5b57\u8282\u7528\u4e8e BT \u63e1\u624b Peers.column.client_identification=\u5ba2\u6237\u7aef\u8bc6\u522b Peers.column.client_identification.info=\u663e\u793a Vuze \u83b7\u5f97\u7684\u7a00\u6709\u5ba2\u6237\u7aef - \u7528\u4e8e Debug dht.warn.user=\u6f5c\u5728\u7684 NAT /\u7aef\u53e3\u6620\u5c04\u95ee\u9898\u8b66\u544a ConfigView.label.openbar.incomplete=\u8ff7\u4f60\u5de5\u5177\u6761\uff1a\u81ea\u52a8\u6253\u5f00\u4e0b\u8f7d\u4efb\u52a1 ConfigView.label.openbar.complete=\u81ea\u52a8\u6253\u5f00\u505a\u79cd\u4efb\u52a1 ConfigView.label.transferbar.remember_location=\u8bb0\u6ce8\u4f20\u8f93\u6761\u4f4d\u7f6e ConfigView.section.transfer.autospeed.forcemin=\u57fa\u7ebf\u8fde\u63a5\u65f6\u5f3a\u5236\u4e0a\u4f20\u901f\u5ea6\u4e3a %1 MainWindow.menu.tools.speedtest=\u901f\u5ea6\u6d4b\u8bd5\u2026 speedtest.wizard.title=\u901f\u5ea6\u6d4b\u8bd5 speedtest.wizard.run=\u8fd0\u884c\u901f\u5ea6\u6d4b\u8bd5 speedtest.wizard.test.mode.updown=\u4e0a\u4f20\u4e0e\u4e0b\u8f7d speedtest.wizard.test.mode.up=\u4e0a\u4f20 speedtest.wizard.test.mode.down=\u4e0b\u8f7d SpeedTestWizard.test.panel.currinfo=BitTorrent \u5e26\u5bbd\u6d4b\u8bd5. SpeedTestWizard.test.panel.label=Vuze \u901f\u5ea6\u6d4b\u8bd5\uff1a SpeedTestWizard.test.panel.already.running=\u6d4b\u8bd5\u5df2\u5728\u8fd0\u884c\u4e2d\uff01 SpeedTestWizard.test.panel.not.accepted=\u6d4b\u8bd5\u8bf7\u6c42\u672a\u88ab\u63a5\u53d7\uff1a SpeedTestWizard.test.panel.abort=\u653e\u5f03 SpeedTestWizard.test.panel.abort.countdown=\u5c06\u653e\u5f03\u6d4b\u8bd5\u4e8e\uff1a SpeedTestWizard.test.panel.test.countdown=\u6d4b\u8bd5\u5c06\u5b8c\u6210\u4e8e\uff1a SpeedTestWizard.test.panel.testfailed=\u6d4b\u8bd5\u5931\u8d25 SpeedTestWizard.test.panel.aborted=\u6d4b\u8bd5\u5df2\u624b\u52a8\u653e\u5f03. SpeedTestWizard.test.panel.enc.label=\u70b9\u51fb\u4f7f\u7528\u52a0\u5bc6\u6d4b\u8bd5\uff1a SpeedTestWizard.test.panel.standard=\u6807\u51c6 SpeedTestWizard.test.panel.encrypted=\u52a0\u5bc6\u7684 SpeedTestWizard.set.upload.button.apply=\u5e94\u7528 SpeedTestWizard.set.upload.result=\u4e0a\u4e00\u6b21\u6d4b\u8bd5\u7ed3\u679c SpeedTestWizard.finish.panel.title=\u901f\u5ea6\u6d4b\u8bd5\u5b8c\u6210\uff01 SpeedTestWizard.finish.panel.click.close=\u4f60\u5df2\u5b8c\u6210\u901f\u5ea6\u6d4b\u8bd5\u5411\u5bfc\u3002\u70b9\u51fb\u8fd9\u91cc\u9000\u51fa\u3002 SpeedTestWizard.finish.panel.max.upload=\u6700\u5927\u4e0a\u4f20\uff1a SpeedTestWizard.finish.panel.max.seeding.upload=\u505a\u79cd\u65f6\u6700\u5927\u4e0b\u8f7d\uff1a SpeedTestWizard.finish.panel.max.download=\u6700\u5927\u4e0b\u8f7d\uff1a SpeedTestWizard.finish.panel.enabled=\u542f\u7528 SpeedTestWizard.finish.panel.disabled=\u7981\u7528 SpeedTestWizard.abort.message.scheduled.in=\u8ba1\u5212\u6d4b\u8bd5\u5c06\u8fdb\u884c\u4e8e \u2026 %1 \u79d2" SpeedTestWizard.abort.message.unsupported.type=\u4e0d\u652f\u6301\u7684\u6d4b\u8bd5\u7c7b\u578b\uff01\uff01\uff01\uff01 SpeedTestWizard.abort.message.manual.abort=\u624b\u52a8\u653e\u5f03 SpeedTestWizard.abort.message.scheduling.failed=\u8ba1\u5212\u6d4b\u8bd5\u5931\u8d25 SpeedTestWizard.abort.message.download.added=\u6d4b\u8bd5\u4e2d\u5df2\u6dfb\u52a0\u4e0b\u8f7d %1 SpeedTestWizard.abort.message.entered.error=\u4e0b\u8f7d\u6d4b\u8bd5\u8f93\u5165\u9519\u8bef "%1" SpeedTestWizard.abort.message.entered.queued=\u6d4b\u8bd5\u4e0b\u8f7d\u8fdb\u5165\u6392\u961f/\u505c\u6b62\u72b6\u6001 SpeedTestWizard.abort.message.interrupted=Torrent \u901f\u5ea6\u6d4b\u8bd5\u76d1\u63a7\u5728\u6d4b\u8bd5\u5b8c\u6210\u524d\u88ab\u6253\u65ad SpeedTestWizard.abort.message.execution.failed=\u6d4b\u8bd5\u5931\u8d25 SpeedTestWizard.abort.message.failed.peers=\u4e0d\u80fd\u8fde\u63a5\u5230\u4efb\u4f55\u7528\u6237 SpeedTestWizard.abort.message.insufficient.slots=\u65e0\u6cd5\u4e0a\u4f20\u5230\u4efb\u4f55\u7528\u6237 - \u4e0a\u4f20\u901a\u9053\u4e0d\u8db3\uff1f SpeedTestWizard.abort.message.not.unchoked=\u65e0\u6cd5\u4ece\u4efb\u4f55\u7528\u6237\u4e0b\u8f7d\uff0c\u56e0\u4e3a\u59cb\u7ec8\u88ab\u5176\u963b\u6b62 SpeedTestWizard.stage.message.requesting=\u6b63\u5728\u8bf7\u6c42\u6d4b\u8bd5\u2026 SpeedTestWizard.stage.message.preparing=\u6b63\u5728\u51c6\u5907\u6d4b\u8bd5\u2026 SpeedTestWizard.stage.message.starting=\u6b63\u5728\u8fdb\u884c\u6d4b\u8bd5\u2026 SpeedTestWizard.stage.message.connect.stats=\u8fde\u63a5\u72b6\u6001\uff1a\u7528\u6237=%1\uff0c \u4e0b\u8f7d\u6b63\u5e38=%2\uff0c \u4e0a\u4f20\u6b63\u5e38=%3 window.uiswitcher.title=Vuze \u754c\u9762\u9009\u62e9\u5668 window.uiswitcher.text=\u8bf7\u9009\u62e9\u4e00\u4e2a\u4f60\u9700\u8981\u7684\u7528\u6237\u754c\u9762\u3002 window.uiswitcher.NewUI.text=* \u63a8\u8350\u7ed9\u521d\u5b66\u8005\u6216\u65b0\u7528\u6237\u3002\n\n* \u7b80\u5355\u7684\uff0c\u76f4\u89c2\u7684\u56fe\u5f62\u754c\u9762\n\n* \u9700\u8981\u5728 Vuze \u5e73\u53f0\u53d1\u5e03\u5185\u5bb9 window.uiswitcher.ClassicUI.title=\u7ecf\u5178\u754c\u9762 window.uiswitcher.ClassicUI.text=* \u4fdd\u7559 2.x \u7684\u529f\u80fd\n\n* Vuze \u5185\u5bb9\u4e0d\u4f1a\u8f7d\u5165 window.uiswitcher.bottom.text=\u901a\u8fc7 Vuze \u754c\u9762\u9009\u62e9\u6309\u7ebd\uff0c\u4f60\u53ef\u4ee5\u8f7b\u677e\u6539\u53d8\u4f60\u7684\u9009\u62e9 iconBar.switch.tooltip=Vuze \u754c\u9762\u9009\u62e9\u5668 VivaldiView.notAvailable=\u7528\u6237\u865a\u62df\u5206\u5e03\u89c6\u56fe\u4e0d\u53ef\u7528 restart.error=\u91cd\u542f\u5931\u8d25\uff1a\n%1\n\u8bf7\u67e5\u770b restarting issues. restart.error.oom=\u5185\u5b58\u4e0d\u8db3 restart.error.fnf="%2" \u4e2d\u6ca1\u6709\u53d1\u73b0 "%1" \u3002 restart.error.pnf=\u76ee\u5f55 "%1" \u4e0d\u5b58\u5728 restart.error.bad=\u9519\u8bef\u6587\u4ef6\u683c\u5f0f "%1" restart.error.denied=\u5c1d\u8bd5\u8fd0\u884c "%1" \u65f6\u62d2\u7edd\u8bbf\u95ee\u3002\u8bf7\u786e\u8ba4\u4f60\u62e5\u6709\u8db3\u591f\u7684\u6743\u9650\u3002 TableColumn.header.date_completed=\u5b8c\u6210\u65f6\u95f4 TableColumn.menu.date_added.reset=\u91cd\u7f6e\u65e5\u671f ConfigView.section.ipfilter.discardbanning=\u963b\u6b62\u8fd9\u4e9b\u7528\u6237\uff0c\u5f53\u635f\u574f\u6570\u636e/\u6b63\u786e\u6570\u636e\u8fbe\u5230\u4e0b\u9762\u7684\u6bd4\u4f8b\u65f6\uff3b0\uff1a\u7981\u7528\uff3d ConfigView.section.ipfilter.discardminkb=\u81f3\u5c11\u51fa\u73b0 %1 \u635f\u574f\u6570\u636e\u624d\u91c7\u53d6\u6bd4\u4f8b\u5224\u65ad\u63aa\u65bd ConfigView.interface.start.advanced=\u4ee5\u9ad8\u7ea7\u89c6\u56fe\u542f\u52a8\uff08AZ 2.x\uff09 MyTorrents.column.ColumnQuality=\u54c1\u8d28 MyTorrents.column.ColumnSpeed=\u901f\u5ea6 MyTorrents.column.ColumnProgressETA.2ndLine=\u5269\u4f59\uff1a %1 MyTorrents.column.ColumnProgressETA.StreamReady=\u51c6\u5907\u5206\u6d41 %1 MyTorrents.column.ColumnProgressETA.PlayableIn=\u53ef\u8fd0\u884c\u4e8e %1 %2 TableColumn.header.Quality=\u54c1\u8d28 TableColumn.header.Speed=\u901f\u5ea6 TableColumn.header.RateIt=\u8bc4\u4ef7 TableColumn.header.Rating=\u8bc4\u8bba TableColumn.header.SpeedGraphic=\u901f\u5ea6 TableColumn.header.AzProduct=\u4ece TableColumn.header.MediaThumb=\u5a92\u4f53 TableColumn.header.ProgressETA=\u8fdb\u5ea6 #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=\u6587\u4ef6\u7c7b\u578b\uff1a %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=\u4eea\u8868\u677f v3.MainWindow.tab.browse=\u6d4f\u89c8\u5185\u5bb9 v3.MainWindow.tab.library=\u6211\u7684\u6587\u4ef6\u5e93 v3.MainWindow.tab.publish=\u53d1\u5e03 v3.MainWindow.tab.advanced=\u9ad8\u7ea7 v3.MainWindow.menu.home=\u4eea\u8868\u677f\uff08&D\uff09 v3.MainWindow.menu.browse=\u6d4f\u89c8\u5185\u5bb9\uff08&B\uff09 v3.MainWindow.menu.library=\u6211\u7684\u6587\u4ef6\u5e93 v3.MainWindow.menu.publish=\u53d1\u5e03\uff08&P\uff09 v3.MainWindow.menu.advanced=\u9ad8\u7ea7\uff08&A\uff09 v3.MainWindow.menu.view.searchbar=\u641c\u7d22\u6761 v3.MainWindow.menu.view.tabbar=\u9875\u9762\u6761 v3.MainWindow.currentDL=\u6b63\u5728\u4e0b\u8f7d v3.MainWindow.button.stream=\u6d41 v3.MainWindow.button.stop=\u505c\u6b62 v3.MainWindow.button.start=\u5f00\u59cb v3.MainWindow.button.pause=\u6682\u505c v3.MainWindow.button.resume=\u7ee7\u7eed v3.MainWindow.button.delete=\u5220\u9664 v3.MainWindow.button.comment=\u8bc4\u8bba v3.MainWindow.button.viewdetails=\u67e5\u770b\u7ec6\u8282 v3.MainWindow.button.play=\u8fd0\u884c v3.MainWindow.button.cancel=\u53d6\u6d88 v3.MainWindow.button.preview=\u9884\u89c8 v3.MainWindow.view.wait=\u521d\u59cb\u5316\u89c6\u56fe\uff0c \u8bf7\u7a0d\u5019 v3.MainWindow.xofx=%2 \u7684 %1 v3.MainWindow.Loading=\u6b63\u5728\u8f7d\u5165.. \u8bf7\u7a0d\u5019 v3.filter-bar=\u6807\u9898\u8fc7\u6ee4\uff1a v3.MainWindow.search.defaultText=\u641c\u7d22 Vuze v3.mb.delPublished.title=\u505c\u6b62\u6b63\u5728\u505a\u79cd\u7684\u5185\u5bb9 v3.mb.delPublished.text=\u8b66\u544a\uff1a\u8fd9\u4e0d\u4f1a\u5c06\u4f60\u53d1\u5e03\u7684 "%1" \u4ece %3\u5220\u9664\u3002\n\n\u4ec5\u5728\u4f60\u60f3\u89e3\u653e\u4f60\u7684\u5e26\u5bbd\u53c8\u4e0d\u60f3\u5220\u9664\u53d1\u5e03\u6216\u4e0b\u8f7d\u7684\u5185\u5bb9\u65f6\uff0c\u70b9\u51fb\u5220\u9664\u3002\u8bf7\u786e\u8ba4\u4f60\u5220\u9664\u524d\u5df2\u53d1\u5e03\u5b8c\u6bd5\uff08how\uff1f\uff09\u3002\n\n\u5982\u679c\u4f60\u60f3\u5b8c\u5168\u4ece%3\u5220\u9664\uff0c\u70b9\u51fb\u53d6\u6d88\uff0c \u4f7f\u7528\u53d1\u5e03\u9875\u53d1\u5e03\u5185\u5bb9\u9762\u677f\u7684\uff08X\uff09 \u6309\u7ebd\u3002\n\n\u66f4\u591a\u5e2e\u52a9\u3002\n\n v3.mb.delPublished.delete=\u5220\u9664\uff08&D\uff09 v3.mb.delPublished.cancel=\u53d6\u6d88\uff08&C\uff09 v3.mb.openFile.title=\u6253\u5f00\u6587\u4ef6 v3.mb.openFile.text.known=\u8be5\u5185\u5bb9\u76ee\u524d\u4e0d\u88ab Vuze Player \u6240\u652f\u6301. \u68c0\u67e5\u793e\u533a\u521b\u5efa\u7684 \u56de\u653e\u6307\u5357 \u5bfb\u6c42\u5e2e\u52a9.\n\n\u6587\u4ef6\u7c7b\u578b\u4f3c\u4e4e\u662f : %2 (%3)\n v3.mb.openFile.text.unknown=\u8be5\u5185\u5bb9\u76ee\u524d\u4e0d\u88ab Vuze Player \u6240\u652f\u6301. \u68c0\u67e5\u793e\u533a\u521b\u5efa\u7684 \u56de\u653e\u6307\u5357 \u5bfb\u6c42\u5e2e\u52a9.\n\n\u6587\u4ef6\u6269\u5c55\u540d : %2\n v3.mb.openFile.button.play=\u64ad\u653e v3.mb.openFile.button.cancel=\u53d6\u6d88 v3.mb.openFile.button.guide=\u9605\u8bfb\u56de\u653e\u6307\u5357 v3.mb.openFile.remember=\u4e00\u76f4\u6253\u5f00\u6587\u4ef6\u800c\u4e0d\u8981\u8be2\u95ee\u6211 v3.mb.PlayFileNotFound.title=\u6587\u4ef6\u672a\u627e\u5230 v3.mb.PlayFileNotFound.text=\u6587\u4ef6 "%1" \u5df2\u5220\u9664\u6216\u4e22\u5931\u3002 v3.mb.PlayFileNotFound.button.remove=\u4ece Vuze \u5220\u9664 v3.mb.PlayFileNotFound.button.redownload=\u91cd\u65b0\u4e0b\u8f7d\u6570\u636e v3.mb.PlayFileNotFound.button.find=\u624b\u52a8\u67e5\u627e.. v3.mb.deletePurchased.title=\u5220\u9664\u8d2d\u4e70\u5185\u5bb9 v3.mb.deletePurchased.text=\u4f60\u786e\u5b9a\u8981\u5220\u9664 "%1" \u5417\uff1f\n\n\u8fd9\u53ef\u80fd\u662f\u4f60\u8d2d\u4e70\u7684\uff0c \u6216\u662f\u88ab\u8bf7\u6c42\u767b\u9646\u4e0b\u8f7d\u7684\u5185\u5bb9\u3002 v3.mb.deletePurchased.button.delete=\u5220\u9664\uff08&D\uff09 v3.mb.deletePurchased.button.cancel=\u53d6\u6d88\uff08&C\uff09 v3.topbar.menu.show.plugin=\u63d2\u4ef6\u533a\u57df v3.topbar.menu.show.search=\u641c\u7d22 v3.topbar.menu.show.frog=\u5927\u84dd\u86d9 splash.initializeCore=\u521d\u59cb\u5316\u6838\u5fc3 splash.initializeUIElements=\u521d\u59cb\u5316\u754c\u9762\u5143\u7d20 ConfigView.section.transfer.autospeedbeta=\u81ea\u52a8\u901f\u5ea6\u8c03\u6574-Beta # ConfigView.section.ipfilter.peerblocking.group=\u963b\u6321\u7528\u6237 ConfigView.section.ipfilter.autoload.group=\u6b63\u5728\u81ea\u52a8\u8f7d\u5165 ConfigView.section.ipfilter.autoload.file=\u8bf7\u9009\u62e9\u9700\u8981\u81ea\u52a8\u8f7d\u5982\u7684 IP \u8fc7\u6ee4\u6587\u4ef6 ConfigView.section.ipfilter.autoload.info=\u652f\u6301 eMule\uff0cPeerGuardian\uff0cP2B v1\uff0c2\uff0c3 \u683c\u5f0f\u3002\u6587\u4ef6\u53ef\u4ee5\u662f\u672c\u5730\u6587\u4ef6\u6216\u8fdc\u7a0b\u94fe\u63a5\u3001\u6587\u4ef6\u3001\u6587\u672c\u3002\n\u8fdc\u7a0b\u94fe\u63a5\u6bcf7\u5929\u4f1a\u81ea\u52a8\u91cd\u65b0\u4e0b\u8f7d\uff0c\u672c\u5730\u6587\u4ef6\u5c06\u5728\u4fee\u6539/\u8bbf\u95ee\u540e\u4e00\u5206\u949f\u5185\u91cd\u65b0\u8f7d\u5165\u3002 ConfigView.section.ipfilter.autoload.loadnow=\u7acb\u5373\u8f7d\u5165 splash.loadIpFilters=\u6b63\u5728\u8f7d\u5165 IP \u8fc7\u6ee4.. SpeedTestWizard.set.upload.title=\u8bbe\u7f6e\u4e0a\u4f20\u548c\u4e0b\u8f7d\u9650\u5236 SpeedTestWizard.set.download.label=\u4e0b\u8f7d\u901f\u5ea6\u9650\u5236\uff1a SpeedTestWizard.set.upload.label=\u4e0a\u4f20\u901f\u5ea6\u9650\u5236\uff1a SpeedTestWizard.name.conf.level.absolute=\u4e0d\u8db3 SpeedTestWizard.name.conf.level.high=\u9ad8 SpeedTestWizard.name.conf.level.med=\u4e2d\u7b49 SpeedTestWizard.name.conf.level.low=\u4f4e SpeedTestWizard.name.conf.level.none=\u65e0 ConfigView.section.transfer.select=\u81ea\u52a8\u901f\u5ea6\u8c03\u6574 ConfigView.section.transfer.select.v2=\u81ea\u52a8\u901f\u5ea6\u8c03\u6574\uff08beta\uff09 mb.azmustclose.title=\u542f\u52a8\u9519\u8bef mb.azmustclose.text=\u67d0\u4e9b\u95ee\u9898\u5bfc\u81f4 Vuze\u4ee5 Administrator \u8eab\u4efd\u91cd\u542f\uff08\u542f\u52a8\uff09\uff0cVuze \u5c06\u9000\u51fa\u3002\n\nVuze \u9000\u51fa\u540e\uff0c\u8bf7\u624b\u52a8\u91cd\u65b0\u542f\u52a8\u3002 network.ipv6.prefer.addresses=\u5f53 IPv6 \u4e0e IPv4 \u5730\u5740\u90fd\u53ef\u7528\u65f6\uff0c\u4f18\u5148\u9009\u7528 IPv6 \u5730\u5740 network.bindError=\u7ed1\u5b9a\u670d\u52a1\u5668 socket \u5931\u8d25\uff0c\u56e0\u4e3a\u6ca1\u6709\u517c\u5bb9\u7684\u5730\u5740\uff0c\u8bf7\u68c0\u67e5\u4f60\u7684 IP \u7ed1\u5b9a\u8bbe\u7f6e network.enforce.ipbinding=\u5f53\u754c\u9762\u4e0d\u53ef\u7528\u65f6\u52a0\u5f3a IP \u7ed1\u5b9a\uff0c\u5982\u679c\u6240\u6709\u6307\u5b9a\u7684\u754c\u9762\u90fd\u4e0d\u53ef\u80fd\u65f6\u9632\u6b62\u4efb\u4f55\u8fde\u63a5 DHTView.title.full_v6=\u5206\u5e03\u5f0f\u6570\u636e\u5e93 IPv6 ConfigView.pluginlist.loadSelected=\u8f7d\u5165\u5df2\u9009\u62e9\u9879\u76ee SpeedView.stats.asn=\u7f51\u7edc\uff1a SpeedView.stats.estupcap=\u4e0a\u4f20\u9650\u5236\uff1a SpeedView.stats.estdowncap=\u4e0b\u8f7d\u9650\u5236\uff1a SpeedView.stats.unknown=\u672a\u77e5 SpeedView.stats.estimate=\u4f30\u8ba1 SpeedView.stats.measured=\u5df2\u6d4b\u7b97\u7684 SpeedView.stats.measuredmin=\u5df2\u6d4b\u7b97\u5206\u949f\u6570 SpeedView.stats.manual=\u4fee\u590d\u7684 ConfigView.section.transfer.autospeed.networks=\u7f51\u7edc\u7ec6\u8282 ConfigView.section.transfer.autospeed.resetnetwork=\u91cd\u7f6e\u7f51\u7edc\u7ec6\u8282 ConfigView.section.transfer.autospeed.network.info=\u4ee5\u4e0a\u9650\u5236\u4e00\u822c\u662f\u4e0b\u8f7d/\u901f\u5ea6\u6d4b\u8bd5\u65f6\u81ea\u52a8\u751f\u6210\u7684\u3002\u5982\u679c\u4f60\u60f3\u624b\u52a8\u8bbe\u7f6e\uff0c\u8bf7\u4f7f\u7528\u4e0b\u9762\u7684\u9009\u9879\u3002\n\u5fc5\u8981\u60c5\u51b5\u4e0b\uff0c\u4fee\u6b63\u503c\u4ee5\u5916\u7684\u6240\u6709\u9650\u5236\u4f1a\u81ea\u52a8\u8c03\u6574\u3002\n\u8f93\u5165\u6570\u503c\u7136\u540e\u9009\u62e9\u7c7b\u578b\u3002\u6ce8\u610f\u901f\u5ea6\u5728%1\u3002 dialog.uiswitcher.restart.title=\u754c\u9762\u8f6c\u6362\uff1a Vuze \u9700\u8981\u91cd\u542f dialog.uiswitcher.restart.text=Vuze \u9700\u8981\u91cd\u542f\u4ee5\u4fbf\u66f4\u6362\u5230\u65b0\u754c\u9762\u3002 TrayWindow.menu.close=\u5173\u95ed\u4e0b\u8f7d\u7bee # Used for peers which we can't determine. PeerSocket.unknown=\u672a\u77e5 PeerSocket.fake_client=\u4f2a\u88c5 PeerSocket.bad_peer_id=\u9519\u8bef\u7528\u6237 ID PeerSocket.mismatch_id=\u4e0d\u5339\u914d PeerSocket.unknown_az_style=\u672a\u77e5 %1/%2 PeerSocket.unknown_shadow_style=\u672a\u77e5 %1/%2 OpenTorrentWindow.mb.askCreateDir.title=\u76ee\u6807\u76ee\u5f55\u4e0d\u5b58\u5728 OpenTorrentWindow.mb.askCreateDir.text=\u76ee\u6807\u76ee\u5f55 "%1" \u4e0d\u5b58\u5728\u3002\n\n\u73b0\u5728\u521b\u5efa\u5417\uff1f SpeedView.stats.estimatechoke=\u4f30\u8ba1\uff08\u963b\u6b62\uff09 ConfigTransferAutoSpeed.upload.capacity.usage=\u4e0a\u4f20\u80fd\u529b\u7528\u9014 ConfigTransferAutoSpeed.mode=\u6a21\u5f0f\uff1a ConfigTransferAutoSpeed.capacity.used=% \u80fd\u529b\u5df2\u4f7f\u7528 ConfigTransferAutoSpeed.while.downloading=\u6b63\u5728\u4e0b\u8f7d\uff1a ConfigTransferAutoSpeed.set.dht.ping=DHT Ping \u8bbe\u7f6e\uff1a ConfigTransferAutoSpeed.set.point=\u8bbe\u7f6e\u70b9\uff08\u6beb\u79d2\uff09 ConfigTransferAutoSpeed.set.tolerance=tolerance\uff08\u6beb\u79d2\uff09 ConfigTransferAutoSpeed.ping.time.good=\u597d\uff1a ConfigTransferAutoSpeed.ping.time.bad=\u574f\uff1a ConfigTransferAutoSpeed.adjustment.interval=\u8c03\u6574\u533a\u95f4\uff1a ConfigTransferAutoSpeed.skip.after.adjust=\u8c03\u6574\u540e\u8df3\u8fc7\uff1a GeneralView.label.distributedCopies=\u5206\u53d1\u62f7\u8d1d\u6570\uff1a PiecesView.DistributionView.title=\u533a\u5757\u5206\u914d PiecesView.DistributionView.NoAvl=\u4e0d\u53ef\u89c1\u533a\u5757 PiecesView.DistributionView.SeedAvl=\u79cd\u5b50\u5e73\u5747\u8d21\u732e PiecesView.DistributionView.PeerAvl=\u7528\u6237\u5e73\u5747\u8d21\u732e PiecesView.DistributionView.RarestAvl=\u6700\u7a00\u6709\u533a\u5757\uff1a %1\uff08\u5e73\u5747\uff1a%2\uff09 PiecesView.DistributionView.weHave=\u4f60\u62e5\u6709\u7684\u533a\u5757 PiecesView.DistributionView.theyHave=\u7528\u6237\u62e5\u6709\u7684\u5757 PiecesView.DistributionView.weDownload=\u4f60\u6b63\u5728\u4e0b\u8f7d\u7684\u533a\u5757 PeersView.gain=\u83b7\u53d6\u91cf PeersView.gain.info=\u5df2\u4e0b\u8f7d - \u5df2\u4e0a\u4f20\u7684\u6570\u636e\u91cf unix.script.new.title=\u68c0\u6d4b\u5230\u65b0\u7684 Vuze \u542f\u52a8\u811a\u672c unix.script.new.text=\u68c0\u6d4b\u5230\u65b0\u7684 Vuze\u542f\u52a8\u811a\u672c\uff0c \u5e76\u4e14\u5df2\u4fdd\u5b58\u5230 "%1"\u3002\n\n\u5f3a\u70c8\u63a8\u8350\u4f60\u7acb\u5373\u91cd\u542f Vuze\u5207\u6362\u5230\u8be5\u811a\u672c\uff08"%2"\uff09\u3002\n\n\u5982\u679c\u4f60\u6539\u52a8\u4e86 Vuze\u542f\u52a8\u811a\u672c\uff0c \u8bf7\u67e5\u770b AzureusWiki\uff1a Unix Script\u3002\n\n\u5982\u679c\u4f60\u662f\u901a\u8fc7\u91cd\u65b0\u6253\u5305\u65b9\u5f0f\u83b7\u5f97 Vuze uff08yum\uff0c apt-get\uff0c etc\uff09\uff0c \u5f3a\u70c8\u63a8\u8350\u4f60\u4ece\u5982\u4e0b\u4f4d\u7f6e\u83b7\u5f97 Vuze Vuze Sourceforge Page\uff08\u4f60\u5c06\u83b7\u5f97\u5f53\u524d\u76f8\u540c\u7684\u754c\u9762\uff09 unix.script.new.button.quit=\u7acb\u5373\u9000\u51fa unix.script.new.button.continue=\u7a0d\u4faf\u6267\u884c unix.script.new.button.asknomore=\u522b\u518d\u7e41\u6211 unix.script.new.auto.title=\u65b0 Vuze \u542f\u52a8\u811a\u672c unix.script.new.auto.text=\u68c0\u6d4b\u5230\u65b0\u7684 Vuze \u542f\u52a8\u811a\u672c\u3002\n\n\u5f3a\u70c8\u63a8\u8350\u4f60\u7acb\u5373\u91cd\u542f Vuze u3002 Content.alert.notuploaded.button.stop=&\u505c\u6b62\uff08&S\uff09 Content.alert.notuploaded.button.continue=&\u7ee7\u7eed\u505a\u79cd\uff08&C\uff09 Content.alert.notuploaded.button.abort=&\u4e0d\u9000\u51fa\uff08&D\uff09 ConfigView.label.checkOnSeeding=\u505a\u79cd\u65f6\u4f7f\u7528\u4f4e\u8d44\u6e90\u65b9\u5f0f\u68c0\u67e5\u533a\u5757 ConfigView.label.ui_switcher=\u663e\u793a Vuze \u754c\u9762\u9009\u62e9\u5668 ConfigView.label.ui_switcher_button=\u663e\u793a SpeedTestWizard.test.panel.explain=\u6d4b\u8bd5\u4f60\u7684 Vuze \u534f\u8bae\u901f\u5ea6\u3002\u9009\u62e9\u901f\u5ea6\u6d4b\u8bd5\u7c7b\u578b\u548c\u52a0\u5bc6\u6a21\u5f0f\u3002\u8bbf\u95ee Aureus \u7ef4\u57fa\u9875\u83b7\u53d6\u8fd9\u6b21\u6d4b\u8bd5\u8be6\u7ec6\u4fe1\u606f\u3002\u6b63\u5e38\u6d4b\u8bd5\u5728\u4e00\u5206\u949f\u5185\u3002\u5982\u679c\u8d85\u8fc7\u4e86\u4e24\u5206\u949f\uff0c\u6d4b\u8bd5\u5c06\u81ea\u52a8\u505c\u6b62\u3002 SpeedTestWizard.set.upload.hint=\u8bbe\u5b9a Vuze \u81ea\u52a8\u901f\u5ea6\u8c03\u6574\u7b97\u6cd5\u7528\u7684\u4e0a\u4f20\u548c\u4e0b\u8f7d\u9650\u5236\u3002 SpeedTestWizard.set.upload.panel.explain=\u8fd9\u91cc\u7684\u9650\u5236\u5c06\u7528\u4e8e Vuze \u81ea\u52a8\u901f\u5ea6\u8c03\u6574\u7b97\u6cd5\u3002\u8bbe\u7f6e\u4f20\u8f93\u9650\u5236\u548c\u4fe1\u5fc3\u9650\u5236\u3002\n\n\u6ce8\u610f\u7ebf\u8def\u901f\u5ea6\u4e00\u822c\u662f\u7528 bits \u505a\u5355\u4f4d - \u4f46\u4ee5\u4e0b\u6570\u503c\u7528 Bytes \u505a\u5355\u4f4d\u3002 SpeedTestWizard.set.limit.conf.level=\u4fe1\u5fc3 SpeedTestWizard.finish.panel.auto.speed=\u81ea\u52a8\u901f\u5ea6\u8c03\u6574\uff1a SpeedTestWizard.finish.panel.auto.speed.seeding=\u505a\u79cd\u65f6\u81ea\u52a8\u901f\u5ea6\u8c03\u6574\uff1a ConfigTransferAutoSpeed.add.comment.to.log.group=\u6dfb\u52a0\u8bc4\u8bba\u5230 Debug \u65e5\u5fd7 ConfigTransferAutoSpeed.add.comment.to.log=\u6dfb\u52a0\u8bc4\u8bba\uff1a ConfigTransferAutoSpeed.log.button=\u65e5\u5fd7 ConfigTransferAutoSpeed.algorithm.selector=\u81ea\u52a8\u901f\u5ea6\u8c03\u6574\u7b97\u6cd5\u9009\u62e9 ConfigTransferAutoSpeed.algorithm=\u7b97\u6cd5\uff1a ConfigTransferAutoSpeed.auto.speed.classic=\u81ea\u52a8\u901f\u5ea6\u8c03\u6574\uff08\u65e7\u5f0f\uff09 ConfigTransferAutoSpeed.auto.speed.beta=\u81ea\u52a8\u901f\u5ea6\u8c03\u6574\uff08beta\uff09 ConfigTransferAutoSpeed.data.update.frequency=\u66f4\u65b0\u9891\u7387 Alert.failed.update=\u81f3\u5c11\u6709\u4e00\u4e2a\u7ec4\u4ef6\u5b89\u88c5\u5931\u8d25\u3002\u8bf7\u67e5\u770b AzureusWiki\uff1a Failed Update [%1] OpenTorrentWindow.mb.existingFiles.partialList=\uff08\u90e8\u5206\u5217\u8868. \u66f4\u591a\u6587\u4ef6\u5df2\u5b58\u5728\uff09 TableColumn.header.bad_avail_time.info=\u4e0a\u4e00\u6b21\u770b\u5230\u5b8c\u6574\u62f7\u8d1d\u7684\u65f6\u95f4 TableColumn.header.bad_avail_time=\u770b\u5230\u5b8c\u6574\u62f7\u8d1d\u7684\u65f6\u523b MyTorrentsView.menu.exporthttpseeds=\u5bfc\u51fa HTTP \u79cd\u5b50 URLs \u5230\u526a\u8d34\u677f SWT.alert.erroringuithread=\u754c\u9762\u53d1\u751f\u672a\u77e5\u9519\u8bef\u3002\u8fd9\u53ef\u80fd\u5bfc\u81f4\u8fde\u7eed\u9519\u8bef - ConfigView.label.minannounce=Tracker Announce \u6700\u5c0f\u65f6\u95f4\uff08\u79d2\uff09\u95f4\u9694 ConfigView.label.maxnumwant=\u9650\u5236 Tracker \u53ef\u80fd\u8fd4\u56de\u7684\u7528\u6237\u6570\u76ee ConfigView.label.announceport=\u8986\u76d6 Tracker Announce \u7aef\u53e3 ConfigView.label.noportannounce=\u4e0d\u5c06\u76d1\u542c\u7aef\u53e3\u62a5\u544a\u7ed9 Tracker\uff08\u8fd9\u4e0d\u5f71\u54cd pex\uff0c dht\uff09 ConfigView.label.maxseedspertorrent=\u9ed8\u8ba4\u6bcf Torrent \u6700\u5927\u79cd\u5b50\u6570\uff3b0\uff1a\u65e0\u9650\u5236\uff3d wizard.webseed=\u6dfb\u52a0 HTTP \u79cd\u5b50\u5230 torrent wizard.webseed.title=HTTP \u505a\u79cd wizard.webseed.configuration=HTTP \u505a\u79cd\u8bbe\u7f6e wizard.webseed.adding=\u6b63\u5728\u6dfb\u52a0 HTTP \u79cd\u5b50 GeneralView.label.private=\u79c1\u4e0b\u7684 Torrent: GeneralView.yes=\u786e\u8ba4 ConfigView.label.userequestlimiting=\u4f7f\u7528\u9650\u5236\u8bf7\u6c42\u7684\u65b9\u5f0f\u6765\u9650\u5236\u4e0b\u8f7d\u901f\u5ea6\uff3b\u5f53\u4e0b\u8f7d\u901f\u5ea6\u65e0\u9650\u5236\u65f6\u65e0\u6548\uff3d ConfigView.label.userequestlimiting.tooltip=\u9650\u5236\u8bf7\u6c42\u7684\u65b9\u5f0f\u4e0d\u5982\u4f20\u7edf\u5ef6\u65f6\u8bfb\u53d6\u6765\u5f97\u5e73\u6ed1\uff0c\u4f46\u5141\u8bb8\u5bf9\u4e0b\u8f7d\u8bf7\u6c42\u5757\u8fdb\u884c\u4f18\u5148\u7ea7\u5904\u7406\uff0c\u56e0\u6b64\u53ef\u80fd\u53ef\u4ee5\u63d0\u9ad8\u7f51\u7edc\u6027\u80fd ConfigView.label.userequestlimitingpriorities=\u5f53\u4e0b\u8f7d\u901f\u5ea6\u5230\u8fbe\u4e0a\u9650\u65f6\uff0c\u5168\u529b\u4e0b\u8f7d\u4e0b\u8f7d\u4efb\u52a1\u4e2d\u6700\u9760\u524d\u7684\u5757 ConfigView.section.logging.timestamp=\u5386\u53f2\u6587\u4ef6\u91c7\u53d6\u65f6\u95f4\u6807\u8bb0\u683c\u5f0f Peers.column.timetocomplete=\u5269\u4f59\u65f6\u95f4 Peers.column.timetocomplete.info=\u7528\u6237\u5b8c\u6210\u524d\u5269\u4f59\u65f6\u95f4 ConfigView.section.interface.display.suppress.file.download.dialog=\u7981\u6b62\u6587\u4ef6\u4e0b\u8f7d\u5f39\u51fa\u6846 ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=\u5728\u72b6\u6001\u6761\u4e2d\u663e\u793a\u6240\u6709\u6587\u4ef6\u4e0b\u8f7d\u8fdb\u5ea6\u800c\u4e0d\u662f\u5f39\u51fa\u6846 FileDownload.canceled=\u4e00\u4e2a torrent \u4e0b\u8f7d\u6587\u4ef6\u6210\u529f\u88ab\u7528\u6237\u4ee5 %1 \u53d6\u6d88 Progress.reporting.status.canceled=\u5df2\u53d6\u6d88 Progress.reporting.status.finished=\u5df2\u5b8c\u6210 Progress.reporting.status.retrying=\u6b63\u5728\u91cd\u8bd5... Progress.reporting.action.label.retry.tooltip=\u91cd\u8bd5 Progress.reporting.action.label.remove.tooltip=\u4ece\u5386\u53f2\u4e2d\u79fb\u9664\u8fd9\u4e2a\u8fdb\u5ea6\u62a5\u544a Progress.reporting.action.label.cancel.tooltip=\u53d6\u6d88\u64cd\u4f5c Progress.reporting.action.label.detail=\u7ec6\u8282 Progress.reporting.default.error=\u5931\u8d25 Progress.reporting.no.reports.to.display=\u5f53\u524d\u6ca1\u6709\u8fdb\u5ea6\u62a5\u544a\u53ef\u663e\u793a\u3002 Progress.reporting.no.history.to.display=\u65e0\u7ec6\u8282\u4fe1\u606f\u53ef\u663e\u793a\u3002 Progress.reporting.detail.history.limit=\u8fd9\u4e2a\u8fdb\u5ea6\u62a5\u544a\u5df2\u7ecf\u5230\u8fbe\u7ec6\u8282\u4fe1\u606f\u9650\u5236\uff08%1\uff09\uff1b\u63a5\u4e0b\u6765\u7684\u7ec6\u8282\u4e0d\u4f1a\u52a0\u5165\u5386\u53f2 Progress.reporting.statusbar.button.tooltip=\u663e\u793a\u8fdb\u5ea6\u62a5\u544a\u7a97\u53e3 webui.bindip=\u7ed1\u5b9a IP \u4e00\u822c\u4e0d\u9700\u8981\uff08*\uff09 v3.MainWindow.text.log.in=\u767b\u9646 v3.MainWindow.text.log.out=\u6ce8\u9500 v3.MainWindow.text.get.started=\u6ce8\u518c v3.MainWindow.text.my.account=\u6211\u7684\u5e10\u6237 v3.MainWindow.text.my.profile=\u9884\u7f6e\u6587\u4ef6 OpenTorrentWindow.simple.open=Torrent \u4f4d\u7f6e \uff08\u6587\u4ef6\uff0cURL\uff0cHash\uff09 Progress.reporting.window.remove.auto=\u81ea\u52a8\u79fb\u9664\u4e0d\u6d3b\u52a8\u7684\u9879\u76ee Progress.reporting.window.remove.auto.tooltip=\u81ea\u52a8\u4ece\u89c6\u56fe\u4e2d\u79fb\u9664\u5df2\u5b8c\u6210\uff0c\u5931\u8d25\uff0c\u6216\u53d6\u6d88\u7684\u8fdb\u5ea6 Progress.reporting.window.remove.now=\u79fb\u9664\u4e0d\u6d3b\u52a8\u7684\u9879\u76ee Progress.reporting.window.remove.now.tooltip=\u4ece\u89c6\u56fe\u4e2d\u79fb\u9664\u5df2\u5b8c\u6210\uff0c\u5931\u8d25\uff0c\u6216\u53d6\u6d88\u7684\u8fdb\u5ea6 dhttracker.tracklimitedwhenonline=\u5c3d\u7ba1\u5982\u6b64\uff0c\u8de8\u4efb\u52a1\u7fa4\u4f53\u60c5\u51b5\u4e0b\uff0c\u91c7\u7528\u4f4e\u8d44\u6e90\u65b9\u5f0f\u8ddf\u8e2a TorrentOptionsView.multi.title.short=Torrent \u9009\u9879 TorrentOptionsView.multi.title.full=Torrent \u9009\u9879 MyTorrentsView.menu.open_parent_folder=\u6253\u5f00\u5173\u8054\u6587\u4ef6\u5939 ConfigView.section.style.use_show_parent_folder=\u5728 torrent \u83dc\u5355\u4e2d\u4f7f\u7528 "%1" \u800c\u4e0d\u662f "%2" ConfigView.section.style.use_show_parent_folder.tooltip=\u542f\u7528\u8fd9\u4e2a\u9009\u9879\u5c06\u5141\u8bb8\u4f60\u7528\u6b63\u786e\u7684\u6587\u4ef6\u7ba1\u7406\u7a0b\u5e8f\u6253\u5f00\u5173\u8054\u6587\u4ef6\u5939\u3002\n\u5c3d\u7ba1\u5982\u6b64\uff0c\u8fd9\u53ef\u80fd\u610f\u5473\u7740\u4e0b\u8f7d\u4fdd\u5b58\u4f4d\u7f6e\u4e0d\u662f\u81ea\u52a8\u8bbe\u5b9a\u7684\u3002 PeerManager.status.ps_disabled=Tracker \u7528\u6237\u6765\u6e90\u5df2\u7981\u7528 ConfigView.section.stats.exportfiles=\u5bfc\u51fa\u6587\u4ef6\u7ec6\u8282 updater.cant.write.to.app.title=\u65e0\u6cd5\u5199\u5165\u7a0b\u5e8f\u6587\u4ef6\u5939 updater.cant.write.to.app.details=\u6587\u4ef6\u5939 "%1" \u65e0\u6cd5\u5199\u5165\u3002\n\n\u8fd9\u5c06\u59a8\u788d\u8f6f\u4ef6\u66f4\u65b0\u3002\n\nsee the wiki for details plugin.install.class_version_error=\u8fd9\u4e2a\u63d2\u4ef6\u9700\u8981\u66f4\u65b0 Java \u624d\u80fd\u4f7f\u7528\u3002 v3.MainWindow.tab.minilibrary=\u4e0b\u8f7d v3.MainWindow.tab.events=\u6d3b\u52a8 button.columnsetup.tooltip=\u5217\u8bbe\u5b9a v3.activity.remove.title=\u79fb\u9664\u6d3b\u52a8\u9879\u76ee v3.activity.remove.text=\u4f60\u786e\u5b9a\u4f60\u60f3\u79fb\u9664\u6d3b\u52a8\u4e8b\u4ef6 "%1" \u5417\uff1f #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=\u5173\u95ed Menu.show.torrent.menu=\u663e\u793a Torrents \u83dc\u5355 Menu.show.torrent.menu.tooltip=\u5728\u7a0b\u5e8f\u83dc\u5355\u6761\u9876\u90e8\u663e\u793a Torrents \u83dc\u5355 #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=\u7f51\u7edc\u72b6\u6001 plugin.aznetstatus.pingtarget=Ping/trace \u8def\u7531\u76ee\u6807 ConfigView.section.style.usePathFinder=\u4f7f\u7528 "\u8def\u5f84\u67e5\u8be2" \u800c\u4e0d\u662f "Finder" menu.sortByColumn=\u4ee5 %1 \u6392\u5e8f MyTorrentsView.menu.manual.per_peer=\u624b\u52a8\uff08\u6bcf\u4e2a\u7528\u6237\uff09 MyTorrentsView.menu.manual.shared_peers=\u624b\u52a8\uff08\u8de8\u7528\u6237\uff09 v3.button.removeActivityEntry=\u79fb\u9664\u6d3b\u52a8\u9879\u76ee v3.splash.initSkin=\u521d\u59cb\u5316\u754c\u9762\u76ae\u80a4 v3.splash.hookPluginUI=\u94a9\u4f4f\u63d2\u4ef6\u754c\u9762 OpenTorrentWindow.mb.notTorrent.cannot.display=\u65e0\u6cd5\u6b63\u786e\u663e\u793a\u6570\u636e MainWindow.menu.window.zoom.maximize=\u6700\u5927\u5316 MainWindow.menu.window.zoom.restore=\u8fd8\u539f ImageResizer.image.too.small=\u63d0\u4f9b\u7684\u56fe\u7247\u592a\u5c0f\u4e86\uff0c\u8bf7\u9009\u62e9\u53e6\u9009\u4e00\u4e2a (\u9700\u8981\u6700\u5c11 %1 x %2) ImageResizer.title=\u8fd9\u4e2a\u5de5\u5177\u8ba9\u4f60\u9884\u89c8\u4f60\u7684\u7f29\u7565\u56fe\u5728 Vuze \u5e73\u53f0\u4e0a\u7684\u6837\u5b50\u3002 ImageResizer.move.image=\u62d6\u52a8\u4ee5\u79fb\u52a8\u56fe\u7247 ImageResizer.move.image.with.slider=\u62d6\u52a8\u4ee5\u79fb\u52a8\u56fe\u7247\uff0c\u4f7f\u7528\u4e0b\u65b9\u7684\u6ed1\u5757\u6539\u53d8\u5927\u5c0f security.crypto.title=\u8bbf\u95ee\u52a0\u5bc6Key security.crypto.encrypt=\u8bf7\u8f93\u5165\u4e00\u4e2a\u5bc6\u7801\u6765\u4fdd\u62a4\u60a8\u65b0\u751f\u6210\u7684\u52a0\u5bc6 key\u3002\u8bf7\u7262\u8bb0\u6b64\u5bc6\u7801\uff0c\u5982\u679c\u5fd8\u8bb0\u5c06\u65e0\u6cd5\u6062\u590d\uff01 security.crypto.decrypt=\u8bf7\u8f93\u5165\u5bc6\u7801\u4ee5\u89e3\u9501\u60a8\u7684\u52a0\u5bc6key security.crypto.reason=\u6267\u884c\u6b64\u64cd\u4f5c\u7684\u539f\u56e0 security.crypto.password=\u5bc6\u7801 security.crypto.password2=\u91cd\u65b0\u8f93\u5165\u5bc6\u7801 security.crypto.persist_for=\u5bc6\u7801\u4fdd\u5b58\u671f security.crypto.persist_for.dont_save=\u4e0d\u4fdd\u5b58 security.crypto.persist_for.session=\u6b64\u6b21\u4f1a\u8bdd security.crypto.persist_for.day=1 \u5929 security.crypto.persist_for.week=1 \u5468 security.crypto.persist_for.30days=30 \u5929 security.crypto.persist_for.forever=\u6c38\u4e45 security.crypto.password.mismatch.title=\u5bc6\u7801\u9519\u8bef security.crypto.password.mismatch=\u8f93\u5165\u7684\u5bc6\u7801\u503c\u4e0d\u5339\u914d\uff0c\u8bf7\u91cd\u65b0\u8f93\u5165 ConfigView.section.security.group.crypto=\u5171\u7528/\u79c1\u6709 Keys ConfigView.section.security.resetkey=\u91cd\u7f6e keys ConfigView.section.security.resetkey.warning.title=\u6570\u636e\u4e22\u5931\u8b66\u544a ConfigView.section.security.resetkey.warning=\u4f60\u786e\u5b9a\u8981\u91cd\u7f6e\u4f60\u7684\u52a0\u5bc6 keys? \u5982\u679c\u90a3\u6837\u7684\u8bdd\u4f60\u6240\u6709\u7528\u4ed6\u4eec\u52a0\u5bc6\u7684\u4fe1\u606f\u90fd\u5c06\u6c38\u4e45\u6027\u4e22\u5931\u3002\u540c\u65f6\u4efb\u4f55\u901a\u8fc7\u4f60\u7684\u516c\u94a5\u8054\u7ed3\u7684\u7528\u6237\u5728\u83b7\u5f97\u4f60\u53d1\u5e03\u65b0\u7684key\u4e4b\u524d\u5c06\u4e0d\u518d\u80fd\u548c\u4f60\u6c9f\u901a\u3002\u6240\u4ee5\uff0c\u9664\u975e\u4f60\u771f\u7684\u6e05\u9664\u81ea\u5df1\u5728\u505a\u4ec0\u4e48\uff0c\u4e0d\u8981\u8fd9\u6837\u505a\u3002 ConfigView.section.security.unlockkey=\u660e\u786e\u89e3\u9501\u7684 keys ConfigView.section.security.unlockkey.button=\u89e3\u9501 ConfigView.section.security.publickey=\u516c\u94a5 ConfigView.section.security.publickey.undef=\u5c1a\u672a\u5b9a\u4e49 ConfigView.section.security.resetkey.error.title=\u64cd\u4f5c\u5931\u8d25 ConfigView.section.security.resetkey.error=\u91cd\u7f6e keys \u5931\u8d25 ConfigView.section.security.unlockkey.error=\u89e3\u9501 key \u5931\u8d25 - \u5bc6\u7801\u4e0d\u6b63\u786e ConfigView.copy.to.clipboard.tooltip=\u590d\u5236\u5230\u526a\u8d34\u677f Views.plugins.azbuddy.title=\u597d\u53cb Browser.popup.error.no.access=\u5c1d\u8bd5\u8bbf\u95ee\u8fdc\u7a0b\u8d44\u6e90\u65f6\u51fa\u73b0\u9519\u8bef.\n\u8bf7\u7a0d\u5019\u518d\u8bd5\u3002\n ConfigView.label.queue.stoponcebandwidthmet=\u5f53\u8fbe\u5230\u4e0a\u4f20/\u4e0b\u8f7d\u901f\u5ea6\u9650\u5236\u4e0d\u8981\u542f\u52a8\u66f4\u591a\u7684 torrents ConfigView.section.style.forceMozilla=\u5f3a\u5236 Vuze \u4f7f\u7528 Mozilla \u6d4f\u89c8 widgets [\u9700\u8981 xulrunner or firefox 3; \u9700\u8981\u91cd\u542f] ConfigView.section.style.xulRunnerPath=\u624b\u52a8\u6307\u5b9a XulRunner / Firefox \u8def\u5f84 [\u5bf9\u4e8eFF3\u5fc5\u987b; \u9700\u8981\u91cd\u542f] azbuddy.name=\u597d\u53cb azbuddy.enabled=\u5141\u8bb8 azbuddy.disabled=\u63d2\u4ef6\u88ab\u7981\u7528, \u67e5\u770b\u63d2\u4ef6\u914d\u7f6e\u6765\u6539\u53d8\u6b64\u72b6\u6001\u3002 azbuddy.nickname=\u4f60\u7684\u6635\u79f0 azbuddy.msglog.title=\u597d\u53cb\u4fe1\u606f azbuddy.addtorrent.title=\u540c\u610f\u4e0b\u8f7d\uff1f azbuddy.addtorrent.msg=\u670b\u53cb '%1' \u5df2\u7ecf\u5411\u4f60\u53d1\u9001 '%2'.\n \u4f60\u60f3\u8981\u6dfb\u52a0\u6b64\u4e0b\u8f7d\u4e48? azbuddy.contextmenu=\u53d1\u9001\u7ed9\u670b\u53cb azbuddy.ui.mykey=\u6211\u7684 key: azbuddy.ui.add=\u6dfb\u52a0 azbuddy.ui.new_buddy=\u65b0\u597d\u53cb\u7684 key: azbuddy.ui.table.name=\u540d\u5b57 azbuddy.ui.table.online=\u5728\u7ebf azbuddy.ui.table.last_msg=\u6700\u65b0\u7684\u6d88\u606f azbuddy.ui.menu.remove=\u79fb\u9664 azbuddy.ui.menu.copypk=\u590d\u5236\u516c\u94a5 azbuddy.ui.menu.send=\u53d1\u9001\u6d88\u606f azbuddy.ui.menu.send_msg=\u8f93\u5165\u8981\u53d1\u9001\u7ed9\u4f60\u597d\u53cb(\u4eec)\u7684\u6587\u5b57 azbuddy.ui.menu.ygm=\u53d1\u9001 YGM azbuddy.ui.menu.enc=\u52a0\u5bc6\u526a\u8d34\u677f azbuddy.ui.menu.dec=\u89e3\u5bc6\u526a\u8d34\u677f azbuddy.ui.menu.sign=\u7b7e\u540d\u526a\u8d34\u677f azbuddy.ui.menu.verify=\u9a8c\u8bc1\u526a\u8d34\u677f azbuddy.ui.table.lastseen=\u6700\u8fd1\u4e00\u6b21\u9047\u89c1 Button.retry=\u91cd\u8bd5(R) Button.ignore=\u5ffd\u7565(I) azbuddy.ui.table.msg_in=\u63a5\u53d7\u7684\u6d88\u606f azbuddy.ui.table.msg_out=\u53d1\u9001\u7684\u6d88\u606f v3.MainWindow.menu.view.footer=\u811a\u6ce8 azbuddy.downspeed=KB/s \u6700\u5927\u597d\u53cb\u4e0b\u8f7d\u901f\u5ea6 [0: \u65e0\u9650\u5236] security.crypto.badpw=\u63d0\u4ea4\u7684\u5bc6\u7801\u4e0d\u6b63\u786e ConfigView.section.security.backupkeys=\u5c06 keys \u5907\u4efd\u5230\u6587\u4ef6 ConfigView.section.security.backupkeys.button=\u5907\u4efd ConfigView.section.security.restorekeys=\u4ece\u6587\u4ef6\u6062\u590d keys ConfigView.section.security.restorekeys.button=\u6062\u590d ConfigView.section.security.op.error.title=\u64cd\u4f5c\u5931\u8d25 ConfigView.section.security.op.error=\u65e0\u6cd5\u5b8c\u6210\u6b64\u64cd\u4f5c:\n %1 ConfigView.section.security.restart.title=\u9700\u8981\u91cd\u542f ConfigView.section.security.restart.msg=Vuze \u5c06\u8981\u91cd\u65b0\u542f\u52a8\u4ee5\u5b8c\u6210\u64cd\u4f5c ConfigView.section.security.system.managed=\u7cfb\u7edf\u7ba1\u7406 key \u4fdd\u62a4 azbuddy.ui.table.msg_queued=\u961f\u5217\u4e2d azbuddy.ui.menu.chat=\u804a\u5929 azbuddy.chat.title=Vuze \u804a\u5929 azbuddy.chat.says=%1 \u8bf4: Button.bar.show=\u5c55\u793a Button.bar.hide=\u9690\u85cf Button.bar.share=\u5206\u4eab Button.bar.add=\u6dfb\u52a0 Button.bar.edit=\u7f16\u8f91 Button.bar.edit.cancel=\u5b8c\u6210\u7f16\u8f91 v3.MainWindow.menu.view.pluginbar=\u63d2\u4ef6\u9762\u677f MainWindow.dialog.select.vuze.file=\u9009\u62e9 Vuze \u6587\u4ef6 MainWindow.menu.file.open.vuze=Vuze \u6587\u4ef6... metasearch.addtemplate.title=\u5b89\u88c5\u641c\u7d22\u6a21\u677f\uff1f metasearch.addtemplate.desc=\u4f60\u786e\u5b9a\u4f60\u60f3\u8981\u5b89\u88c5 '%1' \u7684\u641c\u7d22\u6a21\u677f\uff1f v3.share.private.title=\u5206\u4eab Torrent v3.share.private.text=\u6240\u9009\u7684 torrent \u88ab\u6807\u8bb0\u4e3a\u79c1\u6709 Torrent.\n\n\u60a8\u4e0d\u53ef\u4ee5\u5206\u4eab\u79c1\u6709 torrents\u3002 metasearch.addtemplate.dup.title=\u91cd\u590d\u7684\u6a21\u677f metasearch.addtemplate.dup.desc=\u641c\u7d22\u6a21\u677f %1 \u5df2\u7ecf\u5b89\u88c5\u4e86 metasearch.export.select.template.file=\u4fdd\u5b58\u6a21\u677f metasearch.import.select.template.file=\u6253\u5f00\u6a21\u677f dialog.uiswitch.title=\u5207\u6362\u5230 Vuze UI dialog.uiswitch.text=\u60a8\u9700\u8981\u8fd0\u884c\u4e2d\u7684 Vuze UI \u6765\u4f7f\u7528\u6b64\u529f\u80fd\n\nVuze \u5c06\u9700\u8981\u91cd\u65b0\u542f\u52a8 dialog.uiswitch.button=\u5207\u6362\u5230 Vuze UI azbuddy.tracker.enabled=\u542f\u7528 '\u597d\u53cb\u6367\u573a' \u6765\u901a\u8fc7\u597d\u53cb\u63d0\u5347\u4f60\u7684\u4e0b\u8f7d azbuddy.protocolspeed=KB/s \u6700\u5927\u597d\u53cb\u534f\u8bae\u603b\u5f00\u9500 v3.MainWindow.button.download=\u4e0b\u8f7d v3.MainWindow.button.run=\u542f\u52a8\u5df2\u4e0b\u8f7d\u7684\u6587\u4ef6 v3.activity.header.downloads=\u4e0b\u8f7d v3.activity.header.vuze.news=Vuze \u65b0\u95fb message.taking.too.long=\u5982\u679c\u6240\u82b1\u65f6\u95f4\u6bd4\u9884\u671f\u8981\u957f\u7684\u8bdd\n\u6309\u4e0b 'ESC' \u5165\u80a1\u4f60\u60f3\u8981\u53d6\u6d88\u6b64\u64cd\u4f5c message.status.success=\u6210\u529f azbuddy.tracker.bbb.status.title=\u597d\u53cb\u6367\u573a azbuddy.tracker.bbb.status.title.tooltip=\u53cc\u51fb\u67e5\u770b\u8be6\u60c5 azbuddy.tracker.bbb.status.idle=\u6ca1\u6709\u88ab\u6367\u573a azbuddy.tracker.bbb.status.nli=\u9700\u8981\u767b\u5f55 azbuddy.tracker.bbb.status.in=\u6211\u88ab\u6367\u573a\u5566 azbuddy.tracker.bbb.status.out=\u5f53\u524d\u6367\u573a\u7684\u597d\u53cb v3.MainWindow.search.go.tooltip=\u6267\u884c\u641c\u7d22 v3.MainWindow.search.last.tooltip=\u8fd4\u56de\u641c\u7d22\u7ed3\u679c metasearch.addtemplate.done.title=\u6dfb\u52a0\u7684\u6a21\u677f metasearch.addtemplate.done.desc=\u6a21\u677f '%1' \u6210\u529f\u6dfb\u52a0.\n\u5b83\u4f1a\u5728\u4f60\u4e0b\u6b21\u641c\u7d22\u65f6\u4f7f\u7528\uff01 ConfigView.section.security.nopw=\u6ca1\u6709\u63d0\u4f9b\u5bc6\u7801 ConfigView.section.security.nopw_v=\u6ca1\u6709\u53ef\u7528\u7684\u5bc6\u7801\uff0c\u8bf7\u4e0e Vuze \u7b7e\u540d fileplugininstall.install.title=\u5b89\u88c5\u63d2\u4ef6\uff1f fileplugininstall.install.desc=\u4f60\u786e\u5b9a\u8981\u5b89\u88c5\u63d2\u4ef6 '%1', \u7248\u672c %2 \u4e48\uff1f fileplugininstall.duplicate.title=\u91cd\u590d\u7684\u63d2\u4ef6 fileplugininstall.duplicate.desc=\u63d2\u4ef6 '%1', \u7248\u672c %2 \u5df2\u7ecf\u5b89\u88c5 azbuddy.online_status=\u5728\u7ebf\u72b6\u6001 azbuddy.os_online=\u4e0a\u7ebf azbuddy.os_away=\u79bb\u5f00 azbuddy.os_not_avail=\u4e0d\u53ef\u7528 azbuddy.os_busy=\u5fd9\u788c azbuddy.os_offline=\u79bb\u7ebf azbuddy.ui.menu.disconnect=\u65ad\u5f00\u94fe\u63a5 azbuddy.enable_chat_notif=\u5141\u8bb8\u804a\u5929\u63d0\u793a progress.window.msg.progress=\u8bf7\u7b49\u5f85\u64cd\u4f5c\u5b8c\u6210 DetailedListView.title=\u8be6\u60c5\u5217\u8868 ConfigView.section.connection.network.max.outstanding.connect.attempts=\u6700\u5927\u5bf9\u5916\u8fde\u63a5\u6570 plugins.init.force_enabled=Vuze \u68c0\u6d4b\u5230\u63d2\u4ef6 "%1" \u88ab\u7981\u7528 - \u5b83\u5df2\u7ecf\u88ab\u91cd\u65b0\u542f\u7528\u4ee5\u4fdd\u8bc1 Vuze \u6b63\u5e38\u5de5\u4f5c\u3002 ConfigView.section.connection.prefer.udp=\u4f18\u5148\u4f7f\u7528UDP\u8fde\u63a5 subscript.add.title=\u5b89\u88c5\u8ba2\u9605\uff1f subscript.add.desc=\u60a8\u786e\u5b9a\u60a8\u60f3\u8981\u5b89\u88c5\u8ba2\u9605 '%1'\uff1f subscript.add.dup.title=\u91cd\u590d\u7684\u8ba2\u9605 subscript.add.dup.desc=\u8ba2\u9605 '%1' \u5df2\u7ecf\u5b89\u88c5 subscript.add.upgrade.title=\u5347\u7ea7\u8ba2\u9605\uff1f subscript.add.upgrade.desc=\u60a8\u786e\u5b9a\u60a8\u60f3\u8981\u5347\u7ea7\u8ba2\u9605 '%1'\uff1f subscript.add.upgradeto.desc=\u8ba2\u9605 '%2' \u7684\u7248\u672c %1 \u5df2\u7ecf\u53ef\u7528\u3002\n\u60a8\u60f3\u8981\u5347\u7ea7\u4e48\uff1f azsubs.contextmenu.addassoc=\u6dfb\u52a0\u8ba2\u9605\u8054\u5408 azsubs.contextmenu.lookupassoc=\u67e5\u627e\u8ba2\u9605\u8054\u5408 iconBar.start=\u5f00\u59cb iconBar.stop=\u505c\u6b62 iconBar.remove=\u5220\u9664 iconBar.up=\u5411\u4e0a iconBar.down=\u5411\u4e0b iconBar.run=\u542f\u52a8 iconBar.editcolumns=\u5217\u8bbe\u7f6e iconBar.top=\u79fb\u5230\u9876\u7aef iconBar.bottom=\u79fb\u52a8\u6309\u94ae iconBar.queue=\u5f00\u59cb iconBar.open=\u6dfb\u52a0 Torrent iconBar.share=\u5206\u4eab iconBar.share.tooltip=\u5206\u4eab\u5185\u5bb9 iconBar.details=\u8be6\u60c5 iconBar.comment=\u8bc4\u8bba iconBar.play=\u64ad\u653e iconBar.queue.tooltip=\u961f\u5217 v3.MainWindow.menu.view.sidebar=\u4fa7\u9762\u677f v3.MainWindow.menu.view.actionbar=\u52a8\u4f5c\u680f v3.MainWindow.menu.view.toolbars=\u5de5\u5177\u680f ump.install=\u8fdb\u884c\u4e2d\u7684\u5feb\u901f\u66f4\u65b0:\n\u5b89\u88c5\u64ad\u653e\u6b64\u89c6\u9891\u6240\u9700\u7684\u4e00\u4e2a\u5c0f\u578b\u7684\u56de\u653e\u63d2\u4ef6\u3002 subscriptions.listwindow.title=\u8ba2\u9605\u67e5\u627e subscriptions.listwindow.autochecktext=Vuze \u53ef\u4ee5\u5bfb\u627e\u4e0e\u60a8\u5a92\u4f53\u5e93\u4e2d\u5185\u5bb9\u76f8\u5173\u7684\u8ba2\u9605\u3002\u60a8\u60f3\u8981\u542f\u7528\u6b64\u529f\u80fd\u4e48\uff1f subscriptions.listwindow.loadingtext=\u5bfb\u627e\u4e0e %1 \u76f8\u5173\u7684\u8ba2\u9605 subscriptions.listwindow.failed=\u6ca1\u6709\u53d1\u73b0\u8ba2\u9605 subscriptions.listwindow.popularity=\u6d41\u884c\u5ea6 subscriptions.listwindow.popularity.unknown=\u672a\u77e5 subscriptions.listwindow.name=\u540d\u5b57 subscriptions.listwindow.subscribe=\u8ba2\u9605 TableColumn.header.azsubs.ui.column.subs=\u8ba2\u9605 subscriptions.listwindow.popularity.reading=\u8bfb\u53d6... PluginDeprecation.log.start=\u8be5\u7a97\u53e3\u663e\u793a\u4e86\u4f7f\u7528\u5373\u5c06\u5728\u672a\u6765\u7248\u672c\u79fb\u9664\u7684\u529f\u80fd\u7684\u63d2\u4ef6\u4fe1\u606f\u3002\nY\u60a8\u4e0d\u9700\u8981\u5378\u8f7d\u8be5\u63d2\u4ef6\uff0c\u53ea\u9700\u8981\u66f4\u65b0\u63d2\u4ef6\u5230\u6700\u65b0\u7248\u672c\u3002\n\u5982\u679c\u60a8\u4ee5\u8bf6\u55ef\u5728\u4f7f\u7528\u6700\u65b0\u7248\u672c\uff0c\u8bf7\u590d\u5236\u672c\u7a97\u53e3\u7684\u5185\u5bb9\u5e76\u63d0\u4ea4\u81f3\u8bba\u575b\u6b64\u4f4d\u7f6e:\n \t%1\n\n PluginDeprecation.view=\u63d2\u4ef6 Debug PluginDeprecation.alert=\u4e00\u4e2a\u63d2\u4ef6\u5c1d\u8bd5\u4f7f\u7528\u4e00\u4e2a\u5373\u5c06\u88ab\u79fb\u9664\u7684\u529f\u80fd\u3002- \u8bf7\u6253\u5f00\u63d2\u4ef6 Debug \u65e5\u5fd7\u67e5\u770b\u66f4\u591a\u4fe1\u606f\u3002 TableColumn.header.Thumbnail=\u56fe\u6807 TableColumn.header.Thumbnail.info=\u7528\u4e8e Vuze \u7684\u7f29\u7565\u56fe\uff1b \u5bf9\u4e8e\u5176\u4ed6\u7684\u5185\u5bb9\u7531\u64cd\u4f5c\u7cfb\u7edf\u63d0\u4f9b\u8fd9\u4e9b\u56fe\u6807\u3002 v3.MainWindow.menu.getting_started=\u5f00\u59cb\u4f7f\u7528(G) MainWindow.menu.community=\u793e\u533a\uff08C\uff09 MainWindow.menu.help.faq=\u5e38\u89c1\u95ee\u9898\u89e3\u7b54\uff08&F\uff09 MainWindow.menu.community.wiki=\u793e\u533a\u7ef4\u57fa\uff08W\uff09 MainWindow.menu.community.forums=\u793e\u533a\u8bba\u575b\uff08R\uff09 MainWindow.menu.community.blog=Vuze \u535a\u5ba2\uff08B\uff09 MainWindow.menu.help.support=\u5e2e\u52a9\u548c\u652f\u6301(H) externalLogin.title=\u9700\u8981\u767b\u5f55 externalLogin.explanation=\u6a21\u677f "%1" \u9700\u8981\u60a8\u767b\u5f55\u3002\u4e00\u65e6\u767b\u5f55\u8be5\u7a97\u53e3\u4f1a\u81ea\u52a8\u5173\u95ed\u3002\u5982\u679c\u6ca1\u6709\u7684\u8bdd\u8bf7\u70b9\u51fb\u201c\u5b8c\u6210\u3002 externalLogin.explanation.capture=\u60a8\u9700\u8981\u767b\u5f55\u6765\u521b\u5efa\u6b64\u6a21\u677f\u3002\u4e00\u65e6\u60a8\u767b\u5f55\u4e86\uff0c\u8bf7\u70b9\u51fb\u201c\u5b8c\u6210\u201d Button.done=\u5b8c\u6210 GeneralView.torrent_created_on_and_by=%1 \u7531 %2 \u521b\u5efa Button.continue=\u7ee7\u7eed Button.preview=\u9884\u89c8 Subscription.menu.forcecheck=\u73b0\u5728\u66f4\u65b0 Subscription.menu.clearall=\u6807\u8bb0\u7ed3\u679c\u4e3a\u5df2\u8bfb Subscription.menu.remove=\u5220\u9664 sidebar.Library=\u6211\u7684\u5a92\u4f53\u5e93 sidebar.LibraryDL=\u4e0b\u8f7d\u4e2d sidebar.LibraryCD=\u5df2\u5b8c\u6210 authenticator.location=\u5730\u5740 authenticator.details=\u8be6\u60c5 v3.MainWindow.menu.showActionBarText=\u663e\u793a\u6587\u672c subscript.import.fail.title=\u5bfc\u5165\u5931\u8d25 subscript.import.fail.desc=\u8be6\u60c5: %1 Subscription.menu.export=\u5bfc\u51fa subscript.export.select.template.file=\u4fdd\u5b58\u8ba2\u9605 Button.remove=\u79fb\u9664 Button.send=\u53d1\u9001 Button.back=\u540e\u9000 sidebar.LibraryUnopened=\u672a\u89c2\u770b\u7684 TableColumn.header.unopened=\u65b0\u7684 Unopened.bigView.header=\u65b0\u5efa Subscription.menu.deleteall=\u5220\u9664\u6240\u6709\u7ed3\u679c Subscription.menu.reset=\u91cd\u7f6e\u81f3\u521d\u59cb\u72b6\u6001 ConfigView.section.Subscriptions=\u8ba2\u9605 subscriptions.config.maxresults=\u6bcf\u4e2a\u8ba2\u9605\u76f8\u5173\u7ed3\u679c\u7684\u6700\u5927\u6570 [0: \u65e0\u9650\u5236] v3.activity.button.readall=\u6807\u8bb0\u6240\u6709\u4e3a\u5df2\u8bfb TableColumn.header.activityNew=\u65b0\u5efa TableColumn.header.activityType=\u7c7b\u578b TableColumn.header.activityText=\u6d88\u606f TableColumn.header.activityDate=\u6dfb\u52a0\u7684\u65e5\u671f TableColumn.header.activityActions=\u52a8\u4f5c Subscription.menu.resetauth=\u91cd\u7f6e\u6388\u6743\u8be6\u60c5 Search.menu.engines=\u6a21\u677f Wizard.Subscription.title=\u8ba2\u9605 Wizard.Subscription.optin.title=\u542f\u7528\u8ba2\u9605 #what you've watched? Discover more with a single click... Wizard.Subscription.subscribe.title=\u53ef\u7528\u7684\u8ba2\u9605 Wizard.Subscription.create.title=\u521b\u5efa\u65b0\u7684\u8ba2\u9605 Button.search=\u641c\u7d22 Button.save=\u4fdd\u5b58 Button.add=\u6dfb\u52a0 Button.createNewSubscription=\u521b\u5efa\u65b0\u7684\u8ba2\u9605 Button.availableSubscriptions=\u53ef\u7528\u7684\u8ba2\u9605 Wizard.Subscription.optin.description=\u4e00\u65e6\u542f\u7528\u8ba2\u9605, Vuze \u5c06\u4f1a\u663e\u793a\u4e0e\u60a8\u5a92\u4f53\u5e93\u5185\u5bb9\u76f8\u5173\u7684\u8ba2\u9605\uff0c\u5e76\u5f53\u5b83\u4eec\u53ef\u4e0b\u8f7d\u65f6\u901a\u77e5\u60a8\u3002\n\n\u60a8\u60f3\u8981\u542f\u7528\u8ba2\u9605\u4e48\uff1f Wizard.Subscription.create.search=\u641c\u7d22 Wizard.Subscription.search.subtitle1=\u5728\u641c\u7d22\u4e2d\u8f93\u5165\u4e00\u4e2a\u8bcd\u6765\u521b\u5efa\u60a8\u7684\u8ba2\u9605 Wizard.Subscription.search.subtitle2=\u6211\u53ef\u4ee5\u641c\u7d22\u4ec0\u4e48\uff1f Wizard.Subscription.search.subtitle2.sub1=HD \u5f71\u7247, \u7535\u89c6\u8fde\u7eed\u5267, \u7535\u5f71, \u9884\u544a\u7247\u5c3d\u5728 Vuze Network Wizard.Subscription.search.subtitle2.sub2=\u4ece Web \u4e0a\u83b7\u5f97\u7684 Torrents Wizard.Subscription.search.subtitle3=\u4e00\u65e6\u60a8\u7684\u8ba2\u9605\u5b8c\u6210\uff0c\u5f53\u60a8\u7684\u641c\u7d22\u6709\u65b0\u7ed3\u679c\u65f6\u60a8\u5c31\u4f1a\u5728\u4fa7\u9762\u677f\u4e2d\u5f97\u5230\u5b9e\u65f6\u66f4\u65b0\u3002 Wizard.Subscription.rss.subtitle1=\u5728\u4e0b\u9762\u8f93\u5165\u6216\u7c98\u5e16 URL : Wizard.Subscription.rss.subtitle2=\u8bb8\u591a\u53d1\u5e03\u8005\u4e3a\u4ed6\u4eec\u7684\u5185\u5bb9\u63d0\u4f9b RSS \u8ba2\u9605\u3002\u5728\u53d1\u5e03\u8005\u7684\u7f51\u7ad9\u4e0a\u5b9a\u4f4d\u5230 URL\uff0c\u590d\u5236\u5e76\u7c98\u5e16\u5230\u4ee5\u4e0a\u7684\u533a\u57df\uff0c\u7136\u540e\u70b9\u51fb\u4fdd\u5b58\u3002 Wizard.Subscription.rss.subtitle3=\u4e00\u65e6\u4fdd\u5b58\uff0c\u60a8\u5c31\u53ef\u4ee5\u5728\u4fa7\u9762\u677f\u4e2d\u83b7\u5f97\u901a\u8fc7 RSS \u8ba2\u9605\u5f97\u5230\u7684\u5b9e\u65f6\u66f4\u65b0\u3002 Wizard.Subscription.subscribe.library=\u5a92\u4f53\u5e93\u4e2d\u7684\u5185\u5bb9 Wizard.Subscription.subscribe.subscriptions=\u76f8\u5173\u7684\u8ba2\u9605 Wizard.Subscription.subscribe.library.empty=\u6ca1\u6709\u53ef\u7528\u7684\u8ba2\u9605\uff1f\n \n\u627e\u627e Vuze HD Network \u4e0a\u4eae\u6a59\u8272\u7684\u8ba2\u9605\u6309\u94ae.\n \n\u66f4\u591a\u9605\u8bfb message.confirm.delete.title=\u5220\u9664\u786e\u8ba4 message.confirm.delete.text=\u4f60\u786e\u5b9a\u8981\u5220\u9664 '%1'? Subscription.menu.properties=\u5c5e\u6027 props.window.title='%1' \u5c5e\u6027 subs.prop.is_auto=\u81ea\u52a8\u4e0b\u8f7d\u65b0\u7ed3\u679c subs.prop.last_scan=\u4e0a\u4e00\u6b21\u6210\u529f\u7684\u66f4\u65b0 subs.prop.last_result=\u4e0a\u4e00\u6b21\u627e\u5230\u65b0\u7ed3\u679c subs.prop.last_error=\u4e0a\u4e00\u6b21\u9519\u8bef subs.prop.num_read=\u5df2\u8bfb\u7684\u7ed3\u679c\u6570 subs.prop.num_unread=\u672a\u8bfb\u7684\u7ed3\u679c\u6570 subs.prop.template=\u6a21\u677f subs.prop.auth=\u9700\u8981\u6388\u6743 externalLogin.auth_method_proxy=\u4f7f\u7528\u6269\u5c55\u7684 cookie \u6355\u6349\u65b9\u6cd5\u3002\u5982\u679c\u65e0\u6cd5\u5de5\u4f5c\uff0c\u7981\u7528\u8be5\u9009\u9879\u5e76\u91cd\u8bd5 externalLogin.wait=\u9875\u9762\u8f7d\u5165\uff0c\u8bf7\u7b49\u5f85... TableColumn.menu.date_added.time=\u663e\u793a/\u9690\u85cf\u65f6\u95f4 subs.prop.next_scan=\u4e0b\u4e00\u6b21\u641c\u7d22\u622a\u6b62 subs.prop.version=\u7248\u672c subscriptions.column.new.info=\u5982\u679c\u6709\u4e00\u4e2a\u6216\u591a\u4e2a\u65b0\u7ed3\u679c\u65f6\u6307\u51fa subscriptions.column.name=\u8ba2\u9605 subscriptions.column.nb-results=\u603b\u7ed3\u679c subscriptions.column.nb-new-results=\u65b0\u7ed3\u679c subscriptions.column.last-checked=\u4e0a\u4e00\u6b21\u68c0\u67e5 subscriptions.view.title=\u8ba2\u9605 subs.prop.is_public=\u516c\u5171 subs.prop.high_version=\u9047\u5230\u6700\u9ad8\u7248\u672c Subscription.menu.upgrade=\u542f\u7528\u5347\u7ea7\u81f3\u66f4\u9ad8\u7248\u672c\u3002 metasearch.template.version.bad=\u641c\u7d22\u6a21\u677f '%1' \u65e0\u6cd5\u5b89\u88c5\u9664\u975e\u60a8\u5347\u7ea7 Vuze metasearch.addtemplate.failed.title=\u5b89\u88c5\u5931\u8d25 metasearch.addtemplate.failed.desc=\u5b89\u88c5\u641c\u7d22\u6a21\u677f\u5931\u8d25: %1 subscription.version.bad=\u8ba2\u9605 '%1' \u65e0\u6cd5\u5b89\u88c5\u9664\u975e\u60a8\u5347\u7ea7 Vuze statusbar.feedback=\u53d1\u9001\u53cd\u9988\u4fe1\u606f statusbar.feedback.tooltip=\u70b9\u51fb\u8fd9\u91cc\u53d1\u9001\u53cd\u9988\u4fe1\u606f sidebar.Activity=\u63d0\u793a v3.activity.button.watchall=\u6807\u8bb0\u6240\u6709\u4e3a\u5df2\u770b subscriptions.view.help.1=\u6dfb\u52a0\u8ba2\u9605\u5230\u4f60\u6240\u770b\u7684\u4f4d\u7f6e subscriptions.view.help.2=\u5f53\u6709\u65b0\u5185\u5bb9\u53ef\u4ee5\u4e0b\u8f7d\u65f6\u83b7\u5f97\u5b9e\u65f6\u66f4\u65b0 \u66f4\u591a\u9605\u8bfb. sidebar.sash.tooltip=\u6309\u4e0b F7 \u5feb\u901f\u9690\u85cf/\u663e\u793a\u4fa7\u9762\u677f sidebar.expand.tooltip=\u6269\u5c55\u4fa7\u9762\u677f sidebar.dropdown.tooltip=\u4ee5\u83dc\u5355\u683c\u5f0f\u663e\u793a\u4fa7\u9762\u677f subscript.all.subscribed=\u60a8\u8ba2\u9605\u4e86\u8be5\u5185\u5bb9 subscript.some.subscribed=\u60a8\u8ba2\u9605\u4e86\u8be5\u5185\u5bb9\u7684\u90e8\u5206\u8ba2\u9605\u4fe1\u606f.\n\u70b9\u51fb\u8fd9\u91cc\u67e5\u770b\u5176\u4ed6\u53ef\u7528\u8ba2\u9605\u3002 subscript.none.subscribed=\u70b9\u51fb\u4ee5\u67e5\u770b\u5173\u4e8e\u5f53\u524d\u5185\u5bb9\u7684\u53ef\u7528\u8ba2\u9605 v3.iconBar.up.tooltip=\u5411\u4e0a\u79fb\u52a8\n\u6309\u4f4f\u9f20\u6807\u6309\u94ae\u4f7f\u5176\u79fb\u52a8\u5230\u9876\u7aef v3.iconBar.down.tooltip=\u5411\u4e0b\u79fb\u52a8\n\u6309\u4f4f\u9f20\u6807\u6309\u94ae\u4f7f\u5176\u79fb\u52a8\u5230\u5e95\u7aef TableColumn.header.azsubs.ui.column.subs_link=\u5173\u8054 TableColumn.header.azsubs.ui.column.subs_link.info=\u548c\u8ba2\u9605\u76f8\u5173\u8054\u7684 Button.deleteContent.fromLibrary=\u4ece\u5a92\u4f53\u5e93\u4e2d\u79fb\u9664 Button.deleteContent.fromComputer=\u4ece\u8ba1\u7b97\u673a\u4e2d\u5220\u9664 v3.deleteContent.message=\n\u60a8\u60f3\u8981\u4ece\u60a8\u7535\u8111\u4e2d\u5220\u9664 '%1' \uff0c\u8fd8\u662f\u4ec5\u4ec5\u60f3\u4ece Vuze \u5a92\u4f53\u5e93\u4e2d\u79fb\u9664\u5462\uff1f v3.MainWindow.menu.view.toolbartext=\u5de5\u5177\u680f\u6587\u672c v3.MainWindow.menu.view.asSimpleList=\u7b80\u6d01\u5217\u8868 v3.MainWindow.menu.view.asAdvancedList=\u9ad8\u7ea7\u5217\u8868 v3.MainWindow.menu.view.statusbar=\u72b6\u6001\u680f Subscription.menu.dirtyall=\u6807\u8bb0\u7ed3\u679c\u4e3a\u672a\u8bfb configureWizard.file.message3=Vuze \u4f1a\u628a\u4e0b\u8f7d\u7684\u6587\u4ef6\u4fdd\u5b58\u5728\u4e00\u4e2a\u6307\u5b9a\u7684\u6587\u4ef6\u4e2d\uff0c\u4f60\u53ef\u4ee5\u5728\u8fd9\u91cc\u9009\u62e9\uff1a v3.deleteContent.applyToAll=\u5bf9\u6240\u6709\u9009\u4e2d\u7684 %1 \u6267\u884c\u64cd\u4f5c v3.MainWindow.menu.contentnetworks=\u9ad8\u6e05\u7f51\u7edc\uff08&N\uff09 v3.MainWindow.menu.contentnetworks.about=\u5173\u4e8e\u9ad8\u6e05\u7f51\u7edc ConfigView.label.autoopen=\u81ea\u52a8\u6253\u5f00 ConfigView.label.autoopen.detailstab=\u81ea\u52a8\u6253\u5f00\u8be6\u60c5\u6807\u7b7e\u9875\u5f53 ConfigView.label.systray=\u7cfb\u7edf\u6258\u76d8 ConfigView.label.systray._mac=\u72b6\u6001\u680f\u56fe\u6807 v3.MainWindow.menu.contentnetworks.manage=\u7ba1\u7406\u9ad8\u6e05\u7f51\u7edc\uff08&M\uff09 azbuddy.ui.menu.cat=\u5206\u7c7b azbuddy.ui.menu.cat.share=\u542f\u7528\u6765\u81ea\u597d\u53cb\u7684\u8ba2\u9605 azbuddy.ui.menu.cat.set=\u8f93\u5165\u5206\u7c7b azbuddy.ui.menu.cat.set_msg=\u7528\u9017\u53f7\u5206\u9694\u7684\u5206\u7c7b\u5217\u8868\uff0c\u6216\u8005 'All' azbuddy.ui.menu.cat_subs=\u8ba2\u9605 v3.dialog.cnclose.title=%1 \u5173\u95ed v3.dialog.cnclose.subtitle=\u63d0\u793a v3.dialog.cnclose.info1=\u60a8\u5df2\u7ecf\u5173\u95ed\u4e86\u4e00\u4e2a\u9ad8\u6e05\u7f51\u7edc v3.dialog.cnclose.info2=\u5982\u679c\u60a8\u60f3\u8981\u91cd\u65b0\u6253\u5f00\u5f00\u8bf7\u7f51\u7edc\uff0c\u60a8\u53ef\u4ee5\u5728\u5c4f\u5e55\u4e0a\u65b9\u7684\u201c\u9ad8\u6e05\u7f51\u7edc\u201d\u83dc\u5355\u4e2d\u5b8c\u6210\u3002 v3.dialog.cnclose.noshow=\u4e0d\u8981\u518d\u663e\u793a v3.dialog.cnmanage.title=\u7ba1\u7406\u9ad8\u6e05\u7f51\u7edc\u83dc\u5355 v3.dialog.cnmanage.intro=\u60a8\u53ef\u4ee5\u4ece\u4ee5\u4e0b\u6e05\u5355\u4e2d\u9009\u62e9\u60a8\u5e0c\u671b\u663e\u793a\u5728\u201c\u9ad8\u6e05\u7f51\u7edc\u201d\u83dc\u5355\u4e2d\u7684\u7f51\u7edc\u5185\u5bb9 TableColumn.header.#.info=\u4f4d\u7f6e/\u6b21\u5e8f\u53f7 TableColumn.header.category.info=torrent \u6240\u5c5e\u7684\u5206\u7c7b\u540d TableColumn.header.DateCompleted.info=torrent \u4e0b\u8f7d\u5b8c\u6210\u7684\u65e5\u671f TableColumn.header.AzProduct.info=torrent \u6765\u81ea\u7684\u5185\u5bb9\u7f51\u7edc TableColumn.header.health.info=\u60a8\u5230 torrent \u7fa4\u7684\u94fe\u63a5\u5065\u5eb7\u5ea6\u5982\u4f55 TableColumn.header.maxuploads.info=\u540c\u65f6\u4e0a\u4f20\u7684\u6700\u5927 # peer \u6570 TableColumn.header.name.info=torrent \u7684\u540d\u5b57 TableColumn.header.unopened.info=\u663e\u793a torrent \u662f\u5426\u88ab\u64ad\u653e\u8fc7\uff08\u6253\u5f00\u8fc7\uff09\u7684\u6807\u8bc6\u7b26 TableColumn.header.savepath.info=torrent \u6570\u636e\u7684\u76ee\u6807\u6587\u4ef6\u5939\u6216\u6587\u4ef6 TableColumn.header.SeedingRank.info=\u6807\u8bc6\u8be5 torrent \u5728\u591a\u5927\u7a0b\u5ea6\u4e0a\u9700\u8981\u505a\u79cd\u3002\u8f83\u9ad8\u7684\u503c\u610f\u5473\u7740\u6709\u8f83\u5f3a\u7684\u9700\u8981\u3002 TableColumn.header.shareRatio.info=\u5c06\u60a8\u4e0a\u4f20\uff08\u5206\u4eab\uff09\u7684\u91cf\u4e0e\u4e0b\u8f7d\u7684\u91cf\u6bd4\u8f83 TableColumn.header.size.info=\u5728\u78c1\u76d8\u4e0a torrent \u5185\u5bb9\u6240\u5360\u7a7a\u95f4 TableColumn.header.azsubs.ui.column.subs.info=\u5141\u8bb8\u60a8\u8ba2\u9605\u5305\u542b\u76f8\u5173 torrents \u7684\u6309\u94ae TableColumn.header.upspeed.info=\u5f53\u524d\u4e0a\u4f20\u901f\u5ea6 TableColumn.header.downspeed.info=\u5f53\u524d\u4e0b\u8f7d\u901f\u5ea6 TableColumn.header.up.info=\u5f53\u524d\u53d1\u9001\u7ed9\u5176\u4ed6\u7528\u6237\u7684\u6570\u636e\u91cf TableColumn.header.down.info=\u5f53\u524d\u4ece\u5176\u4ed6\u7528\u6237\u83b7\u5f97\u7684\u6570\u636e\u91cf TableColumn.header.ProgressETA.info=\u5c06\u72b6\u6001\u3001\u5b8c\u6210\u5ea6\u3001\u5269\u4f59\u65f6\u95f4\u548c\u4e0b\u8f7d\u901f\u5ea6\u6574\u5408\u5230\u4e00\u4e2a\u591a\u7ebf\u680f\u4e2d TableColumn.header.eta.info=\u5230 torrent \u4e0b\u8f7d\u5b8c\u6210\u7684\u4f30\u8ba1\u65f6\u95f4 Pieces.column.#.info=\u5757\u7f16\u53f7 TableColumn.header.download.info=\u4ece peer \u83b7\u5f97\u7684\u6570\u636e\u91cf TableColumn.header.upload.info=\u53d1\u7ed9 epeer \u7684\u6570\u636e\u91cf TableColumn.header.downloadspeed.info=\u4ece peer \u63a5\u53d7\u7684\u901f\u5ea6 TableColumn.header.uploadspeed.info=\u7ed9 peer \u7684\u6570\u636e\u53d1\u9001\u901f\u5ea6 TableColumn.header.lan.info=\u663e\u793a Peer \u662f\u5426\u5728\u60a8\u5c40\u57df\u7f51\u4e2d\u7684\u6807\u8bc6\u7b26 TableColumn.header.downloadspeedoverall.info=\u4f30\u8ba1\u7684 peer \u4e0b\u8f7d\u901f\u5ea6 TableColumn.header.TableColumnNameInfo=\u680f\u540d\u79f0\u53ca\u8bf4\u660e TableColumn.header.TableColumnSample=\u6837\u4f8b TableColumn.header.TableColumnInfo=\u680f\u76ee\u8bf4\u660e TableColumn.header.TableColumnChosenColumn=\u9009\u4e2d\u7684\u680f label.learnmore=\u4e86\u89e3\u66f4\u591a ColumnSetup.title=\u5bf9 '%1' \u7684\u680f\u8bbe\u7f6e ColumnSetup.chosencolumns=\u9009\u5b9a\u7684\u680f ColumnSetup.categories=\u5206\u7c7b\uff1a ColumnSetup.filters=\u8fc7\u6ee4\u5668 ColumnSetup.availcolumns=\u53ef\u7528 %1 \u680f ColumnSetup.availcolumns.filteredby=\u7528 %2 \u8fc7\u6ee4\u540e\u7684\u53ef\u7528 %1 \u680f azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_zh_TW.properties0000644000175000017500000047524411301156004026142 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torrent \u6a94... Main.parameter.usage=\u7528\u6cd5 : java org.gudy.azureus2.cl.Main [\u53c3\u6578] "\u6a94\u6848\u540d.torrent" "\u4fdd\u5b58\u8def\u5f91" Main.parameter.maxUploads=\u6700\u5927\u540c\u6642\u4e0a\u50b3\u6578\u76ee Main.parameter.maxSpeed=\u6700\u5927\u4e0a\u50b3\u901f\u5ea6 bytes/sec MainWindow.menu.file=\u6a94\u6848 (&F) MainWindow.menu.file.open=\u958b\u555f (&O) MainWindow.menu.file.create=\u65b0\u589e Torrent... (&N) MainWindow.menu.file.create.fromfile=\u5f9e\u6a94\u6848 (&F) MainWindow.menu.file.create.fromdir=\u5f9e\u76ee\u9304 (&D) MainWindow.menu.file.export=\u532f\u51fa XML Torrent... (&E) MainWindow.menu.file.import=\u532f\u5165 XML Torrent... (&I) MainWindow.menu.file.closetab=\u95dc\u9589\u5206\u9801 (&T) MainWindow.menu.file.closewindow=\u95dc\u9589\u8996\u7a97 (&W) MainWindow.menu.file.exit=\u96e2\u958b (&X) MainWindow.dialog.choose.file=\u9078\u53d6 torrent \u6a94 MainWindow.menu.file.folder=\u8cc7\u6599\u593e... (&F) MainWindow.dialog.choose.folder=\u9078\u53d6\u542b\u6709 torrent \u6a94\u7684\u76ee\u9304 MainWindow.menu.view=\u6aa2\u8996 (&V) MainWindow.menu.view.show=\u986f\u793a MainWindow.menu.view.mytorrents=\u6211\u7684 Torrents (&M) MainWindow.menu.view.configuration=\u9078\u9805... (&O) MainWindow.menu.view.console=\u4e3b\u63a7\u53f0 (&O) MainWindow.menu.view.irc=IRC (&I) MainWindow.menu.closealldetails=\u95dc\u9589\u6240\u6709\u8a73\u7d30\u8cc7\u6599 (&A) MainWindow.menu.closealldownloadbars=\u95dc\u9589\u6240\u6709\u4e0b\u8f09\u6b04 (&B) MainWindow.menu.language=\u8a9e\u8a00 (&L) ConfigView.section.language=\u8a9e\u8a00 MainWindow.menu.window=\u8996\u7a97 (&W) MainWindow.menu.window.minimize=\u6700\u5c0f\u5316 (&M) MainWindow.menu.window.zoom=\u7e2e\u653e (&Z) MainWindow.menu.window.alltofront=\u5168\u90e8\u79fb\u81f3\u6700\u524d (&F) MainWindow.menu.help=\u8f14\u52a9\u8aaa\u660e (&H) MainWindow.menu.help.about=\u95dc\u65bc Vuze MainWindow.about.title=\u95dc\u65bc MainWindow.about.section.developers=\u958b\u767c\u5718\u968a MainWindow.about.section.translators=\u7ffb\u8b6f\u8005 MainWindow.about.section.system=\u7cfb\u7d71 MainWindow.about.section.internet=\u7db2\u969b\u7db2\u8def MainWindow.about.internet.homepage=Vuze \u9996\u9801 MainWindow.about.internet.sourceforge=\u958b\u653e\u539f\u59cb\u78bc\u9801\u9762 MainWindow.about.internet.sourceforgedownloads=\u958b\u653e\u539f\u59cb\u78bc\u4e0b\u8f09 MainWindow.about.internet.bugreports=\u932f\u8aa4\u56de\u5831 MainWindow.about.internet.forumdiscussion=\u8a0e\u8ad6\u5340 MainWindow.about.internet.wiki=Vuze Wiki \u5e38\u898b\u554f\u984c MainWindow.dialog.choose.savepath=\u9078\u53d6\u5132\u5b58\u8def\u5f91 MainWindow.dialog.choose.savepath_forallfiles=\u70ba\u6240\u6709\u6a94\u6848\u9078\u53d6\u5132\u5b58\u8def\u5f91 MainWindow.status.latestversion=\u6700\u65b0 MainWindow.status.latestversion.clickupdate=\u6309\u6b64\u66f4\u65b0 MainWindow.status.unknown=\u672a\u77e5 MainWindow.status.checking=\u6aa2\u67e5\u4e2d MyTorrentsView.mytorrents=\u6211\u7684 Torrents TableColumn.header.name=\u540d\u7a31 TableColumn.header.size=\u5927\u5c0f TableColumn.header.done=\u5df2\u5b8c\u6210 TableColumn.header.done.info=\u76ee\u524d\u5de5\u4f5c\u5b8c\u6210\u9032\u5ea6 TableColumn.header.status=\u72c0\u614b TableColumn.header.status.info=torrent \u6b63\u5728\u505a\u4ec0\u9ebc TableColumn.header.seeds=\u7a2e\u5b50 TableColumn.header.seeds.info=\u5df2\u9023\u7d50\u7684\u7a2e\u5b50\u6578 (\u7a2e\u5b50\u7684\u7e3d\u6578) TableColumn.header.peers=\u5925\u4f34 TableColumn.header.peers.info=\u5df2\u9023\u7d50\u5925\u4f34\u7684\u6578\u91cf (\u5925\u4f34\u5408\u8a08) TableColumn.header.downspeed=\u4e0b\u8f09\u901f\u5ea6 TableColumn.header.upspeed=\u4e0a\u50b3\u901f\u5ea6 TableColumn.header.eta=\u9810\u4f30\u5269\u4e0b\u6642\u9593 TableColumn.header.tracker=Tracker \u72c0\u614b TableColumn.header.tracker.info=Tracker \u72c0\u614b TableColumn.header.trackernextaccess=\u4e0b\u4e00\u500b Traccer \u5b58\u53d6 TableColumn.header.trackernextaccess.info=\u4e0b\u6b21 tracker \u5b58\u53d6\u6642\u9593 TableColumn.header.priority=\u512a\u5148\u9806\u5e8f TableColumn.header.priority.info=\u6307\u5b9a\u9019\u500b torrent \u53ef\u4f7f\u7528\u7684\u4e0a\u50b3\u983b\u5bec TableColumn.header.seeds.fullcopycalc=%2 \u63d0\u4f9b\u7d66 %1 \u5925\u4f34\u7684\u5b8c\u6574\u62f7\u8c9d\u6578\u76ee MyTorrentsView.menu.showdetails=\u986f\u793a\u7d30\u7bc0 (&D) MyTorrentsView.menu.showdownloadbar=\u986f\u793a\u4e0b\u8f09\u6b04 (&B) MyTorrentsView.menu.open=\u958b\u555f\u6a94\u6848 (&O) MyTorrentsView.menu.setpriority=\u8a2d\u5b9a\u512a\u5148\u9806\u5e8f (&P) MyTorrentsView.menu.setpriority.high=\u9ad8 (&H) MyTorrentsView.menu.setpriority.low=\u4f4e (&L) MyTorrentsView.menu.start=\u958b\u59cb (&S) MyTorrentsView.menu.stop=\u505c\u6b62 (&P) MyTorrentsView.menu.remove=\u79fb\u9664 (&R) MyTorrentsView.menu.changeTracker=\u52a0\u5165 Tracker URL (&A) TrayWindow.menu.exit=\u96e2\u958b (&X) TrayWindow.menu.show=\u986f\u793a Vuze (&S) SystemTray.menu.exit=\u96e2\u958b (&X) SystemTray.menu.closealldownloadbars=\u95dc\u9589\u6240\u6709\u4e0b\u8f09\u6b04\u4f4d (&A) SystemTray.menu.show=\u986f\u793a Vuze (&S) PeersView.ip=IP \u4f4d\u5740 PeersView.ip.info=\u5925\u4f34\u7684 IP PeersView.port=\u9023\u63a5\u57e0 PeersView.port.info=\u5df2\u4f7f\u7528\u7684\u9023\u63a5\u57e0\u865f PeersView.T=\u9023\u7dda\u985e\u578b PeersView.T.info=L (\u672c\u5730l): \u60a8\u5df2\u5efa\u7acb\u7684\u9023\u7dda, R (\u9060\u7aef): \u5925\u4f34\u5efa\u7acb\u7684\u9023\u7dda PeersView.T.L.tooltip=\u60a8\u5df2\u5efa\u7acb\u7684\u9023\u7dda PeersView.T.R.tooltip=\u5df2\u5efa\u7acb\u9023\u7dda\u7684\u5925\u4f34 PeersView.I1=I (\u5925\u4f34\u5c0d\u60a8\u7684\u8208\u8da3) PeersView.I1.info=\u60a8\u5c0d\u5925\u4f34\u7684\u6a94\u6848\u662f\u5426\u6709\u8208\u8da3 PeersView.C1=C (\u88ab\u5925\u4f34\u963b\u6b62) PeersView.C1.info=\u5925\u4f34\u662f\u5426\u963b\u6b62\u60a8\u4e0b\u8f09 PeersView.pieces=\u6a94\u6848\u5206\u584a PeersView.%=% \u767e\u5206\u6bd4 PeersView.downloadspeed=\u4e0b\u8f09\u901f\u5ea6 PeersView.download=\u4e0b\u8f09 PeersView.I2=I (\u5c0d\u5925\u4f34\u7684\u8208\u8da3) PeersView.I2.info=\u5925\u4f34\u5c0d\u60a8\u7684\u6a94\u6848\u662f\u5426\u6709\u8208\u8da3? PeersView.C2=C (\u963b\u6b62\u5925\u4f34) PeersView.C2.info=\u60a8\u662f\u5426\u963b\u6b62\u5925\u4f34\u4e0b\u8f09 PeersView.uploadspeed=\u4e0a\u50b3\u901f\u5ea6 PeersView.uploadspeed.info=\u60a8\u6b63\u5728\u4e0a\u50b3\u7d66\u5925\u4f34\u7684\u901f\u5ea6 PeersView.upload=\u4e0a\u50b3 PeersView.upload.info=\u60a8\u4e0a\u50b3\u7d66\u5925\u4f34\u7684\u6574\u9ad4\u901f\u5ea6 PeersView.statup=\u4e0a\u50b3\u7d71\u8a08 PeersView.statup.info=\u4e0a\u50b3\u7d66\u5925\u4f34\u7684\u9810\u4f30\u901f\u5ea6 PeersView.S=\u72c0\u614b PeersView.S.info=\u5c01\u9396: \u53ef\u4ee5\u624b\u52d5\u5c01\u9396\u5925\u4f34, \u6216\u662f\u81ea\u52d5\u5c01\u9396 (\u91dd\u5c0d\u6c92\u6709\u8db3\u5920\u5206\u4eab\u7387\u7684\u5925\u4f34) PeersView.downloadspeedoverall=\u6574\u9ad4\u4e0b\u8f09\u901f\u5ea6 PeersView.optunchoke=\u89e3\u9664\u5c01\u9396 PeersView.client=\u7528\u6236\u7aef PeersView.client.info=\u5925\u4f34\u4f7f\u7528\u7684 BT \u8edf\u9ad4\u7a2e\u985e PeersView.menu.snubbed=\u5c01\u9396 (&S) PeersView.title.short=\u5925\u4f34 PeersView.title.full=\u5925\u4f34 ConfigView.section.files=\u6a94\u6848 ConfigView.label.usefastresume=\u4f7f\u7528\u5feb\u901f\u7e8c\u50b3\u6a21\u5f0f ConfigView.label.incrementalfile=\u555f\u52d5\u6f38\u589e\u6a94\u6848\u5927\u5c0f\u7684\u529f\u80fd [\u9700\u8981 Linux \u7684 FAT32 \u6a94\u6848\u7cfb\u7d71] ConfigView.label.defaultsavepath=\u5b58\u6a94\u81f3\u9810\u8a2d\u7684\u8cc7\u6599\u76ee\u9304 ConfigView.button.browse=\u700f\u89bd... (&B) ConfigView.dialog.choosedefaultsavepath=\u8acb\u9078\u64c7\u9810\u8a2d\u7684\u5b58\u6a94\u76ee\u9304 ConfigView.section.server=\u9023\u7dda ConfigView.section.global=\u4e00\u822c ConfigView.label.disconnetseed=\u505a\u7a2e\u6642\u5207\u65b7\u548c\u5176\u4ed6\u7a2e\u5b50\u7684\u9023\u7dda ConfigView.label.switchpriority=\u505a\u7a2e\u6642\uff0c\u81ea\u52d5\u8f49\u70ba\u4f4e\u512a\u5148\u6b0a ConfigView.label.maxdownloads=\u540c\u6642\u9593\u4e0b\u8f09\u7684\u6700\u5927\u9023\u7dda\u6578 [0\uff1a\u7121\u9650\u5236] \n - \u4e0d\u53ef\u5927\u65bc\u6700\u5927\u7684\u6d3b\u52d5\u4e2d torrents \u6578\u91cf ConfigView.label.maxdownloads.tooltip=\u60a8\u53ef\u4ee5\u5728\u6b64\u6307\u5b9a\u4e0b\u8f09\u6d3b\u52d5\u7684\u6578\u76ee \n \u7b26\u5408\u6700\u9ad8\u512a\u5148\u9806\u5e8f\u689d\u4ef6\u7684 torrent \u6703\u53d6\u4ee3\u5176\u4ed6\u6d3b\u52d5\u4e2d\u7684 torrent ConfigView.label.maxactivetorrents=\u6700\u5927\u7684\u6d3b\u52d5\u4e2d torrent \u6578\u91cf [0\uff1a\u7121\u9650\u5236]\n - \u7576\u60a8\u4e0b\u8f09/\u505a\u7a2e\u8d85\u904e\u9019\u500b\u6578\u91cf\uff0c\u65b0\u7684 torrent \u5c07\u4e0d\u6703\u555f\u52d5 ConfigView.label.priorityExtensions=\u526f\u6a94\u540d\u70ba\u4ee5\u4e0b\u7684\u6a94\u6848\u8a2d\u70ba\u9ad8\u512a\u5148\u9806\u5e8f \n - eg: .txt;.nfo;.jpg ConfigView.section.transfer=\u50b3\u8f38 ConfigView.label.maxuploads=\u6bcf\u500b torrent \u9810\u8a2d\u7684\u6700\u5927\u4e0a\u50b3\u6578 ConfigView.label.maxuploadspeed=\u6574\u9ad4\u6700\u5927\u4e0a\u50b3\u901f\u5ea6 (KB/s) [0\uff1a\u7121\u9650\u5236] ConfigView.label.saveresumeinterval=\u66f4\u65b0\u7e8c\u50b3\u8cc7\u6599\u7684\u9593\u9694\u6642\u9593 ConfigView.unlimited=\u7121\u9650\u5236 ConfigView.section.display=\u986f\u793a ConfigView.label.opendetails=\u81ea\u52d5\u958b\u555f"\u8a73\u7d30\u8cc7\u8a0a" ConfigView.label.openbar=\u81ea\u52d5\u958b\u555f\u4e0b\u8f09\u6b04 ConfigView.label.closetotray=\u95dc\u9589\u6642\u6700\u5c0f\u5316\u81f3\u7cfb\u7d71\u5217 ConfigView.label.minimizetotray=\u6700\u5c0f\u5316\u6642\u7e2e\u5c0f\u81f3\u7cfb\u7d71\u5217 ConfigView.section.general=\u4e00\u822c ConfigView.section.start=\u958b\u59cb ConfigView.label.showsplash=\u986f\u793a\u555f\u52d5\u756b\u9762 ConfigView.label.autoupdate=\u7576\u6709\u65b0\u7248\u672c\u7684\u6642\u5019\u958b\u555f\u5347\u7d1a\u5c0d\u8a71\u8996\u7a97\u3002 ConfigView.label.openconsole=\u555f\u52d5\u6642\u958b\u555f"\u63a7\u5236\u53f0" ConfigView.label.openconfig=\u555f\u52d5\u6642\u958b\u555f"\u9078\u9805" ConfigView.label.startminimized=\u555f\u52d5\u6642\u6700\u5c0f\u5316 ConfigView.section.irc=IRC \u804a\u5929 ConfigView.label.ircwiki=\u8acb\u53c3\u7167 http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=\u4f3a\u670d\u5668 ConfigView.label.ircchannel=\u983b\u9053 ConfigView.label.irclogin=\u66b1\u7a31 ConfigView.group.irctitle=IRC \u8a2d\u5b9a ConfigView.boolean.ircsendinfo=\u5141\u8a31\u533f\u540d\u5bc4\u9001\u60a8\u7684\u8a2d\u5b9a\u7d66\u983b\u9053\u7ba1\u7406\u8005\u4ee5\u7372\u5f97\u9032\u4e00\u6b65\u7684\u5354\u52a9\u3002 ConfigView.boolean.irclog=\u555f\u52d5\u983b\u9053\u5c0d\u8a71\u8a18\u9304 (\u5b58\u5728 IRC_log.htm) ConfigView.section.security=\u5b89\u5168\u6027 ConfigView.label.password=\u4f7f\u7528\u5bc6\u78bc\u4fdd\u8b77 Vuze \n - \u958b\u555f\u6642\u6703\u8a62\u554f\u5bc6\u78bc ConfigView.label.passwordconfirm=\u5bc6\u78bc (\u78ba\u8a8d) ConfigView.label.passwordmatch=\u5bc6\u78bc\u6b63\u78ba : ConfigView.label.passwordmatchnone=\u4e0d\u6b63\u78ba ConfigView.label.passwordmatchno=\u5bc6\u78bc\u4e0d\u6b63\u78ba ConfigView.label.passwordmatchyes=\u6b63\u78ba ConfigView.button.save=\u5132\u5b58 ConfigView.title.short=\u9078\u9805 ConfigView.title.full=\u9078\u9805 ConsoleView.title.short=\u4e3b\u63a7\u53f0 ConsoleView.title.full=\u4e3b\u63a7\u53f0 FileItem.write=\u5beb FileItem.read=\u8b80 FileItem.normal=\u6b63\u5e38 FileItem.high=\u9ad8 FileItem.donotdownload=\u4e0d\u8981\u4e0b\u8f09 FilesView.name=\u540d\u7a31 FilesView.size=\u5927\u5c0f FilesView.done=\u5b8c\u6210 FilesView.%=\u767e\u5206\u6bd4 FilesView.firstpiece=\u8d77\u59cb\u6a94\u6848\u5206\u584a\u7de8\u865f FilesView.numberofpieces=\u6a94\u6848\u5206\u584a\u7de8\u865f FilesView.pieces=\u6a94\u6848\u5206\u584a FilesView.mode=\u6a21\u5f0f FilesView.priority=\u512a\u5148\u9806\u5e8f FilesView.menu.open=\u6253\u958b (&O) FilesView.menu.setpriority=\u8a2d\u5b9a\u512a\u5148\u9806\u5e8f (&S) FilesView.menu.setpriority.high=\u9ad8 (&H) FilesView.menu.setpriority.normal=\u6b63\u5e38 (&N) FilesView.menu.setpriority.skipped=\u4e0d\u8981\u4e0b\u8f09 (&D) FilesView.title.short=\u6a94\u6848 FilesView.title.full=\u6a94\u6848 GeneralView.section.downloaded=\u5df2\u4e0b\u8f09 GeneralView.label.status.file=\u6a94\u6848\u72c0\u614b GeneralView.label.status.pieces=\u6a94\u6848\u5206\u584a\u72c0\u614b GeneralView.section.availability=\u53ef\u7528\u5ea6 GeneralView.label.status.pieces_available=\u6a94\u6848\u5206\u584a\u72c0\u614b GeneralView.section.transfer=\u50b3\u8f38 GeneralView.section.info=\u8cc7\u8a0a GeneralView.title.short=\u4e00\u822c GeneralView.title.full=\u4e00\u822c GeneralView.label.timeelapsed=\u7d93\u904e\u6642\u9593\uff1a GeneralView.label.remaining=\u672a\u5b8c\u6210\uff1a GeneralView.label.downloaded=\u5df2\u4e0b\u8f09 : GeneralView.label.downloadspeed=\u4e0b\u8f09\u901f\u5ea6 : GeneralView.label.maxuploads=\u6700\u5927\u4e0a\u50b3\u6578\u76ee : GeneralView.label.maxuploads.tooltip=\u540c\u6642\u9593\u5167\u4e0d\u6703\u88ab\u963b\u64cb\u7684\u6700\u5927\u5925\u4f34\u6578\u76ee GeneralView.label.uploaded=\u5df2\u4e0a\u50b3\uff1a GeneralView.label.uploadspeed=\u4e0a\u50b3\u901f\u5ea6\uff1a GeneralView.label.seeds=\u7a2e\u5b50\uff1a GeneralView.label.peers=\u5925\u4f34\uff1a GeneralView.label.totalspeed=Swarm \u901f\u5ea6\uff1a GeneralView.label.totalspeed.tooltip=\u6240\u6709\u60a8\u5df2\u9023\u7d50\u7684\u7528\u6236\u7aef\u5168\u90e8\uff08\u4ee5\u53ca\u5e73\u5747\uff09\u901f\u5ea6 GeneralView.label.averagespeed=\u5e73\u5747 GeneralView.label.filename=\u540d\u7a31 : GeneralView.label.totalsize=\u5168\u90e8\u5927\u5c0f\uff1a GeneralView.label.savein=\u5132\u5b58\u65bc\uff1a GeneralView.label.hash=Hash\uff1a GeneralView.label.numberofpieces=\u6a94\u6848\u5206\u584a\u6578\uff1a GeneralView.label.size=\u5927\u5c0f\uff1a GeneralView.label.tracker=Tracker \u72c0\u614b\uff1a GeneralView.label.updatein=\u66f4\u65b0\u65bc\uff1a GeneralView.label.trackerurl=Tracker URL\uff1a GeneralView.label.trackerurlupdate=\u66f4\u65b0 Tracker GeneralView.label.comment=\u8a3b\u89e3 ManagerItem.waiting=\u7b49\u5f85\u4e2d ManagerItem.allocating=\u6e96\u5099\u4e2d ManagerItem.checking=\u6aa2\u67e5\u4e2d ManagerItem.ready=\u7b49\u5f85\u53e6\u4e00\u500b torrernts \u6392\u7a0b ManagerItem.downloading=\u4e0b\u8f09\u4e2d ManagerItem.seeding=\u505a\u7a2e ManagerItem.stopped=\u5df2\u505c\u6b62 ManagerItem.error=\u932f\u8aa4 ManagerItem.high=\u9ad8 ManagerItem.low=\u4f4e MinimizedWindow.name=\u540d\u7a31 PiecesView.#=\u7de8\u865f PiecesView.size=\u5927\u5c0f PiecesView.numberofblocks=\u5340\u584a\u7de8\u865f PiecesView.blocks=\u5340\u584a PiecesView.completed=\u5b8c\u6210 PiecesView.availability=\u53ef\u7528\u5ea6 PiecesView.reservedby=\u9810\u5148\u8a2d\u7f6e PiecesView.writers=\u5340\u6bb5\u63d0\u4f9b\u8005 PiecesView.title.short=\u6a94\u6848\u5206\u584a PiecesView.title.full=\u6a94\u6848\u5206\u584a SystemTray.tooltip.seeding=%1 \u505a\u7a2e\u4e2d, SystemTray.tooltip.downloading=%1 \u4e0b\u8f09\u4e2d, DownloadManager.error.filenotfound=\u672a\u767c\u73fe\u6a94\u6848 DownloadManager.error.fileempty=Torrent \u6a94\u662f\u7a7a\u7684 DownloadManager.error.filetoobig=Torrent \u6a94\u592a\u5927 DownloadManager.error.filewithouttorrentinfo=\u6a94\u6848\u4e2d\u672a\u767c\u73fe Torrent \u8cc7\u8a0a DownloadManager.error.unsupportedencoding=\u4e0d\u652f\u63f4\u7684\u7de8\u78bc\u65b9\u5f0f DownloadManager.error.ioerror=IO \u932f\u8aa4 DownloadManager.error.sha1=\u7121\u6b64\u6f14\u7b97\u6cd5 (SHA1) \u932f\u8aa4 PeerManager.status.offline=\u9023\u7dda\u932f\u8aa4 PeerManager.status.ok=\u78ba\u5b9a PeerManager.status.checking=\u6aa2\u67e5\u4e2d PeerManager.status.finished=\u5df2\u5b8c\u6210 PeerManager.status.finishedin=\u5b8c\u6210\u65bc: MainWindow.upgrade.assistant=\u66f4\u65b0\u5c0f\u5e6b\u624b MainWindow.upgrade.newerversion=\u6709\u65b0\u7248\u672c\u7684 Vuze \u53ef\u4f9b\u4e0b\u8f09 MainWindow.upgrade.explanation=\u9019\u500b\u5c0f\u5e6b\u624b\u5c07\u6703\u4e0b\u8f09\u65b0\u7248\u7684 Vuze \u5230\u60a8\u7684\u8cc7\u6599\u593e\u4e26\u91cd\u65b0\u555f\u52d5 MainWindow.upgrade.explanation.manual=\u60a8\u53ef\u4ee5\u624b\u52d5\u66f4\u65b0, \u53ea\u8981\u95dc\u9589 Vuze \u4e0b\u8f09\u65b0\u7248\u672c\u5f8c\u91cd\u65b0\u555f\u52d5 Vuze \u5373\u53ef MainWindow.upgrade.step1=Step 1: \u4e0b\u8f09\u65b0\u7248\u672c MainWindow.upgrade.step2=Step 2: \u95dc\u9589\u9019\u500b\u7248\u672c\u4e26\u91cd\u65b0\u555f\u52d5 Vuze MainWindow.upgrade.hint1=\u63d0\u793a:\t\u6309\u4e0b\u7d50\u675f\u5f8c,\u6240\u6709\u5de5\u4f5c\u6703\u81ea\u52d5\u5b8c\u6210 MainWindow.upgrade.hint2=\u63d0\u793a:\t\u5982\u679c\u60a8\u60f3\u8981\u7a0d\u5f8c\u518d\u95dc\u9589 Vuze \u6309\u4e0b"\u53d6\u6d88"\u7136\u5f8c\u5728\u95dc\u9589\n\t Vuze \u4e4b\u5f8c,\u5c07 Azureus2-new.jar \u6539\u540d\u70ba Azureus2.jar MainWindow.upgrade.error.downloading.hint=\u932f\u8aa4:\t\u7121\u6cd5\u4e0b\u8f09\u65b0\u7248\u672c,\u8acb\u4f7f\u7528\u624b\u52d5\u66f4\u65b0 MainWindow.upgrade.section.info=\u6709\u65b0\u7684\u7248\u672c\u53ef\u7528 MainWindow.upgrade.section.manual=\u624b\u52d5\u66f4\u65b0 MainWindow.upgrade.section.automatic=\u81ea\u52d5\u66f4\u65b0 MainWindow.upgrade.tooltip.progressbar=\u4e0b\u8f09\u72c0\u6cc1\u5728\u6b64\u986f\u793a Button.next=\u4e0b\u4e00\u500b Button.finish=\u7d50\u675f Button.cancel=\u53d6\u6d88 LocaleUtil.title=\u9078\u64c7\u7de8\u78bc LocaleUtil.section.chooseencoding=\u70ba\u6a94\u6848\u540d\u7a31\u9078\u64c7\u7de8\u78bc\u65b9\u5f0f LocaleUtil.label.chooseencoding=\u8acb\u9078\u64c7\u6700\u9069\u5408\u7684\u7de8\u78bc\u65b9\u5f0f LocaleUtil.label.hint.doubleclick=\u63d0\u793a: \u96d9\u64ca\u4e00\u4e0b\u5217\uff0c\u9078\u64c7\u7de8\u78bc\u6a21\u5f0f\u4e26\u95dc\u9589\u5c0d\u8a71\u8996\u7a97 LocaleUtil.label.checkbox.rememberdecision=\u8a18\u4f4f\u672a\u5b8c\u6210\u7684\u6a94\u6848\u540d\u7a31\u9078\u64c7 LocaleUtil.column.encoding=\u7de8\u78bc\u4e2d IrcClient.copyright=\u4f7f\u7528 PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=\u9023\u7dda\u4e2d IrcClient.connected=\u9023\u7dda\u81f3 IrcClient.joining=\u52a0\u5165\u4e2d IrcClient.channel=\u983b\u9053 IrcClient.joined=\u52a0\u5165 IrcClient.error=\u932f\u8aa4 IrcClient.hasjoined=\u5df2\u7d93\u52a0\u5165 IrcClient.haskicked=\u5df2\u7d93\u88ab\u8e22\u51fa IrcClient.hasleft=\u5df2\u7d93\u96e2\u958b IrcClient.nowknown=\u73fe\u5728\u7684\u540d\u7a31\u662f IrcClient.topicforchannel=\u983b\u9053\u7684\u4e3b\u984c IrcClient.disconnected=\u65b7\u7dda IrcClient.noNick=\u6c92\u6709\u6307\u5b9a\u66b1\u7a31\u3002\u8acb\u5bdf\u770b"\u9078\u9805" IrcView.actionnotsupported=\u9019\u500b\u52d5\u4f5c\u4e0d\u88ab\u652f\u63f4 IrcView.clientsconnected=\u4f7f\u7528\u8005 IrcView.privateto=\u5230 IrcView.privatefrom=\u5f9e IrcView.noticefrom=\u6ce8\u610f\uff1a IrcView.errormsg=/msg \u7684\u8a9e\u6cd5\u932f\u8aa4\uff1a/msg \u4f7f\u7528\u8005\u540d \u6587\u5b57 IrcView.help=\u6709\u6548\u7684\u6307\u4ee4\uff1a\n . /help : \u986f\u793a\u672c\u6bb5\u8a0a\u606f\n . /nick | /name : \u6539\u8b8a\u60a8\u7684\u540d\u7a31 \n . /me action : \u9001\u521d\u4e00\u500b\u52d5\u4f5c \n . /msg nick message : \u9001\u51fa\u6084\u6084\u8a71\u7d66\u67d0\u4eba\n . /r message : \u56de\u61c9\u4e0a\u500b\u6084\u6084\u8a71\n . /join #channelB \uff08\u4e0d\u8981\u9ede\u9078\u9019\u88e1\uff0c\u9019\u53ea\u662f\u7bc4\u4f8b\uff09\uff1a\u52a0\u5165\u53e6\u4e00\u500b\u983b\u9053 PasswordWindow.title=Vuze \u5df2\u9396\u5b9a PasswordWindow.passwordprotected=Vuze \u5df2\u53d7\u5230\u5bc6\u78bc\u4fdd\u8b77\n\u60f3\u8981\u986f\u793a Vuze \u8996\u7a97,\u8acb\u5728\u9019\u908a\u8f38\u5165\u5bc6\u78bc : Button.ok=\u78ba\u5b9a TrackerChangerWindow.title=\u52a0\u5165 Tracker TrackerChangerWindow.newtracker=\u8f38\u5165\u65b0\u7684 tracker \u4f4d\u5740 PeersView.discarded=\u4e1f\u68c4 PeersView.discarded.info=\u4e1f\u68c4\u60a8\u5df2\u63a5\u6536,\u4f46\u662f\u4e0d\u9700\u8981\u7684\u6a94\u6848 discarded=\u4e1f\u68c4 MyTorrentsView.#=\u7de8\u865f MyTorrentsView.menu.move=\u79fb\u52d5 (&M) MyTorrentsView.menu.moveUp=\u4e0a\u79fb (&U) MyTorrentsView.menu.moveDown=\u4e0b\u79fb (&D) GeneralView.label.hashfails=Hash \u932f\u8aa4 : GeneralView.label.shareRatio=\u5206\u4eab\u7387\uff1a ConfigView.section.downloadManagement=\u4e0b\u8f09\u7ba1\u7406 ConfigView.label.startRatioPeers=\u7576\u7a2e\u5b50\u6578\u5c0f\u65bc 1 \u6642\uff0c\u958b\u59cb\u505a\u7a2e ConfigView.text.neverStop=\u6c38\u4e0d\u505c\u6b62 ConfigView.text.neverStart=\u6c38\u4e0d\u555f\u52d5 ConfigView.text.peers=\u5925\u4f34 ConfigView.label.checkOncompletion=\u7576\u4e0b\u8f09\u5b8c\u7562\uff0c\u518d\u6b21\u6aa2\u67e5\u6a94\u6848\u584a\u3002 wizard.title=\u88fd\u4f5c Torrent wizard.previous=< \u4e0a\u4e00\u6b65 wizard.next=\u4e0b\u4e00\u6b65 > wizard.finish=\u5b8c\u6210 wizard.mode=Tracker / \u6a21\u5f0f wizard.tracker=Tracker: wizard.invalidurl=\u9019\u662f\u7121\u6548\u7684 URL \u4f4d\u5740 wizard.singlefile=\u55ae\u4e00\u6a94\u6848 wizard.singlefile.help=\u5f9e\u55ae\u4e00\u6a94\u6848\u5efa\u7acb Torrent \u6a94 wizard.directory=\u76ee\u9304 wizard.directory.help=\u5f9e\u76ee\u9304\u5efa\u7acb Torrent \u6a94 wizard.choosefile=\u9078\u64c7\u6a94\u6848 wizard.file=\u6a94\u6848: wizard.browse=\u700f\u89bd... wizard.choosedirectory=\u9078\u64c7\u76ee\u9304 wizard.invalidfile=\u9019\u662f\u7121\u6548\u7684\u6a94\u6848 wizard.invaliddirectory=\u9019\u662f\u7121\u6548\u7684\u76ee\u9304 wizard.torrentFile=Torrent \u6a94 wizard.choosetorrent=\u8acb\u9078\u64c7\u8981\u5efa\u7acb\u7684 torrent \u6a94 wizard.information=\u8cc7\u8a0a wizard.notimplemented=\u5c1a\u672a\u5be6\u884c wizard.progresstitle=\u5efa\u7acb\u4e00\u500b Torrent \u6a94 wizard.savingfile=\u6a94\u6848\u5132\u5b58\u4e2d wizard.filesaved=\u6a94\u6848\u5df2\u5132\u5b58 wizard.close=\u95dc\u9589 Torrent.create.progress.piecelength=\u6a94\u6848\u5206\u584a\u9577\u5ea6: Torrent.create.progress.piececount=\u6a94\u6848\u5206\u584a\u6578\u91cf: Torrent.create.progress.totalfilesize=\u6240\u6709\u6a94\u6848\u5927\u5c0f: Torrent.create.progress.totalfilecount=\u6240\u6709\u6a94\u6848\u5408\u8a08\u6578\u91cf: Torrent.create.progress.parsingfiles=\u6a94\u6848\u5206\u6790\u4e2d Torrent.create.progress.hashing=Hashing \u6a94\u6848\u8655\u7406\u4e2d MainWindow.upgrade.downloadingfrom=\u6b63\u5728\u4e0b\u8f09\u81ea : MainWindow.menu.view.ipFilter=IP \u904e\u6ffe\u5668 (&I) ConfigView.section.ipfilter=IP \u904e\u6ffe\u5668 ConfigView.section.ipfilter.description=\u8aaa\u660e ConfigView.section.ipfilter.start=IP \u8d77\u59cb ConfigView.section.ipfilter.end=IP \u7d50\u5c3e ConfigView.section.ipfilter.add=\u52a0\u5165 ConfigView.section.ipfilter.remove=\u79fb\u9664 ConfigView.section.ipfilter.edit=\u7de8\u8f2f ConfigView.section.ipfilter.save=\u5132\u5b58 ConfigView.section.ipfilter.editFilter=\u7de8\u8f2f\u904e\u6ffe\u5668 ConfigView.section.ipfilter.enable=\u555f\u7528 PeersView.menu.close=\u95dc\u9589 (&C) seedmore.title=Torrent \u505a\u7a2e\u7684\u6642\u9593\u4e0d\u5920 seedmore.shareratio=\u60a8\u5728\u9019\u500b torrent \u7684\u5206\u4eab\u7387\u662f seedmore.uploadmore=\u5728 BT \u7db2\u8def\u4e0a\u64c1\u6709\u4f4e\u65bc 100% \u7684\u5206\u4eab\u7387\u662f\u5f88\u4f4e\u7d1a\u7684\u884c\u70ba.\n\u61c9\u8a72\u8981\u505a\u66f4\u9577\u6642\u9593\u7684\u7a2e\u5b50\n\u60a8\u78ba\u5b9a\u8981\u7e7c\u7e8c\u55ce? ConfigView.label.showpopuponclose=\u505c\u6b62\u505a\u7a2e\u6642\uff0c\u5982\u679c\u5206\u4eab\u7387\u4f4e\u65bc 1\uff0c\u5f48\u51fa\u78ba\u8a8d\u8996\u7a97 ConfigView.label.startNumSeeds=\n\u7576\u7a2e\u5b50\u6578\u5c11\u65bc\n - \u512a\u5148\u65bc\u5176\u4ed6\u898f\u5247 ConfigView.label.seeds=\u7a2e\u5b50 ConfigView.section.seeding=\u505a\u7a2e\u6642 MyTorrentsView.menu.removeand=\u79fb\u9664\u4e26 (&V) MyTorrentsView.menu.removeand.deletetorrent=\u522a\u9664 Torrent \u6a94\u6848 (&T) MyTorrentsView.menu.removeand.deletedata=\u522a\u9664\u8cc7\u6599 (&D) MyTorrentsView.menu.removeand.deleteboth=\u5169\u8005\u90fd\u522a\u9664 (&B) deletedata.title=\u8b66\u544a deletedata.message1=\u60a8\u5c07\u8981\u522a\u9664\u8cc7\u6599\uff0c\u8a72\u8cc7\u6599\u4f4d\u65bc\uff1a\n MainWindow.menu.file.configure=\u8a2d\u5b9a\u7cbe\u9748 (&W) configureWizard.title=\u8a2d\u5b9a\u7cbe\u9748 configureWizard.welcome.title=\u6b61\u8fce\u4f7f\u7528 Vuze \u8a2d\u5b9a\u7cbe\u9748 configureWizard.welcome.message=\u9019\u500b\u7cbe\u9748\u5c07\u6703\u5354\u52a9\u60a8\u8a2d\u5b9a Vuze u3002\u60a8\u4e5f\u53ef\u4ee5\u5728 \u5de5\u5177->\u9078\u9805 \u4e2d\u4fee\u6539\u9032\u968e\u7684\u8a2d\u5b9a\u3002 configureWizard.transfer.title=\u50b3\u8f38\u548c\u9023\u7dda\u8a2d\u5b9a configureWizard.transfer.hint=\u7955\u8a23 : \u6700\u4f73\u7684\u8a2d\u5b9a\u503c\u61c9\u7565\u5c0f\u65bc\u60a8\u7684\u7dda\u8def\u901f\u5ea6 configureWizard.transfer.message=\u8acb\u5728\u5e95\u4e0b\u9078\u64c7\u9023\u7dda\u901f\u5ea6\u3002\u6ce8\u610f: \u904e\u5c11\u7684\u4e0a\u50b3\u6703\u5c0e\u81f4\u4e0b\u8f09\u901f\u5ea6\u6e1b\u6162\u3002\u7531\u65bc\u4e0a\u50b3\u901f\u5ea6\u662f\u85c9\u7531\u6bcf\u500b\u4e0b\u8f09\u4e2d\u7684 torrent \u4f86\u8a08\u7b97\uff0c\u540c\u6642\u9593\u4e0b\u8f09\u592a\u591a torrents \u6703\u5c0e\u81f4\u901f\u5ea6\u7de9\u6162\u3002\u6211\u5011\u5efa\u8b70\u5206\u914d\u7d66\u6bcf\u500b torrent 5KB/S \u7684\u983b\u5bec\u3002\u53ea\u8981\u60a8\u4e0a\u50b3\u901f\u5ea6\u8d8a\u5feb\uff0c\u60a8\u7684\u4e0b\u8f09\u901f\u5ea6\u4e5f\u6703\u8d8a\u5feb\u3002(\u5fc5\u9808\u8003\u91cf\u5230 torrent \u901f\u5ea6) configureWizard.transfer.connection=\u7dda\u8def configureWizard.transfer.connection.0=\u81ea\u5b9a configureWizard.transfer.connection.1=\u6578\u64da\u6a5f configureWizard.transfer.connection.2=adsl/\u7e9c\u7dda xxx/128 kbps configureWizard.transfer.connection.3=adsl/\u7e9c\u7dda xxx/256 kbps configureWizard.transfer.connection.4=adsl/\u7e9c\u7dda xxx/384 kbps configureWizard.transfer.connection.5=adsl/\u7e9c\u7dda xxx/512 kbps configureWizard.transfer.connection.6=adsl/\u7e9c\u7dda xxx/768 kbps configureWizard.transfer.connection.7=adsl/\u7e9c\u7dda xxx/1024 kbps configureWizard.transfer.maxUpSpeed=\u6700\u5927\u4e0a\u50b3\u901f\u5ea6 (KB/s) configureWizard.transfer.maxActiveTorrents=\u6d3b\u52d5\u4e0a\u9650 configureWizard.transfer.maxDownloads=\u4e0a\u50b3\u6578\u4e0a\u9650 configureWizard.transfer.maxUploadsPerTorrent=\u6bcf\u500b Torrent \u4e0a\u50b3\u6578\u4e0a\u9650 configureWizard.nat.title=NAT / \u4f3a\u670d\u5668\u9023\u63a5\u57e0 configureWizard.nat.message=\u70ba\u4e86\u8b93 Vuze \u767c\u63ee\u5168\u90e8\u7684\u6548\u80fd\uff0c\u5f37\u70c8\u5efa\u8b70\u958b\u555f\u7db2\u969b\u7db2\u8def\u7684\u6240\u6709\u5b58\u53d6\u6b0a\u9650\u3002\u9019\u500b\u5de5\u5177\u53ef\u4ee5\u8b93\u60a8\u6e2c\u8a66\u4e26\u6539\u8b8a\u60a8\u548c\u5925\u4f34\u9023\u7dda\u6642\u6240\u4f7f\u7528\u7684\u9023\u63a5\u57e0.\n\n\u6ce8\u610f: \u9019\u500b\u5de5\u5177\u53ea\u80fd\u6e2c\u8a66 TCP \u9023\u7dda. \u5206\u6563\u6027\u8cc7\u6599\u5eab\u4e5f\u9700\u8981 UDP \u9023\u7dda,\u4f46\u662f\u5982\u679c\u7cfb\u7d71\u5075\u6e2c\u5230\u9632\u706b\u7246\u7684\u8a71,\u6703\u81ea\u52d5\u901a\u77e5\u60a8.\n\n\u6ce8\u610f: TCP \u9023\u63a5\u57e0 6880 \u5df2\u88ab\u7a0b\u5f0f\u5167\u90e8\u4fdd\u7559\uff0c\u6240\u4ee5\u5b83\u7121\u6cd5\u4f7f\u7528\u3002 configureWizard.nat.test=\u6e2c\u8a66 configureWizard.nat.testing=\u6e2c\u8a66\u9023\u63a5\u57e0\u4e2d configureWizard.nat.ok=\u597d ! configureWizard.nat.ko=NAT \u932f\u8aa4 configureWizard.nat.unable=\u7121\u6cd5\u6e2c\u8a66: \u7121\u6548\u7684\u9023\u63a5\u57e0\uff0c\u6216\u8005\u662f\u670d\u52d9\u4e2d\u65b7\u3002\n \u5176\u4ed6\u61c9\u7528\u7a0b\u5f0f\u53ef\u80fd\u6b63\u5728\u4f7f\u7528\u9019\u500b\u9023\u63a5\u57e0\u3002 configureWizard.file.title=Torrents / \u6a94\u6848 configureWizard.file.message1=Vuze \u6703\u5c07\u958b\u555f\u904e\u7684 torrents \u5132\u5b58\u5230\u7279\u5b9a\u7684\u8cc7\u6599\u593e\u5167,\u60a8\u53ef\u4ee5\u5728\u9019\u88e1\u6307\u5b9a\u8cc7\u6599\u593e: configureWizard.file.path=\u8def\u5f91 configureWizard.file.browse=\u700f\u89bd configureWizard.file.message2=Vuze \u53ef\u4ee5\u85c9\u7531\u5728 torrent \u52a0\u5165\u8cc7\u6599\u4ee5\u4fbf\u99ac\u4e0a\u7e8c\u50b3\u60a8\u7684\u6a94\u6848\u3002\u5229\u7528\u9019\u500b\u529f\u80fd\uff0c\u60a8\u4e5f\u53ef\u4ee5\u7e8c\u50b3\u67d0\u7279\u5b9a\u7684\u4e0b\u8f09\u6a94\u6848\u5206\u584a configureWizard.file.fastResume=\u555f\u52d5\u5feb\u901f\u7e8c\u50b3 configureWizard.file.invalidPath=\u7121\u6548\u7684\u76ee\u9304 configureWizard.finish.title=\u5b8c\u7562 configureWizard.finish.message=Vuze \u5df2\u7d93\u8a2d\u5b9a\u5b8c\u7562\uff0c\u795d\u60a8\u4f7f\u7528\u6109\u5feb\uff01 wizard.close.confirmation=\u78ba\u8a8d wizard.close.message=\u60a8\u5e0c\u671b\u4e0b\u6b21\u555f\u52d5 Vuze \u6642\u8f09\u5165\u7cbe\u9748\u55ce? exportTorrentWizard.title=\u532f\u51fa XML \u683c\u5f0f\u7684 torrent exportTorrentWizard.torrentfile.title=\u8f38\u5165 torrent \u9078\u9805 exportTorrentWizard.torrentfile.message=\u9078\u53d6\u8981\u532f\u51fa\u7684 torrent \u6a94\u6848 exportTorrentWizard.torrentfile.path=\u8def\u5f91 exportTorrentWizard.torrentfile.browse=\u700f\u89bd exportTorrentWizard.torrentfile.invalidPath=\u7121\u6548\u7684 torrent \u6a94\u6848 exportTorrentWizard.exportfile.title=\u8f38\u51fa\u6a94\u6848\u9078\u9805 exportTorrentWizard.exportfile.message=\u8f38\u5165\u8981\u532f\u51fa\u7684 xml \u6a94 exportTorrentWizard.exportfile.path=\u8def\u5f91 exportTorrentWizard.exportfile.browse=\u700f\u89bd exportTorrentWizard.exportfile.invalidPath=\u7121\u6548\u7684\u532f\u51fa\u6a94 exportTorrentWizard.finish.title=\u5b8c\u6210 exportTorrentWizard.finish.message=\u532f\u51fa\u6210\u529f exportTorrentWizard.process.inputfilebad.title=\u7121\u6548\u7684 Torrent \u6a94\u6848 exportTorrentWizard.process.inputfilebad.message=\u5b58\u53d6\u8f38\u5165\u6a94\u5931\u6557 exportTorrentWizard.process.outputfileexists.title=\u6a94\u6848\u5df2\u5b58\u5728 exportTorrentWizard.process.outputfileexists.message=\u8f38\u51fa\u6a94\u6848\u5df2\u5b58\u5728 - \u8981\u8986\u5beb\u55ce\uff1f exportTorrentWizard.process.torrentfail.title=\u8b80\u53d6 Torrent \u5931\u6557 exportTorrentWizard.process.exportfail.title=Torrent \u532f\u51fa\u5931\u6557 exportTorrentWizard.process.unknownfail.title=\u7121\u6cd5\u9810\u6e2c\u7684\u932f\u8aa4 importTorrentWizard.title=\u8f09\u5165\u4e00\u500b XML torrent importTorrentWizard.torrentfile.title=\u9078\u64c7\u8981\u8f38\u5165\u7684 Torrent importTorrentWizard.torrentfile.message=\u8f38\u5165\u8981\u532f\u5165\u7684 torrent \u6a94 importTorrentWizard.torrentfile.path=\u8def\u5f91 importTorrentWizard.torrentfile.browse=\u700f\u89bd importTorrentWizard.torrentfile.invalidPath=\u7121\u6548\u7684 torrent \u6a94 importTorrentWizard.importfile.title=\u532f\u5165\u6a94\u6848\u9078\u9805 importTorrentWizard.importfile.message=\u9078\u64c7 xml \u6a94\u6848\u532f\u5165 importTorrentWizard.importfile.path=\u8def\u5f91 importTorrentWizard.importfile.browse=\u700f\u89bd importTorrentWizard.importfile.invalidPath=\u7121\u6548\u7684\u532f\u5165\u6a94\u6848 importTorrentWizard.finish.title=\u5b8c\u6210 importTorrentWizard.finish.message=\u532f\u5165\u6210\u529f importTorrentWizard.process.inputfilebad.title=\u532f\u5165\u6a94\u6848\u7121\u6548 importTorrentWizard.process.inputfilebad.message=\u5b58\u53d6\u8f38\u5165\u6a94\u6848\u5931\u6557 importTorrentWizard.process.outputfileexists.title=\u6a94\u6848\u5df2\u5b58\u5728 importTorrentWizard.process.outputfileexists.message=\u8f38\u51fa\u6a94\u6848\u5df2\u5b58\u5728 - \u8986\u5beb\uff1f importTorrentWizard.process.torrentfail.title=Torrent \u5beb\u5165\u5931\u6557 importTorrentWizard.process.importfail.title=Torrent \u532f\u5165\u5931\u6557 importTorrentWizard.process.unknownfail.title=\u7121\u6cd5\u9810\u77e5\u7684\u932f\u8aa4 ConfigView.label.bindip=\u4f7f\u7528\u5340\u57df IP \u4f4d\u5740 or interface ConfigView.label.zeronewfiles=\u5efa\u7acb\u65b0\u6a94\u6642\u5b9a\u4f4d\u4e26\u6b78\u96f6 ConfigView.label.zeronewfiles.tooltip=\u6e1b\u5c11\u6a94\u6848\u7834\u788e\u7684\u60c5\u5f62 ConfigView.section.stats=\u7d71\u8a08 ConfigView.section.stats.enable=\u555f\u7528 ConfigView.section.stats.defaultsavepath=\u7d71\u8a08\u8cc7\u6599\u5132\u5b58\u76ee\u9304 ConfigView.section.stats.choosedefaultsavepath=\u8acb\u9078\u64c7\u7d71\u8a08\u8cc7\u6599\u5132\u5b58\u76ee\u9304 ConfigView.section.stats.savefreq=\u5b58\u6a94\u983b\u7387 ConfigView.section.stats.minutes=\u5206 ConfigView.section.stats.hours=\u5c0f\u6642 ConfigView.section.stats.seconds=\u79d2 ConfigView.section.stats.savefile=\u7d71\u8a08\u8cc7\u6599\u6a94\u540d\u7a31 MyTorrentsView.menu.export=XML Torrent... (&X) MyTorrentsView.menu.host=\u4ee3\u7ba1... (&H) ManagerItem.finishing=\u6b63\u5728\u5b8c\u6210 ConfigView.dialog.choosedefaulttorrentpath=\u8acb\u9078\u64c7\u9810\u8a2d\u7684 torrent \u76ee\u9304 ConfigView.dialog.choosemovepath=\u8acb\u9078\u64c7\u6a94\u6848\u642c\u79fb\u7684\u76ee\u9304 ConfigView.label.movecompleted=\u4e0b\u8f09\u5b8c\u7562\u4e4b\u5f8c\u79fb\u52d5\u6a94\u6848 ConfigView.label.moveremoved=\u7576\u8981\u88ab\u79fb\u9664\u6642\uff0c\u79fb\u52d5\u4e0b\u8f09\u5b8c\u6210\u7684\u6a94\u6848 ConfigView.label.savetorrents=\u5132\u5b58 .torrent \u6a94\u6848 MainWindow.menu.view.mytracker=\u6211\u7684 Tracker (&T) MyTrackerView.title.full=\u6211\u7684 Tracker MyTrackerView.name=\u540d\u7a31 MyTrackerView.tracker=Tracker MyTrackerView.status=\u72c0\u614b MyTrackerView.status.started=\u9032\u884c\u4e2d MyTrackerView.status.stopped=\u5df2\u505c\u6b62 MyTrackerView.peers=\u5925\u4f34 MyTrackerView.seeds=\u7a2e\u5b50 MyTrackerView.announces=\u767c\u4f48 MyTrackerView.uploaded=\u5df2\u4e0a\u50b3 MyTrackerView.downloaded=\u5df2\u4e0b\u8f09 MyTrackerView.left=\u5269\u9918 ConfigView.section.style=\u754c\u9762\u98a8\u683c ConfigView.label.set_ui_transfer_speeds=\u7f6e\u63db\u53ef\u9078\u64c7\u7684\u50b3\u8f38\u901f\u5ea6 ConfigView.label.set_ui_transfer_speeds.description=\u60a8\u53ef\u4ee5\u5728\u7cfb\u7d71\u5217\u4e0a\u7684\u72c0\u614b\u6b04\u624b\u52d5\u9078\u64c7\u9810\u8a2d\u7684\u4e0b\u8f09\u548c\u4e0a\u50b3\u901f\u5ea6\u3002\n\u6578\u503c\u9808\u7528\u9017\u9ede\u7b26\u865f\u9694\u958b ConfigView.label.set_ui_transfer_speeds.description.download=\u8a2d\u5b9a\u4e0b\u8f09\u901f\u5ea6\uff08KB/s\uff09 ConfigView.label.set_ui_transfer_speeds.description.upload=\u8a2d\u5b9a\u4e0a\u50b3\u901f\u5ea6\uff08KB/s\uff09 ConfigView.section.style.useCustomTabs=\u4f7f\u7528\u53ef\u95dc\u9589\u7684\u5206\u9801\uff08\u9700\u8981\u91cd\u65b0\u555f\u52d5\uff09 MainWindow.menu.view.plugins=\u5916\u639b\u6a21\u7d44 (&P) fileDownloadWindow.saveTorrentIn=\u5c07 Torrent \u6a94\u5132\u5b58\u81f3 fileDownloadWindow.title=Vuze - Torrent \u4e0b\u8f09\u5de5\u5177 fileDownloadWindow.downloading=\u6b63\u5728\u4e0b\u8f09\u81ea\uff1a fileDownloadWindow.status=\u72c0\u614b\uff1a fileDownloadWindow.state_initializing=\u6b63\u5728\u521d\u59cb\u5316 fileDownloadWindow.state_downloading=\u4e0b\u8f09\u4e2d fileDownloadWindow.state_error=\u932f\u8aa4\uff1a MainWindow.menu.file.open.url=\u4f4d\u5740... (&L) openUrl.title=\u958b\u555f\u4f4d\u7f6e openUrl.url=URL\u4f4d\u5740 : MyTorrentsView.menu.host.error.title=Torrent \u4ee3\u7ba1\u5931\u6557 MyTorrentsView.menu.host.error.message=\u7576\u4ee3\u7ba1 torrent \u6642\uff0c\u767c\u751f\u4ee5\u4e0b\u932f\u8aa4 ConfigView.section.tracker=Tracker ConfigView.section.tracker.pollinterval=Tracker \u7528\u6236\u7aef\u8f2a\u8a62\u9593\u9694\uff08\u79d2\uff09 ConfigView.section.tracker.publishenable=\u767c\u4f48 torrent \u8a73\u7d30\u8cc7\u8a0a\u5230 "" ConfigView.section.tracker.ip=Tracker \u5916\u90e8 IP \u4f4d\u5740 ConfigView.section.style.enableXPStyle=\u555f\u7528 XP \u98a8\u683c\uff08\u9700\u8981\u91cd\u65b0\u555f\u52d5\uff09 IPChecker.external.service.dyndns.name=DynDNS \u7db2\u7ad9 IPChecker.external.service.dyndns.url=http://www.dyndns.org/ IPChecker.external.service.dyndns.description=\u865b\u64ec DNS \u7db2\u8def\u670d\u52d9, LLC ConfigView.section.tracker.checkip=\u81ea\u52d5\u63a2\u7d22\u5916\u90e8 IP \u4f4d\u5740 ipCheckerWizard.title=IP \u6aa2\u67e5\u7cbe\u9748 ipCheckerWizard.service=\u670d\u52d9 ipCheckerWizard.chooseService=\u8acb\u5f9e\u670d\u52d9\u5217\u8868\u5167\u9078\u64c7\u4e00\u500b IP \u6aa2\u67e5\u670d\u52d9 ipCheckerWizard.explanations=\u60a8\u53ef\u4ee5\u4f7f\u7528\u9019\u500b\u7cbe\u9748\u4f86\u67e5\u51fa\u4f60\u7684\u5916\u90e8 IP \u4f4d\u5740\u3002\u5982\u679c\u60a8\u7684 IP \u4f4d\u5740\u662f\u865b\u64ec\u7684\uff0c\u6211\u5011\u5efa\u8b70\u60a8\u7533\u8acb\u4e00\u500b\u865b\u64ec DNS \u670d\u52d9\u7684\u5e33\u865f\u3002\u5e95\u4e0b\u5217\u51fa\u4e86\u90e8\u4efd\u670d\u52d9\u5546\uff0c\u8acb\u4f7f\u7528\u63d0\u4f9b\u7684\u9023\u7d50\u958b\u555f\u5e33\u865f\u3002\u7136\u5f8c\u5c07\u60a8\u7684\u865b\u64ec\u7db2\u5740\u540d\u7a31\u586b\u5165 IP \u4f4d\u5740\u6b04\uff08e.g. myhostname.dybdns.org\uff09\u3002\u60a8\u53ef\u80fd\u6703\u9700\u8981\u4f7f\u7528\u8edf\u9ad4\u4f86\u81ea\u52d5\u66f4\u65b0\u540c\u6b65 IP \u4f4d\u5740\u548c\u865b\u64ec DNS\u3002\u9019\u6a23\u4e00\u4f86\uff0c\u5373\u4f7f IP \u66f4\u52d5\uff0c\u60a8\u4f9d\u7136\u53ef\u4ee5\u767c\u4f48 torrent\u3002 ipCheckerWizard.service.description=\u8aaa\u660e\uff1a ipCheckerWizard.service.url=\u9023\u7d50\uff1a ipCheckerWizard.progresstitle=IP \u6aa2\u67e5\u4e2d ipCheckerWizard.checkComplete=\u5b8c\u6210\u7684 IP\uff1a ipCheckerWizard.checkFailed=\u5931\u6557\u539f\u56e0\uff1a wizard.tracker.local=\u4f7f\u7528 Vuze \u5167\u5efa\u7684 Tracker wizard.tracker.external=\u4f7f\u7528\u5916\u90e8 Tracker wizard.tracker.howToLocal=\t\u8acb\u81f3 '\u5de5\u5177->\u9078\u9805->Tracker' \u555f\u7528 wizard.announceUrl=\u767c\u4f48 URL \u4f4d\u7f6e IPChecker.external.service.discoveryvip.name=\u9023\u81f3 Discoveryvip \u67e5\u8a62 IPChecker.external.service.discoveryvip.url=http://ip.discoveryvip.com/ IPChecker.external.service.discoveryvip.description=Discoveryvip - \u53ea\u6aa2\u67e5 IP \u4f4d\u5740 IPChecker.external.httpinvalidresponse=\u7121\u6548\u7684 HTTP \u56de\u61c9 IPChecker.external.loadingwebpage=\u7db2\u9801\u8f09\u5165\u4e2d IPChecker.external.analysingresponse=\u56de\u61c9\u5206\u6790\u4e2d IPChecker.external.addressextracted=\u64f7\u53d6\u5230\u7684 IP \u4f4d\u5740 IPChecker.external.httploadfail=\u8f09\u5165\u9801\u9762\u5931\u6557 IPChecker.external.timeout=\u767c\u751f\u903e\u6642\u72c0\u614b IPChecker.external.ipnotfound=\u627e\u4e0d\u5230 IP \u4f4d\u5740 ConfigView.section.tracker.pollintervalmin=\u6700\u5c0f ConfigView.section.tracker.pollintervalmax=\u6700\u5927 ConfigView.section.tracker.pollintervalincby=\u589e\u52a0\u5230 ConfigView.section.tracker.pollintervalincper=\u6bcf 'n' \u500b\u7528\u6236\u7aef splash.loadingImages=\u5716\u5f62\u8f09\u5165\u4e2d splash.initializeGui=\u4e3b\u8996\u7a97\u521d\u59cb\u5316\u4e2d splash.openViews=\u958b\u555f\u6aa2\u8996 splash.plugin=\u8f09\u5165\u5916\u639b\u6a21\u7d44 : configureWizard.nat.tooManyPorts=\u6e2c\u8a66\u904e\u591a\u7684\u9023\u63a5\u57e0 (\u6700\u591a 9 \u500b) ConfigView.section.color=\u8272\u5f69\u914d\u7f6e MyTorrentsView.menu.publish=\u516c\u4f48... (&P) MyTrackerView.status.published=\u5df2\u516c\u4f48 MyTrackerView.completed=\u5df2\u5b8c\u6210 MainWindow.menu.file.open.torrentnodefault=Torrent \u6a94... (\u6c92\u6709\u9810\u8a2d\u5132\u5b58) wizard.comment=\u8a3b\u89e3 ConfigView.label.movetorrent=\u79fb\u52d5 torrent \u6a94 ConfigView.label.movepartialdownloads=\u7576\u67d0\u4e9b\u6a94\u6848\u88ab\u6a19\u6ce8"\u4e0d\u8981\u4e0b\u8f09"\u6642\u79fb\u52d5 ConfigView.section.file.decoder.label=\u5982\u6709\u5fc5\u8981\uff0c\u4f7f\u7528\u9810\u8a2d\u7684 torrent \u7de8\u78bc ConfigView.section.file.decoder.nodecoder=\u7121 IPChecker.external.service.no-ip.name=No-IP \u7db2\u7ad9 IPChecker.external.service.no-ip.url=http://www.no-ip.com/ IPChecker.external.service.no-ip.description=\u865b\u64ec\u548c\u56fa\u5b9a\u5f0f DNS \u670d\u52d9\u63d0\u4f9b\u8005\n\uff08\u6c92\u6709\u53ef\u7528\u7684\u514d\u8cbb"\u6aa2\u67e5\u4f4d\u5740" \u670d\u52d9\uff09 ConfigView.section.tracker.publicenable=\u555f\u7528\u5916\u90e8 torrents ConfigView.label.playdownloadspeech=\u4e0b\u8f09\u5b8c\u7562\u5f8c\u64ad\u653e\u8a9e\u97f3\u63d0\u793a ConfigView.label.playdownloadspeech.info=\u76ee\u524d\u53ea\u6709\u82f1\u8a9e\u767c\u97f3 # # Tooltips # GeneralView.label.status.pieces_available.tooltip=\u986f\u793a\u6bcf\u500b\u6a94\u6848\u5206\u584a\u53ef\u7528\u7684\u62f7\u8c9d\u6578\u76ee\n\u5982\u679c\u6578\u5b57\u7b49\u65bc\u6216\u5c0f\u65bc 1\uff0c\u60a8\u4fbf\u7121\u6cd5\u627e\u5230\u5b8c\u6574\u7684\u6a94\u6848\u62f7\u8c9d\uff08\u53ef\u80fd\u7121\u6cd5\u5b8c\u6210\u4e0b\u8f09\uff09 GeneralView.label.trackerurl.tooltip=\u9ede\u9078\u6b64\u8655\u4ee5\u62f7\u8c9d\u767c\u4f48 url \u5230\u526a\u8cbc\u7c3f GeneralView.label.trackerurlopen.tooltip=\u9ede\u9078\u6b64\u8655\u6253\u958b tracker \u4e3b\u9801 # # 2.0.4.4 # ConfigView.section.style.guiUpdate=\u66f4\u65b0 GUI \u9593\u9694 ConfigView.section.style.graphicsUpdate=\u6bcf\u9694 N \u6b21 GUI \u66f4\u65b0\uff0c\u4e00\u4f75\u66f4\u65b0\u5716\u5f62\u689d ConfigView.section.style.reOrderDelay=\u6bcf N \u500b GUI \u66f4\u65b0\uff0c\u91cd\u65b0\u6392\u5217\u8868\u683c [0\uff1a\u6c38\u4e0d] ConfigView.section.style.reOrderDelay.never=\u5f9e\u4e0d ConfigView.section.logging=\u8a18\u9304 ConfigView.section.logging.enable=\u555f\u7528\u8a18\u9304\u5b58\u6a94 ConfigView.section.logging.logdir=\u8a18\u9304\u6a94\u76ee\u9304 ConfigView.section.logging.choosedefaultsavepath=\u8acb\u9078\u64c7\u5132\u5b58\u76ee\u9304 GeneralView.label.updatein.querying=\u67e5\u8a62\u4e2d... configureWizard.nat.sharePort=\u6240\u6709\u7684 torrents \u4f7f\u7528\u540c\u4e00\u500b\u9023\u63a5\u57e0 ConfigView.section.logging.maxsize=\u8a18\u9304\u6a94\u53ef\u4f7f\u7528\u6700\u5927\u7a7a\u9593 ConfigView.section.tracker.passwordenableweb=\u555f\u7528 tracker \u7db2\u7ad9\u5bc6\u78bc ConfigView.section.tracker.passwordenabletorrent=\u555f\u7528 torrents \u5bc6\u78bc ConfigView.section.tracker.username=\u4f7f\u7528\u8005\u540d\u7a31 ConfigView.section.tracker.password=\u5bc6\u78bc columnChooser.title=\u9078\u64c7\u986f\u793a\u9805\u76ee columnChooser.move=\u91cd\u65b0\u6392\u5217 columnChooser.apply=\u5957\u7528 columnChooser.columnname=\u9805\u76ee columnChooser.columndescription=\u8aaa\u660e TableColumn.header.shareRatio=\u5206\u4eab\u7387 MyTorrentsView.menu.editTableColumns=\u884c\u9805\u76ee\u8a2d\u5b9a (&C) wizard.operationfailed=\u64cd\u4f5c\u5931\u6557 authenticator.title=\u9700\u8981\u8a8d\u8b49 authenticator.realm=\u5340\u57df authenticator.tracker=Tracker \u4f4d\u7f6e authenticator.user=\u4f7f\u7528\u8005\u540d\u7a31 authenticator.password=\u5bc6\u78bc ConfigView.label.allowSendVersion=\u5141\u8a31 Azures \u6aa2\u67e5\u65b0\u7248\u672c\u6642\u5bc4\u9001\u533f\u540d\u7248\u672c\u7de8\u865f\u548c\u96a8\u6a5f ID wizard.hint.mode=\u63d0\u793a:\t\u60a8\u53ef\u4ee5\u5728\u9019\u500b\u7cbe\u9748\u4e2d\u7528\u62d6\u653e\u7684\u65b9\u5f0f\n\t\u9078\u64c7\u6a94\u6848\u6216\u662f\u76ee\u9304 wizard.hint.file=\u63d0\u793a:\t\u60a8\u53ef\u4ee5\u7528\u62d6\u653e\u7684\u65b9\u5f0f\u9078\u64c7\u6a94\u6848 wizard.hint.directory=\u63d0\u793a:\t\u60a8\u53ef\u4ee5\u7528\u62d6\u653e\u7684\u65b9\u5f0f\u9078\u64c7\u76ee\u9304 MainWindow.menu.help.checkupdate=\u6aa2\u67e5\u66f4\u65b0... (&C) TableColumn.header.down=\u5df2\u4e0b\u8f09 TableColumn.header.up=\u5df2\u4e0a\u50b3 ConfigView.section.tracker.passwordenabletorrent.info=\u9700\u8981\u5408\u9069\u7684 BT \u7528\u6236\u7aef\u8edf\u9ad4 (e.g. Vuze ConfigView.section.style.confirmationOnExit=\u96e2\u958b\u6642\u986f\u793a\u78ba\u8a8d\u5c0d\u8a71\u7a97 MainWindow.dialog.exitconfirmation.title=\u95dc\u9589 Vuze MainWindow.dialog.exitconfirmation.text=\u60a8\u771f\u7684\u8981\u95dc\u9589 Vuze SystemTray.menu.stopalltransfers=\u505c\u6b62\u6240\u6709\u50b3\u8f38\u5de5\u4f5c (&A) TrayWindow.menu.stopalldownloads=\u505c\u6b62\u6240\u6709\u4e0b\u8f09 (&A) ConfigView.section.tracker.sslport.info=\u53c3\u95b1 FAQ \u4ee5\u7372\u5f97\u9032\u4e00\u6b65\u7684\u8cc7\u8a0a wizard.tracker.ssl=\u4f7f\u7528 SSL \u9023\u7dda ConfigView.label.playdownloadfinished=\u4e0b\u8f09\u5b8c\u7562\u5f8c\u64ad\u653e\u8072\u97f3\u63d0\u793a ConfigView.label.popupdownloadfinished=\u4e0b\u8f09\u5b8c\u7562\u5f8c\u8df3\u51fa\u8b66\u544a\u8996\u7a97 ConfigView.label.popupfilefinished=\u6a94\u6848\u5b8c\u6210\u5f8c\u8df3\u51fa\u8b66\u544a\u8996\u7a97 TableColumn.header.pieces=\u6a94\u6848\u5206\u584a TableColumn.header.pieces.info=\u9019\u500b\u9577\u689d\u5716\u53ef\u4ee5\u986f\u793a\u60a8\u5df2\u7d93\u4e0b\u8f09\u4e86\u591a\u5c11\u6a94\u6848\u5206\u584a TableColumn.header.completion=\u5b8c\u6210\u5ea6 TableColumn.header.completion.info=\u4ee5\u5716\u5f62\u8868\u793a\u4e0b\u8f09\u5b8c\u6210\u5ea6% ConfigView.section.style.showdownloadbasket=\u986f\u793a\u4e0b\u8f09\u7c43\uff08\u62d6\u653e .torrents\uff09 ConfigView.section.style.alwaysShowTorrentFiles=\u6c38\u9060\u986f\u793a Torrent \u7684\u7d30\u7bc0\u548c\u5167\u542b\u6a94\u6848 wizard.multitracker=\u5728 Torrent \u4e2d\u52a0\u5165\u591a\u91cd Tracker \u8cc7\u8a0a wizard.multitracker.title=\u591a\u91cd Tracker wizard.multitracker.configuration=\u591a\u91cd Tracker \u8a2d\u5b9a wizard.multitracker.new=\u65b0\u589e... wizard.multitracker.edit=\u7de8\u8f2f... wizard.multitracker.delete=\u522a\u9664 wizard.multitracker.group=Tracker \u7fa4\u7d44 wizard.multitracker.edit.title=\u591a\u91cd Tracker \u7de8\u8f2f\u5668 wizard.multitracker.edit.name=\u540d\u7a31 wizard.multitracker.edit.save=\u5132\u5b58 wizard.multitracker.edit.newgroup=\u65b0\u7fa4\u7d44 wizard.multitracker.edit.deletegroup=\u522a\u9664\u7fa4\u7d44 wizard.multitracker.edit.newtracker=\u65b0 Tracker wizard.multitracker.edit.deletetracker=\u522a\u9664 Tracker wizard.multitracker.edit.edit=\u7de8\u8f2f wizard.addingmt=\u52a0\u5165\u591a\u91cd Tracker \u8cc7\u8a0a wizard.multitracker.noannounce=\u516c\u4f48\u7684 URL \u4f4d\u7f6e\u672a\u5728\u60a8\u7684 trackers \u5217\u8868\u4e2d MyTorrentsView.menu.recheck=\u5f37\u5236\u518d\u6aa2\u67e5 (&K) iconBar.showDownloadBar.tooltip=\u986f\u793a\u4e0b\u8f09\u689d iconBar.start.tooltip=\u958b\u59cb iconBar.stop.tooltip=\u505c\u6b62 iconBar.remove.tooltip=\u79fb\u9664 iconBar.openNoDefault.tooltip=\u6253\u958b .torrent \u6a94\uff08no default save\uff09 iconBar.openURL.tooltip=\u6253\u958b URL iconBar.openFolder.tooltip=\u6253\u958b\u8cc7\u6599\u593e iconBar.new.tooltip=\u5efa\u7acb\u4e00\u500b torrent iconBar.up.tooltip=\u4e0a\u79fb iconBar.down.tooltip=\u4e0b\u79fb iconBar.run.tooltip=\u6253\u958b iconBar.host.tooltip=\u4e3b\u6a5f iconBar.publish.tooltip=\u767c\u4f48 MyTorrentsView.menu.editTracker=\u7de8\u8f2f Tracker \u7684 URL (&E) GeneralView.menu.selectTracker=\u9078\u64c7 ConfigView.section.stats.xslfile=XSL \u6a94\u6848\u540d\u7a31 ConfigView.section.stats.xslfiledetails=\u9019\u5c07\u6703\u5305\u542b\u5728\u7d71\u8a08\u8cc7\u6599\u6a94\u7684\u8868\u982d \u6a19\u7c64 ConfigView.label.savetorrentbackup=\u5132\u5b58\u5099\u4efd ConfigView.section.tracker.forceport=\u5f37\u5236\u5916\u90e8\u4e3b\u6a5f\u7684 torrents \u9023\u7d50\u9810\u8a2d\u9023\u63a5\u57e0 ConfigView.section.ipfilter.allow="\u5141\u8a31"\u9019\u4e9b\u7bc4\u570d \uff08\u9810\u8a2d\u70ba"\u7981\u6b62"\uff09 ConfigView.section.ipfilter.list.inrange=\u5728\u7bc4\u570d\u5167 ConfigView.section.ipfilter.list.notinrange=\u4e0d\u5728\u4efb\u4f55\u7bc4\u570d\u5167 ConfigView.section.ipfilter.list.title=\u88ab\u5c01\u9396\u7684 IP ConfigView.label.allowsameip=\u5141\u8a31\u55ae\u4e00 IP \u591a\u91cd\u9023\u7dda ConfigView.label.allowsameip.tooltip=\u53ea\u6709\u9700\u8981\u6642\u624d\u9ede\u9078.\n\u9019\u662f leecher \u7684\u4fdd\u8b77\u6a5f\u5236 (\u7576\u6c92\u6709\u555f\u52d5\u6642). ManagerItem.superseeding=\u8d85\u7d1a\u7a2e\u5b50 ConfigView.label.userSuperSeeding=\u4f7f\u7528\u8d85\u7d1a\u7a2e\u5b50\u6a21\u5f0f PeersView.uniquepiece=\u6a94\u6848\u5206\u584a (\u8d85\u7d1a\u7a2e\u5b50\u6a21\u5f0f) PeersView.uniquepiece.none=\u7121 PeersView.timetosend=\u91cd\u50b3\u6a94\u6848\u5feb\u7684\u6642\u9593 (\u8d85\u7d1a\u7a2e\u5b50\u6a21\u5f0f) ConfigView.section.style.addurlsilently=\u9ed8\u9ed8\u5730\u6253\u958b\u8df3\u904e\u7684 URLs ConfigView.section.style.addurlsilently.tooltip=\u4e0d\u986f\u793a\u63d0\u793a\u5c0d\u8a71\u7a97\uff0c\u81ea\u52d5\u4e0b\u8f09\u8df3\u904e\u7684/\u4e1f\u68c4\u7684 .torrent URLs ConfigView.section.file.decoder.prompt=\u63d0\u793a\u53ef\u7528\u7684\u7de8\u78bc\u9078\u64c7 ConfigView.section.file.decoder.prompt.tooltip=\u7e3d\u662f\u986f\u793a"\u6240\u6709\u53ef\u7528\u7de8\u78bc\u65b9\u5f0f"\u7684\u5c0d\u8a71\u8996\u7a97 MyTorrentsView.menu.moveTop=\u9802\u7aef (&T) MyTorrentsView.menu.moveEnd=\u5e95\u90e8 (&B) ConfigView.label.moveonlyusingdefaultsave=\u50c5\u5728\u9810\u8a2d\u7684\u6a94\u6848\u76ee\u9304\u5167 ConfigView.label.moveonlyusingdefaultsave.tooltip=\u53ea\u6709\u7576\u4e0b\u8f09\u5b8c\u7562\u7684\u8cc7\u6599\u5728\u9810\u8a2d\u7684\u8cc7\u6599\u76ee\u9304\u6642\u624d\u79fb\u52d5 ConfigView.label.watchtorrentfolder=\u81ea\u52d5\u8f09\u5165\u65b0\u7684 torrent \u6a94 ConfigView.label.watchtorrentfolder.tooltip=\u5b9a\u6642\u67e5\u770b\u65b0\u7684 torrent \u6a94 ConfigView.label.watchtorrentfolderinterval=\u9593\u9694 ConfigView.label.watchtorrentfolderinterval.tooltip=\u66ab\u6642\u505c\u6b62\uff0c\u76f4\u5230\u4e0b\u6b21\u8cc7\u6599\u593e\u6383\u63cf\u7d50\u675f ConfigView.dialog.choosewatchtorrentfolderpath=\u8acb\u9078\u64c7 torrent \u6a94\u6848\u532f\u5165\u7684\u76ee\u9304 ConfigView.label.startwatchedtorrentsstopped=\u958b\u59cb\u505c\u6b62\u7684 ConfigView.label.startwatchedtorrentsstopped.tooltip=\u52a0\u5165\u65b0\u7684 torrent \u6a94\u6642\uff0c\u9810\u8a2d\u70ba\u505c\u6b62 ConfigView.section.plugins=\u5916\u639b\u6a21\u7d44 wizard.maketorrent.filesize=\u6a94\u6848\u5927\u5c0f wizard.maketorrent.piececount=\u6a94\u6848\u584a\u5206\u6578\u91cf wizard.maketorrent.piecesize=\u6a94\u6848\u5206\u584a\u5927\u5c0f wizard.maketorrent.auto=\u81ea\u52d5 MainWindow.menu.view.stats=\u7d71\u8a08 (&S) SpeedView.title.full=\u6d3b\u52d5 SpeedView.downloadSpeed.title=\u4e0b\u8f09\u901f\u5ea6 SpeedView.uploadSpeed.title=\u4e0a\u50b3\u901f\u5ea6 ConfigView.section.style.useSIUnits=\u4f7f\u7528\u570b\u969b\u6a19\u6e96\u55ae\u4f4d\uff08KB -> KiB etc.\uff09 iconBar.top.tooltip=\u79fb\u81f3\u9802\u7aef iconBar.bottom.tooltip=\u79fb\u5230\u6700\u5f8c TableColumn.header.health=\u5065\u5eb7\u5ea6 MyTorrentsView.menu.health=\u95dc\u65bc\u5065\u5eb7\u5ea6 health.explain.grey=\u8868\u793a\u60a8\u7684 torrent \u6c92\u6709\u57f7\u884c\uff08\u4e0b\u8f09\u6216\u4e0a\u50b3\uff09 health.explain.red=\u8868\u793a\u60a8\u4e0b\u8f09\u6642\u6c92\u6709\u9023\u7dda\u5230\u4efb\u4f55\u5925\u4f34 health.explain.blue=\u505a\u7a2e\u6642\uff0c\u9019\u610f\u8b02\u60a8\u6c92\u6709\u9023\u7dda\u5230\u4efb\u4f55\u5925\u4f34\n\u4e0b\u8f09\u6642\uff0c\u9019\u610f\u8b02\u60a8\u9023\u7dda\u5230\u90e8\u4efd\u5925\u4f34\uff0c\u4f46\u662f tracker \u7576\u6389\u4e86 health.explain.yellow=\u8868\u793a tracker \u662f\u6b63\u5e38\u7684\uff0c\u60a8\u5df2\u9023\u7dda\u5230\u5925\u4f34\uff0c\u4f46\u662f\u6c92\u6709\u4efb\u4f55\u9060\u7aef\u9023\u7dda\n\u5982\u679c\u60a8\u7684 torrent \u4e00\u76f4\u7dad\u6301\u9ec3\u8272\uff0cNAT \u8a2d\u5b9a\u53ef\u80fd\u6709\u554f\u984c health.explain.green=\u8868\u793a\u4e00\u5207\u6b63\u5e38 ConfigView.section.style.alwaysRefreshMyTorrents=\u6301\u7e8c\u5237\u65b0"\u6211\u7684 Torrents" ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=\u9019\u500b\u9078\u9805\u6703\u66f4\u65b0"\u6211\u7684 Torrent" ,\u5373\u4f7f\u6c92\u6709\u986f\u793a\u51fa\u4f86 (\u5c0d\u67d0\u4e9b\u5916\u639b\u6a21\u7d44\u5f88\u6709\u7528) # #2.0.7.0 # security.certtruster.title=\u5b89\u5168\u6027\u6191\u8b49\u8b66\u544a security.certtruster.intro=\u9019\u500b\u5b89\u5168\u6027\u6191\u8b49\u662f\u7531\u60a8\u4e0d\u4fe1\u4efb\u7684\u516c\u53f8\u6240\u767c\u884c security.certtruster.resource=\u4f86\u6e90: security.certtruster.issuedto=\u767c\u884c\u7d66: security.certtruster.issuedby=\u767c\u884c\u8005: security.certtruster.prompt=\u60a8\u60f3\u8981\u4fe1\u4efb\u5b83\u55ce? security.certtruster.yes=\u662f security.certtruster.no=\u5426 ConfigView.section.tracker.torrentsperpage=\u6bcf\u9801\u591a\u5c11\u500b torrents\uff1f [0\uff1a\u7121\u9650\u5236] MainWindow.menu.file.share=\u5171\u4eab\u6a94\u6848 (&S) MainWindow.menu.file.share.file=\u6a94\u6848... (&F) MainWindow.menu.file.share.dir=\u6a94\u6848\u593e... (&O) MainWindow.menu.file.share.dircontents=\u6a94\u6848\u593e\u5167\u5bb9... (&C) MainWindow.menu.file.share.dircontentsrecursive=\u6a94\u6848\u593e\u5167\u5bb9...(\u905e\u8ff4) (&R) MainWindow.dialog.share.sharefile=\u9078\u53d6\u8981\u5206\u4eab\u7684\u6a94\u6848 MainWindow.dialog.share.sharedir=\u9078\u53d6\u5171\u4eab\u8cc7\u6599\u593e MainWindow.dialog.share.sharedircontents=\u9078\u53d6\u8981\u5171\u4eab\u7684\u8cc7\u6599\u593e\u5167\u5bb9 MainWindow.dialog.share.sharedircontents.recursive=\u905e\u8ff4 globalmanager.download.remove.veto=\u79fb\u9664\u52d5\u4f5c\u88ab\u7981\u6b62 plugin.sharing.download.remove.veto=\u9019\u500b\u4e0b\u8f09\u662f\u8cc7\u6e90\u88ab\u5171\u4eab\u7684\u7d50\u679c \n \u5982\u60f3\u8981\u79fb\u9664\u9019\u500b\u4e0b\u8f09\uff0c\u8acb\u79fb\u9664\u95dc\u806f\u7684\u5171\u4eab\u6a94\u6848: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=\u4e3b\u8981 ConfigView.section.tracker.web=\u7db2\u7ad9 ConfigView.label.prioritizefirstpiece=\u7b2c\u4e00\u500b\u6a94\u6848\u584a\u548c\u6700\u5f8c\u4e00\u500b\u6a94\u6848\u584a\u5217\u70ba\u512a\u5148\u4e0b\u8f09 ConfigView.label.prioritizefirstpiece.tooltip=\u5617\u8a66\u512a\u5148\u4e0b\u8f09\u6a94\u6848\u7684\u9996\u7aef\u548c\u5c3e\u7aef \n \u4ee5\u65b9\u4fbf\u9810\u89bd\u6a94\u6848 ConfigView.section.file.confirm_data_delete=\u522a\u9664\u6a94\u6848\u6642\u9700\u8981\u78ba\u8a8d ConfigView.section.file.confirm_data_delete.tooltip="\u79fb\u52d5\u6216\u522a\u9664"\u6642\u9700\u8981\u78ba\u8a8d TrayWindow.menu.startalldownloads=\u555f\u52d5\u6240\u6709\u4e0b\u8f09 SystemTray.menu.startalltransfers=\u555f\u52d5\u6240\u6709\u50b3\u8f38\u5de5\u4f5c sharing.progress.title=\u5171\u4eab\u72c0\u6cc1 sharing.progress.hide=\u96b1\u85cf MainWindow.menu.view.myshares=\u6211\u7684\u5171\u4eab\u6a94\u6848 MySharesView.title.full=\u6211\u7684\u5171\u4eab\u6a94\u6848 MySharesView.name=\u540d\u7a31 MySharesView.type=\u7a2e\u985e MySharesView.type.file=\u6a94\u6848 MySharesView.type.dir=\u76ee\u9304 MySharesView.type.dircontents=\u76ee\u9304\u5167\u5bb9 MySharesView.type.dircontentsrecursive=\u76ee\u9304\u5167\u5bb9(\u905e\u8ff4) MySharesView.menu.remove=\u79fb\u9664 ConfigView.section.tracker.extensions=\u64f4\u5145 ConfigView.section.tracker.sendpeerids=\u50b3\u9001\u5925\u4f34\u8eab\u5206\u7d66\u4e0b\u8f09\u8005 ConfigView.section.tracker.enableudp=\u555f\u7528 UDP tracker \u5354\u5b9a plugin.sharing.torrent.remove.veto=\u9019\u500b\u88ab\u767b\u9304\u7684 tracker \u662f\u8cc7\u6e90\u88ab\u5171\u4eab\u7684\u7d50\u679c \n \u5982\u60f3\u8981\u79fb\u9664\u9019\u500b\u4e0b\u8f09\uff0c\u8acb\u79fb\u9664\u95dc\u806f\u7684\u5171\u4eab\u6a94\u6848: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=\u4e0b\u8f09\u7121\u6cd5\u79fb\u9664\uff0c\u56e0\u70ba\u5b83\u9084\u672a\u505c\u6b62 plugin.sharing.remove.veto=\u9019\u500b\u5171\u4eab\u6a94\u6848\u5305\u542b\u5728\u4e00\u500b"\u5171\u4eab\u76ee\u9304"\u4e4b\u4e2d,\u7121\u6cd5\u55ae\u7368\u522a\u9664 \n \u8acb\u522a\u9664\u6574\u500b\u539f\u59cb\u5171\u4eab\u76ee\u9304 GeneralView.label.hash.tooltip=\u9ede\u9078\u6b64\u8655\u5c07 hash \u62f7\u8c9d\u5230\u526a\u8cbc\u7c3f ConfigView.section.tracker.maxpeersreturned=\u56de\u5831\u7684\u6700\u5927\u5925\u4f34\u6578 [0\uff1a\u7121\u9650\u5236] ConfigView.label.serverport=\u76e3\u807d TCP / UDP \u50b3\u5165\u7684\u9023\u63a5\u57e0 ConfigView.label.serverport.tooltip=\u9023\u63a5\u57e0\u7bc4\u570d\u5fc5\u9808\u4ecb\u65bc 1-65535\uff0c\u4e14\u4e0d\u53ef\u4ee5\u662f 6880 \uff08Vuze \u5167\u90e8\u4f7f\u7528\uff09 configureWizard.nat.server.tcp_listen_port=\u76e3\u807d TCP \u4f86\u6e90\u7684\u9023\u63a5\u57e0 ConfigView.section.sharing=\u5171\u4eab\u8cc7\u6e90 ConfigView.section.sharing.usessl=\u5171\u4eab\u8cc7\u6e90\u4f7f\u7528 SSL\uff08\u9700\u8981\u8a2d\u5b9a Tracker\uff09 ConfigView.section.style.dropdiraction=\u555f\u7528\u76ee\u9304\u62d6\u653e\u529f\u80fd ConfigView.section.style.dropdiraction.opentorrents=\u6253\u958b Torrents ConfigView.section.style.dropdiraction.sharefolder=\u5171\u4eab\u76ee\u9304 ConfigView.section.style.dropdiraction.sharefoldercontents=\u5171\u4eab\u5167\u5bb9 # # 2.0.7.x # Categories.all=\u5168\u90e8 Categories.uncategorized=\u672a\u5206\u985e CategoryAddWindow.message=\u8f38\u5165\u65b0\u7684\u5206\u985e\u540d\u7a31 CategoryAddWindow.title=\u589e\u52a0\u65b0\u7684\u5206\u985e ConfigView.label.autoSeedingIgnoreInfo=\u5ffd\u7565\u505a\u7a2e\u6392\u7a0b\u6700\u5e95\u7aef\u7684 torrent\u3002\u4ed6\u5011\u4e0d\u6703\u81ea\u52d5\u555f\u52d5\u3002\n\u5ffd\u7565\u7b26\u5408\u6700\u512a\u5148\u9806\u5e8f\u6a19\u6e96\u7684 torrent \u898f\u5247\u3002 \n\u9664\u975e\u53e6\u5916\u5ba3\u544a\uff0c\u5c07\u503c\u8a2d\u70ba 0 \u4ee5\u95dc\u9589\u9019\u9805\u898f\u5247\u3002 ConfigView.label.directory=\u76ee\u9304 ConfigView.label.disconnetseed.tooltip=\u7576\u4f5c\u7a2e\u7684\u6642\u5019\uff0c\u5207\u65b7\u548c\u5176\u4ed6\u4e5f\u5728\u505a\u7a2e\u7684\u7528\u6236\u7aef\u9023\u7dda.\n \u56e0\u70ba\u4ed6\u5011\u4e0d\u9700\u8981\u548c\u60a8\u4ea4\u63db\u8cc7\u6599 ConfigView.label.ignoreCase=\u5ffd\u7565\u5927\u5c0f\u5beb ConfigView.label.ignoreSeeds=\u5ffd\u7565 torrents-\u81f3\u5c11 ConfigView.label.importdirectory=\u532f\u51fa\u76ee\u9304 ConfigView.label.minPeersToBoostNoSeeds.tooltip=\u7576 torrent \u6c92\u6709\u7a2e\u5b50\uff0c\u4e14\u5925\u4f34\u6578\u6bd4\u60a8\u8a2d\u5b9a\u7684\u6578\u91cf\u5c11\uff0c /n \u8a72 torrent \u6703\u88ab\u79fb\u81f3\u6392\u7a0b\u7684\u6700\u5e95\u7aef\u3002 ConfigView.label.minPeersToBoostNoSeeds=\u964d\u4f4e\u505a\u7a2e\u7684\u7b49\u7d1a - \u6c92\u6709\u7a2e\u5b50\u6216\u662f\u7a2e\u5b50\u6578\u5c11\u65bc ConfigView.label.minSeedingTime.tooltip=\u505a\u7a2e\u7d1a\u5225\u53ef\u80fd\u5728\u6975\u77ed\u6642\u9593\u5167\u4e0d\u65b7\u8b8a\u52d5\uff0c\u6709\u6642\u5019\u6703\u5c0e\u81f4 torrent \u81ea\u52d5\u5730\u9023\u7e8c\u5feb\u901f\u555f\u52d5/\u505c\u6b62\u3002 \n \u9019\u9805\u8a2d\u5b9a\u53ef\u4ee5\u900f\u904e\u5f37\u5236 torrent \u5728\u4e00\u5b9a\u7684\u6642\u9593\u5167\u505a\u7a2e\uff0c\u9032\u800c\u964d\u4f4e\u9019\u500b\u56f0\u64fe\u3002\u60a8\u4e5f\u53ef\u4ee5\u624b\u52d5\u505c\u6b62\u9019\u500b\u8a2d\u5b9a\u3002 ConfigView.label.minSeedingTime=\u6700\u5c11\u7684\u505a\u7a2e\u6642\u9593 (\u4ee5\u79d2\u8a08) ConfigView.label.minSpeedForActiveDL.tooltip=\u7576\u672a\u5b8c\u6210\u7684 torrent \u555f\u52d5\u6642\uff0c\u4e0b\u8f09\u9023\u7dda\u6703\u5728\u6700\u521d\u7684 30 \u79d2\u88ab\u4f7f\u7528 ConfigView.label.minSpeedForActiveDL=\u4e0d\u8981\u5c07 torrent \u5217\u5165\u4e0b\u8f09\u6392\u7a0b-\u5982\u679c\u901f\u5ea6\u4f4e\u65bc ConfigView.label.peers=\u5925\u4f34 ConfigView.label.queue.debuglog=\u8a18\u9304\u9664\u932f\u8cc7\u8a0a ConfigView.label.queue.debuglog.info=\u5c07\u6392\u7a0b\u7684\u9664\u932f\u8cc7\u8a0a\u8a18\u9304\u81f3\u63a7\u5236\u53f0\u7684 log.\n \u96d6\u7136\u5f88\u96e3\u770b\u61c2\uff0c\u9664\u932f\u8cc7\u8a0a\u53ef\u4ee5\u544a\u8a34\u60a8\u9019\u500b torrent \u7684\u72c0\u614b\u4ee5\u53ca\u5b83\u70ba\u4f55\u6c92\u6709\u555f\u52d5\u6216\u662f\u5217\u5165\u6392\u7a0b\u3002 ConfigView.label.queue.minQueueingShareRatio=\u5728\u9054\u5230\u4e00\u5b9a\u7684\u5206\u4eab\u7387\u524d\u4e0d\u8981\u5c07 torrent \u505c\u6b62\u6216\u5217\u5165\u6392\u7a0b ConfigView.label.ratio=\u5206\u4eab\u7387 ConfigView.label.removeOnStop=\u81ea\u52d5\u505c\u6b62\u5f8c\uff0c\u5c07 torrent \u5f9e\u540d\u55ae\u4e0a\u522a\u9664 ConfigView.label.savedirectory=\u5b58\u6a94\u76ee\u9304 ConfigView.label.seeding.autoReposition.tooltip=\u7576\u555f\u52d5\u5f8c\uff0c torrent \u7684\u6392\u5217\u9806\u5e8f\u5c07\u6703\u4f9d\u7167\u505a\u7a2e\u7684\u7b49\u7d1a\u800c\u8b8a\u52d5\u3002 \n \u9019\u529f\u80fd\u5728\u60a8\u60f3\u77e5\u9053\u505a\u7a2e\u7b49\u7d1a\u7684\u7de8\u865f\u6642\u975e\u5e38\u6709\u7528 ConfigView.label.seeding.autoReposition=\u6839\u64da\u505a\u7a2e\u7b49\u7d1a\u81ea\u52d5\u91cd\u65b0\u5b9a\u4f4d torrents ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u4e00\u822c\u4f86\u8aaa\uff0c\u7a2e\u5b50\u6578\u76ee\u5c11\u4f46\u662f\u5925\u4f34\u6578\u91cf\u591a\u7684 torrent \u610f\u8b02\u8457\u5925\u4f34\u5011\u64c1\u6709\u7684\u6a94\u6848\u4e0d\u5b8c\u6574\u3002 \n \u56e0\u6b64\uff0c\u60a8\u61c9\u8a72\u4e0d\u6703\u60f3\u8981\u5047\u88dd\u6709\u5b8c\u6574\u7684\u6a94\u6848 (\u9019\u6a23\u53ef\u80fd\u6703\u4e0d\u6b63\u78ba\u5730\u964d\u4f4e\u7b49\u7d1a) ConfigView.label.seeding.fakeFullCopySeedStart=\u4f46\u662f\u50c5\u9069\u7528\u65bc\u5e95\u4e0b\u7684\u60c5\u6cc1 - torrents \u81f3\u5c11\u6709 ConfigView.label.seeding.ignore=\u5ffd\u7565\u898f\u5247 ConfigView.label.seeding.ignore0Peers=\u5ffd\u7565\u6c92\u6709\u5925\u4f34\u7684\u7684 torrent ConfigView.label.seeding.ignoreRatioPeers=\u5ffd\u7565 torrents-\u81f3\u5c11\u6709\u4e00\u500b\u7a2e\u5b50\u63d0\u4f9b\u7d66 ConfigView.label.seeding.ignoreShareRatio=\u5ffd\u7565 torrents-\u5171\u4eab\u7387\u70ba ConfigView.label.seeding.ignore.header.evenFirstPriority=\u5ffd\u7565 torrent, \u5982\u679c\n\u5957\u7528\u4e86\u6700\u9ad8\u512a\u5148\u9806\u5e8f ConfigView.label.seeding.ignore.header.rule=\u898f\u5247 ConfigView.label.seeding.ignore.header.value=\u6578\u503c ConfigView.label.seeding.firstPriority.info=\u6700\u9ad8\u512a\u5148\u9806\u5e8f\u7684 torrent \u5c07\u6703\u4e00\u76f4\u4fdd\u6301\u5728\u6392\u7a0b\u7684\u9802\u90e8.\n\u4efb\u4f55\u7b26\u5408\u6700\u9ad8\u512a\u5148\u9806\u5e8f\u7684 torrents \u4e0d\u6703\u81ea\u52d5\u505c\u6b62\u6216\u662f\u6392\u7a0b.\n\u7b26\u5408\u6700\u9ad8\u512a\u5148\u9806\u5e8f\u7684 torrent \u5982\u6709\u5fc5\u8981\u5c07\u540c\u6642\u4e0b\u8f09 ConfigView.label.seeding.firstPriority.FP=\u6700\u512a\u5148 ConfigView.label.seeding.firstPriority=\u9ad8\u512a\u5148\u9806\u5e8f\u7d66\u4e88 ConfigView.label.seeding.firstPriority.following=\u7b26\u5408\u4ee5\u4e0b\u689d\u4ef6\u7684 torrent \u5217\u70ba\u6700\u512a\u5148: ConfigView.label.seeding.firstPriority.shareRatio=\u5171\u4eab\u7387\u4f4e\u65bc ConfigView.label.seeding.firstPriority.seedingMinutes=\u5f9e\u4e0b\u8f09\u72c0\u614b\u6539\u8b8a\u70ba\u505a\u7a2e\u72c0\u614b\u5f8c\uff0c\u7d93\u904e\u7684\u6642\u9593 ConfigView.label.seeding.firstPriority.DLMinutes=\u4e0b\u8f09\u958b\u59cb\u5f8c\uff0c\u7d93\u904e\u7684\u6642\u9593 ConfigView.label.seeding.numPeersAsFullCopy.tooltip=\u5047\u88dd\u6bcf X \u500b\u5925\u4f34\u5c31\u6709\u4e00\u500b\u5b8c\u6574\u7684\u6a94\u6848\u62f7\u8c9d\uff0c\u5728\u5925\u4f34\u773e\u591a\u6642\u53ef\u4ee5\u964d\u4f4e torrent \u7684\u7b49\u7d1a\n\u5927\u591a\u6578\u60c5\u6cc1\u4e0b\uff0c\u8a72 torrent \u7684\u5925\u4f34\u6578\u91cf\u8d8a\u591a\u4e5f\u610f\u5473\u8457\u50b3\u8f38\u91cf\u8d8a\u5927\n\u9019\u4e26\u4e0d\u6703\u6539\u8b8a\u986f\u793a\u7684\u7a2e\u5b50\u6578\u91cf ConfigView.label.seeding.numPeersAsFullCopy=\u5047\u88dd\u5df2\u6709\u4e00\u500b\u5b8c\u6574\u7684\u62f7\u8c9d\u80fd\u5920\u5206\u914d\u7d66\n(0\uff1a\u4e0d\u8981\u5047\u88dd) ConfigView.label.seeding.preferLargerSwarms.tooltip=\u5982\u679c\u60a8\u4e3b\u8981\u662f\u70ba\u4e0b\u8f09\u505c\u9813\u4f4f\u7684\u5925\u4f34\u5011\u505a\u7a2e\uff0c\u61c9\u8a72\u9078\u64c7\u8f03\u5927\u7684 swarms\u3002 \n\u7576\u60a8\u5728\u7a2e\u5b50\u4f86\u6e90\u6578\u591a\u7684 torrent \u74b0\u5883\u4e2d\u505a\u7a2e\u6642\uff0c\u9078\u64c7\u5c0f\u7684 swarms \u6703\u6bd4\u8f03\u597d\u3002 ConfigView.label.seeding.preferLargerSwarms=\u7576 torrents \u7684\u7b49\u7d1a\u76f8\u540c\u6642\uff0c\u9078\u64c7\u8f03\u5927\u7684 swarms ConfigView.label.seeding.rankType.none.tooltip=\u4f9d\u64da # \u884c\u4f86\u6c7a\u5b9a\u9806\u5e8f ConfigView.label.seeding.rankType.none=\u7121 ConfigView.label.seeding.rankType.peerSeed.options=\u7a2e\u5b50\uff1a\u5925\u4f34\u6bd4\u7387\u9078\u9805 ConfigView.label.seeding.rankType.peerSeed.tooltip=\u9ad8\u6bd4\u7387 = \u9ad8\u7b49\u7d1a ConfigView.label.seeding.rankType.peerSeed=\u5925\u4f34\uff1a\u505a\u7a2e\u6bd4\u7387 ConfigView.label.seeding.rankType.seed.fallback=\u6539\u8b8a\u5230\u5925\u4f34:\u7a2e\u5b50\u6bd4\u7387\u898f\u5247\uff0c\u7576\u7a2e\u5b50\u6578\u9054\u5230\n[0: \u6c38\u9060\u4e0d\u6539\u8b8a] ConfigView.label.seeding.rankType.seed.options=\u53ea\u8a08\u7b97\u7a2e\u5b50\u7684\u9078\u9805 ConfigView.label.seeding.rankType.seed.tooltip=\u8f03\u5c11\u7a2e\u5b50 = \u8f03\u9ad8\u7b49\u7d1a ConfigView.label.seeding.rankType.seed=\u53ea\u8a08\u7b97\u7a2e\u5b50\u6578 ConfigView.label.seeding.rankType.timedRotation.tooltip=\u6240\u6709\u5217\u5728\u6392\u7a0b\u4e2d\uff0c\u5df2\u5b8c\u6210\u7684 torrent \u6703\u8f2a\u6d41\u505a\u7a2e\n\u505a\u7a2e\u7684\u6642\u9593\u53ef\u4ee5\u5728"\u6700\u5c0f\u505a\u7a2e\u6642\u9593"\u88e1\u8a2d\u5b9a ConfigView.label.seeding.rankType.timedRotation=\u5b9a\u6642\u5faa\u74b0 ConfigView.label.seeding.rankType.tooltip=\u6700\u9ad8\u7b49\u7d1a\u7684 torrents \u6703\u81ea\u52d5\u555f\u52d5\n\u7576\u53e6\u4e00\u500b torrent \u9054\u5230\u8f03\u9ad8\u7684\u7b49\u7d1a\u6642\uff0c\u8f03\u4f4e\u7b49\u7d1a\u7684 torrent \u6703\u505c\u6b62\u50b3\u8f38\u4e26\u56de\u5230\u6392\u7a0b\u4e2d\n\n\u53ea\u6709\u5217\u5728\u6392\u7a0b\u4e2d\u7684 torrent \u53ef\u4ee5\u81ea\u52d5\u555f\u52d5\n\u88ab\u8a2d\u70ba"\u505c\u6b62"\u7684 torrent \u6c38\u9060\u4e0d\u6703\u81ea\u52d5\u555f\u52d5 ConfigView.label.seeding.rankType=\u6839\u64da\u5df2\u5b8c\u6210\u7684 torrent \u7b49\u7d1a,\u6c7a\u5b9a\u662f\u5426\u81ea\u52d5\u555f\u52d5 ConfigView.label.stopAfterMinutes=\u4e00\u65e6\u8f49\u63db\u70ba\u505a\u7a2e\u6a21\u5f0f\uff0c\u7d93\u904e\u4e00\u6bb5\u6642\u9593\u5f8c\u505c\u6b62 ConfigView.label.switchpriority.tooltip=\u8a2d\u70ba\u4f4e\u512a\u5148\u6b0a\uff0c\u53ef\u4ee5\u6e1b\u5c11 torrent \u5206\u914d\u5230\u7684\u4e0a\u50b3\u983b\u5bec ConfigView.pluginlist.info=\u4e0b\u5217\u7684\u5916\u639b\u6a21\u7d44\u5df2\u88ab\u8fa8\u8b58\u51fa\u4f86\u3002\u90e8\u4efd\u5916\u639b\u6a21\u7d44\u53ef\u80fd\u6c92\u6709\u8a2d\u5b9a\u9078\u55ae\u3002 ConfigView.pluginlist.noplugins=\u6c92\u6709\u767c\u73fe\u4efb\u4f55\u5916\u639b\u6a21\u7d44 ConfigView.section.pluginslist=\u5217\u8868 ConfigView.section.queue.seeding=\u505a\u7a2e\u6642 ConfigView.section.queue.seeding.autoStarting=\u81ea\u52d5\u555f\u52d5 ConfigView.section.queue.seeding.ignore=\u5ffd\u7565\u898f\u5247 ConfigView.section.queue.seeding.firstPriority=\u6700\u9ad8\u512a\u5148\u9806\u5e8f ConfigView.section.queue.main=\u4e3b\u8981 ConfigView.section.queue=\u6392\u7a0b ConfigView.section.torrents=Torrent ConfigView.text.all=\u5168\u90e8 ConfigView.text.hours=\u5c0f\u6642 ConfigView.text.ignoreRule=\u5ffd\u7565\u898f\u5247 ConfigView.text.ignore=\u5ffd\u7565 ConfigView.text.minutes=\u5206 ConfigView.text.neverIgnore=\u6c38\u4e0d\u5ffd\u7565 ConfigView.text.any=\u4efb\u4f55 DownloadManager.error.datamissing=\u8cc7\u6599\u907a\u5931 MainWindow.menu.file.open.torrentforseeding=Torrent \u6a94... (\u505a\u7a2e\u7528) MainWindow.menu.language.refresh=\u91cd\u65b0\u8b80\u53d6 (&R) ManagerItem.forced=\u5f37\u5236 ManagerItem.queued=\u6392\u7a0b MySeedersView.header=\u5b8c\u6210\u7684 Torrents TableColumn.header.availability.info=\u51fa\u73fe\u904e\u7684\u5b8c\u6574\u6a94\u6848\u6578 TableColumn.header.availability=\u53ef\u7528\u5ea6 TableColumn.header.category=\u5206\u985e MyTorrentsView.header=\u672a\u5b8c\u6210\u7684 Torrent TableColumn.header.maxuploads=\u6700\u5927\u4e0a\u50b3\u6578\u76ee MyTorrentsView.menu.category.delete=\u522a\u9664\u5206\u985e (&D) MyTorrentsView.menu.forceStart=\u5f37\u5236\u555f\u52d5 (&F) MyTorrentsView.menu.queue=\u6392\u7a0b (&Q) MyTorrentsView.menu.setCategory.add=\u589e\u52a0\u5206\u985e... (&A) MyTorrentsView.menu.setCategory=\u6307\u5b9a\u5206\u985e TableColumn.header.savepath=\u5b58\u6a94\u8def\u5f91 TableColumn.header.SeedingRank=\u505a\u7a2e\u7b49\u7d1a TableColumn.header.totalspeed.info=\u6240\u6709\u60a8\u5df2\u9023\u7dda\u7684\u5925\u4f34\u6574\u9ad4\u901f\u5ea6 TableColumn.header.totalspeed=\u6574\u9ad4\u901f\u5ea6 splash.initializePlugins=\u6b63\u5728\u521d\u59cb\u5316\u5916\u639b\u6a21\u7d44 StartStopRules.SPratioMet=S:P \u6bd4\u7387 OK StartStopRules.FP0Peers=FP / 0 \u5925\u4f34 StartStopRules.0Peers=0 \u500b\u5925\u4f34 StartStopRules.numSeedsMet=\u7a2e\u5b50\u6578 OK StartStopRules.ratioMet=\u5925\u4f34:\u7a2e\u5b50 OK StartStopRules.shareRatioMet=\u5206\u4eab\u7387 OK StartStopRules.waiting=\u7b49\u5f85\u4e2d StartStopRules.firstPriority=\u6700\u9ad8\u512a\u5148\u9806\u5e8f ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\u5171\u4eab\u5167\u5bb9\uff08\u905e\u8ff4\uff09 DownloadManager.error.unabletostartserver=\u7121\u6cd5\u555f\u52d5\u4f3a\u670d\u5668 - \u8acb\u6aa2\u67e5\u50b3\u5165\u9023\u63a5\u57e0\u8a2d\u5b9a\u548c\u9632\u706b\u7246\u6b0a\u9650\u4ee5\u555f\u52d5\u4f3a\u670d\u5668\u3002 GeneralView.label.creationdate=\u5efa\u7acb\u6642\u9593 : ConfigView.section.tracker.announcescrapepercentage=\u5c07 tracker \u767c\u4f48\u7684\u5e74\u9f61\u6bd4\u8996\u70ba Scrape \u9593\u9694\ne.g. 200 = 2:1. 0 =\u8b93\u5925\u4f34\u6c7a\u5b9a ManagerItem.stopping=\u6b63\u5728\u505c\u6b62\u4e2d ConfigView.section.tracker.announcecacheperiod=\u767c\u4f48\u5feb\u53d6\uff08\u6beb\u79d2\uff09 ConfigView.section.tracker.scrapecacheperiod=Scrape \u5feb\u53d6\uff08\u6beb\u79d2\uff09 ConfigView.section.tracker.scrapeandcache=Scrape \u4e26\u5feb\u53d6 ConfigView.section.tracker.announcecacheminpeers=\u555f\u7528\u901a\u544a\u7de9\u5b58\uff0c\u7576\u5925\u4f34\u6578\u9054\u5230 MyTrackerView.scrapes=Scrape fileDownloadWindow.retry=\u91cd\u8a66 MyTrackerView.bytesin=\u63a5\u6536\u7684\u4f4d\u5143\u7d44 MyTrackerView.bytesinave=\u5e73\u5747\u63a5\u6536 MyTrackerView.bytesout=\u9001\u51fa\u7684\u4f4d\u5143\u7d44 MyTrackerView.bytesoutave=\u5e73\u5747\u9001\u51fa ConfigView.section.file.max_open_files=\u4f9b\u8b80 / \u5beb\u7684\u6a94\u6848\u6700\u5927\u958b\u555f\u6578\n[0\uff1a\u7121\u9650\u5236] ConfigView.section.file.max_open_files.tooltip=\u5982\u679c\u60a8\u4e0b\u8f09\u7684 torrent \u542b\u6709\u6578\u767e/\u6578\u5343\u4ee5\u4e0a\u7684\u6a94\u6848\uff0c\u6216\u662f torrent \u542b\u6709\u8d85\u904e\u4f5c\u696d\u7cfb\u7d71\u5141\u8a31\u7684\u6a94\u6848\u6578\u91cf\uff0c\u9019\u500b\u9078\u9805\u5c07\u6703\u975e\u5e38\u6709\u7528\u3002 ConfigView.section.proxy=\u4ee3\u7406\u4f3a\u670d\u5668\u9078\u9805 ConfigView.section.proxy.enable_proxy=\u555f\u7528 tracker \u901a\u8a0a\u7684\u4ee3\u7406\u4f3a\u670d\u6a21\u5f0f [\u9700\u8981\u91cd\u65b0\u555f\u52d5] ConfigView.section.proxy.host=Host. ConfigView.section.proxy.port=\u9023\u63a5\u57e0 ConfigView.section.proxy.username=\u4f7f\u7528\u8005\u540d\u7a31 ConfigView.section.proxy.password=\u5bc6\u78bc ConfigView.section.proxy.enable_socks=\u6211\u6709 SOCKS \u4ee3\u7406\u4f3a\u670d\u5668 wizard.createtorrent.extrahashes=\u70ba\u5176\u4ed6\u7db2\u8def\u52a0\u5165 Hashes (e.g. Gnutella2, eDonkey2000) GeneralView.label.connected=\u5df2\u9023\u7dda GeneralView.label.in_swarm=\u5728\u7fa4\u7d44\u5167 ManagerItem.initializing=\u521d\u59cb\u5316 AlertMessageBox.error=\u932f\u8aa4 AlertMessageBox.warning=\u8b66\u544a AlertMessageBox.comment=\u8cc7\u8a0a AlertMessageBox.information=\u8cc7\u8a0a SharedPortServer.alert.selectorfailed=\u7121\u6cd5\u5efa\u7acb\u4f86\u6e90\u8cc7\u6599\u7684\u76e3\u807d \n\u8acb\u6aa2\u67e5\u9632\u706b\u7246\u8a2d\u5b9a\u662f\u5426\u5141\u8a31 Java \u5efa\u7acb\u4f3a\u670d\u5668 Tracker.alert.listenfail=\u5728\u9023\u63a5\u57e0 %1 \u5efa\u7acb\u76e3\u807d\u5931\u6557.\n\u8acb\u6aa2\u67e5\u662f\u5426\u6709\u5225\u7684\u61c9\u7528\u7a0b\u5f0f\u4f54\u7528\u6b64\u9023\u63a5\u57e0.\n\u540c\u6642\u6aa2\u67e5\u662f\u5426\u6709\u5225\u7684 Vuze \u7528\u6236\u4f7f\u7528\u9019\u500b\u9023\u63a5\u57e0 DiskManager.alert.movefileexists=\u79fb\u52d5\u5df2\u5b8c\u6210\u7684\u6a94\u6848\u932f\u8aa4\n\u6a94\u6848 %1 \u5df2\u7d93\u5b58\u5728\u65bc\u6b32\u79fb\u52d5\u7684\u76ee\u7684\u5730\u76ee\u9304 DiskManager.alert.movefilefails=\u79fb\u52d5\u5df2\u5b8c\u6210\u7684\u6a94\u6848\u932f\u8aa4\n \u6a94\u6848 %1 \u79fb\u52d5\u5931\u6557\uff0c%2 DiskManager.alert.movefilerecoveryfails=\u79fb\u52d5\u5f8c\u56de\u5fa9\u6a94\u6848\u5931\u6557\u932f\u8aa4\n\u56de\u5fa9\u6a94\u6848 %1 \u5931\u6557\uff0c%2 ConfigView.section.tracker.logenable=\u5b9a\u671f\u5c07\u7d71\u8a08\u8cc7\u6599\u8a18\u9304\u81f3 'tracker.log' SpeedView.stats.title=\u7d71\u8a08 SpeedView.stats.total=\u7e3d\u8a08 SpeedView.stats.session=\u672c\u6b21 SpeedView.stats.session.tooltip=\u7e3d\u8a08 (\u5354\u5b9a) SpeedView.stats.downloaded=\u5df2\u4e0b\u8f09 (\u5354\u5b9a) SpeedView.stats.uploaded=\u5df2\u4e0a\u50b3 (\u5354\u5b9a) SpeedView.stats.ratio=\u5206\u4eab\u7387 SpeedView.stats.uptime=\u4e0a\u50b3\u6642\u9593 SpeedView.stats.now=\u73fe\u5728 SpeedView.stats.now.tooltip=\u7e3d\u8a08 (\u5354\u5b9a) AutoMigration.useralert=Vuze \u4f7f\u7528\u8005\u8a2d\u5b9a\u6a94\u6848/\u76ee\u9304\u81ea\u52d5\u79fb\u52d5\u7d50\u679c:\n\n%1\n\u4efb\u4f55\u5931\u6557\u90fd\u5fc5\u9808\u624b\u52d5\u79fb\u52d5.\n\u5982\u679c\u6a94\u6848\u88ab\u79fb\u52d5\u4e86\uff0c\u4e0d\u8981\u5fd8\u8a18\u5728\u8a2d\u5b9a\u4e2d\u66f4\u65b0\u60a8\u7684\u5b58\u6a94\u8def\u5f91 # # > 2.0.8.0 # OpenTorrentWindow.title=\u958b\u555f torrent OpenTorrentWindow.message=\u5be6\u9a57\u4e2d OpenTorrentWindow.addFiles=\u52a0\u5165\u6a94\u6848 (&A) OpenTorrentWindow.dataLocation=\u5132\u5b58\u8cc7\u6599\u7684\u4f4d\u7f6e: OpenTorrentWindow.startMode=\u52a0\u5165\u6a21\u5f0f OpenTorrentWindow.startMode.queued=\u6392\u7a0b OpenTorrentWindow.startMode.stopped=\u505c\u6b62 OpenTorrentWindow.startMode.forceStarted=\u5f37\u5236\u555f\u52d5 OpenTorrentWindow.addPosition=\u6392\u7a0b\u4f4d\u7f6e OpenTorrentWindow.addPosition.first=\u6700\u521d OpenTorrentWindow.addPosition.last=\u6700\u5f8c TableColumn.header.remaining.info=\u9084\u6709\u591a\u5c11\u8981\u4e0b\u8f09 TableColumn.header.remaining=\u5269\u9918 ConfigView.section.tracker.enablecompact=\u555f\u7528\u7c21\u6f54\u7684\u767c\u4f48\u5354\u5b9a ConfigView.section.tracker.enablekey=\u5728 tracker \u555f\u7528 key passing \u4ee5\u5f37\u5316\u5b89\u5168\u6027 ConfigView.section.file.perf=\u504f\u597d\u8a2d\u5b9a\u9078\u9805 ConfigView.section.file.perf.explain=\u8b66\u544a - \u4e0d\u9069\u7576\u7684\u6539\u8b8a\u9019\u4e9b\u53c3\u6578\u53ef\u80fd\u6703\u5927\u5e45\u5f71\u97ff\u4e0b\u8f09\u8868\u73fe\u3002\u9700\u8981\u91cd\u65b0\u555f\u52d5\n\u5982\u679c\u60a8\u6709"\u8a18\u61b6\u9ad4\u4e0d\u8db3"\u7684\u554f\u984c\uff0c\u8a66\u8457\u9650\u5236\u6bcf\u500b torrent \u7684\u9023\u7dda\u6578\u76ee\uff08\u53c3\u7167"\u50b3\u8f38\u8a2d\u5b9a"\uff09 ConfigView.section.file.max_open_files.explain=\u82e5\u662f\u958b\u555f\u904e\u591a\u6a94\u6848\uff0c\u6703\u56e0\u70ba\u8cc7\u6e90\u9650\u5236\u800c\u5c0e\u81f4\u7cfb\u7d71\u51fa\u932f\u3002\u9019\u500b\u9078\u9805\u53ef\u4ee5\u9650\u5236\u540c\u6642\u958b\u555f\u7684\u6a94\u6848\u6578\u91cf popup.error.hide=\u96b1\u85cf popup.error.details=\u8a73\u7d30\u60c5\u5f62 ConfigView.section.style.colorOverrides=\u984f\u8272\u7f6e\u63db ConfigView.section.style.colorOverride.progressBar=\u9032\u5ea6\u689d ConfigView.section.style.colorOverride.error=\u932f\u8aa4 MainWindow.status.tooOld=\u7248\u672c\u5df2\u7d93\u592a\u820a,\u8acb\u66f4\u65b0 ConfigView.section.style.colorOverride.warning=\u8b66\u544a ConfigView.section.style.colorOverride.altRow=\u66ff\u4ee3\u5217 ConfigView.section.file.save.peers.enable=\u5132\u5b58\u5925\u4f34\u9023\u7dda\u8cc7\u6599\u4ee5\u4f9b\u5feb\u901f\u91cd\u65b0\u9023\u7dda ConfigView.section.file.save.peers.max=\u53ef\u5132\u5b58\u7684\u6700\u5927\u5925\u4f34\u6578 [0: \u7121\u9650\u5236] ConfigView.section.file.save.peers.pertorrent=\u6bcf\u500b torrent ConfigView.label.max_peers_per_torrent=\u55ae\u4e00 torrent \u9810\u8a2d\u6700\u5927\u9023\u7dda\u6578 [0\uff1a\u7121\u9650\u5236] ConfigView.label.max_peers_total=\u7e3d\u9ad4\u6700\u5927\u9023\u7dda\u6578 [0\uff1a\u7121\u9650\u5236] ConfigView.section.style.colorOverrides.reset=\u91cd\u7f6e\u984f\u8272 ConfigView.section.language.info=\u555f\u7528\uff1a\u6bcf\u6b21 Vuze \u555f\u52d5\u6642\u6703\u6aa2\u67e5\u66f4\u65b0 ConfigView.section.language.enableUpdate=\u555f\u7528\u7db2\u9801\u66f4\u65b0 ConfigView.section.language.UpdateURL=\u66f4\u65b0 URL ConfigView.section.language.UpdateNow=\u99ac\u4e0a\u66f4\u65b0\uff01 Button.revert=\u56de\u5fa9 MyTorrentsView.menu.changeDirectory=\u66f4\u6539\u8cc7\u6599\u76ee\u9304 GenericText.column=\u884c MyTorrentsView.menu.thisColumn.remove=\u522a\u9664\u884c\u9805\u76ee MyTorrentsView.menu.thisColumn.toClipboard=\u5c07\u6587\u5b57\u62f7\u8c9d\u81f3\u526a\u8cbc\u7c3f MyTorrentsView.menu.tracker=Tracker\u72c0\u614b TableColumn.header.secondsseeding=\u505a\u7a2e\u6642\u9593 TableColumn.header.secondsseeding.info=\u60a8\u5df2\u505a\u7a2e\u7684\u5168\u90e8\u6642\u9593 TableColumn.header.secondsdownloading=\u4e0b\u8f09\u6642\u9593 TableColumn.header.secondsdownloading.info=\u60a8\u4e0b\u8f09\u7684\u7e3d\u6642\u9593 ConfigView.section.tracker.udpversion=UDP \u5354\u5b9a\u7248\u672c\uff081 \u6216 2\uff09 window.updateswt.title=\u60a8\u7684 SWT \u7248\u672c\u592a\u820a\u4e86! window.updateswt.text=\u60a8\u7684 SWT \u7248\u672c\u592a\u820a\u4e86!\nSWT \u662f Vuze \u4f7f\u7528\u7684\u5716\u5f62\u5eab, \u60a8\u6240\u4f7f\u7528\u7684\u7248\u672c\u592a\u820a,\u65b0\u7248\u7684Vuze u4e0d\u9069\u7528. \u8acb\u6309\u4e0b"\u78ba\u5b9a"\u4f86\u66f4\u65b0 SWT. window.updateswt.status=\u72c0\u614b window.updateswt.failed=\u66f4\u65b0\u5931\u6557,\u8acb\u6309\u4e0b"\u78ba\u5b9a"\u91cd\u65b0\u958b\u59cb window.updateswt.status.downloading.updater=\u66f4\u65b0\u6a21\u7d44\u4e0b\u8f09\u4e2d window.updateswt.status.finding=\u5c0b\u627eSWT\u7684\u6700\u65b0\u7248\u672c window.updateswt.status.downloading=\u65b0\u7248 SWT \u4e0b\u8f09\u4e2d window.updateswt.status.done=\u6b63\u5728\u91cd\u65b0\u555f\u52d5 window.updateswt.ok=\u78ba\u5b9a window.updateswt.cancel=\u53d6\u6d88 swt.updater.downloader.downloading=SWT \u4e0b\u8f09\u4e2d,\u4f86\u6e90: swt.updater.urlsgetter.downloading=\u53d6\u5f97\u5217\u8868\u93e1\u50cf\u4f86\u6e90 swt.updater.urlsgetter.platform=SWT \u5e73\u53f0 : window.updateswt.ignore=\u5ffd\u7565 ConfigView.section.style.useFancyTabs=\u4f7f\u7528\u7f8e\u89c0\u7684\u5206\u9801 splash.initializeGM=Torrent \u7ba1\u7406\u7a0b\u5f0f\u521d\u59cb\u5316\u4e2d splash.loadingTorrents=Torrents \u8f09\u5165\u4e2d splash.firstMessageNoI18N=(: \u6bd2\u86d9 :) MyTorrentsView.menu.thisColumn.sort=\u6392\u5e8f Scrape.status.ok=Scrape \u5b8c\u6210 Scrape.status.error=Scrape \u932f\u8aa4: Scrape.status.error.badURL=\u767c\u4f48 URL \u4e0d\u7b26\u5408 scrape \u7279\u6027 Scrape.status.error.nohash=Hash \u7684\u56de\u61c9\u907a\u5931. Scrape.status.error.invalid=\u7121\u6548\u7684\u56de\u61c9 Scrape.status.nextScrapeAt=\u4e0b\u4e00\u500b scrape \u5728 %1 Scrape.status.scraping=\u6b63\u5728 Scraping.. Scrape.status.initializing=\u7b49\u5f85 Scrape ConfigView.label.minSpeedForActiveSeeding=\u4e0d\u8981\u5c07\u5df2\u5b8c\u6210\u7684 torrent \u5217\u5165\u6392\u7a0b-\u5982\u679c\u901f\u5ea6\u4f4e\u65bc ConfigView.section.stats.exportpeers=\u532f\u51fa\u5925\u4f34\u8a73\u7d30\u8cc7\u6599 MainWindow.menu.view.irc.moved=\u73fe\u5728\u53ef\u900f\u904e\u5916\u639b\u6a21\u7d44\u9023\u7d50 IRC, \u8acb\u53c3\u8003 http://azureus.sourceforge.net/plugin_list.php. \u7576\u5b89\u88dd\u5b8c\u7562\u5f8c\u8acb\u4f7f\u7528 \u6aa2\u8996->\u5916\u639b\u6a21\u7d44->IRC \u9078\u55ae\u9032\u5165\u3002 MyTrackerView.webui.contextmenu.copyurl=\u62f7\u8c9d torrent \u7684 URL \u81f3\u526a\u8cbc\u7c3f ConfigView.section.file.torrent.ignorefiles=\u5efa\u7acb torrents \u6642\uff0c\u53ef\u5ffd\u7565\u7684\u6a94\u6848\ne.g. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=\u6a94\u6848\u5ffd\u7565\u4e2d ConfigView.section.style.useUnitsRateBits=\u4f7f\u7528\u4f4d\u5143\u8a08\u91cf\uff0c\u800c\u4e0d\u662f\u4f4d\u5143\u7d44\u4f86\u8a08\u7b97\u901f\u7387\uff08KiB/s->Kibit/s etc.\uff09 ConfigView.section.interface.resetassoc=\u91cd\u8a2d torrent \u6a94\u6aa2\u8996\u95dc\u806f (.torrent) ConfigView.section.interface.resetassocbutton=\u91cd\u8a2d ConfigView.section.interface.checkassoc=\u555f\u52d5\u6642\u6aa2\u67e5\u6a94\u6848\u95dc\u806f dialog.associations.title=\u95dc\u806f\u6027\u6aa2\u67e5 Button.yes=\u662f Button.no=\u5426 ConfigView.label.seeding.autoStart0Peers=\u7576\u6240\u6709\u5b8c\u6210\u7684 torrents \u90fd\u6c92\u6709\u5925\u4f34\u6642\u81ea\u52d5\u555f\u52d5 ConfigView.label.seeding.autoStart0Peers.tooltip=\u5982\u679c\u60a8\u5e0c\u671b tracker \u5c07\u7a2e\u5b50\u5217\u70ba 0 \u500b\u5925\u4f34\u7684 torrents\uff0c\u8acb\u958b\u555f\u9019\u9805\u8a2d\u5b9a dialog.associations.prompt=Vuze \u4e0d\u662f\u9810\u8a2d\u7684 BitTorrent \u6a94\u958b\u555f\u7a0b\u5f0f\u3002\n\u60a8\u8981\u5c07 Vuze \u8a2d\u70ba .torrent \u7684\u9810\u8a2d\u958b\u555f\u7a0b\u5f0f\u55ce\uff1f dialog.associations.askagain=\u958b\u555f\u6642\u6aa2\u67e5 ConfigView.section.plugins.update=\u66f4\u65b0\u5916\u639b\u6a21\u7d44 Plugin.pluginupdate.enablecheck=\u555f\u52d5\u5916\u639b\u6a21\u7d44\u66f4\u65b0\u6aa2\u67e5 plugins.basicview.status=\u72c0\u614b: plugins.basicview.activity=\u6d3b\u52d5: plugins.basicview.progress=\u9032\u5ea6: plugins.basicview.log=Log\u8a18\u9304: ConfigView.label.maxdownloadspeed=\u6574\u9ad4\u6700\u5927\u4e0b\u8f09\u901f\u5ea6 (KB/s) [0\uff1a\u7121\u9650\u5236] splash.loadingTorrent=Torrents \u8f09\u5165\u4e2d splash.of=/ ConfigView.section.plugins.irc=IRC \u983b\u9053 UpdateWindow.title=Vuze \u66f4\u65b0\u7a0b\u5f0f UpdateWindow.header=\u4e0b\u5217\u5143\u4ef6\u9700\u8981\u66f4\u65b0 : UpdateWindow.columns.install=\u5b89\u88dd UpdateWindow.columns.name=\u540d\u7a31 UpdateWindow.columns.version=\u7248\u672c UpdateWindow.columns.size=\u5927\u5c0f UpdateWindow.cancel=\u53d6\u6d88 UpdateWindow.quit=\u7d42\u6b62 UpdateWindow.close=\u95dc\u9589 UpdateWindow.ok=\u66f4\u65b0 UpdateWindow.restart=\u91cd\u65b0\u555f\u52d5 UpdateWindow.status.downloading=\u4e0b\u8f09\u4e2d UpdateWindow.status.done=\u5b8c\u6210 UpdateWindow.status.failed=\u5931\u6557 UpdateWindow.status.restartNeeded=\u5fc5\u9808\u91cd\u65b0\u555f\u52d5 ConfigView.pluginlist.broken=\u640d\u58de ConfigView.pluginlist.whereToPut=\u5c07\u7279\u5b9a\u4f7f\u7528\u8005\u7684\u5916\u639b\u6a21\u7d44\u653e\u5728\u4ed6\u5011\u81ea\u5df1\u7684\u76ee\u9304\u4e0b ConfigView.pluginlist.whereToPutOr=\u5171\u7528\u7684\u5916\u639b\u6a21\u7d44\u653e\u7f6e\u4f4d\u7f6e: MainWindow.statusText.checking=\u6aa2\u67e5\u66f4\u65b0 TableColumn.header.OnlyCDing4=\u7d14\u505a\u7a2e\u6642\u9593 TableColumn.header.OnlyCDing4.info=\u8a72 torrent \u7d14\u505a\u7a2e\u7684\u6642\u9593,\u4e0d\u5305\u542b\u540c\u6642\u4e0b\u8f09/\u4e0a\u50b3\u7684\u6642\u9593 ConfigView.section.style.alternateTablePainting=\u4f7f\u7528\u66ff\u4ee3\u65b9\u5f0f\u7e6a\u88fd\u5716\u5f62\u8868\u6b04\u4f4d\uff08\u53ef\u80fd\u9700\u8981\u91cd\u65b0\u555f\u52d5\uff09 UpdateWindow.status.restartMaybeNeeded=\u5fc5\u9808\u91cd\u65b0\u555f\u52d5 ConfigView.pluginlist.shared=\u5171\u4eab PeersView.host=\u7db2\u8def\u540d\u7a31 PeersView.host.info=\u5925\u4f34\u7684\u7db2\u8def\u540d\u7a31,\u5982\u679c\u6709\u7684\u8a71 (\u53ef\u80fd\u6703\u5f71\u97ff\u6548\u80fd) MainWindow.menu.help.whatsnew=\u65b0\u6771\u897f ConfigView.label.checkonstart=\u7576 Vuze \u555f\u52d5\u6642\u6aa2\u67e5\u65b0\u7248\u672c ConfigView.label.periodiccheck=\u5b9a\u671f\u6aa2\u67e5\u6700\u65b0\u7684\u7248\u672c ConfigView.label.opendialog=\u7576\u6709\u66f4\u65b0\u6a94\u6642\uff0c\u81ea\u52d5\u958b\u555f"\u66f4\u65b0\u5c0f\u5e6b\u624b" MainWindow.updateavail=\u6309\u6b64\u66f4\u65b0 MainWindow.status.latestversionunchecked=\u7248\u672c\u66f4\u65b0\u88ab\u505c\u7528 GeneralView.label.updatein.stopped=\u5df2\u505c\u6b62 StartStopRules.menu.viewDebug=\u6aa2\u8996\u9664\u932f\u8cc7\u8a0a ConfigView.section.style.doNotUseGB=\u4e0d\u8981\u4f7f\u7528 GB \u55ae\u4f4d ConfigView.section.style.doNotUseGB.tooltip=\u52fe\u9078\u6b64\u9805\uff0c\u5373\u4f7f\u6a94\u6848\u5927\u5c0f\u8d85\u904e 1024MB\uff0cVuze \u4ecd\u6703\u4f7f\u7528 MB \u4f5c\u70ba\u986f\u793a\u55ae\u4f4d\u3002 MainWindow.menu.help.plugins=\u53d6\u5f97\u5916\u639b\u6a21\u7d44 ConfigView.section.plugins.TrackerWeb=Tracker \u7db2\u9801 ConfigView.section.tracker.enablecategories=\u4ee5\u5206\u985e\u5340\u9694 torrents health.explain.share=\u8868\u793a\u8a72 torrent \u6c92\u6709\u4e3b\u6a5f\u6216\u662f\u88ab\u767c\u4f48\u904e ConfigView.section.tracker.createcert=\u5efa\u7acb\u81ea\u6211\u7c3d\u7f72\u6191\u8b49 ConfigView.section.tracker.createbutton=\u5efa\u7acb security.certcreate.title=\u5efa\u7acb\u81ea\u6211\u7c3d\u7f72\u7684\u6191\u8b49 security.certcreate.intro=\u9019\u500b\u5c0d\u8a71\u7a97\u8b93\u60a8\u80fd\u5920\u5efa\u7acb\u81ea\u6211\u7c3d\u7f72\u7684\u6191\u8b49 security.certcreate.alias=\u5225\u540d security.certcreate.strength=\u5f37\u5ea6 security.certcreate.firstlastname=\u59d3\u548c\u540d security.certcreate.orgunit=\u7d44\u7e54\u55ae\u4f4d security.certcreate.org=\u7d44\u7e54 security.certcreate.city=\u57ce\u5e02 security.certcreate.state=\u5dde\u6216\u7701 security.certcreate.country=\u96d9\u5b57\u5143\u570b\u78bc security.certcreate.ok=\u5efa\u7acb security.certcreate.cancel=\u53d6\u6d88 security.certcreate.createok=\u6191\u8b49\u5efa\u7acb\u6210\u529f security.certcreate.createfail=\u6191\u8b49\u5efa\u7acb\u5931\u6557 ConfigView.section.plugins.webui=\u639b\u4e0a\u7db2\u9801\u754c\u9762 ConfigView.section.plugins.xml_http_if=XML/HTTP \u754c\u9762 webui.passwordenable=\u555f\u52d5\u5bc6\u78bc webui.user=\u4f7f\u7528\u8005\u540d\u7a31 webui.password=\u5bc6\u78bc webui.port=\u9023\u63a5\u57e0 (*) webui.protocol=\u901a\u8a0a\u5354\u5b9a (*) webui.homepage=\u9996\u9801 (*) webui.rootdir=\u6839\u76ee\u9304 (*) webui.rootres=\u539f\u59cb\u4f86\u6e90 (*) webui.mode=\u6a21\u5f0f (*) webui.mode.info=\u6a21\u5f0f\u53ef\u4ee5\u88ab\u8a2d\u70ba\n\t"full"\t= \u6240\u6709\u64cd\u4f5c\u7686\u53ef\u4f7f\u7528 (\u9810\u8a2d)\n\t"view"\t= \u50c5\u80fd\u6aa2\u8996 (\u4f46\u662f\u53ef\u4ee5\u66f4\u65b0\u91cd\u7f6e\u983b\u7387) webui.access=\u5b58\u53d6 (*) webui.access.info=\u5b58\u53d6\u8a2d\u5b9a\u53ef\u4ee5\u8a2d\u70ba\n\t"local"\t= \u53ea\u6709\u672c\u5730\u7aef\u7684\u6a5f\u5668\u53ef\u4ee5\u9023\u7dda\n\t"all"\t= \u7121\u9023\u7dda\u9650\u5236 (\u9810\u8a2d)\n\tIP\t= e.g. 192.168.0.2\t\t\t\u55ae\u4e00 IP\n\tIP1-IP2\t= e.g. 192.168.0.1-192.168.0.255\t\u5927\u7bc4\u570d\u7684 IP \u4f4d\u7f6e GeneralView.label.maxdownloadspeed=\u6700\u5927\u4e0b\u8f09\u901f\u5ea6 Security.keystore.corrupt=Keystore '%1' \u8f09\u5165\u5931\u6557, \u8acb\u522a\u9664\u5b83\u4e26\u91cd\u65b0\u5efa\u7acb\u6216\u662f\u532f\u5165\u6191\u8b49. Security.keystore.empty=Keystore \u7a7a\u767d. \u8acb\u5efa\u7acb\u4e00\u500b\u81ea\u6211\u7c3d\u7f72\u7684\u6191\u8b49 (\u67e5\u95b1 \u5de5\u5177->\u9078\u9805->\u5b89\u5168\u6027) \u6216\u662f\u532f\u5165\u4e00\u500b\u5df2\u5b58\u5728\u7684\u6191\u8b49\u81f3 '%1' webui.restart.info=\u7576\u6a19\u8a18 (*) \u7684\u9805\u76ee\u88ab\u8b8a\u66f4,\u7cfb\u7d71\u5fc5\u9808\u91cd\u65b0\u555f\u52d5\u624d\u80fd\u8b93\u8b8a\u66f4\u751f\u6548 GeneralView.label.maxdownloadspeed.tooltip=\u6700\u5927\u4e0b\u8f09\u901f\u5ea6 [0\uff1a\u7121\u9650\u5236] ConfigView.section.UPnP=\u901a\u7528\u96a8\u63d2\u96a8\u7528 upnp.enable=\u555f\u7528 UPnP upnp.info=\u901a\u7528\u96a8\u63d2\u96a8\u7528(UPnP)\u53ef\u8b93\u5177\u5099 UPnP \u529f\u80fd\u7684\u7db2\u8def\u5206\u4eab\u5668\u81ea\u52d5\u5b9a\u4f4d\u50b3\u8f38\u57e0\u4f4d\u7f6e upnp.mapping.dataport=\u4f86\u6e90\u5925\u4f34\u7684\u8cc7\u6599\u9023\u63a5\u57e0 upnp.mapping.tcptrackerport=TCP Tracker \u9023\u63a5\u57e0 upnp.mapping.udptrackerport=UDP Tracker \u9023\u63a5\u57e0 upnp.alert.differenthost=UPnP: '%1' \u7684\u5b9a\u4f4d\u5df2\u7d93\u88ab '%2' \u4f54\u7528- \u8acb\u9078\u64c7\u5176\u4ed6\u7684\u50b3\u8f38\u57e0 upnp.alert.mappingok=UPnP: \u5efa\u7acb '%1' \u7684\u5b9a\u4f4d upnp.alert.mappingfailed=UPnP: '%1' \u5b9a\u4f4d\u5931\u6557 upnp.alertsuccess=\u56de\u5831\u6210\u529f\u7684\u5b9a\u4f4d upnp.alert.lostdevice=UPnP: \u907a\u5931 '%1' \u7684\u9023\u7dda,\u5728 UPnP \u88dd\u7f6e '%2' upnp.grabports=\u5373\u4f7f\u50b3\u8f38\u57e0\u88ab\u5225\u7684\u96fb\u8166\u4f54\u7528,\u4ecd\u820a\u4f7f\u7528\u5b9a\u4f4d upnp.refresh.label=\u66f4\u65b0\u5b9a\u4f4d upnp.refresh.button=\u66f4\u65b0 upnp.alert.mappinggrabbed=UPnP: \u5efa\u7acb '%1' \u7684\u5b9a\u4f4d - \u5f9e '%2' \u64f7\u53d6 upnp.mapping.tcpssltrackerport=TCP SSL Tracker \u9023\u63a5\u57e0 upnp.alertothermappings=\u56de\u5831\u88ab\u5176\u4ed6\u96fb\u8166\u4f54\u7528\u7684\u9023\u63a5\u57e0 upnp.alertdeviceproblems=\u56de\u5831 UPnP \u88dd\u7f6e\u7684\u554f\u984c blank.resource=\u8cc7\u6e90 ConfigView.pluginlist.coreplugins=\u4e0b\u500b\u5167\u5efa\u5916\u639b\u6a21\u7d44\u5df2\u8f09\u5165 Peers.column.DLedFromOthers=\u5f9e\u5176\u4ed6 Peers.column.DLedFromOthers.info=\u9023\u7dda\u6642\uff0c\u60a8\u5f9e\u5225\u4eba\u90a3\u908a\u4e0b\u8f09\u7684\u8cc7\u6599 Peers.column.UpDownRatio=\u4e0a\u50b3:\u4e0b\u8f09 Peers.column.UpDownRatio.info=\u5925\u4f34\u7684"\u5df2\u4e0a\u50b3 :\u5df2\u4e0b\u8f09" \u6bd4\u7387 Peers.column.UpRatio=\u4e0a\u50b3\u7387 Peers.column.UpRatio.info=\u60a8\u4e0a\u50b3\u7d66\u5925\u4f34 : \u5225\u4eba\u4e0a\u50b3\u7d66\u5925\u4f34\u7684\u6bd4\u7387 upnp.releasemappings=\u95dc\u9589\u6642\u91cb\u653e\u5b9a\u4f4d\u8cc7\u6599 webui.upnpenable=\u555f\u52d5\u9019\u500b\u9023\u63a5\u57e0\u7684 UPnP (*) ConfigView.section.file.friendly.hashchecking=\u53cb\u5584\u7684 hash \u6aa2\u67e5 ConfigView.section.file.friendly.hashchecking.tooltip=\u901f\u5ea6\u8f03\u6162\uff0c\u4f46\u662f\u5c0d CPU / \u7cfb\u7d71\u7684\u8ca0\u64d4\u8f03\u5c0f\uff0c\u6a94\u6848\u5206\u584a hashchecking \u6a21\u5f0f ConfigView.section.tracker.seedretention=\u6bcf\u500b torrent \u4fdd\u5b58\u7684\u6700\u5927\u7a2e\u5b50\u6578 [0\uff1a\u7121\u9650\u5236] ConfigView.section.tracker.seedretention.info=\u6ce8\u610f: \u6c92\u6709\u4fdd\u7559\u7684\u7a2e\u5b50\uff0c\u5176\u4e0a\u50b3\u7d71\u8a08\u8cc7\u6599\u6703\u907a\u5931 ConfigView.section.tracker.port=\u5728 HTTP \u9023\u63a5\u57e0\u4e0a\u555f\u7528 tracker ConfigView.section.tracker.sslport=\u5728 HTTPS \u9023\u63a5\u57e0\u4e0a\u555f\u7528 tracker ConfigView.section.tracker.publicenable.info=\u6b64\u8a2d\u5b9a\u5141\u8a31\u4ed6\u4eba\u5229\u7528\u60a8\u7684 tracker \u5efa\u7acb torrents\n\u5373\u4f7f\u60a8\u4e26\u975e\u4e3b\u6a5f\u6216\u662f\u767c\u4f48\u8005 Button.clear=\u6e05\u9664 MainWindow.IPs.tooltip={\u6700\u5f8c\u66f4\u65b0\u7684\u904e\u6ffe\u5217\u8868} Total IPFilters in list - Number of blocked/banned/bad IPs this session.\n\u96d9\u64ca\u5de6\u9375\u4ee5\u7372\u5f97\u66f4\u591a\u8cc7\u8a0a ConfigView.section.ipfilter.list.banned=\u5df2\u88ab\u5c01\u9396 ConfigView.section.ipfilter.list.baddata=\u5df2\u50b3\u9001\u7684\u640d\u58de\u8cc7\u6599\uff1a\u767c\u751f\u6b21\u6578 = Button.reset=\u91cd\u7f6e ConfigView.section.ipfilter.bannedinfo=\u9001\u51fa\u640d\u58de\u8cc7\u6599\u7684 IPs - \u5982\u679c\u8d85\u51fa\u9650\u5236\u5247\u5c01\u9396\u5b83\u5011 ConfigView.section.ipfilter.blockedinfo=\u5df2\u88ab IP \u904e\u6ffe\u5668\u5c01\u9396\u7684 IPs download.removerules.name=\u79fb\u9664\u898f\u5247 download.removerules.unauthorised.info=\u672a\u88ab\u6388\u6b0a\u7684torrent\u662f\u6307announce\u5728"failure response"\u4e2d\uff0c\u56de\u5fa9"not authoris(z)ed"\u6216"unauthoris(z)ed"\u7684torrent download.removerules.unauthorised=\u81ea\u52d5\u79fb\u9664\u672a\u6388\u6b0a\u7684 torrents download.removerules.unauthorised.seedingonly=\t\u50c5\u5728\u505a\u7a2e\u4e2d download.removerules.removed.ok=\u6210\u529f\u5730\u81ea\u52d5\u79fb\u9664 torrent '%1' \u3002\u9019\u9805\u5de5\u4f5c\u7531 torrent \u79fb\u9664\u898f\u5247\u57f7\u884c\u3002 download.removerules.updatetorrents=\u6536\u5230 Swarm \u8981\u6c42\u6642\uff0c\u79fb\u9664 Vuze \u66f4\u65b0 torrents ConfigView.label.defaultstarttorrentsstopped=\u65b0\u7684 torrents \u52a0\u5165\u6642\u9810\u8a2d\u70ba\u505c\u6b62\u72c0\u614b ConfigView.section.server.enableudp=\u555f\u7528 UDP tracker \u7528\u6236\u7aef\u5354\u5b9a upnp.mapping.dataportudp=UDP tracker \u7528\u6236\u7aef\u9023\u63a5\u57e0 ConfigView.section.file.decoder.showlax=\u986f\u793a\u4e0d\u592a\u53ef\u80fd\u7684\u7de8\u78bc\u65b9\u5f0f ConfigView.section.file.decoder.showall=\u8003\u616e\u6240\u6709\u53ef\u80fd\u7684\u7de8\u78bc\u65b9\u5f0f MainWindow.status.updowndetails.tooltip=\u4e0b\u8f09/\u4e0a\u50b3\u8a73\u7d30\u8cc7\u8a0a \n\u6309\u53f3\u9375\u66f4\u6539\uff0c\u96d9\u64ca\u53ef\u958b\u555f\u7d71\u8a08\u6578\u5b57 TrackerClient.announce.warningmessage=Tracker '%1' \u56de\u5831\u8b66\u544a '%2' ConfigView.section.tracker.natcheckenable=\u6aa2\u67e5 '\u50b3\u5165\u8cc7\u6599\u9023\u63a5\u57e0' \u9023\u7dda\u80fd\u529b\uff0c\u4e26\u5411\u5925\u4f34\u56de\u5831\u932f\u8aa4 ConfigView.section.tracker.publishenabledetails=\u767c\u4f48\u6240\u6709 torrent \u8a73\u7d30\u8cc7\u8a0a ConfigView.section.tracker.publishenablepeerdetails=\u767c\u4f48\u5925\u4f34\u8a73\u7d30\u8cc7\u6599 MyTrackerView.badnat=NAT \u932f\u8aa4 MyTrackerView.badnat.info=\u7a2e\u5b50/\u5925\u4f34 \u7684 NAT \u6aa2\u67e5\u932f\u8aa4 ConfigView.section.tracker.natchecktimeout=\u6aa2\u67e5\u903e\u6642\uff08\u79d2\uff09 ConfigView.section.file.perf.cache.enable=\u555f\u7528\u78c1\u789f\u5feb\u53d6 ConfigView.section.file.perf.cache.size=\u5feb\u53d6\u5927\u5c0f\u70ba%1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u50b3\u9001 (&R) MainWindow.menu.transfers.startalltransfers=\u5168\u90e8\u555f\u52d5 (&A) MainWindow.menu.transfers.stopalltransfers=\u5168\u90e8\u505c\u6b62 (&O) MainWindow.menu.transfers.pausetransfers=\u66ab\u505c (&P) MainWindow.menu.transfers.resumetransfers=\u7e8c\u50b3 (&R) ConfigView.label.experimental.osx.kernel.panic.fix=\u5617\u8a66\u4fee\u5fa9\u5728\u96d9CPU\u7cfb\u7d71\u4e0a\u7684OSX\u6838\u5fc3\u932f\u8aa4 [\u9700\u8981\u91cd\u65b0\u555f\u52d5] SystemTray.menu.pausetransfers=\u66ab\u505c\u50b3\u8f38\u5de5\u4f5c SystemTray.menu.resumetransfers=\u7e8c\u50b3 ConfigView.section.file.truncate.too.large=\u622a\u65b7\u5df2\u5b58\u5728\u7684\u904e\u5927\u6a94\u6848 ConfigView.section.file.perf.cache.trace=\u8ffd\u8e64\u5feb\u53d6\u7684\u64cd\u4f5c\uff0c\u4ee5\u7528\u4f86\u8a3a\u65b7\u7cfb\u7d71 ConfigView.section.interface.enabletray=\u555f\u7528\u7cfb\u7d71\u5217 [\u9700\u8981\u91cd\u65b0\u555f\u52d5] PeerManager.status.error=\u932f\u8aa4 Stats.title.full=\u7d71\u8a08 TransferStatsView.title.full=\u50b3\u8f38\u91cf CacheView.title.full=\u5feb\u53d6 CacheView.general.size=\u7e3d\u5927\u5c0f CacheView.general.inUse=\u4f7f\u7528\u4e2d CacheView.general.title=\u5feb\u53d6\u72c0\u614b CacheView.reads.title=I/O \u8b80\u53d6 CacheView.reads.fromFile=\u5f9e\u6a94\u6848 CacheView.reads.fromCache=\u5f9e\u5feb\u53d6 CacheView.reads.hits=\u547d\u4e2d\u7387 CacheView.writes.title=I/O \u5beb\u5165 CacheView.writes.toCache=\u5230\u5feb\u53d6 CacheView.writes.toFile=\u5230\u6a94\u6848 CacheView.writes.hits=\u5df2\u5132\u5b58 CacheView.speeds.title=\u8cc7\u6599\u6bd4\u7387 CacheView.speeds.reads=\u8b80\u53d6 CacheView.speeds.writes=\u5beb\u5165 CacheView.speeds.fromCache=\u5f9e/\u5230 \u5feb\u53d6 CacheView.speeds.fromFile=\u5f9e/\u5230 \u6a94\u6848 CacheView.reads.#=No. CacheView.reads.amount=\u7e3d\u8a08 CacheView.reads.avgsize=\u5e73\u5747\u5927\u5c0f openUrl.referrer=\u53c3\u7167\u7db2\u9801 URL : openUrl.referrer.info=\u53ea\u6709\u8ca0\u8cac\u7ba1\u7406\u7684\u7db2\u7ad9\u6709\u6b64\u5fc5\u8981 ConfigView.label.maxuploadspeedseeding=\u53ea\u505a\u7a2e\u6642\u7684\u4e0a\u50b3\u901f\u5ea6 (KB/s) [0\uff1a\u7121\u9650\u5236] ConfigView.label.transfer.ignorepeerports=\u5ffd\u7565\u4f7f\u7528\u9019\u4e9b\u8cc7\u6599\u9023\u63a5\u57e0\u7684\u5925\u4f34(\u4f7f\u7528';'\u5206\u9694, e.g. 0;25) ConfigView.section.proxy.enable_socks.peer=\u555f\u7528\u5925\u4f34\u9593\u901a\u8a0a\u7684\u4ee3\u7406\u4f3a\u670d\u5668\uff08\u50c5\u9650\u65bc\u5916\u9001\u7684\u9023\u7dda\uff09[\u9700\u8981\u91cd\u65b0\u555f\u52d5] ConfigView.section.proxy.peer.informtracker=\u544a\u77e5 tracker \u9650\u5236 ConfigView.section.proxy.socks.version=SOCKS \u7248\u672c PiecesView.legend.written=\u5df2\u5beb\u5165 PiecesView.legend.requested=\u8981\u6c42\u4e2d PiecesView.legend.downloaded=\u5df2\u4e0b\u8f09,\u5beb\u5165\u5ef6\u9072 PiecesView.legend.incache=\u8cc7\u6599\u5728\u5feb\u53d6\u4e2d PiecesView.typeItem.0=\u7de9\u6162 PiecesView.typeItem.1=\u5feb\u901f PiecesView.type=\u7a2e\u985e Security.jar.tools_not_found=JAR \u7c3d\u7f72\u5931\u6557 - 'tools.jar' \u4e0d\u5b58\u5728 %1. \u53c3\u95b1 \u5de5\u5177->\u9078\u9805->\u5b89\u5168\u6027 \u4ee5\u4e86\u89e3\u8a73\u7d30\u8cc7\u8a0a. Security.jar.signfail=JAR \u7c3d\u7f72\u5931\u6557 - %1 ConfigView.section.security.toolsdir='tools.jar' \u6240\u5728\u76ee\u9304 ConfigView.section.security.choosetoolssavedir=\u9078\u64c7\u542b\u6709 "tools.jar" \u7684\u8cc7\u6599\u593e authenticator.torrent=Torrent \u6a94 ConfigView.section.proxy.peer.same=tracker \u548c\u5925\u4f34\u9593\u901a\u8a0a\u7684\u4ee3\u7406\u4f3a\u670d\u5668\uff0c\u4f7f\u7528\u76f8\u540c\u7684\u8a2d\u5b9a ConfigView.section.connection.network.max.simultaneous.connect.attempts=\u6700\u5927\u7684\u540c\u6642\u5c0d\u5916\u9023\u7dda\u6578 ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=\u53ef\u5efa\u7acb\u7684\u65b0\u5c0d\u5916\u9023\u7dda\u6700\u5927\u503c\u3002Vuze \u5728\u7279\u5b9a\u6642\u9593\u5167\u6703\u8a66\u5716\u9023\u7dda\n\u6ce8\u610f: WindowsXP Service Pack 2 (SP2) \u5f37\u5236\u9650\u5b9a\u7cfb\u7d71\u5728\u540c\u6642\u9593\u5167\uff0c\u6700\u591a\u53ea\u80fd\u6709 10 \u500b\u9023\u7dda\n\u9810\u8a2d\u503c\u662f 8 ConfigView.section.file.perf.cache.size.explain=\u5feb\u53d6\u53ef\u7528\u4f86\u6e1b\u5c11\u78c1\u789f\u7684\u8b80\u53d6/\u5beb\u5165\u6b21\u6578\u3002 \u9664\u975e\u60a8\u4f7f\u7528 java \u9078\u9805 '-XX:MaxDirectMemorySize' \u4f86\u660e\u78ba\u8a2d\u5b9a\u53ef\u7528\u7684\u8a18\u61b6\u9ad4\u5feb\u53d6\u7a7a\u9593\u548c\u7db2\u8def\u7684 IO, \u61c9\u8a72\u4fdd\u6301\u6700\u5c11 %1 \u4e14\u4f4e\u65bc\u60a8\u7684\u6700\u5927\u865b\u64ec\u8a18\u61b6\u9ad4\u7a7a\u9593\u3002\u76ee\u524d\u7684\u865b\u64ec\u8a18\u61b6\u9ad4\u5927\u5c0f\u662f %2\u3002\u60f3\u4e86\u89e3\u5982\u4f55\u66f4\u6539\u8a2d\u5b9a\uff0c\u8acb\u53c3\u7167 Wiki \u4e2d %3 \u95dc\u65bc MemoryUsage \u7684\u90e8\u4efd\u3002\u932f\u8aa4\u7684\u8a2d\u5b9a\u6703\u5c0e\u81f4"\u8a18\u61b6\u9ad4\u4e0d\u8db3"\u932f\u8aa4\u3002\u5feb\u53d6\u5927\u5c0f\u4e0d\u8981\u8d85\u904e 32MB\uff0c\u4e0d\u7136\u5c31\u904e\u591a\u5566 MyTorrentsView.menu.setSpeed.unlimit=\u6c92\u6709\u9650\u5236 MyTorrentsView.menu.setSpeed.unlimited=\u7121\u9650\u5236 MyTorrentsView.menu.setSpeed.disable=\u7981\u6b62\u4e0a\u50b3 MyTorrentsView.menu.setSpeed.disabled=\u5df2\u7981\u6b62 MyTorrentsView.menu.setSpeed.in=\u9032 MyTorrentsView.menu.setSpeed.slots=\u500b\u6578 GeneralView.label.maxuploadspeed=\u6700\u5927\u4e0a\u50b3 GeneralView.label.maxuploadspeed.tooltip=\u6700\u5927\u4e0a\u50b3\u901f\u5ea6 [0\uff1a\u7121\u9650\u5236] MyTorrents.items.UpSpeedLimit.disabled=\u7981\u6b62\u4e0a\u50b3 MyTorrents.items.UpSpeedLimit.unlimited=\u7121\u9650\u5236 TableColumn.header.maxupspeed=\u6700\u5927\u4e0a\u50b3\u901f\u5ea6 TableColumn.header.maxupspeed.info=\u6bcf\u500b torrent \u7684\u6700\u5927\u4e0a\u50b3\u901f\u5ea6 ConfigView.section.file.perf.cache.enable.write=\u5c07\u4e0b\u8f09\u7684\u8cc7\u6599\u5b58\u5165\u5feb\u53d6\uff0c\u4ee5\u964d\u4f4e\u78c1\u789f\u5beb\u5165\u6b21\u6578\uff0c\u4e26\u6e1b\u5c11\u6a94\u6848\u5206\u584a\u6aa2\u67e5\u6642\u7684\u78c1\u789f\u8b80\u53d6\u6b21\u6578 ConfigView.section.file.perf.cache.enable.read=\u57f7\u884c"\u5148\u671f\u8b80\u53d6"\u4ee5\u964d\u4f4e\u4e0a\u50b3\u6642\u78c1\u789f\u7684\u8b80\u53d6\u6b21\u6578 ConfigView.section.tracker.separatepeerids=\u5c0d tracker \u548c\u8cc7\u6599\u901a\u8a0a\u4f7f\u7528\u4e0d\u540c\u7684\u5925\u4f34\u8eab\u5206 ConfigView.section.tracker.separatepeerids.info=\u4f7f\u7528\u975e\u533f\u540d\u7684 tracker \u9023\u7dda\u6642\n\u589e\u52a0\u533f\u540d\u4e0b\u8f09/\u505a\u7a2e\u6642\u7684\u96b1\u5bc6\u6027 ConfigView.section.interface.wavlocation=wav \u6a94\u5b58\u653e\u4f4d\u7f6e ConfigView.section.interface.wavlocation.info=\u9078\u64c7 .wav \u6a94\u6216\u662f\u7559\u7a7a\u4ee5\u4f7f\u7528\u9810\u8a2d\u97f3\u6548 ConfigView.section.tracker.server=\u4f3a\u670d\u5668 ConfigView.section.tracker.client=\u7528\u6236\u7aef ConfigView.section.tracker.client.connecttimeout=\u9023\u7dda\u903e\u6642\uff08\u79d2\uff09 ConfigView.section.tracker.client.readtimeout=\u8b80\u53d6\u903e\u6642\uff08\u79d2\uff09 MainWindow.menu.tools=\u5de5\u5177 (&T) FilesView.path=\u8def\u5f91 FilesView.fullpath=\u986f\u793a\u5b8c\u6574\u8def\u5f91 FilesView.remaining=\u672a\u5b8c\u6210\u7684\u6a94\u6848\u5206\u584a TableColumn.header.trackername=Tracker \u540d\u7a31 TableColumn.header.trackername.info=URL \u767c\u4f48\u7684 tracker \u540d\u7a31 ConfigView.group.override=\u512a\u5148\u8a2d\u5b9a ConfigView.section.file.perf.cache.notsmallerthan=\u4e0d\u8981\u5feb\u53d6\u5c0f\u65bc(%1)\u7684\u6a94\u6848 PeersView.menu.blockupload=\u963b\u6b62\u4e0a\u50b3 PeersView.menu.kickandban=\u62d2\u7d55\u4e26\u5c01\u9396 PeersView.menu.kickandban.reason=\u624b\u52d5\u5c01\u9396\u5925\u4f34\u7684\u72c0\u614b PeersView.state=\u9023\u7dda\u72c0\u614b PeersView.state.info=\u5925\u4f34\u7684\u9023\u7dda\u72c0\u6cc1 PeersView.state.pending=\u5ef6\u9072\u4e2d PeersView.state.connecting=\u9023\u7dda\u4e2d PeersView.state.handshake=\u7b49\u5f85\u56de\u61c9 PeersView.state.established=\u5df2\u5efa\u7acb\u9023\u7dda ConfigView.section.tracker.processinglimits=\u8655\u7406\u9650\u5236 ConfigView.section.tracker.maxgettime=\u53d6\u5f97\u57f7\u884c\u7684\u6700\u5927\u6642\u9593\uff08\u79d2\uff09 [0\uff1a\u7121\u9650\u5236] ConfigView.section.tracker.maxgettime.info=\u7528\u4f86\u767c\u4f48\u548c scrapes ConfigView.section.tracker.maxposttimemultiplier=\u5f8c\u90e8\u57f7\u884c\u6642\u53d6\u5f97\u6642\u9593\u4e58\u6578 [0\uff1a\u7121\u9650\u5236] ConfigView.section.tracker.maxposttimemultiplier.info=\u7528\u65bc\u683c\u5f0f\u7684\u63d0\u4ea4\u548c\u4e0a\u50b3 ConfigView.section.tracker.maxthreads=\u540c\u6642\u9032\u884c\u7684\u6700\u5927\u8981\u6c42\u6578 DownloadManager.error.operationcancancelled=\u64cd\u4f5c\u5df2\u53d6\u6d88 Torrent.create.progress.cancelled=\u64cd\u4f5c\u53d6\u6d88 sharing.progress.cancel=\u53d6\u6d88 wizard.maketorrents.autoopen=\u5b8c\u6210\u5f8c\u958b\u555f Torrent\u4ee5\u505a\u7a2e ConfigView.section.sharing.rescanenable=\u555f\u7528\u5b9a\u671f\u91cd\u65b0\u6383\u63cf\uff0c\u76e3\u63a7\u5171\u4eab\u8cc7\u6599\u7684\u8b8a\u52d5 ConfigView.section.sharing.rescanperiod=\u91cd\u65b0\u6383\u63cf\u9031\u671f\uff08\u79d2\uff09 ConfigView.section.connection.advanced=\u9032\u968e\u7db2\u8def\u8a2d\u5b9a ConfigView.section.connection.advanced.mtu=\u7dda\u8def\u6700\u5927\u50b3\u8f38\u55ae\u5143\uff08MTU\uff09 ConfigView.section.connection.advanced.mtu.tooltip=\u5728\u8a72\u7db2\u8def\u6846\u67b6\u4e0b\u6240\u80fd\u50b3\u8f38\u7684\u6700\u5927\u5c01\u5305\nVuze \u4f7f\u7528 MTU-40\uff08MSS\uff09 \u8b93\u4e0a\u50b3\u5c01\u5305\u8ca0\u8f09\u6700\u4f73\u5316\n\u5efa\u8b70\u6578\u503c\uff1a\n 576 - \u64ad\u63a5\u9023\u7dda\n1492 - PPPoE \u5bec\u983b\u9023\u7dda\n1500 - \u4e59\u592a\u7db2\u8def\uff0cDSL \u548c Cable \u7b49\u5bec\u983b\u9023\u7dda ConfigView.section.connection.advanced.SO_RCVBUF=Socket SO_RCVBUF size[0\uff1a\u9810\u8a2d] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=\u8a2d\u5b9a\u6a19\u6e96 socket SO_RCVBUF \u6578\u503c\uff08bytes\uff09\uff0ci.e. TCP \u63a5\u6536\u7a97\u53e3\u7684\u5927\u5c0f\u548c\u6bd4\u4f8b\nVuze \u9810\u8a2d\u70ba\u7a7a\u767d\uff0c\u4e5f\u5c31\u662f\u6839\u64da\u6240\u4f7f\u7528\u7684\u5e95\u5c64\u4f5c\u696d\u7cfb\u7d71\u800c\u5b9a\n\u6ce8\u610f\uff1aLinux \u6703\u4f7f\u7528\u5169\u500d\u7684\u6307\u5b9a\u6578\u503c ConfigView.section.connection.advanced.SO_SNDBUF=Socket SO_SNDBUF size[0\uff1a\u9810\u8a2d] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=\u8a2d\u5b9a\u6a19\u6e96 socket SO_SNDBUF \u6578\u503c\uff08bytes\uff09\uff0ci.e. TCP \u50b3\u9001\u7a97\u53e3\u7684\u5927\u5c0f\nVuze \u9810\u8a2d\u70ba\u7a7a\u767d\uff0c\u4e5f\u5c31\u662f\u6839\u64da\u6240\u4f7f\u7528\u7684\u5e95\u5c64\u4f5c\u696d\u7cfb\u7d71\u800c\u5b9a\n\u6ce8\u610f\uff1aLinux \u6703\u4f7f\u7528\u5169\u500d\u7684\u6307\u5b9a\u6578\u503c ConfigView.section.interface.confirm_torrent_removal=torrent \u88ab\u79fb\u9664\u6642\uff0c\u986f\u793a\u78ba\u8a8d\u5c0d\u8a71\u8996\u7a97 ConfigView.section.interface.confirm_torrent_removal.tooltip=\u5f9e"\u6211\u7684 torrent" \u4e2d\u79fb\u9664 torrent \u6642,\u8981\u6c42\u78ba\u8a8d MyTorrentsView.confirm_torrent_removal=\u60a8\u78ba\u5b9a\u8981\u522a\u9664\uff1f\n TableColumn.header.seed_to_peer_ratio=\u7a2e\u5b50\u5c0d\u5925\u4f34\u7684\u6bd4\u7387 TableColumn.header.seed_to_peer_ratio.info=\u5168\u90e8 swarm \u88e1\u7a2e\u5b50\u5c0d\u5925\u4f34\u7684\u6bd4\u7387 PeersView.connected_time=\u9023\u7dda\u6642\u9593 PeersView.connected_time.info=\u60a8\u548c\u5925\u4f34\u9023\u7dda\u7684\u7e3d\u6642\u9593 ConfigView.section.interface.display.add_torrents_silently=\u9ed8\u9ed8\u5730\u52a0\u5165 torrents ConfigView.section.interface.display.add_torrents_silently.tooltip=\u52a0\u5165 torrent \u4e0b\u8f09\u6642\uff0c\u4e0d\u8981\u555f\u52d5 Vuze \u4e3b\u8996\u7a97 TableColumn.header.maxdownspeed=\u6700\u5927\u4e0b\u8f09\u901f\u5ea6 TableColumn.header.maxdownspeed.info=\u6bcf\u500b torrent \u6700\u5927\u4e0b\u8f09\u901f\u5ea6 PeersGraphicView.title=Swarm \u7fa4\u7d44 ConfigView.section.tracker.passwordwebhttpsonly=\u50c5\u5141\u8a31\u900f\u904e HTTPS \u5b58\u53d6 TableColumn.header.torrentpath=Torrent \u4f4d\u7f6e TableColumn.header.torrentpath.info=Torrent \u5728\u78c1\u789f\u4e2d\u7684\u4f4d\u7f6e ConfigView.section.sharing.torrentcomment=\u7522\u751f\u7684 torrents \u8a3b\u89e3 ConfigView.label.copyanddeleteratherthanmove=\u5148\u62f7\u8c9d\u7136\u5f8c\u624d\u522a\u9664\u539f\u59cb\u6a94\uff0c\u800c\u4e0d\u662f\u4f7f\u7528\u642c\u79fb\u7684\u64cd\u4f5c\u65b9\u5f0f-\u53ef\u4ee5\u907f\u514d\u67d0\u4e9b\u6a94\u6848\u7cfb\u7d71\u53ef\u80fd\u5c0e\u81f4\u7684\u8cc7\u6599\u907a\u5931\u3002 ConfigView.label.openstatsonstart=\u555f\u52d5\u6642\u958b\u555f"\u7d71\u8a08" swt.install.window.title=Vuze \u5916\u639b\u6a21\u7d44\u5b89\u88dd\u7a0b\u5f0f swt.install.window.ok=\u5b89\u88dd swt.install.window.header=\u5b89\u88dd\u4e0b\u5217\u88ab\u9078\u64c7\u7684\u5143\u4ef6 : swt.uninstall.window.title=Vuze \u5916\u639b\u6a21\u7d44\u79fb\u9664\u7a0b\u5f0f swt.uninstall.window.ok=\u79fb\u9664 swt.uninstall.window.header=\u8acb\u5728\u4e0b\u5217\u9078\u64c7\u8981\u79fb\u9664\u7684\u5143\u4ef6 : installPluginsWizard.title=\u5b89\u88dd\u5916\u639b\u6a21\u7d44 installPluginsWizard.mode.title=\u8acb\u9078\u64c7\u4e00\u7a2e\u5b89\u88dd\u65b9\u5f0f installPluginsWizard.mode.list=\u4f9d\u7167 sourceforge.net \u7684\u5217\u8868 installPluginsWizard.list.title=\u53ef\u5b89\u88dd\u7684\u5916\u639b\u6a21\u7d44\u5217\u8868 installPluginsWizard.list.loading=\u5916\u639b\u6a21\u7d44\u5217\u8868\u8f09\u5165\u4e2d\uff0c\u8acb\u7a0d\u5f8c installPluginsWizard.list.loaded=\u8acb\u9078\u64c7\u8981\u5b89\u88dd\u7684\u5916\u639b\u6a21\u7d44 installPluginsWizard.list.name=\u540d\u7a31 installPluginsWizard.list.version=\u7248\u672c installPluginsWizard.list.description=\u5916\u639b\u6a21\u7d44\u8aaa\u660e installPluginsWizard.finish.title=\u5b89\u88dd\u6b63\u5728\u9032\u884c\u4e2d installPluginsWizard.finish.explanation=\u9078\u64c7\u7684\u5916\u639b\u6a21\u7d44\u5c07\u6703\u900f\u904e\u66f4\u65b0\u5c0f\u5e6b\u624b\u5b89\u88dd.\n\n \u8acb\u8010\u5fc3\u7b49\u5f85\uff0c\u5b89\u88dd\u904e\u7a0b\u9700\u8981\u4e00\u9ede\u6642\u9593.\n\n\u5982\u9700\u8981\u9032\u5ea6\u5831\u544a\uff0c\u8acb\u96d9\u64ca\u5de6\u908a\u7684\u72c0\u614b\u6b04\u4f4d installPluginsWizard.details.loading=\u8f09\u5165\u8a73\u7d30\u8cc7\u8a0a\u4e2d\uff0c\u8acb\u7a0d\u5f8c installPluginsWizard.mode.file=\u4f9d\u7167\u6a94\u6848 installPluginsWizard.installMode.title=\u8acb\u9078\u64c7\u5b89\u88dd\u7a2e\u985e installPluginsWizard.installMode.user=\u53ea\u70ba\u60a8\u81ea\u5df1\u5b89\u88dd\u5916\u639b\u6a21\u7d44 installPluginsWizard.installMode.shared=\u70ba\u6240\u6709\u7684\u4f7f\u7528\u8005\u5b89\u88dd\u5916\u639b\u6a21\u7d44 installPluginsWizard.file.title=\u8acb\u700f\u89bd\u8981\u5b89\u88dd\u7684\u5916\u639b\u6a21\u7d44 installPluginsWizard.file.file=\u6a94\u6848 : installPluginsWizard.file.invalidfile=\u9019\u500b\u6a94\u6848\u4e0d\u662f\u6709\u6548\u7684 Vuze \u5916\u639b\u6a21\u7d44 installPluginsWizard.file.browse=\u700f\u89bd uninstallPluginsWizard.title=\u79fb\u9664\u5916\u639b\u6a21\u7d44 uninstallPluginsWizard.list.title=\u5b89\u88dd\u5916\u639b\u6a21\u7d44\u5217\u8868 uninstallPluginsWizard.list.loaded=\u8acb\u9078\u64c7\u60a8\u60f3\u8981\u79fb\u9664\u7684\u5916\u639b\u6a21\u7d44 installPluginsWizard.list.nullversion=\u7121\u7248\u672c uninstallPluginsWizard.finish.title=\u79fb\u9664\u7a0b\u5f0f\u9032\u884c\u4e2d uninstallPluginsWizard.finish.explanation=\u9078\u5b9a\u7684\u5916\u639b\u6a21\u7d44\u5c07\u6703\u88ab\u66f4\u65b0\u5c0f\u5e6b\u624b\u79fb\u9664 MainWindow.menu.plugins.installPlugins=\u5b89\u88dd\u7cbe\u9748... MainWindow.menu.plugins.uninstallPlugins=\u53cd\u5b89\u88dd\u7cbe\u9748... ConfigView.section.ipfilter.totalIPs=\u5171\u6709 %1 IPs \u88ab\u5c01\u9396\uff0c\u4f54\u7db2\u8def\u7684 %2 update.instance.install=\u6aa2\u67e5\u5b89\u88dd\u6a94\u6848 update.instance.uninstall=\u6aa2\u67e5\u53cd\u5b89\u88dd\u6a94\u6848 update.instance.update=\u6aa2\u67e5\u66f4\u65b0\u6a94\u6848 MainWindow.status.update.tooltip=\u96d9\u64ca\u5de6\u9375\u53ef\u6aa2\u8996\u66f4\u591a\u8cc7\u8a0a updater.progress.window.title=\u6700\u8fd1\u5b89\u88dd\u7684\u5de5\u4f5c updater.progress.window.info=\u8acb\u6309\u4e0b"\u4e2d\u65b7"\u7d50\u675f\u6240\u6709\u7368\u7acb\u7684\u5de5\u4f5c Button.abort=\u4e2d\u6b62 ConfigView.section.ipfilter.enablebanning=\u5c01\u9396\u6301\u7e8c\u50b3\u9001\u640d\u58de\u8cc7\u6599\u7684\u5925\u4f34 Network.alert.acceptfail=%1 ,%2 \u7684\u9023\u7dda\u767c\u751f\u592a\u591a\u6b21\u5931\u6557- \u6d3b\u52d5\u66ab\u505c. \u8acb\u6aa2\u67e5\u9023\u63a5\u57e0\u7684\u9632\u706b\u7246\u8a2d\u5b9a\u4ee5\u4fbf\u555f\u52d5\u9023\u7dda MyShares.column.category=\u5206\u985e UpdateWindow.restartLater=\u7a0d\u5f8c\u518d\u91cd\u65b0\u555f\u52d5 MainWindow.menu.file.restart=\u91cd\u65b0\u555f\u52d5 Vuze MainWindow.dialog.restartconfirmation.title=\u91cd\u65b0\u555f\u52d5 Vuze MainWindow.dialog.restartconfirmation.text=\u60a8\u771f\u7684\u60f3\u8981\u91cd\u65b0\u555f\u52d5 Vuze deletetorrent.message1=\u60a8\u5c07\u8981\u522a\u9664 TORRENT\uff1a\n deletetorrent.message2=\n\u60a8\u78ba\u5b9a\u8981\u7e7c\u7e8c? ConfigView.label.prioritizemostcompletedfiles=\u4f9d\u7167\u6a94\u6848\u7684\u5927\u5c0f\u548c\u5b8c\u6210\u5ea6\u4f86\u6c7a\u5b9a\u9ad8\u512a\u5148\u9806\u5e8f splash.plugin.init=\u6b63\u5728\u521d\u59cb\u5316\u5916\u639b\u6a21\u7d44: ConfigView.section.style.osx_small_fonts=\u4f7f\u7528\u5c0f\u5b57\u578b [\u9700\u8981\u91cd\u65b0\u555f\u52d5] ConfigView.section.tracker.tcpnonblocking=\u4f7f\u7528\u672a\u88ab\u5c01\u9396\u7684 I/O \u4f86\u8655\u7406 tracker \u7684 TCP \u9023\u7dda\u3002\u6b64\u9078\u9805\u9069\u7528\u65bc\u5728\u5176\u4ed6\u9023\u63a5\u57e0\u4e0a\u57f7\u884c\u7684 tracker web\u3002\u591a\u8a66\u5e7e\u6b21\uff01 ConfigView.section.tracker.nonblocking=\u7121\u5c01\u9396\u9078\u9805 ConfigView.section.tracker.nonblockingconcmax=\u540c\u6642\u9593\u9023\u7dda\u6578\u6700\u5927\u503c [0\uff1a\u7121\u9650\u5236] MyTorrentsView.menu.exportmenu=\u532f\u51fa ConfigView.section.tracker.client.scrapeinfo=\u505c\u7528 scraping \u53ef\u9632\u6b62\u5927\u90e8\u5206 torrent \u6392\u7a0b\u898f\u5247\u88ab\u57f7\u884c\uff0c\u56e0\u70ba\u5b83\u5011\u4ef0\u8cf4\u85c9\u7531 scraping tracker \u6240\u53d6\u5f97\u7684 swarm \u8cc7\u8a0a ConfigView.section.tracker.client.scrapeenable=\u555f\u7528 scraping ConfigView.section.tracker.client.scrapestoppedenable=Scrape \u975e\u57f7\u884c\u4e2d\u7684 torrents Scrape.status.disabled=\u505c\u7528 Scrape MyTorrentsView.menu.explore=\u986f\u793a\u6a94\u6848 MyTorrentsView.menu.explore._mac=\u5728 Finder \u88e1\u986f\u793a MyTorrentsView.menu.explore._windows=\u5728 Explorer \u88e1\u986f\u793a wizard.maketorrents.autohost=\u5c07 Torrent \u767c\u4f48\u81f3\u5167\u5efa\u7684 Tracker ConfigView.label.overrideip=\u5ffd\u7565 tracker \u516c\u4f48\u7684 IP \u4f4d\u7f6e - \u5982\u679c\u6709\u4e00\u500b\u4ee5\u4e0a\u7684\u4e0d\u540c\u7db2\u8def\uff0c\u4f7f\u7528';'\u5206\u9694 ConfigView.label.overrideip.tooltip=Inform the tracker of different IP address(es) than the one outgoing packets come from. \u4e0d\u60f3\u4f7f\u7528\u9019\u500b\u9078\u9805\u8acb\u4fdd\u6301\u7a7a\u767d ConfigView.section.connection.group.networks=\u7db2\u8def ConfigView.section.connection.group.networks.info=\u9078\u64c7\u5141\u8a31\u7684\u9810\u8a2d\u7db2\u8def\u4f86\u9032\u884c\u9ede\u5c0d\u9ede\u8cc7\u6599\u50b3\u8f38 ConfigView.section.connection.networks.prompt=\u4e0b\u8f09\u6642\u82e5\u6709\u533f\u540d\u7684 tracker \u52a0\u5165\uff0c\u986f\u793a\u9078\u64c7\u63d0\u793a ConfigView.section.connection.networks.Public=\u516c\u958b\u7684 IP \u7db2\u8def\uff08\u975e\u533f\u540d\uff09 ConfigView.section.connection.networks.I2P=I2P \u7db2\u8def ConfigView.section.connection.networks.Tor=\u6d0b\u8525\u8def\u7531\u5668\uff08Tor\uff09\u7db2\u8def\uff1a\u9023\u7dda\u5c0e\u5411\u7684\u533f\u540d\u5316\u901a\u8a0a\u670d\u52d9 TableColumn.header.networks=\u7db2\u8def TableColumn.header.networks.info=\u7db2\u8def\u5141\u8a31 P2P \u8cc7\u6599\u901a\u8a0a Scrape.status.networkdisabled=\u7db2\u8def\u672a\u555f\u52d5 ConfigView.section.tracker.server.group.networks=\u7db2\u8def ConfigView.section.tracker.server.group.networks.info=\u9078\u64c7 tracker \u53ef\u7528\u4ee5\u63a5\u53d7\u5925\u4f34\u7684\u7db2\u8def window.networkselection.title=\u9078\u64c7\u7db2\u8def window.networkselection.info=\u4e0b\u9762\u5217\u51fa\u7684 torrent \u542b\u6709\u652f\u63f4\u4ee5\u4e0b\u7db2\u8def\u7684 tracker \n\u8acb\u9078\u64c7\u9805\u76ee\u4ee5\u555f\u52d5 Tracker \u548c\u5925\u4f34\u4e4b\u9593\u7684\u901a\u8a0a\n \u5982\u679c\u9019\u662f\u4e00\u500b\u533f\u540d\u7684 tracker,\u4e14\u652f\u63f4\u516c\u958b\u7684\u7528\u6236\u7aef,\u4fbf\u53ef\u4ee5\u540c\u6642\u555f\u52d5\u533f\u540d\u548c\u516c\u958b\u7684\u7db2\u8def\n\u555f\u52d5\u516c\u958b\u7db2\u8def\u6703\u5c0e\u81f4\u533f\u540d\u8005\u88ab\u8e22\u51fa\u53bb plugins.basicview.clear=\u6e05\u9664 ConfigView.section.connection.group.peersources=\u5925\u4f34\u4f86\u6e90 ConfigView.section.connection.group.peersources.info=\u9078\u64c7\u5141\u8a31\u7684\u9810\u8a2d\u4f86\u6e90\u4f86\u9032\u884c\u5c0d\u5925\u4f34\u7684\u9023\u7dda ConfigView.section.connection.peersource.Tracker=\u4f86\u81ea\u67d0\u500b tracker ConfigView.section.connection.peersource.DHT=\u5206\u6563 tracking ConfigView.section.connection.peersource.PeerExchange=\u7531\u5225\u7684\u5925\u4f34\u63d0\u4f9b ConfigView.section.connection.peersource.Plugin=\u589e\u52a0\u5916\u639b\u6a21\u7d44 ConfigView.section.connection.peersource.Incoming=\u50b3\u5165\u9023\u7dda PeersView.source=\u4f86\u6e90 PeersView.source.info=\u5925\u4f34\u7684\u4f86\u6e90 TableColumn.header.peersources=\u5925\u4f34\u4f86\u6e90 TableColumn.header.peersources.info=\u5925\u4f34\u4f86\u6e90\u5141\u8a31\u5efa\u7acb\u7684\u9023\u7dda wizard.tracker.dht=\u5206\u6563\u5f0f (Vuze \u7528\u6236\u5c08\u7528) MyTorrentsView.menu.advancedmenu=\u9032\u968e\u8a2d\u5b9a MyTorrentsView.menu.networks=\u7db2\u8def MyTorrentsView.menu.peersource=\u5925\u4f34\u4f86\u6e90 ConfigView.section.sharing.permitdht=tracker \u7121\u6cd5\u4f7f\u7528\u6642\uff0c\u5141\u8a31\u5206\u6563\u5f0f tracking ConfigView.section.sharing.protocol=\u5171\u4eab\u8cc7\u6e90\u7684\u5354\u5b9a PeersView.Messaging=\u8a0a\u606f PeersView.Messaging.info=\u652f\u63f4\u9032\u968e\u8a0a\u606f API. ConfigView.label.queue.newseedsmovetop=\u5c07\u525b\u5b8c\u6210\u7684 torrent \u6392\u81f3\u505a\u7a2e\u540d\u55ae\u7684\u6700\u524d\u9762 ConfigView.label.seeding.firstPriority.ignore.info=\u8acb\u6ce8\u610f\uff0c\u4f7f\u7528\u9019\u500b\u898f\u5247\u53ef\u80fd\u6703\u5c0e\u81f4\u4e0b\u8f09\u5b8c\u6210\u5f8c torrent \u99ac\u4e0a\u505c\u6b62\u3002 ConfigView.label.seeding.firstPriority.ignore=\u5ffd\u7565\u4ee5\u4e0a\u7684\u512a\u5148\u9806\u5e8f\u898f\u5247: ConfigView.label.seeding.firstPriority.ignoreSPRatio=\u7a2e\u5b50:\u5925\u4f34\u8d85\u904e\u6307\u5b9a\u6bd4\u4f8b\u7684 torrent ConfigView.label.seeding.firstPriority.ignore0Peer=\u5925\u4f34\u6578\u70ba 0 \u7684 torrent ConfigView.section.tracker.sendjavaversionandos=\u50b3\u9001 Java \u7248\u672c\u548c\u4f5c\u696d\u7cfb\u7d71\u540d\u7a31 MagnetPlugin.contextmenu.exporturi=\u5c07 Magnet URI \u62f7\u8c9d\u81f3\u526a\u8cbc\u7c3f ConfigView.section.plugins.dht=\u5206\u6563\u8cc7\u6599\u5eab (DHT) dht.info=\u9019\u500b\u5916\u639b\u6a21\u7d44\u652f\u63f4\u5206\u6563\u7684 tracking,\u53d6\u6d88\u6b64\u529f\u80fd\u6703\u964d\u4f4e\u60a8\u7684\u4e0b\u8f09\u80fd\u529b dht.enabled=\u555f\u52d5\u5206\u6563\u5f0f\u8cc7\u6599\u5eab dht.portdefault=\u4f7f\u7528\u9810\u8a2d\u7684\u9023\u63a5\u57e0 dht.port=\u8cc7\u6599\u5eab\u4f7f\u7528 UDP \u9023\u63a5\u57e0 dht.execute.command=\u8a3a\u65b7\u547d\u4ee4 dht.execute.info=\u6309\u4e0b\u4ee5\u57f7\u884c\u547d\u4ee4 dht.execute=\u57f7\u884c dht.logging=\u555f\u52d5\u6d3b\u52d5\u8ffd\u8e64 ConfigView.section.plugins.dhttracker=\u5206\u6563\u7684 Tracker dhttracker.tracknormalwhenoffline=\u7576 tracker \u7121\u6cd5\u4f7f\u7528\u6642\uff0c\u53ea\u8ffd\u8e64\u6b63\u5e38\u7684 torrents ConfigView.section.file.nativedelete._mac=\u4f7f\u7528"\u5783\u573e\u6876"\u522a\u9664\u6a94\u6848\uff08\u860b\u679c\u96fb\u8166\u5c08\u7528\uff09 ConfigView.section.file.nativedelete._windows=\u5c07\u522a\u9664\u7684\u6a94\u6848\u79fb\u81f3\u8cc7\u6e90\u56de\u6536\u7b52\uff08Windows \u5c08\u7528\uff09 ConfigView.section.logging.generatediagnostics=\u7522\u751f ConfigView.section.logging.generatediagnostics.info=\u5982\u6709\u8a2d\u5b9a\uff0c\u7522\u751f\u8a3a\u65b7\u8cc7\u8a0a\u4e26\u62f7\u8c9d\u81f3\u526a\u8cbc\u7c3f\u8207\u8a18\u9304\u6a94 ConfigView.section.sharing.privatetorrent=\u5c08\u5c6c\u7684 torrent - \u53ea\u63a5\u53d7\u4f86\u81ea tracker \u7684\u5925\u4f34 MainWindow.menu.tools.nattest=NAT / Firewall \u6e2c\u8a66 (&N) Button.apply=\u5957\u7528 Button.close=\u95dc\u9589 window.welcome.title=\u6b61\u8fce\u4f7f\u7528 Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=\u66f4\u65b0\u7d00\u9304 dht.reseed.label=\u4e00\u822c\u4f86\u8aaa,\u5206\u6563\u6027\u8cc7\u6599\u5eab\u6c92\u6709\u91cd\u65b0\u4f5c\u7a2e\u7684\u5fc5\u8981.\u4f46\u662f\u5982\u679c\u9023\u7d61\u4eba\u7684\u6578\u76ee\u904e\u4f4e,\u5247\u53ef\u4ee5\u7528\u4f86\u6574\u5408.\n \u4fdd\u6301\u7a7a\u767d\u4ee5\u8e22\u6389\u5df2\u9023\u7dda\u7684\u5925\u4f34\u6216\u662f\u8f38\u5165 IP \u4f4d\u7f6e\u548c\u9023\u63a5\u57e0\u4f86\u65b7\u7dda\u5df2\u77e5\u7684\u5925\u4f34 dht.reseed.group=\u91cd\u65b0\u505a\u7a2e dht.reseed.ip=IP \u4f4d\u5740 dht.reseed.port=\u9023\u63a5\u57e0 dht.reseed=\u91cd\u65b0\u505a\u7a2e dht.reseed.info=\u8cc7\u6599\u5eab\u91cd\u65b0\u505a\u7a2e dht.diagnostics.group=\u8a3a\u65b7 DHTView.title.full=\u5206\u6563\u6027\u8cc7\u6599\u5eab DHTView.title.fullcvs=\u5206\u6563\u6027\u8cc7\u6599\u5eab CVS DHTView.general.title=\u4e00\u822c DHTView.general.uptime=\u5de5\u4f5c\u6642\u9593\uff1a DHTView.general.users=\u4f7f\u7528\u8005\uff1a DHTView.general.nodes=Nodes\uff1a DHTView.general.leaves=Leaves\uff1a DHTView.general.contacts=Contacts\uff1a DHTView.general.replacements=Replacements\uff1a DHTView.general.live=Live\uff1a DHTView.general.unknown=\u672a\u77e5\u7684\uff1a DHTView.general.dying=Dying\uff1a DHTView.transport.title=\u50b3\u9001\u7d30\u7bc0 DHTView.transport.packets=\u5c01\u5305 DHTView.transport.bytes=\u4f4d\u5143\u7d44 DHTView.transport.received=\u5df2\u63a5\u6536 DHTView.transport.sent=\u5df2\u50b3\u9001 DHTView.transport.in=\u9032\uff1a DHTView.transport.out=\u51fa\uff1a DHTView.operations.title=\u64cd\u4f5c\u7d30\u7bc0 DHTView.operations.sent=\u5df2\u50b3\u9001 DHTView.operations.ok=\u78ba\u5b9a DHTView.operations.failed=\u5931\u6557\u7684 DHTView.operations.received=\u5df2\u63a5\u6536 DHTView.operations.ping=Ping\uff1a DHTView.operations.findNode=\u5c0b\u627e\u7bc0\u9ede DHTView.operations.findValue=\u5c0b\u627e\u6578\u503c DHTView.operations.store=\u5132\u5b58 DHTView.activity.title=\u6d3b\u52d5 DHTView.activity.status=\u72c0\u614b DHTView.activity.status.true=\u5df2\u6392\u7a0b DHTView.activity.status.false=\u57f7\u884c\u4e2d DHTView.activity.type=\u985e\u578b DHTView.activity.type.1=\u5167\u90e8\u53d6\u5f97 DHTView.activity.type.2=\u5916\u90e8\u53d6\u5f97 DHTView.activity.type.3=\u5167\u90e8\u767c\u51fa DHTView.activity.type.4=\u5916\u90e8\u767c\u51fa DHTView.activity.target=\u76ee\u6a19 DHTView.activity.details=\u8a73\u7d30\u8cc7\u8a0a DHTView.db.title=\u8cc7\u6599\u5eab DHTView.db.keys=\u95dc\u9375 DHTView.db.values=\u6578\u503c DHTView.db.local=\u672c\u5730 DHTView.db.direct=\u76f4\u63a5 DHTView.db.indirect=\u9593\u63a5 DHTView.db.divfreq=\u983b\u7387 DHTView.db.divsize=\u5927\u5c0f MainWindow.dht.status.tooltip=\u7576\u5206\u6563\u8cc7\u6599\u5eab\u57f7\u884c\u6642\uff0c\u986f\u793a\u9810\u4f30\u7684\u7dda\u4e0a\u4f7f\u7528\u8005\u6578\u76ee MainWindow.dht.status.disabled=\u505c\u7528 DHT MainWindow.dht.status.failed=DHT \u932f\u8aa4 MainWindow.dht.status.initializing=DHT \u521d\u59cb\u5316\u4e2d MainWindow.dht.status.users=%1 \u4f4d\u4f7f\u7528\u8005 MainWindow.dht.status.unreachable=DHT \u88ab\u9632\u706b\u7246\u963b\u64cb MainWindow.dht.status.unreachabletooltip=\u5206\u6563\u5f0f\u8cc7\u6599\u5eab\u7684 UDP \u9023\u63a5\u57e0\u6709\u5b9a\u4f4d\u554f\u984c (NAT/firewall) MyTorrentsView.menu.setUpSpeed=\u8a2d\u5b9a\u4e0a\u50b3\u901f\u5ea6 MyTorrentsView.menu.setDownSpeed=\u8a2d\u5b9a\u4e0b\u8f09\u901f\u5ea6 ConfigView.section.tracker.client.showwarnings=\u986f\u793a tracker \u56de\u5831\u7684\u8b66\u544a\u8a0a\u606f dht.advanced=\u555f\u52d5\u9032\u968e\u8a2d\u5b9a dht.advanced.group=\u9032\u968e\u8a2d\u5b9a dht.advanced.label=\u9664\u975e\u60a8\u6e05\u695a\u5728\u505a\u4ec0\u9ebc\uff0c\u5426\u5247\u4e0d\u8981\u4fee\u6539\u9019\u4e9b\u6578\u503c dht.override.ip=Override \u5916\u90e8 IP \u4f4d\u5740 ConfigView.section.logging.loggerenable=\u555f\u7528\u8a18\u9304 ConfigView.section.ipfilter.blockbanning=\u5982\u6b64\u5340\u6bb5\u81f3\u5c11\u6709\u4e0b\u5217\u4f4d\u5740\u6578\u88ab\u5c01\u9396\uff0c\u5c01\u9396\u6574\u500b\u5340\u6bb5 MyTrackerView.passive=\u88ab\u52d5\u5f0f TableColumn.header.swarm_average_speed=Swarm \u5e73\u5747\u901f\u5ea6 TableColumn.header.swarm_average_speed.info=Swarm \u4e2d\u5925\u4f34\u7684\u5e73\u5747\u901f\u5ea6 MyTrackerView.category=\u5206\u985e MainWindow.menu.file.open.torrentfortracking=Torrent \u6a94... (\u50c5\u4f5c\u70baTracking) MyTrackerView.date_added=\u5df2\u52a0\u5165 ConfigView.section.tracker.portbackup=\u5099\u7528\u9023\u63a5\u57e0\uff08\u7528 ';' \u5206\u9694\uff09 ConfigView.label.playfilespeech=\u7576\u6a94\u6848\u5b8c\u6210\u5f8c\u64ad\u653e\u8a9e\u97f3 ConfigView.label.playfilespeech.info=\u76ee\u524d\u53ea\u6709\u82f1\u8a9e\u767c\u97f3 ConfigView.label.playfilefinished=\u7576\u6a94\u6848\u5b8c\u6210\u5f8c\u64ad\u653e\u8072\u97f3 ConfigView.label.backupconfigfiles=\u5099\u4efd\u8a2d\u5b9a\u6a94\u4ee5\u4fbf\u56de\u5fa9\u3002 ConfigView.section.tracker.client.scrapesingleonly=\u505c\u7528\u6bcf\u500b tracker \u7684 scrape \u96c6\u5408\uff08\u6709\u52a9\u65bc\u6e1b\u5c11 tracker \u56de\u5831 'URL \u904e\u9577'\uff08414\uff09\u932f\u8aa4\uff09 dht.ipfilter.log=\u8a18\u9304 IP \u904e\u6ffe\u5668\u9055\u898f ConfigView.label.seeding.addForSeedingDLCopyCount=\u7576\u5df2\u4e0b\u8f09\u7684\u62f7\u8c9d\u6578\u76ee\u70ba\u4e0b\u5217\u6578\u503c\u6642\uff0c\u8003\u616e\u52a0\u5165\u505a\u7a2e ActivityView.legend.limit=\u901f\u7387\u9650\u5236 ActivityView.legend.achieved=\u9054\u5230\u901f\u7387 ActivityView.legend.peeraverage=\u5e73\u5747 ActivityView.legend.swarmaverage=\u7fa4\u9ad4\u5e73\u5747\u901f\u7387 ActivityView.legend.trimmed=Trimmed (\u865b\u7dda) MyTorrentsView.menu.movemenu=\u79fb\u52d5\u6a94\u6848 MyTorrentsView.menu.movedata=\u79fb\u52d5\u8cc7\u6599\u6a94\u6848... MyTorrentsView.menu.movetorrent=\u79fb\u52d5 Torrent \u6a94 MyTorrentsView.menu.movedata.dialog=\u9078\u64c7\u65b0\u7684\u4f4d\u7f6e DHTView.operations.data=\u8cc7\u6599 DHTView.general.reachable=Reachable\uff1a DHTView.general.rendezvous=Rendezvous\uff1a ConfigView.label.queue.maxactivetorrentswhenseeding=\u7576\u4f5c\u7a2e\u6642\u8a2d\u70ba\u6700\u5927\u503c [0:\u7121\u9650\u5236] IrcView.title.short=IRC \u804a\u5929\u5ba4 Views.plugins.IRC.title=IRC - \u7dda\u4e0a\u6280\u8853\u652f\u63f4 Formats.units.persec=/\u79d2 Formats.units.TiB=TiB (\u4e8c\u9032\u4f4d) Formats.units.Tibit=Tibit (\u4e8c\u9032\u4f4d) Formats.units.Tbit=Tbit (\u5341\u9032\u4f4d) Formats.units.GiB=GiB (\u4e8c\u9032\u4f4d) Formats.units.Gibit=Gibit (\u4e8c\u9032\u4f4d) Formats.units.Gbit=Gbit (\u5341\u9032\u4f4d) Formats.units.MiB=MiB (\u4e8c\u9032\u4f4d) Formats.units.Mibit=Mibit (\u4e8c\u9032\u4f4d) Formats.units.Mbit=Mbit (\u4e8c\u9032\u4f4d) Formats.units.KiB=KiB (\u4e8c\u9032\u4f4d) Formats.units.Kibit=Kibit (\u4e8c\u9032\u4f4d) Formats.units.kbit=kbit (\u5341\u9032\u4f4d) Formats.units.bit=\u4f4d\u5143 Formats.units.alot=\u5f88\u591a !!! ConfigView.section.ipfilter.persistblocking=\u6bcf\u6b21\u91cd\u555f\u6642\u5132\u5b58\u5c01\u9396\u7684 IP \u7d30\u7bc0 FilesView.menu.rename=\u91cd\u65b0\u547d\u540d\u6216\u91cd\u8a2d\u76ee\u7684\u5730 FilesView.rename.choose.path=\u9078\u64c7\u65b0\u589e\u6216\u5df2\u5b58\u5728\u7684\u6a94\u6848 FilesView.rename.confirm.delete.title=\u78ba\u8a8d\u522a\u9664 FilesView.rename.confirm.delete.text=\u78ba\u8a8d\u522a\u9664\u539f\u59cb\u6a94 '%1' ConfigView.section.mode=\u6a21\u5f0f ConfigView.section.mode.title=\u4f7f\u7528\u8005\u719f\u7df4\u5ea6 ConfigView.section.mode.beginner=\u521d\u5b78\u8005 ConfigView.section.mode.beginner.wiki.definitions=BitTorrent \u5b57\u5f59 ConfigView.section.mode.intermediate=\u4e2d\u968e\u4f7f\u7528\u8005 ConfigView.section.mode.intermediate.wiki.host=host \u6a94\u6848 ConfigView.section.mode.intermediate.wiki.publish=\u767c\u4f48\u6a94\u6848 ConfigView.section.mode.advanced=\u9032\u968e ConfigView.section.mode.advanced.wiki.main=Wiki \u4e3b\u9801 ConfigView.section.mode.beginner.text=\u60a8\u53ea\u9700\u8981\u4e0b\u8f09 torrents\n\u5982\u50c5\u9700\u7ba1\u7406 torrents\uff0c\u4f7f\u7528\u9019\u500b\u6a21\u5f0f ConfigView.section.mode.intermediate.text=\u5b58\u53d6 tracker \u529f\u80fd\n\u5982\u679c\u60a8\u60f3\u8981\u5efa\u7acb\u5c08\u5c6c\u7684 tracker \u548c host/\u767c\u4f48\u4f60\u7684\u6a94\u6848\uff0c\u4f7f\u7528\u9019\u500b\u6a21\u5f0f ConfigView.section.mode.advanced.text=\u7db2\u8def\u5b58\u53d6\u8a2d\u5b9a\n\u5982\u679c\u60a8\u77e5\u9053 MTU \u6216\u672a\u5c01\u9396\u7684 I/O \u8a2d\u5b9a\uff0c\u4f7f\u7528\u9019\u500b\u6a21\u5f0f... Files.column.storagetype=\u5132\u5b58\u65b9\u5f0f FileItem.storage.linear=\u7dda\u6027 FileItem.storage.compact=\u7dca\u5bc6 MessageBoxWindow.rememberdecision=\u8a18\u4f4f\u6211\u7684\u9078\u64c7 ConfigView.section.interface.cleardecisions=\u6e05\u9664\u5df2\u8a18\u61b6\u7684\u5c0d\u8a71\u8a2d\u5b9a ConfigView.section.interface.cleardecisionsbutton=\u6e05\u9664 configureWizard.welcome.usermodes=\u9032\u968e\u4f7f\u7528\u8005\u8a2d\u5b9a\u5728 \u5de5\u5177->\u9078\u9805\u4e2d\u3002\u60a8\u53ef\u4ee5\u4f9d\u7167\u81ea\u5df1\u7684\u559c\u597d\u53bb\u8a2d\u5b9a\u3002 FilesView.skip.confirm.delete.text=\u622a\u65b7\u6a94\u6848 '%1' \u4ee5\u7bc0\u7701\u7a7a\u9593? FilesView.rename.failed.title=\u91cd\u65b0\u547d\u540d/\u91cd\u8a2d\u76ee\u7684\u5730\u5931\u6557 FilesView.rename.failed.text=\u64cd\u4f5c\u5931\u6557\uff0c\u53ef\u80fd\u662f\u56e0\u70ba\u9078\u64c7\u4e86\u7121\u6548\u7684\u76ee\u6a19 diagnostics.log_found=Vuze\u4e0a\u6b21\u95dc\u9589\u4e0d\u5b8c\u5168\uff0c\u8acb\u6aa2\u67e5 \u8a18\u9304\u6a94\u8a3a\u65b7\u4e26\u8003\u616e\u662f\u5426\u8981\u5c07\u932f\u8aa4\u8a18\u9304\u56de\u5831\u7d66 Vuze \u5718\u968a\u3002 \u4e5f\u53ef\u4ee5\u67e5\u8a62 Wiki\uff08\u53c3\u7167 Help \u9078\u55ae\uff09\u7684 'Vuze Disappears' ManagerItem.paused=\u66ab\u505c Utils.link.visit=\u8acb\u53c3\u89c0 ConfigView.section.connection.serverport.wiki=\u826f\u597d\u7684\u50b3\u8f38\u57e0\u9078\u9805 ConfigView.section.transfer.speeds.wiki=\u826f\u597d\u7684\u901f\u5ea6\u8a2d\u7f6e installPluginsWizard.installMode.info.title=\u8cc7\u8a0a installPluginsWizard.installMode.info.text=Vuze \u5373\u4f7f\u6c92\u6709\u5916\u639b\u6a21\u7d44\u4e5f\u80fd\u6b63\u5e38\u5de5\u4f5c\uff0c\u5916\u639b\u6a21\u7d44\u984d\u5916\u63d0\u4f9b\u4e86\u81ea\u52d5\u5316\uff0c\u9060\u7aef\u9059\u63a7\u7b49\u6709\u8da3\u7684\u529f\u80fd\u3002 \n \u5728\u60a8\u6c7a\u5b9a\u8981\u5b89\u88dd\u5916\u639b\u6a21\u7d44\u524d\u8acb\u5148\u4ed4\u7d30\u95b1\u8b80\u8aaa\u660e \n \u5927\u90e8\u5206\u7684\u5916\u639b\u6a21\u7d44\u90fd\u53ef\u4ee5\u5b89\u5168\u57f7\u884c\uff0c\u4f46\u8acb\u4e0d\u8981\u5b89\u88dd\u904e\u591a\u4e0d\u9700\u8981\u7684\u5916\u639b\u6a21\u7d44\u3002 Views.plugins.Distributed.DB.title=\u5206\u6563\u5f0f DB Views.plugins.Distributed.Tracker.title=\u5206\u6563\u5f0f Tracker Views.plugins.Plugin.Update.title=\u5916\u639b\u6a21\u7d44\u66f4\u65b0 Views.plugins.UPnP.title=UPnP \u67b6\u69cb Views.plugins.UPnP.title.tooltip=\u901a\u7528\u96a8\u63d2\u96a8\u7528 openUrl.url.info=\u652f\u63f4 http, https, magnet \u4ee5\u53ca raw hex infohash strings TableColumn.header.swarm_average_completion=\u5925\u4f34\u7684\u5e73\u5747\u5b8c\u6210\u5ea6 TableColumn.header.swarm_average_completion.info=Swarm \u4e2d\u5925\u4f34\u7684\u5e73\u5747\u5b8c\u6210\u7387 GeneralView.label.swarm_average_completion=\u5e73\u5747\u5b8c\u6210\uff1a GeneralView.label.swarm_average_completion.tooltip=Swarm \u4e2d\u5925\u4f34\u7684\u5e73\u5747\u5b8c\u6210\u767e\u5206\u6bd4 MainWindow.nat.status.tooltip.unknown=Firewall/NAT \u9023\u7dda\u72c0\u6cc1\u4e0d\u660e (TCP) MainWindow.nat.status.ok=NAT \u6b63\u5e38 MainWindow.nat.status.tooltip.ok=\u9023\u7dda\u6b63\u5e38 (TCP) MainWindow.nat.status.probok=NAT \u6b63\u5e38? MainWindow.nat.status.tooltip.probok=\u9023\u7dda\u6b63\u5e38, \u4f46\u662f\u6c92\u6709\u9032\u884c\u4e2d\u7684 TCP \u9023\u7dda MainWindow.nat.status.bad=\u88ab\u9632\u706b\u7246\u64cb\u4f4f MainWindow.nat.status.tooltip.bad=Firewall/NAT (TCP) \u9023\u7dda\u554f\u984c,\u8acb\u53c3\u7167 Wiki plugin.installer.recommended.plugin=\u5efa\u8b70\u7684\u5916\u639b\u6a21\u7d44 - \u5982\u6709\u5fc5\u8981\u8acb\u5b89\u88dd LoggerView.pause=\u505c\u6b62\u8a18\u9304 LoggerView.clear=\u6e05\u9664 (&C) LoggerView.filter=\u904e\u6ffe LoggerView.filter.uncheckAll=\u53d6\u6d88\u9078\u64c7\u6240\u6709\u5206\u985e LoggerView.filter.checkAll=\u9078\u64c7\u6240\u6709\u5206\u985e LoggerView.loggingDisabled=\u6c92\u6709\u555f\u52d5\u8a18\u9304\u529f\u80fd ConfigView.section.logging.log0type=\u8cc7\u8a0a ConfigView.section.logging.log1type=\u8b66\u544a ConfigView.section.logging.log2type=\u932f\u8aa4 ConfigView.section.logging.filter=\u8a18\u9304\u81f3\u6a94\u6848\u6642\u904e\u6ffe ConfigView.section.logging.level=\u8a18\u9304\u5c64\u7d1a ConfigView.section.logging.showLogsFor=\u70ba\u5e95\u4e0b\u7684\u5206\u985e\u986f\u793a %1 \u8a18\u9304 ConfigView.pluginlist.column.loadAtStartup=\u958b\u6a5f\u6642\u8f09\u5165 ConfigView.pluginlist.column.type=\u7a2e\u985e ConfigView.pluginlist.column.type.perUser=\u6bcf\u500b\u4f7f\u7528\u8005 ConfigView.pluginlist.column.type.shared=\u5171\u4eab ConfigView.pluginlist.column.type.builtIn=\u5167\u5efa ConfigView.pluginlist.column.name=\u540d\u7a31 ConfigView.pluginlist.column.version=\u7248\u672c ConfigView.pluginlist.column.directory=\u76ee\u9304 ConfigView.pluginlist.column.isOperational=\u53ef\u88ab\u64cd\u4f5c\u7684 PeersView.BlockView.Avail.Have=\u96d9\u65b9\u90fd\u6709 PeersView.BlockView.Avail.NoHave=\u5925\u4f34\u6709:\u53ef\u662f\u60a8\u6c92\u6709 PeersView.BlockView.NoAvail.Have=\u60a8\u6709\uff0c\u4f46\u662f\u5925\u4f34\u6c92\u6709 PeersView.BlockView.NoAvail.NoHave=\u90fd\u6c92\u6709 PeersView.BlockView.Transfer=\u50b3\u9001\u4e2d PeersView.BlockView.NextRequest=\u4e0b\u6b21\u8981\u6c42 PeersView.BlockView.title=\u6a94\u6848\u584a\u5206\u5e03\u5716 PeersView.BlockView.AvailCount=\u53ef\u7528\u5ea6\u8a08\u7b97 MyTorrentsView.dialog.NumberError.title=\u7121\u6548\u6216\u7121\u6cd5\u8fa8\u8b58\u7684\u6578\u5b57 MyTorrentsView.dialog.NumberError.text=\u60a8\u8f38\u5165\u7684\u6578\u5b57\u7121\u6548\u6216\u662f\u7121\u6cd5\u8fa8\u8b58 MyTorrentsView.menu.manual=\u624b\u52d5... (&M) MyTorrentsView.dialog.setSpeed.title=\u8a2d\u5b9a %1 \u901f\u5ea6 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=\u8f38\u5165 %1 \u4f86\u66f4\u6539 %2: MyTorrentsView.dialog.setNumber.upload=\u4e0a\u50b3 MyTorrentsView.dialog.setNumber.download=\u5df2\u4e0b\u8f09 MyTorrentsView.dialog.setNumber.inKbps=%1 OpenTorrentWindow.torrentLocation=Torrent \u6a94: OpenTorrentWindow.addFiles.URL=\u5f9e URL \u52a0\u5165 (&U) OpenTorrentWindow.addFiles.Folder=\u5f9e\u6a94\u6848\u593e\u52a0\u5165 (&F) OpenTorrentWindow.addFiles.Clipboard=\u5f9e\u526a\u8cbc\u7c3f\u52a0\u5165 (&B) OpenTorrentWindow.changeDestination=\u8b8a\u66f4\u76ee\u7684\u5730 OpenTorrentWindow.fileList=torrent \u5305\u542b\u7684\u6a94\u6848: OpenTorrentWindow.torrentTable.name=\u540d\u7a31 OpenTorrentWindow.torrentTable.saveLocation=\u5132\u5b58\u4f4d\u7f6e OpenTorrentWindow.fileTable.fileName=\u6a94\u6848\u540d\u7a31 OpenTorrentWindow.fileTable.size=\u5927\u5c0f OpenTorrentWindow.fileTable.destinationName=\u76ee\u6a19\u540d\u7a31 OpenTorrentWindow.startMode.seeding=\u6b63\u5728\u505a\u7a2e OpenTorrentWindow.fileList.changeDestination=\u8b8a\u66f4\u76ee\u7684\u5730 OpenTorrentWindow.mb.badSize.title=\u4e0d\u76f8\u5bb9\u7684\u6a94\u6848 OpenTorrentWindow.mb.badSize.text='%1' \u4e0d\u662f '%2' \u800c\u4e14\u7121\u6cd5\u7528\u65bc\u505a\u7a2e OpenTorrentWindow.mb.alreadyExists.text=%3 \u7684\u8cc7\u6599\u5df2\u7d93\u88ab '%2' \u52a0\u5165\u904e OpenTorrentWindow.mb.alreadyExists.title=Torrent \u5df2\u5b58\u5728 OpenTorrentWindow.mb.openError.title=\u958b\u555f\u932f\u8aa4 OpenTorrentWindow.mb.openError.text='%1' \u53ef\u4ee5\u88ab\u958b\u555f: OpenTorrentWindow.torrent.remove=\u5c07 torrent \u5f9e\u5217\u8868\u4e0a\u79fb\u9664 OpenTorrentWindow.torrent.options=\u4e0b\u5217\u8a2d\u5b9a\u5c07\u6703\u5957\u7528\u5728\u4e0a\u9762\u6240\u9078\u64c7\u7684 torrent OpenTorrentWindow.xOfTotal=(%1 / %2) iconBar.open.tooltip=\u6253\u958b Torrent(s) LocaleUtil.column.text=\u4e0d\u660e\u7684\u6587\u5b57 Tracker.tooltip.MultiSupport=\u9019\u500b tracker \u652f\u63f4\u591a\u91cd hash scrapes \u7684\u8981\u6c42 Tracker.tooltip.NoMultiSupport=\u9019\u500b tracker \u4e0d\u652f\u63f4\u591a\u91cd hash scrapes \u7684\u8981\u6c42 ConfigView.label.lazybitfield=\u4f7f\u7528\u5ef6\u9072\u4f4d\u5143\u6b04\u4f4d (\u6709\u52a9\u65bc\u5728\u57fa\u65bc\u963b\u64cb\u4f4d\u5143\u6b04\u4f4d\u7684\u7db2\u8def\u4e0a\u505a\u7a2e) LoggerView.realtime=\u5373\u6642\u66f4\u65b0 ConfigView.section.file.perf.cache.flushpieces=\u7acb\u5373\u5c07\u5b8c\u6210\u7684\u6a94\u6848\u5206\u584a\u5beb\u5165\u78c1\u789f\u3002\u5982\u6b64\u53ef\u8212\u7de9\u78c1\u789f\u7684\u5b58\u53d6\u6578\uff0c\u4f46\u662f\u6703\u5c0e\u81f4\u8f03\u591a\u7684\u5beb\u5165\u52d5\u4f5c ConfigView.section.file.writemblimit=\u5df2\u6392\u7a0b\u7684\u6700\u5927\u5beb\u5165\u8981\u6c42 ( %1 ) ConfigView.section.file.writemblimit.explain=\u78c1\u789f\u8b80\u53d6\u901f\u5ea6\u4f4e\u65bc\u4e0b\u8f09\u901f\u5ea6\u6642\uff0c\u9019\u500b\u53c3\u6578\u53ef\u7528\u4f86\u9650\u5236\u6392\u7a0b\u7684\u8cc7\u6599\u91cf\uff0c\u76f4\u5230\u4e0b\u8f09\u901f\u5ea6\u964d\u4f4e ConfigView.section.file.readmblimit=\u6392\u7a0b\u4e2d\u7684\u6700\u5927\u8b80\u53d6\u8981\u6c42\u6578 ( %1 ) ConfigView.section.file.readmblimit.explain=\u9019\u9805\u53c3\u6578\u7528\u4f86\u9650\u5236\u672a\u5b8c\u6210\u7684\u8b80\u53d6\u52d5\u4f5c\uff0c\u6240\u80fd\u4f7f\u7528\u7684\u8a18\u61b6\u9ad4\u5927\u5c0f Button.moveUp=\u4e0a\u79fb (&U) Button.moveDown=\u4e0b\u79fb (&D) ConfigView.notAvailableForMode=\u9019\u90e8\u4efd\u662f\u4f9b%1\u6216\u66f4\u9032\u968e\u7684\u6a21\u5f0f\u4f7f\u7528\u3002%2\u6a21\u5f0f\u7121\u6cd5\u4f7f\u7528\u3002 health.explain.error=\u9019\u500b torrent \u6709\u932f\u8aa4\u3002\u8acb\u5bdf\u770b\u72c0\u614b\u884c\uff0c\u6216\u662f\u5bdf\u770b\u5de5\u5177\u63d0\u793a\u7684\u5716\u793a PeersView.piece=\u6a94\u6848\u5206\u584a PeersView.piece.info=\u5411\u5925\u4f34\u8981\u6c42\u7684\u6700\u5f8c\u4e00\u584a\u6a94\u6848\u584a\u7de8\u865f PiecesView.priority=\u512a\u5148\u9806\u5e8f PiecesView.priority.info=\u9019\u500b\u6a94\u6848\u5206\u584a\u7684\u512a\u5148\u5b8c\u6210\u9806\u5e8f,\u4f46\u662f\u4e0d\u9700\u8981\u592a\u904e\u65bc\u6ce8\u610f\u5b83 PiecesView.speed=\u901f\u5ea6 PiecesView.speed.info=\u9632\u6b62\u901f\u5ea6\u8f03\u6162\u7684\u5925\u4f34\u5f71\u97ff\u8f03\u5feb\u901f\u7684\u6a94\u6848\u584a TableColumn.header.AvgAvail.info=\u5168\u90e8\u53ef\u7528\u7684\u6a94\u6848\u584a\u6578\u76ee\u7e3d\u548c\u9664\u4ee5\u6a94\u6848\u584a\u6578\u76ee,\u518d\u9664\u4ee5\u9023\u7dda\u6578\u76ee TableColumn.header.AvgAvail=\u5e73\u5747 \u53ef\u7528\u5ea6/\u6a94\u6848\u5206\u584a ConfigView.label.strictfilelocking=\u5f37\u5236\u9396\u4f4f torrents \u4e4b\u9593\u4e92\u76f8\u6392\u65a5\u7684\u6a94\u6848\u5beb\u5165\u52d5\u4f5c MyTorrentsView.menu.rescanfile=\u5b9a\u671f\u6aa2\u67e5\u672a\u5b8c\u6210\u7684\u6a94\u6848\u584a Plugin.extseed.name=\u5916\u90e8\u7a2e\u5b50 Plugin.localtracker.name=\u5340\u57df\u7db2\u8def\u5925\u4f34\u641c\u5c0b\u5668 Plugin.localtracker.info=\u5340\u57df\u7db2\u8def\u5925\u4f34\u641c\u5c0b\u5668\u5141\u8a31\u5728\u540c\u4e00\u500b\u9632\u706b\u7246\u5167\u7684\u7db2\u8def\u5167\u6709\u591a\u500b Vuze \u4f7f\u7528\u8005 \n \u4f7f\u7528\u8005\u4e4b\u9593\u53ef\u4ee5\u76f4\u63a5\u9023\u7dda\u4e0b\u8f09 torrents Plugin.localtracker.enable=\u555f\u52d5\u5340\u57df\u7db2\u8def\u5925\u4f34\u641c\u5c0b\u5668 azinstancehandler.alert.portclash=\u5075\u6e2c\u5230\u9023\u63a5\u57e0\u885d\u7a81: %1 \u5df2\u7d93\u88ab\u5176\u4ed6\u7684 Vuze \u7528\u6236\u4f7f\u7528, \u8acb\u9078\u64c7\u5176\u4ed6\u7684 TCP/UDP \u9023\u63a5\u57e0\u4f86\u76e3\u807d\u7db2\u8def [\u4ecb\u65bc %2 \u548c %3]. ConfigView.section.transfer.lan=\u5340\u57df\u7db2\u8def\uff08LAN\uff09 ConfigView.section.transfer.lan.tooltip=\u5340\u57df\u7db2\u8def\u5c08\u7528\u8a2d\u7f6e ConfigView.section.transfer.lan.uploadrate=KB/s \u5340\u7db2\u6700\u5927\u4e0a\u50b3\u901f\u5ea6 [0\uff1a\u7121\u9650\u5236] ConfigView.section.transfer.lan.uploadrate.tooltip=\u540c\u4e00\u500b\u5167\u90e8\u5340\u7db2\u5167\uff0c\u5925\u4f34\u53ef\u5206\u914d\u5230\u7684\u4e0a\u50b3\u901f\u9650 ConfigView.section.transfer.lan.downloadrate=KB/s \u5340\u7db2\u6700\u5927\u4e0b\u8f09\u901f\u5ea6 [0\uff1a\u7121\u9650\u5236] ConfigView.section.transfer.lan.downloadrate.tooltip=\u540c\u4e00\u500b\u5167\u90e8\u5340\u7db2\u5167\uff0c\u5925\u4f34\u53ef\u5206\u914d\u5230\u7684\u4e0b\u8f09\u901f\u9650 TorrentOptionsView.title.short=\u9078\u9805 TorrentOptionsView.title.full=\u9078\u9805 TorrentOptionsView.param.max.peers=\u6700\u5927\u9023\u7dda\u6578\u91cf [0\uff1a\u7121\u9650\u5236] ConfigView.section.connection.encryption.require_encrypted_transport=\u9700\u8981\u52a0\u5bc6\u7684\u50b3\u8f38 ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=\u5c0d\u5925\u4f34\u5f37\u5236\u4f7f\u7528\u52a0\u5bc6\u7684\u50b3\u8f38 ConfigView.section.connection.encryption.min_encryption_level=\u6700\u4f4e\u52a0\u5bc6\u7b49\u7d1a ConfigView.section.connection.encryption.min_encryption_level.tooltip=Plain - \u53ea\u6aa2\u67e5\u50b3\u9001\u7684\u8cc7\u6599\nRC4 - \u6aa2\u67e5\u5168\u90e8\u7684\u4e32\u6d41\n\u8d8a\u9ad8\u7684\u52a0\u5bc6\u7b49\u7d1a\u8017\u8cbb\u8d8a\u591a\u7684 CPU \u8cc7\u6e90 Peers.column.Encryption=\u52a0\u5bc6 Peers.column.Encryption.info=\u4f7f\u7528\u591a\u5c64\u52a0\u5bc6 ConfigView.section.connection.encryption.encrypt.info=\u5982\u4f7f\u7528\u52a0\u5bc6\uff0c\u9664\u975e\u53e6\u5916\u8a2d\u5b9a\u5099\u7528\u9078\u9805\uff0c\u5426\u5247\u60a8\u5c07\u7121\u6cd5\u9023\u7dda\u81f3\u4e0d\u652f\u63f4\u52a0\u5bc6\u7684\u7528\u6236\u7aef ConfigView.section.connection.encryption.encrypt.info.link=\u8acb\u53c3\u7167\u9019\u88e1\u4ee5\u7372\u5f97\u8a73\u7d30\u8aaa\u660e MainWindow.sr.status.tooltip.ok=\u5206\u4eab\u7387 %1 OK MainWindow.sr.status.tooltip.poor=\u5206\u4eab\u7387 %1 \u4e0d\u826f: < 0.9 MainWindow.sr.status.tooltip.bad=\u5206\u4eab\u7387 %1 \u5f88\u5dee: < 0.5 ConfigView.section.style.status=\u72c0\u614b\u5340\u57df\uff1a ConfigView.section.style.status.show_sr=\u5206\u4eab\u7387 ConfigView.section.style.status.show_nat=NAT \u72c0\u614b ConfigView.section.style.status.show_ddb=DDB \u72c0\u614b ConfigView.section.connection.encryption.encrypt.group=\u52a0\u5bc6\u50b3\u8f38 / \u6a21\u7cca\u50b3\u8f38 ConfigView.section.connection.encryption.encrypt.fallback_info=\u555f\u7528\u6642\u4e0d\u6703\u62d2\u7d55\u8cc7\u683c\u4e0d\u7b26\u7684\u7528\u6236\u7aef\u9023\u7dda\uff0c\u4f46\u662f\u6703\u5c0e\u81f4\u7121\u52a0\u5bc6\u7684\u9023\u7dda ConfigView.section.connection.encryption.encrypt.fallback_outgoing=\u5982\u679c\u52a0\u5bc6\u7684\u9023\u7dda\u8acb\u6c42\u5931\u6557\uff0c\u5247\u5141\u8a31\u975e\u52a0\u5bc6\u7684\u5916\u9001\u9023\u7dda ConfigView.section.connection.encryption.encrypt.fallback_incoming=\u5141\u8a31\u672a\u52a0\u5bc6\u7684\u50b3\u5165\u9023\u7dda ConfigView.section.connection.encryption=\u52a0\u5bc6\u50b3\u8f38 upnp.selectedinterfaces=\u9078\u64c7\u754c\u9762 (\u7528';'\u5206\u9694, e.g. eth0;eth1) [\u7a7a\u767d: \u5168\u9078] ConfigView.section.style.defaultSortOrder=\u9810\u8a2d\u6392\u5e8f\u65b9\u5f0f ConfigView.section.style.defaultSortOrder.desc=\u905e\u6e1b ConfigView.section.style.defaultSortOrder.asc=\u905e\u589e ConfigView.section.style.defaultSortOrder.flip=\u9006\u8f49\u4e4b\u524d\u7684\u6392\u5217\u9806\u5e8f LoggerView.autoscroll=\u81ea\u52d5\u6372\u52d5 Button.selectAll=\u5168\u9078 Button.markSelected=\u6a19\u8a18\u5df2\u9078 Button.unmarkSelected=\u53cd\u5411\u6a19\u8a18 plugins.basicview.config=\u8a2d\u5b9a TorrentOptionsView.param.max.uploads=\u6700\u5927\u4e0a\u50b3\u9023\u7dda\u6578\u91cf [\u6700\u5c0f\u503c: 2] MyTorrentsView.dialog.setPosition.title=\u8a2d\u5b9a\u4f4d\u7f6e MyTorrentsView.dialog.setPosition.text=\u70ba\u9078\u64c7\u7684 torrents \u8f38\u5165\u4f4d\u7f6e MyTorrentsView.menu.reposition.manual=\u518d\u914d\u7f6e ConfigView.section.connection.advanced.info.link=\u8acb\u53c3\u7167\u6b64\u8655\u7684\u8a73\u7d30\u8aaa\u660e ConfigView.section.connection.advanced.socket.group=Socket \u9078\u9805 ConfigView.section.connection.advanced.bind_port=\u9650\u5236\u5728\u672c\u5730\u9023\u63a5\u57e0 [0\uff1a\u505c\u7528] ConfigView.section.connection.advanced.bind_port.tooltip=\u9001\u51fa\u7684 socket \u9023\u7dda\u5c07\u6703\u9650\u5236\u5728\u7d66\u4e88\u7684\u672c\u5730\u7aef\u9023\u63a5\u57e0\n\u555f\u7528\u6b64\u9078\u9805\u6709\u52a9\u65bc\u907f\u514d NAT \u8def\u7531\u5668\u4e0d\u7a69\u5b9a ConfigView.section.proxy.group.tracker=tracker \u901a\u8a0a ConfigView.section.proxy.group.peer=\u5925\u4f34\u901a\u8a0a Pieces.column.Requested=\u5df2\u8981\u6c42 Pieces.column.Requested.info=\u986f\u793a\u662f\u5426\u8a72\u6a94\u6848\u584a\u6709\u66f4\u591a\u7684\u8981\u6c42 (*) ConfigView.label.maxuploadsseeding=\u505a\u7a2e\u6642\u7684\u9810\u8a2d\u4e0a\u50b3\u901f\u5ea6 MyTorrentsView.filter=\u904e\u6ffe\uff1a popup.error.hideall=\u96b1\u85cf\u5168\u90e8 ConfigView.section.style.dataStatsOnly=\u50c5\u986f\u793a\u8cc7\u6599\u7d71\u8a08\uff08\u96b1\u85cf\u5354\u5b9a\u7d71\u8a08\uff09 ConfigView.section.style.separateProtDataStats=\u5c07\u5206\u9694\u7684\u8cc7\u6599\u548c\u5354\u5b9a\u7d71\u8a08\u986f\u793a\u70ba 'data (protocol)' MyTorrentsView.dialog.setFilter.title=\u8b8a\u66f4\u904e\u6ffe\u689d\u4ef6 MyTorrentsView.dialog.setFilter.text=%1 \u6703\u4f7f\u7528\u60a8\u6307\u5b9a\u7684\u6587\u5b57\u904e\u6ffe. \u4f7f\u7528 | (\u5c0e\u7ba1) \u7b26\u865f\u4f86\u904e\u6ffe\u591a\u91cd\u689d\u4ef6. MyTorrentsView.filter.tooltip=\u4f7f\u7528 Ctrl+X \u5728 RegEx \u548c\u4e00\u822c\u641c\u5c0b\u4e0b\u5207\u63db\u3002\n\u4f7f\u7528 | (\u5c0e\u7ba1) \u7b26\u865f\u4f86\u904e\u6ffe\u591a\u91cd\u689d\u4ef6\u3002 MyTorrentsView.clearFilter.tooltip=\u6e05\u9664\u904e\u6ffe\u689d\u4ef6 MyTorrentsView.menu.filter=\u904e\u6ffe\u5217\u8868... ConfigView.section.file.resume.recheck.all=\u7576\u6a5f\u91cd\u65b0\u555f\u52d5\u6642\uff0c\u6aa2\u67e5\u6240\u6709\u5df2\u5b8c\u6210\u7684\u6a94\u6848\u5206\u584a\uff08\u5426\u5247\u53ea\u6703\u6aa2\u67e5\u6700\u5f8c\u5132\u5b58\u7684\u6a94\u6848\u5206\u584a\uff09 ConfigureWizard.language.choose=\u5f9e\u4e0b\u9762\u7684\u5217\u8868\u9078\u64c7\u8a9e\u8a00 popup.closing.in=\u5728 %1 \u79d2\u5f8c\u81ea\u52d5\u95dc\u9589\u8996\u7a97 popup.more.waiting=%1 \u66f4\u591a\u8a0a\u606f.. # > 2402 popup.next=\u4e0b\u4e00\u500b> popup.previous=\u524d\u4e00\u500b< (%1) popup.download.finished="%1" \u5df2\u7d93\u4e0b\u8f09\u5b8c\u7562 popup.file.finished="%1" \u5df2\u7d93\u4e0b\u8f09\u5b8c\u7562 ConfigView.auto=\u81ea\u52d5 Plugin.localtracker.autoadd.info=\u81ea\u52d5\u589e\u52a0\u9019\u4e9b\u5340\u57df\u7db2\u8def\u5167\u7684\u5925\u4f34 [';' separated addresses, e.g. 1.2.3.4] Plugin.localtracker.autoadd=\u660e\u78ba\u7684\u5925\u4f34 Plugin.localtracker.networks.info=\u5c07\u4e0b\u5217\u7db2\u8def\u8996\u70ba\u5340\u57df\u7db2\u8def [';' separated networks, e.g. 145.227.*.*] Plugin.localtracker.networks=\u5340\u57df\u7db2\u8def MainWindow.menu.view.plugins.logViews=\u6aa2\u8996 Log SpeedView.stats.autospeed=\u81ea\u52d5\u8a2d\u5b9a\u4e0a\u50b3\u901f\u5ea6 SpeedView.stats.autospeed.disabled=\u9019\u500b\u529f\u80fd\u5982\u679c\u4e0d\u662f\u505c\u7528 (\u9700\u8981 DHT) \u5c31\u662f\u6c92\u6709\u4f5c\u7528 (\u624b\u52d5\u8a2d\u5b9a\u4e0a\u50b3\u901f\u5ea6) SpeedView.stats.idlePing=\u767c\u5446\u7684 Ping: SpeedView.stats.maxPing=\u6700\u5927 Ping: SpeedView.stats.currentPing=\u73fe\u5728\u7684 Ping: SpeedView.stats.maxUp=\u6700\u5927\u4e0a\u50b3\u901f\u5ea6: ConfigView.pluginlist.unloadSelected=\u9078\u64c7\u5378\u8f09 ConfigView.pluginlist.scan=\u6383\u63cf\u65b0\u7684\u5916\u639b\u6a21\u7d44 ConfigView.section.transfer.autospeed=\u81ea\u52d5\u8a2d\u5b9a\u901f\u5ea6 ConfigView.section.transfer.autospeed.tooltip=\u81ea\u52d5\u5b9a\u901f\u8a2d\u7f6e ConfigView.section.transfer.autospeed.info=\u81ea\u52d5\u5b9a\u901f\u6703\u81ea\u884c\u8abf\u6574\u4e0a\u50b3\u901f\u9650\u4ee5\u907f\u514d\u7db2\u8def\u9023\u7dda\u8d85\u51fa\u8ca0\u8377\n\n\u81ea\u52d5\u4e0a\u50b3\u5b9a\u901f\u548c\u5206\u6563\u8cc7\u6599\u5eab\u540c\u6642\u555f\u7528\u6642\uff0c\u624d\u6703\u5957\u7528\u9019\u9805\u9650\u5236\n ConfigView.section.transfer.autospeed.minupload=%1 \u6700\u5c0f\u4e0a\u50b3\u901f\u5ea6 ConfigView.section.transfer.autospeed.minupload.tooltip=\u6b63\u5e38\u60c5\u6cc1\u4e0b\uff0c\u4e0a\u50b3\u901f\u5ea6\u4e0d\u6703\u4f4e\u65bc\u9019\u500b\u9650\u5236 ConfigView.section.transfer.autospeed.maxupload=%1 \u6700\u5927\u4e0a\u50b3\u901f\u5ea6 [0\uff1a\u7121\u9650\u5236] ConfigView.section.transfer.autospeed.maxupload.tooltip=\u4e0a\u50b3\u901f\u5ea6\u4e0d\u6703\u8d85\u904e\u9019\u500b\u9650\u5236 ConfigView.section.transfer.autospeed.chokeping=\u58c5\u585e\u7684 ping \u56de\u61c9\u6642\u9593 [\u6beb\u79d2] ConfigView.section.transfer.autospeed.chokeping.tooltip=ping \u7684\u6642\u9593\u5982\u679c\u8d85\u904e\u9019\u500b\u503c\uff0c\u8996\u540c\u7db2\u8def\u6d41\u91cf\u5df2\u98fd\u548c ConfigView.section.transfer.autospeed.enableauto=\u4e0b\u8f09\u548c\u505a\u7a2e\u6642\u555f\u7528 ConfigView.section.transfer.autospeed.enableautoseeding=\u50c5\u5728\u505a\u7a2e\u6642\u555f\u7528 ConfigView.pluginlist.column.unloadable=\u7121\u6cd5\u8f09\u5165\u7684 ConfigView.section.transfer.lan.enable=\u70ba\u5340\u57df\u7db2\u8def\u9023\u7dda\u555f\u7528\u5206\u9694\u7684\u901f\u5ea6\u9650\u5236 Plugin.localtracker.wellknownlocals=\u81ea\u52d5\u5305\u542b\u5340\u57df\u7db2\u8def (192.168 etc) TableColumn.header.filesdone=\u5df2\u5b8c\u6210\u6a94\u6848 TableColumn.header.filesdone.info=\u5df2\u5b8c\u6210\u6a94\u6848/\u5168\u90e8\u6a94\u6848 *\u6216* \u6c92\u6709\u7565\u904e\u7684\u5df2\u5b8c\u6210\u6a94\u6848 (\u5df2\u5b8c\u6210\u6a94\u6848)/\u5168\u90e8\u7684\u672a\u7565\u904e\u6a94\u6848 (\u5168\u90e8\u6a94\u6848) MagnetPlugin.private_torrent=<\u79c1\u4eba torrent> MagnetPlugin.decentral_disabled=<\u53d6\u6d88\u5206\u6563\u5f0f tracking> MagnetPlugin.decentral_backup_disabled=<\u53d6\u6d88\u5206\u6563\u5f0f\u5099\u4efd> MagnetPlugin.report.waiting_ddb=\u7b49\u5f85 DDB \u521d\u59cb\u5316... MagnetPlugin.report.searching=\u641c\u5c0b\u4e2d... MagnetPlugin.report.found=%1 \u767c\u73fe MagnetPlugin.report.alive=%1 \u4ecd\u6d3b\u8457 MagnetPlugin.report.dead=%1 \u6b7b\u6389\u4e86 MagnetPlugin.report.tunnel=\u63a5\u901a\u81f3 %1 MagnetPlugin.report.downloading=\u5f9e %1 \u4e0b\u8f09\u4e2d MagnetPlugin.report.error=%1 \u932f\u8aa4 MagnetURLHandler.report.no_sources=torrent \u5167\u6c92\u6709\u4efb\u4f55\u4f86\u6e90 MagnetURLHandler.report.torrent_size=torrent \u5927\u5c0f: %1 MagnetURLHandler.report.percent=\u5df2\u5b8c\u6210: %1% MagnetURLHandler.report.error=\u932f\u8aa4 %1 DHTTransport.report.request_all=\u8981\u6c42\u4f86\u81ea %1 \u6240\u6709\u7684\u50b3\u8f38 DHTTransport.report.received_bit=\u5df2\u63a5\u6536 %1 \u5230 %2 \u4f86\u81ea %3 DHTTransport.report.complete=\u5b8c\u6210 DHTTransport.report.timeout=\u903e\u6642\uff0c %1 \u6c92\u6709\u4efb\u4f55\u56de\u61c9 DHTTransport.report.rerequest_all=\u91cd\u8907\u8981\u6c42\u4f86\u81ea %1 \u6240\u6709\u7684\u50b3\u8f38 DHTTransport.report.rerequest_bit=\u91cd\u8907\u8981\u6c42 %1 \u5230 %2 \u4f86\u81ea %3 DHTTransport.report.timeout_some=\u903e\u6642\uff0c \u5171 %1 \u5c01\u5305\u63a5\u6536\u81ea %2 \uff0c\u4f46\u672a\u5b8c\u6210 DHTTransport.report.sending=\u8cc7\u6599\u50b3\u9001\u4e2d DHTTransport.report.resending=\u91cd\u50b3\u8cc7\u6599 DHTTransport.report.send_complete=\u50b3\u9001\u5b8c\u6210 DHTTransport.report.send_timeout=\u50b3\u9001\u903e\u6642 ConfigView.section.transfer.autospeed.enabledebug=\u8a18\u9304\u9664\u932f\u8a0a\u606f TableColumn.header.date_added=\u52a0\u5165\u65e5\u671f TableColumn.header.date_added.info=\u52a0\u5165 Torrent \u7684\u65e5\u671f ConfigView.section.file.hashchecking.smallestfirst=\u512a\u5148\u91cd\u8907\u6aa2\u67e5"\u6700\u5c0f\u7684\u4e0b\u8f09" platform.win32.baddll.info=Vuze \u5075\u6e2c\u5230 '%1'. \u9019\u662f '%2' \u7684\u4e00\u90e8\u4efd\u4e26\u4e14\u5df2\u77e5\u6703\u5c0e\u81f4\u4e0d\u5c11\u554f\u984c\uff0c\u4f8b\u5982\u5927\u91cf\u6d88\u8017 CPU \u8cc7\u6e90\u5c0e\u81f4\u7cfb\u7d71\u7576\u6a5f. \u5982\u679c\u60a8\u6709\u906d\u9047\u985e\u4f3c\u7684\u60c5\u6cc1,\u8acb\u89e3\u9664\u6b64\u8edf\u9ad4\u7684\u5b89\u88dd\u6216\u662f\u4fee\u6539\u8a2d\u5b9a\u4ee5\u514d\u5f71\u97ff Vuze platform.win32.baddll.netdog=Armor2net Personal Firewall upnp.ignorebaddevices=\u5ffd\u7565\u7121\u6b63\u78ba\u56de\u61c9\u7684\u88dd\u7f6e upnp.ignorebaddevices.info=\u6700\u8fd1\u5ffd\u7565\u7684\u88dd\u7f6e: %1 upnp.ignorebaddevices.reset=\u91cd\u7f6e\u5ffd\u7565\u7684\u88dd\u7f6e\u6e05\u55ae upnp.ignorebaddevices.reset.action=\u91cd\u7f6e upnp.ignorebaddevices.alert=\u5728 %1 \u7684 UPnP \u88dd\u7f6e\u56e0\u70ba\u91cd\u8907\u7684\u932f\u8aa4\u800c\u88ab\u505c\u7528. \u8acb\u53c3\u7167 UPnP \u5916\u639b\u6a21\u7d44\u8a2d\u5b9a\u9078\u9805 TorrentOptionsView.param.max.uploads.when.busy=KB/s \u6700\u5927\u6574\u9ad4\u50b3\u8f38\u901f\u5ea6 [0\uff1a\u7121\u9650\u5236] UpdateMonitor.messagebox.verification.failed.title=\u5b89\u88dd\u6aa2\u67e5\u5931\u6557 UpdateMonitor.messagebox.verification.failed.text=\u6aa2\u67e5 '%1' \u5931\u6557: %2 UpdateMonitor.messagebox.accept.unverified.title=\u63a5\u53d7\u672a\u7d93\u6aa2\u67e5\u7684\u5b89\u88dd UpdateMonitor.messagebox.accept.unverified.text='%1' \u4e0d\u662f\u6b63\u5f0f\u7684 Vuze u5916\u639b\u6a21\u7d44 \n \u5efa\u8b70\u60a8\u505c\u6b62\u5b89\u88dd\u9019\u500b\u5916\u639b\u6a21\u7d44 \n \u7e7c\u7e8c\u5b89\u88dd\uff1f FileView.BlockView.title=\u6a94\u6848\u5206\u584a FileView.BlockView.Done=\u5b8c\u6210 FileView.BlockView.Skipped=\u5df2\u8df3\u904e\u7684 FileView.BlockView.Active=\u4f7f\u7528\u4e2d FileView.BlockView.Outstanding=\u672a\u8655\u7406 ConfigView.label.tcplistenport=\u76e3\u807d TCP \u50b3\u5165\u7684\u9023\u63a5\u57e0 ConfigView.label.udplistenport=\u76e3\u807d UDP \u7684\u9023\u63a5\u57e0 upnp.portchange.alert=\u4e0b\u5217\u9023\u63a5\u57e0\u8a2d\u5b9a\u88ab\u6539\u8b8a,\u4ee5\u907f\u514d UPnP \u88dd\u7f6e\u885d\u7a81: %1 [old port=%2] %3 [old port=%4] ConfigView.section.proxy.username.info=\u5982\u672a\u6307\u5b9a\u4f7f\u7528\u8005\u540d\u7a31\uff0c\u800c\u4ee3\u7406\u4f3a\u670d\u5668\u8981\u6c42\u8a8d\u8b49\uff0c\u5247\u4f7f\u7528 "" \u7576\u4f5c\u4f7f\u7528\u8005\u540d\u7a31 ConfigView.label.maxuploadswhenbusymin=\u7cfb\u7d71\u7e41\u5fd9\u6642\u6bcf\u500b torrent \u6700\u5927\u7684\u4e0a\u50b3\u901f\u5ea6 [sec] MainWindow.menu.help.debug=\u7522\u751f\u9664\u932f\u8cc7\u8a0a DownloadManager.error.badsize=\u4e0d\u6b63\u78ba\u7684\u5927\u5c0f ConfigView.section.NATPMP=NAT-PMP \u8a2d\u5b9a natpmp.info=NAT-PMP \u662f\u860b\u679c\u96fb\u8166\u63d0\u4f9b\u7684 UPnP \u66ff\u4ee3\u65b9\u6848\uff0c\u6700\u8fd1\u751f\u7522\u7684 Airport Station \u5747\u652f\u63f4\n\n\u5fc5\u9808\u5148\u555f\u7528 UPnP\uff0c\u5982\u6b64\u4e00\u4f86 NAT-PMP \u624d\u80fd\u88ab\u8fa8\u8b58\u70ba\u4e00\u7a2e\u7279\u6b8a\u7684 UPnP \u88dd\u7f6e\u4e26\u7522\u751f\u4f5c\u7528 natpmp.enable=\u555f\u52d5 (\u8acb\u6ce8\u610f Airport \u7684\u8a2d\u5b9a\u662f\u5426\u6b63\u5e38\u4f5c\u7528) ConfigView.section.tracker.host.addurls=\u78ba\u4fdd\u9019\u500b tracker \u7684 URL \u986f\u793a\u5728\u4e3b\u6a5f\u7684 torrents \u5167 ConfigView.filter=\u8f38\u5165\u904e\u6ffe\u6587\u5b57 ConfigView.section.files.move=\u79fb\u52d5\u5b8c\u6210 ConfigView.section.file.defaultdir.section=\u9810\u8a2d\u76ee\u9304\u9078\u9805 ConfigView.section.file.defaultdir.auto=\u81ea\u52d5\u4e0b\u8f09\u81f3\u9810\u8a2d\u76ee\u9304\uff08\u7121\u63d0\u793a\uff09 ConfigView.section.file.defaultdir.bestguess=\u81ea\u52d5\u9078\u64c7\u6700\u4f73\u7684\u9810\u8a2d\u5132\u5b58\u76ee\u9304 ConfigView.section.file.defaultdir.ask=\u9810\u8a2d\u76ee\u9304\uff1a ConfigView.section.file.defaultdir.lastused=\u5c07\u9810\u8a2d\u76ee\u9304\u66f4\u65b0\u81f3\u4e0a\u6b21\u9078\u64c7\u7684\u5132\u5b58\u4f4d\u7f6e ConfigView.section.torrent.decoding=\u5b57\u5143\u89e3\u78bc\u8a2d\u7f6e ConfigView.section.logging.udptransport=\u555f\u7528\u5197\u9577\u7684 UDP \u50b3\u8f38\u8ffd\u8e64 Tracker.announce.ignorePeerSeed=\u5ffd\u7565\u5925\u4f34/\u7a2e\u5b50\u6578 . %1 ConfigView.section.connection.encryption.use_crypto_port=\u4f7f\u7528 'cryptoport' tracker \u5ef6\u4f38\u529f\u80fd\u907f\u514d\u7d14\u50b3\u5165\u9023\u7dda\u8981\u6c42\u3002\u6709\u4e00\u4e9b tracker \u4e0d\u63a5\u53d7\u6b64\u9805\u529f\u80fd\uff0c\u4e26\u4e14\u6703\u56de\u61c9\u932f\u8aa4\u5831\u544a\u50cf\u662f"\u7121\u6548\u7684\u9023\u63a5\u57e0"\u6216\u662f"\u4e0d\u5408\u6cd5\u7684\u8acb\u6c42" TorrentOptionsView.param.reset.to.default=\u5c07\u9078\u9805\u9084\u539f\u6210\u9810\u8a2d\u503c TorrentOptionsView.param.reset.button=\u91cd\u7f6e natpmp.routeraddress=\u7ad9\u53f0\u4f4d\u5740 [\u7a7a\u767d: \u81ea\u52d5] ConfigView.section.style.disableAlertSliding=\u505c\u7528\u8b66\u544a\u8a0a\u606f\u7684\u81f3\u9802\u6ed1\u51fa\u52d5\u756b\u98a8\u683c ConfigView.section.transfer.autospeed.maxinc=%1 \u6bcf\u500b\u5faa\u74b0\u6700\u591a\u589e\u52a0 ConfigView.section.transfer.autospeed.maxdec=%1 \u6bcf\u500b\u5faa\u74b0\u6700\u591a\u4e0b\u964d ConfigView.section.transfer.autospeed.enabledownadj=\u555f\u7528\u4e0b\u8f09\u901f\u5ea6\u8abf\u6574 ConfigView.section.transfer.autospeed.downadjratio=\u4e0b\u8f09\uff1a\u4e0a\u50b3\u901f\u5ea6\u6bd4\u7387 (e.g. 2.0 -> \u4e0b\u8f09\u901f\u5ea6\u9650\u5236\u70ba\u4e0a\u50b3\u7684\u5169\u500d) ConfigView.section.transfer.autospeed.latencyfactor=\u7b49\u5f85\u6642\u9593\u8b8a\u52d5\u548c\u901f\u5ea6\u8b8a\u52d5\u7684\u95dc\u806f\u56e0\u7d20\uff08\u6578\u5b57\u8d8a\u5927\uff0c\u9748\u654f\u5ea6\u8d8a\u4f4e\uff09 ConfigView.section.transfer.autospeed.reset=\u91cd\u7f6e\u9032\u968e\u8a2d\u5b9a\u503c ConfigView.section.transfer.autospeed.reset.button=\u91cd\u7f6e PeerColumn.activationCount=\u5925\u4f34\u8a66\u5716\u9023\u7dda\u6b21\u6578: %1 TableColumn.header.timesincedownload.info=torrent \u958b\u59cb\u4e0b\u8f09\u5f8c\u7d93\u904e\u7684\u6642\u9593 TableColumn.header.timesincedownload=\u4e0b\u8f09\u5ef6\u9072 TableColumn.header.timesinceupload.info=\u8cc7\u6599\u4e0a\u50b3\u81f3 torrent \u5f8c\u7d93\u904e\u7684\u6642\u9593 TableColumn.header.timesinceupload=\u4e0a\u50b3\u5ef6\u9072 PeersView.incomingreqcount=\u9032\u4f86\u7684\u8981\u6c42 PeersView.incomingreqcount.info=\u8a08\u7b97\u5925\u4f34\u5c0d\u60a8\u7684\u9023\u7dda\u8981\u6c42\u6578 PeersView.outgoingreqcount=\u5c0d\u5916\u8981\u6c42 PeersView.outgoingreqcount.info=\u8a08\u7b97\u5c0d\u5916\u90e8\u5925\u4f34\u63d0\u51fa\u7684\u8981\u6c42\u6578 upnp.mapping.trackerclientudp=UDP Tracker \u7528\u6236\u7aef\u9023\u63a5\u57e0 upnp.mapping.dhtudp=\u5206\u6563\u5f0f\u8cc7\u6599\u5eab ConfigView.section.connection.nondata.udp.same=\u5206\u6563\u8cc7\u6599\u5eab\u548c UDP tracker \u4f7f\u7528\u76f8\u540c\u7684 UDP \u9023\u63a5\u57e0 ConfigView.section.connection.tcp.enable=\u555f\u52d5 TCP ConfigView.section.connection.udp.enable=\u555f\u52d5 UDP ConfigView.section.style.showiconbar=\u986f\u793a\u5de5\u5177\u5217 MainWindow.menu.view.iconbar=\u5de5\u5177\u5217 MyTorrentsView.menu.rename=\u66f4\u540d MyTorrentsView.menu.rename.displayed=\u66f4\u6539\u986f\u793a\u540d\u7a31 MyTorrentsView.menu.rename.save_path=\u66f4\u6539\u5132\u5b58\u8def\u5f91 MyTorrentsView.menu.rename.displayed.enter.title=\u66f4\u6539\u986f\u793a\u540d\u7a31 MyTorrentsView.menu.rename.displayed.enter.message=\u70ba\u9019\u500b\u4e0b\u8f09\u8f38\u5165\u65b0\u7684\u986f\u793a\u540d\u7a31\n\u5982\u679c\u6c92\u6709\u8f38\u5165\u6587\u5b57,\u5c31\u4f7f\u7528\u539f\u59cb\u540d\u7a31 UIDebugGenerator.messageask.title=\u9664\u932f\u7522\u751f\u5668 UIDebugGenerator.messageask.text=\u8acb\u8f38\u5165\u60a8\u8981\u56de\u5831\u7684\u932f\u8aa4\u6558\u8ff0 UIDebugGenerator.complete.title=\u9664\u932f\u904e\u7a0b\u5b8c\u6210 UIDebugGenerator.complete.text=\u8acb\u5c07\u6a94\u6848 '%1'.\n\n\u8acb\u6309\u4e0b"\u78ba\u5b9a"\u7528\u65b0\u8996\u7a97\u958b\u555f\u6a94\u6848 ConfigView.section.style.showProgramIcon=\u5728\u540d\u7a31\u5217\u986f\u793a\u7a0b\u5f0f\u5716\u793a ConfigView.section.style.showProgramIcon.tooltip=\u9700\u8981\u91cd\u65b0\u6253\u958b\uff0c\u6aa2\u8996\u65b9\u5f0f\u7684\u66f4\u52d5\u624d\u6703\u751f\u6548 swt.alert.cant.update=\u4f86\u81ea "%3" \u7684 SWT \u51fd\u6578\u5eab\u7121\u6cd5\u5f9e %1 \u66f4\u65b0\u5230 %2 (\u5fc5\u9808\u8f09\u5165 "%4"). \u8acb\u53c3\u7167 the wiki \u4ee5\u7372\u53d6\u8a73\u7d30\u8aaa\u660e authenticator.savepassword=\u8a18\u4f4f\u6211\u7684\u5bc6\u78bc ConfigView.section.security.clearpasswords=\u91cd\u8a2d\u5df2\u8a18\u9304\u7684\u5bc6\u78bc ConfigView.section.security.clearpasswords.button=\u91cd\u8a2d Content.alert.notuploaded.title=\u4e0a\u50b3\u6c92\u6709\u5b8c\u6210 Content.alert.notuploaded.text='%1' \u7684\u4e0a\u50b3\u5c1a\u672a\u5b8c\u6210\u3002\u5982\u679c\u60a8\u73fe\u5728 %2 \uff0c \u5176\u4ed6\u4eba\u5c07\u7121\u6cd5\u5b8c\u6210\u4e0b\u8f09\u60a8\u767c\u4f48\u7684\u5de5\u4f5c\n\n\u60a8\u78ba\u5b9a\u8981 %2? Content.alert.notuploaded.multi.title=\u4e0a\u50b3\u6c92\u6709\u5b8c\u6210 Content.alert.notuploaded.multi.text=\u60a8\u767c\u4f48\u7684\u5167\u5bb9 %1 \u6c92\u6709\u5b8c\u6574\u7684\u7a2e\u5b50\u4f86\u6e90\u3002\u5982\u679c\u60a8\u73fe\u5728 %2 \uff0c\u5176\u4ed6\u4eba\u5c07\u7121\u6cd5\u5b8c\u6574\u4e0b\u8f09\u60a8\u767c\u4f48\u7684\u5de5\u4f5c\u3002\u60a8\u78ba\u5b9a\u8981 %2?\n\n\u5167\u5bb9\u6c92\u6709\u5b8c\u6574\u7684\u7a2e\u5b50\u4f86\u6e90\uff1a\n%3 Content.alert.notuploaded.stop=\u505c\u6b62 Content.alert.notuploaded.quit=\u96e2\u958b Vuze TorrentInfoView.torrent.encoding=Torrent \u7de8\u78bc TorrentInfoView.columns=\u6aa2\u8996 '\u6211\u7684 Torrents' \u884c progress.window.title=\u64cd\u4f5c\u9032\u884c\u4e2d progress.window.msg.filemove=\u8acb\u7b49\u5f85\u6a94\u6848\u79fb\u52d5/\u66f4\u540d\u5b8c\u6210 ConfigView.label.popup.timestamp=\u5728\u8b66\u544a\u8996\u7a97\u5167\u52a0\u5165\u6642\u9593\u6a19\u8a18 ConfigView.label.popup.autohide=\u5728 x \u79d2\u5f8c\u81ea\u52d5\u96b1\u85cf\u975e\u932f\u8aa4\u8b66\u544a\u8996\u7a97 (\u8a2d\u70ba 0 \u53ef\u53d6\u6d88\u81ea\u52d5\u96b1\u85cf) ConfigView.label.please.visit.here=\u8acb\u53c3\u89c0\u6b64\u8655\u4ee5\u7372\u5f97\u8a73\u7d30\u8cc7\u8a0a ConfigView.section.ipfilter.enable.descriptionCache=\u5728 scratch \u6a94\u6848\u4e2d\u5132\u5b58 IP \u8aaa\u660e ConfigView.section.ipfilter.enable.descriptionCache.tooltip=\u505c\u7528\u6642\uff0c\u4e0d\u6703\u8a18\u9304\u8aaa\u660e\u8cc7\u6599 # Used for peers which we can't determine. PeerSocket.unknown=\u672a\u77e5 ConfigView.label.announceport=\u7f6e\u63db tracker \u6307\u5b9a\u7684\u9023\u63a5\u57e0 iconBar.queue.tooltip=\u6392\u7a0b MainWindow.menu.help.faq=\u5e38\u898b\u554f\u984c (&F) MainWindow.menu.help.donate=\u6350\u52a9 ($2,$5,...) azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_it_IT.properties0000644000175000017500000063016111304766154026126 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=File torrent... Main.parameter.usage=Uso : java org.gudy.azureus2.cl.Main [parametri] "file.torrent" "percorso di salvataggio" Main.parameter.maxUploads=Numero massimo di upload contemporanei Main.parameter.maxSpeed=Velocit\u00e0 massima in upload (byte/s) MainWindow.menu.file.open=A&pri MainWindow.menu.file.create=Crea torre&nt... MainWindow.menu.file.create.fromfile=Da un &file MainWindow.menu.file.create.fromdir=&Da una cartella MainWindow.menu.file.export=&Esporta un torrent in un XML... MainWindow.menu.file.import=&Importa un XML in un torrent... MainWindow.menu.file.closetab=Chiudi &scheda MainWindow.menu.file.closewindow=Chiudi &finestra MainWindow.menu.file.exit=E&sci MainWindow.dialog.choose.file=Scegliere il file torrent MainWindow.menu.file.folder=Car&tella... MainWindow.dialog.choose.folder=Scegliere la cartella contenente i file torrent MainWindow.menu.view=&Visualizza MainWindow.menu.view.show=Mostra MainWindow.menu.view.mytorrents=I &miei torrent MainWindow.menu.view.open_global_transfer_bar=Barra dei trasferimenti MainWindow.menu.view.configuration=&Opzioni... MainWindow.menu.view.allpeers=Tutti i peer MainWindow.menu.view.detailedlist=Lista &dettagliata MainWindow.menu.closealldetails=Chiudi &tutti i dettagli MainWindow.menu.closealldownloadbars=Chiudi tutte le &barre di download MainWindow.menu.language=&Lingua ConfigView.section.language=Lingua MainWindow.menu.window=Fi&nestra MainWindow.menu.window.minimize=&Minimizza MainWindow.menu.window.alltofront=Porta tutto in primo &piano MainWindow.menu.help=&Aiuto MainWindow.menu.help.about=Informazioni su Vuze MainWindow.about.title=Informazioni su Vuze MainWindow.about.section.developers=Sviluppatori MainWindow.about.section.translators=Traduttori MainWindow.about.section.system=Sistema MainWindow.about.internet.homepage=Sito di Vuze MainWindow.about.internet.sourceforge=Sito del progetto su Sourceforge MainWindow.about.internet.sourceforgedownloads=Scarica da Sourceforge MainWindow.about.internet.bugreports=Segnalazioni errori MainWindow.about.internet.forumdiscussion=Forum MainWindow.about.internet.wiki=FAQ della wiki di Vuze MainWindow.dialog.choose.savepath=Scegliere il percorso di salvataggio MainWindow.dialog.choose.savepath_forallfiles=Scegliere il percorso di salvataggio per TUTTI i file MainWindow.status.latestversion=Ultima versione disponibile MainWindow.status.latestversion.clickupdate=Fare clic per aggiornare MainWindow.status.unknown=sconosciuto MainWindow.status.checking=verifica in corso MyTorrentsView.mytorrents=I miei torrent TableColumn.header.name=Nome TableColumn.header.size=Dimensione TableColumn.header.done=Ricevuto (%) TableColumn.header.done.info=Percentuale completata dell'operazione attuale TableColumn.header.status=Stato TableColumn.header.status.info=Cosa sta facendo il torrent TableColumn.header.seeds=Seed TableColumn.header.seeds.info=N\u00b0 seed connessi (n\u00b0 seed totali) TableColumn.header.peers=Peer TableColumn.header.peers.info=N\u00b0 peer connessi (n\u00b0 peer totali) TableColumn.header.completed=Completato TableColumn.header.completed.info=Numero di peer che hanno terminato il download secondo quanto riportato dal tracker TableColumn.header.downspeed=Velocit\u00e0 DL TableColumn.header.upspeed=Velocit\u00e0 UL TableColumn.header.eta=Al termine TableColumn.header.tracker=Tracker TableColumn.header.tracker.info=Stato del tracker TableColumn.header.trackernextaccess=Prossimo accesso al tracker TableColumn.header.trackernextaccess.info=Quando avverr\u00e0 il prossimo acesso al tracker TableColumn.header.priority=Priorit\u00e0 TableColumn.header.priority.info=Determina quanta banda in upload \u00e8 data al torrent TableColumn.header.seeds.fullcopycalc=%2 copie complete stimate per %1 peer MyTorrentsView.menu.showdetails=Mostra i &dettagli MyTorrentsView.menu.showdownloadbar=Visualizza la barra del download MyTorrentsView.menu.open=&Apri file MyTorrentsView.menu.setpriority=Imposta la priorit\u00e0 MyTorrentsView.menu.setpriority.high=Alta MyTorrentsView.menu.setpriority.low=Bassa MyTorrentsView.menu.start=&Avvia MyTorrentsView.menu.stop=&Ferma MyTorrentsView.menu.remove=&Rimuovi MyTorrentsView.menu.changeTracker=&Aggiungi URL del tracker TrayWindow.menu.exit=Esci TrayWindow.menu.show=Mo&stra Vuze SystemTray.menu.exit=&Esci SystemTray.menu.closealldownloadbars=Chiudi tutte le b&arre di download SystemTray.menu.open_global_transfer_bar=Mostra la barra dei trasferimenti SystemTray.menu.show=Mo&stra Vuze PeersView.ip.info=IP del peer PeersView.port=Porta PeersView.port.info=Porta in uso PeersView.T.info=l (locale): hai stabilito la connessione, r (remoto): il peer ha stabilito la connessione. PeersView.T.L.tooltip=Hai stabilito la connessione PeersView.T.R.tooltip=Il peer ha stabilito la connessione PeersView.I1=I (Interessato nel peer) PeersView.I1.info=Sei interessato a quello che l'altro peer ha? PeersView.C1=C (Respinto dal peer) PeersView.C1.info=Se il peer sta bloccando il tuo download PeersView.pieces=Parti PeersView.downloadspeed=Velocit\u00e0 DL PeersView.download=Ricevuti PeersView.I2=I (Peer interessato) PeersView.I2.info=Il peer \u00e8 interessato a quello che hai? PeersView.C2=C (Peer respinto) PeersView.C2.info=Se stai bloccando il download del peer PeersView.uploadspeed=Velocit\u00e0 UP PeersView.uploadspeed.info=Velocit\u00e0 di upload verso il peer PeersView.upload=Inviati PeersView.upload.info=Il tuo upload totale verso il peer. PeersView.statup=Stima UP PeersView.statup.info=Un valore stimato della velocit\u00e0 di upload dei peer PeersView.S=I PeersView.S.info=Ignorato: un peer pu\u00f2 essere ignorato manualmente, o automaticamente (perch\u00e9 non inviava dati ad una velocit\u00e0 sufficiente). PeersView.downloadspeedoverall=Velocit\u00e0 di download generale PeersView.optunchoke=Unchoke ottimistico PeersView.client.info=Tipo di client BitTorrent usato dal peer PeersView.menu.snubbed=I&gnorato PeersView.title.short=Peer PeersView.title.full=Peer AllPeersView.title.full=Tutti i peer ConfigView.section.files=File ConfigView.label.usefastresume=Usa il \u00abripristino veloce\u00bb ConfigView.label.incrementalfile=Abilita la creazione incrementale del file [Richiesto per FAT32 sotto Linux] ConfigView.label.defaultsavepath=Salva nella cartella predefinita ConfigView.button.browse=&Sfoglia... ConfigView.dialog.choosedefaultsavepath=Scegliere il percorso di salvataggio predefinito ConfigView.section.server=Connessione ConfigView.section.global=Globale ConfigView.label.disconnetseed=Disconnetti i seed quando si \u00e8 in seed ConfigView.label.switchpriority=Imposta automaticamente a bassa priorit\u00e0 quando in seed ConfigView.label.maxdownloads=Numero massimo di download simultanei [0: illimitato]\n - Non pu\u00f2 essere maggiore del numero massimo di torrent attivi ConfigView.label.maxdownloads.tooltip=Si potr\u00e0 sempre attivare un numero di download pari a quello impostato, con una sola eccezione.\nUn torrent che ha la Prima priorit\u00e0 potrebbe ricevere un ulteriore slot di download se assolutamente necessario. ConfigView.label.maxactivetorrents=Numero massimo di torrent attivi [0: illimitato]\n - I torrent nuovi non possono partire se stai scaricando/inviando un numero di torrent pari a ConfigView.label.priorityExtensions=Dai automaticamente priorit\u00e0 ai file con estensione \n (es: .txt;.nfo;.jpg) ConfigView.section.transfer=Trasferimento ConfigView.label.maxuploads=Numero massimo di invii per torrent ConfigView.label.maxuploadspeed=Velocit\u00e0 massima di upload (globale) (KB/s) [0: illimitato] ConfigView.label.saveresumeinterval=Salva i dati del \u00abripristino veloce\u00bb ogni ConfigView.unlimited=Illimitato ConfigView.section.display=Visualizza ConfigView.label.opendetails=Apri automaticamente la scheda Dettagli per ConfigView.label.openbar=Apri automaticamente la barra di download per ConfigView.label.use_old_speed_menus=Usa menu vecchio stile [richiede riavvio] ConfigView.label.closetotray=Il pulsante \u00abChiudi\u00bb minimizza nel vassoio di sistema ConfigView.label.minimizetotray=Il pulsante \u00abRiduci a icona\u00bb minimizza nel vassoio di sistema ConfigView.section.general=Generale ConfigView.section.start=Avvio ConfigView.label.showsplash=Visualizza la schermata iniziale ConfigView.label.autoupdate=Apri la finestra di aggiornamento quando \u00e8 disponibile una nuova versione ConfigView.label.openconsole=Apri la console all'avvio ConfigView.label.openconfig=Apri la configurazione all'avvio ConfigView.label.startminimized=Avvia minimizzato ConfigView.label.ircwiki=Vedere http://www.azureuswiki.com/index.php/Rules_for_IRC (in inglese) ConfigView.label.ircchannel=Canale ConfigView.label.irclogin=Nome utente ConfigView.group.irctitle=Impostazioni IRC ConfigView.boolean.ircsendinfo=Autorizza l'invio (anonimo) delle tue impostazioni\n agli operatori del canale, per aiutarti meglio ConfigView.boolean.irclog=Abilita la registrazione dell'attivit\u00e0 del canale (in IRC_log.htm) ConfigView.section.security=Sicurezza ConfigView.label.password=Proteggi Vuze usando una password\nVerr\u00e0 chiesta per ripristinarlo (dopo che \u00e8 stato ridotto ad icona) e quando viene avviato. ConfigView.label.passwordconfirm=Password (conferma) ConfigView.label.passwordmatch=Password attiva : ConfigView.label.passwordmatchno=No / Le password non corrispondono ConfigView.label.passwordmatchyes=S\u00ec ConfigView.button.save=Salva ConfigView.title.short=Configurazione ConfigView.title.full=Configurazione ConfigView.title.full._mac=Preferenze FileItem.write=Scrittura FileItem.read=Lettura FileItem.normal=Normale FileItem.high=Alta FileItem.donotdownload=Non scaricare FileItem.delete=Elimina FilesView.name=Nome FilesView.name.fastRename=Rinomina veloce FilesView.size=Dimensione FilesView.done=Completato FilesView.firstpiece=N\u00b0 della prima parte FilesView.numberofpieces=N\u00b0 di parti FilesView.pieces=Parti FilesView.mode=Modalit\u00e0 FilesView.priority=Priorit\u00e0 FilesView.menu.open=&Apri FilesView.menu.setpriority=&Imposta priorit\u00e0 FilesView.menu.setpriority.high=&Alta FilesView.menu.setpriority.normal=&Normale FilesView.menu.setpriority.skipped=&Non scaricare FilesView.title.short=File FilesView.title.full=File GeneralView.section.downloaded=Ricevuto GeneralView.label.status.file=Stato del file GeneralView.label.status.pieces=Stato delle parti GeneralView.section.availability=Disponibilit\u00e0 GeneralView.label.status.pieces_available=Disponibilit\u00e0 delle parti GeneralView.section.transfer=Trasferimento GeneralView.section.info=Informazioni GeneralView.title.short=Generale GeneralView.title.full=Generale GeneralView.label.timeelapsed=Tempo trascorso : GeneralView.label.remaining=Al termine : GeneralView.label.downloaded=Ricevuti : GeneralView.label.downloadspeed=Velocit\u00e0 di download : GeneralView.label.maxuploads=Slot di upload: GeneralView.label.maxuploads.tooltip=Numero massimo dei peer non ignorati in un certo istante. GeneralView.label.uploaded=Inviati : GeneralView.label.uploadspeed=Velocit\u00e0 di upload : GeneralView.label.seeds=Seed: GeneralView.label.peers=Peer: GeneralView.label.completed=Completato : GeneralView.label.totalspeed=Velocit\u00e0 del torrent : GeneralView.label.totalspeed.tooltip=Velocit\u00e0 totale (e media) di tutti i client a cui sei connesso. GeneralView.label.averagespeed=velocit\u00e0 media GeneralView.label.filename=Nome file : GeneralView.label.totalsize=Dimensione totale : GeneralView.label.savein=Salva in : GeneralView.label.hash=Codice hash : GeneralView.label.numberofpieces=N\u00b0 totale parti : GeneralView.label.size=Dimensione : GeneralView.label.tracker=Stato del tracker : GeneralView.label.updatein=Aggiornamento fra : GeneralView.label.trackerurl=URL del tracker: GeneralView.label.trackerurlupdate=Aggiorna adesso GeneralView.label.comment=Commenti: GeneralView.label.user_comment=Commento: GeneralView.label.status=Stato: ManagerItem.waiting=In attesa ManagerItem.allocating=Allocazione in corso ManagerItem.checking=Verifica in corso ManagerItem.ready=Pronto: in attesa che altri torrent vengano messi in coda ManagerItem.downloading=Sto scaricando ManagerItem.seeding=Seed in corso ManagerItem.stopped=Fermato ManagerItem.error=Errore ManagerItem.high=alta ManagerItem.low=bassa MinimizedWindow.name=Nome: MinimizedWindow.all_transfers=Trasferimenti Vuze PiecesView.#=Parte n\u00b0 PiecesView.size=Dimensione parte PiecesView.numberofblocks=N\u00b0 blocchi PiecesView.blocks=Blocchi PiecesView.completed=Blocchi ricevuti PiecesView.availability=Disponibilit\u00e0 PiecesView.reservedby=Riservato PiecesView.writers=Blocca contribuenti PiecesView.title.short=Parti PiecesView.title.full=Parti SystemTray.tooltip.seeding=%1 in seed, SystemTray.tooltip.downloading=%1 in download, DownloadManager.error.filenotfound=File non trovato DownloadManager.error.fileempty=Il file torrent \u00e8 vuoto DownloadManager.error.filetoobig=Il file torrent \u00e8 troppo grande DownloadManager.error.filewithouttorrentinfo=Nessuna informazione su dei torrent trovata nel file DownloadManager.error.unsupportedencoding=Codifica non supportata DownloadManager.error.ioerror=Errore di input/output DownloadManager.error.sha1=Errore: non esiste questo algoritmo (SHA1) PeerManager.status.offline=Errore di connessione PeerManager.status.ok=Ok PeerManager.status.checking=Verifica PeerManager.status.finished=Finito PeerManager.status.finishedin=Finito in MainWindow.upgrade.assistant=Assistente all'aggiornamento MainWindow.upgrade.newerversion=C'\u00e8 una nuova versione di Vuze disponibile da scaricare MainWindow.upgrade.explanation=Questo assistente scaricher\u00e0 la nuova versione nella cartella di Vuze e riavvier\u00e0 il programma MainWindow.upgrade.explanation.manual=Si pu\u00f2 fare un aggiornamento manuale chiudendo Vuze, scaricando la nuova versione e riaprendolo MainWindow.upgrade.step1=Passo 1: scaricare la nuova versione MainWindow.upgrade.step2=Passo 2: chiudere questa versione e avviare con la nuova versione di Vuze MainWindow.upgrade.hint1=Consiglio:\tpremere Fine per rendere tutto automatico MainWindow.upgrade.hint2=Consiglio:\tse si vuole chiudere Vuze pi\u00f9 tardi, premere Annulla e\n\trinominare il file Azureus2-new.jar come Azureus2.jar dopo aver chiuso il programma. MainWindow.upgrade.error.downloading.hint=Errore:\tImpossibile scaricare la nuova versione, aggiornare Vuze manualmente MainWindow.upgrade.section.info=Nuova versione disponibile MainWindow.upgrade.section.manual=Aggiornamento manuale MainWindow.upgrade.section.automatic=Aggiornamento automatico MainWindow.upgrade.tooltip.progressbar=L'avanzamento del download \u00e8 mostrato qui Button.next=Successivo Button.finish=Fine Button.cancel=&Annulla LocaleUtil.title=Scelta della codifica LocaleUtil.section.chooseencoding=Scegli codifica per i nomi dei file LocaleUtil.label.chooseencoding=Selezionare la codifica migliore LocaleUtil.label.hint.doubleclick=Consiglio: facendo doppio clic su una riga si seleziona la codifica e si chiude la finestra LocaleUtil.label.checkbox.rememberdecision=Ricorda la decisione per i nomi di file che restano LocaleUtil.column.encoding=Codifica IrcClient.copyright=Usa le API per l'IRC Java PircBot - http://www.jibble.org/pircbot.php IrcClient.connecting=Connessione in corso a IrcClient.connected=Connesso a IrcClient.joining=Sto entrando in IrcClient.channel=Canale IrcClient.joined=\u00e8 entrato IrcClient.error=Errore IrcClient.hasjoined=\u00e8 entrato in IrcClient.haskicked=ha cacciato (kick) IrcClient.hasleft=ha abbondonato IrcClient.nowknown=\u00e8 ora IrcClient.topicforchannel=Argomento del canale IrcClient.disconnected=Disconnesso da IrcClient.noNick=Nessun nome utente specificato. Per favore inserirlo nella \u00abConfigurazione\u00bb. IrcView.actionnotsupported=Questa azione non \u00e8 supportata IrcView.clientsconnected=utenti IrcView.privateto=A IrcView.privatefrom=Da IrcView.noticefrom=Notizia : IrcView.errormsg=Sintassi sbagliata su /msg : /msg utente messaggio IrcView.help=Comandi validi sono :\n . /help : visualizza questo messaggio\n . /nick | /name : cambia il tuo nome \n . /me azione : invia un'azione \n . /msg nome messaggio : invia un messaggio a \u00abnome\u00bb\n . /r messaggio : risponde all'ultimo messaggio privato\n . /join #channelB (non fare clic qui, \u00e8 solo un esempio): modifica il canale attuale a \u00abcanaleB\u00bb PasswordWindow.title=Vuze \u00e8 bloccato PasswordWindow.passwordprotected=Vuze \u00e8 protetto da password.\nPer visualizzare la finestra di Vuze, inserire la password : TrackerChangerWindow.title=Aggiungi tracker TrackerChangerWindow.newtracker=Inserire il nuovo URL per il tracker PeersView.discarded=Scartato PeersView.discarded.info=A volte si ricevono dati non necessari, quindi si possono scartare. discarded=scartato MyTorrentsView.#=N\u00b0 MyTorrentsView.menu.move=S&posta MyTorrentsView.menu.moveUp=S&u MyTorrentsView.menu.moveDown=&Gi\u00f9 GeneralView.label.hashfails=Fallimenti hash : GeneralView.label.shareRatio=Rapporto di condivisione: ConfigView.section.downloadManagement=Gestione dei download ConfigView.label.startRatioPeers=Avvia il seed quando c'\u00e8 meno di 1 seed ogni ConfigView.text.neverStop=Non fermarti mai ConfigView.text.neverStart=Non iniziare mai ConfigView.text.peers=Peer ConfigView.label.checkOncompletion=Ricontrolla le parti quando il download \u00e8 terminato wizard.title=Creazione del torrent wizard.previous=< Indietro wizard.next=Avanti > wizard.finish=Fine wizard.mode=Tracker / Modalit\u00e0 wizard.invalidurl=Questo URL non \u00e8 valido wizard.singlefile=File singolo wizard.singlefile.help=Crea un torrent da un file singolo wizard.directory=Cartella wizard.directory.help=Crea un torrent da una cartella wizard.choosefile=Scegli il file wizard.file=File: wizard.browse=Sfoglia... wizard.choosedirectory=Scegli una cartella wizard.invalidfile=File non valido! wizard.invaliddirectory=Cartella non valida! wizard.torrentFile=File .torrent wizard.choosetorrent=Scegliere il nome del file torrent da creare wizard.information=Informazioni wizard.notimplemented=Non ancora implementato wizard.progresstitle=Sto creando il file torrent wizard.savingfile=Salvataggio file in corso... wizard.filesaved=File salvato. wizard.close=Chiudi Torrent.create.progress.piecelength=Dimensione della parte: Torrent.create.progress.piececount=Numero delle parti: Torrent.create.progress.totalfilesize=Dimensione totale dei file: Torrent.create.progress.totalfilecount=Numero totale di file: Torrent.create.progress.parsingfiles=Elaborazione file Torrent.create.progress.hashing=Hash dei file MainWindow.upgrade.downloadingfrom=Sto scaricando da : MainWindow.menu.view.ipFilter=Filtri &IP ConfigView.section.ipfilter=Filtri IP ConfigView.section.ipfilter.description=Descrizione ConfigView.section.ipfilter.start=IP iniziale ConfigView.section.ipfilter.end=IP finale ConfigView.section.ipfilter.add=Aggiungi ConfigView.section.ipfilter.remove=Rimuovi ConfigView.section.ipfilter.edit=Modifica ConfigView.section.ipfilter.save=Salva ConfigView.section.ipfilter.editFilter=Modifica filtro ConfigView.section.ipfilter.enable=Abilita PeersView.menu.close=&Chiudi seedmore.title=Il torrent non \u00e8 stato inviato abbastanza seedmore.shareratio=Il tuo rapporto di condivisione per questo torrent \u00e8 seedmore.uploadmore=Avere un rapporto di condivisione sotto il 100% non \u00e8 una buona cosa per la rete di BitTorrent.\nSi dovrebbe rimanere in seed ancora per un po'.\n\nSi \u00e8 sicuri di procedere? ConfigView.label.showpopuponclose=Mostra un popup di conferma quando interrompi l'invio di un file con rapporto di condivisione inferiore ad 1 ConfigView.label.startNumSeeds=\nAvvia il seed se c'\u00e8 meno di\n - Ha la precedenza sulle altre regole ConfigView.label.seeds=seed ConfigView.section.seeding=Seed MyTorrentsView.menu.removeand=Rimuo&vi e MyTorrentsView.menu.removeand.deletetorrent=Elimina file &torrent MyTorrentsView.menu.removeand.deletedata=Elimina file par&ziale MyTorrentsView.menu.removeand.deleteboth=Elimina entram&bi deletedata.title=Eliminazione di contenuti multimediali deletedata.message1=Si vuole eliminare definitivamente \u00ab%1\u00bb? deletedata.noprompt=Non chiedere ancora MainWindow.menu.file.configure=Assistente di configura&zione... configureWizard.title=Assistente di configurazione configureWizard.welcome.title=Benvenuto nell'assistente di configurazione di Vuze configureWizard.welcome.message=Questo assistente aiuter\u00e0 a configurare le opzioni pi\u00f9 comuni di Vuze. Si pu\u00f2 modificare in dettaglio la configurazione andando in \u00abStrumenti -> Opzioni\u00bb. configureWizard.transfer.title=Impostazioni di trasferimento e connessione configureWizard.transfer.hint=Consiglio: impostare una velocit\u00e0 leggermente inferiore a quella reale. configureWizard.transfer.message=Scegliere un tipo di connessione nella lista qui sotto. Se non si abilita una velocit\u00e0 di upload sufficiente, la velocit\u00e0 di download sar\u00e0 limitata. La velocit\u00e0 di upload \u00e8 riferita AL torrent che si sta scaricando, quindi se si scaricano troppi torrent contemporaneamente la velocit\u00e0 di download sar\u00e0 bassa. Si consiglia di usare ALMENO 5KB/s per torrent. Pi\u00f9 velocemente si invia, pi\u00f9 velocemente si scarica (in base alla velocit\u00e0 del torrent). configureWizard.transfer.connection=Linea configureWizard.transfer.connection.0=Personalizzato configureWizard.transfer.connection.2=adsl/cavo xxx/128 kbps configureWizard.transfer.connection.3=adsl/cavo xxx/256 kbps configureWizard.transfer.connection.4=adsl/cavo xxx/384 kbps configureWizard.transfer.connection.5=adsl/cavo xxx/512 kbps configureWizard.transfer.connection.6=adsl/cavo xxx/768 kbps configureWizard.transfer.connection.7=adsl/cavo xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Velocit\u00e0 massima di upload (KB/s) configureWizard.transfer.maxActiveTorrents=Numero massimo di torrent attivi configureWizard.transfer.maxDownloads=Numero massimo di download simultanei configureWizard.transfer.maxUploadsPerTorrent=Numero massimo di upload per torrent configureWizard.nat.title=NAT / Porte del server configureWizard.nat.message=Per avere le migliori prestazioni, \u00e8 vivamente consigliato di essere completamente accessibili da Internet. Questo strumento permette di testare e/o cambiare le porte usate per le connessioni in entrata.\n\nNOTA: Vengono testate solo le connessioni TCP. Il database distribuito ha bisogno anche di connessioni UDP in entrata, ma visualizzer\u00e0 una notifica se scopre di essere bloccato da un firewall.\n\nNOTA: La porta TCP 6880 \u00e8 riservata all'uso interno, quindi non pu\u00f2 essere usata. configureWizard.nat.test=Prova configureWizard.nat.testing=Test delle porte configureWizard.nat.ok=Ok configureWizard.nat.ko=Errore NAT configureWizard.nat.unable=Impossibile effettuare il test: \u00e8 stata specificata una porta non valida, o il servizio di test non ha funzionato correttamente.\nQuesta porta potrebbe essere in uso da un'altra applicazione. configureWizard.file.title=Torrent / File configureWizard.file.message1=Vuze salver\u00e0 i torrent aperti in una cartella specifica, sceglierla qui: configureWizard.file.path=Percorso configureWizard.file.browse=Sfoglia configureWizard.file.message2=Vuze \u00e8 in grado di ricominciare a scaricare istantaneamente, aggiungendo alcune informazioni di ripristino ai torrent. Usando questa funzione, si potranno anche recuperare le parti parzialmente scaricate. configureWizard.file.fastResume=Abilita il \u00abripristino veloce\u00bb configureWizard.file.invalidPath=Cartella non valida configureWizard.finish.title=Completato configureWizard.finish.message=Adesso Vuze \u00e8 configurato, divertiti! wizard.close.confirmation=Conferma wizard.close.message=Aprire questo assistente al prossimo avvio di Vuze? exportTorrentWizard.title=Esporta un torrent XML exportTorrentWizard.torrentfile.title=Scelta del torrent exportTorrentWizard.torrentfile.message=Scegliere il file torrent da esportare exportTorrentWizard.torrentfile.path=Percorso exportTorrentWizard.torrentfile.browse=Sfoglia exportTorrentWizard.torrentfile.invalidPath=File torrent non valido exportTorrentWizard.exportfile.title=Selezione del file su cui esportare exportTorrentWizard.exportfile.message=Indicare il file XML in cui esportare exportTorrentWizard.exportfile.path=Percorso exportTorrentWizard.exportfile.browse=Sfoglia exportTorrentWizard.exportfile.invalidPath=File di esportazione non valido exportTorrentWizard.finish.title=Completato exportTorrentWizard.finish.message=Esportazione completata con successo exportTorrentWizard.process.inputfilebad.title=File torrent non valido exportTorrentWizard.process.inputfilebad.message=Si \u00e8 verificato un errore nell'accedere al file di input: exportTorrentWizard.process.outputfileexists.title=File esistente exportTorrentWizard.process.outputfileexists.message=Il file esiste gi\u00e0 - sovrascriverlo? exportTorrentWizard.process.torrentfail.title=Lettura del torrent non riuscita exportTorrentWizard.process.exportfail.title=Esportazione torrent non riuscita exportTorrentWizard.process.unknownfail.title=Errore inatteso importTorrentWizard.title=Importa un torrent XML importTorrentWizard.torrentfile.title=Selezione del file torrent importTorrentWizard.torrentfile.message=Inserire il file torrent in cui importare importTorrentWizard.torrentfile.path=Percorso importTorrentWizard.torrentfile.browse=Sfoglia importTorrentWizard.torrentfile.invalidPath=File torrent non valido importTorrentWizard.importfile.title=Selezione del file da importare importTorrentWizard.importfile.message=Selezionare il file XML da importare importTorrentWizard.importfile.path=Percorso importTorrentWizard.importfile.browse=Sfoglia importTorrentWizard.importfile.invalidPath=File importato non valido importTorrentWizard.finish.title=Completato importTorrentWizard.finish.message=Importazione completata con successo importTorrentWizard.process.inputfilebad.title=File importato non valido importTorrentWizard.process.inputfilebad.message=\u00c8 avvenuto un errore nell'accesso al file da importare: importTorrentWizard.process.outputfileexists.title=File esistente importTorrentWizard.process.outputfileexists.message=Il file esiste gi\u00e0 - sovrascriverlo? importTorrentWizard.process.torrentfail.title=Scrittura del torrent non riuscita importTorrentWizard.process.importfail.title=Importazione torrent non riuscita importTorrentWizard.process.unknownfail.title=Errore inatteso ConfigView.label.bindip=Associa all'indirizzo IP o all'interfaccia locale ConfigView.label.xfs.allocation=Alloca i nuovi file usando un metodo specifico per il filesystem XFS ConfigView.label.xfs.allocation.tooltip=Assicurarsi che /usr/sbin/xfs_io sia installato correttamente sul sistema. In molte distribuzioni Linux \u00e8 incluso nel pacchetto \u00abxfsprogs\u00bb. xfs.allocation.xfs_io.not.found=L'allocazione XFS del file non \u00e8 riuscita perch\u00e9 /usr/sbin/xfs_io non pu\u00f2 essere eseguito. Assicurarsi che sia installato correttamente sul sistema. L'errore originale \u00e8: \u00ab%1\u00bb. ConfigView.label.zeronewfiles=Alla creazione del file alloca tutto lo spazio e riempilo con zeri ConfigView.label.zeronewfiles.tooltip=Minimizza la frammentazione ConfigView.section.stats=Statistiche ConfigView.section.stats.enable=Abilita ConfigView.section.stats.defaultsavepath=Cartella di salvataggio statistiche ConfigView.section.stats.choosedefaultsavepath=Scegliere la cartella in cui salvare le statistiche ConfigView.section.stats.savefreq=Frequenza di salvataggio delle statistiche ConfigView.section.stats.hours=ore ConfigView.section.stats.savefile=Nome del file delle statistiche ConfigView.section.stats.graph_update_dividers=Traccia una linea verticale ogni 60 aggiornamenti MyTorrentsView.menu.export=Torrent &XML... MyTorrentsView.menu.host=&Ospita... ManagerItem.finishing=Finisco ConfigView.dialog.choosedefaulttorrentpath=Scegliere la cartella predefinita per i torrent ConfigView.dialog.choosemovepath=Scegliere la cartella in cui spostare ConfigView.label.movecompleted=Sposta i file completati (dopo lo scaricamento) ConfigView.label.moveremoved=Sposta i file completati (in caso di rimozione) ConfigView.label.savetorrents=Salva i file .torrent MainWindow.menu.view.mytracker=Il mio &tracker MyTrackerView.title.full=Il mio tracker MyTrackerView.name=Nome MyTrackerView.status=Stato MyTrackerView.status.started=Avviato MyTrackerView.status.stopped=Fermato MyTrackerView.peers=Peer MyTrackerView.seeds=Seed MyTrackerView.announces=Annunci MyTrackerView.uploaded=Inviati MyTrackerView.downloaded=Scaricato MyTrackerView.left=Rimanenti ConfigView.section.style=Interfaccia ConfigView.label.set_ui_transfer_speeds=Modifica le velocit\u00e0 di trasferimento selezionabili ConfigView.label.set_ui_transfer_speeds.description=Si pu\u00f2 scegliere di definire manualmente le velocit\u00e0 predefinite di download e upload disponibili nella barra di stato del vassoio di sistema.\nI valori devono essere separati da virgole. ConfigView.label.set_ui_transfer_speeds.description.download=Velocit\u00e0 di download disponibili (KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Velocit\u00e0 di upload disponibili (KB/s) ConfigView.section.style.useCustomTabs=Usa schede chiudibili (necessario riavvio) MainWindow.menu.view.plugins=&Plugin fileDownloadWindow.saveTorrentIn=Salva il file torrent in fileDownloadWindow.title=Vuze - Scaricatore di torrent fileDownloadWindow.downloading=Download in corso da : fileDownloadWindow.status=Stato : fileDownloadWindow.state_initializing=Inizializzazione in corso fileDownloadWindow.state_downloading=Download in corso fileDownloadWindow.state_error=Errore : MainWindow.menu.file.open.url=Po&sizione... MainWindow.menu.file.open.url.keybinding=Meta+U openUrl.title=Apri URL MyTorrentsView.menu.host.error.title=Impossibile ospitare il torrent MyTorrentsView.menu.host.error.message=Si \u00e8 verificato il seguente errore nel tentativo di ospitare il torrent: ConfigView.section.tracker.pollinterval=Intervallo di poll client tracker (sec) ConfigView.section.tracker.publishenable=Pubblica i dettagli del torrent in \u00ab\u00bb ConfigView.section.tracker.ip=Indirizzo IP esterno del tracker ConfigView.section.style.enableXPStyle=Abilita lo stile XP (riavvio necessario) IPChecker.external.service.dyndns.description=Servizi di rete di DNS dinamico, LLC ConfigView.section.tracker.checkip=Rilevamento automatico dell'IP esterno... ipCheckerWizard.title=Assistente di controllo dell'IP ipCheckerWizard.service=Servizio ipCheckerWizard.chooseService=Si prega di scegliere un servizio di controllo dell'IP tra quelli elencati. ipCheckerWizard.explanations=Si pu\u00f2 usare questo assistente per scoprire qual'\u00e8 il proprio indirizzo IP esterno. Se l'indirizzo IP \u00e8 dinamico, suggeriamo di registrarsi a un servizio di DNS dinamico. Tali servizi sono elencati qui sotto. Usare il collegamento fornito per registrarsi (dove permesso). Quindi riempire i campi con l'indirizzo IP e il proprio nome host dinamico (per esempio ilmionomehost.dyndns.org). Si ha bisogno di un programma per aggiornare automaticamente il servizio di DNS dinamico con l'indirizzo IP. In questo modo si possono ospitare i torrent anche se l'IP cambia. ipCheckerWizard.service.description=Descrizione : ipCheckerWizard.service.url=Collegamento: ipCheckerWizard.progresstitle=Sto verificando l'IP ipCheckerWizard.checkComplete=IP Completo : ipCheckerWizard.checkFailed=Non riuscito, motivo : wizard.tracker.local=Usa il tracker interno a Vuze wizard.tracker.external=Usa un tracker esterno wizard.tracker.howToLocal=\tAndare in \u00abConfigurazione -> Tracker\u00bb per abilitarlo wizard.announceUrl=URL dell'annuncio: IPChecker.external.service.discoveryvip.description=Discoveryvip - Controllo indirizzo IP IPChecker.external.httpinvalidresponse=Risposta HTTP non valida IPChecker.external.loadingwebpage=Caricamento della pagina web in corso IPChecker.external.analysingresponse=Sto analizzando la risposta IPChecker.external.addressextracted=Indirizzo IP estratto IPChecker.external.httploadfail=Impossibile caricare la pagina IPChecker.external.timeout=Tempo scaduto IPChecker.external.ipnotfound=Indirizzo IP non trovato ConfigView.section.tracker.pollintervalmin=Minimo ConfigView.section.tracker.pollintervalmax=Massimo ConfigView.section.tracker.pollintervalincby=Incrementa di ConfigView.section.tracker.pollintervalincper=Ogni N client splash.loadingImages=Caricamento delle immagini splash.initializeGui=Inizializzazione della finestra principale splash.openViews=Apertura finestre splash.plugin=Caricamento del plugin: configureWizard.nat.tooManyPorts=Troppe porte da testare (9 max) ConfigView.section.color=Schema di colori MyTorrentsView.menu.publish=Pubb&lica... MyTrackerView.status.published=Pubblicato MyTrackerView.completed=Completato MainWindow.menu.file.open.torrentnodefault=File torrent... (non salvare nella cartella predefinita) wizard.comment=Commento ConfigView.label.movetorrent=Sposta file .torrent ConfigView.label.movepartialdownloads=Sposta anche quando alcuni file sono contrassegnati con \u00abNon scaricare\u00bb ConfigView.label.subdir_is_in_default=Nel decidere se un download esiste gi\u00e0 nella cartella predefinita, considera anche le sottocartelle ConfigView.section.file.decoder.label=Codifica predefinita dei torrent \n(quando richiesto) ConfigView.section.file.decoder.nodecoder=Nessuna IPChecker.external.service.no-ip.description=Fornisce servizi di DNS statico e dinamico\n(il servizio per il controllo dell'indirizzo non \u00e8 disponibile gratuitamente) ConfigView.section.tracker.publicenable=Abilita torrent esterni ConfigView.label.playdownloadspeech=Parla al completamento di un download ConfigView.label.playdownloadspeech.info=Il servizio di sintesi vocale funziona meglio con la lingua inglese. # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Mostra il numero di copie disponibili per ogni parte.\nSe il numero sulla destra \u00e8 minore di 1, non \u00e8 disponibile una copia intera del file (e si potrebbero avere problemi nel completare il download). GeneralView.label.trackerurl.tooltip=Fare clic per copiare l'URL dell'annuncio negli appunti GeneralView.label.trackerurlopen.tooltip=Fare clic per aprire la pagina principale del tracker # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Aggiorna GUI ogni ConfigView.section.style.inactiveUpdate=Aggiorna la finestra principale (se non \u00e8 attiva) ogni N aggiornamenti della GUI ConfigView.section.style.graphicsUpdate=Aggiorna barre grafiche ogni N aggiornamenti della GUI ConfigView.section.style.reOrderDelay=Riordina le tabelle ogni N aggiornamenti della GUI [0: mai] ConfigView.section.style.reOrderDelay.never=Mai ConfigView.section.logging=Log ConfigView.section.logging.enable=Abilita il file di registro ConfigView.section.logging.logdir=Cartella del file di registro ConfigView.section.logging.choosedefaultsavepath=Selezionare la cartella per il salvataggio GeneralView.label.updatein.querying=Interrogazione... configureWizard.nat.sharePort=Usa una singola porta di ascolto per tutti i torrent ConfigView.section.logging.maxsize=Dimensione massima del file di registro ConfigView.section.tracker.passwordenableweb=Abilita password sui tracker web ConfigView.section.tracker.passwordenabletorrent=Abilita password per i torrent ConfigView.section.tracker.username=Nome utente columnChooser.title=Scelta delle colonne da visualizzare columnChooser.move=Trascinare le righe per riordinarle columnChooser.apply=Applica columnChooser.columnname=Nome colonna columnChooser.columndescription=Descrizione TableColumn.header.shareRatio=Rapporto condiv. MyTorrentsView.menu.editTableColumns=Impostazioni &colonna wizard.operationfailed=Operazione non riuscita authenticator.title=Autenticazione richiesta authenticator.user=Nome utente ConfigView.label.allowSendVersion=Consenti a Vuze di inviare, in modo anonimo, il numero di versione e un identificativo casuale quando controlla se \u00e8 disponibile una nuova versione. ConfigView.label.version.info.link=Fare clic qui per maggiori dettagli sulle informazioni inviate al server di aggiornamento wizard.hint.mode=Suggerimento:\tSi pu\u00f2 trascinare e rilasciare un file o una cartella su questo assitente\n\tper sceglierli wizard.hint.file=Suggerimento:\tSi pu\u00f2 scegliere un file singolo con il trascinamento wizard.hint.directory=Suggerimento:\tSi pu\u00f2 scegliere una singola cartella con il trascinamento MainWindow.menu.help.checkupdate=&Controlla aggiornamenti... TableColumn.header.down=Ricevuto (Dim) TableColumn.header.up=Dati inviati ConfigView.section.tracker.passwordenabletorrent.info=Richiede un client BitTorrent adatto (ad esempio Vuze). ConfigView.section.style.confirmationOnExit=Mostra la finestra di conferma quando esci MainWindow.dialog.exitconfirmation.title=Conferma dell'uscita da Vuze MainWindow.dialog.exitconfirmation.text=Uscire da Vuze? SystemTray.menu.stopalltransfers=&Ferma tutti i trasferimenti TrayWindow.menu.stopalldownloads=&Ferma tutti i download ConfigView.section.tracker.sslport.info=Guarda le FAQ per maggiori informazioni. wizard.tracker.ssl=Usa SSL ConfigView.label.playdownloadfinished=Riproduci un suono al completamento del download ConfigView.label.popupdownloadfinished=Mostra un avviso quando viene completato un download ConfigView.label.popupfilefinished=Mostra un avviso quando viene completato un file TableColumn.header.pieces=Parti TableColumn.header.pieces.info=Barra che rappresenta le parti scaricate TableColumn.header.completion=Completamento TableColumn.header.completion.info=Rappresentazione grafica della percentuale scaricata ConfigView.section.style.showdownloadbasket=Mostra il Cesto dei Download (per scaricare un file .torrent, trascinarlo e rilasciarlo sull'icona) ConfigView.section.style.alwaysShowTorrentFiles=Mostra sempre i file torrent in Dettagli/File wizard.multitracker=Aggiungi informazioni multi-tracker nel torrent wizard.multitracker.title=Multi-tracker wizard.multitracker.configuration=Configurazione del multi-tracker wizard.multitracker.new=Nuovo... wizard.multitracker.edit=Modifica... wizard.multitracker.delete=Elimina wizard.multitracker.group=Gruppo di tracker wizard.multitracker.edit.title=Editor per il multi-tracker wizard.multitracker.edit.name=Nome wizard.multitracker.edit.save=Salva wizard.multitracker.edit.newgroup=Nuovo gruppo wizard.multitracker.edit.deletegroup=Elimina wizard.multitracker.edit.newtracker=Nuovo tracker wizard.multitracker.edit.deletetracker=Elimina wizard.multitracker.edit.edit=Modifica wizard.addingmt=Aggiungi informazioni multi-tracker wizard.multitracker.noannounce=L'URL dell'annuncio non \u00e8 presente nella lista dei tracker MyTorrentsView.menu.recheck=Forza &ricontrollo iconBar.showDownloadBar.tooltip=Mostra la barra di download iconBar.start.tooltip=Avvia i torrent selezionati iconBar.stop.tooltip=Ferma i torrent selezionati iconBar.remove.tooltip=Rimuovi i torrent selezionati iconBar.openNoDefault.tooltip=Apri un file .torrent (non salva di default) iconBar.openURL.tooltip=Apri URL iconBar.openFolder.tooltip=Apri una cartella iconBar.new.tooltip=Crea il torrent iconBar.up.tooltip=Sposta su iconBar.down.tooltip=Sposta gi\u00f9 iconBar.run.tooltip=Apri con l'applicazione predefinita iconBar.host.tooltip=Ospita iconBar.publish.tooltip=Pubblica iconBar.editcolumns.tooltip=Configurazione delle colonne MyTorrentsView.menu.editTracker=Modifica URL del track&er GeneralView.menu.selectTracker=Seleziona ConfigView.section.stats.xslfile=Nome del file XSL ConfigView.section.stats.xslfiledetails=Sar\u00e0 incluso nell'intestazione del file delle statistiche tramite il tag ConfigView.label.savetorrentbackup=Salva backup ConfigView.section.tracker.forceport=Forza la porta predefinita per i torrent esterni ospitati ConfigView.section.ipfilter.allow=Autorizza questi intervalli (di default li blocca) ConfigView.section.ipfilter.list.inrange=era nel range ConfigView.section.ipfilter.list.notinrange=non era in nessun range ConfigView.section.ipfilter.list.title=IP bloccati ConfigView.label.allowsameip=Permetti connessioni multiple dallo stesso IP ConfigView.label.allowsameip.tooltip=Da spuntare solo in caso di NECESSIT\u00c0.\n\u00c8 una protezione anti-leecher (quando disabilitata). ManagerItem.superseeding=Super seed ConfigView.label.userSuperSeeding=Usa il \u00absuper seed\u00bb PeersView.uniquepiece=Parte (modalit\u00e0 di super seed) PeersView.uniquepiece.none=Nessuno PeersView.timetosend=Tempo per il reinvio della parte (modalit\u00e0 di super seed) ConfigView.section.style.addurlsilently=Apri URL in modo silenzioso (senza finestra di dialogo) ConfigView.section.style.addurlsilently.tooltip=Scarica automaticamente i link a file .torrent passati/trascinati nella coda, senza aprire finestre di dialogo ConfigView.section.file.decoder.prompt=Mostra sempre quando sono disponibili delle scelte di codifica ConfigView.section.file.decoder.prompt.tooltip=Mostra sempre la finestra di dialogo quando ci sono scelte di codifica disponibili MyTorrentsView.menu.moveTop=Primo MyTorrentsView.menu.moveEnd=&Ultimo ConfigView.label.moveonlyusingdefaultsave=solo se nella cartella predefinita ConfigView.label.moveonlyusingdefaultsave.tooltip=Sposta solo se i dati sono stati scaricati nella cartella predefinita ConfigView.label.watchtorrentfolder=Importa i nuovi .torrent automaticamente ConfigView.label.watchtorrentfolder.tooltip=Cerca nuovi .torrent regolarmente ConfigView.label.watchtorrentfolderinterval=Intervallo ConfigView.label.watchtorrentfolderinterval.tooltip=La pausa prima che la cartella venga ricontrollata ConfigView.dialog.choosewatchtorrentfolderpath=Scegliere la cartella da cui importare i .torrent ConfigView.label.startwatchedtorrentsstopped=Inizia nello stato di Fermato ConfigView.label.startwatchedtorrentsstopped.tooltip=Aggiungi nuovi .torrent nello stato di Fermato ConfigView.section.plugins=Plugin wizard.maketorrent.filesize=Dimensione file wizard.maketorrent.piececount=Numero parti wizard.maketorrent.piecesize=Dimensione parti wizard.maketorrent.auto=Automatico MainWindow.menu.view.stats=&Statistiche SpeedView.title.full=Statistiche SpeedView.downloadSpeed.title=Velocit\u00e0 di download SpeedView.uploadSpeed.title=Velocit\u00e0 di upload ConfigView.section.style.useSIUnits=Usa le unit\u00e0 di misura del SI (KB -> KiB, ecc.) iconBar.top.tooltip=Sposta in alto iconBar.bottom.tooltip=Sposta in basso TableColumn.header.health=Salute MyTorrentsView.menu.health=Informazioni sulla salute health.explain.grey=Il torrent non \u00e8 avviato (download o upload) health.explain.red=Non si \u00e8 connessi a nessun peer mentre si cerca di scaricare health.explain.blue=Quando si invia, significa che non si \u00e8 ancora connessi a nessun peer\nquando si scarica, significa che si \u00e8 connessi a qualche peer, ma il tracker non \u00e8 attivo health.explain.yellow=Il tracker \u00e8 ok, si \u00e8 connessi ai peer, ma non si hanno connessioni remote.\nForse si ha un problema NAT se i torrent rimangono nello stato giallo per tutto il tempo. health.explain.green=Tutto sta andando bene ConfigView.section.style.alwaysRefreshMyTorrents=Aggiorna sempre \u00abI miei torrent\u00bb ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Questa opzione aggiorna la vista \u00abI miei torrent\u00bb anche se non \u00e8 mostrata (utile per alcuni plugin per mirc) # #2.0.7.0 # security.certtruster.title=Avviso di certificato di sicurezza security.certtruster.intro=Il certificato di sicurezza proviene da una compagnia non ancora autorizzata security.certtruster.resource=Risorsa: security.certtruster.issuedto=Destinato a: security.certtruster.issuedby=Proviene da: security.certtruster.prompt=Accettarlo? security.certtruster.yes=S\u00ec ConfigView.section.tracker.torrentsperpage=Quanti torrent per pagina ? [0: illimitato] MainWindow.menu.file.share=&Condividi MainWindow.menu.file.share.dir=Cartell&a MainWindow.menu.file.share.dircontents=&Contenuto cartella... MainWindow.menu.file.share.dircontentsrecursive=Contenuto cartella... (&Ricorsivo) MainWindow.dialog.share.sharefile=Selezione del file da condividere MainWindow.dialog.share.sharedir=Selezione della cartella da condividere MainWindow.dialog.share.sharedircontents=Selezione della cartella di cui condividere il contenuto MainWindow.dialog.share.sharedircontents.recursive=Ricorsivo globalmanager.download.remove.veto=Operazione di rimozione non consentita plugin.sharing.download.remove.veto=Questo download \u00e8 il risultato di una risorsa che viene condivisa.\n Per rimuovere il download, rimuovere lo share associato. ConfigView.section.tracker.main=Principale ConfigView.label.prioritizefirstpiece=Dai priorit\u00e0 alla prima ed ultima parte dei file ConfigView.label.prioritizefirstpiece.tooltip=Tenta di scaricare innanzi tutto l'inizio e la fine del file.\nPer permettere un veloce controllo. ConfigView.section.file.confirm_data_delete=Chiedi conferma quando elimini dati ConfigView.section.file.confirm_data_delete.tooltip=Chiedi conferma della cancellazione quando si usa \u00abRimuovi e elimina...\u00bb ConfigView.section.file.delete.include_files_outside_save_dir=Quando si eliminano i dati, rimuovi anche i file collegati fuori dalla cartella di salvataggio TrayWindow.menu.startalldownloads=&Avvia tutti i download SystemTray.menu.startalltransfers=&Avvia tutti i trasferimenti sharing.progress.title=Avanzamento della condivisione sharing.progress.hide=Nascondi MainWindow.menu.view.myshares=Le mie condivisioni MySharesView.title.full=Le mie condivisioni MySharesView.name=Nome MySharesView.type=Tipo MySharesView.type.dir=Cartella MySharesView.type.dircontents=Contenuti delle cartelle MySharesView.type.dircontentsrecursive=Contenuti delle cartelle (ricorsivo) MySharesView.menu.remove=Rimuovi ConfigView.section.tracker.extensions=Estensioni ConfigView.section.tracker.sendpeerids=Invia l'identit\u00e0 dei peer a chi scarica ConfigView.section.tracker.enableudp=Abilita il protocollo UDP per il tracker plugin.sharing.torrent.remove.veto=Questa registrazione nel tracker \u00e8 il risultato di una risorsa condivisa.\nPer rimuovere il download, rimuovere la condivisione associata. plugin.download.remove.veto.notstopped=Il download non pu\u00f2 essere rimosso se non viene prima fermato. plugin.sharing.remove.veto=Questa condivisione \u00e8 una sotto-condivisione di una cartella condivisa e non pu\u00f2 essere eliminata esplicitamente.\nEliminare la cartella condivisa. GeneralView.label.hash.tooltip=Fare clic per copiare il codice hash negli appunti ConfigView.section.tracker.maxpeersreturned=Numero massimo di peer restituiti [0: illimitato] ConfigView.label.serverport=Porta di ascolto TCP / UDP (ingresso) ConfigView.label.serverport.tooltip=La porta deve essere compresa tra 1 e 65535, e non deve essere 6880 perch\u00e9 \u00e8 riservata all'uso interno di Vuze. configureWizard.nat.server.tcp_listen_port=Porta TCP di ascolto (traffico in ingresso) ConfigView.section.sharing=Condivisione ConfigView.section.sharing.usessl=Usa SSL per le risorse condivise (richiede la configurazione del tracker) ConfigView.section.style.dropdiraction=Azione connessa al trascinamento e rilascio delle cartelle ConfigView.section.style.dropdiraction.opentorrents=Apri torrent ConfigView.section.style.dropdiraction.sharefolder=Condividi cartella ConfigView.section.style.dropdiraction.sharefoldercontents=Condividi contenuti multimediali # # 2.0.7.x # Categories.all=Tutte Categories.uncategorized=Nessuna categoria CategoryAddWindow.message=Inserire il nome della nuova categoria CategoryAddWindow.title=Aggiunta di una nuova categoria ConfigView.label.autoSeedingIgnoreInfo=I torrent ignorati diventano gli ultimi in coda e non verranno avviati in automatico.\nQueste regole non saranno applicate ai torrent con la Prima priorit\u00e0.\nUsa il valore 0 per disabilitare la regola. ConfigView.label.directory=Cartella ConfigView.label.disconnetseed.tooltip=Durante il seed di un torrent, disconnetti tutti i seed.\nLoro non hanno bisogno di comunicare con te. ConfigView.label.ignoreCase=Ignora Maiuscolo/Minuscolo ConfigView.label.ignoreSeeds=Ignora i torrent con almeno ConfigView.label.importdirectory=Importa cartella ConfigView.label.minPeersToBoostNoSeeds.tooltip=I torrent con nessun seed e meno peer di quanto specificato\nsaranno spostati pi\u00f9 in basso nella coda. ConfigView.label.minPeersToBoostNoSeeds=Diminuisci il punteggio di seed ai torrent senza seed e con meno di ConfigView.label.minSeedingTime.tooltip=Il punteggio di seed pu\u00f2 variare spesso e in breve tempo, a volte causando l'avvio automatico di alcuni torrent, che immediatamente dopo vengono fermati e messi in coda.\nQuesto allevia il problema forzando il torrent a stare in seed per un certo periodo. Lo si pu\u00f2 comunque fermare manualmente se si vuole. ConfigView.label.minSeedingTime=Numero minimo di secondi di seed ConfigView.label.minSpeedForActiveDL.tooltip=Uno slot di download viene sempre usato per i primi 30 secondi\ndopo che il torrent incompleto \u00e8 stato avviato. ConfigView.label.minSpeedForActiveDL=Non considerare nel conto degli slot di download usati i torrent con velocit\u00e0 inferiore a ConfigView.label.peers=peer ConfigView.label.queue.debuglog=Registra le informazioni di debug ConfigView.label.queue.debuglog.info=Aggiungi le informazioni di debug delle code al file di log.\nSebbene criptiche, le informazioni di debug dicono lo stato dei torrent e perch\u00e9 sono o non sono in coda. ConfigView.label.queue.minQueueingShareRatio=Non fermare o mettere in coda i torrent finch\u00e9 il loro rapporto di condivisione non raggiunge ConfigView.label.ratio=rapporto ConfigView.label.removeOnStop=Rimuovi i torrent dalla lista dopo che sono stati fermati in automatico ConfigView.label.savedirectory=Cartella di salvataggio ConfigView.label.seeding.autoReposition.tooltip=Se abilitato, l'ordine dei torrent (la colonna \u00abn\u00b0\u00bb) sar\u00e0 modificato in base al Punteggio di seed.\nQuesto \u00e8 utile se a te non piace guardare i numeri del Punteggio di seed, ma vuoi sapere l'ordine in cui i torrent completi inizieranno. ConfigView.label.seeding.autoReposition=Riposiziona automaticamente i torrent in base al Punteggio di seed ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Spesso, i torrent con pochi seed e molti peer indicano che probabilmente non c'\u00e8 una copia completa del file tra i peer.\nPerci\u00f2, potresti non voler applicare la regola che assume che ci sia una copia completa (e quindi riduce il punteggio in modo errato). ConfigView.label.seeding.fakeFullCopySeedStart=ma solo per i torrent con almeno ConfigView.label.seeding.ignore=Torrent ignorati ConfigView.label.seeding.ignore0Peers=Ignora i torrent con 0 peer ConfigView.label.seeding.ignoreRatioPeers=Ignora i torrent che hanno almeno 1 seed ogni ConfigView.label.seeding.ignoreShareRatio=Ignora i torrent che hanno un rapporto di condivisione di ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignora il torrent anche se\ncorrisponde ai criteri di \u00abPrima priorit\u00e0\u00bb ConfigView.label.seeding.ignore.header.rule=Regola ConfigView.label.seeding.ignore.header.value=Valore ConfigView.label.seeding.firstPriority.info=I torrent con \u00abPrima priorit\u00e0\u00bb saranno sempre i primi della coda. I torrent che soddisfano i criteri della \u00abPrima priorit\u00e0\u00bb non saranno fermati automaticamente, e riceveranno pi\u00f9 slot di download simultanei, se necessario. ConfigView.label.seeding.firstPriority.FP=Prima priorit\u00e0 ConfigView.label.seeding.firstPriority=La \u00abPrima priorit\u00e0\u00bb sar\u00e0 data ai torrent con ConfigView.label.seeding.firstPriority.following=dei seguenti requisiti: ConfigView.label.seeding.firstPriority.shareRatio=Un rapporto di condivisione al di sotto del ConfigView.label.seeding.firstPriority.seedingMinutes=Un tempo trascorso, dal cambio da download in seed, ConfigView.label.seeding.firstPriority.DLMinutes=Un tempo trascorso dall'inizio del download ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Assumendo che ci sia 1 copia completa ogni N peer, si riduce il punteggio dei torrent con un gran numero di peer.\nProbabilmente, i torrent con un gran numero di peer hanno anche un alto traffico.\nQuesta opzione non cambia il numero di seed mostrati. ConfigView.label.seeding.numPeersAsFullCopy=Assumi che ci sia 1 copia completa del torrent ogni\n[0: disabilitato] ConfigView.label.seeding.preferLargerSwarms.tooltip=Se si effettua principalmente il seed di torrent con peer che sono \u00abbloccati\u00bb, ha senso preferire i file con pi\u00f9 swarm\nQuando si effettua principalmente il seed di torrent con alta disponibilit\u00e0, ha senso preferire i file con meno swarm. ConfigView.label.seeding.preferLargerSwarms=Quando pi\u00f9 torrent hanno lo stesso punteggio, preferisci quelli con pi\u00f9 utenti ConfigView.label.seeding.rankType.none.tooltip=Ordine basato sulla colonna \u00abn\u00b0\u00bb ConfigView.label.seeding.rankType.none=Nessuno ConfigView.label.seeding.rankType.peer.tooltip=pi\u00f9 peer e meno seed => punteggio maggiore\nQuesto metodo rende minimo il numero di torrent da mantenere attivi per raggiungere il limite di upload. ConfigView.label.seeding.rankType.peer=Conteggio dei peer pesato ConfigView.label.seeding.rankType.peerSeed.options=Opzioni rapporto peer/seed ConfigView.label.seeding.rankType.peerSeed.tooltip=Pi\u00f9 alto il rapporto => Pi\u00f9 alto il punteggio ConfigView.label.seeding.rankType.peerSeed=Rapporto peer/seed ConfigView.label.seeding.rankType.seed.fallback=Usa il rapporto peer/seed se ci sono pi\u00f9 di\n[0: mai] ConfigView.label.seeding.rankType.seed.options=Opzioni di Conto dei soli seed ConfigView.label.seeding.rankType.seed.tooltip=Pi\u00f9 basso il numero di seed => Pi\u00f9 alto il punteggio ConfigView.label.seeding.rankType.seed=Conto dei soli seed ConfigView.label.seeding.rankType.timedRotation.tooltip=Tutti i torrent completati e in coda entreranno a rotazione nella modalit\u00e0 di seed.\nLa durata del tempo di seed \u00e8 impostata con il \u00abnumero minimo di secondi di seed\u00bb ConfigView.label.seeding.rankType.timedRotation=Rotazione temporale ConfigView.label.seeding.rankType.tooltip=I torrent con il punteggio pi\u00f9 alto sono avviati in automatico.\nQuando un altro torrent acquista un punteggio maggiore, quello con il punteggio minore viene fermato e messo in coda.\n\nSolo i torrent nello stato \u00abMesso in coda\u00bb sono disponibili per l'avvio automatico.\nI torrent in stato \u00abFermato\u00bb non sono mai avviati in automatico. ConfigView.label.seeding.rankType=L'attribuzione del Punteggio di seed ai torrent completati per l'avvio automatico \u00e8 basato su: ConfigView.label.stopAfterMinutes=Una volta entrato in seed, ferma dopo ConfigView.label.switchpriority.tooltip=La bassa priorit\u00e0 riduce la quantit\u00e0 di banda in upload assegnata al torrent. ConfigView.pluginlist.info=I seguenti plugin sono stati identificati. Alcuni plugin potrebbero non avere la scheda di configurazione. ConfigView.pluginlist.noplugins=Nessun plugin trovato. ConfigView.section.pluginslist=Lista ConfigView.section.queue.seeding=Seed ConfigView.section.queue.seeding.autoStarting=Avvio automatico ConfigView.section.queue.seeding.ignore=Torrent ignorati ConfigView.section.queue.seeding.firstPriority=Prima priorit\u00e0 ConfigView.section.queue.main=Principale ConfigView.section.queue=Coda ConfigView.section.torrents=Torrent ConfigView.text.all=tutti ConfigView.text.hours=ore ConfigView.text.ignoreRule=Ignora regola ConfigView.text.ignore=Ignora ConfigView.text.minutes=minuti ConfigView.text.neverIgnore=Non ignorare mai ConfigView.text.any=almeno uno DownloadManager.error.datamissing=Dati mancanti MainWindow.menu.file.open.torrentforseeding=File torrent... (per il seed) MainWindow.menu.language.refresh=&Aggiorna ManagerItem.forced=Forzato ManagerItem.queued=Messo in coda MySeedersView.header=Torrent completati TableColumn.header.availability.info=N\u00b0 copie complete TableColumn.header.availability=Disponibilit\u00e0 TableColumn.header.category=Categoria MyTorrentsView.header=Torrent non completati TableColumn.header.maxuploads=N\u00b0 max di upload MyTorrentsView.menu.category.delete=&Elimina categoria MyTorrentsView.menu.forceStart=&Forza l'avvio MyTorrentsView.menu.queue=&Metti in coda MyTorrentsView.menu.setCategory.add=&Aggiungi categoria... MyTorrentsView.menu.setCategory=Assegna categoria TableColumn.header.savepath=Percorso di salvataggio TableColumn.header.SeedingRank=Punteggio di seed TableColumn.header.totalspeed.info=Velocit\u00e0 totale di tutti i peer a cui si \u00e8 connesso TableColumn.header.totalspeed=Velocit\u00e0 totale splash.initializePlugins=Inizializzazione dei plugin StartStopRules.SPratioMet=Rapporto S:P OK StartStopRules.FP0Peers=PP / 0 peer StartStopRules.0Peers=0 peer StartStopRules.numSeedsMet=N\u00b0 seed OK StartStopRules.ratioMet=Peer:Seed OK StartStopRules.shareRatioMet=Rapporto di condivisione OK StartStopRules.waiting=In attesa StartStopRules.firstPriority=Prima priorit\u00e0 ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Condividi contenuti multimediali (ricorsivo) DownloadManager.error.unabletostartserver=Impossibile avviare il server - controllare la configurazione delle porte in ingresso e i permessi del firewall per le applicazioni che fanno da server. GeneralView.label.creationdate=Creato il : ConfigView.section.tracker.announcescrapepercentage=Intervallo di scrape corrispondente a una % dell'et\u00e0 dell'announce\nad esempio 200 = \u00ab2:1\u00bb. 0 = \u00ablascia decidere il peer\u00bb ManagerItem.stopping=Sto fermando ConfigView.section.tracker.announcecacheperiod=Cache dell'announce (ms) ConfigView.section.tracker.scrapecacheperiod=Cache dello scrape (ms) ConfigView.section.tracker.scrapeandcache=Scrape e cache ConfigView.section.tracker.announcecacheminpeers=Cache dell'annuncio - Abilita la soglia dei peer MyTrackerView.scrapes=Scrape fileDownloadWindow.retry=Riprova MyTrackerView.bytesin=Byte in entrata MyTrackerView.bytesinave=Media entrata MyTrackerView.bytesout=Byte in uscita MyTrackerView.bytesoutave=Media uscita ConfigView.section.file.max_open_files=Numero massimo di file aperti in lettura/scrittura\n[0: illimitato] ConfigView.section.file.max_open_files.tooltip=Utile se si scaricano torrent contenenti centinaia o migliaia di file, e se si sta raggiungendo il limite di file aperti del sistema operativo. ConfigView.section.proxy=Proxy ConfigView.section.proxy.enable_proxy=Abilita proxy ConfigView.section.proxy.port=Porta ConfigView.section.proxy.username=Nome utente ConfigView.section.proxy.enable_socks=Ho un proxy SOCKS wizard.createtorrent.extrahashes=Aggiungi gli hash per le altre reti (ad esempio Gnutella2, eDonkey2000) GeneralView.label.connected=connesso GeneralView.label.in_swarm=nello swarm ManagerItem.initializing=Inizializzazione in corso AlertMessageBox.error=Errore AlertMessageBox.warning=Avviso AlertMessageBox.comment=Commento AlertMessageBox.information=Informazioni AlertMessageBox.unread=Ci sono messaggi di avviso non letti - fare clic qui per visualizzarli. SharedPortServer.alert.selectorfailed=Impossibile mettersi in ascolto per i dati in ingresso.\nControllare che le impostazioni del firewall permettano a java(w).exe di operare da \u00abserver\u00bb. Tracker.alert.listenfail=Impossibile stabilire l'ascolto sulla porta %1.\nControllare che le altre applicazioni non stiano gi\u00e0 usando questa porta.\nControllare anche se sono in esecuzione altre istanze di Vuze. DiskManager.alert.movefileexists=Errore nello spostare i file completati:\nil file %1 esiste gi\u00e0 nella cartella di destinazione. DiskManager.alert.movefilefails=Errore nello spostare i file completati:\nimpossibile spostare il file %1, %2 DiskManager.alert.movefilerecoveryfails=Errore nel recupero del file dopo lo spostamento non riuscito:\n recupero del file %1 non riuscito, %2 ConfigView.section.tracker.logenable=Registra periodicamente le statistiche in \u00abtracker.log\u00bb SpeedView.stats.title=Statistiche SpeedView.stats.total=Totale SpeedView.stats.session=Questa sessione SpeedView.stats.session.tooltip=Totale (Protocollo) SpeedView.stats.downloaded=Scaricati (Protocollo) SpeedView.stats.uploaded=Inviati (Protocollo) SpeedView.stats.ratio=Rapporto SpeedView.stats.uptime=Tempo di attivit\u00e0 (ore) SpeedView.stats.now=Ora SpeedView.stats.now.tooltip=Totale (Protocollo) AutoMigration.useralert=Risultati dell'auto-migrazione dei file utente di Vuze:\n\n%1\nIn caso di fallimento effettuare una migrazione manuale.\nNON DIMENTICARE DI AGGIORNARE I PERCORSI DI SALVATAGGIO NELLA CONFIGURAZIONE IN CASO DI MIGRAZIONE! # # > 2.0.8.0 # OpenTorrentWindow.title=Apri torrent OpenTorrentWindow.message=Sperimentale OpenTorrentWindow.addFiles=&Aggiungi file OpenTorrentWindow.dataLocation=Posizione in cui salvare i dati: OpenTorrentWindow.startMode=Aggiungi in modalit\u00e0 OpenTorrentWindow.startMode.queued=Messo in coda OpenTorrentWindow.startMode.stopped=Fermato OpenTorrentWindow.startMode.forceStarted=Forza l'avvio OpenTorrentWindow.addPosition=Posizione in coda OpenTorrentWindow.addPosition.first=Primo OpenTorrentWindow.addPosition.last=Ultimo TableColumn.header.remaining.info=Dimensione dei dati da scaricare TableColumn.header.remaining=Rimanenti ConfigView.section.tracker.enablecompact=Abilita il protocollo \u00abcompact announce\u00bb ConfigView.section.tracker.enablekey=Abilita il passaggio delle chiavi di cifratura al tracker (aumenta la sicurezza) ConfigView.section.file.perf=Opzioni per le prestazioni ConfigView.section.file.perf.explain=Attenzione - il cambiamento di questi parametri pu\u00f2 compromettere le prestazioni di download. Riavvio necessario.\nSe si hanno problemi di \u00abmemoria insufficiente\u00bb considerare la limitazione delle connessioni per torrent (vedere \u00abConfigurazione -> Trasferimento\u00bb) ConfigView.section.file.max_open_files.explain=Aprire troppi file pu\u00f2 causare problemi al sistema operrativo dovuti a risorse limitate come gli handle dei file. Questo limita il numero di file aperti contemporaneamente. popup.error.hide=Nascondi popup.error.details=Dettagli ConfigView.section.style.colorOverrides=Sovrascrivi colori ConfigView.section.style.colorOverride.progressBar=Barre di progresso ConfigView.section.style.colorOverride.error=Errore MainWindow.status.tooOld=\u00e8 vecchio, aggiornarlo. ConfigView.section.style.colorOverride.warning=Avvisi ConfigView.section.style.colorOverride.altRow=Righe alternate ConfigView.section.file.save.peers.enable=Salva informazioni sulle connessioni ai peer, per facilitare la riconnessione ConfigView.section.file.save.peers.max=Numero massimo di peer di cui salvare le informazioni [0: illimitato] ConfigView.label.max_peers_per_torrent=Numero massimo di connessioni per torrent [0: illimitato] ConfigView.label.max_peers_total=Numero massimo di connessioni (globali) [0: illimitato] ConfigView.section.style.colorOverrides.reset=Ripristina i colori ConfigView.section.language.info=Se abilitato, verranno cercati aggiornamenti ad ogni avvio di Vuze. ConfigView.section.language.enableUpdate=Abilita aggiornamento web ConfigView.section.language.UpdateURL=Aggiorna URL ConfigView.section.language.UpdateNow=Aggiorna ora! Button.revert=Ripristina MyTorrentsView.menu.changeDirectory=Cambia la cartella dei dati GenericText.column=colonna MyTorrentsView.menu.thisColumn.remove=Rimuovi colonna MyTorrentsView.menu.thisColumn.toClipboard=Copia il testo negli appunti MyTorrentsView.menu.thisColumn.autoTooltip=Mostra sempre il suggerimento TableColumn.header.secondsseeding=In seed per TableColumn.header.secondsseeding.info=Tempo totale di seed TableColumn.header.secondsdownloading=Tempo totale di DL TableColumn.header.secondsdownloading.info=Tempo totale di download ConfigView.section.tracker.udpversion=Versione del protocollo UDP (1 o 2) window.updateswt.title=SWT non aggiornato! window.updateswt.text=SWT non \u00e8 aggiornato!\nSWT \u00e8 la libreria grafica usata da Vuze e la versione attualmente installata non supporta l'ultima versione di Vuze.\nFare clic su OK per aggiornare SWT. window.updateswt.status=Stato window.updateswt.failed=Aggiornamento non riuscito, premere nuovamente Ok per ricominciare. window.updateswt.status.downloading.updater=Sto scaricando il modulo Updater window.updateswt.status.finding=Sto cercando l'ultima versione di SWT window.updateswt.status.downloading=Sto scaricando l'ultima versione di SWT window.updateswt.status.done=Riavvio in corso window.updateswt.ok=Ok window.updateswt.cancel=Annulla swt.updater.downloader.downloading=Sto scaricando SWT da swt.updater.urlsgetter.downloading=Ottengo una lista di mirror da swt.updater.urlsgetter.platform=SWT per la piattaforma : window.updateswt.ignore=Ignora ConfigView.section.style.useFancyTabs=Usa le linguette arrotondate splash.initializeGM=Inizializzazione del gestore torrent globale splash.loadingTorrents=Caricamento dei torrent MyTorrentsView.menu.thisColumn.sort=&Ordina Scrape.status.ok=Scrape Ok. Scrape.status.error=Errore scrape: Scrape.status.error.badURL=L'URL dell'annuncio non rispetta le specifiche dello scrape. Scrape.status.error.nohash=Hash mancante nella risposta. Scrape.status.error.invalid=Risposta non valida. Scrape.status.nextScrapeAt=Prossimo scrape fra %1 Scrape.status.scraping=Scrape in corso... Scrape.status.initializing=In attesa dello scrape Scrape.status.scraping.queued=Scrape in coda... ConfigView.label.minSpeedForActiveSeeding=Non considerare nel conteggio degli slot di upload usati i torrent completati con velocit\u00e0 inferiore a ConfigView.section.stats.exportpeers=Esporta i dettagli dei peer MainWindow.menu.view.irc.moved=Adesso Irc \u00e8 disponibile solo come plugin, vedere http://azureus.sourceforge.net/plugin_list.php. Una volta installato, vi si pu\u00f2 accedere attraverso \u00abVisualizza -> Plugin -> IRC\u00bb. MyTrackerView.webui.contextmenu.copyurl=Copia l'URL del torrent negli appunti ConfigView.section.file.torrent.ignorefiles=File da ignorare quando si creano/eliminano torrent\n - per esempio \u00ab.DS_Store;Thumbs.db\u00bb Torrent.create.progress.ignoringfile=Sto ignorando il file ConfigView.section.style.useUnitsRateBits=Usa i bit invece dei byte per i valori basati sui byte (KiB/s -> Kibit/s, ecc.) ConfigView.section.interface.resetassoc=Ripristina le associazioni dei file (.torrent) ConfigView.section.interface.resetassocbutton=Ripristina ConfigView.section.interface.checkassoc=Controlla l'associazione dei file all'avvio dialog.associations.title=Controllo delle associazioni dei file Button.yes=&S\u00ec ConfigView.label.seeding.autoStart0Peers=Avvia in automatico tutti i torrent completi con 0 peer ConfigView.label.seeding.autoStart0Peers.tooltip=Abilita se vuoi che il tracker mostri sempre i seed per i torrent con 0 peer dialog.associations.prompt=Vuze non \u00e8 l'applicazione predefinita per i file BitTorrent.\nAssociare i file .torrent ad Vuze dialog.associations.askagain=Controlla all'avvio ConfigView.section.plugins.update=Aggiorna plugin Plugin.pluginupdate.enablecheck=Abilita la ricerca di aggiornamenti per i plugin plugins.basicview.status=Stato: plugins.basicview.activity=Attivit\u00e0: plugins.basicview.progress=Avanzamento: ConfigView.label.maxdownloadspeed=Velocit\u00e0 massima globale di download (KB/s) [0: illimitata] splash.loadingTorrent=Caricamento del torrent splash.of=di ConfigView.section.plugins.irc=Irc UpdateWindow.title=Aggiornamento di Vuze UpdateWindow.header=I seguenti componenti necessitano di essere aggiornati : UpdateWindow.columns.install=Installa UpdateWindow.columns.name=Nome UpdateWindow.columns.version=Versione UpdateWindow.columns.size=Dimensione UpdateWindow.cancel=Annulla UpdateWindow.quit=Esci UpdateWindow.close=Chiudi UpdateWindow.ok=Aggiorna UpdateWindow.restart=Riavvia UpdateWindow.status.downloading=Download in corso UpdateWindow.status.done=Fatto UpdateWindow.status.failed=Errore UpdateWindow.status.restartNeeded=Sara necessario riavviare! ConfigView.pluginlist.broken=Danneggiato ConfigView.pluginlist.whereToPut=Posiziona i plugin specifici degli utenti nelle loro cartelle sotto: ConfigView.pluginlist.whereToPutOr=Per i plugin condivisi usa: MainWindow.statusText.checking=Verifico la presenza di aggiornamenti TableColumn.header.OnlyCDing4=Solo in seed TableColumn.header.OnlyCDing4.info=Periodo di tempo durante il quale il torrent \u00e8 stato solamente in seed. Esclude il tempo durante il quale il torrent veniva scaricato (e condiviso). ConfigView.section.style.alternateTablePainting=Usa un metodo alternativo per disegnare le colonne delle tabelle grafiche (pu\u00f2 richiedere un riavvio) UpdateWindow.status.restartMaybeNeeded=Potrebbe essere necessario riavviare ConfigView.pluginlist.shared=condiviso PeersView.host=Nome host PeersView.host.info=Il nome host del peer, quando disponibile (potrebbe influire sulle prestazioni) MainWindow.menu.help.whatsnew=Cosa c'\u00e8 di nuovo ConfigView.label.checkonstart=Verifica se ci sono aggiornamenti all'avvio di Vuze ConfigView.label.periodiccheck=Controlla gli aggiornamenti periodicamente ConfigView.label.opendialog=Avvia in automatico l'assistente agli aggiornamenti quando \u00e8 disponibile un aggiornamento MainWindow.updateavail=Fare clic qui per gli aggiornamenti MainWindow.status.unofficialversion=Beta di Vuze MainWindow.status.latestversionunchecked=Verifica della versione disabilitata GeneralView.label.updatein.stopped=Fermato StartStopRules.menu.viewDebug=Vedi le informazioni di debug ConfigView.section.style.doNotUseGB=Non usare l'unit\u00e0 GB ConfigView.section.style.doNotUseGB.tooltip=Se selezionata, Vuze continuer\u00e0 ad usare i MB anche per dimensioni pi\u00f9 grandi di 1024 MB MainWindow.menu.help.plugins=Ottieni plugin ConfigView.section.plugins.TrackerWeb=Tracker web ConfigView.section.tracker.enablecategories=Separa i torrent per categoria health.explain.share=Significa che il torrent \u00e8 ospitato o pubblicato ConfigView.section.tracker.createcert=Crea certificati autofirmati ConfigView.section.tracker.createbutton=Crea security.certcreate.title=Creazione di un certificato autofirmato security.certcreate.intro=Questa sezione permette di creare un certificato auto-firmato security.certcreate.strength=Crittografia security.certcreate.firstlastname=Nome e cognome security.certcreate.orgunit=Gruppo organizzativo security.certcreate.org=Organizzazione security.certcreate.city=Citt\u00e0 o Localit\u00e0 security.certcreate.state=Stato o provincia security.certcreate.country=Codice del Paese (due lettere) security.certcreate.ok=Crea security.certcreate.cancel=Annulla security.certcreate.createok=Certificato creato correttamente security.certcreate.createfail=Creazione del certificato non riuscita ConfigView.section.plugins.webui=Interfaccia Swing Web ConfigView.section.plugins.xml_http_if=Interfaccia XML/HTTP webui.passwordenable=Abilita password webui.user=Nome utente webui.port=Porta (*) webui.protocol=Protocollo (*) webui.homepage=Pagina principale (*) webui.rootdir=Cartella principale (*) webui.rootres=Risorsa principale (*) webui.mode=Modalit\u00e0 (*) webui.mode.info=La modalit\u00e0 puo essere\n\t\u00abfull\u00bb\t= tutte le operazioni disponibili (predefinito)\n\t\u00abview\u00bb\t= solo visione (ma pu\u00f2 modificare la frequenza di aggiornamento). webui.access=Accesso (*) webui.access.info=L'accesso puo essere \n\t\u00ablocal\u00bb\t= solo il computer locale pu\u00f2 connettersi\n\t\u00aball\u00bb\t= accesso senza limiti (default)\n\tIP\t\t= ad esempio 192.168.0.2\t\t\t\tsolo un IP\n\tIP1-IP2\t= ad esempio 192.168.0.1-192.168.0.255\trange di IP GeneralView.label.maxdownloadspeed=Limite down. Security.keystore.corrupt=Errore nel caricamento del keystore \u00ab%1\u00bb, cancellarlo e ricreare/reinportare i certificati. Security.keystore.empty=Il keystore \u00e8 vuoto. Creare un certificato autofirmato (vedere \u00abStrumenti -> Configurazione -> Sicurezza\u00bb) o importarne uno gi\u00e0 esistente in \u00ab%1\u00bb. webui.restart.info=Le modifiche ai parametri indicati con una (*) richiedono un riavvio per funzionare correttamente. GeneralView.label.maxdownloadspeed.tooltip=Velocit\u00e0 massima di download [0: illimitata] upnp.enable=Abilita UPnP upnp.info=Universal Plug and Play (UPnP) permette la mappatura automatica delle porte sui router abilitati all'UPnP. upnp.mapping.dataport=Porta di ascolto upnp.mapping.tcptrackerport=Porta TCP del tracker upnp.mapping.udptrackerport=Porta UDP del tracker upnp.alert.differenthost=UPnP: la mappatura \u00ab%1\u00bb \u00e8 stata riservata da \u00ab%2\u00bb - selezionare una porta differente. upnp.alert.mappingok=UPnP: mappatura \u00ab%1\u00bb stabilita. upnp.alert.mappingfailed=UPnP: mappatura \u00ab%1\u00bb non riuscita. upnp.alertsuccess=Comunica le mappature riuscite upnp.alert.lostdevice=UPnP: persa la connessione al servizio \u00ab%1\u00bb sulla periferica UPnP \u00ab%2\u00bb. upnp.grabports=Mappa le porte anche se sono utilizzate da un altro computer upnp.refresh.label=Aggiorna i mappaggi upnp.refresh.button=Aggiorna upnp.alert.mappinggrabbed=UPnP: mappatura \u00ab%1\u00bb stabilita - acquisita da \u00ab%2\u00bb. upnp.mapping.tcpssltrackerport=Porta TCP con SSL del tracker upnp.alertothermappings=Segnala le porte utilizzate dagli altri computer upnp.alertdeviceproblems=Segnala problemi con la periferica UPnP upnp.trace_to_log=Scrivi informazioni di debug complete nel file registro upnp.wiki_link=Pagina della wiki di Vuze sull'UPnP upnp.refresh_mappings_on_bad_nat=Aggiorna automaticamente i mappaggi quando lo stato del NAT \u00e8 \u00abCon firewall\u00bb ConfigView.pluginlist.coreplugins=Sono stati caricati i seguenti plugin integrati: Peers.column.DLedFromOthers=Da altri Peers.column.DLedFromOthers.info=Quantit\u00e0 di informazioni scaricate dagli altri mentre era connesso a te Peers.column.UpDownRatio=Rapporto Peers.column.UpDownRatio.info=Rapporto \u00abinviato/scaricato\u00bb del peer Peers.column.UpRatio=Rapporto di upload Peers.column.UpRatio.info=Rapporto \u00abInviato da te : Inviato da altri\u00bb del peer upnp.releasemappings=Libera i mappaggi alla chiusura webui.upnpenable=Abilita UPnP per questa porta (*) ConfigView.section.file.friendly.hashchecking=Controllo dell'hash amichevole ConfigView.section.file.friendly.hashchecking.tooltip=Una modalit\u00e0 di hash delle parti leggermente pi\u00f9 lenta, ma molto meno pesante per la cpu ed il sistema. ConfigView.section.tracker.seedretention=Numero massimo di seed conservati per torrent [0: illimitato] ConfigView.section.tracker.seedretention.info=Nota: le statistiche di upload saranno perse per i seed non conservati. ConfigView.section.tracker.port=Abilita tracker sulla porta HTTP ConfigView.section.tracker.sslport=Abilita tracker sulla porta HTTPS ConfigView.section.tracker.publicenable.info=Permette ad altri di creare torrent che usano il tuo tracker\nsenza che sia tu ad ospitarli o pubblicarli. Button.clear=Pulisci MainWindow.IPs.tooltip=Ultimo aggiornamento della lista dei filtri: %1\nTotale filtri IP nella lista - Numero di IP bloccati/bannati/invalidi per questa sessione.\nFare doppio clic per maggiori dettagli. ConfigView.section.ipfilter.list.banned=\u00c8 stato bannato per aver inviato dati danneggiati ConfigView.section.ipfilter.list.baddata=ha inviato dati danneggiati: n\u00b0 volte = Button.reset=Ripristina ConfigView.section.ipfilter.bannedinfo=IP che hanno inviato dati danneggiati - bannati se superano i limiti ConfigView.section.ipfilter.blockedinfo=IP che sono stati bloccati dai filtri IP download.removerules.name=Regole di rimozione download.removerules.unauthorised.info=I torrent non autorizzati sono quelli che contengono nella risposta dell'annuncio il messaggio di errore \u00abNon autorizzato\u00bb. download.removerules.unauthorised=Rimuovi automaticamente i torrent non autorizzati download.removerules.unauthorised.seedingonly=\tSolo se in seed download.removerules.removed.ok=La rimozione automatica del torrent \u00ab%1\u00bb ha avuto successo. Questo \u00e8 causato dalle regole di rimozione del torrent. download.removerules.updatetorrents=Rimuovi i torrent dell'aggiornamento di Vuze se richiesto dallo swarm ConfigView.label.defaultstarttorrentsstopped=Di default aggiungi i nuovi torrent nello stato di fermato. ConfigView.section.server.enableudp=Abilita il protocollo client tracker UDP upnp.mapping.dataportudp=Porta client UDP del tracker ConfigView.section.file.decoder.showlax=Mostra codifiche meno probabili ConfigView.section.file.decoder.showall=Considera tutte le possibili codifiche MainWindow.status.updowndetails.tooltip=Dettagli della velocit\u00e0 di upload/download - fare clic con il tasto destro per cambiare, fare doppio clic per aprire le statistiche TrackerClient.announce.warningmessage=Il Tracker per \u00ab%1\u00bb ha notificato l'avviso \u00ab%2\u00bb ConfigView.section.tracker.natcheckenable=Analizza la connettivit\u00e0 della \u00abporta di dati in ingresso\u00bb e riporta eventuali errori ai peer ConfigView.section.tracker.publishenabledetails=Pubblica tutti i dettagli del torrent ConfigView.section.tracker.publishenablepeerdetails=Pubblica i dettagli sui peer MyTrackerView.badnat=Problema NAT MyTrackerView.badnat.info=Seed/Peer che hanno fallito un controllo sul NAT, se abilitato ConfigView.section.tracker.natchecktimeout=Timeout del controllo (sec) ConfigView.section.file.perf.cache.enable=Abilita cache del disco ConfigView.section.file.perf.cache.size=Dimensione della cache (%1) MainWindow.menu.transfers=T&rasferimenti MainWindow.menu.transfers.startalltransfers=Av&via tutti MainWindow.menu.transfers.stopalltransfers=Fer&ma tutti MainWindow.menu.transfers.pausetransfers=Metti in &pausa MainWindow.menu.transfers.resumetransfers=&Riprendi ConfigView.label.experimental.osx.kernel.panic.fix=Correzione sperimentale per problemi di kernel su sistemi OSX con doppia cpu [richiede riavvio] SystemTray.menu.pausetransfers=Metti in pausa i trasferimenti SystemTray.menu.resumetransfers=Riprendi i trasferimenti ConfigView.section.file.truncate.too.large=Taglia i file esistenti che sono troppo grandi ConfigView.section.file.perf.cache.trace=Traccia le operazioni della cache a scopo diagnostico ConfigView.section.interface.enabletray=Abilita l'icona nel vassoio di sistema [richiede riavvio] PeerManager.status.error=Errore Stats.title.full=Statistiche TransferStatsView.title.full=Trasferimenti CacheView.general.size=Dim. totale CacheView.general.inUse=In uso CacheView.general.title=Informazioni sulla cache CacheView.reads.title=Letture I/O CacheView.reads.fromFile=Da file CacheView.reads.fromCache=Dalla cache CacheView.reads.hits=Accessi CacheView.writes.title=Scritture I/O CacheView.writes.toCache=Alla cache CacheView.writes.toFile=A file CacheView.writes.hits=Salvato CacheView.speeds.title=Grafici dati CacheView.speeds.reads=Letture CacheView.speeds.writes=Scritture CacheView.speeds.fromCache=Dalla/Alla cache CacheView.speeds.fromFile=Da/A file CacheView.reads.#=N\u00b0 CacheView.reads.amount=Quantit\u00e0 CacheView.reads.avgsize=Dim. media openUrl.referrer=Pagina URL di riferimento : openUrl.referrer.info=Necessaria solamente per i siti internet che la richiedono ConfigView.label.maxuploadspeedseeding=Modifica la velocit\u00e0 quando si \u00e8 solo in seed a ConfigView.label.transfer.ignorepeerports=Ignora i peer con queste porte (separale con \u00ab;\u00bb, per esempio \u00ab0;25\u00bb) ConfigView.section.proxy.enable_socks.peer=Abilita il passaggio su proxy delle comunicazioni con i peer (solo connessioni in uscita) [richiede riavvio] ConfigView.section.proxy.peer.informtracker=Informa il tracker delle limitazioni ConfigView.section.proxy.socks.version=Versione di SOCKS PiecesView.legend.written=Scritto PiecesView.legend.requested=Richiesto PiecesView.legend.downloaded=Scaricato, in attesa di scrittura PiecesView.legend.incache=Informazioni nella cache PiecesView.typeItem.0=Lento PiecesView.typeItem.1=Veloce PiecesView.type=Tipo Security.jar.tools_not_found=Firma del JAR non riuscita - \u00abtools.jar\u00bb non \u00e8 stato trovato in %1. Vedere \u00abStumenti -> Configurazione -> Sicurezza\u00bb per maggiori informazioni. Security.jar.signfail=Firma del JAR non riuscita - %1 ConfigView.section.security.toolsinfo=I file JAR firmati sono usati per supportare alcuni plugin, per esempio l'interfaccia Swing Web (quando configurata a farlo).\nPer firmare i file JAR \u00e8 necessario avere accesso al file \u00abtools.jar\u00bb disponibile con l'installazione del Sun JDK (non JRE).\nSe \u00e8 installata solo la JRE, installare la JDK.\nVuze pu\u00f2 normalmente trovare il file in modo autonomo. Tuttavia, se non ci riesce si pu\u00f2 configurare manualmente la cartella. ConfigView.section.security.toolsdir=Cartella contenente \u00abtools.jar\u00bb ConfigView.section.security.choosetoolssavedir=Selezionare la cartella contenente \u00abtools.jar\u00bb ConfigView.section.proxy.peer.same=Usa le stesse impostazioni proxy per il tracker e i peer ConfigView.section.connection.network.max.simultaneous.connect.attempts=Massimo numero di tentativi di connessioni in uscita simultanei ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Numero massimo di nuovi tentativi di connessione in uscita che Vuze dovrebbe cercare di stabilire ogni volta.\nNOTA: Windows XP Service Pack 2 (SP2) impone un limite di 10 tentativi di connessione per tutto il sistema.\nIl valore predefinito \u00e8 8. ConfigView.section.file.perf.cache.size.explain=La cache \u00e8 usata per ridurre le letture/scritture sul disco. A meno che non si stia usando l'opzione java \u00ab-XX:MaxDirectMemorySize\u00bb per impostare esplicitamente la memoria disponibile per la cache e l'IO di rete, si dovrebbe tenere questo valore almeno %1 sotto la massima dimensione della memoria virtuale. L'attuale dimensione massima della memoria virtuale \u00e8 %2. Per informazioni su come cambiare questo valore, vedere il paragrafo MemoryUsage sul wiki (%3). Errori nell'uso di impostazioni delicate provocheranno problemi di \u00abMemoria esaurita\u00bb. Pi\u00f9 di 32MB di cache sono probabilmente eccessivi. MyTorrentsView.menu.setSpeed.unlimit=Nessun limite MyTorrentsView.menu.setSpeed.unlimited=Illimitato MyTorrentsView.menu.setSpeed.disable=Disabilita l'upload MyTorrentsView.menu.setSpeed.disabled=Disabilita MyTorrentsView.menu.setSpeed.slots=slot di GeneralView.label.maxuploadspeed=Limite di upload GeneralView.label.maxuploadspeed.tooltip=Velocit\u00e0 massima di upload [0: illimitata] MyTorrents.items.UpSpeedLimit.disabled=Nessun upload MyTorrents.items.UpSpeedLimit.unlimited=Illimitata TableColumn.header.maxupspeed=Max velocit\u00e0 di upload TableColumn.header.maxupspeed.info=Max velocit\u00e0 di upload per torrent ConfigView.section.file.perf.cache.enable.write=Cache dei dati scaricati per ridurre le letture e le scritture sul disco richieste dall'analisi di ogni parte ConfigView.section.file.perf.cache.enable.read=Abilita la lettura anticipata per ridurre le letture del disco durante l'upload ConfigView.section.tracker.separatepeerids=Usa diverse identit\u00e0 di peer per le comunicazioni con il tracker e le comunicazioni dati ConfigView.section.tracker.separatepeerids.info=Aumenta l'anonimato se si \u00e8 in download/seed anonimo\nma si sta usando un tracker non anonimo. ConfigView.section.interface.wavlocation=Percorso del file .wav ConfigView.section.interface.wavlocation.info=Selezionare un file .wav o lasciare vuoto per il suono di default ConfigView.section.tracker.client.connecttimeout=Timeout di connessione (sec) ConfigView.section.tracker.client.readtimeout=Timeout di lettura (sec) MainWindow.menu.tools=&Strumenti FilesView.path=Percorso FilesView.fullpath=Mostra il percorso completo FilesView.remaining=Parti restanti TableColumn.header.trackername=Nome del tracker TableColumn.header.trackername.info=Nome del tracker basato sull'URL dell'annuncio ConfigView.group.override=Opzioni per l'override ConfigView.section.file.perf.cache.notsmallerthan=Non mettere in cache file pi\u00f9 piccoli di (%1) PeersView.menu.blockupload=Blocca upload PeersView.menu.kickandban=Caccia e banna PeersView.menu.kickandban.reason=Peer bannato manualmente PeersView.state=Stato PeersView.state.info=Stato della connessione del peer PeersView.state.pending=In corso PeersView.state.connecting=In connessione PeersView.state.handshake=In attesa dell'handshake PeersView.state.established=Pienamente stabilito ConfigView.section.tracker.processinglimits=Limiti di elaborazione ConfigView.section.tracker.maxgettime=Tempo massimo per l'elaborazione di GET (sec) [0: illimitato] ConfigView.section.tracker.maxgettime.info=Usato per annunci e scrape ConfigView.section.tracker.maxposttimemultiplier=Moltiplicatore del tempo di GET per l'elaborazione del POST [0: illimitato] ConfigView.section.tracker.maxposttimemultiplier.info=Usato per l'invio di form ed upload ConfigView.section.tracker.maxthreads=Numero massimo di richieste simultanee DownloadManager.error.operationcancancelled=Operazione annullata Torrent.create.progress.cancelled=Operazione annullata sharing.progress.cancel=Annulla wizard.maketorrents.autoopen=Apri il torrent per il seed alla fine del processo ConfigView.section.sharing.rescanenable=Controlla periodicamente lo share per eventuali cambiamenti ConfigView.section.sharing.rescanperiod=Intervallo di ricontrollo (sec) ConfigView.section.connection.advanced=Impostazioni di rete avanzate ConfigView.section.connection.advanced.mtu=Unit\u00e0 massima di trasmissione della linea (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Grandezza massima di un pacchetto che pu\u00f2 essere trasferita in un frame su di una rete.\nVuze usa le MTU-40 (MSS) per ottimizzare l'invio.\nValori raccomandati:\n 576 - Connessioni dial-up\n1492 - Connessioni a banda larga PPPoE\n1500 - Ethernet, DSL e connessioni a banda larga via cavo ConfigView.section.connection.advanced.SO_RCVBUF=Dimensioni di SO_RCVBUF del socket standard [0: usa il valore predefinito del SO] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Imposta i valori di SO_RCVBUF (in byte) del socket standard, cio\u00e8 dimensioni e scala della finestra di ricezione TCP.\nVuze lascia questi valori disattivati di default, intendendo le impostazioni predefinite per il SO che si sta usando.\nNOTA: Linux raddoppia i valori dati. ConfigView.section.connection.advanced.SO_SNDBUF=Dimensioni del SO_SNDBUF del socket [0: usa il valore predefinito del SO] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Imposta il valore standard del socket SO_SNDBUF (in byte), i.e.dimensioni e scala della finestra di ricezione dei TCP.\nVuze lascia questi valori disattivati di default, intendendo le impostazioni predefinite per il SO che si sta usando.\nNOTE: Linux duplica i valori dati. ConfigView.section.connection.advanced.IPDiffServ=Valore DiffServ dei pacchetti In Uscita (campo TOS) ConfigView.section.connection.advanced.IPDiffServ.tooltip=Imposta la sezione DiffServ del campo type-of-service (TOS) nell'intestazione IP per i pacchetti in uscita.\nSi possono specificare valori esadecimali usando il prefisso \u00ab0x\u00bb, ad esempio \u00ab0x10\u00bb.\nVuze per scelta non imposta questo valore, lasciando che venga usato il valore predefinito del sistema operativo.\nNOTA: Le implementazioni di rete sottostanti potrebbero ignorare questo valore, quindi questa opzione \u00e8 altamente dipendente dalle versioni del SO e della JRE. ConfigView.section.interface.confirm_torrent_removal=Mostra messaggi di conferma alla rimozione di un torrent ConfigView.section.interface.confirm_torrent_removal.tooltip=Chiedi conferma quando viene rimosso un torrent dalla scheda \u00abI miei torrent\u00bb. MyTorrentsView.confirm_torrent_removal=Si \u00e8 sicuri di volerlo rimuovere?\n TableColumn.header.seed_to_peer_ratio=Seed alla media dei peer TableColumn.header.seed_to_peer_ratio.info=Seed totali nello swarm rispetto la media dei peer PeersView.connected_time=Tempo di connessione PeersView.connected_time.info=Tempo totale di connessione con il peer ConfigView.section.interface.display.add_torrents_silently=Aggiungi torrent in modo silenzioso ConfigView.section.interface.display.add_torrents_silently.tooltip=Metti i torrent in download senza aprire la finestra principale di Vuze. TableColumn.header.maxdownspeed=Massima velocit\u00e0 di download TableColumn.header.maxdownspeed.info=Massima velocit\u00e0 di download per il peer ConfigView.section.tracker.passwordwebhttpsonly=Abilita accesso solo via HTTPS TableColumn.header.torrentpath=Posizione del torrent TableColumn.header.torrentpath.info=Posizione del torrent nel disco ConfigView.section.sharing.torrentcomment=Commenti per i torrent generati ConfigView.label.copyanddeleteratherthanmove=Copia e poi cancella i dati originali invece di spostarli in una sola operazione - pu\u00f2 evitare perdite di dati su alcuni file system ConfigView.label.openstatsonstart=Apri le Statistiche all'avvio swt.install.window.title=Installazione di plugin per Vuze swt.install.window.ok=Installa swt.install.window.header=I seguenti componenti sono stati selezionati per l'installazione : swt.uninstall.window.title=Disinstallazione di plugin di Vuze swt.uninstall.window.ok=Rimuovi swt.uninstall.window.header=I seguenti componenti sono stati selezionati per la disinstallazione: installPluginsWizard.title=Installazione di plugin installPluginsWizard.mode.title=Scegliere un metodo di installazione installPluginsWizard.mode.list=Dalla lista di sourceforge.net installPluginsWizard.list.title=Lista dei plugin installabili installPluginsWizard.list.loading=Attendere mentre la lista dei plugin viene caricata. installPluginsWizard.list.loaded=Scegliere i plugin da installare. installPluginsWizard.list.name=Nome installPluginsWizard.list.version=Versione installPluginsWizard.list.description=Descrizione del plugin installPluginsWizard.finish.title=Installazione in corso installPluginsWizard.finish.explanation=I plugin selezionati verranno installati usando l'Assistente agli aggiornamenti.\n\nSii paziente, potrebbe richiedere un po' per comparire.\n\nPer dettagli sullo stato di avanzamento, fare doppio clic a sinistra della barra di stato. installPluginsWizard.details.loading=Caricamento dettagli, attendere... installPluginsWizard.mode.file=Da file installPluginsWizard.installMode.title=Scelta del tipo di installazione installPluginsWizard.installMode.user=Installa i plugin solo per te installPluginsWizard.installMode.shared=Installa il plugin per tutti gli utenti installPluginsWizard.file.title=Scelta del plugin da installare installPluginsWizard.file.file=File: installPluginsWizard.file.invalidfile=Il file non \u00e8 un plugin valido di Vuze. installPluginsWizard.file.no_such_file=Non esiste un file con questo nome. installPluginsWizard.file.browse=Sfoglia... uninstallPluginsWizard.title=Disinstallazione dei plugin uninstallPluginsWizard.list.title=Lista dei plugin installati uninstallPluginsWizard.list.loaded=Selezionare il plugin da disinstallare. installPluginsWizard.list.nullversion=Nessuna versione uninstallPluginsWizard.finish.title=Disinstallazione in corso uninstallPluginsWizard.finish.explanation=I plugin selezionati verranno disinstallati usando l'Assistente agli aggiornamenti. MainWindow.menu.plugins.installPlugins=Assistente di installazione... MainWindow.menu.plugins.uninstallPlugins=Assistente di disinstallazione... ConfigView.section.ipfilter.totalIPs=%1 IP bloccati in totale, che rappresentano il %2 di internet. update.instance.install=Controllo dell'installazione update.instance.uninstall=Controllo della disinstallazione update.instance.update=Controllo gli aggiornamenti MainWindow.status.update.tooltip=Fare doppio clic per informazioni sull'avanzamento updater.progress.window.title=Operazioni di installazione in corso updater.progress.window.info=Premere \u00abInterrompi\u00bb per terminare tutti i processi in corso. Button.abort=Annulla ConfigView.section.ipfilter.enablebanning=Blocca i peer che inviano costantemente dati danneggiati Network.alert.acceptfail=Troppi errori consecutivi nella porta %1, %2 - processo interrotto. Controllare le impostazioni del firewall per questa porta, per assicurarsi che sia abilitata a ricevere connessioni. MyShares.column.category=Categoria UpdateWindow.restartLater=Riavvia in seguito MainWindow.menu.file.restart=Riavvia Vuze MainWindow.dialog.restartconfirmation.title=Conferma del riavvio di Vuze MainWindow.dialog.restartconfirmation.text=Riavviare Vuze? deletetorrent.message1=Si sta per eliminare il TORRENT di:\n deletetorrent.message2=\nSi \u00e8 sicuri di procedere? ConfigView.label.prioritizemostcompletedfiles=Dai ulteriore priorit\u00e0 ai file con Prima priorit\u00e0 in base alla percentuale di completamento e alla dimensione del file splash.plugin.init=Inizializzazione del plugin: splash.plugin.UIinit=Inizializzazione del plugin dell'interfaccia: %1 ConfigView.section.style.osx_small_fonts=Usa caratteri piccoli [richiede riavvio] ConfigView.section.tracker.tcpnonblocking=Usa l'I/O non bloccante per i processi TCP del tracker. Selezionare questa opzione richieder\u00e0 l'utilizzo del tracker web su una porta alternativa. Sperimentale! ConfigView.section.tracker.nonblocking=Opzioni di non-bloccaggio ConfigView.section.tracker.nonblockingconcmax=Numero massimo di connessioni simultanee [0: illimitate] MyTorrentsView.menu.exportmenu=Esporta ConfigView.section.tracker.client.scrapeinfo=Disabilitare lo scrape impedir\u00e0 a molte delle regole di gestione della coda di funzionare perch\u00e9 dipendono dalle informazioni sullo swarm ricevute facendo lo scrape dei tracker. ConfigView.section.tracker.client.scrapeenable=Abilita lo scrape ConfigView.section.tracker.client.scrapestoppedenable=Fai lo scrape dei torrent che non sono attivi Scrape.status.disabled=Scrape disabilitato MyTorrentsView.menu.explore=Mostra file MyTorrentsView.menu.explore._mac=Mostra nel Finder MyTorrentsView.menu.explore._windows=Mostra in Explorer wizard.maketorrents.autohost=Ospita il torrent nel tracker integrato ConfigView.label.overrideip=Sovrascrivi l'indirizzo(i) IP per l'annuncio dei tracker - separa con \u00ab:\u00bb se pi\u00f9 di uno, per reti diverse ConfigView.label.overrideip.tooltip=Informa il tracker di un indirizzo(i) IP diverso da quello da cui provengono i pacchetti in uscita. Lasciare bianco per non usare l'opzione. ConfigView.section.connection.group.networks=Reti ConfigView.section.connection.group.networks.info=Selezionare le reti consentite per gli scambi di dati tra peer ConfigView.section.connection.networks.prompt=Richiedi la selezione quando viene aggiunto un download con tracker anonimo ConfigView.section.connection.networks.Public=Rete IP pubblica (non anonima) ConfigView.section.connection.networks.I2P=Rete I2P ConfigView.section.connection.networks.Tor=Rete Onion router (Tor) TableColumn.header.networks=Reti TableColumn.header.networks.info=Reti consentite per la comunicazione di informazioni tra peer Scrape.status.networkdisabled=Rete non abilitata ConfigView.section.tracker.server.group.networks=Reti ConfigView.section.tracker.server.group.networks.info=Selezionare le reti dalle quali il tracker accetter\u00e0 i peer window.networkselection.title=Selezione della rete window.networkselection.info=Il torrent indicato qui sotto ha uno o pi\u00f9 tracker che supportano le seguenti reti.\nSelezionane quelle da abilitare per le comunicazioni tra peer e tracker.\nSe si tratta di un tracker anonimo che supporta i client pubblici abilitare sia la rete anonima sia quella pubblica.\nAbilitare la rete pubblica ha come ovvia conseguenza la perdita dell'anonimato! window.networkselection.description=Torrent: plugins.basicview.clear=Pulisci ConfigView.section.connection.group.peersources=Fonti dei peer ConfigView.section.connection.group.peersources.info=Selezionare le fonti permesse per le connessioni ai peer ConfigView.section.connection.peersource.Tracker=Da un tracker ConfigView.section.connection.peersource.DHT=Tracking decentralizzato ConfigView.section.connection.peersource.PeerExchange=Fornite da un altro peer ConfigView.section.connection.peersource.Plugin=Aggiunte da un plugin ConfigView.section.connection.peersource.Incoming=Connessioni in entrata PeersView.source=Fonte PeersView.source.info=La fonte di questo peer TableColumn.header.peersources=Fonti dei peer TableColumn.header.peersources.info=Fonti dei peer consentite per stabilire le connessioni dei peer wizard.tracker.dht=Decentralizzato (solo per client Vuze) MyTorrentsView.menu.advancedmenu=Avanzate MyTorrentsView.menu.networks=Reti MyTorrentsView.menu.peersource=Fonti dei peer ConfigView.section.sharing.permitdht=Abilita il tracking decentralizzato quando il tracker non \u00e8 disponibile ConfigView.section.sharing.protocol=Protocollo per le risorse condivise PeersView.Messaging=Messaggistica PeersView.Messaging.info=Indica il sistema di messaggistica in uso. ConfigView.label.queue.newseedsmovetop=Sposta i torrent appena completati in cima alla lista di seed ConfigView.label.seeding.firstPriority.ignore.info=Fa attenzione, perch\u00e9 l'uso di queste regole pu\u00f2 portare allo stop di un torrent\nappena il download finisce. ConfigView.label.seeding.firstPriority.ignore=Ignora le regole soprastanti della \u00abPrima priorit\u00e0\u00bb per: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrent con un rapporto tra seed e peer superiore a ConfigView.label.seeding.firstPriority.ignore0Peer=Torrent con 0 peer ConfigView.section.tracker.sendjavaversionandos=Invia la versione di Java ed il nome del sistema operativo MagnetPlugin.contextmenu.exporturi=Copia l'indirizzo Magnet negli appunti ConfigView.section.plugins.dht=DB distribuito dht.info=Questo plugin supporta il tracking decentralizzato, fra le altre cose, - disabilitarlo ridurr\u00e0 la possibilit\u00e0 di scaricare. dht.enabled=Abilita il database distribuito dht.portdefault=Usa la porta di default dht.port=Porta UDP per il database dht.execute.command=Comando di diagnosi dht.execute.info=Premere per eseguire il comando dht.execute=Avvia dht.logging=Abilita il tracciamento dell'attivit\u00e0 ConfigView.section.plugins.dhttracker=Tracker distribuito dhttracker.tracknormalwhenoffline=Traccia i torrent normali solamente quando il loro tracker non \u00e8 disponibile ConfigView.section.file.nativedelete._mac=Usa il Cestino quando vengono eliminati dei file ConfigView.section.file.nativedelete._windows=Sposta i file eliminati nel Cestino ConfigView.section.logging.generatediagnostics=Genera ConfigView.section.logging.netinfo=Genera informazioni sulla rete ConfigView.section.logging.statsinfo=Genera informazioni statistiche ConfigView.section.logging.generatediagnostics.info=Genera informazioni di diagnosi copiandole sulla clipboard e generando un file di registro, se configurato. ConfigView.section.sharing.privatetorrent=Torrent privato - accetta solamente i peer dal tracker MainWindow.menu.tools.nattest=Test &NAT / Firewall Button.apply=Applica Button.close=Chiudi window.welcome.title=Benvenuto in Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Note di rilascio dht.reseed.label=Normalmente, il reseed del database distribuito non \u00e8 necessario. Tuttavia, se il numero di contatti \u00e8 basso, puo essere usato per una reintegrazione.\nLasciare vuoto per ricevere automaticamente la lista dei peer connessi, oppure inserire un indirizzo IP ed una porta per ricevere la lista da un peer conosciuto. dht.reseed.group=Ripetizione del seed dht.reseed.ip=Indirizzo IP dht.reseed.port=Porta dht.reseed=Ripeti il seed dht.reseed.info=Esegue il reseed del database dht.diagnostics.group=Diagnostica DHTView.title.full=Database distribuito DHTView.title.fullcvs=Database distribuito CVS DHTView.general.title=Generale DHTView.general.uptime=Tempo di attivit\u00e0: DHTView.general.users=Utenti: DHTView.general.nodes=Nodi: DHTView.general.leaves=Foglie: DHTView.general.contacts=Contatti: DHTView.general.replacements=Rimpiazzi: DHTView.general.live=Attivi: DHTView.general.unknown=Sconosciuto: DHTView.general.dying=Morenti (Dying): DHTView.transport.title=Dettagli del trasferimento DHTView.transport.packets=Pacchetti DHTView.transport.bytes=Byte DHTView.transport.received=Ricevuti DHTView.transport.sent=Inviati DHTView.transport.in=In entrata : DHTView.transport.out=Uscenti : DHTView.operations.title=Dettagli dell'operazione DHTView.operations.sent=Inviati DHTView.operations.failed=Errori DHTView.operations.received=Ricevuti DHTView.operations.findNode=Trova nodo DHTView.operations.findValue=Trova valore DHTView.operations.store=Memorizzati DHTView.activity.title=Attivit\u00e0 DHTView.activity.status=Stato DHTView.activity.status.true=In coda DHTView.activity.status.false=Avviato DHTView.activity.type=Tipo DHTView.activity.type.1=Get interno DHTView.activity.type.2=Get esterno DHTView.activity.type.3=Put interno DHTView.activity.type.4=Put esterno DHTView.activity.target=Destinazione DHTView.activity.details=Dettagli DHTView.db.keys=Chiavi DHTView.db.values=Valori DHTView.db.local=Locale DHTView.db.direct=Diretto DHTView.db.indirect=Indiretto DHTView.db.divfreq=Divis. di freq. DHTView.db.divsize=Divis. della dim. MainWindow.dht.status.tooltip=Quando il database distribuito \u00e8 avviato viene mostrato il numero stimato di utenti attualmente in linea MainWindow.dht.status.disabled=DHT Disabilitato MainWindow.dht.status.failed=Errore del DHT MainWindow.dht.status.initializing=Inizializzazione del DHT in corso MainWindow.dht.status.users=%1 utenti MainWindow.dht.status.unreachable=DHT bloccato da firewall MainWindow.dht.status.unreachabletooltip=Sembra esserci un problema con la mappatura della porta UDP del database distribuito (NAT/firewall) MyTorrentsView.menu.setUpSpeed=Imposta la velocit\u00e0 di upload MyTorrentsView.menu.setDownSpeed=Imposta la velocit\u00e0 di download ConfigView.section.tracker.client.showwarnings=Mostra i messaggi di avviso restituiti dal tracker dht.advanced=Abilita le impostazioni avanzate dht.advanced.group=Impostazioni avanzate dht.advanced.label=Modificare questi valori solo se si sa quello che si sta facendo dht.override.ip=Sovrascrivi indirizzo IP esterno ConfigView.section.logging.loggerenable=Abilita la registrazione delle operazioni ConfigView.section.ipfilter.blockbanning=Banna un intero blocco di 256 indirizzi quando in quel blocco ne sono stati bannati almeno MyTrackerView.passive=Passivo TableColumn.header.swarm_average_speed=Velocit\u00e0 media dello swarm TableColumn.header.swarm_average_speed.info=La velocit\u00e0 media dei peer nello swarm TableColumn.header.comment=Commento TableColumn.header.comment.info=Commento definito dall'utente per il download TableColumn.header.commenticon=Icona dei commenti TableColumn.header.commenticon.info=Un'icona, se presente, avvisa che il torrent ha ricevuto commenti dagli utenti MyTrackerView.category=Categoria MainWindow.menu.file.open.torrentfortracking=File torrent... (solo tracking) MyTrackerView.date_added=Aggiunto ConfigView.section.tracker.portbackup=Porte di backup (separate da \u00ab;\u00bb) ConfigView.label.playfilespeech=Parla quando un file \u00e8 stato scaricato ConfigView.label.playfilespeech.info=Il servizio di sintesi vocale funziona meglio con la lingua inglese. ConfigView.label.playfilefinished=Riproduci un suono quando un file \u00e8 stato scaricato ConfigView.label.backupconfigfiles=Fai copie di backup dei file di configurazione per permetterne il recupero ConfigView.section.tracker.client.scrapesingleonly=Disabilita l'aggregazione per tracker degli scrape (pu\u00f2 aiutare con i tracker che riportano errori \u00abURL too long\u00bb (414)) dht.ipfilter.log=Registra le violazioni del filtro IP ConfigView.label.seeding.addForSeedingDLCopyCount=Considera l'aggiunta al seed dei download che hanno scaricato questo numero di copie ActivityView.legend.limit=Limite di velocit\u00e0 ActivityView.legend.achieved=Velocit\u00e0 raggiunta ActivityView.legend.overhead=Traffico del protocollo ActivityView.legend.peeraverage=Media ActivityView.legend.swarmaverage=Media dello swarm ActivityView.legend.trimmed=Spezzettato (punteggiato) MyTorrentsView.menu.movemenu=Sposta file MyTorrentsView.menu.movedata=Sposta file di dati... MyTorrentsView.menu.movetorrent=Sposta file torrent... MyTorrentsView.menu.movedata.dialog=Scegliere una nuova posizione DHTView.operations.data=Dati DHTView.general.reachable=Raggiungibile: DHTView.general.rendezvous=Ritrovo: ConfigView.label.queue.maxactivetorrentswhenseeding=Max quando si \u00e8 solo in seed [0:illimitati] IrcView.title.short=Irc Views.plugins.IRC.title=IRC - supporto tecnico in linea Formats.units.alot=Molto !!! ConfigView.section.ipfilter.persistblocking=Salva le informazioni sugli IP bloccati per il prossimo avvio FilesView.menu.rename=Rinomina o reindirizza FilesView.menu.rename_only=Rinominazione veloce FilesView.menu.retarget=Sposta i file FilesView.rename.choose.path=Scegliere un file nuovo o gi\u00e0 esistente FilesView.rename.choose.path.dir=Scegliere una cartella nuova o gi\u00e0 esistente FilesView.rename.confirm.delete.title=Conferma dell'eliminazione FilesView.rename.confirm.delete.text=Eliminare il file originale \u00ab%1\u00bb? FilesView.rename.filename.title=Rinominazione del file FilesView.rename.filename.text=Scegliere un nuovo nome per il file. ConfigView.higher.mode.available=Nelle modalit\u00e0 utente pi\u00f9 avanzate sono disponibili opzioni aggiuntive. ConfigView.section.mode=Modalit\u00e0 ConfigView.section.mode.title=Abilit\u00e0 dell'utente ConfigView.section.mode.beginner=Principiante ConfigView.section.mode.beginner.wiki.definitions=Glossario di BitTorrent (in inglese) ConfigView.section.mode.intermediate=Intermedio ConfigView.section.mode.intermediate.wiki.host=Ospitare file (in inglese) ConfigView.section.mode.intermediate.wiki.publish=Pubblicazione di file (in inglese) ConfigView.section.mode.advanced=Avanzata ConfigView.section.mode.advanced.wiki.main=Pagina iniziale del wiki (in inglese) ConfigView.section.mode.beginner.text=Tutto quello di cui si ha bisogno per scaricare i torrent.\nUsare questa modalit\u00e0 se tutto quello che si vuole fare \u00e8 gestire i torrent. ConfigView.section.mode.intermediate.text=Possibilit\u00e0 di accedere alle funzioni del tracker.\nUsare questa modalit\u00e0 per creare un tracker ed ospitare/pubblicare file. ConfigView.section.mode.advanced.text=Accesso alle impostazioni della rete.\nUsare questa modalit\u00e0 solo se si conosce cosa sono gli MTU o i \u00abnon blocking I/O\u00bb... Files.column.storagetype=Tipo di archiviazione Files.column.fileext=Tipo FileItem.storage.linear=Lineare FileItem.storage.compact=Compatto MessageBoxWindow.rememberdecision=Ricorda la scelta ConfigView.section.interface.cleardecisions=Resetta le decisioni memorizzate nelle finestre di dialogo ConfigView.section.interface.cleardecisionsbutton=Resetta ConfigView.section.interface.cleartrackers=Svuota la cronologia dei tracker ConfigView.section.interface.cleartrackersbutton=Svuota ConfigView.section.interface.clearsavepaths=Svuota la cronologia dei percorsi di salvataggio ConfigView.section.interface.clearsavepathsbutton=Svuota configureWizard.welcome.usermodes=Queste impostazioni sull'abilit\u00e0 dell'utente determineranno il livello delle opzioni mostrate in \u00abStrumenti -> Opzioni\u00bb. \u00c8 nel tuo interesse configurarle correttamente. FilesView.skip.confirm.delete.text=Troncare il file \u00ab%1\u00bb per risparmiare spazio? FilesView.rename.failed.title=Rinominazione/Reindirizzamento non riuscito FilesView.rename.failed.text=L'operazione non \u00e8 riuscita, probabilmente perch\u00e9 il percorso non \u00e8 valido. diagnostics.log_found=Vuze non si \u00e8 chiuso correttamente. Analizzare le registrazioni diagnostiche. Vedere anche l'articolo Vuze Disappears (in inglese) del wiki per maggiori informazioni. ManagerItem.paused=In pausa Utils.link.visit=Visitare ConfigView.section.connection.serverport.wiki=Scelta di una buona porta (in inglese) ConfigView.section.transfer.speeds.wiki=Impostazioni ottimali della velocit\u00e0 installPluginsWizard.installMode.info.title=Informazioni installPluginsWizard.installMode.info.text=Vuze non ha bisogno di plugin per lavorare correttamente, apportano caratteristiche complementari per divertimento, automazione o controllo remoto.\nQuindi leggere attentamente la descrizione di ogni plugin prima di installarlo.\nLa maggior parte dei plugin sono sicuri da provare, comunque \u00e8 meglio non sovraccaricare la configurazione con plugin che non verranno usati. Views.plugins.Distributed.DB.title=DB distribuito Views.plugins.Distributed.Tracker.title=Tracker distribuito Views.plugins.Plugin.Update.title=Aggiornamento dei plugin openUrl.url.info=Supporta http, https, magnet e stringhe infohash grezze esadecimali TableColumn.header.swarm_average_completion=Media di completamento dei peer TableColumn.header.swarm_average_completion.info=La percentuale media di completamento dei peer nello swarm GeneralView.label.swarm_average_completion=Media di completamento: GeneralView.label.swarm_average_completion.tooltip=La percentuale media di completamento dei peer nello swarm MainWindow.nat.status.tooltip.unknown=raggiungibile attraverso Firewall/NAT ? (TCP) MainWindow.nat.status.tooltip.ok=Raggiungibilit\u00e0 OK (TCP) MainWindow.nat.status.tooltip.probok=La raggiungibilt\u00e0 NAT era in OK, ma non c'\u00e8 nessuna connessione TCP recente in entrata MainWindow.nat.status.bad=Bloccato da firewall MainWindow.nat.status.tooltip.bad=Possibile problema di firewall o NAT (TCP), consultare il wiki se il problema persiste plugin.installer.recommended.plugin=Plugin raccomandato - considerarlo ed installarlo se richiesto LoggerView.pause=Metti in pausa la registrazione delle operazioni LoggerView.clear=&Pulisci LoggerView.filter=Filtra LoggerView.filter.uncheckAll=Deseleziona tutte le categorie LoggerView.filter.checkAll=Seleziona tutte le categorie LoggerView.loggingDisabled=La registrazione delle operazioni non \u00e8 attiva. LoggerView.includeOnly=Mostra solo le linee conformi a questa espressione regolare: LoggerView.excludeAll=Nascondi le linee conformi a questa espressione regolare: ConfigView.section.logging.log0type=Informazioni ConfigView.section.logging.log1type=Avviso ConfigView.section.logging.log2type=Errore ConfigView.section.logging.filter=Filtra durante la registrazione nel file ConfigView.section.logging.level=Livello di registrazione ConfigView.section.logging.showLogsFor=Mostra il registro %1 per le categorie seguenti: ConfigView.pluginlist.column.loadAtStartup=Carica all'avvio ConfigView.pluginlist.column.type=Tipo ConfigView.pluginlist.column.type.perUser=Per utente ConfigView.pluginlist.column.type.shared=Condiviso ConfigView.pluginlist.column.type.builtIn=Integrato ConfigView.pluginlist.column.name=Nome ConfigView.pluginlist.column.version=Versione ConfigView.pluginlist.column.directory=Cartella ConfigView.pluginlist.column.isOperational=Attivo? PeersView.BlockView.Avail.Have=Entrambi lo possedete PeersView.BlockView.Avail.NoHave=Il peer lo possiede; tu no PeersView.BlockView.NoAvail.Have=Lo possiedi; il peer no PeersView.BlockView.NoAvail.NoHave=Nessuno dei due lo possiede PeersView.BlockView.Transfer=Trasferimento in corso PeersView.BlockView.NextRequest=Prossima richiesta PeersView.BlockView.title=Mappa delle parti PeersView.BlockView.AvailCount=Disponibilit\u00e0 MyTorrentsView.dialog.NumberError.title=Numero non valido o non riconosciuto MyTorrentsView.dialog.NumberError.text=Il numero inserito non \u00e8 valido o non \u00e8 riconosciuto. MyTorrentsView.menu.manual=&Manuale... MyTorrentsView.menu.manual.per_torrent=Manuale (per torrent) MyTorrentsView.menu.manual.shared_torrents=Manual (su pi\u00f9 torrent) MyTorrentsView.dialog.setSpeed.title=Impostazione della velocit\u00e0 di %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Inserire il valore %1 a cui impostare la velocit\u00e0 di %2 : OpenTorrentWindow.torrentLocation=Torrent da scaricare (uno per riga): OpenTorrentWindow.addFiles.URL=Aggiungi &URL OpenTorrentWindow.addFiles.Folder=Aggiungi &cartella OpenTorrentWindow.addFiles.Clipboard=Aggiungi dagli a&ppunti OpenTorrentWindow.changeDestination=Cambia destinazione OpenTorrentWindow.fileList=File nei torrent: OpenTorrentWindow.torrentTable.name=Nome OpenTorrentWindow.torrentTable.saveLocation=Destinazione OpenTorrentWindow.fileTable.fileName=Nome file OpenTorrentWindow.fileTable.size=Dimensioni OpenTorrentWindow.fileTable.destinationName=Nome destinazione OpenTorrentWindow.startMode.seeding=Seed OpenTorrentWindow.fileList.changeDestination=Cambia destinazione OpenTorrentWindow.mb.badSize.title=File incompatibile OpenTorrentWindow.mb.badSize.text=\u00ab%1\u00bb non \u00e8 \u00ab%2\u00bb e non pu\u00f2 essere usato per il seed. OpenTorrentWindow.mb.alreadyExists.text=\u00ab%3\u00bb \u00e8 gi\u00e0 stato aggiunto come \u00ab%2\u00bb. OpenTorrentWindow.mb.alreadyExists.default.name=Materiale OpenTorrentWindow.mb.alreadyExists.title=Il torrent esiste gi\u00e0 OpenTorrentWindow.mb.openError.title=Errore di apertura OpenTorrentWindow.mb.openError.text=\u00ab%1\u00bb non pu\u00f2 essere aperto:\n%2 OpenTorrentWindow.torrent.remove=Rimuovi il torrent dalla lista OpenTorrentWindow.torrent.options=Ai torrent selezionati sopra verranno applicate le seguenti impostazioni: OpenTorrentWindow.xOfTotal=(%1 di %2) iconBar.open.tooltip=Apri dei file .torrent LocaleUtil.column.text=Testo sconosciuto Tracker.tooltip.MultiSupport=Questo tracker supporta lo scape di pi\u00f9 hash su richiesta. Tracker.tooltip.NoMultiSupport=Questo tracker non supporta lo scape di pi\u00f9 hash su richiesta. ConfigView.label.lazybitfield=Usa il bitfield passivo (migliora il seed sulle reti che usano il bloccaggio bitfield) LoggerView.realtime=Aggiorna in tempo reale ConfigView.section.file.perf.cache.flushpieces=Scrivi immediatamente le parti completate sul disco. Questo distribuisce nel tempo gli accessi al disco, ma comporta piu operazioni di scrittura. ConfigView.section.file.writemblimit=Coda massima di richieste di scrittura (%1) ConfigView.section.file.writemblimit.explain=Quando la velocit\u00e0 di scrittura del disco \u00e8 inferiore alla velocit\u00e0 di download, questo parametro limita la quantita di dati che verranno messi in coda prima di ridurre la velocit\u00e0 di download. ConfigView.section.file.readmblimit=Coda massima di richieste di lettura (%1) ConfigView.section.file.readmblimit.explain=Questo parametro limita la quantita di memoria che verr\u00e0 usata per immagazzinare le letture in attesa. Button.moveUp=Sposta &su Button.moveDown=Sposta &gi\u00f9 ConfigView.notAvailableForMode=Questa sezione \u00e8 dedicata alla modalit\u00e0 %1 o superiore. Non \u00e8 disponibile nella modalit\u00e0 %2 . health.explain.error=C'\u00e8 un errore con questo torrent. Controllare la colonna dello stato, oppure i suggerimenti sull'icona per l'errore. GeneralView.label.trackerscrapeupdate=Scrape del tracker PeersView.piece=Parte PeersView.piece.info=N\u00b0 dell'ultima parte richiesta da questo peer PiecesView.priority=Priorit\u00e0 PiecesView.priority.info=La priorit\u00e0 di completamento della parte, non prestargli molta attenzione. PiecesView.speed=Velocit\u00e0 PiecesView.speed.info=Ai peer pi\u00f9 lenti viene impedito di interferire molto con le parti piu veloci. TableColumn.header.AvgAvail.info=Somma della disponibilit\u00e0 delle parti divisa per il numero delle parti, divisa per il numero delle connessioni TableColumn.header.AvgAvail=Media disp/parti ConfigView.label.strictfilelocking=Rafforza il blocco per l'accesso esclusivo alla scrittura del file attraverso i torrent MyTorrentsView.menu.checkfilesexist=Controlla l'esistenza dei file MyTorrentsView.menu.rescanfile=Ricontrolla periodicamente le parti incomplete MyTorrentsView.menu.clear_resume_data=Cancella i dati di ripristino Plugin.extseed.name=Seed esterni Plugin.localtracker.name=Ricerca peer nella LAN Plugin.localtracker.info=La ricerca di peer nella LAN permette a pi\u00f9 copie di Vuze che si trovano dietro ad un firewall in una rete comune\ndi scaricare in modo efficiente i torrent, attivando connessioni dirette tra di loro. Plugin.localtracker.enable=Abilita la ricerca di peer nella LAN azinstancehandler.alert.portclash=\u00c8 stato rilevato un conflitto di porta nella LAN: %1 \u00e8 gi\u00e0 in uso da un altro utente di Vuze. Selezionare una nuova porta di ascolto per le connessioni TCP / UDP in entrata (tra %2 e %3). ConfigView.section.transfer.lan=LAN (Rete locale) ConfigView.section.transfer.lan.tooltip=Impostazioni specifiche della LAN ConfigView.section.transfer.lan.uploadrate=Massima velocit\u00e0 di upload nella LAN (KB/s) [0: illimitata] ConfigView.section.transfer.lan.uploadrate.tooltip=Le connessioni fra peer all'interno della stessa LAN hanno limiti di upload specifici. ConfigView.section.transfer.lan.downloadrate=Massima velocit\u00e0 di download nella LAN (KB/s) [0: illimitata] ConfigView.section.transfer.lan.downloadrate.tooltip=Le connessioni fra peer all'interno della stessa LAN hanno limiti di download specifici. TorrentOptionsView.title.short=Impostazioni TorrentOptionsView.title.full=Impostazioni TorrentOptionsView.param.max.peers=Numero massimo di connessioni [0: illimitate] ConfigView.section.connection.encryption.require_encrypted_transport=Richiedi il trasferimento cifrato ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Forza l'uso delle connessioni cifrate con gli altri peer. ConfigView.section.connection.encryption.min_encryption_level=Livello minimo di codifica ConfigView.section.connection.encryption.min_encryption_level.tooltip=In chiaro - solo handshake\nRC4 - tutto il flusso\nLivelli di cifratura superiori richiedono pi\u00f9 CPU. Peers.column.Encryption=Cifratura Peers.column.Encryption.info=Livello di cifratura in uso ConfigView.section.connection.encryption.encrypt.info=Con la cifratura attiva non ci si pu\u00f2 connettere ai client incompatibili se non si abilitano le impostazioni alternative. ConfigView.section.connection.encryption.encrypt.info.link=Ulteriori informazioni (in inglese) MainWindow.sr.status.tooltip.ok=Rapporto di condivisione OK: %1 MainWindow.sr.status.tooltip.poor=Rapporto di condivisione scarso: %1 < 0.9 MainWindow.sr.status.tooltip.bad=Rapporto di condivisione pessimo: %1 < 0.5 ConfigView.section.style.status=Barra di stato: ConfigView.section.style.status.show_sr=Rapporto di condivisione ConfigView.section.style.status.show_nat=Stato NAT ConfigView.section.style.status.show_ddb=Stato DDB ConfigView.section.style.status.show_ipf=Stato IPFilter ConfigView.section.connection.encryption.encrypt.group=Cifratura/Offuscamento del trasferimento ConfigView.section.connection.encryption.encrypt.fallback_info=Abilitare entrambe le impostazioni alternative consentir\u00e0 la connessione ai client incompatibili ma comporter\u00e0 connessioni non cifrate. ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Autorizza la connessione in uscita non cifrata se il tentativo di conessione cifrata fallisce ConfigView.section.connection.encryption.encrypt.fallback_incoming=Autorizza le connessioni in entrata non cifrate ConfigView.section.connection.encryption=Cifratura del trasferimento upnp.selectedinterfaces=Interfacce selezionate (separate da \u00ab;\u00bb, ad esempio \u00abeth0;eth1\u00bb) [vuoto: tutte] ConfigView.section.style.defaultSortOrder=Ordine predefinito ConfigView.section.style.defaultSortOrder.desc=Decrescente ConfigView.section.style.defaultSortOrder.asc=Crescente ConfigView.section.style.defaultSortOrder.flip=L'opposto dell'ordine precedente LoggerView.autoscroll=Scorrimento automatico Button.selectAll=Seleziona tutto Button.markSelected=Spunta selezionati Button.unmarkSelected=Togli la spunta ai selezionati plugins.basicview.config=Configura TorrentOptionsView.param.max.uploads=Numero massimo di slot di upload [minimo: 2] MyTorrentsView.dialog.setPosition.title=Impostazione della posizione MyTorrentsView.dialog.setPosition.text=Inserire la posizione da attribuire ai torrent selezionati: MyTorrentsView.menu.reposition.manual=Riposiziona.. ConfigView.section.connection.advanced.info.link=Ulteriori informazioni (in inglese) ConfigView.section.connection.advanced.socket.group=Impostazioni del socket ConfigView.section.connection.advanced.bind_port=Associa alla porta locale [0: disattivato] ConfigView.section.connection.advanced.bind_port.tooltip=Le connessioni socket uscenti saranno associate localmente alla porta stabilita.\nAbilitarlo potrebbe aiutare in caso di problemi di instabilit\u00e0 NAT del router. ConfigView.section.proxy.group.tracker=Comunicazioni con i tracker ConfigView.section.proxy.group.peer=Comunicazioni con i peer Pieces.column.Requested=Richiesto Pieces.column.Requested.info=Mostra se possono essere fatte altre richieste per la parte (*) ConfigView.label.maxuploadsseeding=Valore alternativo quando solo in seed MyTorrentsView.filter=Filtra: popup.error.hideall=Nascondi tutto ConfigView.section.style.dataStatsOnly=Mostra soltanto le statistiche dei dati (nascondi le statistiche del protocollo) ConfigView.section.style.separateProtDataStats=Mostra separatamente le statistiche dei dati e del protocollo come \u00abdati (protocollo)\u00bb MyTorrentsView.dialog.setFilter.title=Modifica del filtro MyTorrentsView.dialog.setFilter.text=La sezione %1 sar\u00e0 filtrata attraverso il testo specificato sotto. Usare il simbolo | (pipe) per filtrare usando pi\u00f9 frasi. MyTorrentsView.filter.tooltip=Premere Ctrl+X per passare dal RegEx alla normale modalit\u00e0 di ricerca.\nUsare il simbolo | (pipe) per filtrare usando pi\u00f9 frasi. MyTorrentsView.clearFilter.tooltip=Rimuovi filtro MyTorrentsView.menu.filter=Lista dei filtri... ConfigView.section.file.resume.recheck.all=Su un riavvio dopo un crash controlla tutti i file integri per le parti completate (altrimenti soltanto le parti attive all'ultimo salvataggio verranno controllate) ConfigureWizard.language.choose=Scegli una lingua dalla lista seguente: popup.closing.in=Chiusura automatica della finestra in %1 secondi popup.more.waiting=altri %1 messaggi... # > 2402 popup.download.finished=\u00ab%1\u00bb \u00e8 stato scaricato. popup.file.finished=\u00ab%1\u00bb \u00e8 stato scaricato. ConfigView.auto=Automatico Plugin.localtracker.autoadd.info=Aggiungi automaticamente questi peer locali [indirizzi separati da \u00ab;\u00bb, ad esempio \u00ab1.2.3.4\u00bb] Plugin.localtracker.autoadd=Peer espliciti Plugin.localtracker.networks.info=Considera locali le seguenti reti [reti separate da \u00ab;\u00bb, ad esempio 145.227.*.*] Plugin.localtracker.networks=Reti locali MainWindow.menu.view.plugins.logViews=Registro delle operazioni SpeedView.stats.autospeed=Velocit\u00e0 di upload automatica SpeedView.stats.autospeed.disabled=Questa caratteristica o \u00e8 disabilitata (ha bisogno del DHT) o non \u00e8 in uso (\u00e8 stata scelta manualmente una velocit\u00e0 di upload) SpeedView.stats.idlePing=Ping quando inattivo: SpeedView.stats.maxPing=Ping massimo SpeedView.stats.currentPing=Ping attuale: SpeedView.stats.maxUp=Velocit\u00e0 max di upload: ConfigView.pluginlist.unloadSelected=Disabilita i selezionati ConfigView.pluginlist.scan=Cerca nuovi plugin ConfigView.section.transfer.autospeed=Auto-speed (classico) ConfigView.section.transfer.autospeed.tooltip=Impostazioni specifiche di Auto-speed ConfigView.section.transfer.autospeed.info=Auto-speed adatta automaticamente il limite di velocit\u00e0 di upload per evitare di sovraccaricare la connessione alla rete.\n\nQuesti limiti saranno applicati solo se la regolazione automatica dell'upload e il database distribuito sono abilitati.\n ConfigView.section.transfer.autospeed.minupload=Velocit\u00e0 minima di upload (%1) ConfigView.section.transfer.autospeed.minupload.tooltip=La velocit\u00e0 di upload non sar\u00e0 ridotta automaticamente sotto questo limite. ConfigView.section.transfer.autospeed.maxupload=Velocit\u00e0 massima di upload (%1) [0: illimitata] ConfigView.section.transfer.autospeed.maxupload.tooltip=La velocit\u00e0 di upload non sar\u00e0 incrementata automaticamente oltre questo limite. ConfigView.section.transfer.autospeed.chokeping=Choking ping time [msec] ConfigView.section.transfer.autospeed.chokeping.tooltip=Tempi di ping superiori a questo valore verranno considerati come indizio di saturazione della rete. ConfigView.section.transfer.autospeed.enableauto=Applica sia durante il download sia durante il seed ConfigView.section.transfer.autospeed.enableautoseeding=Applica solo durante il seed ConfigView.pluginlist.column.unloadable=Non caricabile ConfigView.section.transfer.lan.enable=Abilita limiti di velocit\u00e0 specifici per le connessioni LAN Plugin.localtracker.wellknownlocals=Includi automaticamente le reti locali di loopback/link/siti (192.168 etc) TableColumn.header.filesdone=File completati TableColumn.header.filesdone.info=File: completati/totali *oppure* completati/non saltati (per i torrent scaricati parzialmente). MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=In attesa dell'inizializzazione del DDB... MagnetPlugin.report.searching=ricerca in corso... MagnetPlugin.report.found=trovato %1 MagnetPlugin.report.alive=%1 \u00e8 vivo MagnetPlugin.report.dead=%1 \u00e8 morto MagnetPlugin.report.tunnel=tunnel in corso verso %1 MagnetPlugin.report.downloading=sto scaricando da %1 MagnetPlugin.report.error=errore %1 MagnetURLHandler.report.no_sources=nessuna fonte trovata per il torrent MagnetURLHandler.report.torrent_size=dimensione torrent: %1 MagnetURLHandler.report.percent=completato: %1% MagnetURLHandler.report.error=errore %1 DHTTransport.report.request_all=sto richiedendo l'intero trasferimento da %1 DHTTransport.report.received_bit=ricevuti bit da %1 a %2 da %3 DHTTransport.report.complete=completo DHTTransport.report.timeout=scaduto, nessuna risposta da %1 DHTTransport.report.rerequest_all=sto ripetendo la richiesta dell'intero trasferimento da %1 DHTTransport.report.rerequest_bit=sto ripetendo la richiesta dei bit da %1 a %2 a %3 DHTTransport.report.timeout_some=scaduto, %1 pacchetti ricevuti da %2, ma incompleti DHTTransport.report.sending=invio dati in corso DHTTransport.report.resending=reinvio i dati DHTTransport.report.send_complete=invio completo DHTTransport.report.send_timeout=invio scaduto ConfigView.section.transfer.autospeed.enabledebug=Registra le informazioni di debug TableColumn.header.date_added=Aggiunto il TableColumn.header.date_added.info=Data in cui il torrent \u00e8 stato aggiunto ConfigView.section.file.hashchecking.smallestfirst=Ricontrolla per primi i download pi\u00f9 piccoli platform.win32.baddll.info=Vuze ha rilevato la presenza di \u00ab%1\u00bb. Fa parte di \u00ab%2\u00bb e sappiamo che pu\u00f2 causare gravi problemi quali crash dell'applicazione o elevato utilizzo della CPU. Se ci\u00f2 si verifica, disinstallare il software o configurarlo in modo che non influisca su Vuze. upnp.ignorebaddevices=Ignora le periferiche che non rispondono correttamente upnp.ignorebaddevices.info=Dispositivi attualmente ignorati: %1 upnp.ignorebaddevices.reset=Ripristina l'elenco dei dispositivi ignorati upnp.ignorebaddevices.reset.action=Ripristina upnp.ignorebaddevices.alert=La periferica UPnP collocata in %1 verr\u00e0 ignorata in seguito a ripetuti tentativi di comunicazione non riusciti. Controllare la configurazione del plugin UPnP per opzioni riguardanti questa azione. TorrentOptionsView.param.max.uploads.when.busy=Velocit\u00e0 massima di upload quando \u00e8 stato raggiunto il limite globale di upload (KB/s) [0: disabilitato] UpdateMonitor.messagebox.verification.failed.title=Verifica di installazione fallita UpdateMonitor.messagebox.verification.failed.text=Verifica di \u00ab%1\u00bb fallita: %2 UpdateMonitor.messagebox.accept.unverified.title=Conferma installazione del plugin non verificato UpdateMonitor.messagebox.accept.unverified.text=\u00ab%1\u00bb non pu\u00f2 essere verificato come un plugin ufficiale di Vuze.\nSe si tratta di un plugin del genere NON si dovrebbe continuare.\nProcedere con l'installazione? FileView.BlockView.title=Parti di file FileView.BlockView.Done=Terminato FileView.BlockView.Skipped=Saltato FileView.BlockView.Active=Attivo FileView.BlockView.Outstanding=In attesa ConfigView.label.tcplistenport=Porta in ascolto TCP in entrata ConfigView.label.udplistenport=Porta in ascolto UDP upnp.portchange.alert=Le seguenti porte sono state cambiate per evitare problemi con dispositivi UPnP: %1 [vecchia porta=%2] %3 [vecchia porta=%4] ConfigView.section.proxy.username.info=Se il proxy richiede l'autenticazione anche quando non \u00e8 definita, usare la stringa \u00ab\u00bb come nome utente. ConfigView.label.maxuploadswhenbusymin=Ritardo per la modifica della velocit\u00e0 massima di upload dei torrent quando la velocit\u00e0 di upload globale supera il limite (sec) MainWindow.menu.help.debug=Genera informazioni di debug (registro del crash) DownloadManager.error.badsize=Dimensione non corretta natpmp.info=NAT-PMP \u00e8 l'alternativa per Apple a UPnP ed \u00e8 supportato dalle recenti stazioni Airport.\n\nNota che al momento UPnP dev'essere abilitato per poter abilitare NAT-PMP, in quanto la periferica NAT-PMP \u00e8 trattata come un particolare tipo di periferica UPnP. natpmp.enable=Abilita (nota: dev'essere abilitato anche nella configurazione del router Airport per funzionare) ConfigView.section.tracker.host.addurls=Assicurati che questi URL del tracker siano presenti nei torrent ospitati ConfigView.filter=digitare qui il filtro di ricerca ConfigView.section.files.move=Spostamento completati ConfigView.section.file.defaultdir.section=Opzioni cartella predefinita ConfigView.section.file.defaultdir.auto=Scarica automaticamente nella cartella predefinita (non chiedere) ConfigView.section.file.defaultdir.bestguess=Indovina il percorso pi\u00f9 probabile nello scegliere la cartella predefinita di salvataggio ConfigView.section.file.defaultdir.ask=Cartella predefinita: ConfigView.section.file.defaultdir.lastused=Aggiorna la cartella predefinita all'ultima posizione in cui si \u00e8 salvato ConfigView.section.file.config.section=Impostazioni di configurazione ConfigView.section.file.config.currentdir=Directory di configurazione corrente: ConfigView.section.torrent.decoding=Set di caratteri per la decodifica ConfigView.section.logging.udptransport=Abilita tracciamento prolisso del traffico UDP Tracker.announce.ignorePeerSeed=Ignora il conteggio peer/seed. %1 ConfigView.section.connection.encryption.use_crypto_port=Usa l'estensione del tracker \u00abcryptoport\u00bb per prevenire tentativi di connessione in entrata in chiaro.\nAlcuni tracker non lo supportano e restituiscono errori come \u00abPorta non valida\u00bb o \u00abArgomento non consentito\u00bb. TorrentOptionsView.param.reset.to.default=Riporta le opzioni ai valori predefiniti TorrentOptionsView.param.reset.button=Ripristina natpmp.routeraddress=Indirizzo stazione Airport [vuoto: automatico] ConfigView.section.style.disableAlertSliding=Disabilita scorrimento animato/rilievo per i messaggi di avviso ConfigView.section.transfer.autospeed.maxinc=Incremento massimo per ciclo (%1) ConfigView.section.transfer.autospeed.maxdec=Decremento massimo per ciclo (%1) ConfigView.section.transfer.autospeed.enabledownadj=Abilita la regolazione della velocit\u00e0 di download ConfigView.section.transfer.autospeed.downadjratio=Rapporto velocit\u00e0 Download : Upload (es. 2.0 => il limite di velocit\u00e0 di download sar\u00e0 il doppio di quello di upload) ConfigView.section.transfer.autospeed.latencyfactor=Fattore usato per associare i cambiamenti di latenza ai cambiamenti di velocit\u00e0 (valori maggiori riducono la sensibilit\u00e0). ConfigView.section.transfer.autospeed.reset=Ripristina i valori avanzati ConfigView.section.transfer.autospeed.reset.button=Ripristina PeerColumn.activationCount=Peer che provano a connettersi: %1 TableColumn.header.timesincedownload.info=Il tempo trascorso dall'ultimo scaricamento di dati del torrent TableColumn.header.timesincedownload=Tempo dal download TableColumn.header.timesinceupload.info=Il tempo trascorso dall'ultimo invio di dati del torrent TableColumn.header.timesinceupload=Tempo dall'upload PeersView.incomingreqcount=Rich. ingr. PeersView.incomingreqcount.info=Numero delle richieste in entrata fatte dal peer PeersView.outgoingreqcount=Rich. usc. PeersView.outgoingreqcount.info=Numero delle richieste in uscita fatte al peer upnp.mapping.trackerclientudp=Porta client UDP del tracker upnp.mapping.dhtudp=Database distribuito ConfigView.section.connection.nondata.udp.same=Usa la stessa porta UDP per il database distribuito e per il tracker UDP ConfigView.section.connection.tcp.enable=Abilita TCP ConfigView.section.connection.udp.enable=Abilita UDP ConfigView.section.style.showiconbar=Mostra barra degli strumenti MainWindow.menu.view.iconbar=Barra degli strumenti MyTorrentsView.menu.rename=Rinomina MyTorrentsView.menu.rename.displayed=Cambia il nome visualizzato MyTorrentsView.menu.rename.save_path=Cambia il percorso di salvataggio AdvRenameWindow.title=Rinominazione del torrent AdvRenameWindow.message=Inserire un nuovo nome per questo download. AdvRenameWindow.rename.torrent=Rinomina torrent MyTorrentsView.menu.rename.displayed.enter.title=Rinomina nome visualizzato MyTorrentsView.menu.rename.displayed.enter.message=Inserisci un nuovo nome da visualizzare per questo download. MyTorrentsView.menu.edit_comment=Modifica commento MyTorrentsView.menu.edit_comment.enter.title=Modifica del commento MyTorrentsView.menu.edit_comment.enter.message=Inserire un commento per questo download. UIDebugGenerator.messageask.title=Generatore di rapporti di debug UIDebugGenerator.messageask.text=Inserire una descrizione del bug che si sta segnalando. UIDebugGenerator.complete.title=Generazione del rapporto di debug completata UIDebugGenerator.complete.text=Il file di debug \u00e8 in \u00ab%1\u00bb.\n\nFare clic su OK per mostrare questo file. ConfigView.section.style.showProgramIcon=Mostra l'icona del programma nella colonna del nome ConfigView.section.style.showProgramIcon.tooltip=Potrebbe essere necessario riavviare per vederne gli effetti swt.alert.cant.update=La liberia SWT caricata da \u00ab%3\u00bb non pu\u00f2 essere aggiornata automaticamente dalla versione %1 alla %2 (dev'essere caricata da \u00ab%4\u00bb). Visitare il wiki (in inglese) per maggiori informazioni. authenticator.savepassword=Ricorda la password ConfigView.section.security.clearpasswords=Cancella le password memorizzate ConfigView.section.security.clearpasswords.button=Cancella Content.alert.notuploaded.title=Invio non completo Content.alert.notuploaded.text=L'invio di \u00ab%1\u00bb non \u00e8 completo. Se si decide di %2 ora, gli altri utenti non saranno in grado di scaricare completamente i contenuti multimediali pubblicati.\n\nSi \u00e8 sicuri di voler %2? Content.alert.notuploaded.multi.title=Upload non completi Content.alert.notuploaded.multi.text=%1 dei contenuti multimediali pubblicati non sono stati interamente inviati. Se si decide di %2 ora, gli altri utenti non saranno in grado di scaricare completamente i contenuti multimediali pubblicati. Si \u00e8 sicuri di voler %2?\n\nContenuti multimediali non interamente pubblicati:\n%3 Content.alert.notuploaded.stop=ferma Content.alert.notuploaded.quit=chiude Vuze TorrentInfoView.torrent.encoding=Codifica del torrent TorrentInfoView.columns=Colonne dalla vista \u00abI miei torrent\u00bb progress.window.title=Operazioni in corso progress.window.msg.filemove=Attendere il completamento dell'operazione di spostamento/rinomina. ConfigView.label.popup.timestamp=Aggiungi l'ora agli avvisi a comparsa ConfigView.label.popup.autohide=Nascondi automaticamente gli avvisi che non contengono errori dopo n secondi (imposta a 0 per disabilitare la funzione) ConfigView.label.popup.suppress_alerts=Disabilita gli avvisi ConfigView.label.popup.use_message_boxes=Usa finestre di dialogo invece degli avvisi a comparsa. ConfigView.label.popup.show=Mostra tutti gli avvisi a comparsa registrati fino a questo punto (se ce ne sono) ConfigView.label.popup.show.button=Mostra ConfigView.label.please.visit.here=Ulteriori informazioni (in inglese) ConfigView.section.ipfilter.enable.descriptionCache=Conserva le descrizioni degli IP nello scratch file ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Se disabilitata, le descrizioni non saranno memorizzate OpenTorrentWindow.filesInfo=Saranno scaricati %1 di %2. OpenTorrentWindow.diskUsage=%1 di %2 ConfigView.label.openmytorrents=Apri \u00abI miei torrent\u00bb all'avvio ConfigView.label.open_transfer_bar_on_start=Apri la barra dei trasferimenti all'avvio ConfigView.section.style.DNDalwaysInIncomplete=Mostra sempre i torrent parzialmente completi (contenenti file da \u00abNon Scaricare\u00bb) nella sezione \u00abIncompleti\u00bb di \u00abI miei torrent\u00bb OpenTorrentWindow.mb.noGlobalDestDir.title=Cartella di destinazione non valida OpenTorrentWindow.mb.noGlobalDestDir.text=La cartella di destinazione \u00ab%1\u00bb non \u00e8 valida. OpenTorrentWindow.mb.noDestDir.title=Cartella di destinazione non trovata o valida OpenTorrentWindow.mb.noDestDir.text=La cartella di destinazione \u00ab%1\u00bb per il torrent \u00ab%2\u00bb non esiste o non \u00e8 valida. OpenTorrentWindow.mb.notValid.title=Torrent non valido OpenTorrentWindow.mb.notValid.text=Impossibile aprire il torrent \u00ab%1\u00bb. Se lo si sta aprendo in modalit\u00e0 di seed, assicurarsi che i file dati del torrent esistano. OpenTorrentWindow.mb.notTorrent.title=Formato del file sconosciuto OpenTorrentWindow.mb.notTorrent.text=Impossibile aprire \u00ab%1\u00bb. Non sembra essere un file .torrent.\n\nAlcuni dati ricevuti:\n%2 ConfigView.label.pause.downloads.on.exit=Metti in pausa i download alla chiusura ConfigView.label.resume.downloads.on.start=Riprendi i download in pausa all'avvio, dopo l'inizializzazione UIDebugGenerator.message.cancel.title=Generazione delle informazioni di debug annullata UIDebugGenerator.message.cancel.text=Non si ha inserita una descrizione dell'errore che si sta cercando di segnalare. L'errore pu\u00f2 sembrare ovvio, ma senza una descrizione, noi possiamo solo immaginare qual'\u00e8 il problema.\n\nLa generazione delle informazioni di debug \u00e8 stata annullata. ConfigView.section.connection.group.http.info=Supporto per seed HTTP. ConfigView.section.connection.http.enable=Abilita ConfigView.section.connection.http.port=Numero porta di ascolto ConfigView.section.connection.http.portoverride=Sovrascrivi la porta HTTP del Tracker [0: non sovrascrivere] window.update.noupdates.title=Risultati del controllo degli aggiornamenti window.update.noupdates.text=Non ci sono aggiornamenti disponibili.\n\nCongratulazioni! ConfigView.label.bindip.details=Esempio: 192.168.1.5;eth0;eth1[2] assocer\u00e0 l'IP specificato a tutti gli indirizzi IP della prima interfaccia di rete e al terzo indirizzo IP della seconda interfaccia.\nIl primo IP sar\u00e0 impiegato per tutti i servizi, gli altri saranno usati solo per il bilanciamento del carico.\nSono disponibili le seguenti interfacce:\n%1 ConfigView.label.mindownloads=Numero minimo di download simultanei UI.cannot_submit_blank_text=Si deve immettere un valore. crypto.alert.as.warning=Il provider \u00ab%1\u00bb \u00e8 conosciuto imporre limiti sul traffico per ridurre le prestazioni di download. La cifratura del traffico \u00e8 stata abilitata automaticamente - pu\u00f2 essere disabilitata/modificata attraverso i parametri di configurazione. ConfigView.section.interface.alerts=Avvisi ConfigView.label.popupdownloadadded=Mostra un avviso quando viene aggiunto un download popup.download.added=\u00ab%1\u00bb \u00e8 stato aggiunto alla lista dei download. MessageBoxWindow.nomoreprompting=Non chiedere ancora TorrentOptionsView.param.max.seeds=Numero massimo di connessioni durante il seed [0: pari al limite di connessioni] TorrentOptionsView.param.alternative.value.enable=Valore alternativo quando si \u00e8 in seed ConfigView.section.proxy.check.on.start=Controlla lo stato del proxy all'avvio TransferStatsView.legend.pingaverage=Medio TransferStatsView.legend.ping1=Destinazione 1 TransferStatsView.legend.ping2=Destinazione 2 TransferStatsView.legend.ping3=Destinazione 2 ConfigView.section.interface.enabletray._mac=Abilita l'icona nella barra di stato [richiede riavvio] ConfigView.label.closetotray._mac=Il pulsante \u00abChiudi\u00bb minimizza sull'icona della Barra di stato ConfigView.label.minimizetotray._mac=Il pulsante \u00abRiduci a icona\u00bb minimizza sull'icona della Barra di stato OpenTorrentWindow.mb.existingFiles.title=File gi\u00e0 esistenti! OpenTorrentWindow.mb.existingFiles.text=Alcuni dei file esistono gi\u00e0 delle cartelle di destinazione specificate:\n\n%1\nSe si continua, Vuze controller\u00e0 se quei file contengono dati corretti e li sovrascriver\u00e0 se necessario. splash.unloadingTorrents=Unload dei torrent in corso splash.unloadingTorrent=Unload del torrent in corso ConfigView.section.file.defaultdir.autorename=Rinomina automaticamente i dati del torrent se i file nel percorso sembrano diversi ConfigView.section.file.defaultdir.autorename.tooltip=Impedisce a un torrent di sovrascrivere i file di un altro torrent quando i nomi coicidono alert.raised.at.close=(Messaggio dall'ultima chiusura di Vuze) Plugin.trackerpeerauth.name=Autorizzazione peer del tracker Plugin.trackerpeerauth.info=Questo plugin comunica coi tracker per verificare che i peer siano membri validi dello swarm. Peers.column.maxupspeed=Max UP Peers.column.maxdownspeed=Max DL MyTorrents.items.DownSpeedLimit.disabled=Nessun download upnp.selectedaddresses=Indirizzi (separati da \u00ab;\u00bb, il prefisso \u00ab-\u00bb significa nega, \u00ab+\u00bb significa consente) [vuoto: qualsiasi] upnp.alert.multipledevice.warning=Sono state rilevate pi\u00f9 periferiche UPnP. Controllare se tutte richiedono la mappatura delle porte (vedere il registro delle informazioni di UPnP e la configurazione). UpdateMonitor.messagebox.restart.title=Aggiornamento del software UpdateMonitor.messagebox.restart.text=Vuze ha appena completato il download di un importante aggiornamento e dev'essere riavviato affinch\u00e9 l'aggiornamento possa essere installato. PiecesView.BlockView.Have=Blocchi posseduti PiecesView.BlockView.NoHave=Blocchi non posseduti PiecesView.BlockView.Header=%1 colonna/e, %2 riga/e, %3 parti ConfigView.section.update.autodownload=Scarica automaticamente gli aggiornamenti e avvisa quando sono pronti per l'installazione Peers.column.peer_id=ID del peer Peers.column.peer_id.info=ID del peer in forma leggibile Peers.column.peer_byte_id=ID del peer Peers.column.peer_byte_id.info=ID del peer in byte Peers.column.handshake_reserved=Byte riservati per l'handshake Peers.column.handshake_reserved.info=Indica quali bit riservati sono stati impostati nell'handshake BitTorrent. Peers.column.client_identification=Identificazione del client Peers.column.client_identification.info=Indica i nomi base dei client riportati ad Vuze - utile per il debug. dht.warn.user=Avvisa in caso di potenziali problemi di NAT/mappatura di porte ConfigView.label.openbar.incomplete=Barre di progesso: apri in automatico per i download ConfigView.label.openbar.complete=apri in automatico per i seed ConfigView.label.transferbar.remember_location=Ricorda l'ultima posizione delle barre di trasferimento ConfigView.section.transfer.autospeed.forcemin=Forza questa velocit\u00e0 di upload mentre si stabilisce la connessione (%1) MainWindow.menu.tools.speedtest=Test della velocit\u00e0... speedtest.wizard.title=Test della velocit\u00e0 speedtest.wizard.run=Esegui un test della velocit\u00e0 speedtest.wizard.test.mode.updown=upload e download SpeedTestWizard.test.panel.currinfo=Test di banda BitTorrent. SpeedTestWizard.test.panel.label=Test della velocit\u00e0 di Vuze: SpeedTestWizard.test.panel.already.running=Test gi\u00e0 in esecuzione! SpeedTestWizard.test.panel.not.accepted=Richiesta del test non accettata: SpeedTestWizard.test.panel.abort=Annulla SpeedTestWizard.test.panel.abort.countdown=Il test sar\u00e0 annullato in: SpeedTestWizard.test.panel.test.countdown=Il test terminer\u00e0 in: SpeedTestWizard.test.panel.testfailed=Test non riuscito SpeedTestWizard.test.panel.aborted=Test annullato manualmente. SpeedTestWizard.test.panel.enc.label=Premere per la cifratura: SpeedTestWizard.test.panel.encrypted=cifrato SpeedTestWizard.set.upload.button.apply=Applica SpeedTestWizard.set.upload.result=Risultati dell'ultimo test SpeedTestWizard.set.upload.bytes.per.sec=KB/s SpeedTestWizard.set.upload.bits.per.sec=bit/s SpeedTestWizard.finish.panel.title=Test della velocit\u00e0 terminato! SpeedTestWizard.finish.panel.click.close=Test della velocit\u00e0 completato. Fare clic su Chiudi per uscire. SpeedTestWizard.finish.panel.max.upload=Upload max : SpeedTestWizard.finish.panel.max.seeding.upload=Max upload durante il seed : SpeedTestWizard.finish.panel.max.download=Download max : SpeedTestWizard.finish.panel.enabled=abilitato SpeedTestWizard.finish.panel.disabled=disabilitato SpeedTestWizard.abort.message.scheduled.in=test pianificato fra... %1 secondi SpeedTestWizard.abort.message.unsupported.type=Tipo di test non supportato!!!! SpeedTestWizard.abort.message.manual.abort=Annullato manualmente SpeedTestWizard.abort.message.scheduling.failed=Pianificazione del test non riuscita SpeedTestWizard.abort.message.download.added=\u00c8 stato aggiunto il download %1 durante il test. SpeedTestWizard.abort.message.entered.error=Il download di test \u00e8 entrato nello stato di errore \u00ab%1\u00bb. SpeedTestWizard.abort.message.entered.queued=Il download di test \u00e8 entrato nello stato In coda/Fermato. SpeedTestWizard.abort.message.interrupted=TorrentSpeedTestMonitorThread \u00e8 stato interrotto prima del completamento del test. SpeedTestWizard.abort.message.execution.failed=Esecuzione del test non riuscita. SpeedTestWizard.abort.message.failed.peers=Impossibile connettersi ai peer. SpeedTestWizard.abort.message.insufficient.slots=Non \u00e8 stato possibile effettuare l'upload verso alcun peer - forse gli slot di upload sono insufficienti. SpeedTestWizard.abort.message.not.unchoked=Non \u00e8 stato possibile effettuare il download da nessuno dei peer perch\u00e9 non hanno mai effettuato l'unchoke. SpeedTestWizard.stage.message.requesting=richiesta del test... SpeedTestWizard.stage.message.preparing=preparazione test... SpeedTestWizard.stage.message.starting=avvio test... SpeedTestWizard.stage.message.connect.stats=Statistiche di connessione: peer=%1, down_ok=%2, up_ok=%3 window.uiswitcher.title=Selettore di interfaccia di Vuze window.uiswitcher.text=Scegliere l'interfaccia utente che meglio si adatta alle proprie esigenze tra quelle elencate di seguito. window.uiswitcher.NewUI.text=* Raccomandata per i principianti e i nuovi utenti.\n\n* Un'interfaccia grafica semplice e intuitiva\n\n* Necessaria per pubblicare contenuti multimediali nella piattaforma Vuze window.uiswitcher.ClassicUI.title=Interfaccia classica window.uiswitcher.ClassicUI.text=* Mantiene le funzionalit\u00e0 dei client della serie 2.x\n\n* Il modulo per i contenuti multimediali di Vuze non sar\u00e0 caricato window.uiswitcher.bottom.text=Si pu\u00f2 cambiare facilmente la scelta con il pulsante Selettore di interfaccia di Vuze. iconBar.switch.tooltip=Selettore di interfaccia di Vuze VivaldiView.notAvailable=Vista Vivaldi non disponibile restart.error=Riavvio non riuscito:\n%1\nVedere restarting issues (in inglese) per maggiori informazioni. restart.error.oom=Memoria insufficiente restart.error.fnf=\u00ab%1\u00bb non trovato in \u00ab%2\u00bb restart.error.pnf=Percorso \u00ab%1\u00bb non trovato restart.error.bad=Formato del file \u00ab%1\u00bb errato restart.error.denied=Accesso negato nel tentativo di eseguire \u00ab%1\u00bb. Assicurarsi di avere le autorizzazioni necessarie per eseguire il programma. TableColumn.header.date_completed=Completato il TableColumn.menu.date_added.reset=Resetta la data ConfigView.section.ipfilter.discardbanning=Blocca i peer il cui rapporto dati danneggiati/integri supera [0: disabilitato] ConfigView.section.ipfilter.discardminkb=Applica il rapporto dopo aver scaricato questa quantit\u00e0 di dati danneggiati (%1) ConfigView.interface.start.advanced=Avvia con l'interfaccia avanzata (AZ 2.x) MyTorrents.column.ColumnQuality=Qualit\u00e0 MyTorrents.column.ColumnSpeed=Velocit\u00e0 MyTorrents.column.ColumnProgressETA.2ndLine=Al termine: %1 MyTorrents.column.ColumnProgressETA.StreamReady=Pronto per lo streaming MyTorrents.column.ColumnProgressETA.PlayableIn=Riproducibile in %1 TableColumn.header.Quality=Qualit\u00e0 TableColumn.header.Speed=Velocit\u00e0 TableColumn.header.RateIt=Il tuo voto TableColumn.header.Rating=Valutazione TableColumn.header.SpeedGraphic=Velocit\u00e0 TableColumn.header.AzProduct=Da TableColumn.header.MediaThumb=Materiale TableColumn.header.ProgressETA=Progresso TableColumn.header.name.ext=Tipo di file: %1 v3.MainWindow.tab.browse=Su Vuze v3.MainWindow.tab.library=Libreria v3.MainWindow.tab.publish=Pubblica v3.MainWindow.tab.advanced=Avanzate v3.MainWindow.menu.browse=&Su Vuze v3.MainWindow.menu.library=&Libreria v3.MainWindow.menu.publish=&Pubblica v3.MainWindow.menu.advanced=&Avanzate v3.MainWindow.menu.view.searchbar=Barra di Ricerca v3.MainWindow.menu.view.tabbar=Barra dei Tab v3.MainWindow.currentDL=In download v3.MainWindow.button.stream=Fai lo stream v3.MainWindow.button.stop=Ferma v3.MainWindow.button.start=Avvia v3.MainWindow.button.pause=Pausa v3.MainWindow.button.resume=Riprendi v3.MainWindow.button.delete=Elimina v3.MainWindow.button.comment=Commento v3.MainWindow.button.viewdetails=Vedi dettagli v3.MainWindow.button.play=Riproduci v3.MainWindow.button.cancel=Annulla v3.MainWindow.button.preview=Anteprima v3.MainWindow.view.wait=Inizializzazione dell'interfaccia, attendere. v3.MainWindow.xofx=%1 di %2 v3.MainWindow.Loading=Caricamento in corso... attendere v3.filter-bar=Filtro Titolo: v3.MainWindow.search.defaultText=cerca... v3.mb.delPublished.title=Smetti di fare il seed del contenuto multimediale v3.mb.delPublished.text=ATTENZIONE: Questa azione NON rimuover\u00e0 il contenuto multimediale \u00ab%1\u00bb pubblicato da %3.\n\nFare clic su \u00abElimina\u00bb solo se si vuole che rimanga pubblicato e scaricabile, ma si vuole liberare la banda. Assicurarsi che il processo di upload sia stato completato prima di farlo (come?).\n\nFare clic su \u00abRimuovi\u00bb se si vuole rimuovere completamente da %3 il contenuto multimediale pubblicato, e usare il pulsante (X) del pannello Contenuto pubblicato nel tab Pubblica.\n\nUlteriori informazioni.\n\n v3.mb.delPublished.delete=&Elimina v3.mb.delPublished.cancel=&Rimuovi v3.mb.openFile.title=Apri file v3.mb.openFile.text.known=Questo contenuto multimediale non \u00e8 correntemente supportato dal riproduttore di Vuze. Visitare la Playback guide (in inglese) creata dalla comunit\u00e0 per maggiori informazioni.\n\nIl tipo del file sembra essere: %2 (%3)\n v3.mb.openFile.text.unknown=Questo contenuto multimediale non \u00e8 correntemente supportato dal riproduttore di Vuze. Visitare la Playback guide (in inglese) creata dalla comunit\u00e0 per maggiori informazioni.\n\nEstensione del file: %2\n v3.mb.openFile.button.play=Riproduci v3.mb.openFile.button.cancel=Annulla v3.mb.openFile.button.guide=Leggi la guida alla riproduzione v3.mb.openFile.remember=Apri sempre i file senza chiedere v3.mb.PlayFileNotFound.title=File non trovato v3.mb.PlayFileNotFound.text=I file per \u00ab%1\u00bb sono stati cancellati o sono mancanti. v3.mb.PlayFileNotFound.button.remove=Rimuovi da Vuze v3.mb.PlayFileNotFound.button.redownload=Scarica di nuovo v3.mb.PlayFileNotFound.button.find=Trova manualmente.. v3.mb.deletePurchased.title=Rimozione di contenuti multimediali acquistati v3.mb.deletePurchased.text=Eliminare \u00ab%1\u00bb?\n\nQuesto \u00e8 un contenuto multimediale acquistato, o per il quale era richiesto l'accesso per poter effettuare il download. v3.mb.deletePurchased.button.delete=&Elimina v3.mb.deletePurchased.button.cancel=&Annulla v3.topbar.menu.show.plugin=Area plugin v3.topbar.menu.show.search=Cerca splash.initializeCore=Inizializzazione del core splash.initializeUIElements=Inizializzazione degli elementi dell'interfaccia ConfigView.section.transfer.autospeedbeta=Auto-speed - beta ConfigView.section.ipfilter.peerblocking.group=Blocco dei peer ConfigView.section.ipfilter.autoload.group=Caricamento automatico ConfigView.section.ipfilter.autoload.file=Filtro IP da caricare automaticamente ConfigView.section.ipfilter.autoload.info=Supporta i formati DAT (eMule), P2P (PeerGuardian, splist), e P2B v1,2,3 (PeerGuardian 2). I file possono essere locali oppure URL, con estesione zip, gzip o testo semplice. Le URL saranno automaticamente scaricate/aggiornate ogni 7 giorni, mentre i file saranno ricaricati entro un minuto dalla modifica/sostituzione. ConfigView.section.ipfilter.autoload.loadnow=Carica adesso splash.loadIpFilters=Caricamento dei filtri IP... SpeedTestWizard.set.upload.title=Impostazione dei limiti di upload e download SpeedTestWizard.set.download.label=Limite della velocit\u00e0 di download: SpeedTestWizard.set.upload.label=Limite della velocit\u00e0 di upload: SpeedTestWizard.name.conf.level.absolute=Assoluto SpeedTestWizard.name.conf.level.high=Alto SpeedTestWizard.name.conf.level.med=Medio SpeedTestWizard.name.conf.level.low=Basso SpeedTestWizard.name.conf.level.none=Nessuno mb.azmustclose.title=Errore di avvio mb.azmustclose.text=Vuze sar\u00e0 terminato per un problema di (ri)avvio che molto probabilmente ha causato l'esecuzione del programma con privilegi di Amministratore.\n\nDopo la chiusura, si prega di riaprire Vuze manualmente. network.ipv6.prefer.addresses=Preferisci gli indirizzi IPv6 quando sono disponibili sia IPv6 che IPv4 network.bindError=L'associazione al socket del server non \u00e8 riuscita perch\u00e9 non sono disponibili indirizzi compatibili. Controllare le impostazioni di associazione agli IP. network.enforce.ipbinding=Forza le associazioni di IP anche quando le interfacce non sono disponibili. Impedisce qualsiasi connessione se nessuna delle interfacce specificate \u00e8 disponibile. DHTView.title.full_v6=Database distribuito IPv6 ConfigView.pluginlist.loadSelected=Carica plugin selezionato SpeedView.stats.asn=Rete: SpeedView.stats.estupcap=Limite di upload: SpeedView.stats.estdowncap=Limite di download: SpeedView.stats.unknown=Sconosciuto SpeedView.stats.estimate=Stima SpeedView.stats.measured=Misurato SpeedView.stats.measuredmin=Min misurato SpeedView.stats.manual=Fisso ConfigView.section.transfer.autospeed.networks=Dettagli rete ConfigView.section.transfer.autospeed.resetnetwork=Ripristina dettagli rete ConfigView.section.transfer.autospeed.network.info=I limiti in alto di norma sono calcolati automaticamente durante il download o come risultato di un test di velocit\u00e0. Se si vuole specificarli manualmente, si devono usare le opzioni in basso.\nTutti i limiti eccetto quelli \u00abFissi\u00bb saranno regolati automaticamente in caso di necessit\u00e0. \nInserire il valore e scegliere il suo tipo. Notare che le velocit\u00e0 sono espresse in %1. dialog.uiswitcher.restart.title=Selettore di interfaccia: riavvio di Vuze necessario dialog.uiswitcher.restart.text=Per cambiare l'interfaccia utente \u00e8 nesessario riavviare Vuze. TrayWindow.menu.close=Chiudi il cesto dei download # Used for peers which we can't determine. PeerSocket.unknown=Sconosciuto PeerSocket.fake_client=FALSO PeerSocket.bad_peer_id=peer ID non valido PeerSocket.mismatch_id=non corrispondente PeerSocket.unknown_az_style=Sconosciuto %1/%2 PeerSocket.unknown_shadow_style=Sconosciuto %1/%2 OpenTorrentWindow.mb.askCreateDir.title=Cartella di destinazione inesistente OpenTorrentWindow.mb.askCreateDir.text=La cartella di destinazione \u00ab%1\u00bb non esiste.\n\nCrearla ora? SpeedView.stats.estimatechoke=Stima (choke) ConfigTransferAutoSpeed.upload.capacity.usage=Uso della capacit\u00e0 di upload ConfigTransferAutoSpeed.mode=Modalit\u00e0: ConfigTransferAutoSpeed.capacity.used=% della capacit\u00e0 usata ConfigTransferAutoSpeed.while.downloading=In download: ConfigTransferAutoSpeed.set.dht.ping=Impostazioni di ping del DHT: ConfigTransferAutoSpeed.set.point=imposta punto (ms) ConfigTransferAutoSpeed.set.tolerance=tolleranza (ms) ConfigTransferAutoSpeed.ping.time.good=Buono: ConfigTransferAutoSpeed.ping.time.bad=Cattivo: ConfigTransferAutoSpeed.adjustment.interval=Intervallo di aggiornamento: ConfigTransferAutoSpeed.skip.after.adjust=Ignora dopo la modifica: GeneralView.label.distributedCopies=Copie distribuite : PiecesView.DistributionView.title=Distribuzione delle parti PiecesView.DistributionView.NoAvl=Parti non disp. PiecesView.DistributionView.SeedAvl=Contributo disp. seed PiecesView.DistributionView.PeerAvl=Contributo disp. peer PiecesView.DistributionView.RarestAvl=Parti pi\u00f9 rare: %1 (disp:%2) PiecesView.DistributionView.weHave=Parti che possiedi PiecesView.DistributionView.theyHave=Parti possedute dal peer PiecesView.DistributionView.weDownload=Parti che stai scaricando PeersView.gain=Guadagno PeersView.gain.info=La differenza tra i dati scaricati e quelli inviati unix.script.new.title=Nuovo script di avvio di Vuze disponibile unix.script.new.text=\u00c8 disponibile un nuovo script di avvio di Vuze ed \u00e8 stato salvato in \u00ab%1\u00bb.\n\nSi raccomanda vivamente di uscire da Vuze adesso e di passare al nuovo script (\u00ab%2\u00bb).\n\nSe si ha modificato pesantemente lo script di avvio di Vuze visitare AzureusWiki: Unix Script (in inglese).\n\nSe si ha installato Vuze da una disribuzione (yum, apt-get, etc), raccomandiamo di re-installare Vuze usando il pacchetto nella Pagina di Vuze su Sourceforge (Si manterr\u00e0 la stessa interfaccia di adesso). unix.script.new.button.quit=Esci adesso unix.script.new.button.continue=Lo far\u00f2 in seguito unix.script.new.button.asknomore=Non dirmelo pi\u00f9 unix.script.new.auto.title=Nuovo script di avvio di Vuze unix.script.new.auto.text=\u00c8 disponibile un nuovo script di avvio di Vuze.\n\nSi raccomanda fortemente di riavviare Vuze adesso. Content.alert.notuploaded.button.stop=&Interrompi Content.alert.notuploaded.button.continue=&Continua il seed Content.alert.notuploaded.button.abort=&Non uscire ConfigView.label.checkOnSeeding=Esegui ricontrollo delle parti a basso consumo di risorse se in seed ConfigView.label.ui_switcher=Mostra il selettore di interfaccia di Vuze ConfigView.label.ui_switcher_button=Mostra SpeedTestWizard.test.panel.explain=Misura la velocit\u00e0 del protocollo del client Vuze. Scegliere il tipo di test di velocit\u00e0 e la modalit\u00e0 di cifratura. Visitare la pagina del wiki di Vuze per dettagli su questo test. Il test sar\u00e0 interrotto automaticamente nel caso richieda pi\u00f9 di due minuti. Normalmente il test dura meno di un minuto. SpeedTestWizard.set.upload.hint=Impostare i limiti di upload e download usati dall'algoritmo Auto-speed di Vuze. SpeedTestWizard.set.upload.panel.explain=I limiti qui impostati sono usati dall'algoritmo Auto-speed di Vuze. Impostare i limiti di trasferimento e di confidenza.\n\nNotare che spesso le velocit\u00e0 delle linee spesso sono espresse in \u00abbit per secondo\u00bb, mentre il valore mostrato qui sotto \u00e8 in \u00abkilobyte per secondo\u00bb. SpeedTestWizard.set.limit.conf.level=Confidenza SpeedTestWizard.finish.panel.auto.speed=Valore di Auto-speed : SpeedTestWizard.finish.panel.auto.speed.seeding=Valore di Auto-speed durante il seed : ConfigTransferAutoSpeed.add.comment.to.log.group=Aggiungi commento al registro di debug ConfigTransferAutoSpeed.add.comment.to.log=Aggiungi commento: ConfigTransferAutoSpeed.log.button=Salva ConfigTransferAutoSpeed.algorithm.selector=Selettore di Auto-speed (velocit\u00e0 automatica) ConfigTransferAutoSpeed.algorithm=Algoritmo: ConfigTransferAutoSpeed.auto.speed.classic=Auto-speed (classico) ConfigTransferAutoSpeed.auto.speed.beta=Auto-speed (beta) ConfigTransferAutoSpeed.data.update.frequency=Frequenza di aggiornamento Alert.failed.update=L'installazione di almeno un componente non \u00e8 riuscita. Visitare AzureusWiki: Failed Update (in inglese). [%1] OpenTorrentWindow.mb.existingFiles.partialList=(Lista parziale. Ci sono altri file che esistono gi\u00e0.) TableColumn.header.bad_avail_time.info=L'ultima volta che \u00e8 stata disponibile una copia completa del download TableColumn.header.bad_avail_time=Visto completo MyTorrentsView.menu.exporthttpseeds=Esporta le URL dei seed HTTP negli appunti SWT.alert.erroringuithread=Si \u00e8 verificato un errore non gestito nell'interfaccia, altri errori potrebbero essere notificati in seguito. ConfigView.label.minannounce=Intervallo di tempo minimo tra gli annunci del tracker (sec) ConfigView.label.maxnumwant=Limita il numero di peer restituiti dal tracker ConfigView.label.announceport=Sovrascrivi la porta TCP annunciata dal tracker per gli annunci dei tracker, PEX e DHT\n[vuota: non sovrascrivere la porta, 0: disabilita le connessioni in entrata] ConfigView.label.noportannounce=Non rivelare la porta d'ascolto al tracker (questo non influenza PEX e DHT) ConfigView.label.maxseedspertorrent=Numero massimo di seed per torrent [0: illimitato] wizard.webseed=Aggiungi seed HTTP al torrent wizard.webseed.title=Seed HTTP wizard.webseed.configuration=Configurazione seed HTTP wizard.webseed.adding=Aggiunta seed HTTP GeneralView.label.private=Torrent privato: GeneralView.yes=S\u00ec ConfigView.label.userequestlimiting=Per limitare la velocit\u00e0 di download, limita le richieste invece di usare le letture ritardate [non ha effetto quando la velocit\u00e0 di download \u00e8 illimitata] ConfigView.label.userequestlimiting.tooltip=La limitazione delle richieste \u00e8 un metodo pi\u00f9 rozzo rispetto alle letture ritardate, ma permette di gestire la priorit\u00e0 dei download in base alla posizione in coda e pu\u00f2 migliorare le prestazioni della rete ConfigView.label.userequestlimitingpriorities=Concentra la velocit\u00e0 di download sui torrent in cima alla coda quando viene raggiunto il limite di velocit\u00e0 di download ConfigView.section.logging.timestamp=Applica formato della data ai file di registro Peers.column.timetocomplete=Tempo rimanente Peers.column.timetocomplete.info=Tempo rimanente al completamento per il peer ConfigView.section.interface.display.suppress.file.download.dialog=Disabilita l'avviso a comparsa per i download ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Mostra l'avanzamento di tutti i download nella barra di stato invece dell'avviso a comparsa FileDownload.canceled=Il download di un file torrent \u00e8 stato annullato con successo per intervento dell'utente: %1 Progress.reporting.status.canceled=Annullato Progress.reporting.status.finished=Finito Progress.reporting.status.retrying=Sto ritentando... Progress.reporting.action.label.retry.tooltip=Ritenta l'operazione Progress.reporting.action.label.remove.tooltip=Rimuovi questa operazione dalla cronologia Progress.reporting.action.label.cancel.tooltip=Annulla l'operazione Progress.reporting.action.label.detail=Dettagli Progress.reporting.default.error=Non riuscito Progress.reporting.no.reports.to.display=Non ci sono operazioni in corso da mostrare. Progress.reporting.no.history.to.display=Non ci sono messaggi di dettaglio da mostrare. Progress.reporting.detail.history.limit=Il limite dei messaggi di dettaglio (%1) per questa operazione \u00e8 stato superato; i messaggi successivi non saranno aggiunti alla cronologia. Progress.reporting.statusbar.button.tooltip=Mostra la finestra Operazioni in corso webui.bindip=IP a cui associare - normalmente non richiesto (*) v3.MainWindow.text.log.in=Accedi v3.MainWindow.text.log.out=Esci v3.MainWindow.text.get.started=Registrati v3.MainWindow.text.my.account=Informazioni sull'account v3.MainWindow.text.my.profile=Profilo OpenTorrentWindow.simple.open=Posizione del torrent (file, URL, hash) Progress.reporting.window.remove.auto=Rimuovi automaticamente gli elementi inattivi Progress.reporting.window.remove.auto.tooltip=Rimuove automaticamente dall'elenco tutti i processi completati, non riusciti o annullati. Progress.reporting.window.remove.now=Rimuovi dall'elenco gli elementi inattivi Progress.reporting.window.remove.now.tooltip=Rimuove dall'elenco tutti i processi completati, non riusciti o annullati dhttracker.tracklimitedwhenonline=In ogni caso, quando si \u00e8 online, eseguire il tracking a basso uso di risorse per la swarm cross-population TorrentOptionsView.multi.title.short=Opzioni del torrent TorrentOptionsView.multi.title.full=Opzioni del torrent MyTorrentsView.menu.open_parent_folder=Apri la cartella ConfigView.section.style.use_show_parent_folder=Usa \u00ab%1\u00bb invece di \u00ab%2\u00bb nei menu dei torrent ConfigView.section.style.use_show_parent_folder.tooltip=Abilitando questa opzione si potr\u00e0 aprire la cartella superiore con il corretto file manager.\nTuttavia potrebbe impedire la selezione automatica della cartella di salvataggio. PeerManager.status.ps_disabled=La sorgente dei peer \u00e8 disabilitata per questo tracker. ConfigView.section.stats.exportfiles=Esporta i dettagli dei file updater.cant.write.to.app.title=Impossibile scrivere nella cartella Programmi. updater.cant.write.to.app.details=La cartella \u00ab%1\u00bb non \u00e8 accessibile in scrittura.\n\nQuesto impedir\u00e0 agli aggiornamenti futuri di essere applicati.\n\nVisitare il wiki (in inglese) per maggiori informazioni. plugin.install.class_version_error=Questo plugin richiede una versione pi\u00f9 aggiornata di Java per funzionare. v3.MainWindow.tab.minilibrary=Download v3.MainWindow.tab.events=Attivit\u00e0 button.columnsetup.tooltip=Configuazione delle colonne v3.activity.remove.title=Rimozione dell'avviso v3.activity.remove.text=Cancellare questo avviso? v3.MainWindow.menu.file.closewindow=Chiudi Menu.show.torrent.menu=Mostra il menu Torrent Menu.show.torrent.menu.tooltip=Mostra il menu Torrent sulla barra superiore dell'applicazione Views.plugins.aznetstatus.title=Stato della rete plugin.aznetstatus.pingtarget=Obbiettivo di ping/traceroute ConfigView.section.style.usePathFinder=Usa \u00abCerca percorso\u00bb invece di \u00abCerca\u00bb menu.sortByColumn=Ordina per %1 MyTorrentsView.menu.manual.per_peer=Manuale (per peer) MyTorrentsView.menu.manual.shared_peers=Manuale (su pi\u00f9 peer) v3.button.removeActivityEntry=Rimuovi notifica v3.splash.initSkin=Inizializzazione tema dell'interfaccia v3.splash.hookPluginUI=Aggancio nell'interfaccia del plugin OpenTorrentWindow.mb.notTorrent.cannot.display=Impossibile visualizzare correttamente i dati. MainWindow.menu.window.zoom.maximize=Ingrandisci MainWindow.menu.window.zoom.restore=Ripristina ImageResizer.image.too.small=L'immagine fornita \u00e8 troppo piccola, sceglierne una diversa (dev'essere almeno %1 x %2) ImageResizer.title=Questo strumento consente di regolare l'aspetto delle anteprime sulla piattaforma Vuze ImageResizer.move.image=Muovere l'immagine trascinandola col mouse ImageResizer.move.image.with.slider=Muovere l'immagine trascinandola, ridimensionarla usando il cursore in basso security.crypto.title=Accesso alla chiave di cifratura security.crypto.encrypt=Inserire una password per proteggere la chiave di cifratura appena creata. Non dimenticare questa password, altrimenti non ci sar\u00e0 modo di recuperarla! security.crypto.decrypt=Inserire la password per sbloccare la chiave di cifratura. security.crypto.reason=Motivo dell'operazione security.crypto.password2=Reintroduci la password security.crypto.persist_for=Durata password security.crypto.persist_for.dont_save=Non salvare security.crypto.persist_for.session=Per questa sessione security.crypto.persist_for.day=1 giorno security.crypto.persist_for.week=1 settimana security.crypto.persist_for.30days=30 giorni security.crypto.persist_for.forever=Per sempre security.crypto.password.mismatch.title=Password non coincidenti security.crypto.password.mismatch=Le password non coincidono, digitarle di nuovo. ConfigView.section.security.group.crypto=Chiavi publiche/private ConfigView.section.security.resetkey=Cancella le chiavi ConfigView.section.security.resetkey.warning.title=Avviso di perdita dati ConfigView.section.security.resetkey.warning=Si vogliono davvero cancellare le chiavi di cifratura? Se lo si fa, tutte le informazioni cifrate usandole saranno PERDUTE PER SEMPRE. Inoltre, qualsiasi altro peer in possesso della tua chiave pubblica non sar\u00e0 pi\u00f9 in grado di comunicare con te se prima non otterr\u00e0 la nuova chiave. Quindi, a meno che non si sappia esattamente cosa si sta facendo, non farlo. ConfigView.section.security.unlockkey=Sblocca chiavi esplicitamente ConfigView.section.security.unlockkey.button=Sblocca ConfigView.section.security.publickey=Chiave pubblica ConfigView.section.security.publickey.undef=Non ancora definito ConfigView.section.security.resetkey.error.title=Operazione non riuscita ConfigView.section.security.resetkey.error=Impossibile cancellare le chiavi ConfigView.section.security.unlockkey.error=Sblocco chiave non riuscito - password non corretta ConfigView.copy.to.clipboard.tooltip=Copia negli appunti Views.plugins.azbuddy.title=Amici Browser.popup.error.no.access=Si \u00e8 verificato un errore durante un tentativo di accesso a una risorsa remota.\nProvare pi\u00f9 tardi.\n ConfigView.label.queue.stoponcebandwidthmet=Non far partire altri torrent quando \u00e8 stato raggiunto il limite di upload/download ConfigView.section.style.forceMozilla=Forza Vuze a usare Mozilla per gli widget del browser [richiede xulrunner o firefox 3, e il riavvio] ConfigView.section.style.xulRunnerPath=Specifica manualmente il percorso di XulRunner / Firefox [richiesto per FF3; richiede il riavvio] azbuddy.name=Amici azbuddy.enabled=Abilitato azbuddy.disabled=Il plugin \u00e8 disabilitato, vedere la configurazione del plugin per modificare qui. azbuddy.nickname=Nome utente azbuddy.msglog.title=Informazioni sull'amico azbuddy.addtorrent.title=Accettare il download? azbuddy.addtorrent.msg=L'amico \u00ab%1\u00bb ha inviato \u00ab%2\u00bb.\nAggiungere questo download? azbuddy.contextmenu=Invia ad un amico azbuddy.ui.mykey=La mia chiave: azbuddy.ui.add=Aggiungi azbuddy.ui.new_buddy=Nuova chiave dell'amico: azbuddy.ui.table.name=Nome azbuddy.ui.table.online=In linea azbuddy.ui.table.last_msg=Ultimo messaggio azbuddy.ui.menu.remove=Rimuovi azbuddy.ui.menu.copypk=Copia la chiave pubblica azbuddy.ui.menu.send=Invia il messaggio azbuddy.ui.menu.send_msg=Inserisci il testo da inviare all'amico/agli amici. azbuddy.ui.menu.ygm=Invia YGM azbuddy.ui.menu.enc=Crittografa gli appunti azbuddy.ui.menu.dec=Decritta gli appunti azbuddy.ui.menu.sign=Firma gli appunti azbuddy.ui.menu.verify=Verifica gli appunti azbuddy.ui.table.lastseen=Visto per l'ultima volta Button.retry=&Riprova Button.ignore=&Ignora azbuddy.ui.table.msg_in=Mess. in ingresso azbuddy.ui.table.msg_out=Mess. in uscita v3.MainWindow.menu.view.footer=Riquadro in basso azbuddy.downspeed=Velocit\u00e0 massima di download per gli amici (KB/s) [0: unlimited] security.crypto.badpw=La password inserita \u00e8 errata. ConfigView.section.security.backupkeys=Fai il backup delle chiavi in un file ConfigView.section.security.restorekeys=Ripristina le chiavi da file ConfigView.section.security.restorekeys.button=Ripristina ConfigView.section.security.op.error.title=Impossibile completare l'operazione ConfigView.section.security.op.error=Impossiblie completare l'operazione:\n %1 ConfigView.section.security.restart.title=Riavvio richiesto ConfigView.section.security.restart.msg=Vuze sar\u00e0 riavviato per completare l'operazione. ConfigView.section.security.system.managed=Protezione delle chiavi gestita dal sistema azbuddy.ui.table.msg_queued=In coda azbuddy.chat.title=Chat di Vuze azbuddy.chat.says=%1 dice: Button.bar.show=Visualizza Button.bar.hide=Nascondi Button.bar.share=Condividi Button.bar.add=Aggiungi Button.bar.edit=Modifica Button.bar.edit.cancel=Modifica eseguita v3.MainWindow.menu.view.pluginbar=Barra dei plugin MainWindow.dialog.select.vuze.file=Selezione di un file Vuze MainWindow.menu.file.open.vuze=File Vuze... metasearch.addtemplate.title=Conferma installazione del template di ricerca metasearch.addtemplate.desc=Installare il template di ricerca \u00ab%1\u00bb? v3.share.private.title=Condivisione di torrent v3.share.private.text=Il torrent selezionato \u00e8 marcato come privato.\n\nNon si possono condividere i torrent privati. metasearch.addtemplate.dup.title=Template gi\u00e0 installato metasearch.addtemplate.dup.desc=Il template di ricerca %1 \u00e8 gia installato. metasearch.export.select.template.file=Salva template metasearch.import.select.template.file=Apri template dialog.uiswitch.title=Usa l'interfaccia Vuze dialog.uiswitch.text=\u00c8 necessario usare l'interfaccia Vuze per usare questa funzione.\n\n\u00c8 necessario riavviare Vuze. dialog.uiswitch.button=Usa l'interfaccia Vuze azbuddy.tracker.enabled=Abilitare l'\u00abAccelerazione degli amici\u00bb per dare priorit\u00e0 ai download degli amici. azbuddy.protocolspeed=Massima velocit\u00e0 per il protocollo relativo agli amici (KB/s) v3.MainWindow.button.run=Esegui il file scaricato v3.activity.header.downloads=Download v3.activity.header.vuze.news=Notizie su Vuze message.taking.too.long=L'operazione in corso sta prendendo pi\u00f9 tempo del previsto.\nPremere \u00abESC\u00bb per annullarla. message.status.success=Successo azbuddy.tracker.bbb.status.title=Accelerazione degli amici azbuddy.tracker.bbb.status.title.tooltip=Fare doppio clic per i dettagli azbuddy.tracker.bbb.status.idle=Nessuna accelerazione azbuddy.tracker.bbb.status.nli=Autenticazione richiesta azbuddy.tracker.bbb.status.in=Si \u00e8 accelerati azbuddy.tracker.bbb.status.out=Amici che stanno accelerando il download v3.MainWindow.search.go.tooltip=Esegui ricerca v3.MainWindow.search.last.tooltip=Torna ai risultati di ricerca metasearch.addtemplate.done.title=Template aggiunto metasearch.addtemplate.done.desc=Il template \u00ab%1\u00bb \u00e8 stato aggiunto con successo.\nSar\u00e0 usato nelle prossime ricerche. ConfigView.section.security.nopw=Nessuna password inserita ConfigView.section.security.nopw_v=Nessuna password disponibile, fare l'accesso a Vuze fileplugininstall.install.title=Installare il plugin? fileplugininstall.install.desc=Installare la versione %2 del plugin \u00ab%1\u00bb? fileplugininstall.duplicate.title=Plugin duplicato fileplugininstall.duplicate.desc=La versione %2 del plugin \u00ab%1\u00bb \u00e8 gi\u00e0 installata azbuddy.online_status=Stato azbuddy.os_online=In linea azbuddy.os_away=Non al computer azbuddy.os_not_avail=Non disponibile azbuddy.os_busy=Occupato azbuddy.os_offline=Non in linea azbuddy.ui.menu.disconnect=Disconnetti azbuddy.enable_chat_notif=Abilita le notifiche per la chat progress.window.msg.progress=Attendere il completamento dell'operazione. ConfigView.section.connection.advanced.read_select= ConfigView.section.connection.advanced.read_select_min=Lettura: attesa minima (ms, valore predefinito %1) ConfigView.section.connection.advanced.write_select=Scrittura: timeout (ms, valore predefinito %1) ConfigView.section.connection.advanced.write_select_min=Scrittura: attesa minima (ms, valore predefinito %1) DetailedListView.title=Lista dettagliata ConfigView.section.connection.network.max.outstanding.connect.attempts=Numero massimo di connessioni in uscita in attesa plugins.init.force_enabled=Vuze ha rilevato che il plugin \u00ab%1\u00bb \u00e8 stato disabilitato. \u00c8 stato abilitato nuovamente per permettere a Vuze di funzionare correttamente. ConfigView.section.connection.prefer.udp=Preferisci le connessioni UDP subscript.add.title=Installare l'iscrizione? subscript.add.desc=Installare l'iscrizione \u00ab%1\u00bb? subscript.add.dup.title=Iscrizione gi\u00e0 installata subscript.add.dup.desc=L'iscrizione \u00ab%1\u00bb \u00e8 gi\u00e0 installata. subscript.add.upgrade.title=Aggiornare l'iscrizione? subscript.add.upgrade.desc=Aggiornare l'iscrizione \u00ab%1\u00bb? subscript.add.upgradeto.desc=La versione %1 dell'iscrizione \u00ab%2\u00bb \u00e8 disponibile.\nLa si vuole aggiornare? azsubs.contextmenu.addassoc=Aggiungi iscrizione azsubs.contextmenu.lookupassoc=Vedi le iscrizioni correnti iconBar.start=Avvia iconBar.stop=Ferma iconBar.remove=Rimuovi iconBar.up=Su iconBar.down=Gi\u00f9 iconBar.run=Apri iconBar.editcolumns=Configurazione delle colonne iconBar.top=Sposta in alto iconBar.bottom=Sposta in basso iconBar.queue=Avvia iconBar.open=Aggiungi un torrent iconBar.share=Condividi iconBar.share.tooltip=Condividi contenuti multimediali iconBar.details=Dettagli iconBar.comment=Commento iconBar.play=Riproduci iconBar.queue.tooltip=Avvia (metti in coda) i torrent selezionati v3.MainWindow.menu.view.sidebar=Barra laterale v3.MainWindow.menu.view.actionbar=Barra delle azioni v3.MainWindow.menu.view.toolbars=Barre degli strumenti ump.install=Aggiornamento veloce in corso:\nSto installando un piccolo componente aggiuntivo necessario alla riproduzione di questo video. subscriptions.listwindow.title=Ricerca delle iscrizioni subscriptions.listwindow.autochecktext=Vuze pu\u00f2 trovare le iscrizioni relative ai contenuti multimediali nella Libreria. Abilitare questa funzione? subscriptions.listwindow.loadingtext=Ricerca in corso delle iscrizioni relative a %1 subscriptions.listwindow.failed=Nessuna iscrizione trovata subscriptions.listwindow.popularity=Popolarit\u00e0 subscriptions.listwindow.popularity.unknown=Sconosciuta subscriptions.listwindow.name=Nome subscriptions.listwindow.subscribe=Iscriviti TableColumn.header.azsubs.ui.column.subs=Iscriviti subscriptions.listwindow.popularity.reading=Ricevo... PluginDeprecation.log.start=Questa finestra contiene informazioni relative all'uso da parte dei plugin di funzionalit\u00e0 che saranno rimosse nelle versioni future di Vuze.\nNon \u00e8 necessario disinstallare il plugin, basta aggiornarlo all'ultima versione disponibile.\nSe si sta gi\u00e0 usando l'ultima versione disponibile, copiare il contenuto di questa finestra in un post del forum:\n \t%1\n\n PluginDeprecation.log.details=---------\nIDENTIFICATORE: %1\nCONTESTO: %2\n\n*** INIZIO TRACCIAMENTO ***\n%3*** FINE TRACCIAMENTO ***\n\n PluginDeprecation.view=Debug dei plugin PluginDeprecation.alert=Un plugin ha cercato di usare delle funzionalit\u00e0 che saranno rimosse in futuro - aprire il registro delle informazioni di debug dei plugin per maggiori informazioni. TableColumn.header.Thumbnail=Icona TableColumn.header.Thumbnail.info=L'icona per i contenuti multimediali di Vuze; per gli altri contenuti sono visualizzate le icone del sistema operativo. v3.MainWindow.menu.getting_started=&Per iniziare MainWindow.menu.community=&Comunit\u00e0 MainWindow.menu.help.faq=Domande &frequenti (FAQ) MainWindow.menu.community.wiki=&Wiki della comunit\u00e0 MainWindow.menu.community.forums=Fo&rum della comunit\u00e0 MainWindow.menu.community.blog=&Blog di Vuze MainWindow.menu.help.support=&Aiuto e supporto externalLogin.title=Accesso richiesto externalLogin.explanation=\u00c8 necessario eseguire l'accesso per il template \u00ab%1\u00bb. Una volta effettuato l'accesso, questa finestra si chiuder\u00e0 automaticamente. Se dovesse rimanere aperta, fare clic su \u00abFatto\u00bb. externalLogin.explanation.capture=\u00c8 necessario eseguire l'accesso per creare questo template. Dopo averlo fatto, fare clic su \u00abFatto\u00bb. Button.done=Fatto GeneralView.torrent_created_on_and_by=%1 di %2 Button.continue=Continua Button.preview=Anteprima Subscription.menu.forcecheck=Aggiorna ora Subscription.menu.clearall=Segna tutti i risultati come letti Subscription.menu.remove=Elimina sidebar.Library=Libreria sidebar.LibraryDL=In download sidebar.LibraryCD=Completato authenticator.location=Posizione authenticator.details=Dettagli v3.MainWindow.menu.showActionBarText=Visualizza testo subscript.import.fail.title=Importazione non riuscita subscript.import.fail.desc=Settagli: %1 Subscription.menu.export=Esporta subscript.export.select.template.file=Salva iscrizione Button.remove=Rimuovi Button.send=Invia Button.back=Indietro sidebar.LibraryUnopened=Da vedere TableColumn.header.unopened=Nuovo Unopened.bigView.header=Nuovi Subscription.menu.deleteall=Elimina tutti i risultati Subscription.menu.reset=Ripristina lo stato iniziale ConfigView.section.Subscriptions=Iscrizioni subscriptions.config.maxresults=Numero massimo di risultati mantenuti per ogni iscrizione [0: illimitati] v3.activity.button.readall=Segna tutti come letti TableColumn.header.activityNew=Nuovo TableColumn.header.activityType=Tipo TableColumn.header.activityText=Messaggio TableColumn.header.activityDate=Data di aggiunta TableColumn.header.activityActions=Azioni Subscription.menu.resetauth=Ripristina i dettagli di autenticazione Search.menu.engines=Template Wizard.Subscription.title=Iscriviti Wizard.Subscription.optin.title=Abilita le iscrizioni Wizard.Subscription.subscribe.title=Iscrizioni disponibili Wizard.Subscription.create.title=Crea una nuova iscrizione Button.search=Cerca Button.save=Salva Button.add=Aggiungi Button.createNewSubscription=Nuova iscrizione Button.availableSubscriptions=Iscrizioni disponibili Wizard.Subscription.optin.description=Quando le iscrizioni sono abilitate, Vuze visualizzer\u00e0 le iscrizioni relative ai torrent nella libreria e avviser\u00e0 quando \u00e8 disponibile per il download un nuovo contenuto multimediale.\n\nAbilitare le iscrizioni? Wizard.Subscription.create.search=Cerca Wizard.Subscription.search.subtitle1=Digitare una ricerca per iniziare a creare l'iscrizione: Wizard.Subscription.search.subtitle2=Cosa posso cercare? Wizard.Subscription.search.subtitle2.sub1=Film in HD, serie TV, film, trailer nel network di Vuze Wizard.Subscription.search.subtitle2.sub2=Torrent provenienti dal Web Wizard.Subscription.search.subtitle3=Quando l'iscrizione sar\u00e0 completa, si riceveranno in tempo reale aggiornamenti nella barra laterale quando saranno disponibili nuovi risultati per la ricerca. Wizard.Subscription.rss.subtitle1=Digita o incolla l'URL qui sotto: Wizard.Subscription.rss.subtitle2=Molti produttori di contenuti multimediali mettono a disposizione un feed RSS. Trova l'URL nel sito del produttore, copia e incolla l'URL nel campo sopra e fai clic su Salva. Wizard.Subscription.rss.subtitle3=Una volta salvato, si riceveranno aggiornamenti in tempo reale nella barra laterale quando saranno disponibili nuovi risultati attraverso il feed RSS. Wizard.Subscription.subscribe.library=Contenuti multimediali nella libreria Wizard.Subscription.subscribe.subscriptions=Iscrizioni correlate Wizard.Subscription.subscribe.library.empty=Non ci sono iscrizioni disponibili?\n \nCercare i pulsanti arancioni per l'iscrizione nella rete HD di Vuze.\n \nMaggiori informazioni message.confirm.delete.title=Conferma dell'eliminazione message.confirm.delete.text=Eliminare \u00ab%1\u00bb? Subscription.menu.properties=Propriet\u00e0 props.window.title=Propriet\u00e0 di \u00ab%1\u00bb subs.prop.is_auto=Scarica automaticamente i nuovi risultati subs.prop.last_scan=Ultimo aggiornamento completato con successo subs.prop.last_result=Ultimo risultato trovato subs.prop.last_error=Ultimo errore subs.prop.num_read=Numero dei risultati letti subs.prop.num_unread=Numero dei risultati non letti subs.prop.auth=Richiesta l'autenticazione externalLogin.auth_method_proxy=Usa il metodo esteso di cattura del cookie. Se questo non funziona, disabilitare l'opzione e riprovare. externalLogin.wait=Caricamento pagina in corso, attendere... TableColumn.menu.date_added.time=Visualizza/Nascondi il tempo sidebar.VuzeHDNetwork=Rete HD di Vuze subs.prop.next_scan=Prossima scansione prevista subs.prop.assoc=Associazioni subs.prop.version=Versione subscriptions.column.new.info=Indica se ci sono nuovi risultati subscriptions.column.name=Iscrizione subscriptions.column.nb-results=Risultati totali subscriptions.column.nb-new-results=Nuovi risultati subscriptions.column.last-checked=Ultimo controllo subscriptions.view.title=Iscrizioni subs.prop.is_public=Pubblico subs.prop.high_version=Versione pi\u00f9 recente incontrata Subscription.menu.upgrade=Abilita l'aggiornamento alle versioni successive metasearch.template.version.bad=Il template di ricerca \u00ab%1\u00bb non pu\u00f2 essere installato finch\u00e9 non si aggiorna Vuze. metasearch.addtemplate.failed.title=Installazione non riuscita metasearch.addtemplate.failed.desc=Installazione del template di ricerca %1 non riuscita. subscription.version.bad=L'iscrizione \u00ab%1\u00bb non pu\u00f2 essere installata finch\u00e9 non si aggiorna Vuze. statusbar.feedback=Invia commento statusbar.feedback.tooltip=Fare clic qui per inviare un commento sidebar.Activity=Notifiche v3.activity.button.watchall=Segna tutti come visti subscriptions.view.help.1=Iscriviti quando vedi subscriptions.view.help.2=Ottieni aggiornamenti in tempo reale quando sono disponibili per il download nuovi contenuti multimediali. Maggiori informazioni (in inglese). sidebar.sash.tooltip=Premere F7 per nascondere/visualizzare la barra laterale. sidebar.expand.tooltip=Espandi la barra laterale sidebar.dropdown.tooltip=Visualizza la barra laterale nel formato menu subscript.all.subscribed=Si \u00e8 iscritti a questi contenuti multimediali subscript.some.subscribed=Si \u00e8 iscritti ad alcune delle iscrizioni disponibili per questo contenuto multimediale.\nFare clic per vedere le altre disponibili. subscript.none.subscribed=Fare clic per vedere le iscrizioni disponibili per questo contenuto multimediale v3.iconBar.up.tooltip=Sposta su\nTenere premuto il pulsante del mouse per spostare all'inizio. v3.iconBar.down.tooltip=Sposta gi\u00f9\nTenere premuto il pulsante del mouse per spostare in fondo. TableColumn.header.azsubs.ui.column.subs_link=Associazione TableColumn.header.azsubs.ui.column.subs_link.info=Associato alle iscrizioni Button.deleteContent.fromLibrary=Rimuovi dalla libreria Button.deleteContent.fromComputer=Elimina dal computer v3.deleteContent.message=\nSi vuole eliminare \u00ab%1\u00bb dal computer o solo rimuoverlo dalla libreria di Vuze? v3.MainWindow.menu.view.toolbartext=Descrizioni nella barra degli strumenti v3.MainWindow.menu.view.asSimpleList=Lista semplice v3.MainWindow.menu.view.asAdvancedList=Lista avanzata v3.MainWindow.menu.view.statusbar=Barra di stato Subscription.menu.dirtyall=Segna tutti i risultati come non letti configureWizard.file.message3=Vuze scaricher\u00e0 i file in una cartella specifica, selezionarla qui: v3.deleteContent.applyToAll=Applica l'azione agli %1 elementi selezionati ConfigView.label.seeding.firstPriority.ignoreIdleHours=Torrent che non inviano nulla per v3.MainWindow.menu.contentnetworks=&Reti HD v3.MainWindow.menu.contentnetworks.about=Informazioni sulle reti HD Peers.column.as.info=Dettagli sul sistema autonomo (AS) del peer ConfigTransferAutoSpeed.auto.speed.neural=Neurale (Gudy Alpha) ConfigView.label.autoopen.downloadbars=Apri automaticamente le barre di download per ConfigView.label.autoopen=Apertura automatica ConfigView.label.autoopen.detailstab=Apri automaticamente la scheda Dettagli per ConfigView.label.autoopen.dl=I download ConfigView.label.autoopen.cd=I seed ConfigView.label.systray=Vassoio di sistema ConfigView.label.systray._mac=Icona della barra di stato ConfigView.section.interface.legacy=Vecchio stile v3.MainWindow.menu.contentnetworks.manage=&Gestisci le reti HD azbuddy.ui.table.loc_cat= azbuddy.ui.menu.cat=Categorie azbuddy.ui.menu.cat.share=Abilita le iscrizioni con l'amico/gli amici azbuddy.ui.menu.cat.set=Inserisci le categorie azbuddy.ui.menu.cat.set_msg=Lista di categorie separata da spazio, o \u00abAll\u00bb azbuddy.ui.menu.cat_subs=Iscriviti subs.prop.update_period=Periodo di aggiornamento azbuddy.enable_cat_pub=Categorie pubbliche a cui TUTTI gli amici possono iscriversi (separate da \u00ab,\u00bb) v3.dialog.cnclose.title=%1 chiuso v3.dialog.cnclose.subtitle=Notifica v3.dialog.cnclose.info1=\u00c8 stata chiusa una rete in HD. v3.dialog.cnclose.info2=Se si vuole aprire di nuovo questa rete in HD, lo si pu\u00f2 fare dal menu \u00abReti in HD\u00bb nella parte alta dello schermo. v3.dialog.cnclose.noshow=Non mostrare ancora v3.dialog.cnmanage.title=Menu di gestione delle reti HD v3.dialog.cnmanage.intro=Si possono selezionare nella lista sotto i network da visualizzare nel menu \u00abReti HD\u00bb. TableColumn.header.#=N\u00b0 TableColumn.header.#.info=Posizione/Numero d'ordine TableColumn.header.category.info=Nome della categoria a cui il torrent appartiene TableColumn.header.DateCompleted.info=La data in cui \u00e8 stato completato lo scaricamento del torrent TableColumn.header.AzProduct.info=Rete di contenuti multimediali da cui \u00e8 stato originato il torrent TableColumn.header.health.info=Quanto \u00e8 buona la connessione allo swarm del torrent TableColumn.header.maxuploads.info=Numero massimo di peer a cui inviare contemporaneamente TableColumn.header.name.info=Nome del torrent TableColumn.header.unopened.info=Indica se il torrent \u00e8 stato riprodotto (aperto) TableColumn.header.savepath.info=La cartella o il file di destinazione per i dati del torrent TableColumn.header.SeedingRank.info=Punteggio che indica quanto il torrent ha bisogno di seed. I valori pi\u00f9 alti indicano un maggiore bisogno. TableColumn.header.shareRatio.info=Quanto si \u00e8 inviato (condiviso) in confronto a quanto si \u00e8 scaricato. TableColumn.header.size.info=Dimensione dei dati del torrent su disco TableColumn.header.azsubs.ui.column.subs.info=Pulsante che permette di iscriversi a feed contenenti torrent correlati TableColumn.header.upspeed.info=Velocit\u00e0 attuale di upload TableColumn.header.downspeed.info=Velocit\u00e0 di download attuale TableColumn.header.up.info=Quantit\u00e0 di dati inviati ad altri utenti TableColumn.header.down.info=Quantit\u00e0 di dati ricevuta dagli altri utenti TableColumn.header.ProgressETA.info=Combina lo stato, il completamento, il tempo rimasto e la velocit\u00e0 di download in una sola colonna, a pi\u00f9 righe TableColumn.header.eta.info=Tempo stimato prima del termine del download Pieces.column.#=N\u00b0 Pieces.column.#.info=Numero della parte Peers.column.%.info=La percentuale del torrent scaricata dal peer TableColumn.header.download.info=Quantit\u00e0 di dati ricevuta dal peer TableColumn.header.upload.info=Quantit\u00e0 di dati inviata al peer TableColumn.header.downloadspeed.info=Velocit\u00e0 dello scaricamento dal peer TableColumn.header.uploadspeed.info=Velocit\u00e0 attuale di invio dati al peer TableColumn.header.lan.info=Indica se il peer \u00e8 nella LAN TableColumn.header.downloadspeedoverall.info=Velocit\u00e0 di scaricamento stimata del peer Peers.column.pieces.info=Barra grafica che rappresenta i pezzi scaricati dal peer TableColumn.header.TableColumnNameInfo=Nome e descrizione della colonna TableColumn.header.TableColumnSample=Esempio TableColumn.header.TableColumnInfo=Descrizione della colonna TableColumn.header.TableColumnChosenColumn=Colonne scelte subs.prop.is_auto_ok=Permetti lo scaricamento automatico label.learnmore=Maggiori informazioni ColumnSetup.title=Configurazione delle colonne per \u00ab%1\u00bb ColumnSetup.explain=Scorrere tra le colonne disponibili sulla sinistra, e aggiungerle alla lista delle colonne visibili sulla destra. Si pu\u00f2 espandere o ridurre la lista delle colonne disponibili usando la sezione Filtra in basso a sinistra. Sono supportati anche il trascinamento e le scorciatoie da tastiera. ColumnSetup.chosencolumns=Colonne scelte ColumnSetup.proficiency=Abilit\u00e0: ColumnSetup.categories=Categorie: ColumnSetup.filters=Filtri ColumnSetup.availcolumns=Disponibili %1 colonne ColumnSetup.availcolumns.filteredby=Sono disponibili %1 colonne, filtrate in base a %2 devices.view.title=Dispositivi device.renderer.view.title=Renderer device.mediaserver.view.title=Server per contenuti multimediali device.router.view.title=Router device.model.desc=Descrizione del modello device.model.name=Nome del modello device.model.num=Numero del modello device.manu.desc=Produttore device.router.is_mapping=Mappatura automatica delle porte device.router.req_map=Mappaggi richiesti device.router.configure=Configura UPnP device.mediaserver.configure=Configurazione del server multimediale device.hide=Nascondi dispositivo device.show=Visualizza i dispositivi nascosti device.search=Cerca dei dispositivi device.router.con_type=Connessione: %1 device.browse=Sfoglia device.upnp.desc_url=Descrizione del dispositivo device.upnp.present_url=Amministrazione del dispositivo ConfigView.label.maxStalledSeeding=Numero massimo di torrent \u00abin stallo\u00bb [0: illimitato] device.search.auto=Cerca automaticamente i dispositivi devices.sidebar.simple=Vista semplice devices.xcode.working_dir=Area di conversione devices.xcode.prof_def=Profilo di conversione predefinito devices.xcode.profs=Profili di conversione disponibili device.lastseen=Visto per l'ultima volta devices.contextmenu.xcode=Converti per un dispositivo devices.device=Dispositivo devices.profile=Profilo General.percent=Per cento devices.installed=Installato devices.comp.missing=Supporto Vuze non installato devices.state=Stato MainWindow.menu.help.donate=&Fai una donazione DonationWindow.noload.title=Donazione DonationWindow.noload.text=Caricamento della finestra delle donazioni non riuscito. Riprovare pi\u00f9 tardi. devices.xcode.only.show=Visualizza solo i file convertiti nel dispositivo device.quit.transcoding.title=Conversione in corso device.quit.transcoding.text=\u00ab%1\u00bb sta venendo codificato in \u00ab%2\u00bb ed \u00e8 completo al %3%.\nSe si esce ora, al prossimo avvio la codifica dovr\u00e0 ricominciare dall'inizio. download.removerules.unauthorised.data=\tElimina i dati device.config.xcode.maxbps=Velocit\u00e0 massima di conversione (KB/s) [0: illimitata] device.xcode=Converti device.xcode.always=Sempre device.xcode.whenreq=Quando richiesto device.xcode.never=Mai devices.copy.pending=Copia dei file in attesa devices.sidebar.hide.rend.generic=Nascondi i dispositivi generici v3.devicesview.infobar.text2=Per convertire file per un certo dispositivo, trascinarli dalla libreria nel dispositivo. Per vedere le conversioni completate, fare clic sul dispositivo a destra. iconBar.transcode=Dispositivo iconBar.transcode.tooltip=Rendi disponibili dei contenuti multimediali ad un dispositivo device.retry.copy=Riprova a copiare devices.copy.fail=Impossibile copiare nel dispositivo devices.on.demand=Su richiesta devices.ready=Pronto TableColumn.header.trancode_qpos=N\u00b0 TableColumn.header.trancode_qpos.info=Posizione nella coda di conversione TableColumn.header.profile=Dispositivo TableColumn.header.profile.info=Profilo di conversione in uso TableColumn.header.copied=Copiato TableColumn.header.device=Dispositivo TableColumn.header.device.info=Dispositivo destinazione TableColumn.header.trancode_completion=Progresso della conversione # This is the beginning of the word "View". It's right aligned under the icon bar item v3.iconBar.view.big.tooltip=Visualizza come lista semplice # This is the end of the word "View". It's left aligned under the icon bar item v3.iconBar.view.small=sualizza v3.iconBar.view.small.tooltip=Visualizza come lista avanzata general.dont.ask.again=Non chiedere ancora general.na.short=N/D v3.menu.device.exploreTranscodes=Visualizza file v3.menu.device.exploreTranscodes._windows=Visualizza in Explorer v3.menu.device.exploreTranscodes._mac=Visualizza nel Finder v3.menu.device.defaultprofile=Profilo di default devices.button.installitunes=Installa l'integrazione con iTunes device.itunes.install=\u00c8 necessario installare iTunes device.itunes.start=\u00c8 necessario avviare iTunes o abilitarne l'avvio automatico device.itunes.install_problem=Sembra esserci un problema con l'integrazione con iTunes devices.downloading=Download in corso TableColumn.header.duration=Durata TableColumn.header.resolution=Risoluzione devices.xcode.autoStart=Avvia automaticamente se richiesto option.askeverytime=Chiedi sempre option.rememberthis=Ricorda la scelta devices.associate=Associa con devices.associate.already=Gi\u00e0 associato devices.always.cache=Metti in cache i file non convertiti devices.turnon.prepageload=Per attivare questa funzione, \u00e8 necessaria l'installazione di componenti aggiuntivi. devices.turnon.itunes=Includi il supporto per iTunes (necessario per i dispositivi Apple) devices.turnon.qos=Condividi le statistiche anonime del dispositivo con Vuze devices.turnon.title=Attiva il supporto al dispositivo devices.choose.device.title=Selezionare un dispositivo di riproduzione per questo video: devices.choose.profile.info.text=Dopo la selezione, Vuze rilever\u00e0 automaticamente se il formato video \u00e8 compatibile con il dispositivo, e ne creer\u00e0 una copia compatibile se necessario.\n\nTenere il puntatore del mouse sul dispositivo scelto per maggiori informazioni. devices.choose.profile.info.title.selected=Dettagli di %1: devices.view.heading=Contenuti multimediali da convertire per un dispositivo device.view.heading=Contenuti multimediali per %1 devices.choose.device.info.title=Suggerimento per i dispositivi devices.choose.device.info.text=La prossima volta, trascina semplicemente i file scelti sul dispositivo desiderato nella barra laterale. label.clickone=Fai clic su uno Button.turnon=Attiva ConfigView.label.dm.dblclick=Doppio clic nelle viste dei torrent: ConfigView.option.dm.dblclick.play=Riproduci ConfigView.option.dm.dblclick.details=Apri la scheda Dettagli del torrent ConfigView.option.dm.dblclick.show=Mostra file ConfigView.option.dm.dblclick.show._mac=Mostra file nel Finder ConfigView.option.dm.dblclick.show._windows=Mostra file in Explorer subscriptions.column.auto-download=Download automatico xcode.deletedata.title=Eliminazione dei file convertiti xcode.deletedata.message=Eliminare permanentemente la copia di \u00ab%1\u00bb convertita per \u00ab%2\u00bb%3? xcode.deletedata.message.2=\n(una copia potrebbe ancora esistere in \u00ab%1\u00bb) v3.deviceview.infobar.line1=Trascina i video dalla libreria al dispositivo scelto. v3.deviceview.infobar.line2=Riproduci i video su tutti i tuoi dispositivi: iPhone, iPod e TV. v3.deviceview.infobar.line1.generic=Trascina i video dalla libreria a %1 nella barra laterale. v3.deviceview.infobar.line2.itunes=I video appariranno nella cartella Video di iTunes quando saranno pronti ad essere riprodotti. v3.deviceview.infobar.line2.xbox=Fare lo streaming di video andando in \u00abLa mia XBox -> Libreria video -> Vuze\u00bb v3.deviceview.infobar.line2.ps3=Fare lo streaming di video andando in \u00abVideo -> Vuze\u00bb nella PS3 devices.copy_url=Copiare l'URL dello stream negli appunti devices.converting=Conversione in corso Button.reload=Ricarica devices.auto.start=Avvia automaticamente Subscription.menu.setcookies=Imposta i cookie general.enter.cookies=Cookie dell'elemento device.config.xcode.workdir=Cartella di lavoro predefinita per i file convertiti MyTorrentsView.menu.clear_alloc_data=Elimina i dati dell'allocazione DiskManager.error.nospace=Spazio su disco insufficiente DiskManager.error.nospace_fat32={DiskManager.error.nospace} - vedere {wiki.fat32} (in inglese) per maggiori informazioni. ConfigView.section.file.rename.incomplete=Aggiungi suffisso ai file incompleti subscriptions.config.auto=Scarica automaticamente subscriptions.config.autostartdls=Avvia automaticamente i download quando vengono aggiunti (al posto di metterli nello stato Fermato) subscriptions.config.autostart.min=Avvia solo se >= MB [0: illimitato] subscriptions.config.autostart.max=Avvia solo se <= MB [0: illimitato] dlg.corewait.title=Inizializzo il motore principale dlg.corewait.text=Attendere...\n\nLa richiesta verr\u00e0 processata dopo l'inizializzazione di Vuze. library.core.wait=Attendere...\nInizializzazione del client Vuze in corso ConfigView.label.StartUIBeforeCore=Apri l'interfaccia prima dell'inizializzazione general.add.friends=Aggiungi i tuoi amici! general.all.friends=Tutti gli amici friend.mod.subs=Fare clic con il pulsante destro del mouse per modificare le iscrizioni TableColumn.header.class=Classe device.rss.group=Feed RSS locale devices.xcode.rsspub=Pubblica feed RSS device.rss.enable=Crea un feed RSS dai contenuti multimediali convertiti - li rende disponibili ai lettori di feed RSS device.rss.port=Porta del feed RSS device.rss.view=Fare clic per vedere il feed RSS device.rss.localonly=Limita l'accesso solo a questo computer rcm.rc_tracker.tt=Fare clic aprire il tracker nel browser rcm.rc_hash.tt=Fare clic per scaricare questo contenuto multimediale rcm.rc_title.tt=Fare clic per cercare questo contenuto multimediale devices.xcode.autoCopy=Copia automaticamente nella cartella devices.xcode.setcopyto=Imposta la cartella in cui copiare... devices.xcode.setcopyto.title=Imposta la posizione in cui copiare devices.copy.folder.auto=Copia automaticamente i file nella cartella devices.copy.folder.dest=Copia nella cartella TableColumn.menu.maxuploads=N\u00b0 Max di upload devices.xcode.mancopy=Copia i file manualmente devices.xcode.show.cat=Separa in base alla categoria ConfigView.label.alwaysShowLibraryHeader=Visualizza sempre l'intestazione nella libreria (I miei torrent) devices.cat.show=Visualizza categorie devices.tivo.machine=Nome della macchina TiVo devices.info.copypending=%1 file sono in attesa di essere copiati. device.error.xcodefail=Conversione non riuscita device.error.copyfail=La copia di uno o pi\u00f9 file nella cartella non \u00e8 riuscita. device.error.copytonotset=\u00abCopia nella cartella\u00bb Non impostato device.error.copytomissing=\u00abCopia nella cartella\u00bb \u00ab%1\u00bb Non trovata device.error.copytonowrite=\u00abCopia nella cartella\u00bb \u00ab%1\u00bb Non \u00e8 possibile scrivere nella cartella device.error.copyfail2=La copia di uno o pi\u00f9 file nel dispositivo non \u00e8 riuscita. v3.deviceview.infobar.line2.tivo=Per fare lo stream di video basta selezionare Vuze nella lista In riproduzione del TiVo. v3.deviceview.infobar.line2.psp=I video verranno copiati nella PSP quando verr\u00e0 connessa. devices.info.copypending2=%1 file sono in attesa di essere copiati, connettere il dispositivo. subscriptions.column.nb-subscribers=Sottoscrittori device.offlinedownloader.view.title=Scaricamento non il linea device.od.enable=Abilita i dispositivi per lo scaricamento non in linea device.odauto.enable=Gestisci automaticamente i download device.odpt.enable=Includi i torrent privati devices.contextmenu.od=Scaricamento non in linea devices.contextmenu.od.auto= devices.contextmenu.od.enable=Abilita devices.contextmenu.od.enabled=Abilitato devices.od.view.heading=Download pianificati per lo scaricamento non in linea DevicesOD.column.od_completion=Progresso del trasferimento devices.od.idle=Pronto device.od.turnon.title=Abilita il supporto allo scaricamento non in linea device.is.disabled=Il dispositivo \u00e8 disabilitato device.configure=Configura... device.od.error.notfound=Il dispositivo non \u00e8 connesso device.od.error.opfailstatus=Il dispositivo non \u00e8 riuscito a completare il comando %1: stato %2 device.od.error.opfailexcep=Il dispositivo non \u00e8 riuscito a completare il comando %1: eccezione %2 device.od.error.nospace=Il dispositivo \u00e8 pieno o non connesso device.od.space=Spazio disponibile ConfigView.section.style.forceSIValues=Forza la visualizzazione dei valori come IEC, senza considerare l'unit\u00e0 di visualizzazione, per retro-compatibilit\u00e0 (per es. 1MB = 1MiB = 1048576B) ConfigView.label.enableSystrayToolTip=Visualizza le statistiche sui download quando ci si sofferma con il mouse sull'icona devices.activation=Attivazione dispositivi button.nothanks=No, grazie devices.od.turnon.text1=Vuze ha rilevato che si \u00e8 connesso un %1. devices.od.turnon.text2=Vuoi che il %1 continui a scaricare i file quando il computer non \u00e8 in linea? devices.od.turnon.text3=Connettere un hard disk al %1 per abilitare questa funzione. devices.od.turnon.learn=Maggiori informazioni > devices.od=Programma per il download non in linea webui.pairingenable=Abilita l'associazione webui.group.access=Controllo dell'accesso ConfigView.section.Pairing=Accoppiamento pairing.accesscode=Codice di accesso pairing.ac.getnew=Assegna un nuovo codice di accesso pairing.ac.getnew.create=Crea pairing.ipv4=Indirizzo IPv4 pairing.ipv6=Indirizzo IPv6 pairing.host=Indirizzo dell'host (nome DNS) pairing.group.explicit=Dati espliciti pairing.explicit.enable=Abilita pairing.explicit.info=Normalmente, non \u00e8 necessario specificare esplicitamente i dati IP, perch\u00e9 possono essere determinati automaticamente.\nL'attributo \u00abhost\u00bb pu\u00f2 essere usato, ad esempio, se si \u00e8 registrati a DynDNS e si \u00e8 installato il client per tenere registrato l'IP dinamico. pairing.op.fail=Associazione non riuscita pairing.alloc.fail=L'assegnazione del nuovo codice di accesso non \u00e8 riuscita.\n%1 pairing.enable=Abilita l'associazione di Vuze con le interfacce/applicazioni remote pairing.status.info=Stato pairing.status.registered=Aggiornamento completato (%1) pairing.status.pending=L'aggiornamento verr\u00e0 effettuato alle %1 pairing.status.initialising=Inizializzo pairing.status.disabled=Disabilitato pairing.view.registered=Fare clic per vedere i dettagli della registrazione attuale webui.pairing.info.n=L'associazione \u00e8 disabilitata, vedere le opzioni in Connessione->Associazione per maggiori informazioni su questa funzione. webui.pairing.info.y=L'associazione \u00e8 abilitata, vedere le opzioni in Connessione->Associazione per maggiori informazioni. webui.enable=Abilita (*) ConfigView.section.rss=RSS locali, ecc. subscriptions.rss.enable=Crea feed RSS dalle sottoscrizioni device.tivo.enable=Abilita il supporto a TiVo Button.removeAll=Rimuovi tutto label.rename=Rinomina %1 RCM.column.rc_rank=Punteggio RCM.column.rc_created=Creato RCM.column.rc_lastseen=Visto per l'ultima volta RCM.column.rc_level=Livello rcm.view.heading=Discovery nello swarm rcm.config.enabled=Abilita rcm.config.max_results=Risultati massimi rcm.config.max_level=Livello massimo pairing.server.warning.title=Messaggio del server sull'accoppiamento wizard.webseedseditor.edit.title=Editor dei seed HTTP wizard.webseedseditor.edit.newseed=Nuovo seed MyTorrentsView.menu.editWebSeeds=Modifica seed HTTP ClientStats.title.full=Statistiche del client ClientStats.column.count=Numero Scrape.status.cached=Scrape in cache network.ipv6.enable.support=Abilita supporto IPv6 ConfigView.section.plugins.magnetplugin=Gestore delle Magnet URI MagnetPlugin.use.lookup.service=Usa il servizio di lookup secondario di Vuze se il lookup dei magnet attraverso il DHT non ha successo MagnetPlugin.report.secondarylookup=Provo il servizio di lookup secondario MagnetPlugin.report.secondarylookup.ok=Lookup secondario riuscito MagnetPlugin.report.secondarylookup.fail=Lookup secondario non riuscito: nessuna sorgente trovata azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_in_ID.properties0000644000175000017500000021554211301156004026062 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php Main.parameter.usage=Penggunaan : java org.gudy.azureus2.cl.Main [parameter] "berkas.torrent" "tempat menyimpan data" Main.parameter.maxUploads=Maksimal jumlah unjuk dalam satu waktu Main.parameter.maxSpeed=Maksimal kecepatan unjuk dalam bytes/detik MainWindow.menu.file=&Berkas MainWindow.dialog.choose.file=Pilih berkas torrent MainWindow.dialog.choose.folder=Pilih direktori yang berisi berkas-berkas torrent MainWindow.menu.view=Tampilan MainWindow.menu.view.show=tampilkan MainWindow.menu.view.mytorrents=Torrentku MainWindow.menu.view.configuration=Konfigurasi... MainWindow.menu.view.allpeers=Semua Peer MainWindow.menu.view.detailedlist=Daftar Mendetil MainWindow.menu.closealldetails=Tutup Semua Detil MainWindow.menu.closealldownloadbars=Tutup Semua Download Bar MainWindow.menu.language=Bahasa ConfigView.section.language=Bahasa MainWindow.menu.window=Jendela MainWindow.menu.help=Bantuan MainWindow.menu.help.about=Tentang Vuze MainWindow.about.title=Tentang MainWindow.about.section.developers=Pengembang MainWindow.about.section.translators=Penerjemah MainWindow.about.section.system=Sistem MainWindow.about.internet.sourceforgedownloads=Mengunduh dari Sourceforge MainWindow.about.internet.bugreports=Laporan Bug MainWindow.about.internet.forumdiscussion=Forum Diskusi MainWindow.dialog.choose.savepath=Pilih tempat untuk menyimpan data MainWindow.dialog.choose.savepath_forallfiles=Pilih tempat untuk menyimpan SEMUA berkas MainWindow.status.latestversion=Versi terakhir MainWindow.status.latestversion.clickupdate=klik untuk meremajakan MainWindow.status.unknown=tidak diketahui MainWindow.status.checking=memeriksa MyTorrentsView.mytorrents=Torrentku TableColumn.header.name=Nama TableColumn.header.size=Ukuran TableColumn.header.done=Selesai TableColumn.header.done.info=Persentasi tingkat penyelesaian TableColumn.header.status.info=Apa yang sedang dilakukan oleh torrent TableColumn.header.seeds=Penyemai TableColumn.header.seeds.info=# jumlah penyemai yang terhubung (# total penyemai) TableColumn.header.peers=Peer TableColumn.header.peers.info=# peer yang terhubung (# total peer) TableColumn.header.completed=Usai TableColumn.header.completed.info=# peer yang sudah menyelesaikan torrent ini sesuai laporan dari tracker TableColumn.header.downspeed=Kec. Unduh TableColumn.header.upspeed=Kec. Unjuk TableColumn.header.tracker=Status Tracker TableColumn.header.tracker.info=Status dari tracker TableColumn.header.trackernextaccess=Akses Tracker TableColumn.header.trackernextaccess.info=Kapan akses ke tracker akan terjadi lagi TableColumn.header.priority=Prioritas TableColumn.header.priority.info=Menentukan seberapa besar laju data yang diberikan pada torrent TableColumn.header.seeds.fullcopycalc=asumsikan %2 salinan penuh untuk setiap %1 peer MyTorrentsView.menu.showdetails=Tampilkan Detil MyTorrentsView.menu.open=Buka Berkas MyTorrentsView.menu.setpriority=Atur Prioritas MyTorrentsView.menu.setpriority.high=Tinggi MyTorrentsView.menu.setpriority.low=Rendah MyTorrentsView.menu.start=Mulai MyTorrentsView.menu.stop=Berhenti MyTorrentsView.menu.remove=Singkirkan MyTorrentsView.menu.changeTracker=Tambah URL Tracker SystemTray.menu.closealldownloadbars=Tutup Semua Download Bar PeersView.T.info=L (local): Anda yang membuat koneksi, R (remote): peer yang membuat koneksi. PeersView.T.L.tooltip=Anda yang membuat koneksi PeersView.T.R.tooltip=Peer yang membuat koneksi PeersView.client=Klien PeersView.client.info=Tipe BT klien yang dugunakan oleh peer AllPeersView.title.full=Semua Peers ConfigView.section.files=Berkas ConfigView.label.incrementalfile=Gunakan pembuatan berkas secara increment [Dibutuhkan di FAT32 dalam Linux] ConfigView.label.defaultsavepath=Simpan ke direktori data default ConfigView.button.browse=&Rambah... ConfigView.dialog.choosedefaultsavepath=Pilih default direktori untuk menyimpan data ConfigView.section.server=Koneksi ConfigView.section.global=Umum ConfigView.label.disconnetseed=Putuskan hubungan dengan seed apabila sedang menyemai ConfigView.label.maxdownloads=Maksimal unduh dalam satu waktu [0: Tidak terbatas]\n - Tidak bisa lebih besar dari jumlah maksimum torrent yang aktif ConfigView.label.maxdownloads.tooltip=Anda akan dapat mengunduh sebanyak jumlah yang diberikan, dengan satu pengecualian.\nSebuah torrent yang sudah selesai dan mempunyai Prioritas Utama bisa mengambil slot unduh bila benar-benar diperlukan. ConfigView.label.maxactivetorrents=Maksimal torrent yang aktif [0: Tidak terbatas]\n - Torrent baru tidak akan mulai jika Anda mengunduh/mengunjuk lebih dari ini ConfigView.label.maxuploads=Maksimal slot unjuk setiap torrent ConfigView.label.maxuploadspeed=KB/detik maksimal kecepatan unjuk keseluruhan [0: Tidak terbatas] ConfigView.unlimited=Tidak terbatas ConfigView.label.opendetails=Buka tab detil secara otomatis ConfigView.label.openbar=Buka 'download bar' secara otomatis ConfigView.label.closetotray=Menutup meminimalkan ke System Tray ConfigView.label.minimizetotray=Minimize meminimalkan ke System Tray ConfigView.section.general=Umum ConfigView.section.start=Mulai ConfigView.label.showsplash=Tampilkan splash screen ConfigView.label.autoupdate=Buka dialog peningkatan jika tersedia versi lebih baru ConfigView.label.openconsole=Buka Konsol saat mulai ConfigView.label.openconfig=Buka Konfigurasi saat mulai ConfigView.label.ircwiki=Mohon membaca http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.group.irctitle=Konfigurasi IRC ConfigView.boolean.ircsendinfo=Ijinkan untuk mengirimkan konfigurasi(tanpa identitas) ke\n channel operator untuk mempermudah membantu Anda ConfigView.boolean.irclog=Aktifkan log aktifitas channel (di IRC_log.htm) ConfigView.section.security=Keamanan ConfigView.label.password=Lindungi Vuze dengan kata sandi\n - Akan ditanyakan bila keluar dari keadaan icon dan ketika mulai. ConfigView.label.passwordconfirm=Kata Sandi (konfirmasi) ConfigView.label.passwordmatch=Kata sandi diaktifkan : ConfigView.label.passwordmatchnone=Tidak ConfigView.label.passwordmatchno=Tidak / Kata sandi tidak cocok ConfigView.label.passwordmatchyes=Ya ConfigView.button.save=Simpan ConfigView.title.short=Konfigurasi ConfigView.title.full=Konfigurasi ConfigView.title.full._mac=Konfigurasi FileItem.write=tulis FileItem.read=baca FileItem.high=tinggi FileItem.donotdownload=Jangan diunduh FileItem.delete=Hapus FilesView.name=Nama FilesView.name.fastRename=Ubah Nama dengan cepat FilesView.size=Ukuran FilesView.done=Selesai FilesView.firstpiece=Awal potongan # FilesView.numberofpieces=jumlah potongan FilesView.pieces=Potongan FilesView.priority=Prioritas FilesView.menu.open=&Buka FilesView.menu.setpriority=Tentukan &Prioritas FilesView.menu.setpriority.high=&Tinggi FilesView.menu.setpriority.skipped=&Jangan di unduh FilesView.title.short=Berkas FilesView.title.full=Berkas GeneralView.section.downloaded=Terunduh GeneralView.label.status.file=Status File GeneralView.label.status.pieces=Status Potongan GeneralView.section.availability=Ketersediaan GeneralView.label.status.pieces_available=Status Potongan GeneralView.title.short=Umum GeneralView.title.full=Informasi Umum GeneralView.label.timeelapsed=Waktu yang sudah dilalui : GeneralView.label.downloaded=Terunduh : GeneralView.label.downloadspeed=Kecepatan unduh : GeneralView.label.maxuploads=Slot Unjuk : GeneralView.label.maxuploads.tooltip=Banyaknya peer yang akan di-unchoke pada satu waktu GeneralView.label.uploaded=Terunjuk GeneralView.label.completed=Usai : GeneralView.label.totalspeed=Kecepatan Swarm : GeneralView.label.totalspeed.tooltip=Total (dan rerata) kecepatan dari semua klien yang terhubung dengan Anda. GeneralView.label.averagespeed=kecepatan rata-rata GeneralView.label.filename=Nama : GeneralView.label.totalsize=Ukuran : GeneralView.label.savein=Disimpan Di : GeneralView.label.numberofpieces=banyaknya potongan : GeneralView.label.size=Ukuran : GeneralView.label.tracker=Status Tracker : GeneralView.label.comment=Komentar Torrent : GeneralView.label.user_comment=Komentar : ManagerItem.waiting=Menunggu ManagerItem.allocating=Mengalokasikan ManagerItem.checking=Memeriksa ManagerItem.ready=Menunggu torrent lain untuk diantrikan ManagerItem.downloading=Mengunduh ManagerItem.seeding=Mengunjuk ManagerItem.stopped=Berhenti ManagerItem.error=Kesalahan ManagerItem.high=tinggi ManagerItem.low=rendah PiecesView.size=Ukuran PiecesView.numberofblocks=Jumlah blok PiecesView.blocks=Blok PiecesView.completed=Usai PiecesView.availability=Ketersediaan PiecesView.writers=Kontributor Blok PiecesView.title.short=Potongan PiecesView.title.full=Potongan DownloadManager.error.filenotfound=Berkas tidak ditemukan DownloadManager.error.fileempty=Berkas Torrent kosong DownloadManager.error.filetoobig=Berkas Torrent terlalu bersar DownloadManager.error.filewithouttorrentinfo=Informasi Torrent tidak ditemukan di dalam berkas DownloadManager.error.unsupportedencoding=Pengkodean tidak terdukung DownloadManager.error.ioerror=Kesalahan IO DownloadManager.error.sha1=Kesalahan Algoritma tidak dikenal (SHA1) PeerManager.status.offline=Kesalahan Koneksi PeerManager.status.checking=Memeriksa MainWindow.upgrade.explanation.manual=Anda bisa meremajakan manual dengan menutup Vuze, mengunduh versi baru, dan menyalakan Vuze kembali MainWindow.upgrade.error.downloading.hint=Kesalahan:\tTidak bisa mengunduh versi baru, mohon meremajakan secara manual MainWindow.upgrade.section.manual=Peremajaan Manual MainWindow.upgrade.section.automatic=Peremajaan Otomatis Button.next=Lanjut Button.finish=Selesai Button.cancel=Batal IrcClient.copyright=Menggunakan PircBot Java IRC API - http://www.jibble.org/pircbot.php PasswordWindow.title=Vuze terkunci PasswordWindow.passwordprotected=Vuze dilindungi dengan kata sandi.\nUntuk menampilkan jendela Vuze, silahkan masukkan kata sandi Anda disini : TrackerChangerWindow.title=Tambah Tracker TrackerChangerWindow.newtracker=Masukkan url tracker yang baru discarded=dibuang MyTorrentsView.menu.move=Pindah MyTorrentsView.menu.moveUp=Ke Atas MyTorrentsView.menu.moveDown=Kebawah GeneralView.label.hashfails=Hash Tidak Cocok : ConfigView.text.neverStop=Jangan Berhenti ConfigView.text.neverStart=Jangan Mulai ConfigView.label.checkOncompletion=Periksa kembali tiap potongan saat unduh selesai wizard.title=Membuat Torrent wizard.browse=Rambah... wizard.torrentFile=Berkas Torrent ConfigView.section.ipfilter=Penyaring IP ConfigView.section.ipfilter.description=Keterangan ConfigView.section.ipfilter.add=Tambah ConfigView.section.ipfilter.remove=Hapus ConfigView.section.ipfilter.edit=Ubah ConfigView.section.ipfilter.save=Simpan ConfigView.section.ipfilter.editFilter=Ubah Saringan ConfigView.section.ipfilter.enable=Gunakan seedmore.title=Torrent tidak cukup disemai seedmore.shareratio=Rasio Anda untuk torrent ini adalah seedmore.uploadmore=Mempunyai rasio bagi dibawah 100 persen tidak baik untuk jaringan bittorrent.\nAnda sebaiknya membiarkan torrent ini disemai lagi.\nApakah Anda yakin ingin melanjutkan? ConfigView.label.seeds=penyemai ConfigView.section.seeding=Menyemai MyTorrentsView.menu.removeand=Singkirkan dan MyTorrentsView.menu.removeand.deletetorrent=Hapus Berkas &Torrent MyTorrentsView.menu.removeand.deletedata=Hapus &Data MyTorrentsView.menu.removeand.deleteboth=Hapus Keduanya configureWizard.transfer.title=Konfigurasi Transfer dan Koneksi configureWizard.transfer.hint=Saran : Gunakan kecepatan sedikit dibawah kecepatan sesungguhnya merupakan konfigurasi yang terbaik. configureWizard.transfer.connection=Koneksi configureWizard.transfer.connection.0=Lainnya configureWizard.transfer.connection.2=adsl/kabel xxx/128 kbps configureWizard.transfer.connection.3=adsl/kabel xxx/256 kbps configureWizard.transfer.connection.4=adsl/kabel xxx/384 kbps configureWizard.transfer.connection.5=adsl/kabel xxx/512 kbps configureWizard.transfer.connection.6=adsl/kabel xxx/768 kbps configureWizard.transfer.connection.7=adsl/kabel xxx/1024 kbps configureWizard.nat.test=Uji Coba configureWizard.nat.testing=Menguji port configureWizard.nat.ko=Kesalahan NAT configureWizard.file.title=Torrent / Berkas configureWizard.file.message1=Vuze akan menyimpan torrent yang dibuka dalam folder tertentu, Anda bisa menentukan folder tersebut disini: configureWizard.file.browse=Rambah configureWizard.file.message2=Vuze dapat melanjutkan berkas Anda dengan cepat, dengan menambahkan resume data pada torrent. Dengan fitur ini, Anda juga bisa melanjutkan potongan yang terunduh sebagian. configureWizard.file.fastResume=Gunakan fast Resume configureWizard.file.invalidPath=Direktori tidak valid configureWizard.finish.title=Selesai configureWizard.finish.message=Vuze sudah dikonfigurasi, selamat menggunakan ! exportTorrentWizard.torrentfile.browse=Rambah exportTorrentWizard.exportfile.browse=Rambah importTorrentWizard.torrentfile.title=Pemilihan Input Torrent importTorrentWizard.torrentfile.browse=Rambah importTorrentWizard.torrentfile.invalidPath=Berkas torrent tidak valid importTorrentWizard.importfile.browse=Rambah ConfigView.label.bindip=Tempel dengan alamat IP atau interface ConfigView.section.stats=Statistik ConfigView.section.stats.enable=Nyalakan ConfigView.section.stats.defaultsavepath=Direktori simpan statistik ConfigView.section.stats.choosedefaultsavepath=Silahkan pilih direktori tempat menyimpan statistik ConfigView.section.stats.savefreq=Kekerapan menyimpan ConfigView.section.stats.minutes=menit ConfigView.section.stats.hours=jam ConfigView.section.stats.seconds=dtk ConfigView.section.stats.savefile=Nama berkas statistik ConfigView.section.stats.graph_update_dividers=Tambahkan garis vertikal setiap 60 isian ManagerItem.finishing=Penyelesaian ConfigView.dialog.choosedefaulttorrentpath=Pilih default direktori untuk menyimpan torrent ConfigView.dialog.choosemovepath=Pilih direktori tujuan ConfigView.label.movecompleted=Pindahkan berkas yang sudah diunduh ConfigView.label.moveremoved=Pindahkan berkas yang sudah selesai saat dihilangkan ConfigView.label.savetorrents=Simpan berkas .torrent MainWindow.menu.view.mytracker=Trackerku MyTrackerView.title.full=Trackerku ConfigView.section.style=Tampilan ConfigView.label.set_ui_transfer_speeds.description.download=Atur kecepatan unduh (dalam KB/dtk) ConfigView.label.set_ui_transfer_speeds.description.upload=Atur kecepatan unjuk (dalam KB/dtk) fileDownloadWindow.state_initializing=Inisialisasi MyTorrentsView.menu.host.error.title=Hosting Torrent Gagal MyTorrentsView.menu.host.error.message=Kesalahan berikut terjadi saat hosting torrent ConfigView.section.style.enableXPStyle=Gunakan gaya XP (butuh mulai kembali) wizard.tracker.local=Gunakan Tracker Bawaan Vuze wizard.tracker.external=Gunakan Tracker external wizard.tracker.howToLocal=\tLihat 'Konfigurasi->Tracker' untuk menggunakannya ConfigView.section.tracker.pollintervalincper=Tiap 'n' klien splash.loadingImages=Memuat Gambar splash.initializeGui=Inisialisasi Jendela Utama splash.openViews=Membuka Tampilan splash.plugin=Memuat Plugin: ConfigView.label.movetorrent=Pindahkan .torrent ConfigView.label.movepartialdownloads=Pindahkan sekalipun ada berkas yang ditandai "jangan diunduh" ConfigView.label.playdownloadspeech=Bicara jika mengunduh selesai ConfigView.label.playdownloadspeech.info=Servis Kata-kata saat ini bekerja dengan baik dengan Bahasa Inggris # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Menampilkan banyaknya salinan yang tersedia untuk setiap potongan.\nJika angka di sebelah kanan kurang dari 1, Anda tidak melihat sebuah salinan berkas secara lengkap (dan mungkin dapat menyulitkan mengunduh). GeneralView.label.trackerurl.tooltip=Klik untuk menyalin url ke clipboard GeneralView.label.trackerurlopen.tooltip=Klik untuk membuka halaman utama dari tracker # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Perbarui GUI setiap ConfigView.section.style.reOrderDelay=Urutkan kembali tabel setiap N kali perbaruan GUI [0: tidak pernah] ConfigView.section.style.reOrderDelay.never=Tidak pernah configureWizard.nat.sharePort=Gunakan satu port masuk untuk semua torrent columnChooser.title=Pilih kolom yang akan ditampilkan columnChooser.move=Seret baris untuk mengurutkan kembali columnChooser.apply=Terapkan columnChooser.columnname=Nama Kolom columnChooser.columndescription=Keterangan TableColumn.header.shareRatio=Rasio MyTorrentsView.menu.editTableColumns=Atur &Kolom authenticator.user=Pengguna authenticator.password=Kata sandi ConfigView.label.allowSendVersion=Ijinkan Vuze untuk mengirimkan nomor versi dan identitas acak ketika memeriksa keberadaan versi baru MainWindow.menu.help.checkupdate=Periksa Peremajaan... TableColumn.header.up=Terunjuk ConfigView.section.style.confirmationOnExit=Tampilkan dialog konfirmasi saat keluar MainWindow.dialog.exitconfirmation.title=Keluar dari Vuze MainWindow.dialog.exitconfirmation.text=Anda yakin akan keluar dari Vuze wizard.tracker.ssl=Gunakan SSL ConfigView.label.playdownloadfinished=Mainkan suara saat mengunduh selesai TableColumn.header.pieces=Potongan TableColumn.header.pieces.info=Grafis yang menunjukkan potongan mana yang sudah terunduh TableColumn.header.completion=Terselesaikan TableColumn.header.completion.info=Gambaran grafis dari % terunduh MyTorrentsView.menu.recheck=Paksa untuk periksa kembali iconBar.start.tooltip=Memulai torrent yang dipilih iconBar.stop.tooltip=Menghentikan torrent yang dipilih iconBar.remove.tooltip=Menyingkirkan torrent yang dipilih dari antrian iconBar.up.tooltip=Pindahkan satu tingkat ke atas antrian iconBar.down.tooltip=Pindahkan satu tingkat ke bawah antrian iconBar.run.tooltip=Buka menggunakan default aplikasi iconBar.publish.tooltip=Publikasikan MyTorrentsView.menu.editTracker=Ubah URL Tracker GeneralView.menu.selectTracker=Pilih ConfigView.section.stats.xslfile=Nama berkas XSL ConfigView.label.savetorrentbackup=Simpan Salinan ConfigView.label.allowsameip=Perbolehkan lebih dari satu koneksi dari IP yang sama ConfigView.label.allowsameip.tooltip=Hanya cek bisa SANGAT dibutuhkan.\nJika dimatikan akan melindungi Anda dari leecher. MyTorrentsView.menu.moveTop=Ke Puncak MyTorrentsView.menu.moveEnd=Ke Dasar ConfigView.label.moveonlyusingdefaultsave=hanya jika default data direktori ConfigView.label.moveonlyusingdefaultsave.tooltip=Pindahkan hanya jika data yang diunduh berada pada default data direktori ConfigView.dialog.choosewatchtorrentfolderpath=Pilih direktori untuk mengimpor .torrent ConfigView.section.plugins=Plugin MainWindow.menu.view.stats=&Statistik SpeedView.title.full=Aktifitas SpeedView.downloadSpeed.title=Kecepatan Unduh SpeedView.uploadSpeed.title=Kecepatan Unjuk iconBar.top.tooltip=Pindahkan ke puncak antrian iconBar.bottom.tooltip=Pindahkan ke dasar antrian TableColumn.header.health=Kesehatan MyTorrentsView.menu.health=Tingkat Kesehatan health.explain.grey=menunjukkan bahwa torrent Anda tidak berjalan (baik mengunduh maupun mengunjuk) health.explain.red=menunjukkan Anda tidak terhubung dengan peer manapun saat mengunduh health.explain.blue=saat mengunjuk, ini menunjukkan Anda belum terhubung dengan peer manapun\nsaat mengunduh, ini menunjukkan Anda terhubung dengan peer, tapi tracker tidak bisa dihubungi health.explain.yellow=menunjukkan bahwa tracker baik, Anda terhubung dengan peer, tetapi Anda harus menghubungi peer tersebut terlebih dahulu.\nAnda mungkin saja mempunyai masalah NAT jika torrent Anda selalu dalam status kuning. health.explain.green=menandakan semua baik-baik saja. ConfigView.section.style.alwaysRefreshMyTorrents=Selalu refresh Torrentku # #2.0.7.0 # ConfigView.section.tracker.torrentsperpage=Berapa torrents setiap halaman ? [0: Tidak terbatas] MainWindow.dialog.share.sharefile=Pilih berkas untuk berbagi MainWindow.dialog.share.sharedir=Pilih direktori untuk berbagi MainWindow.dialog.share.sharedircontents=Pilih isi direktori untuk berbagi MainWindow.dialog.share.sharedircontents.recursive=Rekursif ConfigView.section.file.confirm_data_delete=Konfirmasi ketika menghapus data ConfigView.section.file.confirm_data_delete.tooltip=Konfirmasi penghapusan menggunakan 'Singkirkan dan Hapus...' ConfigView.section.file.delete.include_files_outside_save_dir=Ketika menghapus data, ijinkan berkas yang di-link diluar direktori penyimpanan torrent untuk dihapus juga MySharesView.type.file=Berkas plugin.download.remove.veto.notstopped=Unduh tidak bisa disingkirkan karena tidak dalam keadaan berhenti GeneralView.label.hash.tooltip=Klik untuk menyalin hash ke clipboard ConfigView.label.serverport=Port masuk TCP / UDP ConfigView.label.serverport.tooltip=Port harus diantara 1-65535, dan tidak boleh 6880 karena digunakan oleh Vuze untuk keperluan internal. configureWizard.nat.server.tcp_listen_port=Port masuk TCP ConfigView.section.style.dropdiraction.opentorrents=Buka Torrent # # 2.0.7.x # Categories.all=Semua Categories.uncategorized=Tanpa kategori CategoryAddWindow.message=Masukkan nama kategori CategoryAddWindow.title=Menambahkan kategori baru ConfigView.label.autoSeedingIgnoreInfo=Torrent yang diabaikan akan berada pada antrian terbawah dan tidak dimulai secara otomatis.\nAturan pengabaian tidak berpengaruh kepada torrent yang berada dalam Prioritas Utama.\nJika tidak disebutkan, nilai 0 berarti mematikan aturan. ConfigView.label.directory=Direktori ConfigView.label.disconnetseed.tooltip=Ketika menyemai torrent, putuskan hubungan dengan klien yang juga menyemai.\nMereka tidak perlu berkomunikasi dengan Anda. ConfigView.label.ignoreCase=Acuhkan Huruf Besar ConfigView.label.ignoreSeeds=Acuhkan torrent dengan sedikitnya ConfigView.label.importdirectory=Impor Direktori ConfigView.label.minPeersToBoostNoSeeds.tooltip=Semua torrent tanpa penyemai dan mempunyai peer kurang dari yang Anda sebutkan\nakan diletakkan di dasar antrian. ConfigView.label.minPeersToBoostNoSeeds=Turunkan peringkat semai untuk torrent tanpa penyemai dan kurang dari ConfigView.label.minSeedingTime=Waktu semai minimal dalam detik ConfigView.label.minSpeedForActiveDL.tooltip=Slot unduh selalu digunakan untuk 30 detik pertama\nsetelah 'torrent yang belum usai' mulai. ConfigView.label.minSpeedForActiveDL=Mengunduh tidak menggunakan slot jika kecepatan dibawah ConfigView.label.peers=peer ConfigView.label.ratio=rasio ConfigView.label.savedirectory=Direktori menyimpan ConfigView.label.seeding.ignore=Aturan Pengabaian ConfigView.label.seeding.ignore.header.evenFirstPriority=Abaikan torrent sekalipun\naturan Prioritas Utama diterapkan ConfigView.label.seeding.ignore.header.value=Nilai ConfigView.label.seeding.firstPriority.info=Torrent dengan Prioritas Utama akan selalu berada dalam puncak antrian.\nSemua torrent dengan kriteria Prioritas Utama tidak akan dihentikan secara otomatis.\nPrioritas Utama akan menggunakan slot unduh jika diperlukan. ConfigView.label.seeding.firstPriority.seedingMinutes=Waktu berjalan sejak berubah dari unduh menjadi unjuk ConfigView.label.seeding.rankType.none.tooltip=Urutkan berdasar kolom # ConfigView.label.seeding.rankType.none=Tidak ada ConfigView.label.seeding.rankType.peerSeed.tooltip=Makin Tinggi Rasio = Makin Tinggi Rangking ConfigView.label.seeding.rankType.peerSeed=Rasio Peer:Seed ConfigView.label.seeding.rankType.seed.tooltip=Sedikit Penyemai = Rangking lebih tinggi ConfigView.section.pluginslist=Daftar Plugin ConfigView.section.queue.seeding=Menyemai ConfigView.section.queue.seeding.autoStarting=Mulai Otomatis ConfigView.section.queue.seeding.ignore=Aturan Pengabaian ConfigView.section.queue.seeding.firstPriority=Prioritas Utama ConfigView.section.queue=Antrian ConfigView.text.all=semua ConfigView.text.hours=jam ConfigView.text.ignoreRule=Aturan Pengabaian ConfigView.text.ignore=Abaikan ConfigView.text.minutes=menit ConfigView.text.neverIgnore=Jangan Diabaikan ConfigView.text.any=salah satu DownloadManager.error.datamissing=Data tidak ditemukan MainWindow.menu.language.refresh=Segarkan ManagerItem.forced=Paksa ManagerItem.queued=Mengantri MySeedersView.header=Torrent Terselesaikan TableColumn.header.availability.info=# salinan penuh yang terlihat TableColumn.header.availability=Ketersediaan TableColumn.header.category=Kategori MyTorrentsView.header=Torrent Berjalan TableColumn.header.maxuploads=Maks # Unjuk MyTorrentsView.menu.category.delete=Hapus Kategori MyTorrentsView.menu.forceStart=&Paksa Mulai MyTorrentsView.menu.queue=&Mulai Mengantri MyTorrentsView.menu.setCategory.add=&Tambah Kategori... MyTorrentsView.menu.setCategory=Atur Kategori TableColumn.header.totalspeed.info=Total Kecepatan dari semua peer yang terkoneksi dengan Anda TableColumn.header.totalspeed=Total Kecepatan splash.initializePlugins=Inisialisasi Plugin DownloadManager.error.unabletostartserver=Tidak bisa memulai Server - periksa konfigurasi port dan/atau ijin firewall bagi aplikasi untuk berperan sebagai server GeneralView.label.creationdate=Dibuat pada : ManagerItem.stopping=Menghentikan ConfigView.section.file.max_open_files=Maksimum jumlah berkas untuk dibaca/ditulis\n[0: Tidak terbatas] ConfigView.section.file.max_open_files.tooltip=Berguna jika Anda mengunduh torrent dengan ratusan/ribuan berkas, dan Anda mencapai batas 'file handle' dari sistem operasi ConfigView.section.proxy=Proxy ConfigView.section.proxy.enable_proxy=Gunakan proxy untuk komunikasi dengan tracker [dibutuhkan restart] ConfigView.section.proxy.username=Pengguna ConfigView.section.proxy.password=Kata Sandi ConfigView.section.proxy.enable_socks=Menggunakan proxy SOCKS GeneralView.label.connected=terhubung GeneralView.label.in_swarm=dalam swarm ManagerItem.initializing=Menginisialisasi AlertMessageBox.error=Kesalahan AlertMessageBox.warning=Peringatan AlertMessageBox.comment=Informasi AlertMessageBox.information=Informasi AlertMessageBox.unread=Anda mempunyai pesan yang belum dibaca - klik disini untuk menampilkan Tracker.alert.listenfail=Gagal mendengarkan pada port %1.\nPeriksa aplikasi lain tidak sedang menggunakan port ini.\nPeriksa juga apakah ada Vuze lain yang berjalan. SpeedView.stats.session=Sesi ini SpeedView.stats.session.tooltip=Total (Protokol) SpeedView.stats.downloaded=Diunduh (Protokol) SpeedView.stats.uploaded=Diunjuk (Protokol) SpeedView.stats.ratio=Rasio SpeedView.stats.uptime=Waktu Menyala SpeedView.stats.now=Saat ini SpeedView.stats.now.tooltip=Total (Protokol) # # > 2.0.8.0 # TableColumn.header.remaining.info=Jumlah yang masih harus diunduh TableColumn.header.remaining=Kurang ConfigView.section.file.perf=Opsi Performa ConfigView.section.file.max_open_files.explain=Membuka terlalu banyak berkas dapat menimbulkan masalah sistem operasi dikarenakan resource yang terbatas seperti 'file handles'. Hal ini membatasi jumlah berkas yang bisa dibuka. popup.error.hide=Sembunyikan popup.error.details=Detil ConfigView.section.style.colorOverride.error=Kesalahan MainWindow.status.tooOld=terlalu tua, silahkan diremajakan. ConfigView.section.style.colorOverride.warning=Peringatan ConfigView.section.file.save.peers.max=Jumlah maksimum peer yang disimpan [0: Tidak terbatas] ConfigView.section.file.save.peers.pertorrent=setiap torrent ConfigView.label.max_peers_per_torrent=Default maks koneksi tiap torrent [0: Tidak terbatas] ConfigView.label.max_peers_total=Maksimal koneksi keseluruhan [0: Tidak terbatas] MyTorrentsView.menu.changeDirectory=Ubah direktori data GenericText.column=kolom MyTorrentsView.menu.thisColumn.remove=Hilangkan Kolom MyTorrentsView.menu.thisColumn.toClipboard=Salin ke Clipboard MyTorrentsView.menu.thisColumn.autoTooltip=Selalu tampilkan tooltip TableColumn.header.secondsseeding=Lama Unjuk TableColumn.header.secondsseeding.info=Jumlah waktu sejak mulai mengunjuk. TableColumn.header.secondsdownloading=Lama Unduh TableColumn.header.secondsdownloading.info=Jumlah waktu sejak mulai mengunduh. window.updateswt.title=Versi SWT Anda terlalu tua! window.updateswt.text=Versi SWT Anda terlalu tua!\nSWT adalah pustaka grafis yang digunakan oleh Vuze dan versi yang Anda gunakan terlalu tua untuk versi Vuze terkini. Klik tombol OK untuk meremajakan SWT Anda. window.updateswt.failed=Pembaruan gagal, tekan OK untuk memulai kembali. window.updateswt.status.finding=Mencari Versi SWT terkini window.updateswt.cancel=Batal window.updateswt.ignore=Abaikan splash.initializeGM=Inisialisasi Torrent Manager Global splash.loadingTorrents=Memuat Torrent-Torrent MyTorrentsView.menu.thisColumn.sort=Urutkan Scrape.status.error=Kesalahan Scrape: Scrape.status.error.invalid=Balasan tidak sesuai. Scrape.status.initializing=Menunggu untuk scrape... ConfigView.label.minSpeedForActiveSeeding=Menyemai tidak menggunakan slot jika kecepatan dibawah ConfigView.section.stats.exportpeers=Ekspor detil peer ConfigView.section.file.torrent.ignorefiles=Berkas yang diacuhkan ketika membuat/menghapus torrent\n - contoh: .DS_Store;Thumbs.db Button.yes=&Ya Button.no=&Tidak plugins.basicview.activity=Aktifitas: ConfigView.label.maxdownloadspeed=KB/detik kecepatan unduh maksimum keseluruhan [0: Tidak terbatas] splash.loadingTorrent=Memuat Torrent splash.of=dari ConfigView.pluginlist.broken=Rusak MainWindow.statusText.checking=Memeriksa Peremajaan ConfigView.label.checkonstart=Periksa Vuze terbaru saat dinyalakan ConfigView.label.periodiccheck=Periksa versi baru secara periodik MainWindow.updateavail=Klik disini untuk meremajakan MainWindow.status.latestversionunchecked=Pemerikaan versi dimatikan ConfigView.section.style.doNotUseGB=Jangan gunakan satuan GB ConfigView.section.style.doNotUseGB.tooltip=Jika dicentang, Vuze akan tetap menggunakan MB sekalipun ukuran lebih besar dari 1024MB GeneralView.label.maxdownloadspeed=Batas unduh GeneralView.label.maxdownloadspeed.tooltip=kecepatan maksimal unduh [0: tidak terbatas] ConfigView.pluginlist.coreplugins=Built-in plugin berikut ini sudah termuat: Peers.column.DLedFromOthers=Dari Lainnya Peers.column.DLedFromOthers.info=Jumlah data yang diunduh dari yang lain pada saat terhubung denganmu ConfigView.section.file.friendly.hashchecking=Pemeriksaan hash yang lebih ramah ConfigView.section.file.friendly.hashchecking.tooltip=Sedikit lebih lambat, tapi lebih ramah terhadap cpu/system, mode pemeriksaan hash potongan. Button.clear=Bersihkan MainWindow.IPs.tooltip=Daftar saringan terakhir: %1\nJumlah IPFilters dalam daftar - Jumlah blocked/banned/bad IP sesi ini.\nKlik ganda untuk melihat detil. ConfigView.section.ipfilter.blockedinfo=IP yang diblok oleh penyaring IP ConfigView.label.defaultstarttorrentsstopped=Torrent baru secara default dalam keadaan berhenti ConfigView.section.file.decoder.showlax=Tampilkan penyandian yang kecil kemungkinannya ConfigView.section.file.decoder.showall=Perkirakan semua kemungkinan penyendian MainWindow.status.updowndetails.tooltip=Detil kecepatan Unduh/Unjuk\nKlik kanan untuk mengubah, Klik ganda untuk membuka statistik TrackerClient.announce.warningmessage=Tracker untuk '%1' memberikan peringatan '%2' ConfigView.section.file.perf.cache.enable=Gunakan disk cache ConfigView.section.file.perf.cache.size=Ukuran cache dalam %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=T&ransfer ConfigView.label.experimental.osx.kernel.panic.fix=Perbaikan eksperimental untuk kernel panic pada cpu-ganda sistem OSX [butuh restart] PeerManager.status.error=Kesalahan Stats.title.full=Statistik CacheView.title.full=Penyimpanan Sementara CacheView.general.size=Ukuran Keseluruhan CacheView.general.inUse=Sedang Digunakan CacheView.general.title=Informasi Penyimpanan Sementara CacheView.reads.title=Pembacaan I/O CacheView.reads.fromFile=Dari Berkas CacheView.reads.fromCache=Dari Cache CacheView.writes.title=Penulisan I/O CacheView.writes.toCache=Menuju Cache CacheView.writes.toFile=Menuju Berkas CacheView.writes.hits=Tersimpan CacheView.speeds.title=Laju Data CacheView.speeds.reads=Pembacaan CacheView.speeds.writes=Penulisan CacheView.speeds.fromCache=Dari/Ke Cache CacheView.speeds.fromFile=Dari/Ke Berkas CacheView.reads.amount=Jumlah CacheView.reads.avgsize=Rerata Ukuran ConfigView.label.maxuploadspeedseeding=Kecepatan bila hanya menyemai ConfigView.section.proxy.enable_socks.peer=Gunakan proxy untuk komunikasi dengan peer (hanya koneksi keluar) [dibutuhkan restart] ConfigView.section.proxy.peer.informtracker=Informasikan batasan kepada tracker ConfigView.section.proxy.socks.version=versi SOCKS PiecesView.legend.written=Sudah ditulis PiecesView.legend.requested=Diminta PiecesView.legend.downloaded=Sudah diunduh, menunggu penulisan PiecesView.legend.incache=Data dalam Cache PiecesView.typeItem.0=Lambat PiecesView.typeItem.1=Cepat PiecesView.type=Tipe ConfigView.section.security.toolsdir=Direktori yang berisi 'tools.jar' ConfigView.section.security.choosetoolssavedir=Pilih folder yang berisi 'tools.jar' ConfigView.section.proxy.peer.same=Gunakan aturan proxy yang sama untuk komunikasi tracker dan peer MyTorrentsView.menu.setSpeed.unlimit=Tidak dibatasi MyTorrentsView.menu.setSpeed.unlimited=Tidak terbatas MyTorrentsView.menu.setSpeed.disable=Matikan Unjuk MyTorrentsView.menu.setSpeed.disabled=Dimatikan MyTorrentsView.menu.setSpeed.in=dalam MyTorrentsView.menu.setSpeed.slots=slot dari GeneralView.label.maxuploadspeed=Batas Unjuk GeneralView.label.maxuploadspeed.tooltip=kecepatan maksimal unjuk [0 : tidak terbatas] MyTorrents.items.UpSpeedLimit.disabled=Tidak mengunjuk MyTorrents.items.UpSpeedLimit.unlimited=Tidak terbatas TableColumn.header.maxupspeed=Maks Kec. Unjuk TableColumn.header.maxupspeed.info=Maksimal kecepatan unjuk yang ditentukan pada peer ConfigView.section.file.perf.cache.enable.write=Cache data untuk mengurangi penulisan cakram dan juga dapat mengurangi pembacaan cakram yang dibutuhkan untuk pemeriksaan potongan ConfigView.section.tracker.client=Klien FilesView.fullpath=Tampilkan Full Path FilesView.remaining=Sisa Potongan TableColumn.header.trackername=Nama Tracker TableColumn.header.trackername.info=Nama tracker berdasar pada announce URL ConfigView.group.override=Timpa Konfigurasi ConfigView.section.file.perf.cache.notsmallerthan=Jangan cache berkas yang lebih kecil dari (dalam %1) PeersView.state=Keadaan PeersView.state.info=Keadaan dari koneksi peer PeersView.state.pending=Ditunda PeersView.state.connecting=Menghubungi PeersView.state.handshake=Berjabat tangan PeersView.state.established=Terhubung DownloadManager.error.operationcancancelled=Operasi dibatalkan Torrent.create.progress.cancelled=Operasi Dibatalkan ConfigView.section.connection.advanced=Jaringan Tingkat Lanjut MyTorrentsView.confirm_torrent_removal=Anda yakin akan menghilangkan torrent ini? TableColumn.header.maxdownspeed=Maks. Kec. Unduh TableColumn.header.maxdownspeed.info=Maksimal kecepatan unduh yang ditentukan pada peer ConfigView.label.copyanddeleteratherthanmove=Salin dulu baru kemudian hapus data, daripada memindahkan dalam satu operasi - dapat membantu menghindari kehilangan data pada beberapa sistem ConfigView.label.openstatsonstart=Buka Statistik saat mulai installPluginsWizard.title=Pemasangan Plugin installPluginsWizard.mode.title=Silahkan memilih metode pemasangan installPluginsWizard.mode.list=Dengan daftar dari sorceforge.net installPluginsWizard.list.title=Daftar plugin yang bisa dipasang installPluginsWizard.list.loading=Silahkan menunggu daftar plugin sedang dimuat. installPluginsWizard.list.loaded=Silahkan memilih plugin yang ingin dipasang. installPluginsWizard.list.name=Nama installPluginsWizard.list.version=Versi installPluginsWizard.list.description=Keterangan Plugin installPluginsWizard.finish.title=Pemasangan dalam Proses installPluginsWizard.finish.explanation=Plugin akan dipasang menggunakan Update Assistant.\n\nMohon bersabar, ini bisa memakan beberapa waktu.\n\nUntuk laporan proses, klik ganda pada sebelah kiri dari status bar. installPluginsWizard.details.loading=Detil sedang dimuat, mohon tunggu sejenak... installPluginsWizard.mode.file=Dengan berkas yang sudah ada installPluginsWizard.installMode.title=Silahkan memilih tipe pemasangan installPluginsWizard.installMode.user=Pasang plugin hanya untuk Anda installPluginsWizard.installMode.shared=Pasang plugin untuk semua pengguna installPluginsWizard.file.title=Silahkan pilih berkas plugin yang ingin dipasang installPluginsWizard.file.file=Berkas : installPluginsWizard.file.invalidfile=Berkas ini tidak valid sebagai Vuze plugin. installPluginsWizard.file.no_such_file=Tidak ada berkas dengan nama/lokasi yang disebutkan. installPluginsWizard.file.browse=Rambah... uninstallPluginsWizard.title=Melepas Plugin uninstallPluginsWizard.list.title=Daftar Plugin yang terpasang uninstallPluginsWizard.list.loaded=Pilih plugin yang ingin dilepas installPluginsWizard.list.nullversion=Tanpa Versi uninstallPluginsWizard.finish.title=Dalam proses pelepasan uninstallPluginsWizard.finish.explanation=Plugin yang dipilih akan dilepas menggunakan Update Assistant. update.instance.install=Memeriksa pemasangan update.instance.uninstall=Memeriksa pelepasan update.instance.update=Memeriksa peremajaan MainWindow.status.update.tooltip=Klik ganda untuk informasi proses Button.abort=Batalkan ConfigView.section.ipfilter.enablebanning=Blok peer yang mengirim data buruk terus menerus MyShares.column.category=Kategori MainWindow.dialog.restartconfirmation.title=Menyalakan Kembali Vuze MainWindow.dialog.restartconfirmation.text=Anda yakin akan menyalakan kembali Vuze splash.plugin.init=Inisialisasi Plugin: splash.plugin.UIinit=Inisialisasi Plugin GUI: %1 ConfigView.section.style.osx_small_fonts=Gunakan huruf ukuran kecil [dibutuhkan mulai kembali] MyTorrentsView.menu.exportmenu=Ekspor ConfigView.section.tracker.client.scrapeinfo=Mematikan scraping akan menghambat banyak fungsi dari aturan antrian, hal ini dikarenakan mereka bergantung pada informasi yang diterima dari scraping tracker. ConfigView.section.tracker.client.scrapeenable=Gunakan scraping Scrape.status.disabled=Scrape Dimatikan MyTorrentsView.menu.explore=Tampilkan Berkas MyTorrentsView.menu.explore._mac=Tampilkan dalam Finder MyTorrentsView.menu.explore._windows=Tampilkan dalam Explorer TableColumn.header.networks=Jaringan TableColumn.header.networks.info=Jaringan yang diijinkan untuk komunikasi data peer-peer ConfigView.section.tracker.server.group.networks=Jaringan ConfigView.section.tracker.server.group.networks.info=Pilih jaringan dimana tracker akan menerima peer window.networkselection.title=Pilihan Jaringan ConfigView.section.connection.peersource.Tracker=Dari tracker ConfigView.section.connection.peersource.PeerExchange=Diberi oleh peer lain ConfigView.section.connection.peersource.Plugin=Ditambah oleh plugin ConfigView.section.connection.peersource.Incoming=Koneksi Masuk TableColumn.header.peersources=Asal Peer wizard.tracker.dht=Desentralisasi (hanya Vuze) MyTorrentsView.menu.advancedmenu=Tingkat Lanjut MyTorrentsView.menu.networks=Jaringan MyTorrentsView.menu.peersource=Asal-usul Peer ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrent dengan rasio Seed:Peer lebih dari ConfigView.label.seeding.firstPriority.ignore0Peer=Torrent dengan 0 Peer ConfigView.section.file.nativedelete._mac=Gunakan tempat sampah ketika menghapus berkas ConfigView.section.file.nativedelete._windows=Pindahkan berkas yang dihapus ke Tempat Sampah MainWindow.menu.tools.nattest=Uji &NAT / Firewall Button.apply=Terapkan Button.close=Tutup window.welcome.title=Selamat datang di Vuze %1 #file can be a URL or a path in the jar DHTView.activity.title=Aktifitas DHTView.activity.status.true=Mengantri DHTView.activity.status.false=Berjalan DHTView.activity.details=Detil MainWindow.dht.status.tooltip=Jika Distributed Database berjalan, ini menunjukkan perkiraan jumlah pengguna yang sedang online MainWindow.dht.status.disabled=DHT Dimatikan MainWindow.dht.status.failed=DHT Gagal MainWindow.dht.status.initializing=DHT Dimulai MainWindow.dht.status.users=%1 pengguna MainWindow.dht.status.unreachable=DHT Tidak Terhubung MainWindow.dht.status.unreachabletooltip=Kemungkinan terdapat masalah dengan Distributed Database UDP port mapping (NAT/firewall) MyTorrentsView.menu.setUpSpeed=Atur Kecepatan Unjuk MyTorrentsView.menu.setDownSpeed=Tentukan Kecepatan Unduh ConfigView.section.tracker.client.showwarnings=Tampilkan pesan peringatan yang dilaporkan oleh tracker ConfigView.section.ipfilter.blockbanning=Ban sebuah blok dengan 256 alamat IP jika sedikitnya 'n' dalam blok sudah di ban TableColumn.header.comment=Komentar TableColumn.header.comment.info=Komentar pengguna TableColumn.header.commenticon=Icon Komentar ConfigView.label.playfilespeech=Bicara jika sebuah berkas selesai ConfigView.label.playfilespeech.info=Servis Kata-kata saat ini bekerja dengan baik dengan Bahasa Inggris ConfigView.label.playfilefinished=Mainkan suara jika sebuah berkas selesai ConfigView.label.backupconfigfiles=Buat salinan konfigurasi untuk tujuan pemulihan ActivityView.legend.limit=Batas kecepatan ActivityView.legend.achieved=Kecepatan ActivityView.legend.overhead=Kelebihan ActivityView.legend.peeraverage=Rata-rata ActivityView.legend.swarmaverage=Kecepatan rata-rata swarm ActivityView.legend.trimmed=Dipotong (melebihi kapasitas grafis) MyTorrentsView.menu.movemenu=Pindahkan Berkas MyTorrentsView.menu.movedata=Pindah Berkas Data... MyTorrentsView.menu.movetorrent=Pindahkan Berkas Torrent... MyTorrentsView.menu.movedata.dialog=Pilih lokasi baru ConfigView.label.queue.maxactivetorrentswhenseeding=Maksimal jika hanya mengunjuk saja [0:Tidak terbatas] Views.plugins.IRC.title=IRC - Bantuan Teknis Online Formats.units.persec=/dtk Formats.units.alot=Banyak !!! FilesView.menu.rename=Ubah nama atau target FilesView.menu.rename_only=Ubah Nama FilesView.menu.retarget=Pindahkan Berkas FilesView.rename.choose.path=Pilih berkas baru atau yang sudah ada FilesView.rename.choose.path.dir=Pilih direktori baru atau yang sudah ada FilesView.rename.confirm.delete.title=Konfirmasi Penghapusan FilesView.rename.confirm.delete.text=Anda yakin akan menghapus berkas asli '%1'? FilesView.rename.filename.title=Ubah nama berkas FilesView.rename.filename.text=Pilih nama baru untuk berkas ConfigView.higher.mode.available=Opsi lebih mendalam tersedia dalam mode pengguna yang lebih tinggi ConfigView.section.mode=Mode Pengguna ConfigView.section.mode.title=Tingkat Pemahaman Pengguna ConfigView.section.mode.beginner=Pemula ConfigView.section.mode.beginner.wiki.definitions=Istilah dalam BitTorrent ConfigView.section.mode.intermediate=Menengah ConfigView.section.mode.intermediate.wiki.publish=Mempublikasikan Berkas ConfigView.section.mode.advanced=Lanjut ConfigView.section.mode.advanced.wiki.main=Halaman utama wiki ConfigView.section.mode.beginner.text=Anda hanya membutuhkan untuk mengunduh torrent.\nGunakan mode ini jika yang Anda inginkan hanya mengatur torrent Anda. ConfigView.section.mode.intermediate.text=Akses ke fungsi-fungsi tracker.\nGunakan mode ini jika Anda ingin mendirikan tracker dan mempublikasikan berkas-berkas Anda. ConfigView.section.mode.advanced.text=Akses ke konfigurasi jaringan.\nGunakan mode ini jika Anda mengerti tentang MTU atau non blocking I/O... Files.column.storagetype=Tipe Penyimpanan Files.column.fileext=Tipe MessageBoxWindow.rememberdecision=Ingat pilihanku FilesView.rename.failed.title=Ubah nama/target gagal FilesView.rename.failed.text=Operasi gagal, kemungkinan dikarenakan target pemilihan tidak valid Utils.link.visit=Silahkan kunjungi ConfigView.section.connection.serverport.wiki=Pilihan port yang baik installPluginsWizard.installMode.info.title=Informasi installPluginsWizard.installMode.info.text=Anda tidak membutuhkan plugin agar Vuze bekerja semestinya, umumnya plugin digunakan untuk kesenangan, otomatisasi, atau kendali jarak jauh.\nJadi mohon untuk membaca keterangan dari setiap plugin sebelum memutuskan untuk memasangnya.\nPlugin umumnya aman untuk dicoba, hanya saja jangan berlebihan dalam memuat plugin yang tidak digunakan. Views.plugins.Plugin.Update.title=Pembaharuan Plugin MainWindow.nat.status.tooltip.unknown=Jangkauan Firewall/NAT tidak diketahui (TCP) MainWindow.nat.status.tooltip.ok=Dapat dijangkau (TCP) MainWindow.nat.status.tooltip.probok=Dapat dijangkau, tapi tidak ada koneksi TCP yang masuk baru-baru ini MainWindow.nat.status.bad=Tertutup Firewall MainWindow.nat.status.tooltip.bad=Masalah Firewall/NAT (TCP). Silahkan melihat wiki untuk bantuan ConfigView.section.logging.log1type=Peringatan ConfigView.pluginlist.column.loadAtStartup=Muat pada saat mulai ConfigView.pluginlist.column.type=Tipe ConfigView.pluginlist.column.type.perUser=Tiap Pengguna ConfigView.pluginlist.column.name=Nama ConfigView.pluginlist.column.version=Versi ConfigView.pluginlist.column.directory=Direktori ConfigView.pluginlist.column.isOperational=Beroprasi? MyTorrentsView.dialog.NumberError.title=Angka tidak valid MyTorrentsView.dialog.NumberError.text=Angka yang Anda masukkan tidak valid atau tidak terbaca. MyTorrentsView.dialog.setSpeed.title=Atur kecepatan %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Masukkan angka %1 untuk mengubah kecepatan %2: MyTorrentsView.dialog.setNumber.upload=unjuk MyTorrentsView.dialog.setNumber.download=unduh MyTorrentsView.dialog.setNumber.inKbps=dalam %1 OpenTorrentWindow.torrent.options=Konfigurasi berikut akan diterapkan pada torrent-torrent yang dipilih diatas: Tracker.tooltip.MultiSupport=Tracker ini mendukung lebih dari satu scrape setiap request. Tracker.tooltip.NoMultiSupport=Tracker ini tidak mendukung lebih dari satu scrape setiap request.\nHal ini tidak akan mengganggu performa Anda, akan tetapi akan memberikan beban tambahan pada tracker. ConfigView.section.file.perf.cache.flushpieces=Segera tulis potongan yang sudah selesai ke cakram. Hal ini akan memperhalus akses cakram, akan tetapi menghasilkan lebih banyak operasi penulisan. ConfigView.section.file.writemblimit.explain=Ketika kecepatan penulisan cakram lebih lambat dari kecepatan unduh, parameter ini akan membatasi seberapa banyak data yang akan diantrikan sebelum kecepatan unduh diperlambat. Button.moveUp=Pindah Keatas Button.moveDown=Pindah Kebawah ConfigView.notAvailableForMode=Bagian ini diperuntukkan untuk mode %1 atau lebih. Tidak tersedia dalam mode %2. health.explain.error=Terjadi kesalahan dengan torrent ini. Lihat kolom Status, atau tooltip pada icon untuk melihat pesan kesalahan. PiecesView.priority=Prioritas PiecesView.priority.info=prioritas penyelesaian potongan, tapi tidak perlu menaruh banyak perhatian disini PiecesView.speed=Kecepatan PiecesView.speed.info=Peer yang lebih lambat dihalangi untuk berada dalam potongan yang cepat TableColumn.header.AvgAvail.info=Jumlah dari ketersediaan potongan dibagi # poongan, dibagi # koneksi TableColumn.header.AvgAvail=Rerata Tersedia/potong MyTorrentsView.menu.checkfilesexist=Periksa Berkas yang ada MyTorrentsView.menu.rescanfile=Secara periodik periksa potongan yang belum selesai Plugin.extseed.name=Penyemai External azinstancehandler.alert.portclash=Port %1 sudah digunakan oleh pengguna Vuze yang lain, silahkan pilih port baru untuk port masuk TCP / UDP [antara %2 dan %3]. ConfigView.section.transfer.lan.uploadrate=KB/detik kecepatan unjuk LAN [0: Tidak terbatas] ConfigView.section.transfer.lan.downloadrate=KB/detik kecepatan unduh LAN [0: Tidak terbatas] TorrentOptionsView.title.short=Konfigurasi Torrent TorrentOptionsView.title.full=Konfigurasi Torrent TorrentOptionsView.param.max.peers=Maksimal jumlah koneksi [0: tidak terbatas] ConfigView.section.connection.encryption.require_encrypted_transport=Membutuhkan transport ter-enkripsi ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Paksa untuk menggunakan koneksi ter-enkripsi dengan peer lain. ConfigView.section.connection.encryption.min_encryption_level=Level enkripsi minimal ConfigView.section.connection.encryption.min_encryption_level.tooltip=Plain - hanya saat berjabat tangan\nRC4 - stream penuh\nLebih tinggi enkripsi membutuhkan CPU lebih. Peers.column.Encryption=Penyandian Peers.column.Encryption.info=Tingkat penyandian yang digunakan ConfigView.section.connection.encryption.encrypt.info=Jika enkripsi dinyalakan Anda tidak dapat berhubungan dengan klien yang tidak kompatibel, kecuali Anda menggunakan opsi fallback ConfigView.section.connection.encryption.encrypt.info.link=Silahkan berkunjung kemari untuk lebih detil MainWindow.sr.status.tooltip.ok=Rasio Bagi %1 baik MainWindow.sr.status.tooltip.poor=Rasio Bagi %1 buruk: < 0.9 MainWindow.sr.status.tooltip.bad=Rasio Bagi %1 sangat buruk: < 0.5 ConfigView.section.style.status.show_sr=Rasio Bagi ConfigView.section.style.status.show_nat=Status NAT ConfigView.section.style.status.show_ddb=Status DDB ConfigView.section.style.status.show_ipf=Status Penyaring IP ConfigView.section.connection.encryption.encrypt.group=Enkripsi/Pengacak Transport ConfigView.section.connection.encryption.encrypt.fallback_info=Menggunakan opsi fallback dapat membuat Anda berhubungan dengan klien yang tidak kompatibel, tapi akan menghasilkan koneksi yang tidak ter-enkripsi ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Ijinkan koneksi keluar tidak ter-enkripsi jika koneksi ter-enkripsi gagal ConfigView.section.connection.encryption.encrypt.fallback_incoming=Ijinkan koneksi masuk tidak ter-enkripsi ConfigView.section.connection.encryption=Enkripsi Transport ConfigView.section.style.defaultSortOrder=Urutan defaut ConfigView.section.style.defaultSortOrder.desc=Urut Turun ConfigView.section.style.defaultSortOrder.asc=Urut Naik Button.selectAll=Pilih semua Button.markSelected=Tandai Button.unmarkSelected=Hilangkan Penanda TorrentOptionsView.param.max.uploads=Maksimal jumlah slot unjuk [minimum: 2] MyTorrentsView.dialog.setPosition.title=Atur Posisi MyTorrentsView.dialog.setPosition.text=Masukkan posisi untuk torrent yang dipilih: MyTorrentsView.menu.reposition.manual=Ubah Urutan.. ConfigView.section.connection.advanced.info.link=Silahkan berkunjung kemari untuk lebih detil ConfigView.section.connection.advanced.socket.group=Opsi Socket ConfigView.section.connection.advanced.bind_port=Tempel ke port local [0: matikan] ConfigView.section.connection.advanced.bind_port.tooltip=Koneksi socket keluar akan ditempel ke port yang diberikan.\nMenggunakan fungsi ini dapat membantu instabilitas dari NAT router. ConfigView.section.proxy.group.tracker=Komunikasi Tracker ConfigView.section.proxy.group.peer=Komunikasi Peer Pieces.column.Requested=Diminta Pieces.column.Requested.info=Ditampilkan jika semua bagian dari potongan sudah diminta (*) ConfigView.label.maxuploadsseeding=Nilai alternatif ketika menyemai MyTorrentsView.filter=Saringan: popup.error.hideall=Sembunyikan Semua MyTorrentsView.dialog.setFilter.title=Ubah Saringan MyTorrentsView.dialog.setFilter.text=Bagian %1 akan disaring dengan text berikut. Gunakan simbol | (pipe) untuk menyaring dengan lebih dari satu saringan. MyTorrentsView.clearFilter.tooltip=Bersihkan Saringan MyTorrentsView.menu.filter=Saringan... ConfigureWizard.language.choose=Pilih bahasa dari daftar dibawah ini: popup.closing.in=Menutup jendela secara otomatis dalam %1 detik popup.more.waiting=ada %1 pesan lagi.. # > 2402 popup.download.finished="%1" telah selesai diunduh. popup.file.finished="%1" selesai diunduh. ConfigView.auto=Otomatis SpeedView.stats.autospeed=Kecepatan Unjuk Otomatis SpeedView.stats.autospeed.disabled=Fungsi ini dinonaktifkan (Anda membutuhkan DHT) atau tidak digunakan (Anda memilih kecepatan unjuk manual) SpeedView.stats.maxPing=Maks Ping: SpeedView.stats.maxUp=Maks Kecep Unjuk: ConfigView.pluginlist.unloadSelected=Bongkar Pilihan ConfigView.pluginlist.scan=Memeriksa plugin baru ConfigView.section.transfer.autospeed.maxupload=%1 maksimal kecepatan unjuk [0: Tidak terbatas] ConfigView.pluginlist.column.unloadable=Dapat dibongkar TableColumn.header.date_added=Tanggal Ditambahkan TableColumn.header.date_added.info=Kapan torrent ditambahkan ConfigView.section.file.hashchecking.smallestfirst=Cek kembali berkas yang paling kecil terlebih dahulu TorrentOptionsView.param.max.uploads.when.busy=KB/dtk maks kecepatan unjuk jika batas unjuk global tercapai [0: jangan gunakan] FileView.BlockView.title=Potongan Berkas FileView.BlockView.Done=Selesai FileView.BlockView.Skipped=Diacuhkan FileView.BlockView.Active=Aktif ConfigView.label.tcplistenport=Port masuk TCP ConfigView.section.proxy.username.info=Jika proxy server meminta autentifikasi sekalipun tidak didefinisikan, gunakan "" sebagai nama pengguna ConfigView.label.maxuploadswhenbusymin=Maksimal kecepatan unjuk tiap torrent pada saat keadaan sibuk [dtk] DownloadManager.error.badsize=Ukuran tidak cocok ConfigView.filter=Cari opsi ConfigView.section.files.move=Pemindahan ConfigView.section.file.defaultdir.section=Opsi default direktori ConfigView.section.file.defaultdir.auto=Otomatis unduh ke direktori default (Tanpa tanya) ConfigView.section.file.defaultdir.bestguess=Gunakan perkiraan terbaik saat memilih default direktori penyimpanan ConfigView.section.file.defaultdir.ask=Direktori default: ConfigView.section.file.defaultdir.lastused=Perbarui default direktori ke tempat terakhir menyimpan ConfigView.section.file.config.section=Aturan Konfigurasi ConfigView.section.file.config.currentdir=Direktori konfigurasi saat ini: Tracker.announce.ignorePeerSeed=Mengabaikan jumlah Peer/Penyemai. %1 ConfigView.section.connection.encryption.use_crypto_port=Menggunakan 'cryptoport' tracker extension akan mencegah koneksi masuk tidak ter-enkripsi. Sebagian tracker tidak menerima hal ini dan akan melaporkan kesalahan seperti "Port tidak sesuai" atau "Argumen tidak legal" TorrentOptionsView.param.reset.to.default=Mengembalikan konfigurasi ke nilai default PeerColumn.activationCount=Peer yang berusaha menghubungi: %1 ConfigView.section.connection.tcp.enable=Gunakan TCP ConfigView.section.connection.udp.enable=Gunakan UDP ConfigView.section.style.showiconbar=Tampilkan Toolbar MyTorrentsView.menu.rename=Ubah Nama MyTorrentsView.menu.rename.displayed=Ubah nama yang ditampilkan MyTorrentsView.menu.rename.save_path=Ubah Nama Tempat Penyimpanan MyTorrentsView.menu.rename.displayed.enter.title=Ubah nama yang ditampilkan MyTorrentsView.menu.rename.displayed.enter.message=Masukkan nama baru untuk ditampilkan.\nJika dikosongkan, akan digunakan nama yang asli. MyTorrentsView.menu.edit_comment=Ubah Komentar MyTorrentsView.menu.edit_comment.enter.title=Mengubah Komentar MyTorrentsView.menu.edit_comment.enter.message=Masukkan komentar authenticator.savepassword=Ingat kata sandi TorrentInfoView.torrent.encoding=Pengkodean Torrent progress.window.title=Operasi sedang dalam proses progress.window.msg.filemove=Mohon menunggu hingga memindahkan/merubah nama berkas selesai ConfigView.label.popup.show.button=Tampilkan ConfigView.label.please.visit.here=Silahkan berkunjung kemari untuk lebih detil ConfigView.section.ipfilter.enable.descriptionCache=Simpan keterangan IP dalam berkas ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Jika dimatikan, keterangan tidak akan diingat ConfigView.label.openmytorrents=Buka 'Torrentku' pada saat mulai ConfigView.label.open_transfer_bar_on_start=Buka Transfer Bar pada saat mulai ConfigView.section.style.DNDalwaysInIncomplete=Selalu tampilkan torrent dengan 'Jangan Diunduh' di dalam bagian 'Torrent Berjalan' dari Torrentku ConfigView.label.pause.downloads.on.exit=Jeda pengunduhan saat keluar ConfigView.section.connection.http.enable=Gunakan ConfigView.section.connection.http.port=Port masuk window.update.noupdates.title=Memeriksa hasil pembaruan window.update.noupdates.text=Tidak ada pembaruan baru tersedia untuk Anda.\n\nSelamat! ConfigView.label.bindip.details=Contoh: 192.168.1.5;eth0;eth1[2] akan menempelkan pada IP, pada semua IP pada interface pertama, dan pada IP ketiga dari interface kedua.\nIP pertama akan digunakan untuk semua layanan, yang lain akan digunakan sebagai penyeimbang beban.\nInterface yang tersedia:\n%1 ConfigView.label.mindownloads=Min unduh dalam satu waktu UI.cannot_submit_blank_text=Harus diisi. popup.download.added="%1" telah ditambahkan ke dalam daftar unduh. MessageBoxWindow.nomoreprompting=Jangan tanyakan lagi TorrentOptionsView.param.max.seeds=Maksimal jumlah koneksi ke penyemai [0: batas koneksi] TorrentOptionsView.param.alternative.value.enable=Nilai alternatif apabila menyemai ConfigView.section.proxy.check.on.start=Periksa status proxy pada saat mulai ConfigView.label.closetotray._mac=Menutup meminimalkan ke Ikon Status Bar ConfigView.label.minimizetotray._mac=Minimize meminimalkan ke Icon Status Bar splash.unloadingTorrents=Membongkar Torrent-torrent splash.unloadingTorrent=Membongkar Torrent ConfigView.section.file.defaultdir.autorename=Otomatis ubah nama torrent data jika berkas dalam path terlihat berbeda alert.raised.at.close=(Pesan dari penutupan Vuze sebelumnya) Peers.column.maxupspeed=Kecep. Unjuk Maks Peers.column.maxdownspeed=Kecep. Unduh Maks MyTorrents.items.DownSpeedLimit.disabled=Tidak mengunduh PiecesView.BlockView.Have=Punya PiecesView.BlockView.NoHave=Tidak Punya PiecesView.BlockView.Header=%1 kolom, %2 baris, %3 potongan Peers.column.client_identification=Identifikasi Klien Peers.column.client_identification.info=Menunjukkan nama mentah client yang diterima oleh Vuze - berguna untuk debugging MainWindow.menu.tools.speedtest=Uji Kecepatan... speedtest.wizard.title=Uji Kecepatan speedtest.wizard.run=Jalankan uji kecepatan speedtest.wizard.test.mode.updown=unjuk dan unduh speedtest.wizard.test.mode.up=unjuk speedtest.wizard.test.mode.down=unduh SpeedTestWizard.set.upload.button.apply=Terapkan window.uiswitcher.title=Pemilihan Vuze UI window.uiswitcher.text=Silahkan memilih tampilan dibawah yang sesuai dengan kebutuhan Anda. window.uiswitcher.NewUI.text=* Direkomendasikan untuk pemula.\n\n* Mudah, tampilan grafis intuitif\n\n* Jenis tampilan ini dibutuhkan untuk mempublikasikan ke Vuze platform window.uiswitcher.ClassicUI.title=Tampilan Klasik window.uiswitcher.ClassicUI.text=* Mempertahankan fungsionalitas dari 2.x klien\n\n* Vuze content layer tidak akan dimuat window.uiswitcher.bottom.text=Pilihan Anda dapat diubah lagi dengan mudah dengan memilih tombol 'Pemilihan Vuze UI' VivaldiView.notAvailable=Tampilan Vivaldi tidak tersedia TableColumn.header.date_completed=Selesai Pada ConfigView.section.ipfilter.discardbanning=Blok peer yang memiliki rasio data terbuang/data baik melebihi [0: matikan] ConfigView.section.ipfilter.discardminkb=Minimal %1 terbuang sebelum menerapkan rasio ConfigView.interface.start.advanced=Mulai di Tampilan Tingkat Lanjut (AZ 2.x) MyTorrents.column.ColumnQuality=Kualitas MyTorrents.column.ColumnSpeed=Kecepatan MyTorrents.column.ColumnProgressETA.StreamReady=Streaming Siap MyTorrents.column.ColumnProgressETA.PlayableIn=Dapat dijalankan dalam %1 TableColumn.header.Quality=Kualitas TableColumn.header.Speed=Kecepatan TableColumn.header.SpeedGraphic=Kecepatan TableColumn.header.AzProduct=Dari #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=Tipe Berkas: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.library=Pustaka v3.MainWindow.menu.library=Pustaka v3.MainWindow.button.play=Mainkan v3.MainWindow.view.wait=Inisialisasi tampilan, tunggu sejenak. v3.MainWindow.xofx=%1 dari %2 v3.MainWindow.search.defaultText=cari... v3.mb.openFile.title=Buka Berkas v3.mb.openFile.button.play=Mainkan v3.mb.openFile.button.cancel=Batal v3.mb.openFile.button.guide=Baca Playback Guide splash.initializeCore=Inisialisasi Inti splash.initializeUIElements=Inisialisasi Elemen Tampilan # ConfigView.section.ipfilter.autoload.group=Muat Otomatis ConfigView.section.ipfilter.autoload.file=Berkas penyaring IP untuk dimuat otomatis ConfigView.section.ipfilter.autoload.loadnow=Muat Sekarang splash.loadIpFilters=Memuat Penyaring IP.. ConfigView.pluginlist.loadSelected=Muat Pilihan SpeedView.stats.asn=Jaringan: SpeedView.stats.estupcap=Batas unjuk: SpeedView.stats.estdowncap=Batas unduh: SpeedView.stats.unknown=Tidak diketahui SpeedView.stats.estimate=Diperkirakan SpeedView.stats.measured=Diukur SpeedView.stats.manual=Ditetapkan # Used for peers which we can't determine. PeerSocket.unknown=Tidak Diketahui PeerSocket.fake_client=PALSU PeerSocket.bad_peer_id=peer ID buruk PeerSocket.mismatch_id=tidak cocok PeerSocket.unknown_az_style=Tidak Diketahui %1/%2 PeerSocket.unknown_shadow_style=Tidak Diketahui %1/%2 SpeedView.stats.estimatechoke=Diperkirakan (choke) ConfigTransferAutoSpeed.capacity.used=% Kapasitas yang digunakan ConfigTransferAutoSpeed.ping.time.good=Bagus: ConfigTransferAutoSpeed.ping.time.bad=Buruk: PiecesView.DistributionView.title=Distribusi Potongan PiecesView.DistributionView.NoAvl=Potongan tidak tersedia PiecesView.DistributionView.SeedAvl=Kontribusi Penyemai pada ketersediaan PiecesView.DistributionView.PeerAvl=Kontribusi Peer pada ketersediaan PiecesView.DistributionView.RarestAvl=Potongan terlangka: %1 (sedia:%2) PiecesView.DistributionView.weHave=Potongan yang Anda miliki PiecesView.DistributionView.theyHave=Potongan yang dimiliki peer PiecesView.DistributionView.weDownload=Potongan yang Anda unduh ConfigView.label.checkOnSeeding=Gunakan pemeriksaan hemat sumberdaya untuk memeriksa potongan ketika menyemai ConfigTransferAutoSpeed.add.comment.to.log=Tambahkan komentar: ConfigTransferAutoSpeed.algorithm=Algoritma: Alert.failed.update=Satu atau lebih installasi mengalami kegagalan. Lihat AzureusWiki: Gagal Meremajakan [%1] MyTorrentsView.menu.exporthttpseeds=Ekspor HTTP seed URL ke clipboard ConfigView.label.minannounce=Jangka waktu minimal antar tracker announce dalam detik ConfigView.label.maxnumwant=Batasi jumlah peer yang mungkin dikembalikan oleh tracker ConfigView.label.noportannounce=Jangan memberitahukan port masuk kepada tracker (tidak berperngaruh pada pex, dht) ConfigView.label.maxseedspertorrent=Maksimal jumlah penyemai tiap torrent [0: Tidak terbatas] wizard.webseed=Tambah HTTP Seeds pada torrent wizard.webseed.configuration=Konfigurasi Penyemai HTTP wizard.webseed.adding=Menambahkan HTTP Seeds GeneralView.label.private=Torrent Privat: GeneralView.yes=Ya GeneralView.no=Tidak ConfigView.label.userequestlimiting=Batasi permintaan daripada menunda pembacaan untuk membatasi kecepatan unduh [tidak berpengaruh jika kecepatan unduh tidak terbatas] Peers.column.timetocomplete=Sisa Waktu Peers.column.timetocomplete.info=Sisa waktu sampai peer selesai Progress.reporting.status.canceled=Dibatalkan Progress.reporting.status.finished=Selesai Progress.reporting.status.retrying=Mencoba lagi... Progress.reporting.action.label.retry.tooltip=Coba lagi Progress.reporting.action.label.remove.tooltip=Hilangkan laporan dari daftar sejarah Progress.reporting.action.label.cancel.tooltip=Batalkan operasi Progress.reporting.action.label.detail=Detil Progress.reporting.default.error=Gagal Progress.reporting.no.reports.to.display=Tidak ada proses untuk ditampilkan. Progress.reporting.no.history.to.display=Tidak ada detil pesan untuk ditampilkan. Progress.reporting.detail.history.limit=Batasan detil pesan (%1) sudah terlampaui; pesan selanjutnya tidak tercatat dalam sejarah Progress.reporting.statusbar.button.tooltip=Tampilkan jendela Laporan Proses v3.MainWindow.text.my.account=Info Akun v3.MainWindow.text.my.profile=Profil Progress.reporting.window.remove.auto=Hilangkan item yang tidak aktif secara otomatis Progress.reporting.window.remove.auto.tooltip=Hilangkan semua proses yang selesai, gagal, atau dibatalkan secara otomatis Progress.reporting.window.remove.now=Hilangkan item yang tidak aktif Progress.reporting.window.remove.now.tooltip=Hilangkan semua proses yang selesai, gagal, atau dibatalkan TorrentOptionsView.multi.title.short=Konfigurasi Banyak Torrent TorrentOptionsView.multi.title.full=Konfigurasi Banyak Torrent MyTorrentsView.menu.open_parent_folder=Buka Folder PeerManager.status.ps_disabled=Asal peer tracker dalam kondisi mati ConfigView.section.stats.exportfiles=Ekspor detil berkas v3.MainWindow.tab.events=Pemberitahuan button.columnsetup.tooltip=Konfigurasi Kolom #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, Menu.show.torrent.menu=Tampilkan menu Torrent Menu.show.torrent.menu.tooltip=Tampilkan menu Torrent di atas menu bar aplikasi #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=Status Jaringan plugin.aznetstatus.pingtarget=Target ping/trace route menu.sortByColumn=Urutkan berdasarkan %1 v3.splash.initSkin=Inisialisasi Skin Tampilan ConfigView.section.security.resetkey.warning.title=Peringatan Kehilangan Data ConfigView.section.security.resetkey.error.title=Operasi Gagal ConfigView.copy.to.clipboard.tooltip=Salin ke clipboard Views.plugins.azbuddy.title=Teman Browser.popup.error.no.access=Kesalahan terjadi saat mengakses resource.\nMohon coba lagi lain kali.\n ConfigView.section.style.forceMozilla=Paksa Vuze untuk menggunakan Mozilla sebagai Browser [dibutuhkan xulrunner atau firefox 3; dibutuhkan mulai kembali] azbuddy.name=Teman azbuddy.enabled=Aktif azbuddy.nickname=Panggilan Anda azbuddy.msglog.title=Informasi teman azbuddy.addtorrent.title=Terima Mengunduh? azbuddy.addtorrent.msg=Teman Anda '%1' mengirim '%2'.\nApakah Anda akan menambahkan pada daftar unduh? azbuddy.contextmenu=Kirim kepada Teman Button.retry=Coba lagi Button.ignore=Jangan hiraukan azbuddy.downspeed=KB/detik maksimal kecepatan unduh dari teman [0: Tidak terbatas] ConfigView.section.security.op.error.title=Operasi Gagal ConfigView.section.security.restart.msg=Vuze akan memulai kembali untuk menyelesaikan operasi. Button.bar.show=Tampilkan Button.bar.hide=Sembunyikan Button.bar.share=Berbagi Button.bar.add=Tambah Button.bar.edit=Ubah Button.bar.edit.cancel=Selesai Mengubah MainWindow.dialog.select.vuze.file=Pilih Berkas Vuze v3.share.private.title=Berbagi Torrent v3.share.private.text=Torrent yang dipilih merupakan Torrent Privat.\n\nAnda tidak bisa berbagi torrent privat. v3.MainWindow.button.download=Unduh v3.activity.header.vuze.news=Berita Vuze azbuddy.online_status=Status koneksi azbuddy.os_online=Terkoneksi azbuddy.os_away=Tidak ditempat azbuddy.os_not_avail=Tidak bersedia azbuddy.os_busy=Sibuk azbuddy.os_offline=Tidak terkoneksi progress.window.msg.progress=Mohon menunggu hingga operasi selesai plugins.init.force_enabled=Vuze mendeteksi plugin "%1" dimatikan - agar Vuze berjalan semestinya, Vuze telah menyalakannya kembali. ConfigView.section.connection.prefer.udp=Utamakan koneksi UDP iconBar.start=Mulai iconBar.stop=Berhenti iconBar.remove=Hapus iconBar.up=Pindah ke atas iconBar.down=Pindah ke bawah iconBar.run=Jalan iconBar.top=Pindah ke puncak iconBar.bottom=Pindah ke dasar iconBar.queue=Mulai iconBar.details=Detil iconBar.comment=Komentar iconBar.play=Mainkan iconBar.queue.tooltip=Memulai (mengantrikan) torrent yang dipilih TableColumn.header.azsubs.ui.column.subs=Langganan MainWindow.menu.community=&Komunitas MainWindow.menu.community.wiki=&Wiki Komunitas MainWindow.menu.community.forums=Forums Komunitas Button.done=Selesai GeneralView.torrent_created_on_and_by=%1 oleh %2 Button.continue=Lanjutkan Button.preview=Pratayang Subscription.menu.forcecheck=Perbarui Subscription.menu.clearall=Tandai Semua Sebagai Sudah Dibaca Subscription.menu.remove=Hapus sidebar.Library=Pustakaku sidebar.LibraryDL=Mengunduh sidebar.LibraryCD=Selesai authenticator.location=Lokasi authenticator.details=Detil Subscription.menu.export=Ekspor Button.send=Kirim Button.back=Kembali sidebar.LibraryUnopened=Belum Dilihat TableColumn.header.unopened=Baru Unopened.bigView.header=Baru Subscription.menu.deleteall=Hapus Semua Subscription.menu.reset=Kembali Ke Kondisi Awal TableColumn.header.activityNew=Baru TableColumn.header.activityType=Jenis TableColumn.header.activityText=Pesan TableColumn.header.activityDate=Tanggal Ditambahkan TableColumn.header.activityActions=Aksi #what you've watched? Discover more with a single click... Button.search=Cari Button.save=Simpan Button.add=Tambah Subscription.menu.properties=Properti props.window.title=Properti untuk '%1' sidebar.VuzeHDNetwork=Jaringan Vuze HD subscriptions.column.name=Langganan subscriptions.view.title=Langganan Subscription.menu.upgrade=Dapat Diperbarui Ke Versi Lebih Tinggi statusbar.feedback=Umpan Balik statusbar.feedback.tooltip=Klik disini untuk mengirim umpan balik sidebar.Activity=Pemberitahuan sidebar.sash.tooltip=F7 untuk menampilkan/menyembunyikan sidebar sidebar.expand.tooltip=Tampilkan Sidebar sidebar.dropdown.tooltip=Tampilkan sidebar dalam bentuk menu Button.deleteContent.fromLibrary=Hilangkan dari pustaka Button.deleteContent.fromComputer=Hapus dari komputer Subscription.menu.dirtyall=Tandai Semua Sebagai Belum Dibaca configureWizard.file.message3=Vuze akan menyimpan berkas data dalam folder tertentu, Anda bisa menentukan folder tersebut disini: v3.deleteContent.applyToAll=Terapkan pada %1 entri yang dipilih ConfigView.label.seeding.firstPriority.ignoreIdleHours=Torrent yang tidak mengunjuk apapun selama v3.MainWindow.menu.contentnetworks=Jaringan HD v3.MainWindow.menu.contentnetworks.about=Tentang Jaringan HD Peers.column.as.info=Detil AS (Autonomous System) dari peer ConfigView.label.autoopen.downloadbars=Buka Download Bar secara otomatis jika ConfigView.label.autoopen=Buka Otomatis ConfigView.label.autoopen.detailstab=Buka Tab Detil secara otomatis jika v3.MainWindow.menu.contentnetworks.manage=&Atur Jaringan HD v3.dialog.cnclose.subtitle=Pemberitahuan TableColumn.header.#.info=Posisi/Nomor Urut TableColumn.header.category.info=Nama kategori dari torrent TableColumn.header.health.info=Seberapa sehat koneksi Anda ke swarm TableColumn.header.maxuploads.info=Jumlah maksimum peer yang diunjuk dalam satu waktu TableColumn.header.name.info=Nama dari torrent TableColumn.header.SeedingRank.info=Tingkat nilai yang menunjukkan seberapa kebutuhan seed sebuah torrent. Lebih tinggi berarti lebih dibutuhkan. TableColumn.header.shareRatio.info=Berapa banyak yang diunjuk dibandingkan dengan yang diunduh. TableColumn.header.size.info=Ukuran data torrent dalam cakram TableColumn.header.azsubs.ui.column.subs.info=Tombol yang memungkinkan Anda untuk berlangganan feed berisi torrent yang berhubungan TableColumn.header.upspeed.info=Kecepatan unjuk saat ini TableColumn.header.downspeed.info=Kecepatan unduh saat ini TableColumn.header.up.info=Jumlah data yang terkirim ke pengguna lain TableColumn.header.eta.info=Perkiraan waktu yang dibutuhkan sampai torrent terunduh Pieces.column.#.info=Nomor Potongan Peers.column.%.info=Persentasi yang sudah diunduh oleh peer TableColumn.header.upload.info=Jumlah data yang sudah dikirim ke peer TableColumn.header.uploadspeed.info=Kecepatan unjuk menuju peer TableColumn.header.lan.info=Menunjukkan bahwa peer berada dalam LAN TableColumn.header.TableColumnNameInfo=Nama kolom dan keterangan TableColumn.header.TableColumnSample=Contoh TableColumn.header.TableColumnInfo=Keterangan Kolom TableColumn.header.TableColumnChosenColumn=Kolom yang dipilih label.learnmore=Lebih Lanjut ColumnSetup.title=Konfigurasi kolom untuk '%1' ColumnSetup.explain=Pilih kolom-kolom yang tersedia di sebelah kiri, kemudian tambahkan pada kolom yang ada di sebelah kanan. Tambah atau kurangi daftar dengan menggunakan saringan yang ada di kiri bawah. Mendukung seret dengan tetikus maupun jalan pintas dengan keyboard. ColumnSetup.chosencolumns=Kolom yang dipilih ColumnSetup.proficiency=Tingkatan: ColumnSetup.categories=Kategori: ColumnSetup.filters=Saringan ColumnSetup.availcolumns=Kolom %1 yang tersedia ColumnSetup.availcolumns.filteredby=Kolom %1 yang tersedia disaring dengan %2 device.router.con_type=Koneksi: %1 device.browse=Rambah ConfigView.label.maxStalledSeeding=Maksimum 'macet' [0:Tidak terbatas] General.percent=Persentase MainWindow.menu.help.donate=Memberikan Donasi TableColumn.header.copied=Tersalin # This is the beginning of the word "View". It's right aligned under the icon bar item # This is the end of the word "View". It's left aligned under the icon bar item general.dont.ask.again=Jangan menanyakan lagi general.na.short=Tidak tersedia TableColumn.header.duration=Durasi TableColumn.header.resolution=Resolusi option.askeverytime=Selalu tanyakan option.rememberthis=Ingat konfigurasi ini label.clickone=Klik satu Button.turnon=Nyalakan ConfigView.label.dm.dblclick=Klik ganda pada tampilan torrent: subscriptions.column.auto-download=Unduh Otomatis Button.reload=Muat Ulang azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_pl_PL.properties0000644000175000017500000063472211301156004026113 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Plik torrent... Main.parameter.usage=Sk\u0142adnia : java org.gudy.azureus2.cl.Main [parameters] "file.torrent" "save path" Main.parameter.maxUploads=Maksymalna ilo\u015b\u0107 po\u0142\u0105cze\u0144 wychodz\u0105cych jednocze\u015bnie Main.parameter.maxSpeed=Maksymalna pr\u0119dko\u015b\u0107 wysy\u0142ania w bajtach/sek MainWindow.menu.file=&Plik MainWindow.menu.file.open=&Otw\u00f3rz MainWindow.menu.file.create=&Nowy Torrent... MainWindow.menu.file.create.fromfile=Z &pliku MainWindow.menu.file.create.fromdir=Z &katalogu MainWindow.menu.file.export=&Eksportuj XML torrent... MainWindow.menu.file.import=&Importuj xml torrent... MainWindow.menu.file.closetab=Zamknij &zak\u0142adk\u0119 MainWindow.menu.file.closewindow=Zamknij &okno MainWindow.menu.file.exit=Z&ako\u0144cz MainWindow.dialog.choose.file=Wybierz plik torrent MainWindow.menu.file.folder=&Katalog... MainWindow.dialog.choose.folder=Wybierz katalog zawierajacy pliki torrent MainWindow.menu.view=&Widok MainWindow.menu.view.show=Poka\u017c MainWindow.menu.view.mytorrents=&Moje torrenty MainWindow.menu.view.open_global_transfer_bar=Pasek transfer\u00f3w MainWindow.menu.view.configuration=&Opcje... MainWindow.menu.view.console=K&onsola MainWindow.menu.view.allpeers=Wszyscy peers MainWindow.menu.view.detailedlist=&Lista szczeg\u00f3\u0142owa MainWindow.menu.closealldetails=Zamknij &wszystkie szczeg\u00f3\u0142y MainWindow.menu.closealldownloadbars=Zamknij wszystkie pobrania &paski MainWindow.menu.language=&J\u0119zyk ConfigView.section.language=J\u0119zyk MainWindow.menu.window=&Okno MainWindow.menu.window.minimize=&Minimalizuj MainWindow.menu.window.zoom=&Powi\u0119kszenie MainWindow.menu.window.alltofront=Sprowad\u017a wszystko na &pocz\u0105tek MainWindow.menu.help=&Pomoc MainWindow.menu.help.about=O programie Vuze MainWindow.about.title=O programie MainWindow.about.section.developers=Programi\u015bci MainWindow.about.section.translators=T\u0142umacze MainWindow.about.internet.homepage=Strona g\u0142\u00f3wna Vuze MainWindow.about.internet.sourceforge=Strona Sourceforge Project MainWindow.about.internet.sourceforgedownloads=Pobierania Sourceforge MainWindow.about.internet.bugreports=Raportowanie b\u0142\u0119d\u00f3w MainWindow.about.internet.forumdiscussion=Forum MainWindow.dialog.choose.savepath=Wybierz \u015bcie\u017ck\u0119 zapisu MainWindow.dialog.choose.savepath_forallfiles=Wybierz \u015bcie\u017ck\u0119 zapisu dla wszystkich plik\u00f3w MainWindow.status.latestversion=Najnowsza MainWindow.status.latestversion.clickupdate=Kliknij, aby uaktualni\u0107 MainWindow.status.unknown=nieznana MainWindow.status.checking=sprawdzanie MyTorrentsView.mytorrents=Moje torrenty TableColumn.header.name=Nazwa TableColumn.header.size=Rozmiar TableColumn.header.done=Zako\u0144czone TableColumn.header.done.info=Procent uko\u0144czenia obecnego zadania TableColumn.header.status.info=Wy\u015bwietla co robi torrent TableColumn.header.seeds=Seed\u00f3w TableColumn.header.seeds.info=# seed\u00f3w po\u0142\u0105czonych do (# seed\u00f3w ca\u0142kowicie) TableColumn.header.peers=Peer\u00f3w TableColumn.header.peers.info=# peer\u00f3w pod\u0142\u0105czonych do (# peer\u00f3w ca\u0142kowicie) TableColumn.header.completed=Uko\u0144czonych TableColumn.header.completed.info=# peer\u00f3w, kt\u00f3rzy uko\u0144czyli pobieranie torrenta zg\u0142oszonego przez tracker TableColumn.header.downspeed=Pr\u0119dko\u015b\u0107 pobierania TableColumn.header.upspeed=Pr\u0119dko\u015b\u0107 wysy\u0142ania TableColumn.header.eta=Szacowany czas do zako\u0144czenia TableColumn.header.tracker=Status trackera TableColumn.header.tracker.info=Status trackera TableColumn.header.trackernextaccess=Nastepny dost\u0119p do trackera TableColumn.header.trackernextaccess.info=Kiedy pojawi si\u0119 nast\u0119pny dost\u0119p do trackera TableColumn.header.priority=Priorytet TableColumn.header.priority.info=Decyduje o pa\u015bmie wysy\u0142ania jakie zostaje przyznane dla ka\u017cdego torrenta. TableColumn.header.seeds.fullcopycalc=%2 pe\u0142nych kopii na %1 peer(\u00f3w) MyTorrentsView.menu.showdetails=Poka\u017c &szczeg\u00f3\u0142y MyTorrentsView.menu.showdownloadbar=Poka\u017c pasek &pobierania MyTorrentsView.menu.open=&Otw\u00f3rz plik MyTorrentsView.menu.setpriority=Ustaw &Priorytet MyTorrentsView.menu.setpriority.high=&Wysoki MyTorrentsView.menu.setpriority.low=&Niski MyTorrentsView.menu.start=&Uruchom MyTorrentsView.menu.stop=Zatrzy&maj MyTorrentsView.menu.remove=&Usu\u0144 MyTorrentsView.menu.changeTracker=&Dodaj tracker URL TrayWindow.menu.exit=Z&ako\u0144cz TrayWindow.menu.show=&Poka\u017c Vuze SystemTray.menu.exit=W&yjd\u017a SystemTray.menu.closealldownloadbars=Zamknij &wszystkie paski pobierania SystemTray.menu.open_global_transfer_bar=Poka\u017c pasek transfer\u00f3w SystemTray.menu.show=&Poka\u017c Vuze PeersView.ip=Adres IP PeersView.ip.info=Adres IP peera PeersView.port.info=U\u017cywany port PeersView.T.info=l (lokalnie): ustanowi\u0142e\u015b po\u0142\u0105czenie, R (zdalnie): peer ustanowi\u0142 po\u0142\u0105czenie. PeersView.T.L.tooltip=Ustanowi\u0142e\u015b po\u0142\u0105czenie PeersView.T.R.tooltip=Peer ustanowi\u0142 po\u0142\u0105czenie PeersView.I1=Ja od (peera) PeersView.I1.info=Zainteresowany tym co \u015bciagn\u0105\u0142 inny peer? PeersView.C1=C (zatkane przez peera) PeersView.C1.info=Pokazuje czy kto\u015b nie blokuje Ciebie przed pobieraniem PeersView.pieces=Cz\u0119\u015bci PeersView.downloadspeed=Pr\u0119dko\u015b\u0107 pobierania PeersView.download=Pobrano PeersView.I2=Ja (dla peera) PeersView.I2.info=Czy peer interesuje si\u0119 tym co \u015bci\u0105gn\u0105\u0142e\u015b? PeersView.C2=C (zatykanie peera) PeersView.C2.info=Pokazuje czy blokujesz komu\u015b pobieranie PeersView.uploadspeed=Pr\u0119dko\u015b\u0107 wysy\u0142ania PeersView.uploadspeed.info=Pr\u0119dko\u015b\u0107 wysy\u0142ania do peera PeersView.upload=Wys\u0142ano PeersView.upload.info=Ca\u0142kowita ilo\u015b\u0107 danych wys\u0142anych do peera. PeersView.statup=\u015arednie wysy\u0142anie PeersView.statup.info=\u015arednia warto\u015b\u0107 pr\u0119dko\u015bci wysy\u0142ania przez peera PeersView.S.info=Ostrze\u017cenie: peer mo\u017ce dosta\u0107 ostrze\u017cenie r\u0119cznie lub automatycznie (za nie dostarczanie danych ze zbyt wysok\u0105 rang\u0105) PeersView.downloadspeedoverall=Ca\u0142kowita pr\u0119dko\u015b\u0107 pobierania PeersView.optunchoke=Opcjonalnie odetkaj PeersView.client=Klient PeersView.client.info=Rodzaj klienta BitTorrent u\u017cywanego przez peera PeersView.menu.snubbed=&Zablokowany PeersView.title.short=Peer\u00f3w PeersView.title.full=Peer\u00f3w AllPeersView.title.full=Wszyscy Peers ConfigView.section.files=Pliki ConfigView.label.usefastresume=U\u017cywaj szybkiego wznawiania ConfigView.label.incrementalfile=W\u0142\u0105cz przyrostowe tworzenie pliku [wymagany FAT32 dla Linuksa] ConfigView.label.defaultsavepath=Zapisz do domy\u015blnego katalogu danych ConfigView.button.browse=Przegl\u0105daj... ConfigView.dialog.choosedefaultsavepath=Wybierz domysln\u0105 \u015bcie\u017ck\u0119 zapisu (na \u015bci\u0105gane du\u017ce pliki) ConfigView.section.server=Po\u0142\u0105czenie ConfigView.section.global=Og\u00f3lne ConfigView.label.disconnetseed=Od\u0142\u0105cz pe\u0142ne cz\u0119\u015bci podczas udost\u0119pniania ConfigView.label.switchpriority=Automatycznie zmie\u0144 priorytet na "niski" gdy seedujesz ConfigView.label.maxdownloads=Maksymalna ilo\u015b\u0107 torrent\u00f3w pobieranych jednocze\u015bnie [0: nieograniczona]\n- Nie mo\u017ce by\u0107 wy\u017csza ni\u017c warto\u015b\u0107 maksymalna aktywnych torrent\u00f3w ConfigView.label.maxdownloads.tooltip=Zawsze b\u0119dziesz w stanie aktywnie pobiera\u0107 liczb\u0119 torrent\u00f3w podan\u0105 tutaj, z jednym wyj\u0105tkiem.\nUko\u0144czone torrenty z najwy\u017cszym priorytetem mog\u0105 przej\u0105\u0107 gniazdo, je\u015bli b\u0119dzie to konieczne. ConfigView.label.maxactivetorrents=Maksymalna ilo\u015b\u0107 aktywnych torrent\u00f3w [0: nieograniczona]\n- Nowe torrenty nie uruchomi\u0105 si\u0119, je\u015bli pobierasz/seedujesz wi\u0119cej ConfigView.label.priorityExtensions=Automatycznie ustaw priorytet dla rozszerze\u0144\n - np: .txt;.nfo;.jpg ConfigView.label.maxuploads=Maksymalna ilo\u015b\u0107 gniazd na po\u0142\u0105czenia wychodz\u0105ce na torrent ConfigView.label.maxuploadspeed=Globalna maksymalna pr\u0119dko\u015b\u0107 wysy\u0142ania KB/s [0: nieograniczona] ConfigView.label.saveresumeinterval=Aktualizuj dane wznawiania co ConfigView.unlimited=Nieograniczona ConfigView.section.display=Wy\u015bwietl ConfigView.label.opendetails=Automatycznie poka\u017c zak\u0142adk\u0119 szczeg\u00f3\u0142\u00f3w ConfigView.label.openbar=Automatycznie poka\u017c pasek pobierania ConfigView.label.use_old_speed_menus=U\u017cywaj starego stylu menu pr\u0119dko\u015bci [wymagany restart] ConfigView.label.closetotray=Zamkni\u0119cie minimalizuje do paska systemowego ConfigView.label.minimizetotray=Minimalizuj wysy\u0142a do paska systemowego ConfigView.section.general=Og\u00f3lne ConfigView.section.start=Uruchamianie ConfigView.label.showsplash=Poka\u017c ekran powitalny ConfigView.label.autoupdate=Otw\u00f3rz okienko dialogowe je\u015bli dost\u0119pna jest nowsza wersja ConfigView.label.openconsole=Otw\u00f3rz Konsol\u0119 po uruchomieniu ConfigView.label.openconfig=Otw\u00f3rz Konfiguracj\u0119 po uruchomieniu ConfigView.label.startminimized=Uruchom zminimalizowany ConfigView.label.ircwiki=Przeczytaj http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Serwer ConfigView.label.ircchannel=Kana\u0142 ConfigView.label.irclogin=Nick ConfigView.group.irctitle=Ustawienia IRC ConfigView.boolean.ircsendinfo=Pozwalaj wysy\u0142a\u0107 (anonimowo) do\n operator\u00f3w by umo\u017cliwi\u0107 im pomoc Tobie ConfigView.boolean.irclog=W\u0142\u0105cza logowanie aktywno\u015bci kana\u0142u (IRC_log.htm) ConfigView.section.security=Ochrona ConfigView.label.password=Chro\u0144 Vuze u\u017cywaj\u0105c has\u0142a\n - B\u0119dziesz o nie pytany po uruchomieniu. ConfigView.label.passwordconfirm=Has\u0142o (powt\u00f3rz) ConfigView.label.passwordmatch=Has\u0142o aktywne : ConfigView.label.passwordmatchnone=Nie ConfigView.label.passwordmatchno=Nie / Has\u0142a nie pasuj\u0105 ConfigView.label.passwordmatchyes=Tak ConfigView.button.save=Zapisz ConfigView.title.short=Opcje ConfigView.title.full=Opcje ConfigView.title.full._mac=Preferencje ConsoleView.title.short=Konsola ConsoleView.title.full=Konsola FileItem.write=zapis FileItem.read=odczyt FileItem.normal=normalny FileItem.high=wysoki FileItem.donotdownload=Nie pobieraj FileItem.delete=Usu\u0144 FilesView.name=Nazwa pliku FilesView.name.fastRename=Szybka zmiana nazwy FilesView.size=Rozmiar FilesView.done=Zako\u0144czone FilesView.firstpiece=Pierwsza cz\u0119\u015b\u0107 # FilesView.numberofpieces=# z cz\u0119\u015bci FilesView.pieces=Cz\u0119\u015bci FilesView.mode=Tryb FilesView.priority=Priorytet FilesView.menu.open=&Otw\u00f3rz FilesView.menu.setpriority=&Ustaw priorytet FilesView.menu.setpriority.high=&Wysoki FilesView.menu.setpriority.normal=&Normalny FilesView.menu.setpriority.skipped=&Nie pobieraj FilesView.title.short=Pliki FilesView.title.full=Pliki GeneralView.section.downloaded=Pobrano GeneralView.label.status.file=Status pliku GeneralView.label.status.pieces=Status cz\u0119\u015bci GeneralView.section.availability=Dost\u0119pno\u015b\u0107 GeneralView.label.status.pieces_available=Status cz\u0119\u015bci GeneralView.section.info=Informacja GeneralView.title.short=G\u0142\u00f3wne GeneralView.title.full=G\u0142\u00f3wne GeneralView.label.timeelapsed=Up\u0142yn\u0119\u0142o czasu : GeneralView.label.remaining=Pozosta\u0142o : GeneralView.label.downloaded=Pobrano : GeneralView.label.downloadspeed=Pr\u0119dko\u015b\u0107 pobierania : GeneralView.label.maxuploads=Wysy\u0142ane gniazda : GeneralView.label.maxuploads.tooltip=Maksymalna ilo\u015b\u0107 peer\u00f3w, kt\u00f3rzy zostan\u0105 odblokowani w zadanym czasie. GeneralView.label.uploaded=Wys\u0142ano : GeneralView.label.uploadspeed=Pr\u0119dko\u015b\u0107 wysy\u0142ania : GeneralView.label.seeds=Seed\u00f3w : GeneralView.label.peers=Peer\u00f3w : GeneralView.label.completed=Uko\u0144czonych : GeneralView.label.totalspeed=Ca\u0142kowita pr\u0119dko\u015b\u0107 : GeneralView.label.totalspeed.tooltip=Ca\u0142kowita pr\u0119dko\u015b\u0107 wszystkich klient\u00f3w z kt\u00f3rymi jeste\u015b po\u0142\u0105czony. GeneralView.label.averagespeed=\u015brednio GeneralView.label.filename=Nazwa : GeneralView.label.totalsize=Rozmiar ca\u0142kowity : GeneralView.label.savein=Zapisz w : GeneralView.label.hash=Hash : GeneralView.label.numberofpieces=# z cz\u0119\u015bci : GeneralView.label.size=Rozmiar : GeneralView.label.tracker=Status trackera: GeneralView.label.updatein=Aktualizacja za : GeneralView.label.trackerurl=URL trackera : GeneralView.label.trackerurlupdate=Aktualizacja trackera GeneralView.label.comment=Komentarz : GeneralView.label.user_comment=Komentarz u\u017cytkownika: ManagerItem.waiting=Czekanie ManagerItem.allocating=Osadzanie ManagerItem.checking=Sprawdzanie ManagerItem.ready=Oczekiwanie na inne torrenty do kolejki ManagerItem.downloading=Pobieranie ManagerItem.seeding=Seedowanie ManagerItem.stopped=Zatrzymany ManagerItem.error=B\u0142\u0105d ManagerItem.high=wysoki ManagerItem.low=niski MinimizedWindow.name=Nazwa: MinimizedWindow.all_transfers=Transfery Vuze PiecesView.size=Rozmiar PiecesView.numberofblocks=# blok\u00f3w PiecesView.blocks=Bloki PiecesView.completed=Uko\u0144czone PiecesView.availability=Dost\u0119pno\u015b\u0107 PiecesView.reservedby=Zarezerwowany PiecesView.writers=Blokuj wsparcie PiecesView.title.short=Cz\u0119\u015bci PiecesView.title.full=Cz\u0119\u015bci SystemTray.tooltip.seeding=%1 seedowane, SystemTray.tooltip.downloading=%1 pobierane, DownloadManager.error.filenotfound=Nie znaleziono pliku DownloadManager.error.fileempty=Plik torrent jest pusty DownloadManager.error.filetoobig=Plik torrent jest za du\u017cy DownloadManager.error.filewithouttorrentinfo=W pliku nie znaleziono informacji o torrencie DownloadManager.error.unsupportedencoding=Nieobs\u0142ugiwane kodowanie DownloadManager.error.ioerror=B\u0142\u0105d IO DownloadManager.error.sha1=Brak takiego algorytmu (SHA1) PeerManager.status.offline=B\u0142\u0105d po\u0142\u0105czenia PeerManager.status.checking=Sprawdzanie PeerManager.status.finished=Zako\u0144czono PeerManager.status.finishedin=Zako\u0144czono w MainWindow.upgrade.assistant=Asystent aktualizacji MainWindow.upgrade.newerversion=Jest dost\u0119pna nowsza wersja Vuze do pobrania MainWindow.upgrade.explanation=Asystent pobierze now\u0105 wersj\u0119 do folderu Vuze, a nast\u0119pnie ponownie uruchomi program MainWindow.upgrade.explanation.manual=Mo\u017cesz zaktualizowa\u0107 program r\u0119cznie zamykaj\u0105c Vuze, pobra\u0107 now\u0105 wersj\u0119 i ponownie uruchomi\u0107 MainWindow.upgrade.step1=Krok 1: Pobierz now\u0105 wersj\u0119 MainWindow.upgrade.step2=Krok 2: Zamknij t\u0119 wersj\u0119 i ponownie uruchom now\u0105 wersj\u0119 Vuze MainWindow.upgrade.hint1=Podpowied\u017a:\tNaci\u015bni\u0119cie Zako\u0144cz wykona wszystko automatycznie MainWindow.upgrade.hint2=Podpowied\u017a:\tJe\u015bli chcesz zamkn\u0105\u0107 Vuze p\u00f3\u017aniej, naci\u015bnij Anuluj i po\n\tzamkni\u0119ciu programu zmie\u0144 nazw\u0119 pliku Azureus2-new.jar na Azureus2.jar MainWindow.upgrade.error.downloading.hint=B\u0142\u0105d:\tNie mo\u017cna pobra\u0107 nowej wersji, prosz\u0119 zaktualizowa\u0107 r\u0119cznie MainWindow.upgrade.section.info=Dost\u0119pna jest nowa wersja MainWindow.upgrade.section.manual=Aktualizacja r\u0119czna MainWindow.upgrade.section.automatic=Aktualizacja automatyczna MainWindow.upgrade.tooltip.progressbar=Post\u0119p pobierania jest pokazany tutaj Button.next=Dalej Button.finish=Zako\u0144cz Button.cancel=Anuluj LocaleUtil.title=Wybierz kodowanie LocaleUtil.section.chooseencoding=Wybierz kodowanie dla nazwy pliku LocaleUtil.label.chooseencoding=Wybierz najlepiej pasuj\u0105ce kodowanie LocaleUtil.label.hint.doubleclick=Podpowied\u017a: podw\u00f3jne klikni\u0119cie na kolumnie wybiera spos\u00f3b kodowania i zamyka okno dialogowe LocaleUtil.label.checkbox.rememberdecision=Zapami\u0119taj dla zmian nazw plik\u00f3w LocaleUtil.column.encoding=Kodowanie IrcClient.defaultChannel=#Azureus-U\u017cytkownicy IrcClient.copyright=U\u017cywanie PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Pod\u0142\u0105czanie do IrcClient.connected=Pod\u0142\u0105czono do IrcClient.joining=Przy\u0142\u0105czanie do IrcClient.channel=Kana\u0142 IrcClient.joined=do\u0142\u0105czy\u0142 IrcClient.error=B\u0142\u0105d IrcClient.hasjoined=przy\u0142\u0105czy\u0142 si\u0119 IrcClient.haskicked=odrzuci\u0142 IrcClient.hasleft=od\u0142\u0105czy\u0142 si\u0119 IrcClient.nowknown=jest obecnie widziany jako IrcClient.topicforchannel=Temat dla kana\u0142u IrcClient.disconnected=Od\u0142\u0105czono od IrcClient.noNick=Nie wybrano nicka. Przejd\u017a do widoku 'Opcje' IrcView.actionnotsupported=Ta czynno\u015b\u0107 nie jest obs\u0142ugiwana IrcView.clientsconnected=u\u017cytkownik\u00f3w IrcView.privateto=Do IrcView.privatefrom=Od IrcView.noticefrom=Uwaga : IrcView.errormsg=B\u0142\u0105d sk\u0142adni /wiadomo\u015b\u0107 : /wiadomo\u015b\u0107 tekstowa u\u017cytkownika IrcView.help=Poprawne komendy to :\n . /help : wy\u015bwietla ten komunikat\n . /nick | /name : zmienia tw\u00f3j nick \n . /me wiadomo\u015b\u0107 : wysy\u0142a wiadomo\u015b\u0107 poprzedzon\u0105 Twoim nickiem \n . /msg nick wiadomo\u015b\u0107 : wysy\u0142a prywatn\u0105 wiadomo\u015b\u0107 do \n . /r wiadomo\u015b\u0107 : odpowiada na ostatni\u0105 prywatn\u0105 wiadomo\u015b\u0107\n . /join #kana\u0142 : zmienia aktywny kana\u0142 (nie klikaj tutaj, to tylko przyk\u0142ad!). PasswordWindow.title=Vuze jest zablokowany PasswordWindow.passwordprotected=Vuze jest chroniony has\u0142em.\nAby zobaczy\u0107 okno Vuze, nale\u017cy poda\u0107 has\u0142o tutaj: Button.ok=OK TrackerChangerWindow.title=Zmie\u0144 tracker TrackerChangerWindow.newtracker=Wpisz url nowego trackera PeersView.discarded=Odrzucone PeersView.discarded.info=Dane, kt\u00f3re zosta\u0142y pobrane niepotrzebnie i odrzucone. discarded=odrzucone MyTorrentsView.menu.move=&Przenie\u015b MyTorrentsView.menu.moveUp=&G\u00f3ra MyTorrentsView.menu.moveDown=&D\u00f3\u0142 GeneralView.label.hashfails=B\u0142\u0119d\u00f3w hash : GeneralView.label.shareRatio=Share ratio : ConfigView.section.downloadManagement=Zarz\u0105dzanie pobieraniem ConfigView.label.startRatioPeers=Zacznij seedowa\u0107, gdy jest mniej ni\u017c 1 seed dla ConfigView.text.neverStop=Nigdy nie zatrzymuj ConfigView.text.neverStart=Nigdy nie uruchamiaj ConfigView.text.peers=Peer\u00f3w ConfigView.label.checkOncompletion=Sprawd\u017a ponownie cz\u0119\u015bci po zako\u0144czeniu pobierania wizard.title=Zr\u00f3b torrent wizard.previous=< Wstecz wizard.next=Dalej > wizard.finish=Zako\u0144cz wizard.mode=Tracker / Tryb wizard.invalidurl=URL jest nieprawid\u0142owy wizard.singlefile=Pojedynczy plik wizard.singlefile.help=Utw\u00f3rz torrent z pojedynczego pliku wizard.directory=Katalog wizard.directory.help=Utw\u00f3rz torrent z katalogu wizard.choosefile=Wybierz plik wizard.file=Plik : wizard.browse=Przegl\u0105daj... wizard.choosedirectory=Wybierz katalog wizard.invalidfile=Nieprawid\u0142owy plik! wizard.invaliddirectory=Nieprawid\u0142owy katalog! wizard.torrentFile=Plik torrent wizard.choosetorrent=Prosz\u0119 wybra\u0107 plik torrenta, aby utworzy\u0107 wizard.information=Informacje wizard.notimplemented=Jeszcze nie zaimplementowane wizard.progresstitle=Tworzenie pliku torrent wizard.savingfile=Zapisz plik... wizard.filesaved=Plik zapisany. wizard.close=Zamknij Torrent.create.progress.piecelength=D\u0142ugo\u015b\u0107 cz\u0119\u015bci: Torrent.create.progress.piececount=Liczba cz\u0119\u015bci: Torrent.create.progress.totalfilesize=Ca\u0142kowity rozmiar pliku: Torrent.create.progress.totalfilecount=Ca\u0142kowita liczba plik\u00f3w: Torrent.create.progress.parsingfiles=Parsowanie plik\u00f3w Torrent.create.progress.hashing=Hashowanie plik\u00f3w MainWindow.upgrade.downloadingfrom=Pobieranie z: MainWindow.menu.view.ipFilter=&Filtry IP ConfigView.section.ipfilter=Filtry IP ConfigView.section.ipfilter.description=Opis ConfigView.section.ipfilter.start=Pocz\u0105tkowe IP ConfigView.section.ipfilter.end=Ko\u0144cowy adres IP ConfigView.section.ipfilter.add=Dodaj ConfigView.section.ipfilter.remove=Usu\u0144 ConfigView.section.ipfilter.edit=Edytuj ConfigView.section.ipfilter.save=Zapisz ConfigView.section.ipfilter.editFilter=Edytuj filtr ConfigView.section.ipfilter.enable=W\u0142\u0105cz PeersView.menu.close=&Zamknij seedmore.title=Torrent nie jest dostatecznie seedowany seedmore.shareratio=Tw\u00f3j share ratio dla tego torrentu wynosi seedmore.uploadmore=Posiadanie share ratio poni\u017cej 1oo procent negatywnie wp\u0142ywa na sie\u0107 BitTorrent.\nPowiniene\u015b udost\u0119nia\u0107 ten torrent troch\u0119 d\u0142u\u017cej.\nCzy na pewno chcesz kontynuowa\u0107? ConfigView.label.showpopuponclose=Poka\u017c okienko potwierdzenia, gdy ko\u0144cz\u0119 seedowa\u0107 z share ratio mniejszym ni\u017c 1 ConfigView.label.startNumSeeds=\nZacznij seedowa\u0107, gdy jest mniej ni\u017c\n - Przewy\u017csza wszystkie inne regu\u0142y ConfigView.label.seeds=seed\u00f3w ConfigView.section.seeding=Seedowanie MyTorrentsView.menu.removeand=Usu&\u0144 i MyTorrentsView.menu.removeand.deletetorrent=Wykasuj &plik torrent MyTorrentsView.menu.removeand.deletedata=Wykasuj &dane MyTorrentsView.menu.removeand.deleteboth=Wykasuj &oba deletedata.title=Usu\u0144 zawarto\u015b\u0107 deletedata.message1=Czy jeste\u015b pewien, \u017ce chcesz usun\u0105\u0107 trwale '%1'?\n deletedata.noprompt=Nie pokazuj tego ponownie MainWindow.menu.file.configure=Kreator &konfiguracji... configureWizard.title=Kreator konfiguracji configureWizard.welcome.title=Witaj w kreatorze konfiguracji Vuze configureWizard.welcome.message=Kreator ten pomo\u017ce Tobie skonfigurowa\u0107 g\u0142\u00f3wne opcje Vuze. Mo\u017cesz je zmieni\u0107 w menu Narz\u0119dzia ->Opcje. configureWizard.transfer.title=Ustawienia transferu i po\u0142\u0105cze\u0144 configureWizard.transfer.hint=Podpowied\u017a: U\u017cycie mniejszej warto\u015bci ni\u017c rzeczywista pr\u0119dko\u015b\u0107 Twojego \u0142\u0105cza jest najlepszym ustawieniem. configureWizard.transfer.message=Wybierz typ \u0142\u0105cza. Nale\u017cy mie\u0107 na uwadze to, i\u017c ustawienie zbyt ma\u0142ej pr\u0119dko\u015bci wysy\u0142ania mo\u017ce ogranicza\u0107 pasmo pobierania. \u015aci\u0105ganie zbyt wielu torrent\u00f3w w tym samym czasie rownie\u017c mo\u017ce by\u0107 przyczyn\u0105 niskich transfer\u00f3w. Zaleca si\u0119 ustawienie 5kB/s na torrent jako MINIMUM. Im wi\u0119ksze ustawisz pasmo wysy\u0142ania tym szybciej b\u0119dziesz m\u00f3g\u0142 sci\u0105ga\u0107. configureWizard.transfer.connection=\u0141\u0105cze configureWizard.transfer.connection.0=W\u0142asne configureWizard.transfer.connection.1=modem/isdn configureWizard.transfer.connection.2=xxx/128 kbps configureWizard.transfer.connection.3=xxx/256 kbps configureWizard.transfer.connection.4=xxx/384 kbps configureWizard.transfer.connection.5=xxx/512 kbps configureWizard.transfer.connection.6=xxx/768 kbps configureWizard.transfer.connection.7=xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Maksymalna pr\u0119dko\u015b\u0107 wysy\u0142ania (kB/s) configureWizard.transfer.maxActiveTorrents=Maksymalna liczba aktywnych configureWizard.transfer.maxDownloads=Maksymalna liczba pobieranych configureWizard.transfer.maxUploadsPerTorrent=Maksymalna liczba po\u0142\u0105cze\u0144 wychodz\u0105cych na torrent configureWizard.nat.title=NAT / Porty serwera configureWizard.nat.message=Aby jak najlepiej wykorzysta\u0107 mo\u017cliwo\u015bci aplikacji Vuze, nale\u017cy mie\u0107 pe\u0142ny dost\u0119p do Internetu. To narz\u0119dzie pozwoli na przetestowanie i / lub zmian\u0119 portu przyjmuj\u0105cego nadchodz\u0105ce po\u0142\u0105czenia (peer).\n\nUWAGA: To narz\u0119dzie sprawdza tylko po\u0142\u0105czenia TCP. Po\u0142\u0105czenie UDP jest r\u00f3wnie\u017c wymagane, ale zostaniesz powiadomiony je\u015bli firewall b\u0119dzie je blokowa\u0142.\n\nUWAGA: Port TCP 6880 jest ju\u017c zarezerwowany, dlatego nie mo\u017ce by\u0107 u\u017cyty. configureWizard.nat.testing=Testuj\u0119 port configureWizard.nat.ok=OK! configureWizard.nat.ko=B\u0142\u0105d NAT configureWizard.nat.unable=Nie mo\u017cna przetestowa\u0107: Podano niepoprawny port lub serwis testowy napotka\u0142 problem.\nTego portu mo\u017ce ju\u017c u\u017cywa\u0107 inna aplikacja. configureWizard.file.title=Torrenty / Pliki configureWizard.file.message1=Vuze zachowa otwarte pliki .torrent w wybranym katalogu, mo\u017cesz go wybra\u0107 tutaj: configureWizard.file.path=\u015acie\u017cka configureWizard.file.browse=Przegl\u0105daj configureWizard.file.message2=Vuze mo\u017ce natychmiastowo wznowi\u0107 pobieranie plik\u00f3w, dodaj\u0105c dane do torrent\u00f3w. U\u017cywaj\u0105c tej funkcji b\u0119dziesz mia\u0142 tak\u017ce mo\u017cliwo\u015b\u0107 wznowienia plik\u00f3w cz\u0119\u015bciowo pobranych. configureWizard.file.fastResume=W\u0142\u0105cz szybkie wznawianie configureWizard.file.invalidPath=Nieprawid\u0142owa \u015bcie\u017cka configureWizard.finish.title=Uko\u0144czone configureWizard.finish.message=Vuze zosta\u0142 skonfigurowany, baw si\u0119 dobrze! wizard.close.confirmation=Potwierdzenie wizard.close.message=Czy chcesz, aby kreator ten zosta\u0142 uruchomiony podczas kolejnego startu Vuze? exportTorrentWizard.title=Eksportuj XML torrent exportTorrentWizard.torrentfile.title=Wyb\u00f3r wej\u015bciowego torrenta exportTorrentWizard.torrentfile.message=Wybierz plik torrent do eksportu exportTorrentWizard.torrentfile.path=\u015acie\u017cka exportTorrentWizard.torrentfile.browse=Przegl\u0105daj exportTorrentWizard.torrentfile.invalidPath=Nieprawid\u0142owy plik torrent exportTorrentWizard.exportfile.title=Wyb\u00f3r pliku eksportu exportTorrentWizard.exportfile.message=Wybierz plik xml do eksportu do exportTorrentWizard.exportfile.path=\u015acie\u017cka exportTorrentWizard.exportfile.browse=Przegl\u0105daj exportTorrentWizard.exportfile.invalidPath=Nieprawid\u0142owy plik eksportu exportTorrentWizard.finish.title=Uko\u0144czone exportTorrentWizard.finish.message=Eksport zako\u0144czony sukcesem exportTorrentWizard.process.inputfilebad.title=Nieprawid\u0142owy plik torrent exportTorrentWizard.process.inputfilebad.message=Pojawi\u0142 si\u0119 b\u0142\u0105d dost\u0119pu do pliku wej\u015bciowego: exportTorrentWizard.process.outputfileexists.title=Plik istnieje exportTorrentWizard.process.outputfileexists.message=Plik wyj\u015bciowy istnieje - nadpisa\u0107 go? exportTorrentWizard.process.torrentfail.title=Nieudany odczyt torrenta exportTorrentWizard.process.exportfail.title=Nieudany eksport torrenta exportTorrentWizard.process.unknownfail.title=Nieoczekiwany b\u0142\u0105d importTorrentWizard.title=Importuj XML torrenta importTorrentWizard.torrentfile.title=Wyb\u00f3r torrenta wej\u015bciowego importTorrentWizard.torrentfile.message=Wybierz plik torrentowy do zaimportowania do importTorrentWizard.torrentfile.path=\u015acie\u017cka importTorrentWizard.torrentfile.browse=Przegl\u0105daj importTorrentWizard.torrentfile.invalidPath=Nieprawid\u0142owy plik torrent importTorrentWizard.importfile.title=Wyb\u00f3r pliku importu importTorrentWizard.importfile.message=Wybierz plik xml do importu importTorrentWizard.importfile.path=\u015acie\u017cka importTorrentWizard.importfile.browse=Przegl\u0105daj importTorrentWizard.importfile.invalidPath=Nieprawid\u0142owy plik importu importTorrentWizard.finish.title=Uko\u0144czono importTorrentWizard.finish.message=Import zako\u0144czony sukcesem importTorrentWizard.process.inputfilebad.title=Import pliku nieudany importTorrentWizard.process.inputfilebad.message=Pojawi\u0142 si\u0119 b\u0142\u0105d dost\u0119pu do pliku: importTorrentWizard.process.outputfileexists.title=Plik istnieje importTorrentWizard.process.outputfileexists.message=Plik docelowy istnieje - nadpisa\u0107 go? importTorrentWizard.process.torrentfail.title=Zapis torrenta nieudany importTorrentWizard.process.importfail.title=Import torrenta nieudany importTorrentWizard.process.unknownfail.title=Nieoczekiwany b\u0142\u0105d ConfigView.label.bindip=\u0141\u0105cz z miejscowym adresem IP ConfigView.label.xfs.allocation=Ustaw nowe pliki za pomoc\u0105 metody specyficznej dla systemu plik\u00f3w XFS (system Unix) ConfigView.label.xfs.allocation.tooltip=Upewnij si\u0119, czy /usr/sbin/xfs_io jest poprawnie zainstalowane w Twoim systemie. W wi\u0119kszo\u015bci dystrybucji Linuksa znajduje si\u0119 on w pakiecie "xfsprogs". xfs.allocation.xfs_io.not.found=Alokacja pliku XFS nie powiod\u0142a si\u0119, poniewa\u017c nie mo\u017cna uruchomi\u0107 /usr/sbin/xfs_io. Upewnij si\u0119, \u017ce jest on prawid\u0142owo zainstalowany w Twoim systemie. Oryginalny b\u0142\u0105d by\u0142 : "%1". ConfigView.label.zeronewfiles=Przydziel i wyzeruj nowe pliki podczas tworzenia ConfigView.label.zeronewfiles.tooltip=Minimalizuje fragmentacj\u0119 ConfigView.section.stats=Statystyki ConfigView.section.stats.enable=W\u0142\u0105czone ConfigView.section.stats.defaultsavepath=Katalog zapisu statystyk ConfigView.section.stats.choosedefaultsavepath=Wybierz katalog zapisu dla statystyk ConfigView.section.stats.savefreq=Zapisuj co ConfigView.section.stats.hours=godz ConfigView.section.stats.seconds=sek ConfigView.section.stats.savefile=Nazwa pliku statystyk ConfigView.section.stats.graph_update_dividers=Wy\u015bwietl poziom\u0105 lini\u0119 co 60 pozycji MyTorrentsView.menu.export=&Torrent XML... MyTorrentsView.menu.host=&Hostowanie... ManagerItem.finishing=Ko\u0144czenie ConfigView.dialog.choosedefaulttorrentpath=Wybierz domy\u015bln\u0105 \u015bcie\u017ck\u0119 zapisu dla torrent\u00f3w (na ma\u0142e pliki .torrent) ConfigView.dialog.choosemovepath=Prosz\u0119 wybra\u0107 katalog do kt\u00f3rego przenosisz ConfigView.label.movecompleted=Przenie\u015b uko\u0144czone pliki (po pobraniu) ConfigView.label.moveremoved=Przenie\u015b uko\u0144czone pliki (gdy usuni\u0119te) ConfigView.label.savetorrents=Zapisz pliki .torrent MainWindow.menu.view.mytracker=M\u00f3j &tracker MyTrackerView.title.full=M\u00f3j tracker MyTrackerView.name=Nazwa MyTrackerView.status.started=Uruchomiony MyTrackerView.status.stopped=Zatrzymany MyTrackerView.peers=Peer\u00f3w MyTrackerView.seeds=Seed\u00f3w MyTrackerView.announces=Og\u0142oszenia MyTrackerView.uploaded=Wys\u0142ano MyTrackerView.downloaded=Pobrano MyTrackerView.left=Pozosta\u0142o ConfigView.section.style=Interfejs ConfigView.label.set_ui_transfer_speeds=Ignoruj wybieralne pr\u0119dko\u015bci transferu ConfigView.label.set_ui_transfer_speeds.description=Mo\u017cesz wybra\u0107 r\u0119czne definiowanie domy\u015blnie dost\u0119pnych pr\u0119dko\u015bci pobierania i wysy\u0142ania na pasku statusu w pasku systemowym.\nWarto\u015bci musz\u0105 by\u0107 oddzielone kropk\u0105. ConfigView.label.set_ui_transfer_speeds.description.download=Ustaw pr\u0119dko\u015bci pobierania (w KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Ustaw pr\u0119dko\u015bci wysy\u0142ania (w KB/s) ConfigView.section.style.useCustomTabs=U\u017cyj zamykalnych zak\u0142adek (wymagane ponowne uruchomienie) MainWindow.menu.view.plugins=&Wtyczki fileDownloadWindow.saveTorrentIn=Zapisz plik torrent w fileDownloadWindow.title=Vuze - Pobieranie torrent\u00f3w fileDownloadWindow.downloading=Pobieranie z: fileDownloadWindow.status=Status: fileDownloadWindow.state_initializing=Uruchamianie fileDownloadWindow.state_downloading=Pobieranie fileDownloadWindow.state_error=B\u0142\u0105d : MainWindow.menu.file.open.url=&Miejsce... MainWindow.menu.file.open.url.keybinding=Meta+U openUrl.title=Otw\u00f3rz lokalizacj\u0119 MyTorrentsView.menu.host.error.title=Hostowanie torrenta nieudane MyTorrentsView.menu.host.error.message=Wyst\u0105pi\u0142 nast\u0119puj\u0105cy b\u0142\u0105d podczas hostowania torrenta ConfigView.section.tracker.pollinterval=Czas mi\u0119dzy sprawdzaniem trackera (sekundy) ConfigView.section.tracker.publishenable=Publikuj szczeg\u00f3\u0142y torrenta do "" ConfigView.section.tracker.ip=Zewn\u0119trzny adres IP trackera ConfigView.section.style.enableXPStyle=W\u0142\u0105cz styl XP (wymaga ponownego uruchomienia) ConfigView.section.tracker.checkip=Automatycznie odkrywaj zewn\u0119trzny adres IP... ipCheckerWizard.title=Kreator sprawdzania adresu IP ipCheckerWizard.service=Us\u0142uga ipCheckerWizard.chooseService=Wybierz serwis sprawdzaj\u0105cy IP z listy ipCheckerWizard.explanations=Mo\u017cesz u\u017cyc tego kreatora do sprawdzenia jaki jest Tw\u00f3j zewn\u0119trzny adres IP. Je\u015bli Tw\u00f3j adres IP jest dynamiczny, zalecamy otworzenie konta za pomoc\u0105 us\u0142ugi Dynamic DNS. Niekt\u00f3re wymienione poni\u017cej adresy umo\u017cliwiaj\u0105 za\u0142o\u017cenie takiego konta. Wype\u0142nij pole adresu IP swoja dynamiczn\u0105 nazw\u0105 hosta (np. myhostname.dyndns.org). B\u0119dziesz potrzebowa\u0142 programu do automatycznej aktualizacji us\u0142ugi Dynamic DNS Twojego adresu IP. W ten spos\u00f3b b\u0119dziesz m\u00f3g\u0142 hostowa\u0107 torrenty, nawet je\u015bli Tw\u00f3j adres IP si\u0119 zmienia. ipCheckerWizard.service.description=Opis : ipCheckerWizard.progresstitle=Sprawdzanie IP ipCheckerWizard.checkComplete=Kompletne IP : ipCheckerWizard.checkFailed=Nieudane, pow\u00f3d : wizard.tracker.local=U\u017cywaj wbudowanego trackera Vuze wizard.tracker.external=U\u017cyj zewn\u0119trznego trackera wizard.tracker.howToLocal=\tId\u017a do 'Narz\u0119dzia>Opcje->Tracker', aby w\u0142\u0105czy\u0107 wizard.announceUrl=URL : IPChecker.external.service.discoveryvip.description=Discoveryvip - tylko sprawdzanie adresu IP IPChecker.external.httpinvalidresponse=B\u0142\u0119dna odpowied\u017a HTTP IPChecker.external.loadingwebpage=\u0141adowanie strony IPChecker.external.analysingresponse=Analizowanie odpowiedzi IPChecker.external.addressextracted=Uzyskany adres IP IPChecker.external.httploadfail=Nieudane za\u0142adowanie strony IPChecker.external.timeout=Przekroczono czas oczekiwania IPChecker.external.ipnotfound=Nie znaleziono adresu IP ConfigView.section.tracker.pollintervalmax=Maksimum ConfigView.section.tracker.pollintervalincby=Zwi\u0119kszaj o ConfigView.section.tracker.pollintervalincper=Co 'n' klient\u00f3w splash.loadingImages=\u0141adowanie obrazk\u00f3w splash.initializeGui=Uruchamianie g\u0142\u00f3wnego okna splash.openViews=Otwieranie widok\u00f3w splash.plugin=\u0141adowanie wtyczki: configureWizard.nat.tooManyPorts=Zbyt wiele port\u00f3w (9 maksymalnie) ConfigView.section.color=Schemat kolor\u00f3w MyTorrentsView.menu.publish=Pub&likuj... MyTrackerView.status.published=Opublikowany MyTrackerView.completed=Uko\u0144czono MainWindow.menu.file.open.torrentnodefault=Plik torrent (bez domy\u015blnego zapisu) wizard.comment=Komentarz ConfigView.label.movetorrent=Przenie\u015b .torrent ConfigView.label.movepartialdownloads=Przenie\u015b nawet je\u015bli niekt\u00f3re pliki s\u0105 ustawione na "Nie pobieraj" ConfigView.label.subdir_is_in_default=Przy rozstrzyganiu czy pobrania istniej\u0105 w katalogu domy\u015blnym, we\u017a pod uwag\u0119 tak\u017ce podkatalogi. ConfigView.section.file.decoder.label=Domy\u015blne kodowanie torrenta, gdy wyb\u00f3r jest wymagany ConfigView.section.file.decoder.nodecoder=Brak IPChecker.external.service.no-ip.description=Provider dynamicznych i statycznych adres\u00f3w IP\n(swobodne sprawdzanie adresu jest niedost\u0119pne) ConfigView.section.tracker.publicenable=W\u0142\u0105cz zewn\u0119trzne torrenty ConfigView.label.playdownloadspeech=Przem\u00f3w gdy pobieranie zostanie zako\u0144czone ConfigView.label.playdownloadspeech.info=Obecnie Us\u0142ugi g\u0142osowe najlepiej dzia\u0142aj\u0105 w j\u0119zyku angielskim # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Wy\u015bwietla liczb\u0119 dost\u0119pnych kopii ka\u017cdej cz\u0119\u015bci.\nJe\u017celi liczba po prawej stronie jest mniejsza od 1, to znaczy, \u017ce nie ma pod\u0142\u0105czonej ani jednej osoby, kt\u00f3ra ma pe\u0142n\u0105 kopi\u0119. Czasami osoba kt\u00f3ra udost\u0119pnia dany plik roz\u0142\u0105czy si\u0119 (na noc, awaria sieci, itp.) co skutkuje tym i\u017c liczba po prawej stronie jest mniejsza od 1. GeneralView.label.trackerurl.tooltip=Kliknij, aby skopiowa\u0107 url trackera do schowka GeneralView.label.trackerurlopen.tooltip=Kliknij, aby otworzy\u0107 g\u0142\u00f3wn\u0105 stron\u0119 trackera # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Od\u015bwie\u017caj GUI co ConfigView.section.style.inactiveUpdate=Od\u015bwie\u017caj g\u0142\u00f3wne okno co 'n' od\u015bwie\u017ce\u0144 GUI, je\u015bli nie jest to aktywne okno ConfigView.section.style.graphicsUpdate=Od\u015bwie\u017caj paski graficzne co 'n' od\u015bwie\u017cenia GUI ConfigView.section.style.reOrderDelay=Uporz\u0105dkuj tabele co 'n' od\u015bwie\u017ce\u0144 GUI [0: nigdy] ConfigView.section.style.reOrderDelay.never=Nigdy ConfigView.section.logging=Raporty ConfigView.section.logging.enable=W\u0142\u0105cz zapis log\u00f3w do pliku ConfigView.section.logging.logdir=Katalog pliku logu ConfigView.section.logging.choosedefaultsavepath=Wybierz katalog do zapisu GeneralView.label.updatein.querying=wysy\u0142am zapytanie... configureWizard.nat.sharePort=U\u017cyj jednego wsp\u00f3lnego portu po\u0142\u0105cze\u0144 przychodz\u0105cych dla wszystkich torrent\u00f3w ConfigView.section.logging.maxsize=Maksymalny rozmiar pliku logu ConfigView.section.tracker.passwordenableweb=W\u0142\u0105cz has\u0142o na stronie trackera ConfigView.section.tracker.passwordenabletorrent=W\u0142\u0105cz has\u0142o dla torrent\u00f3w ConfigView.section.tracker.username=Nazwa u\u017cytkownika ConfigView.section.tracker.password=Has\u0142o columnChooser.title=Wybierz kolumny columnChooser.move=Przesu\u0144 wiersze aby zmieni\u0107 ich kolejno\u015b\u0107 columnChooser.apply=Zastosuj columnChooser.columnname=Nazwa kolumny columnChooser.columndescription=Opis TableColumn.header.shareRatio=Share ratio MyTorrentsView.menu.editTableColumns=&Ustawienie kolumny wizard.operationfailed=Operacja nieudana authenticator.title=Wymagana autoryzacja authenticator.realm=Domena authenticator.user=Nazwa u\u017cytkownika authenticator.password=Has\u0142o ConfigView.label.allowSendVersion=Pozw\u00f3l Vuzowi anonimowo wysy\u0142a\u0107 numer wersji oraz losowy ID podczas sprawdzania nowszej wersji. ConfigView.label.version.info.link=Kliknij tutaj po szczeg\u00f3\u0142y o tym jakie dane s\u0105 wysy\u0142ane do serwera sprawdzania wersji wizard.hint.mode=Podpowied\u017a:\tMo\u017cesz przeci\u0105gn\u0105\u0107 i upu\u015bci\u0107 pojedynczy plik albo katalog w tym kreatorze,\n\taby wybra\u0107 plik lub katalog wizard.hint.file=Podpowied\u017a:\tMo\u017cesz wybra\u0107 pojedynczy plik metod\u0105 przeci\u0105gnij i upu\u015b\u0107 wizard.hint.directory=Podpowied\u017a:\tMo\u017cesz wybra\u0107 pojedynczy katalog metod\u0105 przeci\u0105gnij i upu\u015b\u0107 MainWindow.menu.help.checkupdate=&Sprawd\u017a aktualizacje... TableColumn.header.down=Pobrano TableColumn.header.up=Wys\u0142ano ConfigView.section.tracker.passwordenabletorrent.info=Wymaga odpowiedniego klienta sieci BitTorrent (np. Vuze) ConfigView.section.style.confirmationOnExit=Poka\u017c okno potwierdzenia zamkni\u0119cia MainWindow.dialog.exitconfirmation.title=Zamkn\u0105\u0107 Vuze MainWindow.dialog.exitconfirmation.text=Czy na pewno chcesz zamkn\u0105\u0107 Vuze SystemTray.menu.stopalltransfers=Zatrzymaj &wszystkie transfery TrayWindow.menu.stopalldownloads=Zatrzymaj &wszystkie pobierania ConfigView.section.tracker.sslport.info=Wi\u0119cej informacji znajdziesz w FAQ wizard.tracker.ssl=U\u017cyj SSL ConfigView.label.playdownloadfinished=Odtw\u00f3rz d\u017awi\u0119k gdy pobieranie zostanie zako\u0144czone ConfigView.label.popupdownloadfinished=Powiadamiaj pop-upem gdy pobieranie zosta\u0142o zako\u0144czone ConfigView.label.popupfilefinished=Powiadamiaj pop-upem gdy plik zostanie uko\u0144czony TableColumn.header.pieces=Cz\u0119\u015bci TableColumn.header.pieces.info=Graficzny pasek prezentuj\u0105cy, kt\u00f3re cz\u0119\u015bci zosta\u0142y pobrane TableColumn.header.completion=Kompletno\u015b\u0107 TableColumn.header.completion.info=Prezentacja graficzna pobierania w % ConfigView.section.style.showdownloadbasket=Poka\u017c koszyk pobierania (przeci\u0105gnij i upu\u015b\u0107 plik .torrent) ConfigView.section.style.alwaysShowTorrentFiles=Zawsze pokazuj pliki torrent w szczeg\u00f3\u0142ach/plikach wizard.multitracker=Dodaj do torrenta informacj\u0119 o wielu trackerach (Multi-Tracker) wizard.multitracker.configuration=Konfiguracja Multi-Trackera wizard.multitracker.new=Nowy... wizard.multitracker.edit=Edytuj.. wizard.multitracker.delete=Usu\u0144 wizard.multitracker.group=Grupa tracker\u00f3w wizard.multitracker.edit.title=Edytor Multi-Trackera wizard.multitracker.edit.name=Nazwa wizard.multitracker.edit.save=Zapisz wizard.multitracker.edit.newgroup=Nowa grupa wizard.multitracker.edit.deletegroup=Usu\u0144 wizard.multitracker.edit.newtracker=Nowy tracker wizard.multitracker.edit.deletetracker=Usu\u0144 wizard.multitracker.edit.edit=Edytuj wizard.addingmt=Dodawanie informacji o wielu trackerach (Multi-Tracker) wizard.multitracker.noannounce=URL jest nieobecny na Twojej liscie tracker\u00f3w MyTorrentsView.menu.recheck=Wymu\u015b ponowne sprawdzan&ie iconBar.showDownloadBar.tooltip=Poka\u017c pasek pobierania iconBar.start.tooltip=Uruchom wybrane torrenty iconBar.stop.tooltip=Zatrzymaj wybrane torrenty iconBar.remove.tooltip=Usu\u0144 wybrane torrenty iconBar.openNoDefault.tooltip=Otw\u00f3rz plik .torrent (bez domy\u015blnego zapisu) iconBar.openURL.tooltip=Otw\u00f3rz URL iconBar.openFolder.tooltip=Otw\u00f3rz katalog iconBar.new.tooltip=Utw\u00f3rz .torrent iconBar.up.tooltip=Przesu\u0144 wy\u017cej iconBar.down.tooltip=Przesu\u0144 ni\u017cej iconBar.run.tooltip=Otw\u00f3rz iconBar.host.tooltip=Hostuj iconBar.publish.tooltip=Publikuj iconBar.editcolumns.tooltip=Ustawienie kolumny MyTorrentsView.menu.editTracker=&Edytuj URL trackera GeneralView.menu.selectTracker=Wybierz ConfigView.section.stats.xslfile=Nazwa pliku XSL ConfigView.section.stats.xslfiledetails=Zostanie ona zapisana w nag\u0142\u00f3wku pliku za pomoc\u0105 tagu ConfigView.label.savetorrentbackup=Zapisz kopi\u0119 ConfigView.section.tracker.forceport=Wymu\u015b zewn\u0119trznie hostowane torrenty do pracy na porcie domy\u015blnym ConfigView.section.ipfilter.allow=Dopu\u015b\u0107 te zakresy (domy\u015blnie jest Zablokuj) ConfigView.section.ipfilter.list.inrange=by\u0142 z zakresu ConfigView.section.ipfilter.list.notinrange=nie by\u0142 z \u017cadnego zakresu ConfigView.section.ipfilter.list.title=Lista zablokowanych adres\u00f3w IP ConfigView.label.allowsameip=Pozw\u00f3l na wiele po\u0142\u0105cze\u0144 z tego samego IP ConfigView.label.allowsameip.tooltip=Zaznacz tylko gdy KONIECZNE.\nJest to ochrona przed leecherami (gdy wy\u0142\u0105czone). ManagerItem.superseeding=Super-Seedowanie ConfigView.label.userSuperSeeding=U\u017cywaj super seedowania PeersView.uniquepiece=Cz\u0119\u015b\u0107 (tryb Super-Seed) PeersView.uniquepiece.none=Brak PeersView.timetosend=Czas do ponownego wys\u0142ania cz\u0119\u015bci (tryb Super-Seed) ConfigView.section.style.addurlsilently=Otw\u00f3rz URLe natychmiast ConfigView.section.style.addurlsilently.tooltip=Automatycznie pobierz URLe plik\u00f3w .torrent bez otwierania okna dialogowego. ConfigView.section.file.decoder.prompt=Zawsze pytaj, gdy mo\u017cliwy jest wyb\u00f3r kodowania ConfigView.section.file.decoder.prompt.tooltip=Zawsze pokazuj okienko dialogowe, gdy mo\u017cliwy jest wyb\u00f3r kodowania MyTorrentsView.menu.moveTop=&Na g\u00f3r\u0119 MyTorrentsView.menu.moveEnd=&Na d\u00f3\u0142 ConfigView.label.moveonlyusingdefaultsave=tylko je\u015bli w domy\u015blnej \u015bcie\u017cce ConfigView.label.moveonlyusingdefaultsave.tooltip=Przenie\u015b tylko je\u015bli pobierane dane s\u0105 w domy\u015blnej \u015bcie\u017cce pobierania ConfigView.label.watchtorrentfolder=Importuj nowe pliki .torrents automatycznie ConfigView.label.watchtorrentfolder.tooltip=Szukaj nowych plik\u00f3w .torrents regularnie ConfigView.label.watchtorrentfolderinterval=Odst\u0119p ConfigView.label.watchtorrentfolderinterval.tooltip=Odst\u0119p czasu pomi\u0119dzy ponownym skanowaniem folderu ConfigView.dialog.choosewatchtorrentfolderpath=Prosz\u0119 wybra\u0107 katalog importu plik\u00f3w .torrent ConfigView.label.startwatchedtorrentsstopped=Uruchom zatrzymane ConfigView.label.startwatchedtorrentsstopped.tooltip=Dodaj nowe torrenty w stanie ZATRZYMANYM ConfigView.section.plugins=Wtyczki wizard.maketorrent.filesize=Rozmiar pliku (-\u00f3w) wizard.maketorrent.piececount=Liczba cz\u0119\u015bci wizard.maketorrent.piecesize=Rozmiar cz\u0119\u015bci wizard.maketorrent.auto=Automatycznie MainWindow.menu.view.stats=&Statystyki SpeedView.title.full=Aktywno\u015b\u0107 SpeedView.downloadSpeed.title=Pr\u0119dko\u015b\u0107 pobierania SpeedView.uploadSpeed.title=Pr\u0119dko\u015b\u0107 Wysy\u0142ania ConfigView.section.style.useSIUnits=U\u017cyj jednostek IEC (KB -> KiB itp.) iconBar.top.tooltip=Przesu\u0144 na g\u00f3r\u0119 iconBar.bottom.tooltip=Przesu\u0144 na d\u00f3\u0142 TableColumn.header.health=Kondycja MyTorrentsView.menu.health=O kondycji health.explain.grey=oznacza, \u017ce tw\u00f3j torrent jest nieuruchomiony (pobieranie lub wysy\u0142anie) health.explain.red=oznacza, \u017ce nie jeste\u015b z nikim po\u0142\u0105czony podczas pobierania health.explain.blue=gdy udost\u0119pniasz, oznacza \u017ce nie jeste\u015b z nikim po\u0142\u0105czony\ngdy pobierasz, oznacza \u017ce jeste\u015b z kim\u015b po\u0142\u0105czony, ale tracker nie dzia\u0142a health.explain.yellow=oznacza, \u017ce tracker dzia\u0142a, jeste\u015b z kim\u015b po\u0142\u0105czony, ale nie posiadasz zdalnego po\u0142\u0105czenia.\nMo\u017cesz mie\u0107 problem z NATem, je\u015bli twoje torrenty ca\u0142y czas maj\u0105 status \u017c\u00f3\u0142ty health.explain.green=oznacza, \u017ce wszystko jest w porz\u0105dku. ConfigView.section.style.alwaysRefreshMyTorrents=Zawsze od\u015bwie\u017caj Moje Torrenty ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Opcja ta b\u0119dzie od\u015bwie\u017ca\u0142a Moje Torrenty, nawet je\u015bli zak\u0142adka nie jest wy\u015bwietlana (przydatne dla niekt\u00f3rych wtyczek) # #2.0.7.0 # security.certtruster.title=Ostrze\u017cenie certyfikatu zabezpiecze\u0144 security.certtruster.intro=Certyfikat bezpiecze\u0144stwa zosta\u0142 wyemitowany przez firm\u0119 nie nale\u017c\u0105c\u0105 do zaufanych security.certtruster.resource=Zas\u00f3b: security.certtruster.issuedto=Wydany dla: security.certtruster.issuedby=Wydany przez: security.certtruster.prompt=Chcesz doda\u0107 do zaufanych? security.certtruster.yes=Tak security.certtruster.no=Nie ConfigView.section.tracker.torrentsperpage=Ile torrent\u00f3w na stron\u0119? [0: nieograniczona] MainWindow.menu.file.share=Klasyczne &udost\u0119pnienie MainWindow.menu.file.share.file=&Plik... MainWindow.menu.file.share.dir=K&atalog... MainWindow.menu.file.share.dircontents=Zawarto\u015b\u0107 &folder\u00f3w... MainWindow.menu.file.share.dircontentsrecursive=Zawarto\u015b\u0107 folder\u00f3w... (&rekursywnie) MainWindow.dialog.share.sharefile=Wybierz plik do udost\u0119pnienia MainWindow.dialog.share.sharedir=Wybierz folder do udost\u0119pnienia MainWindow.dialog.share.sharedircontents=Wybierz zawarto\u015b\u0107 folderu do udost\u0119pnienia MainWindow.dialog.share.sharedircontents.recursive=Rekursywny globalmanager.download.remove.veto=Odm\u00f3wiono usuni\u0119cia plugin.sharing.download.remove.veto=To pobieranie jest wynikiem udost\u0119pniania zasob\u00f3w.\nAby usun\u0105\u0107 pobieranie usu\u0144 udost\u0119pniane zasoby. ConfigView.section.tracker.main=G\u0142\u00f3wne ConfigView.label.prioritizefirstpiece=Zwi\u0119ksz priorytet dla pierwszej i ostatniej cz\u0119\u015bci pliku ConfigView.label.prioritizefirstpiece.tooltip=Zaczyna najpierw od pobrania pocz\u0105tku i ko\u0144ca pliku.\nPrzydatne przy podgl\u0105dzie plik\u00f3w. ConfigView.section.file.confirm_data_delete=Potwierdzaj przy usuwaniu danych ConfigView.section.file.confirm_data_delete.tooltip=Potwierdzaj usuni\u0119cie danych przy u\u017cyciu 'Usu\u0144 i Wykasuj...' ConfigView.section.file.delete.include_files_outside_save_dir=Gdy usuwasz dane, pozw\u00f3l r\u00f3wnie\u017c na usuwanie plik\u00f3w po\u0142\u0105czonych z torrentami poza zapisanym katalogiem TrayWindow.menu.startalldownloads=Uruchom wszystkie pobierania SystemTray.menu.startalltransfers=Uruchom wszystkie transfery sharing.progress.title=Post\u0119p udostepniania sharing.progress.hide=Ukryj MainWindow.menu.view.myshares=Moje pliki MySharesView.title.full=Moje pliki wsp\u00f3\u0142dzielone MySharesView.name=Nazwa MySharesView.type=Typ MySharesView.type.file=Plik MySharesView.type.dir=Katalog MySharesView.type.dircontents=Zawarto\u015b\u0107 katalogu MySharesView.type.dircontentsrecursive=Zawarto\u015b\u0107 katalogu (rekursywna) MySharesView.menu.remove=Usu\u0144 ConfigView.section.tracker.extensions=Rozszerzenia ConfigView.section.tracker.sendpeerids=Wyslij identyfikacj\u0119 peer\u00f3w do pobieraj\u0105cych ConfigView.section.tracker.enableudp=W\u0142\u0105cz protok\u00f3\u0142 UDP trackera plugin.sharing.torrent.remove.veto=Rejestracja trackera jest wynikiem udost\u0119pniania zasob\u00f3w.\nAby usun\u0105\u0107 pobieranie usu\u0144 udost\u0119pniane zasoby. plugin.download.remove.veto.notstopped=Pobieranie nie mo\u017ce by\u0107 usuni\u0119te bez wcze\u015bniejszego zatrzymania GeneralView.label.hash.tooltip=Kliknij, aby skopiowa\u0107 hash do schowka ConfigView.section.tracker.maxpeersreturned=Maksymalna liczba zwr\u00f3conych peer\u00f3w [0: nieograniczona] ConfigView.label.serverport=Port TCP / UDP nas\u0142uchu po\u0142\u0105cze\u0144 przychodz\u0105cych ConfigView.label.serverport.tooltip=Port musi mie\u015bci\u0107 si\u0119 w przedziale 1-65535, nie u\u017cywaj portu 6880, kt\u00f3ry jest zarezerwowany do wewn\u0119trznego u\u017cycia przez Vuze. configureWizard.nat.server.tcp_listen_port=Port TCP dla po\u0142\u0105cze\u0144 przychodz\u0105cych ConfigView.section.sharing=Udost\u0119pnianie ConfigView.section.sharing.usessl=U\u017cywaj SSL dla udost\u0119pnianych zasob\u00f3w (wymaga konfiguracji trackera) ConfigView.section.style.dropdiraction=Aktywuj przeci\u0105gnij i upu\u015b\u0107 dla katalog\u00f3w ConfigView.section.style.dropdiraction.opentorrents=Otw\u00f3rz torrenty ConfigView.section.style.dropdiraction.sharefolder=Udost\u0119pnij katalog ConfigView.section.style.dropdiraction.sharefoldercontents=Udost\u0119pnij zawarto\u015bci # # 2.0.7.x # Categories.all=Wszystkie Categories.uncategorized=Brak kategorii CategoryAddWindow.message=Wpisz nazw\u0119 nowej kategorii CategoryAddWindow.title=Dodaj now\u0105 kategori\u0119 ConfigView.label.autoSeedingIgnoreInfo=Ignorowane torrenty wracaj\u0105 na pocz\u0105tek kolejki. Nie uruchomi\u0105 si\u0119 automatycznie.\nIgnorowane regu\u0142y nie dotycz\u0105 torrent\u00f3w pasuj\u0105cych do kryterium najwy\u017cszego priorytetu.\nW innym wypadku u\u017cyj warto\u015bci 0, aby wy\u0142\u0105czy\u0107 regu\u0142\u0119. ConfigView.label.directory=Katalog ConfigView.label.disconnetseed.tooltip=Podczas seedowania od\u0142\u0105cz wszystkie aplikacje kt\u00f3re tak\u017ce seeduj\u0105. ConfigView.label.ignoreCase=Ignoruj wielko\u015b\u0107 liter ConfigView.label.ignoreSeeds=Ignoruj torrenty z co najmniej ConfigView.label.importdirectory=Katalog importu ConfigView.label.minPeersToBoostNoSeeds.tooltip=Wszystkie torrenty bez seed\u00f3w i maj\u0105ce mniej peer\u00f3w ni\u017c okre\u015bli\u0142e\u015b\nbed\u0105 przenoszone na koniec kolejki. ConfigView.label.minPeersToBoostNoSeeds=Ni\u017cszy ranking seedowania dla torrent\u00f3w bez seed\u00f3w i mniej ni\u017c ConfigView.label.minSeedingTime.tooltip=Ranking seedowania mo\u017ce sie zmienia\u0107 w bardzo kr\u00f3tkim czasie, czasami powoduj\u0105c automatyczny start torrenta tylko po to, by po chwili go zatrzyma\u0107 i z powrotem wstawi\u0107 do kolejki.\nOmin\u0105\u0107 problem mo\u017cna poprzez ustawienie torrenta na seedowanie przez okre\u015blony okres czasu. Je\u017celi chcesz mo\u017cesz go w ka\u017cdej chwili zatrzyma\u0107 r\u0119cznie. ConfigView.label.minSeedingTime=Minimalny czas udost\u0119pniania w sekundach ConfigView.label.minSpeedForActiveDL.tooltip=Gniazdo pobierania jest zawsze u\u017cywane przez pocz\u0105tkowe 30 sekund\npo tym jak nieuko\u0144czony torrent zostanie uruchomiony. ConfigView.label.minSpeedForActiveDL=Nie bierz pod uwag\u0119 torrenta, je\u015bli jego pr\u0119dko\u015b\u0107 pobierania jest ni\u017csza ni\u017c ConfigView.label.peers=peer\u00f3w ConfigView.label.queue.debuglog=Informacja o debugowaniu w pliku log ConfigView.label.queue.debuglog.info=Dodaje informacj\u0119 o kolejce debugowania do konsoli/logu.\nPomimo kodowania, informacja o debugowaniu m\u00f3wi o stanie torrent\u00f3w i dlaczego dany torrent zosta\u0142/nie zosta\u0142 uruchomiony/kolejkowany. ConfigView.label.queue.minQueueingShareRatio=Nie kolejkuj lub zatrzymuj torrenta do czasu a\u017c wzro\u015bnie share ratio ConfigView.label.removeOnStop=Usu\u0144 torrent z listy po automatycznym zatrzymaniu ConfigView.label.savedirectory=Katalog zapisu ConfigView.label.seeding.autoReposition.tooltip=Je\u015bli w\u0142\u0105czone to kolejno\u015b\u0107 torrent\u00f3w (kolumna '#') b\u0119dzie sortowana wed\u0142ug rankingu seedowania \nJest to u\u017cyteczne je\u015bli chcesz widzie\u0107 sortowania w/g rankingu seedowania, ale dalej mo\u017cesz zna\u0107 porz\u0105dek uruchomienia uko\u0144czonych torrent\u00f3w. ConfigView.label.seeding.autoReposition=Automatycznie sk\u0142aduj torrenty bazuj\u0105ce na rankingu seedowania ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Zazwyczaj je\u015bli torrenty s\u0105 z ma\u0142\u0105 liczb\u0105 seed\u00f3w i du\u017c\u0105 peer\u00f3w to prawdopodobnie nie ma pe\u0142nej kopii.\nDlatego mo\u017cesz nie chcie\u0107, aby regu\u0142y seedowania udawa\u0142y, \u017ce jest pe\u0142na kopia (w ten spos\u00f3b niepoprawnie obni\u017ca jego rang\u0119) ConfigView.label.seeding.fakeFullCopySeedStart=ale tylko dla torrent\u00f3w z przynajmniej ConfigView.label.seeding.ignore=Ignoruj regu\u0142y ConfigView.label.seeding.ignore0Peers=Ignoruj torrenty, kt\u00f3re maj\u0105 0 peer\u00f3w ConfigView.label.seeding.ignoreRatioPeers=Ignoruj torrenty, kt\u00f3re maj\u0105 przynajmniej 1 seeda ka\u017cdego ConfigView.label.seeding.ignoreShareRatio=Ignoruj torrenty, kt\u00f3re maj\u0105 share ratio ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignoruj torrent nawet je\u015bli\nobowi\u0105zuj\u0105 regu\u0142y najwy\u017cszego priorytetu ConfigView.label.seeding.ignore.header.rule=Regu\u0142a ConfigView.label.seeding.ignore.header.value=Warto\u015b\u0107 ConfigView.label.seeding.firstPriority.info=Torrenty z najwy\u017cszym priorytetem zawsze b\u0119d\u0105 na pocz\u0105tku kolejki. Torrenty spe\u0142niaj\u0105ce kryteria najwy\u017cszego priorytetu nie b\u0119d\u0105 automatycznie zatrzymywane i kolejkowane. Taki torrent dostanie te\u017c wolne gniazdo, je\u015bli zajdzie taka potrzeba. ConfigView.label.seeding.firstPriority.FP=Najwy\u017cszy priorytet ConfigView.label.seeding.firstPriority=Najwy\u017cszy priorytet ustawiaj dla torrent\u00f3w spe\u0142niaj\u0105cych ConfigView.label.seeding.firstPriority.following=z poni\u017cszych: ConfigView.label.seeding.firstPriority.shareRatio=Share ratio poni\u017cej ConfigView.label.seeding.firstPriority.seedingMinutes=Czas, kt\u00f3ry up\u0142yn\u0105\u0142 od zmiany z pobierania na seedowanie ConfigView.label.seeding.firstPriority.DLMinutes=Czas, kt\u00f3ry up\u0142yn\u0105\u0142 od pocz\u0105tku pobierania ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Poprzez udawanie, \u017ce jest 1 pe\u0142na kopia na X peer\u00f3w, redukujesz rang\u0119 torrent\u00f3w z wysok\u0105 liczb\u0105 peer\u00f3w.\nCz\u0119sto torrenty z wysok\u0105 liczb\u0105 peer\u00f3w nara\u017cone s\u0105 na wi\u0119kszy ruch.\nNie zmienia to wy\u015bwietlania '# seed\u00f3w'. ConfigView.label.seeding.numPeersAsFullCopy=Udawaj, \u017ce jest 1 pe\u0142na kopia ka\u017cdego\n[0: Nie udawaj] ConfigView.label.seeding.preferLargerSwarms.tooltip=Je\u015bli g\u0142\u00f3wnie seedujesz torrenty z peerami, kt\u00f3rzy utkn\u0119li z transferem, preferowanie tych z wi\u0119kszym ruchem ma wi\u0119kszy sens.\nGdy g\u0142\u00f3wnie seedujesz torrenty z wysok\u0105 dost\u0119pno\u015bci\u0105, preferowanie tych z mnijeszym ruchem ma wi\u0119kszy sens. ConfigView.label.seeding.preferLargerSwarms=Gdy torrenty maj\u0105 te same miejsce w rankingu, preferuj te z wi\u0119kszym ruchem wok\u00f3\u0142 nich ConfigView.label.seeding.rankType.none.tooltip=Kolejno\u015b\u0107 bazuje na kolumnie # ConfigView.label.seeding.rankType.none=Brak ConfigView.label.seeding.rankType.peer.tooltip=wi\u0119cej peer\u00f3w i mniej seed\u00f3w = wy\u017csza ranga\nRanking ten minimalizuje liczb\u0119 torrent\u00f3w, kt\u00f3re musz\u0105 pozosta\u0107 aktywne do zwi\u0119kszenia wysy\u0142ania ConfigView.label.seeding.rankType.peer=Uprzywilejowana ilo\u015b\u0107 peer\u00f3w ConfigView.label.seeding.rankType.peerSeed.options=Opcje wsp\u00f3\u0142czynnika Seed\u00f3w:Peer\u00f3w ConfigView.label.seeding.rankType.peerSeed.tooltip=Wy\u017cszy wsp\u00f3\u0142czynnik = Wy\u017cej w rankingu ConfigView.label.seeding.rankType.peerSeed=Wsp\u00f3\u0142czynnik Peer\u00f3w:Seed\u00f3w ConfigView.label.seeding.rankType.seed.fallback=Zako\u0144cz je\u015bli wsp\u00f3\u0142czynnik Peer\u00f3w:Seed\u00f3w po\n[0: Nigdy nie ko\u0144cz] ConfigView.label.seeding.rankType.seed.options=Opcje liczenia samych seed\u00f3w ConfigView.label.seeding.rankType.seed.tooltip=Mniej seed\u00f3w = Wy\u017cej w rankingu ConfigView.label.seeding.rankType.seed=Licz tylko seedy ConfigView.label.seeding.rankType.timedRotation.tooltip=Wszystkie uko\u0144czone torrenty b\u0119d\u0105 w kolejce do udost\u0119pniania.\nCzas trwania seedowania jest ustawiany przez 'Minimalny czas seedowania' ConfigView.label.seeding.rankType.timedRotation=Mierzona rotacja ConfigView.label.seeding.rankType.tooltip=Torrenty, b\u0119d\u0105ce wysoko w rankingu s\u0105 automatycznie uruchamiane.\nGdy inny torrent ma najwy\u017cszy ranking, ten z ni\u017cszym jest zatrzymywany i wraca do kolejki.\n\nTylko torrenty w kolejce s\u0105 dost\u0119pne do automatycznego uruchamiania.\nZatrzymane torrenty nigdy nie s\u0105 automatycznie uruchamiane. ConfigView.label.seeding.rankType=Oce\u0144 uko\u0144czone torrenty dla autostartu bazuj\u0105c na: ConfigView.label.stopAfterMinutes=Gdy przechodzisz w tryb seedowania, zatrzymaj po czasie trwania ConfigView.label.switchpriority.tooltip=Niski priorytet ogranicza zapychanie pasma wysy\u0142ania przyznanego dla torrenta. ConfigView.pluginlist.info=Poni\u017csze wtyczki zosta\u0142y zidentyfikowane. Niekt\u00f3re z nich mog\u0105 by\u0107 pozbawione zak\u0142adek konfiguracyjnych. ConfigView.pluginlist.noplugins=Nie znaleziono \u017cadnych wtyczek. ConfigView.section.pluginslist=Lista ConfigView.section.queue.seeding=Seedowanie ConfigView.section.queue.seeding.autoStarting=Automatyczny start ConfigView.section.queue.seeding.ignore=Ignoruj regu\u0142y ConfigView.section.queue.seeding.firstPriority=Najwy\u017cszy priorytet ConfigView.section.queue.main=G\u0142\u00f3wne ConfigView.section.queue=Kolejkowanie ConfigView.section.torrents=Torrenty ConfigView.text.all=wszystkie ConfigView.text.hours=godziny ConfigView.text.ignoreRule=Ignoruj regu\u0142\u0119 ConfigView.text.ignore=Ignoruj ConfigView.text.minutes=minuty ConfigView.text.neverIgnore=Nigdy nie ignoruj ConfigView.text.any=jakikolwiek DownloadManager.error.datamissing=Brak danych MainWindow.menu.file.open.torrentforseeding=Plik torrent (do seedowania) MainWindow.menu.language.refresh=&Od\u015bwie\u017c ManagerItem.forced=Wymuszone ManagerItem.queued=W kolejce MySeedersView.header=Uko\u0144czone torrenty TableColumn.header.availability.info=Widziano # pe\u0142nych kopii TableColumn.header.availability=Dost\u0119pno\u015b\u0107 TableColumn.header.category=Kategoria MyTorrentsView.header=Niekompletne torrenty TableColumn.header.maxuploads=Maksymalnie # wysy\u0142anych MyTorrentsView.menu.category.delete=&Usu\u0144 kategori\u0119 MyTorrentsView.menu.forceStart=&Wymu\u015b start MyTorrentsView.menu.queue=&Kolejka MyTorrentsView.menu.setCategory.add=&Dodaj kategori\u0119... MyTorrentsView.menu.setCategory=Ustaw kategori\u0119 TableColumn.header.savepath=\u015acie\u017cka zapisu TableColumn.header.SeedingRank=Ranking seedowania TableColumn.header.totalspeed.info=Ca\u0142kowita pr\u0119dko\u015b\u0107 wszystkich torrent\u00f3w TableColumn.header.totalspeed=Pr\u0119dko\u015b\u0107 ca\u0142kowita splash.initializePlugins=Uruchamianie wtyczek StartStopRules.0Peers=0 peer\u00f3w StartStopRules.numSeedsMet=# Seedy OK StartStopRules.ratioMet=Peery:Seedy OK StartStopRules.shareRatioMet=Share ratio OK StartStopRules.waiting=Oczekiwanie StartStopRules.firstPriority=Najwy\u017cszy priorytet ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Podziel zawarto\u015bci DownloadManager.error.unabletostartserver=Nie mo\u017cna uruchomi\u0107 serwera - sprawd\u017a konfiguracj\u0119 portu przychodz\u0105cego / dopu\u015b\u0107 program do po\u0142\u0105cze\u0144 z internetem na firewallu GeneralView.label.creationdate=Utworzono : ConfigView.section.tracker.announcescrapepercentage=Okre\u015bl przedzia\u0142 jako %udzia\u0142\nnp. 200 = 2:1. 0 = niech decyduje peer ManagerItem.stopping=Zatrzymywanie ConfigView.section.tracker.announcecacheperiod=Okre\u015bl pami\u0119\u0107 podr\u0119czn\u0105 (milisekundy) ConfigView.section.tracker.scrapecacheperiod=Okre\u015bl pami\u0119\u0107 podr\u0119czn\u0105 (milisekundy) ConfigView.section.tracker.scrapeandcache=Okre\u015bl pami\u0119\u0107 podr\u0119czn\u0105 ConfigView.section.tracker.announcecacheminpeers=Okre\u015bl pr\u00f3g pami\u0119ci podr\u0119cznej MyTrackerView.scrapes=Oszcz\u0119dzono fileDownloadWindow.retry=Powt\u00f3rz MyTrackerView.bytesin=Bajt\u00f3w odebranych MyTrackerView.bytesinave=\u015arednio MyTrackerView.bytesout=Bajt\u00f3w wys\u0142anych MyTrackerView.bytesoutave=\u015arednio ConfigView.section.file.max_open_files=Maksymalna ilo\u015b\u0107 plik\u00f3w otwartych na odczyt/zapis\n[0: nieograniczona] ConfigView.section.file.max_open_files.tooltip=Pomocne, je\u015bli pobierasz torrenty z setkami/tysi\u0105cami plik\u00f3w i osi\u0105gasz limit obs\u0142ugi plik\u00f3w przez system operacyjny. ConfigView.section.proxy=Opcje Proxy ConfigView.section.proxy.enable_proxy=W\u0142\u0105cz proxy dla komunikacji trackera [wymagane ponowne uruchomienie] ConfigView.section.proxy.username=Nazwa u\u017cytkownika ConfigView.section.proxy.password=Has\u0142o ConfigView.section.proxy.enable_socks=Mam SOCKS proxy wizard.createtorrent.extrahashes=Dodawaj hashy dla innych sieci (np. Gnutella2, eDonkey2000) GeneralView.label.connected=po\u0142\u0105czony(ch) GeneralView.label.in_swarm=oczekuj\u0105cy(ch) ManagerItem.initializing=Uruchamianie AlertMessageBox.error=B\u0142\u0105d AlertMessageBox.warning=Ostrze\u017cenie AlertMessageBox.comment=Informacja AlertMessageBox.information=Informacja AlertMessageBox.unread=Masz nieprzeczytane alerty - kliknij tutaj, aby je wy\u015bwietli\u0107. SharedPortServer.alert.selectorfailed=B\u0142\u0105d przy ustawianiu nas\u0142uchu dla danych przychodz\u0105cych.\nSprawd\u017a konfiguracj\u0119 firewalla na dopuszczenie pliku java(w).exe do zachowywania si\u0119 jako 'serwer' Tracker.alert.listenfail=Nieudane nas\u0142uchiwanie na porcie %1.\nSprawd\u017a czy inna aplikacja nie u\u017cywa tego portu.\nSprawd\u017a te\u017c czy nie jest uruchomiona kolejna kopia Vuze. DiskManager.alert.movefileexists=B\u0142\u0105d przy przenoszeniu uko\u0144czonego plik\nPlik %1 ju\u017c wyst\u0119puje w tym katalogu DiskManager.alert.movefilefails=B\u0142\u0105d przy przenoszeniu uko\u0144czonych plik\u00f3w\nPrzenoszenie %1 nieudane, %2 DiskManager.alert.movefilerecoveryfails=B\u0142\u0105d podczas odzyskiwania po nieudanym przenoszeniu \nOdzyskiwanie pliku %1 nieudane, %2 ConfigView.section.tracker.logenable=Cykliczne zapisywanie statystyk do 'tracker.log' SpeedView.stats.title=Statystyki SpeedView.stats.total=Ca\u0142kowicie SpeedView.stats.session=Ta sesja SpeedView.stats.session.tooltip=Ca\u0142kowicie (protok\u00f3\u0142) SpeedView.stats.downloaded=Pobrano (protok\u00f3\u0142) SpeedView.stats.uploaded=Wys\u0142ano (protok\u00f3\u0142) SpeedView.stats.uptime=Czas pracy SpeedView.stats.now=Teraz SpeedView.stats.now.tooltip=Ca\u0142kowicie (protok\u00f3\u0142) AutoMigration.useralert=Pliki konfiguracyjne u\u017cytkownika/Wyniki auto-migracji katalog\u00f3w:\n\n%1\nW razie b\u0142\u0119d\u00f3w migracj\u0119 przeprowadzi\u0107 r\u0119cznie.\nNIE ZAPOMNIJ UAKTUALNI\u0106 SWOICH \u015aCIE\u017bEK ZAPISU W KONFIGURACJI JE\u015aLI BY\u0141Y PRZENIESIONE! # # > 2.0.8.0 # OpenTorrentWindow.title=Otw\u00f3rz torrent(y) OpenTorrentWindow.message=Eksperymentalny OpenTorrentWindow.addFiles=&Dodaj pliki OpenTorrentWindow.dataLocation=Lokalizacja do zapisania danych: OpenTorrentWindow.startMode=Dodaj tryb OpenTorrentWindow.startMode.queued=W kolejce OpenTorrentWindow.startMode.stopped=Zatrzymany OpenTorrentWindow.startMode.forceStarted=Wymuszone uruchomienie OpenTorrentWindow.addPosition=Pozycja w kolejce OpenTorrentWindow.addPosition.first=Pierwszy OpenTorrentWindow.addPosition.last=Ostatni TableColumn.header.remaining.info=Rozmiar do zako\u0144czenia pobierania TableColumn.header.remaining=Pozosta\u0142o ConfigView.section.tracker.enablecompact=W\u0142acz kompaktowy protok\u00f3\u0142 og\u0142aszania ConfigView.section.tracker.enablekey=W\u0142\u0105cz sprawdzanie klucza do trackera w celu zwi\u0119kszenia bezpiecze\u0144stwa ConfigView.section.file.perf=Opcje wp\u0142ywaj\u0105ce na wydajno\u015b\u0107 ConfigView.section.file.perf.explain=Ostrze\u017cenie - nieumiej\u0119tne wprowadzanie zmian w tych parametrach programu mo\u017ce spowodowa\u0107 k\u0142opoty z pobieraniem lub jego znaczne spowolnienie. Wymagany restart.\nJe\u015bli masz problemy typu "out of memory" rozwa\u017c ograniczenie po\u0142\u0105cze\u0144 na torrent (zobacz konfiguracja transferu) ConfigView.section.file.max_open_files.explain=Otwieranie zbyt wielu plik\u00f3w mo\u017ce spowodowa\u0107 problemy z systemem operacyjnym. Ta opcja przyznaje limity na ilo\u015b\u0107 otwieranych plik\u00f3w. popup.error.hide=Ukryj popup.error.details=Szczeg\u00f3\u0142y ConfigView.section.style.colorOverrides=Wyst\u0105pienie koloru ConfigView.section.style.colorOverride.progressBar=Pasek post\u0119pu ConfigView.section.style.colorOverride.error=B\u0142\u0105d MainWindow.status.tooOld=jest stara, prosz\u0119 zaktualizowa\u0107. ConfigView.section.style.colorOverride.warning=Ostrze\u017cenie ConfigView.section.style.colorOverride.altRow=Kolejne rz\u0119dy ConfigView.section.file.save.peers.enable=Zapisuj po\u0142\u0105czenia peer\u00f3w w celu szybkiego wznowienia po\u0142\u0105czenia po jego utracie ConfigView.section.file.save.peers.max=Maksymalna ilo\u015b\u0107 zapisywanych po\u0142\u0105cze\u0144 peer\u00f3w [0: nieograniczona] ConfigView.section.file.save.peers.pertorrent=na torrent ConfigView.label.max_peers_per_torrent=Maksymalna ilo\u015b\u0107 po\u0142\u0105cze\u0144 na torrent [0: nieograniczona] ConfigView.label.max_peers_total=Maksymalna ilo\u015b\u0107 po\u0142\u0105cze\u0144 (globalnie) [0: nieograniczona] ConfigView.section.style.colorOverrides.reset=Resetuj kolor ConfigView.section.language.info=Gdy w\u0142\u0105czone, sprawdzanie aktualizacji odbywa\u0107 si\u0119 b\u0119dzie przy ka\u017cdym uruchomieniu aplikacji Vuze. ConfigView.section.language.enableUpdate=W\u0142\u0105cz aktualizacje sieciowe ConfigView.section.language.UpdateURL=Adres aktualizacji ConfigView.section.language.UpdateNow=Aktualizuj teraz! Button.revert=Powr\u00f3t MyTorrentsView.menu.changeDirectory=Zmie\u0144 katalog z danymi GenericText.column=kolumna MyTorrentsView.menu.thisColumn.remove=Usu\u0144 kolumn\u0119 MyTorrentsView.menu.thisColumn.toClipboard=Skopiuj tekst do schowka MyTorrentsView.menu.thisColumn.autoTooltip=Zawsze wy\u015bwietlaj pasek narz\u0119dziowy ConfigView.download.abbreviated=P: ConfigView.upload.abbreviated=W: TableColumn.header.secondsseeding=Wysy\u0142ano przez TableColumn.header.secondsseeding.info=Ca\u0142kowity czas dotychczasowego seedowania. TableColumn.header.secondsdownloading=Pobierano przez TableColumn.header.secondsdownloading.info=Ilo\u015b\u0107 czasu dotychczasowego pobierania. ConfigView.section.tracker.udpversion=Wersja protoko\u0142u UDP (1 lub 2) window.updateswt.title=Wersja SWT jest za stara! window.updateswt.text=Wersja SWT jest za stara!\nSWT jest bibliotek\u0105 graficzn\u0105 u\u017cywan\u0105 przez Vuze, a wersja kt\u00f3r\u0105 aktualnie posiadasz nie pozwala na uruchomienie najnowszej wersji. Naci\u015bnij OK, aby uaktualni\u0107 SWT. window.updateswt.failed=Aktualizacja nieudana, naci\u015bnij OK, aby ponownie uruchomi\u0107. window.updateswt.status.downloading.updater=Pobieranie modu\u0142u aktualizacyjnego window.updateswt.status.finding=Szukanie najnowszej wersji SWT window.updateswt.status.downloading=Pobieranie najnowszej wersji SWT window.updateswt.status.done=Ponowne uruchamianie window.updateswt.cancel=Anuluj swt.updater.downloader.downloading=Pobieranie SWT z swt.updater.urlsgetter.downloading=Pobieram list\u0119 mirror\u00f3w z swt.updater.urlsgetter.platform=SWT dla platformy : window.updateswt.ignore=Ignoruj ConfigView.section.style.useFancyTabs=U\u017cyj fantazyjnych zak\u0142adek splash.initializeGM=Uruchamianie globalnego managera torrent\u00f3w splash.loadingTorrents=\u0141adowanie torrent\u00f3w MyTorrentsView.menu.thisColumn.sort=&Sortuj Scrape.status.ok=Omini\u0119cie OK Scrape.status.error=B\u0142\u0105d omijania: Scrape.status.error.badURL=URL Announce niezgodny do specyfikacji omijania. Scrape.status.error.nohash=Brak Hash-a w odpowiedzi. Scrape.status.error.invalid=Nieprawid\u0142owa odpowied\u017a. Scrape.status.nextScrapeAt=Nast\u0119pne sprawdzanie za %1 Scrape.status.scraping=Omijanie... Scrape.status.initializing=Oczekiwanie na omini\u0119cie... Scrape.status.scraping.queued=Omijanie w kolejce... ConfigView.label.minSpeedForActiveSeeding=Nie uwzgl\u0119dniaj uko\u0144czonego torrenta jako u\u017cycie gniazda, je\u015bli pr\u0119dko\u015b\u0107 jest poni\u017cej ConfigView.section.stats.exportpeers=Szczeg\u00f3\u0142y eksportu peer\u00f3w MainWindow.menu.view.irc.moved=IRC jest teraz dost\u0119pny jako wtyczka, zobacz http://azureus.sourceforge.net/plugin_list.php. Po zainstalowaniu przejd\u017a do widok->wtyczki->menu IRC, aby uruchomi\u0107. MyTrackerView.webui.contextmenu.copyurl=Kopiuje URL torrenta do schowka ConfigView.section.file.torrent.ignorefiles=Ignorowane pliki podczas tworzenia/usuwania torrent\u00f3w\nnp. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignorowanie pliku ConfigView.section.style.useUnitsRateBits=U\u017cyj bit\u00f3w zamiast bajt\u00f3w dla bazuj\u0105cych na bajtach warto\u015bciach (KiB/s->Kibit/s etc.) ConfigView.section.interface.resetassoc=Resetuj powi\u0105zania pliku (.torrent) ConfigView.section.interface.resetassocbutton=Uruchom ponownie ConfigView.section.interface.checkassoc=Sprawd\u017a powi\u0105zania na starcie dialog.associations.title=Sprawdzanie powi\u0105za\u0144 Button.yes=Tak Button.no=Nie ConfigView.label.seeding.autoStart0Peers=Automatycznie uruchom wszystkie uko\u0144czone torrenty z 0 peer\u00f3w ConfigView.label.seeding.autoStart0Peers.tooltip=W\u0142\u0105cz je\u015bli chcesz, aby tracker tworzy\u0142 list\u0119 seed\u00f3w dla torrent\u00f3w z 0 peerami. dialog.associations.prompt=Vuze nie jest domy\u015bln\u0105 aplikacj\u0105 plik\u00f3w BitTorrent.\nCzy chcesz powi\u0105za\u0107 pliki .torrent z Vuze? dialog.associations.askagain=Sprawd\u017a przy uruchamianiu ConfigView.section.plugins.update=Aktualizacja plugin\u00f3w Plugin.pluginupdate.enablecheck=W\u0142\u0105cz sprawdzanie aktualizacji wtyczek plugins.basicview.activity=Aktywno\u015b\u0107: plugins.basicview.progress=Post\u0119p: ConfigView.label.maxdownloadspeed=Globalna maksymalna pr\u0119dko\u015b\u0107 pobierania KB/s [0: nieograniczona] splash.loadingTorrent=\u0141adowanie torrenta splash.of=z UpdateWindow.title=Aktualizator Vuze UpdateWindow.header=Nastepuj\u0105ce komponenty potrzebuj\u0105 aktualizacji : UpdateWindow.columns.install=Instaluj UpdateWindow.columns.name=Nazwa UpdateWindow.columns.version=Wersja UpdateWindow.columns.size=Rozmiar UpdateWindow.cancel=Anuluj UpdateWindow.quit=Wyj\u015bcie UpdateWindow.close=Zamknij UpdateWindow.ok=Aktualizacja UpdateWindow.restart=Uruchom ponownie UpdateWindow.status.downloading=Pobieranie UpdateWindow.status.done=Zako\u0144czono UpdateWindow.status.failed=Nieudane UpdateWindow.status.restartNeeded=B\u0119dzie wymagane ponowne uruchomienie! ConfigView.pluginlist.broken=Uszkodzony ConfigView.pluginlist.whereToPut=Umie\u015b\u0107 inne wtyczki u\u017cytkownika w ich w\u0142asnym katalogu o nazwie: ConfigView.pluginlist.whereToPutOr=Dla wtyczek wsp\u00f3\u0142dzielonych u\u017cyj: MainWindow.statusText.checking=Sprawdzanie aktualizacji TableColumn.header.OnlyCDing4=Tylko seedowanie TableColumn.header.OnlyCDing4.info=Pokazuje czas, w kt\u00f3rym torrent by\u0142 tylko seedowany. Nie uwzgl\u0119dnia czasu, w kt\u00f3rym torrent by\u0142 pobierany ( i seedowany). ConfigView.section.style.alternateTablePainting=U\u017cyj alternatywnej metody wype\u0142niania graficznie kolumn tabeli (mo\u017ce wymaga\u0107 ponownego uruchomienia) UpdateWindow.status.restartMaybeNeeded=Mo\u017ce by\u0107 potrzebne ponowne uruchomienie ConfigView.pluginlist.shared=udost\u0119pnione PeersView.host=Nazwa hosta PeersView.host.info=Nazwa hosta peera, gdzie dost\u0119pne (mo\u017ce zmniejszy\u0107 wydajno\u015b\u0107) MainWindow.menu.help.whatsnew=Co nowego ConfigView.label.checkonstart=Sprawd\u017a najnowsz\u0105 wersj\u0119 podczas uruchamiania Vuze ConfigView.label.periodiccheck=Sprawdzaj okresowo najnowsz\u0105 wersj\u0119 ConfigView.label.opendialog=Automatycznie otw\u00f3rz Asystenta aktualizacji gdy dost\u0119pna jest aktualizacja MainWindow.updateavail=Kliknij tutaj po aktualizacje MainWindow.status.latestversionunchecked=Sprawdzanie wersji wy\u0142\u0105czone GeneralView.label.updatein.stopped=Zatrzymano StartStopRules.menu.viewDebug=Zobacz informacj\u0119 o debugowaniu ConfigView.section.style.doNotUseGB=Nie u\u017cywaj jednostki GB ConfigView.section.style.doNotUseGB.tooltip=Je\u015bli zaznaczony, Vuze b\u0119dzie u\u017cywa\u0142 MB nawet dla plik\u00f3w wi\u0119kszych ni\u017c 1024MB MainWindow.menu.help.plugins=Pobierz wtyczki ConfigView.section.plugins.TrackerWeb=Tracker sieci ConfigView.section.tracker.enablecategories=Oddziel torrenty wed\u0142ug kategorii health.explain.share=oznacza, \u017ce torrent jest ju\u017c hostowany lub opublikowany ConfigView.section.tracker.createcert=Utw\u00f3rz certyfikat w\u0142asnor\u0119czny ConfigView.section.tracker.createbutton=Utw\u00f3rz security.certcreate.title=Utw\u00f3rz w\u0142asnor\u0119czny certyfikat security.certcreate.intro=Tutaj mo\u017cesz utworzy\u0107 w\u0142asnor\u0119czny certyfikat security.certcreate.strength=Si\u0142a security.certcreate.firstlastname=Imi\u0119 i nazwisko security.certcreate.orgunit=Jednostka organizacyjna security.certcreate.org=Organizacja security.certcreate.city=Miasto lub lokalizacja security.certcreate.state=Wojew\u00f3dztwo security.certcreate.country=Dwuliterowy kod kraju security.certcreate.ok=Utw\u00f3rz security.certcreate.cancel=Anuluj security.certcreate.createok=Udane utworzenie certyfikatu security.certcreate.createfail=Nieudane utworzenie certyfikatu ConfigView.section.plugins.webui=Interfejs Swing Web ConfigView.section.plugins.xml_http_if=Interfejs XML/HTTP webui.passwordenable=W\u0142\u0105cz has\u0142o webui.user=Nazwa u\u017cytkownika webui.password=Has\u0142o webui.protocol=Protok\u00f3\u0142 (*) webui.homepage=Strona domowa (*) webui.rootdir=Katalog g\u0142\u00f3wny (*) webui.rootres=Zas\u00f3b g\u0142\u00f3wny (*) webui.mode=Tryb (*) webui.mode.info=Tryb mo\u017ce by\u0107\n\t"pe\u0142ny"\t= wszystkie operacje mo\u017cliwe (domy\u015blnie)\n\t"widok"\t= tylko przegl\u0105danie (lecz mo\u017cna aktualizowa\u0107 cz\u0119stotliwo\u015b\u0107 od\u015bwie\u017cania) webui.access=Dost\u0119p (*) webui.access.info=Dost\u0119p mo\u017ce by\u0107\n\t"lokalny"\t = tylko lokalny komputer mo\u017ce uzyska\u0107 dost\u0119p\n\t"wszystkie" = dost\u0119p bez restrykcji (domy\u015blnie)\n\tIP\t = np. 192.168.0.2\ttylko tonowe IP \n\tIP1-IP2\t = np. 192.168.0.1-192.168.0.255\tobejmuj\u0105cy ca\u0142y zakres adres\u00f3w IP GeneralView.label.maxdownloadspeed=Limit pobierania Security.keystore.corrupt=Przechowanie klucza '%1' p nieudane rzy \u0142adowaniu, usu\u0144 je i utw\u00f3rz od nowa lub ponownie zaimportuj certyfikaty Security.keystore.empty=Klucz pusty. Utw\u00f3rz w\u0142\u0105snor\u0119czny certyfikat (Narz\u0119dzia->Opcje->Ochrona) lub importuj istniej\u0105cy certyfikat do '%1 webui.restart.info=Zmiana w parametrach oznaczanych jako (*) wymagane ponownego uruchomienia. GeneralView.label.maxdownloadspeed.tooltip=maksymalna pr\u0119dko\u015b\u0107 pobierania [0: nieograniczona] upnp.enable=W\u0142\u0105cz UPnP upnp.info=Universal Plug and Play (UPnP) pozwala na automatyczne mapowanie port\u00f3w na routerach korzystaj\u0105cych z UPnP upnp.mapping.dataport=Port przychodz\u0105cy peera upnp.mapping.tcptrackerport=Port trackera TCP upnp.mapping.udptrackerport=Port trackera UDP upnp.alert.differenthost=UPnP: Mapowanie '%1' zosta\u0142o zarezerwowane przez '%2' - wybierz inny port upnp.alert.mappingok=UPnP: Mapowanie '%1' ustanowione upnp.alert.mappingfailed=UPnP: Mapowanie '%1' nieudane upnp.alertsuccess=Raportuj udane mapowanie upnp.alert.lostdevice=UPnP: Utracono po\u0142\u0105czenie z us\u0142ug\u0105 '%1' na urz\u0105dzeniu UPnP '%2' upnp.grabports=Mapuj porty nawet, gdy s\u0105 ju\u017c u\u017cywane na innych komputerach upnp.refresh.label=Od\u015bwie\u017c mapowanie upnp.refresh.button=Od\u015bwie\u017c upnp.alert.mappinggrabbed=UPnP: Mapowanie '%1' ustanowione - przechwycono z '%2' upnp.mapping.tcpssltrackerport=Port trackera TCP SSL upnp.alertothermappings=Raportuj porty posiadane przez inne komputery upnp.alertdeviceproblems=Raportuj problemy z urz\u0105dzeniem UPnP upnp.trace_to_log=Zapisuj pe\u0142n\u0105 informacj\u0119 diagnostyczn\u0105 do pliku logowania upnp.wiki_link=Strona Vuze Wiki o UPnP upnp.refresh_mappings_on_bad_nat=Automatycznie od\u015bwie\u017a mapowanie, kiedy status NAT jest ustawiony na "firewalled" blank.resource=Zasoby ConfigView.pluginlist.coreplugins=Nast\u0119puj\u0105ce wbudowane wtyczki zosta\u0142y za\u0142adowane: Peers.column.DLedFromOthers=Od innych Peers.column.DLedFromOthers.info=Ilo\u015b\u0107 danych pobranych od innych u\u017cytkownik\u00f3w, kt\u00f3rzy si\u0119 z Tob\u0105 \u0142\u0105czyli Peers.column.UpDownRatio=Wys\u0142ano:Pobrano Peers.column.UpDownRatio.info=Wsp\u00f3\u0142czynnik "wys\u0142anych : pobranych" peera Peers.column.UpRatio=Wsp\u00f3\u0142czynnik wysy\u0142ania Peers.column.UpRatio.info=Wsp\u00f3\u0142czynnik "wysy\u0142ania od Ciebie : wysy\u0142ania od innych" peera upnp.releasemappings=Zaprzesta\u0144 mapowania przy wyj\u015bciu webui.upnpenable=W\u0142\u0105cz UPnP dla tego portu (*) ConfigView.section.file.friendly.hashchecking=Przyjazne sprawdzanie hash-a ConfigView.section.file.friendly.hashchecking.tooltip=Troszeczk\u0119 wolniejsze, ale mniej obci\u0105\u017caj\u0105ce procesor/system sprawdzanie cz\u0119\u015bci hash-a. ConfigView.section.tracker.seedretention=Maksymalna ilo\u015b\u0107 seed\u00f3w na torrent [0: nieograniczona] ConfigView.section.tracker.seedretention.info=Uwaga: Statystyki wysy\u0142ania zostan\u0105 utracone po od\u0142\u0105czeniu seeda ConfigView.section.tracker.port=W\u0142\u0105cz tracker na porcie HTTP ConfigView.section.tracker.sslport=W\u0142\u0105cz tracker na porcie HTTPS ConfigView.section.tracker.publicenable.info=Ta opcja pozwala innym na tworzenie torrent\u00f3w korzystaj\u0105cych\nz Twojego trackera bez Twojego hostingu/publikuj\u0105c go Button.clear=Wyczy\u015b\u0107 MainWindow.IPs.tooltip=Ostatnia aktualizacja listy filtr\u00f3w: %1\nLiczba filtr\u00f3w IP na li\u015bcie - Liczba zablokowanych/zbanowanych/nieprawid\u0142owych adres\u00f3w IP.\nPodw\u00f3jne klikni\u0119cie po szczeg\u00f3\u0142y. ConfigView.section.ipfilter.list.banned=zosta\u0142 zbanowany ConfigView.section.ipfilter.list.baddata=wys\u0142a\u0142 z\u0142e dane: zdarzenia = Button.reset=Uruchom ponownie ConfigView.section.ipfilter.bannedinfo=Adresy IP z kt\u00f3rych wys\u0142ano z\u0142e dane - banowane je\u015bli przekroczono limit ConfigView.section.ipfilter.blockedinfo=Adresy IP, kt\u00f3re zosta\u0142y zablokowane poprzez filtry IP download.removerules.name=Regu\u0142y usuwania download.removerules.unauthorised.info=Nieautoryzowane torrenty to takie, przy kt\u00f3rych w odpowiedzi trackera wyst\u0119puje "not authorized" lub "unauthorized" download.removerules.unauthorised=Automatycznie usuwaj torrenty bez autoryzacji download.removerules.unauthorised.seedingonly=\tTylko, je\u015bli seeduj\u0119 download.removerules.removed.ok=Automatycznie usuwaj torrenty sko\u0144czone w '%1'. Spowodowane jest to regu\u0142ami usuwania torrent\u00f3w. download.removerules.updatetorrents=Usu\u0144 aktualizacj\u0119 torrent\u00f3w Vuze, je\u015bli wymaga oczekuj\u0105cy ConfigView.label.defaultstarttorrentsstopped=Domy\u015blnie dodaj nowe torrenty w stanie wstrzymanym ConfigView.section.server.enableudp=W\u0142\u0105cz protok\u00f3\u0142 UDP trackera upnp.mapping.dataportudp=Kliencki port trackera UDP ConfigView.section.file.decoder.showlax=Pokazuj mniej prawdopodobne kodowania ConfigView.section.file.decoder.showall=Bierz pod uwag\u0119 wszystkie mo\u017cliwe sposoby kodowania MainWindow.status.updowndetails.tooltip=Szczeg\u00f3\u0142y pr\u0119dko\u015bci pobierania/wysy\u0142ania \nKliknij prawym przyciskiem, aby zmieni\u0107, kliknij dwukrotnie, aby otworzy\u0107 statystyki TrackerClient.announce.warningmessage=Tracker dla '%1' zwr\u00f3ci\u0142 ostrze\u017cenie '%2' ConfigView.section.tracker.natcheckenable=Sprawd\u017a 'port danych przychodz\u0105cych' i raportuj b\u0142\u0119dy do peer\u00f3w ConfigView.section.tracker.publishenabledetails=Publikuj wszystkie szczeg\u00f3\u0142y torrenta ConfigView.section.tracker.publishenablepeerdetails=Publikuj szczeg\u00f3\u0142y o peerach MyTrackerView.badnat=B\u0142\u0105d NAT MyTrackerView.badnat.info=Sprawdzenie Seed\u00f3w/Peer\u00f3w z b\u0142\u0119dnym NAT-em check, je\u015bli w\u0142\u0105czone ConfigView.section.tracker.natchecktimeout=Sprawd\u017a czas oczekiwania (sekundy) ConfigView.section.file.perf.cache.enable=W\u0142\u0105cz cache dysku twardego ConfigView.section.file.perf.cache.size=Rozmiar pami\u0119ci podr\u0119cznej w %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=T&ransfery MainWindow.menu.transfers.startalltransfers=Ur&uchom wszystkie MainWindow.menu.transfers.stopalltransfers=Za&trzymaj wszystkie MainWindow.menu.transfers.pausetransfers=&Pauza MainWindow.menu.transfers.resumetransfers=&Wzn\u00f3w ConfigView.label.experimental.osx.kernel.panic.fix=Eksperymentalny fix dla system\u00f3w dwuprocesorowych [wymaga restartu] SystemTray.menu.pausetransfers=Przerwij transfery SystemTray.menu.resumetransfers=Wzn\u00f3w transfery ConfigView.section.file.truncate.too.large=Przytnij istniej\u0105ce pliki, kt\u00f3re s\u0105 za du\u017ce ConfigView.section.file.perf.cache.trace=\u015aled\u017a operacje w pami\u0119ci podr\u0119cznej w celach diagnostycznych ConfigView.section.interface.enabletray=W\u0142\u0105cz pasek systemowy [wymagany ponowne uruchomienie] PeerManager.status.error=B\u0142\u0105d Stats.title.full=Statystyki TransferStatsView.title.full=Transfery CacheView.general.size=Ca\u0142kowity rozmiar CacheView.general.inUse=W u\u017cyciu CacheView.general.title=Cache - info CacheView.reads.title=Odczyty I/O CacheView.reads.fromFile=Z pliku CacheView.reads.fromCache=Z pami\u0119ci cache CacheView.reads.hits=Trafie\u0144 CacheView.writes.title=Zapis\u00f3w I/O CacheView.writes.toCache=Do pamieci cache CacheView.writes.toFile=Do pliku CacheView.writes.hits=Zapisane CacheView.speeds.title=Pr\u0119dko\u015b\u0107 transmisji CacheView.speeds.reads=Odczyt\u00f3w CacheView.speeds.writes=Zapis\u00f3w CacheView.speeds.fromCache=Z/Do pami\u0119ci cache CacheView.speeds.fromFile=Z/Do pliku CacheView.reads.amount=Ilo\u015b\u0107 CacheView.reads.avgsize=\u015aredni rozmiar openUrl.referrer=Skierowanie strony URL : openUrl.referrer.info=Wymagane tylko dla stron z ograniczeniami ConfigView.label.maxuploadspeedseeding=Alternatywna pr\u0119dko\u015b\u0107 gdy tylko seedujesz ConfigView.label.transfer.ignorepeerports=Ignoruj peer\u00f3w z tymi portami (';' jako oddzielenie, np. 0;25) ConfigView.section.proxy.enable_socks.peer=W\u0142\u0105cz komunikacj\u0119 z peerami poprzez proxy (tylko po\u0142\u0105czenia wychodz\u0105ce) [wymagane ponowne uruchomienie] ConfigView.section.proxy.peer.informtracker=Informuj tracker o limitach ConfigView.section.proxy.socks.version=wersja SOCKS PiecesView.legend.written=Zapisanych PiecesView.legend.requested=Potrzebnych PiecesView.legend.downloaded=Pobrane, oczekuj\u0105ce PiecesView.legend.incache=Dane s\u0105 w pami\u0119ci podr\u0119cznej PiecesView.typeItem.0=Wolne PiecesView.typeItem.1=Szybkie PiecesView.type=Typ Security.jar.tools_not_found=B\u0142\u0119dne podpisanie pliku JAR - nie znaleziono 'tools.jar' w %1. Zobacz Narz\u0119dzia->Opcje->Ochrona. Security.jar.signfail=B\u0142\u0119dne podpisanie pliku JAR - %1 ConfigView.section.security.toolsinfo=Podpisane cyfrowo pliki JAR s\u0105 u\u017cywane do wspierania niekt\u00f3rych plugin\u00f3w, np. interfejs Swing Web (je\u015bli skonfigurowany).\nAby podpisa\u0107 cyfrowo pliki JAR potrzebny jest dost\u0119p do pliku 'tools.jar', kt\u00f3re pochodzi z instalacj\u0105 JDK (nie JRE) firmy Sun.\nJe\u015bli masz zainstalowane JRE prosz\u0119 zainstalowa\u0107 JDK.\nVuze potrafi znale\u017a\u0107 plik za Ciebie. Jednak, je\u015bli b\u0119dzie to niemo\u017cliwe mo\u017cesz ustawi\u0107 katalog tutaj. ConfigView.section.security.toolsdir=Katalog zawieraj\u0105cy 'tools.jar' ConfigView.section.security.choosetoolssavedir=Wybierz folder zawieraj\u0105cy 'tools.jar' ConfigView.section.proxy.peer.same=U\u017cyj tych samych ustawie\u0144 proxy dla trackera i komunikacji proxy z peerami ConfigView.section.connection.network.max.simultaneous.connect.attempts=Maksymalna ilo\u015b\u0107 jednoczesnych pr\u00f3b po\u0142\u0105cze\u0144 ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Vuze powinien ustawi\u0107 maksymaln\u0105 liczb\u0119 nowych po\u0142\u0105cze\u0144 wychodzacych w okre\u015blonym czasie.\nUWAGA: WindowsXP Service Pack 2 (SP2) ogranicza liczb\u0119 jednoczesnych po\u0142\u0105cze\u0144 do 10.\nWarto\u015b\u0107 domy\u015blna to 8. ConfigView.section.file.perf.cache.size.explain=Pami\u0119\u0107 podr\u0119czna jest u\u017cywana w celu redukcji zapis/odczyt na dysku. Chyba, \u017ce u\u017cywasz opcj\u0119 javy '-XX:MaxDirectMemorySize' do ustawienia pami\u0119ci dost\u0119pnej dla pami\u0119ci podr\u0119cznej i u\u017cycia sieci IO, powiniene\u015b utrzyma\u0107 t\u0119 warto\u015b\u0107 na poziomie przynajmniej %1 poni\u017cej maksymalnego rozmiaru VM. Obecny maksymalny rozmiar VM to %2. Aby dowiedzie\u0107 si\u0119 jak to zmieni\u0107 zobacz MemoryUsage w wiki %3. Nie zastosowanie si\u0119 do instrukcji mo\u017ce spowodowa\u0107 pojawianie si\u0119 b\u0142\u0119d\u00f3 'out of memory'. Wi\u0119cej ni\u017c 32MB pami\u0119ci podr\u0119cznej jest prawdopodobnie przesad\u0105. MyTorrentsView.menu.setSpeed.unlimit=Brak limitu MyTorrentsView.menu.setSpeed.unlimited=Nieograniczone MyTorrentsView.menu.setSpeed.disable=Wy\u0142\u0105cz wysy\u0142anie MyTorrentsView.menu.setSpeed.disabled=Wy\u0142\u0105czone MyTorrentsView.menu.setSpeed.in=w MyTorrentsView.menu.setSpeed.slots=gniazdach, po GeneralView.label.maxuploadspeed=Limit wysy\u0142ania GeneralView.label.maxuploadspeed.tooltip=maksymalna pr\u0119dko\u015b\u0107 wysy\u0142ania [0: nieograniczona] MyTorrents.items.UpSpeedLimit.disabled=Nie wysy\u0142aj MyTorrents.items.UpSpeedLimit.unlimited=Nieograniczona TableColumn.header.maxupspeed=Maksymalna pr\u0119dko\u015b\u0107 wysy\u0142ania TableColumn.header.maxupspeed.info=Limit pr\u0119dko\u015bci wysy\u0142ania ustawiony na peer ConfigView.section.file.perf.cache.enable.write=Cache przejmuje pobieranie danych w celu zredukowania zapisywania na dysku ConfigView.section.file.perf.cache.enable.read=Wykonaj wyprzedzenie odczyt, aby ograniczy\u0107 odczyt z dysku gdy wysy\u0142asz ConfigView.section.tracker.separatepeerids=U\u017cyj innej identyfikacji peer\u00f3w do komunikacji tracker\u00f3w i danych ConfigView.section.tracker.separatepeerids.info=Zwi\u0119ksza anonimowo\u015b\u0107, je\u015bli pobierasz/udost\u0119pniasz anonimowo\nw przypadku, gdy korzystasz z anonimowego po\u0142\u0105czenia z trackerem ConfigView.section.interface.wavlocation=Lokalizacja plik\u00f3w .wav ConfigView.section.interface.wavlocation.info=Wybierz plik .wav lub zostaw puste dla d\u017awi\u0119ku domy\u015blnego ConfigView.section.tracker.server=Serwer ConfigView.section.tracker.client=Klient ConfigView.section.tracker.client.connecttimeout=Czas oczekiwania na po\u0142\u0105czenie (sek) ConfigView.section.tracker.client.readtimeout=Czas oczekiwania na odczyt (sek) MainWindow.menu.tools=&Narz\u0119dzia FilesView.path=\u015acie\u017cka FilesView.fullpath=Poka\u017c pe\u0142n\u0105 \u015bcie\u017ck\u0119 FilesView.remaining=Pozosta\u0142o cz\u0119\u015bci TableColumn.header.trackername=Nazwa trackera TableColumn.header.trackername.info=Nazwa trakera bazujac na URL-u ConfigView.group.override=Opcje dodatkowe ConfigView.section.file.perf.cache.notsmallerthan=Nie u\u017cywaj pami\u0119ci podr\u0119cznej dla plik\u00f3w mniejszych ni\u017c (w %1) PeersView.menu.blockupload=Blokuj wysy\u0142anie PeersView.menu.kickandban=Odrzu\u0107 i zbanuj PeersView.menu.kickandban.reason=Peer zbanowany recznie PeersView.state=Stan PeersView.state.info=Stan po\u0142\u0105czenia peera PeersView.state.pending=W trakcie PeersView.state.connecting=Pod\u0142\u0105czanie PeersView.state.handshake=Oczekuj\u0119 PeersView.state.established=Po\u0142\u0105czenie ustanowione ConfigView.section.tracker.processinglimits=Limity przetwarzania ConfigView.section.tracker.maxgettime=Maksymalny czas funkcji GET (sek) [0: nieograniczony] ConfigView.section.tracker.maxgettime.info=U\u017cywane w czasie og\u0142aszania torrent\u00f3w ConfigView.section.tracker.maxposttimemultiplier=Mno\u017cnik czasu funkcji POST [0: nieograniczony] ConfigView.section.tracker.maxposttimemultiplier.info=U\u017cywane przy wysy\u0142aniu ConfigView.section.tracker.maxthreads=Maksymalna liczba konkurencyjnych \u017c\u0105da\u0144 DownloadManager.error.operationcancancelled=Operacja anulowana Torrent.create.progress.cancelled=Operacja anulowana sharing.progress.cancel=Anuluj wizard.maketorrents.autoopen=Otw\u00f3rz torrenty do seedowania, gdy zako\u0144czone ConfigView.section.sharing.rescanenable=W\u0142\u0105cz cykliczne skanowanie udost\u0119pnionych plik\u00f3w, aby wykrywa\u0107 zmiany ConfigView.section.sharing.rescanperiod=Cykl skanowania (sekundy) ConfigView.section.connection.advanced=Zaawansowane ustawienia sieci ConfigView.section.connection.advanced.mtu=Jednostka maksymalnej transmisji liniowej (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Maksymalny rozmiar pakietu jaki mo\u017ce by\u0107 przesy\u0142any w jednej ramce w obr\u0119bie sieci.\nVuze u\u017cywa MTU-40 (MSS) dla optymalizacji wysy\u0142ania.\nZalecane warto\u015bci:\n 576 - po\u0142\u0105czenie Dial-up\n1492 - po\u0142\u0105czenie szerokopasmowe PPPoE\n1500 - Ethernet, DSL i sieci telewizji kablowej ConfigView.section.connection.advanced.SO_RCVBUF=Rozmiar socketu SO_RCVBUF [0: u\u017cyj domy\u015blnego dla systemu operacyjnego] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Ustawia standardow\u0105 warto\u015b\u0107 socketu SO_RCVBUF (w bajtach) np. TCP otrzyma rozmiar i skal\u0119 okna.\nVuze pozostawi te nieustawione jako domy\u015blne, w rozumieniu domy\u015blnych warto\u015bci u\u017cywanych w systemie operacyjnym.\nUWAGA: Linuks podwaja wprowadzon\u0105 warto\u015b\u0107. ConfigView.section.connection.advanced.SO_SNDBUF=Rozmiar socketu SO_SNDBUF [0: u\u017cyj domy\u015blnego dla systemu operacyjnego] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Ustawia standardow\u0105 warto\u015b\u0107 socketu SO_SNDBUF (w bajtach) np. TCP wysy\u0142a rozmiar okna.\nVuze pozostawi te nieustawione jako domy\u015blne, w rozumieniu domy\u015blnych warto\u015bci u\u017cywanych w systemie operacyjnym.\nUWAGA: Linuks podwaja wprowadzon\u0105 warto\u015b\u0107. ConfigView.section.connection.advanced.IPDiffServ=Warto\u015b\u0107 pakietu wychodz\u0105czego DiffServ (pole TOS) ConfigView.section.connection.advanced.IPDiffServ.tooltip=Ustawia DiffServ jako cz\u0119\u015b\u0107 w polu typu serwisu (TOS) w nag\u0142\u00f3wku adresu IP dla nadchodz\u0105cych pakiet\u00f3w. Warto\u015bci szesnastkowe mog\u0105 by\u0107 ustawione przez dostawienie na ich pocz\u0105tku '0x', np. 0x10.\nVuze pozostawi te nieustawione jako domy\u015blne, w rozumieniu domy\u015blnych warto\u015bci u\u017cywanych w systemie operacyjnym.\nUWAGA: Ukryte implementacje sieci mog\u0105 ignorowa\u0107 t\u0119 warto\u015b\u0107, dlatego ta opcja opiera si\u0119 o system operacyjny i wersje JRE. ConfigView.section.interface.confirm_torrent_removal=Poka\u017c okno potwierdzenia przy usuwaniu torrent\u00f3w ConfigView.section.interface.confirm_torrent_removal.tooltip=Wy\u015bwietla okno potwierdzenia, gdy usuwasz torrenta z widoku Moje Torrenty MyTorrentsView.confirm_torrent_removal=Czy jeste\u015b pewien, \u017ce chcesz usun\u0105\u0107?\n TableColumn.header.seed_to_peer_ratio=Ratio seed:peer TableColumn.header.seed_to_peer_ratio.info=Ca\u0142kowite ratio seed\u00f3w do peer\u00f3w PeersView.connected_time=Czas pod\u0142\u0105czenia PeersView.connected_time.info=Ca\u0142kowity czas po\u0142\u0105czenia z peerem ConfigView.section.interface.display.add_torrents_silently=Dodawaj torrenty w tle ConfigView.section.interface.display.add_torrents_silently.tooltip=Dodaje torrenty do pobierania bez aktywacji g\u0142\u00f3wnego okna Vuze. TableColumn.header.maxdownspeed=Maksymalna pr\u0119dko\u015b\u0107 pobierania TableColumn.header.maxdownspeed.info=Limit pr\u0119dko\u015b\u0107i pobierania ustawiony na torrent PeersGraphicView.title=Ruch ConfigView.section.tracker.passwordwebhttpsonly=Dopuszczaj tylko po\u0142\u0105czenia przez HTTPS TableColumn.header.torrentpath=Lokalizacja torrenta TableColumn.header.torrentpath.info=Lokalizacja torrenta na dysku ConfigView.section.sharing.torrentcomment=Komentarz dla nowo utworzonych torrent\u00f3w ConfigView.label.copyanddeleteratherthanmove=Skopiuj, a potem usu\u0144 dane zamiast przenoszenia ich do jednej operacji - mo\u017ce to zapobiec utracie danych w przypadku niekt\u00f3rych system\u00f3w plik\u00f3w ConfigView.label.openstatsonstart=Otw\u00f3rz Statystyki po uruchomieniu swt.install.window.title=Instalator wtyczek Vuze swt.install.window.ok=Instaluj swt.install.window.header=Nastepuj\u0105ce komponenty zosta\u0142y wybrane do zainstalowania : swt.uninstall.window.title=Deinstalator wtyczek Vuze swt.uninstall.window.ok=Odinstaluj swt.uninstall.window.header=Nastepuj\u0105ce komponenty zosta\u0142y wybrane do odinstalowania : installPluginsWizard.title=Instaluj wtyczki installPluginsWizard.mode.title=Wybierz metod\u0119 instalacji installPluginsWizard.mode.list=Z listy sourceforge.net installPluginsWizard.list.title=Lista wtyczek do zainstalowania installPluginsWizard.list.loading=Prosz\u0119 czeka\u0107, lista wtyczek jest \u0142adowana. installPluginsWizard.list.loaded=Wybierz wtyczki, kt\u00f3re chcesz zainstalowa\u0107 installPluginsWizard.list.name=Nazwa installPluginsWizard.list.version=Wersja installPluginsWizard.list.description=Opis wtyczki installPluginsWizard.finish.title=Instalacja w toku installPluginsWizard.finish.explanation=Wybrana wtyczka zostanie zainstalowana przy u\u017cyciu Asystenta aktualizacji.\n\nMo\u017ce to zaj\u0105\u0107 chwil\u0119.\n\nAby wy\u015bwietli\u0107 raport post\u0119pu, dwukrotnie kliknij lewym przyciskiem myszy na pasku statusu. installPluginsWizard.details.loading=\u0141aduj\u0119 szczeg\u00f3\u0142y, prosz\u0119 czeka\u0107... installPluginsWizard.mode.file=Z pliku installPluginsWizard.installMode.title=Wybierz typ instalacji installPluginsWizard.installMode.user=Instaluj wtyczk\u0119(ki) tylko dla mnie installPluginsWizard.installMode.shared=Instaluj wtyczk\u0119(ki) dla wszystkich u\u017cytkownik\u00f3w installPluginsWizard.file.title=Przegl\u0105daj w celu wyszukania wtyczki, kt\u00f3r\u0105 chcesz zainstalowa\u0107 installPluginsWizard.file.file=Plik : installPluginsWizard.file.invalidfile=Ten plik nie jest prawid\u0142ow\u0105 wtyczk\u0105 Vuze. installPluginsWizard.file.no_such_file=Nie istnieje plik o podanej nazwie. installPluginsWizard.file.browse=Przegl\u0105daj... uninstallPluginsWizard.title=Odinstaluj wtyczki uninstallPluginsWizard.list.title=Lista zainstalowanych wtyczek uninstallPluginsWizard.list.loaded=Prosz\u0119 wybra\u0107 wtyczki do odinstalowania. installPluginsWizard.list.nullversion=Brak wersji uninstallPluginsWizard.finish.title=Deinstalacja w trakcie uninstallPluginsWizard.finish.explanation=Wybrane wtyczki zostan\u0105 odinstalowane przy u\u017cyciu Asystenta aktualizacji. MainWindow.menu.plugins.installPlugins=Kreator instalacji... MainWindow.menu.plugins.uninstallPlugins=Kreator deinstalacji... ConfigView.section.ipfilter.totalIPs=%1 adres\u00f3w IP zablokowanych, co stanowi %2 wszystkich. update.instance.install=Sprawdzanie instalacji update.instance.uninstall=Sprawdzanie deinstalacji update.instance.update=Sprawdzanie aktualizacji MainWindow.status.update.tooltip=Kliknij dwukrotnie, aby wy\u015bwietli\u0107 informacje o post\u0119pie updater.progress.window.title=Zadania obecnej instalacji updater.progress.window.info=Naci\u015bnij "Przerwij", aby zako\u0144czy\u0107 wszystkie niezako\u0144czone zadania Button.abort=Przerwij ConfigView.section.ipfilter.enablebanning=Blokuj peer\u00f3w, kt\u00f3rzy stale wysy\u0142aj\u0105 b\u0142\u0119dne dane Network.alert.acceptfail=Zbyt wiele powtarzaj\u0105cych si\u0119 b\u0142\u0119d\u00f3w na porcie %1, %2 - anulowano przetwarzanie. Sprawd\u017a ustawienia firewalla, aby dowiedzie\u0107 si\u0119 czy jest w\u0142\u0105czone odbieranie po\u0142\u0105cze\u0144. MyShares.column.category=Kategoria UpdateWindow.restartLater=Uruchom ponownie p\u00f3\u017aniej MainWindow.menu.file.restart=Uruchom Vuze ponownie MainWindow.dialog.restartconfirmation.title=Ponowne uruchomienie Vuze MainWindow.dialog.restartconfirmation.text=Czy na pewno chcesz uruchomi\u0107 ponownie Vuze deletetorrent.message1=Chcesz usun\u0105\u0107 torrent dla :\n deletetorrent.message2=\nCzy chcesz kontynuowa\u0107? ConfigView.label.prioritizemostcompletedfiles=Ustaw najwy\u017cszy priorytet na pliki, w zale\u017cno\u015bci od ich % uko\u0144czenia i rozmiaru splash.plugin.init=Uruchamianie wtyczki: splash.plugin.UIinit=Uruchamianie wtyczki interfejsu u\u017cytkownika: %1 ConfigView.section.style.osx_small_fonts=U\u017cywaj ma\u0142ej czcionki [wymagane ponowne uruchomienie] ConfigView.section.tracker.tcpnonblocking=U\u017cyj nie-blokowanego I/O do przetwarzania trackera. Wyb\u00f3r tej opcji wymaga uruchomienia trackera na porcie alternatywnym. Opcja eksperymentalna! ConfigView.section.tracker.nonblocking=Opcje nie-blokowania ConfigView.section.tracker.nonblockingconcmax=Maksymalna liczba po\u0142\u0105cze\u0144 jednoczesnych [0: nieograniczona] MyTorrentsView.menu.exportmenu=Eksportuj ConfigView.group.scrape=Omijanie ConfigView.section.tracker.client.scrapeinfo=Wy\u0142\u0105czenie omijania mo\u017ce zapobiec ci\u0105g\u0142emu ustawianiu torrenta w kolejce. ConfigView.section.tracker.client.scrapeenable=W\u0142\u0105cz omijanie ConfigView.section.tracker.client.scrapestoppedenable=Omi\u0144 torrenty, kt\u00f3re nie s\u0105 uruchomione Scrape.status.disabled=Omijanie wy\u0142\u0105czone MyTorrentsView.menu.explore=Poka\u017c plik MyTorrentsView.menu.explore._mac=Poka\u017c w wyszukiwarce MyTorrentsView.menu.explore._windows=Poka\u017c w eksploratorze wizard.maketorrents.autohost=Hostuj torrenta na wbudowanym trackerze ConfigView.label.overrideip=Omi\u0144 adres IP zg\u0142aszany do trackera - oddzielone przecinkiem, je\u015bli wi\u0119cej ni\u017c jeden dla r\u00f3\u017cnych sieci ConfigView.label.overrideip.tooltip=Informuje trackera o innym adresie IP ni\u017c ten, z kt\u00f3rego pochodz\u0105 pakiety wychodz\u0105ce. Zostaw puste je\u015bli ma ta opcja ma by\u0107 nieu\u017cywana. ConfigView.section.connection.group.networks=Sieci ConfigView.section.connection.group.networks.info=Wybierz domy\u015bln\u0105 sie\u0107 dla po\u0142\u0105cze\u0144 peer-peer ConfigView.section.connection.networks.prompt=Pytaj o wyb\u00f3r, gdy dodane zostanie pobieranie z anonimowym trackerem ConfigView.section.connection.networks.Public=Publiczna sie\u0107 IP (nieanonimowa) ConfigView.section.connection.networks.I2P=Sie\u0107 I2P ConfigView.section.connection.networks.Tor=Sie\u0107 The Onion Router (Tor) TableColumn.header.networks=Sieci TableColumn.header.networks.info=Pozwolenie dla komunikacji danych po\u0142\u0105cze\u0144 peer-peer Scrape.status.networkdisabled=Sie\u0107 niew\u0142\u0105czona ConfigView.section.tracker.server.group.networks=Sieci ConfigView.section.tracker.server.group.networks.info=Wybierz sieci dla kt\u00f3rych tracker b\u0119dzie akceptowa\u0142 peer\u00f3w window.networkselection.title=Wyb\u00f3r sieci window.networkselection.info=Torrent wymieniony poni\u017cej jest na trackerze, kt\u00f3ry obs\u0142uguje nast\u0119puj\u0105ce sieci.\nWybierz te, \u017ceby w\u0142\u0105czy\u0107 komunikacj\u0119 z trackerem oraz peerami.\nJe\u015bli tracker jest anonimowy, obs\u0142uguj\u0105cy klient\u00f3w publicznych w\u0142\u0105cza anonimowe i publiczne sieci.\nW\u0142\u0105czenie publicznej sieci ma konsekwencje w postaci usuni\u0119cia anonimowo\u015bci! plugins.basicview.clear=Wyczy\u015b\u0107 ConfigView.section.connection.group.peersources=\u0179r\u00f3d\u0142a peer\u00f3w ConfigView.section.connection.group.peersources.info=Wybierz domy\u015blnie zaufane \u017ar\u00f3d\u0142a dla po\u0142\u0105cze\u0144 z peerami ConfigView.section.connection.peersource.Tracker=Z trackera ConfigView.section.connection.peersource.DHT=\u015aledzenie zdecentralizowane ConfigView.section.connection.peersource.PeerExchange=Dostarczony przez innego peera ConfigView.section.connection.peersource.Plugin=Dodane przez wtyczk\u0119 ConfigView.section.connection.peersource.Incoming=Po\u0142\u0105czenie przychodz\u0105ce PeersView.source=\u0179r\u00f3d\u0142o PeersView.source.info=\u0179r\u00f3d\u0142o tego peera TableColumn.header.peersources=\u0179r\u00f3d\u0142a peer\u00f3w TableColumn.header.peersources.info=Dozwolone \u017ar\u00f3d\u0142a peer\u00f3w w celu ustanawiania po\u0142\u0105cze\u0144 z peerami wizard.tracker.dht=Zdecentralizowany (tylko klienty Vuze) MyTorrentsView.menu.advancedmenu=Zaawansowane MyTorrentsView.menu.networks=Sieci MyTorrentsView.menu.peersource=\u0179r\u00f3d\u0142a peer\u00f3w ConfigView.section.sharing.permitdht=Dopuszczaj zdecentralizowane \u015bledzenie, gdy tracker jest niedost\u0119pny ConfigView.section.sharing.protocol=Protok\u00f3\u0142 dla zasob\u00f3w dzielonych PeersView.Messaging=Wiadomo\u015bci PeersView.Messaging.info=Wskazuje jaki jest u\u017cywany system do przesy\u0142ania wiadomo\u015bci. ConfigView.label.queue.newseedsmovetop=Przenie\u015b ostatnio uko\u0144czone torrenty na pocz\u0105tek listy seedowania ConfigView.label.seeding.firstPriority.ignore.info=U\u017cywanie tych regu\u0142 mo\u017ce skutkowa\u0107 zatrzymaniem torrenta zaraz po tym\njak zostanie zako\u0144czone jego pobieranie. ConfigView.label.seeding.firstPriority.ignore=Ignoruj powy\u017csze regu\u0142y najwy\u017cszego priorytetu dla: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrenty z ratio seed\u00f3w:peer\u00f3w powy\u017cej ConfigView.label.seeding.firstPriority.ignore0Peer=Torrenty z 0 peer\u00f3w ConfigView.section.tracker.sendjavaversionandos=Wy\u015blij wersj\u0119 Javy i nazw\u0119 systemu operacyjnego MagnetPlugin.contextmenu.exporturi=Kopiuj URL do schowka ConfigView.section.plugins.dht=Rozproszona baza danych dht.info=Ta wtyczka obs\u0142uguje zdecentalizowane \u015bledzenie - wy\u0142\u0105czenie zmniejszy mo\u017cliwo\u015b\u0107 do pobierania dht.enabled=W\u0142\u0105cz rozproszon\u0105 baz\u0119 danych dht.portdefault=U\u017cyj portu domy\u015blnego dht.port=Port UDP dla bazy danych dht.execute.command=Komendy diagnostyczne dht.execute.info=Naci\u015bnij w celu wykonania komendy dht.execute=Uruchom dht.logging=W\u0142\u0105cz \u015bledzenie aktywno\u015bci ConfigView.section.plugins.dhttracker=Rozproszony tracker dhttracker.tracknormalwhenoffline=\u015aled\u017a tylko torrenty, gdy ich trackery s\u0105 niedost\u0119pne ConfigView.section.file.nativedelete._mac=U\u017cyj kosza przy usuwaniu plik\u00f3w ConfigView.section.file.nativedelete._windows=Przenie\u015b usuwane pliki do kosza ConfigView.section.logging.generatediagnostics=Generuj ConfigView.section.logging.netinfo=Og\u00f3lna informacja o sieci ConfigView.section.logging.statsinfo=Generuj informacje statystyczne ConfigView.section.logging.generatediagnostics.info=Wygeneruj informacj\u0119 diagnostyczn\u0105 i skopiuj j\u0105 do schowka i pliku logu. ConfigView.section.sharing.privatetorrent=Prywatne torrenty - akceptuje tylko peer\u00f3w z danego trackera MainWindow.menu.tools.nattest=&Test NAT / Firewall Button.apply=Zastosuj Button.close=Zamknij window.welcome.title=Witamy w Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Historia wersji dht.reseed.label=Normalny resseding bazy danych nie jest konieczny. Aczkolwiek, je\u015bli liczba kontakt\u00f3w jest niska zabieg taki mo\u017ce by\u0107 u\u017cyteczny w celu reintegracji.\nZostaw pole puste w celu wy\u0142\u0105czenia lub wpisz adres IP i port by nawi\u0105za\u0107 po\u0142\u0105czenie ze znanym peerem. dht.reseed.group=Reseedowanie dht.reseed.ip=Adres IP dht.reseed=Reseedowanie dht.reseed.info=Reseeduj baz\u0119 danych dht.diagnostics.group=Diagnostyki DHTView.title.full=Rozproszona baza danych DHTView.title.fullcvs=Rozproszona baza danych CVS DHTView.general.title=Og\u00f3lne DHTView.general.uptime=Czas wysy\u0142ania: DHTView.general.users=U\u017cytkownicy: DHTView.general.nodes=W\u0119z\u0142y: DHTView.general.leaves=Pozostawionych: DHTView.general.contacts=Kontakty: DHTView.general.replacements=Zast\u0119pcze: DHTView.general.live=Dzia\u0142aj\u0105cych: DHTView.general.unknown=Nieznane: DHTView.general.dying=Martwych: DHTView.transport.title=Szczeg\u00f3\u0142y przesy\u0142ania danych DHTView.transport.packets=Pakiety DHTView.transport.bytes=Bajty DHTView.transport.received=Otrzymane DHTView.transport.sent=Wys\u0142ane DHTView.transport.in=Przychodz\u0105ce : DHTView.transport.out=Wychodz\u0105ce : DHTView.operations.title=Szczeg\u00f3\u0142y operacji DHTView.operations.sent=Wys\u0142ane DHTView.operations.failed=Nieudane DHTView.operations.received=Otrzymane DHTView.operations.findNode=Znalezione w\u0119z\u0142y DHTView.operations.findValue=Znaleziona warto\u015b\u0107 DHTView.operations.store=Przechowane DHTView.activity.title=Aktywno\u015b\u0107 DHTView.activity.status=Stan DHTView.activity.status.true=W kolejce DHTView.activity.status.false=Uruchomione DHTView.activity.type=Typ DHTView.activity.type.1=Pobieranie wewn\u0119trzne DHTView.activity.type.2=Pobieranie zewn\u0119trzne DHTView.activity.type.3=Wysy\u0142anie wewn\u0119trzne DHTView.activity.type.4=Wysy\u0142anie zewn\u0119trzne DHTView.activity.target=Cel DHTView.activity.details=Szczeg\u00f3\u0142y DHTView.db.title=Baza Danych DHTView.db.keys=Klucze DHTView.db.values=Warto\u015bci DHTView.db.local=Lokalne DHTView.db.direct=Bezpo\u015brednie DHTView.db.indirect=Niebezpo\u015brednie DHTView.db.divfreq=Cz\u0119st. Div. DHTView.db.divsize=Rozmiar Div. MainWindow.dht.status.tooltip=Pokazuje szacunkow\u0105 ilo\u015b\u0107 u\u017cytkownik\u00f3w aktualnie bed\u0105cych online, gdy rozproszona baza dzia\u0142a MainWindow.dht.status.disabled=DHT wy\u0142\u0105czony MainWindow.dht.status.failed=DHT nieudane MainWindow.dht.status.initializing=Uruchamianie DHT MainWindow.dht.status.users=%1 u\u017cytkownik\u00f3w MainWindow.dht.status.unreachable=DHT za firewallem MainWindow.dht.status.unreachabletooltip=Wygl\u0105da na to, \u017ce jest problem z mapowaniem port\u00f3w rozproszonej bazy danych UDP (NAT/firewall) MyTorrentsView.menu.setUpSpeed=Ustaw pr\u0119dko\u015b\u0107 wysy\u0142ania MyTorrentsView.menu.setDownSpeed=Ustaw pr\u0119dko\u015b\u0107 pobierania ConfigView.section.tracker.client.showwarnings=Poka\u017c ostrze\u017cenia zg\u0142oszone przez trackery dht.advanced=W\u0142\u0105cz ustawienia zaawansowane dht.advanced.group=Ustawienia zaawansowane dht.advanced.label=Zmie\u0144 te warto\u015bci tylko je\u015bli naprawd\u0119 wiesz co robisz dht.override.ip=Nadpisz zewn\u0119trzny adres IP ConfigView.section.logging.loggerenable=W\u0142\u0105cz raportowanie ConfigView.section.ipfilter.blockbanning=Banuj ca\u0142y blok 256 adres\u00f3w, gdy w bloku wykryto przynajmniej t\u0119 ilo\u015b\u0107 zbanowanych MyTrackerView.passive=Pasywny TableColumn.header.swarm_average_speed=\u015arednia pr\u0119dko\u015b\u0107 awansu TableColumn.header.swarm_average_speed.info=\u015arednia pr\u0119dko\u015b\u0107 awansu peer\u00f3w TableColumn.header.comment=Komentarz TableColumn.header.comment.info=Komentarz u\u017cytkownika TableColumn.header.commenticon=Ikona komentarza TableColumn.header.commenticon.info=Wy\u015bwietla ikon\u0119, je\u015bli torrent ma zdefiniowany komentarz u\u017cytkownika MyTrackerView.category=Kategoria MainWindow.menu.file.open.torrentfortracking=Plik torrent... (tylko \u015bledzenie) MyTrackerView.date_added=Dodane ConfigView.section.tracker.portbackup=Porty kopii (';' oddzielenie) ConfigView.label.playfilespeech=Przem\u00f3w gdy plik zostanie uko\u0144czony ConfigView.label.playfilespeech.info=Obecnie Us\u0142ugi g\u0142osowe najlepiej dzia\u0142aj\u0105 w j\u0119zyku angielskim ConfigView.label.playfilefinished=Odtw\u00f3rz d\u017awi\u0119k gdy plik zostanie uko\u0144czony ConfigView.label.backupconfigfiles=Kopia zapasowa plik\u00f3w konfiguracyjnych w celu odzyskania po awarii ConfigView.section.tracker.client.scrapesingleonly=Wy\u0142\u0105cz sumowanie \u017c\u0105da\u0144 dla trackera (mo\u017ce pom\u00f3c, gdy tracker raportuje b\u0142\u0105d 414 "URL too long") dht.ipfilter.log=Zapisuj log Filtru IP z naruszeniami ConfigView.label.seeding.addForSeedingDLCopyCount=We\u017a pod uwag\u0119 pobierania "dodaj do seedowania" aby m\u00f3c pobra\u0107 t\u0119 liczb\u0119 kopii ActivityView.legend.limit=Wska\u017anik limitu ActivityView.legend.achieved=Osiagni\u0119ty wska\u017anik ActivityView.legend.peeraverage=\u015arednio ActivityView.legend.swarmaverage=\u015arednio w kolejce ActivityView.legend.trimmed=Przyci\u0119te MyTorrentsView.menu.movemenu=Przenie\u015b pliki MyTorrentsView.menu.movedata=Przenie\u015b pliki danych... MyTorrentsView.menu.movetorrent=Przenie\u015b plik torrent... MyTorrentsView.menu.movedata.dialog=Wybierz now\u0105 lokalizacj\u0119 DHTView.operations.data=Dane DHTView.general.reachable=Osi\u0105galny: DHTView.general.rendezvous=Spotka\u0144: ConfigView.label.queue.maxactivetorrentswhenseeding=Maksymalna ilo\u015b\u0107 gdy tylko wysy\u0142am [0: nieograniczona] Views.plugins.IRC.title=IRC - obs\u0142uga techniczna online Formats.units.alot=Du\u017co!!! ConfigView.section.ipfilter.persistblocking=Zapisuj szczeg\u00f3\u0142y blokowanych adres\u00f3w IP podczas restartu FilesView.menu.rename=Zmie\u0144 nazw\u0119 lub plik docelowy FilesView.menu.rename_only=Szybka zmiana nazwy FilesView.menu.retarget=Przenie\u015b pliki FilesView.rename.choose.path=Wybierz nowy lub istniejacy plik FilesView.rename.choose.path.dir=Wybierz nowy lub istniej\u0105cy katalog FilesView.rename.confirm.delete.title=Potwierd\u017a usuni\u0119cie FilesView.rename.confirm.delete.text=Potwierd\u017a usuni\u0119cie oryginalnego pliku %1 FilesView.rename.filename.title=Zmie\u0144 nazw\u0119 pliku FilesView.rename.filename.text=Wybierz now\u0105 nazw\u0119 dla pliku ConfigView.higher.mode.available=Dalsze opcje dost\u0119pne s\u0105 w wy\u017cszych trybach u\u017cytkownika ConfigView.section.mode=Tryb ConfigView.section.mode.title=Stopie\u0144 zaawansowania u\u017cytkownika ConfigView.section.mode.beginner=Pocz\u0105tkuj\u0105cy ConfigView.section.mode.beginner.wiki.definitions=S\u0142owniczek BitTorrent ConfigView.section.mode.intermediate=\u015aredniozaawansowany ConfigView.section.mode.intermediate.wiki.host=Hostowane pliki ConfigView.section.mode.intermediate.wiki.publish=Publikowane pliki ConfigView.section.mode.advanced=Zaawansowany ConfigView.section.mode.advanced.wiki.main=Strona g\u0142\u00f3wna Wiki ConfigView.section.mode.beginner.text=Wszystko czego potrzebujesz do pobierania torrent\u00f3w.\nU\u017cyj tego trybu, je\u015bli chcesz zarz\u0105dza\u0107 swoimi torrentami. ConfigView.section.mode.intermediate.text=Dost\u0119p do funkcji trackera.\nU\u017cyj tego trybu, je\u015bli chcesz utworzy\u0107 sw\u00f3j w\u0142asny tracker i hostowa\u0107/publikowa\u0107 swoje pliki. ConfigView.section.mode.advanced.text=Dost\u0119p do ustawie\u0144 sieci.\nU\u017cyj tego trybu, je\u015bli wiesz co to jest MTU albo nieblokowane I/O... Files.column.storagetype=Typ pami\u0119ci Files.column.fileext=Typ FileItem.storage.linear=Liniowy FileItem.storage.compact=Kompaktowy MessageBoxWindow.rememberdecision=Zapami\u0119taj m\u00f3j wyb\u00f3r ConfigView.section.interface.cleardecisions=Wyczy\u015b\u0107 raz zapami\u0119tany wyb\u00f3r w oknie dialogowym ConfigView.section.interface.cleardecisionsbutton=Wyczy\u015b\u0107 ConfigView.section.interface.cleartrackers=Wyczy\u015b\u0107 zapami\u0119tane trackery ConfigView.section.interface.cleartrackersbutton=Wyczy\u015b\u0107 ConfigView.section.interface.clearsavepaths=Wyczy\u015b\u0107 zapami\u0119tane \u015bcie\u017cki zapisu ConfigView.section.interface.clearsavepathsbutton=Wyczy\u015b\u0107 configureWizard.welcome.usermodes=To ustawienie u\u017cytkownika skutkuje poziomem wy\u015bwietlania opcji w Narz\u0119dzia > Opcje. W twoim interesie le\u017cy w\u0142a\u015bciwe ustawienie tego parametru. FilesView.skip.confirm.delete.text=Przyci\u0105\u0107 plik '%1' w celu zaoszcz\u0119dzenia miejsca? FilesView.rename.failed.title=Nieudana zmiana nazwy/\u015bcie\u017cki zapisu FilesView.rename.failed.text=Nieudana operacja, prawdopodobnie \u017ale wybrany cel diagnostics.log_found=Vuze nie zosta\u0142 poprawnie zamkni\u0119ty. Sprawd\u017a pliki diagnostyczne. Wi\u0119cej informacji znajdziesz w artykule wiki Zamykanie Vuze. ManagerItem.paused=Wstrzymany Utils.link.visit=Prosz\u0119 odwied\u017a ConfigView.section.connection.serverport.wiki=Dobry wyb\u00f3r port\u00f3w ConfigView.section.transfer.speeds.wiki=Ustawienia dobrej szybko\u015bci installPluginsWizard.installMode.info.title=Informacja installPluginsWizard.installMode.info.text=Nie potrzebujesz \u017cadnych wtyczek, aby Vuze dzia\u0142a\u0142 prawid\u0142owo, s\u0105 to jedynie dodatki s\u0142u\u017c\u0105ce r\u00f3\u017cnym celom (np. zabawie, automatyzacji zada\u0144 lub zdalnego sterowania).\nDlatego przed instalacj\u0105 wtyczki zawsze przeczytaj jego opis.\nWi\u0119kszo\u015bc wtyczek jest bezpieczna, ale nie prze\u0142adowuj systemu niepotrzebnymi wtyczkami, kt\u00f3rych nie b\u0119dziesz u\u017cywa\u0107. Views.plugins.Distributed.DB.title=Rozproszona baza danych Views.plugins.Distributed.Tracker.title=Rozproszony tracker Views.plugins.Plugin.Update.title=Aktualizacja wtyczki openUrl.url.info=Obs\u0142uguje http, https, magnet i raw hex infohash strings TableColumn.header.swarm_average_completion=\u015arednia uko\u0144czenia peer\u00f3w TableColumn.header.swarm_average_completion.info=\u015aredni procent uko\u0144czonenia u peer\u00f3w GeneralView.label.swarm_average_completion=\u015arednio uko\u0144czono: GeneralView.label.swarm_average_completion.tooltip=\u015aredni procent uko\u0144czenia peer\u00f3w z kolejki MainWindow.nat.status.tooltip.unknown=Nieznany status osi\u0105galno\u015bci Firewall/NAT (TCP) MainWindow.nat.status.tooltip.ok=Osi\u0105galno\u015b\u0107 OK (TCP) MainWindow.nat.status.tooltip.probok=Osi\u0105galno\u015b\u0107 jest OK, lecz brak nowych po\u0142\u0105cze\u0144 przychodz\u0105cych TCP MainWindow.nat.status.bad=Za firewallem MainWindow.nat.status.tooltip.bad=Problem z osi\u0105galno\u015bci\u0105 Firewall/NAT (TCP). Poszukaj pomocy w Wiki plugin.installer.recommended.plugin=Rekomendowana wtyczka - zapoznaj si\u0119 z ni\u0105 i zainstaluj je\u015bli potrzebujesz LoggerView.pause=Wstrzymaj raportowanie LoggerView.clear=&Wyczy\u015b\u0107 LoggerView.filter=Filtr LoggerView.filter.uncheckAll=Odznacz wszystkie kategorie LoggerView.filter.checkAll=Zaznacz wszystkie kategorie LoggerView.loggingDisabled=Raportowanie nie jest w\u0142\u0105czone. LoggerView.includeOnly=Wy\u015bwietl tylko linie pasuj\u0105ce do: LoggerView.excludeAll=Nie wy\u015bwietlaj linii pasuj\u0105cych do: ConfigView.section.logging.log0type=Informacja ConfigView.section.logging.log1type=Ostrze\u017cenie ConfigView.section.logging.log2type=B\u0142\u0105d ConfigView.section.logging.filter=Filtruj przy raportowaniu do pliku ConfigView.section.logging.level=Poziom raportowania ConfigView.section.logging.showLogsFor=Poka\u017c %1 log\u00f3w dla nast\u0119puj\u0105cych kategorii: ConfigView.pluginlist.column.loadAtStartup=\u0141aduj na starcie ConfigView.pluginlist.column.type=Typ ConfigView.pluginlist.column.type.perUser=Na u\u017cytkownika ConfigView.pluginlist.column.type.shared=Wsp\u00f3\u0142dzielone ConfigView.pluginlist.column.type.builtIn=Wbudowany ConfigView.pluginlist.column.name=Nazwa ConfigView.pluginlist.column.version=Wersja ConfigView.pluginlist.column.directory=Katalog ConfigView.pluginlist.column.isOperational=Operacyjnie? PeersView.BlockView.Avail.Have=Obydwie strony posiadaj\u0105 PeersView.BlockView.Avail.NoHave=Peer posiada; Ty nie PeersView.BlockView.NoAvail.Have=Ty posiadasz; peer nie PeersView.BlockView.NoAvail.NoHave=Nikt nie ma PeersView.BlockView.Transfer=Transferowanie PeersView.BlockView.NextRequest=Nast\u0119pne \u017c\u0105danie PeersView.BlockView.title=Mapa cz\u0119\u015bci PeersView.BlockView.AvailCount=Licznik dost\u0119pno\u015bci MyTorrentsView.dialog.NumberError.title=Nieprawid\u0142owy lub nierozpoznany numer MyTorrentsView.dialog.NumberError.text=Wprowadzona warto\u015b\u0107 jest nieprawid\u0142owa lub nierozpoznana. MyTorrentsView.menu.manual=&R\u0119cznie... MyTorrentsView.menu.manual.per_torrent=R\u0119cznie (na torrent) MyTorrentsView.menu.manual.shared_torrents=R\u0119cznie (mi\u0119dzy torrenty) MyTorrentsView.dialog.setSpeed.title=Ustaw pr\u0119dko\u015b\u0107 %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Wprowad\u017a liczb\u0119 %1 aby zmieni\u0107 %2 na: MyTorrentsView.dialog.setNumber.upload=wysy\u0142anie MyTorrentsView.dialog.setNumber.download=pobieranie MyTorrentsView.dialog.setNumber.inKbps=w %1 OpenTorrentWindow.torrentLocation=Torrent(y) do pobrania: OpenTorrentWindow.addFiles.URL=Dodaj &URL OpenTorrentWindow.addFiles.Folder=Dodaj &folder OpenTorrentWindow.addFiles.Clipboard=Dodaj ze scho&wka OpenTorrentWindow.changeDestination=Zmie\u0144 folder docelowy OpenTorrentWindow.fileList=Plik\u00f3w w torrentach: OpenTorrentWindow.torrentTable.name=Nazwa OpenTorrentWindow.torrentTable.saveLocation=Zapisz lokalizacj\u0119 OpenTorrentWindow.fileTable.fileName=Nazwa pliku OpenTorrentWindow.fileTable.size=Rozmiar OpenTorrentWindow.fileTable.destinationName=Nazwa docelowa OpenTorrentWindow.startMode.seeding=Seedowanie OpenTorrentWindow.fileList.changeDestination=Zmie\u0144 folder docelowy OpenTorrentWindow.mb.badSize.title=Plik nieobs\u0142ugiwany OpenTorrentWindow.mb.badSize.text='%1' niezgodny z '%2' i nie mo\u017ce by\u0107 u\u017cyty do seedowania OpenTorrentWindow.mb.alreadyExists.text=%3 ju\u017c zosta\u0142 dodany jako '%2' OpenTorrentWindow.mb.alreadyExists.title=Ju\u017c istnieje OpenTorrentWindow.mb.openError.title=B\u0142\u0105d otworzenia OpenTorrentWindow.mb.openError.text='%1' nie mo\u017ce by\u0107 otworzony:\n%2 OpenTorrentWindow.torrent.remove=Usu\u0144 torrent z listy OpenTorrentWindow.torrent.options=Nast\u0119puj\u0105ce ustawienia zostan\u0105 zastosowane do wybranych powy\u017cej torrent\u00f3w: OpenTorrentWindow.xOfTotal=(%1 z %2) iconBar.open.tooltip=Otw\u00f3rz torrent(y) LocaleUtil.column.text=Nieznany tekst Tracker.tooltip.MultiSupport=Ten tracker obs\u0142uguje multi hash-e na \u017c\u0105danie. Tracker.tooltip.NoMultiSupport=Ten tracker nie obs\u0142uguje multi hash-y na \u017c\u0105danie.\nNie b\u0119dzie dotyczy\u0142o wydajno\u015bci, ale zwi\u0119ksza \u0142adowanie do trackera. ConfigView.label.lazybitfield=U\u017cyj "lazy bitfield" (pomaga w seedowaniu w sieciach obs\u0142uguj\u0105cych blokowanie "bitfield") LoggerView.realtime=Aktualizuj w czasie rzeczywistym ConfigView.section.file.perf.cache.flushpieces=Zapisuj natychmiast zako\u0144czone cz\u0119\u015bci na dysk. Przyspiesza dost\u0119p do dysku, ale w rezultacie mo\u017ce zapisywa\u0107 wi\u0119cej operacji. ConfigView.section.file.writemblimit=Maksywalna ilo\u015b\u0107 \u017c\u0105da\u0144 zapisu w kolejce (%1) ConfigView.section.file.writemblimit.explain=Gdy mo\u017cliwo\u015bci zapisu dysku s\u0105 ni\u017csze ni\u017c pr\u0119dko\u015b\u0107 pobierania, ten parametr ograniczy ilo\u015b\u0107 danych w kolejce do czasu, gdy pr\u0119dko\u015b\u0107 pobierania zostanie zmniejszona. ConfigView.section.file.readmblimit=Maksymalna ilo\u015b\u0107 \u017c\u0105da\u0144 odczytu w kolejce (%1) ConfigView.section.file.readmblimit.explain=Ten parametr decyduje jaka wielko\u015b\u0107 pami\u0119ci zostanie u\u017cyta do sk\u0142adowania oczekuj\u0105cych w\u0105tk\u00f3w. Button.moveUp=Przesu\u0144 wy\u017cej Button.moveDown=Przesu\u0144 ni\u017cej ConfigView.notAvailableForMode=Ta sekcja zmierza do trybu %1 lub wy\u017cszego. Nie jest dost\u0119pna w trybie %2 . health.explain.error=Wyst\u0105pi\u0142 b\u0142\u0105d w tym torrencie. Zobacz kolumn\u0119 Status lub podpowied\u017a na ikonie b\u0142\u0119du. PeersView.piece=Cz\u0119\u015b\u0107 PeersView.piece.info=Ostatnia cz\u0119\u015b\u0107 # \u017c\u0105dana przez tego peera PiecesView.priority=Priorytet PiecesView.priority.info=priorytet uko\u0144czenia tej cz\u0119\u015bci, ale nie przyk\u0142adaj zbyt du\u017cej wagi do tego parametru PiecesView.speed=Pr\u0119dko\u015b\u0107 PiecesView.speed.info=Peery z wolnymi \u0142\u0105czami bardzo spowalniaj\u0105 przesy\u0142 szybkich cz\u0119\u015bci TableColumn.header.AvgAvail.info=Suma dost\u0119pnych cz\u0119\u015bci podzielona przez # cz\u0119\u015bci, podzielona przez # po\u0142\u0105cze\u0144 TableColumn.header.AvgAvail=\u015arednia dost\u0119pnych/cz\u0119\u015b\u0107 ConfigView.label.strictfilelocking=Wymu\u015b specjalny dost\u0119p do zapisu chronionego pliku poprzez torrenty MyTorrentsView.menu.checkfilesexist=Sprawd\u017a istnienie plik\u00f3w MyTorrentsView.menu.rescanfile=Sprawd\u017a okresowo niekompletne cz\u0119\u015bci MyTorrentsView.menu.clear_resume_data=Wyczy\u015b\u0107 dane wznowienia Plugin.extseed.name=Zewn\u0119trzne seedy Plugin.localtracker.name=Wyszukiwarka peer\u00f3w LAN Plugin.localtracker.info=Wyszukiwarka peer\u00f3w w sieci LAN zezwala na wiele uruchomionych kopi Vuze za firewallem w wi\u0119kszo\u015bci sieci w celu zwi\u0119kszenia efektywno\u015bci pobierania torrent\u00f3w poprzez po\u0142\u0105czenia bezpo\u015brednie w sieci LAN. Plugin.localtracker.enable=W\u0142\u0105cz szukanie peer\u00f3w w sieci LAN azinstancehandler.alert.portclash=Wykryto b\u0142\u0105d portu w sieci LAN: %1 jest ju\u017c u\u017cyty przez innego u\u017cytkownika Vuze, wybierz nowy losowy port(y) dla po\u0142\u0105cze\u0144 przychodz\u0105cych TCP / UDP [pomi\u0119dzy %2 i %3]. ConfigView.section.transfer.lan.tooltip=Specyficzne ustawienia LAN ConfigView.section.transfer.lan.uploadrate=Maksymalna pr\u0119dko\u015b\u0107 wysy\u0142ania w sieci LAN KB/s [0: nieograniczona] ConfigView.section.transfer.lan.uploadrate.tooltip=Peery b\u0119d\u0105cy w tej samej sieci LAN maj\u0105 oddzielny limit pr\u0119dko\u015bci wysy\u0142ania. ConfigView.section.transfer.lan.downloadrate=Maksymalna pr\u0119dko\u015b\u0107 pobierania w sieci LAN KB/s [0: nieograniczona] ConfigView.section.transfer.lan.downloadrate.tooltip=Peery b\u0119d\u0105cy w tej samej sieci LAN maj\u0105 oddzielny limit pr\u0119dko\u015bci pobierania. TorrentOptionsView.title.short=Opcje TorrentOptionsView.title.full=Opcje TorrentOptionsView.param.max.peers=Maksymalna ilo\u015b\u0107 po\u0142\u0105cze\u0144 [0: nieograniczona] ConfigView.section.connection.encryption.require_encrypted_transport=Wymaga przesy\u0142ania szyfrowanego ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Wymu\u015b szyfrowanie dla po\u0142\u0105cze\u0144 z innymi peerami. ConfigView.section.connection.encryption.min_encryption_level=Minimalny poziom szyfrowania ConfigView.section.connection.encryption.min_encryption_level.tooltip=Prosty - tylko po\u0142\u0105czenie\nRC4 - pe\u0142ny strumie\u0144\nWi\u0119kszy stopie\u0144 szyfrowania wymusza wi\u0119kszego u\u017cycia procesora. Peers.column.Encryption=Szyfrowanie Peers.column.Encryption.info=Poziom u\u017cywanego szyfrowania ConfigView.section.connection.encryption.encrypt.info=Je\u015bli szyfrowanie jest w\u0142\u0105czone, nie b\u0119dzie mo\u017cliwo\u015bci po\u0142\u0105czenia z niekompatybilnymi aplikacjami do czasu skonfigurowania opcji odpowiedzi ConfigView.section.connection.encryption.encrypt.info.link=Kliknij po szczeg\u00f3\u0142y MainWindow.sr.status.tooltip.ok=Share ratio %1 OK MainWindow.sr.status.tooltip.poor=Share ratio %1 s\u0142abo: < 0.9 MainWindow.sr.status.tooltip.bad=Share ratio %1 \u017ale: < 0.5 ConfigView.section.style.status=Strefa statusu: ConfigView.section.style.status.show_sr=Share ratio ConfigView.section.style.status.show_nat=Status NAT ConfigView.section.style.status.show_ddb=Status DDB ConfigView.section.style.status.show_ipf=Status IPFilter ConfigView.section.connection.encryption.encrypt.group=Szyfrowanie przesy\u0142ania/Ukrywanie ConfigView.section.connection.encryption.encrypt.fallback_info=W\u0142\u0105czenie kt\u00f3rejkolwiek opcji odpowiedzi dopu\u015bci po\u0142\u0105czenie niekompatybilnych aplikacji, ale po\u0142\u0105czenie takie nie b\u0119dzie szyfrowane. ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Pozw\u00f3l na nieszyfrowane po\u0142\u0105czenia wychodz\u0105ce, je\u015bli pr\u00f3ba po\u0142\u0105czenia szyfrowanego zawiedzie ConfigView.section.connection.encryption.encrypt.fallback_incoming=Pozw\u00f3l na nie zaszyfrowane po\u0142\u0105czenia przychodz\u0105ce ConfigView.section.connection.encryption=Szyfrowanie przesy\u0142ania upnp.selectedinterfaces=Wybrane interfejsy (';' oddzielenie, np. eth0;eth1) [puste: wszystkie] ConfigView.section.style.defaultSortOrder=Domy\u015blne sortowanie ConfigView.section.style.defaultSortOrder.desc=Malej\u0105ce ConfigView.section.style.defaultSortOrder.asc=Rosn\u0105ce ConfigView.section.style.defaultSortOrder.flip=Odwrotna kolejno\u015b\u0107 LoggerView.autoscroll=Automatyczne przewijanie Button.selectAll=Wybierz wszystkie Button.markSelected=Zaznacz wybrane Button.unmarkSelected=Odznacz zaznaczone plugins.basicview.config=Konfiguracja TorrentOptionsView.param.max.uploads=Maksymalna ilo\u015b\u0107 gniazd do wysy\u0142ania [minimum: 2] MyTorrentsView.dialog.setPosition.title=Ustaw pozycj\u0119 MyTorrentsView.dialog.setPosition.text=Ustaw pozycj\u0119 dla wybranych torrent\u00f3w na: MyTorrentsView.menu.reposition.manual=Ustawianie... ConfigView.section.connection.advanced.info.link=Kliknij po szczeg\u00f3\u0142y ConfigView.section.connection.advanced.socket.group=Opcje socketu ConfigView.section.connection.advanced.bind_port=Powi\u0105\u017c z portem lokalnym [0: wy\u0142\u0105czone] ConfigView.section.connection.advanced.bind_port.tooltip=Wychodz\u0105ce po\u0142\u0105czenia b\u0119d\u0105 lokalnie ograniczane do przydzielonego portu.\nW\u0142\u0105czenie tej funkcji czasem pomaga stabilno\u015bci routera NAT. ConfigView.section.proxy.group.tracker=Komunikacje trackera ConfigView.section.proxy.group.peer=Komunikacje peer\u00f3w Pieces.column.Requested=\u017b\u0105dania Pieces.column.Requested.info=Pokazuje czy mo\u017cna ustawi\u0107 wi\u0119cej \u017c\u0105da\u0144 dla danej cz\u0119\u015bci czy nie (*) ConfigView.label.maxuploadsseeding=Domy\u015blna alternatywa dla seedowania MyTorrentsView.filter=Filtr: popup.error.hideall=Ukryj wszystkie ConfigView.section.style.dataStatsOnly=Poka\u017c tylko statystyki danych (ukryj statystyki protoko\u0142u) ConfigView.section.style.separateProtDataStats=Poka\u017c oddzielnie dane i protoko\u0142y statystyk jako 'dane (protok\u00f3\u0142)' MyTorrentsView.dialog.setFilter.title=Modyfikuj filtrowanie MyTorrentsView.dialog.setFilter.text=%1 sekcja b\u0119dzie przeszukana po tek\u015bcie wpisanym poni\u017cej. U\u017cyj symbolu | do oddzielenia wielu wyraz\u00f3w. MyTorrentsView.filter.tooltip=Ctrl+X prze\u0142\u0105cza mi\u0119dzy trybami wyszukiwania.\nU\u017cyj symbolu (|) w celu oddzielenia wielu wyraz\u00f3w. MyTorrentsView.clearFilter.tooltip=Wyczy\u015b\u0107 filtr MyTorrentsView.menu.filter=Lista filtr\u00f3w... ConfigView.section.file.resume.recheck.all=Po awaryjnym restarcie sprawd\u017a ca\u0142y plik na uko\u0144czone cz\u0119\u015bci (w przeciwnym razie sprawdzane s\u0105 tylko aktywne cz\u0119\u015bci przy ostatnim zapisie) ConfigureWizard.language.choose=Wybierz j\u0119zyk z poni\u017cszej listy: popup.closing.in=Auto zamkni\u0119cie okna za %1 sekund popup.more.waiting=Jeszcze %1 wiadomo\u015b\u0107(i).. # > 2402 popup.download.finished="%1" uko\u0144czy\u0142o pobieranie. popup.file.finished="%1" uko\u0144czy\u0142o pobieranie. Plugin.localtracker.autoadd.info=Automatycznie dodaj tych lokalnych peer\u00f3w [';' oddzielenie adres\u00f3w, np. 1.2.3.4] Plugin.localtracker.autoadd=Wyszczeg\u00f3lnij peery: Plugin.localtracker.networks.info=Uwzgl\u0119dniaj nast\u0119puj\u0105ce sieci jako lokalne [';' oddziela sieci, np. 145.227.*.*] Plugin.localtracker.networks=Sieci lokalne MainWindow.menu.view.plugins.logViews=Przegl\u0105d log\u00f3w SpeedView.stats.autospeed=Automatyczna pr\u0119dko\u015b\u0107 wysy\u0142ania SpeedView.stats.autospeed.disabled=Ta funkcja jest wy\u0142\u0105czona (u\u017cyj DHT) lub wy\u0142\u0105czona z u\u017cytku (wybrana r\u0119cznie pr\u0119dko\u015b\u0107 wysy\u0142ania) SpeedView.stats.idlePing=Ping przy bezczynno\u015bci: SpeedView.stats.maxPing=Maksymalny Ping: SpeedView.stats.currentPing=Aktualny Ping: SpeedView.stats.maxUp=Maksymalna pr\u0119dko\u015b\u0107 wysy\u0142ania: ConfigView.pluginlist.unloadSelected=Zaznaczono nieza\u0142adowane ConfigView.pluginlist.scan=Skanuj w poszukiwaniu nowych wtyczek ConfigView.section.transfer.autospeed=Auto-Speed (klasyczny) ConfigView.section.transfer.autospeed.tooltip=Ustawienia funkcji Auto-speed ConfigView.section.transfer.autospeed.info=Auto-speed automatycznie dostosowuje pr\u0119dko\u015b\u0107 wysy\u0142ania, aby zapobiec zapychaniu \u0142\u0105cza.\n\nTe limity b\u0119d\u0105 obowi\u0105zywa\u0142y, gdy automatyczna pr\u0119dko\u015b\u0107 wysy\u0142ania jest w\u0142\u0105czona oraz wymaga w\u0142\u0105czenia rozproszonej bazy danych.\n ConfigView.section.transfer.autospeed.minupload=Minimalna pr\u0119dko\u015b\u0107 wysy\u0142ania %1 ConfigView.section.transfer.autospeed.minupload.tooltip=Pr\u0119dko\u015b\u0107 wysy\u0142ania nie b\u0119dzie automatycznie zani\u017cana poza ten limit ConfigView.section.transfer.autospeed.maxupload=Maksymalna pr\u0119dko\u015b\u0107 wysy\u0142ania %1 [0: nieograniczona] ConfigView.section.transfer.autospeed.maxupload.tooltip=Pr\u0119dko\u015b\u0107 wysy\u0142ania nie b\u0119dzie automatycznie zwi\u0119kszana poza ten limit ConfigView.section.transfer.autospeed.chokeping=Czas pingu [millisekundy] ConfigView.section.transfer.autospeed.chokeping.tooltip=Czasy ping\u00f3w przekraczaj\u0105ce t\u0119 warto\u015b\u0107 b\u0119d\u0105 wyznacznikiem nasycenia sieci ConfigView.section.transfer.autospeed.enableauto=W\u0142\u0105cz, gdy pobieram i wysy\u0142am ConfigView.section.transfer.autospeed.enableautoseeding=W\u0142\u0105cz, gdy tylko wysy\u0142am ConfigView.pluginlist.column.unloadable=Nie\u0142adowalne ConfigView.section.transfer.lan.enable=W\u0142\u0105cz oddzielne limity pr\u0119dko\u015bci dla po\u0142\u0105cze\u0144 w sieci LAN Plugin.localtracker.wellknownlocals=Automatycznie w\u0142\u0105cz sieci lokalne/loopback/link/site (192.168 itp.) TableColumn.header.filesdone=Pliki uko\u0144czone TableColumn.header.filesdone.info=Uko\u0144czonych plik\u00f3w/Ca\u0142kowita liczba plik\u00f3w MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled=<\u015bledzenie rozproszone wy\u0142\u0105czone> MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=czekam na uruchomienie DDB ... MagnetPlugin.report.searching=szukam... MagnetPlugin.report.found=znalezione %1 MagnetPlugin.report.alive=%1 \u017cywych MagnetPlugin.report.dead=%1 martwych MagnetPlugin.report.tunnel=tunelowanie do %1 MagnetPlugin.report.downloading=pobieram z %1 MagnetPlugin.report.error=b\u0142\u0105d %1 MagnetURLHandler.report.no_sources=nie znaleziono \u017ar\u00f3de\u0142 dla torrenta MagnetURLHandler.report.torrent_size=rozmiar torrenta: %1 MagnetURLHandler.report.percent=uko\u0144czone: %1% MagnetURLHandler.report.error=b\u0142\u0105d %1 DHTTransport.report.request_all=\u017c\u0105danie ca\u0142ego transferu z %1 DHTTransport.report.received_bit=odebrano %1 do %2 z %3 DHTTransport.report.complete=uko\u0144czone DHTTransport.report.timeout=czas oczekiwania, brak odpowiedzi z %1 DHTTransport.report.rerequest_all=ponowne \u017c\u0105danie ca\u0142ego transferu z %1 DHTTransport.report.rerequest_bit=ponowne \u017c\u0105danie %1 do %2 z %3 DHTTransport.report.timeout_some=czas oczekiwania, %1 odebranych pakiet\u00f3w z %2 ale nieuko\u0144czonych DHTTransport.report.sending=przesy\u0142anie danych DHTTransport.report.resending=ponowne wysy\u0142anie danych DHTTransport.report.send_complete=przesy\u0142anie zako\u0144czone DHTTransport.report.send_timeout=wy\u015blij czas oczekiwania ConfigView.section.transfer.autospeed.enabledebug=Raportuj informacje o debugowaniu TableColumn.header.date_added=Data dodania TableColumn.header.date_added.info=Data dodania torrenta ConfigView.section.file.hashchecking.smallestfirst=Sprawdzaj najpierw najmniejsze pliki platform.win32.baddll.info=Vuze wykry\u0142 obecno\u015b\u0107 '%1'. Jest to cz\u0119\u015b\u0107 '%2' i mo\u017ce powodowa\u0107 problemy takie jak zawieszanie aplikacji przy wysokim u\u017cyciu procesora. Je\u015bli posiadasz takie odinstaluj oprogramowanie albo przekonfiguruj je, \u017ceby nie wp\u0142ywa\u0142 na Azureusa. upnp.ignorebaddevices=Ignoruj urz\u0105dzenia, kt\u00f3re nie odpowiedzia\u0142y poprawnie upnp.ignorebaddevices.info=Obecnie ignorowanych urz\u0105dze\u0144: %1 upnp.ignorebaddevices.reset=Resetuj list\u0119 ignorowanych upnp.ignorebaddevices.reset.action=Resetuj upnp.ignorebaddevices.alert=Urz\u0105dzenia UPnP z %1 zosta\u0142o zignorowane z powodu powtarzaj\u0105cych si\u0119 b\u0142\u0119d\u00f3w. Sprawd\u017a konfiguracj\u0119 UPnP. TorrentOptionsView.param.max.uploads.when.busy=KB/s maksymalna pr\u0119dko\u015b\u0107 wysy\u0142ania, gdy osi\u0105gni\u0119ty limit ca\u0142kowity [0: wy\u0142\u0105czony] UpdateMonitor.messagebox.verification.failed.title=Nieudana weryfikacji instalacji UpdateMonitor.messagebox.verification.failed.text=Weryfikacja '%1' nieudane: %2 UpdateMonitor.messagebox.accept.unverified.title=Akceptuj niezweryfikowan\u0105 instalacj\u0119 UpdateMonitor.messagebox.accept.unverified.text='%1' nie mo\u017ce by\u0107 zweryfikowany jako oficjalna wtyczka Vuze.\nNie powiniene\u015b kontynuowa\u0107, je\u015bli wtyczka nie jest zatwierdzona.\nKontynuowa\u0107 instalacj\u0119? FileView.BlockView.title=Cz\u0119\u015bci pliku FileView.BlockView.Done=Zako\u0144czone FileView.BlockView.Skipped=Omini\u0119te FileView.BlockView.Active=Aktywne FileView.BlockView.Outstanding=Niezgodnych ConfigView.label.tcplistenport=Port nas\u0142uchu po\u0142\u0105cze\u0144 przychodzacych TCP ConfigView.label.udplistenport=Port nas\u0142uchu UDP upnp.portchange.alert=Nast\u0119puj\u0105ce porty zosta\u0142y zmienione, aby unikn\u0105\u0107 problem\u00f3w z urz\u0105dzeniami UPnP: %1 [stary port=%2] %3 [stary port=%4] ConfigView.section.proxy.username.info=Je\u015bli serwer proxy wymaga autoryzacji nawet, gdy nic nie zdefiniowano, u\u017cyj wpisu "" jako nazw\u0119 u\u017cytkownika ConfigView.label.maxuploadswhenbusymin=Licznik maksymalnej pr\u0119dko\u015bci wysy\u0142ania peera w czasie zaj\u0119to\u015bci [sek] MainWindow.menu.help.debug=Generuj informacj\u0119 diagnostyczn\u0105 DownloadManager.error.badsize=B\u0142\u0119dny rozmiar natpmp.info=NAT-PMP jest alternatywn\u0105 us\u0142ug\u0105 UPnP firmy Apple i jest obs\u0142ugiwana przez ostatnie stacje Airport\n\nZauwa\u017c, \u017ce obecnie UPnP musi by\u0107 w\u0142\u0105czone, aby w\u0142\u0105czy\u0107 NAT-PMP jako urz\u0105dzenie NAT-PMP i traktowane jako specjalny typ urz\u0105dzenia UPnP natpmp.enable=W\u0142\u0105czone (zauwa\u017c, \u017ce musi by\u0107 te\u017c w\u0142\u0105czone w konfiguracji Airport, aby zadzia\u0142a\u0142o) ConfigView.section.tracker.host.addurls=Upewnij si\u0119, \u017ce URL tego trackera wyst\u0119puje w hostowanych torrentach ConfigView.filter=wpisz szukany tekst ConfigView.section.files.move=Przenoszenie uko\u0144czonych ConfigView.section.file.defaultdir.section=Domy\u015blne opcje katalogu ConfigView.section.file.defaultdir.auto=Automatycznie pobierz do domy\u015blego katalogu (bez potwierdzenia) ConfigView.section.file.defaultdir.bestguess=U\u017cyj najlepszego przypuszczenia podczas wybierania domy\u015blnego katalogu zapisu ConfigView.section.file.defaultdir.ask=Domy\u015blny katalog: ConfigView.section.file.defaultdir.lastused=Aktualizuj domy\u015blny katalog do lokalizacji ostatnio zapisanego ConfigView.section.file.config.section=Ustawienia konfiguracji ConfigView.section.file.config.currentdir=Aktualny katalog konfiguracyjny: ConfigView.section.torrent.decoding=Dekodowanie zestawu znak\u00f3w ConfigView.section.logging.udptransport=W\u0142\u0105cz \u015bledzenie transportu UDP Tracker.announce.ignorePeerSeed=Liczba ignorowaych eeer\u00f3w/seed\u00f3w. %1 ConfigView.section.connection.encryption.use_crypto_port=U\u017cyj rozszerzenia 'kryptoportu' trackera, aby zapobiec prostym pr\u00f3bom po\u0142\u0105cze\u0144 przychodz\u0105cych. Niekt\u00f3re trackery nie akceptuj\u0105 tego, powoduj\u0105c b\u0142\u0105d "Invalid Port" lub "Illegal Argument". TorrentOptionsView.param.reset.to.default=Ustaw opcje z powrotem na warto\u015bci domy\u015blne TorrentOptionsView.param.reset.button=Resetuj natpmp.routeraddress=Adres stacji [puste: auto] ConfigView.section.style.disableAlertSliding=Wy\u0142\u0105cz animacj\u0119 dla powiadomie\u0144 ConfigView.section.transfer.autospeed.maxinc=Maksimum wyprzedze\u0144 na cykl %1 ConfigView.section.transfer.autospeed.maxdec=Maksimum op\u00f3\u017anie\u0144 na cykl %1 ConfigView.section.transfer.autospeed.enabledownadj=W\u0142\u0105cz dostosowanie pr\u0119dko\u015bci pobierania ConfigView.section.transfer.autospeed.downadjratio=Pobieranie: Ratio wysy\u0142ania (np. 2.0 -> limit pr\u0119dko\u015bci pobierania to podwojony limit wysy\u0142ania) ConfigView.section.transfer.autospeed.latencyfactor=Warto\u015b\u0107 u\u017cywana do skorelowania op\u00f3\u017anie\u0144 i wyprzedze\u0144 zmian (wi\u0119ksze warto\u015bci obni\u017caj\u0105 czu\u0142o\u015b\u0107) ConfigView.section.transfer.autospeed.reset=Resetuj warto\u015bci zaawansowane ConfigView.section.transfer.autospeed.reset.button=Resetuj PeerColumn.activationCount=Ilo\u015b\u0107 peer\u00f3w pr\u00f3buj\u0105cych si\u0119 po\u0142\u0105czy\u0107: %1 TableColumn.header.timesincedownload.info=Czas, jaki up\u0142yn\u0105\u0142 od pobrania ostatnich danych dla torrenta TableColumn.header.timesincedownload=Bezczynno\u015b\u0107 pobierania TableColumn.header.timesinceupload.info=Czas, jaki up\u0142yn\u0105\u0142 od wys\u0142ania ostatnich danych dla torrenta TableColumn.header.timesinceupload=Bezczynno\u015b\u0107 wysy\u0142ania PeersView.incomingreqcount=\u017b\u0105da\u0144 przychodz\u0105cych PeersView.incomingreqcount.info=Liczba \u017c\u0105da\u0144 przychodz\u0105cych od peera PeersView.outgoingreqcount=\u017b\u0105da\u0144 wychodz\u0105cych PeersView.outgoingreqcount.info=Liczba \u017c\u0105da\u0144 wychodz\u0105cych do peera upnp.mapping.trackerclientudp=Port klienta trackera UDP upnp.mapping.dhtudp=Rozproszona baza danych ConfigView.section.connection.nondata.udp.same=U\u017cyj tego samego portu UDP dla rozproszonej bazy danych i trackera UDP ConfigView.section.connection.tcp.enable=W\u0142\u0105cz TCP ConfigView.section.connection.udp.enable=W\u0142\u0105cz UDP ConfigView.section.style.showiconbar=Poka\u017c pasek narz\u0119dzi MainWindow.menu.view.iconbar=Pasek narz\u0119dzi MyTorrentsView.menu.rename=Zmiana nazwy MyTorrentsView.menu.rename.displayed=Zmie\u0144 wy\u015bwietlan\u0105 nazw\u0119 MyTorrentsView.menu.rename.save_path=Zmie\u0144 \u015bcie\u017ck\u0119 zapisu MyTorrentsView.menu.rename.displayed.enter.title=Zmie\u0144 wy\u015bwietlan\u0105 nazw\u0119 MyTorrentsView.menu.rename.displayed.enter.message=Wprowad\u017a now\u0105 nazw\u0119 do wy\u015bwietlenia dla tego pobierania.\nJe\u015bli nie wprowadzisz \u017cadnego tekstu, u\u017cyta zostanie oryginalna nazwa. MyTorrentsView.menu.edit_comment=Edytuj komentarz MyTorrentsView.menu.edit_comment.enter.title=Edytuj komentarz MyTorrentsView.menu.edit_comment.enter.message=Wprowad\u017a komentarz dla tego pobierania. UIDebugGenerator.messageask.title=Generator informacji diagnostycznej UIDebugGenerator.messageask.text=Wprowad\u017a opis b\u0142\u0119du, kt\u00f3ry raportujesz UIDebugGenerator.complete.title=Generator informacji diagnostycznej uko\u0144czony UIDebugGenerator.complete.text=Plik informacji diagnostycznej mo\u017cna znale\u017a\u0107 na '%1'.\n\nKliknij Ok, aby otworzy\u0107 okno dla tego pliku. ConfigView.section.style.showProgramIcon=Poka\u017c ikon\u0119 programu w kolumnie nazwy ConfigView.section.style.showProgramIcon.tooltip=Mo\u017ce wymaga\u0107 ponownego otwarcia, aby zmiany by\u0142y widoczne swt.alert.cant.update=Biblioteka SWT za\u0142adowana z "%3" nie mo\u017ce by\u0107 automatycznie zaktualizowana od wersji %1 do %2 (musi by\u0107 za\u0142adowana z "%4"). Zobacz wiki. authenticator.savepassword=Zapami\u0119taj has\u0142o ConfigView.section.security.clearpasswords=Resetuj zapami\u0119tane has\u0142a ConfigView.section.security.clearpasswords.button=Resetuj Content.alert.notuploaded.title=Wysy\u0142anie nieuko\u0144czone Content.alert.notuploaded.text=Pobieranie '%1' jest nieuko\u0144czone. Je\u015bli %2 teraz, ludzie nie b\u0119d\u0105 mogli do ko\u0144ca pobra\u0107 tego co udost\u0119pni\u0142e\u015b.\n\nCzy jeste\u015b pewny, \u017ce chcesz %2? Content.alert.notuploaded.multi.title=Wysy\u0142ania nieuko\u0144czone Content.alert.notuploaded.multi.text=%1 twoich udost\u0119pnionej zawarto\u015bci nie jest do ko\u0144ca wys\u0142ana.Je\u015bli %2 teraz, ludzie nie b\u0119d\u0105 mogli do ko\u0144ca pobra\u0107 tego co udost\u0119pni\u0142e\u015b. Czy jeste\u015b pewny, \u017ce chcesz %2?\n\nZawarto\u015b\u0107 nie do ko\u0144ca wys\u0142ana:\n%3 Content.alert.notuploaded.quit=zamknij Vuze TorrentInfoView.torrent.encoding=Kodowanie torrenta TorrentInfoView.columns=Kolumny z widoku "Moje Torrenty" progress.window.title=Operacja w toku progress.window.msg.filemove=Prosz\u0119 czeka\u0107 na uko\u0144czenie przenoszenia/zmiany nazwy pliku ConfigView.label.popup.timestamp=Dodaj znaczniki czasu do pop-up\u00f3w z powiadomieniami ConfigView.label.popup.autohide=Automatycznie ukryj pop-upy nie sygnalizuj\u0105ce b\u0142\u0119d\u00f3w po x sekundach (ustaw 0, aby wy\u0142\u0105czy\u0107 auto-ukrywanie) ConfigView.label.popup.suppress_alerts=Powstrzymaj powiadomienia ConfigView.label.popup.use_message_boxes=U\u017cyj wiadomo\u015bci pop-up ni\u017c tych standardowych powiadomie\u0144 pop-up. ConfigView.label.popup.show=Poka\u017c wszystkie pop-upy z zapisanymi powiadomieniami (je\u015bli wyst\u0119puj\u0105) ConfigView.label.popup.show.button=Poka\u017c ConfigView.label.please.visit.here=Szczeg\u00f3\u0142y tutaj ConfigView.section.ipfilter.enable.descriptionCache=Zapisz opis adresu IP w pliku notatki ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Gdy wy\u0142\u0105czone, opisy nie b\u0119d\u0105 zapami\u0119tywane OpenTorrentWindow.filesInfo=%1 z %2 zostan\u0105 pobrane. OpenTorrentWindow.diskUsage=%1 z %2 ConfigView.label.openmytorrents=Otw\u00f3rz "Moje Torrenty" po uruchomieniu ConfigView.label.open_transfer_bar_on_start=Otw\u00f3rz pasek post\u0119pu po uruchomieniu ConfigView.section.style.DNDalwaysInIncomplete=Zawsze pokazuj torrenty plik\u00f3w ze statusem "Nie pobieraj" w sekcji Nieuko\u0144czone w Moje Torrenty OpenTorrentWindow.mb.noGlobalDestDir.title=Katalog docelowy nie zosta\u0142 znaleziony OpenTorrentWindow.mb.noGlobalDestDir.text=Katalog docelowy '%1' nie istnieje lub jest nieprawid\u0142owy. OpenTorrentWindow.mb.noDestDir.title=Katalog docelowy nie zosta\u0142 znaleziony OpenTorrentWindow.mb.noDestDir.text=Katalog docelowy '%1' dla torrentu '%2' nie istnieje lub jest nieprawid\u0142owy. OpenTorrentWindow.mb.notValid.title=Otw\u00f3rz torrent OpenTorrentWindow.mb.notValid.text=Nie mo\u017cna otworzy\u0107 torrenta '%1'. Je\u015bli otwierasz w trybie seedowania, upewnij si\u0119, \u017ce torrenty z danymi istniej\u0105. OpenTorrentWindow.mb.notTorrent.title=Otw\u00f3rz torrent OpenTorrentWindow.mb.notTorrent.text=Nie mo\u017cna otworzy\u0107 '%1'. To prawdopodobnie nie jest plik .torrent.\n\nOtrzymano niekt\u00f3re dane:\n%2 ConfigView.label.pause.downloads.on.exit=Zatrzymaj pobieranie przy wyj\u015bciu ConfigView.label.resume.downloads.on.start=Wzn\u00f3w zatrzymane pobieranie na starcie po uko\u0144czeniu inicjalizacji UIDebugGenerator.message.cancel.title=Generowanie informacji diagnosycznej anulowane UIDebugGenerator.message.cancel.text=Nie poda\u0142e\u015b opisu b\u0142\u0119du, kt\u00f3ry pr\u00f3bujesz raportowa\u0107. B\u0142\u0105d ten mo\u017ce by\u0107 oczywisty dla Ciebie, jednak bez opisu mo\u017cemy jedynie zgadywa\u0107 czego problem dotyczy.\n\nGenerowanie informacji diagnostycznej zosta\u0142o anulowane. ConfigView.section.connection.group.http.info=Obs\u0142uga seedowania HTTP. ConfigView.section.connection.http.enable=W\u0142\u0105cz ConfigView.section.connection.http.port=Przychodz\u0105cy port ConfigView.section.connection.http.portoverride=Tracker HTTP Port override [0: brak] window.update.noupdates.title=Wyniki sprawdzania aktualizacji window.update.noupdates.text=Brak dost\u0119pnych aktualizacji.\n\nGratulacje! ConfigView.label.bindip.details=Przyk\u0142ad: 192.168.1.5;eth0;eth1[2] po\u0142\u0105czy si\u0119 do wybranego adresu IP, wszystkich adres\u00f3w IP z pierwszego interfejsu i trzeciego adresu IP drugiego interfejsu.\nPierwszy adres IP b\u0119dzie u\u017cyty we wszystkich serwisach, inne s\u0105 tylko u\u017cyte do \u0142adowania stanu r\u00f3wnowagi.\nDost\u0119pne s\u0105 nast\u0119puj\u0105ce interfejsy:\n%1 ConfigView.label.mindownloads=Minimalna ilo\u015b\u0107 jednoczesnych pobra\u0144 UI.cannot_submit_blank_text=Musisz wprowadzi\u0107 warto\u015b\u0107 crypto.alert.as.warning=Sie\u0107 '%1' narzuca kszta\u0142towanie ruchu, aby zredukowa\u0107 obci\u0105\u017cenie zwi\u0105zane z pobieraniem. Szyfrowanie zosta\u0142o automatycznie w\u0142\u0105czone - ustawienie to mo\u017ce by\u0107 wy\u0142\u0105czone lub zmodyfikowane za pomoc\u0105 konfiguracji parametr\u00f3w. ConfigView.section.interface.alerts=Powiadomienia ConfigView.label.popupdownloadadded=Powiadamiaj pop-upem gdy dodane zosta\u0142o pobieranie popup.download.added="%1" zosta\u0142 dodany do Twojej listy pobierania. MessageBoxWindow.nomoreprompting=Nie pokazuj tego ponownie TorrentOptionsView.param.max.seeds=Maksymalna ilo\u015b\u0107 po\u0142\u0105cze\u0144 seeda [0: limit po\u0142\u0105cze\u0144] TorrentOptionsView.param.alternative.value.enable=Alternatywna warto\u015b\u0107, gdy seedujesz ConfigView.section.proxy.check.on.start=Sprawd\u017a status proxy przy uruchamianiu TransferStatsView.legend.pingaverage=\u015arednio TransferStatsView.legend.ping1=Cel 1 TransferStatsView.legend.ping2=Cel 2 TransferStatsView.legend.ping3=Cel 3 ConfigView.section.interface.enabletray._mac=W\u0142\u0105cz ikon\u0119 na pasku statusu [wymagane ponowne uruchomienie] ConfigView.label.closetotray._mac=Zamknij minimalizuje do ikony na pasku statusu ConfigView.label.minimizetotray._mac=Minimalizuj wysy\u0142a do ikony na pasku statusu OpenTorrentWindow.mb.existingFiles.title=Plik(i) ju\u017c istnieje! OpenTorrentWindow.mb.existingFiles.text=Niekt\u00f3re z plik\u00f3w ju\u017c istniej\u0105 w docelowym folderze(-ach), kt\u00f3re poda\u0142e\u015b:\n\n%1\nJe\u015bli b\u0119dziesz kontynuowa\u0142, Vuze sprawdzi poprawno\u015b\u0107 danych w tych plikach i nadpisze je, je\u015bli b\u0119dzie to potrzebne. splash.unloadingTorrents=Roz\u0142adowywanie torrent\u00f3w splash.unloadingTorrent=Roz\u0142adowywanie torrenta ConfigView.section.file.defaultdir.autorename=Zmie\u0144 automatycznie nazwy danych torrenta, je\u015bli pliki w \u015bcie\u017cce wygl\u0105daj\u0105 inaczej ConfigView.section.file.defaultdir.autorename.tooltip=Zapobiega to nadpisaniu jednego torrenta innym, gdy nazwy plik\u00f3w s\u0105 takie same. alert.raised.at.close=(Komunikat z poprzedniego zamkni\u0119cia Vuze) Plugin.trackerpeerauth.name=Autoryzacja tracker\u00f3w peer\u00f3w Plugin.trackerpeerauth.info=Ta wtyczka dzia\u0142a z trackerami, aby zweryfikowa\u0107 autentyczno\u015b\u0107 peer\u00f3w Peers.column.maxupspeed=Maksymalna pr\u0119dko\u015b\u0107 wysy\u0142ania Peers.column.maxdownspeed=Maksymalna pr\u0119dko\u015b\u0107 pobierania MyTorrents.items.DownSpeedLimit.disabled=Nie pobieraj upnp.selectedaddresses=Adresy ( ';' oddzielenie, '-' prefix=odrzu\u0107, '+' =pozw\u00f3l) [puste: wszystkie] upnp.alert.multipledevice.warning=Wykryto wiele urz\u0105dze\u0144 UPnP - sprawd\u017a czy wszystkie wymagaj\u0105 mapowania port\u00f3w (zobacz log UPnP i konfiguracj\u0119) UpdateMonitor.messagebox.restart.title=Aktualizacja oprogramowania UpdateMonitor.messagebox.restart.text=Vuze w\u0142a\u015bnie zako\u0144czy\u0142 pobieranie wa\u017cnego uaktualnienia i musi by\u0107 ponownie uruchomiony, aby zainstalowa\u0107 to uaktualnienie. PiecesView.BlockView.Have=Mam PiecesView.BlockView.NoHave=Nie mam PiecesView.BlockView.Header=%1 kolumn(y), %2 rz\u0105d(rz\u0119d\u00f3w), %3 cz\u0119\u015bci ConfigView.section.update.autodownload=Automatycznie pobieraj aktualizacje i powiadom, gdy instalacja b\u0119dzie gotowa Peers.column.peer_id=ID peera Peers.column.peer_id.info=ID peera w czytelnej formie Peers.column.peer_byte_id=ID peera Peers.column.peer_byte_id.info=ID peera w formie bajtowej Peers.column.client_identification=Identyfikacja klienta Peers.column.client_identification.info=Wskazuje nazwy klienta otrzymane przez Vuze - przydatne przy debugowaniu dht.warn.user=Ostrzegaj o potencjalnych problemach NAT lub mapowania port\u00f3w ConfigView.label.openbar.incomplete=Paski pobierania: automatycznie otw\u00f3rz pobrania ConfigView.label.openbar.complete=automatyczne otwarcie seed\u00f3w ConfigView.label.transferbar.remember_location=Zapami\u0119taj ostatni\u0105 lokalizacj\u0119 pasku transferu ConfigView.section.transfer.autospeed.forcemin=%1 wymuszona pr\u0119dko\u015b\u0107 wysy\u0142ania, podczas ustanawiania po\u0142\u0105czenia MainWindow.menu.tools.speedtest=Test pr\u0119dko\u015bci... speedtest.wizard.title=Test pr\u0119dko\u015bci speedtest.wizard.run=Uruchom test pr\u0119dko\u015bci speedtest.wizard.test.mode.updown=wysy\u0142anie i pobieranie speedtest.wizard.test.mode.up=wysy\u0142anie speedtest.wizard.test.mode.down=pobieranie SpeedTestWizard.test.panel.currinfo=Testowanie szybko\u015bci przesy\u0142u w sieci BitTorrent. SpeedTestWizard.test.panel.label=Test pr\u0119dko\u015bci Vuze: SpeedTestWizard.test.panel.already.running=Test jest ju\u017c uruchomiony! SpeedTestWizard.test.panel.not.accepted=\u017b\u0105danie testu nie zosta\u0142o zaakceptowane: SpeedTestWizard.test.panel.abort=Przerwano SpeedTestWizard.test.panel.abort.countdown=przerwij test po: SpeedTestWizard.test.panel.test.countdown=test zako\u0144czony w: SpeedTestWizard.test.panel.testfailed=Test zako\u0144czony niepowodzeniem SpeedTestWizard.test.panel.aborted=Test przerwany r\u0119cznie. SpeedTestWizard.test.panel.enc.label=Kliknij, aby testowa\u0107 z szyfrowaniem: SpeedTestWizard.test.panel.standard=standardowy SpeedTestWizard.test.panel.encrypted=zaszyfrowany SpeedTestWizard.set.upload.button.apply=Zastosuj SpeedTestWizard.set.upload.result=Wynik ostatniego testu SpeedTestWizard.set.upload.bytes.per.sec=kB/s SpeedTestWizard.set.upload.bits.per.sec=b/s SpeedTestWizard.finish.panel.title=Test pr\u0119dko\u015bci zako\u0144czony! SpeedTestWizard.finish.panel.click.close=Zako\u0144czy\u0142e\u015b kreator testu pr\u0119dko\u015bci. Kliknij 'Zamknij' aby wyj\u015b\u0107. SpeedTestWizard.finish.panel.max.upload=Maksymalne wysy\u0142anie : SpeedTestWizard.finish.panel.max.seeding.upload=Maksymalne wysy\u0142anie, gdy seeduj\u0119 : SpeedTestWizard.finish.panel.max.download=Maksymalne pobieranie : SpeedTestWizard.finish.panel.enabled=w\u0142\u0105czone SpeedTestWizard.finish.panel.disabled=wy\u0142\u0105czone SpeedTestWizard.abort.message.scheduled.in=zaplanowany test w ... %1 sekund" SpeedTestWizard.abort.message.unsupported.type=Nieobs\u0142ugiwany typ testu!!! SpeedTestWizard.abort.message.manual.abort=Przerwano r\u0119cznie SpeedTestWizard.abort.message.scheduling.failed=Nieudane zaplanowanie testu SpeedTestWizard.abort.message.download.added=Pobieranie %1 zosta\u0142o dodane podczas testu SpeedTestWizard.abort.message.entered.error=Test pobierania wpisanych stan\u00f3w b\u0142\u0119d\u00f3w '%1' SpeedTestWizard.abort.message.entered.queued=Test pobierania wpisanych stan\u00f3w w kolejce/zatrzymanych SpeedTestWizard.abort.message.interrupted=Monitor testu szybko\u015bci zosta\u0142 przerwany zanim test zosta\u0142 uko\u0144czony SpeedTestWizard.abort.message.execution.failed=Nieudane wykonanie testu SpeedTestWizard.abort.message.failed.peers=Nie mo\u017cna si\u0119 po\u0142\u0105czy\u0107 z \u017cadnym peerem SpeedTestWizard.abort.message.insufficient.slots=Nie mo\u017cna wysy\u0142a\u0107 do \u017cadnego z peer\u00f3w - niewystarczaj\u0105ca liczba gniazd wysy\u0142ania? SpeedTestWizard.abort.message.not.unchoked=Nie mo\u017cna pobra\u0107 od \u017cadnego peera, jak nigdy zatkane przez nich SpeedTestWizard.stage.message.requesting=\u017c\u0105danie testu... SpeedTestWizard.stage.message.preparing=przygotowywanie testu... SpeedTestWizard.stage.message.starting=rozpoczynanie testu... SpeedTestWizard.stage.message.connect.stats=Statystyki po\u0142\u0105czenia: peer\u00f3w=%1, down_ok=%2, up_ok=%3 window.uiswitcher.title=Wyb\u00f3r interfejsu u\u017cytkownika window.uiswitcher.text=Wybierz poni\u017cej interfejs u\u017cykownika, kt\u00f3ry najlepiej odpowiada Twoim potrzebom. window.uiswitcher.NewUI.text=* Polecany dla pocz\u0105tkuj\u0105cych i nowych u\u017cykownik\u00f3w.\n\n* \u0141atwy i intuicyjny interfejs u\u017cytkownika.\n\n* Wymagany do publikowania na platformie Vuze window.uiswitcher.ClassicUI.title=Interfejs klasyczny window.uiswitcher.ClassicUI.text=* Zachowuje funkcjonalno\u015b\u0107 serii 2.x klienta\n\n* Zawarto\u015b\u0107 warstwy Vuze nie b\u0119dzie za\u0142adowana. window.uiswitcher.bottom.text=Tw\u00f3j wyb\u00f3r mo\u017ce by\u0107 \u0142atwo zmieniony p\u00f3\u017aniej, za pomoc\u0105 przycisku wyboru interfejsu u\u017cykownika Vuze iconBar.switch.tooltip=Zmiana interfejsu u\u017cytkownika VivaldiView.notAvailable=Widok Vivaldi niedost\u0119pny restart.error=Nieudane ponowne uruchomienie:\n%1\nZobacz problemy z ponownym uruchomieniem. restart.error.oom=Brak pami\u0119ci restart.error.fnf="%1" nie zosta\u0142 znaleziony w "%2" restart.error.pnf=\u015acie\u017cka '%1' nie zosta\u0142a znaleziona restart.error.bad=Z\u0142y format pliku dla '%1' restart.error.denied=Dost\u0119p zosta\u0142 zabroniony podczas pr\u00f3by uruchomienia "%1". Upewnij si\u0119, \u017ce masz prawa do uruchomienia tego programu. TableColumn.header.date_completed=Uko\u0144czono TableColumn.menu.date_added.reset=Data resetowania ConfigView.section.ipfilter.discardbanning=Blokuj peer\u00f3w, kt\u00f3rych wsp\u00f3\u0142czynnik danych odrzuconych/dobrych przekroczy [0: wy\u0142\u0105czone] ConfigView.section.ipfilter.discardminkb=Minimum %1 odrzuconych zanim b\u0119dzie zastosowany wsp\u00f3\u0142czynnik ConfigView.interface.start.advanced=Uruchom w Widoku Zaawansowanym (AZ 2.x) MyTorrents.column.ColumnQuality=Jako\u015b\u0107 MyTorrents.column.ColumnSpeed=Pr\u0119dko\u015b\u0107 MyTorrents.column.ColumnProgressETA.2ndLine=Przewidywany czas do uko\u0144czenia: %1 MyTorrents.column.ColumnProgressETA.StreamReady=Strumieniowanie gotowe MyTorrents.column.ColumnProgressETA.PlayableIn=Dost\u0119pne w %1 %2 TableColumn.header.Quality=Jako\u015b\u0107 TableColumn.header.Speed=Pr\u0119dko\u015b\u0107 TableColumn.header.RateIt=Ocena TableColumn.header.Rating=Wska\u017anik TableColumn.header.SpeedGraphic=Pr\u0119dko\u015b\u0107 TableColumn.header.AzProduct=Od TableColumn.header.ProgressETA=Post\u0119p #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=Typ pliku: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=Strona Domowa v3.MainWindow.tab.browse=Na Vuze v3.MainWindow.tab.library=Biblioteka v3.MainWindow.tab.publish=Publikuj v3.MainWindow.tab.advanced=Zaawansowane v3.MainWindow.menu.home=Strona &Domowa v3.MainWindow.menu.browse=&Na Vuze v3.MainWindow.menu.library=&Biblioteka v3.MainWindow.menu.publish=&Publikuj v3.MainWindow.menu.advanced=&Zaawansowane v3.MainWindow.menu.view.searchbar=Pasek wyszukiwania v3.MainWindow.menu.view.tabbar=Pasek zak\u0142adek v3.MainWindow.currentDL=Obecnie pobierane v3.MainWindow.button.stream=Strumieniuj v3.MainWindow.button.stop=Zatrzymaj v3.MainWindow.button.start=Uruchom v3.MainWindow.button.pause=Pauza v3.MainWindow.button.resume=Wzn\u00f3w v3.MainWindow.button.delete=Usu\u0144 v3.MainWindow.button.comment=Komentarz v3.MainWindow.button.viewdetails=Zobacz szczeg\u00f3\u0142y v3.MainWindow.button.play=Odtw\u00f3rz v3.MainWindow.button.cancel=Anuluj v3.MainWindow.button.preview=Podgl\u0105d v3.MainWindow.view.wait=Uruchamianie widoku, prosz\u0119 czeka\u0107. v3.MainWindow.xofx=%1 z %2 v3.MainWindow.Loading=\u0141adowanie.. prosz\u0119 czeka\u0107 v3.filter-bar=Tytu\u0142 filtra: v3.MainWindow.search.defaultText=szukaj... v3.mb.delPublished.title=Zatrzymaj seedowanie zawarto\u015bci v3.mb.delPublished.text=OSTRZE\u017bENIE: Ta akcja NIE usunie Twojej publikowanej zawarto\u015bci '%1' z %3 .\n\nKliknij "Usu\u0144" tylko, je\u015bli chcesz, aby publikowana i pobierana zawarto\u015b\u0107 zosta\u0142a zachowana, ale chcesz zwolni\u0107 \u0142\u0105cze. Upewnij si\u0119, \u017ce proces wysy\u0142ania zosta\u0142 uko\u0144czony przed wykonaniem (how?).\n\nKliknij "Anuluj", je\u015bli chcesz ca\u0142kowicie usun\u0105\u0107 publikowan\u0105 zawarto\u015b\u0107 z %3, lub u\u017cyj przycisku (X) na panelu publikowanej zawarto\u015bci w zak\u0142adce Publikuj.\n\nWi\u0119cej pomocy.\n\n v3.mb.delPublished.delete=&Usu\u0144 v3.mb.delPublished.cancel=&Anuluj v3.mb.openFile.title=Otw\u00f3rz plik v3.mb.openFile.text.known=Ta zawarto\u015b\u0107 nie jest obecnie obs\u0142ugiwana przez odtwarzacz Vuze. Sprawd\u017a utworzony przez spo\u0142eczno\u015b\u0107 Poradnik odtwarzania.\n\nTypy plik\u00f3w: %2 (%3)\n v3.mb.openFile.text.unknown=Ta zawarto\u015b\u0107 nie jest obecnie obs\u0142ugiwana przez odtwarzacz Vuze. Sprawd\u017a utworzony przez spo\u0142eczno\u015b\u0107 Poradnik odtwarzania.\n\nRozszerzenie pliku : %2\n v3.mb.openFile.button.play=Odtw\u00f3rz v3.mb.openFile.button.cancel=Anuluj v3.mb.openFile.button.guide=Przeczytaj poradnik odtwarzania v3.mb.openFile.remember=Zawsze otwieraj pliki bez pytania v3.mb.PlayFileNotFound.title=Nie znaleziono pliku v3.mb.PlayFileNotFound.text=Brak plik\u00f3w "%1" lub s\u0105 one usuni\u0119te. v3.mb.PlayFileNotFound.button.remove=Usu\u0144 z Vuze v3.mb.PlayFileNotFound.button.redownload=Powt\u00f3rz pobieranie danych v3.mb.PlayFileNotFound.button.find=Wyszukiwanie r\u0119czne.. v3.mb.deletePurchased.title=Usu\u0144 kupion\u0105 zawarto\u015b\u0107 v3.mb.deletePurchased.text=Czy jeste\u015b pewien, \u017ce chcesz usun\u0105\u0107 zawarto\u015b\u0107 '%1'?\n\nJest to zawarto\u015b\u0107 kupi\u0142e\u015b lub musia\u0142e\u015b by\u0107 zalogowanym, aby pobra\u0107. v3.mb.deletePurchased.button.delete=&Usu\u0144 v3.mb.deletePurchased.button.cancel=&Anuluj v3.topbar.menu.show.plugin=Strefa wtyczki v3.topbar.menu.show.search=Szukaj v3.topbar.menu.show.frog=Niebieska \u017caba splash.initializeCore=Uruchamianie rdzenia splash.initializeUIElements=Uruchamianie element\u00f3w interfejsu u\u017cykownika # ConfigView.section.ipfilter.peerblocking.group=Blokowanie peer\u00f3w ConfigView.section.ipfilter.autoload.group=Automatyczne \u0142adowanie ConfigView.section.ipfilter.autoload.file=Plik filtr\u00f3w IP do automatycznego za\u0142adowania ConfigView.section.ipfilter.autoload.info=Obs\u0142uguje formaty DAT (eMule), P2P (PeerGuardian, splist) i P2B v1,2,3 (PeerGuardian 2). Plik mo\u017ce by\u0107 lokalny lub mo\u017ce by\u0107 URLem, spakowany ZIP, GZIP lub tekstowy. URLe b\u0119d\u0105 automatycznie pobrane ponownie po 7 dniach, podczas gdy pliki b\u0119d\u0105 ponownie za\u0142adowane w ci\u0105gu minuty od ich zast\u0105pienia/zmiany. ConfigView.section.ipfilter.autoload.loadnow=\u0141aduj teraz splash.loadIpFilters=\u0141adowanie filtr\u00f3w IP... SpeedTestWizard.set.upload.title=Ustaw limity pobierania i wysy\u0142ania SpeedTestWizard.set.download.label=Limit pr\u0119dko\u015bci pobierania: SpeedTestWizard.set.upload.label=Limit pr\u0119dko\u015bci wysy\u0142ania: SpeedTestWizard.name.conf.level.absolute=Absolutny SpeedTestWizard.name.conf.level.high=Wysoki SpeedTestWizard.name.conf.level.med=\u015aredni SpeedTestWizard.name.conf.level.low=Niski SpeedTestWizard.name.conf.level.none=\u017baden mb.azmustclose.title=B\u0142\u0105d uruchamiania mb.azmustclose.text=Vuze musi si\u0119 zako\u0144czy\u0107 z powodu problemu (ponownego) uruchomienia, kt\u00f3ry w wi\u0119kszo\u015bci przypadk\u00f3w spowodowany jest uruchomieniem programu jako u\u017cytkownik Administrator.\n\nPo zamkni\u0119ciu si\u0119 Vuze, ponownie uruchom go r\u0119cznie. network.ipv6.prefer.addresses=Preferuj adresy IPv6, gdy s\u0105 dost\u0119pne IPv6 i IPv4 DHTView.title.full_v6=Rozproszona baza danych IPv6 ConfigView.pluginlist.loadSelected=Za\u0142aduj wybrane SpeedView.stats.asn=Sie\u0107: SpeedView.stats.estupcap=Limit wysy\u0142ania: SpeedView.stats.estdowncap=Limit pobierania: SpeedView.stats.unknown=Nieznany SpeedView.stats.estimate=Oszacowany SpeedView.stats.measured=Zmierzony SpeedView.stats.measuredmin=Zmierzony minimalny SpeedView.stats.manual=Ustalony ConfigView.section.transfer.autospeed.networks=Szczeg\u00f3\u0142y sieci ConfigView.section.transfer.autospeed.resetnetwork=Resetuj szczeg\u00f3\u0142y sieci ConfigView.section.transfer.autospeed.network.info=Powy\u017csze limity s\u0105 obliczane automatycznie podczas pobierania lub s\u0105 wynikiem testu pr\u0119dko\u015bci. Je\u015bli chcesz wprowadzi\u0107 je r\u0119cznie u\u017cyj poni\u017cszej opcji.\nWszystkie limity inne ni\u017c "ustalone" b\u0119d\u0105 stopniowo automatycznie korygowane w miar\u0119 potrzeby. \nWprowad\u017a warto\u015b\u0107 a nast\u0119pnie wybierz jej typ. Zauwa\u017c, \u017ce pr\u0119dko\u015bci s\u0105 w %1. dialog.uiswitcher.restart.title=Zmienianie interfejsu u\u017cytkownika: wymagane ponowne uruchomienie Vuze dialog.uiswitcher.restart.text=Vuze wymaga ponownego uruchomienia, aby prze\u0142\u0105czy\u0107 si\u0119 na tryb nowego interfejsu u\u017cytkownika. TrayWindow.menu.close=Zamknij koszyk pobierania # Used for peers which we can't determine. PeerSocket.unknown=Nieznany PeerSocket.fake_client=B\u0141\u0118DNY PeerSocket.bad_peer_id=z\u0142e ID peera PeerSocket.mismatch_id=niezgodno\u015b\u0107 PeerSocket.unknown_az_style=Nieznany %1/%2 PeerSocket.unknown_shadow_style=Nieznany %1/%2 OpenTorrentWindow.mb.askCreateDir.title=Katalog docelowy nie istnieje OpenTorrentWindow.mb.askCreateDir.text=Katalog docelowy "%1" nie istnieje.\n\nUtworzy\u0107 go teraz? SpeedView.stats.estimatechoke=Oszacowany (zatkany) ConfigTransferAutoSpeed.upload.capacity.usage=Za\u0142aduj u\u017cycie pojemno\u015bci ConfigTransferAutoSpeed.mode=Tryb: ConfigTransferAutoSpeed.capacity.used=% u\u017cyta pojemno\u015b\u0107 ConfigTransferAutoSpeed.while.downloading=Pobieranie: ConfigTransferAutoSpeed.set.dht.ping=Ustawienie pingu DHT: ConfigTransferAutoSpeed.set.tolerance=tolerancja (ms) ConfigTransferAutoSpeed.ping.time.good=Dobry: ConfigTransferAutoSpeed.ping.time.bad=Z\u0142y: GeneralView.label.distributedCopies=Rozproszone kopie: PiecesView.DistributionView.title=Wyst\u0119powanie cz\u0119\u015bci PiecesView.DistributionView.NoAvl=Niedost\u0119pne cz\u0119\u015bci PiecesView.DistributionView.RarestAvl=Najrzadsze cz\u0119\u015bci: %1 (Avl:%2) PiecesView.DistributionView.weHave=Cz\u0119\u015bci, kt\u00f3re posiadasz PiecesView.DistributionView.theyHave=Peer ma cz\u0119\u015bci PiecesView.DistributionView.weDownload=Cz\u0119\u015bci, kt\u00f3re pobierasz PeersView.gain=Przyrost PeersView.gain.info=Ilo\u015b\u0107 danych pobranych - wys\u0142anych unix.script.new.title=Jest dost\u0119pny nowy skrypt startowy Vuze unix.script.new.text=Jest dost\u0119pny nowy skrypt startowy Vuze i zosta\u0142 zapisany w "%1".\n\nJest wysoce zalecane natychmiastowe zamkni\u0119cie Vuze i prze\u0142\u0105czenie na ten skrypt ("%2").\n\nJe\u015bli zmodyfikowa\u0142e\u015b skrypt startowy Vuze, odwied\u017a AzureusWiki: Unix Script.\n\nJe\u015bli instalowa\u0142e\u015b Vuze z pakiet\u00f3w dystrybucyjnych (yum, apt-get, itp.), zalecana jest reinstalacja Vuze z pakietu na Vuze Sourceforge Page (B\u0119dziesz mia\u0142 taki sam interfejs u\u017cytkownika jak teraz). unix.script.new.button.quit=Wyjd\u017a teraz unix.script.new.button.continue=Zrobi\u0119 to p\u00f3\u017aniej unix.script.new.button.asknomore=Nie powiadamiaj mnie ponownie unix.script.new.auto.title=Nowy skrypt startowy Vuze unix.script.new.auto.text=Jest dost\u0119pny nowy skrypt startowy Vuze.\n\nJest wysoce zalecane natychmiastowe ponowne uruchomienie Vuze. Content.alert.notuploaded.button.continue=&Kontynuuj wysy\u0142anie Content.alert.notuploaded.button.abort=&Nie porzucaj ConfigView.label.checkOnSeeding=Sprawd\u017a ponownie cz\u0119\u015bci podczas seedowania. ConfigView.label.ui_switcher=Wy\u015bwietl zmieniacza interfejsu u\u017cytkownika Vuze ConfigView.label.ui_switcher_button=Poka\u017c SpeedTestWizard.test.panel.explain=Zmierz swoj\u0105 pr\u0119dko\u015b\u0107 protoko\u0142u Vuze. Wybierz rodzaj testu i tryb szyfrowania. Odwied\u017a stron\u0119 wiki Vuze, aby dowiedzie\u0107 si\u0119 o szczeg\u00f3\u0142ach tego testu. Test zatrzyma si\u0119 automatycznie, je\u015bli potrwa d\u0142u\u017cej ni\u017c 2 minuty. Zazwyczaj test trwa mniej ni\u017c minut\u0119. SpeedTestWizard.set.upload.hint=Ustaw limity pobierania i wysy\u0142ania u\u017cywane przez algorytm Vuze AutoSpeed. SpeedTestWizard.set.upload.panel.explain=Limity ustawiane tutaj s\u0105 u\u017cywane przez algorytm Vuze AutoSpeed. Ustaw limity transferu i prywatno\u015bci.\n\nZauwa\u017c, \u017ce pr\u0119dko\u015bci s\u0105 podawane w "bitach na sekund\u0119" (b/s) - a warto\u015b\u0107 poni\u017cej jest podana w "kilobajtach na sekund\u0119" (kB/s). SpeedTestWizard.set.limit.conf.level=Prywatno\u015b\u0107 SpeedTestWizard.finish.panel.auto.speed=AutoSpeed jest : SpeedTestWizard.finish.panel.auto.speed.seeding=AutoSpeed, gdy seedowuj\u0119 jest : ConfigTransferAutoSpeed.add.comment.to.log.group=Dodaj komentarz do pliku debugowania ConfigTransferAutoSpeed.add.comment.to.log=Dodaj komentarz: ConfigTransferAutoSpeed.algorithm.selector=Wyb\u00f3r rodzaju Auto-Speed ConfigTransferAutoSpeed.algorithm=Algorytm: ConfigTransferAutoSpeed.auto.speed.classic=Auto-Speed (klasyczny) ConfigTransferAutoSpeed.auto.speed.beta=Auto-Speed (beta) ConfigTransferAutoSpeed.data.update.frequency=Cz\u0119stotliwo\u015b\u0107 uaktualniania Alert.failed.update=Instalacja co najmniej jednego sk\u0142adnika nieudana. Zobacz AzureusWiki: Failed Update [%1] OpenTorrentWindow.mb.existingFiles.partialList=(Lista cz\u0119\u015bciowa. Istnieje wi\u0119cej plik\u00f3w) TableColumn.header.bad_avail_time.info=Ostatni raz, kiedy pe\u0142na kopia tego pobrania by\u0142a dost\u0119pna TableColumn.header.bad_avail_time=Pe\u0142na kopia widziana MyTorrentsView.menu.exporthttpseeds=Eksportuj URL seeda HTTP do schowka SWT.alert.erroringuithread=Pojawi\u0142 si\u0119 niespodziewany b\u0142\u0105d w interfejsie u\u017cytkownika, p\u00f3\u017aniejsze b\u0142\u0119dy mog\u0105 by\u0107 zaraportowane. ConfigView.label.minannounce=Minimalny czas mi\u0119dzy zg\u0142oszeniami trackera w sekundach ConfigView.label.maxnumwant=Ograniczenie ilo\u015bci pobieraj\u0105cych tracker mo\u017ce zwr\u00f3ci\u0107 ConfigView.label.announceport=Omi\u0144 port announce TCP trackera\n[zostaw puste: brak omini\u0119cia, 0: brak po\u0142\u0105cze\u0144 przychodz\u0105cych] ConfigView.label.noportannounce=Nie zg\u0142aszaj portu nas\u0142uchowego do trackera (nie dotyczy pex, dht) ConfigView.label.maxseedspertorrent=Maksymalna ilo\u015b\u0107 seed\u00f3w na torrent [0: nieograniczona] wizard.webseed=Dodaj seed\u00f3w HTTP do torrentu wizard.webseed.title=Seedowie HTTP wizard.webseed.configuration=Konfiguracja seed\u00f3w HTTP wizard.webseed.adding=Dodawanie seed\u00f3w HTTP GeneralView.label.private=Prywatny torrent: GeneralView.yes=Tak GeneralView.no=Nie ConfigView.label.userequestlimiting=U\u017cywaj pro\u015bby zahamowania zamiast op\u00f3\u017ania\u0107 odczyt limitu pr\u0119dko\u015bci pobierania [brak efektu, gdy pr\u0119dko\u015b\u0107 pobierania jest nieograniczona] ConfigView.label.userequestlimiting.tooltip=Pro\u017aba o ograniczenie nie jest tak dobra jak op\u00f3\u017anienie odczytu, ale pozwala na ustawianie priorytetu pobierania opieraj\u0105c si\u0119 o pozycj\u0119 pobierania w kolejce i mo\u017ce przyspieszy\u0107 wydajno\u015b\u0107 sieci ConfigView.label.userequestlimitingpriorities=Ustawienie pr\u0119dko\u015bci pobierania przed pobieraniem z kolejki, gdy limit pr\u0119dko\u015b\u0107 pobierania jest osi\u0105gni\u0119ty ConfigView.section.logging.timestamp=Format linii czasu dla plik\u00f3w z logami Peers.column.timetocomplete=Pozosta\u0142y czas Peers.column.timetocomplete.info=Pozosta\u0142y czas, uko\u0144czenia peera ConfigView.section.interface.display.suppress.file.download.dialog=Okno potwierdzenia op\u00f3\u017anienia pobierania plik\u00f3w ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Poka\u017c post\u0119p wszystkich pobieranych plik\u00f3w w pasku statusu zamiast w oknie dialogowym FileDownload.canceled=Pobieranie pliku torrent zosta\u0142o anulowane przez akcj\u0119 u\u017cytkownika: %1 Progress.reporting.status.canceled=Anulowano Progress.reporting.status.finished=Zako\u0144czono Progress.reporting.status.retrying=Ponawianie... Progress.reporting.action.label.retry.tooltip=Pon\u00f3w operacj\u0119 Progress.reporting.action.label.remove.tooltip=Usu\u0144 raport post\u0119pu z historii Progress.reporting.action.label.cancel.tooltip=Anuluj operacj\u0119 Progress.reporting.action.label.detail=Szczeg\u00f3\u0142y Progress.reporting.default.error=Nieudany Progress.reporting.no.reports.to.display=Brak raport\u00f3w post\u0119pu do wy\u015bwietlenia. Progress.reporting.no.history.to.display=Brak szczeg\u00f3\u0142owych wiadomo\u015bci do wy\u015bwietlenia. Progress.reporting.detail.history.limit=Limit szczeg\u00f3\u0142owych wiadomo\u015bci (%1) dla tego raportu post\u0119pu zosta\u0142 osi\u0105gni\u0119ty; dalsze wiadomo\u015bci nie b\u0119d\u0105 dodawane do historii Progress.reporting.statusbar.button.tooltip=Poka\u017c okno post\u0119pu raportowania webui.bindip=Bind IP - zwykle niewymagany (*) v3.MainWindow.text.log.in=Zaloguj v3.MainWindow.text.log.out=Wyloguj v3.MainWindow.text.get.started=Zarejestruj v3.MainWindow.text.my.account=Informacja o koncie v3.MainWindow.text.my.profile=Profil OpenTorrentWindow.simple.open=Lokalizacja torrenta (plik, URL, Hash) Progress.reporting.window.remove.auto=Automatycznie usu\u0144 nieaktywne przedmioty Progress.reporting.window.remove.auto.tooltip=Automatycznie usu\u0144 wszystkie uko\u0144czone, nieudane lub anulowane procesy z tego widoku Progress.reporting.window.remove.now=Usu\u0144 nieaktywne przedmioty Progress.reporting.window.remove.now.tooltip=Usu\u0144 wszystkie uko\u0144czone, nieudane lub anulowane procesy z tego widoku TorrentOptionsView.multi.title.short=Opcje torrenta TorrentOptionsView.multi.title.full=Opcje torrenta MyTorrentsView.menu.open_parent_folder=Otw\u00f3rz folder zawieraj\u0105cy ConfigView.section.style.use_show_parent_folder=U\u017cyj "%1" zamiast "%2" w menu torrent ConfigView.section.style.use_show_parent_folder.tooltip=W\u0142\u0105czenie tej opcji pozwoli na otwieranie folderu w prawid\u0142owej aplikacji zarz\u0105dzania plikami.\nJednak, mo\u017ce to znaczy\u0107, \u017ce miejsce zapisu pobra\u0144 nie jest automatycznie wybrane. PeerManager.status.ps_disabled=\u0179r\u00f3d\u0142o trackera peera jest wy\u0142\u0105czone ConfigView.section.stats.exportfiles=Szczeg\u00f3\u0142y eksportu pliku updater.cant.write.to.app.title=Nie mo\u017cna zapisa\u0107 do foleru aplikacji updater.cant.write.to.app.details=Folder "%1" nie jest do zapisu.\n\nPrzeszkodzi to w przysz\u0142o\u015bci uruchomieniu aktualizacji oprogramowania.\n\nProsz\u0119 zobacz szczeg\u00f3\u0142y na wiki. plugin.install.class_version_error=Wtyczka do uruchomienia wymaga nowszej wersji Javy. v3.MainWindow.tab.minilibrary=Pobrania v3.MainWindow.tab.events=Powiadomienia v3.activity.remove.title=Usu\u0144 powiadomienie v3.activity.remove.text=Czy jeste\u015b pewien, \u017ce chcesz usun\u0105\u0107 te powiadomienie ? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=Zamknij Menu.show.torrent.menu=Poka\u017c menu torrent\u00f3w Menu.show.torrent.menu.tooltip=Poka\u017c menu torrent\u00f3w nad paskiem menu aplikacji #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=Status sieci ConfigView.section.style.usePathFinder=U\u017cyj 'wyszukiwania \u015bcie\u017cki' zamiast 'wyszukiwania' menu.sortByColumn=Sortuj po %1 MyTorrentsView.menu.manual.per_peer=R\u0119cznie (na peer) MyTorrentsView.menu.manual.shared_peers=R\u0119cznie (mi\u0119dzy peers) v3.button.removeActivityEntry=Usu\u0144 powiadomienie v3.splash.initSkin=Uruchamianie sk\u00f3rki interfejsu u\u017cytkownika v3.splash.hookPluginUI=Przyczepione do wtyczki interfejsu u\u017cytkownika OpenTorrentWindow.mb.notTorrent.cannot.display=Nie mo\u017cna poprawnie wy\u015bwietli\u0107 danych MainWindow.menu.window.zoom.maximize=Maksymalizuj MainWindow.menu.window.zoom.restore=Przywr\u00f3\u0107 ImageResizer.image.too.small=Wprowadzony obrazek jest za ma\u0142y, wybierz inny (musi by\u0107 przynajmniej %1 x %2) ImageResizer.title=Te narz\u0119dzie pozwala na podgl\u0105d jak b\u0119dzie wygl\u0105da\u0142 Tw\u00f3j paznokie\u0107 kciuka na platformie Vuze ImageResizer.move.image=Przenie\u015b obrazek przez przeci\u0105gni\u0119cie ImageResizer.move.image.with.slider=Przenie\u015b obrazek przez przeci\u0105gni\u0119cie, dostosuj go u\u017cywaj\u0105c poni\u017cszego suwaka security.crypto.title=Kontrola klucza szyfruj\u0105cego security.crypto.encrypt=Wprowad\u017a has\u0142o, \u017ceby zabezpieczy\u0107 nowo wygenerowany klucz szyfruj\u0105cy. Nie zapomnij has\u0142a, nie ma mo\u017cliwo\u015bci na jego odzyskanie! security.crypto.decrypt=Wprowad\u017a has\u0142o, \u017ceby odblokowa\u0107 klucz szyfruj\u0105cy. security.crypto.reason=Pow\u00f3d operacji security.crypto.password=Has\u0142o security.crypto.password2=Wprowad\u017a ponownie has\u0142o security.crypto.persist_for=Okres do wyga\u015bni\u0119cia has\u0142a security.crypto.persist_for.dont_save=Nie zapisuj security.crypto.persist_for.session=Na t\u0119 sesj\u0119 security.crypto.persist_for.day=1 dzie\u0144 security.crypto.persist_for.week=1 tydzie\u0144 security.crypto.persist_for.30days=30 dni security.crypto.persist_for.forever=Na zawsze security.crypto.password.mismatch.title=B\u0142\u0105d has\u0142a security.crypto.password.mismatch=Wprowadzone has\u0142a nie pasuj\u0105, wprowad\u017a ponownie. ConfigView.section.security.group.crypto=Klucze publiczne/prywatne ConfigView.section.security.resetkey=Resetuj klucze ConfigView.section.security.resetkey.warning.title=Ostrze\u017cenie utraty danych ConfigView.section.security.resetkey.warning=Czy jeste\u015b pewien, \u017ce chcesz zresetowa\u0107 klucze szyfruj\u0105ce? Je\u015bli to zrobisz wszystkie u\u017cywane przez nie informacje b\u0119d\u0105 BEZPOWROTNIE UTRACONE. Inni peersi posiadaj\u0105cy Tw\u00f3j klucz publiczny nie b\u0119d\u0105 ju\u017c w stanie komunikowa\u0107 si\u0119 z Tob\u0105 bez wymiany nowego klucza. Dlatego, je\u015bli nie jeste\u015b tego pewien, nie r\u00f3b tego. ConfigView.section.security.unlockkey.button=Odblokuj ConfigView.section.security.publickey=Klucz publiczny ConfigView.section.security.publickey.undef=Jeszcze niezdefiniowane ConfigView.section.security.resetkey.error.title=Operacja nieudana ConfigView.section.security.resetkey.error=Nieudane zresetowanie kluczy ConfigView.section.security.unlockkey.error=Nieudane odblokowanie klucza - z\u0142e has\u0142o ConfigView.copy.to.clipboard.tooltip=Kopiuj do schowka Views.plugins.azbuddy.title=Znajomi Browser.popup.error.no.access=Wyst\u0105pi\u0142 b\u0142\u0105d podczas pr\u00f3by dost\u0119pu do zdalnego \u017ar\u00f3d\u0142a.\nSpr\u00f3buj ponownie p\u00f3\u017aniej.\n ConfigView.label.queue.stoponcebandwidthmet=Nie uruchamiaj wi\u0119cej torrent\u00f3w gdy limit pr\u0119dko\u015bci wysy\u0142ania/pobierania jest osi\u0105gni\u0119ty ConfigView.section.style.forceMozilla=Wymu\u015b na Vuze u\u017cycie wid\u017cet\u00f3w przegl\u0105darki Mozilla [wymagany xulrunner lub firefox 3; wymaga ponownego uruchomienia] ConfigView.section.style.xulRunnerPath=Okre\u015bl \u015bcie\u017ck\u0119 XulRunner / Firefox r\u0119cznie [wymagana dla FF3; wymagane ponownie uruchomienie] azbuddy.name=Znajomi azbuddy.enabled=W\u0142\u0105czony azbuddy.disabled=Wtyczka jest wy\u0142\u0105czona, aby zmieni\u0107 zobacz konfiguracj\u0119 wtyczki. azbuddy.nickname=Tw\u00f3j Nick azbuddy.msglog.title=Informacje od znajomego azbuddy.addtorrent.title=Akceptujesz pobranie? azbuddy.addtorrent.msg=Znajomy '%1' przesta\u0142 Tobie '%2'.\nCzy chcesz doda\u0107 to do pobrania? azbuddy.contextmenu=Wy\u015blij do znajomego azbuddy.ui.mykey=M\u00f3j klucz: azbuddy.ui.add=Dodaj azbuddy.ui.new_buddy=Nowy klucz znajomego: azbuddy.ui.table.name=Nazwa azbuddy.ui.table.last_msg=Ostatnia wiadomo\u015b\u0107 azbuddy.ui.menu.remove=Usu\u0144 azbuddy.ui.menu.copypk=Kopiuj klucz publiczny azbuddy.ui.menu.send=Wy\u015blij wiadomo\u015b\u0107 azbuddy.ui.menu.send_msg=Wpisz tekst, aby wys\u0142a\u0107 znajomemu azbuddy.ui.menu.ygm=Wy\u015blij YGM azbuddy.ui.menu.enc=Zaszyfruj schowek azbuddy.ui.menu.dec=Odszyfruj schowek azbuddy.ui.menu.sign=Zapisz schowek azbuddy.ui.menu.verify=Zweryfikuj schowek azbuddy.ui.table.lastseen=Ostatnio widziany Button.retry=Pon\u00f3w Button.ignore=Ignoruj DHTView.general.skew=Wypaczone: v3.MainWindow.menu.view.footer=Stopka azbuddy.downspeed=KB/s max pr\u0119dko\u015b\u0107 pobierania dla znajomego [0: nieograniczony] security.crypto.badpw=Wprowadzone has\u0142o jest nieprawid\u0142owe ConfigView.section.security.backupkeys=Kopia zapasowa kluczy do pliku ConfigView.section.security.backupkeys.button=Kopia zapasowa ConfigView.section.security.restorekeys=Przywr\u00f3c klucze z pliku ConfigView.section.security.restorekeys.button=Przywr\u00f3\u0107 ConfigView.section.security.op.error.title=Operacja niemo\u017cliwa ConfigView.section.security.op.error=Niemo\u017cliwe uko\u0144czenie operacji:\n %1 ConfigView.section.security.restart.title=Wymagane ponowne uruchomienie ConfigView.section.security.restart.msg=Vuze zostanie ponownie uruchomiomy, aby uko\u0144czy\u0107 operacj\u0119. ConfigView.section.security.system.managed=System zarz\u0105dzania ochron\u0105 klucza azbuddy.ui.table.msg_queued=W kolejce azbuddy.ui.menu.chat=Czat azbuddy.chat.title=Czat Vuze azbuddy.chat.says=%1 m\u00f3wi: Button.bar.show=Poka\u017c Button.bar.hide=Ukryj Button.bar.share=Udost\u0119pnij Button.bar.add=Dodaj Button.bar.edit=Edytuj v3.MainWindow.menu.view.pluginbar=Pasek wtyczki MainWindow.dialog.select.vuze.file=Wybierz plik Vuze MainWindow.menu.file.open.vuze=Plik Vuze... metasearch.addtemplate.title=Zainstalowa\u0107 szablon wyszukiwania? metasearch.addtemplate.desc=Czy jeste\u015b pewien, \u017ce chcesz zainstalowa\u0107 szablon wyszukiwania nazwany '%1'? v3.share.private.title=Udost\u0119pnianie torrenty v3.share.private.text=Wybrany torrent jest zaznaczony jako prywatny torrent.\n\nNie mo\u017cesz udost\u0119pnia\u0107 prywatnych torrent\u00f3w. metasearch.addtemplate.dup.title=Duplikat szablonu metasearch.addtemplate.dup.desc=Szablon wyszukiwania %1 jest ju\u017c zainstalowany metasearch.export.select.template.file=Zapisz szablon metasearch.import.select.template.file=Otw\u00f3rz szablon dialog.uiswitch.title=Prze\u0142\u0105cz do interfejsu u\u017cytkownika Vuze dialog.uiswitch.text=Musisz mie\u0107 uruchomiony interfejs u\u017cytkownika Vuze, aby u\u017cy\u0107 tej opcji.\n\nVuze musi by\u0107 ponownie uruchomiony. dialog.uiswitch.button=Prze\u0142\u0105cz do interfejsu u\u017cytkownika Vuze azbuddy.tracker.enabled=W\u0142\u0105cz 'Friends Boost', aby uszeregowa\u0107 pobieranie ze znajomymi v3.MainWindow.button.download=Pobierz v3.MainWindow.button.run=Uruchom pobrany plik v3.activity.header.downloads=Pobierania v3.activity.header.vuze.news=Wiadomo\u015bci Vuze message.taking.too.long=Zajmuje to wi\u0119cej czasu ni\u017c zwykle\nNaci\u015bnij 'ESC' je\u015bli chcesz anulowa\u0107 operacj\u0119 message.status.success=Sukces azbuddy.tracker.bbb.status.title.tooltip=Kliknij podw\u00f3jnie, aby uzyska\u0107 szczeg\u00f3\u0142y azbuddy.tracker.bbb.status.nli=Wymagany login v3.MainWindow.search.go.tooltip=Wykonaj wyszukiwanie v3.MainWindow.search.last.tooltip=Powr\u00f3\u0107 do wynik\u00f3w wyszukiwania metasearch.addtemplate.done.title=Szablon dodany metasearch.addtemplate.done.desc=Szablon '%1' dodany prawid\u0142owo.\nB\u0119dzie u\u017cyty przy nast\u0119pnym wyszukiwaniu! ConfigView.section.security.nopw=Nie podano has\u0142a ConfigView.section.security.nopw_v=Has\u0142o niedost\u0119pne, prosz\u0119 si\u0119 zalogowa\u0107 do Vuze fileplugininstall.install.title=Zainstalowa\u0107 wtyczk\u0119? fileplugininstall.install.desc=Czy jeste\u015b pewien, \u017ce chcesz zainstalowa\u0107 wtyczk\u0119 '%1', w wersji %2? fileplugininstall.duplicate.title=Duplikat wtyczki fileplugininstall.duplicate.desc=Wtyczka '%1', w wersji %2 jest ju\u017c zainstalowana azbuddy.online_status=Status Online azbuddy.os_away=Oddalony azbuddy.os_not_avail=Niedost\u0119pny azbuddy.os_busy=Zaj\u0119ty azbuddy.ui.menu.disconnect=Roz\u0142\u0105cz azbuddy.enable_chat_notif=W\u0142\u0105cz powiadomienia z czata progress.window.msg.progress=Prosz\u0119 czeka\u0107 na uko\u0144czenie operacji ConfigView.section.connection.advanced.read_select=Odczyt wybranego czasu oczekiwania (milisekundy, domy\u015blnie %1) ConfigView.section.connection.advanced.read_select_min=Odczyt wybraneego minimalnego oczekiwania (milisekundy, domy\u015blnie %1) ConfigView.section.connection.advanced.write_select=Zapis wybranego czasu oczekiwania (milisekundy, domy\u015blnie %1) ConfigView.section.connection.advanced.write_select_min=Zapis wybranego minimalnego oczekiwania (milisekundy, domy\u015blnie %1) DetailedListView.title=Lista ze szczeg\u00f3\u0142ami ConfigView.section.connection.network.max.outstanding.connect.attempts=Maksymalna ilo\u015b\u0107 pr\u00f3b po\u0142\u0105cze\u0144 plugins.init.force_enabled=Vuze wykry\u0142 wy\u0142\u0105czon\u0105 wtyczk\u0119 "%1" - zosta\u0142a ona w\u0142\u0105czona, \u017ceby Vuze m\u00f3g\u0142 poprawnie dzia\u0142a\u0107. ConfigView.section.connection.prefer.udp=Preferuj po\u0142\u0105czenia UDP subscript.add.title=Zainstalowa\u0107 subskrypcj\u0119? subscript.add.desc=Czy na pewno chcesz zainstalowa\u0107 subskrybcj\u0119 '%1'? subscript.add.dup.title=Duplikat subskrypcji subscript.add.dup.desc=Subskrybcja '%1' jest ju\u017c zainstalowana. subscript.add.upgrade.title=Uaktualni\u0107 subskrypcj\u0119? subscript.add.upgrade.desc=Czy na pewno chcesz uaktualni\u0107 subskrypcj\u0119 '%1'? subscript.add.upgradeto.desc=Wersja %1 subskrypcji '%2' jest dost\u0119pna.\nCzy chcesz uaktualni\u0107? iconBar.start=Uruchom iconBar.stop=Zatrzymaj iconBar.remove=Usu\u0144 iconBar.up=G\u00f3ra iconBar.down=D\u00f3\u0142 iconBar.run=Uruchom iconBar.editcolumns=Ustawienie kolumny iconBar.top=Przesu\u0144 w g\u00f3r\u0119 iconBar.bottom=Przesu\u0144 w d\u00f3\u0142 iconBar.queue=Uruchom iconBar.open=Dodaj torrent iconBar.share=Udost\u0119pnij iconBar.share.tooltip=Zawarto\u015b\u0107 udost\u0119pniana iconBar.details=Szczeg\u00f3\u0142y iconBar.comment=Komentarz iconBar.play=Odtw\u00f3rz iconBar.queue.tooltip=Uruchom (w kolejce) wybrane torrenty v3.MainWindow.menu.view.sidebar=Pasek boczny v3.MainWindow.menu.view.actionbar=Pasek akcji v3.MainWindow.menu.view.toolbars=Paski narz\u0119dziowe ump.install=Zako\u0144czenie aktualizacji trwa:\nInstalacja ma\u0142ego dodatku jest wymagana dla tego wideo. subscriptions.listwindow.title=Wyszukiwarka subskrypcji subscriptions.listwindow.autochecktext=Vuze mo\u017ce poszuka\u0107 subskrypcji zwi\u0105zanych z zawarto\u015bci\u0105 Twojej biblioteki. Czy chcesz w\u0142\u0105czy\u0107 t\u0119 funkcj\u0119? subscriptions.listwindow.loadingtext=Szukanie subskrypcji zwi\u0105zanych z %1 subscriptions.listwindow.failed=Nie znaleziono subskrypcji subscriptions.listwindow.popularity=Popularno\u015b\u0107 subscriptions.listwindow.popularity.unknown=Nieznany subscriptions.listwindow.name=Nazwa subscriptions.listwindow.subscribe=Subskrybuj TableColumn.header.azsubs.ui.column.subs=Subskrybuj subscriptions.listwindow.popularity.reading=Wczytywanie... PluginDeprecation.log.start=To okno zawieta informacje o wtyczkach u\u017cywaj\u0105cych funkcjonalno\u015bci, kt\u00f3ra zostanie usuni\u0119ta w przysz\u0142ych wersjach Vuze.\nNie musisz odinstalowa\u0107 wtyczki, ale powiniene\u015b uaktualni\u0107 wtyczk\u0119 do ostaniej wersji,\nJe\u015bli ju\u017c masz najnowsz\u0105 wersj\u0119 to skopiuj zawarto\u015b\u0107 tego okna i umie\u015b\u0107 na forum zlokalizowanym tutaj:\n\t%1 PluginDeprecation.view=Debugowanie wtyczki PluginDeprecation.alert=Wtyczka pr\u00f3buje u\u017cywa\u0107 funkcjonalno\u015bci, kt\u00f3ra b\u0119dzie usuni\u0119ta w przysz\u0142o\u015bci - otw\u00f3rz widok logu debugowania wtyczki po wi\u0119cej informacji. TableColumn.header.Thumbnail=Ikona TableColumn.header.Thumbnail.info=Obrazek dla zawarto\u015bci Vuze; dla innych system operacyjny wprowadzi te ikony. v3.MainWindow.menu.getting_started=&Rozpocznij MainWindow.menu.community=&Spo\u0142eczno\u015b\u0107 MainWindow.menu.help.faq=FAQ MainWindow.menu.community.wiki=Spo\u0142eczno\u015b\u0107 &Wiki MainWindow.menu.community.forums=Fo&rum spo\u0142eczno\u015bciowe MainWindow.menu.help.support=&Pomoc i wsparcie externalLogin.title=Wymagany login externalLogin.explanation=Szablon "%1" wymaga zalogowania. Gdy si\u0119 zalogujesz, to okno automatycznie si\u0119 zamknie. Je\u015bli nie to zamknij je klikaj\u0105c w "wykonano". externalLogin.explanation.capture=Musisz si\u0119 zalogowa\u0107, \u017ceby utworzy\u0107 ten szablon. Je\u015bli ju\u017c b\u0119dziesz, kliknij w "Wykonano". Button.done=Wykonano GeneralView.torrent_created_on_and_by=%1 przez %2 Button.continue=Kontynuuj Button.preview=Podgl\u0105d Subscription.menu.forcecheck=Uaktualnij teraz Subscription.menu.clearall=Zaznacz wszystkie jako przeczytane Subscription.menu.remove=Usu\u0144 sidebar.Library=Moja biblioteka sidebar.LibraryDL=Pobierane sidebar.LibraryCD=Uko\u0144czono authenticator.location=Lokalizacja authenticator.details=Szczeg\u00f3\u0142y v3.MainWindow.menu.showActionBarText=Poka\u017c Tekst subscript.import.fail.title=Nieudany import subscript.import.fail.desc=Szczeg\u00f3\u0142y: %1 Subscription.menu.export=Eksportuj subscript.export.select.template.file=Zapisz subskrypcj\u0119 Button.remove=Usu\u0144 Button.send=Wy\u015blij Button.back=Cofnij sidebar.LibraryUnopened=Nieobserwowane TableColumn.header.unopened=Nowy Unopened.bigView.header=Nowy Subscription.menu.deleteall=Usu\u0144 wszystkie przeczytane Subscription.menu.reset=Resetuj do stanu pocz\u0105tkowego ConfigView.section.Subscriptions=Subskrypcje subscriptions.config.maxresults=Maksymalna ilo\u015b\u0107 wynik\u00f3w przypisanych do subskrypcji [0: nieograniczona] v3.activity.button.readall=Zaznacz wszystkie przeczytanie TableColumn.header.activityNew=Nowy TableColumn.header.activityType=Typ TableColumn.header.activityText=Wiadomo\u015b\u0107 TableColumn.header.activityDate=Data dodania TableColumn.header.activityActions=Akcje Subscription.menu.resetauth=Resetuj szczeg\u00f3\u0142y uwierzytelnienia Search.menu.engines=Szablony Wizard.Subscription.title=Subskrybuj Wizard.Subscription.optin.title=W\u0142\u0105cz subskrypcje #what you've watched? Discover more with a single click... Wizard.Subscription.subscribe.title=Dost\u0119pne subskrypcje Wizard.Subscription.create.title=Utw\u00f3rz now\u0105 subskrypcj\u0119 Button.search=Szukaj Button.save=Zapisz Button.add=Dodaj Button.createNewSubscription=Utw\u00f3rz now\u0105 subskrypcj\u0119 Button.availableSubscriptions=Dost\u0119pne subskrypcje Wizard.Subscription.optin.description=Z w\u0142\u0105czonymi subskrypcjami, Vuze b\u0119dzie pokazywa\u0142 subskrypcje zwi\u0105zane z zawarto\u015bci\u0105 Twojej bibilioteki i powiadomi, gdy zawarto\u015b\u0107 subskrypcji b\u0119dzie dost\u0119pna do pobrania.\n\nCzy chcia\u0142by\u015b w\u0142\u0105czy\u0107 subskrypcje? Wizard.Subscription.create.search=Szukaj Wizard.Subscription.search.subtitle1=Wpisz w wyszukiwark\u0119, aby zacz\u0105\u0107 tworzy\u0107 swoj\u0105 subskrypcj\u0119 : Wizard.Subscription.search.subtitle2=Czego mog\u0119 szuka\u0107? Wizard.Subscription.search.subtitle2.sub1=Filmy HD, seriale telewizyjne, filmy, trailery w sieci Vuze Wizard.Subscription.search.subtitle2.sub2=Torrenty z ca\u0142ej sieci Wizard.Subscription.search.subtitle3=Po zako\u0144czeniu subskrypcji, b\u0119dziesz otrzymywa\u0107 aktualizacje w pasku bocznym, je\u015bli tylko b\u0119d\u0105 dost\u0119pnie nowe wyniki dla Twojego wyszukiwania. Wizard.Subscription.rss.subtitle1=Wpisz lub wklej URL poni\u017cej: Wizard.Subscription.rss.subtitle2=Wielu publikuj\u0105cych wprowadza kana\u0142 RSS do swojej zawarto\u015bci. Znajd\u017a URL na stronie publikuj\u0105cego, skopiuj i wklej URL w pole powy\u017cej, potem kliknij Zapisz. Wizard.Subscription.rss.subtitle3=Po zapisaniu, b\u0119dziesz otrzymywa\u0142 aktualizacje w pasku bocznym, je\u015bli tylko b\u0119d\u0105 dost\u0119pne nowe wyniki przez kana\u0142 RSS. Wizard.Subscription.subscribe.library=Zawarto\u015b\u0107 Twojej biblioteki Wizard.Subscription.subscribe.subscriptions=Powi\u0105zane subskrypcje Wizard.Subscription.subscribe.library.empty=Brak dost\u0119pnych subskrypcji?\n \nSp\u00f3jrz na jasno pomara\u0144czony przycisk subskrypcji w Sie\u0107 Vuze HD.\n \nWi\u0119cej message.confirm.delete.title=Potwierd\u017a usuni\u0119cie message.confirm.delete.text=Czy na pewno chcesz usun\u0105\u0107 '%1'? Subscription.menu.properties=W\u0142a\u015bciwo\u015bci props.window.title=W\u0142a\u015bciwo\u015bci dla '%1' subs.prop.is_auto=Nowe wyniki automatycznego pobierania subs.prop.last_scan=Ostatnia poprawna aktualizacja subs.prop.last_result=Ostatnie nowe wyniki znaleziono subs.prop.last_error=Ostatni b\u0142\u0105d subs.prop.num_read=Wyniki ilo\u015bci przeczytanych subs.prop.num_unread=Wyniki ilo\u015bci nieprzeczytanych subs.prop.template=Szablon subs.prop.auth=Wymagane uwierzytelnienie externalLogin.auth_method_proxy=U\u017cyj zewn\u0119trznej metody przechwytu cookie . Je\u015bli zawiedzie, wy\u0142\u0105cz opcj\u0119 i pon\u00f3w externalLogin.wait=\u0141adowanie strony, prosz\u0119 czeka\u0107... TableColumn.menu.date_added.time=Poka\u017c/Ukryj czas sidebar.VuzeHDNetwork=Sie\u0107 Vuze HD subs.prop.next_scan=Nast\u0119pne skanowanie za subs.prop.version=Wersja subscriptions.column.new.info=Dotyczy, je\u015bli jest jeden lub wi\u0119cej nowych wynik\u00f3w subscriptions.column.name=Subskrypcja subscriptions.column.nb-results=Ca\u0142kowicie wyniki subscriptions.column.nb-new-results=Nowe wyniki subscriptions.column.last-checked=Ostatnio sprawdzone subscriptions.view.title=Subskrypcje subs.prop.is_public=Pulbiczny subs.prop.high_version=Najwy\u017csza wersja napotkana Subscription.menu.upgrade=W\u0142\u0105cz uaktualnienie do wy\u017cszej wersji metasearch.template.version.bad=Szablon wyszukiwania '%1' nie mo\u017ce by\u0107 zainstalowany dop\u00f3ki nie uaktualnisz Vuze metasearch.addtemplate.failed.title=Instalacja nieudana metasearch.addtemplate.failed.desc=Nie mo\u017cna zainstalowa\u0107 szablonu wyszukiwania: %1 subscription.version.bad=Subskrypcja '%1' nie mo\u017ce by\u0107 zainstalowana dop\u00f3kiu Vuze nie b\u0119dzie zaktualizowany statusbar.feedback=Wy\u015blij opini\u0119 statusbar.feedback.tooltip=Kliknij tutaj, aby wys\u0142a\u0107 opini\u0119 sidebar.Activity=Powiadomienia v3.activity.button.watchall=Zaznacz wszystkie zobaczone subscriptions.view.help.1=Dodaj subskrypcje, kt\u00f3re widzisz subscriptions.view.help.2=Zdob\u0105d\u017a bezp\u0142atnie nowe aktualizacje, je\u015bli b\u0119d\u0105 dost\u0119pne do pobrania. Wi\u0119cej. sidebar.sash.tooltip=F7 do szybkiego ukrycia/pokazania paska bocznego sidebar.expand.tooltip=Rozwi\u0144 pasek boczny sidebar.dropdown.tooltip=Poka\u017c pasek boczny w menu formatu subscript.all.subscribed=Zam\u00f3wi\u0142e\u015b ju\u017c t\u0119 zawarto\u015b\u0107 subscript.some.subscribed=Zam\u00f3wi\u0142e\u015b ju\u017c niekt\u00f3re subskrypcje tej zawarto\u015bci.\nKliknij, aby zobaczy\u0107 inne dost\u0119pne subscript.none.subscribed=Kliknij, aby zobaczy\u0107 dost\u0119pne subskrypcje tej zawarto\u015bci v3.iconBar.up.tooltip=Przesu\u0144 wy\u017cej\nPrzytrzymaj przycisk myszy, \u017ceby przesun\u0105\u0107 do g\u00f3ry v3.iconBar.down.tooltip=Przesu\u0144 ni\u017cej\nPrzytrzymaj przycisk myszy, \u017ceby przesun\u0105\u0107 do do\u0142u TableColumn.header.azsubs.ui.column.subs_link=Zwi\u0105zek TableColumn.header.azsubs.ui.column.subs_link.info=Zwi\u0105zej z subskrybcjami Button.deleteContent.fromLibrary=Usu\u0144 z biblioteki Button.deleteContent.fromComputer=Usu\u0144 z komputera v3.deleteContent.message=\nCzy chcia\u0142by\u015b usun\u0105\u0107 '%1' z komputera czy tylko z biblioteki Vuze? v3.MainWindow.menu.view.toolbartext=Tekst pod paskiem narz\u0119dziowym v3.MainWindow.menu.view.asSimpleList=Prosta lista v3.MainWindow.menu.view.asAdvancedList=Zaawansowana lista v3.MainWindow.menu.view.statusbar=Pasek statusu Subscription.menu.dirtyall=Zaznacz wszystkie jako nieprzeczytane configureWizard.file.message3=Vuze pobierze pliki do wybranego katalogu, mo\u017cesz wybra\u0107 go tutaj: v3.deleteContent.applyToAll=Zastosuj akcje do wszystkich %1 wybranych ConfigView.label.seeding.firstPriority.ignoreIdleHours=Torrenty, kt\u00f3re nie wysy\u0142aj\u0105 niczego dla v3.MainWindow.menu.contentnetworks=Sieci &HD v3.MainWindow.menu.contentnetworks.about=O sieciach HD Peers.column.as.info=Szczeg\u00f3\u0142y AS (systemu anonimowego) peera ConfigView.label.autoopen.downloadbars=Automatycznie otw\u00f3rz Pasek pobierania je\u015bli ConfigView.label.autoopen=Auto-otwarcie ConfigView.label.autoopen.detailstab=Automatycznie otw\u00f3rz kart\u0119 Szczeg\u00f3\u0142y je\u015bli ConfigView.label.systray=Pasek systemowy ConfigView.label.systray._mac=Ikona paska statusu ConfigView.section.interface.legacy=Zapis v3.MainWindow.menu.contentnetworks.manage=&Zarz\u0105dzaj sieciami HD azbuddy.ui.menu.cat=Kategorie azbuddy.ui.menu.cat.share=W\u0142\u0105cz subskrypcje ze znajomym(i) azbuddy.ui.menu.cat.set_msg=Lista kategorii oddzielona przecinkami lub 'Wszyscy' azbuddy.ui.menu.cat_subs=Subskrybuj subs.prop.update_period=Cykl aktualizacji azbuddy.enable_cat_pub=Publiczne kategorie, kt\u00f3re WSZYSCY Twoi znajomi mog\u0105 subskrybowa\u0107 (',' separated) v3.dialog.cnclose.title=%1 zamkni\u0119tych v3.dialog.cnclose.subtitle=Powiadomienie v3.dialog.cnclose.info1=Zamkn\u0105\u0142e\u015b sie\u0107 HD v3.dialog.cnclose.info2=Je\u015bli chcia\u0142by\u015b ponownie otworzy\u0107 sie\u0107 HD, mo\u017cesz to zrobi\u0107 w menu "Sieci HD" na g\u00f3rze ekranu. v3.dialog.cnclose.noshow=Nie pokazuj wi\u0119cej v3.dialog.cnmanage.title=Menu zarz\u0105dzania sieciami HD v3.dialog.cnmanage.intro=Mo\u017cesz wybra\u0107 z poni\u017cszej listy, zawarto\u015bci sieci kt\u00f3re chcesz wy\u015bwietli\u0107 w menu "Sieci HD" TableColumn.header.#.info=Pozycja/numer porz\u0105dkowy TableColumn.header.category.info=Nazwa kategorii, do kt\u00f3rej nale\u017cy torrent TableColumn.header.DateCompleted.info=Data, kiedy pobranie torrenta zosta\u0142a uko\u0144czona TableColumn.header.AzProduct.info=Zawarto\u015b\u0107 sieci, z kt\u00f3rej torrent zosta\u0142 zapocz\u0105tkowany TableColumn.header.health.info=Kondycja Twojego po\u0142\u0105czenia swarm torrent\u00f3w jest TableColumn.header.maxuploads.info=Maksimum # peer\u00f3w jednocze\u015bnie wysy\u0142aj\u0105cych do TableColumn.header.name.info=Nazwa torrentu TableColumn.header.unopened.info=Flaga dotycz\u0105ca, kiedy torrent by\u0142 odtwarzany (otworzony) TableColumn.header.savepath.info=Folder docelowy lub plik dla danych torrentowych TableColumn.header.SeedingRank.info=Warto\u015b\u0107 rankingu, w kt\u00f3rym wida\u0107 jak bardzo torrent potrzebuje seedowania. Wy\u017csza warto\u015b\u0107 oznacza wy\u017csz\u0105 potrzeb\u0119. TableColumn.header.shareRatio.info=Jak du\u017co wysy\u0142a\u0142e\u015b (udost\u0119pnia\u0142es) w por\u00f3wnaniu do pobierania. TableColumn.header.size.info=Rozmiar zawarto\u015bci torrent\u00f3w na dysku TableColumn.header.azsubs.ui.column.subs.info=Przycisk, kt\u00f3ry pozwala na subskrybowanie kana\u0142u zawieraj\u0105cego zwi\u0105zane torrenty TableColumn.header.upspeed.info=Obecna pr\u0119dko\u015b\u0107 wysy\u0142ania TableColumn.header.downspeed.info=Obecna pr\u0119dko\u015b\u0107 pobierania TableColumn.header.up.info=Obecna ilo\u015b\u0107 danych wys\u0142anych do innych u\u017cytkownik\u00f3w TableColumn.header.down.info=Obecna ilo\u015b\u0107 danych otrzymanych od innych u\u017cytkownik\u00f3w TableColumn.header.ProgressETA.info=Powi\u0105zany Status, uko\u0144czonych, szacunkowy czas i kolumny pr\u0119dko\u015bci pobierania w jednej kolumnie. TableColumn.header.eta.info=Szacowany czas w kt\u00f3rym torrent b\u0119dzie pobrany Pieces.column.#.info=Numer cz\u0119\u015bci Peers.column.%.info=Procent torrenta pobranego przez peera do tej pory TableColumn.header.download.info=Ilo\u015b\u0107 danych otrzymanych od peer\u00f3w TableColumn.header.upload.info=Ilo\u015bc danych wys\u0142anych do peer\u00f3w TableColumn.header.downloadspeed.info=Tempo, w kt\u00f3rym otrzymujemy od peer\u00f3w TableColumn.header.uploadspeed.info=Ocena wysy\u0142anych danych do peer\u00f3w TableColumn.header.lan.info=Flaga dotycz\u0105ca czy peer jest w Twojej sieci LAN TableColumn.header.downloadspeedoverall.info=Szacowane tempo pobierania od peer\u00f3w Peers.column.pieces.info=Graficzny pasek przedstawiaj\u0105cy, kt\u00f3re cz\u0119\u015bci peer pobra\u0142 TableColumn.header.TableColumnNameInfo=Nazwa i opis kolumny TableColumn.header.TableColumnSample=Przyk\u0142ad TableColumn.header.TableColumnInfo=Opis kolumny TableColumn.header.TableColumnChosenColumn=Wybrane kolumny subs.prop.is_auto_ok=Dozwolone automatyczne pobieranie label.learnmore=Dowiedz si\u0119 wi\u0119cej ColumnSetup.explain=Zobacz dost\u0119pne kolumny po lewej, dodaj je do listy widocznych kolumn po prawej. Rozwi\u0144 lub przejd\u017a na d\u00f3\u0142 listy dost\u0119pnych kolumn przez u\u017cycie sekcji Filtr na dole po lewej. Przeci\u0105gnij i Upu\u015b\u0107 oraz skr\u00f3ty klawiaturowe s\u0105 r\u00f3wnie\u017c wspierane. ColumnSetup.chosencolumns=Wybrane kolumny ColumnSetup.proficiency=Sprawno\u015b\u0107: ColumnSetup.categories=Kategorie: ColumnSetup.filters=Filtry ColumnSetup.availcolumns=Dost\u0119pnych %1 kolumn ColumnSetup.availcolumns.filteredby=Dost\u0119pnych %1 kolumn wybranych przez %2 devices.view.title=Urz\u0105dzenia device.mediaserver.view.title=Serwery medi\u00f3w device.router.view.title=Rutery device.model.desc=Opis modelu device.model.name=Nazwa modelu device.model.num=Numer modelu device.manu.desc=Producent device.router.is_mapping=Automatyczne mapowanie portu device.router.req_map=Wymagane mapowanie device.router.configure=Ustaw UPnP device.mediaserver.configure=Konfiguruj serwer Moje Media device.hide=Ukryj urz\u0105dzenie device.show=Poka\u017c ukryte urz\u0105dzenia device.search=Szukaj urz\u0105dze\u0144 device.router.con_type=Po\u0142\u0105czenie: %1 device.browse=Przegl\u0105daj device.upnp.desc_url=Opis urz\u0105dzenia device.upnp.present_url=Administrator urz\u0105dzenia ConfigView.label.maxStalledSeeding=Maksymalna ilo\u015b\u0107 'stalled' [0:nieograniczona] device.search.auto=Automatycznie szukaj urz\u0105dze\u0144 devices.sidebar.simple=Prosty widok devices.xcode.working_dir=Strefa transkodowania devices.xcode.prof_def=Domy\u015blny profil transkodowania devices.xcode.profs=Dost\u0119pne profile transkodowania device.lastseen=Ostatnio widziany devices.contextmenu.xcode=Transkodowanie dla urz\u0105dze\u0144 devices.device=Urz\u0105dzenie devices.profile=Profil General.percent=Procent devices.installed=Zainstalowane devices.comp.missing=Niezainstalowana obs\u0142uga Vuze devices.state=Stan MainWindow.menu.help.donate=&Dokonaj wp\u0142aty DonationWindow.noload.title=Datki DonationWindow.noload.text=Nieudane za\u0142adowanie okna z datkami. Spr\u00f3buj p\u00f3\u017aniej. devices.xcode.only.show=Poka\u017c tylko pliki transkodowane w urz\u0105dzeniu device.quit.transcoding.title=Transkodowanie w trakcie device.quit.transcoding.text='%1' jest obecnie transcoding dla '%2' i jest %3% uko\u0144czony.\nJe\u015bli zamkniesz teraz, b\u0119dzie musia\u0142 by\u0107 uruchomiony od pocz\u0105tku przy nast\u0119pnym uruchomieniu. download.removerules.unauthorised.data=\tUsu\u0144 dane device.config.xcode.maxbps=Maksymalne tempo transkodowania w KB/sek [0: nieograniczone] device.xcode=Transkodowanie device.xcode.always=Zawsze device.xcode.whenreq=Gdy wymagane device.xcode.never=Nigdy devices.copy.pending=Trwa kopiowanie pliku devices.sidebar.hide.rend.generic=Ukryj urz\u0105dzenia og\u00f3lne v3.devicesview.infobar.text2=Aby dostarczy\u0107 zawarto\u015b\u0107 transkodow\u0105 na urz\u0105dzenie, po prostu przeci\u0105gnij z biblioteki na urz\u0105dzenia na pasku bocznym. Kliknij urz\u0105dzenie po prawej, je\u015bli chcesz zobaczy\u0107 uko\u0144czone transkodowania. iconBar.transcode=Urz\u0105dzenie iconBar.transcode.tooltip=Udost\u0119pnij media dla urz\u0105dzenia device.retry.copy=Spr\u00f3buj ponownie skopiowa\u0107 devices.copy.fail=Nieudane kopiowanie do urz\u0105dzenia devices.on.demand=Na \u017c\u0105danie devices.ready=Gotowe TableColumn.header.trancode_qpos.info=Pozycja w kolejce transkodowania TableColumn.header.profile=Urz\u0105dzenie TableColumn.header.profile.info=U\u017cyty profil transkodowania TableColumn.header.copied=Skopiowano TableColumn.header.device=Urz\u0105dzenie TableColumn.header.device.info=Urz\u0105dzenie docelowe TableColumn.header.trancode_completion=Post\u0119p konwersji # This is the beginning of the word "View". It's right aligned under the icon bar item v3.iconBar.view.big=Wi v3.iconBar.view.big.tooltip=Widok prostej listy # This is the end of the word "View". It's left aligned under the icon bar item v3.iconBar.view.small=dok v3.iconBar.view.small.tooltip=Widok zaawansowanej listy general.dont.ask.again=Ne pytaj ponownie general.na.short=Niedost\u0119pne v3.menu.device.exploreTranscodes=Poka\u017c pliki v3.menu.device.exploreTranscodes._windows=Poka\u017c pliki w eksploratorze v3.menu.device.exploreTranscodes._mac=Poka\u017c pliki w wyszukiwarce v3.menu.device.defaultprofile=Domy\u015blny profil devices.button.installitunes=Zainstaluj integracj\u0119 iTunes device.itunes.install=Musisz zainstalowa\u0107 iTunes device.itunes.start=Musisz uruchomi\u0107 iTunes lub w\u0142\u0105czy\u0107 auto-start device.itunes.install_problem=Wyst\u0105pi\u0142 problem ze zintegrowaniem iTunes devices.downloading=Pobieranie TableColumn.header.duration=Czas TableColumn.header.resolution=Rozdzielczo\u015b\u0107 devices.xcode.autoStart=Automatycznie uruchom, je\u015bli potrzeba option.askeverytime=Pytaj za ka\u017cdym razem option.rememberthis=Zapami\u0119taj te ustawienie devices.associate=Powi\u0105zane z devices.associate.already=Ju\u017c powi\u0105zany devices.always.cache=Pami\u0119\u0107 podr\u0119czna plik\u00f3w nietranskodowanych devices.turnon.prepageload=Aby w\u0142\u0105czy\u0107 t\u0119 opcj\u0119, wymagana b\u0119dzie instalacja dodatkowych komponent\u00f3w. devices.turnon.itunes=W\u0142\u0105cz obs\u0142ug\u0119 iTunes (wymagane dla urz\u0105dze\u0144 Apple) devices.turnon.qos=Udost\u0119pnij anonimowo statystyki urz\u0105dzenia Vuze devices.turnon.title=W\u0142\u0105cz obs\u0142ug\u0119 urz\u0105dze\u0144 devices.choose.device.title=Wybierz urz\u0105dzenie do odtwarzania wideo: devices.choose.profile.info.text=Po wybraniu, Vuze wykryje czy format wideo b\u0119dzie odtworzony na wybranym urz\u0105dzeniu i utworzy kopi\u0119 urz\u0105dzenia kompatybilnego, je\u015bli b\u0119dzie potrzeba.\n\nWi\u0119cej szczeg\u00f3\u0142\u00f3w po najechaniu nad wybranym urz\u0105dzeniem. devices.choose.profile.info.title.selected=Szczeg\u00f3\u0142y %1: devices.view.heading=Konwertowanie medi\u00f3w do odtwarzania na urz\u0105dzeniu device.view.heading=Media dla %1 devices.choose.device.info.title=Podpowied\u017a urz\u0105dzenia devices.choose.device.info.text=Nast\u0119pnym razem, po prostu przeci\u0105gnij i upu\u015b\u0107 pliki do wybranego urz\u0105dzeniaw pasku bocznym. label.clickone=Kliknij raz Button.turnon=W\u0142\u0105cz ConfigView.label.dm.dblclick=Podw\u00f3jny klik w podgl\u0105dy torrent\u00f3w: ConfigView.option.dm.dblclick.play=Odtw\u00f3rz zawarto\u015b\u0107 ConfigView.option.dm.dblclick.details=Otw\u00f3rz podgl\u0105d szczeg\u00f3\u0142\u00f3w torrent\u00f3w ConfigView.option.dm.dblclick.show=Poka\u017c plik ConfigView.option.dm.dblclick.show._mac=Poka\u017c plik(i) w szukaczu ConfigView.option.dm.dblclick.show._windows=Poka\u017c plik(i) w explorerze subscriptions.column.auto-download=Automatyczne pobieranie xcode.deletedata.title=Usu\u0144 zawarto\u015b\u0107 transkodowan\u0105 xcode.deletedata.message=Czy jeste\u015b pewien, \u017ce chcesz nieodwracalnie usun\u0105\u0107 kopi\u0119 '%1' transkodowan\u0105 dla '%2'%3? xcode.deletedata.message.2=\n(kopia mo\u017ce ci\u0105gle istnie\u0107 w '%1') v3.deviceview.infobar.line1=Przeci\u0105gnij i upu\u015b\u0107 wideo z biblioteki na wybrane urz\u0105dzenie. v3.deviceview.infobar.line2=Odtw\u00f3rz wideo na kt\u00f3rym\u015b z ekran\u00f3w - iPhone, iPod, TV v3.deviceview.infobar.line1.generic=Przeci\u0105gnij i upu\u015b\u0107 wideo z biblioteki do %1 na pasku bocznym. v3.deviceview.infobar.line2.itunes=Wideo poka\u017ce si\u0119 w folderze iTunes Movies, gdy b\u0119d\u0105 dost\u0119pne do odtworzenia. v3.deviceview.infobar.line2.xbox=Wideo strumieniowe na Xbox 360 po wybraniu M\u00f3j Xbox->Bilbioteka Wideo -> Vuze. v3.deviceview.infobar.line2.ps3=Wideo strumieniowe na PS3 po wybraniu Wideo -> Vuze. devices.copy_url=Kopiuj stream URL do schowka devices.converting=Konwertowanie Button.reload=Prze\u0142aduj azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_sr.properties0000644000175000017500000161540511301156004025527 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=\u0422\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443... Main.parameter.usage=\u0423\u043f\u043e\u0442\u0440\u0435\u0431\u0430 : java org.gudy.azureus2.cl.Main [\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438] "\u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430.torrent" "\u0441\u0442\u0430\u0437\u0430 \u0437\u0430 \u0441\u043d\u0438\u043c\u0430\u045a\u0435" Main.parameter.maxUploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u0430\u043d \u0431\u0440\u043e\u0458 \u0438\u0441\u0442\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u0438\u0445 \u0441\u043b\u0430\u045a\u0430 Main.parameter.maxSpeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 \u0443 \u0431\u0430\u0458\u0442\u043e\u0432\u0438\u043c\u0430/s MainWindow.menu.file=&\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 MainWindow.menu.file.open=&\u041e\u0442\u0432\u043e\u0440\u0438 MainWindow.menu.file.create=&\u041d\u043e\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442... MainWindow.menu.file.create.fromfile=\u0418\u0437 &\u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 MainWindow.menu.file.create.fromdir=\u0418\u0437 \u0434\u0438&\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430 MainWindow.menu.file.export=&\u0418\u0437\u0432\u0435\u0437\u0438 XML \u0442\u043e\u0440\u0435\u043d\u0442... MainWindow.menu.file.import=&\u0423\u0432\u0435\u0437\u0438 XML \u0442\u043e\u0440\u0435\u043d\u0442... MainWindow.menu.file.closetab=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 &\u0458\u0435\u0437\u0438\u0447\u0430\u043a MainWindow.menu.file.closewindow=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 &\u043f\u0440\u043e\u0437\u043e\u0440 MainWindow.menu.file.exit=&\u0417\u0430\u0432\u0440\u0448\u0438 MainWindow.dialog.choose.file=\u0418\u0437\u0431\u043e\u0440 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 MainWindow.menu.file.folder=&\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c... MainWindow.dialog.choose.folder=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u043a\u043e\u0458\u0438 \u0441\u0430\u0434\u0440\u0436\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 MainWindow.menu.view=&\u041f\u0440\u0435\u0433\u043b\u0435\u0434 MainWindow.menu.view.show=\u041f\u0440\u0438\u043a\u0430\u0437 MainWindow.menu.view.mytorrents=&\u041c\u043e\u0458\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 MainWindow.menu.view.open_global_transfer_bar=\u0422\u0440\u0430\u043a\u0430 \u0441\u0430 \u043f\u0440\u0435\u043d\u043e\u0441\u0438\u043c\u0430 MainWindow.menu.view.configuration=&\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430... MainWindow.menu.view.console=\u041a&\u043e\u043d\u0437\u043e\u043b\u0430 MainWindow.menu.view.irc=&\u0418\u0440\u0446 MainWindow.menu.view.allpeers=\u0421\u0432\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438 MainWindow.menu.closealldetails=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 &\u0441\u0432\u0435 \u0434\u0435\u0442\u0430\u0459\u0435 MainWindow.menu.closealldownloadbars=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 \u0441\u0432\u0435 &\u0442\u0440\u0430\u043a\u0435 \u0441\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0438\u043c\u0430 MainWindow.menu.language=&\u0408\u0435\u0437\u0438\u043a ConfigView.section.language=\u0408\u0435\u0437\u0438\u043a MainWindow.menu.window=&\u041f\u0440\u043e\u0437\u043e\u0440 MainWindow.menu.window.minimize=&\u0423\u043c\u0430\u045a\u0438 MainWindow.menu.window.zoom=\u0423&\u0432\u0435\u045b\u0430j MainWindow.menu.window.alltofront=\u041f\u0440\u0435\u0431\u0430\u0446\u0438 \u0441\u0432\u0435 \u0443 &\u043f\u0440\u0432\u0438 \u043f\u043b\u0430\u043d MainWindow.menu.help=&\u041f\u043e\u043c\u043e\u045b MainWindow.menu.help.about=\u041e \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0443 MainWindow.menu.torrent=\u0422&\u043e\u0440\u0435\u043d\u0442 MainWindow.about.title=\u041e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443 MainWindow.about.section.developers=\u0420\u0430\u0437\u0432\u0438\u0458\u0430\u0447\u0438 MainWindow.about.section.translators=\u041f\u0440\u0435\u0432\u043e\u0434\u0438\u043e\u0446\u0438 MainWindow.about.section.system=\u0421\u0438\u0441\u0442\u0435\u043c MainWindow.about.section.internet=\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 MainWindow.about.internet.homepage=\u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432\u0430 \u0441\u0442\u0440\u0430\u043d\u0430 MainWindow.about.internet.sourceforge=\u0421\u0442\u0440\u0430\u043d\u0430 \u0421\u043e\u0440\u0441\u0444\u043e\u0440\u045f\u043e\u0432\u043e\u0433 \u043f\u0440\u043e\u0458\u0435\u043a\u0442\u0430 MainWindow.about.internet.sourceforgedownloads=\u041f\u0440\u0438\u0458\u0435\u043c \u0441\u0430 \u0421\u043e\u0440\u0441\u0444\u043e\u0440\u045f\u0430 MainWindow.about.internet.bugreports=\u041f\u0440\u0438\u0458\u0430\u0432\u0430 \u0433\u0440\u0435\u0448\u0430\u043a\u0430 MainWindow.about.internet.forumdiscussion=\u0424\u043e\u0440\u0443\u043c\u0438 MainWindow.about.internet.wiki=\u041f\u0438\u0442\u0430\u045a\u0430 \u043e \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0443 \u043d\u0430 \u0412\u0438\u043a\u0438\u0458\u0443 MainWindow.dialog.choose.savepath=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0442\u0430\u0437\u0443 \u0437\u0430 \u0447\u0443\u0432\u0430\u045a\u0435 MainWindow.dialog.choose.savepath_forallfiles=\u0418\u0437\u0431\u043e\u0440 \u0441\u0442\u0430\u0437\u0435 \u0437\u0430 \u0447\u0443\u0432\u0430\u045a\u0435 \u0437\u0430 \u0421\u0412\u0415 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 MainWindow.status.latestversion=\u041d\u0430\u0458\u0441\u0432\u0435\u0436\u0438\u0458\u0438 MainWindow.status.latestversion.clickupdate=\u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u0437\u0430 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0443 MainWindow.status.unknown=\u043d\u0435\u043f\u043e\u0437\u043d\u0430\u0442 MainWindow.status.checking=\u043f\u0440\u043e\u0432\u0435\u0440\u0430 MyTorrentsView.mytorrents=\u041c\u043e\u0458\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.name=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 TableColumn.header.size=\u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 TableColumn.header.done=\u0413\u043e\u0442\u043e\u0432\u043e TableColumn.header.done.info=\u041f\u0440\u043e\u0446\u0435\u043d\u0430\u0442 \u0438\u0441\u043f\u0443\u045a\u0435\u045a\u0430 \u0442\u0440\u0435\u043d\u0443\u0442\u043d\u043e\u0433 \u0437\u0430\u0434\u0430\u0442\u043a\u0430 TableColumn.header.status=\u0421\u0442\u0430\u0442\u0443\u0441 TableColumn.header.status.info=\u0428\u0442\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0442\u0440\u0435\u043d\u0443\u0442\u043d\u043e \u0440\u0430\u0434\u0438 TableColumn.header.seeds=\u0417\u0430\u043c\u0435\u0446\u0438 TableColumn.header.seeds.info=\u0431\u0440. \u043f\u043e\u0432\u0435\u0437\u0430\u043d\u0438\u0445 \u043a\u043b\u0438\u0446\u0430 (\u0443\u043a. \u0431\u0440\u043e\u0458 \u043a\u043b\u0438\u0446\u0430) TableColumn.header.peers=\u0420\u0430\u0447\u0443\u043d\u0430\u0440\u0438 TableColumn.header.peers.info=\u0431\u0440. \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u043d\u0430 \u0432\u0435\u0437\u0438 (\u0443\u043a. \u0431\u0440\u043e\u0458 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430) TableColumn.header.downspeed=\u041f\u0440\u0438\u0458\u0435\u043c TableColumn.header.upspeed=\u0421\u043b\u0430\u045a\u0435 TableColumn.header.eta=\u041f\u0412\u0414 TableColumn.header.tracker=\u0421\u0442\u0430\u0442\u0443\u0441 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 TableColumn.header.tracker.info=\u0421\u0442\u0430\u0442\u0443\u0441 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 TableColumn.header.trackernextaccess=\u0421\u043b\u0435\u0434\u0435\u045b\u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0443 TableColumn.header.trackernextaccess.info=\u0412\u0440\u0435\u043c\u0435 \u043a\u0430\u0434\u0430 \u0441\u0435 \u043f\u043e\u043d\u043e\u0432\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0443 TableColumn.header.priority=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 TableColumn.header.priority.info=\u041e\u0434\u0440\u0435\u0452\u0443\u0458\u0435 \u043a\u043e\u043b\u0438\u043a\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u043d\u0435 \u043c\u043e\u045b\u0438 \u0437\u0430 \u0441\u043b\u0430\u045a\u0435 \u0441\u0435 \u0434\u0430\u0458\u0435 \u043e\u0432\u043e\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0443 TableColumn.header.seeds.fullcopycalc=%2 \u043f\u043e\u0442\u043f\u0443\u043d\u0438\u0445 \u0443\u043c\u043d\u043e\u0436\u0430\u043a\u0430 \u0437\u0430 %1 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 MyTorrentsView.menu.showdetails=\u041f\u043e\u043a\u0430\u0436\u0438 &\u0434\u0435\u0442\u0430\u0459\u0435 MyTorrentsView.menu.showdownloadbar=\u041f\u043e\u043a\u0430\u0436\u0438 \u0442\u0440\u0430\u043a\u0443 \u0437\u0430 &\u043f\u0440\u0438\u0458\u0435\u043c MyTorrentsView.menu.open=&\u041e\u0442\u0432\u043e\u0440\u0438 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 MyTorrentsView.menu.setpriority=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 &\u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 MyTorrentsView.menu.setpriority.high=&\u0412\u0438\u0441\u043e\u043a MyTorrentsView.menu.setpriority.low=&\u041d\u0438\u0437\u0430\u043a MyTorrentsView.menu.start=&\u041a\u0440\u0435\u043d\u0438 MyTorrentsView.menu.stop=&\u0421\u0442\u0430\u043d\u0438 MyTorrentsView.menu.remove=&\u0423\u043a\u043b\u043e\u043d\u0438 MyTorrentsView.menu.changeTracker=&\u0414\u043e\u0434\u0430\u0458 \u0423\u0420\u041b \u0437\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 TrayWindow.menu.exit=&\u041a\u0440\u0430\u0458 TrayWindow.menu.show=&\u041f\u043e\u043a\u0430\u0436\u0438 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 SystemTray.menu.exit=&\u041a\u0440\u0430\u0458 SystemTray.menu.closealldownloadbars=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 &\u0441\u0432\u0435 \u0442\u0440\u0430\u043a\u0435 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c SystemTray.menu.open_global_transfer_bar=\u041f\u0440\u0438\u043a\u0430\u0437 \u0442\u0440\u0430\u043a\u0430 \u0441\u0430 \u043f\u0440\u0435\u043d\u043e\u0441\u0438\u043c\u0430 SystemTray.menu.show=&\u041f\u043e\u043a\u0430\u0436\u0438 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 PeersView.ip.info=IP \u0430\u0434\u0440\u0435\u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 PeersView.port=\u041f\u043e\u0440\u0442 PeersView.port.info=\u041f\u043e\u0440\u0442 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 PeersView.T=\u0422 PeersView.T.info=\u043b (\u043b\u043e\u043a\u0430\u043b): \u0432\u0438 \u0441\u0442\u0435 \u0443\u0441\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0432\u0435\u0437\u0443, \u0443 (\u0443\u0434\u0430\u0459\u0435\u043d): \u0443\u0434\u0430\u0459\u0435\u043d\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u0458\u0435 \u0443\u0441\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043e \u0432\u0435\u0437\u0443. PeersView.T.L.tooltip=\u0412\u0438 \u0441\u0442\u0435 \u0443\u0441\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0432\u0435\u0437\u0443 PeersView.T.R.tooltip=\u0423\u0434\u0430\u0459\u0435\u043d \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u0458\u0435 \u0443\u0441\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043e \u0432\u0435\u0437\u0443 PeersView.I1=\u0417 (\u0443\u0434\u0430\u0459\u0435\u043d\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u0458\u0435 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d) PeersView.I1.info=\u0414\u0430 \u043b\u0438 \u0432\u0430\u0441 \u0437\u0430\u043d\u0438\u043c\u0430 \u0448\u0442\u0430 \u0443\u0434\u0430\u0459\u0435\u043d\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u043f\u043e\u0441\u0435\u0434\u0443\u0458\u0435? PeersView.C1=\u041f (\u041f\u0440\u0438\u0433\u0443\u0448\u0435\u043d \u043e\u0434 \u0434\u0440\u0443\u0433\u043e\u0433 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430) PeersView.C1.info=\u0414\u0430 \u043b\u0438 \u0432\u0430\u0441 \u0443\u0434\u0430\u0459\u0435\u043d\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u0441\u043f\u0440\u0435\u0447\u0430\u0432\u0430 \u0434\u0430 \u043f\u0440\u0438\u043c\u0430\u0442\u0435 PeersView.pieces=\u0414\u0435\u043b\u043e\u0432\u0438 PeersView.downloadspeed=\u041f\u0440\u0438\u0458\u0435\u043c PeersView.download=\u041f\u0440\u0435\u0443\u0437. PeersView.I2=\u0417 (\u0443\u0434\u0430\u0459\u0435\u043d\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u0458\u0435 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d) PeersView.I2.info=\u0414\u0430 \u043b\u0438 \u0458\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d \u0437\u0430 \u0441\u0430\u0434\u0440\u0436\u0430\u0458 \u043a\u043e\u0433 \u043d\u0443\u0434\u0438\u0442\u0435? PeersView.C2=\u041f (\u041f\u0440\u0438\u0433\u0443\u0448\u0438\u0432\u0430\u045a\u0435 \u0443\u0434\u0430\u0459\u0435\u043d\u043e\u0433 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430) PeersView.C2.info=\u0414\u0430 \u043b\u0438 \u0441\u043f\u0440\u0435\u0447\u0430\u0432\u0430\u0442\u0435 \u0443\u0434\u0430\u0459\u0435\u043d\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u0434\u0430 \u043f\u0440\u0438\u043c\u0430 PeersView.uploadspeed=\u0421\u043b\u0430\u045a\u0435 PeersView.uploadspeed.info=\u0411\u0440\u0437\u0438\u043d\u0430 \u043a\u043e\u0458\u043e\u043c \u0448\u0430\u0459\u0435\u0442\u0435 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u0443\u0434\u0430\u0459\u0435\u043d\u043e\u043c \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0443 PeersView.upload=\u0421\u043b\u0430\u045a\u0435 PeersView.upload.info=\u0423\u043a\u0443\u043f\u043d\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 \u043a\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0443. PeersView.statup=\u0421\u0442\u0430\u0442. \u0431\u0440\u0437\u0438\u043d\u0430 PeersView.statup.info=\u041f\u0440\u043e\u0446\u0435\u043d\u0430 \u0431\u0440\u0437\u0438\u043d\u0435 \u0441\u043b\u0430\u045a\u0430 \u0443\u0434\u0430\u0459\u0435\u043d\u043e\u0433 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 PeersView.S.info=\u041e\u043f\u043e\u043c\u0435\u043d\u0430: \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u043c\u043e\u0436\u0435 \u0431\u0438\u0442\u0438 \u201e\u043e\u043f\u043e\u043c\u0435\u043d\u0443\u0442\u201c \u0440\u0443\u0447\u043d\u043e \u0438\u043b\u0438 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 (\u043d\u043f\u0440. \u0430\u043a\u043e \u043d\u0435 \u0448\u0430\u0459\u0435 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u0434\u043e\u0432\u043e\u0459\u043d\u043e \u0431\u0440\u0437\u043e) PeersView.downloadspeedoverall=\u0423\u043a\u0443\u043f\u043d\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 PeersView.optunchoke=\u041e\u043f\u0446. \u043e\u0434\u0433\u0443\u0448\u0438\u0432\u0430\u045a\u0435 PeersView.client=\u041a\u043b\u0438\u0458\u0435\u043d\u0442 PeersView.client.info=\u0412\u0440\u0441\u0442\u0430 \u0411\u0422 \u043a\u043b\u0438\u0458\u0435\u043d\u0442\u0430 \u043a\u043e\u0433 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 PeersView.menu.snubbed=&\u041e\u043f\u043e\u043c\u0435\u043d\u0443\u0442 PeersView.title.short=\u0420\u0430\u0447\u0443\u043d\u0430\u0440\u0438 PeersView.title.full=\u0420\u0430\u0447\u0443\u043d\u0430\u0440\u0438 AllPeersView.title.full=\u0421\u0432\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438 ConfigView.section.files=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0435 ConfigView.label.usefastresume=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0431\u0440\u0437\u0438 \u043e\u043f\u043e\u0440\u0430\u0432\u0430\u043a ConfigView.label.incrementalfile=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043e \u0441\u0442\u0432\u0430\u0440\u0430\u045a\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 [\u043d\u0435\u043e\u043f\u0445\u043e\u0434\u043d\u043e \u0437\u0430 FAT32 \u043f\u043e\u0434 \u041b\u0438\u043d\u0443\u043a\u0441\u043e\u043c] ConfigView.label.defaultsavepath=\u0421\u0430\u0447\u0443\u0432\u0430\u0458 \u0443 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0441 \u043f\u043e\u0434\u0430\u0446\u0438\u043c\u0430 ConfigView.button.browse=&\u041f\u0440\u0435\u0433\u043b\u0435\u0434... ConfigView.dialog.choosedefaultsavepath=\u041c\u043e\u043b\u0438\u043c \u0438\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0437\u0430 \u0447\u0443\u0432\u0430\u045a\u0435 ConfigView.section.server=\u0412\u0435\u0437\u0430 ConfigView.section.global=\u041e\u043f\u0448\u0442\u0435 ConfigView.label.disconnetseed=\u0420\u0430\u0441\u043a\u0438\u0434\u0430\u045a\u0435 \u0432\u0435\u0437\u0430 \u0441\u0430 \u043e\u0441\u0442\u0430\u043b\u0438\u043c \u043a\u043b\u0438\u0446\u0430\u043c\u0430 \u043a\u0430\u0434\u0430 \u0458\u0435 \u043e\u0432\u0430\u0458 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u043a\u043b\u0438\u0446\u0430 ConfigView.label.switchpriority=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043f\u0440\u0435\u0431\u0430\u0446\u0438\u0432\u0430\u045a\u0435 \u043d\u0430 \u043d\u0438\u0437\u0430\u043a \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043a\u0430\u0434\u0430 \u0458\u0435 \u043a\u043b\u0438\u0446\u0430 ConfigView.label.maxdownloads=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u0431\u0440\u043e\u0458 \u0438\u0441\u0442\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u0438\u0445 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e]\n - \u041d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u0443\u0434\u0435 \u0432\u0438\u0448\u0435 \u043e\u0434 \u043d\u0430\u0458\u0432\u0435\u045b\u0435\u0433 \u0431\u0440\u043e\u0458\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 ConfigView.label.maxdownloads.tooltip=\u0423\u0432\u0435\u043a \u0458\u0435 \u043c\u043e\u0433\u0443\u045b\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u0438\u043c\u0430\u0442\u0438 \u0431\u0440\u043e\u0458 \u043a\u043e\u0433 \u043e\u0432\u0434\u0435 \u0443\u043f\u0438\u0448\u0435\u0442\u0435, \u0441\u0430 \u0458\u0435\u0434\u043d\u0438\u043c \u0438\u0437\u0443\u0437\u0435\u0442\u043a\u043e\u043c.\n\u0417\u0430\u0432\u0440\u0448\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442 \u043a\u043e\u0458\u0438 \u0438\u043c\u0430 \u043f\u0440\u0432\u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043c\u043e\u0436\u0435 \u0434\u0430 \u043f\u0440\u0435\u0443\u0437\u043c\u0435 \u0430\u043a\u0442\u0438\u0432\u0430\u043d \u043f\u0440\u0438\u0458\u0435\u043c \u0443\u043a\u043e\u043b\u0438\u043a\u043e \u0458\u0435 \u0437\u0430\u0438\u0441\u0442\u0430 \u043d\u0435\u043e\u043f\u0445\u043e\u0434\u043d\u043e. ConfigView.label.maxactivetorrents=\u041d\u0430\u0458\u0432\u0438\u0448\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e]\n - \u041d\u043e\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441\u0435 \u043d\u0435\u045b\u0435 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u0442\u0438 \u0430\u043a\u043e \u043f\u0440\u0438\u043c\u0430\u0442\u0435 \u0438\u043b\u0438 \u0434\u0435\u043b\u0438\u0442\u0435 \u0432\u0438\u0448\u0435 ConfigView.label.priorityExtensions=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430\u043c\u0430 \u0441\u0430 \u0435\u043a\u0441\u0442\u0435\u043d\u0437\u0438\u0458\u0430\u043c\u0430\n - \u043d\u043f\u0440: .txt;.nfo;.jpg ConfigView.section.transfer=\u041f\u0440\u0435\u043d\u043e\u0441\u0438 ConfigView.label.maxuploads=\u041f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0438 \u043d\u0430\u0458\u0432\u0435\u045b\u0438 \u0431\u0440\u043e\u0458 \u043f\u0440\u043e\u0440\u0435\u0437\u0430 \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 ConfigView.label.maxuploadspeed=\u0433\u043b\u043e\u0431\u0430\u043b\u043d\u0430 \u043d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 \u0443 KB/s [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.label.saveresumeinterval=\u041e\u0441\u0432\u0435\u0436\u0430\u0432\u0430\u045a\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u043e \u043e\u0431\u043d\u043e\u0432\u0438 \u0441\u0432\u0430\u043a\u0438\u0445 ConfigView.unlimited=\u041d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 ConfigView.section.display=\u041f\u0440\u0438\u043a\u0430\u0437 ConfigView.label.opendetails=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043e\u0442\u0432\u043e\u0440\u0438 \u0458\u0435\u0437\u0438\u0447\u0430\u043a \u0441\u0430 \u0434\u0435\u0442\u0430\u0459\u0438\u043c\u0430 ConfigView.label.openbar=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043e\u0442\u0432\u043e\u0440\u0438 \u0442\u0440\u0430\u043a\u0443 \u0437\u0430 \u043f\u0440\u0435\u043d\u043e\u0441 ConfigView.label.use_old_speed_menus=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0441\u0442\u0430\u0440\u0435 \u0431\u0440\u0437\u0435 \u043c\u0435\u043d\u0438\u0458\u0435 [\u0442\u0440\u0430\u0436\u0438 \u043f\u043e\u043d\u043e\u0432\u043d\u043e \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435] ConfigView.label.closetotray=\u0417\u0430\u0442\u0432\u0430\u0440\u0430\u045a\u0435 \u0443\u043c\u0430\u045a\u0443\u0458\u0435 \u0443 \u043e\u0431\u0430\u0432\u0435\u0448\u0442\u0430\u0458\u043d\u0443 \u0437\u043e\u043d\u0443 ConfigView.label.minimizetotray=\u0423\u043c\u0430\u045a\u0438\u0432\u0430\u045a\u0435 \u0443\u043c\u0430\u045a\u0443\u0458\u0435 \u0443 \u043e\u0431\u0430\u0432\u0435\u0448\u0442\u0430\u0458\u043d\u0443 \u0437\u043e\u043d\u0443 ConfigView.section.general=\u041e\u043f\u0448\u0442\u0435 ConfigView.section.start=\u041f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 ConfigView.label.showsplash=\u041f\u043e\u043a\u0430\u0436\u0438 \u043d\u0430\u0441\u043b\u043e\u0432\u043d\u0438 \u0435\u043a\u0440\u0430\u043d ConfigView.label.autoupdate=\u041e\u0442\u0432\u043e\u0440\u0438 \u043f\u0440\u043e\u0437\u043e\u0440 \u0437\u0430 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0443 \u043a\u0430\u0434\u0430 \u043d\u043e\u0432\u043e \u0438\u0437\u0434\u0430\u045a\u0435 \u043f\u043e\u0441\u0442\u0430\u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e ConfigView.label.openconsole=\u041e\u0442\u0432\u043e\u0440\u0438 \u043a\u043e\u043d\u0437\u043e\u043b\u0443 \u043f\u0440\u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0443 ConfigView.label.openconfig=\u041e\u0442\u0432\u043e\u0440\u0438 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0443 ConfigView.label.startminimized=\u0423\u043c\u0430\u045a\u0438 \u043f\u0440\u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0443 ConfigView.section.irc=\u0418\u0420\u0426 ConfigView.label.ircwiki=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u0435 http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=\u0421\u0435\u0440\u0432\u0435\u0440 ConfigView.label.ircchannel=\u041a\u0430\u043d\u0430\u043b ConfigView.label.irclogin=\u041d\u0430\u0434\u0438\u043c\u0430\u043a ConfigView.group.irctitle=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0418\u0420\u0426\u0430 ConfigView.boolean.ircsendinfo=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 (\u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e) \u0441\u043b\u0430\u045a\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0438\u043c\u0430\n\u043a\u0430\u043a\u043e \u0431\u0438 \u0432\u0430\u043c \u043b\u0430\u043a\u0448\u0435 \u043f\u043e\u043c\u043e\u0433\u043b\u0438 ConfigView.boolean.irclog=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u0431\u0435\u043b\u0435\u0436\u0435\u045a\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0443 (\u0443 IRC_log.htm) ConfigView.section.security=\u0411\u0435\u0437\u0431\u0435\u0434\u043d\u043e\u0441\u0442 ConfigView.label.password=\u0417\u0430\u0448\u0442\u0438\u0442\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 \u043b\u043e\u0437\u0438\u043d\u043a\u043e\u043c\n- \u0422\u0440\u0430\u0436\u0438 \u0441\u0435 \u043f\u0440\u0438\u043b\u0438\u043a\u043e\u043c \u0443\u0432\u0435\u043b\u0438\u0447\u0430\u0432\u0430\u045a\u0430 \u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0430. ConfigView.label.passwordconfirm=\u041b\u043e\u0437\u0438\u043d\u043a\u0430 (\u043f\u043e\u0442\u0432\u0440\u0434\u0430) ConfigView.label.passwordmatch=\u041b\u043e\u0437\u0438\u043d\u043a\u0430 \u0458\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u0430 : ConfigView.label.passwordmatchnone=\u041d\u0435 ConfigView.label.passwordmatchno=\u041d\u0435 / \u041b\u043e\u0437\u0438\u043d\u043a\u0435 \u0441\u0435 \u043d\u0435 \u043f\u043e\u043a\u043b\u0430\u043f\u0430\u0458\u0443 ConfigView.label.passwordmatchyes=\u0414\u0430 ConfigView.button.save=\u0421\u0430\u0447\u0443\u0432\u0430\u0458 ConfigView.title.short=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 ConfigView.title.full=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 ConsoleView.title.short=\u041a\u043e\u043d\u0437\u043e\u043b\u0430 ConsoleView.title.full=\u041a\u043e\u043d\u0437\u043e\u043b\u0430 FileItem.write=\u0443\u043f\u0438\u0441 FileItem.read=\u0447\u0438\u0442\u0430\u045a\u0435 FileItem.normal=\u043d\u043e\u0440\u043c\u0430\u043b\u0430\u043d FileItem.high=\u0432\u0438\u0441\u043e\u043a FileItem.donotdownload=\u041d\u0435 \u043f\u0440\u0438\u043c\u0430\u0458 FilesView.name=\u0418\u043c\u0435 FilesView.size=\u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 FilesView.done=\u0413\u043e\u0442\u043e\u0432\u043e FilesView.firstpiece=\u041f\u0440\u0432\u0438 \u0434\u0435\u043e FilesView.numberofpieces=\u0431\u0440. \u0434\u0435\u043b\u043e\u0432\u0430 FilesView.pieces=\u0414\u0435\u043b\u043e\u0432\u0438 FilesView.mode=\u041d\u0430\u0447\u0438\u043d \u0440\u0430\u0434\u0430 FilesView.priority=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 FilesView.menu.open=&\u041e\u0442\u0432\u043e\u0440\u0438 FilesView.menu.setpriority=&\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 FilesView.menu.setpriority.high=&\u0412\u0438\u0441\u043e\u043a FilesView.menu.setpriority.normal=&\u041e\u0431\u0438\u0447\u0430\u043d FilesView.menu.setpriority.skipped=&\u041d\u0435 \u043f\u0440\u0438\u043c\u0430\u0458 FilesView.title.short=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0435 FilesView.title.full=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0435 GeneralView.section.downloaded=\u041f\u0440\u0435\u0443\u0437\u0435\u0442\u043e GeneralView.label.status.file=\u0421\u0442\u0430\u0442\u0443\u0441 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 GeneralView.label.status.pieces=\u0421\u0442\u0430\u0442\u0443\u0441 \u0434\u0435\u043b\u043e\u0432\u0430 GeneralView.section.availability=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442 GeneralView.label.status.pieces_available=\u0421\u0442\u0430\u0442\u0443\u0441 \u0434\u0435\u043b\u043e\u0432\u0430 GeneralView.section.transfer=\u041f\u0440\u0435\u043d\u043e\u0441\u0438 GeneralView.section.info=\u041f\u043e\u0434\u0430\u0446\u0438 GeneralView.title.short=\u041e\u043f\u0448\u0442\u0435 GeneralView.title.full=\u041e\u043f\u0448\u0442\u0435 GeneralView.label.timeelapsed=\u041f\u0440\u043e\u0442\u0435\u043a\u043b\u043e \u0432\u0440\u0435\u043c\u0435 : GeneralView.label.remaining=\u041f\u0440\u0435\u043e\u0441\u0442\u0430\u043b\u043e : GeneralView.label.downloaded=\u041f\u0440\u0435\u0443\u0437\u0435\u0442\u043e : GeneralView.label.downloadspeed=\u0411\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 : GeneralView.label.maxuploads=\u0421\u043b\u043e\u0442\u043e\u0432\u0438 \u0437\u0430 \u0441\u043b\u0430\u045a\u0435 : GeneralView.label.maxuploads.tooltip=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u0431\u0440\u043e\u0458 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u043a\u043e\u0458\u0438 \u043d\u0438\u0441\u0443 \u043f\u0440\u0438\u0433\u0443\u0448\u0435\u043d\u0438 \u0443 \u0434\u0430\u0442\u043e\u043c \u0442\u0440\u0435\u043d\u0443\u0442\u043a\u0443. GeneralView.label.uploaded=\u041f\u0440\u0435\u0434\u0430\u0442\u043e : GeneralView.label.uploadspeed=\u0411\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 : GeneralView.label.seeds=\u0417\u0430\u043c\u0435\u0446\u0438 : GeneralView.label.peers=\u0420\u0430\u0447\u0443\u043d\u0430\u0440\u0438 : GeneralView.label.totalspeed=\u0411\u0440\u0437\u0438\u043d\u0430 \u0440\u043e\u0458\u0430 : GeneralView.label.totalspeed.tooltip=\u0423\u043a\u0443\u043f\u043d\u0430 (\u0438 \u0441\u0440\u0435\u0434\u045a\u0430) \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u0432\u0438\u0445 \u043f\u0440\u0438\u043a\u0459\u0443\u0447\u0435\u043d\u0438\u0445 \u043a\u043b\u0438\u0458\u0435\u043d\u0430\u0442\u0430. GeneralView.label.averagespeed=\u0441\u0440\u0435\u0434\u045a\u0430 GeneralView.label.filename=\u0418\u043c\u0435 : GeneralView.label.totalsize=\u0423\u043a. \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430: GeneralView.label.savein=\u0427\u0443\u0432\u0430\u045a\u0435 \u0443 : GeneralView.label.hash=\u0425\u0435\u0448 : GeneralView.label.numberofpieces=\u0411\u0440. \u0434\u0435\u043b\u043e\u0432\u0430 GeneralView.label.size=\u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 : GeneralView.label.tracker=\u0421\u0442\u0430\u045a\u0435 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 : GeneralView.label.updatein=\u041e\u0441\u0432\u0435\u0436\u0430\u0432\u0430\u045a\u0435 \u0437\u0430: GeneralView.label.trackerurl=\u0423\u0420\u041b \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430: GeneralView.label.trackerurlupdate=\u041e\u0441\u0432\u0435\u0436\u0438 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 GeneralView.label.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 : GeneralView.label.user_comment=\u041a\u043e\u0440\u0438\u0441\u043d\u0438\u043a\u043e\u0432 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 : GeneralView.label.status=\u0421\u0442\u0430\u0442\u0443\u0441 : ManagerItem.waiting=\u0427\u0435\u043a\u0430\u045a\u0435 ManagerItem.allocating=\u0421\u043c\u0435\u0448\u0442\u0430\u045a\u0435 ManagerItem.checking=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 ManagerItem.ready=\u0427\u0435\u043a\u0430\u045a\u0435 \u0434\u0430 \u0441\u0435 \u0434\u0440\u0443\u0433\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0443\u0431\u0430\u0446\u0435 \u0443 \u0440\u0435\u0434 ManagerItem.downloading=\u041f\u0440\u0438\u0458\u0435\u043c ManagerItem.seeding=\u0417\u0430\u043c\u0435\u0442\u0430\u045a\u0435 ManagerItem.stopped=\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0459\u0435\u043d ManagerItem.error=\u0413\u0440\u0435\u0448\u043a\u0430 ManagerItem.high=\u0432\u0438\u0441\u043e\u043a ManagerItem.low=\u043d\u0438\u0437\u0430\u043a MinimizedWindow.name=\u0418\u043c\u0435: MinimizedWindow.all_transfers=\u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432\u0438 \u043f\u0440\u0435\u043d\u043e\u0441\u0438 PiecesView.#=\u0431\u0440. PiecesView.size=\u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 PiecesView.numberofblocks=\u0431\u0440. \u0431\u043b\u043e\u043a\u043e\u0432\u0430 PiecesView.blocks=\u0411\u043b\u043e\u043a\u043e\u0432\u0438 PiecesView.completed=\u041f\u0440\u0435\u0443\u0437\u0435\u0442\u043e PiecesView.availability=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442 PiecesView.reservedby=\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0441\u0430\u043d\u043e PiecesView.writers=\u041f\u0440\u0438\u043b\u043e\u0436\u043d\u0438\u0446\u0438 \u0437\u0430 \u0431\u043b\u043e\u043a PiecesView.title.short=\u0414\u0435\u043b\u043e\u0432\u0438 PiecesView.title.full=\u0414\u0435\u043b\u043e\u0432\u0438 SystemTray.tooltip.seeding=\u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0430: %1, SystemTray.tooltip.downloading=\u043f\u0440\u0438\u0458\u0435\u043c\u0430: %1, DownloadManager.error.filenotfound=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043d\u0438\u0458\u0435 \u043d\u0430\u0452\u0435\u043d\u0430 DownloadManager.error.fileempty=\u0422\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0458\u0435 \u043f\u0440\u0430\u0437\u043d\u0430 DownloadManager.error.filetoobig=\u0422\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0458\u0435 \u043f\u0440\u0435\u0432\u0435\u043b\u0438\u043a\u0430 DownloadManager.error.filewithouttorrentinfo=\u0423 \u0434\u0430\u0442\u043e\u0442\u0435\u0446\u0438 \u043d\u0435\u043c\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 DownloadManager.error.unsupportedencoding=\u041a\u043e\u0434\u0438\u0440\u0430\u045a\u0435 \u043d\u0438\u0458\u0435 \u043f\u043e\u0434\u0440\u0436\u0430\u043d\u043e DownloadManager.error.ioerror=\u0423/\u0418 \u0433\u0440\u0435\u0448\u043a\u0430 DownloadManager.error.sha1=\u0413\u0440\u0435\u0448\u043a\u0430: \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0458\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u0430\u043c (SHA1) PeerManager.status.offline=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u0432\u0435\u0437\u0438\u0432\u0430\u045a\u0443 PeerManager.status.ok=\u0423 \u0440\u0435\u0434\u0443 PeerManager.status.checking=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 PeerManager.status.finished=\u0417\u0430\u0432\u0440\u0448\u0435\u043d\u043e PeerManager.status.finishedin=\u0417\u0430\u0432\u0440\u0448\u0430\u0432\u0430 \u0437\u0430 MainWindow.upgrade.assistant=\u0414\u043e\u0433\u0440\u0430\u0434\u0438 \u0441\u0430\u0440\u0430\u0434\u043d\u0438\u043a\u0430 MainWindow.upgrade.newerversion=\u041f\u043e\u0441\u0442\u043e\u0458\u0438 \u043d\u043e\u0432\u043e \u0438\u0437\u0434\u0430\u045a\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 \u0441\u043f\u0440\u0435\u043c\u043d\u043e \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c MainWindow.upgrade.explanation=\u041e\u0432\u0430\u0458 \u0441\u0430\u0440\u0430\u0434\u043d\u0438\u043a \u045b\u0435 \u043f\u0440\u0435\u0443\u0437\u0435\u0442\u0438 \u043d\u043e\u0432\u043e \u0438\u0437\u0434\u0430\u045a\u0435 \u0443 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0438 \u043f\u043e\u043d\u043e\u0432\u043e \u043f\u043e\u043a\u0440\u0435\u043d\u0443\u0442\u0438 \u0410\u0437\u0443\u0440\u0435\u0443\u0441 MainWindow.upgrade.explanation.manual=\u0414\u043e\u0433\u0440\u0430\u0434\u045a\u0443 \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043a\u0440\u0435\u043d\u0443\u0442\u0438 \u0440\u0443\u0447\u043d\u043e \u0442\u0430\u043a\u043e \u0448\u0442\u043e \u0443\u0433\u0430\u0441\u0438\u0442\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441, \u043f\u0440\u0435\u0443\u0437\u043c\u0435\u0442\u0435 \u043d\u043e\u0432\u043e \u0438\u0437\u0434\u0430\u045a\u0435 \u0438 \u043f\u043e\u043a\u0440\u0435\u043d\u0435\u0442\u0435 \u0433\u0430 \u043f\u043e\u043d\u043e\u0432\u043e MainWindow.upgrade.step1=\u041a\u043e\u0440\u0430\u043a 1: \u041f\u0440\u0438\u0458\u0435\u043c \u043d\u043e\u0432\u043e\u0433 \u0438\u0437\u0434\u0430\u045a\u0430 MainWindow.upgrade.step2=\u041a\u043e\u0440\u0430\u043a 2: \u0417\u0430\u0442\u0432\u0430\u0440\u0430\u045a\u0435 \u043e\u0432\u043e\u0433 \u0438\u0437\u0434\u0430\u045a\u0430 \u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u043d\u043e\u0432\u043e\u0433 \u0438\u0437\u0434\u0430\u045a\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 MainWindow.upgrade.hint1=\u0421\u0430\u0432\u0435\u0442: \u041f\u0440\u0438\u0442\u0438\u0441\u0430\u043a \u043d\u0430 \u201e\u0417\u0430\u0432\u0440\u0448\u0438\u201c \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043e\u0434\u0440\u0430\u0452\u0443\u0458\u0435 \u0441\u0432\u0435 MainWindow.upgrade.hint2=\u0421\u0430\u0432\u0435\u0442: \u0410\u043a\u043e \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u043a\u0430\u0441\u043d\u0438\u0458\u0435 \u0437\u0430\u0442\u0432\u043e\u0440\u0438\u0442\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441, \u043f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u201e\u041e\u0442\u043a\u0430\u0436\u0438\u201c \u0438\n \u043f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0458\u0442\u0435 Azureus2-new.jar \u0443 Azureus2.jar \u043f\u043e \u0437\u0430\u0442\u0432\u0430\u0440\u0430\u045a\u0443 MainWindow.upgrade.error.downloading.hint=\u0413\u0440\u0435\u0448\u043a\u0430: \u041d\u0438\u0458\u0435 \u043c\u043e\u0433\u0443\u045b\u0435 \u043f\u0440\u0435\u0443\u0437\u0435\u0442\u0438 \u043d\u043e\u0432\u043e \u0438\u0437\u0434\u0430\u045a\u0435, \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0434\u043e\u0433\u0440\u0430\u0434\u0438\u0442\u0435 \u0440\u0443\u0447\u043d\u043e MainWindow.upgrade.section.info=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0458\u0435 \u043d\u043e\u0432\u043e \u0438\u0437\u0434\u0430\u045a\u0435 MainWindow.upgrade.section.manual=\u0420\u0443\u0447\u043d\u0430 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0430 MainWindow.upgrade.section.automatic=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0430 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0430 MainWindow.upgrade.tooltip.progressbar=\u0422\u043e\u043a \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0435 \u0458\u0435 \u043f\u0440\u0438\u043a\u0430\u0437\u0430\u043d \u043e\u0432\u0434\u0435 Button.next=\u0421\u043b\u0435\u0434\u0435\u045b\u0438 Button.finish=\u0417\u0430\u0432\u0440\u0448\u0438 Button.cancel=\u041e\u0442\u043a\u0430&\u0436\u0438 LocaleUtil.title=\u0418\u0437\u0431\u043e\u0440 \u043a\u043e\u0434\u0438\u0440\u0430\u045a\u0430 LocaleUtil.section.chooseencoding=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u043e\u0434\u0438\u0440\u0430\u045a\u0435 \u0437\u0430 \u0438\u043c\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 LocaleUtil.label.chooseencoding=\u041c\u043e\u043b\u0438\u043c\u043e \u0438\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u043d\u0430\u0458\u043f\u043e\u0434\u0435\u0441\u043d\u0438\u0458\u0435 \u043a\u043e\u0434\u0438\u0440\u0430\u045a\u0435 LocaleUtil.label.hint.doubleclick=\u0421\u0430\u0432\u0435\u0442: \u0434\u0432\u043e\u0441\u0442\u0440\u0443\u043a\u0438 \u043f\u0440\u0438\u0442\u0438\u0441\u0430\u043a \u043d\u0430 \u0440\u0435\u0434 \u0431\u0438\u0440\u0430 \u043a\u043e\u0434\u0438\u0440\u0430\u045a\u0435 \u0438 \u0437\u0430\u0442\u0432\u0430\u0440\u0430 \u043f\u0440\u043e\u0437\u043e\u0440\u0447\u0438\u045b LocaleUtil.label.checkbox.rememberdecision=\u0417\u0430\u043f\u0430\u043c\u0442\u0438 \u043e\u0434\u043b\u0443\u043a\u0443 \u0437\u0430 \u043f\u0440\u0435\u043e\u0441\u0442\u0430\u043b\u0430 \u0438\u043c\u0435\u043d\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 LocaleUtil.column.encoding=\u041a\u043e\u0434\u0438\u0440\u0430\u045a\u0435 IrcClient.copyright=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0441\u0435 PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=\u041f\u043e\u0432\u0435\u0437\u0438\u0432\u0430\u045a\u0435 \u0441\u0430 IrcClient.connected=\u041f\u043e\u0432\u0435\u0437\u0430\u043d \u0441\u0430 IrcClient.joining=\u041f\u0440\u0438\u0434\u0440\u0443\u0436\u0438\u0432\u0430\u045a\u0435 IrcClient.channel=\u041a\u0430\u043d\u0430\u043b IrcClient.joined=\u043f\u0440\u0438\u0434\u0440\u0443\u0436\u0435\u043d IrcClient.error=\u0413\u0440\u0435\u0448\u043a\u0430 IrcClient.hasjoined=\u0441\u0435 \u043f\u0440\u0438\u0434\u0440\u0443\u0436\u0438\u043e IrcClient.haskicked=\u0458\u0435 \u0438\u0437\u0431\u0430\u0446\u0438\u043e IrcClient.hasleft=\u0458\u0435 \u043d\u0430\u043f\u0443\u0441\u0442\u0438\u043e IrcClient.nowknown=\u043e\u0434 \u0441\u0430\u0434\u0430 \u0438\u043c\u0430 \u0438\u043c\u0435 IrcClient.topicforchannel=\u0422\u0435\u043c\u0430 \u0437\u0430 \u043a\u0430\u043d\u0430\u043b IrcClient.disconnected=\u0418\u0441\u043a\u0459\u0443\u0447\u0435\u043d \u0441\u0430 IrcClient.noNick=\u041a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e \u0438\u043c\u0435 \u043d\u0438\u0458\u0435 \u0443\u043f\u0438\u0441\u0430\u043d\u043e. \u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0433\u0430 \u0434\u043e\u0434\u0430\u0442\u0435 \u0443 \u043f\u043e\u0433\u043b\u0435\u0434\u0443 \u201e\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430\u201c IrcView.actionnotsupported=\u041e\u0432\u043e \u0434\u0435\u0458\u0441\u0442\u0432\u043e \u043d\u0438\u0458\u0435 \u043f\u043e\u0434\u0440\u0436\u0430\u043d\u043e IrcView.clientsconnected=\u043a\u043e\u0440\u0438\u0441\u043d\u0438\u043a\u0430 IrcView.privateto=\u0417\u0430 IrcView.privatefrom=\u041e\u0434 IrcView.noticefrom=\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435 : IrcView.errormsg=\u041f\u043e\u0433\u0440\u0435\u0448\u043d\u0430 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0430 \u0437\u0430 /msg : /msg \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u043a \u0442\u0435\u043a\u0441\u0442 IrcView.help=\u0412\u0430\u0436\u0435\u045b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0441\u0443 :\n . /help : \u043f\u0440\u0438\u043a\u0430\u0437\u0443\u0458\u0435 \u043e\u0432\u0443 \u043f\u043e\u0440\u0443\u043a\u0443\n . /nick | /name : \u043c\u0435\u045a\u0430 \u0438\u043c\u0435\n . /me action : \u0448\u0430\u0459\u0435 \u0434\u0435\u0458\u0441\u0442\u0432\u043e\n . /msg \u0438\u043c\u0435 \u043f\u043e\u0440\u0443\u043a\u0430 : \u0441\u043b\u0430\u045a\u0435 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u0435 \u043f\u043e\u0440\u0443\u043a\u0435 \u0437\u0430 <\u0438\u043c\u0435>\n . /r \u043f\u043e\u0440\u0443\u043a\u0430 : \u043e\u0434\u0433\u043e\u0432\u043e\u0440 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u045a\u0443 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u0443 \u043f\u043e\u0440\u0443\u043a\u0443\n . /join #\u043a\u0430\u043d\u0430\u043b\u0411 (\u043d\u0435\u043c\u043e\u0458\u0442\u0435 \u043f\u0440\u0438\u0442\u0438\u0441\u043a\u0430\u0442\u0438 \u043e\u0432\u0434\u0435 \u0458\u0435\u0440 \u0442\u043e \u0458\u0435 \u0441\u0430\u043c\u043e \u043f\u0440\u0438\u043c\u0435\u0440): \u043c\u0435\u045a\u0430 \u0442\u0440\u0435\u043d\u0443\u0442\u043d\u0438 \u043a\u0430\u043d\u0430\u043b \u043d\u0430 \u201e\u043a\u0430\u043d\u0430\u043b\u0411\u201c\n . /whois \u0438\u043c\u0435 : \u0434\u043e\u0431\u0430\u0432\u0438 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u043e <\u0438\u043c\u0435\u043d\u0443> PasswordWindow.title=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u0458\u0435 \u0437\u0430\u043a\u0459\u0443\u0447\u0430\u043d PasswordWindow.passwordprotected=\u0414\u0430 \u0431\u0438 \u0431\u0438\u043e \u043f\u0440\u0438\u043a\u0430\u0437\u0430\u043d \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432 \u043f\u0440\u043e\u0437\u043e\u0440, \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0443\u043d\u0435\u0441\u0435\u0442 \u043e\u0432\u0434\u0435 \u0412\u0430\u0448\u0443 \u043b\u043e\u0437\u0438\u043d\u043a\u0443 : Button.ok=&\u0423 \u0440\u0435\u0434\u0443 TrackerChangerWindow.title=\u0414\u043e\u0434\u0430\u0458 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 TrackerChangerWindow.newtracker=\u0414\u043e\u0434\u0430\u0458 \u043d\u043e\u0432 \u0423\u0420\u041b \u0437\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 PeersView.discarded=\u041e\u0434\u0431\u0430\u0447\u0435\u043d\u043e PeersView.discarded.info=\u041f\u043e\u0434\u0430\u0446\u0438 \u043a\u043e\u0458\u0435 \u0441\u0442\u0435 \u043d\u0435\u043a\u0430\u043a\u043e \u043f\u0440\u0438\u043c\u0438\u043b\u0438 \u0438\u0430\u043a\u043e \u0412\u0430\u043c \u043d\u0438\u0441\u0443 \u0431\u0438\u043b\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u0438, \u043f\u0430 \u0441\u0442\u0435 \u0438\u0445 \u0441\u0435 \u043e\u0442\u0430\u0440\u0430\u0441\u0438\u043b\u0438. discarded=\u043e\u0434\u0431\u0430\u0447\u0435\u043d\u043e MyTorrentsView.#=\u0431\u0440. MyTorrentsView.menu.move=&\u041f\u043e\u043c\u0435\u0440\u0438 MyTorrentsView.menu.moveUp=&\u0413\u043e\u0440\u0435 MyTorrentsView.menu.moveDown=&\u0414\u043e\u043b\u0435 GeneralView.label.hashfails=\u0413\u0440\u0435\u0448\u043a\u0435 \u0445\u0435\u0448\u0430 : GeneralView.label.shareRatio=\u041e\u0434\u043d\u043e\u0441 \u0434\u0435\u0459\u0435\u045a\u0430 : ConfigView.section.downloadManagement=\u0423\u043f\u0440\u0430\u0432\u0459\u0430\u045a\u0435 \u043f\u0440\u0435\u043d\u043e\u0441\u043e\u043c ConfigView.label.startRatioPeers=\u041f\u043e\u0447\u043d\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 \u0430\u043a\u043e \u043f\u043e\u0441\u0442\u043e\u0458\u0438 \u043c\u0430\u045a\u0435 \u043e\u0434 1 \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u0437\u0430 ConfigView.text.neverStop=\u041d\u0438\u043a\u0430\u0434\u0430 \u043d\u0435 \u0441\u0442\u0430\u0458 ConfigView.text.neverStart=\u041d\u0438\u043a\u0430\u0434\u0430 \u043d\u0435 \u043f\u043e\u0447\u0438\u045a\u0438 ConfigView.text.peers=\u0420\u0430\u0447\u0443\u043d\u0430\u0440\u0438 ConfigView.label.checkOncompletion=\u041f\u0440\u043e\u0432\u0435\u0440\u0438 \u0434\u0435\u043b\u043e\u0432\u0435 \u043a\u0430\u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u043d\u043e\u0441 \u0437\u0430\u0432\u0440\u0448\u0438 wizard.title=\u041d\u0430\u043f\u0440\u0430\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 wizard.previous=<\u041d\u0430\u0437\u0430\u0434 wizard.next=\u0414\u0430\u0459\u0435 > wizard.finish=\u0417\u0430\u0432\u0440\u0448\u0438 wizard.mode=\u041f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 / \u041d\u0430\u0447\u0438\u043d wizard.tracker=\u041f\u0440\u0430\u0442\u0438\u043b\u0430\u0446: wizard.invalidurl=\u041e\u0432\u0430\u0458 \u0423\u0420\u041b \u043d\u0438\u0458\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u0430\u043d wizard.singlefile=\u0408\u0435\u0434\u043d\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 wizard.singlefile.help=\u041d\u0430\u043f\u0440\u0430\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u043e\u0434 \u0458\u0435\u0434\u043d\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 wizard.directory=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c wizard.directory.help=\u041d\u0430\u043f\u0440\u0430\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u043e\u0434 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430 wizard.choosefile=\u041d\u0430\u043f\u0440\u0430\u0432\u0438 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 wizard.file=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 : wizard.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434... wizard.choosedirectory=\u0418\u0437\u0431\u043e\u0440 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430 wizard.invalidfile=\u041d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430! wizard.invaliddirectory=\u041d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u0430\u043d \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c! wizard.torrentFile=\u0422\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 wizard.choosetorrent=\u041c\u043e\u043b\u0438\u043c\u043e \u0438\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u043a\u043e\u0458\u0443 \u0442\u0440\u0435\u0431\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442\u0438 wizard.information=\u041f\u043e\u0434\u0430\u0446\u0438 wizard.notimplemented=\u0408\u043e\u0448 \u043d\u0438\u0458\u0435 \u0443\u0433\u0440\u0430\u0452\u0435\u043d\u043e wizard.progresstitle=\u041f\u0440\u0430\u0432\u0459\u0435\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 wizard.savingfile=\u0427\u0443\u0432\u0430\u045a\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435... wizard.filesaved=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0458\u0435 \u0441\u0430\u0447\u0443\u0432\u0430\u043d\u0430. wizard.close=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 Torrent.create.progress.piecelength=\u0414\u0443\u0436\u0438\u043d\u0430 \u0434\u0435\u043b\u0430: Torrent.create.progress.piececount=\u0411\u0440\u043e\u0458 \u0434\u0435\u043b\u0430: Torrent.create.progress.totalfilesize=\u0423\u043a\u0443\u043f\u043d\u0430 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435: Torrent.create.progress.totalfilecount=\u0423\u043a\u0443\u043f\u0430\u043d \u0431\u0440\u043e\u0458 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430: Torrent.create.progress.parsingfiles=\u0420\u0430\u0448\u0447\u043b\u0430\u045a\u0438\u0432\u0430\u045a\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 Torrent.create.progress.hashing=\u0425\u0435\u0448\u0438\u0440\u0430\u045a\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 MainWindow.upgrade.downloadingfrom=\u041f\u0440\u0438\u0458\u0435\u043c \u0441\u0430 : MainWindow.menu.view.ipFilter=&\u0418\u041f \u0444\u0438\u043b\u0442\u0435\u0440\u0438 ConfigView.section.ipfilter=\u0418\u041f \u0444\u0438\u043b\u0442\u0435\u0440\u0438 ConfigView.section.ipfilter.description=\u041e\u043f\u0438\u0441 ConfigView.section.ipfilter.start=\u041f\u043e\u0447\u0435\u0442\u043d\u0438 \u0418\u041f ConfigView.section.ipfilter.end=\u041a\u0440\u0430\u0458\u045a\u0438 \u0418\u041f ConfigView.section.ipfilter.add=\u0414\u043e\u0434\u0430\u0458 ConfigView.section.ipfilter.remove=\u0423\u043a\u043b\u043e\u043d\u0438 ConfigView.section.ipfilter.edit=\u0423\u0440\u0435\u0434\u0438 ConfigView.section.ipfilter.save=\u0421\u0430\u0447\u0443\u0432\u0430\u0458 ConfigView.section.ipfilter.editFilter=\u0423\u0440\u0435\u0434\u0438 \u0444\u0438\u043b\u0442\u0435\u0440 ConfigView.section.ipfilter.enable=\u0423\u043a\u0459\u0443\u0447\u0435\u043d\u043e PeersView.menu.close=&\u0417\u0430\u0442\u0432\u043e\u0440\u0438 seedmore.title=\u0422\u043e\u0440\u0435\u043d\u0442 \u043d\u0438\u0458\u0435 \u0434\u043e\u0431\u0440\u043e \u0437\u0430\u043c\u0435\u0442\u043d\u0443\u0442 seedmore.shareratio=\u0412\u0430\u0448 \u043e\u0434\u043d\u043e\u0441 \u0434\u0435\u0459\u0435\u045a\u0430 \u0437\u0430 \u043e\u0432\u0430\u0458 \u0442\u043e\u0440\u0435\u043d\u0442 \u0458\u0435 seedmore.uploadmore=\u041e\u0434\u043d\u043e\u0441 \u0434\u0435\u0459\u0435\u045a\u0430 \u0438\u0441\u043f\u043e\u0434 1 \u043d\u0438\u0458\u0435 \u0434\u043e\u0431\u0430\u0440 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u043c\u0440\u0435\u0436\u0443.\n\u041d\u0435\u043e\u043f\u0445\u043e\u0434\u043d\u043e \u0458\u0435 \u0434\u0430 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u0434\u0430 \u0441\u0435 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0435\u043b\u0438 \u0458\u043e\u0448 \u043d\u0435\u043a\u043e \u0432\u0440\u0435\u043c\u0435.\n\u0414\u0430 \u043b\u0438 \u0441\u0438\u0433\u0443\u0440\u043d\u043e \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u043d\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u0435? ConfigView.label.showpopuponclose=\u041f\u043e\u043a\u0430\u0436\u0438 \u043f\u0440\u043e\u0437\u043e\u0440\u0447\u0438\u045b \u0437\u0430 \u043f\u043e\u0442\u0432\u0440\u0434\u0443 \u043a\u0430\u0434\u0430 \u0441\u0435 \u043e\u0431\u0443\u0441\u0442\u0430\u0432\u0459\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 \u0441\u0430 \u043e\u0434\u043d\u043e\u0441\u043e\u043c \u0434\u0435\u0459\u0435\u045a\u0430 \u043c\u0430\u045a\u0438\u043c \u043e\u0434 1 ConfigView.label.startNumSeeds=\n\u041f\u043e\u043a\u0440\u0435\u043d\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 \u0430\u043a\u043e \u0438\u043c\u0430 \u043c\u0430\u045a\u0435 \u043e\u0434\n - \u043f\u0440\u0435\u0438\u043d\u0430\u0447\u0443\u0458\u0435 \u0441\u0432\u0430 \u043e\u0441\u0442\u0430\u043b\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 ConfigView.label.seeds=\u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 ConfigView.section.seeding=\u0417\u0430\u043c\u0435\u0442\u0430\u045a\u0435 MyTorrentsView.menu.removeand=&\u0423\u043a\u043b\u043e\u043d\u0438 \u0438 MyTorrentsView.menu.removeand.deletetorrent=\u0423\u043a\u043b\u043e\u043d\u0438 &\u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 MyTorrentsView.menu.removeand.deletedata=\u0423\u043a\u043b\u043e\u043d\u0438 &\u043f\u043e\u0434\u0430\u0442\u043a\u0435 MyTorrentsView.menu.removeand.deleteboth=\u0423\u043a\u043b\u043e\u043d\u0438 &\u043e\u0431\u043e\u0458\u0435 deletedata.title=\u0423\u043f\u043e\u0437\u043e\u0440\u0435\u045a\u0435 deletedata.message1=\u0421\u0430\u043c\u043e \u0448\u0442\u043e \u043d\u0438\u0441\u0442\u0435 \u0443\u043a\u043b\u043e\u043d\u0438\u043b\u0438 \u041f\u041e\u0414\u0410\u0422\u041a\u0415 \u0441\u0430 :\n MainWindow.menu.file.configure=&\u0427\u0430\u0440\u043e\u0431\u045a\u0430\u043a \u0437\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430... configureWizard.title=\u0427\u0430\u0440\u043e\u0431\u045a\u0430\u043a \u0437\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 configureWizard.welcome.title=\u0414\u043e\u0431\u0440\u043e\u0434\u043e\u0448\u043b\u0438 \u043a\u043e\u0434 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432\u043e\u0433 \u0447\u0430\u0440\u043e\u0431\u045a\u0430\u043a\u0430 \u0437\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 configureWizard.welcome.message=\u041e\u0432\u0430\u0458 \u0447\u0430\u0440\u043e\u0431\u045a\u0430\u043a \u045b\u0435 \u0412\u0430\u043c \u043f\u043e\u043c\u043e\u045b\u0438 \u0434\u0430 \u043f\u043e\u0434\u0435\u0441\u0438\u0442\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u0437\u0430 \u0443\u043e\u0431\u0438\u0447\u0430\u0458\u0435\u043d\u0443 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0443. \u0414\u0435\u0442\u0430\u0459\u0435 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u0438\u0442\u0438 \u043a\u043e\u0440\u0438\u0441\u0442\u0435\u045b\u0438 \u043c\u0435\u043d\u0438 \u201e\u0410\u043b\u0430\u0442\u0438->\u041e\u043f\u0446\u0438\u0458\u0435\u201c. configureWizard.transfer.title=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u043f\u0440\u0435\u043d\u043e\u0441\u0430 \u0438 \u0432\u0435\u0437\u0435 configureWizard.transfer.hint=\u0421\u0430\u0432\u0435\u0442: \u043a\u043e\u0440\u0438\u0448\u045b\u0435\u045a\u0435 \u043d\u0435\u0448\u0442\u043e \u043c\u0430\u043b\u043e \u043c\u0430\u045a\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u043d\u0435\u0433\u043e \u0448\u0442\u043e \u0458\u0435 \u043a\u0430\u043f\u0430\u0446\u0438\u0442\u0435\u0442 \u0432\u0435\u0437\u0435 \u0458\u0435 \u043d\u0430\u0458\u0431\u043e\u0459\u0438 \u0438\u0437\u0431\u043e\u0440. configureWizard.transfer.message=\u041c\u043e\u043b\u0438\u043c\u043e \u0438\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0435\u0437\u0443 \u0438\u0437 \u0434\u043e\u043b\u0435 \u0434\u0430\u0442\u043e\u0433 \u0441\u043f\u0438\u0441\u043a\u0430. \u0418\u043c\u0430\u0458\u0442\u0435 \u043d\u0430 \u0443\u043c\u0443 \u0434\u0430 \u0430\u043a\u043e \u043d\u0435 \u0434\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0435 \u0434\u043e\u0432\u043e\u0459\u043d\u0443 \u0431\u0440\u0437\u0438\u043d\u0443 \u0441\u043b\u0430\u045a\u0430 \u0442\u043e \u045b\u0435 \u0438\u043c\u0430\u0442\u0438 \u0437\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u0438\u0446\u0443 \u0438 \u0441\u043f\u043e\u0440 \u043f\u0440\u0438\u0458\u0435\u043c. \u041a\u0430\u043a\u043e \u0441\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u043f\u0440\u0435\u043d\u043e\u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0458\u0443 \u043f\u043e \u043f\u043e\u0458\u0435\u0434\u0438\u043d\u0430\u0447\u043d\u043e\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0443, \u043f\u043e\u043a\u0443\u0448\u0430\u0458 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u043f\u0440\u0435\u0432\u0438\u0448\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0443 \u0438\u0441\u0442\u043e \u0432\u0440\u0435\u043c\u0435 \u043c\u043e\u0436\u0435 \u0431\u0438\u0442\u0438 \u0443\u0437\u0440\u043e\u043a \u043c\u0430\u043b\u043e\u0458 \u0431\u0440\u0437\u0438\u043d\u0438 \u043f\u0440\u0435\u043d\u043e\u0441\u0430. \u041f\u0440\u0435\u043f\u043e\u0440\u0443\u0447\u0443\u0458\u0435\u043c\u043e \u0434\u0430 \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 5KB/s \u043a\u0430\u043e \u0421\u0422\u0420\u041e\u0413\u0418 \u043c\u0438\u043d\u0438\u043c\u0443\u043c. \u0428\u0442\u043e \u0431\u0440\u0436\u0435 \u0448\u0430\u0459\u0435\u0442\u0435, \u0431\u0440\u0436\u0435 \u045b\u0435\u0442\u0435 \u043f\u0440\u0438\u043c\u0430\u0442\u0438 (\u0443 \u043e\u0434\u043d\u043e\u0441\u0443 \u043d\u0430 \u0431\u0440\u0437\u0438\u043d\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0430). configureWizard.transfer.connection=\u0412\u0435\u0437\u0430 configureWizard.transfer.connection.0=\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0459\u043d\u0430 configureWizard.transfer.connection.1=\u043c\u043e\u0434\u0435\u043c\u0441\u043a\u0430 configureWizard.transfer.connection.2=\u0430\u0434\u0441\u043b/\u043a\u0430\u0431\u043b xxx/128 kbps configureWizard.transfer.connection.3=\u0430\u0434\u0441\u043b/\u043a\u0430\u0431\u043b xxx/256 kbps configureWizard.transfer.connection.4=\u0430\u0434\u0441\u043b/\u043a\u0430\u0431\u043b xxx/384 kbps configureWizard.transfer.connection.5=\u0430\u0434\u0441\u043b/\u043a\u0430\u0431\u043b xxx/512 kbps configureWizard.transfer.connection.6=\u0430\u0434\u0441\u043b/\u043a\u0430\u0431\u043b xxx/768 kbps configureWizard.transfer.connection.7=\u0430\u0434\u0441\u043b/\u043a\u0430\u0431\u043b xxx/1024 kbps configureWizard.transfer.maxUpSpeed=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 (KB/s) configureWizard.transfer.maxActiveTorrents=\u041d\u0430\u0458\u0432\u0438\u0448\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0445 configureWizard.transfer.maxDownloads=\u041d\u0430\u0458\u0432\u0438\u0448\u0435 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 configureWizard.transfer.maxUploadsPerTorrent=\u041d\u0430\u0458\u0432\u0438\u0448\u0435 \u0441\u043b\u0430\u045a\u0430 \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 configureWizard.nat.title=NAT / \u043f\u043e\u0440\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 configureWizard.nat.message=\u041a\u0430\u043a\u043e \u0431\u0438\u0441\u0442\u0435 \u0438\u0437\u0432\u0443\u043a\u043b\u0438 \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0438\u0437 \u0411\u0438\u0442 \u0422\u043e\u0440\u0435\u043d\u0442\u0430, \u043f\u0440\u0435\u043f\u043e\u0440\u0443\u0447\u0443\u0458\u0435 \u0441\u0435 \u0434\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u0431\u0443\u0434\u0435 \u043f\u043e\u0442\u043f\u0443\u043d\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430\u043d \u0441\u0430 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430. \u041e\u0432\u0430\u0458 \u0430\u043b\u0430\u0442 \u0432\u0430\u043c \u0434\u043e\u043f\u0443\u0448\u0442\u0430 \u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u0438 \u043f\u0440\u043e\u043c\u0435\u043d\u0438\u0442\u0435 \u0431\u0440\u043e\u0458 \u043f\u043e\u0440\u0442\u0430 \u043a\u043e\u0458\u0438 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0437\u0430 \u043f\u0440\u0438\u0445\u0432\u0430\u0442 \u0434\u043e\u043b\u0430\u0437\u043d\u0438\u0445 \u0432\u0435\u0437\u0430.\n\n\u041f\u0420\u0418\u041c\u0415\u0414\u0411\u0410: \u041e\u0432\u0430\u0458 \u0430\u043b\u0430\u0442 \u0441\u0430\u043c\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0430\u0432\u0430 \u0422\u0426\u041f \u0432\u0435\u0437\u0435. \u0420\u0430\u0441\u043f\u043e\u0434\u0435\u0459\u0435\u043d\u0430 \u0431\u0430\u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u0442\u0440\u0430\u0436\u0438 \u0438 \u0423\u0414\u041f \u0432\u0435\u0437\u0435, \u0430\u043b\u0438 \u045b\u0435 \u0412\u0430\u0441 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043e\u0431\u0430\u0432\u0435\u0441\u0442\u0438\u0442 \u0430\u043a\u043e \u043e\u0442\u043a\u0440\u0438\u0458\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u0458\u0443\u045b\u0438 \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d.\n\n\u041f\u0420\u0418\u041c\u0415\u0414\u0411\u0410: \u0422\u0426\u041f \u043f\u043e\u0440\u0442 6880 \u0458\u0435 \u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0441\u0430\u043d\u043d \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0438. configureWizard.nat.test=\u041f\u0440\u043e\u0431\u0430 configureWizard.nat.testing=\u041f\u043e\u0440\u0442 \u0437\u0430 \u043f\u0440\u043e\u0431\u0443 configureWizard.nat.ok=\u0423 \u0440\u0435\u0434\u0443 ! configureWizard.nat.ko=NAT \u0413\u0440\u0435\u0448\u043a\u0430 configureWizard.nat.unable=\u041d\u0438\u0458\u0435 \u043c\u043e\u0433\u0443\u045b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0438: \u0417\u0430\u0434\u0430\u0442 \u0458\u0435 \u043d\u0435\u0432\u0430\u0436\u0435\u045b\u0438 \u043f\u043e\u0440\u0442, \u0438\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 \u043d\u0435 \u0440\u0430\u0434\u0438.\n\u0414\u0440\u0443\u0433\u0430 \u0430\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u0458\u0430 \u043c\u043e\u0436\u0434\u0430 \u0432\u0435\u045b \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u043e\u0432\u0430\u0458 \u043f\u043e\u0440\u0442 configureWizard.file.title=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 / \u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0435 configureWizard.file.message1=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u045b\u0435 \u0441\u0430\u0447\u0443\u0432\u0430\u0442\u0438 \u043e\u0442\u0432\u043e\u0440\u0435\u043d\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0443 \u043e\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c, \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0441\u0435 \u043c\u043e\u0436\u0435 \u043e\u0434\u0430\u0431\u0440\u0430\u0442\u0438 \u043e\u0432\u0434\u0435: configureWizard.file.path=\u0421\u0442\u0430\u0437\u0430 configureWizard.file.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 configureWizard.file.message2=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u043c\u043e\u0436\u0435 \u0434\u0430 \u043e\u0434\u043c\u0430\u0445 \u043d\u0430\u0441\u0442\u0430\u0432\u0438 \u043f\u0440\u0435\u043d\u043e\u0441 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430, \u0442\u0430\u043a\u043e \u0448\u0442\u043e \u0434\u043e\u0434\u0430\u0458\u0435 \u0438\u0437\u0432\u0435\u0441\u043d\u0443 \u043a\u043e\u043b\u0438\u0447\u0438\u043d\u0443 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u043a\u043e\u0458\u0438 \u0443 \u0442\u043e\u043c\u0435 \u043f\u043e\u043c\u0430\u0436\u0443. \u0410\u043a\u043e \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u043e\u0432\u0443 \u043c\u043e\u0433\u0443\u045b\u043d\u043e\u0441\u0442, \u043d\u0430\u0441\u0442\u0430\u0432\u0430\u043a \u0434\u0435\u043b\u0438\u043c\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u0438\u0445 \u0434\u0435\u043b\u043e\u0432\u0430 \u0458\u0435 \u0442\u0430\u043a\u043e\u0452\u0435 \u043c\u043e\u0433\u0443\u045b. configureWizard.file.fastResume=\u0423\u043a\u0459\u0443\u0447\u0438 \u0431\u0440\u0437\u0438 \u043d\u0430\u0441\u0442\u0430\u0432\u0430\u043a configureWizard.file.invalidPath=\u041d\u0435\u0432\u0430\u0436\u0435\u045b\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c configureWizard.finish.title=\u041f\u0440\u0435\u0443\u0437\u0435\u0442\u043e configureWizard.finish.message=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u0458\u0435 \u0441\u0430\u0434\u0430 \u043f\u043e\u0434\u0435\u0448\u0435\u043d. \u0423\u0436\u0438\u0432\u0430\u0458\u0442\u0435 ! wizard.close.confirmation=\u041f\u043e\u0442\u0432\u0440\u0434\u0430 wizard.close.message=\u0414\u0430 \u043b\u0438 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u0441\u0435 \u0447\u0430\u0440\u043e\u0431\u045a\u0430\u043a \u0443\u0447\u0438\u0442\u0430 \u043d\u0430\u0440\u0435\u0434\u043d\u0438 \u043f\u0443\u0442 \u043a\u0430\u0434\u0430 \u0441\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u043f\u043e\u043a\u0440\u0435\u043d\u0435? exportTorrentWizard.title=\u0418\u0437\u0432\u043e\u0437 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0443 XML \u0444\u043e\u0440\u043c\u0430\u0442 exportTorrentWizard.torrentfile.title=\u0418\u0437\u0431\u043e\u0440 \u0443\u043b\u0430\u0437\u043d\u043e\u0433 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 exportTorrentWizard.torrentfile.message=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u0437\u0430 \u0438\u0437\u0432\u043e\u0437 exportTorrentWizard.torrentfile.path=\u0421\u0442\u0430\u0437\u0430 exportTorrentWizard.torrentfile.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 exportTorrentWizard.torrentfile.invalidPath=\u041d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 exportTorrentWizard.exportfile.title=\u0418\u0437\u0431\u043e\u0440 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 exportTorrentWizard.exportfile.message=\u041e\u0434\u0440\u0435\u0434\u0438\u0442\u0435 XML \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u0437\u0430 \u0438\u0437\u0432\u043e\u0437 exportTorrentWizard.exportfile.path=\u0421\u0442\u0430\u0437\u0430 exportTorrentWizard.exportfile.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 exportTorrentWizard.exportfile.invalidPath=\u041d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0437\u0430 \u0438\u0437\u0432\u043e\u0437 exportTorrentWizard.finish.title=\u041f\u0440\u0435\u0443\u0437\u0435\u0442\u043e exportTorrentWizard.finish.message=\u0418\u0437\u0432\u043e\u0437 \u0458\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0431\u0430\u0432\u0459\u0435\u043d exportTorrentWizard.process.inputfilebad.title=\u0422\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0458\u0435 \u043d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u0430 exportTorrentWizard.process.inputfilebad.message=\u0414\u043e\u0448\u043b\u043e \u0458\u0435 \u0434\u043e \u0433\u0440\u0435\u0448\u043a\u0435 \u043f\u0440\u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0443 \u0443\u043b\u0430\u0437\u043d\u043e\u0458 \u0434\u0430\u0442\u043e\u0442\u0435\u0446\u0438: exportTorrentWizard.process.outputfileexists.title=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 exportTorrentWizard.process.outputfileexists.message=\u0418\u0437\u043b\u0430\u0437\u043d\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043f\u043e\u0441\u0442\u043e\u0458\u0438? \u0414\u0430 \u043b\u0438 \u0434\u0430 \u0458\u0435 \u043f\u0440\u0435\u0431\u0440\u0438\u0448\u0435\u043c? exportTorrentWizard.process.torrentfail.title=\u0427\u0438\u0442\u0430\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e exportTorrentWizard.process.exportfail.title=\u0418\u0437\u0432\u043e\u0437 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043e exportTorrentWizard.process.unknownfail.title=\u041d\u0435\u043e\u0447\u0435\u043a\u0438\u0432\u0430\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 importTorrentWizard.title=\u0423\u0432\u043e\u0437 XML \u0442\u043e\u0440\u0435\u043d\u0442\u0430 importTorrentWizard.torrentfile.title=\u0418\u0437\u0431\u043e\u0440 \u0443\u043b\u0430\u0437\u043d\u043e\u0433 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 importTorrentWizard.torrentfile.message=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u0443 \u043a\u043e\u0458\u0443 \u0441\u0435 \u0443\u0432\u043e\u0437\u0438 importTorrentWizard.torrentfile.path=\u0421\u0442\u0430\u0437\u0430 importTorrentWizard.torrentfile.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 importTorrentWizard.torrentfile.invalidPath=\u041d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 importTorrentWizard.importfile.title=\u0418\u0437\u0431\u043e\u0440 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0437\u0430 \u0443\u0432\u043e\u0437 importTorrentWizard.importfile.message=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 xml \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u0437\u0430 \u0443\u0432\u043e\u0437 importTorrentWizard.importfile.path=\u0421\u0442\u0430\u0437\u0430 importTorrentWizard.importfile.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434 importTorrentWizard.importfile.invalidPath=\u041d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0437\u0430 \u0443\u0432\u043e\u0437 importTorrentWizard.finish.title=\u041f\u0440\u0435\u0443\u0437\u0435\u0442\u043e importTorrentWizard.finish.message=\u0423\u0432\u043e\u0437 \u0458\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0431\u0430\u0432\u0459\u0435\u043d importTorrentWizard.process.inputfilebad.title=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0437\u0430 \u0443\u0432\u043e\u0437 \u0458\u0435 \u043d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u0430 importTorrentWizard.process.inputfilebad.message=\u0414\u043e\u0448\u043b\u043e \u0458\u0435 \u0434\u043e \u0433\u0440\u0435\u0448\u043a\u0435 \u043f\u0440\u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0443 \u0443\u043b\u0430\u0437\u043d\u043e\u0458 \u0434\u0430\u0442\u043e\u0442\u0435\u0446\u0438: importTorrentWizard.process.outputfileexists.title=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 importTorrentWizard.process.outputfileexists.message=\u0418\u0437\u043b\u0430\u0437\u043d\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043f\u043e\u0441\u0442\u043e\u0458\u0438? \u0414\u0430 \u043b\u0438 \u0434\u0430 \u0458\u0435 \u043f\u0440\u0435\u0431\u0440\u0438\u0448\u0435\u043c? importTorrentWizard.process.torrentfail.title=\u0423\u043f\u0438\u0441 \u0443 \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043e importTorrentWizard.process.importfail.title=\u0423\u0432\u043e\u0437 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043e importTorrentWizard.process.unknownfail.title=\u041d\u0435\u043e\u0447\u0435\u043a\u0438\u0432\u0430\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 ConfigView.label.bindip=\u041f\u0440\u0438\u0432\u0435\u0436\u0438 \u0437\u0430 \u043b\u043e\u043a\u0430\u043b\u043d\u0443 \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0443 \u0438\u043b\u0438 \u0441\u0443\u0447\u0435\u0459\u0435 ConfigView.label.xfs.allocation=\u041e\u0441\u043b\u043e\u0431\u0430\u0452\u0430\u045a\u0435 \u043c\u0435\u0441\u0442\u0430 \u0437\u0430 \u043d\u043e\u0432\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u043d\u0430 \u043d\u0430\u0447\u0438\u043d \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0430\u043d \u0437\u0430 \u0441\u0438\u0441\u0442\u0435\u043c \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 XFS ConfigView.label.xfs.allocation.tooltip=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u0434\u0430 \u0458\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c /usr/sbin/xfs_io \u0438\u0441\u043f\u0440\u0430\u0432\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d \u043d\u0430 \u0412\u0430\u0448 \u0441\u0438\u0441\u0442\u0435\u043c. \u041d\u0430 \u043c\u043d\u043e\u0433\u0438\u043c \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0446\u0438\u0458\u0430\u043c\u0430 \u0437\u0430\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u043c \u043d\u0430 \u041b\u0438\u043d\u0443\u043a\u0441\u0443, \u043d\u0430\u043b\u0430\u0437\u0438 \u0441\u0435 \u0443 \u043f\u0430\u043a\u0435\u0442\u0443 \u201exfsprogs\u201f. xfs.allocation.xfs_io.not.found=\u0420\u0435\u0437\u0430\u0435\u0440\u0432\u0430\u0446\u0438\u0458\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043f\u043e \u043c\u0435\u0442\u043e\u0434\u0443 XFS \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u0430 \u0458\u0435\u0440 \u043f\u0440\u043e\u0433\u0440\u0430\u043c /usr/sbin/xfs_io \u043d\u0438\u0458\u0435 \u043c\u043e\u0433\u0430\u043e \u0434\u0430 \u0431\u0443\u0434\u0435 \u043f\u043e\u043a\u0440\u0435\u043d\u0443\u0442. \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u0434\u0430 \u0458\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d \u043d\u0430 \u0412\u0430\u0448\u0435\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u0443. \u0418\u0437\u0432\u043e\u0440\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 \u0458\u0435 \u0431\u0438\u043b\u0430: \u201e%1\u201f. ConfigView.label.zeronewfiles=\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0448\u0438 \u0438 \u0430\u043d\u0443\u043b\u0438\u0440\u0430\u0458 \u043d\u043e\u0432\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u043f\u0440\u0438 \u0441\u0442\u0432\u0430\u0440\u0430\u045a\u0443 ConfigView.label.zeronewfiles.tooltip=\u0421\u043c\u0430\u045a\u0443\u0458\u0435 \u0440\u0430\u0441\u0446\u0435\u043f\u043a\u0430\u043d\u043e\u0441\u0442 ConfigView.section.stats=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 ConfigView.section.stats.enable=\u0423\u043a\u0459\u0443\u0447\u0435\u043d\u043e ConfigView.section.stats.defaultsavepath=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0437\u0430 \u0437\u0430\u043f\u0438\u0441 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 ConfigView.section.stats.choosedefaultsavepath=\u041c\u043e\u043b\u0438\u043c\u043e \u0438\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0437\u0430 \u0437\u0430\u043f\u0438\u0441 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 ConfigView.section.stats.savefreq=\u0423\u0447\u0435\u0441\u0442\u0430\u043d\u043e\u0441\u0442 \u0437\u0430\u043f\u0438\u0441\u0438\u0432\u0430\u045a\u0430 ConfigView.section.stats.minutes=\u043c\u0438\u043d ConfigView.section.stats.hours=\u0441\u0430\u0442 ConfigView.section.stats.seconds=\u0441\u0435\u043a ConfigView.section.stats.savefile=\u0418\u043c\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0441\u0430 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u043e\u043c ConfigView.section.stats.graph_update_dividers=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u043d\u0443 \u043b\u0438\u043d\u0438\u0458\u0443 \u043d\u0430 \u0441\u0432\u0430\u043a\u0438\u0445 60 \u043e\u0441\u0432\u0435\u0436\u0435\u045a\u0430 MyTorrentsView.menu.export=&XML \u0442\u043e\u0440\u0435\u043d\u0442... MyTorrentsView.menu.host=&\u0420\u0430\u0447\u0443\u043d\u0430\u0440... ManagerItem.finishing=\u041e\u043a\u043e\u043d\u0447\u0430\u0432\u0430\u045a\u0435 ConfigView.dialog.choosedefaulttorrentpath=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0438\u0437\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 ConfigView.dialog.choosemovepath=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0438\u0437\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0458\u0443\u043c \u0443 \u043a\u043e\u0433\u0430 \u0442\u0440\u0435\u0431\u0430 \u043f\u0440\u0435\u0431\u0430\u0446\u0438\u0442\u0438 ConfigView.label.movecompleted=\u041f\u043e\u043c\u0435\u0440\u0438 \u0437\u0430\u0432\u0440\u0448\u0435\u043d\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 (\u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u0438\u0458\u0435\u043c\u0430) ConfigView.label.moveremoved=\u041f\u043e\u043c\u0435\u0440\u0438 \u0437\u0430\u0432\u0440\u0448\u0435\u043d\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 (\u043f\u0440\u0438 \u0443\u043a\u043b\u0430\u045a\u0430\u045a\u0443) ConfigView.label.savetorrents=\u0421\u0430\u0447\u0443\u0432\u0430\u0458 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 MainWindow.menu.view.mytracker=\u041c\u043e\u0458 &\u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 MyTrackerView.title.full=\u041c\u043e\u0458 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 MyTrackerView.name=\u0418\u043c\u0435 MyTrackerView.tracker=\u041f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 MyTrackerView.status=\u0421\u0442\u0430\u0442\u0443\u0441 MyTrackerView.status.started=\u0420\u0430\u0434\u0438 MyTrackerView.status.stopped=\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0459\u0435\u043d MyTrackerView.peers=\u0420\u0430\u0447\u0443\u043d\u0430\u0440\u0438 MyTrackerView.seeds=\u0417\u0430\u043c\u0435\u0446\u0438 MyTrackerView.announces=\u041d\u0430\u0458\u0430\u0432\u0435 MyTrackerView.uploaded=\u041f\u043e\u0441\u043b\u0430\u0442\u043e MyTrackerView.downloaded=\u041f\u0440\u0435\u0443\u0437\u0435\u0442\u043e MyTrackerView.left=\u041f\u0440\u0435\u043e\u0441\u0442\u0430\u043b\u043e ConfigView.section.style=\u0421\u0443\u0447\u0435\u0459\u0435 ConfigView.label.set_ui_transfer_speeds=\u041f\u0440\u0435\u0438\u043d\u0430\u0447\u0438 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u043f\u0440\u0435\u043d\u043e\u0441\u0430 ConfigView.label.set_ui_transfer_speeds.description=\u041c\u043e\u0436\u0435\u0442\u0435 \u0434\u0430 \u0440\u0443\u0447\u043d\u043e \u043e\u0434\u0440\u0435\u0434\u0438\u0442\u0435 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u0438 \u0441\u043b\u0430\u045a\u0430 \u043a\u043e\u0458\u0435 \u0441\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0435 \u0443 \u0441\u0442\u0430\u0442\u0443\u0441\u043d\u043e\u0458 \u0442\u0440\u0430\u0446\u0438 \u0443 \u043e\u0431\u0430\u0432\u0435\u0448\u0442\u0430\u0458\u043d\u043e\u0458 \u0437\u043e\u043d\u0438.\n\u0412\u0440\u0435\u0434\u043d\u043e\u0441\u0442\u0438 \u043c\u043e\u0440\u0430\u0458\u0443 \u0431\u0438\u0442\u0438 \u043e\u0434\u0432\u043e\u0458\u0435\u043d\u0435 \u0437\u0430\u043f\u0435\u0442\u0430\u043c\u0430. ConfigView.label.set_ui_transfer_speeds.description.download=\u041f\u043e\u0441\u0442\u0430\u0432\u043a\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 (\u0443 KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 (\u0443 KB/s) ConfigView.section.style.useCustomTabs=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0458\u0435\u0437\u0438\u0447\u043a\u0435 \u043a\u043e\u0458\u0438 \u0441\u0435 \u043c\u043e\u0433\u0443 \u0437\u0430\u0442\u0432\u043e\u0440\u0438\u0442\u0438 (\u043d\u0435\u043e\u043f\u0445\u043e\u0434\u043d\u043e \u043f\u043e\u043d\u043e\u0432\u043d\u043e \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435) MainWindow.menu.view.plugins=&\u041f\u0440\u043e\u0448\u0438\u0440\u0435\u045a\u0430 fileDownloadWindow.saveTorrentIn=\u0421\u0430\u0447\u0443\u0432\u0430\u0458 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u0443 fileDownloadWindow.title=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 - \u041f\u0440\u0438\u0458\u0435\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0430 fileDownloadWindow.downloading=\u041f\u0440\u0438\u0458\u0435\u043c \u043e\u0434 : fileDownloadWindow.status=\u0421\u0442\u0430\u0442\u0443\u0441 : fileDownloadWindow.state_initializing=\u041f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 fileDownloadWindow.state_downloading=\u041f\u0440\u0438\u0458\u0435\u043c fileDownloadWindow.state_error=\u0413\u0440\u0435\u0448\u043a\u0430 : MainWindow.menu.file.open.url=&\u041c\u0435\u0441\u0442\u043e... openUrl.title=\u041e\u0442\u0432\u043e\u0440\u0438 \u043c\u0435\u0441\u0442\u043e openUrl.url=\u0423\u0420\u041b : MyTorrentsView.menu.host.error.title=\u0423\u0433\u043e\u0448\u045b\u0435\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e MyTorrentsView.menu.host.error.message=\u041d\u0430\u0440\u0435\u0434\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 \u0441\u0435 \u0434\u043e\u0433\u043e\u0434\u0438\u043b\u0430 \u043f\u0440\u0438 \u0443\u0433\u043e\u0448\u045b\u0430\u0432\u0430\u045a\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 ConfigView.section.tracker=\u041f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 ConfigView.section.tracker.pollinterval=\u0412\u0440\u0435\u043c\u0435\u043d\u0441\u043a\u0438 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u0435 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 (\u0441\u0435\u043a\u0443\u043d\u0434\u0435) ConfigView.section.tracker.publishenable=\u041e\u0431\u0458\u0430\u0432\u0430 \u0434\u0435\u0442\u0430\u0459\u0430 \u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u043d\u0430 \u201e\u201c ConfigView.section.tracker.ip=\u0421\u043f\u043e\u0459\u0430\u0448\u045a\u0430 \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 ConfigView.section.style.enableXPStyle=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u0418\u043a\u0441-\u043f\u0435 \u0441\u0442\u0438\u043b (\u0437\u0430\u0445\u0442\u0435\u0432\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442) ConfigView.section.tracker.checkip=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043e\u0442\u043a\u0440\u0438\u0458 \u0435\u043a\u0441\u0442\u0435\u0440\u043d\u0443 \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0443... ipCheckerWizard.title=\u0427\u0430\u0440\u043e\u0431\u045a\u0430\u043a \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0430 ipCheckerWizard.service=\u0423\u0441\u043b\u0443\u0433\u0430 ipCheckerWizard.chooseService=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0438\u0437\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u0443\u0441\u043b\u0443\u0433\u0443 \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0435 \u0441\u0430 \u0434\u0430\u0442\u043e\u0433 \u0441\u043f\u0438\u0441\u043a\u0430 ipCheckerWizard.explanations=\u041c\u043e\u0436\u0435\u0442\u0435 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0438 \u043e\u0432\u043e\u0433 \u0447\u0430\u0440\u043e\u0431\u045a\u0430\u043a\u0430 \u0434\u0430 \u0441\u0430\u0437\u043d\u0430\u0442\u0435 \u043a\u043e\u0458\u0430 \u0458\u0435 \u0441\u043f\u043e\u0459\u0430\u0448\u045a\u0430 \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0430 \u043e\u0432\u043e\u0433 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430. \u0410\u043a\u043e \u0458\u0435 \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0430 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u043a\u0430, \u043f\u0440\u0435\u043f\u043e\u0440\u0443\u0447\u0443\u0458\u0435\u043c\u043e \u0434\u0430 \u043e\u0442\u0432\u043e\u0440\u0438\u0442\u0435 \u043d\u0430\u043b\u043e\u0433 \u043a\u043e\u0434 \u043d\u0435\u043a\u043e\u0433 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u043a\u043e\u0433 \u0414\u041d\u0421 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u041d\u0435\u043a\u0435 \u043e\u0434 \u043f\u043e\u0441\u043b\u0443\u0436\u0438\u0442\u0435\u0459\u0430 \u043a\u043e\u0458\u0438 \u0434\u0430\u0458\u0443 \u043e\u0432\u0443 \u0443\u0441\u043b\u0443\u0433\u0443 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438 \u0441\u0443 \u0438\u0441\u043f\u043e\u0434. \u041a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u0434\u0430\u0442\u0443 \u0432\u0435\u0437\u0443 \u043a\u0430\u043a\u043e \u0431\u0438\u0441\u0442\u0435 \u043e\u0442\u0432\u043e\u0440\u0438\u043b\u0438 \u043d\u0430\u043b\u043e\u0433 (\u0442\u0430\u043c\u043e \u0433\u0434\u0435 \u0458\u0435 \u0442\u043e \u043c\u043e\u0433\u0443\u045b\u0435). \u0417\u0430\u0442\u0438\u043c \u0438\u0441\u043f\u0443\u043d\u0438\u0442\u0435 \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0443 \u043f\u043e\u0459\u0430 \u0441\u0430 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u043a\u0438\u043c \u0438\u043c\u0435\u043d\u043e\u043c (\u043d\u043f\u0440. myhostname.dyndns.org). \u0411\u0438\u045b\u0435 \u0412\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0430\u043d \u043f\u0440\u043e\u0433\u0440\u0430\u043c \u043a\u043e\u0458\u0438 \u045b\u0435 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043e\u0431\u0430\u0432\u0435\u0448\u0442\u0430\u0432\u0430\u0442\u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u043a\u0438 \u0414\u041d\u0421 \u043e \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0438. \u041d\u0430 \u0442\u0430\u0458 \u043d\u0430\u0447\u0438\u043d \u045b\u0435\u0442\u0435 \u043c\u043e\u045b\u0438 \u0434\u0430 \u0443\u0433\u043e\u0441\u0442\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0447\u0430\u043a \u0438 \u0441\u0430 \u043f\u0440\u043e\u043c\u0435\u043d\u0459\u0438\u0432\u043e\u043c \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u043e\u043c. ipCheckerWizard.service.description=\u041e\u043f\u0438\u0441 : ipCheckerWizard.service.url=\u0412\u0435\u0437\u0430 ipCheckerWizard.progresstitle=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u0418\u041f\u0430 ipCheckerWizard.checkComplete=\u041e\u0434\u0440\u0435\u0452\u0435\u043d \u0418\u041f : ipCheckerWizard.checkFailed=\u041d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e, \u0440\u0430\u0437\u043b\u043e\u0433: wizard.tracker.local=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432 \u0443\u0433\u0440\u0430\u0452\u0435\u043d \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 wizard.tracker.external=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0441\u043f\u043e\u0459\u0430\u0448\u045a\u0438 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 wizard.tracker.howToLocal=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u201e\u0410\u043b\u0430\u0442\u0438->\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430->\u041f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u201c \u043a\u0430\u043a\u043e \u0431\u0438\u0441\u0442\u0435 \u0433\u0430 \u0443\u043a\u0459\u0443\u0447\u0438\u043b\u0438 wizard.announceUrl=\u0423\u0420\u041b \u0437\u0430 \u043e\u0431\u0458\u0430\u0432\u0443 : IPChecker.external.service.discoveryvip.description=Discoveryvip - \u0441\u0430\u043c\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0430 \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0435 IPChecker.external.httpinvalidresponse=\u041d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u0430\u043d \u043e\u0434\u0433\u043e\u0432\u043e\u0440 \u043d\u0430 HTTP \u0443\u043f\u0438\u0442 IPChecker.external.loadingwebpage=\u0423\u0447\u0438\u0442\u0430\u0432\u0430\u045a\u0435 \u043c\u0440\u0435\u0436\u043d\u0435 \u0441\u0442\u0440\u0430\u043d\u0435 IPChecker.external.analysingresponse=\u041e\u0431\u0440\u0430\u0434\u0430 \u043e\u0434\u0433\u043e\u0432\u043e\u0440\u0430 IPChecker.external.addressextracted=\u0418\u0437\u0432\u0443\u0447\u0435\u043d\u0430 \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0430 IPChecker.external.httploadfail=\u0423\u0447\u0438\u0442\u0430\u0432\u0430\u045a\u0435 \u0441\u0442\u0440\u0430\u043d\u0435 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e IPChecker.external.timeout=\u0412\u0440\u0435\u043c\u0435 \u0458\u0435 \u0438\u0441\u0442\u0435\u043a\u043b\u043e IPChecker.external.ipnotfound=\u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0430 \u043d\u0438\u0458\u0435 \u043f\u0440\u043e\u043d\u0430\u0452\u0435\u043d\u0430 ConfigView.section.tracker.pollintervalmin=\u041d\u0430\u0458\u043c\u0430\u045a\u0438 ConfigView.section.tracker.pollintervalmax=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 ConfigView.section.tracker.pollintervalincby=\u041f\u043e\u0432\u0435\u045b\u0430\u045a\u0435 ConfigView.section.tracker.pollintervalincper=\u0421\u0432\u0430\u043a\u0438\u0445 n \u043a\u043b\u0438\u0458\u0435\u043d\u0430\u0442\u0430 splash.loadingImages=\u0423\u0447\u0438\u0442\u0430\u0432\u0430\u045a\u0435 \u0441\u043b\u0438\u043a\u0430 splash.initializeGui=\u041f\u043e\u0441\u0442\u0430\u0432\u0459\u0430\u045a\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0433 \u043f\u0440\u043e\u0437\u043e\u0440\u0430 splash.openViews=\u041e\u0442\u0432\u0430\u0440\u0430\u045a\u0435 \u043f\u043e\u0433\u043b\u0435\u0434\u0430 splash.plugin=\u0423\u0447\u0438\u0442\u0430\u0432\u0430\u045a\u0435 \u0434\u043e\u0434\u0430\u0442\u0430\u043a\u0430 : configureWizard.nat.tooManyPorts=\u0421\u0443\u0432\u0438\u0448\u0435 \u043f\u043e\u0440\u0442\u043e\u0432\u0430 \u0458\u0435 \u043e\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 (\u043d\u0430\u0458\u0432\u0438\u0448\u0435 9) ConfigView.section.color=\u0411\u043e\u0458\u0435 MyTorrentsView.menu.publish=&\u041e\u0431\u0458\u0430\u0432\u0438... MyTrackerView.status.published=\u041e\u0431\u0458\u0430\u0432\u0459\u0435\u043d\u043e MyTrackerView.completed=\u041f\u0440\u0435\u0443\u0437\u0435\u0442\u043e MainWindow.menu.file.open.torrentnodefault=\u0422\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 (\u0431\u0435\u0437 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u043e\u0433 \u0447\u0443\u0432\u0430\u045a\u0430) wizard.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 ConfigView.label.movetorrent=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 ConfigView.label.movepartialdownloads=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0438 \u043a\u0430\u0434\u0430 \u0441\u0443 \u043d\u0435\u043a\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0435 \u0441\u0430 \u201e\u041d\u0435 \u043f\u0440\u0438\u043c\u0430\u0458\u201f ConfigView.label.subdir_is_in_default=\u041f\u0440\u0438 \u043e\u0434\u0440\u0435\u0452\u0438\u0432\u0430\u045a\u0443 \u0434\u0430 \u043b\u0438 \u043f\u043e\u0441\u0442\u043e\u0458\u0435 \u043f\u0440\u0435\u0443\u0437\u0435\u0442\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0443 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u043e\u043c \u0434\u0438\u0440\u0430\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0443, \u043f\u0440\u0435\u0433\u043b\u0435\u0434\u0430\u0458 \u0442\u0430\u043a\u043e\u0452\u0435 \u0438 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0435 \u043f\u043e\u0434\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0435 ConfigView.section.file.decoder.label=\u041f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u043e \u043a\u043e\u0434\u0438\u0440\u0430\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u043a\u0430\u0434\u0430 \u0441\u0435 \u0442\u0440\u0430\u0436\u0438 \u0438\u0437\u0431\u043e\u0440 ConfigView.section.file.decoder.nodecoder=\u041d\u0438\u0458\u0435\u0434\u0430\u043d IPChecker.external.service.no-ip.description=\u0414\u043e\u0431\u0430\u0432\u0459\u0430\u0447 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u043a\u0435 \u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u043a\u0435 \u0414\u041d\u0421 \u0430\u0434\u0440\u0435\u0441\u0435\n(\u043d\u0435 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u0430 \u0443\u0441\u043b\u0443\u0433\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0435 \u0430\u0434\u0440\u0435\u0441\u0435) ConfigView.section.tracker.publicenable=\u0423\u043a\u0459\u0443\u0447\u0438 \u0441\u043f\u043e\u0459\u0430\u0448\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 ConfigView.label.playdownloadspeech=\u041e\u0431\u0430\u0432\u0435\u0441\u0442\u0438 \u0433\u043b\u0430\u0441\u043e\u043c \u043e \u043a\u0440\u0430\u0458\u0443 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 ConfigView.label.playdownloadspeech.info=\u0413\u043e\u0432\u043e\u0440\u043d\u0435 \u0443\u0441\u043b\u0443\u0433\u0435 \u0442\u0440\u0435\u043d\u0443\u0442\u043d\u043e \u043d\u0430\u0458\u0431\u043e\u0459\u0435 \u0440\u0430\u0434\u0435 \u043d\u0430 \u0435\u043d\u0433\u043b\u0435\u0441\u043a\u043e\u043c \u0458\u0435\u0437\u0438\u043a\u0443 # # Tooltips # GeneralView.label.status.pieces_available.tooltip=\u041f\u0440\u0438\u043a\u0430\u0437\u0443\u0458\u0435 \u0431\u0440\u043e\u0458 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u0443\u043c\u043d\u043e\u0436\u0430\u043a\u0430 \u0441\u0432\u0430\u043a\u043e\u0433 \u0434\u0435\u043b\u0430. \u0410\u043a\u043e \u0458\u0435 \u0431\u0440\u043e\u0458 \u0437\u0434\u0435\u0441\u043d\u0430 \u043c\u0430\u045a\u0438 \u043e\u0434 1, \u0442\u043e \u0437\u043d\u0430\u0447\u0438 \u0434\u0430 \u0446\u0435\u043b\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043d\u0438\u0458\u0435 \u0432\u0438\u0434\u0459\u0438\u0432\u0430 (\u043f\u0430 \u045b\u0435\u0442\u0435 \u0432\u0435\u0440\u043e\u0432\u0430\u0442\u043d\u043e \u0438\u043c\u0430\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0434\u0430 \u0434\u043e\u0432\u0440\u0448\u0438\u0442\u0435 \u043f\u0440\u0438\u0458\u0435\u043c). GeneralView.label.trackerurl.tooltip=\u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u0434\u0430 \u0443\u043c\u043d\u043e\u0436\u0438\u0442\u0435 \u0423\u0420\u041b \u0437\u0430 \u043e\u0431\u0458\u0430\u0432\u0443 \u043d\u0430 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434 GeneralView.label.trackerurlopen.tooltip=\u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u0434\u0430 \u0431\u0438\u0441\u0442\u0435 \u043e\u0442\u0432\u043e\u0440\u0438\u043b\u0438 \u0433\u043b\u0430\u0432\u043d\u0443 \u0441\u0442\u0440\u0430\u043d\u0443 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 # # 2.0.4.4 # ConfigView.section.style.guiUpdate=\u041e\u0441\u0432\u0435\u0436\u0438 \u043f\u0440\u0438\u043a\u0430\u0437 \u0441\u0432\u0430\u043a\u0438\u0445 ConfigView.section.style.graphicsUpdate=\u041e\u0441\u0432\u0435\u0436\u0430\u0432\u0430\u045a\u0435 \u0433\u0440\u0430\u0444\u0438\u0447\u043a\u0438\u0445 \u0442\u0440\u0430\u043a\u0430 \u0441\u0432\u0430\u043a\u0438\u0445 \u043d \u043e\u0441\u0432\u0435\u0436\u0430\u0432\u0430\u045a\u0430 \u0441\u0443\u0447\u0435\u0459\u0430 ConfigView.section.style.reOrderDelay=\u041f\u0440\u0435\u0443\u0440\u0435\u0434\u0438 \u0442\u0430\u0431\u0435\u043b\u0435 \u0441\u0432\u0430\u043a\u0438\u0445 \u043d \u043e\u0441\u0432\u0435\u0436\u0430\u0432\u0430\u045a\u0430 \u0441\u0443\u0447\u0435\u0459\u0430 [0: \u043d\u0438\u043a\u0430\u0434\u0430] ConfigView.section.style.reOrderDelay.never=\u041d\u0438\u043a\u0430\u0434\u0430 ConfigView.section.logging=\u0411\u0435\u043b\u0435\u0436\u0435\u045a\u0435 ConfigView.section.logging.enable=\u0423\u043a\u0459\u0443\u0447\u0438 \u0431\u0435\u043b\u0435\u0436\u0435\u045a\u0435 \u0443 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 ConfigView.section.logging.logdir=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0437\u0430 \u0431\u0435\u043b\u0435\u0448\u043a\u0435 ConfigView.section.logging.choosedefaultsavepath=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0438\u0437\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0437\u0430 \u0447\u0443\u0432\u0430\u045a\u0435 GeneralView.label.updatein.querying=\u0423\u043f\u0438\u0442\u0438... configureWizard.nat.sharePort=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0458\u0435\u0434\u0430\u043d \u0434\u0435\u0459\u0435\u043d\u0438 \u0443\u043b\u0430\u0437\u043d\u0438 \u043f\u043e\u0440\u0442 \u0437\u0430 \u0441\u0432\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 ConfigView.section.logging.maxsize=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u0431\u0435\u043b\u0435\u0448\u043a\u0438 ConfigView.section.tracker.passwordenableweb=\u0423\u043a\u0459\u0443\u0447\u0438 \u043b\u043e\u0437\u0438\u043d\u043a\u0443 \u0437\u0430 \u043c\u0440\u0435\u0436\u0443 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 ConfigView.section.tracker.passwordenabletorrent=\u0423\u043a\u0459\u0443\u0447\u0438 \u043b\u043e\u0437\u0438\u043d\u043a\u0443 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 ConfigView.section.tracker.username=\u041a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e \u0438\u043c\u0435 ConfigView.section.tracker.password=\u041b\u043e\u0437\u0438\u043d\u043a\u0430 columnChooser.title=\u0418\u0437\u0431\u043e\u0440 \u043a\u043e\u043b\u043e\u043d\u0430 \u0437\u0430 \u043f\u0440\u0438\u043a\u0430\u0437 columnChooser.move=\u041f\u0440\u0435\u0432\u0443\u0446\u0438\u0442\u0435 \u0440\u0435\u0434\u043e\u0432\u0435 \u043a\u0430\u043a\u043e \u0431\u0438\u0441\u0442\u0435 \u0438\u0445 \u043f\u0440\u0435\u0443\u0440\u0435\u0434\u0438\u043b\u0438 columnChooser.apply=\u041f\u0440\u0438\u043c\u0435\u043d\u0438 columnChooser.columnname=\u0418\u043c\u0435 \u043a\u043e\u043b\u043e\u043d\u0435 columnChooser.columndescription=\u041e\u043f\u0438\u0441 TableColumn.header.shareRatio={MyTorrentsView.shareRatio} MyTorrentsView.menu.editTableColumns=&\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 \u043a\u043e\u043b\u043e\u043d\u0430 wizard.operationfailed=\u0414\u0435\u0458\u0441\u0442\u0432\u043e \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e authenticator.title=\u041f\u043e\u0442\u0440\u0435\u0431\u043d\u0430 \u0430\u0443\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0458\u0430 authenticator.realm=\u041e\u0431\u043b\u0430\u0441\u0442 authenticator.tracker=\u041f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 authenticator.user=\u041a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e \u0438\u043c\u0435 authenticator.password=\u041b\u043e\u0437\u0438\u043d\u043a\u0430 ConfigView.label.allowSendVersion=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0443 \u0434\u0430 \u0448\u0430\u0459\u0435 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0438 \u0431\u0440\u043e\u0458 \u0438\u0437\u0434\u0430\u045a\u0430 \u0438 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u043d\u043e\u0432\u043e\u0433 \u0438\u0437\u0434\u0430\u045a\u0430 ConfigView.label.version.info.link=\u041f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 \u043e\u0432\u0443 \u0432\u0435\u0437\u0443 \u0437\u0430 \u0434\u0435\u0442\u0430\u0459\u0435 \u043e \u043f\u043e\u0434\u0430\u0446\u0438\u043c\u0430 \u043a\u043e\u0458\u0438 \u0441\u0435 \u0448\u0430\u0459\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 \u0438\u0437\u0434\u0430\u045a\u0430 wizard.hint.mode=\u0421\u0430\u0432\u0435\u0442: \u041c\u043e\u0436\u0435\u0442\u0435 \u0434\u0430 \u043f\u0440\u0435\u0432\u0443\u0447\u0435\u0442\u0435 \u0438 \u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u043f\u043e \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u043d\u0430 \u043e\u0432\u043e\u0433 \u0447\u0430\u0440\u043e\u0431\u045a\u0430\u043a\u0430\n \u043a\u0430\u043a\u043e \u0431\u0438\u0441\u0442\u0435 \u0438\u0437\u0430\u0431\u0440\u0430\u043b\u0438 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u0438\u043b\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c wizard.hint.file=\u0421\u0430\u0432\u0435\u0442: \u041c\u043e\u0436\u0435\u0442\u0435 \u0438\u0437\u0430\u0431\u0440\u0430\u0442\u0438 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u043f\u0440\u0435\u0432\u043b\u0430\u0447\u0435\u045a\u0435\u043c \u0438 \u043f\u0443\u0448\u0442\u0430\u045a\u0435\u043c wizard.hint.directory=\u0421\u0430\u0432\u0435\u0442: \u041c\u043e\u0436\u0435\u0442\u0435 \u0434\u0430 \u0438\u0437\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u043f\u0440\u0435\u0432\u043b\u0430\u0447\u0435\u045a\u0435\u043c \u0438 \u043f\u0443\u0448\u0442\u0430\u045a\u0435\u043c MainWindow.menu.help.checkupdate=&\u041f\u0440\u043e\u0432\u0435\u0440\u0438 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0435... TableColumn.header.down=\u041f\u0440\u0435\u0443\u0437\u0435\u0442\u043e TableColumn.header.up={MyTorrentsView.up} ConfigView.section.tracker.passwordenabletorrent.info=\u0417\u0430\u0445\u0442\u0435\u0432\u0430 \u043f\u043e\u0434\u0435\u0441\u0430\u043d \u0411\u0438\u0442 \u0422\u043e\u0440\u0435\u043d\u0442 \u043a\u043b\u0438\u0458\u0435\u043d\u0442 (\u043d\u043f\u0440. \u0410\u0437\u0443\u0440\u0435\u0443\u0441) ConfigView.section.style.confirmationOnExit=\u041f\u043e\u043a\u0430\u0436\u0438 \u043f\u0440\u043e\u0437\u043e\u0440\u0447\u0435 \u0437\u0430 \u043f\u043e\u0442\u0432\u0440\u0434\u0443 \u043f\u0440\u0438 \u0438\u0437\u043b\u0430\u0441\u043a\u0443 MainWindow.dialog.exitconfirmation.title=\u0418\u0437\u043b\u0430\u0437\u0430\u043a \u0438\u0437 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430? MainWindow.dialog.exitconfirmation.text=\u0414\u0430 \u043b\u0438 \u0437\u0430\u0438\u0441\u0442\u0430 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u0437\u0430\u0432\u0440\u0448\u0438\u0442\u0435 \u0440\u0430\u0434 \u0441\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u043c? SystemTray.menu.stopalltransfers=\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0438 &\u0441\u0432\u0435 \u043f\u0440\u0435\u043d\u043e\u0441\u0435 TrayWindow.menu.stopalldownloads=\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0438 \u0441\u0432\u0435 &\u043f\u0440\u0438\u0458\u0435\u043c\u0435 ConfigView.section.tracker.sslport.info=\u041f\u043e\u0433\u043b\u0435\u0434\u0430\u0458\u0442\u0435 \u0427\u041f\u041f \u0437\u0430 \u0432\u0438\u0448\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 wizard.tracker.ssl=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0421\u0421\u041b ConfigView.label.playdownloadfinished=\u041f\u0443\u0441\u0442\u0438 \u0437\u0432\u0443\u043a \u043a\u0430\u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u043d\u043e\u0441 \u0437\u0430\u0432\u0440\u0448\u0438 ConfigView.label.popupdownloadfinished=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u043e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435 \u043e \u043a\u0440\u0430\u0458\u0443 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 ConfigView.label.popupfilefinished=\u041e\u0431\u0430\u0432\u0435\u0441\u0442\u0438 \u043e \u043a\u0440\u0430\u0458\u0443 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 TableColumn.header.pieces=\u0414\u0435\u043b\u043e\u0432\u0438 TableColumn.header.pieces.info=\u0413\u0440\u0430\u0444\u0438\u0447\u043a\u0435 \u0442\u0440\u0430\u043a\u0435 \u043a\u043e\u0458\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0459\u0430\u0458\u0443 \u043f\u0440\u0435\u0443\u0437\u0435\u0442\u0435 \u0434\u0435\u043b\u043e\u0432\u0435 TableColumn.header.completion=\u0417\u0430\u0432\u0440\u0448\u0435\u043d\u043e TableColumn.header.completion.info=\u0413\u0440\u0430\u0444\u0438\u0447\u043a\u0438 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u0443\u0430\u043b\u043d\u0438 \u043f\u0440\u0438\u043a\u0430\u0437 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 ConfigView.section.style.showdownloadbasket=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u043a\u043e\u0440\u043f\u0443 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 (\u0437\u0430 \u043f\u0440\u0435\u0432\u043b\u0430\u0447\u0435\u045a\u0435 \u0438 \u043f\u0443\u0448\u0442\u0430\u045a\u0435) ConfigView.section.style.alwaysShowTorrentFiles=\u0423\u0432\u0435\u043a \u043f\u0440\u0438\u043a\u0430\u0436\u0438 \u0434\u0435\u0442\u0430\u0459\u0435 \u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 wizard.multitracker=\u0414\u043e\u0434\u0430\u0458 \u0432\u0438\u0448\u0435 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 \u0443 \u0442\u043e\u0440\u0435\u043d\u0442 wizard.multitracker.title=\u0412\u0438\u0448\u0435 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 wizard.multitracker.configuration=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 \u0432\u0438\u0448\u0435 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 wizard.multitracker.new=\u041d\u043e\u0432... wizard.multitracker.edit=\u0423\u0440\u0435\u0434\u0438... wizard.multitracker.delete=\u0423\u043a\u043b\u043e\u043d\u0438 wizard.multitracker.group=\u0413\u0440\u0443\u043f\u0430 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 wizard.multitracker.edit.title=\u0423\u0440\u0435\u0434\u043d\u0438\u043a \u0432\u0438\u0448\u0435 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 wizard.multitracker.edit.name=\u0418\u043c\u0435 wizard.multitracker.edit.save=\u0421\u0430\u0447\u0443\u0432\u0430\u0458 wizard.multitracker.edit.newgroup=\u041d\u043e\u0432\u0430 \u0433\u0440\u0443\u043f\u0430 wizard.multitracker.edit.deletegroup=\u0423\u043a\u043b\u043e\u043d\u0438 wizard.multitracker.edit.newtracker=\u041d\u043e\u0432\u0438 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 wizard.multitracker.edit.deletetracker=\u0423\u043a\u043b\u043e\u043d\u0438 wizard.multitracker.edit.edit=\u0423\u0440\u0435\u0434\u0438 wizard.addingmt=\u0414\u043e\u0434\u0430\u0432\u0430\u045a\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u043e \u0432\u0438\u0448\u0435 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 wizard.multitracker.noannounce=\u041e\u0431\u0458\u0430\u0432\u0430 \u0423\u0420\u041b\u0430 \u043a\u043e\u0458\u0438 \u043d\u0438\u0458\u0435 \u0443 \u0412\u0430\u0448\u0435\u043c \u0441\u043f\u0438\u0441\u043a\u0443 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 MyTorrentsView.menu.recheck=\u041f\u0440\u0438\u043d\u0443\u0434\u043d\u0430 &\u043f\u0440\u043e\u0432\u0435\u0440\u0430 iconBar.showDownloadBar.tooltip=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u0442\u0440\u0430\u043a\u0443 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c iconBar.start.tooltip=\u041f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 iconBar.stop.tooltip=\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0438 iconBar.remove.tooltip=\u0423\u043a\u043b\u043e\u043d\u0438 iconBar.openNoDefault.tooltip=\u041e\u0442\u0432\u043e\u0440\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 (\u0431\u0435\u0437 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u043e\u0433 \u0447\u0443\u0432\u0430\u045a\u0430) iconBar.openURL.tooltip=\u041e\u0442\u0432\u043e\u0440\u0438 \u0423\u0420\u041b iconBar.openFolder.tooltip=\u041e\u0442\u0432\u043e\u0440\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c iconBar.new.tooltip=\u041d\u0430\u043f\u0440\u0430\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 iconBar.up.tooltip=\u041f\u043e\u043c\u0435\u0440\u0438 \u043d\u0430 \u0433\u043e\u0440\u0435 iconBar.down.tooltip=\u041f\u043e\u043c\u0435\u0440\u0438 \u043d\u0430 \u0434\u043e\u043b\u0435 iconBar.run.tooltip=\u041e\u0442\u0432\u043e\u0440\u0438 iconBar.host.tooltip=\u0414\u043e\u043c\u0430\u045b\u0438\u043d iconBar.publish.tooltip=\u041e\u0431\u0458\u0430\u0432\u0438 MyTorrentsView.menu.editTracker=&\u0423\u0440\u0435\u0434\u0438 \u0423\u0420\u041b \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 GeneralView.menu.selectTracker=\u0418\u0437\u0431\u043e\u0440 ConfigView.section.stats.xslfile=\u0418\u043c\u0435 XSL \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 ConfigView.section.stats.xslfiledetails=\u041e\u0432\u043e \u045b\u0435 \u0431\u0438\u0442\u0438 \u0443\u043a\u0459\u0443\u0447\u0435\u043d\u043e \u0443 \u0437\u0430\u0433\u043b\u0430\u0432\u0459\u0435 \u0441\u0430 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430\u043c\u0430 \u043f\u043e\u043c\u043e\u045b\u0443 \u043e\u0437\u043d\u0430\u043a\u0435 ConfigView.label.savetorrentbackup=\u0421\u0430\u0447\u0443\u0432\u0430\u0458 \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u0438 \u0443\u043c\u043d\u043e\u0436\u0430\u043a ConfigView.section.tracker.forceport=\u041f\u0440\u0438\u043d\u0443\u0434\u043d\u0430 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0430 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u043e\u0433 \u043f\u043e\u0440\u0442\u0430 \u0437\u0430 \u0441\u043f\u043e\u0459\u0430\u0448\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 ConfigView.section.ipfilter.allow=\u0414\u041e\u0417\u0412\u041e\u041b\u0418 \u043e\u0432\u0435 \u043e\u043f\u0441\u0435\u0433\u0435 (\u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430 \u0441\u0435 \u0417\u0410\u0411\u0420\u0410\u041d\u0418) ConfigView.section.ipfilter.list.inrange=\u0458\u0435 \u0443 \u043e\u043f\u0441\u0435\u0433\u0443 ConfigView.section.ipfilter.list.notinrange=\u043d\u0438\u0458\u0435 \u043d\u0438 \u0443 \u0458\u0435\u0434\u043d\u043e\u043c \u043e\u043f\u0441\u0435\u0433\u0443 ConfigView.section.ipfilter.list.title=\u0417\u0430\u0431\u0440\u0430\u045a\u0435\u043d\u0438 \u0418\u041f\u043e\u0432\u0438 ConfigView.label.allowsameip=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u0432\u0438\u0448\u0435\u0441\u0442\u0440\u0443\u043a\u0443 \u0432\u0435\u0437\u0443 \u0441\u0430 \u0438\u0441\u0442\u0438\u043c \u0418\u041f\u043e\u043c ConfigView.label.allowsameip.tooltip=\u0421\u0430\u043c\u043e \u0443\u043a\u0459\u0443\u0447\u0438\u0442\u0435 \u0430\u043a\u043e \u0432\u0430\u043c \u0417\u0410\u0418\u0421\u0422\u0410 \u0442\u0440\u0435\u0431\u0430.\n\u041e\u0432\u043e \u0458\u0435 \u0437\u0430\u0448\u0442\u0438\u0442\u0430 \u043e\u0434 \u043f\u0438\u0458\u0430\u0432\u0438\u0446\u0430 (\u043a\u0430\u0434\u0430 \u0458\u0435 \u0438\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u043e). ManagerItem.superseeding=\u041d\u0430\u0434-\u0437\u0430\u043c\u0435\u0442\u0430\u043a ConfigView.label.userSuperSeeding=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u043d\u0430\u0434-\u0437\u0430\u043c\u0435\u0442\u0430\u043a PeersView.uniquepiece=\u0414\u0435\u043e (\u043a\u0430\u0434\u0430 \u0440\u0430\u0434\u0438 \u043a\u0430\u043e \u043d\u0430\u0434-\u0437\u0430\u043c\u0435\u0442\u0430\u043a) PeersView.uniquepiece.none=\u041d\u0438\u0458\u0435\u0434\u0430\u043d PeersView.timetosend=\u0412\u0440\u0435\u043c\u0435 \u0437\u0430 \u043f\u043e\u043d\u043e\u0432\u043d\u043e \u0441\u043b\u0430\u045a\u0435 \u0434\u0435\u043b\u0430 (\u043a\u0430\u043e \u043d\u0430\u0434-\u0437\u0430\u043c\u0435\u0442\u0430\u043a) ConfigView.section.style.addurlsilently=\u041f\u0440\u0435\u045b\u0443\u0442\u043d\u043e \u043e\u0442\u0432\u043e\u0440\u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u0438 \u0423\u0420\u041b ConfigView.section.style.addurlsilently.tooltip=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043f\u0440\u0438\u0458\u0435\u043c \u043f\u0440\u043e\u0441\u043b\u0435\u0452\u0435\u043d\u0438\u0445 \u0438\u043b\u0438 \u0441\u043f\u0443\u0448\u0442\u0435\u043d\u0438\u0445 \u0423\u0420\u041b\u043e\u0432\u0430 \u0441\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u043c\u0430, \u0431\u0435\u0437 \u043e\u0442\u0432\u0430\u0440\u0430\u045a\u0430 \u043f\u0440\u043e\u0437\u043e\u0440\u0447\u0435\u0442\u0430 \u0441\u0430 \u0443\u043f\u0438\u0442\u043e\u043c. ConfigView.section.file.decoder.prompt=\u0423\u0432\u0435\u043a \u043f\u0438\u0442\u0430\u0458 \u043a\u0430\u0434\u0430 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 \u0438\u0437\u0431\u043e\u0440 \u043a\u043e\u0434\u0438\u0440\u0430\u045a\u0430 ConfigView.section.file.decoder.prompt.tooltip=\u0423\u0432\u0435\u043a \u043f\u0440\u0438\u043a\u0430\u0436\u0438 \u043f\u0440\u043e\u0437\u043e\u0440\u0447\u0435 \u0441\u0430 \u0438\u0437\u0431\u043e\u0440\u043e\u043c \u043a\u043e\u0434\u0438\u0440\u0430\u045a\u0430 \u043a\u0430\u0434\u0430 \u0458\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430\u043d MyTorrentsView.menu.moveTop=&\u0412\u0440\u0445 MyTorrentsView.menu.moveEnd=&\u0414\u043d\u043e ConfigView.label.moveonlyusingdefaultsave=\u0441\u0430\u043c\u043e \u0430\u043a\u043e \u0458\u0435 \u0443 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u043e\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0443 \u0441\u0430 \u043f\u043e\u0434\u0430\u0446\u0438\u043c\u0430 ConfigView.label.moveonlyusingdefaultsave.tooltip=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0438 \u0441\u0430\u043c\u043e \u0430\u043a\u043e \u0441\u0443 \u043f\u0440\u0435\u0443\u0437\u0435\u0442\u0438 \u043f\u043e\u0434\u0430\u0446\u0438 \u0443 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u043e\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0443 \u0441\u0430 \u043f\u043e\u0434\u0430\u0446\u0438\u043c\u0430 ConfigView.label.watchtorrentfolder=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u0443\u0432\u0435\u0437\u0438 \u043d\u043e\u0432\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 ConfigView.label.watchtorrentfolder.tooltip=\u0420\u0435\u0434\u043e\u0432\u043d\u043e \u043f\u0440\u0435\u0442\u0440\u0430\u0436\u0443\u0458 \u043d\u043e\u0432\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 ConfigView.label.watchtorrentfolderinterval=\u041f\u0435\u0440\u0438\u043e\u0434 ConfigView.label.watchtorrentfolderinterval.tooltip=\u041f\u0430\u0443\u0437\u0430 \u043f\u043e\u0441\u043b\u0435 \u043a\u043e\u0458\u0435 \u045b\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u043f\u043e\u043d\u043e\u0432\u043e \u0431\u0438\u0442\u0438 \u043f\u0440\u0435\u0442\u0440\u0430\u0436\u0435\u043d ConfigView.dialog.choosewatchtorrentfolderpath=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0438\u0437\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0437\u0430 \u0443\u0432\u043e\u0437 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 ConfigView.label.startwatchedtorrentsstopped=\u041f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u0458\u0435 \u043e\u0431\u0443\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u043e ConfigView.label.startwatchedtorrentsstopped.tooltip=\u0414\u043e\u0434\u0430\u0458 \u043d\u043e\u0432\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0443 \u0417\u0410\u0423\u0421\u0422\u0410\u0412\u0409\u0415\u041d\u041e\u041c \u0441\u0442\u0430\u045a\u0443 ConfigView.section.plugins=\u0414\u043e\u0434\u0430\u0446\u0438 wizard.maketorrent.filesize=\u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 wizard.maketorrent.piececount=\u0411\u0440\u043e\u0458 \u0434\u0435\u043b\u043e\u0432\u0430 wizard.maketorrent.piecesize=\u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u0434\u0435\u043b\u043e\u0432\u0430 wizard.maketorrent.auto=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 MainWindow.menu.view.stats=&\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 SpeedView.title.full=\u0410\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442 SpeedView.downloadSpeed.title=\u041f\u0440\u0438\u0458\u0435\u043c SpeedView.uploadSpeed.title=\u0421\u043b\u0430\u045a\u0435 ConfigView.section.style.useSIUnits=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0418\u0415\u0426 \u0458\u0435\u0434\u0438\u043d\u0438\u0446\u0435 (KiB \u0443\u043c\u0435\u0441\u0442\u043e KB \u0438\u0442\u0434.) iconBar.top.tooltip=\u041f\u043e\u043c\u0435\u0440\u0438 \u043d\u0430 \u0432\u0440\u0445 iconBar.bottom.tooltip=\u041f\u043e\u043c\u0435\u0440\u0438 \u043d\u0430 \u0434\u043d\u043e TableColumn.header.health=\u0417\u0434\u0440\u0430\u0432\u0459\u0435 MyTorrentsView.menu.health=\u041e \u0437\u0434\u0440\u0430\u0432\u0459\u0443 health.explain.grey=\u0437\u043d\u0430\u0447\u0438 \u0434\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0438\u0458\u0435 \u043f\u043e\u043a\u0440\u0435\u043d\u0443\u0442 (\u0438 \u0437\u0430 \u0441\u043b\u0430\u045a\u0435 \u0438 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c) health.explain.red=\u0437\u043d\u0430\u0447\u0438 \u0434\u0430 \u043d\u0438\u0441\u0442\u0435 \u043f\u043e\u0432\u0435\u0437\u0430\u043d\u0438 \u043d\u0438 \u0437\u0430 \u0458\u0435\u0434\u0430\u043d \u0443\u0434\u0430\u0459\u0435\u043d\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440, \u043f\u0440\u0438 \u043f\u0440\u0438\u0458\u0435\u043c\u0443 health.explain.blue=\u043f\u0440\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443, \u0437\u043d\u0430\u0447\u0438 \u0434\u0430 \u0458\u043e\u0448 \u043d\u0438\u0441\u0442\u0435 \u043f\u043e\u0432\u0435\u0437\u0430\u043d\u0438 \u043d\u0438 \u043d\u0430 \u0458\u0435\u0434\u0430\u043d \u0440\u0430\u0447\u0443\u043d\u0430\u0440\n\u043f\u0440\u0438 \u043f\u0440\u0438\u0458\u0435\u043c\u0443, \u0437\u043d\u0430\u0447\u0438 \u0434\u0430 \u0441\u0442\u0435 \u043f\u043e\u0432\u0435\u0437\u0430\u043d\u0438 \u043d\u0430 \u043d\u0435\u043a\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0435, \u0430\u043b\u0438 \u0434\u0430 \u0458\u0435 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 \u043e\u0431\u043e\u0440\u0435\u043d health.explain.yellow=\u0437\u043d\u0430\u0447\u0438 \u0434\u0430 \u0458\u0435 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 \u0443 \u0440\u0435\u0434\u0443, \u0434\u0430 \u0441\u0442\u0435 \u043f\u043e\u0432\u0435\u0437\u0430\u043d\u0438 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430, \u0430\u043b\u0438 \u043d\u0435\u043c\u0430\u0442\u0435 \u043d\u0438\u0458\u0435\u0434\u043d\u0443 \u0443\u0434\u0430\u0459\u0435\u043d\u0443 \u0432\u0435\u0437\u0443.\n\u041c\u043e\u0436\u0434\u0430 \u0438\u043c\u0430\u0442\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441\u0430 NAT\u043e\u043c \u0430\u043a\u043e \u0441\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441\u0432\u0435 \u0432\u0440\u0435\u043c\u0435 \u043e\u0441\u0442\u0430\u0458\u0443 \u0443 \u0436\u0443\u0442\u043e\u043c \u0441\u0442\u0430\u045a\u0443 health.explain.green=\u0437\u043d\u0430\u0447\u0438 \u0434\u0430 \u0458\u0435 \u0441\u0432\u0435 \u0443 \u0440\u0435\u0434\u0443 ConfigView.section.style.alwaysRefreshMyTorrents=\u0423\u0432\u0435\u043a \u043e\u0441\u0432\u0435\u0436\u0438 \u043c\u043e\u0458\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=\u041e\u0432\u0430 \u043e\u043f\u0446\u0438\u0458\u0430 \u045b\u0435 \u043e\u0441\u0432\u0435\u0436\u0438\u0442\u0438 \u043f\u0440\u0438\u043a\u0430\u0437 \u041c\u043e\u0458\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0447\u0430\u043a \u0438 \u043a\u0430\u0434\u0430 \u043d\u0438\u0458\u0435 \u043f\u0440\u0438\u043a\u0430\u0437\u0430\u043d (\u043a\u043e\u0440\u0438\u0441\u043d\u043e \u0437\u0430 \u043d\u0435\u043a\u0435 \u0434\u043e\u0434\u0430\u0442\u043a\u0435 \u0437\u0430 mirc) # #2.0.7.0 # security.certtruster.title=\u0423\u043f\u043e\u0437\u043e\u0440\u0435\u045a\u0435 \u043e \u0441\u0438\u0433\u0443\u0440\u043d\u043e\u0441\u043d\u043e\u043c \u0441\u0435\u0440\u0438\u0444\u0438\u043a\u0430\u0442\u0443 security.certtruster.intro=\u0421\u0438\u0433\u0443\u0440\u043d\u043e\u0441\u043d\u0438 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u0458\u0435 \u0438\u0437\u0434\u0430\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0458\u0430 \u0443 \u043a\u043e\u0458\u0443 \u043d\u0435\u043c\u0430\u0442\u0435 \u043f\u043e\u0432\u0435\u0440\u0435\u045a\u0430 security.certtruster.resource=\u0420\u0435\u0441\u0443\u0440\u0441: security.certtruster.issuedto=\u0418\u0437\u0434\u0430\u0442 \u0437\u0430: security.certtruster.issuedby=\u0418\u0437\u0434\u0430\u043e: security.certtruster.prompt=\u0414\u0430 \u043b\u0438 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u0432\u0435\u0440\u0443\u0458\u0435\u0442\u0435 \u043e\u0432\u043e\u043c \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0443? security.certtruster.yes=\u0414\u0430 security.certtruster.no=\u041d\u0435 ConfigView.section.tracker.torrentsperpage=\u041a\u043e\u043b\u0438\u043a\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u043f\u043e \u0441\u0442\u0440\u0430\u043d\u0438 ? [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] MainWindow.menu.file.share=&\u0414\u0435\u0459\u0435\u045a\u0435 MainWindow.menu.file.share.file=&\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430... MainWindow.menu.file.share.dir=\u0414&\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c... MainWindow.menu.file.share.dircontents=&\u0421\u0430\u0434\u0440\u0436\u0430\u0458 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430... MainWindow.menu.file.share.dircontentsrecursive=\u0421\u0430\u0434\u0440\u0436\u0430\u0458 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430... (\u0440\u0435\u043a\u0443\u0440\u0437\u0438\u0432\u0430\u043d) MainWindow.dialog.share.sharefile=\u0418\u0437\u0431\u043e\u0440 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0437\u0430 \u0434\u0435\u0459\u0435\u045a\u0435 MainWindow.dialog.share.sharedir=\u0418\u0437\u0431\u043e\u0440 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430 \u0437\u0430 \u0434\u0435\u0459\u0435\u045a\u0435 MainWindow.dialog.share.sharedircontents=\u0418\u0437\u0431\u043e\u0440 \u0441\u0430\u0434\u0440\u0436\u0430\u0458\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430 \u0437\u0430 \u0434\u0435\u0459\u0435\u045a\u0435 MainWindow.dialog.share.sharedircontents.recursive=\u0420\u0435\u043a\u0443\u0440\u0437\u0438\u0432\u043d\u043e globalmanager.download.remove.veto=\u0423\u043a\u043b\u0430\u045a\u0430\u045a\u0435 \u0458\u0435 \u0437\u0430\u0431\u0440\u0430\u045a\u0435\u043d\u043e plugin.sharing.download.remove.veto=\u041e\u0432\u0430\u0458 \u043f\u0440\u0438\u0458\u0435\u043c \u0458\u0435 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442 \u0434\u0435\u0459\u0435\u043d\u043e\u0433 \u0440\u0435\u0441\u0443\u0440\u0441\u0430.\n\u0414\u0430 \u0443\u043a\u043b\u043e\u043d\u0438\u0442\u0435 \u043f\u0440\u0438\u0458\u0435\u043c, \u0443\u043a\u043b\u043e\u043d\u0438\u0442\u0435 \u043f\u0440\u0438\u0434\u0440\u0443\u0436\u0435\u043d\u043e \u0434\u0435\u0459\u0435\u045a\u0435: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=\u0413\u043b\u0430\u0432\u043d\u0438 ConfigView.section.tracker.web=\u041c\u0440\u0435\u0436\u0430 ConfigView.label.prioritizefirstpiece=\u0421\u0442\u0430\u0432\u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043d\u0430 \u043f\u0440\u0432\u0438 \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u045a\u0438 \u0434\u0435\u043e \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 ConfigView.label.prioritizefirstpiece.tooltip=\u041f\u043e\u043a\u0443\u0448\u0430\u0432\u0430 \u0434\u0430 \u043f\u0440\u0432\u043e \u043f\u0440\u0435\u0443\u0437\u043c\u0435 \u0441\u0430\u043c \u043f\u043e\u0447\u0435\u0442\u0430\u043a \u0438 \u0441\u0430\u043c \u043a\u0440\u0430\u0458 \u0441\u0432\u0430\u043a\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435.\n\u0421\u043b\u0443\u0436\u0438 \u0434\u0430 \u043f\u043e\u0434\u0440\u0436\u0438 \u0440\u0430\u043d\u0438 \u043f\u0440\u0435\u0433\u043b\u0435\u0434 \u0441\u0430\u0434\u0440\u0436\u0430\u0458\u0430. ConfigView.section.file.confirm_data_delete=\u0422\u0440\u0430\u0436\u0438 \u043f\u043e\u0442\u0432\u0440\u0434\u0443 \u043f\u0440\u0435 \u0443\u043a\u043b\u0430\u045a\u0430\u045a\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 ConfigView.section.file.confirm_data_delete.tooltip=\u041f\u043e\u0442\u0432\u0440\u0434\u0438 \u0443\u043a\u043b\u0430\u045a\u0430\u045a\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u043f\u0440\u0438 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0438 \u201e\u0423\u043a\u043b\u043e\u043d\u0438 \u0438 \u043e\u0431\u0440\u0438\u0448\u0438...\u201c TrayWindow.menu.startalldownloads=\u041f\u043e\u043a\u0440\u0435\u043d\u0438 \u0441\u0432\u0435 \u043f\u0440\u0438\u0458\u0435\u043c\u0435 SystemTray.menu.startalltransfers=\u041f\u043e\u043a\u0440\u0435\u043d\u0438 \u0441\u0432\u0435 \u043f\u0440\u0435\u043d\u043e\u0441\u0435 sharing.progress.title=\u0422\u043e\u043a \u0434\u0435\u0459\u0435\u045a\u0430 sharing.progress.hide=\u0421\u0430\u043a\u0440\u0438\u0458 MainWindow.menu.view.myshares=\u0414\u0435\u0459\u0435\u043d\u043e MySharesView.title.full=\u0414\u0435\u0459\u0435\u043d\u043e MySharesView.name=\u0418\u043c\u0435 MySharesView.type=\u0412\u0440\u0441\u0442\u0430 MySharesView.type.file=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0435 MySharesView.type.dir=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c MySharesView.type.dircontents=\u0421\u0430\u0434\u0440\u0436\u0430\u0458\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430 MySharesView.type.dircontentsrecursive=\u0421\u0430\u0434\u0440\u0436\u0430\u0458\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430 (\u0440\u0435\u043a\u0443\u0440\u0437\u0438\u0432\u043d\u043e) MySharesView.menu.remove=\u0423\u043a\u043b\u043e\u043d\u0438 ConfigView.section.tracker.extensions=\u041f\u0440\u043e\u0448\u0438\u0440\u0435\u045a\u0430 ConfigView.section.tracker.sendpeerids=\u041f\u043e\u0448\u0430\u0459\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0442\u0435\u0442 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u0441\u0432\u0438\u043c \u043f\u0440\u0438\u0458\u0435\u043c\u043d\u0438\u0446\u0438\u043c\u0430 ConfigView.section.tracker.enableudp=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u0423\u0414\u041f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0437\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0435 plugin.sharing.torrent.remove.veto=\u041e\u0432\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0458\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 \u0458\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u0438\u0446\u0430 \u0434\u0435\u0459\u0435\u045a\u0430 \u043d\u0435\u043a\u043e\u0433 \u0440\u0435\u0441\u0443\u0440\u0441\u0430.\n\u0414\u0430 \u0431\u0438\u0441\u0442\u0435 \u0443\u043a\u043b\u043e\u043d\u0438\u043b\u0438 \u043f\u0440\u0435\u043d\u043e\u0441 \u0443\u043a\u043b\u043e\u043d\u0438\u0442\u0435 \u043f\u0440\u0438\u0434\u0440\u0443\u0436\u0435\u043d\u043e \u0434\u0435\u0459\u0435\u045a\u0435.: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=\u041f\u0440\u0438\u0458\u0435\u043c \u0441\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0443\u043a\u043b\u043e\u043d\u0438\u0442\u0438 \u043f\u043e\u0448\u0442\u043e \u043d\u0438\u0458\u0435 \u0437\u0430\u0443\u0441\u0442\u0430\u0432\u0459\u0435\u043d plugin.sharing.remove.veto=\u041e\u0432\u043e \u0434\u0435\u0459\u0435\u045a\u0435 \u0458\u0435 \u043f\u043e\u0434-\u0434\u0435\u0459\u0435\u045a\u0435 \u043d\u0435\u043a\u043e\u0433 \u0441\u0430\u0434\u0440\u0436\u0430\u0458\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430 \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0441\u0435 \u0435\u043a\u0441\u043f\u043b\u0438\u0446\u0438\u0442\u043d\u043e \u043e\u0431\u0440\u0438\u0441\u0430\u0442\u0438.\n\u041e\u0431\u0440\u0438\u0448\u0438\u0442\u0435 \u043d\u0430\u0434\u0440\u0435\u0452\u0435\u043d\u043e \u0434\u0435\u0459\u0435\u045a\u0435. GeneralView.label.hash.tooltip=\u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u0434\u0430 \u0443\u043c\u043d\u043e\u0436\u0438\u0442\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0445\u0435\u0448\u0430 \u043d\u0430 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434 ConfigView.section.tracker.maxpeersreturned=\u041d\u0430\u0458\u0432\u0438\u0448\u0435 \u0432\u0440\u0430\u045b\u0435\u043d\u0438\u0445 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.label.serverport=\u041f\u043e\u0440\u0442 \u0437\u0430 \u043f\u0440\u0438\u0445\u0432\u0430\u0442\u0430\u045a\u0435 \u0422\u0426\u041f \u0438\u043b\u0438 \u0423\u0414\u041f \u0432\u0435\u0437\u0435 ConfigView.label.serverport.tooltip=\u041f\u043e\u0440\u0442 \u043c\u043e\u0440\u0430 \u0431\u0438\u0442\u0438 \u0443 \u043e\u043f\u0441\u0435\u0433\u0443 1-65535, \u0438 \u043d\u0435 \u0441\u043c\u0435 \u0431\u0438\u0442\u0438 6880 \u043f\u043e\u0448\u0442\u043e \u0458\u0435 \u0442\u0430\u0458 \u043f\u043e\u0440\u0442 \u043e\u0434\u0440\u0435\u0452\u0435\u043d \u0437\u0430 \u0438\u043d\u0442\u0435\u0440\u043d\u0443 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0443 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430. configureWizard.nat.server.tcp_listen_port=\u0414\u043e\u043b\u0430\u0437\u043d\u0438 \u043f\u043e\u0440\u0442 \u0437\u0430 \u0441\u043b\u0443\u0448\u0430\u045a\u0435 \u0422\u0426\u041f \u0432\u0435\u0437\u0435 ConfigView.section.sharing=\u0414\u0435\u0459\u0435\u045a\u0435 ConfigView.section.sharing.usessl=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0421\u0421\u041b \u0437\u0430 \u0434\u0435\u0459\u0435\u043d\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0435 (\u0437\u0430\u0445\u0442\u0435\u0432\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430) ConfigView.section.style.dropdiraction=\u0414\u0435\u0458\u0441\u0442\u0432\u043e \u043f\u0440\u0438 \u0434\u043e\u0432\u043b\u0430\u0447\u0430\u045a\u0443 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430 ConfigView.section.style.dropdiraction.opentorrents=\u041e\u0442\u0432\u0430\u0440\u0430\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 ConfigView.section.style.dropdiraction.sharefolder=\u0414\u0435\u0459\u0435\u045a\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430 ConfigView.section.style.dropdiraction.sharefoldercontents=\u0414\u0435\u0459\u0435\u045a\u0435 \u0441\u0430\u0434\u0440\u0436\u0430\u0458\u0430 # # 2.0.7.x # Categories.all=\u0421\u0432\u0435 Categories.uncategorized=\u0411\u0435\u0437 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0435 CategoryAddWindow.message=\u0423\u043d\u0435\u0441\u0438\u0442\u0435 \u043d\u043e\u0432\u043e \u0438\u043c\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0435 CategoryAddWindow.title=\u0414\u043e\u0434\u0430\u0458 \u043d\u043e\u0432\u0443 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0443 ConfigView.label.autoSeedingIgnoreInfo=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0435\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0438\u0434\u0443 \u043d\u0430 \u0434\u043d\u043e \u0440\u0435\u0434\u0430 \u0437\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435. \u041e\u043d\u0438 \u0441\u0435 \u043d\u0435 \u043f\u043e\u043a\u0440\u0435\u045b\u0443 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438.\n\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0437\u0430 \u0437\u0430\u043d\u0435\u043c\u0430\u0440\u0438\u0432\u0430\u045a\u0435 \u0441\u0435 \u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u045a\u0443\u0458\u0443 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u043a\u043e\u0458\u0438 \u043e\u0434\u0433\u043e\u0432\u0430\u0440\u0430\u0458\u0443 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0458\u0443\u043c\u0443 \u041f\u0440\u0432\u043e\u0433 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430.\n\u041e\u0441\u0438\u043c \u0430\u043a\u043e \u043d\u0438\u0458\u0435 \u0434\u0440\u0443\u0433\u0430\u0447\u0438\u0458\u0435 \u043d\u0430\u0433\u043b\u0430\u0448\u0435\u043d\u043e, \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442 0 \u0434\u0430 \u0438\u0441\u043a\u0459\u0443\u0447\u0438\u0442\u0435 \u043e\u0432\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u043e. ConfigView.label.directory=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c ConfigView.label.disconnetseed.tooltip=\u041f\u0440\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0430, \u0438\u0441\u043a\u0459\u0443\u0447\u0438 \u0441\u0432\u0435 \u043a\u043b\u0438\u0458\u0435\u043d\u0442\u0435 \u043a\u043e\u0458\u0438 \u0442\u0430\u043a\u043e\u0452\u0435 \u0437\u0430\u043c\u0435\u045b\u0443.\n\u041e\u043d\u0438 \u043d\u0435 \u0442\u0440\u0435\u0431\u0430 \u0434\u0430 \u0440\u0430\u0437\u0433\u043e\u0432\u0430\u0440\u0430\u0458\u0443 \u0441 \u0432\u0430\u043c\u0430. ConfigView.label.ignoreCase=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 \u0441\u043b\u043e\u0432\u0430 ConfigView.label.ignoreSeeds=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 \u043d\u0430\u0458\u043c\u0430\u045a\u0435 ConfigView.label.importdirectory=\u0423\u0432\u0435\u0437\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c ConfigView.label.minPeersToBoostNoSeeds.tooltip=\u0421\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0431\u0435\u0437 \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u0438 \u0441\u0430 \u043c\u0430\u045a\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u043e\u0434 \u0431\u0440\u043e\u0458\u0430 \u043a\u043e\u0433 \u0441\u0442\u0435 \u0437\u0430\u0434\u0430\u043b\u0438\n\u0431\u0438\u045b\u0435 \u043f\u043e\u043c\u0435\u0440\u0435\u043d\u0438 \u043a\u0430 \u0434\u043d\u0443 \u0440\u0435\u0434\u0430. ConfigView.label.minPeersToBoostNoSeeds=\u0423\u043c\u0430\u045a\u0438 \u0440\u0430\u043d\u0433 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0430 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 \u043c\u0430\u045a\u0435 \u043e\u0434 ConfigView.label.minSeedingTime.tooltip=\u0420\u0430\u043d\u0433 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0430 \u043c\u043e\u0436\u0435 \u0447\u0435\u0441\u0442\u043e \u0434\u0430 \u043e\u0441\u0446\u0438\u043b\u0443\u0458\u0435 \u0443 \u043a\u0440\u0430\u0442\u043a\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0441\u043a\u043e\u043c \u043f\u0435\u0440\u0438\u043e\u0434\u0443, \u0448\u0442\u043e \u043f\u043e\u043d\u0435\u043a\u0430\u0434 \u0434\u043e\u0432\u0435\u0434\u0435 \u0434\u043e \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u043e\u0433 \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u045a\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430, \u043a\u0430\u043a\u043e \u0431\u0438 \u0441\u0435 \u043a\u0430\u0441\u043d\u0438\u0458\u0435 \u0441\u0430\u043c\u043e \u0437\u0430\u0443\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0438 \u043f\u043e\u043d\u043e\u0432\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0443 \u0440\u0435\u0434.\n\u041e\u0432\u043e \u0441\u0440\u0435\u0452\u0443\u0458\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0444\u043e\u0440\u0441\u0438\u0440\u0430\u045a\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0434\u0430 \u043d\u0430\u0441\u0442\u0430\u0432\u0435 \u0434\u0430 \u0437\u0430\u043c\u0435\u045b\u0443 \u043e\u0434\u0440\u0435\u0452\u0435\u043d\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0441\u043a\u0438 \u043f\u0435\u0440\u0438\u043e\u0434. \u041f\u0430 \u0438\u043f\u0430\u043a, \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0443\u0441\u0442\u0430\u0432\u0438\u0442\u0438 \u0440\u0443\u0447\u043d\u043e \u0430\u043a\u043e \u0436\u0435\u043b\u0438\u0442\u0435. ConfigView.label.minSeedingTime=\u041d\u0430\u0458\u043c\u0430\u045a\u0435 \u0432\u0440\u0435\u043c\u0435 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0430 \u0443 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u043c\u0430 ConfigView.label.minSpeedForActiveDL.tooltip=\u041f\u0440\u043e\u0440\u0435\u0437 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c \u0441\u0435 \u0443\u0432\u0435\u043a \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0437\u0430 \u043f\u0440\u0432\u0438\u0445 30 \u0441\u0435\u043a\u0443\u043d\u0434\u0438 \u043a\u0430\u0434\u0430 \u0441\u0435 \u0437\u0430\u043f\u043e\u0447\u043d\u0435 \u043d\u0435\u043f\u043e\u0442\u043f\u0443\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442. ConfigView.label.minSpeedForActiveDL=\u041d\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0458 \u0434\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u043f\u0440\u043e\u0440\u0435\u0437 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c \u0430\u043a\u043e \u0458\u0435 \u0431\u0440\u0437\u0438\u043d\u0430 \u043c\u0430\u045a\u0430 \u043e\u0434 ConfigView.label.peers=\u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 ConfigView.label.queue.debuglog=\u0417\u0430\u043f\u0438\u0441\u0443\u0458 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u043e \u0433\u0440\u0435\u0448\u043a\u0430\u043c\u0430 ConfigView.label.queue.debuglog.info=\u0414\u043e\u0434\u0430\u0458\u0435 \u0440\u0435\u0434 \u0441\u0430 \u043f\u043e\u0434\u0430\u0446\u0438\u043c\u0430 \u043e \u0433\u0440\u0435\u0448\u043a\u0430\u043c\u0430 \u0443 \u043a\u043e\u043d\u0437\u043e\u043b\u043d\u0438 \u0438\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u043d\u0438\u043a \u0443 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443.\n\u0418\u0430\u043a\u043e \u0458\u0435 \u043a\u0440\u0438\u043f\u0442\u0438\u0447\u0430\u043d, \u043e\u0432\u0430\u0458 \u0440\u0435\u0434 \u0441\u0430 \u043f\u043e\u0434\u0430\u0446\u0438\u043c\u0430 \u0433\u043e\u0432\u043e\u0440\u0438 \u043e \u0441\u0442\u0430\u045a\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0438 \u0437\u0430\u0448\u0442\u043e \u0440\u0430\u0434\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0440\u0430\u0434\u0435. ConfigView.label.queue.minQueueingShareRatio=\u041d\u0435 \u0441\u0442\u0430\u0432\u0459\u0430\u0458 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0443 \u0440\u0435\u0434 \u043d\u0438\u0442\u0438 \u0438\u0445 \u0437\u0430\u0443\u0441\u0442\u0430\u0432\u0459\u0430\u0458 \u0434\u043e\u043a \u043e\u0434\u043d\u043e\u0441 \u0434\u0435\u0459\u0435\u045a\u0430 \u043d\u0435 \u043f\u043e\u0441\u0442\u0430\u043d\u0435 ConfigView.label.ratio=\u043e\u0434\u043d\u043e\u0441 ConfigView.label.removeOnStop=\u0423\u043a\u043b\u043e\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0441\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u0448\u0442\u043e \u0441\u0435 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u0437\u0430\u0443\u0441\u0442\u0430\u0432\u0438 ConfigView.label.savedirectory=\u0421\u0430\u0447\u0443\u0432\u0430\u0458 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c ConfigView.label.seeding.autoReposition.tooltip=\u0410\u043a\u043e \u0458\u0435 \u0443\u043a\u0459\u0443\u0447\u0435\u043d, \u0440\u0435\u0434\u043e\u0441\u043b\u0435\u0434 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 (\u043a\u043e\u043b\u043e\u043d\u0430 \u201e\u0411\u0440.\u201c) \u045b\u0435 \u0431\u0438\u0442\u0438 \u043f\u0440\u043e\u043c\u0435\u045a\u0435\u043d\u0430 \u0442\u0430\u043a\u043e \u0434\u0430 \u043e\u0434\u0433\u043e\u0432\u0430\u0440\u0430 \u0440\u0435\u0434\u043e\u0441\u043b\u0435\u0434\u0443 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0430\n\u041e\u0432\u043e \u0458\u0435 \u043a\u043e\u0440\u0438\u0441\u043d\u043e \u0430\u043a\u043e \u043d\u0435 \u0432\u043e\u043b\u0438\u0442\u0435 \u0434\u0430 \u0432\u0438\u0434\u0438\u0442\u0435 \u0440\u0435\u0434\u043e\u0441\u043b\u0435\u0434 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0430, \u0430\u043b\u0438 \u0438 \u0434\u0430\u0459\u0435 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u0437\u043d\u0430\u0442\u0435 \u0440\u0435\u0434\u043e\u0441\u043b\u0435\u0434 \u043f\u043e \u043a\u043e\u043c\u0435 \u045b\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0431\u0438\u0442\u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u043d\u0438. ConfigView.label.seeding.autoReposition=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043f\u0440\u0435\u043c\u0435\u0441\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u043f\u0440\u0435\u043c\u0430 \u0440\u0435\u0434\u043e\u0441\u043b\u0435\u0434\u0443 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0430 ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u0427\u0435\u0441\u0442\u043e \u0441\u0435 \u0434\u0435\u0448\u0430\u0432\u0430 \u0434\u0430 \u0430\u043a\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0438\u043c\u0430\u0458\u0443 \u0441\u0430 \u043c\u0430\u043b\u0438 \u0431\u0440\u043e\u0458\u0435 \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 \u0438 \u0432\u0435\u043b\u0438\u043a\u0438\u043c \u0431\u0440\u043e\u0458\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430, \u0434\u0430 \u0446\u0435\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043a \u043d\u0438\u0458\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430\u043d \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c.\n\u041f\u0440\u0435\u043c\u0430 \u0442\u043e\u043c\u0435, \u043c\u043e\u0436\u0434\u0430 \u043d\u0435 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u0440\u0430\u0432\u0435\u045b\u0438 \u0441\u0435 \u0434\u0430 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 \u043f\u043e\u0442\u043f\u0443\u043d\u0430 \u043a\u043e\u043f\u0438\u0458\u0430, \u0448\u0442\u043e \u0431\u0438 \u043d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u043e \u0441\u043c\u0430\u045a\u0438\u043b\u043e \u0440\u0435\u0434\u043e\u0441\u043b\u0435\u0434 ConfigView.label.seeding.fakeFullCopySeedStart=\u0430\u043b\u0438 \u0441\u0430\u043c\u043e \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 \u0431\u0430\u0440 ConfigView.label.seeding.ignore=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 ConfigView.label.seeding.ignore0Peers=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 0 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 ConfigView.label.seeding.ignoreRatioPeers=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 \u0431\u0430\u0440 \u0458\u0435\u0434\u043d\u0438\u043c \u0437\u0430\u043c\u0435\u0442\u043a\u043e\u043c \u043d\u0430 \u0441\u0432\u0430\u043a\u0438\u0445 ConfigView.label.seeding.ignoreShareRatio=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 \u043e\u0434\u043d\u043e\u0441\u043e\u043c \u0434\u0435\u0459\u0435\u045a\u0430 ConfigView.label.seeding.ignore.header.evenFirstPriority=\u041f\u0440\u0438\u043c\u0435\u043d\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u041f\u0440\u0432\u043e\u0433 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 ConfigView.label.seeding.ignore.header.rule=\u041f\u0440\u0430\u0432\u0438\u043b\u043e ConfigView.label.seeding.ignore.header.value=\u0412\u0440\u0435\u0434\u043d\u043e\u0441\u0442 ConfigView.label.seeding.firstPriority.info=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u041f\u0440\u0432\u043e\u0433 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 \u045b\u0435 \u0431\u0438\u0442\u0438 \u0443\u0432\u0435\u043a \u043d\u0430 \u0432\u0440\u0445\u0443 \u0440\u0435\u0434\u0430.\n\u041c\u0430 \u043a\u043e\u0458\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u043a\u043e\u0458\u0438 \u0438\u043c\u0430 \u041f\u0440\u0432\u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043d\u0435\u045b\u0435 \u0431\u0438\u0442\u0438 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u0437\u0430\u0443\u0441\u0442\u0430\u0432\u0459\u0430\u043d \u0438 \u0441\u0442\u0430\u0432\u0459\u0430\u043d \u0443 \u0440\u0435\u0434.\n\u0422\u043e\u0440\u0435\u043d\u0442 \u041f\u0440\u0432\u043e\u0433 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 \u045b\u0435 \u0437\u0430\u0443\u0437\u0435\u0442\u0438 \u043f\u0440\u043e\u0440\u0435\u0437 \u0437\u0430 \u0438\u0441\u0442\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0440\u0438\u0458\u0435\u043c \u0430\u043a\u043e \u0458\u0435 \u043d\u0435\u043e\u043f\u0445\u043e\u0434\u043d\u043e. ConfigView.label.seeding.firstPriority.FP=\u041f\u0440\u0432\u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.label.seeding.firstPriority=\u041f\u0440\u0432\u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0438\u0434\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u043c\u0430 \u0441\u0430 ConfigView.label.seeding.firstPriority.following=\u043e\u0434 \u043d\u0430\u0440\u0435\u0434\u043d\u0438\u0445: ConfigView.label.seeding.firstPriority.shareRatio=\u041e\u0434\u043d\u043e\u0441 \u0434\u0435\u0459\u0435\u045a\u0430 \u0438\u0441\u043f\u043e\u0434 ConfigView.label.seeding.firstPriority.seedingMinutes=\u041f\u0440\u043e\u0442\u0435\u043a\u043b\u043e \u0432\u0440\u0435\u043c\u0435 \u043e\u0434 \u043f\u0440\u043e\u043c\u0435\u043d\u0435 \u0441\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u043d\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 ConfigView.label.seeding.firstPriority.DLMinutes=\u041f\u0440\u043e\u0442\u0435\u043a\u043b\u043e \u0432\u0440\u0435\u043c\u0435 \u043e\u0434 \u043f\u043e\u0447\u0435\u0442\u043a\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 ConfigView.label.seeding.numPeersAsFullCopy.tooltip=\u0410\u043a\u043e \u0441\u0435 \u043f\u0440\u0435\u0442\u0432\u0430\u0440\u0430\u0442\u0435 \u0434\u0430 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 1 \u043f\u0443\u043d\u0430 \u043a\u043e\u043f\u0438\u0458\u0430 \u043d\u0430 X \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430, \u043e\u043d\u0434\u0430 \u0441\u043c\u0430\u045a\u0443\u0458\u0435\u0442\u0435 \u0440\u0435\u0434\u043e\u0441\u043b\u0435\u0434 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0441\u0430 \u0432\u0435\u043b\u0438\u043a\u0438\u043c \u0431\u0440\u043e\u0458\u0435\u043c \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430.\n\u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u0441\u0430 \u0432\u0435\u043b\u0438\u043a\u0438\u043c \u0431\u0440\u043e\u0458\u0435\u043c \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u043d\u0430\u0458\u0432\u0435\u0440\u043e\u0432\u0430\u0442\u043d\u0438\u0458\u0435 \u043e\u0441\u0442\u0432\u0430\u0440\u0443\u0458\u0443 \u0438 \u0432\u0435\u043b\u0438\u043a\u0438 \u043f\u0440\u043e\u0442\u043e\u043a.\n\u0422\u043e \u043d\u0435 \u043c\u0435\u045a\u0430 \u043d\u0438\u0458\u0435\u0434\u0430\u043d \u043f\u0440\u0438\u043a\u0430\u0437 \u043e \u0431\u0440\u043e\u0458\u0443 \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430. ConfigView.label.seeding.numPeersAsFullCopy=\u041f\u0440\u0435\u0442\u0432\u0430\u0440\u0430\u045a\u0435 \u0434\u0430 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 1 \u043f\u0443\u043d\u0430 \u043a\u043e\u043f\u0438\u0458\u0430 \u0437\u0430 \u0441\u0432\u0430\u043a\u0438\u0445\n[0: \u0431\u0435\u0437 \u043f\u0440\u0435\u0442\u0432\u0430\u0440\u0430\u045a\u0430] ConfigView.label.seeding.preferLargerSwarms.tooltip=\u0410\u043a\u043e \u0443\u0433\u043b\u0430\u0432\u043d\u043e\u043c \u0437\u0430\u043c\u0435\u045b\u0435\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 \u043a\u043e\u0458\u0438 \u0441\u0443 \u201e\u0437\u0430\u0433\u043b\u0430\u0432\u0459\u0435\u043d\u0438\u201c, \u0431\u0438\u0440\u0430\u045a\u0435 \u0432\u0435\u045b\u0438\u0445 \u0440\u043e\u0458\u0435\u0432\u0430 \u0438\u043c\u0430 \u0441\u043c\u0438\u0441\u043b\u0430\n\u041a\u0430\u0434\u0430 \u0443\u0433\u043b\u0430\u0432\u043d\u043e\u043c \u0437\u0430\u043c\u0435\u045b\u0435\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u043a\u043e\u0458\u0438 \u0441\u0443 \u0448\u0438\u0440\u043e\u043a\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438, \u0431\u0438\u0440\u0430\u045a\u0435 \u043c\u0430\u045a\u0438\u0445 \u0440\u043e\u0458\u0435\u0432\u0430 \u0438\u043c\u0430 \u0432\u0438\u0448\u0435 \u0441\u043c\u0438\u0441\u043b\u0430. ConfigView.label.seeding.preferLargerSwarms=\u041a\u0430\u0434\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0438\u043c\u0430\u0458\u0443 \u0438\u0441\u0442\u0438 \u0440\u0435\u0434, \u0431\u0438\u0440\u0430\u0458 \u043c\u0430\u045a\u0435 \u0432\u0435\u045b\u0435 \u0440\u043e\u0458\u0435\u0432\u0435 ConfigView.label.seeding.rankType.none.tooltip=\u0420\u0435\u0434\u043e\u0441\u043b\u0435\u0434 \u0458\u0435 \u0437\u0430\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u0438 \u0411\u0440. ConfigView.label.seeding.rankType.none=\u041d\u0438\u0458\u0435\u0434\u0430\u043d ConfigView.label.seeding.rankType.peerSeed.options=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 \u043e\u0434\u043d\u043e\u0441\u0430 \u0437\u0430\u043c\u0435\u0446\u0438:\u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438 ConfigView.label.seeding.rankType.peerSeed.tooltip=\u0412\u0435\u045b\u0438 \u043e\u0434\u043d\u043e\u0441 = \u0432\u0435\u045b\u0438 \u0440\u0430\u043d\u0433 ConfigView.label.seeding.rankType.peerSeed=\u041e\u0434\u043d\u043e\u0441 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438:\u0437\u0430\u043c\u0435\u0446\u0438 ConfigView.label.seeding.rankType.seed.fallback=\u041f\u0440\u0435\u0431\u0430\u0446\u0438\u0432\u0430\u045a\u0435 \u043d\u0430 \u043e\u0434\u043d\u043e\u0441 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438:\u0437\u0430\u043c\u0435\u0446\u0438 \u043f\u043e\u0441\u043b\u0435\n[0: \u043d\u0438\u043a\u0430\u0434 \u043d\u0435 \u043f\u0440\u0435\u0431\u0430\u0446\u0443\u0458] ConfigView.label.seeding.rankType.seed.options=\u041e\u043f\u0446\u0438\u0458\u0435 \u0443 \u0432\u0435\u0437\u0438 \u0441\u0430 \u043f\u0440\u0435\u0431\u0440\u0430\u0458\u0430\u045a\u0435\u043c \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 ConfigView.label.seeding.rankType.seed.tooltip=\u041c\u0430\u045a\u0435 \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 = \u0432\u0435\u045b\u0438 \u0440\u0435\u0434\u043e\u0441\u043b\u0435\u0434 ConfigView.label.seeding.rankType.seed=\u0421\u0430\u043c\u043e \u043f\u0440\u0435\u0431\u0440\u0430\u0458\u0430\u045a\u0435 \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 ConfigView.label.seeding.rankType.timedRotation.tooltip=\u0421\u0432\u0438 \u0443\u0432\u0440\u0448\u045b\u0435\u043d\u0438 \u043f\u043e\u0442\u043f\u0443\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u045b\u0435 \u0441\u0435 \u0440\u043e\u0442\u0438\u0440\u0430\u0442\u0438 \u0443 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443.\n\u0422\u0440\u0430\u0458\u0430\u045a\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0430 \u043e\u0434\u0433\u043e\u0432\u0430\u0440\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0443 \u201e\u043d\u0430\u0458\u043c\u0430\u045a\u0435 \u0432\u0440\u0435\u043c\u0435 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0430\u201c ConfigView.label.seeding.rankType.timedRotation=\u0412\u0440\u0435\u043c\u0435\u043d\u0441\u043a\u0430 \u0440\u043e\u0442\u0430\u0446\u0438\u0458\u0430 ConfigView.label.seeding.rankType.tooltip=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u0441\u0430 \u043d\u0430\u0458\u0432\u0438\u0448\u0438\u043c \u0440\u0435\u0434\u043e\u0441\u043b\u0435\u0434\u043e\u043c \u0441\u0435 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043f\u043e\u043a\u0440\u0435\u045b\u0443.\n\u041a\u0430\u0434\u0430 \u043d\u0435\u043a\u0438 \u0434\u0440\u0443\u0433\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u043e\u0431\u0438\u0458\u0435 \u0432\u0435\u045b\u0438 \u0440\u0435\u0434\u043e\u0441\u043b\u0435\u0434, \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0438\u0436\u0435\u0433 \u0440\u0435\u0434\u043e\u0441\u043b\u0435\u0434\u0430 \u0441\u0435 \u0437\u0430\u0443\u0441\u0442\u0430\u0432\u0459\u0430 \u0438 \u0432\u0440\u0430\u045b\u0430 \u0443 \u0440\u0435\u0434.\n\n\u0421\u0430\u043c\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0443 \u0440\u0435\u0434\u0443 \u0441\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438 \u0437\u0430 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u043e \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435.\n\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441\u0435 \u043d\u0438\u043a\u0430\u0434\u0430 \u043d\u0435 \u043f\u043e\u043a\u0440\u0435\u045b\u0443 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438. ConfigView.label.seeding.rankType=\u041f\u043e\u0440\u0435\u0452\u0430\u0458 \u043f\u043e\u0442\u043f\u0443\u043d\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0437\u0430 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u043e \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u043f\u0440\u0435\u043c\u0430: ConfigView.label.stopAfterMinutes=\u0408\u0435\u0434\u043d\u043e\u043c \u043f\u0440\u0435\u0431\u0430\u0447\u0435\u043d \u043d\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435, \u043e\u0431\u0443\u0441\u0442\u0430\u0432\u0438 \u043f\u043e\u0441\u043b\u0435 \u043e\u0432\u043e\u043b\u0438\u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0430 ConfigView.label.switchpriority.tooltip=\u041d\u0438\u0437\u0430\u043a \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0441\u043c\u0430\u045a\u0443\u0458\u0435 \u043a\u043e\u043b\u0438\u0447\u0438\u043d\u0443 \u043f\u0440\u043e\u043f\u0443\u0441\u043d\u0435 \u043c\u043e\u045b\u0438 \u043a\u043e\u0458\u0430 \u0458\u0435 \u0434\u043e\u0434\u0435\u0459\u0435\u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0443. ConfigView.pluginlist.info=\u041d\u0430\u0432\u0435\u0434\u0435\u043d\u0438 \u0434\u043e\u0434\u0430\u0446\u0438 \u0441\u0443 \u043f\u0440\u043e\u043d\u0430\u0452\u0435\u043d\u0438. \u041d\u0435\u043a\u0438 \u0434\u043e\u0434\u0430\u0446\u0438 \u043d\u0435 \u043c\u043e\u0440\u0430\u0458\u0443 \u0438\u043c\u0430\u0442\u0438 \u0458\u0435\u0437\u0438\u0447\u043a\u0435 \u0441\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0438\u043c\u0430. ConfigView.pluginlist.noplugins=\u041d\u0438\u0458\u0435\u0434\u0430\u043d \u0434\u043e\u0434\u0430\u0442\u0430\u043a \u043d\u0438\u0458\u0435 \u043f\u0440\u043e\u043d\u0430\u0452\u0435\u043d. ConfigView.section.pluginslist=\u0421\u043f\u0438\u0441\u0430\u043a ConfigView.section.queue.seeding=\u0417\u0430\u043c\u0435\u0442\u0430\u045a\u0435 ConfigView.section.queue.seeding.autoStarting=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u043e \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 ConfigView.section.queue.seeding.ignore=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 ConfigView.section.queue.seeding.firstPriority=\u041f\u0440\u0432\u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.section.queue.main=\u0413\u043b\u0430\u0432\u043d\u0438 ConfigView.section.queue=\u0420\u0435\u0434 ConfigView.section.torrents=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 ConfigView.text.all=\u0441\u0432\u0435 ConfigView.text.hours=\u0441\u0430\u0442\u0438 ConfigView.text.ignoreRule=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u043e ConfigView.text.ignore=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 ConfigView.text.minutes=\u043c\u0438\u043d\u0443\u0442\u0430 ConfigView.text.neverIgnore=\u041d\u0438\u043a\u0430\u0434\u0430 \u043d\u0435 \u0437\u0430\u043d\u0435\u043c\u0430\u0440\u0443\u0458 ConfigView.text.any=\u0431\u0438\u043b\u043e \u043a\u043e\u0458\u0438 DownloadManager.error.datamissing=\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0458\u0443 \u043f\u043e\u0434\u0430\u0446\u0438 MainWindow.menu.file.open.torrentforseeding=\u0422\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u043e\u0442\u0435\u043a\u0430... (\u0437\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435) MainWindow.menu.language.refresh=&\u041e\u0441\u0432\u0435\u0436\u0438 ManagerItem.forced=\u041f\u0440\u0438\u043d\u0443\u0452\u0435\u043d ManagerItem.queued=\u0417\u0430\u043a\u0430\u0437\u0430\u043d\u043e MySeedersView.header=\u0417\u0430\u0432\u0440\u0448\u0435\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.availability.info=\u0431\u0440. \u043f\u0440\u0438\u043c\u0435\u045b\u0435\u043d\u0438\u0445 \u043a\u043e\u043f\u0438\u0458\u0430 TableColumn.header.availability=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442 TableColumn.header.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0430 MyTorrentsView.header=\u041d\u0435\u043f\u043e\u0442\u043f\u0443\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.maxuploads=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u0431\u0440\u043e\u0458 \u0441\u043b\u0430\u045a\u0430 MyTorrentsView.menu.category.delete=&\u0423\u043a\u043b\u043e\u043d\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0443 MyTorrentsView.menu.forceStart=&\u041f\u0440\u0438\u043d\u0443\u0434\u043d\u043e \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 MyTorrentsView.menu.queue=&\u0420\u0435\u0434 MyTorrentsView.menu.setCategory.add=&\u0414\u043e\u0434\u0430\u0458 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0443... MyTorrentsView.menu.setCategory=\u0414\u043e\u0434\u0435\u043b\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0443 TableColumn.header.savepath=\u0421\u0430\u0447\u0443\u0432\u0430\u0458 \u0441\u0442\u0430\u0437\u0443 TableColumn.header.SeedingRank=\u0420\u0435\u0434\u043e\u0441\u043b\u0435\u0434 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0430 TableColumn.header.totalspeed.info=\u0423\u043a\u0443\u043f\u043d\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u0432\u0438\u0445 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u0441 \u043a\u043e\u0458\u0438\u043c \u0441\u0442\u0435 \u0443 \u0432\u0435\u0437\u0438 TableColumn.header.totalspeed=\u0423\u043a\u0443\u043f\u043d\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 splash.initializePlugins=\u041f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u0434\u043e\u0434\u0430\u0442\u0430\u043a\u0430 StartStopRules.SPratioMet=\u0417:\u0420 \u043e\u0434\u043d\u043e\u0441 \u0443 \u0440\u0435\u0434\u0443 StartStopRules.FP0Peers=\u0424\u041f / 0 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 StartStopRules.0Peers=0 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 StartStopRules.numSeedsMet=\u0411\u0440\u043e\u0458 \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 \u0458\u0435 \u0443 \u0440\u0435\u0434\u0443 StartStopRules.ratioMet=\u0420\u0430\u0447:\u0417\u0430\u043c\u0435\u0446\u0438 \u0443 \u0440\u0435\u0434\u0443 StartStopRules.shareRatioMet=\u041e\u0434\u043d\u043e\u0441 \u0434\u0435\u0459\u0435\u045a\u0430 \u0458\u0435 \u0443 \u0440\u0435\u0434\u0443 StartStopRules.waiting=\u0427\u0435\u043a\u0430\u045a\u0435 StartStopRules.firstPriority=1. \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\u0414\u0435\u0459\u0435\u045a\u0435 \u0441\u0430\u0434\u0440\u0436\u0430\u0458\u0430 (\u0438 \u043f\u043e\u0434-\u0434\u0438\u0440\u043e\u0432\u0430) DownloadManager.error.unabletostartserver=\u041d\u0438\u0458\u0435 \u043c\u043e\u0433\u0443\u045b\u0435 \u043f\u043e\u043a\u0440\u0435\u043d\u0443\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 - \u043f\u0440\u0435\u0433\u043b\u0435\u0434\u0430\u0458\u0442\u0435 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0434\u043e\u043b\u0430\u0437\u043d\u043e\u0433 \u043f\u043e\u0440\u0442\u0430 \u0438 \u0434\u043e\u0437\u0432\u043e\u043b\u0435 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430 \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d\u0443 \u0437\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c \u043a\u043e\u0458\u0438 \u0442\u0440\u0435\u0431\u0430 \u0434\u0430 \u0431\u0443\u0434\u0435 \u0441\u0435\u0440\u0432\u0435\u0440 GeneralView.label.creationdate=\u041d\u0430\u043f\u0440\u0430\u0432\u0459\u0435\u043d\u043e : ConfigView.section.tracker.announcescrapepercentage=\u041f\u0435\u0440\u0438\u043e\u0434 \u0447\u0438\u0448\u045b\u0435\u045a\u0430 \u043a\u0430\u043e \u043f\u0440\u043e\u0446\u0435\u043d\u0430\u0442 \u043d\u0430\u0458\u0430\u0432\u0435\n\u043d\u043f\u0440. 200 = 2:1. 0 = \u043d\u0435\u043a\u0430 \u0443\u0434\u0430\u0459\u0435\u043d\u0438 \u0440\u0430\u0447. \u043e\u0434\u043b\u0443\u0447\u0438 ManagerItem.stopping=\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0459\u0430\u045a\u0435 ConfigView.section.tracker.announcecacheperiod=\u041a\u0435\u0448\u0438\u0440\u0430\u0458 \u043d\u0430\u0458\u0430\u0432\u0443 (\u043c\u0438\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u0435) ConfigView.section.tracker.scrapecacheperiod=\u041e\u0447\u0438\u0441\u0442\u0438 \u043a\u0435\u0448 (\u043c\u0438\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u0435) ConfigView.section.tracker.scrapeandcache=\u041e\u0447\u0438\u0441\u0442\u0438 \u0438 \u043a\u0435\u0448\u0438\u0440\u0430\u0458 ConfigView.section.tracker.announcecacheminpeers=\u041d\u0430\u0458\u0430\u0432\u0438 \u043a\u0435\u0448 MyTrackerView.scrapes=\u0427\u0438\u0448\u045b\u0435\u045a\u0430 fileDownloadWindow.retry=\u041f\u043e\u043d\u043e\u0432\u043d\u0438 \u043f\u043e\u043a\u0443\u0448\u0430\u0458 MyTrackerView.bytesin=\u0423\u043b. \u0431\u0430\u0458\u0442\u043e\u0432\u0430 MyTrackerView.bytesinave=\u0421\u0440. \u0443\u043b\u0430\u0437 MyTrackerView.bytesout=\u0418\u0437\u043b. \u0431\u0430\u0458\u0442\u043e\u0432\u0430 MyTrackerView.bytesoutave=\u0421\u0440. \u0438\u0437\u043b\u0430\u0437 ConfigView.section.file.max_open_files=\u041d\u0430\u0458\u0432\u0438\u0448\u0435 \u043e\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0445 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0437\u0430 \u0443\u043f\u0438\u0441 \u0438\u043b\u0438 \u0447\u0438\u0442\u0430\u045a\u0435\n[0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.file.max_open_files.tooltip=\u041a\u043e\u0440\u0438\u0441\u043d\u043e \u0430\u043a\u043e \u043f\u0440\u0438\u043c\u0430\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 \u0441\u0442\u043e\u0442\u0438\u043d\u0430\u043c\u0430 \u0438\u043b\u0438 \u0445\u0438\u0459\u0430\u0434\u0430\u043c\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0438 \u0430\u043a\u043e \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0435\u0442\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0435 \u0443 \u0431\u0440\u043e\u0458\u0443 \u043e\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0445 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0433 \u0441\u0438\u0441\u0442\u0435\u043c\u0430. ConfigView.section.proxy=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0437\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u043a\u0430 (proxy) ConfigView.section.proxy.enable_proxy=\u0423\u043a\u0459\u0443\u0447\u0438 \u0437\u0430\u0441\u0442\u0443\u043f\u0430\u045a\u0435 (proxying) \u0440\u0430\u0437\u0433\u043e\u0432\u043e\u0440\u0430 \u0441\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0438\u043c\u0430 [\u0442\u0440\u0430\u0436\u0438 \u0440\u0435\u0441\u0442\u0430\u0440\u0442] ConfigView.section.proxy.host=\u0414\u043e\u043c\u0430\u045b\u0438\u043d ConfigView.section.proxy.port=\u041f\u043e\u0440\u0442 ConfigView.section.proxy.username=\u041a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e \u0438\u043c\u0435 ConfigView.section.proxy.password=\u041b\u043e\u0437\u0438\u043d\u043a\u0430 ConfigView.section.proxy.enable_socks=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0441\u0435 SOCKS \u0437\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u043a (proxy) wizard.createtorrent.extrahashes=\u0414\u043e\u0434\u0430\u0458 \u0445\u0435\u0448\u0435\u0432\u0435 \u0437\u0430 \u0434\u0440\u0443\u0433\u0435 \u043c\u0440\u0435\u0436\u0435 (\u043d\u043f\u0440. \u0413\u043d\u0443\u0442\u0435\u043b\u04302, eDonkey2000) GeneralView.label.connected=\u043f\u043e\u0432\u0435\u0437\u0430\u043d GeneralView.label.in_swarm=\u0443 \u0440\u043e\u0458\u0443 ManagerItem.initializing=\u041f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 AlertMessageBox.error=\u0413\u0440\u0435\u0448\u043a\u0430 AlertMessageBox.warning=\u0423\u043f\u043e\u0437\u043e\u0440\u0435\u045a\u0435 AlertMessageBox.comment=\u041f\u043e\u0434\u0430\u0446\u0438 AlertMessageBox.information=\u041f\u043e\u0434\u0430\u0446\u0438 AlertMessageBox.unread=\u041f\u043e\u0441\u0442\u043e\u0458\u0435 \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0430 \u0443\u043f\u043e\u0437\u043e\u0440\u0435\u045a\u0430 - \u043f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u043e\u0432\u0434\u0435 \u0434\u0430 \u0438\u0445 \u043f\u043e\u0433\u043b\u0435\u0434\u0430\u0442\u0435. SharedPortServer.alert.selectorfailed=\u041d\u0438\u0458\u0435 \u043c\u043e\u0433\u0443\u045b\u0435 \u0443\u0441\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0438 \u0441\u043b\u0443\u0448\u0430\u0447 \u0437\u0430 \u0434\u043e\u043b\u0430\u0437\u043d\u0435 \u043f\u043e\u0434\u0430\u0442\u043a\u0435.\n\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u0434\u0430 \u043b\u0438 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d\u0430 \u0434\u043e\u0437\u0432\u043e\u0459\u0430\u0432\u0430\u0458\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443 java(w).exe \u0434\u0430 \u0440\u0430\u0434\u0438 \u043a\u0430\u043e \u0441\u0435\u0440\u0432\u0435\u0440 Tracker.alert.listenfail=\u041d\u0438\u0458\u0435 \u043c\u043e\u0433\u0443\u045b\u0435 \u0441\u043b\u0443\u0448\u0430\u0442\u0438 \u043f\u043e\u0440\u0442 %1.\n\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u0434\u0430 \u043b\u0438 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 \u043d\u0435\u043a\u0438 \u0434\u0440\u0443\u0433\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c \u043a\u043e\u0458\u0438 \u0432\u0435\u045b \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u043e\u0432\u0430\u0458 \u043f\u043e\u0440\u0442.\n\u0422\u0430\u043a\u043e\u0452\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u0434\u0430 \u0441\u043b\u0443\u0447\u0430\u0458\u043d\u043e \u043d\u0435 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 \u0438 \u0440\u0430\u0434\u0438 \u0434\u0440\u0443\u0433\u0430 \u043a\u043e\u043f\u0438\u0458\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430. DiskManager.alert.movefileexists=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u0435\u043c\u0435\u0448\u0442\u0430\u045a\u0443 \u0433\u043e\u0442\u043e\u0432\u0438\u0445 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430\n\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 %1 \u0432\u0435\u045b \u043f\u043e\u0441\u0442\u043e\u0458\u0438 \u0443 \u043e\u0434\u0440\u0435\u0434\u0438\u0448\u043d\u043e\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0443\u0458\u0443\u043c\u0443 DiskManager.alert.movefilefails=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u0435\u043c\u0435\u0448\u0442\u0430\u045a\u0443 \u0437\u0430\u0432\u0440\u0448\u0435\u043d\u0438\u0445 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430\n\u041f\u0440\u0435\u043c\u0435\u0448\u0442\u0430\u045a\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 %1 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e, %2 DiskManager.alert.movefilerecoveryfails=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043e\u043f\u043e\u0440\u0430\u0432\u043a\u0443 \u043f\u043e\u0441\u043b\u0435 \u043d\u0435\u0443\u0441\u043f\u0435\u043b\u043e\u0433 \u043f\u0440\u0435\u043c\u0435\u0448\u0442\u0430\u045a\u0430\n\u041e\u043f\u043e\u0440\u0430\u0432\u0430\u043a \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 %1 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043e, %2 ConfigView.section.tracker.logenable=\u0417\u0430\u043f\u0438\u0441\u0443\u0458 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u043d\u043e \u0443 \u201etracker.log\u201c SpeedView.stats.title=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 SpeedView.stats.total=\u0423\u043a\u0443\u043f\u043d\u043e SpeedView.stats.session=\u041e\u0432\u0430 \u0441\u0435\u0441\u0438\u0458\u0430 SpeedView.stats.session.tooltip=\u0423\u043a\u0443\u043f\u043d\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) SpeedView.stats.downloaded=\u041f\u0440\u0438\u043c\u0459\u0435\u043d\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) SpeedView.stats.uploaded=\u041f\u043e\u0441\u043b\u0430\u0442\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) SpeedView.stats.ratio=\u041e\u0434\u043d\u043e\u0441 SpeedView.stats.uptime=\u0412\u0440\u0435\u043c\u0435 \u0440\u0430\u0434\u0430 SpeedView.stats.now=\u0421\u0430\u0434\u0430 SpeedView.stats.now.tooltip=\u0423\u043a\u0443\u043f\u043d\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) AutoMigration.useralert=\u0420\u0435\u0437\u0443\u043b\u0442\u0430\u0442 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0458\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u0438\u0445 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430\n\n%1\n\u0421\u0432\u0435 \u0433\u0440\u0435\u0448\u043a\u0435 \u0441\u0435 \u043c\u043e\u0440\u0430\u0458\u0443 \u0440\u0443\u0447\u043d\u043e \u043e\u0431\u0440\u0430\u0434\u0438\u0442\u0438\n\u041d\u0415 \u0417\u0410\u0411\u041e\u0420\u0410\u0412\u0418\u0422\u0415 \u0414\u0410 \u041e\u0421\u0412\u0415\u0416\u0418\u0422\u0415 \u0421\u0422\u0410\u0417\u0415 \u0417\u0410 \u041a\u041e\u041d\u0424\u0418\u0413\u0423\u0420\u0410\u0426\u0418\u0408\u0423 \u0410\u041a\u041e \u0421\u0423 \u041c\u0418\u0413\u0420\u0418\u0420\u0410\u041d\u0415! # # > 2.0.8.0 # OpenTorrentWindow.title=\u041e\u0442\u0432\u043e\u0440\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 OpenTorrentWindow.message=\u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u043d\u043e OpenTorrentWindow.addFiles=&\u0414\u043e\u0434\u0430\u0458 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 OpenTorrentWindow.dataLocation=\u041c\u0435\u0441\u0442\u043e \u0437\u0430 \u0437\u0430\u043f\u0438\u0441 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430: OpenTorrentWindow.startMode=\u0414\u043e\u0434\u0430\u0432\u0430\u045a\u0435 OpenTorrentWindow.startMode.queued=\u0417\u0430\u043a\u0430\u0437\u0430\u043d\u043e OpenTorrentWindow.startMode.stopped=\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0459\u0435\u043d OpenTorrentWindow.startMode.forceStarted=\u041f\u0440\u0438\u043d\u0443\u0434\u043d\u0438 \u043f\u043e\u0447\u0435\u0442\u0430\u043a OpenTorrentWindow.addPosition=\u041c\u0435\u0441\u0442\u043e \u0443 \u0440\u0435\u0434\u0443 OpenTorrentWindow.addPosition.first=\u041f\u0440\u0432\u043e OpenTorrentWindow.addPosition.last=\u041f\u043e\u0441\u043b\u0435\u0434\u045a\u0435 TableColumn.header.remaining.info=\u041f\u0440\u0435\u043e\u0441\u0442\u0430\u043b\u0430 \u043a\u043e\u043b\u0438\u0447\u0438\u043d\u0430 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c TableColumn.header.remaining=\u041f\u0440\u0435\u043e\u0441\u0442\u0430\u043b\u043e ConfigView.section.tracker.enablecompact=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u043a\u043e\u043d\u0446\u0438\u0437\u0430\u043d \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0437\u0430 \u043d\u0430\u0458\u0430\u0432\u0443 ConfigView.section.tracker.enablekey=\u0423\u043a\u0459\u0443\u0447\u0438 \u043f\u0440\u043e\u0441\u043b\u0435\u0452\u0438\u0432\u0430\u045a\u0435 \u043a\u0459\u0443\u0447\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0443 \u0437\u0430 \u0431\u043e\u0459\u0443 \u0441\u0438\u0433\u0443\u0440\u043d\u043e\u0441\u0442 ConfigView.section.file.perf=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0431\u0440\u0437\u0438\u043d\u0435 \u0440\u0430\u0434\u0430 ConfigView.section.file.perf.explain=\u0423\u043f\u043e\u0437\u043e\u0440\u0435\u045a\u0435 - \u043d\u0435\u043e\u0434\u0433\u043e\u0432\u043e\u0440\u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0435 \u043e\u0432\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0430\u0440\u0430 \u043c\u043e\u0433\u0443 \u043e\u0437\u0431\u0438\u0459\u043d\u043e \u0434\u0430 \u0443\u0433\u0440\u043e\u0437\u0435 \u0431\u0440\u0437\u0438\u043d\u0443 \u043f\u0440\u0438\u0458\u0435\u043c\u0430. \u041f\u043e\u0442\u0440\u0435\u0431\u0430\u043d \u0458\u0435 \u0438 \u0440\u0435\u0441\u0442\u0430\u0440\u0442.\n\u0410\u043a\u043e \u0438\u043c\u0430\u0442\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u043e\u043c \u043c\u0435\u043c\u043e\u0440\u0438\u0458\u0435, \u0440\u0430\u0437\u043c\u0438\u0441\u043b\u0438\u0442\u0435 \u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0443 \u0431\u0440\u043e\u0458\u0430 \u0432\u0435\u0437\u0430 \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 (\u043f\u043e\u0433\u043b\u0435\u0434\u0430\u0458\u0442\u0435 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u043f\u0440\u0435\u043d\u043e\u0441\u0430) ConfigView.section.file.max_open_files.explain=\u041e\u0442\u0432\u0430\u0440\u0430\u045a\u0435 \u0441\u0443\u0432\u0438\u0448\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0443\u0437\u0440\u043e\u043a\u0443\u0458\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0443\u0441\u043b\u0435\u0434 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e\u0433 \u0431\u0440\u043e\u0458\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0437\u0430 \u0440\u0430\u0434 \u0441\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430\u043c\u0430. \u041e\u0432\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0430\u0432\u0430 \u0431\u0440\u043e\u0458 \u0438\u0441\u0442\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043e \u043e\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0445 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430. popup.error.hide=\u0421\u0430\u043a\u0440\u0438\u0458 popup.error.details=\u0414\u0435\u0442\u0430\u0459\u0438 ConfigView.section.style.colorOverrides=\u0418\u0437\u043c\u0435\u043d\u0430 \u0431\u043e\u0458\u0430 ConfigView.section.style.colorOverride.progressBar=\u0422\u0440\u0430\u043a\u0430 \u043d\u0430\u043f\u0440\u0435\u0442\u043a\u0430 ConfigView.section.style.colorOverride.error=\u0413\u0440\u0435\u0448\u043a\u0430 MainWindow.status.tooOld=\u0458\u0435 \u043f\u0440\u0435\u0441\u0442\u0430\u0440, \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0433\u0430 \u0434\u043e\u0433\u0440\u0430\u0434\u0438\u0442\u0435. ConfigView.section.style.colorOverride.warning=\u0423\u043f\u043e\u0437\u043e\u0440\u0435\u045a\u0435 ConfigView.section.style.colorOverride.altRow=\u041d\u0430\u0438\u0437\u043c\u0435\u043d\u0438\u0447\u043d\u0438 \u0440\u0435\u0434\u043e\u0432\u0438 ConfigView.section.file.save.peers.enable=\u0421\u0430\u0447\u0443\u0432\u0430\u0458 \u0432\u0435\u0437\u0435 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 \u0437\u0430 \u0431\u0440\u0437\u043e \u043f\u043e\u043d\u043e\u0432\u043d\u043e \u043f\u043e\u0432\u0435\u0437\u0438\u0432\u0430\u045a\u0435 ConfigView.section.file.save.peers.max=\u041d\u0430\u0458\u0432\u0438\u0448\u0435 \u0431\u0440\u043e\u0458\u0435\u0432\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u043a\u043e\u0458\u0438 \u0441\u0435 \u0447\u0443\u0432\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.file.save.peers.pertorrent=\u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 ConfigView.label.max_peers_per_torrent=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0438 \u0431\u0440\u043e\u0458 \u0432\u0435\u0437\u0430 \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.label.max_peers_total=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u0443\u043a\u0443\u043f\u0430\u043d \u0431\u0440\u043e\u0458 \u0432\u0435\u0437\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.style.colorOverrides.reset=\u0412\u0440\u0430\u0442\u0438 \u0431\u043e\u0458\u0435 ConfigView.section.language.info=\u041a\u0430\u0434\u0430 \u0458\u0435 \u0443\u043a\u0459\u0443\u0447\u0435\u043d\u043e, \u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u045b\u0435 \u043f\u043e\u0442\u0440\u0430\u0436\u0438\u0442\u0438 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0435 \u0441\u0432\u0430\u043a\u0438 \u043f\u0443\u0442 \u043a\u0430\u0434\u0430 \u0441\u0435 \u043f\u043e\u043a\u0440\u0435\u043d\u0435. ConfigView.section.language.enableUpdate=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u043c\u0440\u0435\u0436\u043d\u0443 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0443 ConfigView.section.language.UpdateURL=\u041e\u0441\u0432\u0435\u0436\u0438 \u0423\u0420\u041b ConfigView.section.language.UpdateNow=\u0414\u043e\u0433\u0440\u0430\u0434\u0438 \u043e\u0434\u043c\u0430\u0445! Button.revert=\u0412\u0440\u0430\u0442\u0438 MyTorrentsView.menu.changeDirectory=\u041f\u0440\u043e\u043c\u0435\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0441\u0430 \u043f\u043e\u0434\u0430\u0446\u0438\u043c\u0430 GenericText.column=\u043a\u043e\u043b\u043e\u043d\u0430 MyTorrentsView.menu.thisColumn.remove=\u0423\u043a\u043b\u043e\u043d\u0438 \u043a\u043e\u043b\u043e\u043d\u0443 MyTorrentsView.menu.thisColumn.toClipboard=\u0423\u043c\u043d\u043e\u0436\u0438 \u0442\u0435\u043a\u0441\u0442 \u043d\u0430 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434 MyTorrentsView.menu.thisColumn.autoTooltip=\u0423\u0432\u0435\u043a \u043f\u0440\u0438\u043a\u0430\u0437\u0443\u0458 \u043e\u0431\u043b\u0430\u0447\u0438\u045b \u0441\u0430 \u043e\u0431\u0458\u0430\u0448\u045a\u0435\u045a\u0438\u043c\u0430 MyTorrentsView.menu.tracker=\u041f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 ConfigView.download.abbreviated=\u041f: ConfigView.upload.abbreviated=\u0421: ConfigView.complete.abbreviated=\u0413: TableColumn.header.secondsseeding=\u0417\u0430\u043c\u0435\u0442\u0430\u045a\u0435 \u0437\u0430 TableColumn.header.secondsseeding.info=\u0423\u043a\u0443\u043f\u043d\u0430 \u043a\u043e\u043b\u0438\u0447\u0438\u043d\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0430 \u043a\u043e\u0458\u0430 \u0458\u0435 \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0430 \u0443 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443. TableColumn.header.secondsdownloading=\u041f\u0440\u0438\u0458\u0435\u043c \u0437\u0430 TableColumn.header.secondsdownloading.info=\u041a\u043e\u043b\u0438\u0447\u0438\u043d\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0430 \u043a\u043e\u0458\u0430 \u0458\u0435 \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0430 \u0443 \u043f\u0440\u0438\u0458\u0435\u043c\u0443. ConfigView.section.tracker.udpversion=\u0418\u0437\u0434\u0430\u045a\u0435 \u0423\u0414\u041f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 (1 \u0438\u043b\u0438 2) window.updateswt.title=\u0418\u0437\u0434\u0430\u045a\u0435 SWT \u0458\u0435 \u043f\u0440\u0435\u0441\u0442\u0430\u0440\u043e! window.updateswt.text=\u0412\u0430\u0448\u0435 \u0438\u0437\u0434\u0430\u045a\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 SWT \u0458\u0435 \u043f\u0440\u0435\u0441\u0442\u0430\u0440\u043e!\nSWT \u0458\u0435 \u0433\u0440\u0430\u0444\u0438\u0447\u043a\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043a\u043e\u0458\u0443 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0410\u0437\u0443\u0440\u0435\u0443\u0441, \u0430 \u0438\u0437\u0434\u0430\u045a\u0435 \u043a\u043e\u0458\u0435 \u0438\u043c\u0430\u0442\u0435 \u0458\u0435 \u043f\u0440\u0435\u0441\u0442\u0430\u0440\u043e \u0434\u0430 \u0431\u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u043b\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u045a\u0435 \u0438\u0437\u0434\u0430\u045a\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430. \u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u0434\u0443\u0433\u043c\u0435 \u201e\u0423 \u0440\u0435\u0434\u0443\u201c \u0434\u0430 \u0431\u0438\u0441\u0442\u0435 \u0434\u043e\u0433\u0440\u0430\u0434\u0438\u043b\u0438 SWT. window.updateswt.status=\u0421\u0442\u0430\u0442\u0443\u0441 window.updateswt.failed=\u0414\u043e\u0433\u0440\u0430\u0434\u045a\u0430 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u0430, \u043f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u043e \u201e\u0423 \u0440\u0435\u0434\u0443\u201c \u0434\u0430 \u043f\u043e\u043a\u0443\u0448\u0430\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u043e. window.updateswt.status.downloading.updater=\u041f\u0440\u0438\u0458\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u0430 \u0437\u0430 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0443 window.updateswt.status.finding=\u0422\u0440\u0430\u0436\u0435\u045a\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u045a\u0435\u0433 \u0438\u0437\u0434\u0430\u045a\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 SWT window.updateswt.status.downloading=\u041f\u0440\u0438\u0458\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u045a\u0435\u0433 \u0438\u0437\u0434\u0430\u045a\u0430 SWT window.updateswt.status.done=\u041f\u043e\u043d\u043e\u0432\u043d\u043e \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 window.updateswt.ok=\u0423 \u0440\u0435\u0434\u0443 window.updateswt.cancel=\u041e\u0442\u043a\u0430\u0436\u0438 swt.updater.downloader.downloading=\u041f\u0440\u0438\u0458\u0435\u043c SWT\u0430 \u0441\u0430 swt.updater.urlsgetter.downloading=\u0414\u043e\u0431\u0430\u0432\u0459\u0430\u045a\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u043e\u0433\u043b\u0435\u0434\u0430\u043b\u0430 \u0441\u0430 swt.updater.urlsgetter.platform=SWT \u0437\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443 : window.updateswt.ignore=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 ConfigView.section.style.useFancyTabs=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0443\u043a\u0440\u0430\u0441\u043d\u0435 \u0458\u0435\u0437\u0438\u0447\u043a\u0435 splash.initializeGM=\u041f\u043e\u043a\u0440\u0430\u0442\u0435\u045a\u0435 \u0433\u043b\u043e\u0431\u0430\u043b\u043d\u043e\u0433 \u0443\u043f\u0440\u0430\u0432\u043d\u0438\u043a\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u043c\u0430 splash.loadingTorrents=\u0423\u0447\u0438\u0442\u0430\u0432\u0430\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 splash.firstMessageNoI18N=(: \u0410\u0437\u0443\u0440\u0435\u0443\u0441 :) MyTorrentsView.menu.thisColumn.sort=&\u0420\u0435\u0452\u0430\u0458 Scrape.status.ok=\u0427\u0438\u0448\u045b\u0435\u045a\u0435 \u0458\u0435 \u0443 \u0440\u0435\u0434\u0443 Scrape.status.error=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u0447\u0438\u0448\u045b\u0435\u045a\u0443: Scrape.status.error.badURL=\u0423\u0420\u041b \u0437\u0430 \u043d\u0430\u0458\u0430\u0432\u0443 \u043d\u0435 \u043f\u043e\u0448\u0442\u0443\u0458\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0458\u0435 \u043e \u0447\u0438\u0448\u045b\u0435\u045a\u0443 Scrape.status.error.nohash=\u0425\u0435\u0448 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0458\u0435 \u0443 \u043e\u0434\u0433\u043e\u0432\u043e\u0440\u0443. Scrape.status.error.invalid=\u041e\u0434\u0433\u043e\u0432\u043e\u0440 \u0458\u0435 \u043d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u0430\u043d. Scrape.status.nextScrapeAt=\u0421\u043b\u0435\u0434\u0435\u045b\u0435 \u0447\u0438\u0448\u045b\u0435\u045a\u0435 \u0443 %1 Scrape.status.scraping=\u0427\u0438\u0448\u045b\u0435\u045a\u0435... Scrape.status.initializing=\u0427\u0435\u043a\u0430\u045a\u0435 \u043d\u0430 \u0447\u0438\u0448\u045b\u0435\u045a\u0435... Scrape.status.scraping.queued=\u0427\u0438\u0448\u045b\u0435\u045a\u0435 \u0458\u0435 \u0437\u0430\u043a\u0430\u0437\u0430\u043d\u043e... ConfigView.label.minSpeedForActiveSeeding=\u041d\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0458 \u0434\u0430 \u0437\u0430\u0432\u0440\u0448\u0435\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043a\u043e\u0440\u0438\u0441\u0442\u0435 \u043f\u0440\u043e\u0440\u0435\u0437 \u0430\u043a\u043e \u0458\u0435 \u0431\u0440\u0437\u0438\u043d\u0430 \u0438\u0441\u043f\u043e\u0434 ConfigView.section.stats.exportpeers=\u0418\u0437\u0432\u043e\u0437 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u043e \u0443\u0434\u0430\u0459\u0435\u043d\u043e\u043c \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0443 MainWindow.menu.view.irc.moved=\u0418\u0440\u0446 \u0458\u0435 \u0441\u0430\u0434\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430\u043d \u043a\u0430\u043e \u0434\u043e\u0434\u0430\u0442\u0430\u043a, \u043f\u043e\u0433\u043b\u0435\u0434\u0430\u0458\u0442\u0435 \u0430\u0434\u0440\u0435\u0441\u0443 http://azureus.sf.net/plugin_list.php. \u041a\u0430\u0434\u0430 \u0458\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d, \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u043c\u0435\u043d\u0438 \u201e\u041f\u0440\u0435\u0433\u043b\u0435\u0434->\u0414\u043e\u0434\u0430\u0446\u0438->\u0418\u0420\u0426\u201c \u0437\u0430 \u043f\u0440\u0438\u0441\u0442\u0443\u043f. MyTrackerView.webui.contextmenu.copyurl=\u0423\u043c\u043d\u043e\u0436\u0438 \u0423\u0420\u041b \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u043d\u0430 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434 ConfigView.section.file.torrent.ignorefiles=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u043a\u043e\u0458\u0435 \u0441\u0435 \u0437\u0430\u043d\u0435\u043c\u0430\u0440\u0443\u0458\u0443 \u043f\u0440\u0438 \u043f\u0440\u0430\u0432\u0459\u0435\u045a\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\n\u043d\u043f\u0440. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0435\u043d\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 ConfigView.section.style.useUnitsRateBits=\u0423\u043f\u043e\u0442\u0440\u0435\u0431\u0430 \u0431\u0438\u0442\u043e\u0432\u0430 \u0443\u043c\u0435\u0441\u0442\u043e \u0431\u0430\u0458\u0442\u043e\u0432\u0430 \u0437\u0430 \u043f\u0440\u043e\u0442\u043e\u043a (KiB/s->Kibit/s \u0438\u0442\u0434) ConfigView.section.interface.resetassoc=\u0420\u0435\u0441\u0435\u0442\u043e\u0432\u0430\u045a\u0435 \u0435\u043a\u0441\u043f\u043b\u043e\u0440\u0435\u0440\u043e\u0432\u0438\u0445 \u043f\u043e\u0432\u0435\u0437\u0438\u0432\u0430\u045a\u0430 \u0441\u0430 \u0435\u043a\u0441\u0442\u0435\u043d\u0437\u0438\u0458\u0430\u043c\u0430 (.torrent) ConfigView.section.interface.resetassocbutton=\u0412\u0440\u0430\u0442\u0438 ConfigView.section.interface.checkassoc=\u041f\u0440\u043e\u0432\u0435\u0440\u0438 \u043f\u043e\u0432\u0435\u0437\u0438\u0432\u0430\u045a\u0430 \u043d\u0430 \u043f\u043e\u0447\u0435\u0442\u043a\u0443 dialog.associations.title=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u043f\u043e\u0432\u0435\u0437\u0438\u0432\u0430\u045a\u0430 Button.yes=&\u0414\u0430 Button.no=&\u041d\u0435 ConfigView.label.seeding.autoStart0Peers=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u043e \u043f\u043e\u0432\u0435\u0437\u0438\u0432\u0430\u045a\u0435 \u0441\u0432\u0438\u0445 \u0433\u043e\u0442\u043e\u0432\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0441\u0430 0 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 ConfigView.label.seeding.autoStart0Peers.tooltip=\u0423\u043a\u0459\u0443\u0447\u0438\u0442\u0435 \u0430\u043a\u043e \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 \u0443\u0432\u0435\u043a \u043f\u0440\u0438\u0458\u0430\u0432\u0459\u0443\u0458\u0435 0 \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 0 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430. dialog.associations.prompt=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u043d\u0438\u0458\u0435 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c \u0437\u0430 \u043e\u0431\u0440\u0430\u0434\u0443 \u0411\u0438\u0442 \u0422\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430.\n\u0414\u0430 \u043b\u0438 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u043f\u043e\u0432\u0435\u0436\u0435\u0442\u0435 .torrent \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0441\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0435\u043e\u043c? dialog.associations.askagain=\u041f\u0440\u043e\u0432\u0435\u0440\u0438 \u043d\u0430 \u043f\u043e\u0447\u0435\u0442\u043a\u0443 ConfigView.section.plugins.update=\u0414\u043e\u0433\u0440\u0430\u0434\u045a\u0430 \u0434\u043e\u0434\u0430\u0442\u0430\u043a\u0430 Plugin.pluginupdate.enablecheck=\u0423\u043a\u0459\u0443\u0447\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0438 \u0437\u0430 \u0434\u043e\u0434\u0430\u0442\u043a\u0435 plugins.basicview.status=\u0421\u0442\u0430\u0442\u0443\u0441: plugins.basicview.activity=\u0410\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442 plugins.basicview.progress=\u041d\u0430\u043f\u0440\u0435\u0434\u0430\u043a: plugins.basicview.log=\u0417\u0430\u043f\u0438\u0441\u043d\u0438\u043a: ConfigView.label.maxdownloadspeed=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u0443 KB/s [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] splash.loadingTorrent=\u041f\u0440\u0438\u0458\u0435\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0430 splash.of=\u043e\u0434 ConfigView.section.plugins.irc=\u0418\u0420\u0426 UpdateWindow.title=\u0414\u043e\u0433\u0440\u0430\u0434\u045a\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 UpdateWindow.header=\u0421\u043b\u0435\u0434\u0435\u045b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u043c\u043e\u0440\u0430\u0458\u0443 \u0434\u0430 \u0441\u0435 \u0434\u043e\u0433\u0440\u0430\u0434\u0435 : UpdateWindow.columns.install=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 UpdateWindow.columns.name=\u0418\u043c\u0435 UpdateWindow.columns.version=\u0418\u0437\u0434\u0430\u045a\u0435 UpdateWindow.columns.size=\u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 UpdateWindow.cancel=\u041e\u0442\u043a\u0430\u0436\u0438 UpdateWindow.quit=\u041a\u0440\u0430\u0458 UpdateWindow.close=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 UpdateWindow.ok=\u041e\u0441\u0432\u0435\u0436\u0438 UpdateWindow.restart=\u041f\u043e\u043a\u0440\u0435\u043d\u0438 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 \u043f\u043e\u043d\u043e\u0432\u043e UpdateWindow.status.downloading=\u041f\u0440\u0438\u0458\u0435\u043c UpdateWindow.status.done=\u0413\u043e\u0442\u043e\u0432\u043e UpdateWindow.status.failed=\u041d\u0435\u0443\u0441\u043f\u0435\u043b\u043e UpdateWindow.status.restartNeeded=\u041f\u043e\u0442\u0440\u0435\u0431\u043d\u043e \u0458\u0435 \u043f\u043e\u043d\u043e\u0432\u043e \u043f\u043e\u043a\u0440\u0435\u043d\u0443\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c! ConfigView.pluginlist.broken=\u041f\u043e\u043a\u0432\u0430\u0440\u0435\u043d\u043e ConfigView.pluginlist.whereToPut=\u041f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u0441\u0432\u0435 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u0435 \u0434\u043e\u0434\u0430\u0442\u043a\u0435 \u0443 \u043e\u0434\u0433\u043e\u0432\u0430\u0440\u0430\u0458\u0443\u045b\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0438\u0441\u043f\u043e\u0434: ConfigView.pluginlist.whereToPutOr=\u0417\u0430 \u0434\u0435\u0459\u0435\u043d\u0435 \u0434\u043e\u0434\u0430\u0442\u043a\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435: MainWindow.statusText.checking=\u041f\u0440\u043e\u0432\u0435\u0440\u0430\u0432\u0430\u045a\u0435 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0438... TableColumn.header.OnlyCDing4.info=\u0412\u0440\u0435\u043c\u0435 \u043a\u043e\u0458\u0435 \u0458\u0435 \u0442\u043e\u0440\u0435\u043d\u0442 \u043f\u0440\u043e\u0432\u0435\u043e \u0441\u0430\u043c\u043e \u0443 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443. \u041d\u0438\u0458\u0435 \u0443\u0440\u0430\u0447\u0443\u043d\u0430\u0442\u043e \u0432\u0440\u0435\u043c\u0435 \u043a\u0430\u0434\u0430 \u0458\u0435 \u0442\u043e\u0440\u0435\u043d\u0442 \u043f\u0440\u0438\u043c\u0430\u043d (\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u043d \u0443 \u0438\u0441\u0442\u043e \u0432\u0440\u0435\u043c\u0435). ConfigView.section.style.alternateTablePainting=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0434\u0440\u0443\u0433\u0438 \u043d\u0430\u0447\u0438\u043d \u0437\u0430 \u0446\u0440\u0442\u0430\u045a\u0435 \u043a\u043e\u043b\u043e\u043d\u0430 \u0443 \u0442\u0430\u0431\u0435\u043b\u0430\u043c\u0430 (\u043c\u043e\u0436\u0435 \u0434\u0430 \u0442\u0440\u0430\u0436\u0438 \u0440\u0435\u0441\u0442\u0430\u0440\u0442) UpdateWindow.status.restartMaybeNeeded=\u041c\u043e\u0436\u0434\u0430 \u045b\u0435\u0442\u0435 \u043c\u043e\u0440\u0430\u0442\u0438 \u0434\u0430 \u043f\u043e\u043d\u043e\u0432\u043e \u043f\u043e\u043a\u0440\u0435\u043d\u0435\u0442\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c ConfigView.pluginlist.shared=\u0434\u0435\u0459\u0435\u043d\u043e PeersView.host=\u0418\u043c\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 PeersView.host.info=\u0418\u043c\u0435 \u0443\u0434\u0430\u0459\u0435\u043d\u043e\u0433 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430, \u0430\u043a\u043e \u0458\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e (\u043c\u043e\u0436\u0435 \u0443\u0442\u0438\u0446\u0430\u0442\u0438 \u043d\u0430 \u043f\u0440\u0435\u0444\u043e\u0440\u043c\u0430\u043d\u0441\u0435) MainWindow.menu.help.whatsnew=\u0428\u0442\u0430 \u0438\u043c\u0430 \u043d\u043e\u0432\u043e ConfigView.label.checkonstart=\u041f\u0440\u043e\u0432\u0435\u0440\u0438 \u043a\u043e\u0458\u0435 \u0458\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u045a\u0435 \u0438\u0437\u0434\u0430\u045a\u0435 \u043f\u0440\u0438 \u043f\u043e\u0447\u0435\u0442\u043a\u0443 \u0440\u0430\u0434\u0430 ConfigView.label.periodiccheck=\u041f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u0434\u0430 \u043b\u0438 \u043f\u043e\u0441\u0442\u043e\u0458\u0435 \u043d\u043e\u0432\u0430 \u0438\u0437\u0434\u0430\u045a\u0430 ConfigView.label.opendialog=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043e\u0442\u0432\u043e\u0440\u0438 \u0421\u0430\u0440\u0430\u0434\u043d\u0438\u043a\u0430 \u0437\u0430 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0443 \u0430\u043a\u043e \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0430 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 MainWindow.updateavail=\u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u043e\u0432\u0434\u0435 \u0437\u0430 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0443 MainWindow.status.unofficialversion=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u0411\u0435\u0442\u0430 MainWindow.status.latestversionunchecked=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u0438\u0437\u0434\u0430\u045a\u0430 \u0458\u0435 \u0438\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u0430 GeneralView.label.updatein.stopped=\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0459\u0435\u043d StartStopRules.menu.viewDebug=\u041f\u0440\u0435\u0433\u043b\u0435\u0434\u0430\u0458 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u0437\u0430 \u0438\u0441\u043f\u0440\u0430\u0432\u0459\u0430\u045a\u0435 \u0433\u0440\u0435\u0448\u0430\u043a\u0430 ConfigView.section.style.doNotUseGB=\u041d\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0458\u0435\u0434\u0438\u043d\u0438\u0446\u0443 GB ConfigView.section.style.doNotUseGB.tooltip=\u0410\u043a\u043e \u0458\u0435 \u0443\u043a\u0459\u0443\u0447\u0435\u043d\u043e, \u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u045b\u0435 \u043d\u0430\u0441\u0442\u0432\u0438\u0442\u0438 \u0434\u0430 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0458\u0435\u0434\u0438\u043d\u0438\u0446\u0443 MB \u0447\u0430\u043a \u0438 \u0437\u0430 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0435 \u043a\u043e\u0458\u0435 \u043f\u0440\u0435\u043c\u0430\u0448\u0443\u0458\u0443 1024MB MainWindow.menu.help.plugins=\u0414\u043e\u0431\u0430\u0432\u0438 \u0434\u043e\u0434\u0430\u0442\u043a\u0435 ConfigView.section.plugins.TrackerWeb=\u041c\u0440\u0435\u0436\u0430 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 ConfigView.section.tracker.enablecategories=\u0420\u0430\u0437\u0434\u0432\u043e\u0458 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u043f\u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0430\u043c\u0430 health.explain.share=\u0437\u043d\u0430\u0447\u0438 \u0434\u0430 \u0458\u0435 \u0442\u043e\u0440\u0435\u043d\u0442 \u0438\u043b\u0438 \u0445\u043e\u0441\u0442\u043e\u0432\u0430\u043d \u0438\u043b\u0438 \u043e\u0431\u0458\u0430\u0432\u0459\u0435\u043d ConfigView.section.tracker.createcert=\u041d\u0430\u043f\u0440\u0430\u0432\u0438 \u0441\u0430\u043c\u043e\u043f\u043e\u0442\u043f\u0438\u0441\u0430\u043d \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 ConfigView.section.tracker.createbutton=\u041d\u0430\u043f\u0440\u0430\u0432\u0459\u0435\u043d\u043e security.certcreate.title=\u041d\u0430\u043f\u0440\u0430\u0432\u0438 \u0441\u0430\u043c\u043e \u043f\u043e\u0442\u043f\u0438\u0441\u0430\u043d \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 security.certcreate.intro=\u041e\u0432\u0430\u0458 \u043f\u0440\u043e\u0437\u043e\u0440\u0447\u0438\u045b \u0432\u0430\u043c \u0434\u043e\u0437\u0432\u043e\u0459\u0430\u0432\u0430 \u0434\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442\u0435 \u0441\u0430\u043c\u043e\u043f\u043e\u0442\u043f\u0438\u0441\u0430\u043d \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 security.certcreate.alias=\u0410\u043b\u0438\u0430\u0441 security.certcreate.strength=\u0421\u043d\u0430\u0433\u0430 security.certcreate.firstlastname=\u0418\u043c\u0435 \u0438 \u043f\u0440\u0435\u0437\u0438\u043c\u0435 security.certcreate.orgunit=\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u0430 \u0458\u0435\u0434\u0438\u043d\u0438\u0446\u0430 security.certcreate.org=\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0458\u0430 security.certcreate.city=\u0413\u0440\u0430\u0434 \u0438\u043b\u0438 \u043c\u0435\u0441\u0442\u043e security.certcreate.state=\u0414\u0440\u0436\u0430\u0432\u0430 \u0438\u043b\u0438 \u043f\u043e\u043a\u0440\u0430\u0458\u0438\u043d\u0430 security.certcreate.country=\u0414\u0432\u043e\u0441\u043b\u043e\u0432\u043d\u0438 \u043a\u00f4\u0434 \u0434\u0440\u0436\u0430\u0432\u0435 security.certcreate.ok=\u041d\u0430\u043f\u0440\u0430\u0432\u0459\u0435\u043d\u043e security.certcreate.cancel=\u041e\u0442\u043a\u0430\u0436\u0438 security.certcreate.createok=\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u0458\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u0459\u0435\u043d security.certcreate.createfail=\u041f\u0440\u0430\u0432\u0459\u0435\u045a\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e ConfigView.section.plugins.webui=\u0421\u0432\u0438\u043d\u0433\u043e\u0432\u043e \u043c\u0440\u0435\u0436\u043d\u043e \u0441\u0443\u0447\u0435\u0459\u0435 ConfigView.section.plugins.xml_http_if=XML/HTTP \u0441\u0443\u0447\u0435\u0459\u0435 webui.passwordenable=\u0423\u043a\u0459\u0443\u0447\u0438 \u043b\u043e\u0437\u0438\u043d\u043a\u0443 webui.user=\u041a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e \u0438\u043c\u0435 webui.password=\u041b\u043e\u0437\u0438\u043d\u043a\u0430 webui.port=\u041f\u043e\u0440\u0442 (*) webui.protocol=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b (*) webui.homepage=\u0414\u043e\u043c\u0430\u045b\u0430 \u0441\u0442\u0440\u0430\u043d\u0430 (*) webui.rootdir=\u041a\u043e\u0440\u0435\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c (*) webui.rootres=\u041a\u043e\u0440\u0435\u043d\u0438 \u0440\u0435\u0441\u0443\u0440\u0441 (*) webui.mode=\u041d\u0430\u0447\u0438\u043d (*) webui.mode.info=\u041d\u0430\u0447\u0438\u043d \u043c\u043e\u0436\u0435 \u0431\u0438\u0442\u0438\n\t\u201e\u043f\u043e\u0442\u043f\u0443\u043d\u201c = \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0441\u0443 \u0441\u0432\u0430 \u0434\u0435\u0458\u0441\u0442\u0432\u0430 (\u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u043e)\n\t\u201e\u043f\u043e\u0433\u043b\u0435\u0434\u201c = \u0441\u0430\u043c\u043e \u043f\u043e\u0433\u043b\u0435\u0434\u0438 (\u0430\u043b\u0438 \u043c\u043e\u0436\u0435 \u0434\u0430 \u043f\u043e\u0431\u043e\u0459\u0448\u0430 \u0443\u0447\u0435\u0441\u0442\u0430\u043d\u043e\u0441\u0442 \u043e\u0441\u0432\u0435\u0436\u0430\u0432\u0430\u045a\u0430) webui.access=\u041f\u0440\u0438\u0441\u0442\u0443\u043f (*) webui.access.info=\u041f\u0440\u0438\u0441\u0442\u0443\u043f \u043c\u043e\u0436\u0435 \u0431\u0438\u0442\u0438\n\t\u201e\u043b\u043e\u043a\u0430\u043b\u043d\u0438\u201c = \u0441\u0430\u043c\u043e \u043b\u043e\u043a\u0430\u043b\u043d\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u043f\u043e\u0432\u0435\u0436\u0435\n\t\u201e\u0441\u0432\u0435\u201c = \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d \u043f\u0440\u0438\u0441\u0442\u0443\u043f (\u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u043e)\n\tIP = \u043d\u043f\u0440 192.168.0.2\t\t\t\u0441\u0430\u043c\u043e \u0458\u0435\u0434\u0430\u043d \u0418\u041f \u0431\u0440\u043e\u0458\n\tIP1-IP2 = \u043d\u043f\u0440 192.168.0.1-192.168.0.255\t\u0438\u043d\u043a\u043b\u0443\u0437\u0438\u0432\u0430\u043d \u043e\u043f\u0441\u0435\u0433 \u0431\u0440\u043e\u0458\u0435\u0432\u0430 GeneralView.label.maxdownloadspeed=\u0411\u0440\u0437. \u043f\u0440\u0438\u0458\u0435\u043c\u0430 Security.keystore.corrupt=\u041e\u0441\u0442\u0430\u0432\u0430 \u0437\u0430 \u043a\u0459\u0443\u0447\u0435\u0432\u0435 \u201e%1\u201c \u043d\u0438\u0458\u0435 \u0443\u0447\u0438\u0442\u0430\u043d\u0430, \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0458\u0435 \u043e\u0431\u0440\u0438\u0448\u0435\u0442\u0435 \u0438 \u043f\u043e\u043d\u043e\u0432\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442\u0435 \u0438\u043b\u0438 \u043f\u043e\u043d\u043e\u0432\u043e \u0443\u0432\u0435\u0437\u0435\u0442\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0435 Security.keystore.empty=\u041e\u0441\u0442\u0430\u0432\u0430 \u0437\u0430 \u043a\u0459\u0443\u0447\u0435\u0432\u0435 \u0458\u0435 \u043f\u0440\u0430\u0437\u043d\u0430. \u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442\u0435 \u0441\u0430\u043c\u043e-\u043f\u043e\u0442\u043f\u0438\u0441\u0430\u043d\u0438 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 (\u043f\u043e\u0433\u043b\u0435\u0434\u0430\u0458\u0442\u0435 \u201e\u0410\u043b\u0430\u0442\u0438->\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430->\u0411\u0435\u0437\u0431\u0435\u0434\u043d\u043e\u0441\u0442\u201c) \u0438\u043b\u0438 \u0443\u0432\u0435\u0437\u0438\u0442\u0435 \u043f\u043e\u0441\u0442\u043e\u0458\u0435\u045b\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0435 \u0443 \u201e%1\u201c webui.restart.info=\u041f\u0440\u043e\u043c\u0435\u043d\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0430\u0440\u0430 \u0441\u0430 \u043e\u0437\u043d\u0430\u043a\u043e\u043c (*) \u0442\u0440\u0430\u0436\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442 \u043a\u0430\u043a\u043e \u0431\u0438 \u043f\u043e\u0447\u0435\u043b\u0438 \u0434\u0430 \u0432\u0430\u0436\u0435 GeneralView.label.maxdownloadspeed.tooltip=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430] upnp.enable=\u0423\u043a\u0459\u0443\u0447\u0438 UPnP upnp.info=\u0423\u043d\u0438\u0432\u0435\u0440\u0437\u0430\u043b\u043d\u0438 PnP (UPnP) \u043e\u043c\u043e\u0433\u0443\u045b\u0443\u0458\u0435 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u043e \u043f\u0440\u0435\u0441\u043b\u0438\u043a\u0430\u0432\u0430\u045a\u0435 \u043f\u043e\u0440\u0442\u043e\u0432\u0430 \u043d\u0430 \u0440\u0443\u0442\u0435\u0440\u0438\u043c\u0430 \u043a\u043e\u0458\u0438 \u0442\u043e \u043f\u043e\u0434\u0440\u0436\u0430\u0432\u0430\u0458\u0443. upnp.mapping.dataport=\u0414\u043e\u043b\u0430\u0437\u043d\u0438 \u043f\u043e\u0440\u0442 \u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 upnp.mapping.tcptrackerport=\u041f\u043e\u0440\u0442 \u0437\u0430 \u0422\u0426\u041f \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 upnp.mapping.udptrackerport=\u041f\u043e\u0440\u0442 \u0437\u0430 \u0423\u0414\u041f \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 upnp.alert.differenthost=UPnP: \u041f\u0440\u0435\u0441\u043b\u0438\u043a\u0430\u0432\u0430\u045a\u0435 \u201e%1\u201c \u0458\u0435 \u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0441\u0430\u043e \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u201e%2\u201c - \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0438\u0437\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u0434\u0440\u0443\u0433\u0438 \u043f\u043e\u0440\u0442 upnp.alert.mappingok=UPnP: \u041f\u0440\u0435\u0441\u043b\u0438\u043a\u0430\u0432\u0430\u045a\u0435 \u201e%1\u201c \u0458\u0435 \u043e\u043c\u043e\u0433\u0443\u045b\u0435\u043d\u043e upnp.alert.mappingfailed=UPnP: \u041f\u0440\u0435\u0441\u043b\u0438\u043a\u0430\u0432\u0430\u045a\u0435 \u201e%1\u201c \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e upnp.alertsuccess=\u041e\u0431\u0458\u0430\u0432\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u0430 \u043f\u0440\u0435\u0441\u043b\u0438\u043a\u0430\u0432\u0430\u045a\u0430 upnp.alert.lostdevice=UPnP: \u0418\u0437\u0433\u0443\u0431\u0459\u0435\u043d\u0430 \u0432\u0435\u0437\u0430 \u0434\u043e \u0443\u0441\u043b\u0443\u043a\u0435 \u201e%1\u201c \u043d\u0430 UPnP \u0443\u0440\u0435\u0452\u0430\u0458\u0443 \u201e%2\u201c upnp.grabports=\u041f\u0440\u0435\u0441\u043b\u0438\u043a\u0430\u0458 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 \u0447\u0430\u043a \u0438 \u0430\u043a\u043e \u0438\u0445 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0434\u0440\u0443\u0433\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 upnp.refresh.label=\u041e\u0441\u0432\u0435\u0436\u0438 \u043f\u0440\u0435\u0441\u043b\u0438\u043a\u0430\u0432\u0430\u045a\u0430 upnp.refresh.button=\u041e\u0441\u0432\u0435\u0436\u0438 upnp.alert.mappinggrabbed=UPnP: \u041f\u0440\u0435\u0441\u043b\u0438\u043a\u0430\u0432\u0430\u045a\u0435 \u201e%1\u201c \u0458\u0435 \u0443\u0441\u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u043e - \u043e\u0442\u0435\u0442\u043e \u043e\u0434 \u201e%2\u201c upnp.mapping.tcpssltrackerport=\u041f\u0440\u0430\u0442\u0438\u043e\u0447\u0435\u0432 TCP SSL \u043f\u043e\u0440\u0442 upnp.alertothermappings=\u041f\u0440\u0438\u0458\u0430\u0432\u0438 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 \u043a\u043e\u0458\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0435 \u0434\u0440\u0443\u0433\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438 upnp.alertdeviceproblems=\u041f\u0440\u0438\u0458\u0430\u0432\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435 \u0441\u0430 UPnP \u0443\u0440\u0435\u0452\u0430\u0458\u0435\u043c upnp.trace_to_log=\u0417\u0430\u043f\u0438\u0441\u0443\u0458 \u0434\u0435\u0442\u0430\u0459\u043d\u0435 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u043e \u0433\u0440\u0435\u0448\u043a\u0430\u043c\u0430 upnp.wiki_link=\u0421\u0442\u0440\u0430\u043d\u0430 \u043e \u0423\u041f\u043d\u041f\u0443 \u043d\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432\u043e\u043c \u0432\u0438\u043a\u0438\u0458\u0443 blank.resource=_: blank.resource\n ConfigView.pluginlist.coreplugins=\u0423\u0447\u0438\u0442\u0430\u043d\u0438 \u0441\u0443 \u043d\u0430\u0440\u0435\u0434\u043d\u0438 \u0443\u0433\u0440\u0430\u0452\u0435\u043d\u0438 \u0434\u043e\u0434\u0430\u0446\u0438: Peers.column.DLedFromOthers=\u041e\u0434 \u043e\u0441\u0442\u0430\u043b\u0438\u0445 Peers.column.DLedFromOthers.info=\u041a\u043e\u043b\u0438\u0447\u0438\u043d\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u043f\u0440\u0435\u0443\u0437\u0435\u0442\u0430 \u043e\u0434 \u0434\u0440\u0443\u0433\u0438\u0445 \u0434\u043e\u043a \u0441\u0443 \u0431\u0438\u043b\u0438 \u043f\u043e\u0432\u0435\u0437\u0430\u043d\u0438 \u0441\u0430 \u0432\u0430\u043c\u0430 Peers.column.UpDownRatio=\u0421\u043b:\u041f\u0440 Peers.column.UpDownRatio.info=\u041e\u0434\u043d\u043e\u0441 \u201e\u043f\u0440\u0438\u043c\u0459\u0435\u043d\u043e:\u043f\u043e\u0441\u043b\u0430\u0442\u043e\u201c \u0443\u0434\u0430\u0459\u0435\u043d\u043e\u0433 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 Peers.column.UpRatio=\u041e\u0434\u043d\u043e\u0441 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 Peers.column.UpRatio.info=\u041e\u0434\u043d\u043e\u0441 \u201e\u043f\u0440\u0435\u0443\u0437\u0435\u0442\u043e \u043e\u0434 \u0432\u0430\u0441 : \u043f\u043e\u0441\u043b\u0430\u0442\u043e \u043e\u0434 \u0434\u0440\u0443\u0433\u0438\u0445\u201c \u0443\u0434\u0430\u0459\u0435\u043d\u043e\u0433 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 upnp.releasemappings=\u041e\u0442\u043f\u0443\u0441\u043d\u0438 \u043f\u0440\u0435\u0441\u043b\u0438\u043a\u0430\u0432\u0430\u045a\u0430 \u043f\u0440\u0438 \u043a\u0440\u0430\u0458\u0443 \u0440\u0430\u0434\u0430 webui.upnpenable=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 UPnP \u0437\u0430 \u043e\u0432\u0430\u0458 \u043f\u043e\u0440\u0442 (*) ConfigView.section.file.friendly.hashchecking=\u041f\u0440\u0438\u0458\u0430\u0442\u0435\u0459\u0441\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0430 \u0445\u0435\u0448\u0430 ConfigView.section.file.friendly.hashchecking.tooltip=\u041d\u0435\u0448\u0442\u043e \u0441\u043f\u043e\u0440\u0438\u0458\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0430 \u043a\u0435\u0448\u0430, \u0430\u043b\u0438 \u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u0458\u0430\u0442\u0435\u0459\u0441\u043a\u0438\u0458\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0458\u0435\u043d\u0430 \u043f\u0440\u0435\u043c\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u0443 \u0438\u043b\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0443. ConfigView.section.tracker.seedretention=\u041d\u0430\u0458\u0432\u0438\u0448\u0435 \u0437\u0430\u0434\u0440\u0436\u0430\u043d\u0438\u0445 \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.tracker.seedretention.info=\u041f\u0440\u0438\u043c\u0435\u0434\u0431\u0430: \u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 \u043e \u043f\u0440\u0438\u0458\u0435\u043c\u0443 \u0431\u0438\u045b\u0435 \u0438\u0437\u0433\u0443\u0431\u0459\u0435\u043d\u0435 \u0437\u0430 \u043d\u0435\u0437\u0430\u0434\u0440\u0436\u0430\u043d\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0435 ConfigView.section.tracker.port=\u0423\u043a\u0459\u0443\u0447\u0438 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 \u043d\u0430 HTTP \u043f\u043e\u0440\u0442\u0443 ConfigView.section.tracker.sslport=\u0423\u043a\u0459\u0443\u0447\u0438 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 \u043d\u0430 HTTPS \u043f\u043e\u0440\u0442\u0443 ConfigView.section.tracker.publicenable.info=\u041e\u0432\u043e \u0434\u043e\u0437\u0432\u043e\u0459\u0430\u0432\u0430 \u0434\u0440\u0443\u0433\u0438\u043c\u0430 \u0434\u0430 \u043f\u0440\u0430\u0432\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u043a\u043e\u0458\u0438 \u043a\u043e\u0440\u0438\u0441\u0442\u0435 \u0432\u0430\u0448\u0435\u0433 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 \u0434\u043e\u043a \u0433\u0430 \u0432\u0438 \u043d\u0435 \u0445\u043e\u0441\u0442\u0443\u0458\u0435\u0442\u0435 \u043d\u0438\u0442\u0438 \u043e\u0431\u0458\u0430\u0432\u0459\u0443\u0458\u0435\u0442\u0435 Button.clear=\u041e\u0447\u0438\u0441\u0442\u0438 MainWindow.IPs.tooltip=\u041f\u043e\u0441\u043b\u0435\u0434\u045a\u0435 \u043e\u0441\u0432\u0435\u0436\u0435\u045a\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0444\u0438\u043b\u0442\u0435\u0440\u0430: %1\n\u0423\u043a\u0443\u043f\u043d\u043e \u0418\u041f \u0444\u0438\u043b\u0442\u0435\u0440\u0430 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443 - \u0411\u0440\u043e\u0458 \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0438\u0445/\u0437\u0430\u0431\u0440\u0430\u045a\u0435\u043d\u0438\u0445/\u043b\u043e\u0448\u0438\u0445 \u0418\u041f\u043e\u0432\u0430 \u0437\u0430 \u043e\u0432\u0443 \u0441\u0435\u0441\u0438\u0458\u0443.\n\u0414\u0443\u043f\u043b\u0438 \u043a\u043b\u0438\u043a \u0437\u0430 \u0434\u0435\u0442\u0430\u0459\u0435. ConfigView.section.ipfilter.list.banned=\u0458\u0435 \u0437\u0430\u0431\u0440\u0430\u045a\u0435\u043d ConfigView.section.ipfilter.list.baddata=\u0458\u0435 \u043f\u043e\u0441\u043b\u0430\u043e \u043b\u043e\u0448\u0435 \u043f\u043e\u0434\u0430\u0442\u043a\u0435: \u043f\u043e\u043d\u0430\u0432\u0459\u0430\u045a\u0430 = Button.reset=\u0412\u0440\u0430\u0442\u0438 ConfigView.section.ipfilter.bannedinfo=\u0418\u041f\u043e\u0432\u0438 \u043a\u043e\u0458\u0438 \u0441\u0443 \u0441\u043b\u0430\u043b\u0438 \u043b\u043e\u0448\u0435 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 - \u0437\u0430\u0431\u0440\u0430\u045a\u0435\u043d\u0438 \u0430\u043a\u043e \u0441\u0435 \u043f\u0440\u0435\u0432\u0440\u0448\u0438 \u043c\u0435\u0440\u0430 ConfigView.section.ipfilter.blockedinfo=\u0418\u041f\u043e\u0432\u0438 \u043a\u043e\u0458\u0438 \u0441\u0443 \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0438 \u0437\u0431\u043e\u0433 \u0418\u041f \u0444\u0438\u043b\u0442\u0435\u0440\u0430 download.removerules.name=\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0437\u0430 \u0443\u043a\u043b\u0430\u045a\u0430\u045a\u0435 download.removerules.unauthorised.info=\u041d\u0435\u043e\u0432\u043b\u0430\u0448\u045b\u0435\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441\u0443 \u043e\u043d\u0438 \u0447\u0438\u0458\u0430 \u043d\u0430\u0458\u0430\u0432\u0430 \u0441\u0430\u0434\u0440\u0436\u0438 \u0442\u0435\u043a\u0441\u0442 \u201e\u043d\u0435\u043e\u0432\u043b\u0430\u0448\u045b\u0435\u043d\u043e\u201c \u0443 \u043e\u0434\u0433\u043e\u0432\u043e\u0440\u0443 \u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0443 download.removerules.unauthorised=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u0443\u043a\u043b\u043e\u043d\u0438 \u043d\u0435\u043e\u0432\u043b\u0430\u0448\u045b\u0435\u043d\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 download.removerules.unauthorised.seedingonly=\u0421\u0430\u043c\u043e \u043f\u0440\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443 download.removerules.removed.ok=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u043e \u0443\u043a\u043b\u0430\u045a\u0430\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u201e%1\u201c \u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e. \u0423\u0437\u0440\u043e\u043a \u043e\u0432\u043e\u043c\u0435 \u0441\u0443 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0437\u0430 \u0443\u043a\u043b\u0430\u045a\u0430\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430. download.removerules.updatetorrents=\u0423\u043a\u043b\u043e\u043d\u0438 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0430\u043c\u0430 \u043a\u0430\u043a\u043e \u0440\u043e\u0458 \u0437\u0430\u0445\u0442\u0435\u0432\u0430 ConfigView.label.defaultstarttorrentsstopped=\u041a\u0430\u0434\u0430 \u0441\u0435 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u043e\u0434\u0430, \u0434\u043e\u0434\u0435\u0459\u0443\u0458\u0435 \u043c\u0443 \u0441\u0435 \u0441\u0442\u0430\u045a\u0435 \u201e\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u043e\u201f ConfigView.section.server.enableudp=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u043a\u043b\u0438\u0458\u0435\u043d\u0442\u0441\u043a\u0438 \u0423\u0414\u041f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0437\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0435 upnp.mapping.dataportudp=\u041a\u043b\u0438\u0458\u0435\u043d\u0442\u0441\u043a\u0438 \u043f\u043e\u0440\u0442 \u0423\u0414\u041f \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 ConfigView.section.file.decoder.showlax=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u0438 \u043c\u0430\u045a\u0435 \u0432\u0435\u0440\u043e\u0432\u0430\u0442\u043d\u0430 \u043a\u043e\u0434\u0438\u0440\u0430\u045a\u0430 ConfigView.section.file.decoder.showall=\u0420\u0430\u0437\u043c\u043e\u0442\u0440\u0438 \u0441\u0432\u0430 \u043c\u043e\u0433\u0443\u045b\u0430 \u043a\u043e\u0434\u0438\u0440\u0430\u045a\u0430 MainWindow.status.updowndetails.tooltip=\u0411\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u0438\u043b\u0438 \u0441\u043b\u0430\u045a\u0430\n\u0414\u0435\u0441\u043d\u0438\u043c \u0434\u0443\u0433\u043c\u0435\u0442\u043e\u043c \u0441\u0435 \u043c\u0435\u045a\u0430, \u0434\u0443\u043f\u043b\u0438\u043c \u043f\u0440\u0438\u0442\u0438\u0441\u043a\u043e\u043c \u0441\u0435 \u043f\u0440\u0438\u043a\u0430\u0437\u0443\u0458\u0443 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 TrackerClient.announce.warningmessage=\u041f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 \u0437\u0430 \u201e%1\u201c \u0432\u0440\u0430\u0442\u0438\u043e \u0458\u0435 \u0443\u043f\u043e\u0437\u043e\u0440\u0435\u045a\u0435 \u201e%2\u201c ConfigView.section.tracker.natcheckenable=\u041f\u0440\u043e\u0432\u0435\u0442\u0438 \u0441\u0432\u0443 \u043f\u043e\u0432\u0435\u0437\u0438\u0432\u043e\u0441\u0442 \u0437\u0430 \u201e\u0443\u043b\u0430\u0437\u043d\u0438 \u043f\u043e\u0440\u0442 \u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u043a\u0435\u201c \u0438 \u043f\u0440\u0438\u0458\u0430\u0432\u0438 \u0433\u0440\u0435\u0448\u043a\u0435 \u0443\u0434\u0430\u0459\u0435\u043d\u0438\u043c \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 ConfigView.section.tracker.publishenabledetails=\u041e\u0431\u0458\u0430\u0432\u0438 \u0441\u0432\u0435 \u0434\u0435\u0442\u0430\u0459\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 ConfigView.section.tracker.publishenablepeerdetails=\u041e\u0431\u0458\u0430\u0432\u0438 \u0434\u0435\u0442\u0430\u0459\u0435 \u043e \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 MyTrackerView.badnat=\u041b\u043e\u0448 NAT MyTrackerView.badnat.info=\u0417\u0430\u043c\u0435\u0446\u0438 \u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438 \u043a\u043e\u0458\u0438 \u043d\u0435 \u043f\u0440\u043e\u043b\u0430\u0437\u0435 NAT \u043f\u0440\u043e\u0432\u0435\u0440\u0435, \u0430\u043a\u043e \u0458\u0435 \u0443\u043a\u0459\u0443\u0447\u0435\u043d\u043e ConfigView.section.tracker.natchecktimeout=\u041f\u0440\u043e\u0432\u0435\u0440\u0438 \u0440\u043e\u043a\u043e\u0432\u0435 (\u0441\u0435\u043a\u0443\u043d\u0434\u0435) ConfigView.section.file.perf.cache.enable=\u0423\u043a\u0459\u0443\u0447\u0438 \u0434\u0438\u0441\u043a \u043a\u0435\u0448 ConfigView.section.file.perf.cache.size=\u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u043a\u0435\u0448\u0430 \u0443 %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=&\u041f\u0440\u0435\u043d\u043e\u0441\u0438 MainWindow.menu.transfers.startalltransfers=\u041f\u043e&\u043a\u0440\u0435\u043d\u0438 \u0441\u0432\u0435 MainWindow.menu.transfers.stopalltransfers=&\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0438 \u0441\u0432\u0435 MainWindow.menu.transfers.pausetransfers=\u041f\u0430&\u0443\u0437\u0438\u0440\u0430\u0458 MainWindow.menu.transfers.resumetransfers=&\u041d\u0430\u0441\u0442\u0430\u0432\u0438 ConfigView.label.experimental.osx.kernel.panic.fix=\u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u043d\u0430 \u0437\u0430\u043a\u0440\u043f\u0430 \u0437\u0430 \u0433\u0440\u0435\u0448\u043a\u0435 \u0443 \u0458\u0435\u0437\u0433\u0440\u0443 \u043d\u0430 \u0434\u0432\u043e\u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u0441\u043a\u043e\u043c \u041e\u0421 \u0418\u043a\u0441 \u0441\u0438\u0441\u0442\u0435\u043c\u0438\u043c\u0430 [\u0442\u0440\u0430\u0436\u0438 \u0440\u0435\u0441\u0442\u0430\u0440\u0442] SystemTray.menu.pausetransfers=\u041f\u0430\u0443\u0437\u0438\u0440\u0430\u0458 \u043f\u0440\u0435\u043d\u043e\u0441\u0435 SystemTray.menu.resumetransfers=\u041d\u0430\u0441\u0442\u0430\u0432\u0438 \u043f\u0440\u0435\u043d\u043e\u0441\u0435 ConfigView.section.file.truncate.too.large=\u041e\u0434\u0441\u0435\u0446\u0438 \u043f\u043e\u0441\u0442\u043e\u0458\u0435\u045b\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u043a\u043e\u0458\u0435 \u0441\u0443 \u043f\u0440\u0435\u0432\u0435\u043b\u0438\u043a\u0435 ConfigView.section.file.perf.cache.trace=\u041f\u0440\u0430\u0442\u0438 \u0434\u0435\u0458\u0441\u0442\u0432\u0430 \u043d\u0430 \u043a\u0435\u0448\u0443 \u0437\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0435 \u0442\u0440\u0430\u0436\u0435\u045a\u0430 \u0433\u0440\u0435\u0448\u0430\u043a\u0430 ConfigView.section.interface.enabletray=\u0423\u043a\u0459\u0443\u0447\u0438 \u0441\u0442\u0430\u0442\u0443\u0441\u043d\u0443 \u0442\u0440\u0430\u043a\u0443 [\u0442\u0440\u0430\u0436\u0438 \u0440\u0435\u0441\u0442\u0430\u0440\u0442] PeerManager.status.error=\u0413\u0440\u0435\u0448\u043a\u0430 Stats.title.full=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 TransferStatsView.title.full=\u041f\u0440\u0435\u043d\u043e\u0441\u0438 CacheView.title.full=\u041a\u0435\u0448 CacheView.general.size=\u0423\u043a\u0443\u043f\u043d\u0430 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430 CacheView.general.inUse=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0441\u0435 CacheView.general.title=\u041f\u043e\u0434\u0430\u0446\u0438 \u043e \u043a\u0435\u0448\u0443 CacheView.reads.title=\u0423/\u0418 \u0447\u0438\u0442\u0430\u045a\u0430 CacheView.reads.fromFile=\u0418\u0437 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 CacheView.reads.fromCache=\u0418\u0437 \u043a\u0435\u0448\u0430 CacheView.reads.hits=\u041f\u043e\u0433\u043e\u0446\u0438 CacheView.writes.title=\u0423/\u0418 \u0443\u043f\u0438\u0441\u0438 CacheView.writes.toCache=\u0423 \u043a\u0435\u0448 CacheView.writes.toFile=\u0423 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 CacheView.writes.hits=\u0421\u0430\u0447\u0443\u0432\u0430\u043d\u043e CacheView.speeds.title=\u0411\u0440\u0437\u0438\u043d\u0430 CacheView.speeds.reads=\u0427\u0438\u0442\u0430\u045a\u0430 CacheView.speeds.writes=\u0423\u043f\u0438\u0441\u0438 CacheView.speeds.fromCache=\u0418\u0437/\u0443 \u043a\u0435\u0448 CacheView.speeds.fromFile=\u0418\u0437/\u0443 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 CacheView.reads.#=\u0431\u0440. CacheView.reads.amount=\u0418\u0437\u043d\u043e\u0441 CacheView.reads.avgsize=\u0421\u0440. \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430 openUrl.referrer=\u0423\u0420\u041b \u0441\u0442\u0440\u0430\u043d\u0435 \u0437\u0430 \u043e\u0431\u0440\u0430\u045b\u0430\u045a\u0435 : openUrl.referrer.info=\u041f\u043e\u0442\u0440\u0435\u0431\u043d\u043e \u0458\u0435 \u0441\u0430\u043c\u043e \u0437\u0430 \u0435\u043b. \u043c\u0435\u0441\u0442\u0430 \u043a\u043e\u0458\u0430 \u0442\u043e \u0437\u0430\u0445\u0442\u0435\u0432\u0430\u0458\u0443 ConfigView.label.maxuploadspeedseeding=\u0414\u0440\u0443\u0433\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443 ConfigView.label.transfer.ignorepeerports=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0435 \u0441\u0430 \u043e\u0432\u0438\u043c \u043f\u043e\u0440\u0442\u043e\u0432\u0438\u043c\u0430 (\u0440\u0430\u0437\u0434\u0432\u043e\u0458\u0435\u043d\u043e \u0441\u0430 \u201e;\u201c \u043d\u043f\u0440 0;25) ConfigView.section.proxy.enable_socks.peer=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u0437\u0430\u0441\u0442\u0443\u043f\u0430\u045a\u0435 (proxying) \u043a\u043e\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0458\u0435 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 (\u0441\u0430\u043c\u043e \u043e\u0434\u043b\u0430\u0437\u043d\u0435 \u0432\u0435\u0437\u0435) [\u043d\u0435\u043e\u043f\u0445\u043e\u0434\u0430\u043d \u0440\u0435\u0441\u0442\u0430\u0440\u0442] ConfigView.section.proxy.peer.informtracker=\u041e\u0431\u0430\u0432\u0435\u0441\u0442\u0438 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 \u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0443 ConfigView.section.proxy.socks.version=\u0418\u0437\u0434\u0430\u045a\u0435 SOCKS\u0430 PiecesView.legend.written=\u0417\u0430\u043f\u0438\u0441\u0430\u043d\u043e PiecesView.legend.requested=\u041f\u043e\u0442\u0440\u0430\u0436\u0435\u043d\u043e PiecesView.legend.downloaded=\u041f\u0440\u0435\u0443\u0437\u0435\u0442\u043e, \u0447\u0435\u043a\u0430 \u0441\u0435 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441 PiecesView.legend.incache=\u041f\u043e\u0434\u0430\u0446\u0438 \u0441\u0443 \u0443 \u043a\u0435\u0448\u0443 PiecesView.typeItem.0=\u0411\u0440\u0437 PiecesView.typeItem.1=\u0421\u043f\u043e\u0440 PiecesView.type=\u0412\u0440\u0441\u0442\u0430 Security.jar.tools_not_found=\u041f\u043e\u0442\u043f\u0438\u0441\u0438\u0432\u0430\u045a\u0435 JAR \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e - \u201etools.jar\u201c \u043d\u0438\u0458\u0435 \u043d\u0430\u0452\u0435\u043d\u0430 %1. \u041f\u043e\u0433\u043b\u0435\u0434\u0430\u0458\u0442\u0435 \u201e\u0410\u043b\u0430\u0442\u0438->\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430->\u0411\u0435\u0437\u0431\u0435\u0434\u043d\u043e\u0441\u0442\u201c \u0437\u0430 \u0434\u0435\u0442\u0430\u0459\u0435. Security.jar.signfail=\u041f\u043e\u0442\u043f\u0438\u0441 JAR \u0430\u0440\u0445\u0438\u0432\u0435 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043e - %1 ConfigView.section.security.toolsinfo=\u041f\u043e\u0442\u043f\u0438\u0441\u0430\u043d\u0435 JAR \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0435 \u0434\u0430 \u043f\u043e\u0434\u0440\u0436\u0435 \u043d\u0435\u043a\u0435 \u0434\u043e\u0434\u0430\u0442\u043a\u0435, \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440 \u0421\u0432\u0438\u043d\u0433\u043e\u0432\u043e \u043c\u0440\u0435\u0436\u043d\u043e \u0441\u0443\u0447\u0435\u0459\u0435 (\u043a\u0430\u0434\u0430 \u0458\u0435 \u043f\u043e\u0434\u0435\u0448\u0435\u043d \u0434\u0430 \u0442\u0430\u043a\u043e \u0443\u0440\u0430\u0434\u0438).\n\u0414\u0430 \u0431\u0438 JAR \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0431\u0438\u043b\u0435 \u043f\u043e\u0442\u043f\u0438\u0441\u0430\u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e \u0458\u0435 \u0434\u0430 \u0438\u043c\u0430\u0442\u0435 \u043f\u0440\u0438\u0441\u0442\u0443\u043f \u201etools.jar\u201c \u043a\u043e\u0458\u0438 \u0434\u043e\u043b\u0430\u0437\u0438 \u0441\u0430 \u0421\u0430\u043d\u043e\u0432\u0438\u043c \u0408\u0414\u041a\u043e\u043c (\u043d\u0435 \u0408\u0420\u0415).\n\u0410\u043a\u043e \u0438\u043c\u0430\u0442\u0435 \u0441\u0430\u043c\u043e \u0408\u0420\u0415, \u043e\u043d\u0434\u0430 \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0434\u043e\u0434\u0430\u0442\u0435 \u0438 \u0408\u0414\u041a.\n\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u043e\u0431\u0438\u0447\u043d\u043e \u043c\u043e\u0436\u0435 \u0434\u0430 \u043f\u0440\u043e\u043d\u0430\u0452\u0435 \u043e\u0432\u0443 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u0437\u0430 \u0432\u0430\u0441. \u041c\u0435\u0452\u0443\u0442\u0438\u043c, \u0430\u043a\u043e \u043e\u0432\u043e \u043d\u0435 \u0443\u0441\u043f\u0435, \u043c\u043e\u0436\u0435\u0442\u0435 \u0435\u043a\u0441\u043f\u043b\u0438\u0446\u0438\u0442\u043d\u043e \u0434\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0437\u0430 \u043f\u0440\u0435\u0442\u0440\u0430\u0433\u0443. ConfigView.section.security.toolsdir=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440 \u043a\u043e\u0458\u0438 \u0441\u0430\u0434\u0440\u0436\u0438 \u201etools.jar\u201c ConfigView.section.security.choosetoolssavedir=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u043a\u043e\u0458\u0438 \u0441\u0430\u0434\u0440\u0436\u0438 \u201etools.jar\u201c authenticator.torrent=\u0422\u043e\u0440\u0435\u043d\u0442 ConfigView.section.proxy.peer.same=\u041a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u0438\u0441\u0442\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0437\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u043a\u0430 (proxy) \u0437\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 \u0438 \u0437\u0430 \u043a\u043e\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0458\u0443 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 ConfigView.section.connection.network.max.simultaneous.connect.attempts=\u041d\u0430\u0458\u0432\u0438\u0448\u0435 \u0438\u0441\u0442\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u0438\u0445 \u043e\u0434\u043b\u0430\u0437\u0435\u045b\u0438\u0445 \u0432\u0435\u0437\u0430 ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u0431\u0440\u043e\u0458 \u043f\u043e\u043a\u0443\u0448\u0430\u0458\u0430 \u043e\u0434\u043b\u0430\u0437\u043d\u0438\u0445 \u0432\u0435\u0437\u0430 \u043a\u043e\u0458\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u043f\u043e\u043a\u0443\u0448\u0430\u0432\u0430 \u0443 \u0434\u0430\u0442\u043e \u0432\u0440\u0435\u043c\u0435.\n\u041f\u0420\u0418\u041c\u0415\u0414\u0411\u0410: \u0412\u0438\u043d\u0434\u043e\u0432\u0441 \u0418\u043a\u0441-\u043f\u0435, \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0438 \u043f\u0430\u043a\u0435\u0442 2 (SP2) \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0441\u043a\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0435 \u043e\u0434 10 \u0438\u0441\u0442\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u0438\u0445 \u043f\u043e\u043a\u0443\u0448\u0430\u0458\u0430 \u0432\u0435\u0437\u0430.\n\u041f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0430 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442 \u0458\u0435 8. ConfigView.section.file.perf.cache.size.explain=\u041a\u0435\u0448 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0434\u0430 \u0443\u043c\u0430\u045a\u0438 \u0431\u0440\u043e\u0458 \u0447\u0438\u0442\u0430\u045a\u0430 \u0438 \u0443\u043f\u0438\u0441\u0430 \u043d\u0430 \u0434\u0438\u0441\u043a. \u041e\u0441\u0438\u043c \u0430\u043a\u043e \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u0458\u0430\u0432\u0438\u043d\u0443 \u043e\u043f\u0446\u0438\u0458\u0443 \u201e-XX:MaxDirectMemorySize\u201c \u0434\u0430 \u0435\u043a\u0441\u043f\u043b\u0438\u0446\u0438\u0442\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u043a\u043e\u043b\u0438\u0447\u0438\u043d\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0435 \u043c\u0435\u043c\u043e\u0440\u0438\u0458\u0435 \u0437\u0430 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 \u043a\u0435\u0448\u0430 \u0438 \u043c\u0435\u043c\u043e\u0440\u0438\u0458\u0435 \u0437\u0430 \u0443/\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0435, \u0442\u0440\u0435\u0431\u0430 \u0434\u0430 \u0434\u0440\u0436\u0438\u0442\u0435 \u043e\u0432\u043e \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 \u0431\u0430\u0440 %1 \u0438\u0441\u043f\u043e\u0434 \u0442\u0440\u0435\u043d\u0443\u0442\u043d\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u0435 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0435 \u0412\u041c. \u0422\u0440\u0435\u043d\u0443\u0442\u043d\u0430 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u0430 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u0412\u041c \u0458\u0435 %2. \u0417\u0430 \u0443\u043f\u0443\u0442\u0441\u0442\u0432\u043e \u043a\u0430\u043a\u043e \u0434\u0430 \u0442\u043e \u0443\u0440\u0430\u0434\u0438\u0442\u0435, \u0432\u0438\u0434\u0438\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0443 MemoryUsage \u043d\u0430 \u0432\u0438\u043a\u0438\u0458\u0443 \u043d\u0430 \u0430\u0434\u0440\u0435\u0441\u0438 %3. \u041d\u0435\u043c\u043e\u0433\u0443\u045b\u043d\u043e\u0441\u0442 \u0434\u0430 \u0441\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u0435 \u0441\u043c\u0438\u0441\u043b\u0435\u043d\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0434\u0430\u045b\u0435 \u0433\u0440\u0435\u0448\u043a\u0435 \u043e \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0443 \u043c\u0435\u043c\u043e\u0440\u0438\u0458\u0435. \u0412\u0438\u0448\u0435 \u043e\u0434 32MB \u043a\u0435\u0448\u0430 \u0458\u0435 \u0432\u0435\u0440\u043e\u0432\u0430\u0442\u043d\u043e \u0441\u0443\u0432\u0438\u0448\u0435. MyTorrentsView.menu.setSpeed.unlimit=\u041d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 MyTorrentsView.menu.setSpeed.unlimited=\u041d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 MyTorrentsView.menu.setSpeed.disable=\u0417\u0430\u0431\u0440\u0430\u043d\u0438 \u0441\u043b\u0430\u045a\u0435 MyTorrentsView.menu.setSpeed.disabled=\u0418\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u043e MyTorrentsView.menu.setSpeed.in=\u0443 MyTorrentsView.menu.setSpeed.slots=\u043f\u0440\u043e\u0440\u0435\u0437\u0430 \u043e\u0434 GeneralView.label.maxuploadspeed=\u0411\u0440\u0437. \u0441\u043b\u0430\u045a\u0430 GeneralView.label.maxuploadspeed.tooltip=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] MyTorrents.items.UpSpeedLimit.disabled=\u041d\u0435\u043c\u0430 \u0441\u043b\u0430\u045a\u0430 MyTorrents.items.UpSpeedLimit.unlimited=\u041d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 TableColumn.header.maxupspeed=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 TableColumn.header.maxupspeed.info=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 ConfigView.section.file.perf.cache.enable.write=\u041a\u0435\u0448\u0438\u0440\u0430\u0458 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0443 \u043a\u0430\u043a\u043e \u0431\u0438 \u0441\u0435 \u0443\u043c\u0430\u045a\u0438\u043e \u0431\u0440\u043e\u0458 \u0443\u043f\u0438\u0441\u0430\u043d \u043d\u0430 \u0434\u0438\u0441\u043a \u0438 \u0442\u0430\u043a\u043e\u0452\u0435 \u0443\u043c\u0430\u045a\u0438\u043e \u0431\u0440\u043e\u0458 \u0443\u043f\u0438\u0441\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u0438\u0445 \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 \u0434\u0435\u043b\u043e\u0432\u0430 ConfigView.section.file.perf.cache.enable.read=\u0427\u0438\u0442\u0430\u0458 \u0443\u043d\u0430\u043f\u0440\u0435\u0434 \u043a\u0430\u043a\u043e \u0431\u0438 \u0441\u0435 \u043f\u0440\u0438 \u0441\u043b\u0430\u045a\u0443 \u0443\u043c\u0430\u045a\u0438\u043e \u0431\u0440\u043e\u0458 \u0447\u0438\u0442\u0430\u045a\u0430 \u0434\u0438\u0441\u043a\u0430 ConfigView.section.tracker.separatepeerids=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0442\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0442\u0435\u0442\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u0437\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 \u0438 \u043f\u0440\u043e\u043c\u0435\u0442 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 ConfigView.section.tracker.separatepeerids.info=\u041f\u043e\u0432\u0435\u045b\u0430\u0432\u0430 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e\u0441\u0442 \u043f\u0440\u0438 \u0441\u043b\u0430\u045a\u0443 \u0438 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e\u043c \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443\n\u043f\u0440\u0438 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0438 \u043d\u0435-\u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0438\u0445 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 ConfigView.section.interface.wavlocation=\u041c\u0435\u0441\u0442\u043e .wav \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 ConfigView.section.interface.wavlocation.info=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 .wav \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u0438 \u043f\u0440\u0430\u0437\u043d\u043e \u0437\u0430 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0438 \u0437\u0432\u0443\u043a ConfigView.section.tracker.server=\u0421\u0435\u0440\u0432\u0435\u0440 ConfigView.section.tracker.client=\u041a\u043b\u0438\u0458\u0435\u043d\u0442 ConfigView.section.tracker.client.connecttimeout=\u0412\u0440\u0435\u043c\u0435 \u0437\u0430 \u043f\u043e\u0432\u0435\u0437\u0438\u0432\u0430\u045a\u0435 (\u0441\u0435\u043a\u0443\u043d\u0434\u0438) ConfigView.section.tracker.client.readtimeout=\u0412\u0440\u0435\u043c\u0435 \u0447\u0438\u0442\u0430\u045a\u0430 (\u0441\u0435\u043a\u0443\u043d\u0434\u0438) MainWindow.menu.tools=&\u0410\u043b\u0430\u0442\u043a\u0435 FilesView.path=\u0421\u0442\u0430\u0437\u0430 FilesView.fullpath=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u043f\u0443\u043d\u0443 \u0441\u0442\u0430\u0437\u0443 FilesView.remaining=\u041f\u0440\u0435\u043e\u0441\u0442\u0430\u043b\u0438 \u0434\u0435\u043b\u043e\u0432\u0438 TableColumn.header.trackername=\u0418\u043c\u0435 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 TableColumn.header.trackername.info=\u0418\u043c\u0435 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 \u0437\u0430\u0441\u043d\u043e\u0432\u0430\u043d\u043e \u043d\u0430 \u0423\u0420\u041b\u0443 \u0437\u0430 \u043d\u0430\u0458\u0430\u0432\u0443 ConfigView.group.override=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0437\u0430 \u043f\u0440\u0435\u0438\u043d\u0430\u0447\u0435\u045a\u0435 ConfigView.section.file.perf.cache.notsmallerthan=\u041d\u0435 \u043a\u0435\u0448\u0438\u0440\u0430\u0458 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u043c\u0430\u045a\u0435 \u043e\u0434 \u043e\u0432\u043e\u0433 (\u0443 %1) PeersView.menu.blockupload=\u0411\u043b\u043e\u043a\u043e\u0432\u0441\u043a\u043e \u0441\u043b\u0430\u045a\u0435 PeersView.menu.kickandban=\u0418\u0437\u0431\u0430\u0446\u0438 \u0438 \u0443\u045b\u0443\u0442\u043a\u0430\u0458 PeersView.menu.kickandban.reason=\u0420\u0443\u0447\u043d\u043e \u0443\u045b\u0443\u0442\u043a\u0430\u043d\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438 PeersView.state=\u0421\u0442\u0430\u045a\u0435 PeersView.state.info=\u0421\u0442\u0430\u045a\u0435 \u0432\u0435\u0437\u0435 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 PeersView.state.pending=\u041d\u0430 \u0447\u0435\u043a\u0430\u045a\u0443 PeersView.state.connecting=\u041f\u043e\u0432\u0435\u0437\u0438\u0432\u0430\u045a\u0435 PeersView.state.handshake=\u0427\u0435\u043a\u0430\u045a\u0435 \u043d\u0430 \u0441\u0443\u0441\u0440\u0435\u0442 PeersView.state.established=\u041f\u043e\u0442\u043f\u0443\u043d\u043e \u0443\u0441\u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u043e ConfigView.section.tracker.processinglimits=\u0413\u0440\u0430\u043d\u0438\u0446\u0435 \u043e\u0431\u0440\u0430\u0434\u0435 ConfigView.section.tracker.maxgettime=\u041d\u0430\u0458\u0432\u0435\u045b\u0435 \u0432\u0440\u0435\u043c\u0435 \u0437\u0430 \u043e\u0431\u0440\u0430\u0434\u0443 GET (\u0441\u0435\u043a\u0443\u043d\u0434\u0438) [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.tracker.maxgettime.info=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0441\u0435 \u0437\u0430 \u043d\u0430\u0458\u0430\u0432\u0435 \u0438 \u0447\u0438\u0448\u045b\u0435\u045a\u0435 ConfigView.section.tracker.maxposttimemultiplier=\u041c\u043d\u043e\u0436\u0438\u043b\u0430\u0446 \u0437\u0430 GET \u043a\u043e\u0458\u0438 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0437\u0430 \u043e\u0431\u0440\u0430\u0434\u0443 POST [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.tracker.maxposttimemultiplier.info=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0441\u0435 \u0437\u0430 \u043f\u043e\u0434\u043d\u043e\u0448\u0435\u045a\u0435 \u0444\u043e\u0440\u043c\u0443\u043b\u0430\u0440\u0430 \u0438 \u0441\u043b\u0430\u045a\u0435 ConfigView.section.tracker.maxthreads=\u041d\u0430\u0458\u0432\u0438\u0448\u0435 \u0438\u0441\u0442\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u0438\u0445 \u0437\u0430\u0445\u0442\u0435\u0432\u0430 DownloadManager.error.operationcancancelled=\u0414\u0435\u0458\u0441\u0442\u0432\u043e \u0458\u0435 \u043e\u0442\u043a\u0430\u0437\u0430\u043d\u043e Torrent.create.progress.cancelled=\u0414\u0435\u0458\u0441\u0442\u0432\u043e \u0458\u0435 \u043e\u0442\u043a\u0430\u0437\u0430\u043d\u043e sharing.progress.cancel=\u041e\u0442\u043a\u0430\u0436\u0438 wizard.maketorrents.autoopen=\u041e\u0442\u0432\u043e\u0440\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0437\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 \u043d\u0430 \u043a\u0440\u0430\u0458\u0443 ConfigView.section.sharing.rescanenable=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u043d\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 \u0434\u0435\u0459\u0435\u045a\u0430 \u043a\u0430\u043a\u043e \u0431\u0438 \u0441\u0435 \u0432\u0438\u0434\u0435\u043b\u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u0435 ConfigView.section.sharing.rescanperiod=\u041f\u0435\u0440\u0438\u043e\u0434 \u043f\u0440\u043e\u0432\u0435\u0440\u0435 (\u0441\u0435\u043a\u0443\u043d\u0434\u0435) ConfigView.section.connection.advanced=\u041d\u0430\u043f\u0440\u0435\u0434\u043d\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u043c\u0440\u0435\u0436\u0435 ConfigView.section.connection.advanced.mtu=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0458\u0435\u0434\u0438\u043d\u0438\u0446\u0430 \u0441\u043b\u0430\u045a\u0430 \u0437\u0430 \u043b\u0438\u043d\u0438\u0458\u0443 (MTU) ConfigView.section.connection.advanced.mtu.tooltip=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u043f\u0430\u043a\u0435\u0442\u0430 \u043a\u043e\u0458\u0430 \u0441\u0435 \u043f\u0440\u0435\u043d\u043e\u0441\u0438 \u0443 \u0458\u0435\u0434\u043d\u043e\u043c \u0440\u0430\u043c\u0443 \u043f\u0440\u0435\u043a\u043e \u043c\u0440\u0435\u0436\u0435.\n\u0410\u0437\u0443\u0440\u0435\u0437\u0443\u0441 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 MTU-40 (MSS) \u0437\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0458\u0443 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u0443 \u043f\u0430\u043a\u0435\u0442\u0443\n\u041f\u0440\u0435\u043f\u043e\u0440\u0443\u0447\u0435\u043d\u0435 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442\u0438:\n 576 - \u041c\u043e\u0434\u0435\u043c\u0441\u043a\u0430 \u0432\u0435\u0437\u0430\n1492 - PPPoE \u0432\u0435\u0437\u0430 \u0432\u0438\u0441\u043e\u043a\u0435 \u043f\u0440\u043e\u043f\u0443\u0441\u043d\u0435 \u043c\u043e\u045b\u0438\n1500 - \u0415\u0442\u0435\u0440\u043d\u0435\u0442, \u0414\u0421\u041b \u0438 \u043a\u0430\u0431\u043b\u043e\u0432\u0441\u043a\u0430 \u0432\u0435\u0437\u0430 ConfigView.section.connection.advanced.SO_RCVBUF=\u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 SO_RCVBUF \u0443\u0442\u0438\u0447\u043d\u0438\u0446\u0435 [0: \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0443 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=\u041f\u043e\u0441\u0442\u0430\u0432\u0459\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0434\u043d\u0443 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 SO_RCVBUF (\u0443 \u0431\u0430\u0458\u0442\u043e\u0432\u0438\u043c\u0430), \u0442\u0458. \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 \u043f\u0440\u0438\u0458\u0435\u043c\u043d\u043e\u0433 \u043f\u0440\u043e\u0437\u043e\u0440\u0430 \u0438 \u0441\u043a\u0430\u043b\u0438\u0440\u0430\u045a\u0435 \u0422\u0426\u041f\u0430.\n\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u043e \u043d\u0435 \u043c\u0435\u045a\u0430 \u043e\u0432\u0443 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442, \u0448\u0442\u043e \u0437\u043d\u0430\u0447\u0438 \u0434\u0430 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0435 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u0434\u0430\u0442\u0435 \u0443 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u0443.\n\u041f\u0440\u0438\u043c\u0435\u0434\u0431\u0430: \u041b\u0438\u043d\u0443\u043a\u0441 \u0443\u0434\u0432\u043e\u0441\u0442\u0440\u0443\u0447\u0443\u0458\u0435 \u043e\u0432\u0443 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442. ConfigView.section.connection.advanced.SO_SNDBUF=\u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 SO_SNDBUF \u0437\u0430 \u0443\u0442\u0438\u0447\u043d\u0438\u0446\u0443 [0: \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u043e \u0437\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u0438 \u0441\u0438\u0441\u0442\u0435\u043c] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=\u041f\u043e\u0441\u0442\u0430\u0432\u0459\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u043d\u0443 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 SO_SNDBUF (\u0443 \u0431\u0430\u0458\u0442\u043e\u0432\u0438\u043c\u0430), \u0442\u0458. \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 \u0422\u0426\u041f\u043e\u0432\u043e\u0433 \u043f\u0440\u043e\u0437\u043e\u0440\u0430 \u0437\u0430 \u0441\u043b\u0430\u045a\u0435.\n\u0410\u0443\u0437\u0440\u0435\u0443\u0441 \u043e\u0441\u0442\u0430\u0432\u0459\u0430 \u043e\u0432\u043e \u043d\u0435\u043f\u043e\u0434\u0435\u0448\u0435\u043d\u043e, \u0448\u0442\u043e \u0437\u043d\u0430\u0447\u0438 \u0434\u0430 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0435 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u0434\u0430\u0442\u0435 \u0443 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u0443.\n\u041f\u0440\u0438\u043c\u0435\u0434\u0431\u0430:\u041b\u0438\u043d\u0443\u043a\u0441 \u0443\u0434\u0432\u043e\u0441\u0442\u0440\u0443\u0447\u0443\u0458\u0435 \u043e\u0432\u0443 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442. ConfigView.section.interface.confirm_torrent_removal=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u043f\u0440\u043e\u0437\u043e\u0440 \u0437\u0430 \u043f\u043e\u0442\u0432\u0440\u0434\u0443 \u0437\u0430 \u0443\u043a\u043b\u0430\u045a\u0430\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 ConfigView.section.interface.confirm_torrent_removal.tooltip=\u041f\u043e\u0442\u0432\u0440\u0434\u0438 \u0443\u043a\u043b\u0430\u045a\u0430\u043b\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0438\u0437 \u043f\u0440\u0435\u0433\u043b\u0435\u0434\u0430 \u041c\u043e\u0458\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0430. MyTorrentsView.confirm_torrent_removal=\u0414\u0430 \u043b\u0438 \u0441\u0438\u0433\u0443\u0440\u043d\u043e \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u0443\u043a\u043b\u043e\u043d\u0438\u0442\u0435?\n TableColumn.header.seed_to_peer_ratio=\u041e\u0434\u043d\u043e\u0441 \u0431\u0440\u043e\u0458\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 \u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 TableColumn.header.seed_to_peer_ratio.info=\u041e\u0434\u043d\u043e\u0441 \u0431\u0440\u043e\u0458\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 \u0443 \u0440\u043e\u0458\u0443 \u0438 \u0431\u0440\u043e\u0458\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 PeersView.connected_time=\u0412\u0440\u0435\u043c\u0435 \u0432\u0435\u0437\u0435 PeersView.connected_time.info=\u0423\u043a\u0443\u043f\u043d\u043e \u0432\u0440\u0435\u043c\u0435 \u0432\u0435\u0437\u0435 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 ConfigView.section.interface.display.add_torrents_silently=\u0422\u0438\u0445\u043e \u0434\u043e\u0434\u0430\u0432\u0430\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 ConfigView.section.interface.display.add_torrents_silently.tooltip=\u0414\u043e\u0434\u0430\u0458 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0443\u0458\u0443\u045b\u0438 \u0433\u043b\u0430\u0432\u043d\u0438 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432 \u043f\u0440\u043e\u0437\u043e\u0440 TableColumn.header.maxdownspeed=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 TableColumn.header.maxdownspeed.info=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 PeersGraphicView.title=\u0420\u043e\u0458 ConfigView.section.tracker.passwordwebhttpsonly=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f \u0441\u0430\u043c\u043e \u043a\u0440\u043e\u0437 HTTPS TableColumn.header.torrentpath=\u041c\u0435\u0441\u0442\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0430 TableColumn.header.torrentpath.info=\u041c\u0435\u0441\u0442\u043e \u0433\u0434\u0435 \u0441\u0435 \u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u0447\u0443\u0432\u0430\u0458\u0443 \u043d\u0430 \u0434\u0438\u0441\u043a\u0443 ConfigView.section.sharing.torrentcomment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440\u0438 \u0437\u0430 \u043d\u0430\u0447\u0438\u045a\u0435\u043d\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 ConfigView.label.copyanddeleteratherthanmove=\u0420\u0430\u0437\u0434\u0432\u0430\u0458\u0430\u045a\u0435 \u0443\u043c\u043d\u043e\u0436\u0430\u0432\u0430\u045a\u0430 \u0438 \u0443\u043a\u043b\u0430\u045a\u0430\u045a\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u0443 \u0434\u0432\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0458\u0435, \u0443\u043c\u0435\u0441\u0442\u043e \u043f\u043e\u043c\u0435\u0440\u0430\u045a\u0430 \u0443 \u0458\u0435\u0434\u043d\u043e\u043c \u043f\u043e\u0442\u0435\u0437\u0443 - \u043e\u0432\u043e \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u043f\u0440\u0435\u0447\u0438 \u0433\u0443\u0431\u0438\u0442\u0430\u043a \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u043d\u0430 \u043d\u0435\u043a\u0438\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u0438\u043c\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 ConfigView.label.openstatsonstart=\u041e\u0442\u0432\u043e\u0440\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 \u043f\u0440\u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0443 swt.install.window.title=\u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432 \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0430\u0447 \u0434\u043e\u0434\u0430\u0442\u0430\u043a\u0430 swt.install.window.ok=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 swt.install.window.header=\u041d\u0430\u0440\u0435\u0434\u043d\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u0441\u0443 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0435 \u0437\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0430\u045a\u0435 : swt.uninstall.window.title=\u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432 \u0443\u043a\u043b\u0430\u045a\u0430\u0447 \u0434\u043e\u0434\u0430\u0442\u0430\u043a\u0430 swt.uninstall.window.ok=\u0423\u043a\u043b\u043e\u043d\u0438 swt.uninstall.window.header=\u041d\u0430\u0440\u0435\u0434\u043d\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u0441\u0443 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0435 \u0437\u0430 \u0443\u043a\u043b\u0430\u045a\u0430\u045a\u0435 : installPluginsWizard.title=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u0434\u043e\u0434\u0430\u0442\u043a\u0435 installPluginsWizard.mode.title=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0438\u0437\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u043d\u0430\u0447\u0438\u043d \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0430\u045a\u0430 installPluginsWizard.mode.list=\u041f\u0440\u0435\u043c\u0430 \u0441\u043f\u0438\u0441\u043a\u0443 \u0441\u0430 sourceforge.net installPluginsWizard.list.title=\u0421\u043f\u0438\u0441\u0430\u043a \u0434\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u043a\u043e\u0458\u0438 \u0441\u0435 \u043c\u043e\u0433\u0443 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0438 installPluginsWizard.list.loading=\u041c\u043e\u043b\u0438\u043c\u043e \u0412\u0430\u0441 \u0434\u0430 \u0441\u0430\u0447\u0435\u043a\u0430\u0442\u0435 \u0434\u043e\u043a \u0441\u0435 \u0441\u043f\u0438\u0441\u0430\u043a \u0434\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u0443\u0447\u0438\u0442\u0430. installPluginsWizard.list.loaded=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0438\u0437\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u0434\u043e\u0434\u0430\u0442\u043a\u0435 \u043a\u043e\u0458\u0435 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435. installPluginsWizard.list.name=\u0418\u043c\u0435 installPluginsWizard.list.version=\u0418\u0437\u0434\u0430\u045a\u0435 installPluginsWizard.list.description=\u041e\u043f\u0438\u0441 \u0434\u043e\u0434\u0430\u0442\u043a\u0430 installPluginsWizard.finish.title=\u041f\u043e\u0441\u0442\u0430\u0432\u0459\u0430\u045a\u0435 \u0458\u0435 \u0443 \u0442\u043e\u043a\u0443 installPluginsWizard.finish.explanation=\u0418\u0437\u0430\u0431\u0440\u0430\u043d\u0438 \u0434\u043e\u0434\u0430\u0446\u0438 \u0447\u0435 \u0431\u0438\u0442\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u0438 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u043e\u043c \u0441\u0430\u0440\u0430\u0434\u043d\u0438\u043a\u0430 \u0437\u0430 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0443.\n\n\u041c\u043e\u043b\u0438\u043c\u043e \u0412\u0430\u0441 \u0437\u0430 \u043c\u0430\u043b\u043e \u0441\u0442\u0440\u043f\u0459\u0435\u045a\u0430, \u0431\u0438\u045b\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e \u043c\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0430 \u0434\u0430 \u0441\u0435 \u043f\u0440\u0438\u043a\u0430\u0436\u0443.\n\n\u0417\u0430 \u0438\u0437\u0432\u0435\u0448\u0442\u0430\u0458 \u043e \u043d\u0430\u043f\u0440\u0435\u0442\u043a\u0443, \u0434\u0432\u0430\u043f\u0443\u0442 \u043f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u0441\u0442\u0430\u0442\u0443\u0441\u043d\u0443 \u0442\u0440\u0430\u043a\u0443. installPluginsWizard.details.loading=\u0414\u0435\u0442\u0430\u0459\u0438 \u0441\u0435 \u0443\u0447\u0438\u0442\u0430\u0432\u0430\u0458\u0443, \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0441\u0430\u0447\u0435\u043a\u0430\u0442\u0435... installPluginsWizard.mode.file=\u041f\u043e \u0434\u0430\u0442\u043e\u0442\u0435\u0446\u0438 installPluginsWizard.installMode.title=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043e\u0434\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u0432\u0440\u0441\u0442\u0443 \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0430\u045a\u0430 installPluginsWizard.installMode.user=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u0434\u043e\u0434\u0430\u0442\u043a\u0435 \u0441\u0430\u043c\u043e \u0437\u0430 \u0412\u0430\u0441 installPluginsWizard.installMode.shared=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u0434\u043e\u0434\u0430\u0442\u043a\u0435 \u0437\u0430 \u0441\u0432\u0435 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u043a\u0435 installPluginsWizard.file.title=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0438\u0437\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u0434\u043e\u0434\u0430\u0442\u043a\u0435 \u043a\u043e\u0458\u0435 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 installPluginsWizard.file.file=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 : installPluginsWizard.file.invalidfile=\u041e\u0432\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043d\u0438\u0458\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u0430\u043d \u0434\u043e\u0434\u0430\u0442\u0430\u043a \u0437\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441. installPluginsWizard.file.no_such_file=\u041d\u0435\u043c\u0430 \u043d\u0438\u0458\u0435\u0434\u043d\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0441\u0430 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u043c \u0438\u043c\u0435\u043d\u043e\u043c. installPluginsWizard.file.browse=\u041f\u0440\u0435\u0433\u043b\u0435\u0434... uninstallPluginsWizard.title=\u0423\u043a\u043b\u043e\u043d\u0438 \u0434\u043e\u0434\u0430\u0442\u0430\u043a uninstallPluginsWizard.list.title=\u0421\u043f\u0438\u0441\u0430\u043a \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u0438\u0445 \u0434\u043e\u0434\u0430\u0442\u0430\u043a\u0430 uninstallPluginsWizard.list.loaded=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0438\u0437\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u0434\u043e\u0434\u0430\u0442\u043a\u0435 \u043a\u043e\u0458\u0435 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u0443\u043a\u043b\u043e\u043d\u0438\u0442\u0435. installPluginsWizard.list.nullversion=\u041d\u0435\u043c\u0430 \u043e\u0437\u043d\u0430\u043a\u0435 \u0438\u0437\u0434\u0430\u045a\u0430 uninstallPluginsWizard.finish.title=\u0423\u043a\u043b\u0430\u045a\u0430\u045a\u0435 \u0458\u0435 \u0443 \u0442\u043e\u043a\u0443 uninstallPluginsWizard.finish.explanation=\u0418\u0437\u0430\u0431\u0440\u0430\u043d\u0438 \u0434\u043e\u0434\u0430\u0446\u0438 \u0431\u0438\u045b\u0435 \u0443\u043a\u043b\u043e\u045a\u0435\u043d\u0438 \u043f\u043e\u043c\u043e\u045b\u0443 \u0441\u0430\u0440\u0430\u0434\u043d\u0438\u043a\u0430 \u0437\u0430 \u0434\u043e\u0434\u0430\u0442\u043a\u0435. MainWindow.menu.plugins.installPlugins=\u0427\u0430\u0440\u043e\u0431\u045a\u0430\u043a \u0437\u0430 \u0434\u043e\u0434\u0430\u0442\u043a\u0435... MainWindow.menu.plugins.uninstallPlugins=\u0427\u0430\u0440\u043e\u0431\u045a\u0430\u043a \u0437\u0430 \u0443\u043a\u043b\u0430\u045a\u0430\u045a\u0435 \u0434\u043e\u0434\u0430\u0442\u0430\u043a\u0430... ConfigView.section.ipfilter.totalIPs=\u0411\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0438\u0445 \u0430\u0434\u0440\u0435\u0441\u0430 %1 , \u0448\u0442\u043e \u0447\u0438\u043d\u0438 %2 \u0446\u0435\u043b\u043e\u0433 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430. update.instance.install=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0430\u045a\u0430 update.instance.uninstall=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u0443\u043a\u043b\u0430\u045a\u0430\u045a\u0430 update.instance.update=\u041f\u0440\u043e\u0432\u0435\u0440\u0430\u0432\u0430\u045a\u0435 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0438... MainWindow.status.update.tooltip=\u0414\u0432\u0430\u043f\u0443\u0442 \u043f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u043e \u043d\u0430\u043f\u0440\u0435\u0442\u043a\u0443 updater.progress.window.title=\u0422\u0440\u0435\u043d\u0443\u0442\u043d\u043e \u0430\u043a\u0442\u0438\u0432\u043d\u0435 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0435 updater.progress.window.info=\u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u201e\u041e\u0442\u043a\u0430\u0436\u0438\u201c \u043a\u0430\u043a\u043e \u0431\u0438\u0441\u0442\u0435 \u0437\u0430\u0443\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0441\u0432\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u0435 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0435 Button.abort=\u041e\u0442\u043a\u0430\u0436\u0438 ConfigView.section.ipfilter.enablebanning=\u0423\u045b\u0443\u0442\u043a\u0430\u0458 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0435 \u043a\u043e\u0458\u0438 \u0441\u0442\u0430\u043b\u043d\u043e \u0448\u0430\u0459\u0443 \u043b\u043e\u0448\u0435 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 Network.alert.acceptfail=\u0421\u0443\u0432\u0438\u0448\u0435 \u0443\u0437\u0430\u0441\u0442\u043e\u043f\u043d\u0438\u0445 \u0433\u0440\u0435\u0448\u0430\u043a\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 %1, %2 - \u043e\u0431\u0440\u0430\u0434\u0430 \u0458\u0435 \u043d\u0430\u043f\u0443\u0448\u0442\u0435\u043d\u0430. \u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d\u0430 \u0437\u0430 \u043e\u0432\u0430\u0458 \u043f\u043e\u0440\u0442 \u043a\u0430\u043a\u043e \u0431\u0438\u0441\u0442\u0435 \u0431\u0438\u043b\u0438 \u0441\u0438\u0433\u0443\u0440\u043d\u0438 \u0434\u0430 \u0458\u0435 \u0443\u043a\u0459\u0443\u0447\u0435\u043d \u0437\u0430 \u043f\u0440\u0438\u043c\u0459\u0435\u043d\u0435 \u0432\u0435\u0437\u0435. MyShares.column.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0430 UpdateWindow.restartLater=\u041f\u043e\u043a\u0440\u0435\u043d\u0438 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 \u043f\u043e\u043d\u043e\u0432\u043e, \u0430\u043b\u0438 \u043a\u0430\u0441\u043d\u0438\u0458\u0435 MainWindow.menu.file.restart=\u041f\u043e\u043a\u0440\u0435\u043d\u0438 \u043f\u043e\u043d\u043e\u0432\u043e MainWindow.dialog.restartconfirmation.title=\u0414\u0430 \u043b\u0438 \u0434\u0430 \u043f\u043e\u043d\u043e\u0432\u043e \u043f\u043e\u043a\u0440\u0435\u043d\u0435\u043c \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430? MainWindow.dialog.restartconfirmation.text=\u0414\u0430 \u043b\u0438 \u0437\u0430\u0438\u0441\u0442\u0430 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0443\u0458\u0435\u0442\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430? deletetorrent.message1=\u0421\u0430\u043c\u043e \u0448\u0442\u043e \u043d\u0438\u0441\u0442\u0435 \u0443\u043a\u043b\u043e\u043d\u0438\u043b\u0438 \u0422\u041e\u0420\u0415\u041d\u0422 \u0437\u0430 :\n deletetorrent.message2=\n\u0414\u0430 \u043b\u0438 \u0441\u0438\u0433\u0443\u0440\u043d\u043e \u0434\u0430 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u043d\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u0435? ConfigView.label.prioritizemostcompletedfiles=\u0423\u0440\u0435\u0434\u0438 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0441\u0430 \u0432\u0438\u0441\u043e\u043a\u043e\u043c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u043f\u0440\u0435\u043c\u0430 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u0443 \u0437\u0430\u0432\u0440\u0448\u0435\u0442\u043a\u0430 \u0438 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0438 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 splash.plugin.init=\u041f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u0434\u043e\u0434\u0430\u0442\u043a\u0430: ConfigView.section.style.osx_small_fonts=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0441\u0438\u0442\u043d\u0430 \u0441\u043b\u043e\u0432\u0430 [\u0442\u0440\u0430\u0436\u0438 \u043f\u043e\u043d\u043e\u0432\u043d\u043e \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435] ConfigView.section.tracker.tcpnonblocking=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u043d\u0435-\u0431\u043b\u043e\u043a\u0438\u0440\u0430\u0458\u0443\u045b\u0438 \u0423\u0418 \u0437\u0430 \u043e\u0431\u0440\u0430\u0434\u0443 \u0422\u0426\u041f \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430. \u0411\u0438\u0440\u0430\u045a\u0435 \u043e\u0432\u0435 \u043c\u043e\u0433\u0443\u045b\u043d\u043e\u0441\u0442 \u0442\u0440\u0430\u0436\u0438 \u0434\u0430 \u0441\u0435 \u0437\u0430 \u043c\u0440\u0435\u0436\u0443 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0434\u0440\u0443\u0433\u0438 \u043f\u043e\u0440\u0442. \u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u043d\u043e! ConfigView.section.tracker.nonblocking=\u041d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0430\u0458\u0443\u045b\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 ConfigView.section.tracker.nonblockingconcmax=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u0431\u0440\u043e\u0458 \u0438\u0441\u0442\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u0438\u0445 \u0432\u0435\u0437\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] MyTorrentsView.menu.exportmenu=\u0418\u0437\u0432\u043e\u0437 MyTorrentsView.menu.exporttorrent=\u0422\u043e\u0440\u0435\u043d\u0442... ConfigView.group.scrape=\u0427\u0438\u0448\u045b\u0435\u045a\u0435 ConfigView.section.tracker.client.scrapeinfo=\u0418\u0441\u043a\u0459\u0443\u0447\u0438\u0432\u0430\u045a\u0435 \u0447\u0438\u0448\u045b\u0435\u045a\u0430 \u045b\u0435 \u0441\u043f\u0440\u0435\u0447\u0438\u0442\u0438 \u043c\u043d\u043e\u0433\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0437\u0430 \u0443\u0440\u0435\u0452\u0438\u0432\u0430\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0434\u0430 \u0440\u0430\u0434\u0435 \u043f\u043e\u0448\u0442\u043e \u0441\u0435 \u043e\u0441\u043b\u0430\u045a\u0430\u0458\u0443 \u043d\u0430 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u043a\u043e\u0458\u0435 \u0434\u043e\u0431\u0430\u0432\u0459\u0430\u0458\u0443 \u043e\u0434 \u0447\u0438\u0448\u045b\u0435\u043d\u0438\u0445 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430. ConfigView.section.tracker.client.scrapeenable=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u0447\u0438\u0448\u045b\u0435\u045a\u0435 ConfigView.section.tracker.client.scrapestoppedenable=\u041e\u0447\u0438\u0441\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u043a\u043e\u0458\u0438 \u043d\u0438\u0441\u0443 \u043f\u043e\u043a\u0440\u0435\u043d\u0443\u0442\u0438 Scrape.status.disabled=\u0427\u0438\u0448\u045b\u0435\u045a\u0435 \u0458\u0435 \u0438\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u043e MyTorrentsView.menu.explore=\u041f\u043e\u043a\u0430\u0436\u0438 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 MyTorrentsView.menu.explore._mac=\u041f\u043e\u043a\u0430\u0436\u0438 \u0443 \u043f\u0440\u0435\u0442\u0440\u0430\u0437\u0438 MyTorrentsView.menu.explore._windows=\u041f\u043e\u043a\u0430\u0436\u0438 \u0443 \u0438\u0441\u0442\u0440\u0430\u0436\u0438\u0432\u0430\u0447\u0443 wizard.maketorrents.autohost=\u0423\u0433\u043e\u0441\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0430 \u0443\u0433\u0440\u0430\u0452\u0435\u043d\u043e\u043c \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0443 ConfigView.label.overrideip=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 \u043e\u0431\u0458\u0430\u0432\u0459\u0435\u043d\u0435 \u0418\u041f\u043e\u0432\u0435 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 - \u0441\u043f\u0438\u0441\u0430\u043a \u0440\u0430\u0437\u0434\u0432\u043e\u0458\u0435\u043d \u0442\u0430\u0447\u043a\u0430-\u0437\u0430\u043f\u0435\u0442\u0430\u043c\u0430 \u0443\u043a\u043e\u043b\u0438\u043a\u043e \u0438\u0445 \u0438\u043c\u0430 \u0432\u0438\u0448\u0435 \u0437\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0442\u0435 \u043c\u0440\u0435\u0436\u0435 ConfigView.label.overrideip.tooltip=\u041e\u0431\u0430\u0432\u0435\u0441\u0442\u0438 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 \u043e \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0442\u0438\u043c \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0430\u043c\u0430 \u0441\u0430 \u043a\u043e\u0458\u0438\u0445 \u0434\u043e\u043b\u0430\u0437\u0438 \u043d\u0435\u043a\u0438 \u043f\u0430\u043a\u0435\u0442. \u041e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u043f\u0440\u0430\u0437\u043d\u043e \u0434\u0430 \u043d\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u043e\u0432\u0443 \u043c\u043e\u0433\u0443\u045b\u043d\u043e\u0441\u0442. ConfigView.section.connection.group.networks=\u041c\u0440\u0435\u0436\u0435 ConfigView.section.connection.group.networks.info=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0435 \u0434\u043e\u0437\u0432\u043e\u0459\u0435\u043d\u0435 \u043c\u0440\u0435\u0436\u0435 \u0437\u0430 \u043f\u0440\u0435\u043d\u043e\u0441 ConfigView.section.connection.networks.prompt=\u0423\u043f\u0438\u0442\u0430\u0458 \u0437\u0430 \u0438\u0437\u0431\u043e\u0440 \u043f\u0440\u0438 \u043f\u0440\u0438\u0458\u0435\u043c\u0443 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e\u0433 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 ConfigView.section.connection.networks.Public=\u0408\u0430\u0432\u043d\u0430 \u0418\u041f \u043c\u0440\u0435\u0436\u0430 (\u043d\u0438\u0458\u0435 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0430) ConfigView.section.connection.networks.I2P=\u04182\u041f \u043c\u0440\u0435\u0436\u0430 ConfigView.section.connection.networks.Tor=\u041c\u0440\u0435\u0436\u0430 \u043b\u0443\u043a\u043e\u0432\u0438\u0446\u0435 (\u0422\u043e\u0440) TableColumn.header.networks=\u041c\u0440\u0435\u0436\u0435 TableColumn.header.networks.info=\u041c\u0440\u0435\u0436\u0435 \u0441\u0430 \u043a\u043e\u0458\u0438\u0445 \u0458\u0435 \u0434\u043e\u0437\u0432\u043e\u0459\u0435\u043d\u0430 \u043a\u043e\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0458\u0430 Scrape.status.networkdisabled=\u041c\u0440\u0435\u0436\u0430 \u043d\u0438\u0458\u0435 \u0443\u043a\u0459\u0443\u0447\u0435\u043d\u0430 ConfigView.section.tracker.server.group.networks=\u041c\u0440\u0435\u0436\u0435 ConfigView.section.tracker.server.group.networks.info=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u043c\u0440\u0435\u0436\u0435 \u0441\u0430 \u043a\u043e\u0458\u0438\u0445 \u045b\u0435 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 \u0434\u043e\u0437\u0432\u043e\u0459\u0430\u0432\u0430\u0442\u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 window.networkselection.title=\u0418\u0437\u0431\u043e\u0440 \u043c\u0440\u0435\u0436\u0435 window.networkselection.info=\u041d\u0430\u0432\u0435\u0434\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043f\u043e\u0434\u0440\u0436\u0430\u0432\u0430\u0458\u0443 \u043d\u0430\u0440\u0435\u0434\u043d\u0435 \u043c\u0440\u0435\u0436\u0435.\n\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u043d\u0435 \u043a\u043e\u0458\u0438 \u0434\u043e\u0437\u0432\u043e\u0459\u0430\u0432\u0430\u0458\u0443 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0435 \u0438 \u043a\u043e\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0458\u0443.\n\u0410\u043a\u043e \u0458\u0435 \u043e\u0432\u043e \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0438 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 \u043a\u043e\u0458\u0438 \u043f\u043e\u0434\u0440\u0436\u0430\u0432\u0430 \u0458\u0430\u0432\u043d\u0435 \u043a\u043b\u0438\u0458\u0435\u043d\u0442\u0435, \u043e\u043d\u0434\u0430 \u0443\u043a\u0459\u0443\u0447\u0438\u0442\u0435 \u0438 \u0458\u0430\u0432\u043d\u0435 \u0438 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u0435 \u043c\u0440\u0435\u0436\u0435.\n\u0414\u043e\u0437\u0432\u043e\u0459\u0430\u0432\u0430\u045a\u0435 \u0458\u0430\u0432\u043d\u0438\u0445 \u043c\u0440\u0435\u0436\u0430 \u043e\u0447\u0438\u0433\u043b\u0435\u0434\u043d\u043e \u0443\u043a\u043b\u0430\u045a\u0430 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e\u0441\u0442! window.networkselection.description=\u0422\u043e\u0440\u0435\u043d\u0442 : plugins.basicview.clear=\u041e\u0447\u0438\u0441\u0442\u0438 ConfigView.section.connection.group.peersources=\u0418\u0437\u0432\u043e\u0440\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 ConfigView.section.connection.group.peersources.info=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0435 \u0438\u0437\u0432\u043e\u0440\u0435 \u0437\u0430 \u0432\u0435\u0437\u0435 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 ConfigView.section.connection.peersource.Tracker=\u0421\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 ConfigView.section.connection.peersource.DHT=\u0414\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u043f\u0440\u0430\u045b\u0435\u045a\u0435 ConfigView.section.connection.peersource.PeerExchange=\u041e\u0434 \u0434\u0440\u0443\u0433\u0438\u0445 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 ConfigView.section.connection.peersource.Plugin=\u0421\u0430 \u043d\u0435\u043a\u043e\u0433 \u0434\u043e\u0434\u0430\u0442\u043a\u0430 ConfigView.section.connection.peersource.Incoming=\u0414\u043e\u043b\u0430\u0437\u0435\u045b\u0430 \u0432\u0435\u0437\u0430 PeersView.source=\u0418\u0437\u0432\u043e\u0440 PeersView.source.info=\u0418\u0437\u0432\u043e\u0440 \u043e\u0432\u043e\u0433 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 TableColumn.header.peersources=\u0418\u0437\u0432\u043e\u0440\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 TableColumn.header.peersources.info=\u0418\u0437\u0432\u043e\u0440\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u043a\u043e\u0458\u0438 \u0441\u0443 \u0434\u043e\u0437\u0432\u043e\u0459\u0435\u043d\u0438 \u0437\u0430 \u0432\u0435\u0437\u0435 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 wizard.tracker.dht=\u0414\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e (\u0441\u0430\u043c\u043e \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432\u0438 \u043a\u043b\u0438\u0458\u0435\u043d\u0442\u0438) MyTorrentsView.menu.advancedmenu=\u041d\u0430\u043f\u0440\u0435\u0434\u043d\u043e MyTorrentsView.menu.networks=\u041c\u0440\u0435\u0436\u0435 MyTorrentsView.menu.peersource=\u0418\u0437\u0432\u043e\u0440\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 ConfigView.section.sharing.permitdht=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u043f\u0440\u0430\u045b\u0435\u045a\u0435 \u043a\u0430\u0434\u0430 \u0458\u0435 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0430\u043d ConfigView.section.sharing.protocol=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0437\u0430 \u0434\u0435\u0459\u0435\u043d\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0435 PeersView.Messaging=\u041f\u043e\u0440\u0443\u043a\u0435 PeersView.Messaging.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0458\u0435 \u043a\u043e\u0458\u0438 \u0441\u0435 \u0441\u0438\u0441\u0442\u0435\u043c \u0437\u0430 \u043f\u043e\u0440\u0443\u043a\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438. ConfigView.label.queue.newseedsmovetop=\u041f\u043e\u043c\u0435\u0440\u0438 \u043d\u043e\u0432\u0435 \u0437\u0430\u0432\u0440\u0448\u0435\u043d\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u043d\u0430 \u0432\u0440\u0445 \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 ConfigView.label.seeding.firstPriority.ignore.info=\u0418\u043c\u0430\u0458\u0442\u0435 \u043d\u0430 \u0443\u043c\u0443 \u0434\u0430 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0430 \u043e\u0432\u0438\u0445 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043c\u043e\u0436\u0435 \u0437\u0430\u0443\u0441\u0442\u0430\u0432\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0435\n\u0447\u0438\u043c \u0441\u0435 \u043f\u0440\u0438\u0458\u0438\u0435\u043c \u0437\u0430\u0432\u0440\u0448\u0438. ConfigView.label.seeding.firstPriority.ignore=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 \u041f\u0440\u0432\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0435 \u0438\u0437\u043d\u0430\u0434 \u0437\u0430: ConfigView.label.seeding.firstPriority.ignoreSPRatio=\u0422\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 \u043e\u0434\u043d\u043e\u0441\u043e\u043c \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 \u043f\u0440\u0435\u043c\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 \u043f\u0440\u0435\u043a\u043e ConfigView.label.seeding.firstPriority.ignore0Peer=\u0422\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 0 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 ConfigView.section.tracker.sendjavaversionandos=\u041f\u043e\u0448\u0430\u0459\u0438 \u0438\u0437\u0434\u0430\u045a\u0435 \u0408\u0430\u0432\u0435 \u0438 \u0438\u043c\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0433 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 MagnetPlugin.contextmenu.exporturi=\u0423\u043c\u043d\u043e\u0436\u0438 \u041c\u0430\u0433\u043d\u0435\u0442 \u0423\u0420\u0418 \u043d\u0430 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434 ConfigView.section.plugins.dht=\u0414\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0430 \u0431\u0430\u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 dht.info=\u041e\u0432\u0430\u0458 \u0434\u043e\u0434\u0430\u0442\u0430\u043a \u043f\u043e\u0434\u0440\u0436\u0430\u0432\u0430 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u043f\u0440\u0430\u045b\u0435\u045a\u0435 \u0438\u0437\u043c\u0435\u0452\u0443 \u043e\u0441\u0442\u0430\u043b\u043e\u0433 - \u0438\u0441\u043a\u0459\u0443\u0447\u0438\u0432\u0430\u045a\u0435 \u045b\u0435 \u043f\u043e\u0433\u043e\u0440\u0448\u0430\u0442\u0438 \u043f\u0440\u0438\u0458\u0435\u043c dht.enabled=\u0423\u043a\u0459\u0443\u0447\u0438 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0443 \u0431\u0430\u0437\u0443 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 dht.portdefault=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0438 \u043f\u043e\u0440\u0442 dht.port=\u0423\u0414\u041f \u043f\u043e\u0440\u0442 \u0437\u0430 \u0431\u0430\u0437\u0443 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 dht.execute.command=\u0414\u0438\u0458\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u043a\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 dht.execute.info=\u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u0434\u0430 \u0438\u0437\u0432\u0440\u0448\u0438\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 dht.execute=\u041f\u043e\u043a\u0440\u0435\u043d\u0438 dht.logging=\u0423\u043a\u0459\u0443\u0447\u0438 \u043f\u0440\u0430\u045b\u0435\u045a\u0435 \u0434\u0435\u0458\u0441\u0442\u0430\u0432\u0430 ConfigView.section.plugins.dhttracker=\u0414\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0438 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 dhttracker.tracknormalwhenoffline=\u0421\u0430\u043c\u043e \u043f\u0440\u0430\u0442\u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u043a\u0430\u0434\u0430 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 \u043d\u0438\u0458\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430\u043d ConfigView.section.file.nativedelete._mac=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u041a\u0430\u043d\u0442\u0443 \u043f\u0440\u0438 \u0443\u043a\u043b\u0430\u045a\u0430\u045a\u0443 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 ConfigView.section.file.nativedelete._windows=\u041f\u043e\u043c\u0435\u0440\u0438 \u043e\u0431\u0440\u0438\u0441\u0430\u043d\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0443 \u041a\u0430\u043d\u0442\u0443 ConfigView.section.logging.generatediagnostics=\u041d\u0430\u043f\u0440\u0430\u0432\u0438 ConfigView.section.logging.netinfo=\u041d\u0430\u043f\u0440\u0430\u0432\u0438 \u0434\u0435\u0442\u0430\u0459\u0435 \u043e \u043c\u0440\u0435\u0436\u0438 ConfigView.section.logging.statsinfo=\u041d\u0430\u043f\u0440\u0430\u0432\u0438 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u043e \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u0446\u0438 ConfigView.section.logging.generatediagnostics.info=\u041d\u0430\u043f\u0440\u0430\u0432\u0438 \u0434\u0438\u0458\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u043a\u0435 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u0438 \u0443\u043c\u043d\u043e\u0436\u0438 \u0438\u0445 \u043d\u0430 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434 \u0438 \u0443 \u0437\u0430\u043f\u0438\u0441\u043d\u0438\u043a, \u0430\u043a\u043e \u0458\u0435 \u0442\u043e \u0434\u043e\u0437\u0432\u043e\u0459\u0435\u043d\u043e ConfigView.section.sharing.privatetorrent=\u041f\u0440\u0438\u0432\u0430\u0442\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 - \u043f\u0440\u0438\u0445\u0432\u0430\u0442\u0430 \u0441\u0430\u043c\u043e \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0435 \u0441\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 MainWindow.menu.tools.nattest=&\u041f\u0440\u043e\u0432\u0435\u0440\u0430 NAT-\u0430 / \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d\u0430 Button.apply=\u041f\u0440\u0438\u043c\u0435\u043d\u0438 Button.close=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 window.welcome.title=\u0414\u043e\u0431\u0440\u043e\u0434\u043e\u0448\u043b\u0438 \u0443 \u0410\u0437\u0443\u0440\u0435\u0443\u0441 %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=\u0411\u0435\u043b\u0435\u0448\u043a\u0435 \u043e \u0438\u0437\u0434\u0430\u045a\u0443 dht.reseed.label=\u041e\u0431\u0438\u0447\u043d\u043e, \u043f\u043e\u043d\u043e\u0432\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0435 \u0431\u0430\u0437\u0435 \u043d\u0438\u0458\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e. \u041c\u0435\u0452\u0443\u0442\u0438\u043c, \u0430\u043a\u043e \u0458\u0435 \u0431\u0440\u043e\u0458 \u043a\u043e\u043d\u0442\u0430\u043a\u0430\u0442\u0430 \u043d\u0438\u0437\u0430\u043a, \u043e\u0432\u043e \u0441\u0435 \u043c\u043e\u0436\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0438 \u0437\u0430 \u043f\u043e\u043d\u043e\u0432\u043d\u043e \u0443\u043a\u0459\u0443\u0447\u0435\u045a\u0435 \u0443 \u043c\u0440\u0435\u0436\u0443.\n\u041e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u043f\u0440\u0430\u0437\u043d\u043e \u043a\u0430\u043a\u043e \u0431\u0438 \u0441\u0435 \u0437\u0430 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u043b\u0438 \u043f\u0440\u0438\u043a\u0459\u0443\u0447\u0435\u043d\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438 \u0438\u043b\u0438 \u0435\u043a\u0441\u043f\u043b\u0438\u0446\u0438\u0442\u043d\u043e \u0443\u043d\u0435\u0441\u0438\u0442\u0435 \u0418\u041f \u0431\u0440\u043e\u0458 \u0438 \u043f\u043e\u0440\u0442 \u0437\u0430 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u043f\u043e\u043c\u043e\u045b\u0443 \u043f\u043e\u0437\u043d\u0430\u0442\u043e\u0433 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430. dht.reseed.group=\u041e\u043f\u0435\u0442 \u0437\u0430\u043c\u0435\u0442\u0430\u043a dht.reseed.ip=\u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0435 dht.reseed.port=\u041f\u043e\u0440\u0442 dht.reseed=\u041e\u043f\u0435\u0442 \u0437\u0430\u043c\u0435\u0442\u0430\u043a dht.reseed.info=\u041f\u043e\u043d\u043e\u0432\u043e \u0437\u0430\u043c\u0435\u0442\u043d\u0438 \u0431\u0430\u0437\u0443 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 dht.diagnostics.group=\u0414\u0438\u0458\u0430\u0433\u043d\u043e\u0437\u0430 DHTView.title.full=\u0414\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0430 \u0431\u0430\u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 DHTView.title.fullcvs=\u0421\u0423\u0412 \u0437\u0430 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0443 \u0431\u0430\u0437\u0443 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 DHTView.general.title=\u041e\u043f\u0448\u0442\u0435 DHTView.general.uptime=\u0412\u0440\u0435\u043c\u0435 \u043e\u0434 \u043f\u043e\u0447\u0435\u0442\u043a\u0430: DHTView.general.users=\u041a\u043e\u0440\u0438\u0441\u043d\u0438\u043a\u0430: DHTView.general.nodes=\u0420\u0430\u0447\u0443\u043d\u0430\u0440\u0430: DHTView.general.leaves=\u041b\u0438\u0441\u0442\u043e\u0432\u0430: DHTView.general.contacts=\u041a\u043e\u043d\u0442\u0430\u043a\u0430\u0442\u0430: DHTView.general.replacements=\u0417\u0430\u043c\u0435\u043d\u0430: DHTView.general.live=\u0416\u0438\u0432\u0438\u0445: DHTView.general.unknown=\u041d\u0435\u043f\u043e\u0437\u043d\u0430\u0442\u0438\u0445: DHTView.general.dying=\u041c\u0440\u0442\u0432\u0438\u0445: DHTView.transport.title=\u0414\u0435\u0442\u0430\u0459\u0438 \u043e \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u0443 DHTView.transport.packets=\u041f\u0430\u043a\u0435\u0442\u0430 DHTView.transport.bytes=\u0411\u0430\u0458\u0442\u043e\u0432\u0430 DHTView.transport.received=\u041f\u0440\u0438\u043c\u0459\u0435\u043d\u043e DHTView.transport.sent=\u041f\u043e\u0441\u043b\u0430\u0442\u043e DHTView.transport.in=\u0414\u043e\u0441\u043f\u0435\u043b\u043e: DHTView.transport.out=\u041f\u043e\u0441\u043b\u0430\u0442\u043e: DHTView.operations.title=\u0414\u0435\u0442\u0430\u0459\u0438 \u043e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0458\u0438 DHTView.operations.sent=\u041f\u043e\u0441\u043b\u0430\u0442\u043e DHTView.operations.ok=\u0423 \u0440\u0435\u0434\u0443 DHTView.operations.failed=\u041d\u0435\u0443\u0441\u043f\u0435\u043b\u043e DHTView.operations.received=\u041f\u0440\u0438\u043c\u0459\u0435\u043d\u043e DHTView.operations.ping=\u041f\u0438\u043d\u0433 DHTView.operations.findNode=\u041d\u0430\u0452\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 DHTView.operations.findValue=\u041d\u0430\u0452\u0438 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442 DHTView.operations.store=\u0417\u0430\u043f\u0430\u043c\u0442\u0438 DHTView.activity.title=\u0410\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442 DHTView.activity.status=\u0421\u0442\u0430\u0442\u0443\u0441 DHTView.activity.status.true=\u0417\u0430\u043a\u0430\u0437\u0430\u043d\u043e DHTView.activity.status.false=\u0420\u0430\u0434\u0438 DHTView.activity.type=\u0412\u0440\u0441\u0442\u0430 DHTView.activity.type.1=\u0418\u043d\u0442\u0435\u0440\u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043a\u0430 DHTView.activity.type.2=\u0415\u043a\u0441\u0442\u0435\u0440\u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043a\u0430 DHTView.activity.type.3=\u0418\u043d\u0442\u0435\u0440\u043d\u0430 \u043d\u0430\u0431\u0430\u0432\u043a\u0430 DHTView.activity.type.4=\u0415\u043a\u0441\u0442\u0435\u0440\u043d\u0430 \u043d\u0430\u0431\u0430\u0432\u043a\u0430 DHTView.activity.target=\u041e\u0434\u0440\u0435\u0434\u0438\u0448\u0442\u0435 DHTView.activity.details=\u0414\u0435\u0442\u0430\u0459\u0438 DHTView.db.title=\u0411\u0430\u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 DHTView.db.keys=\u041a\u0459\u0443\u0447\u0435\u0432\u0438 DHTView.db.values=\u0412\u0440\u0435\u0434\u043d\u043e\u0441\u0442\u0438 DHTView.db.local=\u041b\u043e\u043a\u0430\u043b\u043d\u043e DHTView.db.direct=\u0414\u0438\u0440\u0435\u043a\u0442\u043d\u043e DHTView.db.indirect=\u0418\u043d\u0434\u0438\u0440\u0435\u043a\u0442\u043d\u043e DHTView.db.divfreq=\u0424\u0440\u0435\u043a\u0432. \u043f\u043e\u0434\u0435\u043b\u0430 DHTView.db.divsize=\u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u043f\u043e\u0434\u0435\u043b\u0435 MainWindow.dht.status.tooltip=\u041a\u0430\u0434\u0430 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0430 \u0431\u0430\u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u0440\u0430\u0434\u0438, \u043f\u043e\u043a\u0430\u0437\u0443\u0458\u0435 \u043f\u0440\u043e\u0446\u0435\u045a\u0435\u043d\u0438 \u0431\u0440\u043e\u0458 \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0445 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u043a\u0430 MainWindow.dht.status.disabled=\u0414\u0425\u0422 \u0438\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u0430 MainWindow.dht.status.failed=\u0414\u0425\u0422 \u043d\u0438\u0458\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u043d\u0430 MainWindow.dht.status.initializing=\u041f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u0414\u0425\u0422 MainWindow.dht.status.users=\u043a\u043e\u0440\u0438\u0441\u043d\u0438\u043a\u0430: %1 MainWindow.dht.status.unreachable=\u0414\u0425\u0422 \u0458\u0435 \u043f\u043e\u0434 \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d\u043e\u043c MainWindow.dht.status.unreachabletooltip=\u0418\u0437\u0433\u043b\u0435\u0434\u0430 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441\u0430 \u043f\u0440\u0435\u0441\u043b\u0438\u043a\u0430\u0432\u0430\u045a\u0435\u043c \u0423\u0414\u041f \u043f\u043e\u0440\u0442\u0430 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0435 \u0431\u0430\u0437\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 (\u041d\u0410\u0422/\u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d) MyTorrentsView.menu.setUpSpeed=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u0431\u0440\u0437\u0438\u043d\u0443 \u0441\u043b\u0430\u045a\u0430 MyTorrentsView.menu.setDownSpeed=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u0431\u0440\u0437\u0438\u043d\u0443 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 ConfigView.section.tracker.client.showwarnings=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u0443\u043f\u043e\u0437\u043e\u0440\u0435\u045a\u0430 \u043a\u043e\u0458\u0435 \u043f\u043e\u043a\u0430\u0437\u0443\u0458\u0443 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0438 dht.advanced=\u0423\u043a\u0459\u0443\u0447\u0438 \u043d\u0430\u043f\u0440\u0435\u0434\u043d\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 dht.advanced.group=\u041d\u0430\u043f\u0440\u0435\u0434\u043d\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 dht.advanced.label=\u041c\u0435\u045a\u0430\u0458\u0442\u0435 \u043e\u0432\u0435 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442\u0438 \u0441\u0430\u043c\u043e \u0430\u043a\u043e \u0434\u043e\u0431\u0440\u043e \u0437\u043d\u0430\u0442\u0435 \u0448\u0442\u0430 \u0440\u0430\u0434\u0438\u0442\u0435 dht.override.ip=\u041f\u0440\u0435\u0438\u043d\u0430\u0447\u0438 \u0441\u043f\u043e\u0459\u0430\u0448\u045a\u0443 \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0443 ConfigView.section.logging.loggerenable=\u0423\u043a\u0459\u0443\u0447\u0438 \u0431\u0435\u043b\u0435\u0436\u0435\u045a\u0435 ConfigView.section.ipfilter.blockbanning=\u0417\u0430\u0431\u0440\u0430\u043d\u0438 \u0431\u043b\u043e\u043a \u043e\u0434 256 \u0430\u0434\u0440\u0435\u0441\u0430 \u043a\u0430\u0434\u0430 \u0458\u0435 \u0431\u0430\u0440 \u043e\u0432\u043e\u043b\u0438\u043a\u043e \u0443 \u0431\u043b\u043e\u043a\u0443 \u0437\u0430\u0431\u0440\u0430\u045a\u0435\u043d\u043e MyTrackerView.passive=\u041f\u0430\u0441\u0438\u0432\u043d\u043e TableColumn.header.swarm_average_speed=\u0421\u0440. \u0431\u0440\u0437\u0438\u043d\u0430 \u0440\u043e\u0458\u0430 TableColumn.header.swarm_average_speed.info=\u0421\u0440\u0435\u0434\u045a\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u0443 \u0440\u043e\u0458\u0443 TableColumn.header.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 TableColumn.header.comment.info=\u041a\u043e\u0440\u0438\u0441\u043d\u0438\u043a\u043e\u0432 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c TableColumn.header.commenticon=\u0421\u043b\u0438\u0447\u0438\u0446\u0430 \u0437\u0430 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 TableColumn.header.commenticon.info=\u041f\u0440\u0438\u043a\u0430\u0437\u0443\u0458\u0435 \u0441\u043b\u0438\u0447\u0438\u0446\u0443 \u0430\u043a\u043e \u043f\u0440\u0438\u0458\u0435\u043c \u0438\u043c\u0430 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u0438 \u0434\u0435\u0444\u0438\u043d\u0438\u0441\u0430\u043d \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 MyTrackerView.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0430 MainWindow.menu.file.open.torrentfortracking=\u0422\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 (\u0441\u0430\u043c\u043e \u0437\u0430 \u043f\u0440\u0430\u045b\u0435\u045a\u0435) VivaldiView.title.full=\u0412\u0438\u0432\u0430\u043b\u0434\u0438 MyTrackerView.date_added=\u0414\u043e\u0434\u0430\u0442\u043e ConfigView.section.tracker.portbackup=\u0420\u0435\u0437\u0435\u0440\u0432\u043d\u0438 \u043f\u043e\u0440\u0442\u043e\u0432\u0438 (\u201e;\u201c \u0437\u0430 \u0440\u0430\u0437\u0434\u0432\u0430\u0458\u0430\u045a\u0435) ConfigView.label.playfilespeech=\u041e\u0431\u0430\u0432\u0435\u0441\u0442\u0438 \u0433\u043b\u0430\u0441\u043e\u043c \u043e \u043a\u0440\u0430\u0458\u0443 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 ConfigView.label.playfilespeech.info=\u0413\u043e\u0432\u043e\u0440\u043d\u0435 \u0443\u0441\u043b\u0443\u0433\u0435 \u0442\u0440\u0435\u043d\u0443\u0442\u043d\u043e \u043d\u0430\u0458\u0431\u043e\u0459\u0435 \u0440\u0430\u0434\u0435 \u043d\u0430 \u0435\u043d\u0433\u043b\u0435\u0441\u043a\u043e\u043c \u0458\u0435\u0437\u0438\u043a\u0443 ConfigView.label.playfilefinished=\u041f\u0443\u0441\u0442\u0438 \u0437\u0432\u0443\u043a \u043a\u0430\u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u043d\u043e\u0441 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0437\u0430\u0432\u0440\u0448\u0438 ConfigView.label.backupconfigfiles=\u041f\u0440\u0438 \u0441\u0432\u0430\u043a\u043e\u043c \u0434\u0435\u0458\u0441\u0442\u0432\u0443 \u043d\u0430\u043f\u0440\u0430\u0432\u0438 \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u0438 \u0443\u043c\u043d\u043e\u0436\u0430\u043a \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0441\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0438\u043c\u0430 ConfigView.section.tracker.client.scrapesingleonly=\u0417\u0430\u0431\u0440\u0430\u043d\u0438 \u0443\u0434\u0440\u0443\u0436\u0438\u0432\u0430\u045a\u0435 \u0447\u0438\u0441\u0442\u0430\u0447\u0430 \u043f\u043e \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0443 (\u043c\u043e\u0436\u0435 \u0434\u0430 \u043f\u043e\u043c\u043e\u0433\u043d\u0435 \u043e\u043a\u043e \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446\u0430 \u043a\u043e\u0458\u0438 \u0458\u0430\u0432\u0459\u0430\u0458\u0443 \u0434\u0430 \u0458\u0435 \u0423\u0420\u041b \u043f\u0440\u0435\u0434\u0443\u0433\u0430\u0447\u0430\u043a (\u0433\u0440\u0435\u0448\u043a\u0430 414)) dht.ipfilter.log=\u0411\u0435\u043b\u0435\u0436\u0438 \u043f\u0440\u0435\u043a\u0440\u0448\u0430\u0458\u0435 \u0418\u041f \u0444\u0438\u043b\u0442\u0440\u0438\u0440\u0430\u045a\u0430 ConfigView.label.seeding.addForSeedingDLCopyCount=\u0420\u0430\u0437\u043c\u0438\u0441\u043b\u0438\u0442\u0435 \u043e \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0438 \u201e\u0434\u043e\u0434\u0430\u0458 \u0437\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435\u201c \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c \u043e\u0432\u043e\u043b\u0438\u043a\u043e \u0443\u043c\u043d\u043e\u0436\u0430\u043a\u0430 ActivityView.legend.limit=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0435 \u043f\u0440\u043e\u0442\u043e\u043a\u0430 ActivityView.legend.achieved=\u041e\u0441\u0442\u0432\u0430\u0440\u0435\u043d \u043f\u0440\u043e\u0442\u043e\u043a ActivityView.legend.overhead=\u041f\u0440\u0435\u043a\u043e\u0440\u0430\u0447\u0435\u045a\u0435 ActivityView.legend.peeraverage=\u0421\u0440\u0435\u0434\u045a\u0430 ActivityView.legend.swarmaverage=\u041f\u0440\u043e\u0441\u0435\u043a \u0440\u043e\u0458\u0430 ActivityView.legend.trimmed=\u041e\u043f\u0441\u0435\u0447\u0435\u043d\u0430 (\u0442\u0430\u0447\u043a\u0435) MyTorrentsView.menu.movemenu=\u041f\u043e\u043c\u0435\u0440\u0438 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 MyTorrentsView.menu.movedata=\u041f\u043e\u043c\u0435\u0440\u0438 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0441\u0430 \u043f\u043e\u0434\u0430\u0446\u0438\u043c\u0430... MyTorrentsView.menu.movetorrent=\u041f\u043e\u043c\u0435\u0440\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443... MyTorrentsView.menu.movedata.dialog=\u0418\u0437\u0431\u043e\u0440 \u043d\u043e\u0432\u043e\u0433 \u043c\u0435\u0441\u0442\u0430 DHTView.operations.data=\u041f\u043e\u0434\u0430\u0446\u0438 DHTView.general.reachable=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0438: DHTView.general.rendezvous=\u0421\u0443\u0441\u0440\u0435\u0442: ConfigView.label.queue.maxactivetorrentswhenseeding=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430] IrcView.title.short=\u0418\u0420\u0426 Views.plugins.IRC.title=\u0418\u0420\u0426 - \u0442\u0435\u0445\u043d\u0438\u0447\u043a\u0430 \u043f\u043e\u0434\u0440\u0448\u043a\u0430 \u043d\u0430 \u043c\u0440\u0435\u0436\u0438 Formats.units.alot=\u041c\u043d\u043e\u0433\u043e !!! ConfigView.section.ipfilter.persistblocking=\u0427\u0443\u0432\u0430\u0458 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u043e \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u043d\u0438\u043c \u0418\u041f \u0431\u0440\u043e\u0458\u0435\u0432\u0438\u043c\u0430 FilesView.menu.rename=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0458 \u0438\u043b\u0438 \u043f\u0440\u043e\u043c\u0435\u043d\u0438 \u0446\u0438\u0459 FilesView.menu.rename_only=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0458 FilesView.menu.retarget=\u041f\u0440\u0435\u0443\u0441\u043c\u0435\u0440\u0438 FilesView.rename.choose.path=\u0418\u0437\u0431\u043e\u0440 \u043d\u043e\u0432\u0435 \u0438\u043b\u0438 \u043f\u043e\u0441\u0442\u043e\u0458\u0435\u045b\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 FilesView.rename.choose.path.dir=\u0418\u0437\u0431\u043e\u0440 \u043d\u043e\u0432\u043e\u0433 \u0438\u043b\u0438 \u043f\u043e\u0441\u0442\u043e\u0458\u0435\u045b\u0435\u0433 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0430 FilesView.rename.confirm.delete.title=\u041f\u043e\u0442\u0432\u0440\u0434\u0430 \u0431\u0440\u0438\u0441\u0430\u045a\u0430 FilesView.rename.confirm.delete.text=\u041f\u041e\u0442\u0432\u0440\u0434\u0438 \u0431\u0440\u0438\u0441\u0430\u045a\u0435 \u0438\u0437\u0432\u043e\u0440\u043d\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u201e%1\u201c FilesView.rename.filename.title=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0458 FilesView.rename.filename.text=\u0418\u0437\u0431\u043e\u0440 \u043d\u043e\u0432\u043e\u0433 \u0438\u043c\u0435\u043d\u0430 \u0437\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 ConfigView.section.mode=\u041d\u0430\u0447\u0438\u043d \u0440\u0430\u0434\u0430 ConfigView.section.mode.title=\u041a\u043e\u0440\u0438\u0441\u043d\u0438\u043a\u043e\u0432\u043e \u0437\u043d\u0430\u045a\u0435 ConfigView.section.mode.beginner=\u041f\u043e\u0447\u0435\u0442\u043d\u0438\u043a ConfigView.section.mode.beginner.wiki.definitions=\u0420\u0435\u0447\u043d\u0438\u043a \u0411\u0438\u0442 \u0422\u043e\u0440\u0435\u043d\u0442\u0430 ConfigView.section.mode.intermediate=\u041f\u0440\u043e\u0441\u0435\u0447\u0430\u043d ConfigView.section.mode.intermediate.wiki.host=\u0423\u0433\u043e\u0448\u045b\u0430\u0432\u0430\u045a\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 ConfigView.section.mode.intermediate.wiki.publish=\u041e\u0431\u0458\u0430\u0432\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 ConfigView.section.mode.advanced=\u041d\u0430\u043f\u0440\u0435\u0434\u043d\u043e ConfigView.section.mode.advanced.wiki.main=\u0413\u043b\u0430\u0432\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0430 \u043d\u0430 \u0432\u0438\u043a\u0438\u0458\u0443 ConfigView.section.mode.beginner.text=\u0421\u0432\u0435 \u0448\u0442\u043e \u0412\u0430\u043c \u0442\u0440\u0435\u0431\u0430 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0430.\n\u041a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u043e\u0432\u0430\u0458 \u043d\u0430\u0447\u0438\u043d \u0440\u0430\u0434a \u0430\u043a\u043e \u0441\u0430\u043c\u043e \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u0443\u043f\u0440\u0430\u0432\u0459\u0430\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u043c\u0430. ConfigView.section.mode.intermediate.text=\u041f\u0440\u0438\u0441\u0442\u0443\u043f \u0444\u0443\u043d\u043a\u0446\u0438\u0458\u0430\u043c\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430.\n\u041a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u043e\u0432\u0430\u0458 \u043d\u0430\u0447\u0438\u043d \u0440\u0430\u0434\u0430 \u0430\u043a\u043e \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442\u0435 \u0441\u043e\u043f\u0441\u0442\u0432\u0435\u043d\u043e\u0433 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 \u0438 \u0445\u043e\u0441\u0442\u0443\u0458\u0435\u0442\u0435 \u0438\u043b\u0438 \u043e\u0431\u0458\u0430\u0432\u0459\u0443\u0458\u0435\u0442\u0435 \u0441\u0432\u043e\u0458\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435. ConfigView.section.mode.advanced.text=\u041f\u0440\u0438\u0441\u0442\u0443\u043f \u043c\u0440\u0435\u0436\u043d\u0438\u043c \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0438\u043c\u0430\n\u041a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u043e\u0432\u0430\u0458 \u043d\u0430\u0447\u0438\u043d \u0440\u0430\u0434\u0430 \u0430\u043a\u043e \u0437\u043d\u0430\u0442\u0435 \u043a\u043e\u0458\u0435 \u0441\u0443 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u041c\u0422\u0423 \u0438\u043b\u0438 \u043c\u0440\u0435\u0436\u043d\u043e \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u045a\u0435. Files.column.storagetype=\u0412\u0440\u0441\u0442\u0430 \u0441\u043a\u043b\u0430\u0434\u0438\u0448\u0442\u0430 Files.column.fileext=\u0412\u0440\u0441\u0442\u0430 FileItem.storage.linear=\u041b\u0438\u043d\u0435\u0430\u0440\u0430\u043d FileItem.storage.compact=\u041a\u043e\u043c\u043f\u0430\u043a\u0442\u0430\u043d MessageBoxWindow.rememberdecision=\u0417\u0430\u043f\u0430\u043c\u0442\u0438 \u043c\u043e\u0458\u0443 \u043e\u0434\u043b\u0443\u043a\u0443 ConfigView.section.interface.cleardecisions=\u0423\u043a\u043b\u043e\u043d\u0438 \u0437\u0430\u043f\u0430\u043c\u045b\u0435\u043d\u0435 \u043e\u0434\u043b\u0443\u043a\u0435 \u0443 \u043f\u0440\u043e\u0437\u043e\u0440\u0447\u0435\u0442\u0443 ConfigView.section.interface.cleardecisionsbutton=\u041e\u0447\u0438\u0441\u0442\u0438 ConfigView.section.interface.cleartrackers=\u0423\u043a\u043b\u043e\u043d\u0438 \u0437\u0430\u043f\u0430\u043c\u045b\u0435\u043d\u0435 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0435 ConfigView.section.interface.cleartrackersbutton=\u041e\u0447\u0438\u0441\u0442\u0438 ConfigView.section.interface.clearsavepaths=\u0423\u043a\u043b\u043e\u043d\u0438 \u0437\u0430\u043f\u0430\u043c\u045b\u0435\u043d\u0435 \u0441\u0442\u0430\u0437\u0435 \u0437\u0430 \u0447\u0443\u0432\u0430\u045a\u0435 ConfigView.section.interface.clearsavepathsbutton=\u041e\u0447\u0438\u0441\u0442\u0438 configureWizard.welcome.usermodes=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 \u0432\u0435\u0448\u0442\u0438\u043d\u0435 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u043a\u0430 \u043e\u0434\u0440\u0435\u0452\u0443\u0458\u0435 \u043d\u0438\u0432\u043e \u0434\u0435\u0442\u0430\u0459\u0430 \u043a\u043e\u0458\u0438 \u0441\u0435 \u043f\u0440\u0438\u043a\u0430\u0437\u0443\u0458\u0435 \u0443 \u201e\u0410\u043b\u0430\u0442\u0438->\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430\u201c. \u0423 \u0412\u0430\u0448\u0435\u043c \u0458\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443 \u0434\u0430 \u043e\u0432\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435. FilesView.skip.confirm.delete.text=\u0414\u0430 \u043b\u0438 \u0442\u0440\u0435\u0431\u0430 \u0441\u043a\u0440\u0430\u0442\u0438\u0442\u0438 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u201e%1\u201c \u0437\u0430 \u0443\u0448\u0442\u0435\u0434\u0443 \u043f\u0440\u043e\u0441\u0442\u043e\u0440\u0430? FilesView.rename.failed.title=\u041f\u0440\u043e\u043c\u0435\u043d\u0430 \u0438\u043c\u0435\u043d\u0430 \u0438\u043b\u0438 \u0446\u0438\u0459\u0430 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u0430 FilesView.rename.failed.text=\u0414\u0435\u0458\u0441\u0442\u0432\u043e \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e, \u043c\u043e\u0433\u0443\u045b\u0435 \u0437\u0431\u043e\u0433 \u043d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u043e\u0433 \u0438\u0437\u0431\u043e\u0440\u0430 \u0446\u0438\u0459\u0430 diagnostics.log_found=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u043d\u0438\u0458\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u043d\u043e \u0438\u0441\u043a\u0459\u0443\u0447\u0435\u043d \u043f\u0440\u043e\u0448\u043b\u0438 \u043f\u0443\u0442. \u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u0438 \u0443 \u045a\u0435\u043c\u0443 \u043f\u043e\u0440\u0443\u043a\u0435 \u043e \u0433\u0440\u0435\u0448\u043a\u0430\u043c\u0430 \u0438 \u0440\u0430\u0437\u043c\u0438\u0441\u043b\u0438\u0442\u0435 \u043e \u0442\u043e\u043c\u0435 \u0434\u0430 \u0438\u0445 \u043f\u0440\u0438\u0458\u0430\u0432\u0438\u0442\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0438\u0432\u0438\u043c \u0442\u0438\u043c\u0443 \u0443\u043a\u043e\u043b\u0438\u043a\u043e \u0441\u0443 \u043d\u0430\u0441\u0442\u0430\u043b\u0435 \u0443\u0441\u043b\u0435\u0434 \u0433\u0440\u0435\u0448\u043a\u0435 \u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443. \u0422\u0430\u043a\u043e\u0452\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u0432\u0438\u043a\u0438 (\u0432\u0438\u0434\u0438\u0442\u0435 \u043c\u0435\u043d\u0438 \u0437\u0430 \u043f\u043e\u043c\u043e\u045b) \u0438 \u0441\u0442\u0430\u0432\u043a\u0443 \u201e\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u043d\u0435\u0441\u0442\u0430\u0458\u0435\u201c ManagerItem.paused=\u041f\u0430\u0443\u0437\u0438\u0440\u0430\u043d\u043e Utils.link.visit=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 ConfigView.section.connection.serverport.wiki=\u0414\u043e\u0431\u0440\u0438 \u0438\u0437\u0431\u043e\u0440\u0438 \u0437\u0430 \u043f\u043e\u0440\u0442\u043e\u0432\u0435 ConfigView.section.transfer.speeds.wiki=\u0414\u043e\u0431\u0440\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0431\u0440\u0437\u0438\u043d\u0435 installPluginsWizard.installMode.info.title=\u041f\u043e\u0434\u0430\u0446\u0438 installPluginsWizard.installMode.info.text=\u0414\u043e\u0434\u0430\u0446\u0438 \u043d\u0438\u0441\u0443 \u043d\u0435\u043e\u043f\u0445\u043e\u0434\u043d\u0438 \u0434\u0430 \u0431\u0438 \u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u0438\u0441\u043f\u0440\u0430\u0432\u043d\u043e \u0440\u0430\u0434\u0438\u043e. \u041e\u043d\u0438 \u0434\u0430\u0458\u0443\n\u043f\u043e\u0441\u0435\u0431\u043d\u0435 \u043c\u043e\u0433\u0443\u045b\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u0437\u0430\u0431\u0430\u0432\u0443, \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0458\u0443 \u0440\u0430\u0434\u0430 \u0438\u043b\u0438 \u0434\u0430\u0459\u0438\u043d\u0441\u043a\u043e \u0443\u043f\u0440\u0430\u0432\u0459\u0430\u045a\u0435.\n\u0417\u0430\u0442\u043e \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u0435 \u043f\u0430\u0436\u0459\u0438\u0432\u043e \u043e\u043f\u0438\u0441 \u0441\u0432\u0430\u043a\u043e\u0433 \u0434\u043e\u0434\u0430\u0442\u043a\u0430 \u043f\u0440\u0435 \u043d\u0435\u0433\u043e \u0448\u0442\u043e \n\u043e\u0434\u043b\u0443\u0447\u0438\u0442\u0435 \u0434\u0430 \u0433\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435.\n\u0412\u0435\u045b\u0438\u043d\u0430 \u0434\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u0441\u0443 \u0431\u0435\u0437\u0431\u0435\u0434\u043d\u0438 \u0437\u0430 \u043f\u0440\u043e\u0431\u0430\u045a\u0435, \u0430\u043b\u0438 \u043d\u0435\u043c\u043e\u0458\u0442\u0435 \u043f\u0440\u0435\u043e\u043f\u0442\u0435\u0440\u0435\u045b\u0438\u0432\u0430\u0442\u0438\n\u0438\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u0458\u0443 \u0434\u043e\u0434\u0430\u0446\u0438\u043c\u0430 \u043a\u043e\u0458\u0435 \u043d\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435. Views.plugins.Distributed.DB.title=\u0414\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0430 \u0431\u0430\u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 Views.plugins.Distributed.Tracker.title=\u0414\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0438 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 Views.plugins.Plugin.Update.title=\u0414\u043e\u0433\u0440\u0430\u0434\u045a\u0430 \u0434\u043e\u0434\u0430\u0442\u0430\u043a\u0430 Views.plugins.UPnP.title.tooltip=\u0423\u043d\u0438\u0432\u0435\u0440\u0437\u0430\u043b\u043d\u0438 PnP openUrl.url.info=\u041f\u043e\u0434\u0440\u0436\u0430\u0432\u0430 http, https, magnet \u0438 \u0441\u0438\u0440\u043e\u0432\u0435 \u0445\u0435\u043a\u0441\u0430 \u043d\u0438\u0437\u043e\u0432\u0435 TableColumn.header.swarm_average_completion=\u0423\u0441\u0440\u0435\u0434\u045a\u0435\u043d\u0430 \u043a\u043e\u043c\u043f\u043b\u0435\u0442\u043d\u043e\u0441\u0442 TableColumn.header.swarm_average_completion.info=\u0421\u0440\u0435\u0434\u045a\u0430 \u0433\u043e\u0442\u043e\u0432\u043e\u0441\u0442 \u043a\u043e\u0434 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u0443 \u0440\u043e\u0458\u0443 GeneralView.label.swarm_average_completion=\u0421\u0440\u0435\u0434\u045a\u0430 \u0433\u043e\u0442\u043e\u0432\u043e\u0441\u0442: GeneralView.label.swarm_average_completion.tooltip=\u0421\u0440\u0435\u0434\u045a\u0430 \u0433\u043e\u0442\u043e\u0432\u043e\u0441\u0442 \u043a\u043e\u0434 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u0443 \u0440\u043e\u0458\u0443 MainWindow.nat.status.tooltip.unknown=\u0421\u0442\u0430\u0442\u0443\u0441 NAT\u0430 \u0438 \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d\u0430 \u0458\u0435 \u043d\u0435\u043f\u043e\u0437\u043d\u0430\u0442 (TCP) MainWindow.nat.status.ok=NAT \u0458\u0435 \u0443 \u0440\u0435\u0434\u0443 MainWindow.nat.status.tooltip.ok=\u0420\u0430\u0447\u0443\u043d\u0430\u0440 \u0458\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430\u043d (TCP) MainWindow.nat.status.probok=NAT \u0458\u0435 \u0443 \u0440\u0435\u0434\u0443? MainWindow.nat.status.tooltip.probok=\u0420\u0430\u0447\u0443\u043d\u0430\u0440 \u0458\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430\u043d, \u0430\u043b\u0438 \u043e\u0434\u0430\u0432\u043d\u043e \u043d\u0438\u043a\u043e \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043e TCP \u0432\u0435\u0437\u0443 MainWindow.nat.status.bad=\u041f\u043e\u0434 \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d\u043e\u043c MainWindow.nat.status.tooltip.bad=\u041c\u043e\u0433\u0443\u045b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441\u0430 NAT\u043e\u043c \u0438\u043b\u0438 \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d\u043e\u043c. (TCP). \u041f\u043e\u0442\u0440\u0430\u0436\u0438\u0442\u0435 \u043f\u043e\u043c\u043e\u045b \u043d\u0430 \u0432\u0438\u043a\u0438\u0458\u0443 plugin.installer.recommended.plugin=\u041f\u0440\u0435\u043f\u043e\u0440\u0443\u0447\u0435\u043d\u0438 \u0434\u043e\u0434\u0430\u0442\u0430\u043a - \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u043e\u0433\u043b\u0435\u0434\u0430\u0442\u0435 \u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u0430\u043a\u043e \u0458\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e LoggerView.pause=\u041f\u0430\u0443\u0437\u0438\u0440\u0430\u0458 \u0431\u0435\u043b\u0435\u0436\u0435\u045a\u0435 LoggerView.clear=&\u041e\u0447\u0438\u0441\u0442\u0438 LoggerView.filter=\u0424\u0438\u043b\u0442\u0435\u0440 LoggerView.filter.uncheckAll=\u0423\u043a\u043b\u043e\u043d\u0438 \u043e\u0437\u043d\u0430\u043a\u0443 \u0441\u0430 \u0441\u0432\u0438\u0445 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0430 LoggerView.filter.checkAll=\u041f\u0440\u043e\u0432\u0435\u0440\u0438 \u0441\u0432\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0435 LoggerView.loggingDisabled=\u0411\u0435\u043b\u0435\u0436\u0435\u045a\u0435 \u043d\u0438\u0458\u0435 \u0443\u043a\u0459\u0443\u0447\u0435\u043d\u043e. LoggerView.includeOnly=\u041f\u0440\u0438\u043a\u0430\u0437 \u0441\u0430\u043c\u043e \u043b\u0438\u043d\u0438\u0458\u0430 \u043a\u043e\u0458\u0435 \u0441\u0435 \u0443\u043a\u043b\u0430\u043f\u0430\u0458\u0443 \u0443 \u0440\u0435\u0433\u0443\u043b\u0430\u0440\u043d\u0438 \u0438\u0437\u0440\u0430\u0437: LoggerView.excludeAll=\u041f\u0440\u0438\u043a\u0430\u0437 \u0441\u0430\u043c\u043e \u043b\u0438\u043d\u0438\u0458\u0430 \u043a\u043e\u0458\u0435 \u0441\u0435 \u043d\u0435 \u0443\u043a\u043b\u0430\u043f\u0430\u0458\u0443 \u0443 \u0440\u0435\u0433\u0443\u043b\u0430\u0440\u043d\u0438 \u0438\u0437\u0440\u0430\u0437 ConfigView.section.logging.log0type=\u041f\u043e\u0434\u0430\u0446\u0438 ConfigView.section.logging.log1type=\u0423\u043f\u043e\u0437\u043e\u0440\u0435\u045a\u0435 ConfigView.section.logging.log2type=\u0413\u0440\u0435\u0448\u043a\u0430 ConfigView.section.logging.filter=\u0424\u0438\u043b\u0442\u0440\u0438\u0440\u0430\u045a\u0435 \u043f\u0440\u0438 \u0431\u0435\u043b\u0435\u0436\u0435\u045a\u0443 \u0443 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 ConfigView.section.logging.level=\u0414\u0435\u0442\u0430\u0459\u043d\u043e\u0441\u0442 \u0431\u0435\u043b\u0435\u0436\u0435\u045a\u0430 ConfigView.section.logging.showLogsFor=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u043e\u0432\u043e\u043b\u0438\u043a\u043e \u0434\u043d\u0435\u0432\u043d\u0438\u043a\u0430 (%1) \u0437\u0430 \u043d\u0430\u0440\u0435\u0434\u043d\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0435: ConfigView.pluginlist.column.loadAtStartup=\u0423\u0447\u0438\u0442\u0430\u0458 \u043d\u0430 \u043f\u043e\u0447\u0435\u0442\u043a\u0443 ConfigView.pluginlist.column.type=\u0412\u0440\u0441\u0442\u0430 ConfigView.pluginlist.column.type.perUser=\u041f\u043e \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u043a\u0443 ConfigView.pluginlist.column.type.shared=\u0414\u0435\u0459\u0435\u043d\u043e ConfigView.pluginlist.column.type.builtIn=\u0423\u0433\u0440\u0430\u0452\u0435\u043d\u043e ConfigView.pluginlist.column.name=\u0418\u043c\u0435 ConfigView.pluginlist.column.version=\u0418\u0437\u0434\u0430\u045a\u0435 ConfigView.pluginlist.column.directory=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c ConfigView.pluginlist.column.isOperational=\u0414\u0430 \u043b\u0438 \u0440\u0430\u0434\u0438? PeersView.BlockView.Avail.Have=\u041e\u0431\u0430 \u0438\u043c\u0430\u0458\u0443 PeersView.BlockView.Avail.NoHave=\u0423\u0434\u0430\u0459\u0435\u043d\u0438 \u0438\u043c\u0430; \u0412\u0438 \u043d\u0435 PeersView.BlockView.NoAvail.Have=\u0412\u0438 \u0438\u043c\u0430\u0442\u0435; \u0443\u0434\u0430\u0459\u0435\u043d\u0438 \u0438\u043c\u0430 PeersView.BlockView.NoAvail.NoHave=\u041d\u0438\u043a\u043e \u043d\u0435\u043c\u0430 PeersView.BlockView.Transfer=\u041f\u0440\u0435\u043d\u043e\u0441 PeersView.BlockView.NextRequest=\u041d\u0430\u0440\u0435\u0434\u043d\u0438 \u0437\u0430\u0445\u0442\u0435\u0432 PeersView.BlockView.title=\u041a\u0430\u0440\u0442\u0430 \u0434\u0435\u043b\u043e\u0432\u0430 PeersView.BlockView.AvailCount=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442 MyTorrentsView.dialog.NumberError.title=\u041d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u0430\u043d \u0438\u043b\u0438 \u043d\u0435\u043f\u0440\u0435\u043f\u043e\u0437\u043d\u0430\u0442 \u0431\u0440\u043e\u0458 MyTorrentsView.dialog.NumberError.text=\u0411\u0440\u043e\u0458 \u043a\u043e\u0433 \u0441\u0442\u0435 \u0443\u043d\u0435\u043b\u0438 \u043d\u0438\u0458\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u0430\u043d \u0438\u043b\u0438 \u043d\u0438\u0458\u0435 \u043f\u0440\u0435\u043f\u043e\u0437\u043d\u0430\u0442. MyTorrentsView.menu.manual=&\u0420\u0443\u0447\u043d\u043e... MyTorrentsView.menu.manual.per_torrent=\u0420\u0443\u0447\u043d\u043e (\u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443) MyTorrentsView.menu.manual.shared_torrents=\u0420\u0443\u0447\u043d\u043e (\u0437\u0430 \u0441\u0432\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435) MyTorrentsView.dialog.setSpeed.title=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u0431\u0440\u0437\u0438\u043d\u0443 %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=\u0423\u043d\u0435\u0441\u0438 \u0431\u0440\u043e\u0458 %1 \u0434\u0430 \u0441\u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u0438 %2 \u0443: MyTorrentsView.dialog.setNumber.upload=\u0441\u043b\u0430\u045a\u0435 MyTorrentsView.dialog.setNumber.download=\u043f\u0440\u0438\u0458\u0435\u043c MyTorrentsView.dialog.setNumber.inKbps=\u043f\u0440\u0438\u0458\u0435\u043c: %1 OpenTorrentWindow.torrentLocation=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c: OpenTorrentWindow.addFiles.URL=\u0414\u043e\u0434\u0430\u0458 &\u0423\u0420\u041b OpenTorrentWindow.addFiles.Folder=\u0414\u043e\u0434\u0430\u0458 &\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c OpenTorrentWindow.addFiles.Clipboard=\u0414\u043e\u0434\u0430\u0458 \u0441\u0430 &\u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434\u0430 OpenTorrentWindow.changeDestination=\u041f\u0440\u043e\u043c\u0435\u043d\u0430 \u043e\u0434\u0440\u0435\u0434\u0438\u0448\u0442\u0430 OpenTorrentWindow.fileList=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u043c\u0430: OpenTorrentWindow.torrentTable.name=\u0418\u043c\u0435 OpenTorrentWindow.torrentTable.saveLocation=\u0421\u0430\u0447\u0443\u0432\u0430\u0458 \u043c\u0435\u0441\u0442\u043e OpenTorrentWindow.fileTable.fileName=\u0418\u043c\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 OpenTorrentWindow.fileTable.size=\u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 OpenTorrentWindow.fileTable.destinationName=\u0418\u043c\u0435 \u043e\u0434\u0440\u0435\u0434\u0438\u0448\u0442\u0430 OpenTorrentWindow.startMode.seeding=\u0417\u0430\u043c\u0435\u0442\u0430\u045a\u0435 OpenTorrentWindow.fileList.changeDestination=\u041f\u0440\u043e\u043c\u0435\u043d\u0430 \u043e\u0434\u0440\u0435\u0434\u0438\u0448\u0442\u0430 OpenTorrentWindow.mb.badSize.title=\u041d\u0435\u043a\u043e\u043c\u043f\u0430\u0442\u0438\u0431\u0438\u043b\u043d\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 OpenTorrentWindow.mb.badSize.text=\u201e%1\u201c \u043d\u0438\u0458\u0435 \u201e%2\u201c \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0438\u0442\u0438 \u043a\u043e\u0440\u0438\u0448\u045b\u0435\u043d\u043e \u0437\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 OpenTorrentWindow.mb.alreadyExists.text=\u201e%3\u201f \u0458\u0435 \u0432\u0435\u045b \u0434\u043e\u0434\u0430\u0442 \u043a\u0430\u043e \u201e%2\u201f OpenTorrentWindow.mb.alreadyExists.default.name=\u041c\u0435\u0434\u0438\u0458\u0443\u043c OpenTorrentWindow.mb.alreadyExists.title=\u0412\u0435\u045b \u043f\u043e\u0441\u0442\u043e\u0458\u0438 OpenTorrentWindow.mb.openError.title=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043e\u0442\u0432\u0430\u0440\u0430\u045a\u0443 OpenTorrentWindow.mb.openError.text=\u201e%1\u201c \u043d\u0438\u0458\u0435 \u043c\u043e\u0433\u0430\u043e \u0431\u0438\u0442\u0438 \u043e\u0442\u0432\u043e\u0440\u0435\u043d: OpenTorrentWindow.torrent.remove=\u0423\u043a\u043b\u043e\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0441\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 OpenTorrentWindow.torrent.options=\u0421\u043b\u0435\u0434\u0435\u045b\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u045b\u0435 \u0431\u0438\u0442\u0438 \u043f\u0440\u0438\u043c\u0435\u045a\u0435\u043d\u0430 \u0441\u0430\u043c\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0435 \u0438\u0437\u043d\u0430\u0434: OpenTorrentWindow.xOfTotal=(%1 \u043e\u0434 %2) iconBar.open.tooltip=\u041e\u0442\u0432\u043e\u0440\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 LocaleUtil.column.text=\u041d\u0435\u043f\u043e\u0437\u043d\u0430\u0442 \u0442\u0435\u043a\u0441\u0442 Tracker.tooltip.MultiSupport=\u041e\u0432\u0430\u0458 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 \u043f\u043e\u0434\u0440\u0436\u0430\u0432\u0430 \u0432\u0438\u0448\u0435\u0441\u0442\u0440\u0443\u043a\u0430 \u0447\u0438\u0448\u045b\u0435\u045a\u0430 \u0445\u0435\u0448\u0435\u0432\u0430 \u043f\u043e \u0437\u0430\u0445\u0442\u0435\u0432\u0443. Tracker.tooltip.NoMultiSupport=\u041e\u0432\u0430\u0458 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 \u043d\u0435 \u043f\u043e\u0434\u0440\u0436\u0430\u0432\u0430 \u0432\u0438\u0448\u0435\u0441\u0442\u0440\u0443\u043a\u0430 \u0447\u0438\u0448\u045b\u0435\u045a\u0430 \u0445\u0435\u0448\u0435\u0432\u0430 \u043f\u043e \u0437\u0430\u0445\u0442\u0435\u0432\u0443.\n\u0411\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0435\u043d\u043e\u0441\u0430 \u043d\u0438\u0458\u0435 \u0443\u0433\u0440\u043e\u0436\u0435\u043d\u0430, \u0430\u043b\u0438 \u0434\u043e\u0434\u0430\u0442\u043d\u043e \u043e\u043f\u0442\u0435\u0440\u0435\u045b\u0443\u0458\u0435 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430. ConfigView.label.lazybitfield=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u043b\u0435\u045a\u043e \u043f\u043e\u0459\u0435 \u0431\u0438\u0442\u043e\u0432\u0430 (\u043f\u043e\u043c\u0430\u0436\u0435 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 \u043d\u0430 \u043c\u0440\u0435\u0436\u0430\u043c\u0430 \u043a\u043e\u0458\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0435 \u043f\u043e\u0459\u0435 \u0431\u0438\u0442\u043e\u0432\u0430 \u0437\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u0430\u045a\u0435) LoggerView.realtime=\u041e\u0441\u0432\u0435\u0436\u0430\u0432\u0430\u045a\u0435 \u0443 \u0440\u0435\u0430\u043b\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0443 ConfigView.section.file.perf.cache.flushpieces=\u0417\u0430\u043f\u0438\u0441\u0443\u0458 \u0437\u0430\u0432\u0440\u0448\u0435\u043d\u0435 \u0434\u0435\u043b\u043e\u0432\u0435 \u043e\u0434\u043c\u0430\u0445 \u043d\u0430 \u0434\u0438\u0441\u043a. \u041e\u0432\u043e \u0440\u0435\u0448\u0430\u0432\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430 \u0434\u0438\u0441\u043a\u0443 \u0430\u043b\u0438 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0438\u043c\u0430 \u0437\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u0438\u0446\u0443 \u043f\u043e\u0432\u0435\u045b\u0430\u045a\u0435 \u0431\u0440\u043e\u0458\u0430 \u0443\u043f\u0438\u0441\u0430. ConfigView.section.file.writemblimit=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u0431\u0440\u043e\u0458 \u0437\u0430\u043f\u0438\u0441\u0430 \u043a\u043e\u0458\u0438 \u0447\u0435\u043a\u0430\u0458\u0443 (\u0443 %1) ConfigView.section.file.writemblimit.explain=\u041a\u0430\u0434\u0430 \u0458\u0435 \u0431\u0440\u0437\u0438\u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u0430 \u043d\u0430 \u0434\u0438\u0441\u043a \u043d\u0438\u0436\u0430 \u043e\u0434 \u0431\u0440\u0437\u0438\u043d\u0435 \u043f\u0440\u0438\u0458\u0435\u043c\u0430, \u043e\u0432\u0430\u0458 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0430\u0440 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0430\u0432\u0430 \u043a\u043e\u043b\u0438\u043a\u043e \u045b\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u0431\u0438\u0442\u0438 \u0441\u0442\u0430\u0432\u0459\u0435\u043d\u043e \u043d\u0430 \u0447\u0435\u043a\u0430\u045a\u0435 \u043f\u0440\u0435 \u043d\u0435\u0433\u043e \u0448\u0442\u043e \u0441\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u0441\u043c\u0430\u045a\u0435. ConfigView.section.file.readmblimit=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u0431\u0440\u043e\u0458 \u0437\u0430\u0445\u0442\u0435\u0432\u0430 \u0437\u0430 \u0447\u0438\u0442\u0430\u045a\u0435 \u043d\u0430 \u0447\u0435\u043a\u0430\u045a\u0443 (\u0443 %1) ConfigView.section.file.readmblimit.explain=\u041e\u0432\u0430\u0458 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0430\u0440 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0430\u0432\u0430 \u043a\u043e\u043b\u0438\u0447\u0438\u043d\u0443 \u043c\u0435\u043c\u043e\u0440\u0438\u0458\u0435 \u043a\u043e\u0458\u0430 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0437\u0430 \u0447\u0443\u0432\u0430\u045a\u0435 \u0447\u0438\u0442\u0430\u045a\u0430 \u043a\u043e\u0458\u0430 \u0447\u0435\u043a\u0430\u0458\u0443 \u043d\u0430 \u043e\u0431\u0440\u0430\u0434\u0443. Button.moveUp=\u041f\u043e\u043c\u0435\u0440\u0438 \u043d\u0430 &\u0433\u043e\u0440\u0435 Button.moveDown=\u041f\u043e\u043c\u0435\u0440\u0438 \u043d\u0430 &\u0434\u043e\u043b\u0435 ConfigView.notAvailableForMode=\u041e\u0432\u0430\u0458 \u043e\u0434\u0435\u0459\u0430\u043a \u0458\u0435 \u043d\u0430\u043c\u0435\u045a\u0435\u043d \u0437\u0430 \u043d\u0430\u0447\u0438\u043d \u0440\u0430\u0434\u0430 %1 \u0438\u043b\u0438 \u0432\u0438\u0448\u0438. \u041d\u0438\u0458\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430\u043d \u0443 \u043d\u0430\u0447\u0438\u043d\u0443 \u0440\u0430\u0434\u0430 %2. health.explain.error=\u041e\u0432\u0430\u0458 \u0442\u043e\u0440\u0435\u043d\u0442 \u0441\u0430\u0434\u0440\u0436\u0438 \u0433\u0440\u0435\u0448\u043a\u0443. \u041f\u043e\u0433\u043b\u0435\u0434\u0430\u0458\u0442\u0435 \u043a\u043e\u043b\u043e\u043d\u0443 \u201e\u0421\u0442\u0430\u0442\u0443\u0441\u201c \u0438\u043b\u0438 \u0431\u0430\u043b\u043e\u043d\u0447\u0438\u045b \u043d\u0430 \u0441\u043b\u0438\u0447\u0438\u0446\u0438 \u043a\u043e\u0458\u0430 \u043f\u0440\u0438\u043a\u0430\u0437\u0443\u0458\u0435 \u0433\u0440\u0435\u0448\u043a\u0443. GeneralView.label.trackerscrapeupdate=\u041e\u0447\u0438\u0441\u0442\u0438 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 PeersView.piece=\u0414\u0435\u043e PeersView.piece.info=\u041f\u043e\u0441\u043b\u0435\u0434\u045a\u0438 \u0431\u0440\u043e\u0458 \u0434\u0435\u043b\u0430 \u043a\u043e\u0433 \u0458\u0435 \u0442\u0440\u0430\u0436\u0438\u043e \u043e\u0432\u0430\u0458 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 PiecesView.priority=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 PiecesView.priority.info=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0437\u0430 \u0437\u0430\u0432\u0440\u0448\u0435\u0442\u0430\u043a \u043e\u0432\u043e\u0433 \u0434\u0435\u043b\u0430; \u043d\u0435 \u043e\u0431\u0440\u0430\u045b\u0430\u0458\u0442\u0435 \u043f\u0440\u0435\u0442\u0435\u0440\u0430\u043d\u043e \u043f\u0430\u0436\u045a\u0443 \u043d\u0430 \u045a\u0435\u0433\u0430 PiecesView.speed=\u0411\u0440\u0437\u0438\u043d\u0430 PiecesView.speed.info=\u0421\u043f\u043e\u0440\u0438\u0458\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438 \u043d\u0435\u043c\u0430\u0458\u0443 \u043f\u0440\u0438\u043b\u0438\u043a\u0443 \u0434\u0430 \u043c\u043d\u043e\u0433\u043e \u043e\u043f\u0435\u0440\u0438\u0448\u0443 \u0441\u0430 \u0431\u0440\u0436\u0438\u043c \u0434\u0435\u043b\u043e\u0432\u0438\u043c\u0430 TableColumn.header.AvgAvail.info=\u0417\u0431\u0438\u0440 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0434\u0435\u043b\u043e\u0432\u0430 \u043f\u043e\u0434\u0435\u0459\u0435\u043d \u0431\u0440\u043e\u0458\u0435\u043c \u0434\u0435\u043b\u043e\u0432\u0430, \u043f\u043e\u0434\u0435\u0459\u0435\u043d \u0431\u0440\u043e\u0458\u0435\u043c \u0432\u0435\u0437\u0430 TableColumn.header.AvgAvail=\u0421\u0440. \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442/\u0434\u0435\u043b\u0443 ConfigView.label.strictfilelocking=\u041f\u0440\u0438\u043d\u0443\u0434\u0438 \u043d\u0430 \u0435\u043a\u0441\u043a\u043b\u0443\u0437\u0438\u0432\u043d\u043e \u0437\u0430\u043a\u0459\u0443\u0447\u0430\u0432\u0430\u045a\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u0438 \u0443\u043f\u0438\u0441\u0443 \u0437\u0430 \u0441\u0432\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 MyTorrentsView.menu.rescanfile=\u041f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u043d\u0435\u0437\u0430\u0432\u0440\u0448\u0435\u043d\u0435 \u0434\u0435\u043b\u043e\u0432\u0435 MyTorrentsView.menu.clear_resume_data=\u041e\u0447\u0438\u0441\u0442\u0438 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u043e \u043f\u043e\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0443 Plugin.extseed.name=\u0421\u043f\u043e\u0459\u0430\u0448\u045a\u0438 \u0437\u0430\u043c\u0435\u0446\u0438 Plugin.localtracker.name=\u041f\u0440\u0435\u0442\u0440\u0430\u0433\u0430 \u043b\u043e\u043a\u0430\u043b\u043d\u0438\u0445 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 Plugin.localtracker.info=\u041f\u0440\u043e\u043d\u0430\u043b\u0430\u0437\u0430\u0447 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u0443 \u043b\u043e\u043a\u0430\u043b\u043d\u043e\u0458 \u043c\u0440\u0435\u0436\u0438 \u043f\u043e\u043a\u0443\u0448\u0430\u0432\u0430 \u0434\u0430 \u043d\u0430\u0452\u0435 \u0432\u0438\u0448\u0435 \u043a\u043e\u043f\u0438\u0458\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 \u043a\u043e\u0458\u0438 \u0440\u0430\u0434\u0435 \u0438\u0437\u0430 \u0438\u0441\u0442\u043e\u0433 \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d\u0430 \u043d\u0430 \u0437\u0430\u0458\u0435\u0434\u043d\u0438\u0447\u043a\u043e\u0458 \u043c\u0440\u0435\u0436\u0438\n\u043a\u0430\u043a\u043e \u0431\u0438 \u043f\u043e\u0432\u0435\u045b\u0430\u043e \u0435\u0444\u0438\u043a\u0430\u0441\u043d\u043e\u0441\u0442 \u043f\u0440\u0435\u043d\u043e\u0441\u0430 \u0443\u0441\u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0430\u045a\u0435\u043c \u0441\u0430\u0440\u0430\u0434\u045a\u0435 \u0438\u0437\u043c\u0435\u0452\u0443 \u045a\u0438\u0445 Plugin.localtracker.enable=\u0423\u043a\u0459\u0443\u0447\u0438 \u043f\u0440\u043e\u043d\u0430\u043b\u0430\u0437\u0430\u0447 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u0443 \u043b\u043e\u043a\u0430\u043b\u043d\u043e\u0458 \u043c\u0440\u0435\u0436\u0438 azinstancehandler.alert.portclash=\u0421\u0443\u043a\u043e\u0431 \u043f\u043e\u0440\u0442\u043e\u0432\u0430 \u0458\u0435 \u043e\u0442\u043a\u0440\u0438\u0432\u0435\u043d \u0443 \u043b\u043e\u043a\u0430\u043b\u043d\u043e\u0458 \u043c\u0440\u0435\u0436\u0438: %1 \u0432\u0435\u045b \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u043d\u0435\u043a\u0438 \u0434\u0440\u0443\u0433\u0438 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u043a \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430. \u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u043d\u043e\u0432\u0435 (\u0441\u043b\u0443\u0447\u0430\u0458\u043d\u0435) \u043f\u043e\u0440\u0442\u043e\u0432\u0435 \u0437\u0430 \u043f\u0440\u0438\u0445\u0432\u0430\u0442\u0430\u045a\u0435 \u0422\u0426\u041f \u0438 \u0423\u0414\u041f \u0432\u0435\u0437\u0430 [\u0438\u0437\u043c\u0435\u0452\u0443 %2 \u0438 %3]. ConfigView.section.transfer.lan=\u041b\u0410\u041d ConfigView.section.transfer.lan.tooltip=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u043f\u043e\u0441\u0435\u0431\u043d\u043e \u0437\u0430 \u041b\u0410\u041d ConfigView.section.transfer.lan.uploadrate=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 \u0443 KB/s \u0437\u0430 \u041b\u0410\u041d [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.transfer.lan.uploadrate.tooltip=\u0412\u0435\u0437\u0435 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 \u0443 \u041b\u0410\u041d\u0443 \u0438\u043c\u0430\u0458\u0443 \u043e\u0434\u0432\u043e\u0458\u0435\u043d\u0435 \u0433\u0440\u0430\u043d\u0438\u0446\u0435 \u0437\u0430 \u0441\u043b\u0430\u045a\u0435. ConfigView.section.transfer.lan.downloadrate=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u0443 KB/s \u0437\u0430 \u041b\u0410\u041d [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.transfer.lan.downloadrate.tooltip=\u0412\u0435\u0437\u0435 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 \u0443 \u0438\u0441\u0442\u043e\u043c \u041b\u0410\u041d\u0443 \u0438\u043c\u0430\u0458\u0443 \u043e\u0434\u0432\u043e\u0458\u0435\u043d\u0435 \u0433\u0440\u0430\u043d\u0438\u0446\u0435 \u0437\u0430 \u0431\u0440\u0437\u0438\u043d\u0443 \u043f\u0440\u0438\u0458\u0435\u043c\u0430. TorrentOptionsView.title.short=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 TorrentOptionsView.title.full=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 TorrentOptionsView.param.max.peers=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u0443\u043a\u0443\u043f\u0430\u043d \u0431\u0440\u043e\u0458 \u0432\u0435\u0437\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.connection.encryption.require_encrypted_transport=\u0417\u0430\u0445\u0442\u0435\u0432\u0430\u0458 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d \u043f\u0440\u0435\u043d\u043e\u0441 ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=\u0417\u0430\u0445\u0442\u0435\u0432\u0430\u0458 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0443 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0445 \u0432\u0435\u0437\u0430 \u0441\u0430 \u0434\u0440\u0443\u0433\u0438\u043c \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430. ConfigView.section.connection.encryption.min_encryption_level=\u041d\u0430\u0458\u043c\u0430\u045a\u0438 \u043d\u0438\u0432\u043e \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u045a\u0430 ConfigView.section.connection.encryption.min_encryption_level.tooltip=\u041e\u0431\u0438\u0447\u0430\u043d - \u0441\u0430\u043c\u043e \u043f\u043e\u0437\u0434\u0440\u0430\u0432\nRC4 - \u0446\u0435\u043e \u0442\u043e\u043a\n\u0428\u0442\u043e \u0432\u0435\u045b\u0438 \u043d\u0438\u0432\u043e \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u045a\u0430, \u0432\u0435\u045b\u0438 \u0441\u0443 \u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u0441\u043a\u0438 \u0437\u0430\u0445\u0442\u0435\u0432\u0438. Peers.column.Encryption=\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u045a\u0435 Peers.column.Encryption.info=\u041d\u0438\u0432\u043e \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u045a\u0430 \u043a\u043e\u0458\u0438 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 ConfigView.section.connection.encryption.encrypt.info=\u0410\u043a\u043e \u0458\u0435 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u045a\u0435 \u0443\u043a\u0459\u0443\u0447\u0435\u043d\u043e, \u043d\u0435\u045b\u0435\u0442\u0435 \u043c\u043e\u045b\u0438 \u0434\u0430 \u0441\u0435 \u043f\u043e\u0432\u0435\u0436\u0435\u0442\u0435 \u0441\u0430 \u043d\u0435\u043a\u043e\u043c\u043f\u0430\u0442\u0438\u0431\u0438\u043b\u043d\u0438\u043c \u043a\u043b\u0438\u0458\u0435\u043d\u0442\u0438\u043c\u0430 \u043e\u0441\u0438\u043c \u0430\u043a\u043e \u043d\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442\u0435 \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 ConfigView.section.connection.encryption.encrypt.info.link=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 \u043e\u0432\u0443 \u0432\u0435\u0437\u0443 \u0437\u0430 \u0432\u0438\u0448\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 MainWindow.sr.status.tooltip.ok=\u041e\u0434\u043d\u043e\u0441 \u0434\u0435\u0459\u0435\u045a\u0430 %1 \u0458\u0435 \u0443 \u0440\u0435\u0434\u0443 MainWindow.sr.status.tooltip.poor=\u041e\u0434\u043d\u043e\u0441 \u0434\u0435\u0459\u0435\u045a\u0430 %1 \u0458\u0435 \u0441\u043b\u0430\u0431: < 0.9 MainWindow.sr.status.tooltip.bad=\u041e\u0434\u043d\u043e\u0441 \u0434\u0435\u0459\u0435\u045a\u0430 %1 \u0458\u0435 \u043b\u043e\u0448: < 0.5 ConfigView.section.style.status=\u0421\u0442\u0430\u0442\u0443\u0441\u043d\u0430 \u0442\u0440\u0430\u043a\u0430: ConfigView.section.style.status.show_sr=\u041e\u0434\u043d\u043e\u0441 \u0434\u0435\u0459\u0435\u045a\u0430 ConfigView.section.style.status.show_nat=\u0421\u0442\u0430\u045a\u0435 \u041d\u0410\u0422\u0430 ConfigView.section.style.status.show_ddb=\u0421\u0442\u0430\u045a\u0435 \u0414\u0414\u0411\u0430 ConfigView.section.style.status.show_ipf=\u0421\u0442\u0430\u0442\u0443\u0441 \u0418\u041f\u0424\u0438\u043b\u0442\u0440\u0430 (IPFilter) ConfigView.section.connection.encryption.encrypt.group=\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u045a\u0435 \u0438 \u0441\u043a\u0440\u0438\u0432\u0430\u045a\u0435 \u043f\u0440\u0435\u043d\u043e\u0441\u0430 ConfigView.section.connection.encryption.encrypt.fallback_info=\u0423\u043a\u0459\u0443\u0447\u0438\u0432\u0430\u045a\u0435 \u0431\u0438\u043b\u043e \u043a\u043e\u0458\u0435\u0433 \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u043e\u0433 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u045b\u0435 \u0434\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 \u0432\u0435\u0437\u0443 \u0441\u0430 \u043d\u0435\u043a\u043e\u043c\u043f\u0430\u0442\u0438\u0431\u0438\u043b\u043d\u0438\u043c \u043a\u043b\u0438\u0458\u0435\u043d\u0442\u0438\u043c\u0430 \u0430\u043b\u0438 \u043d\u0435\u045b\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0438 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0435 \u0432\u0435\u0437\u0435 ConfigView.section.connection.encryption.encrypt.fallback_outgoing=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u043d\u0435\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0435 \u043e\u0434\u043b\u0430\u0437\u043d\u0435 \u0432\u0435\u0437\u0435 \u0430\u043a\u043e \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d \u043f\u0440\u0435\u043d\u043e\u0441 \u043d\u0435 \u0443\u0441\u043f\u0435 ConfigView.section.connection.encryption.encrypt.fallback_incoming=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u0434\u043e\u043b\u0430\u0437\u043d\u0435 \u0432\u0435\u0437\u0435 \u043a\u043e\u0458\u0435 \u043d\u0438\u0441\u0443 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0435 ConfigView.section.connection.encryption=\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u045a\u0435 \u043f\u0440\u0435\u043d\u043e\u0441\u0430 upnp.selectedinterfaces=\u0418\u0437\u0430\u0431\u0440\u0430\u043d\u0430 \u043c\u0440\u0435\u0436\u043d\u0430 \u0441\u0443\u0447\u0435\u0459\u0430 (\u0440\u0430\u0437\u0434\u0432\u043e\u0458\u0438\u0442\u0435 \u0441\u0430 \u201e;\u201c, \u043d\u043f\u0440. eth0;eth1) [\u043f\u0440\u0430\u0437\u043d\u043e: \u0441\u0432\u0435] ConfigView.section.style.defaultSortOrder=\u041f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0438 \u043f\u043e\u0440\u0435\u0434\u0430\u043a ConfigView.section.style.defaultSortOrder.desc=\u041e\u043f\u0430\u0434\u0430\u0458\u0443\u045b\u0438 ConfigView.section.style.defaultSortOrder.asc=\u0420\u0430\u0441\u0442\u0443\u045b\u0438 ConfigView.section.style.defaultSortOrder.flip=\u0421\u0443\u043f\u0440\u043e\u0442\u043d\u043e \u043e\u0434 \u043f\u0440\u0435\u0442\u0445\u043e\u0434\u043d\u043e\u0433 \u043f\u043e\u0440\u0435\u0442\u043a\u0430 LoggerView.autoscroll=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u043e \u043f\u043e\u043c\u0435\u0440\u0430\u045a\u0435 Button.selectAll=\u0418\u0437\u0430\u0431\u0435\u0440\u0438 \u0441\u0432\u0435 Button.markSelected=\u041e\u0437\u043d\u0430\u0447\u0438 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0435 Button.unmarkSelected=\u0423\u043a\u043b\u043e\u043d\u0438 \u043e\u0437\u043d\u0430\u043a\u0443 \u0437\u0430 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0435 plugins.basicview.config=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 TorrentOptionsView.param.max.uploads=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u0431\u0440\u043e\u0458 \u043f\u0440\u043e\u0440\u0435\u0437\u0430 \u0437\u0430 \u0441\u043b\u0430\u045a\u0435 [\u043d\u0430\u0458\u043c\u0430\u045a\u0435: 2] MyTorrentsView.dialog.setPosition.title=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u043c\u0435\u0441\u0442\u043e MyTorrentsView.dialog.setPosition.text=\u0423\u043d\u0435\u0441\u0438\u0442\u0435 \u043c\u0435\u0441\u0442\u043e \u0437\u0430 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435: MyTorrentsView.menu.reposition.manual=\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0438... ConfigView.section.connection.advanced.info.link=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 \u043e\u0432\u0443 \u0432\u0435\u0437\u0443 \u0437\u0430 \u0432\u0438\u0448\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 ConfigView.section.connection.advanced.socket.group=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u043f\u0440\u0438\u043a\u0459\u0443\u0447\u0430\u043a\u0430 ConfigView.section.connection.advanced.bind_port=\u041f\u0440\u0438\u0432\u0435\u0436\u0438 \u0437\u0430 \u043b\u043e\u043a\u0430\u043b\u043d\u0438 \u043f\u043e\u0440\u0442 [0: \u0438\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u043e] ConfigView.section.connection.advanced.bind_port.tooltip=\u041e\u0434\u043b\u0430\u0437\u043d\u0435 \u0432\u0435\u0437\u0435 \u045b\u0435 \u0443 \u043b\u043e\u043a\u0430\u043b\u0443 \u0431\u0438\u0442\u0438 \u043f\u043e\u0432\u0435\u0437\u0430\u043d\u0435 \u0441\u0430 \u0434\u0430\u0442\u0438\u043c \u043f\u043e\u0440\u0442\u043e\u043c.\n\u0423\u043a\u0459\u0443\u0447\u0438\u0432\u0430\u045a\u0435 \u043e\u0432\u043e\u0433\u0430 \u043c\u043e\u0436\u0435 \u0434\u0430 \u043f\u043e\u043c\u043e\u0433\u043d\u0435 \u0441\u0430 \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u043d\u043e\u0441\u0442\u0438\u043c\u0430 \u043a\u043e\u0434 \u041d\u0410\u0422 \u0440\u0443\u0442\u0435\u0440\u0430. ConfigView.section.proxy.group.tracker=\u0420\u0430\u0437\u0433\u043e\u0432\u043e\u0440 \u0441\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0438\u043c\u0430 ConfigView.section.proxy.group.peer=\u0420\u0430\u0437\u0433\u043e\u0432\u043e\u0440 \u0441\u0430 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438\u043c\u0430 Pieces.column.Requested=\u041f\u043e\u0442\u0440\u0430\u0436\u0435\u043d\u043e Pieces.column.Requested.info=\u041f\u0440\u0438\u043a\u0430\u0437\u0443\u0458\u0435 \u0434\u0430 \u043b\u0438 \u0432\u0438\u0448\u0435 \u0437\u0430\u0445\u0442\u0435\u0432\u0430 \u043c\u043e\u0433\u0443 \u0434\u0430 \u0441\u0435 \u043e\u0434\u043d\u043e\u0441\u0435 \u043d\u0430 \u0438\u0441\u0442\u0438 \u0434\u0435\u043e \u0438\u043b\u0438 \u043d\u0435 (*) ConfigView.label.maxuploadsseeding=\u0414\u0440\u0443\u0433\u043e \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 \u0437\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 MyTorrentsView.filter=\u0424\u0438\u043b\u0442\u0435\u0440: popup.error.hideall=\u0421\u0430\u043a\u0440\u0438\u0458 \u0441\u0432\u0435 ConfigView.section.style.dataStatsOnly=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 \u0441\u0430\u043c\u043e \u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 (\u0441\u0430\u043a\u0440\u0438\u0458 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 \u0437\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) ConfigView.section.style.separateProtDataStats=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u0440\u0430\u0437\u0434\u0432\u043e\u0458\u0435\u043d\u0435 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 \u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b MyTorrentsView.dialog.setFilter.title=\u0418\u0437\u043c\u0435\u043d\u0438 \u0444\u0438\u043b\u0442\u0435\u0440 MyTorrentsView.dialog.setFilter.text=\u041e\u0434\u0435\u0459\u0430\u043a %1 \u045b\u0435 \u0431\u0438\u0442\u0438 \u0444\u0438\u043b\u0442\u0440\u0438\u0440\u0430\u043d \u043f\u043e \u0442\u0435\u043a\u0441\u0442\u0443 \u043a\u043e\u0433 \u043e\u0432\u0434\u0435 \u0443\u043d\u0435\u0441\u0435\u0442\u0435. \u041a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u0437\u043d\u0430\u043a \u201e|\u201c (\u0446\u0435\u0432) \u0434\u0430 \u0444\u0438\u043b\u0442\u0440\u0438\u0440\u0430\u0442\u0435 \u043f\u043e \u0432\u0438\u0448\u0435 \u0444\u0440\u0430\u0437\u0430. MyTorrentsView.filter.tooltip=Ctrl+X \u0437\u0430 \u043f\u0440\u0435\u0431\u0430\u0446\u0438\u0432\u0430\u045a\u0435 \u0438\u0437\u043c\u0435\u0452\u0443 \u043e\u0431\u0438\u0447\u043d\u0435 \u043f\u0440\u0435\u0442\u0440\u0430\u0433\u0435 \u0438 \u043f\u0440\u0435\u0442\u0440\u0430\u0433\u0435 \u043f\u043e \u0440\u0435\u0433\u0443\u043b\u0430\u0440\u043d\u0438\u043c \u0438\u0437\u0440\u0430\u0437\u0438\u043c\u0430.\n\u041a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u0437\u043d\u0430\u043a \u201e|\u201c (\u0446\u0435\u0432) \u0434\u0430 \u0431\u0438\u0441\u0442\u0435 \u0444\u0438\u043b\u0442\u0440\u0438\u0440\u0430\u043b\u0438 \u043f\u043e \u0432\u0438\u0448\u0435 \u0444\u0440\u0430\u0437\u0430. MyTorrentsView.clearFilter.tooltip=\u041e\u0447\u0438\u0441\u0442\u0438 \u0444\u0438\u043b\u0442\u0435\u0440 MyTorrentsView.menu.filter=\u0421\u043f\u0438\u0441\u0430\u043a \u0444\u0438\u043b\u0442\u0435\u0440\u0430... ConfigView.section.file.resume.recheck.all=\u041a\u043e\u0434 \u043e\u043f\u043e\u0440\u0430\u0432\u043a\u0430 \u043f\u043e\u0441\u043b\u0435 \u0440\u0443\u0448\u0435\u045a\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u0446\u0435\u043b\u0443 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u0438 \u0437\u0430\u0432\u0440\u0448\u0435\u043d\u0435 \u0434\u0435\u043b\u043e\u0432\u0435 (\u0443 \u0441\u0443\u043f\u0440\u043e\u0442\u043d\u043e\u043c \u0441\u0430\u043c\u043e \u043e\u043d\u0435 \u0434\u0435\u043b\u043e\u0432\u0435 \u043a\u043e\u0458\u0438 \u0441\u0443 \u0431\u0438\u043b\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u0438 \u043f\u0440\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u045a\u0435\u043c \u0447\u0443\u0432\u0430\u045a\u0443) ConfigureWizard.language.choose=\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0458\u0435\u0437\u0438\u043a \u0441\u0430 \u0434\u043e\u043b\u0435 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u043e\u0433 \u0441\u043f\u0438\u0441\u043a\u0430: popup.closing.in=\u0417\u0430\u0442\u0432\u0430\u0440\u0430\u045a\u0435 \u043f\u0440\u043e\u0437\u043e\u0440\u0430: %1 s popup.more.waiting=\u0411\u0440\u043e\u0458 \u043f\u043e\u0440\u0443\u043a\u0430: %1 # > 2402 popup.download.finished=\u201e%1\u201f \u0458\u0435 \u0437\u0430\u0432\u0440\u0448\u0438\u043e \u0441\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u043e\u043c. popup.file.finished=\u201e%1\u201f \u0458\u0435 \u0437\u0430\u0432\u0440\u0448\u0438\u043e \u0441\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u043e\u043c. ConfigView.auto=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 Plugin.localtracker.autoadd.info=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u0434\u043e\u0434\u0430\u0458 \u043e\u0432\u0435 \u043b\u043e\u043a\u0430\u043b\u043d\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0435 [\u201e;\u201f \u043e\u0434\u0432\u0430\u0458\u0430 \u0430\u0434\u0440\u0435\u0441\u0435, \u043d\u043f\u0440. 1.2.3.4] Plugin.localtracker.autoadd=\u0415\u043a\u0441\u043f\u043b\u0438\u0446\u0438\u0442\u043d\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438 Plugin.localtracker.networks.info=\u0421\u043c\u0430\u0442\u0440\u0430\u0458 \u0434\u0430 \u0441\u0443 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0435 \u043c\u0440\u0435\u0436\u0435 \u043b\u043e\u043a\u0430\u043b\u043d\u0435 [\u201e;\u201f \u043e\u0434\u0432\u0430\u0458\u0430 \u043c\u0440\u0435\u0436\u0435, \u043d\u043f\u0440. 145.227.*.*] Plugin.localtracker.networks=\u041b\u043e\u043a\u0430\u043b\u043d\u0435 \u043c\u0440\u0435\u0436\u0435 MainWindow.menu.view.plugins.logViews=\u041f\u0440\u0435\u0433\u043b\u0435\u0434\u0438 \u0434\u043d\u0435\u0432\u043d\u0438\u043a\u0430 SpeedView.stats.autospeed=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 SpeedView.stats.autospeed.disabled=\u041e\u0432\u0430 \u043c\u043e\u0433\u0443\u045b\u043d\u043e\u0441\u0442 \u0458\u0435 \u0438\u043b\u0438 \u0438\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u0430 (\u043f\u043e\u0442\u0440\u0435\u0431\u0430\u043d \u0458\u0435 \u0414\u0425\u0422) \u0438\u043b\u0438 \u0441\u0435 \u043d\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 (\u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 \u0458\u0435 \u0440\u0443\u0447\u043d\u043e \u043f\u043e\u0434\u0435\u0448\u0435\u043d\u0430) SpeedView.stats.idlePing=\u041f\u0438\u043d\u0433: SpeedView.stats.maxPing=\u041d\u0430\u0458\u0432. \u043f\u0438\u043d\u0433: SpeedView.stats.currentPing=\u0422\u0440\u0435\u043d\u0443\u0442\u043d\u0438 \u043f\u0438\u043d\u0433: SpeedView.stats.maxUp=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430: ConfigView.pluginlist.unloadSelected=\u0423\u043a\u043b\u043e\u043d\u0438 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0435 ConfigView.pluginlist.scan=\u041f\u043e\u0442\u0440\u0430\u0436\u0438 \u043d\u043e\u0432\u0435 \u0434\u043e\u0434\u0430\u0442\u043a\u0435 ConfigView.section.transfer.autospeed=\u0410\u0443\u0442\u043e\u043c. \u0431\u0440\u0437\u0438\u043d\u0430 (\u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0430) ConfigView.section.transfer.autospeed.tooltip=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0437\u0430 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0443 \u0440\u0435\u0433\u0443\u043b\u0430\u0446\u0438\u0458\u0443 \u0431\u0440\u0437\u0438\u043d\u0435 ConfigView.section.transfer.autospeed.info=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u043e \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430 \u0433\u043e\u0440\u045a\u0443 \u0433\u0440\u0430\u043d\u0438\u0446\u0443 \u0431\u0440\u0437\u0438\u043d\u0435 \u043f\u0440\u0435\u043d\u043e\u0441\u0430 \u043a\u0430\u043a\u043e \u0431\u0438 \u0441\u0435 \u0438\u0437\u0431\u0435\u0433\u043b\u043e \u043f\u0440\u0435\u043e\u043f\u0442\u0435\u0440\u0435\u045b\u0435\u045a\u0435 \u043c\u0440\u0435\u0436\u043d\u0435 \u0432\u0435\u0437\u0435.\n\n\u041e\u0432\u0435 \u0433\u0440\u0430\u043d\u0438\u0446\u0435 \u0441\u0435 \u043f\u0440\u0438\u043c\u0435\u045a\u0443\u0458\u0443 \u0441\u0430\u043c\u043e \u0430\u043a\u043e \u0458\u0435 \u0443\u043a\u0459\u0443\u0447\u0435\u043d\u0430 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0430 \u0440\u0435\u0433\u0443\u043b\u0430\u0446\u0438\u0458\u0430 \u0431\u0440\u0437\u0438\u043d\u0435 \u0441\u043b\u0430\u045a\u0430, \u0438 \u0442\u0430\u043a\u043e\u0452\u0435 \u0437\u0430\u0445\u0442\u0435\u0432\u0430 \u0434\u0430 \u0458\u0435 \u0443\u043a\u0459\u0443\u0447\u0435\u043d\u0430 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0430 \u0431\u0430\u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430.\n ConfigView.section.transfer.autospeed.minupload=%1 \u043d\u0430\u0458\u043c\u0430\u045a\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 ConfigView.section.transfer.autospeed.minupload.tooltip=\u0411\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 \u043d\u0435\u045b\u0435 \u0431\u0438\u0442\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u0430 \u0438\u0441\u043f\u043e\u0434 \u043e\u0432\u0435 \u0433\u0440\u0430\u043d\u0438\u0446\u0435 ConfigView.section.transfer.autospeed.maxupload=%1 \u043d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.transfer.autospeed.maxupload.tooltip=\u0411\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 \u043d\u0435\u045b\u0435 \u0431\u0438\u0442\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u0430 \u0438\u0437\u043d\u0430\u0434 \u043e\u0432\u0435 \u0433\u0440\u0430\u043d\u0438\u0446\u0435 ConfigView.section.transfer.autospeed.chokeping=\u0412\u0440\u0435\u043c\u0435 \u0437\u0430 \u043f\u0438\u043d\u0433 \u0437\u0430 \u043f\u0440\u0438\u0433\u0443\u0448\u0435\u045a\u0435 [ms] ConfigView.section.transfer.autospeed.chokeping.tooltip=\u0412\u0440\u0435\u043c\u0435\u043d\u0430 \u043f\u0438\u043d\u0433\u043e\u0432\u0430\u045a\u0430 \u043a\u043e\u0458\u0430 \u0441\u0443 \u0432\u0435\u045b\u0430 \u043e\u0434 \u043e\u0432\u0435 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442\u0438 \u0431\u0438\u045b\u0435 \u0443\u0437\u0435\u0442\u0430 \u043a\u0430\u043e \u0437\u043d\u0430\u043a \u0434\u0430 \u0458\u0435 \u043c\u0440\u0435\u0436\u0430 \u0437\u0430\u0441\u0438\u045b\u0435\u043d\u0430 ConfigView.section.transfer.autospeed.enableauto=\u0423\u043a\u0459\u0443\u0447\u0438 \u043f\u0440\u0438 \u043f\u0440\u0438\u0458\u0435\u043c\u0443 \u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443 ConfigView.section.transfer.autospeed.enableautoseeding=\u0423\u043a\u0459\u0443\u0447\u0438 \u0441\u0430\u043c\u043e \u043f\u0440\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443 ConfigView.pluginlist.column.unloadable=\u0418\u0441\u043a\u0459\u0443\u0447\u0438\u0432 ConfigView.section.transfer.lan.enable=\u0414\u043e\u0437\u0432\u043e\u043b\u0438 \u043e\u0434\u0432\u043e\u0458\u0435\u043d\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0430 \u0431\u0440\u0437\u0438\u043d\u0435 \u0437\u0430 \u041b\u0410\u041d \u0432\u0435\u0437\u0435 Plugin.localtracker.wellknownlocals=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u0443\u043a\u0459\u0443\u0447\u0438 \u043f\u043e\u0432\u0440\u0430\u0442\u043d\u0435 \u0438 \u0441\u043b\u0438\u0447\u043d\u0435 \u043b\u043e\u043a\u0430\u043b\u043d\u0435 \u043c\u0440\u0435\u0436\u0435 (192.168...) TableColumn.header.filesdone=\u0413\u043e\u0442\u043e\u0432\u043e \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 TableColumn.header.filesdone.info=\u041f\u0440\u0435\u0443\u0437\u0435\u0442\u0438\u0445 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430/\u0443\u043a\u0443\u043f\u043d\u043e \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0438\u043b\u0438 \u043d\u0435\u043f\u0440\u0435\u0441\u043a\u043e\u0447\u0435\u043d\u0438\u0445 \u0434\u0430\u043e\u0442\u0442\u0435\u043a\u0430 (\u0443\u043a\u0443\u043f\u043d\u043e \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430)/\u0443\u043a\u0443\u043f\u043d\u043e \u043d\u0435\u043f\u0440\u0435\u0441\u043a\u043e\u0447\u0435\u043d\u0438\u0445 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 (\u0443\u043a\u0443\u043f\u043d\u043e \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430) MagnetPlugin.private_torrent=<\u043f\u0440\u0438\u0432\u0430\u0442\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442> MagnetPlugin.decentral_disabled=<\u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u043f\u0440\u0430\u045b\u0435\u045a\u0435 \u0458\u0435 \u0438\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u043e> MagnetPlugin.decentral_backup_disabled=<\u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0435 \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u0435 \u043a\u043e\u043f\u0438\u0458\u0435 \u0441\u0443 \u0438\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u0435> MagnetPlugin.report.waiting_ddb=\u0447\u0435\u043a\u0430 \u0441\u0435 \u043d\u0430 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u0414\u0414\u0411... MagnetPlugin.report.searching=\u0442\u0440\u0430\u0436\u0435\u045a\u0435... MagnetPlugin.report.found=\u043d\u0430\u0452\u0435\u043d\u043e: %1 MagnetPlugin.report.alive=\u0436\u0438\u0432: %1 MagnetPlugin.report.dead=\u043c\u0440\u0442\u0430\u0432: %1 MagnetPlugin.report.tunnel=\u0442\u0443\u043d\u0435\u043b\u043e\u0432\u0430\u045a\u0435 \u0434\u043e %1 MagnetPlugin.report.downloading=\u043f\u0440\u0438\u0458\u0435\u043c \u0441\u0430 %1 MagnetPlugin.report.error=\u0433\u0440\u0435\u0448\u043a\u0430 %1 MagnetURLHandler.report.no_sources=\u043d\u0438\u0458\u0435\u0434\u0430\u043d \u0438\u0437\u0432\u043e\u0440 \u043d\u0438\u0458\u0435 \u043d\u0430\u0452\u0435\u043d \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 MagnetURLHandler.report.torrent_size=\u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430: %1 MagnetURLHandler.report.percent=\u0433\u043e\u0442\u043e\u0432\u043e: %1% MagnetURLHandler.report.error=\u0433\u0440\u0435\u0448\u043a\u0430 %1 DHTTransport.report.request_all=\u0442\u0440\u0430\u0436\u0435\u045a\u0435 \u0446\u0435\u043b\u043e\u0433 \u043f\u0440\u0435\u043d\u043e\u0441\u0430 \u043e\u0434 %1 DHTTransport.report.received_bit=\u043f\u0440\u0438\u043c\u0459\u0435\u043d\u043e %1 \u0434\u043e %2 \u043e\u0434 %3 DHTTransport.report.complete=\u0433\u043e\u0442\u043e\u0432\u043e DHTTransport.report.timeout=\u0432\u0440\u0435\u043c\u0435 \u0458\u0435 \u0438\u0441\u0442\u0435\u043a\u043b\u043e, \u043d\u0435\u043c\u0430 \u043e\u0434\u0433\u043e\u0432\u043e\u0440\u0430 \u043e\u0434 %1 DHTTransport.report.rerequest_all=\u043f\u043e\u043d\u043e\u0432\u043d\u043e \u0442\u0440\u0430\u0436\u0435\u045a\u0435 \u0446\u0435\u043b\u043e\u0433 \u043f\u0440\u0435\u043d\u043e\u0441\u0430 \u043e\u0434 %1 DHTTransport.report.rerequest_bit=\u043f\u043e\u043d\u043e\u0432\u043e \u0442\u0440\u0430\u0436\u0435\u045a\u0435 %1 \u0434\u043e %2 \u043e\u0434 %3 DHTTransport.report.timeout_some=\u0432\u0440\u0435\u043c\u0435 \u0458\u0435 \u0438\u0441\u0442\u0435\u043a\u043b\u043e, \u043f\u0440\u0438\u043c\u0435\u0459\u043d\u0438\u0445 \u043f\u0430\u043a\u0435\u0442\u0430: %1 \u043e\u0434 %2, \u0430\u043b\u0438 \u043d\u0435\u043a\u043e\u043c\u043f\u043b\u0435\u0442\u043d\u0438\u0445 DHTTransport.report.sending=\u0441\u043b\u0430\u045a\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 DHTTransport.report.resending=\u043f\u043e\u043d\u043e\u0432\u043d\u043e \u0441\u043b\u0430\u045a\u0435 DHTTransport.report.send_complete=\u043f\u043e\u0441\u043b\u0430\u0442\u043e DHTTransport.report.send_timeout=\u0432\u0440\u0435\u043c\u0435 \u0458\u0435 \u0438\u0441\u0442\u0435\u043a\u043b\u043e ConfigView.section.transfer.autospeed.enabledebug=\u0417\u0430\u043f\u0438\u0441\u0443\u0458 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u043e \u0433\u0440\u0435\u0448\u043a\u0430\u043c\u0430 TableColumn.header.date_added={MyTorrentsView.date_added} TableColumn.header.date_added.info=\u0414\u0430\u0442\u0443\u043c \u043a\u0430\u0434\u0430 \u0458\u0435 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u043e\u0434\u0430\u0442 ConfigView.section.file.hashchecking.smallestfirst=\u041f\u0440\u043e\u0432\u0435\u0440\u0438 \u043f\u0440\u0432\u043e \u043d\u0430\u0458\u043c\u0430\u045a\u0435 \u043f\u0440\u0438\u0458\u0435\u043c\u0435 platform.win32.baddll.info=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u0458\u0435 \u043f\u0440\u0438\u043c\u0435\u0442\u0438 \u043f\u0440\u0438\u0441\u0443\u0441\u0442\u0432\u043e '%1'. \u0422\u043e \u0458\u0435 \u0434\u0435\u043e '%2' \u0438 \u043f\u043e\u0437\u043d\u0430\u0442\u043e \u0458\u0435 \u0434\u0430 \u043c\u043e\u0436\u0435 \u0431\u0443\u0434\u0435 \u0443\u0437\u0440\u043e\u043a \u043e\u0437\u0431\u0438\u0459\u043d\u0438\u0445 \u043f\u0440\u043f\u043e\u0431\u043b\u0435\u043c\u0430 \u043f\u043e\u043f\u0443\u0442 \u0440\u0443\u0448\u0435\u045a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u0438 \u0432\u0435\u043b\u0438\u043a\u0435 \u0437\u0430\u0443\u0437\u0435\u0442\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u0430. \u0410\u043a\u043e \u0441\u0435 \u0441\u0443\u043e\u0447\u0438\u0442\u0435 \u0441\u0430 \u043d\u0435\u043a\u0438\u043c \u043e\u0434 \u043e\u0432\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0443\u043a\u043b\u043b\u043e\u043d\u0438\u0442\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c \u0438\u043b\u0438 \u0433\u0430 \u043f\u043e\u0434\u0435\u0441\u0438\u0442\u0435 \u0434\u0430 \u043d\u0435 \u0443\u0442\u0438\u0447\u0435 \u043d\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430. platform.win32.baddll.niphk=\u041d\u043e\u0440\u043c\u0430\u043d\u043e\u0432 \u0410\u043d\u0442\u0438-\u0432\u0438\u0440\u0443\u0441 platform.win32.baddll.nvappfilter=\u041d\u0412\u0438\u0434\u0438\u0458\u0438\u043d \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d platform.win32.baddll.netdog=\u041b\u0438\u0447\u043d\u0438 \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d Armor2net platform.win32.baddll.vlsp=\u0412\u0435\u043d\u0442\u0443\u0440\u0438 \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d platform.win32.baddll.sarah=\u0412\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d \u043d\u0430 \u0430\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u0458\u0441\u043a\u043e\u043c \u043d\u0438\u0432\u043e\u0443, FRITZ! platform.win32.baddll.MxAVLsp=\u0412\u041a\u043e\u043c-\u043e\u0432\u0438 (VCom) \u0430\u043b\u0430\u0442\u0438 \u0437\u0430 \u043e\u043f\u0440\u0430\u0432\u043a\u0443 (Fix-It) platform.win32.baddll.mclsp=\u041c\u0435\u043a\u0435\u0444\u0438\u0458\u0435\u0432\u0430 (McAfee) \u0441\u043b\u0443\u0436\u0431\u0430 \u0437\u0430 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0441\u0442 platform.win32.baddll.radhslib=\u041d\u0430\u043e\u043c\u0438 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0444\u0438\u043b\u0442\u0435\u0440 (\u0420\u0430\u0434\u0438\u0458\u0430\u043d\u0442) platform.win32.baddll.nl_lsp=\u041d\u0435\u0442\u041b\u0438\u043c\u0438\u0442\u0435\u0440 platform.win32.baddll.winsflt=\u041f\u0458\u0443\u0440\u0421\u0430\u0458\u0442 (PureSight), \u0444\u0438\u043b\u0442\u0435\u0440 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0441\u0430\u0434\u0440\u0436\u0430\u0458\u0430 platform.win32.baddll.AxShlex=120% \u0430\u043b\u043a\u043e\u0445\u043e\u043b platform.win32.baddll.iFW_Xfilter=\u041b\u0438\u0447\u043d\u0438 \u0432\u0430\u0442\u0440\u043e\u0431\u0440\u0430\u043d \u0418\u043e\u043b\u043e (iolo) platform.win32.baddll.WSOCKHK=\u041c\u0440\u0435\u0436\u043d\u0430 \u0434\u0430\u0434\u0438\u0459\u0430 upnp.ignorebaddevices=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0438 \u0443\u0440\u0435\u0452\u0430\u0458\u0435 \u043a\u043e\u0458\u0438 \u043d\u0435 \u043e\u0434\u0433\u043e\u0432\u043e\u0440\u0435 \u043a\u0430\u043a\u043e \u0442\u0440\u0435\u0431\u0430 upnp.ignorebaddevices.info=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0435\u043d\u0438 \u0443\u0440\u0435\u0452\u0430\u0458\u0438: %1 upnp.ignorebaddevices.reset=\u041e\u0447\u0438\u0441\u0442\u0438 \u0441\u043f\u0438\u0441\u0430\u043a \u0437\u0430\u043d\u0435\u043c\u0430\u0440\u0435\u043d\u0438\u0445 \u0443\u0440\u0435\u0452\u0430\u0458\u0430 upnp.ignorebaddevices.reset.action=\u0412\u0440\u0430\u0442\u0438 upnp.ignorebaddevices.alert=\u0423\u0440\u0435\u0452\u0430\u0458 UPnP \u043d\u0430 \u043c\u0435\u0441\u0442\u0443 %1 \u0458\u0435 \u0437\u0430\u043d\u0435\u043c\u0430\u0440\u0435\u043d \u0443\u0441\u043b\u0435\u0434 \u0443\u0447\u0435\u0441\u0442\u0430\u043b\u0438\u0445 \u0433\u0440\u0435\u0448\u0430\u043a\u0430. \u041f\u043e\u0433\u043b\u0435\u0434\u0430\u0458\u0442\u0435 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0437\u0430 UPnP \u0434\u043e\u0434\u0430\u0442\u0430\u043a \u0437\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0435 \u043c\u043e\u0433\u0443\u045b\u043d\u043e\u0441\u0442\u0438 \u0443 \u0432\u0435\u0437\u0438 \u0441 \u043e\u0432\u0438\u043c \u0434\u0435\u0458\u0441\u0442\u0432\u043e\u043c. TorrentOptionsView.param.max.uploads.when.busy=KB/s \u043d\u0430\u0458\u0432\u0435\u045b\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u0441\u043b\u0430\u045a\u0430 \u043a\u0430\u0434\u0430 \u0458\u0435 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442\u043e \u0433\u043b\u043e\u0431\u0430\u043b\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u0441\u043b\u0430\u045a\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] UpdateMonitor.messagebox.verification.failed.title=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0435 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u0430 UpdateMonitor.messagebox.verification.failed.text=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u201e%1\u201f \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u0430: %2 UpdateMonitor.messagebox.accept.unverified.title=\u041f\u0440\u0438\u0445\u0432\u0430\u0442\u0438 \u043d\u0435\u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u0443 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0443 UpdateMonitor.messagebox.accept.unverified.text='%1' \u0438\u0437\u0433\u043b\u0435\u0434\u0430 \u043d\u0438\u0458\u0435 \u0437\u0432\u0430\u043d\u0438\u0447\u043d\u0438 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432 \u0434\u043e\u0434\u0430\u0442\u0430\u043a.\n\u0410\u043a\u043e \u0437\u0430\u0438\u0441\u0442\u0430 \u043d\u0438\u0458\u0435 \u0437\u0432\u0430\u043d\u0438\u0447\u0430\u043d \u0434\u043e\u0434\u0430\u0442\u0430\u043a, \u041d\u0415 \u0411\u0418\u0421\u0422\u0415 \u0442\u0440\u0435\u0431\u0430\u043b\u0438 \u0434\u0430 \u043d\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u0435.\n\u0414\u0430 \u043b\u0438 \u0434\u0430 \u043d\u0430\u0441\u0442\u0430\u0432\u0438\u043c \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0430\u045a\u0435? FileView.BlockView.title=\u0414\u0435\u043b\u043e\u0432\u0438 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 FileView.BlockView.Done=\u0413\u043e\u0442\u043e\u0432\u043e FileView.BlockView.Skipped=\u041f\u0440\u0435\u0441\u043a\u043e\u0447\u0435\u043d FileView.BlockView.Active=\u0410\u043a\u0442\u0438\u0432\u0430\u043d FileView.BlockView.Outstanding=\u041f\u0440\u0435\u043e\u0441\u0442\u0430\u043b\u043e ConfigView.label.tcplistenport=\u0414\u043e\u043b\u0430\u0437\u043d\u0438 \u043f\u043e\u0440\u0442 \u0437\u0430 \u0441\u043b\u0443\u0448\u0430\u045a\u0435 \u0422\u0426\u041f \u0432\u0435\u0437\u0435 ConfigView.label.udplistenport=\u0423\u0414\u041f \u043f\u043e\u0440\u0442 \u0437\u0430 \u0441\u043b\u0443\u0448\u0430\u045a\u0435 upnp.portchange.alert=\u041d\u0430\u0440\u0435\u0434\u043d\u0438 \u043f\u043e\u0440\u0442\u043e\u0432\u0438 \u0441\u0443 \u043f\u0440\u043e\u043c\u0435\u045a\u0435\u043d\u0438 \u043a\u0430\u043a\u043e \u0431\u0438 \u0441\u0435 \u0438\u0437\u0431\u0435\u0433\u043b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 \u0441\u0430 UPnP \u0443\u0440\u0435\u0452\u0430\u0458\u0435\u043c: %1 [\u0441\u0442\u0430\u0440\u0438 \u043f\u043e\u0440\u0442=%2] %3 [\u0441\u0442\u0430\u0440\u0438 \u043f\u043e\u0440\u0442=%4] ConfigView.section.proxy.username.info=\u0410\u043a\u043e \u0437\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u043a (proxy) \u0442\u0440\u0430\u0436\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0458\u0443 \u0447\u0430\u043a \u0438 \u0430\u043a\u043e \u043d\u0438\u0458\u0435 \u0434\u0435\u0444\u0438\u043d\u0438\u0441\u0430\u043d\u0430, \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u043d\u0438\u0441\u043a\u0443 \u201e\u201f \u0437\u0430 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e \u0438\u043c\u0435. ConfigView.label.maxuploadswhenbusymin=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 \u043a\u0430\u0434\u0430 \u0458\u0435 \u043c\u0435\u0440\u0430\u0447 \u0432\u0440\u0435\u043c\u0435\u043d\u0430 \u043f\u043e\u043a\u0440\u0435\u043d\u0443\u0442 [s] MainWindow.menu.help.debug=\u0417\u0430\u043f\u0438\u0448\u0438 \u043f\u043e\u0434\u0430\u0442\u043a\u0435 \u0437\u0430 \u0438\u0441\u043f\u0440\u0430\u0432\u0459\u0430\u045a\u0435 \u0433\u0440\u0435\u0448\u0430\u043a\u0430 (\u0434\u043d\u0435\u0432\u043d\u0438\u043a \u0440\u0443\u0448\u0435\u045a\u0430) DownloadManager.error.badsize=\u041d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u0430 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430 ConfigView.section.NATPMP=\u041d\u0410\u0422-\u041f\u041c\u041f natpmp.info=\u041d\u0410\u0422-\u041f\u041c\u041f \u0458\u0435 \u0415\u043f\u043b\u043e\u0432\u0430 (Apple) \u0437\u0430\u043c\u0435\u043d\u0430 \u0437\u0430 \u0423\u041f\u043d\u041f \u043a\u043e\u0458\u0443 \u043f\u043e\u0434\u0440\u0436\u0430\u0432\u0430\u0458\u0443 \u043d\u043e\u0432\u0435 \u0415\u0440\u043f\u043e\u0440\u0442 (Airport) \u0441\u0442\u0430\u043d\u0438\u0446\u0435.\n\n\u0422\u0440\u0435\u043d\u0443\u0442\u043d\u043e \u0458\u0435 \u043d\u0435\u043e\u043f\u0445\u043e\u0434\u043d\u043e \u0434\u0430 \u0423\u041f\u043d\u041f \u0431\u0443\u0434\u0435 \u0443\u043a\u0459\u0443\u0447\u0435\u043d \u043a\u0430\u043a\u043e \u0431\u0438 \u0438 \u041d\u0410\u0422-\u041f\u041c\u041f \u0431\u0438\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430\u043d, \u043f\u043e\u0448\u0442\u043e \u0441\u0435 \u041d\u0410\u0422-\u041f\u041c\u041f \u0443\u0440\u0435\u0452\u0430\u0458 \u0442\u0440\u0435\u0442\u0438\u0442\u0430 \u043a\u0430\u043e \u043f\u043e\u0441\u0435\u0431\u043d\u0430 \u0432\u0440\u0441\u0442\u0430 \u0423\u041f\u043d\u041f \u0443\u0440\u0435\u0452\u0430\u0458\u0430. natpmp.enable=\u0423\u043a\u0459\u0443\u0447\u0438 (\u0438 \u0415\u0440\u043f\u043e\u0440\u0442\u043e\u0432\u043e \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 \u043c\u043e\u0440\u0430 \u0431\u0438\u0442\u0438 \u0443\u043a\u0459\u0443\u0447\u0435\u043d\u043e \u043a\u0430\u043a\u043e \u0431\u0438 \u043e\u0432\u043e \u0440\u0430\u0434\u0438\u043b\u043e) ConfigView.section.tracker.host.addurls=\u041e\u0431\u0435\u0437\u0431\u0435\u0434\u0438 \u0434\u0430 \u0458\u0435 \u0423\u0420\u041b \u043e\u0432\u043e\u0433 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 \u043f\u0440\u0438\u0441\u0443\u0442\u0430\u043d \u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0438\u043c\u0430 \u043a\u043e\u0458\u0438 \u0441\u0435 \u0434\u0435\u043b\u0435 ConfigView.filter=\u0443\u043d\u0435\u0441\u0438\u0442\u0435 \u0442\u0435\u043a\u0441\u0442 \u0437\u0430 \u0444\u0438\u043b\u0442\u0440\u0438\u0440\u0430\u045a\u0435 ConfigView.section.files.move=\u041f\u0440\u0435\u043c\u0435\u0448\u0442\u0430\u045a\u0435 \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 ConfigView.section.file.defaultdir.section=\u0418\u0437\u0432\u043e\u0440\u043d\u0435 \u043e\u043f\u0446\u0438\u0458\u0435 \u0437\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c ConfigView.section.file.defaultdir.auto=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043f\u0440\u0438\u0458\u0435\u043c \u0443 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c (\u0431\u0435\u0437 \u043f\u0438\u0442\u0430\u045a\u0430) ConfigView.section.file.defaultdir.bestguess=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u043d\u0430\u0458\u0431\u043e\u0459\u0443 \u043f\u0440\u0435\u0442\u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0443 \u0437\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c ConfigView.section.file.defaultdir.ask=\u0418\u0437\u0432\u043e\u0440\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c: ConfigView.section.file.defaultdir.lastused=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c \u043d\u0430 \u043c\u0435\u0441\u0442\u043e \u0433\u0434\u0435 \u0458\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u045a\u0438 \u043f\u0443\u0442 \u0441\u043d\u0438\u043c\u0430\u043d\u043e ConfigView.section.file.config.section=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 ConfigView.section.file.config.currentdir=\u0422\u0440\u0435\u043d\u0443\u0442\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u0437\u0430 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430: ConfigView.section.torrent.decoding=\u0414\u0435\u043a\u043e\u0434\u0438\u0440\u0430\u045a\u0435 \u0441\u043a\u0443\u043f\u0430 \u0437\u043d\u0430\u043a\u043e\u0432\u0430 ConfigView.section.logging.udptransport=\u0423\u043a\u0459\u0443\u0447\u0438 \u0438\u0441\u0446\u0440\u043f\u0430\u043d \u0438\u0437\u0432\u0435\u0448\u0442\u0430\u0458 \u043e \u0423\u0414\u041f \u043f\u0440\u0435\u043d\u043e\u0441\u0443 Tracker.announce.ignorePeerSeed=\u0417\u0430\u043d\u0435\u043c\u0430\u0440\u0443\u0458\u0435 \u0441\u0435 \u0431\u0440\u043e\u0458 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430/\u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430. %1 ConfigView.section.connection.encryption.use_crypto_port=\u041a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u043f\u0440\u043e\u0448\u0438\u0440\u0435\u045a\u0435 \u0437\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 \u043f\u043e\u0434 \u0438\u043c\u0435\u043d\u043e\u043c \u201e\u043a\u0440\u0438\u043f\u0442\u043e\u043f\u043e\u0440\u0442\u201f \u043a\u0430\u043a\u043e \u0431\u0438\u0441\u0442\u0435 \u0441\u043f\u0440\u0435\u0447\u0438\u043b\u0438 \u043f\u043e\u043a\u0443\u0448\u0430\u0458\u0435 \u043e\u0431\u0438\u0447\u043d\u0438\u0445 \u0432\u0435\u0437\u0430. \u041d\u0435\u043a\u0438 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0438 \u043d\u0435 \u043f\u043e\u0434\u0440\u0436\u0430\u0432\u0430\u0458\u0443 \u043e\u0432\u0443 \u043c\u043e\u0433\u0443\u045b\u043d\u043e\u0441\u0442 \u043f\u0430 \u045b\u0435 \u0458\u0430\u0432\u0438\u0442\u0438 \u0433\u0440\u0435\u0448\u043a\u0443 \u043f\u043e\u043f\u0443\u0442 \u201e\u043d\u0435\u0432\u0430\u0436\u0435\u045b\u0438 \u043f\u043e\u0440\u0442\u201f \u0438\u043b\u0438 \u201e\u043d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u0430\u043d \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0430\u0440\u201f TorrentOptionsView.param.reset.to.default=\u0412\u0440\u0430\u0442\u0438 \u043d\u0430\u0437\u0430\u0434 \u043d\u0430 \u0438\u0437\u0432\u043e\u0440\u043d\u0435 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442\u0438 TorrentOptionsView.param.reset.button=\u0412\u0440\u0430\u0442\u0438 natpmp.routeraddress=\u0410\u0434\u0440\u0435\u0441\u0430 \u0441\u0442\u0430\u043d\u0438\u0446\u0435 [\u043f\u0440\u0430\u0437\u043d\u043e: \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438] ConfigView.section.style.disableAlertSliding=\u0418\u0441\u043a\u0459\u0443\u0447\u0438 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0458\u0443 \u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0430\u045a\u0435 \u043d\u0430 \u0432\u0440\u0445 \u0437\u0430 \u0445\u0438\u0442\u043d\u0435 \u043f\u043e\u0440\u0443\u043a\u0435 ConfigView.section.transfer.autospeed.maxinc=\u043d\u0430\u0458\u0432\u0435\u045b\u0435 \u043f\u043e\u0432\u0435\u045b\u0430\u045a\u0435 \u043f\u043e \u0446\u0438\u043a\u043b\u0443\u0441\u0443 %1 ConfigView.section.transfer.autospeed.maxdec=\u043d\u0430\u0458\u0432\u0435\u045b\u0435 \u0443\u043c\u0430\u045a\u0435\u045a\u0435 \u043f\u043e \u0446\u0438\u043a\u043b\u0443\u0441\u0443 %1 ConfigView.section.transfer.autospeed.enabledownadj=\u0423\u043a\u0459\u0443\u0447\u0438 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 ConfigView.section.transfer.autospeed.downadjratio=\u041f\u0440\u0438\u0458\u0435\u043c : \u041e\u0434\u043d\u043e\u0441 \u0431\u0440\u0437\u0438\u043d\u0430 (\u043d\u043f\u0440. 2.0 -> \u0433\u0440\u0430\u043d\u0438\u0446\u0430 \u0437\u0430 \u0431\u0440\u0437\u0438\u043d\u0443 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u0458\u0435 \u0434\u0432\u043e\u0441\u0442\u0440\u0443\u043a\u043e \u0432\u0435\u045b\u0430 \u043e\u0434 \u0431\u0440\u0437\u0438\u043d\u0435 \u0441\u043b\u0430\u045a\u0430) ConfigView.section.transfer.autospeed.latencyfactor=\u0424\u0430\u043a\u0442\u043e\u0440 \u043a\u043e\u0458\u0438 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u043a\u0430\u043e \u0432\u0435\u0437\u0430 \u0438\u0437\u043c\u0435\u0452\u0443 \u043a\u0430\u0448\u045a\u0435\u045a\u0430 \u0438 \u043f\u0440\u043e\u043c\u0435\u043d\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 (\u0432\u0435\u045b\u0438 \u0431\u0440\u043e\u0458 \u0437\u043d\u0430\u0447\u0438 \u043c\u0430\u045a\u0443 \u043e\u0441\u0435\u0442\u0459\u0438\u0432\u043e\u0441\u0442) ConfigView.section.transfer.autospeed.reset=\u0412\u0440\u0430\u0442\u0438 \u0438\u0437\u0432\u043e\u0440\u043d\u0435 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442\u0438 ConfigView.section.transfer.autospeed.reset.button=\u0412\u0440\u0430\u0442\u0438 PeerColumn.activationCount=\u0411\u0440\u043e\u0458 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u043a\u043e\u0458\u0438 \u0436\u0435\u043b\u0435 \u0434\u0430 \u0441\u0435 \u043f\u043e\u0432\u0435\u0436\u0443: %1 TableColumn.header.timesincedownload.info=\u041f\u0440\u043e\u0442\u0435\u043a\u043b\u043e \u0432\u0440\u0435\u043c\u0435 \u043e\u0434 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 TableColumn.header.timesincedownload=\u041f\u0440\u0438\u0458\u0435\u043c \u0441\u0442\u043e\u0458\u0438 TableColumn.header.timesinceupload.info=\u041f\u0440\u043e\u0442\u0435\u043a\u043b\u043e \u0432\u0440\u0435\u043c\u0435 \u043e\u0434 \u0441\u043b\u0430\u045a\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 TableColumn.header.timesinceupload=\u0421\u043b\u0430\u045a\u0435 \u0441\u0442\u043e\u0458\u0438 PeersView.incomingreqcount=\u0414\u043e\u043b\u0430\u0437\u043d\u0438 \u0437\u0430\u0445\u0442\u0435\u0432\u0438 PeersView.incomingreqcount.info=\u0411\u0440\u043e\u0458 \u0434\u043e\u043b\u0430\u0437\u043d\u0438\u0445 \u0437\u0430\u0445\u0442\u0435\u0432\u0430 \u043a\u043e\u0458\u0435 \u0458\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u043f\u043e\u0441\u043b\u0430\u043e PeersView.outgoingreqcount=\u041e\u0434\u043b\u0430\u0437\u043d\u0438 \u0437\u0430\u0445\u0442\u0435\u0432\u0438 PeersView.outgoingreqcount.info=\u0411\u0440\u043e\u0458 \u043e\u0434\u043b\u0430\u0437\u043d\u0438\u0445 \u0437\u0430\u0445\u0442\u0435\u0432\u0430 \u043f\u043e\u0441\u043b\u0430\u0442\u0438\u0445 \u0443\u0434\u0430\u0459\u0435\u043d\u043e\u043c \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0443 upnp.mapping.trackerclientudp=\u041a\u043b\u0438\u0458\u0435\u043d\u0442\u0441\u043a\u0438 \u043f\u043e\u0440\u0442 \u0423\u0414\u041f \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 upnp.mapping.dhtudp=\u0414\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0430 \u0431\u0430\u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 ConfigView.section.connection.nondata.udp.same=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0438\u0441\u0442\u0438 \u0423\u0414\u041f \u043f\u043e\u0440\u0442 \u0437\u0430 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0443 \u0431\u0430\u0437\u0443 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u0438 \u0423\u0414\u041f \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 ConfigView.section.connection.tcp.enable=\u0423\u043a\u0459\u0443\u0447\u0438 \u0422\u0426\u041f ConfigView.section.connection.udp.enable=\u0423\u043a\u0459\u0443\u0447\u0438 \u0423\u0414\u041f ConfigView.section.style.showiconbar=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u0430\u043b\u0430\u0442\u043d\u0443 \u0442\u0440\u0430\u043a\u0443 MainWindow.menu.view.iconbar=\u0410\u043b\u0430\u0442\u043d\u0430 \u0442\u0440\u0430\u043a\u0430 MyTorrentsView.menu.rename=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0458 MyTorrentsView.menu.rename.displayed=\u041f\u0440\u043e\u043c\u0435\u043d\u0438 \u043f\u0440\u0438\u043a\u0430\u0437\u0430\u043d\u043e \u0438\u043c\u0435 MyTorrentsView.menu.rename.save_path=\u041f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0458 \u0441\u0442\u0430\u0437\u0443 \u0437\u0430 \u0447\u0443\u0432\u0430\u045a\u0435 MyTorrentsView.menu.rename.displayed.enter.title=\u041f\u0440\u043e\u043c\u0435\u043d\u0438 \u043f\u0440\u0438\u043a\u0430\u0437\u0430\u043d\u043e \u0438\u043c\u0435 MyTorrentsView.menu.rename.displayed.enter.message=\u0423\u043d\u0435\u0441\u0438\u0442\u0435 \u043d\u043e\u0432\u043e \u0438\u043c\u0435 \u0437\u0430 \u043e\u0432\u0430\u0458 \u043f\u0440\u0438\u0458\u0435\u043c.\n\u0410\u043a\u043e \u0441\u0435 \u043d\u0435 \u0443\u043d\u0435\u0441\u0435 \u043d\u0438\u043a\u0430\u043a\u0430\u0432 \u0442\u0435\u043a\u0441\u0442, \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0441\u0435 \u0438\u0437\u0432\u043e\u0440\u043d\u043e \u0438\u043c\u0435. MyTorrentsView.menu.edit_comment=\u0423\u0440\u0435\u0434\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 MyTorrentsView.menu.edit_comment.enter.title=\u0423\u0440\u0435\u0434\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 MyTorrentsView.menu.edit_comment.enter.message=\u0423\u043d\u0435\u0441\u0438\u0442\u0435 \u043d\u043e\u0432\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0437\u0430 \u043e\u0432\u0430\u0458 \u043f\u0440\u0438\u0458\u0435\u043c. UIDebugGenerator.messageask.title=\u0413\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043f\u0440\u0438\u0458\u0430\u0432\u0435 \u0437\u0430 \u0433\u0440\u0435\u0448\u043a\u0443 UIDebugGenerator.messageask.text=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0443\u043d\u0435\u0441\u0435\u0442\u0435 \u043e\u043f\u0438\u0441 \u0433\u0440\u0435\u0448\u043a\u0435 \u043a\u043e\u0458\u0443 \u043f\u0440\u0438\u0458\u0430\u0432\u0459\u0443\u0458\u0435\u0442\u0435 UIDebugGenerator.complete.title=\u0417\u0430\u0432\u0440\u0448\u0435\u043d\u043e \u0458\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0441\u0430\u045a\u0435 \u0438\u0437\u0432\u0435\u0448\u0442\u0430\u0458\u0430 \u043e \u0433\u0440\u0435\u0448\u0446\u0438 UIDebugGenerator.complete.text=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u043e\u0448\u0430\u0459\u0435\u0442\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u201e%1\u201f \u043d\u0430 \u0430\u0434\u0440\u0435\u0441\u0443\n\n\u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u201e\u0423 \u0440\u0435\u0434\u0443\u201f \u0434\u0430 \u0431\u0438\u0441\u0442\u0435 \u043e\u0442\u0432\u043e\u0440\u0438\u043b\u0438 \u043e\u0432\u0443 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 \u0443 \u043f\u0440\u043e\u0437\u043e\u0440\u0443. ConfigView.section.style.showProgramIcon=\u041f\u0440\u0438\u043a\u0430\u0437\u0443\u0458 \u0441\u043b\u0438\u0447\u0438\u0446\u0443 \u0437\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c \u0443 \u043a\u043e\u043b\u043e\u043d\u0438 \u0437\u0430 \u0438\u043c\u0435 ConfigView.section.style.showProgramIcon.tooltip=\u041c\u043e\u0436\u0434\u0430 \u045b\u0435\u0442\u0435 \u043c\u043e\u0440\u0430\u0442\u0438 \u0434\u0430 \u043f\u043e\u043d\u043e\u0432\u043e \u043e\u0442\u0432\u043e\u0440\u0438\u0442\u0435 \u043f\u0440\u0435\u0433\u043b\u0435\u0434 \u043a\u0430\u043a\u043e \u0431\u0438 \u0438\u0437\u043c\u0435\u043d\u0435 \u0431\u0438\u043b\u0435 \u0443\u0432\u0430\u0436\u0435\u043d\u0435 swt.alert.cant.update=SWT \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0443\u0447\u0438\u0442\u0430\u043d\u0430 \u0441\u0430 "%3" \u043d\u0435 \u043c\u043e\u0436\u0435 \u0441\u0435 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u0434\u043e\u0433\u0440\u0430\u0434\u0438\u0442\u0438 \u0441\u0430 \u0438\u0437\u0434\u0430\u045a\u0430 %1 \u043d\u0430 %2 (\u043c\u043e\u0440\u0430 \u0441\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u0438 \u0441\u0430 "%4"). \u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u043e\u0433\u043b\u0435\u0434\u0430\u0442\u0435 \u0432\u0438\u043a\u0438 \u0437\u0430 \u0432\u0438\u0448\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430. authenticator.savepassword=\u0417\u0430\u043f\u0430\u043c\u0442\u0438 \u043b\u043e\u0437\u0438\u043d\u043a\u0443 ConfigView.section.security.clearpasswords=\u0423\u043a\u043b\u043e\u043d\u0438 \u0441\u043f\u0438\u0441\u0430\u043a \u0437\u0430\u043f\u0430\u043c\u045b\u0435\u043d\u0438\u0445 \u043b\u043e\u0437\u0438\u043d\u043a\u0438 ConfigView.section.security.clearpasswords.button=\u0412\u0440\u0430\u0442\u0438 Content.alert.notuploaded.title=\u0421\u043b\u0430\u045a\u0435 \u043d\u0438\u0458\u0435 \u0434\u043e\u0432\u0440\u0448\u0435\u043d\u043e Content.alert.notuploaded.text=\u041f\u0440\u0435\u043d\u043e\u0441 \u0437\u0430 \u201e%1\u201f \u043d\u0438\u0458\u0435 \u0434\u043e\u0432\u0440\u0448\u0435\u043d. \u0410\u043a\u043e \u0441\u0430\u0434\u0430 %2, \u0434\u0440\u0443\u0433\u0438 \u043d\u0435\u045b\u0435 \u043c\u043e\u045b\u0438 \u0434\u0430 \u043f\u0440\u0435\u0443\u0437\u043c\u0443 \u0412\u0430\u0448\u0443 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443.\n\n\u0414\u0430 \u043b\u0438 \u0441\u0442\u0435 \u0441\u0438\u0433\u0443\u0440\u043d\u0438 \u0434\u0430 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 %2? Content.alert.notuploaded.multi.title=\u0421\u043b\u0430\u045a\u0435 \u043d\u0438\u0458\u0435 \u043f\u043e\u0442\u043f\u0443\u043d\u043e Content.alert.notuploaded.multi.text=%1 \u0441\u0430\u0434\u0440\u0436\u0430\u0458\u0430 \u043a\u043e\u0433 \u0441\u0442\u0435 \u043e\u0431\u0458\u0430\u0432\u0438\u043b\u0438 \u043d\u0438\u0458\u0435 \u0437\u0430\u043c\u0435\u0442\u043d\u0443\u0442\u043e. \u0410\u043a\u043e \u0441\u0430\u0434\u0430 %2, \u0459\u0443\u0434\u0438 \u043d\u0435\u045b\u0435 \u043c\u043e\u045b\u0438 \u0434\u0430 \u043f\u0440\u0435\u0443\u0437\u043c\u0443 \u0412\u0430\u0448\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0443 \u0446\u0435\u043b\u0438\u043d\u0438. \u0414\u0430 \u043b\u0438 \u0441\u0438\u0433\u0443\u0440\u043d\u043e \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 %2?\n\n\u0421\u0430\u0434\u0440\u0436\u0430\u0458 \u043a\u043e\u0458\u0438 \u043d\u0438\u0458\u0435 \u0437\u0430\u043c\u0435\u0442\u043d\u0443\u0442:\n%3 Content.alert.notuploaded.stop=\u0437\u0430\u0443\u0441\u0442\u0430\u0432\u0438 Content.alert.notuploaded.quit=\u043a\u0440\u0430\u0458 \u0440\u0430\u0434\u0430 TorrentInfoView.torrent.encoding=\u041a\u043e\u0434\u0438\u0440\u0430\u045a\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 TorrentInfoView.columns=\u041a\u043e\u043b\u043e\u043d\u0435 \u0438\u0437 \u043f\u043e\u0433\u043b\u0435\u0434\u0430 \u201eMy Torrents\u201f progress.window.title=\u0414\u0435\u0458\u0441\u0442\u0432\u043e \u0458\u0435 \u0443 \u0442\u043e\u043a\u0443 progress.window.msg.filemove=\u041c\u043e\u043b\u0438\u043c\u043e \u0412\u0430\u0441 \u0434\u0430 \u0441\u0430\u0447\u0435\u043a\u0430\u0442\u0435 \u0434\u0430 \u0441\u0435 \u043f\u043e\u043c\u0435\u0440\u0430\u045a\u0435 \u0438\u043b\u0438 \u043f\u0440\u043e\u043c\u0435\u043d\u0430 \u0438\u043c\u0435\u043d\u0430 \u0434\u043e\u0432\u0440\u0448\u0438 ConfigView.label.popup.timestamp=\u0414\u043e\u0434\u0430\u0432\u0430\u045a\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0441\u043a\u0435 \u043e\u0437\u043d\u0430\u043a\u0435 \u043d\u0430 \u0443\u0437\u0431\u0443\u043d\u0435 ConfigView.label.popup.autohide=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u043e \u0441\u0430\u043a\u0440\u0438\u0432\u0430\u045a\u0435 \u0443\u0437\u0431\u0443\u043d\u0430 \u043a\u043e\u0458\u0435 \u043d\u0435 \u0441\u0430\u0434\u0440\u0436\u0435 \u0433\u0440\u0435\u0448\u043a\u0435, \u043f\u043e\u0441\u043b\u0435 X \u0441\u0435\u043a\u0443\u043d\u0434\u0438 (\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u043d\u0430 0 \u0434\u0430 \u0443\u043a\u0438\u043d\u0435\u0442\u0435 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u043e \u0441\u0430\u043a\u0440\u0438\u0432\u0430\u045a\u0435) ConfigView.label.popup.suppress_alerts=\u0423\u045b\u0443\u0442\u043a\u0430\u0458 \u0443\u0437\u0431\u0443\u043d\u0435 ConfigView.label.popup.use_message_boxes=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0438\u0441\u043a\u0430\u0447\u0443\u045b\u0435 \u043f\u043e\u0440\u0443\u043a\u0435 \u0440\u0430\u0434\u0438\u0458\u0435 \u043d\u0435\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0434\u043d\u0435 \u043f\u043e\u0440\u0443\u043a\u0435 \u0441\u0430 \u0443\u043f\u043e\u0437\u043e\u0440\u0435\u045a\u0438\u043c\u0430. ConfigView.label.popup.show=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u0441\u0432\u0435 \u0434\u043e\u0441\u0430\u0434 \u0437\u0430\u0431\u0435\u043b\u0435\u0436\u0435\u043d\u0435 \u0443\u0437\u0431\u0443\u043d\u0435 (\u0430\u043a\u043e \u0438\u0445 \u0438\u043c\u0430) ConfigView.label.popup.show.button=\u041f\u0440\u0438\u043a\u0430\u0437 ConfigView.label.please.visit.here=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 \u043e\u0432\u0443 \u0432\u0435\u0437\u0443 \u0437\u0430 \u0432\u0438\u0448\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 ConfigView.section.ipfilter.enable.descriptionCache=\u0427\u0443\u0432\u0430\u045a\u0435 \u043e\u043f\u0438\u0441\u0430 \u0418\u041f \u0430\u0434\u0440\u0435\u0441\u0430 \u0443 \u043f\u0440\u0438\u0432\u0440\u0435\u043c\u0435\u043d\u043e\u0458 \u0434\u0430\u0442\u043e\u0442\u0435\u0446\u0438 ConfigView.section.ipfilter.enable.descriptionCache.tooltip=\u041a\u0430\u0434\u0430 \u0458\u0435 \u0438\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u043e, \u043e\u043f\u0438\u0441\u0438 \u043d\u0435\u045b\u0435 \u0431\u0438\u0442\u0438 \u0447\u0443\u0432\u0430\u043d\u0438 OpenTorrentWindow.filesInfo=%1 \u043e\u0434 %2 \u045b\u0435 \u0431\u0438\u0442\u0438 \u043f\u0440\u0435\u0443\u0437\u0435\u0442\u043e. OpenTorrentWindow.diskUsage=%1 \u043e\u0434 %2 ConfigView.label.openmytorrents=\u041e\u0442\u0432\u043e\u0440\u0438 \u201e\u041c\u043e\u0458\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435\u201f \u043f\u0440\u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0443 ConfigView.label.open_transfer_bar_on_start=\u041e\u0442\u0432\u043e\u0440\u0438 \u0442\u0440\u0430\u043a\u0443 \u0437\u0430 \u043f\u0440\u0435\u043d\u043e\u0441 \u043f\u0440\u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0443 ConfigView.section.style.DNDalwaysInIncomplete=\u0423\u0432\u0435\u043a \u043f\u0440\u0438\u043a\u0430\u0437\u0443\u0458 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 \u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0435 \u043a\u0430\u043e \u201e\u041d\u0435 \u043f\u0440\u0438\u043c\u0430\u0458\u201f \u0443 \u043e\u0434\u0435\u0459\u043a\u0443 \u0437\u0430 \u043d\u0435\u0437\u0430\u0432\u0440\u0448\u0435\u043d\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0435 OpenTorrentWindow.mb.noGlobalDestDir.title=\u041e\u0434\u0440\u0435\u0434\u0438\u0448\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c OpenTorrentWindow.mb.noGlobalDestDir.text=\u041e\u0434\u0440\u0435\u0434\u0438\u0448\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u201e%1\u201f \u043d\u0438\u0458\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u0430\u043d. OpenTorrentWindow.mb.noDestDir.title=\u041e\u0434\u0440\u0435\u0434\u0438\u0448\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u043d\u0438\u0458\u0435 \u043f\u0440\u043e\u043d\u0430\u0452\u0435\u043d OpenTorrentWindow.mb.noDestDir.text=\u041e\u0434\u0440\u0435\u0434\u0438\u0448\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u201e%1\u201f \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 \u201e%2\u201f \u043d\u0435 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 \u0438\u043b\u0438 \u043d\u0438\u0458\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u0430\u043d. OpenTorrentWindow.mb.notValid.title=\u041e\u0442\u0432\u043e\u0440\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 OpenTorrentWindow.mb.notValid.text=\u0422\u043e\u0440\u0435\u043d\u0442 \u201e%1\u201f \u043d\u0438\u0458\u0435 \u043c\u043e\u0433\u0443\u045b\u0435 \u043e\u0442\u0432\u043e\u0440\u0438\u0442\u0438. \u0410\u043a\u043e \u043e\u0442\u0432\u0430\u0440\u0430\u0442\u0435 \u0437\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435, \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u0434\u0430 \u0441\u0443 \u043f\u043e\u0434\u0430\u0446\u0438 \u043f\u0440\u0438\u0441\u0443\u0442\u043d\u0438. OpenTorrentWindow.mb.notTorrent.title=\u041e\u0442\u0432\u043e\u0440\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 OpenTorrentWindow.mb.notTorrent.text=\u041d\u0438\u0458\u0435 \u043c\u043e\u0433\u0443\u045b\u0435 \u043e\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u201e%1\u201f. \u0418\u0437\u0433\u043b\u0435\u0434\u0430 \u0434\u0430 \u043d\u0438\u0458\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0441\u0430 \u043f\u043e\u0434\u0430\u0446\u0438\u043c\u0430 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442.\n\n\u0428\u0442\u0430 \u0458\u0435 \u043e\u0434 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u043f\u0440\u0438\u043c\u0459\u0435\u043d\u043e:\n%2 ConfigView.label.pause.downloads.on.exit=\u041f\u0430\u0443\u0437\u0438\u0440\u0430\u0458 \u043f\u0440\u0438\u0458\u0435\u043c \u043f\u0440\u0435 \u043a\u0440\u0430\u0458\u0430 \u0440\u0430\u0434\u0430 ConfigView.label.resume.downloads.on.start=\u041d\u0430\u0441\u0442\u0430\u0432\u0438 \u043f\u0430\u0443\u0437\u0438\u0440\u0430\u043d\u0435 \u043f\u0440\u0438\u0458\u0435\u043c\u0435 \u043f\u0440\u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0443 \u043a\u0430\u0434\u0430 \u0458\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c \u0441\u043f\u0440\u0435\u043c\u0430\u043d \u0437\u0430 \u0440\u0430\u0434 UIDebugGenerator.message.cancel.title=\u041e\u0442\u043a\u0430\u0437\u0430\u043d\u043e \u0458\u0435 \u043f\u0440\u0430\u0432\u0459\u0435\u045a\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u0437\u0430 \u0438\u0441\u043f\u0440\u0430\u0432\u043a\u0443 \u0433\u0440\u0435\u0448\u0430\u043a\u0430 UIDebugGenerator.message.cancel.text=\u041d\u0438\u0441\u0442\u0435 \u0443\u043d\u0435\u043b\u0438 \u043e\u043f\u0438\u0441 \u0433\u0440\u0435\u0448\u043a\u0435 \u043a\u043e\u0458\u0443 \u043f\u043e\u043a\u0443\u0448\u0430\u0432\u0430\u0442\u0435 \u0434\u0430 \u043f\u0440\u0438\u0458\u0430\u0432\u0438\u0442\u0435. \u0413\u0440\u0435\u0448\u043a\u0430 \u043a\u043e\u0458\u0430 \u0441\u0435 \u0434\u0435\u0441\u0438\u043b\u0430 \u0458\u0435 \u043c\u043e\u0436\u0434\u0430 \u043e\u0447\u0438\u0433\u043b\u0435\u0434\u043d\u0430 \u0432\u0430\u043c\u0430, \u0430\u043b\u0438 \u0431\u0435\u0437 \u043e\u043f\u0438\u0441\u0430, \u043c\u0438 \u0431\u0438\u0441\u043c\u043e \u043c\u043e\u0440\u0430\u043b\u0438 \u0434\u0430 \u043d\u0430\u0433\u0430\u0452\u0430\u043c\u043e \u0443 \u0447\u0435\u043c\u0443 \u0458\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c.\n\n\u041f\u0440\u0430\u0432\u0459\u0435\u045a\u0435 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 \u0441\u0430 \u0438\u0437\u0432\u0435\u0448\u0442\u0430\u0458\u0435\u043c \u043e \u0433\u0440\u0435\u0448\u0446\u0438 \u0458\u0435 \u043e\u0442\u043a\u0430\u0437\u0430\u043d\u043e. ConfigView.section.connection.group.http.info=\u041f\u043e\u0434\u0440\u0448\u043a\u0430 \u0437\u0430 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 \u043f\u0443\u0442\u0435\u043c HTTP\u0430. ConfigView.section.connection.http.enable=\u0423\u043a\u0459\u0443\u0447\u0435\u043d\u043e ConfigView.section.connection.http.port=\u0411\u0440\u043e\u0458 \u0434\u043e\u043b\u0430\u0437\u043d\u043e\u0433 \u043f\u043e\u0440\u0442\u0430 ConfigView.section.connection.http.portoverride=HTTP \u043f\u043e\u0440\u0442 \u0437\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 [0: \u043d\u0438\u0458\u0435\u0434\u0430\u043d] window.update.noupdates.title=\u0420\u0435\u0437\u0443\u043b\u0442\u0430\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u0435 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0438 window.update.noupdates.text=\u0417\u0430 \u0432\u0430\u0441 \u043d\u0435\u043c\u0430 \u043d\u043e\u0432\u0438\u0445 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0438.\n\n\u0427\u0435\u0441\u0442\u0438\u0442\u0430\u043c\u043e! ConfigView.label.bindip.details=\u041f\u0440\u0438\u043c\u0435\u0440: 192.168.1.5;eth0;eth1[2] \u045b\u0435 \u0434\u0430 \u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0448\u0435 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438 \u0418\u041f \u0431\u0440\u043e\u0458, \u0437\u0430 \u0441\u0432\u0435 \u0431\u0440\u043e\u0458\u0435\u0432\u0435 \u0434\u043e \u043f\u0440\u0432\u043e\u0433 \u0441\u0443\u0447\u0435\u0459\u0430 \u0438 \u0442\u0440\u0435\u045b\u0438 \u0418\u041f \u0431\u0440\u043e\u0458 \u0434\u0440\u0443\u0433\u043e\u0433 \u0441\u0443\u0447\u0435\u0459\u0430 IP of the 2nd interface.\n\u041f\u0440\u0432\u0438 \u0418\u041f \u0431\u0440\u043e\u0458 \u045b\u0435 \u0431\u0438\u0442\u0438 \u043a\u043e\u0440\u0438\u0448\u045b\u0435\u043d \u0437\u0430 \u0441\u0432\u0435 \u0443\u0441\u043b\u0443\u0433\u0435, \u043e\u0441\u0442\u0430\u043b\u0438 \u0418\u041f \u0431\u0440\u043e\u0458\u0435\u0432\u0438 \u045b\u0435 \u0434\u0430 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0435 \u0437\u0430 \u0441\u0432\u0435 \u0443\u0441\u043b\u0443\u0433\u0435, \u0441\u0432\u0438 \u043e\u0441\u0442\u0430\u043b\u0438 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u0442\u0435 \u0437\u0430 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u0430\u045a\u0435 \u043e\u043f\u0442\u0435\u0440\u0435\u045b\u0435\u045a\u0430.\n\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0438 \u0441\u0443 \u043e\u0432\u0434\u0435 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0438:\n%1 ConfigView.label.mindownloads=\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u0430\u043d \u0431\u0440\u043e\u0458 \u0438\u0441\u0442\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u0438\u0445 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 UI.cannot_submit_blank_text=\u041c\u043e\u0440\u0430\u0442\u0435 \u0434\u0430 \u0443\u043d\u0435\u0441\u0435\u0442\u0435 \u043d\u0435\u043a\u0443 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442. crypto.alert.as.warning=\u0417\u0430 \u043c\u0440\u0435\u0436\u0443 \u201e%1\u201f \u0441\u0435 \u0437\u043d\u0430 \u0434\u0430 \u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u043e\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u045a\u0435 \u0441\u0430\u043e\u0431\u0440\u0430\u045b\u0430\u0458\u0430 \u043a\u0430\u043a\u043e \u0431\u0438 \u0443\u0441\u043f\u043e\u0440\u0438\u043b\u0430 \u043f\u0440\u0435\u043d\u043e\u0441 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430. \u0428\u0438\u0444\u0440\u043e\u0432\u0430\u045a\u0435 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u0430 \u0458\u0435 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u0443\u043a\u0459\u0443\u0447\u0435\u043d\u043e. \u041e\u0432\u043e \u043f\u043e\u043d\u0430\u0448\u0430\u045a\u0435 \u0441\u0435 \u043c\u043e\u0436\u0435 \u0438\u0441\u043a\u0459\u0443\u0447\u0438\u0442\u0438 \u0438\u043b\u0438 \u043f\u0440\u043e\u043c\u0435\u043d\u0438\u0442\u0438 \u0443 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0438\u043c\u0430. ConfigView.section.interface.alerts=\u0423\u0437\u0431\u0443\u043d\u0435 ConfigView.label.popupdownloadadded=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u0443\u0437\u0431\u0443\u043d\u0443 \u043a\u0430\u0434\u0430 \u0441\u0435 \u0434\u043e\u0434\u0430 \u043d\u043e\u0432\u0438 \u043f\u0440\u0438\u0458\u0435\u043c popup.download.added=\u201e%1\u201f \u0458\u0435 \u0434\u043e\u0434\u0430\u0442 \u0443 \u0441\u043f\u0438\u0441\u0430\u043a \u043f\u0440\u0438\u0458\u0435\u043c\u0430. MessageBoxWindow.nomoreprompting=\u041d\u0435 \u043f\u0438\u0442\u0430\u0458 \u043e\u043f\u0435\u0442 TorrentOptionsView.param.max.seeds=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u0443\u043a\u0443\u043f\u0430\u043d \u0431\u0440\u043e\u0458 \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 [0: \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0435 \u0432\u0435\u0437\u0435] TorrentOptionsView.param.alternative.value.enable=\u0414\u0440\u0443\u0433\u043e \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 \u043f\u0440\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443 ConfigView.section.proxy.check.on.start=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0437\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u043a\u0430 (proxy) \u043d\u0430 \u043f\u043e\u0447\u0435\u0442\u043a\u0443 TransferStatsView.legend.pingaverage=\u0421\u0440\u0435\u0434\u045a\u0430 TransferStatsView.legend.ping1=\u041e\u0434\u0440\u0435\u0434\u0438\u0448\u0442\u0435 1 TransferStatsView.legend.ping2=\u041e\u0434\u0440\u0435\u0434\u0438\u0448\u0442\u0435 2 TransferStatsView.legend.ping3=\u041e\u0434\u0440\u0435\u0434\u0438\u0448\u0442\u0435 3 ConfigView.section.interface.enabletray._mac=\u0423\u043a\u0459\u0443\u0447\u0438 \u0441\u043b\u0438\u0447\u0438\u0446\u0443 \u043d\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u043d\u043e\u0458 \u0442\u0440\u0430\u0446\u0438 [\u0442\u0440\u0430\u0436\u0438 \u0440\u0435\u0441\u0442\u0430\u0440\u0442] ConfigView.label.closetotray._mac=\u0417\u0430\u0442\u0432\u0430\u0440\u0430\u045a\u0435 \u0443\u043c\u0430\u045a\u0443\u0458\u0435 \u0443 \u0441\u0442\u0430\u0442\u0443\u0441\u043d\u0443 \u0442\u0440\u0430\u043a\u0443 ConfigView.label.minimizetotray._mac=\u0423\u043c\u0430\u045a\u0438\u0432\u0430\u045a\u0435 \u0443\u043c\u0430\u045a\u0443\u0458\u0435 \u0443 \u0441\u043b\u0438\u0447\u0438\u0446\u0443 \u043d\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u043d\u043e\u0458 \u0442\u0440\u0430\u0446\u0438 OpenTorrentWindow.mb.existingFiles.title=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0432\u0435\u045b \u043f\u043e\u0441\u0442\u043e\u0458\u0435! OpenTorrentWindow.mb.existingFiles.text=\u041d\u0435\u043a\u0435 \u043e\u0434 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0432\u0435\u045b \u043f\u043e\u0441\u0442\u043e\u0458\u0435 \u0443 \u043e\u0434\u0440\u0435\u0434\u0438\u0448\u043d\u043e\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c\u0443 \u043a\u043e\u0433 \u0441\u0442\u0435 \u0437\u0430\u0434\u0430\u043b\u0438:\n\n%1\n\u0410\u043a\u043e \u043d\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u0435, \u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u045b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0438 \u0434\u0430 \u043b\u0438 \u043e\u0432\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0438\u043c\u0430\u0458\u0443 \u043e\u0447\u0435\u043a\u0438\u0432\u0430\u043d \u0441\u0430\u0434\u0440\u0436\u0430\u0458 \u0438 \u043f\u0440\u0435\u043f\u0438\u0441\u0438\u0432\u0430\u045b\u0435 \u0438\u0445 \u0430\u043a\u043e \u0431\u0443\u0434\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e. splash.unloadingTorrents=\u0418\u0441\u0442\u043e\u0432\u0430\u0440 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 splash.unloadingTorrent=\u0418\u0441\u0442\u043e\u0432\u0430\u0440 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 ConfigView.section.file.defaultdir.autorename=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0430 \u043f\u0440\u043e\u043c\u0435\u043d\u0430 \u0438\u043c\u0435\u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0430\u043a\u043e \u043f\u043e\u0434\u0430\u0446\u0438 \u0438\u0437\u0433\u043b\u0435\u0434\u0430\u0458\u0443 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0442\u043e ConfigView.section.file.defaultdir.autorename.tooltip=\u041e\u0432\u043e \u0441\u043f\u0440\u0435\u0447\u0430\u0432\u0430 \u0434\u0430 \u0458\u0435\u0434\u0430\u043d \u0442\u043e\u0440\u0435\u043d\u0442 \u043f\u0440\u0435\u0438\u043d\u0430\u0447\u0438 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0434\u0440\u0443\u0433\u043e\u0433 \u0430\u043a\u043e \u0441\u0443 \u0438\u043c\u0435\u043d\u0430 \u0438\u0441\u0442\u0430 alert.raised.at.close=(\u041f\u043e\u0440\u0443\u043a\u0435 \u043e\u0434 \u043f\u0440\u0435\u0442\u0445\u043e\u0434\u043d\u043e\u0433 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430) Plugin.trackerpeerauth.name=\u0410\u0443\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0458\u0430 \u0443\u0434\u0430\u0459\u0435\u043d\u043e\u0433 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430 Plugin.trackerpeerauth.info=\u041e\u0432\u0430\u0458 \u0434\u043e\u0434\u0430\u0442\u0430\u043a \u0440\u0430\u0434\u0438 \u0441\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0438\u043c\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0430\u0432\u0430 \u0434\u0430 \u043b\u0438 \u0441\u0443 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0438 \u0437\u0430\u0438\u0441\u0442\u0430 \u0447\u043b\u0430\u043d\u043e\u0432\u0438 \u0440\u043e\u0458\u0430 Peers.column.maxupspeed=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 Peers.column.maxdownspeed=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 MyTorrents.items.DownSpeedLimit.disabled=\u041d\u0435\u043c\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 Peers.column.lan=\u041b\u0410\u041d upnp.selectedaddresses=\u0410\u0434\u0440\u0435\u0441\u0435 (\u201e;\u201f \u0437\u0430 \u043e\u0434\u0432\u0430\u0458\u0430\u045a\u0435, \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u201e-\u201f=\u0437\u0430\u0431\u0440\u0430\u043d\u0430, \u201e+\u201f =\u0434\u043e\u0437\u043d\u043e\u043b\u0430) [\u043f\u0440\u0430\u0437\u043d\u043e: \u0431\u0438\u043b\u043e \u043a\u043e\u0458\u0430] upnp.alert.multipledevice.warning=\u041f\u0440\u043e\u043d\u0430\u0452\u0435\u043d\u043e \u0458\u0435 \u043d\u0435\u043a\u043e\u043b\u0438\u043a\u043e \u0423\u041f\u043d\u041f \u0443\u0440\u0435\u0452\u0430\u0458\u0430 - \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u0434\u0430 \u043b\u0438 \u0458\u0435 \u0441\u0432\u0438\u043c\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e \u043f\u0440\u0435\u0441\u043b\u0438\u043a\u0430\u0432\u0430\u045a\u0435 \u043f\u043e\u0440\u0442\u043e\u0432\u0430 (\u043f\u043e\u0433\u043b\u0435\u0434\u0430\u0458\u0442\u0435 \u0434\u043d\u0435\u0432\u043d\u0438\u043a \u0438 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0437\u0430 \u0423\u041f\u043d\u041f) UpdateMonitor.messagebox.restart.title=\u0414\u043e\u0433\u0440\u0430\u0434\u045a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 UpdateMonitor.messagebox.restart.text=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u0458\u0435 \u0443\u043f\u0440\u0430\u0432\u043e \u0437\u0430\u0432\u0440\u0448\u0438\u043e \u0441\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u043e\u043c \u0432\u0430\u0436\u043d\u0435 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0435 \u0438 \u043c\u043e\u0440\u0430 \u0434\u0430 \u0441\u0435 \u043f\u043e\u043d\u043e\u0432\u043e \u043f\u043e\u043a\u0440\u0435\u043d\u0435 \u043a\u0430\u043a\u043e \u0431\u0438 \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0430 \u0431\u0438\u043b\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u0430. PiecesView.BlockView.Have=\u0418\u043c\u0430 PiecesView.BlockView.NoHave=\u041d\u0435\u043c\u0430 PiecesView.BlockView.Header=\u043a\u043e\u043b\u043e\u043d\u0430: %1, \u0440\u0435\u0434\u043e\u0432\u0430: %2, \u0434\u0435\u043b\u043e\u0432\u0430: %3 ConfigView.section.update.autodownload=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043f\u0440\u0438\u0458\u0435\u043c \u0434\u043e\u0433\u0440\u0430\u0434\u045a\u0438 \u0438 \u0443\u043f\u0438\u0442 \u043a\u0430\u0434\u0430 \u0458\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0430\u045a\u0435 \u0441\u043f\u0440\u0435\u043c\u043d\u043e Peers.column.peer_id=\u0418\u0414 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 Peers.column.peer_id.info=\u041e\u0437\u043d\u0430\u043a\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u0443 \u0447\u0438\u0442\u0459\u0438\u0432\u043e\u043c \u043e\u0431\u043b\u0438\u043a\u0443 Peers.column.peer_byte_id=\u0418\u0414 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 Peers.column.peer_byte_id.info=\u041e\u0437\u043d\u0430\u043a\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u043a\u0430\u043e \u043d\u0438\u0437 \u0431\u0430\u0458\u0442\u043e\u0432\u0430 Peers.column.handshake_reserved=\u0411\u0430\u0458\u0442\u043e\u0432\u0438 \u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0441\u0430\u043d\u0438 \u0437\u0430 \u0440\u0430\u043d\u0434\u0435\u0432\u0443 Peers.column.handshake_reserved.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0458\u0435 \u043a\u043e\u0458\u0438 \u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0441\u0430\u043d\u0438 \u0431\u0438\u0442\u043e\u0432\u0438 \u0441\u0443 \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u0438 \u0443 \u0411\u0422 \u0440\u0430\u043d\u0434\u0435\u0432\u0443\u0443 Peers.column.client_identification=\u0418\u0434\u0435\u043d\u0442\u0438\u0432\u0438\u043a\u0430\u0446\u0438\u0458\u0430 \u043a\u043b\u0438\u0458\u0435\u043d\u0442\u0430 Peers.column.client_identification.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0458\u0435 \u0438\u043c\u0435 \u043a\u043b\u0438\u0458\u0435\u043d\u0442\u0430 \u043a\u043e\u0433 \u0458\u0435 \u0434\u043e\u0431\u0438\u043e \u0410\u0437\u0443\u0440\u0435\u0443\u0441 - \u043a\u043e\u0440\u0438\u0441\u043d\u043e \u0437\u0430 \u0442\u0440\u0430\u0436\u0435\u045a\u0435 \u0433\u0440\u0435\u0448\u0430\u043a\u0430 dht.warn.user=\u0423\u043f\u043e\u0437\u043e\u0440\u0438 \u0443 \u0441\u043b\u0443\u0447\u0430\u0458\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441\u0430 \u041d\u0410\u0422-\u043e\u043c \u0438 \u043f\u0440\u0435\u0441\u043b\u0438\u043a\u0430\u0432\u0430\u045a\u0435\u043c \u043f\u043e\u0440\u0442\u043e\u0432\u0430 ConfigView.label.openbar.incomplete=\u0422\u0440\u0430\u043a\u0435 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c: \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043e\u0442\u0432\u043e\u0440\u0438 \u043f\u0440\u0438\u0458\u0435\u043c\u0435 ConfigView.label.openbar.complete=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043e\u0442\u0432\u043e\u0440\u0438 \u0437\u0430\u043c\u0435\u0442\u043a\u0435 ConfigView.label.transferbar.remember_location=\u0417\u0430\u043f\u0430\u043c\u0442\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u045a\u0435 \u043c\u0435\u0441\u0442\u043e \u0442\u0440\u0430\u043a\u0435 \u0437\u0430 \u043f\u0440\u0435\u043d\u043e\u0441\u0435 ConfigView.section.transfer.autospeed.forcemin=%1 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u043f\u0440\u0438\u043c\u043e\u0440\u0430\u043d\u0430 \u0437\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u0443 \u0432\u0435\u0437\u0443 MainWindow.menu.tools.speedtest=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u0431\u0440\u0437\u0438\u043d\u0435... speedtest.wizard.title=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u0431\u0440\u0437\u0438\u043d\u0435 speedtest.wizard.run=\u041f\u043e\u043a\u0440\u0435\u043d\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 \u0431\u0440\u0437\u0438\u043d\u0435 speedtest.wizard.test.mode.updown=\u0441\u043b\u0430\u045a\u0435 \u0438 \u043f\u0440\u0438\u0458\u0435\u043c speedtest.wizard.test.mode.up=\u0441\u043b\u0430\u045a\u0435 speedtest.wizard.test.mode.down=\u043f\u0440\u0438\u0458\u0435\u043c SpeedTestWizard.test.panel.currinfo=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u043f\u0440\u043e\u043f\u0443\u0441\u043d\u043e\u0433 \u043e\u043f\u0441\u0435\u0433\u0430. SpeedTestWizard.test.panel.label=\u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0430 \u0431\u0440\u0437\u0438\u043d\u0435: SpeedTestWizard.test.panel.already.running=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u0432\u0435\u045b \u0440\u0430\u0434\u0438! SpeedTestWizard.test.panel.not.accepted=\u0417\u0430\u0445\u0442\u0435\u0432 \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 \u0458\u0435 \u043e\u0434\u0431\u0438\u0458\u0435\u043d: SpeedTestWizard.test.panel.abort=\u041e\u0442\u043a\u0430\u0436\u0438 SpeedTestWizard.test.panel.abort.countdown=\u043e\u0442\u043a\u0430\u0436\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 \u0437\u0430: SpeedTestWizard.test.panel.test.countdown=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u0437\u0430\u0432\u0440\u0448\u0430\u0432\u0430 \u0437\u0430: SpeedTestWizard.test.panel.testfailed=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u0430 SpeedTestWizard.test.panel.aborted=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u0458\u0435 \u0440\u0443\u0447\u043d\u043e \u043e\u0442\u043a\u0430\u0437\u0430\u043d\u0430. SpeedTestWizard.test.panel.enc.label=\u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 \u0441\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u045a\u0435\u043c: SpeedTestWizard.test.panel.standard=\u0441\u0442\u0430\u0434\u0430\u0440\u0434\u043d\u0438 SpeedTestWizard.test.panel.encrypted=\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d SpeedTestWizard.set.upload.button.apply=\u041f\u0440\u0438\u043c\u0435\u043d\u0438 SpeedTestWizard.set.upload.result=\u0420\u0435\u0437\u0443\u043b\u0442\u0430\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u045a\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0435 SpeedTestWizard.set.upload.bytes.per.sec=kiB/s SpeedTestWizard.set.upload.bits.per.sec=b/s SpeedTestWizard.finish.panel.title=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u0431\u0440\u0437\u0438\u043d\u0435 \u0458\u0435 \u0433\u043e\u0442\u043e\u0432\u0430! SpeedTestWizard.finish.panel.click.close=\u0417\u0430\u0432\u0440\u0448\u0438\u043b\u0438 \u0441\u0442\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0443 \u0431\u0440\u0437\u0438\u043d\u0435. \u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u201e\u0417\u0430\u0442\u0432\u043e\u0440\u0438\u201f \u0434\u0430 \u0437\u0430\u0442\u0432\u043e\u0440\u0438\u0442\u0435. SpeedTestWizard.finish.panel.max.upload=\u041d\u0430\u0458\u0431\u0440\u0436\u0435 \u0441\u043b\u0430\u045a\u0435 : SpeedTestWizard.finish.panel.max.seeding.upload=\u041d\u0430\u0458\u0431\u0440\u0436\u0435 \u0441\u043b\u0430\u045a\u0435 \u043f\u0440\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443 : SpeedTestWizard.finish.panel.max.download=\u041d\u0430\u0458\u0431\u0440\u0436\u0438 \u043f\u0440\u0438\u0458\u0435\u043c : SpeedTestWizard.finish.panel.enabled=\u0443\u043a\u0459\u0443\u0447\u0435\u043d\u043e SpeedTestWizard.finish.panel.disabled=\u0438\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u043e SpeedTestWizard.abort.message.scheduled.in=\u043f\u0440\u043e\u0432\u0435\u0440\u0430 \u0458\u0435 \u0437\u0430\u043a\u0430\u0437\u0430\u043d\u0430 \u0437\u0430 ... %1 s SpeedTestWizard.abort.message.unsupported.type=\u041e\u0432\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0430 \u043d\u0438\u0458\u0435 \u043f\u043e\u0434\u0440\u0436\u0430\u043d\u0430! SpeedTestWizard.abort.message.manual.abort=\u0420\u0443\u0447\u043d\u043e \u043e\u0442\u043a\u0430\u0437\u0430\u043d\u043e SpeedTestWizard.abort.message.scheduling.failed=\u0417\u0430\u043a\u0430\u0437\u0438\u0432\u0430\u045a\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0435 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e SpeedTestWizard.abort.message.download.added=\u041f\u0440\u0438\u043b\u0438\u043a\u043e\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0435 \u0434\u043e\u0434\u0430\u0442 \u0458\u0435 \u043f\u0440\u0435\u043d\u043e\u0441 \u0437\u0430 %1 SpeedTestWizard.abort.message.entered.error=\u041f\u0440\u043e\u0431\u043d\u0438 \u043f\u0440\u0435\u043d\u043e\u0441 \u0458\u0435 \u0438\u043c\u0430\u043e \u0433\u0440\u0435\u0448\u043a\u0443: %1 SpeedTestWizard.abort.message.entered.queued=\u041f\u0440\u043e\u0431\u043d\u0438 \u043f\u0440\u0435\u043d\u043e\u0441 \u0458\u0435 \u0443\u0448\u0430\u043e \u0443 \u0441\u0442\u0430\u045a\u0435: \u0437\u0430\u043a\u0430\u0437\u0430\u043d/\u0437\u0430\u0443\u0441\u0442\u0430\u0432\u0459\u0435\u043d SpeedTestWizard.abort.message.interrupted=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 TorrentSpeedTestMonitorThread \u0458\u0435 \u043f\u0440\u0435\u043a\u0438\u043d\u0443\u0442\u0430 \u043f\u0440\u0435 \u043d\u0435\u0433\u043e \u0448\u0442\u043e \u0458\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0430 \u0437\u0430\u0432\u0440\u0448\u0435\u043d\u0430 SpeedTestWizard.abort.message.execution.failed=\u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u0430 SpeedTestWizard.abort.message.failed.peers=\u041d\u0438\u0458\u0435 \u043c\u043e\u0433\u0443\u045b\u0435 \u043f\u043e\u0432\u0435\u0437\u0430\u0442\u0438 \u0441\u0435 \u043d\u0438 \u043d\u0430 \u0458\u0435\u0434\u0430\u043d \u0440\u0430\u0447\u0443\u043d\u0430\u0440 SpeedTestWizard.abort.message.insufficient.slots=\u041d\u0438\u0458\u0435 \u043c\u043e\u0433\u0443\u045b\u0435 \u043f\u043e\u0441\u043b\u0430\u0442\u0438 \u043d\u0438 \u043d\u0430 \u0458\u0435\u0434\u0430\u043d \u0443\u0434\u0430\u0459\u0435\u043d \u0440\u0430\u0447\u0443\u043d\u0430\u0440 - \u043c\u043e\u0436\u0434\u0430 \u043d\u0435\u043c\u0430 \u0434\u043e\u0432\u043e\u0459\u043d\u043e \u043f\u0440\u043e\u0440\u0435\u0437\u0430 \u0437\u0430 \u0441\u043b\u0430\u045a\u0435? SpeedTestWizard.abort.message.not.unchoked=\u041d\u0438\u0458\u0435 \u043c\u043e\u0433\u0443\u045b\u0435 \u043f\u0440\u0438\u043c\u0438\u0442\u0438 \u043d\u0438 \u0441\u0430 \u0458\u0435\u0434\u043d\u043e\u0433 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u0443\u0441\u043b\u0435\u0434 \u0443\u0434\u0430\u0459\u0435\u043d\u043e\u0433 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0430 \u0431\u0440\u0437\u0438\u043d\u0435 SpeedTestWizard.stage.message.requesting=\u0437\u0430\u0445\u0442\u0435\u0432 \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0437... SpeedTestWizard.stage.message.preparing=\u043f\u0440\u0438\u043f\u0440\u0435\u043c\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0435... SpeedTestWizard.stage.message.starting=\u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0435... SpeedTestWizard.stage.message.connect.stats=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0435: \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430=%1, \u043f\u0440\u0438\u0458\u0435\u043c_\u0443_\u0440\u0435\u0434\u0443=%2, \u0441\u043b\u0430\u045a\u0435_\u0443_\u0440\u0435\u0434\u0443=%3 window.uiswitcher.title=\u0418\u0437\u0431\u043e\u0440 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e\u0433 \u0441\u0443\u0447\u0435\u0459\u0430 window.uiswitcher.text=\u041c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0438\u0441\u043f\u043e\u0434 \u0438\u0437\u0430\u0431\u0435\u0440\u0435\u0442\u0435 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e \u0441\u0443\u0447\u0435\u0459\u0435 \u043a\u043e\u0458\u0435 \u043d\u0430\u0458\u0431\u043e\u0459\u0435 \u043e\u0434\u0433\u043e\u0432\u0430\u0440\u0430 \u0412\u0430\u0448\u0438\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0430\u043c\u0430. window.uiswitcher.NewUI.title=\u0412\u0458\u0443\u0437 (Vuze ) window.uiswitcher.NewUI.text=* \u041f\u0440\u0435\u043f\u043e\u0440\u0443\u0447\u0443\u0458\u0435 \u0441\u0435 \u0437\u0430 \u043f\u043e\u0447\u0435\u0442\u043d\u0438\u043a\u0435 \u0438 \u043d\u043e\u0432\u0435 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u043a\u0435.\n\n* \u0408\u0435\u0434\u043d\u043e\u0441\u0442\u0430\u0432\u043d\u043e, \u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e \u0441\u0443\u0447\u0435\u0459\u0435\n\n* \u041d\u0435\u043e\u043f\u0445\u043e\u0434\u043d\u043e \u0441\u0443\u0447\u0435\u0459\u0435 \u0437\u0430 \u043e\u0431\u0458\u0430\u0432\u0459\u0438\u0432\u0430\u045a\u0435 \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0438 \u0412\u0458\u0443\u0437 (Vuze ) window.uiswitcher.ClassicUI.title=\u041a\u043b\u0430\u0441\u0438\u0447\u043d\u043e \u0441\u0443\u0447\u0435\u0459\u0435 window.uiswitcher.ClassicUI.text=* \u0417\u0430\u0434\u0440\u0436\u0430\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043d\u043e\u0441\u0442 \u043a\u043b\u0438\u0458\u0435\u043d\u0430\u0442\u0430 \u0443 \u0438\u0437\u0434\u0430\u045a\u0443 2.x\n\n* \u0412\u0458\u0443\u0437\u043e\u0432 \u0441\u043b\u043e\u0458 \u0441\u0430 \u0441\u0430\u0434\u0440\u0436\u0430\u0458\u0435\u043c \u043d\u0435\u045b\u0435 \u0431\u0438\u0442\u0438 \u0443\u0447\u0438\u0442\u0430\u043d window.uiswitcher.bottom.text=\u0412\u0430\u0448 \u0438\u0437\u0431\u043e\u0440 \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u043e \u0434\u0430 \u043f\u0440\u043e\u043c\u0435\u043d\u0438\u0442\u0435 \u0438\u0437\u0431\u043e\u0440\u043e\u043c \u0434\u0443\u0433\u043c\u0435\u0442\u0430 \u201e\u0418\u0437\u0431\u043e\u0440 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e\u0433 \u0441\u0443\u0447\u0435\u0459\u0430\u201f iconBar.switch.tooltip=\u0418\u0437\u0431\u043e\u0440 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e\u0433 \u0441\u0443\u0447\u0435\u0459\u0430 VivaldiView.notAvailable=\u0412\u0438\u0432\u0430\u043b\u0434\u0438 \u043d\u0438\u0458\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430\u043d restart.error=\u041f\u043e\u043d\u043e\u0432\u043e \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u043d\u0438\u0458\u0435 \u0443\u0441\u043f\u0435\u043b\u043e:\n%1\n\u041f\u043e\u0433\u043b\u0435\u0434\u0430\u0458\u0442\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435 \u043f\u0440\u0438 \u043f\u043e\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0443. restart.error.url=http://www.azureuswiki.com/index.php/AdvancedNetworkSettings restart.error.oom=\u041d\u0435\u043c\u0430 \u043c\u0435\u043c\u043e\u0440\u0438\u0458\u0435 restart.error.fnf=\u201e%1\u201f \u043d\u0438\u0458\u0435 \u043f\u0440\u043e\u043d\u0430\u0452\u0435\u043d \u0443 \u201e%2\u201f restart.error.pnf=\u0421\u0442\u0430\u0437\u0430 \u201e%1\u201f \u043d\u0438\u0458\u0435 \u043f\u0440\u043e\u043d\u0430\u0452\u0435\u043d\u0430 restart.error.bad=\u041d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u0430\u043d \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0437\u0430 \u201e%1\u201f restart.error.denied=\u041f\u0440\u0438\u0441\u0442\u0443\u043f \u043d\u0438\u0458\u0435 \u0434\u043e\u0437\u0432\u043e\u0459\u0435\u043d \u043f\u0440\u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0443 \u201e%1\u201f. \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u0434\u0430 \u043b\u0438 \u0441\u043c\u0435\u0442\u0435 \u0434\u0430 \u043f\u043e\u043a\u0440\u0435\u045b\u0435\u0442\u0435 \u043e\u0432\u0430\u0458 \u043f\u0440\u043e\u0433\u0440\u0430\u043c. TableColumn.header.date_completed=\u0413\u043e\u0442\u043e\u0432\u043e \u0443 TableColumn.menu.date_added.reset=\u0414\u0430\u0442\u0443\u043c \u0440\u0435\u0441\u0435\u0442\u0430 ConfigView.section.ipfilter.discardbanning=\u0411\u043b\u043e\u043a\u0438\u0440\u0430\u0458 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0435 \u0437\u0430 \u043a\u043e\u0458\u0435 \u043e\u0434\u043d\u043e\u0441 \u043e\u0434\u0431\u0430\u0447\u0435\u043d\u0438\u0445 \u0438 \u0434\u043e\u0431\u0440\u0438\u0445 \u043f\u0430\u043a\u0435\u0442\u0430 \u043f\u0440\u0435\u043c\u0430\u0448\u0443\u0458\u0435: [0: \u0438\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u043e] ConfigView.section.ipfilter.discardminkb=\u041d\u0430\u0458\u043c\u0430\u045a\u0435 %1 \u043e\u0434\u0431\u0430\u0447\u0435\u043d\u0438\u0445 \u043f\u0440\u0435 \u043d\u0435\u0433\u043e \u0448\u0442\u043e \u0441\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0438 \u043e\u0434\u043d\u043e\u0441 ConfigView.interface.start.advanced=\u041f\u043e\u043a\u0440\u0435\u043d\u0438 \u0441\u0430 \u043d\u0430\u043f\u0440\u0435\u0434\u043d\u0438\u043c \u0441\u0443\u0447\u0435\u0459\u0435\u043c (AZ 2.x) MyTorrents.column.ColumnQuality=\u041a\u0432\u0430\u043b\u0438\u0442\u0435\u0442 MyTorrents.column.ColumnSpeed=\u0411\u0440\u0437\u0438\u043d\u0430 MyTorrents.column.ColumnProgressETA.2ndLine=\u041f\u0412\u0414: %1 MyTorrents.column.ColumnProgressETA.StreamReady=\u0422\u043e\u043a \u0458\u0435 \u0441\u043f\u0440\u0435\u043c\u0430\u043d MyTorrents.column.ColumnProgressETA.PlayableIn=\u041f\u0443\u0448\u0442\u0430\u045a\u0435 \u0443 %1 TableColumn.header.Quality=\u041a\u0432\u0430\u043b\u0438\u0442\u0435\u0442 TableColumn.header.Speed=\u0411\u0440\u0437\u0438\u043d\u0430 TableColumn.header.RateIt=\u041e\u0434\u043d\u043e\u0441 TableColumn.header.Rating=\u041e\u0446\u0435\u043d\u0430 TableColumn.header.SpeedGraphic=\u0411\u0440\u0437\u0438\u043d\u0430 TableColumn.header.AzProduct=\u041e\u0434 TableColumn.header.MediaThumb=\u041c\u0435\u0434\u0438\u0458\u0443\u043c TableColumn.header.ProgressETA=\u041d\u0430\u043f\u0440\u0435\u0434\u0430\u043a #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=\u0412\u0440\u0441\u0442\u0430: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} TableColumn.header.DateCompleted={MyTorrentsView.date_completed} v3.MainWindow.tab.home=\u0413\u043b\u0430\u0432\u043d\u0438 \u043f\u0430\u043d\u0435\u043b v3.MainWindow.tab.browse=\u041d\u0430 \u0412\u0458\u0443\u0437\u0443 (Vuze ) v3.MainWindow.tab.library=\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 v3.MainWindow.tab.publish=\u041e\u0431\u0458\u0430\u0432\u0438 v3.MainWindow.tab.advanced=\u041d\u0430\u043f\u0440\u0435\u0434\u043d\u043e v3.MainWindow.menu.home=&\u0413\u043b\u0430\u0432\u043d\u0438 \u043f\u0430\u043d\u0435\u043b v3.MainWindow.menu.browse=\u041d\u0430 \u0412\u0458\u0443\u0437\u0443 (Vuze ) v3.MainWindow.menu.library=&\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 v3.MainWindow.menu.publish=&\u041e\u0431\u0458\u0430\u0432\u0438 v3.MainWindow.menu.advanced=&\u041d\u0430\u043f\u0440\u0435\u0434\u043d\u043e v3.MainWindow.menu.view.searchbar=\u0422\u0440\u0430\u043a\u0430 \u0437\u0430 \u043f\u0440\u0435\u0442\u0440\u0430\u0433\u0443 v3.MainWindow.menu.view.tabbar=\u0422\u0440\u0430\u043a\u0430 \u0441\u0430 \u0458\u0435\u0437\u0438\u0447\u0446\u0438\u043c\u0430 v3.MainWindow.currentDL=\u0422\u0440\u0435\u043d\u0443\u0442\u043d\u0438 \u043f\u0440\u0438\u0458\u0435\u043c v3.MainWindow.button.stream=\u0422\u043e\u043a v3.MainWindow.button.stop=\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0438 v3.MainWindow.button.start=\u041f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 v3.MainWindow.button.pause=\u041f\u0430\u0443\u0437\u0430 v3.MainWindow.button.resume=\u041d\u0430\u0441\u0442\u0430\u0432\u0438 v3.MainWindow.button.delete=\u0423\u043a\u043b\u043e\u043d\u0438 v3.MainWindow.button.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 v3.MainWindow.button.viewdetails=\u0414\u0435\u0442\u0430\u0459\u0438 v3.MainWindow.button.play=\u041f\u0443\u0441\u0442\u0438 v3.MainWindow.button.cancel=\u041e\u0442\u043a\u0430\u0436\u0438 v3.MainWindow.view.wait=\u041f\u043e\u0433\u043b\u0435\u0434 \u0441\u0435 \u0443\u0447\u0438\u0442\u0430\u0432\u0430, \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0441\u0430\u0447\u0435\u043a\u0430\u0442\u0435... v3.MainWindow.xofx=%1 \u043e\u0434 %2 v3.MainWindow.Loading=\u0423\u0447\u0438\u0442\u0430\u0432\u0430\u045a\u0435, \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0441\u0430\u0447\u0435\u043a\u0430\u0442\u0435... v3.filter-bar=\u0424\u0438\u043b\u0442\u0435\u0440 \u043d\u0430\u0441\u043b\u043e\u0432\u0430: v3.MainWindow.search.defaultText=\u041f\u0440\u0435\u0442\u0440\u0430\u0436\u0438 \u0412\u0458\u0443\u0437 v3.mb.delPublished.title=\u041f\u0440\u0435\u043a\u0438\u043d\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 \u0441\u0430\u0434\u0440\u0436\u0430\u0458\u0430 v3.mb.delPublished.text=\u0423\u041f\u041e\u0417\u041e\u0420\u0415\u040a\u0415: \u041e\u0432\u043e \u0434\u0435\u0458\u0441\u0442\u0432\u043e \u041d\u0415\u040b\u0415 \u0443\u043a\u043b\u043e\u043d\u0438\u0442\u0438 \u043e\u0431\u0458\u0430\u0432\u0459\u0435\u043d \u0441\u0430\u0434\u0440\u0436\u0430\u0458 \u201e%1\u201f \u0441\u0430 %3 .\n\n\u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u201e\u0423\u043a\u043b\u043e\u043d\u0438\u201f \u0441\u0430\u043c\u043e \u0430\u043a\u043e \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u0432\u0430\u0448 \u0441\u0430\u0434\u0440\u0436\u0430\u0458 \u043e\u0441\u0442\u0430\u043d\u0435 \u043e\u0431\u0458\u0430\u0432\u0459\u0435\u043d \u0438 \u0441\u043f\u0440\u0435\u043c\u0430\u043d \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c, \u0430\u043b\u0438 \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u043e\u0441\u043b\u043e\u0431\u043e\u0434\u0438\u0442\u0435 \u0441\u0432\u043e\u0458 \u043f\u0440\u043e\u043f\u0443\u0441\u043d\u0438 \u043e\u043f\u0441\u0435\u0433. \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435 \u0434\u0430 \u0458\u0435 \u043f\u0440\u0435\u043d\u043e\u0441 \u0433\u043e\u0442\u043e\u0432 \u043f\u0440\u0435 \u043d\u0435\u0433\u043e \u0448\u0442\u043e \u0442\u043e \u0443\u0440\u0430\u0434\u0438\u0442\u0435 (\u043a\u0430\u043a\u043e?).\n\n\u041f\u0440\u0438\u0442\u0438\u0441\u043d\u0438\u0442\u0435 \u201e\u041e\u0442\u043a\u0430\u0436\u0438\u201f \u0430\u043a\u043e \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u043f\u043e\u0442\u043f\u0443\u043d\u043e \u0443\u043a\u043b\u043e\u043d\u0438\u0442\u0435 \u043e\u0431\u0458\u0430\u0432\u0459\u0435\u043d \u0441\u0430\u0434\u0440\u0436\u0430\u0458 \u0441\u0430 %3, \u0438 \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u0434\u0443\u0433\u043c\u0435 (X) \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0443 \u201e\u041e\u0431\u0458\u0430\u0432\u0459\u0435\u043d \u0441\u0430\u0434\u0440\u0436\u0430\u0458\u201f \u043d\u0430 \u0458\u0435\u0437\u0438\u0447\u043a\u0443 \u0441\u0430 \u043e\u0431\u0458\u0430\u0432\u0459\u0435\u043d\u0438\u043c \u0441\u0430\u0434\u0440\u0436\u0430\u0458\u0438\u043c\u0430.\n\n\u0412\u0438\u0448\u0435 \u043f\u043e\u043c\u043e\u045b\u0438.\n\n v3.mb.delPublished.delete=&\u0423\u043a\u043b\u043e\u043d\u0438 v3.mb.delPublished.cancel=\u041e\u0442\u043a\u0430&\u0436\u0438 v3.mb.openFile.button.play=\u041f\u0443\u0441\u0442\u0438 v3.mb.PlayFileNotFound.title=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043d\u0438\u0458\u0435 \u043d\u0430\u0452\u0435\u043d\u0430 v3.mb.PlayFileNotFound.text=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u0437\u0430 \u201e%1\u201f \u0441\u0443 \u0438\u043b\u0438 \u0443\u043a\u043b\u043e\u045a\u0435\u043d\u0435 \u0438\u043b\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0458\u0443. v3.mb.PlayFileNotFound.button.remove=\u0423\u043a\u043b\u043e\u043d\u0438 \u0438\u0437 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 v3.mb.PlayFileNotFound.button.redownload=\u041f\u043e\u043d\u043e\u0432\u043d\u0438 \u043f\u0440\u0438\u0458\u0435\u043c v3.mb.PlayFileNotFound.button.find=\u0420\u0443\u0447\u043d\u043e \u0442\u0440\u0430\u0436\u0435\u045a\u0435... v3.mb.deletePurchased.title=\u0423\u043a\u043b\u043e\u043d\u0438 \u043a\u0443\u043f\u0459\u0435\u043d\u0438 \u0441\u0430\u0434\u0440\u0436\u0430\u0458 v3.mb.deletePurchased.text=\u0414\u0430 \u043b\u0438 \u0441\u0438\u0433\u0443\u0440\u043d\u043e \u0452\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u0443\u043a\u043b\u043e\u043d\u0438\u0442\u0435 \u0441\u0430\u0434\u0440\u0436\u0430\u0458 \u201e%1\u201f?\n\n\u041e\u0432\u0430\u0458 \u0441\u0442\u0435 \u0441\u0430\u0434\u0440\u0436\u0430\u0458 \u0438\u043b\u0438 \u043a\u0443\u043f\u0438\u043b\u0438 \u0438\u043b\u0438 \u0458\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u0430 \u043f\u0440\u0438\u0458\u0430\u0432\u0430 \u0434\u0430 \u0431\u0438\u0441\u0442\u0435 \u0433\u0430 \u043f\u0440\u0435\u0443\u0437\u0435\u043b\u0438. v3.mb.deletePurchased.button.delete=&\u0423\u043a\u043b\u043e\u043d\u0438 v3.mb.deletePurchased.button.cancel=\u041e\u0442\u043a\u0430&\u0436\u0438 v3.topbar.menu.show.logo=\u041b\u043e\u0433\u043e\u0442\u0438\u043f v3.topbar.menu.show.plugin=\u041e\u0431\u043b\u0430\u0441\u0442 \u0441\u0430 \u0434\u043e\u0434\u0430\u0446\u0438\u043c\u0430 v3.topbar.menu.show.search=\u041f\u0440\u0435\u0442\u0440\u0430\u0433\u0430 v3.topbar.menu.show.frog=\u041f\u043b\u0430\u0432\u0430 \u0436\u0430\u0431\u0430 splash.initializeCore=\u041f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u0458\u0435\u0437\u0433\u0440\u0430 splash.initializeUIElements=\u041f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u0434\u0435\u043b\u043e\u0432\u0430 \u043a\u043e\u0440. \u0441\u0443\u0447\u0435\u0459\u0430 # ConfigView.section.ipfilter.peerblocking.group=\u0411\u043b\u043e\u043a\u0438\u0440\u0430\u045a\u0435 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 ConfigView.section.ipfilter.autoload.group=\u0410\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u043e \u0443\u0447\u0438\u0442\u0430\u0432\u0430\u045a\u0435 ConfigView.section.ipfilter.autoload.file=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0441\u0430 \u0418\u041f \u0444\u0438\u043b\u0442\u0440\u0438\u043c\u0430 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c ConfigView.section.ipfilter.autoload.info=\u041f\u043e\u0434\u0440\u0436\u0430\u0432\u0430 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 DAT (eMule), P2P (PeerGuardian, splist), \u0438 P2B v1,2,3 (PeerGuardian 2). \u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u0443\u0434\u0435 \u043b\u043e\u043a\u0430\u043b\u043d\u0430 \u0438\u043b\u0438 \u0434\u0430\u0442\u0430 \u043a\u0430\u043e URL, \u043a\u043e\u043c\u043f\u0440\u0438\u043c\u043e\u0432\u0430\u043d\u0430 (zip, gzip) \u0438\u043b\u0438 \u043d\u0435\u043a\u043e\u043c\u043f\u0440\u0438\u043c\u043e\u0432\u0430\u043d\u0430. URL\u043e\u0432\u0438 \u045b\u0435 \u0431\u0438\u0442\u0438 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043f\u0440\u0435\u0443\u0437\u0438\u043c\u0430\u043d\u0438 \u043d\u0430 \u0441\u0432\u0430\u043a\u0438\u0445 7 \u0434\u0430\u043d\u0430, \u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0435 \u045b\u0435 \u0434\u0430 \u0431\u0443\u0434\u0443 \u043f\u0440\u0435\u0443\u0437\u0438\u043c\u0430\u043d\u0435 \u043e\u0434\u043c\u0430\u0445 \u043f\u043e \u0438\u0437\u043c\u0435\u043d\u0438. ConfigView.section.ipfilter.autoload.loadnow=\u0423\u0447\u0438\u0442\u0430\u0458 \u043e\u0434\u043c\u0430\u0445 splash.loadIpFilters=\u0423\u0447\u0438\u0442\u0430\u0432\u0430\u045a\u0435 \u0418\u041f \u0444\u0438\u043b\u0442\u0435\u0440\u0430... SpeedTestWizard.set.upload.title=\u041f\u043e\u0441\u0442\u0430\u0432\u043a\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u0438 \u0441\u043b\u0430\u045a\u0430 SpeedTestWizard.set.download.label=\u0411\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430: SpeedTestWizard.set.upload.label=\u0411\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430: SpeedTestWizard.name.conf.level.absolute=\u0410\u043f\u0441\u043e\u043b\u0443\u0442\u0430\u043d SpeedTestWizard.name.conf.level.high=\u0412\u0438\u0441\u043e\u043a SpeedTestWizard.name.conf.level.med=\u0421\u0440\u0435\u0434\u045a\u0438 SpeedTestWizard.name.conf.level.low=\u041d\u0438\u0437\u0430\u043a SpeedTestWizard.name.conf.level.none=\u041d\u0438\u0458\u0435\u0434\u0430\u043d ConfigView.section.transfer.select=\u0410\u0443\u0442\u043e\u043c. \u0431\u0440\u0437\u0438\u043d\u0430 ConfigView.section.transfer.select.v2=\u0410\u0443\u0442\u043e\u043c. \u0431\u0440\u0437\u0438\u043d\u0430 (\u0431\u0435\u0442\u0430) mb.azmustclose.title=\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0443 mb.azmustclose.text=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u0458\u0435 \u043c\u043e\u0440\u0430\u043e \u0434\u0430 \u0431\u0443\u0434\u0435 \u0437\u0430\u0442\u0432\u043e\u0440\u0435\u043d \u0443\u0441\u043b\u0435\u0434 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043f\u0440\u0438 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0443, \u043a\u043e\u0458\u0438 \u0458\u0435 \u043d\u0430\u0458\u0432\u0435\u0440\u043e\u0432\u0430\u0442\u043d\u0438\u0458\u0435 \u0443\u0437\u0440\u043e\u043a\u043e\u0432\u0430\u043e \u0434\u0430 \u0441\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u043f\u043e\u043a\u0440\u0435\u043d\u0435 \u0441\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0441\u043a\u0438\u043c \u043f\u0440\u0430\u0432\u0438\u043c\u0430 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430.\n\n\u041f\u043e\u0448\u0442\u043e \u0441\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u0437\u0430\u0442\u0432\u043e\u0440\u0438, \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u0433\u0430 \u0440\u0443\u0447\u043d\u043e \u043f\u043e\u043d\u043e\u0432\u043e \u043f\u043e\u043a\u0440\u0435\u043d\u0435\u0442\u0435. network.ipv6.prefer.addresses=\u0411\u0438\u0440\u0430\u0458 \u0430\u0434\u0440\u0435\u0441\u0443 \u0443 IPv6 \u0444\u043e\u0440\u043c\u0430\u0442\u0443 \u043a\u0430\u0434\u0430 \u0441\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0435 \u0438 IPv6 \u0438 IPv4 DHTView.title.full_v6=\u0414\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0430 \u0431\u0430\u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 IPv6 ConfigView.pluginlist.loadSelected=\u0423\u0447\u0438\u0442\u0430\u0458 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0435 SpeedView.stats.asn=\u041c\u0440\u0435\u0436\u0430: SpeedView.stats.estupcap=\u0411\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430: SpeedView.stats.estdowncap=\u0411\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430: SpeedView.stats.unknown=\u041d\u0435\u043f\u043e\u0437\u043d\u0430\u0442 SpeedView.stats.estimate=\u041f\u0440\u043e\u0446\u0435\u043d\u0430 SpeedView.stats.measured=\u041c\u0435\u0440\u0435\u043d\u043e SpeedView.stats.measuredmin=\u041c\u0435\u0440\u0435\u043d\u0438 \u043c\u0438\u043d. SpeedView.stats.manual=\u0418\u0441\u043f\u0440\u0430\u0432\u0459\u0435\u043d\u043e ConfigView.section.transfer.autospeed.networks=\u0414\u0435\u0442\u0430\u0459\u0438 \u043e \u043c\u0440\u0435\u0436\u0438 ConfigView.section.transfer.autospeed.resetnetwork=\u041f\u043e\u043d\u043e\u0432\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438 \u0434\u0435\u0442\u0430\u0459\u0435 \u043e \u043c\u0440\u0435\u0436\u0438 ConfigView.section.transfer.autospeed.network.info=\u0413\u043e\u0440\u0435 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0435 \u0433\u0440\u0430\u043d\u0438\u0446\u0435 \u0441\u0435 \u043e\u0431\u0438\u0447\u043d\u043e \u0440\u0430\u0447\u0443\u043d\u0430\u0458\u0443 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u0442\u043e\u043a\u043e\u043c \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u0438\u043b\u0438 \u0441\u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u0438\u0446\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u043f\u0440\u0435\u043d\u043e\u0441\u0430. \u0410\u043a\u043e \u0436\u0435\u043b\u0438\u0442\u0435 \u0434\u0430 \u0438\u0445 \u0437\u0430\u0434\u0430\u0442\u0435 \u0440\u0443\u0447\u043d\u043e, \u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u043e\u043f\u0446\u0438\u0458\u0435 \u0438\u0441\u043f\u043e\u0434.\n\u0421\u0432\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0430 \u043e\u0441\u0438\u043c \u201e\u0444\u0438\u043a\u0441\u043d\u043e\u201f \u045b\u0435 \u0431\u0438\u0442\u0438 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u043d\u0430 \u0430\u043a\u043e \u0458\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e.\n\u0423\u043d\u0435\u0441\u0438\u0442\u0435 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442 \u0438 \u0438\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0440\u0441\u0442\u0443. \u0411\u0440\u0437\u0438\u043d\u0435 \u0441\u0443 \u0438\u0437\u0440\u0430\u0436\u0435\u043d\u0435 \u0443 %1. dialog.uiswitcher.restart.title=\u041f\u0440\u043e\u043c\u0435\u043d\u0430 \u043a\u043e\u0440. \u0441\u0443\u0447\u0435\u0459\u0430: \u043f\u043e\u0442\u0440\u0435\u0431\u0430\u043d \u0458\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 dialog.uiswitcher.restart.text=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u043c\u043e\u0440\u0430 \u0434\u0430 \u0441\u0435 \u043f\u043e\u043d\u043e\u0432\u043e \u043f\u043e\u043a\u0440\u0435\u043d\u0435 \u0434\u0430 \u0431\u0438 \u0441\u0435 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e \u0441\u0443\u0447\u0435\u0459\u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u0438\u043b\u043e. TrayWindow.menu.close=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 \u043a\u043e\u0440\u043f\u0443 \u0441\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0438\u043c\u0430 # Used for peers which we can't determine. PeerSocket.unknown=\u041d\u0435\u043f\u043e\u0437\u043d\u0430\u0442 PeerSocket.fake_client=\u041b\u0410\u0416\u041d\u0418 PeerSocket.bad_peer_id=\u043d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u0430\u043d \u0418\u0414 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 PeerSocket.mismatch_id=\u043d\u0435\u0441\u0430\u0433\u043b\u0430\u0441\u043d\u043e PeerSocket.unknown_az_style=\u041d\u0435\u043f\u043e\u0437\u043d\u0430\u0442 %1/%2 PeerSocket.unknown_shadow_style=\u041d\u0435\u043f\u043e\u0437\u043d\u0430\u0442 %1/%2 OpenTorrentWindow.mb.askCreateDir.title=\u041e\u0434\u0440\u0435\u0434\u0438\u0448\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u043d\u0435 \u043f\u043e\u0441\u0442\u043e\u0458\u0438 OpenTorrentWindow.mb.askCreateDir.text=\u041e\u0434\u0440\u0435\u0434\u0438\u0448\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0458\u0443\u043c \u201e%1\u201f \u043d\u0435 \u043f\u043e\u0441\u0442\u043e\u0458\u0438.\n\n\u0414\u0430 \u043b\u0438 \u0434\u0430 \u0433\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u043c? SpeedView.stats.estimatechoke=\u041f\u0440\u043e\u0446\u0435\u043d\u0430 (\u0433\u0430\u0441) ConfigTransferAutoSpeed.upload.capacity.usage=\u0423\u043f\u043e\u0442\u0440\u0435\u0431\u0430 \u043a\u0430\u043f\u0430\u0446\u0438\u0442\u0435\u0442\u0430 \u0437\u0430 \u0441\u043b\u0430\u045a\u0435 ConfigTransferAutoSpeed.mode=\u041d\u0430\u0447\u0438\u043d \u0440\u0430\u0434\u0430: ConfigTransferAutoSpeed.capacity.used=% \u043a\u0430\u043f\u0430\u0446\u0438\u0442\u0435\u0442\u0430 \u0443 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0438 ConfigTransferAutoSpeed.while.downloading=\u041f\u0440\u0438\u0458\u0435\u043c: ConfigTransferAutoSpeed.set.dht.ping=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 \u0414\u0425\u0422 \u043f\u0438\u043d\u0433\u0430: ConfigTransferAutoSpeed.set.point=\u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u0430 \u0442\u0430\u0447\u043a\u0430 (ms) ConfigTransferAutoSpeed.set.tolerance=\u0442\u043e\u043b\u0435\u0440\u0430\u043d\u0446\u0438\u0458\u0430 (ms) ConfigTransferAutoSpeed.ping.time.good=\u0414\u043e\u0431\u0440\u0438: ConfigTransferAutoSpeed.ping.time.bad=\u041b\u043e\u0448\u0438: ConfigTransferAutoSpeed.adjustment.interval=\u0412\u0440\u0435\u043c\u0435 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430: ConfigTransferAutoSpeed.skip.after.adjust=\u041f\u0440\u0435\u0441\u043a\u043e\u0447\u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430: GeneralView.label.distributedCopies=\u0414\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0438\u0440\u0430\u043d\u0438 \u0443\u043c\u043d\u043e\u0448\u0446\u0438: PiecesView.DistributionView.title=\u0420\u0430\u0441\u043f\u043e\u0434\u0435\u043b\u0430 \u0434\u0435\u043b\u043e\u0432\u0430 PiecesView.DistributionView.NoAvl=\u041d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438 \u0434\u0435\u043b\u043e\u0432\u0438 PiecesView.DistributionView.SeedAvl=\u041f\u0440\u0438\u043b\u043e\u0433 \u0430\u0432\u043b-\u0443 \u0437\u0430\u043c\u0435\u0442\u043a\u0430 PiecesView.DistributionView.PeerAvl=\u041f\u0440\u0438\u043b\u043e\u0433 \u0430\u0432\u043b-\u0443 \u043e\u0434 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 PiecesView.DistributionView.RarestAvl=\u041d\u0430\u0458\u0440\u0435\u0452\u0438 \u0434\u0435\u043b\u043e\u0432\u0438: %1 (\u0434\u043e\u0441\u0442.:%2) PiecesView.DistributionView.weHave=\u0414\u0435\u043b\u043e\u0432\u0438 \u043a\u043e\u0458\u0435 \u0438\u043c\u0430\u0442\u0435 PiecesView.DistributionView.theyHave=\u0414\u0435\u043b\u043e\u0432\u0438 \u043a\u043e\u0458\u0435 \u0438\u043c\u0430 \u0443\u0434\u0430\u0459\u0435\u043d\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 PiecesView.DistributionView.weDownload=\u0414\u0435\u043b\u043e\u0432\u0438 \u043a\u043e\u0458\u0435 \u043f\u0440\u0438\u043c\u0430\u0442\u0435 PeersView.gain=\u041f\u043e\u0458\u0430\u0447\u0430\u045a\u0435 PeersView.gain.info=\u041a\u043e\u043b\u0438\u0447\u0438\u043d\u0430 \u043f\u0440\u0438\u043c\u0459\u0435\u043d\u0438\u0445 - \u043f\u043e\u0441\u043b\u0430\u0442\u0438\u0445 \u043f\u043e\u0434\u0430\u0442\u0430\u043a\u0430 unix.script.new.title=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0438 \u0441\u0443 \u043d\u043e\u0432\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u0438 \u0437\u0430 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 unix.script.new.text=\u0414\u043e\u0441\u0442\u0443\u043f\u0430\u043d \u0458\u0435 \u043d\u043e\u0432\u0438 \u0441\u043a\u0440\u0438\u043f\u0442 \u0437\u0430 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430, \u0430 \u0441\u0430\u0447\u0443\u0432\u0430\u043d \u0458\u0435 \u0443 \u201e%1\u201f.\n\n\u041f\u0440\u0435\u043f\u043e\u0440\u0443\u0447\u0443\u0458\u0435 \u0441\u0435 \u0434\u0430 \u043e\u0434\u043c\u0430\u0445 \u0437\u0430\u0442\u0432\u043e\u0440\u0438\u0442\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 \u0438 \u0434\u0430 \u0441\u0435 \u043f\u0440\u0435\u0431\u0430\u0446\u0438\u0442\u0435 \u043d\u0430 \u043e\u0432\u0430\u0458 \u0441\u043a\u0440\u0438\u043f\u0442. (\u201e%2\u201f).\n\n\u0410\u043a\u043e \u0441\u0442\u0435 \u043c\u0435\u045a\u0430\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442 \u0437\u0430 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435, \u043c\u043e\u043b\u0438\u043c\u043e \u0434\u0430 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u0435 \u0447\u043b\u0430\u043d\u0430\u043a AzureusWiki: Unix Script.\n\n\u0410\u043a\u043e \u0441\u0442\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043b\u0438 \u0438\u0437 \u043d\u0435\u043a\u0435 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0446\u0438\u0458\u0435 (yum, apt-get, \u0438\u0442\u0434.), \u043f\u0440\u0435\u043f\u043e\u0440\u0443\u0447\u0443\u0458\u0435 \u0441\u0435 \u0434\u0430 \u0433\u0430 \u043f\u043e\u043d\u043e\u0432\u043e \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u0442\u0435 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u043e\u043c \u043f\u0430\u043a\u0435\u0442\u0430 \u0441\u0430 \u0430\u0434\u0440\u0435\u0441\u0435: \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432\u0430 \u0441\u0442\u0440\u0430\u043d\u0430 \u043d\u0430 \u0421\u043e\u0440\u0441\u0444\u043e\u0440\u045f\u0443 (\u0438 \u0434\u0430\u0459\u0435 \u045b\u0435\u0442\u0435 \u0438\u043c\u0430\u0442\u0438 \u0438\u0441\u0442\u043e \u0441\u0443\u0447\u0435\u0459\u0435 \u043a\u0430\u043e \u0438 \u0441\u0430\u0434\u0430) unix.script.new.manual.url=http://azureuswiki.com/index.php/AdvancedNetworkSettings unix.script.new.button.quit=\u041a\u0440\u0430\u0458 \u0440\u0430\u0434\u0430 unix.script.new.button.continue=\u0423\u0440\u0430\u0434\u0438\u045b\u0443 \u0442\u043e \u043a\u0430\u0441\u043d\u0438\u0458\u0435 unix.script.new.button.asknomore=\u041d\u0435 \u043e\u0431\u0430\u0432\u0435\u0448\u0442\u0430\u0432\u0430\u0458 \u043c\u0435 \u0432\u0438\u0448\u0435 unix.script.new.auto.title=\u041d\u043e\u0432\u0438 \u0441\u043a\u0440\u0438\u043f\u0442 \u0437\u0430 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430 unix.script.new.auto.text=\u0414\u043e\u0441\u0442\u0443\u043f\u0430\u043d \u0458\u0435 \u043d\u043e\u0432\u0438 \u0441\u043a\u0440\u0438\u043f\u0442 \u0437\u0430 \u043f\u043e\u043a\u0440\u0435\u0442\u0430\u045a\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430.\n\n\u041f\u0440\u0435\u043f\u043e\u0440\u0443\u0447\u0443\u0458\u0435 \u0441\u0435 \u0434\u0430 \u043e\u0434\u043c\u0430\u0445 \u043f\u043e\u043d\u043e\u0432\u043e \u043f\u043e\u043a\u0440\u0435\u043d\u0435\u0442\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u0430. Content.alert.notuploaded.button.stop=&\u0421\u0442\u0430\u043d\u0438 Content.alert.notuploaded.button.continue=\u041d\u0430\u0441\u0442\u0430\u0432\u0438 &\u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0435 Content.alert.notuploaded.button.abort=&\u041d\u0435 \u0437\u0430\u0432\u0440\u0448\u0430\u0432\u0430\u0458 ConfigView.label.checkOnSeeding=\u0411\u0440\u0437\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438 \u0434\u0435\u043b\u043e\u0432\u0435 \u043f\u0440\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443 ConfigView.label.ui_switcher=\u0418\u0437\u0431\u043e\u0440 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e\u0433 \u0441\u0443\u0447\u0435\u0459\u0430 ConfigView.label.ui_switcher_button=\u041f\u0440\u0438\u043a\u0430\u0437 SpeedTestWizard.test.panel.explain=\u0418\u0437\u043c\u0435\u0440\u0438\u0442\u0435 \u0431\u0440\u0437\u0438\u043d\u0443 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432\u043e\u0433 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430. \u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0440\u0441\u0442\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u0438 \u043d\u0430\u0447\u0438\u043d \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u045a\u0430. \u041f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432\u0443 \u0432\u0438\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0443 \u0437\u0430 \u0434\u0435\u0442\u0430\u0459\u0435 \u043e\u0432\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0435. \u041f\u0440\u043e\u0432\u0435\u0440\u0430 \u045b\u0435 \u0441\u0435 \u0437\u0430\u0432\u0440\u0448\u0438\u0442\u0438 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0438 \u0430\u043a\u043e \u043f\u043e\u0442\u0440\u0430\u0458\u0435 \u0434\u0443\u0436\u0435 \u043e\u0434 \u0434\u0432\u0430 \u043c\u0438\u043d\u0443\u0442\u0430. \u0422\u0438\u043f\u0438\u0447\u043d\u043e \u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0430 \u0431\u0440\u0437\u0438\u043d\u0435 \u0441\u0430\u043c\u0430 \u0437\u0430\u0432\u0440\u0448\u0438 \u0437\u0430 \u043c\u0430\u045a\u0435 \u043e\u0434 \u043c\u0438\u043d\u0443\u0442\u0430. SpeedTestWizard.set.upload.hint=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0430 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c \u0438 \u0441\u043b\u0430\u045a\u0435 \u043f\u0440\u0435\u043c\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441\u043e\u0432\u043e\u043c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0443 \u0437\u0430 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0443 \u0440\u0435\u0433\u0443\u043b\u0430\u0446\u0438\u0458\u0443. SpeedTestWizard.set.upload.panel.explain=\u0413\u0440\u0430\u043d\u0438\u0446\u0435 \u043a\u043e\u0458\u0435 \u0441\u0435 \u043e\u0432\u0434\u0435 \u043f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u0458\u0443 \u043a\u043e\u0440\u0438\u0441\u0442\u0435 \u0441\u0435 \u0443 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0443 \u0437\u0430 \u0430\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0443 \u0440\u0435\u0433\u0443\u043b\u0430\u0446\u0438\u0458\u0443 \u0431\u0440\u0437\u0438\u043d\u0435. \u041f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u0433\u0440\u0430\u043d\u0438\u0447\u043d\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u043f\u0440\u0435\u043d\u043e\u0441\u0430 \u0438 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0435 \u043f\u043e\u0432\u0435\u0440\u0435\u045a\u0430.\n\n\u0411\u0440\u0437\u0438\u043d\u0435 \u043f\u0440\u0435\u043d\u043e\u0441\u0430 \u0441\u0435 \u043e\u0431\u0438\u0447\u043d\u043e \u043d\u0430\u0432\u043e\u0434\u0435 \u0443 \u201e\u0431\u0438\u0442\u0438\u043c\u0430 \u0443 \u0441\u0435\u043a\u0443\u043d\u0434\u0438\u201f, \u0434\u043e\u043a \u0441\u0443 \u043e\u0432\u0434\u0435 \u043f\u0440\u0438\u043a\u0430\u0437\u0430\u043d\u0438 \u201e\u043a\u0438\u043b\u043e\u0431\u0430\u0458\u0442\u0438 \u0443 \u0441\u0435\u043a\u0443\u043d\u0434\u0438\u201f. SpeedTestWizard.set.limit.conf.level=\u041f\u043e\u0432\u0435\u0440\u0435\u045a\u0435 SpeedTestWizard.finish.panel.auto.speed=\u0410\u0443\u0442\u043e\u043c. \u0431\u0440\u0437\u0438\u043d\u0430 \u0458\u0435 : SpeedTestWizard.finish.panel.auto.speed.seeding=A\u0443\u0442\u043e\u043c\u0430\u0442\u0441\u043a\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438 \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0443 \u0458\u0435 : ConfigTransferAutoSpeed.add.comment.to.log.group=\u0414\u043e\u0434\u0430\u0458 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0443 \u0434\u043d\u0435\u0432\u043d\u0438\u043a ConfigTransferAutoSpeed.add.comment.to.log=\u0414\u043e\u0434\u0430\u0458 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440: ConfigTransferAutoSpeed.log.button=\u0414\u043d\u0435\u0432\u043d\u0438\u043a ConfigTransferAutoSpeed.algorithm.selector=\u0418\u0437\u0431\u043e\u0440 \u0430\u0443\u0442\u043e\u043c. \u0431\u0440\u0437\u0438\u043d\u0435 ConfigTransferAutoSpeed.algorithm=\u0410\u043b\u0433\u043e\u0440\u0438\u0442\u0430\u043c: ConfigTransferAutoSpeed.auto.speed.classic=\u0410\u0443\u0442\u043e\u043c. \u0431\u0440\u0437\u0438\u043d\u0430 (\u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0430) ConfigTransferAutoSpeed.auto.speed.beta=\u0410\u0443\u0442\u043e\u043c. \u0431\u0440\u0437\u0438\u043d\u0430 (\u0431\u0435\u0442\u0430) ConfigTransferAutoSpeed.data.update.frequency=\u0423\u0447\u0435\u0441\u0442\u0430\u043d\u043e\u0441\u0442 \u043e\u0441\u0432\u0435\u0436\u0430\u0432\u0430\u045a\u0430 Alert.failed.update=\u0411\u0430\u0440 \u0458\u0435\u0434\u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043d\u0438\u0458\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0435\u043d\u0430. \u0412\u0438\u0434\u0438\u0442\u0435 AzureusWiki: Failed Update [%1] OpenTorrentWindow.mb.existingFiles.partialList=(\u0414\u0435\u043b\u0438\u043c\u0438\u0447\u0430\u043d \u0441\u043f\u0438\u0441\u0430\u043a. \u0412\u0435\u045b \u0438\u043c\u0430 \u0458\u043e\u0448 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430) TableColumn.header.bad_avail_time.info=\u041f\u043e\u0441\u043b\u0435\u0434\u045a\u0438 \u043f\u0443\u0442 \u043a\u0430\u0434\u0430 \u0458\u0435 \u0446\u0435\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043a \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u0431\u0438\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430\u043d TableColumn.header.bad_avail_time=\u041f\u0440\u043e\u043d\u0430\u0452\u0435\u043d \u0458\u0435 \u0446\u0435\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043a MyTorrentsView.menu.exporthttpseeds=\u0423\u043c\u043d\u043e\u0436\u0438 \u0423\u0420\u041b \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u043d\u0430 \u043a\u043b\u0438\u043f\u0431\u043e\u0440\u0434 SWT.alert.erroringuithread=\u0414\u0435\u0441\u0438\u043b\u0430 \u0441\u0435 \u043d\u0435\u043e\u0431\u0440\u0430\u0452\u0435\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430 \u0443 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e\u043c \u0441\u0443\u0447\u0435\u0459\u0443. \u041c\u043e\u0433\u0443 \u0434\u0430 \u0441\u0435 \u0458\u0430\u0432\u0435 \u0434\u0440\u0443\u0433\u0435 \u0432\u0435\u0437\u0430\u043d\u0435 \u0433\u0440\u0435\u0448\u043a\u0435 ConfigView.label.minannounce=\u041d\u0430\u0458\u043c\u0430\u045a\u0435 \u0432\u0440\u0435\u043c\u0435 \u0438\u0437\u043c\u0435\u0452\u0443 \u0437\u0430\u0445\u0442\u0435\u0432\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0443, \u0443 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u043c\u0430 ConfigView.label.maxnumwant=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438 \u0431\u0440\u043e\u0458 \u0440\u0430\u0447\u0443\u043d\u0430\u0440\u0430 \u043a\u043e\u0458\u0438 \u043f\u0440\u0430\u0442\u0438\u043b\u0430\u0446 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0434\u043e\u0441\u0442\u0430\u0432\u0438 ConfigView.label.announceport=\u041f\u0440\u0435\u0438\u043d\u0430\u0447\u0438 \u043d\u0430\u0458\u0430\u0432\u0459\u0435\u043d\u0438 \u0422\u0426\u041f \u043f\u043e\u0440\u0442 \u0437\u0430 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0430, pex \u0438 \u0414\u0425\u0422.\n[\u043f\u0440\u0430\u0437\u043d\u043e: \u043d\u0435 \u043f\u0440\u0435\u0438\u043d\u0430\u0447\u0443\u0458, 0: \u043d\u0435\u043c\u0430 \u0434\u043e\u043b\u0430\u0437\u043d\u0438\u0445 \u0432\u0435\u0437\u0430] ConfigView.label.noportannounce=\u041d\u0435 \u043d\u0430\u0458\u0430\u0432\u0459\u0443\u0458 \u043f\u043e\u0440\u0442 \u0437\u0430 \u0441\u043b\u0443\u0448\u0430\u045a\u0435 \u043f\u0440\u0430\u0442\u0438\u043e\u0446\u0443 (\u043e\u0432\u043e \u043d\u0435 \u0443\u0442\u0438\u0447\u0435 \u043d\u0430 \u0414\u0425\u0422 \u0438 \u043e\u0441\u0442\u0430\u043b\u043e) ConfigView.label.maxseedspertorrent=\u041d\u0430\u0458\u0432\u0435\u045b\u0438 \u0431\u0440\u043e\u0458 \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] wizard.webseed=\u0414\u043e\u0434\u0430\u0458 HTTP \u0437\u0430\u043c\u0435\u0442\u043a\u0435 \u0443 \u0442\u043e\u0440\u0435\u043d\u0442 wizard.webseed.title=HTTP \u0437\u0430\u043c\u0435\u0446\u0438 wizard.webseed.configuration=\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0435 HTTP \u0437\u0430\u043c\u0435\u0442\u0430\u045a\u0430 wizard.webseed.adding=\u0414\u043e\u0434\u0430\u0432\u0430\u045a\u0435 HTTP \u0437\u0430\u043c\u0435\u0442\u0430\u043a\u0430 GeneralView.label.private=\u041f\u0440\u0438\u0432\u0430\u0442\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442: GeneralView.yes=\u0434\u0430 GeneralView.no=\u043d\u0435 ConfigView.label.userequestlimiting=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0435 \u0431\u0440\u043e\u0458\u0430 \u0437\u0430\u0445\u0442\u0435\u0432\u0430 \u0443\u043c\u0435\u0441\u0442\u043e \u043a\u0430\u0448\u045a\u0435\u045a\u0430 \u0447\u0438\u0442\u0430\u045a\u0430 \u0437\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0435 \u0431\u0440\u0437\u0438\u043d\u0435 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 [\u043d\u0435\u043c\u0430 \u0435\u0444\u0435\u043a\u0442\u0430 \u043a\u0430\u0434\u0430 \u0458\u0435 \u0431\u0440\u0437\u0438\u043d\u0430 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430] ConfigView.label.userequestlimiting.tooltip=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0435 \u0431\u0440\u043e\u0458\u0430 \u0437\u0430\u0445\u0442\u0435\u0432\u0430 \u043d\u0435 \u0440\u0430\u0434\u0438 \u0442\u0430\u043a\u043e \u0433\u043b\u0430\u0442\u043a\u043e \u043a\u0430\u043e \u043a\u0430\u0448\u045a\u0435\u045a\u0435 \u0447\u0438\u0442\u0430\u045a\u0430, \u0430\u043b\u0438 \u0434\u043e\u0437\u0432\u043e\u0459\u0430\u0432\u0430 \u0443\u0440\u0435\u0452\u0438\u0432\u0430\u045a\u0435 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u043f\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u043f\u0440\u0435\u043c\u0430 \u043c\u0435\u0441\u0442\u0443 \u0443 \u0440\u0435\u0434\u0443 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c, \u0438 \u043c\u043e\u0436\u0434\u0430 \u043f\u043e\u0431\u043e\u0459\u0448\u0430 \u043f\u0440\u043e\u0442\u043e\u043a \u043d\u0430 \u043c\u0440\u0435\u0436\u0438 ConfigView.section.logging.timestamp=\u0424\u043e\u0440\u043c\u0430\u0442 \u0438\u0441\u043f\u0438\u0441\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0430 \u0437\u0430 \u0434\u043d\u0435\u0432\u043d\u0438\u043a Peers.column.timetocomplete=\u041f\u0440\u0435\u043e\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u0435 Peers.column.timetocomplete.info=\u041f\u0440\u0435\u043e\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u0435 \u0434\u043e\u043a \u0434\u0440\u0443\u0433\u0438 \u0440\u0430\u0447\u0443\u043d\u0430\u0440 \u043d\u0435 \u0437\u0430\u0432\u0440\u0448\u0438 ConfigView.section.interface.display.suppress.file.download.dialog=\u041f\u0440\u0438\u043a\u0440\u0438\u0458 \u043f\u0440\u043e\u0437\u043e\u0440 \u0437\u0430 \u043f\u0440\u0438\u0458\u0435\u043c \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u043d\u0430\u043f\u0440\u0435\u0434\u0430\u043a \u0441\u0432\u0438\u0445 \u043f\u0440\u0438\u0458\u0435\u043c\u0430 \u0443 \u0441\u0442\u0430\u0442\u0443\u0441\u043d\u043e\u0458 \u0442\u0440\u0430\u0446\u0438, \u0443\u043c\u0435\u0441\u0442\u043e \u0438\u0441\u043a\u0430\u0447\u0443\u045b\u0435\u0433 \u043f\u0440\u043e\u0437\u043e\u0440\u0430 FileDownload.canceled=\u0422\u043e\u0440\u0435\u043d\u0442 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 \u0458\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0442\u043a\u0430\u0437\u0430\u043d\u0430 \u043d\u0430 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u043a\u043e\u0432 \u0437\u0430\u0445\u0442\u0435\u0432: %1 Progress.reporting.status.canceled=\u041e\u0442\u043a\u0430\u0437\u0430\u043d Progress.reporting.status.finished=\u0417\u0430\u0432\u0440\u0448\u0435\u043d\u043e Progress.reporting.status.retrying=\u041e\u043f\u0435\u0442... Progress.reporting.action.label.retry.tooltip=\u041f\u043e\u043d\u043e\u0432\u0438 \u043e\u0432\u043e \u0434\u0435\u0458\u0441\u0442\u0432\u043e Progress.reporting.action.label.remove.tooltip=\u0423\u043a\u043b\u043e\u043d\u0438 \u043e\u0432\u0430\u0458 \u0438\u0437\u0432\u0435\u0448\u0442\u0430\u0458 \u043e \u043d\u0430\u043f\u0440\u0435\u0442\u043a\u0443 \u0438\u0437 \u0438\u0441\u0442\u043e\u0440\u0438\u0458\u0430\u0442\u0430 Progress.reporting.action.label.cancel.tooltip=\u041e\u0442\u043a\u0430\u0436\u0438 \u043e\u0432\u043e \u0434\u0435\u0458\u0441\u0442\u0432\u043e Progress.reporting.action.label.detail=\u0414\u0435\u0442\u0430\u0459\u0438 Progress.reporting.default.error=\u041d\u0435\u0443\u0441\u043f\u0435\u043b\u043e Progress.reporting.no.reports.to.display=\u0417\u0430 \u0441\u0430\u0434\u0430 \u043d\u0435\u043c\u0430 \u0438\u0437\u0432\u0435\u0448\u0442\u0430\u0458\u0430 \u043e \u043d\u0430\u043f\u0440\u0435\u0442\u043a\u0443 Progress.reporting.no.history.to.display=\u041d\u0435\u043c\u0430 \u0434\u0435\u0442\u0430\u0459\u043d\u0438\u0445 \u043f\u043e\u0440\u0443\u043a\u0430 \u0437\u0430 \u043f\u0440\u0438\u043a\u0430\u0437 Progress.reporting.detail.history.limit=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u045a\u0435 \u0437\u0430 \u0431\u0440\u043e\u0458 \u0434\u0435\u0442\u0430\u0459\u043d\u0438\u0445 \u043f\u043e\u0440\u0443\u043a\u0430 (%1) \u0437\u0430 \u043e\u0432\u0430\u0458 ProgressReporter \u0445\u0435 \u043f\u0440\u0435\u043c\u0430\u0448\u0435\u043d\u043e; \u043d\u0430\u0440\u0435\u0434\u043d\u0435 \u043f\u043e\u0440\u0443\u043a\u0435 \u043d\u0435\u045b\u0435 \u0431\u0438\u0442\u0438 \u0434\u043e\u0434\u0430\u0432\u0430\u043d\u0435 \u0443 \u0438\u0441\u0442\u043e\u0440\u0438\u0458\u0430\u0442 Progress.reporting.statusbar.button.tooltip=\u041f\u0440\u0438\u043a\u0430\u0436\u0438 \u043f\u0440\u043e\u0437\u043e\u0440 \u0437\u0430 \u043f\u0440\u0430\u045b\u0435\u045a\u0435 \u043d\u0430\u043f\u0440\u0435\u0442\u043a\u0430 webui.bindip=\u041a\u043e\u0440\u0438\u0441\u0442\u0438 \u0418\u041f \u0431\u0440\u043e\u0458 - \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e \u043d\u0438\u0458\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e (*) v3.MainWindow.text.log.in=\u041f\u0440\u0438\u0458\u0430\u0432\u0430 v3.MainWindow.text.log.out=\u041e\u0434\u0458\u0430\u0432\u0430 v3.MainWindow.text.get.started=\u0423\u0432\u043e\u0434 v3.MainWindow.text.my.account=\u041c\u043e\u0458 \u043d\u0430\u043b\u043e\u0433 v3.MainWindow.text.my.profile=\u041f\u0440\u043e\u0444\u0438\u043b OpenTorrentWindow.simple.open=\u041c\u0435\u0441\u0442\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0430 (\u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430, \u0423\u0420\u041b, \u0445\u0435\u0448) MainWindow.menu.window.zoom.maximize=\u0423\u0432\u0435\u045b\u0430\u0458 MainWindow.dialog.select.vuze.file=\u041e\u0434\u0430\u0431\u0435\u0440\u0438 \u0412\u0458\u0443\u0437 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0443 MainWindow.menu.file.open.vuze=\u0412\u0458\u0443\u0437 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430... v3.activity.header.downloads=\u041f\u0440\u0435\u0443\u0437\u0438\u043c\u0430\u045a\u0430 iconBar.play=\u041f\u0443\u0441\u0442\u0438 iconBar.queue.tooltip=\u0420\u0435\u0434 v3.MainWindow.menu.getting_started=&\u041f\u043e\u0447\u0435\u0442\u0430\u043a MainWindow.menu.community=&\u0417\u0430\u0458\u0435\u0434\u043d\u0438\u0446\u0430 MainWindow.menu.help.faq=&\u0427\u0435\u0441\u0442\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0459\u0430\u043d\u0430 \u043f\u0438\u0442\u0430\u045a\u0430 MainWindow.menu.community.wiki=&\u0412\u0438\u043a\u0438 MainWindow.menu.community.forums=&\u0424\u043e\u0440\u0443\u043c MainWindow.menu.community.blog=\u0412\u0458\u0443\u0437 &\u0411\u043b\u043e\u0433 MainWindow.menu.help.support=&\u041f\u043e\u043c\u043e\u045b \u0438 \u043f\u043e\u0434\u0440\u0448\u043a\u0430 v3.activity.button.readall=\u0421\u0432\u0435 \u043a\u0430\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043e v3.activity.button.watchall= MainWindow.menu.help.donate=&\u0414\u0430\u0458\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0433 azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_iw_IL.properties0000644000175000017500000034430511301156004026103 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=\u05e7\u05d5\u05d1\u05e5 \u05d8\u05d5\u05e8\u05e0\u05d8 Main.parameter.maxUploads=\u05de\u05e1\u05e4\u05e8 \u05d4\u05e2\u05dc\u05d0\u05d5\u05ea \u05de\u05d9\u05e8\u05d1\u05d9 Main.parameter.maxSpeed=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05d5\u05e8\u05d3\u05d4 \u05de\u05d9\u05e8\u05d1\u05d9\u05ea - \u05d1\u05d9\u05d9\u05d8\u05d9\u05dd \u05dc\u05e9\u05e0\u05d9\u05d4 MainWindow.menu.file=\u05e7\u05d5\u05d1\u05e5 MainWindow.menu.file.open=\u05e4\u05ea\u05d7 MainWindow.menu.file.create=\u05e6\u05d5\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8 MainWindow.menu.file.create.fromfile=\u05de\u05e7\u05d5\u05d1\u05e5 MainWindow.menu.file.create.fromdir=\u05de\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 MainWindow.menu.file.export=\u05d9\u05d9\u05e6\u05d0 \u05d8\u05d5\u05e8\u05e0\u05d8 MainWindow.menu.file.import=\u05d9\u05d9\u05d1\u05d0 \u05d8\u05d5\u05e8\u05e0\u05d8 MainWindow.menu.file.exit=\u05d9\u05e6\u05d9\u05d0\u05d4 MainWindow.dialog.choose.file=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 MainWindow.menu.file.folder=\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 MainWindow.dialog.choose.folder=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05d4\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 \u05d4\u05de\u05db\u05d9\u05dc\u05d4 \u05d0\u05ea \u05e7\u05d5\u05d1\u05e6\u05d9 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 MainWindow.menu.view=\u05e4\u05e2\u05d5\u05dc\u05d5\u05ea MainWindow.menu.view.mytorrents=\u05d4\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05e9\u05dc\u05d9 MainWindow.menu.view.configuration=\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea MainWindow.menu.view.console=\u05d9\u05d5\u05de\u05df MainWindow.menu.view.irc=Irc MainWindow.menu.closealldetails=\u05e1\u05d2\u05d5\u05e8 \u05d0\u05ea \u05db\u05dc \u05d4\u05e4\u05e8\u05d8\u05d9\u05dd MainWindow.menu.closealldownloadbars=\u05e1\u05d2\u05d5\u05e8 \u05d0\u05ea \u05db\u05dc \u05d7\u05dc\u05d5\u05e0\u05d5\u05ea \u05ea\u05e6\u05d5\u05d2\u05ea \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 MainWindow.menu.language=\u05e9\u05e4\u05d4 ConfigView.section.language=\u05e9\u05e4\u05d4 MainWindow.menu.help=\u05e2\u05d6\u05e8\u05d4 MainWindow.menu.help.about=\u05d0\u05d5\u05d3\u05d5\u05ea \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 MainWindow.about.title=\u05ea\u05e8\u05d2\u05d5\u05dd \u05dc\u05e2\u05d1\u05e8\u05d9\u05ea, \u05d2\u05d9\u05e8\u05e1\u05d4 MainWindow.about.section.developers=\u05de\u05e4\u05ea\u05d7\u05d9\u05dd MainWindow.about.section.translators=\u05de\u05ea\u05e8\u05d2\u05de\u05d9\u05dd MainWindow.about.section.internet=\u05d0\u05d9\u05e0\u05d8\u05e8\u05e0\u05d8 MainWindow.about.internet.homepage=\u05d3\u05e3 \u05d4\u05d1\u05d9\u05ea \u05e9\u05dc \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 MainWindow.about.internet.sourceforge=\u05d3\u05e3 \u05d4\u05e4\u05e8\u05d5\u05d9\u05e7\u05d8\u05d9\u05dd \u05e9\u05dc Sourceforge MainWindow.about.internet.sourceforgedownloads=Sourceforge-\u05d4\u05d5\u05e8\u05d3\u05d5\u05ea \u05de MainWindow.about.internet.bugreports=\u05d3\u05d5\u05d5\u05d7 \u05e2\u05dc \u05d1\u05d0\u05d2\u05d9\u05dd MainWindow.about.internet.forumdiscussion=\u05e4\u05d5\u05e8\u05d5\u05dd \u05db\u05dc\u05dc\u05d9 MainWindow.dialog.choose.savepath=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05e0\u05ea\u05d9\u05d1 \u05d4\u05e9\u05de\u05d9\u05e8\u05d4 MainWindow.dialog.choose.savepath_forallfiles=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05e0\u05ea\u05d9\u05d1 \u05d4\u05e9\u05de\u05d9\u05e8\u05d4 \u05e2\u05d1\u05d5\u05e8 \u05db\u05dc \u05d4\u05e7\u05d1\u05e6\u05d9\u05dd MainWindow.status.latestversion=\u05d4\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d4\u05d0\u05d7\u05e8\u05d5\u05e0\u05d4 MainWindow.status.latestversion.clickupdate=\u05dc\u05d7\u05e5 \u05dc\u05e2\u05d9\u05d3\u05db\u05d5\u05df MainWindow.status.unknown=\u05dc\u05d0 \u05d9\u05d3\u05d5\u05e2\u05d4 MainWindow.status.checking=\u05d1\u05d5\u05d3\u05e7 MyTorrentsView.mytorrents=\u05d4\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05e9\u05dc\u05d9 TableColumn.header.name=\u05e9\u05dd TableColumn.header.size=\u05d2\u05d5\u05d3\u05dc TableColumn.header.done=\u05e1\u05d9\u05d9\u05dd TableColumn.header.done.info=\u05d0\u05d7\u05d5\u05d6\u05d9 \u05d1\u05d9\u05e6\u05d5\u05e2 \u05e9\u05dc \u05d4\u05e4\u05e2\u05d5\u05dc\u05d4 \u05d4\u05e0\u05d5\u05db\u05d7\u05d9\u05ea TableColumn.header.status=\u05de\u05e6\u05d1 TableColumn.header.status.info=\u05de\u05d4 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 \u05de\u05d1\u05e6\u05e2 TableColumn.header.seeds=\u05de\u05e4\u05d9\u05e6\u05d9\u05dd TableColumn.header.seeds.info=(\u05de\u05e7\u05d5\u05e8\u05d5\u05ea \u05d0\u05dc\u05d9\u05d4\u05dd \u05d0\u05ea\u05d4 \u05de\u05d7\u05d5\u05d1\u05e8 (\u05de\u05e1\u05e4\u05e8 \u05de\u05e7\u05d5\u05e8\u05d5\u05ea \u05db\u05d5\u05dc\u05dc TableColumn.header.peers=\u05de\u05e9\u05ea\u05e4\u05d9\u05dd TableColumn.header.peers.info=(\u05de\u05e1\u05e4\u05e8 \u05de\u05e9\u05ea\u05e4\u05d9\u05dd \u05d0\u05dc\u05d9\u05d4\u05dd \u05d0\u05ea\u05d4 \u05de\u05d7\u05d5\u05d1\u05e8 (\u05de\u05e1\u05e4\u05e8 \u05de\u05e9\u05ea\u05e4\u05d9\u05dd \u05db\u05dc\u05dc\u05d9 TableColumn.header.downspeed=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05d5\u05e8\u05d3\u05d4 TableColumn.header.upspeed=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05e2\u05dc\u05d0\u05d4 TableColumn.header.eta=\u05d6\u05de\u05df \u05de\u05e9\u05d5\u05e2\u05e8 \u05dc\u05e1\u05d9\u05d5\u05dd TableColumn.header.tracker=\u05d8\u05e8\u05e7\u05e8 TableColumn.header.tracker.info=\u05de\u05e6\u05d1 \u05d4\u05d8\u05e8\u05e7\u05e8 TableColumn.header.trackernextaccess=\u05ea\u05e7\u05e9\u05d5\u05e8\u05ea \u05d4\u05d1\u05d0\u05d4 \u05dc\u05d8\u05e8\u05d0\u05e7\u05e8 TableColumn.header.trackernextaccess.info=\u05d4\u05e4\u05e2\u05dd \u05d4\u05d1\u05d0\u05d4 \u05e9\u05ea\u05ea\u05e7\u05d9\u05d9\u05dd \u05ea\u05e7\u05e9\u05d5\u05e8\u05ea \u05dc\u05d8\u05e8\u05d0\u05e7\u05e8 TableColumn.header.priority=\u05e2\u05d3\u05d9\u05e4\u05d5\u05ea TableColumn.header.priority.info=\u05dc\u05e7\u05d1\u05d9\u05e2\u05d4 \u05e9\u05dc \u05db\u05de\u05d5\u05ea \u05e8\u05d5\u05d7\u05d1 \u05d4\u05e4\u05e1 \u05dc\u05d4\u05e2\u05dc\u05d0\u05d4 \u05dc\u05d8\u05d5\u05e8\u05e0\u05d8 \u05d6\u05d4 MyTorrentsView.menu.showdetails=\u05d4\u05e6\u05d2 \u05e4\u05e8\u05d8\u05d9\u05dd MyTorrentsView.menu.showdownloadbar=\u05d4\u05e6\u05d2 \u05e4\u05e8\u05d8\u05d9 \u05d4\u05d5\u05e8\u05d3\u05d4 MyTorrentsView.menu.open=\u05e4\u05ea\u05d7 MyTorrentsView.menu.setpriority=\u05e7\u05d1\u05e2 \u05e2\u05d3\u05d9\u05e4\u05d5\u05ea MyTorrentsView.menu.setpriority.high=\u05d2\u05d1\u05d5\u05d4\u05d4 MyTorrentsView.menu.setpriority.low=\u05e0\u05de\u05d5\u05db\u05d4 MyTorrentsView.menu.start=\u05d4\u05ea\u05d7\u05dc MyTorrentsView.menu.stop=\u05e2\u05e6\u05d5\u05e8 MyTorrentsView.menu.remove=\u05d4\u05e1\u05e8 MyTorrentsView.menu.changeTracker=\u05d4\u05d5\u05e1\u05e3 \u05db\u05ea\u05d5\u05d1\u05ea \u05d8\u05e8\u05e7\u05e8 TrayWindow.menu.exit=\u05d9\u05e6\u05d9\u05d0\u05d4 TrayWindow.menu.show=\u05d4\u05e6\u05d2 \u05d7\u05dc\u05d5\u05df \u05e8\u05d0\u05e9\u05d9 SystemTray.menu.exit=\u05d9\u05e6\u05d9\u05d0\u05d4 SystemTray.menu.closealldownloadbars=\u05e1\u05d2\u05d5\u05e8 \u05d0\u05ea \u05db\u05dc \u05ea\u05e6\u05d5\u05d2\u05d5\u05ea \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 SystemTray.menu.show=\u05d4\u05e6\u05d2 \u05d7\u05dc\u05d5\u05df \u05e8\u05d0\u05e9\u05d9 PeersView.ip=\u05d0\u05d9\u05d9.\u05e4\u05d9. PeersView.ip.info=\u05d0\u05d9\u05d9.\u05e4\u05d9. \u05e9\u05dc \u05d4\u05de\u05e9\u05ea\u05e3 PeersView.port=\u05e4\u05d5\u05e8\u05d8 PeersView.port.info=\u05d4\u05e4\u05d5\u05e8\u05d8 \u05d1\u05e9\u05d9\u05de\u05d5\u05e9 PeersView.T=\u05e1 PeersView.T.info=L - \u05de\u05e7\u05d5\u05de\u05d9, \u05d0\u05ea\u05d4 \u05d9\u05d6\u05de\u05ea \u05d0\u05ea \u05d4\u05d7\u05d9\u05d1\u05d5\u05e8, R - \u05de\u05e8\u05d5\u05d7\u05e7, \u05de\u05e9\u05ea\u05de\u05e9 \u05de\u05e8\u05d5\u05d7\u05e7 \u05d9\u05e6\u05e8 \u05d0\u05ea \u05d4\u05d7\u05d9\u05d1\u05d5\u05e8. PeersView.I1=(\u05de (\u05de\u05e2\u05d5\u05e0\u05d9\u05d9\u05df \u05d1\u05de\u05d9\u05d3\u05e2 \u05e9\u05d0\u05e6\u05dc \u05d4\u05de\u05e9\u05ea\u05e3 PeersView.I1.info=\u05d4\u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e2\u05d5\u05e0\u05d9\u05d9\u05df \u05d1\u05de\u05d4 \u05e9\u05d9\u05e9 \u05d0\u05e6\u05dc \u05d4\u05de\u05e9\u05ea\u05e3? PeersView.C1=(\u05d7 (\u05d7\u05e0\u05d5\u05e7 \u05e2"\u05d9 \u05d4\u05de\u05e9\u05ea\u05e3 PeersView.C1.info=\u05db\u05e9\u05d4\u05de\u05e9\u05ea\u05e3 \u05de\u05d5\u05e0\u05e2 \u05de\u05de\u05da \u05dc\u05d4\u05d5\u05e8\u05d9\u05d3 PeersView.pieces=\u05d7\u05dc\u05e7\u05d9\u05dd PeersView.%=\u05d0\u05d7\u05d5\u05d6 PeersView.downloadspeed=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05d5\u05e8\u05d3\u05d4 PeersView.download=\u05d9\u05e8\u05d3 PeersView.I2=(\u05de (\u05de\u05e2\u05e0\u05d9\u05d9\u05df \u05d0\u05ea \u05d4\u05de\u05e9\u05ea\u05e3 PeersView.I2.info=\u05d4\u05d0\u05dd \u05d4\u05de\u05e9\u05ea\u05e3 \u05de\u05e2\u05d5\u05e0\u05d9\u05d9\u05df \u05d1\u05de\u05d9\u05d3\u05e2 \u05e9\u05d0\u05e6\u05dc\u05da? PeersView.C2=(\u05d7 (\u05d7\u05d5\u05e0\u05e7 \u05d0\u05ea \u05d4\u05de\u05e9\u05ea\u05e3 PeersView.C2.info=\u05db\u05e9\u05d0\u05ea\u05d4 \u05de\u05d5\u05e0\u05e2 \u05de\u05d4\u05de\u05e9\u05ea\u05e3 \u05d4\u05d5\u05e8\u05d3\u05d4 PeersView.uploadspeed=\u05d4\u05e2\u05dc\u05d0\u05d4 PeersView.uploadspeed.info=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05d4\u05e2\u05dc\u05d0\u05d4 \u05e9\u05dc\u05da \u05dc\u05de\u05e9\u05ea\u05e3 PeersView.upload=\u05e0\u05e9\u05dc\u05d7 PeersView.upload.info=\u05d4\u05d4\u05e2\u05dc\u05d0\u05d4 \u05d4\u05db\u05d5\u05dc\u05dc\u05ea \u05e9\u05dc\u05da \u05dc\u05de\u05e9\u05ea\u05e3 PeersView.statup=\u05de\u05e6\u05d1 \u05d4\u05e2\u05dc\u05d0\u05d4 PeersView.statup.info=\u05d4\u05e2\u05e8\u05db\u05ea \u05d4\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05e9\u05dc \u05d4\u05de\u05e9\u05ea\u05e3 PeersView.S=\u05e1 PeersView.S.info=\u05d7\u05e1\u05d5\u05dd: \u05de\u05e9\u05ea\u05e3 \u05d9\u05db\u05d5\u05dc \u05dc\u05d4\u05d9\u05d5\u05ea "\u05d7\u05e1\u05d5\u05dd " \u05d9\u05d3\u05e0\u05d9\u05ea, \u05d0\u05d5 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea (\u05d5\u05db\u05da \u05dc\u05d0 \u05dc\u05d4\u05e2\u05d1\u05d9\u05e8 \u05de\u05d9\u05d3\u05e2 \u05d1\u05e7\u05e6\u05d1 \u05de\u05d4\u05d9\u05e8 \u05de\u05e1\u05e4\u05d9\u05e7) PeersView.downloadspeedoverall=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05d5\u05e8\u05d3\u05d4 \u05db\u05d5\u05dc\u05dc\u05ea PeersView.client=\u05ea\u05d5\u05db\u05e0\u05d4 PeersView.client.info=\u05e1\u05d5\u05d2 \u05d4\u05ea\u05d5\u05db\u05e0\u05d4 \u05e9\u05d1\u05d4 \u05d4\u05de\u05e9\u05ea\u05e3 \u05de\u05e9\u05ea\u05de\u05e9 PeersView.menu.snubbed=\u05de\u05d5\u05d2\u05d1\u05dc PeersView.title.short=\u05e4\u05e8\u05d8\u05d9\u05dd PeersView.title.full=\u05e4\u05e8\u05d8\u05d9\u05dd ConfigView.section.files=\u05e7\u05d1\u05e6\u05d9\u05dd ConfigView.label.usefastresume=\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05de\u05e6\u05d1 \u05d4\u05de\u05e9\u05db\u05d4 \u05de\u05d4\u05d9\u05e8\u05d4 ConfigView.label.incrementalfile=\u05d0\u05e4\u05e9\u05e8 \u05d9\u05e6\u05d9\u05e8\u05ea \u05e7\u05d1\u05e6\u05d9\u05dd \u05de\u05d5\u05d2\u05d3\u05dc\u05ea ConfigView.label.defaultsavepath=\u05e9\u05de\u05d5\u05e8 \u05dc\u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc ConfigView.button.browse=..\u05e1\u05d9\u05d9\u05e8 ConfigView.dialog.choosedefaultsavepath=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05d1\u05e8\u05d9\u05e8\u05ea \u05d4\u05de\u05d7\u05d3\u05dc \u05e9\u05dc\u05de\u05d9\u05e8\u05d4 ConfigView.section.server=\u05e9\u05e8\u05ea ConfigView.section.global=\u05db\u05dc\u05dc\u05d9 ConfigView.label.disconnetseed=\u05e0\u05ea\u05e7 \u05de\u05e4\u05d9\u05e6\u05d9\u05dd \u05db\u05d0\u05e9\u05e8 \u05de\u05e4\u05d9\u05e5 ConfigView.label.switchpriority=\u05e2\u05d1\u05d5\u05e8 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea \u05dc\u05e2\u05d3\u05d9\u05e4\u05d5\u05ea \u05e0\u05de\u05d5\u05db\u05d4 \u05db\u05d0\u05e9\u05e8 \u05de\u05e4\u05d9\u05e5 ConfigView.label.maxdownloads=(\u05de\u05e1\u05e4\u05e8 \u05d4\u05d4\u05d5\u05e8\u05d3\u05d5\u05ea \u05d4\u05d1\u05d5-\u05d6\u05de\u05e0\u05d9\u05d5\u05ea \u05d4\u05de\u05d9\u05e8\u05d1\u05d9 (0 : \u05d1\u05dc\u05ea\u05d9 \u05de\u05d5\u05d2\u05d1\u05dc ConfigView.label.maxactivetorrents=(\u05de\u05e1\u05e4\u05e8 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d4\u05e4\u05e2\u05d9\u05dc\u05d9\u05dd \u05d4\u05de\u05d9\u05e8\u05d1\u05d9 (0 : \u05d1\u05dc\u05ea\u05d9 \u05de\u05d5\u05d2\u05d1\u05dc\n - \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d7\u05d3\u05e9\u05d9\u05dd \u05dc\u05d0 \u05d9\u05d5\u05e4\u05e2\u05dc\u05d5 \u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05d5\u05e8\u05d9\u05d3/\u05de\u05e4\u05d9\u05e5 \u05d9\u05d5\u05ea\u05e8 ConfigView.label.priorityExtensions=\u05e2\u05d3\u05d9\u05e4\u05d5\u05ea \u05d2\u05d1\u05d5\u05d4\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea \u05dc\u05e7\u05d1\u05e6\u05d9\u05dd \u05d1\u05e2\u05dc\u05d9 \u05e1\u05d9\u05d5\u05de\u05ea\n\u05dc\u05d3\u05d5\u05d2\u05de\u05d0 : .txt;.nfo;.jpg ConfigView.section.transfer=\u05d4\u05e2\u05d1\u05e8\u05d4 ConfigView.label.maxuploads=\u05de\u05e1\u05e4\u05e8 \u05d4\u05e2\u05dc\u05d0\u05d5\u05ea \u05de\u05d9\u05e8\u05d1\u05d9 \u05dc\u05d8\u05d5\u05e8\u05e0\u05d8 ConfigView.label.maxuploadspeed=(\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05e2\u05dc\u05d0\u05d4 \u05de\u05d9\u05e8\u05d1\u05d9\u05ea (\u05db\u05d5\u05dc\u05dc\u05ea ConfigView.label.saveresumeinterval=\u05e2\u05d3\u05db\u05df \u05de\u05d9\u05d3\u05e2 \u05d4\u05de\u05e9\u05db\u05d4 \u05db\u05dc ConfigView.unlimited=\u05d1\u05dc\u05ea\u05d9-\u05de\u05d5\u05d2\u05d1\u05dc ConfigView.section.display=\u05ea\u05e6\u05d5\u05d2\u05d4 ConfigView.label.opendetails=\u05e4\u05ea\u05d7 \u05ea\u05e6\u05d5\u05d2\u05ea \u05de\u05d9\u05d3\u05e2 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea ConfigView.label.openbar=\u05e4\u05ea\u05d7 \u05d0\u05ea \u05ea\u05e6\u05d5\u05d2\u05ea \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea ConfigView.label.closetotray=\u05e1\u05d2\u05d5\u05e8 \u05de\u05de\u05d6\u05e2\u05e8 \u05dc\u05de\u05d2\u05e9 \u05de\u05e2\u05e8\u05db\u05ea ConfigView.label.minimizetotray=\u05de\u05d6\u05e2\u05e8 \u05de\u05de\u05d6\u05e2\u05e8\u05ea \u05dc\u05de\u05d2\u05e9 \u05de\u05e2\u05e8\u05db\u05ea ConfigView.section.general=\u05db\u05dc\u05dc\u05d9 ConfigView.section.start=\u05d4\u05e4\u05e2\u05dc\u05d4 ConfigView.label.showsplash=\u05d4\u05e6\u05d2 \u05de\u05e1\u05da \u05e4\u05ea\u05d9\u05d7\u05d4 ConfigView.label.autoupdate=\u05e4\u05ea\u05d7 \u05ea\u05d9\u05d1\u05ea \u05e9\u05d9\u05d3\u05e8\u05d5\u05d2 \u05db\u05e9\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d7\u05d3\u05e9\u05d4 \u05d9\u05d5\u05ea\u05e8 \u05d6\u05de\u05d9\u05e0\u05d4 ConfigView.label.openconsole=\u05e4\u05ea\u05d7 \u05d9\u05d5\u05de\u05df \u05d1\u05d4\u05e4\u05e2\u05dc\u05d4 ConfigView.label.openconfig=\u05e4\u05ea\u05d7 \u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05d1\u05d4\u05e4\u05e2\u05dc\u05d4 ConfigView.label.startminimized=\u05d4\u05ea\u05d7\u05dc \u05de\u05de\u05d5\u05d6\u05e2\u05e8 ConfigView.section.irc=Irc ConfigView.label.ircserver=\u05e9\u05e8\u05ea ConfigView.label.ircchannel=\u05e2\u05e8\u05d5\u05e5 ConfigView.label.irclogin=\u05db\u05d9\u05e0\u05d5\u05d9 ConfigView.section.security=\u05d0\u05d1\u05d8\u05d7\u05d4 ConfigView.label.password=\u05d4\u05d2\u05df \u05e2\u05dc \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05d1\u05d0\u05de\u05e6\u05e2\u05d5\u05ea \u05e1\u05d9\u05e1\u05de\u05d4 - \u05ea\u05ea\u05d1\u05e7\u05e9 \u05db\u05d0\u05e9\u05e8 \u05de\u05e4\u05e2\u05d9\u05dc\u05d9\u05dd \u05d0\u05ea \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05d5\u05db\u05d0\u05e9\u05e8 \u05e4\u05d5\u05ea\u05d7\u05d9\u05dd \u05de\u05de\u05d9\u05d6\u05e2\u05d5\u05e8 ConfigView.label.passwordconfirm=(\u05e1\u05d9\u05e1\u05de\u05d4 (\u05e1\u05d9\u05e1\u05de\u05d4 \u05e9\u05d5\u05d1 ConfigView.label.passwordmatch=\u05e1\u05d9\u05e1\u05de\u05d4 \u05de\u05d5\u05e4\u05e2\u05dc\u05ea : ConfigView.label.passwordmatchnone=\u05dc\u05d0 ConfigView.label.passwordmatchno=\u05dc\u05d0 / \u05e1\u05d9\u05e1\u05de\u05d4 \u05dc\u05d0 \u05ea\u05d5\u05d0\u05de\u05ea ConfigView.label.passwordmatchyes=\u05db\u05df ConfigView.button.save=\u05e9\u05de\u05d5\u05e8 ConfigView.title.short=\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea ConfigView.title.full=\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea ConsoleView.title.short=\u05d9\u05d5\u05de\u05df ConsoleView.title.full=\u05d9\u05d5\u05de\u05df FileItem.write=\u05db\u05ea\u05d9\u05d1\u05d4 FileItem.read=\u05e7\u05e8\u05d9\u05d0\u05d4 FileItem.normal=\u05e8\u05d2\u05d9\u05dc\u05d4 FileItem.high=\u05d2\u05d1\u05d5\u05d4\u05d4 FileItem.donotdownload=\u05d0\u05dc \u05ea\u05d5\u05e8\u05d9\u05d3 FilesView.name=\u05e9\u05dd FilesView.size=\u05d2\u05d5\u05d3\u05dc FilesView.done=\u05e1\u05d9\u05d9\u05dd FilesView.%=\u05d0\u05d7\u05d5\u05d6 FilesView.firstpiece=\u05de\u05e1\u05e4\u05e8 \u05d7\u05dc\u05e7 \u05e8\u05d0\u05e9\u05d5\u05df FilesView.numberofpieces=\u05de\u05e1\u05e4\u05e8 \u05d7\u05dc\u05e7\u05d9\u05dd FilesView.pieces=\u05d7\u05dc\u05e7\u05d9\u05dd FilesView.mode=\u05de\u05e6\u05d1 FilesView.priority=\u05e2\u05d3\u05d9\u05e4\u05d5\u05ea FilesView.menu.open=\u05e4\u05ea\u05d7 FilesView.menu.setpriority=\u05e7\u05d1\u05e2 \u05e2\u05d3\u05d9\u05e4\u05d5\u05ea FilesView.menu.setpriority.high=&\u05d2\u05d1\u05d5\u05d4\u05d4 FilesView.menu.setpriority.normal=&\u05e8\u05d2\u05d9\u05dc\u05d4 FilesView.menu.setpriority.skipped=&\u05d0\u05dc \u05ea\u05d5\u05e8\u05d9\u05d3 FilesView.title.short=\u05e7\u05d1\u05e6\u05d9\u05dd FilesView.title.full=\u05e7\u05d1\u05e6\u05d9\u05dd GeneralView.section.downloaded=\u05d9\u05e8\u05d3 GeneralView.label.status.file=\u05de\u05e6\u05d1 \u05e7\u05d5\u05d1\u05e5 GeneralView.label.status.pieces=\u05de\u05e6\u05d1 \u05d7\u05dc\u05e7\u05d9\u05dd GeneralView.section.availability=\u05d6\u05de\u05d9\u05e0\u05d5\u05ea GeneralView.label.status.pieces_available=\u05de\u05e6\u05d1 \u05d7\u05dc\u05e7\u05d9\u05dd GeneralView.section.transfer=\u05d4\u05e2\u05d1\u05e8\u05d4 GeneralView.section.info=\u05de\u05d9\u05d3\u05e2 GeneralView.title.short=\u05db\u05dc\u05dc\u05d9 GeneralView.title.full=\u05db\u05dc\u05dc\u05d9 GeneralView.label.timeelapsed=\u05d6\u05de\u05df \u05e9\u05e2\u05d1\u05e8 : GeneralView.label.remaining=\u05d6\u05de\u05df \u05e0\u05d5\u05ea\u05e8 : GeneralView.label.downloaded=\u05d9\u05e8\u05d3 : GeneralView.label.downloadspeed=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05d5\u05e8\u05d3\u05d4 : GeneralView.label.maxuploads=\u05de\u05e1\u05e4\u05e8 \u05d4\u05d5\u05e8\u05d3\u05d5\u05ea \u05de\u05d9\u05e8\u05d1\u05d9 : GeneralView.label.uploaded=\u05e2\u05dc\u05d4 : GeneralView.label.uploadspeed=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05e2\u05dc\u05d0\u05d4 : GeneralView.label.seeds=\u05de\u05e4\u05d9\u05e6\u05d9\u05dd : GeneralView.label.peers=\u05de\u05e9\u05ea\u05e4\u05d9\u05dd : GeneralView.label.totalspeed=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05db\u05d5\u05dc\u05dc\u05ea : GeneralView.label.totalspeed.tooltip=\u05d4\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05db\u05d5\u05dc\u05dc\u05ea \u05e9\u05dc \u05d4\u05e7\u05dc\u05d9\u05d9\u05e0\u05d8\u05d9\u05dd \u05d0\u05dc\u05d9\u05d4\u05dd \u05d0\u05ea\u05d4 \u05de\u05d7\u05d5\u05d1\u05e8. GeneralView.label.filename=\u05e9\u05dd : GeneralView.label.totalsize=\u05d2\u05d5\u05d3\u05dc \u05db\u05d5\u05dc\u05dc : GeneralView.label.savein=\u05e9\u05de\u05d5\u05e8 \u05d1 : GeneralView.label.hash=\u05d4\u05d0\u05e9 : GeneralView.label.numberofpieces=\u05de\u05e1\u05e4\u05e8 \u05d7\u05dc\u05e7\u05d9\u05dd : GeneralView.label.size=\u05d2\u05d5\u05d3\u05dc : GeneralView.label.tracker=\u05de\u05e6\u05d1 \u05d4\u05d8\u05e8\u05e7\u05e8 : GeneralView.label.updatein=\u05de\u05ea\u05e2\u05d3\u05db\u05df \u05ea\u05d5\u05da : GeneralView.label.trackerurl=\u05db\u05ea\u05d5\u05d1\u05ea \u05d4\u05d8\u05e8\u05e7\u05e8 : GeneralView.label.trackerurlupdate=\u05e2\u05d9\u05d3\u05db\u05d5\u05df \u05d9\u05d3\u05e0\u05d9 GeneralView.label.comment=\u05d4\u05e2\u05e8\u05d4 : ManagerItem.waiting=\u05de\u05de\u05ea\u05d9\u05df ManagerItem.allocating=\u05de\u05e7\u05e6\u05d4 \u05de\u05e7\u05d5\u05dd ManagerItem.checking=\u05d1\u05d5\u05d3\u05e7 ManagerItem.ready=\u05de\u05d5\u05db\u05df ManagerItem.downloading=\u05de\u05d5\u05e8\u05d9\u05d3 ManagerItem.seeding=\u05de\u05e4\u05d9\u05e5 ManagerItem.stopped=\u05e2\u05e6\u05e8 ManagerItem.error=\u05e9\u05d2\u05d9\u05d0\u05d4 ManagerItem.high=\u05d2\u05d1\u05d5\u05d4\u05d4 ManagerItem.low=\u05e0\u05de\u05d5\u05db\u05d4 MinimizedWindow.name=\u05e9\u05dd : PiecesView.#=\u05de\u05e1\u05e4\u05e8 PiecesView.size=\u05d2\u05d5\u05d3\u05dc PiecesView.numberofblocks=\u05de\u05e1\u05e4\u05e8 \u05d1\u05dc\u05d5\u05e7\u05d9\u05dd PiecesView.blocks=\u05d1\u05dc\u05d5\u05e7\u05d9\u05dd PiecesView.completed=\u05d4\u05e1\u05ea\u05d9\u05d9\u05dd PiecesView.availability=\u05d6\u05de\u05d9\u05e0\u05d5\u05ea PiecesView.title.short=\u05d7\u05dc\u05e7\u05d9\u05dd PiecesView.title.full=\u05d7\u05dc\u05e7\u05d9\u05dd SystemTray.tooltip.seeding=.\u05de\u05e4\u05d9\u05e5 %1, SystemTray.tooltip.downloading=.\u05de\u05d5\u05e8\u05d9\u05d3 %1, DownloadManager.error.filenotfound=\u05e7\u05d5\u05d1\u05e5 \u05dc\u05d0 \u05e0\u05de\u05e6\u05d0 DownloadManager.error.fileempty=\u05e7\u05d5\u05d1\u05e5 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 \u05e8\u05d9\u05e7 DownloadManager.error.filetoobig=\u05e7\u05d5\u05d1\u05e5 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 \u05d2\u05d3\u05d5\u05dc \u05de\u05d3\u05d9 DownloadManager.error.filewithouttorrentinfo=\u05dc\u05d0 \u05e0\u05de\u05e6\u05d0 \u05de\u05d9\u05d3\u05e2 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05d1\u05e7\u05d5\u05d1\u05e5 DownloadManager.error.unsupportedencoding=\u05e7\u05d9\u05d3\u05d5\u05d3 \u05dc\u05d0 \u05e0\u05ea\u05de\u05da DownloadManager.error.ioerror=\u05e9\u05d2\u05d9\u05d0\u05ea \u05e7\u05dc\u05d8/\u05e4\u05dc\u05d8 DownloadManager.error.sha1=(SHA1) \u05e9\u05d2\u05d9\u05d0\u05d4 - \u05dc\u05d0 \u05e7\u05d9\u05d9\u05dd \u05d0\u05dc\u05d2\u05d5\u05e8\u05d9\u05ea\u05dd \u05db\u05d6\u05d4 PeerManager.status.offline=\u05dc\u05d0 \u05de\u05e7\u05d5\u05df PeerManager.status.ok=\u05e2\u05d5\u05d1\u05d3 PeerManager.status.checking=\u05d1\u05d5\u05d3\u05e7 PeerManager.status.finished=\u05d4\u05e1\u05ea\u05d9\u05d9\u05dd PeerManager.status.finishedin=\u05d4\u05e1\u05ea\u05d9\u05d9\u05dd \u05ea\u05d5\u05da : MainWindow.upgrade.assistant=\u05d0\u05e9\u05e3 \u05d4\u05e9\u05d9\u05d3\u05e8\u05d5\u05d2 MainWindow.upgrade.newerversion=\u05d9\u05e9\u05e0\u05d4 \u05d2\u05d9\u05e8\u05e1\u05d4 \u05d7\u05d3\u05e9\u05d4 \u05d9\u05d5\u05ea\u05e8 \u05e9\u05dc \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05d6\u05de\u05d9\u05e0\u05d4 \u05dc\u05d4\u05d5\u05e8\u05d3\u05d4 MainWindow.upgrade.explanation=\u05d0\u05e9\u05e3 \u05d6\u05d4 \u05d9\u05d5\u05e8\u05d9\u05d3 \u05d0\u05ea \u05d4\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d4\u05d7\u05d3\u05e9\u05d4 \u05e9\u05dc \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05dc\u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05d4\u05ea\u05d5\u05db\u05e0\u05d4 \u05d5\u05d9\u05d0\u05ea\u05d7\u05dc \u05d0\u05d5\u05ea\u05d4 MainWindow.upgrade.explanation.manual=\u05d1\u05d0\u05e4\u05e9\u05e8\u05d5\u05ea\u05da \u05dc\u05e2\u05d3\u05db\u05df \u05d9\u05d3\u05e0\u05d9\u05ea \u05e2"\u05d9 \u05e1\u05d2\u05d9\u05e8\u05ea \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1, \u05d4\u05d5\u05e8\u05d3\u05ea \u05d4\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d4\u05d7\u05d3\u05e9\u05d4 \u05d5\u05d4\u05e4\u05e2\u05dc\u05d4 \u05de\u05d7\u05d3\u05e9 MainWindow.upgrade.step1=\u05e6\u05e2\u05d3 1: \u05d4\u05d5\u05e8\u05d3 \u05d0\u05ea \u05d4\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d4\u05d7\u05d3\u05e9\u05d4 MainWindow.upgrade.step2=\u05e6\u05e2\u05d3 2: \u05e1\u05d2\u05d5\u05e8 \u05d2\u05d9\u05e8\u05e1\u05d4 \u05d6\u05d5 \u05d5\u05d4\u05e4\u05e2\u05dc \u05de\u05d7\u05d3\u05e9 \u05d0\u05ea \u05d4\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d4\u05d7\u05d3\u05e9\u05d4 MainWindow.upgrade.hint1=\u05de\u05d9\u05d3\u05e2 :\t\u05dc\u05d7\u05d9\u05e6\u05d4 \u05e2\u05dc \u05e1\u05d9\u05d5\u05dd \u05de\u05d1\u05e6\u05e2\u05ea \u05d4\u05db\u05dc \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea MainWindow.upgrade.hint2=\u05de\u05d9\u05d3\u05e2:\t\u05d0\u05dd \u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05dc\u05e1\u05d2\u05d5\u05e8 \u05d0\u05ea \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05de\u05d0\u05d5\u05d7\u05e8 \u05d9\u05d5\u05ea\u05e8 \u05dc\u05d7\u05e5 \u05d1\u05d9\u05d8\u05d5\u05dc\n\t \u05d5\u05d4\u05d7\u05dc\u05e3 \u05d0\u05ea \u05d1\u05e7\u05d5\u05d1\u05e5Azureus2-new.jar \u05d1: Azureus2.jar \u05dc\u05d0\u05d7\u05e8 \u05d4\u05db\u05d9\u05d1\u05d5\u05d9. MainWindow.upgrade.error.downloading.hint=\u05e9\u05d2\u05d9\u05d0\u05d4:\t\u05dc\u05d0 \u05de\u05e6\u05dc\u05d9\u05d7 \u05dc\u05d4\u05d5\u05e8\u05d9\u05d3 \u05d2\u05d9\u05e8\u05e1\u05d4 \u05e2\u05d3\u05db\u05e0\u05d9\u05ea, \u05d0\u05e0\u05d0 \u05e2\u05d3\u05db\u05df \u05d9\u05d3\u05e0\u05d9\u05ea MainWindow.upgrade.section.info=\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d7\u05d3\u05e9\u05d4 \u05d6\u05de\u05d9\u05e0\u05d4 MainWindow.upgrade.section.manual=\u05e2\u05d9\u05d3\u05db\u05d5\u05df \u05d9\u05d3\u05e0\u05d9 MainWindow.upgrade.section.automatic=\u05e2\u05d9\u05d3\u05db\u05d5\u05df \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9 MainWindow.upgrade.tooltip.progressbar=\u05d4\u05ea\u05e7\u05d3\u05de\u05d5\u05ea \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 \u05de\u05d5\u05e6\u05d2\u05ea \u05db\u05d0\u05df Button.next=\u05d4\u05d1\u05d0 Button.finish=\u05e1\u05d9\u05d5\u05dd Button.cancel=\u05d1\u05d9\u05d8\u05d5\u05dc LocaleUtil.title=\u05d1\u05d7\u05e8 \u05e7\u05d9\u05d3\u05d5\u05d3 LocaleUtil.section.chooseencoding=\u05d1\u05d7\u05e8 \u05e7\u05d9\u05d3\u05d5\u05d3 \u05dc\u05e9\u05dd \u05d4\u05e7\u05d5\u05d1\u05e5 LocaleUtil.label.chooseencoding=\u05d0\u05e0\u05d0 \u05d1\u05d7\u05e8 \u05d0\u05ea \u05d4\u05e7\u05d9\u05d3\u05d5\u05d3 \u05d4\u05de\u05ea\u05d0\u05d9\u05dd \u05d1\u05d9\u05d5\u05ea\u05e8 LocaleUtil.label.hint.doubleclick=\u05de\u05d9\u05d3\u05e2: \u05dc\u05d7\u05d9\u05e6\u05d4 \u05db\u05e4\u05d5\u05dc\u05d4 \u05e2\u05dc \u05e9\u05d5\u05e8\u05d4 \u05d1\u05d5\u05d7\u05e8\u05ea \u05e7\u05d9\u05d3\u05d5\u05d3 \u05d5\u05e1\u05d5\u05d2\u05e8\u05ea \u05d0\u05ea \u05d4\u05ea\u05d9\u05d1\u05d4 LocaleUtil.label.checkbox.rememberdecision=\u05e9\u05de\u05d5\u05e8 \u05d1\u05d7\u05d9\u05e8\u05d4 \u05dc\u05e7\u05d1\u05e6\u05d9\u05dd \u05e0\u05d5\u05ea\u05e8\u05d9\u05dd LocaleUtil.column.encoding=\u05e7\u05d9\u05d3\u05d5\u05d3 IrcClient.connecting=\u05de\u05ea\u05d7\u05d1\u05e8 \u05dc : IrcClient.connected=\u05de\u05d7\u05d5\u05d1\u05e8 \u05dc : IrcClient.joining=\u05de\u05e6\u05d8\u05e8\u05e3 IrcClient.channel=\u05e2\u05e8\u05d5\u05e5 IrcClient.joined=\u05d4\u05e6\u05d8\u05e8\u05e3 IrcClient.error=\u05e9\u05d2\u05d9\u05d0\u05d4 IrcClient.hasjoined=\u05d4\u05e6\u05d8\u05e8\u05e3 IrcClient.haskicked=\u05d4\u05d5\u05e2\u05e3 IrcClient.hasleft=\u05e2\u05d6\u05d1 IrcClient.nowknown=\u05e2\u05ea\u05d4 \u05d9\u05d3\u05d5\u05e2 \u05db : IrcClient.topicforchannel=\u05de\u05d5\u05e9\u05d0 \u05dc\u05e2\u05e8\u05d5\u05e5 IrcClient.disconnected=\u05de\u05e0\u05d5\u05ea\u05e7 \u05de : IrcClient.noNick=\u05dc\u05d0 \u05e0\u05d1\u05d7\u05e8 \u05db\u05d9\u05e0\u05d5\u05d9. \u05d0\u05e0\u05d0 \u05d1\u05d7\u05e8 \u05d1\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea IrcView.actionnotsupported=\u05e4\u05e2\u05d5\u05dc\u05d4 \u05d6\u05d5 \u05d0\u05d9\u05e0\u05d4 \u05e0\u05ea\u05de\u05db\u05ea IrcView.clientsconnected=\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd IrcView.privateto=\u05dc : IrcView.privatefrom=\u05de : IrcView.noticefrom=\u05e9\u05d9\u05dd \u05dc\u05d1 : IrcView.help=Valid commands are :\n . /help : displays this message\n . /nick | /name : changes your name \n . /me action : sends an action \n . /msg nick message : sends a private message to \n . /r message : reply to last private message\n . /join #channel : changes current channel PasswordWindow.title=\u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05e0\u05e2\u05d5\u05dc\u05d4 PasswordWindow.passwordprotected=\u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05de\u05d5\u05d2\u05e0\u05ea \u05e2"\u05d9 \u05e1\u05d9\u05e1\u05de\u05d4\n\u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05d4\u05e6\u05d9\u05d2 \u05d0\u05ea \u05d7\u05dc\u05d5\u05df \u05d4\u05ea\u05d5\u05db\u05e0\u05d4 \u05d4\u05db\u05e0\u05e1 \u05db\u05d0\u05df \u05d0\u05ea \u05d4\u05e1\u05d9\u05e1\u05de\u05d4 : Button.ok=\u05d0\u05d9\u05e9\u05d5\u05e8 TrackerChangerWindow.title=\u05d4\u05d5\u05e1\u05e3 \u05d8\u05e8\u05e7\u05e8 TrackerChangerWindow.newtracker=\u05d4\u05db\u05e0\u05e1 \u05db\u05ea\u05d5\u05d1\u05ea \u05d8\u05e8\u05e7\u05e8 \u05d7\u05d3\u05e9\u05d4 PeersView.discarded=\u05de\u05ea\u05e2\u05dc\u05dd PeersView.discarded.info=\u05de\u05d9\u05d3\u05e2 \u05e9\u05e7\u05d9\u05d1\u05dc\u05ea \u05d0\u05e3 \u05e2\u05dc \u05e4\u05d9 \u05e9\u05d0\u05d9\u05df \u05dc\u05da \u05e6\u05d5\u05e8\u05da \u05d1\u05d5, \u05d4\u05de\u05d9\u05d3\u05e2 \u05e0\u05de\u05d7\u05e7 discarded=\u05d4\u05ea\u05e2\u05dc\u05dd MyTorrentsView.#=\u05de\u05e1\u05e4\u05e8 MyTorrentsView.menu.move=\u05d4\u05d6\u05d6 MyTorrentsView.menu.moveUp=\u05de\u05e2\u05dc\u05d4 MyTorrentsView.menu.moveDown=\u05de\u05d8\u05d4 GeneralView.label.hashfails=\u05db\u05d9\u05e9\u05dc\u05d5\u05df \u05d4\u05d0\u05e9 : GeneralView.label.shareRatio=\u05d9\u05d7\u05e1 \u05e9\u05d9\u05ea\u05d5\u05e3 : ConfigView.section.downloadManagement=\u05e0\u05d9\u05d4\u05d5\u05dc \u05d4\u05d5\u05e8\u05d3\u05d5\u05ea ConfigView.label.startRatioPeers=\u05d4\u05ea\u05d7\u05dc \u05dc\u05d4\u05e4\u05d9\u05e5 \u05db\u05e9\u05d0\u05e8 \u05d9\u05e9\u05e0\u05dd \u05e4\u05d7\u05d5\u05ea \u05de-1 \u05de\u05e4\u05d9\u05e6\u05d9\u05dd \u05dc : ConfigView.text.neverStop=\u05d0\u05e3 \u05e4\u05e2\u05dd \u05d0\u05dc \u05ea\u05e2\u05e6\u05d5\u05e8 ConfigView.text.neverStart=\u05d0\u05e3 \u05e4\u05e2\u05dd \u05d0\u05dc \u05ea\u05ea\u05d7\u05d9\u05dc ConfigView.text.peers=\u05de\u05e9\u05ea\u05e4\u05d9\u05dd ConfigView.label.checkOncompletion=\u05d1\u05d3\u05d5\u05e7 \u05e9\u05d5\u05d1 \u05ea\u05e7\u05d9\u05e0\u05d5\u05ea \u05d7\u05dc\u05e7\u05d9\u05dd \u05d1\u05e1\u05d9\u05d5\u05dd \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 wizard.title=\u05e6\u05d5\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8 wizard.previous=< \u05d7\u05d6\u05e8\u05d4 wizard.next=\u05d4\u05d1\u05d0 > wizard.finish=\u05e1\u05d9\u05d5\u05dd wizard.mode=\u05d8\u05e8\u05e7\u05e8 / \u05de\u05e6\u05d1 wizard.tracker=\u05d8\u05e8\u05e7\u05e8 : wizard.invalidurl=\u05db\u05ea\u05d5\u05d1\u05ea \u05e9\u05d2\u05d5\u05d9\u05d4 wizard.singlefile=\u05e7\u05d5\u05d1\u05e5 \u05d9\u05d7\u05d9\u05d3 wizard.singlefile.help=\u05e6\u05d5\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05de\u05e7\u05d5\u05d1\u05e5 \u05d9\u05d7\u05d9\u05d3 wizard.directory=\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 wizard.directory.help=\u05e6\u05d5\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05de\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 wizard.choosefile=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05d4\u05e7\u05d5\u05d1\u05e5 wizard.file=\u05e7\u05d5\u05d1\u05e5 : wizard.browse=..\u05e1\u05d9\u05d9\u05e8 wizard.choosedirectory=\u05d1\u05d7\u05e8 \u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 wizard.invalidfile=\u05e7\u05d5\u05d1\u05e5 \u05e9\u05d2\u05d5\u05d9 wizard.invaliddirectory=\u05e6\u05d9\u05e7\u05d9\u05d9\u05d4 \u05e9\u05d2\u05d5\u05d9\u05d4 wizard.torrentFile=\u05e7\u05d5\u05d1\u05e5 \u05d8\u05d5\u05e8\u05e0\u05d8 wizard.choosetorrent=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d4\u05d8\u05e8\u05e7\u05e8 \u05dc\u05d9\u05e6\u05d9\u05e8\u05d4 wizard.information=\u05de\u05d9\u05d3\u05e2 wizard.notimplemented=\u05e2\u05d3\u05d9\u05d9\u05df \u05dc\u05d0 \u05de\u05d9\u05d5\u05e9\u05dd wizard.progresstitle=\u05d9\u05e6\u05d9\u05e8\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d8\u05d5\u05e8\u05e0\u05d8 wizard.savingfile=..\u05e9\u05d5\u05de\u05e8 \u05e7\u05d5\u05d1\u05e5 wizard.filesaved=\u05e7\u05d5\u05d1\u05e5 \u05e0\u05e9\u05de\u05e8 wizard.close=\u05e1\u05d2\u05d5\u05e8 Torrent.create.progress.piecelength=\u05d0\u05d5\u05e8\u05da \u05d7\u05dc\u05e7 : Torrent.create.progress.piececount=\u05de\u05e1\u05e4\u05e8 \u05d7\u05dc\u05e7\u05d9\u05dd : Torrent.create.progress.totalfilesize=\u05d2\u05d5\u05d3\u05dc \u05e7\u05d5\u05d1\u05e5 \u05db\u05d5\u05dc\u05dc : Torrent.create.progress.totalfilecount=\u05de\u05e1\u05e4\u05e8 \u05e7\u05d1\u05e6\u05d9\u05dd \u05db\u05d5\u05dc\u05dc : Torrent.create.progress.parsingfiles=\u05de\u05e0\u05ea\u05d7 \u05e7\u05d1\u05e6\u05d9\u05dd Torrent.create.progress.hashing=\u05de\u05d7\u05dc\u05e7 \u05e7\u05d1\u05e6\u05d9\u05dd \u05dc\u05d4\u05d0\u05e9\u05d9\u05dd MainWindow.upgrade.downloadingfrom=\u05d4\u05d5\u05e8\u05d3 \u05de : MainWindow.menu.view.ipFilter=\u05de\u05e1\u05e0\u05e0\u05d9 IP ConfigView.section.ipfilter=\u05de\u05e1\u05e0\u05df \u05d0\u05d9\u05d9.\u05e4\u05d9. ConfigView.section.ipfilter.description=\u05ea\u05d9\u05d0\u05d5\u05e8 ConfigView.section.ipfilter.start=\u05d0\u05d9\u05d9.\u05e4\u05d9. \u05d4\u05ea\u05d7\u05dc\u05d4 ConfigView.section.ipfilter.end=\u05d0\u05d9\u05d9.\u05e4\u05d9. \u05e1\u05d9\u05d5\u05dd ConfigView.section.ipfilter.add=\u05d4\u05d5\u05e1\u05e3 ConfigView.section.ipfilter.remove=\u05d4\u05e1\u05e8 ConfigView.section.ipfilter.edit=\u05e2\u05e8\u05d5\u05da ConfigView.section.ipfilter.save=\u05e9\u05de\u05d5\u05e8 ConfigView.section.ipfilter.editFilter=\u05e2\u05e8\u05d5\u05da \u05de\u05e1\u05e0\u05df ConfigView.section.ipfilter.enable=\u05d0\u05e4\u05e9\u05e8 PeersView.menu.close=\u05e1\u05d2\u05d5\u05e8 seedmore.title=\u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 \u05d0\u05d9\u05e0\u05e0\u05d5 \u05de\u05d5\u05e4\u05e5 \u05d1\u05e6\u05d5\u05e8\u05d4 \u05de\u05e1\u05e4\u05e7\u05ea seedmore.shareratio=\u05d9\u05d7\u05e1 \u05d4\u05e9\u05d9\u05ea\u05d5\u05e3 \u05e9\u05dc\u05da \u05dc\u05d8\u05d5\u05e8\u05e0\u05d8 \u05d6\u05d4 \u05d4\u05d5\u05d0 seedmore.uploadmore=\u05d9\u05d7\u05e1 \u05e9\u05d9\u05ea\u05d5\u05e3 \u05e9\u05dc \u05e4\u05d7\u05d5\u05ea \u05de-100 \u05d0\u05d7\u05d5\u05d6 \u05d0\u05d9\u05e0\u05e0\u05d5 \u05d8\u05d5\u05d1 \u05e2\u05d1\u05d5\u05e8 \u05e8\u05e9\u05ea \u05d4\u05d1\u05d9\u05d8\u05d5\u05e8\u05e0\u05d8.\n\u05e2\u05dc\u05d9\u05da \u05dc\u05d4\u05e0\u05d9\u05d7 \u05dc\u05d8\u05d5\u05e8\u05e0\u05d8 \u05dc\u05d4\u05e4\u05d9\u05e5 \u05e2\u05d5\u05d3\n\u05d4\u05d0\u05dd \u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05dc\u05d4\u05de\u05e9\u05d9\u05da ? ConfigView.label.showpopuponclose=\u05d4\u05e6\u05d2 \u05ea\u05d9\u05d1\u05ea \u05d0\u05d9\u05e9\u05d5\u05e8 \u05db\u05d0\u05e9\u05e8 \u05e2\u05d5\u05e6\u05e8\u05d9\u05dd\n\u05d4\u05e4\u05e6\u05ea \u05e7\u05d5\u05d1\u05e5 \u05e2\u05dd \u05d9\u05d7\u05e1 \u05e9\u05d9\u05ea\u05d5\u05e3 \u05e7\u05d8\u05df \u05de-1 ConfigView.label.startNumSeeds=\n\u05d4\u05ea\u05d7\u05dc \u05dc\u05d4\u05e4\u05d9\u05e5 \u05d0\u05dd \u05d9\u05e9\u05e0\u05dd \u05e4\u05d7\u05d5\u05ea \u05de:\n- \u05e2\u05d5\u05e7\u05e3 \u05d0\u05ea \u05e9\u05d0\u05e8 \u05d4\u05db\u05dc\u05dc\u05d9\u05dd ConfigView.label.seeds=\u05de\u05e4\u05d9\u05e6\u05d9\u05dd ConfigView.section.seeding=\u05d4\u05e4\u05e6\u05d4 MyTorrentsView.menu.removeand=\u05d4\u05e1\u05e8 \u05d5.. MyTorrentsView.menu.removeand.deletetorrent=\u05de\u05d7\u05e7 \u05d8\u05d5\u05e8\u05e0\u05d8 MyTorrentsView.menu.removeand.deletedata=\u05de\u05d7\u05e7 \u05de\u05d9\u05d3\u05e2 MyTorrentsView.menu.removeand.deleteboth=\u05de\u05d7\u05e7 \u05d4\u05db\u05dc deletedata.title=!!! \u05d6\u05d4\u05d9\u05e8\u05d5\u05ea !!! deletedata.message1=:\u05d0\u05ea\u05d4 \u05e2\u05d5\u05de\u05d3 \u05dc\u05de\u05d7\u05d5\u05e7 \u05d0\u05ea \u05d4\u05de\u05d9\u05d3\u05e2 \u05de MainWindow.menu.file.configure=\u05d0\u05e9\u05e3 \u05d4\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea configureWizard.title=\u05d0\u05e9\u05e3 \u05d4\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea configureWizard.welcome.title=\u05d1\u05e8\u05d5\u05db\u05d9\u05dd \u05d4\u05d1\u05d0\u05d9\u05dd \u05dc\u05d0\u05e9\u05e3 \u05d4\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05e9\u05dc \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 configureWizard.welcome.message=\u05d0\u05e9\u05e3 \u05d6\u05d4 \u05d9\u05e1\u05d9\u05d9\u05e2 \u05dc\u05da \u05dc\u05d4\u05d2\u05d3\u05d9\u05e8 \u05d0\u05ea \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05dc\u05e9\u05d9\u05de\u05d5\u05e9 \u05d4\u05e0\u05e4\u05d5\u05e5 \u05d1\u05d9\u05d5\u05ea\u05e8. \u05d0\u05ea\u05d4 \u05d9\u05db\u05d5\u05dc \u05dc\u05e9\u05e0\u05d5\u05ea \u05dc\u05e2\u05d5\u05de\u05e7 \u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05d0\u05dc\u05d4 \u05d1\u05ea\u05e4\u05e8\u05d9\u05d8 \u05e4\u05e2\u05d5\u05dc\u05d5\u05ea>\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea. configureWizard.transfer.title=\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05d4\u05e2\u05d1\u05e8\u05d4 \u05d5\u05d7\u05d9\u05d1\u05d5\u05e8 configureWizard.transfer.hint=.\u05de\u05d9\u05d3\u05e2 : \u05d4\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05de\u05d5\u05de\u05dc\u05e6\u05ea \u05d4\u05d9\u05d0 \u05e7\u05e6\u05ea \u05d9\u05d5\u05ea\u05e8 \u05e0\u05de\u05d5\u05db\u05d4 \u05de\u05d4\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05de\u05d9\u05e8\u05d1\u05d9\u05ea \u05e9\u05dc \u05d4\u05d7\u05d9\u05d1\u05d5\u05e8 \u05e9\u05dc\u05da configureWizard.transfer.message=\u05d0\u05e0\u05d0 \u05d1\u05d7\u05e8 \u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d7\u05d9\u05d1\u05d5\u05e8. \u05d4\u05ea\u05d7\u05e9\u05d1 \u05d1\u05db\u05da \u05e9\u05d0\u05dd \u05dc\u05d0 \u05ea\u05d0\u05e4\u05e9\u05e8 \u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05e2\u05dc\u05d0\u05d4 \u05de\u05e1\u05e4\u05e7\u05ea \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 \u05e9\u05dc\u05da \u05ea\u05d4\u05d9\u05d4 \u05d0\u05d9\u05d8\u05d9\u05ea \u05d9\u05d5\u05ea\u05e8. \u05d4\u05d9\u05d5\u05ea \u05d5\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05d4\u05e2\u05dc\u05d0\u05d4 \u05de\u05d7\u05d5\u05e9\u05d1\u05ea \u05dc\u05db\u05dc \u05d8\u05d5\u05e8\u05e0\u05d8 \u05d1\u05e0\u05e4\u05e8\u05d3, \u05d4\u05d5\u05e8\u05d3\u05ea \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05e8\u05d1\u05d9\u05dd \u05d1\u05d1\u05ea \u05d0\u05d7\u05ea \u05d9\u05db\u05d5\u05dc\u05d4 \u05dc\u05d2\u05e8\u05d5\u05dd \u05d2\u05dd \u05db\u05df \u05dc\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05d5\u05e8\u05d3\u05d4 \u05d0\u05d9\u05d8\u05d9\u05ea. \u05d0\u05e0\u05d5 \u05de\u05de\u05dc\u05d9\u05e6\u05d9\u05dd \u05e2\u05dc \u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05e2\u05dc\u05d0\u05d4 \u05de\u05d9\u05e0\u05d9\u05de\u05dc\u05d9\u05ea \u05e9\u05dc 5 \u05e7"\u05d1/\u05e9\u05e0\u05d9\u05d4. \u05db\u05db\u05dc \u05e9\u05ea\u05e2\u05dc\u05d4 \u05de\u05d4\u05e8 \u05d9\u05d5\u05ea\u05e8, \u05db\u05da \u05ea\u05d5\u05e8\u05d9\u05d3 \u05de\u05d4\u05e8 \u05d9\u05d5\u05ea\u05e8 (\u05d1\u05d4\u05ea\u05d7\u05e9\u05d1 \u05d1\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8) configureWizard.transfer.connection=\u05e1\u05d5\u05d2 \u05d7\u05d9\u05d1\u05d5\u05e8 configureWizard.transfer.connection.0=\u05d4\u05ea\u05d0\u05de\u05d4 \u05d0\u05d9\u05e9\u05d9\u05ea configureWizard.transfer.connection.1=\u05de\u05d5\u05d3\u05dd configureWizard.transfer.connection.2=ADSL / \u05d4\u05e2\u05dc\u05d0\u05d4 128 configureWizard.transfer.connection.3=ADSL / \u05d4\u05e2\u05dc\u05d0\u05d4 256 configureWizard.transfer.connection.4=ADSL / \u05d4\u05e2\u05dc\u05d0\u05d4 384 configureWizard.transfer.connection.5=ADSL / \u05d4\u05e2\u05dc\u05d0\u05d4 512 configureWizard.transfer.connection.6=ADSL / \u05d4\u05e2\u05dc\u05d0\u05d4 768 configureWizard.transfer.connection.7=ADSL / \u05d4\u05e2\u05dc\u05d0\u05d4 1024 configureWizard.transfer.maxUpSpeed=(\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05de\u05d9\u05e8\u05d1\u05d9\u05ea (\u05e7"\u05d1/\u05e9\u05e0\u05d9\u05d4 configureWizard.transfer.maxActiveTorrents=\u05de\u05e7\u05e1\u05d9\u05de\u05d5\u05dd \u05e4\u05e2\u05d9\u05dc\u05d9\u05dd configureWizard.transfer.maxDownloads=\u05de\u05e1\u05e4\u05e8 \u05d4\u05d5\u05e8\u05d3\u05d5\u05ea \u05de\u05e7\u05e1\u05d9\u05de\u05dc\u05d9 configureWizard.transfer.maxUploadsPerTorrent=\u05de\u05e1\u05e4\u05e8 \u05d4\u05e2\u05dc\u05d0\u05d5\u05ea \u05dc\u05d8\u05d5\u05e8\u05e0\u05d8 configureWizard.nat.message=\u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05d4\u05e4\u05d9\u05e7 \u05d0\u05ea \u05d4\u05de\u05d9\u05e8\u05d1 \u05de\u05d1\u05d9\u05d8\u05d5\u05e8\u05e0\u05d8, \u05de\u05d5\u05de\u05dc\u05e5 \u05d1\u05d9\u05d5\u05ea\u05e8 \u05e9\u05dc\u05ea\u05d5\u05db\u05e0\u05d4 \u05ea\u05d4\u05d9\u05d4 \u05d2\u05d9\u05e9\u05d4 \u05de\u05dc\u05d0\u05d4 \u05dc\u05d0\u05d9\u05e0\u05d8\u05e8\u05e0\u05d8. .\u05e4\u05d5\u05e8\u05d8 \u05d1\u05e8\u05d9\u05e8\u05ea \u05d4\u05de\u05d7\u05d3\u05dc \u05e9\u05dc \u05d1\u05d9\u05d8\u05d5\u05e8\u05e0\u05d8 \u05d4\u05d5\u05d0 6881. \u05db\u05dc\u05d9 \u05d6\u05d4 \u05de\u05d0\u05e4\u05e9\u05e8 \u05dc\u05da \u05dc\u05d1\u05d3\u05d5\u05e7 \u05d5/\u05d0\u05d5 \u05dc\u05e9\u05e0\u05d5\u05ea \u05e4\u05d5\u05e8\u05d8 \u05d6\u05d4 configureWizard.nat.test=\u05d1\u05d3\u05d9\u05e7\u05d4 configureWizard.nat.testing=\u05e4\u05d5\u05e8\u05d8 \u05dc\u05d1\u05d3\u05d9\u05e7\u05d4 configureWizard.nat.ok=\u05d1\u05e1\u05d3\u05e8 configureWizard.nat.ko=\u05e9\u05d2\u05d9\u05d0\u05ea \u05d7\u05d5\u05de\u05ea-\u05d0\u05e9 configureWizard.nat.unable=\u05dc\u05d0 \u05de\u05e1\u05d5\u05d2\u05dc \u05dc\u05d1\u05d3\u05d5\u05e7 configureWizard.file.title=\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd / \u05e7\u05d1\u05e6\u05d9\u05dd configureWizard.file.message1=\u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05ea\u05e9\u05de\u05d5\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05e9\u05e0\u05e4\u05ea\u05d7\u05d5 \u05d1\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 \u05de\u05e1\u05d5\u05d9\u05de\u05ea \u05d1\u05d0\u05e4\u05e9\u05e8\u05d5\u05ea\u05da \u05dc\u05d1\u05d7\u05d5\u05e8 \u05d0\u05ea \u05d4\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 \u05db\u05d0\u05df : configureWizard.file.path=\u05e0\u05ea\u05d9\u05d1 configureWizard.file.browse=\u05e1\u05d9\u05d9\u05e8 configureWizard.file.message2=\u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05de\u05e1\u05d5\u05d2\u05dc\u05ea \u05dc\u05d4\u05de\u05e9\u05d9\u05da \u05d0\u05ea \u05e4\u05e2\u05d5\u05dc\u05ea \u05d4\u05e7\u05d1\u05e6\u05d9\u05dd \u05e9\u05dc\u05da \u05de\u05d9\u05d9\u05d3\u05d9\u05ea, \u05e2"\u05d9 \u05d4\u05d5\u05e1\u05e4\u05d4 \u05e9\u05dc \u05de\u05d9\u05d3\u05e2 \u05d4\u05de\u05e9\u05db\u05d4 \u05dc\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05e9\u05dc\u05da. \u05d4\u05e9\u05d9\u05de\u05d5\u05e9 \u05d1\u05d0\u05e4\u05e9\u05e8\u05d5\u05ea \u05d6\u05d5 \u05d2\u05dd \u05de\u05de\u05e9\u05d9\u05da \u05d7\u05dc\u05e7\u05d9 \u05d4\u05d5\u05e8\u05d3\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05d2\u05de\u05d5\u05e8\u05d9\u05dd configureWizard.file.fastResume=\u05d0\u05e4\u05e9\u05e8 \u05d4\u05de\u05e9\u05db\u05d4 \u05de\u05d4\u05d9\u05e8\u05d4 configureWizard.file.invalidPath=\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 \u05e9\u05d2\u05d5\u05d9\u05d4 configureWizard.finish.title=\u05d4\u05e1\u05ea\u05d9\u05d9\u05dd configureWizard.finish.message=!\u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05de\u05d5\u05d2\u05d3\u05e8\u05ea \u05e2\u05ea\u05d4, \u05ea\u05d4\u05e0\u05d5 wizard.close.confirmation=\u05d0\u05d9\u05e9\u05d5\u05e8 wizard.close.message=\u05d4\u05d0\u05dd \u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05e9\u05d4\u05d0\u05e9\u05e3 \u05d9\u05d5\u05e4\u05d9\u05e2 \u05d1\u05d4\u05e4\u05e2\u05dc\u05d4 \u05d4\u05d1\u05d0\u05d4? exportTorrentWizard.title=\u05d9\u05d9\u05e6\u05d0 \u05d8\u05d5\u05e8\u05e0\u05d8 exportTorrentWizard.torrentfile.title=\u05d1\u05d7\u05d9\u05e8\u05ea \u05d8\u05d5\u05e8\u05e0\u05d8 \u05dc\u05e7\u05dc\u05d8 exportTorrentWizard.torrentfile.message=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 \u05dc\u05d9\u05d9\u05e6\u05d5\u05d0 exportTorrentWizard.torrentfile.path=\u05e0\u05ea\u05d9\u05d1 exportTorrentWizard.torrentfile.browse=\u05e1\u05d9\u05d9\u05e8 exportTorrentWizard.torrentfile.invalidPath=\u05e7\u05d5\u05d1\u05e5 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05e9\u05d2\u05d5\u05d9 exportTorrentWizard.exportfile.title=\u05d1\u05d7\u05d9\u05e8\u05ea \u05e7\u05d5\u05d1\u05e5 \u05dc\u05d9\u05d9\u05e6\u05d5\u05d0 exportTorrentWizard.exportfile.message=\u05d4\u05db\u05e0\u05e1 \u05e9\u05dd \u05e7\u05d5\u05d1\u05e5 \u05dc\u05d9\u05d9\u05e6\u05d0 \u05d0\u05dc\u05d9\u05d5 exportTorrentWizard.exportfile.path=\u05e0\u05ea\u05d9\u05d1 exportTorrentWizard.exportfile.browse=\u05e1\u05d9\u05d9\u05e8 exportTorrentWizard.exportfile.invalidPath=\u05e7\u05d5\u05d1\u05e5 \u05d9\u05d9\u05e6\u05d5\u05d0 \u05e9\u05d2\u05d5\u05d9 exportTorrentWizard.finish.title=\u05d4\u05e1\u05ea\u05d9\u05d9\u05dd exportTorrentWizard.finish.message=\u05d4\u05d9\u05d9\u05e6\u05d5\u05d0 \u05d4\u05e1\u05ea\u05d9\u05d9\u05dd \u05d1\u05d4\u05e6\u05dc\u05d7\u05d4 exportTorrentWizard.process.inputfilebad.title=\u05e7\u05d5\u05d1\u05e5 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05e9\u05d2\u05d5\u05d9 exportTorrentWizard.process.inputfilebad.message=:\u05d4\u05ea\u05e8\u05d7\u05e9\u05d4 \u05e9\u05d2\u05d9\u05d0\u05d4 \u05d1\u05de\u05d4\u05dc\u05da \u05d4\u05d2\u05d9\u05e9\u05d4 \u05dc\u05e7\u05d5\u05d1\u05e5 \u05d4\u05e7\u05dc\u05d8 exportTorrentWizard.process.outputfileexists.title=\u05d4\u05e7\u05d5\u05d1\u05e5 \u05e7\u05d9\u05d9\u05dd \u05db\u05d1\u05e8 exportTorrentWizard.process.outputfileexists.message=?\u05e7\u05d5\u05d1\u05e5 \u05d4\u05d9\u05e2\u05d3 \u05e7\u05d9\u05d9\u05dd - \u05dc\u05d4\u05d7\u05dc\u05d9\u05e3 exportTorrentWizard.process.torrentfail.title=\u05e7\u05e8\u05d9\u05d0\u05ea \u05d8\u05d5\u05e8\u05e0\u05d8 \u05e0\u05db\u05e9\u05dc\u05d4 exportTorrentWizard.process.exportfail.title=\u05d9\u05d9\u05e6\u05d5\u05d0 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 \u05e0\u05db\u05e9\u05dc exportTorrentWizard.process.unknownfail.title=\u05e9\u05d2\u05d9\u05d0\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05e6\u05e4\u05d5\u05d9\u05d4 importTorrentWizard.title=\u05d9\u05d9\u05d1\u05d0 \u05d8\u05d5\u05e8\u05e0\u05d8 importTorrentWizard.torrentfile.title=\u05d1\u05d7\u05d9\u05e8\u05ea \u05d8\u05d5\u05e8\u05e0\u05d8 \u05e7\u05dc\u05d8 importTorrentWizard.torrentfile.message=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 \u05dc\u05d9\u05d9\u05d1\u05d5\u05d0 \u05d0\u05dc\u05d9\u05d5 importTorrentWizard.torrentfile.path=\u05e0\u05ea\u05d9\u05d1 importTorrentWizard.torrentfile.browse=\u05e1\u05d9\u05d9\u05e8 importTorrentWizard.torrentfile.invalidPath=\u05e7\u05d5\u05d1\u05e5 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05e9\u05d2\u05d5\u05d9 importTorrentWizard.importfile.title=\u05d1\u05d7\u05d9\u05e8\u05ea \u05e7\u05d5\u05d1\u05e5 \u05dc\u05d9\u05d9\u05d1\u05d5\u05d0 importTorrentWizard.importfile.message=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05d4\u05e7\u05d5\u05d1\u05e5 \u05dc\u05d9\u05d9\u05d1\u05d5\u05d0 importTorrentWizard.importfile.path=\u05e0\u05ea\u05d9\u05d1 importTorrentWizard.importfile.browse=\u05e1\u05d9\u05d9\u05e8 importTorrentWizard.importfile.invalidPath=\u05e7\u05d5\u05d1\u05e5 \u05de\u05d9\u05d5\u05d1\u05d0 \u05e9\u05d2\u05d5\u05d9 importTorrentWizard.finish.title=\u05d4\u05e1\u05ea\u05d9\u05d9\u05dd importTorrentWizard.finish.message=\u05d4\u05d9\u05d9\u05d1\u05d5\u05d0 \u05d4\u05e1\u05ea\u05d9\u05d9\u05dd \u05d1\u05d4\u05e6\u05dc\u05d7\u05d4 importTorrentWizard.process.inputfilebad.title=\u05e9\u05dd \u05e7\u05d5\u05d1\u05e5 \u05e9\u05d2\u05d5\u05d9 importTorrentWizard.process.inputfilebad.message=\u05d4\u05ea\u05e8\u05d7\u05e9\u05d4 \u05e9\u05d2\u05d9\u05d0\u05d4 \u05d1\u05de\u05d4\u05dc\u05da \u05d4\u05d2\u05d9\u05e9\u05d4 \u05dc\u05e7\u05d5\u05d1\u05e5 \u05d4\u05e7\u05dc\u05d8 : importTorrentWizard.process.outputfileexists.title=\u05e7\u05d5\u05d1\u05e5 \u05e7\u05d9\u05d9\u05dd importTorrentWizard.process.outputfileexists.message=?\u05e7\u05d5\u05d1\u05e5 \u05d9\u05e2\u05d3 \u05e7\u05d9\u05d9\u05dd - \u05d4\u05d0\u05dd \u05dc\u05d4\u05d7\u05dc\u05d9\u05e3 importTorrentWizard.process.torrentfail.title=\u05db\u05ea\u05d9\u05d1\u05ea \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 \u05e0\u05db\u05e9\u05dc\u05d4 importTorrentWizard.process.importfail.title=\u05d9\u05d9\u05d1\u05d5\u05d0 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05e0\u05db\u05e9\u05dc importTorrentWizard.process.unknownfail.title=\u05e9\u05d2\u05d9\u05d0\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05e6\u05e4\u05d5\u05d9\u05d4 ConfigView.label.bindip=\u05e9\u05d9\u05d9\u05da \u05dc\u05db\u05ea\u05d5\u05d1\u05ea \u05d0\u05d9\u05d9.\u05e4\u05d9. \u05de\u05e7\u05d5\u05de\u05d9\u05ea or interface ConfigView.label.zeronewfiles=\u05d4\u05e7\u05e6\u05d4 \u05de\u05e7\u05d5\u05dd \u05d5\u05d0\u05e4\u05e1 \u05e7\u05d1\u05e6\u05d9\u05dd \u05d7\u05d3\u05e9\u05d9\u05dd \u05d1\u05e9\u05e2\u05ea \u05d4\u05d9\u05e6\u05d9\u05e8\u05d4 ConfigView.label.zeronewfiles.tooltip=\u05de\u05e7\u05d8\u05d9\u05df \u05d0\u05ea \u05e4\u05d9\u05e6\u05d5\u05dc \u05d4\u05db\u05d5\u05e0\u05df ConfigView.section.stats=\u05e1\u05d8\u05d8\u05d9\u05e1\u05d8\u05d9\u05e7\u05d4 ConfigView.section.stats.enable=\u05d0\u05e4\u05e9\u05e8 ConfigView.section.stats.defaultsavepath=\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 \u05dc\u05e9\u05de\u05d9\u05e8\u05ea \u05e1\u05d8\u05d8\u05d9\u05e1\u05d8\u05d9\u05e7\u05d4 ConfigView.section.stats.choosedefaultsavepath=\u05d0\u05e0\u05d0 \u05d1\u05d7\u05e8 \u05d0\u05ea \u05d4\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 \u05dc\u05e9\u05de\u05d9\u05e8\u05ea \u05d4\u05e1\u05d8\u05d8\u05d9\u05e1\u05d8\u05d9\u05e7\u05d4 ConfigView.section.stats.savefreq=\u05ea\u05d3\u05d9\u05e8\u05d5\u05ea \u05e9\u05de\u05d9\u05e8\u05d4 ConfigView.section.stats.minutes=\u05d3\u05e7\u05d5\u05ea ConfigView.section.stats.hours=\u05e9\u05e2\u05d5\u05ea ConfigView.section.stats.seconds=\u05e9\u05e0\u05d9\u05d5\u05ea ConfigView.section.stats.savefile=\u05e9\u05dd \u05e7\u05d5\u05d1\u05e5 \u05e1\u05d8\u05d8\u05d9\u05e1\u05d8\u05d9\u05e7\u05d4 MyTorrentsView.menu.export=\u05d9\u05d9\u05e6\u05d0 MyTorrentsView.menu.host=\u05d0\u05e8\u05d7.. ManagerItem.finishing=\u05de\u05e1\u05d9\u05d9\u05dd ConfigView.dialog.choosedefaulttorrentpath=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05d1\u05e8\u05d9\u05e8\u05ea \u05d4\u05de\u05d7\u05d3\u05dc \u05dc\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd ConfigView.dialog.choosemovepath=\u05d1\u05d7\u05e8 \u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc \u05dc\u05d4\u05e2\u05d1\u05d9\u05e8 \u05d0\u05dc\u05d9\u05d4 ConfigView.label.movecompleted=\u05d4\u05e2\u05d1\u05e8 \u05e7\u05d1\u05e6\u05d9\u05dd \u05e9\u05d4\u05e1\u05ea\u05d9\u05d9\u05de\u05d5 ConfigView.label.savetorrents=\u05e9\u05de\u05d5\u05e8 \u05e7\u05d1\u05e6\u05d9 \u05d8\u05d5\u05e8\u05e0\u05d8 MainWindow.menu.view.mytracker=\u05d4\u05d8\u05e8\u05e7\u05e8 \u05e9\u05dc\u05d9 MyTrackerView.title.full=\u05d4\u05d8\u05e8\u05e7\u05e8 \u05e9\u05dc\u05d9 MyTrackerView.name=\u05e9\u05dd MyTrackerView.tracker=\u05d8\u05e8\u05e7\u05e8 MyTrackerView.status=\u05de\u05e6\u05d1 MyTrackerView.status.started=\u05e2\u05d5\u05d1\u05d3 MyTrackerView.status.stopped=\u05e2\u05e6\u05e8 MyTrackerView.peers=\u05de\u05e9\u05ea\u05e4\u05d9\u05dd MyTrackerView.seeds=\u05de\u05e4\u05d9\u05e6\u05d9\u05dd MyTrackerView.announces=\u05d4\u05db\u05e8\u05d6\u05d5\u05ea MyTrackerView.uploaded=\u05e2\u05dc\u05d4 MyTrackerView.downloaded=\u05d9\u05e8\u05d3 MyTrackerView.left=\u05e0\u05d5\u05ea\u05e8 ConfigView.section.style=\u05de\u05de\u05e9\u05e7 ConfigView.section.style.useCustomTabs=\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05db\u05e8\u05d8\u05d9\u05e1\u05d9\u05d5\u05ea \u05d4\u05e0\u05d9\u05ea\u05e0\u05d5\u05ea \u05dc\u05e1\u05d2\u05d9\u05e8\u05d4 (\u05d3\u05e8\u05d5\u05e9\u05d4 \u05d4\u05e4\u05e2\u05dc\u05d4 \u05de\u05d7\u05d3\u05e9) MainWindow.menu.view.plugins=\u05ea\u05d5\u05e1\u05e4\u05d5\u05ea fileDownloadWindow.saveTorrentIn=:\u05e9\u05de\u05d5\u05e8 \u05e7\u05d5\u05d1\u05e5 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05d1 fileDownloadWindow.title=\u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 - \u05de\u05d5\u05e8\u05d9\u05d3 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd fileDownloadWindow.downloading=:\u05de\u05d5\u05e8\u05d9\u05d3 \u05de fileDownloadWindow.status=:\u05de\u05e6\u05d1 fileDownloadWindow.state_initializing=\u05de\u05d0\u05ea\u05d7\u05dc fileDownloadWindow.state_downloading=\u05de\u05d5\u05e8\u05d9\u05d3 fileDownloadWindow.state_error=:\u05e9\u05d2\u05d9\u05d0\u05d4 MainWindow.menu.file.open.url=\u05db\u05ea\u05d5\u05d1\u05ea openUrl.title=\u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 - \u05e4\u05ea\u05d7 \u05db\u05ea\u05d5\u05d1\u05ea openUrl.url=\u05db\u05ea\u05d5\u05d1\u05ea : MyTorrentsView.menu.host.error.title=\u05d0\u05d9\u05e8\u05d5\u05d7 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05e0\u05db\u05e9\u05dc MyTorrentsView.menu.host.error.message=\u05d4\u05d8\u05e2\u05d5\u05ea \u05d4\u05d1\u05d0\u05d4 \u05d4\u05ea\u05e8\u05d7\u05e9\u05d4 \u05d1\u05de\u05d4\u05dc\u05da \u05d0\u05d9\u05e8\u05d5\u05d7 \u05d4\u05d8\u05d5\u05e8\u05d8\u05e0 ConfigView.section.tracker=\u05d8\u05e8\u05e7\u05e8 ConfigView.section.tracker.ip=\u05db\u05ea\u05d5\u05d1\u05ea \u05d7\u05d9\u05e6\u05d5\u05e0\u05d9\u05ea \u05e9\u05dc \u05d8\u05e8\u05e7\u05e8 ConfigView.section.style.enableXPStyle=(\u05e0\u05d3\u05e8\u05e9 \u05d0\u05d9\u05ea\u05d7\u05d5\u05dc) XP \u05d0\u05e4\u05e9\u05e8 \u05de\u05e8\u05d0\u05d4 ConfigView.section.tracker.checkip=\u05d1\u05d3\u05d5\u05e7 \u05db\u05ea\u05d5\u05d1\u05ea.. ipCheckerWizard.title=\u05d0\u05e9\u05e3 \u05d1\u05d3\u05d9\u05e7\u05ea \u05d0\u05d9\u05d9.\u05e4\u05d9. ipCheckerWizard.service=\u05e9\u05d9\u05e8\u05d5\u05ea ipCheckerWizard.chooseService=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05e9\u05d9\u05e8\u05d5\u05ea \u05d1\u05d3\u05d9\u05e7\u05ea \u05d4\u05d0\u05d9\u05d9.\u05e4\u05d9. \u05de\u05d4\u05e8\u05e9\u05d9\u05de\u05d4 \u05d4\u05d1\u05d0\u05d4 ipCheckerWizard.service.description=\u05ea\u05d9\u05d0\u05d5\u05e8 : ipCheckerWizard.service.url=\u05e7\u05d9\u05e9\u05d5\u05e8 : ipCheckerWizard.progresstitle=\u05d1\u05d5\u05d3\u05e7 \u05d0\u05d9\u05d9.\u05e4\u05d9. ipCheckerWizard.checkComplete=\u05d0\u05d9\u05d9.\u05e4\u05d9. \u05e9\u05d4\u05e1\u05ea\u05d9\u05d9\u05dd : ipCheckerWizard.checkFailed=\u05e0\u05db\u05e9\u05dc, \u05e1\u05d9\u05d1\u05d4 : wizard.tracker.local=\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05d8\u05e8\u05e7\u05e8 \u05d4\u05de\u05e9\u05d5\u05dc\u05d1 \u05d1\u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 wizard.tracker.external=\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05d8\u05e8\u05e7\u05e8 \u05d7\u05d9\u05e6\u05d5\u05e0\u05d9 wizard.tracker.howToLocal=\t'\u05e0\u05d9\u05ea\u05df \u05dc\u05d0\u05e4\u05e9\u05e8 \u05d6\u05d0\u05ea \u05d1\u05ea\u05e4\u05e8\u05d9\u05d8 '\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea wizard.announceUrl=\u05db\u05ea\u05d5\u05d1\u05ea \u05d4\u05d4\u05db\u05e8\u05d6\u05d4 IPChecker.external.httpinvalidresponse=\u05e9\u05d2\u05d5\u05d9\u05d4 HTTP \u05ea\u05d2\u05d5\u05d1\u05ea IPChecker.external.loadingwebpage=\u05d8\u05d5\u05e2\u05df \u05d3\u05e3 \u05d0\u05d9\u05e0\u05d8\u05e8\u05e0\u05d8 IPChecker.external.analysingresponse=\u05de\u05e0\u05ea\u05d7 \u05ea\u05d2\u05d5\u05d1\u05d4 IPChecker.external.addressextracted=\u05db\u05ea\u05d5\u05d1\u05ea \u05d0\u05d9\u05d9.\u05e4\u05d9. \u05e9\u05d4\u05d5\u05e6\u05d0\u05d4 IPChecker.external.httploadfail=\u05e0\u05db\u05e9\u05dc \u05d1\u05d8\u05e2\u05d9\u05e0\u05ea \u05d3\u05e3 IPChecker.external.timeout=\u05d4\u05ea\u05e8\u05d7\u05e9\u05d4 \u05e9\u05d2\u05d9\u05d0\u05ea \u05e4\u05e1\u05e7 \u05d6\u05de\u05df IPChecker.external.ipnotfound=\u05db\u05ea\u05d5\u05d1\u05ea \u05d0\u05d9\u05d9.\u05e4\u05d9. \u05dc\u05d0 \u05e0\u05de\u05e6\u05d0\u05d4 ConfigView.section.tracker.pollintervalmin=\u05de\u05d9\u05e0\u05d9\u05de\u05d5\u05dd ConfigView.section.tracker.pollintervalmax=\u05de\u05e7\u05e1\u05d9\u05de\u05d5\u05dd ConfigView.section.tracker.pollintervalincby=\u05d4\u05d2\u05d3\u05dc \u05d1 : ConfigView.section.tracker.pollintervalincper=\u05db\u05dc \u05de\u05e1\u05e4\u05e8 \u05dc\u05e7\u05d5\u05d7\u05d5\u05ea splash.loadingImages=\u05d8\u05d5\u05e2\u05df \u05ea\u05de\u05d5\u05e0\u05d5\u05ea splash.initializeGui=\u05de\u05d0\u05ea\u05d7\u05dc \u05d7\u05dc\u05d5\u05df \u05e8\u05d0\u05e9\u05d9 splash.openViews=\u05d8\u05d5\u05e2\u05df \u05ea\u05e6\u05d5\u05d2\u05d5\u05ea splash.plugin=\u05d8\u05d5\u05e2\u05df \u05ea\u05d5\u05e1\u05e4\u05ea : configureWizard.nat.tooManyPorts=(\u05e4\u05d5\u05e8\u05d8\u05d9\u05dd \u05e8\u05d1\u05d9\u05dd \u05de\u05d3\u05d9 \u05dc\u05d1\u05d7\u05d9\u05e0\u05d4 (\u05de\u05e7\u05e1\u05d9\u05de\u05d5\u05dd 9 MyTorrentsView.menu.publish=\u05e4\u05e8\u05e1\u05dd.. MyTrackerView.status.published=\u05e4\u05d5\u05e8\u05e1\u05dd MyTrackerView.completed=\u05d4\u05e1\u05ea\u05d9\u05d9\u05dd MainWindow.menu.file.open.torrentnodefault=(\u05e7\u05d5\u05d1\u05e5 \u05d8\u05d5\u05e8\u05e0\u05d8 (\u05dc\u05d0 \u05dc\u05e0\u05ea\u05d9\u05d1 \u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc wizard.comment=\u05d4\u05e2\u05e8\u05d4 ConfigView.label.movetorrent=\u05d4\u05e2\u05d1\u05e8 \u05e7\u05d1\u05e6\u05d9 \u05d8\u05d5\u05e8\u05e0\u05d8 ConfigView.section.file.decoder.label=\u05e7\u05d9\u05d3\u05d5\u05d3 \u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc \u05e2\u05d1\u05d5\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05db\u05d0\u05e9\u05e8 \u05e0\u05d3\u05e8\u05e9\u05ea \u05d1\u05d7\u05d9\u05e8\u05d4 ConfigView.section.file.decoder.nodecoder=\u05db\u05dc\u05d5\u05dd ConfigView.section.tracker.publicenable=\u05d0\u05e4\u05e9\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d7\u05d9\u05e6\u05d5\u05e0\u05d9\u05d9\u05dd # # Tooltips # GeneralView.label.status.pieces_available.tooltip=\u05de\u05e6\u05d9\u05d2 \u05d0\u05ea \u05de\u05e1\u05e4\u05e8 \u05d4\u05d7\u05dc\u05e7\u05d9\u05dd \u05d4\u05d6\u05de\u05d9\u05e0\u05d9\u05dd \u05e9\u05dc \u05db\u05dc \u05d7\u05dc\u05e7\n\u05d0\u05dd \u05d4\u05de\u05e1\u05e4\u05e8 \u05de\u05d9\u05de\u05d9\u05df \u05e7\u05d8\u05df \u05de-1, \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05dc\u05d0 (\u05de\u05e6\u05d0\u05d4 \u05e2\u05d5\u05ea\u05e7 \u05e9\u05dc\u05dd \u05e9\u05dc \u05d4\u05e7\u05d5\u05d1\u05e5 (\u05d5\u05d9\u05d9\u05ea\u05db\u05df \u05e9\u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 \u05dc\u05d0 \u05ea\u05d5\u05db\u05dc \u05dc\u05d4\u05e1\u05ea\u05d9\u05d9\u05dd GeneralView.label.trackerurl.tooltip=\u05dc\u05d7\u05e5 \u05db\u05d3\u05d9 \u05dc\u05d4\u05e2\u05ea\u05d9\u05e7 \u05d0\u05ea \u05d4\u05db\u05ea\u05d5\u05d1\u05ea \u05e9\u05dc \u05d4\u05d4\u05db\u05e8\u05d6\u05d4 \u05dc\u05dc\u05d5\u05d7 GeneralView.label.trackerurlopen.tooltip=\u05dc\u05d7\u05e5 \u05dc\u05de\u05e2\u05d1\u05e8 \u05dc\u05d3\u05e3 \u05d4\u05d1\u05d9\u05ea \u05e9\u05dc \u05d4\u05d8\u05e8\u05e7\u05e8 # # 2.0.4.4 # ConfigView.section.style.guiUpdate=\u05e2\u05d3\u05db\u05df \u05d0\u05ea \u05d4\u05de\u05de\u05e9\u05e7 \u05d4\u05d2\u05e8\u05e4\u05d9 \u05db\u05dc ConfigView.section.style.graphicsUpdate=?\u05e2\u05d3\u05db\u05df \u05ea\u05e6\u05d5\u05d2\u05d4 \u05d2\u05e8\u05e4\u05d9\u05ea \u05db\u05dc \u05db\u05de\u05d4 \u05e2\u05d3\u05db\u05d5\u05e0\u05d9\u05dd ConfigView.section.style.reOrderDelay=\u05e1\u05d3\u05e8 \u05de\u05d7\u05d3\u05e9 \u05d8\u05d1\u05dc\u05d0\u05d5\u05ea \u05db\u05dc \u05db\u05de\u05d4 \u05e2\u05d3\u05db\u05d5\u05e0\u05d9\u05dd \u05e9\u05dc \u05de\u05de\u05e9\u05e7 \u05d2\u05e8\u05e4\u05d9? ConfigView.section.style.reOrderDelay.never=\u05d0\u05e3 \u05e4\u05e2\u05dd ConfigView.section.logging=\u05d9\u05d5\u05de\u05df ConfigView.section.logging.enable=\u05d0\u05e4\u05e9\u05e8 \u05db\u05ea\u05d9\u05d1\u05ea \u05d9\u05d5\u05de\u05df \u05dc\u05e7\u05d5\u05d1\u05e5 ConfigView.section.logging.logdir=\u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d9\u05d5\u05de\u05df ConfigView.section.logging.choosedefaultsavepath=\u05d1\u05d7\u05e8 \u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 \u05dc\u05e9\u05de\u05d9\u05e8\u05d4 GeneralView.label.updatein.querying=\u05d1\u05d5\u05d3\u05e7.. configureWizard.nat.sharePort=\u05e9\u05d9\u05de\u05d5\u05e9 \u05d1\u05e4\u05d5\u05e8\u05d8 \u05db\u05e0\u05d9\u05e1\u05d4 \u05d0\u05d7\u05d3 \u05dc\u05db\u05dc \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd ConfigView.section.logging.maxsize=\u05d2\u05d5\u05d3\u05dc \u05e7\u05d5\u05d1\u05e5 \u05d9\u05d5\u05de\u05df \u05de\u05d9\u05e8\u05d1\u05d9 ConfigView.section.tracker.passwordenableweb=\u05d0\u05e4\u05e9\u05e8 \u05e1\u05d9\u05e1\u05de\u05d4 \u05dc\u05d8\u05e8\u05e7\u05e8 \u05d1\u05e8\u05e9\u05ea ConfigView.section.tracker.passwordenabletorrent=\u05d0\u05e4\u05e9\u05e8 \u05e1\u05d9\u05e1\u05de\u05d4 \u05dc\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd ConfigView.section.tracker.username=\u05e9\u05dd \u05de\u05e9\u05ea\u05de\u05e9 ConfigView.section.tracker.password=\u05e1\u05d9\u05e1\u05de\u05d4 columnChooser.title=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05ea\u05e6\u05d5\u05d2\u05ea \u05d4\u05d8\u05d5\u05e8 columnChooser.move=\u05d2\u05e8\u05d5\u05e8 \u05e9\u05d5\u05e8\u05d5\u05ea \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05e1\u05d3\u05e8 \u05de\u05d7\u05d3\u05e9 columnChooser.apply=\u05d4\u05d7\u05dc columnChooser.columnname=\u05e9\u05dd \u05d8\u05d5\u05e8 columnChooser.columndescription=\u05ea\u05d9\u05d0\u05d5\u05e8 TableColumn.header.shareRatio=\u05d9\u05d7\u05e1 \u05e9\u05d9\u05ea\u05d5\u05e3 MyTorrentsView.menu.editTableColumns=\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05d8\u05d5\u05e8 wizard.operationfailed=\u05d4\u05e4\u05e2\u05d5\u05dc\u05d4 \u05e0\u05db\u05e9\u05dc\u05d4 authenticator.title=\u05d3\u05e8\u05d5\u05e9 \u05d0\u05d9\u05de\u05d5\u05ea authenticator.realm=\u05de\u05ea\u05d7\u05dd authenticator.tracker=\u05d8\u05e8\u05e7\u05e8 authenticator.user=\u05e9\u05dd \u05de\u05e9\u05ea\u05de\u05e9 authenticator.password=\u05e1\u05d9\u05e1\u05de\u05d4 ConfigView.label.allowSendVersion=\u05d0\u05e4\u05e9\u05e8 \u05dc\u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05dc\u05e9\u05dc\u05d5\u05d7 \u05d1\u05e6\u05d5\u05e8\u05d4 \u05d0\u05e0\u05d5\u05e0\u05d9\u05de\u05d9\u05ea \u05de\u05e1\u05e4\u05e8 \u05d2\u05d9\u05e8\u05e1\u05d4 \u05d5\u05de\u05e1\u05e4\u05e8 \u05d6\u05d9\u05d4\u05d5\u05d9 \u05d0\u05e7\u05e8\u05d0\u05d9 \u05d1\u05de\u05d4\u05dc\u05da \u05d1\u05d3\u05d9\u05e7\u05ea \u05d2\u05d9\u05e8\u05e1\u05d4 wizard.hint.mode=\u05de\u05d9\u05d3\u05e2 : \u05d1\u05d9\u05db\u05d5\u05dc\u05ea\u05da \u05dc\u05d2\u05e8\u05d5\u05e8 \u05e7\u05d5\u05d1\u05e5 \u05d0\u05d5 \u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 \u05dc\u05d0\u05e9\u05e3 \u05d6\u05d4\n\t\u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05d1\u05d7\u05d5\u05e8 \u05d0\u05d5\u05ea\u05dd wizard.hint.file=:\u05de\u05d9\u05d3\u05e2\t\u05d0\u05ea\u05d4 \u05d9\u05db\u05d5\u05dc \u05dc\u05d1\u05d7\u05d5\u05e8 \u05e7\u05d5\u05d1\u05e5 \u05d0\u05d7\u05ea \u05e2"\u05d9 \u05d2\u05e8\u05d9\u05e8\u05d4 wizard.hint.directory=:\u05de\u05d9\u05d3\u05e2\t\u05d0\u05ea\u05d4 \u05d9\u05db\u05d5\u05dc \u05dc\u05d1\u05d7\u05d5\u05e8 \u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 \u05d0\u05d7\u05ea \u05e2"\u05d9 \u05d2\u05e8\u05d9\u05e8\u05d4 MainWindow.menu.help.checkupdate=\u05d1\u05d3\u05d5\u05e7 \u05e2\u05d9\u05d3\u05db\u05d5\u05e0\u05d9\u05dd TableColumn.header.down=\u05d9\u05e8\u05d3 TableColumn.header.up=\u05e2\u05dc\u05d4 ConfigView.section.tracker.passwordenabletorrent.info=(\u05d3\u05d5\u05e8\u05e9 \u05ea\u05d5\u05db\u05e0\u05ea \u05d1\u05d9\u05d8\u05d5\u05e8\u05e0\u05d8 \u05de\u05ea\u05d0\u05d9\u05de\u05d4 (\u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05dc\u05d3\u05d5\u05d2\u05de\u05d0 ConfigView.section.style.confirmationOnExit=\u05d4\u05e6\u05d2 \u05ea\u05d9\u05d1\u05ea \u05d0\u05d9\u05e9\u05d5\u05e8 \u05d1\u05d9\u05e6\u05d9\u05d0\u05d4 MainWindow.dialog.exitconfirmation.title=?\u05dc\u05e6\u05d0\u05ea \u05de\u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 MainWindow.dialog.exitconfirmation.text=\u05d4\u05d0\u05dd \u05d0\u05ea\u05d4 \u05d1\u05d8\u05d5\u05d7 \u05e9\u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05dc\u05e6\u05d0\u05ea \u05de\u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1? SystemTray.menu.stopalltransfers=\u05e2\u05e6\u05d5\u05e8& \u05d0\u05ea \u05db\u05dc \u05d4\u05d4\u05e2\u05d1\u05e8\u05d5\u05ea TrayWindow.menu.stopalldownloads=\u05e2\u05e6\u05d5\u05e8 \u05d0\u05ea \u05db\u05dc \u05d4\u05d4\u05d5\u05e8\u05d3\u05d5\u05ea ConfigView.section.tracker.sslport.info=\u05e8\u05d0\u05d4 \u05d0\u05ea \u05d4'\u05e9\u05d0\u05dc\u05d5\u05ea \u05d5\u05ea\u05e9\u05d5\u05d1\u05d5\u05ea' \u05dc\u05de\u05d9\u05d3\u05e2 \u05e0\u05d5\u05e1\u05e3 wizard.tracker.ssl=\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1-SSL ConfigView.label.playdownloadfinished=\u05d4\u05e9\u05de\u05e2 \u05e6\u05dc\u05d9\u05dc \u05d1\u05e1\u05d9\u05d5\u05dd \u05d4\u05d5\u05e8\u05d3\u05d4 TableColumn.header.pieces=\u05d7\u05dc\u05e7\u05d9\u05dd TableColumn.header.pieces.info=\u05ea\u05e6\u05d5\u05d2\u05d4 \u05d2\u05e8\u05e4\u05d9\u05ea \u05d4\u05de\u05e9\u05e7\u05e4\u05ea \u05d0\u05ea \u05d4\u05d7\u05dc\u05e7\u05d9\u05dd \u05e9\u05d9\u05e8\u05d3\u05d5 TableColumn.header.completion=\u05e1\u05d9\u05d5\u05dd TableColumn.header.completion.info=\u05ea\u05e6\u05d5\u05d2\u05d4 \u05d2\u05e8\u05e4\u05d9\u05ea \u05e9\u05dc \u05d0\u05d7\u05d5\u05d6\u05d9 \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 ConfigView.section.style.showdownloadbasket=\u05d4\u05e8\u05d0\u05d4 \u05e1\u05dc \u05d4\u05d5\u05e8\u05d3\u05d4 (\u05d2\u05e8\u05d5\u05e8 \u05d5\u05e9\u05d7\u05e8\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd) ConfigView.section.style.alwaysShowTorrentFiles=\u05ea\u05de\u05d9\u05d3 \u05d4\u05e6\u05d2 \u05e7\u05d1\u05e6\u05d9 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05d1\u05e4\u05e8\u05d8\u05d9\u05dd/\u05e7\u05d1\u05e6\u05d9\u05dd wizard.multitracker=\u05d4\u05d5\u05e1\u05e3 \u05de\u05d9\u05d3\u05e2 \u05de\u05d5\u05dc\u05d8\u05d9-\u05d8\u05e8\u05e7\u05e8 \u05dc\u05e7\u05d5\u05d1\u05e5 wizard.multitracker.title=\u05de\u05d5\u05dc\u05d8\u05d9-\u05d8\u05e8\u05e7\u05e8 wizard.multitracker.configuration=\u05d4\u05d2\u05d3\u05e8\u05ea \u05de\u05d5\u05dc\u05d8\u05d9-\u05d8\u05e8\u05e7\u05e8 wizard.multitracker.new=..\u05d7\u05d3\u05e9 wizard.multitracker.edit=..\u05e2\u05e8\u05d5\u05da wizard.multitracker.delete=\u05de\u05d7\u05e7 wizard.multitracker.group=\u05db\u05ea\u05d5\u05d1\u05ea \u05d8\u05e8\u05e7\u05e8 wizard.multitracker.edit.title=\u05e2\u05d5\u05e8\u05da \u05de\u05d5\u05dc\u05d8\u05d9-\u05d8\u05e8\u05e7\u05e8 wizard.multitracker.edit.name=\u05e9\u05dd wizard.multitracker.edit.save=\u05e9\u05de\u05d5\u05e8 wizard.multitracker.edit.newgroup=\u05db\u05ea\u05d5\u05d1\u05ea \u05d7\u05d3\u05e9\u05d4 wizard.multitracker.edit.deletegroup=\u05de\u05d7\u05e7 wizard.multitracker.edit.newtracker=\u05d8\u05e8\u05e7\u05e8 \u05d7\u05d3\u05e9 wizard.multitracker.edit.deletetracker=\u05de\u05d7\u05e7 wizard.multitracker.edit.edit=\u05e2\u05e8\u05d5\u05da wizard.addingmt=\u05de\u05d5\u05e1\u05d9\u05e3 \u05de\u05d9\u05d3\u05e2 \u05de\u05d5\u05dc\u05d8\u05d9-\u05d8\u05e8\u05e7\u05e8 wizard.multitracker.noannounce=\u05db\u05ea\u05d5\u05d1\u05ea \u05d4\u05d4\u05db\u05e8\u05d6\u05d4 \u05d0\u05d9\u05e0\u05d4 \u05e0\u05de\u05e6\u05d0\u05ea \u05d1\u05e8\u05e9\u05d9\u05de\u05ea \u05d4\u05d8\u05e8\u05e7\u05e8\u05d9\u05dd \u05e9\u05dc\u05da MyTorrentsView.menu.recheck=\u05d0\u05dc\u05e5 \u05d1\u05d3\u05d9\u05e7\u05d4 \u05d7\u05d5\u05d6\u05e8\u05ea iconBar.showDownloadBar.tooltip=\u05d4\u05e6\u05d2 \u05de\u05e6\u05d1 \u05d4\u05d5\u05e8\u05d3\u05d4 iconBar.start.tooltip=\u05d4\u05ea\u05d7\u05dc iconBar.stop.tooltip=\u05e2\u05e6\u05d5\u05e8 iconBar.remove.tooltip=\u05d4\u05e1\u05e8 iconBar.openNoDefault.tooltip=(\u05e4\u05ea\u05d7 \u05e7\u05d5\u05d1\u05e5 \u05d8\u05d5\u05e8\u05e0\u05d8 (\u05dc\u05d0 \u05dc\u05e0\u05ea\u05d9\u05d1 \u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc iconBar.openURL.tooltip=\u05e4\u05ea\u05d7 \u05db\u05ea\u05d5\u05d1\u05ea iconBar.openFolder.tooltip=\u05e4\u05ea\u05d7 \u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 iconBar.new.tooltip=\u05e6\u05d5\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05d7\u05d3\u05e9 iconBar.up.tooltip=\u05d4\u05d6\u05d6 \u05de\u05e2\u05dc\u05d4 iconBar.down.tooltip=\u05d4\u05d6\u05d6 \u05dc\u05de\u05d8\u05d4 iconBar.run.tooltip=\u05e4\u05ea\u05d7 iconBar.host.tooltip=\u05d0\u05e8\u05d7 iconBar.publish.tooltip=\u05e4\u05e8\u05e1\u05dd MyTorrentsView.menu.editTracker=\u05e2\u05e8\u05d5\u05da \u05db\u05ea\u05d5\u05d1\u05ea \u05d8\u05e8\u05e7\u05e8 GeneralView.menu.selectTracker=\u05d1\u05d7\u05e8 ConfigView.section.stats.xslfile=\u05e1\u05d9\u05d5\u05de\u05ea \u05e7\u05d5\u05d1\u05e5 XSL ConfigView.label.savetorrentbackup=\u05e9\u05de\u05d5\u05e8 \u05d2\u05d9\u05d1\u05d5\u05d9 ConfigView.section.tracker.forceport=\u05d4\u05db\u05e8\u05d7 \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d7\u05d9\u05e6\u05d5\u05e0\u05d9\u05d9\u05dd \u05e9\u05de\u05ea\u05d0\u05e8\u05d7\u05d9\u05dd \u05dc\u05e2\u05d1\u05d5\u05d3 \u05e2\u05dd \u05e4\u05d5\u05e8\u05d8 \u05d1\u05e8\u05d9\u05e8\u05ea \u05d4\u05de\u05d7\u05d3\u05dc ConfigView.section.ipfilter.allow=(\u05d0\u05e9\u05e8 \u05d8\u05d5\u05d5\u05d7\u05d9\u05dd \u05d0\u05dc\u05d5 (\u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc - \u05d7\u05e1\u05d5\u05dd ConfigView.section.ipfilter.list.inrange=\u05e0\u05de\u05e6\u05d0 \u05d1\u05d8\u05d5\u05d5\u05d7 ConfigView.section.ipfilter.list.notinrange=\u05dc\u05d0 \u05e0\u05de\u05e6\u05d0 \u05d1\u05e9\u05d5\u05dd \u05d8\u05d5\u05d5\u05d7 ConfigView.section.ipfilter.list.title=\u05e8\u05e9\u05d9\u05de\u05ea \u05d0\u05d9\u05d9.\u05e4\u05d9. \u05d7\u05e1\u05d5\u05de\u05d9\u05dd ConfigView.label.allowsameip=\u05d0\u05e4\u05e9\u05e8 \u05d7\u05d9\u05d1\u05d5\u05e8\u05d9\u05dd \u05de\u05e8\u05d5\u05d1\u05d9\u05dd \u05de\u05d0\u05d5\u05ea\u05d5 \u05d0\u05d9\u05d9.\u05e4\u05d9. ConfigView.label.allowsameip.tooltip=\u05d4\u05e4\u05e2\u05dc \u05e8\u05e7 \u05d0\u05dd \u05e0\u05d7\u05d5\u05e5.\n\u05db\u05e9\u05d0\u05e4\u05e9\u05e8\u05d5\u05ea \u05d6\u05d5 \u05de\u05db\u05d5\u05d1\u05d4 \u05d4\u05d9\u05d0 \u05de\u05d2\u05d9\u05e0\u05d4 \u05d1\u05e4\u05e0\u05d9 \u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05d8\u05d5\u05e8\u05d3\u05e0\u05d9\u05d9\u05dd ManagerItem.superseeding=\u05e1\u05d5\u05e4\u05e8-\u05d4\u05e4\u05e6\u05d4 ConfigView.label.userSuperSeeding=\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05e1\u05d5\u05e4\u05e8-\u05d4\u05e4\u05e6\u05d4 PeersView.uniquepiece=(\u05d7\u05dc\u05e7 (\u05de\u05e6\u05d1 \u05e1\u05d5\u05e4\u05e8-\u05d4\u05e4\u05e6\u05d4 PeersView.uniquepiece.none=\u05d0\u05e3 \u05d0\u05d7\u05d3 PeersView.timetosend=\u05d6\u05de\u05df \u05dc\u05de\u05e9\u05dc\u05d5\u05d7 \u05d7\u05d5\u05d6\u05e8 \u05e9\u05dc \u05d7\u05dc\u05e7 (\u05de\u05e6\u05d1 \u05e1\u05d5\u05e4\u05e8-\u05d4\u05e4\u05e6\u05d4) ConfigView.section.style.addurlsilently=\u05e4\u05ea\u05d7 \u05db\u05ea\u05d5\u05d1\u05ea \u05d0\u05d9\u05e0\u05d8\u05e8\u05e0\u05d8 \u05dc\u05dc\u05d0 \u05ea\u05d9\u05d1\u05d4 ConfigView.section.style.addurlsilently.tooltip=Warning: the main window will not made visible again if activated!\nIf you loose the tray icon, you should deactivate this option. ConfigView.section.file.decoder.prompt=\u05ea\u05de\u05d9\u05d3 \u05e9\u05d0\u05dc \u05db\u05d0\u05e9\u05e8 \u05d9\u05e9 \u05d0\u05e4\u05e9\u05e8\u05d5\u05ea \u05e7\u05d9\u05d3\u05d5\u05d3 ConfigView.section.file.decoder.prompt.tooltip=\u05ea\u05de\u05d9\u05d3 \u05d4\u05e6\u05d2 \u05ea\u05d9\u05d1\u05ea \u05e7\u05d9\u05d3\u05d5\u05d3 \u05db\u05d0\u05e9\u05e8 \u05d4\u05d0\u05e4\u05e9\u05e8\u05d5\u05ea \u05d6\u05de\u05d9\u05e0\u05d4 MyTorrentsView.menu.moveTop=\u05dc\u05e2\u05dc\u05d9\u05d5\u05df MyTorrentsView.menu.moveEnd=\u05dc\u05ea\u05d7\u05ea\u05d5\u05df ConfigView.label.moveonlyusingdefaultsave=\u05d0\u05dd \u05d1\u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc ConfigView.label.moveonlyusingdefaultsave.tooltip=\u05d4\u05e2\u05d1\u05e8 \u05e8\u05e7 \u05d0\u05dd \u05d4\u05de\u05d9\u05d3\u05e2 \u05e9\u05d9\u05e8\u05d3 \u05e0\u05de\u05e6\u05d0 \u05d1\u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05d1\u05e8\u05d9\u05e8\u05ea \u05d4\u05de\u05d7\u05d3\u05dc \u05dc\u05d4\u05d5\u05e8\u05d3\u05d5\u05ea. ConfigView.label.watchtorrentfolder=\u05d9\u05d9\u05d1\u05d0 \u05e7\u05d5\u05d1\u05e6\u05d9 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05d7\u05d3\u05e9\u05d9\u05dd \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea ConfigView.label.watchtorrentfolder.tooltip=\u05de\u05d7\u05e4\u05e9 \u05e7\u05d1\u05e6\u05d9 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05d7\u05d3\u05e9\u05d9\u05dd \u05d1\u05e7\u05d1\u05d9\u05e2\u05d5\u05ea ConfigView.label.watchtorrentfolderinterval=\u05de\u05d7\u05d6\u05d5\u05e8 ConfigView.label.watchtorrentfolderinterval.tooltip=\u05d6\u05de\u05df \u05d4\u05d4\u05e4\u05e1\u05e7\u05d4 \u05e2\u05d3 \u05dc\u05e1\u05e8\u05d9\u05e7\u05d4 \u05d7\u05d5\u05d6\u05e8\u05ea \u05e9\u05dc \u05d4\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 ConfigView.dialog.choosewatchtorrentfolderpath=\u05d1\u05d7\u05e8 \u05d0\u05ea \u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05d1\u05e8\u05d9\u05e8\u05ea \u05d4\u05de\u05d7\u05d3\u05dc \u05dc\u05d9\u05d9\u05d1\u05d5\u05d0 \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd ConfigView.label.startwatchedtorrentsstopped=\u05d4\u05e4\u05e2\u05dc \u05d1\u05e2\u05e6\u05d9\u05e8\u05d4 ConfigView.label.startwatchedtorrentsstopped.tooltip=\u05d4\u05d5\u05e1\u05e3 \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d7\u05d3\u05e9\u05d9\u05dd \u05d1\u05de\u05e6\u05d1 \u05e2\u05e6\u05d9\u05e8\u05d4. ConfigView.section.plugins=\u05ea\u05d5\u05e1\u05e4\u05d5\u05ea wizard.maketorrent.filesize=(\u05d2\u05d5\u05d3\u05dc \u05d4\u05e7\u05d5\u05d1\u05e5(\u05d9\u05dd wizard.maketorrent.piececount=\u05de\u05e1\u05e4\u05e8 \u05d7\u05dc\u05e7\u05d9\u05dd wizard.maketorrent.piecesize=\u05d2\u05d5\u05d3\u05dc \u05d7\u05dc\u05e7 wizard.maketorrent.auto=\u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9 MainWindow.menu.view.stats=\u05e1\u05d8\u05d8\u05d9\u05e1\u05d8\u05d9\u05e7\u05d4 SpeedView.title.full=\u05e4\u05e2\u05d9\u05dc\u05d5\u05ea SpeedView.downloadSpeed.title=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05d5\u05e8\u05d3\u05d4 SpeedView.uploadSpeed.title=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05e2\u05dc\u05d0\u05d4 ConfigView.section.style.useSIUnits=\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05d9\u05d7\u05d9\u05d3\u05d5\u05ea IEC - (\u05e7\u05d9\u05dc\u05d5\u05d1\u05d9\u05d9\u05d8 --> \u05e7\u05d9\u05dc\u05d5\u05d1\u05d9\u05d8) iconBar.top.tooltip=\u05d4\u05d6\u05d6 \u05dc\u05e2\u05dc\u05d9\u05d5\u05df iconBar.bottom.tooltip=\u05d4\u05d6\u05d6 \u05dc\u05ea\u05d7\u05ea\u05d5\u05df TableColumn.header.health=\u05ea\u05e7\u05d9\u05e0\u05d5\u05ea MyTorrentsView.menu.health=\u05d0\u05d5\u05d3\u05d5\u05ea \u05ea\u05e7\u05d9\u05e0\u05d5\u05ea health.explain.grey=(\u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 \u05d0\u05d9\u05e0\u05d5 \u05e4\u05d5\u05e2\u05dc (\u05d4\u05d5\u05e8\u05d3\u05d4 \u05d0\u05d5 \u05d4\u05e2\u05dc\u05d0\u05d4 health.explain.red=\u05d0\u05d9\u05e0\u05da \u05de\u05d7\u05d5\u05d1\u05e8 \u05dc\u05e9\u05d5\u05dd \u05de\u05e9\u05ea\u05e3 \u05d1\u05de\u05d4\u05dc\u05da \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 health.explain.blue=\u05db\u05d0\u05e9\u05e8 \u05de\u05e4\u05d9\u05e6\u05d9\u05dd, \u05de\u05e1\u05de\u05dc \u05e9\u05d0\u05d9\u05e0\u05da \u05de\u05d7\u05d5\u05d1\u05e8 \u05dc\u05e9\u05d5\u05dd \u05de\u05e9\u05ea\u05e3\n\u05db\u05d0\u05e9\u05e8 \u05de\u05d5\u05e8\u05d9\u05d3\u05d9\u05dd, \u05de\u05e1\u05de\u05dc \u05e9\u05d0\u05ea\u05d4 \u05de\u05d7\u05d5\u05d1\u05e8 \u05dc\u05db\u05de\u05d4 \u05de\u05e9\u05ea\u05e4\u05d9\u05dd \u05d0\u05da \u05d4\u05d8\u05e8\u05e7\u05e8 \u05d0\u05d9\u05e0\u05d5 \u05e4\u05d5\u05e2\u05dc health.explain.yellow=\u05d4\u05d8\u05e8\u05e7\u05e8 \u05e4\u05d5\u05e2\u05dc, \u05d0\u05ea\u05d4 \u05de\u05d7\u05d5\u05d1\u05e8 \u05dc\u05e2\u05d5\u05d3 \u05de\u05e9\u05ea\u05e4\u05d9\u05dd, \u05d0\u05d1\u05dc \u05d0\u05d9\u05df \u05dc\u05da \u05d7\u05d9\u05d1\u05d5\u05e8\u05d9\u05dd \u05de\u05e8\u05d5\u05d7\u05e7\u05d9\u05dd\n\u05d9\u05d9\u05ea\u05db\u05df \u05e9\u05d9\u05e9 \u05dc\u05da \u05d1\u05e2\u05d9\u05d9\u05ea \u05d7\u05d5\u05de\u05ea-\u05d0\u05e9 \u05d0\u05dd \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05e9\u05dc\u05da \u05d1\u05de\u05e6\u05d1 \u05e6\u05d4\u05d5\u05d1 \u05db\u05dc \u05d4\u05d6\u05de\u05df health.explain.green=\u05d4\u05db\u05dc \u05e4\u05d5\u05e2\u05dc \u05d1\u05e1\u05d3\u05e8 ConfigView.section.style.alwaysRefreshMyTorrents=\u05ea\u05de\u05d9\u05d3 \u05e8\u05e2\u05e0\u05df \u05d0\u05ea \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05e9\u05dc\u05d9 ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=(\u05d0\u05e4\u05e9\u05e8\u05d5\u05ea \u05d6\u05d5 \u05ea\u05e8\u05e2\u05e0\u05df \u05d0\u05ea \u05ea\u05e6\u05d5\u05d2\u05ea \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d0\u05e4\u05d9\u05dc\u05d5 \u05db\u05d0\u05e9\u05e8 \u05dc\u05d0 \u05de\u05d5\u05e6\u05d2\u05ea (\u05e9\u05d9\u05de\u05d5\u05e9\u05d9 \u05dc\u05ea\u05d5\u05e4\u05e1\u05d5\u05ea \u05de\u05e1\u05d5\u05d9\u05de\u05d5\u05ea \u05e9\u05dc mirc # #2.0.7.0 # security.certtruster.title=\u05d0\u05d6\u05d4\u05e8\u05ea \u05d0\u05d9\u05e9\u05d5\u05e8 \u05d0\u05d1\u05d8\u05d7\u05d4 security.certtruster.intro=\u05d0\u05d9\u05e9\u05d5\u05e8 \u05d4\u05d1\u05d8\u05d9\u05d7\u05d5\u05ea \u05d4\u05d5\u05e0\u05e4\u05e7 \u05e2"\u05d9 \u05d7\u05d1\u05e8\u05d4 \u05e9\u05e2\u05dc\u05d9\u05d4 \u05d0\u05ea\u05d4 \u05dc\u05d0 \u05e1\u05d5\u05de\u05da security.certtruster.resource=\u05de\u05e9\u05d0\u05d1 : security.certtruster.issuedto=\u05e0\u05d5\u05e6\u05e8 \u05e2\u05d1\u05d5\u05e8 : security.certtruster.issuedby=\u05e0\u05d5\u05e6\u05e8 \u05e2"\u05d9 : security.certtruster.prompt=\u05d4\u05d0\u05dd \u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05dc\u05e1\u05de\u05d5\u05da \u05e2\u05dc\u05d9\u05d5? security.certtruster.yes=\u05db\u05df security.certtruster.no=\u05dc\u05d0 ConfigView.section.tracker.torrentsperpage=(\u05de\u05e1\u05e4\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05dc\u05d3\u05e3 ? (0 - \u05d1\u05dc\u05ea\u05d9 \u05de\u05d5\u05d2\u05d1\u05dc MainWindow.menu.file.share=\u05e9\u05ea\u05e3 MainWindow.menu.file.share.file=\u05e7\u05d5\u05d1\u05e5 MainWindow.menu.file.share.dir=\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 MainWindow.menu.file.share.dircontents=\u05ea\u05d5\u05db\u05df \u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 MainWindow.menu.file.share.dircontentsrecursive=(\u05ea\u05d5\u05db\u05df \u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 (\u05db\u05d5\u05dc\u05dc \u05ea\u05ea-\u05ea\u05d9\u05e7\u05d9\u05d5\u05ea MainWindow.dialog.share.sharefile=\u05d1\u05d7\u05e8 \u05e7\u05d5\u05d1\u05e5 \u05dc\u05e9\u05d9\u05ea\u05d5\u05e3 MainWindow.dialog.share.sharedir=\u05d1\u05d7\u05e8 \u05e0\u05ea\u05d9\u05d1 \u05dc\u05e9\u05d9\u05ea\u05d5\u05e3 MainWindow.dialog.share.sharedircontents=\u05d1\u05d7\u05e8 \u05ea\u05d5\u05db\u05df \u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 \u05dc\u05e9\u05d9\u05ea\u05d5\u05e3 MainWindow.dialog.share.sharedircontents.recursive=\u05db\u05d5\u05dc\u05dc \u05ea\u05ea \u05ea\u05d9\u05e7\u05d9\u05d5\u05ea globalmanager.download.remove.veto=\u05e4\u05e2\u05d5\u05dc\u05ea \u05d4\u05d4\u05e1\u05e8\u05d4 \u05e0\u05e2\u05e7\u05e4\u05d4 ConfigView.section.tracker.main=\u05e8\u05d0\u05e9\u05d9 ConfigView.section.tracker.web=\u05d0\u05d9\u05e0\u05d8\u05e8\u05e0\u05d8 ConfigView.label.prioritizefirstpiece=(\u05e9\u05d9\u05dd \u05d1\u05e2\u05d3\u05d9\u05e4\u05d5\u05ea \u05d0\u05ea \u05d4\u05d7\u05dc\u05e7 \u05d4\u05e8\u05d0\u05e9\u05d5\u05df \u05e9\u05dc \u05d4\u05e7\u05d5\u05d1\u05e5(\u05d9\u05dd ConfigView.label.prioritizefirstpiece.tooltip=\u05e0\u05e1\u05d4 \u05dc\u05d4\u05d5\u05e8\u05d9\u05d3 \u05d0\u05ea \u05ea\u05d7\u05d9\u05dc\u05ea \u05d4\u05e7\u05d5\u05d1\u05e5 \u05e7\u05d5\u05d3\u05dd.\n\u05dc\u05ea\u05de\u05d9\u05db\u05d4 \u05d1\u05ea\u05e6\u05d5\u05d2\u05d4 \u05de\u05d5\u05e7\u05d3\u05de\u05ea ConfigView.section.file.confirm_data_delete=\u05d0\u05e9\u05e8 \u05de\u05d7\u05d9\u05e7\u05ea \u05de\u05d9\u05d3\u05e2 ConfigView.section.file.confirm_data_delete.tooltip='..\u05d1\u05e7\u05e9 \u05d0\u05d9\u05e9\u05d5\u05e8 \u05de\u05d7\u05d9\u05e7\u05d4 \u05db\u05d0\u05e9\u05e8 \u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05d1'\u05de\u05d7\u05e7 \u05d5 TrayWindow.menu.startalldownloads=\u05d4\u05ea\u05d7\u05dc \u05d0\u05ea \u05db\u05dc \u05d4\u05d4\u05d5\u05e8\u05d3\u05d5\u05ea SystemTray.menu.startalltransfers=\u05d4\u05ea\u05d7\u05dc \u05d0\u05ea \u05db\u05dc \u05d4\u05d4\u05e2\u05d1\u05e8\u05d5\u05ea sharing.progress.title=\u05d4\u05ea\u05e7\u05d3\u05de\u05d5\u05ea \u05d4\u05e9\u05d9\u05ea\u05d5\u05e3 sharing.progress.hide=\u05d4\u05e1\u05ea\u05e8 MainWindow.menu.view.myshares=\u05d4\u05e9\u05d9\u05ea\u05d5\u05e4\u05d9\u05dd \u05e9\u05dc\u05d9 MySharesView.title.full=\u05d4\u05e9\u05d9\u05ea\u05d5\u05e4\u05d9\u05dd \u05e9\u05dc\u05d9 MySharesView.name=\u05e9\u05dd MySharesView.type=\u05e1\u05d5\u05d2 MySharesView.type.file=\u05e7\u05d5\u05d1\u05e5 MySharesView.type.dir=\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 MySharesView.type.dircontents=\u05ea\u05d5\u05db\u05df \u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 MySharesView.type.dircontentsrecursive=(\u05ea\u05d5\u05db\u05df \u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 (\u05db\u05d5\u05dc\u05dc \u05ea\u05ea-\u05ea\u05d9\u05e7\u05d9\u05d5\u05ea MySharesView.menu.remove=\u05d4\u05e1\u05e8 ConfigView.section.tracker.extensions=\u05e1\u05d9\u05d5\u05de\u05d5\u05ea ConfigView.section.tracker.sendpeerids=\u05e9\u05dc\u05d7 \u05d6\u05d4\u05d5\u05ea \u05de\u05e9\u05ea\u05e3 \u05dc\u05de\u05d5\u05e8\u05d9\u05d3\u05d9\u05dd ConfigView.section.tracker.enableudp=\u05d0\u05e4\u05e9\u05e8 \u05e4\u05e8\u05d5\u05d8\u05d5\u05e7\u05d5\u05dc UDP \u05dc\u05d8\u05e8\u05e7\u05e8 plugin.download.remove.veto.notstopped=\u05dc\u05d0 \u05e0\u05d9\u05ea\u05df \u05dc\u05de\u05d7\u05d5\u05e7 \u05d0\u05ea \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 \u05de\u05e9\u05d5\u05dd \u05e9\u05d4\u05d9\u05d0 \u05dc\u05d0 \u05e0\u05e2\u05e6\u05e8\u05d4 GeneralView.label.hash.tooltip=\u05dc\u05d7\u05e5 \u05db\u05d3\u05d9 \u05dc\u05d4\u05e2\u05ea\u05d9\u05e7 \u05d0\u05ea \u05d4\u05d4\u05d0\u05e9 \u05dc\u05dc\u05d5\u05d7 ConfigView.section.tracker.maxpeersreturned=(\u05de\u05e1\u05e4\u05e8 \u05de\u05e9\u05ea\u05e4\u05d9\u05dd \u05de\u05d9\u05e8\u05d1\u05d9 (0 : \u05d1\u05dc\u05ea\u05d9 \u05de\u05d5\u05d2\u05d1\u05dc ConfigView.label.serverport=\u05e4\u05d5\u05e8\u05d8 TCP \u05dc\u05ea\u05e7\u05e9\u05d5\u05e8\u05ea \u05e0\u05db\u05e0\u05e1\u05ea configureWizard.nat.server.tcp_listen_port=\u05e4\u05d5\u05e8\u05d8 TCP \u05dc\u05ea\u05e7\u05e9\u05d5\u05e8\u05ea \u05e0\u05db\u05e0\u05e1\u05ea ConfigView.section.sharing=\u05e9\u05d9\u05ea\u05d5\u05e3 ConfigView.section.sharing.usessl=\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05d0\u05d1\u05d8\u05d7\u05ea SSL \u05e2\u05d1\u05d5\u05e8 \u05de\u05e9\u05d0\u05d1\u05d9\u05dd \u05de\u05e9\u05d5\u05ea\u05e4\u05d9\u05dd (\u05d3\u05d5\u05e8\u05e9 \u05d4\u05d2\u05d3\u05e8\u05ea \u05d4\u05d8\u05e8\u05e7\u05e8) ConfigView.section.style.dropdiraction=\u05d0\u05e4\u05e9\u05e8\u05d5\u05ea \u05d2\u05e8\u05d9\u05e8\u05d4 \u05e2\u05d1\u05d5\u05e8 \u05ea\u05d9\u05e7\u05d9\u05d5\u05ea ConfigView.section.style.dropdiraction.opentorrents=\u05e4\u05ea\u05d7 \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd ConfigView.section.style.dropdiraction.sharefolder=\u05e9\u05ea\u05e3 \u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 ConfigView.section.style.dropdiraction.sharefoldercontents=\u05e9\u05ea\u05e3 \u05ea\u05d5\u05db\u05df # # 2.0.7.x # Categories.all=\u05d4\u05db\u05dc Categories.uncategorized=\u05dc\u05d0 \u05de\u05e7\u05d5\u05d8\u05dc\u05d2 CategoryAddWindow.message=\u05d4\u05db\u05e0\u05e1 \u05e9\u05dd \u05e7\u05d8\u05d2\u05d5\u05e8\u05d9\u05d4 \u05d7\u05d3\u05e9\u05d4 CategoryAddWindow.title=\u05d4\u05d5\u05e1\u05e3 \u05e7\u05d8\u05d2\u05d5\u05e8\u05d9\u05d4 \u05d7\u05d3\u05e9\u05d4 ConfigView.label.autoSeedingIgnoreInfo=Ignored torrents go to the bottom of the seeding queue. They do not get automatically started. Ignore rules do not apply to torrents that match the First Priority criteria. Unless otherwise stated, use a value of 0 to disable a rule. ConfigView.label.directory=\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4 ConfigView.label.disconnetseed.tooltip=\u05db\u05e9\u05de\u05e4\u05d9\u05e5 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05e0\u05ea\u05e7 \u05e9\u05d0\u05e8 \u05de\u05e4\u05d9\u05e6\u05d9\u05dd \n\u05d0\u05d9\u05e0\u05da \u05e6\u05e8\u05d9\u05da \u05dc\u05ea\u05e7\u05e9\u05e8 \u05d0\u05d9\u05ea\u05dd ConfigView.label.ignoreCase=\u05d4\u05ea\u05e2\u05dc\u05dd \u05de\u05d2\u05d5\u05d3\u05dc \u05d0\u05d5\u05ea ConfigView.label.ignoreSeeds=\u05d4\u05ea\u05e2\u05dc\u05dd \u05de\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05e2\u05dd \u05dc\u05e4\u05d7\u05d5\u05ea ConfigView.label.importdirectory=\u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05d9\u05d9\u05d1\u05d5\u05d0 ConfigView.label.minPeersToBoostNoSeeds.tooltip=\u05db\u05dc \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05dc\u05dc\u05d0 \u05de\u05e4\u05d9\u05e6\u05d9\u05dd \u05d5\u05e2\u05dd \u05e4\u05d7\u05d5\u05ea \u05de\u05e9\u05ea\u05e4\u05d9\u05dd \u05de\u05de\u05e1\u05e4\u05e8 \u05e9\u05ea\u05e7\u05d1\u05e2\n\u05d9\u05e2\u05d1\u05e8\u05d5 \u05dc\u05ea\u05d7\u05ea\u05d9\u05ea \u05d4\u05ea\u05d5\u05e8. ConfigView.label.minPeersToBoostNoSeeds=\u05d4\u05d5\u05e8\u05d3 \u05d3\u05d9\u05e8\u05d5\u05d2 \u05e9\u05d9\u05ea\u05d5\u05e3 \u05e2\u05d1\u05d5\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05dc\u05dc\u05d0 \u05de\u05e9\u05ea\u05e4\u05d9\u05dd \u05d5\u05e2\u05dd \u05e4\u05d7\u05d5\u05ea \u05de : ConfigView.label.minSeedingTime.tooltip=Seeding Ranks can fluctuate often in a short period time, sometimes causing the torrent to automatically start, only to be stopped && queued immediately afterwards.\nThis alleviates the problem by forcing the torrent to stay seeding for a given period of time. You can still stop it manually if you want. ConfigView.label.minSeedingTime=\u05d6\u05de\u05df \u05d4\u05e4\u05e6\u05d4 \u05de\u05d9\u05e0\u05d9\u05de\u05dc\u05d9 \u05d1\u05e9\u05e0\u05d9\u05d5\u05ea ConfigView.label.minSpeedForActiveDL.tooltip=\u05de\u05e7\u05d5\u05dd \u05d4\u05d5\u05e8\u05d3\u05d4 \u05e0\u05de\u05e6\u05d0 \u05ea\u05de\u05d9\u05d3 \u05d1\u05e9\u05d9\u05de\u05d5\u05e9 \u05d1-30 \u05d4\u05e9\u05e0\u05d9\u05d5\u05ea \u05d4\u05e8\u05d0\u05e9\u05d5\u05e0\u05d5\u05ea\n\u05dc\u05d0\u05d7\u05e8 \u05e9\u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 \u05d4\u05d1\u05dc\u05ea\u05d9-\u05d2\u05de\u05d5\u05e8 \u05de\u05ea\u05d7\u05d9\u05dc \u05d0\u05ea \u05e4\u05e2\u05d5\u05dc\u05ea\u05d5 ConfigView.label.minSpeedForActiveDL=\u05d0\u05dc \u05ea\u05d7\u05e9\u05d9\u05d1 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05db\u05de\u05e9\u05ea\u05de\u05e9 \u05d1\u05de\u05e7\u05d5\u05dd \u05d4\u05d5\u05e8\u05d3\u05d4 \u05db\u05d0\u05e9\u05e8 \u05d4\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05ea\u05d7\u05ea \u05dc ConfigView.label.peers=\u05de\u05e9\u05ea\u05e4\u05d9\u05dd ConfigView.label.queue.debuglog=\u05d4\u05db\u05e0\u05e1 \u05dc\u05d9\u05d5\u05de\u05df \u05de\u05d9\u05d3\u05e2 \u05e0\u05d9\u05e4\u05d5\u05d9 \u05e9\u05d2\u05d9\u05d0\u05d5\u05ea ConfigView.label.queue.debuglog.info=\u05de\u05d5\u05e1\u05d9\u05e3 \u05de\u05d9\u05d3\u05e2 \u05e0\u05d9\u05e4\u05d5\u05d9 \u05e9\u05d2\u05d9\u05d0\u05d5\u05ea \u05e9\u05dc \u05ea\u05d5\u05e8 \u05dc\u05d9\u05d5\u05de\u05df/\u05e7\u05d5\u05d1\u05e5.\n\u05de\u05de\u05d9\u05d3\u05e2 \u05e0\u05d9\u05e4\u05d5\u05d9 \u05d4\u05e9\u05d2\u05d9\u05d0\u05d5\u05ea \u05e0\u05d9\u05ea\u05df \u05dc\u05dc\u05de\u05d5\u05d3 \u05e2\u05dc \u05de\u05e6\u05d1 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d5\u05de\u05d3\u05d5\u05e2 \u05d0\u05d9\u05e0\u05dd \u05de\u05ea\u05d7\u05d9\u05dc\u05d9\u05dd ConfigView.label.queue.minQueueingShareRatio=\u05d0\u05dc \u05ea\u05e9\u05d9\u05dd \u05d1\u05ea\u05d5\u05e8 \u05d0\u05d5 \u05ea\u05e2\u05e6\u05d5\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05e2\u05d3 \u05e9\u05d9\u05d7\u05e1 \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 \u05e9\u05dc\u05d5 \u05d9\u05d2\u05d9\u05e2 \u05dc : ConfigView.label.ratio=\u05d9\u05d7\u05e1 ConfigView.label.removeOnStop=\u05d4\u05e1\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05de\u05d4\u05e8\u05e9\u05d9\u05de\u05d4 \u05dc\u05d0\u05d7\u05e8 \u05e9\u05d4\u05d5\u05d0 \u05de\u05e4\u05e1\u05d9\u05e7 \u05d1\u05e6\u05d5\u05e8\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea ConfigView.label.savedirectory=\u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05e9\u05de\u05d9\u05e8\u05d4 ConfigView.label.seeding.autoReposition=\u05de\u05e7\u05dd \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea \u05d1\u05d4\u05ea\u05d1\u05e1\u05e1 \u05e2\u05dc \u05d3\u05d9\u05e8\u05d5\u05d2 \u05d4\u05d4\u05e4\u05e6\u05d4 ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Often, torrents with low seed counts and high peer counts means that there probably isn't a full copy amoungst the peers.\nTherefore, you may not want the seeding rules pretending there's a full copy (and thus incorrectly reducing its rank) ConfigView.label.seeding.fakeFullCopySeedStart=\u05d0\u05d1\u05dc \u05e8\u05e7 \u05e2\u05d1\u05d5\u05e8 \u05d8\u05d5\u05e8\u05e0\u05d8 \u05e2\u05dd \u05dc\u05e4\u05d7\u05d5\u05ea ConfigView.label.seeding.ignore0Peers=\u05d4\u05ea\u05e2\u05dc\u05dd \u05de\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05dc\u05dc\u05d0 \u05de\u05e9\u05ea\u05e4\u05d9\u05dd ConfigView.label.seeding.ignoreRatioPeers=\u05d4\u05ea\u05e2\u05dc\u05dd \u05de\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05e9\u05d9\u05e9 \u05dc\u05d4\u05dd \u05dc\u05e4\u05d7\u05d5\u05ea \u05de\u05e9\u05ea\u05e3 \u05d0\u05d7\u05d3 \u05dc\u05db\u05dc ConfigView.label.seeding.ignoreShareRatio=\u05d4\u05ea\u05e2\u05dc\u05dd \u05de\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05e2\u05dd \u05d9\u05d7\u05e1 \u05e9\u05d9\u05ea\u05d5\u05e3 \u05e9\u05dc ConfigView.label.seeding.ignore.header.evenFirstPriority=\u05d4\u05ea\u05e2\u05dc\u05dd \u05de\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d0\u05e4\u05d9\u05dc\u05d5 \u05d0\u05dd\n\u05d7\u05dc\u05d9\u05dd \u05e2\u05dc\u05d9\u05d4\u05dd \u05db\u05dc\u05dc\u05d9 \u05e2\u05d3\u05d9\u05e4\u05d5\u05ea \u05e8\u05d0\u05e9\u05d5\u05e0\u05d4 ConfigView.label.seeding.ignore.header.rule=\u05db\u05dc\u05dc ConfigView.label.seeding.ignore.header.value=\u05e2\u05e8\u05da ConfigView.label.seeding.firstPriority.info=First Priority torrents will always be at the top of the queue. Any torrents matching the First Priority criteria will not be automatically stopped and queued. A torrent matching First Priority criteria will take a Simultaneous Download slot if it needs to. ConfigView.label.seeding.firstPriority=\u05e2\u05d3\u05d9\u05e4\u05d5\u05ea \u05e8\u05d0\u05e9\u05d5\u05e0\u05d4 \u05dc\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05e2\u05dd ConfigView.label.seeding.firstPriority.following=\u05de\u05d4\u05e1\u05d5\u05d2 \u05d4\u05d1\u05d0 : ConfigView.label.seeding.firstPriority.shareRatio=\u05d9\u05d7\u05e1 \u05d4\u05d5\u05e8\u05d3\u05d4 \u05de\u05ea\u05d7\u05ea \u05dc: ConfigView.label.seeding.firstPriority.seedingMinutes=\u05d6\u05de\u05df \u05d4\u05d4\u05de\u05ea\u05e0\u05d4 \u05d1\u05d9\u05df \u05de\u05e2\u05d1\u05e8 \u05de\u05d4\u05d5\u05e8\u05d3\u05d4 \u05dc\u05d4\u05e4\u05e6\u05d4 ConfigView.label.seeding.firstPriority.DLMinutes=\u05d4\u05d6\u05de\u05df \u05e9\u05e2\u05d1\u05e8 \u05de\u05d0\u05d6 \u05ea\u05d7\u05d9\u05dc\u05ea \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4. ConfigView.label.seeding.numPeersAsFullCopy=\u05d4\u05ea\u05d9\u05d9\u05d7\u05e1 \u05db\u05d0\u05d9\u05dc\u05d5 \u05d9\u05e9 \u05e2\u05d5\u05ea\u05e7 \u05e9\u05dc\u05dd \u05dc\u05db\u05dc\n(0 : \u05d0\u05dc \u05ea\u05ea\u05d9\u05d7\u05e1) ConfigView.label.seeding.preferLargerSwarms=\u05db\u05e9\u05dc\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d9\u05e9 \u05d0\u05ea \u05d0\u05d5\u05ea\u05d5 \u05d3\u05d9\u05e8\u05d5\u05d2 \u05d4\u05e2\u05d3\u05e3 \u05d0\u05ea \u05d6\u05d4 \u05e9\u05d9\u05e9 \u05dc\u05d5 \u05e7\u05d1\u05d5\u05e6\u05ea \u05de\u05e9\u05ea\u05e4\u05d9\u05dd \u05d2\u05d3\u05d5\u05dc\u05d4 \u05d9\u05d5\u05ea\u05e8 ConfigView.label.seeding.rankType.none.tooltip=\u05e1\u05d3\u05e8 \u05de\u05d1\u05d5\u05e1\u05e1 \u05e2\u05dc \u05e2\u05de\u05d5\u05d3\u05ea \u05de\u05e1\u05e4\u05e8 ConfigView.label.seeding.rankType.none=\u05e9\u05d5\u05dd \u05d3\u05d1\u05e8 ConfigView.label.seeding.rankType.peerSeed.options=\u05d0\u05e4\u05e9\u05e8\u05d5\u05d9\u05d5\u05ea \u05d9\u05d7\u05e1 \u05de\u05e4\u05d9\u05e6\u05d9\u05dd:\u05de\u05e9\u05ea\u05e4\u05d9\u05dd ConfigView.label.seeding.rankType.peerSeed.tooltip=\u05d9\u05d7\u05e1 \u05d2\u05d1\u05d5\u05d4 = \u05d3\u05d9\u05e8\u05d5\u05d2 \u05d2\u05d1\u05d5\u05d4 ConfigView.label.seeding.rankType.peerSeed=\u05de\u05e9\u05ea\u05e4\u05d9\u05dd:\u05d9\u05d7\u05e1 \u05e9\u05d9\u05ea\u05d5\u05e3 ConfigView.label.seeding.rankType.seed.options=\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05de\u05e1\u05e4\u05e8 \u05de\u05e9\u05ea\u05e4\u05d9\u05dd \u05d1\u05dc\u05d1\u05d3 ConfigView.label.seeding.rankType.seed.tooltip=\u05e4\u05d7\u05d5\u05ea \u05de\u05e9\u05ea\u05e4\u05d9\u05dd = \u05d3\u05d9\u05e8\u05d5\u05d2 \u05d2\u05d1\u05d5\u05d4 \u05d9\u05d5\u05ea\u05e8 ConfigView.label.seeding.rankType.seed=\u05de\u05e1\u05e4\u05e8 \u05de\u05e9\u05ea\u05e4\u05d9\u05dd \u05d1\u05dc\u05d1\u05d3 ConfigView.label.seeding.rankType.timedRotation=\u05ea\u05d7\u05dc\u05d5\u05e4\u05d4 \u05e2\u05dc \u05e4\u05d9 \u05d6\u05de\u05df ConfigView.label.seeding.rankType=\u05d3\u05e8\u05d2 \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d2\u05de\u05d5\u05e8\u05d9\u05dd \u05dc\u05d4\u05e4\u05e6\u05d4 \u05e2\u05dc \u05e4\u05d9: ConfigView.label.stopAfterMinutes=\u05d0\u05d7\u05e8\u05d9 \u05de\u05e2\u05d1\u05e8 \u05dc\u05d4\u05e4\u05e6\u05d4, \u05e2\u05e6\u05d5\u05e8 \u05dc\u05d0\u05d7\u05e8 \u05d6\u05de\u05df \u05de\u05e1\u05d5\u05d9\u05dd ConfigView.label.switchpriority.tooltip=\u05e2\u05d3\u05d9\u05e4\u05d5\u05ea \u05e0\u05de\u05d5\u05db\u05d4 \u05de\u05e7\u05d8\u05d9\u05e0\u05d4 \u05d0\u05ea \u05e8\u05d5\u05d7\u05d1 \u05d4\u05e4\u05e1 \u05d4\u05de\u05d5\u05e7\u05e6\u05d4 \u05dc\u05d4\u05e2\u05dc\u05d0\u05d4 \u05e2\u05d1\u05d5\u05e8 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 ConfigView.pluginlist.info=\u05d4\u05ea\u05d5\u05e1\u05e4\u05d5\u05ea \u05d4\u05d1\u05d0\u05d5\u05ea \u05d6\u05d5\u05d4\u05d5. \u05dc\u05d7\u05dc\u05e7 \u05de\u05d4\u05ea\u05d5\u05e1\u05e4\u05d5\u05ea \u05d0\u05d9\u05df \u05d0\u05e4\u05e9\u05e8\u05d5\u05ea \u05d4\u05d2\u05d3\u05e8\u05d4. ConfigView.pluginlist.noplugins=\u05dc\u05d0 \u05e0\u05de\u05e6\u05d0\u05d5 \u05ea\u05d5\u05e1\u05e4\u05d5\u05ea ConfigView.section.pluginslist=\u05e8\u05e9\u05d9\u05de\u05d4 ConfigView.section.queue.seeding=\u05d4\u05e4\u05e6\u05d4 ConfigView.section.queue.seeding.autoStarting=\u05d4\u05ea\u05d7\u05dc\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea ConfigView.section.queue.seeding.ignore=\u05db\u05dc\u05dc\u05d9 \u05d4\u05ea\u05e2\u05dc\u05de\u05d5\u05ea ConfigView.section.queue.seeding.firstPriority=\u05e2\u05d3\u05d9\u05e4\u05d5\u05ea \u05e8\u05d0\u05e9\u05d5\u05e0\u05d4 ConfigView.section.queue.main=\u05e8\u05d0\u05e9\u05d9 ConfigView.section.queue=\u05ea\u05d5\u05e8 ConfigView.section.torrents=\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd ConfigView.text.all=\u05d4\u05db\u05dc ConfigView.text.hours=\u05e9\u05e2\u05d5\u05ea ConfigView.text.ignoreRule=\u05db\u05dc\u05dc \u05d4\u05ea\u05e2\u05dc\u05de\u05d5\u05ea ConfigView.text.ignore=\u05d4\u05ea\u05e2\u05dc\u05dd ConfigView.text.minutes=\u05d3\u05e7\u05d5\u05ea ConfigView.text.neverIgnore=\u05d0\u05e3 \u05e4\u05e2\u05dd \u05d0\u05dc \u05ea\u05ea\u05e2\u05dc\u05dd ConfigView.text.any=\u05db\u05dc\u05e9\u05d4\u05d5 DownloadManager.error.datamissing=\u05de\u05d9\u05d3\u05e2 \u05d7\u05e1\u05e8 MainWindow.menu.file.open.torrentforseeding=(\u05e7\u05d5\u05d1\u05e5 \u05d8\u05d5\u05e8\u05e0\u05d8 (\u05dc\u05d4\u05e4\u05e6\u05d4 MainWindow.menu.language.refresh=\u05e8\u05e2\u05e0\u05df ManagerItem.forced=\u05de\u05d0\u05d5\u05dc\u05e5 ManagerItem.queued=\u05d1\u05ea\u05d5\u05e8 MySeedersView.header=\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05e9\u05dc\u05de\u05d9\u05dd/\u05dc\u05d4\u05e4\u05e6\u05d4 TableColumn.header.availability.info=\u05de\u05e1\u05e4\u05e8 \u05e2\u05d5\u05ea\u05e7\u05d9\u05dd \u05e9\u05dc\u05de\u05d9\u05dd \u05e9\u05e0\u05e8\u05d0\u05d5 TableColumn.header.availability=\u05d6\u05de\u05d9\u05e0\u05d5\u05ea TableColumn.header.category=\u05e7\u05d8\u05d2\u05d5\u05e8\u05d9\u05d4 MyTorrentsView.header=\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d7\u05dc\u05e7\u05d9\u05d9\u05dd/\u05dc\u05d4\u05d5\u05e8\u05d3\u05d4 TableColumn.header.maxuploads=\u05de\u05e1\u05e4\u05e8 \u05d4\u05e2\u05dc\u05d0\u05d5\u05ea \u05de\u05d9\u05e8\u05d1\u05d9 MyTorrentsView.menu.category.delete=\u05de\u05d7\u05e7 \u05e7\u05d8\u05d2\u05d5\u05e8\u05d9\u05d4 MyTorrentsView.menu.forceStart=\u05d4\u05db\u05e8\u05d7 \u05d4\u05ea\u05d7\u05dc\u05d4 MyTorrentsView.menu.queue=\u05d4\u05db\u05e0\u05e1 \u05dc\u05ea\u05d5\u05e8 MyTorrentsView.menu.setCategory.add=\u05d4\u05d5\u05e1\u05e3 \u05e7\u05d8\u05d2\u05d5\u05e8\u05d9\u05d4 MyTorrentsView.menu.setCategory=\u05e7\u05d1\u05e2 \u05e7\u05d8\u05d2\u05d5\u05e8\u05d9\u05d4 TableColumn.header.savepath=\u05e0\u05ea\u05d9\u05d1 \u05e9\u05de\u05d9\u05e8\u05d4 TableColumn.header.SeedingRank=\u05d3\u05d9\u05e8\u05d5\u05d2 \u05d4\u05e4\u05e6\u05d4 TableColumn.header.totalspeed.info=\u05d4\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05db\u05d5\u05dc\u05dc\u05ea \u05e9\u05dc \u05db\u05dc \u05d4\u05de\u05e9\u05ea\u05e4\u05d9\u05dd \u05d0\u05dc\u05d9\u05d4\u05dd \u05d0\u05ea\u05d4 \u05de\u05d7\u05d5\u05d1\u05e8 TableColumn.header.totalspeed=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05db\u05dc\u05dc\u05d9\u05ea splash.initializePlugins=\u05de\u05d0\u05ea\u05d7\u05dc \u05ea\u05d5\u05e1\u05e4\u05d5\u05ea StartStopRules.0Peers=\u05d0\u05d9\u05df \u05de\u05e9\u05ea\u05e4\u05d9\u05dd StartStopRules.numSeedsMet=\u05de\u05e1\u05e4\u05e8 \u05de\u05e4\u05d9\u05e6\u05d9\u05dd \u05d1\u05e1\u05d3\u05e8 StartStopRules.ratioMet=\u05de\u05ea\u05e4\u05e9\u05d9\u05dd:\u05de\u05e4\u05d9\u05e6\u05d9\u05dd \u05d1\u05e1\u05d3\u05e8 StartStopRules.shareRatioMet=\u05d9\u05d7\u05e1 \u05e9\u05d9\u05ea\u05d5\u05e3 \u05d1\u05e1\u05d3\u05e8 StartStopRules.waiting=\u05de\u05de\u05ea\u05d9\u05df StartStopRules.firstPriority=\u05e2\u05d3\u05d9\u05e4\u05d5\u05ea \u05e8\u05d0\u05e9\u05d5\u05e0\u05d4 ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=(\u05e9\u05ea\u05e3 \u05ea\u05d5\u05db\u05df (\u05db\u05d5\u05dc\u05dc \u05ea\u05ea-\u05ea\u05d9\u05e7\u05d9\u05d5\u05ea DownloadManager.error.unabletostartserver=\u05dc\u05d0 \u05de\u05e1\u05d5\u05d2\u05dc \u05dc\u05d4\u05e4\u05e2\u05d9\u05dc \u05e9\u05e8\u05ea - \u05d1\u05d3\u05d5\u05e7 \u05d0\u05ea \u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05e4\u05d5\u05e8\u05d8 \u05d4\u05ea\u05e7\u05e9\u05d5\u05e8\u05ea \u05d4\u05e0\u05db\u05e0\u05e1\u05ea / \u05d7\u05d5\u05de\u05ea \u05d4\u05d0\u05e9 \u05d4\u05d0\u05dd \u05de\u05d0\u05e4\u05e9\u05e8\u05d9\u05dd \u05dc\u05ea\u05d5\u05db\u05e0\u05d4 \u05dc\u05e4\u05e2\u05d5\u05dc \u05db\u05e9\u05e8\u05ea GeneralView.label.creationdate=\u05e0\u05d5\u05e6\u05e8 \u05d1 : ManagerItem.stopping=\u05e2\u05d5\u05e6\u05e8 MyTrackerView.scrapes=\u05d1\u05ea\u05e1\u05d1\u05d5\u05db\u05ea fileDownloadWindow.retry=\u05e0\u05e1\u05d4 \u05e9\u05e0\u05d9\u05ea MyTrackerView.bytesin=\u05d1\u05d9\u05d9\u05d8\u05d9\u05dd \u05e0\u05db\u05e0\u05e1\u05d9\u05dd MyTrackerView.bytesinave=\u05de\u05de\u05d5\u05e6\u05e2 \u05d1\u05d9\u05d9\u05d8\u05d9\u05dd \u05e0\u05db\u05e0\u05e1\u05d9\u05dd MyTrackerView.bytesout=\u05d1\u05d9\u05d9\u05d8\u05d9\u05dd \u05d9\u05d5\u05e6\u05d0\u05d9\u05dd MyTrackerView.bytesoutave=\u05de\u05de\u05d5\u05e6\u05e2 \u05d1\u05d9\u05d9\u05d8\u05d9\u05dd \u05d9\u05d5\u05e6\u05d0\u05d9\u05dd ConfigView.section.file.max_open_files=\u05de\u05e1\u05e4\u05e8 \u05e7\u05d1\u05e6\u05d9\u05dd \u05de\u05d9\u05e8\u05d1\u05d9 \u05dc\u05e7\u05e8\u05d9\u05d0\u05d4/\u05db\u05ea\u05d9\u05d1\u05d4\n0 = \u05d1\u05dc\u05ea\u05d9 \u05de\u05d5\u05d2\u05d1\u05dc ConfigView.section.file.max_open_files.tooltip=\u05e9\u05d9\u05de\u05d5\u05e9\u05d9 \u05d1\u05d4\u05d5\u05e8\u05d3\u05ea \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd \u05d4\u05de\u05db\u05d9\u05dc\u05d9\u05dd \u05de\u05d0\u05d5\u05ea \u05d0\u05d5 \u05d0\u05dc\u05e4\u05d9 \u05e7\u05d1\u05e6\u05d9\u05dd, \u05d5\u05d0\u05dd \u05de\u05e2\u05e8\u05db\u05ea \u05d4\u05d4\u05e4\u05e2\u05dc\u05d4 \u05e9\u05dc\u05da \u05de\u05d2\u05d9\u05e2\u05d4 \u05dc\u05d2\u05d1\u05d5\u05dc\u05d5\u05ea \u05d4\u05e4\u05e2\u05d5\u05dc\u05d4 \u05e9\u05dc\u05d4. ConfigView.section.proxy=\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05e4\u05e8\u05d5\u05e7\u05e1\u05d9 ConfigView.section.proxy.enable_proxy=\u05d0\u05e4\u05e9\u05e8 \u05e4\u05e8\u05d5\u05e7\u05e1\u05d9 ConfigView.section.proxy.host=\u05e9\u05e8\u05ea ConfigView.section.proxy.port=\u05e4\u05d5\u05e8\u05d8 ConfigView.section.proxy.username=\u05e9\u05dd \u05de\u05e9\u05ea\u05de\u05e9 ConfigView.section.proxy.password=\u05e1\u05d9\u05e1\u05de\u05d4 ConfigView.section.proxy.enable_socks=\u05d9\u05e9 \u05dc\u05d9 \u05e9\u05e8\u05ea \u05e4\u05e8\u05d5\u05e7\u05e1\u05d9 SOCKS wizard.createtorrent.extrahashes=(Gnutella2, eDonkey2000 : \u05d4\u05d5\u05e1\u05e3 \u05d4\u05d0\u05e9\u05d9\u05dd \u05dc\u05e8\u05e9\u05ea\u05d5\u05ea \u05d0\u05d7\u05e8\u05d5\u05ea? (\u05dc\u05d3\u05d5\u05d2\u05de\u05d0 GeneralView.label.connected=\u05de\u05d7\u05d5\u05d1\u05e8\u05d9\u05dd GeneralView.label.in_swarm=\u05d1\u05e7\u05d1\u05d5\u05e6\u05d4 ManagerItem.initializing=\u05de\u05d0\u05ea\u05d7\u05dc AlertMessageBox.error=\u05e9\u05d2\u05d9\u05d0\u05d4 AlertMessageBox.warning=\u05d0\u05d6\u05d4\u05e8\u05d4 AlertMessageBox.comment=\u05de\u05d9\u05d3\u05e2 AlertMessageBox.information=\u05de\u05d9\u05d3\u05e2 SharedPortServer.alert.selectorfailed=\u05e0\u05db\u05e9\u05dc \u05d1\u05d4\u05d0\u05d6\u05e0\u05d4 \u05dc\u05ea\u05e7\u05e9\u05d5\u05e8\u05ea \u05e0\u05db\u05e0\u05e1\u05ea\n\u05d1\u05d3\u05d5\u05e7 \u05d0\u05ea \u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05d7\u05d5\u05de\u05ea \u05d4\u05d0\u05e9 \u05e9\u05dc\u05da \u05d4\u05d0\u05dd \u05de\u05d0\u05e4\u05e9\u05e8\u05d9\u05dd \u05dc\u05d2'\u05d0\u05d5\u05d5\u05d4 (java(w).exe) \u05dc\u05e9\u05de\u05e9 \u05db\u05e9\u05e8\u05ea. Tracker.alert.listenfail=\u05e0\u05db\u05e9\u05dc \u05d1\u05e4\u05ea\u05d9\u05d7\u05ea \u05d4\u05d0\u05d6\u05e0\u05d4 \u05d1\u05e4\u05d5\u05e8\u05d8 %1.\nC\u05d1\u05d3\u05d5\u05e7 \u05d0\u05dd \u05d9\u05d9\u05e9\u05d5\u05de\u05d9\u05dd \u05d0\u05d7\u05e8\u05d9\u05dd \u05d0\u05d9\u05e0\u05dd \u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05d1\u05e4\u05d5\u05e8\u05d8 \u05d6\u05d4.\n\u05db\u05de\u05d5 \u05db\u05df \u05d1\u05d3\u05d5\u05e7 \u05d0\u05dd \u05e2\u05d5\u05ea\u05e7\u05d9\u05dd \u05e0\u05d5\u05e1\u05e4\u05d9\u05dd \u05e9\u05dc \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 \u05e4\u05d5\u05e2\u05dc\u05d9\u05dd DiskManager.alert.movefileexists=\u05e9\u05d2\u05d9\u05d0\u05d4 \u05d1\u05d4\u05e2\u05d1\u05e8\u05ea \u05e7\u05d5\u05d1\u05e5\n\u05d4\u05e7\u05d5\u05d1\u05e5 %1 \u05e0\u05de\u05e6\u05d0 \u05db\u05d1\u05e8 \u05d1\u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05d4\u05d9\u05e2\u05d3 DiskManager.alert.movefilefails=\u05e9\u05d2\u05d9\u05d0\u05d4 \u05d1\u05d4\u05e2\u05d1\u05e8\u05ea \u05e7\u05d1\u05e6\u05d9\u05dd\n\u05d4\u05e2\u05d1\u05e8\u05ea %1 \u05e0\u05db\u05e9\u05dc\u05d4, %2 DiskManager.alert.movefilerecoveryfails=\u05e9\u05d2\u05d9\u05d0\u05d4 \u05d1\u05de\u05d4\u05dc\u05da \u05d4\u05ea\u05d0\u05d5\u05e9\u05e9\u05d5\u05ea\n\u05e9\u05d9\u05d7\u05d6\u05d5\u05e8 %1\u05e0\u05db\u05e9\u05dc, %2 ConfigView.section.tracker.logenable='tracker.log' \u05d4\u05db\u05e0\u05e1 \u05e1\u05d8\u05d8\u05d9\u05e1\u05d8\u05d9\u05e7\u05d4 \u05ea\u05e7\u05d5\u05e4\u05ea\u05d9\u05ea \u05dc\u05e7\u05d5\u05d1\u05e5 \u05d9\u05d5\u05de\u05df SpeedView.stats.title=\u05de\u05e6\u05d1 SpeedView.stats.total=\u05e1\u05da \u05d4\u05db\u05dc SpeedView.stats.session=\u05d4\u05e4\u05e2\u05dc\u05d4 \u05e0\u05d5\u05db\u05d7\u05d9\u05ea SpeedView.stats.downloaded=\u05d9\u05e8\u05d3 SpeedView.stats.uploaded=\u05e2\u05dc\u05d4 SpeedView.stats.uptime=(\u05d6\u05de\u05df \u05e4\u05e2\u05d5\u05dc\u05d4 (\u05e9\u05e2\u05d5\u05ea AutoMigration.useralert=\u05ea\u05d5\u05e6\u05d0\u05d5\u05ea \u05d4\u05e2\u05d1\u05e8\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea \u05e9\u05dc \u05e7\u05d1\u05e6\u05d9\u05dd/\u05ea\u05d9\u05e7\u05d9\u05d5\u05ea :\n\n%1\n%2 \u05db\u05dc \u05ea\u05e7\u05dc\u05d4 \u05d9\u05e9 \u05dc\u05d4\u05e2\u05d1\u05d9\u05e8 \u05d1\u05e6\u05d5\u05e8\u05d4 \u05d9\u05d3\u05e0\u05d9\u05ea # # > 2.0.8.0 # OpenTorrentWindow.title=(\u05e4\u05ea\u05d7 \u05d8\u05d5\u05e8\u05e0\u05d8(\u05d9\u05dd OpenTorrentWindow.message=\u05e0\u05d9\u05e1\u05d9\u05d5\u05e0\u05d9 OpenTorrentWindow.addFiles=\u05d4\u05d5\u05e1\u05e3 \u05e7\u05d1\u05e6\u05d9\u05dd OpenTorrentWindow.dataLocation=\u05d9\u05e2\u05d3 \u05dc\u05e9\u05de\u05d9\u05e8\u05ea \u05de\u05d9\u05d3\u05e2: OpenTorrentWindow.startMode=\u05de\u05e6\u05d1 \u05d4\u05d5\u05e1\u05e4\u05d4 OpenTorrentWindow.startMode.queued=\u05d1\u05ea\u05d5\u05e8 OpenTorrentWindow.startMode.stopped=\u05e2\u05e6\u05e8 OpenTorrentWindow.startMode.forceStarted=\u05de\u05d0\u05d5\u05dc\u05e5 \u05dc\u05d4\u05ea\u05d7\u05d9\u05dc OpenTorrentWindow.addPosition=\u05de\u05d9\u05e7\u05d5\u05dd \u05d1\u05ea\u05d5\u05e8 OpenTorrentWindow.addPosition.first=\u05e8\u05d0\u05e9\u05d5\u05df OpenTorrentWindow.addPosition.last=\u05d0\u05d7\u05e8\u05d5\u05df TableColumn.header.remaining.info=\u05d6\u05de\u05df \u05e0\u05d5\u05ea\u05e8 \u05dc\u05e1\u05d9\u05d5\u05dd \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 TableColumn.header.remaining=\u05e0\u05d5\u05ea\u05e8 popup.error.hide=\u05d4\u05e1\u05ea\u05e8 popup.error.details=\u05e4\u05e8\u05d8\u05d9\u05dd MainWindow.status.tooOld=\u05d4\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d9\u05e9\u05e0\u05d4, \u05d0\u05e0\u05d0 \u05e2\u05d3\u05db\u05df \u05d0\u05d5\u05ea\u05d4 ConfigView.label.max_peers_per_torrent=Maximum number of connections per torrent [0: unlimited] ConfigView.label.max_peers_total=Maximum number of connections globally [0: unlimited] Button.revert=\u05d4\u05e4\u05d5\u05da GenericText.column=\u05d8\u05d5\u05e8 MyTorrentsView.menu.thisColumn.remove=\u05d4\u05e1\u05e8 \u05d8\u05d5\u05e8 MyTorrentsView.menu.thisColumn.toClipboard=\u05d4\u05e2\u05ea\u05e7 \u05d8\u05e7\u05e1\u05d8 \u05dc\u05dc\u05d5\u05d7 MyTorrentsView.menu.tracker=\u05d8\u05e8\u05d0\u05e7\u05e8 TableColumn.header.secondsseeding=\u05de\u05e4\u05d9\u05e5 \u05d1\u05de\u05e9\u05da TableColumn.header.secondsseeding.info=\u05d4\u05d6\u05de\u05df \u05d4\u05db\u05d5\u05dc\u05dc \u05e9\u05d1\u05de\u05d4\u05dc\u05db\u05d5 \u05d4\u05d5\u05e4\u05e5 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 TableColumn.header.secondsdownloading=\u05de\u05d5\u05e8\u05d9\u05d3 \u05d1\u05de\u05e9\u05da TableColumn.header.secondsdownloading.info=\u05d4\u05d6\u05de\u05df \u05d4\u05db\u05d5\u05dc\u05dc \u05e9\u05d1\u05de\u05d4\u05dc\u05db\u05d5 \u05d4\u05d5\u05e8\u05d3 \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 window.updateswt.status=\u05de\u05e6\u05d1 window.updateswt.ok=\u05d0\u05d9\u05e9\u05d5\u05e8 window.updateswt.cancel=\u05d1\u05d9\u05d8\u05d5\u05dc window.updateswt.ignore=\u05d4\u05ea\u05e2\u05dc\u05dd splash.initializeGM=\u05de\u05d0\u05ea\u05d7\u05dc \u05d0\u05ea \u05de\u05e0\u05d4\u05dc \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd splash.loadingTorrents=\u05d8\u05d5\u05e2\u05df \u05d8\u05d5\u05e8\u05e0\u05d8\u05d9\u05dd splash.firstMessageNoI18N=(: \u05d0\u05d6\u05d5\u05e8\u05d0\u05d5\u05e1 :) MyTorrentsView.menu.thisColumn.sort=\u05de\u05d9\u05d9\u05df MyTrackerView.webui.contextmenu.copyurl=\u05d4\u05e2\u05ea\u05e7 \u05d0\u05ea \u05db\u05ea\u05d5\u05d1\u05ea \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 \u05dc\u05dc\u05d5\u05d7 Torrent.create.progress.ignoringfile=\u05de\u05ea\u05e2\u05dc\u05dd \u05de\u05e7\u05d5\u05d1\u05e5 Button.yes=\u05db\u05df Button.no=\u05dc\u05d0 dialog.associations.askagain=\u05d1\u05d3\u05d5\u05e7 \u05d1\u05d4\u05e4\u05e2\u05dc\u05d4 Plugin.pluginupdate.enablecheck=\u05d0\u05e4\u05e9\u05e8 \u05d1\u05d3\u05d9\u05e7\u05ea \u05e2\u05d9\u05d3\u05db\u05d5\u05df \u05ea\u05d5\u05e1\u05e4\u05ea plugins.basicview.status=\u05de\u05e6\u05d1: plugins.basicview.activity=\u05e4\u05e2\u05d9\u05dc\u05d5\u05ea: plugins.basicview.progress=\u05d4\u05ea\u05e7\u05d3\u05de\u05d5\u05ea: plugins.basicview.log=\u05d9\u05d5\u05de\u05df: splash.loadingTorrent=\u05d8\u05d5\u05e2\u05df \u05d8\u05d5\u05e8\u05e0\u05d8 splash.of=\u05de\u05ea\u05d5\u05da MainWindow.statusText.checking=\u05de\u05d7\u05e4\u05e9 \u05e2\u05d9\u05d3\u05db\u05d5\u05e0\u05d9\u05dd MainWindow.menu.help.whatsnew=\u05d7\u05d9\u05d3\u05d5\u05e9\u05d9\u05dd MainWindow.updateavail=(\u05e7\u05d9\u05d9\u05dd \u05e2\u05d9\u05d3\u05db\u05d5\u05df) GeneralView.label.updatein.stopped=\u05e2\u05e6\u05e8 StartStopRules.menu.viewDebug=\u05d4\u05e6\u05d2 \u05de\u05d9\u05d3\u05e2 \u05e0\u05d9\u05e4\u05d5\u05d9 \u05e9\u05d2\u05d9\u05d0\u05d5\u05ea MainWindow.menu.help.plugins=\u05ea\u05d5\u05e1\u05e4\u05d5\u05ea security.certcreate.cancel=\u05d1\u05d9\u05d8\u05d5\u05dc webui.passwordenable=\u05d0\u05e4\u05e9\u05e8 \u05e1\u05d9\u05e1\u05de\u05d4 webui.user=\u05e9\u05dd \u05de\u05e9\u05ea\u05de\u05e9 webui.password=\u05e1\u05d9\u05e1\u05de\u05d4 webui.port=(*) \u05e4\u05d5\u05e8\u05d8 webui.protocol=(*) \u05e4\u05e8\u05d5\u05d8\u05d5\u05e7\u05d5\u05dc webui.homepage=(*) \u05d3\u05e3 \u05d1\u05d9\u05ea webui.mode=(*) \u05de\u05e6\u05d1 webui.access=(*) \u05d2\u05d9\u05e9\u05d4 GeneralView.label.maxdownloadspeed=\u05d4\u05d5\u05e8\u05d3\u05d4 \u05de\u05d9\u05e8\u05d1\u05d9\u05ea GeneralView.label.maxdownloadspeed.tooltip=[\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05d5\u05e8\u05d3\u05d4 \u05de\u05d9\u05e8\u05d1\u05d9\u05ea [\u05d1\u05dc\u05ea\u05d9 \u05de\u05d5\u05d2\u05d1\u05dc : 0 upnp.enable=UPnP \u05d0\u05e4\u05e9\u05e8 upnp.refresh.button=\u05e8\u05e2\u05e0\u05df blank.resource=\u05de\u05e9\u05d0\u05d1 Peers.column.DLedFromOthers=\u05de\u05d0\u05d7\u05e8\u05d9\u05dd Peers.column.DLedFromOthers.info=\u05db\u05de\u05d5\u05ea \u05d4\u05de\u05d9\u05d3\u05e2 \u05e9\u05d9\u05e8\u05d3\u05d4 \u05de\u05d0\u05d7\u05e8\u05d9\u05dd \u05d1\u05d6\u05de\u05df \u05d4\u05d7\u05d9\u05d1\u05d5\u05e8 \u05d0\u05dc\u05d9\u05da Peers.column.UpDownRatio=\u05d9\u05e8\u05d3:\u05e2\u05dc\u05d4 Peers.column.UpRatio=\u05d9\u05d7\u05e1 \u05d4\u05e2\u05dc\u05d0\u05d4 Button.clear=\u05e0\u05e7\u05d4 MainWindow.IPs.tooltip=\u05de\u05e1\u05e4\u05e8 \u05d8\u05d5\u05d5\u05d7\u05d9 \u05d0\u05d9\u05d9.\u05e4\u05d9. \u05d1\u05de\u05e1\u05e0\u05df - \u05de\u05e1\u05e4\u05e8 \u05db\u05ea\u05d5\u05d1\u05d5\u05ea \u05d4\u05d0\u05d9\u05d9.\u05e4\u05d9. \u05d4\u05d7\u05e1\u05d5\u05de\u05d5\u05ea.\n\u05dc\u05d7\u05e5 \u05dc\u05d7\u05d9\u05e6\u05d4 \u05db\u05e4\u05d5\u05dc\u05d4 \u05dc\u05e4\u05e8\u05d8\u05d9\u05dd ConfigView.section.ipfilter.list.banned=has been banned for sending bad data Button.reset=\u05d0\u05ea\u05d7\u05dc download.removerules.unauthorised.info=Unauthorised torrents are those where the announce response contains either "not authoris(z)ed" or "unauthoris(z)ed" in the "failure response" download.removerules.unauthorised=Automatically remove unauthorised torrents ConfigView.section.server.enableudp=Enable UDP tracker client protocol. ConfigView.section.tracker.publishenabledetails=Publish torrent file and peer details MyTrackerView.badnat=\u05d1\u05e2\u05d9\u05d9\u05ea \u05ea\u05e7\u05e9\u05d5\u05e8\u05ea #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u05d4\u05e2\u05d1\u05e8\u05d5\u05ea MainWindow.menu.transfers.startalltransfers=\u05d4\u05ea\u05d7\u05dc \u05d4\u05db\u05dc MainWindow.menu.transfers.stopalltransfers=\u05e2\u05e6\u05d5\u05e8 \u05d4\u05db\u05dc MainWindow.menu.transfers.pausetransfers=\u05d4\u05e9\u05d4\u05d4 MainWindow.menu.transfers.resumetransfers=\u05d4\u05de\u05e9\u05da SystemTray.menu.pausetransfers=\u05d4\u05e9\u05d4\u05d4 \u05d4\u05e2\u05d1\u05e8\u05d5\u05ea SystemTray.menu.resumetransfers=\u05d7\u05d3\u05e9 \u05d4\u05e2\u05d1\u05e8\u05d5\u05ea PeerManager.status.error=\u05e9\u05d2\u05d9\u05d0\u05d4 Stats.title.full=\u05e1\u05d8\u05d8\u05d9\u05e1\u05d8\u05d9\u05e7\u05d4 TransferStatsView.title.full=\u05d4\u05e2\u05d1\u05e8\u05d5\u05ea CacheView.general.size=\u05d2\u05d5\u05d3\u05dc \u05db\u05d5\u05dc\u05dc CacheView.general.inUse=\u05d1\u05e9\u05d9\u05de\u05d5\u05e9\n CacheView.reads.fromFile=\u05de\u05e7\u05d5\u05d1\u05e5 CacheView.writes.toFile=\u05dc\u05e7\u05d5\u05d1\u05e5 CacheView.writes.hits=\u05e0\u05e9\u05de\u05e8 CacheView.speeds.reads=\u05e4\u05e2\u05d5\u05dc\u05d5\u05ea \u05e7\u05e8\u05d9\u05d0\u05d4 CacheView.speeds.writes=\u05e4\u05e2\u05d5\u05dc\u05d5\u05ea \u05db\u05ea\u05d9\u05d1\u05d4 CacheView.speeds.fromFile=\u05de/\u05d0\u05dc \u05e7\u05d5\u05d1\u05e5 CacheView.reads.#=\u05de\u05e1\u05e4\u05e8 CacheView.reads.amount=\u05db\u05de\u05d5\u05ea CacheView.reads.avgsize=\u05d2\u05d5\u05d3\u05dc \u05de\u05de\u05d5\u05e6\u05e2 ConfigView.label.maxuploadspeedseeding=KB/s global max upload speed when only seeding [0: unlimited] authenticator.torrent=\u05d8\u05d5\u05e8\u05e0\u05d8\n ConfigView.section.file.perf.cache.size.explain=The cache is used to reduce reads from/writes to disk. Unless you are using the java option '-XX:MaxDirectMemorySize' to explicitly set the memory available for cache and network IO use, you should keep this value at least %1 below your maximum VM size. The current maximum VM size is %2. For instructions on how to change this, see MemoryUsage in the wiki on %3. Failure to use sensible settings will result on 'out of memory' errors. More than 32MB of cache is probably overkill. MyTorrentsView.menu.setSpeed.unlimit=\u05dc\u05dc\u05d0 \u05d4\u05d2\u05d1\u05dc\u05d4 MyTorrentsView.menu.setSpeed.unlimited=\u05d1\u05dc\u05ea\u05d9 \u05de\u05d5\u05d2\u05d1\u05dc MyTorrentsView.menu.setSpeed.disable=\u05d1\u05d8\u05dc \u05d4\u05e2\u05dc\u05d0\u05d4 MyTorrentsView.menu.setSpeed.disabled=\u05de\u05d1\u05d5\u05d8\u05dc GeneralView.label.maxuploadspeed=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05e2\u05dc\u05d0\u05d4 \u05de\u05d9\u05e8\u05d1\u05d9\u05ea GeneralView.label.maxuploadspeed.tooltip=[\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05e2\u05dc\u05d0\u05d4 \u05de\u05d9\u05e8\u05d1\u05d9\u05ea [\u05d1\u05dc\u05ea\u05d9 \u05de\u05d5\u05d2\u05d1\u05dc : 0 MyTorrents.items.UpSpeedLimit.disabled=\u05dc\u05dc\u05d0 \u05d4\u05e2\u05dc\u05d0\u05d4 MyTorrents.items.UpSpeedLimit.unlimited=\u05d1\u05dc\u05ea\u05d9 \u05de\u05d5\u05d2\u05d1\u05dc TableColumn.header.maxupspeed=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05e2\u05dc\u05d0\u05d4 \u05de\u05d9\u05e8\u05d1\u05d9\u05ea TableColumn.header.maxupspeed.info=\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05d4\u05e2\u05dc\u05d0\u05d4 \u05de\u05d9\u05e8\u05d1\u05d9\u05ea \u05dc\u05d8\u05d5\u05e8\u05e0\u05d8 MainWindow.menu.tools=\u05db\u05dc\u05d9\u05dd FilesView.path=\u05e0\u05ea\u05d9\u05d1 FilesView.fullpath=\u05d4\u05e6\u05d2 \u05e0\u05ea\u05d9\u05d1 \u05de\u05dc\u05d0 FilesView.remaining=\u05d7\u05dc\u05e7\u05d9\u05dd \u05e9\u05e0\u05d5\u05ea\u05e8\u05d5 TableColumn.header.trackername=\u05e9\u05dd \u05d4\u05d8\u05e8\u05d0\u05e7\u05e8 TableColumn.header.trackername.info=\u05e9\u05dd \u05d4\u05d8\u05e8\u05d0\u05e7\u05e8, \u05de\u05d1\u05d5\u05e1\u05e1 \u05e2\u05dc \u05db\u05ea\u05d5\u05d1\u05ea \u05d4\u05d4\u05db\u05e8\u05d6\u05d4 ConfigView.group.override=\u05e2\u05e7\u05d5\u05e3 \u05d0\u05e4\u05e9\u05e8\u05d5\u05d9\u05d5\u05ea PeersView.state.connecting=\u05de\u05ea\u05d7\u05d1\u05e8 PeersView.state.established=\u05d4\u05ea\u05d1\u05e1\u05e1 \u05d1\u05de\u05dc\u05d5\u05d0\u05d5 Torrent.create.progress.cancelled=\u05d4\u05e4\u05e2\u05d5\u05dc\u05d4 \u05d1\u05d5\u05d8\u05dc\u05d4 sharing.progress.cancel=\u05d1\u05d9\u05d8\u05d5\u05dc wizard.maketorrents.autoopen=\u05e4\u05ea\u05d7 \u05d0\u05ea \u05d4\u05d8\u05d5\u05e8\u05e0\u05d8 \u05dc\u05d4\u05e4\u05e6\u05d4 \u05d1\u05e1\u05d9\u05d5\u05dd ConfigView.section.connection.advanced=\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05e8\u05e9\u05ea \u05de\u05ea\u05e7\u05d3\u05de\u05d5\u05ea PeersView.connected_time=\u05d6\u05de\u05df \u05d7\u05d9\u05d1\u05d5\u05e8 PeersView.connected_time.info=\u05d6\u05de\u05df \u05d4\u05d7\u05d9\u05d1\u05d5\u05e8 \u05d4\u05db\u05d5\u05dc\u05dc \u05e2\u05dd \u05d4\u05de\u05e9\u05ea\u05de\u05e9 update.instance.update=\u05e1\u05d5\u05e8\u05e7 \u05e2\u05d1\u05d5\u05e8 \u05e2\u05d9\u05d3\u05db\u05d5\u05e0\u05d9\u05dd updater.progress.window.title=\u05d1\u05d8\u05dc \u05e4\u05e2\u05d5\u05dc\u05d5\u05ea \u05d4\u05ea\u05e7\u05e0\u05d4 Button.abort=\u05d1\u05d8\u05dc ConfigView.label.overrideip=\u05e2\u05e7\u05d5\u05e3 \u05db\u05ea\u05d5\u05d1\u05ea \u05d0\u05d9\u05d9.\u05e4\u05d9. \u05e9\u05e0\u05e9\u05dc\u05d7\u05ea \u05dc\u05d8\u05e8\u05e7\u05e8\n - \u05ea\u05e9\u05ea\u05de\u05e9 \u05e8\u05e7 \u05d0\u05dd \u05d0\u05ea\u05d4 \u05d9\u05d5\u05d3\u05e2 \u05dc\u05de\u05d4 \u05d1\u05d0\u05de\u05ea \u05d0\u05ea\u05d4 \u05e6\u05e8\u05d9\u05da \u05d6\u05d0\u05ea ConfigView.label.overrideip.tooltip=Inform the tracker of a different IP address than the one outgoing packets come from. Leave blank not to use the option. #file can be a URL or a path in the jar diagnostics.log_found=Vuze did not shutdown tidily. Please check %1 for diagnostic log files and consider reporting them to the Vuze team if this is the result of an application error. ConfigView.section.logging.log0type=\u05de\u05d9\u05d3\u05e2 # %1 = "in kbps" or ""; %2 = "upload" or "download" OpenTorrentWindow.torrentLocation=Torrent Files: Button.moveUp=\u05d4\u05d6\u05d6 \u05de\u05e2\u05dc\u05d4 Button.moveDown=\u05d4\u05d6\u05d6 \u05dc\u05de\u05d8\u05d4 # > 2402 # Used for peers which we can't determine. PeerSocket.unknown=\u05dc\u05d0 \u05d9\u05d3\u05d5\u05e2 iconBar.queue.tooltip=\u05ea\u05d5\u05e8 MainWindow.menu.help.faq=\u05e9\u05d0\u05dc\u05d5\u05ea \u05d5\u05ea\u05e9\u05d5\u05d1\u05d5\u05ea MainWindow.menu.help.donate=\u05ea\u05e8\u05d5\u05dd azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_hy_AM.properties0000644000175000017500000004722611301156004026077 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file=&\u0556\u0561\u0575\u056c MainWindow.menu.file.open=&\u0532\u0561\u0581\u0565\u056c MainWindow.menu.file.create.fromfile=&\u0556\u0561\u0575\u056c\u056b\u0581 MainWindow.menu.file.closetab=\u0553\u0561\u056f\u0565\u056c &\u0576\u0565\u0580\u0564\u0580\u0578\u0582\u0574\u0568 MainWindow.menu.file.closewindow=\u0553\u0561\u056f\u0565\u056c &\u054a\u0561\u057f\u0578\u0582\u0570\u0561\u0576\u0568 MainWindow.menu.file.exit=&\u0535\u056c\u0584 MainWindow.menu.file.folder=&\u0539\u0572\u0569\u0561\u057a\u0561\u0576\u0561\u056f... MainWindow.menu.view=&\u054f\u0565\u057d\u0561\u0564\u0561\u0577\u057f MainWindow.menu.view.mytorrents=&\u053b\u0574 \u057f\u0578\u0580\u0580\u0565\u0576\u057f\u0576\u0565\u0580\u0568 MainWindow.menu.language=&\u053c\u0565\u0566\u0578\u0582 ConfigView.section.language=\u053c\u0565\u0566\u0578\u0582 MainWindow.menu.help=&\u0555\u0563\u0576\u0578\u0582\u0569\u0575\u0578\u0582\u0576 MyTorrentsView.mytorrents=\u053b\u0574 \u057f\u0578\u0580\u0580\u0565\u0576\u057f\u0576\u0565\u0580\u0568 TableColumn.header.name=\u0531\u0576\u0578\u0582\u0576\u0568 TableColumn.header.size=\u0549\u0561\u0583 TableColumn.header.downspeed=\u0532\u0565\u057c\u0576\u0574\u0561\u0576 \u0561\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0568 MyTorrentsView.menu.open=&\u0532\u0561\u0581\u0565\u056c PeersView.pieces=\u053f\u057f\u0578\u0580\u0576\u0565\u0580\u0568 PeersView.downloadspeed=\u0532\u0565\u057c\u0576\u0574\u0561\u0576 \u0561\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0568 PeersView.downloadspeedoverall=\u0538\u0576\u0564\u0570\u0561\u0576\u0578\u0582\u0580 \u0562\u0565\u057c\u0576\u0574\u0561\u0576 \u0561\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0568 ConfigView.section.files=\u0556\u0561\u0575\u056c\u0565\u0580\u0568 ConfigView.button.browse=&\u0539\u0565\u0580\u0569\u0565\u056c ConfigView.section.irc=Irc ConfigView.label.ircserver=\u054d\u0565\u0580\u057e\u0565\u0580 ConfigView.label.ircchannel=\u053f\u0561\u057a\u0578\u0582\u0572\u0572\u056b ConfigView.label.irclogin=\u0544\u0561\u056f\u0561\u0576\u0578\u0582\u0576 ConfigView.label.passwordconfirm=\u0533\u0561\u0572\u057f\u0576\u0561\u0562\u0561\u057c (\u0570\u0561\u057d\u057f\u0561\u057f\u0565\u056c) ConfigView.label.passwordmatchnone=\u0548\u0579 ConfigView.label.passwordmatchno=\u0548\u0579 / \u0533\u0561\u0572\u057f\u0576\u0561\u0562\u0561\u057c\u0568 \u057d\u056d\u0561\u056c \u0567 ConfigView.label.passwordmatchyes=\u0531\u0575\u0578 ConsoleView.title.short=\u053f\u0578\u0576\u057d\u0578\u056c ConsoleView.title.full=\u053f\u0578\u0576\u057d\u0578\u056c FileItem.normal=\u0576\u0578\u0580\u0574\u0561\u056c FileItem.high=\u0532\u0561\u0580\u0571\u0580 FilesView.name=\u0531\u0576\u0578\u0582\u0576 FilesView.size=\u0549\u0561\u0583 FilesView.pieces=\u053f\u057f\u0578\u0580\u0576\u0565\u0580\u0568 FilesView.mode=\u054c\u0565\u056a\u056b\u0574 FilesView.menu.open=&\u0532\u0561\u0581\u0565\u056c FilesView.menu.setpriority=&\u054f\u0561\u056c \u0533\u0565\u0580\u0561\u056f\u0561\u0575\u0578\u0582\u0569\u0575\u0578\u0582\u0576 FilesView.menu.setpriority.high=&\u0532\u0561\u0580\u0571\u0580 FilesView.menu.setpriority.normal=&\u0546\u0578\u0580\u0574\u0561\u056c FilesView.menu.setpriority.skipped=&\u0549\u0562\u0565\u057c\u0576\u0565\u056c FilesView.title.short=\u0556\u0561\u0575\u056c\u0565\u0580\u0568 FilesView.title.full=\u0556\u0561\u0575\u056c\u0565\u0580\u0568 GeneralView.label.status.file=\u0556\u0561\u0575\u056c\u056b \u057e\u056b\u0573\u0561\u056f\u0568 GeneralView.label.downloadspeed=\u0532\u0565\u057c\u0576\u0574\u0561\u0576 \u0561\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0568 : GeneralView.label.filename=\u0531\u0576\u0578\u0582\u0576 : GeneralView.label.size=\u0549\u0561\u0583 : GeneralView.label.comment=\u053b\u0576\u0586\u0578\u0580\u0574\u0561\u0581\u056b\u0561 : MinimizedWindow.name=\u0531\u0576\u0578\u0582\u0576: PiecesView.size=\u0549\u0561\u0583 PiecesView.blocks=\u0532\u056c\u0578\u056f\u0576\u0565\u0580\u0568 PiecesView.title.short=\u053f\u057f\u0578\u0580\u0576\u0565\u0580\u0568 PiecesView.title.full=\u053f\u057f\u0578\u0580\u0576\u0565\u0580\u0568 DownloadManager.error.ioerror=IO \u054d\u056d\u0561\u056c Button.next=\u0540\u0561\u057b\u0578\u0580\u0564 Button.finish=\u0531\u057e\u0561\u0580\u057f\u057e\u0565\u056c Button.cancel=\u0540\u0580\u0561\u056a\u0561\u0580\u057e\u0565\u056c PasswordWindow.title=Vuze \u0562\u056c\u0578\u056f\u0561\u057e\u0578\u0580\u057e\u0561\u056e \u0567 PasswordWindow.passwordprotected=Vuze \u057a\u0561\u0577\u057f\u057a\u0561\u0576\u057e\u0561\u056e \u0567 \u0563\u0561\u0572\u057f\u0576\u0561\u0562\u0561\u057c\u0578\u057e:\nAzureus-\u056b \u057a\u0561\u057f\u0578\u0582\u0570\u0561\u0576\u0568 \u0581\u0578\u0582\u0575\u0581 \u057f\u0561\u056c\u0578\u0582 \u0570\u0561\u0574\u0561\u0580 \u056f\u056d\u0576\u0564\u0580\u0565\u056b\u0576\u0584 \u0574\u0578\u0582\u057f\u0584\u0561\u0563\u0580\u0565\u056c \u0563\u0561\u0572\u057f\u0576\u0561\u0562\u0561\u057c\u0568 \u0561\u0575\u057d\u057f\u0565\u0572. Button.ok=\u0540\u0561\u057d\u057f\u0561\u057f\u0565\u056c discarded=\u0570\u0580\u0561\u056a\u0561\u0580\u057e\u0561\u056e \u0567 wizard.title=\u054d\u057f\u0565\u0572\u056e\u0565\u056c \u057f\u0578\u0580\u0580\u0565\u0576\u057f wizard.previous=< \u0535\u057f wizard.next=\u0540\u0561\u057b\u0578\u0580\u0564 > wizard.singlefile=\u0544\u056b \u0586\u0561\u0575\u056c wizard.singlefile.help=\u054d\u057f\u0565\u0572\u056e\u0565\u056c \u057f\u0578\u0580\u0580\u0565\u0576\u057f \u0574\u056b \u0586\u0561\u0575\u056c\u056b\u0581 wizard.directory=\u0533\u0580\u0561\u0581\u0578\u0582\u0581\u0561\u056f wizard.file=\u0556\u0561\u0575\u056c : wizard.browse=\u0539\u0565\u0580\u0569\u0565\u056c... wizard.torrentFile=\u054f\u0578\u0580\u0580\u0565\u0576\u057f \u0586\u0561\u0575\u056c wizard.savingfile=\u0556\u0561\u0575\u056c\u0568 \u0563\u0580\u0561\u0576\u0581\u057e\u0578\u0582\u0574 \u0567 wizard.close=\u0553\u0561\u056f\u0565\u056c ConfigView.section.ipfilter.add=\u0531\u057e\u0565\u056c\u0561\u0581\u0576\u0565\u056c ConfigView.section.ipfilter.remove=\u0540\u0565\u057c\u0561\u0581\u0576\u0565\u056c ConfigView.section.ipfilter.edit=\u053d\u0574\u0562\u0561\u0563\u0580\u0565\u056c ConfigView.section.ipfilter.enable=\u0544\u056b\u0561\u0581\u0576\u0565\u056c PeersView.menu.close=&\u0553\u0561\u056f\u0565\u056c configureWizard.transfer.connection=\u0533\u056b\u056e configureWizard.transfer.connection.0=\u0540\u0561\u057f\u0578\u0582\u056f configureWizard.transfer.connection.1=\u0544\u0578\u0564\u0565\u0574 configureWizard.transfer.connection.2=adsl/\u0544\u0561\u056c\u0578\u0582\u056d xxx/128 kbps configureWizard.transfer.connection.3=adsl/\u0544\u0561\u056c\u0578\u0582\u056d xxx/256 kbps configureWizard.transfer.connection.4=adsl/\u0544\u0561\u056c\u0578\u0582\u056d xxx/384 kbps configureWizard.transfer.connection.5=adsl/\u0544\u0561\u056c\u0578\u0582\u056d xxx/512 kbps configureWizard.transfer.connection.6=adsl/\u0544\u0561\u056c\u0578\u0582\u056d xxx/768 kbps configureWizard.transfer.connection.7=adsl/\u0544\u0561\u056c\u0578\u0582\u056d xxx/1024 kbps configureWizard.nat.test=\u0539\u0565\u057d\u0569 configureWizard.nat.testing=\u054a\u0578\u0580\u057f\u056b \u0569\u0565\u057d\u0569\u0561\u057e\u0578\u0580\u0578\u0582\u0574 configureWizard.nat.ok=\u0540\u0561\u057d\u057f\u0561\u057f\u0565\u056c configureWizard.nat.ko=NAT-\u056b \u057d\u056d\u0561\u056c configureWizard.file.title=\u054f\u0578\u0580\u0580\u0565\u0576\u057f\u0576\u0565\u0580 / \u0556\u0561\u0575\u056c\u0565\u0580 configureWizard.file.path=\u0548\u0552\u0572\u056b configureWizard.file.browse=\u0539\u0565\u0580\u0569\u0565\u056c configureWizard.finish.title=\u0561\u057e\u0561\u0580\u057f\u057e\u0561\u056e \u0567 wizard.close.confirmation=\u0540\u0561\u057d\u057f\u0561\u057f\u0578\u0582\u0574 exportTorrentWizard.torrentfile.path=\u0548\u0552\u0572\u056b exportTorrentWizard.torrentfile.browse=\u0539\u0565\u0580\u0569\u0565\u056c exportTorrentWizard.exportfile.path=\u0548\u0552\u0572\u056b exportTorrentWizard.exportfile.browse=\u0539\u0565\u0580\u0569\u0565\u056c importTorrentWizard.torrentfile.path=\u0548\u0552\u0572\u056b importTorrentWizard.torrentfile.browse=\u0539\u0565\u0580\u0569\u0565\u056c importTorrentWizard.importfile.path=\u0548\u0552\u0572\u056b importTorrentWizard.importfile.browse=\u0539\u0565\u0580\u0569\u0565\u056c MyTrackerView.name=\u0531\u0576\u0578\u0582\u0576 fileDownloadWindow.status=\u054e\u056b\u0573\u0561\u056f : fileDownloadWindow.state_error=\u054d\u056d\u0561\u056c : wizard.comment=\u0544\u0565\u056f\u0576\u0561\u0562\u0561\u0576\u0578\u0582\u0569\u0575\u0578\u0582\u0576 ConfigView.section.file.decoder.nodecoder=\u0548\u0579 \u0574\u0565\u056f\u0568 # # Tooltips # # # 2.0.4.4 # ConfigView.section.tracker.passwordenabletorrent=\u0531\u056f\u057f\u056b\u057e\u0561\u0581\u0576\u0565\u056c \u0563\u0561\u0572\u057f\u0576\u0561\u0562\u0561\u057c\u0568 \u057f\u0578\u0580\u0580\u0565\u0576\u057f\u0576\u0565\u0580\u056b \u057e\u0580\u0561 ConfigView.section.tracker.username=\u0533\u0578\u0580\u056e\u0561\u056e\u0578\u0572\u056b \u0561\u0576\u0578\u0582\u0576\u0568 ConfigView.section.tracker.password=\u0533\u0561\u0572\u057f\u0576\u0561\u0562\u0561\u057c columnChooser.title=\u0538\u0576\u057f\u0580\u0565\u056c \u057d\u0575\u0578\u0582\u0576\u0561\u056f\u0576\u0565\u0580\u0568 columnChooser.apply=\u053f\u056b\u0580\u0561\u057c\u0565\u056c columnChooser.columnname=\u054d\u0575\u0578\u0582\u0576\u0561\u056f\u056b \u0561\u0576\u0578\u0582\u0576\u0568 columnChooser.columndescription=\u0546\u056f\u0561\u0580\u0561\u0563\u0580\u0578\u0582\u0569\u0575\u0578\u0582\u0576 authenticator.title=\u054a\u0561\u0570\u0561\u0576\u057b\u057e\u0578\u0582\u0574 \u0567 \u0563\u0561\u0572\u057f\u0576\u0561\u0562\u0561\u057c authenticator.realm=\u0547\u0580\u057b\u0561\u0576 authenticator.tracker=\u054f\u057c\u0565\u056f\u0565\u057c authenticator.user=\u0533\u0578\u0580\u056e\u0561\u056e\u0578\u0572\u056b \u0561\u0576\u0578\u0582\u0576\u0568 authenticator.password=\u0533\u0561\u0572\u057f\u0576\u0561\u0562\u0561\u057c ConfigView.section.tracker.passwordenabletorrent.info=\u057a\u0561\u0570\u0561\u0576\u057b\u057e\u0578\u0582\u0574 \u0567 \u0570\u0561\u0574\u0561\u057a\u0561\u057f\u0561\u057d\u056d\u0561\u0576 BitTorrent \u056f\u056c\u056b\u0565\u0576\u057f (\u0585\u0580\u056b\u0576\u0561\u056f Vuze wizard.tracker.ssl=\u0555\u0563\u057f\u0561\u0563\u0578\u0580\u056e\u0565\u056c SSL wizard.multitracker.new=\u0546\u0578\u0580... wizard.multitracker.edit=\u053d\u0574\u0562\u0561\u0563\u0580\u0565\u056c wizard.multitracker.delete=\u0540\u0565\u057c\u0561\u0581\u0576\u0565\u056c wizard.multitracker.edit.name=\u0531\u0576\u0578\u0582\u0576 wizard.multitracker.edit.save=\u0563\u0580\u0561\u0576\u0581\u0565\u056c wizard.multitracker.edit.deletegroup=\u0540\u0565\u057c\u0561\u0581\u0576\u0565\u056c wizard.multitracker.edit.deletetracker=\u0540\u0565\u057c\u0561\u0581\u0576\u0565\u056c wizard.multitracker.edit.edit=\u053d\u0574\u0562\u0561\u0563\u0580\u0565\u056c PeersView.uniquepiece.none=\u0548\u0579 ConfigView.section.plugins=\u0544\u0578\u0564\u0578\u0582\u056c\u0576\u0565\u0580\u0568 wizard.maketorrent.piecesize=\u053f\u057f\u0578\u0580\u056b \u0579\u0561\u0583 wizard.maketorrent.auto=\u0531\u057e\u057f\u0578\u0574\u0561\u057f TableColumn.header.health=\u054e\u056b\u0573\u0561\u056f\u0568 MyTorrentsView.menu.health=\u054e\u056b\u0573\u0561\u056f\u056b \u0576\u0577\u0561\u0576\u0576\u0565\u0580\u056b \u0574\u0561\u057d\u056b\u0576 # #2.0.7.0 # security.certtruster.yes=\u0531\u0575\u0578 MySharesView.name=\u0531\u0576\u0578\u0582\u0576 MySharesView.type=\u054f\u0565\u057d\u0561\u056f MySharesView.type.file=\u0556\u0561\u0575\u056c # # 2.0.7.x # Categories.all=\u0532\u0578\u056c\u0578\u0580\u0568 ConfigView.label.seeding.rankType.none=\u0548\u0579 \u0574\u0565\u056f\u0568 ConfigView.section.pluginslist=\u0551\u0578\u0582\u0581\u0561\u056f MainWindow.menu.language.refresh=&\u0546\u0578\u0580\u0561\u0581\u0576\u0565\u056c ConfigView.section.proxy.username=\u0533\u0578\u0580\u056e\u0561\u056e\u0578\u0572\u056b \u0561\u0576\u0578\u0582\u0576\u0568 ConfigView.section.proxy.password=\u0533\u0561\u0572\u057f\u0576\u0561\u0562\u0561\u057c AlertMessageBox.error=\u054d\u056d\u0561\u056c AlertMessageBox.warning=\u0546\u0561\u056d\u0561\u0566\u0563\u0578\u0582\u0577\u0561\u0581\u0578\u0582\u0574 AlertMessageBox.comment=\u053b\u0576\u0586\u0578\u0580\u0574\u0561\u0581\u056b\u0561 AlertMessageBox.information=\u053b\u0576\u0586\u0578\u0580\u0574\u0561\u0581\u056b\u0561 SpeedView.stats.total=\u0538\u0576\u0564\u0570\u0561\u0576\u0578\u0582\u0580 SpeedView.stats.now=\u0540\u056b\u0574\u0561 # # > 2.0.8.0 # ConfigView.section.style.colorOverride.error=\u054d\u056d\u0561\u056c Button.revert=\u0565\u057f ConfigView.complete.abbreviated=\u054a\u0538\u0550\u053e: window.updateswt.status=\u054e\u056b\u0573\u0561\u056f window.updateswt.cancel=\u0540\u0580\u0561\u056a\u0561\u0580\u057e\u0565\u056c window.updateswt.ignore=\u0531\u0580\u0570\u0561\u0574\u0561\u0580\u0570\u0565\u056c ConfigView.section.interface.resetassocbutton=\u054e\u0565\u0580\u0561\u056f\u0561\u0576\u0563\u0576\u0565\u056c Button.yes=\u0531\u0575\u0578 Button.no=\u0548\u0579 UpdateWindow.columns.name=\u0531\u0576\u0578\u0582\u0576\u0568 UpdateWindow.columns.size=\u0549\u0561\u0583 UpdateWindow.cancel=\u0540\u0580\u0561\u056a\u0561\u0580\u057e\u0565\u056c UpdateWindow.close=\u0553\u0561\u056f\u0565\u056c PeersView.host=\u0540\u0578\u057d\u057f\u056b \u0561\u0576\u0578\u0582\u0576\u0568 security.certcreate.firstlastname=\u0531\u0576\u0578\u0582\u0576 \u0561\u0566\u0563\u0561\u0576\u0578\u0582\u0576\u0568 security.certcreate.cancel=\u0540\u0580\u0561\u056a\u0561\u0580\u057e\u0565\u056c webui.passwordenable=\u0531\u056f\u057f\u056b\u057e\u0561\u0581\u0576\u0565\u056c \u0563\u0561\u0572\u057f\u0576\u0561\u0562\u0561\u057c\u0568 webui.user=\u0555\u0563\u057f\u0561\u0563\u0578\u0580\u056e\u0578\u0572\u056b \u0561\u0576\u0578\u0582\u0576\u0568 webui.password=\u0533\u0561\u0572\u057f\u0576\u0561\u0562\u0561\u057c GeneralView.label.maxdownloadspeed=\u0531\u057c\u0561\u057e\u0565\u056c\u0561\u0563\u0578\u0582\u0575\u0576 \u0562\u0565\u057c\u0576\u0574\u0561\u0576 \u0561\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0568 blank.resource=\u054c\u0565\u057d\u0578\u0582\u0580\u057d Button.clear=\u0544\u0561\u0584\u0580\u0565\u056c Button.reset=\u054e\u0565\u0580\u0561\u056f\u0561\u0576\u0563\u0576\u0565\u056c #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed CacheView.title.full=\u053f\u0565\u0577 CacheView.general.size=\u053c\u0580\u056b\u057e \u0579\u0561\u0583\u0568 CacheView.general.inUse=\u0555\u0563\u057f\u0561\u0563\u0578\u0580\u056e\u057e\u0578\u0582\u0574 \u0567 CacheView.general.title=\u053b\u0576\u0586\u0578\u0580\u0574\u0561\u0581\u056b\u0561 \u056f\u0565\u0577\u056b \u0574\u0561\u057d\u056b\u0576 CacheView.reads.title=I/O \u053f\u0561\u0580\u0564\u0561\u056c CacheView.reads.fromFile=\u0556\u0561\u0575\u056c\u056b\u0581 CacheView.reads.fromCache=\u053f\u0565\u0577\u056b\u0581 CacheView.reads.hits=\u0540\u0561\u057b\u0578\u0572\u057e\u0561\u056e CacheView.writes.title=I/O \u0533\u0580\u0565\u056c CacheView.writes.toCache=\u0534\u0565\u057a\u056b \u056f\u0565\u0577 CacheView.writes.toFile=\u0534\u0565\u057a\u056b \u0586\u0561\u0575\u056c CacheView.writes.hits=\u0533\u0580\u0561\u0576\u0581\u057e\u0561\u056e \u0567 CacheView.speeds.title=\u054f\u057e\u0575\u0561\u056c\u0576\u0565\u0580\u056b \u0583\u0578\u056d\u0561\u0576\u0561\u056f\u0574\u0561\u0576 \u0561\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576 CacheView.speeds.reads=\u053f\u0561\u0580\u0564\u0561\u056c CacheView.speeds.writes=\u0533\u0580\u0565\u056c CacheView.speeds.fromCache=\u053f\u0565\u0577\u056b\u0581/\u0534\u0565\u057a\u056b \u056f\u0565\u0577 CacheView.speeds.fromFile=\u0556\u0561\u0575\u056c\u056b\u0581/\u0534\u0565\u057a\u056b \u0586\u0561\u0575\u056c CacheView.reads.amount=\u0554\u0561\u0576\u0561\u056f CacheView.reads.avgsize=\u0544\u056b\u057b\u056b\u0576 Size PiecesView.typeItem.0=\u0534\u0561\u0576\u0564\u0561\u0572 PiecesView.typeItem.1=\u0531\u0580\u0561\u0563 PiecesView.type=\u054f\u0565\u057d\u0561\u056f authenticator.torrent=\u054f\u0578\u0580\u0580\u0565\u0576\u057f MyTorrents.items.UpSpeedLimit.unlimited=\u0531\u0576\u057d\u0561\u0570\u0574\u0561\u0576 MainWindow.menu.tools=&\u0533\u0578\u0580\u056e\u056b\u0584\u0576\u0565\u0580 sharing.progress.cancel=\u0540\u0580\u0561\u056a\u0561\u0580\u057e\u0565\u056c TableColumn.header.maxdownspeed=\u0532\u0565\u057c\u0576\u0574\u0561\u0576 \u0561\u057c\u0561\u057e\u0565\u056c\u0561\u0563\u0578\u0582\u0575\u0576 \u0561\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0568 installPluginsWizard.list.name=\u0531\u0576\u0578\u0582\u0576 installPluginsWizard.file.file=\u0556\u0561\u0575\u056c : installPluginsWizard.file.browse=\u0539\u0565\u0580\u0569\u0565\u056c... Button.abort=\u0538\u0576\u0564\u0570\u0561\u057f\u0565\u056c ConfigView.section.connection.group.networks=\u0551\u0561\u0576\u0581\u0565\u0580 TableColumn.header.networks=\u0551\u0561\u0576\u0581\u0565\u0580 ConfigView.section.tracker.server.group.networks=\u0551\u0561\u0576\u0581\u0565\u0580 window.networkselection.title=\u0551\u0561\u0576\u0581\u056b \u0568\u0576\u057f\u0580\u0578\u0582\u0569\u0575\u0578\u0582\u0576 window.networkselection.description=\u054f\u0578\u0580\u0580\u0565\u0576\u057f : MyTorrentsView.menu.networks=\u0551\u0561\u0576\u0581\u0565\u0580 Button.apply=\u053f\u056b\u0580\u0561\u057c\u0565\u056c Button.close=\u0553\u0561\u056f\u0565\u056c #file can be a URL or a path in the jar DHTView.operations.ok=\u0540\u0561\u057d\u057f\u0561\u057f\u0565\u056c DHTView.activity.type=\u054f\u0565\u057d\u0561\u056f MyTorrentsView.menu.setDownSpeed=\u054d\u0561\u0570\u0574\u0561\u0576\u0565\u056c \u0562\u0565\u057c\u0576\u0574\u0561\u0576 \u0561\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0568 ActivityView.legend.limit=\u0531\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0561\u0576 \u057d\u0561\u0570\u0574\u0561\u0576\u0561\u0583\u0561\u056f\u0578\u0582\u0574 ActivityView.legend.achieved=\u0540\u0561\u057d\u0561\u056e \u0561\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0568 ActivityView.legend.peeraverage=\u0544\u056b\u057b\u056b\u0576 ActivityView.legend.swarmaverage=\u0531\u0574\u0562\u0578\u056d\u056b \u0574\u056b\u057b\u056b\u0576\u0568 ActivityView.legend.trimmed=\u0544\u0577\u0561\u056f\u057e\u0561\u056e (dotted) LoggerView.clear=&\u0544\u0561\u0584\u0580\u0565\u056c ConfigView.section.logging.log1type=\u0536\u0563\u0578\u0582\u0577\u0561\u0581\u0578\u0582\u0574 ConfigView.section.logging.log2type=\u054d\u056d\u0561\u056c ConfigView.pluginlist.column.type=\u054f\u0565\u057d\u0561\u056f ConfigView.pluginlist.column.name=\u0531\u0576\u0578\u0582\u0576 # %1 = "in kbps" or ""; %2 = "upload" or "download" OpenTorrentWindow.addFiles.Folder=\u0531\u057e\u0565\u056c\u0561\u0581\u0576\u0565\u056c &\u0539\u0572\u0569\u0561\u057a\u0561\u0576\u0561\u056f OpenTorrentWindow.torrentTable.name=\u0531\u0576\u0578\u0582\u0576 OpenTorrentWindow.fileTable.fileName=\u0556\u0561\u0575\u056c\u056b \u0561\u0576\u0578\u0582\u0576\u0568 OpenTorrentWindow.fileTable.size=\u0549\u0561\u0583 Button.moveUp=\u054f\u0565\u0572\u0561\u0583\u0578\u056d\u0565\u056c &\u057e\u0565\u0580\u0587 Button.moveDown=\u054f\u0565\u0572\u0561\u0583\u0578\u056d\u0565\u056c &\u0576\u0565\u0580\u0584\u0587 PeersView.piece=\u053f\u057f\u0578\u0580 PiecesView.speed=\u0531\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576 Button.selectAll=\u0538\u0576\u057f\u0580\u0565\u056c \u0562\u0578\u056c\u0578\u0580\u0568 Button.markSelected=\u0546\u0577\u0565\u056c \u0568\u0576\u057f\u0580\u057e\u0561\u056e\u0576\u0565\u0580\u0568 Button.unmarkSelected=\u0549\u0576\u0577\u0565\u056c \u0568\u0576\u057f\u0580\u057e\u0561\u056e\u0576\u0565\u0580\u0568 azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_fr_FR.properties0000644000175000017500000040406711301156004026100 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Fichier .torrent Main.parameter.usage=Utilisation: java org.gudy.azureus2.cl.Main [param\u00e8tres] "fichier .torrent" "r\u00e9pertoire de sauvegarde" Main.parameter.maxUploads=Nombre max d'envois simultan\u00e9s Main.parameter.maxSpeed=Vitesse d'envoi max en octets/s MainWindow.menu.file=&Fichier MainWindow.menu.file.open=&Ouvrir MainWindow.menu.file.create=&Cr\u00e9er un torrent MainWindow.menu.file.create.fromfile=\u00c0 &partir d'un fichier MainWindow.menu.file.create.fromdir=\u00c0 partir d'un r\u00e9perto&ire MainWindow.menu.file.export=&Exporter un torrent en XML... MainWindow.menu.file.import=&Importer un torrent XML... MainWindow.menu.file.closetab=Fermer l'ongle&t MainWindow.menu.file.closewindow=Fermer la &fen\u00eatre MainWindow.menu.file.exit=&Quitter MainWindow.dialog.choose.file=Choisissez le fichier torrent MainWindow.menu.file.folder=R\u00e9pe&rtoire MainWindow.dialog.choose.folder=Choisissez le r\u00e9pertoire contenant les .torrent MainWindow.menu.view=&Affichage MainWindow.menu.view.show=Afficher MainWindow.menu.view.mytorrents=M&es torrents MainWindow.menu.view.configuration=O&ptions... MainWindow.menu.closealldetails=Fermer tous les &d\u00e9tails MainWindow.menu.closealldownloadbars=Fermer toutes les &mini-barres MainWindow.menu.language=&Langue ConfigView.section.language=Langue MainWindow.menu.window=&Fen\u00eatre MainWindow.menu.window.minimize=&Minimiser MainWindow.menu.window.alltofront=A&fficher tout devant MainWindow.menu.help=Aid&e MainWindow.menu.help.about=\u00c0 &propos... MainWindow.about.title=\u00c0 propos de Vuze MainWindow.about.section.developers=D\u00e9veloppeurs MainWindow.about.section.translators=Traducteurs MainWindow.about.section.system=Syst\u00e8me MainWindow.about.section.internet=Sur Internet MainWindow.about.internet.homepage=Page d'accueil de Vuze MainWindow.about.internet.sourceforge=Page Sourceforge MainWindow.about.internet.sourceforgedownloads=T\u00e9l\u00e9chargements sur Sourceforge MainWindow.about.internet.bugreports=Rapporter un bogue MainWindow.about.internet.forumdiscussion=Forum g\u00e9n\u00e9ral MainWindow.about.internet.wiki=Wiki FAQ Vuze MainWindow.dialog.choose.savepath=Choisissez le r\u00e9pertoire de sauvegarde MainWindow.dialog.choose.savepath_forallfiles=Choisissez le r\u00e9pertoire de sauvegarde pour TOUS les fichiers MainWindow.status.latestversion=Derni\u00e8re MainWindow.status.latestversion.clickupdate=Cliquer pour mettre \u00e0 jour MainWindow.status.unknown=Inconnue MainWindow.status.checking=v\u00e9rification MyTorrentsView.mytorrents=Mes torrents TableColumn.header.name=Nom TableColumn.header.size=Taille TableColumn.header.done=Fait TableColumn.header.done.info=Pourcentage de la t\u00e2che actuelle compl\u00e9t\u00e9e TableColumn.header.status=\u00c9tat TableColumn.header.status.info=\u00c9tat du torrent TableColumn.header.seeds=Sources TableColumn.header.seeds.info=# de source(s) connect\u00e9(s) \u00e0 (# de source(s) total) TableColumn.header.peers=Clients TableColumn.header.peers.info=# de client(s) connect\u00e9(s) \u00e0 (# de client(s) total) TableColumn.header.downspeed=Re\u00e7oit \u00e0 TableColumn.header.upspeed=Envoie \u00e0 TableColumn.header.eta=Restant TableColumn.header.tracker=Tracker TableColumn.header.tracker.info=\u00c9tat du Tracker TableColumn.header.trackernextaccess=Prochain acc\u00e8s tracker TableColumn.header.trackernextaccess.info=Quand le prochain acc\u00e8s au tracker va avoir lieu TableColumn.header.priority=Priorit\u00e9 TableColumn.header.priority.info=D\u00e9termine la proportion de votre capacit\u00e9 d'envoi r\u00e9serv\u00e9 \u00e0 ce torrent. TableColumn.header.seeds.fullcopycalc=%2 copies compl\u00e8tes pour %1 clients MyTorrentsView.menu.showdetails=Afficher les d\u00e9&tails MyTorrentsView.menu.showdownloadbar=Afficher la &mini-bar MyTorrentsView.menu.open=&Ouvrir MyTorrentsView.menu.setpriority=Priorit\u00e9 MyTorrentsView.menu.setpriority.high=&Haute MyTorrentsView.menu.setpriority.low=&Basse MyTorrentsView.menu.start=&D\u00e9marrer MyTorrentsView.menu.stop=&Arr\u00eater MyTorrentsView.menu.remove=&Enlever MyTorrentsView.menu.changeTracker=C&hanger l'URL du tracker TrayWindow.menu.exit=&Quitter TrayWindow.menu.show=Afficher Vuze SystemTray.menu.exit=&Quitter SystemTray.menu.closealldownloadbars=F&ermer toutes les mini-barres SystemTray.menu.open_global_transfer_bar=Montrer la barre de transferts SystemTray.menu.show=&Afficher Vuze PeersView.ip.info=IP du client PeersView.port.info=Port utilis\u00e9 PeersView.T.info=l (local): vous avez \u00e9tabli la connexion, r (distant): un client vous a contact\u00e9. PeersView.T.L.tooltip=vous avez \u00e9tabli la connexion PeersView.T.R.tooltip=un client vous a contact\u00e9. PeersView.I1=I (Int\u00e9ress\u00e9 par le client) PeersView.I1.info=\u00cates-vous interess\u00e9 par ce que l'autre client poss\u00e8de\u00a0? PeersView.C1=C (Bloqu\u00e9 par le client) PeersView.C1.info=Si un client vous emp\u00eache de t\u00e9l\u00e9charger PeersView.pieces=Pi\u00e8ces PeersView.downloadspeed=Re\u00e7oit \u00e0 PeersView.download=T\u00e9l\u00e9charg\u00e9 PeersView.I2=I (Int\u00e9ressant pour le client) PeersView.I2.info=Est-ce que le client est interess\u00e9 par vos pi\u00e8ces\u00a0? PeersView.C2=C (Bloquant le client) PeersView.C2.info=Si vous emp\u00eacher un client de t\u00e9l\u00e9charger PeersView.uploadspeed=Envoie \u00e0 PeersView.uploadspeed.info=Votre vitesse d'envoi actuelle au client. PeersView.upload=Envoy\u00e9 PeersView.upload.info=Votre vitesse moyenne d'envoi au client. PeersView.statup=Statistique d'Envoi PeersView.statup.info=Valeur estim\u00e9 de la vitesse d'envoi d'un client PeersView.S.info=Ignor\u00e9 (Snubbed): Un client peut \u00eatre "ignor\u00e9" manuellement, ou automatiquement (s'il n'envoit pas des donn\u00e9es assez rapidement). PeersView.downloadspeedoverall=R\u00e9ception (Vit. Totale de) PeersView.client.info=Sorte de logiciel BT le client utilise PeersView.menu.snubbed=Ignor\u00e9 PeersView.title.short=D\u00e9tails PeersView.title.full=D\u00e9tails AllPeersView.title.full=Tous les pairs ConfigView.section.files=Fichiers ConfigView.label.usefastresume=Utiliser la reprise rapide ConfigView.label.incrementalfile=Cr\u00e9ation incr\u00e9mentale des fichiers ConfigView.label.defaultsavepath=R\u00e9pertoire de sauvegarde des donn\u00e9es par d\u00e9faut ConfigView.button.browse=Parcourir... ConfigView.dialog.choosedefaultsavepath=Choissisez le r\u00e9pertoire d'enregistrement des donn\u00e9es ConfigView.section.server=Connexion ConfigView.section.global=G\u00e9n\u00e9ral ConfigView.label.disconnetseed=Se d\u00e9connecter des sources lorsqu'on est source ConfigView.label.switchpriority=Passez en basse priorit\u00e9 lorsque l'on est source ConfigView.label.maxdownloads=Nombre de t\u00e9l\u00e9chargements simultan\u00e9s ConfigView.label.maxdownloads.tooltip=Vous allez toujours \u00eatre en mesure de t\u00e9l\u00e9charger autant de fichiers que vous sp\u00e9cifiez ici.\n Par contre les torrents identifi\u00e9s "1\u00e8re priorit\u00e9" peuvent voler un emplacement de t\u00e9l\u00e9chargement si c'est absolument n\u00e9cessaire. ConfigView.label.maxactivetorrents=Nombre total de torrents actifs [0\u00a0: illimit\u00e9]\n ConfigView.label.priorityExtensions=Passez en haute priorit\u00e9 les fichiers dont l'extension est\u00a0:\n(ex: .txt;.nfo;.jpg) ConfigView.section.transfer=Transfert ConfigView.label.maxuploads=Nombre d'uploads par d\u00e9faut (par torrent) ConfigView.label.maxuploadspeed=ko/s Vitesse globale maximale d'envoi [0\u00a0: illimit\u00e9e] ConfigView.label.saveresumeinterval=Sauver les donn\u00e9es de 'reprise rapide' toutes les ConfigView.unlimited=Illimit\u00e9 ConfigView.section.display=Affichage ConfigView.label.opendetails=Ouverture automatique de la fen\u00eatre D\u00e9tails ConfigView.label.openbar=Ouverture automatique des mini-barres ConfigView.label.closetotray=Fermer r\u00e9duit dans la barre des t\u00e2ches ConfigView.label.minimizetotray=Minimiser r\u00e9duit dans la barre des t\u00e2ches ConfigView.section.general=G\u00e9neral ConfigView.section.start=Lancement ConfigView.label.showsplash=Afficher l'\u00e9cran d'accueil au d\u00e9marrage ConfigView.label.autoupdate=Ex\u00e9cuter l'assistant de mise \u00e0 jour quand une nouvelle version est disponible ConfigView.label.openconsole=Ouvrir la Console au d\u00e9marrage ConfigView.label.openconfig=Ouvrir le menu Options au d\u00e9marrage ConfigView.label.startminimized=Lancer minimis\u00e9 ConfigView.label.ircwiki=Veuillez visiter http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Serveur ConfigView.label.ircchannel=Canal ConfigView.label.irclogin=Alias ConfigView.group.irctitle=R\u00e9glages IRC ConfigView.boolean.ircsendinfo=Permettre l'envoi de vos r\u00e9glages aux op\u00e9rateurs\n du canal pour mieux vous aider ConfigView.boolean.irclog=Activer la journalisation du canal (dans IRC_log.htm) ConfigView.section.security=S\u00e9curit\u00e9 ConfigView.label.password=Prot\u00e9ger Vuze par un mot de passe\nN\u00e9cessaire pour d\u00e9-iconifier, ainsi qu'au lancement. ConfigView.label.passwordconfirm=Mot de passe (confirmation) ConfigView.label.passwordmatch=Mot de passe activ\u00e9\u00a0: ConfigView.label.passwordmatchnone=Non ConfigView.label.passwordmatchno=Non / Les mots de passe ne correspondent pas ConfigView.label.passwordmatchyes=Oui ConfigView.button.save=Sauver FileItem.write=\u00c9criture FileItem.read=Lecture FileItem.normal=Normale FileItem.high=\u00c9lev\u00e9e FileItem.donotdownload=Ne pas t\u00e9l\u00e9charger FileItem.delete=Supprim\u00e9 FilesView.name=Nom FilesView.size=Taille FilesView.done=Fait FilesView.firstpiece=n\u00b0 de la premi\u00e8re pi\u00e8ce FilesView.numberofpieces=# de pi\u00e8ces FilesView.pieces=Pi\u00e8ces FilesView.priority=Priorit\u00e9 FilesView.menu.open=&Ouvrir FilesView.menu.setpriority=&Priorit\u00e9 FilesView.menu.setpriority.high=\u00c9l&ev\u00e9e FilesView.menu.setpriority.normal=&Normale FilesView.menu.setpriority.skipped=Ne pas &t\u00e9l\u00e9charger FilesView.title.short=Fichiers FilesView.title.full=Fichiers GeneralView.section.downloaded=T\u00e9l\u00e9charg\u00e9 GeneralView.label.status.file=Fichier GeneralView.label.status.pieces=Pi\u00e8ces GeneralView.section.availability=Disponibilit\u00e9 GeneralView.label.status.pieces_available=Pi\u00e8ces\u00a0 GeneralView.section.transfer=Transfert GeneralView.section.info=Informations GeneralView.title.short=G\u00e9n\u00e9ral GeneralView.title.full=G\u00e9n\u00e9ral GeneralView.label.timeelapsed=Temps \u00e9coul\u00e9: GeneralView.label.remaining=Temps/Taille restant\u00a0: GeneralView.label.downloaded=T\u00e9l\u00e9charg\u00e9\u00a0: GeneralView.label.downloadspeed=Vitesse de t\u00e9l\u00e9chargement\u00a0: GeneralView.label.maxuploads=Max. clients actifs\u00a0: GeneralView.label.maxuploads.tooltip=Nombre maximum de clients "unchock\u00e9s" (clients auxquels on est susceptibles d'envoyer des donn\u00e9es) en m\u00eame temps GeneralView.label.uploaded=Envoy\u00e9\u00a0: GeneralView.label.uploadspeed=Vitesse d'envoi\u00a0: GeneralView.label.seeds=Source(s)\u00a0: GeneralView.label.peers=Client(s)\u00a0: GeneralView.label.completed=Termin\u00e9 : GeneralView.label.totalspeed=Vitesse totale\u00a0: GeneralView.label.totalspeed.tooltip=Vitesse de r\u00e9ception totale du torrent, redistribu\u00e9e entre tous les clients auxquels vous \u00eates connect\u00e9s.\nPour situer votre vitesse de t\u00e9l\u00e9chargement, vous pouvez calculer la moyenne de vitesse des\nclients en divisant cette vitesse totale par le nombre de clients auxquels vous \u00eates connect\u00e9s.\n GeneralView.label.averagespeed=moyenne GeneralView.label.filename=Nom\u00a0: GeneralView.label.totalsize=Taille totale\u00a0: GeneralView.label.savein=Enregistrer dans\u00a0: GeneralView.label.hash=Hash\u00a0: GeneralView.label.numberofpieces=Nombre de pi\u00e8ces\u00a0: GeneralView.label.size=Taille d'une pi\u00e8ce\u00a0: GeneralView.label.tracker=\u00c9tat du Tracker\u00a0: GeneralView.label.updatein=Mise \u00e0 jour dans\u00a0: GeneralView.label.trackerurl=URL du Tracker\u00a0: GeneralView.label.trackerurlupdate=Mise \u00e0 jour manuelle GeneralView.label.comment=Commentaire\u00a0: ManagerItem.waiting=En attente ManagerItem.allocating=Allocation ManagerItem.checking=V\u00e9rification ManagerItem.ready=Pr\u00eat ManagerItem.downloading=T\u00e9l\u00e9chargement ManagerItem.seeding=Source ManagerItem.stopped=Arr\u00eat\u00e9 ManagerItem.error=Erreur ManagerItem.high=Haute ManagerItem.low=Basse MinimizedWindow.name=Nom\u00a0: PiecesView.size=Taille PiecesView.numberofblocks=Nbre de Blocs PiecesView.blocks=Blocs PiecesView.completed=Faits PiecesView.availability=Disponibilit\u00e9 PiecesView.reservedby=Reserv\u00e9 PiecesView.writers=Contributeurs au bloc PiecesView.title.short=Pi\u00e8ces PiecesView.title.full=Pi\u00e8ces SystemTray.tooltip.seeding=%1 \u00a0Sources,\u00a0 SystemTray.tooltip.downloading=%1 \u00a0T\u00e9l\u00e9chargements\n DownloadManager.error.filenotfound=Fichier non trouv\u00e9 DownloadManager.error.fileempty=Fichier .torrent vide DownloadManager.error.filetoobig=Fichier .torrent trop gros DownloadManager.error.filewithouttorrentinfo=Pas d'information "torrent" dans le fichier DownloadManager.error.unsupportedencoding=Format d'encodage non support\u00e9 DownloadManager.error.ioerror=Erreur d'IO DownloadManager.error.sha1=Erreur\u00a0: pas d'algorithme SHA1 PeerManager.status.offline=Erreur de connexion PeerManager.status.ok=ok PeerManager.status.checking=en cours PeerManager.status.finished=Termin\u00e9 PeerManager.status.finishedin=Termin\u00e9 en MainWindow.upgrade.assistant=Assistant de mise \u00e0 jour MainWindow.upgrade.newerversion=Une nouvelle version de Vuze est disponible MainWindow.upgrade.explanation=Cet assistant va t\u00e9l\u00e9charger la nouvelle version dans votre r\u00e9pertoire Vuze et relancer le programme MainWindow.upgrade.explanation.manual=- \u00c9tape 1: Fermez Vuze n- \u00c9tape 2: T\u00e9l\u00e9chargez la nouvelle du lien ci-dessous dans le r\u00e9pertoire d'installation de Vuze n- \u00c9tape 3: Red\u00e9marrez Vuze MainWindow.upgrade.step1=\u00c9tape 1: T\u00e9l\u00e9chargement de la nouvelle version MainWindow.upgrade.step2=\u00c9tape 2: Fermeture de cette version et relance de la nouvelle MainWindow.upgrade.hint1=Astuce:\tAppuyer sur Terminer rend l'op\u00e9ration automatique MainWindow.upgrade.hint2=Astuce:\tSi vous voulez fermer Vuze plus tard, appuyer sur Annuler et\n\trenommez Azureus2-new.jar en Azureus2.jar apr\u00e8s fermeture MainWindow.upgrade.error.downloading.hint=Erreur:\tIncapable de t\u00e9l\u00e9charger la nouvelle version, veuillez faire la mise \u00e0 jour manuellement MainWindow.upgrade.section.info=Nouvelle version disponible MainWindow.upgrade.section.manual=Mise \u00e0 jour manuelle MainWindow.upgrade.section.automatic=Mise \u00e0 jour automatique MainWindow.upgrade.tooltip.progressbar=\u00c9tat d'avancement du t\u00e9l\u00e9chargement Button.next=Suivant Button.finish=Terminer Button.cancel=Annuler LocaleUtil.title=Choisir le codage des caract\u00e8res LocaleUtil.section.chooseencoding=Choisir l'encodage pour le nom du fichier LocaleUtil.label.chooseencoding=Veuillez choisir l'encodage le plus appropri\u00e9 LocaleUtil.label.hint.doubleclick=Astuce: Double-cliquer sur une colonne s\u00e9lectionne l'encodage et ferme la fen\u00eatre LocaleUtil.label.checkbox.rememberdecision=Se souvenir du r\u00e9glage pour les autres fichiers LocaleUtil.column.encoding=Encodage IrcClient.defaultChannel=#Azureus-French IrcClient.copyright=Utilise l'API Java IRC PircBot - www.jibble.org/pircbot IrcClient.connecting=Se connecte \u00e0 IrcClient.connected=Connect\u00e9 \u00e0 IrcClient.joining=Rejoint IrcClient.channel=Canal IrcClient.joined=rejoint IrcClient.error=Erreur IrcClient.hasjoined=a rejoint le canal IrcClient.haskicked=a \u00e9ject\u00e9 IrcClient.hasleft=est parti IrcClient.nowknown=est maintenant IrcClient.topicforchannel=Topic pour le canal IrcClient.disconnected=D\u00e9connect\u00e9 de IrcClient.noNick=Alias non pr\u00e9cis\u00e9. Veuillez remplir le champ correspondant dans le menu 'Options' IrcView.actionnotsupported=Cette action n'est pas support\u00e9e IrcView.clientsconnected=Utilisateurs IrcView.privateto=\u00c0 IrcView.privatefrom=De IrcView.noticefrom=Notice: IrcView.errormsg=Erreur de syntaxe /msg : /msg [utilisateur] texte IrcView.help=Commandes valides :\n . /help : affiche ce message\n . /nick | /name : change votre alias\n . /me action : envoie une action \n . /msg [utilisateur] message : envoie un message priv\u00e9 \u00e0 \n . /r message : r\u00e9pond au dernier message priv\u00e9\n . /join #canal : change le canal actuel PasswordWindow.title=Vuze est barr\u00e9 PasswordWindow.passwordprotected=Vuze est prot\u00e9g\u00e9 par un mot de passe.\nPour r\u00e9tablir Vuze veuillez entrer votre mot de passe : TrackerChangerWindow.title=Ajouter/changer le tracker TrackerChangerWindow.newtracker=Entrer la nouvelle URL du tracker PeersView.discarded=Rejet\u00e9 PeersView.discarded.info=Pi\u00e8ces re\u00e7ues alors que vous les aviez d\u00e9j\u00e0. Elimin\u00e9es. discarded=rejet\u00e9s MyTorrentsView.menu.move=&D\u00e9placer MyTorrentsView.menu.moveUp=Vers le h&aut MyTorrentsView.menu.moveDown=Vers le ba&s GeneralView.label.hashfails=Pi\u00e8ce(s) invalide(s)\u00a0: GeneralView.label.shareRatio=Taux de partage\u00a0: ConfigView.section.downloadManagement=Gestion des t\u00e9l\u00e9chargements ConfigView.label.startRatioPeers=D\u00e9marrer le torrent quand il y a moins de 1 source pour ConfigView.text.neverStop=Ne jamais arr\u00eater ConfigView.text.neverStart=Ne jamais d\u00e9marrer ConfigView.text.peers=Clients ConfigView.label.checkOncompletion=V\u00e9rifier le fichier \u00e0 la fin du t\u00e9l\u00e9chargement wizard.title=Cr\u00e9er un torrent wizard.previous=< Retour wizard.next=Suivant > wizard.finish=Terminer wizard.invalidurl=Cette URL n'est pas valide wizard.singlefile=Un seul fichier wizard.singlefile.help=Cr\u00e9er un torrent \u00e0 partir d'un seul fichier wizard.directory=R\u00e9pertoire wizard.directory.help=Cr\u00e9er un torrent \u00e0 partir d'un r\u00e9pertoire wizard.choosefile=Choisir un fichier wizard.file=Fichier: wizard.browse=Rechercher... wizard.choosedirectory=Choisir un r\u00e9pertoire wizard.invalidfile=Fichier non valide\u00a0! wizard.invaliddirectory=R\u00e9pertoire non valide\u00a0! wizard.torrentFile=Fichier torrent wizard.choosetorrent=Veuillez choisir le fichier torrent \u00e0 cr\u00e9er wizard.notimplemented=Pas encore impl\u00e9ment\u00e9 wizard.progresstitle=Cr\u00e9ation du fichier torrent wizard.savingfile=Sauvegarde du fichier... wizard.filesaved=Fichier sauvegard\u00e9. wizard.close=Fermer Torrent.create.progress.piecelength=Taille d'une pi\u00e8ce: Torrent.create.progress.piececount=Nombre de pi\u00e8ces: Torrent.create.progress.totalfilesize=Taille totale du fichier: Torrent.create.progress.totalfilecount=Nombre total de fichiers: Torrent.create.progress.parsingfiles=Analyse des fichiers Torrent.create.progress.hashing=Calcul du Hash des fichiers MainWindow.upgrade.downloadingfrom=T\u00e9l\u00e9chargement depuis : MainWindow.menu.view.ipFilter=Filtres I&P ConfigView.section.ipfilter=Filtres IP ConfigView.section.ipfilter.start=IP de d\u00e9part ConfigView.section.ipfilter.end=IP de fin ConfigView.section.ipfilter.add=Ajouter ConfigView.section.ipfilter.remove=Enlever ConfigView.section.ipfilter.edit=\u00c9diter ConfigView.section.ipfilter.save=Sauver ConfigView.section.ipfilter.editFilter=\u00c9diter le filtre ConfigView.section.ipfilter.enable=Appliquer le filtre PeersView.menu.close=Fermer seedmore.title=Le torrent a besoin de plus de sources seedmore.shareratio=Votre taux de partage sur ce torrent est de seedmore.uploadmore=Un taux de partage inf\u00e9rieur \u00e0 100% est mauvais pour le r\u00e9seau BitTorrent.\nVous devriez continuer \u00e0 partager ce torrent.\n\u00cates-vous s\u00fbr de vouloir continuer\u00a0? ConfigView.label.showpopuponclose=Faire apparaitre une fen\u00eatre de confirmation lors de la fermeture d'un torrent avec un taux de partage inf\u00e9rieur \u00e0 1 ConfigView.label.startNumSeeds=\nD\u00e9marrer la source quand il y a moins de \nA priorit\u00e9 sur les autres r\u00e8gles ConfigView.label.seeds=sources ConfigView.section.seeding=Gestion des sources MyTorrentsView.menu.removeand=E&nlever et MyTorrentsView.menu.removeand.deletetorrent=effacer le fichier &torrent MyTorrentsView.menu.removeand.deletedata=effacer les &donn\u00e9es MyTorrentsView.menu.removeand.deleteboth=e&ffacer tout deletedata.title=!!! Attention !!! deletedata.message1=Vous vous appr\u00eatez \u00e0 effacer les DONN\u00c9ES de\u00a0:\n MainWindow.menu.file.configure=&Assistant de configuration configureWizard.title=Assistant de Configuration configureWizard.welcome.title=Bienvenue dans l'Assistant de Configuration de Vuze configureWizard.welcome.message=Cet Assistant va vous permettre de configurer Vuze pour un usage courant. Vous pouvez modifier plus en profondeur la configuration dans le menu:\n\nOutils > Options... configureWizard.transfer.title=Transferts et Connexion configureWizard.transfer.hint=Astuce\u00a0: Choisir une vitesse l\u00e9g\u00e8rement inf\u00e9rieure \u00e0 votre connexion. configureWizard.transfer.message=Veuillez choisir votre connexion ci-dessous. Soyez pr\u00e9venus qu'une faible vitesse d'envoi donnera de pi\u00e8tres performances. Puisque la vitesse d'envoi importe pour chaque torrent, t\u00e9l\u00e9charger trop de torrents \u00e0 la fois donnera \u00e9galement de mauvaises performances. Nous conseillons d'allouer un MINIMUM de 5kB/s par torrent. Plus la vitesse d'envoi est haute, plus la vitesse de t\u00e9l\u00e9chargement sera rapide. (en fonction de la vitesse totale partag\u00e9 du torrent) configureWizard.transfer.connection=Type de connexion configureWizard.transfer.connection.0=Personnalis\u00e9e configureWizard.transfer.connection.1=Modem/ISDN configureWizard.transfer.connection.2=ADSL/Cable xxx/128 kbit/s configureWizard.transfer.connection.3=ADSL/Cable xxx/256 kbit/s configureWizard.transfer.connection.4=ADSL/Cable xxx/384 kbit/s configureWizard.transfer.connection.5=ADSL/Cable xxx/512 kbit/s configureWizard.transfer.connection.6=ADSL/Cable xxx/768 kbit/s configureWizard.transfer.connection.7=ADSL/Cable xxx/1024 kbit/s configureWizard.transfer.maxUpSpeed=Vitesse d'Envoi Max (kbit/s) configureWizard.transfer.maxActiveTorrents=Maximum Actifs configureWizard.transfer.maxDownloads=T\u00e9l\u00e9chargements Max configureWizard.transfer.maxUploadsPerTorrent=Max Envois par Torrent configureWizard.nat.title=NAT / Port du Serveur configureWizard.nat.message=Pour une utilisation optimale de BitTorrent, il est conseill\u00e9 d'\u00eatre pleinement accessible depuis internet. BitTorrent utilise seulement le port 6881 par d\u00e9faut. Cet assistant vous permet de tester et / ou de changer ce port. Si vous avez des t\u00e9l\u00e9chargements en cours, certains ports ne pourront pas \u00eatre test\u00e9s. configureWizard.nat.test=Test en cours configureWizard.nat.testing=Test du port configureWizard.nat.ko=Erreur NAT configureWizard.nat.unable=Test impossible configureWizard.file.title=Torrents / Fichiers configureWizard.file.message1=Vuze va sauvegarder vos .torrent actif dans un r\u00e9pertoire sp\u00e9cifique, qui sera\u00a0: configureWizard.file.path=\u00a0 configureWizard.file.browse=... configureWizard.file.message2=\nVuze peut reprendre instantan\u00e9ment le t\u00e9l\u00e9chargement de vos fichiers, en ajoutant des informations de reprise dans vos torrents. Gr\u00e2ce \u00e0 cette fonctionnalit\u00e9, vous pourrez \u00e9galement poursuivre le t\u00e9l\u00e9chargement des pi\u00e8ces partiellement re\u00e7ues.\n\n configureWizard.file.fastResume=Activer la reprise rapide configureWizard.file.invalidPath=R\u00e9pertoire invalide configureWizard.finish.title=Termin\u00e9 configureWizard.finish.message=Vuze est maintenant configur\u00e9, amusez-vous bien\u00a0! wizard.close.message=Voulez-vous ex\u00e9cuter cet assistant la prochaine fois qu'Vuze est lanc\u00e9\u00a0? exportTorrentWizard.title=Exporter un torrent en XML exportTorrentWizard.torrentfile.title=S\u00e9lection du torrent exportTorrentWizard.torrentfile.message=S\u00e9lectionner le fichier torrent \u00e0 exporter exportTorrentWizard.torrentfile.path=Chemin exportTorrentWizard.torrentfile.browse=... exportTorrentWizard.torrentfile.invalidPath=Fichier torrent invalide exportTorrentWizard.exportfile.title=S\u00e9lection du torrent \u00e0 exporter exportTorrentWizard.exportfile.message=Entrer le nom du fichier XML \u00e0 cr\u00e9er exportTorrentWizard.exportfile.path=Chemin exportTorrentWizard.exportfile.browse=... exportTorrentWizard.exportfile.invalidPath=Fichier \u00e0 exporter invalide exportTorrentWizard.finish.title=Termin\u00e9 exportTorrentWizard.finish.message=Exportation termin\u00e9 avec succ\u00e8s exportTorrentWizard.process.inputfilebad.title=Fichier torrent invalide exportTorrentWizard.process.inputfilebad.message=Une erreur s'est produite en acc\u00e9dant au fichier\u00a0: exportTorrentWizard.process.outputfileexists.title=Le fichier existe d\u00e9j\u00e0 exportTorrentWizard.process.outputfileexists.message=Le fichier de destination existe d\u00e9j\u00e0\u00a0; le remplacer\u00a0? exportTorrentWizard.process.torrentfail.title=La lecture du torrent a \u00e9chou\u00e9 exportTorrentWizard.process.exportfail.title=L'exportation du torrent a \u00e9chou\u00e9 exportTorrentWizard.process.unknownfail.title=Erreur inattendue importTorrentWizard.title=Importer un torrent importTorrentWizard.torrentfile.title=S\u00e9lection du torrent importTorrentWizard.torrentfile.message=S\u00e9lectionner le fichier torrent \u00e0 importer importTorrentWizard.torrentfile.path=Chemin d'acc\u00e8s importTorrentWizard.torrentfile.browse=Rechercher importTorrentWizard.torrentfile.invalidPath=Fichier torrent invalide importTorrentWizard.importfile.title=S\u00e9lection du fichier \u00e0 importer importTorrentWizard.importfile.message=Choissiser le fichier \u00e0 importer: importTorrentWizard.importfile.path=Chemin: importTorrentWizard.importfile.browse=... importTorrentWizard.importfile.invalidPath=Fichier d'importation invalide importTorrentWizard.finish.title=Termin\u00e9 importTorrentWizard.finish.message=Importation termin\u00e9 avec succ\u00e8s importTorrentWizard.process.inputfilebad.title=Fichier d'import invalide importTorrentWizard.process.inputfilebad.message=Une erreur s'est produite en acc\u00e8dant au fichier \u00e0 importer: importTorrentWizard.process.outputfileexists.title=Le fichier existe d\u00e9j\u00e0 importTorrentWizard.process.outputfileexists.message=Le fichier destination existe d\u00e9j\u00e0\u00a0; le remplacer\u00a0? importTorrentWizard.process.torrentfail.title=L'\u00e9criture du torrent a \u00e9chou\u00e9 importTorrentWizard.process.importfail.title=L'importation du torrent a \u00e9chou\u00e9 importTorrentWizard.process.unknownfail.title=Erreur inconnue ConfigView.label.bindip=Associer \u00e0 l'adresse IP locale ou \u00e0 l'interface ConfigView.label.xfs.allocation=Allouer les nouveaux fichiers en utilisant une m\u00e9thode sp\u00e9cifique au syst\u00e8me de fichier XFS ConfigView.label.xfs.allocation.tooltip=Assurez-vous que /usr/sbin/xfs_io est correctement install\u00e9 sur votre syst\u00e8me. La plupart des distributions Linux l'incluent dans le paquetage "xfsprogs". xfs.allocation.xfs_io.not.found=L'allocation de fichier pour syst\u00e8me de fichiers XFS a \u00e9chou\u00e9 parce que /usr/sbin/xfs_io n'a pu \u00eatre lanc\u00e9. Assurez-vous qu'il est correctement install\u00e9 sur votre syst\u00e8me. L'erreur originelle est : "%1". ConfigView.label.zeronewfiles=Allouer les nouveaux fichiers avec des z\u00e9ros ConfigView.label.zeronewfiles.tooltip=La console doit \u00eatre ferm\u00e9e ConfigView.section.stats=Statistiques ConfigView.section.stats.enable=Activer ConfigView.section.stats.defaultsavepath=R\u00e9pertoire de sauvegarde des statistiques ConfigView.section.stats.choosedefaultsavepath=Veuillez choisir le r\u00e9pertoire de sauvegarde des statistiques ConfigView.section.stats.savefreq=Fr\u00e9quence de sauvegarde ConfigView.section.stats.savefile=Nom du fichier de statistiques MyTorrentsView.menu.export=Exporter en XML... MyTorrentsView.menu.host=H\u00e9&berger... ManagerItem.finishing=Ach\u00e8vement ConfigView.dialog.choosedefaulttorrentpath=Choissisez le r\u00e9pertoire d'enregistrement des .torrent ConfigView.dialog.choosemovepath=Choissisez le r\u00e9pertoire o\u00f9 d\u00e9placer les torrents compl\u00e9t\u00e9s ConfigView.label.movecompleted=D\u00e9placer les fichiers achev\u00e9s ConfigView.label.savetorrents=Conserver les fichiers .torrent MainWindow.menu.view.mytracker=Mon &tracker MyTrackerView.title.full=Mon Tracker MyTrackerView.name=Nom MyTrackerView.status=\u00c9tat MyTrackerView.status.started=En marche MyTrackerView.status.stopped=Arr\u00eat\u00e9 MyTrackerView.peers=Clients MyTrackerView.seeds=Sources MyTrackerView.announces=Annonces MyTrackerView.uploaded=Qt\u00e9 envoy\u00e9e MyTrackerView.downloaded=Qt\u00e9 re\u00e7ue MyTrackerView.left=Restant ConfigView.label.set_ui_transfer_speeds.description.download=R\u00e9glage des vitesses de t\u00e9l\u00e9chargement (en Ko / s) ConfigView.label.set_ui_transfer_speeds.description.upload=R\u00e9glage des vitesses de partage (en Ko / s) ConfigView.section.style.useCustomTabs=Utiliser des onglets fermables (n\u00e9cessite un red\u00e9marrage) fileDownloadWindow.saveTorrentIn=Sauvegarder le fichier torrent dans fileDownloadWindow.title=Vuze - T\u00e9l\u00e9chargeur de torrents fileDownloadWindow.downloading=T\u00e9l\u00e9chargement depuis\u00a0: fileDownloadWindow.status=\u00c9tat\u00a0: fileDownloadWindow.state_initializing=Initialisation fileDownloadWindow.state_downloading=T\u00e9l\u00e9chargement fileDownloadWindow.state_error=Erreur\u00a0: MainWindow.menu.file.open.url=&URL MainWindow.menu.file.open.url.keybinding=Meta+U openUrl.title=Vuze - Ouvrir l'URL openUrl.url=URL: MyTorrentsView.menu.host.error.title=L'h\u00e9bergement du torrent a \u00e9chou\u00e9 MyTorrentsView.menu.host.error.message=L'erreur suivante s'est produite lors de l'h\u00e9bergement du torrent ConfigView.section.tracker.pollinterval=Intervalle de temps d'interrogation du tracker (secs) ConfigView.section.tracker.publishenable=Publier les d\u00e9tails du torrent vers "/" ConfigView.section.tracker.ip=Adresse IP externe du tracker ConfigView.section.style.enableXPStyle=Activer le style XP (n\u00e9cessite un red\u00e9marrage) IPChecker.external.service.dyndns.url=www.dyndns.org ConfigView.section.tracker.checkip=V\u00e9rification de l'adresse... ipCheckerWizard.title=Assistant de v\u00e9rification d'IP ipCheckerWizard.chooseService=Veuillez choisir un service de v\u00e9rification d'IP ci-dessous: ipCheckerWizard.explanations=Cet assistant vous aide \u00e0 d\u00e9terminer votre adresse IP externe. Si votre IP est dynamique, il est conseill\u00e9 d'ouvrir un compte avec un Dynamic DNS Service. De tels services sont list\u00e9s ci-dessous, utiliser le lien fourni pour cr\u00e9er un compte. Remplissez alors le champ IP avec votre nom d'h\u00f4te (e.g. monnomdhote.dyndns.org). Vous aurez besoin d'un programme qui mettra \u00e0 jour Dynamic DNS Service avec votre adresse IP. De cette mani\u00e8re, vous pourrez h\u00e9berger des torrents, m\u00eame si votre IP change. ipCheckerWizard.service.description=Description: ipCheckerWizard.service.url=Lien: ipCheckerWizard.progresstitle=V\u00e9rification IP ipCheckerWizard.checkComplete=IP trouv\u00e9e : ipCheckerWizard.checkFailed=Erreur, raison: wizard.tracker.local=Utiliser le tracker int\u00e9gr\u00e9 \u00e0 Vuze wizard.tracker.external=Utiliser un tracker externe wizard.tracker.howToLocal=\tAller dans 'Options > Tracker' pour l'activer wizard.announceUrl=Annonce URL: IPChecker.external.service.discoveryvip.url=ip.discoveryvip.com IPChecker.external.service.discoveryvip.description=Discoveryvip - v\u00e9rification d'adresses IP seulement IPChecker.external.httpinvalidresponse=R\u00e9ponse HTTP non valide IPChecker.external.loadingwebpage=Chargement de la page Web IPChecker.external.analysingresponse=Analyse de la r\u00e9ponse IPChecker.external.addressextracted=Adresse IP extraite IPChecker.external.httploadfail=Le chargement de la page a \u00e9chou\u00e9 IPChecker.external.timeout=Timeout IPChecker.external.ipnotfound=Adresse IP introuvable ConfigView.section.tracker.pollintervalincby=Augmenter de ConfigView.section.tracker.pollintervalincper=Tous les 'n' clients splash.loadingImages=Chargement des images... splash.initializeGui=Initialisation de la fen\u00eatre principale... splash.openViews=Ouverture des onglets... splash.plugin=Chargement du Plugin : configureWizard.nat.tooManyPorts=Trop de ports \u00e0 tester (9 max) ConfigView.section.color=Th\u00e8me de Couleur MyTorrentsView.menu.publish=&Publier... MyTrackerView.status.published=Publi\u00e9 MyTrackerView.completed=Complet\u00e9 MainWindow.menu.file.open.torrentnodefault=Fichier torrent (sans r\u00e9pertoire par d\u00e9faut) wizard.comment=Commentaire ConfigView.label.movetorrent=D\u00e9placer le .torrent ConfigView.label.movepartialdownloads=D\u00e9placer, m\u00eame si certains fichiers sont marqu\u00e9s "Ne pas t\u00e9l\u00e9charger" ConfigView.section.file.decoder.label=Encodage par d\u00e9faut\nquand un choix est n\u00e9cessaire ConfigView.section.file.decoder.nodecoder=Aucun IPChecker.external.service.no-ip.url=www.no-ip.com IPChecker.external.service.no-ip.description=Fournisseur de services DNS dynamique et statique\n(aucun service de v\u00e9rification d'IP gratuit) ConfigView.section.tracker.publicenable=Autoriser les torrents externes ConfigView.label.playdownloadspeech=Jouer \u00e0 la fin d'un t\u00e9l\u00e9chargement ConfigView.label.playdownloadspeech.info=Les services de parole fonctionnent actuellement mieux en anglais # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Refl\u00e8te le nombre de copies disponibles.\nSi le nombre \u00e0 droite est inf\u00e9rieur \u00e0 1, vous ne voyez pas une copie compl\u00e8te du fichier\net il fortement probable que votre t\u00e9l\u00e9chargement n'aboutisse pas. GeneralView.label.trackerurl.tooltip=Cliquer pour copier l'URL d'annonce dans le presse-papier GeneralView.label.trackerurlopen.tooltip=Cliquer pour ouvrir la page Web du Tracker # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Mise \u00e0 jour de l'interface graphique (GUI) toutes les ConfigView.section.style.graphicsUpdate=Mise \u00e0 jour des barres graphiques toutes les 'n' mises \u00e0 jour GUI ConfigView.section.style.reOrderDelay=R\u00e9-ordonner les tables toutes les 'n' mises \u00e0 jour GUI [0\u00a0: jamais] ConfigView.section.style.reOrderDelay.never=Jamais ConfigView.section.logging=Journalisation ConfigView.section.logging.enable=Activer la journalisation vers un fichier ConfigView.section.logging.logdir=R\u00e9pertoire du fichier journal ConfigView.section.logging.choosedefaultsavepath=Veuillez choisir le r\u00e9pertoire de sauvegarde GeneralView.label.updatein.querying=Requ\u00eate en cours... configureWizard.nat.sharePort=N'utiliser qu'un seul port entrant partag\u00e9 pour tous les torrents ConfigView.section.logging.maxsize=Taille maximale du fichier de journalisation ConfigView.section.tracker.passwordenableweb=Activer mot de passe sur le tracker Web ConfigView.section.tracker.passwordenabletorrent=Activer mot de passe sur les torrents ConfigView.section.tracker.username=Nom d'utilisateur ConfigView.section.tracker.password=Mot de passe columnChooser.title=Choisissez les colonnes \u00e0 afficher columnChooser.move=D\u00e9placer les lignes pour r\u00e9organiser l'ordre columnChooser.apply=Appliquer columnChooser.columnname=Nom de la colonne TableColumn.header.shareRatio=TP MyTorrentsView.menu.editTableColumns=Choix des &colonnes \u00e0 afficher wizard.operationfailed=L'op\u00e9ration a \u00e9chou\u00e9e authenticator.title=Authentification requise authenticator.realm=Domaine authenticator.user=Nom d'utilisateur authenticator.password=Mot de passe ConfigView.label.allowSendVersion=Permettre \u00e0 Vuze d'envoyer un num\u00e9ro de version anonyme et un identifiant al\u00e9atoire lors de la recherche de mise \u00e0 jour (dans un but statistique). ConfigView.label.version.info.link=Allez voir ici pour plus de d\u00e9tails sur les donn\u00e9es qui sont envoy\u00e9es \u00e0 la v\u00e9rification de version du serveur wizard.hint.mode=Astuce:\tVous pouvez glisser/d\u00e9placer un fichier ou un r\u00e9pertoire \n\tsur cet assistant pour le s\u00e9lectionner wizard.hint.file=Astuce:\tVous pouvez choisir un seul fichier avec le glisser/d\u00e9placer wizard.hint.directory=Astuce:\tVous pouvez choisir un seul r\u00e9pertoire avec le glisser/d\u00e9placer MainWindow.menu.help.checkupdate=Rechercher une &mise \u00e0 jour de Vuze TableColumn.header.down=T\u00e9l\u00e9charg\u00e9 TableColumn.header.up=Envoy\u00e9 ConfigView.section.tracker.passwordenabletorrent.info=N\u00e9cessite un client BitTorrent adapt\u00e9 (e.g. Vuze ConfigView.section.style.confirmationOnExit=Faire apparaitre une confirmation \u00e0 la fermeture MainWindow.dialog.exitconfirmation.title=Fermer Vuze u00a0? MainWindow.dialog.exitconfirmation.text=Voulez-vous vraiment fermer Vuze u00a0? SystemTray.menu.stopalltransfers=&Arr\u00eater tous les transferts TrayWindow.menu.stopalldownloads=&Arr\u00eater tous les t\u00e9l\u00e9chargements ConfigView.section.tracker.sslport.info=Voir le FAQ pour plus d'informations wizard.tracker.ssl=Utiliser SSL ConfigView.label.playdownloadfinished=Jouer un son quand un t\u00e9l\u00e9chargement se termine ConfigView.label.popupdownloadfinished=Montrer une alerte 'popup' quand un t\u00e9l\u00e9chargement est termin\u00e9 ConfigView.label.popupfilefinished=Montrer une alerte 'popup' quand un fichier est termin\u00e9 TableColumn.header.pieces=Pi\u00e8ces TableColumn.header.pieces.info=Barre graphique r\u00e9pr\u00e9sentant quelles pi\u00e8ces vous avez t\u00e9l\u00e9charg\u00e9 TableColumn.header.completion=\u00c9tat d'avancement TableColumn.header.completion.info=Repr\u00e9sentation graphique du % t\u00e9l\u00e9charg\u00e9 ConfigView.section.style.showdownloadbasket=Afficher le panier de t\u00e9l\u00e9chargements (glisser et d\u00e9placer les .torrent) ConfigView.section.style.alwaysShowTorrentFiles=Toujours montrer les fichiers Torrent dans Details/Fichiers wizard.multitracker=Ajouter des informations Multi-tracker au torrent wizard.multitracker.title=Multi-tracker wizard.multitracker.configuration=Configuration du Multi-tracker wizard.multitracker.new=Nouveau... wizard.multitracker.edit=\u00c9diter.. wizard.multitracker.delete=Effacer wizard.multitracker.group=Groupe de trackers wizard.multitracker.edit.title=\u00c9diteur de multi-tracker wizard.multitracker.edit.name=Nom wizard.multitracker.edit.save=Sauver wizard.multitracker.edit.newgroup=Nouveau groupe wizard.multitracker.edit.deletegroup=Effacer wizard.multitracker.edit.newtracker=Nouveau tracker wizard.multitracker.edit.deletetracker=Effacer wizard.multitracker.edit.edit=\u00c9diter wizard.addingmt=Ajout des infos Multi-tracker wizard.multitracker.noannounce=L'URL d'annonce n'est pas pr\u00e9sente dans la liste de tracker MyTorrentsView.menu.recheck=Forcer une re-&v\u00e9rification iconBar.showDownloadBar.tooltip=Afficher la barre de t\u00e9l\u00e9chargement iconBar.start.tooltip=Commencer iconBar.stop.tooltip=Arr\u00eater iconBar.remove.tooltip=Enlever iconBar.openNoDefault.tooltip=Ouvrir un fichier torrent (sans r\u00e9pertoire par d\u00e9faut) iconBar.openURL.tooltip=Ouvrir une URL iconBar.openFolder.tooltip=Ouvrir un r\u00e9pertoire iconBar.new.tooltip=Cr\u00e9er un torrent iconBar.up.tooltip=D\u00e9placer vers le haut iconBar.down.tooltip=D\u00e9placer vers le bas iconBar.run.tooltip=Ouvrir iconBar.host.tooltip=H\u00e9berger iconBar.publish.tooltip=Publier MyTorrentsView.menu.editTracker=\u00c9diter l'(les) &URL(s) du tracker GeneralView.menu.selectTracker=S\u00e9lectionner ConfigView.section.stats.xslfile=Nom du fichier XSL ConfigView.section.stats.xslfiledetails=Ajout\u00e9 aux stats gr\u00e2ce \u00e0 ConfigView.label.savetorrentbackup=Conserver une sauvegarde ConfigView.section.tracker.forceport=Forcer les torrents externes h\u00e9berg\u00e9s sur le port par d\u00e9faut. ConfigView.section.ipfilter.allow=AUTORISER ces IP (BLOQUER par d\u00e9faut) ConfigView.section.ipfilter.list.inrange=est dans la plage ConfigView.section.ipfilter.list.notinrange=n'est dans aucune plage ConfigView.section.ipfilter.list.title=Liste des IP bloqu\u00e9es ConfigView.label.allowsameip=Permettre plus d'une connection de la m\u00eame IP ConfigView.label.allowsameip.tooltip=\u00c0 n'activer qu'en cas de BESOIN.\nProtection contre les "leechers" (quand d\u00e9sactiv\u00e9). ManagerItem.superseeding=Super-Source ConfigView.label.userSuperSeeding=Utiliser le mode Super-Source PeersView.uniquepiece=Pi\u00e8ce (Mode Super-Source) PeersView.uniquepiece.none=Aucune PeersView.timetosend=Temps pour redistribuer la pi\u00e8ce (Mode Super-Source) ConfigView.section.style.addurlsilently=Ouvrir l'URL discr\u00e8tement (sans boite de dialogue) ConfigView.section.style.addurlsilently.tooltip=Attention\u00a0: si activ\u00e9, la fen\u00eatre principale ne sera pas rendue visible\u00a0!\nSi vous perdez l'icone Vuze d\u00e9sactivez cette option. ConfigView.section.file.decoder.prompt=Toujours demander quand un choix d'encodage est disponible ConfigView.section.file.decoder.prompt.tooltip=Afficher une bo\u00eete de dialogue quand un choix d'encodage est possible MyTorrentsView.menu.moveTop=&Haut MyTorrentsView.menu.moveEnd=&Bas ConfigView.label.moveonlyusingdefaultsave=si dans le r\u00e9p par d\u00e9faut ConfigView.label.moveonlyusingdefaultsave.tooltip=Ne d\u00e9placer que si le .torrent est dans le r\u00e9pertoire de sauvegarde par d\u00e9faut ConfigView.label.watchtorrentfolder=Importer les nouveaux torrents automatiquement ConfigView.label.watchtorrentfolder.tooltip=Recherche les nouveaux .torrent r\u00e9guli\u00e8rement ConfigView.label.watchtorrentfolderinterval=Intervale ConfigView.label.watchtorrentfolderinterval.tooltip=Intervale de temps entre les rafra\u00eechissements du contenu du r\u00e9pertoire ConfigView.dialog.choosewatchtorrentfolderpath=Choissisez le r\u00e9pertoire o\u00f9 importer des .torrent ConfigView.label.startwatchedtorrentsstopped=Commencer arr\u00eat\u00e9 ConfigView.label.startwatchedtorrentsstopped.tooltip=Ajoute les nouveaux torrents en mode ARR\u00caT\u00c9 wizard.maketorrent.filesize=Taille fichier(s) wizard.maketorrent.piececount=Nombre de pi\u00e8ces wizard.maketorrent.piecesize=Taille d'une pi\u00e8ce wizard.maketorrent.auto=Automatique MainWindow.menu.view.stats=&Statistiques SpeedView.title.full=Activit\u00e9 SpeedView.downloadSpeed.title=Vitesse de t\u00e9l\u00e9chargement SpeedView.uploadSpeed.title=Vitesse d'envoi ConfigView.section.style.useSIUnits=Utiliser les unit\u00e9s du C\u00c9I (ko -> Kio, etc.) iconBar.top.tooltip=D\u00e9placer en t\u00eate de file iconBar.bottom.tooltip=D\u00e9placer en bas de file TableColumn.header.health=Indicateur de sant\u00e9 MyTorrentsView.menu.health=\u00c0 propos de l'indic&ateur de sant\u00e9 health.explain.grey=Le torrent n'est pas en route. (ni en t\u00e9l\u00e9chargement ni en envoi) health.explain.red=En t\u00e9l\u00e9chargeant, vous n'\u00eates connect\u00e9s \u00e0 aucun client. health.explain.blue=Si source, vous n'\u00eates encore connect\u00e9s \u00e0 aucun client\nSi en t\u00e9l\u00e9chargement, vous \u00eates connect\u00e9s \u00e0 des clients mais le tracker est d\u00e9connect\u00e9. health.explain.yellow=Le Tracker est OK, vous avez des connexions \u00e0 des clients, mais aucune entrante.\nSi persistant, vous avez vraisemblablement un probl\u00e8me de configuration de routeur ou de pare-feu health.explain.green=Tout se passe bien. ConfigView.section.style.alwaysRefreshMyTorrents=Toujours rafra\u00eechir 'Mes Torrents' ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Cette option force la mise \u00e0 jour de 'Mes torrents' m\u00eame si cet onglet n'est pas affich\u00e9 (utile pour certains plugins Mirc) # #2.0.7.0 # security.certtruster.title=Avertissement du certificat de s\u00e9curit\u00e9 security.certtruster.intro=Le certificat de s\u00e9curit\u00e9 provient d'une compagnie \u00e0 laquelle vous ne faites pas confiance security.certtruster.resource=Ressource: security.certtruster.issuedto=Publi\u00e9 pour: security.certtruster.issuedby=Publi\u00e9 par: security.certtruster.prompt=Voulez-vous y faire confiance\u00a0? security.certtruster.yes=Oui security.certtruster.no=Non ConfigView.section.tracker.torrentsperpage=Combien de torrents par page\u00a0? [0\u00a0: illimit\u00e9] MainWindow.menu.file.share=&Partager MainWindow.menu.file.share.file=&Fichier... MainWindow.menu.file.share.dir=&R\u00e9pertoire... MainWindow.menu.file.share.dircontents=C&ontenu du r\u00e9pertoire... MainWindow.menu.file.share.dircontentsrecursive=Contenu du r\u00e9pertoire (inclure &sous-r\u00e9pertoires)... MainWindow.dialog.share.sharefile=Selectionner le fichier \u00e0 partager MainWindow.dialog.share.sharedir=S\u00e9lectionner le r\u00e9pertoire \u00e0 partager MainWindow.dialog.share.sharedircontents=S\u00e9lectionner le contenu du r\u00e9pertoire \u00e0 partager MainWindow.dialog.share.sharedircontents.recursive=Inclure les sous-r\u00e9pertoires globalmanager.download.remove.veto=V\u00e9to d'arr\u00eat plugin.sharing.download.remove.veto=Ce t\u00e9l\u00e9chargement provient d'une ressource partag\u00e9e.\nEnlever le t\u00e9l\u00e9chargement revient \u00e0 priver les autres de la ressource: voir Outils->Mes Partages. ConfigView.section.tracker.main=Principal ConfigView.label.prioritizefirstpiece=Donner la priorit\u00e9 aux premi\u00e8res pi\u00e8ces de fichiers ConfigView.label.prioritizefirstpiece.tooltip=Tente de t\u00e9l\u00e9charger le d\u00e9but d'un fichier en premier.\nPeut permettre la pr\u00e9visualisation. ConfigView.section.file.confirm_data_delete=Demander une confirmation avant d'effacer les donn\u00e9es ConfigView.section.file.confirm_data_delete.tooltip=Demande une confirmation quand "Enlever et effacer..." est utilis\u00e9. TrayWindow.menu.startalldownloads=&D\u00e9marrer tous les t\u00e9l\u00e9chargements SystemTray.menu.startalltransfers=&D\u00e9marrer tous les transferts sharing.progress.title=\u00c9tat du partage sharing.progress.hide=Cacher MainWindow.menu.view.myshares=&Mes partages MySharesView.title.full=Mes partages MySharesView.name=Nom MySharesView.type.file=Fichier MySharesView.type.dir=R\u00e9pertoire MySharesView.type.dircontents=Contenu du r\u00e9pertoire MySharesView.type.dircontentsrecursive=Contenu du r\u00e9pertoire (et sous-r\u00e9pertoires) MySharesView.menu.remove=Enlever ConfigView.section.tracker.sendpeerids=Envoyer le num\u00e9ro de client ("peer ID") aux t\u00e9l\u00e9chargeurs ConfigView.section.tracker.enableudp=Activer l'UDP pour le protocole du tracker plugin.sharing.torrent.remove.veto=Cet enregistrement au tracker est d\u00fb \u00e0 une ressource partag\u00e9e.\nPour supprimer le t\u00e9l\u00e9chargement vous devez enlever le partage. plugin.download.remove.veto.notstopped=Ce t\u00e9l\u00e9chargement ne peut pas \u00eatre enlev\u00e9 car il n'est pas arr\u00eat\u00e9. plugin.sharing.remove.veto=Ce partage est inclus dans un contenu de r\u00e9peroire partag\u00e9 et ne peut pas \u00eatre effac\u00e9 seul.\n Veuiller enlever le partage du r\u00e9pertoire racine. GeneralView.label.hash.tooltip=Cliquer pour copier le hash dans le presse-papier. ConfigView.section.tracker.maxpeersreturned=Nombre maximum de clients renvoy\u00e9s [0\u00a0: illimit\u00e9] ConfigView.label.serverport=Port d'\u00e9coute TCP entrant ConfigView.label.serverport.tooltip=Le port doit \u00eatre entre 1 et 65535, et diff\u00e9rent de 6880 qu'Vuze utilise en interne. configureWizard.nat.server.tcp_listen_port=Port TCP d'\u00e9coute entrant ConfigView.section.sharing=Partage ConfigView.section.sharing.usessl=Utiliser le SSL pour le partage (n\u00e9cessite de configurer le tracker) ConfigView.section.style.dropdiraction=Glisser-d\u00e9placer pour les r\u00e9pertoires ConfigView.section.style.dropdiraction.opentorrents=Ouvrir les torrents ConfigView.section.style.dropdiraction.sharefolder=R\u00e9pertoire de partage ConfigView.section.style.dropdiraction.sharefoldercontents=Contenu partag\u00e9 # # 2.0.7.x # Categories.all=Tous Categories.uncategorized=Non class\u00e9s CategoryAddWindow.message=Entrer un nom de cat\u00e9gorie CategoryAddWindow.title=Ajouter une nouvelle cat\u00e9gorie ConfigView.label.autoSeedingIgnoreInfo=Les torrents ignor\u00e9s sont d\u00e9plac\u00e9s en bas de file. Ils ne d\u00e9marrent pas automatiquement. Les r\u00e8gles "Ignorer" ne s'appliquent pas aux torrents de "Premi\u00e8re priorit\u00e9". Utilisez la valeur 0 pour ignorer une r\u00e8gle.\n\n ConfigView.label.directory=Dans le r\u00e9pertoire\u00a0: ConfigView.label.disconnetseed.tooltip=Lorsque le t\u00e9l\u00e9chargement est termin\u00e9, la communication\navec d'autres sources n'est plus vraiment n\u00e9cessaire. ConfigView.label.ignoreCase=Ignorer la case ConfigView.label.ignoreSeeds=Ignorer les torrents avec au moins ConfigView.label.importdirectory=Dans le r\u00e9pertoire\u00a0: ConfigView.label.minPeersToBoostNoSeeds.tooltip=Tout torrent sans source ou avec moins de sources que sp\u00e9cifi\u00e9\nsera plac\u00e9 en bas de file. ConfigView.label.minPeersToBoostNoSeeds=Diminuer le "Rang de source" pour les torrents avec moins de ConfigView.label.minSeedingTime.tooltip=Le "rang de source" d'un torrent peut varier fortement pendant une courte p\u00e9riode, for\u00e7ant parfois un torrent \u00e0 d\u00e9marrer pour \u00eatre arr\u00eat\u00e9 et mis en attente juste apr\u00e8s.\nCeci all\u00e8ge le probl\u00e8me en for\u00e7ant le torrent \u00e0 rester source pendant un certain temps. Vous pouvez toujours l'arr\u00eater manuellement. ConfigView.label.minSeedingTime=Temps de source minimum en secondes ConfigView.label.minSpeedForActiveDL.tooltip=Un cr\u00eaneau de t\u00e9l\u00e9chargement est utilis\u00e9 pendant les 30 premi\u00e8res secondes\nde d\u00e9marrage d'un torrent incomplet. ConfigView.label.minSpeedForActiveDL=Ne pas compter de cr\u00eaneau de t\u00e9l\u00e9chargement pour les torrents dont la vitesse est de moins de ConfigView.label.peers=clients ConfigView.label.queue.debuglog=Journalisation des informations de d\u00e9boguage ConfigView.label.queue.debuglog.info=Ajoute les informations de d\u00e9boguage \u00e0 propos de la file d'attente\ndans la console et dans le journal. Quoique cryptiques,\nces informations vous donnent l'\u00e9tat des torrents\net et pourquoi ils sont arr\u00eat\u00e9s/refusent de d\u00e9marrer. ConfigView.label.queue.minQueueingShareRatio=Ne pas arr\u00eater ou mettre en attente un torrent tant que son taux de partage n'atteint pas ConfigView.label.ratio=taux ConfigView.label.removeOnStop=Enlever le torrent de la liste s'il s'arr\u00eate automatiquement ConfigView.label.savedirectory=Dans le r\u00e9pertoire\u00a0: ConfigView.label.seeding.autoReposition.tooltip=Si activ\u00e9e, l'ordre des torrents (la colonne '#') sera chang\u00e9 pour s'accorder \u00e0 celui des "Rangs de source"\nC'est utile si vous ne voulez pas voir les nombres des rangs de source mais voulez tout de m\u00eame savoir dans quel ordre les torrents compl\u00e9t\u00e9s vont d\u00e9marrer. ConfigView.label.seeding.autoReposition=Repositionner automatiquement les torrents en fonction de leur Rang de source ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Souvent les torrents avec peu de sources et beaucoup de clients n'ont pas de copie compl\u00e8te parmi les clients.\nOn ne veut pas alors pr\u00e9tendre qu'il y a une copie compl\u00e8te dans ce cas (et ainsi r\u00e9duire injustement la priorit\u00e9 du torrent) ConfigView.label.seeding.fakeFullCopySeedStart=mais seulement pour les torrents avec au moins ConfigView.label.seeding.ignore=R\u00e8gles Ignorer ConfigView.label.seeding.ignore0Peers=Ignorer les torrents avec 0 client ConfigView.label.seeding.ignoreRatioPeers=Ignorer les torrents avec au moins 1 source pour ConfigView.label.seeding.ignoreShareRatio=Ignorer les torrents avec un taux de partage de ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorer un torrent m\u00eame si\nles r\u00e8gles de Premi\u00e8re Priorit\u00e9 s'appliquent ConfigView.label.seeding.ignore.header.rule=R\u00e8gle ConfigView.label.seeding.ignore.header.value=Valeur ConfigView.label.seeding.firstPriority.info=Les torrents de Premi\u00e8re Priorit\u00e9 seront toujours en t\u00eate de liste. Les torrents class\u00e9s dans "Aucun" ou "Rotation temporelle" correspondant aux crit\u00e8res de "Premi\u00e8re Priorit\u00e9" ne seront pas automatiquement arr\u00eat\u00e9 et mis en attente. Un torrent de premi\u00e8re priorit\u00e9 prendra un cr\u00eaneau de t\u00e9l\u00e9chargement simultan\u00e9 si besoin (un torrent en source a priorit\u00e9 sur un torrent en t\u00e9l\u00e9chargement). ConfigView.label.seeding.firstPriority.FP=Premi\u00e8re Priorit\u00e9 ConfigView.label.seeding.firstPriority=La premi\u00e8re priorit\u00e9 s'applique aux torrents v\u00e9rifiant ConfigView.label.seeding.firstPriority.following=conditions suivantes\u00a0: ConfigView.label.seeding.firstPriority.shareRatio=Un taux de partage inf\u00e9rieur \u00e0 ConfigView.label.seeding.firstPriority.seedingMinutes=Un temps \u00e9coul\u00e9 depuis le passage de "t\u00e9l\u00e9chargement" \u00e0 "source" ConfigView.label.seeding.firstPriority.DLMinutes=Un temps \u00e9coul\u00e9 depuis le d\u00e9but du t\u00e9l\u00e9chargement ConfigView.label.seeding.numPeersAsFullCopy.tooltip=En pr\u00e9tendant qu'il y a 1 copie compl\u00e8te tous les X clients, on diminue le rang des torrents avec beaucoup de clients.\nCes torrents ont g\u00e9n\u00e9ralement beaucoup de trafic.\nCela ne change pas l'affichage du nombre de sources effectives. ConfigView.label.seeding.numPeersAsFullCopy=Pr\u00e9tendre qu'il y a 1 copie compl\u00e8te tous les\n(0\u00a0: ne pas pr\u00e9tendre) ConfigView.label.seeding.preferLargerSwarms.tooltip=Si vous \u00eates source de principalement des torrents avec des clients "bloqu\u00e9s", pr\u00e9ferer les plus utilis\u00e9s\nSi vous \u00eates source de principalement des torrents \u00e0 haute disponibilit\u00e9, pref\u00e9rer les moins utilis\u00e9s. ConfigView.label.seeding.preferLargerSwarms=Quand des torrents ont le m\u00eame rang, pr\u00e9ferer les plus utilis\u00e9s. ConfigView.label.seeding.rankType.none.tooltip=Ordre \u00e0 partir de la colonne '#' ConfigView.label.seeding.rankType.none=Aucun ConfigView.label.seeding.rankType.peerSeed.options=Options de "taux Clients/Sources" ConfigView.label.seeding.rankType.peerSeed.tooltip=Taux plus haut = rang plus \u00e9lev\u00e9 ConfigView.label.seeding.rankType.peerSeed=Taux de Clients/Sources ConfigView.label.seeding.rankType.seed.fallback=Revenir au taux Clients/Sources apr\u00e8s\n(0\u00a0: ne pas y revenir) ConfigView.label.seeding.rankType.seed.options=Options du "nombre de sources uniquement" ConfigView.label.seeding.rankType.seed.tooltip=Nombre de sources faible = Rang plus \u00e9lev\u00e9 ConfigView.label.seeding.rankType.seed=Nombre de sources uniquement ConfigView.label.seeding.rankType.timedRotation.tooltip=Tous les torrents termin\u00e9s et mis en attente passeront source chacun leur tour.\nLa dur\u00e9e de source est d\u00e9finie par 'Temps de source minimum' ConfigView.label.seeding.rankType.timedRotation=Rotation temporelle ConfigView.label.seeding.rankType.tooltip=Les torrents de plus haut rangs sont d\u00e9marr\u00e9s automatiquement.\nSi un torrent prend un rang plus \u00e9lev\u00e9, l'autre torrent s'arr\u00eate et se remet dans la file d'attente.\n\nSeuls les torrents "En attente..." sont disponibles pour un d\u00e9marrage automatique.\nJamais les torrents arr\u00eat\u00e9s seront d\u00e9marr\u00e9s automatiquement. ConfigView.label.seeding.rankType=Pour le d\u00e9marrage automatique, classer les torrents termin\u00e9s en fonction de\u00a0: ConfigView.label.stopAfterMinutes=Une fois en mode source, arr\u00eater apr\u00e8s ConfigView.label.switchpriority.tooltip=Une faible priorit\u00e9 r\u00e9duit la vitesse d'envoi allou\u00e9e \u00e0 un torrent. ConfigView.pluginlist.info=Les plugins suivants ont \u00e9t\u00e9 identifi\u00e9s. Certains plugins peuvent ne pas avoir d'onglet de configuration. ConfigView.pluginlist.noplugins=Aucun plugin trouv\u00e9. ConfigView.section.pluginslist=Liste ConfigView.section.queue.seeding=Source ConfigView.section.queue.seeding.autoStarting=D\u00e9marrage automatique ConfigView.section.queue.seeding.ignore=R\u00e8gles "Ignorer" ConfigView.section.queue.seeding.firstPriority=Premi\u00e8re Priorit\u00e9 ConfigView.section.queue.main=Principal ConfigView.section.queue=File d'attente ConfigView.text.all=toutes les ConfigView.text.hours=heures ConfigView.text.ignoreRule=Ignorer la r\u00e8gle ConfigView.text.ignore=Ignorer ConfigView.text.neverIgnore=Ne jamais ignorer ConfigView.text.any=une des DownloadManager.error.datamissing=Donn\u00e9es manquantes MainWindow.menu.file.open.torrentforseeding=Fichier .torrent (source) MainWindow.menu.language.refresh=&Rafra\u00eechir ManagerItem.forced=(Forc\u00e9) ManagerItem.queued=En attente MySeedersView.header=Torrents complets/en source TableColumn.header.availability.info=# de copies compl\u00e8tes vues TableColumn.header.availability=Disponibilit\u00e9 TableColumn.header.category=Cat\u00e9gorie MyTorrentsView.header=Torrents incomplets/en t\u00e9l\u00e9chargement TableColumn.header.maxuploads=Nb max d'envois MyTorrentsView.menu.category.delete=Effacer cette cat\u00e9&gorie MyTorrentsView.menu.forceStart=Forcer le d\u00e9&marrage MyTorrentsView.menu.queue=Placer en &file d'attente MyTorrentsView.menu.setCategory.add=&Ajouter une cat\u00e9gorie.. MyTorrentsView.menu.setCategory=Classer dans TableColumn.header.savepath=Chemin de sauvegarde TableColumn.header.SeedingRank=Rang de source TableColumn.header.totalspeed.info=Vitesse d'envoi individuelle de tout les autres clients/sources auquel vous \u00eates reli\u00e9s. Votre vitesse de t\u00e9l\u00e9chargement \u00e0 ceux-ci n'est pas compt\u00e9e dans ce total. TableColumn.header.totalspeed=Vit. Totale splash.initializePlugins=Initialisation des plugins StartStopRules.SPratioMet=1\u00e8re P / Taux S:P OK StartStopRules.FP0Peers=1\u00e8reP / 0 client StartStopRules.0Peers=0 client StartStopRules.numSeedsMet=Sources OK StartStopRules.ratioMet=Taux C:S OK StartStopRules.shareRatioMet=Taux Partage OK StartStopRules.waiting=En attente StartStopRules.firstPriority=1\u00e8re Priorit\u00e9 ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Partager le contenu (et les sous-r\u00e9pertoire) DownloadManager.error.unabletostartserver=Impossible de d\u00e9marrer le serveur; V\u00e9rifier la configuration du port entrant et/ou les permissions du pare-feu pour permettre \u00e0 l'application de s'ex\u00e9cuter en tant que serveur. GeneralView.label.creationdate=Cr\u00e9\u00e9 le\u00a0: ConfigView.section.tracker.announcescrapepercentage=Intervalle de "Scrape" comme %age de l'annonce\ne.g. 200 = 2:1. (0 = laisser le client d\u00e9cider) ManagerItem.stopping=En arr\u00eat... ConfigView.section.tracker.announcecacheperiod=Cache de l'annonce (ms) ConfigView.section.tracker.scrapecacheperiod=Cache du "Scrape" (ms) ConfigView.section.tracker.scrapeandcache="Scrape" et cache ConfigView.section.tracker.announcecacheminpeers=Seuil de client pour activation du cache de l'annonce MyTrackerView.scrapes="Scrapes" fileDownloadWindow.retry=R\u00e9-essai MyTrackerView.bytesin=Octets Entr\u00e9s MyTrackerView.bytesinave=Moyenne Entr\u00e9e MyTrackerView.bytesout=Octets Sortis MyTrackerView.bytesoutave=Moyenne Sortie ConfigView.section.file.max_open_files=Nombre maximum de fichiers ouverts en\nlecture/\u00e9criture (0 = illimit\u00e9) ConfigView.section.file.max_open_files.tooltip=Utile si vous t\u00e9l\u00e9chargez des torrents compos\u00e9s de centaines de fichiers, et que vous atteignez la limite de gestion de fichiers du syst\u00e8me d'exploitation. ConfigView.section.proxy=Options Proxy ConfigView.section.proxy.enable_proxy=Activer un proxy ConfigView.section.proxy.host=H\u00f4te ConfigView.section.proxy.username=Nom d'utilisateur ConfigView.section.proxy.password=Mot de passe ConfigView.section.proxy.enable_socks=J'ai un proxy SOCKS wizard.createtorrent.extrahashes=Ajoute des "Hash" pour pouvoir utiliser le torrent sur d'autres r\u00e9seaux (e.g. Gnutella2, eDonkey2K). GeneralView.label.connected=connect\u00e9(s) GeneralView.label.in_swarm=au total ManagerItem.initializing=Initialisation AlertMessageBox.error=Erreur AlertMessageBox.warning=Avertissement AlertMessageBox.unread=Vous avez des messages d'alerte non lus - Cliquez ici pour les afficher. SharedPortServer.alert.selectorfailed=Ne peut \u00e9tablir d'\u00e9coute pour les donn\u00e9es entrantes.\nV\u00e9rifier que le pare-feu est r\u00e9gl\u00e9 de telle fa\u00e7on \u00e0 ce que java(w).exe puisse s'ex\u00e9cuter en tant que 'serveur'. Tracker.alert.listenfail=Ne peut pas \u00e9couter sur le port %1.\nV\u00e9rifiez si d'autres applications ne sont pas en train d'utiliser ce port.\nV\u00e9rifiez \u00e9galement si une autre version de Vuze n'est en cours d'execution. DiskManager.alert.movefileexists=Erreur en d\u00e9pla\u00e7ant les fichiers termin\u00e9s\nLe fichier %1 existe d\u00e9j\u00e0 dans le r\u00e9pertoire de destination DiskManager.alert.movefilefails=Erreur en d\u00e9pla\u00e7ant les fichiers termin\u00e9s\nLe d\u00e9placement du fichier %1 a \u00e9chou\u00e9, %2 DiskManager.alert.movefilerecoveryfails=Erreur de r\u00e9cup\u00e9ration apr\u00e8s l'echec du d\u00e9placement\nLa restauration du fichier %1 a \u00e9chou\u00e9, %2 ConfigView.section.tracker.logenable=Ecrire les statistiques p\u00e9riodiques dans 'tracker.log' SpeedView.stats.title=Statistiques SpeedView.stats.session=Cette Session SpeedView.stats.session.tooltip=Total (Protocole) SpeedView.stats.downloaded=T\u00e9l\u00e9charg\u00e9 (Protocole) SpeedView.stats.uploaded=Envoy\u00e9 (Protocole) SpeedView.stats.ratio=Taux SpeedView.stats.uptime=Temps allum\u00e9 (heures) SpeedView.stats.now=Maintenant AutoMigration.useralert=R\u00e9sultat de la migration des fichiers et r\u00e9pertoires utilisateur de Vuze u00a0:\n\n%1\n%2TOUT D\u00c9PLACEMENT \u00c9CHOU\u00c9 DOIT \u00caTRE FAIT MANUELLEMENT. # # > 2.0.8.0 # OpenTorrentWindow.title=Ouvrir le(s) torrent(s) OpenTorrentWindow.message=Exp\u00e9rimental OpenTorrentWindow.addFiles=&Ajouter des fichiers OpenTorrentWindow.dataLocation=Emplacement de sauvegarde: OpenTorrentWindow.startMode=Ajouter en mode OpenTorrentWindow.startMode.queued=En attente OpenTorrentWindow.startMode.stopped=Arr\u00eat\u00e9 OpenTorrentWindow.startMode.forceStarted=D\u00e9marrage forc\u00e9 OpenTorrentWindow.addPosition=Position dans la file OpenTorrentWindow.addPosition.first=Premi\u00e8re OpenTorrentWindow.addPosition.last=Derni\u00e8re TableColumn.header.remaining.info=Quantit\u00e9 restante \u00e0 t\u00e9l\u00e9charger TableColumn.header.remaining=Restant ConfigView.section.tracker.enablecompact=Activer l'annonce de protocole compacte ConfigView.section.tracker.enablekey=Activer l'envoi d'une cl\u00e9 au tracker pour une meilleure s\u00e9curit\u00e9 ConfigView.section.file.perf=Options de Performance ConfigView.section.file.perf.explain=Attention - Des changements innapropri\u00e9s \u00e0 ces param\u00e8tres peuvent diminuer la vitesse de vos transferts. Si vous avez des probl\u00e8me de\nsaturation de m\u00e9moire, diminuez le nombres de clients connect\u00e9s et/ou actifs par d\u00e9faut par torrent. (Options > Transfert) ConfigView.section.file.max_open_files.explain=Avoir trop de fichiers ouverts simultan\u00e9ment peut causer des probl\u00e8mes de performance du syst\u00e8me.\nVous pouvez limiter le nombre de fichiers ouverts simultan\u00e9ment.\n popup.error.hide=Cacher popup.error.details=D\u00e9tails ConfigView.section.style.colorOverrides=Choix de couleur ConfigView.section.style.colorOverride.progressBar=Barre de progession ConfigView.section.style.colorOverride.error=Erreur MainWindow.status.tooOld=est vieux, veuillez le mettre \u00e0 jour. ConfigView.section.style.colorOverride.warning=Attention ConfigView.section.style.colorOverride.altRow=Rangs pairs ConfigView.section.file.save.peers.enable=Sauvegarder les connexions pour des reconnexions rapides ConfigView.section.file.save.peers.max=Nombre maximum de peers \u00e0 sauvegarder [0: illimit\u00e9] ConfigView.section.file.save.peers.pertorrent=par torrent ConfigView.label.max_peers_per_torrent=Nombre maximum de connexions par torrent [0\u00a0: illimit\u00e9] ConfigView.label.max_peers_total=Nombre maximum de connexions en tout [0\u00a0: illimit\u00e9] ConfigView.section.style.colorOverrides.reset=R\u00e9initialiser ConfigView.section.language.info=Une v\u00e9rification sera faite \u00e0 chaque d\u00e9marrage d'Azureus. ConfigView.section.language.enableUpdate=Activer la mise \u00e0 jour par le Web ConfigView.section.language.UpdateURL=URL de mise \u00e0 jour ConfigView.section.language.UpdateNow=Mettre \u00e0 jour maintenant\u00a0! Button.revert=Annuler MyTorrentsView.menu.changeDirectory=Changer le r\u00e9pertoire des donn\u00e9es GenericText.column=colonne MyTorrentsView.menu.thisColumn.remove=Enlever cette colonne MyTorrentsView.menu.thisColumn.toClipboard=Copier le texte dans le presse-papiers ConfigView.upload.abbreviated=U\u00a0: TableColumn.header.secondsseeding=En source depuis TableColumn.header.secondsseeding.info=temps pass\u00e9 en source. TableColumn.header.secondsdownloading=T\u00e9l\u00e9charge depuis TableColumn.header.secondsdownloading.info=temps pass\u00e9 en t\u00e9l\u00e9chargement. ConfigView.section.tracker.udpversion=Version du protocole UDP (1 ou 2) window.updateswt.title=Votre version de SWT est d\u00e9pass\u00e9e\u00a0! window.updateswt.text=Votre version de SWT est d\u00e9pass\u00e9e\u00a0!\nSWT est le coeur de l'interface graphique d'Azureus. Appuyez sur OK pour commencer la mise \u00e0 jour de SWT. window.updateswt.status=\u00c9tat window.updateswt.failed=Mise \u00e0 jour impossible. Appuyez sur OK pour recommencer la proc\u00e9dure. window.updateswt.status.downloading.updater=T\u00e9l\u00e9chargement du Module de mise \u00e0 jour window.updateswt.status.finding=Recherche de la version la plus r\u00e9cente window.updateswt.status.downloading=T\u00e9l\u00e9chargement de la derni\u00e8re version de SWT window.updateswt.status.done=Red\u00e9marrage window.updateswt.ok=Ok window.updateswt.cancel=Annuler swt.updater.downloader.downloading=T\u00e9l\u00e9chargement de SWT \u00e0 partir de swt.updater.urlsgetter.downloading=Liste des sites mirroirs en provenance de swt.updater.urlsgetter.platform=SWT pour: window.updateswt.ignore=Ignor\u00e9 ConfigView.section.style.useFancyTabs=Utiliser le nouveau type d'onglet splash.initializeGM=Initialisation du Global Torrent Manager splash.loadingTorrents=Chargement des Torrents MyTorrentsView.menu.thisColumn.sort=C&lasser Scrape.status.ok='Scrape' Ok. Scrape.status.error=Erreurs 'Scrape': Scrape.status.error.badURL=L'URL d'annonce ne respecte pas les normes du 'scrape'. Scrape.status.error.nohash=Le 'Hash' est manquant. Scrape.status.error.invalid=R\u00e9ponse invalide. Scrape.status.nextScrapeAt='scrape' suivante \u00e0 %1 Scrape.status.scraping=En 'Scrape'.. Scrape.status.initializing=En attente ConfigView.label.minSpeedForActiveSeeding=Exclure les torrents compl\u00e9t\u00e9s de la file active si la vitesse est moins de ConfigView.section.stats.exportpeers=Exporter les details des peers MainWindow.menu.view.irc.moved=Irc est d\u00e9sormais disponible en tant que plugin, voir http://azureus.sourceforge.net/plugin_list.php. Une fois install\u00e9, utiliser le menu Affichage->plugins->IRC pour y acc\u00e8der. MyTrackerView.webui.contextmenu.copyurl=Copier l'URL du torrent dans le presse-papiers ConfigView.section.file.torrent.ignorefiles=Fichiers \u00e0 ignorer en cr\u00e9ant des torrents\ne.g. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignore le fichier ConfigView.section.style.useUnitsRateBits=Utiliser des bits au lieu des octets pour les valeurs des taux (Kio/s->Kibits/s, etc.) ConfigView.section.interface.resetassoc=R\u00e9initialiser les associations de fichiers de l'explorateur (.torrent) ConfigView.section.interface.resetassocbutton=R\u00e9initialiser ConfigView.section.interface.checkassoc=V\u00e9rifier les associations au d\u00e9marrage dialog.associations.title=V\u00e9rification de l'association Button.yes=Oui Button.no=Non ConfigView.label.seeding.autoStart0Peers=D\u00e9marrer automatiquement tous les torrents termin\u00e9s qui ont 0 peer. ConfigView.label.seeding.autoStart0Peers.tooltip=Activer pour que le tracker liste toujours les torrents avec 0 peer. dialog.associations.prompt=Vuze n'est pas l'application BitTorrent par d\u00e9faut.\nVoulez-vous associer les fichiers .torrent \u00e0 Vuze u00a0? dialog.associations.askagain=V\u00e9rifier au d\u00e9marrage ConfigView.section.plugins.update=Mise \u00e0 jour Plugin Plugin.pluginupdate.enablecheck=Activer la v\u00e9rification de mise \u00e0 jour des plugins plugins.basicview.status=Statut: plugins.basicview.activity=Activit\u00e9: plugins.basicview.progress=Progression: ConfigView.label.maxdownloadspeed=ko/s vitesse globale maximale de t\u00e9l\u00e9chargement [0\u00a0: illimit\u00e9e] splash.loadingTorrent=Chargement du Torrent splash.of=sur UpdateWindow.title=Mise \u00e0 jour de Vuze UpdateWindow.header=Les composants suivants ont besoin d'une mise \u00e0 jour UpdateWindow.columns.install=Installation UpdateWindow.columns.name=Nom UpdateWindow.columns.size=Taille UpdateWindow.cancel=Annuler UpdateWindow.quit=Quitter UpdateWindow.close=Fermer UpdateWindow.ok=Ok UpdateWindow.restart=Red\u00e9marrer UpdateWindow.status.downloading=T\u00e9l\u00e9charge UpdateWindow.status.done=Termin\u00e9 UpdateWindow.status.failed=Echou\u00e9 UpdateWindow.status.restartNeeded=Un red\u00e9marrage sera n\u00e9cessaire\u00a0! ConfigView.pluginlist.broken=Endommag\u00e9 ConfigView.pluginlist.whereToPut=Placer tout plugin utilisateur dans leur r\u00e9pertoire sp\u00e9cifique sous\u00a0: ConfigView.pluginlist.whereToPutOr=Pour un plugin partag\u00e9, utiliser: MainWindow.statusText.checking=V\u00e9rification des mises \u00e0 jour TableColumn.header.OnlyCDing4=EnSourceDepuis TableColumn.header.OnlyCDing4.info=Dur\u00e9e pendant laquelle le torrent n'a fait qu'\u00eatre en source. Ne prend pas en compte le temps de t\u00e9l\u00e9chargement. ConfigView.section.style.alternateTablePainting=Utiliser une m\u00e9thode alternative pour tracer les colonnes des tables graphiques (peut necessiter un red\u00e9marrage) UpdateWindow.status.restartMaybeNeeded=Un red\u00e9marrage sera peut-\u00eatre necessaire ConfigView.pluginlist.shared=partag\u00e9 PeersView.host=Nom d'h\u00f4te PeersView.host.info=Le nom d'h\u00f4te du peer, si disponible (peut affecter les performances) MainWindow.menu.help.whatsnew=Quoi de neuf ConfigView.label.checkonstart=V\u00e9rifier les mises \u00e0 jour au d\u00e9marrage ConfigView.label.periodiccheck=V\u00e9rifier les mises \u00e0 jour p\u00e9riodiquement ConfigView.label.opendialog=Ouvrir automatiquement l'assistant de mise \u00e0 jour quand une mise \u00e0 jour est disponible MainWindow.updateavail=(Mise \u00e0 jour disponible) MainWindow.status.latestversionunchecked=V\u00e9rification de mise \u00e0 jour d\u00e9sactiv\u00e9e GeneralView.label.updatein.stopped=Arr\u00eat\u00e9 StartStopRules.menu.viewDebug=Voir les informations de d\u00e9boggage ConfigView.section.style.doNotUseGB=Ne pas utiliser l'unit\u00e9 GB ConfigView.section.style.doNotUseGB.tooltip=Si activ\u00e9, Vuze utilisera des MB m\u00eame pour des tailles sup\u00e9rieures \u00e0 1024MB MainWindow.menu.help.plugins=Plugins ConfigView.section.tracker.enablecategories=S\u00e9parer les torrents par cat\u00e9gorie health.explain.share=signifie que le torrent est soit h\u00e9berg\u00e9 soit publi\u00e9 ConfigView.section.tracker.createcert=Cr\u00e9er un certificat auto-sign\u00e9 ConfigView.section.tracker.createbutton=Cr\u00e9er security.certcreate.title=Cr\u00e9er un certificat auto-sign\u00e9 security.certcreate.intro=Vous permet de cr\u00e9er un certificat auto-sign\u00e9. security.certcreate.strength=Puissance security.certcreate.firstlastname=Pr\u00e9nom et nom security.certcreate.orgunit=Unit\u00e9 d'organisation security.certcreate.city=Ville ou Localit\u00e9 security.certcreate.state=Etat ou Province security.certcreate.country=Code Pays (2 lettres) security.certcreate.ok=Cr\u00e9er security.certcreate.cancel=Annuler security.certcreate.createok=Cr\u00e9ation du certificat r\u00e9alis\u00e9e avec succ\u00e8s. security.certcreate.createfail=La cr\u00e9ation du certificat a \u00e9chou\u00e9. ConfigView.section.plugins.webui=Interface Web Swing ConfigView.section.plugins.xml_http_if=Interface XML/HTTP webui.passwordenable=Activer le mot de passe webui.user=Nom d'utilisateur webui.password=Mot de passe webui.protocol=Protocole (*) webui.homepage=Page d'accueil (*) webui.rootdir=R\u00e9pertoire racine (*) webui.rootres=Ressource racine (*) webui.mode.info=Mode peut \u00eatre\n\t"full"\t= toutes op\u00e9rations possibles (d\u00e9faut)\n\t"voir"\t= voir seulement (mais peut mettre \u00e0 jour la fr\u00e9quence de rafra\u00eechissement) webui.access=Acc\u00e8s (*) webui.access.info=L'acc\u00e8s peut \u00eatre\n\t"local"\t= seule la machine locale peut se connecter\n\t"all"\t= acc\u00e8s pour tous (d\u00e9faut)\n\tIP\t= e.g. 192.168.0.2\t\t\tseulement une IP\n\tIP1-IP2\t= e.g. 192.168.0.1-192.168.0.255\tintervalle inclusif d'IPs. GeneralView.label.maxdownloadspeed=Vit. T\u00e9l. Max. Security.keystore.corrupt=Le lancement de la cl\u00e9 '%1' a \u00e9chou\u00e9, veuillez l'effacer et recr\u00e9er/r\u00e9importer les certificats. Security.keystore.empty=La cl\u00e9 est vide. Veuillez cr\u00e9er un certificat auto-sign\u00e9 (voir Options > S\u00e9curit\u00e9) ou importer un certificat existant dans '%1'. webui.restart.info=Des changements sur les param\u00e8tres marqu\u00e9s d'une (*) n\u00e9cessite un red\u00e9marrage GeneralView.label.maxdownloadspeed.tooltip=Vitesse maximale de t\u00e9l\u00e9chargement [0\u00a0: illimit\u00e9e] upnp.enable=Activer l'UPnP upnp.info=Universal Plug and Play (UPnP) permet le mapping automatique de ports sur des routeurs supportant l'UPnP. upnp.mapping.dataport=Port entrant de donn\u00e9es des clients upnp.mapping.tcptrackerport=Port Tracker TCP upnp.mapping.udptrackerport=Port Tracker UDP upnp.alert.differenthost=UPnP: Mapping '%1' a \u00e9t\u00e9 r\u00e9serv\u00e9 par '%2' - veuillez s\u00e9lectionner un port diff\u00e9rent upnp.alert.mappingok=UPnP: Mapping '%1' \u00e9tabli upnp.alert.mappingfailed=UPnP: Mapping '%1' a \u00e9chou\u00e9 upnp.alertsuccess=Rapporter les mappings r\u00e9ussis upnp.alert.lostdevice=UPnP: A perdu la connexion '%1' sur l'appareil UPnP '%2' upnp.grabports=Mapper les ports m\u00eame s'ils appartiennent \u00e0 un autre ordinateur. upnp.refresh.label=Rafra\u00eechir les mappings upnp.refresh.button=Rafra\u00eechir upnp.alert.mappinggrabbed=UPnP: Mapping '%1' \u00e9tabli - \u00e0 partir de '%2' upnp.mapping.tcpssltrackerport=Port Tracker TCP SSL upnp.alertothermappings=Rapporter les ports utilis\u00e9s par d'autres ordinateurs upnp.alertdeviceproblems=Rapporter les probl\u00e8mes avec l'UPnP ConfigView.pluginlist.coreplugins=Les plugins int\u00e9gr\u00e9s suivants sont charg\u00e9s\u00a0: Peers.column.DLedFromOthers=Des autres Peers.column.DLedFromOthers.info=Quantit\u00e9 de donn\u00e9es t\u00e9l\u00e9charg\u00e9es des autres quand ils \u00e9taient connect\u00e9s \u00e0 vous. Peers.column.UpDownRatio=Envoy\u00e9:T\u00e9l\u00e9charg\u00e9 Peers.column.UpDownRatio.info=Taux "Envoy\u00e9:T\u00e9l\u00e9charg\u00e9" du client Peers.column.UpRatio=Ratio de l'envoi Peers.column.UpRatio.info=Taux "Envoy\u00e9 par vous:Envoy\u00e9 par les autres" du client upnp.releasemappings=Lib\u00e9rer les mappings \u00e0 la fermeture webui.upnpenable=Activer l'UPnP pour ce port (*) ConfigView.section.file.friendly.hashchecking=V\u00e9rification du hash moins intensive ConfigView.section.file.friendly.hashchecking.tooltip=Un mode de v\u00e9rification du hash des pi\u00e8ces plus lent mais beaucoup moins consommateur de m\u00e9moire et de processeur. ConfigView.section.tracker.seedretention=Nb max de sources retenues par torrent [0\u00a0: illimit\u00e9] ConfigView.section.tracker.seedretention.info=Note\u00a0: Les statistiques d'envoi seront perdues pour les sources non retenues. ConfigView.section.tracker.port=Activer le tracker sur le port HTTP ConfigView.section.tracker.sslport=Activer le tracker sur le port HTTPS ConfigView.section.tracker.publicenable.info=Ceci permet \u00e0 d'autres d'utiliser votre tracker\nsans avoir \u00e0 les h\u00e9berger ou les publier. Button.clear=Effacer MainWindow.IPs.tooltip=Nombre de filtres IP - Nombre d'IP bloqu\u00e9es\nDouble-cliquer pour afficher la liste des connexions refus\u00e9es . ConfigView.section.ipfilter.list.banned=a \u00e9t\u00e9 banni pour avoir envoy\u00e9 des mauvaises donn\u00e9es ConfigView.section.ipfilter.list.baddata=a envoy\u00e9 de mauvaises donn\u00e9es: nombre de fois = Button.reset=R\u00e9initialiser ConfigView.section.ipfilter.bannedinfo=IPs qui ont envoy\u00e9s de mauvaises donn\u00e9es - bannies si la limite est d\u00e9pass\u00e9e ConfigView.section.ipfilter.blockedinfo=IPs bloqu\u00e9es par les filtres IP download.removerules.name=R\u00e8gles de suppression download.removerules.unauthorised.info=Les torrents non autoris\u00e9s sont ceux qui contiennent dans la \u00ab\u00a0r\u00e9ponse d'erreur\u00a0\u00bb\u00a0: \u00ab\u00a0not authoris(z)ed\u00a0\u00bb or \u00ab\u00a0unauthoris(z)ed\u00a0\u00bb. download.removerules.unauthorised=Supprimer automatiquement les torrents non autoris\u00e9s download.removerules.unauthorised.seedingonly=\tSeulement si en source download.removerules.removed.ok=La suppression automatique du torrent '%1' a \u00e9t\u00e9 effectu\u00e9e avec succ\u00e8s. Ceci est d\u00fb aux r\u00e8gles de suppression. download.removerules.updatetorrents=Supprimer les torrents de mise \u00e0 jour de Vuze si n\u00e9cessaire pour le r\u00e9seau ConfigView.label.defaultstarttorrentsstopped=Par d\u00e9faut, ajout des nouveaux torrents \u00e0 l'arr\u00eat ConfigView.section.server.enableudp=Activer le protocol UDP pour le client tracker. Utilise le m\u00eame port que TCP. upnp.mapping.dataportudp=Port UDP du client tracker ConfigView.section.file.decoder.showlax=Montrer les encodages moins probables ConfigView.section.file.decoder.showall=Consid\u00e9rer tous les encodages possibles MainWindow.status.updowndetails.tooltip=Details sur les vitesses de t\u00e9l\u00e9chargement/envoi - changer par clic droit TrackerClient.announce.warningmessage=Tracker de '%1' a retourn\u00e9 l'avertissement '%2' ConfigView.section.tracker.natcheckenable=V\u00e9rifier les possibilit\u00e9s de connexion sur le "port entrant des donn\u00e9es" et rapporter les erreurs aux clients ConfigView.section.tracker.publishenabledetails=Publier le fichier torrent et ses d\u00e9tails ConfigView.section.tracker.publishenablepeerdetails=Publier les d\u00e9tails des clients MyTrackerView.badnat=NAT mal configur\u00e9 MyTrackerView.badnat.info=Sources/Clients ayant echou\u00e9s au test NAT, si activ\u00e9 ConfigView.section.tracker.natchecktimeout=Expiration de la v\u00e9rification (secs) ConfigView.section.file.perf.cache.enable=Activer le cache disque ConfigView.section.file.perf.cache.size=Taille du cache en %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=&Transferts MainWindow.menu.transfers.startalltransfers=&D\u00e9marrer tout MainWindow.menu.transfers.stopalltransfers=&Arr\u00eater tout MainWindow.menu.transfers.resumetransfers=&Reprendre ConfigView.label.experimental.osx.kernel.panic.fix=Fix exp\u00e9rimental des kernel panics sur les syst\u00e8mes OSX dual processeurs [n\u00e9cessite un red\u00e9marrage]. SystemTray.menu.pausetransfers=Pause (tous transferts) SystemTray.menu.resumetransfers=Reprendre (tous transferts) ConfigView.section.file.truncate.too.large=Tronquer les fichiers existant trop gros ConfigView.section.file.perf.cache.trace=Conserver les op\u00e9rations de cache pour \u00e9ventuel diagnostic ConfigView.section.interface.enabletray=Activer le system tray PeerManager.status.error=Erreur Stats.title.full=Statistiques TransferStatsView.title.full=Transferts CacheView.general.size=Taille totale CacheView.general.inUse=Utilisation CacheView.general.title=Infos Cache CacheView.reads.title=Lectures E/S CacheView.reads.fromFile=Depuis Fichier CacheView.reads.fromCache=Depuis Cache CacheView.writes.title=Ecritures E/S CacheView.writes.toCache=Vers Cache CacheView.writes.toFile=Vers Fichier CacheView.writes.hits=d'\u00e9conomis\u00e9 CacheView.speeds.title=Taux de donn\u00e9es CacheView.speeds.reads=Lectures CacheView.speeds.writes=Ecritures CacheView.speeds.fromCache=Depuis/Vers Cache CacheView.speeds.fromFile=Depuis/Vers Fichier CacheView.reads.amount=Quantit\u00e9 CacheView.reads.avgsize=Taille Moy. openUrl.referrer=URL de la page r\u00e9f\u00e9r\u00e9e : openUrl.referrer.info=Uniquement pour les sites qui l'exige ConfigView.label.maxuploadspeedseeding=Taux diff\u00e9rent quand seulement en source ConfigView.label.transfer.ignorepeerports=Ignorer les clients utilisant ces ports (s\u00e9par\u00e9s par ';') ConfigView.section.proxy.enable_socks.peer=Activer le proxy pour les communications entre clients (pour les connexions sortantes uniquement). ConfigView.section.proxy.peer.informtracker=Informer le tracker de la limitation. ConfigView.section.proxy.socks.version=Version SOCKS PiecesView.legend.written=Ecrites PiecesView.legend.requested=D\u00e9mand\u00e9es PiecesView.legend.downloaded=T\u00e9l\u00e9charg\u00e9e, \u00e9criture en attente PiecesView.legend.incache=Donn\u00e9es dans le cache PiecesView.typeItem.0=Lent PiecesView.typeItem.1=Rapide Security.jar.tools_not_found=La signature du JAR a \u00e9chou\u00e9e - 'tools.jar' introuvable dans %1. Se reporter \u00e0 Options/s\u00e9curit\u00e9 pour plus d'information. Security.jar.signfail=La signature du JAR a \u00e9chou\u00e9e - %1 ConfigView.section.security.toolsinfo=Les fichiers JAR sign\u00e9s sont utilis\u00e9s par certains plugins, par exemple l'interface Web Swing (si configur\u00e9e pour).\nPour signer des fichiers JAR, il faut avoir acc\u00e8s \u00e0 'tools.jar' qui d\u00e9pend de l'environnement de d\u00e9veloppement Sun JDK (et pas du simple JRE).\nSi seul le JRE est install\u00e9, veuillez installer le JDK.\nVuze doit pouvoir trouver le fichier pour vous. Sinon, vous pouvez pr\u00e9ciser son chemin d'acc\u00e8s ici. ConfigView.section.security.toolsdir=R\u00e9pertoire contenant 'tools.jar' ConfigView.section.security.choosetoolssavedir=Selectionner le r\u00e9pertoire contenant 'tools.jar' ConfigView.section.proxy.peer.same=Utiliser les m\u00eame r\u00e9glages de proxy pour les communications avec le tracker et les clients. ConfigView.section.connection.network.max.simultaneous.connect.attempts=Nombre maximum de connexions sortantes simultan\u00e9es ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Nombre maximum de connexions sortantes qu'Vuze tente d'\u00e9tablir \u00e0 un instant donn\u00e9.\nNOTE: WindowsXP Service Pack 2 (SP2) impose une limite au syst\u00e8me de 10 essai simultan\u00e9s.\nValeur par d\u00e9faut: 5. ConfigView.section.file.perf.cache.size.explain=Le cache est utilis\u00e9 pour r\u00e9duire les lectures depuis / les \u00e9critures vers le disque. A moins d'utiliser l'option java '-XX:MaxDirectMemerySize' pour sp\u00e9cifier la m\u00e9moire disponible pour le cache et les E/S r\u00e9seau, cette valeur doit rester %1 inf\u00e9rieure \u00e0 la taille maximum de m\u00e9moire virtuelle. La taille maximale actuelle de la m\u00e9moire virtuelle est %2. Pour des instructions sur comment modifier ce r\u00e9glage, voir MemoryUsage sur le wiki (%3). Des r\u00e9glages non raisonnables donneront des erreurs d'utilisation m\u00e9moire ('OutOfMemory' errors). MyTorrentsView.menu.setSpeed.unlimit=Pas de limite MyTorrentsView.menu.setSpeed.unlimited=Illimit\u00e9e MyTorrentsView.menu.setSpeed.disable=D\u00e9sactiver l'envoi MyTorrentsView.menu.setSpeed.disabled=D\u00e9sactiv\u00e9 MyTorrentsView.menu.setSpeed.in=en MyTorrentsView.menu.setSpeed.slots=cr\u00e9neaux de GeneralView.label.maxuploadspeed=Vit. Env. Max. GeneralView.label.maxuploadspeed.tooltip=vitesse maximale d'envoi [0 : illimit\u00e9e] MyTorrents.items.UpSpeedLimit.disabled=Pas d'envoi MyTorrents.items.UpSpeedLimit.unlimited=Illimit\u00e9 TableColumn.header.maxupspeed=Vit. Envoi Max. TableColumn.header.maxupspeed.info=Vit. Envoi Max. par torrent ConfigView.section.file.perf.cache.enable.write=Mettre le t\u00e9l\u00e9chargement en cache pour r\u00e9duire les \u00e9critures disque et les lectures disque pour la v\u00e9rification de pi\u00e8ce. ConfigView.section.file.perf.cache.enable.read=Ex\u00e9cuter des lectures en avance pour r\u00e9duire les lectures disque quand en source. ConfigView.section.tracker.separatepeerids=Utiliser des identit\u00e9s clients diff\u00e9rentes pour les communications de donn\u00e9es et vers le tracker. ConfigView.section.tracker.separatepeerids.info=Augmente l'anonymat si en t\u00e9l\u00e9chargement/source anonyme\nen utilisant une connexion vers le tracker non-anonyme. ConfigView.section.interface.wavlocation=Chemin d'acc\u00e8s du fichier .wav ConfigView.section.interface.wavlocation.info=S\u00e9lectionner un fichier .wav ou laisser vide pour utiliser le son par d\u00e9faut. ConfigView.section.tracker.server=Serveur ConfigView.section.tracker.client.connecttimeout=Timeout de connexion (secs) ConfigView.section.tracker.client.readtimeout=Timeout de lecture (secs) MainWindow.menu.tools=&Outils FilesView.path=Chemin d'acc\u00e8s FilesView.fullpath=Montrer le chemin d'acc\u00e8s complet FilesView.remaining=Pi\u00e8ces restantes TableColumn.header.trackername=Nom du tracker TableColumn.header.trackername.info=Nom du tracker bas\u00e9 sur l'URL d'annonce ConfigView.group.override=Options prioritaires ConfigView.section.file.perf.cache.notsmallerthan=Ne pas mettre en cache les fichiers inf\u00e9rieurs \u00e0 (en %1) PeersView.menu.blockupload=Bloquer l'envoi PeersView.menu.kickandban=Exclure et bannir PeersView.menu.kickandban.reason=Client banni manuellement PeersView.state=Etat PeersView.state.info=Etat de la connexion PeersView.state.pending=En cours PeersView.state.connecting=Se connecte PeersView.state.handshake=Attends le handshake PeersView.state.established=Etabli ConfigView.section.tracker.processinglimits=Limites de traitement ConfigView.section.tracker.maxgettime=Temps maximal pour traiter un GET (en s) [0\u00a0: illimit\u00e9] ConfigView.section.tracker.maxgettime.info=Utilis\u00e9s pour les annonces et les scrapes ConfigView.section.tracker.maxposttimemultiplier=Multiplicateur du temps GET pour traiter les POST [0\u00a0: illimit\u00e9] ConfigView.section.tracker.maxposttimemultiplier.info=Utilis\u00e9 pour des formulaires et des envois ConfigView.section.tracker.maxthreads=Requ\u00eates simultan\u00e9es maximales DownloadManager.error.operationcancancelled=Op\u00e9ration annul\u00e9e Torrent.create.progress.cancelled=Op\u00e9ration annul\u00e9e sharing.progress.cancel=Annuler wizard.maketorrents.autoopen=Ouvrir le torrent en source \u00e0 la fin ConfigView.section.sharing.rescanenable=Activer un scan p\u00e9riodique des partages (pour inclure des changements) ConfigView.section.sharing.rescanperiod=P\u00e9riode de scan (s) ConfigView.section.connection.advanced=Configuration r\u00e9seau avanc\u00e9e ConfigView.section.connection.advanced.mtu=Maximum Transmission Unit (MTU) de la ligne ConfigView.section.connection.advanced.mtu.tooltip=Taille maximum d'un paquet pouvant \u00eatre transmis en une seule trame sur le r\u00e9seau.\nVuze utilise MTU-40 (MSS) pour optimiser la charge en envoi.\nValeurs recommand\u00e9es:\n 576 - connexions 56k\n1492 - connexions haut-d\u00e9bit PPPoE\n1500 - connexions haut-d\u00e9bit Ethernet, DSL et Cable. ConfigView.section.connection.advanced.SO_RCVBUF=Taille de la socket SO_RCVBUF [0: utilise la valeur par d\u00e9faut du syst\u00e8me d'exploitation] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=R\u00e8gle la taille du socket standard SO_RCVBUF (en octets), soit l'\u00e9chelle et la taille de la fen\u00eatre de reception TCP.\nVuze laisse ce champ vide par d\u00e9faut, donc les valeurs par d\u00e9fault du syst\u00e8me d'exploitation sont utilis\u00e9es.\nNOTE: Linux double la valeur indiqu\u00e9e. ConfigView.section.connection.advanced.SO_SNDBUF=Taille de la socket SO_SNDBUF [0: utilise la valeur par d\u00e9faut du syst\u00e8me d'exploitation] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=R\u00e8gle la taille du socket standard SO_SNDBUF (en octets), soit la taille de la fen\u00eatre d'envoi TCP.\nVuze laisse ce champ vide par d\u00e9faut, donc les valeurs par d\u00e9fault du syst\u00e8me d'exploitation sont utilis\u00e9es.\nNOTE: Linux double la valeur indiqu\u00e9e. ConfigView.section.interface.confirm_torrent_removal=Afficher une fen\u00eatre de confirmation pour supprimer un torrent ConfigView.section.interface.confirm_torrent_removal.tooltip=Demande confirmation lors de la suppression d'un torrent de la vue Mes Torrents. MyTorrentsView.confirm_torrent_removal=Confirmation de la suppression\u00a0?\n TableColumn.header.seed_to_peer_ratio=TauxSources/Clients TableColumn.header.seed_to_peer_ratio.info=Taux global sources/clients du groupe PeersView.connected_time=Temps connect\u00e9 PeersView.connected_time.info=Temps total de connexion avec le client ConfigView.section.interface.display.add_torrents_silently=Ajouter les torrents silencieusement ConfigView.section.interface.display.add_torrents_silently.tooltip=Ajouter les torrents sans activer la fen\u00eatre principale d'Azureus. TableColumn.header.maxdownspeed=Vit. T\u00e9l. max TableColumn.header.maxdownspeed.info=Vitesse maximale de t\u00e9l\u00e9chargement par torrent PeersGraphicView.title=Essaim ConfigView.section.tracker.passwordwebhttpsonly=Ne permet que l'acc\u00e8s par HTTPS TableColumn.header.torrentpath=Chemin d'acc\u00e8s du torrent TableColumn.header.torrentpath.info=Chemin d'acc\u00e8s du torrent sur le disque ConfigView.section.sharing.torrentcomment=Commentaire pour les torrents g\u00e9n\u00e9r\u00e9s ConfigView.label.copyanddeleteratherthanmove=Copier et ensuite supprimer les donn\u00e9es (au lieu de le faire en une op\u00e9ration) - peut pr\u00e9venir la perte de donn\u00e9es avec certains syst\u00e8mes de fichiers ConfigView.label.openstatsonstart=Ouvrir la vue Statistiques au d\u00e9marrage swt.install.window.title=Installeur de plugins pour Vuze swt.install.window.ok=Installer swt.install.window.header=Les composants suivants ont \u00e9t\u00e9 s\u00e9lectionn\u00e9s pour \u00eatre install\u00e9s : swt.uninstall.window.title=D\u00e9sintalleur de plugins pour Vuze swt.uninstall.window.ok=Supprimer swt.uninstall.window.header=Les compossants suivants ont \u00e9t\u00e9 s\u00e9lectionn\u00e9s pour \u00eatre supprim\u00e9s : installPluginsWizard.title=Installation de plugins installPluginsWizard.mode.title=Veuillez choisir une m\u00e9thode d'installation installPluginsWizard.mode.list=Par liste, depuis sourceforge.net installPluginsWizard.list.title=Liste des plugins installables installPluginsWizard.list.loading=Veuillez patientez pendant le chargement de la liste des plugins. installPluginsWizard.list.loaded=Veuillez choisir les plugins \u00e0 installer. installPluginsWizard.list.name=Nom installPluginsWizard.list.description=Description du plugin installPluginsWizard.finish.title=Installation en cours installPluginsWizard.finish.explanation=Les plugins s\u00e9lectionn\u00e9s seront install\u00e9s gr\u00e2ce \u00e0 l'Assistant de mise \u00e0 jour.\n\nSoyez patients, la proc\u00e9dure peut prendre quelques minutes.\n\nPour des informations sur la progression, veuillez double-cliquer \u00e0 gauche dans la barre d'\u00e9tat. installPluginsWizard.details.loading=Chargement des d\u00e9tails, veuillez patienter... installPluginsWizard.mode.file=Par fichier installPluginsWizard.installMode.title=Veuillez choisir le type d'installation installPluginsWizard.installMode.user=Installe le(s) plugin(s) pour vous uniquement installPluginsWizard.installMode.shared=Installe le(s) plugin(s) pour tous les utilisateurs (partag\u00e9) installPluginsWizard.file.title=Veuillez choisir le plugin \u00e0 installer installPluginsWizard.file.file=Fichier : installPluginsWizard.file.invalidfile=Le fichier n'est pas un plugin valide pour Azureus. installPluginsWizard.file.browse=Parcourir... uninstallPluginsWizard.title=D\u00e9sinstallation de plugins uninstallPluginsWizard.list.title=Liste des plugins install\u00e9s uninstallPluginsWizard.list.loaded=Veuillez choisir les plugins \u00e0 d\u00e9sintaller. installPluginsWizard.list.nullversion=pas de version uninstallPluginsWizard.finish.title=D\u00e9sintallation en cours uninstallPluginsWizard.finish.explanation=Les plugins s\u00e9lectionn\u00e9s seront supprim\u00e9s gr\u00e2ce \u00e0 l'assistant de mise \u00e0 jour. MainWindow.menu.plugins.installPlugins=Assistant d'installation MainWindow.menu.plugins.uninstallPlugins=Assistant de d\u00e9sinstallation ConfigView.section.ipfilter.totalIPs=%1 IPs bloqu\u00e9es au total, soit %2 d'internet. update.instance.install=V\u00e9rification des installations update.instance.uninstall=V\u00e9rification des d\u00e9sinstallations update.instance.update=V\u00e9rification des mises \u00e0 jour MainWindow.status.update.tooltip=Double-cliquer pour voir la progression updater.progress.window.title=Travaux d'installation en cours updater.progress.window.info=Appuyer sur 'Abandonner' pour mettre fin aux t\u00e2ches en cours. Button.abort=Annuler ConfigView.section.ipfilter.enablebanning=Bloquer les clients qui envoient constamment de mauvaises donn\u00e9es Network.alert.acceptfail=Trop d'\u00e9checs successifs sur le port %1, %2 - essais stopp\u00e9s.\n Veuillez v\u00e9rifier les r\u00e9glages du pare-feu pour que ce port soit capable de recevoir des connexions. MyShares.column.category=Cat\u00e9gorie UpdateWindow.restartLater=Red\u00e9marrer plus tard MainWindow.menu.file.restart=Red\u00e9marrer MainWindow.dialog.restartconfirmation.title=Red\u00e9marrer Vuze u00a0? MainWindow.dialog.restartconfirmation.text=Voulez-vous vraiment red\u00e9marrer Vuze u00a0? deletetorrent.message1=Vous vous appr\u00eatez \u00e0 supprimer le TORRENT pour\u00a0:\n deletetorrent.message2=\nEtes-vous s\u00fbrs de vouloir continuer\u00a0? ConfigView.label.prioritizemostcompletedfiles=Donner priorit\u00e9 aux fichiers les plus avanc\u00e9s splash.plugin.init=Initialisation du Plugin: ConfigView.section.style.osx_small_fonts=Utiliser une petite police [red\u00e9marrage n\u00e9cessaire] ConfigView.section.tracker.tcpnonblocking=Utiliser des E/S non bloquantes pour le tracker TCP. Cette option n\u00e9cessite de faire tourner le racker sur un autre port. Exp\u00e9rimental\u00a0! ConfigView.section.tracker.nonblocking=Options non bloquantes ConfigView.section.tracker.nonblockingconcmax=Nombre max de connexions simultan\u00e9es [0\u00a0: illimit\u00e9es] MyTorrentsView.menu.exportmenu=Exporter MyTorrentsView.menu.exporttorrent=Exporter le torrent... ConfigView.section.tracker.client.scrapeinfo=D\u00e9sactiver le scrape emp\u00eache les r\u00e8gles de classement de torrents de fonctionner car elles se fondent sur les informations de scrape que renvoient les trackers. ConfigView.section.tracker.client.scrapeenable=Activer le scrape ConfigView.section.tracker.client.scrapestoppedenable=Utiliser le scrape sur les torrents non actifs Scrape.status.disabled=Scrape d\u00e9sactiv\u00e9 MyTorrentsView.menu.explore=Ouvrir le dossier MyTorrentsView.menu.explore._mac=Montrer dans le Finder MyTorrentsView.menu.explore._windows=Montrer dans l'exploreur wizard.maketorrents.autohost=H\u00e9berger le torrent dans le tracker int\u00e9gr\u00e9 ConfigView.label.overrideip=Forcer l'IP envoy\u00e9e au tracker (NAT) ConfigView.label.overrideip.tooltip=Informe le tracker d'une adresse IP diff\u00e9rente de celle depuis laquelle les paquets sortants arrivent. Laisser vide pour ne pas utiliser cette option. ConfigView.section.connection.group.networks=R\u00e9seaux ConfigView.section.connection.group.networks.info=S\u00e9lectionner les r\u00e9seaux permis par d\u00e9faut pour les transmissions de donn\u00e9es client-client ConfigView.section.connection.networks.prompt=Inviter \u00e0 s\u00e9lectionner quand un t\u00e9l\u00e9chargement avec tracker anonyme est ajout\u00e9 ConfigView.section.connection.networks.Public=R\u00e9seau IP public (pas anonyme) ConfigView.section.connection.networks.I2P=R\u00e9seau I2P ConfigView.section.connection.networks.Tor=R\u00e9seau Onion Router (Tor) TableColumn.header.networks=R\u00e9seaux TableColumn.header.networks.info=R\u00e9seaux permis pour les transmissions de donn\u00e9es client-client Scrape.status.networkdisabled=R\u00e9seau non activ\u00e9 ConfigView.section.tracker.server.group.networks=R\u00e9seaux ConfigView.section.tracker.server.group.networks.info=S\u00e9lectionner les r\u00e9seaux desquels le tracker accepte les clients window.networkselection.title=S\u00e9lection r\u00e9seau window.networkselection.info=Le(s) tracker(s) du torrent affich\u00e9 ci-dessous supporte les r\u00e9seaux suivants.\nS\u00e9lectionner ceux \u00e0 utiliser pour les communications avec le tracker et les clients.\nS'il s'agit d'un tracker anonyme supportant les clients publics, activer \u00e0 la fois les r\u00e9seaux anonyme et public.\nActiver le r\u00e9seau public a pour cons\u00e9quence \u00e9vidente de supprimer l'anonymat. plugins.basicview.clear=Vider ConfigView.section.connection.group.peersources=Origines des clients ConfigView.section.connection.group.peersources.info=S\u00e9lectionner les origines permises par d\u00e9faut pour les connexions clients ConfigView.section.connection.peersource.Tracker=D'un tracker ConfigView.section.connection.peersource.DHT=Tracking d\u00e9centralis\u00e9 ConfigView.section.connection.peersource.PeerExchange=Fourni par un autre client ConfigView.section.connection.peersource.Plugin=Ajout\u00e9 par un plugin ConfigView.section.connection.peersource.Incoming=Connexion entrante PeersView.source=Origine PeersView.source.info=L'origine de ce client TableColumn.header.peersources=Origines des clients TableColumn.header.peersources.info=Origines des clients permises pour l'\u00e9tablissement de connexions wizard.tracker.dht=D\u00e9centralis\u00e9 (clients Vuze uniquement) MyTorrentsView.menu.advancedmenu=Avanc\u00e9 MyTorrentsView.menu.networks=R\u00e9seaux MyTorrentsView.menu.peersource=Origines de clients ConfigView.section.sharing.permitdht=Permettre le tracking d\u00e9centralis\u00e9 si le tracker est injoignable ConfigView.section.sharing.protocol=Protocole pour les ressources partag\u00e9es (configuration du tracker n\u00e9cessaire) PeersView.Messaging.info=Supporte une API de messaging avanc\u00e9e. ConfigView.label.queue.newseedsmovetop=D\u00e9placer les torrents r\u00e9cemments termin\u00e9s au d\u00e9but de la liste de sources ConfigView.label.seeding.firstPriority.ignore.info=Attention. Utiliser ces r\u00e8gles peut faire en sorte qu'un torrent s'arr\u00eate d\u00e8s qu'il est termin\u00e9. ConfigView.label.seeding.firstPriority.ignore=Ignorer les r\u00e8gles de premi\u00e8re priorit\u00e9 pour\u00a0: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents avec un taux sources/clients > ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents avec 0 clients ConfigView.section.tracker.sendjavaversionandos=Envoyer la version de java et le nom du syst\u00e8me d'exploitation MagnetPlugin.contextmenu.exporturi=Copier l'URI Magnet dans le presse-papier ConfigView.section.plugins.dht=BdD distribu\u00e9e dht.info=Ce plugin supporte le tracking d\u00e9centralis\u00e9, entre autres - le d\u00e9sactiver r\u00e9duit votre habilit\u00e9 \u00e0 t\u00e9l\u00e9charger dht.enabled=Activer la base de donn\u00e9es distribu\u00e9e dht.portdefault=Utiliser le port par d\u00e9faut dht.port=Port UDP pour la base de donn\u00e9es dht.execute.command=Commande de diagnostic dht.execute.info=Appuyer pour ex\u00e9cuter la commande dht.execute=Ex\u00e9cuter dht.logging=Activer le tra\u00e7age de l'activit\u00e9 ConfigView.section.plugins.dhttracker=Tracker distribu\u00e9 dhttracker.tracknormalwhenoffline=Ne tracker les torrents normaux que lorsque leur tracker est injoignable ConfigView.section.file.nativedelete._mac=Utiliser la corbeille en supprimant des fichiers ConfigView.section.file.nativedelete._windows=Placer les fichiers effac\u00e9s dans la corbeille ConfigView.section.logging.generatediagnostics=G\u00e9n\u00e9rer ConfigView.section.logging.generatediagnostics.info=G\u00e9n\u00e8re des informations de diagnostic et les copie dans le presse-papier et le fichier de log, si activ\u00e9 ConfigView.section.sharing.privatetorrent=Torrents priv\u00e9s - n'accepter que les clients du tracker MainWindow.menu.tools.nattest=Test &NAT / Firewall Button.apply=Appliquer Button.close=Fermer window.welcome.title=Bienvenue dans Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Notes dht.reseed.label=Normally reseeding of the Distributed Database is not necessary. However, if the number of contacts is low this can be used for re-integratation.\nLeave blank to bootrap off connected peers or enter IP and port to explicitly bootstrap from a known peer. dht.reseed.group=Reseeder dht.reseed.ip=Adresse IP dht.reseed=Reseeder dht.reseed.info=Reseeder la base de donnees DHTView.title.full=Base de donn\u00e9es distribu\u00e9e DHTView.title.fullcvs=Base de donn\u00e9es distribu\u00e9e CVS DHTView.general.title=G\u00e9n\u00e9ral DHTView.general.uptime=En service\u00a0: DHTView.general.users=Utilisateurs\u00a0: DHTView.general.nodes=Noeuds\u00a0: DHTView.general.leaves=Sorties\u00a0: DHTView.general.contacts=Contacts\u00a0: DHTView.general.replacements=Remplacements\u00a0: DHTView.general.live=En vie\u00a0: DHTView.general.unknown=Inconnu\u00a0: DHTView.general.dying=Expirant\u00a0: DHTView.transport.title=D\u00e9tails de transport DHTView.transport.packets=Paquets DHTView.transport.bytes=Octets DHTView.transport.received=Re\u00e7u DHTView.transport.sent=Envoy\u00e9 DHTView.transport.in=Entrant\u00a0: DHTView.transport.out=Sortant\u00a0: DHTView.operations.title=D\u00e9tails d'op\u00e9ration DHTView.operations.sent=Envoy\u00e9 DHTView.operations.failed=Echec DHTView.operations.received=Re\u00e7u DHTView.operations.findNode=Noeuds trouv\u00e9s DHTView.operations.findValue=Valeurs trouv\u00e9es DHTView.operations.store=Enregistrements DHTView.activity.title=Activit\u00e9 DHTView.activity.status=Etat DHTView.activity.status.true=En attente DHTView.activity.status.false=Lanc\u00e9 DHTView.activity.type.1=Get Interne DHTView.activity.type.2=Get Externe DHTView.activity.type.3=Put Interne DHTView.activity.type.4=Put Externe DHTView.activity.target=Cible DHTView.activity.details=D\u00e9tails DHTView.db.title=Base de donn\u00e9es DHTView.db.keys=Cl\u00e9s DHTView.db.values=Valeurs DHTView.db.divfreq=Div. Freq. DHTView.db.divsize=Div. Taille. MainWindow.dht.status.tooltip=Lorsque la base de donn\u00e9e est lanc\u00e9e, nombre estim\u00e9 d'utilisateurs connect\u00e9s (ie ayant lanc\u00e9 la base de donn\u00e9es \u00e9galement) MainWindow.dht.status.disabled=D\u00e9sactiv\u00e9 MainWindow.dht.status.failed=Echec MainWindow.dht.status.initializing=Initialisation MainWindow.dht.status.users=%1 Utilisateurs MainWindow.dht.status.unreachable=DHT derri\u00e8re un pare-feu MainWindow.dht.status.unreachabletooltip=Il semble qu'il y ait un probl\u00e8me avec le mapping du port de la base de donn\u00e9es distribu\u00e9e MyTorrentsView.menu.setUpSpeed=Vit. d'envoi MyTorrentsView.menu.setDownSpeed=Vit. de t\u00e9l. ConfigView.section.tracker.client.showwarnings=Afficher les avertissements des trackers dht.advanced=Activer les r\u00e9glages avanc\u00e9s dht.advanced.group=R\u00e9glages avanc\u00e9s dht.advanced.label=Ne pas modifier ces valeurs sans savoir pourquoi dht.override.ip=Forcer l'IP externe ConfigView.section.logging.loggerenable=Activer la journalisation ConfigView.section.ipfilter.blockbanning=Bannit un bloc de 256 adresses si le nombre d'IP bannies dans ce bloc est sup\u00e9rieur \u00e0 MyTrackerView.passive=Passif TableColumn.header.swarm_average_speed=Vit. moy. essaim TableColumn.header.swarm_average_speed.info=La vitesse moyenne des peers de l'essaim MyTrackerView.category=Cat\u00e9gorie MainWindow.menu.file.open.torrentfortracking=Fichier Torrent... (Tracking Uniquement) MyTrackerView.date_added=Ajout\u00e9 ConfigView.section.tracker.portbackup=Ports de r\u00e9serve (s\u00e9par\u00e9s par ';') ConfigView.label.playfilespeech=Parler \u00e0 la fin du t\u00e9l\u00e9chargement d'un fichier ConfigView.label.playfilespeech.info=Les services "parl\u00e9s" fonctionne le mieux en anglais ConfigView.label.playfilefinished=Jouer un son \u00e0 la fin du t\u00e9l\u00e9chargement d'un fichier ConfigView.label.backupconfigfiles=Sauvegarder les fichiers de configuration (pour r\u00e9cup\u00e9ration \u00e9ventuelle) ConfigView.section.tracker.client.scrapesingleonly=D\u00e9sactiver l'agr\u00e9gation de scrape par tracker (peut \u00e9viter les erreurs du type 'URL too long' (414)) dht.ipfilter.log=Logger les violations des filtres IP ConfigView.label.seeding.addForSeedingDLCopyCount=Consid\u00e9rer les torrents ajout\u00e9s "en source" comme ayant t\u00e9l\u00e9charg\u00e9 ce nombre de copies\u00a0: ActivityView.legend.limit=Taux limite ActivityView.legend.achieved=Taux atteint ActivityView.legend.peeraverage=Moyenne ActivityView.legend.swarmaverage=Moyenne Essaim ActivityView.legend.trimmed=Tronqu\u00e9 (pointill\u00e9) MyTorrentsView.menu.movemenu=D\u00e9placer les fichiers MyTorrentsView.menu.movedata=D\u00e9placer les donn\u00e9es... MyTorrentsView.menu.movetorrent=D\u00e9placer le torrent... MyTorrentsView.menu.movedata.dialog=Choisir la destination DHTView.operations.data=Donn\u00e9es DHTView.general.reachable=Accessible\u00a0: DHTView.general.rendezvous=Rendez-vous\u00a0: ConfigView.label.queue.maxactivetorrentswhenseeding=Max quand uniquement en source [0\u00a0:illimit\u00e9] Views.plugins.IRC.title=IRC - Support Technique en Ligne Formats.units.TiB=Tio Formats.units.TB=To Formats.units.GiB=Gio Formats.units.GB=Go Formats.units.MiB=Mio Formats.units.MB=Mo Formats.units.KiB=Kio Formats.units.kB=ko Formats.units.KB=ko Formats.units.B=o Formats.units.alot=Beaucoup\u00a0!!! ConfigView.section.ipfilter.persistblocking=Sauver les d\u00e9tails des IP bloqu\u00e9es entre sessions FilesView.menu.rename=Renommer ou changer de cible FilesView.rename.choose.path=Choisir un fichier nouveau ou existant FilesView.rename.confirm.delete.title=Confirmer la suppression FilesView.rename.confirm.delete.text=Confirmer la suppression du fichier original %1 ConfigView.higher.mode.available=\t ConfigView.section.mode.title=Niveau utilisateur ConfigView.section.mode.beginner=D\u00e9butant ConfigView.section.mode.beginner.wiki.definitions=Vocabulaire BitTorrent ConfigView.section.mode.intermediate=Interm\u00e9diaire ConfigView.section.mode.intermediate.wiki.host=H\u00e9berger des fichiers ConfigView.section.mode.intermediate.wiki.publish=Publier des fichiers ConfigView.section.mode.advanced=Avanc\u00e9 ConfigView.section.mode.advanced.wiki.main=Page Principale du Wiki ConfigView.section.mode.beginner.text=Tout ce dont vous avez besoin pour t\u00e9l\u00e9charger des torrents.\nUtilisez ce mode pour simplement g\u00e9rer vos torrents. ConfigView.section.mode.intermediate.text=Donne acc\u00e8s aux fonctions du tracker interne.\nUtilisez ce mode pour cr\u00e9er votre propre tracker et publier/h\u00e9berger vos fichiers. ConfigView.section.mode.advanced.text=Donne acc\u00e8s aux r\u00e9glages r\u00e9seau.\nUtilisez ce mode si vous savez ce que sont MTU ou I/O non bloquants... Files.column.storagetype=Type de stockage FileItem.storage.linear=Lin\u00e9aire MessageBoxWindow.rememberdecision=Se souvenir de ma d\u00e9cision ConfigView.section.interface.cleardecisions=Vider les "d\u00e9cisions retenues" ConfigView.section.interface.cleardecisionsbutton=Vider configureWizard.welcome.usermodes=Ce r\u00e9glage du niveau utilisateur d\u00e9termine le niveau des options accessibles dans Outils > Options. Il est recommand\u00e9 de choisir avec sagesse. FilesView.skip.confirm.delete.text=Tronquer le fichier \u00ab\u00a0%1\u00a0\u00bb pour sauver de l'espace\u00a0? FilesView.rename.failed.title=Echec du renommage/reciblage FilesView.rename.failed.text=L'op\u00e9ration a \u00e9chou\u00e9e, probablement \u00e0 cause d'une mauvaise destination diagnostics.log_found=Vuze ne s'est pas ferm\u00e9 correctement. Regarder dans %1 pour des fichiers log de diagnostic et envoyer \u00e0 l'\u00e9quipe de Vuze si c'est le r\u00e9sultat d'une erreur de l'application. Penser \u00e0 chercher 'Vuze Disappears' dans le Wiki (voir le menu Aide). ManagerItem.paused=En Pause Utils.link.visit=Merci de visiter ConfigView.section.connection.serverport.wiki=Bon choix de ports ConfigView.section.transfer.speeds.wiki=Bons r\u00e9glages de vitesse installPluginsWizard.installMode.info.text=Les plugins ne sont pas n\u00e9cessaires pour qu'Vuze fonctionne correctement, ils apportent des fonctions suppl\u00e9mentaires, pour le plaisir, l'automatisation ou le contr\u00f4le \u00e0 distance.\nVeuillez lire attentivement la description du plugin avant de d\u00e9cider de l'installer.\nLa plupart des plugins peuvent \u00eatre test\u00e9s sans risques mais ne surchargez pas inutilement votre configuration avec des plugins que vous n'utiliserez pas. Views.plugins.Distributed.DB.title=BdD distribu\u00e9e Views.plugins.Distributed.Tracker.title=Tracker distribu\u00e9 Views.plugins.Plugin.Update.title=Mise \u00e0 jour Plugins openUrl.url.info=Supporte http, https, magnet et l'infohash brut en hexa TableColumn.header.swarm_average_completion=Compl\u00e9tion moyenne des clients TableColumn.header.swarm_average_completion.info=Pourcentage moyen de compl\u00e9tion des clients connect\u00e9s GeneralView.label.swarm_average_completion=Compl\u00e9tion moyenne: GeneralView.label.swarm_average_completion.tooltip=Pourcentage moyen de compl\u00e9tion des clients connect\u00e9s MainWindow.nat.status.tooltip.unknown=Etat inconnu (TCP) [pare-feu/NAT] MainWindow.nat.status.tooltip.ok=Accessibilit\u00e9 OK (TCP) MainWindow.nat.status.probok=NAT OK\u00a0? MainWindow.nat.status.tooltip.probok=Accessibilit\u00e9 OK, mais pas de connections entrantes (TCP) r\u00e9centes MainWindow.nat.status.bad=Bloqu\u00e9 par pare-feu MainWindow.nat.status.tooltip.bad=Probl\u00e8me NAT (TCP) possible, voir le Wiki si persistant (double-cliquer) plugin.installer.recommended.plugin=Plugin recommand\u00e9 - voir le descriptif LoggerView.pause=Mettre en pause LoggerView.filter=Filtrer LoggerView.filter.uncheckAll=D\u00e9s\u00e9lectionner toutes les cat\u00e9gories LoggerView.filter.checkAll=S\u00e9lectionner toutes les cat\u00e9gories LoggerView.loggingDisabled=La journalisation n'est pas activ\u00e9e ConfigView.section.logging.filter=Filtres ConfigView.pluginlist.column.loadAtStartup=Se charge au d\u00e9marrage ConfigView.pluginlist.column.type.perUser=Per Utilisateur ConfigView.pluginlist.column.type.shared=Partag\u00e9 ConfigView.pluginlist.column.type.builtIn=Embarqu\u00e9 ConfigView.pluginlist.column.name=Nom ConfigView.pluginlist.column.directory=R\u00e9pertoire ConfigView.pluginlist.column.isOperational=Op\u00e9rationel\u00a0? PeersView.BlockView.Avail.Have=Les 2 ont PeersView.BlockView.Avail.NoHave=Le client a; Pas vous PeersView.BlockView.NoAvail.Have=Vous avez; pas le client PeersView.BlockView.NoAvail.NoHave=Les 2 n'ont pas PeersView.BlockView.Transfer=En transfert PeersView.BlockView.NextRequest=Prochaine requ\u00eate PeersView.BlockView.title=D\u00e9tails de pi\u00e8ces PeersView.BlockView.AvailCount=Disponibilit\u00e9 MyTorrentsView.dialog.NumberError.title=Nombre non valide ou non reconnu MyTorrentsView.dialog.NumberError.text=Le nombre entr\u00e9 n'est pas valide ou pas reconnu MyTorrentsView.menu.manual=&Manuellement... MyTorrentsView.dialog.setSpeed.title=R\u00e9gler la vitesse de %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Entrer un nombre %1 pour changer %2 vers: MyTorrentsView.dialog.setNumber.inKbps=en kbit/s OpenTorrentWindow.torrentLocation=fichier(s) torrent: OpenTorrentWindow.addFiles.URL=Ajouter &URL OpenTorrentWindow.addFiles.Folder=Ajouter &r\u00e9pertoire OpenTorrentWindow.addFiles.Clipboard=Ajouter du &presse-papier OpenTorrentWindow.changeDestination=Changer l'emplacement de sauvegarde OpenTorrentWindow.fileList=Fichiers dans les torrents: OpenTorrentWindow.torrentTable.name=Nom OpenTorrentWindow.torrentTable.saveLocation=Emplacement de sauvegarde OpenTorrentWindow.fileTable.fileName=Fichier OpenTorrentWindow.fileTable.size=Taille OpenTorrentWindow.fileTable.destinationName=Rep. OpenTorrentWindow.startMode.seeding=En source OpenTorrentWindow.fileList.changeDestination=Changer l'emplacement de sauvegarde OpenTorrentWindow.mb.badSize.title=Fichier incompatible OpenTorrentWindow.mb.badSize.text='%1' n'est pas '%2' et ne peut pas \u00eatre utilis\u00e9 pour seeder OpenTorrentWindow.mb.alreadyExists.text=Le %3 a d\u00e9j\u00e0 \u00e9t\u00e9 ajout\u00e9 en tant que '%2' OpenTorrentWindow.mb.alreadyExists.title=Le torrent existe d\u00e9j\u00e0 OpenTorrentWindow.mb.openError.title=Erreur d'ouverture OpenTorrentWindow.mb.openError.text='%1' n'a pas pu \u00eatre ouvert: OpenTorrentWindow.torrent.remove=Enlever le torrent de la liste OpenTorrentWindow.torrent.options=Les param\u00e8tres suivants seront appliqu\u00e9s aux torrents s\u00e9lectionn\u00e9s ci-dessus OpenTorrentWindow.xOfTotal=(%1 sur %2) iconBar.open.tooltip=Ouvrir Torrent(s) LocaleUtil.column.text=Texte inconnu Tracker.tooltip.MultiSupport=Ce tracker supporte plusieurs hash par requ\u00eate. Tracker.tooltip.NoMultiSupport=Ce tracker ne supporte pas plusieurs hash par requ\u00eate. ConfigView.label.lazybitfield=Utiliser le bitfield "paresseux" (aide \u00e0 seeder sur les r\u00e9seaux bloquant par d\u00e9tection de bitfield) LoggerView.realtime=Mettre \u00e0 jour en temps r\u00e9el ConfigView.section.file.perf.cache.flushpieces=Ecrit les pi\u00e8ces compl\u00e8tes imm\u00e9diatement sur le disque. Cela rend l'acc\u00e8s disque plus fluide mais engendre plus d'op\u00e9rations d'\u00e9criture. ConfigView.section.file.writemblimit=Nombre maximum de requ\u00eates d'\u00e9criture mises en file d'attente (en %1) ConfigView.section.file.writemblimit.explain=Lorsque la vitesse d'\u00e9criture sur le disque est inf\u00e9rieure \u00e0 la vitesse de t\u00e9l\u00e9chargement, ce param\u00e8tre limite la quantit\u00e9 de donn\u00e9es mise en attente avant une limitation de la vitesse de t\u00e9l\u00e9chargement. ConfigView.section.file.readmblimit=Nombre maximum de requ\u00eates de lecture mises en file d'attente (en %1) ConfigView.section.file.readmblimit.explain=Ce param\u00e8tre limite la m\u00e9moire allou\u00e9e aux lectures en cours. Button.moveUp=D\u00e9placer vers le haut Button.moveDown=D\u00e9placer vers le bas ConfigView.notAvailableForMode=Cette section s'adresse au mode %1 ou plus. Elle n'est pas disponible en mode %2. health.explain.error=Ce torrent a produit une erreur. Voir la colonne "Etat", ou l'indication sur l'icone de l'erreur. PeersView.piece.info=Num\u00e9ro de la derni\u00e8re pi\u00e8ce demand\u00e9e \u00e0 ce client PiecesView.priority=Priorit\u00e9 PiecesView.priority.info=la priorit\u00e9 affect\u00e9e \u00e0 cette pi\u00e8ce (pas tr\u00e8s fiable) PiecesView.speed=Vitesse PiecesView.speed.info=Les clients lents n'interf\u00e8rent pas avec les pi\u00e8ces rapides TableColumn.header.AvgAvail.info=Somme des disponibilit\u00e9s des pi\u00e8ces divis\u00e9e par le nombre de pi\u00e8ces, divis\u00e9e par le nombre de connections TableColumn.header.AvgAvail=Dispo. moy./pi\u00e8ce ConfigView.label.strictfilelocking=Forcer le verrouillage exclusif de l'acc\u00e8s en \u00e9criture \u00e0 un fichier sur tous les torrents MyTorrentsView.menu.rescanfile=Rev\u00e9rifier p\u00e9riodiquement les pi\u00e8ces incompl\u00e8tes Plugin.localtracker.name=D\u00e9tecteur de clients sur LAN Plugin.localtracker.info=Le d\u00e9tecteur de clients sur LAN permet \u00e0 plusieurs Vuze derri\u00e8re un pare-feu ou sur un m\u00eame r\u00e9seau local\nde t\u00e9l\u00e9charger efficacement un m\u00eame torrent en \u00e9tablissant des connections directes entre eux. Plugin.localtracker.enable=Activer la d\u00e9tection des clients sur le LAN azinstancehandler.alert.portclash=Conflit de port sur LAN\u00a0: %1 est d\u00e9j\u00e0 utilis\u00e9 par un autre utilisateur, veuillez s\u00e9lectionner un (deux) port(s) au hasard pour l'\u00e9coute TCP/UDP [entre %2 et %3] ConfigView.section.transfer.lan.tooltip=R\u00e9glages sp\u00e9cifiques LAN ConfigView.section.transfer.lan.uploadrate=ko/s LAN vitesse maximale d'envoi [0\u00a0: illimit\u00e9e] ConfigView.section.transfer.lan.uploadrate.tooltip=Limite d'envoi propre aux clients sur un m\u00eame r\u00e9seau local ConfigView.section.transfer.lan.downloadrate=ko/s LAN vitesse maximale de t\u00e9l\u00e9chargement [0\u00a0: illimit\u00e9e] ConfigView.section.transfer.lan.downloadrate.tooltip=Limite de t\u00e9l\u00e9chargement propre aux clients sur un m\u00eame r\u00e9seau local TorrentOptionsView.param.max.peers=Nombre maximum de connections [0: illimit\u00e9] ConfigView.section.connection.encryption.require_encrypted_transport=Exiger un flux encrypt\u00e9 ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Force l'utilisation de connections encrypt\u00e9es avec les autres clients ConfigView.section.connection.encryption.min_encryption_level=Niveau d'encryption minimum ConfigView.section.connection.encryption.min_encryption_level.tooltip=Simple - handshake seulement\nRC4 - tout le flux\nUne encryption plus forte requiert plus de CPU. Peers.column.Encryption.info=Niveau d'encryption utilis\u00e9 ConfigView.section.connection.encryption.encrypt.info=Si l'encryption est activ\u00e9e, vous ne pourrez pas vous connecter aux clients incompatibles (sauf \u00e0 activer des options de repli) ConfigView.section.connection.encryption.encrypt.info.link=Voir ici pour plus de pr\u00e9cisions MainWindow.sr.status.tooltip.ok=Taux de partage %1 OK MainWindow.sr.status.tooltip.poor=Taux de partage %1 insuffisant: < 0.9 MainWindow.sr.status.tooltip.bad=Taux de partage %1 mauvais: < 0.5 ConfigView.section.style.status=Zone d'\u00e9tat\u00a0: ConfigView.section.style.status.show_sr=Tx Partage ConfigView.section.style.status.show_nat=\u00e9tat NAT ConfigView.section.style.status.show_ddb=\u00e9tat DDB ConfigView.section.connection.encryption.encrypt.group=Transfert encrypt\u00e9/obfusqu\u00e9 ConfigView.section.connection.encryption.encrypt.fallback_info=Activer les options de repli va permettre des connections aux clients non compatibles mais elles seront non encrypt\u00e9es ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Permettre les connections sortantes non encrypt\u00e9es si un essai de connection encrypt\u00e9e \u00e9choue ConfigView.section.connection.encryption.encrypt.fallback_incoming=Permettre les connections entrantes non encrypt\u00e9es ConfigView.section.connection.encryption=Encryption upnp.selectedinterfaces=Interfaces s\u00e9lectionn\u00e9es (s\u00e9par\u00e9es par ';' [ex: eth0;eth1]) [vide: toutes] ConfigView.section.style.defaultSortOrder=Sens de classement par d\u00e9faut ConfigView.section.style.defaultSortOrder.desc=D\u00e9croissant ConfigView.section.style.defaultSortOrder.asc=Croissant ConfigView.section.style.defaultSortOrder.flip=Inverse du classement pr\u00e9c\u00e9dent LoggerView.autoscroll=D\u00e9filement automatique Button.selectAll=Tout s\u00e9lectionner Button.markSelected=Marquer les s\u00e9lections Button.unmarkSelected=D\u00e9marquer les s\u00e9lections TorrentOptionsView.param.max.uploads=Nombre maximum d'uploads [minimum: 2] MyTorrentsView.dialog.setPosition.title=R\u00e9gler la position MyTorrentsView.dialog.setPosition.text=Entrer la position \u00e0 laquelle mettre les torrents s\u00e9lectionn\u00e9s: MyTorrentsView.menu.reposition.manual=Repositionner.. ConfigView.section.connection.advanced.info.link=Voir ici pour plus de pr\u00e9cisions ConfigView.section.connection.advanced.bind_port=Lier au port local [0: d\u00e9sactiv\u00e9] ConfigView.section.connection.advanced.bind_port.tooltip=Les connections sortantes seront li\u00e9es localement \u00e0 ce port.\nPeut aider avec certaines instabilit\u00e9es NAT des routeurs. Pieces.column.Requested=Demand\u00e9 Pieces.column.Requested.info=Montre si d'autres requ\u00eates peuvent \u00eatre faites sur cette pi\u00e8ce ou pas (*) ConfigView.label.maxuploadsseeding=quand en source seulement MyTorrentsView.filter=Filtre: popup.error.hideall=Tout cacher MyTorrentsView.menu.filter=Filtre... ConfigView.section.file.resume.recheck.all=Lors d'un red\u00e9marrage apr\u00e8s crash, v\u00e9rifier tout le fichier (sinon seules les pi\u00e8ces actives avant le crash seront v\u00e9rifi\u00e9es) ConfigureWizard.language.choose=Choisir une langue dans la liste suivante: popup.closing.in=Fermeture automatique de la fen\u00eatre dans %1 seconde(s) popup.more.waiting=%1 message(s) restant(s)... # > 2402 popup.download.finished="%1" est termin\u00e9. popup.file.finished="%1" est termin\u00e9. DownloadManager.error.badsize=Taille incorrecte authenticator.savepassword=Retenir mon mot de passe Content.alert.notuploaded.text=Le partage de "% 1" n'est pas termin\u00e9. Si vous avez 2% aujourd'hui, les gens ne seront pas en mesure de t\u00e9l\u00e9charger compl\u00e8tement vos fichiers publi\u00e9s. \n\nVoulez-vous vraiment 2%? Content.alert.notuploaded.multi.text=\t Content.alert.notuploaded.stop=arr\u00eater Content.alert.notuploaded.quit=Quitter Vuze ConfigView.label.popup.show=Voir tous les popups d'alerte enregistr\u00e9s \u00e0 ce jour (le cas \u00e9ch\u00e9ant) ConfigView.label.popup.show.button=Montrer ConfigView.label.please.visit.here=Pour plus de d\u00e9tails, vous pouvez aller voir ici ConfigView.label.openmytorrents=Ouvrir 'Mes Torrents' au d\u00e9marrage ConfigView.label.open_transfer_bar_on_start=Ouvrir la Barre de Transfert au d\u00e9marrage ConfigView.label.pause.downloads.on.exit=Mettre les t\u00e9l\u00e9chargements en pause \u00e0 la sortie ConfigView.label.resume.downloads.on.start=Reprendre des t\u00e9l\u00e9chargements en pause au d\u00e9marrage apr\u00e8s l'initialisation compl\u00e8te ConfigView.label.mindownloads=Nombre minimum de t\u00e9l\u00e9chargements simultan\u00e9s ConfigView.label.popupdownloadadded=Montrer une alerte 'popup' quand un t\u00e9l\u00e9chargement est ajout\u00e9 popup.download.added="%1" a \u00e9t\u00e9 ajout\u00e9 \u00e0 votre liste de t\u00e9l\u00e9chargement. alert.raised.at.close=(Message de la pr\u00e9c\u00e9dente fermeture de Vuze) speedtest.wizard.title=Test de d\u00e9bit speedtest.wizard.run=D\u00e9marrer un test de d\u00e9bit speedtest.wizard.test.mode.updown=partage et t\u00e9l\u00e9chargement speedtest.wizard.test.mode.up=partage speedtest.wizard.test.mode.down=t\u00e9l\u00e9chargement ConfigView.interface.start.advanced=D\u00e9marrer en vue avanc\u00e9e (AZ 2.x) MyTorrents.column.ColumnQuality=Qualit\u00e9 MyTorrents.column.ColumnSpeed=Vitesse MyTorrents.column.ColumnProgressETA.2ndLine=Reste: %1 TableColumn.header.Quality=Qualit\u00e9 TableColumn.header.Speed=Vitesse TableColumn.header.RateIt=Noter TableColumn.header.Rating=Note TableColumn.header.SpeedGraphic=Vitesse TableColumn.header.AzProduct=De TableColumn.header.ProgressETA=Avancement #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=Accueil v3.MainWindow.tab.browse=Sur Vuze v3.MainWindow.tab.library=Biblioth\u00e8que v3.MainWindow.tab.publish=Publier v3.MainWindow.tab.advanced=Avanc\u00e9 v3.MainWindow.menu.home=&Accueil v3.MainWindow.menu.browse=&Naviguer v3.MainWindow.menu.library=$Biblioth\u00e8que v3.MainWindow.menu.publish=&Publier v3.MainWindow.menu.advanced=A&vanc\u00e9 v3.MainWindow.menu.view.searchbar=Barre de Recherche v3.MainWindow.menu.view.tabbar=Barre d'Onglets v3.MainWindow.currentDL=T\u00e9l\u00e9chargements en cours v3.MainWindow.button.stream=Jouer v3.MainWindow.button.stop=Arr\u00eater v3.MainWindow.button.start=D\u00e9marrer v3.MainWindow.button.resume=Reprendre v3.MainWindow.button.delete=Supprimer v3.MainWindow.button.comment=Commenter v3.MainWindow.button.viewdetails=D\u00e9tails v3.MainWindow.button.play=Ouvrir v3.MainWindow.button.cancel=Annuler v3.MainWindow.button.preview=Pr\u00e9visualiser v3.MainWindow.view.wait=En cours d'initialisation. Veuillez patienter v3.MainWindow.xofx=%1 sur %2 v3.MainWindow.Loading=Chargement en cours.. Merci de bien vouloir patienter v3.filter-bar=Filtrer sur le Titre : v3.MainWindow.search.defaultText=Rechercher des Fichiers torrents v3.mb.delPublished.delete=&Supprimer v3.mb.delPublished.cancel=&Annuler v3.mb.deletePurchased.button.delete=&Supprimer v3.mb.deletePurchased.button.cancel=&Annuler # # Used for peers which we can't determine. PeerSocket.unknown=Inconnu Content.alert.notuploaded.button.stop=&Arr\u00eater Content.alert.notuploaded.button.continue=&Continuer \u00e0 partager Content.alert.notuploaded.button.abort=&Ne pas quitter Alert.failed.update=L'installation du dernier composant a \u00e9chou\u00e9. Allez voir: AzureusWiki: Failed Update [%1] ConfigView.label.minannounce=Temps minimum entre les annonces du tracker en secondes ConfigView.label.maxnumwant=Limite le nombre de pairs que le tracker peut envoyer ConfigView.label.announceport=Passer outre au port d'annonce du tracker ConfigView.label.maxseedspertorrent=Nombre maximum de seed par torrent, par d\u00e9faut: [0: illimit\u00e9] Progress.reporting.status.canceled=Annul\u00e9 Progress.reporting.status.finished=Termin\u00e9 Progress.reporting.status.retrying=R\u00e9essayer... Progress.reporting.action.label.retry.tooltip=R\u00e9essayer cette op\u00e9ration Progress.reporting.action.label.cancel.tooltip=Annuler l'op\u00e9ration Progress.reporting.action.label.detail=D\u00e9tails Progress.reporting.default.error=Erreur v3.MainWindow.text.log.in=Se Connecter v3.MainWindow.text.log.out=Se D\u00e9connecter v3.MainWindow.text.get.started=S'Enregistrer v3.MainWindow.text.my.account=Mon Compte v3.MainWindow.text.my.profile=Mon Profil v3.MainWindow.tab.minilibrary=T\u00e9l\u00e9chargements v3.MainWindow.tab.events=Activit\u00e9s v3.activity.remove.title=Supprimer l'entr\u00e9e d'activit\u00e9 v3.activity.remove.text=Etes vous s\u00fbr de vouloir supprimer l'entr\u00e9e d'activit\u00e9 '%1' ? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=Fermer #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences v3.button.removeActivityEntry=Supprimer l'entr\u00e9e d'activit\u00e9 ConfigView.copy.to.clipboard.tooltip=Copier dans le presse-papier Browser.popup.error.no.access=Une erreur s'est produite lors de la tentative d'acc\u00e9der \u00e0 une ressource \u00e9loign\u00e9e. \nR\u00e9essayez ult\u00e9rieurement. \n ConfigView.label.queue.stoponcebandwidthmet=Ne pas d\u00e9marrer plus de torrents quand la vitesse limite de partage/t\u00e9l\u00e9chargement est atteinte azbuddy.name=Amis azbuddy.enabled=Activ\u00e9 azbuddy.disabled=Le plugin est d\u00e9sactiv\u00e9, regardez la configuration du plugin pour changer cela. azbuddy.nickname=Votre surnom azbuddy.msglog.title=Information sur votre ami azbuddy.addtorrent.title=Accepter le t\u00e9l\u00e9chargement? azbuddy.addtorrent.msg=L'ami '%1' vous a envoy\u00e9 '%2'./nVoulez-vous ajouter ce t\u00e9l\u00e9chargement? azbuddy.contextmenu=Envoyer \u00e0 un ami azbuddy.ui.mykey=Ma Cl\u00e9 azbuddy.ui.add=Ajouter azbuddy.ui.table.last_msg=Dernier message azbuddy.ui.menu.remove=Supprimer azbuddy.ui.menu.copypk=Copie de Cl\u00e9 Publique azbuddy.ui.menu.send=Envoyer un message azbuddy.ui.menu.send_msg=Entrez le texte a envoyer \u00e0 votre (vos) ami(s) v3.MainWindow.menu.view.footer=Barre d'Amis azbuddy.downspeed=KB/s max vitesse de t\u00e9l\u00e9chargement ami [0: illimit\u00e9] azbuddy.chat.says=%1 dit: Button.bar.add=Ajouter des Amis Button.bar.edit=Modifier Button.bar.edit.cancel=Fini de Modifier v3.MainWindow.menu.view.pluginbar=Barre de Plugin v3.share.private.title=Partage de Torrents v3.share.private.text=Le torrent s\u00e9lectionn\u00e9 est marqu\u00e9 comme "priv\u00e9".\n\nVous ne pouvez pas partager des torrents priv\u00e9s azbuddy.tracker.enabled=Activer le 'Boost d'Amis' pour t\u00e9l\u00e9charger plus vite avec vos Amis v3.MainWindow.button.download=T\u00e9l\u00e9charger v3.MainWindow.button.run=Ouvrir le fichier t\u00e9l\u00e9charg\u00e9 v3.activity.header.downloads=T\u00e9l\u00e9chargements v3.activity.header.vuze.news=Nouvelles de Vuze message.status.success=Succ\u00e8s azbuddy.tracker.bbb.status.title=Boost d'Amis azbuddy.tracker.bbb.status.title.tooltip=Double cliquez pour obtenir des d\u00e9tails azbuddy.tracker.bbb.status.idle=Pas de Boost azbuddy.tracker.bbb.status.nli=Connection Requise azbuddy.tracker.bbb.status.in=Je suis Boost\u00e9 azbuddy.tracker.bbb.status.out=En train de Booster des Amis v3.MainWindow.search.go.tooltip=Lancer la Recherche v3.MainWindow.search.last.tooltip=Afficher la derni\u00e8re Recherche azbuddy.online_status=Statut de connection azbuddy.os_online=Connect\u00e9 azbuddy.os_away=Absent azbuddy.os_not_avail=Pas disponible azbuddy.os_busy=Occup\u00e9 azbuddy.os_offline=D\u00e9connect\u00e9 azbuddy.ui.menu.disconnect=D\u00e9connect\u00e9 azbuddy.enable_chat_notif=Activer les notifications du chat DetailedListView.title=Liste d\u00e9taill\u00e9e iconBar.queue.tooltip=File d'attente MainWindow.menu.help.faq=&FAQ sidebar.Library=Ma biblioth\u00e8que sidebar.LibraryDL=T\u00e9l\u00e9chargement sidebar.LibraryCD=Termin\u00e9 authenticator.location=Lieu authenticator.details=D\u00e9tails Button.back=Retour sidebar.LibraryUnopened=Non visionn\u00e9s #what you've watched? Discover more with a single click... Button.add=Ajouter message.confirm.delete.title=Confirmer la suppression message.confirm.delete.text=\u00cates-vous certain de vouloir supprimer '%1'? props.window.title=Propri\u00e9t\u00e9s pour '%1' Button.deleteContent.fromComputer=Supprimer de votre ordinateur configureWizard.file.message3=Vuze placera les fichiers t\u00e9l\u00e9charg\u00e9s dans un dossier sp\u00e9cifique, vous pouvez choisir ce dossier ici: azbuddy.ui.menu.cat=Cat\u00e9gories azbuddy.ui.menu.cat.set=Entrez des cat\u00e9gories azbuddy.ui.menu.cat.set_msg=S\u00e9parez la liste des cat\u00e9gories par des virgules, ou marquez "Tous" azbuddy.ui.menu.cat_subs=S'abonner azbuddy.enable_cat_pub=Cat\u00e9gories publiques auxquelles TOUS vos amis peuvent s'abonner (s\u00e9par\u00e9 par des ',') device.browse=Parcourir ConfigView.label.maxStalledSeeding=Maximum 'stalled' [0: illimit\u00e9] General.percent=Pourcent MainWindow.menu.help.donate=Faire une &donation... # This is the beginning of the word "View". It's right aligned under the icon bar item # This is the end of the word "View". It's left aligned under the icon bar item general.dont.ask.again=Ne plus me redemander device.itunes.install=Vous devez installer iTunes device.itunes.start=Vous devez d\u00e9marrer iTunes ou activer le d\u00e9marrage automatique device.itunes.install_problem=Il semble y avoir un probl\u00e8me avec l'int\u00e9gration d'iTunes option.askeverytime=Demander \u00e0 chaque fois option.rememberthis=Se souvenir de ce r\u00e9glage azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_fy_NL.properties0000644000175000017500000025220511301156004026104 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=.torrent-triem Main.parameter.usage=Gebruik : java org.gudy.azureus2.cl.Main [parameters] "bestand.torrent" "Bewaar pad" Main.parameter.maxUploads=Max aantal gelijktijdige uploads Main.parameter.maxSpeed=Max uploadsnelheid in bytes/sec MainWindow.menu.file=Triem MainWindow.menu.file.open=&Iepene MainWindow.menu.file.create=Torrenttriem meitsje MainWindow.menu.file.create.fromfile=Van een Bestand MainWindow.menu.file.create.fromdir=Van een Map MainWindow.menu.file.export=Torrent &Exporteren... MainWindow.menu.file.import=Torrent &Importeren... MainWindow.menu.file.closetab=Tabbl\u00ead sl\u00faten MainWindow.menu.file.closewindow=&Finster sl\u00faten MainWindow.menu.file.exit=\u00d4fsl\u00fate MainWindow.dialog.choose.file=Kies het torrentbestand MainWindow.menu.file.folder=Map MainWindow.dialog.choose.folder=Kies de map waar de torrents zich bevinden MainWindow.menu.view=Byld MainWindow.menu.view.show=Sjin litten MainWindow.menu.view.mytorrents=&Myn Torrents MainWindow.menu.view.configuration=&Konfiguraasje MainWindow.menu.view.irc=Irc MainWindow.menu.closealldetails=Sluit &alle Details MainWindow.menu.closealldownloadbars=Sluit alle Download &Balken MainWindow.menu.language=Taal ConfigView.section.language=Taal MainWindow.menu.window=Finster MainWindow.menu.window.minimize=&Minimalisearje MainWindow.menu.window.alltofront=Alle naar voren brengen MainWindow.menu.help=&Help MainWindow.menu.help.about=Oer &Vuze MainWindow.about.title=Ynfo oer Vuze MainWindow.about.section.developers=Ontwikkelaars MainWindow.about.section.translators=Fertellers MainWindow.about.section.internet=Ynternet MainWindow.about.internet.homepage=Thuispagina Vuze MainWindow.about.internet.sourceforge=Sourceforge-projectpagina MainWindow.about.internet.sourceforgedownloads=Sourceforge-Downloads MainWindow.about.internet.bugreports=Foutrapportages MainWindow.about.internet.wiki=Veelgestelde vragen over Vuze Wiki MainWindow.dialog.choose.savepath=Kies het pad voor opslag MainWindow.dialog.choose.savepath_forallfiles=Kies het pad voor opslag van ALLE bestanden MainWindow.status.latestversion=Nijste ferzje MainWindow.status.latestversion.clickupdate=Klik om bij te werken MainWindow.status.unknown=\u00fbnbekend MainWindow.status.checking=kontrolearje MyTorrentsView.mytorrents=Myn Torrents TableColumn.header.name=Namme TableColumn.header.size=Grootte TableColumn.header.done=Klear TableColumn.header.done.info=Percentage gedaan van huidige taak TableColumn.header.status.info=Wat de torrent doet TableColumn.header.seeds=Uploaders TableColumn.header.seeds.info=# uploaders waarmee je bent verbonden (# uploaders totaal) TableColumn.header.peers=Ontvangers TableColumn.header.peers.info=# downloaders waar je mee bent verbonden (# downloaders totaal) TableColumn.header.downspeed=Downloadsnelheid TableColumn.header.upspeed=Uploadsnelheid TableColumn.header.eta=Tijd tot voltooiing TableColumn.header.tracker=Tracker TableColumn.header.tracker.info=Status van tracker TableColumn.header.trackernextaccess=Trackerupdate TableColumn.header.trackernextaccess.info=Wanneer de volgende trackerupdate zal plaatsvinden TableColumn.header.priority=Prioriteit TableColumn.header.priority.info=Bepaalt hoeveel bandbreedte aan uploadende torrent wordt gegeven MyTorrentsView.menu.showdetails=Bekijk &details MyTorrentsView.menu.showdownloadbar=Toon download&balk MyTorrentsView.menu.open=&Iepene MyTorrentsView.menu.setpriority=Wijzig &Prioriteit MyTorrentsView.menu.setpriority.high=&Heech MyTorrentsView.menu.setpriority.low=&Leech MyTorrentsView.menu.remove=Ve&rwijderen MyTorrentsView.menu.changeTracker=Voeg Tr&acker-URL toe TrayWindow.menu.exit=\u00d4fsl\u00faten TrayWindow.menu.show=Azureu&s iepene SystemTray.menu.exit=\u00d4fsl\u00fate SystemTray.menu.closealldownloadbars=Sluit &Alle downloadbalken SystemTray.menu.show=Azureu&s iepene PeersView.ip.info=IP-adres van de downloader PeersView.port=Poarte PeersView.port.info=Poarte yn br\u00fbk PeersView.T.info=L (lokaal): je hebt verbinding gemaakt, R (afstand): de downloader heeft verbinding gemaakt. PeersView.T.L.tooltip=je hebt verbinding gemaakt PeersView.T.R.tooltip=de downloader heeft verbinding gemaakt. PeersView.I1=I1 (Aangevraagd door de downloader) PeersView.I1.info=Ben je ge\u00efntereseerd in wat de andere downloader heeft? PeersView.C1=V1 (Verstopt door de downloader) PeersView.C1.info=Of de downloader je blokkeert bij het downloaden PeersView.pieces=Stukjes PeersView.downloadspeed=Downloadsnelheid PeersView.I2=I2 (Aangevraagd door de downloader) PeersView.I2.info=Is de andere downloader ge\u00efntereseerd in wat jij hebt? PeersView.C2=V2 (De dowloader verstoppen) PeersView.C2.info=Of de downloader je blokkeert bij het downloaden PeersView.uploadspeed=Uploadsnelheid PeersView.uploadspeed.info=Je uploadsnelheid naar de downloader PeersView.upload.info=Je totale upload naar de downloader. PeersView.statup=Up-status PeersView.statup.info=Een geschatte waarde van de upload snelheid van de downloader PeersView.S=A PeersView.S.info=Afwijzen: Een downloader kan handmatig worden \u201eafgewezen\u201d, of automatisch (voor het niet leveren van gegevens met een waarde die hoog genoeg is) PeersView.downloadspeedoverall=Gemiddelde Downloadsnelheid PeersView.optunchoke=Opt. Ontstop PeersView.client=Br\u00fbker PeersView.client.info=Het type BT-cli\u00ebnt dat de downloader gebruikt PeersView.menu.snubbed=Afwijzen PeersView.title.short=Details PeersView.title.full=Details ConfigView.section.files=Triemen ConfigView.label.usefastresume=Downloads snel herstarten ConfigView.label.incrementalfile=Zet oplopende bestandsgrootte aan ConfigView.label.defaultsavepath=Opslaan in standaard data map ConfigView.button.browse=Bl\u00eadzje... ConfigView.dialog.choosedefaultsavepath=Standert map selektearje ConfigView.section.server=Server ConfigView.section.global=Globaal ConfigView.label.disconnetseed=Verbreek verbinding met zenders tijdens uploaden ConfigView.label.switchpriority=Automatisch omschakelen naar lage prioriteit tijdens zenden ConfigView.label.maxdownloads=Maximum gelijktijdige downloads [0: ongelimiteerd] ConfigView.label.maxdownloads.tooltip=Het aantal downloads dat je hier hebt opgegeven, kunnen gewoon gedownload worden.\nDe enige voorwaarde is dat een voltooide torrent met de hoogste prioriteit een actief downloadslot gebruiken indien dit nodig is. ConfigView.label.maxactivetorrents=Maximum actieve torrents [0 : ongelimiteerd]\n - Nieuwe torrents starten niet als je meer verzendt/ontvangt ConfigView.label.priorityExtensions=Automatisch hoge prioriteit bij bepaalde extensies \n zoals: .txt;.nfo;.jpg ConfigView.section.transfer=Oerdracht ConfigView.label.maxuploads=Standaard maximum uploads per torrent ConfigView.label.maxuploadspeed=Globale maximum uploadsnelheid in KB/s [0: ongelimiteerd] ConfigView.label.saveresumeinterval=Update de gegevens voor snel-hervatten iedere ConfigView.unlimited=Ongelimiteerd ConfigView.section.display=Byld ConfigView.label.opendetails=Automatisch details-tab openen ConfigView.label.openbar=Automatisch downloadbalk openen ConfigView.label.closetotray=Sluiten minimaliseerd naar systeemvak ConfigView.label.minimizetotray=Minimaliseren minimaliseert naar Systeemvak ConfigView.section.general=Algemyn ConfigView.section.start=Begjin ConfigView.label.showsplash=Laat opstartscherm zien ConfigView.label.autoupdate=Laat de Updatedialoog zien wanneer er een nieuwe versie is ConfigView.label.openconsole=Open de Console tijdens het starten ConfigView.label.openconfig=Open Configuratie tijdens het starten ConfigView.label.startminimized=Start geminimaliseerd ConfigView.section.irc=Irc ConfigView.label.ircserver=Server ConfigView.label.ircchannel=Kanaal ConfigView.label.irclogin=Schermnaam ConfigView.section.security=Beveiliging ConfigView.label.password=Bescherm Vuze met een wachtwoord\n - Zal om gevraagd worden tijdens het starten en uit het Systeemvak halen. ConfigView.label.passwordconfirm=Wachtwoord (bevestigen) ConfigView.label.passwordmatch=Wachtwoord geactiveerd : ConfigView.label.passwordmatchnone=Nee ConfigView.label.passwordmatchno=Nee / Wachtwoorden komen niet overeen ConfigView.label.passwordmatchyes=Ja ConfigView.button.save=Bewarje ConfigView.title.short=Ynstellings ConfigView.title.full=Ynstellings ConsoleView.title.short=Betsjinningspaniel ConsoleView.title.full=Betsjinningspaniel FileItem.write=skriuwe FileItem.read=l\u00eaze FileItem.normal=normaal FileItem.high=heech FileItem.donotdownload=Net ynlade FilesView.name=Namme FilesView.size=Grutte FilesView.done=Klear FilesView.%=% FilesView.firstpiece=N\u00fbmer earste diel FilesView.numberofpieces=Oantal stikken FilesView.pieces=Stikken FilesView.mode=Manear FilesView.priority=Prioriteit FilesView.menu.open=&Iepenje FilesView.menu.setpriority=Verander prioriteit FilesView.menu.setpriority.high=&Heech FilesView.menu.setpriority.normal=&Normaal FilesView.menu.setpriority.skipped=Net &ynlade FilesView.title.short=Triemen FilesView.title.full=Triemen GeneralView.section.downloaded=Gedownload GeneralView.label.status.file=Bestandsstatus GeneralView.label.status.pieces=Stukjesstatus GeneralView.section.availability=Beskikberheid GeneralView.label.status.pieces_available=Stukjesstatus GeneralView.section.transfer=Oerdracht GeneralView.section.info=Ynformaasje GeneralView.title.short=Algemien GeneralView.title.full=Algemien GeneralView.label.timeelapsed=Tijd verstreken: GeneralView.label.remaining=Resterend: GeneralView.label.downloaded=Ynladen: GeneralView.label.downloadspeed=Downloadsnelheid: GeneralView.label.maxuploads=Maks Uploads: GeneralView.label.uploaded=Oplade: GeneralView.label.uploadspeed=Uploadsnelhyd: GeneralView.label.seeds=Stjoerders: GeneralView.label.peers=\u00dbntfangers: GeneralView.label.totalspeed=Totale snelheid: GeneralView.label.totalspeed.tooltip=Totale snelheid van alle cli\u00ebnten waarmee je verbonden bent. GeneralView.label.averagespeed=trochhinne GeneralView.label.filename=Namme: GeneralView.label.totalsize=Totale grootte: GeneralView.label.savein=Bewarje yn: GeneralView.label.hash=Hash: GeneralView.label.numberofpieces=Oantal stikken: GeneralView.label.size=Grutte: GeneralView.label.tracker=Trackerstatus: GeneralView.label.trackerurl=URL fan tracker: GeneralView.label.trackerurlupdate=Handmatige Update GeneralView.label.comment=Kommentear: ManagerItem.waiting=Wachtsje ManagerItem.allocating=Reserveren ManagerItem.checking=Controleren ManagerItem.ready=Klear ManagerItem.downloading=Downloaden ManagerItem.seeding=Oerbringe ManagerItem.stopped=Stoppe ManagerItem.error=Fout ManagerItem.high=heech ManagerItem.low=leech MinimizedWindow.name=Namme: PiecesView.size=Grutte PiecesView.numberofblocks=# blokken PiecesView.blocks=Blokken PiecesView.completed=Kompleet PiecesView.availability=Beskikberheid PiecesView.title.short=Stukjes PiecesView.title.full=Stukjes SystemTray.tooltip.seeding=%1 bringe oer, SystemTray.tooltip.downloading=%1 helje oer, DownloadManager.error.filenotfound=Triem net f\u00fbn DownloadManager.error.fileempty=Torrentbestand is leeg DownloadManager.error.filetoobig=Torrentbestand is te groot DownloadManager.error.filewithouttorrentinfo=Torrentynformaasje in triem net f\u00fbn DownloadManager.error.unsupportedencoding=Niet ondersteunde codering DownloadManager.error.ioerror=I/O-fout DownloadManager.error.sha1=Fout: onbekend algoritme (SHA1) PeerManager.status.offline=Gjin ferbinding PeerManager.status.ok=ok PeerManager.status.checking=kontrolearje PeerManager.status.finished=Klear PeerManager.status.finishedin=Klearmakke yn MainWindow.upgrade.assistant=Update-assistent MainWindow.upgrade.newerversion=Er is een nieuwere versie van Vuze beschikbaar MainWindow.upgrade.explanation=Deze assistent zal de nieuwe versie downloaden in je Vuze map en Vuze herstarten MainWindow.upgrade.explanation.manual=Je kunt handmatig updaten door Vuze te sluiten, de nieuwe versie te downloaden en Vuze weer te starten MainWindow.upgrade.step1=Stap 1: Download de nieuwe versie MainWindow.upgrade.step2=Stap 2: Sluit deze versie en start de nieuwe versie van Vuze MainWindow.upgrade.hint1=Hint:\tDoor op Voltooien te drukken zal alles automatisch gaan MainWindow.upgrade.hint2=Hint:\tAls je Vuze later wilt afsluiten,druk op Annuleren en\n\thernoem Azureus2-new.jar naar Azureus2.jar na het sluiten MainWindow.upgrade.error.downloading.hint=Fout:\tKan geen nieuwe versie downloaden, update Vuze handmatig MainWindow.upgrade.section.info=Nieuwe versie beschikbaar MainWindow.upgrade.section.manual=Handmatige update MainWindow.upgrade.section.automatic=Automatische update MainWindow.upgrade.tooltip.progressbar=De download voortgang is hier te zien Button.next=Fierder Button.finish=Klear Button.cancel=\u00d4fbrekke LocaleUtil.title=Kies fersifering LocaleUtil.section.chooseencoding=Kies fersifering foar triemnamme LocaleUtil.label.chooseencoding=Kies de best passende codering LocaleUtil.label.hint.doubleclick=Hint: Dubbelklikken op een regel kiest coderen en sluit de dialoog LocaleUtil.label.checkbox.rememberdecision=Onthoud beslissing voor overige bestandsnamen LocaleUtil.column.encoding=Fersiferje IrcClient.copyright=PircBot Java IRC API wordt gebruikt - http://www.jibble.org/pircbot.php IrcClient.connecting=Verbinden met IrcClient.connected=Verbonden met IrcClient.joining=Inloggen IrcClient.channel=Kanaal IrcClient.joined=ingelogd IrcClient.error=Fout IrcClient.hasjoined=is verbonden IrcClient.haskicked=is gekickt IrcClient.hasleft=is vertrokken IrcClient.nowknown=is nu bekend als IrcClient.topicforchannel=Onderwerp van dit kanaal IrcClient.disconnected=Verbinding verloren met IrcClient.noNick=Geen schermnaam opgegeven. Open de 'Configuratie' IrcView.actionnotsupported=Deze actie wordt niet ondersteund IrcView.clientsconnected=gebruikers IrcView.privateto=Aan IrcView.privatefrom=Van IrcView.noticefrom=Let op : IrcView.errormsg=Verkeerde Syntax bij /msg : /msg gebruiker tekst IrcView.help=Geldige commando's zijn :\n . /help : geeft dit bericht weer\n . /nick | /naam : wijzigt je naam \n . /me actie : verstuurt een actie \n . /msg naam bericht : stuurt een priv\u00e9bericht naar \n . /r bericht : antwoordt op laatste priv\u00e9bericht\n . /join #kanaal : wijzigt het huidige kanaal PasswordWindow.title=Vuze is geblokkeerd PasswordWindow.passwordprotected=Vuze is beschermd met een wachtwoord.\nVul hier je wachtwoord in, om het venster te tonen : Button.ok=Ok TrackerChangerWindow.title=Voeg Tracker toe TrackerChangerWindow.newtracker=Vul een nieuw trackeradres in PeersView.discarded=Negearje PeersView.discarded.info=Gegevens die je ontvangen hebt maar niet nodig hebt en daarom verwijderd zijn. discarded=\u00f4ftankje MyTorrentsView.#=# MyTorrentsView.menu.move=Verplaats MyTorrentsView.menu.moveUp=Omhoog MyTorrentsView.menu.moveDown=Omlaag GeneralView.label.hashfails=Hashfouten: GeneralView.label.shareRatio=Dielferh\u00e2lding: ConfigView.section.downloadManagement=Downloadbeheer ConfigView.label.startRatioPeers=Start met uploaden wanneer er minder dan 1 uploader is voor ConfigView.text.neverStop=Nea stopje ConfigView.text.neverStart=Nea begjinne ConfigView.text.peers=Peers ConfigView.label.checkOncompletion=Controleer de stukjes na voltooiing download opnieuw wizard.title=Maak een torrent wizard.previous=< Vorige wizard.next=Volgende > wizard.finish=Voltooien wizard.mode=Tracker/Modus wizard.invalidurl=Dit adres is niet geldig wizard.singlefile=Enkel bestand wizard.singlefile.help=Maak een torrent aan van een enkel bestand wizard.directory=Map wizard.directory.help=Maak een torrent aan van een map wizard.choosefile=Selecteer het bestand wizard.file=Triem: wizard.browse=Bl\u00eadzje... wizard.choosedirectory=Kies een map wizard.invalidfile=Ongeldig bestand! wizard.invaliddirectory=Ongeldige map! wizard.torrentFile=Torrentbestand wizard.choosetorrent=Kies het torrentbestand om aan te maken wizard.information=Ynformaasje wizard.notimplemented=Nog niet beschikbaar wizard.progresstitle=Aanmaken Torrentbestand wizard.savingfile=Bestand opslaan... wizard.filesaved=Bestand opgeslagen. wizard.close=Sl\u00faten Torrent.create.progress.piecelength=Lengte stukjes: Torrent.create.progress.piececount=Aantal stukjes: Torrent.create.progress.totalfilesize=Totale bestandsgrootte: Torrent.create.progress.totalfilecount=Totaal aantal bestanden: Torrent.create.progress.parsingfiles=Doorgeven bestanden Torrent.create.progress.hashing=Berekenen bestanden MainWindow.upgrade.downloadingfrom=Downloaden van : MainWindow.menu.view.ipFilter=&IP-Filters ConfigView.section.ipfilter=IP-filters ConfigView.section.ipfilter.description=Omschrijving ConfigView.section.ipfilter.start=Begin IP ConfigView.section.ipfilter.end=Eind IP ConfigView.section.ipfilter.add=Toevoegen ConfigView.section.ipfilter.remove=Verwijderen ConfigView.section.ipfilter.edit=Bewerken ConfigView.section.ipfilter.save=Opslaan ConfigView.section.ipfilter.editFilter=Bewerk Filter ConfigView.section.ipfilter.enable=Aanzetten PeersView.menu.close=Sluiten seedmore.title=Torrent wordt niet genoeg verspreid seedmore.shareratio=Je deelverhouding voor deze torrent is seedmore.uploadmore=Een deelverhouding van minder dan 100% is niet goed voor het Bittorrent netwerk.\nJe zou deze torrent nog wat langer moeten uploaden.\nWeet je zeker dat je wilt doorgaan? ConfigView.label.showpopuponclose=Laat een pop-up zien wanneer je stopt met uploaden met een deelverhouding van minder dan 1 ConfigView.label.startNumSeeds=\nBegin met uploaden als er minder dan\n - Overbrugt alle andere regels ConfigView.label.seeds=uploaders ConfigView.section.seeding=Uploaden MyTorrentsView.menu.removeand=Verwijder en MyTorrentsView.menu.removeand.deletetorrent=Verwijder .&torrent MyTorrentsView.menu.removeand.deletedata=Verwijder &gegevens MyTorrentsView.menu.removeand.deleteboth=Verwijder &beide deletedata.title=Warsk\u00f4ging! deletedata.message1=Je staat op het punt de GEGEVENS te verwijderen van:\n MainWindow.menu.file.configure=Konfiguraasjewizard... configureWizard.title=Configuratiewizard configureWizard.welcome.title=Wolkom by de konfiguraasjewizard fan Vuze configureWizard.welcome.message=Deze wizard helpt met het instellen van Vuze voor algemeen gebruik. Natuurlijk is het mogelijk om via Tools->Configuratie menu Vuze dieper in te stellen configureWizard.transfer.title=Verbindings en Overdracht setup configureWizard.transfer.hint=Hint : Een klein beetje minder dan je verbindingsnelheid is de beste instelling. configureWizard.transfer.message=Kies een verbinding hier beneden. Houdt er rekening mee dat een kleine upload resulteert in lage downloadsnelheden. Omdat de uploadsnelheid enkel PER torrent geldt, zal het downloaden van teveel torrents ook in lage snelheden resulteren. We raden aan 5kB/s per torrent als minimum te gebruiken. Hoe sneller je upload, des te sneller je zult downloaden (rekening houdend met de torrent snelheid). configureWizard.transfer.connection=Rigel configureWizard.transfer.connection.0=Handmatig configureWizard.transfer.connection.2=adsl/kabel xxx/128 kbps configureWizard.transfer.connection.3=adsl/kabel xxx/256 kbps configureWizard.transfer.connection.4=adsl/kabel xxx/384 kbps configureWizard.transfer.connection.5=adsl/kabel xxx/512 kbps configureWizard.transfer.connection.6=adsl/kabel xxx/768 kbps configureWizard.transfer.connection.7=adsl/kabel xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Max Uploadsnelheid (KB/s) configureWizard.transfer.maxActiveTorrents=Max Actief configureWizard.transfer.maxDownloads=Maks Downloads configureWizard.transfer.maxUploadsPerTorrent=Maks Uploads per Torrent configureWizard.nat.title=NAT / Server Poorten configureWizard.nat.message=Om het beste uit Bittorrent te behalen is het raadzaam om goed bereikbaar te zijn vanaf het internet. De standaard poort is 6881. Dit programma helpt met het testen / veranderen van de poort. configureWizard.nat.testing=Testen van poort configureWizard.nat.ok=Ok ! configureWizard.nat.ko=NAT-Fout configureWizard.nat.unable=Kan niet testen configureWizard.file.title=Torrents / Triemen configureWizard.file.message1=Vuze zal geopende torrents in een speciale map opslaan. Je kunt deze map hier aangeven: configureWizard.file.path=Paad configureWizard.file.browse=Sykje configureWizard.file.message2=Vuze kan gedownloade bestanden direct hervatten door gegevens toe te voegen aan de torrents. Door het gebruik van deze functie kun je ook gedeeltelijk gedownloade stukjes hervatten. configureWizard.file.fastResume=Schakel Snel hervatten in configureWizard.file.invalidPath=Map net jildich configureWizard.finish.title=Klear configureWizard.finish.message=Vuze is nu geconfigureerd. Veel plezier ! wizard.close.confirmation=Bevestiging wizard.close.message=Wil je deze wizard starten als Vuze de volgende keer start? exportTorrentWizard.title=Exporteer een torrent exportTorrentWizard.torrentfile.title=Selectie importeren exportTorrentWizard.torrentfile.message=Selecteer het te exporteren torrentbestand exportTorrentWizard.torrentfile.path=Paad exportTorrentWizard.torrentfile.browse=Bl\u00eadzje exportTorrentWizard.torrentfile.invalidPath=Ongeldig torrentbestand exportTorrentWizard.exportfile.title=Selectie exporteren exportTorrentWizard.exportfile.message=Voer de naam van het te exporteren XML-bestand in exportTorrentWizard.exportfile.path=Paad exportTorrentWizard.exportfile.browse=Bl\u00eadzje exportTorrentWizard.exportfile.invalidPath=Ongeldig exportbestand exportTorrentWizard.finish.title=Klear exportTorrentWizard.finish.message=Exporteren is succesvol voltooid exportTorrentWizard.process.inputfilebad.title=Torrentbestand Ongeldig exportTorrentWizard.process.inputfilebad.message=Er is een fout opgetreden tijdens het openen van invoerbestand: exportTorrentWizard.process.outputfileexists.title=Triem besjit exportTorrentWizard.process.outputfileexists.message=Uitvoerbestand bestaat - overschrijven? exportTorrentWizard.process.torrentfail.title=Torrent Lezen Mislukt exportTorrentWizard.process.exportfail.title=Torrent Exporteren Mislukt exportTorrentWizard.process.unknownfail.title=net ferwachte flater importTorrentWizard.title=Importeer een XML-torrent importTorrentWizard.torrentfile.title=Voer Torrentselectie in importTorrentWizard.torrentfile.message=Voer het torrent bestand in om naar te importeren importTorrentWizard.torrentfile.path=Paad importTorrentWizard.torrentfile.browse=Bl\u00eadzje importTorrentWizard.torrentfile.invalidPath=Ongeldig torrentbestand importTorrentWizard.importfile.title=Importeer selectie importTorrentWizard.importfile.message=Selecteer het XML-bestand om te importeren importTorrentWizard.importfile.path=Paad importTorrentWizard.importfile.browse=Bl\u00eadzje importTorrentWizard.importfile.invalidPath=Ongeldig importbestand importTorrentWizard.finish.title=Afgerond importTorrentWizard.finish.message=Importeren succesvol voltooid importTorrentWizard.process.inputfilebad.title=Het Importbestand is ongeldig importTorrentWizard.process.inputfilebad.message=Er is een fout opgetreden tijdens het openen van invoerbestand: importTorrentWizard.process.outputfileexists.title=Bestand bestaat importTorrentWizard.process.outputfileexists.message=Uitvoerbestand bestaat - overschrijven? importTorrentWizard.process.torrentfail.title=Torrent Schrijven Mislukt importTorrentWizard.process.importfail.title=Torrent Importeren Mislukt importTorrentWizard.process.unknownfail.title=Onverwachte fout ConfigView.label.bindip=Bind aan lokaal IP-adres or interface ConfigView.label.zeronewfiles=Bestanden van grootte 0 bij aanmaken ConfigView.label.zeronewfiles.tooltip=Minimaliseert fragmentatie ConfigView.section.stats=Statistieken ConfigView.section.stats.enable=Inschakelen ConfigView.section.stats.defaultsavepath=Map voor statistieken ConfigView.section.stats.choosedefaultsavepath=Kies de opslagplaats voor de statistieken ConfigView.section.stats.savefreq=Opslagfrequentie ConfigView.section.stats.minutes=min ConfigView.section.stats.hours=uur ConfigView.section.stats.seconds=sec ConfigView.section.stats.savefile=Statistiekbestand MyTorrentsView.menu.export=XML &Exporteren... MyTorrentsView.menu.host=Host... ManagerItem.finishing=Afronden ConfigView.dialog.choosedefaulttorrentpath=Kies de standaard map voor opslag van torrents ConfigView.dialog.choosemovepath=Kies de standaard map om naar te verplaatsen ConfigView.label.movecompleted=Verplaats afgeronde bestanden ConfigView.label.savetorrents=Torrents bewarje MainWindow.menu.view.mytracker=Myn &Tracker MyTrackerView.title.full=Myn Tracker MyTrackerView.name=Namme MyTrackerView.status.started=Rint MyTrackerView.status.stopped=\u00d4fbrutsen MyTrackerView.peers=Oerhellers MyTrackerView.seeds=Oerbringers MyTrackerView.announces=Ferkundigings MyTrackerView.uploaded=Ge\u00fcpload MyTrackerView.downloaded=Oerhelje MyTrackerView.left=Resterend ConfigView.section.style=\u00dbntwerp ConfigView.section.style.useCustomTabs=Gebruik sluitbare tabs (herstart nodig) fileDownloadWindow.saveTorrentIn=Torrent bewarje yn fileDownloadWindow.title=Vuze - Torrentdownloader fileDownloadWindow.downloading=Downloaden fan: fileDownloadWindow.status=Status: fileDownloadWindow.state_initializing=Beuzich fileDownloadWindow.state_downloading=Downloaden fileDownloadWindow.state_error=Flater: MainWindow.menu.file.open.url=&URL openUrl.title=Vuze - URL openen openUrl.url=URL: MyTorrentsView.menu.host.error.title=Torrent Hosting mislukt MyTorrentsView.menu.host.error.message=De volgende foutmelding trad op tijdens het hosten van de torrent ConfigView.section.tracker=Tracker ConfigView.section.tracker.pollinterval=Tracker cli\u00ebn afstemmings tussen pauze (sec) ConfigView.section.tracker.publishenable=Publiseer torrent details naar "" ConfigView.section.tracker.ip=IP-adres van externe tracker ConfigView.section.style.enableXPStyle=Activeer XP stijl (herstart nodig) ConfigView.section.tracker.checkip=Automatisch extern IP adress opzoeken... ipCheckerWizard.title=Wizard IP-controle ipCheckerWizard.service=Diensten ipCheckerWizard.chooseService=Kies een dienst van IP-controle uit de lijst hieronder ipCheckerWizard.explanations=Je kan deze wizard gebruiken, om uit te vinden wat je externe IP adres is. Als je IP adres dynamisch is, raden we je aan dat je een een account opend bij een Dynamic DNS Service. Enkele van deze diensten zijn hieronder aangegeven, gebruik de link om een account te maken (waar mogelijk). Vul vervolgens het IP adres veld met je dynamische hostnaam (bijv: myhostname.dyndns.org). Je hebt een programma om automatisch je Dynamic DNS Service te updaten met je IP adres. Op die manier, kan je torrents hosten, zelfs als je IP veranderd. ipCheckerWizard.service.description=Omschrijving : ipCheckerWizard.service.url=Verwijzing : ipCheckerWizard.progresstitle=IP controleren ipCheckerWizard.checkComplete=Afgerond IP : ipCheckerWizard.checkFailed=Fout, reden : wizard.tracker.local=Gebruik Vuze ingebouwde tracker wizard.tracker.external=Gebruik een externe tracker wizard.tracker.howToLocal=\tGa naar 'Konfiguraasje->Tracker' om het in te schakelen wizard.announceUrl=Mededelings-URL: IPChecker.external.httpinvalidresponse=Ongeldig HTTP antwoord IPChecker.external.loadingwebpage=Webpagina laden IPChecker.external.analysingresponse=Reactie analiseren IPChecker.external.addressextracted=IP adres gevonden IPChecker.external.httploadfail=Pagina laden mislukt IPChecker.external.timeout=Timeout opgetreden IPChecker.external.ipnotfound=IP-adres niet gevonden ConfigView.section.tracker.pollintervalmin=Minimum ConfigView.section.tracker.pollintervalmax=Maximum ConfigView.section.tracker.pollintervalincby=Ophogen met ConfigView.section.tracker.pollintervalincper=Iedere 'n' Cli\u00ebnten splash.loadingImages=Afbeeldingen Laden splash.initializeGui=Initialiseren Hoofdvenster splash.openViews=Openen van Schermen splash.plugin=Plugin wordt geladen : configureWizard.nat.tooManyPorts=Te veel poorten om te testen (9 max) ConfigView.section.color=Kleurschema MyTorrentsView.menu.publish=&Publiceren... MyTrackerView.status.published=Gepubliceerd MyTrackerView.completed=Dien MainWindow.menu.file.open.torrentnodefault=.torrent-triem (Gjin standertopslach) wizard.comment=Kommentear ConfigView.label.movetorrent=Verplaats .torrent ConfigView.section.file.decoder.label=Standaard torrentcodering wanneer selectie nodig is ConfigView.section.file.decoder.nodecoder=Gjin ConfigView.section.tracker.publicenable=Externe torrents toestaan ConfigView.label.playdownloadspeech=Geef met spraak aan wanneer een download voltooid is ConfigView.label.playdownloadspeech.info=De spraakservice werkt momenteel het beste met Engels # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Laat het aantal beschikbare kopie\u00ebn zien van ieder deel.\nAls het nummer rechts kleiner dan 1 is, dan zie je geen volledige kopie van het bestand (en kan je problemen hebben bij het voltooien van de download). GeneralView.label.trackerurl.tooltip=Klik om de URL naar het klembord te kopieren GeneralView.label.trackerurlopen.tooltip=Klik om de hoofdpagina van de tracker te openen # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Update GUI iedere ConfigView.section.style.graphicsUpdate=Update Grafische balken iedere N GUI update(s) ConfigView.section.style.reOrderDelay=Deel tabellen iedere N GUI update(s) opnieuw in [0: nooit] ConfigView.section.style.reOrderDelay.never=Nooit ConfigView.section.logging=Registrearje ConfigView.section.logging.enable=Schakel logbestand in ConfigView.section.logging.logdir=Map logtriem ConfigView.section.logging.choosedefaultsavepath=Kies de opslagmap GeneralView.label.updatein.querying=dwaande... configureWizard.nat.sharePort=Gebruik een enkele gedeelde poort voor alle torrents ConfigView.section.logging.maxsize=maksimale grutte fan logtriem ConfigView.section.tracker.passwordenableweb=Schakel trackerweb wachtwoord in ConfigView.section.tracker.passwordenabletorrent=Wachtwurd ynskeakelje ConfigView.section.tracker.username=Br\u00fbkersnamme ConfigView.section.tracker.password=Wachtwurd columnChooser.title=Kolommen selektearje columnChooser.move=Sleep rijen om ze opnieuw in te delen columnChooser.apply=Tapasse columnChooser.columnname=Kolomnamme columnChooser.columndescription=Beskriuwing TableColumn.header.shareRatio=Deelverhouding MyTorrentsView.menu.editTableColumns=Selecteer kolommen wizard.operationfailed=Operatie mislukt authenticator.title=Authenticatie benodigd authenticator.realm=Domein authenticator.user=Br\u00fbkersnamme authenticator.password=Wachtwoord ConfigView.label.allowSendVersion=Geef Vuze toestemming om anoniem het versienummer en een willekeurig ID door te geven bij het zoeken naar een nieuwe versie wizard.hint.mode=Hint:\tJe kunt een enkele map of bestand op deze wizard slepen \n\tom een map of bestand te kiezen wizard.hint.file=Hint:\tJe kunt enkel bestand kiezen door te slepen wizard.hint.directory=Hint:\tJe kunt een enkele map kiezen door te slepen MainWindow.menu.help.checkupdate=&Controleer of er een nieuwe versie is TableColumn.header.down=Oerhelje TableColumn.header.up=Ge\u00fcpload ConfigView.section.tracker.passwordenabletorrent.info=Hier is een goede Bittorrent-client voor nodig (zoals Vuze ConfigView.section.style.confirmationOnExit=Laat bevestigingsvenster zien bij afsluiten MainWindow.dialog.exitconfirmation.title=Vuze be\u00ebinigje? MainWindow.dialog.exitconfirmation.text=Vuze be\u00ebinigje? SystemTray.menu.stopalltransfers=Stop &Alle Overdrachten TrayWindow.menu.stopalldownloads=Alle oerhellings stopje ConfigView.section.tracker.sslport.info=Zie de FAQ voor meer informatie wizard.tracker.ssl=Gebruik SSL ConfigView.label.playdownloadfinished=Speel een geluid af wanneer een download voltooid is TableColumn.header.pieces=Stukjes TableColumn.header.pieces.info=Grafische balk vertegenwoordigt welke delen je hebt gedownload TableColumn.header.completion=Oanfolje TableColumn.header.completion.info=Grafische vertegenwoordiging van % gedownload ConfigView.section.style.showdownloadbasket=Laat Downloadmand zien (Sleep-en-plaats .torrents) ConfigView.section.style.alwaysShowTorrentFiles=Laat altijd Torrent bestanden zien in Details/Bestanden wizard.multitracker=Voeg multitracker-informatie aan de torrent toe wizard.multitracker.title=Multitracker wizard.multitracker.configuration=Configuratie multitracker wizard.multitracker.new=Nij... wizard.multitracker.edit=Bewerken.. wizard.multitracker.delete=Verwijderen wizard.multitracker.group=Trackergroep wizard.multitracker.edit.title=Multitracker-bewerker wizard.multitracker.edit.name=Namme wizard.multitracker.edit.save=Opslaan wizard.multitracker.edit.newgroup=Nije Groep wizard.multitracker.edit.deletegroup=Verwijderen wizard.multitracker.edit.newtracker=Nije Tracker wizard.multitracker.edit.deletetracker=Verwijderen wizard.multitracker.edit.edit=Bewerken wizard.addingmt=Voeg multitracker-informatie toe wizard.multitracker.noannounce=Mededelings-URL staat niet op je trackerlijst MyTorrentsView.menu.recheck=Forceer hercontrole iconBar.showDownloadBar.tooltip=Laat Downloadbalk zien iconBar.remove.tooltip=Wisse iconBar.openNoDefault.tooltip=.torrent-bestand iepenje (gjin standertopslach) iconBar.openURL.tooltip=URL iepenje iconBar.openFolder.tooltip=Map iepenje iconBar.new.tooltip=Torrent meitsje iconBar.up.tooltip=Omheech iconBar.down.tooltip=Omleach iconBar.run.tooltip=Iepenje iconBar.publish.tooltip=\u00datjaan MyTorrentsView.menu.editTracker=Bew&erk Tracker-URL('s) GeneralView.menu.selectTracker=Selektearje ConfigView.section.stats.xslfile=XSL-bestandsnaam ConfigView.section.stats.xslfiledetails=Deze wordt opgenomen in de header van het statistiekenbestand\nvia de tag ConfigView.label.savetorrentbackup=Sla reservekopie op ConfigView.section.tracker.forceport=Forceer gehoste externe torrents naar standaard poort ConfigView.section.ipfilter.allow=TOESTAAN van deze gebieden (standaard is WIJGEREN) ConfigView.section.ipfilter.list.inrange=zat binnen het gebied ConfigView.section.ipfilter.list.notinrange=zat niet binnen een gebied ConfigView.section.ipfilter.list.title=Lijst geblokkeerde IP's ConfigView.label.allowsameip=Meerdere verbindingen van het zelfde IP toestaan ConfigView.label.allowsameip.tooltip=Alleen aanvinken indien NODIG.\nDit is een leecher bescherming (indien uitgeschakeld). ManagerItem.superseeding=Super-Seeden ConfigView.label.userSuperSeeding=Gebruik Super-Seeding PeersView.uniquepiece=Deeltje (Super-Seedmodus) PeersView.uniquepiece.none=Gjin PeersView.timetosend=Tijd tot het opnieuw versturen van stukje (Super-Seed Modus) ConfigView.section.style.addurlsilently=URL stil openen (zonder dialoog) ConfigView.section.style.addurlsilently.tooltip=Let op: het hoofdvenster kan niet weer zichtbaar worden gemaakt na activatie!\nIndien je het systeemicoon verliest zul je deze optie moeten uitzetten. ConfigView.section.file.decoder.prompt=Altyd freegje as in nije \u00fbntsifering beskikber is ConfigView.section.file.decoder.prompt.tooltip=Altyd in fenster sjin litte as in \u00fbntsifering beskikber is MyTorrentsView.menu.moveTop=Verplaats naar &top MyTorrentsView.menu.moveEnd=Verplaats naar &bodem ConfigView.label.moveonlyusingdefaultsave=alleen als in standaard gegevensmap ConfigView.label.moveonlyusingdefaultsave.tooltip=Alleen verplaatsen als de gedownloade data zich in de standaard data map bevind ConfigView.label.watchtorrentfolder=Importeer automatisch nieuwe torrents ConfigView.label.watchtorrentfolder.tooltip=Zoekt regelmatig naar nieuwe .torrents ConfigView.label.watchtorrentfolderinterval=Tussenpauze ConfigView.label.watchtorrentfolderinterval.tooltip=De pauze tot de map opnieuw gescand wordt ConfigView.dialog.choosewatchtorrentfolderpath=Kies de .torrent import map ConfigView.label.startwatchedtorrentsstopped=Begin gestopt ConfigView.label.startwatchedtorrentsstopped.tooltip=Voeg nieuwe torrents toe met als status GESTOPT ConfigView.section.plugins=Plugins wizard.maketorrent.filesize=Grutte fan triem(en) wizard.maketorrent.piececount=Aantal stukjes wizard.maketorrent.piecesize=Grootte stukjes wizard.maketorrent.auto=Automatisch MainWindow.menu.view.stats=&Statistieken SpeedView.title.full=Activiteit SpeedView.downloadSpeed.title=Downloadsnelheid SpeedView.uploadSpeed.title=Uploadsnelheid ConfigView.section.style.useSIUnits=Gebruik IEC-eenheden (KB -> KiB enz.) iconBar.top.tooltip=Verplaats naar top iconBar.bottom.tooltip=Ferpleatse nei \u00fbnder TableColumn.header.health=Status MyTorrentsView.menu.health=Statusinformatie health.explain.grey=betekent dat je torrent niet uploadt of downloadt health.explain.red=betekent dat je niet met een peer bent verbonden tijdens downloaden health.explain.blue=bij uploaden betekent dit dat je niet met een peer bent verbonden\nbij downloaden betekent dit dat je wel verbonden bent met een aantal peers, maar dat de tracker niet verbonden is health.explain.yellow=betekent dat de tracker goed is, je met peers verbonden bent, maar dat je geen verbinding op afstand hebt.\nJe kan een NAT-probleem hebben als de torrents altijd geel blijven. health.explain.green=betekent dat alles goed is. ConfigView.section.style.alwaysRefreshMyTorrents=Mijn Torrents altijd opnieuw laden ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Deze optie ververst Mijn Torrent scherm, ook als het venster niet weergegeven wordt (handig voor enkele mIRC-plugins) # #2.0.7.0 # security.certtruster.title=Beveiligings Certificaat Waarschuwing security.certtruster.intro=Het beveiligings certificaat is vrijgegeven door een bedrijf dat je niet vertrouwd security.certtruster.resource=Bron: security.certtruster.issuedto=Vrijgegeven aan: security.certtruster.issuedby=Vrijgegeven door: security.certtruster.prompt=Wil je het vertrouwen? security.certtruster.yes=Ja security.certtruster.no=Nee ConfigView.section.tracker.torrentsperpage=Maximum aantal torrents per pagina? [0: ongelimiteerd] MainWindow.menu.file.share=Dielen MainWindow.menu.file.share.file=Triem... MainWindow.menu.file.share.dir=Map... MainWindow.menu.file.share.dircontents=Mapinhoud... MainWindow.menu.file.share.dircontentsrecursive=Mapinhoud (&Recursief) MainWindow.dialog.share.sharefile=Selecteer het te delen bestand MainWindow.dialog.share.sharedir=Selecteer de te delen map MainWindow.dialog.share.sharedircontents=Selecteer de te delen mapinhoud MainWindow.dialog.share.sharedircontents.recursive=Recursief globalmanager.download.remove.veto=Verwijderingsactie geweigerd plugin.sharing.download.remove.veto=Deze download is het resultaat van een gedeelde bron.\nOm te verwijderen, verwijder de bijbehorende gedeelde bron: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Hoofd ConfigView.section.tracker.web=Web ConfigView.label.prioritizefirstpiece=Geef het eerste deel van bestand(en) voorrang ConfigView.label.prioritizefirstpiece.tooltip=Probeert het eerste deel van een bestand eerst te downloaden.\nOm previews te ondersteunen. ConfigView.section.file.confirm_data_delete=Bevestig het verwijderen van gegevens ConfigView.section.file.confirm_data_delete.tooltip=Bevestig het verwijderen van gegevens bij het gebruik van 'Verplaats en Verwijder...' TrayWindow.menu.startalldownloads=Alle oerhellings starten SystemTray.menu.startalltransfers=Start Alle Overdrachten sharing.progress.title=Voortgang van het Delen sharing.progress.hide=Verbergen MainWindow.menu.view.myshares=Myn dielde boarne MySharesView.title.full=Myn dielde boarne MySharesView.name=Namme MySharesView.type=Type MySharesView.type.file=Triem MySharesView.type.dir=Map MySharesView.type.dircontents=Mapinhoud MySharesView.type.dircontentsrecursive=Mapinhoud (recursief) MySharesView.menu.remove=Fuortsmite ConfigView.section.tracker.extensions=Ekstensjes ConfigView.section.tracker.sendpeerids=Zend peer identiteit naar downloaders ConfigView.section.tracker.enableudp=Activeer UDP tracker protocol plugin.sharing.torrent.remove.veto=Deze download is het resultaat van een gedeelde bron.\nOm te verwijderen, verwijder de bijbehorende gedeelde bron: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Deze download kan niet verwijderd worden omdat deze niet gestopt is plugin.sharing.remove.veto=Deze deling is een sub-deling van een gedeelde 'map inhoud' en kan expliciet niet worden verwijderd.\n Verwijder de hoofd deling. GeneralView.label.hash.tooltip=Klik om de hash naar het klembord te kopieren ConfigView.section.tracker.maxpeersreturned=Maximum downloaders teruggekregen [0: ongelimiteerd] ConfigView.label.serverport=Inkomende luisterende TCP-poort configureWizard.nat.server.tcp_listen_port=Inkomende TCP luister poort ConfigView.section.sharing=Diele ConfigView.section.sharing.usessl=Gebruik SSL voor gedeelde bronnen (vereist Tracker configuratie) ConfigView.section.style.dropdiraction='Sleep-en-plaats' actie voor mappen ConfigView.section.style.dropdiraction.opentorrents=Open Torrents ConfigView.section.style.dropdiraction.sharefolder=Deel map ConfigView.section.style.dropdiraction.sharefoldercontents=Deel inhoud # # 2.0.7.x # Categories.all=Alle Categories.uncategorized=Ongecategoriseerd CategoryAddWindow.message=Nije kategorynamme CategoryAddWindow.title=Nije kategory tafoegje ConfigView.label.autoSeedingIgnoreInfo=Negeerde torrents gaan naar de bodem van de upload rij.\nZe starten niet automatisch.\nNegeerde regels zijn niet van toepassing op torrents die de eerste Prioriteit criteria hebben.\nTenzij anders aangegeven, gebruik een waarde van 0 om de regel uit te schakelen. ConfigView.label.directory=Map ConfigView.label.disconnetseed.tooltip=Wanneer je een torrent aan het uploaden bent, verbreek de verbinding met cli\u00ebnts die ook aan het uploaden zijn.\nZe hoeven niet met je te communiceren. ConfigView.label.ignoreCase=Negeer Hoofdletters ConfigView.label.ignoreSeeds=Negeer torrents met tenminste ConfigView.label.importdirectory=Importeermap ConfigView.label.minPeersToBoostNoSeeds.tooltip=Alle torrents zonder uploaders en minder downloaders dan je specifiseerd\ngaan naar de bodem van de wachtrij. ConfigView.label.minPeersToBoostNoSeeds=Verlaag Uploadrang voor torrents zonder uploaders en minder dan ConfigView.label.minSeedingTime.tooltip=Positie kan snel wisselen in een korte tijd, waardoor torrents soms automatisch worden gestart om daarna direct te stoppen en in de wachtrij gezet te worden.\nDit verlicht het probleem door de torrent te dwingen om een bepaalde tijd te blijven uploaden. Je kunt het handmatig stoppen als je dit wil. ConfigView.label.minSeedingTime=Minimale uploadtijd in seconden ConfigView.label.minSpeedForActiveDL.tooltip=Een download slot wordt altijd voor de eerste 30 seconden\ngebruikt na het starten van een onvolledige torrent. ConfigView.label.minSpeedForActiveDL=Torrent gebruikt geen downloadslot als de snelheid lager is dan ConfigView.label.peers=downloaders ConfigView.label.queue.debuglog=Sla foutopsporingsinformatie op ConfigView.label.queue.debuglog.info=Voeg foutopsporingsgegevens van de wachtrij toe aan het logbestand (console).\nHoewel cryptisch, de foutopsporingsgegevens geven informatie over de status van de torrents en waarom ze wel of niet starten of in de wachtrij komen. ConfigView.label.queue.minQueueingShareRatio=Stop en zet torrents niet in de wachtrij tenzij de deel factor is bereikt ConfigView.label.ratio=verhouding ConfigView.label.removeOnStop=Verwijder torrent uit lijst wanneer de torrent automatisch gestopt wordt ConfigView.label.savedirectory=Opslagmap ConfigView.label.seeding.autoReposition.tooltip=Wanneer ingeschakeld, de volgorde van de torrents (de '#'-kolom) wordt veranderd op basis van de Uploadwaarde\nDit is handig wanneer je Uploadwaardenummers niet gebruikt, maar wel wilt weten in welke volgorde de voltooide torrents starten. ConfigView.label.seeding.autoReposition=Automatische repositionering van torrents gebaseerd op de Uploadwaarde ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Vaak betekenen torrents met weinig uploaders en veel downloads, dat er waarschijnlijk geen volledige kopie onder de downloaders is.\nHierdoor, wil je misschien niet dat de upload regels doen alsof er er een volledige kopie is (en daardoor de waarde onterecht verlagen) ConfigView.label.seeding.fakeFullCopySeedStart=maar alleen voor torrents met minstens ConfigView.label.seeding.ignore=Negeerregels ConfigView.label.seeding.ignore0Peers=Negeer torrents met 0 downloaders ConfigView.label.seeding.ignoreRatioPeers=Negeer torrents die minstens 1 upload voor iedere ConfigView.label.seeding.ignoreShareRatio=Negeer torrents die een deel factor hebben van ConfigView.label.seeding.ignore.header.evenFirstPriority=Negeer torrent zelfs als\nEerste Prioriteit regel van toepassing is ConfigView.label.seeding.ignore.header.rule=Regel ConfigView.label.seeding.ignore.header.value=Waarde ConfigView.label.seeding.firstPriority.info=Torrents met de Eerste Prioriteit worden altijd boven in de rij gezet.\nAlle torrents die de Eerste Prioriteit criteria hebben, worden niet automatisch gestopt or in de wachtrij gezet.\nEen torrent die de Eerste Prioriteit criteria heeft, krijgt een Stimulerend Download slot wanneer nodig. ConfigView.label.seeding.firstPriority=Eerste prioriteit gaat naar torrents met ConfigView.label.seeding.firstPriority.following=van de volgende kenmerken: ConfigView.label.seeding.firstPriority.shareRatio=Een Deel factor onder ConfigView.label.seeding.firstPriority.seedingMinutes=Een verlopen tijd sinds het veranderen van downloaden naar uploaden van ConfigView.label.seeding.firstPriority.DLMinutes=Een verlopen tijd sinds het starten van downloaden van ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Door te doen alsof er 1 volledig kopie per X peers is, verlaag je de waarde van torrents met een hoog aantal uploads.\nMeestal hebben torrents met veel uploads veel verkeer.\nDit veranderd niets aan '# van uploads'. ConfigView.label.seeding.numPeersAsFullCopy=Doe alsof er 1 volledige kopie voor iedere\n(0 : Geen Pretendering) ConfigView.label.seeding.preferLargerSwarms.tooltip=Als je hoofdzakelijk torrents upload met downloaders die "vast zitten", een hogere prioriteit geven aan grote zwermen is dan logisch\nWanneer je hoofdzakelijk torrents upload met een hoge toegankelijkheid, dan is het logische om de prioriteit te geven aan kleine zwermen. ConfigView.label.seeding.preferLargerSwarms=Geeft hogere prioriteit aan grote zwermen, wanneer torrents de zelfde waarde hebben. ConfigView.label.seeding.rankType.none.tooltip=Volgorde gebaseerd op # kolom ConfigView.label.seeding.rankType.none=Geen ConfigView.label.seeding.rankType.peerSeed.options=Uploaders:Downloaders Verhouding Opties ConfigView.label.seeding.rankType.peerSeed.tooltip=Hogere Verhouding = Hogere Waarde ConfigView.label.seeding.rankType.peerSeed=Downloaders:Upload Verhouding ConfigView.label.seeding.rankType.seed.fallback=Terugvallen naar Downloaders:Uploaders na\n(0: Nooit Terugvallen) ConfigView.label.seeding.rankType.seed.options=Alleen Upload-Aantal Opties ConfigView.label.seeding.rankType.seed.tooltip=Minder Uploads = Hogere Waarde ConfigView.label.seeding.rankType.seed=Alleen Upload Aantal ConfigView.label.seeding.rankType.timedRotation.tooltip=Alle Complete torrents in de wachtrij roteren naar upload modus.\nTijdsduur van uploaden is ingesteld door 'Minimale Upload Tijd' ConfigView.label.seeding.rankType.timedRotation=Getijde Rotatie ConfigView.label.seeding.rankType.tooltip=Torrents met de hoogste waarde starten automatisch.\nWanneer een andere torrent een hogere warde krijgt, de torrent met een lagere waarde stopt en gaat terug in de wachtrij.\n\nAlleen torrents in een wachtrij kunnen automatisch starten.\nTorrents die gestopt zijn starten nooit automatisch. ConfigView.label.seeding.rankType=Waarde complete torrents voor auto-starten gebaseerd op: ConfigView.label.stopAfterMinutes=Wanneer overgeschakeld naar uploaden, stop na een tijd van ConfigView.label.switchpriority.tooltip=Lage prioriteit verminderd de hoeveelheid bandbreedte die een torrent kan gebruiken. ConfigView.pluginlist.info=De volgende plugins zijn ge\u00efdentificeerd. Sommige plugins hebben mogelijk geen configuratie tabs. ConfigView.pluginlist.noplugins=Er zijn geen plugins gevonden. ConfigView.section.queue.seeding=Zenden ConfigView.section.queue.seeding.autoStarting=Start Automatisch ConfigView.section.queue.seeding.ignore=Negeer Regels ConfigView.section.queue.seeding.firstPriority=Eerste Prioriteit ConfigView.section.queue.main=Hoofd ConfigView.section.queue=Wachtrige ConfigView.section.torrents=Torrents ConfigView.text.all=alle ConfigView.text.hours=oeren ConfigView.text.ignoreRule=Regel negearje ConfigView.text.ignore=Negearje ConfigView.text.minutes=minuten op ConfigView.text.neverIgnore=Nea negearje ConfigView.text.any=ien DownloadManager.error.datamissing=\u00dbntbrekkende data MainWindow.menu.file.open.torrentforseeding=.torrent-triem (Foar seeding) MainWindow.menu.language.refresh=F&ernije ManagerItem.forced=Geforceerd ManagerItem.queued=In de wachtrij MySeedersView.header=Torrents dy't klear binne TableColumn.header.availability.info=# volledige kopie\u00ebn te zien TableColumn.header.availability=Beskikberheid TableColumn.header.category=Kategory MyTorrentsView.header=Ynkomplete torrents TableColumn.header.maxuploads=Max aantal uploads MyTorrentsView.menu.category.delete=Kategory fuortsmite MyTorrentsView.menu.forceStart=&Forceer Start MyTorrentsView.menu.queue=Wachtrij MyTorrentsView.menu.setCategory.add=K&ategory tafoegje... MyTorrentsView.menu.setCategory=Kategory TableColumn.header.savepath=Opslachpaad TableColumn.header.SeedingRank=Uploadwaarde TableColumn.header.totalspeed.info=Totale Snelheid van alle downloaders waarmee je verbonden bent TableColumn.header.totalspeed=Totale Snelheid splash.initializePlugins=Initialiseren Plugins StartStopRules.0Peers=0 Uploaders StartStopRules.numSeedsMet=# Uploads OK StartStopRules.ratioMet=Downloaders:Upload OK StartStopRules.shareRatioMet=Deel Factor Ok StartStopRules.waiting=Wachten StartStopRules.firstPriority=1e Prioriteit ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Deel Inhoud (Recursief) DownloadManager.error.unabletostartserver=Kan server niet starten - controleer de configuratie van de inkomende poort en of Vuze in de firewallinstellingen als server uitgevoerd mag worden GeneralView.label.creationdate=Meitsje op: ConfigView.section.tracker.announcescrapepercentage=Deel tussenpauze als %leeftijd van meededeling\nzoals 200 = 2:1. 0 = laat peer beslissen ManagerItem.stopping=Wurd stopt ConfigView.section.tracker.announcecacheperiod=Deel cache mee iedere (millis) ConfigView.section.tracker.scrapecacheperiod=Deeltjes cache periode (millis) ConfigView.section.tracker.scrapeandcache=Deeltjes en cache ConfigView.section.tracker.announcecacheminpeers=Deel cache peer drempelwaarde mee MyTrackerView.scrapes=Dieltsjes fileDownloadWindow.retry=Opnij probearje MyTrackerView.bytesin=Bytes yn MyTrackerView.bytesinave=Gemiddeld inkomend MyTrackerView.bytesout=Bytes uitgaand MyTrackerView.bytesoutave=Gemiddelde uitgaand ConfigView.section.file.max_open_files=Maximum aantal geopende bestanden voor lezen/schrijven\n[0: ongelimiteerd] ConfigView.section.file.max_open_files.tooltip=Handing als je torrents download met honderden/duizenden bestanden, en je het maximaal aantal bestanden dat je besturingssysteem kan verwerken hebt bereikt. ConfigView.section.proxy=Proxy-ynstellings ConfigView.section.proxy.enable_proxy=Proxy br\u00fbken ConfigView.section.proxy.port=Poarte ConfigView.section.proxy.username=Br\u00fbkersnamme ConfigView.section.proxy.password=Wachtwurd ConfigView.section.proxy.enable_socks=Ik heb een SOCKS proxy wizard.createtorrent.extrahashes=Voeg hashes voor andere netwerken toe (zoals Gnutella2, eDonkey2000) GeneralView.label.connected=Ferbine GeneralView.label.in_swarm=yn zwerm ManagerItem.initializing=Initialiseren AlertMessageBox.error=Fout AlertMessageBox.warning=Waarschuwing AlertMessageBox.comment=Ynformaasje AlertMessageBox.information=Ynformaasje SharedPortServer.alert.selectorfailed=Gefaald een listener voor inkomende data te maken.\nControleer je firewall instellingen en geef java(w).exe toestemming om zich te gedragen als 'server' Tracker.alert.listenfail=Aanmaken van luisterende poort %1 is mislukt.\nControleer of geen andere applicaties deze poort gebruiken.\nControleer ook of er een andere kopie van Vuze draait. DiskManager.alert.movefileexists=Fout bij verplaatsen voltooide bestanden\nBestand %1 bestaat al in de doelmap DiskManager.alert.movefilefails=Fout bij verplaatsen voltooide bestanden\nVerplaatsen van bestand %1 is mislukt, %2 DiskManager.alert.movefilerecoveryfails=Fout bij terughalen na mislukte verplaatsing\nTerughalen van bestand %1 is mislukt, %2 ConfigView.section.tracker.logenable=Log periodische statistieken naar 'tracker.log' SpeedView.stats.title=Statistieken SpeedView.stats.total=Totaal SpeedView.stats.session=Deze Sessie SpeedView.stats.downloaded=Gedownload SpeedView.stats.uploaded=Ge\u00fcpload SpeedView.stats.uptime=Online Tijd (uren) AutoMigration.useralert=Vuze configuratiebestanden en -mappen auto-migratieresultaat:\n\n%1\nAlle gefaalde bestanden moeten handmatig worden gemigreerd.\nVERGEET NIET JE OPSLAGPAD BIJ TE WERKEN IN JE CONFIGURATIE NA DE MIGRATIE! # # > 2.0.8.0 # OpenTorrentWindow.title=Torrent(s) iepene OpenTorrentWindow.message=Experimenteel OpenTorrentWindow.addFiles=Voeg Best&anden toe: OpenTorrentWindow.dataLocation=Lokatie om gegevens op te slaan: OpenTorrentWindow.startMode=Voeg Modus toe OpenTorrentWindow.startMode.queued=Yn wachtrige OpenTorrentWindow.startMode.stopped=\u00d4fbrutsen OpenTorrentWindow.startMode.forceStarted=Forceer Gestarte OpenTorrentWindow.addPosition=Wachtrijpositie OpenTorrentWindow.addPosition.first=Earste OpenTorrentWindow.addPosition.last=L\u00easte TableColumn.header.remaining.info=Hoeveelheid te downloaden gegevens TableColumn.header.remaining=Te gean ConfigView.section.tracker.enablecompact=Zet compact mededelings protocol aan ConfigView.section.tracker.enablekey=Zet doorgeven van sleutel aan de tracker aan voor verbeterde beveiliging ConfigView.section.file.perf=Prestaasje-opsjes ConfigView.section.file.perf.explain=Waarschuwing - onjuiste veranderingen aan deze parameters kunnen nadelige effecten op de downloadprestaties hebben. Opnieuw opstarten is nodig.\nAls je een "out of memory"-probleem hebt, overweeg dan het aantal verbindingen per torrent te limiteren (Zie overdrachtconfiguratie) ConfigView.section.file.max_open_files.explain=Het openen van te veel bestanden kan problemen opleveren met het besturingssysteem door te weinig bronnen voor bestandshandelingen. Dit limiteert het aantal tegelijk geopende bestanden. popup.error.hide=Verberg ConfigView.section.style.colorOverrides=Kleur instellingen ConfigView.section.style.colorOverride.progressBar=Voortgangs Balk ConfigView.section.style.colorOverride.error=Fout MainWindow.status.tooOld=is oud, update het a.u.b. ConfigView.section.style.colorOverride.warning=Waarschuwing ConfigView.section.style.colorOverride.altRow=Alternatieve rijen ConfigView.section.file.save.peers.enable=Sla peerverbindingen op voor snelle herverbinding ConfigView.section.file.save.peers.max=Maximaal aantal peers om op te slaan [0: ongelimiteerd] ConfigView.section.file.save.peers.pertorrent=foar elke torrent ConfigView.label.max_peers_per_torrent=Maximum aantal connecties per torrent [0: ongelimiteerd] ConfigView.label.max_peers_total=Maximum aantal connecties globaal [0: ongelimiteerd] ConfigView.section.style.colorOverrides.reset=Reset Kleur ConfigView.section.language.info=Wanneer ingeschakeld, wordt er op een update gecontroleerd tijdens het starten van Vuze ConfigView.section.language.enableUpdate=Schakel Web Update in ConfigView.section.language.UpdateNow=Nu Updaten! Button.revert=\u00dbngedien meitsje MyTorrentsView.menu.changeDirectory=Verander Gegevensmap GenericText.column=kolom MyTorrentsView.menu.thisColumn.remove=Verwijder Kolom MyTorrentsView.menu.thisColumn.toClipboard=Kopi\u00eber tekst naar Klembord TableColumn.header.secondsseeding=Upload-tijd TableColumn.header.secondsseeding.info=Tijdsduur dat je aan het uploaden bent. TableColumn.header.secondsdownloading=Download-Tijd TableColumn.header.secondsdownloading.info=Tijdsduur dat je aan het downloaden bent. ConfigView.section.tracker.udpversion=UDP Protocol Versie (1 of 2) window.updateswt.title=Je SWT-versie is te oud! window.updateswt.text=Je SWT-versie is te oud!\nSWT is de grafische bibliotheek die Vuze gebruikt, de versie die je hebt is te oud om de laaste Azureus-versie te draaien. Klik op OK om je SWT bij te werken. window.updateswt.failed=Update mislukt, druk opnieuw op OK om te herstarten. window.updateswt.status.downloading.updater=Downloaden van de bijwerkingsmodule window.updateswt.status.finding=Zoeken van de laatste SWT-versie window.updateswt.status.downloading=Downloaden van de laatste SWT-versie window.updateswt.status.done=Op 'e nij lade window.updateswt.cancel=Annuleren swt.updater.downloader.downloading=Downloaden SWT van swt.updater.urlsgetter.downloading=Een lijst met mirrors ophalen van swt.updater.urlsgetter.platform=SWT voor platform : window.updateswt.ignore=Negeer ConfigView.section.style.useFancyTabs=Gebruik Fancy Tabs splash.initializeGM=Initialiseren Globale Torrent Manager splash.loadingTorrents=Torrents Laden MyTorrentsView.menu.thisColumn.sort=&Sortearje Scrape.status.ok=Blok Ok. Scrape.status.error=Blok Fout: Scrape.status.error.badURL=Deel mee: URL volgt niet de blok specificaties. Scrape.status.error.nohash=Hash mist van antwoord. Scrape.status.error.invalid=Ongeldig antwoord. Scrape.status.nextScrapeAt=Volgende stukje op %1 Scrape.status.scraping=Opdelen.. Scrape.status.initializing=Wachten om op te delen ConfigView.label.minSpeedForActiveSeeding=Tel voltooide torrents niet mee als de snelheid lager is dan ConfigView.section.stats.exportpeers=Exporteer peer details MainWindow.menu.view.irc.moved=IRC is nu beschikbaar als een plugin, zie http://azureus.sourceforge.net/plugin_list.php. Wanneer geinstalleerd gebruik Plungins ->IRC menu om het te openen. MyTrackerView.webui.contextmenu.copyurl=Kopi\u00eber torrent-URL naar klembord ConfigView.section.file.torrent.ignorefiles=Bestanden om te negeren wanneer torrents gemaakt worden\nzoals: .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Negeer bestand ConfigView.section.style.useUnitsRateBits=Gebruik bits in plaats van bytes voor byte-gebaseerde waardes (KiB/s->Kibit/s enz.) ConfigView.section.interface.resetassoc=Bestandsassociaties (.torrent) opnieuw instellen ConfigView.section.interface.resetassocbutton=Weromsette ConfigView.section.interface.checkassoc=Controleer associaties tijdens opstarten dialog.associations.title=Associatiecontrole Button.yes=Ja Button.no=Nee ConfigView.label.seeding.autoStart0Peers=Start alle complete torrents met 0 uploaders automatisch ConfigView.label.seeding.autoStart0Peers.tooltip=Zet aan, als je wil dat de tracker altijd seeds geeft voor torrents zonder peers. dialog.associations.prompt=Vuze is niet de standaard applicatie voor BitTorent bestanden.\nWil je de Vuze met .torrent bestanden associ\u00ebren? dialog.associations.askagain=Controleer tijdens starten Plugin.pluginupdate.enablecheck=Zet plugin update controle aan plugins.basicview.activity=Activiteit: plugins.basicview.progress=Voortgang: ConfigView.label.maxdownloadspeed=Globale maximum downloadsnelheid in KB/s [0: ongelimiteerd] splash.loadingTorrent=Torrent Laden splash.of=van UpdateWindow.header=De volgede componenten hebben een update nodig : UpdateWindow.columns.install=Installeren UpdateWindow.columns.name=Naam UpdateWindow.columns.version=Versie UpdateWindow.columns.size=Grootte UpdateWindow.cancel=Annuleren UpdateWindow.quit=Afsluiten UpdateWindow.close=Sluiten UpdateWindow.restart=Herstarten UpdateWindow.status.downloading=Downloaden UpdateWindow.status.done=Voltooid UpdateWindow.status.failed=Mislukt UpdateWindow.status.restartNeeded=Herstarten is nodig! ConfigView.pluginlist.broken=Fout ConfigView.pluginlist.whereToPut=Plaats alle gebruikers-specifieke plugins in hun eigen directory onder: ConfigView.pluginlist.whereToPutOr=Gebruik voor gedeelde plugins: MainWindow.statusText.checking=Controleren op Updates TableColumn.header.OnlyCDing4=AlleenUploaden TableColumn.header.OnlyCDing4.info=Hoeveelheid tijd waarin de torrent alleen aan het uploaden was. Exclusief de tijd dat de torrent aan het downloaden was (en uploaden) ConfigView.section.style.alternateTablePainting=Gebruik alternatieve methode om grafische tabel colommen te tekenen (kan herstart nodig hebben) UpdateWindow.status.restartMaybeNeeded=Herstart kan nodig zijn ConfigView.pluginlist.shared=gedeeld PeersView.host=Hostnaam PeersView.host.info=De host naam van de downloader, wanneer beschikbaar (kan de prestaties be\u00efnvloeden) MainWindow.menu.help.whatsnew=Wat is nij ConfigView.label.checkonstart=Controleer op de laaste versie wanneer Vuze start ConfigView.label.periodiccheck=Controleer periodiek op laatste versie ConfigView.label.opendialog=Open automatisch de Update Assistent wanneer er een update beschikbaar is MainWindow.updateavail=(Fernije verzje beskikber) MainWindow.status.unofficialversion=Vuze B\u00e8ta MainWindow.status.latestversionunchecked=Versie controle uitgeschakeld GeneralView.label.updatein.stopped=\u00d4fbrekke StartStopRules.menu.viewDebug=Bekijk Debug Info ConfigView.section.style.doNotUseGB=Gebruik geen GB eenheid ConfigView.section.style.doNotUseGB.tooltip=Vuze zal, wanneer aangevinkt, de MB blijven gebruiken, zelfs als de grootte groter is dan 1024MB MainWindow.menu.help.plugins=Plugins ConfigView.section.tracker.enablecategories=Sorteer torrents op category health.explain.share=betekent dat de torrent niet gehost of gepubliseerd is ConfigView.section.tracker.createcert=Maak zelf-ondertekende certificatie ConfigView.section.tracker.createbutton=Meitsje security.certcreate.title=Maak Zelf-ondertekend Certificaat security.certcreate.intro=Deze dialoog laat je een zelf-ondertekend certificaat maken security.certcreate.strength=Sterkte security.certcreate.firstlastname=Voor en Achternaam security.certcreate.orgunit=Organisatie Eenheid security.certcreate.org=Organisatie security.certcreate.city=Stad of streek security.certcreate.state=Staat of Provincie security.certcreate.country=Twee-letter land code security.certcreate.ok=Maken security.certcreate.cancel=Annuleren security.certcreate.createok=Maken certificaat voltooid security.certcreate.createfail=Certificaat maken mislukt webui.passwordenable=Schakel password in webui.user=Gebruikersnaam webui.password=Wachtwurd webui.port=Poarte (*) webui.protocol=Protokol (*) webui.homepage=Start pagina (*) webui.rootdir=Hoofdmap (*) webui.rootres=Hoofdbron (*) webui.mode=Modus (*) webui.mode.info=Modus kan zijn:\n\t"volledig"\t= alle operaties zijn toegankelijk (standaard)\n\t"Kijken"= alleen bekijken (maar kan vaak vernieuwen) webui.access=Toegang (*) webui.access.info=Toegang kan zijn:\n\t"Locaal"\t= Alleen de locale machine kan verbinden\n\t"Alle"\t= Ongeregistreerde toegang (standaard)\n\tIP\t= zoals: 192.168.0.1\t\t1 IP tegelijk\n\tIP1-IP2\t= zoals: 192.168.0.1-192.168.0.255\teen reeks van IP's Security.keystore.corrupt=Gefaald de sleutelreeks '%1' te laden, verwijder het en maak/importeer het certificaat opnieuw Security.keystore.empty=Sleutelreeks is leeg. Maak een zelf-ondertekend certificaat (zie Configuratie->Beveiliging) of importeer een bestaand certificaat in '%1' webui.restart.info=Veranderen van parameters met een (*) hebben een herstart nodig om effect te hebben GeneralView.label.maxdownloadspeed.tooltip=Maximum download snelheid [0: ongelimiteerd] upnp.enable=Schakel UPnP in upnp.info=Universal Plug and Play (UPnP) maakt het mogelijk automatisch poorten te mappen op UPnP ingeschakelde routers. upnp.mapping.dataport=Inkomende Uploadpoort upnp.mapping.tcptrackerport=TCP-Trackerpoort upnp.mapping.udptrackerport=UDP-Trackerpoort upnp.alert.differenthost=UPnP: Mappen '%1' is gereserveerd door '%2' - selecteer een andere poort upnp.alert.mappingok=UPnP: Mappen '%1' ingesteld upnp.alert.mappingfailed=UPnP: Mappen '%1' mislukt upnp.alertsuccess=Successvol gemapt upnp.alert.lostdevice=UPnP: Verbinding verloren met service '%1' op UPnP apparaat '%2' upnp.grabports=Map poorten zelfs als deze in het bezit zijn van een andere computer upnp.refresh.label=Mappings ferfarskje upnp.refresh.button=Ferfarskje upnp.alert.mappinggrabbed=UPnP: Mappen '%1' ingesteld - verkregen van '%2' upnp.mapping.tcpssltrackerport=Poort voor TCP SSL Tracker upnp.alertothermappings=Rapporteer poorten die in het bezit zijn van andere computers upnp.alertdeviceproblems=Rapporteer problemen met het UPnP-apparaat ConfigView.pluginlist.coreplugins=De volgende ingebouwde plugins zijn geladen: Peers.column.DLedFromOthers=Van Anderen Peers.column.DLedFromOthers.info=Hoeveelheid gegevens gedownload van anderen terwijl die verbonden zijn met jou Peers.column.UpDownRatio=Up- en downloadverhouding Peers.column.UpDownRatio.info=Downloaders "Upload/Download"-verhouding Peers.column.UpRatio=Uploadverhouding Peers.column.UpRatio.info=Downloaders "Upload van jou : Ge\u00fcpload van anderen" verhouding upnp.releasemappings=Geef de mappings vrij en sluit af webui.upnpenable=Schakel UPnP voor deze poort in (*) ConfigView.section.file.friendly.hashchecking=Vriendelijke hashcontrole ConfigView.section.file.friendly.hashchecking.tooltip=Een stuk langzamer, maar zorgt voor minder belasting op de processor of het systeem, modus met hashcontrole van deeltjes. ConfigView.section.tracker.seedretention=Maximum aantal uploads per torrent beperken [0: ongelimiteerd] ConfigView.section.tracker.seedretention.info=Upload statistieken worden verloren voor niet-beperkte uploads ConfigView.section.tracker.port=Zet tracker op HTTP poort ConfigView.section.tracker.sslport=Zet tracker op HTTPS poort aan ConfigView.section.tracker.publicenable.info=Dit staat anderen toe om torrents te maken die jouw tracker gebruiken\nzonder dat jij ze host/publiceert Button.clear=Leechmeitsje MainWindow.IPs.tooltip=Laatste update van filterlijst: %1\nTotaal aantal IPFilters in lijst - Aantal geblokkeerde IP-adressen deze sessie\nDubbelklik voor details. ConfigView.section.ipfilter.list.banned=is verbannen voor het zenden van corrupte data ConfigView.section.ipfilter.list.baddata=heeft corrupte data gezonden: voorval = Button.reset=Op'e nij starte ConfigView.section.ipfilter.bannedinfo=IP's die corrupte data hebben gezonden - verbannen als het limiet is overschreden ConfigView.section.ipfilter.blockedinfo=IP's die zijn geblokkeerd door IP filters download.removerules.name=Verwijderregels download.removerules.unauthorised.info=Ongeautoriseerde torrents zijn torrents waar in de meegedeelde reactie\n"niet geautoriseerd" of "ongeautoriseerd" in de trackerstatus staat download.removerules.unauthorised=Verwijder ongeautoriseerde torrents automatisch. download.removerules.unauthorised.seedingonly=\tAlleen tijdens uploaden download.removerules.removed.ok=Automatisch verwijderen van torrent '%1' voltooid. Dit is uitgevoerd door de torrentverwijderregels. download.removerules.updatetorrents=Verwijder de torrents met updates voor Vuze indien de zwerm hierom vraagt ConfigView.label.defaultstarttorrentsstopped=Voeg torrents standaard in gestopte status toe ConfigView.section.server.enableudp=Zet UDP tracker cli\u00ebnt protocol aan. upnp.mapping.dataportudp=Cli\u00ebntpoort UDP-tracker ConfigView.section.file.decoder.showlax=Toon minder gebruikelijke coderingen ConfigView.section.file.decoder.showall=Overweeg alle mogelijke coderingen MainWindow.status.updowndetails.tooltip=Details up- en downloadsnelheid - klik met rechtermuisknop om te veranderen TrackerClient.announce.warningmessage=Tracker voor '%1' geeft waarschuwing '%2' ConfigView.section.tracker.natcheckenable=Controleer 'inkomende data poort' verbindingsmogelijkheid en rapporteer fouten aan de downloaders ConfigView.section.tracker.publishenabledetails=Publiceer torrentbestand en peer-details ConfigView.section.tracker.publishenablepeerdetails=Publiceer download details MyTrackerView.badnat=Ferrotte NAT MyTrackerView.badnat.info=Uploaders/Ontvangers die de NAT controlle hebben gefaald wanneer ingeschakeld ConfigView.section.tracker.natchecktimeout=Controle timeout (secs) ConfigView.section.file.perf.cache.enable=Schakel schijfcaching in ConfigView.section.file.perf.cache.size=Grutte fan cache yn %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=Oerdrachten MainWindow.menu.transfers.startalltransfers=St&art Alle MainWindow.menu.transfers.stopalltransfers=St&op Alle MainWindow.menu.transfers.pausetransfers=&Pauze MainWindow.menu.transfers.resumetransfers=T&rochgean ConfigView.label.experimental.osx.kernel.panic.fix=Experimentele oplossing voor kernel problemen op dual processor OSX systemen [heeft herstart nodig] SystemTray.menu.pausetransfers=Pauzeer Overdrachten SystemTray.menu.resumetransfers=Hervat Overdrachten ConfigView.section.file.truncate.too.large=Kap bestaande bestanden die te groot zijn af ConfigView.section.file.perf.cache.trace=Traceer cache-operaties voor diagnostische doeleinden ConfigView.section.interface.enabletray=Schakel Systeemvak in PeerManager.status.error=Flater Stats.title.full=Statistieken TransferStatsView.title.full=Gegevensoverdracht CacheView.general.size=Totale grutte CacheView.general.inUse=Yn gebr\u00fbk CacheView.general.title=Cache-ynformaasje CacheView.reads.title=I/O Leesbewerkingen CacheView.reads.fromFile=Fan triem CacheView.reads.fromCache=Van Cache CacheView.writes.title=I/O Schrijf bewerkingen CacheView.writes.toCache=Naar Cache CacheView.writes.toFile=Naar Bestand CacheView.writes.hits=Hits CacheView.speeds.title=Datasnelheid CacheView.speeds.reads=L\u00eaze CacheView.speeds.writes=Skriuwe CacheView.speeds.fromCache=Van/Naar Cache CacheView.speeds.fromFile=Van/Naar Bestand CacheView.reads.amount=Hoeveelheid CacheView.reads.avgsize=Gemiddelde Grootte openUrl.referrer=Verwijzing naar URL-pagina: openUrl.referrer.info=Alleen nodig voor websites die dit afdwingen ConfigView.label.maxuploadspeedseeding=Globale maximum uploadsnelheid wanneer er alleen wordt geupload in KB/s [0: ongelimiteerd] ConfigView.label.transfer.ignorepeerports=Negeer downloaders die de volgende poorten gebruiken (gescheiden met ';', zoals: 0;25) ConfigView.section.proxy.enable_socks.peer=Schakel proxy voor uploads in (Alleen uitgaande verbindingen) ConfigView.section.proxy.peer.informtracker=Informeer tracker over beperking ConfigView.section.proxy.socks.version=SOCKS-ferzje PiecesView.legend.written=Weggeschreven PiecesView.legend.requested=Aangevraagd PiecesView.legend.downloaded=Gedownload,\n nog niet weg geschreven PiecesView.legend.incache=Gegevens staan in buffer PiecesView.typeItem.0=Traach PiecesView.typeItem.1=Fluch Security.jar.tools_not_found=JAR ondertekening mislukt - 'tools.jar' niet gevonden in %1. Zie configuratie -> beveiliging voor details. Security.jar.signfail=JAR ondertekening mislukt - %1 ConfigView.section.security.toolsinfo=Ondertekende JAR bestanden worden gebruikt om sommige plugins zoals de Swing Web Interface (wanneer geconfigureerd) te ondersteunen.\nOm JAR bestanden te ondertekenen, is het nodig toegang te hebben tot het 'tools.jar' bestand.\nDit bestand komt met de Sun JDG (niet JRE) installatie.\nAls je alleen de JRE hebt ge\u00efnstalleerd moet je de JDK installeren.\nVuze kan dit bestand voor je vinden, als dit niet lukt, kan je hier alsnog de map aangeven. ConfigView.section.security.toolsdir=Map met 'tools.jar' ConfigView.section.security.choosetoolssavedir=Selecteer de map met 'tools.jar' ConfigView.section.proxy.peer.same=Gebruik voor trackers en downloaders dezelfde proxy-instellingen ConfigView.section.connection.network.max.simultaneous.connect.attempts=Maximum gelijktijdig uitgaande verbindingspogingen ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Maximum aantal nieuwe uitgaande verbindingen die Vuze op ieder moment kan maken.\n- Windows XP Service Pack 2 (SP2) bevat een limiet van 10 gelijktijdige verbindingspogingen over het hele systeem.\nStandaardwaarde is 5. ConfigView.section.file.perf.cache.size.explain=De cache wordt gebruikt om schijfactiviteit te verminderen. Tenzij je de optie '-XX:MaxDirectMemorySize' in Java gebruikt waarmee de beschikbaarheid van het gegheugen voor cache- en netwerkgebruik wordt ingesteld, moet deze waarde tenminste %1 onder de maximale grootte van het virtueel geheugen. De huidige maximumwaarde van het virtuele geheugen is %2. Zie MemoryUsage in de Wiki op %3 voor informatie over hoe dit veranderd moet worden. Indien deze opties niet juist ingesteld worden, zal dit tot geheugenfouten ('out of memory') leiden. Meer dan 32 MB aan cacheruimte is waarschijnlijk te veel. MyTorrentsView.menu.setSpeed.unlimit=Gjin limiet MyTorrentsView.menu.setSpeed.unlimited=Gjin limiet MyTorrentsView.menu.setSpeed.disable=Schakel Upload uit MyTorrentsView.menu.setSpeed.disabled=Uitgeschakeld MyTorrentsView.menu.setSpeed.in=yn MyTorrentsView.menu.setSpeed.slots=sloten van GeneralView.label.maxuploadspeed=Maks yn GeneralView.label.maxuploadspeed.tooltip=max upload snelheid [0 : ongelimiteerd] MyTorrents.items.UpSpeedLimit.disabled=Gjin oerbringst MyTorrents.items.UpSpeedLimit.unlimited=Gjin begrinzing TableColumn.header.maxupspeed=Max Up Snelheid TableColumn.header.maxupspeed.info=Max Uploadsnelheid per torrent ConfigView.section.file.perf.cache.enable.write=Downloadgegevens in cache; zowel het aantal schrijfbewerkingen als het aantal leesbewerkingen voor controle van stukjes wordt verkleind ConfigView.section.file.perf.cache.enable.read=Schakel vooruit-lezen in, om schijfactiviteit tijdens het uploaden te verminderen ConfigView.section.tracker.separatepeerids=Gebruik verschillende peer identiteiten voor tracker en data communicatie ConfigView.section.tracker.separatepeerids.info=Verhoog anonimiteit tijdens anoniem downloaden/uploaden\nterwijl je een niet-anonieme tracker verbinding gebruikt ConfigView.section.interface.wavlocation=Lokaasje fan .wav-triem ConfigView.section.interface.wavlocation.info=Selecteer .wav bestand of laat dit leeg voor het standaard geluid ConfigView.section.tracker.client=Cli\u00ebnt ConfigView.section.tracker.client.connecttimeout=Connectie timeout (secs) ConfigView.section.tracker.client.readtimeout=Lees timeout (secs) FilesView.path=Paad FilesView.fullpath=Hiel paad sjin litte FilesView.remaining=Stukjes te gaan TableColumn.header.trackername=Trackernaam TableColumn.header.trackername.info=Naam van de tracker gebaseerd op de meegedeelde URL ConfigView.group.override=Overbrugopties ConfigView.section.file.perf.cache.notsmallerthan=Triemen lytser as dit (yn %1) net yn cache bewarje PeersView.menu.blockupload=Blokupload PeersView.menu.kickandban=Verbinding verbreken en blokkeren PeersView.menu.kickandban.reason=Verbinding handmatig geblokkeerd PeersView.state=Status PeersView.state.info=Status van de verbinding van de uploader PeersView.state.pending=Bezig PeersView.state.connecting=Verbinding maken PeersView.state.handshake=Wachten op handshake PeersView.state.established=Volledig verbonden ConfigView.section.tracker.processinglimits=Verwerkingslimieten ConfigView.section.tracker.maxgettime=Maximale tijd voor de GET-verwerking (in sec) [0: ongelimiteerd] ConfigView.section.tracker.maxposttimemultiplier=GET-tijdvermenigvuldiging voor POST-verwerking [0: ongelimiteerd] ConfigView.section.tracker.maxposttimemultiplier.info=Worden gebruikt voor doorgeven van formulierinformatie en uploads ConfigView.section.tracker.maxthreads=Maximum aantal aanvragen tegelijkertijd DownloadManager.error.operationcancancelled=Aksje \u00f4fbrekke Torrent.create.progress.cancelled=Aksje \u00f4fbrutsen wizard.maketorrents.autoopen=De torrent voor uploaden gebruiken indien voltooid ConfigView.section.connection.advanced.mtu=Maximale overdrachtseenheid van de lijn (MTU) ConfigView.section.connection.advanced.SO_RCVBUF=Grootte van Socket SO_RCVBUF[0: gebruik standaard besturingssysteem] ConfigView.section.connection.advanced.SO_SNDBUF=Grotte Socket SO_SNDBUF [0: gebruik standaard besturingssysteem] ConfigView.section.interface.confirm_torrent_removal=Om befestiching freegje as in torrent fuortsmite wurdt ConfigView.section.interface.confirm_torrent_removal.tooltip=Om befestiching freegje as in torrent fuortsmite wurdt \u00fat it skerm MyTorrents MyTorrentsView.confirm_torrent_removal=Weet je zeker dat je deze torrent wilt verplaatsen?\n TableColumn.header.seed_to_peer_ratio=Naar uploader overgebracht TableColumn.header.seed_to_peer_ratio.info=Verhouding van totaal downloads naar uploaders in zwerm PeersView.connected_time=Verbindingsduur PeersView.connected_time.info=De totale tijd van de verbinding met de cli\u00ebnt ConfigView.section.interface.display.add_torrents_silently=Torrents op de achtergrond toevoegen ConfigView.section.interface.display.add_torrents_silently.tooltip=Torrents toevoegen zonder het hoofdscherm vna Vuze te openen. TableColumn.header.maxdownspeed=Max downloadsnelheid TableColumn.header.maxdownspeed.info=Max Downloadsnelheid per torrent ConfigView.section.tracker.passwordwebhttpsonly=Alleen toegang via HTTPS toestaan TableColumn.header.torrentpath=Torrentlokaasje TableColumn.header.torrentpath.info=Lokaasje fan de torrent op de hurde skyf ConfigView.label.openstatsonstart=Open Statistieken tijdens het staren installPluginsWizard.file.file=Triem: installPluginsWizard.file.browse=Bl\u00eadzje... uninstallPluginsWizard.title=Plug-ins verwijderen uninstallPluginsWizard.list.title=Lijst met ge\u00efnstalleerde plug-ins uninstallPluginsWizard.list.loaded=Selecteer de plug-ins die je wilt verwijderen uninstallPluginsWizard.finish.title=Bezig met verwijderen uninstallPluginsWizard.finish.explanation=De geselecteerde plug-ins worden verwijderd m.b.v. de Update-assistent MainWindow.menu.plugins.installPlugins=Installation Wizard MainWindow.menu.plugins.uninstallPlugins=Uninstallation Wizard update.instance.install=Installatie wordt gecontroleerd update.instance.uninstall=De\u00efnstallatie wordt gecontroleerd update.instance.update=Zoeken naar updates MainWindow.status.update.tooltip=Dubbelklik om de voortgang te zien updater.progress.window.title=Huidige installatietaken updater.progress.window.info=Klik op \u201eAnnuleren\u201d om alle uitgaande taken te annuleren Button.abort=\u00d4fbrekke Network.alert.acceptfail=Te veel achtereenvolgende mislukte pogingen op poort %1, %2: de verwerking is geannuleerd. Controleer de firewallinstellingen voor deze poort om er zeker van te zijn dat inkomende verbindingen toegestaan zijn. MyShares.column.category=Kategory MainWindow.menu.file.restart=Vuze opnieuw opstarten MainWindow.dialog.restartconfirmation.title=Vuze opnij opstarte? MainWindow.dialog.restartconfirmation.text=Vuze opnij opstarte? deletetorrent.message1=Je staat op het punt de TORRENT te verwijderen van:\n deletetorrent.message2=\nWolst trochgean? ConfigView.label.prioritizemostcompletedfiles=Prioriteer meest-voltooide bestanden ConfigView.section.tracker.nonblocking=Opties voor het niet blokkeren ConfigView.section.tracker.nonblockingconcmax=Maximum aantal aanvragen tegelijkertijd [0: ongelimiteerd] MyTorrentsView.menu.exportmenu=Exporteren MyTorrentsView.menu.explore=Triem sjin litten MyTorrentsView.menu.explore._mac=Yn Finder sjin litten MyTorrentsView.menu.explore._windows=Yn Verkenner sjin litten wizard.maketorrents.autohost=De torrent m.b.v. de ingebouwde tracker hosten ConfigView.label.overrideip=Negeer het verzenden van het IP-adres naar de tracker\n \u2013 Gebruik dit alleen als je echt weet waarom je het nodig hebt! ConfigView.label.overrideip.tooltip=Informeer de tracker van een ander IP adres dan het adres waar uitgaande pakketjes vandaan komen. Laat de optie leeg als je deze niet wil gebruiken. ConfigView.section.connection.group.networks=Netwurken ConfigView.section.connection.group.networks.info=Selecteer de standaard toegestane netwerken voor peer-to-peer gegevensoverdracht ConfigView.section.connection.networks.prompt=Vraag om selectie wanneer een download met anonieme tracker is toegevoegd ConfigView.section.connection.networks.Public=Iepenbier IP-netwurk (net anoniem) ConfigView.section.connection.networks.I2P=I2P-netwurk ConfigView.section.connection.networks.Tor=Netwurk foar de Onion Router (Tor) TableColumn.header.networks=Netwurken TableColumn.header.networks.info=Netwerken waarbij peer-peer-gegevenscommunicatie is toegestaan ConfigView.section.tracker.server.group.networks=Netwurken ConfigView.section.tracker.server.group.networks.info=Selecteer de netwerken welke de tracker als uploaders accepteert window.networkselection.title=Netwurkseleksje window.networkselection.description=Torrent: ConfigView.section.connection.group.peersources=Uploadboarne ConfigView.section.connection.group.peersources.info=Selecteer de standaard toegestane bronnen voor verbindingen van uploaders ConfigView.section.connection.peersource.Tracker=Van een tracker ConfigView.section.connection.peersource.DHT=Sintrale tracking ConfigView.section.connection.peersource.PeerExchange=Door een andere peer geleverd ConfigView.section.connection.peersource.Plugin=Toegevoegd door een plug-in ConfigView.section.connection.peersource.Incoming=Inkomende verbinding PeersView.source=Bron PeersView.source.info=De bron van deze uploader TableColumn.header.peersources=Uploadbronnen TableColumn.header.peersources.info=Uploadbronnen waarbij het maken van een verbinding met uploadverbindingen is toegestaan wizard.tracker.dht=Gedecentraliseerd (alleen voor gebruikers van Vuze MyTorrentsView.menu.advancedmenu=Geavanceerd MyTorrentsView.menu.networks=Netwurken MyTorrentsView.menu.peersource=Uploadbronnen PeersView.Messaging=Berichten PeersView.Messaging.info=Ondersteunt geavanceerde API-messaging ConfigView.label.queue.newseedsmovetop=Verplaats meest recentelijk voltooide torrents naar het begin van de uploadlijst ConfigView.section.tracker.sendjavaversionandos=Verstuur Javaversie en naam besturingssysteem MagnetPlugin.contextmenu.exporturi=Kopieer magneet-URI naar klembord dht.info=Deze plug-in ondersteunt o.a. decentrale tracking. Het uitschakelen hiervan zal het aantal downloadmogelijkheden verkleinen dht.enabled=Verspreide database inschakelen dht.portdefault=Standertpoarte br\u00fbke dht.port=UDP-poort van de database dht.execute.command=Diagnostische opdracht dht.execute.info=Klik op Uitvoeren om de opdracht uit te voeren dht.execute=\u00datfieren dht.logging=Activiteiten tracken inschakelen ConfigView.section.file.nativedelete._mac=Jiskefet br\u00fbken by fuortsmite triemen ConfigView.section.file.nativedelete._windows=Fuortsmite triemen nei jiskefet fersette ConfigView.section.logging.generatediagnostics=Genereren ConfigView.section.logging.generatediagnostics.info=Diagnostische informatie aanmaken en naar het klembord en logbestand kopi\u00ebren (indien ingesteld) MainWindow.menu.tools.nattest=&NAT/Firewalltest window.welcome.title=Wolkom by Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=\u00datjefte-opmerkingen dht.reseed.label=Het opnieuw uploaden van de verspreide database is normaal gesproken niet nodig. Indien het aantal contacten laag is, kan dit voor herintegratie handig zijn.\nLaat leeg om de database van verbonden peers te gebruiken of geef een IP-adres en poort op om de database van een bekende peer te gebruiken dht.reseed.group=Opnieuw uploaden dht.reseed.ip=IP-adres dht.reseed.port=Poarte dht.reseed=Opnieuw uploaden dht.reseed.info=Database opnieuw uploaden dht.diagnostics.group=Diagnose DHTView.title.full=Ferspreide databank DHTView.general.title=Algemien DHTView.general.users=Br\u00fbkers: DHTView.general.leaves=Verlitten: DHTView.general.contacts=Kontakten: DHTView.general.replacements=Ferfangings: DHTView.general.live=Aktief: DHTView.general.unknown=\u00dbnbekend DHTView.general.dying=Verlittend: DHTView.transport.title=Transportdetails DHTView.transport.packets=Pakketten: DHTView.transport.received=\u00dbntfangen: DHTView.transport.sent=Ferstjoerd: DHTView.transport.in=Ynkaam: DHTView.transport.out=Naar b\u00fbten: DHTView.operations.title=Details verwerking DHTView.operations.sent=Ferstjoerd DHTView.operations.ok=Guod DHTView.operations.failed=Mislukt DHTView.operations.received=\u00dbntfangen DHTView.operations.findNode=Node sykje DHTView.operations.findValue=Wearde sykje DHTView.operations.store=Bewarje DHTView.activity.title=Aksje DHTView.activity.status.true=Yn wachtrige DHTView.activity.status.false=Rint DHTView.activity.type.1=Ynterne Get DHTView.activity.type.2=Eksterne Get DHTView.activity.type.3=Ynterne Put DHTView.activity.type.4=Eksterne Put DHTView.activity.target=Doel DHTView.db.title=Databank DHTView.db.keys=Kaaien DHTView.db.values=Wearde DHTView.db.local=Lokaal DHTView.db.direct=Direkt DHTView.db.indirect=Yndirekt MainWindow.dht.status.tooltip=Als de verspreide database wordt uitgevoerd, wordt hier het geschatte aantal on-line gebruikers weergegeven MainWindow.dht.status.disabled=\u00datskakelje MainWindow.dht.status.failed=Mislearje MainWindow.dht.status.initializing=Dwaande MainWindow.dht.status.users=%1 Br\u00fbkers MyTorrentsView.menu.setUpSpeed=Uploadsnelheid instellen MyTorrentsView.menu.setDownSpeed=Downloadsnelheid instellen diagnostics.log_found=Vuze is niet correct afgesloten. Controleer %1 voor diagnostische logbestanden en overweeg deze aan het Vuze team te rapporteren als dit het resultaat van een applicatiefout is. ConfigView.section.logging.log0type=Ynformaasje # %1 = "in kbps" or ""; %2 = "upload" or "download" OpenTorrentWindow.torrentLocation=Torrentbestanden: Button.moveUp=Omheech Button.moveDown=Omleach # > 2402 #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} # # Used for peers which we can't determine. PeerSocket.unknown=\u00dbnbekend ConfigView.label.announceport=Negeer door tracker meegedeelde poort #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences iconBar.queue.tooltip=Wachtrige MainWindow.menu.help.faq=Veelgestelde vragen #what you've watched? Discover more with a single click... MainWindow.menu.help.donate=Geef een donatie !!! azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_mk_MK.properties0000644000175000017500000011437511301156004026100 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 MainWindow.menu.file.open=\u041e\u0442\u0432\u043e\u0440\u0438 MainWindow.menu.file.create=\u041d\u043e\u0432 \u0442\u043e\u0440\u0435\u043d\u0442 MainWindow.menu.file.create.fromfile=\u041e\u0434 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430 MainWindow.menu.file.create.fromdir=\u041e\u0434 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0443\u043c MainWindow.menu.file.closetab=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 \u0433\u043e \u0458\u0430\u0437\u0438\u0447\u0435\u0442\u043e MainWindow.menu.file.closewindow=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 \u0433\u043e \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446\u043e\u0442 MainWindow.menu.file.exit=\u0418\u0437\u043b\u0435\u0437 MainWindow.menu.file.folder=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0443\u043c MainWindow.menu.view=\u041f\u043e\u0433\u043b\u0435\u0434 MainWindow.menu.view.show=\u041f\u043e\u043a\u0430\u0436\u0438 \u0433\u0438 MainWindow.menu.view.mytorrents=\u043c\u043e\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 MainWindow.menu.view.configuration=\u041e\u043f\u0446\u0438\u0438 MainWindow.menu.view.console=\u041a\u043e\u043d\u0437\u043e\u043b\u0430 MainWindow.menu.view.irc=\u0418\u0420\u0426 MainWindow.menu.language=\u0408\u0430\u0437\u0438\u043a MainWindow.menu.window=\u041f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 MainWindow.menu.window.minimize=\u041c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0430\u0458 MainWindow.menu.window.zoom=\u0417\u0433\u043e\u043b\u0435\u043c\u0438 MainWindow.menu.window.alltofront=\u041f\u043e\u0432\u043b\u0435\u0447\u0438 \u0433\u0438 \u0441\u0438\u0442\u0435 \u043d\u0430\u043f\u0440\u0435\u0434 MainWindow.menu.help=\u041f\u043e\u043c\u043e\u0448 MainWindow.menu.help.about=\u0417\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441 MainWindow.about.title=\u0417\u0430 MainWindow.about.section.developers=\u0420\u0430\u0437\u0432\u0438\u0432\u0430\u0447\u0438 MainWindow.about.section.translators=\u041f\u0440\u0435\u0432\u0435\u0434\u0443\u0432\u0430\u0447\u0438 MainWindow.about.section.internet=\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 MainWindow.about.internet.homepage=\u0414\u043e\u043c\u0430\u0448\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0430 \u043d\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441 MainWindow.about.internet.sourceforge=\u0421\u0442\u0440\u0430\u043d\u0442\u0430 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0442 \u043d\u0430 Sourceforge MainWindow.about.internet.sourceforgedownloads=\u041f\u0440\u0435\u0437\u0435\u043c\u0430\u045a\u0430 \u043e\u0434 Sourceforge MainWindow.about.internet.forumdiscussion=\u0424\u043e\u0440\u0443\u043c\u0438 MainWindow.status.latestversion=\u041d\u0430\u0458\u043d\u043e\u0432\u0430 MainWindow.status.latestversion.clickupdate=\u041a\u043b\u0438\u043a\u043d\u0438 \u0437\u0430 \u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u0437\u0438\u0458\u0430 MainWindow.status.unknown=\u043d\u0435\u043f\u043e\u0437\u043d\u0430\u0442\u043e MainWindow.status.checking=\u043f\u0440\u043e\u0432\u0435\u0440\u0443\u0432\u0430\u043c MyTorrentsView.mytorrents=\u041c\u043e\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.name=\u0418\u043c\u0435 TableColumn.header.size=\u0413\u043e\u043b\u0435\u043c\u0438\u043d\u0430 TableColumn.header.done=\u0417\u0430\u0432\u0440\u0448\u0435\u043d\u043e TableColumn.header.done.info=\u0417\u0430\u0432\u0440\u0448\u0435\u043d \u0434\u0435\u043b \u043e\u0434 \u0441\u0435\u0433\u0430\u0448\u043d\u0430\u0442\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 TableColumn.header.status=\u0421\u043e\u0441\u0442\u043e\u0458\u0431\u0430 TableColumn.header.status.info=\u0428\u0442\u043e \u043f\u0440\u0430\u0432\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u0442 TableColumn.header.downspeed=\u041d\u0430\u0434\u043e\u043b\u0443 TableColumn.header.upspeed=\u041d\u0430\u0433\u043e\u0440\u0435 TableColumn.header.eta=\u0423\u0448\u0442\u0435 TableColumn.header.tracker=\u0421\u0442\u0430\u0442\u0443\u0441 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u043e\u0442 TableColumn.header.tracker.info=\u0421\u0442\u0430\u0442\u0443\u0441 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u043e\u0442 TableColumn.header.trackernextaccess=\u0421\u043b\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u0441\u0442\u0430\u043f \u043a\u043e\u043d \u0442\u0440\u0430\u043a\u0435\u0440\u043e\u0442 TableColumn.header.trackernextaccess.info=\u041a\u043e\u0433\u0430 \u045c\u0435 \u0441\u0435 \u043f\u0440\u0438\u0441\u0442\u0430\u043f\u0438 \u043a\u043e\u043d \u0442\u0440\u0430\u043a\u0435\u0440\u043e\u0442 \u0441\u043b\u0435\u0434\u0435\u043d \u043f\u0430\u0442 TableColumn.header.priority=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 MyTorrentsView.menu.showdetails=\u041f\u043e\u043a\u0430\u0436\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0438\u0441\u0442\u0438 MyTorrentsView.menu.showdownloadbar=\u041f\u043e\u043a\u0430\u0436\u0438 \u043b\u0435\u043d\u0442\u0430 \u0437\u0430 \u043f\u0440\u0435\u0437\u0435\u043c\u0430\u045a\u0435\u0442\u043e MyTorrentsView.menu.open=\u041e\u0442\u0432\u043e\u0440\u0438 \u0458\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430\u0442\u0430 MyTorrentsView.menu.setpriority=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 MyTorrentsView.menu.setpriority.high=\u0412\u0438\u0441\u043e\u043a MyTorrentsView.menu.setpriority.low=\u041d\u0438\u0437\u043e\u043a MyTorrentsView.menu.start=\u0417\u0430\u043f\u043e\u0447\u043d\u0438 MyTorrentsView.menu.stop=\u0417\u0430\u043f\u0440\u0438 MyTorrentsView.menu.remove=\u041e\u0442\u0441\u0442\u0440\u0430\u043d\u0438 MyTorrentsView.menu.changeTracker=\u0414\u043e\u0434\u0430\u0434\u0438 \u0423\u0420\u041b \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440 TrayWindow.menu.exit=\u0418\u0437\u043b\u0435\u0437\u0438 TrayWindow.menu.show=\u041f\u043e\u043a\u0430\u0436\u0438 \u0433\u043e \u0410\u0437\u0443\u0440\u0435\u0443\u0441 SystemTray.menu.exit=\u0418\u0437\u043b\u0435\u0437\u0438 SystemTray.menu.closealldownloadbars=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 \u0433\u0438 \u0441\u0438\u0442\u0435 \u043b\u0435\u043d\u0442\u0438 SystemTray.menu.show=\u041f\u043e\u043a\u0430\u0436\u0438 \u0433\u043e \u0410\u0437\u0443\u0440\u0435\u0443\u0441 ConfigView.label.maxdownloads=Max simultaneous downloads [0: unlimited] ConfigView.label.priorityExtensions=Auto-prioritize files with extension\n - eg: .txt;.nfo;.jpg ConfigView.label.maxuploads=Default max upload slots per torrent ConfigView.section.irc=Irc FileItem.normal=\u043d\u043e\u0440\u043c\u0430\u043b\u0435\u043d FileItem.high=\u0432\u0438\u0441\u043e\u043a FileItem.donotdownload=\u041d\u0435 \u0441\u0438\u043c\u043d\u0443\u0432\u0430\u0458 FilesView.name=\u0418\u043c\u0435 FilesView.size=\u0413\u043e\u043b\u0435\u043c\u0438\u043d\u0430 FilesView.numberofpieces=\u0431\u0440\u043e\u0458 \u043d\u0430 \u043f\u0430\u0440\u0447\u0438\u045a\u0430 FilesView.pieces=\u041f\u0430\u0440\u0447\u0438\u045a\u0430 FilesView.priority=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 FilesView.menu.open=\u041e\u0442\u0432\u043e\u0440\u0438 FilesView.menu.setpriority=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 FilesView.menu.setpriority.high=\u0412\u0438\u0441\u043e\u043a FilesView.menu.setpriority.normal=\u041d\u043e\u0440\u043c\u0430\u043b\u0435\u043d FilesView.menu.setpriority.skipped=\u041d\u0435 \u0441\u0438\u043c\u043d\u0443\u0432\u0430\u0458 FilesView.title.short=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0438 FilesView.title.full=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0438 GeneralView.section.downloaded=\u041f\u0440\u0435\u0437\u0435\u043c\u0435\u043d\u043e GeneralView.section.availability=\u0414\u043e\u0441\u0442\u0430\u043f\u043d\u043e\u0441\u0442 GeneralView.section.transfer=\u0422\u0440\u0430\u043d\u0441\u0444\u0435\u0440 GeneralView.section.info=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 GeneralView.title.short=\u041e\u043f\u0448\u0442\u043e GeneralView.title.full=\u041e\u043f\u0448\u0442\u043e GeneralView.label.timeelapsed=\u041f\u043e\u043c\u0438\u043d\u0430\u0442\u043e \u0432\u0440\u0435\u043c\u0435 : GeneralView.label.remaining=\u041f\u0440\u0435\u043e\u0441\u0442\u0430\u043d\u0430\u0442\u043e : GeneralView.label.downloaded=\u041f\u0440\u0435\u0437\u0435\u043c\u0435\u043d\u043e : GeneralView.label.downloadspeed=\u0411\u0440\u0437\u0438\u043d\u0430 \u043d\u0430 \u043f\u0440\u0435\u0437\u0435\u043c\u0430\u045a\u0435 : GeneralView.label.maxuploads=\u041c\u0435\u0441\u0442\u0430 \u0437\u0430 \u0438\u0441\u043f\u0440\u0430\u045c\u0430\u045a\u0435 : GeneralView.label.uploaded=\u0418\u0441\u043f\u0440\u0430\u0442\u0435\u043d\u043e : GeneralView.label.uploadspeed=\u0411\u0440\u0437\u0438\u043d\u0430 \u043d\u0430 \u0438\u0441\u043f\u0440\u0430\u045c\u0430\u045a\u0435 : GeneralView.label.seeds=\u201e\u0421\u0435\u0458\u0430\u0447\u0438\u201c : GeneralView.label.peers=\u041a\u043e\u0440\u0438\u0441\u043d\u0438\u0446\u0438 : GeneralView.label.totalspeed=\u0411\u0440\u0437\u0438\u043d\u0430 \u043d\u0430 \u0440\u043e\u0458\u043e\u0442 : GeneralView.label.totalspeed.tooltip=\u0412\u043a\u0443\u043f\u043d\u0430 (\u0438 \u043f\u0440\u043e\u0441\u0435\u0447\u043d\u0430) \u0431\u0440\u0437\u0438\u043d\u0430 \u043d\u0430 \u043f\u043e\u0432\u0440\u0437\u0430\u043d\u0438\u0442\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0438 GeneralView.label.averagespeed=\u043f\u0440\u043e\u0441\u0435\u0447\u043d\u0430 GeneralView.label.filename=\u0418\u043c\u0435 : GeneralView.label.totalsize=\u0412\u043a\u0443\u043f\u043d\u0430 \u0433\u043e\u043b\u0435\u043c\u0438\u043d\u0430 : GeneralView.label.savein=\u0421\u043d\u0438\u043c\u0438 \u0432\u043e : GeneralView.label.hash=\u0425\u0435\u0448 : GeneralView.label.numberofpieces=# \u043d\u0430 \u043f\u0430\u0440\u0447\u0438\u045a\u0430 : GeneralView.label.size=\u0413\u043e\u043b\u0435\u043c\u0438\u043d\u0430 : GeneralView.label.tracker=\u0421\u043e\u0441\u0442\u043e\u0458\u0431\u0430 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u043e\u0442 : GeneralView.label.trackerurl=URL \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u043e\u0442 : GeneralView.label.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 : ManagerItem.ready=Ready SystemTray.tooltip.seeding=%1 \u201e\u0441\u0435\u0430\u043c\u201c, SystemTray.tooltip.downloading=%1 \u0441\u0438\u043c\u043d\u0443\u0432\u0430\u043c, Button.next=\u0421\u043b\u0435\u0434\u043d\u043e Button.finish=\u0417\u0430\u0432\u0440\u0448\u0438 Button.cancel=\u041f\u043e\u043d\u0438\u0448\u0442\u0438 IrcView.help=Valid commands are :\n . /help : displays this message\n . /nick | /name : changes your name \n . /me action : sends an action \n . /msg nick message : sends a private message to \n . /r message : reply to last private message\n . /join #channel : changes current channel Button.ok=\u0412\u043e \u0440\u0435\u0434 MyTorrentsView.menu.move=\u041f\u043e\u043c\u0435\u0441\u0442\u0438 MyTorrentsView.menu.moveUp=\u041d\u0430\u0433\u043e\u0440\u0435 MyTorrentsView.menu.moveDown=\u041d\u0430\u0434\u043e\u043b\u0443 GeneralView.label.hashfails=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0430\u043d\u0438 \u043f\u0430\u0440\u0447\u0438\u045a\u0430 : GeneralView.label.shareRatio=\u0421\u043e\u043e\u0434\u043d\u043e\u0441 : MainWindow.menu.view.ipFilter=\u0424\u0438\u043b\u0442\u0440\u0438 \u0437\u0430 \u0418\u041f-\u0430\u0434\u0440\u0435\u0441\u0438 MyTorrentsView.menu.removeand=\u041e\u0442\u0441\u0442\u0440\u0430\u043d\u0438 \u0438 MyTorrentsView.menu.removeand.deletetorrent=\u0438\u0437\u0431\u0440\u0438\u0448\u0438 \u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u0442 MyTorrentsView.menu.removeand.deletedata=\u0438\u0437\u0431\u0440\u0438\u0448\u0438 \u0433\u0438 \u043f\u043e\u0434\u0430\u0442\u043e\u0446\u0438\u0442\u0435 MyTorrentsView.menu.removeand.deleteboth=\u0438\u0437\u0431\u0440\u0438\u0448\u0438 \u0441\u0450 deletedata.title=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0443\u0432\u0430\u045a\u0435 deletedata.message1=\u040c\u0435 \u0433\u0438 \u0438\u0437\u0431\u0440\u0438\u0448\u0435\u0442\u0435 \u043f\u043e\u0434\u0430\u0442\u043e\u0446\u0438\u0442\u0435 \u0437\u0430 :\n configureWizard.title=\u0412\u043e\u043b\u0448\u0435\u0431\u043d\u0438\u043a \u0437\u0430 \u043f\u043e\u0434\u0435\u0441\u0443\u0432\u0430\u045a\u0430 configureWizard.transfer.hint=\u0421\u043e\u0432\u0435\u0442: \u041d\u0430\u043c\u0435\u0441\u0442\u0435\u0442\u0435 \u043d\u0435\u0448\u0442\u043e \u043f\u043e\u043c\u0430\u043b\u043a\u0443 \u043e\u0434 \u043d\u0430\u0458\u0433\u043e\u043b\u0435\u043c\u0430\u0442\u0430 \u0432\u0440\u0435\u0434\u043d\u043e\u0441\u0442 configureWizard.transfer.connection=\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0432\u0440\u0441\u043a\u0430 configureWizard.transfer.connection.0=\u041f\u043e \u0441\u0432\u043e\u0458 \u0438\u0437\u0431\u043e\u0440 configureWizard.transfer.connection.1=\u043c\u043e\u0434\u0435\u043c configureWizard.transfer.maxUpSpeed=\u041d\u0430\u0458\u0432\u0438\u0441\u043e\u043a\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0437\u0430 \u0438\u0441\u043f\u0440\u0430\u045c\u0430\u045a\u0435 \u0432\u043e KB/s configureWizard.transfer.maxActiveTorrents=\u041d\u0430\u0458\u043c\u043d\u043e\u0433\u0443 \u0430\u043a\u0442\u0438\u0432\u043d\u0438 configureWizard.transfer.maxDownloads=\u041d\u0430\u0458\u043c\u043d\u043e\u0433\u0443 \u043f\u0440\u0435\u0437\u0435\u043c\u0430\u045a\u0430 configureWizard.transfer.maxUploadsPerTorrent=\u041d\u0430\u0458\u043c\u043d\u043e\u0433\u0443 \u0438\u0441\u043f\u0440\u0430\u045c\u0430\u045a\u0430 \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442 configureWizard.nat.message=\u041f\u0440\u0435\u043f\u043e\u0440\u0430\u0447\u043b\u0438\u0432\u043e \u0435 \u0431\u0430\u0440\u0435\u043c \u0435\u0434\u043d\u0430 \u043f\u043e\u0440\u0442\u0430 \u0434\u0430 \u0435 \u043f\u0440\u0438\u0441\u0442\u0430\u043f\u043b\u0438\u0432\u0430 \u043e\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0437\u0430 \u043d\u0430\u0458\u0434\u043e\u0431\u0440\u043e \u0438\u0441\u043a\u0443\u0441\u0442\u0432\u043e \u0441\u043e \u0411\u0438\u0442\u0422\u043e\u0440\u0435\u043d\u0442. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0434\u043d\u0430\u0442\u0430 \u043f\u043e\u0440\u0442\u0430 \u0437\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u0442 \u0435 6881. \u0421\u043e \u043e\u0432\u0430\u0430 \u0430\u043b\u0430\u0442\u043a\u0430 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0458\u0430 \u0441\u043c\u0435\u043d\u0438\u0442\u0435 \u0438 \u0434\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u0430\u0442\u0435 \u0434\u0430\u043b\u0438 \u0435 \u043f\u0440\u0438\u0441\u0442\u0430\u043f\u043b\u0438\u0432\u0430 \u043e\u0434 \u043d\u0430\u0434\u0432\u043e\u0440. configureWizard.nat.test=\u0422\u0435\u0441\u0442\u0438\u0440\u0430\u0458 configureWizard.nat.testing=\u0422\u0435\u0441\u0442\u0438\u0440\u0430\u043c \u0437\u0430 \u043f\u043e\u0440\u0442\u0430\u0442\u0430 configureWizard.nat.ok=\u0412\u043e \u0440\u0435\u0434 \u0435! configureWizard.nat.ko=\u0413\u0440\u0435\u0448\u043a\u0430 \u0441\u043e NAT configureWizard.nat.unable=\u041d\u0435 \u0441\u0443\u043c \u0432\u043e \u043c\u043e\u0436\u043d\u043e\u0441\u0442 \u0434\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u0430\u043c configureWizard.file.title=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 / \u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0438 configureWizard.file.message1=\u0418\u0437\u0431\u0435\u0440\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0443\u043c \u043a\u0430\u0434\u0435 \u0448\u0442\u043e \u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u045c\u0435 \u0433\u0438 \u0441\u043d\u0438\u043c\u0430 \u043e\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438: configureWizard.file.path=\u041f\u0430\u0442 configureWizard.file.browse=\u0420\u0430\u0437\u0433\u043b\u0435\u0434\u0430\u0458 configureWizard.file.message2=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u043c\u043e\u0436\u0435 \u0432\u0435\u0434\u043d\u0430\u0448 \u0434\u0430 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438 \u0441\u043e \u043f\u0440\u0435\u0437\u0435\u043c\u0430\u045a\u0435\u0442\u043e \u0441\u043e \u0442\u043e\u0430 \u0448\u0442\u043e \u0447\u0443\u0432\u0430 \u0434\u043e\u0434\u0430\u0442\u043d\u0438 \u043f\u043e\u0434\u0430\u0442\u043e\u0446\u0438 \u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u0442. \u041d\u0430 \u043e\u0432\u043e\u0458 \u043d\u0430\u0447\u0438\u043d \u043d\u0435 \u0441\u0435 \u043e\u0442\u0444\u0440\u043b\u0430\u0430\u0442 \u043d\u0435\u0446\u0435\u043b\u043e\u0441\u043d\u043e \u0441\u0438\u043c\u043d\u0430\u0442\u0438\u0442\u0435 \u0434\u0435\u043b\u0447\u0438\u045a\u0430.\n configureWizard.file.fastResume=\u041e\u0432\u043e\u0437\u043c\u043e\u0436\u0438 \u0431\u0440\u0437\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0443\u0432\u0430\u045a\u0435 configureWizard.file.invalidPath=\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0443\u043c configureWizard.finish.title=\u0417\u0430\u0432\u0440\u0448\u0435\u043d\u043e configureWizard.finish.message=\u041f\u043e\u0434\u0435\u0441\u0443\u0432\u0430\u045a\u0435\u0442\u043e \u043d\u0430 \u0410\u0437\u0443\u0440\u0435\u0443\u0441 \u0437\u0430\u0432\u0440\u0448\u0438. \u0417\u0430\u0431\u0430\u0432\u0443\u0432\u0430\u0458 \u0441\u0435! ConfigView.label.movecompleted=Move completed files MainWindow.menu.view.mytracker=\u043c\u043e\u0458\u043e\u0442 \u0442\u0440\u0430\u043a\u0435\u0440 MainWindow.menu.view.plugins=\u0414\u043e\u0434\u0430\u0442\u043e\u0446\u0438 fileDownloadWindow.saveTorrentIn=\u0421\u043d\u0438\u043c\u0438 \u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u0442 \u0432\u043e fileDownloadWindow.title=\u0410\u0437\u0443\u0440\u0435\u0443\u0441 - \u0441\u043e\u0431\u0438\u0440\u0430\u0447 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 fileDownloadWindow.downloading=\u0421\u0438\u043c\u043d\u0443\u0432\u0430\u043c \u043e\u0434 : fileDownloadWindow.status=\u0421\u043e\u0441\u0442\u043e\u0458\u0431\u0430 : fileDownloadWindow.state_initializing=\u0418\u043d\u0438\u0446\u0438\u0458\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043c fileDownloadWindow.state_downloading=\u0421\u0438\u043c\u043d\u0443\u0432\u0430\u043c fileDownloadWindow.state_error=\u0413\u0440\u0435\u0448\u043a\u0430 : MainWindow.menu.file.open.url=\u041b\u043e\u043a\u0430\u0446\u0438\u0458\u0430 openUrl.title=\u041e\u0442\u0432\u043e\u0440\u0438 \u043b\u043e\u043a\u0430\u0446\u0438\u0458\u0430 splash.loadingImages=\u0412\u0447\u0438\u0442\u0443\u0432\u0430\u043c \u0441\u043b\u0438\u043a\u0438 splash.initializeGui=\u0413\u043e \u0438\u043d\u0446\u0438\u0458\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043c \u0433\u043b\u0430\u0432\u043d\u0438\u043e\u0442 \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446 splash.openViews=\u041e\u0442\u0432\u043e\u0440\u0430\u043c \u043f\u043e\u0433\u043b\u0435\u0434\u0438 splash.plugin=\u0413\u043e \u0432\u0447\u0438\u0442\u0443\u0432\u0430\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0442 configureWizard.nat.tooManyPorts=\u041f\u0440\u0435\u043c\u043d\u043e\u0433\u0443 \u043f\u043e\u0440\u0442\u0438 \u0437\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u0430\u045a\u0435 (\u0441\u043c\u0435\u0435 \u0434\u043e 9) MyTorrentsView.menu.publish=\u041e\u0431\u0458\u0430\u0432\u0438 # # Tooltips # # # 2.0.4.4 # configureWizard.nat.sharePort=\u0423\u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0432\u0430\u0458 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u0430 \u0432\u043b\u0435\u0437\u043d\u0430 \u043f\u043e\u0440\u0442\u0430 \u0437\u0430 \u0441\u0438\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 columnChooser.title=\u0418\u0437\u0431\u0435\u0440\u0438 \u043a\u043e\u043b\u043e\u043d\u0438 \u0437\u0430 \u043f\u0440\u0438\u043a\u0430\u0437 columnChooser.move=\u041f\u0440\u0435\u0440\u0435\u0434\u0435\u0442\u0435 \u0433\u0438 \u0440\u0435\u0434\u043e\u0432\u0438\u0442\u0435 \u0441\u043e \u0432\u043b\u0435\u0447\u0435\u045a\u0435 columnChooser.apply=\u041f\u0440\u0438\u043c\u0435\u043d\u0438 columnChooser.columnname=\u0418\u043c\u0435 \u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u0430 columnChooser.columndescription=\u041e\u043f\u0438\u0441 TableColumn.header.shareRatio=\u0421\u043e\u043e\u0434\u043d\u043e\u0441 MyTorrentsView.menu.editTableColumns=\u041f\u043e\u0434\u0435\u0441\u0443\u0432\u0430\u045a\u0435 \u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u0438\u0442\u0435 authenticator.title=\u041f\u043e\u0442\u0440\u0435\u0431\u043d\u0430 \u0435 \u0430\u0432\u0442\u0435\u043d\u0442\u0438\u043a\u0430\u0446\u0438\u0458\u0430 authenticator.realm=\u041e\u0431\u043b\u0430\u0441\u0442 authenticator.tracker=\u0422\u0440\u0430\u043a\u0435\u0440 authenticator.user=\u041a\u043e\u0440\u0438\u0441\u043d\u0438\u0447\u043a\u043e \u0438\u043c\u0435 authenticator.password=\u041b\u043e\u0437\u0438\u043d\u043a\u0430 MainWindow.menu.help.checkupdate=\u041f\u043e\u0431\u0430\u0440\u0430\u0458 \u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u0437\u0438\u0458\u0430 TableColumn.header.down=\u0421\u0438\u043c\u043d\u0430\u0442\u043e TableColumn.header.up=\u0418\u0441\u043f\u0440\u0430\u0442\u0435\u043d\u043e SystemTray.menu.stopalltransfers=\u0417\u0430\u043f\u0440\u0438 \u0433\u0438 \u0441\u0438\u0442\u0435 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 TrayWindow.menu.stopalldownloads=\u0417\u0430\u043f\u0440\u0438 \u0433\u0438 \u0441\u0438\u0442\u0435 \u043f\u0440\u0435\u0437\u0435\u043c\u0430\u045a\u0430 TableColumn.header.pieces=\u041f\u0430\u0440\u0447\u0438\u045a\u0430 TableColumn.header.completion=\u0412\u0435\u045c\u0435 \u0441\u0438\u043c\u043d\u0430\u0442\u043e TableColumn.header.completion.info=\u0413\u0440\u0430\u0444\u0438\u0447\u043a\u0438 \u043f\u0440\u0438\u043a\u0430\u0437 \u043d\u0430 \u0432\u0435\u045c\u0435 \u0441\u0438\u043c\u043d\u0430\u0442\u043e\u0442\u043e MyTorrentsView.menu.recheck=\u041f\u0440\u043e\u0432\u0435\u0440\u0438 \u0443\u0448\u0442\u0435 \u0435\u0434\u043d\u0430\u0448 MyTorrentsView.menu.editTracker=\u0418\u0437\u043c\u0435\u043d\u0438 \u0433\u043e \u0423\u0420\u041b\u0442\u043e \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u043e\u0442 GeneralView.menu.selectTracker=\u0418\u0437\u0431\u0435\u0440\u0435\u0442\u0435 MyTorrentsView.menu.moveTop=\u041d\u0430\u0458\u0433\u043e\u0440\u0435 MyTorrentsView.menu.moveEnd=\u041d\u0430\u0458\u0434\u043e\u043b\u0443 MainWindow.menu.view.stats=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 TableColumn.header.health=\u0417\u0434\u0440\u0430\u0432\u0458\u0435 MyTorrentsView.menu.health=\u0417\u0430 \u0437\u0434\u0440\u0430\u0432\u0458\u0435\u0442\u043e # #2.0.7.0 # security.certtruster.yes=\u0414\u0430 security.certtruster.no=\u041d\u0435 MainWindow.menu.file.share=\u0421\u043f\u043e\u0434\u0435\u043b\u0438 MainWindow.menu.file.share.file=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0430 MainWindow.menu.file.share.dir=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0443\u043c MainWindow.menu.file.share.dircontents=\u0421\u043e\u0434\u0440\u0436\u0438\u043d\u0430 \u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0443\u043c MainWindow.menu.file.share.dircontentsrecursive=\u0421\u043e\u0434\u0440\u0436\u0438\u043d\u0430\u0442\u0430 \u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0443\u043c (\u0434\u043b\u0430\u0431\u043e\u043a\u043e) TrayWindow.menu.startalldownloads=\u0417\u0430\u043f\u043e\u0447\u043d\u0438 \u0433\u0438 \u0441\u0438\u0442\u0435 \u043f\u0440\u0435\u0437\u0435\u043c\u0430\u045a\u0430 SystemTray.menu.startalltransfers=\u0417\u0430\u043f\u043e\u0447\u043d\u0438 \u0433\u0438 \u0441\u0438\u0442\u0435 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 MainWindow.menu.view.myshares=\u0441\u043f\u043e\u0434\u0435\u043b\u0435\u043d\u0438\u0442\u0435 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0438 GeneralView.label.hash.tooltip=\u0418\u0441\u043a\u043e\u043f\u0438\u0440\u0430\u0458 \u0433\u043e \u0445\u0435\u0448\u043e\u0442 \u0441\u043e \u043a\u043b\u0438\u043a\u0430\u045a\u0435 ConfigView.label.serverport=Incoming TCP listen port configureWizard.nat.server.tcp_listen_port=\u0412\u043b\u0435\u0437\u043d\u0430 \u201eTCP\u201c \u043f\u043e\u0440\u0442\u0430 # # 2.0.7.x # Categories.all=\u0421\u0438\u0442\u0435 Categories.uncategorized=\u041d\u0435\u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0437\u0438\u0440\u0430\u043d\u0438 CategoryAddWindow.message=\u0414\u043e\u0434\u0430\u0434\u0438 \u043d\u043e\u0432\u043e \u0438\u043c\u0435 \u0437\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0430 CategoryAddWindow.title=\u0414\u043e\u0434\u0430\u0434\u0438 \u043d\u043e\u0432\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0430 ConfigView.label.minSeedingTime.tooltip=Seeding Ranks can fluctuate often in a short period time, sometimes causing the torrent to automatically start, only to be stopped && queued immediately afterwards.\nThis alleviates the problem by forcing the torrent to stay seeding for a given period of time. You can still stop it manually if you want. ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Often, torrents with low seed counts and high peer counts means that there probably isn't a full copy amoungst the peers.\nTherefore, you may not want the seeding rules pretending there's a full copy (and thus incorrectly reducing its rank) MainWindow.menu.language.refresh=\u041e\u0431\u043d\u043e\u0432\u0438 TableColumn.header.availability.info=\u0411\u0440\u043e\u0458 \u043d\u0430 \u0446\u0435\u043b\u0438 \u043a\u043e\u043f\u0438\u0438 TableColumn.header.availability=\u0414\u043e\u0441\u0442\u0430\u043f\u043d\u043e\u0441\u0442 TableColumn.header.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0430 MyTorrentsView.header=\u041d\u0435\u0446\u0435\u043b\u043e\u0441\u043d\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 TableColumn.header.maxuploads=\u041d\u0430\u0458\u0433\u043e\u043b\u0435\u043c \u0431\u0440\u043e\u0458 \u043d\u0430 \u0438\u0441\u043f\u0440\u0430\u045c\u0430\u045a\u0430 MyTorrentsView.menu.category.delete=\u0418\u0437\u0431\u0440\u0438\u0448\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0430 MyTorrentsView.menu.forceStart=\u041f\u0440\u0438\u0441\u0438\u043b\u043d\u043e \u0437\u0430\u043f\u043e\u0447\u043d\u0438 MyTorrentsView.menu.setCategory.add=\u0414\u043e\u0434\u0430\u0434\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0430 MyTorrentsView.menu.setCategory=\u0414\u043e\u0434\u0435\u043b\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0458\u0430 TableColumn.header.totalspeed.info=\u0412\u043a\u0443\u043f\u043d\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043d\u0430 \u0441\u0438\u0442\u0435 \u043a\u043e\u0440\u0438\u0441\u043d\u0438\u0446\u0438 \u0441\u043e \u043a\u043e\u0438 \u0441\u0442\u0435 \u043f\u043e\u0432\u0440\u0437\u0430\u043d\u0438 TableColumn.header.totalspeed=\u0412\u043a\u0443\u043f\u043d\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 splash.initializePlugins=\u0418\u043d\u0438\u0446\u0438\u0458\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u0438 GeneralView.label.creationdate=\u0421\u043e\u0437\u0434\u0430\u0434\u0435\u043d\u043e \u043d\u0430 : fileDownloadWindow.retry=\u041e\u0431\u0438\u0434\u0438 \u0441\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e GeneralView.label.connected=\u043f\u043e\u0432\u0440\u0437\u0430\u043d\u0438 GeneralView.label.in_swarm=\u0432\u043e \u0440\u043e\u0458\u043e\u0442 AlertMessageBox.error=\u0413\u0440\u0435\u0448\u043a\u0430 AlertMessageBox.warning=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0443\u0432\u0430\u045a\u0435 AlertMessageBox.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 AlertMessageBox.information=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0458\u0430 # # > 2.0.8.0 # TableColumn.header.remaining=\u041f\u0440\u0435\u043e\u0441\u0442\u0430\u043d\u0430\u0442\u043e popup.error.hide=\u0422\u0440\u0433\u043d\u0438 \u0433\u043e popup.error.details=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 ConfigView.label.max_peers_per_torrent=Maximum number of connections per torrent [0: unlimited] ConfigView.label.max_peers_total=Maximum number of connections globally [0: unlimited] Button.revert=\u0412\u0440\u0430\u0442\u0438 MyTorrentsView.menu.changeDirectory=\u0421\u043c\u0435\u043d\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0443\u043c \u0437\u0430 \u043f\u043e\u0434\u0430\u0442\u043e\u0446\u0438 GenericText.column=\u043a\u043e\u043b\u043e\u043d\u0430 MyTorrentsView.menu.thisColumn.remove=\u041e\u0442\u0441\u0442\u0440\u0430\u043d\u0438 \u0458\u0430 \u043a\u043e\u043b\u043e\u043d\u0430\u0442\u0430 MyTorrentsView.menu.tracker=\u0422\u0440\u0430\u043a\u0435\u0440 splash.initializeGM=\u0413\u043e \u0438\u043d\u0438\u0446\u0438\u0458\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043c \u0433\u043b\u043e\u0431\u0430\u043b\u043d\u0438\u043e\u0442 \u043c\u0435\u043d\u0430\u045f\u0435\u0440 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 splash.loadingTorrents=\u0412\u0447\u0438\u0442\u0443\u0432\u0430\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0438 splash.firstMessageNoI18N=(: \u0410\u0437\u0443\u0440\u0435\u0443\u0441 :) MyTorrentsView.menu.thisColumn.sort=\u041f\u043e\u0434\u0440\u0435\u0434\u0438 Button.yes=\u0414\u0430 Button.no=\u041d\u0435 splash.loadingTorrent=\u0413\u043e \u0432\u0447\u0438\u0442\u0443\u0432\u0430\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u0442 \u0431\u0440\u043e\u0458 splash.of=\u043d\u0430 MainWindow.menu.help.whatsnew=\u0428\u0442\u043e \u0435 \u043d\u043e\u0432\u043e MainWindow.status.latestversionunchecked=\u041e\u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u0435\u043d\u043e \u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0443\u0432\u0430\u045a\u0435\u0442\u043e \u0437\u0430 \u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u0437\u0438\u0458\u0430 GeneralView.label.updatein.stopped=\u0417\u0430\u043f\u0440\u0435\u043d\u043e MainWindow.menu.help.plugins=\u0417\u0435\u043c\u0438 \u0434\u043e\u0434\u0430\u0442\u043e\u0446\u0438 GeneralView.label.maxdownloadspeed=\u0413\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430\u0434\u043e\u043b\u0443 GeneralView.label.maxdownloadspeed.tooltip=\u041d\u0430\u0458\u0433\u043e\u043b\u0435\u043c\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043d\u0430 \u0441\u0438\u043c\u043d\u0443\u0432\u0430\u045a\u0435 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430] Button.clear=\u0418\u0441\u0447\u0438\u0441\u0442\u0438 Button.reset=\u0420\u0435\u0441\u0442\u0430\u0440\u0442 ConfigView.section.server.enableudp=Enable UDP tracker client protocol. #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u0422\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438 MainWindow.menu.transfers.startalltransfers=\u0417\u0430\u043f\u043e\u0447\u043d\u0438 \u0433\u0438 \u0441\u0438\u0442\u0435 MainWindow.menu.transfers.stopalltransfers=\u0417\u0430\u043f\u0440\u0438 \u0433\u0438 \u0441\u0438\u0442\u0435 MainWindow.menu.transfers.pausetransfers=\u041f\u0430\u0443\u0437\u0438\u0440\u0430\u0458 MainWindow.menu.transfers.resumetransfers=\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438 SystemTray.menu.pausetransfers=\u041f\u0430\u0443\u0437\u0438\u0440\u0430\u0458 \u0433\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438\u0442\u0435 SystemTray.menu.resumetransfers=\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438 \u0433\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440\u0438\u0442\u0435 openUrl.referrer=URL \u043d\u0430 \u043f\u0440\u0435\u0442\u0445\u043e\u0434\u043d\u0430\u0442\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 openUrl.referrer.info=\u0414\u043e\u043a\u043e\u043b\u043a\u0443 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0442\u0430 \u0433\u043e \u0431\u0430\u0440\u0430 ConfigView.label.maxuploadspeedseeding=KB/s global max upload speed when only seeding [0: unlimited] authenticator.torrent=\u0422\u043e\u0440\u0435\u043d\u0442 ConfigView.section.connection.network.max.simultaneous.connect.attempts=Max simultaneous outbound connection attempts [0: outbound disabled] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Max number of new outbound connection establishments Vuze should attempt any given time.\nNOTE: WindowsXP Service Pack 2 (SP2) imposes a system-wide limit of 10 simultaneous connect attempts.\nDefault value is 8. Value of 0 disables outbound connects entirely. ConfigView.section.file.perf.cache.size.explain=The cache is used to reduce reads from/writes to disk. Unless you are using the java option '-XX:MaxDirectMemorySize' to explicitly set the memory available for cache and network IO use, you should keep this value at least %1 below your maximum VM size. The current maximum VM size is %2. For instructions on how to change this, see MemoryUsage in the wiki on %3. Failure to use sensible settings will result on 'out of memory' errors. More than 32MB of cache is probably overkill. MyTorrentsView.menu.setSpeed.unlimit=\u0411\u0435\u0437 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0443\u0432\u0430\u045a\u0435 MyTorrentsView.menu.setSpeed.unlimited=\u041d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e MyTorrentsView.menu.setSpeed.disable=\u041e\u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u0438 \u0438\u0441\u043f\u0440\u0430\u045c\u0430\u045a\u0435 MyTorrentsView.menu.setSpeed.disabled=\u041e\u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u0435\u043d\u043e GeneralView.label.maxuploadspeed=\u0413\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430\u0433\u043e\u0440\u0435 GeneralView.label.maxuploadspeed.tooltip=\u041d\u0430\u0458\u0433\u043e\u043b\u0435\u043c\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043d\u0430 \u0438\u0441\u043f\u0440\u0430\u045c\u0430\u045a\u0435 [0 : \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430] MyTorrents.items.UpSpeedLimit.disabled=\u0411\u0435\u0437 \u0438\u0441\u043f\u0440\u0430\u045c\u0430\u045a\u0435 MyTorrents.items.UpSpeedLimit.unlimited=\u041d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 TableColumn.header.maxupspeed=\u0413\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430\u0433\u043e\u0440\u0435 TableColumn.header.maxupspeed.info=\u041d\u0430\u0458\u0433\u043e\u043b\u0435\u043c\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043d\u0430\u0433\u043e\u0440\u0435 \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442 MainWindow.menu.tools=\u0410\u043b\u0430\u0442\u043a\u0438 FilesView.path=\u041f\u0430\u0442 FilesView.fullpath=\u041f\u043e\u043a\u0430\u0436\u0438 \u0433\u043e \u0446\u0435\u043b\u0438\u043e\u0442 \u043f\u0430\u0442 FilesView.remaining=\u041f\u0440\u0435\u043e\u0441\u0442\u0430\u043d\u0430\u0442\u0438 \u043f\u0430\u0440\u0447\u0438\u045a\u0430 TableColumn.header.trackername=\u0418\u043c\u0435 \u043d\u0430 \u0442\u0440\u0430\u043a\u0435\u0440\u043e\u0442 MyTorrentsView.confirm_torrent_removal=\u0421\u0438\u0433\u0443\u0440\u043d\u043e \u043b\u0438 \u0441\u043a\u0430\u0442\u0430 \u0434\u0430 \u0433\u043e \u0442\u0440\u0433\u043d\u0435\u0442\u0435?\n TableColumn.header.maxdownspeed=\u041d\u0430\u0458\u0433\u043e\u043b\u0435\u043c\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043d\u0430\u0434\u043e\u043b\u0443 TableColumn.header.maxdownspeed.info=\u041d\u0430\u0458\u0433\u043e\u043b\u0435\u043c\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u043d\u0430\u0434\u043e\u043b\u0443 \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442 TableColumn.header.torrentpath=\u041c\u0435\u0441\u0442\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u0442 TableColumn.header.torrentpath.info=\u041c\u0435\u0441\u0442\u043e \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u0442 \u043d\u0430 \u0434\u0438\u0441\u043a Button.abort=\u041e\u0442\u043a\u0430\u0436\u0438 MainWindow.menu.file.restart=\u0420\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u0458 \u0433\u043e \u0410\u0437\u0443\u0440\u0435\u0443\u0441 deletetorrent.message1=\u040c\u0435 \u0433\u043e \u0438\u0437\u0431\u0440\u0438\u0448\u0435\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u0442 \u0437\u0430 :\n deletetorrent.message2=\n\u0414\u0430\u043b\u0438 \u0441\u0442\u0435 \u0441\u0438\u0433\u0443\u0440\u043d\u0438? ConfigView.label.prioritizemostcompletedfiles=Prioritize most completed files splash.plugin.init=\u0413\u043e \u0438\u043d\u0438\u0446\u0438\u0458\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0442 MyTorrentsView.menu.explore=\u041f\u043e\u043a\u0430\u0436\u0438 \u0458\u0430 \u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430\u0442\u0430 MyTorrentsView.menu.explore._mac=\u041f\u043e\u043a\u0430\u0436\u0438 \u0458\u0430 \u0432\u043e Finder MyTorrentsView.menu.explore._windows=\u041f\u043e\u043a\u0430\u0436\u0438 \u0458\u0430 \u0432\u043e \u0415\u043a\u0441\u043f\u043b\u043e\u0440\u0435\u0440 TableColumn.header.networks=\u041c\u0440\u0435\u0436\u0438 MyTorrentsView.menu.advancedmenu=\u041d\u0430\u043f\u0440\u0435\u0434\u043d\u043e MyTorrentsView.menu.networks=\u041c\u0440\u0435\u0436\u0438 Button.apply=\u041f\u0440\u0438\u043c\u0435\u043d\u0438 Button.close=\u0417\u0430\u0442\u0432\u043e\u0440\u0438 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0437\u0430 \u043d\u043e\u0432\u0430\u0442\u0430 \u0432\u0435\u0440\u0437\u0438\u0458\u0430 dht.reseed.label=Normally reseeding of the Distributed Database is not necessary. However, if the number of contacts is low this can be used for re-integratation.\nLeave blank to bootrap off connected peers or enter IP and port to explicitly bootstrap from a known peer. MainWindow.dht.status.disabled=Disabled MainWindow.dht.status.failed=Failed MainWindow.dht.status.initializing=Initializing MainWindow.dht.status.users=%1 Users MyTorrentsView.menu.setUpSpeed=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u0431\u0440\u0437\u0438\u043d\u0430 \u043d\u0430\u0433\u043e\u0440\u0435 MyTorrentsView.menu.setDownSpeed=\u041f\u043e\u0441\u0442\u0430\u0432\u0438 \u0431\u0440\u0437\u0438\u043d\u0430 \u043d\u0430\u0434\u043e\u043b\u0443 diagnostics.log_found=Vuze did not shutdown tidily. Please check %1 for diagnostic log files and consider reporting them to the Vuze team if this is the result of an application error. # %1 = "in kbps" or ""; %2 = "upload" or "download" OpenTorrentWindow.torrentLocation=\u0414\u0430\u0442\u043e\u0442\u0435\u043a\u0438: # > 2402 MainWindow.menu.help.faq=\u0427\u0435\u0441\u0442\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0443\u0432\u0430\u043d\u0438 \u043f\u0440\u0430\u0448\u0430\u045a\u0430 MainWindow.menu.help.donate=\u0414\u043e\u043d\u0438\u0440\u0430\u0458 azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_nl_NL.properties0000644000175000017500000047744111301156004026112 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torrent-bestand Main.parameter.usage="Gebruik: java org.gudy.azureus2.cl.Main [parameters] "bestand.torrent" "Bewaar pad"" Main.parameter.maxUploads=Max aantal gelijktijdige uploads Main.parameter.maxSpeed=Max uploadsnelheid in bytes/sec MainWindow.menu.file=&Bestand MainWindow.menu.file.open=&Openen MainWindow.menu.file.create=Een torrentbestand maken MainWindow.menu.file.create.fromfile=Van een Bestand MainWindow.menu.file.create.fromdir=Van een Map MainWindow.menu.file.export=XML Torrent &Exporteren... MainWindow.menu.file.import=XML Torrent &Importeren... MainWindow.menu.file.closetab=Sluit &Tab MainWindow.menu.file.closewindow=Sluit Venster MainWindow.menu.file.exit=Afsluiten MainWindow.dialog.choose.file=Kies het torrentbestand MainWindow.menu.file.folder=Map... MainWindow.dialog.choose.folder=Kies de map waar de torrents zich bevinden MainWindow.menu.view=Beeld MainWindow.menu.view.show=Toon MainWindow.menu.view.mytorrents=&Mijn Torrents MainWindow.menu.view.open_global_transfer_bar=Overdrachten balk MainWindow.menu.view.configuration=&Configuratie MainWindow.menu.view.allpeers=Alle Peers MainWindow.menu.closealldetails=Sluit &alle Details MainWindow.menu.closealldownloadbars=Sluit alle Download &Balken MainWindow.menu.language=Taa&l ConfigView.section.language=Taal MainWindow.menu.window=Scherm MainWindow.menu.window.minimize=&Minimaliseren MainWindow.menu.window.alltofront=Breng alles naar voren MainWindow.menu.help=&Help MainWindow.menu.help.about=Over Vuze MainWindow.menu.torrent=Torrent Besturing MainWindow.about.title=Over Vuze MainWindow.about.section.developers=Ontwikkelaars MainWindow.about.section.translators=Vertalers MainWindow.about.section.system=Systeem MainWindow.about.section.internet=Internet MainWindow.about.internet.sourceforge=Sourceforge Projectpagina MainWindow.about.internet.sourceforgedownloads=Sourceforge Downloads. MainWindow.about.internet.bugreports=Fout rapportages MainWindow.about.internet.forumdiscussion=Forums. MainWindow.about.internet.wiki=Vuze Wiki FAQ. MainWindow.dialog.choose.savepath=Kies het pad voor opslag MainWindow.dialog.choose.savepath_forallfiles=Kies het pad voor opslag van ALLE bestanden MainWindow.status.latestversion=Laatste versie MainWindow.status.latestversion.clickupdate=Klik om bij te werken MainWindow.status.unknown=onbekend MainWindow.status.checking=controleren MyTorrentsView.mytorrents=Mijn Torrents TableColumn.header.name=Naam TableColumn.header.size=Grootte TableColumn.header.done=Gedaan TableColumn.header.done.info=Percentage gedaan van huidige taak TableColumn.header.status.info=Wat de torrent doet TableColumn.header.seeds=Seeders TableColumn.header.seeds.info=Aantal seeders waar je mee bent verbonden (aantal seeders totaal) TableColumn.header.peers=Leechers TableColumn.header.peers.info=Aantal leechers waar je mee bent verbonden (aantal leechers totaal) TableColumn.header.completed=Voltooiden TableColumn.header.completed.info=# van peers die de download voltooid hebben zoals geraporteerd door de tracker TableColumn.header.downspeed=Downloadsnelheid TableColumn.header.upspeed=Uploadsnelheid TableColumn.header.tracker=Tracker TableColumn.header.tracker.info=Status van de tracker TableColumn.header.trackernextaccess=Tracker Update TableColumn.header.trackernextaccess.info=Wanneer de volgende tracker verbinding zal plaatsvinden TableColumn.header.priority=Prioriteit TableColumn.header.priority.info=Bepaalt hoeveel upload bandbreedte aan torrent wordt gegeven TableColumn.header.seeds.fullcopycalc=%2 volledige kopie\u00ebn bestemd voor %1 peers MyTorrentsView.menu.showdetails=Bekijk &details MyTorrentsView.menu.showdownloadbar=Toon Download &Balk MyTorrentsView.menu.open=&Openen MyTorrentsView.menu.setpriority=Wijzig &Prioriteit MyTorrentsView.menu.setpriority.high=&Hoog MyTorrentsView.menu.setpriority.low=&Laag MyTorrentsView.menu.remove=Ve&rwijder MyTorrentsView.menu.changeTracker=Voeg Tr&acker URL toe TrayWindow.menu.exit=Afsluiten TrayWindow.menu.show=Open Vuze SystemTray.menu.exit=Afsluiten SystemTray.menu.closealldownloadbars=Sluit &alle Download Balken SystemTray.menu.open_global_transfer_bar=Open overdracht balk SystemTray.menu.show=Toon Vuze PeersView.ip.info=IP van de peer PeersView.port=Poort PeersView.port.info=Poort in gebruik PeersView.T.info=L (lokaal): je hebt verbinding gemaakt, R (afstand): de downloader heeft verbinding gemaakt. PeersView.T.L.tooltip=Je hebt de verbinding gemaakt PeersView.T.R.tooltip=De peer heeft de verbinding gemaakt PeersView.I1=I1 (Ge\u00efnteresseerd door de downloader) PeersView.I1.info=Ben je ge\u00efnteresseerd in wat de andere downloader heeft? PeersView.C1=V1 (Verstopt door de downloader) PeersView.C1.info=Of de downloader je blokkeert bij het downloaden PeersView.pieces=Stukjes PeersView.downloadspeed=Downloadsnelheid PeersView.download=Omlaag PeersView.I2=I2 (Interessant voor de downloader) PeersView.I2.info=Is de andere downloader ge\u00efnteresseerd in wat jij hebt? PeersView.C2=V2 (De downloader verstoppen) PeersView.C2.info=Of jij de downloader blokkeert bij het downloaden PeersView.uploadspeed=Uploadsnelheid PeersView.uploadspeed.info=Je upload snelheid naar de downloader PeersView.upload.info=Je totale upload naar de downloader. PeersView.statup=Up-status PeersView.statup.info=Een geschatte waarde van de upload snelheid van de downloader PeersView.S.info=Afwijzen: Een downloader kan handmatig worden \u201cafgewezen\u201d, of automatisch (voor het niet leveren van data met een waarde die hoog genoeg is) PeersView.downloadspeedoverall=Gemiddelde Downloadsnelheid PeersView.optunchoke=Opt. Ontstop PeersView.client=Cli\u00ebnt PeersView.client.info=Het type BT cli\u00ebnt dat de downloader gebruikt PeersView.menu.snubbed=Afwijzen AllPeersView.title.full=Alle Peers ConfigView.section.files=Bestanden ConfigView.label.usefastresume=Downloads snel herstarten ConfigView.label.incrementalfile=Zet oplopende bestandsgrootte aan [Nodig voor FAT32 onder Linux] ConfigView.label.defaultsavepath=Opslaan in standaard data map ConfigView.button.browse=&Bladeren... ConfigView.dialog.choosedefaultsavepath=Kies de standaard opslag map ConfigView.section.server=Verbindingen ConfigView.section.global=Globaal ConfigView.label.disconnetseed=Verbreek verbinding met zenders tijdens uploaden ConfigView.label.switchpriority=Automatisch omschakelen naar lage prioriteit tijdens zenden ConfigView.label.maxdownloads=Maximum gelijktijdige downloads [0: ongelimiteerd] ConfigView.label.maxdownloads.tooltip=Je kan altijd de hoeveelheid downloads aan hebben staan gelijk aan het nummer hieraangegeven, met 1 uitzondering.\nEen complete torrent die de Eerste Prioriteit criteria heeft, kan een actief download slot overnemen, als deze het absoluut nodig heeft. ConfigView.label.maxactivetorrents=Maximum actieve torrents [0 : ongelimiteerd]\n - Nieuwe torrents starten niet als je meer verzendt/ontvangt ConfigView.label.priorityExtensions=Geef voorrang aan files met bepaalde extensies \n- zoals: .txt;.nfo;.jpg ConfigView.section.transfer=Overdracht ConfigView.label.maxuploads=Standaard maximum uploads slots per torrent ConfigView.label.maxuploadspeed=Globale maximum uploadsnelheid in KB/s [0: ongelimiteerd] ConfigView.label.saveresumeinterval=Update de snel-hervatten data iedere ConfigView.unlimited=Ongelimiteerd ConfigView.section.display=Beeld ConfigView.label.opendetails=Automatisch details-tab openen ConfigView.label.openbar=Automatisch downloadbalk openen ConfigView.label.use_old_speed_menus=Gebruik oude stijl snelheids menu [herstart vereist] ConfigView.label.closetotray=Sluiten minimaliseert naar systeemvak ConfigView.label.minimizetotray=Minimaliseren minimaliseert naar Systeemvak ConfigView.section.general=Algemeen ConfigView.section.start=Start ConfigView.label.showsplash=Laat opstartscherm zien ConfigView.label.autoupdate=Laat de Updatedialoog zien wanneer er een nieuwe versie is ConfigView.label.openconsole=Open de Console tijdens het starten ConfigView.label.openconfig=Open Configuratie tijdens het starten ConfigView.label.startminimized=Start geminimaliseerd ConfigView.section.irc=Irc ConfigView.label.ircwiki=A.U.B. lees http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Server ConfigView.label.ircchannel=Kanaal ConfigView.label.irclogin=Schermnaam ConfigView.group.irctitle=IRC Instellingen ConfigView.boolean.ircsendinfo=Toestaan zenden van jouw instellingen (anoniem) naar\n de operators in het IRC kanaal om hen in staat te stellen jou te helpen ConfigView.boolean.irclog=Aanzetten loggen van de IRC kanaal activiteit (in IRC_log.htm) ConfigView.section.security=Beveiliging ConfigView.label.password=Bescherm Vuze met een wachtwoord\n - Zal om gevraagd worden tijdens het starten en uit het Systeemvak halen. ConfigView.label.passwordconfirm=Wachtwoord (bevestigen) ConfigView.label.passwordmatch=Wachtwoord geactiveerd : ConfigView.label.passwordmatchnone=Nee ConfigView.label.passwordmatchno=Nee / Wachtwoorden komen niet overeen ConfigView.label.passwordmatchyes=Ja ConfigView.button.save=Opslaan ConfigView.title.short=Configuratie ConfigView.title.full=Configuratie ConsoleView.title.short=Console ConsoleView.title.full=Console FileItem.write=schrijven FileItem.read=lezen FileItem.normal=normaal FileItem.high=hoog FileItem.donotdownload=Niet downloaden FilesView.name=Naam FilesView.name.fastRename=Snel hernoemen FilesView.size=Grootte FilesView.done=Gedaan FilesView.%=% FilesView.firstpiece=Eerste stukje No: FilesView.numberofpieces=Aantal stukjes FilesView.pieces=Stukjes FilesView.mode=Modus FilesView.priority=Prioriteit FilesView.menu.open=&Openen FilesView.menu.setpriority=Verander prioriteit FilesView.menu.setpriority.high=&Hoog FilesView.menu.setpriority.normal=&Normaal FilesView.menu.setpriority.skipped=Niet &downloaden FilesView.title.short=Bestanden FilesView.title.full=Bestanden GeneralView.section.downloaded=Gedownload GeneralView.label.status.file=Bestand Status GeneralView.label.status.pieces=Stukjes Status GeneralView.section.availability=Beschikbaarheid GeneralView.label.status.pieces_available=Stukjes Status GeneralView.section.transfer=Overdracht GeneralView.title.short=Algemeen GeneralView.title.full=Algemeen GeneralView.label.timeelapsed=Tijd verstreken : GeneralView.label.remaining=Resterend: GeneralView.label.downloaded=Gedownload : GeneralView.label.downloadspeed=Downloadsnelheid: GeneralView.label.maxuploads=Upload Slots : GeneralView.label.maxuploads.tooltip=Maximum aantal leechers die gelijktijdig ontstopt worden. GeneralView.label.uploaded=Ge\u00fcpload : GeneralView.label.uploadspeed=Uploadsnelheid : GeneralView.label.seeds=Zenders : GeneralView.label.peers=Peers: GeneralView.label.completed=Voltooiden: GeneralView.label.totalspeed=Totalen snelheid : GeneralView.label.totalspeed.tooltip=Totalen (en gemiddelde) snelheid van alle cli\u00ebnts waarmee je verbonden bent. GeneralView.label.averagespeed=gemiddeld GeneralView.label.filename=Naam : GeneralView.label.totalsize=Totalen grootte : GeneralView.label.savein=Opslaan in : GeneralView.label.hash=Hash: GeneralView.label.numberofpieces=Aantal stukjes : GeneralView.label.size=Grootte : GeneralView.label.tracker=Tracker Status : GeneralView.label.updatein=Geupdate in : GeneralView.label.trackerurl=Tracker URL: GeneralView.label.trackerurlupdate=Update de Tracker GeneralView.label.comment=Commentaar : GeneralView.label.user_comment=Gebruiker commentaar : GeneralView.label.status=Status: ManagerItem.waiting=Wachten ManagerItem.allocating=Reserveren ManagerItem.checking=Controleren ManagerItem.ready=Wachten op anderen torrent(s) in wachtrij plaatsen ManagerItem.downloading=Downloaden ManagerItem.seeding=Uploaden ManagerItem.stopped=Gestopt ManagerItem.error=Fout ManagerItem.high=hoog ManagerItem.low=laag MinimizedWindow.name=Naam: MinimizedWindow.all_transfers=Vuze Overdrachten PiecesView.#=Nr: PiecesView.size=Grootte PiecesView.numberofblocks=Aantal Blokken PiecesView.blocks=Blokken PiecesView.completed=Afgerond PiecesView.availability=Beschikbaarheid PiecesView.reservedby=Gereserveerd PiecesView.writers=Blokkeer bijdragers PiecesView.title.short=Stukjes PiecesView.title.full=Stukjes SystemTray.tooltip.seeding=%1 uploaden, SystemTray.tooltip.downloading=%1 downloaden, DownloadManager.error.filenotfound=Bestand niet gevonden DownloadManager.error.fileempty=Torrent bestand is leeg DownloadManager.error.filetoobig=Torrent bestand is te groot DownloadManager.error.filewithouttorrentinfo=Geen torrent informatie gevonden in bestand DownloadManager.error.unsupportedencoding=Niet ondersteunde Codering DownloadManager.error.ioerror=I/O-fout DownloadManager.error.sha1=Onbekend Algoritme (SHA1) Fout PeerManager.status.offline=Connectie Fout PeerManager.status.ok=Ok PeerManager.status.checking=Controleren PeerManager.status.finished=Afgerond PeerManager.status.finishedin=Afgerond in MainWindow.upgrade.assistant=Update-assistent MainWindow.upgrade.newerversion=Er is een nieuwen versie van Vuze beschikbaar MainWindow.upgrade.explanation=Deze assistent zal de nieuwe versie downloaden in je Vuze map en Vuze herstarten MainWindow.upgrade.explanation.manual=Je kunt handmatig updaten door Vuze te sluiten, de nieuwe versie te downloaden en Vuze weer te starten MainWindow.upgrade.step1=Stap 1: Download de nieuwe versie MainWindow.upgrade.step2=Stap 2: Sluit deze versie en start de nieuwe versie van Vuze MainWindow.upgrade.hint1=Hint:\tDoor op Voltooien te drukken zal alles automatisch gaan MainWindow.upgrade.hint2=Hint:\tAls je Vuze later wilt afsluiten, druk op Annuleren en\n\therbenoem Azureus2-new.jar naar Azureus2.jar na het sluiten MainWindow.upgrade.error.downloading.hint=Fout:\tKan geen nieuwe versie downloaden, update Vuze handmatig MainWindow.upgrade.section.info=Nieuwe versie beschikbaar MainWindow.upgrade.section.manual=Handmatige update MainWindow.upgrade.section.automatic=Automatische update MainWindow.upgrade.tooltip.progressbar=De download voortgang is hier te zien Button.next=Volgende Button.finish=Voltooien Button.cancel=Annuleren LocaleUtil.title=Kies Codering LocaleUtil.section.chooseencoding=Kies codering voor bestandsnaam LocaleUtil.label.chooseencoding=Kies de best passende codering LocaleUtil.label.hint.doubleclick=Hint: Dubbelklikken op een regel kiest coderen en sluit de dialoog LocaleUtil.label.checkbox.rememberdecision=Onthoud beslissing voor overige bestandsnamen LocaleUtil.column.encoding=Coderen IrcClient.defaultChannel=#Azureus-Dutch IrcClient.copyright=PircBot Java IRC API wordt gebruikt - http://www.jibble.org/pircbot.php IrcClient.connecting=Verbinden met IrcClient.connected=Verbonden met IrcClient.joining=Inloggen IrcClient.channel=Kanaal IrcClient.joined=ingelogd IrcClient.error=Fout IrcClient.hasjoined=is verbonden IrcClient.haskicked=is gekickt IrcClient.hasleft=is vertrokken IrcClient.nowknown=is nu bekend als IrcClient.topicforchannel=Onderwerp van dit kanaal IrcClient.disconnected=Verbinding verloren met IrcClient.noNick=Geen schermnaam opgegeven. Ga naar het 'Configuratie' scherm IrcView.actionnotsupported=Deze actie wordt niet ondersteund IrcView.clientsconnected=gebruikers IrcView.privateto=Aan IrcView.privatefrom=Van IrcView.noticefrom=Let op : IrcView.errormsg=Verkeerde Syntax bij /msg : /msg gebruiker tekst IrcView.help=Geldige commando's zijn :\n . /help : geeft dit bericht weer\n . /Nick | /naam : wijzigt je naam \n . /me actie : verstuurt een actie \n . /msg naam bericht : stuurt een priv\u00e9bericht naar \n . /r bericht : antwoordt op laatste priv\u00e9bericht\n . /join #kanaal : wijzigt het huidige kanaal PasswordWindow.title=Vuze is vergrendeld PasswordWindow.passwordprotected=Vuze is beschermd met een wachtwoord.\nVul hier je wachtwoord in, om het venster te tonen : Button.ok=&Ok TrackerChangerWindow.title=Voeg Tracker toe TrackerChangerWindow.newtracker=Vul een nieuw tracker adres in PeersView.discarded=Verworpen PeersView.discarded.info=Data die je wel hebt ontvangen, maar niet nodig hebt, dus je hebt het verwijderd. discarded=verworpen MyTorrentsView.#=Nr: MyTorrentsView.menu.move=Verplaats MyTorrentsView.menu.moveUp=Omhoog MyTorrentsView.menu.moveDown=Omlaag GeneralView.label.hashfails=Hashfouten : GeneralView.label.shareRatio=Deelverhouding : ConfigView.section.downloadManagement=Download beheer ConfigView.label.startRatioPeers=Start met uploaden wanneer er minder dan 1 uploader is voor ConfigView.text.neverStop=Nooit stoppen ConfigView.text.neverStart=Nooit starten ConfigView.text.peers=Peers ConfigView.label.checkOncompletion=Controleer de stukjes na voltooiing download opnieuw wizard.title=Maak een torrent wizard.previous=< Vorige wizard.next=Volgende > wizard.finish=Voltooien wizard.mode=Tracker / Modus wizard.tracker=Tracker: wizard.invalidurl=Dit adres is niet geldig wizard.singlefile=Enkel bestand wizard.singlefile.help=Maak een torrent aan van een enkel bestand wizard.directory=Map wizard.directory.help=Maak een torrent aan van een map wizard.choosefile=Selecteer het bestand wizard.file=Bestand : wizard.browse=Bladeren... wizard.choosedirectory=Kies een map wizard.invalidfile=Ongeldig bestand! wizard.invaliddirectory=Ongeldige map! wizard.torrentFile=Torrent bestand wizard.choosetorrent=Kies het torrentbestand om aan te maken wizard.information=Informatie wizard.notimplemented=Nog niet beschikbaar wizard.progresstitle=Aanmaken Torrent bestand wizard.savingfile=Bestand opslaan... wizard.filesaved=Bestand opgeslagen. wizard.close=Sluiten Torrent.create.progress.piecelength=Lengte stukjes: Torrent.create.progress.piececount=Aantal stukjes: Torrent.create.progress.totalfilesize=Totalen bestandsgrootte: Torrent.create.progress.totalfilecount=Totaal aantal bestanden: Torrent.create.progress.parsingfiles=Doorgeven bestanden Torrent.create.progress.hashing=Berekenen bestanden MainWindow.upgrade.downloadingfrom=Downloaden van : ConfigView.section.ipfilter.description=Omschrijving ConfigView.section.ipfilter.start=Begin IP ConfigView.section.ipfilter.end=Eind IP ConfigView.section.ipfilter.add=Toevoegen ConfigView.section.ipfilter.remove=Verwijderen ConfigView.section.ipfilter.edit=Bewerken ConfigView.section.ipfilter.save=Opslaan ConfigView.section.ipfilter.editFilter=Bewerk Filter ConfigView.section.ipfilter.enable=Aanzetten PeersView.menu.close=Sluiten seedmore.title=Torrent wordt niet genoeg verspreid seedmore.shareratio=Je deelverhouding voor deze torrent is seedmore.uploadmore=Een deelverhouding van minder dan 100% is niet goed voor het Bittorrent netwerk.\nJe zou deze torrent nog wat langer moeten uploaden.\nWeet je zeker dat je wilt doorgaan? ConfigView.label.showpopuponclose=Laat een popup zien als je stopt met uploaden met een deelverhouding lager dan 1 ConfigView.label.startNumSeeds=\nBegin met uploaden als er minder dan\n - Vervangt alle andere regels ConfigView.label.seeds=seeders ConfigView.section.seeding=Uploaden MyTorrentsView.menu.removeand=&Verwijder (extreem) MyTorrentsView.menu.removeand.deletetorrent=Verwijder &Torrent bestand MyTorrentsView.menu.removeand.deletedata=Verwijder &Data MyTorrentsView.menu.removeand.deleteboth=Verwijder &Beide deletedata.title=!!! Waarschuwing !!! deletedata.message1=Je staat op het punt de DATA te verwijderen van : MainWindow.menu.file.configure=Configuratie &Wizard... configureWizard.title=Configuratie wizard configureWizard.welcome.title=Welkom bij de Vuze Configuratie wizard configureWizard.welcome.message=Deze wizard helpt met het instellen van Vuze voor algemeen gebruik. Het is mogelijk om via Gereedschappen->Configuratie menu Vuze meer gedetailleerd in te stellen configureWizard.transfer.title=Verbindings en Overdracht setup configureWizard.transfer.hint=Hint : Een klein beetje minder dan je verbindingsnelheid is de beste instelling. configureWizard.transfer.message=Kies een verbinding hier beneden. Houdt er rekening mee dat een kleine upload resulteert in lage downloadsnelheden. Omdat de uploadsnelheid enkel PER torrent geldt, zal het downloaden van teveel torrents ook in lage snelheden resulteren. We raden aan 5kB/s per torrent als minimum te gebruiken. Hoe sneller je upload, des te sneller je zult downloaden (rekening houdend met de torrent snelheid). configureWizard.transfer.connection=Lijn configureWizard.transfer.connection.0=Handmatig configureWizard.transfer.connection.2=adsl/kabel xxx/128 kbps configureWizard.transfer.connection.3=adsl/kabel xxx/256 kbps configureWizard.transfer.connection.4=adsl/kabel xxx/384 kbps configureWizard.transfer.connection.5=adsl/kabel xxx/512 kbps configureWizard.transfer.connection.6=adsl/kabel xxx/768 kbps configureWizard.transfer.connection.7=adsl/kabel xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Max Uploadsnelheid (KB/s) configureWizard.transfer.maxActiveTorrents=Max Actief configureWizard.transfer.maxDownloads=Max. Downloads configureWizard.transfer.maxUploadsPerTorrent=Max. Uploads per Torrent configureWizard.nat.title=NAT / Server Poort configureWizard.nat.message=Om het beste uit Bittorrent te behalen is het raadzaam om goed bereikbaar te zijn vanaf het internet. De standaard poort is 6881. Dit programma helpt met het testen / veranderen van de poort. configureWizard.nat.testing=Testen van poort configureWizard.nat.ok=NAT OK ! configureWizard.nat.ko=NAT-Fout configureWizard.nat.unable=Kan niet testen: Verkeerde poort opgegeven, of de test service mislukt.\nEen ander programma maakt misschien gebruik van deze poort. configureWizard.file.title=Torrents / Bestanden configureWizard.file.message1=Vuze zal geopende torrents in een speciale map opslaan. Je kunt deze map hier aangeven: configureWizard.file.path=Pad configureWizard.file.browse=Bladeren configureWizard.file.message2=Vuze kan gedownloade bestanden direct hervatten door gegevens toe te voegen aan de torrents. Door het gebruik van deze functie kun je ook gedeeltelijk gedownloade stukjes hervatten. configureWizard.file.fastResume=Schakel snel hervatten in configureWizard.file.invalidPath=Ongeldige map configureWizard.finish.title=Voltooid configureWizard.finish.message=Vuze is nu geconfigureerd. Veel plezier ! wizard.close.confirmation=Bevestiging wizard.close.message=Wil je deze wizard starten als Vuze de volgende keer start? exportTorrentWizard.title=Exporteer een XML torrent exportTorrentWizard.torrentfile.title=Importeer Torrent Selectie exportTorrentWizard.torrentfile.message=Selecteer het te exporteren torrentbestand exportTorrentWizard.torrentfile.path=Pad exportTorrentWizard.torrentfile.browse=Bladeren exportTorrentWizard.torrentfile.invalidPath=Ongeldig torrentbestand exportTorrentWizard.exportfile.title=Exporteer Bestand Selectie exportTorrentWizard.exportfile.message=Voer de naam van het te exporteren XML bestand in exportTorrentWizard.exportfile.path=Pad exportTorrentWizard.exportfile.browse=Bladeren exportTorrentWizard.exportfile.invalidPath=Ongeldig export bestand exportTorrentWizard.finish.title=Afgerond exportTorrentWizard.finish.message=Exporteren is succesvol voltooid exportTorrentWizard.process.inputfilebad.title=Torrentbestand Ongeldig exportTorrentWizard.process.inputfilebad.message=Er is een fout opgetreden tijdens het openen van invoerbestand: exportTorrentWizard.process.outputfileexists.title=Bestand bestaat exportTorrentWizard.process.outputfileexists.message=Uitvoerbestand bestaat - overschrijven? exportTorrentWizard.process.torrentfail.title=Torrent Lezen Mislukt exportTorrentWizard.process.exportfail.title=Torrent Exporteren Mislukt exportTorrentWizard.process.unknownfail.title=Onverwachte fout importTorrentWizard.title=Importeer een XML torrent importTorrentWizard.torrentfile.title=Voer Torrent Selectie in importTorrentWizard.torrentfile.message=Voer het torrent bestand in om naar te importeren importTorrentWizard.torrentfile.path=Pad importTorrentWizard.torrentfile.browse=Bladeren importTorrentWizard.torrentfile.invalidPath=Ongeldig torrentbestand importTorrentWizard.importfile.title=Importeer Bestands Selectie importTorrentWizard.importfile.message=Selecteer het XML-bestand om te importeren importTorrentWizard.importfile.path=Pad importTorrentWizard.importfile.browse=Bladeren importTorrentWizard.importfile.invalidPath=Ongeldig import bestand importTorrentWizard.finish.title=Afgerond importTorrentWizard.finish.message=Importeren succesvol voltooid importTorrentWizard.process.inputfilebad.title=Het Import bestand is ongeldig importTorrentWizard.process.inputfilebad.message=Er is een fout opgetreden tijdens het openen van invoerbestand: importTorrentWizard.process.outputfileexists.title=Bestand bestaat importTorrentWizard.process.outputfileexists.message=Uitvoerbestand bestaat - overschrijven? importTorrentWizard.process.torrentfail.title=Torrent Schrijven Mislukt importTorrentWizard.process.importfail.title=Torrent Importeren Mislukt importTorrentWizard.process.unknownfail.title=Onverwachte fout ConfigView.label.bindip=Koppel aan lokaal IP adres ConfigView.label.xfs.allocation=Wijs nieuwe files toe met gebruikmaking van van de specifieken methode voor het XFS filesystem ConfigView.label.xfs.allocation.tooltip=Gelieve ervoor te zorgen dat /usr/sbin/xfs_io is behoorlijk ge\u00efnstalleerd op uw systeem. Voor de meeste distributies van Linux, is het inbegrepen in het "xfsprogs" pakket. xfs.allocation.xfs_io.not.found=XFS filetoewijzing ontbrak omdat /usr/sbin/xfs_io niet gestart kan worden. Zorg ervoor het behoorlijk ge\u00efnstalleerd is op uw systeem. De originele fout was: "%1". ConfigView.label.zeronewfiles=Bestanden van grootte 0 bij aanmaken ConfigView.label.zeronewfiles.tooltip=Minimaliseert fragmentatie ConfigView.section.stats=Statistieken ConfigView.section.stats.enable=Inschakelen ConfigView.section.stats.defaultsavepath=Map voor statistieken ConfigView.section.stats.choosedefaultsavepath=Kies de opslagplaats voor de statistieken ConfigView.section.stats.savefreq=Opslag frequentie ConfigView.section.stats.minutes=min ConfigView.section.stats.hours=uur ConfigView.section.stats.seconds=sec ConfigView.section.stats.savefile=Statistiek bestand naam ConfigView.section.stats.graph_update_dividers=Toon een verticale lijn bij elke 60 updates. MyTorrentsView.menu.export=&XML Exporteren... MyTorrentsView.menu.host=&Host.. ManagerItem.finishing=Afronden ConfigView.dialog.choosedefaulttorrentpath=Kies de standaard map voor opslag van torrents ConfigView.dialog.choosemovepath=Kies de standaard map om naar te verplaatsen ConfigView.label.movecompleted=Verplaats voltooide bestanden ConfigView.label.moveremoved=Verplaats voltooide files (wanneer wordt verwijderd) ConfigView.label.savetorrents=Bewaar .torrent bestanden MainWindow.menu.view.mytracker=Mijn &Tracker MyTrackerView.title.full=Mijn Tracker MyTrackerView.name=Naam MyTrackerView.status.started=Bezig MyTrackerView.status.stopped=Gestopt MyTrackerView.peers=Leechers MyTrackerView.seeds=Seeders MyTrackerView.announces=Aankondigingen MyTrackerView.uploaded=Ge\u00fcpload MyTrackerView.downloaded=Gedownload MyTrackerView.left=Resterend ConfigView.section.style=Uiterlijk ConfigView.label.set_ui_transfer_speeds=Overschrijf selecteerbaren overdrachtsnelheden ConfigView.label.set_ui_transfer_speeds.description=Aanpassen standaard beschikbare download en upload snelheden, beschikbaar in de status bar in de systeem tray.\nDe waarde moet komma gescheiden zijn. ConfigView.label.set_ui_transfer_speeds.description.download=Zet download snelheid (in KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Zet upload snelheid (in KB/s) ConfigView.section.style.useCustomTabs=Gebruik sluitbare tabs (herstart nodig) fileDownloadWindow.saveTorrentIn=Bewaar Torrentbestand In fileDownloadWindow.downloading=Downloaden Van : fileDownloadWindow.status=Status : fileDownloadWindow.state_initializing=Initialiseren fileDownloadWindow.state_downloading=Downloaden fileDownloadWindow.state_error=Fout : MainWindow.menu.file.open.url=&Locatie openUrl.title=Open Locatie MyTorrentsView.menu.host.error.title=Torrent Hosting mislukt MyTorrentsView.menu.host.error.message=De volgende foutmelding trad op tijdens het hosten van de torrent ConfigView.section.tracker=Tracker ConfigView.section.tracker.pollinterval=Tracker cli\u00ebnt afstemming interval (sec) ConfigView.section.tracker.publishenable="Publiceer torrent details naar """ ConfigView.section.tracker.ip=IP-adres van externe tracker ConfigView.section.style.enableXPStyle=Activeer XP stijl (herstart nodig) ConfigView.section.tracker.checkip=Automatisch extern IP adres opzoeken... ipCheckerWizard.title=Wizard IP Controle ipCheckerWizard.service=Diensten ipCheckerWizard.chooseService=Kies een dienst voor IP Controle Service uit de lijst hieronder ipCheckerWizard.explanations=Je kan deze wizard gebruiken, om uit te vinden wat je externe IP adres is. Als je IP adres dynamisch is, raden we je aan dat je een account opent bij een Dynamic DNS Service. Enkele van deze diensten zijn hieronder aangegeven, gebruik de link om een account te maken (waar mogelijk). Vul vervolgens het IP adres veld met je dynamische hostnaam (bijv: myhostname.dyndns.org). Je hebt een programma om automatisch je Dynamic DNS Service te updaten met je IP adres. Op die manier, kan je torrents hosten, zelfs als je IP verandert. ipCheckerWizard.service.description=Omschrijving : ipCheckerWizard.service.url=Link: ipCheckerWizard.progresstitle=IP controleren ipCheckerWizard.checkComplete=Afgerond IP : ipCheckerWizard.checkFailed=Mislukt, reden : wizard.tracker.local=Gebruik Vuze ingebouwde tracker wizard.tracker.external=Gebruik een externe Tracker wizard.tracker.howToLocal=\tGa naar 'Gereedschappen -> Configuratie-> Tracker' om het in te schakelen wizard.announceUrl=Deel URL mee : IPChecker.external.service.discoveryvip.description=Discoveryvip - IP adres alleen controleren IPChecker.external.httpinvalidresponse=Ongeldige HTTP response IPChecker.external.loadingwebpage=Webpagina laden IPChecker.external.analysingresponse=Response analyseren IPChecker.external.addressextracted=IP adres gevonden IPChecker.external.httploadfail=Pagina laden mislukt IPChecker.external.timeout=Time-out opgetreden IPChecker.external.ipnotfound=IP adres niet gevonden ConfigView.section.tracker.pollintervalmin=Minimum ConfigView.section.tracker.pollintervalmax=Maximum ConfigView.section.tracker.pollintervalincby=Ophogen met ConfigView.section.tracker.pollintervalincper=Iedere ' x ' Cli\u00ebnten splash.loadingImages=Afbeeldingen Laden splash.initializeGui=Initialiseren Hoofdvenster splash.openViews=Openen van Schermen splash.plugin=Plugin wordt geladen : configureWizard.nat.tooManyPorts=Te veel poorten om te testen (9 max) ConfigView.section.color=Kleuren Schema MyTorrentsView.menu.publish=&Publiceren... MyTrackerView.status.published=Gepubliceerd MyTrackerView.completed=Voltooid MainWindow.menu.file.open.torrentnodefault=Torrent-bestand (Geen standaardopslag) wizard.comment=Commentaar ConfigView.label.movetorrent=Verplaats .torrent ConfigView.label.movepartialdownloads="Verplaats wanneer sommigen files zijn gemarkeerd met "Niet downloaden"." ConfigView.label.subdir_is_in_default=Als overweging dat downloads bestaan in een standaard directorie, overweeg dan ook de standaard subdirectorie. ConfigView.section.file.decoder.label=Standaard torrent codering wanneer selectie nodig is ConfigView.section.file.decoder.nodecoder=Geen IPChecker.external.service.no-ip.description=Dynamic en Static DNS service provider\n(niet vrij beschikbaar 'check adres' service) ConfigView.section.tracker.publicenable=Externe torrents toestaan ConfigView.label.playdownloadspeech=Spreek wanneer een download voltooid is ConfigView.label.playdownloadspeech.info=De Spraak Service werkt het beste met Engels # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Laat het aantal beschikbare kopie\u00ebn zien van ieder deel.\nAls het nummer rechts kleiner dan 1 is, dan zie je geen volledige kopie van het bestand (en kan je problemen hebben bij het voltooien van de download). GeneralView.label.trackerurl.tooltip=Klik om de url naar het klembord te kopi\u00ebren GeneralView.label.trackerurlopen.tooltip=Klik om de hoofdpagina van de tracker te openen # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Update GUI iedere ConfigView.section.style.inactiveUpdate=Update hooft scherm elke N GUI update(s) wanneer het niet het active scherm is. ConfigView.section.style.graphicsUpdate=Update Grafische balken iedere N GUI update(s) ConfigView.section.style.reOrderDelay=Deel de tabellen iedere N GUI update(s) opnieuw in [0: nooit] ConfigView.section.style.reOrderDelay.never=Nooit ConfigView.section.logging=Logging ConfigView.section.logging.enable=Schakel logbestand in ConfigView.section.logging.logdir=Logbestand map ConfigView.section.logging.choosedefaultsavepath=Kies de opslagmap GeneralView.label.updatein.querying=Wachten... configureWizard.nat.sharePort=Gebruik een enkele gedeelde poort voor alle torrents ConfigView.section.logging.maxsize=maximale grootte van logbestand ConfigView.section.tracker.passwordenableweb=Schakel trackerweb wachtwoord in ConfigView.section.tracker.passwordenabletorrent=torrents wachtwoord inschakelen ConfigView.section.tracker.username=Gebruikersnaam ConfigView.section.tracker.password=Wachtwoord columnChooser.title=Selecteer kolommen columnChooser.move=Sleep de rijen om ze opnieuw in te delen columnChooser.apply=Toepassen columnChooser.columnname=Kolom Naam columnChooser.columndescription=Beschrijving TableColumn.header.shareRatio=Deelverhouding MyTorrentsView.menu.editTableColumns=Selecteer kolommen wizard.operationfailed=Operatie mislukt authenticator.title=Verificatie vereist authenticator.realm=Domein authenticator.tracker=Tracker authenticator.user=Gebruikersnaam authenticator.password=Wachtwoord ConfigView.label.allowSendVersion=Geef Vuze toestemming om anoniem het versienummer en een willekeurig ID door te geven bij het zoeken naar een nieuwe versie ConfigView.label.version.info.link=Kijk hier voor details voor welke data is verzonden naar de versie controle server. wizard.hint.mode=Hint:\tJe kunt een enkele map of bestand op deze wizard slepen \n\tom een map of bestand te kiezen wizard.hint.file=Hint:\tJe kunt een enkel bestand kiezen door te slepen wizard.hint.directory=Hint:\tJe kunt een enkele map kiezen door te slepen MainWindow.menu.help.checkupdate=&Controleer of er een nieuwe versie is TableColumn.header.down=Gedownload TableColumn.header.up=Ge\u00fcpload ConfigView.section.tracker.passwordenabletorrent.info=Hier is een goede Bittorrent cli\u00ebnt voor nodig (zoals Vuze) ConfigView.section.style.confirmationOnExit=Laat bevestigingsvenster zien bij afsluiten MainWindow.dialog.exitconfirmation.title=Vuze afsluiten? MainWindow.dialog.exitconfirmation.text=Wil je Vuze echt afsluiten? SystemTray.menu.stopalltransfers=Stop &Alle Overdrachten TrayWindow.menu.stopalldownloads=Stop &Alle Downloads ConfigView.section.tracker.sslport.info=Zie de FAQ voor meer informatie wizard.tracker.ssl=Gebruik SSL ConfigView.label.playdownloadfinished=Speel een geluid af wanneer een download voltooid is ConfigView.label.popupdownloadfinished=Popup een waarschuwing als een download klaar is ConfigView.label.popupfilefinished=Popup een waarschuwing als een deel van een bestand klaar is TableColumn.header.pieces=Stukjes TableColumn.header.pieces.info=Grafische balk vertegenwoordigt welke delen je hebt gedownload TableColumn.header.completion=Afgerond TableColumn.header.completion.info=Grafische vertegenwoordiging van % gedownload ConfigView.section.style.showdownloadbasket=Laat Downloadmand zien (Sleep-en-plaats .torrents) ConfigView.section.style.alwaysShowTorrentFiles=Laat altijd Torrent bestanden zien in Details/Bestanden wizard.multitracker=Voeg Multi-Tracker informatie aan de torrent toe wizard.multitracker.title=Multi -Tracker wizard.multitracker.configuration=Multi-Tracker Configuratie wizard.multitracker.new=Nieuw... wizard.multitracker.edit=Bewerken.. wizard.multitracker.delete=Verwijderen wizard.multitracker.group=Tracker Groep wizard.multitracker.edit.title=Multi-Tracker Editor wizard.multitracker.edit.name=Naam wizard.multitracker.edit.save=Opslaan wizard.multitracker.edit.newgroup=Nieuwe Groep wizard.multitracker.edit.deletegroup=Verwijderen wizard.multitracker.edit.newtracker=Nieuwe Tracker wizard.multitracker.edit.deletetracker=Verwijderen wizard.multitracker.edit.edit=Bewerken wizard.addingmt=Voeg Multi-Tracker informatie toe wizard.multitracker.noannounce=Mededeling URL staat niet op je trackerlijst MyTorrentsView.menu.recheck=Forceer hercontrole iconBar.showDownloadBar.tooltip=Laat Downloadbalk zien iconBar.remove.tooltip=Verwijderen iconBar.openNoDefault.tooltip=Open een .torrent-bestand (geen standaardopslag) iconBar.openURL.tooltip=Open een URL iconBar.openFolder.tooltip=Open een map iconBar.new.tooltip=Maak een torrent iconBar.up.tooltip=Omhoog iconBar.down.tooltip=Verplaats Omlaag iconBar.run.tooltip=Open iconBar.publish.tooltip=Publiceren MyTorrentsView.menu.editTracker=Bew&erk Tracker-URL('s) GeneralView.menu.selectTracker=Selecteer ConfigView.section.stats.xslfile=XSL-bestandsnaam ConfigView.section.stats.xslfiledetails=Deze wordt opgenomen in de header van het statistiekenbestand\nvia de tag ConfigView.label.savetorrentbackup=Sla reservekopie op ConfigView.section.tracker.forceport=Forceer gehoste externe torrents naar standaard poort ConfigView.section.ipfilter.allow=TOESTAAN van deze gebieden (standaard is WEIGEREN) ConfigView.section.ipfilter.list.inrange=zat binnen het gebied ConfigView.section.ipfilter.list.notinrange=zat niet binnen een gebied ConfigView.section.ipfilter.list.title=Lijst geblokkeerde IP's ConfigView.label.allowsameip=Meerdere verbindingen van het zelfde IP toestaan ConfigView.label.allowsameip.tooltip=Alleen aanvinken indien NODIG.\nDit is een leecher bescherming (indien uitgeschakeld). ManagerItem.superseeding=Super-Seeden ConfigView.label.userSuperSeeding=Gebruik Super-Seeden (werkt alleen bij eerste en als enige seeder) PeersView.uniquepiece=Deeltje (Super-Seed Modus) PeersView.uniquepiece.none=Geen PeersView.timetosend=Tijd tot het opnieuw versturen van stukje (Super-Seed Modus) ConfigView.section.style.addurlsilently=Open passed URLs stilzwijgend ConfigView.section.style.addurlsilently.tooltip=Automatisch passed/gedropte .torrent URLs downloaden zonder een dialoog venster te openen. ConfigView.section.file.decoder.prompt=Altijd vragen wanneer codering keuze beschikbaar is ConfigView.section.file.decoder.prompt.tooltip=Laat altijd een dialoog zien wanneer codering keuze beschikbaar is MyTorrentsView.menu.moveTop=Verplaats naar &top MyTorrentsView.menu.moveEnd=Verplaats naar &bodem ConfigView.label.moveonlyusingdefaultsave=alleen als in standaard data map ConfigView.label.moveonlyusingdefaultsave.tooltip=Alleen verplaatsen als de gedownloade data zich in de standaard data map bevind ConfigView.label.watchtorrentfolder=Importeer automatisch nieuwe torrents ConfigView.label.watchtorrentfolder.tooltip=Zoekt regelmatig naar nieuwe .torrents ConfigView.label.watchtorrentfolderinterval=Tussen pauze ConfigView.label.watchtorrentfolderinterval.tooltip=Tussen pauze tot de map opnieuw gescand wordt ConfigView.dialog.choosewatchtorrentfolderpath=Kies de .torrent importeer map ConfigView.label.startwatchedtorrentsstopped=Begin gestopt ConfigView.label.startwatchedtorrentsstopped.tooltip=Voeg nieuwe torrents toe met als status GESTOPT ConfigView.section.plugins=Plugins wizard.maketorrent.filesize=Grootte bestand(en) wizard.maketorrent.piececount=Aantal stukjes wizard.maketorrent.piecesize=Grootte stukjes wizard.maketorrent.auto=Automatisch MainWindow.menu.view.stats=&Statistieken SpeedView.title.full=Activiteit SpeedView.downloadSpeed.title=Downloadsnelheid SpeedView.uploadSpeed.title=Uploadsnelheid ConfigView.section.style.useSIUnits=Gebruik IEC-eenheden (KB -> KiB enz.) iconBar.top.tooltip=Verplaats naar top iconBar.bottom.tooltip=Verplaats naar onderen TableColumn.header.health=Status MyTorrentsView.menu.health=Statusinformatie health.explain.grey=betekent dat je torrent niet aanstaat (upload of download) health.explain.red=betekent dat je niet met een peer bent verbonden tijdens downloaden health.explain.blue=bij uploaden betekent dit dat je niet met een peer bent verbonden\nbij downloaden betekent dit dat je wel verbonden bent met een aantal peers, maar dat de tracker niet verbonden is health.explain.yellow=betekent dat de tracker goed is, je met peers verbonden bent, maar dat je geen verbinding op afstand hebt.\nJe kan een NAT-probleem hebben als de torrents altijd geel blijven. health.explain.green=betekent dat alles goed is. ConfigView.section.style.alwaysRefreshMyTorrents=Mijn Torrents altijd verversen ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Deze optie ververst Mijn Torrent scherm, ook als het venster niet weergegeven wordt (handig voor enkele mIRC-plugins) # #2.0.7.0 # security.certtruster.title=Beveiliging Certificaat Waarschuwing security.certtruster.intro=Het beveiliging certificaat is vrijgegeven door een bedrijf dat je niet vertrouwt security.certtruster.resource=Bron: security.certtruster.issuedto=Vrijgegeven aan: security.certtruster.issuedby=Vrijgegeven door: security.certtruster.prompt=Wil je het vertrouwen? security.certtruster.yes=Ja security.certtruster.no=Nee ConfigView.section.tracker.torrentsperpage=Maximum aantal torrents per pagina? [0: ongelimiteerd] MainWindow.menu.file.share=Delen MainWindow.menu.file.share.file=Bestand... MainWindow.menu.file.share.dir=Map... MainWindow.menu.file.share.dircontents=Map &Inhoud... MainWindow.menu.file.share.dircontentsrecursive=Map Inhoud (&Recursief/met sub mappen) MainWindow.dialog.share.sharefile=Selecteer het te delen bestand MainWindow.dialog.share.sharedir=Selecteer de te delen map MainWindow.dialog.share.sharedircontents=Selecteer de te delen mapinhoud MainWindow.dialog.share.sharedircontents.recursive=Recursief globalmanager.download.remove.veto=Verwijdering actie geweigerd plugin.sharing.download.remove.veto=Deze download is het resultaat van een gedeelde bron.\nOm te verwijderen, verwijder de bijbehorende gedeelde bron: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Hoofd ConfigView.section.tracker.web=Web ConfigView.label.prioritizefirstpiece=Geef het eerste deel van bestand(en) voorrang ConfigView.label.prioritizefirstpiece.tooltip=Probeert het eerste deel van een bestand eerst te downloaden.\nOm previews te ondersteunen. ConfigView.section.file.confirm_data_delete=Bevestig het verwijderen van data ConfigView.section.file.confirm_data_delete.tooltip=Bevestig het verwijderen van data bij het gebruik van 'Verplaats en Verwijder...' ConfigView.section.file.delete.include_files_outside_save_dir=Bij verwijderen van data, torrents die gelinkt zijn in een opslag directorie ook verwijderen. TrayWindow.menu.startalldownloads=Start Alle Downloads SystemTray.menu.startalltransfers=Start Alle Overdrachten sharing.progress.title=Voortgang van het Delen sharing.progress.hide=Verbergen MainWindow.menu.view.myshares=Mijn gedeelde bronnen MySharesView.title.full=Mijn Gedeelde Bronnen MySharesView.name=Naam MySharesView.type=Type MySharesView.type.file=Bestand MySharesView.type.dir=Map MySharesView.type.dircontents=Map inhoud MySharesView.type.dircontentsrecursive=Map inhoud (recursief/met sub mappen) MySharesView.menu.remove=Verwijderen ConfigView.section.tracker.extensions=Extensies ConfigView.section.tracker.sendpeerids=Zend peer identiteit naar leechers ConfigView.section.tracker.enableudp=Activeer UDP tracker protocol plugin.sharing.torrent.remove.veto=Deze download is het resultaat van een gedeelde bron.\nOm te verwijderen, verwijder de bijbehorende gedeelde bron: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Deze download kan niet verwijderd worden omdat deze niet gestopt is plugin.sharing.remove.veto=Deze deling is een subdeling van een gedeelde 'map inhoud' en kan (dit benadrukt) niet worden verwijderd.\n Verwijder de hoofd deling. GeneralView.label.hash.tooltip=Klik om de hash naar het klembord te kopi\u00ebren ConfigView.section.tracker.maxpeersreturned=Maximum peers terugkrijgen [0: ongelimiteerd] ConfigView.label.serverport=Inkomende TCP/UDP luister poort ConfigView.label.serverport.tooltip=Poort moet in een range van 1-65535 zijn en niet 6880, omdat die voor intern gebruik van Vuze is gereserveerd. configureWizard.nat.server.tcp_listen_port=Inkomende TCP luister poort ConfigView.section.sharing=Delen ConfigView.section.sharing.usessl=Gebruik SSL voor gedeelde bronnen (vereist Tracker configuratie) ConfigView.section.style.dropdiraction='Sleep-en-plaats' actie voor mappen ConfigView.section.style.dropdiraction.opentorrents=Open Torrents ConfigView.section.style.dropdiraction.sharefolder=Deel map ConfigView.section.style.dropdiraction.sharefoldercontents=Deel inhoud # # 2.0.7.x # Categories.all=Alle Categories.uncategorized=Ongecategoriseerd CategoryAddWindow.message=Voer een nieuwe categorie naam in CategoryAddWindow.title=Voeg een Nieuwe Categorie toe ConfigView.label.autoSeedingIgnoreInfo=Genegeerde torrents gaan naar de bodem van de upload rij. Ze starten niet automatisch.\nGenegeerde regels zijn niet van toepassing op torrents die de eerste Prioriteit criteria hebben.\nTenzij anders aangegeven, gebruik een waarde van 0 om de regel uit te schakelen. ConfigView.label.directory=Map ConfigView.label.disconnetseed.tooltip=Wanneer je een torrent aan het uploaden bent, verbreek de verbinding met cli\u00ebnts die ook aan het uploaden zijn.\nZe hoeven niet met je te communiceren. ConfigView.label.ignoreCase=Negeer Hoofdletters ConfigView.label.ignoreSeeds=Negeer torrents met tenminste ConfigView.label.importdirectory=Importeer Map ConfigView.label.minPeersToBoostNoSeeds.tooltip=Alle torrents zonder seeders en minder leechers dan je specificeert\ngaan naar de bodem van de wachtrij. ConfigView.label.minPeersToBoostNoSeeds=Verlaag Upload Waarde voor torrents zonder seeders en minder dan ConfigView.label.minSeedingTime.tooltip=De Upload Waarde kan snel wisselen in een korte tijd, waardoor torrents soms automatisch worden gestart om daarna direct te stoppen en in de wachtrij gezet te worden.\nDit verlicht het probleem door de torrent te dwingen om een bepaalde tijd te blijven uploaden. Je kunt het handmatig stoppen als je dit wil. ConfigView.label.minSeedingTime=Minimale upload tijd in seconden ConfigView.label.minSpeedForActiveDL.tooltip=Een download slot wordt altijd voor de eerste 30 seconden\ngebruikt na het starten van een onvolledige torrent. ConfigView.label.minSpeedForActiveDL=Torrent gebruikt geen download slot als de snelheid lager is dan ConfigView.label.queue.debuglog=Sla de debug informatie op ConfigView.label.queue.debuglog.info=Voeg wachtrij debug info aan het console/log bestand toe.\nHoewel cryptisch, vertelt de debug info je de status van de torrents en waarom ze wel/niet starten of in de wachtrij komen. ConfigView.label.queue.minQueueingShareRatio=Stop niet of zet torrents niet in de wachtrij tenzij de deel verhouding is bereikt ConfigView.label.ratio=verhouding ConfigView.label.removeOnStop=Verwijder torrent van lijst wanneer de torrent automatisch gestopt wordt ConfigView.label.savedirectory=Opslag Map ConfigView.label.seeding.autoReposition.tooltip=De volgorde van de torrents (de 'No:' kolom) wordt veranderd op basis van de Upload Waarde, wanneer ingeschakeld\nDit is handig als je Upload Waarde nummers niet leuk vindt, maar wel wil weten in welke volgorde de voltooide torrents starten. ConfigView.label.seeding.autoReposition=Herpositioneer torrents automatisch gebaseerd op de Upload waarde ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Vaak betekenen torrents met weinig seeders en veel peers, dat er waarschijnlijk geen volledige kopie onder de peers is.\nHierdoor wil je misschien niet dat de upload regels doen alsof er een volledige kopie is (en daardoor de rangorde onterecht verlagen) ConfigView.label.seeding.fakeFullCopySeedStart=maar alleen voor torrents met minstens ConfigView.label.seeding.ignore=Negeer Regels ConfigView.label.seeding.ignore0Peers=Negeer torrents met 0 leechers ConfigView.label.seeding.ignoreRatioPeers=Negeer torrents die minstens 1 upload voor iedere ConfigView.label.seeding.ignoreShareRatio=Negeer torrents die een deel verhouding hebben van ConfigView.label.seeding.ignore.header.evenFirstPriority=Negeer torrent zelfs als\nEerste Prioriteit regel van toepassing is ConfigView.label.seeding.ignore.header.rule=Regel ConfigView.label.seeding.ignore.header.value=Waarde ConfigView.label.seeding.firstPriority.info=Torrents met de Eerste Prioriteit worden altijd boven in de rij gezet.\nAlle torrents die aan de Eerste Prioriteit criteria voldoen, worden niet automatisch gestopt en in de wachtrij gezet.\nEen torrent die aan de Eerste Prioriteit criteria voldoet, krijgt een Gelijktijdig Download slot wanneer nodig. ConfigView.label.seeding.firstPriority.FP=Eerste Prioriteit ConfigView.label.seeding.firstPriority=Eerste prioriteit gaat naar torrents met ConfigView.label.seeding.firstPriority.following=van de volgende kenmerken: ConfigView.label.seeding.firstPriority.shareRatio=Een Deel verhouding onder ConfigView.label.seeding.firstPriority.seedingMinutes=Een verlopen tijd sinds het veranderen van downloaden naar uploaden van ConfigView.label.seeding.firstPriority.DLMinutes=Een verlopen tijd sinds het starten van downloaden van ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Door te doen alsof er 1 volledig kopie per X peers is, verlaag je de waarde van torrents met een hoog aantal peers.\nMeestal hebben torrents met veel peers, veel verkeer.\nDit verandert niets aan 'No:' van uploads'. ConfigView.label.seeding.numPeersAsFullCopy=Doe alsof er 1 volledige kopie voor iedere\n(0 : Doe niet alsof) ConfigView.label.seeding.preferLargerSwarms.tooltip=Als je hoofdzakelijk torrents upload met peers die "vast zitten", dan is een hogere prioriteit geven aan grote zwermen logisch\nWanneer je hoofdzakelijk torrents upload met een hoge toegankelijkheid, is het logische om de prioriteit te geven aan kleine zwermen. ConfigView.label.seeding.preferLargerSwarms=Geeft hogere prioriteit aan grote zwermen, wanneer torrents dezelfde waarde hebben.; ConfigView.label.seeding.rankType.none.tooltip=Volgorde gebaseerd op Nr: kolom ConfigView.label.seeding.rankType.none=Geen ConfigView.label.seeding.rankType.peerSeed.options=Seeders:Leechers Verhouding Opties ConfigView.label.seeding.rankType.peerSeed.tooltip=Hogere Verhouding = Hogere Waarde ConfigView.label.seeding.rankType.peerSeed=Leechers:Upload Verhouding ConfigView.label.seeding.rankType.seed.fallback=Terugvallen naar Leechers:Seeders na\n(0: Nooit Terugvallen) ConfigView.label.seeding.rankType.seed.options=Alleen Upload-Aantal Opties ConfigView.label.seeding.rankType.seed.tooltip=Minder Uploads , Hogere Waarde ConfigView.label.seeding.rankType.seed=Alleen Upload Aantal ConfigView.label.seeding.rankType.timedRotation.tooltip=Alle Complete torrents in de wachtrij omzetten naar upload modus.\nTijdsduur van uploaden is ingesteld door 'Minimale Upload Tijd' ConfigView.label.seeding.rankType.timedRotation=Geklokte Rotatie ConfigView.label.seeding.rankType.tooltip=Torrents met de hoogste waarde starten automatisch.\nWanneer een andere torrent een hogere waarde krijgt, stopt de torrent met een lagere waarde en gaat terug in de wachtrij.\n\nAlleen torrents in een wachtrij kunnen automatisch starten.\nTorrents die gestopt zijn starten nooit automatisch. ConfigView.label.seeding.rankType=Waarde complete torrents voor auto-starten gebaseerd op:; ConfigView.label.stopAfterMinutes=Wanneer overgeschakeld naar uploaden, stop na een tijd van; ConfigView.label.switchpriority.tooltip=Lage prioriteit vermindert de hoeveelheid bandbreedte die een torrent kan gebruiken.; ConfigView.pluginlist.info=De volgende plugins zijn ge\u00efdentificeerd. Sommige plugins hebben mogelijk geen configuratie tabs. ConfigView.pluginlist.noplugins=Er zijn geen plugins gevonden. ConfigView.section.pluginslist=Lijst ConfigView.section.queue.seeding=Zenden ConfigView.section.queue.seeding.autoStarting=Start Automatisch ConfigView.section.queue.seeding.ignore=Negeer Regels ConfigView.section.queue.seeding.firstPriority=Eerste Prioriteit ConfigView.section.queue.main=Hoofd ConfigView.section.queue=Wachtrij ConfigView.section.torrents=Torrents ConfigView.text.all=alle ConfigView.text.hours=uren ConfigView.text.ignoreRule=Negeer Regel ConfigView.text.ignore=Negeer ConfigView.text.minutes=minuten op ConfigView.text.neverIgnore=Nooit Negeren ConfigView.text.any=een DownloadManager.error.datamissing=Gegevens ontbreken MainWindow.menu.file.open.torrentforseeding=Torrent bestand (Voor Uploaden) MainWindow.menu.language.refresh=Ve&rnieuwen ManagerItem.forced=Geforceerd ManagerItem.queued=In de wachtrij TableColumn.header.availability.info=aantal volledige kopie\u00ebn te zien TableColumn.header.availability=Beschikbaarheid TableColumn.header.category=Categorie MyTorrentsView.header=Niet complete Torrents TableColumn.header.maxuploads=Max aantal Uploads MyTorrentsView.menu.category.delete=Verwij&der Categorie MyTorrentsView.menu.forceStart=&Forceer Start MyTorrentsView.menu.queue=Wachtrij MyTorrentsView.menu.setCategory.add=Voeg C&ategorie toe... MyTorrentsView.menu.setCategory=Wijs Categorie toe TableColumn.header.savepath=Opslag pad TableColumn.header.SeedingRank=Upload Waarde TableColumn.header.totalspeed.info=Totalen Snelheid van alle leechers waar je mee verbonden bent TableColumn.header.totalspeed=Totalen Snelheid splash.initializePlugins=Initialiseren Plugins StartStopRules.SPratioMet=S:P Verhouding OK StartStopRules.FP0Peers=E.P. / 0 Leechers StartStopRules.numSeedsMet=Nr: Uploads OK StartStopRules.ratioMet=Peers:Upload OK StartStopRules.shareRatioMet=Deel Verhouding Ok StartStopRules.waiting=Wachten StartStopRules.firstPriority=1e Prioriteit ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Deel Inhoud (Recursief) DownloadManager.error.unabletostartserver=Kan server niet starten - controleer inkomende poort configuratie / Firewall instellingen zodat de applicatie een server kan zijn GeneralView.label.creationdate=Gemaakt Op: ConfigView.section.tracker.announcescrapepercentage=Deeltjes tussenpauze als %leeftijd van mededeling\nzoals 200 ; 2:1. 0 ; laat peer beslissen ManagerItem.stopping=Bezig met Stoppen ConfigView.section.tracker.announcecacheperiod=Deel cache mee iedere (millisec.) ConfigView.section.tracker.scrapecacheperiod=Deeltjes cache periode (millisec.) ConfigView.section.tracker.scrapeandcache=Deeltjes en cache ConfigView.section.tracker.announcecacheminpeers=Deel cache peer drempelwaarde mee MyTrackerView.scrapes=Deeltjes fileDownloadWindow.retry=Opnieuw proberen MyTrackerView.bytesin=Bytes in MyTrackerView.bytesinave=Gemiddelde In MyTrackerView.bytesout=Bytes Uit MyTrackerView.bytesoutave=Gemiddelde Uit ConfigView.section.file.max_open_files=Maximum geopende bestanden voor lezen/schrijven\n[0: ongelimiteerd] ConfigView.section.file.max_open_files.tooltip=Handig als je torrents download met honderden/duizenden bestanden, en je het maximaal aantal bestanden dat je OS kan verwerken hebt bereikt. ConfigView.section.proxy=Proxy ConfigView.section.proxy.enable_proxy=Schakel proxy voor tracker communicaties in [herstart nodig] ConfigView.section.proxy.host=Host. ConfigView.section.proxy.port=Poort ConfigView.section.proxy.username=Gebruikersnaam ConfigView.section.proxy.password=Wachtwoord ConfigView.section.proxy.enable_socks=Ik heb een SOCKS proxy wizard.createtorrent.extrahashes=Voeg hashes voor andere netwerken toe (zoals Gnutella2, eDonkey2000) GeneralView.label.connected=verbonden GeneralView.label.in_swarm=in zwerm ManagerItem.initializing=Initialiseren AlertMessageBox.error=Fout AlertMessageBox.warning=Waarschuwing AlertMessageBox.comment=Informatie AlertMessageBox.information=Informatie AlertMessageBox.unread=Je hebt ongelezen waarschuwings berichten - klik hier om deze te lezen. SharedPortServer.alert.selectorfailed=Gefaald om een listener voor inkomende data te maken.\nControleer je Firewall instellingen en geef java(w).exe toestemming om zich te gedragen als 'server' Tracker.alert.listenfail=Mislukt om een listen op poort %1 te maken.\nControleer of andere applicaties deze poort niet gebruiken.\nControleer ook of er een andere kopie van Vuze draait. DiskManager.alert.movefileexists=Verplaatsen voltooide bestanden mislukt\nBestand %1 bestaat al in de doel map DiskManager.alert.movefilefails=Verplaatsen voltooide bestanden mislukt\nVerplaatsen van bestand %1 mislukt, %2 DiskManager.alert.movefilerecoveryfails=Fout herstellen na mislukte verplaatsing.\nHerstellen van bestand %1 mislukt, %2 ConfigView.section.tracker.logenable=Log periodieke statistieken naar 'tracker.log' SpeedView.stats.title=Statistieken SpeedView.stats.total=Totaal SpeedView.stats.session=Deze Sessie SpeedView.stats.session.tooltip=Totaal(Protocol) SpeedView.stats.downloaded=Gedownload SpeedView.stats.uploaded=Ge\u00fcpload (Protocol) SpeedView.stats.ratio=Ratio verhouding SpeedView.stats.uptime=Online Tijd (uren) SpeedView.stats.now=Nu SpeedView.stats.now.tooltip=Totaal (Protocol) AutoMigration.useralert=Vuze configuratie bestanden/mappen auto-migratie resultaten:\n\n%1\nAlle mislukten moeten handmatig worden migreert.\nVERGEET NIET JE SAVE PAD TE UPDATEN IN JE CONFIGURATIE ALS DEZE IS MIGREERT! # # > 2.0.8.0 # OpenTorrentWindow.title=Open torrent(s) OpenTorrentWindow.message=Experimenteel OpenTorrentWindow.addFiles=Voeg Best&anden toe OpenTorrentWindow.dataLocation=Locatie om data op te slaan: OpenTorrentWindow.startMode=Voeg Mode toe OpenTorrentWindow.startMode.queued=In Wachtrij OpenTorrentWindow.startMode.stopped=Gestopt OpenTorrentWindow.startMode.forceStarted=Geforceerd Starten OpenTorrentWindow.addPosition=Wachtrij Positie OpenTorrentWindow.addPosition.first=Eerste OpenTorrentWindow.addPosition.last=Laatste TableColumn.header.remaining.info=Hoeveelheid te downloaden data TableColumn.header.remaining=Te gaan ConfigView.section.tracker.enablecompact=Zet compact mededeling protocol aan ConfigView.section.tracker.enablekey=Zet doorgeven van sleutel aan de tracker aan voor verbeterde beveiliging ConfigView.section.file.perf=Prestatie Opties ConfigView.section.file.perf.explain="Waarschuwing - ongekwalificeerde veranderingen aan deze parameters kunnen nadelige effecten op de download prestaties hebben. Herstart nodig.\nAls je een "out of memorie" probleem hebt, overweeg dan het aantal connecties per torrent te limiteren (Zie Overdracht configuratie)" ConfigView.section.file.max_open_files.explain=Het openen van te veel bestanden kan problemen opleveren met het operating systeem door een gelimiteerde aantal bronnen voor bestands handelingen. Dit limiteert het aantal tegelijk geopende bestanden. popup.error.hide=Verberg ConfigView.section.style.colorOverrides=Kleur instellingen ConfigView.section.style.colorOverride.progressBar=Voortgang Balk ConfigView.section.style.colorOverride.error=Fout MainWindow.status.tooOld=is te oud, update het a.u.b. ConfigView.section.style.colorOverride.warning=Waarschuwing ConfigView.section.style.colorOverride.altRow=Alternatiefe rijen ConfigView.section.file.save.peers.enable=Sla peer verbindingen op voor snelle herverbinding ConfigView.section.file.save.peers.max=Maximum peers om op te slaan [0: ongelimiteerd] ConfigView.label.max_peers_per_torrent=Maximum aantal connecties per torrent [0: ongelimiteerd] ConfigView.label.max_peers_total=Maximum aantal connecties globaal [0: ongelimiteerd] ConfigView.section.style.colorOverrides.reset=Herstel Kleur ConfigView.section.language.info=Wanneer ingeschakeld, wordt er op een update gecontroleerd tijdens het starten van Vuze ConfigView.section.language.enableUpdate=Schakel Web Update in ConfigView.section.language.UpdateNow=Nu Updaten! Button.revert=Ongedaan maken MyTorrentsView.menu.changeDirectory=Verander Data Map GenericText.column=kolom MyTorrentsView.menu.thisColumn.remove=Verwijder Kolom MyTorrentsView.menu.thisColumn.toClipboard=Kopi\u00eber tekst naar Klembord MyTorrentsView.menu.thisColumn.autoTooltip=Altijd tooltip tonen TableColumn.header.secondsseeding=Upload tijd TableColumn.header.secondsseeding.info=Tijdsduur dat je aan het Uploaden bent. TableColumn.header.secondsdownloading=DLoad Tijd TableColumn.header.secondsdownloading.info=Tijdsduur dat je aan het downloaden bent. ConfigView.section.tracker.udpversion=UDP Protocol Versie (1 of 2) window.updateswt.title=Je SWT Versie is te oud! window.updateswt.text=Je SWT Versie is te oud!\nSWT is de grafische bibliotheek die Vuze gebruikt, de versie die je hebt is te oud om de laatste Vuze versie te draaien. Klik op OK om je SWT te updaten. window.updateswt.failed=Update mislukt, druk opnieuw op OK om te herstarten. window.updateswt.status.downloading.updater=Downloaden van de Update Module window.updateswt.status.finding=Zoeken van de laatste SWT Versie window.updateswt.status.downloading=Downloaden van de laatste SWT Versie window.updateswt.status.done=Herstarten window.updateswt.ok=Ok window.updateswt.cancel=Annuleren swt.updater.downloader.downloading=Downloaden SWT van swt.updater.urlsgetter.downloading=Een lijst met -linken- ophalen van swt.updater.urlsgetter.platform=SWT voor platform : window.updateswt.ignore=Negeer ConfigView.section.style.useFancyTabs=Gebruik Fancy Tabs splash.initializeGM=Initialiseren Globale Torrent Manager splash.loadingTorrents=Torrents Laden splash.firstMessageNoI18N=(:Vuze:) MyTorrentsView.menu.thisColumn.sort=&Sorteer Scrape.status.ok=Scrape Ok. Scrape.status.error=Scrape Fout: Scrape.status.error.badURL=Deel mee URL volgt niet de scrape specificaties. Scrape.status.error.nohash=Hash gemist van antwoord. Scrape.status.error.invalid=Ongeldig antwoord. Scrape.status.nextScrapeAt=Volgende scrape op %1 Scrape.status.scraping=Scrapen... Scrape.status.initializing=Wachten om te Scrapen Scrape.status.scraping.queued=Scraping Gestopt.. ConfigView.label.minSpeedForActiveSeeding=Tel voltooide torrents niet mee als de snelheid lager is dan ConfigView.section.stats.exportpeers=Exporteer peer details MainWindow.menu.view.irc.moved=IRC is nu beschikbaar als een plugin, zie http://vuze.sourceforge.net/plugin_list.php. Wanneer ge\u00efnstalleerd gebruik Plugins ->IRC menu om het te openen. MyTrackerView.webui.contextmenu.copyurl=Kopi\u00eber torrent URL naar klembord ConfigView.section.file.torrent.ignorefiles=Bestanden om te negeren wanneer torrents gemaakt worden\nzoals: .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Negeer bestand ConfigView.section.style.useUnitsRateBits=Gebruik bits in plaats van bytes voor byte-gebaseerde waardes (KiB/s->Kibit/s enz.) ConfigView.section.interface.resetassoc=Herstel verkenner bestands associaties (.torrent) ConfigView.section.interface.resetassocbutton=Herstel ConfigView.section.interface.checkassoc=Controleer associaties tijdens opstarten dialog.associations.title=Associatie Controle Button.yes=Ja Button.no=&Nee ConfigView.label.seeding.autoStart0Peers=Start alle complete torrents automatisch met 0 seeders ConfigView.label.seeding.autoStart0Peers.tooltip=Zet aan, als je wil dat de tracker altijd seeds geeft voor torrents zonder peers. dialog.associations.prompt=Vuze is niet de standaard applicatie voor Bittorrent bestanden.\nWil je de Vuze met .torrent bestanden associ\u00ebren? dialog.associations.askagain=Controleer tijdens starten ConfigView.section.plugins.update=Plugin Update. Plugin.pluginupdate.enablecheck=Zet plugin update controle aan plugins.basicview.status=Status: plugins.basicview.activity=Activiteit: plugins.basicview.progress=Voortgang: plugins.basicview.log=Log: ConfigView.label.maxdownloadspeed=Globale maximum download snelheid in KB/s [0: ongelimiteerd] splash.loadingTorrent=Torrent Laden splash.of=van UpdateWindow.title=Vuze updater UpdateWindow.header=De volgende componenten hebben een update nodig : UpdateWindow.columns.install=Installeren UpdateWindow.columns.name=Naam UpdateWindow.columns.version=Versie UpdateWindow.columns.size=Grootte UpdateWindow.cancel=Annuleren UpdateWindow.quit=Afsluiten UpdateWindow.close=Sluiten UpdateWindow.restart=Herstart Nu UpdateWindow.status.downloading=Downloaden UpdateWindow.status.done=Voltooid UpdateWindow.status.failed=Mislukt UpdateWindow.status.restartNeeded=Herstarten is nodig! ConfigView.pluginlist.broken=Fout ConfigView.pluginlist.whereToPut=Plaats alle gebruikers-specifieke plugins in hun eigen directory onder: ConfigView.pluginlist.whereToPutOr=Gebruik voor gedeelde plugins: MainWindow.statusText.checking=Controleren op Updates TableColumn.header.OnlyCDing4=Alleen Uploaden TableColumn.header.OnlyCDing4.info=Hoeveelheid tijd waarin de torrent alleen aan het uploaden was.\nExclusief de tijd dat de torrent aan het downloaden was (en uploaden). ConfigView.section.style.alternateTablePainting=Gebruik alternatieve methode om grafische tabel kolommen te tekenen (kan herstart nodig hebben) UpdateWindow.status.restartMaybeNeeded=Herstart kan nodig zijn ConfigView.pluginlist.shared=gedeelt PeersView.host=Host Naam PeersView.host.info=De host naam van de downloader, wanneer beschikbaar (kan de prestaties be\u00efnvloeden) MainWindow.menu.help.whatsnew=Wat is nieuw ConfigView.label.checkonstart=Controleer voor de laatste versie wanneer Vuze start ConfigView.label.periodiccheck=Controleer periodiek voor de laatste versie ConfigView.label.opendialog=Open automatisch de Update Assistent wanneer er een update beschikbaar is MainWindow.updateavail=(Update Beschikbaar) MainWindow.status.latestversionunchecked=Versie controle uitgeschakeld GeneralView.label.updatein.stopped=Gestopt StartStopRules.menu.viewDebug=Bekijk Debug Info ConfigView.section.style.doNotUseGB=Gebruik geen GB eenheid ConfigView.section.style.doNotUseGB.tooltip=Vuze zal, wanneer aangevinkt, de MB blijven gebruiken, zelfs als de grootte meer is dan 1024MB MainWindow.menu.help.plugins=Plugins ConfigView.section.plugins.TrackerWeb=Tracker Web. ConfigView.section.tracker.enablecategories=Sorteer torrents op categorie health.explain.share=betekend dat de torrent gehost of gepubliceerd is ConfigView.section.tracker.createcert=Maak zelfondertekende certificatie ConfigView.section.tracker.createbutton=Maken security.certcreate.title=Maak zelfondertekende Certificaat security.certcreate.intro=Deze dialoog laat je een zelfondertekende certificaat maken security.certcreate.alias=Pseudoniem security.certcreate.strength=Sterkte security.certcreate.firstlastname=Voor en Achternaam security.certcreate.orgunit=Organisatie Eenheid security.certcreate.org=Organisatie security.certcreate.city=Stad of streek security.certcreate.state=Staat of Provincie security.certcreate.country=Twee letter land code security.certcreate.ok=Maken security.certcreate.cancel=Annuleren security.certcreate.createok=Maken certificaat voltooid security.certcreate.createfail=Certificaat maken mislukt ConfigView.section.plugins.webui=Swing Web Interface. ConfigView.section.plugins.xml_http_if=XML/HTTP Interface. webui.passwordenable=Schakel wachtwoord in webui.user=Gebruikers naam webui.password=Wachtwoord webui.port=Poort (*) webui.protocol=Protocol (*) webui.homepage=Start pagina (*) webui.rootdir=Hoofd map (*) webui.rootres=Hoofd bron (*) webui.mode=Modus (*) webui.mode.info="Modus kan zijn:\n\t"full"\t";" alle operaties zijn toegankelijk (standaard)\n\t"view""; alleen bekijken (maar kan vaak vernieuwen) webui.access=Toegang (*) webui.access.info="Toegang kan zijn:\n\t"local"\t";" Alleen de lokale machine kan verbinden\n\t"all"\t\t"; Ongeregistreerde toegang (standaard)\n\tIP\t\t\t; zoals: 192.168.0.1\t\t1 IP tegelijk\n\tIP1-IP2\t; zoals: 192.168.0.1-192.168.0.255\teen reeks van IP's GeneralView.label.maxdownloadspeed=Max. Down Security.keystore.corrupt=Gefaald de sleutelreeks '%1' te laden, verwijder het en maak/importeer het certificaat opnieuw Security.keystore.empty=Sleutelreeks is leeg. Maak een zelfondertekende certificaat (zie Gereedschappen-> Configuratie-> Beveiliging) of importeer een bestaand certificaat in '%1' webui.restart.info=Veranderingen van parameters met een (*) hebben een herstart nodig om effect te hebben GeneralView.label.maxdownloadspeed.tooltip=Maximum download snelheid [0: ongelimiteerd] ConfigView.section.UPnP=UPnP. upnp.enable=Schakel UPnP in upnp.info=Universele Plug and Play (UPnP) maakt het mogelijk automatisch poorten te mappen op UPnP ingeschakelde routers. upnp.mapping.dataport=Inkomende Peer Data Poort upnp.mapping.tcptrackerport=TCP Tracker Poort upnp.mapping.udptrackerport=UDP Tracker Poort upnp.alert.differenthost=UPnP: Mapping '%1' is gereserveerd door '%2' - selecteer een andere poort upnp.alert.mappingok=UPnP: Mapping '%1' ingesteld upnp.alert.mappingfailed=UPnP: Mapping '%1' mislukt upnp.alertsuccess=Rapporteer Succesvolle Mapping upnp.alert.lostdevice=UPnP: Verbinding verloren met service '%1' op UPnP apparaat '%2' upnp.grabports=Map poorten zelfs als deze in het bezit zijn van een andere computer upnp.refresh.label=Vernieuw de mappings upnp.refresh.button=Vernieuwen upnp.alert.mappinggrabbed=UPnP: Mapping '%1' ingesteld - verkregen van '%2' upnp.mapping.tcpssltrackerport=TCP SSL Tracker Poort upnp.alertothermappings=Rapporteer poorten die in het bezit zijn van andere computers upnp.alertdeviceproblems=Rapporteer problemen met het UPnP apparaat upnp.trace_to_log=Output volledig naar debug informatie log upnp.wiki_link=Vuze Wiki pagina over UPnP ConfigView.pluginlist.coreplugins=De volgende ingebouwde plugins zijn geladen: Peers.column.DLedFromOthers=Van Anderen Peers.column.DLedFromOthers.info=Hoeveelheid data gedownload van anderen terwijl die verbonden zijn met jou Peers.column.UpDownRatio=Up/Down Peers.column.UpDownRatio.info="Leechers "Upload : Download" Verhouding" Peers.column.UpRatio=Up Verhouding Peers.column.UpRatio.info="Leechers "Upload van jou : Geupload van anderen" verhouding" upnp.releasemappings=Geef de mappings vrij en sluit af webui.upnpenable=Aanzetten UPnP voor deze poort (*) ConfigView.section.file.friendly.hashchecking=Vriendelijke hash controle ConfigView.section.file.friendly.hashchecking.tooltip=Een stuk langzamer, maar zorgt voor minder belasting op de CPU, het systeem en deeltjes hash controle modus. ConfigView.section.tracker.seedretention=Maximum aantal uploads per torrent beperken [0: ongelimiteerd] ConfigView.section.tracker.seedretention.info=Upload statistieken worden verloren voor niet-beperkte uploads ConfigView.section.tracker.port=Zet tracker op HTTP poort ConfigView.section.tracker.sslport=Zet tracker op HTTPS poort aan ConfigView.section.tracker.publicenable.info=Dit staat anderen toe om torrents te maken die jouw tracker gebruiken\nzonder dat jij ze host/publiceert Button.clear=Verwijderen MainWindow.IPs.tooltip={Laatste update van filter lijst} Totaal aantal IP filters in lijst - Aantal geblokkeerde IP adressen deze sessie\nDubbelklik voor details. ConfigView.section.ipfilter.list.banned=is verbannen voor het zenden van corrupte data ConfigView.section.ipfilter.list.baddata=heeft corrupte data gezonden: voorval Button.reset=Herstel ConfigView.section.ipfilter.bannedinfo=IP's die corrupte data hebben gezonden - verbannen als het limiet is overschreden ConfigView.section.ipfilter.blockedinfo=IP's die zijn geblokkeerd door IP filters download.removerules.name=Verwijder Regels download.removerules.unauthorised.info=Ongeautoriseerde torrents zijn torrents waar in de meegedeelde reactie\n"niet geautoriseerd" of "ongeautoriseerd" in de "mislukt reactie staat" download.removerules.unauthorised=Verwijder ongeautoriseerde torrents automatisch. download.removerules.unauthorised.seedingonly=\tAlleen tijdens uploaden download.removerules.removed.ok=Automatisch verwijderen van torrent '%1' voltooid. Dit is uitgevoerd door de torrent verwijder regels. download.removerules.updatetorrents=Verwijder Vuze update torrents als de zwerm dit nodig heeft ConfigView.label.defaultstarttorrentsstopped=Voeg torrents standaard in gestopte status toe ConfigView.section.server.enableudp=Zet UDP tracker cli\u00ebnt protocol aan. Dit gebruikt dezelfde poort als de TCP server upnp.mapping.dataportudp=UDP tracker cli\u00ebnt poort ConfigView.section.file.decoder.showlax=Toon minder gebruikelijke coderingen ConfigView.section.file.decoder.showall=Overweeg alle mogelijke coderingen MainWindow.status.updowndetails.tooltip=Upload/download snelheid details - klik rechter muis om te veranderen TrackerClient.announce.warningmessage=Tracker voor '%1' geeft waarschuwing '%2' ConfigView.section.tracker.natcheckenable=Controleer 'inkomende data poort' verbindingsmogelijkheid en rapporteer fouten aan de peers ConfigView.section.tracker.publishenabledetails=Publiceer torrentbestand en peerdetails ConfigView.section.tracker.publishenablepeerdetails=Publiceer download details MyTrackerView.badnat=Slechte NAT MyTrackerView.badnat.info=Seeders/Leechers die de NAT controle hebben gefaald wanneer ingeschakeld ConfigView.section.tracker.natchecktimeout=Controle time-out (secs) ConfigView.section.file.perf.cache.enable=Schakel disk cache in ConfigView.section.file.perf.cache.size=Grootte van cache in %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=Ove&rdrachten MainWindow.menu.transfers.startalltransfers=St&art Alle MainWindow.menu.transfers.stopalltransfers=St&op Alle MainWindow.menu.transfers.pausetransfers=&Pauze MainWindow.menu.transfers.resumetransfers=He&rvat ConfigView.label.experimental.osx.kernel.panic.fix=Experimentele oplossing voor kernel problemen op dual processor OSX systemen [herstart nodig] SystemTray.menu.pausetransfers=Pauzeer Overdrachten SystemTray.menu.resumetransfers=Hervat Overdrachten ConfigView.section.file.truncate.too.large=Kap bestaande bestanden die te groot zijn af ConfigView.section.file.perf.cache.trace=Traceer cache operaties voor diagnostische doeleinden ConfigView.section.interface.enabletray=Schakel Systeemvak in [herstart nodig] PeerManager.status.error=Fout Stats.title.full=Statistieken TransferStatsView.title.full=Data verkeer CacheView.general.size=Totalen Grootte CacheView.general.inUse=In Gebruik CacheView.general.title=Cache Informatie CacheView.reads.title=I/O Lees bewerkingen CacheView.reads.fromFile=Van Bestand CacheView.reads.fromCache=Van Cache CacheView.writes.title=I/O Schrijf bewerkingen CacheView.writes.toCache=Naar Cache CacheView.writes.toFile=Naar Bestand CacheView.writes.hits=Hits CacheView.speeds.title=Data Snelheid CacheView.speeds.reads=Lezen CacheView.speeds.writes=Schrijven CacheView.speeds.fromCache=Van/Naar Cache CacheView.speeds.fromFile=Van/Naar Bestand CacheView.reads.#=Nr: CacheView.reads.amount=Hoeveelheid CacheView.reads.avgsize=Gemiddelde Grootte openUrl.referrer=URL pagina verwijzing : openUrl.referrer.info=Alleen nodig voor websites die dit afdwingen ConfigView.label.maxuploadspeedseeding=Globale maximum uploadsnelheid wanneer er alleen wordt geupload in KB/s [0: ongelimiteerd] ConfigView.label.transfer.ignorepeerports=Negeer leechers met de volgende data poorten (gescheiden met ';') zoals: 0;25) ConfigView.section.proxy.enable_socks.peer=Schakel proxy voor peer communicaties in (Alleen uitgaande verbindingen) [herstart nodig] ConfigView.section.proxy.peer.informtracker=Informeer tracker over beperking ConfigView.section.proxy.socks.version=SOCKS versie PiecesView.legend.written=Weg geschreven PiecesView.legend.requested=Aangevraagd PiecesView.legend.downloaded=Gedownload,\n nog niet weg geschreven PiecesView.legend.incache=Data is in de Cache PiecesView.typeItem.0=Langzaam PiecesView.typeItem.1=Snel Security.jar.tools_not_found=JAR ondertekening mislukt - 'tools.jar' niet gevonden in %1. Zie Gereedschappen-> Configuratie-> Beveiliging voor details. Security.jar.signfail=JAR ondertekening mislukt - %1 ConfigView.section.security.toolsinfo=Ondertekende JAR bestanden worden gebruikt om sommige plugins zoals de Swing Web Interface \n(wanneer geconfigureerd) te ondersteunen.\nOm JAR bestanden te ondertekenen, is het nodig toegang te hebben tot het 'tools.jar' bestand.\nDit bestand komt met de Sun JDG (niet JRE) installatie.\nAls je alleen de JRE hebt geinstalleerd moet je de JDK installeren.\nVuze kan dit bestand voor je vinden, als dit niet lukt, kan je hier alsnog de map aangeven. ConfigView.section.security.toolsdir=Map met 'tools.jar' ConfigView.section.security.choosetoolssavedir=Selecteer de map met 'tools.jar' authenticator.torrent=Torrent ConfigView.section.proxy.peer.same=Gebruik de zelfde proxy instellingen voor tracker en peer communicatie proxy ConfigView.section.connection.network.max.simultaneous.connect.attempts=Maximum gelijktijdig uitgaande verbindings pogingen [0: uitgeschakeld] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Maximum aantal nieuwe uitgaande verbindingen die Vuze op ieder moment kan maken.\nOpmerking: Windows XP Service Pack 2 (SP2) bevat een limiet van 10 gelijktijdige verbindings pogingen over het hele systeem.\nStandaard waarde is 8. Een waarde van 0 schakelt dit volledig uit. ConfigView.section.file.perf.cache.size.explain=De cache wordt gebruikt om het aantal schijf bewerkingen te verkleinen. Tenzij je de java optie '- XX:MaxDirectMemorySize' gebruikt om het geheugen speciaal voor cache en network IO te gebruiken, moet je deze waarde rond 1% onder je maximum VM grootte houden. De huidige maximum VM grootte is %2. Lees MemoryUsage in de Wiki op %3 om te zie hoe dit aangepast kan worden. Onverstandige instellingen kunnen leiden tot 'out of memory' fouten. Meer dan 32MB cache is waarschijnlijk overkill. MyTorrentsView.menu.setSpeed.unlimit=Geen limiet MyTorrentsView.menu.setSpeed.unlimited=Ongelimiteerd MyTorrentsView.menu.setSpeed.disable=Schakel Upload uit MyTorrentsView.menu.setSpeed.disabled=Uitgeschakeld MyTorrentsView.menu.setSpeed.slots=sloten van GeneralView.label.maxuploadspeed=Max. Up GeneralView.label.maxuploadspeed.tooltip=Max Upload Snelheid [0 : ongelimiteerd] MyTorrents.items.UpSpeedLimit.disabled=Geen upload MyTorrents.items.UpSpeedLimit.unlimited=Ongelimiteerd TableColumn.header.maxupspeed=Max Up Snelheid TableColumn.header.maxupspeed.info=Max Upload Snelheid per torrent ConfigView.section.file.perf.cache.enable.write=Cache download data om het aantal schrijf bewerkingen te verkleinen en lees bewerkingen voor stukjes controle te verkleinen ConfigView.section.file.perf.cache.enable.read=Schakel vooruit-lezen in, om schijf activiteit tijdens het uploaden te verminderen ConfigView.section.tracker.separatepeerids=Gebruik verschillende peer identiteiten voor tracker en data communicatie ConfigView.section.tracker.separatepeerids.info=Verhoog anonimiteit tijdens anoniem downloaden/uploaden\nterwijl je een niet-anonieme tracker verbinding gebruikt ConfigView.section.interface.wavlocation=Locatie van .wav bestand ConfigView.section.interface.wavlocation.info=Selecteer .wav bestand of laat dit leeg voor het standaard geluid ConfigView.section.tracker.server=Server. ConfigView.section.tracker.client=Cli\u00ebnt ConfigView.section.tracker.client.connecttimeout=Connectie time-out (secs) ConfigView.section.tracker.client.readtimeout=Lees time-out (secs) MainWindow.menu.tools=&Gereedschappen FilesView.path=Pad FilesView.fullpath=Toon Volledig Pad FilesView.remaining=Stukjes te gaan TableColumn.header.trackername=Tracker Naam TableColumn.header.trackername.info=Naam van de tracker gebaseerd op de meegedeelde URL ConfigView.group.override=Overbrug Opties ConfigView.section.file.perf.cache.notsmallerthan=Cache geen bestanden die kleiner zijn dan dit (in %1) PeersView.menu.blockupload=Blokkeer Upload PeersView.menu.kickandban=Kick en Ban PeersView.menu.kickandban.reason=Peer handmatig verbannen PeersView.state=Status PeersView.state.info=Status van de peer verbinding PeersView.state.pending=Hangend PeersView.state.connecting=Bezig met verbinden PeersView.state.handshake=Wachten op handshake PeersView.state.established=Volledig verbonden ConfigView.section.tracker.processinglimits=Verwerking limieten ConfigView.section.tracker.maxgettime=Max tijd voor GET verwerking (secs) [0: ongelimiteerd] ConfigView.section.tracker.maxgettime.info=Gebruikt voor mededelingen en scrapes ConfigView.section.tracker.maxposttimemultiplier=GET tijd vermenigvuldigingsfactor voor POST verwerking [0: ongelimiteerd] ConfigView.section.tracker.maxposttimemultiplier.info=Gebruikt voor formulier verzendingen en uploads ConfigView.section.tracker.maxthreads=Max gezamenlijke verzoeken DownloadManager.error.operationcancancelled=Operatie geannuleerd Torrent.create.progress.cancelled=Bewerking geannuleerd sharing.progress.cancel=Annuleer wizard.maketorrents.autoopen=Open de torrent voor uploaden wanneer deze is voltooid ConfigView.section.sharing.rescanenable=Schakel periodiek opnieuw scannen in voor veranderingen ConfigView.section.sharing.rescanperiod=Opnieuw Scannen periode (secs) ConfigView.section.connection.advanced=Geavanceerde Netwerk Instellingen ConfigView.section.connection.advanced.mtu=Lijn Maximum Transmission Unit (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Maximum grootte van een pakket dat verzonden kan worden in 1 frame over een netwerk.\nVuze gebruikt MTU-40 (MSS) voor upload packet-payload optimalisaties.\nAangeraden waardes:\n 576 - Telefoon verbindingen\n1792 - PPPoE breedband verbindingen\n1500 - Ethernet, DSL en Kabel breedband verbindingen ConfigView.section.connection.advanced.SO_RCVBUF=Socket SO_RCVBUF grootte [0: gebruik OS standaard] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Stel de standaard socket SO_RCVBUF waarde (in bytes) in, zoals TCP ontvang venster grootte en schaal.\nVuze laat dit standaard oningesteld, dit betekend dat de standaard OS instellingen worden gebruikt.\nOpmerking: Linux verdubbeld de gegeven waarde. ConfigView.section.connection.advanced.SO_SNDBUF=Socket SO_SNDBUF grootte [0: gebruik OS standaard] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Stel de standaard socket SO_SNDBUF waarde (in bytes) in, zoals TCP zend venster grootte.\nVuze laat dit standaard oningesteld, dit betekend dat de standaard OS instellingen worden gebruikt.\nOpmerking: Linux verdubbeld de gegeven waarde. ConfigView.section.connection.advanced.IPDiffServ=Uitgaande packet DiffServ waarde (TOS field) ConfigView.section.connection.advanced.IPDiffServ.tooltip=Zet de DiffServ deel van het type-of-service (TOS) veldt in de IP header voor uitgaande packets.\nHexadecimal waardes kunnen gespecificeerd worden door deze te prefixing met '0x', e.g. 0x10.\nVuze laat dit standaard ongebruikt, dit betekent dat de standaard ven de underlying OS word gebruikt.\nNOTE: Underlying network implementaties kunnen deze waardes negeeren, zo is deze optie afhankelijk van de OS en JRE versie. ConfigView.section.interface.confirm_torrent_removal=Laat bevestigingsvenster zien bij het verwijderen van een torrent ConfigView.section.interface.confirm_torrent_removal.tooltip=Bevestig wanneer er een torrent uit Mijn Torrents wordt verwijderd. MyTorrentsView.confirm_torrent_removal=Weet je zeker dat je wil verwijderen?\n TableColumn.header.seed_to_peer_ratio=Seed2PeerVerhouding TableColumn.header.seed_to_peer_ratio.info=Totalen zwerm seeders naar leechers verhouding PeersView.connected_time=Verbonden Tijd PeersView.connected_time.info=Totalen tijd verbonden met de peer ConfigView.section.interface.display.add_torrents_silently=Voeg torrents stil toe ConfigView.section.interface.display.add_torrents_silently.tooltip=Voeg torrent downloads toe, zonder het hoofd venster te activeren. TableColumn.header.maxdownspeed=Max Down Snelheid TableColumn.header.maxdownspeed.info=Max Download Snelheid per torrent PeersGraphicView.title=Zwerm ConfigView.section.tracker.passwordwebhttpsonly=Sta toegang alleen toe via HTTPS TableColumn.header.torrentpath=Torrent Locatie TableColumn.header.torrentpath.info=Locatie van de Torrent op de schijf ConfigView.section.sharing.torrentcomment=Opmerking voor gegenereerde torrents. ConfigView.label.copyanddeleteratherthanmove=Kopi\u00ebren en verwijderen van de originele data, in plaats van het te verplaatsen - kan helpen dataverlies te verkomen op sommige bestands systemen ConfigView.label.openstatsonstart=Open Statistieken tijdens het starten swt.install.window.title=Vuze Plugin Installatie swt.install.window.ok=Installeer swt.install.window.header=De volgende componenten zijn geselecteerd voor installatie : swt.uninstall.window.title=Vuze Plugin De-installatie swt.uninstall.window.ok=Verwijder swt.uninstall.window.header=De volgende componenten zijn geselecteerd voor verwijdering : installPluginsWizard.title=Plugins Installeren installPluginsWizard.mode.title=Kies een installatie methode installPluginsWizard.mode.list=Uit een lijst van sourceforge.net installPluginsWizard.list.title=Installeerbare Plugin Lijst installPluginsWizard.list.loading=Even wachten tot de Plugin lijst is geladen. installPluginsWizard.list.loaded=Kies de plugins die je wil installeren. installPluginsWizard.list.name=Naam installPluginsWizard.list.version=Versie installPluginsWizard.list.description=Plugins beschrijving installPluginsWizard.finish.title=Bezig met installeren installPluginsWizard.finish.explanation=De geselecteerde Plugins worden geinstalleerd door de Update Assistent.\n\nEven geduld, het kan enkele ogenblikken duren voor deze verschijnt.\n\nDubbelklik op de statusbalk voor het voortgang rapport. installPluginsWizard.details.loading=Bezig met laden Details, even geduld.... installPluginsWizard.mode.file=Uit bestand installPluginsWizard.installMode.title=Kies het installatie type installPluginsWizard.installMode.user=Installeer de plugin(s) alleen voor deze gebruiker installPluginsWizard.installMode.shared=Installeer de plugin(s) voor alle gebruikers installPluginsWizard.file.title=Zoek de plugin die je wil installeren installPluginsWizard.file.file=Bestand : installPluginsWizard.file.invalidfile=Dit bestand is geen geldige Vuze plugin. installPluginsWizard.file.no_such_file=De file met de opgegeven naam bestaat niet. installPluginsWizard.file.browse=Verkennen... uninstallPluginsWizard.title=Un-install Plugins uninstallPluginsWizard.list.title=Geinstalleerde Plugin Lijst uninstallPluginsWizard.list.loaded=Kies de plugins die je wil verwijderen. installPluginsWizard.list.nullversion=Geen Versie uninstallPluginsWizard.finish.title=Bezig met de Un-install uninstallPluginsWizard.finish.explanation=De geselecteerde Plugins worden ge-uninstalleerd door de Update Assistant. MainWindow.menu.plugins.installPlugins=Installatie Wizard... MainWindow.menu.plugins.uninstallPlugins=Uninstallatie Wizard... ConfigView.section.ipfilter.totalIPs=%1 IP's geblokkeerd in totaal, dat is %2 van het internet. update.instance.install=Installatie Controleren update.instance.uninstall=Un-installatie Controleren update.instance.update=Controleren op Updates MainWindow.status.update.tooltip=Dubbel klik voor voortgang informatie updater.progress.window.title=Huidige Installatie Taken updater.progress.window.info=Druk op 'Afbreken' om alle klaar staande taken te be\u00ebindigen Button.abort=Afbreken ConfigView.section.ipfilter.enablebanning=Blokkeer seeders die constant corrupte data verzenden Network.alert.acceptfail=Te veel opeenvolgende mislukkingen op poort %1, %2 - verwerking gestopt. Controleer je Firewall instellingen voor deze poort om er zeker van te zijn dat deze is ingesteld voor het ontvangen van verbindingen. MyShares.column.category=Categorie UpdateWindow.restartLater=Herstart Later MainWindow.menu.file.restart=Herstart Vuze MainWindow.dialog.restartconfirmation.title=Vuze opnieuw opstarten? MainWindow.dialog.restartconfirmation.text=Weet je zeker dat je Vuze opnieuw wil opstarten? deletetorrent.message1=U staat op het punt de TORRENT te verwijderen voor :\n deletetorrent.message2=\nWeet u zeker dat u verder wil gaan? ConfigView.label.prioritizemostcompletedfiles=Geef voorrang met hoge prioriteit aan bestanden volgens % compleet en de grootte van de file splash.plugin.init=Initialiseren Plugin: splash.plugin.UIinit=Initialiceren Plugin GUI: %1 ConfigView.section.style.osx_small_fonts=Gebruik klein lettertype [herstart nodig] ConfigView.section.tracker.tcpnonblocking=Gebruik niet-blokkerende I/O voor TCP tracker verwerking. Het selecteren van deze optie vereist dat de tracker web op een alternatieve poort draait. Experimenteel! ConfigView.section.tracker.nonblocking=Niet-blokkeer opties ConfigView.section.tracker.nonblockingconcmax=Max gezamenlijke verbindingen [0: ongelimiteerd] MyTorrentsView.menu.exportmenu=Exporteer MyTorrentsView.menu.exporttorrent=Torrent.. ConfigView.group.scrape=Controle ConfigView.section.tracker.client.scrapeinfo=Het uitschakelen van scraping zal voorkomen dat veel van de torrent wachtrij regels werken, omdat deze informatie nodig hebben die verkregen wordt door het scrapen van trackers. ConfigView.section.tracker.client.scrapeenable=Schakel scraping in ConfigView.section.tracker.client.scrapestoppedenable=Scrape torrents die niet draaien Scrape.status.disabled=Scrape Uitgeschakeld MyTorrentsView.menu.explore=Toon Bestand MyTorrentsView.menu.explore._mac=Toon In Finder MyTorrentsView.menu.explore._windows=Toon in Verkenner wizard.maketorrents.autohost=Host de torrent op de ingebouwde tracker ConfigView.label.overrideip="Vervang tracker annouce-IP - gebruik ; als er meerdere verschillende netwerken zijn" ConfigView.label.overrideip.tooltip=Informeer de tracker van ander(e) IP adres(sen) dan het adres waar uitgaande pakketjes vandaan komen. Laat de optie leeg als je deze niet wil gebruiken. ConfigView.section.connection.group.networks=Netwerken ConfigView.section.connection.group.networks.info=Selecteer de standaard toegestane netwerken voor peer-peer data overdracht ConfigView.section.connection.networks.prompt=Vraag om een selectie wanneer een download met een anonieme tracker is toegevoegd ConfigView.section.connection.networks.Public=Een publiek IP netwerk (niet anoniem) ConfigView.section.connection.networks.I2P=Het I2P netwerk ConfigView.section.connection.networks.Tor=Het Onion Router (Tor) netwerk TableColumn.header.networks=Netwerken TableColumn.header.networks.info=Netwerken toegestaan voor peer-peer data communicatie Scrape.status.networkdisabled=Netwerken niet ingeschakeld ConfigView.section.tracker.server.group.networks=Netwerken ConfigView.section.tracker.server.group.networks.info=Selecteer de netwerken waarvan de tracker peers accepteert window.networkselection.title=Netwerk Selectie window.networkselection.info=De torrent hieronder heeft tracker(s) die de volgende netwerken ondersteunen.\nSelecteer de protocollen voor tracker en peer communicatie.\nAls het een anonieme tracker is die publieke cli\u00ebnts ondersteunt, schakel dan zowel de anonieme als publieke netwerken in.\nInschakelen van een publiek netwerk heeft natuurlijk als consequentie dat de anonimiteit wordt verwijderd! window.networkselection.description=Torrent: plugins.basicview.clear=Ververs ConfigView.section.connection.group.peersources=Peer bronnen ConfigView.section.connection.group.peersources.info=Selecteer de standaard toegestane bronnen voor peer verbindingen ConfigView.section.connection.peersource.Tracker=Van een tracker ConfigView.section.connection.peersource.DHT=Ongecentraliseerde tracking ConfigView.section.connection.peersource.PeerExchange=Geleverd door een andere downloader ConfigView.section.connection.peersource.Plugin=Toegevoegd door een plugin ConfigView.section.connection.peersource.Incoming=Inkomende verbinding PeersView.source=Bron PeersView.source.info=De bron van deze downloader TableColumn.header.peersources=Leechers Bronnen TableColumn.header.peersources.info=Leechers bronnen toegestaan voor het maken van peer verbindingen wizard.tracker.dht=Ongecentraliseerd (Alleen Vuze cli\u00ebnts) MyTorrentsView.menu.advancedmenu=Geavanceerd MyTorrentsView.menu.networks=Netwerken MyTorrentsView.menu.peersource=Peer Bronnen ConfigView.section.sharing.permitdht=Sta ongecentraliseerde tracking toe wanneer een tracker niet beschikbaar is ConfigView.section.sharing.protocol=Protocol voor gedeelde bronnen PeersView.Messaging=Communiceren PeersView.Messaging.info=Ondersteund geavanceerde communicatie API. ConfigView.label.queue.newseedsmovetop=Verplaats nieuwe complete torrents naar het begin van de upload lijst ConfigView.label.seeding.firstPriority.ignore.info=Het gebruik van deze regels kan er voor zorgen dat een torrent\nstopt zodra de download voltooid is. ConfigView.label.seeding.firstPriority.ignore=Negeer Eerste Prioriteit regels hierboven voor: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents met een Upload naar Download verhouding boven ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents met 0 Leechers ConfigView.section.tracker.sendjavaversionandos=Stuur Java versie en OS naam MagnetPlugin.contextmenu.exporturi=Kopieer Magneet URI naar Klembord ConfigView.section.plugins.dht=Gedistribueerde database dht.info=Deze plugin ondersteunt onder andere ongecentraliseerde tracking.\nHet uitschakelen hiervan zal uw download mogelijkheden verkleinen. dht.enabled=Schakel de verspreide database in dht.portdefault=Gebruik de standaard poort dht.port=UDP poort voor de database dht.execute.command=Diagnose commando dht.execute.info=Klik om het commando uit te voeren dht.execute=Uitvoeren dht.logging=Schakel bijhouden van activiteit in ConfigView.section.plugins.dhttracker=Gedistribueerde Tracker dhttracker.tracknormalwhenoffline=Houd alleen normale torrents bij wanneer hun tracker niet beschikbaar is ConfigView.section.file.nativedelete._mac=Gebruik prullenbak voor verwijderen bestanden ConfigView.section.file.nativedelete._windows=Verplaats verwijderde bestanden naar de Prullenbak ConfigView.section.logging.generatediagnostics=Genereer ConfigView.section.logging.netinfo=Genereer netwerk info ConfigView.section.logging.statsinfo=Genereer statistieken info ConfigView.section.logging.generatediagnostics.info=Genereer diagnostische informatie en kopieer deze naar het klembord en een log bestand, als dit ingesteld is ConfigView.section.sharing.privatetorrent=Priv\u00e9 torrent - accepteert alleen downloaders van de tracker MainWindow.menu.tools.nattest=&NAT/Firewall Test Button.apply=Toepassen Button.close=Sluiten window.welcome.title=Welkom bij Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Versie Details dht.reseed.label=Normaal is het herseeden van de Verspreide Database niet nodig. Als het aantal contacten laag is, kan dit gebruikt worden voor herintegratie.\nLaat leeg om met verbonden peers te delen, of vul een IP en poort in om te seeden aan een bekende peer. dht.reseed.group=Opnieuw seeden dht.reseed.ip=IP adres dht.reseed.port=Poort dht.reseed=Her seed dht.reseed.info=De database opnieuw uploaden dht.diagnostics.group=Diagnostiek DHTView.title.full=Gedistribueerde Database DHTView.title.fullcvs=Gedistribueerde Database CVS DHTView.general.title=Algemeen DHTView.general.uptime=Uptijd: DHTView.general.users=Gebruikers: DHTView.general.nodes=Nodus: DHTView.general.contacts=Contacten: DHTView.general.replacements=Vervangingen: DHTView.general.live=Leven: DHTView.general.unknown=Onbekend: DHTView.general.dying=Stervend: DHTView.transport.title=Transport details DHTView.transport.packets=Pakketjes DHTView.transport.received=Ontvangen DHTView.transport.sent=Verzonden DHTView.transport.in=In: DHTView.transport.out=Uit : DHTView.operations.title=Operatie Details DHTView.operations.sent=Verzonden DHTView.operations.failed=Mislukt DHTView.operations.received=Ontvangen DHTView.operations.findNode=Zoek Node DHTView.operations.findValue=Zoek Waarde DHTView.operations.store=Opslag DHTView.activity.title=Activiteit DHTView.activity.status.true=Gestopt DHTView.activity.status.false=Bezig DHTView.activity.type.1=Interne Ontvangst DHTView.activity.type.2=Externe Ontvangst DHTView.activity.type.3=Interne Plaatsing DHTView.activity.type.4=Externe Plaatsing DHTView.activity.target=Doel DHTView.db.values=Waarden DHTView.db.local=Lokaal DHTView.db.direct=Direkt DHTView.db.indirect=Indirekt DHTView.db.divfreq=Freq. Verschil DHTView.db.divsize=Grootte Verschil MainWindow.dht.status.tooltip=Wanneer de Verspreidde Database draait, wordt hier het geschatte aantal gebruikers dat online is getoond. MainWindow.dht.status.disabled=DDB uitgeschakeld MainWindow.dht.status.failed=Mislukt MainWindow.dht.status.initializing=Initialiseren MainWindow.dht.status.users=%1 Gebruikers MainWindow.dht.status.unreachable=DHT Ge-Firewalled MainWindow.dht.status.unreachabletooltip=Er blijkt een probleem te zijn met de Distributed Databases met de poort mapping MyTorrentsView.menu.setUpSpeed=Wijzig Upload Snelheid MyTorrentsView.menu.setDownSpeed=Wijzig Download Snelheid ConfigView.section.tracker.client.showwarnings=Toon waarschuw berichten gerapporteerd door trackers dht.advanced=Schakel geavanceerde instellingen in dht.advanced.group=Geavanceerde instellingen dht.advanced.label=Verander deze waardes alleen als je weet wat je doet dht.override.ip=Vervang externe IP adressen ConfigView.section.logging.loggerenable=Schakel logging in ConfigView.section.ipfilter.blockbanning=Ban een blok van 256 adressen, wanneer minstens de volgende hoeveelheid in dat blok is verbannen MyTrackerView.passive=Passief TableColumn.header.swarm_average_speed=Zwerm Gem. Snelheid TableColumn.header.swarm_average_speed.info=De gemiddelde snelheid van peers in de zwerm TableColumn.header.comment=Commentaar TableColumn.header.comment.info=Gebruiker gedefineerd commentaar voor deze download TableColumn.header.commenticon=Commentaar Icon TableColumn.header.commenticon.info=Toon het icon als er gebruikers commentaar bij de torrent geplaatst is. MyTrackerView.category=Categorie MainWindow.menu.file.open.torrentfortracking=Torrent Bestand... (Alleen Tracking) MyTrackerView.date_added=Toegevoegd ConfigView.section.tracker.portbackup="Backup poorten ( gescheiden door ; )" ConfigView.label.playfilespeech=Spreek als een file gereed is ConfigView.label.playfilespeech.info=Spraak Service werkt momenteel het beste met Engels ConfigView.label.playfilefinished=Speel een geluid/muziekje als een stukje van de file gereed is ConfigView.label.backupconfigfiles=Backup configuratie files voor herstel opties ConfigView.section.tracker.client.scrapesingleonly=Uitzetten per-tracker scrape aggregation (kan helpen bij trackers die rapporteren dat de 'URL te lang is ' (414) errors) dht.ipfilter.log=Log IP Filter overtredingen ConfigView.label.seeding.addForSeedingDLCopyCount=Beschouw 'toevoegen voor seeden' downloads alsof ze dit aantal kopie\u00ebn hebben gedownload ActivityView.legend.limit=Snelheidslimiet ActivityView.legend.achieved=Snelheid bereikt ActivityView.legend.overhead=Algemenen beoordeling ActivityView.legend.peeraverage=Gemiddeld ActivityView.legend.swarmaverage=Zwerm gemiddelde ActivityView.legend.trimmed=Op orde gezet (gestippeld) MyTorrentsView.menu.movemenu=Wis Files MyTorrentsView.menu.movedata=Wis Data Files... MyTorrentsView.menu.movetorrent=Wis Torrent File... MyTorrentsView.menu.movedata.dialog=Kies nieuwe locatie DHTView.general.reachable=Bereikbaar: DHTView.general.rendezvous=Afspraken: ConfigView.label.queue.maxactivetorrentswhenseeding=Max bij alleen seeden [0:ongelimiteerd] Views.plugins.IRC.title=IRC - Online Technische Hulp. Formats.units.persec=/sec. Formats.units.alot=Heel veel !!! ConfigView.section.ipfilter.persistblocking=Bewaar geblokkeerde IP details tijdens herstart FilesView.menu.rename=Hernoem of herplaats FilesView.menu.rename_only=Hernoem FilesView.menu.retarget=Nieuwe doelstelling FilesView.rename.choose.path=Kies nieuw of bestaande file FilesView.rename.choose.path.dir=Kies een nieuwen of bestaande directorie FilesView.rename.confirm.delete.title=Bevestig verwijderen FilesView.rename.confirm.delete.text=Bevestig verwijdering van het originele bestand '%1' FilesView.rename.filename.title=Hernoem de file FilesView.rename.filename.text=Kies een nieuwen naam voor de file ConfigView.higher.mode.available=Meer opties zijn beschikbaar in een hogeren gebruiker modes. ConfigView.section.mode=Modus ConfigView.section.mode.title=Gebruikers kennis ConfigView.section.mode.beginner=Beginner. ConfigView.section.mode.beginner.wiki.definitions=Bittorrent woordenboek (In het Engels) ConfigView.section.mode.intermediate=Gevorderd (beheer tracker) ConfigView.section.mode.intermediate.wiki.host=Hosten van Files ConfigView.section.mode.intermediate.wiki.publish=Publiceren van Files ConfigView.section.mode.advanced=Experts (beheer tracker en netwerk) ConfigView.section.mode.advanced.wiki.main=Wiki hoofd pagina ConfigView.section.mode.beginner.text=Alleen wat je nodig hebt om torrents te downloaden.\nGebruik deze mode om alleen je torrents te beheren. ConfigView.section.mode.intermediate.text=Toegang tot tracker functies.\nGebruik deze mode als je zelf de ingebouwde tracker wil gebruiken en host/publiceren van je bestanden. ConfigView.section.mode.advanced.text=Toegang tot netwerk instellingen.\nGebruik deze mode als je weet wat MTU en non blocking I/O zijn... Files.column.storagetype=Opslag Type FileItem.storage.linear=Lineair FileItem.storage.compact=Kompakt MessageBoxWindow.rememberdecision=Onthoud mijn besluit! ConfigView.section.interface.cleardecisions=Verwijder de onthouden dialoog besluiten ConfigView.section.interface.cleardecisionsbutton=Verwijder ConfigView.section.interface.cleartrackers=Verwijder onthouden trackers uit de lijst. ConfigView.section.interface.cleartrackersbutton=Verwijder ConfigView.section.interface.clearsavepaths=Verwijder onthouden opslag richting/paths ConfigView.section.interface.clearsavepathsbutton=Verwijder configureWizard.welcome.usermodes=Deze Gebruiker-Vaardigheids instelling bepaalt het niveau van de opties te zien in Gereedschappen > Configuratie. Het is in jouw eigen belang deze juist in te stellen. FilesView.skip.confirm.delete.text=Inkorten van bestand '%1' om ruimte te sparen? FilesView.rename.failed.title=Herbenoem/Herplaatsing gefaald FilesView.rename.failed.text=De bewerking faalde, waarschijnlijk door een foute keuze van het doel diagnostics.log_found=Vuze is niet correct afgesloten. Controleer %1 het diagnostische log bestanden en overweeg deze aan het Vuze team te rapporteren als dit het resultaat van een applicatie fout is. ManagerItem.paused=Gepauzeerd Utils.link.visit=Bezoek a.u.b. ConfigView.section.connection.serverport.wiki=Goede poort keuzes ConfigView.section.transfer.speeds.wiki=Goede snelheid instellingen installPluginsWizard.installMode.info.text=Je hebt geen plugins nodig om Vuze goed te laten werken, ze zijn alleen bedoelt voor wat extra plezier, automatisering en bediening op afstand.\nDaarom lees de beschrijving goed van de plugin voordat je besluit deze te installeren.\nDe meeste plugins zijn veilig uit te proberen, maar overlaad je configuratie niet met plugins die je toch niet gaat gebruiken. Views.plugins.Distributed.DB.title=Gedistribueerde Database Views.plugins.Distributed.Tracker.title=Gedistribueerde Tracker Views.plugins.Plugin.Update.title=Plugin update Views.plugins.UPnP.title.tooltip=Universeel Plug en Play openUrl.url.info=Ondersteunt http, https, magnet and raw hex infohash strings TableColumn.header.swarm_average_completion=Zwerm gemiddelde kompleet TableColumn.header.swarm_average_completion.info=Gemiddelde kompleet in percentage van peers in de zwerm GeneralView.label.swarm_average_completion=Gemiddeld compleet GeneralView.label.swarm_average_completion.tooltip=Het complete gemiddelde in procenten van de peers in de zwerm. MainWindow.nat.status.unknown=NAT Uitgeschakeld MainWindow.nat.status.tooltip.unknown=NAT Status Onbekend (TCP) MainWindow.nat.status.ok=NAT Ok. MainWindow.nat.status.tooltip.ok=NAT OK (TCP) MainWindow.nat.status.probok=NAT Ok? MainWindow.nat.status.tooltip.probok=NAT was OK, hoewel geen recente binnen komende TCP connecties MainWindow.nat.status.tooltip.bad=Mogelijk een NAT (TCP) probleem, kijk op de Wiki pagina als dit zo blijft plugin.installer.recommended.plugin=Aangeraden plugin - A.U.B. bekijk deze en installeer als het nodig is LoggerView.pause=Pauzeer het Loggen LoggerView.clear=&Verwijder LoggerView.filter.uncheckAll=Alle Categorie\u00ebn uit LoggerView.filter.checkAll=Alle Categorie\u00ebn aan LoggerView.loggingDisabled=Loggen is niet aangezet. LoggerView.includeOnly=Vertoon alleen regels die overeen komen met de standaard uitdrukking(en): LoggerView.excludeAll=Vertoon geen regels welke overeen komen met de standaard uitdrukking(en): ConfigView.section.logging.log0type=Informatie ConfigView.section.logging.log1type=Waarschuwing ConfigView.section.logging.log2type=Fout ConfigView.section.logging.filter=Filter wanneer de file gelogd word ConfigView.section.logging.level=Log level ConfigView.section.logging.showLogsFor=Toon %1 logs voor de volgende categorie: ConfigView.pluginlist.column.loadAtStartup=Laden bij opstarten ConfigView.pluginlist.column.type.perUser=Per Gebruiker ConfigView.pluginlist.column.type.shared=Gedeeld ConfigView.pluginlist.column.type.builtIn=Ingebouwd ConfigView.pluginlist.column.name=Naam ConfigView.pluginlist.column.version=Versie ConfigView.pluginlist.column.directory=Directorie ConfigView.pluginlist.column.isOperational=Operationeel? PeersView.BlockView.Avail.Have=Beide hebben PeersView.BlockView.Avail.NoHave=Peer heeft, jij niet PeersView.BlockView.NoAvail.Have=Jij hebt, Peer niet PeersView.BlockView.NoAvail.NoHave=Niemand heeft PeersView.BlockView.Transfer=Verzenden PeersView.BlockView.NextRequest=Volgend verzoek PeersView.BlockView.title=Stukjes Map PeersView.BlockView.AvailCount=Beschikbaarheidsteller MyTorrentsView.dialog.NumberError.title=Ongeldig of onbekend nummer MyTorrentsView.dialog.NumberError.text=Het opgegeven nummer is fout of niet herkenbaar. MyTorrentsView.menu.manual=&Handmatig.. MyTorrentsView.menu.manual.per_torrent=Handmatig (per torrent) MyTorrentsView.menu.manual.shared_torrents=Handmatig (door de torrents) MyTorrentsView.dialog.setSpeed.title=Zet %1 Snelheid # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Geef een nummer %1 om %2 te veranderen in: OpenTorrentWindow.torrentLocation=Torrent Bestanden: (1 torrent bestand per regel) OpenTorrentWindow.addFiles.URL=Nieuwe &URL OpenTorrentWindow.addFiles.Folder=Nieuwe &Folder OpenTorrentWindow.addFiles.Clipboard=Plaats van Clip&board OpenTorrentWindow.changeDestination=Verander bestemming OpenTorrentWindow.fileList=Bestanden in de torrents: OpenTorrentWindow.torrentTable.name=Naam OpenTorrentWindow.torrentTable.saveLocation=Bewaar locatie OpenTorrentWindow.fileTable.fileName=File naam: OpenTorrentWindow.fileTable.size=Grote: OpenTorrentWindow.fileTable.destinationName=Bestem. naam: OpenTorrentWindow.startMode.seeding=Seeden OpenTorrentWindow.fileList.changeDestination=Verander bestemming OpenTorrentWindow.mb.badSize.title=Onverenigbaar bestand OpenTorrentWindow.mb.badSize.text='%1' is niet '%2' en kan niet gebruikt worden om te seeden OpenTorrentWindow.mb.alreadyExists.text=Torrent '%1' is al toegevoegd als '%2' OpenTorrentWindow.mb.alreadyExists.title=Torrent bestaat al OpenTorrentWindow.mb.openError.title=Opening fout OpenTorrentWindow.mb.openError.text='%1' kon niet geopend worden: OpenTorrentWindow.torrent.remove=Verwijder de torrent van de lijst. OpenTorrentWindow.torrent.options=De volgende instellingen zullen gebruikt worden voor de bovenstaande torrents: OpenTorrentWindow.xOfTotal=(%1 van %2) iconBar.open.tooltip=Open een .torrent-bestand LocaleUtil.column.text=Onbekende tekst Tracker.tooltip.MultiSupport=Deze tracker ondersteunt multiple hash scrapes per verzoek. Tracker.tooltip.NoMultiSupport=Deze tracker ondersteunt geen multiple hash scrapes per verzoek. ConfigView.label.lazybitfield=Gebruik lazy bitfield (helpt seeden op netwerken dat gebruik maakt van bitfield-based blocking) LoggerView.realtime=Update in werkelijke tijd ConfigView.section.file.perf.cache.flushpieces=Schrijf complete stukjes direct naar de schijf. Dit veroorzaak een rustigere toegang tot de schijf, maar kan tot meer schrijfbewerking leiden. ConfigView.section.file.writemblimit=Maximum schrijf verzoeken in wachtrij (in %1) ConfigView.section.file.writemblimit.explain=Wanneer de disk schrijf snelheid lager is als de download snelheid, zet deze parameter de weg te schrijven data in een wachtrij zodat de download snelheid niet nog lager wordt. ConfigView.section.file.readmblimit=Maximum lees verzoeken in wachtrij (in %1) ConfigView.section.file.readmblimit.explain=Deze parameter limiteert hoeveel geheugen gebruikt wordt voor het opslaan van lees bewerkingen voor CPU gebruik. Button.moveUp=Verplaats &Op Button.moveDown=Verplaats &Neer ConfigView.notAvailableForMode=Deze sectie is bedoeld voor %1 modus of hoger. Het is niet beschikbaar in %2 modus. health.explain.error=Er is iets fout met deze torrent. Bekijk de status kolom, of de tooltip op het icoontje voor de uitleg van de fout. GeneralView.label.trackerscrapeupdate=Scrape de Tracker PeersView.piece=Stukjes PeersView.piece.info=Laatste stukje aantal gevraagd van deze peer PiecesView.priority=Prioriteit PiecesView.priority.info=dit stukje compleetheids prioriteit, maar besteed er niet teveel aandacht aan PiecesView.speed=Snelheid PiecesView.speed.info=Langzame peers worden geweerd inzake verwerking van snelleren stukjes TableColumn.header.AvgAvail.info=Som van de beschikbaren stukjes gedeelt door aantal stukjes, gedeelt door aantal connecties TableColumn.header.AvgAvail=Avg Avail/piece ConfigView.label.strictfilelocking=Forceer exclusieve file schrijf toegang blokkering voor alle torrents MyTorrentsView.menu.checkfilesexist=Controleer of de files bestaan. MyTorrentsView.menu.rescanfile=Periodieke hercontrole incomplete stukjes MyTorrentsView.menu.clear_resume_data=Verwijder vernieuwde data Plugin.extseed.name=Externe Seeds Plugin.localtracker.name=LAN Peer Zoeker Plugin.localtracker.info=De LAN peer zoeker staat meer kopie\u00ebn toe als Vuze achter een Firewall zit of een normaal netwerk\ndoor effectief te downloaden door een direct contact tussen de twee. Plugin.localtracker.enable=Aanzetten van de LAN peer zoeker azinstancehandler.alert.portclash=Poort conflict gedetecteerd op LAN: %1 wordt al gebruikt door een andere Vuze gebruiker, selecteer een nieuwe willekeurige poort(en) voor inkomende TCP / UDP listen [tussen %2 en %3]. ConfigView.section.transfer.lan=LAN. ConfigView.section.transfer.lan.tooltip=LAN-specifieken instellingen ConfigView.section.transfer.lan.uploadrate=KB/s LAN max upload snelheid [0: ongelimiteerd] ConfigView.section.transfer.lan.uploadrate.tooltip=Peers verbindingen binnen de zelfde interne LAN hebben een gescheiden upload grens limit. ConfigView.section.transfer.lan.downloadrate=KB/s LAN max download snelheid [0: ongelimiteerd] ConfigView.section.transfer.lan.downloadrate.tooltip=Peers connectie in de zelfde interne LAN hebben een gescheiden download grens limit. TorrentOptionsView.title.short=Opties TorrentOptionsView.title.full=Opties TorrentOptionsView.param.max.peers=Maximum nummer voor connectie`s [0: ongelimiteerd] ConfigView.section.connection.encryption.require_encrypted_transport=Benodigd encryptie transport ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Forceer gebruik van encryptie connecties met anderen peers. ConfigView.section.connection.encryption.min_encryption_level=Min. encryptie level ConfigView.section.connection.encryption.min_encryption_level.tooltip=Alleen Normaal - handshake\nRC4 - full stream\nHooger encryptie heeft meer CPU nodig. Peers.column.Encryption=Encryptie Peers.column.Encryption.info=Hoogte van encryptie in gebruik ConfigView.section.connection.encryption.encrypt.info=Als encryptie wordt gebruikt kun je geen kontact maken met niet gelijkwaardige cli\u00ebnte. ConfigView.section.connection.encryption.encrypt.info.link=Ga hier op bezoek voor details MainWindow.sr.status.tooltip.ok=Deel Ratio %1 OK > 1.1 MainWindow.sr.status.tooltip.poor=Deel Ratio %1 laag: < 0.9 MainWindow.sr.status.tooltip.bad=Deel Ratio %1 slecht: < 0.5 ConfigView.section.style.status=Status gebied: ConfigView.section.style.status.show_sr=Deel Ratio ConfigView.section.style.status.show_nat=NAT Status. ConfigView.section.style.status.show_ddb=DDB Status. ConfigView.section.style.status.show_ipf=IPFilter Status. ConfigView.section.connection.encryption.encrypt.fallback_info=Toestaan oftewel terugval optie, zal connecties toestaan tot incompatibel cli\u00ebnte MAAR zal resulteren in niet-encryptie connecties ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Toestaan niet-encryptie uitgaande connecties als encryptie connectie pogingen falen ConfigView.section.connection.encryption.encrypt.fallback_incoming=Toestaan niet-encryptie inkomende connecties upnp.selectedinterfaces="Geselecteerde Interfaces (';'gescheiden door, e.g. eth0;eth1) [Leeg: alle]" ConfigView.section.style.defaultSortOrder=Standaard sorteer volgorde ConfigView.section.style.defaultSortOrder.desc=Oplopend ConfigView.section.style.defaultSortOrder.asc=Aflopend ConfigView.section.style.defaultSortOrder.flip=Tegengesteld aan de vorige volgorde Button.selectAll=Selecteer Alles Button.markSelected=Markeer geselecteerde Button.unmarkSelected=Demarkeer geselecteerde plugins.basicview.config=Configuratie TorrentOptionsView.param.max.uploads=Maximum nummer voor upload slots [minimum: 2] MyTorrentsView.dialog.setPosition.title=Zet de Positie MyTorrentsView.dialog.setPosition.text=Geef de map op, om de torrents naar toe te plaatsen: MyTorrentsView.menu.reposition.manual=Herplaatsen.. ConfigView.section.connection.advanced.info.link=Bezoek a.u.b. deze link voor nadere details ConfigView.section.connection.advanced.socket.group=Socket Opties ConfigView.section.connection.advanced.bind_port=Koppel uitgaande connecties aan dezelfde lokale poort ConfigView.section.connection.advanced.bind_port.tooltip=Uitgaande socket connecties zullen lokaal gezet worden op dezelfde poort als de inkomende connecties.\nAanzetten kan helpen met een NAT, als de router onstabiel is. ConfigView.section.proxy.group.tracker=Tracker Communicaties ConfigView.section.proxy.group.peer=Peer Communicaties Pieces.column.Requested=Gevraagd Pieces.column.Requested.info=Bekijk/probeer of er meer verzoeken gedaan kunnen worden op het stukje of niet (*) ConfigView.label.maxuploadsseeding=Alternatieven standaard slots bij alleen seeden MyTorrentsView.filter=Filter: [%1] popup.error.hideall=Verstop allen ConfigView.section.style.dataStatsOnly=Toon alleen data statistieken (geen protocol statistieken) ConfigView.section.style.separateProtDataStats=Toon gescheiden data en protocol statistieken als 'data (protocol)' MyTorrentsView.dialog.setFilter.title=Modificeer Filter MyTorrentsView.dialog.setFilter.text=De %1 sectie zal gefilterd worden op de tekst die je hier onder specificeert. Gebruik het | (pipe) symbool om te filteren op veelvoudige uitdrukkingen. MyTorrentsView.filter.tooltip=Ctrl+X om te schakelen tussen RegEx en normalen zoek modes.\nGebruik het | (pipe) symbool om te filteren op veelvoudige uitdrukkingen. MyTorrentsView.clearFilter.tooltip=Opschonen Filter MyTorrentsView.menu.filter=Filter Lijst... ConfigView.section.file.resume.recheck.all=Na crash-herstart controleer totalen file voor complete stukjes (Anders alleen stukjes die actief waren na laatste gecontroleerde opslag) ConfigureWizard.language.choose=Kies een taal uit de onderstaande lijst: popup.closing.in=Auto-sluiten scherm in %1 seconden popup.more.waiting=%1 meer bericht(en)... # > 2402 popup.download.finished="%1" Is klaar met downloaden. popup.file.finished="%1" Is klaar met downloaden. ConfigView.auto=Automatisch Plugin.localtracker.autoadd.info="Automatisch plaats deze local peers [';' gescheiden adressen, e.g. 1.2.3.4]" Plugin.localtracker.autoadd=Expliciet peers Plugin.localtracker.networks.info="Overweeg de volgende netwerken als local [';' gescheiden netwerken, e.g. 145.227.*.*]" Plugin.localtracker.networks=Local netwerk MainWindow.menu.view.plugins.logViews=Log bekijken SpeedView.stats.autospeed=Automatische upload Snelheid SpeedView.stats.autospeed.disabled=Deze eigenschap is of uitgezet (u hebt DHT nodig) of niet in gebruik (handmatig geselecteerde upload snelheid) SpeedView.stats.currentPing=Huidigen Ping: SpeedView.stats.maxUp=Max Up Snelheid: ConfigView.pluginlist.unloadSelected=Unload Geselecteerden ConfigView.pluginlist.scan=Scan voor nieuwen Plugins ConfigView.section.transfer.autospeed=Auto-Snelheid ConfigView.section.transfer.autospeed.tooltip=Auto-Snelheid specifieke instellingen ConfigView.section.transfer.autospeed.info=De Auto-Snelheid past automatisch de upload snelheidsgrens aan,om overbelasting van de netwerkverbinding te vermijden.\n\nDit limit zal slechts van toepassing zijn wanneer automatisch upload snelheid is aan gezet en ook de distributed database aanstaat.\n ConfigView.section.transfer.autospeed.minupload=%1 minimum upload snelheid ConfigView.section.transfer.autospeed.minupload.tooltip=Upload snelheid zal niet automatisch verminderd worden onder deze grens ConfigView.section.transfer.autospeed.maxupload=%1 maximum upload snelheid [0: ongelimiteerd] ConfigView.section.transfer.autospeed.maxupload.tooltip=Upload snelheid zal niet automatisch stijgen boven deze grens ConfigView.section.transfer.autospeed.chokeping=Choking ping tijd [milliseconde] ConfigView.section.transfer.autospeed.chokeping.tooltip=Ping tijden in deze waarde zullen als indicator van netwerkverzadiging worden beschouwd ConfigView.section.transfer.autospeed.enableauto=Gebruik met downloaden en uploaden ConfigView.section.transfer.autospeed.enableautoseeding=Gebruik alleen met seeden ConfigView.pluginlist.column.unloadable=Niet laadbaar ConfigView.section.transfer.lan.enable=Aanzetten gescheiden snelheid limit voor LAN connecties Plugin.localtracker.wellknownlocals=Automatisch gebruiken loopback/link/site local networks (192.168 etc) TableColumn.header.filesdone=Files klaar TableColumn.header.filesdone.info=Files klaar/Totaal files *of* Non-skipped files klaar (Files klaar)/Totaal Non-skipped files (Totaal files) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=wachten op DDB initialiseren... MagnetPlugin.report.searching=zoeken... MagnetPlugin.report.found=gevonden %1 MagnetPlugin.report.alive=%1 is levend/aanwezig MagnetPlugin.report.dead=%1 is dood/afwezig MagnetPlugin.report.tunnel=op zoek naar %1 MagnetPlugin.report.downloading=downloaden van %1 MagnetPlugin.report.error=fout %1 MagnetURLHandler.report.no_sources=geen bronnen gevonden voor torrent MagnetURLHandler.report.torrent_size=torrent grote: %1 MagnetURLHandler.report.percent=compleet: %1% MagnetURLHandler.report.error=fout %1 DHTTransport.report.request_all=verzoek complete verzending van %1 DHTTransport.report.received_bit=ontvangen %1 naar %2 van %3 DHTTransport.report.complete=compleet DHTTransport.report.timeout=time-out, geen antwoord van %1 DHTTransport.report.rerequest_all=herverzoek complete verzending van %1 DHTTransport.report.rerequest_bit=herverzoek %1 naar %2 van %3 DHTTransport.report.timeout_some=time-out, %1 pakketen ontvangen van %2 maar incompleet DHTTransport.report.sending=verzenden data DHTTransport.report.resending=herzenden data DHTTransport.report.send_complete=verzenden compleet DHTTransport.report.send_timeout=verzend time-out ConfigView.section.transfer.autospeed.enabledebug=Log debug informatie TableColumn.header.date_added=Datum gemaakt TableColumn.header.date_added.info=Datum dat de torrent is gemaakt ConfigView.section.file.hashchecking.smallestfirst=Hercontroleer de kleinste downloads eerst platform.win32.baddll.info=Vuze heeft de aanwezigheid ontdekt van '%1'. Dit is een deel van '%2' en staat bekend dat het server problemen veroorzaakt zoals applicatie crashes en hoog CPU gebruik. Als je dit constateert, dan uninstall de software of configureer het zo dat het geen invloed heeft op Vuze. platform.win32.baddll.winsflt=PureSight Internet Inhoud Filter upnp.ignorebaddevices=Negeer devices die niet correct reageren upnp.ignorebaddevices.info=Momenteel genegeerde devices: %1 upnp.ignorebaddevices.reset=Herstel de genegeerde device lijst upnp.ignorebaddevices.reset.action=Herstel upnp.ignorebaddevices.alert=UPnP device op locatie %1 word genegeerd door herhaalde vale. Bekijk de UPnP plugin configuratie voor mogelijkheden betreffende deze actie. TorrentOptionsView.param.max.uploads.when.busy=KB/s max upload snelheid wanneer het globale upload limiet is bereikt [0: uitgezet] UpdateMonitor.messagebox.verification.failed.title=Installatie Controle Mislukt UpdateMonitor.messagebox.verification.failed.text=Controle van '%1' mislukt : %2 UpdateMonitor.messagebox.accept.unverified.title=Accepteer ongecontroleerd Installatie UpdateMonitor.messagebox.accept.unverified.text='%1' kon niet bevestigt worden als een offici\u00eble Vuze plugin.\nAls het geen offici\u00eble is zou U NIET door moeten gaan.\nDoor gaan met installeren? FileView.BlockView.title=File stukjes FileView.BlockView.Done=Gedaan FileView.BlockView.Skipped=Overgeslagen FileView.BlockView.Active=Actief FileView.BlockView.Outstanding=Achterstallig ConfigView.label.tcplistenport=Inkomende TCP luister poort ConfigView.label.udplistenport=UDP luister poort upnp.portchange.alert=De volgende poorten zijn veranderd om problemen te voorkomen in de UPnP device: %1 [oude poort;%2] %3 [oude poort;%4] ConfigView.section.proxy.username.info=Als de proxy server authentificatie eist, zelf als none is bepaald, gebruik de string "" als de gebruikers naam/namen. ConfigView.label.maxuploadswhenbusymin=Per torrent max upload snelheid, gebruik tijdopnemer [sec] MainWindow.menu.help.debug=Genereer Debug Info DownloadManager.error.badsize=Niet correcte Grootte ConfigView.section.NATPMP=NAT - PMP natpmp.info=NAT-PMP is Apple's alternatief voor UPnP en is ondersteunt door recente luchthavens\n\nOnthoud dat momenteel UPnP moet zijn aan gezet voor gebruik van NAT-PMP als de NAT-PMP device is gebruikt als een special type of UPnP device natpmp.enable=Gebruik (onthoud dat het moet aanstaan in de luchthaven configuratie om te werken) ConfigView.section.tracker.host.addurls=Verzeker dat de tracker's URLs aanwezig zijn in gehoste torrents ConfigView.filter=- type zoek tekst - ConfigView.section.files.move=Verplaatsen van Torrent (compleet) ConfigView.section.file.defaultdir.section=Standaard Directorie Opties ConfigView.section.file.defaultdir.auto=Automatische download naar standaard directorie (Geen Prompt) ConfigView.section.file.defaultdir.bestguess=Gebruik de beste keuze bij het kiezen van een standaard opslag directorie ConfigView.section.file.defaultdir.ask=Standaard directorie: ConfigView.section.file.defaultdir.lastused=Update standaard directorie naar de locatie waar het laast opgeslagen is ConfigView.section.file.config.section=Configuratie Instellingen ConfigView.section.file.config.currentdir=Huidigen configuratie directorie: ConfigView.section.torrent.decoding=Decoderen karakter tekens ConfigView.section.logging.udptransport=Aanzetten verbose UDP transport tracering Tracker.announce.ignorePeerSeed=Negeren Peer/Seed aantal. %1 ConfigView.section.connection.encryption.use_crypto_port=Gebruik de ' crypto-poort ', om onduidelijke inkomende tracker verbindingspogingen te verhinderen.\nSommige trackers keuren dit niet goed en onderbreken met fouten zoals "OngeldigePoort" of "illegaal Argument" TorrentOptionsView.param.reset.to.default=Zet de opties terug naar hun standaard waarden TorrentOptionsView.param.reset.button=Herstel natpmp.routeraddress=Station adres [Leeg: auto] ConfigView.section.style.disableAlertSliding=Uitzetten (glijden stijl) van het animatie schermpje met waarschuwings berichten. ConfigView.section.transfer.autospeed.maxinc=%1 maximum verlaagt per ronde ConfigView.section.transfer.autospeed.maxdec=%1 maximum verhoogt per ronde ConfigView.section.transfer.autospeed.enabledownadj=Gebruik download snelheid gelijkstelling ConfigView.section.transfer.autospeed.downadjratio=Download : Upload snelheid ratio (e.g. 2.0 -> download snelheid limit is dubbel upload limit) ConfigView.section.transfer.autospeed.latencyfactor=Factor gebruikt naar de link latency veranderd naar snelheid verandering (hogeren nummersverlagen de sensitiviteit) ConfigView.section.transfer.autospeed.reset=Herstel geadvanceerde waardes ConfigView.section.transfer.autospeed.reset.button=Herstel PeerColumn.activationCount=Peers poging voor connect: %1 TableColumn.header.timesincedownload.info=De tijd is verstreken zins de data van de torrent is gedownload TableColumn.header.timesincedownload=Downl Idle TableColumn.header.timesinceupload.info=De tijd is verstreken zins de data van de torrent was geupload TableColumn.header.timesinceupload=Upl Idle PeersView.incomingreqcount=In verz. PeersView.incomingreqcount.info=Tel de binnen komende verzoeken gemaak door een peer PeersView.outgoingreqcount=Uitgaande verzoek PeersView.outgoingreqcount.info=Tel de uitgaande verzoeken gemaak door een peer upnp.mapping.trackerclientudp=UDP Tracker Client Poort upnp.mapping.dhtudp=Gedistribueerde Database ConfigView.section.connection.nondata.udp.same=Gebruik de zelfde UDP poort voor de Gedistribueerde Database en UDP Tracker ConfigView.section.connection.tcp.enable=Aanzetten TCP ConfigView.section.connection.udp.enable=Aanzetten UDP ConfigView.section.style.showiconbar=Toon gereedschap balk MainWindow.menu.view.iconbar=Gereedschap balk MyTorrentsView.menu.rename=Hernoem MyTorrentsView.menu.rename.displayed=Hernoem de getoonde naam MyTorrentsView.menu.rename.save_path=Hernoem opslag map MyTorrentsView.menu.rename.displayed.enter.title=Hernoem de getoonde naam MyTorrentsView.menu.rename.displayed.enter.message=Geef een nieuwen naam om deze download te tonen.\nAls er geen tekst geplaatst is, wordt de originelen naam gebruikt. MyTorrentsView.menu.edit_comment=Schrijf commentaar MyTorrentsView.menu.edit_comment.enter.title=Schrijf commentaar MyTorrentsView.menu.edit_comment.enter.message=Plaats een commentaar voor deze download UIDebugGenerator.messageask.title=Debug generator UIDebugGenerator.messageask.text=A.u.b. geef een beschrijving van de bug die u wil raporteren. UIDebugGenerator.complete.title=Debug Genereren Compleet UIDebugGenerator.complete.text=A.u.b. zend de file '%1'.\n\nClick op Ok om een scherm te openen naar deze file. ConfigView.section.style.showProgramIcon=Toon programma icon in de naam kolom. ConfigView.section.style.showProgramIcon.tooltip=Bekijken heeft misschien heropen nodig voor de veranderingen werken. swt.alert.cant.update=SWT bibliotheek geladen van "%3" kan niet automatisch geupdate worden van versie %1 naar %2 (moet geladen worden van "%4"). A.u.b. bekijk the wiki voor details (Engels). authenticator.savepassword=Onthoud mijn wachtwoord. ConfigView.section.security.clearpasswords=Herstel onthoud mijn wachtwoord. ConfigView.section.security.clearpasswords.button=Herstel Content.alert.notuploaded.title=Uploads niet compleet Content.alert.notuploaded.text=Upload van '%1' is niet compleet. Als je %2 dit nu doet, zullen personen niet de mogelijk hebben het geen je geplubiseerd hebt kunnen downloaden.\n\nWeet je zeker dat je %2 dit wil? Content.alert.notuploaded.multi.title=Uploads niet compleet Content.alert.notuploaded.multi.text=%1 als de inhoud van het gepubliseerde niet compleet is geseed. Als je %2 dit nu doet, zullen personen niet de mogelijkheid hebben het geen je gepubliseerd heb, compleet te kunnen downloaden. Weet je zeker dat je %2 dit wil?\n\nInhoud niet compleet geseed: %3 Content.alert.notuploaded.quit=stop Vuze TorrentInfoView.torrent.encoding=Torrent coderen TorrentInfoView.columns=Kolommen van 'Mijn Torrents' bekijken progress.window.title=Bewerking in uitvoering! progress.window.msg.filemove=A.u.b. wacht even tot de file verplaatst of verwijderd is ConfigView.label.popup.timestamp=Plaats een tijdsduur voor popup meldingen ConfigView.label.popup.autohide=Automatisch verstoppen van niet-error popup waarschuwingen na x seconden.\n (Zet op 0 voor uitzetten automatisch verstoppen) ConfigView.label.popup.suppress_alerts=Onderdruk waarschuwingen ConfigView.label.popup.use_message_boxes=Gebruik popup bericht boxen eerder dan de standaard popup waarschuwings box. ConfigView.label.popup.show=Toon alle popup meldingen die tot nu gelogt zijn (als deze er zijn) ConfigView.label.popup.show.button=Toon ConfigView.label.please.visit.here=A.u.b. bezoek deze site voor details (link). ConfigView.section.ipfilter.enable.descriptionCache=Opslaan IP beschrijvingen in scratch file (tijdelijke bestand). ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Wanneer uitgezet, zullen de beschrijvingen niet onthouden worden. OpenTorrentWindow.filesInfo=%1 van %2 zal gedownload worden. OpenTorrentWindow.diskUsage=%1 van %2 ConfigView.label.openmytorrents=Open 'Mijn Torrents' bij opstarten. ConfigView.label.open_transfer_bar_on_start=Open de overdracht balk met opstarten. ConfigView.section.style.DNDalwaysInIncomplete=Altijd de torrents met de status 'Niet downloaden' laten zien in de "niet compleet"deel van Mijn Torrents scherm (download). OpenTorrentWindow.mb.noGlobalDestDir.title=Bestemming Directorie niet gevonden. OpenTorrentWindow.mb.noGlobalDestDir.text=De bestemming directorie '%1' bestaat niet of is niet beschikbaar. OpenTorrentWindow.mb.noDestDir.title=Bestemming Directorie niet gevonden. OpenTorrentWindow.mb.noDestDir.text=De bestemming directorie '%1' voor torrent '%2' bestaat niet of is niet beschikbaar. OpenTorrentWindow.mb.notValid.title=Openen Torrent OpenTorrentWindow.mb.notValid.text=Kon torrent '%1' niet openen. Als je deze in de seeding mode wil openen, wees dan zeker dat de data file bestaat. OpenTorrentWindow.mb.notTorrent.text=Niet te openen '%1'. Waarscheinlijk geen .torrent file.\n\nGedeeltelijke data ontvangen:\n%2 ConfigView.label.pause.downloads.on.exit=Pauzeer downloads bij eindigen programma. ConfigView.label.resume.downloads.on.start=Hervat gepauzeerde downloads bij opstarten, na dat de initialisatie compleet is. UIDebugGenerator.message.cancel.title=Generatie Debug Info Geannuleerd UIDebugGenerator.message.cancel.text=U heeft geen omschrijving van de bug gegeven welke u wil raporteren, de bug mag dan voor u duidelijk zijn maar wij kunnen hier niets mee zonder een duidelijken omschrijving en moeten dan maar raden naar het probleem.\n\nGeneratie van de Debug Informatie is geannuleerd. ConfigView.section.connection.group.http.info=Ondersteuning voor HTTP seeding. ConfigView.section.connection.http.enable=Toestaan ConfigView.section.connection.http.port=Inkomende poort nummer ConfigView.section.connection.http.portoverride=Tracker HTTP Poort overschrijving [0: geen] window.update.noupdates.title=Resultaten voor controle op een nieuwe versie. window.update.noupdates.text=Er is geen nieuwen versie beschikbaar voor u.\n\nOns gelukwensen, u heeft de laatste versie! ConfigView.label.bindip.details=Voorbeeld: 192.168.1.5;eth0;eth1[2] verbind het gespecificeerde IP adres, naar alle IPs van de 1st interface en de 3de IP van de 2de interface.\nHet 1st IP adres zal gebruikt worden voor alle services, alle anderen worden alleen gebruikt om de balans te houden.\n\nDe volgende interfaces zijn beschikbaar:\n%1 ConfigView.label.mindownloads=Min gelijktijdigen downloads UI.cannot_submit_blank_text=U moet een waarde opgeven. crypto.alert.as.warning=Het Netwerk '%1' is bekent voor het afdwingen van vermindering van de download prestatie. Transport Encrytion is automatisch aan gezet, dit kan uit gezet of gemodificeerd worden via de configuratie instellingen. ConfigView.section.interface.alerts=Waarschuwingen. ConfigView.label.popupdownloadadded=Popup een waarschuwing als een download is geplaatst. popup.download.added="%1" is geplaatst in jouw download lijst. MessageBoxWindow.nomoreprompting=Waarschuw mij niet meer! TorrentOptionsView.param.max.seeds=Maximum nummer of seed connecties [0: connectie limit] TorrentOptionsView.param.alternative.value.enable=Alternatieve waarde wanneer seeding. ConfigView.section.proxy.check.on.start=Controleer proxy status bij opstarten. TransferStatsView.legend.pingaverage=Gemiddeld TransferStatsView.legend.ping1=Doel 1 TransferStatsView.legend.ping2=Doel 2 TransferStatsView.legend.ping3=Doel 3 ConfigView.section.interface.enabletray._mac=Gebruk Status Bar Icon [herstart benodigt] ConfigView.label.closetotray._mac=Sluiten minimaliceert naar Status Bar Icon ConfigView.label.minimizetotray._mac=Minimaliseer minimaliseert naar Status Bar Icon OpenTorrentWindow.mb.existingFiles.title=File(s) is/zijn al aanwezig! OpenTorrentWindow.mb.existingFiles.text=Enkel van de bestanden bestaan reeds in de bestemmings directorie (s) die je gespecificeerd hebt:\n\n%1\nals je door gaat, zal Vuze de bovenstaande controleren of de data juist is en deze overschrijven als het nodig is. splash.unloadingTorrents=Uitschakelen Torrents splash.unloadingTorrent=Uitschakelen Torrent ConfigView.section.file.defaultdir.autorename=Auto hernoem torrent gegevens als bestanden in het path verschillend lijken te zijn. ConfigView.section.file.defaultdir.autorename.tooltip=Dit voorkomt een torent van overschreven worden door een anderen torrent's files wanneer de file namen het zelfde zijn. alert.raised.at.close=(Bericht van vorigen sluiten van Vuze) Plugin.trackerpeerauth.name=Tracker Peer Autorisatie Plugin.trackerpeerauth.info=Deze plugin werk met trackers om te controleren dat peers geldigen zwerm leden zijn. Peers.column.maxupspeed=Max Up Snelheid Peers.column.maxdownspeed=Max Down Snelheid MyTorrents.items.DownSpeedLimit.disabled=Geen download upnp.selectedaddresses=Adressen (';' gescheinden, '-' prefix=niet toestaan, '+' =toestaan) [blank: elken] upnp.alert.multipledevice.warning=Multiple UPnP devices zijn gedetecteerd - controleer of alle benodigde poorten geopend zijn (bekijk de UPnP log en configuratie) UpdateMonitor.messagebox.restart.text=Vuze downloadende juist een belangrijke update en moet nu worden herstart zodat de update kan worden geinstalleerd. PiecesView.BlockView.Have=Heeft PiecesView.BlockView.NoHave=Heeft niet PiecesView.BlockView.Header=%1 kolom(men), %2 rij(en), %3 stukjes ConfigView.section.update.autodownload=Auto download updates en prompt wanneer de installatie klaar is Peers.column.peer_id.info=Peer ID in leesbaar formaat Peers.column.peer_byte_id=Peerbits ID Peers.column.peer_byte_id.info=Peer ID in byte formaat Peers.column.handshake_reserved=Handshake Gereserveerde Bytes Peers.column.handshake_reserved.info=Indiceerd welke gereserveerde bits zijn ingesteld in de BT handshake Peers.column.client_identification=Client Identificatie Peers.column.client_identification.info=Indiceerd de ruwen client namen ontvangen door Vuze - nuttig voor debugging dht.warn.user=Waarschuwing voor potentieel NAT/poort mapping problemen ConfigView.label.openbar.incomplete=Download bars: auto openen downloads ConfigView.label.openbar.complete=auto openen seeds ConfigView.label.transferbar.remember_location=Onthoud de laatste locatie van de overdrachts balk. ConfigView.section.transfer.autospeed.forcemin=%1 upload snelheid geforceerd met analiceren van de verbinding. MainWindow.menu.tools.speedtest=Snelheids test... speedtest.wizard.title=Snelheid Test speedtest.wizard.run=Start een snelheids test. speedtest.wizard.test.mode.updown=upload en download SpeedTestWizard.test.panel.currinfo=BitTorrent bandbreedte testen. SpeedTestWizard.test.panel.label=Vuze snelheids test: SpeedTestWizard.test.panel.already.running=Test is al bezig! SpeedTestWizard.test.panel.not.accepted=Test verzoek niet geaccepteerd: SpeedTestWizard.test.panel.abort=Afbreken SpeedTestWizard.test.panel.abort.countdown=afbreken test in: SpeedTestWizard.test.panel.test.countdown=test gereed in: SpeedTestWizard.test.panel.testfailed=Test mislukt SpeedTestWizard.test.panel.aborted=Test handmatig afgebroken. SpeedTestWizard.test.panel.enc.label=Klik om te testen met encryptie: SpeedTestWizard.test.panel.standard=standaard SpeedTestWizard.set.upload.button.apply=Toevoegen SpeedTestWizard.set.upload.result=Laatste test resultaten SpeedTestWizard.finish.panel.title=Snelheids test gereed! SpeedTestWizard.finish.panel.click.close=De snelheids test wizard is gereed. Klik op Voltooien om te stoppen. SpeedTestWizard.finish.panel.max.seeding.upload=Max upload tijdens seeding : SpeedTestWizard.finish.panel.enabled=ingeschakeld SpeedTestWizard.finish.panel.disabled=uitgeschakeld SpeedTestWizard.abort.message.scheduled.in=test gepland in ... %1 seconde" SpeedTestWizard.abort.message.unsupported.type=Niet ondersteund test type!!!! SpeedTestWizard.abort.message.manual.abort=Handmatig gestopt SpeedTestWizard.abort.message.scheduling.failed=Scheduling van de test is mislukt SpeedTestWizard.abort.message.download.added=Download %1 geplaatst tijdens de test SpeedTestWizard.abort.message.entered.error=Test download aangegeven fout status '%1' SpeedTestWizard.abort.message.entered.queued=Test aangegeven gedownloade klaar/gestopte status SpeedTestWizard.abort.message.interrupted=Torrent snelheids test monitor bewerking was onderbroken voor de test compleet was. SpeedTestWizard.abort.message.execution.failed=Test uitvoering mislukt SpeedTestWizard.abort.message.failed.peers=Verbinding mislukt naar peers SpeedTestWizard.abort.message.insufficient.slots=Kon niet uploaden naar peers - onvoldoende upload slots? SpeedTestWizard.abort.message.not.unchoked=Kon niet downloaden van peers alsof zij de verbinding nooit unchoked hebben gemaakt. SpeedTestWizard.stage.message.requesting=verzoeken om een test... SpeedTestWizard.stage.message.preparing=voorbereiden test... SpeedTestWizard.stage.message.starting=starten test... SpeedTestWizard.stage.message.connect.stats=Connectie status: peers=%1, down_ok=%2, up_ok=%3 window.uiswitcher.title=Vuze UI Kiezer window.uiswitcher.text=Selecteer de gewenste gebruikersinterface (UI). window.uiswitcher.NewUI.text=* Aanbevolen voor beginners en nieuwen gebruikers.\n\n* Een makelijk, intiutief grafisch uiterlijk.\n\n* Vereiste uiterlijk voor het publiceren op het Vuze platform. window.uiswitcher.ClassicUI.title=Klassiek uiterlijk window.uiswitcher.ClassicUI.text=* Behoud de functionaliteit van de 2.x versies.\n\n* Vuze skin word niet geladen. window.uiswitcher.bottom.text=U kunt later opnieuw met de UI Kiezer eenvoudig uw keuze wijzigen. iconBar.switch.tooltip=Vuze UI Kiezer VivaldiView.notAvailable=Vivaldi bekijken niet beschikbaar restart.error=Herstart mislukt:\n%1\nZie herstarten onderdeel. restart.error.oom=Tewijnig geheugen restart.error.fnf='%1' niet gevonden in '%2' restart.error.pnf=Path '%1' niet gevonden restart.error.bad=Slechte file formaatvoor '%1' restart.error.denied=Toegang geblokkeerd met opstarten van '%1'. Je moet de rechten hebben om dit programma te gebruiken. TableColumn.header.date_completed=Compleet op TableColumn.menu.date_added.reset=Herstel datum ConfigView.section.ipfilter.discardbanning=Blokkeer peers wie verworpen data/goede data ratio overtreft [0: uitgezet] ConfigView.section.ipfilter.discardminkb=Minimum %1 verworpen voor geldende ratio ConfigView.interface.start.advanced=Start in Geavanceerde beeld (AZ 2.x) MyTorrents.column.ColumnQuality=Kwaliteit MyTorrents.column.ColumnSpeed=Snelheid MyTorrents.column.ColumnProgressETA.StreamReady=Streaming Gereed %1 MyTorrents.column.ColumnProgressETA.PlayableIn=Speelbaar in %1 %2 TableColumn.header.Quality=Kwaliteit TableColumn.header.Speed=Snelheid TableColumn.header.RateIt=Waardering TableColumn.header.Rating=Waarderen TableColumn.header.SpeedGraphic=Snelheid TableColumn.header.AzProduct=Van TableColumn.header.ProgressETA=Voortgang #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.browse=Browse Inhoud v3.MainWindow.tab.library=Mijn Bibliotheek v3.MainWindow.tab.publish=Publiceer v3.MainWindow.tab.advanced=geavanceerd v3.MainWindow.menu.browse=&Browse de Inhoud v3.MainWindow.menu.library=Mijn &Bibliotheek v3.MainWindow.menu.publish=&Publiceer v3.MainWindow.menu.advanced=&Geavanceerd v3.MainWindow.menu.view.searchbar=Zoek balk v3.MainWindow.menu.view.tabbar=Tab Balk v3.MainWindow.currentDL=Momenteel Downloaden v3.MainWindow.button.pause=Pauze v3.MainWindow.button.resume=Opnieuw v3.MainWindow.button.delete=Verwijder v3.MainWindow.button.comment=Commentaar v3.MainWindow.button.viewdetails=Bekijk Details v3.MainWindow.button.play=Speel v3.MainWindow.button.cancel=Afbreken v3.MainWindow.view.wait=Initialicering voor tonen, momentje. v3.MainWindow.xofx=%1 van %2 v3.MainWindow.Loading=Laden. Momentje graag. v3.filter-bar=Titel Filter: v3.MainWindow.search.defaultText=Zoek Vuze v3.mb.delPublished.title=Stop met uploaden van de inhoud v3.mb.delPublished.text=WAARSCHUWING: Deze actie zal niet de gepubliceerde inhoud '%1' verwijderen van %3 \n\nKlik "Verwijderen" alleen als de gepubliceerde inhoud beschikbaar moet blijven voor downloaden, maar wel bandbreedte vrij wil maken. Zorg wel dat de uploads goed afgesloten zijn voordat je deze verwerking doorvoerd. (how?).\n\nKlik "Annuleer" als je de complete gepubliceerde inhoud wil verwijderen van www.GetVuze, en gebruik de (X) knop op het Gepubliceerde Inhoud Paneel in de publiceer tab.\n\nMeer hulp.\n\n v3.mb.delPublished.delete=&Verwijder v3.mb.delPublished.cancel=&Annuleer v3.mb.PlayFileNotFound.title=Bestand Niet Gevonden v3.mb.PlayFileNotFound.text=De files voor '%1' zijn verwijder of vermist. v3.mb.PlayFileNotFound.button.remove=Verwijder uit Vuze v3.mb.PlayFileNotFound.button.redownload=Herdownload de data. v3.mb.PlayFileNotFound.button.find=Handmatig zoeken v3.mb.deletePurchased.title=Verwijder de verkregen inhoud v3.mb.deletePurchased.text=Ben je zeker dat je deze inhoud '%1' wilt verwijderen?\n\nDeze heb je nog niet verkregen, je moet misschien inloggen om te kunnen downloaden. v3.mb.deletePurchased.button.delete=&Verwijder v3.mb.deletePurchased.button.cancel=&Annuleer v3.topbar.menu.show.plugin=Plugin Gebied v3.topbar.menu.show.search=Zoek splash.initializeCore=Initialiseren Core splash.initializeUIElements=Initialiseren UI Elementen ConfigView.section.transfer.autospeedbeta=Auto-Snelheid-Beta # ConfigView.section.ipfilter.peerblocking.group=Peer Blokkeren ConfigView.section.ipfilter.autoload.group=Automatisch laden ConfigView.section.ipfilter.autoload.file=IP filter file voor autoload ConfigView.section.ipfilter.autoload.info=Ondersteund DAT (eMule), P2P (PeerGardian, splist), en P2B v1,2,3 (Peer Gardian 2) formaten. File kan zijn lokaal of URL, zip'd, gzip'd of gewoon tekst. URLs zal automatisch her-downloaden na 7 dagen, waar files zullen worden her-laden binnen een minuut of her-plaatst. ConfigView.section.ipfilter.autoload.loadnow=Nu laden splash.loadIpFilters=Laden van IP Filters.. SpeedTestWizard.set.upload.title=Stel Upload en Download grens in. SpeedTestWizard.set.download.label=Aangeraadde Download Snelheid lemiet: SpeedTestWizard.set.upload.label=Upload snelheid grens: SpeedTestWizard.name.conf.level.absolute=Onbegrensd SpeedTestWizard.name.conf.level.high=Hoog SpeedTestWizard.name.conf.level.med=Gemiddeld SpeedTestWizard.name.conf.level.low=Laag SpeedTestWizard.name.conf.level.none=Geen ConfigView.section.transfer.select=Auto snelheid ConfigView.section.transfer.select.v2=Vuze snelheid opnamen (beta) mb.azmustclose.title=Opstart fout mb.azmustclose.text=Vuze moet stoppen door een probleem (her)Starten van azureus veroorzaakte dat azureus als Administrator opgestart is.\n\nNadat Vuze gesloten is, deze handmatig her-openen. network.ipv6.prefer.addresses=Prefereer IPV6 adressen wanneer zowel IPV6 als IPV4 beschikbaar zijn network.enforce.ipbinding=Forceer IP verbindingen zelfs wanneer er geen interfaces beschikbaar zijn, voorkom elke verbinding wanneer geen gespecificeerde verbindingen beschikbaar zijn. DHTView.title.full_v6=Gedistribueerde database IPv6 ConfigView.pluginlist.loadSelected=Laad geselecteerde SpeedView.stats.asn=Netwerk: SpeedView.stats.estupcap=Upload limiet: SpeedView.stats.estdowncap=Download limiet: SpeedView.stats.unknown=Onbekend SpeedView.stats.estimate=Getaxeerd SpeedView.stats.measured=Gemeten SpeedView.stats.measuredmin=Gemeten Min SpeedView.stats.manual=Vastgesteld ConfigView.section.transfer.autospeed.networks=Netwerk Details ConfigView.section.transfer.autospeed.resetnetwork=Herstel netwerk details ConfigView.section.transfer.autospeed.network.info=De boven staande limieten worden gewoon automatisch tijdens de overdracht uitgerekend of zijn het resultaat van een snelheid test.\nAls je deze handmatig wil specificeren gebruik dan de optie hieronder.\nAlle limieten anders dan 'vastgesteld' zullen nadien automatisch bijgesteld worden als dit nodig is. \nGeef een waarde en selecteer het type. Onthoud dat de snelheden in %1 zijn.\n dialog.uiswitcher.restart.title=UI Kiezer: Herstart Vuze Vereist dialog.uiswitcher.restart.text=Een herstart is vereist om te kunnen overgaan naar de nieuwe gebruikersinterface. TrayWindow.menu.close=Sluit de Download Mand # Used for peers which we can't determine. PeerSocket.unknown=Onbekend PeerSocket.fake_client=VERVALSING PeerSocket.bad_peer_id=slechte peer ID PeerSocket.mismatch_id=onjuist PeerSocket.unknown_az_style=Onbekende (client-code: %1, versie: %2) PeerSocket.unknown_shadow_style=Onbekend %1/%2 OpenTorrentWindow.mb.askCreateDir.title=Bestemming Directorie bestaat niet OpenTorrentWindow.mb.askCreateDir.text=De bestemmings directorie '%1' bestaat niet.\n\nDeze aanmaken? SpeedView.stats.estimatechoke=Schatting (choke) ConfigTransferAutoSpeed.upload.capacity.usage=Upload Capaciteit Gebruikt ConfigTransferAutoSpeed.capacity.used=% Capaciteit Gebruikt ConfigTransferAutoSpeed.while.downloading=Downloaden: ConfigTransferAutoSpeed.set.dht.ping=DHT Ping Instelling: ConfigTransferAutoSpeed.set.point=Stel punt (ms) ConfigTransferAutoSpeed.set.tolerance=tolerantie (ms) ConfigTransferAutoSpeed.ping.time.good=Goed: ConfigTransferAutoSpeed.ping.time.bad=Slecht: ConfigTransferAutoSpeed.adjustment.interval=Instelling interval: ConfigTransferAutoSpeed.skip.after.adjust=Overspringen na instellingen: GeneralView.label.distributedCopies=Gedistribueerde kopie\u00ebn: PiecesView.DistributionView.title=Stukjes distributie PiecesView.DistributionView.NoAvl=Niet beschikbaren stukjes PiecesView.DistributionView.SeedAvl=Seed Avl bijdrage PiecesView.DistributionView.PeerAvl=Peer Avl bijdrage PiecesView.DistributionView.RarestAvl=Ongewoonste stukjes: %1 (Avl:%2) PiecesView.DistributionView.weHave=Stukjes die je hebt. PiecesView.DistributionView.theyHave=Stukjes die de peer heeft PiecesView.DistributionView.weDownload=Stukjes die je gedownload hebt. PeersView.gain=Resultaat PeersView.gain.info=Som van gedownloade - geuploade data. unix.script.new.title=Nieuw Vuze Opstart Script beschikbaar unix.script.new.text=Een nieuw Vuze opstart script is beschikbaar, en is opgeslagen naar '%1'.\n\nHet is zeer aanbevolen dat je Vuze stopt en over gaat naar dit script ('%2').\n\nAls je jou Vuze opstart script erg hebt aangepast, kijk dan a.u.b. eens hier bij VuzeWiki: Unix Script (Engels).\n\nAls je Vuze hebt geinstalleerd van een distro (yum, apt-get, etc), is het aanbevolen deze opnieuw te installeren, gebruik makend van het pakket op Vuze' Sourceforge Page (Je krijgt dan de zelfde UI die je nu ook gebruikt). unix.script.new.button.quit=Stop nu unix.script.new.button.continue=Ik doe het later unix.script.new.button.asknomore=Vertel het mij niet meer unix.script.new.auto.title=Nieuw Vuze Opstart Script unix.script.new.auto.text=Een nieuw Vuze Opstart Script is beschikbaar.\n\nHet is zeer aanbevolen dat je nu Vuze herstart. Content.alert.notuploaded.button.continue=&Doorgaan met Uploaden Content.alert.notuploaded.button.abort=&Niet stoppen ConfigView.label.checkOnSeeding=Gebruik een lage hulpbron bij hercontrole van stukjes bij het seeden. ConfigView.label.ui_switcher=Toon UI schakelaar ConfigView.label.ui_switcher_button=Toon SpeedTestWizard.test.panel.explain=Meet de upload en download snelheid met het BT protocol. Selecteer de type snelheids test en de encryptie mode. Klik dan op de Uitvoeren knop om te beginnen. Als de test bezig is, kun je deze onderbreken door op de Afbreken knop te klikken. De test stopt automatisch als het langer duurt als twee minuten. Een normalen test stopt binnen een minuut. Wanneer de test gereed is word er een upload snelheid aan geraden, wil je deze gebruiken, klik dan op Volgende. SpeedTestWizard.set.upload.hint=Stel de upload en download beperkingen in, word gebruikt door Vuze Speedsense algoritme welken momenteel in b\u00e8ta is. SpeedTestWizard.set.upload.panel.explain=Om de beste prestatie van Vuze te krijgen, is het aangeraden de upload grens op 80% in te stellen van de beschikbaren maxium.\n\nNote: dat de lijn snelheid vaak wordt aangegeven in "bits per seconden" - hoewel de waarde hier onder is weergegeven in "kilobytes per seconden". SpeedTestWizard.set.limit.conf.level=Vertrouwens niveau SpeedTestWizard.finish.panel.auto.speed=Auto snelheid is : SpeedTestWizard.finish.panel.auto.speed.seeding=Auto snelheid tijdens seeding is : ConfigTransferAutoSpeed.add.comment.to.log.group=Plaats commentaar naar de debug log ConfigTransferAutoSpeed.add.comment.to.log=Plaats commentaar: ConfigTransferAutoSpeed.algorithm.selector=Auto-Snelheid selector ConfigTransferAutoSpeed.algorithm=Algorithme: ConfigTransferAutoSpeed.auto.speed.classic=Auto-Snelheid(classic) ConfigTransferAutoSpeed.auto.speed.beta=Auto-Snelheid(beta) ConfigTransferAutoSpeed.data.update.frequency=Update Frequentie Alert.failed.update=Installatie van minstens \u00e9\u00e9n component mislukt. Bekijk VuzeWiki: Failed Update OpenTorrentWindow.mb.existingFiles.partialList=(Gedeeltelijken lijst. Meer files bestaan reeds) TableColumn.header.bad_avail_time.info=Laatst keer dat een volledigen kopie van de download beschikbaar was TableColumn.header.bad_avail_time=Volledigen Kopie Gezien MyTorrentsView.menu.exporthttpseeds=Export HTTP seed URLs naar het clipboard SWT.alert.erroringuithread=Een onbekende fout verscheen in de GUI,meerderen fouten kunnen geraporteerd worden. ConfigView.label.minannounce=Minimum tijd tussen tracker announces in seconden ConfigView.label.maxnumwant=Limiteer de nummers van peers welke de tracker terug mag sturen. ConfigView.label.announceport=Vervang tracker announce-poort ConfigView.label.noportannounce=Announce de luister poort niet naar de tracker (heeft geen effect op pex, dht) ConfigView.label.maxseedspertorrent=Max seeds per torrent standaard [0: ongelimiteerd] wizard.webseed=Plaats HTTP Seeds naar de torrent wizard.webseed.configuration=HTTP Seed Configuratie wizard.webseed.adding=Plaatsen HTTP Seeds GeneralView.label.private=Priv\u00e8 Torrent: GeneralView.yes=ja GeneralView.no=nee ConfigView.label.userequestlimiting=Gebruik het verzoek tot vermindering inplaats van vertraagd lezen voor het limiteren van de download snelheid [heeft geen effect wanneer de download snelheid ongelimiteerd is] ConfigView.label.userequestlimiting.tooltip=Verzoek tot limiteren is niet zo stabiel als vertraagd lezen,maar is toegestaan voor download volgorde van prioriteit gebaseerd op de wachtrij positie en kan de netwerk prestatie verbeteren. ConfigView.label.userequestlimitingpriorities=Focus download snelheid op de bovenkant van de downloadrij wanneer de download snelheid limit is berijkt. ConfigView.section.logging.timestamp=Tijdindeling formaat voor log files Peers.column.timetocomplete=Tijd nog tegaan Peers.column.timetocomplete.info=Tijd nog tegaan tot dat de peer compleet is. ConfigView.section.interface.display.suppress.file.download.dialog=Onderdruk File Download popup dialoog ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Toon alle file download vorderingen in de status bar inplaats van een popup dialoog FileDownload.canceled=Een torrent file download is succesvol geannuleerd door gebruikers actie: %1 Progress.reporting.status.canceled=Geannuleerd Progress.reporting.status.finished=Gereed Progress.reporting.status.retrying=Opnieuw proberen... Progress.reporting.action.label.retry.tooltip=Bewerking opnieuw proberen. Progress.reporting.action.label.remove.tooltip=Verwijder dit Voortgangs Raport van de historie. Progress.reporting.action.label.cancel.tooltip=Annuleer de bewerking. Progress.reporting.default.error=Gevaald Progress.reporting.no.reports.to.display=Er zijn geen Voortgangs Raportages om te laten zien op het moment. Progress.reporting.no.history.to.display=Er zijn geen detail berichten om te laten zien. Progress.reporting.detail.history.limit=Het detail bericht limit (%1) voor de Voortgangs Raporteerder is overschreden; volgende detail berichten zullen niet in de historie lijst geplaatst worden. Progress.reporting.statusbar.button.tooltip=Toon het Voortgangs Raportage scherm webui.bindip=Kopel IP - normaal niet nodig (*) v3.MainWindow.text.log.in=Log In v3.MainWindow.text.log.out=Log uit v3.MainWindow.text.get.started=Nu Beginnen v3.MainWindow.text.my.account=Mijn Account OpenTorrentWindow.simple.open=Torrent Locatie (File, URL, Hash) Progress.reporting.window.remove.auto=Automatisch verwijderen van de in-active onderdelen. Progress.reporting.window.remove.auto.tooltip=Automatisch verwijderen van alle completen, mislukten of afgebroken processen van dit scherm. Progress.reporting.window.remove.now=Verwijder in-active onderdelen. Progress.reporting.window.remove.now.tooltip=Verwijder alle completen, mislukten of afgebroken processen van dit scherm. dhttracker.tracklimitedwhenonline=Nochtans, voer laag gebruik van resource tracking uit, bij een online zwerm cross-population. TorrentOptionsView.multi.title.short=Torrent Opties TorrentOptionsView.multi.title.full=Torrent Opties MyTorrentsView.menu.open_parent_folder=Open inhoud map ConfigView.section.style.use_show_parent_folder=Gebruik "%1" inplaats van "%2" in torrent menus ConfigView.section.style.use_show_parent_folder.tooltip=Aanzetten van deze optie zal je toestaan om de bewaar map te openen met de juiste file manager applicatie.\nHoewel, het zo kan zijn dat de opslag lokatie niet automatisch word geselecteerd. PeerManager.status.ps_disabled=Tracker peer source is uitgezet. ConfigView.section.stats.exportfiles=Exporteer file details updater.cant.write.to.app.title=Kan niet naar de programma map schrijven. updater.cant.write.to.app.details=De map "%1" is niet beschrijfbaar.\n\nDit zal voorkomen dat toekomstigen update`s kunnen worden toegevoegd.\n\nA.U.B. Lees de wikivoor details (Engels). plugin.install.class_version_error=Deze plugin heeft een nieuweren Java versie nodig om te werken. v3.MainWindow.tab.events=Activiteit button.columnsetup.tooltip=Kolom instelling v3.activity.remove.title=Verwijder de activiteit gegevens v3.activity.remove.text=Weet je zeker dat je de activiteit evenement '%1' verwijderen wil? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=Sluit Menu.show.torrent.menu=Toon het torrents besturings menu Menu.show.torrent.menu.tooltip=Toon torrent besturings menu in de boven balk. #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=Netwerk Status plugin.aznetstatus.pingtarget=Ping/traceren trac\u00e9 doel ConfigView.section.style.usePathFinder=Gebruik 'Directories zoeken' inplaats van 'zoeken' menu.sortByColumn=Gesoorteerd op %1 MyTorrentsView.menu.manual.per_peer=Handmatig (per peer) MyTorrentsView.menu.manual.shared_peers=Handmatig (meerderen peers) v3.button.removeActivityEntry=Verwijder activiteit specificatie v3.splash.initSkin=Initialiseren UI Skin v3.splash.hookPluginUI=Inhaken op de Plugin UI OpenTorrentWindow.mb.notTorrent.cannot.display=Onmogelijk om de date te tonen. MainWindow.menu.window.zoom.maximize=Maximaliseer MainWindow.menu.window.zoom.restore=Herstellen ImageResizer.image.too.small=De aangegeven image is teklein, a.u.b. kies een anderen (het minimalen formaat moet zijn %1 x %2 ImageResizer.title=Dit stukje gereedschap laat de thumbnail zien zoals deze op het Vuze Platform geplaats worden. ImageResizer.move.image=Verplaats de image door deze te slepen ImageResizer.move.image.with.slider=Verplaats de image door deze te slepen, voor verschalen gebruik de schuifregelaar hier onder security.crypto.title=Encryptie Key Toegang security.crypto.encrypt=Plaats het wachtwoord voor het beschermen van de nieuw gemaakte encryption key. Vergeet dit wachtwoord niet, er is geen mannier om dit terug te halen wanneer dit wel gebeurt! security.crypto.decrypt=Geef het wachtwoord voor het unlocken van de encryption key. security.crypto.reason=Reden voor bewerking security.crypto.password=Wachtwoord security.crypto.password2=Nogmaals het wachtwoord security.crypto.persist_for=Wachtwoord onthoud periode security.crypto.persist_for.dont_save=NIET opslaan security.crypto.persist_for.session=Deze sessie security.crypto.persist_for.day=1 dag security.crypto.persist_for.30days=30 dagen security.crypto.persist_for.forever=Vooraltijd security.crypto.password.mismatch.title=Wachtwoord Fout security.crypto.password.mismatch=Wachtwoord waarde welke geplaatst is komt niet overeen, plaats hem opnieuw. ConfigView.section.security.group.crypto=Publiek of priv\u00e9 Keys ConfigView.section.security.resetkey=Herstel keys ConfigView.section.security.resetkey.warning.title=Data Verlies Waarschuwing ConfigView.section.security.resetkey.warning=Weet je zeker dat je de encryption keys wil terugstellen/-zetten? Wanneer je dit gedaan hebt, zal alle informatie welke encryptie was voorgoed verloren zijn! Ook kunnen peers wie in het bezit zijn van jou public key, dan niet langer met jou computer communiseren tot dat zij een nieuwen key hebben van jou. Dus als je niet weet wat je eigenlijk doet, doe dit dan niet. ConfigView.section.security.unlockkey="Nadrukkelijk" unlock de keys ConfigView.section.security.publickey=Publiek key ConfigView.section.security.publickey.undef=Nog niet gedefini\u00eberd ConfigView.section.security.resetkey.error.title=Bewerking mislukt ConfigView.section.security.resetkey.error=Herstellen van de keys mislukt ConfigView.section.security.unlockkey.error=Unlock key is mislukt - wachtwoord incorrect ConfigView.copy.to.clipboard.tooltip=kopi\u00ebr naar het clipboard Views.plugins.azbuddy.title=Vrienden Browser.popup.error.no.access=Er is een fout opgetreden tijden het contact maken met een anderen bron.\nProbeer het later nog eens ! ConfigView.label.queue.stoponcebandwidthmet=Start geen torrents wanneer de upload/download snelheids limit is berijkt ConfigView.section.style.forceMozilla=Dwing Vuze voor het gebruiken van Mozilla voor Browser inschakeling [xulrunner of firefox 3 nodig; Vuze herstarten vereist] ConfigView.section.style.xulRunnerPath=Specificeer de XulRunner / Firefox map handmatig [vereist voor FF3; Vuze herstart vereist] azbuddy.name=Vrienden azbuddy.enabled=Ingeschakeld azbuddy.disabled=Plugin is uitgeschakeld, bekijk de plugin config voor veranderen. azbuddy.nickname=Jou Nickname azbuddy.msglog.title=Vriend Informatie azbuddy.addtorrent.title=Accepteren Download? azbuddy.addtorrent.msg=Jou vriend '%1' heeft je gezonden '%2'.\nWil je deze download plaatsen? azbuddy.contextmenu=Verzend naar je vriend azbuddy.ui.mykey=Mijn key: azbuddy.ui.add=Plaats azbuddy.ui.new_buddy=Nieuwen vriend key: azbuddy.ui.table.name=Naam azbuddy.ui.table.last_msg=Laaste bericht azbuddy.ui.menu.remove=Verwijder azbuddy.ui.menu.copypk=Kopi\u00ebr Public Key azbuddy.ui.menu.send=Zend bericht azbuddy.ui.menu.send_msg=Plaats de tekst voor verzenden naar je vriend(en) azbuddy.ui.menu.ygm=Zend YGM azbuddy.ui.menu.sign=Onderteken Clipboard azbuddy.ui.menu.verify=Verifi\u00ebr Clipboard azbuddy.ui.table.lastseen=Laatst gezien Button.retry=&Opnieuw Button.ignore=&Negeer v3.MainWindow.menu.view.footer=Vrienden balk azbuddy.downspeed=KB/s max vriend download snelheid [0: onbeperkt] security.crypto.badpw=Het opgegeven password is niet juist ConfigView.section.security.backupkeys=Backup keys naar een file ConfigView.section.security.restorekeys=Restore keys van een file ConfigView.section.security.op.error.title=Bewerking mislukt ConfigView.section.security.op.error=Mislukt om de bewerking af temaken: %1 ConfigView.section.security.restart.title=Herstart Vereist ConfigView.section.security.restart.msg=Vuze zal nu herstarten om de bewerking compleet te maken. ConfigView.section.security.system.managed=Systeem beheerde key bescherming azbuddy.ui.table.msg_queued=In rij azbuddy.chat.says=%1 zegt: Button.bar.show=Toon Button.bar.hide=Verberg Button.bar.share=Deel Button.bar.add=Plaats Vrienden Button.bar.edit=Bewerk Button.bar.edit.cancel=Klaar met bewerken v3.MainWindow.menu.view.pluginbar=Plugin balk MainWindow.dialog.select.vuze.file=Selecteer Vuze File metasearch.addtemplate.title=Installeer Zoek Template? metasearch.addtemplate.desc=Weet je zeker dat je de zoek template met de naam '%1' wil installeren? v3.share.private.title=Delen Torrent v3.share.private.text=De geselecteerde torrent is gemarkeerd als een prive torrent.\n\nJe kunt geen prive torrents delen. metasearch.addtemplate.dup.desc=Zoek template %1 is al geinstalleerd metasearch.export.select.template.file=Opslaan Template dialog.uiswitch.title=Schakel naar de Vuze UI dialog.uiswitch.text=Je moet de Vuze UI gebruiker om gebruik te kunnen maken van deze mogelijkheid. dialog.uiswitch.button=Schakel naar de Vuze UI azbuddy.tracker.enabled=Geef prioriteit aan vrienden met het downloaden van de zelfde inhoud azbuddy.protocolspeed=KB/s max vriend protocol overhead v3.MainWindow.button.run=Start gedownloaden file iconBar.queue.tooltip=Wachtrij MainWindow.menu.help.faq=Vaak gestelde vragen MainWindow.menu.help.donate=Geef een donatie !!! azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_ru_RU.properties0000644000175000017500000210315511301156004026132 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=\u0422\u043e\u0440\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b... Main.parameter.usage=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435: java org.gudy.azureus2.cl.Main [\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b] "\u0444\u0430\u0439\u043b.torrent" "\u043f\u0443\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f" Main.parameter.maxUploads=\u041c\u0430\u043a\u0441. \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0440\u0430\u0437\u0434\u0430\u0447 Main.parameter.maxSpeed=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438, \u0411/\u0441 MainWindow.menu.file=&\u0424\u0430\u0439\u043b MainWindow.menu.file.open=&\u041e\u0442\u043a\u0440\u044b\u0442\u044c MainWindow.menu.file.create=&\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442... MainWindow.menu.file.create.fromfile=\u0438\u0437 &\u0444\u0430\u0439\u043b\u0430 MainWindow.menu.file.create.fromdir=\u0418\u0437 &\u043f\u0430\u043f\u043a\u0438 MainWindow.menu.file.export=&\u042d\u043a\u0441\u043f\u043e\u0440\u0442 XML \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430... MainWindow.menu.file.import=\u0418\u043c\u043f\u043e\u0440\u0442 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 MainWindow.menu.file.closetab=\u0417\u0430\u043a\u0440\u044b\u0442\u044c &\u0432\u043a\u043b\u0430\u0434\u043a\u0443 MainWindow.menu.file.closewindow=\u0417\u0430\u043a\u0440\u044b\u0442\u044c &\u043e\u043a\u043d\u043e MainWindow.menu.file.exit=\u0412&\u044b\u0445\u043e\u0434 MainWindow.dialog.choose.file=\u0412\u044b\u0431\u043e\u0440 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 MainWindow.menu.file.folder=\u041f\u0430\u043f\u043a\u0430 MainWindow.dialog.choose.folder=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0443 \u0441 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430\u043c\u0438 MainWindow.menu.view=&\u0412\u0438\u0434 MainWindow.menu.view.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c MainWindow.menu.view.mytorrents=&\u041c\u043e\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b MainWindow.menu.view.open_global_transfer_bar=\u0421\u043a\u0440\u0438\u043d\u043b\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a MainWindow.menu.view.configuration=&\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438... MainWindow.menu.view.console=&\u041a\u043e\u043d\u0441\u043e\u043b\u044c MainWindow.menu.view.allpeers=\u0412\u0441\u0435 \u0443\u0437\u043b\u044b MainWindow.menu.view.detailedlist=&\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a MainWindow.menu.closealldetails=\u0417\u0430\u043a\u0440\u044b\u0442\u044c &\u0432\u0441\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 MainWindow.menu.closealldownloadbars=\u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0432\u0441\u0435 \u0441&\u043a\u0440\u0438\u043d\u043b\u0435\u0442\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a MainWindow.menu.language=&\u042f\u0437\u044b\u043a ConfigView.section.language=\u042f\u0437\u044b\u043a MainWindow.menu.window=&\u041e\u043a\u043d\u043e MainWindow.menu.window.minimize=&\u0421\u0432\u0435\u0440\u043d\u0443\u0442\u044c MainWindow.menu.window.zoom=&\u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c MainWindow.menu.window.alltofront=&\u041f\u043e\u0432\u0435\u0440\u0445 \u0432\u0441\u0435\u0445 \u043e\u043a\u043e\u043d MainWindow.menu.help=&\u0421\u043f\u0440\u0430\u0432\u043a\u0430 MainWindow.menu.help.about=\u041e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435 Vuze MainWindow.menu.torrent=\u0422\u043e&\u0440\u0440\u0435\u043d\u0442 MainWindow.about.title=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f MainWindow.about.section.developers=\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 MainWindow.about.section.translators=\u041f\u0435\u0440\u0435\u0432\u043e\u0434\u0447\u0438\u043a\u0438 MainWindow.about.section.system=\u0421\u0438\u0441\u0442\u0435\u043c\u0430 MainWindow.about.section.internet=\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 MainWindow.about.internet.homepage=\u0414\u043e\u043c\u0430\u0448\u043d\u044f\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 Vuze MainWindow.about.internet.sourceforge=\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 Sourceforge MainWindow.about.internet.sourceforgedownloads=\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0441 Sourceforge MainWindow.about.internet.bugreports=\u0421\u043e\u043e\u0431\u0449\u0438\u0442\u044c \u043e \u043e\u0448\u0438\u0431\u043a\u0435 MainWindow.about.internet.forumdiscussion=\u041e\u0431\u0449\u0438\u0439 \u0444\u043e\u0440\u0443\u043c MainWindow.about.internet.wiki=\u0427\u0430\u0441\u0442\u043e \u0437\u0430\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043d\u0430 \u0412\u0438\u043a\u0438 Vuze MainWindow.dialog.choose.savepath=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0443 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f MainWindow.dialog.choose.savepath_forallfiles=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u0449\u0443\u044e \u043f\u0430\u043f\u043a\u0443 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f MainWindow.status.latestversion=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0432\u0435\u0440\u0441\u0438\u044f MainWindow.status.latestversion.clickupdate=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c MainWindow.status.unknown=\u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e MainWindow.status.checking=\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 MyTorrentsView.mytorrents=M\u043e\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b TableColumn.header.name=\u0418\u043c\u044f TableColumn.header.size=\u0420\u0430\u0437\u043c\u0435\u0440 TableColumn.header.done=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e TableColumn.header.done.info=\u041f\u0440\u043e\u0446\u0435\u043d\u0442 \u0433\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 TableColumn.header.status=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 TableColumn.header.status.info=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 TableColumn.header.seeds=\u0420\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 TableColumn.header.seeds.info=\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u043c (\u043e\u0431\u0449\u0435\u0435 \u0447\u0438\u0441\u043b\u043e \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445) TableColumn.header.peers=\u0423\u0437\u043b\u043e\u0432 TableColumn.header.peers.info=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u043e\u0432 (\u0438\u0445 \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e) TableColumn.header.completed=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e TableColumn.header.completed.info=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u0437\u043b\u043e\u0432, \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0432\u0448\u0438\u0445 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u043f\u043e \u0434\u0430\u043d\u043d\u044b\u043c \u0442\u0440\u0435\u043a\u0435\u0440\u0430 TableColumn.header.downspeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 TableColumn.header.upspeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 TableColumn.header.eta=\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c TableColumn.header.tracker=\u0422\u0440\u0435\u043a\u0435\u0440 TableColumn.header.tracker.info=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 TableColumn.header.trackernextaccess=\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 TableColumn.header.trackernextaccess.info=\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 TableColumn.header.priority=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 TableColumn.header.priority.info=\u0427\u0430\u0441\u0442\u044c \u043f\u043e\u043b\u043e\u0441\u044b \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c\u0443 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0443 \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 TableColumn.header.seeds.fullcopycalc=%2 \u043f\u043e\u043b\u043d\u044b\u0445 \u043a\u043e\u043f\u0438\u0439 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0443 %1 \u0443\u0437\u043b\u043e\u0432 MyTorrentsView.menu.showdetails=\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 MyTorrentsView.menu.showdownloadbar=\u0421&\u043a\u0440\u0438\u043d\u043b\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 MyTorrentsView.menu.open=&\u041e\u0442\u043a\u0440\u044b\u0442\u044c MyTorrentsView.menu.setpriority=\u0417\u0430\u0434\u0430\u0442\u044c &\u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 MyTorrentsView.menu.setpriority.high=&\u0412\u044b\u0441\u043e\u043a\u0438\u0439 MyTorrentsView.menu.setpriority.low=&\u041d\u0438\u0437\u043a\u0438\u0439 MyTorrentsView.menu.start=&\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c MyTorrentsView.menu.stop=\u041e&\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c MyTorrentsView.menu.remove=&\u0423\u0434\u0430\u043b\u0438\u0442\u044c MyTorrentsView.menu.changeTracker=&\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c URL \u0442\u0440\u0435\u043a\u0435\u0440\u0430 TrayWindow.menu.exit=\u0412\u044b\u0439\u0442\u0438 TrayWindow.menu.show=&\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c Vuze SystemTray.menu.exit=\u0412&\u044b\u0445\u043e\u0434 SystemTray.menu.closealldownloadbars=\u0417\u0430\u043a\u0440\u044b\u0442\u044c &\u0432\u0441\u0435 \u0441\u043a\u0440\u0438\u043d\u043b\u0435\u0442\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a SystemTray.menu.open_global_transfer_bar=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043e\u043a\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a SystemTray.menu.show=&\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c Vuze PeersView.ip.info=IP \u0443\u0437\u043b\u0430 PeersView.port=\u041f\u043e\u0440\u0442 PeersView.port.info=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043f\u043e\u0440\u0442 PeersView.T=\u0422 PeersView.T.info=L (local): \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435, R (remote): \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0443\u0437\u043b\u0430. PeersView.T.L.tooltip=\u0418\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 PeersView.T.R.tooltip=\u0412\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 PeersView.I1=\u0418 (\u044f \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d) PeersView.I1.info=\u042f \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d \u0432 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u043c\u0435\u044e\u0449\u0438\u0445\u0441\u044f \u0443 \u0443\u0437\u043b\u0430 PeersView.C1=C (\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u043c) PeersView.C1.info=\u0420\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0439 \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u043b \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0441 \u0432\u0430\u0448\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b PeersView.pieces=\u0427\u0430\u0441\u0442\u0438 PeersView.downloadspeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 PeersView.download=\u041f\u0440\u0438\u043d\u044f\u0442\u043e PeersView.I2=\u0418 (\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0435\u043d \u0443\u0437\u043b\u0443) PeersView.I2.info=\u0423\u0437\u0435\u043b \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d \u0432 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u043c\u0435\u044e\u0449\u0438\u0445\u0441\u044f \u0443 \u043c\u0435\u043d\u044f PeersView.C2=C (\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d) PeersView.C2.info=\u0423\u0437\u043b\u0443 \u0431\u044b\u043b\u043e \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u043e \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 PeersView.uploadspeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 PeersView.uploadspeed.info=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0443\u0437\u043b\u0443 PeersView.upload=\u0420\u043e\u0437\u0434\u0430\u043d\u043e PeersView.upload.info=\u0412\u0430\u043c\u0438 \u0440\u043e\u0437\u0434\u0430\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e. PeersView.statup=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 PeersView.statup.info=\u041f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0443\u0437\u043b\u0430 PeersView.S=\u0411 PeersView.S.info=\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430: \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0451\u043d \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0438\u043b\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 (\u0437\u0430 \u0440\u0430\u0437\u0434\u0430\u0447\u0443 \u043d\u0430 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043d\u0438\u0437\u043a\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438) PeersView.downloadspeedoverall=\u041e\u0431\u0449\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 PeersView.optunchoke=\u0420\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c PeersView.client=\u041a\u043b\u0438\u0435\u043d\u0442 PeersView.client.info=\u0422\u0438\u043f BitTorrent-\u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0443\u0437\u043b\u043e\u043c PeersView.menu.snubbed=\u041f\u043e\u043c\u0435\u0447\u0435\u043d PeersView.title.short=\u0423\u0437\u043b\u044b PeersView.title.full=\u0423\u0437\u043b\u044b AllPeersView.title.full=\u0412\u0441\u0435 \u0443\u0437\u043b\u044b ConfigView.section.files=\u0424\u0430\u0439\u043b\u044b ConfigView.label.usefastresume=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u00ab\u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f\u00bb ConfigView.label.incrementalfile=\u0418\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 [\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f FAT32 \u0432 Linux] ConfigView.label.defaultsavepath=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 ConfigView.button.browse=&\u041e\u0431\u0437\u043e\u0440... ConfigView.dialog.choosedefaultsavepath=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u0441\u0435\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 ConfigView.section.server=\u0421\u0435\u0440\u0432\u0435\u0440 ConfigView.section.global=\u041e\u0431\u0449\u0435\u0435 ConfigView.label.disconnetseed=\u041e\u0442\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.label.switchpriority=\u0421\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.label.maxdownloads=\u041c\u0430\u043a\u0441. \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e]\n - \u041d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 ConfigView.label.maxdownloads.tooltip=\u0412\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441 \u043e\u0434\u043d\u0438\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c.\n\u0421\u043a\u0430\u0447\u0430\u043d\u043d\u044b\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u0441 \u0432\u044b\u0441\u0448\u0438\u043c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u043b\u043e\u0442 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u0434\u043e\u0431\u043d\u043e\u0441\u0442\u0438. ConfigView.label.maxactivetorrents=\u041c\u0430\u043a\u0441. \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e]\n - \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u043b\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0430 \u043d\u043e\u0432\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u043d\u0435 \u043d\u0430\u0447\u043d\u0451\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 \u043f\u0440\u0435\u0432\u044b\u0448\u0435\u043d \u044d\u0442\u043e\u0442 \u043f\u0440\u0435\u0434\u0435\u043b ConfigView.label.priorityExtensions=\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0432\u044b\u0441\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 \n (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u00ab.jpg;.txt;.nfo\u00bb) ConfigView.section.transfer=\u041e\u0431\u043c\u0435\u043d \u0434\u0430\u043d\u043d\u044b\u043c\u0438 ConfigView.label.maxuploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.label.maxuploadspeed=\u041a\u0411/\u0441 \u043c\u0430\u043a\u0441. \u043e\u0431\u0449\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.label.saveresumeinterval=\u0417\u0430\u043f\u0438\u0441\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u00ab\u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f\u00bb \u043a\u0430\u0436\u0434\u044b\u0435 ConfigView.unlimited=\u0411\u0435\u0437 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f ConfigView.section.display=\u0412\u043d\u0435\u0448\u043d\u0438\u0439 \u0432\u0438\u0434 ConfigView.label.opendetails=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0441 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438 ConfigView.label.openbar=\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043f\u0430\u043d\u0435\u043b\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 ConfigView.label.use_old_speed_menus=\u041f\u0440\u0435\u0436\u043d\u0438\u0439 \u0434\u0438\u0437\u0430\u0439\u043d \u043c\u0435\u043d\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 [\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a] ConfigView.label.closetotray=\u041f\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 \u0441\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 ConfigView.label.minimizetotray=\u0421\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 ConfigView.section.general=\u041e\u0431\u0449\u0435\u0435 ConfigView.section.start=\u0417\u0430\u043f\u0443\u0441\u043a ConfigView.label.showsplash=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0443 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 ConfigView.label.autoupdate=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0434\u0438\u0430\u043b\u043e\u0433 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b ConfigView.label.openconsole=\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 ConfigView.label.openconfig=\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 ConfigView.label.startminimized=\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432 \u0441\u0432\u0451\u0440\u043d\u0443\u0442\u043e\u043c \u0432\u0438\u0434\u0435 ConfigView.label.ircwiki=\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c\u0438 \u043d\u0430 http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=\u0421\u0435\u0440\u0432\u0435\u0440 ConfigView.label.ircchannel=\u041a\u043e\u043c\u043d\u0430\u0442\u0430 ConfigView.label.irclogin=\u041f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c ConfigView.group.irctitle=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 IRC ConfigView.boolean.ircsendinfo=\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043f\u043e\u0441\u044b\u043b\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Vuze (\u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e),\n\u0447\u0442\u043e\u0431\u044b \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u043c\u043e\u0433\u043b\u0438 \u0432\u0430\u043c \u043f\u043e\u043c\u043e\u0447\u044c ConfigView.boolean.irclog=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 IRC (\u0432 \u0444\u0430\u0439\u043b IRC_log.htm) ConfigView.section.security=\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c ConfigView.label.password=\u0417\u0430\u0449\u0438\u0442\u0438\u0442\u044c Vuze \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0430\u0440\u043e\u043b\u044f\n\u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0438\u043b\u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u043e\u043a\u043d\u0430 \u0438\u0437 \u0437\u043d\u0430\u0447\u043a\u0430. ConfigView.label.passwordconfirm=\u041f\u0430\u0440\u043e\u043b\u044c (\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435) ConfigView.label.passwordmatch=\u041f\u0430\u0440\u043e\u043b\u044c \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d: ConfigView.label.passwordmatchnone=\u041d\u0435\u0442 ConfigView.label.passwordmatchno=\u041d\u0435\u0442 / \u043f\u0430\u0440\u043e\u043b\u0438 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 ConfigView.label.passwordmatchyes=\u0414\u0430 ConfigView.button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c ConfigView.title.short=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 ConfigView.title.full=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 ConfigView.title.full._mac=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b ConsoleView.title.short=\u041a\u043e\u043d\u0441\u043e\u043b\u044c ConsoleView.title.full=\u041a\u043e\u043d\u0441\u043e\u043b\u044c FileItem.write=\u0437\u0430\u043f\u0438\u0441\u044c FileItem.read=\u0447\u0442\u0435\u043d\u0438\u0435 FileItem.normal=\u0421\u0440\u0435\u0434\u043d\u0438\u0439 FileItem.high=\u0412\u044b\u0441\u043e\u043a\u0438\u0439 FileItem.donotdownload=\u041d\u0435 \u0433\u0440\u0443\u0437\u0438\u0442\u044c FileItem.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c FilesView.name=\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 FilesView.name.fastRename=\u0411\u044b\u0441\u0442\u0440\u043e\u0435 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 FilesView.size=\u0420\u0430\u0437\u043c\u0435\u0440 FilesView.done=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e FilesView.firstpiece=\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c FilesView.numberofpieces=\u0427\u0430\u0441\u0442\u0435\u0439 FilesView.pieces=\u0427\u0430\u0441\u0442\u0438 FilesView.mode=\u0420\u0435\u0436\u0438\u043c FilesView.priority=\u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 FilesView.menu.open=&\u041e\u0442\u043a\u0440\u044b\u0442\u044c FilesView.menu.setpriority=\u0417\u0430\u0434\u0430\u0442\u044c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 FilesView.menu.setpriority.high=&\u0412\u044b\u0441\u043e\u043a\u0438\u0439 FilesView.menu.setpriority.normal=&\u0421\u0440\u0435\u0434\u043d\u0438\u0439 FilesView.menu.setpriority.skipped=&\u041d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c FilesView.title.short=\u0424\u0430\u0439\u043b\u044b FilesView.title.full=\u0424\u0430\u0439\u043b\u044b GeneralView.section.downloaded=\u0417\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043e GeneralView.label.status.file=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 GeneralView.label.status.pieces=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0447\u0430\u0441\u0442\u0435\u0439 GeneralView.section.availability=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c GeneralView.label.status.pieces_available=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0447\u0430\u0441\u0442\u0435\u0439 GeneralView.section.transfer=\u041e\u0431\u043c\u0435\u043d \u0434\u0430\u043d\u043d\u044b\u043c\u0438 GeneralView.section.info=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f GeneralView.title.short=\u041e\u0431\u0449\u0435\u0435 GeneralView.title.full=\u041e\u0431\u0449\u0435\u0435 GeneralView.label.timeelapsed=\u041f\u0440\u043e\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438: GeneralView.label.remaining=\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c: GeneralView.label.downloaded=\u041f\u0440\u0438\u043d\u044f\u0442\u043e: GeneralView.label.downloadspeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430: GeneralView.label.maxuploads=\u0421\u043b\u043e\u0442\u044b \u0440\u0430\u0437\u0434\u0430\u0447\u0438: GeneralView.label.maxuploads.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u0437\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e. GeneralView.label.uploaded=\u0420\u043e\u0437\u0434\u0430\u043d\u043e: GeneralView.label.uploadspeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438: GeneralView.label.seeds=\u0420\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445: GeneralView.label.peers=\u0423\u0437\u043b\u043e\u0432: GeneralView.label.completed=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e: GeneralView.label.totalspeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f: GeneralView.label.totalspeed.tooltip=\u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0430\u044f (\u0438 \u0441\u0440\u0435\u0434\u043d\u044f\u044f) \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0441\u0435\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432. GeneralView.label.averagespeed=\u0432 \u0441\u0440\u0435\u0434\u043d\u0435\u043c GeneralView.label.filename=\u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430: GeneralView.label.totalsize=\u041e\u0431\u0449\u0438\u0439 \u0440\u0430\u0437\u043c\u0435\u0440: GeneralView.label.savein=\u0421\u043e\u0445\u0440\u0430\u043d\u0451\u043d \u0432: GeneralView.label.hash=\u0425\u0435\u0448: GeneralView.label.numberofpieces=\u0427\u0430\u0441\u0442\u0435\u0439: GeneralView.label.size=\u0420\u0430\u0437\u043c\u0435\u0440: GeneralView.label.tracker=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u0430: GeneralView.label.updatein=\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437: GeneralView.label.trackerurl=URL \u0442\u0440\u0435\u043a\u0435\u0440\u0430: GeneralView.label.trackerurlupdate=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441 GeneralView.label.comment=\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u0434\u043b\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430: GeneralView.label.user_comment=\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f: GeneralView.label.status=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435: ManagerItem.waiting=\u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 ManagerItem.allocating=\u0412\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0441\u0442\u0430 ManagerItem.checking=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 ManagerItem.ready=\u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430(\u043e\u0432) \u0432 \u041e\u0447\u0435\u0440\u0435\u0434\u0438 ManagerItem.downloading=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 ManagerItem.seeding=\u0420\u0430\u0437\u0434\u0430\u0447\u0430 ManagerItem.stopped=\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d ManagerItem.error=o\u0448\u0438\u0431\u043a\u0430 ManagerItem.high=\u0432\u044b\u0441\u043e\u043a\u0438\u0439 ManagerItem.low=\u043d\u0438\u0437\u043a\u0438\u0439 MinimizedWindow.name=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435: MinimizedWindow.all_transfers=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0438 Vuze PiecesView.size=\u0420\u0430\u0437\u043c\u0435\u0440 PiecesView.numberofblocks=\u0411\u043b\u043e\u043a\u043e\u0432 PiecesView.blocks=\u0411\u043b\u043e\u043a\u0438 PiecesView.completed=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430 PiecesView.availability=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c PiecesView.reservedby=\u0417\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043e\u0432\u0430\u043d PiecesView.writers=\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 PiecesView.title.short=\u0427\u0430\u0441\u0442\u0438 PiecesView.title.full=\u0427\u0430\u0441\u0442\u0438 SystemTray.tooltip.seeding=%1 \u0440\u0430\u0437\u0434\u0430\u0451\u0442\u0441\u044f, SystemTray.tooltip.downloading=%1 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f, DownloadManager.error.filenotfound=\u0424\u0430\u0439\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d DownloadManager.error.fileempty=\u041f\u0443\u0441\u0442\u043e\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 DownloadManager.error.filetoobig=Torrent \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u043e\u0439 DownloadManager.error.filewithouttorrentinfo=\u041d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442-\u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 DownloadManager.error.unsupportedencoding=\u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f DownloadManager.error.ioerror=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 DownloadManager.error.sha1="\u0410\u043b\u0433o\u0440\u0438\u0442\u043c (SHA1) \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d"- \u041e\u0448\u0438\u0431\u043a\u0430 PeerManager.status.offline=\u041e\u0448\u0438\u0431\u043a\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f PeerManager.status.checking=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 PeerManager.status.finished=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e PeerManager.status.finishedin=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e \u0437\u0430 MainWindow.upgrade.assistant=\u041c\u0430\u0441\u0442\u0435\u0440 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f MainWindow.upgrade.newerversion=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c? MainWindow.upgrade.explanation=Vuze \u0441\u043a\u0430\u0447\u0430\u0435\u0442\u0441\u044f \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f MainWindow.upgrade.explanation.manual=\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e: \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0441\u043a\u0430\u0447\u0430\u0432 \u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0432 Vuze MainWindow.upgrade.step1=\u0428\u0430\u0433 1: \u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e MainWindow.upgrade.step2=\u0428\u0430\u0433 2: \u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 Vuze MainWindow.upgrade.hint1=\u0421\u043e\u0432\u0435\u0442:\t\u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0432\u0441\u0451 \u0431\u0443\u0434\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 MainWindow.upgrade.hint2=\u0421\u043e\u0432\u0435\u0442:\t\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u044c Vuze \u043f\u043e\u0437\u0436\u0435, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u00ab\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c\u00bb \u0438\n\t\u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0439\u0442\u0435 \u0444\u0430\u0439\u043b Azureus2-new.jar \u0432 Azureus2.jar \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b MainWindow.upgrade.error.downloading.hint=\u041e\u0448\u0438\u0431\u043a\u0430:\t\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0432\u0440\u0443\u0447\u043d\u0443\u044e MainWindow.upgrade.section.info=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f MainWindow.upgrade.section.manual=\u0412\u0440\u0443\u0447\u043d\u0443\u044e MainWindow.upgrade.section.automatic=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 MainWindow.upgrade.tooltip.progressbar=\u041f\u0440\u043e\u0433\u0440\u0435\u0441\u0441 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u0442\u0443\u0442 Button.next=\u0414\u0430\u043b\u0435\u0435 Button.finish=\u0413\u043e\u0442\u043e\u0432\u043e Button.cancel=\u041e&\u0442\u043c\u0435\u043d\u0438\u0442\u044c LocaleUtil.title=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0443 LocaleUtil.section.chooseencoding=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0443 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0430 LocaleUtil.label.chooseencoding=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0430\u043c\u0443\u044e \u043b\u0443\u0447\u0448\u0443\u044e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0443 LocaleUtil.label.hint.doubleclick=\u0441\u043e\u0432\u0435\u0442: \u0434\u0432\u043e\u0439\u043d\u043e\u0439 \u043a\u043b\u0438\u043a \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0443 \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0434\u0438\u0430\u043b\u043e\u0433 LocaleUtil.label.checkbox.rememberdecision=\u0417\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u0432\u044b\u0431\u043e\u0440 \u0434\u043b\u044f \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 LocaleUtil.column.encoding=\u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 IrcClient.copyright=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a IrcClient.connected=\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0451\u043d \u043a IrcClient.joining=\u0412\u0445\u043e\u0434 \u0432 IrcClient.channel=\u041a\u043e\u043c\u043d\u0430\u0442\u0430 IrcClient.joined=\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 IrcClient.error=\u041e\u0448\u0438\u0431\u043a\u0430 IrcClient.hasjoined=\u0432\u043e\u0448\u0451\u043b \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 IrcClient.haskicked=\u0432\u044b\u0433\u043d\u0430\u043b IrcClient.hasleft=\u0432\u044b\u0448\u0435\u043b \u0438\u0437 \u043a\u043e\u043c\u043d\u0430\u0442\u044b IrcClient.nowknown=\u0442\u0435\u043f\u0435\u0440\u044c \u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d \u043a\u0430\u043a IrcClient.topicforchannel=\u0422\u0435\u043c\u0430 \u043a\u043e\u043c\u043d\u0430\u0442\u044b IrcClient.disconnected=\u041e\u0442\u043a\u043b\u044e\u0447\u0451\u043d \u043e\u0442 IrcClient.noNick=\u0412\u044b \u0437\u0430\u0431\u044b\u043b\u0438 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c. \u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043e\u043a\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0438 \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u0435\u0433\u043e IrcView.actionnotsupported=\u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f IrcView.clientsconnected=\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 IrcView.privateto=\u041a IrcView.privatefrom=\u041e\u0442 IrcView.noticefrom=\u0417\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u0435: IrcView.errormsg=\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0432 /msg: \u00ab/msg \u0432\u0430\u0448 \u0442\u0435\u043a\u0441\u0442\u00bb IrcView.help=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:\n/help: \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0442\u0435\u043a\u0441\u0442\n/nick | /name: \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c\n/me \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435: \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u0435\n/msg \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435: \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043b\u0438\u0447\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\n/r \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435: \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u043b\u0438\u0447\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\n/join #\u043a\u043e\u043c\u043d\u0430\u0442\u0430: \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u0434\u0440\u0443\u0433\u0443\u044e \u043a\u043e\u043c\u043d\u0430\u0442\u0443 PasswordWindow.title=Vuze \u0437\u0430\u0449\u0438\u0449\u0451\u043d \u043f\u0430\u0440\u043e\u043b\u0435\u043c PasswordWindow.passwordprotected=Vuze \u0437\u0430\u0449\u0438\u0449\u0451\u043d \u043f\u0430\u0440\u043e\u043b\u0435\u043c.\n\u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043e\u043a\u043d\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c: TrackerChangerWindow.title=\u0417\u0430\u043c\u0435\u043d\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 TrackerChangerWindow.newtracker=\u0417\u0430\u0434\u0430\u0442\u044c URL \u043d\u043e\u0432\u043e\u0433\u043e \u0442\u0440\u0435\u043a\u0435\u0440\u0430 PeersView.discarded=\u041e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u043e PeersView.discarded.info=\u0414\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0431\u044b\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u044b, \u043d\u043e \u0431\u044b\u043b\u0438 \u043a\u0430\u043a\u0438\u043c-\u043b\u0438\u0431\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b, \u0438 \u0431\u044b\u043b\u0438 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u044b discarded=\u043e\u0442\u0431\u0440\u043e\u0448\u0435\u043d\u043e MyTorrentsView.#=\u2116 MyTorrentsView.menu.move=\u041f\u0435\u0440\u0435&\u043c\u0435\u0441\u0442\u0438\u0442\u044c MyTorrentsView.menu.moveUp=&\u0412\u0432\u0435\u0440\u0445 MyTorrentsView.menu.moveDown=&\u0412\u043d\u0438\u0437 GeneralView.label.hashfails=\u041d\u0435\u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0439 \u0445\u0435\u0448\u0430: GeneralView.label.shareRatio=\u0420\u0435\u0439\u0442\u0438\u043d\u0433: ConfigView.section.downloadManagement=\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430\u043c\u0438 ConfigView.label.startRatioPeers=\u041d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0443 \u043f\u0440\u0438 \u043c\u0435\u043d\u0435\u0435 \u0447\u0435\u043c 1 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0435\u043c ConfigView.text.neverStop=\u041d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c ConfigView.text.neverStart=\u041d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c ConfigView.text.peers=\u0443\u0437\u043b\u043e\u0432 ConfigView.label.checkOncompletion=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0447\u0430\u0441\u0442\u0438 \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 wizard.title=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 wizard.previous=< \u041d\u0430\u0437\u0430\u0434 wizard.next=\u0414\u0430\u043b\u0435\u0435 > wizard.finish=\u0413\u043e\u0442\u043e\u0432\u043e wizard.mode=\u0422\u0440\u0435\u043a\u0435\u0440 / \u0420\u0435\u0436\u0438\u043c wizard.tracker=\u0422\u0440\u0435\u043a\u0435\u0440: wizard.invalidurl=\u041e\u0448\u0438\u0431\u043e\u0447\u043d\u0430\u044f URL wizard.singlefile=\u041e\u0434\u0438\u043d \u0444\u0430\u0439\u043b wizard.singlefile.help=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 wizard.directory=\u041f\u0430\u043f\u043a\u0430 wizard.directory.help=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 wizard.choosefile=\u0412\u044b\u0431\u043e\u0440 \u0444\u0430\u0439\u043b\u0430 wizard.file=\u0424\u0430\u0439\u043b: wizard.browse=\u041e\u0431\u0437\u043e\u0440... wizard.choosedirectory=\u0412\u044b\u0431\u043e\u0440 \u043f\u0430\u043f\u043a\u0438 wizard.invalidfile=\u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u0444\u0430\u0439\u043b! wizard.invaliddirectory=\u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0430\u044f \u043f\u0430\u043f\u043a\u0430! wizard.torrentFile=\u0424\u0430\u0439\u043b \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 wizard.choosetorrent=\u0412\u044b\u0431\u043e\u0440 torrent-\u0424\u0430\u0439\u043b\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f wizard.information=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f wizard.notimplemented=\u0412 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 wizard.progresstitle=\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 wizard.savingfile=\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430... wizard.filesaved=\u0424\u0430\u0439\u043b \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d. wizard.close=\u0417\u0430\u043a\u0440\u044b\u0442\u044c Torrent.create.progress.piecelength=\u0414\u043b\u0438\u043d\u0430 \u0447\u0430\u0441\u0442\u0438: Torrent.create.progress.piececount=\u041a\u043e\u043b-\u0432\u043e \u0447\u0430\u0441\u0442\u0435\u0439: Torrent.create.progress.totalfilesize=\u041e\u0431\u0449\u0438\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430: Torrent.create.progress.totalfilecount=\u0412\u0441\u0435\u0433\u043e \u0444\u0430\u0439\u043b\u043e\u0432: Torrent.create.progress.parsingfiles=\u041f\u0430\u0440\u0441\u0438\u043d\u0433 \u0444\u0430\u0439\u043b\u0430 Torrent.create.progress.hashing=\u0425\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 MainWindow.upgrade.downloadingfrom=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441: MainWindow.menu.view.ipFilter=\u0424\u0438\u043b\u044c\u0442\u0440\u044b &IP ConfigView.section.ipfilter=\u0424\u0438\u043b\u044c\u0442\u0440\u044b IP ConfigView.section.ipfilter.description=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 ConfigView.section.ipfilter.start=\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 IP ConfigView.section.ipfilter.end=\u041a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 IP ConfigView.section.ipfilter.add=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c ConfigView.section.ipfilter.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c ConfigView.section.ipfilter.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c ConfigView.section.ipfilter.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c ConfigView.section.ipfilter.editFilter=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430 ConfigView.section.ipfilter.enable=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c PeersView.menu.close=&\u0417\u0430\u043a\u0440\u044b\u0442\u044c seedmore.title=\u0420\u0430\u0437\u0434\u0430\u0447\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0430 seedmore.shareratio=\u0412\u0430\u0448\u0435 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u044d\u0442\u043e\u0433\u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 seedmore.uploadmore=\u0421\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 <1 \u043f\u043b\u043e\u0445\u043e \u043e\u0442\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0442\u0438 BitTorrent.\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u043d\u0430\u0434\u043e\u043b\u0433\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0443. ConfigView.label.showpopuponclose=\u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0441 \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u043e\u043c <1 ConfigView.label.startNumSeeds=\n\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0443 \u043f\u0440\u0438 \u043c\u0435\u043d\u0435\u0435 \u0447\u0435\u043c\n - \u0412\u0441\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f ConfigView.label.seeds=\u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 ConfigView.section.seeding=\u0420\u0430\u0437\u0434\u0430\u0447\u0430 MyTorrentsView.menu.removeand=\u0423&\u0434\u0430\u043b\u0438\u0442\u044c \u0438 MyTorrentsView.menu.removeand.deletetorrent=\u0423\u0434\u0430\u043b\u0438\u0442\u044c &\u0442\u043e\u0440\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b MyTorrentsView.menu.removeand.deletedata=\u0423\u0434\u0430\u043b\u0438\u0442\u044c &\u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b MyTorrentsView.menu.removeand.deleteboth=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u0441&\u0451 deletedata.title=\u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435 deletedata.message1=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u00ab%1\u00bb \u0431\u0435\u0437\u0432\u043e\u0437\u0432\u0440\u0430\u0442\u043d\u043e? deletedata.noprompt=\u041d\u0435 \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0441\u043d\u043e\u0432\u0430 MainWindow.menu.file.configure=\u041c\u0430\u0441\u0442\u0435\u0440 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a configureWizard.title=\u041c\u0430\u0441\u0442\u0435\u0440 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a configureWizard.welcome.title=\u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u0432 \u043c\u0430\u0441\u0442\u0435\u0440 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a Vuze configureWizard.welcome.message=\u042d\u0442\u043e\u0442 \u043c\u0430\u0441\u0442\u0435\u0440 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c Vuze \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u0414\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0442\u043e\u043d\u043a\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u043c\u0435\u043d\u044e \u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b/\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. configureWizard.transfer.title=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043e\u0431\u043c\u0435\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 configureWizard.transfer.hint=\u0417\u0430\u043c\u0435\u0442\u044c\u0442\u0435: \t\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044c\u0448\u0435\u0439 \u0432\u0430\u0448\u0435\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f configureWizard.transfer.message=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043d\u0438\u0436\u0435. \u0423\u0447\u0442\u0438\u0442\u0435, \u0447\u0442\u043e \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043d\u0438\u0437\u043a\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u043c\u043e\u0436\u0435\u0442 \u0441\u043d\u0438\u0437\u0438\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430. \u0422\u0430\u043a \u043a\u0430\u043a \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430\u043c, \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043f\u0430\u0434\u0435\u043d\u0438\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043f\u0440\u0438\u0451\u043c\u0430. \u041d\u0430\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 5 \u041a\u0411/\u0441 \u043d\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442. \u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0430, \u0442\u0435\u043c \u0432\u044b\u0448\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430. configureWizard.transfer.connection=\u0421\u0432\u044f\u0437\u044c configureWizard.transfer.connection.0=\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f configureWizard.transfer.connection.1=\u043c\u043e\u0434\u0435\u043c configureWizard.transfer.connection.2=ADSL/\u041a\u0430\u0431\u0435\u043b\u044c xxx/128 \u041a\u0431\u0438\u0442/\u0441 configureWizard.transfer.connection.3=ADSL/\u041a\u0430\u0431\u0435\u043b\u044c xxx/256 \u041a\u0431\u0438\u0442/\u0441 configureWizard.transfer.connection.4=ADSL/\u041a\u0430\u0431\u0435\u043b\u044c xxx/384 \u041a\u0431\u0438\u0442/\u0441 configureWizard.transfer.connection.5=ADSL/\u041a\u0430\u0431\u0435\u043b\u044c xxx/512 \u041a\u0431\u0438\u0442/\u0441 configureWizard.transfer.connection.6=ADSL/\u041a\u0430\u0431\u0435\u043b\u044c xxx/768 \u041a\u0431\u0438\u0442/\u0441 configureWizard.transfer.connection.7=ADSL/\u041a\u0430\u0431\u0435\u043b\u044c xxx/1024 \u041a\u0431\u0438\u0442/\u0441 configureWizard.transfer.maxUpSpeed=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 (\u041a\u0411/\u0441) configureWizard.transfer.maxActiveTorrents=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 configureWizard.transfer.maxDownloads=\u041c\u0430\u043a\u0441. \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a configureWizard.transfer.maxUploadsPerTorrent=\u041c\u0430\u043a\u0441. \u0440\u0430\u0437\u0434\u0430\u0447 \u043d\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 configureWizard.nat.title=NAT / \u043f\u043e\u0440\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 configureWizard.nat.message=\u0414\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 BitTorrent \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0443. \u042d\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0438, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e, \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043f\u043e\u0440\u0442\u044b.\n\n\u0417\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043f\u043e\u0440\u0442\u043e\u0432 TCP. \u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u0411\u0414 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u043f\u043e\u0440\u0442\u043e\u0432 UDP, \u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u0438\u0442, \u0435\u0441\u043b\u0438 \u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u044d\u043a\u0440\u0430\u043d.\n\n\u0417\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u043f\u043e\u0440\u0442 TCP 6880 \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043e\u0439 \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d. configureWizard.nat.test=\u0422\u0435\u0441\u0442 configureWizard.nat.testing=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u0440\u0442\u0430 configureWizard.nat.ok=OK! configureWizard.nat.ko=\u041e\u0448\u0438\u0431\u043a\u0430 NAT configureWizard.nat.unable=\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e: \u0443\u043a\u0430\u0437\u0430\u043d \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043f\u043e\u0440\u0442 \u0438\u043b\u0438 \u0441\u043b\u0443\u0436\u0431\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435 \u0441\u043c\u043e\u0433\u043b\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441.\n\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0440\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043e\u0439. configureWizard.file.title=\u0422\u043e\u0440\u0440\u0435\u043d\u0442\u044b / \u0444\u0430\u0439\u043b\u044b configureWizard.file.message1=\u0417\u0430\u043f\u0438\u0441\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0432 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435. \u0412\u044b\u0431\u043e\u0440: configureWizard.file.path=\u041f\u0430\u043f\u043a\u0430 configureWizard.file.browse=\u041e\u0431\u0437\u043e\u0440 configureWizard.file.message2=Vuze \u0438\u043c\u0435\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0434\u043e\u0431\u0430\u0432\u043a\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a \u0432\u0430\u0448\u0438\u043c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430\u043c. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u043f\u0440\u0438\u0451\u043c \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u0435\u0439. configureWizard.file.fastResume=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u00ab\u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e\u00bb \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f configureWizard.file.invalidPath=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430\u044f \u043f\u0430\u043f\u043a\u0430 configureWizard.finish.title=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e configureWizard.finish.message=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u0430. \u0416\u0435\u043b\u0430\u0435\u043c \u0432\u0430\u043c \u0443\u0434\u0430\u0447\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0432\u0440\u0435\u043c\u044f! wizard.close.confirmation=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 wizard.close.message=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043c\u0430\u0441\u0442\u0435\u0440 \u043f\u0440\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b? exportTorrentWizard.title=\u042d\u043a\u0441\u043f\u043e\u0440\u0442 XML \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 exportTorrentWizard.torrentfile.title=\u0412\u044b\u0431\u043e\u0440 \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 exportTorrentWizard.torrentfile.message=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 exportTorrentWizard.torrentfile.path=\u041f\u0430\u043f\u043a\u0430 exportTorrentWizard.torrentfile.browse=\u041e\u0431\u0437\u043e\u0440 exportTorrentWizard.torrentfile.invalidPath=\u041e\u0448\u0438\u0431\u043e\u0447\u043d\u044b\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 exportTorrentWizard.exportfile.title=\u0412\u044b\u0431\u043e\u0440 \u0444\u0430\u0439\u043b\u0430 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 exportTorrentWizard.exportfile.message=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 XML-\u0444\u0430\u0439\u043b\u0430 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 exportTorrentWizard.exportfile.path=\u041f\u0430\u043f\u043a\u0430 exportTorrentWizard.exportfile.browse=\u041e\u0431\u0437\u043e\u0440 exportTorrentWizard.exportfile.invalidPath=\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 exportTorrentWizard.finish.title=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e exportTorrentWizard.finish.message=\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d \u0443\u0441\u043f\u0435\u0448\u043d\u043e exportTorrentWizard.process.inputfilebad.title=\u041e\u0448\u0438\u0431\u043e\u0447\u043d\u044b\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 exportTorrentWizard.process.inputfilebad.message=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0444\u0430\u0439\u043b\u0443: exportTorrentWizard.process.outputfileexists.title=\u0424\u0430\u0439\u043b \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 exportTorrentWizard.process.outputfileexists.message=\u0424\u0430\u0439\u043b \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u2014 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c? exportTorrentWizard.process.torrentfail.title=\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0447\u0442\u0435\u043d\u0438\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 exportTorrentWizard.process.exportfail.title=\u041d\u0435\u0443\u0434\u0430\u0447\u043d\u044b\u0439 \u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 exportTorrentWizard.process.unknownfail.title=\u041d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 importTorrentWizard.title=XML-\u0438\u043c\u043f\u043e\u0440\u0442 \u0444\u0430\u0439\u043b\u0430 importTorrentWizard.torrentfile.title=\u0412\u0432\u043e\u0434 \u0432\u044b\u0431\u043e\u0440\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 importTorrentWizard.torrentfile.message=\u0412\u0432\u043e\u0434 \u0438\u043c\u0435\u043d\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 importTorrentWizard.torrentfile.path=\u041f\u0430\u043f\u043a\u0430 importTorrentWizard.torrentfile.browse=\u041e\u0431\u0437\u043e\u0440 importTorrentWizard.torrentfile.invalidPath=\u041e\u0448\u0438\u0431\u043e\u0447\u043d\u044b\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 importTorrentWizard.importfile.title=\u0412\u044b\u0431\u043e\u0440 \u0444\u0430\u0439\u043b\u0430 \u0438\u043c\u043f\u043e\u0440\u0442\u0430 importTorrentWizard.importfile.message=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 importTorrentWizard.importfile.path=\u041f\u0430\u043f\u043a\u0430 importTorrentWizard.importfile.browse=\u041e\u0431\u0437\u043e\u0440 importTorrentWizard.importfile.invalidPath=\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0438\u043c\u043f\u043e\u0440\u0442\u0430 importTorrentWizard.finish.title=\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d importTorrentWizard.finish.message=\u0418\u043c\u043f\u043e\u0440\u0442 \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d \u0443\u0434\u0430\u0447\u043d\u043e importTorrentWizard.process.inputfilebad.title=\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b \u043e\u0448\u0438\u0431\u043e\u0447\u0435\u043d importTorrentWizard.process.inputfilebad.message=\u0412\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b \u0432\u0432\u043e\u0434\u0430: importTorrentWizard.process.outputfileexists.title=\u0424\u0430\u0439\u043b \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 importTorrentWizard.process.outputfileexists.message=\u0424\u0430\u0439\u043b \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u2014 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c? importTorrentWizard.process.torrentfail.title=\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 importTorrentWizard.process.importfail.title=\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 importTorrentWizard.process.unknownfail.title=\u041d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 ConfigView.label.bindip=\u041f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u043a \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0430\u0434\u0440\u0435\u0441\u0443 IP ConfigView.label.xfs.allocation=\u0412\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b XFS ConfigView.label.xfs.allocation.tooltip=\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e /usr/sbin/xfs_io \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435. \u0412\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u0430\u0445 Linux \u043e\u043d \u0432\u043a\u043b\u044e\u0447\u0451\u043d \u0432 \u043f\u0430\u043a\u0435\u0442 \u00abxfsprogs\u00bb. xfs.allocation.xfs_io.not.found=\u0412\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0441\u0442\u0430 \u043c\u0435\u0442\u043e\u0434\u043e\u043c XFS \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u00ab/usr/sbin/xfs_io\u00bb. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0430\u043a\u0435\u0442\u0430 \u00abxfsprogs\u00bb. \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435: \u00ab%1\u00bb. ConfigView.label.zeronewfiles=\u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0435\u0441\u0442\u043e \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439 \u043d\u0443\u043b\u044f\u043c\u0438 \u0444\u0430\u0439\u043b ConfigView.label.zeronewfiles.tooltip=\u0423\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e ConfigView.section.stats=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 ConfigView.section.stats.enable=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c ConfigView.section.stats.defaultsavepath=\u041f\u0430\u043f\u043a\u0430 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 ConfigView.section.stats.choosedefaultsavepath=\u0412\u044b\u0431\u043e\u0440 \u043f\u0430\u043f\u043a\u0438 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 ConfigView.section.stats.savefreq=\u0427\u0430\u0441\u0442\u043e\u0442\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f ConfigView.section.stats.minutes=\u043c ConfigView.section.stats.hours=\u0447 ConfigView.section.stats.seconds=\u0441 ConfigView.section.stats.savefile=\u0424\u0430\u0439\u043b \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 ConfigView.section.stats.graph_update_dividers=\u0412\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u043b\u0438\u043d\u0438\u044e \u043a\u0430\u0436\u0434\u044b\u0435 60 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 MyTorrentsView.menu.export=&\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 XML... MyTorrentsView.menu.host=&\u0425\u043e\u0441\u0442... ManagerItem.finishing=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 ConfigView.dialog.choosedefaulttorrentpath=\u0412\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 ConfigView.dialog.choosemovepath=\u0412\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0430 ConfigView.label.movecompleted=\u041f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b (\u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438) ConfigView.label.moveremoved=\u041f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b (\u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438) ConfigView.label.savetorrents=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u044b MainWindow.menu.view.mytracker=\u041c\u043e\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u044b MyTrackerView.title.full=\u041c\u043e\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u044b MyTrackerView.name=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 MyTrackerView.tracker=\u0422\u0440\u0435\u043a\u0435\u0440 MyTrackerView.status=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 MyTrackerView.status.started=\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 MyTrackerView.status.stopped=\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d MyTrackerView.peers=\u0423\u0437\u043b\u043e\u0432 MyTrackerView.seeds=\u0420\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 MyTrackerView.announces=\u0410\u043d\u043e\u043d\u0441\u044b MyTrackerView.uploaded=\u0420\u043e\u0437\u0434\u0430\u043d\u043e MyTrackerView.downloaded=\u0417\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043e MyTrackerView.left=\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c ConfigView.section.style=\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 ConfigView.label.set_ui_transfer_speeds=\u041a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0435\u0439 \u043e\u0431\u043c\u0435\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 ConfigView.label.set_ui_transfer_speeds.description=\u0417\u0434\u0435\u0441\u044c \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043f\u0440\u0438\u0451\u043c\u0430 \u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0432 \u043c\u0435\u043d\u044e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438.\n\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0437\u0430\u043f\u044f\u0442\u044b\u043c\u0438. ConfigView.label.set_ui_transfer_speeds.description.download=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 (\u041a\u0411/c) ConfigView.label.set_ui_transfer_speeds.description.upload=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 (\u041a\u0411/c) ConfigView.section.style.useCustomTabs=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0438 (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a) MainWindow.menu.view.plugins=&\u041c\u043e\u0434\u0443\u043b\u0438 fileDownloadWindow.saveTorrentIn=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u0432 fileDownloadWindow.title=Vuze \u2014 BitTorrent-\u043a\u043b\u0438\u0435\u043d\u0442 fileDownloadWindow.downloading=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441: fileDownloadWindow.status=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435: fileDownloadWindow.state_initializing=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f fileDownloadWindow.state_downloading=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 fileDownloadWindow.state_error=\u041e\u0448\u0438\u0431\u043a\u0430: MainWindow.menu.file.open.url=&\u0410\u0434\u0440\u0435\u0441... openUrl.title=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0430\u0434\u0440\u0435\u0441 openUrl.url=URL: MyTorrentsView.menu.host.error.title=\u041e\u0448\u0438\u0431\u043a\u0430 \u0445\u043e\u0441\u0442\u0438\u043d\u0433a \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 MyTorrentsView.menu.host.error.message=\u041f\u0440\u0438 \u0445\u043e\u0441\u0442\u0438\u043d\u0433\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 ConfigView.section.tracker=\u0422\u0440\u0435\u043a\u0435\u0440 ConfigView.section.tracker.pollinterval=\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u0434\u043b\u044f \u043e\u043f\u0440\u043e\u0441\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 (\u0441) ConfigView.section.tracker.publishenable=\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0435\u0442\u0430\u043b\u0435\u0439 \u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u043d\u0430 "/" ConfigView.section.tracker.ip=\u0412\u043d\u0435\u0448\u043d\u0438\u0439 \u0430\u0434\u0440\u0435\u0441 IP \u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.style.enableXPStyle=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u0442\u0438\u043b\u044c XP (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a) ConfigView.section.tracker.checkip=\u0423\u0437\u043d\u0430\u0442\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0430\u0434\u0440\u0435\u0441... ipCheckerWizard.title=\u041c\u0430\u0441\u0442\u0435\u0440 "IP Checker" ipCheckerWizard.service=\u0421\u0435\u0440\u0432\u0438\u0441 ipCheckerWizard.chooseService=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0435\u0440\u0432\u0438\u0441 IP-Checker \u0438\u0437 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u043d\u0438\u0436\u0435 ipCheckerWizard.explanations=\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0430\u0441\u0442\u0435\u0440 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430 IP. \u0415\u0441\u043b\u0438 \u0432\u0430\u0448 IP \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u043d\u044b\u0439, \u043c\u044b \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 "Dynamic DNS". \u041d\u0438\u0436\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043b\u0443\u0436\u0431\u044b, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0449\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441, \u0447\u044c\u0438 \u043b\u0438\u043d\u043a\u0438 (\u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f) \u0432\u0435\u0434\u0443\u0442 \u043a \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438. \u0417\u0430\u0442\u0435\u043c \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0432 \u043f\u043e\u043b\u0435 \u0430\u0434\u0440\u0435\u0441\u0430 IP \u0438\u043c\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u0445\u043e\u0441\u0442\u0430 (\u043d\u0430\u043f\u0440. myhostname.dyndns.org). \u0412\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0430\u0448\u0435\u0433\u043e "Dynamic DNS"-\u0421\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u043e\u0432\u044b\u043c \u0430\u0434\u0440\u0435\u0441\u043e\u043c IP. \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0432\u0430\u0448 IP \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f. ipCheckerWizard.service.description=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435: ipCheckerWizard.service.url=\u0421\u0441\u044b\u043b\u043a\u0430: ipCheckerWizard.progresstitle=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 IP ipCheckerWizard.checkComplete=\u041f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0435 IP: ipCheckerWizard.checkFailed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c, \u043f\u0440\u0438\u0447\u0438\u043d\u0430: wizard.tracker.local=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u043a\u0435\u0440 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b Vuze wizard.tracker.external=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 wizard.tracker.howToLocal=\t\u0414\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b/\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438/\u0422\u0440\u0435\u043a\u0435\u0440\u00bb wizard.announceUrl=URL \u0430\u043d\u043e\u043d\u0441\u0430: IPChecker.external.service.discoveryvip.description=Discoveryvip \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0430\u0434\u0440\u0435\u0441\u0430 IP IPChecker.external.httpinvalidresponse=\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 HTTP IPChecker.external.loadingwebpage=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u0430 IPChecker.external.analysingresponse=\u0410\u043d\u0430\u043b\u0438\u0437 \u043e\u0442\u0432\u0435\u0442\u0430 IPChecker.external.addressextracted=\u0418\u0437\u0432\u043b\u0435\u0447\u0451\u043d\u043d\u044b\u0435 \u0430\u0434\u0440\u0435\u0441\u0430 IP IPChecker.external.httploadfail=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 IPChecker.external.timeout=\u0412\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u0438\u0441\u0442\u0435\u043a\u043b\u043e IPChecker.external.ipnotfound=\u0410\u0434\u0440\u0435\u0441 IP \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d ConfigView.section.tracker.pollintervalmin=\u041c\u0438\u043d\u0438\u043c\u0443\u043c ConfigView.section.tracker.pollintervalmax=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c ConfigView.section.tracker.pollintervalincby=\u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u043d\u0430 ConfigView.section.tracker.pollintervalincper=\u043a\u0430\u0436\u0434\u044b\u0435 N \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 splash.loadingImages=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043e\u043a splash.initializeGui=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 splash.openViews=\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f splash.plugin=\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u043c\u043e\u0434\u0443\u043b\u044c: configureWizard.nat.tooManyPorts=\u0421\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u043e\u0432 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 (\u043c\u0430\u0445. 9) ConfigView.section.color=\u0426\u0432\u0435\u0442\u043e\u0432\u0430\u044f \u0441\u0445\u0435\u043c\u0430 MyTorrentsView.menu.publish=&\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c... MyTrackerView.status.published=\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d MyTrackerView.completed=\u0417\u0430\u0432\u0435\u0440\u0448\u0451\u043d MainWindow.menu.file.open.torrentnodefault=\u0422\u043e\u0440\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b... (\u0431\u0435\u0437 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e) wizard.comment=\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 ConfigView.label.movetorrent=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b ConfigView.label.movepartialdownloads=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0431\u044b\u043b\u0438 \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u044b \u043a\u0430\u043a \u00ab\u041d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u00bb ConfigView.label.subdir_is_in_default=\u0423\u0441\u043b\u043e\u0432\u0438\u0435 \u00ab\u0422\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0432 \u043f\u0430\u043f\u043a\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e\u00bb \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u0438 \u0432\u0441\u0435\u0445 \u0435\u0451 \u043f\u043e\u0434\u043f\u0430\u043f\u043e\u043a ConfigView.section.file.decoder.label=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430,\n\u0435\u0441\u043b\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u0431\u043e\u0440 ConfigView.section.file.decoder.nodecoder=\u041d\u0435\u0442 IPChecker.external.service.no-ip.description=\u0421\u043b\u0443\u0436\u0431\u044b \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 Dynamic \u0438 Static DNS\n(\u0431\u0435\u0437 \u043e\u0442\u043a\u0440\u044b\u0442\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 'check address') ConfigView.section.tracker.publicenable=\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b ConfigView.label.playdownloadspeech=\u0421\u043e\u043e\u0431\u0449\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u0441\u0438\u043d\u0442\u0435\u0437\u0430\u0442\u043e\u0440 \u0440\u0435\u0447\u0438 \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 ConfigView.label.playdownloadspeech.info=\u0421\u0438\u043d\u0442\u0435\u0437\u0430\u0442\u043e\u0440 \u0440\u0435\u0447\u0438 \u043b\u0443\u0447\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438\u043c \u044f\u0437\u044b\u043a\u043e\u043c # # Tooltips # GeneralView.label.status.pieces_available.tooltip=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043a\u043e\u043f\u0438\u0439 \u043a\u0430\u0436\u0434\u043e\u0439 \u0447\u0430\u0441\u0442\u0438.\n\u0415\u0441\u043b\u0438 \u0447\u0438\u0441\u043b\u043e \u043c\u0435\u043d\u044c\u0448\u0435 1, \u0444\u0430\u0439\u043b \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0442\u0440\u0443\u0434\u043d\u0438\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. GeneralView.label.trackerurl.tooltip=\u041d\u0430\u0436\u043c\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0430\u043d\u043e\u043d\u0441\u0430 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430 GeneralView.label.trackerurlopen.tooltip=\u041d\u0430\u0436\u043c\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 # # 2.0.4.4 # ConfigView.section.style.guiUpdate=\u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043a\u0430\u0436\u0434\u044b\u0435 ConfigView.section.style.inactiveUpdate=\u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u043e\u043a\u043d\u043e N \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u043e \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e ConfigView.section.style.graphicsUpdate=\u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043a\u0430\u0436\u0434\u044b\u0435 N \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 ConfigView.section.style.reOrderDelay=\u041f\u0435\u0440\u0435\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u0430\u0431\u043b\u0438\u0446 \u043a\u0430\u0436\u0434\u044b\u0435 N \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 [0: \u043d\u0438\u043a\u043e\u0433\u0434\u0430] ConfigView.section.style.reOrderDelay.never=\u041d\u0438\u043a\u043e\u0433\u0434\u0430 ConfigView.section.logging=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 ConfigView.section.logging.enable=\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0436\u0443\u0440\u043d\u0430\u043b \u0432 \u0444\u0430\u0439\u043b ConfigView.section.logging.logdir=\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0436\u0443\u0440\u043d\u0430\u043b\u0430 \u0432 \u043f\u0430\u043f\u043a\u0443 ConfigView.section.logging.choosedefaultsavepath=\u0412\u044b\u0431\u043e\u0440 \u043f\u0430\u043f\u043a\u0438 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f GeneralView.label.updatein.querying=\u0417\u0430\u043f\u0440\u043e\u0441... configureWizard.nat.sharePort=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 ConfigView.section.logging.maxsize=\u041c\u0430\u043a\u0441. \u0440\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 ConfigView.section.tracker.passwordenableweb=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u0441\u0435\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.tracker.passwordenabletorrent=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 ConfigView.section.tracker.username=\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f ConfigView.section.tracker.password=\u041f\u0430\u0440\u043e\u043b\u044c columnChooser.title=\u0412\u044b\u0431\u043e\u0440 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432 columnChooser.move=\u041e\u0447\u0435\u0440\u0451\u0434\u043d\u043e\u0441\u0442\u044c \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u044b\u0448\u0438 columnChooser.apply=\u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c columnChooser.columnname=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 columnChooser.columndescription=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 TableColumn.header.shareRatio=\u0420\u0435\u0439\u0442\u0438\u043d\u0433 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 MyTorrentsView.menu.editTableColumns=&\u0421\u0442\u043e\u043b\u0431\u0446\u044b... wizard.operationfailed=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u0443\u0434\u0430\u043b\u0430\u0441\u044c authenticator.title=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f authenticator.realm=\u041e\u0431\u043b\u0430\u0441\u0442\u044c authenticator.tracker=\u0422\u0440\u0435\u043a\u0435\u0440 authenticator.user=\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f authenticator.password=\u041f\u0430\u0440\u043e\u043b\u044c ConfigView.label.allowSendVersion=\u041f\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u044c Vuze \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0443\u044e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u043d\u043e\u043c\u0435\u0440\u0430 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438 \u0432\u044b\u0431\u043e\u0440\u043e\u0447\u043d\u043e\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b. ConfigView.label.version.info.link=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043e \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0437\u0434\u0435\u0441\u044c wizard.hint.mode=\u0421\u043e\u0432\u0435\u0442:\t\u041c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u044c \u0432 \u043e\u043a\u043d\u043e \u043c\u0430\u0441\u0442\u0435\u0440\u0430\n\t\u043d\u0443\u0436\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0438\u043b\u0438 \u043f\u0430\u043f\u043a\u0443 wizard.hint.file=\u0421\u043e\u0432\u0435\u0442:\t\u0412\u043e\u0437\u043c\u043e\u0436\u0435\u043d \u0432\u044b\u0431\u043e\u0440 \u0444\u0430\u0439\u043b\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 wizard.hint.directory=\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:\t\u041c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0443, \u043f\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0432 \u0435\u0451 \u0441\u044e\u0434\u0430 MainWindow.menu.help.checkupdate=&\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f... TableColumn.header.down=\u041f\u0440\u0438\u043d\u044f\u0442\u043e TableColumn.header.up=\u0420\u043e\u0437\u0434\u0430\u043d\u043e ConfigView.section.tracker.passwordenabletorrent.info=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 BitTorrent-\u043a\u043b\u0438\u0435\u043d\u0442 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Vuze) ConfigView.section.style.confirmationOnExit=\u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0432\u044b\u0445\u043e\u0434\u0435 MainWindow.dialog.exitconfirmation.title=\u0412\u044b\u0439\u0442\u0438 \u0438\u0437 Vuze MainWindow.dialog.exitconfirmation.text=\u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u043a\u0438\u043d\u0443\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443? SystemTray.menu.stopalltransfers=\u041e&\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u0441\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 TrayWindow.menu.stopalldownloads=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0432\u0441\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 ConfigView.section.tracker.sslport.info=\u0421\u043c. FAQ \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 wizard.tracker.ssl=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c SSL ConfigView.label.playdownloadfinished=\u0417\u0432\u0443\u043a \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 ConfigView.label.popupdownloadfinished=\u0412\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 ConfigView.label.popupfilefinished=\u0412\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 TableColumn.header.pieces=\u0427\u0430\u0441\u0442\u0438 TableColumn.header.pieces.info=\u0418\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u0435\u0439 TableColumn.header.completion=\u0413\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u044c TableColumn.header.completion.info=\u0413\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432 % ConfigView.section.style.showdownloadbasket=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043d\u043b\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a (\u0434\u043b\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435\u043c) ConfigView.section.style.alwaysShowTorrentFiles=\u0412\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0443\u044e (\u0444\u0430\u0439\u043b\u043e\u0432\u0443\u044e) \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430\u0445 wizard.multitracker=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0443\u043b\u044c\u0442\u0438\u0442\u0440\u0435\u043a\u0438\u043d\u0433\u043e\u0432\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e wizard.multitracker.title=\u041c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440 wizard.multitracker.configuration=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440\u0430 wizard.multitracker.new=\u0421\u043e\u0437\u0434\u0430\u0442\u044c... wizard.multitracker.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c... wizard.multitracker.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c wizard.multitracker.group=\u0413\u0440\u0443\u043f\u043f\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u0432 wizard.multitracker.edit.title=\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440\u0430 wizard.multitracker.edit.name=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 wizard.multitracker.edit.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c wizard.multitracker.edit.newgroup=\u041d\u043e\u0432\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 wizard.multitracker.edit.deletegroup=\u0423\u0434\u0430\u043b\u0438\u0442\u044c wizard.multitracker.edit.newtracker=\u041d\u043e\u0432\u044b\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 wizard.multitracker.edit.deletetracker=\u0423\u0434\u0430\u043b\u0438\u0442\u044c wizard.multitracker.edit.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 wizard.addingmt=\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043c\u0443\u043b\u044c\u0442\u0438\u0442\u0440\u0435\u043a\u0438\u043d\u0433\u0430 wizard.multitracker.noannounce=URL \u0430\u043d\u043e\u043d\u0441\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u0432 MyTorrentsView.menu.recheck=\u041f\u0440\u043e&\u0432\u0435\u0440\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b iconBar.showDownloadBar.tooltip=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u043d\u0435\u043b\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a iconBar.start.tooltip=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c iconBar.stop.tooltip=\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c iconBar.remove.tooltip=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b iconBar.openNoDefault.tooltip=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b (\u0431\u0435\u0437 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f) iconBar.openURL.tooltip=\u041e\u0442\u043a\u0440\u044b\u0442\u044c URL iconBar.openFolder.tooltip=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043f\u0430\u043f\u043a\u0443 iconBar.new.tooltip=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 iconBar.up.tooltip=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432\u0432\u0435\u0440\u0445 iconBar.down.tooltip=\u0441\u0434\u0432\u0438\u043d\u0443\u0442\u044c \u0432\u0432\u0435\u0440\u0445 iconBar.run.tooltip=\u043e\u0442\u043a\u0440\u044b\u0442\u044c iconBar.host.tooltip=\u0445\u043e\u0441\u0442 iconBar.publish.tooltip=\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c iconBar.editcolumns.tooltip=\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0442\u043e\u043b\u0431\u0446\u044b MyTorrentsView.menu.editTracker=&\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c URL \u0442\u0440\u0435\u043a\u0435\u0440\u0430 GeneralView.menu.selectTracker=\u0412\u044b\u0431\u0440\u0430\u0442\u044c ConfigView.section.stats.xslfile=\u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430 XSL ConfigView.section.stats.xslfiledetails=\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0444\u0430\u0439\u043b\u0430 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0432 \u0442\u0435\u0433 ConfigView.label.savetorrentbackup=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u0443\u044e \u043a\u043e\u043f\u0438\u044e ConfigView.section.tracker.forceport=\u0422\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 ConfigView.section.ipfilter.allow=\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u0438 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u044b (\u043e\u0431\u044b\u0447\u043d\u043e \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u044b) ConfigView.section.ipfilter.list.inrange=\u0431\u044b\u043b \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 ConfigView.section.ipfilter.list.notinrange=\u041d\u0435 \u0431\u044b\u043b \u043d\u0438 \u0432 \u043e\u0434\u043d\u043e\u043c \u0441\u043f\u0438\u0441\u043a\u0435 ConfigView.section.ipfilter.list.title=\u0421\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 IP ConfigView.label.allowsameip=\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0441 \u043e\u0434\u043d\u043e\u0433\u043e IP ConfigView.label.allowsameip.tooltip=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0422\u041e\u041b\u042c\u041a\u041e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438.\n\u0412 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u0438\u0447\u0435\u0440\u043e\u0432. ManagerItem.superseeding=\u0421\u0443\u043f\u0435\u0440-\u0440\u0430\u0437\u0434\u0430\u0447\u0430 ConfigView.label.userSuperSeeding=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u043f\u0435\u0440-\u0440\u0430\u0437\u0434\u0430\u0447\u0443 PeersView.uniquepiece=\u0427\u0430\u0441\u0442\u044c (\u0440\u0435\u0436\u0438\u043c \u0441\u0443\u043f\u0435\u0440-\u0440\u0430\u0437\u0434\u0430\u0447\u0438) PeersView.uniquepiece.none=\u041d\u0435\u0442 PeersView.timetosend=\u0412\u0440\u0435\u043c\u044f \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0447\u0430\u0441\u0442\u0438 (\u0440\u0435\u0436\u0438\u043c \u0441\u0443\u043f\u0435\u0440-\u0440\u0430\u0437\u0434\u0430\u0447\u0438) ConfigView.section.style.addurlsilently=\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c URL \u0431\u0435\u0437 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f ConfigView.section.style.addurlsilently.tooltip=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u043f\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c URL \u0431\u0435\u0437 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f. ConfigView.section.file.decoder.prompt=\u041f\u0440\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0432\u044b\u0431\u043e\u0440\u0430 \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c ConfigView.section.file.decoder.prompt.tooltip=\u041f\u0440\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0432\u044b\u0431\u043e\u0440\u0430 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0434\u0438\u0430\u043b\u043e\u0433 MyTorrentsView.menu.moveTop=\u0412 &\u0441\u0430\u043c\u044b\u0439 \u0432\u0435\u0440\u0445 MyTorrentsView.menu.moveEnd=\u0412 \u0441\u0430\u043c\u044b\u0439 &\u043d\u0438\u0437 ConfigView.label.moveonlyusingdefaultsave=\u0422\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0432 \u043f\u0430\u043f\u043a\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e ConfigView.label.moveonlyusingdefaultsave.tooltip=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 ConfigView.label.watchtorrentfolder=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b ConfigView.label.watchtorrentfolder.tooltip=\u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u043e\u0432\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 ConfigView.label.watchtorrentfolderinterval=\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b ConfigView.label.watchtorrentfolderinterval.tooltip=\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u0430\u0443\u0437\u044b \u0434\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u0430\u043f\u043a\u0438 ConfigView.dialog.choosewatchtorrentfolderpath=\u0412\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 ConfigView.label.startwatchedtorrentsstopped=\u041d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b ConfigView.label.startwatchedtorrentsstopped.tooltip=\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0432 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 ConfigView.section.plugins=\u041c\u043e\u0434\u0443\u043b\u0438 wizard.maketorrent.filesize=\u0420\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430(-\u043e\u0432) wizard.maketorrent.piececount=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0447\u0430\u0441\u0442\u0435\u0439 wizard.maketorrent.piecesize=\u0420\u0430\u0437\u043c\u0435\u0440 \u0447\u0430\u0441\u0442\u0438 wizard.maketorrent.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 MainWindow.menu.view.stats=&\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 SpeedView.title.full=\u0410\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c SpeedView.downloadSpeed.title=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 SpeedView.uploadSpeed.title=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.section.style.useSIUnits=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0434\u0438\u043d\u0438\u0446\u044b \u0421\u0418 (KB -> KiB \u0438.\u0442.\u0434.) iconBar.top.tooltip=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043d\u0430 \u0441\u0430\u043c\u044b\u0439 \u0432\u0432\u0435\u0440\u0445 iconBar.bottom.tooltip=\u0441\u0434\u0432\u0438\u043d\u0443\u0442\u044c \u0432\u043d\u0438\u0437 TableColumn.header.health=\u0410\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c MyTorrentsView.menu.health=\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 \u0437\u043d\u0430\u0447\u043a\u043e\u0432 health.explain.grey=\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 (\u043d\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438) health.explain.red=\u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u0443\u0437\u043b\u0430\u043c\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 health.explain.blue=\u043f\u0440\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0435\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u043d\u0438 \u0441 \u043e\u0434\u043d\u0438\u043c \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u043c\n\u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u2014 \u0447\u0442\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u043c\u0438 \u0435\u0441\u0442\u044c, \u043d\u043e \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 health.explain.yellow=\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0442\u0440\u0435\u043a\u0435\u0440 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u043c\u0438 \u0435\u0441\u0442\u044c, \u043d\u043e \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043d\u0435\u0442.\n\u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0441 NAT, \u0435\u0441\u043b\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f \u0436\u0451\u043b\u0442\u044b\u0435 health.explain.green=\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0432\u0441\u0451 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 ConfigView.section.style.alwaysRefreshMyTorrents=\u0412\u0441\u0435\u0433\u0434\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u00ab\u041c\u043e\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b\u00bb ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=\u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u00ab\u041c\u043e\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b\u00bb, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u0441\u043a\u0440\u044b\u0442\u0430 (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u043e\u0434\u0443\u043b\u044f\u043c\u0438 mIRC) # #2.0.7.0 # security.certtruster.title=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 security.certtruster.intro=\u042d\u0442\u043e\u0442 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0444\u0438\u0440\u043c\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u044b \u043d\u0435 \u0434\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0435 security.certtruster.resource=\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: security.certtruster.issuedto=\u0418\u0437\u0434\u0430\u043d \u0434\u043b\u044f: security.certtruster.issuedby=\u0418\u0437\u0434\u0430\u0442\u0435\u043b\u044c: security.certtruster.prompt=\u0412\u044b \u0434\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0435 \u0435\u043c\u0443? security.certtruster.yes=\u0414\u0430 security.certtruster.no=\u041d\u0435\u0442 ConfigView.section.tracker.torrentsperpage=\u0422\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] MainWindow.menu.file.share=&\u0420\u0430\u0437\u0434\u0430\u0442\u044c MainWindow.menu.file.share.file=&\u0424\u0430\u0439\u043b... MainWindow.menu.file.share.dir=&\u041f\u0430\u043f\u043a\u0443... MainWindow.menu.file.share.dircontents=&\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0430\u043f\u043a\u0438... MainWindow.menu.file.share.dircontentsrecursive=\u0421&\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0430\u043f\u043a\u0438 \u0438 \u0432\u0441\u0435\u0445 \u0435\u0451 \u043f\u043e\u0434\u043f\u0430\u043f\u043e\u043a... MainWindow.dialog.share.sharefile=\u0412\u044b\u0431\u043e\u0440 \u0444\u0430\u0439\u043b\u0430 \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 MainWindow.dialog.share.sharedir=\u0412\u044b\u0431\u043e\u0440 \u043f\u0430\u043f\u043a\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 MainWindow.dialog.share.sharedircontents=\u0412\u044b\u0431\u043e\u0440 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043f\u0430\u043f\u043a\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 MainWindow.dialog.share.sharedircontents.recursive=\u0418 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0432\u0441\u0435\u0445 \u0435\u0435 \u043f\u043e\u0434\u043f\u0430\u043f\u043e\u043a globalmanager.download.remove.veto=\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u043e plugin.sharing.download.remove.veto=\u042d\u0442\u043e\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u043c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043e\u043c.\n\u0414\u043b\u044f \u0435\u0433\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u0440\u0430\u0437\u0434\u0430\u0447\u0443: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=\u0413\u043b\u0430\u0432\u043d\u0430\u044f ConfigView.section.tracker.web=\u0421\u0435\u0442\u044c ConfigView.label.prioritizefirstpiece=\u041f\u043e\u0432\u044b\u0441\u0438\u0442\u044c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043f\u0435\u0440\u0432\u043e\u0439 \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 ConfigView.label.prioritizefirstpiece.tooltip=\u0412 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0430\u043c\u043e\u0435 \u043d\u0430\u0447\u0430\u043b\u043e \u0438 \u043a\u043e\u043d\u0435\u0446 \u0444\u0430\u0439\u043b\u0430.\n\u0414\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430. ConfigView.section.file.confirm_data_delete=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 ConfigView.section.file.confirm_data_delete.tooltip=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u00ab\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0438 \u0441\u0442\u0435\u0440\u0435\u0442\u044c\u00bb ConfigView.section.file.delete.include_files_outside_save_dir=\u041f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0438 \u0432\u0441\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0432\u043d\u0435 \u043f\u0430\u043f\u043a\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 TrayWindow.menu.startalldownloads=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0432\u0441\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 SystemTray.menu.startalltransfers=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0432\u0441\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 sharing.progress.title=\u0418\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u043e\u0431\u0449\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 sharing.progress.hide=\u0421\u043a\u0440\u044b\u0442\u044c MainWindow.menu.view.myshares=\u0420\u0430\u0437\u0434\u0430\u0447\u0438 MySharesView.title.full=M\u043e\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 MySharesView.name=\u0418\u043c\u044f MySharesView.type=\u0422\u0438\u043f MySharesView.type.file=\u0424\u0430\u0439\u043b MySharesView.type.dir=\u041f\u0430\u043f\u043a\u0430 MySharesView.type.dircontents=\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0430\u043f\u043a\u0438 MySharesView.type.dircontentsrecursive=\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0430\u043f\u043a\u0438 \u0438 \u0432\u0441\u0435\u0445 \u0435\u0451 \u043f\u043e\u0434\u043f\u0430\u043f\u043e\u043a MySharesView.menu.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c ConfigView.section.tracker.extensions=\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f ConfigView.section.tracker.sendpeerids=\u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0443\u0437\u043b\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u043c ConfigView.section.tracker.enableudp=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b UDP \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430 plugin.sharing.torrent.remove.veto=\u0414\u0430\u043d\u043d\u0430\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a \u043e\u0431\u0449\u0435\u0439 \u0440\u0430\u0437\u0434\u0430\u0447\u0435.\n\u0414\u043b\u044f \u0435\u0451 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0443\u0434\u0430\u043b\u0438\u0442\u0435 \u043e\u0431\u0449\u0443\u044e \u0440\u0430\u0437\u0434\u0430\u0447\u0443.: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=\u0414\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043a\u0435\u0442\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443. plugin.sharing.remove.veto=\u0414\u0430\u043d\u043d\u0430\u044f \u043e\u0431\u0449\u0430\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0430 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438\u0442 \u0440\u0430\u0437\u0434\u0430\u0447\u0435 "\u041f\u0430\u043f\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e" \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d\u0430.\n\u0423\u0434\u0430\u043b\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 \u0438\u0437 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 GeneralView.label.hash.tooltip=\u041d\u0430\u0436\u043c\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0445\u0435\u0448 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430 ConfigView.section.tracker.maxpeersreturned=\u041c\u0430\u043a\u0441. \u0443\u0437\u043b\u043e\u0432 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.label.serverport=\u041f\u043e\u0440\u0442 TCP/UDP \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 ConfigView.label.serverport.tooltip=\u041d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 1 \u0434\u043e 65535, \u043a\u0440\u043e\u043c\u0435 6880 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 Azureus. configureWizard.nat.server.tcp_listen_port=\u041f\u043e\u0440\u0442 TCP \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 ConfigView.section.sharing=\u041e\u0431\u0449\u0430\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0430 ConfigView.section.sharing.usessl=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c SSL \u0434\u043b\u044f \u043e\u0431\u0449\u0438\u0445 \u0440\u0430\u0437\u0434\u0430\u0447 (\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u0430) ConfigView.section.style.dropdiraction=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0438 \u043f\u0430\u043f\u043e\u043a ConfigView.section.style.dropdiraction.opentorrents=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b ConfigView.section.style.dropdiraction.sharefolder=\u0420\u0430\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0443 ConfigView.section.style.dropdiraction.sharefoldercontents=\u0420\u0430\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 # # 2.0.7.x # Categories.all=\u0412\u0441\u0435 Categories.uncategorized=\u0411\u0435\u0437 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439 CategoryAddWindow.message=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 CategoryAddWindow.title=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044e ConfigView.label.autoSeedingIgnoreInfo=\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u043f\u043e\u043c\u0435\u0449\u0430\u044e\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0435\u0446 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0438 \u043d\u0435 \u0441\u0442\u0430\u0440\u0442\u0443\u044e\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.\n\u042d\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u043d\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0441\u043e \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u043c \u00ab\u0412\u044b\u0441\u0448\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u00bb.\n\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c 0. ConfigView.label.directory=\u041f\u0430\u043f\u043a\u0430 ConfigView.label.disconnetseed.tooltip=\u041f\u0440\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u043e\u0431\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u043c\u0438.\n\u041a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u044f \u0441 \u043d\u0438\u043c\u0438 \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430. ConfigView.label.ignoreCase=\u041d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440 ConfigView.label.ignoreSeeds=\u041e\u0442\u043a\u043b\u043e\u043d\u044f\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0441 \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u0447\u0435\u043c ConfigView.label.importdirectory=\u041f\u0430\u043f\u043a\u0430 \u0438\u043c\u043f\u043e\u0440\u0442\u0430 ConfigView.label.minPeersToBoostNoSeeds.tooltip=\u0412\u0441\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0431\u0435\u0437 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 \u0438\u043b\u0438 \u043a\u0430\u0447\u0430\u044e\u0449\u0438\u0445 \u043c\u0435\u043d\u0435\u0435 \n\u0434\u0432\u0438\u0433\u0430\u0442\u044c \u0432\u0432\u0435\u0440\u0445 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 ConfigView.label.minPeersToBoostNoSeeds=\u041f\u043e\u043d\u0438\u0436\u0430\u0442\u044c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0431\u0435\u0437 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 \u0438 ConfigView.label.minSeedingTime.tooltip=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u044b \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0433\u043e \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043a\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043f\u0440\u0438\u0432\u043e\u0434\u044f \u043a \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0438 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e\u0439 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435.\n\u041f\u043e\u0434\u043e\u0431\u043d\u0443\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c, \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0432 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0443 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 (\u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e). ConfigView.label.minSeedingTime=\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445 ConfigView.label.minSpeedForActiveDL.tooltip=\u0421\u043b\u043e\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u043d\u044f\u0442\u044b\u043c \u0432 \u043f\u0435\u0440\u0432\u044b\u0435 30 \u0441\u0435\u043a\u0443\u043d\u0434\n\u043f\u043e\u0441\u043b\u0435 \u0441\u0442\u0430\u0440\u0442\u0430 \u043d\u0435\u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430. ConfigView.label.minSpeedForActiveDL=\u041d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442, \u0435\u0441\u043b\u0438 \u0435\u0433\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043d\u0438\u0436\u0435, \u0447\u0435\u043c ConfigView.label.peers=\u0443\u0437\u043b\u043e\u0432 ConfigView.label.queue.debuglog=\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e ConfigView.label.queue.debuglog.info=\u0412\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0438 \u0444\u0430\u0439\u043b \u0436\u0443\u0440\u043d\u0430\u043b\u0430.\n\u0425\u043e\u0442\u044f \u043e\u043d\u0430 \u0438 \u0442\u0440\u0443\u0434\u043d\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u0430, \u043f\u043e\u0434\u043e\u0431\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0443\u0437\u043d\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0438 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u0441\u0431\u043e\u0435\u0432. ConfigView.label.queue.minQueueingShareRatio=\u041d\u0435 \u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0438 \u043d\u0435 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0434\u043e \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a \u0440\u0430\u0437\u0434\u0430\u0447\u0435 \u0432\u044b\u0448\u0435 ConfigView.label.ratio=\u0440\u0435\u0439\u0442\u0438\u043d\u0433 ConfigView.label.removeOnStop=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u0441\u043b\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 ConfigView.label.savedirectory=\u041f\u0430\u043f\u043a\u0430 ConfigView.label.seeding.autoReposition.tooltip=\u0415\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e, \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 (\u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u00ab\u2116\u00bb) \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0440\u0430\u0437\u0434\u0430\u0447\u0438.\n\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435, \u0435\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u0432\u0438\u0434\u0435\u0442\u044c \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043d\u0430 \u0440\u0430\u0437\u0434\u0430\u0447\u0443, \u043d\u043e \u0432\u0441\u0451 \u0435\u0449\u0451 \u0445\u043e\u0442\u0438\u0442\u0435 \u0437\u043d\u0430\u0442\u044c \u043f\u043e\u0440\u044f\u0434\u043e\u043a, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b. ConfigView.label.seeding.autoReposition=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u043f\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u0427\u0430\u0441\u0442\u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0441 \u043c\u0430\u043b\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 \u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0443\u0437\u043b\u043e\u0432 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0441\u0440\u0435\u0434\u0438 \u0443\u0437\u043b\u043e\u0432 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435\u0442 \u043f\u043e\u043b\u043d\u043e\u0439 \u043a\u043e\u043f\u0438\u0438.\n\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0440\u0430\u0437\u0434\u0430\u0447\u0438, \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0449\u0438\u0435 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043f\u043e\u043b\u043d\u043e\u0439 \u043a\u043e\u043f\u0438\u0438 \u0438 \u043e\u0448\u0438\u0431\u043e\u0447\u043d\u043e \u0441\u043d\u0438\u0436\u0430\u044e\u0449\u0438\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u0430\u0437\u0434\u0430\u0447\u0438. ConfigView.label.seeding.fakeFullCopySeedStart=\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0441 \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u0447\u0435\u043c ConfigView.label.seeding.ignore=\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f ConfigView.label.seeding.ignore0Peers=\u041e\u0442\u043a\u043b\u043e\u043d\u044f\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0441 0 \u0443\u0437\u043b\u043e\u0432 ConfigView.label.seeding.ignoreRatioPeers=\u041e\u0442\u043a\u043b\u043e\u043d\u044f\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b, \u0438\u043c\u0435\u044e\u0449\u0438\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 1 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0435\u0433\u043e \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0435 ConfigView.label.seeding.ignoreShareRatio=\u041e\u0442\u043a\u043b\u043e\u043d\u044f\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b, \u0438\u043c\u0435\u044e\u0449\u0438\u0435 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.label.seeding.ignore.header.evenFirstPriority=\u041e\u0442\u043a\u043b\u043e\u043d\u044f\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u0434\u0430\u0436\u0435\n\u0435\u0441\u043b\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0432\u044b\u0441\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 ConfigView.label.seeding.ignore.header.rule=\u041f\u0440\u0430\u0432\u0438\u043b\u043e ConfigView.label.seeding.ignore.header.value=\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 ConfigView.label.seeding.firstPriority.info=\u0412\u044b\u0441\u0448\u0438\u043c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b, \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0438\u0435\u0441\u044f \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u0438. \u0422\u043e\u0440\u0440\u0435\u043d\u0442\u044b, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c \u0432\u044b\u0441\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 \u043d\u0435 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0438 \u043d\u0435 \u0441\u0442\u0430\u0432\u044f\u0442\u0441\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438. \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u043c \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u043e\u0442 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u043a\u0430\u0447\u043a\u0438. ConfigView.label.seeding.firstPriority.FP=\u0412\u044b\u0441\u0448\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.label.seeding.firstPriority=\u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0442\u044c \u0432\u044b\u0441\u0448\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430\u043c, \u043a\u043e\u0433\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b ConfigView.label.seeding.firstPriority.following=\u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u0439: ConfigView.label.seeding.firstPriority.shareRatio=\u0420\u0435\u0439\u0442\u0438\u043d\u0433 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u043c\u0435\u043d\u0435\u0435 ConfigView.label.seeding.firstPriority.seedingMinutes=\u041f\u0440\u043e\u0448\u0435\u0434\u0448\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0441 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0441\u043c\u0435\u043d\u044b \u0440\u0435\u0436\u0438\u043c\u0430 \u0437\u0430\u043a\u0430\u0447\u043a\u0438 \u043d\u0430 \u0440\u0435\u0436\u0438\u043c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.label.seeding.firstPriority.DLMinutes=\u041f\u0440\u043e\u0448\u0435\u0434\u0448\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0441 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043a\u0430\u0447\u043a\u0438 ConfigView.label.seeding.numPeersAsFullCopy.tooltip=\u0414\u043e\u043f\u0443\u0441\u043a\u0430\u044f, \u0447\u0442\u043e \u0441\u0440\u0435\u0434\u0438 X \u0443\u0437\u043b\u043e\u0432 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043e\u0434\u043d\u0430 \u043f\u043e\u043b\u043d\u0430\u044f \u043a\u043e\u043f\u0438\u044f, \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0443\u0437\u043b\u043e\u0432 \u0441\u043d\u0438\u0436\u0430\u0435\u0442\u0441\u044f.\n\u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0442\u0430\u043a\u0438\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u044e\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0442\u0440\u0430\u0444\u0438\u043a.\n\u042d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043d\u0435 \u043c\u0435\u043d\u044f\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445. ConfigView.label.seeding.numPeersAsFullCopy=\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043f\u043e\u043b\u043d\u043e\u0439 \u043a\u043e\u043f\u0438\u0438 \u043a\u0430\u0436\u0434\u044b\u0435\n[0: \u043d\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c] ConfigView.label.seeding.preferLargerSwarms.tooltip=\u0415\u0441\u043b\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0440\u0430\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u043d\u0435\u043c\u043d\u043e\u0433\u0438\u043c \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u043c \u0443\u0437\u043b\u0430\u043c, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u00ab\u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0433\u0440\u0443\u043f\u043f\u00bb.\n\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u2014 \u00ab\u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0435\u043d\u0438\u0435 \u043c\u0430\u043b\u044b\u0445 \u0433\u0440\u0443\u043f\u043f\u00bb. ConfigView.label.seeding.preferLargerSwarms=\u0421\u0440\u0435\u0434\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0435\u043d\u0438\u0435 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0443\u0437\u043b\u043e\u0432 ConfigView.label.seeding.rankType.none.tooltip=\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u043f\u043e \u0441\u0442\u043e\u043b\u0431\u0446\u0443 \u00ab\u2116\u00bb ConfigView.label.seeding.rankType.none=\u041e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043e ConfigView.label.seeding.rankType.peer.tooltip=\u0411\u043e\u043b\u044c\u0448\u0435 \u0443\u0437\u043b\u043e\u0432 \u0438 \u043c\u0435\u043d\u044c\u0448\u0435 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 = \u0432\u044b\u0448\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\n\u041f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043c\u0430\u043a\u0441\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u043c\u0435\u043d\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 ConfigView.label.seeding.rankType.peer=\u0412\u0437\u0432\u0435\u0448\u0435\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u0437\u043b\u043e\u0432 ConfigView.label.seeding.rankType.peerSeed.options=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0435:\u0443\u0437\u043b\u044b ConfigView.label.seeding.rankType.peerSeed.tooltip=\u0412\u044b\u0448\u0435 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u2014 \u0432\u044b\u0448\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.label.seeding.rankType.peerSeed=\u0421\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435\u043c \u0443\u0437\u043b\u044b:\u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0435 ConfigView.label.seeding.rankType.seed.fallback=\u0412\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043a \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044e \u0443\u0437\u043b\u044b:\u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0435 \u0447\u0435\u0440\u0435\u0437\n [0: \u043d\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f] ConfigView.label.seeding.rankType.seed.options=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 ConfigView.label.seeding.rankType.seed.tooltip=\u041c\u0435\u043d\u044c\u0448\u0435 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 \u2014 \u0432\u044b\u0448\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.label.seeding.rankType.seed=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 ConfigView.label.seeding.rankType.timedRotation.tooltip=\u0412\u0441\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u043f\u043e\u043e\u0447\u0435\u0440\u0451\u0434\u043d\u043e \u0441\u0442\u0430\u0432\u044f\u0442\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c \u0440\u0430\u0437\u0434\u0430\u0447\u0438.\n\u0412\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 \u00ab\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438\u00bb ConfigView.label.seeding.rankType.timedRotation=\u041e\u0447\u0435\u0440\u0435\u0434\u044c \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 ConfigView.label.seeding.rankType.tooltip=\u0422\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0441 \u043d\u0430\u0438\u0432\u044b\u0441\u0448\u0438\u043c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0441\u0442\u0430\u0440\u0442\u0443\u044e\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.\n\u0415\u0441\u043b\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442, \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u0431\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u043e\u0433\u043e \u0440\u0430\u043d\u0433\u0430 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c.\n\n\u0422\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0441\u0442\u043e\u044f\u0449\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043c\u043e\u0433\u0443\u0442 \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.\n\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438. ConfigView.label.seeding.rankType=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0430\u0432\u0442\u043e\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u043a\u0430\u0447\u0435\u043d\u043d\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f: ConfigView.label.stopAfterMinutes=\u0417\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u0443\u044e \u0440\u0430\u0437\u0434\u0430\u0447\u0443 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 ConfigView.label.switchpriority.tooltip=\u041d\u0438\u0437\u043a\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0441\u043d\u0438\u0436\u0430\u0435\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430. ConfigView.pluginlist.info=\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437 \u043d\u0438\u0445 \u043c\u043e\u0433\u0443\u0442 \u043d\u0435 \u0438\u043c\u0435\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a. ConfigView.pluginlist.noplugins=\u041c\u043e\u0434\u0443\u043b\u0438 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u044b. ConfigView.section.pluginslist=\u0421\u043f\u0438\u0441\u043e\u043a ConfigView.section.queue.seeding=\u0420\u0430\u0437\u0434\u0430\u0447\u0430 ConfigView.section.queue.seeding.autoStarting=\u0410\u0432\u0442\u043e\u0437\u0430\u043f\u0443\u0441\u043a ConfigView.section.queue.seeding.ignore=\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f ConfigView.section.queue.seeding.firstPriority=\u0412\u044b\u0441\u0448\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.section.queue.main=\u0413\u043b\u0430\u0432\u043d\u0430\u044f ConfigView.section.queue=\u041e\u0447\u0435\u0440\u0435\u0434\u044c ConfigView.section.torrents=\u0422\u043e\u0440\u0440\u0435\u043d\u0442\u044b ConfigView.text.all=\u0432\u0441\u0435 ConfigView.text.hours=\u0447\u0430\u0441\u043e\u0432 ConfigView.text.ignoreRule=\u041f\u0440\u0430\u0432\u0438\u043b\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043e ConfigView.text.ignore=\u041e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043e ConfigView.text.minutes=\u043c\u0438\u043d\u0443\u0442 ConfigView.text.neverIgnore=\u041d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c ConfigView.text.any=\u043b\u044e\u0431\u044b\u0435 DownloadManager.error.datamissing=\u0414\u0430\u043d\u043d\u044b\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 MainWindow.menu.file.open.torrentforseeding=\u0422\u043e\u0440\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b... (\u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438) MainWindow.menu.language.refresh=&\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c ManagerItem.forced=\u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e ManagerItem.queued=\u0412 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 MySeedersView.header=\u0417\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u043d\u044b\u0435/\u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b TableColumn.header.availability.info=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u043b\u043d\u044b\u0445 \u043a\u043e\u043f\u0438\u0439 TableColumn.header.availability=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c TableColumn.header.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f MyTorrentsView.header=\u041d\u0435\u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u043d\u044b\u0435/\u0433\u0440\u0443\u0437\u044f\u0449\u0438\u0435\u0441\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b TableColumn.header.maxuploads=\u041c\u0430\u043a\u0441. \u0440\u0430\u0437\u0434\u0430\u0447 MyTorrentsView.menu.category.delete=&\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044e MyTorrentsView.menu.forceStart=&\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e MyTorrentsView.menu.queue=&\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c MyTorrentsView.menu.setCategory.add=&\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044e... MyTorrentsView.menu.setCategory=\u0417\u0430\u0434\u0430\u0442\u044c \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044e TableColumn.header.savepath=\u041f\u0443\u0442\u044c TableColumn.header.SeedingRank=\u041f\u043e\u0437\u0438\u0446\u0438\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 TableColumn.header.totalspeed.info=\u041e\u0431\u0449\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0441\u0435\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0451\u043d\u043d\u044b\u0445 \u0441 \u0432\u0430\u043c\u0438 \u0443\u0437\u043b\u043e\u0432 TableColumn.header.totalspeed=\u041e\u0431\u0449\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c splash.initializePlugins=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u0435\u0439 StartStopRules.SPratioMet=S:P \u0421\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 OK StartStopRules.FP0Peers=FP / 0 \u0443\u0437\u043b\u043e\u0432 StartStopRules.0Peers=0 \u0443\u0437\u043b\u043e\u0432 StartStopRules.numSeedsMet=# \u0420\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0435 OK StartStopRules.ratioMet=\u0423\u0437\u043b\u044b:\u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0439 OK StartStopRules.shareRatioMet=\u0420\u0435\u0439\u0442\u0438\u043d\u0433 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 OK StartStopRules.waiting=\u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 StartStopRules.firstPriority=\u0412\u044b\u0441\u0448\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\u0420\u0430\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 (\u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e) DownloadManager.error.unabletostartserver=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u043f\u043e\u0440\u0442\u0430/\u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430 GeneralView.label.creationdate=\u0421\u043e\u0437\u0434\u0430\u043d: ConfigView.section.tracker.announcescrapepercentage=\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 % \u043e\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0436\u0438\u0437\u043d\u0438 \u0430\u043d\u043e\u043d\u0441\u0430\n\u0442.\u0435. 200 = 2:1. [0: \u043d\u0430 \u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435 \u0443\u0437\u043b\u0430] ManagerItem.stopping=\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 ConfigView.section.tracker.announcecacheperiod=\u041a\u044d\u0448 \u0430\u043d\u043e\u043d\u0441\u0430 (\u043c\u0441) ConfigView.section.tracker.scrapecacheperiod=\u041a\u044d\u0448 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 (\u043c\u0441) ConfigView.section.tracker.scrapeandcache=\u0417\u0430\u043f\u0440\u043e\u0441\u044b \u0438 \u043a\u044d\u0448 ConfigView.section.tracker.announcecacheminpeers=\u041a\u044d\u0448 \u0430\u043d\u043e\u043d\u0441\u043e\u0432 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043f\u043e\u0440\u043e\u0433 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 MyTrackerView.scrapes=\u0417\u0430\u043f\u0440\u043e\u0441\u043e\u0432 fileDownloadWindow.retry=\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c MyTrackerView.bytesin=\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043e, \u0411 MyTrackerView.bytesinave=\u0421\u0440. \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043e MyTrackerView.bytesout=\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e, \u0411 MyTrackerView.bytesoutave=\u0421\u0440. \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e ConfigView.section.file.max_open_files=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f/\u0437\u0430\u043f\u0438\u0441\u0438\n[0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.file.max_open_files.tooltip=\u041f\u043e\u043b\u0435\u0437\u043d\u043e \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0441 \u0441\u043e\u0442\u043d\u044f\u043c\u0438/\u0442\u044b\u0441\u044f\u0447\u0430\u043c\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u043b\u0438 \u0435\u0441\u043b\u0438 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442\u044b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u041e\u0421 \u043f\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 ConfigView.section.proxy=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u043a\u0441\u0438 ConfigView.section.proxy.enable_proxy=\u0414\u043e\u0441\u0442\u0443\u043f \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u043a\u0441\u0438-\u0441\u0435\u0440\u0432\u0435\u0440 ConfigView.section.proxy.host=\u0418\u043c\u044f \u0443\u0437\u043b\u0430 ConfigView.section.proxy.port=\u041f\u043e\u0440\u0442 ConfigView.section.proxy.username=\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f ConfigView.section.proxy.password=\u041f\u0430\u0440\u043e\u043b\u044c ConfigView.section.proxy.enable_socks=SOCKS-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u043f\u0440\u043e\u043a\u0441\u0438-\u0441\u0435\u0440\u0432\u0435\u0440 wizard.createtorrent.extrahashes=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0445\u0435\u0448\u0438 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0435\u0442\u0435\u0439 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Gnutella2, ed2k) GeneralView.label.connected=\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043e GeneralView.label.in_swarm=\u0432\u0441\u0435\u0433\u043e ManagerItem.initializing=\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f AlertMessageBox.error=\u041e\u0448\u0438\u0431\u043a\u0430 AlertMessageBox.warning=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 AlertMessageBox.comment=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f AlertMessageBox.information=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f AlertMessageBox.unread=\u0415\u0441\u0442\u044c \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f \u2014 \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0437\u0434\u0435\u0441\u044c. SharedPortServer.alert.selectorfailed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445.\n\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0447\u0442\u043e \u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u044d\u043a\u0440\u0430\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435 java(w).exe \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u0435\u0442\u0438 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u00abserver\u00bb. Tracker.alert.listenfail=\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0440\u0442\u0430 %1.\n\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0440\u0442 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438.\n\u0412 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \u043a\u043e\u043f\u0438\u0435\u0439 Vuze. DiskManager.alert.movefileexists=\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0438 \u043f\u0440\u0438\u043d\u044f\u0442\u043e\u0433\u043e \u0444\u0430\u0439\u043ba.\n\u0424\u0430\u0439\u043b %1 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. DiskManager.alert.movefilefails=\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u043d\u044f\u0442\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430.\n\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0444\u0430\u0439\u043b %1, %2 DiskManager.alert.movefilerecoveryfails=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f\n\u0424\u0430\u0439\u043b %1 \u043d\u0435 \u0431\u044b\u043b \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d, %2 ConfigView.section.tracker.logenable=\u041f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0432 \u00abtracker.log\u00bb SpeedView.stats.title=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 SpeedView.stats.total=\u0412\u0441\u0435\u0433\u043e SpeedView.stats.session=\u042d\u0442\u043e\u0442 \u0441\u0435\u0430\u043d\u0441 SpeedView.stats.session.tooltip=\u0412\u0441\u0435\u0433\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) SpeedView.stats.downloaded=\u041f\u0440\u0438\u043d\u044f\u0442\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) SpeedView.stats.uploaded=\u0420\u043e\u0437\u0434\u0430\u043d\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) SpeedView.stats.ratio=\u0420\u0435\u0439\u0442\u0438\u043d\u0433 SpeedView.stats.uptime=\u0412\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b SpeedView.stats.now=\u0421\u0435\u0439\u0447\u0430\u0441 SpeedView.stats.now.tooltip=\u0412\u0441\u0435\u0433\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b) AutoMigration.useralert=\u0418\u043c\u043f\u043e\u0440\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u043f\u0430\u043f\u043e\u043a:\n\n%1\n\u0412\u0441\u0435 \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u044b\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e.\n\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0430\u043f\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0430! # # > 2.0.8.0 # OpenTorrentWindow.title=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442(\u044b) OpenTorrentWindow.message=\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e OpenTorrentWindow.addFiles=&\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u0430\u0439\u043b OpenTorrentWindow.dataLocation=\u041c\u0435\u0441\u0442\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445: OpenTorrentWindow.startMode=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c OpenTorrentWindow.startMode.queued=\u0412 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 OpenTorrentWindow.startMode.stopped=\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d OpenTorrentWindow.startMode.forceStarted=\u0423\u0441\u043a\u043e\u0440\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a OpenTorrentWindow.addPosition=\u041f\u043e\u0437\u0438\u0446\u0438\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 OpenTorrentWindow.addPosition.first=\u041f\u0435\u0440\u0432\u0430\u044f OpenTorrentWindow.addPosition.last=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f TableColumn.header.remaining.info=\u041e\u0431\u044a\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u0438\u043d\u044f\u0442\u044c TableColumn.header.remaining=\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c ConfigView.section.tracker.enablecompact=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0430\u043d\u043e\u043d\u0441\u043e\u0432 ConfigView.section.tracker.enablekey=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043a\u043b\u044e\u0447\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u043c \u0434\u043b\u044f \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u043d\u043e\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 ConfigView.section.file.perf=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 ConfigView.section.file.perf.explain=\u041e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u043e \u2014 \u043d\u0435\u043e\u0431\u0434\u0443\u043c\u0430\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043c\u043e\u0433\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u0432\u043b\u0438\u044f\u043d\u0438\u0435 \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u041f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a.\n\u041f\u0440\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0434\u0443\u043c\u0430\u0439\u0442\u0435 \u043e \u043f\u043e\u043d\u0438\u0436\u0435\u043d\u0438\u0438 \u043f\u0440\u0435\u0434\u0435\u043b\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 (\u0441\u043c. \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043e\u0431\u043c\u0435\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438) ConfigView.section.file.max_open_files.explain=\u041f\u0440\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u0445 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u0417\u0434\u0435\u0441\u044c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u0447\u0438\u0441\u043b\u043e \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043e\u0442\u0440\u044b\u0442\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 popup.error.hide=\u0421\u043a\u0440\u044b\u0442\u044c popup.error.details=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 ConfigView.section.style.colorOverrides=\u041e\u0442\u043c\u0435\u043d\u0430 \u0446\u0432\u0435\u0442\u043e\u0432 ConfigView.section.style.colorOverride.progressBar=\u0418\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430 ConfigView.section.style.colorOverride.error=\u041e\u0448\u0438\u0431\u043a\u0430 MainWindow.status.tooOld=\u0443\u0441\u0442\u0430\u0440\u0435\u043b\u0430 \u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f. ConfigView.section.style.colorOverride.warning=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 ConfigView.section.style.colorOverride.altRow=\u041d\u0435\u0447\u0451\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 ConfigView.section.file.save.peers.enable=\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u0443\u0437\u043b\u0430\u043c\u0438 \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f ConfigView.section.file.save.peers.max=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0443\u0437\u043b\u043e\u0432 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.file.save.peers.pertorrent=\u043d\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 ConfigView.label.max_peers_per_torrent=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.label.max_peers_total=\u041c\u0430\u043a\u0441. \u0432\u0441\u0435\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.style.colorOverrides.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0446\u0432\u0435\u0442\u0430 \u0432 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 ConfigView.section.language.info=\u0415\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b ConfigView.section.language.enableUpdate=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u0442\u044c ConfigView.section.language.UpdateURL=URL \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f ConfigView.section.language.UpdateNow=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441 Button.revert=\u041d\u0430\u0437\u0430\u0434 MyTorrentsView.menu.changeDirectory=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0443\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f GenericText.column=\u0441\u0442\u043e\u043b\u0431\u0435\u0446 MyTorrentsView.menu.thisColumn.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0442\u043e\u043b\u0431\u0435\u0446 MyTorrentsView.menu.thisColumn.toClipboard=\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430 MyTorrentsView.menu.thisColumn.autoTooltip=\u0412\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0443 MyTorrentsView.menu.tracker=\u0422\u0440\u0435\u043a\u0435\u0440 ConfigView.download.abbreviated=\u041f: ConfigView.upload.abbreviated=\u0420: ConfigView.complete.abbreviated=\u0417: TableColumn.header.secondsseeding=\u0412\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 TableColumn.header.secondsseeding.info=\u041e\u0431\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 TableColumn.header.secondsdownloading=\u0412\u0440\u0435\u043c\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 TableColumn.header.secondsdownloading.info=\u041e\u0431\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 ConfigView.section.tracker.udpversion=\u0412\u0435\u0440\u0441\u0438\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 UDP (1 \u0438\u043b\u0438 2) window.updateswt.title=\u0412\u0430\u0448\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 SWT \u0443\u0441\u0442\u0430\u0440\u0435\u043b\u0430! window.updateswt.text=\u0412\u0435\u0440\u0441\u0438\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 SWT \u0443\u0441\u0442\u0430\u0440\u0435\u043b\u0430!\nVuze \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 SWT \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u0438. \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 SWT.\n\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u00ab\u041e\u041a\u00bb, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c SWT. window.updateswt.status=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 window.updateswt.failed=\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u041e\u041a \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430. window.updateswt.status.downloading.updater=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043c\u043e\u0434\u0443\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 window.updateswt.status.finding=\u041f\u043e\u0438\u0441\u043a \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 SWT window.updateswt.status.downloading=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 SWT window.updateswt.status.done=\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a window.updateswt.cancel=O\u0442\u043c\u0435\u043d\u0430 swt.updater.downloader.downloading=\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 SWT \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0441 swt.updater.urlsgetter.downloading=\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0435\u0440\u043a\u0430\u043b swt.updater.urlsgetter.platform=\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 SWT \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b: window.updateswt.ignore=\u041f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c ConfigView.section.style.useFancyTabs=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0446\u0432\u0435\u0442\u043d\u044b\u0435 \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0438 splash.initializeGM=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f Global Torrent Manager splash.loadingTorrents=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 splash.firstMessageNoI18N= MyTorrentsView.menu.thisColumn.sort=&\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 Scrape.status.ok=\u0417\u0430\u043f\u0440\u043e\u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 OK Scrape.status.error=\u041e\u0448\u0438\u0431\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430: Scrape.status.error.badURL=URL \u0430\u043d\u043e\u043d\u0441\u0430 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438. Scrape.status.error.nohash=\u0412 \u043e\u0442\u0432\u0435\u0442\u043d\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0445\u0435\u0448. Scrape.status.error.invalid=\u041e\u0448\u0438\u0431\u043e\u0447\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442. Scrape.status.nextScrapeAt=\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0447\u0435\u0440\u0435\u0437 %1 Scrape.status.scraping=\u0417\u0430\u043f\u0440\u043e\u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438... Scrape.status.initializing=\u0417\u0430\u043f\u0440\u043e\u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438... Scrape.status.scraping.queued=\u0417\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c... ConfigView.label.minSpeedForActiveSeeding=\u0413\u043e\u0442\u043e\u0432\u044b\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u043d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u043b\u043e\u0442, \u0435\u0441\u043b\u0438 \u0435\u0433\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043d\u0438\u0436\u0435, \u0447\u0435\u043c ConfigView.section.stats.exportpeers=\u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0443\u0437\u043b\u0430 MainWindow.menu.view.irc.moved=IRC \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u043e\u0434\u0443\u043b\u044f \u043d\u0430 http://azureus.sourceforge.net/plugin_list.php. \u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043e\u043d \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 \u043c\u0435\u043d\u044e \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b/\u041c\u043e\u0434\u0443\u043b\u0438/IRC\u00bb. MyTrackerView.webui.contextmenu.copyurl=\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c URL \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430 ConfigView.section.file.torrent.ignorefiles=\u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\n(\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 .DS_Store;Thumbs.db) Torrent.create.progress.ignoringfile=\u0424\u0430\u0439\u043b \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f ConfigView.section.style.useUnitsRateBits=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0442\u044b \u0432\u043c\u0435\u0441\u0442\u043e \u0431\u0430\u0439\u0442\u043e\u0432 \u0434\u043b\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 (\u041a\u0438\u0411/\u0441 > \u041a\u0438\u0431\u0438\u0442/\u0441 \u0438 \u0442.\u0434) ConfigView.section.interface.resetassoc=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0435 \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 .torrent \u0432 explorer ConfigView.section.interface.resetassocbutton=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c ConfigView.section.interface.checkassoc=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u0432\u044f\u0437\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0441 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043e\u0439 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 dialog.associations.title=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 Button.yes=&\u0414\u0430 Button.no=&\u041d\u0435\u0442 ConfigView.label.seeding.autoStart0Peers=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0441 0 \u0443\u0437\u043b\u043e\u0432 ConfigView.label.seeding.autoStart0Peers.tooltip=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0431\u0435\u0437 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u044e\u0449\u0438\u0445. dialog.associations.prompt=Vuze \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043e\u0439 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 BitTorrent.\n\u0416\u0435\u043b\u0430\u0435\u0442\u0435 \u043b\u0438 \u0432\u044b \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c Vuze \u044d\u0442\u043e\u0442 \u0441\u0442\u0430\u0442\u0443\u0441? dialog.associations.askagain=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 ConfigView.section.plugins.update=\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 Plugin.pluginupdate.enablecheck=\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u0435\u0439 plugins.basicview.status=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435: plugins.basicview.activity=\u0414\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c: plugins.basicview.progress=\u041f\u0440\u043e\u0433\u0440\u0435\u0441\u0441: plugins.basicview.log=\u0416\u0443\u0440\u043d\u0430\u043b: ConfigView.label.maxdownloadspeed=\u041a\u0411/c \u043e\u0431\u0449\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] splash.loadingTorrent=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 splash.of=\u0438\u0437 UpdateWindow.title=\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f Vuze UpdateWindow.header=\u0414\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f: UpdateWindow.columns.install=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c UpdateWindow.columns.name=\u0418\u043c\u044f UpdateWindow.columns.version=\u0412\u0435\u0440\u0441\u0438\u044f UpdateWindow.columns.size=\u0420\u0430\u0437\u043c\u0435\u0440 UpdateWindow.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c UpdateWindow.quit=\u0412\u044b\u0439\u0442\u0438 UpdateWindow.close=\u0417\u0430\u043a\u0440\u044b\u0442\u044c UpdateWindow.ok=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c UpdateWindow.restart=\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441 UpdateWindow.status.downloading=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 UpdateWindow.status.done=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e UpdateWindow.status.failed=\u041d\u0435\u0443\u0434\u0430\u0447\u043d\u043e UpdateWindow.status.restartNeeded=\u041f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a! ConfigView.pluginlist.broken=\u041f\u043e\u0432\u0440\u0435\u0436\u0434\u0451\u043d ConfigView.pluginlist.whereToPut=\u041f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 \u0432: ConfigView.pluginlist.whereToPutOr=\u0414\u043b\u044f \u043e\u0431\u0449\u0438\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439: MainWindow.statusText.checking=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 TableColumn.header.OnlyCDing4=\u041d\u0430 \u0440\u0430\u0437\u0434\u0430\u0447\u0435 TableColumn.header.OnlyCDing4.info=\u041e\u0431\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430, \u043d\u0435 \u0441\u0447\u0438\u0442\u0430\u044f \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 ConfigView.section.style.alternateTablePainting=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u0440\u043e\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u044b (\u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a) UpdateWindow.status.restartMaybeNeeded=\u041c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a ConfigView.pluginlist.shared=\u0440\u043e\u0437\u0434\u0430\u043d\u043e PeersView.host=\u0414\u043e\u043c\u0435\u043d\u043d\u043e\u0435 \u0438\u043c\u044f PeersView.host.info=\u0414\u043e\u043c\u0435\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u0443\u0437\u043b\u0430, \u0435\u0441\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e (\u043c\u043e\u0436\u0435\u0442 \u0441\u043d\u0438\u0437\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c) MainWindow.menu.help.whatsnew=\u0427\u0442\u043e \u043d\u043e\u0432\u043e\u0433\u043e ConfigView.label.checkonstart=\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 ConfigView.label.periodiccheck=\u041f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 ConfigView.label.opendialog=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u041c\u0430\u0441\u0442\u0435\u0440\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 MainWindow.updateavail=\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f MainWindow.status.unofficialversion=Vuze \u0411\u0435\u0442\u0430 MainWindow.status.latestversionunchecked=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0430 GeneralView.label.updatein.stopped=\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e StartStopRules.menu.viewDebug=\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e ConfigView.section.style.doNotUseGB=\u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0413\u0411 \u043a\u0430\u043a \u0435\u0434\u0438\u043d\u0438\u0446\u0443 ConfigView.section.style.doNotUseGB.tooltip=\u0415\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e, Vuze \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442\u044b (\u041c\u0411), \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 1024\u041c\u0411 MainWindow.menu.help.plugins=\u0421\u043f\u0438\u0441\u043e\u043a \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u043d\u0430 \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u0435 ConfigView.section.plugins.TrackerWeb=\u0422\u0440\u0435\u043a\u0435\u0440 \u0441\u0435\u0442\u0438 ConfigView.section.tracker.enablecategories=\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u043f\u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f\u043c health.explain.share=\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u043d\u0435 \u0440\u0430\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0438 \u043d\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u0442\u0441\u044f ConfigView.section.tracker.createcert=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 ConfigView.section.tracker.createbutton=\u0421\u043e\u0437\u0434\u0430\u0442\u044c security.certcreate.title=\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 security.certcreate.intro=\u0414\u0430\u043d\u043d\u044b\u0439 \u0434\u0438\u0430\u043b\u043e\u0433 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 security.certcreate.alias=\u042f\u0440\u043b\u044b\u043a security.certcreate.strength=\u0421\u0442\u043e\u0439\u043a\u043e\u0441\u0442\u044c security.certcreate.firstlastname=\u0418\u043c\u044f \u0438 \u0444\u0430\u043c\u0438\u043b\u0438\u044f security.certcreate.orgunit=\u041e\u0442\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 security.certcreate.org=\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f security.certcreate.city=\u0413\u043e\u0440\u043e\u0434 \u0438\u043b\u0438 \u043c\u0435\u0441\u0442\u043e \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f security.certcreate.state=\u041e\u0431\u043b\u0430\u0441\u0442\u044c \u0438\u043b\u0438 \u0440\u0430\u0439\u043e\u043d security.certcreate.country=\u0414\u0432\u0443\u0445\u0431\u0443\u043a\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0441\u0442\u0440\u0430\u043d\u044b security.certcreate.ok=\u0421\u043e\u0437\u0434\u0430\u0442\u044c security.certcreate.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c security.certcreate.createok=\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 \u043f\u0440\u043e\u0448\u043b\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e security.certcreate.createfail=\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 \u043f\u0440\u043e\u0448\u043b\u043e \u043d\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e ConfigView.section.plugins.webui=\u0412\u0435\u0431-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430 Swing ConfigView.section.plugins.xml_http_if=\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 XML/HTTP webui.passwordenable=\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c webui.user=\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f webui.password=\u041f\u0430\u0440\u043e\u043b\u044c webui.port=\u041f\u043e\u0440\u0442 (*) webui.protocol=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b (*) webui.homepage=\u0414\u043e\u043c\u0430\u0448\u043d\u044f\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 (*) webui.rootdir=\u041a\u043e\u0440\u043d\u0435\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 (*) webui.rootres=\u041a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u0440\u0435\u0441\u0443\u0440\u0441 (*) webui.mode=\u0420\u0435\u0436\u0438\u043c (*) webui.mode.info=\u0420\u0435\u0436\u0438\u043c\u044b\n\t\u00abfull\u00bb\t= \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e)\n\t\u00abview\u00bb\t= \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 (\u0430 \u0442\u0430\u043a\u0436\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b) webui.access=\u0414\u043e\u0441\u0442\u0443\u043f (*) webui.access.info=\u0414\u043e\u0441\u0442\u0443\u043f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c\n\t\u00ablocal\u00bb\t= \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440 \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\n\t\u00aball\u00bb\t\t= \u0434\u043e\u0441\u0442\u0443\u043f \u0431\u0435\u0437 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e)\n\tIP\t\t= \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 192.168.0.2\t\t\t\t\u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0430\u0434\u0440\u0435\u0441\n\tIP1-IP2\t= \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 192.168.0.1-192.168.0.255\t\u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0430\u0434\u0440\u0435\u0441\u043d\u044b\u0435 \u0433\u0440\u0430\u043d\u0438\u0446\u044b GeneralView.label.maxdownloadspeed=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u0451\u043c\u0430 Security.keystore.corrupt=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043a\u043b\u044e\u0447\u0435\u0439 \u00ab%1\u00bb, \u0443\u0434\u0430\u043b\u0438\u0442\u0435 \u0435\u0433\u043e \u0438 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435/\u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b \u0437\u0430\u043d\u043e\u0432\u043e Security.keystore.empty=\u041f\u0440\u043e\u0432\u0435\u0440\u043e\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. \u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0441\u043e\u0431\u043e\u0439 \u0437\u0430\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 (\u0441\u043c. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 > \u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c) \u0438\u043b\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u0432 '%1' webui.restart.info=* \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 GeneralView.label.maxdownloadspeed.tooltip=\u043c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.UPnP=UPnP upnp.enable=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c UPnP upnp.info=\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 Plug and Play (UPnP) \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u0440\u0442\u044b \u043d\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0430\u0445 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 UPnP. upnp.mapping.dataport=\u041f\u043e\u0440\u0442 \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 upnp.mapping.tcptrackerport=TCP \u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 upnp.mapping.udptrackerport=\u041f\u043e\u0440\u0442 UDP-\u0442\u0440\u0435\u043a\u0435\u0440\u0430 upnp.alert.differenthost=UPnP: \u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u00ab%1\u00bb \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0434\u043b\u044f \u00ab%2\u00bb \u2014 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u043e\u0440\u0442 upnp.alert.mappingok=UPnP: \u041f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u00ab%1\u00bb \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e upnp.alert.mappingfailed=UPnP: \u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u00ab%1\u00bb upnp.alertsuccess=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c \u043e\u0431 \u0443\u0434\u0430\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u0445 upnp.alert.lostdevice=UPnP: \u041f\u043e\u0442\u0435\u0440\u044f\u043d\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c \u00ab%1\u00bb \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 UPnP \u00ab%2\u00bb upnp.grabports=\u041f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u0440\u0442\u044b, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0442 \u0434\u0440\u0443\u0433\u043e\u043c\u0443 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0443 upnp.refresh.label=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u0442\u043e\u0432 upnp.refresh.button=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c upnp.alert.mappinggrabbed=UPnP: \u041f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u00ab%1\u00bb \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u2014 \u0432\u0437\u044f\u0442\u043e \u0438\u0437 \u00ab%2\u00bb upnp.mapping.tcpssltrackerport=TCP SSL \u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 upnp.alertothermappings=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u0440\u0442\u044b, \u0437\u0430\u043d\u044f\u0442\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430\u043c\u0438 upnp.alertdeviceproblems=\u0421\u043e\u043e\u0431\u0449\u0430\u0442\u044c \u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0445 \u0441 UPnP \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 upnp.trace_to_log=\u0412\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0432\u0441\u044e \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u043c\u0430\u0446\u0438\u044e \u0432 \u0436\u0443\u0440\u043d\u0430\u043b upnp.wiki_link=\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0432 \u0412\u0438\u043a\u0438 Vuze \u043f\u043e UPnP upnp.refresh_mappings_on_bad_nat=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u0440\u0442\u044b, \u0435\u0441\u043b\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 NAT \u2014 \u00ab\u0437\u0430 \u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u044b\u043c \u044d\u043a\u0440\u0430\u043d\u043e\u043c\u00bb ConfigView.pluginlist.coreplugins=\u0417\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438: Peers.column.DLedFromOthers=\u041e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 Peers.column.DLedFromOthers.info=\u041e\u0431\u044a\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 \u0443\u0437\u043b\u043e\u0432 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u0432\u0430\u043c\u0438 Peers.column.UpDownRatio=\u0420\u043e\u0437\u0434\u0430\u043d\u043e:\u043f\u0440\u0438\u043d\u044f\u0442\u043e Peers.column.UpDownRatio.info=\u0421\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0443\u0437\u043b\u0430 "\u0420\u0430\u0437\u0434\u0430\u043b : \u041f\u0440\u0438\u043d\u044f\u043b" Peers.column.UpRatio=\u0420\u0435\u0439\u0442\u0438\u043d\u0433 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 Peers.column.UpRatio.info=\u0421\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0443\u0437\u043b\u0430 "\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043e \u043e\u0442 \u0432\u0430\u0441 : \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043e \u043e\u0442 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445" upnp.releasemappings=\u041e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u0440\u0442\u044b \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f webui.upnpenable=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c UPnP \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0430 (*) ConfigView.section.file.friendly.hashchecking=\u0429\u0430\u0434\u044f\u0449\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0445\u0435\u0448\u0435\u0439 ConfigView.section.file.friendly.hashchecking.tooltip=\u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0439, \u043d\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0440\u0430\u0437\u0433\u0440\u0443\u0436\u0430\u044e\u0449\u0438\u0439 \u0426\u041f/\u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0440\u0435\u0436\u0438\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0445\u0435\u0448\u0430 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c. ConfigView.section.tracker.seedretention=\u041c\u0430\u043a\u0441. \u0437\u0430\u043f\u043e\u043c\u043d\u0435\u043d\u043d\u044b\u0445 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 \u0434\u043b\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.tracker.seedretention.info=\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u043e\u043c\u043d\u0435\u043d\u043d\u044b\u0445 ConfigView.section.tracker.port=\u0422\u0440\u0435\u043a\u0435\u0440 \u043d\u0430 \u043f\u043e\u0440\u0442\u0435 HTTP ConfigView.section.tracker.sslport=\u0422\u0440\u0435\u043a\u0435\u0440 \u043d\u0430 \u043f\u043e\u0440\u0442\u0435 HTTPS ConfigView.section.tracker.publicenable.info=\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b\n\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0432\u0430\u0448\u0435\u0433\u043e \u0442\u0440\u0435\u043a\u0435\u0440\u0430 Button.clear=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c MainWindow.IPs.tooltip=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u043e\u0432 \u0444\u0438\u043b\u044c\u0442\u0440\u0430: %1\n\u0412\u0441\u0435\u0433\u043e \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 IPFilters - \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445/\u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445/\u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0445 IP \u0441\u0435\u0430\u043d\u0441\u0430.\n\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c, \u0434\u0432\u0430\u0436\u0434\u044b \u0449\u0451\u043b\u043a\u043d\u0443\u0432 \u0437\u0434\u0435\u0441\u044c. ConfigView.section.ipfilter.list.banned=\u0431\u044b\u043b \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d ConfigView.section.ipfilter.list.baddata=\u043f\u0440\u0438\u0441\u043b\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u0447\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435: \u0441\u043b\u0443\u0447\u0430\u0435\u0432 = Button.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c ConfigView.section.ipfilter.bannedinfo=\u0410\u0434\u0440\u0435\u0441\u0430 IP, \u043f\u0440\u0438\u0441\u043b\u0430\u0432\u0448\u0438\u0435 \u043e\u0448\u0438\u0431\u043e\u0447\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e\u0441\u043b\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u0438\u0439 ConfigView.section.ipfilter.blockedinfo=\u0410\u0434\u0440\u0435\u0441\u0430 IP, \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 download.removerules.name=\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f download.removerules.unauthorised.info=\u041d\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442, \u0432 \u0437\u0430\u043f\u0440\u0435\u0449\u0430\u044e\u0449\u0435\u043c \u043e\u0442\u0432\u0435\u0442\u0435 \u043d\u0430 \u0430\u043d\u043e\u043d\u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u00abnot authoris(z)ed\u00bb \u0438\u043b\u0438 \u00abunauthoris(z)ed\u00bb download.removerules.unauthorised=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043d\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 download.removerules.unauthorised.seedingonly=\t\u0422\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0435 download.removerules.removed.ok=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0441 \u0433\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u044c\u044e '%1'. \u042d\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u043f\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432. download.removerules.updatetorrents=\u0423\u0434\u0430\u043b\u044f\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0441 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f\u043c\u0438 \u0434\u043b\u044f Vuze, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435\u043c ConfigView.label.defaultstarttorrentsstopped=\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0432 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e ConfigView.section.server.enableudp=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b UDP upnp.mapping.dataportudp=\u041f\u043e\u0440\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 UDP-\u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.file.decoder.showlax=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0434\u043a\u0438\u0435 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438 ConfigView.section.file.decoder.showall=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438 MainWindow.status.updowndetails.tooltip=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438/\u043f\u0440\u0438\u0451\u043c\u0430\n\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0440\u0430\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438 \u043c\u044b\u0448\u0438, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c, \u0434\u0432\u0430\u0436\u0434\u044b \u0449\u0451\u043b\u043a\u043d\u0443\u0432 \u043b\u0435\u0432\u043e\u0439 TrackerClient.announce.warningmessage=\u0422\u0440\u0435\u043a\u0435\u0440 \u0434\u043b\u044f \u00ab%1\u00bb \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u00ab%2\u00bb ConfigView.section.tracker.natcheckenable=\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u043e\u0440\u0442\u0430\u043c \u0443\u0437\u043b\u043e\u0432 \u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c \u0443\u0437\u043b\u044b \u043e \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0445 ConfigView.section.tracker.publishenabledetails=\u041f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0435 ConfigView.section.tracker.publishenablepeerdetails=\u041f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 MyTrackerView.badnat=\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 NAT MyTrackerView.badnat.info=\u0420\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0435/\u0443\u0437\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043f\u0440\u043e\u0448\u043b\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 NAT (\u0435\u0441\u043b\u0438 NAT \u0432\u043a\u043b\u044e\u0447\u0451\u043d) ConfigView.section.tracker.natchecktimeout=\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 (\u0441) ConfigView.section.file.perf.cache.enable=\u041a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0438\u0441\u043a\u043e\u0432\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 ConfigView.section.file.perf.cache.size=\u0420\u0430\u0437\u043c\u0435\u0440 \u043a\u044d\u0448\u0430 \u0432 %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u0417&\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 MainWindow.menu.transfers.startalltransfers=&\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0432\u0441\u0435 MainWindow.menu.transfers.stopalltransfers=\u041e&\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u0441\u0435 MainWindow.menu.transfers.pausetransfers=&\u041f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c MainWindow.menu.transfers.resumetransfers=&\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c ConfigView.label.experimental.osx.kernel.panic.fix=\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0442\u0447 \u0434\u043b\u044f \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f kernel panic \u043d\u0430 \u0434\u0432\u0443\u0445\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0441 Mac OS X [\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a] SystemTray.menu.pausetransfers=\u041f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 SystemTray.menu.resumetransfers=\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.section.file.truncate.too.large=\u0420\u0430\u0437\u0440\u0435\u0437\u0430\u0442\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0444\u0430\u0439\u043b\u044b \u043d\u0430 \u043c\u0435\u043d\u044c\u0448\u0438\u0435 \u043f\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0443 ConfigView.section.file.perf.cache.trace=\u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0446\u0435\u043b\u044f\u0445 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438 ConfigView.section.interface.enabletray=\u0417\u043d\u0430\u0447\u043e\u043a \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 [\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a] PeerManager.status.error=\u041e\u0448\u0438\u0431\u043a\u0430 Stats.title.full=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 TransferStatsView.title.full=\u041e\u0431\u043c\u0435\u043d \u0434\u0430\u043d\u043d\u044b\u043c\u0438 CacheView.title.full=\u041a\u044d\u0448 CacheView.general.size=\u0412\u0441\u0435\u0433\u043e CacheView.general.inUse=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f CacheView.general.title=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043a\u044d\u0448\u0435 CacheView.reads.title=\u0427\u0442\u0435\u043d\u0438\u0435 CacheView.reads.fromFile=\u0418\u0437 \u0444\u0430\u0439\u043b\u0430 CacheView.reads.fromCache=\u0418\u0437 \u043a\u044d\u0448\u0430 CacheView.reads.hits=\u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u0439 CacheView.writes.title=\u0417\u0430\u043f\u0438\u0441\u044c CacheView.writes.toCache=\u0412 \u043a\u044d\u0448 CacheView.writes.toFile=\u0412 \u0444\u0430\u0439\u043b CacheView.writes.hits=\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043e CacheView.speeds.title=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 CacheView.speeds.reads=\u0427\u0442\u0435\u043d\u0438\u0435 CacheView.speeds.writes=\u0417\u0430\u043f\u0438\u0441\u044c CacheView.speeds.fromCache=\u0418\u0437/\u0432 \u043a\u044d\u0448 CacheView.speeds.fromFile=\u0418\u0437/\u0432 \u0444\u0430\u0439\u043b CacheView.reads.amount=\u0412\u0441\u0435\u0433\u043e CacheView.reads.avgsize=\u0421\u0440\u0435\u0434\u043d\u0438\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 openUrl.referrer=\u0410\u0434\u0440\u0435\u0441 \u0441\u0441\u044b\u043b\u0430\u044e\u0449\u0435\u0439\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b: openUrl.referrer.info=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0430\u0439\u0442\u043e\u0432 ConfigView.label.maxuploadspeedseeding=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u0434\u0430\u0447\u0435 ConfigView.label.transfer.ignorepeerports=\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0437\u043b\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u043e\u0440\u0442\u0430\u043c\u0438 (\u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c: \u00ab;\u00bb, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 0;25) ConfigView.section.proxy.enable_socks.peer=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u043a\u0441\u0438 \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u0443\u0437\u043b\u0430\u043c\u0438 (\u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f) [\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a] ConfigView.section.proxy.peer.informtracker=\u0418\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u043a\u0435\u0440 \u043e\u0431 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0438 ConfigView.section.proxy.socks.version=\u0412\u0435\u0440\u0441\u0438\u044f SOCKS PiecesView.legend.written=\u0417\u0430\u043f\u0438\u0441\u0430\u043d PiecesView.legend.requested=\u0417\u0430\u043f\u0440\u043e\u0448\u0435\u043d PiecesView.legend.downloaded=\u041f\u0440\u0438\u043d\u044f\u0442\u043e, \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f PiecesView.legend.incache=\u0414\u0430\u043d\u043d\u044b\u0445 \u0432 \u043a\u044d\u0448\u0435 PiecesView.typeItem.0=\u041c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0439 PiecesView.typeItem.1=\u0411\u044b\u0441\u0442\u0440\u044b\u0439 PiecesView.type=\u0422\u0438\u043f Security.jar.tools_not_found=\u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u0435 JAR \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c - \u0444\u0430\u0439\u043b 'tools.jar' \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d \u0432 %1. \u0421\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b->\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438->\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438. Security.jar.signfail=\u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u0435 JAR \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c - %1 ConfigView.section.security.toolsinfo=\u041f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b JAR \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439; \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0435\u0431-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043d\u0430 Swing (\u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e).\n\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0430\u0439\u043b JAR, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u043c\u0435\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0444\u0430\u0439\u043b\u0443 \u00abtools.jar\u00bb, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u043f\u0430\u043a\u0435\u0442\u043e\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 Sun JDK (\u043d\u0435 \u043f\u0443\u0442\u0430\u0442\u044c \u0441 JRE).\n\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e JRE, \u0432\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0435\u0449\u0451 \u0438 JDK.\n\u041e\u0431\u044b\u0447\u043d\u043e Vuze \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e. \u041e\u0434\u043d\u0430\u043a\u043e, \u0435\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u043d\u0430\u0439\u0442\u0438 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c, \u043d\u0438\u0436\u0435 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0443, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0443\u044e \u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b. ConfigView.section.security.toolsdir=\u041f\u0430\u043f\u043a\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f 'tools.jar' ConfigView.section.security.choosetoolssavedir=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0443, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0443\u044e 'tools.jar' authenticator.torrent=\u0422\u043e\u0440\u0440\u0435\u043d\u0442 ConfigView.section.proxy.peer.same=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u043d\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u043a\u0441\u0438 \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u0438 \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u0443\u0437\u043b\u0430\u043c\u0438 ConfigView.section.connection.network.max.simultaneous.connect.attempts=\u041c\u0430\u043a\u0441. \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439, \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c\u044b\u0445 Vuze \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438.\n\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: Windows XP SP2 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0438\u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0432 10 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439.\n\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e - 8. ConfigView.section.file.perf.cache.size.explain=\u041a\u044d\u0448 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u0434\u0438\u0441\u043a\u0443. \u041f\u043e\u043a\u0430 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 java '-XX:MaxDirectMemorySize' \u0447\u0442\u043e\u0431\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0443\u044e \u043f\u0430\u043c\u044f\u0442\u044c \u0434\u043b\u044f \u043a\u044d\u0448\u0430 \u0438 \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435 %1 \u043d\u0438\u0436\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u0430\u0448\u0435\u0439 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u044b. \u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0434\u043b\u044f \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u044b %2. \u0414\u043b\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439, \u043a\u0430\u043a \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u0441\u043c. MemoryUsage \u043d\u0430 wiki- \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435: %3. \u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043e\u0448\u0438\u0431\u043a\u0435 'out of memory'. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f 32MB. MyTorrentsView.menu.setSpeed.unlimit=\u0411\u0435\u0437 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f MyTorrentsView.menu.setSpeed.unlimited=\u0411\u0435\u0437 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f MyTorrentsView.menu.setSpeed.disable=\u0417\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0443 MyTorrentsView.menu.setSpeed.disabled=\u0412\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043e MyTorrentsView.menu.setSpeed.in=\u0432 MyTorrentsView.menu.setSpeed.slots=\u044f\u0447\u0435\u0439\u043a\u0430\u0445 GeneralView.label.maxuploadspeed=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 GeneralView.label.maxuploadspeed.tooltip=\u043c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] MyTorrents.items.UpSpeedLimit.disabled=\u041d\u0435\u0442 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 MyTorrents.items.UpSpeedLimit.unlimited=\u0411\u0435\u0437 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f TableColumn.header.maxupspeed=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 TableColumn.header.maxupspeed.info=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 ConfigView.section.file.perf.cache.enable.write=\u041a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u043d\u0430 \u0434\u0438\u0441\u043a, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0447\u0442\u0435\u043d\u0438\u044f \u0441 \u0434\u0438\u0441\u043a\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0447\u0430\u0441\u0442\u0435\u0439 ConfigView.section.file.perf.cache.enable.read=\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043e\u043f\u0435\u0440\u0435\u0436\u0430\u044e\u0449\u0435\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0439 \u043a \u0434\u0438\u0441\u043a\u0443 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.section.tracker.separatepeerids=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0443\u0437\u043b\u0430 \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u0438 \u0434\u043b\u044f \u043e\u0431\u043c\u0435\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 ConfigView.section.tracker.separatepeerids.info=\u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e\u0441\u0442\u044c \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f/\u0440\u0430\u0437\u0434\u0430\u0447\u0438 \n\u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e\u0433\u043e \u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.interface.wavlocation=\u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 .wav ConfigView.section.interface.wavlocation.info=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u0430\u0439\u043b .wav \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u0443\u0441\u0442\u044b\u043c \u0434\u043b\u044f \u0437\u0432\u0443\u043a\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e ConfigView.section.tracker.server=\u0421\u0435\u0440\u0432\u0435\u0440 ConfigView.section.tracker.client=\u041a\u043b\u0438\u0435\u043d\u0442 ConfigView.section.tracker.client.connecttimeout=\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (\u0441) ConfigView.section.tracker.client.readtimeout=\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0447\u0442\u0435\u043d\u0438\u044f (\u0441) MainWindow.menu.tools=&\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b FilesView.path=\u041f\u0443\u0442\u044c FilesView.fullpath=\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u0443\u0442\u044c FilesView.remaining=\u041e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0447\u0430\u0441\u0442\u0438 TableColumn.header.trackername=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 TableColumn.header.trackername.info=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u0430, \u0432\u0437\u044f\u0442\u043e\u0435 \u0438\u0437 URL \u0430\u043d\u043e\u043d\u0441\u0430 ConfigView.group.override=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f ConfigView.section.file.perf.cache.notsmallerthan=\u041d\u0435 \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u043c\u0435\u043d\u044c\u0448\u0435, \u0447\u0435\u043c (\u0432 %1) PeersView.menu.blockupload=\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0443 PeersView.menu.kickandban=\u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c PeersView.menu.kickandban.reason=\u0423\u0437\u0435\u043b \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d \u0432\u0440\u0443\u0447\u043d\u0443\u044e PeersView.state=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 PeersView.state.info=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0443\u0437\u043b\u0430 PeersView.state.pending=\u041e\u0436\u0438\u0434\u0430\u0435\u0442 PeersView.state.connecting=\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 PeersView.state.handshake=\u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0441\u0432\u044f\u0437\u0438 PeersView.state.established=\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0451\u043d ConfigView.section.tracker.processinglimits=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f ConfigView.section.tracker.maxgettime=\u041c\u0430\u043a\u0441. \u0432\u0440\u0435\u043c\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 GET (\u0441) [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.tracker.maxgettime.info=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0430\u043d\u043e\u043d\u0441\u043e\u0432 \u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 ConfigView.section.tracker.maxposttimemultiplier=\u041c\u043d\u043e\u0436\u0438\u0442\u0435\u043b\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 GET \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 POST [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.tracker.maxposttimemultiplier.info=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0444\u043e\u0440\u043c \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 ConfigView.section.tracker.maxthreads=\u041c\u0430\u043a\u0441. \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 DownloadManager.error.operationcancancelled=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u0430 Torrent.create.progress.cancelled=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u0430 sharing.progress.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c wizard.maketorrents.autoopen=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f ConfigView.section.sharing.rescanenable=\u041f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 ConfigView.section.sharing.rescanperiod=\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0441) ConfigView.section.connection.advanced=\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0435\u0442\u0438 ConfigView.section.connection.advanced.mtu=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0435\u0434\u0438\u043d\u0438\u0446\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 (MTU) ConfigView.section.connection.advanced.mtu.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0430\u043a\u0435\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u043d \u0432 \u043e\u0434\u043d\u043e\u043c \u043a\u0430\u0434\u0440\u0435 \u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u0442\u044c.\nVuze \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 MTU-40 (MSS) \u0434\u043b\u044f \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u043d\u0430 \u0440\u0430\u0437\u0434\u0430\u0447\u0443.\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f:\n 576 - \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043c\u043d\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439\n1492 - \u0448\u0438\u0440\u043e\u043a\u043e\u043f\u043e\u043b\u043e\u0441\u043d\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 PPPoE \n1500 - Ethernet, DSL \u0438 \u0448\u0438\u0440\u043e\u043a\u043e\u043f\u043e\u043b\u043e\u0441\u043d\u044b\u0445 \u043a\u0430\u0431\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 ConfigView.section.connection.advanced.SO_RCVBUF=\u0420\u0430\u0437\u043c\u0435\u0440 SO_RCVBUF \u0434\u043b\u044f \u0441\u043e\u043a\u0435\u0442\u0430 [0: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u041e\u0421] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 SO_RCVBUF (\u0432 \u0431\u0430\u0439\u0442\u0430\u0445), \u0442.\u0435. \u0440\u0430\u0437\u043c\u0435\u0440 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431 \u043a\u0430\u0434\u0440\u0430 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 TCP.\nVuze \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u041e\u0421 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.\n\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0432 Linux \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0443\u0434\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f. ConfigView.section.connection.advanced.SO_SNDBUF=\u0420\u0430\u0437\u043c\u0435\u0440 SO_SNDBUF \u0434\u043b\u044f \u0441\u043e\u043a\u0435\u0442\u0430 [0: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u041e\u0421] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 SO_SNDBUF (\u0432 \u0431\u0430\u0439\u0442\u0430\u0445), \u0442.\u0435. \u0440\u0430\u0437\u043c\u0435\u0440 \u043a\u0430\u0434\u0440\u0430 \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 TCP.\nVuze \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u041e\u0421 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.\n\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0432 Linux \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0443\u0434\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f. ConfigView.section.connection.advanced.IPDiffServ=\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 DiffServ \u0434\u043b\u044f \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 (\u043f\u043e\u043b\u0435 TOS) ConfigView.section.connection.advanced.IPDiffServ.tooltip=\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 DiffServ \u043f\u043e\u043b\u044f type-of-service (TOS) \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 IP \u0434\u043b\u044f \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432.\n\u0428\u0435\u0441\u0442\u043d\u0430\u0434\u0446\u0430\u0442\u0435\u0440\u0438\u0447\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u0441 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c \u00ab0x\u00bb, \u0442.\u0435. 0x10.\nVuze \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u041e\u0421 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.\n\u0417\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0442\u0435\u0432\u044b\u0445 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u0432 \u043c\u043e\u0433\u0443\u0442 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u2014 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u041e\u0421 \u0438 \u0432\u0435\u0440\u0441\u0438\u0438 JRE. ConfigView.section.interface.confirm_torrent_removal=\u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 ConfigView.section.interface.confirm_torrent_removal.tooltip=\u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u0438\u0437 "\u041c\u043e\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b" MyTorrentsView.confirm_torrent_removal=\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0442\u043e\u0440\u0440\u0435\u043d\u0442?\n TableColumn.header.seed_to_peer_ratio=\u0421\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445/\u0443\u0437\u043b\u043e\u0432 TableColumn.header.seed_to_peer_ratio.info=\u0418\u0442\u043e\u0433\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445/\u0443\u0437\u043b\u043e\u0432 \u0434\u043b\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f PeersView.connected_time=\u0412\u0440\u0435\u043c\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f PeersView.connected_time.info=\u041e\u0431\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u0443\u0437\u043b\u043e\u043c ConfigView.section.interface.display.add_torrents_silently=\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0431\u0435\u0437 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f ConfigView.section.interface.display.add_torrents_silently.tooltip=\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0432 \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0431\u0435\u0437 \u043f\u043e\u043a\u0430\u0437\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 Azureus. TableColumn.header.maxdownspeed=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 TableColumn.header.maxdownspeed.info=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 \u044d\u0442\u043e\u0433\u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 PeersGraphicView.title=\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 ConfigView.section.tracker.passwordwebhttpsonly=\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 HTTPS TableColumn.header.torrentpath=\u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 TableColumn.header.torrentpath.info=\u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 ConfigView.section.sharing.torrentcomment=\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 ConfigView.label.copyanddeleteratherthanmove=\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u0430 \u043d\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043e\u0434\u043d\u0443 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e (\u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u043e\u0442\u0435\u0440\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445) ConfigView.label.openstatsonstart=\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 swt.install.window.title=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 Vuze swt.install.window.ok=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c swt.install.window.header=\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0432\u044b\u0431\u0440\u0430\u043d\u044b \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438: swt.uninstall.window.title=\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 Vuze swt.uninstall.window.ok=\u0423\u0434\u0430\u043b\u0438\u0442\u044c swt.uninstall.window.header=\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0432\u044b\u0431\u0440\u0430\u043d\u044b \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f: installPluginsWizard.title=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 installPluginsWizard.mode.title=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u043f\u043e\u0441\u043e\u0431 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 installPluginsWizard.mode.list=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0441 sourceforge.net installPluginsWizard.list.title=\u0421\u043f\u0438\u0441\u043e\u043a \u043c\u043e\u0434\u0443\u043b\u0435\u0439, \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043a \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 installPluginsWizard.list.loading=\u041f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435, \u043f\u043e\u043a\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u043c\u043e\u0434\u0443\u043b\u0435\u0439. installPluginsWizard.list.loaded=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043c\u043e\u0434\u0443\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c. installPluginsWizard.list.name=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 installPluginsWizard.list.version=\u0412\u0435\u0440\u0441\u0438\u044f installPluginsWizard.list.description=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u044f installPluginsWizard.finish.title=\u0418\u0434\u0451\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 installPluginsWizard.finish.explanation=\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u041c\u0430\u0441\u0442\u0435\u0440\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f\n\n\u041f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435, \u043f\u043e\u043a\u0430 \u043e\u043d \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0441\u044f.\n\n\u0414\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0445\u043e\u0434\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438, \u0434\u0432\u0430\u0436\u0434\u044b \u0449\u0451\u043b\u043a\u043d\u0438\u0442\u0435 \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. installPluginsWizard.details.loading=\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438, \u043f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435... installPluginsWizard.mode.file=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 installPluginsWizard.installMode.title=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u043f\u043e\u0441\u043e\u0431 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 installPluginsWizard.installMode.user=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f installPluginsWizard.installMode.shared=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 installPluginsWizard.file.title=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043c\u043e\u0434\u0443\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c installPluginsWizard.file.file=\u0424\u0430\u0439\u043b: installPluginsWizard.file.invalidfile=\u0414\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043c\u043e\u0434\u0443\u043b\u0435\u043c Vuze. installPluginsWizard.file.no_such_file=\u041d\u0435\u0442 \u0444\u0430\u0439\u043b\u0430 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c. installPluginsWizard.file.browse=\u041e\u0431\u0437\u043e\u0440... uninstallPluginsWizard.title=\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 uninstallPluginsWizard.list.title=\u0421\u043f\u0438\u0441\u043e\u043a \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 uninstallPluginsWizard.list.loaded=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043c\u043e\u0434\u0443\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0434\u0430\u043b\u0438\u0442\u044c. installPluginsWizard.list.nullversion=\u0412\u0435\u0440\u0441\u0438\u044f \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u0430 uninstallPluginsWizard.finish.title=\u0418\u0434\u0435\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 uninstallPluginsWizard.finish.explanation=\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u041c\u0430\u0441\u0442\u0435\u0440\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439. MainWindow.menu.plugins.installPlugins=\u041c\u0430\u0441\u0442\u0435\u0440 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438... MainWindow.menu.plugins.uninstallPlugins=\u041c\u0430\u0441\u0442\u0435\u0440 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f... ConfigView.section.ipfilter.totalIPs=%1 IP \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0432\u0441\u0435\u0433\u043e, %2 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435. update.instance.install=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 update.instance.uninstall=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b update.instance.update=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 MainWindow.status.update.tooltip=\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435, \u0434\u0432\u0430\u0436\u0434\u044b \u0449\u0451\u043b\u043a\u043d\u0438\u0442\u0435 \u0437\u0434\u0435\u0441\u044c updater.progress.window.title=\u0422\u0435\u043a\u0443\u0449\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 updater.progress.window.info=\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u00ab\u041f\u0440\u0435\u0440\u0432\u0430\u0442\u044c\u00bb \u0434\u043b\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 Button.abort=\u041f\u0440\u0435\u0440\u0432\u0430\u0442\u044c ConfigView.section.ipfilter.enablebanning=\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0437\u043b\u044b, \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043f\u043e\u0441\u044b\u043b\u0430\u044e\u0449\u0438\u0435 \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 Network.alert.acceptfail=\u0421\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 %1, %2 \u2014 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430. \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432\u0430\u0448\u0435\u0433\u043e \u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0430; \u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u0435\u0441\u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. MyShares.column.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f UpdateWindow.restartLater=\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u043e\u0437\u0436\u0435 MainWindow.menu.file.restart=\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Vuze MainWindow.dialog.restartconfirmation.title=\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a Vuze MainWindow.dialog.restartconfirmation.text=\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Vuze deletetorrent.message1=\u0412\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0435\u0441\u044c \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u0434\u043b\u044f:\n deletetorrent.message2=\n\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c? ConfigView.label.prioritizemostcompletedfiles=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0434\u043b\u044f \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 splash.plugin.init=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f: splash.plugin.UIinit=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430: %1 ConfigView.section.style.osx_small_fonts=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u0435 \u0448\u0440\u0438\u0444\u0442\u044b [\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a] ConfigView.section.tracker.tcpnonblocking=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0432\u0432\u043e\u0434-\u0432\u044b\u0432\u043e\u0434 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b TCP-\u0442\u0440\u0435\u043a\u0435\u0440\u0430. \u0412\u044b\u0431\u043e\u0440 \u044d\u0442\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\n\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0430 \u0434\u043b\u044f \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0430. \u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c! ConfigView.section.tracker.nonblocking=\u0410\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c ConfigView.section.tracker.nonblockingconcmax=\u041c\u0430\u043a\u0441. \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] MyTorrentsView.menu.exportmenu=\u042d\u043a\u0441\u043f\u043e\u0440\u0442 MyTorrentsView.menu.exporttorrent=\u0422\u043e\u0440\u0440\u0435\u043d\u0442... ConfigView.group.scrape=\u0417\u0430\u043f\u0440\u043e\u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 ConfigView.section.tracker.client.scrapeinfo=\u0412\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043e\u0447\u0435\u0440\u0451\u0434\u043d\u043e\u0441\u0442\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u043d\u0435 \u0441\u043c\u043e\u0433\u0443\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0435\u0440\u0451\u0442\u0441\u044f \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. ConfigView.section.tracker.client.scrapeenable=\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 ConfigView.section.tracker.client.scrapestoppedenable=\u041f\u043e\u0441\u044b\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 Scrape.status.disabled=\u0417\u0430\u043f\u0440\u043e\u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0451\u043d MyTorrentsView.menu.explore=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0444\u0430\u0439\u043b MyTorrentsView.menu.explore._mac=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432 Finder MyTorrentsView.menu.explore._windows=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u043f\u0440\u043e\u0432\u043e\u0434\u043d\u0438\u043a\u0435 wizard.maketorrents.autohost=\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0443 \u043d\u0430 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u043c \u0442\u0440\u0435\u043a\u0435\u0440\u0435 ConfigView.label.overrideip=\u041f\u043e\u0441\u044b\u043b\u0430\u0435\u043c\u044b\u0439 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u0430\u0434\u0440\u0435\u0441(\u0430) IP (\u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c: \u00ab;\u00bb) ConfigView.label.overrideip.tooltip=\u0421\u043e\u043e\u0431\u0449\u0430\u0442\u044c \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0430\u0434\u0440\u0435\u0441\u0430\u0445 IP, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u044b. \u041e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u043e\u043b\u0435 \u043f\u0443\u0441\u0442\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c. ConfigView.section.connection.group.networks=\u0421\u0435\u0442\u0438 ConfigView.section.connection.group.networks.info=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0435 \u0442\u0438\u043f\u044b \u0441\u0435\u0442\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u043c\u0435\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 ConfigView.section.connection.networks.prompt=\u0421\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e\u0433\u043e \u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.connection.networks.Public=\u041f\u0443\u0431\u043b\u0438\u0447\u043d\u0430\u044f \u0441\u0435\u0442\u044c IP (\u043d\u0435 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0430\u044f) ConfigView.section.connection.networks.I2P=\u0421\u0435\u0442\u044c I2P ConfigView.section.connection.networks.Tor=\u0421\u0435\u0442\u044c The Onion Router (Tor) TableColumn.header.networks=\u0421\u0435\u0442\u0438 TableColumn.header.networks.info=\u0421\u0435\u0442\u0438, \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u0431\u043c\u0435\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0442\u0438\u043f\u0430 \u0443\u0437\u0435\u043b-\u0443\u0437\u0435\u043b Scrape.status.networkdisabled=\u0421\u0435\u0442\u044c \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430 ConfigView.section.tracker.server.group.networks=\u0421\u0435\u0442\u0438 ConfigView.section.tracker.server.group.networks.info=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0435\u0442\u0438, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u0440\u0435\u043a\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0443\u0437\u043b\u044b window.networkselection.title=\u0412\u044b\u0431\u043e\u0440 \u0441\u0435\u0442\u0438 window.networkselection.info=\u0422\u043e\u0440\u0440\u0435\u043d\u0442, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u043c (\u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0435\u0442\u0438.\n\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043d\u0443\u0436\u043d\u044b\u0435 \u0441\u0435\u0442\u0438 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441 \u0434\u0430\u043d\u043d\u044b\u043c \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u043c \u0438 \u0443\u0437\u043b\u0430\u043c\u0438.\n\u0415\u0441\u043b\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u044b\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0438 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u044b\u0435 \u0441\u0435\u0442\u0438, \u0438 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u0435\u0442\u0438.\n\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0439 \u0441\u0435\u0442\u0438, \u043e\u0434\u043d\u0430\u043a\u043e, \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u043f\u043e\u0442\u0435\u0440\u0435 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e\u0441\u0442\u0438! window.networkselection.description=\u0422\u043e\u0440\u0440\u0435\u043d\u0442: plugins.basicview.clear=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c ConfigView.section.connection.group.peersources=\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0443\u0437\u043b\u043e\u0432 ConfigView.section.connection.group.peersources.info=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0443\u0437\u043b\u043e\u0432 \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e ConfigView.section.connection.peersource.Tracker=\u041e\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.connection.peersource.DHT=\u0414\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0438\u043d\u0433 ConfigView.section.connection.peersource.PeerExchange=\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u043c \u0443\u0437\u043b\u043e\u043c ConfigView.section.connection.peersource.Plugin=\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0434\u0443\u043b\u044f ConfigView.section.connection.peersource.Incoming=\u0412\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f PeersView.source=\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a PeersView.source.info=\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u044d\u0442\u043e\u0433\u043e \u0443\u0437\u043b\u0430 TableColumn.header.peersources=\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0443\u0437\u043b\u043e\u0432 TableColumn.header.peersources.info=\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0443\u0437\u043b\u043e\u0432, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u044b \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f wizard.tracker.dht=\u0414\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 (\u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 Vuze) MyTorrentsView.menu.advancedmenu=\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e MyTorrentsView.menu.networks=\u0421\u0435\u0442\u0438 MyTorrentsView.menu.peersource=\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0443\u0437\u043b\u043e\u0432 ConfigView.section.sharing.permitdht=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0442\u044c \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0438\u043d\u0433, \u043a\u043e\u0433\u0434\u0430 \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d ConfigView.section.sharing.protocol=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0434\u043b\u044f \u043e\u0431\u0449\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0430) PeersView.Messaging=\u041e\u0431\u043c\u0435\u043d \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 PeersView.Messaging.info=\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043e\u0431\u043c\u0435\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438. ConfigView.label.queue.newseedsmovetop=\u041f\u043e\u043c\u0435\u0449\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u043d\u0430 \u0441\u0430\u043c\u044b\u0439 \u0432\u0435\u0440\u0445 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.label.seeding.firstPriority.ignore.info=\u041f\u043e\u043c\u043d\u0438\u0442\u0435, \u0447\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u043f\u0440\u0430\u0432\u0438\u043b \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430,\n\u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0441\u044f. ConfigView.label.seeding.firstPriority.ignore=\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u0441\u043e\u043a\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0434\u043b\u044f: ConfigView.label.seeding.firstPriority.ignoreSPRatio=\u0422\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0441 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0435:\u0443\u0437\u043b\u044b \u0432\u044b\u0448\u0435 ConfigView.label.seeding.firstPriority.ignore0Peer=\u0422\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0441 0 \u0443\u0437\u043b\u043e\u0432 ConfigView.section.tracker.sendjavaversionandos=\u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0432\u0435\u0440\u0441\u0438\u0438 Java \u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 MagnetPlugin.contextmenu.exporturi=\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c Magnet URI \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430 ConfigView.section.plugins.dht=\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u0411\u0414 dht.info=\u041a\u0440\u043e\u043c\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u043e\u0447\u0435\u0433\u043e, \u044d\u0442\u043e\u0442 \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0438\u043d\u0433. \u0415\u0433\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0441\u043d\u0438\u0437\u0438\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 dht.enabled=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0443\u044e \u0411\u0414 dht.portdefault=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0440\u0442 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e dht.port=\u041f\u043e\u0440\u0442 UDP \u0434\u043b\u044f \u0411\u0414 dht.execute.command=\u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b dht.execute.info=\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b dht.execute=\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c dht.logging=\u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c ConfigView.section.plugins.dhttracker=\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 dhttracker.tracknormalwhenoffline=\u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b, \u043a\u043e\u0433\u0434\u0430 \u0438\u0445 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d ConfigView.section.file.nativedelete._mac=\u0423\u0434\u0430\u043b\u044f\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0443 ConfigView.section.file.nativedelete._windows=\u0423\u0434\u0430\u043b\u044f\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0443 ConfigView.section.logging.generatediagnostics=\u0412\u044b\u0434\u0430\u0442\u044c ConfigView.section.logging.netinfo=\u0412\u044b\u0434\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0441\u0435\u0442\u0438 ConfigView.section.logging.statsinfo=\u0412\u044b\u0434\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 ConfigView.section.logging.generatediagnostics.info=\u0412\u044b\u0434\u0430\u0442\u044c \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0435\u0451 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430 \u0438 \u0436\u0443\u0440\u043d\u0430\u043b (\u0435\u0441\u043b\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043e) ConfigView.section.sharing.privatetorrent=\u0417\u0430\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 - \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0443\u0437\u043b\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 MainWindow.menu.tools.nattest=\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c &NAT/\u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u044d\u043a\u0440\u0430\u043d Button.apply=\u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c Button.close=\u0417\u0430\u043a\u0440\u044b\u0442\u044c window.welcome.title=\u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u0432 Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u044f \u043a \u0432\u044b\u043f\u0443\u0441\u043a\u0443 dht.reseed.label=\u041e\u0431\u044b\u0447\u043d\u043e \u043e\u0447\u0438\u0449\u0435\u043d\u0438\u0435 \u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0411\u0414 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. \u041e\u0434\u043d\u0430\u043a\u043e, \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043d\u0435\u043c\u043d\u043e\u0433\u043e, \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0430 \u0434\u043b\u044f \u0440\u0435\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438.\n\u041e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u043e\u043b\u0435 \u043f\u0443\u0441\u0442\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0443\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043e\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u043e\u0432 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 IP \u0438 \u043f\u043e\u0440\u0442, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043e\u0442 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430. dht.reseed.group=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c dht.reseed.ip=\u0410\u0434\u0440\u0435\u0441 IP dht.reseed.port=\u041f\u043e\u0440\u0442 dht.reseed=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c dht.reseed.info=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0411\u0414 dht.diagnostics.group=\u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 DHTView.title.full=\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u0411\u0414 DHTView.title.fullcvs=\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u0411\u0414 CVS DHTView.general.title=\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 DHTView.general.uptime=\u0412\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b: DHTView.general.users=\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439: DHTView.general.nodes=\u0423\u0437\u043b\u043e\u0432: DHTView.general.leaves=\u041a\u043e\u043d\u0446\u0435\u0432\u044b\u0445: DHTView.general.contacts=\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439: DHTView.general.replacements=\u0417\u0430\u043c\u0435\u043d: DHTView.general.live=\u0416\u0438\u0432\u044b\u0445: DHTView.general.unknown=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0445: DHTView.general.dying=\u041c\u0435\u0440\u0442\u0432\u044b\u0445: DHTView.transport.title=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043e\u0431\u043c\u0435\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 DHTView.transport.packets=\u041f\u0430\u043a\u0435\u0442\u043e\u0432 DHTView.transport.bytes=\u0411\u0430\u0439\u0442 DHTView.transport.received=\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043e DHTView.transport.sent=\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e DHTView.transport.in=\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435: DHTView.transport.out=\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430: DHTView.operations.title=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 DHTView.operations.sent=\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e DHTView.operations.ok=\u0423\u0434\u0430\u0447\u043d\u043e DHTView.operations.failed=\u041d\u0435\u0443\u0434\u0430\u0447\u043d\u043e DHTView.operations.received=\u041f\u0440\u0438\u043d\u044f\u0442\u043e DHTView.operations.ping=\u041e\u043f\u0440\u043e\u0441 DHTView.operations.findNode=\u041f\u043e\u0438\u0441\u043a \u0443\u0437\u043b\u0430 DHTView.operations.findValue=\u041f\u043e\u0438\u0441\u043a \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f DHTView.operations.store=\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 DHTView.activity.title=\u0410\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c DHTView.activity.status=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 DHTView.activity.status.true=\u0412 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 DHTView.activity.status.false=\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f DHTView.activity.type=\u0422\u0438\u043f DHTView.activity.type.1=\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 DHTView.activity.type.2=\u0412\u043d\u0435\u0448\u043d\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 DHTView.activity.type.3=\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 DHTView.activity.type.4=\u0412\u043d\u0435\u0448\u043d\u0435\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 DHTView.activity.target=\u0426\u0435\u043b\u044c DHTView.activity.details=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 DHTView.db.title=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 DHTView.db.keys=\u041a\u043b\u044e\u0447\u0438 DHTView.db.values=\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f DHTView.db.local=\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u043e DHTView.db.direct=\u041d\u0430\u043f\u0440\u044f\u043c\u0443\u044e DHTView.db.indirect=\u041a\u043e\u0441\u0432\u0435\u043d\u043d\u043e DHTView.db.divfreq=\u0427\u0430\u0441\u0442\u043e\u0442\u0430 Div. DHTView.db.divsize=\u0420\u0430\u0437\u043c\u0435\u0440 Div. MainWindow.dht.status.tooltip=\u041a\u043e\u0433\u0434\u0430 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430 \u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u0411\u0414, \u0437\u0434\u0435\u0441\u044c \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u043e\u0447\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 MainWindow.dht.status.disabled=\u0412\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043e MainWindow.dht.status.failed=DHT \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c MainWindow.dht.status.initializing=\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f MainWindow.dht.status.users=%1 \u0443\u0437\u043b\u043e\u0432 MainWindow.dht.status.unreachable=DHT \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u044b\u043c \u044d\u043a\u0440\u0430\u043d\u043e\u043c MainWindow.dht.status.unreachabletooltip=\u0412\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u0440\u0442\u043e\u0432 UDP \u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0439 \u0411\u0414 (\u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u044d\u043a\u0440\u0430\u043d \u0438\u043b\u0438 NAT) MyTorrentsView.menu.setUpSpeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 MyTorrentsView.menu.setDownSpeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 ConfigView.section.tracker.client.showwarnings=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f, \u0432\u044b\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u043c dht.advanced=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 dht.advanced.group=\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 dht.advanced.label=\u041c\u0435\u043d\u044f\u0439\u0442\u0435 \u044d\u0442\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u0432\u044b \u0434\u0435\u043b\u0430\u0435\u0442\u0435 dht.override.ip=\u041f\u043e\u0434\u043c\u0435\u043d\u044f\u0442\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0430\u0434\u0440\u0435\u0441 IP ConfigView.section.logging.loggerenable=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0436\u0443\u0440\u043d\u0430\u043b ConfigView.section.ipfilter.blockbanning=\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0438\u0437 256 \u0430\u0434\u0440\u0435\u0441\u043e\u0432, \u0435\u0441\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0443\u0436\u0435 \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043e MyTrackerView.passive=\u041f\u0430\u0441\u0441\u0438\u0432\u043d\u044b\u0439 TableColumn.header.swarm_average_speed=\u0421\u0440\u0435\u0434\u043d\u044f\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f TableColumn.header.swarm_average_speed.info=\u0421\u0440\u0435\u0434\u043d\u044f\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0443\u0437\u043b\u043e\u0432 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f TableColumn.header.comment=\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 TableColumn.header.comment.info=\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 TableColumn.header.commenticon=\u0417\u043d\u0430\u0447\u043e\u043a \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f TableColumn.header.commenticon.info=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u043e\u043a, \u0435\u0441\u043b\u0438 \u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0435\u0441\u0442\u044c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f MyTrackerView.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f MainWindow.menu.file.open.torrentfortracking=\u0422\u043e\u0440\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b... (\u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430) VivaldiView.title.full=\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u0412\u0438\u0432\u0430\u043b\u044c\u0434\u0438 VivaldiView.title.fullcvs=\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u0412\u0438\u0432\u0430\u043b\u044c\u0434\u0438 CVS VivaldiView.title.full_v6=\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u0412\u0438\u0432\u0430\u043b\u044c\u0434\u0438 IPv6 MyTrackerView.date_added=\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d ConfigView.section.tracker.portbackup=\u0420\u0435\u0437\u0435\u0440\u0432\u043d\u044b\u0435 \u043f\u043e\u0440\u0442\u044b (\u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c: \u00ab;\u00bb) ConfigView.label.playfilespeech=\u041f\u0440\u043e\u0438\u0437\u043d\u043e\u0441\u0438\u0442\u044c \u0441\u0438\u043d\u0442\u0435\u0437\u0430\u0442\u043e\u0440\u043e\u043c \u0433\u043e\u043b\u043e\u0441\u0430 \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044e \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 ConfigView.label.playfilespeech.info=\u0421\u0438\u043d\u0442\u0435\u0437\u0430\u0442\u043e\u0440 \u0433\u043e\u043b\u043e\u0441\u0430 \u043f\u043e\u043a\u0430 \u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438\u043c \u044f\u0437\u044b\u043a\u043e\u043c ConfigView.label.playfilefinished=\u0417\u0432\u0443\u043a \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 ConfigView.label.backupconfigfiles=\u0414\u0435\u043b\u0430\u0442\u044c \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u044b\u0435 \u043a\u043e\u043f\u0438\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u044f ConfigView.section.tracker.client.scrapesingleonly=\u041d\u0435 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u043e \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c (\u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u043e\u0448\u0438\u0431\u043a\u0438 414: URL too long) dht.ipfilter.log=\u0412\u0435\u0441\u0442\u0438 \u0436\u0443\u0440\u043d\u0430\u043b \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0439 IP \u0444\u0438\u043b\u044c\u0442\u0440\u0430 ConfigView.label.seeding.addForSeedingDLCopyCount=\u0421\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u00ab\u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438\u00bb \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u043c\u0435\u044e\u0442 \u0434\u0430\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043f\u0438\u0439 ActivityView.legend.limit=\u041f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u0430\u044f ActivityView.legend.achieved=\u041c\u043e\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f ActivityView.legend.overhead=\u0414\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 ActivityView.legend.peeraverage=\u0421\u0440\u0435\u0434\u043d\u044f\u044f ActivityView.legend.swarmaverage=\u0421\u0440\u0435\u0434\u043d\u044f\u044f \u043f\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044e ActivityView.legend.trimmed=\u0417\u0430 \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0430 (\u043f\u0443\u043d\u043a\u0442\u0438\u0440) MyTorrentsView.menu.movemenu=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b MyTorrentsView.menu.movedata=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438... MyTorrentsView.menu.movetorrent=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b... MyTorrentsView.menu.movedata.dialog=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043d\u043e\u0432\u043e\u0435 \u043c\u0435\u0441\u0442\u043e DHTView.operations.data=\u0414\u0430\u043d\u043d\u044b\u0435 DHTView.general.reachable=\u0414\u043e\u0441\u0442\u0443\u043f\u0435\u043d: ConfigView.label.queue.maxactivetorrentswhenseeding=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c, \u0435\u0441\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u0434\u0430\u0447\u0430 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] Views.plugins.IRC.title=IRC \u2014 \u0441\u043b\u0443\u0436\u0431\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0432 \u0441\u0435\u0442\u0438 Formats.units.persec=/\u0441 Formats.units.TiB=\u0422\u0438\u0411 Formats.units.Tibit=\u0422\u0438\u0431\u0438\u0442 Formats.units.TB=\u0422\u0411 Formats.units.Tbit=\u0422\u0431\u0438\u0442 Formats.units.GiB=\u0413\u0438\u0411 Formats.units.Gibit=\u0413\u0438\u0431\u0438\u0442 Formats.units.GB=\u0413\u0411 Formats.units.Gbit=\u0413\u0431\u0438\u0442 Formats.units.MiB=\u041c\u0438\u0411 Formats.units.Mibit=\u041c\u0438\u0431\u0438\u0442 Formats.units.MB=\u041c\u0411 Formats.units.Mbit=\u041c\u0431\u0438\u0442 Formats.units.KiB=\u041a\u0438\u0411 Formats.units.Kibit=K\u0438\u0431\u0438\u0442 Formats.units.kB=\u041a\u0411 Formats.units.KB=\u041a\u0411 Formats.units.kbit=\u043a\u0431\u0438\u0442 Formats.units.B=\u0411 Formats.units.bit=\u0431\u0438\u0442 Formats.units.alot=\u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e !!! ConfigView.section.ipfilter.persistblocking=\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043e \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 IP \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043c\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b FilesView.menu.rename=\u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u041f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 FilesView.menu.rename_only=\u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c FilesView.menu.retarget=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c FilesView.rename.choose.path=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u0438\u043b\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0444\u0430\u0439\u043b FilesView.rename.choose.path.dir=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0438\u043b\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u0430\u043f\u043a\u0443 FilesView.rename.confirm.delete.title=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 FilesView.rename.confirm.delete.text=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 '%1' FilesView.rename.filename.title=\u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b FilesView.rename.filename.text=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u0438\u043c\u044f \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0430 ConfigView.higher.mode.available=\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0440\u0435\u0436\u0438\u043c\u0430\u0445 ConfigView.section.mode=\u0420\u0435\u0436\u0438\u043c ConfigView.section.mode.title=\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f ConfigView.section.mode.beginner=\u041d\u043e\u0432\u0438\u0447\u043e\u043a ConfigView.section.mode.beginner.wiki.definitions=\u0421\u043b\u043e\u0432\u0430\u0440\u044c BitTorrent ConfigView.section.mode.intermediate=\u041e\u043f\u044b\u0442\u043d\u044b\u0439 ConfigView.section.mode.intermediate.wiki.host=\u0420\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 ConfigView.section.mode.intermediate.wiki.publish=\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 ConfigView.section.mode.advanced=\u041f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0439 ConfigView.section.mode.advanced.wiki.main=\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0412\u0438\u043a\u0438 ConfigView.section.mode.beginner.text=\u0412\u0441\u0451, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432.\n\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0440\u0435\u0436\u0438\u043c, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430\u043c\u0438. ConfigView.section.mode.intermediate.text=\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c \u0442\u0440\u0435\u043a\u0435\u0440\u0430.\n\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0440\u0435\u0436\u0438\u043c, \u0435\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432. ConfigView.section.mode.advanced.text=\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u0435\u0442\u0435\u0432\u044b\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c.\n\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0440\u0435\u0436\u0438\u043c, \u0435\u0441\u043b\u0438 \u0432\u044b \u0437\u043d\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 MTU \u0438\u043b\u0438 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0432\u0432\u043e\u0434/\u0432\u044b\u0432\u043e\u0434... Files.column.storagetype=\u0422\u0438\u043f \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 Files.column.fileext=\u0422\u0438\u043f FileItem.storage.linear=\u041b\u0438\u043d\u0435\u0439\u043d\u044b\u0439 FileItem.storage.compact=\u041a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u0439 MessageBoxWindow.rememberdecision=\u0417\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043c\u043e\u0439 \u0432\u044b\u0431\u043e\u0440 ConfigView.section.interface.cleardecisions=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0437\u0430\u043f\u043e\u043c\u043d\u0435\u043d\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0432 \u0434\u0438\u0430\u043b\u043e\u0433\u0430\u0445 ConfigView.section.interface.cleardecisionsbutton=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c ConfigView.section.interface.cleartrackers=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u0432 ConfigView.section.interface.cleartrackersbutton=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c ConfigView.section.interface.clearsavepaths=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0443\u0442\u0435\u0439 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f ConfigView.section.interface.clearsavepathsbutton=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c configureWizard.welcome.usermodes=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0442\u0435\u043f\u0435\u043d\u0438 \u043e\u043f\u044b\u0442\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u041e\u043d\u0438 \u0437\u0430\u0434\u0430\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u044f \u0432\u0430\u043c. FilesView.skip.confirm.delete.text=\u041e\u0431\u0440\u0435\u0437\u0430\u0442\u044c \u0444\u0430\u0439\u043b '%1' \u0434\u043b\u044f \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0438 \u043c\u0435\u0441\u0442\u0430? FilesView.rename.failed.title=\u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u041f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c FilesView.rename.failed.text=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u0435\u0440\u0432\u0430\u043d\u0430, \u0432\u043e\u0437\u043e\u043c\u0436\u043d\u043e \u0438\u0437-\u0437\u0430 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u0446\u0435\u043b\u0438 diagnostics.log_found=Vuze \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0441\u044f \u0430\u0432\u0430\u0440\u0438\u0439\u043d\u043e. \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0436\u0443\u0440\u043d\u0430\u043b\u0435. \u0422\u0430\u043a\u0436\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 \u0412\u0438\u043a\u0438: Vuze Disappears. ManagerItem.paused=\u041f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e Utils.link.visit=\u041f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 ConfigView.section.connection.serverport.wiki=\u041a\u0430\u043a\u0438\u0435 \u043f\u043e\u0440\u0442\u044b \u0432\u044b\u0431\u0440\u0430\u0442\u044c ConfigView.section.transfer.speeds.wiki=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0445\u043e\u0440\u043e\u0448\u0435\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 installPluginsWizard.installMode.info.title=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f installPluginsWizard.installMode.info.text=\u041c\u043e\u0434\u0443\u043b\u0438 \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b \u0434\u043b\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b Vuze. \u041e\u043d\u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b, \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f.\n\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0435\u0433\u043e.\n\u0411\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0432\u043f\u043e\u043b\u043d\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043d\u043e \u0432\u0441\u0451 \u0436\u0435 \u043d\u0435 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0430\u0439\u0442\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u043c\u0438 \u043c\u043e\u0434\u0443\u043b\u044f\u043c\u0438. Views.plugins.Distributed.DB.title=\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u0411\u0414 Views.plugins.Distributed.Tracker.title=\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 Views.plugins.Plugin.Update.title=\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u044f Views.plugins.UPnP.title.tooltip=\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 Plug and Play openUrl.url.info=\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f http, https, magnet \u0438 \u043d\u0435\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 infohash TableColumn.header.swarm_average_completion=\u0421\u0440\u0435\u0434\u043d\u044f\u044f \u0441\u0442\u0435\u043f\u0435\u043d\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u043e\u0441\u0442\u0438 TableColumn.header.swarm_average_completion.info=\u0421\u0440\u0435\u0434\u043d\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u043d\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0441\u0440\u0435\u0434\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f GeneralView.label.swarm_average_completion=\u0421\u0440\u0435\u0434\u043d\u044f\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u043e\u0441\u0442\u044c: GeneralView.label.swarm_average_completion.tooltip=\u0421\u0440\u0435\u0434\u043d\u044f\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u043e\u0441\u0442\u044c \u0441\u0440\u0435\u0434\u0438 \u0443\u0437\u043b\u043e\u0432 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f MainWindow.nat.status.tooltip.unknown=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u043e\u043c \u044d\u043a\u0440\u0430\u043d\u0435 \u0438\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0435 \u0447\u0435\u0440\u0435\u0437 NAT (TCP) \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430 MainWindow.nat.status.tooltip.ok=\u0414\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0438\u0437\u0432\u043d\u0435 (TCP) MainWindow.nat.status.tooltip.probok=\u0411\u044b\u043b \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0438\u0437\u0432\u043d\u0435, \u043d\u043e \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u043e TCP \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f MainWindow.nat.status.bad=\u0417\u0430 \u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u044b\u043c \u044d\u043a\u0440\u0430\u043d\u043e\u043c MainWindow.nat.status.tooltip.bad=\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u044b\u043c \u044d\u043a\u0440\u0430\u043d\u043e\u043c \u0438\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u0447\u0435\u0440\u0435\u0437 NAT (TCP). \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0435 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 \u0412\u0438\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430 plugin.installer.recommended.plugin=\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u2014 \u043e\u0446\u0435\u043d\u0438\u0442\u0435 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435, \u0435\u0441\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e LoggerView.pause=\u041f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0436\u0443\u0440\u043d\u0430\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 LoggerView.clear=&\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c LoggerView.filter=\u0424\u0438\u043b\u044c\u0442\u0440 LoggerView.filter.uncheckAll=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u044b\u0431\u043e\u0440 LoggerView.filter.checkAll=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0451 LoggerView.loggingDisabled=\u0416\u0443\u0440\u043d\u0430\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e. LoggerView.includeOnly=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a\u0438, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0435 \u0441 \u0440\u0435\u0433. \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c: LoggerView.excludeAll=\u041d\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0435 \u0441 \u0440\u0435\u0433. \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c: ConfigView.section.logging.log0type=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f ConfigView.section.logging.log1type=\u041f\u0440\u0438\u043d\u044f\u0442\u043e ConfigView.section.logging.log2type=\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e ConfigView.section.logging.filter=\u0424\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0436\u0443\u0440\u043d\u0430\u043b\u0430 \u0432 \u0444\u0430\u0439\u043b ConfigView.section.logging.level=\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u0437\u0430\u043f\u0438\u0441\u0438 ConfigView.section.logging.showLogsFor=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044e \u00ab%1\u00bb \u043f\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c: ConfigView.pluginlist.column.loadAtStartup=\u0410\u0432\u0442\u043e\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 ConfigView.pluginlist.column.type=\u0422\u0438\u043f ConfigView.pluginlist.column.type.perUser=\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 ConfigView.pluginlist.column.type.shared=\u041e\u0431\u0449\u0438\u0439 ConfigView.pluginlist.column.type.builtIn=\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 ConfigView.pluginlist.column.name=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 ConfigView.pluginlist.column.version=\u0412\u0435\u0440\u0441\u0438\u044f ConfigView.pluginlist.column.directory=\u041f\u0430\u043f\u043a\u0430 ConfigView.pluginlist.column.isOperational=\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442? PeersView.BlockView.Avail.Have=\u0415\u0441\u0442\u044c \u0443 \u043e\u0431\u043e\u0438\u0445 PeersView.BlockView.Avail.NoHave=\u0422\u043e\u043b\u044c\u043a\u043e \u0443 \u0443\u0437\u043b\u0430 PeersView.BlockView.NoAvail.Have=\u0422\u043e\u043b\u044c\u043a\u043e \u0443 \u043c\u0435\u043d\u044f PeersView.BlockView.NoAvail.NoHave=\u041d\u0435\u0442 \u0443 \u043e\u0431\u043e\u0438\u0445 PeersView.BlockView.Transfer=\u041f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f PeersView.BlockView.NextRequest=\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 PeersView.BlockView.title=\u041a\u0430\u0440\u0442\u0430 \u0447\u0430\u0441\u0442\u0435\u0439 PeersView.BlockView.AvailCount=\u0418\u043d\u0434\u0435\u043a\u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 MyTorrentsView.dialog.NumberError.title=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u0438\u043b\u0438 \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0447\u0438\u0441\u043b\u043e MyTorrentsView.dialog.NumberError.text=\u0412\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0438\u043b\u0438 \u043d\u0435 \u0431\u044b\u043b\u043e \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u043e. MyTorrentsView.menu.manual=&\u0417\u0430\u0434\u0430\u0442\u044c... MyTorrentsView.menu.manual.per_torrent=\u0417\u0430\u0434\u0430\u0442\u044c (\u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442) MyTorrentsView.menu.manual.shared_torrents=\u0417\u0430\u0434\u0430\u0442\u044c (\u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432) MyTorrentsView.dialog.setSpeed.title=\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c (%1) # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 %1, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043a\u0430\u043d\u0430\u043b\u0430 \u00ab%2\u00bb: MyTorrentsView.dialog.setNumber.upload=\u0420\u0430\u0437\u0434\u0430\u0447\u0430 MyTorrentsView.dialog.setNumber.download=\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 MyTorrentsView.dialog.setNumber.inKbps=\u0432 %1 OpenTorrentWindow.torrentLocation=\u0422\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438: OpenTorrentWindow.addFiles.URL=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c &\u0430\u0434\u0440\u0435\u0441 OpenTorrentWindow.addFiles.Folder=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c &\u043f\u0430\u043f\u043a\u0443 OpenTorrentWindow.addFiles.Clipboard=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0438\u0437 \u0431\u0443\u0444\u0435\u0440\u0430 \u043e\u0431\u043c\u0435\u043d\u0430 OpenTorrentWindow.changeDestination=\u0421\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u0435\u0441\u0442\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f OpenTorrentWindow.fileList=\u0424\u0430\u0439\u043b\u043e\u0432 \u0432 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430\u0445: OpenTorrentWindow.torrentTable.name=\u0418\u043c\u044f OpenTorrentWindow.torrentTable.saveLocation=\u041f\u0443\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f OpenTorrentWindow.fileTable.fileName=\u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430 OpenTorrentWindow.fileTable.size=\u0420\u0430\u0437\u043c\u0435\u0440 OpenTorrentWindow.fileTable.destinationName=\u041a\u043e\u043d\u0435\u0447\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 OpenTorrentWindow.startMode.seeding=\u0420\u0430\u0437\u0434\u0430\u0447\u0430 OpenTorrentWindow.fileList.changeDestination=\u041f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 OpenTorrentWindow.mb.badSize.title=\u0424\u0430\u0439\u043b \u043d\u0435\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 OpenTorrentWindow.mb.badSize.text='%1' \u043d\u0435 '%2' \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f OpenTorrentWindow.mb.alreadyExists.text=%3 \u0443\u0436\u0435 \u0431\u044b\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043a\u0430\u043a \u00ab%2\u00bb OpenTorrentWindow.mb.alreadyExists.default.name=\u041c\u0435\u0434\u0438\u0430 OpenTorrentWindow.mb.alreadyExists.title=\u0422\u0430\u043a\u043e\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 OpenTorrentWindow.mb.openError.title=\u041e\u0448\u0438\u0431\u043a\u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u0444\u0430\u0439\u043b\u0430 OpenTorrentWindow.mb.openError.text=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u00ab%1\u00bb: OpenTorrentWindow.torrent.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u0438\u0437 \u043b\u0438\u0441\u0442\u0430 OpenTorrentWindow.torrent.options=\u041a \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430\u043c \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438: OpenTorrentWindow.xOfTotal=(%1 \u0438\u0437 %2) iconBar.open.tooltip=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0444\u0430\u0439\u043b \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 LocaleUtil.column.text=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 Tracker.tooltip.MultiSupport=\u042d\u0442\u043e\u0442 \u0442\u0440\u0435\u043a\u0435\u0440 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0445\u0435\u0448\u0435\u0439. Tracker.tooltip.NoMultiSupport=\u042d\u0442\u043e\u0442 \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0445\u0435\u0448\u0435\u0439.\n\u042d\u0442\u043e \u043d\u0435 \u0441\u043d\u0438\u0437\u0438\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c Vuze, \u043d\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0447\u0430\u0449\u0435. ConfigView.label.lazybitfield=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u00ab\u043b\u0435\u043d\u0438\u0432\u043e\u0435\u00bb \u043f\u043e\u043b\u0435 \u0431\u0438\u0442\u043e\u0432 (\u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043f\u0440\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0435 \u0432 \u0441\u0435\u0442\u044f\u0445, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0445 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0443 \u043f\u043e \u0431\u0438\u0442\u043e\u0432\u043e\u043c\u0443 \u043f\u043e\u043b\u044e) LoggerView.realtime=\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 ConfigView.section.file.perf.cache.flushpieces=\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u0441\u0440\u0430\u0437\u0443. \u042d\u0442\u043e \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430 \u0434\u0438\u0441\u043a, \u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0447\u0438\u0441\u043b\u043e \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0439 \u043a \u043d\u0435\u043c\u0443. ConfigView.section.file.writemblimit=\u041c\u0430\u043a\u0441. \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 (\u0432 %1) ConfigView.section.file.writemblimit.explain=\u0415\u0441\u043b\u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0438 \u043d\u0430 \u0434\u0438\u0441\u043a \u043c\u0435\u043d\u044c\u0448\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f, \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0443\u0444\u0435\u0440\u0430, \u0434\u043e \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043e\u0439 ConfigView.section.file.readmblimit=\u041c\u0430\u043a\u0441. \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 (\u0432 %1) ConfigView.section.file.readmblimit.explain=\u042d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0430\u043c\u044f\u0442\u0438, \u0445\u0440\u0430\u043d\u044f\u0449\u0435\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0447\u0442\u0435\u043d\u0438\u044f. Button.moveUp=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c &\u0432\u0432\u0435\u0440\u0445 Button.moveDown=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c &\u0432\u043d\u0438\u0437 ConfigView.notAvailableForMode=\u042d\u0442\u0430 \u0441\u0435\u043a\u0446\u0438\u044f \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u0434\u043b\u044f \u0443\u0440\u043e\u0432\u0435\u043d\u044f %1 \u0438\u043b\u0438 \u0432\u044b\u0448\u0435. \u0412 \u0440\u0435\u0436\u0438\u043c\u0435 %2 \u043e\u043d\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430. health.explain.error=\u0421 \u0434\u0430\u043d\u043d\u044b\u043c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u043c \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b; \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0442\u043e\u043b\u0431\u0446\u0435 \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438\u043b\u0438 \u0432 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0435 \u0434\u043b\u044f \u0437\u043d\u0430\u0447\u043a\u0430 \u043e\u0448\u0438\u0431\u043a\u0438. GeneralView.label.trackerscrapeupdate=\u0417\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e PeersView.piece=\u0427\u0430\u0441\u0442\u044c PeersView.piece.info=\u041d\u043e\u043c\u0435\u0440 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438, \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043d\u043e\u0439 \u0443 \u044d\u0442\u043e\u0433\u043e \u0443\u0437\u043b\u0430 PiecesView.priority=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 PiecesView.priority.info=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u0438, \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u043e \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u043a \u043d\u0435\u043c\u0443 PiecesView.speed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c PiecesView.speed.info=\u041c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u043c \u0443\u0437\u043b\u0430\u043c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0431\u044b\u0441\u0442\u0440\u044b\u043c \u0447\u0430\u0441\u0442\u044f\u043c TableColumn.header.AvgAvail.info=\u0421\u0443\u043c\u043c\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0447\u0430\u0441\u0442\u0435\u0439, \u0440\u0430\u0437\u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u043d\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0447\u0430\u0441\u0442\u0435\u0439, \u0440\u0430\u0437\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u043d\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 TableColumn.header.AvgAvail=\u0421\u0440\u0435\u0434\u043d\u044f\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c ConfigView.label.strictfilelocking=\u0417\u0430\u043f\u0440\u0435\u0449\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430\u043c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0444\u0430\u0439\u043b MyTorrentsView.menu.checkfilesexist=\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 MyTorrentsView.menu.rescanfile=\u041f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u044e\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u0438 MyTorrentsView.menu.clear_resume_data=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 Plugin.extseed.name=\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0435 Plugin.localtracker.name=\u041f\u043e\u0438\u0441\u043a \u0443\u0437\u043b\u043e\u0432 \u0432 LAN Plugin.localtracker.info=\u041f\u043e\u0438\u0441\u043a \u0443\u0437\u043b\u043e\u0432 \u0432 LAN \u0434\u0430\u0451\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c Vuze \u0437\u0430 \u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u044b\u043c \u044d\u043a\u0440\u0430\u043d\u043e\u043c \u0432 \u043e\u0431\u0449\u0435\u0439 \u0441\u0435\u0442\u0438\n\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u0440\u044f\u043c\u044b\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u043c \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439 Plugin.localtracker.enable=\u0418\u0441\u043a\u0430\u0442\u044c \u0443\u0437\u043b\u044b \u0432 LAN azinstancehandler.alert.portclash=\u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442 \u043f\u043e\u0440\u0442\u043e\u0432 \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0435\u0442\u0438: %1 \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b Vuze. \u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u043e\u0440\u0442 TCP/UDP \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 [\u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 %2 \u0434\u043e %3]. ConfigView.section.transfer.lan.tooltip=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 LAN ConfigView.section.transfer.lan.uploadrate=\u041a\u0411/\u0441 \u043c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u043f\u043e LAN [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.transfer.lan.uploadrate.tooltip=\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0443\u0437\u043b\u043e\u0432 \u043f\u043e \u0435\u0434\u0438\u043d\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 LAN \u0438\u043c\u0435\u044e\u0442 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0440\u0435\u0434\u0435\u043b \u0440\u0430\u0437\u0434\u0430\u0447\u0438. ConfigView.section.transfer.lan.downloadrate=\u041a\u0411/\u0441 \u043c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 \u043f\u043e LAN [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.transfer.lan.downloadrate.tooltip=\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0443\u0437\u043b\u043e\u0432 \u043f\u043e \u0435\u0434\u0438\u043d\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 LAN \u0438\u043c\u0435\u044e\u0442 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0440\u0435\u0434\u0435\u043b \u043f\u0440\u0438\u0451\u043c\u0430. TorrentOptionsView.title.short=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 TorrentOptionsView.title.full=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 TorrentOptionsView.param.max.peers=\u041c\u0430\u043a\u0441. \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.connection.encryption.require_encrypted_transport=\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=\u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438. ConfigView.section.connection.encryption.min_encryption_level=\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f ConfigView.section.connection.encryption.min_encryption_level.tooltip=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f\nRC4 \u2014 \u0432\u0435\u0441\u044c \u043f\u043e\u0442\u043e\u043a\n\u0411\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. Peers.column.Encryption=\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 Peers.column.Encryption.info=\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f ConfigView.section.connection.encryption.encrypt.info=\u0415\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0431\u0443\u0434\u0443\u0442 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b, \u043f\u043e\u043a\u0430 \u043e\u043d\u0438 \u044f\u0432\u043d\u043e \u043d\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u044b \u043d\u0438\u0436\u0435 ConfigView.section.connection.encryption.encrypt.info.link=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0437\u0434\u0435\u0441\u044c MainWindow.sr.status.tooltip.ok=\u0420\u0435\u0439\u0442\u0438\u043d\u0433 %1: \u0445\u043e\u0440\u043e\u0448\u0438\u0439 MainWindow.sr.status.tooltip.poor=\u0420\u0435\u0439\u0442\u0438\u043d\u0433 %1: \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 (<0.9) MainWindow.sr.status.tooltip.bad=\u0420\u0435\u0439\u0442\u0438\u043d\u0433 %1: \u043f\u043b\u043e\u0445\u043e\u0439 (<0.5) ConfigView.section.style.status=\u041e\u0431\u043b\u0430\u0441\u0442\u044c \u0441\u0442\u0430\u0442\u0443\u0441\u0430: ConfigView.section.style.status.show_sr=\u0420\u0435\u0439\u0442\u0438\u043d\u0433 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.section.style.status.show_nat=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 NAT ConfigView.section.style.status.show_ddb=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0420\u0411\u0414 ConfigView.section.style.status.show_ipf=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430 IP ConfigView.section.connection.encryption.encrypt.group=\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0432\u0443\u0430\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 ConfigView.section.connection.encryption.encrypt.fallback_info=\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043d\u0438\u0436\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0442\u044c\u0441\u044f \u0441 \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u043c\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438, \u041d\u041e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044e \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 ConfigView.section.connection.encryption.encrypt.fallback_outgoing=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0442\u044c \u043d\u0435\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0443\u0434\u0430\u043b\u0438\u0441\u044c \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 ConfigView.section.connection.encryption.encrypt.fallback_incoming=\u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0442\u044c \u043d\u0435\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f ConfigView.section.connection.encryption=\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0440\u0430\u0444\u0438\u043a\u0430 upnp.selectedinterfaces=\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b (\u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c: \u00ab;\u00bb, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, eth0;eth1) [\u043f\u0443\u0441\u0442\u043e\u0435 \u043f\u043e\u043b\u0435: \u0432\u0441\u0435] ConfigView.section.style.defaultSortOrder=\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e ConfigView.section.style.defaultSortOrder.desc=\u041f\u043e \u0443\u0431\u044b\u0432\u0430\u043d\u0438\u044e ConfigView.section.style.defaultSortOrder.asc=\u041f\u043e \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u043d\u0438\u044e ConfigView.section.style.defaultSortOrder.flip=\u041f\u0440\u043e\u0442\u0438\u0432\u043e\u043f\u043e\u043b\u043e\u0436\u043d\u044b\u0439 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 LoggerView.autoscroll=\u0410\u0432\u0442\u043e\u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0430 Button.selectAll=\u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0432\u0441\u0451 Button.markSelected=\u041f\u043e\u043c\u0435\u0442\u0438\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 Button.unmarkSelected=\u0421\u043d\u044f\u0442\u044c \u043f\u043e\u043c\u0435\u0442\u043a\u0443 \u0441 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 plugins.basicview.config=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 TorrentOptionsView.param.max.uploads=\u041c\u0430\u043a\u0441. \u0441\u043b\u043e\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 [\u043c\u0438\u043d\u0438\u043c\u0443\u043c: 2] MyTorrentsView.dialog.setPosition.title=\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 MyTorrentsView.dialog.setPosition.text=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0434\u043b\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432: MyTorrentsView.menu.reposition.manual=\u041f\u043e\u0437\u0438\u0446\u0438\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438... ConfigView.section.connection.advanced.info.link=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0437\u0434\u0435\u0441\u044c ConfigView.section.connection.advanced.socket.group=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u043e\u043a\u0435\u0442\u043e\u0432 ConfigView.section.connection.advanced.bind_port=\u041f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u043a \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u043e\u0440\u0442\u0443 [0: \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043e] ConfigView.section.connection.advanced.bind_port.tooltip=\u0418\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u043f\u043e\u0440\u0442\u043e\u043c.\n\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0435 \u0440\u043e\u0443\u0442\u0435\u0440\u0430 NAT. ConfigView.section.proxy.group.tracker=\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u043c ConfigView.section.proxy.group.peer=\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0443\u0437\u043b\u0430\u043c\u0438 Pieces.column.Requested=\u0417\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043e Pieces.column.Requested.info=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b \u043b\u0438 \u0435\u0449\u0451 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0434\u0430\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0438\u043b\u0438 \u043d\u0435\u0442 (*) ConfigView.label.maxuploadsseeding=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043f\u0440\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u0434\u0430\u0447\u0435 MyTorrentsView.filter=\u0424\u0438\u043b\u044c\u0442\u0440: popup.error.hideall=\u0421\u043a\u0440\u044b\u0442\u044c \u0432\u0441\u0451 ConfigView.section.style.dataStatsOnly=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e \u0434\u0430\u043d\u043d\u044b\u043c (\u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430) ConfigView.section.style.separateProtDataStats=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430\u043c \u0438 \u0434\u0430\u043d\u043d\u044b\u043c \u043a\u0430\u043a \u00ab\u0434\u0430\u043d\u043d\u044b\u0435 (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b)\u00bb MyTorrentsView.dialog.setFilter.title=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440 MyTorrentsView.dialog.setFilter.text=\u0421\u0435\u043a\u0446\u0438\u044f %1 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u043d\u0430 \u043f\u043e \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u043c\u0443 \u0442\u0435\u043a\u0441\u0442\u0443. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0441\u0438\u043c\u0432\u043e\u043b \u00ab|\u00bb \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u043a\u0438 \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u0441\u043b\u043e\u0432\u0430\u043c. MyTorrentsView.filter.tooltip=Ctrl+X \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0440\u0435\u0436\u0438\u043c\u043e\u043c \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u043c\u0438 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c\u0438.\n\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c | \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0434\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. MyTorrentsView.clearFilter.tooltip=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440 MyTorrentsView.menu.filter=\u0424\u0438\u043b\u044c\u0442\u0440... ConfigView.section.file.resume.recheck.all=\u041f\u043e\u0441\u043b\u0435 \u0430\u0432\u0430\u0440\u0438\u0439\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0432\u0441\u0435 \u0447\u0430\u0441\u0442\u0438 \u0444\u0430\u0439\u043b\u0430 (\u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438) ConfigureWizard.language.choose=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u044f\u0437\u044b\u043a \u0438\u0437 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u043d\u0438\u0436\u0435 \u0441\u043f\u0438\u0441\u043a\u0430: popup.closing.in=\u041e\u043a\u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 %1 popup.more.waiting=\u0415\u0449\u0451 %1 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435(\u044f).. # > 2402 popup.download.finished=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u00ab%1\u00bb \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430. popup.file.finished=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u00ab%1\u00bb \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430. ConfigView.auto=\u0410\u0432\u0442\u043e Plugin.localtracker.autoadd.info=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u044d\u0442\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0443\u0437\u043b\u044b [\u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c: \u00ab;\u00bb, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 1.2.3.4] Plugin.localtracker.autoadd=\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u044b Plugin.localtracker.networks.info=\u0420\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0435\u0442\u0438 \u043a\u0430\u043a \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 [\u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c: \u00ab;\u00bb, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 145.227.*.*] Plugin.localtracker.networks=\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0435\u0442\u0438 MainWindow.menu.view.plugins.logViews=\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u0436\u0443\u0440\u043d\u0430\u043b\u043e\u0432 SpeedView.stats.autospeed=\u0410\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 SpeedView.stats.autospeed.disabled=\u042d\u0442\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043b\u0438\u0431\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0430 (\u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0420\u0411\u0414), \u043b\u0438\u0431\u043e \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f (\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u0430 \u0432\u0440\u0443\u0447\u043d\u0443\u044e) SpeedView.stats.idlePing=\u041f\u0438\u043d\u0433 \u043f\u0440\u0438 \u0431\u0435\u0437\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438: SpeedView.stats.maxPing=\u041c\u0430\u043a\u0441. \u043f\u0438\u043d\u0433: SpeedView.stats.currentPing=\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0438\u043d\u0433: SpeedView.stats.maxUp=\u041f\u0440\u0435\u0434\u0435\u043b \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438: ConfigView.pluginlist.unloadSelected=\u0412\u044b\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 ConfigView.pluginlist.scan=\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 ConfigView.section.transfer.autospeed=\u0410\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c (\u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0430\u044f) ConfigView.section.transfer.autospeed.tooltip=\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 ConfigView.section.transfer.autospeed.info=\u0410\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0435\u0433\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u0435\u0434\u0435\u043b \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0447\u0440\u0435\u0437\u043c\u0435\u0440\u043d\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430 \u0441\u0435\u0442\u044c.\n\n\u042d\u0442\u0438 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u0433\u0434\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043d\u0438 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0439 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445.\n ConfigView.section.transfer.autospeed.minupload=%1 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.section.transfer.autospeed.minupload.tooltip=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0430 \u043d\u0438\u0436\u0435 \u044d\u0442\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f ConfigView.section.transfer.autospeed.maxupload=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 %1 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] ConfigView.section.transfer.autospeed.maxupload.tooltip=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0430 \u0432\u044b\u0448\u0435 \u044d\u0442\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f ConfigView.section.transfer.autospeed.chokeping=\u0412\u0440\u0435\u043c\u044f \u043f\u0438\u043d\u0433\u0430 \u043f\u0440\u0438 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0435 [\u043c\u0441] ConfigView.section.transfer.autospeed.chokeping.tooltip=\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u044b\u0448\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0441\u0447\u0438\u0442\u0430\u0442\u044c\u0441\u044f \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u043d\u0430\u0441\u044b\u0449\u0435\u043d\u043d\u043e\u0441\u0442\u0438 ConfigView.section.transfer.autospeed.enableauto=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430\u0445 \u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0430\u0445 ConfigView.section.transfer.autospeed.enableautoseeding=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0440\u0430\u0437\u0434\u0430\u0447\u0430\u0445 ConfigView.pluginlist.column.unloadable=\u0412\u044b\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0439 ConfigView.section.transfer.lan.enable=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u043f\u043e LAN Plugin.localtracker.wellknownlocals=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0435\u0442\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 192.168.x.x) \u0438 \u0430\u0434\u0440\u0435\u0441\u0430 \u043a\u043e\u043b\u044c\u0446\u0435\u0432\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 TableColumn.header.filesdone=\u0424\u0430\u0439\u043b\u043e\u0432 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e TableColumn.header.filesdone.info=\u0424\u0430\u0439\u043b\u043e\u0432 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043e/\u0432\u0441\u0435\u0433\u043e *\u0438\u043b\u0438* \u041d\u0435 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043e (\u0444\u0430\u0439\u043b\u043e\u0432 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043e)/\u0432\u0441\u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 (\u0432\u0441\u0435\u0433\u043e \u0444\u0430\u0439\u043b\u043e\u0432) MagnetPlugin.private_torrent=<\u0437\u0430\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442> MagnetPlugin.decentral_disabled=<\u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0438\u043d\u0433 \u043e\u0442\u043a\u043b\u044e\u0447\u0451\u043d> MagnetPlugin.decentral_backup_disabled=<\u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e\u0435 \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u043e\u0435 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043e> MagnetPlugin.report.waiting_ddb=\u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0440\u0442\u0430 \u0420\u0414\u0411... MagnetPlugin.report.searching=\u043f\u043e\u0438\u0441\u043a... MagnetPlugin.report.found=\u043d\u0430\u0439\u0434\u0435\u043d\u043e %1 MagnetPlugin.report.alive=%1 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 MagnetPlugin.report.dead=%1 \u043d\u0435\u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 MagnetPlugin.report.tunnel=\u0442\u0443\u043d\u043d\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 %1 MagnetPlugin.report.downloading=\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0441 %1 MagnetPlugin.report.error=\u043e\u0448\u0438\u0431\u043a\u0430 %1 MagnetURLHandler.report.no_sources=\u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0438\u0441\u0447\u0442\u043e\u043d\u0438\u043a\u043e\u0432 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 MagnetURLHandler.report.torrent_size=\u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430: %1 MagnetURLHandler.report.percent=\u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e: %1% MagnetURLHandler.report.error=\u043e\u0448\u0438\u0431\u043a\u0430 %1 DHTTransport.report.request_all=\u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0438\u0437 %1 DHTTransport.report.received_bit=\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043e %1 \u0432 %2 \u0438\u0437 %3 DHTTransport.report.complete=\u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e DHTTransport.report.timeout=\u0442\u0430\u0439\u043c\u0430\u0443\u0442, \u043d\u0435\u0442 \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0442 %1 DHTTransport.report.rerequest_all=\u043f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0438\u0437 %1 DHTTransport.report.rerequest_bit=\u043f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 %1 \u0432 %2 \u0438\u0437 %3 DHTTransport.report.timeout_some=\u0432\u0440\u0435\u043c\u044f \u0438\u0441\u0442\u0435\u043a\u043b\u043e, %1 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043e \u043e\u0442 %2, \u043d\u043e \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e DHTTransport.report.sending=\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 DHTTransport.report.resending=\u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 DHTTransport.report.send_complete=\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430 DHTTransport.report.send_timeout=\u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0438\u0441\u0442\u0435\u043a\u043b\u043e ConfigView.section.transfer.autospeed.enabledebug=\u0412\u0435\u0441\u0442\u0438 \u0436\u0443\u0440\u043d\u0430\u043b \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 TableColumn.header.date_added=\u0414\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f TableColumn.header.date_added.info=\u0414\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 ConfigView.section.file.hashchecking.smallestfirst=\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0430\u043c\u044b\u0435 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 platform.win32.baddll.info=\u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u00ab%1\u00bb. \u042d\u0442\u043e \u0447\u0430\u0441\u0442\u044c \u00ab%2\u00bb, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b; \u0441\u0431\u043e\u0438 \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0438 \u0447\u0440\u0435\u0437\u043c\u0435\u0440\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430. \u0415\u0441\u043b\u0438 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442, \u0443\u0434\u0430\u043b\u0438\u0442\u0435 \u044d\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0435\u0433\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u043e \u043d\u0435 \u043c\u0435\u0448\u0430\u043b\u043e \u0440\u0430\u0431\u043e\u0442\u0435 Vuze. upnp.ignorebaddevices=\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e upnp.ignorebaddevices.info=\u0422\u0435\u043a\u0443\u0449\u0438\u0435 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430: %1 upnp.ignorebaddevices.reset=\u0421\u0431\u0440\u043e\u0441 \u0441\u043f\u0438\u0441\u043a\u0430 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 upnp.ignorebaddevices.reset.action=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c upnp.ignorebaddevices.alert=\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e UPnP \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 %1 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u0437-\u0437\u0430 \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0441\u0431\u043e\u0435\u0432. \u0412\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u043c\u043e\u0434\u0443\u043b\u044f UPnP. TorrentOptionsView.param.max.uploads.when.busy=\u041a\u0411/c \u043c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438, \u043a\u043e\u0433\u0434\u0430 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442\u043e [0: \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043e] UpdateMonitor.messagebox.verification.failed.title=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043d\u0435 \u0443\u0434\u0430\u043b\u0430\u0441\u044c UpdateMonitor.messagebox.verification.failed.text=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u00ab%1\u00bb \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0430\u0441\u044c \u043e\u0448\u0438\u0431\u043a\u043e\u0439: %2 UpdateMonitor.messagebox.accept.unverified.title=\u041f\u0440\u0438\u043d\u044f\u0442\u044c \u043d\u0435\u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u0443\u044e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 UpdateMonitor.messagebox.accept.unverified.text=\u041c\u043e\u0434\u0443\u043b\u044c \u00ab%1\u00bb \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u043c \u043c\u043e\u0434\u0443\u043b\u0435\u043c Vuze .\n\u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0439 \u043c\u043e\u0434\u0443\u043b\u044c, \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u041f\u0420\u0415\u0420\u0412\u0410\u0422\u042c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443.\n\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443? FileView.BlockView.title=\u0427\u0430\u0441\u0442\u0438 \u0444\u0430\u0439\u043b\u0430 FileView.BlockView.Done=\u0417\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0435 FileView.BlockView.Skipped=\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0435 FileView.BlockView.Active=\u0410\u043a\u0442\u0438\u0432\u043d\u044b\u0435 FileView.BlockView.Outstanding=\u041d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 ConfigView.label.tcplistenport=\u041f\u043e\u0440\u0442 TCP \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 ConfigView.label.udplistenport=\u041f\u043e\u0440\u0442 UDP \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 upnp.portchange.alert=\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u0440\u0442\u044b \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b \u0432\u043e \u0438\u0437\u0431\u0435\u0436\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 UPnP: %1 [\u043f\u0440\u0435\u0436\u043d\u0438\u0439 \u043f\u043e\u0440\u0442=%2] %3 [\u043f\u0440\u0435\u0436\u043d\u0438\u0439 \u043f\u043e\u0440\u0442=%4] ConfigView.section.proxy.username.info=\u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u043a\u0441\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u0430 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0441\u0442\u0440\u043e\u043a\u0443 \u00ab\u00bb \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f ConfigView.label.maxuploadswhenbusymin=\u0422\u0430\u0439\u043c\u0435\u0440 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 [\u0441] MainWindow.menu.help.debug=\u0412\u044b\u0434\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 (\u0436\u0443\u0440\u043d\u0430\u043b \u0441\u0431\u043e\u0435\u0432) DownloadManager.error.badsize=\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 natpmp.info=NAT-PMP \u2014 \u044d\u0442\u043e \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 UPnP, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u0430\u044f Apple, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 Airport\n\n\u0417\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u0435: UPnP \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c NAT-PMP, \u0442\u0430\u043a \u043a\u0430\u043a \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 NAT-PMP \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0441\u043e\u0431\u044b\u0439 \u0442\u0438\u043f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 UPnP natpmp.enable=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c (\u044d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0441\u0442\u0430\u043d\u0446\u0438\u0438 Airport) ConfigView.section.tracker.host.addurls=\u041e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 \u0432 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430\u0445 ConfigView.filter=\u0444\u0438\u043b\u044c\u0442\u0440 ConfigView.section.files.move=\u041f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044e ConfigView.section.file.defaultdir.section=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0443\u0442\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e ConfigView.section.file.defaultdir.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 (\u0431\u0435\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u0443\u0442\u0438) ConfigView.section.file.defaultdir.bestguess=\u0412\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0430\u043c\u0443\u044e \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0443\u044e \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a ConfigView.section.file.defaultdir.ask=\u041f\u0430\u043f\u043a\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e: ConfigView.section.file.defaultdir.lastused=\u0417\u0430\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u0430\u043f\u043a\u0443 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u0440\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0430\u043f\u043a\u0438 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f ConfigView.section.file.config.section=\u0425\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a ConfigView.section.file.config.currentdir=\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0443\u0442\u044c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a: ConfigView.section.torrent.decoding=\u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 ConfigView.section.logging.udptransport=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0443\u044e \u0442\u0440\u0430\u0441\u0441\u0438\u0440\u043e\u0432\u043a\u0443 \u043e\u0431\u043c\u0435\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u043e UDP Tracker.announce.ignorePeerSeed=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0443\u0437\u043b\u043e\u0432/\u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f. %1 ConfigView.section.connection.encryption.use_crypto_port=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u00abcryptoport\u00bb, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u043d\u0435\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u044b \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b \u0441 \u043d\u0438\u043c \u0438 \u043c\u043e\u0433\u0443\u0442 \u043e\u0442\u0432\u0435\u0440\u0433\u043d\u0443\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439 \u00ab\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u043f\u043e\u0440\u0442\u00bb \u0438\u043b\u0438 \u00ab\u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u00bb. TorrentOptionsView.param.reset.to.default=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043a \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u043c TorrentOptionsView.param.reset.button=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c natpmp.routeraddress=\u0410\u0434\u0440\u0435\u0441 \u0441\u0442\u0430\u043d\u0446\u0438\u0438 [\u043f\u0443\u0441\u0442\u043e\u0435 \u043f\u043e\u043b\u0435: \u0430\u0432\u0442\u043e] ConfigView.section.style.disableAlertSliding=\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043b\u0430\u0432\u043d\u0443\u044e \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e/\u043f\u043e\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u0432\u0435\u0440\u0445 \u0432\u0441\u0435\u0445 \u043e\u043a\u043e\u043d \u0434\u043b\u044f \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 ConfigView.section.transfer.autospeed.maxinc=%1 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0443\u0432\u0435\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u0446\u0438\u043a\u043b ConfigView.section.transfer.autospeed.maxdec=%1 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0446\u0438\u043a\u043b ConfigView.section.transfer.autospeed.enabledownadj=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u043a\u0443 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f ConfigView.section.transfer.autospeed.downadjratio=\u0421\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0435\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438:\u0440\u0430\u0437\u0434\u0430\u0447\u0438 (\u0442.\u0435. 2.0 -> \u043f\u0440\u0435\u0434\u0435\u043b \u043f\u0440\u0438\u0451\u043c\u0430 \u0432 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0440\u0435\u0434\u0435\u043b\u0430 \u0440\u0430\u0437\u0434\u0430\u0447\u0438) ConfigView.section.transfer.autospeed.latencyfactor=\u041a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0441\u0435\u0442\u0438 (\u0431\u043e\u043b\u044c\u0448\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u2014 \u043c\u0435\u043d\u044c\u0448\u0435 \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c) ConfigView.section.transfer.autospeed.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 ConfigView.section.transfer.autospeed.reset.button=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c PeerColumn.activationCount=\u0423\u0437\u043b\u044b \u043f\u044b\u0442\u0430\u044e\u0442\u0441\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c\u0441\u044f: %1 TableColumn.header.timesincedownload.info=\u0412\u0440\u0435\u043c\u044f \u0441 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043f\u0440\u0438\u0451\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 TableColumn.header.timesincedownload=\u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u0451\u043c\u0430 TableColumn.header.timesinceupload.info=\u0412\u0440\u0435\u043c\u044f \u0441 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 TableColumn.header.timesinceupload=\u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 PeersView.incomingreqcount=\u0412\u0445. \u0437\u0430\u043f\u0440\u043e\u0441\u044b PeersView.incomingreqcount.info=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0441\u0434\u0435\u043b\u0430\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u043e\u043c PeersView.outgoingreqcount=\u0418\u0441\u0445. \u0437\u0430\u043f\u0440\u043e\u0441\u044b PeersView.outgoingreqcount.info=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0443\u0437\u043b\u0443 upnp.mapping.trackerclientudp=\u041f\u043e\u0440\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 UDP-\u0442\u0440\u0435\u043a\u0435\u0440\u0430 upnp.mapping.dhtudp=\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u0411\u0430\u0437\u0430 \u0414\u0430\u043d\u043d\u044b\u0445 ConfigView.section.connection.nondata.udp.same=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u043f\u043e\u0440\u0442 UDP \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0439 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 UDP-\u0442\u0440\u0435\u043a\u0435\u0440\u0430 ConfigView.section.connection.tcp.enable=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c TCP ConfigView.section.connection.udp.enable=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c UDP ConfigView.section.style.showiconbar=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 MainWindow.menu.view.iconbar=\u041f\u0430\u043d\u0435\u043b\u044c \u0438\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 MyTorrentsView.menu.rename=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0438\u043c\u044f/\u043f\u0443\u0442\u044c MyTorrentsView.menu.rename.displayed=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f MyTorrentsView.menu.rename.save_path=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0443\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f MyTorrentsView.menu.rename.displayed.enter.title=\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0433\u043e \u0438\u043c\u0435\u043d\u0438 MyTorrentsView.menu.rename.displayed.enter.message=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u043e\u0432\u043e\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438.\n\u0415\u0441\u043b\u0438 \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u0432\u0432\u0435\u0434\u0435\u043d, \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u043d\u043e\u0435 \u0438\u043c\u044f \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b. MyTorrentsView.menu.edit_comment=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 MyTorrentsView.menu.edit_comment.enter.title=\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f MyTorrentsView.menu.edit_comment.enter.message=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u043a \u044d\u0442\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435. UIDebugGenerator.messageask.title=\u0413\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u041e\u0442\u043b\u0430\u0434\u043a\u0438 UIDebugGenerator.messageask.text=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 UIDebugGenerator.complete.title=\u0413\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u041e\u0442\u043b\u0430\u0434\u043a\u0438 \u0417\u0430\u0432\u0435\u0440\u0448\u0451\u043d UIDebugGenerator.complete.text=\u0424\u0430\u0439\u043b \u0441\u043e \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f\u043c\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0439\u0434\u0435\u043d \u0432 \u00ab%1\u00bb.\n\n\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u00abOK\u00bb, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043e\u043a\u043d\u043e \u0441 \u044d\u0442\u0438\u043c \u0444\u0430\u0439\u043b\u043e\u043c. ConfigView.section.style.showProgramIcon=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u043e\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0432 \u0441\u0442\u043e\u043b\u0431\u0446\u0435 \u00ab\u0418\u043c\u044f\u00bb ConfigView.section.style.showProgramIcon.tooltip=\u0412\u0438\u0434 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u0434\u043b\u044f \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 swt.alert.cant.update=\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 SWT, \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u0430\u044f \u0441 \u00ab%3\u00bb, \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0430 \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 %1 \u0434\u043e %2 (\u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0441 \u00ab%4\u00bb). \u041f\u043e\u0441\u0438\u0442\u0438\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0412\u0438\u043a\u0438 \u0441 \u0434\u043e\u043f\u043e\u043b\u044c\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439. authenticator.savepassword=\u0417\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043c\u043e\u0439 \u043f\u0430\u0440\u043e\u043b\u044c ConfigView.section.security.clearpasswords=\u0421\u0431\u0440\u043e\u0441 \u043f\u0430\u0440\u043e\u043b\u0435\u0439 ConfigView.section.security.clearpasswords.button=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c Content.alert.notuploaded.title=\u0420\u0430\u0437\u0434\u0430\u0447\u0430 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430 Content.alert.notuploaded.text=\u0420\u0430\u0437\u0434\u0430\u0447\u0430 %1 \u0435\u0449\u0451 \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430. \u0415\u0441\u043b\u0438 \u0432\u044b %2 \u0441\u0435\u0439\u0447\u0430\u0441, \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043d\u0435 \u0441\u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443. \u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435 %2? Content.alert.notuploaded.multi.title=\u0420\u0430\u0437\u0434\u0430\u0447\u0438 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u044b Content.alert.notuploaded.multi.text=%1 \u0444\u0430\u0439\u043b\u043e\u0432 \u0435\u0449\u0451 \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0440\u043e\u0437\u0434\u0430\u043d\u043e. \u0415\u0441\u043b\u0438 \u0432\u044b %2 \u0441\u0435\u0439\u0447\u0430\u0441, \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043d\u0435 \u0441\u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u044d\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432. \u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435 %2?\n\n\u041a\u043e\u043d\u0442\u0435\u043d\u0442 \u043d\u0435 \u0440\u043e\u0437\u0434\u0430\u043d \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e:\n%3 Content.alert.notuploaded.stop=\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 Content.alert.notuploaded.quit=\u0432\u044b\u0439\u0434\u0435\u0442\u0435 \u0438\u0437 Vuze TorrentInfoView.torrent.encoding=\u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 TorrentInfoView.columns=\u0421\u0442\u043e\u043b\u0431\u0446\u044b \u0438\u0437 \u0432\u0438\u0434\u0430 \u00ab\u041c\u043e\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b\u00bb progress.window.title=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f progress.window.msg.filemove=\u0424\u0430\u0439\u043b \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f ConfigView.label.popup.timestamp=\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0448\u0442\u0430\u043c\u043f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u043e \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f ConfigView.label.popup.autohide=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043d\u0435\u043a\u0440\u0438\u0442\u0438\u0447\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 X \u0441\u0435\u043a\u0443\u043d\u0434 [0: \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043e] ConfigView.label.popup.suppress_alerts=\u041d\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f ConfigView.label.popup.use_message_boxes=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043e\u043a\u043d\u0430 \u0434\u043b\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u043e\u043a\u043e\u043d ConfigView.label.popup.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0441\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f (\u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c) ConfigView.label.popup.show.button=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c ConfigView.label.please.visit.here=\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0437\u0434\u0435\u0441\u044c ConfigView.section.ipfilter.enable.descriptionCache=\u0425\u0440\u0430\u043d\u0438\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f IP \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 ConfigView.section.ipfilter.enable.descriptionCache.tooltip=\u041a\u043e\u0433\u0434\u0430 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043e, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0442\u044c\u0441\u044f OpenTorrentWindow.filesInfo=%1 \u0438\u0437 %2 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b. OpenTorrentWindow.diskUsage=%1 \u0438\u0437 %2 ConfigView.label.openmytorrents=\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u00ab\u041c\u043e\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b\u00bb \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 ConfigView.label.open_transfer_bar_on_start=\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043d\u043b\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 ConfigView.section.style.DNDalwaysInIncomplete=\u0412\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u00ab\u041d\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u00bb \u0432 \u0441\u0435\u043a\u0446\u0438\u0438 \u00ab\u043d\u0435\u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0435\u00bb OpenTorrentWindow.mb.noGlobalDestDir.title=\u041f\u0430\u043f\u043a\u0430 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 OpenTorrentWindow.mb.noGlobalDestDir.text=\u041f\u0430\u043f\u043a\u0430 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f '%1' \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043b\u0438 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430. OpenTorrentWindow.mb.noDestDir.title=\u041f\u0430\u043f\u043a\u0430 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 OpenTorrentWindow.mb.noDestDir.text=\u041f\u0430\u043f\u043a\u0430 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f '%1' \u0434\u043b\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 '%2' \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043b\u0438 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430. OpenTorrentWindow.mb.notValid.title=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 OpenTorrentWindow.mb.notValid.text=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u00ab%1\u00bb. \u0415\u0441\u043b\u0438 \u043e\u043d \u0431\u044b\u043b \u043e\u0442\u043a\u0440\u044b\u0442 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0430\u0437\u0434\u0430\u0447\u0438, \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u044d\u0442\u043e\u0433\u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430. OpenTorrentWindow.mb.notTorrent.title=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 OpenTorrentWindow.mb.notTorrent.text=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u00ab%1\u00bb. \u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0444\u0430\u0439\u043b \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u043c.\n\n\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b:\n%2 ConfigView.label.pause.downloads.on.exit=\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u0440\u0438 \u0432\u044b\u0445\u043e\u0434\u0435 ConfigView.label.resume.downloads.on.start=\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 UIDebugGenerator.message.cancel.title=\u0421\u0431\u043e\u0440 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u043e\u0442\u043c\u0435\u043d\u0451\u043d UIDebugGenerator.message.cancel.text=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u043e\u043e\u0431\u0449\u0438\u0442\u044c, \u043d\u0435 \u0431\u044b\u043b\u043e \u0432\u0432\u0435\u0434\u0435\u043d\u043e. \u0414\u043b\u044f \u0432\u0430\u0441 \u044d\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u0439, \u043d\u043e \u0431\u0435\u0437 \u0435\u0451 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e \u0435\u0451 \u0440\u0435\u0448\u0438\u0442\u044c.\n\n\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0431\u044b\u043b\u0430 \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u0430. ConfigView.section.connection.group.http.info=\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 HTTP-\u0440\u0430\u0437\u0434\u0430\u0447\u0438. ConfigView.section.connection.http.enable=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c ConfigView.section.connection.http.port=\u041d\u043e\u043c\u0435\u0440 \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u043f\u043e\u0440\u0442\u0430 ConfigView.section.connection.http.portoverride=\u041f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u0442\u0430 HTTP-\u0442\u0440\u0435\u043a\u0435\u0440\u0430 [0: \u043d\u0435\u0442] window.update.noupdates.title=\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f window.update.noupdates.text=\u041d\u0435\u0442 \u043d\u043e\u0432\u044b\u0445 \u043e\u0431\u043d\u043e\u043b\u0435\u043d\u0438\u0439.\n\n\u041f\u043e\u0437\u0434\u0440\u0430\u0432\u043b\u044f\u044e! ConfigView.label.bindip.details=\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: 192.168.1.5;eth0;eth1[2] \u0441\u0432\u044f\u0436\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 IP \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0430\u0434\u0440\u0435\u0441\u0430\u043c\u0438 1\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0438 \u0441 \u0442\u0440\u0435\u0442\u044c\u0438\u043c \u0430\u0434\u0440\u0435\u0441\u043e\u043c 2\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430.\n\u041f\u0435\u0440\u0432\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 IP \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u0434\u043b\u044f \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438.\n\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b:\n%1 ConfigView.label.mindownloads=\u041c\u0438\u043d\u0438\u043c\u0443\u043c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0439 UI.cannot_submit_blank_text=\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u0432\u0435\u0441\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. crypto.alert.as.warning=\u041e \u0441\u0435\u0442\u0438 \u00ab%1\u00bb \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0447\u0442\u043e \u043e\u043d\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0442\u0440\u0430\u0444\u0438\u043a \u0434\u043b\u044f \u0441\u043d\u0438\u0436\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0438. \u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u2014 \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445. ConfigView.section.interface.alerts=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f ConfigView.label.popupdownloadadded=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 popup.download.added=\u00ab%1\u00bb \u0431\u044b\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a. MessageBoxWindow.nomoreprompting=\u041d\u0435 \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0442\u044c \u043c\u043d\u0435 \u0441\u043d\u043e\u0432\u0430 TorrentOptionsView.param.max.seeds=\u041c\u0430\u043a\u0441. \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 [0: \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f\u043c\u0438] TorrentOptionsView.param.alternative.value.enable=\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigView.section.proxy.check.on.start=\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u043e\u043a\u0441\u0438 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 TransferStatsView.legend.pingaverage=\u0421\u0440\u0435\u0434\u043d\u0435\u0435 TransferStatsView.legend.ping1=\u041c\u0435\u0441\u0442\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f 1 TransferStatsView.legend.ping2=\u041c\u0435\u0441\u0442\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f 2 TransferStatsView.legend.ping3=\u041c\u0435\u0441\u0442\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f 3 ConfigView.section.interface.enabletray._mac=\u0417\u043d\u0430\u0447\u043e\u043a \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f [\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a] ConfigView.label.closetotray._mac=\u0417\u0430\u043a\u0440\u044b\u0442\u0438\u0435 \u043e\u043a\u043d\u0430 \u0441\u0432\u0435\u0440\u043d\u0451\u0442 \u0435\u0433\u043e \u0432 \u0437\u043d\u0430\u0447\u043e\u043a \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f ConfigView.label.minimizetotray._mac=\u0421\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0432 \u0442\u0440\u0435\u0439 OpenTorrentWindow.mb.existingFiles.title=\u0424\u0430\u0439\u043b(\u044b) \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442! OpenTorrentWindow.mb.existingFiles.text=\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0432 \u043f\u0430\u043f\u043a\u0435 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f:\n\n%1\n\u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c, Vuze \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0444\u0430\u0439\u043b\u0430\u0445 \u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 (\u043e\u0434\u043d\u0430\u043a\u043e, \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u043d\u044b). splash.unloadingTorrents=\u0412\u044b\u0433\u0440\u0443\u0437\u043a\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 splash.unloadingTorrent=\u0412\u044b\u0433\u0440\u0443\u0437\u043a\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 ConfigView.section.file.defaultdir.autorename=\u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f ConfigView.section.file.defaultdir.autorename.tooltip=\u042d\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u043e\u0434\u043d\u0438\u043c \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u043c \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u0441 \u0442\u0430\u043a\u0438\u043c\u0438 \u0436\u0435 \u0438\u043c\u0435\u043d\u0430\u043c\u0438 alert.raised.at.close=(\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u0441\u0435\u0430\u043d\u0441\u0430 Vuze) Plugin.trackerpeerauth.name=\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0443\u0437\u043b\u043e\u0432 \u043d\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0435 Plugin.trackerpeerauth.info=\u042d\u0442\u043e\u0442 \u043c\u043e\u0434\u0443\u043b\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0443\u0437\u043b\u044b \u043d\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0438 \u0440\u0430\u0431\u043e\u0442\u0443 \u0432 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438 Peers.column.maxupspeed=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 Peers.column.maxdownspeed=\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 MyTorrents.items.DownSpeedLimit.disabled=\u041d\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a upnp.selectedaddresses=\u0410\u0434\u0440\u0435\u0441\u0430 (\u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c: \u00ab;\u00bb, \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u00ab-\u00bb =\u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c, \u00ab+\u00bb =\u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c) [\u043f\u0443\u0441\u0442\u043e\u0435 \u043f\u043e\u043b\u0435: \u0432\u0441\u0435] upnp.alert.multipledevice.warning=\u0411\u044b\u043b\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 UPnP \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0432\u0441\u0435\u043c \u043b\u0438 \u0438\u0437 \u043d\u0438\u0445 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u0442\u043e\u0432 (\u0441\u043c. \u0436\u0443\u0440\u043d\u0430\u043b UPnP \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b) UpdateMonitor.messagebox.restart.title=\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b UpdateMonitor.messagebox.restart.text=\u0411\u044b\u043b\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043e \u0432\u0430\u0436\u043d\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u0435\u0433\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a Vuze. PiecesView.BlockView.Have=\u041f\u0440\u0438\u043d\u044f\u0442\u0430 PiecesView.BlockView.NoHave=\u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 PiecesView.BlockView.Header=%1 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432, %2 \u0441\u0442\u0440\u043e\u043a, %3 \u0447\u0430\u0441\u0442\u0435\u0439 ConfigView.section.update.autodownload=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c \u043f\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 Peers.column.peer_id=ID \u0443\u0437\u043b\u0430 Peers.column.peer_id.info=ID \u0443\u0437\u043b\u0430 \u0432 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0439 \u0444\u043e\u0440\u043c\u0435 Peers.column.peer_byte_id=ID \u0443\u0437\u043b\u0430 Peers.column.peer_byte_id.info=ID \u0443\u0437\u043b\u0430 \u0432 \u0431\u0430\u0439\u0442\u043e\u0432\u043e\u0439 \u0444\u043e\u0440\u043c\u0435 Peers.column.handshake_reserved=\u0417\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0431\u0438\u0442\u044b Peers.column.handshake_reserved.info=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0431\u0438\u0442\u044b \u0431\u044b\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 BT Peers.column.client_identification=\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430 Peers.column.client_identification.info=\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043d\u0435\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0435 \u0438\u043c\u0435\u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u2014 \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 dht.warn.user=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043e \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435 NAT ConfigView.label.openbar.incomplete=\u0421\u043a\u0440\u0438\u043d\u043b\u0435\u0442\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a: \u0430\u0432\u0442\u043e\u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a ConfigView.label.openbar.complete=\u0430\u0432\u0442\u043e\u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 ConfigView.label.transferbar.remember_location=\u0417\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043d\u043b\u0435\u0442\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a ConfigView.section.transfer.autospeed.forcemin=%1 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0431\u044b\u043b\u0430 \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430 \u043f\u0440\u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f MainWindow.menu.tools.speedtest=\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c... speedtest.wizard.title=\u0422\u0435\u0441\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 speedtest.wizard.run=\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 speedtest.wizard.test.mode.updown=\u0440\u0430\u0437\u0434\u0430\u0447\u0430 \u0438 \u043f\u0440\u0438\u0451\u043c speedtest.wizard.test.mode.up=\u0440\u0430\u0437\u0434\u0430\u0447\u0430 speedtest.wizard.test.mode.down=\u043f\u0440\u0438\u0451\u043c SpeedTestWizard.test.panel.currinfo=\u0422\u0435\u0441\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 BitTorrent. SpeedTestWizard.test.panel.label=\u0422\u0435\u0441\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 Vuze: SpeedTestWizard.test.panel.already.running=\u0422\u0435\u0441\u0442 \u0443\u0436\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d! SpeedTestWizard.test.panel.not.accepted=\u0417\u0430\u043f\u0440\u043e\u0441 \u0442\u0435\u0441\u0442\u0430 \u043d\u0435 \u0431\u044b\u043b \u043e\u0442\u043a\u043b\u043e\u043d\u0451\u043d: SpeedTestWizard.test.panel.abort=\u041f\u0440\u0435\u0440\u0432\u0430\u0442\u044c SpeedTestWizard.test.panel.abort.countdown=\u041e\u0442\u043c\u0435\u043d\u0430 \u0442\u0435\u0441\u0442\u0430 \u0447\u0435\u0440\u0435\u0437: SpeedTestWizard.test.panel.test.countdown=\u0442\u0435\u0441\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437: SpeedTestWizard.test.panel.testfailed=\u0422\u0435\u0441\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0441\u044f \u043d\u0435\u0443\u0434\u0430\u0447\u0435\u0439 SpeedTestWizard.test.panel.aborted=\u0422\u0435\u0441\u0442 \u043f\u0440\u0435\u0440\u0432\u0430\u043d \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c. SpeedTestWizard.test.panel.enc.label=\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c: SpeedTestWizard.test.panel.standard=\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e SpeedTestWizard.test.panel.encrypted=\u0441 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c SpeedTestWizard.set.upload.button.apply=\u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c SpeedTestWizard.set.upload.result=\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0442\u0435\u0441\u0442\u0430 SpeedTestWizard.set.upload.bytes.per.sec=\u041a\u0411/\u0441 SpeedTestWizard.set.upload.bits.per.sec=\u0431\u0438\u0442/\u0441 SpeedTestWizard.finish.panel.title=\u0422\u0435\u0441\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d! SpeedTestWizard.finish.panel.click.close=\u0422\u0435\u0441\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d. SpeedTestWizard.finish.panel.max.upload=\u041c\u0430\u043a\u0441. \u0440\u0430\u0437\u0434\u0430\u0447\u0430: SpeedTestWizard.finish.panel.max.seeding.upload=\u041c\u0430\u043a\u0441. \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u0440\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0435: SpeedTestWizard.finish.panel.max.download=\u041c\u0430\u043a\u0441. \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430: SpeedTestWizard.finish.panel.enabled=\u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e SpeedTestWizard.finish.panel.disabled=\u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043e SpeedTestWizard.abort.message.scheduled.in=\u0442\u0435\u0441\u0442 \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d \u0447\u0435\u0440\u0435\u0437 ... %1 \u0441\u0435\u043a\u0443\u043d\u0434" SpeedTestWizard.abort.message.unsupported.type=\u0422\u0438\u043f \u0442\u0435\u0441\u0442\u0430 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f! SpeedTestWizard.abort.message.manual.abort=\u041f\u0440\u0435\u0440\u0432\u0430\u043d \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c SpeedTestWizard.abort.message.scheduling.failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442 SpeedTestWizard.abort.message.download.added=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0432 \u0445\u043e\u0434\u0435 \u0442\u0435\u0441\u0442\u0430 %1 SpeedTestWizard.abort.message.entered.error=\u0422\u0435\u0441\u0442 \u043f\u0440\u0438\u0451\u043c\u0430 \u0431\u044b\u043b \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u00ab%1\u00bb SpeedTestWizard.abort.message.entered.queued=\u0422\u0435\u0441\u0442 \u043f\u0440\u0438\u0451\u043c\u0430 \u0431\u044b\u043b \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c/\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d SpeedTestWizard.abort.message.interrupted=TorrentSpeedTestMonitorThread \u0431\u044b\u043b \u043f\u0440\u0435\u0440\u0432\u0430\u043d \u0434\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430 SpeedTestWizard.abort.message.execution.failed=\u0417\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u0430 \u043d\u0435 \u0443\u0434\u0430\u043b\u0441\u044f SpeedTestWizard.abort.message.failed.peers=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c\u0441\u044f \u0441 \u0443\u0437\u043b\u0430\u043c\u0438 SpeedTestWizard.abort.message.insufficient.slots=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0440\u0430\u0437\u0434\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u0430\u043c \u2014 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043b\u043e\u0442\u043e\u0432 \u0440\u0430\u0437\u0434\u0430\u0447\u0438? SpeedTestWizard.abort.message.not.unchoked=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u0438\u043d\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0438 \u043e\u0442 \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430 (\u043d\u0438 \u043e\u0434\u0438\u043d \u043d\u0435 \u043f\u0440\u0438\u043d\u044f\u043b \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435) SpeedTestWizard.stage.message.requesting=\u0437\u0430\u043f\u0440\u043e\u0441 \u0442\u0435\u0441\u0442\u0430... SpeedTestWizard.stage.message.preparing=\u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0442\u0435\u0441\u0442\u0430... SpeedTestWizard.stage.message.starting=\u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u0430... SpeedTestWizard.stage.message.connect.stats=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f: \u0443\u0437\u043b\u043e\u0432=%1, down_ok=%2, up_ok=%3 window.uiswitcher.title=\u0412\u044b\u0431\u043e\u0440 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 Vuze window.uiswitcher.text=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043b\u0443\u0447\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u0430\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442. window.uiswitcher.NewUI.text=* \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043d\u043e\u0432\u0438\u0447\u043a\u043e\u0432 \u0438 \u043d\u0435\u0438\u0441\u043a\u0443\u0448\u0451\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.\n\n* \u041f\u0440\u043e\u0441\u0442\u043e\u0439, \u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\n\n* \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0447\u0435\u0440\u0435\u0437 Vuze window.uiswitcher.ClassicUI.title=\u041a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 window.uiswitcher.ClassicUI.text=* \u041e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043e\u043c \u0441\u0435\u0440\u0438\u0438 2.x\n\n* \u041a\u043e\u043d\u0442\u0435\u043d\u0442 Vuze \u0432 \u044d\u0442\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d window.uiswitcher.bottom.text=\u0412\u044b\u0431\u043e\u0440 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441 \u043b\u0451\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u0438\u0437\u043c\u0435\u043d\u0451\u043d \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u043a\u043d\u0430 \u0432\u044b\u0431\u043e\u0440\u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 Vuze iconBar.switch.tooltip=\u0412\u044b\u0431\u043e\u0440 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 Vuze VivaldiView.notAvailable=\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u0412\u0438\u0432\u0430\u043b\u044c\u0434\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 restart.error=\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0435 \u0443\u0434\u0430\u043b\u0441\u044f:\n%1\n\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 restarting issues. restart.error.oom=\u041f\u0430\u043c\u044f\u0442\u044c \u0438\u0441\u0447\u0435\u0440\u043f\u0430\u043d\u0430 restart.error.fnf=\u00ab%1\u00bb \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d \u0432 \u00ab%2\u00bb restart.error.pnf=\u041f\u0443\u0442\u044c \u00ab%1\u00bb \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d restart.error.bad=\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0444\u0430\u0439\u043b\u0430 \u0434\u043b\u044f \u00ab%1\u00bb restart.error.denied=\u041f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u00ab%1\u00bb \u0434\u043e\u0441\u0442\u0443\u043f \u0431\u044b\u043b \u0437\u0430\u043f\u0440\u0435\u0449\u0451\u043d. \u0423\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044c\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0430\u0432 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b. TableColumn.header.date_completed=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e \u0432 TableColumn.menu.date_added.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0434\u0430\u0442\u0443 ConfigView.section.ipfilter.discardbanning=\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0437\u043b\u044b, \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u00ab\u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u0431\u0440\u043e\u0448\u0435\u043d\u043e/\u043f\u0440\u0438\u043d\u044f\u0442\u043e\u00bb \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 [0: \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043e] ConfigView.section.ipfilter.discardminkb=\u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0435\u0441\u043b\u0438 \u0431\u044b\u043b\u043e \u043e\u0442\u0431\u0440\u043e\u0448\u0435\u043d\u043e \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 (%1) ConfigView.interface.start.advanced=\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 (AZ 2.x) MyTorrents.column.ColumnQuality=\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e MyTorrents.column.ColumnSpeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c MyTorrents.column.ColumnProgressETA.2ndLine=\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c: %1 MyTorrents.column.ColumnProgressETA.StreamReady=\u041f\u043e\u0442\u043e\u043a \u0433\u043e\u0442\u043e\u0432 MyTorrents.column.ColumnProgressETA.PlayableIn=\u0413\u043e\u0442\u043e\u0432 \u043a \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0443 \u0447\u0435\u0440\u0435\u0437 %1 TableColumn.header.Quality=\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e TableColumn.header.Speed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c TableColumn.header.RateIt=\u041e\u0446\u0435\u043d\u0438\u0442\u044c TableColumn.header.Rating=\u041e\u0446\u0435\u043d\u043a\u0430 TableColumn.header.SpeedGraphic=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c TableColumn.header.AzProduct=\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a TableColumn.header.MediaThumb=\u041c\u0435\u0434\u0438\u0430 TableColumn.header.ProgressETA=\u041f\u0440\u043e\u0433\u0440\u0435\u0441\u0441 #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=\u0422\u0438\u043f \u0444\u0430\u0439\u043b\u0430: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.browse=\u0412 Vuze v3.MainWindow.tab.library=\u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 v3.MainWindow.tab.publish=\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 v3.MainWindow.tab.advanced=\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0439 v3.MainWindow.menu.browse=&\u0412 Vuze v3.MainWindow.menu.library=&\u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 v3.MainWindow.menu.publish=&\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f v3.MainWindow.menu.advanced=&\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0439 v3.MainWindow.menu.view.searchbar=\u041f\u0430\u043d\u0435\u043b\u044c \u043f\u043e\u0438\u0441\u043a\u0430 v3.MainWindow.menu.view.tabbar=\u041f\u0430\u043d\u0435\u043b\u044c \u0432\u043a\u043b\u0430\u0434\u043e\u043a v3.MainWindow.currentDL=\u0421\u0435\u0439\u0447\u0430\u0441 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f v3.MainWindow.button.stream=\u041f\u043e\u0442\u043e\u043a v3.MainWindow.button.stop=\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c v3.MainWindow.button.start=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c v3.MainWindow.button.pause=\u041f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c v3.MainWindow.button.resume=\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c v3.MainWindow.button.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c v3.MainWindow.button.comment=\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c v3.MainWindow.button.viewdetails=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 v3.MainWindow.button.play=\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 v3.MainWindow.button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c v3.MainWindow.button.preview=\u041f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 v3.MainWindow.view.wait=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430, \u043f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435. v3.MainWindow.xofx=%1 \u0438\u0437 %2 v3.MainWindow.Loading=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430... v3.filter-bar=\u0424\u0438\u043b\u044c\u0442\u0440: v3.MainWindow.search.defaultText=\u043d\u0430\u0439\u0442\u0438... v3.mb.delPublished.title=\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0443 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 v3.mb.delPublished.text=\u0412\u041d\u0418\u041c\u0410\u041d\u0418\u0415: \u042d\u0442\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u041d\u0415 \u0443\u0434\u0430\u043b\u0438\u0442 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u00ab%1\u00bb \u0438\u0437 %3 .\n\n\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u00ab\u0423\u0434\u0430\u043b\u0438\u0442\u044c\u00bb \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c, \u043d\u043e \u043f\u0440\u0435\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0435\u0433\u043e. \u041f\u0435\u0440\u0435\u0434 \u044d\u0442\u0438\u043c \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0440\u0430\u0437\u0434\u0430\u0447\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430 (\u043a\u0430\u043a?).\n\n\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u00ab\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c\u00bb, \u0435\u0441\u043b\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0438\u0437 %3, \u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u043a\u043d\u043e\u043f\u043a\u043e\u0439 (X) \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438.\n\n\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435....\n\n v3.mb.delPublished.delete=&\u0423\u0434\u0430\u043b\u0438\u0442\u044c v3.mb.delPublished.cancel=\u041e&\u0442\u043c\u0435\u043d\u0438\u0442\u044c v3.mb.openFile.title=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0444\u0430\u0439\u043b v3.mb.openFile.text.known=Vuze Player \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u0442\u0438\u043f \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 Playback Guide.\n\n\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0442\u0438\u043f \u0444\u0430\u0439\u043b\u0430: %2 (%3)\n v3.mb.openFile.text.unknown=Vuze Player \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u0442\u0438\u043f \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 Playback Guide.\n\n\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430: %2\n v3.mb.openFile.button.play=\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 v3.mb.openFile.button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c v3.mb.openFile.button.guide=\u0421\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044e v3.mb.openFile.remember=\u0412\u0441\u0435\u0433\u0434\u0430 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b v3.mb.PlayFileNotFound.title=\u0424\u0430\u0439\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d v3.mb.PlayFileNotFound.text=\u0424\u0430\u0439\u043b\u044b \u00ab%1\u00bb \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0438\u043b\u0438 \u0431\u044b\u043b\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u044b. v3.mb.PlayFileNotFound.button.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u0437 Vuze v3.mb.PlayFileNotFound.button.redownload=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u043d\u043e\u0432\u0430 v3.mb.PlayFileNotFound.button.find=\u041d\u0430\u0439\u0442\u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e... v3.mb.deletePurchased.title=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0451\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442 v3.mb.deletePurchased.text=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u00ab%1\u00bb?\n\n\u042d\u0442\u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043b\u0438\u0431\u043e \u0431\u044b\u043b \u0432\u0430\u043c\u0438 \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0451\u043d, \u043b\u0438\u0431\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. v3.mb.deletePurchased.button.delete=&\u0423\u0434\u0430\u043b\u0438\u0442\u044c v3.mb.deletePurchased.button.cancel=\u041e&\u0442\u043c\u0435\u043d\u0438\u0442\u044c v3.topbar.menu.show.logo=\u041b\u043e\u0433\u043e\u0442\u0438\u043f v3.topbar.menu.show.plugin=\u041e\u0431\u043b\u0430\u0441\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u0435\u0439 v3.topbar.menu.show.search=\u041d\u0430\u0439\u0442\u0438 splash.initializeCore=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044f\u0434\u0440\u0430 splash.initializeUIElements=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 ConfigView.section.transfer.autospeedbeta=\u0410\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c (\u0431\u0435\u0442\u0430) # ConfigView.section.ipfilter.peerblocking.group=\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u0443\u0437\u043b\u043e\u0432 ConfigView.section.ipfilter.autoload.group=\u0410\u0432\u0442\u043e\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 ConfigView.section.ipfilter.autoload.file=\u0424\u0430\u0439\u043b \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 IP \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 ConfigView.section.ipfilter.autoload.info=\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u044b DAT (eMule), P2P (PeerGuardian, splist), \u0438 P2B v1,2,3 (PeerGuardian 2). \u0424\u0430\u0439\u043b \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438\u043b\u0438 \u043f\u043e URL, \u0441\u0436\u0430\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ZIP/GZIP \u0438\u043b\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0435\u0441\u0436\u0430\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442. URL \u0431\u0443\u0434\u0443\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0435 7 \u0434\u043d\u0435\u0439, \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0447\u0435\u0440\u0435\u0437 \u043c\u0438\u043d\u0443\u0442\u0443 \u043f\u043e\u0441\u043b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f/\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f. ConfigView.section.ipfilter.autoload.loadnow=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c splash.loadIpFilters=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 IP-\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432... SpeedTestWizard.set.upload.title=\u041f\u0440\u0435\u0434\u0435\u043b\u044b \u043f\u0440\u0438\u0451\u043c\u0430 \u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438 SpeedTestWizard.set.download.label=\u041f\u0440\u0435\u0434\u0435\u043b \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043f\u0440\u0438\u0451\u043c\u0430: SpeedTestWizard.set.upload.label=\u041f\u0440\u0435\u0434\u0435\u043b \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438: SpeedTestWizard.name.conf.level.absolute=\u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u044b\u0439 SpeedTestWizard.name.conf.level.high=\u0412\u044b\u0441\u043e\u043a\u0438\u0439 SpeedTestWizard.name.conf.level.med=\u0421\u0440\u0435\u0434\u043d\u0438\u0439 SpeedTestWizard.name.conf.level.low=\u041d\u0438\u0437\u043a\u0438\u0439 SpeedTestWizard.name.conf.level.none=\u041d\u0435\u0442 ConfigView.section.transfer.select=\u0410\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c ConfigView.section.transfer.select.v2=\u0410\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c (\u0431\u0435\u0442\u0430) mb.azmustclose.title=\u041e\u0448\u0438\u0431\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 mb.azmustclose.text=\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 Vuze \u0434\u043e\u043b\u0436\u043d\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0438\u0437-\u0437\u0430 \u043e\u0448\u0438\u0431\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u0432\u0435\u043b\u0430 \u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e Vuze \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430.\n\n\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f Vuze \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0432\u0440\u0443\u0447\u043d\u0443\u044e. network.ipv6.prefer.addresses=\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c IPv6, \u0435\u0441\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b IPv6 \u0438 IPv4 network.bindError=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438\u0437-\u0437\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u043a IP. network.enforce.ipbinding=\u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u043a \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0430\u0434\u0440\u0435\u0441\u0443 IP, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b (\u0432 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0441\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u044b) DHTView.title.full_v6=\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u0411\u0414 IPv6 ConfigView.pluginlist.loadSelected=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 SpeedView.stats.asn=\u0421\u0435\u0442\u044c: SpeedView.stats.estupcap=\u041c\u0430\u043a\u0441. \u0440\u0430\u0437\u0434\u0430\u0447\u0430: SpeedView.stats.estdowncap=\u041c\u0430\u043a\u0441. \u043f\u0440\u0438\u0451\u043c: SpeedView.stats.unknown=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e SpeedView.stats.estimate=\u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e SpeedView.stats.measured=\u0438\u0437\u043c\u0435\u0440\u0435\u043d\u043e SpeedView.stats.measuredmin=\u0438\u0437\u043c\u0435\u0440\u0435\u043d\u043e \u043c\u0438\u043d. SpeedView.stats.manual=\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043e ConfigView.section.transfer.autospeed.networks=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0435\u0442\u0438 ConfigView.section.transfer.autospeed.resetnetwork=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0435\u0442\u0438 ConfigView.section.transfer.autospeed.network.info=\u0414\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u043e\u0431\u043c\u0435\u043d\u0435 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u043b\u0438 \u043f\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c \u0442\u0435\u0441\u0442\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438. \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e.\n\u0412\u0441\u0435 \u043d\u0435\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438. \n\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0438\u043f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u0423\u0447\u0442\u0438\u0442\u0435, \u0447\u0442\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0438\u0437\u043c\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u0432 %1. dialog.uiswitcher.restart.title=\u0412\u044b\u0431\u043e\u0440 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 Vuze: \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a dialog.uiswitcher.restart.text=\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a Vuze. TrayWindow.menu.close=\u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0441\u043a\u0440\u0438\u043d\u043b\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a # Used for peers which we can't determine. PeerSocket.unknown=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e PeerSocket.bad_peer_id=\u043d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 ID \u0443\u0437\u043b\u0430 PeerSocket.mismatch_id=\u043d\u0435\u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 PeerSocket.unknown_az_style=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e %1/%2 PeerSocket.unknown_shadow_style=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e %1/%2 OpenTorrentWindow.mb.askCreateDir.title=\u041f\u0430\u043f\u043a\u0430 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 OpenTorrentWindow.mb.askCreateDir.text=\u041f\u0430\u043f\u043a\u0430 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u00ab%1\u00bb \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.\n\n\u0421\u043e\u0437\u0434\u0430\u0442\u044c? SpeedView.stats.estimatechoke=\u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e (\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e) ConfigTransferAutoSpeed.upload.capacity.usage=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u043d\u0430\u043b\u0430 \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0438 ConfigTransferAutoSpeed.mode=\u0420\u0435\u0436\u0438\u043c: ConfigTransferAutoSpeed.capacity.used=\u041f\u0440\u043e\u0446\u0435\u043d\u0442 \u043e\u0442 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0438 ConfigTransferAutoSpeed.while.downloading=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430: ConfigTransferAutoSpeed.set.point=\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0443 (\u043c\u0441) ConfigTransferAutoSpeed.set.tolerance=\u043f\u043e\u0433\u0440\u0435\u0448\u043d\u043e\u0441\u0442\u044c (\u043c\u0441) ConfigTransferAutoSpeed.ping.time.good=\u0425\u043e\u0440\u043e\u0448\u0438\u0439: ConfigTransferAutoSpeed.ping.time.bad=\u041f\u043b\u043e\u0445\u043e\u0439: ConfigTransferAutoSpeed.adjustment.interval=\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u043a\u0438: ConfigTransferAutoSpeed.skip.after.adjust=\u041f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u043a\u0438: GeneralView.label.distributedCopies=\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u043a\u043e\u043f\u0438\u0439: PiecesView.DistributionView.title=\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0447\u0430\u0441\u0442\u0435\u0439 PiecesView.DistributionView.NoAvl=\u041d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 PiecesView.DistributionView.SeedAvl=\u0412\u0437\u043d\u043e\u0441 \u0443\u0437\u043b\u0430 \u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c PiecesView.DistributionView.PeerAvl= PiecesView.DistributionView.RarestAvl=\u0420\u0435\u0434\u043a\u0438\u0435: %1 (\u0414\u043e\u0441\u0442.:%2) PiecesView.DistributionView.weHave=\u0418\u043c\u0435\u044e\u0449\u0438\u0435\u0441\u044f \u0447\u0430\u0441\u0442\u0438 PiecesView.DistributionView.theyHave=\u0427\u0430\u0441\u0442\u0438 \u0443\u0437\u043b\u0430 PiecesView.DistributionView.weDownload=\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 PeersView.gain=\u041f\u0440\u0438\u0431\u044b\u043b\u044c PeersView.gain.info=\u041e\u0431\u044a\u0451\u043c \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0438\u043d\u0443\u0441 \u043e\u0431\u044a\u0451\u043c \u0440\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 unix.script.new.title=\u0414\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u043e\u0432\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Vuze unix.script.new.text=\u041d\u043e\u0432\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Vuze \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d \u0432 \u00ab%1\u00bb.\n\n\u041d\u0430\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u0439\u0442\u0438 \u0438\u0437 Vuze \u0438 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 (\u00ab%2\u00bb).\n\n\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0432\u0430\u043c\u0438 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435\u0439 AzureusWiki: Unix Script.\n\n\u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0431\u044b\u043b\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 (yum, apt-get, etc), \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c Vuze \u0438\u0437 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0430\u043a\u0435\u0442\u0430 \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b Vuze \u043d\u0430 Sourceforge (\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u043c \u0436\u0435, \u043a\u0430\u043a \u0441\u0435\u0439\u0447\u0430\u0441) unix.script.new.button.quit=\u0412\u044b\u0439\u0442\u0438 \u0441\u0435\u0439\u0447\u0430\u0441 unix.script.new.button.continue=\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043f\u043e\u0437\u0436\u0435 unix.script.new.button.asknomore=\u041d\u0435 \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0442\u044c \u0441\u043d\u043e\u0432\u0430 unix.script.new.auto.title=\u041d\u043e\u0432\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Vuze unix.script.new.auto.text=\u0414\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u043e\u0432\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Vuze.\n\n\u041d\u0430\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Vuze. Content.alert.notuploaded.button.stop=\u041e&\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c Content.alert.notuploaded.button.continue=&\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0443 Content.alert.notuploaded.button.abort=&\u041d\u0435 \u0432\u044b\u0445\u043e\u0434\u0438\u0442\u044c ConfigView.label.checkOnSeeding=\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043d\u0435\u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0451\u043c\u043a\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u0440\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0435 ConfigView.label.ui_switcher=\u041e\u043a\u043d\u043e \u0432\u044b\u0431\u043e\u0440\u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 Vuze ConfigView.label.ui_switcher_button=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c SpeedTestWizard.test.panel.explain=\u0418\u0437\u043c\u0435\u0440\u044c\u0442\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c Vuze. \u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0438\u043f \u0442\u0435\u0441\u0442\u0430 \u0438 \u0440\u0435\u0436\u0438\u043c \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043e \u0442\u0435\u0441\u0442\u0435 \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u044b \u0432 \u0412\u0438\u043a\u0438 Vuze. \u0422\u0435\u0441\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0435\u0441\u043b\u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u043b\u044c\u0448\u0435 \u0434\u0432\u0443\u0445 \u043c\u0438\u043d\u0443\u0442. \u041e\u0431\u044b\u0447\u043d\u043e \u0442\u0435\u0441\u0442 \u0434\u043b\u0438\u0442\u0441\u044f \u043d\u0435 \u0434\u043e\u043b\u044c\u0448\u0435 \u043c\u0438\u043d\u0443\u0442\u044b. SpeedTestWizard.set.upload.hint=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u043e\u0432 \u043f\u0440\u0438\u0451\u043c\u0430 \u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0435 \u0430\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 Vuze. SpeedTestWizard.set.upload.panel.explain=\u041f\u0440\u0435\u0434\u0435\u043b\u044b, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0437\u0434\u0435\u0441\u044c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0435 \u0430\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u0438 \u0442\u0438\u043f \u043f\u0440\u0435\u0434\u0435\u043b\u043e\u0432.\n\n\u0423\u0447\u0442\u0438\u0442\u0435, \u0447\u0442\u043e \u0447\u0430\u0441\u0442\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u044b \u0432 \u0431\u0438\u0442/\u0441, \u043d\u043e \u043d\u0438\u0436\u0435 \u043e\u043d\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432 \u0431\u0430\u0439\u0442/\u0441. SpeedTestWizard.set.limit.conf.level=\u0422\u0438\u043f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f SpeedTestWizard.finish.panel.auto.speed=\u0410\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c: SpeedTestWizard.finish.panel.auto.speed.seeding=\u0410\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0435: ConfigTransferAutoSpeed.add.comment.to.log.group=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u0432 \u0436\u0443\u0440\u043d\u0430\u043b ConfigTransferAutoSpeed.add.comment.to.log=\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439: ConfigTransferAutoSpeed.log.button=\u0416\u0443\u0440\u043d\u0430\u043b ConfigTransferAutoSpeed.algorithm.selector=\u0412\u044b\u0431\u043e\u0440 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0430\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 ConfigTransferAutoSpeed.algorithm=\u0421\u0445\u0435\u043c\u0430: ConfigTransferAutoSpeed.auto.speed.classic=\u0410\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c (\u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0430\u044f) ConfigTransferAutoSpeed.auto.speed.beta=\u0410\u0432\u0442\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c (\u0431\u0435\u0442\u0430) ConfigTransferAutoSpeed.data.update.frequency=\u0427\u0430\u0441\u0442\u043e\u0442\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f Alert.failed.update=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435: AzureusWiki: \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c [%1] OpenTorrentWindow.mb.existingFiles.partialList=(\u041d\u0435\u043f\u043e\u043b\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u0444\u0430\u0439\u043b\u043e\u0432) TableColumn.header.bad_avail_time.info=\u0412\u0440\u0435\u043c\u044f, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u043d\u0430\u044f \u043a\u043e\u043f\u0438\u044f \u0431\u044b\u043b\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0440\u0430\u0437 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 TableColumn.header.bad_avail_time=\u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u043f\u043e\u043b\u043d\u043e\u0439 \u043a\u043e\u043f\u0438\u0438 MyTorrentsView.menu.exporthttpseeds=\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c URL HTTP-\u0440\u0430\u0437\u0434\u0430\u0447\u0438 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430 SWT.alert.erroringuithread=\u0412 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043d\u0435\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438. ConfigView.label.minannounce=\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043c\u0435\u0436\u0434\u0443 \u0430\u043d\u043e\u043d\u0441\u0430\u043c\u0438 (\u0441) ConfigView.label.maxnumwant=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u0437\u043b\u043e\u0432, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u043c ConfigView.label.announceport=\u041f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0440\u0442 TCP \u0434\u043b\u044f \u0430\u043d\u043e\u043d\u0441\u043e\u0432, PEX \u0438 DHT.\n[\u043f\u0443\u0441\u0442\u043e\u0435 \u043f\u043e\u043b\u0435: \u043d\u0435 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c, 0: \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f] ConfigView.label.noportannounce=\u041d\u0435 \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 (\u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0430 \u043d\u0430 PEX \u0438 \u0420\u0411\u0414) ConfigView.label.maxseedspertorrent=\u041c\u0430\u043a\u0441. \u0440\u0430\u0437\u0434\u0430\u044e\u0449\u0438\u0445 \u043d\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] wizard.webseed=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0443 HTTP-\u0440\u0430\u0437\u0434\u0430\u0447\u0438 wizard.webseed.title=HTTP-\u0440\u0430\u0437\u0434\u0430\u0447\u0438 wizard.webseed.configuration=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 HTTP-\u0440\u0430\u0437\u0434\u0430\u0447\u0438 wizard.webseed.adding=\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 HTTP-\u0440\u0430\u0437\u0434\u0430\u0447 GeneralView.label.private=\u0417\u0430\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442: GeneralView.yes=\u0414\u0430 GeneralView.no=\u041d\u0435\u0442 ConfigView.label.userequestlimiting=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u043d\u0435 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 [\u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0430, \u0435\u0441\u043b\u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430] ConfigView.label.userequestlimiting.tooltip=\u041c\u0435\u0442\u043e\u0434 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0435 \u0442\u0430\u043a\u043e\u0439 \u043f\u043b\u0430\u0432\u043d\u044b\u0439, \u043a\u0430\u043a \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u0447\u0442\u0435\u043d\u0438\u044f, \u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u044b \u043f\u043e \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0432\u044b\u0441\u0438\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c ConfigView.label.userequestlimitingpriorities=\u041f\u0440\u0438 \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0438 \u043f\u0440\u0435\u0434\u0435\u043b\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043f\u0440\u0438\u0451\u043c\u0430 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0435\u043d\u0438\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430\u043c \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 ConfigView.section.logging.timestamp=\u0424\u043e\u0440\u043c\u0430\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0436\u0443\u0440\u043d\u0430\u043b\u0430 Peers.column.timetocomplete=\u041e\u0441\u0442\u0430\u0432\u0448\u0435\u0435\u0441\u044f \u0432\u0440\u0435\u043c\u044f Peers.column.timetocomplete.info=\u0412\u0440\u0435\u043c\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0437\u043b\u0443 \u0434\u043b\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f ConfigView.section.interface.display.suppress.file.download.dialog=\u041d\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0434\u0438\u0430\u043b\u043e\u0433 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0430\u0439\u043b\u0430 ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0430 \u043d\u0435 \u0432\u043e \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0435\u043c \u043e\u043a\u043d\u0435 FileDownload.canceled=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0444\u0430\u0439\u043b\u0430 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u0431\u044b\u043b\u0430 \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u0430 \u043f\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f: %1 Progress.reporting.status.canceled=\u041e\u0442\u043c\u0435\u043d\u0435\u043d\u043e Progress.reporting.status.finished=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e Progress.reporting.status.retrying=\u041f\u043e\u0432\u0442\u043e\u0440... Progress.reporting.action.label.retry.tooltip=\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 Progress.reporting.action.label.remove.tooltip=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u043e\u0442\u0447\u0451\u0442 \u0438\u0437 \u0436\u0443\u0440\u043d\u0430\u043b\u0430 Progress.reporting.action.label.cancel.tooltip=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 Progress.reporting.action.label.detail=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 Progress.reporting.default.error=\u041e\u0448\u0438\u0431\u043a\u0430 Progress.reporting.no.reports.to.display=\u041e\u0442\u0447\u0451\u0442\u044b \u043e\u0431 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0445 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442. Progress.reporting.no.history.to.display=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442. Progress.reporting.detail.history.limit=\u041f\u0440\u0435\u0434\u0435\u043b \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 (%1) \u0431\u044b\u043b \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442; \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b \u0432 \u0436\u0443\u0440\u043d\u0430\u043b Progress.reporting.statusbar.button.tooltip=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u043a\u043d\u043e \u043e\u0442\u0447\u0451\u0442\u0430 \u043e\u0431 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 webui.bindip=\u0410\u0434\u0440\u0435\u0441 IP \u0434\u043b\u044f \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u2014 \u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f (*) v3.MainWindow.text.log.in=\u0412\u043e\u0439\u0442\u0438 v3.MainWindow.text.log.out=\u0412\u044b\u0439\u0442\u0438 v3.MainWindow.text.get.started=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0443\u0447\u0451\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c v3.MainWindow.text.my.account=\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e\u0431 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 v3.MainWindow.text.my.profile=\u041f\u0440\u043e\u0444\u0438\u043b\u044c OpenTorrentWindow.simple.open=\u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 (\u0444\u0430\u0439\u043b, URL, \u0445\u0435\u0448) Progress.reporting.window.remove.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0441\u0442\u0430\u0440\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 Progress.reporting.window.remove.auto.tooltip=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0432\u0441\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0435, \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u044b\u0435 \u0438\u043b\u0438 \u043e\u0442\u043c\u0435\u043d\u0451\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 Progress.reporting.window.remove.now=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0442\u0430\u0440\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 Progress.reporting.window.remove.now.tooltip=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u0441\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0435, \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u044b\u0435 \u0438\u043b\u0438 \u043e\u0442\u043c\u0435\u043d\u0451\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 dhttracker.tracklimitedwhenonline=\u041d\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043d\u0435\u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0451\u043c\u043a\u043e\u0435 \u0441\u043b\u0435\u0436\u0435\u043d\u0438\u0435 \u0432 \u0446\u0435\u043b\u044f\u0445 \u043f\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f TorrentOptionsView.multi.title.short=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 TorrentOptionsView.multi.title.full=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 MyTorrentsView.menu.open_parent_folder=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043f\u0430\u043f\u043a\u0443 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c ConfigView.section.style.use_show_parent_folder=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u00ab%1\u00bb \u0432\u043c\u0435\u0441\u0442\u043e \u00ab%2\u00bb \u0432 \u043c\u0435\u043d\u044e \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 ConfigView.section.style.use_show_parent_folder.tooltip=\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0438 \u0432 \u043d\u0443\u0436\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u043c \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0435.\n\u041e\u0434\u043d\u0430\u043a\u043e, \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0442\u044c, \u0447\u0442\u043e \u043f\u0443\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0431\u0440\u0430\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438. PeerManager.status.ps_disabled=\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0443\u0437\u043b\u043e\u0432 \u043e\u0442\u043a\u043b\u044e\u0447\u0451\u043d \u043d\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0435 ConfigView.section.stats.exportfiles=\u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0444\u0430\u0439\u043b\u0430 updater.cant.write.to.app.title=\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0430\u0432 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u043f\u0430\u043f\u043a\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b updater.cant.write.to.app.details=\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0430\u0432 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u043f\u0430\u043f\u043a\u0443 \u00ab%1\u00bb.\n\n\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b.\n\n\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f. plugin.install.class_version_error=\u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438 Java. v3.MainWindow.tab.minilibrary=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0438 v3.MainWindow.tab.events=\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f button.columnsetup.tooltip=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432 v3.activity.remove.title=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 v3.activity.remove.text=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u0442\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=\u0417\u0430\u043a\u0440\u044b\u0442\u044c Menu.show.torrent.menu=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u043d\u044e \u00ab\u0422\u043e\u0440\u0440\u0435\u043d\u0442\u044b\u00bb Menu.show.torrent.menu.tooltip=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u043d\u044e \u00ab\u0422\u043e\u0440\u0440\u0435\u043d\u0442\u044b\u00bb \u0432 \u043c\u0435\u043d\u044e \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u0435\u0442\u0438 plugin.aznetstatus.pingtarget=\u0422\u0440\u0430\u0441\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u0434\u043e \u0446\u0435\u043b\u0438 ConfigView.section.style.usePathFinder=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u00abPath Finder\u00bb \u0432\u043c\u0435\u0441\u0442\u043e \u00abFinder\u00bb menu.sortByColumn=\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e %1 MyTorrentsView.menu.manual.per_peer=\u0417\u0430\u0434\u0430\u0442\u044c (\u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0443\u0437\u0435\u043b) MyTorrentsView.menu.manual.shared_peers=\u0417\u0430\u0434\u0430\u0442\u044c (\u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0443\u0437\u043b\u043e\u0432) v3.button.removeActivityEntry=\u0423\u0431\u0440\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 v3.splash.initSkin=\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 v3.splash.hookPluginUI=\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 OpenTorrentWindow.mb.notTorrent.cannot.display=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 MainWindow.menu.window.zoom.maximize=\u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c MainWindow.menu.window.zoom.restore=\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c ImageResizer.image.too.small=\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 (\u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c %1 \u043d\u0430 %2) ImageResizer.title=\u042d\u0442\u043e\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0430\u043a\u0438\u043c, \u043a\u0430\u043a\u0438\u043c \u043e\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0432 Vuze ImageResizer.move.image=\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0442\u044c \u043c\u044b\u0448\u044c\u044e ImageResizer.move.image.with.slider=\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0442\u044c \u043c\u044b\u0448\u044c\u044e \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u043e\u043b\u0437\u0443\u043d\u043a\u0430 \u043d\u0438\u0436\u0435 security.crypto.title=\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u043b\u044e\u0447\u0430\u043c \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f security.crypto.encrypt=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u0437\u0430\u0449\u0438\u0442\u044b \u043a\u043b\u044e\u0447\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u043e\u043b\u044c, \u0435\u0433\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c! security.crypto.decrypt=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u0441\u043d\u044f\u0442\u0438\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0441 \u043a\u043b\u044e\u0447\u0430 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f. security.crypto.reason=\u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u0434\u043b\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f security.crypto.password=\u041f\u0430\u0440\u043e\u043b\u044c security.crypto.password2=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c \u0435\u0449\u0451 \u0440\u0430\u0437 security.crypto.persist_for=\u0417\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c security.crypto.persist_for.dont_save=\u041d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c security.crypto.persist_for.session=\u042d\u0442\u043e\u0442 \u0441\u0435\u0430\u043d\u0441 security.crypto.persist_for.day=1 \u0434\u0435\u043d\u044c security.crypto.persist_for.week=1 \u043d\u0435\u0434\u0435\u043b\u044f security.crypto.persist_for.30days=30 \u0434\u043d\u0435\u0439 security.crypto.persist_for.forever=\u041d\u0430\u0432\u0441\u0435\u0433\u0434\u0430 security.crypto.password.mismatch.title=\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c security.crypto.password.mismatch=\u0412\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435 \u043f\u0430\u0440\u043e\u043b\u0438 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442, \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443. ConfigView.section.security.group.crypto=\u041e\u0442\u043a\u0440\u044b\u0442\u044b\u0435/\u0437\u0430\u043a\u0440\u044b\u0442\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 ConfigView.section.security.resetkey= ConfigView.section.security.resetkey.warning.title=\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0439 \u043f\u043e\u0442\u0435\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 ConfigView.section.security.resetkey.warning=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043a\u043b\u044e\u0447\u0438 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f? \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0432\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u0437\u0430\u0449\u0438\u0449\u0451\u043d\u043d\u0430\u044f \u0441 \u0438\u0445 \u043f\u043e\u043c\u043e\u0449\u044c\u044e, \u0431\u0443\u0434\u0435\u0442 \u041f\u041e\u0422\u0415\u0420\u042f\u041d\u0410 \u0411\u0415\u0417\u0412\u041e\u0417\u0412\u0420\u0410\u0422\u041d\u041e. \u041a\u0440\u043e\u043c\u0435 \u044d\u0442\u043e\u0433\u043e, \u0434\u0440\u0443\u0433\u0438\u0435 \u0443\u0437\u043b\u044b, \u0438\u043c\u0435\u044e\u0449\u0438\u0435 \u0432\u0430\u0448 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043b\u044e\u0447 \u043d\u0435 \u0441\u043c\u043e\u0433\u0443\u0442 \u043e\u0431\u043c\u0435\u043d\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0431\u0435\u0437 \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430. \u041d\u0435 \u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u044d\u0442\u043e\u0433\u043e, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0443\u0432\u0435\u0440\u0435\u043d\u044b \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u044d\u0442\u043e \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e. ConfigView.section.security.unlockkey=\u0420\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u044e\u0447\u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e ConfigView.section.security.unlockkey.button=\u0420\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c ConfigView.section.security.publickey=\u041e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043b\u044e\u0447 ConfigView.section.security.publickey.undef=\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d ConfigView.section.security.resetkey.error.title=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u0443\u0434\u0430\u043b\u0430\u0441\u044c ConfigView.section.security.resetkey.error=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043a\u043b\u044e\u0447\u0438 ConfigView.section.security.unlockkey.error=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0440\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u044e\u0447 \u2014 \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c ConfigView.copy.to.clipboard.tooltip=\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430 Views.plugins.azbuddy.title=\u0414\u0440\u0443\u0437\u044c\u044f Browser.popup.error.no.access=\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u043c\u0443 \u0440\u0435\u0441\u0443\u0440\u0441\u0443.\n\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u043f\u043e\u0437\u0434\u043d\u0435\u0435.\n ConfigView.label.queue.stoponcebandwidthmet=\u041d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b, \u043a\u043e\u0433\u0434\u0430 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442 \u043f\u0440\u0435\u0434\u0435\u043b \u0440\u0430\u0437\u0434\u0430\u0447\u0438/\u043f\u0440\u0438\u0451\u043c\u0430 ConfigView.section.style.forceMozilla=\u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0438\u0434\u0436\u0435\u0442\u044b Mozilla [\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f xulrunner \u0438\u043b\u0438 firefox 3; \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a] ConfigView.section.style.xulRunnerPath=\u0423\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u0434\u043e XulRunner / Firefox \u0432\u0440\u0443\u0447\u043d\u0443\u044e [\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f FF3; \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a] azbuddy.name=\u0414\u0440\u0443\u0437\u044c\u044f azbuddy.enabled=\u0412\u043a\u043b\u044e\u0447\u0451\u043d azbuddy.disabled=\u041c\u043e\u0434\u0443\u043b\u044c \u043e\u0442\u043a\u043b\u044e\u0447\u0451\u043d, \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u043c\u043e\u0434\u0443\u043b\u044f. azbuddy.nickname=\u041f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c azbuddy.msglog.title=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0434\u0440\u0443\u0433\u0435 azbuddy.addtorrent.title=\u041f\u0440\u0438\u043d\u044f\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443? azbuddy.addtorrent.msg=\u0412\u0430\u0448 \u0434\u0440\u0443\u0433 \u00ab%1\u00bb \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b \u0432\u0430\u043c \u00ab%2\u00bb.\n\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443? azbuddy.contextmenu=\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0440\u0443\u0433\u0443 azbuddy.ui.mykey=\u041c\u043e\u0439 \u043a\u043b\u044e\u0447: azbuddy.ui.add=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c azbuddy.ui.new_buddy=\u041d\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u0447 \u0434\u0440\u0443\u0433\u0430: azbuddy.ui.table.name=\u0418\u043c\u044f azbuddy.ui.table.online=\u0414\u043e\u0441\u0442\u0443\u043f\u0435\u043d azbuddy.ui.table.last_msg=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 azbuddy.ui.menu.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c azbuddy.ui.menu.copypk=\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043b\u044e\u0447 azbuddy.ui.menu.send=\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 azbuddy.ui.menu.send_msg=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043a\u0441\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0434\u0440\u0443\u0433\u0443 \u0438\u043b\u0438 \u0434\u0440\u0443\u0437\u044c\u044f\u043c azbuddy.ui.menu.ping=\u041f\u0438\u043d\u0433 azbuddy.ui.menu.ygm=\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c YGM azbuddy.ui.menu.enc=\u0417\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0431\u0443\u0444\u0435\u0440\u0430 \u043e\u0431\u043c\u0435\u043d\u0430 azbuddy.ui.menu.dec=\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0431\u0443\u0444\u0435\u0440\u0430 \u043e\u0431\u043c\u0435\u043d\u0430 azbuddy.ui.menu.sign=\u041f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0431\u0443\u0444\u0435\u0440\u0430 \u043e\u0431\u043c\u0435\u043d\u0430 azbuddy.ui.menu.verify=\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0431\u0443\u0444\u0435\u0440\u0430 \u043e\u0431\u043c\u0435\u043d\u0430 azbuddy.ui.table.lastseen=\u0411\u044b\u043b \u0432 \u0441\u0435\u0442\u0438 Button.retry=&\u041f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0441\u043d\u043e\u0432\u0430 Button.ignore=&\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c DHTView.general.skew=\u0410\u0441\u0441\u0438\u043c\u0435\u0442\u0440\u0438\u044f: azbuddy.ui.table.msg_in=\u0412\u0445\u043e\u0434\u044f\u0449\u0435\u0435 azbuddy.ui.table.msg_out=\u0418\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0435 azbuddy.downspeed=\u041a\u0411/\u0441 \u043c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0430 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] azbuddy.ui.table.con=\u0421\u043e\u0435\u0434 security.crypto.badpw=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0435\u0432\u0435\u0440\u0435\u043d ConfigView.section.security.backupkeys=\u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u044e\u0447\u0438 \u0432 \u0444\u0430\u0439\u043b ConfigView.section.security.backupkeys.button=\u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c ConfigView.section.security.restorekeys=\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043a\u043b\u044e\u0447\u0438 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 ConfigView.section.security.restorekeys.button=\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c ConfigView.section.security.op.error.title=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u0443\u0434\u0430\u043b\u0430\u0441\u044c ConfigView.section.security.op.error=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e:\n %1 ConfigView.section.security.restart.title=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a ConfigView.section.security.restart.msg=\u0414\u043b\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430. ConfigView.section.security.system.managed=\u0417\u0430\u0449\u0438\u0442\u0430 \u043a\u043b\u044e\u0447\u0435\u0439 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 \u041e\u0421 azbuddy.ui.table.msg_queued=\u0412 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 azbuddy.ui.menu.chat=\u0411\u0435\u0441\u0435\u0434\u0430 azbuddy.chat.title=\u0427\u0430\u0442 Vuze azbuddy.chat.says=%1 \u0441\u043a\u0430\u0437\u0430\u043b(\u0430): Button.bar.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c Button.bar.hide=\u0421\u043a\u0440\u044b\u0442\u044c Button.bar.share=\u041f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f Button.bar.add=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c Button.bar.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c Button.bar.edit.cancel=\u0413\u043e\u0442\u043e\u0432\u043e v3.MainWindow.menu.view.pluginbar=\u041f\u0430\u043d\u0435\u043b\u044c \u043c\u043e\u0434\u0443\u043b\u0435\u0439 MainWindow.dialog.select.vuze.file=\u0412\u044b\u0431\u043e\u0440 \u0444\u0430\u0439\u043b\u0430 Vuze MainWindow.menu.file.open.vuze=\u0424\u0430\u0439\u043b Vuze... metasearch.addtemplate.title=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d? metasearch.addtemplate.desc=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u00ab%1\u00bb? v3.share.private.title=\u041f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u043c v3.share.private.text=\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u044b\u043c.\n\n\u041d\u0435\u043b\u044c\u0437\u044f \u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u044b\u043c\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430\u043c\u0438. metasearch.addtemplate.dup.title=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d metasearch.addtemplate.dup.desc=\u041f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d \u00ab%1\u00bb \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d metasearch.export.select.template.file=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d metasearch.import.select.template.file=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d dialog.uiswitch.title=\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Vuze UI dialog.uiswitch.text=\u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Vuze UI.\n\n\u041f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a Vuze. dialog.uiswitch.button=\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Vuze UI azbuddy.tracker.enabled=\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u00ab\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443\u00bb \u0434\u0440\u0443\u0437\u0435\u0439, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u043e\u0431\u043c\u0435\u043d \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0441 \u043d\u0438\u043c\u0438 azbuddy.protocolspeed=\u041a\u0411/\u0441 \u043c\u0430\u043a\u0441. \u0442\u0440\u0430\u0444\u0438\u043a \u0434\u043b\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u0434\u0440\u0443\u0437\u0435\u0439 v3.MainWindow.button.download=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c v3.MainWindow.button.run=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b v3.activity.header.downloads=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0438 v3.activity.header.vuze.news=\u041d\u043e\u0432\u043e\u0441\u0442\u0438 Vuze message.taking.too.long=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0435\u043c \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043b\u043e\u0441\u044c\n\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u0435\u0451, \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0436\u0430\u0442\u044c \u00abESC\u00bb message.status.success=\u0423\u0441\u043f\u0435\u0448\u043d\u043e azbuddy.tracker.bbb.status.title=\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u0440\u0443\u0437\u0435\u0439 azbuddy.tracker.bbb.status.title.tooltip=\u0414\u0432\u043e\u0439\u043d\u043e\u0439 \u0449\u0435\u043b\u0447\u043e\u043a \u043e\u0442\u043a\u0440\u043e\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0441\u043f\u0440\u0430\u0432\u043a\u0438 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 azbuddy.tracker.bbb.status.idle=\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 azbuddy.tracker.bbb.status.nli=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f azbuddy.tracker.bbb.status.in=\u041c\u0435\u043d\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 azbuddy.tracker.bbb.status.out=\u0412 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0434\u0440\u0443\u0437\u044c\u044f v3.MainWindow.search.go.tooltip=\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a v3.MainWindow.search.last.tooltip=\u041d\u0430\u0437\u0430\u0434 \u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c \u043f\u043e\u0438\u0441\u043a\u0430 metasearch.addtemplate.done.title=\u0428\u0430\u0431\u043b\u043e\u043d \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d metasearch.addtemplate.done.desc=\u0428\u0430\u0431\u043b\u043e\u043d \u00ab%1\u00bb \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d.\n\u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d \u043f\u0440\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435. ConfigView.section.security.nopw=\u041f\u0430\u0440\u043e\u043b\u044c \u043d\u0435 \u0431\u044b\u043b \u0443\u043a\u0430\u0437\u0430\u043d ConfigView.section.security.nopw_v=\u041f\u0430\u0440\u043e\u043b\u044c \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d, \u0432\u043e\u0439\u0434\u0438\u0442\u0435 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 Vuze fileplugininstall.install.title=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u044c? fileplugininstall.install.desc=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u044c \u00ab%1\u00bb \u0432\u0435\u0440\u0441\u0438\u0438 %2? fileplugininstall.duplicate.title=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c fileplugininstall.duplicate.desc=\u041c\u043e\u0434\u0443\u043b\u044c \u00ab%1\u00bb \u0432\u0435\u0440\u0441\u0438\u0438 %2 \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d azbuddy.online_status=\u0421\u0442\u0430\u0442\u0443\u0441 azbuddy.os_online=\u0414\u043e\u0441\u0442\u0443\u043f\u0435\u043d azbuddy.os_away=\u041e\u0442\u043e\u0448\u0451\u043b azbuddy.os_not_avail=\u041d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d azbuddy.os_busy=\u0417\u0430\u043d\u044f\u0442 azbuddy.os_offline=\u041d\u0435 \u0432 \u0441\u0435\u0442\u0438 azbuddy.ui.menu.disconnect=\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f azbuddy.enable_chat_notif=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u0431\u0435\u0441\u0435\u0434\u0430\u0445 progress.window.msg.progress=\u041f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435, \u043f\u043e\u043a\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0441\u044f ConfigView.section.connection.advanced.read_select=\u041c\u0430\u043a\u0441. \u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0432\u044b\u0431\u043e\u0440\u0430 (\u043c\u0441, \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e %1) ConfigView.section.connection.advanced.read_select_min=\u041c\u0438\u043d. \u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0432\u044b\u0431\u043e\u0440\u0430 (\u043c\u0441, \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e %1) ConfigView.section.connection.advanced.write_select=\u041c\u0430\u043a\u0441. \u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u044b\u0431\u043e\u0440\u0430 (\u043c\u0441, \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e %1) ConfigView.section.connection.advanced.write_select_min=\u041c\u0438\u043d. \u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u044b\u0431\u043e\u0440\u0430 (\u043c\u0441, \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e %1) DetailedListView.title=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a ConfigView.section.connection.network.max.outstanding.connect.attempts=\u041c\u0430\u043a\u0441. \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 plugins.init.force_enabled=\u041c\u043e\u0434\u0443\u043b\u044c \u00ab%1\u00bb \u0431\u044b\u043b \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0451\u043d \u0434\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b Vuze. ConfigView.section.connection.prefer.udp=\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u043e UDP subscript.add.title=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443? subscript.add.desc=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 \u00ab%1\u00bb? subscript.add.dup.title=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0430\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 subscript.add.dup.desc=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u00ab%1\u00bb \u0443\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430. subscript.add.upgrade.title=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443? subscript.add.upgrade.desc=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 \u00ab%1\u00bb? subscript.add.upgradeto.desc=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044f %1 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u00ab%2\u00bb.\n\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c? azsubs.contextmenu.addassoc=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u044e \u043a \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 azsubs.contextmenu.lookupassoc=\u041d\u0430\u0439\u0442\u0438 \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 iconBar.start=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c iconBar.stop=\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c iconBar.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c iconBar.up=\u0412\u0432\u0435\u0440\u0445 iconBar.down=\u0412\u043d\u0438\u0437 iconBar.run=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c iconBar.editcolumns=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432 iconBar.top=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 \u0441\u0430\u043c\u044b\u0439 \u0432\u0435\u0440\u0445 iconBar.bottom=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 \u0441\u0430\u043c\u044b\u0439 \u043d\u0438\u0437 iconBar.queue= iconBar.open=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u0440\u0440\u0435\u043d\u0442 iconBar.share=\u041f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f iconBar.share.tooltip=\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u043e\u0431\u0449\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c iconBar.details=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 iconBar.comment=\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c iconBar.play=\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 iconBar.queue.tooltip=B \u043e\u0447\u0435\u0440\u0435\u0434\u044c v3.MainWindow.menu.view.sidebar=\u0411\u043e\u043a\u043e\u0432\u0430\u044f \u043f\u0430\u043d\u0435\u043b\u044c v3.MainWindow.menu.view.actionbar=\u041f\u0430\u043d\u0435\u043b\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 v3.MainWindow.menu.view.toolbars=\u041f\u0430\u043d\u0435\u043b\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 ump.install=\u0418\u0434\u0451\u0442 \u0431\u044b\u0441\u0442\u0440\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435:\n\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043c\u043e\u0434\u0443\u043b\u044f \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u044d\u0442\u043e\u0433\u043e \u0432\u0438\u0434\u0435\u043e. subscriptions.listwindow.title=\u041f\u043e\u0438\u0441\u043a \u043f\u043e\u0434\u043f\u0438\u0441\u043e\u043a subscriptions.listwindow.autochecktext=Vuze \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0439\u0442\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 \u0432 \u0432\u0430\u0448\u0435\u0439 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435. \u0425\u043e\u0442\u0438\u0442\u0435 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u044d\u0442\u043e\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e? subscriptions.listwindow.loadingtext=\u041f\u043e\u0438\u0441\u043a \u043f\u043e\u0434\u043f\u0438\u0441\u043e\u043a, \u043f\u043e\u0445\u043e\u0436\u0438\u0445 \u043d\u0430 \u00ab%1\u00bb subscriptions.listwindow.failed=\u041f\u043e\u0434\u043f\u0438\u0441\u043e\u043a \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e subscriptions.listwindow.popularity=\u041f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u044c subscriptions.listwindow.popularity.unknown=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e subscriptions.listwindow.name=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 subscriptions.listwindow.subscribe=\u041f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f TableColumn.header.azsubs.ui.column.subs=\u041f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f subscriptions.listwindow.popularity.reading=\u0427\u0442\u0435\u043d\u0438\u0435... PluginDeprecation.log.start=\u042d\u0442\u043e \u043e\u043a\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043c\u043e\u0434\u0443\u043b\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0443\u0431\u0440\u0430\u043d\u044b \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 Vuze.\n\u041d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u0438, \u043d\u0443\u0436\u043d\u043e \u043b\u0438\u0448\u044c \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0445.\n\u0415\u0441\u043b\u0438 \u0436\u0435 \u0443 \u0432\u0430\u0441 \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f, \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043e\u043a\u043d\u0430 \u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0435\u0433\u043e \u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435 \u043d\u0430 \u0444\u043e\u0440\u0443\u043c\u0435:\n \t%1\n\n PluginDeprecation.log.details=---------\n\u0418\u0414\u0415\u041d\u0422\u0418\u0424\u0418\u041a\u0410\u0422\u041e\u0420: %1\n\u041a\u041e\u041d\u0422\u0415\u041a\u0421\u0422: %2\n\n*** \u041d\u0410\u0427\u0410\u041b\u041e \u041e\u0422\u041b\u0410\u0414\u041a\u0418 ***\n%3*** \u041a\u041e\u041d\u0415\u0426 \u041e\u0422\u041b\u0410\u0414\u041a\u0418 ***\n\n PluginDeprecation.view=\u041e\u0442\u043b\u0430\u0434\u043a\u0430 \u043c\u043e\u0434\u0443\u043b\u044f PluginDeprecation.alert=\u041c\u043e\u0434\u0443\u043b\u044c \u043f\u043e\u043f\u044b\u0442\u0430\u043b\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0443\u0431\u0440\u0430\u043d \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 \u2014 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0432 \u043e\u043a\u043d\u0435 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u043c\u043e\u0434\u0443\u043b\u044f TableColumn.header.Thumbnail=\u0417\u043d\u0430\u0447\u043e\u043a TableColumn.header.Thumbnail.info=\u0417\u043d\u0430\u0447\u043e\u043a \u0441 \u043f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 (\u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 Vuze) \u0438\u043b\u0438 \u0437\u043d\u0430\u0447\u043e\u043a \u0444\u0430\u0439\u043b\u0430 (\u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e) v3.MainWindow.menu.getting_started=&\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0442\u0430\u0440\u0442 MainWindow.menu.community=\u0421\u043e\u043e&\u0431\u0449\u0435\u0441\u0442\u0432\u043e MainWindow.menu.help.faq=&\u0427\u0430\u0441\u0442\u043e \u0437\u0430\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b (FAQ) MainWindow.menu.community.wiki=&\u0412\u0438\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430 MainWindow.menu.community.forums=&\u0424\u043e\u0440\u0443\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430 MainWindow.menu.community.blog=&\u0411\u043b\u043e\u0433 Vuze MainWindow.menu.help.support=&\u0421\u043f\u0440\u0430\u0432\u043a\u0430 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 externalLogin.title=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f externalLogin.explanation=\u0428\u0430\u0431\u043b\u043e\u043d \u00ab%1\u00bb \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e \u043e\u043a\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u044c\u0441\u044f. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u00ab\u0413\u043e\u0442\u043e\u0432\u043e\u00bb externalLogin.explanation.capture=\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u00ab%1\u00bb \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u00ab\u0413\u043e\u0442\u043e\u0432\u043e\u00bb. Button.done=\u0413\u043e\u0442\u043e\u0432\u043e GeneralView.torrent_created_on_and_by=%1 ( %2 ) Button.continue=\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c Button.preview=\u041f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 Subscription.menu.forcecheck=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c Subscription.menu.clearall=\u041f\u043e\u043c\u0435\u0442\u0438\u0442\u044c \u0432\u0441\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u0440\u043e\u0447\u0442\u0451\u043d\u043d\u044b\u043c\u0438 Subscription.menu.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c sidebar.Library=\u041c\u043e\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 sidebar.LibraryDL=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0438 sidebar.LibraryCD=\u0413\u043e\u0442\u043e\u0432\u043e authenticator.location=\u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 authenticator.details=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 v3.MainWindow.menu.showActionBarText=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u0438 subscript.import.fail.title=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c subscript.import.fail.desc=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438: %1 Subscription.menu.export=\u042d\u0441\u043f\u043e\u0440\u0442 subscript.export.select.template.file=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 Button.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c Button.send=\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c Button.back=\u041d\u0430\u0437\u0430\u0434 sidebar.LibraryUnopened=\u041d\u043e\u0432\u044b\u0435 TableColumn.header.unopened=\u041d\u043e\u0432\u044b\u0439 Unopened.bigView.header=\u041d\u043e\u0432\u044b\u0435 Subscription.menu.deleteall=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u0441\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b Subscription.menu.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0432 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 ConfigView.section.Subscriptions=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 subscriptions.config.maxresults=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u043c\u044b\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] v3.activity.button.readall=\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0432\u0441\u0451 \u043f\u0440\u043e\u0447\u0442\u0451\u043d\u043d\u044b\u043c TableColumn.header.activityNew=\u041d\u043e\u0432\u044b\u0439 TableColumn.header.activityType=\u0422\u0438\u043f TableColumn.header.activityText=\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 TableColumn.header.activityDate=\u0414\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f TableColumn.header.activityActions=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f Subscription.menu.resetauth=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 Search.menu.engines=\u0428\u0430\u0431\u043b\u043e\u043d\u044b Wizard.Subscription.title=\u041f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f Wizard.Subscription.optin.title=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 #what you've watched? Discover more with a single click... Wizard.Subscription.subscribe.title=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 Wizard.Subscription.create.title=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 Button.search=\u041d\u0430\u0439\u0442\u0438 Button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c Button.add=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c Button.createNewSubscription=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 Button.availableSubscriptions=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 Wizard.Subscription.optin.description=\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 Vuze \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 \u0432 \u0432\u0430\u0448\u0435\u0439 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435 \u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043b\u0438\u0441\u044c.\n\n\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438? Wizard.Subscription.create.search=\u041d\u0430\u0439\u0442\u0438 Wizard.Subscription.search.subtitle1=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438: Wizard.Subscription.search.subtitle2=\u0427\u0442\u043e \u043c\u043d\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043a\u0430\u0442\u044c? Wizard.Subscription.search.subtitle2.sub1=\u0424\u0438\u043b\u044c\u043c\u044b \u0432 HD, \u0442\u0435\u043b\u0435\u0448\u043e\u0443, \u0444\u0438\u043b\u044c\u043c\u044b, \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u043d\u0430 \u043f\u043e\u0440\u0442\u0430\u043b\u0435 Vuze Wizard.Subscription.search.subtitle2.sub2=\u0422\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0438\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 Wizard.Subscription.search.subtitle3=\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0432\u044b \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043b\u0438\u0441\u044c \u043d\u0430 \u043a\u043e\u043d\u0442\u0435\u043d\u0442, \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u0432 \u0431\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435. Wizard.Subscription.rss.subtitle1=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043b\u0438 \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u0441\u044e\u0434\u0430 URL: Wizard.Subscription.rss.subtitle2=\u041c\u043d\u043e\u0433\u0438\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u0435\u043b\u0438 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 RSS. \u041d\u0430\u0439\u0434\u0438\u0442\u0435 URL \u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u043d\u0430 \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u0435\u043b\u044f, \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u0438 \u0432\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0441\u044e\u0434\u0430, \u0430 \u0437\u0430\u0442\u0435\u043c \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u00ab\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c\u00bb. Wizard.Subscription.rss.subtitle3=\u041f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u0432 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u043e\u0439 \u043b\u0435\u043d\u0442\u0435 RSS \u0432 \u0431\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435. Wizard.Subscription.subscribe.library=\u041a\u043e\u043d\u0442\u0435\u043d\u0442 \u0432 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435 Wizard.Subscription.subscribe.subscriptions=\u041f\u043e\u0445\u043e\u0436\u0438\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 Wizard.Subscription.subscribe.library.empty=\u041d\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043e\u043a?\n \n\u0418\u0449\u0438\u0442\u0435 \u044f\u0440\u043a\u043e-\u043e\u0440\u0430\u043d\u0436\u0435\u0432\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 \u043d\u0430 \u043f\u043e\u0440\u0442\u0430\u043b\u0435 Vuze HD.\n \n\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435... message.confirm.delete.title=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 message.confirm.delete.text=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u00ab%1\u00bb? Subscription.menu.properties=\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 props.window.title=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u00ab%1\u00bb subs.prop.is_auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b subs.prop.last_scan=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0443\u0434\u0430\u0447\u043d\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 subs.prop.last_result=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0438\u0437 \u043d\u043e\u0432\u044b\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 subs.prop.last_error=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u043e\u0448\u0438\u0431\u043a\u0430 subs.prop.num_read=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 subs.prop.num_unread=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 subs.prop.template=\u0428\u0430\u0431\u043b\u043e\u043d subs.prop.auth=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f externalLogin.auth_method_proxy=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0430 cookies. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0441\u043d\u043e\u0432\u0430 externalLogin.wait=\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f, \u043f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435... TableColumn.menu.date_added.time=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c/\u0441\u043a\u0440\u044b\u0442\u044c \u0432\u0440\u0435\u043c\u044f sidebar.VuzeHDNetwork=\u041f\u043e\u0440\u0442\u0430\u043b Vuze HD subs.prop.next_scan=\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 subs.prop.assoc=\u0410\u0441\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u0438 subs.prop.version=\u0412\u0435\u0440\u0441\u0438\u044f subscriptions.column.new.info=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b subscriptions.column.name=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 subscriptions.column.nb-results=\u0412\u0441\u0435\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 subscriptions.column.nb-new-results=\u041d\u043e\u0432\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b subscriptions.column.last-checked=\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 subscriptions.view.title=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 subs.prop.is_public=\u041e\u0442\u043a\u0440\u044b\u0442\u0430\u044f subs.prop.high_version=\u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0430 \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f Subscription.menu.upgrade=\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043e \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 metasearch.template.version.bad=\u0414\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u00ab%1\u00bb \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 Vuze metasearch.addtemplate.failed.title=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0435 \u0443\u0434\u0430\u043b\u0430\u0441\u044c metasearch.addtemplate.failed.desc=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d: %1 subscription.version.bad=\u0414\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u00ab%1\u00bb \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 Vuze statusbar.feedback=\u041f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0432\u043f\u0435\u0447\u0430\u0442\u043b\u0435\u043d\u0438\u044f\u043c\u0438 statusbar.feedback.tooltip=\u041d\u0430\u0436\u043c\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441\u0432\u043e\u0438\u043c\u0438 \u0432\u043f\u0435\u0447\u0430\u0442\u043b\u0435\u043d\u0438\u044f\u043c\u0438 \u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438 Vuze sidebar.Activity=\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f v3.activity.button.watchall=\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u043c subscriptions.view.help.1=\u041f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043c\u043e\u0436\u043d\u043e \u043d\u0430 \u0432\u0441\u0451, \u0433\u0434\u0435 \u0435\u0441\u0442\u044c \u0437\u043d\u0430\u0447\u043e\u043a subscriptions.view.help.2=\u041f\u043e\u043b\u0443\u0447\u0430\u0439\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435. sidebar.sash.tooltip=F7 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442/\u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0431\u043e\u043a\u043e\u0432\u0443\u044e \u043f\u0430\u043d\u0435\u043b\u044c sidebar.expand.tooltip=\u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0431\u043e\u043a\u043e\u0432\u0443\u044e \u043f\u0430\u043d\u0435\u043b\u044c sidebar.dropdown.tooltip=\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0431\u043e\u043a\u043e\u0432\u0443\u044e \u043f\u0430\u043d\u0435\u043b\u044c \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u043c\u0435\u043d\u044e subscript.all.subscribed=\u0412\u044b \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 \u044d\u0442\u043e\u0442 \u043a\u043e\u043d\u0442\u0435\u043d\u0442 subscript.some.subscribed=\u0423 \u0432\u0430\u0441 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442.\n\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0437\u0434\u0435\u0441\u044c, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 subscript.none.subscribed=\u041d\u0430\u0436\u043c\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0432\u0438\u0434\u0435\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 v3.iconBar.up.tooltip=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432\u0432\u0435\u0440\u0445\n\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u0435 \u043a\u0443\u0440\u0441\u043e\u0440 \u043c\u044b\u0448\u0438 \u0432\u0432\u0435\u0440\u0445, \u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044f \u043b\u0435\u0432\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 v3.iconBar.down.tooltip=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u0437\n\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u0435 \u043a\u0443\u0440\u0441\u043e\u0440 \u043c\u044b\u0448\u0438 \u0432\u043d\u0438\u0437, \u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044f \u043b\u0435\u0432\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 TableColumn.header.azsubs.ui.column.subs_link=\u0410\u0441\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u044f TableColumn.header.azsubs.ui.column.subs_link.info=\u0421\u0432\u044f\u0437\u0438 \u0441 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430\u043c\u0438 Button.deleteContent.fromLibrary=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u0437 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438 Button.deleteContent.fromComputer=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430 v3.deleteContent.message=\n\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u00ab%1\u00bb \u0441 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430 \u0438\u043b\u0438 \u0443\u0431\u0440\u0430\u0442\u044c \u0438\u0437 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438 Vuze? v3.MainWindow.menu.view.toolbartext=\u041f\u043e\u0434\u043f\u0438\u0441\u0438 \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 v3.MainWindow.menu.view.asSimpleList=\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u0438\u0441\u043e\u043a v3.MainWindow.menu.view.asAdvancedList=\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a v3.MainWindow.menu.view.statusbar=\u0421\u0442\u0440\u043e\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f Subscription.menu.dirtyall=\u041f\u043e\u043c\u0435\u0442\u0438\u0442\u044c \u0432\u0441\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u043c\u0438 configureWizard.file.message3=Vuze \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442 \u0444\u0430\u0439\u043b\u044b \u0432 \u043e\u0441\u043e\u0431\u0443\u044e \u043f\u0430\u043f\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c: v3.deleteContent.applyToAll=\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043d\u0430\u0434 \u0432\u0441\u0435\u043c\u0438 %1 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 ConfigView.label.seeding.firstPriority.ignoreIdleHours=\u0422\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0440\u0430\u0437\u0434\u0430\u0432\u0430\u043b\u0438\u0441\u044c \u043d\u0430 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 v3.MainWindow.menu.contentnetworks=\u0421&\u0435\u0442\u0438 HD v3.MainWindow.menu.contentnetworks.about=\u041e \u0441\u0435\u0442\u044f\u0445 HD Peers.column.as.info=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043e\u0431 AS (\u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435) \u0443\u0437\u043b\u0430 ConfigTransferAutoSpeed.auto.speed.neural=\u041d\u0435\u0439\u0440\u043e\u0441\u0435\u0442\u044c (Gudy Alpha) ConfigView.label.autoopen.downloadbars=\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043d\u043b\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u0440\u0438 ConfigView.label.autoopen=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 ConfigView.label.autoopen.detailstab=\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0435\u0439 \u043f\u0440\u0438 ConfigView.label.systray=\u041e\u0431\u043b\u0430\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 ConfigView.label.systray._mac=\u0417\u043d\u0430\u0447\u043e\u043a \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f ConfigView.section.interface.legacy=\u041f\u0440\u0435\u0436\u043d\u0438\u0439 \u0434\u0438\u0437\u0430\u0439\u043d v3.MainWindow.menu.contentnetworks.manage=&\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0435\u0442\u044f\u043c\u0438 HD azbuddy.ui.table.loc_cat= azbuddy.ui.menu.cat=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 azbuddy.ui.menu.cat.share=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u0434\u043b\u044f \u0434\u0440\u0443\u0437\u0435\u0439 azbuddy.ui.menu.cat.set=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 azbuddy.ui.menu.cat.set_msg=\u0421\u043f\u0438\u0441\u043e\u043a \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043f\u044f\u0442\u0443\u044e \u0438\u043b\u0438 \u00abAll\u00bb azbuddy.ui.menu.cat_subs=\u041f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f subs.prop.update_period=\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f azbuddy.enable_cat_pub=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u0412\u0421\u0415 \u0432\u0430\u0448\u0438 \u0434\u0440\u0443\u0437\u044c\u044f (\u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c: \u00ab,\u00bb) v3.dialog.cnclose.title=\u0417\u0430\u043a\u0440\u044b\u0442\u043e %1 v3.dialog.cnclose.subtitle=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 v3.dialog.cnclose.info1=\u0412\u044b \u0437\u0430\u043a\u0440\u044b\u043b\u0438 \u0441\u0435\u0442\u044c HD v3.dialog.cnclose.info2=\u0415\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u043f\u044f\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u044d\u0442\u0443 \u0441\u0435\u0442\u044c HD, \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u043d\u044e \u00ab\u0421\u0435\u0442\u0438 HD\u00bb v3.dialog.cnclose.noshow=\u041d\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u043d\u043e\u0432\u0430 v3.dialog.cnmanage.title=\u041c\u0435\u043d\u044e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0435\u0442\u044f\u043c\u0438 HD v3.dialog.cnmanage.intro=\u041d\u0438\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0441\u0435\u0442\u0438 HD, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u044f\u0432\u044f\u0442\u0441\u044f \u0432 \u043c\u0435\u043d\u044e \u00ab\u0421\u0435\u0442\u0438 HD\u00bb TableColumn.header.#=\u2116 TableColumn.header.#.info=\u041f\u043e\u0437\u0438\u0446\u0438\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0438\u043b\u0438 \u043f\u043e\u0440\u044f\u0434\u043a\u043e\u0432\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 TableColumn.header.category.info=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432\u043a\u043b\u044e\u0447\u0451\u043d \u0442\u043e\u0440\u0440\u0435\u043d\u0442 TableColumn.header.DateCompleted.info=\u0414\u0430\u0442\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 TableColumn.header.AzProduct.info=\u0421\u0435\u0442\u044c-\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 TableColumn.header.health.info=\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0441 \u0443\u0437\u043b\u0430\u043c\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f TableColumn.header.maxuploads.info=\u041d\u0430\u0438\u0431\u043e\u043b\u044c\u0448\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u0437\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0430 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0430 TableColumn.header.name.info=\u0418\u043c\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 TableColumn.header.unopened.info=\u0418\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439, \u0431\u044b\u043b \u043b\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u043e\u0442\u043a\u0440\u044b\u0442 (\u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0451\u043d) TableColumn.header.savepath.info=\u0426\u0435\u043b\u0435\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 TableColumn.header.SeedingRank.info=\u041e\u0446\u0435\u043d\u043e\u0447\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u0430\u0436\u043d\u043e\u0441\u0442\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u0432 \u043f\u043b\u0430\u043d\u0435 \u0440\u0430\u0437\u0434\u0430\u0447\u0438. \u0427\u0435\u043c \u0432\u044b\u0448\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0442\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442 \u043d\u0443\u0436\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u0440\u0430\u0437\u0434\u0430\u0447\u0435. TableColumn.header.shareRatio.info=\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0440\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u043c \u0434\u0430\u043d\u043d\u044b\u043c. TableColumn.header.size.info=\u0420\u0430\u0437\u043c\u0435\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 TableColumn.header.azsubs.ui.column.subs.info=\u041a\u043d\u043e\u043f\u043a\u0430, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043b\u0435\u043d\u0442\u0443 \u043f\u043e\u0445\u043e\u0436\u0438\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 TableColumn.header.upspeed.info=\u0422\u0435\u043a\u0443\u0449\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 TableColumn.header.downspeed.info=\u0422\u0435\u043a\u0443\u0449\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 TableColumn.header.up.info=\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u043e\u0431\u044a\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u0440\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u0430\u043c TableColumn.header.down.info=\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u043e\u0431\u044a\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0445 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 \u0443\u0437\u043b\u043e\u0432 TableColumn.header.ProgressETA.info=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u0433\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u044c, \u043e\u0441\u0442\u0430\u0432\u0448\u0435\u0435\u0441\u044f \u0432\u0440\u0435\u043c\u044f \u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 \u0432 \u043e\u0434\u043d\u043e\u043c \u0441\u0442\u043e\u043b\u0431\u0446\u0435. TableColumn.header.eta.info=\u041f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 Pieces.column.#.info=\u041d\u043e\u043c\u0435\u0440 \u0447\u0430\u0441\u0442\u0438 Peers.column.%.info=\u041f\u0440\u043e\u0446\u0435\u043d\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u043e\u0441\u0442\u0438 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0443\u0437\u043b\u0430 TableColumn.header.download.info=\u041e\u0431\u044a\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0440\u0438\u044f\u0442\u044b\u0445 \u043e\u0442 \u0443\u0437\u043b\u0430 TableColumn.header.upload.info=\u041e\u0431\u044a\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u0443 TableColumn.header.downloadspeed.info=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u0443\u0437\u043b\u0430 TableColumn.header.uploadspeed.info=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u0443 TableColumn.header.lan.info=\u0418\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0443\u0437\u043b\u0430 \u0432 LAN TableColumn.header.downloadspeedoverall.info=\u041f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0451\u043c\u0430 \u0443\u0437\u043b\u0430 Peers.column.pieces.info=\u0413\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u043e\u0441\u0442\u0438 \u0447\u0430\u0441\u0442\u0435\u0439 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430 TableColumn.header.TableColumnNameInfo=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 TableColumn.header.TableColumnSample=\u041f\u0440\u0438\u043c\u0435\u0440 TableColumn.header.TableColumnInfo=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 TableColumn.header.TableColumnChosenColumn=\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0441\u0442\u043e\u043b\u0431\u0435\u0446 subs.prop.is_auto_ok=\u0410\u0432\u0442\u043e\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0430 label.learnmore=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435... ColumnSetup.title=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432 \u0434\u043b\u044f \u00ab%1\u00bb ColumnSetup.explain=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043d\u0443\u0436\u043d\u044b\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u044b \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0432\u0441\u0435\u0445 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0441\u043b\u0435\u0432\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0438\u0434\u0438\u043c\u044b\u0445 \u0441\u043f\u0440\u0430\u0432\u0430. \u0424\u0438\u043b\u044c\u0442\u0440 \u0432\u043d\u0438\u0437\u0443 \u0441\u043b\u0435\u0432\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u044b\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u044b \u0432 \u043b\u0435\u0432\u043e\u043c \u0441\u043f\u0438\u0441\u043a\u0435. \u0421\u0442\u043e\u043b\u0431\u0446\u044b \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u044b\u0448\u0438 \u0438\u043b\u0438 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0439 \u043a\u043b\u0430\u0432\u0438\u0448. ColumnSetup.chosencolumns=\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u044b ColumnSetup.proficiency=\u0423\u0440\u043e\u0432\u0435\u043d\u044c: ColumnSetup.categories=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438: ColumnSetup.filters=\u0424\u0438\u043b\u044c\u0442\u0440\u044b ColumnSetup.availcolumns=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u044b (%1) ColumnSetup.availcolumns.filteredby=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u044b (%1, \u0444\u0438\u043b\u044c\u0442\u0440 \u043f\u043e %2) ConfigView.label.maxStalledSeeding=\u041c\u0430\u043a\u0441. \u00ab\u0437\u0430\u0433\u043b\u043e\u0445\u0448\u0438\u0445\u00bb [0: \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e] azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_fi_FI.properties0000644000175000017500000064061411301156004026056 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torrent-tiedosto... Main.parameter.usage=K\u00e4ytt\u00f6: java org.gudy.azureus2.cl.Main [parametrit] "tiedosto.torrent" "tallennushakemisto" Main.parameter.maxUploads=Yht\u00e4aikaisten l\u00e4hetyspaikkojen enimm\u00e4ism\u00e4\u00e4r\u00e4 Main.parameter.maxSpeed=Enimm\u00e4isl\u00e4hetysnopeus (kB/s) MainWindow.menu.file=&Tiedosto MainWindow.menu.file.open=&Avaa MainWindow.menu.file.create=L&uo torrent-tiedosto... MainWindow.menu.file.create.fromfile=&Tiedostosta MainWindow.menu.file.create.fromdir=&Hakemistosta MainWindow.menu.file.export=&Vie torrent-tiedosto XML-muotoon... MainWindow.menu.file.import=&Tuo torrent-tiedosto XML-muodosta... MainWindow.menu.file.closetab=Sulje v&\u00e4lilehti MainWindow.menu.file.closewindow=Sulje &ikkuna MainWindow.menu.file.exit=&Lopeta MainWindow.dialog.choose.file=Valitse torrent-tiedosto MainWindow.menu.file.folder=Torrent-tiedostot &hakemistosta MainWindow.dialog.choose.folder=Valitse torrent-tiedostot sis\u00e4lt\u00e4v\u00e4 hakemisto MainWindow.menu.view=&N\u00e4yt\u00e4 MainWindow.menu.view.show=N\u00e4yt\u00e4 MainWindow.menu.view.mytorrents=&Siirrot MainWindow.menu.view.open_global_transfer_bar=Siirrot-palkki MainWindow.menu.view.configuration=&Asetukset... MainWindow.menu.view.console=&Konsoli MainWindow.menu.view.irc=IRC MainWindow.menu.view.allpeers=Kaikki yhteydet MainWindow.menu.view.detailedlist=&Yksityiskohtainen luettelo MainWindow.menu.closealldetails=Sulje kaikki tarkat ti&edot MainWindow.menu.closealldownloadbars=Sulje kaikki &seurantapalkit MainWindow.menu.language=&Kieli ConfigView.section.language=Kieli MainWindow.menu.window=&Ikkuna MainWindow.menu.window.minimize=&Pienenn\u00e4 MainWindow.menu.window.zoom=&L\u00e4henn\u00e4 MainWindow.menu.window.alltofront=Tuo kaikki &eteen MainWindow.menu.help=&Ohje MainWindow.menu.help.about=Tietoja Vuzesta MainWindow.menu.torrent=To&rrent-tiedosto MainWindow.about.title=Tietoja Vuzesta- versio MainWindow.about.section.developers=Kehitt\u00e4j\u00e4t MainWindow.about.section.translators=K\u00e4\u00e4nt\u00e4j\u00e4t MainWindow.about.section.system=J\u00e4rjestelm\u00e4tiedot MainWindow.about.section.internet=Vuze Internetiss\u00e4 MainWindow.about.internet.homepage=Kotisivu MainWindow.about.internet.sourceforge=SourceForge.netin projektisivu MainWindow.about.internet.sourceforgedownloads=SourceForge.netin lataussivu MainWindow.about.internet.bugreports=Ohjelmavirheilmoitukset MainWindow.about.internet.forumdiscussion=Keskustelualueet MainWindow.about.internet.wiki=Vuze Wiki (UKK) MainWindow.dialog.choose.savepath=Valitse tallennushakemisto MainWindow.dialog.choose.savepath_forallfiles=Valitse tallennushakemisto kaikille tiedostoille MainWindow.status.latestversion=Uusin virallinen versio: MainWindow.status.latestversion.clickupdate=P\u00e4ivit\u00e4 t\u00e4st\u00e4 MainWindow.status.unknown=Tuntematon MainWindow.status.checking=Tarkastetaan MyTorrentsView.mytorrents=Siirrot TableColumn.header.name=Nimi TableColumn.header.size=Koko TableColumn.header.done=Valmiina TableColumn.header.done.info=Latauksen valmistuminen prosenteissa. TableColumn.header.status=Tila TableColumn.header.status.info=Torrent-tiedoston tila TableColumn.header.seeds=L\u00e4hteet TableColumn.header.seeds.info=Yhdistettyjen l\u00e4hteiden lukum\u00e4\u00e4r\u00e4 (suluissa lukum\u00e4\u00e4r\u00e4 kaikkiaan). TableColumn.header.peers=Lataajat TableColumn.header.peers.info=Yhdistettyjen lataajien lukum\u00e4\u00e4r\u00e4 (suluissa lukum\u00e4\u00e4r\u00e4 kaikkiaan). TableColumn.header.completed=Valmiit TableColumn.header.completed.info=K\u00e4ytt\u00e4jien lukum\u00e4\u00e4r\u00e4, jotka ovat seurantapalvelimen mukaan saaneet latauksen valmiiksi. TableColumn.header.downspeed=Latausnopeus TableColumn.header.upspeed=L\u00e4hetysnopeus TableColumn.header.eta=Valm.aika TableColumn.header.tracker=Seurantapalvelimen tila TableColumn.header.tracker.info=Seurantapalvelimen tila. TableColumn.header.trackernextaccess=Seuraava p\u00e4ivitys TableColumn.header.trackernextaccess.info=J\u00e4ljell\u00e4 oleva aika seurantapalvelimen seuraavaan p\u00e4ivitykseen. TableColumn.header.priority=Prioriteetti TableColumn.header.priority.info=M\u00e4\u00e4rittelee torrent-tiedostolle varattavan l\u00e4hetysnopeuden. TableColumn.header.seeds.fullcopycalc=%2 oletettua t\u00e4ytt\u00e4 kopiota %1 lataajaa kohti MyTorrentsView.menu.showdetails=&N\u00e4yt\u00e4 tarkemmat tiedot MyTorrentsView.menu.showdownloadbar=N&\u00e4yt\u00e4 seurantapalkki MyTorrentsView.menu.open=Avaa MyTorrentsView.menu.setpriority=Aseta p&rioriteetti MyTorrentsView.menu.setpriority.high=&Korkea MyTorrentsView.menu.setpriority.low=&Alhainen MyTorrentsView.menu.start=K\u00e4ynnist\u00e4 MyTorrentsView.menu.stop=P&ys\u00e4yt\u00e4 MyTorrentsView.menu.remove=&Poista MyTorrentsView.menu.changeTracker=&Lis\u00e4\u00e4 uusi seurantapalvelin TrayWindow.menu.exit=&Lopeta TrayWindow.menu.show=&N\u00e4yt\u00e4 Vuze SystemTray.menu.exit=&Lopeta SystemTray.menu.closealldownloadbars=&Sulje kaikki seurantapalkit SystemTray.menu.open_global_transfer_bar=N\u00e4yt\u00e4 Siirrot-palkki SystemTray.menu.show=&N\u00e4yt\u00e4 Vuze PeersView.ip=IP-osoite PeersView.ip.info=K\u00e4ytt\u00e4j\u00e4n IP-osoite. PeersView.port=Portti PeersView.port.info=K\u00e4ytetty portti. PeersView.T=Tyyppi PeersView.T.info=Yhteyden muodostuminen: L (sin\u00e4 muodostit) tai R (k\u00e4ytt\u00e4j\u00e4 muodosti). PeersView.T.L.tooltip=Sin\u00e4 muodostit yhteyden. PeersView.T.R.tooltip=K\u00e4ytt\u00e4j\u00e4 muodosti yhteyden. PeersView.I1=Kiinnostus (sin\u00e4 kiinnostunut) PeersView.I1.info=Sin\u00e4 olet kiinnostunut toisen k\u00e4ytt\u00e4j\u00e4n osista. PeersView.C1=Estetty PeersView.C1.info=K\u00e4ytt\u00e4j\u00e4 est\u00e4\u00e4 sinua lataamasta h\u00e4nelt\u00e4. PeersView.pieces=Osat PeersView.downloadspeed=Latausnopeus PeersView.download=Ladattu PeersView.I2=Kiinnostus (K\u00e4ytt\u00e4j\u00e4 kiinnostunut) PeersView.I2.info=Toinen k\u00e4ytt\u00e4j\u00e4 on kiinnostunut sinun osistasi. PeersView.C2=Estet\u00e4\u00e4n k\u00e4ytt\u00e4j\u00e4\u00e4 PeersView.C2.info=Sin\u00e4 est\u00e4t k\u00e4ytt\u00e4j\u00e4\u00e4 lataamasta sinulta. PeersView.uploadspeed=L\u00e4hetysnopeus PeersView.uploadspeed.info=L\u00e4hetysnopeus k\u00e4ytt\u00e4j\u00e4lle. PeersView.upload=L\u00e4hetetty PeersView.upload.info=L\u00e4hetetty m\u00e4\u00e4r\u00e4. PeersView.statup=Arvio PeersView.statup.info=Arvioitu l\u00e4hetysnopeus, jolla k\u00e4ytt\u00e4j\u00e4 pystyy l\u00e4hett\u00e4m\u00e4\u00e4n tietoa. PeersView.S=Siirtoeste PeersView.S.info=Manuaalisesti tai autom. estetty, jos ei l\u00e4hetet\u00e4 riitt\u00e4v\u00e4n nopeasti. PeersView.downloadspeedoverall=K\u00e4ytt\u00e4j\u00e4nopeus PeersView.optunchoke=Optimistinen vapautus PeersView.client=Asiakasohjelma PeersView.client.info=K\u00e4ytt\u00e4j\u00e4n BitTorrent-asiakasohjelma. PeersView.menu.snubbed=&Estetty PeersView.title.short=Yhteydet PeersView.title.full=Yhteydet AllPeersView.title.full=Kaikki yhteydet ConfigView.section.files=Tiedostot ConfigView.label.usefastresume=K\u00e4yt\u00e4 nopeaa latauksen jatkamista ConfigView.label.incrementalfile=Varaa levytilaa viimeiseen ladattuun osaan asti (vaaditaan Linux-k\u00e4yt\u00f6ss\u00e4, jos tallennetaan FAT32-osiolle) ConfigView.label.defaultsavepath=Tallenna tiedostot oletushakemistoon ConfigView.button.browse=&Selaa... ConfigView.dialog.choosedefaultsavepath=Valitse oletustallennushakemisto ConfigView.section.server=Yhteys ConfigView.section.global=Yleiset ConfigView.label.disconnetseed=Katkaise yhteys l\u00e4hett\u00e4jiin latauksen valmistuttua ConfigView.label.switchpriority=Vaihda alhaiselle prioriteetille latauksen valmistuttua ConfigView.label.maxdownloads=Yht\u00e4aikaisten latausten enimm\u00e4ism\u00e4\u00e4r\u00e4 (0 = rajoittamaton)\n - ei voi olla suurempi kuin aktiivisten torrent-tiedostojen enimm\u00e4ism\u00e4\u00e4r\u00e4 ConfigView.label.maxdownloads.tooltip=Enimm\u00e4ism\u00e4\u00e4r\u00e4 t\u00e4yttyy yleens\u00e4 normaalisti. S\u00e4\u00e4nt\u00f6\u00f6n on kuitenkin yksi poikkeus:\njos v\u00e4ltt\u00e4m\u00e4tt\u00e4 niin vaaditaan, voi ensisijainen, valmistunut torrent-tiedosto ottaa haltuunsa yhden latauspaikan.\nT\u00e4ll\u00f6in aktiivisten latausten m\u00e4\u00e4r\u00e4 siis v\u00e4henee yhdell\u00e4. ConfigView.label.maxactivetorrents=Aktiivisten torrent-tiedostojen enimm\u00e4ism\u00e4\u00e4r\u00e4 (0 = rajoittamaton)\n - uudet siirrot eiv\u00e4t k\u00e4ynnisty, jos enimm\u00e4ism\u00e4\u00e4r\u00e4 on t\u00e4ynn\u00e4 ConfigView.label.priorityExtensions=Lataa ensisijaisesti\ntiedostotyypin ollessa\n(esim: .txt;.nfo;.jpg) ConfigView.section.transfer=Siirrot ConfigView.label.maxuploads=L\u00e4hetyspaikkojen oletusenimm\u00e4ism\u00e4\u00e4r\u00e4/torrent-tiedosto ConfigView.label.maxuploadspeed=kB/s, enimm\u00e4isl\u00e4hetysnopeus (kaikki torrent-tiedostot, 0 = rajoittamaton) ConfigView.label.saveresumeinterval=P\u00e4ivit\u00e4 tiedot joka ConfigView.unlimited=Rajoittamaton ConfigView.section.display=Ulkoasu ConfigView.label.opendetails=N\u00e4yt\u00e4 torrent-tiedoston tarkemmat tiedot automaattisesti ConfigView.label.openbar=N\u00e4yt\u00e4 seurantapalkki automaattisesti ConfigView.label.use_old_speed_menus=K\u00e4yt\u00e4 perinteist\u00e4 valikkotyyli\u00e4 lataus- ja l\u00e4hetysnopeuksien asettamiseen (vaatii uudelleenk\u00e4ynnistyksen) ConfigView.label.closetotray=Sulkeminen piilottaa ilmoitusalueelle ConfigView.label.minimizetotray=Pienent\u00e4minen piilottaa ilmoitusalueelle ConfigView.section.general=Yleiset ConfigView.section.start=K\u00e4ynnistys ConfigView.label.showsplash=N\u00e4yt\u00e4 aloitusruutu ConfigView.label.autoupdate=Avaa P\u00e4ivitysavustaja, kun uusi versio on saatavilla ConfigView.label.openconsole=Avaa konsoli k\u00e4ynnistett\u00e4ess\u00e4 ConfigView.label.openconfig=Avaa asetukset k\u00e4ynnistett\u00e4ess\u00e4 ConfigView.label.startminimized=K\u00e4ynnist\u00e4 piilotettuna ilmoitusalueelle ConfigView.section.irc=IRC-yhteys ConfigView.label.ircwiki=Muista lukea s\u00e4\u00e4nn\u00f6t osoitteesta http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Palvelin ConfigView.label.ircchannel=Kanava ConfigView.label.irclogin=Nimimerkki ConfigView.group.irctitle=IRC (reaaliaikainen tekninen tuki) ConfigView.boolean.ircsendinfo=Salli ongelmatilanteissa asetusten l\u00e4hett\u00e4minen (anonyymisti) kanavien yll\u00e4pit\u00e4jille ConfigView.boolean.irclog=Kirjaa kanavien tapahtumat lokitiedostoon (IRC_log.htm Vuzen asennushakemistossa) ConfigView.section.security=Suojaus ConfigView.label.password=Suojaa Vuzen k\u00e4ytt\u00f6\u00e4 salasanalla\n - kysyt\u00e4\u00e4n k\u00e4ynnistett\u00e4ess\u00e4 ja ilmoitusalueelta palautettaessa ConfigView.label.passwordconfirm=Salasana uudelleen ConfigView.label.passwordmatch=Salasanasuojaus k\u00e4yt\u00f6ss\u00e4: ConfigView.label.passwordmatchnone=Ei ConfigView.label.passwordmatchno=Ei - salasanat eiv\u00e4t t\u00e4sm\u00e4\u00e4 ConfigView.label.passwordmatchyes=Kyll\u00e4 ConfigView.button.save=Tallenna ConfigView.title.short=Asetukset ConfigView.title.full=Asetukset ConfigView.title.full._mac=Asetukset ConsoleView.title.short=Konsoli ConsoleView.title.full=Konsoli FileItem.write=Kirjoitus FileItem.read=Luku FileItem.normal=Normaali FileItem.high=Korkea FileItem.donotdownload=Ei ladata FileItem.delete=Poista FilesView.name=Nimi FilesView.name.fastRename=Nopea uudelleennime\u00e4minen FilesView.size=Koko FilesView.done=Ladattu FilesView.%=Valmiina FilesView.firstpiece=Ensimm\u00e4inen osa FilesView.numberofpieces=Osien lkm FilesView.pieces=Osat FilesView.mode=Tila FilesView.priority=Prioriteetti FilesView.menu.open=&Avaa FilesView.menu.setpriority=Aseta &prioriteetti FilesView.menu.setpriority.high=&Korkea FilesView.menu.setpriority.normal=&Normaali FilesView.menu.setpriority.skipped=&\u00c4l\u00e4 lataa FilesView.title.short=Tiedostot FilesView.title.full=Tiedostot GeneralView.section.downloaded=Ladattu GeneralView.label.status.file=Tiedoston tila GeneralView.label.status.pieces=Osien tila GeneralView.section.availability=Saatavuus GeneralView.label.status.pieces_available=Osien tila GeneralView.section.transfer=Siirrot GeneralView.section.info=Torrent-tiedosto GeneralView.title.short=Yleiset GeneralView.title.full=Yleiset GeneralView.label.timeelapsed=Aikaa kulunut: GeneralView.label.remaining=J\u00e4ljell\u00e4: GeneralView.label.downloaded=Ladattu: GeneralView.label.downloadspeed=Latausnopeus: GeneralView.label.maxuploads=L\u00e4hetyspaikkojen enimm\u00e4ism\u00e4\u00e4r\u00e4: GeneralView.label.maxuploads.tooltip=Lataajien enimm\u00e4ism\u00e4\u00e4r\u00e4, joille l\u00e4hetet\u00e4\u00e4n tietoa yht\u00e4aikaisesti. GeneralView.label.uploaded=L\u00e4hetetty: GeneralView.label.uploadspeed=L\u00e4hetysnopeus: GeneralView.label.seeds=L\u00e4hteit\u00e4: GeneralView.label.peers=Lataajia: GeneralView.label.completed=Valmiit: GeneralView.label.totalspeed=Nopeus yhteens\u00e4: GeneralView.label.totalspeed.tooltip=Kaikkien yhdistettyjen k\u00e4ytt\u00e4jien nopeus yhteens\u00e4 ja keskim\u00e4\u00e4rin. GeneralView.label.averagespeed=keskim\u00e4\u00e4rin GeneralView.label.filename=Nimi: GeneralView.label.totalsize=Koko yhteens\u00e4: GeneralView.label.savein=Tallennushakemisto: GeneralView.label.hash=Tiiviste: GeneralView.label.numberofpieces=Osien m\u00e4\u00e4r\u00e4: GeneralView.label.size=Osan koko: GeneralView.label.tracker=Seurantapalvelimen tila: GeneralView.label.updatein=Aikaa p\u00e4ivitykseen: GeneralView.label.trackerurl=Seurantapalvelimen osoite: GeneralView.label.trackerurlupdate=Tee p\u00e4ivitys GeneralView.label.comment=Kommentti: GeneralView.label.user_comment=Oma kommentti: GeneralView.label.status=Tila: ManagerItem.waiting=Odotetaan ManagerItem.allocating=Varataan tilaa ManagerItem.checking=Tarkastetaan ManagerItem.ready=Odotetaan muita torrent-tiedostoja ManagerItem.downloading=Ladataan ManagerItem.seeding=L\u00e4hetet\u00e4\u00e4n ManagerItem.stopped=Pys\u00e4ytetty ManagerItem.error=Virhe ManagerItem.high=Korkea ManagerItem.low=Alhainen MinimizedWindow.name=Nimi: MinimizedWindow.all_transfers=Kaikki siirrot PiecesView.size=Koko PiecesView.numberofblocks=Lohkojen lkm PiecesView.blocks=Lohkot PiecesView.completed=Valmiina PiecesView.availability=Saatavuus PiecesView.reservedby=Varattu PiecesView.writers=Lohkojen l\u00e4hett\u00e4j\u00e4t PiecesView.title.short=Osat PiecesView.title.full=Osat SystemTray.tooltip.seeding=%1 l\u00e4hetet\u00e4\u00e4n, SystemTray.tooltip.downloading=%1 ladataan, DownloadManager.error.filenotfound=Tiedostoa ei l\u00f6ytynyt DownloadManager.error.fileempty=Torrent-tiedosto tyhj\u00e4 DownloadManager.error.filetoobig=Torrent-tiedosto liian suuri DownloadManager.error.filewithouttorrentinfo=Torrent-tietoja ei l\u00f6ydy tiedostosta DownloadManager.error.unsupportedencoding=Koodausta ei tueta DownloadManager.error.ioerror=Siirr\u00e4nt\u00e4virhe DownloadManager.error.sha1=Algoritmi ei k\u00e4ytett\u00e4viss\u00e4 (SHA1) PeerManager.status.offline=Yhteysvirhe PeerManager.status.ok=OK PeerManager.status.checking=Tarkastetaan PeerManager.status.finished=Valmis PeerManager.status.finishedin=Valmis, aikaa kului MainWindow.upgrade.assistant=P\u00e4ivitysavustaja MainWindow.upgrade.newerversion=Uudempi versio Vuzesta on ladattavissa MainWindow.upgrade.explanation=T\u00e4m\u00e4 avustaja lataa ohjelman uuden version Vuzen asennushakemistoon ja k\u00e4ynnist\u00e4\u00e4 Vuzen uudelleen MainWindow.upgrade.explanation.manual=Voit suorittaa p\u00e4ivityksen my\u00f6s manuaalisesti sulkemalla Vuzen, lataamalla uudemman .jar-version, \nkopioimalla sen Vuzen asennushakemistoosi ja k\u00e4ynnist\u00e4m\u00e4ll\u00e4 Vuzen uudestaan MainWindow.upgrade.step1=Vaihe 1: Uusi versio ladataan MainWindow.upgrade.step2=Vaihe 2: Vuze k\u00e4ynnistet\u00e4\u00e4n uudelleen, p\u00e4ivitys on suoritettu MainWindow.upgrade.hint1=Vihje:\tPainamalla Valmis kaikki tapahtuu automaattisesti MainWindow.upgrade.hint2=Vihje:\tJos haluat sulkea Vuzen my\u00f6hemmin, paina nyt Peruuta ja\n\tuudelleennime\u00e4 Azureus2-new.jar Azureus2.jar:ksi my\u00f6hemmin sulkemisen j\u00e4lkeen MainWindow.upgrade.error.downloading.hint=Virhe:\tUutta versiota ei pystytty lataamaan, p\u00e4ivit\u00e4 manuaalisesti MainWindow.upgrade.section.info=Uusi versio saatavilla MainWindow.upgrade.section.manual=Manuaalinen p\u00e4ivitys MainWindow.upgrade.section.automatic=Automaattinen p\u00e4ivitys MainWindow.upgrade.tooltip.progressbar=T\u00e4st\u00e4 n\u00e4et latauksen edistymisen Button.next=Seuraava Button.finish=Valmis Button.cancel=&Peruuta LocaleUtil.title=Valitse tiedoston koodaus LocaleUtil.section.chooseencoding=Valitse koodaus tiedostonimelle LocaleUtil.label.chooseencoding=Valitse parhaiten sopiva koodaus: LocaleUtil.label.hint.doubleclick=Vihje: tuplaklikkaus rivill\u00e4 valitsee koodauksen ja sulkee ikkunan. LocaleUtil.label.checkbox.rememberdecision=K\u00e4yt\u00e4 samaa koodausta kaikille tiedostoille LocaleUtil.column.encoding=Koodaus IrcClient.copyright=K\u00e4yt\u00f6ss\u00e4 PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Yhdistet\u00e4\u00e4n palvelimeen IrcClient.connected=Yhdistetty palvelimeen IrcClient.joining=Liityt\u00e4\u00e4n kanavalle IrcClient.channel=Liitytty IrcClient.joined=-kanavalle IrcClient.error=Virhe IrcClient.hasjoined=liittyi kanavalle IrcClient.haskicked=poisti kanavalta k\u00e4ytt\u00e4j\u00e4n IrcClient.hasleft=poistui kanavalta IrcClient.nowknown=on nyt nimelt\u00e4\u00e4n IrcClient.topicforchannel=Kanavan otsikko on: IrcClient.disconnected=Yhteys katkesi palvelimeen IrcClient.noNick=Nimimerkki\u00e4 ei ole m\u00e4\u00e4ritelty. Aseta nimimerkkisi Asetuksissa kohdassa Lis\u00e4osat | IRC-yhteys. IrcView.actionnotsupported=T\u00e4m\u00e4 komento ei ole k\u00e4ytett\u00e4viss\u00e4 IrcView.clientsconnected=k\u00e4ytt\u00e4j\u00e4\u00e4 IrcView.privateto=K\u00e4ytt\u00e4j\u00e4lle IrcView.privatefrom=K\u00e4ytt\u00e4j\u00e4lt\u00e4 IrcView.noticefrom=Tiedotus: IrcView.errormsg=Virheellinen komento /msg : /msg k\u00e4ytt\u00e4j\u00e4 viesti IrcView.help=Toimivia komentoja ovat:\n . /help : n\u00e4ytt\u00e4\u00e4 t\u00e4m\u00e4n ohjeen\n . /nick | /name uusi_nimi : vaihtaa nimimerkkisi\n . /me toiminto : l\u00e4hett\u00e4\u00e4 toiminnon (mit\u00e4 olet tekem\u00e4ss\u00e4)\n . /msg k\u00e4ytt\u00e4j\u00e4 viesti : l\u00e4hett\u00e4\u00e4 yksityisviestin m\u00e4\u00e4ritetylle k\u00e4ytt\u00e4j\u00e4lle\n . /r viesti : vastaa viimeisimp\u00e4\u00e4n yksityisviestiin\n . /join #kanava : vaihtaa m\u00e4\u00e4ritetylle kanavalle PasswordWindow.title=Vuze lukittu PasswordWindow.passwordprotected=Vuze on salasanasuojatussa tilassa.\nJotta voisit k\u00e4ytt\u00e4\u00e4 Vuzea, anna salasana: TrackerChangerWindow.title=Lis\u00e4\u00e4 seurantapalvelin TrackerChangerWindow.newtracker=Anna uuden seurantapalvelimen osoite PeersView.discarded=Hyl\u00e4tty PeersView.discarded.info=Ladattu tietom\u00e4\u00e4r\u00e4, jota ei tarvita. discarded=hyl\u00e4tty MyTorrentsView.menu.move=Sii&rr\u00e4 MyTorrentsView.menu.moveUp=&Yl\u00f6s MyTorrentsView.menu.moveDown=&Alas GeneralView.label.hashfails=Korruptoituneet osat: GeneralView.label.shareRatio=Jakosuhde: ConfigView.section.downloadManagement=Latausten hallinta ConfigView.label.startRatioPeers=Aloita l\u00e4hett\u00e4minen, kun on v\u00e4hemm\u00e4n kuin yksi l\u00e4hde kohti ConfigView.text.neverStop=Ei koskaan ConfigView.text.neverStart=Ei koskaan ConfigView.text.peers=lataajaa ConfigView.label.checkOncompletion=Tarkasta osat uudelleen, kun lataus on valmistunut wizard.title=Luo torrent-tiedosto wizard.previous=Edellinen wizard.next=Seuraava wizard.finish=Valmis wizard.mode=Seurantapalvelin/kohteen muoto wizard.tracker=Seurantapalvelin: wizard.invalidurl=Antamasi osoite ei ole kelvollinen. wizard.singlefile=Yksitt\u00e4inen tiedosto wizard.singlefile.help=Luo torrent-tiedosto yksitt\u00e4isest\u00e4 tiedostosta wizard.directory=Hakemisto wizard.directory.help=Luo torrent-tiedosto hakemistosta wizard.choosefile=Valitse tiedosto wizard.file=Tiedosto wizard.browse=Selaa... wizard.choosedirectory=Valitse hakemisto wizard.invalidfile=Kelpaamaton tiedosto! wizard.invaliddirectory=Kelpaamaton hakemisto! wizard.torrentFile=Torrent-tiedosto wizard.choosetorrent=Valitse luotavan torrent-tiedoston asetukset wizard.information=Info wizard.notimplemented=Ei viel\u00e4 toteutettu wizard.progresstitle=Luodaan torrent-tiedostoa wizard.savingfile=Tallennetaan torrent-tiedostoa... wizard.filesaved=Torrent-tiedosto tallennettu. wizard.close=Sulje Torrent.create.progress.piecelength=Osan koko: Torrent.create.progress.piececount=Osien lukum\u00e4\u00e4r\u00e4: Torrent.create.progress.totalfilesize=Koko yhteens\u00e4: Torrent.create.progress.totalfilecount=Tiedostojen m\u00e4\u00e4r\u00e4 yhteens\u00e4: Torrent.create.progress.parsingfiles=J\u00e4sennell\u00e4\u00e4n tiedostoja Torrent.create.progress.hashing=Lasketaan tiedostoille tiivisteet MainWindow.upgrade.downloadingfrom=Ladataan kohteesta: MainWindow.menu.view.ipFilter=&IP-suotimet ConfigView.section.ipfilter=IP-suotimet ConfigView.section.ipfilter.description=Kuvaus ConfigView.section.ipfilter.start=Ensimm\u00e4inen IP-osoite ConfigView.section.ipfilter.end=Viimeinen IP-osoite ConfigView.section.ipfilter.add=Lis\u00e4\u00e4 ConfigView.section.ipfilter.remove=Poista ConfigView.section.ipfilter.edit=Muokkaa ConfigView.section.ipfilter.save=Tallenna ConfigView.section.ipfilter.editFilter=Muokkaa suodinta ConfigView.section.ipfilter.enable=IP-suotimet k\u00e4yt\u00f6ss\u00e4 PeersView.menu.close=&Sulje seedmore.title=Jakosuhde alhainen seedmore.shareratio=T\u00e4m\u00e4n torrent-tiedoston jakosuhde on seedmore.uploadmore=Alle 100 %:n jakosuhde ei ole hyv\u00e4ksi BitTorrent-verkolle.\nOn suositeltavaa, ett\u00e4 l\u00e4hett\u00e4mist\u00e4 jatkettaisiin pidemp\u00e4\u00e4n.\nHaluatko varmasti jatkaa? ConfigView.label.showpopuponclose=Pyyd\u00e4 l\u00e4hett\u00e4mist\u00e4 lopetettaessa vahvistus, jos jakosuhde on pienempi kuin 1.0 ConfigView.label.startNumSeeds=Aloita l\u00e4hett\u00e4minen, jos on v\u00e4hemm\u00e4n kuin\n - ohittaa kaikki muut s\u00e4\u00e4nn\u00f6t ConfigView.label.seeds=l\u00e4hett\u00e4j\u00e4\u00e4 ConfigView.section.seeding=Tiedostojen l\u00e4hett\u00e4minen MyTorrentsView.menu.removeand=Po&ista ja MyTorrentsView.menu.removeand.deletetorrent=tuhoa &torrent-tiedosto MyTorrentsView.menu.removeand.deletedata=tuhoa &kohdetiedostot MyTorrentsView.menu.removeand.deleteboth=tuhoa &molemmat deletedata.title=Varoitus! deletedata.message1=Haluatko varmasti poistaa pysyv\u00e4sti '%1'?\n deletedata.noprompt=\u00c4l\u00e4 kysy t\u00e4t\u00e4 uudelleen MainWindow.menu.file.configure=&Ohjattu asetusten m\u00e4\u00e4rittely... configureWizard.title=Ohjattu asetusten m\u00e4\u00e4rittely configureWizard.welcome.title=Tervetuloa ohjattuun asetusten m\u00e4\u00e4rittelyyn configureWizard.welcome.message=T\u00e4m\u00e4 ohjattu toiminto auttaa sinua asettamaan Vuzen t\u00e4rkeimm\u00e4t asetukset k\u00e4ytt\u00f6kuntoon. Voit muokata asetuksia my\u00f6hemmin tarkemmin valitsemalla Ty\u00f6kalut-valikosta Asetukset. configureWizard.transfer.title=Yhteysasetukset configureWizard.transfer.hint=Vihje: \u00c4l\u00e4 k\u00e4yt\u00e4 t\u00e4ytt\u00e4 l\u00e4hetyskapasiteettia (hidastaa latauksia). configureWizard.transfer.message=Valitse alta yhteysasetuksesi. Muista, ett\u00e4 pieni l\u00e4hetysnopeus johtaa samalla pieniin latausnopeuksiin. Samoin voi k\u00e4yd\u00e4, jos lataat liian montaa torrent-tiedostoa yht\u00e4aikaisesti (jolloin torrent-kohtainen l\u00e4hetysnopeus j\u00e4\u00e4 pieneksi). Suositus ehdottomaksi l\u00e4hetysnopeuden alarajaksi on 5 KB/s (yht\u00e4 torrent-tiedostoa kohti). Eli yleisesti: mit\u00e4 nopeammin l\u00e4het\u00e4t, sit\u00e4 nopeammin lataat (riippuen tietenkin muista k\u00e4ytt\u00e4jist\u00e4). configureWizard.transfer.connection=Yhteystyyppi configureWizard.transfer.connection.0=Mukautettu configureWizard.transfer.connection.1=Modeemi configureWizard.transfer.connection.2=Laajakaista x/128 kbps configureWizard.transfer.connection.3=Laajakaista x/256 kbps configureWizard.transfer.connection.4=Laajakaista x/384 kbps configureWizard.transfer.connection.5=Laajakaista x/512 kbps configureWizard.transfer.connection.6=Laajakaista x/768 kbps configureWizard.transfer.connection.7=Laajakaista x/1024 kbps configureWizard.transfer.maxUpSpeed=Enimm\u00e4isl\u00e4hetysnopeus configureWizard.transfer.maxActiveTorrents=Aktiivisten torrent-tiedostojen enimm\u00e4ism\u00e4\u00e4r\u00e4 configureWizard.transfer.maxDownloads=Yht\u00e4aikaisten latausten enimm\u00e4ism\u00e4\u00e4r\u00e4 configureWizard.transfer.maxUploadsPerTorrent=L\u00e4hetyspaikkojen enimm\u00e4ism\u00e4\u00e4r\u00e4/torrent configureWizard.nat.title=Sis\u00e4\u00e4ntulevan TCP-liikenteen portti configureWizard.nat.message=Jotta Vuze saavuttaisi parhaat nopeudet, tulisi siihen voida muodostaa yhteys ulkoap\u00e4in esteitt\u00e4. Alla voit testata ja/tai vaihtaa sis\u00e4\u00e4ntulevan liikenteen porttia.\n\nHuom.! T\u00e4m\u00e4 ty\u00f6kalu testaa vain TCP-yhteyksien toimivuutta. Hajautetun tietokannan (DHT) k\u00e4ytt\u00e4minen vaatii my\u00f6s avoimen UDP-portin sis\u00e4\u00e4ntulevalle liikenteelle. Jos palomuuri est\u00e4\u00e4 t\u00e4m\u00e4n liikenteen, siit\u00e4 ilmoitetaan erikseen.\n\nHuom.! Portti 6880 on varattu Vuzen sis\u00e4iseen k\u00e4ytt\u00f6\u00f6n, joten sit\u00e4 ei voida valita k\u00e4ytett\u00e4v\u00e4ksi. configureWizard.nat.test=Testaa configureWizard.nat.testing=Testataan porttia configureWizard.nat.ok=OK configureWizard.nat.ko=NAT-ongelma havaittu configureWizard.nat.unable=Testausta ei voitu suorittaa: joko...\n - porttinumero on virheellinen\n - tai porttia ei voitu k\u00e4ytt\u00e4\u00e4 (toinen sovellus ehk\u00e4 jo k\u00e4ytt\u00e4\u00e4 ko. porttia) configureWizard.file.title=Torrent-tiedostot ja nopea latauksen jatkaminen configureWizard.file.message1=Vuze tallentaa avatut torrent-tiedostot (luo kopiot) seuraavaan hakemistoon: configureWizard.file.path=Tallennushakemisto configureWizard.file.browse=Selaa... configureWizard.file.message2=Vuze voi jatkaa tiedostojen lataamista v\u00e4litt\u00f6m\u00e4sti lis\u00e4\u00e4m\u00e4ll\u00e4 t\u00e4h\u00e4n toimintoon liittyvi\u00e4 tietoja torrent-tiedostoihin (huomattavasti nopeampaa, kuin jos ladatut osat k\u00e4yt\u00e4isiin yksitellen l\u00e4pi jatkettaessa lataamista). T\u00e4ll\u00e4 menetelm\u00e4ll\u00e4 Vuze osaa my\u00f6s jatkaa yksitt\u00e4isten osien lataamista, jotka ovat j\u00e4\u00e4neet kesken. configureWizard.file.fastResume=K\u00e4yt\u00e4 nopeaa latauksen jatkamista configureWizard.file.invalidPath=Kelpaamaton hakemisto! configureWizard.finish.title=Ohjattu asetusten m\u00e4\u00e4rittely suoritettu loppuun configureWizard.finish.message=Vuzen v\u00e4ltt\u00e4m\u00e4tt\u00f6mimm\u00e4t perusasetukset ovat nyt asetettu ja Vuze on k\u00e4ytt\u00f6kunnossa.\n\nMuista, ett\u00e4 voit palata Ohjattuun asetusten m\u00e4\u00e4rittelyyn milloin tahansa k\u00e4ynnist\u00e4m\u00e4ll\u00e4 sen Ty\u00f6kalut-valikosta. Yksityiskohtaisempia asetuksia voit tarkastella valitsemalla Asetukset samaisesta valikosta. wizard.close.confirmation=Vahvistus wizard.close.message=Haluatko, ett\u00e4 t\u00e4m\u00e4 asetustenm\u00e4\u00e4rittelytoiminto n\u00e4ytet\u00e4\u00e4n ensi kerralla, kun Vuze k\u00e4ynnistet\u00e4\u00e4n? exportTorrentWizard.title=Vie torrent-tiedosto XML-muotoon exportTorrentWizard.torrentfile.title=K\u00e4sitelt\u00e4v\u00e4n torrent-tiedoston valitseminen exportTorrentWizard.torrentfile.message=Valitse viet\u00e4v\u00e4 torrent-tiedosto exportTorrentWizard.torrentfile.path=Kohde exportTorrentWizard.torrentfile.browse=Selaa... exportTorrentWizard.torrentfile.invalidPath=Kelpaamaton torrent-tiedosto exportTorrentWizard.exportfile.title=Kohdetiedoston valitseminen exportTorrentWizard.exportfile.message=Anna luotavalle XML-tiedostolle nimi ja sijainti exportTorrentWizard.exportfile.path=Kohde exportTorrentWizard.exportfile.browse=Selaa... exportTorrentWizard.exportfile.invalidPath=Kelpaamaton kohdetiedosto exportTorrentWizard.finish.title=Torrent-tiedoston vienti suoritettu loppuun exportTorrentWizard.finish.message=XML-tiedosto luotiin onnistuneesti. exportTorrentWizard.process.inputfilebad.title=Torrent-tiedosto on virheellinen exportTorrentWizard.process.inputfilebad.message=L\u00e4hdetiedostoa k\u00e4sitelt\u00e4ess\u00e4 tapahtui virhe: exportTorrentWizard.process.outputfileexists.title=Tiedosto jo olemassa exportTorrentWizard.process.outputfileexists.message=Kohdetiedosto on jo olemassa, korvataanko? exportTorrentWizard.process.torrentfail.title=Torrent-tiedostosta ei voida lukea tietoja exportTorrentWizard.process.exportfail.title=Torrent-tiedoston vieminen ei onnistu exportTorrentWizard.process.unknownfail.title=Tuntematon virhe importTorrentWizard.title=Tuo torrent-tiedosto XML-muodosta importTorrentWizard.torrentfile.title=Kohdetiedoston valitseminen importTorrentWizard.torrentfile.message=Anna luotavalle torrent-tiedostolle nimi ja sijainti importTorrentWizard.torrentfile.path=Kohde importTorrentWizard.torrentfile.browse=Selaa... importTorrentWizard.torrentfile.invalidPath=Kelpaamaton torrent-tiedosto importTorrentWizard.importfile.title=K\u00e4sitelt\u00e4v\u00e4n XML-tiedoston valitseminen importTorrentWizard.importfile.message=Valitse tuotava XML-tiedosto importTorrentWizard.importfile.path=Kohde importTorrentWizard.importfile.browse=Selaa... importTorrentWizard.importfile.invalidPath=Kelpaamaton l\u00e4hdetiedosto importTorrentWizard.finish.title=Torrent-tiedoston tuonti suoritettu loppuun importTorrentWizard.finish.message=Torrent-tiedosto luotiin onnistuneesti importTorrentWizard.process.inputfilebad.title=XML-tiedosto on virheellinen importTorrentWizard.process.inputfilebad.message=L\u00e4hdetiedostoa k\u00e4sitelt\u00e4ess\u00e4 tapahtui virhe: importTorrentWizard.process.outputfileexists.title=Tiedosto jo olemassa importTorrentWizard.process.outputfileexists.message=Kohdetiedosto on jo olemassa, korvataanko? importTorrentWizard.process.torrentfail.title=Torrent-tiedoston luominen ei onnistu importTorrentWizard.process.importfail.title=Torrent-tiedoston tuominen ei onnistu importTorrentWizard.process.unknownfail.title=Tuntematon virhe ConfigView.label.bindip=Sido paikalliseen IP-osoitteeseen tai liit\u00e4nt\u00e4\u00e4n ConfigView.label.xfs.allocation=Varaa levytilaa k\u00e4ytt\u00e4m\u00e4ll\u00e4 XFS-tiedostoj\u00e4rjestelm\u00e4n varaustapaa ConfigView.label.xfs.allocation.tooltip=Varmista, ett\u00e4 tiedosto /usr/sbin/xfs_io l\u00f6ytyy j\u00e4rjestelm\u00e4st\u00e4. Useimmissa Linux-jakeluversioissa ko. tiedosto asentuu xfsprogs-paketin mukana. xfs.allocation.xfs_io.not.found=XFS-levytilanvaraus ep\u00e4onnistui, sill\u00e4 tiedostoa /usr/sbin/xfs_io ei voitu suorittaa. Varmista, ett\u00e4 se l\u00f6ytyy j\u00e4rjestelm\u00e4st\u00e4si. Alkuper\u00e4inen virhe oli: "%1". ConfigView.label.zeronewfiles=Varaa levytilaa tiedostojen valmiin koon verran t\u00e4ytt\u00e4m\u00e4ll\u00e4 tila nollilla ConfigView.label.zeronewfiles.tooltip=V\u00e4hent\u00e4\u00e4 kiintolevyn sis\u00e4ll\u00f6n pirstoutumista. ConfigView.section.stats=Tilastot ConfigView.section.stats.enable=Tilastointitoiminto k\u00e4yt\u00f6ss\u00e4 ConfigView.section.stats.defaultsavepath=Tallennushakemisto ConfigView.section.stats.choosedefaultsavepath=Valitse tallennushakemisto tilastoille ConfigView.section.stats.savefreq=Tallennuksen aikav\u00e4li ConfigView.section.stats.hours=h ConfigView.section.stats.seconds=s ConfigView.section.stats.savefile=Tiedostonimi ConfigView.section.stats.graph_update_dividers=N\u00e4yt\u00e4 pystysuuntainen ositusviiva aina 60 p\u00e4ivityksen v\u00e4lein MyTorrentsView.menu.export=&XML-muotoon... MyTorrentsView.menu.host=Aseta &seurantaan ManagerItem.finishing=Viimeistell\u00e4\u00e4n ConfigView.dialog.choosedefaulttorrentpath=Valitse tallennushakemisto torrent-tiedostoille ConfigView.dialog.choosemovepath=Valitse hakemisto, johon siirret\u00e4\u00e4n ConfigView.label.movecompleted=Siirr\u00e4 valmistuneet tiedostot (latauksen j\u00e4lkeen) ConfigView.label.moveremoved=Siirr\u00e4 valmistuneet tiedostot (poistettaessa) ConfigView.label.savetorrents=Tallenna torrent-tiedostot MainWindow.menu.view.mytracker=Seuranta&palvelin MyTrackerView.title.full=Seurantapalvelin MyTrackerView.name=Nimi MyTrackerView.tracker=Seurantapalvelin MyTrackerView.status=Tila MyTrackerView.status.started=Seurataan MyTrackerView.status.stopped=Pys\u00e4ytetty MyTrackerView.peers=Lataajat MyTrackerView.seeds=L\u00e4hteet MyTrackerView.announces=P\u00e4ivitykset MyTrackerView.uploaded=L\u00e4hetetty MyTrackerView.downloaded=Ladattu MyTrackerView.left=J\u00e4ljell\u00e4 ConfigView.section.style=K\u00e4ytt\u00f6liittym\u00e4 ConfigView.label.set_ui_transfer_speeds=Ohita valittavat siirtonopeusrajoitukset ConfigView.label.set_ui_transfer_speeds.description=Voit asettaa manuaalisesti tilarivin ja ilmoitusalueen valikoista valittavissa olevat lataus- ja l\u00e4hetysnopeusrajoitusarvot.\nErota arvot toisistaan pilkulla. ConfigView.label.set_ui_transfer_speeds.description.download=Aseta arvot latausnopeudelle (KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Aseta arvot l\u00e4hetysnopeudelle (KB/s) ConfigView.section.style.useCustomTabs=K\u00e4yt\u00e4 suljettavia v\u00e4lilehti\u00e4 (vaatii uudelleenk\u00e4ynnistyksen) MainWindow.menu.view.plugins=&Lis\u00e4osat fileDownloadWindow.saveTorrentIn=Tallenna torrent-tiedosto hakemistoon fileDownloadWindow.title=Torrent-tiedoston lataaminen fileDownloadWindow.downloading=Ladataan kohdetta: fileDownloadWindow.status=Tila: fileDownloadWindow.state_initializing=Aloitetaan fileDownloadWindow.state_downloading=Ladataan fileDownloadWindow.state_error=Virhe: MainWindow.menu.file.open.url=Torrent-tiedosto &URL-osoitteesta... MainWindow.menu.file.open.url.keybinding=Meta+U openUrl.title=Avaa torrent-tiedosto osoitteesta openUrl.url=URL-osoite: MyTorrentsView.menu.host.error.title=Seurantaan asettaminen ep\u00e4onnistui MyTorrentsView.menu.host.error.message=Seuraava virhe esiintyi asetettaessa torrent-tiedostoa seurantaan ConfigView.section.tracker=Seuranta ConfigView.section.tracker.pollinterval=Tietojen kysymisen aikav\u00e4li sekunneissa ConfigView.section.tracker.publishenable=N\u00e4yt\u00e4 seurattavat/julkistetut torrent-tiedostot www-sivulla seurantapalvelimen URL-osoitteessa ConfigView.section.tracker.ip=Seurantapalvelimen ulkoinen IP-osoite ConfigView.section.style.enableXPStyle=K\u00e4yt\u00e4 Windows XP -tyyli\u00e4 (vaatii uudelleenk\u00e4ynnistyksen) IPChecker.external.service.dyndns.url=http://www.dyndns.org IPChecker.external.service.dyndns.description=Dynamic DNS Network Services, LLC. ConfigView.section.tracker.checkip=Hae osoite automaattisesti... ipCheckerWizard.title=IP-osoitteen tarkastaminen ipCheckerWizard.service=Palvelu ipCheckerWizard.chooseService=Valitse palvelu, jonka avulla IP-osoite tarkastetaan. ipCheckerWizard.explanations=T\u00e4m\u00e4n toiminnon avulla voit selvitt\u00e4\u00e4 ulkoisen IP-osoitteesi, jota tarvitaan oman seurantapalvelimen k\u00e4ytt\u00e4misess\u00e4.\n\nJos IP-osoitteesi on dynaaminen (vaihtuva), on suositeltavaa k\u00e4ytt\u00e4\u00e4 dynaamisen tuen tarjoavaa verkkotunnusj\u00e4rjestelm\u00e4palvelua. Muutamia t\u00e4llaisia palveluja on listattu alla, k\u00e4y rekister\u00f6itym\u00e4ss\u00e4 johonkin niist\u00e4 (jos kyseinen palvelu mahdollistaa t\u00e4m\u00e4n). T\u00e4m\u00e4n j\u00e4lkeen voit k\u00e4ytt\u00e4\u00e4 oman seurantapalvelimen osoitteena nimimuodossa olevaa osoitetta, tyyliin esimerkki.dyndns.org.\n\nTarvitset my\u00f6s ohjelman, joka p\u00e4ivitt\u00e4\u00e4 muuttuvan IP-osoitteesi valitsemaasi palveluun. T\u00e4ll\u00e4 tavoin voit k\u00e4ytt\u00e4\u00e4 omaa seurantapalvelintasi, vaikka IP-osoite vaihtelisikin jatkuvasti. ipCheckerWizard.service.description=Kuvaus: ipCheckerWizard.service.url=Sivusto: ipCheckerWizard.progresstitle=Tarkastetaan IP-osoitetta ipCheckerWizard.checkComplete=K\u00e4ytett\u00e4v\u00e4 IP-osoite: ipCheckerWizard.checkFailed=Tarkastus ep\u00e4onnistui, syy: wizard.tracker.local=Vuzen oma sis\u00e4inen seurantapalvelin wizard.tracker.external=Ulkoinen seurantapalvelin wizard.tracker.howToLocal=\tVaatii k\u00e4ytt\u00f6\u00f6noton asetuksista! wizard.announceUrl=P\u00e4ivitysosoite: IPChecker.external.service.discoveryvip.url=http://ip.discoveryvip.com IPChecker.external.service.discoveryvip.description=Ainoastaan IP-osoitteen tarkastus. IPChecker.external.httpinvalidresponse=Virheellinen HTTP-vastaus IPChecker.external.loadingwebpage=Ladataan sivua IPChecker.external.analysingresponse=Analysoidaan vastausta IPChecker.external.addressextracted=Selvitetty IP-osoite IPChecker.external.httploadfail=Sivua ei voitu ladata IPChecker.external.timeout=Pyynt\u00f6 aikakatkaistiin IPChecker.external.ipnotfound=IP-osoitetta ei l\u00f6ytynyt ConfigView.section.tracker.pollintervalmin=V\u00e4himm\u00e4isaika ConfigView.section.tracker.pollintervalmax=Enimm\u00e4isaika ConfigView.section.tracker.pollintervalincby=Kasvata aikaa ConfigView.section.tracker.pollintervalincper=sekunnilla n\u00e4in monen k\u00e4ytt\u00e4j\u00e4n j\u00e4lkeen splash.loadingImages=Ladataan kuvia splash.initializeGui=Alustetaan graafista k\u00e4ytt\u00f6liittym\u00e4\u00e4 splash.openViews=Avataan v\u00e4lilehti\u00e4 splash.plugin=Ladataan lis\u00e4osaa - configureWizard.nat.tooManyPorts=Liian monta testattavaa porttia (enint\u00e4\u00e4n 9) ConfigView.section.color=V\u00e4riteema MyTorrentsView.menu.publish=&Julkaise MyTrackerView.status.published=Julkistettu MyTrackerView.completed=Valmiina MainWindow.menu.file.open.torrentnodefault=Torrent-tiedosto... (m\u00e4\u00e4rit\u00e4 lataushakemisto) wizard.comment=Kommentti ConfigView.label.movetorrent=Siirr\u00e4 torrent-tiedosto ConfigView.label.movepartialdownloads=Siirr\u00e4, vaikka tiedoston tila olisikin "Ei ladata" ConfigView.label.subdir_is_in_default=Siirrett\u00e4ess\u00e4 tiedostoja oletustallennushakemistosta siirr\u00e4 my\u00f6s sen alihakemistojen tiedostot ConfigView.section.file.decoder.label=Kysytt\u00e4ess\u00e4 torrent-tiedoston koodausta k\u00e4yt\u00e4 oletuksena ConfigView.section.file.decoder.nodecoder=Ei mit\u00e4\u00e4n IPChecker.external.service.no-ip.url=http://www.no-ip.com IPChecker.external.service.no-ip.description=Dynaamisen ja staattisen tuen tarjoava DNS-palvelu\n(ei IP-osoitteen tarkastusta ilmaiseksi). ConfigView.section.tracker.publicenable=Salli ulkoiset torrent-tiedostot ConfigView.label.playdownloadspeech=Ilmoita puhuen latauksen valmistumisesta ConfigView.label.playdownloadspeech.info=Puhepalvelu toimii t\u00e4ll\u00e4 hetkell\u00e4 parhaiten englanniksi. # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Kuvastaa osien saatavilla olevien kopioiden m\u00e4\u00e4r\u00e4\u00e4 k\u00e4ytt\u00e4jien keskuudessa.\nJos oikealla oleva luku on alle yhden, kaikkia osia eli tiedosto(j)a kokonaisena ei ole saatavilla. GeneralView.label.trackerurl.tooltip=Klikkaa kopioidaksesi seurantapalvelimen p\u00e4ivitysosoite leikep\u00f6yd\u00e4lle. GeneralView.label.trackerurlopen.tooltip=Klikkaa avataksesi seurantapalvelimen etusivu. # # 2.0.4.4 # ConfigView.section.style.guiUpdate=P\u00e4ivit\u00e4 graafinen k\u00e4ytt\u00f6liittym\u00e4 (GUI) joka ConfigView.section.style.inactiveUpdate=P\u00e4ivit\u00e4 toimeton p\u00e4\u00e4ikkuna n\u00e4in monen GUI-p\u00e4ivityksen j\u00e4lkeen ConfigView.section.style.graphicsUpdate=P\u00e4ivit\u00e4 graafiset palkit n\u00e4in monen GUI-p\u00e4ivityksen j\u00e4lkeen ConfigView.section.style.reOrderDelay=J\u00e4rjest\u00e4 taulukot uudelleen n\u00e4in monen GUI-p\u00e4ivityksen j\u00e4lkeen (0 = ei koskaan) ConfigView.section.style.reOrderDelay.never=Ei koskaan ConfigView.section.logging=Loki ConfigView.section.logging.enable=Kirjaa tapahtumat lokitiedostoon ConfigView.section.logging.logdir=Lokien tallennushakemisto ConfigView.section.logging.choosedefaultsavepath=Valitse lokien tallennushakemisto GeneralView.label.updatein.querying=Pyydet\u00e4\u00e4n tietoja... configureWizard.nat.sharePort=K\u00e4yt\u00e4 yht\u00e4 porttia kaikkien torrent-tiedostojen sis\u00e4\u00e4ntulevalle liikenteelle ConfigView.section.logging.maxsize=Tiedoston enimm\u00e4iskoko ConfigView.section.tracker.passwordenableweb=K\u00e4yt\u00e4 salasanasuojausta seurantapalvelimen sivulla ConfigView.section.tracker.passwordenabletorrent=K\u00e4yt\u00e4 salasanasuojausta torrent-tiedostoissa ConfigView.section.tracker.username=K\u00e4ytt\u00e4j\u00e4tunnus ConfigView.section.tracker.password=Salasana columnChooser.title=N\u00e4ytett\u00e4v\u00e4t sarakkeet columnChooser.move=Voit vaihtaa sarakkeiden j\u00e4rjestyst\u00e4 raahaamalla ne haluamiisi kohtiin. columnChooser.apply=K\u00e4yt\u00e4 columnChooser.columnname=Sarake columnChooser.columndescription=Kuvaus TableColumn.header.shareRatio=Jakosuhde MyTorrentsView.menu.editTableColumns=&Valitse n\u00e4ytett\u00e4v\u00e4t sarakkeet wizard.operationfailed=Toiminto ep\u00e4onnistui authenticator.title=Vahvista toiminto authenticator.realm=Asiakasohjelma authenticator.tracker=Seurantapalvelin authenticator.user=K\u00e4ytt\u00e4j\u00e4tunnus authenticator.password=Salasana ConfigView.label.allowSendVersion=L\u00e4het\u00e4 anonyymisti Vuzen versionumero ja satunnainen tunniste uutta versiota tarkastettaessa ConfigView.label.version.info.link=Katso t\u00e4st\u00e4 lis\u00e4tietoja l\u00e4hetett\u00e4vist\u00e4 tiedoista wizard.hint.mode=Vihje:\tVoit raahata ja pudottaa yksitt\u00e4isen tiedoston tai hakemiston\n\tt\u00e4m\u00e4n ikkunan p\u00e4\u00e4lle valitaksesi kohteen. wizard.hint.file=Vihje:\tVoit valita yksitt\u00e4isen tiedoston my\u00f6s raahaamalla ja\n\tpudottamalla sen t\u00e4m\u00e4n ikkunan p\u00e4\u00e4lle. wizard.hint.directory=Vihje:\tVoit valita yksitt\u00e4isen hakemiston my\u00f6s raahaamalla ja\n\tpudottamalla sen t\u00e4m\u00e4n ikkunan p\u00e4\u00e4lle. MainWindow.menu.help.checkupdate=Tarkasta &p\u00e4ivitykset... TableColumn.header.down=Ladattu TableColumn.header.up=L\u00e4hetetty ConfigView.section.tracker.passwordenabletorrent.info=Vaatii yhteensopivan asiakasohjelman (kuten Vuzen) ConfigView.section.style.confirmationOnExit=Pyyd\u00e4 vahvistus lopetettaessa MainWindow.dialog.exitconfirmation.title=Lopeta Vuze MainWindow.dialog.exitconfirmation.text=Haluatko varmasti sulkea Vuzen? SystemTray.menu.stopalltransfers=&Pys\u00e4yt\u00e4 kaikki siirrot TrayWindow.menu.stopalldownloads=&Pys\u00e4yt\u00e4 kaikki lataukset ConfigView.section.tracker.sslport.info=Lis\u00e4tietoja UKK:ssa wizard.tracker.ssl=K\u00e4yt\u00e4 SSL:\u00e4\u00e4 ConfigView.label.playdownloadfinished=Anna \u00e4\u00e4nimerkki latauksen valmistuttua ConfigView.label.popupdownloadfinished=Ilmoita latauksen valmistumisesta ponnahdusikkunalla ConfigView.label.popupfilefinished=Ilmoita tiedoston valmistumisesta ponnahdusikkunalla TableColumn.header.pieces=Osat TableColumn.header.pieces.info=Valmistuneet osat graafisena palkkiesityksen\u00e4. TableColumn.header.completion=Valmistumisaste TableColumn.header.completion.info=Latauksen prosenttim\u00e4\u00e4r\u00e4inen valmistuminen graafisesti. ConfigView.section.style.showdownloadbasket=N\u00e4yt\u00e4 pikalatauskuvake - lis\u00e4\u00e4 ty\u00f6p\u00f6yd\u00e4lle kuvakkeen, johon voit raahata ja pudottaa torrent-tiedostoja ConfigView.section.style.alwaysShowTorrentFiles=N\u00e4yt\u00e4 aina torrent-tiedoston k\u00e4sitt\u00e4m\u00e4t tiedostot wizard.multitracker=M\u00e4\u00e4rit\u00e4 useita seurantapalvelimia wizard.multitracker.title=Seurantapalvelimien valitseminen wizard.multitracker.configuration=Valmiit p\u00e4\u00e4ryhm\u00e4t: wizard.multitracker.new=Uusi... wizard.multitracker.edit=Muokkaa... wizard.multitracker.delete=Poista wizard.multitracker.group=Seurantapalvelinryhm\u00e4 wizard.multitracker.edit.title=Seurantapalvelimien muokkaus wizard.multitracker.edit.name=Nimi wizard.multitracker.edit.save=Tallenna wizard.multitracker.edit.newgroup=Uusi ryhm\u00e4 wizard.multitracker.edit.deletegroup=Poista wizard.multitracker.edit.newtracker=Uusi seurantapalvelin wizard.multitracker.edit.deletetracker=Poista wizard.multitracker.edit.edit=Muokkaa wizard.addingmt=Lis\u00e4t\u00e4\u00e4n tietoja seurantapalvelimista wizard.multitracker.noannounce=P\u00e4ivitysosoitetta ei l\u00f6ydy seurantapalvelinlistalta. MyTorrentsView.menu.recheck=&Tarkasta ladatut osat uudelleen iconBar.showDownloadBar.tooltip=N\u00e4yt\u00e4 seurantapalkki iconBar.start.tooltip=K\u00e4ynnist\u00e4 (aseta jonoon) valitut torrentit iconBar.stop.tooltip=Pys\u00e4yt\u00e4 valitut torrentit iconBar.remove.tooltip=Poista torrent-tiedosto iconBar.openNoDefault.tooltip=Avaa torrent-tiedosto (m\u00e4\u00e4rit\u00e4 lataushakemisto) iconBar.openURL.tooltip=Avaa torrent-tiedosto URL-osoitteesta iconBar.openFolder.tooltip=Avaa hakemisto (lis\u00e4\u00e4 kaikki hakemiston torrent-tiedostot) iconBar.new.tooltip=Luo torrent-tiedosto iconBar.up.tooltip=Siirr\u00e4 yl\u00f6s iconBar.down.tooltip=Siirr\u00e4 alas iconBar.run.tooltip=Avaa oletussovelluksessa iconBar.host.tooltip=Aseta seurantaan iconBar.publish.tooltip=Julkaise iconBar.editcolumns.tooltip=Sarakeasetukset MyTorrentsView.menu.editTracker=&Muokkaa seurantapalvelimia GeneralView.menu.selectTracker=Valitse seurantapalvelin ConfigView.section.stats.xslfile=XSL-tyylitiedoston nimi ConfigView.section.stats.xslfiledetails=Lis\u00e4t\u00e4\u00e4n XML-tiedostoon -tunnisteeksi ConfigView.label.savetorrentbackup=Tallenna my\u00f6s varmuuskopio ConfigView.section.tracker.forceport=Pakota ulkoiset torrent-tiedostot oletusporttiin ConfigView.section.ipfilter.allow=Salli yhteydet vain n\u00e4ilt\u00e4 osoitealueilta (k\u00e4\u00e4nt\u00e4\u00e4 suotimien tarkoituksen) ConfigView.section.ipfilter.list.inrange=oli osoitealueella ConfigView.section.ipfilter.list.notinrange=ei ollut osoitealueilla ConfigView.section.ipfilter.list.title=Estetyt k\u00e4ytt\u00e4j\u00e4t ConfigView.label.allowsameip=Salli useat yhteydet samasta IP-osoitteesta ConfigView.label.allowsameip.tooltip=K\u00e4yt\u00e4 vain, jos todella tarvitset.\nKun asetus ei ole k\u00e4yt\u00f6ss\u00e4, se est\u00e4\u00e4 sellaisten k\u00e4ytt\u00e4jien yhteydenotot,\njotka lataavat tiedostoja, mutta eiv\u00e4t juurikaan (tai ollenkaan) l\u00e4het\u00e4 (mik\u00e4 ei ole hyv\u00e4 asia). ManagerItem.superseeding=L\u00e4hetet\u00e4\u00e4n (tehostetusti) ConfigView.label.userSuperSeeding=K\u00e4yt\u00e4 tehostettua l\u00e4hetystapaa PeersView.uniquepiece=Osa (tehostettu) PeersView.uniquepiece.none=Ei k\u00e4yt\u00f6ss\u00e4 PeersView.timetosend=Uudelleenl\u00e4hetys (tehostettu) ConfigView.section.style.addurlsilently=Avaa torrent-tiedostot URL-osoitteista ilman erillisi\u00e4 ilmoituksia ConfigView.section.style.addurlsilently.tooltip=URL-osoitteista ladattavat torrent-tiedostot avataan ilman erillisi\u00e4 ilmoituksia. ConfigView.section.file.decoder.prompt=Kysy aina, kun eri koodausvaihtoehtoja k\u00e4ytett\u00e4viss\u00e4 ConfigView.section.file.decoder.prompt.tooltip=N\u00e4ytt\u00e4\u00e4 aina valintaikkunan, jos on tarjolla eri koodausvaihtoehtoja. MyTorrentsView.menu.moveTop=Ylimm&\u00e4ksi MyTorrentsView.menu.moveEnd=A&limmaksi ConfigView.label.moveonlyusingdefaultsave=Siirr\u00e4, jos oletustallennushakemistossa ConfigView.label.moveonlyusingdefaultsave.tooltip=Siirt\u00e4\u00e4 tiedostot vain, jos ne ovat tallennettu oletustallennushakemistoon. ConfigView.label.watchtorrentfolder=Avaa torrent-tiedostot automaattisesti ConfigView.label.watchtorrentfolder.tooltip=Etsii uusia torrent-tiedostoja ladattavaksi s\u00e4\u00e4nn\u00f6llisin v\u00e4liajoin. ConfigView.label.watchtorrentfolderinterval=Tarkastusaikav\u00e4li ConfigView.label.watchtorrentfolderinterval.tooltip=Aikav\u00e4li, jonka kuluttua hakemisto tarkastetaan uudelleen. ConfigView.dialog.choosewatchtorrentfolderpath=Valitse torrent-tiedostojen avaushakemisto ConfigView.label.startwatchedtorrentsstopped=Aseta pys\u00e4ytetty-tilaan ConfigView.label.startwatchedtorrentsstopped.tooltip=Latausta ei aloiteta, vaan torrent-tiedosto asetetaan heti pys\u00e4ytetty-tilaan. ConfigView.section.plugins=Lis\u00e4osat wizard.maketorrent.filesize=Tiedosto(je)n koko: wizard.maketorrent.piececount=Osien lukum\u00e4\u00e4r\u00e4: wizard.maketorrent.piecesize=Osan koko: wizard.maketorrent.auto=Autom. MainWindow.menu.view.stats=T&ilastot SpeedView.title.full=Siirtonopeudet SpeedView.downloadSpeed.title=Latausnopeus SpeedView.uploadSpeed.title=L\u00e4hetysnopeus ConfigView.section.style.useSIUnits=K\u00e4yt\u00e4 IEC-mittayksikk\u00f6j\u00e4rjestelm\u00e4\u00e4 (esim. kB -> KiB) iconBar.top.tooltip=Siirr\u00e4 ylimm\u00e4ksi iconBar.bottom.tooltip=Siirr\u00e4 alimmaksi TableColumn.header.health=Yhteys MyTorrentsView.menu.health=Tietoja sarakkeesta "Yhteys" health.explain.grey=Torrent-tiedosto on t\u00e4ysin pys\u00e4ytetty (sit\u00e4 ei ladata eik\u00e4 l\u00e4hetet\u00e4). health.explain.red=Et ole yhteydess\u00e4 yhteenk\u00e4\u00e4n k\u00e4ytt\u00e4j\u00e4\u00e4n (ladattaessa). health.explain.blue=L\u00e4hetett\u00e4ess\u00e4: et ole viel\u00e4 yhteydess\u00e4 yhteenk\u00e4\u00e4n lataajaan.\nLadattaessa: olet yhteydess\u00e4 k\u00e4ytt\u00e4jiin, mutta seurantapalvelin ei ole k\u00e4ytett\u00e4viss\u00e4. health.explain.yellow=Seurantapalvelin on kunnossa ja olet yhdist\u00e4nyt k\u00e4ytt\u00e4jiin, mutta sinuun ei saada yhteytt\u00e4 ulkoa k\u00e4sin.\nT\u00e4m\u00e4 voi olla merkki NAT-ongelmasta, jos n\u00e4et keltaisia ilmaisimia jatkuvasti. health.explain.green=Kaikki kunnossa. ConfigView.section.style.alwaysRefreshMyTorrents=P\u00e4ivit\u00e4 aina Siirrot-ikkuna ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Siirrot-ikkunan sis\u00e4lt\u00f6 p\u00e4ivitet\u00e4\u00e4n, vaikka ikkuna ei olisikaan avattuna (tietyt lis\u00e4osat hy\u00f6dynt\u00e4v\u00e4t t\u00e4t\u00e4). # #2.0.7.0 # security.certtruster.title=Turvallisuusvarmennevaroitus security.certtruster.intro=Turvallisuusvarmenteen my\u00f6nsi osapuoli, johon et luota. security.certtruster.resource=L\u00e4hde: security.certtruster.issuedto=Kenelle: security.certtruster.issuedby=My\u00f6nt\u00e4j\u00e4: security.certtruster.prompt=Hyv\u00e4ksytk\u00f6 t\u00e4m\u00e4n varmenteen? security.certtruster.yes=Kyll\u00e4 security.certtruster.no=En ConfigView.section.tracker.torrentsperpage=Torrent-tiedostojen lukum\u00e4\u00e4r\u00e4/sivu (0 = rajoittamaton) MainWindow.menu.file.share=&Jaa MainWindow.menu.file.share.file=&Tiedosto... MainWindow.menu.file.share.dir=&Hakemisto... MainWindow.menu.file.share.dircontents=Hakemiston &sis\u00e4lt\u00f6... MainWindow.menu.file.share.dircontentsrecursive=Hakemiston sis\u00e4lt\u00f6... (&rekursiivisesti) MainWindow.dialog.share.sharefile=Valitse jaettava tiedosto MainWindow.dialog.share.sharedir=Valitse jaettava hakemisto MainWindow.dialog.share.sharedircontents=Valitse p\u00e4\u00e4hakemisto MainWindow.dialog.share.sharedircontents.recursive=jaetaan rekursiivisesti globalmanager.download.remove.veto=Poistaminen estetty plugin.sharing.download.remove.veto=T\u00e4m\u00e4 siirto on jaossa oleva kohde.\nJotta voisit poistaa siirron, sinun t\u00e4ytyy ensin poistaa kyseinen jako (Classic-Share): Ty\u00f6kalut->Jaot (Tools->My Classic-Shares). ConfigView.section.tracker.main=Perusasetukset ConfigView.label.prioritizefirstpiece=Pyri lataamaan ensisijaisesti tiedostojen ensimm\u00e4iset ja viimeiset osat ConfigView.label.prioritizefirstpiece.tooltip=Pyrkii lataamaan aluksi tiedoston ensimm\u00e4isen ja viimeisen osan mahdollista esikatselua varten. ConfigView.section.file.confirm_data_delete=Vahvista tiedostojen poisto ConfigView.section.file.confirm_data_delete.tooltip=Pyyt\u00e4\u00e4 vahvistusta, kun torrent-tiedostolle k\u00e4ytet\u00e4\u00e4n toimintoa "Poista ja tuhoa...". ConfigView.section.file.delete.include_files_outside_save_dir=Kun tiedostoja poistetaan, salli linkitettyjen tiedostojen poistaminen my\u00f6s muualta kuin torrenttien tallennushakemistosta TrayWindow.menu.startalldownloads=K\u00e4ynnist\u00e4 kaikki lataukset SystemTray.menu.startalltransfers=K\u00e4ynnist\u00e4 kaikki siirrot sharing.progress.title=Jakamisen edistyminen sharing.progress.hide=Piilota MainWindow.menu.view.myshares=&Jaot MySharesView.title.full=Jaot MySharesView.name=Nimi MySharesView.type=Tyyppi MySharesView.type.file=Tiedosto MySharesView.type.dir=Hakemisto MySharesView.type.dircontents=Hakemiston sis\u00e4lt\u00f6 MySharesView.type.dircontentsrecursive=Hakemiston sis\u00e4lt\u00f6 (rekursiivisesti) MySharesView.menu.remove=Poista ConfigView.section.tracker.extensions=Lis\u00e4asetukset ConfigView.section.tracker.sendpeerids=L\u00e4het\u00e4 tunnisteet k\u00e4ytt\u00e4jist\u00e4 lataajille ConfigView.section.tracker.enableudp=K\u00e4yt\u00e4 seurantapalvelimen UDP-protokollaa plugin.sharing.torrent.remove.veto=T\u00e4m\u00e4 on jaettu kohde.\nPoistaaksesi kohteen poista ensin kyseinen jako (Classic-Share): Ty\u00f6kalut->Jaot (Tools->My Classic-Shares). plugin.download.remove.veto.notstopped=Kohdetta ei voida poistaa, koska sit\u00e4 ei ole pys\u00e4ytetty. plugin.sharing.remove.veto=T\u00e4m\u00e4 kohde on Hakemiston sis\u00e4lt\u00f6 -jaon alainen, joten et voi poistaa sit\u00e4 suoraan.\nPoistaaksesi kohteen poista p\u00e4\u00e4jako (p\u00e4\u00e4hakemisto). GeneralView.label.hash.tooltip=Klikkaa kopioidaksesi tiiviste leikep\u00f6yd\u00e4lle. ConfigView.section.tracker.maxpeersreturned=Palautettavien yhteystietojen enimm\u00e4ism\u00e4\u00e4r\u00e4\n(0 = rajoittamaton) ConfigView.label.serverport=Sis\u00e4\u00e4ntulevan TCP- ja UDP-liikenteen portti ConfigView.label.serverport.tooltip=Portin t\u00e4ytyy olla v\u00e4lilt\u00e4 1-65535, eik\u00e4 se saa olla 6880, koska\nkyseinen portti on varattu Vuzen sis\u00e4iseen k\u00e4ytt\u00f6\u00f6n. configureWizard.nat.server.tcp_listen_port=Sis\u00e4\u00e4ntulevan TCP-liikenteen portti ConfigView.section.sharing=Jakaminen ConfigView.section.sharing.usessl=K\u00e4yt\u00e4 SSL:\u00e4\u00e4 jaetuille resursseille (seurantapalvelimen asetusten oltava vastaavat) ConfigView.section.style.dropdiraction=Toiminto raahatessa ja pudotettaessa kansioita Vuzeen ConfigView.section.style.dropdiraction.opentorrents=Avaa torrent-tiedostot ConfigView.section.style.dropdiraction.sharefolder=Jaa hakemisto ConfigView.section.style.dropdiraction.sharefoldercontents=Jaa hakemiston sis\u00e4lt\u00f6 # # 2.0.7.x # Categories.all=Kaikki Categories.uncategorized=Luokittelemattomat CategoryAddWindow.message=Anna uuden luokan nimi: CategoryAddWindow.title=Uusi luokka ConfigView.label.autoSeedingIgnoreInfo=Ohitetut torrent-tiedostot menev\u00e4t l\u00e4hetysjonon loppup\u00e4\u00e4h\u00e4n ja niit\u00e4 ei aloiteta l\u00e4hett\u00e4m\u00e4\u00e4n automaattisesti.\nN\u00e4m\u00e4 ohituss\u00e4\u00e4nn\u00f6t eiv\u00e4t p\u00e4de niihin torrent-tiedostoihin, jotka ovat saavuttaneet ensisijaisuuden.\nNolla-arvo (0) tarkoittaa asetuksissa s\u00e4\u00e4nn\u00f6n poistamista k\u00e4yt\u00f6st\u00e4, ellei toisin mainita. ConfigView.label.directory=Hakemisto ConfigView.label.disconnetseed.tooltip=Yhteys l\u00e4hett\u00e4jiin voidaan katkaista, koska niit\u00e4 ei en\u00e4\u00e4 tarvita latauksen valmistuttua. ConfigView.label.ignoreCase=Kirjainten koolla ei v\u00e4li\u00e4 ConfigView.label.ignoreSeeds=Ohita torrent-tiedostot, joilla on v\u00e4hint\u00e4\u00e4n ConfigView.label.importdirectory=Avaushakemisto ConfigView.label.minPeersToBoostNoSeeds.tooltip=Ehdot t\u00e4ytt\u00e4v\u00e4t torrent-tiedostot siirret\u00e4\u00e4n l\u00e4hetysjonon loppup\u00e4\u00e4h\u00e4n. ConfigView.label.minPeersToBoostNoSeeds=Alenna torrent-tiedostojen l\u00e4hetystarvetta, joilla ei ole l\u00e4hteit\u00e4 ja v\u00e4hemm\u00e4n kuin ConfigView.label.minSeedingTime.tooltip=Torrent-tiedostojen l\u00e4hetystarpeet voivat vaihdella niin nopeasti, ett\u00e4 kun torrent-tiedosto on asetettu l\u00e4hetett\u00e4v\u00e4ksi,\nse pys\u00e4ytet\u00e4\u00e4nkin samantien ja palautetaan jonoon. T\u00e4ll\u00e4 asetuksella v\u00e4himm\u00e4isl\u00e4hetysaika voidaan pakottaa tietyn pituiseksi.\nL\u00e4hetyksen voi toki t\u00e4llaisessa tilanteessa pys\u00e4ytt\u00e4\u00e4 manuaalisesti. ConfigView.label.minSeedingTime=V\u00e4himm\u00e4isl\u00e4hetysaika sekunneissa ConfigView.label.minSpeedForActiveDL.tooltip=Normaalisti torrent-tiedosto lasketaan kuuluvaksi t\u00e4h\u00e4n\njoukkoon v\u00e4hint\u00e4\u00e4n 30 sekunnin ajaksi latauksen k\u00e4ynnistymisest\u00e4 l\u00e4htien. ConfigView.label.minSpeedForActiveDL=\u00c4l\u00e4 laske torrent-tiedostoa ladattavien joukkoon, jos latausnopeus on alle ConfigView.label.peers=lataajaa ConfigView.label.queue.debuglog=Kirjaa virheenm\u00e4\u00e4ritystiedot lokiin ConfigView.label.queue.debuglog.info=Lis\u00e4\u00e4 siirtojonotoimintojen virheenm\u00e4\u00e4ritystiedot konsoliin/lokitiedostoon.\nVaikka tiedot ovatkin vaikeaselkoisia, saa niist\u00e4 selville torrent-tiedostojen tilan ja miksi ne ovat k\u00e4ynnistyneet tai pys\u00e4htyneet. ConfigView.label.queue.minQueueingShareRatio=\u00c4l\u00e4 aseta jonoon/pys\u00e4yt\u00e4 torrent-tiedostoa ennen kuin jakosuhde on ConfigView.label.ratio=jakosuhde ConfigView.label.removeOnStop=Poista torrent-tiedosto, kun se on automaattisesti pys\u00e4htynyt ConfigView.label.savedirectory=Tallennushakemisto ConfigView.label.seeding.autoReposition.tooltip=Jos k\u00e4yt\u00f6ss\u00e4, torrent-tiedostojen j\u00e4rjestys (#-sarake Siirrot-ikkunassa)\nm\u00e4\u00e4r\u00e4ytyy niiden l\u00e4hetystarpeen mukaan.\nHy\u00f6dyllinen toiminto, jos et halua n\u00e4hd\u00e4 l\u00e4hetystarvearvoja, mutta haluat silti\nolla selvill\u00e4 siit\u00e4, mit\u00e4 valmistunutta torrent-tiedostoa aloitetaan l\u00e4hett\u00e4\u00e4 seuraavaksi. ConfigView.label.seeding.autoReposition=J\u00e4rjest\u00e4 torrent-tiedostot perustuen l\u00e4hetystarpeeseen ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Jos torrent-tiedostolla on v\u00e4h\u00e4n l\u00e4hteit\u00e4 ja kuitenkin paljon lataajia, tarkoittaa se usein sit\u00e4,\nett\u00e4 lataajien joukossa on tuskin yht\u00e4\u00e4n t\u00e4ytt\u00e4 kopiota.\nNiinp\u00e4 haluat ehk\u00e4 rajoittaa edellist\u00e4 s\u00e4\u00e4nt\u00f6\u00e4, jotta Vuze ei turhaan alenna torrent-tiedoston sijoitusta l\u00e4hetysjonossa. ConfigView.label.seeding.fakeFullCopySeedStart=mutta vain torrent-tiedostoille, joilla on v\u00e4hint\u00e4\u00e4n ConfigView.label.seeding.ignore=Ohituss\u00e4\u00e4nn\u00f6t ConfigView.label.seeding.ignore0Peers=Ohita torrent-tiedostot, joilla ei ole yht\u00e4\u00e4n lataajaa ConfigView.label.seeding.ignoreRatioPeers=Ohita torrent-tiedostot, joilla on v\u00e4hint\u00e4\u00e4n yksi l\u00e4hde kohti ConfigView.label.seeding.ignoreShareRatio=Ohita torrent-tiedostot, joiden jakosuhde on ConfigView.label.seeding.ignore.header.evenFirstPriority=Ohita torrent-tiedosto,\nvaikka olisi ensisijainen ConfigView.label.seeding.ignore.header.rule=S\u00e4\u00e4nt\u00f6 ConfigView.label.seeding.ignore.header.value=Arvo ConfigView.label.seeding.firstPriority.info=Ensisijaiset torrent-tiedostot ovat aina l\u00e4hetysjonon k\u00e4rkip\u00e4\u00e4ss\u00e4. Jos torrent-tiedosto on ensisijainen, sit\u00e4 ei automaattisesti pys\u00e4ytet\u00e4 eik\u00e4 aseteta takaisin jonoon. Ensisijainen torrent-tiedosto voi my\u00f6s varata itselleen yht\u00e4aikaisen latauspaikan, jos se tarvitsee sellaista. ConfigView.label.seeding.firstPriority.FP=Ensisijaisuus ConfigView.label.seeding.firstPriority=Ensisijaisuus my\u00f6nnet\u00e4\u00e4n torrent-tiedostoille, jotka t\u00e4ytt\u00e4v\u00e4t ConfigView.label.seeding.firstPriority.following=seuraavista s\u00e4\u00e4nn\u00f6ist\u00e4: ConfigView.label.seeding.firstPriority.shareRatio=Jakosuhde on alle ConfigView.label.seeding.firstPriority.seedingMinutes=Aikaa kulunut siit\u00e4, kun lataus valmistui ja l\u00e4hett\u00e4minen alkoi ConfigView.label.seeding.firstPriority.DLMinutes=Aikaa kulunut latauksen aloittamisesta ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Lis\u00e4\u00e4m\u00e4ll\u00e4 teoreettisesti yhden t\u00e4yden kopion siirrosta tietty\u00e4 lataajam\u00e4\u00e4r\u00e4\u00e4 kohti\nv\u00e4henn\u00e4t niiden torrent-tiedostojen l\u00e4hetystarvetta, joilla on paljon lataajia.\nT\u00e4llaisten torrent-tiedostojen kohdalla tietoa liikkuu todenn\u00e4k\u00f6isesti jo aivan tarpeeksi.\nT\u00e4m\u00e4 asetus ei lis\u00e4\u00e4 miss\u00e4\u00e4n k\u00e4ytt\u00e4j\u00e4lle n\u00e4ytett\u00e4vien l\u00e4hteiden lukum\u00e4\u00e4r\u00e4\u00e4. ConfigView.label.seeding.numPeersAsFullCopy=Lis\u00e4\u00e4 teoreettisesti yksi t\u00e4ysi kopio kohti (0 = ei teoreettista lis\u00e4yst\u00e4) ConfigView.label.seeding.preferLargerSwarms.tooltip=T\u00e4st\u00e4 asetuksesta on hy\u00f6ty\u00e4 silloin, kun l\u00e4hetet\u00e4\u00e4n torrent-tiedostoja, joiden tiedon siirt\u00e4minen\nlataajille/lataajien kesken on hyvin hidasta. Jos puolestaan l\u00e4het\u00e4t torrent-tiedostoja, joilla on hyv\u00e4 saatavuus,\non parempi suosia niit\u00e4, joilla on v\u00e4hemm\u00e4n lataajia. ConfigView.label.seeding.preferLargerSwarms=Jos torrent-tiedostoilla on sama l\u00e4hetystarve, suosi sit\u00e4, jolla on enemm\u00e4n lataajia ConfigView.label.seeding.rankType.none.tooltip=J\u00e4rjestys pohjautuu torrent-tiedoston j\u00e4rjestysnumeroon (#-sarake Siirrot-ikkunassa). ConfigView.label.seeding.rankType.none=Ei mihink\u00e4\u00e4n ConfigView.label.seeding.rankType.peer.tooltip=Enemm\u00e4n lataajia, v\u00e4hemm\u00e4n l\u00e4hteit\u00e4 --> korkeampi prioriteetti\nT\u00e4m\u00e4 asetus pienent\u00e4\u00e4 tarvittavien aktiivisten torrenttien m\u00e4\u00e4r\u00e4\u00e4 l\u00e4hetysnopeuden maksimoimiseksi ConfigView.label.seeding.rankType.peer=Painotettu lataajien m\u00e4\u00e4r\u00e4 ConfigView.label.seeding.rankType.peerSeed.options=Ohitusasetukset ConfigView.label.seeding.rankType.peerSeed.tooltip=Korkeampi suhdeluku vastaa korkeampaa l\u00e4hetystarvetta. ConfigView.label.seeding.rankType.peerSeed=Lataajia/l\u00e4hde-suhdelukuun ConfigView.label.seeding.rankType.seed.fallback=Vaihda edelliseen s\u00e4\u00e4nt\u00f6\u00f6n, kun on\n(0 = \u00e4l\u00e4 vaihda koskaan) ConfigView.label.seeding.rankType.seed.options=Ohitusasetukset ConfigView.label.seeding.rankType.seed.tooltip=V\u00e4hemm\u00e4n l\u00e4hteit\u00e4 vastaa korkeampaa l\u00e4hetystarvetta. ConfigView.label.seeding.rankType.seed=L\u00e4hteiden lukum\u00e4\u00e4r\u00e4\u00e4n ConfigView.label.seeding.rankType.timedRotation.tooltip=Kaikkia jonossa olevia torrent-tiedostoja l\u00e4hetet\u00e4\u00e4n vuorotellen.\nL\u00e4hetysajan pituus m\u00e4\u00e4ritell\u00e4\u00e4n L\u00e4hett\u00e4minen-asetusryhm\u00e4n kohdassa V\u00e4himm\u00e4isl\u00e4hetysaika sekunneissa. ConfigView.label.seeding.rankType.timedRotation=Aikaan ConfigView.label.seeding.rankType.tooltip=Korkeimman l\u00e4hetystarpeen torrent-tiedostoja aloitetaan l\u00e4hett\u00e4\u00e4 automaattisesti.\nKun toinen torrent-tiedosto saavuttaa korkeamman l\u00e4hetystarpeen, edellisen l\u00e4hett\u00e4minen keskeytet\u00e4\u00e4n ja se asetetaan takaisin jonoon.\n\nAutomaattista l\u00e4hetyksen aloittamista voidaan soveltaa vain niihin torrent-tiedostohin, jotka ovat Jonossa-tilassa.\nT\u00e4ysin pys\u00e4ytettyj\u00e4 torrent-tiedostoja ei koskaan aloiteta l\u00e4hett\u00e4m\u00e4\u00e4n automaattisesti. ConfigView.label.seeding.rankType=Priorisoi valmistuneiden torrent-tiedostojen l\u00e4hett\u00e4minen perustuen: ConfigView.label.stopAfterMinutes=Pys\u00e4yt\u00e4 l\u00e4hett\u00e4minen, kun on kulunut valmistumisen j\u00e4lkeen ConfigView.label.switchpriority.tooltip=Alhainen prioriteetti v\u00e4hent\u00e4\u00e4 torrent-tiedostolle jaettua l\u00e4hetysnopeutta. ConfigView.pluginlist.info=Vuze tunnisti seuraavat lis\u00e4osat.\nHuomaa, ett\u00e4 kaikilla ei v\u00e4ltt\u00e4m\u00e4tt\u00e4 ole asetusmahdollisuuksia. ConfigView.pluginlist.noplugins=Lis\u00e4osia ei l\u00f6ytynyt. ConfigView.section.pluginslist=Listaa ConfigView.section.queue.seeding=L\u00e4hett\u00e4minen ConfigView.section.queue.seeding.autoStarting=Automaattinen aloitus ConfigView.section.queue.seeding.ignore=Ohituss\u00e4\u00e4nn\u00f6t ConfigView.section.queue.seeding.firstPriority=Ensisijaisuus ConfigView.section.queue.main=Perusasetukset ConfigView.section.queue=Siirtojonot ConfigView.section.torrents=Torrent-tiedostot ConfigView.text.all=kaikki ConfigView.text.hours=tuntia ConfigView.text.ignoreRule=Ohita s\u00e4\u00e4nt\u00f6 ConfigView.text.ignore=Ei k\u00e4yt\u00f6ss\u00e4 ConfigView.text.minutes=min ConfigView.text.neverIgnore=\u00c4l\u00e4 koskaan ohita ConfigView.text.any=jonkun DownloadManager.error.datamissing=Tiedostoja ei saatavilla MainWindow.menu.file.open.torrentforseeding=Torrent-tiedosto... (l\u00e4hett\u00e4mist\u00e4 varten) MainWindow.menu.language.refresh=&P\u00e4ivit\u00e4 ManagerItem.forced=Ohita s\u00e4\u00e4nn\u00f6t, ManagerItem.queued=Jonossa MySeedersView.header=Valmistuneet torrent-tiedostot TableColumn.header.availability.info=T\u00e4ysien kopioiden lukum\u00e4\u00e4r\u00e4. TableColumn.header.availability=Saatavuus TableColumn.header.category=Luokka MyTorrentsView.header=Keskener\u00e4iset torrent-tiedostot TableColumn.header.maxuploads=L\u00e4hetyspaikat MyTorrentsView.menu.category.delete=&Poista luokka MyTorrentsView.menu.forceStart=K\u00e4ynnist\u00e4 (&ohita s\u00e4\u00e4nn\u00f6t) MyTorrentsView.menu.queue=&K\u00e4ynnist\u00e4 (aseta jonoon) MyTorrentsView.menu.setCategory.add=&Lis\u00e4\u00e4 luokka... MyTorrentsView.menu.setCategory=Aseta &luokka TableColumn.header.savepath=Tallennushakemisto TableColumn.header.SeedingRank=L\u00e4hetystarve TableColumn.header.totalspeed.info=Yhdistettyin\u00e4 olevien k\u00e4ytt\u00e4jien siirtonopeus yhteens\u00e4. TableColumn.header.totalspeed=Nopeus yht. splash.initializePlugins=Alustetaan lis\u00e4osia StartStopRules.SPratioMet=L\u00e4h:Lat-suhdeluku OK StartStopRules.FP0Peers=Ensisijaisuus/0 lataajaa StartStopRules.0Peers=0 lataajaa StartStopRules.numSeedsMet=L\u00e4hteiden lkm OK StartStopRules.ratioMet=Lataajia/l\u00e4hde-suhde OK StartStopRules.shareRatioMet=Jakosuhde OK StartStopRules.waiting=Odotetaan StartStopRules.firstPriority=Ensisijainen ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Jaa hakemiston sis\u00e4lt\u00f6 (rekursiivisesti) DownloadManager.error.unabletostartserver=Yhteyden muodostaminen ei onnistu - tarkasta sis\u00e4\u00e4ntulevan TCP-liikenteen portti/palomuurin asetukset koskien Vuzea GeneralView.label.creationdate=Luontiaika: ConfigView.section.tracker.announcescrapepercentage=Pikap\u00e4ivitysten suhde %:ina p\u00e4ivityksist\u00e4,\nesim. 200 = 2:1 (0 = k\u00e4ytt\u00e4j\u00e4 p\u00e4\u00e4tt\u00e4\u00e4) ManagerItem.stopping=Pys\u00e4ytet\u00e4\u00e4n ConfigView.section.tracker.announcecacheperiod=P\u00e4ivitysten v\u00e4limuistiaika (ms) ConfigView.section.tracker.scrapecacheperiod=Pikap\u00e4ivitysten v\u00e4limuistiaika (ms) ConfigView.section.tracker.scrapeandcache=Pikap\u00e4ivitykset ja v\u00e4limuisti ConfigView.section.tracker.announcecacheminpeers=K\u00e4ytt\u00e4jien m\u00e4\u00e4r\u00e4, jonka j\u00e4lkeen\np\u00e4ivitysten v\u00e4limuisti k\u00e4yt\u00f6ss\u00e4 MyTrackerView.scrapes=Pikap\u00e4ivitykset fileDownloadWindow.retry=Uudestaan MyTrackerView.bytesin=Sis\u00e4\u00e4n MyTrackerView.bytesinave=Keskim. sis\u00e4\u00e4n MyTrackerView.bytesout=Ulos MyTrackerView.bytesoutave=Keskim. ulos ConfigView.section.file.max_open_files=Lukua/kirjoitusta varten avattavien tiedostojen\nenimm\u00e4islukum\u00e4\u00e4r\u00e4 (0 = rajoittamaton) ConfigView.section.file.max_open_files.tooltip=Tiedostojen lukum\u00e4\u00e4r\u00e4\u00e4 kannattaa rajoittaa siin\u00e4 tapauksessa, jos torrent-tiedosto k\u00e4sitt\u00e4\u00e4\nsatoja tai jopa tuhansia tiedostoja ja k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4n tiedostonk\u00e4sittelyrajat tulevat t\u00e4ll\u00f6in vastaan. ConfigView.section.proxy=V\u00e4lityspalvelin ConfigView.section.proxy.enable_proxy=K\u00e4yt\u00e4 v\u00e4lityspalvelinta (vaatii uudelleenk\u00e4ynnistyksen) ConfigView.section.proxy.host=Osoite ConfigView.section.proxy.port=Portti ConfigView.section.proxy.username=K\u00e4ytt\u00e4j\u00e4tunnus ConfigView.section.proxy.password=Salasana ConfigView.section.proxy.enable_socks=V\u00e4lityspalvelin on SOCKS-yhteensopiva wizard.createtorrent.extrahashes=Lis\u00e4\u00e4 tiivisteet muille verkoille (esim. Gnutella2 ja ed2k) GeneralView.label.connected=yhdistetty GeneralView.label.in_swarm=kaikkiaan ManagerItem.initializing=Aloitetaan AlertMessageBox.error=Virhe AlertMessageBox.warning=Varoitus AlertMessageBox.comment=Info AlertMessageBox.information=Info AlertMessageBox.unread=Lukemattomia viestej\u00e4 - klikkaa t\u00e4st\u00e4 SharedPortServer.alert.selectorfailed=Sis\u00e4\u00e4ntulevan tiedon vastaanottamisessa ongelmia.\nTarkasta palomuurin asetukset Vuzen osalta. Tracker.alert.listenfail=Portti %1 ei ole k\u00e4ytett\u00e4viss\u00e4.\nTarkasta, ett\u00e4 muut sovellukset eiv\u00e4t k\u00e4yt\u00e4 ko. porttia ja varmista my\u00f6s, ettei sinulla ole useampaa Vuzea k\u00e4ynniss\u00e4. DiskManager.alert.movefileexists=Ongelma tiedostojen siirt\u00e4misess\u00e4.\nTiedosto %1 on jo olemassa kohdehakemistossa. DiskManager.alert.movefilefails=Ongelma tiedostojen siirt\u00e4misess\u00e4.\nTiedoston %1 siirto ep\u00e4onnistui, %2 DiskManager.alert.movefilerecoveryfails=Ongelma tietojen palauttamisessa.\nTiedoston %1 palautus ep\u00e4onnistui, %2 ConfigView.section.tracker.logenable=Tallenna tilastotiedot (tracker.log-tiedosto) SpeedView.stats.title=Tilastot SpeedView.stats.total=Yhteens\u00e4 SpeedView.stats.session=T\u00e4m\u00e4 sessio SpeedView.stats.session.tooltip=Yhteens\u00e4 (yhteysk\u00e4yt\u00e4nt\u00f6) SpeedView.stats.downloaded=Ladattu (yhteysk\u00e4yt\u00e4nt\u00f6) SpeedView.stats.uploaded=L\u00e4hetetty (yhteysk\u00e4yt\u00e4nt\u00f6) SpeedView.stats.ratio=Jakosuhde SpeedView.stats.uptime=K\u00e4ytt\u00f6aika SpeedView.stats.now=Parhaillaan SpeedView.stats.now.tooltip=Yhteens\u00e4 (yhteysk\u00e4yt\u00e4nt\u00f6) AutoMigration.useralert=Vuzen asetustiedostojen ja hakemistojen\nautomaattisen kopioinnin tulokset:\n\n%1\nEp\u00e4onnistuneet ('FAILED') kopioinnit t\u00e4ytyy tehd\u00e4 manuaalisesti.\nMuista my\u00f6s p\u00e4ivitt\u00e4\u00e4 tallennuspolut asetuksiin! # # > 2.0.8.0 # OpenTorrentWindow.title=Avaa torrent-tiedosto OpenTorrentWindow.message=Kokeellinen OpenTorrentWindow.addFiles=Lis\u00e4\u00e4 &tiedostoja OpenTorrentWindow.dataLocation=Tallennushakemisto: OpenTorrentWindow.startMode=Aloitustila OpenTorrentWindow.startMode.queued=K\u00e4ynnist\u00e4 (aseta jonoon) OpenTorrentWindow.startMode.stopped=Pys\u00e4ytetty OpenTorrentWindow.startMode.forceStarted=K\u00e4ynnist\u00e4 (ohita s\u00e4\u00e4nn\u00f6t) OpenTorrentWindow.addPosition=Sijoitus jonossa OpenTorrentWindow.addPosition.first=Ensimm\u00e4inen OpenTorrentWindow.addPosition.last=Viimeinen TableColumn.header.remaining.info=J\u00e4ljell\u00e4 oleva ladattava m\u00e4\u00e4r\u00e4. TableColumn.header.remaining=J\u00e4ljell\u00e4 ConfigView.section.tracker.enablecompact=K\u00e4yt\u00e4 tiivistetty\u00e4 p\u00e4ivitysprotokollaa (IP- ja porttitiedot l\u00e4hetet\u00e4\u00e4n 6 bitin sarjoina string-arvon sijaan) ConfigView.section.tracker.enablekey=K\u00e4yt\u00e4 turva-avaimen siirtoa seurantapalvelimelle (parantaa turvallisuutta) ConfigView.section.file.perf=Suorituskyky ConfigView.section.file.perf.explain=Varoitus - n\u00e4iden asetusten harkitsematon muuttaminen voi vaikuttaa alentavasti latausnopeuksiin.\nJotta muutokset tulisivat voimaan, Vuze t\u00e4ytyy k\u00e4ynnist\u00e4\u00e4 uudelleen.\nJos muistin k\u00e4ytt\u00f6 nousee huomattavasti, voit kokeilla torrent-kohtaisten yhteyksien enimm\u00e4ism\u00e4\u00e4r\u00e4n pienent\u00e4mist\u00e4 Siirrot-asetuksissa. ConfigView.section.file.max_open_files.explain=Liian suuren tiedostom\u00e4\u00e4r\u00e4n k\u00e4sittely voi johtaa k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4ongelmiin. T\u00e4m\u00e4 asetus rajoittaa yht\u00e4aikaisesti k\u00e4sitelt\u00e4vien tiedostojen m\u00e4\u00e4r\u00e4\u00e4. popup.error.hide=Piilota popup.error.details=Lis\u00e4\u00e4... ConfigView.section.style.colorOverrides=Tarkemmat v\u00e4riasetukset ConfigView.section.style.colorOverride.progressBar=Edistymispalkit ConfigView.section.style.colorOverride.error=Virheet MainWindow.status.tooOld=on vanha. P\u00e4ivit\u00e4. ConfigView.section.style.colorOverride.warning=Varoitukset ConfigView.section.style.colorOverride.altRow=Taulukoiden rivit (joka toinen) ConfigView.section.file.save.peers.enable=Tallenna tiedot k\u00e4ytt\u00e4jist\u00e4 ConfigView.section.file.save.peers.max=K\u00e4ytt\u00e4jien enimm\u00e4ism\u00e4\u00e4r\u00e4 (0 = rajoittamaton) ConfigView.section.file.save.peers.pertorrent=/torrent-tiedosto ConfigView.label.max_peers_per_torrent=Yhteyksien oletusenimm\u00e4ism\u00e4\u00e4r\u00e4/torrent-tiedosto (0 = rajoittamaton) ConfigView.label.max_peers_total=Yhteyksien enimm\u00e4ism\u00e4\u00e4r\u00e4 kaikkiaan (0 = rajoittamaton) ConfigView.section.style.colorOverrides.reset=Oletusv\u00e4ri ConfigView.section.language.info=Jos k\u00e4yt\u00f6ss\u00e4, Vuze tarkastaa k\u00e4ynnistyksen yhteydess\u00e4 saatavilla olevat p\u00e4ivitykset. ConfigView.section.language.enableUpdate=K\u00e4yt\u00e4 Web-p\u00e4ivityst\u00e4 ConfigView.section.language.UpdateURL=Tarkastusosoite ConfigView.section.language.UpdateNow=P\u00e4ivit\u00e4 nyt Button.revert=Palaa MyTorrentsView.menu.changeDirectory=Vaihda tallennushakemistoa GenericText.column=-sarake MyTorrentsView.menu.thisColumn.remove=Poista sarake n\u00e4kyvist\u00e4 MyTorrentsView.menu.thisColumn.toClipboard=Kopioi teksti leikep\u00f6yd\u00e4lle MyTorrentsView.menu.thisColumn.autoTooltip=N\u00e4yt\u00e4 aina ty\u00f6kaluvihje MyTorrentsView.menu.tracker=Seurantapalvelin/Torrent ConfigView.download.abbreviated=Lad: ConfigView.upload.abbreviated=L\u00e4h: ConfigView.complete.abbreviated=Valm: TableColumn.header.secondsseeding=L\u00e4h.aika TableColumn.header.secondsseeding.info=Torrent-tiedoston l\u00e4hetysaika sen lataukseen asettamisesta l\u00e4htien. TableColumn.header.secondsdownloading=Lat.aika TableColumn.header.secondsdownloading.info=Torrent-tiedoston latausaika sen lataukseen asettamisesta l\u00e4htien. ConfigView.section.tracker.udpversion=UDP-protokollan k\u00e4ytett\u00e4v\u00e4 versio (1 tai 2) window.updateswt.title=SWT-ohjelmakirjasto vanhentunut! window.updateswt.text=SWT-versiosi on vanhentunut!\nSWT on vuzen k\u00e4ytt\u00e4m\u00e4 graafinen ohjelmakirjasto, ja t\u00e4m\u00e4nhetkinen SWT-versiosi on liian vanha Vuzen k\u00e4ynnist\u00e4miseen. Valitse OK p\u00e4ivitt\u00e4\u00e4ksesi SWT-ohjelmakirjasto uusimpaan versioon. window.updateswt.status=Tila window.updateswt.failed=P\u00e4ivitys ep\u00e4onnistui, valitse OK k\u00e4ynnist\u00e4\u00e4ksesi uudelleen. window.updateswt.status.downloading.updater=Ladataan p\u00e4ivitysmoduulia window.updateswt.status.finding=Etsit\u00e4\u00e4n viimeisint\u00e4 SWT-versiota window.updateswt.status.downloading=Ladataan viimeisint\u00e4 SWT-versiota window.updateswt.status.done=K\u00e4ynnistet\u00e4\u00e4n uudelleen window.updateswt.cancel=Peruuta swt.updater.downloader.downloading=Ladataan SWT:t\u00e4 kohteesta swt.updater.urlsgetter.downloading=Ladataan peilaavien palvelimien listaa kohteesta swt.updater.urlsgetter.platform=SWT k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4alustalle: window.updateswt.ignore=Ohita ConfigView.section.style.useFancyTabs=K\u00e4yt\u00e4 ulkoasultaan tyyliteltyj\u00e4 v\u00e4lilehti\u00e4 splash.initializeGM=Alustetaan torrent-tiedostojen k\u00e4sittely\u00e4 splash.loadingTorrents=Ladataan torrent-tiedostoja MyTorrentsView.menu.thisColumn.sort=&Lajittele torrent-tiedostot Scrape.status.ok=Pikap\u00e4ivitys OK. Scrape.status.error=Pikap\u00e4ivitysvirhe: Scrape.status.error.badURL=P\u00e4ivitysosoite ei tue pikap\u00e4ivitysm\u00e4\u00e4rittelyj\u00e4. Scrape.status.error.nohash=Vastaus ei sis\u00e4lt\u00e4nyt tiivistett\u00e4. Scrape.status.error.invalid=Virheellinen vastaus. Scrape.status.nextScrapeAt=Seuraava pikap\u00e4ivitys %1 Scrape.status.scraping=Suoritetaan pikap\u00e4ivityst\u00e4... Scrape.status.initializing=Odotetaan pikap\u00e4ivityst\u00e4 Scrape.status.scraping.queued=Pikap\u00e4ivitys jonossa... ConfigView.label.minSpeedForActiveSeeding=\u00c4l\u00e4 laske valmistunutta torrent-tiedostoa aktiiviseksi, jos l\u00e4hetysnopeus on alle ConfigView.section.stats.exportpeers=Tallenna tarkat tiedot k\u00e4ytt\u00e4jist\u00e4 MainWindow.menu.view.irc.moved=IRC-laajennus on nyt saatavilla lis\u00e4osana, katso lis\u00e4tietoja osoitteesta http://azureus.sourceforge.net/plugin_list.php. MyTrackerView.webui.contextmenu.copyurl=Kopioi torrent-tiedoston URL-osoite leikep\u00f6yd\u00e4lle ConfigView.section.file.torrent.ignorefiles=Tiedostot, jotka ohitetaan luotaessa/poistettaessa tiedostoja\nesim. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ohitetaan tiedosto ConfigView.section.style.useUnitsRateBits=K\u00e4yt\u00e4 bittej\u00e4 tavujen sijasta tavupohjaisissa nopeusarvoissa (esim. KiB/s -> Kibit/s) ConfigView.section.interface.resetassoc=Palauta tiedostoassosiaatio (.torrent) Vuzelle ConfigView.section.interface.resetassocbutton=Palauta ConfigView.section.interface.checkassoc=Tarkasta assosiaatio k\u00e4ynnistett\u00e4ess\u00e4 dialog.associations.title=Tiedostoassosiaation tarkastus Button.yes=&Kyll\u00e4 Button.no=&Ei ConfigView.label.seeding.autoStart0Peers=K\u00e4ynnist\u00e4 valmistuneet torrent-tiedostot, joilla ei ole yht\u00e4\u00e4n lataajaa ConfigView.label.seeding.autoStart0Peers.tooltip=K\u00e4yt\u00e4 t\u00e4t\u00e4, jos haluat, ett\u00e4 seurantapalvelin tallentaa aina tiedot l\u00e4hteist\u00e4. dialog.associations.prompt=Vuzea ei ole asetettu oletussovellukseksi BitTorrent-tiedostoille.\nHaluatko assosioida .torrent-tiedostot Vuzelle? dialog.associations.askagain=Tarkasta k\u00e4ynnistett\u00e4ess\u00e4 ConfigView.section.plugins.update=Lis\u00e4osien p\u00e4ivitys Plugin.pluginupdate.enablecheck=Tarkasta, onko k\u00e4yt\u00f6ss\u00e4 oleviin lis\u00e4osiin saatavilla p\u00e4ivityksi\u00e4 plugins.basicview.status=Tila: plugins.basicview.activity=Toiminta: plugins.basicview.progress=Edistyminen: plugins.basicview.log=Loki: ConfigView.label.maxdownloadspeed=kB/s, enimm\u00e4islatausnopeus (kaikki torrent-tiedostot, 0 = rajoittamaton) splash.loadingTorrent=Ladataan torrent-tiedostoa splash.of=/ ConfigView.section.plugins.irc=IRC-yhteys UpdateWindow.title=Vuzen p\u00e4ivitystoimenpiteet UpdateWindow.header=Seuraavat osat vaativat p\u00e4ivitt\u00e4mist\u00e4: UpdateWindow.columns.install=Asenna UpdateWindow.columns.name=Nimi UpdateWindow.columns.version=Versio UpdateWindow.columns.size=Koko UpdateWindow.cancel=Peruuta UpdateWindow.quit=Lopeta UpdateWindow.close=Sulje UpdateWindow.ok=P\u00e4ivit\u00e4 UpdateWindow.restart=K\u00e4ynnist\u00e4 Vuze uudelleen UpdateWindow.status.downloading=Ladataan UpdateWindow.status.done=Valmis UpdateWindow.status.failed=P\u00e4ivitys ep\u00e4onnistui UpdateWindow.status.restartNeeded=P\u00e4ivitt\u00e4minen vaatii Vuzen uudelleenk\u00e4ynnistyksen! ConfigView.pluginlist.broken=Ei kunnossa ConfigView.pluginlist.whereToPut=Aseta k\u00e4ytt\u00e4j\u00e4kohtaiset lis\u00e4osat omiin hakemistoihinsa seuraavan p\u00e4\u00e4hakemiston alle: ConfigView.pluginlist.whereToPutOr=Aseta kaikkien tietokoneen k\u00e4ytt\u00e4jien kesken jaetut lis\u00e4osat omiin hakemistoihinsa seuraavan p\u00e4\u00e4hakemiston alle: MainWindow.statusText.checking=Tarkastetaan p\u00e4ivitykset... TableColumn.header.OnlyCDing4=Tod. l\u00e4h.aika TableColumn.header.OnlyCDing4.info=Torrent-tiedoston l\u00e4hetysaika sen latauksen valmistumisesta l\u00e4htien. ConfigView.section.style.alternateTablePainting=S\u00e4vyt\u00e4 graafiset taulukoiden sarakkeet vaihtoehtoisella tavalla (saattaa vaatia uudelleenk\u00e4ynnistyksen) UpdateWindow.status.restartMaybeNeeded=P\u00e4ivitys vaatii ehk\u00e4 uud.k\u00e4ynnistyksen. ConfigView.pluginlist.shared=jaettu PeersView.host=Verkko-osoite PeersView.host.info=K\u00e4ytt\u00e4j\u00e4n symbolinen verkko-osoite, jos saatavilla. MainWindow.menu.help.whatsnew=Mit\u00e4 uutta t\u00e4ss\u00e4 versiossa? ConfigView.label.checkonstart=Tarkasta saatavilla olevat p\u00e4ivitykset k\u00e4ynnistett\u00e4ess\u00e4 ConfigView.label.periodiccheck=Tarkasta saatavilla olevat p\u00e4ivitykset s\u00e4\u00e4nn\u00f6llisesti uudestaan ConfigView.label.opendialog=K\u00e4ynnist\u00e4 P\u00e4ivitysavustaja automaattisesti, jos p\u00e4ivitys on saatavilla MainWindow.updateavail=(P\u00e4ivitys saatavilla) MainWindow.status.unofficialversion=Vuze beetaversio MainWindow.status.latestversionunchecked=Uusimman version tarkastus ei k\u00e4yt\u00f6ss\u00e4 GeneralView.label.updatein.stopped=Pys\u00e4ytetty StartStopRules.menu.viewDebug=Katso virheenm\u00e4\u00e4ritystiedot ConfigView.section.style.doNotUseGB=\u00c4l\u00e4 k\u00e4yt\u00e4 yksik\u00f6iss\u00e4 gigatavuja ConfigView.section.style.doNotUseGB.tooltip=Vuze jatkaa megatavujen k\u00e4ytt\u00e4mist\u00e4 yksikk\u00f6n\u00e4,\nkun luku ylitt\u00e4\u00e4 1024 Mt:a (yhden gigatavun). MainWindow.menu.help.plugins=Lis\u00e4osat ConfigView.section.plugins.TrackerWeb=Seurantapalvelimen sivu ConfigView.section.tracker.enablecategories=N\u00e4yt\u00e4 torrent-tiedostot omissa luokissaan health.explain.share=Torrent-tiedosto on joko asetettu seurantaan omalle seurantapalvelimelle tai julkistettu. ConfigView.section.tracker.createcert=Luo itseallekirjoitettu varmenne ConfigView.section.tracker.createbutton=Luo... security.certcreate.title=Itseallekirjoitettu varmenne security.certcreate.intro=T\u00e4ll\u00e4 toiminnolla voit luoda itseallekirjoitetun varmenteen. security.certcreate.alias=Nimi security.certcreate.strength=Vahvuus security.certcreate.firstlastname=Etu- ja sukunimi security.certcreate.orgunit=Organisaatioyksikk\u00f6 security.certcreate.org=Organisaatio security.certcreate.city=Kaupunki security.certcreate.state=Maakunta security.certcreate.country=Kaksikirjaiminen maakoodi security.certcreate.ok=Luo security.certcreate.cancel=Peruuta security.certcreate.createok=Varmenne luotiin onnistuneesti. security.certcreate.createfail=Varmenteen luonti ep\u00e4onnistui. ConfigView.section.plugins.webui=Swing-et\u00e4k\u00e4ytt\u00f6liittym\u00e4 ConfigView.section.plugins.xml_http_if=XML/HTTP-et\u00e4k\u00e4ytt\u00f6liittym\u00e4 webui.passwordenable=K\u00e4yt\u00e4 salasanasuojausta webui.user=K\u00e4ytt\u00e4j\u00e4tunnus webui.password=Salasana webui.port=Portti (*) webui.protocol=Protokolla (*) webui.homepage=Kotisivu (*) webui.rootdir=P\u00e4\u00e4hakemisto (*) webui.rootres=P\u00e4\u00e4resurssi (*) webui.mode=Hallintatila (*) webui.mode.info=Hallintatila voi olla\n\t"full"\t= k\u00e4ytt\u00e4j\u00e4 pystyy hallitsemaan kaikkia et\u00e4k\u00e4ytt\u00f6liittym\u00e4n toimintoja (oletusasetus)\n\t"view"\t= k\u00e4ytt\u00e4j\u00e4 pystyy vaihtamaan vain et\u00e4k\u00e4ytt\u00f6liittym\u00e4n p\u00e4ivitysnopeutta, muilta osin pelkk\u00e4 katseluoikeus webui.access=P\u00e4\u00e4syoikeus (*) webui.access.info=P\u00e4\u00e4syoikeus voi olla\n\t"local"\t= yhteys sallitaan vain paikalliselta koneelta, eli silt\u00e4 koneelta, jolla Vuze on k\u00e4ynniss\u00e4\n\t"all"\t= rajoittamaton p\u00e4\u00e4syoikeus, kaikki yhteydet sallitaan (oletusasetus)\n\tIP\t= esim. 192.168.0.2 (yhteys sallitaan yksitt\u00e4isest\u00e4 IP-osoitteesta)\n\tIP1-IP2\t= esim. 192.168.0.1-192.168.0.255 (yhteydet sallitaan tietylt\u00e4 IP-osoitev\u00e4lilt\u00e4) GeneralView.label.maxdownloadspeed=Enimm\u00e4islatausnopeus Security.keystore.corrupt=Keystore-tiedostoa '%1' ei voitu ladata; poista se ja luo/hae varmenteet uudelleen. Security.keystore.empty=Keystore-tiedosto on tyhj\u00e4; luo joko itseallekirjoitettu varmenne (katso Ty\u00f6kalut | Asetukset | Suojaus) tai hae olemassa oleva varmenne tiedostolle '%1'. webui.restart.info=Jos asetus on merkitty t\u00e4hdell\u00e4 (*), t\u00e4ytyy Vuze k\u00e4ynnist\u00e4\u00e4 uudelleen, jotta muutokset kyseiseen asetukseen tulisivat voimaan. GeneralView.label.maxdownloadspeed.tooltip=- enimm\u00e4islatausnopeus (0 = rajoittamaton) ConfigView.section.UPnP=UPnP-m\u00e4\u00e4ritys upnp.enable=K\u00e4yt\u00e4 UPnP:t\u00e4 upnp.info=Universal Plug and Play (UPnP) mahdollistaa automaattisen porttien m\u00e4\u00e4ritt\u00e4misen niihin verkkolaitteisiin, joissa UPnP on k\u00e4ytett\u00e4viss\u00e4. upnp.mapping.dataport=Sis\u00e4\u00e4ntulevan TCP-liikenteen portti upnp.mapping.tcptrackerport=Seurantapalvelimen TCP-portti upnp.mapping.udptrackerport=Seurantapalvelimen UDP-portti upnp.alert.differenthost=UPnP: M\u00e4\u00e4rityksen '%1' on varannut '%2' - valitse jokin toinen portti upnp.alert.mappingok=UPnP: M\u00e4\u00e4ritys '%1' muodostettu upnp.alert.mappingfailed=UPnP: M\u00e4\u00e4ritys '%1' ep\u00e4onnistui upnp.alertsuccess=Ilmoita onnistuneista m\u00e4\u00e4rityksist\u00e4 upnp.alert.lostdevice=UPnP: Yhteys palveluun '%1' UPnP-laitteessa '%2' menetettiin upnp.grabports=M\u00e4\u00e4rit\u00e4 portit, vaikka ne olisivat toisen tietokoneen k\u00e4yt\u00f6ss\u00e4 upnp.refresh.label=P\u00e4ivit\u00e4 m\u00e4\u00e4ritykset upnp.refresh.button=P\u00e4ivit\u00e4 upnp.alert.mappinggrabbed=UPnP: M\u00e4\u00e4ritys '%1' muodostettu - haettu kohteelta '%2' upnp.mapping.tcpssltrackerport=Seurantapalvelimen TCP-portti (SSL) upnp.alertothermappings=Ilmoita porteista, jotka ovat toisen tietokoneen k\u00e4yt\u00f6ss\u00e4 upnp.alertdeviceproblems=Ilmoita UPnP-laitteen ongelmatilanteista upnp.trace_to_log=Tulosta kaikki virheenm\u00e4\u00e4ritystiedot lokiin upnp.wiki_link=Katso lis\u00e4tietoja t\u00e4st\u00e4 upnp.refresh_mappings_on_bad_nat=P\u00e4ivit\u00e4 porttim\u00e4\u00e4ritykset automaattisesti, jos NAT status on "firewalled" ConfigView.pluginlist.coreplugins=Seuraavat sis\u00e4\u00e4nrakennetut lis\u00e4osat ovat k\u00e4yt\u00f6ss\u00e4: Peers.column.DLedFromOthers=Muilta Peers.column.DLedFromOthers.info=K\u00e4ytt\u00e4j\u00e4n muilta lataama tietom\u00e4\u00e4r\u00e4 t\u00e4m\u00e4n yhteyden ollessa voimassa. Peers.column.UpDownRatio=L\u00e4h:Lad Peers.column.UpDownRatio.info=K\u00e4ytt\u00e4j\u00e4n l\u00e4hetys-lataussuhde. Peers.column.UpRatio=L\u00e4h.suhteet Peers.column.UpRatio.info=Oma l\u00e4hetysm\u00e4\u00e4r\u00e4 suhteessa muiden l\u00e4hetysm\u00e4\u00e4r\u00e4\u00e4n ko. k\u00e4ytt\u00e4j\u00e4lle. upnp.releasemappings=Vapauta porttim\u00e4\u00e4ritykset lopetettaessa webui.upnpenable=K\u00e4yt\u00e4 UPnP:t\u00e4 t\u00e4lle portille (*) ConfigView.section.file.friendly.hashchecking=K\u00e4yt\u00e4 resurssiyst\u00e4v\u00e4llist\u00e4 tapaa osien tarkastamiseen ConfigView.section.file.friendly.hashchecking.tooltip=Osien tiivisteet lasketaan ja tarkastetaan hieman hitaammin kuin normaalissa tilassa,\nmutta v\u00e4hemmill\u00e4 resursseilla (suoritink\u00e4ytt\u00f6/muistin k\u00e4ytt\u00f6). ConfigView.section.tracker.seedretention=S\u00e4ilytett\u00e4vien l\u00e4hteiden enimm\u00e4ism\u00e4\u00e4r\u00e4/torrent-tiedosto\n(0 = rajoittamaton) ConfigView.section.tracker.seedretention.info=Huom.: Muista l\u00e4hteist\u00e4 ei saada l\u00e4hetystilastoja. ConfigView.section.tracker.port=K\u00e4yt\u00e4 HTTP-porttia ConfigView.section.tracker.sslport=K\u00e4yt\u00e4 HTTPS-porttia ConfigView.section.tracker.publicenable.info=Sallii muiden k\u00e4ytt\u00e4\u00e4 seurantapalvelintasi ilman,\nett\u00e4 sin\u00e4 itse asetat torrent-tiedostoja seurantaan/julkaiset niit\u00e4. Button.clear=Tyhjenn\u00e4 MainWindow.IPs.tooltip=IP-suotimien viimeisin p\u00e4ivitys: %1\nIP-suodinosoitealueiden m\u00e4\u00e4r\u00e4\n-> k\u00e4ytt\u00e4j\u00e4t t\u00e4m\u00e4n session aikana, jotka on\n- estetty IP-suotimien toimesta\n- estetty muutoin\n- ovat l\u00e4hett\u00e4neet korruptoitunutta tietoa.\nTuplaklikkaa n\u00e4hd\u00e4ksesi tarkemmat tiedot. ConfigView.section.ipfilter.list.banned=- yhteydenotto estetty ConfigView.section.ipfilter.list.baddata=l\u00e4hetti korruptoitunutta tietoa, esiintym\u00e4t: Button.reset=Tyhjenn\u00e4 ConfigView.section.ipfilter.bannedinfo=Korruptoitunutta tietoa l\u00e4hett\u00e4neet - estetty tietyn rajan ylitytty\u00e4. ConfigView.section.ipfilter.blockedinfo=IP-suotimien toimesta estetyt yhteydet. download.removerules.name=Poistamiss\u00e4\u00e4nn\u00f6t download.removerules.unauthorised.info=Luvattomat torrent-tiedostot ovat sellaisia, jotka palauttavat virheilmoituksena joko tekstin "not authoris(z)ed" tai "unauthoris(z)ed" seurantapalvelimen tilaa tiedusteltaessa. download.removerules.unauthorised=Poista automaattisesti luvattomat torrent-tiedostot download.removerules.unauthorised.seedingonly=\tVain jos torrent-tiedostoa l\u00e4hetet\u00e4\u00e4n (lataus jo valmistunut) download.removerules.removed.ok=Torrent-tiedoston '%1' poistaminen onnistui. T\u00e4m\u00e4 tapahtui poistamiss\u00e4\u00e4nt\u00f6jen johdosta. download.removerules.updatetorrents=Poista automaattisesti p\u00e4ivitt\u00e4miseen k\u00e4ytetyt torrent-tiedostot, jos l\u00e4hett\u00e4miselle ei en\u00e4\u00e4 ole tarvetta ConfigView.label.defaultstarttorrentsstopped=Aseta avatut torrent-tiedostot oletuksena pys\u00e4ytetty-tilaan ConfigView.section.server.enableudp=K\u00e4yt\u00e4 UDP-protokollaa seurantapalvelinyhteyksiin upnp.mapping.dataportudp=Sis\u00e4\u00e4ntulevan UDP-liikenteen portti ConfigView.section.file.decoder.showlax=N\u00e4yt\u00e4 ep\u00e4todenn\u00e4k\u00f6iset koodausvaihtoehdot ConfigView.section.file.decoder.showall=Luettele kaikki mahdolliset koodausvaihtoehdot MainWindow.status.updowndetails.tooltip=Lataus- ja l\u00e4hetysnopeudet\n - Vaihda rajoituksia klikkaamalla hiiren kakkospainikkeella ja valitsemalla haluamasi arvot\n - Tuplaklikkaus avaa tilastot TrackerClient.announce.warningmessage=Torrent-tiedoston '%1' seurantapalvelin palautti varoituksen '%2'. ConfigView.section.tracker.natcheckenable=Tarkasta k\u00e4ytt\u00e4j\u00e4n sis\u00e4\u00e4ntulevan TCP-liikenteen portin toimivuus ja ilmoita ongelmista ConfigView.section.tracker.publishenabledetails=Julkaise kaikki tarkat tiedot torrent-tiedostoista ConfigView.section.tracker.publishenablepeerdetails=Julkaise tarkat tiedot k\u00e4ytt\u00e4jist\u00e4 MyTrackerView.badnat=NAT-ongelmat MyTrackerView.badnat.info=K\u00e4ytt\u00e4j\u00e4t, jotka eiv\u00e4t l\u00e4p\u00e4isseet NAT-testi\u00e4 (jos testaus k\u00e4yt\u00f6ss\u00e4). ConfigView.section.tracker.natchecktimeout=Tarkastuksen aikakatkaisu (s) ConfigView.section.file.perf.cache.enable=K\u00e4yt\u00e4 v\u00e4limuistia ConfigView.section.file.perf.cache.size=V\u00e4limuistin koko (%1) #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=&Siirrot MainWindow.menu.transfers.startalltransfers=&K\u00e4ynnist\u00e4 kaikki MainWindow.menu.transfers.stopalltransfers=&Pys\u00e4yt\u00e4 kaikki MainWindow.menu.transfers.pausetransfers=K&eskeyt\u00e4 MainWindow.menu.transfers.resumetransfers=&Jatka keskeytettyj\u00e4 ConfigView.label.experimental.osx.kernel.panic.fix=Korjaa kaksiytimisten OSX-koneiden kernel panic -ongelmat (vaatii uud.k\u00e4yn.) SystemTray.menu.pausetransfers=K&eskeyt\u00e4 siirrot SystemTray.menu.resumetransfers=Jatka keskeytettyj\u00e4 siirtoja ConfigView.section.file.truncate.too.large=Pienenn\u00e4 olemassa olevat liian isot tiedostot oikeaan kokoonsa ConfigView.section.file.perf.cache.trace=J\u00e4ljit\u00e4 v\u00e4limuistioperaatiot virheenm\u00e4\u00e4rityst\u00e4 varten ConfigView.section.interface.enabletray=N\u00e4yt\u00e4 Vuzen kuvake ilmoitusalueella (vaatii uudelleenk\u00e4ynnistyksen) PeerManager.status.error=Virhe Stats.title.full=Tilastot TransferStatsView.title.full=Siirrot ja k\u00e4ytt\u00f6aika CacheView.title.full=V\u00e4limuisti CacheView.general.size=Koko yhteens\u00e4 CacheView.general.inUse=K\u00e4yt\u00f6ss\u00e4 CacheView.general.title=Tila CacheView.reads.title=Siirr\u00e4nt\u00e4luvut CacheView.reads.fromFile=Tiedostosta CacheView.reads.fromCache=V\u00e4limuistista CacheView.reads.hits=k\u00e4ytt\u00f6 CacheView.writes.title=Siirr\u00e4nt\u00e4kirjoitukset CacheView.writes.toCache=V\u00e4limuistiin CacheView.writes.toFile=Tiedostoon CacheView.writes.hits=s\u00e4\u00e4stetty CacheView.speeds.title=Luku- ja kirjoitusnopeudet CacheView.speeds.reads=Luvut CacheView.speeds.writes=Kirjoitukset CacheView.speeds.fromCache=V\u00e4limuistista/\nv\u00e4limuistiin CacheView.speeds.fromFile=Tiedostosta/\ntiedostoon CacheView.reads.#=Kertaa CacheView.reads.amount=M\u00e4\u00e4r\u00e4 CacheView.reads.avgsize=Keskim\u00e4\u00e4r\u00e4inen koko openUrl.referrer=Viittaavan sivun osoite: openUrl.referrer.info=Tarvitaan vain, jos sivusto vaatii t\u00e4t\u00e4. ConfigView.label.maxuploadspeedseeding=Vaihtoehtoinen nopeus ainoastaan l\u00e4hetett\u00e4ess\u00e4 ConfigView.label.transfer.ignorepeerports=Est\u00e4 k\u00e4ytt\u00e4j\u00e4, jos sis\u00e4\u00e4ntulevan TCP-liikenteen porttina on (erota ;-merkill\u00e4, esim. 0;25) ConfigView.section.proxy.enable_socks.peer=K\u00e4yt\u00e4 v\u00e4lityspalvelinta (yhteydet ulosp\u00e4in, vaatii uudelleenk\u00e4ynnistyksen) ConfigView.section.proxy.peer.informtracker=Ilmoita seurantapalvelimelle, ett\u00e4 sis\u00e4\u00e4ntulevia yhteyksi\u00e4 ei voida ottaa vastaan ConfigView.section.proxy.socks.version=SOCKS-versio PiecesView.legend.written=Kirjoitettu levylle PiecesView.legend.requested=Pyydetty PiecesView.legend.downloaded=Ladattu, odottaa kirjoittamista PiecesView.legend.incache=Tieto on v\u00e4limuistissa PiecesView.typeItem.0=Hidas PiecesView.typeItem.1=Nopea PiecesView.type=Tyyppi Security.jar.tools_not_found=JAR-allekirjoitus ep\u00e4onnistui - tools.jar-tiedostoa ei l\u00f6ytynyt kohteesta %1. Katso lis\u00e4tietoja kohdasta Ty\u00f6kalut | Asetukset | Suojaus. Security.jar.signfail=JAR-allekirjoitus ep\u00e4onnistui - %1 ConfigView.section.security.toolsinfo=Er\u00e4\u00e4t Vuzen lis\u00e4osat, kuten Swing-et\u00e4k\u00e4ytt\u00f6liittym\u00e4, k\u00e4ytt\u00e4v\u00e4t tarvittaessa ns. varmennettuja JAR-tiedostoja.\n\nJAR-tiedostojen varmentamiseen tarvitset tools.jar-tiedoston, joka tulee Sunin JDK:n (Java Development Kit) mukana.\nJos olet asentanut vain JRE:n (Java Runtime Environment), tarvitsee sinun siis asentaa JDK.\n\nYleens\u00e4 Vuze l\u00f6yt\u00e4\u00e4 tools.jar-tiedoston sijainnin automaattisesti. Jos n\u00e4in ei kuitenkaan syyst\u00e4 tai toisesta tapahdu,\nvoit itse m\u00e4\u00e4ritell\u00e4 tools.jar-tiedoston sijainnin alla. ConfigView.section.security.toolsdir=Tools.jar-tiedoston sijainti ConfigView.section.security.choosetoolssavedir=Valitse tools.jar-tiedoston sis\u00e4lt\u00e4v\u00e4 hakemisto authenticator.torrent=Torrent-tiedosto ConfigView.section.proxy.peer.same=K\u00e4yt\u00e4 samaa v\u00e4lityspalvelinta kuin yhteyksiss\u00e4 seurantapalvelimiin ConfigView.section.connection.network.max.simultaneous.connect.attempts=Yht\u00e4aikaisesti ulosp\u00e4in luotavien yhteyksien enimm\u00e4ism\u00e4\u00e4r\u00e4 ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Huom.: Windows XP -tuoteperheen SP2-p\u00e4ivityspaketti rajoittaa automaattisesti ulosp\u00e4in luotavat yhteydet kymmeneen.\nAsetuksen oletusarvo on 8. ConfigView.section.file.perf.cache.size.explain=V\u00e4limuistia k\u00e4ytet\u00e4\u00e4n v\u00e4hent\u00e4m\u00e4\u00e4n tiedon lukua kiintolevylt\u00e4/kirjoittamista kiintolevylle. Jos et k\u00e4yt\u00e4 Javan -XX:MaxDirectMemorySize -asetusta muistim\u00e4\u00e4r\u00e4n asettamiseen v\u00e4limuisti- ja verkkosiirr\u00e4nt\u00e4k\u00e4ytt\u00f6\u00e4 varten, sinun tulisi pit\u00e4\u00e4 t\u00e4m\u00e4 arvo v\u00e4hint\u00e4\u00e4n %1:\u00e4 alle virtuaalimuistisi enimm\u00e4ism\u00e4\u00e4r\u00e4n. Nykyinen virtuaalimuistin enimm\u00e4ism\u00e4\u00e4r\u00e4 on %2. Jos haluat vaihtaa t\u00e4t\u00e4 arvoa, katso aihetta "MemoryUsage" Vuzen wikiss\u00e4 osoitteessa %3. V\u00e4\u00e4r\u00e4t asetukset johtavat ilmoituksiin riitt\u00e4m\u00e4tt\u00f6m\u00e4st\u00e4 muistin m\u00e4\u00e4r\u00e4st\u00e4. Yli 32 MB on todenn\u00e4k\u00f6isesti jo liikaa. MyTorrentsView.menu.setSpeed.unlimit=Rajoittamaton MyTorrentsView.menu.setSpeed.unlimited=Rajoittamaton MyTorrentsView.menu.setSpeed.disable=\u00c4l\u00e4 l\u00e4het\u00e4 MyTorrentsView.menu.setSpeed.disabled=Ei l\u00e4hetet\u00e4 MyTorrentsView.menu.setSpeed.in=jaettuna MyTorrentsView.menu.setSpeed.slots=paikkaan, kullekin GeneralView.label.maxuploadspeed=Enimm\u00e4isl\u00e4hetysnopeus GeneralView.label.maxuploadspeed.tooltip=- enimm\u00e4isl\u00e4hetysnopeus (0 = rajoittamaton) MyTorrents.items.UpSpeedLimit.disabled=Ei l\u00e4hetet\u00e4 MyTorrents.items.UpSpeedLimit.unlimited=Rajoittamaton TableColumn.header.maxupspeed=Enim.l\u00e4h.nopeus TableColumn.header.maxupspeed.info=Torrent-tiedoston enimm\u00e4isl\u00e4hetysnopeus. ConfigView.section.file.perf.cache.enable.write=Siirr\u00e4 ladattu tieto v\u00e4limuistiin levylle kirjoituksen v\u00e4hent\u00e4miseksi ja levylt\u00e4 lukemisen v\u00e4hent\u00e4miseksi osia tarkastettaessa ConfigView.section.file.perf.cache.enable.read=Lue tiedostoja ennakoidusti v\u00e4limuistiin levylt\u00e4 lukemisen v\u00e4hent\u00e4miseksi tiedostoja l\u00e4hetett\u00e4ess\u00e4 ConfigView.section.tracker.separatepeerids=K\u00e4yt\u00e4 eri k\u00e4ytt\u00e4j\u00e4tunnisteita seurantapalvelin- ja tiedonsiirtoyhteyksiss\u00e4 ConfigView.section.tracker.separatepeerids.info=Lis\u00e4\u00e4 anonymiteettia, jos siirret\u00e4\u00e4n tietoa anonyymisti\nk\u00e4ytett\u00e4ess\u00e4 ei-anonyymista yhteytt\u00e4 seurantapalvelimeen. ConfigView.section.interface.wavlocation=Valitse .wav-tiedosto ConfigView.section.interface.wavlocation.info=.wav tai j\u00e4t\u00e4 tyhj\u00e4ksi (oletus\u00e4\u00e4ni) ConfigView.section.tracker.server=Oma seurantapalvelin ConfigView.section.tracker.client=Asiakasyhteys ConfigView.section.tracker.client.connecttimeout=Yhteydenoton aikakatkaisu (sekunneissa) ConfigView.section.tracker.client.readtimeout=Tietojen vastaanottamisen aikakatkaisu (sekunneissa) MainWindow.menu.tools=Ty&\u00f6kalut FilesView.path=Hakemisto FilesView.fullpath=N\u00e4yt\u00e4 koko polku FilesView.remaining=Osia j\u00e4ljell\u00e4 TableColumn.header.trackername=Seurantapalvelin TableColumn.header.trackername.info=Seurantapalvelimen nimi perustuen sen p\u00e4ivitysosoitteeseen. ConfigView.group.override=Ohitusasetukset ConfigView.section.file.perf.cache.notsmallerthan=\u00c4l\u00e4 siirr\u00e4 t\u00e4st\u00e4 pienempi\u00e4 tiedostoja v\u00e4limuistiin (%1) PeersView.menu.blockupload=Est\u00e4 l\u00e4hett\u00e4minen PeersView.menu.kickandban=Sulje yhteys ja est\u00e4 yhteydenotot PeersView.menu.kickandban.reason=Manuaalisesti estetty PeersView.state=Tila PeersView.state.info=Yhteyden tila k\u00e4ytt\u00e4j\u00e4\u00e4n. PeersView.state.pending=Odottava PeersView.state.connecting=Yhdistet\u00e4\u00e4n PeersView.state.handshake=Odotetaan k\u00e4ttely\u00e4 PeersView.state.established=Muodostettu ConfigView.section.tracker.processinglimits=K\u00e4sittelyrajoitukset ConfigView.section.tracker.maxgettime=GET-k\u00e4sittelyn enimm\u00e4isaika sekunneissa (0 = rajoittamaton) ConfigView.section.tracker.maxgettime.info=K\u00e4ytet\u00e4\u00e4n p\u00e4ivityksiss\u00e4 ja pikap\u00e4ivityksiss\u00e4. ConfigView.section.tracker.maxposttimemultiplier=GET-ajan kerroin POST-k\u00e4sittelylle (0 = rajoittamaton) ConfigView.section.tracker.maxposttimemultiplier.info=K\u00e4ytet\u00e4\u00e4n lomaketietojen l\u00e4hett\u00e4misess\u00e4 ja siirroissa. ConfigView.section.tracker.maxthreads=Yht\u00e4aikaisten pyynt\u00f6jen enimm\u00e4ism\u00e4\u00e4r\u00e4 DownloadManager.error.operationcancancelled=Toiminto peruutettu Torrent.create.progress.cancelled=Toiminto peruutettu sharing.progress.cancel=Peruuta wizard.maketorrents.autoopen=Kun torrent-tiedosto on luotu, avaa se suoraan l\u00e4hetett\u00e4v\u00e4ksi ConfigView.section.sharing.rescanenable=Tarkasta jaetut kohteet s\u00e4\u00e4nn\u00f6llisesti muutosten varalta ConfigView.section.sharing.rescanperiod=Tarkastusten aikav\u00e4li (sekunneissa) ConfigView.section.connection.advanced=Lis\u00e4asetukset ConfigView.section.connection.advanced.url=http://wiki.vuze.com/index.php/UG_Options#Advanced_Network_Settings ConfigView.section.connection.advanced.mtu=Pakettien enimm\u00e4iskoko (MTU) ConfigView.section.connection.advanced.mtu.tooltip=MTU-arvolla s\u00e4\u00e4dell\u00e4\u00e4n paketin enimm\u00e4iskokoa, joka voidaan siirt\u00e4\u00e4 yhdess\u00e4 kehyksess\u00e4.\nVuze v\u00e4hent\u00e4\u00e4 itse MTU-arvosta aina 40 tavua, jolloin saadaan MSS-arvo (paketin sis\u00e4lt\u00e4m\u00e4 varsinainen tieto ilman otsikkotietoja).\nEsimerkkej\u00e4 suositelluista MTU-arvoista:\n 576 - soittoyhteydet\n1492 - PPPoE:t\u00e4 k\u00e4ytt\u00e4v\u00e4t laajakaistayhteydet\n1500 - Ethernet-l\u00e4hiverkko, DSL- ja kaapelimodeemilaajakaistayhteydet ConfigView.section.connection.advanced.SO_RCVBUF=Pistokkeen SO_RCVBUF-koko (0 = k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4n oletusarvo) ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=SO_RCVBUF-arvolla m\u00e4\u00e4ritell\u00e4\u00e4n pistokkeen vastaanottopuskurin koko tavuissa.\nVuze ei itse m\u00e4\u00e4rittele t\u00e4t\u00e4 oletusarvoisesti ollenkaan, joten k\u00e4yt\u00f6ss\u00e4 ovat k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4n asettamat arvot.\nHuom.: Linux-k\u00e4yt\u00f6ss\u00e4 arvo kaksinkertaistuu automaattisesti. ConfigView.section.connection.advanced.SO_SNDBUF=Pistokkeen SO_SNDBUF-koko (0 = k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4n oletusarvo) ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=SO_SNDBUF-arvolla m\u00e4\u00e4ritell\u00e4\u00e4n pistokkeen l\u00e4hetyspuskurin koko tavuissa.\nVuze ei itse m\u00e4\u00e4rittele t\u00e4t\u00e4 oletusarvoisesti ollenkaan, joten k\u00e4yt\u00f6ss\u00e4 ovat k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4n asettamat arvot.\nHuom.: Linux-k\u00e4yt\u00f6ss\u00e4 arvo kaksinkertaistuu automaattisesti. ConfigView.section.connection.advanced.IPDiffServ=Ulosmenevien pakettien liikenteen luokka/palvelu (TOS / type-of-service) ConfigView.section.connection.advanced.IPDiffServ.tooltip=Voit m\u00e4\u00e4ritt\u00e4\u00e4 ulosmenevien pakettien IP-otsakkeisiin liikenteen luokan/palvelun (type-of-service).\nVuze ei itse m\u00e4\u00e4rittele t\u00e4t\u00e4 oletusarvoisesti ollenkaan, joten k\u00e4yt\u00f6ss\u00e4 ovat k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4n asettamat arvot.\nEsimerkkej\u00e4 mahdollisista arvoista:\n0x02 = IPTOS_LOWCOST\n0x04 = IPTOS_RELIABILITY\n0x08 = IPTOS_THROUGHPUT\n0x10 = IPTOS_LOWDELAY\nHuom.: Asetus ei v\u00e4ltt\u00e4m\u00e4tt\u00e4 toimi ollenkaan, sill\u00e4 se on hyvin pitk\u00e4lti riippuvainen siit\u00e4, kuinka kulloinkin\nk\u00e4yt\u00f6ss\u00e4 oleva k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4 ja Java hyv\u00e4ksyv\u00e4t "ulkopuoliset" muutokset n\u00e4ihin arvoihin. ConfigView.section.interface.confirm_torrent_removal=Pyyd\u00e4 vahvistus torrent-tiedostoa poistettaessa ConfigView.section.interface.confirm_torrent_removal.tooltip=K\u00e4ytt\u00e4j\u00e4lt\u00e4 pyydet\u00e4\u00e4n vahvistus torrent-tiedostoa poistettaessa Siirrot-n\u00e4kym\u00e4st\u00e4. MyTorrentsView.confirm_torrent_removal=Haluatko varmasti poistaa t\u00e4m\u00e4n torrent-tiedoston?\n TableColumn.header.seed_to_peer_ratio=K\u00e4ytt\u00e4j\u00e4suhde TableColumn.header.seed_to_peer_ratio.info=Kaikkien l\u00e4hteiden lukum\u00e4\u00e4r\u00e4n suhde kaikkien lataajien lukum\u00e4\u00e4r\u00e4\u00e4n. PeersView.connected_time=Aika PeersView.connected_time.info=Yhteysaika k\u00e4ytt\u00e4j\u00e4\u00e4n. ConfigView.section.interface.display.add_torrents_silently=Avaa torrent-tiedostot aktivoimatta Vuzea ConfigView.section.interface.display.add_torrents_silently.tooltip=Jos Vuze on pienennettyn\u00e4 esimerkiksi ilmoitusalueelle,\nei Vuze avaudu ruudulle torrent-tiedostoa avattaessa. TableColumn.header.maxdownspeed=Enim.lat.nopeus TableColumn.header.maxdownspeed.info=Torrent-tiedoston enimm\u00e4islatausnopeus. PeersGraphicView.title=Parvi ConfigView.section.tracker.passwordwebhttpsonly=Salli p\u00e4\u00e4sy sivustolle vain HTTPS-protokollaa k\u00e4ytt\u00e4en TableColumn.header.torrentpath=Torrent-tiedosto TableColumn.header.torrentpath.info=Torrent-tiedoston sijainti ja nimi ConfigView.section.sharing.torrentcomment=Kommentti, joka lis\u00e4t\u00e4\u00e4n luotaviin torrent-tiedostoihin ConfigView.label.copyanddeleteratherthanmove=Kopioi ja poista alkuper\u00e4iset tiedostot siirt\u00e4misen sijaan - ehk\u00e4isee tietojen menett\u00e4mist\u00e4 ongelmatilanteissa ConfigView.label.openstatsonstart=Avaa tilastot k\u00e4ynnistett\u00e4ess\u00e4 swt.install.window.title=Vuzen lis\u00e4osien asennus swt.install.window.ok=Asenna swt.install.window.header=Seuraavat osat on valittu asennettavaksi: swt.uninstall.window.title=Vuzen lis\u00e4osien poistaminen swt.uninstall.window.ok=Poista swt.uninstall.window.header=Seuraavat osat on valittu poistettavaksi: installPluginsWizard.title=Asenna lis\u00e4osia installPluginsWizard.mode.title=Valitse lis\u00e4osien l\u00e4hde installPluginsWizard.mode.list=Valitsemalla listasta (ladataan SourceForge.netist\u00e4) installPluginsWizard.list.title=Asennettavat lis\u00e4osat installPluginsWizard.list.loading=Odota hetki, kunnes lis\u00e4osien lista on ladattu. installPluginsWizard.list.loaded=Valitse lis\u00e4osat, jotka haluat asentaa: installPluginsWizard.list.name=Nimi installPluginsWizard.list.version=Versio installPluginsWizard.list.description=Lis\u00e4osan kuvaus: installPluginsWizard.finish.title=Asennus k\u00e4ynniss\u00e4 installPluginsWizard.finish.explanation=Valitut lis\u00e4osat asennetaan k\u00e4ytt\u00e4en Vuzen P\u00e4ivitysavustajaa.\n\nOle k\u00e4rsiv\u00e4llinen, sill\u00e4 P\u00e4ivitysavustajan ilmestyminen ruudulle\nsaattaa kest\u00e4\u00e4 hetkisen. installPluginsWizard.details.loading=Ladataan tietoja, odota hetki... installPluginsWizard.mode.file=Suoraan tiedostosta installPluginsWizard.installMode.title=Valitse asennustapa installPluginsWizard.installMode.user=Asenna lis\u00e4osa(t) vain sinun k\u00e4ytt\u00f6\u00f6si installPluginsWizard.installMode.shared=Asenna lis\u00e4osa(t) kaikille tietokoneen k\u00e4ytt\u00e4jille installPluginsWizard.file.title=Etsi lis\u00e4osa, jonka haluat asentaa. installPluginsWizard.file.file=Tiedosto: installPluginsWizard.file.invalidfile=Tiedosto ei ole kelvollinen Vuzen lis\u00e4osa. installPluginsWizard.file.no_such_file=Tiedostoa ei l\u00f6ydy. installPluginsWizard.file.browse=Selaa... uninstallPluginsWizard.title=Poista lis\u00e4osia uninstallPluginsWizard.list.title=Asennetut lis\u00e4osat uninstallPluginsWizard.list.loaded=Valitse lis\u00e4osat, jotka haluat poistaa: installPluginsWizard.list.nullversion=Ei versionumeroa uninstallPluginsWizard.finish.title=Poistaminen k\u00e4ynniss\u00e4 uninstallPluginsWizard.finish.explanation=Valitut lis\u00e4osat poistetaan k\u00e4ytt\u00e4en P\u00e4ivitysavustajaa. MainWindow.menu.plugins.installPlugins=Ohjattu asennustoiminto... MainWindow.menu.plugins.uninstallPlugins=Ohjattu poistotoiminto... ConfigView.section.ipfilter.totalIPs=%1 IP-osoitetta estetty yhteens\u00e4, joka on %2 kaikista osoitteista Internetiss\u00e4. update.instance.install=Tarkastetaan asennusteht\u00e4v\u00e4t update.instance.uninstall=Tarkastetaan poistoteht\u00e4v\u00e4t update.instance.update=Tarkastetaan p\u00e4ivitykset MainWindow.status.update.tooltip=Tuplaklikkaa n\u00e4hd\u00e4ksesi tarkemmat tiedot edistymisest\u00e4. updater.progress.window.title=Asennusteht\u00e4v\u00e4t updater.progress.window.info=Valitse Keskeyt\u00e4 peruuttaaksesi kaikki suorittamattomat teht\u00e4v\u00e4t. Button.abort=Keskeyt\u00e4 ConfigView.section.ipfilter.enablebanning=Est\u00e4 k\u00e4ytt\u00e4j\u00e4t, jotka l\u00e4hett\u00e4v\u00e4t korruptoitunutta tietoa toistuvasti Network.alert.acceptfail=Portin %1 (%2) k\u00e4yt\u00f6ss\u00e4 esiintyi ongelmia toistuvasti - toiminta lopetettu. Tarkasta palomuurin asetukset portin osalta niin, ett\u00e4 sis\u00e4\u00e4ntulevat yhteydet p\u00e4\u00e4sev\u00e4t l\u00e4pi. MyShares.column.category=Luokka UpdateWindow.restartLater=K\u00e4yn. uud. my\u00f6hemmin MainWindow.menu.file.restart=&K\u00e4ynnist\u00e4 Vuze uudelleen MainWindow.dialog.restartconfirmation.title=K\u00e4ynnist\u00e4 Vuze uudelleen MainWindow.dialog.restartconfirmation.text=Haluatko varmasti k\u00e4ynnist\u00e4\u00e4 Vuzen uudelleen? deletetorrent.message1=Olet aikeissa poistaa seuraavan siirron torrent-tiedoston:\n deletetorrent.message2=\nHaluatko varmasti jatkaa? ConfigView.label.prioritizemostcompletedfiles=Pyri lataamaan ensisijaisesti l\u00e4himp\u00e4n\u00e4 valmistumista olevia korkean prioriteetin tiedostoja splash.plugin.init=Alustetaan lis\u00e4osaa - splash.plugin.UIinit=Alustetaan lis\u00e4osan graafista k\u00e4ytt\u00f6liittym\u00e4\u00e4: %1 ConfigView.section.style.osx_small_fonts=K\u00e4yt\u00e4 pieni\u00e4 kirjasinkokoja (vaatii uudelleenk\u00e4ynnistyksen) ConfigView.section.tracker.tcpnonblocking=K\u00e4yt\u00e4 ei-rajoittavaa siirr\u00e4nt\u00e4\u00e4 TCP-k\u00e4sittelyss\u00e4. Jos k\u00e4yt\u00f6ss\u00e4, seurantapalvelimen sivun t\u00e4ytyy k\u00e4ytt\u00e4\u00e4 toista porttia. Kokeellinen! ConfigView.section.tracker.nonblocking=Siirr\u00e4nn\u00e4n rajoittaminen ConfigView.section.tracker.nonblockingconcmax=Yht\u00e4aikaisten yhteyksien enimm\u00e4ism\u00e4\u00e4r\u00e4 (0 = rajoittamaton) MyTorrentsView.menu.exportmenu=Vie MyTorrentsView.menu.exporttorrent=torrent-tiedostoksi... ConfigView.group.scrape=Pikap\u00e4ivitykset ConfigView.section.tracker.client.scrapeinfo=Pikap\u00e4ivitysten ohittaminen est\u00e4\u00e4 monien siirtojonos\u00e4\u00e4nt\u00f6jen toimimisen, sill\u00e4 ne ovat riippuvaisia seurantapalvelimien pikap\u00e4ivitystiedoista. ConfigView.section.tracker.client.scrapeenable=K\u00e4yt\u00e4 pikap\u00e4ivityksi\u00e4 ConfigView.section.tracker.client.scrapestoppedenable=Tee pikap\u00e4ivitykset pys\u00e4ytetyille torrent-tiedostoille Scrape.status.disabled=Pikap\u00e4ivitys ei k\u00e4yt\u00f6ss\u00e4 MyTorrentsView.menu.explore=N\u00e4yt\u00e4 MyTorrentsView.menu.explore._mac=N\u00e4yt\u00e4 Finderissa MyTorrentsView.menu.explore._windows=N\u00e4yt\u00e4 Windows Explorerissa wizard.maketorrents.autohost=Aseta torrent-tiedosto seurantaan omalle seurantapalvelimelle ConfigView.label.overrideip=Ohita seurantapalvelimelle n\u00e4kyv\u00e4 IP-osoite - erota puolipisteill\u00e4, jos useita osoitteita eri verkoille ConfigView.label.overrideip.tooltip=Ilmoittaa seurantapalvelimelle m\u00e4\u00e4ritetyn IP-osoitteen (tai osoitteet) sen sijaan, mist\u00e4 tietoa oikeasti l\u00e4hetet\u00e4\u00e4n.\nJ\u00e4t\u00e4 tyhj\u00e4ksi, jos et halua k\u00e4ytt\u00e4\u00e4 t\u00e4t\u00e4 asetusta. ConfigView.section.connection.group.networks=Verkot ConfigView.section.connection.group.networks.info=Valitse oletusverkot, joissa sallitaan varsinaisen siirrett\u00e4v\u00e4n tiedon liikkuminen ConfigView.section.connection.networks.prompt=Kysy valintaa, jos torrent-tiedosto k\u00e4ytt\u00e4\u00e4 anonyymista seurantapalvelinta (verkkoa) ConfigView.section.connection.networks.Public=Julkinen IP-verkko (ei anonyyminen) ConfigView.section.connection.networks.I2P=I2P-verkko ConfigView.section.connection.networks.Tor=The Onion Router (Tor) -verkko TableColumn.header.networks=Verkot TableColumn.header.networks.info=Verkot, joissa sallitaan varsinaisen siirrett\u00e4v\u00e4n tiedon liikkuminen. Scrape.status.networkdisabled=Verkko ei k\u00e4ytett\u00e4viss\u00e4 ConfigView.section.tracker.server.group.networks=Verkot ConfigView.section.tracker.server.group.networks.info=Valitse verkot, joihin hyv\u00e4ksyt\u00e4\u00e4n k\u00e4ytt\u00e4ji\u00e4: window.networkselection.title=Verkkojen valitseminen window.networkselection.info=Alla olevan torrent-tiedoston seurantapalvelimet tukevat seuraavia verkkoja.\nValitse ne, joita haluat k\u00e4ytt\u00e4\u00e4 yhteyksiss\u00e4 seurantapalvelimiin ja k\u00e4ytt\u00e4jiin.\nJos kyseess\u00e4 on anonyyminen seurantapalvelin, joka tukee julkisia yhteyksi\u00e4, k\u00e4yt\u00e4 sek\u00e4\nanonyymista ett\u00e4 julkista verkkoa.\nJulkisen verkon k\u00e4ytt\u00e4misest\u00e4 seuraa luonnollisesti se, ett\u00e4 anonymiteetti h\u00e4vi\u00e4\u00e4. window.networkselection.description=Torrent-tiedosto: plugins.basicview.clear=Tyhjenn\u00e4 ConfigView.section.connection.group.peersources=K\u00e4ytt\u00e4j\u00e4t ConfigView.section.connection.group.peersources.info=Valitse oletustietol\u00e4hteet, joista saadut k\u00e4ytt\u00e4j\u00e4t voivat muodostaa yhteyden ConfigView.section.connection.peersource.Tracker=Seurantapalvelimen palauttamat tiedot ConfigView.section.connection.peersource.DHT=Hajautettu k\u00e4ytt\u00e4jien seuranta (DHT) ConfigView.section.connection.peersource.PeerExchange=K\u00e4ytt\u00e4jien luovuttamat tiedot ConfigView.section.connection.peersource.Plugin=Lis\u00e4osan lis\u00e4\u00e4m\u00e4 yhteystieto ConfigView.section.connection.peersource.Incoming=Sis\u00e4\u00e4ntulevat yhteydet PeersView.source=L\u00e4hde PeersView.source.info=L\u00e4hde, josta kyseisen k\u00e4ytt\u00e4j\u00e4n tiedot on saatu selville. TableColumn.header.peersources=Tietol\u00e4hteet TableColumn.header.peersources.info=Tietol\u00e4hteet, joista saadut k\u00e4ytt\u00e4j\u00e4t voivat muodostaa yhteyden. wizard.tracker.dht=Hajautettu k\u00e4ytt\u00e4jien seuranta (vain Vuze-asiakasohjelmat) MyTorrentsView.menu.advancedmenu=Lis\u00e4asetukset MyTorrentsView.menu.networks=K\u00e4ytett\u00e4v\u00e4t verkot MyTorrentsView.menu.peersource=K\u00e4ytt\u00e4jien etsiminen ConfigView.section.sharing.permitdht=Hajautettu k\u00e4ytt\u00e4jien seuranta, kun seurantapalvelin ei ole k\u00e4ytett\u00e4viss\u00e4 ConfigView.section.sharing.protocol=Protokolla jaetuille resursseille PeersView.Messaging=Viestint\u00e4 PeersView.Messaging.info=K\u00e4ytett\u00e4v\u00e4 viestint\u00e4j\u00e4rjestelm\u00e4. ConfigView.label.queue.newseedsmovetop=Siirr\u00e4 viimeksi valmistuneet torrent-tiedostot l\u00e4hetysjonon k\u00e4rkeen ConfigView.label.seeding.firstPriority.ignore.info=Huomaa, ett\u00e4 n\u00e4iden ohituss\u00e4\u00e4nt\u00f6jen k\u00e4ytt\u00e4minen saattaa johtaa siihen, ett\u00e4\ntorrent-tiedosto pys\u00e4ytet\u00e4\u00e4n heti kun lataus on valmistunut. ConfigView.label.seeding.firstPriority.ignore=Ohita yll\u00e4 olevat s\u00e4\u00e4nn\u00f6t torrent-tiedostojen kohdalla ConfigView.label.seeding.firstPriority.ignoreSPRatio=joiden l\u00e4hteit\u00e4/lataajia-suhdeluku on yli ConfigView.label.seeding.firstPriority.ignore0Peer=joilla ei ole yht\u00e4\u00e4n lataajaa ConfigView.section.tracker.sendjavaversionandos=L\u00e4het\u00e4 tiedot Javan versiosta ja k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4st\u00e4 MagnetPlugin.contextmenu.exporturi=Kopioi Magnet URI -linkki leikep\u00f6yd\u00e4lle ConfigView.section.plugins.dht=Hajautettu tietokanta dht.info=T\u00e4m\u00e4 lis\u00e4osa mahdollistaa mm. hajautetun k\u00e4ytt\u00e4jien seurannan - k\u00e4ytt\u00e4m\u00e4tt\u00e4 j\u00e4tt\u00e4minen vaikuttaa alentavasti latausnopeuksiin. dht.enabled=K\u00e4yt\u00e4 hajautettua tietokantaa dht.portdefault=K\u00e4yt\u00e4 oletusporttia dht.port=Hajautetun tietokannan UDP-portti dht.execute.command=Virheenm\u00e4\u00e4rityskomento dht.execute.info=Suorita komento dht.execute=Suorita dht.logging=Seuraa toimintaa ConfigView.section.plugins.dhttracker=Hajautettu seurantapalvelin dhttracker.tracknormalwhenoffline=Seuraa normaaleja torrent-tiedostoja vain, kun niiden seurantapalvelin ei ole k\u00e4ytett\u00e4viss\u00e4 ConfigView.section.file.nativedelete._mac=K\u00e4yt\u00e4 Roskakoria tiedostoja tuhottaessa ConfigView.section.file.nativedelete._windows=Siirr\u00e4 tuhotut tiedostot Roskakoriin ConfigView.section.logging.generatediagnostics=Luo ConfigView.section.logging.netinfo=Luo verkon tiedot ja kopioi ne leikep\u00f6yd\u00e4lle (sek\u00e4 lokiin ja lokitiedostoon, jos asetettu) ConfigView.section.logging.statsinfo=Luo tilastotiedot ja kopioi ne leikep\u00f6yd\u00e4lle (sek\u00e4 lokiin ja lokitiedostoon, jos asetettu) ConfigView.section.logging.generatediagnostics.info=Luo virheenm\u00e4\u00e4ritystiedot ja kopioi ne leikep\u00f6yd\u00e4lle (sek\u00e4 lokiin ja lokitiedostoon, jos asetettu) ConfigView.section.sharing.privatetorrent=Yksityinen jako - vain oman seurantapalvelimen k\u00e4ytt\u00e4j\u00e4t hyv\u00e4ksyt\u00e4\u00e4n MainWindow.menu.tools.nattest=&NAT- ja palomuuritesti Button.apply=K\u00e4yt\u00e4 Button.close=Sulje window.welcome.title=Tervetuloa k\u00e4ytt\u00e4m\u00e4\u00e4n Vuzen versiota %1! #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Julkaisutiedot dht.reseed.label=Normaalisti hajautetun tietokannan uudelleenjakoon ei ole tarvetta. Jos yhteystietojen m\u00e4\u00e4r\u00e4 on kuitenkin pieni, voidaan t\u00e4ll\u00e4 kasvattaa tietojen m\u00e4\u00e4r\u00e4\u00e4.\nJ\u00e4t\u00e4 kent\u00e4t tyhj\u00e4ksi yhdist\u00e4\u00e4ksesi tietoja kaikilta yhdistetyilt\u00e4 k\u00e4ytt\u00e4jilt\u00e4 tai m\u00e4\u00e4rit\u00e4 IP-osoite ja portti tehd\u00e4ksesi saman vain tietyn k\u00e4ytt\u00e4j\u00e4n kanssa. dht.reseed.group=Uudelleenjako dht.reseed.ip=IP-osoite dht.reseed.port=Portti dht.reseed=Jaa dht.reseed.info=Jaa tietokanta uudelleen dht.diagnostics.group=Virheenm\u00e4\u00e4ritys DHTView.title.full=Hajautettu tietokanta DHTView.title.fullcvs=Hajautettu tietokanta (CVS) DHTView.general.title=Yleiset DHTView.general.uptime=K\u00e4ytt\u00f6aika: DHTView.general.users=K\u00e4ytt\u00e4j\u00e4t: DHTView.general.nodes=Solmut: DHTView.general.leaves=Lehti\u00e4: DHTView.general.contacts=Yhteydet: DHTView.general.replacements=Varalla: DHTView.general.live=El\u00e4v\u00e4t: DHTView.general.unknown=Vieraat: DHTView.general.dying=Kuolevat: DHTView.transport.title=Siirrot DHTView.transport.packets=Paketit DHTView.transport.bytes=Tavut DHTView.transport.received=Vastaanotetut DHTView.transport.sent=L\u00e4hetetyt DHTView.transport.in=Sis\u00e4\u00e4n: DHTView.transport.out=Ulos: DHTView.operations.title=Toiminnan tarkemmat tiedot DHTView.operations.sent=L\u00e4hetetyt DHTView.operations.ok=Onnistuneet DHTView.operations.failed=Ep\u00e4onnistuneet DHTView.operations.received=Vastaanotetut DHTView.operations.ping=Vasteaikojen haut DHTView.operations.findNode=Solmujen etsint\u00e4 DHTView.operations.findValue=Arvojen etsint\u00e4 DHTView.operations.store=Tallennukset DHTView.activity.title=Toiminta DHTView.activity.status=Tila DHTView.activity.status.true=Jonossa DHTView.activity.status.false=K\u00e4yt\u00f6ss\u00e4 DHTView.activity.type=Tyyppi DHTView.activity.type.1=Sis\u00e4inen haku DHTView.activity.type.2=Ulkoinen haku DHTView.activity.type.3=Sis\u00e4inen asetus DHTView.activity.type.4=Ulkoinen asetus DHTView.activity.target=Kohde DHTView.activity.details=Tarkemmat tiedot DHTView.db.title=Tietokanta DHTView.db.keys=Avaimet DHTView.db.values=Arvot DHTView.db.local=Paikalliset DHTView.db.direct=Suorat DHTView.db.indirect=Ep\u00e4suorat DHTView.db.divfreq=Taajuuden jakaja DHTView.db.divsize=Koon jakaja MainWindow.dht.status.tooltip=Kun hajautettu tietokanta on k\u00e4yt\u00f6ss\u00e4, n\u00e4et t\u00e4st\u00e4 kytkettyin\u00e4 olevien k\u00e4ytt\u00e4jien arvioidun m\u00e4\u00e4r\u00e4n. MainWindow.dht.status.disabled=DHT ei k\u00e4yt\u00f6ss\u00e4 MainWindow.dht.status.failed=DHT:n k\u00e4ytt\u00f6\u00f6notto ep\u00e4onnistui MainWindow.dht.status.initializing=Alustetaan DHT:t\u00e4 MainWindow.dht.status.users=%1 k\u00e4ytt\u00e4j\u00e4\u00e4 MainWindow.dht.status.unreachable=DHT:n k\u00e4ytt\u00f6 estetty MainWindow.dht.status.unreachabletooltip=Hajautetun tietokannan (DHT:n) UDP-portin k\u00e4yt\u00f6ss\u00e4 on havaittu ongelmia\n - palomuuri est\u00e4\u00e4 liikenteen/NAT-ongelma MyTorrentsView.menu.setUpSpeed=L\u00e4hetysnopeus MyTorrentsView.menu.setDownSpeed=Latausnopeus ConfigView.section.tracker.client.showwarnings=N\u00e4yt\u00e4 seurantapalvelimien palauttamat varoitusviestit dht.advanced=K\u00e4yt\u00e4 lis\u00e4asetuksia dht.advanced.group=Lis\u00e4asetukset dht.advanced.label=Vaihda n\u00e4it\u00e4 asetuksia vain, jos todella tied\u00e4t mit\u00e4 olet tekem\u00e4ss\u00e4. dht.override.ip=Ohita ulkoinen IP-osoite ConfigView.section.logging.loggerenable=Kirjaa tapahtumat lokiin (n\u00e4ht\u00e4vill\u00e4 konsolissa) ConfigView.section.ipfilter.blockbanning=Est\u00e4 koko 256 osoitteen osoiteryhm\u00e4, kun v\u00e4hint\u00e4\u00e4n n\u00e4in monta osoitetta ryhm\u00e4n sis\u00e4lt\u00e4 on jo estetty MyTrackerView.passive=Passiivinen TableColumn.header.swarm_average_speed=Keskim. nopeus TableColumn.header.swarm_average_speed.info=K\u00e4ytt\u00e4jien keskim\u00e4\u00e4r\u00e4inen siirtonopeus TableColumn.header.comment=Kommentti TableColumn.header.comment.info=Oma kommentti siirrolle. TableColumn.header.commenticon=Kommentoitu TableColumn.header.commenticon.info=N\u00e4ytt\u00e4\u00e4 ikonin, jos siirrolle on asetettu oma kommentti. MyTrackerView.category=Luokka MainWindow.menu.file.open.torrentfortracking=Torrent-tiedosto... (seurantaa varten) VivaldiView.title.full=Vivaldi-n\u00e4kym\u00e4 MyTrackerView.date_added=Lis\u00e4tty ConfigView.section.tracker.portbackup=Varaportit (erota ;-merkill\u00e4) ConfigView.label.playfilespeech=Kerro tiedoston valmistumisesta puheella ConfigView.label.playfilespeech.info=Puhepalvelu toimii toistaiseksi parhaiten englanniksi. ConfigView.label.playfilefinished=Anna \u00e4\u00e4nimerkki yksitt\u00e4isen tiedoston valmistuttua ConfigView.label.backupconfigfiles=Varmuuskopioi asetustiedostot tietojen palauttamisen varalta ConfigView.section.tracker.client.scrapesingleonly=Est\u00e4 seurantapalvelinkohtaiset pikap\u00e4ivitysker\u00e4ym\u00e4t (k\u00e4yt\u00e4, jos seurantapalvelin antaa 'URL too long' (414) -virhesanomia) dht.ipfilter.log=N\u00e4yt\u00e4 lokissa IP-suotimien est\u00e4m\u00e4t k\u00e4ytt\u00e4j\u00e4t ConfigView.label.seeding.addForSeedingDLCopyCount=Avattaessa torrent-tiedosto pelkk\u00e4\u00e4 l\u00e4hett\u00e4mist\u00e4 varten, aseta latauskertoimeksi ActivityView.legend.limit=Nopeusrajoitus ActivityView.legend.achieved=Saavutettu nopeus ActivityView.legend.overhead=Yleisrasite ActivityView.legend.peeraverage=Keskim\u00e4\u00e4r\u00e4inen nopeus ActivityView.legend.swarmaverage=K\u00e4ytt\u00e4jien keskinopeus ActivityView.legend.trimmed=Tasattu (sovitettu) nopeus MyTorrentsView.menu.movemenu=Siirr\u00e4 tiedostot MyTorrentsView.menu.movedata=Vaihda tallennushakemistoa... MyTorrentsView.menu.movetorrent=Siirr\u00e4 torrent-tiedosto... MyTorrentsView.menu.movedata.dialog=Valitse uusi sijainti DHTView.operations.data=Tieto DHTView.general.reachable=Saavutettavissa DHTView.general.rendezvous=Tavattavissa ConfigView.label.queue.maxactivetorrentswhenseeding=Ainoastaan l\u00e4hetett\u00e4ess\u00e4 (0 = rajoittamaton) Views.plugins.IRC.title=IRC - reaaliaikainen tekninen tuki Formats.units.alot=Paljon! ConfigView.section.ipfilter.persistblocking=Muista estettyjen k\u00e4ytt\u00e4jien tiedot uudelleenk\u00e4ynnistyksen j\u00e4lkeen FilesView.menu.rename=Nime\u00e4 uudelleen ja/tai siirr\u00e4 FilesView.menu.rename_only=Nime\u00e4 uudelleen FilesView.menu.retarget=Siirr\u00e4 FilesView.rename.choose.path=Valitse uusi tai olemassa oleva tiedosto FilesView.rename.choose.path.dir=Valitse uusi tai olemassa oleva hakemisto FilesView.rename.confirm.delete.title=Vahvista poisto FilesView.rename.confirm.delete.text=Haluatko varmasti poistaa seuraavan tiedoston?\n%1 FilesView.rename.filename.title=Nime\u00e4 uudelleen FilesView.rename.filename.text=Anna uusi nimi tiedostolle: ConfigView.higher.mode.available=Korkeammissa k\u00e4ytt\u00e4j\u00e4tiloissa on valittavissa lis\u00e4\u00e4 asetuksia ConfigView.section.mode=K\u00e4ytt\u00e4j\u00e4tila ConfigView.section.mode.title=K\u00e4ytt\u00e4j\u00e4n taidot ConfigView.section.mode.beginner=Aloittelija ConfigView.section.mode.beginner.wiki.definitions=BitTorrent-sanasto ConfigView.section.mode.intermediate=Keskiverto ConfigView.section.mode.intermediate.wiki.host=Torrent-tiedostojen seuranta ConfigView.section.mode.intermediate.wiki.publish=Torrent-tiedostojen julkaiseminen ConfigView.section.mode.advanced=Edistynyt ConfigView.section.mode.advanced.wiki.main=Wikin etusivu ConfigView.section.mode.beginner.text=Kaikki mit\u00e4 tarvitset torrent-tiedostojen lataamiseen.\nK\u00e4yt\u00e4 t\u00e4t\u00e4 tilaa, jos haluat vain hallita torrent-tiedostojasi. ConfigView.section.mode.intermediate.text=Vaikutusmahdollisuus oman seurantapalvelimen asetuksiin.\nK\u00e4yt\u00e4 t\u00e4t\u00e4 tilaa, jos haluat asettaa seurantaan tai julkaista torrent-tiedostoja. ConfigView.section.mode.advanced.text=Vaikutusmahdollisuus tarkempiin yhteysasetuksiin.\nK\u00e4yt\u00e4 t\u00e4t\u00e4 tilaa vain, jos todella tied\u00e4t mit\u00e4 olet tekem\u00e4ss\u00e4. Files.column.storagetype=Varaustapa Files.column.fileext=Tyyppi FileItem.storage.linear=Lineaarinen FileItem.storage.compact=Kompakti MessageBoxWindow.rememberdecision=Muista valinta jatkossa ConfigView.section.interface.cleardecisions=Tyhjenn\u00e4 tallennetut asetusvalinnat ConfigView.section.interface.cleardecisionsbutton=Tyhjenn\u00e4 ConfigView.section.interface.cleartrackers=Tyhjenn\u00e4 tallennetut seurantapalvelintiedot ConfigView.section.interface.cleartrackersbutton=Tyhjenn\u00e4 ConfigView.section.interface.clearsavepaths=Tyhjenn\u00e4 tallennetut tallennushakemistovalinnat ConfigView.section.interface.clearsavepathsbutton=Tyhjenn\u00e4 configureWizard.welcome.usermodes=K\u00e4ytt\u00e4j\u00e4tilan m\u00e4\u00e4ritt\u00e4minen vaikuttaa k\u00e4ytt\u00e4j\u00e4lle n\u00e4ytett\u00e4vien asetusmahdollisuuksien m\u00e4\u00e4r\u00e4\u00e4n. Oikean tason valinta varmistaa sen, ett\u00e4 k\u00e4ytt\u00e4j\u00e4lle n\u00e4ytet\u00e4\u00e4n vain h\u00e4nen osaamistasolleen sopivat toiminnot, ja perusk\u00e4ytt\u00f6 onnistuu vaivattomasti. Voit halutessasi vaihtaa k\u00e4ytt\u00e4j\u00e4tilaa my\u00f6hemmin asetuksista. FilesView.skip.confirm.delete.text=Haluatko varmasti poistaa seuraavan tiedoston k\u00e4ytt\u00e4m\u00e4n tilanvarauksen?\n%1 FilesView.rename.failed.title=Uudelleennime\u00e4minen/siirt\u00e4minen ep\u00e4onnistui FilesView.rename.failed.text=Toiminto ep\u00e4onnistui - todenn\u00e4k\u00f6isesti virheellinen kohdevalinta. diagnostics.log_found=Vuze ei sulkeutunut viimeksi kunnollisesti. Tarkasta virheenm\u00e4\u00e4rityslokitiedostot ja ilmoita mahdollisista ohjelmavirheist\u00e4 Azureuksen kehitt\u00e4jille. Tarkasta my\u00f6s wikist\u00e4 (katso Ohje-valikko) artikkeli "Vuze Disappears". ManagerItem.paused=Keskeytetty Utils.link.visit=Katso my\u00f6s ConfigView.section.connection.serverport.wiki=Hyv\u00e4 porttivalinta ConfigView.section.transfer.speeds.wiki=Hyv\u00e4t nopeusrajoitusasetukset installPluginsWizard.installMode.info.title=Tietoa lis\u00e4osista installPluginsWizard.installMode.info.text=Vuze toimii vallan mainosti ilman lis\u00e4osiakin, mutta niiden avulla voit esimerkiksi hy\u00f6dynt\u00e4\u00e4 automaattisia toimenpiteit\u00e4 ja et\u00e4hallita Vuzea.\n\nLue jokaisen lis\u00e4osan kuvaus tarkasti ennen kuin asennat sen.\nN\u00e4in pid\u00e4t huolen siit\u00e4, ettet turhaan pid\u00e4 asennettuina sellaisia lis\u00e4osia, joita et kuitenkaan k\u00e4ytt\u00e4isi.\n\nLis\u00e4osia voit poistaa ohjatulla poistotoiminnolla, jonka l\u00f6yd\u00e4t my\u00f6skin Lis\u00e4osat-valikosta. Views.plugins.Distributed.DB.title=Hajautettu tietokanta Views.plugins.Distributed.Tracker.title=Hajautettu seurantapalvelin Views.plugins.Plugin.Update.title=Lis\u00e4osien p\u00e4ivitys Views.plugins.UPnP.title=UPnP-m\u00e4\u00e4ritys Views.plugins.UPnP.title.tooltip=Universal Plug and Play -tuki openUrl.url.info=Tukee http- ja https-protokollia, magnet-linkkej\u00e4 sek\u00e4 heksadesimaalisia tiivistearvoja TableColumn.header.swarm_average_completion=Keskim. valmiina TableColumn.header.swarm_average_completion.info=Keskim\u00e4\u00e4r\u00e4inen valmistumisprosentti kaikkien lataajien keskuudessa. GeneralView.label.swarm_average_completion=Keskim\u00e4\u00e4rin valmistunut: GeneralView.label.swarm_average_completion.tooltip=Keskim\u00e4\u00e4r\u00e4inen valmistumisprosentti kaikkien k\u00e4ytt\u00e4jien keskuudessa. MainWindow.nat.status.unknown=NAT-tila MainWindow.nat.status.tooltip.unknown=Yhteyden toimivuus palomuurin/NATin suhteen tuntematon (TCP-portin osalta). MainWindow.nat.status.ok=NAT-tila OK MainWindow.nat.status.tooltip.ok=Yhteyden toimivuus kunnossa (TCP-portin osalta). MainWindow.nat.status.probok=NAT-tila OK? MainWindow.nat.status.tooltip.probok=Yhteyden toimivuuden pit\u00e4isi olla kunnossa, mutta Vuze ei ole saanut l\u00e4hiaikoina sis\u00e4\u00e4ntulevia TCP-yhteyksi\u00e4. MainWindow.nat.status.bad=Yhteysongelma MainWindow.nat.status.tooltip.bad=Palomuuri est\u00e4\u00e4 liikenteen/NAT-ongelma havaittu (TCP-portin osalta)\n - ohjeita ongelman ratkaisemiseksi wikiss\u00e4 (katso Ohje | Wiki (UKK)) plugin.installer.recommended.plugin=Suositeltu lis\u00e4osa - tarkasta tiedot ja asenna, jos tarvitset. LoggerView.pause=Keskeyt\u00e4 lokin luominen LoggerView.clear=&Tyhjenn\u00e4 LoggerView.filter=Suodata n\u00e4ytett\u00e4vi\u00e4 tietoja LoggerView.filter.uncheckAll=Poista kaikki LoggerView.filter.checkAll=Valitse kaikki LoggerView.loggingDisabled=Lokin tekeminen on asetettu pois p\u00e4\u00e4lt\u00e4. LoggerView.includeOnly=N\u00e4yt\u00e4 vain t\u00e4t\u00e4 s\u00e4\u00e4nn\u00f6llist\u00e4 lauseketta vastaavat rivit: LoggerView.excludeAll=\u00c4l\u00e4 n\u00e4yt\u00e4 t\u00e4t\u00e4 s\u00e4\u00e4nn\u00f6llist\u00e4 lauseketta vastaavia rivej\u00e4: ConfigView.section.logging.log0type=Tiedot ConfigView.section.logging.log1type=Varoitukset ConfigView.section.logging.log2type=Virheet ConfigView.section.logging.filter=Kirjattavien tietojen suodatus ConfigView.section.logging.level=P\u00e4\u00e4taso ConfigView.section.logging.showLogsFor=N\u00e4yt\u00e4 %1-tason lokimerkinn\u00e4t luokista: ConfigView.pluginlist.column.loadAtStartup=Lataa k\u00e4ynnistett\u00e4ess\u00e4 ConfigView.pluginlist.column.type=Tyyppi ConfigView.pluginlist.column.type.perUser=K\u00e4ytt\u00e4j\u00e4kohtainen ConfigView.pluginlist.column.type.shared=Jaettu ConfigView.pluginlist.column.type.builtIn=Sis\u00e4\u00e4nrakennettu ConfigView.pluginlist.column.name=Nimi ConfigView.pluginlist.column.version=Versio ConfigView.pluginlist.column.directory=Hakemisto ConfigView.pluginlist.column.isOperational=K\u00e4ytett\u00e4viss\u00e4 PeersView.BlockView.Avail.Have=On molemmilla PeersView.BlockView.Avail.NoHave=On toisella; ei itsell\u00e4 PeersView.BlockView.NoAvail.Have=On itsell\u00e4; ei toisella PeersView.BlockView.NoAvail.NoHave=Ei ole kummallakaan PeersView.BlockView.Transfer=Siirret\u00e4\u00e4n PeersView.BlockView.NextRequest=Pyydet\u00e4\u00e4n seuraavaksi PeersView.BlockView.title=Kuvaus osista PeersView.BlockView.AvailCount=Saatavuusluku MyTorrentsView.dialog.NumberError.title=Virheellinen arvo MyTorrentsView.dialog.NumberError.text=Sy\u00f6tt\u00e4m\u00e4si arvo ei ole kelvollinen. MyTorrentsView.menu.manual=&Manuaalinen... MyTorrentsView.menu.manual.per_torrent=Manuaalinen (torrent-tiedostokohtainen)... MyTorrentsView.menu.manual.shared_torrents=Manuaalinen (jaettuna valittujen kesken)... MyTorrentsView.dialog.setSpeed.title=Aseta %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Rajoita %2 arvoon (%1): MyTorrentsView.dialog.setNumber.upload=l\u00e4hetysnopeus MyTorrentsView.dialog.setNumber.download=latausnopeus MyTorrentsView.dialog.setNumber.inKbps=%1 OpenTorrentWindow.torrentLocation=Ladattavat torrent-tiedostot: OpenTorrentWindow.addFiles.URL=Lis\u00e4\u00e4 &URL OpenTorrentWindow.addFiles.Folder=Lis\u00e4\u00e4 &hakemisto OpenTorrentWindow.addFiles.Clipboard=Lis\u00e4\u00e4 &leikep\u00f6yd\u00e4lt\u00e4 OpenTorrentWindow.changeDestination=Vaihda tallennushakemistoa OpenTorrentWindow.fileList=Ladattavat tiedostot: OpenTorrentWindow.torrentTable.name=Nimi OpenTorrentWindow.torrentTable.saveLocation=Tallennushakemisto OpenTorrentWindow.fileTable.fileName=Tiedostonimi OpenTorrentWindow.fileTable.size=Koko OpenTorrentWindow.fileTable.destinationName=Kohdesijainti ja -nimi OpenTorrentWindow.startMode.seeding=Aseta l\u00e4hetett\u00e4v\u00e4ksi OpenTorrentWindow.fileList.changeDestination=Vaihda tallennushakemistoa (kohdetta) OpenTorrentWindow.mb.badSize.title=Yhteensopimaton tiedosto OpenTorrentWindow.mb.badSize.text='%1' ei ole sama kuin '%2', joten sit\u00e4 ei voida asettaa l\u00e4hetett\u00e4v\u00e4ksi. OpenTorrentWindow.mb.alreadyExists.text=%3 on jo lis\u00e4tty nimell\u00e4 '%2'. OpenTorrentWindow.mb.alreadyExists.default.name=Kohde OpenTorrentWindow.mb.alreadyExists.title=Kohde jo lis\u00e4tty OpenTorrentWindow.mb.openError.title=Virhe tiedoston avauksessa OpenTorrentWindow.mb.openError.text=Kohdetta '%1' ei voitu avata:\n%2 OpenTorrentWindow.torrent.remove=Poista torrent-tiedosto listalta OpenTorrentWindow.torrent.options=Seuraavat asetukset koskevat yll\u00e4 valittuina olevia torrent-tiedostoja: OpenTorrentWindow.xOfTotal=(%1/%2) iconBar.open.tooltip=Avaa torrent-tiedosto LocaleUtil.column.text=Tuntematon tekstiosa Tracker.tooltip.MultiSupport=Seurantapalvelin tukee useita pikap\u00e4ivityksi\u00e4 yhdell\u00e4 yhteydenottokerralla. Tracker.tooltip.NoMultiSupport=Seurantapalvelin ei tue useita pikap\u00e4ivityksi\u00e4 yhdell\u00e4 yhteydenottokerralla.\nT\u00e4m\u00e4 ei vaikuta Vuzen suorituskykyyn, mutta asettaa seurantapalvelimelle lis\u00e4\u00e4 kuormaa. ConfigView.label.lazybitfield=L\u00e4het\u00e4 tiedot saatavilla olevista osista hajautetusti (auttaa tilanteessa, jossa ISP est\u00e4\u00e4 tietojen l\u00e4hett\u00e4misen kerralla) LoggerView.realtime=P\u00e4ivit\u00e4 reaaliajassa ConfigView.section.file.perf.cache.flushpieces=Kirjoita valmistuneet osat v\u00e4litt\u00f6m\u00e4sti kiintolevylle. Tasaa levyhakuja, mutta voi johtaa useampiin kirjoitusoperaatioihin ConfigView.section.file.writemblimit=Jonoon asetettavan kirjoitettavan tiedon enimm\u00e4ism\u00e4\u00e4r\u00e4 (%1) ConfigView.section.file.writemblimit.explain=Kun kirjoitusnopeus kiintolevylle on pienempi kuin latausnopeus, t\u00e4m\u00e4 asetus rajoittaa jonoon asetettavan, kirjoitusta odottavan tiedon enimm\u00e4ism\u00e4\u00e4r\u00e4\u00e4. Jos enimm\u00e4ism\u00e4\u00e4r\u00e4 tulee t\u00e4yteen, alennetaan latausnopeutta automaattisesti. ConfigView.section.file.readmblimit=Jonoon asetettavan luettavan tiedon enimm\u00e4ism\u00e4\u00e4r\u00e4 (%1) ConfigView.section.file.readmblimit.explain=T\u00e4m\u00e4 asetus rajoittaa keskusmuistiin asetettavan, k\u00e4sittely\u00e4 odottavan luettavan tiedon m\u00e4\u00e4r\u00e4\u00e4. Button.moveUp=Siirr\u00e4 &yl\u00f6s Button.moveDown=Siirr\u00e4 &alas ConfigView.notAvailableForMode=N\u00e4m\u00e4 asetukset ovat suunnattu edistyneemmille k\u00e4ytt\u00e4jille (%1-tila tai korkeampi).\nNe eiv\u00e4t siis ole k\u00e4ytett\u00e4viss\u00e4 %2-k\u00e4ytt\u00e4j\u00e4tilassa. health.explain.error=Torrent-tiedoston kanssa on ongelma - katso lis\u00e4tietoja Tila-sarakkeesta tai Yhteys-sarakkeen ilmaisimen ty\u00f6kaluvihjeest\u00e4. GeneralView.label.trackerscrapeupdate=Tee pikap\u00e4ivitys PeersView.piece=Viimeisin osa PeersView.piece.info=Viimeisimm\u00e4n k\u00e4ytt\u00e4j\u00e4lt\u00e4 pyydetyn osan numero PiecesView.priority=Prioriteetti PiecesView.priority.info=Osan valmistumisprioriteetti. PiecesView.speed=Nopeus PiecesView.speed.info=Hitaiden k\u00e4ytt\u00e4jien ei anneta h\u00e4irit\u00e4 nopeasti tulevien osien lataamista. TableColumn.header.AvgAvail.info=Osien saatavuuslukujen summa / osien m\u00e4\u00e4r\u00e4ll\u00e4 / yhteyksien m\u00e4\u00e4r\u00e4ll\u00e4. TableColumn.header.AvgAvail=Keskim. saatavuus/osa ConfigView.label.strictfilelocking=Lukitse tiedostot kirjoittamisen varalta torrent-tiedostojen kesken MyTorrentsView.menu.checkfilesexist=Tarkasta tiedostojen olemassaolo MyTorrentsView.menu.rescanfile=Tarkasta keskener\u00e4iset osat uudelleen s\u00e4\u00e4nn\u00f6llisesti MyTorrentsView.menu.clear_resume_data=Tyhjenn\u00e4 nopean latauksen jatkamisen tiedot Plugin.extseed.name=Ulkoiset l\u00e4hteet Plugin.localtracker.name=L\u00e4hiverkkok\u00e4ytt\u00f6 Plugin.localtracker.info=Vuze-asiakasohjelmien yhteisk\u00e4ytt\u00f6\u00e4 voidaan tehostaa l\u00e4hiverkossa ja palomuurisuojatussa ymp\u00e4rist\u00f6ss\u00e4. T\u00e4m\u00e4 lis\u00e4osa muodostaa suorat tiedonsiirtoyhteydet asiakasohjelmien v\u00e4lille ja parantaa n\u00e4in siirtonopeuksia. Plugin.localtracker.enable=Tarkkaile l\u00e4hiverkkoa Vuze-k\u00e4ytt\u00e4jien varalta azinstancehandler.alert.portclash=Porttivastaavuus havaittu LAN:ssa: %1 toisen Vuze-k\u00e4ytt\u00e4j\u00e4n k\u00e4yt\u00f6ss\u00e4, valitse toinen portti sis\u00e4\u00e4ntulevalle TCP- ja UDP-liikenteelle (v\u00e4lilt\u00e4 %2 ja %3). ConfigView.section.transfer.lan=L\u00e4hiverkko ConfigView.section.transfer.lan.tooltip=L\u00e4hiverkkokohtaiset asetukset ConfigView.section.transfer.lan.uploadrate=kB/s, enimm\u00e4isl\u00e4hetysnopeus l\u00e4hiverkossa (0 = rajoittamaton) ConfigView.section.transfer.lan.uploadrate.tooltip=Erillinen enimm\u00e4isl\u00e4hetysnopeusrajoitus, jota k\u00e4ytet\u00e4\u00e4n l\u00e4hiverkon sis\u00e4isess\u00e4 liikenteess\u00e4. ConfigView.section.transfer.lan.downloadrate=kB/s, enimm\u00e4islatausnopeus l\u00e4hiverkossa (0 = rajoittamaton) ConfigView.section.transfer.lan.downloadrate.tooltip=Erillinen enimm\u00e4islatausnopeusrajoitus, jota k\u00e4ytet\u00e4\u00e4n l\u00e4hiverkon sis\u00e4isess\u00e4 liikenteess\u00e4. TorrentOptionsView.title.short=Asetukset TorrentOptionsView.title.full=Asetukset TorrentOptionsView.param.max.peers=Yhteyksien enimm\u00e4ism\u00e4\u00e4r\u00e4 (0 = rajoittamaton) ConfigView.section.connection.encryption.require_encrypted_transport=Vaadi salattu liikenne ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Pakottaa k\u00e4ytt\u00e4m\u00e4\u00e4n salattua liikennett\u00e4 yhteyksiss\u00e4 k\u00e4ytt\u00e4jiin. ConfigView.section.connection.encryption.min_encryption_level=Salauksen v\u00e4himm\u00e4istaso ConfigView.section.connection.encryption.min_encryption_level.tooltip=Plain - pelkk\u00e4 k\u00e4ttelyvaihe\nRC4 - t\u00e4ysi salaus\nKorkeampi salaustaso vaatii enemm\u00e4n suoritinaikaa. Peers.column.Encryption=Salaus Peers.column.Encryption.info=K\u00e4ytett\u00e4v\u00e4n salauksen taso. ConfigView.section.connection.encryption.encrypt.info=Jos salaus on k\u00e4yt\u00f6ss\u00e4, et voi yhdist\u00e4\u00e4 k\u00e4ytt\u00e4jiin, joiden asiakasohjelmat\neiv\u00e4t tue salausta (ellet m\u00e4\u00e4rittele salauksenohitusasetuksia k\u00e4ytt\u00f6\u00f6n alempana). ConfigView.section.connection.encryption.encrypt.info.link=Katso lis\u00e4tietoja t\u00e4st\u00e4 MainWindow.sr.status.tooltip.ok=Jakosuhde riitt\u00e4v\u00e4 (%1) MainWindow.sr.status.tooltip.poor=Jakosuhde alhainen: %1 < 0.9 MainWindow.sr.status.tooltip.bad=Jakosuhde eritt\u00e4in alhainen: %1 < 0.5 ConfigView.section.style.status=Tilarivi: ConfigView.section.style.status.show_sr=Jakosuhde ConfigView.section.style.status.show_nat=NAT-tila ConfigView.section.style.status.show_ddb=Hajautetun tietokannan tila ConfigView.section.style.status.show_ipf=IP-suotimien toiminta ConfigView.section.connection.encryption.encrypt.group=Liikenteen salaaminen/peitt\u00e4minen ConfigView.section.connection.encryption.encrypt.fallback_info=Kumpi tahansa alla olevista asetuksista sallii yhteydet ep\u00e4yhteensopiviin asiakasohjelmiin, mutta poistaa liikenteen salauksen. ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Salli salaamattomat ulosp\u00e4in luotavat yhteydet, jos salattu liikenne ei ole k\u00e4ytett\u00e4viss\u00e4 ConfigView.section.connection.encryption.encrypt.fallback_incoming=Salli salaamattomat sis\u00e4\u00e4ntulevat yhteydet ConfigView.section.connection.encryption=Salaus upnp.selectedinterfaces=Valitut liit\u00e4nn\u00e4t (erota ;-merkill\u00e4, esim. eth0;eth1, tyhj\u00e4 ruutu = kaikki) ConfigView.section.style.defaultSortOrder=Tietojen oletuslajittelu ConfigView.section.style.defaultSortOrder.desc=Laskeva ConfigView.section.style.defaultSortOrder.asc=Nouseva ConfigView.section.style.defaultSortOrder.flip=Viimeisimm\u00e4n vastakohta LoggerView.autoscroll=Automaattinen vieritys Button.selectAll=Valitse kaikki Button.markSelected=Merkitse valitut Button.unmarkSelected=Poista merkinn\u00e4t valituista plugins.basicview.config=Asetukset TorrentOptionsView.param.max.uploads=L\u00e4hetyspaikkojen enimm\u00e4ism\u00e4\u00e4r\u00e4 (v\u00e4hint\u00e4\u00e4n 2) MyTorrentsView.dialog.setPosition.title=Vaihda paikkaa jonossa MyTorrentsView.dialog.setPosition.text=Anna uusi j\u00e4rjestysnumero valitulle torrent-tiedostolle: MyTorrentsView.menu.reposition.manual=Vaihda paikkaa jonossa... ConfigView.section.connection.advanced.info.link=Katso lis\u00e4tietoja t\u00e4st\u00e4 ConfigView.section.connection.advanced.socket.group=Pistokeasetukset ConfigView.section.connection.advanced.bind_port=Sido paikalliseen porttiin (0 = ei k\u00e4yt\u00f6ss\u00e4) ConfigView.section.connection.advanced.bind_port.tooltip=Ulosp\u00e4in luotavat yhteydet sidotaan paikallisesti m\u00e4\u00e4riteltyyn porttiin.\nSaattaa auttaa tilanteissa, joissa NAT-liikennett\u00e4 ohjaavan laitteen kanssa esiintyy ep\u00e4vakautta. ConfigView.section.proxy.group.tracker=Yhteydet seurantapalvelimiin ConfigView.section.proxy.group.peer=Yhteydet k\u00e4ytt\u00e4jiin Pieces.column.Requested=Pyydetty Pieces.column.Requested.info=Voidaanko osaa pyyt\u00e4\u00e4 ladattavaksi edelleen. ConfigView.label.maxuploadsseeding=Vaihtoehtoinen oletusm\u00e4\u00e4r\u00e4 ainoastaan l\u00e4hetett\u00e4ess\u00e4 MyTorrentsView.filter=Suodin popup.error.hideall=Piilota kaikki ConfigView.section.style.dataStatsOnly=N\u00e4yt\u00e4 tilastot vain varsinaisesta siirrett\u00e4v\u00e4st\u00e4 tiedosta (ei yhteysk\u00e4yt\u00e4nn\u00f6n tietoja) ConfigView.section.style.separateProtDataStats=N\u00e4yt\u00e4 tilastot eriteltyn\u00e4 siirrett\u00e4v\u00e4st\u00e4 tiedosta ja yhteysk\u00e4yt\u00e4nn\u00f6st\u00e4 (muodossa "tieto (yhteysk\u00e4yt\u00e4nt\u00f6)") MyTorrentsView.dialog.setFilter.title=Muokkaa suodinta MyTorrentsView.dialog.setFilter.text=%1 suodatetaan sy\u00f6tetyn tekstin perusteella. K\u00e4yt\u00e4 |-merkki\u00e4 (putkimerkki) suodattaaksesi useilla termeill\u00e4. MyTorrentsView.filter.tooltip=Ctrl+X vaihtaa RegEx-haun ja normaalin haun v\u00e4lill\u00e4.\nK\u00e4yt\u00e4 |-merkki\u00e4 (putkimerkki) suodattaaksesi useilla termeill\u00e4. MyTorrentsView.clearFilter.tooltip=Tyhjenn\u00e4 suodin MyTorrentsView.menu.filter=Suodata torrent-tiedostoja... ConfigView.section.file.resume.recheck.all=Tarkasta kaatumisen j\u00e4lkeen tiedostot kokonaisuudessaan (muutoin vain viimeisen tallennuksen aktiiviset osat tarkastetaan) ConfigureWizard.language.choose=Valitse kieli: popup.closing.in=Suljetaan autom. %1 sekunnissa popup.more.waiting=%1 viesti(\u00e4) j\u00e4ljell\u00e4... # > 2402 popup.download.finished=Lataus valmistunut: "%1". popup.file.finished=Lataus valmistunut: "%1". ConfigView.auto=Automaattinen Plugin.localtracker.autoadd.info=Lis\u00e4\u00e4 automaattisesti seuraavat l\u00e4hiverkon k\u00e4ytt\u00e4j\u00e4t (esim. 1.2.3.4, erota osoitteet ;-merkill\u00e4) Plugin.localtracker.autoadd=K\u00e4ytt\u00e4j\u00e4t Plugin.localtracker.networks.info=K\u00e4sittele seuraavia verkkoalueita l\u00e4hiverkkoina (esim. 145.227.*.*, erota verkot ;-merkill\u00e4) Plugin.localtracker.networks=L\u00e4hiverkot MainWindow.menu.view.plugins.logViews=Lokiseurannat SpeedView.stats.autospeed=Automaattinen l\u00e4hetysnopeuden asettaminen SpeedView.stats.autospeed.disabled=T\u00e4m\u00e4 ominaisuus joko ei ole k\u00e4ytett\u00e4viss\u00e4 (hajautetun tietokannan tulee olla toiminnassa) tai l\u00e4hetysnopeus on asetettu manuaalisesti. SpeedView.stats.idlePing=Joutovasteaika: SpeedView.stats.maxPing=Enimm\u00e4isvasteaika: SpeedView.stats.currentPing=T\u00e4m\u00e4nhetkinen vasteaika: SpeedView.stats.maxUp=Enimm\u00e4isl\u00e4hetysnopeus: ConfigView.pluginlist.unloadSelected=Poista valitut k\u00e4yt\u00f6st\u00e4 ConfigView.pluginlist.scan=Hae uudet ConfigView.section.transfer.autospeed=Auto-Speed (perinteinen) ConfigView.section.transfer.autospeed.tooltip=Automaattisen l\u00e4hetysnopeuden asetukset ConfigView.section.transfer.autospeed.info=Automaattisella enimm\u00e4isl\u00e4hetysnopeusrajoituksen asettamisella v\u00e4ltet\u00e4\u00e4n verkon liian suuri kuormittuminen.\n\nAlla olevat raja-arvot ovat k\u00e4yt\u00f6ss\u00e4, kun automaattinen l\u00e4hetysnopeuden asettaminen ja hajautettu tietokanta ovat k\u00e4yt\u00f6ss\u00e4. ConfigView.section.transfer.autospeed.minupload=%1, v\u00e4himm\u00e4isl\u00e4hetysnopeus ConfigView.section.transfer.autospeed.minupload.tooltip=L\u00e4hetysnopeutta ei normaalisti lasketa automaattisesti t\u00e4m\u00e4n rajan alle. ConfigView.section.transfer.autospeed.maxupload=%1, enimm\u00e4isl\u00e4hetysnopeus (0 = rajoittamaton) ConfigView.section.transfer.autospeed.maxupload.tooltip=L\u00e4hetysnopeutta ei automaattisesti nosteta t\u00e4m\u00e4n rajan yli. ConfigView.section.transfer.autospeed.chokeping=Vasteaika, jonka ylitytty\u00e4 enimm\u00e4isl\u00e4hetysnopeusrajoitusta alennetaan (millisekunteja) ConfigView.section.transfer.autospeed.chokeping.tooltip=Vasteajan ylittyminen on merkki liian suuresta verkon kuormituksesta. ConfigView.section.transfer.autospeed.enableauto=K\u00e4yt\u00e4 automaattista asetusta sek\u00e4 ladattaessa ett\u00e4 l\u00e4hetett\u00e4ess\u00e4 ConfigView.section.transfer.autospeed.enableautoseeding=K\u00e4yt\u00e4 ainoastaan l\u00e4hetett\u00e4ess\u00e4 (kun ei ladata mit\u00e4\u00e4n) ConfigView.pluginlist.column.unloadable=Poistettavissa k\u00e4yt\u00f6st\u00e4 ConfigView.section.transfer.lan.enable=K\u00e4yt\u00e4 erillisi\u00e4 nopeusrajoituksia l\u00e4hiverkossa Plugin.localtracker.wellknownlocals=Ota automaattisesti huomioon paikalliset verkot (esim. 192.168...) TableColumn.header.filesdone=Tiedostot TableColumn.header.filesdone.info=Valm. tiedostot/kaikki TAI valm. ladattavat tiedostot (valm. tiedostot)/kaikki lad. tiedostot (kaikki) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=alustetaan hajautettua tietokantaa... MagnetPlugin.report.searching=etsit\u00e4\u00e4n... MagnetPlugin.report.found=l\u00f6ydettiin %1 MagnetPlugin.report.alive=%1 on tavoitettavissa MagnetPlugin.report.dead=%1 ei ole tavoitettavissa MagnetPlugin.report.tunnel=tunneloidaan kohteeseen %1 MagnetPlugin.report.downloading=ladataan kohteesta %1 MagnetPlugin.report.error=virhe %1 MagnetURLHandler.report.no_sources=torrent-tiedostolle ei l\u00f6ytynyt l\u00e4hteit\u00e4 MagnetURLHandler.report.torrent_size=torrent-tiedoston koko: %1 MagnetURLHandler.report.percent=valmiiina: %1% MagnetURLHandler.report.error=virhe %1 DHTTransport.report.request_all=pyydet\u00e4\u00e4n tietoa siirrett\u00e4v\u00e4ksi kohteelta %1 DHTTransport.report.received_bit=vastaanotettiin %1 - %2 kohteelta %3 DHTTransport.report.complete=valmis DHTTransport.report.timeout=aikakatkaisu, ei vastausta kohteelta %1 DHTTransport.report.rerequest_all=pyydet\u00e4\u00e4n uudestaan tietoa siirrett\u00e4v\u00e4ksi kohteelta %1 DHTTransport.report.rerequest_bit=pyydet\u00e4\u00e4n tietoja %1 - %2 uudestaan kohteelta %3 DHTTransport.report.timeout_some=aikakatkaisu, %1 pakettia vastaanotettu kohteelta %2, mutta siirto ei valmis DHTTransport.report.sending=l\u00e4hetet\u00e4\u00e4n tietoa DHTTransport.report.resending=l\u00e4hetet\u00e4\u00e4n tietoja uudelleen DHTTransport.report.send_complete=l\u00e4hetys valmistunut DHTTransport.report.send_timeout=l\u00e4hetyksen aikakatkaisu ConfigView.section.transfer.autospeed.enabledebug=Kirjaa virheenm\u00e4\u00e4ritystiedot lokiin TableColumn.header.date_added=Lis\u00e4tty TableColumn.header.date_added.info=Ajankohta, jolloin torrent-tiedosto on avattu Vuzeen ConfigView.section.file.hashchecking.smallestfirst=Aloita osien tarkastaminen uudelleen pienimmist\u00e4 latauksista platform.win32.baddll.info=Vuze on havainnut kohteen %1 (%2) olemassaolon. T\u00e4m\u00e4n tiedet\u00e4\u00e4n aiheuttavan ongelmia Vuzen kanssa, esimerkiksi ohjelman kaatuilua ja korkeaa suoritink\u00e4ytt\u00f6\u00e4. Jos havaitset ongelmia, poista ohjelmisto tai aseta se niin, ettei se vaikuta Vuzeen. upnp.ignorebaddevices=Ohita laitteet, jotka eiv\u00e4t vastaa oikein upnp.ignorebaddevices.info=T\u00e4ll\u00e4 hetkell\u00e4 ohitetut laitteet: %1 upnp.ignorebaddevices.reset=Tyhjenn\u00e4 ohitettavien laitteiden lista upnp.ignorebaddevices.reset.action=Tyhjenn\u00e4 upnp.ignorebaddevices.alert=UPnP-laite kohteessa %1 on ohitettu toistuvien yhteysongelmien takia. Katso asetusvaihtoehdot UPnP-m\u00e4\u00e4rityksen asetuksista. TorrentOptionsView.param.max.uploads.when.busy=KB/s - enimm\u00e4isl\u00e4hetysnopeus, kun yleinen raja saavutettu (0 = ei k\u00e4yt\u00f6ss\u00e4) UpdateMonitor.messagebox.verification.failed.title=Asennuksen vahvistus ep\u00e4onnistui UpdateMonitor.messagebox.verification.failed.text=Kohteen '%1' vahvistus ep\u00e4onnistui: %2 UpdateMonitor.messagebox.accept.unverified.title=Vahvistamaton asennus UpdateMonitor.messagebox.accept.unverified.text=Kohdetta '%1' ei voitu vahvistaa Vuzen viralliseksi lis\u00e4osaksi.\nT\u00e4llaisessa tilanteessa asennusta ei kannata jatkaa.\nJatketaanko asennusta? FileView.BlockView.title=Tiedoston osat FileView.BlockView.Done=Valmis FileView.BlockView.Skipped=Ohitettu FileView.BlockView.Active=Aktiivinen FileView.BlockView.Outstanding=Keskener\u00e4inen ConfigView.label.tcplistenport=Sis\u00e4\u00e4ntulevan TCP-liikenteen portti ConfigView.label.udplistenport=UDP-liikenteen portti upnp.portchange.alert=Seuraavat portit on vaihdettu UPnP-laitteen ongelmien v\u00e4ltt\u00e4miseksi: %1 (vanha portti = %2) %3 (vanha portti = %4) ConfigView.section.proxy.username.info=Jos v\u00e4lityspalvelin vaatii k\u00e4ytt\u00e4j\u00e4n todentamisen, vaikka todentamistietoja ei ole m\u00e4\u00e4ritelty, k\u00e4yt\u00e4 k\u00e4ytt\u00e4j\u00e4tunnusta "" ConfigView.label.maxuploadswhenbusymin=Torrent-kohtainen l\u00e4hetysrajoitus k\u00e4ytt\u00f6\u00f6n, kun yleinen raja ollut saavutettuna (sekunteja) MainWindow.menu.help.debug=Luo virheenm\u00e4\u00e4ritystiedot DownloadManager.error.badsize=Virheellinen koko ConfigView.section.NATPMP=NAT-PMP-m\u00e4\u00e4ritys natpmp.info=NAT-PMP on Applen kehitt\u00e4m\u00e4 vaihtoehto UPnP:lle ja sit\u00e4 tukevat uusimmat AirPort-tukiasemat.\n\nHuomaa, ett\u00e4 t\u00e4ll\u00e4 hetkell\u00e4 UPnP-m\u00e4\u00e4rityksen t\u00e4ytyy olla k\u00e4yt\u00f6ss\u00e4, jotta voisit k\u00e4ytt\u00e4\u00e4 NAT-PMP:t\u00e4, sill\u00e4 NAT-PMP-laitetta k\u00e4sitell\u00e4\u00e4n erityistyyppisen\u00e4 UPnP-laitteena. natpmp.enable=K\u00e4yt\u00e4 NAT-PMP:t\u00e4 (huomaa, ett\u00e4 ominaisuus t\u00e4ytyy ottaa k\u00e4ytt\u00f6\u00f6n my\u00f6s AirPort-tukiaseman asetuksista) ConfigView.section.tracker.host.addurls=Lis\u00e4\u00e4 oman seurantapalvelimen p\u00e4ivitysosoite seurattaviin torrent-tiedostoihin ConfigView.filter=hae asetuksia ConfigView.section.files.move=Valmistuneiden siirt\u00e4minen ConfigView.section.file.defaultdir.section=Oletustallennushakemisto ConfigView.section.file.defaultdir.auto=Tallenna automaattisesti oletushakemistoon (ei kysyt\u00e4 erikseen) ConfigView.section.file.defaultdir.bestguess=K\u00e4yt\u00e4 parasta arvausta valittaessa oletustallennushakemistoa ConfigView.section.file.defaultdir.ask=Hakemisto: ConfigView.section.file.defaultdir.lastused=P\u00e4ivit\u00e4 oletustallennushakemistoksi sijainti, jonne on viimeksi tallennettu ConfigView.section.file.config.section=Asetustiedostot ConfigView.section.file.config.currentdir=Asetusten tallennushakemisto: ConfigView.section.torrent.decoding=Merkist\u00f6jen purkaminen ConfigView.section.logging.udptransport=J\u00e4ljit\u00e4 yksityiskohtaiset UDP-siirtojen tiedot Tracker.announce.ignorePeerSeed=Ohitetaan lataajien/l\u00e4hteiden m\u00e4\u00e4r\u00e4. %1 ConfigView.section.connection.encryption.use_crypto_port=K\u00e4yt\u00e4 cryptoport-seurantapalvelinlaajennusta est\u00e4m\u00e4\u00e4n Plain-salatut yhteyden sis\u00e4\u00e4np\u00e4in TorrentOptionsView.param.reset.to.default=Palauta asetukset oletusarvoihin TorrentOptionsView.param.reset.button=Palauta natpmp.routeraddress=Tukiaseman osoite (tyhj\u00e4 ruutu = automaattinen haku) ConfigView.section.style.disableAlertSliding=Poista k\u00e4yt\u00f6st\u00e4 ponnahdusikkunoiden liukuva esiintulo ja aina p\u00e4\u00e4llimm\u00e4isen\u00e4 -tyyli ConfigView.section.transfer.autospeed.maxinc=%1, enimm\u00e4iskasvu yhden kierron aikana ConfigView.section.transfer.autospeed.maxdec=%1, enimm\u00e4isv\u00e4hennys yhden kierron aikana ConfigView.section.transfer.autospeed.enabledownadj=Salli latausnopeuden s\u00e4\u00e4tely ConfigView.section.transfer.autospeed.downadjratio=Lataus- ja l\u00e4hetysnopeuksien suhde (esim. 2.0 -> latausrajoitus on kaksi kertaa l\u00e4hetysrajoitus) ConfigView.section.transfer.autospeed.latencyfactor=Vasteajan ja nopeuden muutokset yhdist\u00e4v\u00e4 tekij\u00e4 (suuri luku v\u00e4hent\u00e4\u00e4 herkkyytt\u00e4) ConfigView.section.transfer.autospeed.reset=Palauta lis\u00e4asetukset oletusarvoihin ConfigView.section.transfer.autospeed.reset.button=Palauta PeerColumn.activationCount=K\u00e4ytt\u00e4j\u00e4t, jotka yritt\u00e4v\u00e4t yhdist\u00e4\u00e4: %1 TableColumn.header.timesincedownload.info=Aikaa kulunut siit\u00e4, kun torrent-tiedostoa viimeksi ladattiin. TableColumn.header.timesincedownload=Lat. joutilasaika TableColumn.header.timesinceupload.info=Aikaa kulunut siit\u00e4, kun torrent-tiedostoa viimeksi l\u00e4hetettiin. TableColumn.header.timesinceupload=L\u00e4h. joutilasaika PeersView.incomingreqcount=Pyynn\u00f6t sis\u00e4\u00e4n PeersView.incomingreqcount.info=K\u00e4ytt\u00e4j\u00e4n tekemien sis\u00e4\u00e4np\u00e4in tulevien pyynt\u00f6jen m\u00e4\u00e4r\u00e4. PeersView.outgoingreqcount=Pyynn\u00f6t ulos PeersView.outgoingreqcount.info=K\u00e4ytt\u00e4j\u00e4lle tehtyjen ulosp\u00e4in menevien pyynt\u00f6jen m\u00e4\u00e4r\u00e4. upnp.mapping.trackerclientudp=Seurantapalvelinyhteyksien UDP-portti upnp.mapping.dhtudp=Hajautettu tietokanta ConfigView.section.connection.nondata.udp.same=K\u00e4yt\u00e4 samaa UDP-porttia hajautetulle tietokannalle ja UDP-seurantapalvelimelle ConfigView.section.connection.tcp.enable=K\u00e4yt\u00e4 TCP:t\u00e4 ConfigView.section.connection.udp.enable=K\u00e4yt\u00e4 UDP:t\u00e4 ConfigView.section.style.showiconbar=N\u00e4yt\u00e4 ty\u00f6kalupalkki MainWindow.menu.view.iconbar=Ty\u00f6kalupalkki MyTorrentsView.menu.rename=Nime\u00e4 uudelleen... MyTorrentsView.menu.rename.displayed=Vaihda n\u00e4ytett\u00e4v\u00e4 nimi MyTorrentsView.menu.rename.save_path=Tallennushakemisto AdvRenameWindow.title=Uudelleennime\u00e4 torrent-lataus AdvRenameWindow.message=Anna uusi nimi ja valitse nimett\u00e4v\u00e4t kohteet: AdvRenameWindow.rename.torrent=Torrent-tiedosto MyTorrentsView.menu.rename.displayed.enter.title=Vaihda torrentin nimi MyTorrentsView.menu.rename.displayed.enter.message=Anna uusi nimi t\u00e4lle torrentille. MyTorrentsView.menu.edit_comment=Muokkaa kommenttia MyTorrentsView.menu.edit_comment.enter.title=Muokkaa kommenttia MyTorrentsView.menu.edit_comment.enter.message=Anna oma kommentti siirrolle: UIDebugGenerator.messageask.title=Virheenm\u00e4\u00e4ritystietojen luominen UIDebugGenerator.messageask.text=Kirjoita kuvaus havaitusta ohjelmavirheest\u00e4. UIDebugGenerator.complete.title=Virheenm\u00e4\u00e4ritystiedot luotu onnistuneesti UIDebugGenerator.complete.text=L\u00e4het\u00e4 tiedosto '%1'.\n\nValitse OK tarkastellaksesi tiedostoa. ConfigView.section.style.showProgramIcon=N\u00e4yt\u00e4 avaavan ohjelman ikoni Nimi-sarakkeessa ConfigView.section.style.showProgramIcon.tooltip=Siirrot-ikkuna t\u00e4ytyy ehk\u00e4 sulkea ja avata uudelleen,\njotta muutos astuu voimaan. swt.alert.cant.update=SWT-ohjelmakirjastoa (ladattu kohteesta "%3") ei voida automaattisesti p\u00e4ivitt\u00e4\u00e4 versiosta %1 versioon %2 (t\u00e4ytyy ladata kohteesta "%4"). Katso lis\u00e4tietoja wikist\u00e4. authenticator.savepassword=Muista salasana ConfigView.section.security.clearpasswords=Tyhjenn\u00e4 muistetut salasanat ConfigView.section.security.clearpasswords.button=Tyhjenn\u00e4 Content.alert.notuploaded.title=Siirto ei valmis Content.alert.notuploaded.text=Julkaisemasi kohteen '%1' siirto ei ole kokonaan valmis. Jos aiot %2 nyt, lataajilla ei ole mahdollisuutta saada latausta valmiiksi.\n\nHaluatko varmasti %2? Content.alert.notuploaded.multi.title=Siirrot ei valmiita Content.alert.notuploaded.multi.text=%1 julkaisemasi kohteen siirto ei ole kokonaan valmis. Jos aiot %2 nyt, lataajilla ei ole mahdollisuutta saada latauksia valmiiksi. Haluatko varmasti %2?\n\nKohteet, joita ei ole l\u00e4hetetty tarpeeksi:\n%3 Content.alert.notuploaded.stop=pys\u00e4ytt\u00e4\u00e4 Content.alert.notuploaded.quit=sulkea Vuzen TorrentInfoView.torrent.encoding=Torrent-tiedoston koodaus TorrentInfoView.columns=Siirrot-ikkunan sarakkeet progress.window.title=Toiminto meneill\u00e4\u00e4n progress.window.msg.filemove=Odota, ett\u00e4 tiedoston siirto/uudelleennime\u00e4minen valmistuu. ConfigView.label.popup.timestamp=N\u00e4yt\u00e4 aikaleimat ponnahdusikkunoissa ConfigView.label.popup.autohide=Ponnahdusikkunoiden piilotusaika (sekunteja, ei koske virheviestej\u00e4, 0 = ei automaattista piilotusta) ConfigView.label.popup.suppress_alerts=Piilota ilmoitukset (uusista tiedotetaan tilarivill\u00e4) ConfigView.label.popup.use_message_boxes=K\u00e4yt\u00e4 sanomaikkunoita ponnahdusikkunoiden sijaan ConfigView.label.popup.show=N\u00e4yt\u00e4 kaikki menneet ilmoitukset ConfigView.label.popup.show.button=N\u00e4yt\u00e4 ConfigView.label.please.visit.here=Katso lis\u00e4tietoja t\u00e4st\u00e4 ConfigView.section.ipfilter.enable.descriptionCache=Tallenna kuvaukset osoitealueista v\u00e4liaikaistiedostoon ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Jos tietoja ei tallenneta, kuvauksia ei muisteta. OpenTorrentWindow.filesInfo=Ladataan %1/%2 OpenTorrentWindow.diskUsage=%1/%2 ConfigView.label.openmytorrents=Avaa siirrot k\u00e4ynnistett\u00e4ess\u00e4 ConfigView.label.open_transfer_bar_on_start=Avaa Siirrot-palkki k\u00e4ynnistett\u00e4ess\u00e4 ConfigView.section.style.DNDalwaysInIncomplete=N\u00e4yt\u00e4 ei-ladattavia tiedostoja sis\u00e4lt\u00e4v\u00e4t torrent-tiedostot aina keskener\u00e4isiss\u00e4 siirroissa OpenTorrentWindow.mb.noGlobalDestDir.title=Tallennushakemistoa ei kelpaa OpenTorrentWindow.mb.noGlobalDestDir.text=Tallennushakemisto '%1' on virheellinen. OpenTorrentWindow.mb.noDestDir.title=Tallennushakemistoa ei l\u00f6ytynyt OpenTorrentWindow.mb.noDestDir.text=Tallennushakemistoa '%1' torrent-tiedostolle '%2' ei ole olemassa tai se on virheellinen. OpenTorrentWindow.mb.notValid.title=Torrent-tiedoston avaaminen OpenTorrentWindow.mb.notValid.text=Torrent-tiedostoa '%1' ei voitu avata. Jos olet avaamassa l\u00e4hett\u00e4mist\u00e4 varten, varmista ett\u00e4 itse l\u00e4hetett\u00e4v\u00e4t tiedostot ovat olemassa. OpenTorrentWindow.mb.notTorrent.title=Virhe tiedoston avauksessa OpenTorrentWindow.mb.notTorrent.text=Tiedostoa '%1' ei voitu avata. Se ei vaikuta olevan torrent-tiedosto.\n\nTiedostosta saatuja tietoja:\n%2 ConfigView.label.pause.downloads.on.exit=Aseta siirrot keskeytettyyn tilaan lopetettaessa ConfigView.label.resume.downloads.on.start=Jatka keskeytettyj\u00e4 siirtoja k\u00e4ynnistett\u00e4ess\u00e4 kun alustus on valmistunut UIDebugGenerator.message.cancel.title=Virheenm\u00e4\u00e4ritystietojen luonti peruutettu UIDebugGenerator.message.cancel.text=Et kirjoittanut mink\u00e4\u00e4nlaista kuvausta havaitsemastasi ohjelmavirheest\u00e4. Ongelman esiintyminen saattaa olla itsest\u00e4\u00e4n selv\u00e4\u00e4 sinulle, mutta kehitt\u00e4j\u00e4t joutuisivat n\u00e4in vain arvailemaan ongelman taustoja ja ilmenemistilannetta.\n\nVirheenm\u00e4\u00e4ritystietojen luominen ja l\u00e4hett\u00e4minen on peruutettu. ConfigView.section.connection.group.http.info=HTTP-pohjaisen l\u00e4hett\u00e4misen tuki ConfigView.section.connection.http.enable=Ota k\u00e4ytt\u00f6\u00f6n ConfigView.section.connection.http.port=Sis\u00e4\u00e4ntulevien pyynt\u00f6jen portti ConfigView.section.connection.http.portoverride=Oman seurantapalvelimen HTTP-portin ohitus (0 = ei k\u00e4yt\u00f6ss\u00e4) window.update.noupdates.title=Ei p\u00e4ivityksi\u00e4 saatavilla window.update.noupdates.text=T\u00e4ll\u00e4 hetkell\u00e4 ei ole uusia p\u00e4ivityksi\u00e4 saatavilla. ConfigView.label.bindip.details=Esimerkki: "192.168.1.5;eth0;eth1[2]" sitoo m\u00e4\u00e4ritetyn IP-osoitteen kaikkiin ensimm\u00e4isen liit\u00e4nn\u00e4n IP-osoitteisiin ja toisen liit\u00e4nn\u00e4n kolmanteen IP-osoitteeseen.\nEnsimm\u00e4ist\u00e4 IP-osoitetta k\u00e4ytet\u00e4\u00e4n kaikille palveluille, muut on tarkoitettu kuorman tasaamista varten.\nK\u00e4ytett\u00e4viss\u00e4 ovat seuraavat liit\u00e4nn\u00e4t:\n%1 ConfigView.label.mindownloads=Yht\u00e4aikaisten latausten v\u00e4himm\u00e4ism\u00e4\u00e4r\u00e4 UI.cannot_submit_blank_text=Sy\u00f6t\u00e4 arvo. crypto.alert.as.warning='%1' -verkossa tiedet\u00e4\u00e4n tapahtuvan BitTorrent-liikenteen suodatusta. Vuzen liikenteen salaaminen on otettu automaattisesti k\u00e4ytt\u00f6\u00f6n - voit halutessasi muokata salausasetuksia asetuksista. ConfigView.section.interface.alerts=Ilmoitukset ConfigView.label.popupdownloadadded=Ilmoita siirron lis\u00e4\u00e4misest\u00e4 ponnahdusikkunalla popup.download.added="%1" lis\u00e4tty Siirtoihin. MessageBoxWindow.nomoreprompting=\u00c4l\u00e4 huomauta jatkossa TorrentOptionsView.param.max.seeds=Yhteyksien enimm\u00e4ism\u00e4\u00e4r\u00e4 l\u00e4hett\u00e4jiin (0 = k\u00e4yt\u00e4 yleist\u00e4 yhteysrajoitusta) TorrentOptionsView.param.alternative.value.enable=Vaihtoehtoinen m\u00e4\u00e4r\u00e4 ainoastaan l\u00e4hetett\u00e4ess\u00e4 ConfigView.section.proxy.check.on.start=Tarkasta v\u00e4lityspalvelimen tila k\u00e4ynnistett\u00e4ess\u00e4 TransferStatsView.legend.pingaverage=Keskim\u00e4\u00e4r\u00e4inen TransferStatsView.legend.ping1=Kohde 1 TransferStatsView.legend.ping2=Kohde 2 TransferStatsView.legend.ping3=Kohde 3 ConfigView.section.interface.enabletray._mac=N\u00e4yt\u00e4 Vuzen kuvake tilapalkissa (vaatii uudelleenk\u00e4ynnistyksen) ConfigView.label.closetotray._mac=Sulkeminen piilottaa tilapalkkiin ConfigView.label.minimizetotray._mac=Pienent\u00e4minen piilottaa tilapalkkiin OpenTorrentWindow.mb.existingFiles.title=Tiedostot jo olemassa OpenTorrentWindow.mb.existingFiles.text=Seuraavat tiedostot ovat jo olemassa kohdehakemistoissa:\n\n%1\nJos jatkat, Vuze tarkastaa yll\u00e4olevien tiedostojen sis\u00e4ll\u00f6n vastaavuuden ja ylikirjoittaa ne tarvittaessa. splash.unloadingTorrents=Poistetaan torrent-tiedostoja muistista splash.unloadingTorrent=Poistetaan torrent-tiedostoa muistista ConfigView.section.file.defaultdir.autorename=Nime\u00e4 samannimiset, mutta sis\u00e4ll\u00f6lt\u00e4\u00e4n erilaiset tiedostot automaattisesti uudelleen ConfigView.section.file.defaultdir.autorename.tooltip=T\u00e4m\u00e4 est\u00e4\u00e4 torrent-tiedoston k\u00e4sitt\u00e4mien tiedostojen ylikirjoittamisen toisen torrent-tiedoston samannimisill\u00e4 tiedostoilla. alert.raised.at.close=(Viesti Vuzen edelliselt\u00e4 sulkemiskerralta) Plugin.trackerpeerauth.name=K\u00e4ytt\u00e4j\u00e4valtuutus Plugin.trackerpeerauth.info=T\u00e4t\u00e4 lis\u00e4osaa k\u00e4ytet\u00e4\u00e4n yhdess\u00e4 seurantapalvelimien toimintojen kanssa varmistamaan k\u00e4ytt\u00e4jien oikeudet torrent-tiedostoihin. Peers.column.maxupspeed=Enim.l\u00e4h.nopeus Peers.column.maxdownspeed=Enim.lat.nopeus MyTorrents.items.DownSpeedLimit.disabled=Ei ladata Peers.column.lan=L\u00e4hiverkko upnp.selectedaddresses=Osoitteet (erota ;-merkill\u00e4, etumerkit: - est\u00e4\u00e4, + sallii, tyhj\u00e4 ruutu = mik\u00e4 tahansa) upnp.alert.multipledevice.warning=Useita UPnP-laitteita havaittu - tarkasta vaativatko kaikki porttim\u00e4\u00e4ritykset (katso UPnP-loki ja -asetukset) UpdateMonitor.messagebox.restart.title=Ohjelmap\u00e4ivitys UpdateMonitor.messagebox.restart.text=Uusi t\u00e4rke\u00e4 ohjelmap\u00e4ivitys ladattu - Vuze t\u00e4ytyy k\u00e4ynnist\u00e4\u00e4 nyt uudelleen, jotta p\u00e4ivitys voidaan asentaa. PiecesView.BlockView.Have=Valmis PiecesView.BlockView.NoHave=Puuttuu PiecesView.BlockView.Header=%1 sarake(tta), %2 rivi(\u00e4), %3 osa(a) ConfigView.section.update.autodownload=Lataa p\u00e4ivitykset automaattisesti ja ilmoita kun ollaan valmiita asentamaan Peers.column.peer_id=Tunniste Peers.column.peer_id.info=K\u00e4ytt\u00e4j\u00e4n tunniste luettavassa muodossa. Peers.column.peer_byte_id=Tunniste Peers.column.peer_byte_id.info=K\u00e4ytt\u00e4j\u00e4n tunniste tavumuodossa. Peers.column.handshake_reserved=K\u00e4ttelybitit Peers.column.handshake_reserved.info=K\u00e4ttelyvaiheessa asetetut varatut bitit. Peers.column.client_identification=Asiakasohjelma (raaka) Peers.column.client_identification.info=Asiakasohjelman nimi raakamuodossa - hy\u00f6dyllinen virheenm\u00e4\u00e4rityksess\u00e4. dht.warn.user=Varoita mahdollisista NAT-/porttiohjausongelmista ConfigView.label.openbar.incomplete=Avaa seurantapalkki automaattisesti ladattaville ConfigView.label.openbar.complete=l\u00e4hetett\u00e4ville torrent-tiedostoille ConfigView.label.transferbar.remember_location=Muista Siirrot-palkin viimeisin sijainti ConfigView.section.transfer.autospeed.forcemin=%1, pakotettu l\u00e4hetysnopeus m\u00e4\u00e4ritett\u00e4ess\u00e4 vasteajan pohjavertailuarvoa MainWindow.menu.tools.speedtest=Nopeustesti speedtest.wizard.title=Nopeustesti speedtest.wizard.run=Suorita nopeustesti speedtest.wizard.test.mode.updown=l\u00e4hetys ja lataus speedtest.wizard.test.mode.up=l\u00e4hetys speedtest.wizard.test.mode.down=lataus SpeedTestWizard.test.panel.currinfo=BitTorrent-pohjainen yhteysnopeustesti. SpeedTestWizard.test.panel.label=Testin tyyppi: SpeedTestWizard.test.panel.already.running=Testi on jo k\u00e4ynniss\u00e4! SpeedTestWizard.test.panel.not.accepted=Testipyynt\u00f6\u00e4 ei hyv\u00e4ksytty: SpeedTestWizard.test.panel.abort=Keskeyt\u00e4 SpeedTestWizard.test.panel.abort.countdown=Aikaa keskeytt\u00e4miseen: SpeedTestWizard.test.panel.test.countdown=Aikaa valmistumiseen: SpeedTestWizard.test.panel.testfailed=Testi ep\u00e4onnistui SpeedTestWizard.test.panel.aborted=Testi keskeytetty manuaalisesti. SpeedTestWizard.test.panel.enc.label=Liikenteen salaus: SpeedTestWizard.test.panel.standard=normaali SpeedTestWizard.test.panel.encrypted=salattu SpeedTestWizard.set.upload.button.apply=K\u00e4yt\u00e4 SpeedTestWizard.set.upload.result=Testin tulokset SpeedTestWizard.set.upload.bytes.per.sec=kilotavua/s SpeedTestWizard.set.upload.bits.per.sec=bitti\u00e4/s SpeedTestWizard.finish.panel.title=Nopeustesti suoritettu! SpeedTestWizard.finish.panel.click.close=Nopeustesti suoritettu onnistuneesti, voit sulkea t\u00e4m\u00e4n ikkunan Sulje-painikkeella. SpeedTestWizard.finish.panel.max.upload=Enimm\u00e4isl\u00e4hetysnopeus: SpeedTestWizard.finish.panel.max.seeding.upload=- ainoastaan l\u00e4hetett\u00e4ess\u00e4: SpeedTestWizard.finish.panel.max.download=Enimm\u00e4islatausnopeus: SpeedTestWizard.finish.panel.enabled=k\u00e4yt\u00f6ss\u00e4 SpeedTestWizard.finish.panel.disabled=ei k\u00e4yt\u00f6ss\u00e4 SpeedTestWizard.abort.message.scheduled.in=Testi ajastettu alkamaan %1 sekunnin kuluttua SpeedTestWizard.abort.message.unsupported.type=Testin tyyppi\u00e4 ei tueta! SpeedTestWizard.abort.message.manual.abort=Keskeytetty manuaalisesti SpeedTestWizard.abort.message.scheduling.failed=Testin ajastus ep\u00e4onnistui SpeedTestWizard.abort.message.download.added=Lataus %1 lis\u00e4tty testin aikana SpeedTestWizard.abort.message.entered.error=Testilataus aiheutti virhetilanteen '%1' SpeedTestWizard.abort.message.entered.queued=Testilataus jonossa/pys\u00e4ytetyss\u00e4 tilassa SpeedTestWizard.abort.message.interrupted=TorrentSpeedTestMonitorThread-toiminto keskeytyi ennen testin valmistumista SpeedTestWizard.abort.message.execution.failed=Testin suoritus ep\u00e4onnistui SpeedTestWizard.abort.message.failed.peers=Yhteydenmuodostus k\u00e4ytt\u00e4jiin ei onnistunut SpeedTestWizard.abort.message.insufficient.slots=L\u00e4hett\u00e4minen k\u00e4ytt\u00e4jille ei onnistunut - ei vapaita l\u00e4hetyspaikkoja? SpeedTestWizard.abort.message.not.unchoked=Lataaminen k\u00e4ytt\u00e4jilt\u00e4 ei onnistunut, sill\u00e4 kaikki est\u00e4v\u00e4t tiedonsiirron SpeedTestWizard.stage.message.requesting=Pyydet\u00e4\u00e4n testi\u00e4 palvelimelta... SpeedTestWizard.stage.message.preparing=Valmistellaan testi\u00e4... SpeedTestWizard.stage.message.starting=Aloitetaan testi... SpeedTestWizard.stage.message.connect.stats=Yhteystilastot: k\u00e4ytt\u00e4ji\u00e4=%1, lataus ok=%2, l\u00e4hetys ok=%3 window.uiswitcher.title=K\u00e4ytt\u00f6liittym\u00e4n vaihtaminen window.uiswitcher.text=Valitse k\u00e4ytt\u00f6liittym\u00e4, joka vastaa parhaiten tarpeitasi. window.uiswitcher.NewUI.text=* Suositellaan aloitteleville, uusille k\u00e4ytt\u00e4jille\n\n* Helppo, intuitiivinen k\u00e4ytt\u00f6liittym\u00e4\n\n* Vaaditaan julkaisemiseen Vuze -alustalla window.uiswitcher.ClassicUI.title=Perinteinen window.uiswitcher.ClassicUI.text=* Vastaa t\u00e4ysin Azureuksen 2.x-sarjan toimintoja ja ulkoasua\n\n* Vuze -sis\u00e4lt\u00f6\u00e4 ei ladata n\u00e4kyville window.uiswitcher.bottom.text=Valintaa voi vaihtaa helposti j\u00e4lkik\u00e4teen valitsemalla ty\u00f6kalupalkin UI-painikkeen. iconBar.switch.tooltip=K\u00e4ytt\u00f6liittym\u00e4n vaihtaminen VivaldiView.notAvailable=Vivaldi-n\u00e4kym\u00e4 ei k\u00e4ytett\u00e4viss\u00e4. restart.error=Uudelleenk\u00e4ynnistys ep\u00e4onnistui:\n%1\nKatso lis\u00e4tietoja uudelleenk\u00e4ynnistysongelmista. restart.error.oom=Ei vapaata muistia k\u00e4ytett\u00e4viss\u00e4. restart.error.fnf=Tiedostoa '%1' ei l\u00f6ytynyt hakemistosta '%2'. restart.error.pnf=Polkua '%1' ei l\u00f6ytynyt. restart.error.bad=Kelpaamaton tiedostomuoto (%1). restart.error.denied=Kohteen '%1' suorittaminen ei onnistunut. Varmista, ett\u00e4 sinulla on oikeudet suorittaa t\u00e4m\u00e4 ohjelma. TableColumn.header.date_completed=Valmistunut TableColumn.menu.date_added.reset=Nollaa ajankohta ConfigView.section.ipfilter.discardbanning=Vastaanotetun hyl\u00e4tyn/hyv\u00e4n tiedon suhde, jonka j\u00e4lkeen k\u00e4ytt\u00e4j\u00e4 estet\u00e4\u00e4n (0 = ei k\u00e4yt\u00f6ss\u00e4) ConfigView.section.ipfilter.discardminkb=Vaadittu hyl\u00e4tyn tiedon v\u00e4himm\u00e4ism\u00e4\u00e4r\u00e4 (%1) ennen suhdes\u00e4\u00e4nn\u00f6n k\u00e4ytt\u00f6\u00f6nottoa ConfigView.interface.start.advanced=K\u00e4ynnist\u00e4 lis\u00e4n\u00e4kym\u00e4ss\u00e4 (Vuze 2.x -tyyli) MyTorrents.column.ColumnQuality=Laatu MyTorrents.column.ColumnSpeed=Nopeus MyTorrents.column.ColumnProgressETA.2ndLine=J\u00e4ljell\u00e4: %1 MyTorrents.column.ColumnProgressETA.StreamReady=Suoratoisto valmis MyTorrents.column.ColumnProgressETA.PlayableIn=Aikaa toistoon %1 TableColumn.header.Quality=Laatu TableColumn.header.Speed=Nopeus TableColumn.header.RateIt=Arvostele TableColumn.header.Rating=Arvostelu TableColumn.header.SpeedGraphic=Nopeus TableColumn.header.AzProduct=L\u00e4hde TableColumn.header.ProgressETA=Valmistuminen #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=Tyyppi: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=Kojelauta v3.MainWindow.tab.browse=Vuze v3.MainWindow.tab.library=Kirjasto v3.MainWindow.tab.publish=Julkaise v3.MainWindow.tab.advanced=Lis\u00e4n\u00e4kym\u00e4 v3.MainWindow.menu.home=&Kojelauta v3.MainWindow.menu.browse=&Vuze v3.MainWindow.menu.library=K&irjasto v3.MainWindow.menu.publish=&Julkaise v3.MainWindow.menu.advanced=&Lis\u00e4n\u00e4kym\u00e4 v3.MainWindow.menu.view.searchbar=Hakupalkki v3.MainWindow.menu.view.tabbar=V\u00e4lilehtipalkki v3.MainWindow.currentDL=Ladataan parhaillaan v3.MainWindow.button.stream=Suoratoista v3.MainWindow.button.stop=Pys\u00e4yt\u00e4 v3.MainWindow.button.start=K\u00e4ynnist\u00e4 v3.MainWindow.button.pause=Keskeyt\u00e4 v3.MainWindow.button.resume=Jatka v3.MainWindow.button.delete=Tuhoa v3.MainWindow.button.comment=Kommentoi v3.MainWindow.button.viewdetails=Lis\u00e4tiedot v3.MainWindow.button.play=Toista v3.MainWindow.button.cancel=Peruuta v3.MainWindow.button.preview=Esikatselu v3.MainWindow.view.wait=Alustetaan n\u00e4kym\u00e4\u00e4, odota hetki. v3.MainWindow.xofx=%1/%2 v3.MainWindow.Loading=Ladataan, odota hetki. v3.filter-bar=Nimisuodatus: v3.MainWindow.search.defaultText=Etsi... v3.mb.delPublished.title=L\u00e4hett\u00e4misen lopettaminen v3.mb.delPublished.text=Huom.! T\u00e4m\u00e4 toiminto ei poista julkaisemaasi sis\u00e4lt\u00f6\u00e4 ('%1') %3-sivustolta.\n\nValitse Tuhoa vain, jos haluat j\u00e4tt\u00e4\u00e4 julkaisusi kaikkien n\u00e4ht\u00e4v\u00e4ksi ja ladattavaksi, mutta vapauttaa omia resurssejasi. Varmista kuitenkin ensin, ett\u00e4 julkaisu on siirretty kokonaan muiden saataville (kuinka?).\n\nValitse Peruuta, jos aikomuksenasi on poistaa julkaisemasi sis\u00e4lt\u00f6 kokonaan %3-sivustolta. Voit tehd\u00e4 t\u00e4m\u00e4n Julkaise-v\u00e4lilehdelt\u00e4, Published Content -sivulta valitsemalla X-painikkeen haluamasi kohteen vierelt\u00e4.\n\nKatso lis\u00e4tietoja t\u00e4st\u00e4.\n\n v3.mb.delPublished.delete=&Tuhoa v3.mb.delPublished.cancel=&Peruuta v3.mb.openFile.title=Avaa tiedosto v3.mb.openFile.text.known=Vuze Player ei t\u00e4ll\u00e4 hetkell\u00e4 tue t\u00e4t\u00e4 sis\u00e4lt\u00f6\u00e4. Lue k\u00e4ytt\u00e4j\u00e4yhteis\u00f6n laatima Soitto-opas\n Playback Guide saadaksesi lis\u00e4tietoja.\n\nTiedoston tyyppi voi olla: %2 (%3)\n v3.mb.openFile.text.unknown=Vuze Player ei t\u00e4ll\u00e4 hetkell\u00e4 tue t\u00e4t\u00e4 sis\u00e4lt\u00f6\u00e4. Lue k\u00e4ytt\u00e4j\u00e4yhteis\u00f6n laatima Soitto-opas\n Playback Guide saadaksesi lis\u00e4tietoja.\n\nTiedostotyyppi: %2\n v3.mb.openFile.button.play=Soita v3.mb.openFile.button.cancel=Keskeyt\u00e4 v3.mb.openFile.button.guide=Lue soitto-opas v3.mb.openFile.remember=Avaa tiedostot aina kysym\u00e4tt\u00e4 minulta v3.mb.PlayFileNotFound.title=Tiedostoa ei l\u00f6ytynyt v3.mb.PlayFileNotFound.text=Kohteen '%1' tiedostoja ei l\u00f6ytynyt v3.mb.PlayFileNotFound.button.remove=Poista Vuzesta v3.mb.PlayFileNotFound.button.redownload=Lataa uudelleen v3.mb.PlayFileNotFound.button.find=Etsi manuaalisesti... v3.mb.deletePurchased.title=Ostetun sis\u00e4ll\u00f6n tuhoaminen v3.mb.deletePurchased.text=Haluatko varmasti tuhota kohteen '%1'?\n\nT\u00e4m\u00e4 sis\u00e4lt\u00f6 on joko ostettu tai sen lataamiseen vaadittiin sis\u00e4\u00e4nkirjautuminen palveluun. v3.mb.deletePurchased.button.delete=&Tuhoa v3.mb.deletePurchased.button.cancel=&Peruuta v3.topbar.menu.show.logo=Vuze -logo v3.topbar.menu.show.plugin=Lis\u00e4osaalue v3.topbar.menu.show.search=Haku v3.topbar.menu.show.frog=Azureus-logo splash.initializeCore=Alustetaan ydint\u00e4 splash.initializeUIElements=Alustetaan k\u00e4ytt\u00f6liittym\u00e4elementtej\u00e4 ConfigView.section.transfer.autospeedbeta=Autom. l\u00e4h.nopeus (beeta) # ConfigView.section.ipfilter.peerblocking.group=K\u00e4ytt\u00e4jien est\u00e4minen ConfigView.section.ipfilter.autoload.group=Automaattinen suodatinlistan lataaminen ConfigView.section.ipfilter.autoload.file=IP-suodintiedosto ConfigView.section.ipfilter.autoload.info=Tuetut tiedostomuodot ovat DAT (eMule), P2P (PeerGuardian, splist) ja P2B:n versiot 1, 2 ja 3 (PeerGuardian 2). Tiedosto voi olla paikallinen tai se voidaan noutaa URL-osoitteen perusteella, ja se voi olla zip- tai gzip-pakattu tai puhdas tekstitiedosto. URL-osoitteesta tiedosto ladataan automaattisesti uudelleen seitsem\u00e4n p\u00e4iv\u00e4n v\u00e4lein, paikallinen tiedosto minuutin sis\u00e4ll\u00e4 sen korvautumisesta tai muokkaamisesta. ConfigView.section.ipfilter.autoload.loadnow=Lataa splash.loadIpFilters=Ladataan IP-suotimia... SpeedTestWizard.set.upload.title=Aseta l\u00e4hetys- ja latausnopeusrajoitukset SpeedTestWizard.set.download.label=Enimm\u00e4islatausnopeus: SpeedTestWizard.set.upload.label=Enimm\u00e4isl\u00e4hetysnopeus: SpeedTestWizard.name.conf.level.absolute=Absoluuttinen SpeedTestWizard.name.conf.level.high=Korkea SpeedTestWizard.name.conf.level.med=Keskiverto SpeedTestWizard.name.conf.level.low=Matala SpeedTestWizard.name.conf.level.none=Ei mik\u00e4\u00e4n ConfigView.section.transfer.select=Autom. nopeus ConfigView.section.transfer.select.v2=Auto-Speed (beeta) mb.azmustclose.title=K\u00e4ynnistysvirhe mb.azmustclose.text=Vuze t\u00e4ytyy sulkea k\u00e4ynnistysvirheen takia - t\u00e4m\u00e4 todenn\u00e4k\u00f6isesti aiheutti ohjelman suorittamisen j\u00e4rjestelm\u00e4nvalvojan oikeuksilla.\n\nKun Vuze on suljettu, k\u00e4ynnist\u00e4 se uudelleen manuaalisesti. network.ipv6.prefer.addresses=K\u00e4yt\u00e4 IPv6-osoitteita, kun sek\u00e4 IPv6- ett\u00e4 IPv4-osoitteet ovat k\u00e4ytett\u00e4viss\u00e4 network.bindError=Palvelinpistokkeen (server socket) kiinnitys ep\u00e4onnistui, koska yhteensopivia osoitteita ei l\u00f6ytynyt, tarkista sidosasetukset (bind-to-IP). network.enforce.ipbinding=Pakota IP-sidokset k\u00e4ytt\u00f6\u00f6n, vaikka liit\u00e4nt\u00f6j\u00e4 ei olisi saatavilla (est\u00e4\u00e4 yhteydet, jos yksik\u00e4\u00e4n m\u00e4\u00e4ritetyist\u00e4 liit\u00e4nn\u00f6ist\u00e4 ei ole saatavilla) DHTView.title.full_v6=Hajautettu tietokanta (IPv6) ConfigView.pluginlist.loadSelected=Lataa valitut SpeedView.stats.asn=Verkko: SpeedView.stats.estupcap=Enimm\u00e4isl\u00e4hetysnopeus: SpeedView.stats.estdowncap=Enimm\u00e4islatausnopeus: SpeedView.stats.unknown=tuntematon SpeedView.stats.estimate=arvio SpeedView.stats.measured=mitattu SpeedView.stats.measuredmin=mitattu v\u00e4h. SpeedView.stats.manual=kiinte\u00e4 ConfigView.section.transfer.autospeed.networks=Verkon tarkemmat tiedot ConfigView.section.transfer.autospeed.resetnetwork=Palauta oletusarvot ConfigView.section.transfer.autospeed.network.info=Yll\u00e4olevat nopeusrajoitukset lasketaan automaattisesti normaalien siirtojen aikana tai ne saadaan nopeustestin tuloksena. Jos haluat m\u00e4\u00e4ritt\u00e4\u00e4 arvot manuaalisesti, k\u00e4yt\u00e4 alla olevia asetuksia.\nKaikkia muita paitsi tyypilt\u00e4\u00e4n kiinteit\u00e4 arvoja s\u00e4\u00e4det\u00e4\u00e4n tarvittaessa jatkossa automaattisesti.\nSy\u00f6t\u00e4 arvo ja valitse t\u00e4m\u00e4n j\u00e4lkeen sen varmuusrajatyyppi. Huomaa, ett\u00e4 nopeudet ovat yksik\u00f6ss\u00e4 %1. dialog.uiswitcher.restart.title=Uudelleenk\u00e4ynnistys vaaditaan dialog.uiswitcher.restart.text=K\u00e4ytt\u00f6liittym\u00e4n vaihtaminen vaatii Vuzen uudelleenk\u00e4ynnist\u00e4misen. TrayWindow.menu.close=Sulje pikalatauskuvake # Used for peers which we can't determine. PeerSocket.unknown=Tuntematon PeerSocket.fake_client=V\u00e4\u00e4renne PeerSocket.bad_peer_id=Kelpaamaton tunniste PeerSocket.mismatch_id=Poikkeama PeerSocket.unknown_az_style=Tuntematon %1 %2 PeerSocket.unknown_shadow_style=Tuntematon %1 %2 OpenTorrentWindow.mb.askCreateDir.title=Tallennushakemistoa ei ole olemassa OpenTorrentWindow.mb.askCreateDir.text=Tallennushakemistoa '%1' ei ole olemassa.\n\nLuodaanko se nyt? SpeedView.stats.estimatechoke=arvio, esto ConfigTransferAutoSpeed.upload.capacity.usage=L\u00e4hetyskapasiteetin k\u00e4ytt\u00f6 ConfigTransferAutoSpeed.mode=Tila: ConfigTransferAutoSpeed.capacity.used=% kapasiteetista k\u00e4ytetty ConfigTransferAutoSpeed.while.downloading=Ladattaessa: ConfigTransferAutoSpeed.set.dht.ping=Vasteaika-asetus: ConfigTransferAutoSpeed.set.point=asetuskohta (ms) ConfigTransferAutoSpeed.set.tolerance=toleranssi (ms) ConfigTransferAutoSpeed.ping.time.good=Hyv\u00e4: ConfigTransferAutoSpeed.ping.time.bad=Huono: ConfigTransferAutoSpeed.adjustment.interval=Asetusv\u00e4li: ConfigTransferAutoSpeed.skip.after.adjust=Ohita asettamisen j\u00e4lkeen: GeneralView.label.distributedCopies=Jaetut kopiot: PiecesView.DistributionView.title=Osien jakauma PiecesView.DistributionView.NoAvl=Eiv\u00e4t saatavilla PiecesView.DistributionView.SeedAvl=Saatavuusosuus - l\u00e4hteet PiecesView.DistributionView.PeerAvl=Saatavuusosuus - lataajat PiecesView.DistributionView.RarestAvl=Harvinaisimmat: %1 (saat.: %2) PiecesView.DistributionView.weHave=On itsell\u00e4 PiecesView.DistributionView.theyHave=On toisella PiecesView.DistributionView.weDownload=Parhaillaan ladattavat PeersView.gain=Saavutettu PeersView.gain.info=Ladattu m\u00e4\u00e4r\u00e4 v\u00e4hennettyn\u00e4 l\u00e4hetetyll\u00e4 m\u00e4\u00e4r\u00e4ll\u00e4. unix.script.new.title=Uusi k\u00e4ynnistyskomentosarja unix.script.new.text=Uusi Vuzen k\u00e4ynnistyskomentosarja on saatavilla ja se on tallennettu kohteeseen '%1'.\n\nOn suositeltavaa, ett\u00e4 suljet nyt Vuzen ja vaihdat uuteen komentosarjaan ('%2').\n\nJos olet muokannut kattavasti alkuper\u00e4ist\u00e4 komentosarjaa, katso lis\u00e4tietoja seuraavasta artikkelista: AzureusWiki: Unix Script.\n\nJos k\u00e4yt\u00e4t jakeluversion omaa versiota Vuzesta (asennettu esimerkiksi yum:n tai apt-get:n avulla), on suositeltavaa, ett\u00e4 vaihdat Vuzen viralliseen versioon (kaikki asetuksesi s\u00e4ilyv\u00e4t ennallaan). unix.script.new.button.quit=Lopeta nyt unix.script.new.button.continue=My\u00f6hemmin unix.script.new.button.asknomore=\u00c4l\u00e4 huomauta jatkossa unix.script.new.auto.title=Uusi k\u00e4ynnistyskomentosarja unix.script.new.auto.text=Uusi Vuzen k\u00e4ynnistyskomentosarja on saatavilla.\n\nOn suositeltavaa, ett\u00e4 k\u00e4ynnist\u00e4t Vuzen nyt uudelleen. Content.alert.notuploaded.button.stop=&Pys\u00e4yt\u00e4 Content.alert.notuploaded.button.continue=&Jatka l\u00e4hett\u00e4mist\u00e4 Content.alert.notuploaded.button.abort=&\u00c4l\u00e4 lopeta ConfigView.label.checkOnSeeding=Tee resurssiyst\u00e4v\u00e4llinen osien uudelleentarkastus l\u00e4hetett\u00e4ess\u00e4 ConfigView.label.ui_switcher=K\u00e4ytt\u00f6liittym\u00e4n vaihtaminen ConfigView.label.ui_switcher_button=N\u00e4yt\u00e4 SpeedTestWizard.test.panel.explain=L\u00e4hetys- ja latausnopeuksien m\u00e4\u00e4ritt\u00e4minen BitTorrent-protokollan avulla. Valitse testin tyyppi, salaustaso ja Suorita. Testi keskeytyy automaattisesti viimeist\u00e4\u00e4n kahden minuutin kuluttua, normaalisti testi vie kuitenkin vain alle minuutin. Lis\u00e4tietoja on luettavissa wikist\u00e4. SpeedTestWizard.set.upload.hint=Aseta nopeusrajoitukset Vuzen Auto-Speed-algoritmille SpeedTestWizard.set.upload.panel.explain=Alla olevia asetuksia k\u00e4ytt\u00e4\u00e4 Vuzen Auto-Speed-algoritmi, joka on tarkoitettu l\u00e4hetys- ja latausnopeuksien automaattiseen asettamiseen - anna nopeusrajoitukset ja varmuusrajat.\n\nHuom.: Yhteysnopeudet ilmoitetaan yleens\u00e4 kilobittein\u00e4 sekunnissa, mutta alla olevat arvot ovat kilotavuja sekunnissa. SpeedTestWizard.set.limit.conf.level=Varmuusraja SpeedTestWizard.finish.panel.auto.speed=Autom. nopeuden asettaminen: SpeedTestWizard.finish.panel.auto.speed.seeding=- ainoastaan l\u00e4hetett\u00e4ess\u00e4: ConfigTransferAutoSpeed.add.comment.to.log.group=Lis\u00e4\u00e4 kommentti virheenm\u00e4\u00e4rityslokiin ConfigTransferAutoSpeed.add.comment.to.log=Kommentti: ConfigTransferAutoSpeed.log.button=Lis\u00e4\u00e4 ConfigTransferAutoSpeed.algorithm.selector=Automaattinen l\u00e4hetys- ja latausnopeuksien asettaminen ConfigTransferAutoSpeed.algorithm=Algoritmi: ConfigTransferAutoSpeed.auto.speed.classic=Auto-Speed (perinteinen) ConfigTransferAutoSpeed.auto.speed.beta=Auto-Speed (beeta) ConfigTransferAutoSpeed.data.update.frequency=P\u00e4ivitystiheys Alert.failed.update=Ainakin yhden p\u00e4ivityksen asentaminen ep\u00e4onnistui. Katso lis\u00e4tietoja: AzureusWiki: Failed Update [%1] OpenTorrentWindow.mb.existingFiles.partialList=(Vain osittainen listaus - lis\u00e4\u00e4 p\u00e4\u00e4llekk\u00e4isyyksi\u00e4 olemassa.) TableColumn.header.bad_avail_time.info=Aika, jolloin siirrosta on viimeksi ollut saatavilla t\u00e4ysi kopio. TableColumn.header.bad_avail_time=T\u00e4ysi kopio n\u00e4hty MyTorrentsView.menu.exporthttpseeds=HTTP-l\u00e4hteiden URL-osoitteet leikep\u00f6yd\u00e4lle SWT.alert.erroringuithread=Graafisessa k\u00e4ytt\u00f6liittym\u00e4ss\u00e4 ilmeni k\u00e4sittelem\u00e4t\u00f6n virhe. Seurauksena voi ilmet\u00e4 muita virheit\u00e4. ConfigView.label.minannounce=Seurantapalvelimen p\u00e4ivitysten v\u00e4linen v\u00e4himm\u00e4isaika (sekunneissa) ConfigView.label.maxnumwant=Seurantapalvelimen palauttamien yhteystietojen enimm\u00e4ism\u00e4\u00e4r\u00e4 ConfigView.label.announceport=Ohita ilmoitettava TCP-portti (seurantapalvelimet, PEX ja DHT)\n(tyhj\u00e4 ruutu = ei ohitusta, 0 = ei sis\u00e4\u00e4ntulevia yhteyksi\u00e4) ConfigView.label.noportannounce=\u00c4l\u00e4 ilmoita kuuntelevaa porttia seurantapalvelimelle (ei vaikuta PEX- ja DHT-toimintoihin) ConfigView.label.maxseedspertorrent=Yhteyksien oletusenimm\u00e4ism\u00e4\u00e4r\u00e4 l\u00e4hett\u00e4jiin/torrent-tiedosto (0 = rajoittamaton) wizard.webseed=Lis\u00e4\u00e4 HTTP-l\u00e4hteet wizard.webseed.title=HTTP-l\u00e4hteet wizard.webseed.configuration=Lis\u00e4\u00e4 HTTP-l\u00e4hteet: wizard.webseed.adding=Lis\u00e4t\u00e4\u00e4n HTTP-l\u00e4hteit\u00e4 GeneralView.label.private=Yksityinen: GeneralView.yes=Kyll\u00e4 GeneralView.no=Ei ConfigView.label.userequestlimiting=K\u00e4yt\u00e4 latausnopeuden rajoittamiseen pyynt\u00f6jen hidastamista viiv\u00e4stettyjen lukujen sijaan (ei vaikutusta, jos rajoittamaton) ConfigView.label.userequestlimiting.tooltip=Pyynt\u00f6jen rajoittaminen ei ole yht\u00e4 sulava tapa kuin lukujen viiv\u00e4stytt\u00e4minen, mutta se mahdollistaa latausten priorisoinnin perustuen sijoitukseen latausjonossa ja saattaa parantaa verkkotoimintojen suorituskyky\u00e4. ConfigView.label.userequestlimitingpriorities=Keskit\u00e4 latausnopeus latausjonon alkuun, kun enimm\u00e4islatausnopeusrajoitus saavutettu ConfigView.section.logging.timestamp=Aikaleiman muoto Peers.column.timetocomplete=Aikaa j\u00e4ljell\u00e4 Peers.column.timetocomplete.info=Aika, jonka kuluttua k\u00e4ytt\u00e4j\u00e4 on saanut latauksen valmiiksi. ConfigView.section.interface.display.suppress.file.download.dialog=Piilota torrent-tiedostojen lataamisen edistymisest\u00e4 kertovat tiedot ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Kaikki torrent-tiedostojen lataamisesta kertovat tiedot esitet\u00e4\u00e4n tilarivin edistymisraportteina ponnahdusikkunoiden sijaan. FileDownload.canceled=Torrent-tiedoston lataaminen on peruutettu k\u00e4ytt\u00e4j\u00e4n toimesta: %1 Progress.reporting.status.canceled=Peruutettu Progress.reporting.status.finished=Valmis Progress.reporting.status.retrying=Yritet\u00e4\u00e4n uudelleen... Progress.reporting.action.label.retry.tooltip=Yrit\u00e4 operaation suorittamista uudelleen Progress.reporting.action.label.remove.tooltip=Poista t\u00e4m\u00e4 edistymisraportti historiasta Progress.reporting.action.label.cancel.tooltip=Peruuta operaatio Progress.reporting.action.label.detail=Tarkemmat tiedot Progress.reporting.default.error=Toiminto ep\u00e4onnistui Progress.reporting.no.reports.to.display=T\u00e4ll\u00e4 hetkell\u00e4 ei ole edistymisraportteja n\u00e4ytett\u00e4v\u00e4ksi. Progress.reporting.no.history.to.display=Ei tarkempia tietoja n\u00e4ytett\u00e4v\u00e4ksi. Progress.reporting.detail.history.limit=Edistymisraporttien historiaan ei mahdu enemp\u00e4\u00e4 raporttien tarkempia tietoja (raja: %1) - tulevia tietoja ei lis\u00e4t\u00e4 historiaan. Progress.reporting.statusbar.button.tooltip=N\u00e4yt\u00e4 edistymisraportit webui.bindip=Sido IP-osoitteeseen - ei normaalisti tarpeen (*) v3.MainWindow.text.log.in=Kirjaudu sis\u00e4\u00e4n v3.MainWindow.text.log.out=Kirjaudu ulos v3.MainWindow.text.get.started=Rekister\u00f6idy v3.MainWindow.text.my.account=Oma tunnus v3.MainWindow.text.my.profile=Profiili OpenTorrentWindow.simple.open=Sijainti (tiedosto, URL-osoite, tiiviste) Progress.reporting.window.remove.auto=Poista toimettomat raportit automaattisesti Progress.reporting.window.remove.auto.tooltip=Poistaa automaattisesti kaikkien valmiiden, ep\u00e4onnistuneiden ja peruutettujen toimintojen raportit listasta. Progress.reporting.window.remove.now=Poista toimettomat Progress.reporting.window.remove.now.tooltip=Poistaa kaikkien valmiiden, ep\u00e4onnistuneiden ja peruutettujen toimintojen raportit listasta. dhttracker.tracklimitedwhenonline=Kun seurantapalvelin on k\u00e4ytett\u00e4viss\u00e4, k\u00e4yt\u00e4 resurssiyst\u00e4v\u00e4llist\u00e4 seurantaa k\u00e4ytt\u00e4j\u00e4vaihdon varalta TorrentOptionsView.multi.title.short=Torrent-tiedoston asetukset TorrentOptionsView.multi.title.full=Torrent-tiedoston asetukset MyTorrentsView.menu.open_parent_folder=Avaa tallennushakemisto ConfigView.section.style.use_show_parent_folder=N\u00e4yt\u00e4 "%1" oletuksen "%2" sijaan torrent-tiedostovalikoissa ConfigView.section.style.use_show_parent_folder.tooltip=T\u00e4m\u00e4 mahdollistaa torrent-tiedoston kohteet sis\u00e4lt\u00e4v\u00e4n hakemiston avaamisen oikeassa tiedostonhallintaohjelmassa.\nAsetus voi kuitenkin aiheuttaa sen, ett\u00e4 latauksille ei pystyt\u00e4 valitsemaan automaattisesti tallennushakemistoa. PeerManager.status.ps_disabled=Seurantapalvelimen palauttamat tiedot eiv\u00e4t k\u00e4yt\u00f6ss\u00e4 ConfigView.section.stats.exportfiles=Tallenna tarkat tiedot tiedostoista updater.cant.write.to.app.title=Asennushakemisto ei kirjoitettavissa updater.cant.write.to.app.details=Hakemistoon "%1" ei voida kirjoittaa.\n\nT\u00e4m\u00e4 est\u00e4\u00e4 tulevien ohjelmap\u00e4ivitysten asentamisen.\n\nKatso lis\u00e4tietoja wikist\u00e4. plugin.install.class_version_error=T\u00e4m\u00e4 lis\u00e4osa vaatii toimiakseen uudemman version Javasta. v3.MainWindow.tab.minilibrary=Lataukset v3.MainWindow.tab.events=Tapahtumat button.columnsetup.tooltip=Valitse n\u00e4ytett\u00e4v\u00e4t sarakkeet v3.activity.remove.title=Poista viesti v3.activity.remove.text=Haluatko varmasti poistaa t\u00e4m\u00e4n viestin?\n%1 #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=Sulje Menu.show.torrent.menu=N\u00e4yt\u00e4 torrent-tiedostovalikko Menu.show.torrent.menu.tooltip=N\u00e4ytt\u00e4\u00e4 torrent-tiedostovalikon p\u00e4\u00e4valikkopalkissa. #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=Verkon tila plugin.aznetstatus.pingtarget=Tiedustelupakettien/reittihaun kohde ConfigView.section.style.usePathFinder=K\u00e4yt\u00e4 Path Finderia Finderin sijaan menu.sortByColumn=Lajittele sarakkeen '%1' mukaan MyTorrentsView.menu.manual.per_peer=Manuaalinen (k\u00e4ytt\u00e4j\u00e4kohtainen)... MyTorrentsView.menu.manual.shared_peers=Manuaalinen (jaettuna valittujen kesken)... v3.button.removeActivityEntry=Poista viesti v3.splash.initSkin=Alustetaan k\u00e4ytt\u00f6liittym\u00e4olemusta v3.splash.hookPluginUI=Liitet\u00e4\u00e4n lis\u00e4osak\u00e4ytt\u00f6liittym\u00e4 OpenTorrentWindow.mb.notTorrent.cannot.display=Tietoja ei voida n\u00e4ytt\u00e4\u00e4 kunnolla MainWindow.menu.window.zoom.maximize=Suurenna MainWindow.menu.window.zoom.restore=Palauta ImageResizer.image.too.small=Annettu kuva on liian pieni - valitse uusi, jonka koko on v\u00e4hint\u00e4\u00e4n %1 x %2 ImageResizer.title=T\u00e4m\u00e4n ty\u00f6kalun avulla n\u00e4et, milt\u00e4 pikkukuva tulee n\u00e4ytt\u00e4m\u00e4\u00e4n Vuze ssa ImageResizer.move.image=Siirr\u00e4 kuvaa raahaamalla sit\u00e4 ImageResizer.move.image.with.slider=Siirr\u00e4 kuvaa raahaamalla sit\u00e4, muuta kokoa alla olevalla liukus\u00e4\u00e4timell\u00e4 security.crypto.title=Salausavaimen suojaus security.crypto.encrypt=Anna salasana uuden salausavaimesi suojaamiseksi. T\u00e4t\u00e4 salasanaa ei ole mahdollista palauttaa, joten valitse se huolella. security.crypto.decrypt=Anna salasana salausavaimen avaamiseen. security.crypto.reason=Toiminnon syy security.crypto.password=Salasana security.crypto.password2=Salasana uudelleen security.crypto.persist_for=Salasanan s\u00e4ilyvyysaika security.crypto.persist_for.dont_save=\u00c4l\u00e4 tallenna security.crypto.persist_for.session=T\u00e4m\u00e4 istunto security.crypto.persist_for.day=1 p\u00e4iv\u00e4 security.crypto.persist_for.week=1 viikko security.crypto.persist_for.30days=30 p\u00e4iv\u00e4\u00e4 security.crypto.persist_for.forever=Ikuisesti security.crypto.password.mismatch.title=Salasanavirhe security.crypto.password.mismatch=Annetut salasanat eiv\u00e4t ole yhtenevi\u00e4, anna salasana uudelleen. ConfigView.section.security.group.crypto=Julkiset/yksityiset avaimet ConfigView.section.security.resetkey=Tyhjenn\u00e4 avaimet ConfigView.section.security.resetkey.warning.title=Varoitus tietojen menett\u00e4misest\u00e4 ConfigView.section.security.resetkey.warning=Haluatko varmasti tyhjent\u00e4\u00e4 salausavaimesi? Jos tyhjenn\u00e4t avaimet, kaikki niiden avulla salatut tiedot menetet\u00e4\u00e4n pysyv\u00e4sti, eiv\u00e4tk\u00e4 julkisen avaimesi k\u00e4ytt\u00e4j\u00e4t pysty en\u00e4\u00e4 kommunikoimaan kanssasi ilman uutta avainta. ConfigView.section.security.unlockkey=Avaa avaimet ConfigView.section.security.unlockkey.button=Avaa ConfigView.section.security.publickey=Julkinen avain ConfigView.section.security.publickey.undef=Ei viel\u00e4 m\u00e4\u00e4ritelty ConfigView.section.security.resetkey.error.title=Toiminto ep\u00e4onnistui ConfigView.section.security.resetkey.error=Avainten tyhjent\u00e4minen ep\u00e4onnistui ConfigView.section.security.unlockkey.error=Avainten avaaminen ep\u00e4onnistui - salasana ei kelpaa ConfigView.copy.to.clipboard.tooltip=Kopioi leikep\u00f6yd\u00e4lle Views.plugins.azbuddy.title=Yst\u00e4v\u00e4t Browser.popup.error.no.access=Virhe et\u00e4resurssin k\u00e4yt\u00f6ss\u00e4.\nYrit\u00e4 my\u00f6hemmin uudelleen. ConfigView.label.queue.stoponcebandwidthmet=\u00c4l\u00e4 k\u00e4ynnist\u00e4 uusia torrentteja, kun l\u00e4hetys/lataus nopeusraja on saavutettu ConfigView.section.style.forceMozilla=Pakota Vuze k\u00e4ytt\u00e4m\u00e4\u00e4n Mozillaa selain-widgetteihin [vaaditaan xulrunner tai firefox 3; uudelleenk\u00e4ynnistys] ConfigView.section.style.xulRunnerPath=Aseta XulRunner / Firefox -hakemisto k\u00e4sin [Vaaditaan FF3:a varten; uudelleenk\u00e4ynnistys] Button.retry=Yrit\u00e4 uudelleen Button.ignore=Ohita DHTView.general.skew=Vinous: security.crypto.badpw=Salasana oli v\u00e4\u00e4rin ConfigView.section.security.backupkeys=Varmuuskopioi avaimet tiedostoon ConfigView.section.security.backupkeys.button=Varmuuskopio ConfigView.section.security.restorekeys=Palauta avaimet tiedostosta ConfigView.section.security.restorekeys.button=Palauta ConfigView.section.security.op.error.title=Toiminto ep\u00e4onnistui ConfigView.section.security.op.error=Toiminto ep\u00e4onnistui:\n %1 ConfigView.section.security.restart.title=Uudelleenk\u00e4ynnistys tarvitaan ConfigView.section.security.restart.msg=Vuze k\u00e4ynnistyy uudelleen toiminnon viimeistelemiseksi. ConfigView.section.security.system.managed=Avainten suojaus j\u00e4rjestelm\u00e4ss\u00e4 Button.bar.show=N\u00e4yt\u00e4 Button.bar.hide=Piilota Button.bar.share=Jaa Button.bar.add=Lis\u00e4\u00e4 Button.bar.edit=Muokkaa Button.bar.edit.cancel=Muokkaus valmis v3.MainWindow.menu.view.pluginbar=Lis\u00e4osat-palkki MainWindow.dialog.select.vuze.file=Valitse Vuze-tiedosto MainWindow.menu.file.open.vuze=Vuze-tiedosto... metasearch.addtemplate.title=Asenna hakupohja? metasearch.addtemplate.desc=Oletko varma, ett\u00e4 haluat asentaa hakupohjan nimelt\u00e4\u00e4n '%1'? v3.share.private.title=Torrentin jakaminen v3.share.private.text=Valittu torrent on merkitty yksityiseksi (Private Torrent).\n\nEt voi jakaa yksityisi\u00e4 torrentteja. metasearch.addtemplate.dup.title=Duplikaatti hakupohja metasearch.addtemplate.dup.desc=Hakupohja %1 on jo asennettu metasearch.export.select.template.file=Tallenna hakupohja metasearch.import.select.template.file=Avaa hakupohja dialog.uiswitch.title=Vaihda Vuze-k\u00e4ytt\u00f6liittym\u00e4\u00e4n dialog.uiswitch.text=T\u00e4t\u00e4 toimintoa voi k\u00e4ytt\u00e4\u00e4 vain Vuze-k\u00e4ytt\u00f6liittym\u00e4ss\u00e4.\n\nVuzen pit\u00e4\u00e4 uudelleenk\u00e4ynnisty\u00e4. dialog.uiswitch.button=Vaihda Vuze-k\u00e4ytt\u00f6liittym\u00e4\u00e4n v3.MainWindow.button.download=Lataa v3.MainWindow.button.run=K\u00e4ynnist\u00e4 ladattu tiedosto v3.activity.header.downloads=Lataukset v3.activity.header.vuze.news=Vuze-uutiset message.taking.too.long=Toiminto n\u00e4ytt\u00e4\u00e4 kest\u00e4v\u00e4n odotettua pidemp\u00e4\u00e4n.\nPaina 'ESC', jos haluat keskeytt\u00e4\u00e4 operaation message.status.success=Onnistui v3.MainWindow.search.go.tooltip=Suorita haku v3.MainWindow.search.last.tooltip=Palaa hakutuloksiin metasearch.addtemplate.done.title=Hakupohja lis\u00e4tty metasearch.addtemplate.done.desc=Hakupohja '%1' lis\u00e4tty onnistuneesti.\nSit\u00e4 k\u00e4ytet\u00e4\u00e4n jo seuraavaan hakuusi! ConfigView.section.security.nopw=Salasana ei ollut annettu ConfigView.section.security.nopw_v=Salasana ei tiedossa, kirjaudu sis\u00e4\u00e4n Vuzeen fileplugininstall.install.title=Asenna lis\u00e4osa? fileplugininstall.install.desc=Oletko varma, ett\u00e4 haluat asentaan lis\u00e4osan '%1' version %2? fileplugininstall.duplicate.title=Lis\u00e4osan tuplakopio fileplugininstall.duplicate.desc=Lis\u00e4osan '%1' versio %2 on jo asennettuna progress.window.msg.progress=Odota toimenpiteen valmistumista DetailedListView.title=Yksityiskohtainen luettelo ConfigView.section.connection.network.max.outstanding.connect.attempts=Suurin sallittu l\u00e4htevien yhteyksien m\u00e4\u00e4r\u00e4 plugins.init.force_enabled=Vuze havaitsi lis\u00e4osan "%1" olevan estettyn\u00e4 toimimasta - se on sallittu uudelleen Vuzen toiminnan varmistamiseksi. ConfigView.section.connection.prefer.udp=Suosi UDP-yhteyksi\u00e4 iconBar.start=K\u00e4ynnist\u00e4 iconBar.stop=Pys\u00e4yt\u00e4 iconBar.remove=Poista iconBar.up=Yl\u00f6s iconBar.down=Alas iconBar.run=K\u00e4ynnist\u00e4 iconBar.editcolumns=Sarakeasetukset iconBar.top=Ylimm\u00e4ksi iconBar.bottom=Alimmaksi iconBar.queue=K\u00e4ynnist\u00e4 iconBar.open=Lis\u00e4\u00e4 torrent iconBar.share=Jaa iconBar.share.tooltip=Jaa sis\u00e4lt\u00f6\u00e4 iconBar.details=Yksityiskohdat iconBar.comment=Kommentti iconBar.play=Soita iconBar.queue.tooltip=K\u00e4ynnist\u00e4 (aseta jonoon) v3.MainWindow.menu.view.sidebar=Sivupalkki v3.MainWindow.menu.view.toolbars=Ty\u00f6kalupalkit ump.install=Pikap\u00e4ivitys k\u00e4ynniss\u00e4:\nAsennetaan video soittamiseen tarvittava pieni lis\u00e4osa. PluginDeprecation.log.start=T\u00e4m\u00e4 ikkuna sis\u00e4lt\u00e4\u00e4 tietoa lis\u00e4osista, jotak k\u00e4ytt\u00e4v\u00e4t tulevaisuudessa poistettavia Vuzen toiminnallisuuksia.\nSinun ei tarvitse poistaa kyseisten lis\u00e4osien asennusta, mutta sinun pit\u00e4isi p\u00e4ivitt\u00e4\u00e4 lis\u00e4osat uusimpaan versioon.\nJos k\u00e4yt\u00e4t jo lis\u00e4osan uusinta versiota, voisit kopioida t\u00e4m\u00e4n ikkunan sis\u00e4ll\u00f6n Vuzen foorumille:\n \t%1\n\n PluginDeprecation.view=Lis\u00e4osien Debug PluginDeprecation.alert=Lis\u00e4osa on yritt\u00e4nyt k\u00e4ytt\u00e4\u00e4 toimintoa, joka tullaan poistamaan tulevaisuudessa. Katso lis\u00e4tietoja lis\u00e4osien debug-lokista. TableColumn.header.Thumbnail=Kuvake TableColumn.header.Thumbnail.info=Kuvake, joka riippuu sis\u00e4ll\u00f6n tyypist\u00e4. Vuze asettaa sen omalle sis\u00e4ll\u00f6lleen, muutoin se tulee k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4st\u00e4. v3.MainWindow.menu.getting_started=Aloitussivu MainWindow.menu.community=&K\u00e4ytt\u00e4j\u00e4yhteis\u00f6 MainWindow.menu.help.faq=&FAQ (UKK) MainWindow.menu.community.wiki=K\u00e4ytt\u00e4jien Wiki-artikkelit MainWindow.menu.community.forums=K\u00e4ytt\u00e4jien keskustelufoorumi MainWindow.menu.help.support=Apua ja tukea Button.done=Valmis GeneralView.torrent_created_on_and_by=%1 / %2 Button.continue=Jatka Button.preview=Esikatsele sidebar.Library=Kirjasto sidebar.LibraryDL=Lataukset sidebar.LibraryCD=Valmiit authenticator.location=Sijainti authenticator.details=Detaljit v3.MainWindow.menu.showActionBarText=N\u00e4yt\u00e4 teksti Button.remove=Poista Button.send=L\u00e4het\u00e4 Button.back=Takaisin sidebar.LibraryUnopened=Ei-katsotut TableColumn.header.unopened=Uusi Unopened.bigView.header=Uusi ConfigView.section.Subscriptions=Tilaukset v3.activity.button.readall=Merkitse kaikki luetuiksi TableColumn.header.activityNew=Uusi TableColumn.header.activityType=Tyyppi TableColumn.header.activityText=Viesti TableColumn.header.activityDate=Lis\u00e4ysp\u00e4iv\u00e4 TableColumn.header.activityActions=Toimet Search.menu.engines=Hakupohjat #what you've watched? Discover more with a single click... Button.search=Etsi Button.save=Tallenna Button.add=Lis\u00e4\u00e4 message.confirm.delete.title=Vahvista poistaminen message.confirm.delete.text=Haluatko varmasti poistaa '%1'? props.window.title='%1':n ominaisuudet externalLogin.wait=Sivu lautautuu, odota... TableColumn.menu.date_added.time=N\u00e4yt\u00e4/piilota lis\u00e4ysaika subscriptions.view.title=Tilaukset metasearch.template.version.bad=Hakupohjan '%1' asentaminen vaati Vuzen p\u00e4ivitt\u00e4misen metasearch.addtemplate.failed.title=Asennus ep\u00e4onnistui metasearch.addtemplate.failed.desc=Hakupohjan asennus ep\u00e4onnistui: %1 statusbar.feedback=Anna palautetta statusbar.feedback.tooltip=Paina t\u00e4st\u00e4 antaaksesi palautetta sidebar.Activity=Tiedotteet v3.activity.button.watchall=Merkitse kaikki katsotuiksi sidebar.sash.tooltip=F7: Sivupalkin n\u00e4ytt\u00f6/sulkeminen sidebar.expand.tooltip=N\u00e4yt\u00e4 sivupalkki sidebar.dropdown.tooltip=N\u00e4yt\u00e4 sivupalkki valikkona v3.iconBar.up.tooltip=Siirr\u00e4 yl\u00f6s\nPid\u00e4 hiirt\u00e4 painettuna siirt\u00e4\u00e4ksesi ylimm\u00e4ksi v3.iconBar.down.tooltip=Siirr\u00e4 alas\nPid\u00e4 hiirt\u00e4 painettuna siirt\u00e4\u00e4ksesi alimmaksi Button.deleteContent.fromLibrary=Poista Vuzen kirjastosta Button.deleteContent.fromComputer=Poista tietokoneelta v3.deleteContent.message=\nHaluatko poistaa '%1' my\u00f6s tietokoneeltasi, vai poistaa sen vain Vuzen kirjastosta? v3.MainWindow.menu.view.toolbartext=Ty\u00f6kalupalkin tekstit v3.MainWindow.menu.view.asSimpleList=Yksinkertainen luettelo v3.MainWindow.menu.view.asAdvancedList=Kehittynyt luettelo v3.MainWindow.menu.view.statusbar=Tilarivi configureWizard.file.message3=Vuze tallentaa lataamasi tiedostot hakemistoon. Valitse kyseinen hakemisto nyt: v3.deleteContent.applyToAll=Tee toiminto %1 kaikille valituille kohteille ConfigView.label.seeding.firstPriority.ignoreIdleHours=jotka eiv\u00e4t l\u00e4het\u00e4 mit\u00e4\u00e4n v3.MainWindow.menu.contentnetworks=&HD Network v3.MainWindow.menu.contentnetworks.about=HD Networks -tietoa ConfigTransferAutoSpeed.auto.speed.neural=Auto-Speed (Neural,Gudy Alpha) ConfigView.label.autoopen.downloadbars=... torrentin seurantapalkki, kun ConfigView.label.autoopen=Avaa automaattisesti ConfigView.label.autoopen.detailstab=... torrentin yksityiskohdat-sivu, kun ConfigView.label.systray=Ilmoitusalue (System Tray) ConfigView.section.interface.legacy=Perinteiset optiot v3.MainWindow.menu.contentnetworks.manage=HD Networks -asetukset v3.dialog.cnclose.title=%1 suljettu v3.dialog.cnclose.subtitle=Tiedoksi v3.dialog.cnclose.info1=Olet sulkenut er\u00e4\u00e4n HD Networkin v3.dialog.cnclose.info2=Jos haluat avata t\u00e4m\u00e4n HD Networkin uudelleen, voit tehd\u00e4 sen "HD Networks"-valikosta ikkunan yl\u00e4osassa. v3.dialog.cnclose.noshow=\u00c4l\u00e4 n\u00e4yt\u00e4 uudelleen v3.dialog.cnmanage.title=Hallitse HD Network -asetuksia v3.dialog.cnmanage.intro=Voit valita allaolevasta listasta, mitk\u00e4 sis\u00e4lt\u00f6verkot haluat n\u00e4hd\u00e4 "HD Networks"-valikossa TableColumn.header.#.info=Latausj\u00e4rjestyksen numero TableColumn.header.category.info=Luokka, johon torrent-tiedosto on asetettu. TableColumn.header.DateCompleted.info=Torrentin latauksen valmistumisp\u00e4iv\u00e4 TableColumn.header.AzProduct.info=Torrentin l\u00e4hdeverkko TableColumn.header.health.info=Yhteyden ja siirron tila (katso lis\u00e4tietoja Ohje-valikosta). TableColumn.header.maxuploads.info=Hy\u00f6dynnett\u00e4vien l\u00e4hetyspaikkojen enimm\u00e4ism\u00e4\u00e4r\u00e4. TableColumn.header.name.info=Torrent-tiedoston kohteen nimi. TableColumn.header.unopened.info=Tieto siit\u00e4, onko torrent jo avattu TableColumn.header.savepath.info=Kohde, johon tietoja tallennetaan. TableColumn.header.SeedingRank.info=Mit\u00e4 korkeampi luku, sit\u00e4 t\u00e4rke\u00e4mp\u00e4\u00e4 on saada l\u00e4hetetty\u00e4. TableColumn.header.shareRatio.info=Torrent-tiedoston oma l\u00e4hetysm\u00e4\u00e4r\u00e4 suhteessa omaan latausm\u00e4\u00e4r\u00e4\u00e4n. TableColumn.header.size.info=Torrent-tiedoston kohteen koko. TableColumn.header.upspeed.info=Torrent-tiedoston l\u00e4hetysnopeus. TableColumn.header.downspeed.info=Torrent-tiedoston latausnopeus. TableColumn.header.up.info=Kohteen l\u00e4hetysm\u00e4\u00e4r\u00e4. TableColumn.header.down.info=Ladattu m\u00e4\u00e4r\u00e4. TableColumn.header.ProgressETA.info=Yhdist\u00e4 Tila, Valmistuminen, ETA ja nopeus yhteen moniriviseen sarakkeeseen. TableColumn.header.eta.info=Arvioitu aika, jonka kuluttua lataus on valmistunut. Pieces.column.#.info=Osan numero Peers.column.%.info=K\u00e4ytt\u00e4j\u00e4n t\u00e4h\u00e4n menness\u00e4 lataama osuus torrentista TableColumn.header.download.info=Kohteelt\u00e4 ladattu tietom\u00e4\u00e4r\u00e4 TableColumn.header.upload.info=L\u00e4hetetyn tiedon m\u00e4\u00e4r\u00e4 TableColumn.header.downloadspeed.info=Meid\u00e4n lataamisnopeutemme t\u00e4lt\u00e4 kohteelta TableColumn.header.uploadspeed.info=Tiedon l\u00e4hetysnopeus TableColumn.header.lan.info=Samassa LAN-verkossa olevan lataajan indikaattori TableColumn.header.downloadspeedoverall.info=Lataajan arvioitu lataamisnopeus Peers.column.pieces.info=Graafinen esitys k\u00e4ytt\u00e4j\u00e4n lataamista osista TableColumn.header.TableColumnNameInfo=Sarakkeen nimi ja kuvaus TableColumn.header.TableColumnSample=Esimerkki TableColumn.header.TableColumnInfo=Sarakkeen kuvaus TableColumn.header.TableColumnChosenColumn=Valittu sarake label.learnmore=Lis\u00e4tietoja ColumnSetup.title=Sarakeasetukset: '%1' ColumnSetup.explain=Katso valittavissa olevia sarakkeiden listaa vasemmalla, ja lis\u00e4\u00e4 haluamasi oikealla olevaan valittujen sarakkeiden listaan. Voit suodattaa tarjolla olevien listaa alavasemmalla olevilla suodattimilla. Sarakenimien vet\u00e4minen hiirell\u00e4 on mahdollista. ColumnSetup.chosencolumns=Valitut sarakkeet ColumnSetup.proficiency=K\u00e4ytt\u00e4j\u00e4n taidot: ColumnSetup.categories=Luokat: ColumnSetup.filters=Suodatus ColumnSetup.availcolumns=Mahdolliset %1 sarakkeet ColumnSetup.availcolumns.filteredby=Mahdolliset %1 sarakkeet, suodatus %2 devices.view.title=Oheislaitteet ConfigView.label.maxStalledSeeding=Max. 'pys\u00e4htynyt' [0:rajoittamaton] General.percent=Prosenttia MainWindow.menu.help.donate=Tee &lahjoitus DonationWindow.noload.title=Lahjoitukset DonationWindow.noload.text=Lahjoitusikkunan lataaminen ep\u00e4onnistui. Yrit\u00e4 my\u00f6hemmin uudelleen. download.removerules.unauthorised.data=\tPoista my\u00f6s datatiedostot iconBar.transcode=Oheislaite iconBar.transcode.tooltip=Muunna media oheislaitetta varten TableColumn.header.profile=Oheislaite TableColumn.header.device=Oheislaite TableColumn.header.device.info=Kohde-oheislaite # This is the beginning of the word "View". It's right aligned under the icon bar item v3.iconBar.view.big=N\u00e4k v3.iconBar.view.big.tooltip=Yksinkertainen # This is the end of the word "View". It's left aligned under the icon bar item v3.iconBar.view.small=ym\u00e4 v3.iconBar.view.small.tooltip=Kehittynyt luettelo general.dont.ask.again=\u00c4l\u00e4 kysy uudelleen TableColumn.header.duration=Kesto TableColumn.header.resolution=Resoluutio option.askeverytime=Kysy joka kerta option.rememberthis=Muista t\u00e4m\u00e4 asetus label.clickone=Valitse yksi Button.turnon=K\u00e4ynnist\u00e4 ConfigView.label.dm.dblclick=Tuplaklikkaus torrent-n\u00e4kym\u00e4ss\u00e4: ConfigView.option.dm.dblclick.play=Soita/k\u00e4ynnist\u00e4 sis\u00e4lt\u00f6 ConfigView.option.dm.dblclick.details=Avaa torrentin yksityiskohdat ConfigView.option.dm.dblclick.show=N\u00e4yt\u00e4 tiedosto ConfigView.option.dm.dblclick.show._mac=N\u00e4yt\u00e4 tiedosto(t) Finderissa ConfigView.option.dm.dblclick.show._windows=N\u00e4yt\u00e4 tiedosto(t) Windows Explorerissa Button.reload=Lataa uudelleen general.enter.cookies=Ev\u00e4steet (cookies) MyTorrentsView.menu.clear_alloc_data=Resetoi tiedostojen allokointitieto DiskManager.error.nospace=Ei riitt\u00e4v\u00e4sti levytilaa DiskManager.error.nospace_fat32={DiskManager.error.nospace} - tarkista {wiki.fat32} ConfigView.section.file.rename.incomplete=Lis\u00e4\u00e4 p\u00e4\u00e4te keskener\u00e4isiin tiedostoihin dlg.corewait.title=Vuzea k\u00e4ynnistet\u00e4\u00e4n dlg.corewait.text=Odota hetki...\n\nPyynt\u00f6si k\u00e4sitell\u00e4\u00e4n Vuzen k\u00e4ynnistymisen p\u00e4\u00e4tytty\u00e4 library.core.wait=Odota hetki...\nVuze on k\u00e4ynnistym\u00e4ss\u00e4 ConfigView.label.StartUIBeforeCore=K\u00e4ynnist\u00e4 k\u00e4ytt\u00f6liittym\u00e4 ennen Vuzen ydint\u00e4 general.add.friends=Lis\u00e4\u00e4 yst\u00e4vi\u00e4! general.all.friends=Kaikki yst\u00e4v\u00e4t TableColumn.header.class=Luokka rcm.rc_tracker.tt=Valitse selataksesi seurantapalvelinta rcm.rc_hash.tt=Valitse ladataksesi t\u00e4m\u00e4 sis\u00e4lt\u00f6 rcm.rc_title.tt=Valitse etsi\u00e4ksesi t\u00e4t\u00e4 sis\u00e4lt\u00f6\u00e4 TableColumn.menu.maxuploads=# Max l\u00e4hetyspaikkoja ConfigView.label.alwaysShowLibraryHeader=N\u00e4yt\u00e4 otsikko/suodatinrivi aina (Siirrot-ikkuna) ConfigView.section.style.forceSIValues=N\u00e4yt\u00e4 arvot IEC-arvoina riippumatta esitysyksik\u00f6st\u00e4 yhteensopivuussyist\u00e4 (esim. 1MB = 1MiB = 1048576B) ConfigView.label.enableSystrayToolTip=N\u00e4yt\u00e4 nopeustiedot hiiren ollessa kohdalla button.nothanks=Ei kiitos webui.pairingenable=Mahdollista paritus webui.group.access=P\u00e4\u00e4syoikeudet ConfigView.section.Pairing=Paritus pairing.accesscode=Tunnistuskoodi pairing.ac.getnew=Aseta uusi tunnistuskoodi pairing.ac.getnew.create=Luo pairing.ipv4=IPv4-osoite pairing.ipv6=IPv6-osoite pairing.host=Koneen osoite (DNS-nimi) pairing.group.explicit=Erityiset asetukset pairing.explicit.enable=K\u00e4yt\u00e4 erityisasetuksia pairing.explicit.info=Normaalisti IP-erityisasetuksia ei tarvita, koska ne m\u00e4\u00e4rittyv\u00e4t automaattisesti.\n'Koneen osoite' -m\u00e4\u00e4rityst\u00e4 voidaan k\u00e4ytt\u00e4\u00e4 esim. jos sinulla on DynDNS-tili ja soveltuva ohjelmisto dynaamisen IP-osoitteen hallintaan. pairing.op.fail=Paritus ep\u00e4onnistui pairing.alloc.fail=Uuden tunnistuskoodin asetus ep\u00e4onnistui\n%1 pairing.enable=Mahdollista Vuzen ja et\u00e4sovellusten/liittymien paritus pairing.status.info=Tila pairing.status.registered=P\u00e4ivitys onnistui (%1) pairing.status.pending=P\u00e4ivitys suoritetaan %1 pairing.status.initialising=Alustetaan pairing.status.disabled=Pois p\u00e4\u00e4lt\u00e4 pairing.view.registered=Valitse n\u00e4hd\u00e4ksesi rekister\u00f6intitiedot webui.pairing.info.n=Paritus on pois p\u00e4\u00e4lt\u00e4. Katso lis\u00e4tietoja Yhteys->Paritus-asetuksista webui.pairing.info.y=Paritus on mahdollista. Katso lis\u00e4tietoja Yhteys->Paritus-asetuksista. webui.enable=Toiminto k\u00e4yt\u00f6ss\u00e4 (*) ConfigView.section.rss=Paikallinen RSS jne. Button.removeAll=Poista kaikki label.rename=Uudelleennime\u00e4 %1 RCM.column.rc_rank=Sija RCM.column.rc_created=Luotu RCM.column.rc_hash=Tiiviste RCM.column.rc_lastseen=Viimeksi n\u00e4hty RCM.column.rc_level=Taso RCM.column.rc_tracker=Seurantapalvelin rcm.view.heading=Naapuritorrentit rcm.config.enabled=K\u00e4yt\u00f6ss\u00e4 rcm.config.max_results=Tuloksia enint\u00e4\u00e4n rcm.config.max_level=Maksimitaso rcm.search.provider=Parvi wizard.webseedseditor.edit.title=HTTP-l\u00e4hteiden muokkaus wizard.webseedseditor.edit.newseed=Uusi l\u00e4hde MyTorrentsView.menu.editWebSeeds=Muokkaa HTTP-l\u00e4hteit\u00e4 ClientStats.title.full=Asiakasohjelma-tilastot ClientStats.column.count=M\u00e4\u00e4r\u00e4 Scrape.status.cached=Pikap\u00e4ivitys v\u00e4limuistista azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_ca_AD.properties0000644000175000017500000040420111301156004026017 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Fitxer .torrent Main.parameter.usage=\u00das : java org.gudy.azureus2.cl.Main [par\u00e0metres] "fitxer.torrent" "ruta desc\u00e0rrega" Main.parameter.maxUploads=Nombre m\u00e0xim de desc\u00e0rregues simult\u00e0nies Main.parameter.maxSpeed=Velocitat m\u00e0xima de c\u00e0rrega en bytes/seg MainWindow.menu.file=&Fitxer MainWindow.menu.file.open=Obrir MainWindow.menu.file.create=Crear un .torrent MainWindow.menu.file.create.fromfile=Des d'un fitxer MainWindow.menu.file.create.fromdir=&Des d'una carpeta MainWindow.menu.file.export=Exportar un .torrent... MainWindow.menu.file.export.keybinding.mac=Meta+Maj+E MainWindow.menu.file.import=Importar un .torrent... MainWindow.menu.file.import.keybinding.mac=Meta+Maj+I MainWindow.menu.file.closetab=Tancar E&tiqueta MainWindow.menu.file.closetab.keybinding=Meta+T MainWindow.menu.file.closewindow=Tancar &Finestra MainWindow.menu.file.closewindow.keybinding=Meta+Shift+F MainWindow.menu.file.exit=Sortir MainWindow.dialog.choose.file=Seleccioneu el fitxer .torrent MainWindow.menu.file.folder=&Carpeta MainWindow.menu.file.folder.keybinding=Meta+Shift+C MainWindow.dialog.choose.folder=Seleccioni la carpeta MainWindow.menu.view=&Visualitzaci\u00f3 MainWindow.menu.view.show=Mostrar MainWindow.menu.view.mytorrents=Els meus Torrents MainWindow.menu.view.open_global_transfer_bar=Barra de transfer\u00e8ncies MainWindow.menu.view.configuration=Configuraci\u00f3 MainWindow.menu.view.console=C\u00f2nsola MainWindow.menu.view.irc=Client IRC MainWindow.menu.view.allpeers=Tots els iguals MainWindow.menu.view.detailedlist=Llista &detallada MainWindow.menu.closealldetails=Tancar tots els detalls MainWindow.menu.closealldownloadbars=Tancar les barres de desc\u00e0rrega MainWindow.menu.language=Idioma ConfigView.section.language=Idioma MainWindow.menu.window=&Finestra MainWindow.menu.window.minimize=&Minimitzar MainWindow.menu.window.alltofront=Porta-ho tot a &Davant MainWindow.menu.help=Ajuda MainWindow.menu.help.about=Sobre Vuze MainWindow.about.title=Sobre MainWindow.about.section.developers=Desenvolupadors MainWindow.about.section.translators=Traductors MainWindow.about.section.system=Sistema MainWindow.about.section.internet=Internet MainWindow.about.internet.homepage=P\u00e0gina de Vuze MainWindow.about.internet.sourceforge=P\u00e0gina del projecte en Sourceforge MainWindow.about.internet.sourceforgedownloads=Desc\u00e0rregues des de Sourceforge MainWindow.about.internet.bugreports=Informe de fallades MainWindow.about.internet.forumdiscussion=F\u00f2rum General MainWindow.about.internet.wiki=Preguntes m\u00e9s freq\u00fcents al Wiki del Vuze MainWindow.dialog.choose.savepath=Seleccioni la carpeta per a la desc\u00e0rrega MainWindow.dialog.choose.savepath_forallfiles=Seleccioneu la carpeta per a tots els fitxers MainWindow.status.latestversion=Ultima versi\u00f3 MainWindow.status.latestversion.clickupdate=Clic per a actualitzar MainWindow.status.unknown=Desconegut MainWindow.status.checking=Comprovant MyTorrentsView.mytorrents=Els meus Torrents TableColumn.header.name=Nom TableColumn.header.size=Mida TableColumn.header.done=Completat TableColumn.header.done.info=Percentatge fet de la feina actual TableColumn.header.status=Estat TableColumn.header.status.info=Lo que est\u00e0 fent el torrent TableColumn.header.seeds=Llavors TableColumn.header.seeds.info=# llavors connectades a (# llavors total) TableColumn.header.peers=Iguals TableColumn.header.peers.info=# Iguals connectats a (# Iguals total) TableColumn.header.downspeed=Vel. desc\u00e0rrega TableColumn.header.upspeed=Vel. c\u00e0rrega TableColumn.header.eta=Estimaci\u00f3 Temps Acabar TableColumn.header.tracker=Estat Rastrejador TableColumn.header.tracker.info=Estat del rastrejador TableColumn.header.trackernextaccess=Acc\u00e9s al seg\u00fcent rastrejador TableColumn.header.trackernextaccess.info=Quan farem el seg\u00fcent acces al rastrejador TableColumn.header.priority=Prioritat TableColumn.header.priority.info=Determina quanta amplada de banda de desc\u00e0rrega cal donar al torrent MyTorrentsView.menu.showdetails=Mostrar &Detalls MyTorrentsView.menu.showdownloadbar=Mostrar &Barra de desc\u00e0rrega MyTorrentsView.menu.open=&Obrir MyTorrentsView.menu.setpriority=Establir &Prioritat MyTorrentsView.menu.setpriority.high=&Alta MyTorrentsView.menu.setpriority.low=&Baixa MyTorrentsView.menu.start=&Iniciar MyTorrentsView.menu.stop=A&turar MyTorrentsView.menu.remove=T&reure MyTorrentsView.menu.changeTracker=&Afegir URL de rastrejador TrayWindow.menu.exit=Sortir TrayWindow.menu.show=Mostrar Azureu&s SystemTray.menu.exit=&Sortir SystemTray.menu.closealldownloadbars=Tancar barres de desc\u00e0rrega SystemTray.menu.show=&Mostrar Vuze PeersView.ip.info=IP de l'Igual PeersView.port.info=Port que fa servir PeersView.T.info=L (local): heu establert la connexi\u00f3, R (remot): l'igual ha establert la connexi\u00f3. PeersView.I1=I PeersView.I1.info=Esteu interessat en el que t\u00e9 l'altre igual? PeersView.C1=C PeersView.C1.info=Quan l'igual us est\u00e0 bloquejant per descarregar PeersView.pieces=Peces PeersView.downloadspeed=Vel. desc\u00e0rrega PeersView.download=Rebut PeersView.I2=I PeersView.I2.info=L'igual est\u00e0 interessat en el que vosaltres teniu? PeersView.C2=C PeersView.C2.info=Quan esteu bloquejant l'igual per descarregar PeersView.uploadspeed=Vel. c\u00e0rrega PeersView.uploadspeed.info=La vostra velocitat de c\u00e0rrega respecte de l'igual PeersView.upload=Pujat PeersView.upload.info=La vostra c\u00e0rrega global cap a l'igual. PeersView.statup=C\u00e0rrega mitjana PeersView.statup.info=Un valor estimat de la velocitat de c\u00e0rrega de l'igual PeersView.S.info=Desanimat: Un Igual pot ser "desanimat" manualment, o autom\u00e0ticament (perqu\u00e8 no distribueix dades a prou velocitat) PeersView.downloadspeedoverall=Desc\u00e0rrega mitjana PeersView.optunchoke=Prefer\u00e8ncia PeersView.client.info=Tipus de client BT que fa servir l'Igual PeersView.menu.snubbed=De&sanimat PeersView.title.short=Detalls PeersView.title.full=Detalls AllPeersView.title.full=Tots iguals ConfigView.section.files=Fitxers ConfigView.label.usefastresume=Usar la manera de resumir r\u00e0pidament ConfigView.label.incrementalfile=Activa la creaci\u00f3 incremental de fitxers [Requerit per FAT32 sota Linux] ConfigView.label.defaultsavepath=Ruta de desc\u00e0rrega per defecte ConfigView.button.browse=Examinar... ConfigView.dialog.choosedefaultsavepath=Seleccioni la carpeta per a les desc\u00e0rregues ConfigView.section.server=Servidor ConfigView.section.global=Global ConfigView.label.disconnetseed=Desconnectar llavors al compartir ConfigView.label.switchpriority=Establir prioritat baixa autom\u00e0ticament al servir ConfigView.label.maxdownloads=Desc\u00e0rregues m\u00e0ximes simult\u00e0nies ConfigView.label.maxdownloads.tooltip=Sempre podreu tenir actius descarregant el nombre que poseu aqu\u00ed amb una sola excepci\u00f3,\nun torrent completat que tingui primera prioritat pot posar-se davant d'un canal de desc\u00e0rrega actiu si \u00e9s absolutament necessari. ConfigView.label.maxactivetorrents=Torrents m\u00e0xims actius (0 : il\u00edmitat)\nEls nous torrents no s'iniciaran si est\u00e0 descarregant/servint m\u00e9s de ConfigView.label.priorityExtensions=Canvia autom\u00e0ticament a alta prioritat fitxers d'extensi\u00f3\n (ex: .txt;.nfo;.jpg) ConfigView.section.transfer=Transfer\u00e8ncia ConfigView.label.maxuploads=C\u00e0rregues m\u00e0ximes per torrent ConfigView.label.maxuploadspeed=Velocitat m\u00e0xima de c\u00e0rrega (global) ConfigView.label.saveresumeinterval=Desa'n una c\u00f2pia autom\u00e0ticament cada ConfigView.unlimited=Sense l\u00edmit ConfigView.section.display=Visualitzaci\u00f3 ConfigView.label.opendetails=Obrir autom\u00e0ticament la barra de detalls ConfigView.label.openbar=Obrir autom\u00e0ticament la barra de desc\u00e0rrega ConfigView.label.closetotray=Posar icona en safata al tancar ConfigView.label.minimizetotray=Posar icona en safata al minimitzar ConfigView.section.general=General ConfigView.section.start=Comen\u00e7ar ConfigView.label.showsplash=Mostrar pantalla emergent a l'inici ConfigView.label.autoupdate=Obrir el di\u00e0leg d'actualitzacions per a veure si n'hi ha alguna disponible ConfigView.label.openconsole=Obrir la c\u00f2nsola en l'inici ConfigView.label.openconfig=Obrir la configuraci\u00f3 en l'inici ConfigView.label.startminimized=Comen\u00e7ar minimitzat ConfigView.section.irc=Client Irc ConfigView.label.ircwiki=Si us plau llegiu http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Servidor ConfigView.label.ircchannel=Sala ConfigView.label.irclogin=\u00c0lies ConfigView.group.irctitle=Configuraci\u00f3 IRC ConfigView.boolean.ircsendinfo=Perm\u00eds per transmtre (an\u00f2nimament) la vostra configuraci\u00f3 als\n operadors del canal per tal que us puguin ajudar ConfigView.boolean.irclog=Habilita el registre de l'activitat del canal (a IRC_log.htm) ConfigView.section.security=Seguretat ConfigView.label.password=Protegir Vuze usant contrassenya\nAl restaurar Vuze se't preguntar\u00e0 la contrassenya ConfigView.label.passwordconfirm=Contrassenya (confirmar) ConfigView.label.passwordmatch=Contrassenya activada : ConfigView.label.passwordmatchnone=No ConfigView.label.passwordmatchno=No / Les contrassenyes no concorden ConfigView.label.passwordmatchyes=Si ConfigView.button.save=Desa ConfigView.title.short=Config. ConfigView.title.full=Configuraci\u00f3 ConsoleView.title.short=C\u00f2nsola ConsoleView.title.full=C\u00f2nsola FileItem.write=Escriptura FileItem.read=Lectura FileItem.normal=Normal FileItem.high=Alta FileItem.donotdownload=No descarregar FileItem.delete=Esborra FilesView.name=Nom FilesView.name.fastRename=Reanomenada r\u00e0pida FilesView.size=Mida FilesView.done=Completat FilesView.%=% FilesView.firstpiece=# primera pe\u00e7a FilesView.numberofpieces=# de peces FilesView.pieces=Peces FilesView.mode=Manera FilesView.priority=Prioritat FilesView.menu.open=Obrir FilesView.menu.setpriority=Establir prioritat FilesView.menu.setpriority.high=Alta FilesView.menu.setpriority.normal=Normal FilesView.menu.setpriority.skipped=No descarregar FilesView.title.short=Fitxers FilesView.title.full=Ftixers GeneralView.section.downloaded=Descarregat GeneralView.label.status.file=Estat del fitxer GeneralView.label.status.pieces=Estat peces GeneralView.section.availability=Disponibilitat GeneralView.label.status.pieces_available=Estat Peces GeneralView.section.transfer=Transfer\u00e8ncia GeneralView.section.info=Informaci\u00f3 GeneralView.label.timeelapsed=Temps actiu : GeneralView.label.remaining=Restant : GeneralView.label.downloaded=Descarregat : GeneralView.label.downloadspeed=Vel. desc\u00e0rrega : GeneralView.label.maxuploads=C\u00e0rrega m\u00e0xims : GeneralView.label.maxuploads.tooltip=M\u00e0xim nombre d'iguals no embussats en un moment donat. GeneralView.label.uploaded=Enviat : GeneralView.label.uploadspeed=Vel. c\u00e0rrega: GeneralView.label.seeds=Llavors : GeneralView.label.peers=Clients : GeneralView.label.completed=Completat: GeneralView.label.totalspeed=Velocitat total : GeneralView.label.totalspeed.tooltip=Velocitat total de tots els clients amb els quals esteu connectat. GeneralView.label.averagespeed=mitjana GeneralView.label.filename=Nom : GeneralView.label.totalsize=Mida total : GeneralView.label.savein=Desat a: GeneralView.label.hash=Hash : GeneralView.label.numberofpieces=# de peces : GeneralView.label.size=Mida de la pe\u00e7a : GeneralView.label.tracker=Rastrejador : GeneralView.label.updatein=Actualitzat en : GeneralView.label.trackerurl=URL del rastrejador : GeneralView.label.trackerurlupdate=Actualizaci\u00f3 manual GeneralView.label.comment=Comentaris : GeneralView.label.user_comment=Comentari de l'usuari: GeneralView.label.status=Estatus: ManagerItem.waiting=Esperant ManagerItem.allocating=Establint ManagerItem.checking=Comprovant ManagerItem.ready=Preparat ManagerItem.downloading=Descarregant ManagerItem.seeding=Compartint ManagerItem.stopped=Aturat ManagerItem.error=Error ManagerItem.high=Alta ManagerItem.low=Baixa MinimizedWindow.name=Nom: MinimizedWindow.all_transfers=Transfer\u00e8ncies del Vuze PiecesView.size=Mida PiecesView.numberofblocks=# de blocs PiecesView.blocks=Blocs PiecesView.completed=Completats PiecesView.availability=Disponibilitat PiecesView.reservedby=Reservat PiecesView.writers=Contribuidors de Bloc PiecesView.title.short=Peces PiecesView.title.full=Peces SystemTray.tooltip.seeding=%1 Sembrant, SystemTray.tooltip.downloading=%1 descarregant, DownloadManager.error.filenotfound=No es troba el fitxer DownloadManager.error.fileempty=El fitxer .torrent est\u00e0 buit DownloadManager.error.filetoobig=El fitxer .torrent \u00e9s molt gran DownloadManager.error.filewithouttorrentinfo=No hi ha informaci\u00f3 al fitxer .torrent DownloadManager.error.unsupportedencoding=Codificaci\u00f3 no suportada DownloadManager.error.ioerror=Error d'E/S DownloadManager.error.sha1=Error d'Algoritme (SHA1) PeerManager.status.offline=Desconnectat PeerManager.status.ok=Actiu PeerManager.status.checking=Comprovant PeerManager.status.finished=Completat PeerManager.status.finishedin=Completat MainWindow.upgrade.assistant=Assistent d'actualitzaci\u00f3 MainWindow.upgrade.newerversion=Hi ha disponible una nova versi\u00f3 d'Vuze per a descarregar MainWindow.upgrade.explanation=Aquest assistent descarregar\u00e0 la nova versi\u00f3 en la carpeta de Vuze i despr\u00e9s reiniciar\u00e0 Vuze MainWindow.upgrade.explanation.manual=Podeu fer una actualitzaci\u00f3 manual tancant el Vuze, descarregant la nova versi\u00f3 i reiniciant el programa MainWindow.upgrade.step1=Pas 1: Desc\u00e0rrega de la nova versi\u00f3 MainWindow.upgrade.step2=Pas 2: Tancar aquesta versi\u00f3 per a reiniciar en la nova versi\u00f3 de Vuze MainWindow.upgrade.hint1=Truc:\tSi mantens pressionat alguns segons Acabar i despr\u00e9s el deixes anar, el proc\u00e9s ser\u00e0 autom\u00e0tic MainWindow.upgrade.hint2=Truc:\tSi voleu tancar el Vuze m\u00e9s endavant, premeu Cancel\u00b7la i\n\trenanomeneu Azureus2-new.jar l'Azureus2.jar despr\u00e9s de tancar MainWindow.upgrade.error.downloading.hint=Error:\tImposible descarregar la nova versi\u00f3, si us plau actualitzi manualment MainWindow.upgrade.section.info=Nova versi\u00f3 disponible MainWindow.upgrade.section.manual=Actualitzaci\u00f3 manual MainWindow.upgrade.section.automatic=Actualitzaci\u00f3 autom\u00e0tica MainWindow.upgrade.tooltip.progressbar=El progr\u00e9s de la desc\u00e0rrega es mostra aqu\u00ed Button.next=Seg\u00fcent Button.finish=Acaba Button.cancel=Cancel\u00b7lar LocaleUtil.title=Trieu la codificaci\u00f3 LocaleUtil.section.chooseencoding=Trieu la codificaci\u00f3 per al fitxer LocaleUtil.label.chooseencoding=Si us plau, seleccioneu la millor codificaci\u00f3 corresponent LocaleUtil.label.hint.doubleclick=Truc: feu doble clic en una fila per triar la codificaci\u00f3 i tancar el quadre de di\u00e0leg LocaleUtil.label.checkbox.rememberdecision=Recorda decisions per als fitxers restants LocaleUtil.column.encoding=Codificaci\u00f3 IrcClient.copyright=Usant PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Connectant a IrcClient.connected=Connectat a IrcClient.joining=Unint se a IrcClient.channel=Sala IrcClient.joined=Unit correctament IrcClient.hasjoined=s'ha unit IrcClient.haskicked=ha estat patejat IrcClient.hasleft=s'en ha anat IrcClient.nowknown=\u00e9s ara conegut com IrcClient.topicforchannel=Tema per a la sala IrcClient.disconnected=Desconnectat de IrcClient.noNick=No tens un \u00e0lies especificat. Si us plau aneu a la pantalla de 'Configuraci\u00f3' IrcView.actionnotsupported=Aquesta acci\u00f3 no est\u00e0 suportada IrcView.clientsconnected=Usuaris IrcView.privateto=Per a IrcView.privatefrom=De IrcView.noticefrom=Av\u00eds : IrcView.errormsg=Sintaxi incorrecta en /msg : /msg usuari missatge IrcView.help=Els comandos valids s\u00f3n :\n . /help : mostra aquest missatge\n . /nick | /name : canvia el teu \u00e0lies \n . /me acci\u00f3 : envia una acci\u00f3 \n ./ msg \u00e0lies missatge : envia un missatge privat \n . /r missatge : respon a l'ultim missatge privat \n . /join #sala : canvia la sala actual PasswordWindow.title=Vuze est\u00e0 protegit per contrassenya PasswordWindow.passwordprotected=Vuze est\u00e0 protegit per contrassenya.\nPer restaurar Vuze si us plau tipee la seva contrassenya aqu\u00ed : Button.ok=Ok TrackerChangerWindow.title=Canviar rastrejador TrackerChangerWindow.newtracker=Ingressi la nova url del rastrejador PeersView.discarded=Rebutjat PeersView.discarded.info=Dades que heu rebut encara que no les necessiteu, aix\u00ed us en podeu desfer. discarded=rebutjat MyTorrentsView.menu.move=&Moure MyTorrentsView.menu.moveUp=Am&unt MyTorrentsView.menu.moveDown=&Avall GeneralView.label.hashfails=Fallada el Hash : GeneralView.label.shareRatio=Terme mitj\u00e0 compartit : ConfigView.section.downloadManagement=Administrador de Desc\u00e0rrega ConfigView.label.startRatioPeers=Comen\u00e7ar a compartir quan hagi menys de 1 llavor ConfigView.text.neverStop=No detenir mai ConfigView.text.neverStart=No comen\u00e7ar mai ConfigView.text.peers=Parells ConfigView.label.checkOncompletion=Comprovar peces una vegada descarregades wizard.title=Crea un .torrent wizard.previous=< Anterior wizard.next=Seg\u00fcent > wizard.finish=Acabar wizard.mode=Rastrejador / Modus wizard.tracker=Rastrejador: wizard.invalidurl=Aquesta URL no \u00e9s valida wizard.singlefile=Fitxer wizard.singlefile.help=Crea un .torrent des d'un fitxer wizard.directory=Carpeta wizard.directory.help=Crea un .torrent des d'una carpeta wizard.choosefile=Seleccioneu el fitxer wizard.file=Fitxer: wizard.browse=Examina... wizard.choosedirectory=Seleccioneu la carpeta wizard.invalidfile=Fitxer no v\u00e0lid! wizard.invaliddirectory=Carpeta no v\u00e0lida! wizard.torrentFile=Fitxer .torrent wizard.choosetorrent=Si us plau seleccioneu el fitxer .torrent que voleu crear wizard.information=Informaci\u00f3 wizard.notimplemented=No implementat encara wizard.progresstitle=Creant fitxer .torrent wizard.savingfile=Desant el fitxer... wizard.filesaved=Fitxer desat. wizard.close=Tanca Torrent.create.progress.piecelength=Longitud de pe\u00e7a: Torrent.create.progress.piececount=Quantitat de peces: Torrent.create.progress.totalfilesize=Mida total del fitxer: Torrent.create.progress.totalfilecount=Quantitat total de fitxers: Torrent.create.progress.parsingfiles=Analitzant fitxers Torrent.create.progress.hashing=Hashing fitxers MainWindow.upgrade.downloadingfrom=Descarregant des de: MainWindow.menu.view.ipFilter=Filtres de Ip ConfigView.section.ipfilter=Filtres de IP ConfigView.section.ipfilter.description=Descripci\u00f3 ConfigView.section.ipfilter.start=Ip inicial ConfigView.section.ipfilter.end=Ip final ConfigView.section.ipfilter.add=Afegir ConfigView.section.ipfilter.remove=Treure ConfigView.section.ipfilter.edit=Edita ConfigView.section.ipfilter.save=Desa ConfigView.section.ipfilter.editFilter=Edita els filtres ConfigView.section.ipfilter.enable=Activar PeersView.menu.close=Tan&car seedmore.title=No hi ha suficient llavors per a aquest .torrent seedmore.shareratio=El teu terme mitj\u00e0 compartit per a aquest .torrent \u00e9s de seedmore.uploadmore=No conv\u00e9 tenir una proporci\u00f3 de dades compartides de menys del 100% a la xarxa bittorrent.\nHaur\u00edeu de fer servir m\u00e9s aquest torrent.\nSegur que voleu seguir? ConfigView.label.showpopuponclose=Demanar confirmaci\u00f3 al detenir compartint amb un terme mitj\u00e0 compartit menor de 1 ConfigView.label.startNumSeeds=\nComen\u00e7ar a compartir si hi ha menys de ConfigView.label.seeds=llavors ConfigView.section.seeding=Sembrant MyTorrentsView.menu.removeand=&Treure i MyTorrentsView.menu.removeand.deletetorrent=Esborra el fitxer &torrent MyTorrentsView.menu.removeand.deletedata=Esborra les &dades MyTorrentsView.menu.removeand.deleteboth=Esborra'ls tots dos deletedata.title=Esborra el contingut deletedata.message1=Esteu a punt d'esborrar les dades contingudes a:\n MainWindow.menu.file.configure=&Assistent de Configuraci\u00f3 ... configureWizard.title=Assistent de configuraci\u00f3 configureWizard.welcome.title=Benvingut a l'assistent de configuraci\u00f3 d'Vuze configureWizard.welcome.message=Aquest assistent t'ajudar\u00e0 a configurar les opcions m\u00e9s com\u00fans d'Azureus. Pot modificar amb major profunditat aquestes opcions en el men\u00fa Vistes>Configuraci\u00f3. configureWizard.transfer.title=Configuraci\u00f3 de la connexi\u00f3 i les transfer\u00e8ncies configureWizard.transfer.hint=Truc : posar una mica menys de la velocitat real de la l\u00ednia \u00e9s la millor opci\u00f3. configureWizard.transfer.message=Si us plau, trieu una connexi\u00f3 de la llista seg\u00fcent. Aneu amb compte de no permetre massa velocitat de c\u00e0rrega, ja que far\u00e0 que la velocitat de desc\u00e0rrega sigui lenta. Com que les velocitats de c\u00e0rrega nom\u00e9s compten per al torrent que esteu descarregant, voler descarregar massa torrents igualment provocar\u00e0 petites velocitats de desc\u00e0rrega. Us recomanem de fer servir 5 kB/s per torrent com a m\u00ednim ESTRICTE. Com m\u00e9s de pressa carregueu, m\u00e9s de pressa descarregareu (respecte de la velocitat del torrent). configureWizard.transfer.connection=L\u00ednia configureWizard.transfer.connection.0=Personalitzat configureWizard.transfer.connection.1=m\u00f2dem/isdn configureWizard.transfer.connection.2=adsl/cable xxx/128 kbps configureWizard.transfer.connection.3=adsl/cable xxx/256 kbps configureWizard.transfer.connection.4=adsl/cable xxx/384 kbps configureWizard.transfer.connection.5=adsl/cable xxx/512 kbps configureWizard.transfer.connection.6=adsl/cable xxx/768 kbps configureWizard.transfer.connection.7=adsl/cable xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Vel.M\u00e0x.Pujar (kB/s) configureWizard.transfer.maxActiveTorrents=M\u00e0x. Actius configureWizard.transfer.maxDownloads=M\u00e0x. Desc\u00e0rregues configureWizard.transfer.maxUploadsPerTorrent=Nombre m\u00e0xim de c\u00e0rregues per torrent configureWizard.nat.title=NAT / Ports del servidor configureWizard.nat.message=Si voleu obtenir el millor de BitTorrent, \u00e9s altament recomanable que el vostre ordinador tingui acc\u00e9s complet des d'Internet. El rang de ports per defecte de BitTorrent va des del 6881 fins al 6889. Aquesta eina us permet provar i canviar aquests ports. Si teniu alguna desc\u00e0rrega activa, \u00e9s possible que alguns ports no siguin accessibles. configureWizard.nat.test=Prova configureWizard.nat.testing=Provant ports configureWizard.nat.ok=Ok configureWizard.nat.ko=Error de NAT configureWizard.nat.unable=No s'ha pogut comprovar configureWizard.file.title=Torrents / Fitxers configureWizard.file.message1=El Vuze desar\u00e0 els .torrent oberts en una carpeta espec\u00edfica. La podeu triar aqu\u00ed: configureWizard.file.path=Ruta configureWizard.file.browse=Examinar configureWizard.file.message2=El Vuze \u00e9s capa\u00e7 de resumir instant\u00e0niament els teus fitxers afegint algunes dades de resum als teus .torrents. Si fas servir aquesta caracter\u00edstica, tamb\u00e9 podr\u00e0s resumir peces de fitxers descarregats parcialment. configureWizard.file.fastResume=Activar resum r\u00e0pid configureWizard.file.invalidPath=Carpeta inv\u00e0lida configureWizard.finish.title=Completat configureWizard.finish.message=El Vuze est\u00e0 configurat. Gaudeix-ne! wizard.close.confirmation=Confirmaci\u00f3 wizard.close.message=Voleu que l'assistent es carregui la propera vegada que inicieu el Vuze exportTorrentWizard.title=Exportar un .torrent exportTorrentWizard.torrentfile.title=Selecci\u00f3 del fitxer .torrent exportTorrentWizard.torrentfile.message=Seleccioneu el fitxer .torrent per exportar exportTorrentWizard.torrentfile.path=Ruta exportTorrentWizard.torrentfile.browse=Examinar exportTorrentWizard.torrentfile.invalidPath=Ftixer .torrent inv\u00e0lid exportTorrentWizard.exportfile.title=Exporta els fitxers seleccionats exportTorrentWizard.exportfile.message=Ingressar la carpeta \u00f3n es va a exportar exportTorrentWizard.exportfile.path=Ruta exportTorrentWizard.exportfile.browse=Examinar exportTorrentWizard.exportfile.invalidPath=Ftixer .torrent inv\u00e0lid exportTorrentWizard.finish.title=Completat exportTorrentWizard.finish.message=El proc\u00e9s d'exportaci\u00f3 s'ha completat correctament exportTorrentWizard.process.inputfilebad.title=Ftixer .torrent inv\u00e0lid exportTorrentWizard.process.inputfilebad.message=S'ha produ\u00eft un erroe quan s'estava accedint als fitxers: exportTorrentWizard.process.outputfileexists.title=El fitxer existeix exportTorrentWizard.process.outputfileexists.message=El ftixer de sortida ja existeix. El voleu sobreescriure? exportTorrentWizard.process.torrentfail.title=va Fallar la lectura del .torrent exportTorrentWizard.process.exportfail.title=El proc\u00e9s d'exportaci\u00f3 va fallar exportTorrentWizard.process.unknownfail.title=Error inesperat importTorrentWizard.title=Importar un .torrent importTorrentWizard.torrentfile.title=Selecci\u00f3 del fitxer .torrent importTorrentWizard.torrentfile.message=Seleccioneu el fitxer .torrent per importar importTorrentWizard.torrentfile.path=Ruta importTorrentWizard.torrentfile.browse=Examinar importTorrentWizard.torrentfile.invalidPath=Ftixer .torrent inv\u00e0lid importTorrentWizard.importfile.title=Selecci\u00f3 de fitxers per importar importTorrentWizard.importfile.message=Selecciona el fitxer xml per importar importTorrentWizard.importfile.path=Ruta importTorrentWizard.importfile.browse=Examinar importTorrentWizard.importfile.invalidPath=El fitxer per importar \u00e9s inv\u00e0lid importTorrentWizard.finish.title=Completat importTorrentWizard.finish.message=El proc\u00e9s d'importaci\u00f3 s'ha completat correctament importTorrentWizard.process.inputfilebad.title=El fitxer per importar \u00e9s inv\u00e0lid importTorrentWizard.process.inputfilebad.message=S'ha produ\u00eft un error quan s'estava accedint als ftixers: importTorrentWizard.process.outputfileexists.title=El fitxer existeix importTorrentWizard.process.outputfileexists.message=El fitxer de sortida existeix. El voleu sobreescriure? importTorrentWizard.process.torrentfail.title=Errors d'escriptura del Torrent importTorrentWizard.process.importfail.title=Errors al importar el Torrent importTorrentWizard.process.unknownfail.title=Error inesperat ConfigView.label.bindip=Enlla\u00e7ar a una adre\u00e7a IP local or interface ConfigView.label.zeronewfiles=Quan es creen els fitxers nous assignar l'espai i posar-lo a zero ConfigView.label.zeronewfiles.tooltip=Minimitza fragmentaci\u00f3 ConfigView.section.stats=Estad\u00edstiques ConfigView.section.stats.enable=Activat ConfigView.section.stats.defaultsavepath=Carpeta per desar les estad\u00edstiques ConfigView.section.stats.choosedefaultsavepath=Si us plau, trieu la carpeta on voleu desar les estad\u00edstiques ConfigView.section.stats.savefreq=Freq\u00fc\u00e8ncia de desada ConfigView.section.stats.seconds=seg ConfigView.section.stats.savefile=Nom del fitxer d'estad\u00edsitiques MyTorrentsView.menu.export=&XML Exportar... MyTorrentsView.menu.host=&Hoste... ManagerItem.finishing=Acabant ConfigView.dialog.choosedefaulttorrentpath=Seleccioneu la carpeta de .torrent per defecte ConfigView.dialog.choosemovepath=Seleccioneu la carpeta on ho voleu moure ConfigView.label.movecompleted=Mou els fitxers completats ConfigView.label.savetorrents=Des els fitxers torrent MainWindow.menu.view.mytracker=El meu Rastrejador MyTrackerView.title.full=El meu Rastrejador MyTrackerView.name=Nom MyTrackerView.tracker=Rastrejador MyTrackerView.status=Estat MyTrackerView.status.started=Executant MyTrackerView.status.stopped=Aturat MyTrackerView.peers=Iguals MyTrackerView.seeds=Llavors MyTrackerView.announces=Anuncis MyTrackerView.uploaded=Carregat MyTrackerView.downloaded=Descarregat MyTrackerView.left=Deixat ConfigView.section.style=Interf\u00edcie ConfigView.section.style.useCustomTabs=Fer servir Etiquetes tancables (requereix reiniciar) MainWindow.menu.view.plugins=Complements fileDownloadWindow.saveTorrentIn=Desa el ftixer torrent a fileDownloadWindow.title=Vuze - Descarregador Torrent fileDownloadWindow.downloading=Descarregant de : fileDownloadWindow.status=Estat : fileDownloadWindow.state_initializing=Inicialitzant fileDownloadWindow.state_downloading=Descarregant fileDownloadWindow.state_error=Error: MainWindow.menu.file.open.url=URL openUrl.title=Vuze - Obrir Url openUrl.url=URL: MyTorrentsView.menu.host.error.title=Allotjar el Torrent ha fallat MyTorrentsView.menu.host.error.message=Ha passat el seg\u00fcent error quan allotjavem el torrent ConfigView.section.tracker=rastrejador ConfigView.section.tracker.pollinterval=Interval per consutar clients al rastrejador (segons) ConfigView.section.tracker.publishenable=Publicar detalls del torrent a "/" ConfigView.section.tracker.ip=Adre\u00e7a IP Externa del rastrejador ConfigView.section.style.enableXPStyle=Activa estil XP (necessita reiniciar) ConfigView.section.tracker.checkip=Comprovar adre\u00e7a... ipCheckerWizard.title=Assistent per a comprovar la teva adre\u00e7a IP ipCheckerWizard.service=Servei ipCheckerWizard.chooseService=Si us plau tria un comprovador d'adreces IP dels llistats a continuaci\u00f3 ipCheckerWizard.explanations=Pots fer servir l'assistent per a trobar la teva direcci\u00f3 IP externa. Si la teva adre\u00e7a IP \u00e9s din\u00e0mica, recomanem que obris un compte amb un prove\u00efdor de DNS din\u00e0mic. Alguns dels prove\u00efdors d'aquests serveis estan llistats a continuaci\u00f3, f\u00e9s servir l'enlla\u00e7 per a obrir un nou compte. Despr\u00e9s emplena el camp 'IP address' amb el teu servidor din\u00e1mic (ex. myhostname.dyndns.org). Necessitar\u00e0s un programa que autom\u00e0ticament actualitzi el teu prove\u00efdor de DNS din\u00e0mic amb la teva adre\u00e7a IP. D'aquesta forma podr\u00e0s oferir Torrents, fins i tot si la teva adre\u00e7a IP canvia. ipCheckerWizard.service.description=Descripci\u00f3 : ipCheckerWizard.service.url=Enlla\u00e7 : ipCheckerWizard.progresstitle=Comprovant IP ipCheckerWizard.checkComplete=IP completada : ipCheckerWizard.checkFailed=Va fallar, ra\u00f3 : wizard.tracker.local=Usar el rastrejador intern de Vuze wizard.tracker.external=Usar un rastrejador extern wizard.tracker.howToLocal=\tAnar a 'Configuraci\u00f3>rastrejador' per a habilitar-ho wizard.announceUrl=Adre\u00e7a URL d'anunci : IPChecker.external.service.discoveryvip.description=Discoveryvip - Comprovaci\u00f3 d'adre\u00e7a IP \u00fanica IPChecker.external.httpinvalidresponse=Resposta HTTP inv\u00e0lida IPChecker.external.loadingwebpage=Carregant la p\u00e0gina web IPChecker.external.analysingresponse=Analitzant resposta IPChecker.external.addressextracted=Adreces IP extretes IPChecker.external.httploadfail=Fallada al carregar la p\u00e0gina IPChecker.external.timeout=Fora de temps IPChecker.external.ipnotfound=L'Adre\u00e7a IP no es troba ConfigView.section.tracker.pollintervalmin=M\u00ednim ConfigView.section.tracker.pollintervalmax=M\u00e0xim ConfigView.section.tracker.pollintervalincby=Incrementar per ConfigView.section.tracker.pollintervalincper=Cada 'n' Clients splash.loadingImages=Carregant imatges splash.initializeGui=Iniciant finestra principal splash.openViews=Obrint vistes splash.plugin=Carregant complement : configureWizard.nat.tooManyPorts=Massa ports per a provar (9 m\u00e1xim) ConfigView.section.color=Esquema de Color MyTorrentsView.menu.publish=&Publica... MyTrackerView.status.published=Publicat MyTrackerView.completed=Completat MainWindow.menu.file.open.torrentnodefault=Fitxer torrent... (No desis per defecte) wizard.comment=Comentaris ConfigView.label.movetorrent=Moure .torrent ConfigView.label.subdir_is_in_default=Quan creguis que les desc\u00e0rregues ja existeixen a la carpeta per defecte, considera tamb\u00e9 les subcarpetes ConfigView.section.file.decoder.label=Codificacio per defecte del torrent\nselecci\u00f3 requerida ConfigView.section.file.decoder.nodecoder=Cap IPChecker.external.service.no-ip.description=Subministrador de servei DNS est\u00e0tic i din\u00e0mic\n(na hi ha servei gratuit de comprovaci\u00f3 d'adreces) ConfigView.section.tracker.publicenable=Activar .torrents externs ConfigView.label.playdownloadspeech=Parla quan s'acaba una desc\u00e0rrega ConfigView.label.playdownloadspeech.info=Actualment els Serveis de Parla van millor en angl\u00e8s # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Mostra el nombre de c\u00f2pies disponible de cada pe\u00e7a.\nSi el nombre de la dreta \u00e9s m\u00e9s petit que 1, no esteu veient una c\u00f2pia sencera del fitxer (i podeu tenir problemes per completar la desc\u00e0rrega). GeneralView.label.trackerurl.tooltip=Cliqui per copiar la URL de l'anunci al portapapers GeneralView.label.trackerurlopen.tooltip=Cliqui per obrir la p\u00e0gina principal del rastrejador # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Actualitzar GUI cada ConfigView.section.style.graphicsUpdate=Actualitzar barres Grafiques cada N GUI actualitzaci\u00f3(ns) ConfigView.section.style.reOrderDelay=Re-Ordenar taules cada N GUI actualitzaci\u00f3(ns) ConfigView.section.style.reOrderDelay.never=Mai ConfigView.section.logging=Registrant... ConfigView.section.logging.enable=Activa anotacions al fitxer ConfigView.section.logging.logdir=Carpeta del fitxer d'anotacions ConfigView.section.logging.choosedefaultsavepath=Si us plau, selecioneu la carpeta per desar GeneralView.label.updatein.querying=Preguntant... configureWizard.nat.sharePort=Usar un \u00fanic port compartit per a tots els .torrent ConfigView.section.logging.maxsize=Mida m\u00e0xima del fitxer d'anotacions ConfigView.section.tracker.passwordenableweb=Activar password en la Web del rastrejador ConfigView.section.tracker.passwordenabletorrent=Activar password en torrents ConfigView.section.tracker.username=Nom d'Usuari ConfigView.section.tracker.password=Mot clau columnChooser.title=Trieu les columnes per mostrar columnChooser.move=Arrossegui les files per re-ordenarles columnChooser.apply=Aplicar columnChooser.columnname=Nom Columna columnChooser.columndescription=Descripci\u00f3 TableColumn.header.shareRatio=Rati Compartir MyTorrentsView.menu.editTableColumns=&Columnes per mostrar wizard.operationfailed=L'operaci\u00f3 ha fallat authenticator.title=Requereix identificaci\u00f3 authenticator.realm=Domini authenticator.tracker=Rastrejador authenticator.user=Nom de l'Usuari authenticator.password=Mot clau ConfigView.label.allowSendVersion=Permetre a Vuze enviar un n\u00famero de versi\u00f3 an\u00f3nima i identificador aleatori mentre comprova la nova versi\u00f3 wizard.hint.mode=Hint:\tPodeu arrossegar i deixar anar un \u00fanic fitxer o carpeta a l'assistent\n\tper triar un fitxer o carpeta wizard.hint.file=Hint:\tPodeu triar un sol fitxer arrossegant i deixant anar wizard.hint.directory=Hint:\tPodeu triar un \u00fanica carpeta arrossegant i deixant anar MainWindow.menu.help.checkupdate=&Cercar actualitzacions del programa TableColumn.header.down=Descarregat TableColumn.header.up=Carregat ConfigView.section.tracker.passwordenabletorrent.info=Necessita client BitTorrent adequat (ex. Vuze ConfigView.section.style.confirmationOnExit=Mostrar di\u00e0leg de confirmaci\u00f3 al sortir MainWindow.dialog.exitconfirmation.title=Sortir d'Vuze MainWindow.dialog.exitconfirmation.text=Realment vol sortir d'Vuze SystemTray.menu.stopalltransfers=Aturar &Totes les Transfer\u00e8ncies TrayWindow.menu.stopalldownloads=&Aturar Totes les Desc\u00e0rregues ConfigView.section.tracker.sslport.info=Miri el FAQ per m\u00e9s informaci\u00f3 wizard.tracker.ssl=Fer servir SSL ConfigView.label.playdownloadfinished=Tocar un s\u00f3 quan es finalitza la desc\u00e0rrega TableColumn.header.pieces=Peces TableColumn.header.pieces.info=Barra gr\u00e0fica representant quines peces heu descarregat TableColumn.header.completion=Completat TableColumn.header.completion.info=Representaci\u00f3 Gr\u00e0fica del % descarregat ConfigView.section.style.showdownloadbasket=Mostrar Cistell de Desc\u00e0rregues (Arrossegar i Deixar .torrents) ConfigView.section.style.alwaysShowTorrentFiles=Mostra sempre ftixers Torrent en Detalls/Fitxers wizard.multitracker=Afegeix informaci\u00f3 Multi-rastrejador al torrent wizard.multitracker.title=Multi-rastrejador wizard.multitracker.configuration=Configuraci\u00f3 Multi-rastrejador wizard.multitracker.new=Nou... wizard.multitracker.edit=Edita... wizard.multitracker.delete=Esborra wizard.multitracker.group=Grup del Rastrejador wizard.multitracker.edit.title=Editor Multi-rastrejador wizard.multitracker.edit.name=Nom wizard.multitracker.edit.save=Desa wizard.multitracker.edit.newgroup=Nou Grup wizard.multitracker.edit.deletegroup=Esborra wizard.multitracker.edit.newtracker=Nou Rastrejador wizard.multitracker.edit.deletetracker=Esborra wizard.multitracker.edit.edit=Edita wizard.addingmt=Afegint informaci\u00f3 Multi-rastrejador wizard.multitracker.noannounce=La URL d'anunci no \u00e9s present en la vostre llista de rastrejadors MyTorrentsView.menu.recheck=&For\u00e7ar Re-comprovar iconBar.showDownloadBar.tooltip=Mostrar Barra de Desc\u00e0rrega iconBar.start.tooltip=Comen\u00e7ar iconBar.stop.tooltip=Aturar iconBar.remove.tooltip=Treure iconBar.openNoDefault.tooltip=Obre un fitxer .torrent (no desar per defecte) iconBar.openURL.tooltip=Obrir una URL iconBar.openFolder.tooltip=Obrir una carpeta iconBar.new.tooltip=Crear un torrent iconBar.up.tooltip=Moure amunt iconBar.down.tooltip=Moure a baix iconBar.run.tooltip=Obrir iconBar.host.tooltip=Hoste iconBar.publish.tooltip=Publica MyTorrentsView.menu.editTracker=&Edita la URL del rastrejador GeneralView.menu.selectTracker=Seleccionar ConfigView.section.stats.xslfile=Nom del fitxer XSL ConfigView.section.stats.xslfiledetails=Aix\u00f2 s'inclour\u00e0 a la capcalera del ftixer d'estats amb una etiqueta ConfigView.label.savetorrentbackup=Desa'n una c\u00f2pia ConfigView.section.tracker.forceport=Forca torrents externs allotjats en el port per defecte ConfigView.section.ipfilter.allow=PERMETRE aquests intervals (defecte \u00e9s PROHIBIR) ConfigView.section.ipfilter.list.inrange=\u00e9s entre limits ConfigView.section.ipfilter.list.notinrange=no \u00e9s entre limits ConfigView.section.ipfilter.list.title=Llista de IPs bloquejades ConfigView.label.allowsameip=Permetre M\u00faltiples connexions des de la mateixa IP ConfigView.label.allowsameip.tooltip=Nom\u00e9s marcar-ho quan es necessiti.\nQuan est\u00e0 desactivat \u00e9s una proteccio contra"leecher" ManagerItem.superseeding=Super-Sembrant ConfigView.label.userSuperSeeding=Fer Servir Super-Sembrant PeersView.uniquepiece=Pe\u00e7a (Modus Super-Sembrant) PeersView.uniquepiece.none=Cap PeersView.timetosend=Estafi per reenviar la Peca (Modus Super-Sembrant) ConfigView.section.style.addurlsilently=Obrir URL silenciosament (sense di\u00e0leg) ConfigView.section.style.addurlsilently.tooltip=Av\u00eds: si s'activa la finestra principal es pot fer invisible un altre cop!\nsi perdeu la icona de la safata, heu de desactivar aquesta opci\u00f3. ConfigView.section.file.decoder.prompt=Pregunta sempre quan hi hagi possibilitats de triar la codificaci\u00f3 ConfigView.section.file.decoder.prompt.tooltip=Mostra sempre el di\u00e0leg quan hi hagi possibilitats de triar la codificaci\u00f3 MyTorrentsView.menu.moveTop=A Dal&t MyTorrentsView.menu.moveEnd=A &Baix ConfigView.label.moveonlyusingdefaultsave=si \u00e9s a la carpeta de dades per defecte ConfigView.label.moveonlyusingdefaultsave.tooltip=Moure nom\u00e9s si el torrent \u00e9s en directori defecte de dades ConfigView.label.watchtorrentfolder=Importar nous .torrents autom\u00e0ticament ConfigView.label.watchtorrentfolder.tooltip=Mirar regularment si hi ha nous torrents ConfigView.label.watchtorrentfolderinterval=Int\u00e8rval ConfigView.label.watchtorrentfolderinterval.tooltip=Temps d'espera fins a tornar a comprovar la carpeta ConfigView.dialog.choosewatchtorrentfolderpath=Seleccioneu la carpeta des d'on importem .torrent ConfigView.label.startwatchedtorrentsstopped=Comen\u00e7ar aturat ConfigView.label.startwatchedtorrentsstopped.tooltip=Afegir torrents nous en estat ATURAT ConfigView.section.plugins=Complements wizard.maketorrent.filesize=Mida del fitxer(s) wizard.maketorrent.piececount=Comptador de Peces wizard.maketorrent.piecesize=Mida Peca MainWindow.menu.view.stats=E&stadistiques SpeedView.title.full=Activitat SpeedView.downloadSpeed.title=Velocitat de desc\u00e0rrega SpeedView.uploadSpeed.title=Velocitat de c\u00e0rrega ConfigView.section.style.useSIUnits=Fer servir unitats IEC (KB -> KiB etc.) iconBar.top.tooltip=Moure al principi iconBar.bottom.tooltip=Moure al final TableColumn.header.health=Salut MyTorrentsView.menu.health=Sobre Salut health.explain.grey=significa que el seu torrent no est\u00e0 en marxa (descarregant o pujant) health.explain.red=Significa que mentre descarreguem, no estem conectat a cap igual health.explain.blue=Estar sembrant implica que mentre descarreguem\nno estem connectat a cap igual, i aix\u00f2 significa que haur\u00edem d'estar connectat a alguns iguals per\u00f2 el rastrejador est\u00e0 aturat health.explain.yellow=significa que el rastrejador \u00e9s correcte i que esteu connectats a iguals, per\u00f2 no teniu cap connexi\u00f3 remota.\nPotser teniu un problema NAT si els torrents romanen en estat groc tota l'estona health.explain.green=significa que tot va b\u00e9 ConfigView.section.style.alwaysRefreshMyTorrents=Sempre refrescar Els meus Torrents ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Aquesta opci\u00f3 refrescar\u00e0 la vista Els meus Torrents incl\u00fas si no es mostra (t\u00e9 \u00fas per alguns complements mirc) # #2.0.7.0 # security.certtruster.title=Av\u00e9s del Certificat de Seguretat security.certtruster.intro=Una empresa de qui no us refieu ha em\u00e8s el certificat de seguretat security.certtruster.resource=Recurs: security.certtruster.issuedto=Em\u00e8s per A: security.certtruster.issuedby=Em\u00e8s per: security.certtruster.prompt=Us en refieu? security.certtruster.yes=S\u00ed ConfigView.section.tracker.torrentsperpage=Quants torrents per p\u00e0gina? [0: il\u00b7limitat] MainWindow.menu.file.share=&Compartir MainWindow.menu.file.share.file=&Fitxer... MainWindow.menu.file.share.dir=C&arpeta... MainWindow.menu.file.share.dircontents=C&ontingut Carpeta... MainWindow.menu.file.share.dircontentsrecursive=Contingut Carpeta... (&Recursiu) MainWindow.dialog.share.sharefile=Seleccioneu el fitxer per compartir MainWindow.dialog.share.sharedir=Seleccioni Carpeta a Compartir MainWindow.dialog.share.sharedircontents=Seleccioni Contingut de Carpeta a Compartir MainWindow.dialog.share.sharedircontents.recursive=Recursiu globalmanager.download.remove.veto=Acci\u00f3 d'eliminaci\u00f3 prohibida plugin.sharing.download.remove.veto=Aquesta desc\u00e0rrega \u00e9s el resultat de compartir un recurs.\nPer treure la desc\u00e0rrega tregui el recurs compartit associat ConfigView.section.tracker.main=Principal ConfigView.label.prioritizefirstpiece=D\u00f3na prioritat a la primera i l'\u00faltima pe\u00e7a del fitxer(s) ConfigView.label.prioritizefirstpiece.tooltip=Intenta descarregar l'aut\u00e8ntic inici i final del fitxer.\nPer suportar la vista pr\u00e8via prematura. ConfigView.section.file.confirm_data_delete=Confirmar quan esborrem dades ConfigView.section.file.confirm_data_delete.tooltip=Confirmar quan esborrem dades fent servir 'Treure i Borrar...' TrayWindow.menu.startalldownloads=Comencar Totes les Desc\u00e0rregues SystemTray.menu.startalltransfers=Comen\u00e7ar Totes les Transfer\u00e8ncies sharing.progress.title=Progr\u00e9s de Compartir sharing.progress.hide=Amagar MainWindow.menu.view.myshares=Compartits MySharesView.title.full=Compartits MySharesView.name=Nom MySharesView.type=Tipus MySharesView.type.file=Fitxer MySharesView.type.dir=Carpeta MySharesView.type.dircontents=Contingut de la carpeta MySharesView.type.dircontentsrecursive=Contingut de la carpeta (recursiu) MySharesView.menu.remove=Treure ConfigView.section.tracker.sendpeerids=Enviar identitat de l'Igual als descarregadors ConfigView.section.tracker.enableudp=Activar protocol UDP del rastrejador plugin.sharing.torrent.remove.veto=Aquest registre del rastrejador \u00e9s el resultat de compartir un recurs.\nPer treure la desc\u00e0rrega tregui el recurs associat plugin.download.remove.veto.notstopped=No es pot treure la desc\u00e0rrega si no est\u00e0 aturada plugin.sharing.remove.veto=Aquest compartit \u00e9s un sub-compartit d'un 'contingut de carpeta' i no es pot eliminar.\nElimineu el compartit principal GeneralView.label.hash.tooltip=Cliqui per copiar el hash al portapapers ConfigView.section.tracker.maxpeersreturned=M\u00e0xim d'iguals tornats [0: il\u00b7limitat] ConfigView.label.serverport=Escoltar port TCP d'entrada configureWizard.nat.server.tcp_listen_port=Escoltar port TCP entrant ConfigView.section.sharing=Compartint ConfigView.section.sharing.usessl=Fes servir SSL per als recursos compartits (cal que configureu el rastrejador) ConfigView.section.style.dropdiraction=Acci\u00f3 d'arrossegar i deixar anar per carpetes ConfigView.section.style.dropdiraction.opentorrents=Obrir Torrents ConfigView.section.style.dropdiraction.sharefolder=Comparteix carpeta ConfigView.section.style.dropdiraction.sharefoldercontents=Compartir Contingut # # 2.0.7.x # Categories.all=Tots Categories.uncategorized=No Catalogat CategoryAddWindow.message=Entrar un nom nou de Categoria CategoryAddWindow.title=Afegir una nova Categoria ConfigView.label.autoSeedingIgnoreInfo=Els torrents ignorats van al final de la cua de sembrat. Ells no son arrencats autom\u00e8ticament\nLes Regles d'Ignorar no s'apliquen a torrents que cumpleixen el criteri de Primera Prioritat.\nA menys de que s'arrenquin d'una altra manera, feu servir un valor 0 per desactivar la regla. ConfigView.label.directory=Carpeta ConfigView.label.disconnetseed.tooltip=Quan sembrem un torrent, desconecta els clients que no estan sembrant. No necessiten parlar amb vosaltres ConfigView.label.ignoreCase=Ignorar Maj./Min. ConfigView.label.ignoreSeeds=Ignorar torrents amb al menys ConfigView.label.importdirectory=Carpeta d'importaci\u00f3 ConfigView.label.minPeersToBoostNoSeeds.tooltip=Qualsevol torrent sense llavors i tenint menys iguals que els que vosaltres especifiqueu\nes posar\u00e0 al final de la cua ConfigView.label.minPeersToBoostNoSeeds=Grau de sembrat m\u00e9s petit per torrents sense llavors i menys de ConfigView.label.minSeedingTime.tooltip=Els graus de sembrat poden variar sovint en un per\u00edode curt de temps. De vegades fan que el torrent arrenqui autom\u00e0ticament, s'aturi i despr\u00e9s es posi en cua autom\u00e0ticament\nAix\u00f2 alleugereix el problema for\u00e7ant rl torrent a romandre sembrant durant un per\u00edode de temps determinat. Encara el podeu aturar manualment si ho voleu. ConfigView.label.minSeedingTime=Min\u00edm temps de sembrat en segons ConfigView.label.minSpeedForActiveDL.tooltip=Un canal de desc\u00e0rrega sempre es fa servir durant els 30 segons inicials\ndespr\u00e9s que el torrent incomplet arrenqui. ConfigView.label.minSpeedForActiveDL=No comptar el torrent com fent servir un canal de desc\u00e0rrega si la velocitat \u00e9s per sota de ConfigView.label.peers=iguals ConfigView.label.queue.debuglog=Anota informaci\u00f3 depuraci\u00f3 ConfigView.label.queue.debuglog.info=Afegeix informaci\u00f3 de depuraci\u00f3 de la cua a la consola i al fitxer d'anotacions.\nEncara que \u00e9s encriptada, la informaci\u00f3 de depuraci\u00f3 us mostra l'estat dels torrents i per qu\u00e8 estan o no iniciant o en cua. ConfigView.label.queue.minQueueingShareRatio=No posis en cua o paris un torrent fins que arribi al seu rati de compartir. ConfigView.label.ratio=rati ConfigView.label.removeOnStop=Treure el torrent de la llista despr\u00e9s de que aquest es pari autom\u00e0ticament ConfigView.label.savedirectory=Carpeta per desar ConfigView.label.seeding.autoReposition.tooltip=Si est\u00e0 habilitat, l'ordre dels torrents (la columna #) canviar\u00e0 per estar d'acord amb el grau de sembrat\nAix\u00f2 \u00e9s \u00fatil si no voleu veure els nombres de grau de sembrat, per\u00f2 encara voleu saber l'ordre en qu\u00e8 comen\u00e7aran els torrents complets. ConfigView.label.seeding.autoReposition=Reordenar els torrents autom\u00e0ticament segons el seu grau de sembrat ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Sovint els torrents amb poques llavors i molts iguals vol dir que probablement no hi ha una c\u00f2pia completa ajuntant els iguals.\nAleshores, podeu no voler que les regles de sembrat pretenguin que hi ha una c\u00f2pia completa (i aix\u00ed incorrectament reduir el grau) ConfigView.label.seeding.fakeFullCopySeedStart=per\u00f2 nom\u00e9s torrents amb al menys ConfigView.label.seeding.ignore=Regles d'Ignorar ConfigView.label.seeding.ignore0Peers=Ignorar torrents amb 0 iguals ConfigView.label.seeding.ignoreRatioPeers=Ignorar torrents que tenen al menys 1 igual per cada ConfigView.label.seeding.ignoreShareRatio=Ignorar torrents que tenen un rati de compartir de ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorar un torrent incl\u00fas si\ncompleix les regles de Primera Prioritat ConfigView.label.seeding.ignore.header.rule=Regla ConfigView.label.seeding.ignore.header.value=Valor ConfigView.label.seeding.firstPriority.info=Els torrents amb Primera Prioritat sempre estaran al principi de la cua.\nQualsevol torrent que cumpl\u00f1eixi els criteris de Primera Prioritat no s'aturar\u00e0 i es posar\u00e0 en cua autom\u00e0ticament.\nUn torrent que compleixi la Primera Prioritat agafar\u00e0 un Canal de Desc\u00e0rrega Simult\u00e0ni si el necessita. ConfigView.label.seeding.firstPriority.FP=Primera Prioritat ConfigView.label.seeding.firstPriority=Donem Primera Prioritat als torrents amb ConfigView.label.seeding.firstPriority.following=de els seg\u00fcents: ConfigView.label.seeding.firstPriority.shareRatio=Un rati de compartir per sota de ConfigView.label.seeding.firstPriority.seedingMinutes=Un temps d'espera canviant de descarregant a sembrant ConfigView.label.seeding.firstPriority.DLMinutes=Un temps d'espera des de que comen\u00e7a la desc\u00e0rrega ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Suposant que hi ha una c\u00f2pia completa per a X iguals, redu\u00efu el grau de torrents amb molts iguals.\nM\u00e9s aproximadament, els torrents amb molts d'iguals tenen molt de tr\u00e0nsit.\nAix\u00f2 no canvia el nombre de llavors que es mostra. ConfigView.label.seeding.numPeersAsFullCopy=Fer veure que hi ha 1 c\u00f2pia completa per cada un\n(0: no fer-ho veure) ConfigView.label.seeding.preferLargerSwarms.tooltip=Si principalment esteu sembrant torrents amb iguals que estan encallats, t\u00e9 sentit preferir eixams m\u00e9s grans\nQuan principalment esteu sembrant torrents amb una alta disponibilitat, \u00e9s millor tenir eixams petits. ConfigView.label.seeding.preferLargerSwarms=Quan els torrents tenen el mateix grau, preferir els eixams m\u00e9s grans ConfigView.label.seeding.rankType.none.tooltip=Ordre basat en # de columna ConfigView.label.seeding.rankType.none=Cap ConfigView.label.seeding.rankType.peerSeed.options=Opcions de Rati de Sembrat a Iguals ConfigView.label.seeding.rankType.peerSeed.tooltip=Rati m\u00e9s gran = Nivell m\u00e9s alt ConfigView.label.seeding.rankType.peerSeed=Rati de Sembrat a Iguals ConfigView.label.seeding.rankType.seed.fallback=Tornar a Rati Iguals/Llavors despr\u00e9s de\n(0 : No tornar mai ConfigView.label.seeding.rankType.seed.options=Opcions de compte de Llavors ConfigView.label.seeding.rankType.seed.tooltip=Menys Llavors = Nivell m\u00e9s alt ConfigView.label.seeding.rankType.seed=Nom\u00e9s compte de Llavors ConfigView.label.seeding.rankType.timedRotation.tooltip=Tots els torrents completats s'alternaran al modus sembrant.\nLa duraci\u00f3 del temps de sembrat \u00e9s establert per 'Temps M\u00ednim Sembrant' ConfigView.label.seeding.rankType.timedRotation=Rotaci\u00f3 temporitzada ConfigView.label.seeding.rankType.tooltip=Els torrents amb nivell m\u00e9s alt s'arrenquen autom\u00e0ticament.\nQuan un altre torrent arriva a un nivell m\u00e9s alt, el de menys nivell es para i va endarrera de la cua.\n\nNom\u00e9s estan disponibles per arrancar autom\u00e0ticament els torrents en un estat 'en Cua'.\nMai son arrancats autom\u00e0ticament els torrents parats. ConfigView.label.seeding.rankType=Valora els torrents complets per obrir-los autom\u00e0ticament d'acord amb: ConfigView.label.stopAfterMinutes=Un cop canviat a sembrant, aturar despr\u00e9s d'un temps de ConfigView.label.switchpriority.tooltip=Prioritat baixa redueix la quantitat d'ample de banda en desc\u00e0rrega permesa al torrent. ConfigView.pluginlist.info=S'han identificat els seg\u00fcents complements. Alguns complements pot ser no tenen etiquetes de configuraci\u00f3. ConfigView.pluginlist.noplugins=No s'han trobat complements. ConfigView.section.pluginslist=Llista ConfigView.section.queue.seeding=Sembrant ConfigView.section.queue.seeding.autoStarting=Auto-arrancar ConfigView.section.queue.seeding.ignore=Regles d'Ignorar ConfigView.section.queue.seeding.firstPriority=Primera Prioritat ConfigView.section.queue.main=Principal ConfigView.section.queue=En Cua ConfigView.section.torrents=Torrents ConfigView.text.all=tots ConfigView.text.hours=hores ConfigView.text.ignoreRule=Regles d'Ignorar ConfigView.text.ignore=Ignorar ConfigView.text.minutes=minuts ConfigView.text.neverIgnore=No Ignorar mai ConfigView.text.any=qualsevol DownloadManager.error.datamissing=Dades Perdudes MainWindow.menu.file.open.torrentforseeding=Fitxer torrent... (per sembrar) MainWindow.menu.language.refresh=&Refrescar ManagerItem.forced=For\u00e7at ManagerItem.queued=En Cua MySeedersView.header=Torrents complets TableColumn.header.availability.info=# c\u00f2pies completes que es veuen TableColumn.header.availability=Disponibilitat TableColumn.header.category=Categoria MyTorrentsView.header=Torrents incomplets TableColumn.header.maxuploads=# M\u00e0x. Desc\u00e0rregues MyTorrentsView.menu.category.delete=&Esborra Categoria MyTorrentsView.menu.forceStart=&For\u00e7a Arrancar MyTorrentsView.menu.queue=En &Cua MyTorrentsView.menu.setCategory.add=&Afegir Categoria... MyTorrentsView.menu.setCategory=Assignar Categoria TableColumn.header.savepath=Ruta de desada TableColumn.header.SeedingRank=Grau Sembrant TableColumn.header.totalspeed.info=Velocitat total de tots els iguals amb els quals esteu connectats TableColumn.header.totalspeed=Velocitat total splash.initializePlugins=Inicialitzant Complements StartStopRules.SPratioMet=LL:I Rati OK StartStopRules.FP0Peers=FP / 0 Iguals StartStopRules.0Peers=0 Iguals StartStopRules.numSeedsMet=# Llavors OK StartStopRules.ratioMet=Iguals:Llavor OK StartStopRules.shareRatioMet=Rati Compartir OK StartStopRules.waiting=Esperant StartStopRules.firstPriority=1a. Prioritat ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Compartir Contingut (Recursiu) DownloadManager.error.unabletostartserver=No es pot arrancar el Servidor - comprobi la configuraci\u00f3 del port entrant / i els permisos del tallafocs per la aplicaci\u00f3 que actua com a servidor GeneralView.label.creationdate=Creat en : ConfigView.section.tracker.announcescrapepercentage=Interval a Agafar com % d'edat de l'anunci\nex. 200 = 2:1. 0 = deixa decidir a l'Igual ManagerItem.stopping=Aturant ConfigView.section.tracker.announcecacheperiod=Cach\u00e9 de l'anunci (milisegs) ConfigView.section.tracker.scrapecacheperiod=Cach\u00e9 d'Agafar(milisegs) ConfigView.section.tracker.scrapeandcache=Agafar i cach\u00e9 ConfigView.section.tracker.announcecacheminpeers=Cach\u00e9 Anunci activa threshold de l'Igual fileDownloadWindow.retry=Reintentar MyTrackerView.bytesin=Bytes Entrants MyTrackerView.bytesinave=Mitjana entrant MyTrackerView.bytesout=Bytes Sortint MyTrackerView.bytesoutave=Mitjana sortint ConfigView.section.file.max_open_files=Nre. m\u00e0xim de fitxers oberts per lectura/escriptura\n[0: il\u00b7limitat] ConfigView.section.file.max_open_files.tooltip=\u00datil si descarregueu torrents que contenen centenars/milers de ftixer, i esteu arribant al l\u00edmit dels gestors de ftixers del sistema operatiu. ConfigView.section.proxy=Intermediari ConfigView.section.proxy.enable_proxy=Activar intermediari a les comunicacions del rastrejador [reinciar requerit] ConfigView.section.proxy.host=Hoste ConfigView.section.proxy.username=Nom d'Usuari ConfigView.section.proxy.password=Mot clau ConfigView.section.proxy.enable_socks=Jo tinc un intermediari SOCKS wizard.createtorrent.extrahashes=Afegir hashes per altres xarxes (ex. Gnutella2, eDonkey2000) GeneralView.label.connected=connectats GeneralView.label.in_swarm=en eixam ManagerItem.initializing=Inicialitzant AlertMessageBox.error=Error AlertMessageBox.warning=Alerta AlertMessageBox.comment=Informaci\u00f3 AlertMessageBox.information=Informaci\u00f3 AlertMessageBox.unread=Teniu misstages d'alerta pendents de llegir. Feu clic aqu\u00ed per mostrar-los. SharedPortServer.alert.selectorfailed=No es pot establir l'escolta per les dades entrants.\nComprovi que la configuraci\u00f3 del tallafocs permet que java(w).exe actui com un 'servidor' Tracker.alert.listenfail=No es pot establir l'escolta en el port %1.\nComprobi que les altres aplicacions no estiguin fent servir ja aquest port.\nTambe comprobi que no hi hagi en marxa una altra copia d'Azureus. DiskManager.alert.movefileexists=Error en moure els fitxers completats\nEl fitxer %1 ja existeix a la carpeta de destinaci\u00f3 DiskManager.alert.movefilefails=Error en moure fitxers completats\nMoure el fitxer %1 ha fallat, %2 DiskManager.alert.movefilerecoveryfails=Error recuperant despr\u00e9s de moure ha fallat\nRecuperaci\u00f3 del fitxer %1 ha fallat, %2 ConfigView.section.tracker.logenable=Apunta les estad\u00edstiques peri\u00f2diques al 'tracker.log' SpeedView.stats.title=Estats SpeedView.stats.session=Aquesta Sessi\u00f3 SpeedView.stats.downloaded=Descarregat SpeedView.stats.uploaded=Carregat (protocol) SpeedView.stats.uptime=Temps Pujant SpeedView.stats.now=Ara AutoMigration.useralert=Resultats de migraci\u00f3 autom\u00e0tica de fitxers/carpetes de configuraci\u00f3 d'usuari Vuze \n\n%1\nAlgunes fallades s'han de moure manualment.\nNO US OBLIDEU D'ACTUALITZAR LES C\u00d2PIES DE SEGURETAT DE LES CONFIGURACIONS SI LES HEU MOGUDES! # # > 2.0.8.0 # OpenTorrentWindow.title=Obrir Torrent(s) OpenTorrentWindow.message=Experimental OpenTorrentWindow.addFiles=&Afegeix fitxers OpenTorrentWindow.dataLocation=Ubicaci\u00f3 per desar dades: OpenTorrentWindow.startMode=Modus Afegir OpenTorrentWindow.startMode.queued=En Cua OpenTorrentWindow.startMode.stopped=Aturat OpenTorrentWindow.startMode.forceStarted=For\u00e7ar Arrancar OpenTorrentWindow.addPosition=Posici\u00f3 de Cua OpenTorrentWindow.addPosition.first=Primer OpenTorrentWindow.addPosition.last=\u00daltim TableColumn.header.remaining.info=Quantitat que falta per descarregar TableColumn.header.remaining=Faltant ConfigView.section.tracker.enablecompact=Activar protocol d'anunci compacte ConfigView.section.tracker.enablekey=Activar pas de clau al rastrejador per seguretat millorada ConfigView.section.file.perf=Opcions Rendiment ConfigView.section.file.perf.explain=Av\u00eds - canvis sense sentit en aquests par\u00e0metres poden afectar negativament el rendiment de desc\u00e0rrega. Cal reiniciar.\nSi teniu us quedeu sense mem\u00f2ria, plantegeu-vos de limitar les connexions per torrent. (Consulteu la configuraci\u00f3 de la transfer\u00e8ncia.) ConfigView.section.file.max_open_files.explain=Obrint massa ftixers podeu causar problemes al sistema operatiu a causa dels recursos limitats com gestors de fitxes. Aix\u00f2 limita el nombre de ftixers oberts al mateix temps. popup.error.hide=Amagar popup.error.details=Detalls ConfigView.section.style.colorOverrides=Sobreescriu Colors ConfigView.section.style.colorOverride.progressBar=Barra de Progr\u00e9s MainWindow.status.tooOld=\u00e9s vell, si us plau actualitza-ho ConfigView.section.style.colorOverride.warning=Av\u00eds ConfigView.section.style.colorOverride.altRow=Files Alternades ConfigView.section.file.save.peers.enable=Desa les connexions amb iguals per reconnectar-hi f\u00e0cilment ConfigView.section.file.save.peers.max=M\u00e0xim iguals per desar [0: il\u00b7limitat] ConfigView.label.max_peers_per_torrent=Nre. m\u00e0xim de connexions per torrent [0: il\u00b7limitat] ConfigView.label.max_peers_total=Nre. m\u00e0xim de connexions globament [0: il\u00b7limitat] ConfigView.section.style.colorOverrides.reset=Restablir Color ConfigView.section.language.info=Quan s'activa, es far\u00e0 una comprovaci\u00f3 d'actualitzaci\u00f3 quan arrenca Azureus. ConfigView.section.language.enableUpdate=Permet l'actualitzaci\u00f3 Web ConfigView.section.language.UpdateURL=URL d'Actualitzaci\u00f3 ConfigView.section.language.UpdateNow=Actualitza Ara! Button.revert=Desfer MyTorrentsView.menu.changeDirectory=Canvia la carpeta de dades GenericText.column=columna MyTorrentsView.menu.thisColumn.remove=Treu Columna MyTorrentsView.menu.thisColumn.toClipboard=Copia Texte al Portapapers MyTorrentsView.menu.tracker=Rastrejador ConfigView.download.abbreviated=D: ConfigView.complete.abbreviated=C: TableColumn.header.secondsseeding=Sembrant durant TableColumn.header.secondsseeding.info=Temps total que heu estat sembrant. TableColumn.header.secondsdownloading=Temps Enlla\u00e7 TableColumn.header.secondsdownloading.info=Temps total que heu estat descarregant. ConfigView.section.tracker.udpversion=Versi\u00f3 Protocol UDP (1 or 2) window.updateswt.title=La seva Versi\u00f3 SWT \u00e9s massa vella! window.updateswt.text=La vostra Versi\u00f3 SWT \u00e9s massa antiga!\nSWT \u00e9s la llibreria gr\u00e0fica que fa servir el Vuze i la versi\u00f3 que teniu \u00e9s massa vella per funcionar amb aquesta versi\u00f3 del Vuze. Cliqueu el bot\u00f3 Fet per actualitzar el SWT. window.updateswt.status=Estat window.updateswt.failed=L'actualitzaci\u00f3 ha fallat. Premeu OK un altre cop per reiniciar. window.updateswt.status.downloading.updater=Descarregant el Modul Actualitzador window.updateswt.status.finding=Buscant la ultima Versi\u00f3 SWT window.updateswt.status.downloading=Descarregant la ultima Versi\u00f3 SWT window.updateswt.status.done=Reiniciant window.updateswt.ok=D'acord window.updateswt.cancel=Cancel\u00b7la swt.updater.downloader.downloading=Descarregant SWT des de swt.updater.urlsgetter.downloading=Agafant una llista de miralls des de swt.updater.urlsgetter.platform=SWT per la plataforma : window.updateswt.ignore=Ignora ConfigView.section.style.useFancyTabs=Fer Servir Etiquetes Extravagants splash.initializeGM=Inicialitzant el Gestor Global de Torrents splash.loadingTorrents=Carregant Torrents MyTorrentsView.menu.thisColumn.sort=&Classificar Scrape.status.error.badURL=URL Anunci no segueix les specifications d'Scrape. Scrape.status.error.nohash=No hi ha Hash a la resposta. Scrape.status.error.invalid=Resposta Invalida. Scrape.status.nextScrapeAt=Seg\u00fcent scrape a %1 Scrape.status.initializing=Esperant per Scrape ConfigView.label.minSpeedForActiveSeeding=No comptis el torrent complet com fent servir un canal si la velocitat \u00e9s per sota dels ConfigView.section.stats.exportpeers=Exportar detalls d'Iguals MainWindow.menu.view.irc.moved=Irc est\u00e0 disponible com un complement. Vegeu http://azureus.sourceforge.net/plugin_list.php. Quan l'hagueu instal\u00b7lat feu servir el men\u00fa Visualitzaci\u00f3 >Complements > IRC per accedir-hi. MyTrackerView.webui.contextmenu.copyurl=Copiar URL del torrent al portapapers ConfigView.section.file.torrent.ignorefiles=Fitxers per ignorar quan creem torrents\nex. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignorant fitxer ConfigView.section.style.useUnitsRateBits=Fer servir bits en comptes de bytes per valors de rati basats en byte (KiB/s->Kibit/s etc.) ConfigView.section.interface.resetassoc=Ref\u00e9s les associacions de ftixers a l'Explorador (.torrent) ConfigView.section.interface.resetassocbutton=Refer ConfigView.section.interface.checkassoc=Comprova les associacions de fitxers en comen\u00e7ar dialog.associations.title=Comprova Associaci\u00f3 Button.yes=S\u00ed Button.no=&No ConfigView.label.seeding.autoStart0Peers=Auto-arrancar tots els torrents completats amb 0 iguals ConfigView.label.seeding.autoStart0Peers.tooltip=Activeu-ho si voleu que el rastrejador sempre llisti les llavors per als torrents amb 0 iguals dialog.associations.prompt=El Vuze no \u00e9s l'applicaci\u00f3 per defecte per a fitxers BitTorrent.\nVoleu associar fitxers .torrent amb elVuze? dialog.associations.askagain=Comprova al comen\u00e7ar ConfigView.section.plugins.update=Actualitzaci\u00f3 de Complements Plugin.pluginupdate.enablecheck=Activa comprovaci\u00f3 d'Actualitzaci\u00f3 de Complements plugins.basicview.status=Estat: plugins.basicview.activity=Activitat: plugins.basicview.progress=Progr\u00e9s: plugins.basicview.log=Anotar ConfigView.label.maxdownloadspeed=KB/s m\u00e0x velocitat de desc\u00e0rrega global [0: il\u00b7limitat] splash.loadingTorrent=Carregant Torrent splash.of=de UpdateWindow.title=Actualitzador d'Vuze UpdateWindow.header=Els seg\u00fcents components necessiten una actualitzaci\u00f3 : UpdateWindow.columns.install=Instal\u00b7la UpdateWindow.columns.name=Nom UpdateWindow.columns.version=Versi\u00f3 UpdateWindow.columns.size=Mida UpdateWindow.cancel=Cancel\u00b7la UpdateWindow.quit=Sortir UpdateWindow.close=Tancar UpdateWindow.ok=Actualitzar UpdateWindow.restart=Reiniciar UpdateWindow.status.downloading=Descarregant UpdateWindow.status.done=Fet UpdateWindow.status.failed=Fallat UpdateWindow.status.restartNeeded=Requerit Reiniciar! ConfigView.pluginlist.broken=Trencat ConfigView.pluginlist.whereToPut=Poseu els complements espec\u00edfics de l'usuari a la seva carpeta a: ConfigView.pluginlist.whereToPutOr=Pels complements compartits feu servir: MainWindow.statusText.checking=Comprovant Actualitzacions TableColumn.header.OnlyCDing4=NomesSembrant* TableColumn.header.OnlyCDing4.info=Quantitat de temps que el torrent ha estat nom\u00e9s sembrant. Exclueix el temps que el torrent estava descarregant (i sembrant). ConfigView.section.style.alternateTablePainting=Fes servir un m\u00e8tode alternatiu per pintar les columnes de taules gr\u00e0fiques (pot requerir un reinici) UpdateWindow.status.restartMaybeNeeded=Pot requerir Reiniciar ConfigView.pluginlist.shared=compartit PeersView.host=Nom Host PeersView.host.info=El nom de host de l'Igual, quan est\u00e0 disponible (pot afectar al rendiment) MainWindow.menu.help.whatsnew=Qu\u00e8 hi ha de Nou ? ConfigView.label.checkonstart=Comprovar l'\u00faltima versi\u00f3 quan Vuze arrenca ConfigView.label.periodiccheck=Cercar peri\u00f3dicament la ultima versi\u00f3 ConfigView.label.opendialog=Autom\u00e0ticament obrir l'Ajudant de Actualitzaci\u00f3 quan hi ha una actualitzaci\u00f3 disponible MainWindow.updateavail=Cliqui aqu\u00ed per Actualitzacions MainWindow.status.latestversionunchecked=Comprovaci\u00f3 de Versi\u00f3 desactivada GeneralView.label.updatein.stopped=Aturat StartStopRules.menu.viewDebug=Veure Informaci\u00f3 de depuraci\u00f3 ConfigView.section.style.doNotUseGB=No fer servir unitat GB ConfigView.section.style.doNotUseGB.tooltip=Si es marca, Vuze continuar\u00e0 fent servir MB incl\u00fas per mides m\u00e9s grans de 1024MB MainWindow.menu.help.plugins=Agafar Complements ConfigView.section.plugins.TrackerWeb=Web rastrejador ConfigView.section.tracker.enablecategories=Separar torrents per categoria health.explain.share=significa que el torrent \u00e9s allotjat o publicat ConfigView.section.tracker.createcert=Crear certificat auto-signat ConfigView.section.tracker.createbutton=Crear security.certcreate.title=Crear certificat auto-signat security.certcreate.intro=Aquest di\u00e0leg li deixa crear un certificat auto-signat security.certcreate.alias=Alies security.certcreate.strength=For\u00e7a security.certcreate.firstlastname=Nom i Cognoms security.certcreate.orgunit=Unitat Organitzativa security.certcreate.org=Organitzaci\u00f3 security.certcreate.city=Ciutat o Poble security.certcreate.state=Estat o Provincia security.certcreate.country=Codi pais de dues lletres security.certcreate.ok=Crear security.certcreate.cancel=Cancel\u00b7la security.certcreate.createok=Certificat creat satisfactoriament security.certcreate.createfail=Ha fallat la creaci\u00f3 del certificat ConfigView.section.plugins.webui=Interf\u00edcie Swing Web ConfigView.section.plugins.xml_http_if=Intef\u00edcie XML/HTTP webui.passwordenable=Activar password webui.user=Nom de l'Usuari webui.password=Mot Clau webui.homepage=P\u00e0gina Home (*) webui.rootdir=Carpeta arrel (*) webui.rootres=Recurs arrel (*) webui.mode=Modus (*) webui.mode.info=Modus pot ser\n\t"full"\t= disponibles totes les operacions (defecte)\n\t"view"\t= nomes veure (pero pot actualitzar la frequencia de refresc) webui.access=Acc\u00e9s (*) webui.access.info=L'acc\u00e9s pot ser\n\t"local"\t= significant que nom\u00e9s pot connectar la m\u00e0quina local\n\t"totes"\t= acc\u00e9s no restringit (defecte)\n\tIP\t= ex. 192.168.0.2\t\t\tuna IP nom\u00e9s\n\tIP1-IP2\t= ex. 192.168.0.1-192.168.0.255\tinterval inclosiu de IPs GeneralView.label.maxdownloadspeed=M\u00e0x Desc\u00e0rrega Security.keystore.corrupt=Magatzem de claus '%1' no es pot carregar, si us plau borreu-lo i torni a crear o a importar els certificats Security.keystore.empty=Magatzem de claus \u00e9s buit. Si us plau crear un certificat auto-signat (vegi Eines->Opcions->Seguretat) o importi un certificat existent dintre de '%1' webui.restart.info=Els Canvis a parametres marcats amb un (*) requereixen reiniciar per tenir efecte GeneralView.label.maxdownloadspeed.tooltip=Velocitat m\u00e0xima de desc\u00e0rrega [0: il\u00b7limitat] upnp.enable=Activar UPnP upnp.info=Universal Plug and Play (UPnP) permet el mapa autom\u00e0tic de ports en routers amb UPnP activat. upnp.mapping.dataport=Port entrant de dades de l'Igual upnp.mapping.tcptrackerport=Port TCP del rastrejador upnp.mapping.udptrackerport=Port UDP del rastrejador upnp.alert.differenthost=UPnP: Mapejat de '%1' ha estat reservat per '%2' - si us plau seleccioni un port diferent upnp.alert.mappingok=UPnP: Mapejat de '%1' establert upnp.alert.mappingfailed=UPnP: Mapejat de '%1' fallat upnp.alertsuccess=Informa de mapejats satisfactoris upnp.alert.lostdevice=UPnP: S'ha perdut la connexi\u00f3 al servei '%1' en el dispositiu UPnP '%2' upnp.grabports=Mapejar ports inclos si pertanyen a un altre ordinador upnp.refresh.label=Refrescar els mapejats upnp.refresh.button=Refrescar upnp.alert.mappinggrabbed=UPnP: Mapejat '%1' establert - agafat des de '%2' upnp.mapping.tcpssltrackerport=Port TCP SSL del rastrejador upnp.alertothermappings=Informa de ports que pertanyen a altres ordinadors upnp.alertdeviceproblems=Informa de problemes amb el dispositiu UPnP upnp.wiki_link=P\u00e0gina Wiki del Vuze a UPnP ConfigView.pluginlist.coreplugins=S'han carregat els seg\u00fcents complements interns Peers.column.DLedFromOthers=Des d'altres Peers.column.DLedFromOthers.info=Quantitat de dades descarregades des d'altres mentre estaven connectats amb vosaltres Peers.column.UpDownRatio=Pujat:Baixat Peers.column.UpDownRatio.info=R\u00e0tio d'iguals "Carregat : Descarregat" Peers.column.UpRatio=R\u00e0tio c\u00e0rrega Peers.column.UpRatio.info=R\u00e0tio d'iguals "Carregat meu : Carregat dels altres" upnp.releasemappings=Lliberar mapejats al tancar webui.upnpenable=Activar UPnP per aquest port (*) ConfigView.section.file.friendly.hashchecking=Comprovaci\u00f3 de hash amistosa ConfigView.section.file.friendly.hashchecking.tooltip=Un modus de comprovar el hash lleugerament mes lent, pero amb molt menys esfor\u00e7 de cpu/sistema. ConfigView.section.tracker.seedretention=M\u00e0xim de llavors retingudes per torrent [0: il\u00b7limitat] ConfigView.section.tracker.seedretention.info=Nota: Les estad\u00edstiques de c\u00e0rrega es perdran per les llavors no retingudes ConfigView.section.tracker.port=Activar rastrejador en port HTTP ConfigView.section.tracker.sslport=Activar rastrejador en port HTTPS ConfigView.section.tracker.publicenable.info=Permet que els altres cre\u00efn torrents que fan servir el nostre rastrejador\nsense que nosaltres els allotgem o publiquem Button.clear=Netejar MainWindow.IPs.tooltip=\u00daltima actualitzaci\u00f3 de la llista de filtres: %1\nTotal IPFiltres a la llista - Nombre de IPs bloquejades/vetat/dolentes aquesta sessi\u00f3.\nDoble clic per detalls. ConfigView.section.ipfilter.list.banned=ha estat vetat ConfigView.section.ipfilter.list.baddata=ha enviat dades dolentes: vegades = Button.reset=Restablir ConfigView.section.ipfilter.bannedinfo=IPs que han enviat dades dolentes - vetat si excedeix els l\u00edmits ConfigView.section.ipfilter.blockedinfo=IPs que han estat bloquejades a causa dels filtres IP download.removerules.name=Regles de Treure download.removerules.unauthorised.info=Torrents no autoritzats s\u00f3n aquells que la resposta de l'anunci cont\u00e9 tant "not authoris(z)ed" o "unauthoris(z)ed" en la resposta de fallada download.removerules.unauthorised=Autom\u00e0ticament treure torrents no autoritzats download.removerules.unauthorised.seedingonly=\tNom\u00e9s si est\u00e0 sembrant download.removerules.removed.ok=Eliminaci\u00f3 autom\u00e0tica del torrent '%1' satisfact\u00f2ria. S'ha fet a causa de les regles d'eliminaci\u00f3 de torrents. download.removerules.updatetorrents=Treure torrents d'actualitzaci\u00f3 d'Vuze si l'eixam ho requereix ConfigView.label.defaultstarttorrentsstopped=Afegir per defecte els nous torrents en estat aturat ConfigView.section.server.enableudp=Activa protocol UDP del rastrejador client. upnp.mapping.dataportudp=Port UDP client rastrejador ConfigView.section.file.decoder.showlax=Mostrar codificacions menys normals ConfigView.section.file.decoder.showall=Considerar totes les codificacions possibles MainWindow.status.updowndetails.tooltip=Detalls de velocitat c\u00e0rrega/desc\u00e0rrega - Cliqueu al bot\u00f3 dret per canviar-ho i feu doble clic per obrir les estad\u00edstiques TrackerClient.announce.warningmessage=Rastrejador per '%1' ha tornat l'avis '%2' ConfigView.section.tracker.natcheckenable=Comprovi la connectivitat del 'port de dades entrant' i informi als iguals de fallades ConfigView.section.tracker.publishenabledetails=Publiqueu el fitxer torrent i els detalls dels iguals ConfigView.section.tracker.publishenablepeerdetails=Publiqui detalls dels Iguals MyTrackerView.badnat=NAT dolenta MyTrackerView.badnat.info=Llavors/Iguals que han fallat en comprovaci\u00f3 de NAT, si activada ConfigView.section.tracker.natchecktimeout=Comprova temps l\u00edmit (segons) ConfigView.section.file.perf.cache.enable=Activa cach\u00e9 de disc ConfigView.section.file.perf.cache.size=Mida del cach\u00e9 en %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=T&ransfer\u00e8ncies MainWindow.menu.transfers.startalltransfers=&Arrancar Tot MainWindow.menu.transfers.stopalltransfers=A&turar Tot MainWindow.menu.transfers.pausetransfers=&Pausa MainWindow.menu.transfers.resumetransfers=&Resumir ConfigView.label.experimental.osx.kernel.panic.fix=Arreglo experimental per kernel panics sobre sistemes dual-cpu OSX [requireix re-arrancar] SystemTray.menu.pausetransfers=Pausa Transfer\u00e8ncies SystemTray.menu.resumetransfers=Resumir Transfer\u00e8ncies ConfigView.section.file.truncate.too.large=Parteix els fitxers existents que s\u00f3n massa llargs ConfigView.section.file.perf.cache.trace=Apunta operacions del cach\u00e9 per prop\u00f2sits de diagnostic ConfigView.section.interface.enabletray=Activar la safata del sistema (es necessita reengegar) PeerManager.status.error=Error Stats.title.full=Estad\u00edstiques TransferStatsView.title.full=Transfer\u00e8ncies CacheView.title.full=Cach\u00e9 CacheView.general.size=Mida total CacheView.general.inUse=En \u00fas CacheView.general.title=Info de cach\u00e9 CacheView.reads.title=Lectures E/S CacheView.reads.fromFile=Des de fitxer CacheView.reads.fromCache=Des de Cach\u00e9 CacheView.reads.hits=Encerts CacheView.writes.title=Escriptures E/S CacheView.writes.toCache=Cap a Cach\u00e9 CacheView.writes.toFile=Cap a fitxer CacheView.writes.hits=Desat CacheView.speeds.title=Transfer\u00e8ncia Dades CacheView.speeds.reads=Lectures CacheView.speeds.writes=Escriptures CacheView.speeds.fromCache=Des de/Cap a Cach\u00e9 CacheView.speeds.fromFile=Des de/Cap a fitxer CacheView.reads.#=Nre. CacheView.reads.amount=Quantitat CacheView.reads.avgsize=Mida mitjana openUrl.referrer=P\u00e0gina referida a URL : openUrl.referrer.info=Nom\u00e9s necessari per llocs web que ho manen aix\u00ed ConfigView.label.maxuploadspeedseeding=KB/s m\u00e0x. velocitat c\u00e0rrega global quan nom\u00e9s estem sembrant [0: il\u00b7limitat] ConfigView.label.transfer.ignorepeerports=Ignorar Iguals amb aquests ports de dades (';' separats, p.ex. 0;25) ConfigView.section.proxy.enable_socks.peer=Activeu l'intermediari de comunicacions amb iguals (connexions sortints nom\u00e9s) [cal reiniciar] ConfigView.section.proxy.peer.informtracker=Informar al rastrejador dels l\u00edmits ConfigView.section.proxy.socks.version=Versi\u00f3 SOCKS PiecesView.legend.written=Escrit PiecesView.legend.requested=Demanat PiecesView.legend.downloaded=Descarregat, pendent d'escriure PiecesView.legend.incache=Dades son al Cach\u00e9 PiecesView.typeItem.0=Lent PiecesView.typeItem.1=R\u00e0pid PiecesView.type=Tipus Security.jar.tools_not_found=Signar JAR falla - 'tools.jar' no trobat a %1. Veure Eines->Opcions->Seguretat per detalls. Security.jar.signfail=Signar JAR falla - %1 ConfigView.section.security.toolsinfo=El fitxers JAR signats es fan servir per suportar alguns complements, per exemple el Swing Web Interface (quan s'ha configurat per fer-ho).\nPer signar fitxers JAR cal tenir acc\u00e9s al fitxer 'tools.jar' prove\u00eft amb la instal\u00b7laci\u00f3 del Sun JDK (no JRE).\nSi nom\u00e9s teniu instal\u00b7lat el JRE, si us plau instal\u00b7leu el JDK.\nNormalment el Vuze us pot trobar el fitxer. De totes maneres, si falla podeu esciure el nom de la carpeta que el cont\u00e9. ConfigView.section.security.toolsdir=Carpeta que cont\u00e9 'tools.jar' ConfigView.section.security.choosetoolssavedir=Seleccioni carpeta que cont\u00e9 'tools.jar' authenticator.torrent=Torrent ConfigView.section.proxy.peer.same=Fer servir la mateixa configuraci\u00f3 d'intermediari per les comunicacions del rastrejador i dels Iguals ConfigView.section.connection.network.max.simultaneous.connect.attempts=Nre. m\u00e0xim de connexions simult\u00e0nies sortint [0: desactivar sortida] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Nombre m\u00e0xim de noves connexions sortints que Vuze ha d'intentar en tot moment.\nNOTA: WindowsXP Service Pack 2 (SP2) imposa un l\u00edmit per tot el sistema de 10 intents simultanis.\nEl valor per defecte \u00e9s 8. El valor 0 desactiva totalment les connexions sortints. ConfigView.section.file.perf.cache.size.explain=El cach\u00e9 es fa servir per reduir lectures i escriptures al disc. A menys que feu servir l'opci\u00f3 Java '-XX:MaxDirectMemorySize' per posar la mem\u00f2ria disponible per fer servir en cach\u00e9 i E/S de xarxa, heu de mantenir aquest valor almenys %1 per sota de la mida VM m\u00e0xima. La mida VM m\u00e0xima actual \u00e9s %2. Per instruccions sobre com canviar-ho, aneu a MemoryUsage a la Wiki a %3. Les fallades en fer servir configuracions correctes provocaran errors del tipus 'out of memory'. M\u00e9s de 32 MB de cach\u00e9 probablement \u00e9s excessiu. MyTorrentsView.menu.setSpeed.unlimit=Sense limit MyTorrentsView.menu.setSpeed.unlimited=Il\u00b7limitat MyTorrentsView.menu.setSpeed.disable=Desactiva la c\u00e0rrega MyTorrentsView.menu.setSpeed.disabled=Desactivat MyTorrentsView.menu.setSpeed.in=entrada MyTorrentsView.menu.setSpeed.slots=canals de GeneralView.label.maxuploadspeed=M\u00e0x. c\u00e0rrega GeneralView.label.maxuploadspeed.tooltip=m\u00e0xima velocitat c\u00e0rrega [0 : il\u00b7limitat] MyTorrents.items.UpSpeedLimit.disabled=No carreguis MyTorrents.items.UpSpeedLimit.unlimited=Il\u00b7limitat TableColumn.header.maxupspeed=M\u00e0x. velocitat c\u00e0rrega TableColumn.header.maxupspeed.info=Velocitat m\u00e0xima de c\u00e0rrega per torrent ConfigView.section.file.perf.cache.enable.write=Cach\u00e9 de dades en desc\u00e0rrega per redu\u00efr escriptures a disc i tamb\u00e9 redu\u00efr lectures demanades per comprovaci\u00f3 de peces ConfigView.section.file.perf.cache.enable.read=Fer lectures anticipades per reduir lectures a disc quan pujem dades ConfigView.section.tracker.separatepeerids=Fer servir identitats diferents per comunicaci\u00f3\ndel rastrejador i de dades ConfigView.section.tracker.separatepeerids.info=Augmenta l'anonimat si descarreguem i sembrem an\u00f3nimament\nmentre fem servir una connexi\u00f3 no-an\u00f3nima del rastrejador ConfigView.section.interface.wavlocation=Ubicaci\u00f3 del fitxer .wav ConfigView.section.interface.wavlocation.info=Seleccioneu el fitxer .wav, o deixeu-ho en blanc pel so definit per defecte ConfigView.section.tracker.server=Servidor ConfigView.section.tracker.client.connecttimeout=Temps l\u00edmit Connexi\u00f3 (segons) ConfigView.section.tracker.client.readtimeout=Temps l\u00edmit Lectura (segons) MainWindow.menu.tools=&Eines FilesView.path=Ruta FilesView.fullpath=Mostra la ruta completa FilesView.remaining=Peces Faltants TableColumn.header.trackername=Nom del Rastrejador TableColumn.header.trackername.info=Nom del rastrejador basat en URL de l'anunci ConfigView.group.override=Opcions de sobreescriptura ConfigView.section.file.perf.cache.notsmallerthan=No feu cach\u00e9 de ftixers m\u00e9s petits que (en %1) PeersView.menu.blockupload=Bloquejar c\u00e0rrega PeersView.menu.kickandban=Patejar i Bloquejar PeersView.menu.kickandban.reason=Igual bloquejat manualment PeersView.state=Estat PeersView.state.info=Estat de la connexi\u00f3 amb l'Igual PeersView.state.pending=Pendent PeersView.state.connecting=Connectant PeersView.state.handshake=Esperant per handshake PeersView.state.established=Completament establert ConfigView.section.tracker.processinglimits=Processant l\u00edmits ConfigView.section.tracker.maxgettime=M\u00e0xim temps per processar GET (segons) [0: il\u00b7limitat] ConfigView.section.tracker.maxgettime.info=Usat per anuncis and scrapes ConfigView.section.tracker.maxposttimemultiplier=AGAFA multiplicador de temps per POST-processament [0: il\u00b7limitat] ConfigView.section.tracker.maxposttimemultiplier.info=Es fa servir per sotmetre formularis i c\u00e0rregues ConfigView.section.tracker.maxthreads=M\u00e0xim peticions concurrents DownloadManager.error.operationcancancelled=Operaci\u00f3 cancel\u00b7lada Torrent.create.progress.cancelled=Operaci\u00f3 cancel\u00b7lada sharing.progress.cancel=Cancel\u00b7la wizard.maketorrents.autoopen=Obre el torrent per sembrar quan completat ConfigView.section.sharing.rescanenable=Habilita el reescaneig peri\u00f2dic dels compartits per canvis ConfigView.section.sharing.rescanperiod=Periode de Re-scan (segons) ConfigView.section.connection.advanced=Opcions de xarxa avan\u00e7ades ConfigView.section.connection.advanced.mtu=Unitat M\u00e0xima Transmissi\u00f3 de la Linia (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Mida m\u00e0xima d'un paquet que pot ser transferit en una frame sobre una xarxa.\nVuze fa servir MTU-40 (MSS) per optimitzacions de pujar packet-payload.\nValors recomanats:\n 576 - Conexions linia telef\u00f3nica\n1492 - Conexions banda ample PPPoE\n1500 - Conexions banda ample Ethernet, DSL i Cable ConfigView.section.connection.advanced.SO_RCVBUF=Mida del s\u00f2col SO_RCVBUF [0: usar defalt OS] ConfigView.section.connection.advanced.SO_SNDBUF=Mida del s\u00f2col SO_SNDBUF [0: usar defalt OS] ConfigView.section.interface.confirm_torrent_removal=Mostra el di\u00e0leg de confirmaci\u00f3 quan esborris un torrent ConfigView.section.interface.confirm_torrent_removal.tooltip=Confirmar quan s'esborri un torrent de la vista "Els meus Torrents". MyTorrentsView.confirm_torrent_removal=Est\u00e0 seguir de que el vol treure ?\n TableColumn.header.seed_to_peer_ratio.info=Rati Total de llavors a l'eixam per Iguals PeersView.connected_time=Temps Connectat PeersView.connected_time.info=Temps Total connectat amb l'Igual ConfigView.section.interface.display.add_torrents_silently=Afegir torrents silenciosament ConfigView.section.interface.display.add_torrents_silently.tooltip=Afegir desc\u00e0rregues de torrent sense activar la pantalla principal d'Vuze TableColumn.header.maxdownspeed=M\u00e0x Velocitat Desc\u00e0rrega TableColumn.header.maxdownspeed.info=M\u00e0x Velocitat Desc\u00e0rrega per torrent PeersGraphicView.title=Eixam ConfigView.section.tracker.passwordwebhttpsonly=Nom\u00e9s permetre acc\u00e9s via HTTPS TableColumn.header.torrentpath=Ubicaci\u00f3 Torrent TableColumn.header.torrentpath.info=Ubicaci\u00f3 del Torrent en disc ConfigView.section.sharing.torrentcomment=Comentari per torrents generats ConfigView.label.copyanddeleteratherthanmove=Copia i esborra les dades originals en comptes de moure-les en una sola operaci\u00f3 - pot ajudar a evitar p\u00e8dues de dades en alguns sistemes de fitxers ConfigView.label.openstatsonstart=Obrir estad\u00edstiques al comen\u00e7ar swt.install.window.title=Complement instal\u00b7lador del Vuze swt.install.window.ok=Instal\u00b7la swt.install.window.header=S'han seleccionat els components seg\u00fcents per a instal\u00b7laci\u00f3: swt.uninstall.window.title=Complement Treure d'Vuze swt.uninstall.window.ok=Treu swt.uninstall.window.header=Els seg\u00fcents components han sigut seleccionats per treure : installPluginsWizard.title=Instal\u00b7la complements installPluginsWizard.mode.title=Si us plau, trieu un m\u00e8tode d'instal\u00b7laci\u00f3 installPluginsWizard.mode.list=Per llista des de sourceforge.net installPluginsWizard.list.title=Llista de complements instal\u00b7lables installPluginsWizard.list.loading=Esperi Si us plau mentre es carrega la llista de complements. installPluginsWizard.list.loaded=Si us plau, trieu els complements que vol instal\u00b7lar. installPluginsWizard.list.name=Nom installPluginsWizard.list.version=Versi\u00f3 installPluginsWizard.list.description=Descripci\u00f3 del Complement installPluginsWizard.finish.title=Instal\u00b7laci\u00f3 en progr\u00e9s installPluginsWizard.finish.explanation=Els complements seleccionats s'instal\u00b7laran fent sevir l'assistent d'actualitzaci\u00f3.\n\nSi us plau, tingueu paci\u00e8ncia, aix\u00f2 pot tardar un moment a apar\u00e8ixer.\n\nPer un informe de progr\u00e9s, feu doble clic a l'esquerra de la barra d'estat. installPluginsWizard.details.loading=Carregant detalls, esperi si us plau ... installPluginsWizard.mode.file=Per fitxer installPluginsWizard.installMode.title=Si us plau trieu el tipus d'instal\u00b7laci\u00f3 installPluginsWizard.installMode.user=Instal\u00b7la el(s) complement(s) nom\u00e9s per a mi installPluginsWizard.installMode.shared=Instal\u00b7la el(s) complement(s) per a tots els usuaris installPluginsWizard.file.title=Si us plau, trieu el complement que voleu instal\u00b7lar installPluginsWizard.file.file=Ftixer: installPluginsWizard.file.invalidfile=El ftixer no \u00e9s un complement v\u00e0lid del Vuze. installPluginsWizard.file.browse=Trii... uninstallPluginsWizard.title=Desinstal\u00b7la complements uninstallPluginsWizard.list.title=Llista de complements instal\u00b7lats uninstallPluginsWizard.list.loaded=Si us plau, trieu els complements que voleu desinstal\u00b7lar. installPluginsWizard.list.nullversion=No hi ha Versi\u00f3 uninstallPluginsWizard.finish.title=Desinstal\u00b7laci\u00f3 en progr\u00e9s uninstallPluginsWizard.finish.explanation=Els components seleccionats seran desinstal\u00b7lats fent servir l'assistent d'actualitzaci\u00f3. MainWindow.menu.plugins.installPlugins=Assistent d'instal\u00b7laci\u00f3... MainWindow.menu.plugins.uninstallPlugins=Assistent de desinstal\u00b7laci\u00f3... ConfigView.section.ipfilter.totalIPs=%1 IPs bloquejades en total, que \u00e9s el %2 de l'internet. update.instance.install=Comprovant la instal\u00b7laci\u00f3 update.instance.uninstall=Comprovant la desinstal\u00b7laci\u00f3 update.instance.update=Cercant Actualitzacions MainWindow.status.update.tooltip=Faci Doble-clic per informaci\u00f3 de progr\u00e9s updater.progress.window.title=Tasques actuals d'instal\u00b7laci\u00f3 updater.progress.window.info=Premi 'Abortar' per acabar totes les feines pendents Button.abort=Abortar ConfigView.section.ipfilter.enablebanning=Vetar iguals que constantment envien dades dolentes Network.alert.acceptfail=Han ocurregud massa fallades seguides en el port %1, %2 - proc\u00e9s abandonat. Si us plau comprovi la configuraci\u00f3 del tallafocs per aquest port per assegurar-se de que est\u00e0 activat per rebre. MyShares.column.category=Categoria UpdateWindow.restartLater=Reiniciar m\u00e9s tard MainWindow.menu.file.restart=Reiniciar Vuze MainWindow.dialog.restartconfirmation.title=Reiniciar Vuze MainWindow.dialog.restartconfirmation.text=Segur que voleu reiniciar el Vuze? deletetorrent.message1=Esteu a punt d'esborrar el TORRENT per a:\n deletetorrent.message2=\nEsta segur de que vol seguir? ConfigView.label.prioritizemostcompletedfiles=D\u00f3na prioritat als fitxers m\u00e9s complets splash.plugin.init=Inicialitzant Complement: ConfigView.section.style.osx_small_fonts=Fer servir lletra petita [requireix reiniciar] ConfigView.section.tracker.tcpnonblocking=Fer servir E/S sense bloquejar per el proc\u00e9s TCP del rastrejador. Seleccionant aquesta opci\u00f3 requereix que la web del rastrejador vagi en un altre port. Experimental! ConfigView.section.tracker.nonblocking=Opcions de No-bloquejar ConfigView.section.tracker.nonblockingconcmax=M\u00e0xim connexions concurrents [0: il\u00b7limitat] MyTorrentsView.menu.exportmenu=Exportar MyTorrentsView.menu.exporttorrent=Torrent... ConfigView.group.scrape=Connexi\u00f3 ConfigView.section.tracker.client.scrapeinfo=Desactivar scraping far\u00e0 que no funcionin moltes de les regles de cua dels torrents\nja que aquestes van segons la informaci\u00f2 de l'eixam recuperada per els rastrejadors d'scraping. ConfigView.section.tracker.client.scrapeenable=Activar scraping ConfigView.section.tracker.client.scrapestoppedenable=Fer Scrape dels torrents que no estan en marxa Scrape.status.disabled=Desactivar scraping MyTorrentsView.menu.explore=Mostra el fitxer MyTorrentsView.menu.explore._mac=Mostra-ho al cercador MyTorrentsView.menu.explore._windows=Mostra-ho a l'explorador wizard.maketorrents.autohost=Allotjar el torrent en el rastrejador intern ConfigView.label.overrideip=Establir IP enviada al rastrejador (NAT) ConfigView.label.overrideip.tooltip=Informar al rastrejador de diferents adreces IP que la que venen els paquets sortints- Deixi en blanc per no fer servir aquesta opci\u00f3. ConfigView.section.connection.group.networks=Xarxes ConfigView.section.connection.group.networks.info=Seleccioni les xarxes permeses per defecte per transmissio de dades igual a igual ConfigView.section.connection.networks.prompt=Demani una seleccio quan s'afegeix una desc\u00e0rrega amb un rastrejador an\u00f2nim ConfigView.section.connection.networks.Public=Xarxa IP P\u00fablica (no an\u00f2nim) ConfigView.section.connection.networks.I2P=Xarxa I2P ConfigView.section.connection.networks.Tor=Xarxa 'The Onion Router (Tor)' TableColumn.header.networks=Xarxes TableColumn.header.networks.info=Xarxes permeses per comunicaci\u00f3 de dades igual a igual Scrape.status.networkdisabled=Xarxa no activada ConfigView.section.tracker.server.group.networks=Xarxes ConfigView.section.tracker.server.group.networks.info=Seleccioni les Xarxes per les que el rastrejador acceptar\u00e0 Iguals window.networkselection.title=Selecci\u00f3 de xarxes window.networkselection.info=El torrent seg\u00fcent t\u00e9 rastrejador(s) que suporten les xarxes seg\u00fcents.\nSeleccioneu les que activem per comunicaci\u00f3 amb el rastrejador i els Iguals.\nSi un rastrejador an\u00f2nim que suporta clients p\u00fablics activa tant les xarxes an\u00f2nima com p\u00fablica.\nActivar la xarxa p\u00fablica t\u00e9 la conseq\u00fc\u00e8ncia \u00f2bvia de la p\u00e8rdua d'anonimat! plugins.basicview.clear=Netejar ConfigView.section.connection.group.peersources=Origens d'Iguals ConfigView.section.connection.group.peersources.info=Seleccioneu els or\u00edgens permesos per defecte per connexions amb iguals ConfigView.section.connection.peersource.Tracker=Des d'un rastrejador ConfigView.section.connection.peersource.DHT=Rastrejador Descentralitzat ConfigView.section.connection.peersource.PeerExchange=Prove\u00eft per un altre Igual ConfigView.section.connection.peersource.Plugin=Afegit per un complement ConfigView.section.connection.peersource.Incoming=Connexi\u00f3 entrant PeersView.source=Origen PeersView.source.info=L'origen d'aquest igual TableColumn.header.peersources=Origens d'Iguals TableColumn.header.peersources.info=Or\u00edgens d'Iguals permesos per establir connexions entre iguals wizard.tracker.dht=Descentralitzat (clients Vuze nom\u00e9s) MyTorrentsView.menu.advancedmenu=Avan\u00e7at MyTorrentsView.menu.networks=Xarxes MyTorrentsView.menu.peersource=Origens d'Iguals ConfigView.section.sharing.permitdht=Permetre rastreig descentralitzat quan el rastrejador no \u00e9s disponible ConfigView.section.sharing.protocol=Protocol per a recursos compartits PeersView.Messaging=Missatges PeersView.Messaging.info=Suporta missatges API avan\u00e7ats. ConfigView.label.queue.newseedsmovetop=Mou els nous torrents complets davant de la llista de sembra. ConfigView.label.seeding.firstPriority.ignore.info=Vagi amb compte que fent servir aquestes regles pot fer aturar un torrent\ntant aviat com la desc\u00e0rrega acaba. ConfigView.label.seeding.firstPriority.ignore=Ignorar les anteriors regles de Primera Prioritat per: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents amb un rati Llavors a Iguals per sobre de ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents amb 0 Iguals ConfigView.section.tracker.sendjavaversionandos=Envia versi\u00f3 Java i nom del Sistema Operatiu MagnetPlugin.contextmenu.exporturi=Copia URI Magnet al portapapers ConfigView.section.plugins.dht=Base de Dades Distribuida dht.info=Aquest complement soporta rastreix descentralitzat, aprart d'altres coses, - desactivant-lo pot redu\u00efr la seva habilitat per descarregar dht.enabled=Activa la base de dades distribuida dht.portdefault=Fes servir el port per defecte dht.port=Port UDP per la base de dades dht.execute.command=Diagnosticar Ordre dht.execute.info=Premi aqu\u00ed per executar l'Ordre dht.execute=Executar dht.logging=Activar tra\u00e7a d'activitat ConfigView.section.plugins.dhttracker=Rastrejador Distribuit dhttracker.tracknormalwhenoffline=Nom\u00e9s rastrejar torrents normals quan el seu rastrejador no est\u00e0 disponible ConfigView.section.logging.generatediagnostics=Generar ConfigView.section.logging.netinfo=Genera informaci\u00f3 de la xarxa ConfigView.section.logging.statsinfo=Genera informaci\u00f3 d'estats ConfigView.section.logging.generatediagnostics.info=Genera informaci\u00f3 de diagn\u00f2stic i copia al porta-retalls i el fitxer log, si es configura ConfigView.section.sharing.privatetorrent=Torrent privat - nom\u00e9s accepta iguals del tracker MainWindow.menu.tools.nattest=Prova &NAT / Tallafocs Button.apply=Aplicar Button.close=Tancar window.welcome.title=Benvinguts a Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Notes de la Distribuci\u00f3 dht.reseed.label=Normalment no cal resembrar la dase de Dades Distribuida. Tanmateix, si hi ha un nombre baix de contactes aix\u00f2 pot fer-se servir per re-integrar-los.\nDeixu-ho ne blanc per no engegar amb iguals connectats, o b\u00e9 escriviu un IP i un port per tal d'expl\u00edcitament engegar des d'un igual connectat. dht.reseed.group=Resembrar dht.reseed.ip=Adre\u00e7a IP dht.reseed.port=Port dht.reseed=Resembrar dht.reseed.info=Resembrar bse de dades dht.diagnostics.group=Diagn\u00f2stics DHTView.title.full=Base de Dades Dsitribu\u00efda DHTView.title.fullcvs=CVS de la Base de Dades Dsitribu\u00efda DHTView.general.title=General DHTView.general.uptime=Temps sembra: DHTView.general.users=Usuaris: DHTView.general.nodes=Nodes: DHTView.general.leaves=Abandonaments: DHTView.general.contacts=Contactes: DHTView.general.replacements=Substitucions: DHTView.general.live=Vius: DHTView.general.unknown=Inconegut: DHTView.general.dying=Moribunds: DHTView.transport.title=Detalls de Transport DHTView.transport.packets=Paquets DHTView.transport.bytes=Bytes DHTView.transport.received=Rebuts DHTView.transport.sent=Tramesos DHTView.transport.in=De : DHTView.transport.out=Vers : DHTView.operations.title=Detalls Operatius DHTView.operations.sent=Tram\u00e8s DHTView.operations.ok=D'acord DHTView.operations.failed=Fallida DHTView.operations.received=Rebut DHTView.operations.ping=Ping DHTView.operations.findNode=Trobar Node DHTView.operations.findValue=Trobar Valor DHTView.operations.store=Emmegatzemar DHTView.activity.title=Activitat DHTView.activity.status=Estat DHTView.activity.status.true=En cua DHTView.activity.status.false=Funcionant DHTView.activity.type=Tipus DHTView.activity.target=Objectiu DHTView.activity.details=Detalls DHTView.db.title=Base de Dades DHTView.db.keys=Claus DHTView.db.values=Valors DHTView.db.local=Local DHTView.db.direct=Directe DHTView.db.indirect=Indirecte DHTView.db.divfreq=Div. Freq. DHTView.db.divsize=Div. Mida MainWindow.dht.status.tooltip=Quan funciona la Base de Dades Distribu\u00efda es mostra le nombre estimat d'usuaris actuals MainWindow.dht.status.disabled=Inhbilitat MainWindow.dht.status.failed=Fallida MainWindow.dht.status.initializing=Inicialitzaci\u00f3 MainWindow.dht.status.users=%1 Usuaris MainWindow.dht.status.unreachable=Tallafocs DHT MainWindow.dht.status.unreachabletooltip=Sembla que hi ha un problema amb la correspond\u00e8ncia de ports (NAT) UDP de la Base de Dades Distribu\u00efda ConfigView.section.tracker.client.showwarnings=Mostrar missatges d'av\u00eds declarats pels trackers dht.advanced=Habilitar cofiguraci\u00f3 avan\u00e7ada dht.advanced.group=Configuraci\u00f3 avan\u00e7ada dht.advanced.label=Nom\u00e9s si sabeu el que us feu podeu modificar-ne els valors dht.override.ip=Substituir adre\u00e7a externa IP ConfigView.section.logging.loggerenable=Habilita el registre ConfigView.section.ipfilter.blockbanning=Prohibir un bloc de 256 adreces quan altres tantes del bloc ja han estat prohibides MyTrackerView.passive=Passiu TableColumn.header.swarm_average_speed=Velocitat Mitjana Eixam MyTrackerView.category=Categoria MainWindow.menu.file.open.torrentfortracking=Fitxer Torrent File... (Nom\u00e9s Tracking) MyTrackerView.date_added=Afegit ConfigView.section.tracker.portbackup=Ports de c\u00f2pia de seguretat (seprats amb ';' ) ConfigView.label.playfilespeech=Paralr quan s'ha acabat el fitxer ConfigView.label.playfilefinished=Fer un so quan s'ha acabat el fitxer ConfigView.label.backupconfigfiles=Fer c\u00f2pia de seguretat dels fitxers de configuraci\u00f3 per tal de poder fer llur recuperaci\u00f3 ConfigView.section.tracker.client.scrapesingleonly=Inhabilitar agregaci\u00f3 scrape per tracker scrape (pot fer servei amb trackers que declaren errors 'URL masa llarga' (414)) dht.ipfilter.log=Enregistrar violacions del Filtre IP ActivityView.legend.limit=L\u00edmit ratio ActivityView.legend.achieved=Ratio assolida ActivityView.legend.peeraverage=Mitjana ActivityView.legend.swarmaverage=Mitjana eixam ActivityView.legend.trimmed=Retallat (suspensius) MyTorrentsView.menu.movemenu=Mou fitxers MyTorrentsView.menu.movedata=Mou fitxers de dades... MyTorrentsView.menu.movetorrent=Mou fitxers torrent... DHTView.operations.data=Dades DHTView.general.reachable=A l'abast: DHTView.general.rendezvous=Cites: ConfigView.label.queue.maxactivetorrentswhenseeding=M\u00e0xim quan sembreu [0:sense l\u00edmit] Views.plugins.IRC.title=IRC - Suport T\u00e8cnic En L\u00ednia Formats.units.persec=/s Formats.units.TiB=TiB Formats.units.Tibit=Tibit Formats.units.TB=TB Formats.units.Tbit=Tbit Formats.units.GiB=GiB Formats.units.Gibit=Gibit Formats.units.GB=GB Formats.units.Gbit=Gbit Formats.units.MiB=MiB Formats.units.Mibit=Mibit Formats.units.MB=MB Formats.units.Mbit=Mbit Formats.units.KiB=KiB Formats.units.Kibit=Kibit Formats.units.kB=kB Formats.units.KB=KB Formats.units.kbit=kbit Formats.units.B=B Formats.units.bit=bit Formats.units.alot=Molt !!! ConfigView.section.ipfilter.persistblocking=Desar deatall d'IP entre execucions FilesView.menu.rename=Canviar Nom o Objectiu FilesView.menu.rename_only=Reanomena r\u00e0pidament FilesView.menu.retarget=Mou els fitxers FilesView.rename.choose.path=Triar fitxer nou o existent FilesView.rename.choose.path.dir=Trieu una carpeta existent o una de nova FilesView.rename.confirm.delete.title=Confirma l'eliminaci\u00f3 FilesView.rename.confirm.delete.text=Confirma l'eliminaci\u00f3 del fitxer original '%1' FilesView.rename.filename.title=Reanomena el fitxer FilesView.rename.filename.text=Tria un nom nou per al fitxer ConfigView.higher.mode.available=Hi ha m\u00e9s opcions disponibles a les configuracions d'usuari avan\u00e7at ConfigView.section.mode=Mode ConfigView.section.mode.beginner.text=Tot el que necessiteu per descarregar torrents.\nUtilitzeu aquest mode si els voleu gestionar. ConfigView.section.mode.advanced.text=Acc\u00e9s a les prefer\u00e8ncies de la xarxa.\n this mode if you know what MTU or non blocking I/O are... Files.column.storagetype=Tipus Emmegatzematge Files.column.fileext=Tipus FileItem.storage.linear=Linial FileItem.storage.compact=Compacte MessageBoxWindow.rememberdecision=Recordar-ne la decisi\u00f3 ConfigView.section.interface.cleardecisions=Esborra la mem\u00f2iria d'opcions de di\u00e0leg ConfigView.section.interface.cleardecisionsbutton=Esborra configureWizard.welcome.usermodes=El par\u00e0metre efici\u00e8ncia d'usuari determinar\u00e0 el nivell de les opcions que es mostren a Eines > Opcions. Cal que el configureu adequadament. FilesView.skip.confirm.delete.text=Truncar fitxer '%1' per estalviar espai? FilesView.rename.failed.title=Canvi de nom/objecctiu ha fet falla FilesView.rename.failed.text=L'operaci\u00f3 ha fallat, probablement a causa d'una selecci\u00f3 inv\u00e0lida d'objectiu diagnostics.log_found=El Vuze no s'ha aturat correctament. Si us plau, comproveu %1 per a ftixers d'anotacions de diagn\u00f2stics i considereu la possibilitat d'informar-ne a l'equip Vuze si \u00e9s el resultat d'un error d'aplicaci\u00f3. ManagerItem.paused=Pausa Utils.link.visit=Visiteu ConfigView.section.connection.serverport.wiki=Ports recomanats ConfigView.section.transfer.speeds.wiki=Configuraci\u00f3 de velocitat \u00e9s bona installPluginsWizard.installMode.info.text=No cal tenir el m\u00f2duls d'Vuze nom\u00e9s aporten funcionalitats complement\u00e0ries, automatizaci\u00f3 i control remot. Views.plugins.Distributed.DB.title=BD Distribu\u00efda Views.plugins.Distributed.Tracker.title=Tracker Distribu\u00eft Views.plugins.Plugin.Update.title=Actualitzaci\u00f3 M\u00f2duls TableColumn.header.swarm_average_completion=Compelci\u00f3 Mitjana dels Iguals GeneralView.label.swarm_average_completion=Compleci\u00f3 Mitjana: MainWindow.nat.status.tooltip.ok=NAT (TCP) correcte MainWindow.nat.status.tooltip.probok=NAT correcte,tanmateix no hi ha hagut recientment connexions TCP MainWindow.nat.status.bad=Tallafocs MainWindow.nat.status.tooltip.bad=Possible problema NAT (TCP), cal consultar el Wiki si persisteix plugin.installer.recommended.plugin=M\u00f2dul recomenat - feu consulta i instal\u00b7laci\u00f3 si cal LoggerView.pause=Atura el registre LoggerView.clear=Esborra LoggerView.filter=Filtre LoggerView.filter.uncheckAll=Desmarca totes les categories LoggerView.filter.checkAll=Marca totes les categories LoggerView.loggingDisabled=El registre no est\u00e0 habilitat ConfigView.section.logging.log0type=Informaci\u00f3 ConfigView.section.logging.log1type=Rebut ConfigView.section.logging.log2type=Enviat ConfigView.section.logging.level=Nivell de registre ConfigView.section.logging.showLogsFor=Mostra %1 registres per a les categories seg\u00fcents: ConfigView.pluginlist.column.loadAtStartup=Carrega-ho en comen\u00e7ar ConfigView.pluginlist.column.type=Tipus ConfigView.pluginlist.column.type.perUser=Per usuari ConfigView.pluginlist.column.type.shared=Compartit ConfigView.pluginlist.column.type.builtIn=Fet a ConfigView.pluginlist.column.name=Nom ConfigView.pluginlist.column.version=Versi\u00f3 ConfigView.pluginlist.column.directory=Carpeta ConfigView.pluginlist.column.isOperational=Operativa? MyTorrentsView.dialog.NumberError.title=Nombre inv\u00e0lid o irrecognoscible MyTorrentsView.dialog.NumberError.text=El nombre que heu introdu\u00eft \u00e9s inv\u00e0lid o no es reconeix MyTorrentsView.menu.manual=&Manual... MyTorrentsView.menu.manual.per_torrent=Manual (per torrent) MyTorrentsView.menu.manual.shared_torrents=Manual (entre torrents) # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.upload=c\u00e0rrega MyTorrentsView.dialog.setNumber.download=descarrega OpenTorrentWindow.torrentLocation=Torrents per descarregar :\n(un fitxer torrent per l\u00ednia) OpenTorrentWindow.addFiles.URL=Afegeix &URL OpenTorrentWindow.addFiles.Folder=Afegeix &carpeta OpenTorrentWindow.addFiles.Clipboard=Afegeix del &porta-retalls OpenTorrentWindow.changeDestination=Canvia la destinaci\u00f3 OpenTorrentWindow.torrentTable.name=Nom OpenTorrentWindow.torrentTable.saveLocation=Desa la ubicaci\u00f3 OpenTorrentWindow.fileTable.fileName=Nom fitxer OpenTorrentWindow.fileTable.size=Mida OpenTorrentWindow.fileTable.destinationName=Nom dest. OpenTorrentWindow.startMode.seeding=Sembrant OpenTorrentWindow.fileList.changeDestination=Canvia la destinaci\u00f3 OpenTorrentWindow.mb.badSize.title=Fitxer incompatible OpenTorrentWindow.mb.badSize.text='%1' no \u00e9s '%2' i no es pot fer servir per sembrar OpenTorrentWindow.mb.alreadyExists.title=Ja existeix OpenTorrentWindow.mb.openError.title=Error en obrir OpenTorrentWindow.mb.openError.text='%1' no es pot obrir: OpenTorrentWindow.torrent.remove=Elimina el torrent de la llista OpenTorrentWindow.torrent.options=Les caracter\u00edsitques seg\u00fcents s'aplicaran als torrents que seleccioneu a continuaci\u00f3: OpenTorrentWindow.xOfTotal=(%1 de %2) iconBar.open.tooltip=Obre un ftixer .torrent LocaleUtil.column.text=Text desconegut LoggerView.realtime=Actualitza-ho en temps real Button.moveUp=Mou a&munt Button.moveDown=Mou a&vall ConfigView.notAvailableForMode=Aquesta secci\u00f3 \u00e9s per al mode %1 o superior. No est\u00e0 disponible per al mode %2. health.explain.error=S'ha proodu\u00eft un error amb aquest torrent. Vegeu la columna d'estat o or the tooltip on the icon for the error. MyTorrentsView.menu.clear_resume_data=Esborra les dades de resum Peers.column.Encryption=Encriptaci\u00f3 Peers.column.Encryption.info=Nivell d'encriptaci\u00f3 en \u00fas MainWindow.sr.status.tooltip.ok=R\u00e0tio de compartir %1 CORRECTE MainWindow.sr.status.tooltip.poor=R\u00e0tio de compartir %1 pobre: < 0,9 MainWindow.sr.status.tooltip.bad=R\u00e0tio de compartir %1 dolent: < 0,5 ConfigView.section.connection.encryption=Encritaci\u00f3 del transport upnp.selectedinterfaces=Interf\u00edcies seleccionades (separades per ';', p.ex. eth0;eth1) [blanc: tot] Button.selectAll=Selecciona'ls tots Button.markSelected=Marca selecci\u00f3 Button.unmarkSelected=Desmarca els seleccionats TorrentOptionsView.param.max.uploads=Nombre m\u00e0xim de buits de c\u00e0rrega [m\u00ednm: 2] ConfigView.section.connection.advanced.info.link=Entra per als detalls Pieces.column.Requested.info=Mostra-ho si es poden fer m\u00e9s sol\u00b7licituds a la pe\u00e7a o no (*) MyTorrentsView.filter=Filtre: popup.error.hideall=Amagueu-ho tot MyTorrentsView.dialog.setFilter.title=Modifica el filtre MyTorrentsView.dialog.setFilter.text=La secci\u00f3 %1 es filtrar\u00e0 segons el text que especifiqueu. Fer servir el s\u00edmbol | (barra vertical) per filtrar segons diverses frases. MyTorrentsView.clearFilter.tooltip=Esborra el filtre MyTorrentsView.menu.filter=Llista de filtres... ConfigureWizard.language.choose=Tria una llengua de la llista seg\u00fcent: # > 2402 ConfigView.auto=Autom\u00e0tic MainWindow.menu.view.plugins.logViews=Vistes de registre SpeedView.stats.autospeed=Velocitat autom\u00e0tica de c\u00e0rrega SpeedView.stats.autospeed.disabled=Aquesta caracter\u00edsitca est\u00e0 deshabilitada (necessiteu el DHT) o no es fa servir (s'ha seleccionat la velocitat manual de c\u00e0rrega) ConfigView.pluginlist.unloadSelected=Descarrega la selecci\u00f3 ConfigView.pluginlist.scan=Cerca nous complements ConfigView.pluginlist.column.unloadable=No es pot carregar MagnetURLHandler.report.no_sources=no s'han trobat recursos per al torrent MagnetURLHandler.report.torrent_size=mida del torrent: %1 MagnetURLHandler.report.percent=complet: %1% MagnetURLHandler.report.error=error %1 DHTTransport.report.request_all=demanant la transfer\u00e8ncia sencera de %1 DHTTransport.report.received_bit=rebut %1 de %2 des de %3 DHTTransport.report.complete=complet DHTTransport.report.rerequest_all=tornant a demanar la transfer\u00e8ncia sencera de%1 DHTTransport.report.rerequest_bit=tornant a demanar %1 de %2 des de %3 DHTTransport.report.sending=enviant dades DHTTransport.report.resending=reenviant dades DHTTransport.report.send_complete=enviament complet UpdateMonitor.messagebox.verification.failed.title=La verificaci\u00f3 de la instal\u00b7laci\u00f3 ha fallat UpdateMonitor.messagebox.verification.failed.text=La verificati\u00f3 de '%1' ha fallat: %2 UpdateMonitor.messagebox.accept.unverified.title=Accepta la instal\u00b7laci\u00f3 no comprovada UpdateMonitor.messagebox.accept.unverified.text=No es pot comporvar que '%1' sigui un complement oficial del Vuze.\nSi no ho \u00e9s, NO continueu.\nEl voleu seguir instal\u00b7lant? FileView.BlockView.title=Peces del fitxer FileView.BlockView.Done=Fet FileView.BlockView.Active=Actiu DownloadManager.error.badsize=Mida incorrecta ConfigView.section.NATPMP=NAT-PMP ConfigView.filter=cerca opcions aqu\u00ed PeerColumn.activationCount=Iguals intentant connectar: %1 MainWindow.menu.view.iconbar=Barra d'eines MyTorrentsView.menu.rename=Reanomena MyTorrentsView.menu.rename.displayed=Canvia el nom que es mostra MyTorrentsView.menu.rename.displayed.enter.title=Canvia el nom que es mostra MyTorrentsView.menu.rename.displayed.enter.message=Introdu\u00efu un nom nou per mostrar per aquesta desc\u00e0rrega. MyTorrentsView.menu.edit_comment=Edita el comentari authenticator.savepassword=Recorda la contrasenya ConfigView.section.security.clearpasswords=Esborra les contrasenyes desades ConfigView.section.security.clearpasswords.button=Esborra Content.alert.notuploaded.title=Actualitzaci\u00f3 no completada Content.alert.notuploaded.text=L'actualitzaci\u00f3 de '%1' no s'ha completat. Si %2 ara, people will not be able to completely download your published work.\n\nSegur que voleu %2? Content.alert.notuploaded.multi.title=C\u00e0rregues no completes Content.alert.notuploaded.stop=atura Content.alert.notuploaded.quit=surt del Vuze ConfigView.label.please.visit.here=Entra per veure'n els detalls OpenTorrentWindow.filesInfo=%1 de %2 es descarregar\u00e0. OpenTorrentWindow.diskUsage=%1 de %2 ConfigView.label.openmytorrents=Obre 'Els meus torrents' en entrar ConfigView.label.open_transfer_bar_on_start=Obre la barra de transfer\u00e8ncia quan obris OpenTorrentWindow.mb.noGlobalDestDir.title=Carpeta de destinaci\u00f3 OpenTorrentWindow.mb.noGlobalDestDir.text=La carpeta de destinaci\u00f3 '%1' no \u00e9s v\u00e0lida. OpenTorrentWindow.mb.noDestDir.title=No s'ha trobat la carpeta de destinaci\u00f3 OpenTorrentWindow.mb.noDestDir.text=La carpeta de destinaci\u00f3 '%1' per al torrent '%2' no existeix o no \u00e9s v\u00e0lida. OpenTorrentWindow.mb.notValid.title=Obre el torrent OpenTorrentWindow.mb.notValid.text=No es pot obrir el torrent '%1'. Si obriu en mode de sembra, si us plau assegureu-vos que el fitxer de dades torrent exsiteix. OpenTorrentWindow.mb.notTorrent.title=Obre el torrent OpenTorrentWindow.mb.notTorrent.text=No es pot obrir '%1'. no sembla que sigui un fitxer .torrent.\n\nAlgunes de les dades rebudes:\n%2 ConfigView.label.pause.downloads.on.exit=Atura les desc\u00e0rregues quan surtis ConfigView.label.resume.downloads.on.start=Resumeix les desc\u00e0rregues en pausa en comen\u00e7ar despr\u00e9s de completar la inicialitzaci\u00f3 window.update.noupdates.title=Resultats de cerca d'actualitzacions window.update.noupdates.text=No teniu actualitzacions pendents.\n\nFelicitats! UI.cannot_submit_blank_text=Hi has d'introduir un valor OpenTorrentWindow.mb.existingFiles.title=El(s) fitxer(s) ja existeix(en)! alert.raised.at.close=(Missatge d'un tancament anterior del Vuze) Peers.column.maxupspeed=Vel. m\u00e0x. c\u00e0r. Peers.column.maxdownspeed=Vel. m\u00e0x. desc. MyTorrents.items.DownSpeedLimit.disabled=No descarregat Peers.column.lan=LAN UpdateMonitor.messagebox.restart.title=Actualitzaci\u00f3 de programari UpdateMonitor.messagebox.restart.text=El Vuze acaba de completar una actaulitzaci\u00f3 important i s'ha de reiniciar per tal que la instal\u00b7laci\u00f3 es pugui completar. Peers.column.peer_id=ID d'igual Peers.column.peer_id.info=ID de l'igual en fromat lectura Peers.column.peer_byte_id=ID d'igual Peers.column.peer_byte_id.info=ID de l'igual en bytes Peers.column.client_identification=Identificaci\u00f3 del client ConfigView.label.openbar.incomplete=Barres de desc\u00e0rrega: obre autom\u00e0ticament les desc\u00e0rregues ConfigView.label.openbar.complete=obre autom\u00e0ticament les llavors MainWindow.menu.tools.speedtest=Prova de velocitat... speedtest.wizard.test.mode.updown=c\u00e0rrega i desc\u00e0rrega speedtest.wizard.test.mode.up=c\u00e0rrega SpeedTestWizard.test.panel.currinfo=Provant l'amplada de banda BitTorrent. SpeedTestWizard.test.panel.label=Prova de velocitat del Vuze: SpeedTestWizard.set.upload.result=Resultat de l'\u00faltima prova SpeedTestWizard.set.upload.bits.per.sec=bits/s SpeedTestWizard.finish.panel.max.upload=C\u00e0rrega m\u00e0x.: window.uiswitcher.text=Seleccioneu la interf\u00edcie d'usuari que s'adapti millor a les vostres necessitats. window.uiswitcher.NewUI.text=* Recomanat per a principiants i usuaris novells.\n\n* F\u00e0cil amb interf\u00edcie gr\u00e0fica intu\u00eftiva\n\n* Interf\u00edcie necess\u00e0ria per a poder publicar en la plataforma Vuze ConfigView.interface.start.advanced=Comen\u00e7a en visualitzaci\u00f3 avan\u00e7ada (AZ 2.x) MyTorrents.column.ColumnQuality=Qualitat MyTorrents.column.ColumnSpeed=Velocitat MyTorrents.column.ColumnProgressETA.2ndLine=Temps: %1 MyTorrents.column.ColumnProgressETA.PlayableIn=Reprodu\u00efble d'aqu\u00ed a %1 #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.publish=Publica v3.MainWindow.menu.publish=&Publica v3.mb.delPublished.title=Deixa de sembrar el contingut v3.mb.delPublished.text=ATENCI\u00d3: Aquesta acci\u00f3 NO esborrar\u00e0 els continguts que heu publicat '%1' de %3 .\n\nClicque "Esborra" nom\u00e9s si voleu mantenir el contingut publicat i descarregable, per\u00f2 voleu alliberar amplada de banda. Assegureu-vos que el proc\u00e9s de c\u00e0rrega s'ha completat abans de fer-ho (how?).\n\nCliqueu "Cancel\u00b7la" si voleu eliminar completament el contingut publicat de %3, i feu servir el bot\u00f3 (X) del contingut publicat al tabulador de publicaci\u00f3.\n\nMore help.\n\n v3.mb.delPublished.delete=&Esborra v3.mb.delPublished.cancel=&Cancel\u00b7la # splash.loadIpFilters=Carregant filtres IP... SpeedTestWizard.set.upload.title=Ajusta els l\u00edmits de c\u00e0rrega i desc\u00e0rrega SpeedTestWizard.set.upload.label=L\u00edmit de velocitat de c\u00e0rrega: SpeedTestWizard.name.conf.level.low=Baixa DHTView.title.full_v6=Base de dades distribu\u00efda IPv6 ConfigView.pluginlist.loadSelected=Carrega la selecci\u00f3 SpeedView.stats.estupcap=Velocitat de c\u00e0rrega # Used for peers which we can't determine. PeerSocket.unknown=Desconegut PeerSocket.unknown_az_style=Desconegut %1/%2 PeerSocket.unknown_shadow_style=Desconegut %1/%2 ConfigTransferAutoSpeed.upload.capacity.usage=\u00das de la capacitat de c\u00e0rrega ConfigTransferAutoSpeed.mode=Mode: ConfigTransferAutoSpeed.capacity.used=% \u00fas de capacitat ConfigTransferAutoSpeed.while.downloading=Descarregant: ConfigTransferAutoSpeed.set.tolerance=toler\u00e0ncia (ms) ConfigTransferAutoSpeed.ping.time.good=Bo: ConfigTransferAutoSpeed.ping.time.bad=Dolent: ConfigTransferAutoSpeed.adjustment.interval=Interval d'ajustament: ConfigTransferAutoSpeed.skip.after.adjust=Surt despr\u00e9s d'ajustar: GeneralView.label.distributedCopies=C\u00f2pies distribu\u00efdes: PeersView.gain.info=Quantitat de dades descarregades i carregades Content.alert.notuploaded.button.stop=&Atura Content.alert.notuploaded.button.continue=&Continua sembrant Content.alert.notuploaded.button.abort=&No surtis SpeedTestWizard.set.upload.hint=Ajusta els l\u00edmits de c\u00e0rrega i desc\u00e0rrega als que fa servir l'algoritme de velocitat autom\u00e0tica del Vuze. ConfigTransferAutoSpeed.add.comment.to.log.group=Afegeix un comentari al registre de depuraci\u00f3 ConfigTransferAutoSpeed.add.comment.to.log=Afegeix el comentari: ConfigTransferAutoSpeed.log.button=Registre ConfigTransferAutoSpeed.algorithm.selector=Selector de velocitat autom\u00e0tica ConfigTransferAutoSpeed.algorithm=Algoritme: ConfigTransferAutoSpeed.auto.speed.classic=Velocitat autom\u00e0tica (cl\u00e0ssic) ConfigTransferAutoSpeed.auto.speed.beta=Velocitat autom\u00e0tica (beta) ConfigTransferAutoSpeed.data.update.frequency=Freq\u00fc\u00e8ncia d'actualitzaci\u00f3 Alert.failed.update=La instal\u00b7laci\u00f3 d'almenys un component ha fallat. Vegeu AzureusWiki: Failed Update [%1] ConfigView.label.announceport=Canviar el port d'anunci del rastrejador GeneralView.label.private=Torrent privat: GeneralView.yes=S\u00ed GeneralView.no=No Peers.column.timetocomplete=Temps restant Peers.column.timetocomplete.info=Time que falta perqu\u00e8 l'igual estigui complet FileDownload.canceled=La desc\u00e0rrega del fitxer torrent ha estat cancel\u00b7lada correctament per l'usuari: %1 OpenTorrentWindow.simple.open=Ubicaci\u00f3 del torrent (fitxer, URL, hash) MyTorrentsView.menu.open_parent_folder=Obre la carpeta de contingut updater.cant.write.to.app.title=No es pot escriure a la carpeta de l'aplicaci\u00f3 updater.cant.write.to.app.details=No es pot escriure a la carpeta "%1".\n\nAix\u00f2 impedir\u00e0 que s'apliquin les instal\u00b7lacions de programari.\n\nSi us plau, consulteu la Wiki per als detalls. v3.MainWindow.tab.events=Notificacions button.columnsetup.tooltip=Actualitza la columna v3.activity.remove.title=Esborra la notificaci\u00f3 v3.activity.remove.text=Segur que voleu eliminar aquesta noitificaci\u00f3? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, Menu.show.torrent.menu=Mostra el men\u00fa dels torrents #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences menu.sortByColumn=Ordena per %1 MyTorrentsView.menu.manual.per_peer=Manual (per igual) MyTorrentsView.menu.manual.shared_peers=Manual (entre iguals) OpenTorrentWindow.mb.notTorrent.cannot.display=No es pode mostrar les dades correctament MainWindow.menu.window.zoom.maximize=Maximitza MainWindow.menu.window.zoom.restore=Restaura security.crypto.encrypt=Si us plau, introdu\u00efu una contrasenya per protegir la clau d'encriptaci\u00f3 que acabeu de generar. Atenci\u00f3, no us oblideu d'aquesta contrasenya, ja que no la podreu recuperar! security.crypto.decrypt=Si us plau, introdu\u00efu la contrasenya per desbloquejar la clau d'encrotaci\u00f3. security.crypto.password=Contrasenya security.crypto.password2=Repetiu la contrasenya security.crypto.persist_for=Per\u00edode de validesa de la contrasenya ConfigView.section.security.unlockkey.error=La clau de desboqueig ha fallat. La constrasenya \u00e9s incorrecta ConfigView.copy.to.clipboard.tooltip=Copia-ho al porta-retalls Browser.popup.error.no.access=S'ha produ\u00eft un error quan s'intentava accedir a un recurs remot.\nSi us plau, intenteu-ho una altra vegada d'aqu\u00ed a un moment.\n ConfigView.label.queue.stoponcebandwidthmet=No comencis m\u00e9s torrents quan s'arribi al l\u00edmit de velocitat de c\u00e0rrega/desc\u00e0rrega azbuddy.name=Amics azbuddy.enabled=Deshabilitat azbuddy.disabled=El complement est\u00e0 deshabilitat. Si el voleu habilitar, feu-ho des de la confiuguraci\u00f3 dels complements. azbuddy.nickname=Sobrenom azbuddy.msglog.title=Informaci\u00f3 de l'amic azbuddy.addtorrent.title=Accepteu la desc\u00e0rrega? azbuddy.addtorrent.msg=L'amic '%1' us ha enviat '%2'.\nVoleu afegir aquesta desc\u00e0rrega? azbuddy.contextmenu=Envia-ho a l'amic Button.retry=To&rna-ho a intentar Button.ignore=&Ignora azbuddy.downspeed=KB/s velocitat m\u00e0xima de desc\u00e0rrega de l'amic [0: il\u00b7limitat] security.crypto.badpw=La contrasenya indicada \u00e9s incorrecta azbuddy.chat.title=Xat del Vuze azbuddy.chat.says=%1 diu: Button.bar.show=Mostra Button.bar.hide=Amaga Button.bar.share=Comparteix Button.bar.add=Afegeix Button.bar.edit=Edita Button.bar.edit.cancel=Edici\u00f3 feta MainWindow.dialog.select.vuze.file=Selecciona un fitxer del Vuze MainWindow.menu.file.open.vuze=Fitxer del Vuze... metasearch.addtemplate.title=Voleu instal\u00b7lar la plantilla de cerca? metasearch.addtemplate.desc=Segur que voleu instal\u00b7lar una plantilla de cerca anomenada '%1'? metasearch.addtemplate.dup.title=Duplica la plantilla metasearch.addtemplate.dup.desc=La plantilla de cerca %1 ja est\u00e0 instal\u00b7lada metasearch.export.select.template.file=Desa la plantilla metasearch.import.select.template.file=Obre la plantilla azbuddy.protocolspeed=KB/s m\u00e0x friend protocol overhead v3.activity.header.downloads=Desc\u00e0rregues v3.activity.header.vuze.news=Not\u00edcies del Vuze message.taking.too.long=Sembla que tarda m\u00e9s del que caldria\nPremeu 'ESC' si voleu cancel\u00b7lar l'operaci\u00f3 message.status.success=\u00c8xit azbuddy.tracker.bbb.status.nli=Cal que us registreu metasearch.addtemplate.done.title=Pantilla afegida metasearch.addtemplate.done.desc=La plantilla '%1' s'ha afegit correctament.\nEs far\u00e0 servir en la propera cerca! ConfigView.section.security.nopw=No heu indicat cap contrasenya ConfigView.section.security.nopw_v=No hi ha cap contrasenya disponible. Si us plau, registreu-vos al Vuze fileplugininstall.install.title=Voleu instal\u00b7lar el complement? fileplugininstall.install.desc=Segur que voleu instal\u00b7lar el complement '%1', versi\u00f3 %2? fileplugininstall.duplicate.title=Complement de duplicaci\u00f3 fileplugininstall.duplicate.desc=El complement '%1', versi\u00f3 %2 ja s'ha instal\u00b7lat. azbuddy.online_status=Connectat azbuddy.os_online=Connectat azbuddy.os_away=No hi s\u00f3c azbuddy.os_not_avail=No disponible azbuddy.os_busy=Ocupat azbuddy.os_offline=Desconnectat azbuddy.enable_chat_notif=Habilita les nostificacions de xat DetailedListView.title=Llista detallada azsubs.contextmenu.addassoc=Afegeix una associaci\u00f3 de subscripci\u00f3 azsubs.contextmenu.lookupassoc=Cerca associacions de subscripci\u00f3 iconBar.down=Avall iconBar.editcolumns=Configuraci\u00f3 de la columna iconBar.details=Detalls iconBar.comment=Comentari iconBar.queue.tooltip=Cua v3.MainWindow.menu.view.sidebar=Barra lateral MainWindow.menu.community=&Comunitat MainWindow.menu.help.faq=&FAQ MainWindow.menu.community.wiki=&Wiki de la comunitat MainWindow.menu.community.forums=F\u00f2&rums de la comunitat MainWindow.menu.community.blog=&Blog del Vuze MainWindow.menu.help.support=&Ajuda i suport externalLogin.title=Cal que us registreu externalLogin.explanation=La caracter\u00edsitca "%1" requereix que us registreu. Un cop registrats aquesta finestra es tancar\u00e0 autom\u00e0ticament. Si no ho fa, cliqueu a "Fet". externalLogin.explanation.capture=Cal que us registreu per crear aquest plantilla. Quan ho hagueu fet, feu clic a "Fet". Button.done=Fet GeneralView.torrent_created_on_and_by=%1 per %2 Button.continue=Continua Button.preview=Previsualitzaci\u00f3 Subscription.menu.forcecheck=Actualitza-ho ara Subscription.menu.clearall=Marca tots els resultats com a llegits Subscription.menu.remove=Esborra sidebar.Library=La biblioteca sidebar.LibraryDL=Descarregant sidebar.LibraryCD=Complet authenticator.location=Localitzaci\u00f3 authenticator.details=Detalls Subscription.menu.export=Exporta Button.remove=Esborra Button.send=Envia Button.back=Enrere sidebar.LibraryUnopened=No visualitzat Unopened.bigView.header=Nou Subscription.menu.deleteall=Esborra tots els resultats Subscription.menu.reset=Recupera l'estat incial ConfigView.section.Subscriptions=Subscripcions subscriptions.config.maxresults=Nombre m\u00e0xim de resultats per subscripci\u00f3 [0: il\u00b7limitat] v3.activity.button.readall=Marca'ls tots com a llegits Subscription.menu.resetauth=Esborraels detalls d'identificaci\u00f3 #what you've watched? Discover more with a single click... Wizard.Subscription.create.title=Crea una subscrpci\u00f3 nova Button.search=Cerca Button.save=Desa Button.add=Afegeix Button.createNewSubscription=Crea una subscrpci\u00f3 nova Button.availableSubscriptions=Subscripcions disponibles Wizard.Subscription.create.search=Cerca Wizard.Subscription.rss.subtitle2=Alguns publicadors proporcionen canals RSS del seu contingut. Localitzeu la URL al web del publicador, copieu i enganxeu la URL al camp de sota, i cliqueu a Desa. message.confirm.delete.title=Confirma esborrar message.confirm.delete.text=Segur que voleu esborrar '%1'? Subscription.menu.properties=Propietats externalLogin.wait=Carregant la p\u00e0gina. Si us plau, espereu... sidebar.VuzeHDNetwork=Xarxa Vuze HD subscriptions.column.new.info=Indicat si hi ha un o m\u00e9s resultats nous subscriptions.column.name=Subscripci\u00f3 subscriptions.column.nb-results=Resultats totals subscriptions.column.nb-new-results=Resultats nous subscriptions.column.last-checked=\u00daltima comprovaci\u00f3 Subscription.menu.upgrade=Habilita l'actualitzaci\u00f3 a la versi\u00f3 m\u00e9s nova metasearch.template.version.bad=La plantilla de cerca '%1' no es pot instal\u00b7lar fins que no s'actualitzi el Vuze metasearch.addtemplate.failed.title=La instal\u00b7laci\u00f3 ha fallat metasearch.addtemplate.failed.desc=La instal\u00b7laci\u00f3 de la plantilla de cerca '%1' ha fallat subscription.version.bad=La subscipci\u00f3 '%1' no es pot instal\u00b7lar fins que no actualitzeu el Vuze sidebar.Activity=Notificacions v3.activity.button.watchall=Marca'ls tots com a vistos sidebar.sash.tooltip=F7 per amagar/mostrar la barra lateral sidebar.dropdown.tooltip=Mostra la barra lateral en format men\u00fa Button.deleteContent.fromLibrary=Elimina de la biblioteca Button.deleteContent.fromComputer=Esborra de l'ordinador Subscription.menu.dirtyall=Marca tots els resultats com a no llegits configureWizard.file.message3=El Vuze descarregar\u00e0 fitxers en una carpeta espe\u00edfica, que podeu triar: v3.MainWindow.menu.contentnetworks.about=Sobre les xarxes HD Peers.column.as=AS/ASN Peers.column.as.info=Detalls de l'AS (Sistema Aut\u00f2nom) de l'igual ConfigView.label.autoopen=Obertura autom\u00e0tica v3.MainWindow.menu.contentnetworks.manage=&Gestiona les xarxes HD azbuddy.ui.menu.cat.share=Habilita les subscripcions amb amics azbuddy.enable_cat_pub=Categories p\u00fabliques a les quals TOTS els amics es poden subscriure (separades per ',') v3.dialog.cnclose.info2=Si voleu tornar a obrir aquesta xarxa HD, ho heu de fer al men\u00fa "Xarxes HD" de la part superior de la pantalla. v3.dialog.cnmanage.title=Gestiona el men\u00fa de xarxes HD v3.dialog.cnmanage.intro=Podeu triar de la llista seg\u00fcent quins coninguts de la xarxa voleu mostrar al men\u00fa de xarxes HD TableColumn.header.maxuploads.info=M\u00e0xim # of peers to simultaneously upload to TableColumn.header.upspeed.info=Velocitat de c\u00e0rrega actual Peers.column.%=% Peers.column.%.info=Percentatge del torrent que l'igual ha descarregat TableColumn.header.upload.info=Quantitat de dades que heu enviat al epeer Peers.column.pieces.info=Barra gr\u00e0fica que representa quines peces l'igual ha descarregat label.learnmore=Per saber-ne m\u00e9s coses ColumnSetup.title=Configuraci\u00f3 de la columna per a '%1' ColumnSetup.explain=Explore les columns disponibles de l'esquerra i afegeix-les a la llista de columnes visibles de la dreta. Expandeix o redueix la llista de columnes disponibles fent servir la secci\u00f3 del filtre del bot\u00f3 esquerre. Podeu arrossegar i deixar anar, o fer servir les dreceres del teclat. ColumnSetup.chosencolumns=Columns triades ColumnSetup.proficiency=Professionalitat: ColumnSetup.categories=Categories: ColumnSetup.filters=Filtres ColumnSetup.availcolumns=%1 columnes disponibles ColumnSetup.availcolumns.filteredby=%1 columnes disponibles filtrades per %2 devices.view.title=Dispositius device.mediaserver.view.title=Servidor de mitjans device.model.desc=Descripci\u00f3 del model device.model.name=Nom del model device.model.num=N\u00famero del model device.manu.desc=Fabricant device.mediaserver.configure=Configura el servidor de mitjans device.hide=Amaga el dispositiu device.browse=Navega device.upnp.desc_url=Descripci\u00f3 del dispositiu device.upnp.present_url=Administraci\u00f3 del dispositiu devices.sidebar.simple=Visualitzaci\u00f3 simple device.lastseen=\u00daltima visualitzaci\u00f3 devices.device=Dispositiu devices.profile=Perfil General.percent=Percentatge devices.installed=Instal\u00b7lat devices.state=Estat MainWindow.menu.help.donate=F\u00e9s una &donaci\u00f3 (\u20ac,$,...) DonationWindow.noload.title=Donaci\u00f3 DonationWindow.noload.text=La finestra de donaci\u00f3 no s'ha pogut obrir. Si su plau, intenteu-ho d'aqu\u00ed a una estona. download.removerules.unauthorised.data=\tEsborra les dades device.xcode.always=Sempre device.xcode.whenreq=Quan se sol\u00b7liciti device.xcode.never=Mai devices.copy.pending=La c\u00f2pia del fitxer est\u00e0 pendent devices.sidebar.hide.rend.generic=Amaga els dispositius gen\u00e8rics devices.copy.fail=La c\u00f2pia al dispositiu ha fallat devices.ready=Fet # This is the beginning of the word "View". It's right aligned under the icon bar item # This is the end of the word "View". It's left aligned under the icon bar item general.dont.ask.again=No ho tornis a preguntar devices.button.installitunes=Instal\u00b7la la integraci\u00f3 amb l'iTunes device.itunes.install=Cal que instal\u00b7leu l'iTunes device.itunes.start=Cal que inicieu l'iTunes o que deshabiliteu l'obertura autom\u00e0tica device.itunes.install_problem=Sembla que hi ha algun problema amb la integraci\u00f3 de l'iTunes devices.downloading=Descarregant devices.xcode.autoStart=Obre autom\u00e0ticament quan es necessiti option.askeverytime=Pregunta-ho cada vegada option.rememberthis=Recorda aquesta caracter\u00edstica devices.associate=Associat amb devices.turnon.itunes=Inclou suport per a l'iTunes (us cal per als dispositiu d'Apple) devices.turnon.title=Activa el suport del dipositiu device.view.heading=Mitjans per a %1 devices.choose.device.info.title=Tipus de dispositiu devices.choose.device.info.text=La porpera vegada, simplement arrossega i dexa anr fitxer al dispositiu que vulguis de la barra lateral. Button.turnon=Connecta ConfigView.option.dm.dblclick.play=Reprodueix-ne el contingut ConfigView.option.dm.dblclick.details=Obre la visualitzaci\u00f3 dels detalls del torrent ConfigView.option.dm.dblclick.show=Mostra el fitxer ConfigView.option.dm.dblclick.show._mac=Mostra el(s) fitxer(s) al cercador ConfigView.option.dm.dblclick.show._windows=Mostra el(s) fitxer(s) a l'explorador subscriptions.column.auto-download=Descarrega autom\u00e0ticament devices.copy_url=Copia el flux URL al porta-retalls devices.converting=Convertint Button.reload=Torna a carregar devices.auto.start=Obertura autom\u00e0tica azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_en_GB.properties0000644000175000017500000000463211301156004026046 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.window.minimize=Minimise ConfigView.label.priorityExtensions=Auto-prioritise files with \n - eg: .txt;.nfo;.jpg ConfigView.label.closetotray=Close minimises to System Tray ConfigView.label.minimizetotray=Minimise minimises to System Tray ConfigView.label.startminimized=Start minimised ConfigView.label.zeronewfiles.tooltip=Minimises fragmentation splash.initializeGui=Initialising Main Window ConfigView.section.color=Colour Scheme # # Tooltips # # # 2.0.4.4 # # #2.0.7.0 # ConfigView.label.prioritizefirstpiece=Prioritise first and last piece of file(s) # # 2.0.7.x # Categories.uncategorized=Uncategorised ConfigView.label.seeding.rankType.peer.tooltip=more peers and fewer seeds = higher rank\nThis ranking minimises the number of torrents that need to be kept active to maximise the upload # # > 2.0.8.0 # ConfigView.section.style.colorOverrides=Colour Overrides ConfigView.section.style.colorOverrides.reset=Reset Colour splash.initializeGM=Initialising Global Torrent Manager download.removerules.unauthorised.info=Unauthorised torrents are those where the announce response contains either "not authoris(z)ed" or "unauthoris(z)ed" in the "failure response" download.removerules.unauthorised=Automatically remove unauthorised torrents #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed splash.plugin.init=Initialising Plugin: splash.plugin.UIinit=Initialising Plugin GUI: %1 ConfigView.section.connection.peersource.DHT=Decentralised tracking wizard.tracker.dht=Decentralised (Vuze clients only) ConfigView.section.sharing.permitdht=Allow decentralised tracking when tracker is unavailable dht.info=This plugin supports decentralised tracking, amongst other things, - disabling it will reduce your ability to download #file can be a URL or a path in the jar # %1 = "in kbps" or ""; %2 = "upload" or "download" # > 2402 UIDebugGenerator.message.cancel.title=Generate Debug Info Cancelled # Used for peers which we can't determine. FileDownload.canceled=A torrent file download has been successfully cancelled by a user action: %1 Progress.reporting.status.canceled=Cancelled Progress.reporting.window.remove.auto.tooltip=Automatically remove all completed, failed, or cancelled processes from the view Progress.reporting.window.remove.now.tooltip=Remove all completed, failed, or cancelled processes from the view azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_ms_SG.properties0000644000175000017500000007453211301156004026112 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Fail .torrent MainWindow.menu.file=&Fail MainWindow.menu.file.open=&Buka MainWindow.menu.file.create=&Bina Torrent MainWindow.menu.file.create.fromfile=Dari &Fail MainWindow.menu.file.create.fromdir=Dari &Directori MainWindow.menu.file.export=&Eksport Torrent... MainWindow.menu.file.import=&Import Torrent... MainWindow.menu.file.exit=K&eluar MainWindow.dialog.choose.file=Pilih fail Torrent MainWindow.menu.file.folder=&Direktori MainWindow.dialog.choose.folder=Pilih direktori yang mengandungi fail torrent MainWindow.menu.view=&Pandangan MainWindow.menu.view.mytorrents=&TorrentKu MainWindow.menu.view.configuration=&Konfigurasi MainWindow.menu.view.irc=&Irc MainWindow.menu.closealldetails=Tutup &semua maklumat terperinci MainWindow.menu.closealldownloadbars=Tutup semua barisan &memuat turun MainWindow.menu.language=&Bahasa MainWindow.menu.help=&Pertolongan MainWindow.menu.help.about=&Tentang Vuze MainWindow.about.title=Tentang MainWindow.about.section.developers=Pengarang MainWindow.about.section.translators=Penterjemah MainWindow.about.internet.homepage=Lelaman Vuze MainWindow.about.internet.sourceforge=Lelaman Projek Sourceforge MainWindow.about.internet.sourceforgedownloads=Muat turunan Sourceforge MainWindow.about.internet.bugreports=Report Masalah MainWindow.about.internet.forumdiscussion=Forum Umum MainWindow.dialog.choose.savepath=Pilih tempat simpan MainWindow.dialog.choose.savepath_forallfiles=Pilih tempat simpan untuk SEMUA fail MainWindow.status.latestversion=Terbaru MainWindow.status.latestversion.clickupdate=Klik untuk mengemaskini MainWindow.status.unknown=tidak dapat ditetapkan MainWindow.status.checking=sedang memeriksa MyTorrentsView.mytorrents=TorrentKu TableColumn.header.name=Nama TableColumn.header.size=Saiz TableColumn.header.done=Selesai TableColumn.header.done.info=Peratusan kerja kini yang telah selesai TableColumn.header.status.info=Apa yang sedang berlaku berkaitan Torrent tersebut TableColumn.header.seeds=Penyemai TableColumn.header.seeds.info=bilangan penyemai yang bersambung (bilangan kesemua penyemai) TableColumn.header.peers=Rakankongsi TableColumn.header.peers.info=Rakankongsi yang bersambung (Jumlah rakankongsi) TableColumn.header.downspeed=Kelajuan memuat turun TableColumn.header.upspeed=Kelajuan memuat naik TableColumn.header.eta=Masa sebelum selesai TableColumn.header.tracker=Pengesan TableColumn.header.tracker.info=Status pengesan TableColumn.header.priority=Kepentingan TableColumn.header.priority.info=Menetapkan had memuat naik untuk Torrent tersebut MyTorrentsView.menu.showdetails=Tunjukkan &maklumat terperinci MyTorrentsView.menu.showdownloadbar=Tunjukkan barisan memuat turun MyTorrentsView.menu.open=&Buka MyTorrentsView.menu.setpriority=Tetapkan &Kepentingan MyTorrentsView.menu.setpriority.high=&Tinggi MyTorrentsView.menu.setpriority.low=&Rendah MyTorrentsView.menu.start=&Mula MyTorrentsView.menu.stop=Berhenti MyTorrentsView.menu.remove=&Buang MyTorrentsView.menu.changeTracker=&Tambah URL Pengesan TrayWindow.menu.exit=K&eluar TrayWindow.menu.show=&Buka Vuze SystemTray.menu.exit=K&eluar SystemTray.menu.closealldownloadbars=Tutup &Semua Barisan Memuat Turun SystemTray.menu.show=&Buka Vuze PeersView.ip.info=IP rakankongsi anda PeersView.port.info=Port yang digunakan PeersView.T.info=l (local): anda yang menyambung, r (remote): rakankongsi yang menyambung. PeersView.T.L.tooltip=anda yang menyambung PeersView.T.R.tooltip=rakankongsi yang menyambung. PeersView.I1=I PeersView.I1.info=Adakah anda mahukan apa yang rakankongsi anda ada? PeersView.C1=C ("Dicekik" oleh rakankongsi) PeersView.C1.info=Jika rakankongsi anda tidak membenarkan anda memuat turun. PeersView.pieces=Ketulan PeersView.downloadspeed=Kelajuan turun PeersView.download=Turun PeersView.I2=I PeersView.I2.info=Adakah rakankongsi anda mahukan apa yang anda ada? PeersView.C2=C ("Menyekik" rakankongsi) PeersView.C2.info=Jika anda tidak membenarkan rakankongsi memuat turun. PeersView.uploadspeed=Kelajuan naik PeersView.uploadspeed.info=Kelajuan memuatnaik anda ke rakankongsi. PeersView.upload=Naik PeersView.upload.info=Jumlah memuat naik anda ke rakankongsi. PeersView.downloadspeedoverall=Jumlah kelajuan turun PeersView.client=Klien PeersView.client.info=Jenis klien BT rakankongsi anda menggunakan PeersView.title.short=Maklumat lanjut PeersView.title.full=Maklumat lanjut ConfigView.section.files=Fail ConfigView.label.incrementalfile=Enable incremental file creation ConfigView.dialog.choosedefaultsavepath=Sila pilih direktori simpan tetap ConfigView.section.server=Pelayan ConfigView.section.global=Am ConfigView.label.disconnetseed=Putuskan penyemai apabila menyemai ConfigView.label.switchpriority=Gunakan tahap kepentingan rendah apabila menyemai ConfigView.label.maxdownloads=Max simultaneous downloads [0: unlimited] ConfigView.label.priorityExtensions=Auto-prioritize files with extension\n - eg: .txt;.nfo;.jpg ConfigView.section.transfer=Pindahan ConfigView.label.maxuploads=Default max uploads per torrent ConfigView.label.maxuploadspeed=Global max upload speed [0: unlimited] ConfigView.unlimited=Tidak terhad ConfigView.section.general=Am ConfigView.label.openconfig=Open Configuration on startup ConfigView.section.irc=Irc ConfigView.label.ircserver=Pelayan ConfigView.label.ircchannel=Saluran ConfigView.label.irclogin=Nama timangan ConfigView.section.security=Keselamatan ConfigView.button.save=Simpan ConfigView.title.short=Konfigurasi ConfigView.title.full=Konfigurasi FileItem.write=Tulis FileItem.read=Baca FileItem.normal=Biasa FileItem.high=Tinggi FileItem.donotdownload=Jangan muat turunkan FilesView.name=Nama FilesView.size=Saiz FilesView.done=Selesai FilesView.firstpiece=No. ketulan pertama FilesView.numberofpieces=Jumlah ketulan FilesView.pieces=Ketulan FilesView.priority=Kepentingan FilesView.menu.open=&Buka FilesView.menu.setpriority=&Tetapkan had kepentingan FilesView.menu.setpriority.high=&Tinggi FilesView.menu.setpriority.normal=&Biasa FilesView.menu.setpriority.skipped=&Jangan muat turunkan FilesView.title.short=Fail FilesView.title.full=Fail GeneralView.section.downloaded=Telah dimuat turun GeneralView.label.status.file=Status Fail GeneralView.label.status.pieces=Status Ketulan GeneralView.section.availability=Jumlah Ketulan GeneralView.label.status.pieces_available=Status Ketulan GeneralView.section.transfer=Pindah GeneralView.section.info=Maklumat GeneralView.title.short=Am GeneralView.title.full=Am GeneralView.label.timeelapsed=Masa telah berlalu : GeneralView.label.remaining=Baki: GeneralView.label.downloaded=Telah dimuat turun : GeneralView.label.downloadspeed=Kelajuan memuat turun: GeneralView.label.maxuploads=Had memuat naik : GeneralView.label.uploaded=Telah dimuat naik : GeneralView.label.uploadspeed=Kelajuan memuat naik : GeneralView.label.seeds=Penyemai : GeneralView.label.peers=Rakankongsi : GeneralView.label.totalspeed=Jumlah Kelajuan : GeneralView.label.totalspeed.tooltip=Jumlah kelajuan semua klien yang bersambung. GeneralView.label.filename=Nama : GeneralView.label.totalsize=Jumlah Saiz : GeneralView.label.savein=Simpan di : GeneralView.label.hash=Hash : GeneralView.label.numberofpieces=Jumlah ketulan : GeneralView.label.size=Saiz : GeneralView.label.tracker=Status Pengesan: GeneralView.label.updatein=Kemas kini dalam : GeneralView.label.trackerurl=URL Pengesan : GeneralView.label.trackerurlupdate=Manual Update GeneralView.label.comment=Komen : ManagerItem.waiting=Sedang menunggu ManagerItem.checking=Sedang memeriksa ManagerItem.ready=Sedia ManagerItem.downloading=Sedang memuat turun ManagerItem.seeding=Sedang menyemai ManagerItem.stopped=Telah dihentikan ManagerItem.error=Ralat ManagerItem.high=tinggi ManagerItem.low=rendah MinimizedWindow.name=Nama: PiecesView.size=Saiz PiecesView.numberofblocks=Jumlah Blok PiecesView.blocks=Blok PiecesView.completed=Selesai PiecesView.availability=Jumlah ketulan PiecesView.title.short=Ketulan PiecesView.title.full=Ketulan SystemTray.tooltip.seeding=%1 menyemai, SystemTray.tooltip.downloading=%1 memuat turun, DownloadManager.error.filenotfound=Fail tidak dijumpai DownloadManager.error.fileempty=Fail Torrent kosong DownloadManager.error.filetoobig=Fail Torrent terlalu besar DownloadManager.error.filewithouttorrentinfo=Maklumat Torrent tidak dijumpai DownloadManager.error.unsupportedencoding=Encoding tidak disokong DownloadManager.error.ioerror=Ralat IO DownloadManager.error.sha1=Tiada Algorithm tersebut, Ralat (SHA1) PeerManager.status.offline=offline PeerManager.status.ok=ok PeerManager.status.checking=Sedang memeriksa PeerManager.status.finished=Selesai PeerManager.status.finishedin=Selesai dalam MainWindow.upgrade.assistant=Pembantu mengemaskini MainWindow.upgrade.newerversion=Ada versi baru Vuze untuk dimuat turunkan MainWindow.upgrade.step1=Langkah 1: Memuat turunkan versi baru MainWindow.upgrade.step2=Langkah 2: Tutup versi ini dan buka semula versi baru Vuze MainWindow.upgrade.section.info=Ada Versi Baru MainWindow.upgrade.section.manual=Kemaskini secara manual MainWindow.upgrade.section.automatic=Kemas kini secara otomatik Button.next=Kemudian Button.finish=Habis Button.cancel=Batal IrcClient.copyright=Menggunakan PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Sedang disambungkan ke IrcClient.connected=Bersambung ke IrcClient.joining=Sedang memasuki IrcClient.channel=Saluran IrcClient.joined=telah dimasuki IrcClient.error=Ralat IrcClient.hasjoined=telah masuk IrcClient.haskicked=telah menendang IrcClient.hasleft=telah keluar IrcClient.nowknown=sekarang dikenali sebagai IrcClient.topicforchannel=Topik untuk saluran IrcClient.disconnected=Diputuskan dari IrcClient.noNick=Tiada Nama Timangan Ditetapkan. Sila ke pandangan 'Konfigurasi' IrcView.help=Valid commands are :\n . /help : displays this message\n . /nick | /name : changes your name \n . /me action : sends an action \n . /msg nick message : sends a private message to \n . /r message : reply to last private message\n . /join #channel : changes current channel PasswordWindow.title=Vuze telah dikunci PasswordWindow.passwordprotected=Vuze telah dikunci.\nUntuk menggunakannya, sila taip passwordnya disini : TrackerChangerWindow.title=Tambah Pengesan TrackerChangerWindow.newtracker=Masukkan url pengesan baru PeersView.discarded=Dibuang PeersView.discarded.info=Data yang anda terima walaupun tidak diperlukan, lalu dibuang. discarded=dibuang MyTorrentsView.menu.move=&Pindah MyTorrentsView.menu.moveUp=&Atas MyTorrentsView.menu.moveDown=&Bawah GeneralView.label.hashfails=Gagalan hash : GeneralView.label.shareRatio=Tahap Kongsi : ConfigView.label.startRatioPeers=Start seeding when there is less than 1 seed for ConfigView.text.neverStop=Jangan Berhenti ConfigView.text.neverStart=Jangan Mula ConfigView.text.peers=Rakankongsi wizard.title=Bina Torrent wizard.previous=< Sebelum wizard.next=Kemudian > wizard.finish=Selesai wizard.mode=Pengesan / Mode wizard.tracker=Pengesan: wizard.invalidurl=URL ini tidak sah wizard.directory=Direktori wizard.directory.help=Bina Torrent dari direktori wizard.choosefile=Pilih fail wizard.file=Fail : wizard.choosedirectory=Pilih direktori wizard.invalidfile=Fail tidak sah! wizard.invaliddirectory=Direktori tidak sah! wizard.torrentFile=Fail Torrent wizard.choosetorrent=Sila pilih fail Torrent untuk dibina wizard.information=Maklumat wizard.progresstitle=Sedang membina fail Torrent wizard.savingfile=Menyimpan fail... wizard.filesaved=Fail telah disimpan. wizard.close=Tutup Torrent.create.progress.piecelength=Saiz ketulan: Torrent.create.progress.piececount=Bilangan ketulan: Torrent.create.progress.totalfilesize=Jumlah saiz fail: Torrent.create.progress.totalfilecount=Jumlah bilangan fail: Torrent.create.progress.parsingfiles=Sedang "mengparse" fail Torrent.create.progress.hashing=Sedang "menghash" fail MainWindow.upgrade.downloadingfrom=Memuat turun dari : MainWindow.menu.view.ipFilter=&Penapis Ip ConfigView.section.ipfilter=Penapis Ip ConfigView.section.ipfilter.start=Ip permulaan ConfigView.section.ipfilter.end=Ip terakhir ConfigView.section.ipfilter.add=Tambah ConfigView.section.ipfilter.remove=Buang ConfigView.section.ipfilter.save=Simpan ConfigView.section.ipfilter.editFilter=Edit Penapis ConfigView.section.ipfilter.enable=Gunakan PeersView.menu.close=&Tutup seedmore.title=Torrent tidak cukup disemai seedmore.shareratio=Tahap kongsian anda pada Torrent ini sebanyak seedmore.uploadmore=Tahap kongsian dibawah 100% tidak baik untuk rangkaian bittorrent.\nYAnda sepatutnya menyemai Torrent ini sedikit lagi.\nPastikah anda? ConfigView.label.showpopuponclose=Show confirmation popup when stopping\nseeding with a share ratio lower than 1 ConfigView.section.seeding=Menyemai MyTorrentsView.menu.removeand=Buang dan MyTorrentsView.menu.removeand.deletetorrent=Padam .&torrent MyTorrentsView.menu.removeand.deletedata=Padam &Data MyTorrentsView.menu.removeand.deleteboth=Padam Kedua-duanya deletedata.title=!!! Awas !!! deletedata.message1=Kamu akan memadam DATA dari :\n MainWindow.menu.file.configure=Configuration &Wizard configureWizard.welcome.message=This wizard will help you configure Vuze for most common use. You can modify in depth the configuration using the View>Configuration menu. configureWizard.nat.message=In order to get the best out of BitTorrent, it's highly recommended to be fully accessible from the internet. Default bittorrent port is 6881. This tool lets you test and / or change the port. configureWizard.nat.unable=Unable to test configureWizard.file.title=Torrent / Fail configureWizard.file.message1=Vuze akan menyimpan Torrent terbuka di satu direktori, kamu boleh memilih direktori tersebut di sini: configureWizard.file.message2=Vuze boleh menyambung semula fail anda secara langsung, dengan menambah data sambung semula ke Torrent anda. Anda juga dapat menyambung semula ketulan yang belum habis dimuat turunkan. configureWizard.file.fastResume=Gunakan sambung semula cepat configureWizard.file.invalidPath=Direktori tidak sah configureWizard.finish.title=Selesai configureWizard.finish.message=Vuze telah dikonfigurasikan! exportTorrentWizard.title=Eksport Torrent exportTorrentWizard.torrentfile.title=Pilihan Torrent untuk digunakan exportTorrentWizard.torrentfile.message=Pilih fail Torrent untuk dieksport exportTorrentWizard.torrentfile.invalidPath=Fail Torrent tidak sah exportTorrentWizard.exportfile.title=Pilihan fail eksport exportTorrentWizard.exportfile.message=Masukkan fail untuk dieksportkan ke exportTorrentWizard.exportfile.invalidPath=Fail eksport tidak sah exportTorrentWizard.finish.title=Selesai exportTorrentWizard.finish.message=Eksport berjaya diselesaikan exportTorrentWizard.process.inputfilebad.title=Fail Torrent tidak sah exportTorrentWizard.process.inputfilebad.message=Tidak boleh baca fail yang digunakan: exportTorrentWizard.process.outputfileexists.title=Fail sudah ada exportTorrentWizard.process.outputfileexists.message=Fail yang dibina sudah ada - tukar dengan yang baru? exportTorrentWizard.process.torrentfail.title=Gagal untuk baca Torrent exportTorrentWizard.process.exportfail.title=Eksport Torrent Gagal importTorrentWizard.title=Import Torrent importTorrentWizard.torrentfile.title=Pilihan Torrent untuk digunakan importTorrentWizard.torrentfile.message=Pilih fail Torrent untuk diimport kedalam importTorrentWizard.torrentfile.invalidPath=Fail Torrent tidak sah importTorrentWizard.importfile.title=Pilihan fail import importTorrentWizard.importfile.message=Pilih fail untuk diimport importTorrentWizard.importfile.invalidPath=Fail import tidak sah importTorrentWizard.finish.title=Selesai importTorrentWizard.finish.message=Import berjaya diselesaikan importTorrentWizard.process.inputfilebad.title=Fail untuk diimport tidak sah importTorrentWizard.process.inputfilebad.message=Ralat ketika membaca fail untuk digunakan: importTorrentWizard.process.outputfileexists.title=Fail sudah ada importTorrentWizard.process.outputfileexists.message=Fail yang dibina sudah ada - padam dan tulis semula? importTorrentWizard.process.torrentfail.title=Tulisan ke Torrent gagal importTorrentWizard.process.importfail.title=Torrent gagal diimport ConfigView.section.stats=Statistik ConfigView.section.stats.enable=Gunakan ConfigView.section.stats.defaultsavepath=Direktori simpanan statistik ConfigView.section.stats.choosedefaultsavepath=Sila pilih direktori simpanan untuk statistik ConfigView.section.stats.savefreq=Kekerapan menyimpan ConfigView.section.stats.minutes=minit ConfigView.section.stats.hours=jam ConfigView.section.stats.seconds=saat ConfigView.section.stats.savefile=Nama fail statistik MyTorrentsView.menu.export=&Eksport... ConfigView.dialog.choosedefaulttorrentpath=Sila pilih direktori Torrent tetap ConfigView.dialog.choosemovepath=Sila pilih direktori untuk dipindahkan kedalam ConfigView.label.movecompleted=Move completed files ConfigView.label.savetorrents=Simpan fail .torrent MainWindow.menu.view.mytracker=&PengesanKu MyTrackerView.title.full=PengesanKu MyTrackerView.name=Nama MyTrackerView.tracker=Pengesan MyTrackerView.status.started=Berlangsung MyTrackerView.status.stopped=Dihentikan MyTrackerView.peers=Rakankongsi MyTrackerView.seeds=Penyemai MyTrackerView.announces=Makluman MyTrackerView.uploaded=Telah dimuat naik MyTrackerView.downloaded=Telah dimuat turun MyTrackerView.left=Baki MainWindow.menu.view.plugins=&Plugin fileDownloadWindow.saveTorrentIn=Simpan fail Torrent di fileDownloadWindow.title=Vuze - Pemuat turun Torrent fileDownloadWindow.downloading=Memuat turunkan dari : fileDownloadWindow.state_downloading=Sedang memuat turun fileDownloadWindow.state_error=Ralat : MainWindow.menu.file.open.url=&URL openUrl.title=Vuze - Buka Url MyTorrentsView.menu.host.error.message=The following error occurred when ConfigView.section.tracker=Pengesan ConfigView.section.tracker.checkip=Check Address... ipCheckerWizard.explanations=You can use this wizard to find out what your external IP address is. If your IP address is dynamic, we recommend that you open an account with a Dynamic DNS Service. Some such services are listed below, use the link provided to create an account (where supported). Then fill the IP address field with your dynamic hostname (e.g. myhostname.dyndns.org). You'll need a program to automatically update your Dynamic DNS Service with your IP address. That way, you'll be able to host torrents, even if your IP changes. wizard.tracker.local=Gunakan Pengesan Dalam Vuze wizard.tracker.external=Gunakan pengesan luar wizard.tracker.howToLocal=\tSila ke 'Konfigurasi>Pengesan' untuk menggunakannya wizard.announceUrl=URL makluman : splash.plugin=Loading Plugin : MyTorrentsView.menu.publish=&Publish... MyTrackerView.completed=Selesai MainWindow.menu.file.open.torrentnodefault=Fail .torrent (Tiada tempat simpan ditetapkan) wizard.comment=Komen # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Menggambarkan jumlah setiap ketulan yang ada.\nJika nombor di sebelah kanan kurang dari 1, anda tidak melihat fail yang selesai (dan mungkin menghadapi masalah menyelesaikan memuat turun). GeneralView.label.trackerurl.tooltip=Klik untuk menyalin URL makluman ke klipbod GeneralView.label.trackerurlopen.tooltip=Klik untuk membuka lelaman pengesan utama. # # 2.0.4.4 # ConfigView.section.logging=Catatan ConfigView.section.logging.enable=Gunakan catatan ke fail ConfigView.section.logging.logdir=Catatkan direktori fail ConfigView.section.logging.choosedefaultsavepath=Sila pilih direktori simpanan GeneralView.label.updatein.querying=querying... ConfigView.section.logging.maxsize=Had saiz fail catatan TableColumn.header.shareRatio=Tahap Kongsian wizard.operationfailed=Operasi gagal authenticator.tracker=Pengesan authenticator.user=Nama pengguna MainWindow.menu.help.checkupdate=&Cari versi baru TableColumn.header.down=Telah dimuat turunkan TableColumn.header.up=Telah dimuat naik MainWindow.dialog.exitconfirmation.title=Keluar dari Vuze MainWindow.dialog.exitconfirmation.text=Anda mahu keluar dari Vuze TrayWindow.menu.stopalldownloads=Berhentikan kesemua memuat turun wizard.tracker.ssl=Gunakan SSL TableColumn.header.pieces=Ketulan TableColumn.header.pieces.info=Gambaran menunjukkan ketulan yang telah dimuat turunkan TableColumn.header.completion=Penyelesaian TableColumn.header.completion.info=Gambaran peratusan yang telah dimuat turunkan wizard.multitracker.edit=Edit.. MyTorrentsView.menu.recheck=Paksa periksa semula iconBar.showDownloadBar.tooltip=Tunjuk barisan memuat turun iconBar.start.tooltip=Mula iconBar.stop.tooltip=Berhenti iconBar.remove.tooltip=Buang iconBar.openNoDefault.tooltip=Buka fail .torrent (tidak ditetapkan tempat simpan) iconBar.openURL.tooltip=Buka URL iconBar.openFolder.tooltip=Buka direktori iconBar.new.tooltip=Bina Torrent iconBar.up.tooltip=Pindah ke atas iconBar.down.tooltip=Pindah ke bawah iconBar.run.tooltip=Buka MyTorrentsView.menu.editTracker=&Edit URL Pengesan GeneralView.menu.selectTracker=Pilih ConfigView.section.stats.xslfile=Nama fail XSL ConfigView.section.stats.xslfiledetails=Ini akan dimasukkan kedalam fail statistik melalui tag ConfigView.section.ipfilter.allow=BENARKAN range tersebut (sepatutnya TIDAK DIBENARKAN) ConfigView.section.ipfilter.list.inrange=was in range ConfigView.section.ipfilter.list.title=Blocked IPs List ConfigView.label.allowsameip=Allow Multiple connections from the same IP ConfigView.label.userSuperSeeding=Gunakan Super Seeding PeersView.uniquepiece=Ketulan (Mode Super-Seed) PeersView.uniquepiece.none=Tiada ConfigView.section.style.addurlsilently=Buka URL secara senyap (tanpa dialog) ConfigView.section.style.addurlsilently.tooltip=Warning: the main window will not made visible again if activated!\nIf you loose the tray icon, you should deactivate this option. MyTorrentsView.menu.moveTop=&Paling Atas MyTorrentsView.menu.moveEnd=&Paling Bawah ConfigView.label.moveonlyusingdefaultsave=if in default data dir ConfigView.dialog.choosewatchtorrentfolderpath=Sila pilih direktori import .torrent ConfigView.section.plugins=Plugin wizard.maketorrent.filesize=Saiz fail wizard.maketorrent.piececount=Jumlah ketulan wizard.maketorrent.piecesize=Saiz ketulan MainWindow.menu.view.stats=&Statistik SpeedView.title.full=Activiti SpeedView.downloadSpeed.title=Kelajuan memuat turun SpeedView.uploadSpeed.title=Kelajuan memuat naik ConfigView.section.style.useSIUnits=Gunakan unit IEC (KB -> KiB dll.) iconBar.top.tooltip=Pindah ke paling atas iconBar.bottom.tooltip=Pindah ke paling bawah TableColumn.header.health=Kecergasan MyTorrentsView.menu.health=&Tentang Kecergasan health.explain.grey=Torrent anda tidak berlangsung (memuat turun atau memuat naik). health.explain.red=Anda tidak bersambung kepada mana-mana rakankongsi apabila memuat turun. health.explain.blue=Apabila menyemai, ia bermakna bahawa anda belum lagi disambungkan kepada mana-mana rakankongsi\napabila memuat turun, ia bermakna anda telah bersambung kepada rakan kongsi lain tetapi pengesan tidak berfungsi. health.explain.yellow=Bermakna pengesan berfungsi dan anda telah bersambung dengan rakan-rakankongsi, tetapi anda tidak mempunyai sambungan dari luar.\nAnda mungkin menghadapi masalah NAT jika Torrent kamu tetap berwarna kuning. health.explain.green=Semua berjalan lancar. ConfigView.section.style.alwaysRefreshMyTorrents=Selalu lancarsemula TorrentKu # #2.0.7.0 # MainWindow.menu.file.share=&Kongsi MainWindow.menu.file.share.file=&Fail... MainWindow.menu.file.share.dir=D&irektori... MainWindow.menu.file.share.dircontents=&Kandungan Direktori... MainWindow.menu.file.share.dircontentsrecursive=Kandungan Direktori (&Rekursif)... MainWindow.dialog.share.sharefile=Pilih fail untuk dikongsi MainWindow.dialog.share.sharedir=Pilih direktori untuk dikongsi MainWindow.dialog.share.sharedircontents=Pilih kandungan direktori untuk dikongsi MainWindow.dialog.share.sharedircontents.recursive=Rekursif ConfigView.label.prioritizefirstpiece=Prioritize first piece of file(s) ConfigView.label.prioritizefirstpiece.tooltip=Attempts to download the very beginning of a file first.\nFor support of early previewing. TrayWindow.menu.startalldownloads=Mulakan kesemua memuat turun MainWindow.menu.view.myshares=PengongsianKu MySharesView.title.full=PengongsianKu MySharesView.name=Nama MySharesView.type=Jenis MySharesView.type.file=Fail MySharesView.type.dir=Direktori MySharesView.type.dircontents=Kandungan direktori MySharesView.type.dircontentsrecursive=Kandungan direktori (recursif) GeneralView.label.hash.tooltip=Kilk untuk menyalin hash ke klipbod ConfigView.label.serverport=Incoming TCP listen port ConfigView.section.sharing=Pengongsian ConfigView.section.sharing.usessl=Gunakan SSL untuk shared resources (memerlukan konfigurasi pengesan) # # 2.0.7.x # Categories.all=Semua Categories.uncategorized=Tidak dikategorikan CategoryAddWindow.message=Masukkan nama kategori baru CategoryAddWindow.title=Tambah Kategori Baru ConfigView.label.autoSeedingIgnoreInfo=Ignored torrents go to the bottom of the seeding queue. They do not get automatically started. Ignore rules do not apply to torrents that match the First Priority criteria. Unless otherwise stated, use a value of 0 to disable a rule. ConfigView.label.minPeersToBoostNoSeeds=Tahap menyemai yang lebih rendah untuk Torrent yang tidak mempunyai penyemai dan kurang dari ConfigView.label.minSeedingTime.tooltip=Seeding Ranks can fluctuate often in a short period time, sometimes causing the torrent to automatically start, only to be stopped && queued immediately afterwards.\nThis alleviates the problem by forcing the torrent to stay seeding for a given period of time. You can still stop it manually if you want. ConfigView.label.minSeedingTime=Jangkamasa minimum untuk menyemai dalam saat ConfigView.label.savedirectory=Direktori Simpanan ConfigView.label.seeding.autoReposition=Atur semula Torrent mengikut tahap kongsi ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Biasanya, Torrent yang mempunyai kadar penyemai yang rendah serta bilangan rakankongsi yang tinggi bermakna \nbahawa kemungkinan tiada salinan penuh di kalangan rakankongsi. Kerana itu, anda mungkin tidak mahu \nundang-undang menyemai menganggap bahawa ada salinan penuh (sekaligus tersilap merendahkan tahapnya) ConfigView.label.seeding.fakeFullCopySeedStart=tetapi hanya untuk Torrent yang mempunyai sekurang-kurangnya ConfigView.label.seeding.firstPriority.info=Torrent berkepentingan utama akan sentiasa di atas susunan. Mana-mana Torrent yang memuaskan kriteria kepentingan utama tidak akan diberhentikan secara otomatik, serta akan menggunakan slot memuat turun lain jika perlu. ConfigView.label.seeding.firstPriority=Kepentingan utama diberi kepada Torrent yang memuaskan ConfigView.label.seeding.firstPriority.following=daripada berikut: ConfigView.label.seeding.firstPriority.shareRatio=Tahap kongsi kurang dari ConfigView.label.seeding.firstPriority.seedingMinutes=Masa yang telah berlalu sejak bertukar dari memuat turun ke manyemai ConfigView.label.seeding.firstPriority.DLMinutes=Masa yang telah berlalu sejak mulanya memuat turun ConfigView.label.seeding.numPeersAsFullCopy=Anggap bahawa ada 1 salinan penuh bagi setiap\n(0 : Jangan anggap) ConfigView.label.seeding.preferLargerSwarms=Apabila Torrent mempunyai tahap yang sama, pilih kumpulan lebih besar ConfigView.pluginlist.info=Plugin tersebut telah dikesan. Plugin tidak sementinya mempunyai butang konfigurasi. ConfigView.pluginlist.noplugins=Tiada plugin dikesan. ConfigView.section.queue.seeding=Menyemai ConfigView.section.queue.seeding.autoStarting=Permulaan Otomatik ConfigView.section.queue.seeding.firstPriority=Kepentingan utama ConfigView.section.torrents=Torrent ConfigView.text.all=semua ConfigView.text.hours=jam ConfigView.text.ignoreRule=Jangan perdulikan undang-undang ConfigView.text.ignore=Jangan perdulikan ConfigView.text.minutes=minit ConfigView.text.neverIgnore=Jangan tidak perdulikan ConfigView.text.any=mana-mana DownloadManager.error.datamissing=Tidak ada Data MainWindow.menu.file.open.torrentforseeding=Fail .torrent (Untuk penyemaian) MainWindow.menu.language.refresh=&Lancarsemula ManagerItem.forced=Dipaksa MySeedersView.header=Selesai/Menyemai Torrents TableColumn.header.availability.info=Jumlah fail penuh yang dikesan TableColumn.header.availability=Jumlah ketulan TableColumn.header.category=Kategori MyTorrentsView.header=Belum selesai/Sedang memuat turunkan Torrent TableColumn.header.maxuploads=Had bilangan memuat naik MyTorrentsView.menu.category.delete=&Padam Kategori MyTorrentsView.menu.forceStart=&Paksa Bermula MyTorrentsView.menu.setCategory.add=&Tambah Kategori.. MyTorrentsView.menu.setCategory=Tetapkan Kategori TableColumn.header.savepath=Tempat simpan TableColumn.header.SeedingRank=Tahap penyemaian TableColumn.header.totalspeed.info=Jumlah rakankongsi yang telah bersambung TableColumn.header.totalspeed=Jumlah kelajuan StartStopRules.shareRatioMet=Share Ratio Ok GeneralView.label.creationdate=Dibina pada : ManagerItem.stopping=Sedang berhenti fileDownloadWindow.retry=Cuba lagi MyTrackerView.bytesin=Bytes masuk MyTrackerView.bytesinave=Purata masuk MyTrackerView.bytesout=Bytes keluar MyTrackerView.bytesoutave=Purata keluar ConfigView.section.proxy=Proxy ConfigView.section.proxy.enable_proxy=Enable proxy wizard.createtorrent.extrahashes=Tambah hash untuk rangkaian lain (e.g. Gnutella2, eDonkey2000) GeneralView.label.connected=bersambung GeneralView.label.in_swarm=di kumpulan AlertMessageBox.error=Ralat AlertMessageBox.warning=Awas AlertMessageBox.comment=Maklumat AlertMessageBox.information=Maklumat Tracker.alert.listenfail=Tidak dapat menggunakan port %1.\nPastikan program lain tidak menggunanya.\nPastikan juga tiada sesi Vuze lain berlangsung. DiskManager.alert.movefileexists=Ralat ketika memindahkan fail\nFail %1 sudah wujud di direktori destinasi SpeedView.stats.title=Statistik SpeedView.stats.total=Jumlah SpeedView.stats.session=Sesi ini SpeedView.stats.downloaded=Telah dimuat turun SpeedView.stats.uploaded=Telah dimuat naik SpeedView.stats.uptime=Masa berfungsi (jam) # # > 2.0.8.0 # OpenTorrentWindow.title=Buka Torrent OpenTorrentWindow.addFiles=&Tambah Fail OpenTorrentWindow.dataLocation=Tempat simpan data: OpenTorrentWindow.addPosition=Kedudukan beratur OpenTorrentWindow.addPosition.first=Pertama OpenTorrentWindow.addPosition.last=Terakhir popup.error.hide=Sembunyikan popup.error.details=Maklumat terperinci ConfigView.section.tracker.publishenabledetails=Publish torrent file and peer details #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed ConfigView.label.overrideip=Override IP address sent to tracker\n - Only use if you really know why you'd need it! #file can be a URL or a path in the jar ConfigView.section.logging.log0type=Maklumat # %1 = "in kbps" or ""; %2 = "upload" or "download" OpenTorrentWindow.torrentLocation=Fail Torrent: Button.moveUp=Pindah ke atas Button.moveDown=Pindah ke bawah # > 2402 MainWindow.menu.help.faq=&FAQ MainWindow.menu.help.donate=&Derma !!! azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_eu.properties0000644000175000017500000012500411301156004025502 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torrent fitxategia... Main.parameter.usage=Erabilera: java org.gudy.azureus2.cl.Main [parameters] "file.torrent" "save path" Main.parameter.maxUploads=Aldibereko karga-kopuru maximoa Main.parameter.maxSpeed=Karga-abiadura maximoa byte/seg-tan MainWindow.menu.file=&Fitxategia MainWindow.menu.file.open=&Ireki MainWindow.menu.file.create=&Torrent berria... MainWindow.menu.file.create.fromfile=&Fitxategi batetik MainWindow.menu.file.create.fromdir=&Direktorio batetik MainWindow.menu.file.export=&Esportatu XML torrent-a... MainWindow.menu.file.export.keybinding.mac=Meta+Shit+E MainWindow.menu.file.import=&Inportatu XML torrent-a... MainWindow.menu.file.closetab=Itxi &fitxa MainWindow.menu.file.closewindow=Itxi &leihoa MainWindow.menu.file.exit=I&rten MainWindow.dialog.choose.file=Hautatu torrent fitxategia MainWindow.menu.file.folder=&Karpeta... MainWindow.dialog.choose.folder=Hautatu torrent fitxategien direktorioa MainWindow.menu.view=&Ikusi MainWindow.menu.view.show=Erakutsi MainWindow.menu.view.mytorrents=&Nire torrent-ak MainWindow.menu.view.open_global_transfer_bar=Transferentzien barra MainWindow.menu.view.configuration=&Aukerak... MainWindow.menu.view.console=K&ontsola MainWindow.menu.view.allpeers=Pare guztiak MainWindow.menu.view.detailedlist=Zerrenda &xehea MainWindow.menu.closealldetails=Itxi xehetasun &guztiak MainWindow.menu.closealldownloadbars=Itxi deskarga-&barra guztiak MainWindow.menu.language=&Hizkuntza ConfigView.section.language=Hizkuntza MainWindow.menu.window=&Leihoa MainWindow.menu.window.minimize=&Ikonotu MainWindow.menu.window.alltofront=Mugitu denak &aurrera MainWindow.menu.help=La&guntza MainWindow.menu.help.about=Vuze-ri buruz MainWindow.menu.torrent=T&orrent-a MainWindow.about.title=Honi buruz MainWindow.about.section.developers=Garatzaileak MainWindow.about.section.translators=Itzultzaileak MainWindow.about.section.system=Sistema MainWindow.about.internet.homepage=Vuze-ren webgunea MainWindow.about.internet.sourceforge=Proiektuaren webgunea Sourceforge-n MainWindow.about.internet.sourceforgedownloads=Sourceforge-ko deskargak MainWindow.about.internet.bugreports=Akatsen jakinarazpena MainWindow.about.internet.forumdiscussion=Foroak MainWindow.about.internet.wiki=Vuze-ren wikiko MEG-ak MainWindow.dialog.choose.savepath=Hautatu gordetze-bidea MainWindow.dialog.choose.savepath_forallfiles=Hautatu fitxategi GUZTIEN gordetze-bidea MainWindow.status.latestversion=Azkena MainWindow.status.latestversion.clickupdate=Egin klik eguneratzeko MainWindow.status.unknown=ezezaguna MainWindow.status.checking=egiaztatzen MyTorrentsView.mytorrents=Nire torrent-ak TableColumn.header.name=Izena TableColumn.header.size=Tamaina TableColumn.header.done=Egina TableColumn.header.done.info=Uneko atazatik egindako ehunekoa TableColumn.header.status=Egoera TableColumn.header.status.info=Torrent-a egiten ari dena TableColumn.header.seeds=Aleak TableColumn.header.seeds.info=Konektatutako # ale (# ale guztira) TableColumn.header.peers=Pareak TableColumn.header.peers.info=# pare konektaturik (# pare guztira) TableColumn.header.completed=Osatua TableColumn.header.completed.info=Torrent-aren deskarga amaitu duten pareen #, aztarnariaren arabera TableColumn.header.downspeed=Deskarga-abiadura TableColumn.header.upspeed=Karga-abiadura TableColumn.header.eta=GDD TableColumn.header.tracker=Aztarnariaren egoera TableColumn.header.tracker.info=Aztarnariaren egoera TableColumn.header.trackernextaccess=Hurrengo aztarnariaren atzipena TableColumn.header.trackernextaccess.info=Hurrengo aztarnariaren atzipena noiz gertatuko den TableColumn.header.priority=Lehentasuna TableColumn.header.priority.info=Torrent-ari ematen zaion banda-zabalera finkatzen du TableColumn.header.seeds.fullcopycalc= %1 parek onartutako %2 kopia oso MyTorrentsView.menu.showdetails=Erakutsi &xehetasunak MyTorrentsView.menu.showdownloadbar=Erakutsi deskarga-&barra MyTorrentsView.menu.open=&Ireki fitxategia MyTorrentsView.menu.setpriority=Ezarri &lehentasuna MyTorrentsView.menu.setpriority.high=&Altua MyTorrentsView.menu.setpriority.low=&Baxua MyTorrentsView.menu.start=&Hasi MyTorrentsView.menu.stop=&Gelditu MyTorrentsView.menu.remove=&Ezabatu MyTorrentsView.menu.changeTracker=Gehitu aztarnariaren &URLa TrayWindow.menu.exit=I&rten TrayWindow.menu.show=Erakutsi &Vuze SystemTray.menu.exit=I&rten SystemTray.menu.closealldownloadbars=Itxi deskarga-&barra guztiak SystemTray.menu.open_global_transfer_bar=Erakutsi transferentzien barra SystemTray.menu.show=Erakutsi &Vuze PeersView.ip=IPa PeersView.ip.info=Parearen IPa PeersView.port=Ataka PeersView.port.info=Erabiltzen ari den ataka PeersView.T.info=L (lokala): zuk ezarri duzu konexioa, R (urrunekoa): pareak ezarri du konexioa. PeersView.T.L.tooltip=Zuk ezarri duzu konexioa PeersView.T.R.tooltip=Pareak ezarri du konexioa PeersView.I1=I (parearen interesekoa) PeersView.I1.info=Beste pareak duena interesatzen zaizu? PeersView.C1=C (Pareak buxatua) PeersView.C1.info=Pareak deskarga galarazten badizu PeersView.pieces=Atalak PeersView.downloadspeed=Deskarga-abiadura PeersView.download=Deskarga PeersView.I2=I (parearentzat interesgarria) PeersView.I2.info=Parea zure fitxategiren batean interesaturik dago? PeersView.C2=C (parea buxatzen) PeersView.C2.info=Pareari deskarga galarazten badiozu PeersView.uploadspeed=Karga-abiadura PeersView.uploadspeed.info=Zure karga-abiadura parearekiko PeersView.upload=Kargatu PeersView.upload.info=Zure karga-abiadura osoa parearekiko PeersView.statup=Batez besteko karga PeersView.statup.info=Parearen karga-abiaduraren balio estimatua PeersView.S.info=Errefusatua: Pare bat eskuz "errefusa" daiteke, edo automatikoki (datuak abiadura motelegian bidaltzeagatik) PeersView.downloadspeedoverall=Deskarga-abiadura guztira PeersView.optunchoke=Auk. Ezabatu buxadura PeersView.client=Bezeroa PeersView.client.info=Parea erabiltzen ari den BT bezero-mota PeersView.menu.snubbed=&Errefusatua PeersView.title.short=Pareak PeersView.title.full=Pareak AllPeersView.title.full=Pare guztiak ConfigView.section.files=Fitxategiak ConfigView.label.usefastresume=Erabili berrabiaratze azkarreko aukera ConfigView.label.incrementalfile=Gaitu fitxategien sorrera inkrementala [beharrezkoa Linux-en FAT32 erabiliz gero] ConfigView.label.defaultsavepath=Direktorio lehenetsian gorde ConfigView.button.browse=&Arakatu... ConfigView.dialog.choosedefaultsavepath=Adierazi lehenetsitako gordetze-direktorioa ConfigView.section.server=Konexioa ConfigView.section.global=Orokorra ConfigView.label.disconnetseed=Deskonektatu aleak aletzean ConfigView.label.switchpriority=Aletzean lehentasun baxura aldatu automatikoki ConfigView.label.maxdownloads=Aldibereko deskarga-kopuru maximoa [0: mugagabea]\n - Ezin da izan torrent aktiboen kopuru maximoa baino altuagoa ConfigView.label.maxdownloads.tooltip=Hemen erabaki duzun kopurua aktiboki deskargatu ahal izango duzu beti, salbuespen batekin.\nLehentasun handiena duen torrent osatu batek deskarga aktibo baten lekua har dezake guztiz beharrezkoa bada. ConfigView.label.maxactivetorrents=Torrent aktiboen kopuru maximoa [0: mugagabea]\n - Torrent berriak ez dira abian jarriko gehiago deskargatzen/aletzen ari bazara ConfigView.label.priorityExtensions=Eman lehentasuna automatikoki fitxategi hauei: \n - adib: .txt;.nfo;.jpg ConfigView.section.transfer=Transferentzia ConfigView.label.maxuploads=Karga-zirrikituen kopuru maximo lehenetsia torrent bakoitzeko ConfigView.label.maxuploadspeed=Karga-abiadura maximoa guztira KB/s-tan [0: mugagabea] ConfigView.label.saveresumeinterval=Eguneratu berrekite-datuak ConfigView.unlimited=Mugagabea ConfigView.section.display=Bistaratzea ConfigView.label.opendetails=Ireki automatikoki xehetasunen fitxa ConfigView.label.openbar=Ireki automatikoki deskarga-barra ConfigView.label.use_old_speed_menus=Erabili estilo zaharreko abiadura-menuak [aplikazioa berrabiarazi behar da] ConfigView.label.closetotray='Itxi' aukerak sistemaren erretilura ikonotzen du ConfigView.label.minimizetotray='Ikonotu' aukerak sistemaren erretilura ikonotzen du ConfigView.section.general=Orokorra ConfigView.section.start=Hasi ConfigView.label.showsplash=Erakutsi splash pantaila ConfigView.label.autoupdate=Ireki berritze-leihoa bertsio berri bat eskuragarri dagoenean ConfigView.label.openconsole=Ireki kontsola abioan ConfigView.label.openconfig=Ireki aukeren leihoa abioan ConfigView.label.startminimized=Abiatu ikonotuta ConfigView.label.ircwiki=Irakurri http://azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Zerbitzaria ConfigView.label.ircchannel=Kanala ConfigView.label.irclogin=Ezizena ConfigView.group.irctitle=IRC konfigurazioa ConfigView.boolean.ircsendinfo=Baimendu zure ezarpenak bidaltzea (modu anonimoan)\n kanal-eragileei, laguntza eman ahal diezazuten ConfigView.boolean.irclog=Gaitu kanal-jardueraren datuen erregistratzea (IRC_log.htm barnean) ConfigView.section.security=Segurtasuna ConfigView.label.password=Babestu Vuze pasahitza erabiliz\n - Abioan eta ikonotutako leihoa leheneratzean eskatuko da. ConfigView.label.passwordconfirm=Pasahitza (baieztapena) ConfigView.label.passwordmatch=Pasahitza aktibatua: ConfigView.label.passwordmatchnone=Ez ConfigView.label.passwordmatchno=Ez / Pasahitza ez da zuzena ConfigView.label.passwordmatchyes=Bai ConfigView.button.save=Gorde ConfigView.title.short=Aukerak ConfigView.title.full=Aukerak ConfigView.title.full._mac=Hobespenak ConsoleView.title.short=Kontsola ConsoleView.title.full=Kontsola FileItem.write=idatzi FileItem.read=irakurri FileItem.normal=normala FileItem.high=altua FileItem.donotdownload=Ez deskargatu FileItem.delete=Ezabatu FilesView.name=Izena FilesView.name.fastRename=Berrizendatze azkarra FilesView.size=Tamaina FilesView.done=Egina FilesView.firstpiece=Lehen atala # FilesView.numberofpieces=# atal FilesView.pieces=Atalak FilesView.mode=Modua FilesView.priority=Lehentasuna FilesView.menu.open=&Ireki FilesView.menu.setpriority=Ezarri &lehentasuna FilesView.menu.setpriority.high=&Altua FilesView.menu.setpriority.normal=&Normala FilesView.menu.setpriority.skipped=&Ez deskargatu FilesView.title.short=Fitxategiak FilesView.title.full=Fitxategiak GeneralView.section.downloaded=Deskargatua GeneralView.label.status.file=Fitxategiaren egoera GeneralView.label.status.pieces=Atalen egoera GeneralView.section.availability=Eskuragarritasuna GeneralView.label.status.pieces_available=Atalen egoera GeneralView.section.transfer=Transferentzia GeneralView.section.info=Informazioa GeneralView.title.short=Orokorra GeneralView.title.full=Orokorra GeneralView.label.timeelapsed=Igarotako denbora: GeneralView.label.remaining=Falta dena: GeneralView.label.downloaded=Deskargatua: GeneralView.label.downloadspeed=Deskarga-abiadura: GeneralView.label.maxuploads=Karga-zirrikituak: GeneralView.label.maxuploads.tooltip=Une jakin batean buxadura ezabatuko zaien pare-kopuru maximoa GeneralView.label.uploaded=Kargatua: GeneralView.label.uploadspeed=Karga-abiadura: GeneralView.label.seeds=Aleak: GeneralView.label.peers=Pareak: GeneralView.label.completed=Osatua: GeneralView.label.totalspeed=Erlekumearen abiadura: GeneralView.label.totalspeed.tooltip=Zurekin konektatuta dauden bezero guztien abiadura osoa (eta batez bestekoa). GeneralView.label.averagespeed=batez bestekoa GeneralView.label.filename=Izena: GeneralView.label.totalsize=Tamaina osoa: GeneralView.label.savein=Gorde hemen: GeneralView.label.hash=Hash-a: GeneralView.label.numberofpieces=# atal GeneralView.label.size=Tamaina: GeneralView.label.tracker=Aztarnariaren egoera: GeneralView.label.updatein=Eguneratu hemen: GeneralView.label.trackerurl=Aztarnariaren URLa: GeneralView.label.trackerurlupdate=Eguneratu aztarnaria GeneralView.label.comment=Torrent-aren iruzkina: GeneralView.label.user_comment=Erabiltzailearen iruzkina: GeneralView.label.status=Egoera: ManagerItem.waiting=Itxaroten ManagerItem.allocating=Esleitzen ManagerItem.checking=Egiaztatzen ManagerItem.ready=Torrent-ak ilaran jar daitezen itxaroten ManagerItem.downloading=Deskargatzen ManagerItem.seeding=Aletzen ManagerItem.stopped=Geldituta ManagerItem.error=Errorea ManagerItem.high=altua ManagerItem.low=baxua MinimizedWindow.name=Izena: MinimizedWindow.all_transfers=Vuze-ren transferentziak PiecesView.size=Tamaina PiecesView.numberofblocks=Blokeen # PiecesView.blocks=Blokeak PiecesView.completed=Osatua PiecesView.availability=Eskuragarritasuna PiecesView.reservedby=Erreserbatua PiecesView.writers=Blokearen emaileak PiecesView.title.short=Atalak PiecesView.title.full=Atalak SystemTray.tooltip.seeding=%1 aletzen, SystemTray.tooltip.downloading=%1 deskargatzen, DownloadManager.error.filenotfound=Ez da aurkitu fitxategia DownloadManager.error.fileempty=Torrent fitxategia hutsik dago DownloadManager.error.filetoobig=Torrent fitxategia handiegia da DownloadManager.error.filewithouttorrentinfo=Ez da torrent informaziorik aurkitu fitxategian DownloadManager.error.unsupportedencoding=Onartzen ez den kodeketa DownloadManager.error.ioerror=IO errorea DownloadManager.error.sha1=(SHA1) errorea, ez dago algoritmo hori PeerManager.status.offline=Konexio-errorea PeerManager.status.checking=Egiaztatzen PeerManager.status.finished=Amaitua PeerManager.status.finishedin=Amaitze-denbora MainWindow.upgrade.assistant=Berritze-laguntzailea MainWindow.upgrade.newerversion=Vuze-ren bertsio berri bat dago eskuragarri MainWindow.upgrade.explanation=Laguntzaile honek bertsio berria deskargatuko du zure ordenagailuko Vuze karpetara eta Vuze berrabiaraziko du MainWindow.upgrade.explanation.manual=Eskuz eguneratu dezakezu aplikazioa Vuze itxiz, bertsio berria deskargatuz eta Vuze berrabiaraziz MainWindow.upgrade.step1=1. urratsa: Deskargatu bertsio berria MainWindow.upgrade.step2=2. urratsa: Bertsio hau itxi eta Vuze-ren bertsio berria berrabiarazi MainWindow.upgrade.hint1=Aholkua:\t Amaitu botoia sakatuz dena automatikoki egingo da MainWindow.upgrade.hint2=Aholkua:\tGero Vuze itxi nahi baduzu, sakatu Utzi eta\n\titxi ondoren berrizendatu Azureus2-new.jar eta deitu Azureus2.jar MainWindow.upgrade.error.downloading.hint=Errorea:\tEzin izan da bertsio berria deskargatu, mesedez eguneratu eskuz MainWindow.upgrade.section.info=Bertsio berria eskuragarri MainWindow.upgrade.section.manual=Eskuzko eguneraketa MainWindow.upgrade.section.automatic=Eguneraketa automatikoa MainWindow.upgrade.tooltip.progressbar=Deskargaren aurrerapena hemen erakusten da Button.next=Hurrengoa Button.finish=Amaitu Button.cancel=&Utzi LocaleUtil.title=Hautatu kodeketa LocaleUtil.section.chooseencoding=Hautatu kodeketa fitxategi-izenerako LocaleUtil.label.chooseencoding=Hautatu kodeketarik egokiena LocaleUtil.label.hint.doubleclick=Aholkua: lerro batean bi aldiz klik eginez kodeketa hautatzen da eta leihoa ixten da LocaleUtil.label.checkbox.rememberdecision=Gogoratu erabakia gainerako fitxategi-izenetarako LocaleUtil.column.encoding=Kodeketa IrcClient.defaultChannel=#Azureus-erabiltzaileak IrcClient.copyright=PircBot Java IRC APIa erabiltzen - http://www.jibble.org/pircbot.php IrcClient.connecting=Konektatzen hona: IrcClient.connected=Konektatua hona: IrcClient.joining=Sartzen IrcClient.channel=Kanala IrcClient.joined=sartuta IrcClient.error=Errorea IrcClient.hasjoined=sartu da IrcClient.haskicked=kanporatu dute IrcClient.hasleft=utzi du IrcClient.nowknown=orain honela ezagutzen dute: IrcClient.topicforchannel=Gaia kanalerako IrcClient.disconnected=Deskonektatua hemendik: IrcClient.noNick=Ez da goitizenik adieraz. Mesedez joan 'Aukerak' atalera IrcView.actionnotsupported=Ekintza hau ez dago onartua IrcView.clientsconnected=erabiltzaileak IrcView.privateto=Hona: IrcView.privatefrom=Hemendik IrcView.noticefrom=Oharra: IrcView.errormsg=Sintaxi akastuna /msg : /msg erabiltzaile-testuan IrcView.help=Baliozko aginduak hauek dira:\n . /help: mezu hau erakusten du\n . /nick | /name: zure izena aldatzen du \n . /me action: ekintza bat bidaltzen du \n . /msg nick message: mezu pribatua bidaltzen dio -(e)ri\n . /r message: azken mezu pribatuari erantzuten dio\n . /join #channelB (ez egin klik hemen, adibide bat da): uneko kanaletik channelB-ra aldatzen du PasswordWindow.title=Vuze blokeatuta dago PasswordWindow.passwordprotected=Vuze pasahitzez babestuta dago.\nVuze-ren leihoa erakusteko, mesedez sartu zure pasahitza hemen: TrackerChangerWindow.title=Gehitu aztarnaria TrackerChangerWindow.newtracker=Sartu aztarnari berriaren URLa PeersView.discarded=Baztertua PeersView.discarded.info=Nola edo hala jaso duzun datua, nahiz eta beharrezkoa ez izan, eta baztertu duzuna. discarded=baztertua MyTorrentsView.menu.move=&Mugitu MyTorrentsView.menu.moveUp=&Gora MyTorrentsView.menu.moveDown=&Behera GeneralView.label.hashfails=Hash-ak huts egin du: GeneralView.label.shareRatio=Partekatze-tasa: ConfigView.section.downloadManagement=Deskargen kudeaketa ConfigView.label.startRatioPeers=Hasi aletzen ale bat baino gutxiago dagoenean honentzat: ConfigView.text.neverStop=Ez gelditu inoiz ConfigView.text.neverStart=Ez hasi inoiz ConfigView.text.peers=Pareak ConfigView.label.checkOncompletion=Egiaztatu berriro atalak deskarga egin ondoren wizard.title=Sortu torrent-a wizard.previous=< Atzera wizard.next=Aurrera > wizard.finish=Amaitu wizard.mode=Aztarnaria / Modua wizard.tracker=Aztarnaria: wizard.invalidurl=URL hau baliogabea da wizard.singlefile=Fitxategi bakarra wizard.singlefile.help=Sortu torrent-a fitxategi bakarretik wizard.directory=Direktorioa wizard.directory.help=Sortu torrent-a direktorio batetik wizard.choosefile=Hautatu fitxategia wizard.file=Fitxategia: wizard.browse=Arakatu... wizard.choosedirectory=Hautatu direktorioa wizard.invalidfile=Baliogabeko fitxategia! wizard.invaliddirectory=Baliogabeko direktorioa! wizard.torrentFile=Torrent fitxategia wizard.choosetorrent=Hautatu sortuko den torrent fitxategia wizard.information=Informazioa wizard.notimplemented=Garatu gabea wizard.progresstitle=Torrent fitxategia sortzen wizard.savingfile=Fitxategia gordetzen... wizard.filesaved=Fitxategia gordeta. wizard.close=Itxi Torrent.create.progress.piecelength=Atalen luzera: Torrent.create.progress.piececount=Atal-kopurua: Torrent.create.progress.totalfilesize=Fitxategiaren tamaina osoa: Torrent.create.progress.totalfilecount=Fitxategi-kopuru osoa: Torrent.create.progress.parsingfiles=Fitxategiak prozesatzen Torrent.create.progress.hashing=Fitxategien hash-a sortzen MainWindow.upgrade.downloadingfrom=Deskargatzen hemendik: MainWindow.menu.view.ipFilter=&IP iragazkiak ConfigView.section.ipfilter=IP iragazkiak ConfigView.section.ipfilter.description=Deskribapena ConfigView.section.ipfilter.start=Hasierako IPa ConfigView.section.ipfilter.end=Amaierako IPa ConfigView.section.ipfilter.add=Gehitu ConfigView.section.ipfilter.remove=Ezabatu ConfigView.section.ipfilter.edit=Editatu ConfigView.section.ipfilter.save=Gorde ConfigView.section.ipfilter.editFilter=Editatu iragazkia ConfigView.section.ipfilter.enable=Gaitu PeersView.menu.close=&Itxi seedmore.title=Torrent-ak ez dauka aski alerik seedmore.shareratio=Torrent honentzako, zure partekatze-tasa hau da: seedmore.uploadmore=Ehuneko 100eko partekatze-tasa baino txikiagoa edukitzea ez da ona torrent sarearentzat.\nTorrent honi pixka bat gehiago aletzen utzi behar zenioke.\nSeguru jarraitu nahi duzula? ConfigView.label.showpopuponclose=Erakutsi berrespen-leihoa 1 azpitik dagoen partekatze-tasa duen aletzea gelditzean ConfigView.label.startNumSeeds=\nHasi aletzen hauek baino gutxiago daudenean:\n - Gainerako arauak gainidazten ditu ConfigView.label.seeds=ale ConfigView.section.seeding=Aletzen MyTorrentsView.menu.removeand=Ken&du eta MyTorrentsView.menu.removeand.deletetorrent=Ezabatu &torrent fitxategia MyTorrentsView.menu.removeand.deletedata=Ezabatu &datuak MyTorrentsView.menu.removeand.deleteboth=Ezabatu &biak deletedata.title=Ezabatu edukia deletedata.message1=Seguru '%1' behin-betiko ezabatu nahi duzula? deletedata.noprompt=Ez galdetu berriro MainWindow.menu.file.configure=Konfigurazio-&morroia... configureWizard.title=Konfigurazio-morroia configureWizard.welcome.title=Ongi etorri Vuze-ren konfigurazio-morroira configureWizard.welcome.message=Morroi honek zure Vuze modu egokian erabiltzen lagunduko dizu. Konfigurazioa sakonago aldatu nahi baduzu, erabili Tresnak->Aukerak menua. configureWizard.transfer.title=Transferentziaren eta konexioaren konfigurazioa configureWizard.transfer.hint=Aholkua: hautatu zure linearen abiadura baino pixka bat txikiagoa. configureWizard.transfer.message=Hautatu azpian adierazitako konexioetako bat. Kontuan izan karga-abiadura aski altua onartzen ez bada, deskarga-abiadura motela izango dela. Karga-abiadura torrent BAKOITZEKO soilik zenbatzen denez, torrent gehiegi aldi berean deskargatzeak ere abiadura motel dezake. Gutxieneko HERTSI gisa, torrent bakoitzeko 5KB/s erabiltzea aholkatzen dugu. Azkarrago kargatzen baduzu, azkarrago deskargatuko duzu (torrent-aren abiadurarekin konparatuz gero). configureWizard.transfer.connection=Linea configureWizard.transfer.connection.0=pertsonalizatua configureWizard.transfer.connection.1=modem-a configureWizard.transfer.connection.2=adsl/xxx kablea/128 kbps configureWizard.transfer.connection.3=adsl/xxx kablea/256 kbps configureWizard.transfer.connection.4=adsl/xxx kablea/384 kbps configureWizard.transfer.connection.5=adsl/xxx kablea/512 kbps configureWizard.transfer.connection.6=adsl/xxx kablea/768 kbps configureWizard.transfer.connection.7=adsl/xxx kablea/1024 kbps configureWizard.transfer.maxUpSpeed=Karga-abiadura maximoa (KB/s) configureWizard.transfer.maxActiveTorrents=Torrent aktiboen maximoa configureWizard.transfer.maxDownloads=Deskarga-kopuru maximoa configureWizard.transfer.maxUploadsPerTorrent=Karga-kopuru maximoa torrent bakoitzeko configureWizard.nat.title=NAT / Zerbitzari-ataka configureWizard.nat.message=Vuze-k eman dezakeen onena eskuratzeko, biziki aholkatzen da Internetetik erabat atzigarria izatea. Tresna honek sarrerako pare-konexioak onartzeko erabilitako ataka probatzen eta/edo aldatzen laguntzen du.\n\nOHARRA: Tresna honek TCP konexioak probatzen ditu soilik. DB banatuak sarrerako UDP konexioak ere behar ditu, baina automatikoki jakinaraziko dizu suebaki blokeatzailea aurkitzen badu.\n\nOHARRA: 6880 TCP ataka barne-funtzioetarako erreserbatuta dago eta, beraz, ezin da erabili. configureWizard.nat.test=Probatu configureWizard.nat.testing=Ataka probatzen: configureWizard.nat.ko=NAT errorea configureWizard.nat.unable=Ezin izan da proba egin: Okerreko ataka eman da, edo probarako zerbitzuak huts egin du.\nAgian beste aplikazio bat ataka hau erabiltzen ari da. configureWizard.file.title=Torrent-ak / Fitxategiak configureWizard.file.message1=Vuze-k irekitako torrent-ak karpeta batean gordeko dira, karpeta hori hemen adierazi dezakezu: configureWizard.file.path=Bidea configureWizard.file.browse=Arakatu configureWizard.file.message2=Vuze-k berehala berrabiarazi ditzake zure fitxategiak, zure torrent-ei berrabiaratze-datuak eransten badizkiozu. Ezaugarri hau erabiliz, partzialki deskargatutako atalak ere berrabiaraziko dituzu. configureWizard.file.fastResume=Gaitu berrabiaratze azkarra configureWizard.file.invalidPath=Direktorio baliogabea configureWizard.finish.title=Osatua configureWizard.finish.message=Orain Vuze konfiguratuta dago, ondo pasa ! wizard.close.confirmation=Baieztapena wizard.close.message=Nahi al duzu morroi hau karga dadin Vuze abiatzen den hurrengoan? exportTorrentWizard.title=Esportatu XML torrent-a exportTorrentWizard.torrentfile.title=Sarrerako torrent-aren hautapena exportTorrentWizard.torrentfile.message=Hautatu esportatuko den torrent fitxategia exportTorrentWizard.torrentfile.path=Bidea exportTorrentWizard.torrentfile.browse=Arakatu exportTorrentWizard.torrentfile.invalidPath=Torrent fitxategi baliogabea exportTorrentWizard.exportfile.title=Hautatu esportatuko den fitxategia exportTorrentWizard.exportfile.message=Sartu esportazioko xml fitxategia exportTorrentWizard.exportfile.path=Bidea exportTorrentWizard.exportfile.browse=Arakatu exportTorrentWizard.exportfile.invalidPath=Esportazio-fitxategi baliogabea exportTorrentWizard.finish.title=Osatua exportTorrentWizard.finish.message=Esportazioa arrakastaz burutu da exportTorrentWizard.process.inputfilebad.title=Torrent fitxategi baliogabea exportTorrentWizard.process.inputfilebad.message=Hutsegitea gertatu da hurrengo sarrera-fitxategia atzitzean: exportTorrentWizard.process.outputfileexists.title=Fitxategia existitzen da exportTorrentWizard.process.outputfileexists.message=Irteerako fitxategia existitzen da - gainidatzi? exportTorrentWizard.process.torrentfail.title=Torrent-aren irakurketak huts egin du exportTorrentWizard.process.exportfail.title=Torrent-aren esportazioak huts egin du exportTorrentWizard.process.unknownfail.title=Ustekabeko hutsegitea importTorrentWizard.title=Inportatu XML torrent-a importTorrentWizard.torrentfile.title=Sarrerako torrent-aren hautapena importTorrentWizard.torrentfile.message=Adierazi inportatu nahi den torrent fitxategia importTorrentWizard.torrentfile.path=Bidea importTorrentWizard.torrentfile.browse=Arakatu importTorrentWizard.torrentfile.invalidPath=Torrent fitxategi baliogabea importTorrentWizard.importfile.title=Inportatuko den fitxategiaren hautapena importTorrentWizard.importfile.message=Hautatu inportatuko den xml fitxategia importTorrentWizard.importfile.path=Bidea importTorrentWizard.importfile.browse=Arakatu importTorrentWizard.importfile.invalidPath=Inportazio fitxategi baliogabea importTorrentWizard.finish.title=Osatua importTorrentWizard.finish.message=Inportazioa arrakastaz burutu da importTorrentWizard.process.inputfilebad.title=Inportazio fitxategi baliogabea importTorrentWizard.process.inputfilebad.message=Hutsegitea gertatu da hurrengo sarrera-fitxategia atzitzean: importTorrentWizard.process.outputfileexists.title=Fitxategia existitzen da importTorrentWizard.process.outputfileexists.message=Irteerako fitxategia existitzen da - gainidatzi? importTorrentWizard.process.torrentfail.title=Torrent-aren idazketak huts egin du importTorrentWizard.process.importfail.title=Torrent-aren inportazioak huts egin du importTorrentWizard.process.unknownfail.title=Ustekabeko hutsegitea ConfigView.label.bindip=Lotu IP helbide edo interfaze lokalera ConfigView.label.xfs.allocation=Esleitu fitxategi berriak XFS fitxategi-sisteman espezifikoa den metodo bat erabiliz ConfigView.label.xfs.allocation.tooltip=Segurtatu /usr/sbin/xfs_io zure sisteman ongi instalatuta dagoela. Linux banaketa gehienetan "xfsprogs" paketean dago. xfs.allocation.xfs_io.not.found=XFS fitxategiaren esleipenak huts egin du ezin izan delako /usr/sbin/xfs_io exekutatu. Segurtatu zure sisteman ongi instalatuta dagoela. Jatorrizko errorea hau izan da: "%1". ConfigView.label.zeronewfiles=Esleitu eta hasieratu fitxategi berriak, haiek sortzen direnean ConfigView.label.zeronewfiles.tooltip=Zatikatzea txikitzen du ConfigView.section.stats=Estatistikak ConfigView.section.stats.enable=Gaitu ConfigView.section.stats.defaultsavepath=Estatistikak gordetzeko direktorioa ConfigView.section.stats.choosedefaultsavepath=Hautatu estatistikak gordetzeko direktorioa ConfigView.section.stats.savefreq=Gordetze-maiztasuna ConfigView.section.stats.minutes= minutu ConfigView.section.stats.hours= ordu ConfigView.section.stats.seconds= segundo ConfigView.section.stats.savefile=Estatistiken fitxategi-izena ConfigView.section.stats.graph_update_dividers=Erakutsi linea bertikala 60 eguneraketen multzoetarako MyTorrentsView.menu.export=&XML torrent-a... MyTorrentsView.menu.host=&Ostalaria... ManagerItem.finishing=Amaitzen ConfigView.dialog.choosedefaulttorrentpath=Hautatu torrent direktorio lehenetsia ConfigView.dialog.choosemovepath=Hautatu zein direktoriora mugituko den ConfigView.label.movecompleted=Mugitu osatutako fitxategiak (deskargatu ondoren) ConfigView.label.moveremoved=Mugitu osatutako fitxategiak (ezabatzerakoan) ConfigView.label.savetorrents=Gorde .torrent fitxategiak MainWindow.menu.view.mytracker=Nire a&ztarnaria MyTrackerView.title.full=Nire aztarnaria MyTrackerView.name=Izena MyTrackerView.tracker=Aztarnaria MyTrackerView.status=Egoera MyTrackerView.status.started=Abian MyTrackerView.status.stopped=Geldituta MyTrackerView.peers=Pareak MyTrackerView.seeds=Aleak MyTrackerView.announces=Iragarkiak MyTrackerView.uploaded=Kargatua MyTrackerView.downloaded=Deskargatua MyTrackerView.left=Ezkerra ConfigView.section.style=Interfazea ConfigView.label.set_ui_transfer_speeds=Gainidatzi transferentzia-abiadura hautagarriak ConfigView.label.set_ui_transfer_speeds.description=Eskuz defini ditzakezu sistemaren erretiluko egoera-barran eskuragarri egongo diren karga- eta deskarga-abiadura lehenetsiak.\nBalioak komaz bananduak idatzi behar dira. ConfigView.label.set_ui_transfer_speeds.description.download=Ezarri deskarga-abiadurak (KB/s-tan) ConfigView.label.set_ui_transfer_speeds.description.upload=Ezarri karga-abiadurak (KB/s-tan) ConfigView.section.style.useCustomTabs=Erabili itxi daitezkeen etiketak (beharrezkoa da berrabiaraztea) MainWindow.menu.view.plugins=&Plugin-ak fileDownloadWindow.saveTorrentIn=Gorde torrent fitxategia hemen: fileDownloadWindow.title=Vuze - Torrent deskargatzailea fileDownloadWindow.downloading=Deskargatzen hemendik: fileDownloadWindow.status=Egoera: fileDownloadWindow.state_initializing=Hasieratzen fileDownloadWindow.state_downloading=Deskargatzen fileDownloadWindow.state_error=Errorea: MainWindow.menu.file.open.url=&Kokalekua... openUrl.title=Ireki kokalekua openUrl.url=URLa: MyTorrentsView.menu.host.error.title=Torrent-aren ostatatzeak huts egin du MyTorrentsView.menu.host.error.message=Torrent-a ostatatzean hurrengo akatsa gertatu da ConfigView.section.tracker=Aztarnaria ConfigView.section.tracker.pollinterval=Aztarnariaren bezeroa zenbatero zundatuko den (segundoak) ConfigView.section.tracker.publishenable=Argitaratu torrent-aren xehetasunak ""-era ConfigView.section.tracker.ip=Aztarnariaren kanpoko IP helbidea ConfigView.section.style.enableXPStyle=Gaitu XP estiloa (beharrezkoa da berrabiaraztea) IPChecker.external.service.dyndns.description=DNS Dinamikoko Sare Zerbitzuak, LLC ConfigView.section.tracker.checkip=Automatikoki aurkitu kanpoko IP helbidea... ipCheckerWizard.title=IPa egiaztatzeko morroia ipCheckerWizard.service=Zerbitzua ipCheckerWizard.chooseService=Hautatu IPa egiaztatzeko zerbitzu bat zerrendatutako zerbitzuetatik ipCheckerWizard.explanations=Zure kanpoko IP helbidea zein den aurkitzeko erabil dezakezu morroi hau. Zure IP helbidea dinamikoa bada, DNS Zerbitzu Dinamiko batekin kontua irekitzea aholkatzen dizugu. Beheko zerrendan zerbitzu horietako zenbait ematen ditugu, erabili estekak kontu bat sortzeko (onartuta dagoen lekuetan). Ondoren, bete IP helbidearen eremua zure ostatatze-izen dinamikoarekin (adib. nireizena.dyndns.org). Aplikazio bat beharko duzu zure DNS Zerbitzu Dinamikoa automatikoki eguneratzeko zure IP helbidearekin. Horrela, torrent-ak ostatatu ahal izango dituzu zure IPa aldakorra izan arren. ipCheckerWizard.service.description=Deskribapena: ipCheckerWizard.service.url=Esteka: ipCheckerWizard.progresstitle=IPa egiaztatzen ipCheckerWizard.checkComplete=IP osatua: ipCheckerWizard.checkFailed=Huts egin du, arrazoia: wizard.tracker.local=Erabili Vuze-k kapsulatuta daraman aztarnaria wizard.tracker.external=Erabili kanpoko aztarnaria wizard.tracker.howToLocal=Joan 'Tresnak->Aukerak->Aztarnaria' aukerara aztarnaria gaitzeko wizard.announceUrl=Iragarpen URLa: IPChecker.external.service.discoveryvip.description=Discoveryvip - IP helbidearen egiaztatzea soilik IPChecker.external.httpinvalidresponse=HTTP erantzun baliogabea IPChecker.external.loadingwebpage=Web orria kargatzen IPChecker.external.analysingresponse=Erantzuna aztertzen IPChecker.external.addressextracted=Erauzitako IP helbidea IPChecker.external.httploadfail=Orria kargatzeak huts egin du IPChecker.external.timeout=Denboraz kanpo geratu da IPChecker.external.ipnotfound=IP helbidea ez da aurkitu ConfigView.section.tracker.pollintervalmin=Minimoa ConfigView.section.tracker.pollintervalmax=Maximoa ConfigView.section.tracker.pollintervalincby=Handitu honenbeste: ConfigView.section.tracker.pollintervalincper='n' bezeroko splash.loadingImages=Irudiak kargatzen splash.initializeGui=Leiho nagusia hasieratzen splash.openViews=Bistak irekitzen splash.plugin=Plugin-a kargatzen: configureWizard.nat.tooManyPorts=Aztertzeko portu gehiegi (9 gehienez) ConfigView.section.color=Kolore-eskema MyTorrentsView.menu.publish=Ar&gitaratu... MyTrackerView.status.published=Argitaratua MyTrackerView.completed=Osatua MainWindow.menu.file.open.torrentnodefault=Torrent fitxategia... (ez gorde lehenetsi gisa) wizard.comment=Iruzkina ConfigView.label.movetorrent=Mugitu .torrent-a ConfigView.label.movepartialdownloads=Mugitu fitxategi batzuk "Ez deskargatu" bandera eduki arren ConfigView.label.subdir_is_in_default=Deskargak direktorio lehenetsi batean existitzen ote diren aztertzean, aztertu azpidirektorioak ere. ConfigView.section.file.decoder.label=Torrent kodifikazio lehenetsia hautaketak hala eskatzen duenean ConfigView.section.file.decoder.nodecoder=Bat ere ez IPChecker.external.service.no-ip.description=DNS zerbitzu dinamiko eta estatikoen hornitzailea (ez dauka 'egiaztatu helbidea' zerbitzu librerik) ConfigView.section.tracker.publicenable=Gaitu kanpoko torrent-ak ConfigView.label.playdownloadspeech=Hitz egin deskarga amaitutakoan ConfigView.label.playdownloadspeech.info=Hizketa-zerbitzuak hobeto dabiltza ingelesez # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Bistaratu atal bakoitzaren kopia eskuragarrien kopurua.\nEskuineko zenbakia 1 baino txikiagoa bada, ez zaude ikusten fitxategiaren kopia oso bat (eta arazoak egon daitezke deskarga burutzeko). GeneralView.label.trackerurl.tooltip=Egin klik iragarpen URLa arbelera kopiatzeko GeneralView.label.trackerurlopen.tooltip=Egin klik aztarnariaren orri nagusia irekitzeko # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Eguneratu EIa honenbestero: ConfigView.section.style.inactiveUpdate=Eguneratu leiho nagusia EIaren N eguneratzetik behin, leiho aktiboa ez denean ConfigView.section.style.graphicsUpdate=Eguneratu barra grafikoak EIaren N eguneratzetik behin ConfigView.section.style.reOrderDelay=Berrantolatu taulak EIaren N eguneratzetik behin [0: inoiz ez] ConfigView.section.style.reOrderDelay.never=Inoiz ConfigView.section.logging=Egunkaria ConfigView.section.logging.enable=Gaitu egunkaria fitxategira idaztea ConfigView.section.logging.logdir=Egunkari-fitxategiaren direktorioa ConfigView.section.logging.choosedefaultsavepath=Hautatu gordetze-direktorioa GeneralView.label.updatein.querying=Kontsultatzen... configureWizard.nat.sharePort=Erabili sarrerako ataka partekatu bakarra torrent guztientzako ConfigView.section.logging.maxsize=Egunkari-fitxategiaren tamaina maximoa ConfigView.section.tracker.passwordenableweb=Gaitu pasahitza aztarnariaren webean ConfigView.section.tracker.passwordenabletorrent=Gaitu pasahitza torrent-etan ConfigView.section.tracker.username=Erabiltzaile-izena ConfigView.section.tracker.password=Pasahitza columnChooser.title=Hautatu bistaratuko diren zutabeak columnChooser.move=Arrastatu errenkadak haiek berrantolatzeko columnChooser.apply=Aplikatu columnChooser.columnname=Zutabe-izena columnChooser.columndescription=Deskribapena TableColumn.header.shareRatio=Partekatze-tasa MyTorrentsView.menu.editTableColumns=&Zutabearen konfigurazioa wizard.operationfailed=Eragiketak huts egin du authenticator.title=Autentifikazioa beharrekoa da authenticator.realm=Erreinua authenticator.tracker=Aztarnaria authenticator.user=Erabiltzaile-izena authenticator.password=Pasahitza ConfigView.label.allowSendVersion=Utzi Vuze-ri bertsio-zenbakia eta ausazko id anonimoak bidaltzen bertsio berriaren bila ari denean ConfigView.label.version.info.link=Bisitatu hau bertsioak egiaztatzen dituen zerbitzarira bidaltzen diren datuen xehetasunak ezagutzeko wizard.hint.mode=Aholkua:\tFitxategi bat edo direktorio bat arrastatu eta jaregin dezakezu\nmorroi honetan fitxategia edo direktorioa hautatzeko wizard.hint.file=Aholkua:\tArrastatu eta jareginez hauta dezakezu fitxategia wizard.hint.directory=Aholkua:\tArrastatu eta jareginez hauta dezakezu direktorioa MainWindow.menu.help.checkupdate=&Bilatu eguneraketak... TableColumn.header.down=Deskargatua TableColumn.header.up=Kargatua ConfigView.section.tracker.passwordenabletorrent.info=BitTorrent bezero egokia (esaterako Vuze) behar da ConfigView.section.style.confirmationOnExit=Erakutsi berrespen-leihoa irtetean MainWindow.dialog.exitconfirmation.title=Irten Vuze-tik MainWindow.dialog.exitconfirmation.text=Benetan irten nahi duzu Vuze-tik? SystemTray.menu.stopalltransfers=Gelditu transferentzia &guztiak TrayWindow.menu.stopalldownloads=Gelditu deskarga &guztiak ConfigView.section.tracker.sslport.info=Begiratu MEGak informazio gehiago jasotzeko wizard.tracker.ssl=Erabili SSL ConfigView.label.playdownloadfinished=Erreproduzitu soinu bat deskarga burutzen denean ConfigView.label.popupdownloadfinished=Erakutsi alerta-leihoa deskarga burutzen denean ConfigView.label.popupfilefinished=Erakutsi alerta-leihoa fitxategia amaituta dagoenean TableColumn.header.pieces=Atalak TableColumn.header.pieces.info=Deskargatu dituzun atalak ordezkatzen dituen barra grafikoa TableColumn.header.completion=Osaketa TableColumn.header.completion.info=Deskargatutako ehunekoa ordezkatzen duen grafikoa ConfigView.section.style.showdownloadbasket=Erakutsi deskarga-saskia (arrastatu eta jaregin .torrent-ak) ConfigView.section.style.alwaysShowTorrentFiles=Erakutsi beti torrent fitxategiak Xehetasunk/Fitxategiak atalean wizard.multitracker=Gehitu multi-aztarnari informazioa torrent-ari wizard.multitracker.title=Multi-aztarnaria wizard.multitracker.configuration=Multi-aztarnariaren konfigurazioa wizard.multitracker.new=Berria... wizard.multitracker.edit=Editatu... wizard.multitracker.delete=Ezabatu wizard.multitracker.group=Aztarnari-taldea wizard.multitracker.edit.title=Multi-aztarnariaren editorea wizard.multitracker.edit.name=Izena wizard.multitracker.edit.save=Gorde wizard.multitracker.edit.newgroup=Talde berria wizard.multitracker.edit.deletegroup=Ezabatu wizard.multitracker.edit.newtracker=Aztarnari berria wizard.multitracker.edit.deletetracker=Ezabatu wizard.multitracker.edit.edit=Editatu wizard.addingmt=Multi-aztarnariaren informazioa gehitzen wizard.multitracker.noannounce=Zure aztarnarien zerrendan ez dago iragarpen URLrik MyTorrentsView.menu.recheck=&Behartu berregiaztapena iconBar.showDownloadBar.tooltip=Erakutsi deskarga-barra iconBar.start.tooltip=Hasi hautatutako torrent-ak iconBar.stop.tooltip=Gelditu hautatutako torrent-ak iconBar.remove.tooltip=Kendu hautatutako torrent-ak iconBar.openNoDefault.tooltip=Ireki .torrent fitxategia (ez gorde lehenetsi gisa) iconBar.openURL.tooltip=Ireki URLa iconBar.openFolder.tooltip=Ireki karpeta iconBar.new.tooltip=Sortu torrent-a iconBar.up.tooltip=Mugitu gora iconBar.down.tooltip=Mugitu behera iconBar.run.tooltip=Ireki aplikazio lehenetsia erabiliz iconBar.host.tooltip=Ostalaria iconBar.publish.tooltip=Argitaratu iconBar.editcolumns.tooltip=Zutabearen konfigurazioa MyTorrentsView.menu.editTracker=&Editatu aztarnarien URLak GeneralView.menu.selectTracker=Hautatu ConfigView.section.stats.xslfile=XSL fitxategiaren izena ConfigView.section.stats.xslfiledetails=Hau estatistiken fitxategiaren goiburuan sartuko da etiketa erabiliz ConfigView.label.savetorrentbackup=Gorde babeskopia ConfigView.section.tracker.forceport=Behartu kanpoan ostatatutako torrent-ek lehenetsitako ataka erabil dezaten ConfigView.section.ipfilter.allow=ONARTU barruti hauek (balio lehenetsia UKATZEA da) ConfigView.section.ipfilter.list.inrange=barrutian zegoen ConfigView.section.ipfilter.list.notinrange=ez zegoen inolako barrutitan ConfigView.section.ipfilter.list.title=Blokeatutako IPak ConfigView.label.allowsameip=Onartu konexio anitz IP beretik ConfigView.label.allowsameip.tooltip=Markatu BEHAR baduzu soilik.\nHau izainen aurkako babesa da (desgaituta dagoenean). ManagerItem.superseeding=Super-aletzen ConfigView.label.userSuperSeeding=Erabili super-aletzea PeersView.uniquepiece=Atala (super-aletze modua) PeersView.uniquepiece.none=Bat ere ez PeersView.timetosend=Atala birbidaltzeko denbora (super-aletze modua) ConfigView.section.style.addurlsilently=Ireki pasatutako URLak modu isilean ConfigView.section.style.addurlsilently.tooltip=Deskargatu automatikoki pasatutako/jaregindako .torrent-en URLak galdetze-koadroa ireki gabe. ConfigView.section.file.decoder.prompt=Galdetu beti kodeketa-aukera eskuragarri dagoenean ConfigView.section.file.decoder.prompt.tooltip=Erakutsi beti elkarrizketa-koadroa kodeketa-aukera eskuragarri dagoenean MyTorrentsView.menu.moveTop=&Goia MyTorrentsView.menu.moveEnd=&Behea ConfigView.label.moveonlyusingdefaultsave=soilik datuen direktorio lehenetsian ConfigView.label.moveonlyusingdefaultsave.tooltip=Mugitu soilik datu deskargatuak datuen direktorio lehenetsian daudenean ConfigView.label.watchtorrentfolder=Inportatu .torrent berriak automatikoki ConfigView.label.watchtorrentfolder.tooltip=Bilatu .torrent berriak aldizka ConfigView.label.watchtorrentfolderinterval=Tartea ConfigView.label.watchtorrentfolderinterval.tooltip=Karpeta berriro eskaneatu arteko pausaldia ConfigView.dialog.choosewatchtorrentfolderpath=Hautatu .torrent-en inportazio-direktorioa ConfigView.label.startwatchedtorrentsstopped=Abiatu geldituta ConfigView.label.startwatchedtorrentsstopped.tooltip=Gehitu .torrent berria GELDITUTA egoeran ConfigView.section.plugins=Plugin-ak wizard.maketorrent.filesize=Fitxategien tamaina wizard.maketorrent.piececount=Atal-kopurua wizard.maketorrent.piecesize=Atalen tamaina MainWindow.menu.view.stats=&Estatistikak SpeedView.title.full=Jarduera SpeedView.downloadSpeed.title=Deskarga-abiadura SpeedView.uploadSpeed.title=Karga-abiadura ConfigView.section.style.useSIUnits=Erabili IEC unitateak (KB -> KiB, etab.) iconBar.top.tooltip=Mugitu lehen postura iconBar.bottom.tooltip=Mugitu azken postura TableColumn.header.health=Osasuna MyTorrentsView.menu.health=Osasunari buruz health.explain.grey=esan nahi du zure torrent-a ez dabilela (ez deskargatzen ez kargatzen) health.explain.red=esan nahi du ez zaudela inolako paretara konektaturik deskargan zehar health.explain.blue=aletzean, esan nahi du ez zaudela inolako paretara konektaturik\ndeskargatzean, esan nahi du zenbait paretara konektaturik zaudela, baina aztarnaria bertan behera dagoela health.explain.yellow=esan nahi du aztarnaria ongi dagoela, pareetara konektaturik zaudela, baina ez daukazula inolako urruneko konexiorik\nZure torrent-ak egoera horian badaude etengabe, agian NAT arazoa daukazu health.explain.green=esan nahi du dena ongi doala. ConfigView.section.style.alwaysRefreshMyTorrents=Freskatu 'Nire torrent-ak' beti ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Aukera honek 'Nire torrent-ak' bista freskatzen du nahiz eta begien bistan ez egon (erabilgarria zenbait mirc plugin-entzako) # #2.0.7.0 # security.certtruster.title=Segurtasun-ziurtagirien abisua security.certtruster.intro=Segurtasun-ziurtagiria fidagarritasunik onartu ez diozun konpainia batek jaulki du security.certtruster.resource=Baliabidea: security.certtruster.issuedto=Nori jaulkia: security.certtruster.issuedby=Nork jaulkia: security.certtruster.prompt=Fidagarritasuna onartu nah azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_ar_SA.properties0000644000175000017500000011523511301156004026063 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=\u0645\u0644\u0641 .torrent Main.parameter.usage=Usage : java org.gudy.azureus2.cl.Main [parameters] "file.torrent" "save path" Main.parameter.maxUploads=\u0627\u0644\u062d\u062f \u0627\u0644\u0623\u0642\u0635\u0649 \u0644\u0644\u0625\u0631\u0633\u0627\u0644 \u0627\u0644\u0645\u062a\u0648\u0627\u0641\u0642 Main.parameter.maxSpeed=\u0627\u0644\u062d\u062f \u0627\u0644\u0623\u0642\u0635\u0649 \u0644\u0633\u0631\u0639\u0629 \u0627\u0644\u0627\u0631\u0633\u0627\u0644 \u0628\u0627\u0644\u0640 \u0628\u0627\u064a\u062a/\u062b\u0627\u0646\u064a\u0629 MainWindow.menu.file=\u0645\u0644\u0641 MainWindow.menu.file.open=\u0641\u062a\u062d MainWindow.menu.file.create=Torrent \u0635\u064f\u0646\u0639 MainWindow.menu.file.create.fromfile=\u0645\u0646 \u0645\u0644\u0641 MainWindow.menu.file.create.fromdir=\u0645\u0646 \u0645\u062c\u0644\u062f MainWindow.menu.file.export=Torrent \u062a\u0635\u062f\u064a\u0631 \u0645\u0644\u0641... MainWindow.menu.file.import=Torrent \u0625\u0633\u062a\u064a\u0631\u0627\u062f \u0645\u0644\u0641... MainWindow.menu.file.exit=\u0627\u0644\u062e\u0631\u0648\u062c MainWindow.dialog.choose.file=torrent \u0627\u062e\u062a\u0631 \u0645\u0644\u0641 MainWindow.menu.file.folder=\u0645\u062c\u0644\u062f MainWindow.dialog.choose.folder=torrent \u0627\u062e\u062a\u0631 \u0627\u0644\u0645\u062c\u0644\u062f \u0627\u0644\u0630\u064a \u064a\u062d\u062a\u0648\u064a \u0639\u0644\u0649 \u0645\u0644\u0641\u0627\u062a MainWindow.menu.view=\u0639\u0631\u0636 MainWindow.menu.view.mytorrents=My Torrents MainWindow.menu.view.configuration=\u0627\u0644\u0625\u0639\u062f\u0627\u062f\u0627\u062a MainWindow.menu.view.console=Console MainWindow.menu.view.irc=\u0622\u064a \u0622\u0631 \u0633\u064a MainWindow.menu.closealldetails=\u0625\u063a\u0644\u0627\u0642 \u062c\u0645\u064a\u0639 \u0627\u0644\u062a\u0641\u0627\u0635\u064a\u0644 MainWindow.menu.closealldownloadbars=\u0625\u063a\u0644\u0627\u0642 \u062c\u0645\u064a\u0639 \u0623\u0634\u0631\u0637\u0629 \u0627\u0644\u062a\u0646\u0632\u064a\u0644 MainWindow.menu.language=\u0627\u0644\u0644\u063a\u0629 ConfigView.section.language=\u0627\u0644\u0644\u063a\u0629 MainWindow.menu.help=\u0645\u0633\u0627\u0639\u062f\u0629 MainWindow.menu.help.about=\u062d\u0648\u0644 \u0623\u0632\u0648\u0631\u064a\u0648\u0633 MainWindow.about.title=\u062d\u0648\u0644 MainWindow.about.section.developers=\u0627\u0644\u0645\u0635\u0646\u0651\u0639\u0648\u0646 MainWindow.about.section.translators=\u0627\u0644\u0645\u062a\u0631\u062c\u0645\u0648\u0646 MainWindow.about.section.internet=\u0627\u0646\u062a\u0631\u0646\u062a MainWindow.about.internet.homepage=\u0627\u0644\u0635\u0641\u062d\u0629 \u0627\u0644\u0631\u0626\u064a\u0633\u064a\u0629 \u0644\u0640 \u0622\u0632\u0648\u0631\u064a\u0648\u0633 MainWindow.about.internet.sourceforge=Sourceforge \u0635\u0641\u062d\u0629 \u0627\u0644\u0645\u0634\u0631\u0648\u0639 \u0641\u064a MainWindow.about.internet.sourceforgedownloads=Sourceforge \u062a\u062d\u0645\u064a\u0644 \u0628\u0631\u0627\u0645\u062c MainWindow.about.internet.bugreports=\u062a\u0642\u0627\u0631\u064a\u0631 \u0627\u0644\u0623\u062e\u0637\u0627\u0621 MainWindow.about.internet.forumdiscussion=\u0627\u0644\u0645\u0646\u062a\u062f\u0649 \u0627\u0644\u0639\u0627\u0645 MainWindow.dialog.choose.savepath=\u0627\u062e\u062a\u0631 \u0645\u0633\u0627\u0631 \u0627\u0644\u062a\u0633\u062c\u064a\u0644 MainWindow.dialog.choose.savepath_forallfiles=\u0627\u062e\u062a\u0631 \u0645\u0633\u0627\u0631 \u0627\u0644\u062a\u0633\u062c\u064a\u0644 \u0644\u062c\u0645\u064a\u0639 \u0627\u0644\u0645\u0644\u0641\u0627\u062a MainWindow.status.latestversion=\u0627\u0644\u0623\u062c\u062f\u062f MainWindow.status.latestversion.clickupdate=\u0627\u0636\u063a\u0637 \u0644\u062a\u062d\u062f\u064a\u062b \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c MainWindow.status.unknown=\u063a\u064a\u0631 \u0645\u0639\u0631\u0648\u0641 MainWindow.status.checking=\u062c\u0627\u0631\u064a \u0627\u0644\u0643\u0634\u0641 MyTorrentsView.mytorrents=My Torrents TableColumn.header.name=\u0627\u0644\u0627\u0633\u0645 TableColumn.header.size=\u0627\u0644\u062d\u062c\u0645 TableColumn.header.done=\u0644\u0642\u062f \u062a\u0645 TableColumn.header.status=\u0627\u0644\u062d\u0627\u0644\u0629 TableColumn.header.seeds=\u0627\u0644\u0628\u0630\u0648\u0631 TableColumn.header.peers=\u0627\u0644\u0646\u0638\u0627\u0626\u0631 TableColumn.header.downspeed=\u0633\u0631\u0639\u0629 \u0627\u0644\u062a\u0646\u0632\u064a\u0644 TableColumn.header.upspeed=\u0633\u0631\u0639\u0629 \u0627\u0644\u0627\u0631\u0633\u0627\u0644 TableColumn.header.eta=\u0627\u0644\u0645\u062a\u0628\u0642\u0651\u064a TableColumn.header.tracker=\u0627\u0644\u0645\u062a\u0642\u0641\u0651\u064a TableColumn.header.priority=\u0627\u0644\u0623\u0648\u0644\u0648\u064a\u0629 MyTorrentsView.menu.showdetails=\u0625\u0638\u0647\u0627\u0631 \u0627\u0644\u062a\u0641\u0627\u0635\u064a\u0644 MyTorrentsView.menu.showdownloadbar=\u0625\u0638\u0647\u0627\u0631 \u0634\u0631\u064a\u0637 \u0627\u0644\u062a\u0646\u0632\u064a\u0644 MyTorrentsView.menu.open=\u0641\u062a\u062d MyTorrentsView.menu.setpriority=\u0625\u0639\u062f\u0627\u062f \u0627\u0644\u0623\u0648\u0644\u0648\u064a\u0629 MyTorrentsView.menu.setpriority.high=\u0639\u0627\u0644\u064a MyTorrentsView.menu.setpriority.low=\u0645\u0646\u062e\u0641\u0636 MyTorrentsView.menu.start=\u062a\u0634\u063a\u064a\u0644 MyTorrentsView.menu.stop=\u0625\u064a\u0642\u0627\u0641 MyTorrentsView.menu.remove=\u0625\u0632\u0627\u0644\u0629 MyTorrentsView.menu.changeTracker=\u0625\u0636\u0627\u0641\u0629 URL \u0645\u062a\u0642\u0641\u064a TrayWindow.menu.exit=\u062e\u0631\u0648\u062c TrayWindow.menu.show=\u0625\u0638\u0647\u0627\u0631 \u0622\u0632\u0648\u0631\u064a\u0648\u0633 SystemTray.menu.exit=\u062e\u0631\u0648\u062c SystemTray.menu.closealldownloadbars=\u0625\u063a\u0644\u0627\u0642 \u062c\u0645\u064a\u0639 \u0623\u0634\u0631\u0637\u0629 \u0627\u0644\u062a\u0646\u0632\u064a\u0644 SystemTray.menu.show=\u0625\u0638\u0647\u0627\u0631 \u0622\u0632\u0648\u0631\u064a\u0648\u0633 PeersView.ip=\u0622\u064a \u0628\u064a PeersView.port=\u0645\u0646\u0641\u0630 PeersView.T=T PeersView.I1=I PeersView.C1=C PeersView.pieces=\u0627\u0644\u0623\u062c\u0632\u0627\u0621 PeersView.%=% PeersView.downloadspeed=\u0633\u0631\u0639\u0629 \u0627\u0644\u062a\u0646\u0632\u064a\u0644 PeersView.download=\u062a\u0646\u0632\u064a\u0644 PeersView.I2=I PeersView.C2=C PeersView.uploadspeed=\u0633\u0631\u0639\u0629 \u0627\u0644\u0625\u0631\u0633\u0627\u0644 PeersView.upload=\u0627\u0644\u0627\u0631\u0633\u0627\u0644 PeersView.statup=\u0633\u0631\u0639\u0629 \u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645 \u0627\u0644\u0645\u062a\u0628\u0642\u064a\u0629 PeersView.S=S PeersView.downloadspeedoverall=\u0633\u0631\u0639\u0629 \u0627\u0644\u062a\u0646\u0632\u064a\u0644 \u0643\u0643\u064f\u0644 PeersView.optunchoke=\u0627\u0633\u062a\u0626\u0646\u0627\u0641 \u0639\u0634\u0648\u0627\u0626\u064a PeersView.client=\u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c \u0627\u0644\u0645\u064f\u0633\u062a\u062e\u062f\u0645 PeersView.menu.snubbed=\u0645\u0631\u0641\u0648\u0636 PeersView.title.short=\u0627\u0644\u062a\u0641\u0627\u0635\u064a\u0644 PeersView.title.full=\u0627\u0644\u062a\u0641\u0627\u0635\u064a\u0644 ConfigView.section.files=\u0627\u0644\u0645\u0644\u0641\u0627\u062a ConfigView.label.usefastresume=\u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0646\u0645\u0637 \u0627\u0644\u0627\u0633\u062a\u0626\u0646\u0627\u0641 \u0627\u0644\u0633\u0631\u064a\u0639 ConfigView.label.incrementalfile=\u062a\u0645\u0643\u064a\u0646 \u0635\u0646\u0627\u0639\u0629 \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u062a\u0632\u0627\u064a\u062f\u064a ConfigView.label.defaultsavepath=\u0645\u0633\u0627\u0631 \u0627\u0644\u062d\u0641\u0638 \u0627\u0644\u0627\u0641\u062a\u0631\u0627\u0636\u064a ConfigView.button.browse=\u062a\u0635\u0641\u0651\u062d... ConfigView.dialog.choosedefaultsavepath=\u0627\u0644\u0631\u062c\u0627\u0621 \u0627\u062e\u062a\u064a\u0627\u0631 \u0645\u0633\u0627\u0631 \u0627\u0644\u062d\u0641\u0638 \u0627\u0644\u0627\u0641\u062a\u0631\u0627\u0636\u064a ConfigView.section.server=\u0627\u0644\u062e\u0627\u062f\u0645 ConfigView.section.global=\u0627\u0644\u0639\u0627\u0645 ConfigView.label.disconnetseed=\u0641\u0635\u0644 \u0627\u0644\u0628\u0630\u0648\u0631 \u0639\u0646\u062f \u0627\u0644\u0628\u0630\u0631 ConfigView.label.switchpriority=\u0627\u0644\u062a\u0628\u062f\u064a\u0644 \u0627\u0644\u062a\u0644\u0642\u0627\u0626\u064a \u0644\u0644\u0623\u0648\u0644\u0648\u064a\u0629 \u0627\u0644\u0623\u0642\u0644 \u0639\u0646\u062f \u0627\u0644\u0628\u0630\u0631 ConfigView.label.maxdownloads=\u0627\u0644\u062d\u062f \u0627\u0644\u0623\u0642\u0635\u0649 \u0627\u0644\u0645\u062a\u0648\u0627\u0641\u0642 \u0644\u0644\u062a\u0646\u0632\u064a\u0644 ConfigView.label.maxactivetorrents=\u0627\u0644\u062d\u062f \u0627\u0644\u0623\u0642\u0635\u0649 \u0644\u0640 torrents (0 : \u063a\u064a\u0631 \u0645\u062d\u062f\u0648\u062f)\n - torrents \u0627\u0644\u062c\u062f\u064a\u062f\u0629 \u0644\u0646 \u062a\u0628\u062f\u0623 \u0625\u0630\u0627 \u0643\u0646\u062a \u062a\u0646\u0632\u0651\u0644/\u062a\u064f\u0628\u0630\u0631 \u0623\u0643\u062b\u0631 ConfigView.label.priorityExtensions=\u0627\u0644\u062a\u0628\u062f\u064a\u0644 \u0627\u0644\u062a\u0644\u0642\u0627\u0626\u064a \u0644\u0644\u0623\u0648\u0644\u0648\u064a\u0629 \u0627\u0644\u0623\u0639\u0644\u0649 \u0644\u0644\u0645\u0644\u0641\u0627\u062a \u0630\u0627\u062a \u0627\u0645\u062a\u062f\u0627\u062f \u0645\u0639\u064a\u0646\n - \u0645\u062b\u0627\u0644: .txt;.nfo;.jpg ConfigView.section.transfer=\u0646\u0642\u0644 ConfigView.label.maxuploads=\u0627\u0644\u0639\u062f\u062f \u0627\u0644\u0627\u0641\u062a\u0631\u0627\u0636\u064a \u0644\u0644\u0625\u0631\u0633\u0627\u0644 \u0644\u0643\u0644 torrent ConfigView.label.maxuploadspeed=\u0627\u0644\u0633\u0631\u0639\u0629 \u0627\u0644\u0642\u0635\u0648\u0629 \u0644\u0644\u0625\u0631\u0633\u0627\u0644 (\u0627\u0644\u0645\u062c\u0645\u0648\u0639 \u0627\u0644\u0643\u0644\u0651\u064a) ConfigView.label.saveresumeinterval=\u062d\u0641\u0638 \u0628\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0627\u0633\u062a\u0626\u0646\u0627\u0641 \u0627\u0644\u0633\u0631\u064a\u0639 \u0643\u0644 ConfigView.unlimited=\u063a\u064a\u0631 \u0645\u062d\u062f\u0648\u062f ConfigView.section.display=\u0639\u0631\u0636 ConfigView.label.opendetails=\u0641\u062a\u062d \u062a\u0644\u0642\u0627\u0626\u064a \u0644\u0644\u062a\u0628\u0648\u064a\u0628 \u0627\u0644\u062a\u0641\u0627\u0635\u064a\u0644 ConfigView.label.openbar=\u0641\u062a\u062d \u062a\u0644\u0642\u0627\u0626\u064a \u0644\u0634\u0631\u064a\u0637 \u0627\u0644\u062a\u0646\u0632\u064a\u0644 ConfigView.label.closetotray=\u0627\u0644\u0625\u063a\u0644\u0627\u0642 \u064a\u0642\u0648\u0645 \u0628\u0627\u0644\u062a\u0635\u063a\u064a\u0631 \u0644\u0639\u0644\u0628\u0629 \u0627\u0644\u0646\u0638\u0627\u0645 ConfigView.label.minimizetotray=\u0627\u0644\u062a\u0635\u063a\u064a\u0631 \u064a\u0642\u0648\u0645 \u0628\u0627\u0644\u062a\u0635\u063a\u064a\u0631 \u0644\u0639\u0644\u0628\u0629 \u0627\u0644\u0646\u0638\u0627\u0645 ConfigView.section.general=\u0627\u0644\u0639\u0627\u0645 ConfigView.section.start=\u0627\u0644\u0628\u062f\u0621 ConfigView.label.showsplash=\u0625\u0638\u0647\u0627\u0631 \u0634\u0627\u0634\u0629 \u0628\u062f\u0621 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c ConfigView.label.autoupdate=\u0641\u062a\u062d \u0645\u0631\u0628\u0639 \u062d\u0648\u0627\u0631 \u0627\u0644\u062a\u062d\u062f\u064a\u062b \u0639\u0646\u062f \u0635\u062f\u0648\u0631 \u0646\u0633\u062e\u0629 \u062c\u062f\u064a\u062f\u0629 ConfigView.label.openconsole=\u0641\u062a\u062d console \u0639\u0646\u062f \u0628\u062f\u0621 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c ConfigView.label.openconfig=\u0641\u062a\u062d \u0627\u0644\u0625\u0639\u062f\u0627\u062f\u0627\u062a \u0639\u0646\u062f \u0628\u062f\u0621 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c ConfigView.label.startminimized=\u0627\u0644\u0628\u062f\u0621 \u0645\u0635\u063a\u0631\u064b\u0627 ConfigView.section.irc=\u0622\u064a \u0622\u0631 \u0633\u064a ConfigView.label.ircserver=\u0627\u0644\u062e\u0627\u062f\u0645 ConfigView.label.ircchannel=\u0627\u0644\u0642\u0646\u0627\u0629 ConfigView.label.irclogin=\u0627\u0644\u0644\u0642\u0628 ( \u0627\u0644\u0646\u0643 \u0646\u064a\u0645 ) ConfigView.section.security=\u0627\u0644\u0623\u0645\u0627\u0646 ConfigView.label.password=\u062d\u0645\u0627\u064a\u0629 \u0623\u0632\u0648\u0631\u064a\u0648\u0633 \u0628\u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0643\u0644\u0645\u0629 \u0633\u0631\n - \u0633\u062a\u064f\u0633\u0623\u0644 \u0639\u0646\u0647\u0627 \u0639\u0646\u062f \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c \u0645\u0646 \u0639\u0644\u0628\u0629 \u0627\u0644\u0646\u0638\u0627\u0645 \u0648 \u0639\u0646\u062f \u0628\u062f\u0621 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c. ConfigView.label.passwordconfirm=\u0627\u0644\u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631\u064a\u0629 (\u062a\u0623\u0643\u064a\u062f) ConfigView.label.passwordmatch=\u0646\u0634\u0627\u0637 \u0627\u0644\u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631\u064a\u0629 : ConfigView.label.passwordmatchnone=\u0644\u0627 ConfigView.label.passwordmatchno=\u0644\u0627 / \u0627\u0644\u0643\u0644\u0645\u0627\u062a \u0627\u0644\u0633\u0631\u064a\u0629 \u063a\u064a\u0631 \u0645\u062a\u0637\u0627\u0628\u0642\u0629 ConfigView.label.passwordmatchyes=\u0646\u0639\u0645 ConfigView.button.save=\u062d\u0641\u0638 ConfigView.title.short=\u0625\u0639\u062f\u0627\u062f\u0627\u062a ConfigView.title.full=\u0625\u0639\u062f\u0627\u062f\u0627\u062a ConsoleView.title.short=Console ConsoleView.title.full=Console FileItem.write=\u0643\u062a\u0627\u0628\u0629 FileItem.read=\u0642\u0631\u0627\u0621\u0629 FileItem.normal=\u0639\u0627\u062f\u064a FileItem.high=\u0639\u0627\u0644\u064a FileItem.donotdownload=\u0644\u0627 \u062a\u0642\u0645 \u0628\u0627\u0644\u062a\u0646\u0632\u064a\u0644 FilesView.name=\u0627\u0644\u0627\u0633\u0645 FilesView.size=\u0627\u0644\u062d\u062c\u0645 FilesView.done=\u062a\u0645\u0651 FilesView.%=% FilesView.firstpiece=\u0627\u0644\u0642\u0637\u0639\u0629 \u0627\u0644\u0623\u0648\u0644\u0629 # FilesView.numberofpieces=# \u0645\u0646 \u0627\u0644\u0642\u0637\u0639 FilesView.pieces=\u0627\u0644\u0642\u0637\u0639 FilesView.mode=\u0627\u0644\u0637\u0648\u0631 FilesView.priority=\u0627\u0644\u0623\u0648\u0644\u0648\u064a\u0629 FilesView.menu.open=\u0641\u062a\u062d FilesView.menu.setpriority=\u0623\u0639\u062f\u0651 \u0627\u0644\u0623\u0648\u0644\u0648\u064a\u0629 FilesView.menu.setpriority.high=\u0639\u0627\u0644\u064a FilesView.menu.setpriority.normal=\u0639\u0627\u062f\u064a FilesView.menu.setpriority.skipped=\u0644\u0627 \u062a\u0642\u0645 \u0628\u0627\u0644\u062a\u0646\u0632\u064a\u0644 FilesView.title.short=\u0627\u0644\u0645\u0644\u0641\u0627\u062a FilesView.title.full=\u0627\u0644\u0645\u0644\u0641\u0627\u062a GeneralView.section.downloaded=\u062a\u0645 \u0627\u0644\u062a\u0646\u0632\u064a\u0644 GeneralView.label.status.file=\u062d\u0627\u0644\u0629 \u0627\u0644\u0645\u0644\u0641 GeneralView.label.status.pieces=\u062d\u0627\u0644\u0629 \u0627\u0644\u0642\u0637\u0639 GeneralView.section.availability=\u0627\u0644\u062a\u0648\u0641\u0651\u0631 GeneralView.label.status.pieces_available=\u062d\u0627\u0644\u0629 \u0627\u0644\u0642\u0637\u0639 GeneralView.section.transfer=\u0646\u0642\u0644 GeneralView.section.info=\u0645\u0639\u0644\u0648\u0645\u0627\u062a GeneralView.title.short=\u0627\u0644\u0639\u0627\u0645 GeneralView.title.full=\u0627\u0644\u0639\u0627\u0645 GeneralView.label.timeelapsed=\u0627\u0644\u0648\u0642\u062a \u0627\u0644\u0645\u062a\u0628\u0642\u064a : GeneralView.label.remaining=\u0627\u0644\u0645\u062a\u0628\u0642\u064a: GeneralView.label.downloaded=\u0627\u0644\u0645\u064f\u0646\u0632\u0651\u0644 : GeneralView.label.downloadspeed=\u0633\u0631\u0639\u0629 \u0627\u0644\u062a\u0646\u0632\u064a\u0644 : GeneralView.label.maxuploads=\u0627\u0644\u062d\u062f \u0627\u0644\u0623\u0642\u0635\u0649 \u0644\u0644\u0645\u0631\u0633\u0644\u0627\u062a : GeneralView.label.uploaded=\u0627\u0644\u0645\u064f\u0631\u0633\u064e\u0644 : GeneralView.label.uploadspeed=\u0633\u0631\u0639\u0629 \u0627\u0644\u0625\u0631\u0633\u0627\u0644 : GeneralView.label.seeds=\u0627\u0644\u0628\u0630\u0648\u0631 : GeneralView.label.peers=\u0627\u0644\u0646\u0638\u0627\u0626\u0631 : GeneralView.label.totalspeed=\u0627\u0644\u0633\u0631\u0639\u0629 \u0627\u0644\u0643\u0644\u0651\u064a\u0651\u0629 : GeneralView.label.filename=\u0627\u0644\u0627\u0633\u0645 : GeneralView.label.totalsize=\u0627\u0644\u062d\u062c\u0645 \u0627\u0644\u0643\u0644\u0651\u064a : GeneralView.label.savein=\u0627\u0644\u062d\u0641\u0638 \u0641\u064a : GeneralView.label.numberofpieces=# \u0645\u0646 \u0627\u0644\u0642\u0637\u0639 : GeneralView.label.size=\u0627\u0644\u062d\u062c\u0645 : GeneralView.label.tracker=\u0627\u0644\u0645\u062a\u0642\u0641\u0651\u064a : GeneralView.label.updatein=\u0627\u0644\u062a\u062d\u062f\u064a\u062b \u0641\u064a : GeneralView.label.trackerurl=\u0645\u0648\u0642\u0639 \u0627\u0644\u0645\u062a\u0642\u0641\u0651\u064a : GeneralView.label.trackerurlupdate=\u0627\u0644\u062a\u062d\u062f\u064a\u062b \u0627\u0644\u064a\u062f\u0648\u064a GeneralView.label.comment=\u0627\u0644\u062a\u0639\u0644\u064a\u0642 : ManagerItem.waiting=\u0625\u0646\u062a\u0638\u0627\u0631 ManagerItem.allocating=\u062c\u0627\u0631\u064a \u0627\u0644\u062a\u0648\u0632\u064a\u0639 ManagerItem.checking=\u062c\u0627\u0631\u064a \u0627\u0644\u0643\u0634\u0641 ManagerItem.ready=\u062c\u0627\u0647\u0632 ManagerItem.downloading=\u062c\u0627\u0631\u064a \u0627\u0644\u062a\u0646\u0632\u064a\u0644 ManagerItem.seeding=\u062c\u0627\u0631\u064a \u0627\u0644\u0628\u064e\u0630\u0631 ManagerItem.stopped=\u062a\u0648\u0642\u0651\u0641 ManagerItem.error=\u062e\u0637\u0623 ManagerItem.high=\u0639\u0627\u0644\u064a ManagerItem.low=\u0645\u0646\u062e\u0641\u0636 MinimizedWindow.name=\u0627\u0644\u0627\u0633\u0645: PiecesView.#=# PiecesView.size=\u0627\u0644\u062d\u062c\u0645 PiecesView.numberofblocks=# \u0645\u0646 \u0627\u0644\u0642\u0648\u0627\u0644\u0628 PiecesView.blocks=\u0627\u0644\u0642\u0648\u0627\u0644\u0628 PiecesView.completed=\u0623\u064f\u0646\u062c\u0632 PiecesView.availability=\u0627\u0644\u062a\u0648\u0641\u0651\u0631 PiecesView.title.short=\u0627\u0644\u0642\u0637\u0639 PiecesView.title.full=\u0627\u0644\u0642\u0637\u0639 SystemTray.tooltip.seeding=%1 \u062c\u0627\u0631\u064a \u0627\u0644\u0628\u0630\u0631, SystemTray.tooltip.downloading=%1 \u062c\u0627\u0631\u064a \u0627\u0644\u062a\u0646\u0632\u064a\u0644, DownloadManager.error.filenotfound=\u0644\u0645 \u064a\u062a\u0645 \u0627\u0644\u0639\u062b\u0648\u0631 \u0639\u0644\u0649 \u0627\u0644\u0645\u0644\u0641 DownloadManager.error.fileempty=\u0641\u0627\u0636\u064a Torrent \u0645\u0644\u0641 DownloadManager.error.filetoobig=\u0643\u0628\u064a\u0631 \u062c\u062f\u064b\u0627 Torrent \u0645\u0644\u0641 DownloadManager.error.filewithouttorrentinfo=\u0641\u064a \u0647\u0630\u0627 \u0627\u0644\u0645\u0644\u0641 Torrent \u0644\u0627 \u062a\u0648\u062c\u062f \u0645\u0639\u0644\u0648\u0645\u0627\u062a DownloadManager.error.unsupportedencoding=\u0627\u0644\u062a\u0634\u0641\u064a\u0631 \u063a\u064a\u0631 \u0645\u062f\u0639\u0648\u0645 DownloadManager.error.ioerror=IO \u062e\u0637\u0623 DownloadManager.error.sha1=\u062e\u0637\u0623 (SHA1) \u0644\u0627 \u064a\u0648\u062c\u062f \u0623\u064a \u062e\u0648\u0627\u0631\u0632\u0645 PeerManager.status.offline=\u063a\u064a\u0631 \u0645\u062a\u0651\u0635\u0644 PeerManager.status.ok=\u0623\u0648\u0643\u0649 PeerManager.status.checking=\u062c\u0627\u0631\u064a \u0627\u0644\u0643\u0634\u0641 PeerManager.status.finished=\u0644\u0642\u062f \u062a\u0645 PeerManager.status.finishedin=\u0644\u0642\u062f \u062a\u0645 \u0641\u064a MainWindow.upgrade.assistant=\u0645\u0633\u0627\u0639\u062f \u0627\u0644\u062a\u062d\u062f\u064a\u062b MainWindow.upgrade.newerversion=\u0647\u0646\u0627\u0643 \u0646\u0633\u062e\u0629 \u062c\u062f\u064a\u062f\u0629 \u0645\u0646 \u0623\u0632\u0648\u0631\u064a\u0648\u0633 \u062c\u0627\u0647\u0632\u0629 \u0644\u0644\u062a\u0646\u0632\u064a\u0644 MainWindow.upgrade.explanation=\u0647\u0630\u0627 \u0627\u0644\u0645\u0633\u0627\u0639\u062f \u0633\u064a\u0642\u0648\u0645 \u0628\u062a\u0646\u0632\u064a\u0644 \u0627\u0644\u0646\u0633\u062e\u0629 \u0627\u0644\u062c\u062f\u064a\u062f\u0629 \u0648 \u0648\u0636\u0639\u0647\u0627 \u0641\u064a \u0645\u062c\u0644\u062f \u0623\u0632\u0648\u0631\u064a\u0648\u0633 \u062b\u0645 \u0633\u064a\u0639\u064a\u062f \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c MainWindow.upgrade.explanation.manual=\u0628\u0625\u0645\u0643\u0627\u0646\u0643 \u0627\u0644\u062a\u062d\u062f\u064a\u062b \u064a\u062f\u0648\u064a\u064b\u0627 \u0628\u0625\u063a\u0644\u0627\u0642 \u0623\u0632\u0648\u0631\u064a\u0648\u0633 , \u0628\u062a\u0646\u0632\u064a\u0644 \u0627\u0644\u0646\u0633\u062e\u0629 \u0627\u0644\u062c\u062f\u064a\u062f\u0629 \u062b\u0645 \u0625\u0639\u0627\u062f\u0629 \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c. MainWindow.upgrade.step1=\u0627\u0644\u062e\u0637\u0648\u0629 1: \u062a\u0646\u0632\u064a\u0644 \u0627\u0644\u0646\u0633\u062e\u0629 \u0627\u0644\u062c\u062f\u064a\u062f\u0629 MainWindow.upgrade.step2=\u0627\u0644\u062e\u0637\u0648\u0629 2: \u0625\u063a\u0644\u0627\u0642 \u0647\u0630\u0647 \u0627\u0644\u0646\u0633\u062e\u0629 \u0648 \u0625\u0639\u0627\u062f\u0629 \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0646\u0633\u062d\u0629 \u0627\u0644\u062c\u062f\u064a\u062f\u0629 \u0645\u0646 \u0623\u0632\u0648\u0631\u064a\u0648\u0633 MainWindow.upgrade.hint1=\u062a\u0644\u0645\u064a\u062d:\t\u0627\u0644\u0636\u063a\u0637 \u0639\u0644\u0649 \u0625\u0646\u0647\u0627\u0621 \u0633\u064a\u0642\u0648\u0645 \u0628\u0639\u0645\u0644 \u0643\u0644 \u0634\u064a\u0621 \u062a\u0644\u0642\u064a\u0627\u0626\u064a\u064b\u0627 MainWindow.upgrade.hint2=\u062a\u0644\u0645\u064a\u062d:\t \u0625\u0630\u0627 \u0643\u0646\u062a \u062a\u0631\u064a\u062f \u0625\u063a\u0644\u0627\u0642 \u0623\u0632\u0648\u0631\u064a\u0648\u0633 \u0644\u0627\u062d\u0642\u064b\u0627, \u0627\u0636\u063a\u0637 \u0625\u0644\u063a\u0627\u0621 \u0627\u0644\u0623\u0645\u0631,\n\t\u0623\u0639\u062f \u062a\u0633\u0645\u064a\u0629 Azureus2-new.jar \u0625\u0644\u0649 Azureus2.jar \u0628\u0639\u062f \u0627\u0644\u0625\u063a\u0644\u0627\u0642 MainWindow.upgrade.error.downloading.hint=\u062e\u0637\u0623:\t\u0639\u0627\u062c\u0632 \u0639\u0646 \u062a\u0646\u0632\u064a\u0644 \u0627\u0644\u0646\u0633\u062e\u0629 \u0627\u0644\u062c\u062f\u064a\u062f\u0629, \u0627\u0644\u0631\u062c\u0627\u0621 \u0627\u0644\u062a\u062d\u062f\u064a\u062b \u064a\u062f\u0648\u064a\u064b\u0627 MainWindow.upgrade.section.info=\u0647\u0646\u0627\u0643 \u0646\u0633\u062e\u0629 \u062c\u062f\u064a\u062f\u0629 MainWindow.upgrade.section.manual=\u0627\u0644\u062a\u062d\u062f\u064a\u062b \u0627\u0644\u064a\u062f\u0648\u064a MainWindow.upgrade.section.automatic=\u0627\u0644\u062a\u062d\u062f\u064a\u062b \u0627\u0644\u062a\u0644\u0642\u0627\u0626\u064a MainWindow.upgrade.tooltip.progressbar=\u0627\u0633\u062a\u0645\u0631\u0627\u0631\u064a\u0629 \u0627\u0644\u062a\u0646\u0632\u064a\u0644 \u0645\u0648\u062c\u0648\u062f\u0629 \u0647\u0646\u0627 Button.next=\u0627\u0644\u062a\u0627\u0644\u064a Button.finish=\u0627\u0644\u0646\u0647\u0627\u064a\u0629 Button.cancel=\u0625\u0644\u063a\u0627\u0621 \u0627\u0644\u0623\u0645\u0631 LocaleUtil.title=\u0623\u062e\u062a\u0631 \u0627\u0644\u062a\u0631\u0645\u064a\u0632 LocaleUtil.section.chooseencoding=\u0627\u062e\u062a\u0631 \u0627\u0644\u062a\u0631\u0645\u064a\u0632 \u0644\u0627\u0633\u0645 \u0627\u0644\u0645\u0644\u0641 LocaleUtil.label.chooseencoding=\u0627\u0644\u0631\u062c\u0627\u0621 \u0627\u062e\u062a\u064a\u0627\u0631 \u0627\u0644\u062a\u0631\u0645\u064a\u0632 \u0627\u0644\u0645\u062a\u0648\u0627\u0641\u0642 \u062a\u0645\u0627\u0645\u064b\u0627 LocaleUtil.label.hint.doubleclick=\u062a\u0644\u0645\u064a\u062d: double-clicking on a row chooses encoding and closes the dialog LocaleUtil.label.checkbox.rememberdecision=Remember decision for remaining filenames LocaleUtil.column.encoding=Encoding IrcClient.copyright=Using the PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Connecting to IrcClient.connected=Connected to IrcClient.joining=Joining IrcClient.channel=Channel IrcClient.joined=joined IrcClient.error=Error IrcClient.hasjoined=has joined IrcClient.haskicked=has kicked IrcClient.hasleft=has left IrcClient.nowknown=is now known as IrcClient.topicforchannel=Topic for channel IrcClient.disconnected=Disconnected from IrcClient.noNick=No Nickname Specified. Please go to 'Configuration' View IrcView.actionnotsupported=This action isn't supported IrcView.clientsconnected=users IrcView.privateto=To IrcView.privatefrom=From IrcView.noticefrom=Notice : IrcView.errormsg=Wrong Syntax on /msg : /msg user text IrcView.help=Valid commands are :\n . /help : displays this message\n . /nick | /name : changes your name \n . /me action : sends an action \n . /msg nick message : sends a private message to \n . /r message : reply to last private message\n . /join #channel : changes current channel PasswordWindow.title=Vuze is locked Button.ok=Ok TrackerChangerWindow.title=Add Tracker TrackerChangerWindow.newtracker=Enter new tracker url PeersView.discarded=Discarded discarded=discarded MyTorrentsView.#=# MyTorrentsView.menu.move=Move MyTorrentsView.menu.moveUp=Up MyTorrentsView.menu.moveDown=Down ConfigView.section.downloadManagement=Download Management ConfigView.text.neverStop=Never Stop ConfigView.text.neverStart=Never Start ConfigView.text.peers=Peers ConfigView.label.checkOncompletion=Re-check pieces when download is done wizard.title=Make a torrent wizard.previous=< Back wizard.next=Next > wizard.finish=Finish wizard.mode=Tracker / Mode wizard.tracker=Tracker: wizard.invalidurl=This URL isn't valid wizard.singlefile=Single file wizard.singlefile.help=Create a torrent from a single file wizard.directory=Directory wizard.directory.help=Create a torrent from a directory wizard.choosefile=Choose the file wizard.file=File : wizard.browse=Browse... wizard.choosedirectory=Choose a directory wizard.invalidfile=Invalid File! wizard.invaliddirectory=Invalid Directory! wizard.torrentFile=Torrent File wizard.choosetorrent=Please choose the torrent file to create wizard.information=Information wizard.notimplemented=Not yet implemented wizard.progresstitle=Creating Torrent File wizard.savingfile=Saving File... wizard.filesaved=File saved. wizard.close=Close Torrent.create.progress.parsingfiles=Parsing files Torrent.create.progress.hashing=Hashing files MainWindow.menu.view.ipFilter=Ip Filters ConfigView.section.ipfilter=Ip Filters ConfigView.section.ipfilter.description=Description ConfigView.section.ipfilter.start=Start Ip ConfigView.section.ipfilter.end=End Ip ConfigView.section.ipfilter.add=Add ConfigView.section.ipfilter.remove=Remove ConfigView.section.ipfilter.edit=Edit ConfigView.section.ipfilter.save=Save ConfigView.section.ipfilter.editFilter=Edit Filter ConfigView.section.ipfilter.enable=Enable PeersView.menu.close=Close seedmore.title=Torrent is not seeded enough seedmore.uploadmore=Having a share ratio under 100% is not a good thing for the bittorrent network.\nYou should let this torrent seed a little bit more.\nAre you sure you want to proceed? ConfigView.label.showpopuponclose=Show confirmation popup when stopping seeding with a share ratio lower than 1 ConfigView.label.startNumSeeds=\nStart seeding if there is less than\n - Overrides all other rules ConfigView.label.seeds=seeds ConfigView.section.seeding=Seeding MyTorrentsView.menu.removeand=Remove and MyTorrentsView.menu.removeand.deletetorrent=Delete .torrent MyTorrentsView.menu.removeand.deletedata=Delete Data MyTorrentsView.menu.removeand.deleteboth=Delete Both deletedata.title=!!! Warning !!! deletedata.message1=You are about to delete the DATA from :\n MainWindow.menu.file.configure=Configuration Wizard configureWizard.title=Configuration Wizard configureWizard.welcome.title=Welcome to the Vuze Configuration Wizard configureWizard.welcome.message=This wizard will help you configure Vuze for most common use. You can modify in depth the configuration using the View>Configuration menu. configureWizard.transfer.title=Transfer and Connection setup configureWizard.transfer.hint=Hint : Using a little bit less than your line speed is the best setting. configureWizard.transfer.message=Please choose a connection below. Be aware that not allowing enough upload speed will result in slow download speeds. As upload speed only counts PER torrent you're downloading, trying to download too many torrents at the same time will also result in slow speeds. We recommend using 5kB/s per torrent as a STRICT minimum. The faster you upload, the faster you'll download (with respect to the torrent speed). configureWizard.transfer.connection=Line configureWizard.transfer.connection.0=Custom configureWizard.transfer.connection.1=modem/isdn configureWizard.transfer.connection.2=adsl/cable xxx/128 kbps configureWizard.transfer.connection.3=adsl/cable xxx/256 kbps configureWizard.transfer.connection.4=adsl/cable xxx/384 kbps configureWizard.transfer.maxUpSpeed=Max Up Speed (kB/s) configureWizard.transfer.maxActiveTorrents=Max Active configureWizard.transfer.maxDownloads=Max Downloads configureWizard.transfer.maxUploadsPerTorrent=Max Uploads per Torrent configureWizard.nat.title=NAT / Server Ports configureWizard.nat.message=In order to get the best out of BitTorrent, it's highly recommended to be fully accessible from the internet. Default bittorrent ports range from 6881 to 6889. This tool lets you test and / or change those default ports. If you have some active downloads, some ports may not be accessible. configureWizard.nat.test=Test configureWizard.nat.testing=Testing port configureWizard.nat.ok=Ok configureWizard.nat.ko=NAT Error configureWizard.nat.unable=Unable to test configureWizard.file.title=Torrents / Files configureWizard.file.message1=Vuze will save opened torrents in a specific folder, you can choose this folder here: configureWizard.file.path=Path configureWizard.file.browse=Browse configureWizard.file.message2=Vuze is able to resume your files instantly, by adding some resume data to your torrents. Using this feature, you'll also resume partially downloaded pieces. configureWizard.file.fastResume=Enable fast Resume configureWizard.file.invalidPath=Invalid directory configureWizard.finish.title=Completed configureWizard.finish.message=Vuze is now configured, have fun ! wizard.close.confirmation=Confirmation exportTorrentWizard.title=Export a torrent exportTorrentWizard.torrentfile.title=Input Torrent Selection exportTorrentWizard.torrentfile.message=Select the torrent file to export exportTorrentWizard.torrentfile.path=Path exportTorrentWizard.torrentfile.browse=Browse exportTorrentWizard.torrentfile.invalidPath=Invalid torrent file exportTorrentWizard.exportfile.title=Export File Selection exportTorrentWizard.exportfile.message=Enter the file to export to exportTorrentWizard.exportfile.path=Path exportTorrentWizard.exportfile.browse=Browse exportTorrentWizard.exportfile.invalidPath=Invalid export file exportTorrentWizard.finish.title=Completed exportTorrentWizard.finish.message=Export completed successfully exportTorrentWizard.process.inputfilebad.title=Torrent File Invalid exportTorrentWizard.process.inputfilebad.message=A failure occurred accessing the input file: exportTorrentWizard.process.outputfileexists.title=File Exists exportTorrentWizard.process.outputfileexists.message=Output file exists - overwrite? exportTorrentWizard.process.torrentfail.title=Torrent Read Fails exportTorrentWizard.process.exportfail.title=Torrent Export Fails exportTorrentWizard.process.unknownfail.title=Unexpected Error importTorrentWizard.title=Import a torrent importTorrentWizard.torrentfile.title=Input Torrent Selection importTorrentWizard.torrentfile.message=Enter the torrent file to import into importTorrentWizard.torrentfile.path=Path importTorrentWizard.torrentfile.browse=Browse importTorrentWizard.torrentfile.invalidPath=Invalid torrent file importTorrentWizard.importfile.title=Import File Selection importTorrentWizard.importfile.message=Select the file to import importTorrentWizard.importfile.path=Path importTorrentWizard.importfile.browse=Browse importTorrentWizard.importfile.invalidPath=Invalid import file importTorrentWizard.finish.title=Completed importTorrentWizard.finish.message=Import completed successfully importTorrentWizard.process.inputfilebad.title=Import File Invalid importTorrentWizard.process.inputfilebad.message=A failure occurred accessing the input file: importTorrentWizard.process.outputfileexists.title=File Exists importTorrentWizard.process.outputfileexists.message=Output file exists - overwrite? importTorrentWizard.process.torrentfail.title=Torrent Write Fails importTorrentWizard.process.importfail.title=Torrent Import Fails importTorrentWizard.process.unknownfail.title=Unexpected Error ConfigView.section.stats=Statistics ConfigView.section.stats.enable=Enable ConfigView.section.stats.defaultsavepath=Statistics save directory ConfigView.section.stats.savefreq=Save frequency ConfigView.section.stats.minutes=min ConfigView.section.stats.hours=hr ConfigView.section.stats.seconds=sec ConfigView.section.stats.savefile=Statistics file name MyTorrentsView.menu.export=Export... MyTorrentsView.menu.host=Host... ManagerItem.finishing=Finishing ConfigView.dialog.choosedefaulttorrentpath=Please choose the default torrent directory ConfigView.dialog.choosemovepath=Please choose the directory to move to ConfigView.label.movecompleted=Move completed files ConfigView.label.savetorrents=Save torrent files MainWindow.menu.view.mytracker=My Tracker MyTrackerView.title.full=My Tracker MyTrackerView.name=Name MyTrackerView.tracker=Tracker MyTrackerView.status=Status MyTrackerView.status.started=Running MyTrackerView.status.stopped=Stopped MyTrackerView.peers=Peers MyTrackerView.seeds=Seeds MyTrackerView.announces=Announces MyTrackerView.uploaded=Uploaded MyTrackerView.downloaded=Downloaded MyTrackerView.left=Left ConfigView.section.style=Interface ConfigView.section.style.useCustomTabs=Use closeable tabs (needs restart) MainWindow.menu.view.plugins=Plugins fileDownloadWindow.saveTorrentIn=Save Torrent File In fileDownloadWindow.title=Vuze - Torrent Downloader fileDownloadWindow.downloading=Downloading From : fileDownloadWindow.status=Status : fileDownloadWindow.state_initializing=Initializing fileDownloadWindow.state_downloading=Downloading MainWindow.menu.file.open.url=URL openUrl.title=Vuze - Open Url openUrl.url=URL : MyTorrentsView.menu.host.error.title=Torrent Hosting Failed MyTorrentsView.menu.host.error.message=The following error occurred when hosting the torrent ConfigView.section.tracker=Tracker ConfigView.section.tracker.pollinterval=Tracker client poll interval (secs) ConfigView.section.tracker.publishenable=Publish torrent details to "" ConfigView.section.tracker.ip=External tracker IP address ConfigView.section.style.enableXPStyle=Enable XP style (needs restart) IPChecker.external.service.dyndns.name=DynDNS IPChecker.external.service.dyndns.url=http://www.dyndns.org/ IPChecker.external.service.dyndns.description=Dynamic DNS Network Services, LLC ConfigView.section.tracker.checkip=Check Address... ipCheckerWizard.title=IP Checker Wizard ipCheckerWizard.service=Service ipCheckerWizard.chooseService=Please Choose an IP Checker Service from the services listed ipCheckerWizard.service.description=Description : ipCheckerWizard.service.url=Link : ipCheckerWizard.progresstitle=Checking IP ipCheckerWizard.checkComplete=Completed IP : ipCheckerWizard.checkFailed=Failed, reason : wizard.tracker.local=Use Vuze Embedded Tracker wizard.tracker.external=Use an external Tracker wizard.tracker.howToLocal=\tGo to 'Configuration>Tracker' to enable it wizard.announceUrl=Announce URL : IPChecker.external.service.discoveryvip.name=Discoveryvip IPChecker.external.service.discoveryvip.url=http://ip.discoveryvip.com/ IPChecker.external.service.discoveryvip.description=Discoveryvip - IP address checking only IPChecker.external.httpinvalidresponse=Invalid HTTP response IPChecker.external.loadingwebpage=Loading web page IPChecker.external.analysingresponse=Analysing response IPChecker.external.addressextracted=Extracted IP address IPChecker.external.httploadfail=Failed to load page IPChecker.external.timeout=Timeout occurred IPChecker.external.ipnotfound=IP address not found ConfigView.section.tracker.pollintervalmin=Minimum ConfigView.section.tracker.pollintervalmax=Maximum ConfigView.section.tracker.pollintervalincby=Increase by ConfigView.section.tracker.pollintervalincper=Every 'n' clients splash.loadingImages=Loading Images splash.initializeGui=Initializing Main Window splash.openViews=Opening Views configureWizard.nat.tooManyPorts=Too many ports to test (9 max) MyTorrentsView.menu.publish=Publish... MyTrackerView.status.published=Published MainWindow.menu.file.open.torrentnodefault=.torrent File (No default Save) ConfigView.section.file.decoder.label=Default torrent encoding when\nselection required # # Tooltips # # # 2.0.4.4 # ConfigView.section.style.reOrderDelay=Re Order tables every N GUI update(s) GeneralView.label.updatein.querying=querying... MyTorrentsView.menu.editTableColumns=Choose the columns to display MainWindow.menu.help.checkupdate=Check for program update TrayWindow.menu.stopalldownloads=Stop All Downloads wizard.multitracker.edit=Edit.. MyTorrentsView.menu.recheck=Force Re-check MyTorrentsView.menu.editTracker=Edit Tracker URL(s) ConfigView.section.ipfilter.list.title=Blocked IPs List ConfigView.label.allowsameip=Allow Multiple connections from the same IP ConfigView.section.style.addurlsilently=Open URL silently (without dialog) ConfigView.section.style.addurlsilently.tooltip=Warning: the main window will not made visible again if activated!\nIf you loose the tray icon, you should deactivate this option. MyTorrentsView.menu.moveTop=Top MyTorrentsView.menu.moveEnd=Bottom ConfigView.label.moveonlyusingdefaultsave=if in default data dir ConfigView.label.moveonlyusingdefaultsave.tooltip=Move only if the .torrent is in the default data dir MainWindow.menu.view.stats=Statistics # #2.0.7.0 # # # 2.0.7.x # TableColumn.header.availability=\u0627\u0644\u062a\u0648\u0641\u0651\u0631 # # > 2.0.8.0 # ConfigView.section.tracker.publishenabledetails=Publish torrent file and peer details ConfigView.label.overrideip=\u062a\u062c\u0627\u0648\u0632 \u0625\u0631\u0633\u0627\u0644 \u0627\u0644\u0622\u064a \u0628\u064a \u0644\u0644\u0645\u062a\u0642\u0641\u0651\u064a\n - NAT \u0642\u062f \u062a\u062d\u062a\u0627\u062c\u0647 \u0625\u0630\u0627 \u0643\u0646\u062a \u062a\u0633\u062a\u062e\u062f\u0645 # Used for peers which we can't determine. PeerSocket.unknown=Unknown MainWindow.menu.help.faq=FAQ azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_sv_SE.properties0000644000175000017500000052413111301156004026114 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torrentfil Main.parameter.usage=Anv\u00e4ndning : java org.gudy.azureus2.cl.Main [parametrar] "fil.torrent" "s\u00f6kv\u00e4g att spara i" Main.parameter.maxUploads=Max antal samtidiga uppladdningar Main.parameter.maxSpeed=Max uppladdningshastighet i bytes/sek MainWindow.menu.file=&Arkiv MainWindow.menu.file.open=&\u00d6ppna MainWindow.menu.file.create=Skapa torrentfil MainWindow.menu.file.create.fromfile=Fr\u00e5n en fil MainWindow.menu.file.create.fromdir=Fr\u00e5n en &katalog MainWindow.menu.file.export=&Exportera en torrent... MainWindow.menu.file.import=&Importera en torrent... MainWindow.menu.file.closetab=S&t\u00e4ng flik MainWindow.menu.file.closewindow=St&\u00e4ng f\u00f6nstret MainWindow.menu.file.exit=&Avsluta MainWindow.dialog.choose.file=\u00d6ppna torrentfil MainWindow.menu.file.folder=&Katalog MainWindow.dialog.choose.folder=V\u00e4lj katalog som inneh\u00e5ller torrents MainWindow.menu.view=&Visa MainWindow.menu.view.show=Visa MainWindow.menu.view.mytorrents=Mina torrents MainWindow.menu.view.open_global_transfer_bar=\u00d6verf\u00f6ringsruta MainWindow.menu.view.configuration=&Inst\u00e4llningar MainWindow.menu.view.console=Konsoll MainWindow.menu.view.irc=&IRC MainWindow.menu.view.allpeers=Alla klienter MainWindow.menu.view.detailedlist=&Detaljerad Lista MainWindow.menu.closealldetails=St\u00e4ng &alla detaljer MainWindow.menu.closealldownloadbars=St\u00e4ng alla nedladdningsrutor MainWindow.menu.language=&Spr\u00e5k ConfigView.section.language=Spr\u00e5k MainWindow.menu.window=&F\u00f6nster MainWindow.menu.window.minimize=&Minimera MainWindow.menu.window.zoom=&Zooma MainWindow.menu.window.alltofront=Placera alla &fr\u00e4mst MainWindow.menu.help=&Hj\u00e4lp MainWindow.menu.help.about=Om Vuze MainWindow.about.title=Om MainWindow.about.section.developers=Utvecklare MainWindow.about.section.translators=\u00d6vers\u00e4ttare MainWindow.about.section.system=System MainWindow.about.section.internet=Internet MainWindow.about.internet.homepage=Vuze hemsida MainWindow.about.internet.sourceforge=Projektets SourceForge-sida MainWindow.about.internet.sourceforgedownloads=Nedladdningar fr\u00e5n SourceForge.net MainWindow.about.internet.bugreports=Rapportera buggar MainWindow.about.internet.forumdiscussion=Allm\u00e4nt diskussionsforum MainWindow.about.internet.wiki=Vuze Wiki FAQ MainWindow.dialog.choose.savepath=V\u00e4lj s\u00f6kv\u00e4g att spara i MainWindow.dialog.choose.savepath_forallfiles=V\u00e4lj s\u00f6kv\u00e4g att spara i f\u00f6r alla filer MainWindow.status.latestversion=Senaste MainWindow.status.latestversion.clickupdate=Klicka f\u00f6r att uppdatera MainWindow.status.unknown=Ok\u00e4nt MainWindow.status.checking=kontrollerar MyTorrentsView.mytorrents=Mina torrents TableColumn.header.name=Namn TableColumn.header.size=Storlek TableColumn.header.done=Slutf\u00f6rt TableColumn.header.done.info=Procent f\u00e4rdigt TableColumn.header.status=Status TableColumn.header.status.info=Vad torrenten g\u00f6r TableColumn.header.seeds=K\u00e4llor TableColumn.header.seeds.info=Antal anslutna k\u00e4llor (totalt antal k\u00e4llor) TableColumn.header.peers=Klienter TableColumn.header.peers.info=antal anslutna klienter (totalt antal) TableColumn.header.completed=Slutf\u00f6rt TableColumn.header.completed.info=# av klienter som trackern rapporterar har slutf\u00f6rt h\u00e4mtningen TableColumn.header.downspeed=(k)B/s ner TableColumn.header.upspeed=(k)B/s upp TableColumn.header.eta=Tid kvar TableColumn.header.tracker=Tracker TableColumn.header.tracker.info=Trackerns status TableColumn.header.trackernextaccess=N\u00e4sta trackers tillg\u00e4nglighet TableColumn.header.trackernextaccess.info=N\u00e4r n\u00e4sta tracker kommer att bli tillg\u00e4nglig TableColumn.header.priority=Prioritet TableColumn.header.priority.info=Begr\u00e4nsar hur mycket utg\u00e5ende bandbredd som torrenten tilldelas MyTorrentsView.menu.showdetails=Visa &Detaljer MyTorrentsView.menu.showdownloadbar=Visa nerladdningsruta MyTorrentsView.menu.open=&\u00d6ppna MyTorrentsView.menu.setpriority=Prioritet MyTorrentsView.menu.setpriority.high=&H\u00f6g MyTorrentsView.menu.setpriority.low=&L\u00e5g MyTorrentsView.menu.start=&Starta MyTorrentsView.menu.stop=&Stoppa MyTorrentsView.menu.remove=&Ta bort MyTorrentsView.menu.changeTracker=&L\u00e4gg till ny tracker TrayWindow.menu.exit=Avsluta TrayWindow.menu.show=Vi&sa Vuze SystemTray.menu.exit=Avsluta SystemTray.menu.closealldownloadbars=St\u00e4ng &alla nedladdningsrutor SystemTray.menu.open_global_transfer_bar=Visa \u00f6verf\u00f6ringsf\u00e4ltet SystemTray.menu.show=Visa Vuze PeersView.ip=IP PeersView.ip.info=Klientens IP PeersView.port=Port PeersView.port.info=Vilken port du \u00e4r ansluten till hos klienten PeersView.T=T PeersView.T.info=L (Local): Du skapade anslutningen. R (Remote): Klienten skapade anslutningen. PeersView.T.L.tooltip=Du skapade anslutningen PeersView.T.R.tooltip=Klienten skapade anslutningen PeersView.I1=I (Intressant hos k\u00e4llan) PeersView.I1.info=\u00c4r du intresserad av data som klienten har? PeersView.C1=C (Strypt av klient) PeersView.C1.info=Huruvida klienten hindrar dig fr\u00e5n att ladda ner PeersView.pieces=Delar PeersView.downloadspeed=Nedladdningshastighet PeersView.download=Nedladdat PeersView.I2=I (Intressant f\u00f6r k\u00e4llan) PeersView.I2.info=\u00c4r klienten intresserad av data som du har? PeersView.C2=C (Stryper klienten) PeersView.C2.info=Huruvida du hindrar klienten fr\u00e5n att ladda ned fr\u00e5n dig PeersView.uploadspeed=Uppladdningshastighet PeersView.uploadspeed.info=Uppladdningshastighet till klienten PeersView.upload=Uppladdat PeersView.upload.info=Totalt uppladdat till klienten. PeersView.statup=Status upp PeersView.statup.info=Ber\u00e4knad uppladdningshastighet hos klienten PeersView.S=S PeersView.S.info=En klient kan markeras som ohyfsad automatiskt om denne inte levererar data i tillr\u00e4cligt h\u00f6g hastighet. Du kan ocks\u00e5 manuellt markera en klient som ohyfsad. PeersView.downloadspeedoverall=Total nedladdningshastighet PeersView.client=Klient PeersView.client.info=Vilken typ av BitTorrentprogram som klienten anv\u00e4nder PeersView.menu.snubbed=&Ohyfsad PeersView.title.short=Klienter PeersView.title.full=Klienter AllPeersView.title.full=Alla k\u00e4llor ConfigView.section.files=Filer ConfigView.label.usefastresume=Anv\u00e4nd snabb \u00e5terupptagning ConfigView.label.incrementalfile=Aktivera sekventiell skrivning under nerladdning [N\u00f6dv\u00e4ndig f\u00f6r FAT32 i Linux] ConfigView.label.defaultsavepath=Standards\u00f6kv\u00e4g f\u00f6r nerladdning ConfigView.button.browse=&Bl\u00e4ddra... ConfigView.dialog.choosedefaultsavepath=V\u00e4lj standards\u00f6kv\u00e4g f\u00f6r nerladdning ConfigView.section.server=Server ConfigView.section.global=Globalt ConfigView.label.disconnetseed=Koppla fr\u00e5n k\u00e4llor vid uppladdning ConfigView.label.switchpriority=Byt till l\u00e5g prioritet vid uppladdning ConfigView.label.maxdownloads=Max samtidiga nerladdningar [0: obegr\u00e4nsat] ConfigView.label.maxdownloads.tooltip=Du kommer alltid att kunna ladda ned s\u00e5 m\u00e5nga torrents som du anger h\u00e4r, med ett undantag.\nEn torrent med regeln "F\u00f6rsta Prioritet" kan ta \u00f6ver en annan nedladdning om s\u00e5 kr\u00e4vs. ConfigView.label.maxactivetorrents=Max aktiva torrents (0 : obegr\u00e4nsat)\n - Nya torrents kommer inte starta om du laddar ner/skickar fler ConfigView.label.priorityExtensions=Autoprioritera filer med dom h\u00e4r\n\u00e4ndelserna (t ex txt;.nfo;.jpg) ConfigView.section.transfer=\u00d6verf\u00f6ring ConfigView.label.maxuploads=Max uppladdningar per torrent (standard) ConfigView.label.maxuploadspeed=KB/s global max uppladdningshastighet [0: obegr\u00e4nsat] ConfigView.label.saveresumeinterval=Spara data f\u00f6r snabb \u00e5terupptagning varje ConfigView.unlimited=Obegr\u00e4nsat ConfigView.section.display=Visa ConfigView.label.opendetails=\u00d6ppna fliken detaljer automatiskt ConfigView.label.openbar=\u00d6ppna nedladdningsrutan automatiskt ConfigView.label.use_old_speed_menus=Anv\u00e4nd gamla stilen f\u00f6r hastighetsmenyerna [omstart kr\u00e4vs] ConfigView.label.closetotray=St\u00e4ng minimerar till meddelandef\u00e4ltet ConfigView.label.minimizetotray=Minimera minimerar till meddelandef\u00e4ltet ConfigView.section.general=Allm\u00e4nt ConfigView.section.start=Starta ConfigView.label.showsplash=Visa startbild ConfigView.label.autoupdate=\u00d6ppna uppgraderingsrutan n\u00e4r en ny version finns tillg\u00e4nglig ConfigView.label.openconsole=\u00d6ppna Konsollen n\u00e4r programmet startas ConfigView.label.openconfig=\u00d6ppna Inst\u00e4llningar n\u00e4r programmet startas ConfigView.label.startminimized=Starta minimerat ConfigView.section.irc=IRC ConfigView.label.ircwiki=G\u00e5 till http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Server ConfigView.label.ircchannel=Kanal ConfigView.label.irclogin=Namn (nickname) ConfigView.group.irctitle=IRC-inst\u00e4llningar ConfigView.boolean.ircsendinfo=Till\u00e5t att dina inst\u00e4llningar skickas anonymt till kanaloperat\u00f6rerna s\u00e5 de kan hj\u00e4lpa dig ConfigView.boolean.irclog=Aktivera loggning f\u00f6r kanalaktivitet (i IRC_log.htm) ConfigView.section.security=S\u00e4kerhet ConfigView.label.password=Skydda Vuze med ett l\u00f6senord\n - Efterfr\u00e5gas vid uppstart och vid \u00e5terst\u00e4llning fr\u00e5n meddelandef\u00e4ltet. ConfigView.label.passwordconfirm=L\u00f6senord (bekr\u00e4fta) ConfigView.label.passwordmatch=L\u00f6senord aktiverat : ConfigView.label.passwordmatchnone=Nej ConfigView.label.passwordmatchno=Nej/L\u00f6senorden matchade inte ConfigView.label.passwordmatchyes=Ja ConfigView.button.save=Spara ConfigView.title.short=Inst\u00e4llningar ConfigView.title.full=Inst\u00e4llningar ConfigView.title.full._mac=Inst\u00e4llningar ConsoleView.title.short=Konsol ConsoleView.title.full=Konsoll FileItem.write=Skriver FileItem.read=L\u00e4ser FileItem.normal=Normal FileItem.high=H\u00f6g FileItem.donotdownload=Ladda inte ned FileItem.delete=Radera FilesView.name=Namn FilesView.size=Storlek FilesView.done=Klart FilesView.%=% FilesView.firstpiece=F\u00f6rsta delen FilesView.numberofpieces=Antal delar FilesView.pieces=Delar FilesView.mode=L\u00e4ge FilesView.priority=Prioritet FilesView.menu.open=&\u00d6ppna FilesView.menu.setpriority=Prioritet FilesView.menu.setpriority.high=H\u00f6g FilesView.menu.setpriority.normal=Normal FilesView.menu.setpriority.skipped=La&dda inte ned FilesView.title.short=Filer FilesView.title.full=Filer GeneralView.section.downloaded=Nedladdat GeneralView.label.status.file=Totalt GeneralView.label.status.pieces=Delar GeneralView.section.availability=Tillg\u00e4nglighet GeneralView.label.status.pieces_available=Status f\u00f6r delarna GeneralView.section.transfer=\u00d6verf\u00f6ring GeneralView.section.info=Information GeneralView.title.short=Allm\u00e4nt GeneralView.title.full=Allm\u00e4nt GeneralView.label.timeelapsed=\u00c5tg\u00e5ngen tid: GeneralView.label.remaining=\u00c5terst\u00e5ende tid: GeneralView.label.downloaded=Nedladdat: GeneralView.label.downloadspeed=Nedladdningshastighet: GeneralView.label.maxuploads=Max uppladdningar: GeneralView.label.maxuploads.tooltip=Du kan begr\u00e4nsa antalet samtidiga uppladdningar\nf\u00f6r att inte hastigheten ska bli f\u00f6r l\u00e5g GeneralView.label.uploaded=Uppladdat: GeneralView.label.uploadspeed=Uppladdningshastighet : GeneralView.label.seeds=Kompletta k\u00e4llor: GeneralView.label.peers=Icke kompletta k\u00e4llor: GeneralView.label.completed=Slutf\u00f6rt : GeneralView.label.totalspeed=Total hastighet: GeneralView.label.totalspeed.tooltip=Total (och medel) hastighet hos alla klienter du \u00e4r ansluten till GeneralView.label.averagespeed=medel GeneralView.label.filename=Namn: GeneralView.label.totalsize=Total storlek : GeneralView.label.savein=Sparar i: GeneralView.label.hash=Kontrollsumma: GeneralView.label.numberofpieces=Antal delar: GeneralView.label.size=Delstorlek : GeneralView.label.tracker=Tracker: GeneralView.label.updatein=Uppdaterar om: GeneralView.label.trackerurl=Trackeradress: GeneralView.label.trackerurlupdate=Manuell uppdatering GeneralView.label.comment=Kommentar fr\u00e5n Torrent : GeneralView.label.user_comment=Din kommentar : GeneralView.label.status=Status: ManagerItem.waiting=V\u00e4ntar ManagerItem.allocating=Allokerar utrymme ManagerItem.checking=Kontrollerar ManagerItem.ready=Klar ManagerItem.downloading=Laddar ned ManagerItem.seeding=Skickar ManagerItem.stopped=Stoppad ManagerItem.error=Fel ManagerItem.high=H\u00f6g ManagerItem.low=L\u00e5g MinimizedWindow.name=Namn: MinimizedWindow.all_transfers=\u00d6verf\u00f6ringar PiecesView.size=Storlek PiecesView.numberofblocks=antal block PiecesView.blocks=Block PiecesView.completed=Slutf\u00f6rda PiecesView.availability=Tillg\u00e4nglighet PiecesView.reservedby=Reserverad PiecesView.writers=Blockutdelare PiecesView.title.short=Delar PiecesView.title.full=Delar SystemTray.tooltip.seeding=%1 uppladdningar, SystemTray.tooltip.downloading=%1 nerladdningar, DownloadManager.error.filenotfound=Filen hittades inte DownloadManager.error.fileempty=Torrentfilen \u00e4r tom DownloadManager.error.filetoobig=Torrentfilen \u00e4r f\u00f6r stor DownloadManager.error.filewithouttorrentinfo=Ingen torrentinformation hittades i filen DownloadManager.error.unsupportedencoding=Kodningen st\u00f6ds inte DownloadManager.error.ioerror=I/O-fel DownloadManager.error.sha1=Algoritmfel (SHA1) PeerManager.status.offline=Anslutningsfel PeerManager.status.ok=OK PeerManager.status.checking=Kontrollerar PeerManager.status.finished=Klar PeerManager.status.finishedin=Slutf\u00f6rd p\u00e5 MainWindow.upgrade.assistant=Uppdateringsassistenten MainWindow.upgrade.newerversion=Det finns en ny version av Vuze tillg\u00e4nglig MainWindow.upgrade.explanation=Den h\u00e4r assistenten kommer att ladda ned den nya versionen och starta om Vuze MainWindow.upgrade.explanation.manual=Du kan uppdatera manuellt genom att st\u00e4nga Vuze ladda ned den nya versionen, och starta Vuze igen. MainWindow.upgrade.step1=Steg 1: Ladda ned den nya versionen. MainWindow.upgrade.step2=Steg 2: St\u00e4ng den h\u00e4r versionen och starta den nya versionen av Vuze MainWindow.upgrade.hint1=Tips:\tTryck p\u00e5 Slutf\u00f6r f\u00f6r att g\u00f6ra allt automatiskt MainWindow.upgrade.hint2=Tips:\tTryck p\u00e5 Avbryt om du vill st\u00e4nga Vuze senare och\n\tbyt namn p\u00e5 Azureus2-new.jar till Azureus2.jar n\u00e4r du st\u00e4ngt programmet MainWindow.upgrade.error.downloading.hint=Fel:\tDet gick inte att ladda ned den nya versionen, uppdatera manuellt. MainWindow.upgrade.section.info=Ny version tillg\u00e4nglig MainWindow.upgrade.section.manual=Manuell uppdatering MainWindow.upgrade.section.automatic=Automatisk uppdatering MainWindow.upgrade.tooltip.progressbar=Nedladdningsf\u00f6rloppet visas h\u00e4r Button.next=N\u00e4sta Button.finish=Slutf\u00f6r Button.cancel=Avbryt LocaleUtil.title=V\u00e4lj kodning LocaleUtil.section.chooseencoding=V\u00e4lj kodning f\u00f6r filnamnet LocaleUtil.label.chooseencoding=V\u00e4lj den b\u00e4st matchande kodningen LocaleUtil.label.hint.doubleclick=Tips: Om du dubbelklickar p\u00e5 en rad v\u00e4ljs kodning och dialogrutan st\u00e4ngs LocaleUtil.label.checkbox.rememberdecision=Kom ih\u00e5g val f\u00f6r resterande filnamn LocaleUtil.column.encoding=Kodning IrcClient.defaultChannel=#Azureusanv\u00e4ndare IrcClient.copyright=Anv\u00e4nder PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Ansluter till IrcClient.connected=Ansluten till IrcClient.joining=Ansluter till kanalen IrcClient.channel=Kanal IrcClient.joined=inne IrcClient.error=Fel IrcClient.hasjoined=har anslutit IrcClient.haskicked=har sparkat IrcClient.hasleft=har l\u00e4mnat kanalen IrcClient.nowknown=heter nu IrcClient.topicforchannel=Kanalens rubrik IrcClient.disconnected=Nerkopplad fr\u00e5n IrcClient.noNick=Ingen anv\u00e4ndare angiven. G\u00e5 till "Inst\u00e4llningar" och klicka p\u00e5 "IRC" IrcView.actionnotsupported=Detta kommando st\u00f6ds inte IrcView.clientsconnected=anv\u00e4ndare IrcView.privateto=Till IrcView.privatefrom=Fr\u00e5n IrcView.noticefrom=Meddelande: IrcView.errormsg=Fel syntax f\u00f6r /msg : /msg namn meddelande IrcView.help=Giltiga kommandon \u00e4r :\n . /help : visar detta meddelande\n . /nick | /name : \u00e4ndrar ditt namn \n . /me kommando : skickar ett kommando \n . /msg namn message : skickar ett privat meddelande till \n . /r meddelande : svarar p\u00e5 det senaste privata meddelandet\n . /join #kanal : \u00e4ndrar den aktuella kanalen PasswordWindow.title=Vuze \u00e5r l\u00e5st PasswordWindow.passwordprotected=Vuze \u00e4r l\u00f6senordsskyddat.\nSkriv in ditt l\u00f6senord f\u00f6r att forts\u00e4tta: Button.ok=Ok TrackerChangerWindow.title=L\u00e4gg till tracker TrackerChangerWindow.newtracker=Ange ny trackeradress PeersView.discarded=Bortkastat PeersView.discarded.info=Data som du tagit emot men som du inte beh\u00f6vde. D\u00e4rf\u00f6r kastas den bort. discarded=bortkastat MyTorrentsView.menu.move=&Flytta MyTorrentsView.menu.moveUp=&Upp MyTorrentsView.menu.moveDown=&Ned GeneralView.label.hashfails=Felaktig kontrollsumma: GeneralView.label.shareRatio=Ratio: ConfigView.section.downloadManagement=Download Management ConfigView.label.startRatioPeers=B\u00f6rja skicka n\u00e4r det finns f\u00e4rre \u00e4n 1 k\u00e4lla f\u00f6r varje ConfigView.text.neverStop=Sluta aldrig ConfigView.text.neverStart=B\u00f6rja aldrig ConfigView.text.peers=Klienter ConfigView.label.checkOncompletion=Verifiera delarna n\u00e4r nerladdningen \u00e4r klar wizard.title=Skapa en torrent wizard.previous=< Tillbaka wizard.next=N\u00e4sta > wizard.finish=Slutf\u00f6r wizard.mode=Tracker/L\u00e4ge wizard.tracker=Tracker: wizard.invalidurl=Denna URL \u00e4r inte giltig wizard.singlefile=Enskild fil wizard.singlefile.help=Skapa en torrent fr\u00e5n en enskild fil wizard.directory=Katalog wizard.directory.help=Skapa en torrent fr\u00e5n en katalog wizard.choosefile=V\u00e4lj fil wizard.file=Fil: wizard.browse=Bl\u00e4ddra... wizard.choosedirectory=V\u00e4lj katalog wizard.invalidfile=Ogiltig fil! wizard.invaliddirectory=Ogiltig katalog! wizard.torrentFile=Torrentfil wizard.choosetorrent=V\u00e4lj torrentfil att skapa wizard.information=Information wizard.notimplemented=Inte implementerad \u00e4nnu wizard.progresstitle=Skapar torrentfil wizard.savingfile=Sparar fil... wizard.filesaved=Fil sparad wizard.close=St&\u00e4ng Torrent.create.progress.piecelength=Storlek p\u00e5 del: Torrent.create.progress.piececount=Antal delar: Torrent.create.progress.totalfilesize=Total filstorlek: Torrent.create.progress.totalfilecount=Totalt filantal: Torrent.create.progress.parsingfiles=G\u00e5r igenom filer Torrent.create.progress.hashing=Skapar kontrollsummor MainWindow.upgrade.downloadingfrom=Laddar ned fr\u00e5n : MainWindow.menu.view.ipFilter=&IP-filter ConfigView.section.ipfilter=IP-filter ConfigView.section.ipfilter.description=Beskrivning ConfigView.section.ipfilter.start=B\u00f6rja med IP ConfigView.section.ipfilter.end=Slut IP ConfigView.section.ipfilter.add=L\u00e4gg till ConfigView.section.ipfilter.remove=Ta bort ConfigView.section.ipfilter.edit=\u00c4ndra ConfigView.section.ipfilter.save=Spara ConfigView.section.ipfilter.editFilter=\u00c4ndra filter ConfigView.section.ipfilter.enable=Aktivera PeersView.menu.close=St&\u00e4ng seedmore.title=Det finns inte tillr\u00e4ckligt med k\u00e4llor seedmore.shareratio=Du har skickat denna torrent med ratio seedmore.uploadmore=Att ha en ratio under \u00e4n 100% \u00e4r inte bra f\u00f6r BitTorrentn\u00e4tverket.\nDu borde dela ut mer av den h\u00e4r filen.\n\u00c4r du s\u00e4ker p\u00e5 att du vill forts\u00e4tta? ConfigView.label.showpopuponclose=Be om bekr\u00e4ftelse om ratio \u00e4r l\u00e4gre \u00e4n 1 n\u00e4r en torrent stoppas. ConfigView.label.startNumSeeds=\nB\u00f6rja skicka n\u00e4r det finns f\u00e4rre \u00e4n\n - \u00c5sidos\u00e4tter alla andra regler. ConfigView.label.seeds=k\u00e4llor ConfigView.section.seeding=Laddar upp MyTorrentsView.menu.removeand=Ta bort och MyTorrentsView.menu.removeand.deletetorrent=Radera &Torrentfilen MyTorrentsView.menu.removeand.deletedata=Radera &Data MyTorrentsView.menu.removeand.deleteboth=Radera Allt deletedata.title=Varning deletedata.message1=Vill du verkligen radera DATA fr\u00e5n '%1'? deletedata.noprompt=Fr\u00e5ga mig inte igen MainWindow.menu.file.configure=Guide -- Konfigurationsguide... configureWizard.title=Guide -- Konfigurationsguide configureWizard.welcome.title=V\u00e4lkommen till Vuze konfigurationsguide configureWizard.welcome.message=Den h\u00e4r guiden hj\u00e4lper dig att st\u00e4lla in Vuze f\u00f6r normalt bruk. Du kan senare modifiera konfigurationen ytterliggare i inst\u00e4llningarna fr\u00e5n menyn "Verktyg->Inst\u00e4llningar". configureWizard.transfer.title=\u00d6verf\u00f6ring och anslutning configureWizard.transfer.hint=Tips: Anv\u00e4nd strax under din bandbredd f\u00f6r maximal prestanda. configureWizard.transfer.message=V\u00e4lj en anslutning nedan. T\u00e4nk p\u00e5 att nerladdningshastigheten blir l\u00e5g om du inte v\u00e4ljer tillr\u00e4ckligt h\u00f6g uppladdningshastighet. Som absolut minimum b\u00f6r du ha minst 5KB/s i uppladdningshastighet per torrent. Ju snabbare du laddar upp, desto snabbare kan du ocks\u00e5 ladda ner. configureWizard.transfer.connection=Anslutning configureWizard.transfer.connection.0=Anpassad configureWizard.transfer.connection.1=Modem/ISDN configureWizard.transfer.connection.2=ADSL/kabelmodem xxx/128 kbps configureWizard.transfer.connection.3=ADSL/kabelmodem xxx/256 kbps configureWizard.transfer.connection.4=ADSL/kabelmodem xxx/384 kbps configureWizard.transfer.connection.5=ADSL/kabelmodem xxx/512 kbps configureWizard.transfer.connection.6=ADSL/kabelmodem xxx/768 kbps configureWizard.transfer.connection.7=ADSL/kabelmodem xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Max uppladdningshastighet (KB/s) configureWizard.transfer.maxActiveTorrents=Max aktiva configureWizard.transfer.maxDownloads=Max nedladdningar configureWizard.transfer.maxUploadsPerTorrent=Max uppladdningar per torrent configureWizard.nat.title=NAT / serverportar configureWizard.nat.message=F\u00f6r att f\u00e5 b\u00e4sta prestanda beh\u00f6ver du ha full tillg\u00e4nglighet till internet. Standardportar \u00e4r 6881 till 6889. Guiden kan testa och \u00e4ndra dessa portar f\u00f6r att se vilka som \u00e4r b\u00e4st att anv\u00e4nda. Om du redan har n\u00e5gra torrents aktiva kan vissa portar vara upptagna. configureWizard.nat.test=Test configureWizard.nat.testing=Testar port configureWizard.nat.ko=NAT-fel configureWizard.nat.unable=Kan inte testa: Ogiltig port angiven eller s\u00e5 misslyckades tj\u00e4nsten\np\u00e5 grund av att en annan applikation redan anv\u00e4nder den h\u00e4r porten. configureWizard.file.title=Torrents / Filer configureWizard.file.message1=Vuze kommer spara \u00f6ppnade torrentfiler i en specifik katalog. Du kan v\u00e4lja den katalogen h\u00e4r: configureWizard.file.path=S\u00f6kv\u00e4g configureWizard.file.browse=Bl\u00e4ddra configureWizard.file.message2=Vuze kan \u00e5teruppta nedladdning av dina filer snabbt genom att l\u00e4gga till \u00e5terupptagningsdata f\u00f6r dina torrents. Med den h\u00e4r funktionen kan du \u00e4ven \u00e5teruppta nedladdade delar som \u00e4r ofullst\u00e4ndiga. configureWizard.file.fastResume=Aktivera snabb \u00e5terupptagning configureWizard.file.invalidPath=Felaktig katalog configureWizard.finish.title=Slutf\u00f6rd configureWizard.finish.message=Vuze \u00e4r nu inst\u00e4llt. Ha kul! wizard.close.confirmation=Bekr\u00e4ftelse wizard.close.message=Vill du starta denna guide n\u00e4sta g\u00e5ng Vuze startar? exportTorrentWizard.title=Exportera en torrent exportTorrentWizard.torrentfile.title=V\u00e4lj torrent exportTorrentWizard.torrentfile.message=V\u00e4lj torrent f\u00f6r export exportTorrentWizard.torrentfile.path=S\u00f6kv\u00e4g exportTorrentWizard.torrentfile.browse=Bl\u00e4ddra exportTorrentWizard.torrentfile.invalidPath=Felaktig torrentfil exportTorrentWizard.exportfile.title=Exportera till fil exportTorrentWizard.exportfile.message=V\u00e4lj XML-fil att exportera till exportTorrentWizard.exportfile.path=S\u00f6kv\u00e4g exportTorrentWizard.exportfile.browse=Bl\u00e4ddra exportTorrentWizard.exportfile.invalidPath=Ogiltig exporteringsfil exportTorrentWizard.finish.title=Sludf\u00f6rd exportTorrentWizard.finish.message=Export slutf\u00f6rdes framg\u00e5ngsrikt exportTorrentWizard.process.inputfilebad.title=Felaktig torrentfil exportTorrentWizard.process.inputfilebad.message=Ett fel p\u00e5tr\u00e4ffades n\u00e4r filen skulle l\u00e4sas: exportTorrentWizard.process.outputfileexists.title=Filen finns exportTorrentWizard.process.outputfileexists.message=Filen finns redan - skriv \u00f6ver? exportTorrentWizard.process.torrentfail.title=L\u00e4sfel exportTorrentWizard.process.exportfail.title=Export avbryts exportTorrentWizard.process.unknownfail.title=Ov\u00e4ntat fel importTorrentWizard.title=Importera en torrent importTorrentWizard.torrentfile.title=V\u00e4lj torrent importTorrentWizard.torrentfile.message=V\u00e4lj torrentfil att importera till importTorrentWizard.torrentfile.path=S\u00f6kv\u00e4g importTorrentWizard.torrentfile.browse=Bl\u00e4ddra importTorrentWizard.torrentfile.invalidPath=Felaktig torrentfil importTorrentWizard.importfile.title=Importera fil importTorrentWizard.importfile.message=V\u00e4lj fil att importera importTorrentWizard.importfile.path=S\u00f6kv\u00e4g importTorrentWizard.importfile.browse=Bl\u00e4ddra importTorrentWizard.importfile.invalidPath=Felaktig fil importTorrentWizard.finish.title=Slutf\u00f6rd importTorrentWizard.finish.message=Import slutf\u00f6rdes framg\u00e5ngsrikt importTorrentWizard.process.inputfilebad.title=Felaktig fil importTorrentWizard.process.inputfilebad.message=Ett fel uppstod n\u00e4r filen skulle l\u00e4sas: importTorrentWizard.process.outputfileexists.title=Filen finns importTorrentWizard.process.outputfileexists.message=Filen finns - skriv \u00f6ver? importTorrentWizard.process.torrentfail.title=Skrivfel importTorrentWizard.process.importfail.title=Import avbr\u00f6ts importTorrentWizard.process.unknownfail.title=Ov\u00e4ntat fel ConfigView.label.bindip=Bind endast till denna IP-adress eller enhet ConfigView.label.xfs.allocation=Allokera ny filer speciellt f\u00f6r filsystemet XFS ConfigView.label.xfs.allocation.tooltip=Se till att /usr/sbin/xfs_io \u00e4r korrekt installerat p\u00e5 ditt system. I de flesta Linuxpaket finns filerna i "xfsprogs". xfs.allocation.xfs_io.not.found=XFS-filallokering misslyckades eftersom "/usr/sbin/xfs_io" inte kan k\u00f6ras. Se till att det \u00e4r installerat p\u00e5 r\u00e4tt s\u00e4tt. Originalfelet var: "%1". ConfigView.label.zeronewfiles=Allokera utrymme och fyll nya filer med nollor ConfigView.label.zeronewfiles.tooltip=Minimerar fragmentering ConfigView.section.stats=Statistik ConfigView.section.stats.enable=Aktivera ConfigView.section.stats.defaultsavepath=Spara statistik i ConfigView.section.stats.choosedefaultsavepath=V\u00e4lj katalog att spara statistik i ConfigView.section.stats.savefreq=Spara varje ConfigView.section.stats.minutes=min ConfigView.section.stats.hours=tim ConfigView.section.stats.seconds=sek ConfigView.section.stats.savefile=Filnamn f\u00f6r statisitk ConfigView.section.stats.graph_update_dividers=Visa vertikal linje vid var 60:e uppdatering MyTorrentsView.menu.export=&Exportera... MyTorrentsView.menu.host=&Flytta till min egen tracker... ManagerItem.finishing=Slutf\u00f6r ConfigView.dialog.choosedefaulttorrentpath=V\u00e4lj standard torrentkatalog ConfigView.dialog.choosemovepath=V\u00e4lj katalog att flytta f\u00e4rdiga torrents till ConfigView.label.movecompleted=Flytta f\u00e4rdiga filer ConfigView.label.moveremoved=Flytta f\u00e4rdiga filer (n\u00e4r de tas bort) ConfigView.label.savetorrents=Spara .torrent filer MainWindow.menu.view.mytracker=Min tracker MyTrackerView.title.full=Min tracker MyTrackerView.name=Namn MyTrackerView.tracker=Tracker MyTrackerView.status=Status MyTrackerView.status.started=P\u00e5g\u00e5r MyTrackerView.status.stopped=Stoppad MyTrackerView.peers=Nedladdare MyTrackerView.seeds=K\u00e4llor MyTrackerView.announces=Announces MyTrackerView.uploaded=Uppladdat MyTrackerView.downloaded=Nedladdat MyTrackerView.left=Kvar ConfigView.section.style=Gr\u00e4nsnitt ConfigView.label.set_ui_transfer_speeds=\u00c5sidos\u00e4tt valbara \u00f6verf\u00f6ringshastigheter ConfigView.label.set_ui_transfer_speeds.description=Du kan v\u00e4lja att manuellt definiera standardv\u00e4rdena som \u00e4r tillg\u00e4ngliga i statusf\u00e4ltet och i meddelandef\u00e4ltet f\u00f6r val av upp- och nedladdningshastigheter.\nV\u00e4rdena m\u00e5ste vara kommaseparerade. ConfigView.label.set_ui_transfer_speeds.description.download=St\u00e4ll in nedladdningshastigheter (i KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=St\u00e4ll in uppladdningshastigheter (i KB/s) ConfigView.section.style.useCustomTabs=Anv\u00e4nd st\u00e4ngbara f\u00f6nster (Omstart kr\u00e4vs) fileDownloadWindow.saveTorrentIn=Spara torrentfilen i fileDownloadWindow.title=Vuze - Torrentnedladdning fileDownloadWindow.downloading=Laddar ned fr\u00e5n: fileDownloadWindow.status=Status: fileDownloadWindow.state_initializing=Initierar fileDownloadWindow.state_downloading=Laddar ned fileDownloadWindow.state_error=Fel: MainWindow.menu.file.open.url=URL openUrl.title=Vuze - \u00d6ppna URL openUrl.url=URL : MyTorrentsView.menu.host.error.title=Torrent kunde inte flyttas till trackern MyTorrentsView.menu.host.error.message=F\u00f6ljande fel uppstod n\u00e4r torrent flyttades till trackern ConfigView.section.tracker=Tracker ConfigView.section.tracker.pollinterval=Uppdateringsintervall (sekunder) ConfigView.section.tracker.publishenable=Publicera torrentdetailjer till "/" ConfigView.section.tracker.ip=Extern IP-adress f\u00f6r tracker ConfigView.section.style.enableXPStyle=Anv\u00e4nd Windows XP-stil (kr\u00e4ver omstart) IPChecker.external.service.dyndns.name=DynDNS IPChecker.external.service.dyndns.url=http://www.dyndns.org/ IPChecker.external.service.dyndns.description=Dynamic DNS Network Services, LLC ConfigView.section.tracker.checkip=Kontrollera extern IP-adress... ipCheckerWizard.title=Guide f\u00f6r kontroll av IP-adress ipCheckerWizard.service=Tj\u00e4nst ipCheckerWizard.chooseService=V\u00e4lj en av f\u00f6ljande tj\u00e4nster ipCheckerWizard.explanations=Denna guide hj\u00e4lper dig att ta reda p\u00e5 din externa IP-adress. Om du har en dynamisk IP-adress rekomenderar vi att du anv\u00e4nder en dynamisk DNS-tj\u00e4nst. N\u00e5gra vanliga \u00e4r listade nedanf\u00f6r. Klicka p\u00e5 l\u00e4nken f\u00f6r att skapa ett konto. Sedan kan du ist\u00e4llet anv\u00e4nda ditt nya dynamiska dom\u00e4nnamn ist\u00e4llet f\u00f6r IP-adress. D\u00e5 kommer Vuze att fungera (inklusive den inbyggda trackern) \u00e4ven om din IP-adress \u00e4ndras. ipCheckerWizard.service.description=Beskrivning: ipCheckerWizard.service.url=L\u00e4nk: ipCheckerWizard.progresstitle=Kontrollerar IP ipCheckerWizard.checkComplete=F\u00e4rdig IP: ipCheckerWizard.checkFailed=Misslyckades: wizard.tracker.local=Anv\u00e4nd Vuze tracker wizard.tracker.external=Anv\u00e4nd en extern tracker wizard.tracker.howToLocal=\tG\u00e5 till "Verktyg->Inst\u00e4llningar->Tracker" f\u00f6r att aktivera den (Mac: "Vuze->Inst\u00e4llningar->Tracker") wizard.announceUrl=Meddela URL: IPChecker.external.service.discoveryvip.name=Discoveryvip IPChecker.external.service.discoveryvip.url=http://ip.discoveryvip.com/ IPChecker.external.service.discoveryvip.description=Discoveryvip - IP address checking only IPChecker.external.httpinvalidresponse=Otill\u00e5tet HTTP-svar IPChecker.external.loadingwebpage=Laddar webbsida IPChecker.external.analysingresponse=Analyserar svar IPChecker.external.addressextracted=Extraherad IP-adress IPChecker.external.httploadfail=Det gick inte att ladda sidan IPChecker.external.timeout=Timeout IPChecker.external.ipnotfound=Det gick inte att hitta IP-adressen ConfigView.section.tracker.pollintervalmin=Min ConfigView.section.tracker.pollintervalmax=Max ConfigView.section.tracker.pollintervalincby=\u00d6ka med ConfigView.section.tracker.pollintervalincper=varje 'N' klienter splash.loadingImages=L\u00e4ser in bilder splash.initializeGui=Initialiserar Huvudf\u00f6nster splash.openViews=\u00d6ppnar f\u00f6nster splash.plugin=L\u00e4ser in plugin: configureWizard.nat.tooManyPorts=F\u00f6r m\u00e5nga portar att testa (Max 9) ConfigView.section.color=F\u00e4rgschema MyTorrentsView.menu.publish=Pub&licera... MyTrackerView.status.published=Publicerad MyTrackerView.completed=F\u00e4rdig MainWindow.menu.file.open.torrentnodefault=Torrentfil (utan att spara i standards\u00f6kv\u00e4g) wizard.comment=Kommentar ConfigView.label.movetorrent=Flytta .torrent ConfigView.label.movepartialdownloads=Flytta n\u00e4r filer \u00e4r markerade "Ladda inte ned" ConfigView.label.subdir_is_in_default=Kontrollera \u00e4ven om det redan finns filer i underkataloger ConfigView.section.file.decoder.label=Standardteckenkodning n\u00e4r val beh\u00f6vs ConfigView.section.file.decoder.nodecoder=Ingen IPChecker.external.service.no-ip.name=No-IP IPChecker.external.service.no-ip.url=http://www.no-ip.com/ IPChecker.external.service.no-ip.description=Dynamisk och statisk DNS-tj\u00e4nst ConfigView.section.tracker.publicenable=Till\u00e5t externa torrents ConfigView.label.playdownloadspeech=Tala om n\u00e4r en nedladdning \u00e4r slutf\u00f6rd ConfigView.label.playdownloadspeech.info=Taltj\u00e4nsten fungerar f\u00f6r n\u00e4rvarande b\u00e4st med engelska # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Visar antalet komplett tillg\u00e4ngliga kopior av varje del.\nFinns det mindre \u00e4n en (1) kopia kan det vara problem att slutf\u00f6ra nedladdningen. GeneralView.label.trackerurl.tooltip=Klicka f\u00f6r att kopiera adressen till urklipp GeneralView.label.trackerurlopen.tooltip=Klicka f\u00f6r att \u00f6ppna trackerns websida. # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Uppdatera gr\u00e4nsnitt (GUI) varje ConfigView.section.style.graphicsUpdate=Uppdatera grafiska staplar varje N GUI uppdateringar ConfigView.section.style.reOrderDelay=Sortera tabeller varje N GUI uppdateringar ConfigView.section.style.reOrderDelay.never=Aldrig ConfigView.section.logging=Loggning ConfigView.section.logging.enable=Aktivera loggning till fil ConfigView.section.logging.logdir=Katalog f\u00f6r loggfil ConfigView.section.logging.choosedefaultsavepath=V\u00e4lj katalog att spara i GeneralView.label.updatein.querying=Uppdaterar... configureWizard.nat.sharePort=Anv\u00e4nd en delad inkommande port f\u00f6r alla torrents ConfigView.section.logging.maxsize=Max storlek f\u00f6r logg ConfigView.section.tracker.passwordenableweb=Aktivera l\u00f6senord f\u00f6r trackerns webbsida ConfigView.section.tracker.passwordenabletorrent=Aktivera l\u00f6senord f\u00f6r torrents ConfigView.section.tracker.username=Anv\u00e4ndarnamn ConfigView.section.tracker.password=L\u00f6senord columnChooser.title=V\u00e4lj kolumner att visa columnChooser.move=Drag rader f\u00f6r att \u00e4ndra placering columnChooser.apply=&Verkst\u00e4ll columnChooser.columnname=Kolumn columnChooser.columndescription=Beskrivning TableColumn.header.shareRatio=Ratio MyTorrentsView.menu.editTableColumns=&V\u00e4lj kolumner wizard.operationfailed=Operationen misslyckades authenticator.title=Autentisering kr\u00e4vs authenticator.realm=Omr\u00e5de authenticator.tracker=Tracker authenticator.user=Anv\u00e4ndarnamn authenticator.password=L\u00f6senord ConfigView.label.allowSendVersion=Till\u00e5t Vuze skicka anonym statistik (versions- och slumpm\u00e4ssigt ID-nummer) n\u00e4r Vuze s\u00f6ker efter uppdateringar ConfigView.label.version.info.link=F\u00f6r att f\u00e5 veta vad som skickas till servern, g\u00e5 hit wizard.hint.mode=Tips:\tDu kan dra-och-sl\u00e4ppa en fil eller katalog direkt p\u00e5 detta f\u00f6nster wizard.hint.file=Tips:\tDu kan v\u00e4lja en fil genom att dra-och-sl\u00e4ppa den p\u00e5 detta f\u00f6nster wizard.hint.directory=Tips:\tDu kan v\u00e4lja en katalog genom att dra-och-sl\u00e4ppa den p\u00e5 detta f\u00f6nster MainWindow.menu.help.checkupdate=S\u00f6k efter uppdatering TableColumn.header.down=Nedladdat TableColumn.header.up=Uppladdat ConfigView.section.tracker.passwordenabletorrent.info=Kr\u00e4ver en kompatibel BitTorrentklient (t. ex. Vuze ConfigView.section.style.confirmationOnExit=Visa en dialogruta f\u00f6r bekr\u00e4ftelse vid nedst\u00e4ngning MainWindow.dialog.exitconfirmation.title=Avsluta Vuze MainWindow.dialog.exitconfirmation.text=Vill du verkligen avsluta Vuze? SystemTray.menu.stopalltransfers=Stoppa &alla \u00f6verf\u00f6ringar TrayWindow.menu.stopalldownloads=Stoppa alla nedladdningar ConfigView.section.tracker.sslport.info=L\u00e4s FAQ f\u00f6r mer information wizard.tracker.ssl=Anv\u00e4nd SSL ConfigView.label.playdownloadfinished=Spela upp ett ljud n\u00e4r en nedladdning \u00e4r klar ConfigView.label.popupdownloadfinished=Visa n\u00e4r en nedladdning \u00e4r f\u00e4rdig ConfigView.label.popupfilefinished=Visa n\u00e4r en fil \u00e4r f\u00e4rdig TableColumn.header.pieces=Delar TableColumn.header.pieces.info=Grafisk representation \u00f6ver nedladdade delar TableColumn.header.completion=Slutf\u00f6rd TableColumn.header.completion.info=Grafisk representation \u00f6ver procent nedladdat. ConfigView.section.style.showdownloadbasket=Visa nedladdningsruta (Drag-och-sl\u00e4pp .torrents) ConfigView.section.style.alwaysShowTorrentFiles=Visa alltid torrents i Detaljer/Filer wizard.multitracker=L\u00e4gg till Multi-Tracker information till torrent wizard.multitracker.title=Multi-Tracker wizard.multitracker.configuration=Multi-Trackerkonfiguration wizard.multitracker.new=Ny... wizard.multitracker.edit=Redigera... wizard.multitracker.delete=Radera wizard.multitracker.group=Trackergrupp wizard.multitracker.edit.title=Multi-Tracker Editor wizard.multitracker.edit.name=Namn wizard.multitracker.edit.save=Spara wizard.multitracker.edit.newgroup=Ny grupp wizard.multitracker.edit.deletegroup=Radera wizard.multitracker.edit.newtracker=Ny tracker wizard.multitracker.edit.deletetracker=Radera wizard.multitracker.edit.edit=\u00c4ndra wizard.addingmt=L\u00e4gger till Multi-Trackerinformation wizard.multitracker.noannounce=Meddelar-URL finns inte i din trackerlista MyTorrentsView.menu.recheck=Kontrollera integritet iconBar.showDownloadBar.tooltip=Visa nedladdningsruta iconBar.start.tooltip=Start iconBar.stop.tooltip=Stopp iconBar.remove.tooltip=Ta bort iconBar.openNoDefault.tooltip=\u00d6ppna en .torrent-fil (utan att spara i standards\u00f6kv\u00e4g) iconBar.openURL.tooltip=\u00d6ppna en URL iconBar.openFolder.tooltip=\u00d6ppna en katalog iconBar.new.tooltip=Skapa en torrent iconBar.up.tooltip=Flytta upp\u00e5t iconBar.down.tooltip=Flytta ned iconBar.run.tooltip=\u00d6ppna iconBar.host.tooltip=Host iconBar.publish.tooltip=Publicera MyTorrentsView.menu.editTracker=&\u00c4ndra trackeradress(er) GeneralView.menu.selectTracker=V\u00e4lj ConfigView.section.stats.xslfile=XSL-filnamn ConfigView.section.stats.xslfiledetails=Detta inkluderas i statistikfilens filhuvud via -taggen ConfigView.label.savetorrentbackup=Spara s\u00e4kerhetskopia ConfigView.section.tracker.forceport=Tvinga externa torrents att anv\u00e4nda standardport ConfigView.section.ipfilter.allow=TILL\u00c5T dessa IP-adresser (standard \u00e4r NEKA). ConfigView.section.ipfilter.list.inrange=fanns i listan: ConfigView.section.ipfilter.list.notinrange=fanns inte i listan ConfigView.section.ipfilter.list.title=Blockerade adresser ConfigView.label.allowsameip=Till\u00e5t flera anslutningar fr\u00e5n samma IP ConfigView.label.allowsameip.tooltip=Anv\u00e4nd endast om du verkligen beh\u00f6ver.\nDetta \u00e4r ett "leecher"-skydd (n\u00e4r avst\u00e4ngd). ManagerItem.superseeding=Super-Seeding ConfigView.label.userSuperSeeding=Anv\u00e4nd Super-Seeding PeersView.uniquepiece=Del (Super-Seed) PeersView.uniquepiece.none=Ingen PeersView.timetosend=Tid (Super-Seed) ConfigView.section.style.addurlsilently=\u00d6ppna URL direkt (utan dialogruta) ConfigView.section.style.addurlsilently.tooltip=Ladda ned torrents automatiskt (utan dialogruta) ConfigView.section.file.decoder.prompt=Fr\u00e5ga alltid om kodning n\u00e4r det finns flera kodningsalternativ ConfigView.section.file.decoder.prompt.tooltip=Visa alltid dialogruta n\u00e4r det finns flera kodningsalternativ MyTorrentsView.menu.moveTop=&L\u00e4ngst upp MyTorrentsView.menu.moveEnd=&L\u00e4ngst ned ConfigView.label.moveonlyusingdefaultsave=bara om den \u00e4r i standardkatalogen ConfigView.label.moveonlyusingdefaultsave.tooltip=Flytta bara om nedladdad data \u00e4r i standardkatalogen ConfigView.label.watchtorrentfolder=Importera nya .torrentfiler automatiskt ConfigView.label.watchtorrentfolder.tooltip=S\u00f6k efter nya torrents regelbundet ConfigView.label.watchtorrentfolderinterval=Intervall ConfigView.label.watchtorrentfolderinterval.tooltip=Tid innan mappen kommer att s\u00f6kas igenom igen ConfigView.dialog.choosewatchtorrentfolderpath=V\u00e4lj katalog f\u00f6r import av .torrent ConfigView.label.startwatchedtorrentsstopped=P\u00e5b\u00f6rja stoppade ConfigView.label.startwatchedtorrentsstopped.tooltip=L\u00e4gg till nya .torrents i STOPPAT l\u00e4ge ConfigView.section.plugins=Plugins wizard.maketorrent.filesize=Storlek p\u00e5 fil(er) wizard.maketorrent.piececount=Antal delar wizard.maketorrent.piecesize=Storlek p\u00e5 delar wizard.maketorrent.auto=Auto MainWindow.menu.view.stats=&Statistik SpeedView.title.full=Aktivitet SpeedView.downloadSpeed.title=Nedladdningshastighet SpeedView.uploadSpeed.title=Uppladdningshastighet ConfigView.section.style.useSIUnits=Anv\u00e4nd IEC-enheter (KB -> KiB osv) iconBar.top.tooltip=Flytta l\u00e4ngst upp iconBar.bottom.tooltip=Flytta l\u00e4ngst ned TableColumn.header.health=H\u00e4lsa MyTorrentsView.menu.health=Om h\u00e4lsa health.explain.grey=betyder att din torrent inte \u00e4r aktiv (ned- eller uppladdning) health.explain.red=betyder att du inte \u00e4r ansluten till n\u00e5gra klienter n\u00e4r du ladder ned health.explain.blue=n\u00e4r du laddar upp betyder det att du \u00e4r inte \u00e4nnu ansluten till n\u00e5gra klienter. N\u00e4r du laddar ned betyder det att du \u00e4r ansluten till klienter men inte till trackern. health.explain.yellow=betyder att trackern \u00e4r ok. Du har utg\u00e5ende anslutningar till klienter, men ingen inkommande. Om det kvarst\u00e5r kan det betyda att du har problem med NAT eller din brandv\u00e4gg. health.explain.green=Allt \u00e4r OK =) ConfigView.section.style.alwaysRefreshMyTorrents=Uppdatera alltid "Mina torrents" ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Denna inst\u00e4llning uppdaterar "Mina torrents" \u00e4ven om de inte visas (anv\u00e4ndbart f\u00f6r vissa mirc plugins) # #2.0.7.0 # security.certtruster.title=S\u00e4kerhetsvarning security.certtruster.intro=Certifikatet \u00e4r utgivet av ett f\u00f6retag som du inte litar p\u00e5 security.certtruster.resource=Resurs: security.certtruster.issuedto=Utgivet till: security.certtruster.issuedby=Utgivet av: security.certtruster.prompt=Vill du lita p\u00e5 certifikatet? security.certtruster.yes=Ja security.certtruster.no=Nej ConfigView.section.tracker.torrentsperpage=Antal torrents per sida? (0: Obegr\u00e4nsat) MainWindow.menu.file.share=Kla&ssisk - Dela ut MainWindow.menu.file.share.file=&Fil... MainWindow.menu.file.share.dir=Katal&og... MainWindow.menu.file.share.dircontents=Kataloginneh\u00e5ll... MainWindow.menu.file.share.dircontentsrecursive=Kataloginneh\u00e5ll (&rekursivt)... MainWindow.dialog.share.sharefile=V\u00e4lj fil att dela ut MainWindow.dialog.share.sharedir=V\u00e4lj katalog att dela ut MainWindow.dialog.share.sharedircontents=V\u00e4lj kataloginneh\u00e5ll att dela ut MainWindow.dialog.share.sharedircontents.recursive=Rekursivt globalmanager.download.remove.veto=Veto anv\u00e4ndes mot "ta bort". plugin.sharing.download.remove.veto=Denna torrent \u00e4r utdelad.\nDu m\u00e5ste stoppa utdelningen f\u00f6r att ta bort torrenten.: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Tracker ConfigView.section.tracker.web=Webbsida ConfigView.label.prioritizefirstpiece=Prioritera f\u00f6rsta och sista delen p\u00e5 filerna ConfigView.label.prioritizefirstpiece.tooltip=F\u00f6rs\u00f6ker ladda ned b\u00f6rjan och slutet p\u00e5 varje fil allra f\u00f6rst s\u00e5 att det\nblir l\u00e4ttare att f\u00f6rhandsgranska innan hela filen \u00e4r nedladdad. ConfigView.section.file.confirm_data_delete=Bekr\u00e4fta vid radering av data ConfigView.section.file.confirm_data_delete.tooltip=Bekr\u00e4fta radering av data n\u00e4r du anv\u00e4nder 'Ta bort..' TrayWindow.menu.startalldownloads=Starta alla nedladdningar SystemTray.menu.startalltransfers=Starta alla \u00f6verf\u00f6ringar sharing.progress.hide=D\u00f6lj MainWindow.menu.view.myshares=Mina utdelningar MySharesView.title.full=Mina utdelningar MySharesView.name=Namn MySharesView.type=Typ MySharesView.type.file=Fil MySharesView.type.dir=Katalog MySharesView.type.dircontents=Kataloginneh\u00e5ll MySharesView.type.dircontentsrecursive=Kataloginneh\u00e5ll (rekursivt) MySharesView.menu.remove=Ta bort ConfigView.section.tracker.extensions=Ut\u00f6kningar ConfigView.section.tracker.sendpeerids=Skicka ID till klienter ConfigView.section.tracker.enableudp=Aktivera st\u00f6d f\u00f6r UDP plugin.sharing.torrent.remove.veto=Denna torrent \u00e4r utdelad.\nDu m\u00e5ste stoppa utdelningen f\u00f6r att ta bort torrenten.: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Nedladdningen kan inte tas bort eftersom den inte \u00e4r stoppad plugin.sharing.remove.veto=Denna fil delas ut fr\u00e5n en katalog (med inneh\u00e5ll).\nStoppa utdelningen av katalogen f\u00f6r att sluta dela ut filen. GeneralView.label.hash.tooltip=Klicka f\u00f6r att kopiera kontrollsumman till urklipp ConfigView.section.tracker.maxpeersreturned=Max antal klienter som rapporteras (0: Obegr\u00e4nsat) ConfigView.label.serverport=Inkommande TCP/UDP-port ConfigView.label.serverport.tooltip=Portnummer m\u00e5ste vara mellan 1-65535. 6880 f\u00e5r ej anv\u00e4ndas d\u00e5 den \u00e4r reserverad f\u00f6r programmet. configureWizard.nat.server.tcp_listen_port=Inkommande TCP-port ConfigView.section.sharing=Utdelning ConfigView.section.sharing.usessl=Anv\u00e4nd SSL f\u00f6r utdelade filer (Kr\u00e4ver trackerinst\u00e4llning) ConfigView.section.style.dropdiraction=Drag-och-sl\u00e4pp funktion f\u00f6r kataloger ConfigView.section.style.dropdiraction.opentorrents=\u00d6ppna torrents ConfigView.section.style.dropdiraction.sharefolder=Dela ut katalog ConfigView.section.style.dropdiraction.sharefoldercontents=Dela ut inneh\u00e5ll # # 2.0.7.x # Categories.all=Alla Categories.uncategorized=Okategoriserat CategoryAddWindow.message=Ange ett namn f\u00f6r den nya kategorin CategoryAddWindow.title=Skapa en ny Kategori ConfigView.label.autoSeedingIgnoreInfo=Ignorerade torrents hamnar i botten av k\u00f6n. De startas inte automatiskt. ConfigView.label.directory=Katalog ConfigView.label.disconnetseed.tooltip=Koppla fr\u00e5n andra k\u00e4llor n\u00e4r du sj\u00e4lv \u00e4r k\u00e4lla. ConfigView.label.ignoreCase=Ignorera versaler/gemener ConfigView.label.ignoreSeeds=Ignorera torrents med minst ConfigView.label.importdirectory=Importera katalog ConfigView.label.minPeersToBoostNoSeeds.tooltip=En torrent utan k\u00e4llor och har f\u00e4rre klienter \u00e4n du anger\nkommer att hamna l\u00e4ngre ned i k\u00f6n. ConfigView.label.minPeersToBoostNoSeeds=Minska prioritet f\u00f6r torrents som inte har k\u00e4llor, samt mindre \u00e4n ConfigView.label.minSeedingTime.tooltip=Prioriteringsordningen kan ibland variera snabbt. Det kan f\u00e5 en torrent att starta, stoppa och hamna i k\u00f6 och sen startas igen. Denna inst\u00e4llning minskar risken genom att l\u00e5ta torrenten laddas upp f\u00f6r en minsta tid som du anger. Du kan ocks\u00e5 alltid manuellt stoppa en torrent. ConfigView.label.minSeedingTime=Minsta tid f\u00f6r uppladdning i sekunder ConfigView.label.minSpeedForActiveDL.tooltip=En torrent tar alltid upp en aktiv plats i 30 sekunder efter att den startas. ConfigView.label.minSpeedForActiveDL=Ignorera torrents som laddar ned l\u00e5ngsammare \u00e4n ConfigView.label.peers=klienter ConfigView.label.queue.debuglog=Spara information f\u00f6r fels\u00f6kning ConfigView.label.queue.debuglog.info=L\u00e4gger till information f\u00f6r fels\u00f6kning i konsollen och loggfiler.\nInformationen kan t ex hj\u00e4lpa till att tala om varf\u00f6r torrents inte startar. ConfigView.label.queue.minQueueingShareRatio=Stoppa eller flytta inte till k\u00f6 om inte utdelningsratio \u00e4r ConfigView.label.removeOnStop=Ta bort torrent fr\u00e5n listan om den stoppats automatiskt ConfigView.label.savedirectory=Spara i katalog ConfigView.label.seeding.autoReposition.tooltip=Sorterar listan med kompletta torrents (som laddas upp) efter kolumnen prioritering. Det kan vara bra om du valt att inte visa kolumnen prioritering. ConfigView.label.seeding.autoReposition=\u00c4ndra ordning automatiskt beroende p\u00e5 prioritet ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Om det finns f\u00e5 k\u00e4llor och m\u00e5nga klienter s\u00e5 betyder det m\u00e5nga g\u00e5nger att det inte finns en full kopia av torrenten p\u00e5 n\u00e4tverket.\nP\u00e5 grund av detta kanske du inte vill att Vuze k\u00f6system ska anta att det finns minst en full kopia p\u00e5 n\u00e4tverket (det minskar prioriteten i k\u00f6n). ConfigView.label.seeding.fakeFullCopySeedStart=... men bara f\u00f6r torrents med minst ConfigView.label.seeding.ignore=Ignorera regler ConfigView.label.seeding.ignore0Peers=Ignorera torrents med 0 klienter ConfigView.label.seeding.ignoreRatioPeers=Ignorera torrents som har minst 1 k\u00e4lla f\u00f6r varje ConfigView.label.seeding.ignoreShareRatio=Ignorera torrents som har en ratio p\u00e5 ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorera torrent \u00e4ven\nom regeln "H\u00f6gsta prioritet" g\u00e4ller. ConfigView.label.seeding.ignore.header.rule=Regel ConfigView.label.seeding.ignore.header.value=V\u00e4rde ConfigView.label.seeding.firstPriority.info=Torrents med h\u00f6gsta prioritet kommer alltid vara aktiv (laddar upp) och ligga \u00f6verst i k\u00f6n. En torrent som har h\u00f6gsta prioritet kommer inte att stoppas automatiskt eller bli placerad i k\u00f6. H\u00f6gsta prioritering g\u00f6r att flera torrents kan dela plats om det beh\u00f6vs. ConfigView.label.seeding.firstPriority.FP=H\u00f6gsta prioritet ConfigView.label.seeding.firstPriority=H\u00f6gsta prioritet g\u00e5r till torrent(s) med ConfigView.label.seeding.firstPriority.following=av f\u00f6ljande: ConfigView.label.seeding.firstPriority.shareRatio=En ratio l\u00e4gre \u00e4n ConfigView.label.seeding.firstPriority.seedingMinutes=En f\u00f6rfluten tid sen torrenten blev f\u00e4rdig. ConfigView.label.seeding.firstPriority.DLMinutes=En f\u00f6rfluten tid sen torrenten startades ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Genom att anta att det \u00e4r 1 full kopia per X klienter kommer du att minska prioriteringen f\u00f6r torrenten om det finns m\u00e5nga klienter. Antalet k\u00e4llor som visas kommer dock inte att \u00e4ndras. ConfigView.label.seeding.numPeersAsFullCopy=Anta att det finns 1 full kopia f\u00f6r varje\n(0: Anta inte) ConfigView.label.seeding.preferLargerSwarms.tooltip=Om du i huvudsak laddar upp torrents och det finns m\u00e5nga klienter som har "stannat" kan det vara rimligt att v\u00e4lja stora sv\u00e4rmar.\n\nOm du i huvudsak laddar upp torrents och det finns m\u00e5nga f\u00e4rdiga k\u00e4llor kan det vara rimligt att v\u00e4lja en liten sv\u00e4rm.\n ConfigView.label.seeding.preferLargerSwarms=Prioritera den st\u00f6rsta sv\u00e4rmen om torrents har samma prioritet. ConfigView.label.seeding.rankType.none.tooltip=Ordning baserad p\u00e5 kolumnen # ConfigView.label.seeding.rankType.none=Inget ConfigView.label.seeding.rankType.peerSeed.tooltip=H\u00f6gre ratio = h\u00f6gre prioritet ConfigView.label.seeding.rankType.seed.fallback=Fall tillbaka till ratio klienter:k\u00e4llor efter\n(0 : aldrig) ConfigView.label.seeding.rankType.seed.options=Alternativ ConfigView.label.seeding.rankType.seed.tooltip=F\u00e4rre k\u00e4llor = H\u00f6gre prioritet ConfigView.label.seeding.rankType.seed=Enbart k\u00e4llor ConfigView.label.seeding.rankType.timedRotation.tooltip=Alla f\u00e4rdiga torrents i k\u00f6n kommer att rotera mellan uppladdning och paus. ConfigView.label.seeding.rankType.timedRotation=Tidsbest\u00e4md rotation ConfigView.label.seeding.rankType.tooltip=Torrents med h\u00f6gsta prioritet startas automatiskt. N\u00e4r en annan torrent f\u00e5r h\u00f6gre prioritet stoppas torrent med l\u00e4gre prioritet. ConfigView.label.seeding.rankType=Prioritera torrents f\u00f6r automatisk uppladdning baserat p\u00e5: ConfigView.label.stopAfterMinutes=Stanna efter en tid av uppladdning ConfigView.label.switchpriority.tooltip=L\u00e5g prioritet minskar den tilldelade utg\u00e5ende bandbredden f\u00f6r torrenten. ConfigView.pluginlist.info=F\u00f6ljande plugin har identifierats. Vissa plugin kanske inte har konfigurationsflikar. ConfigView.pluginlist.noplugins=Inga plugin har identifierats. ConfigView.section.pluginslist=Lista ConfigView.section.queue.seeding=Uppladdning ConfigView.section.queue.seeding.autoStarting=Automatisk utdelning ConfigView.section.queue.seeding.ignore=Ignorera regler ConfigView.section.queue.seeding.firstPriority=H\u00f6gsta prioritet ConfigView.section.queue=K\u00f6 ConfigView.section.torrents=Torrents ConfigView.text.all=alla ConfigView.text.hours=timmar ConfigView.text.ignoreRule=Ignorera regel ConfigView.text.ignore=Ignorera ConfigView.text.minutes=minuter ConfigView.text.neverIgnore=Ignorera aldrig ConfigView.text.any=vilken som DownloadManager.error.datamissing=Data saknas MainWindow.menu.file.open.torrentforseeding=Torrentfil (Att ladda upp) MainWindow.menu.language.refresh=&Uppdatera ManagerItem.forced=Tvingad: ManagerItem.queued=I k\u00f6 MySeedersView.header=Kompletta torrents TableColumn.header.availability.info=Antal kompletta kopior TableColumn.header.availability=Tillg\u00e4nglighet TableColumn.header.category=Kategori MyTorrentsView.header=Inkompletta torrents TableColumn.header.maxuploads=Max # uppladdningar MyTorrentsView.menu.category.delete=Ra&dera Kategori MyTorrentsView.menu.forceStart=&Tvinga start MyTorrentsView.menu.queue=&S\u00e4tt i k\u00f6 MyTorrentsView.menu.setCategory.add=Sk&apa en ny Kategori... MyTorrentsView.menu.setCategory=Ange kategori TableColumn.header.savepath=Sparar i s\u00f6kv\u00e4g TableColumn.header.SeedingRank=Prioritet TableColumn.header.totalspeed.info=Total hastighet hos alla klienter som du \u00e4r ansluten till TableColumn.header.totalspeed=Total hastighet splash.initializePlugins=Initialiserar Plugins StartStopRules.SPratioMet=Ratio OK StartStopRules.FP0Peers=H\u00f6gsta prioritet/0 klienter StartStopRules.0Peers=0 klienter StartStopRules.numSeedsMet=# Klienter OK StartStopRules.ratioMet=Klienter:K\u00e4llor OK StartStopRules.shareRatioMet=Ratio OK StartStopRules.waiting=V\u00e4ntar StartStopRules.firstPriority=H\u00f6gsta prioritet ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Dela ut inneh\u00e5ll (rekursivt) DownloadManager.error.unabletostartserver=Kan inte starta servern - kontrollera konfiguration f\u00f6r inkommande port samt brandv\u00e4ggsinst\u00e4llningar f\u00f6r serverprogramvaran GeneralView.label.creationdate=Skapades: ConfigView.section.tracker.announcescrapepercentage=Snabb uppdatering som %tid av full\n(ex. 200 = 2:1). 0 = l\u00e5t klienten avg\u00f6ra. ManagerItem.stopping=Stoppar ConfigView.section.tracker.announcecacheperiod=Beh\u00e5ll buffert f\u00f6r full uppdatering i (ms) ConfigView.section.tracker.scrapecacheperiod=Beh\u00e5ll buffert f\u00f6r snabb skrapningsuppdatering i (ms) ConfigView.section.tracker.scrapeandcache=Tracker: Uppdatering och buffert ConfigView.section.tracker.announcecacheminpeers=Aktivera buffert om fler klienter \u00e4n MyTrackerView.scrapes=Skrapningar fileDownloadWindow.retry=F\u00f6rs\u00f6k igen MyTrackerView.bytesin=Bytes in MyTrackerView.bytesinave=Medel in MyTrackerView.bytesout=Bytes ut MyTrackerView.bytesoutave=Medel ut ConfigView.section.file.max_open_files=Maximalt antal \u00f6ppna filer f\u00f6r skrivning/l\u00e4sning\n[0: obegr\u00e4nsat] ConfigView.section.file.max_open_files.tooltip=Anv\u00e4ndbart om du laddar ned torrents med hundratals/tusentals filer i och du n\u00e5r taket f\u00f6r antalet 'file handles' som ditt OS klarar av. ConfigView.section.proxy=Proxy ConfigView.section.proxy.enable_proxy=Aktivera proxy ConfigView.section.proxy.host=Server ConfigView.section.proxy.port=Port ConfigView.section.proxy.username=Anv\u00e4ndarnamn ConfigView.section.proxy.password=L\u00f6senord ConfigView.section.proxy.enable_socks=Jag har en SOCKS-proxy wizard.createtorrent.extrahashes=Skapa kontrollsummor f\u00f6r andra n\u00e4tverk/protokoll (t.ex. Gnutella2, eDonkey2000) GeneralView.label.connected=anslutna GeneralView.label.in_swarm=i sv\u00e4rmen ManagerItem.initializing=Initierar AlertMessageBox.error=Fel AlertMessageBox.warning=Varning AlertMessageBox.comment=Information AlertMessageBox.information=Information AlertMessageBox.unread=Det finns ol\u00e4sta varningsmeddelanden - klicka h\u00e4r f\u00f6r att visa dem. SharedPortServer.alert.selectorfailed=Det gink inte att etablera en port f\u00f6r att lyssna efter inkommande data.\nKontrollera att brandv\u00e4ggens inst\u00e4llningar till\u00e5ter java(w).exe att agera som en server. Tracker.alert.listenfail=Kunde inte \u00f6ppna port %1.\nKontrollera att den inte anv\u00e4nds av andra program. DiskManager.alert.movefileexists=Fel: Kan inte flytta f\u00e4rdiga filer.\nFilen %1 finns redan i destinationsmappen. DiskManager.alert.movefilefails=Fel: Kunde inte flytta f\u00e4rdiga filer\nFlytt av fil %1 misslyckades, %2 DiskManager.alert.movefilerecoveryfails=Fel: Kunde inte \u00e5terg\u00e5 efter misslyckad flytt av filer.\n\u00c5terst\u00e4llning av fil %1 misslyckades, %2 ConfigView.section.tracker.logenable=Skriv periodisk statistik till "tracker.log". SpeedView.stats.title=Statistik SpeedView.stats.total=Totalt SpeedView.stats.session=Den h\u00e4r sessionen SpeedView.stats.session.tooltip=Totalt under den h\u00e4r sessionen SpeedView.stats.downloaded=Nedladdat (Protokoll) SpeedView.stats.uploaded=Uppladdat (Protokoll) SpeedView.stats.uptime=Upptid (timmar) SpeedView.stats.now=Just nu SpeedView.stats.now.tooltip=\u00d6verf\u00f6ringshastighet just nu. AutoMigration.useralert=Vuze anv\u00e4ndarkonfiguration har automatiskt flyttats. Resultat:\n\n%1\n%2ALLA FEL SOM UPPST\u00c5TT M\u00c5STE FLYTTAS MANUELLT. # # > 2.0.8.0 # OpenTorrentWindow.title=\u00d6ppna torrent(s) OpenTorrentWindow.message=Experimentell OpenTorrentWindow.addFiles=&L\u00e4gg till filer OpenTorrentWindow.dataLocation=Plats (katalog) att spara data: OpenTorrentWindow.startMode=L\u00e4gg till l\u00e4ge OpenTorrentWindow.startMode.queued=I k\u00f6 OpenTorrentWindow.startMode.stopped=Stoppad OpenTorrentWindow.startMode.forceStarted=Tvinga startad OpenTorrentWindow.addPosition=Position i k\u00f6 OpenTorrentWindow.addPosition.first=F\u00f6rst OpenTorrentWindow.addPosition.last=Sist TableColumn.header.remaining.info=Kvar att ladda ner TableColumn.header.remaining=Kvar ConfigView.section.tracker.enablecompact=Anv\u00e4nd kompakt protokoll f\u00f6r uppdateringar ConfigView.section.tracker.enablekey=Till\u00e5t Vuze att skicka nycklar till trackern f\u00f6r ut\u00f6kad s\u00e4kerhet ConfigView.section.file.perf=Prestanda ConfigView.section.file.perf.explain=Varning! felaktiga \u00e4ndringar f\u00f6r dessa parametrar kan f\u00f6rs\u00e4mra nedladdningsprestandan. Omstart kr\u00e4vs.\nOm du har "slut p\u00e5 minne" (out of memory) fel, \u00f6verv\u00e4g d\u00e5 att begr\u00e4nsa antalet anslutningar per torrent (se Inst\u00e4llningar -> \u00d6verf\u00f6ring).\n ConfigView.section.file.max_open_files.explain=Att \u00f6ppna f\u00f6r m\u00e5nga filer kan orsaka problem i operativsystemet p.g.a. begr\u00e4nsade resurser som t.ex. 'file handles'. Detta begr\u00e4nsar antalet filer som samtidigt kan vara \u00f6ppnade. popup.error.hide=D\u00f6lj popup.error.details=Detaljer ConfigView.section.style.colorOverrides=F\u00e4rger ConfigView.section.style.colorOverride.progressBar=F\u00f6rloppsindikatorn ConfigView.section.style.colorOverride.error=Fel MainWindow.status.tooOld=\u00e4r gammal. Du b\u00f6r uppdatera den. ConfigView.section.style.colorOverride.warning=Varning ConfigView.section.style.colorOverride.altRow=Varannan Rad ConfigView.section.file.save.peers.enable=Kom ih\u00e5g anslutningar till k\u00e4llor/klienter f\u00f6r snabb \u00e5teranslutning. ConfigView.section.file.save.peers.max=Maximalt antal anslutningar att komma ih\u00e5g [0: obegr\u00e4nsat] ConfigView.section.file.save.peers.pertorrent=per torrent ConfigView.label.max_peers_per_torrent=Max antal anslutningar per torrent [0: obegr\u00e4nsat] ConfigView.label.max_peers_total=Max antal anslutningar globalt [0: obegr\u00e4nsat] ConfigView.section.style.colorOverrides.reset=\u00c5terst\u00e4ll f\u00e4rg ConfigView.section.language.info=Vuze kontrollerar om det finns nya uppdateringar n\u00e4r programmet startar om denna funktion \u00e4r aktiverad. ConfigView.section.language.enableUpdate=Aktivera webbuppdatering ConfigView.section.language.UpdateURL=Uppdatera fr\u00e5n URL ConfigView.section.language.UpdateNow=Uppdatera nu! Button.revert=\u00c5terg\u00e5 MyTorrentsView.menu.changeDirectory=\u00c4ndra datakatalog GenericText.column=kolumn MyTorrentsView.menu.thisColumn.remove=Ta bort kolumn MyTorrentsView.menu.thisColumn.toClipboard=Kopiera text till urklipp MyTorrentsView.menu.tracker=Tracker ConfigView.download.abbreviated=Ned ConfigView.upload.abbreviated=Upp TableColumn.header.secondsseeding=Skickat i TableColumn.header.secondsseeding.info=Hur l\u00e4nge du har laddat upp TableColumn.header.secondsdownloading=Laddat ned i TableColumn.header.secondsdownloading.info=Hur l\u00e4nge du har laddat ner ConfigView.section.tracker.udpversion=UDP-protokoll: Version 1 eller 2. window.updateswt.title=Din SWT-version \u00e4r f\u00f6r gammal! window.updateswt.text=Din version av SWT \u00e4r f\u00f6r gammal!\nSWT \u00e4r ett grafikbibliotek som anv\u00e4nds av Vuze och versionen du har \u00e4r f\u00f6r gammal f\u00f6r att k\u00f6ra senaste Vuzeversionen. Klicka p\u00e5 OK knappen f\u00f6r att uppdatera din SWT. window.updateswt.failed=Uppdatering misslyckades. Klicka p\u00e5 OK f\u00f6r att f\u00f6rs\u00f6ka igen. window.updateswt.status.downloading.updater=Laddar ner modul f\u00f6r uppdatering window.updateswt.status.finding=Letar efter senaste versionen av SWT window.updateswt.status.downloading=Laddar ned senaste versionen av SWT window.updateswt.status.done=Startar om window.updateswt.cancel=Avbryt swt.updater.downloader.downloading=Laddar ned SWT fr\u00e5n swt.updater.urlsgetter.downloading=H\u00e4mtar en speglingslista fr\u00e5n swt.updater.urlsgetter.platform=SWT f\u00f6r plattform: window.updateswt.ignore=Ignorera ConfigView.section.style.useFancyTabs=Anv\u00e4nd alternativa flikar splash.initializeGM=Initialiserar global torrentmanager splash.loadingTorrents=L\u00e4ser in torrents MyTorrentsView.menu.thisColumn.sort=&Sortera Scrape.status.ok=Skrapning Ok. Scrape.status.error=Skrapfel: Scrape.status.error.badURL=URL f\u00f6r uppdatering f\u00f6ljer inte skrapningsstandard. Scrape.status.error.nohash=Kontrollsumma saknas fr\u00e5n svar Scrape.status.error.invalid=Felaktigt svar Scrape.status.nextScrapeAt=N\u00e4sta skrapning vid %1 Scrape.status.scraping=Skrapar.. Scrape.status.initializing=V\u00e4ntar att f\u00e5 skrapa... Scrape.status.scraping.queued=Skrapning k\u00f6ad... ConfigView.label.minSpeedForActiveSeeding=Ignorera en f\u00e4rdig torrent som laddas upp l\u00e5ngsammare \u00e4n ConfigView.section.stats.exportpeers=Exportera detaljer om klienter MainWindow.menu.view.irc.moved=IRC finns nu tillg\u00e4ngligt som ett plugin. G\u00e5 till http://azureus.sourceforge.net/plugin_list.php. Efter installation kan du g\u00e5 till Visa -> Plugin -> IRC f\u00f6r att anv\u00e4nda den. MyTrackerView.webui.contextmenu.copyurl=Kopiera torrent URL till urklip ConfigView.section.file.torrent.ignorefiles=Ignorera dessa filer n\u00e4r nya torrents skapas\nt.ex. .DS_Store, Thumbs.db Torrent.create.progress.ignoringfile=Ignorerar fil ConfigView.section.style.useUnitsRateBits=Anv\u00e4nd bits ist\u00e4llet f\u00f6r bytes (KiB/s -> Kibit/s osv) ConfigView.section.interface.resetassoc=\u00c5terst\u00e4ll association f\u00f6r .torrentfiler (\u00d6ppna med Vuze) ConfigView.section.interface.resetassocbutton=\u00c5terst\u00e4ll ConfigView.section.interface.checkassoc=Kontrollera filassociationer vid uppstart dialog.associations.title=Associationskontroll Button.yes=Ja Button.no=Nej ConfigView.label.seeding.autoStart0Peers=Starta automatiskt f\u00e4rdiga torrents som inte har n\u00e5gra klienter. ConfigView.label.seeding.autoStart0Peers.tooltip=Anv\u00e4nd om du vill att antalet k\u00e4llor ska synas f\u00f6r torrents utan klienter. dialog.associations.prompt=Vuze \u00e4r inte standardprogrammet f\u00f6r att \u00f6ppna BitTorrent filer.\nVill du associera .torrent filer med Vuze? dialog.associations.askagain=Kontrollera under uppstart ConfigView.section.plugins.update=Uppdatering f\u00f6r Plugin Plugin.pluginupdate.enablecheck=Aktivera s\u00f6kning efter pluginuppdateringar plugins.basicview.status=Status: plugins.basicview.activity=Aktivitet: plugins.basicview.progress=Utveckling: plugins.basicview.log=Logg: ConfigView.label.maxdownloadspeed=KB/s global maxhastighet f\u00f6r nedladdning [0: obegr\u00e4nsat] splash.loadingTorrent=L\u00e4ser in torrent splash.of=av ConfigView.section.plugins.irc=IRC UpdateWindow.title=Vuze uppdaterare UpdateWindow.header=F\u00f6ljande komponenter beh\u00f6ver uppdateras: UpdateWindow.columns.install=Installera UpdateWindow.columns.name=Namn UpdateWindow.columns.size=Storlek UpdateWindow.cancel=Avbryt UpdateWindow.quit=Avsluta UpdateWindow.close=St&\u00e4ng UpdateWindow.ok=Uppdatera UpdateWindow.restart=Starta om UpdateWindow.status.downloading=Laddar ner UpdateWindow.status.done=F\u00e4rdig UpdateWindow.status.failed=Misslyckades UpdateWindow.status.restartNeeded=Omstart kr\u00e4vs! ConfigView.pluginlist.broken=Trasig ConfigView.pluginlist.whereToPut=Placera anv\u00e4ndarspecifika plugins i en egen katalog i: ConfigView.pluginlist.whereToPutOr=Anv\u00e4nd katalog f\u00f6r delade plugins: MainWindow.statusText.checking=Kontrollerar om det finns uppdateringar TableColumn.header.OnlyCDing4=Tid uppladdning TableColumn.header.OnlyCDing4.info=Tid som torrenten endast har laddat upp data. ConfigView.section.style.alternateTablePainting=Anv\u00e4nd en annan metod f\u00f6r att rita de grafiska tabellkolumnerna (kanske kr\u00e4ver omstart) UpdateWindow.status.restartMaybeNeeded=Omstart kan beh\u00f6vas ConfigView.pluginlist.shared=delade PeersView.host=Dom\u00e4nnamn PeersView.host.info=Klientens dom\u00e4nnamn, om tillg\u00e4ngligt. Kan p\u00e5verka prestandan negativt. MainWindow.menu.help.whatsnew=Vad \u00e4r nytt ConfigView.label.checkonstart=S\u00f6k efter uppdateringar n\u00e4r Vuze startas ConfigView.label.periodiccheck=S\u00f6k efter uppdateringar periodvis. ConfigView.label.opendialog=\u00d6ppna automatiskt Uppdateringsguiden n\u00e4r en uppdatering finns tillg\u00e4nglig MainWindow.updateavail=(ny uppdatering finns) MainWindow.status.unofficialversion=Vuze Beta MainWindow.status.latestversionunchecked=Versionskontroll inaktiverad GeneralView.label.updatein.stopped=Stoppad StartStopRules.menu.viewDebug=Visa debug-info ConfigView.section.style.doNotUseGB=Anv\u00e4nd inte enheten GB. ConfigView.section.style.doNotUseGB.tooltip=Vuze anv\u00e4nder alltid MB \u00e4ven om storleken \u00e4r st\u00f6rre \u00e4n 1024MB MainWindow.menu.help.plugins=H\u00e4mta Plugins ConfigView.section.tracker.enablecategories=Dela upp torrents per kategori health.explain.share=betyder att torrenten \u00e4r antingen hostad eller publicerad ConfigView.section.tracker.createcert=Skapa ett sj\u00e4lvsignerat certifikat ConfigView.section.tracker.createbutton=Skapa security.certcreate.title=Skapa ett sj\u00e4lvsignerat certifikat security.certcreate.intro=Denna dialog l\u00e5ter dig skapa ett sj\u00e4lvsignerat certifikat security.certcreate.strength=Styrka security.certcreate.firstlastname=F\u00f6rnamn och efternamn security.certcreate.orgunit=Avdelning security.certcreate.city=Stad eller Ort security.certcreate.state=L\u00e4n eller landsdel security.certcreate.country=Landskod med tv\u00e5 bokst\u00e4ver (SE) security.certcreate.ok=Skapa security.certcreate.cancel=Avbryt security.certcreate.createok=Skapa certifikat lyckades security.certcreate.createfail=Skapa certifikat misslyckades ConfigView.section.plugins.webui=Swing web-gr\u00e4nssnitt ConfigView.section.plugins.xml_http_if=XML/HTTP-gr\u00e4nssnitt webui.passwordenable=Aktivera l\u00f6senord webui.user=Anv\u00e4ndarnamn webui.password=L\u00f6senord webui.protocol=Protokoll (*) webui.homepage=Hemsida (*) webui.rootdir=Root-mapp (*) webui.rootres=Root-resurs (*) webui.mode=L\u00e4ge (*) webui.mode.info=L\u00e4ge kan vara\n\t"full"\t= alla funktioner tillg\u00e4ngliga (standard)\n\t"view"\t= \u00f6verblick endast (men kan \u00e4ndra uppdateringsfrekvens) webui.access=Tilltr\u00e4de (*) webui.access.info=Tilltr\u00e4de kan vara\n\t"local"\t= endast den lokala maskinen kan ansluta\n\t"all"\t= obegr\u00e4nsad tillg\u00e5ng (standard)\n\tIP\t= t.ex. 192.168.0.2\t\t\tendast ett IP\n\tIP1-IP2\t= t.ex. 192.168.0.1-192.168.0.255\tett IP-subn\u00e4t GeneralView.label.maxdownloadspeed=Max Ned Security.keystore.corrupt=Nyckeln "%1" kunde inte laddas in, var v\u00e4nlig ta bort den och \u00e5terskapa/importera om certifikaten Security.keystore.empty=Nyckeln \u00e4r tom. Var v\u00e4nlig skapa ett sj\u00e4lvsignerat certifikat (se Inst\u00e4llningar->S\u00e4kerhet) eller importera ett existerande certifikat till '%1' webui.restart.info=\u00c4ndringar i parametrar markerade med (*) kr\u00e4ver en omstart f\u00f6r att f\u00e5 effekt GeneralView.label.maxdownloadspeed.tooltip=max nedladdningshastighet [0: Obegr\u00e4nsad] ConfigView.section.UPnP=UPnP upnp.enable=Aktivera UPnP upnp.info=Universell Plug & Play (UPnP) m\u00f6jligg\u00f6r automatisk omdirigering (mappning) av portar i UPnP-aktiverade brandv\u00e4ggar och andra enheter. upnp.mapping.dataport=Inkommande port f\u00f6r klientdata upnp.mapping.tcptrackerport=TCP Trackerport upnp.mapping.udptrackerport=UDP Trackerport upnp.alert.differenthost=UPnP: Mappning "%1" \u00e4r redan reserverad av "%2" - V\u00e4lj en annan port upnp.alert.mappingok=UPnP: Mappning "%1" etablerad upnp.alert.mappingfailed=UPnP: Mappning "%1" misslyckades upnp.alertsuccess=Visa lyckade anslutningar/mappningar upnp.alert.lostdevice=UPnP: Tappade anslutningen till tj\u00e4nst "%1" p\u00e5 UPnP-enhet "%2" upnp.grabports=Mappa portar \u00e4ven om de an\u00e4nds av en annan dator upnp.refresh.label=Uppdatera portmappningar upnp.refresh.button=Uppdatera upnp.alert.mappinggrabbed=UPnP: Mappning "%1" etablerad - tagen fr\u00e5n "%2" upnp.mapping.tcpssltrackerport=TCP SSL Trackerport upnp.alertothermappings=Visa portar som anv\u00e4nds av andra datorer upnp.alertdeviceproblems=Visa problem med UPnP-enheten upnp.trace_to_log=Skriv felinformation till logg upnp.wiki_link=Vuze Wikisiida ang\u00e5ende UPnP ConfigView.pluginlist.coreplugins=F\u00f6ljande inbyggda plugin \u00e4r laddade: Peers.column.DLedFromOthers=Fr\u00e5n andra Peers.column.DLedFromOthers.info=M\u00e4ngd data som laddats ned fr\u00e5n andra som varit anslutna till dig Peers.column.UpDownRatio=Upp:Ned Peers.column.UpDownRatio.info=Klienters ratio Peers.column.UpRatio=Ratio uppladdat Peers.column.UpRatio.info=Klienters ration enl "Laddat fr\u00e5n dig:Laddat fr\u00e5n andra" upnp.releasemappings=Sl\u00e4pp portmappningar vid nedst\u00e4nging webui.upnpenable=Aktivera UPnP f\u00f6r denna port (*) ConfigView.section.file.friendly.hashchecking=V\u00e4nlig hashkontroll ConfigView.section.file.friendly.hashchecking.tooltip=Ett n\u00e5got l\u00e5ngsammare hashkontrollsl\u00e4ge (mycket mindre arbetsamt f\u00f6r din cpu/system). ConfigView.section.tracker.seedretention=Max uppladdningar per torrent [0: Obegr\u00e4nsat] ConfigView.section.tracker.seedretention.info=OBS: Uppladdningsstatistik f\u00f6rsvinner n\u00e4r uppladdningen tas bort ConfigView.section.tracker.port=M\u00f6jligg\u00f6r tracker p\u00e5 HTTP-port ConfigView.section.tracker.sslport=M\u00f6jligg\u00f6r tracker p\u00e5 HTTPS-port ConfigView.section.tracker.publicenable.info=Detta g\u00f6r det m\u00f6jligt f\u00f6r andra att skapa torrents som anv\u00e4nder din tracker\nutan att du hostar/publicerar dem Button.clear=Rensa MainWindow.IPs.tooltip=Senaste uppdateringen av filterlistan: %1\nAntal IPFilter i listan - Antal blockerade/bannlysta/d\u00e5liga adresser den h\u00e4r sessionen.\nDubbelklicka f\u00f6r att visa detaljer. ConfigView.section.ipfilter.list.banned=har blivit bannlyst f\u00f6r att skicka felaktig data ConfigView.section.ipfilter.list.baddata=har skickat felaktig data: tillf\u00e4llen = Button.reset=\u00c5terst\u00e4ll ConfigView.section.ipfilter.bannedinfo=IP adresser som har skickat felaktig data bannlyses om gr\u00e4ns \u00f6verskridits ConfigView.section.ipfilter.blockedinfo=IP adresser som har blivit blockerade p\u00e5 grund av IP-filter download.removerules.name=Regler f\u00f6r avl\u00e4gsning download.removerules.unauthorised.info=Oauktoriserade torrents \u00e4r s\u00e5dana som anses ej godk\u00e4nda av trackern download.removerules.unauthorised=Avl\u00e4gsna icke godk\u00e4nda torrents automatiskt download.removerules.unauthorised.seedingonly=\tEndast om uppladdning p\u00e5g\u00e5r download.removerules.removed.ok=Automatisk avl\u00e4gsning av torrent med '%1' avklarat. Detta beror p\u00e5 borttagningsreglerna f\u00f6r denna torrent. download.removerules.updatetorrents=Avl\u00e4gsna Vuze uppdateringstorrents s\u00e5 som sv\u00e4rmen kr\u00e4ver ConfigView.label.defaultstarttorrentsstopped=L\u00e4gg alltid till nya torrents i stoppat l\u00e4ge ConfigView.section.server.enableudp=M\u00f6jligg\u00f6r klientprotokoll f\u00f6r UDP-tracker. upnp.mapping.dataportudp=UDP-tracker klientport ConfigView.section.file.decoder.showlax=Visa mindre vanliga kodningar ConfigView.section.file.decoder.showall=Visa alla m\u00f6jliga kodningar MainWindow.status.updowndetails.tooltip=Upp/Nedladdningshastighet detaljer\nH\u00f6gerklicka f\u00f6r att \u00e4ndra eller\ndubbelklicka f\u00f6r att \u00f6ppna statistiken. TrackerClient.announce.warningmessage=Trackern "%1" returnerade en varning "%2" ConfigView.section.tracker.natcheckenable=Kontrollera port f\u00f6r inkommande data och rapportera till klienter ConfigView.section.tracker.publishenabledetails=Publicera detaljer om torrentfil och klienter ConfigView.section.tracker.publishenablepeerdetails=Publicera detaljer om klienter MyTrackerView.badnat=NAT-fel MyTrackerView.badnat.info=K\u00e4llor/klienter som inte klarade en NAT-kontroll ConfigView.section.tracker.natchecktimeout=Kontrollerar timeout (sekunder) ConfigView.section.file.perf.cache.enable=Aktivera diskbuffert ConfigView.section.file.perf.cache.size=Storlek f\u00f6r bufferten i %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u00d6ve&rf\u00f6ringar MainWindow.menu.transfers.startalltransfers=St&arta alla MainWindow.menu.transfers.stopalltransfers=St&oppa alla MainWindow.menu.transfers.pausetransfers=&Pausa MainWindow.menu.transfers.resumetransfers=&\u00c5teruppta ConfigView.label.experimental.osx.kernel.panic.fix=Experimentfix f\u00f6r kernel panics p\u00e5 OS X-system med dubbla processorer [kr\u00e4ver omstart] SystemTray.menu.pausetransfers=Pausa \u00f6verf\u00f6ringar SystemTray.menu.resumetransfers=\u00c5teruppta \u00f6verf\u00f6ringar ConfigView.section.file.truncate.too.large=Korta av existerande filer som \u00e4r f\u00f6r stora ConfigView.section.file.perf.cache.trace=Sp\u00e5ra buffert aktiviteter f\u00f6r diagnostiska syften ConfigView.section.interface.enabletray=Aktivera ikon i Meddelandef\u00e4ltet [Omstart kr\u00e4vs] PeerManager.status.error=Fel Stats.title.full=Statistik TransferStatsView.title.full=\u00d6verf\u00f6ringar CacheView.title.full=Buffert CacheView.general.size=Total storlek CacheView.general.inUse=Anv\u00e4nds CacheView.general.title=Buffertinformation CacheView.reads.title=L\u00e4sningar I/O CacheView.reads.fromFile=Fr\u00e5n fil CacheView.reads.fromCache=Fr\u00e5n buffert CacheView.reads.hits=Tr\u00e4ffar CacheView.writes.title=Skrivningar I/O CacheView.writes.toCache=Till buffert CacheView.writes.toFile=Till fil CacheView.writes.hits=Sparat CacheView.speeds.title=Datahastigheter CacheView.speeds.reads=L\u00e4sningar CacheView.speeds.writes=Skrivningar CacheView.speeds.fromCache=Fr\u00e5n/till buffert CacheView.speeds.fromFile=Fr\u00e5n/till fil CacheView.reads.amount=Totalt CacheView.reads.avgsize=Medelstorlek openUrl.referrer=H\u00e4nvisad fr\u00e5n URL : openUrl.referrer.info=Beh\u00f6vs bara f\u00f6r de webbsidor som kr\u00e4ver det ConfigView.label.maxuploadspeedseeding=Alternativ hastighet n\u00e4r du endast laddar upp ConfigView.label.transfer.ignorepeerports=Ignorera kli3enter med f\u00f6ljande data portar (separerade med ';', t. ex. 0;25) ConfigView.section.proxy.enable_socks.peer=Aktivera proxy f\u00f6r kommunikation med klienter (endast utg\u00e5ende anslutningar) [omstart kr\u00e4vs] ConfigView.section.proxy.peer.informtracker=Informera tracker om begr\u00e4nsningar ConfigView.section.proxy.socks.version=SOCKS-version PiecesView.legend.written=Skrivet PiecesView.legend.requested=Beg\u00e4rt PiecesView.legend.downloaded=Nedladdat, avvaktar skrivning PiecesView.legend.incache=Data \u00e4r i bufferten PiecesView.typeItem.0=L\u00e5ngsam PiecesView.typeItem.1=Snabb PiecesView.type=Typ Security.jar.tools_not_found=JAR-signering misslyckades - "tools.jar" hittades ej i %1. Se Verktyg->Inst\u00e4llningar->S\u00e4kerhet (Mac: Vuze->Inst\u00e4llningar->S\u00e4kerhet) f\u00f6r mer detaljer. Security.jar.signfail=JAR-signering misslyckades - %1 ConfigView.section.security.toolsinfo=Signerade JAR-filer anv\u00e4nds f\u00f6r att st\u00f6dja vissa plugins, till exempel 'Swing Web Interface' (n\u00e4r den \u00e4r konfigurerad f\u00f6r det).\nF\u00f6r att signera JAR filer \u00e4r det n\u00f6dv\u00e4ndigt att ha tillg\u00e5ng till 'tools.jar', filen som f\u00f6ljer med Sun JDK (inte JRE).\nOm du bara installerat JRE (Java Runtime Enviroment) installera d\u00e5 JDK (Java Development Kit).\nVuze kan normalt sett hitta filen \u00e5t dig. Om det d\u00e4remot misslyckas kan du specificera katalogen h\u00e4r. ConfigView.section.security.toolsdir=Katalog som inneh\u00e5ller 'tools.jar' ConfigView.section.security.choosetoolssavedir=V\u00e4lj katalogen som inneh\u00e5ller 'tools.jar' authenticator.torrent=Torrent ConfigView.section.proxy.peer.same=Anv\u00e4nd samma proxyinst\u00e4llnngar vid kommunikation med klienter som f\u00f6r trackern ConfigView.section.connection.network.max.simultaneous.connect.attempts=Max samtidiga utg\u00e5ende anslutningsf\u00f6rs\u00f6k [0: utg\u00e5ende inaktiverat] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Max number of new outbound connection establishments Vuze should attempt any given time.\nNOTE: WindowsXP Service Pack 2 (SP2) imposes a system-wide limit of 10 simultaneous connect attempts.\nDefault value is 8. Value of 0 disables outbound connects entirely. ConfigView.section.file.perf.cache.size.explain=The cache is used to reduce reads from/writes to disk. Unless you are using the java option '-XX:MaxDirectMemorySize' to explicitly set the memory available for cache and network IO use, you should keep this value at least %1 below your maximum VM size. The current maximum VM size is %2. For instructions on how to change this, see MemoryUsage in the wiki on %3. Failure to use sensible settings will result on 'out of memory' errors. More than 32MB of cache is probably overkill. MyTorrentsView.menu.setSpeed.unlimit=Ingen begr\u00e4nsning MyTorrentsView.menu.setSpeed.unlimited=Obegr\u00e4nsad MyTorrentsView.menu.setSpeed.disable=Inaktivera uppladdning MyTorrentsView.menu.setSpeed.disabled=Inaktiverad MyTorrentsView.menu.setSpeed.in=i MyTorrentsView.menu.setSpeed.slots=platser av GeneralView.label.maxuploadspeed=Max Upp GeneralView.label.maxuploadspeed.tooltip=max uppladdningshastighet [0 : Obegr\u00e4nsad] MyTorrents.items.UpSpeedLimit.disabled=Ingen uppladdning MyTorrents.items.UpSpeedLimit.unlimited=Obegr\u00e4nsad TableColumn.header.maxupspeed=Max uppladdningshastighet TableColumn.header.maxupspeed.info=Max uppladdningshastighet per torrent ConfigView.section.file.perf.cache.enable.write=Buffra nedladdad data f\u00f6r att reducera skrivningar till disk och ocks\u00e5 minska diskl\u00e4sningar som beh\u00f6vs f\u00f6r kontroll av delar ConfigView.section.file.perf.cache.enable.read=L\u00e4s i f\u00f6rv\u00e4g f\u00f6r att minimera diskl\u00e4sning n\u00e4r du laddar upp ConfigView.section.tracker.separatepeerids=Anv\u00e4nd olika klientidentiteter f\u00f6r tracker- och datakommunikation ConfigView.section.tracker.separatepeerids.info=\u00d6kar anonymiteten n\u00e4r du laddar anonymt\np\u00e5 en ickeanonym anslutning ConfigView.section.interface.wavlocation=S\u00f6kv\u00e4g till .wav-fil ConfigView.section.interface.wavlocation.info=V\u00e4lj .wav-fil eller l\u00e4mna tom f\u00f6r standardljud ConfigView.section.tracker.server=Server ConfigView.section.tracker.client=Klient ConfigView.section.tracker.client.connecttimeout=Timeout f\u00f6r anslutning (sekunder) ConfigView.section.tracker.client.readtimeout=L\u00e4s-timeout (sekunder) MainWindow.menu.tools=Verk&tyg FilesView.path=S\u00f6kv\u00e4g FilesView.fullpath=Visa fullst\u00e4ndig s\u00f6kv\u00e4g FilesView.remaining=\u00c5terst\u00e5ende delar TableColumn.header.trackername=Trackerns namn TableColumn.header.trackername.info=Trackerns namn ConfigView.group.override=Val f\u00f6r \u00e5sidos\u00e4ttning ConfigView.section.file.perf.cache.notsmallerthan=Buffra inte filer mindre \u00e4n det h\u00e4r (i %1) PeersView.menu.blockupload=Blockera uppladdning PeersView.menu.kickandban=Sparka och banna PeersView.menu.kickandban.reason=Manuellt bannlyst klient PeersView.state=L\u00e4ge PeersView.state.info=Tillst\u00e5nd f\u00f6r anslutning till klient PeersView.state.pending=Avvaktande PeersView.state.connecting=Ansluter PeersView.state.handshake=V\u00e4ntar p\u00e5 handskakning PeersView.state.established=Kontakt etablerad ConfigView.section.tracker.processinglimits=Ber\u00e4kningsgr\u00e4nsv\u00e4rden ConfigView.section.tracker.maxgettime=Max tids\u00e5tg\u00e5ng f\u00f6r GET-behandling (sekunder) [0: Obegr\u00e4nsat] ConfigView.section.tracker.maxgettime.info=Anv\u00e4nds f\u00f6r trackeranm\u00e4lan och skrapning ConfigView.section.tracker.maxposttimemultiplier.info=Anv\u00e4nds f\u00f6r "form submissions" och uppladdningar ConfigView.section.tracker.maxthreads=Max antal samtidiga f\u00f6rfr\u00e5gningar DownloadManager.error.operationcancancelled=\u00c5tg\u00e4rd avbruten Torrent.create.progress.cancelled=\u00c5tg\u00e4rd avbruten sharing.progress.cancel=Avbryt wizard.maketorrents.autoopen=\u00d6ppna torrenten f\u00f6r uppladdning ConfigView.section.sharing.rescanenable=Aktivera periodisk scanning efter \u00e4ndringar i din utdelning ConfigView.section.sharing.rescanperiod=Intervall f\u00f6r scanning (sekunder) ConfigView.section.connection.advanced=Avancerade n\u00e4tverksinst\u00e4llningar ConfigView.section.connection.advanced.mtu=Line Maximum Transmission Unit (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Max paketstorlek som kan \u00f6verf\u00f6ras per frame.\nVuze anv\u00e4nder MTU-40 (MSS). ConfigView.section.connection.advanced.SO_RCVBUF=Storlek p\u00e5 "Socket SO_RCVBUF" [0: operativsystemets standardv\u00e4rde] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=St\u00e4ll in standardv\u00e4rdet f\u00f6r "Socket SO_RCVBUF" (i bytes), d v s storlek och skala p\u00e5 mottagningsf\u00f6nstret f\u00f6r TCP.\nVuze l\u00e4mnar normalt denna tom vilket betyder att operativsystemets standardv\u00e4rde anv\u00e4nds ist\u00e4llet.\nOBS: Linux dubblerar v\u00e4rdet. ConfigView.section.connection.advanced.SO_SNDBUF=Storlek p\u00e5 "Socket SO_SNDBUF" [0: operativsystemets standardv\u00e4rde] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=St\u00e4ll in standardv\u00e4rdet f\u00f6r "Socket SO_SNDBUF" (i bytes), d v s storlek p\u00e5 s\u00e4ndningsf\u00f6nstret f\u00f6r TCP.\nVuze l\u00e4mnar normalt denna tom vilket betyder att operativsystemets standardv\u00e4rde anv\u00e4nds ist\u00e4llet.\nOBS: Linux dubblerar v\u00e4rdet. ConfigView.section.interface.confirm_torrent_removal=Visa en dialogruta f\u00f6r bekr\u00e4ftelse vid borttagning av torrent ConfigView.section.interface.confirm_torrent_removal.tooltip=Bekr\u00e4fta vid borttagning av torrent fr\u00e5n "Mina Torrents". MyTorrentsView.confirm_torrent_removal=\u00c4r du s\u00e4ker p\u00e5 att du vill ta bort?\n TableColumn.header.seed_to_peer_ratio=Ratio TableColumn.header.seed_to_peer_ratio.info=Ratio totalt i sv\u00e4rmen PeersView.connected_time=Ansluten tid PeersView.connected_time.info=Totala tiden ansluten till klient ConfigView.section.interface.display.add_torrents_silently=L\u00e4gg till torrents automatiskt ConfigView.section.interface.display.add_torrents_silently.tooltip=L\u00e4gg till torrentnedladdningar utan att aktivera Vuze huvudf\u00f6nster. TableColumn.header.maxdownspeed=Max nedladdninghastighet TableColumn.header.maxdownspeed.info=Max nedladdningshastighet per torrent PeersGraphicView.title=Sv\u00e4rm ConfigView.section.tracker.passwordwebhttpsonly=Till\u00e5t endast \u00e5tkomst via HTTPS TableColumn.header.torrentpath=Torrentfilens plats TableColumn.header.torrentpath.info=Var torrentfilen finns p\u00e5 h\u00e5rddisken ConfigView.section.sharing.torrentcomment=Kommentar for genererade torrents ConfigView.label.copyanddeleteratherthanmove=Kopiera och ta sen bort originaldata hellre \u00e4n att flytta i en operation - detta kan undvika dataf\u00f6rlust i vissa filsystem ConfigView.label.openstatsonstart=\u00d6ppna Statistik n\u00e4r programmet startas swt.install.window.title=Vuze plugininstallerare swt.install.window.ok=Installera swt.install.window.header=F\u00f6ljande komponenter har markerats f\u00f6r installation: swt.uninstall.window.title=Vuze pluginborttagare swt.uninstall.window.ok=Ta bort swt.uninstall.window.header=F\u00f6ljande komponenter har markerats f\u00f6r borttagning: installPluginsWizard.title=Installera plugins installPluginsWizard.mode.title=Var v\u00e4nlig och v\u00e4lj hur du vill installera: installPluginsWizard.mode.list=Fr\u00e5n en lista som h\u00e4mtas ifr\u00e5n sourceforge.net installPluginsWizard.list.title=Lista \u00f6ver plugins som kan installeras installPluginsWizard.list.loading=V\u00e4nta medan listan med plugins laddas. installPluginsWizard.list.loaded=V\u00e4lj vilka plugins du vill installera: installPluginsWizard.list.name=Namn installPluginsWizard.list.version=Version installPluginsWizard.list.description=Beskrivning av plugin: installPluginsWizard.finish.title=Installation p\u00e5g\u00e5r installPluginsWizard.finish.explanation=De plugin du har valt kommer att installeras med hj\u00e4lp av assistenten.\n\nHa t\u00e5lamod, det kan ta en stund innan den visas.\nDubbelklicka till v\u00e4nster i statusf\u00e4ltet f\u00f6r att visa \u00c5tg\u00e4rdsrapport f\u00f6nstret\nd\u00e4r du kan se status f\u00f6r \u00e5tg\u00e4rden. installPluginsWizard.details.loading=Var v\u00e4nlig och v\u00e4nta. Laddar detaljer... installPluginsWizard.mode.file=Fr\u00e5n fil installPluginsWizard.installMode.title=Var v\u00e4nlig och v\u00e4lj typ av installation installPluginsWizard.installMode.user=Installera plugin(s) endast f\u00f6r dig installPluginsWizard.installMode.shared=Installera plugin(s) f\u00f6r alla anv\u00e4ndare installPluginsWizard.file.title=Var v\u00e4nlig och bl\u00e4ddra efter det plugin du vill installera installPluginsWizard.file.file=Fil : installPluginsWizard.file.invalidfile=Filen \u00e4r inte ett giltigt plugin f\u00f6r Vuze. installPluginsWizard.file.no_such_file=Det finns ingen fil med det namnet. installPluginsWizard.file.browse=Bl\u00e4ddra... uninstallPluginsWizard.title=Avinstallera plugin uninstallPluginsWizard.list.title=Lista \u00f6ver installerade plugins uninstallPluginsWizard.list.loaded=V\u00e4lj vilka plugins som du vill avinstallera. installPluginsWizard.list.nullversion=Ingen version uninstallPluginsWizard.finish.title=Avinstallation p\u00e5g\u00e5r uninstallPluginsWizard.finish.explanation=Valda plugins kommer att avinstalleras med hj\u00e4lp av uppdateringsassistenten. MainWindow.menu.plugins.installPlugins=Guide -- Installationsguide... MainWindow.menu.plugins.uninstallPlugins=Guide -- Avinstallationsguide... ConfigView.section.ipfilter.totalIPs=Sammanlagt %1 IP-adresser \u00e4r blockerade. Det \u00e4r %2 av internet. update.instance.install=Kontrollerar installation update.instance.uninstall=Kontrollerar avinstallation update.instance.update=S\u00f6ker efter uppdateringar MainWindow.status.update.tooltip=Dubbelklicka f\u00f6r information om f\u00f6rloppet updater.progress.window.title=Aktuella installationer updater.progress.window.info=Klicka p\u00e5 "Avbryt" f\u00f6r att stoppa alla p\u00e5g\u00e5ende operationer Button.abort=Avbryt ConfigView.section.ipfilter.enablebanning=Blockera klienter som j\u00e4mt skickar felaktig data Network.alert.acceptfail=F\u00f6r m\u00e5nga fel uppstod f\u00f6r port %1, %2 - \u00e5tg\u00e4rden avbr\u00f6ts.. Kontrollera dina brandv\u00e4ggsinst\u00e4llningar. MyShares.column.category=Kategori UpdateWindow.restartLater=Starta om senare MainWindow.menu.file.restart=Starta om Vuze MainWindow.dialog.restartconfirmation.title=Starta om Vuze MainWindow.dialog.restartconfirmation.text=Vill du verkligen starta om Vuze? deletetorrent.message1=Du \u00e4r p\u00e5 v\u00e4g att radera TORRENT filen f\u00f6r :\n\n deletetorrent.message2=\n\n\u00c4r du s\u00e4ker p\u00e5 att du vill forts\u00e4tta? ConfigView.label.prioritizemostcompletedfiles=Prioritera de mest kompletta filerna splash.plugin.init=Initialiserar plugin: splash.plugin.UIinit=Initialiserar Plugin GUI: %1 ConfigView.section.style.osx_small_fonts=Anv\u00e4nd litet teckensnitt [Omstart kr\u00e4vs] ConfigView.section.tracker.tcpnonblocking=Anv\u00e4nd "non-blocking I/O" f\u00f6r TCP-trackers. Om detta v\u00e4ljs m\u00e5ste trackern k\u00f6ras p\u00e5 en annan port. Experimentversion! ConfigView.section.tracker.nonblockingconcmax=Max antal samtidiga anslutningar [0: Obegr\u00e4nsat] MyTorrentsView.menu.exportmenu=Exportera MyTorrentsView.menu.exporttorrent=Torrent... ConfigView.group.scrape=Skrapning ConfigView.section.tracker.client.scrapeinfo=Om du inaktiverar skrapning kommer inte alla k\u00f6reglerna att fungera eftersom de f\u00f6rlitar sig p\u00e5 information fr\u00e5n sv\u00e4rmen. ConfigView.section.tracker.client.scrapeenable=Aktivera skrapning ConfigView.section.tracker.client.scrapestoppedenable=Skrapa torrents som inte laddar Scrape.status.disabled=Skrapning inaktiverad MyTorrentsView.menu.explore=Visa fil MyTorrentsView.menu.explore._mac=Visa i Finder MyTorrentsView.menu.explore._windows=Visa i Utforskaren wizard.maketorrents.autohost=L\u00e4gg upp torrent med den inbyggda trackern ConfigView.label.overrideip=\u00c5sidos\u00e4tt IP-adressen som skickas till trackern (NAT) - anv\u00e4nd semikolon f\u00f6r att separera flera adresser ConfigView.label.overrideip.tooltip=Informera trackern om andra IP-adresser \u00e4n den som utg\u00e5ende datapaket skickas fr\u00e5n. L\u00e4mna f\u00e4ltet tomt f\u00f6r att inte anv\u00e4nda inst\u00e4llningen. ConfigView.section.connection.group.networks=N\u00e4tverk ConfigView.section.connection.group.networks.info=V\u00e4lj de vanligaste till\u00e5tna n\u00e4tverken f\u00f6r P2P-\u00f6verf\u00f6ring ConfigView.section.connection.networks.prompt=Visa en dialogruta n\u00e4r en nedladdning fr\u00e5n en anonym tracker l\u00e4ggs till ConfigView.section.connection.networks.Public=Publikt IP n\u00e4tverk (ej anonymt) ConfigView.section.connection.networks.I2P=I2P-n\u00e4tverk ConfigView.section.connection.networks.Tor=N\u00e4tverket The Onion Router (Tor) TableColumn.header.networks=N\u00e4tverk TableColumn.header.networks.info=Till\u00e5tna n\u00e4tverk f\u00f6r P2P datakommunikation Scrape.status.networkdisabled=N\u00e4tverk ej aktiverat ConfigView.section.tracker.server.group.networks=N\u00e4tverk ConfigView.section.tracker.server.group.networks.info=V\u00e4lj vilka n\u00e4tverk som trackern skall acceptera klienter fr\u00e5n window.networkselection.title=N\u00e4tverksval window.networkselection.info=Nedanst\u00e5ende torrent har trackers med st\u00f6d f\u00f6r f\u00f6ljande n\u00e4tverk.\nV\u00e4lj vilka du vill aktivera f\u00f6r anslutningar till tracker och klienter. window.networkselection.description=Torrent: plugins.basicview.clear=Rensa ConfigView.section.connection.group.peersources=Klientk\u00e4llor ConfigView.section.connection.group.peersources.info=V\u00e4lj de till\u00e5tna k\u00e4llorna f\u00f6r anslutningar till klienter ConfigView.section.connection.peersource.Tracker=Fr\u00e5n en tracker ConfigView.section.connection.peersource.DHT=Decentraliserad tracking ConfigView.section.connection.peersource.PeerExchange=Tillagd av en annan klient ConfigView.section.connection.peersource.Plugin=Tillagd av ett plugin ConfigView.section.connection.peersource.Incoming=Inkommande anslutning PeersView.source=K\u00e4lla PeersView.source.info=K\u00e4llan f\u00f6r den h\u00e4r klienten TableColumn.header.peersources=Klientk\u00e4llor TableColumn.header.peersources.info=Till\u00e5tna klientk\u00e4llor f\u00f6r P2P wizard.tracker.dht=Decentraliserad (endast Vuzeklienter) MyTorrentsView.menu.advancedmenu=Avancerat MyTorrentsView.menu.networks=N\u00e4tverk MyTorrentsView.menu.peersource=Klientk\u00e4llor ConfigView.section.sharing.permitdht=Till\u00e5t decentraliserad sp\u00e5rning n\u00e4r trackern inte \u00e4r tillg\u00e4nglig ConfigView.section.sharing.protocol=Protokoll f\u00f6r delade resurser PeersView.Messaging=Meddelanden PeersView.Messaging.info=Visar vilket meddelandesystem som anv\u00e4nds ConfigView.label.queue.newseedsmovetop=Flytta nyss f\u00e4rdiga torrents till toppen av seedlistan ConfigView.label.seeding.firstPriority.ignore.info=Kom ih\u00e5g att om du anv\u00e4nder n\u00e5gon av dessa regler kan det inneb\u00e4ra att en nedladdning stoppas s\u00e5 fort den \u00e4r klar. ConfigView.label.seeding.firstPriority.ignore=Ignorera regeln "H\u00f6gsta prioritet" f\u00f6r: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents med en ratio \u00f6ver ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents utan klienter ConfigView.section.tracker.sendjavaversionandos=Skicka Java-version och OS-namn MagnetPlugin.contextmenu.exporturi=Kopiera Magnet-URI till Urklipp ConfigView.section.plugins.dht=Distribuerande DB dht.info=Denna plugin st\u00f6der bland annat decentralliserad tracking. Om du st\u00e4nger av den begr\u00e4nsar det dina m\u00f6jligheter att ladda ned dht.enabled=Aktivera den distribuerade databasen dht.portdefault=Anv\u00e4nd standardport dht.port=UDP-port f\u00f6r databasen dht.execute.command=Diagnostikkommando dht.execute.info=Klicka f\u00f6r att utf\u00f6ra kommandot dht.execute=K\u00f6r dht.logging=Aktivera sp\u00e5rning av aktivitet ConfigView.section.plugins.dhttracker=Distribuerande Tracker dhttracker.tracknormalwhenoffline=Sp\u00e5ra bara normala torrentfiler n\u00e4r deras tracker inte \u00e4r tillg\u00e4nglig ConfigView.section.file.nativedelete._mac=Anv\u00e4nd papperskorgen n\u00e4r filer tas bort ConfigView.section.file.nativedelete._windows=Flytta raderade filer till Papperskorgen ConfigView.section.logging.generatediagnostics=Skapa ConfigView.section.logging.netinfo=Generera n\u00e4tverksinformation ConfigView.section.logging.statsinfo=Generera statistikinformation ConfigView.section.logging.generatediagnostics.info=Generera information f\u00f6r diagnostik och kopiera till urklipp och loggfil (om konfigurerat) ConfigView.section.sharing.privatetorrent=Privat torrent - acceptera endast klienter fr\u00e5n trackern MainWindow.menu.tools.nattest=&NAT/Brandv\u00e4ggstest... Button.apply=&Verkst\u00e4ll Button.close=St&\u00e4ng window.welcome.title=V\u00e4lkommen till Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Versionsinformation dht.reseed.label=Normalt \u00e4r det inte n\u00f6dv\u00e4ndigt att ladda upp distribuerad databas p\u00e5 nytt. Om antalet klienter \u00e4r l\u00e5gt kan det dock vara bra f\u00f6r komma ig\u00e5ng. dht.reseed.group=Ladda upp p\u00e5 nytt dht.reseed.ip=IP-adress dht.reseed.port=Port dht.reseed=Ladda upp p\u00e5 nytt dht.reseed.info=Ladda upp databasen p\u00e5 nytt dht.diagnostics.group=Diagnostik DHTView.title.full=Distribuerad databas DHTView.title.fullcvs=Distribuerad databas CVS DHTView.general.title=Allm\u00e4nt DHTView.general.uptime=Ansluten i: DHTView.general.users=Anv\u00e4ndare: DHTView.general.nodes=Noder: DHTView.general.leaves=Blad: DHTView.general.contacts=Kontakter: DHTView.general.replacements=Ers\u00e4ttare: DHTView.general.live=Levande: DHTView.general.unknown=Ok\u00e4nda: DHTView.general.dying=D\u00f6ende: DHTView.transport.title=\u00d6verf\u00f6ringsdetaljer DHTView.transport.packets=Paket DHTView.transport.bytes=Bytes DHTView.transport.received=Mottaget DHTView.transport.sent=Skickat DHTView.transport.in=In: DHTView.transport.out=Ut: DHTView.operations.title=Driftsdetaljer DHTView.operations.sent=Skickat DHTView.operations.ok=Ok DHTView.operations.failed=Misslyckades DHTView.operations.received=Mottaget DHTView.operations.ping=Ping DHTView.operations.findNode=Hitta nod DHTView.operations.findValue=Hitta v\u00e4rde DHTView.operations.store=Lagrat DHTView.activity.title=Aktivitet DHTView.activity.status=Status DHTView.activity.status.true=K\u00f6ad DHTView.activity.status.false=K\u00f6rs DHTView.activity.type=Typ DHTView.activity.type.1=Intern 'Get' DHTView.activity.type.2=Extern 'Get' DHTView.activity.type.3=Intern 'Put' DHTView.activity.type.4=Extern 'Put' DHTView.activity.target=M\u00e5l DHTView.activity.details=Detaljer DHTView.db.title=Databas DHTView.db.keys=Nycklar DHTView.db.values=V\u00e4rden DHTView.db.local=Lokal DHTView.db.direct=Direkt DHTView.db.indirect=Indirekt DHTView.db.divfreq=Frekvens DHTView.db.divsize=Storlek MainWindow.dht.status.tooltip=N\u00e4r den distribuerade databasen k\u00f6rs visas h\u00e4r en uppskattning av uppkopplade anv\u00e4ndare. MainWindow.dht.status.disabled=DHT inaktiverad MainWindow.dht.status.failed=DHT misslyckades MainWindow.dht.status.initializing=DHT Initieras MainWindow.dht.status.users=%1 Anv\u00e4ndare MainWindow.dht.status.unreachable=DHT stoppad av brandv\u00e4gg MainWindow.dht.status.unreachabletooltip=Det verkar vara problem med den Distribuerande Databasens UDP portmappning (NAT/brandv\u00e4gg) MyTorrentsView.menu.setUpSpeed=Uppladdningshastighet MyTorrentsView.menu.setDownSpeed=Nedladdningshastighet ConfigView.section.tracker.client.showwarnings=Visa varningsmeddelanden fr\u00e5n trackers dht.advanced=Aktivera avancerade inst\u00e4llningar dht.advanced.group=Avancerade inst\u00e4llningar dht.advanced.label=Modifiera bara dessa v\u00e4rden om du verkligen vet vad du g\u00f6r dht.override.ip=\u00c5sidos\u00e4tt extern IP-address ConfigView.section.logging.loggerenable=Aktivera logging ConfigView.section.ipfilter.blockbanning=Bannlys hela serien p\u00e5 256 adresser om minst s\u00e5 h\u00e4r m\u00e5nga adresser i serien \u00e4r bannlysta MyTrackerView.passive=Passiv TableColumn.header.swarm_average_speed=Genomsnittshastighet i sv\u00e4rmen TableColumn.header.swarm_average_speed.info=Genomsnittshastighet i sv\u00e4rmen TableColumn.header.comment=Kommentar TableColumn.header.comment.info=Kommentar f\u00f6r nedladdning TableColumn.header.commenticon=Kommentarikon TableColumn.header.commenticon.info=Visar en ikon om anv\u00e4ndaren har angett en kommentar f\u00f6r nedladdningen MyTrackerView.category=Kategori MainWindow.menu.file.open.torrentfortracking=Torrentfile... (F\u00f6r tracking) MyTrackerView.date_added=Tillagd ConfigView.section.tracker.portbackup=Reservportar (Separeras med komma) ConfigView.label.playfilespeech=Tala om n\u00e4r en fil \u00e4r nedladdad ConfigView.label.playfilespeech.info=Taltj\u00e4nsten fungerar f\u00f6r n\u00e4rvarande b\u00e4st med engelska ConfigView.label.playfilefinished=Spela upp ett ljud n\u00e4r en fil \u00e4r nedladdad ConfigView.label.backupconfigfiles=S\u00e4kerhetskopiera konfigurationsfilerna i \u00e5terst\u00e4llningssyfte ConfigView.section.tracker.client.scrapesingleonly=Inaktivera skrapningsanhopning (Det kan avhj\u00e4lpa fel s\u00e5som "URL too long". dht.ipfilter.log=Logga IP-filter\u00f6vertr\u00e4delser ConfigView.label.seeding.addForSeedingDLCopyCount=St\u00e4ll hur m\u00e5nga g\u00e5nger en neddladdning skall tas ned innan den l\u00e4ggs till f\u00f6r uppladdning ActivityView.legend.limit=Hastighetsgr\u00e4ns ActivityView.legend.achieved=Uppn\u00e5dd hastighet ActivityView.legend.peeraverage=Genomsnitt ActivityView.legend.swarmaverage=Genomsnitt i sv\u00e4rmen MyTorrentsView.menu.movemenu=Flytta filer MyTorrentsView.menu.movedata=Flytta datafiler... MyTorrentsView.menu.movetorrent=Flytta torrentfil... MyTorrentsView.menu.movedata.dialog=V\u00e4lj ny plats DHTView.operations.data=Data DHTView.general.reachable=N\u00e5bar: DHTView.general.rendezvous=Rendezvous ConfigView.label.queue.maxactivetorrentswhenseeding=Max n\u00e4r du endast laddar upp [0:obegr\u00e4nsat] IrcView.title.short=IRC Views.plugins.IRC.title=IRC - teknisk support online Formats.units.persec=/sek Formats.units.TiB=TiB Formats.units.Tibit=Tibit Formats.units.TB=TB Formats.units.Tbit=Tbit Formats.units.GiB=GiB Formats.units.Gibit=Gibit Formats.units.GB=GB Formats.units.Gbit=Gbit Formats.units.MiB=MiB Formats.units.Mibit=Mibit Formats.units.MB=MB Formats.units.Mbit=Mbit Formats.units.KiB=KiB Formats.units.Kibit=Kibit Formats.units.kB=kB Formats.units.KB=KB Formats.units.kbit=kbit Formats.units.B=B Formats.units.bit=bit Formats.units.alot=Mycket! ConfigView.section.ipfilter.persistblocking=Spara detaljer om blockerade IP adresser mellan omstarter FilesView.menu.rename=Byt namn eller plats FilesView.menu.rename_only=Byt namn FilesView.menu.retarget=Byt plats FilesView.rename.choose.path=V\u00e4lj ny eller existerande fil FilesView.rename.choose.path.dir=V\u00e4lj ny eller existerande katalog FilesView.rename.confirm.delete.title=Bekr\u00e4fta Ta bort FilesView.rename.confirm.delete.text=Bekr\u00e4fta borttagning av originalfilen '%1' FilesView.rename.filename.title=Byt namn p\u00e5 filen FilesView.rename.filename.text=V\u00e4lj ett nytt namn f\u00f6r filen ConfigView.higher.mode.available=Fler alternativ \u00e4r tillg\u00e4ngliga i h\u00f6gre anv\u00e4ndarniv\u00e5er ConfigView.section.mode=L\u00e4ge ConfigView.section.mode.title=Anv\u00e4ndarkompetens ConfigView.section.mode.beginner=Nyb\u00f6rjare ConfigView.section.mode.beginner.wiki.definitions=Vokabul\u00e4r f\u00f6r BitTorrent ConfigView.section.mode.intermediate=Medel ConfigView.section.mode.intermediate.wiki.host=L\u00e4gga upp filer ConfigView.section.mode.intermediate.wiki.publish=Publicera filer ConfigView.section.mode.advanced=Avancerad ConfigView.section.mode.advanced.wiki.main=Wikis startsida ConfigView.section.mode.beginner.text=Allt du beh\u00f6ver f\u00f6r att ladda ned torrents. ConfigView.section.mode.intermediate.text=Tillg\u00e5ng till trackerfunktioner. ConfigView.section.mode.advanced.text=\u00c5tkomst till n\u00e4tverksinst\u00e4llningar.\nAnv\u00e4nd detta l\u00e4ge om du vet vad MTU eller "Non blocking I/O" \u00e4r... Files.column.storagetype=Lagringstyp Files.column.fileext=Typ FileItem.storage.linear=Linj\u00e4r FileItem.storage.compact=Kompakt MessageBoxWindow.rememberdecision=Kom ih\u00e5g mitt val ConfigView.section.interface.cleardecisions=Rensa tidigare dialogval ConfigView.section.interface.cleardecisionsbutton=Rensa ConfigView.section.interface.cleartrackers=Rensa tidigare trackers ConfigView.section.interface.cleartrackersbutton=Rensa ConfigView.section.interface.clearsavepaths=Rensa tidigare sparaplatser ConfigView.section.interface.clearsavepathsbutton=Rensa configureWizard.welcome.usermodes=Den h\u00e4r inst\u00e4llningen f\u00f6r anv\u00e4ndarkompetens p\u00e5verkar hur avancerade inst\u00e4llningar som visas i Vertyg->Inst\u00e4llningar. Det ligger i ditt eget intresse att st\u00e4lla in det r\u00e4tt (kan \u00e4ndras i efterhand). FilesView.skip.confirm.delete.text=Trunkera filen '%1' f\u00f6r att spara utrymme? FilesView.rename.failed.title=Byt namn/plats misslyckades FilesView.rename.failed.text=Operationen misslyckades, troligen beroende p\u00e5 felaktigt val av m\u00e5l diagnostics.log_found=Vuze st\u00e4ngdes inte ned ordentligt. Kolla om det finns n\u00e5gra diagnostikloggar och l\u00e4s \u00e4ven wikiartikeln Vuze Disappears f\u00f6r ytterliggare information. \u00d6verv\u00e4g att rapportera felet till Vuze om det \u00e4r ett resultat av ett applikationsfel. ManagerItem.paused=Pausad Utils.link.visit=G\u00e5 till ConfigView.section.connection.serverport.wiki=Bra portval ConfigView.section.transfer.speeds.wiki=Inst\u00e4llningar f\u00f6r bra hastighet installPluginsWizard.installMode.info.title=Information installPluginsWizard.installMode.info.text=Du beh\u00f6ver inte ha n\u00e5gra plugins f\u00f6r att Vuze skall fungera, de bidrar med extrafunktioner f\u00f6r automatisering, fj\u00e4rrkontroll eller bara f\u00f6r skojs skull.\nVar v\u00e4nlig och l\u00e4s beskrivningen f\u00f6r varje plugin innan du best\u00e4mmer dig f\u00f6r att installera det.\nDom flesta \u00e4r ofarliga att testa, men \u00f6verbelasta inte din konfiguration med plugin som du inte anv\u00e4nder.\n Views.plugins.Distributed.DB.title=Distribuerad databas Views.plugins.Distributed.Tracker.title=Distribuerad tracker Views.plugins.Plugin.Update.title=Pluginuppdatering Views.plugins.UPnP.title.tooltip=Universell Plug and Play openUrl.url.info=St\u00f6d f\u00f6r http-, https-, magnet- och hexstr\u00e4ngar TableColumn.header.swarm_average_completion=Genomsnittsantal klienter i sv\u00e4rmen som har laddat f\u00e4rdigt TableColumn.header.swarm_average_completion.info=Genomsnittsantal klienter i sv\u00e4rmen som har laddat f\u00e4rdigt GeneralView.label.swarm_average_completion=Medel: GeneralView.label.swarm_average_completion.tooltip=Medelv\u00e4rdet f\u00f6r antalet klienter i sv\u00e4rmen som laddat f\u00e4rdigt MainWindow.nat.status.unknown=NAT MainWindow.nat.status.tooltip.unknown=NAT (TCP) status ok\u00e4nt MainWindow.nat.status.ok=NAT OK MainWindow.nat.status.tooltip.ok=NAT OK (TCP) MainWindow.nat.status.probok=NAT OK? MainWindow.nat.status.tooltip.probok=NAT \u00e4r OK, du har dock inga inkommande TCP-anslutningar MainWindow.nat.status.bad=Blockerad av brandv\u00e4gg MainWindow.nat.status.tooltip.bad=M\u00f6jligt NAT(TCP)-problem, kolla i Wiki'n om det kvarst\u00e5r plugin.installer.recommended.plugin=Rekommenderat plugin - granska och installera om det kr\u00e4vs LoggerView.pause=Pausa loggning LoggerView.clear=&Rensa LoggerView.filter=Filter LoggerView.filter.uncheckAll=Avmarkera alla Kategorier LoggerView.filter.checkAll=Markera alla Kategorier LoggerView.loggingDisabled=Loggning \u00e4r inte aktiverad. LoggerView.includeOnly=Visa endast rader som matchar det h\u00e4r regulj\u00e4ra uttrycket: LoggerView.excludeAll=Visa inte rader som matchar det h\u00e4r regulj\u00e4ra uttrycket: ConfigView.section.logging.log0type=Information ConfigView.section.logging.log1type=Varning ConfigView.section.logging.log2type=Fel ConfigView.section.logging.filter=Anv\u00e4nt filter vid loggning till fil ConfigView.section.logging.level=Loggniv\u00e5 ConfigView.section.logging.showLogsFor=Visa %1 loggar f\u00f6r f\u00f6ljande kategorier: ConfigView.pluginlist.column.loadAtStartup=Ladda in n\u00e4r programmet startar ConfigView.pluginlist.column.type=Typ ConfigView.pluginlist.column.type.perUser=Per anv\u00e4ndare ConfigView.pluginlist.column.type.shared=Delad ConfigView.pluginlist.column.type.builtIn=Inbyggt ConfigView.pluginlist.column.name=Namn ConfigView.pluginlist.column.version=Version ConfigView.pluginlist.column.directory=Katalog ConfigView.pluginlist.column.isOperational=F\u00e4rdig? PeersView.BlockView.Avail.Have=B\u00e5da har PeersView.BlockView.Avail.NoHave=Klienten har men inte du PeersView.BlockView.NoAvail.Have=Du har men inte klienten PeersView.BlockView.NoAvail.NoHave=Ingen har PeersView.BlockView.Transfer=\u00d6verf\u00f6r PeersView.BlockView.NextRequest=N\u00e4sta beg\u00e4ran PeersView.BlockView.title=Filkarta PeersView.BlockView.AvailCount=Kalkylerad tillg\u00e4nglighet MyTorrentsView.dialog.NumberError.title=Ogiltigt eller ok\u00e4nt tal MyTorrentsView.dialog.NumberError.text=Ogiltigt eller ok\u00e4nt tal MyTorrentsView.menu.manual=&Manuellt... MyTorrentsView.menu.manual.per_torrent=Manuellt (per torrent) MyTorrentsView.menu.manual.shared_torrents=Manuellt (alla torrents) MyTorrentsView.dialog.setSpeed.title=St\u00e4ll in hastighet f\u00f6r %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Skriv in ett tal %1 att \u00e4ndra %2 till: MyTorrentsView.dialog.setNumber.upload=uppladdning MyTorrentsView.dialog.setNumber.download=nedladdning MyTorrentsView.dialog.setNumber.inKbps=i %1 OpenTorrentWindow.torrentLocation=Torrent-filer:\n(en torrent per rad) OpenTorrentWindow.addFiles.URL=L\u00e4gg till &adress OpenTorrentWindow.addFiles.Folder=L\u00e4gg till &katalog OpenTorrentWindow.addFiles.Clipboard=L\u00e4gg till fr\u00e5n &urklipp OpenTorrentWindow.changeDestination=\u00c4ndra destination OpenTorrentWindow.fileList=Filer in torrents: OpenTorrentWindow.torrentTable.name=Namn OpenTorrentWindow.torrentTable.saveLocation=Katalog att spara i OpenTorrentWindow.fileTable.fileName=Filnamn OpenTorrentWindow.fileTable.size=Storlek OpenTorrentWindow.fileTable.destinationName=Destination OpenTorrentWindow.startMode.seeding=Laddar upp OpenTorrentWindow.fileList.changeDestination=\u00c4ndra destination OpenTorrentWindow.mb.badSize.title=Inkompatibel fil OpenTorrentWindow.mb.badSize.text="%1" \u00e4r inte "%2" och kan inte anv\u00e4ndas f\u00f6r uppladdning OpenTorrentWindow.mb.alreadyExists.text=Torrent "%1" har redan lagts till som "%2" OpenTorrentWindow.mb.alreadyExists.title=Torrent existerar redan OpenTorrentWindow.mb.openError.title=Fel vid start OpenTorrentWindow.mb.openError.text="%1" kunde inte \u00f6ppnas:\n%2 OpenTorrentWindow.torrent.remove=Ta bort torrent fr\u00e5n listan OpenTorrentWindow.torrent.options=F\u00f6ljande inst\u00e4llningar kommer att appliceras p\u00e5 ovanst\u00e5ende torrents: OpenTorrentWindow.xOfTotal=(%1 av %2) iconBar.open.tooltip=\u00d6ppna en .torrent-fil LocaleUtil.column.text=Ok\u00e4nd text Tracker.tooltip.MultiSupport=Denna tracker har st\u00f6d f\u00f6r flera skrapningar per beg\u00e4ran. Tracker.tooltip.NoMultiSupport=Denna tracker har ej st\u00f6d f\u00f6r flera skrapningar per beg\u00e4ran. ConfigView.label.lazybitfield=Anv\u00e4nd "lazy bitfield" (hj\u00e4lper till vid uppladdning p\u00e5 n\u00e4tverk som anv\u00e4nder "bitfield-based blocking" LoggerView.realtime=Uppdatera i realtid ConfigView.section.file.perf.cache.flushpieces=Skriv f\u00e4rdiga delar direkt till h\u00e5rddisken. Det ger en j\u00e4mnare h\u00e5rddiskanv\u00e4ndning men kan resultera i fler skrivoperationer. ConfigView.section.file.writemblimit=Max k\u00f6ade skrivkommandon (i %1) ConfigView.section.file.writemblimit.explain=N\u00e4r skrivhastigheten till h\u00e5rddisken \u00e4r l\u00e4gre \u00e4n nedladdningshastigheten begr\u00e4nsar detta v\u00e4rde hur mycket data som skall k\u00f6as innan nedladdningshastigheten begr\u00e4nsas. ConfigView.section.file.readmblimit=Max k\u00f6ade l\u00e4skommandon (i %1) ConfigView.section.file.readmblimit.explain=V\u00e4rdet anger hur mycket minne som skall anv\u00e4ndas f\u00f6r att spara l\u00e4sningar som \u00e4r p\u00e5 k\u00f6 f\u00f6r att behandlas Button.moveUp=Flytta &upp Button.moveDown=Flytta &ned ConfigView.notAvailableForMode=Den h\u00e4r sektionen \u00e4r f\u00f6r anv\u00e4ndare med %1 kompetens eller h\u00f6gre.\nDen \u00e4r inte tillg\u00e4nglig om anv\u00e4ndarkompetens \u00e4r inst\u00e4llt p\u00e5 %2.\n(Du kan \u00e4ndra niv\u00e5n under rubriken "L\u00e4ge") health.explain.error=N\u00e5got \u00e4r fel med torrenten. Kontrollera statuskolumnen eller se tips (popupruta) p\u00e5 felikonen. GeneralView.label.trackerscrapeupdate=Skrapa tracker PeersView.piece=Del PeersView.piece.info=Senaste fildel som beg\u00e4rdes av klient PiecesView.priority=Prioritet PiecesView.priority.info=Detta visar vilken prioritet filen har att bli f\u00e4rdig. PiecesView.speed=Hastighet PiecesView.speed.info=L\u00e5ngsamma klienter hindras fr\u00e5n att st\u00f6ra snabbare delar TableColumn.header.AvgAvail.info=Summan av tillg\u00e4ngliga delar delat med # delar, delat med # anslutningar TableColumn.header.AvgAvail=Medeltillg\u00e4nglighet/del ConfigView.label.strictfilelocking=Enforce exclusive file write access locking across torrents MyTorrentsView.menu.checkfilesexist=Kontrollera att filerna finns MyTorrentsView.menu.rescanfile=Kontrollera inkompletta delar periodvis MyTorrentsView.menu.clear_resume_data=Rensa \u00e5terupptagningsinformation Plugin.extseed.name=Externa k\u00e4llor Plugin.localtracker.info="LAN peer finder" \u00e4r en funktion som till\u00e5ter att flera kopior av Vuze k\u00f6rs samtidigt bakom en brandv\u00e4gg f\u00f6r att snabbare kunna ladda ned torrents genom att etablera en direktanslutning mellan dom. Plugin.localtracker.enable=Aktivera "LAN peer finder" azinstancehandler.alert.portclash=%1 anv\u00e4nds redan av en annan Vuzeanv\u00e4ndare, v\u00e4lj ny(a) port(ar) f\u00f6r inkommande TCP/UDP-trafik [mellan %2 och %3]. ConfigView.section.transfer.lan=LAN ConfigView.section.transfer.lan.tooltip=LAN-specifika inst\u00e4llningar ConfigView.section.transfer.lan.uploadrate=KB/s LAN max uppladdningshastighet [0: Obegr\u00e4nsat] ConfigView.section.transfer.lan.uploadrate.tooltip=Klienter anslutna fr\u00e5n samma LAN har separata uppladdningsbegr\u00e4nsningar. ConfigView.section.transfer.lan.downloadrate=KB/s LAN max nedladdningshastighet [0: Obegr\u00e4nsat] ConfigView.section.transfer.lan.downloadrate.tooltip=Klienter anslutna fr\u00e5n samma LAN har separata nedladdningsbegr\u00e4nsningar. TorrentOptionsView.title.short=Inst\u00e4llningar TorrentOptionsView.title.full=Inst\u00e4llningar TorrentOptionsView.param.max.peers=Max antal anslutningar [0: Obegr\u00e4nsat] ConfigView.section.connection.encryption.require_encrypted_transport=Beg\u00e4r krypterad \u00f6verf\u00f6ring ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Tvinga krypterad anslutning ConfigView.section.connection.encryption.min_encryption_level=L\u00e4gsta krypteringsniv\u00e5 ConfigView.section.connection.encryption.min_encryption_level.tooltip=Plain - endast handskakning\nRC4 - full stream\nH\u00f6gre kryptering kr\u00e4ver mer processorkraft. Peers.column.Encryption=Kryptering Peers.column.Encryption.info=Krypteringsniv\u00e5 ConfigView.section.connection.encryption.encrypt.info=Om du v\u00e4ljer kryptering kan du inte ansluta till inkompatibla klienter s\u00e5vida du inte har en reservplan ConfigView.section.connection.encryption.encrypt.info.link=F\u00f6r ytterligare information, bes\u00f6k denna sida MainWindow.sr.status.tooltip.ok=Ratio %1 OK MainWindow.sr.status.tooltip.poor=Ratio %1 halvbra: < 0.9 MainWindow.sr.status.tooltip.bad=Ratio %1 d\u00e5lig: < 0.5 ConfigView.section.style.status=Statusf\u00e4lt: ConfigView.section.style.status.show_sr=Ratio ConfigView.section.style.status.show_nat=NAT-status ConfigView.section.style.status.show_ddb=DDB-status ConfigView.section.style.status.show_ipf=IP-Filterstatus ConfigView.section.connection.encryption.encrypt.group=Kryptering ConfigView.section.connection.encryption.encrypt.fallback_info=Om du l\u00e4gger till en reservplan kan du ansluta till inkompatibla klienter men det sker i s\u00e5 fall okrypterat ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Till\u00e5t okrypterad utg\u00e5ende anslutning om krypterad anslutning misslyckas ConfigView.section.connection.encryption.encrypt.fallback_incoming=Till\u00e5t okrypterade inkommande anslutningar ConfigView.section.connection.encryption=Kryptering upnp.selectedinterfaces=Valda gr\u00e4nssnitt (Separera med semikolon, t ex eth0;eth1) [tom: alla] ConfigView.section.style.defaultSortOrder=Standardsorteringsordning ConfigView.section.style.defaultSortOrder.desc=Fallande ConfigView.section.style.defaultSortOrder.asc=Stigande ConfigView.section.style.defaultSortOrder.flip=\u00c5t motsatt h\u00e5ll LoggerView.autoscroll=Automatisk rullning Button.selectAll=V\u00e4lj Alla Button.markSelected=Markera valda Button.unmarkSelected=Avmarkera valda plugins.basicview.config=Konfiguration TorrentOptionsView.param.max.uploads=Max antal uppladdningsplatser [Minimum: 2] MyTorrentsView.dialog.setPosition.title=V\u00e4lj position MyTorrentsView.dialog.setPosition.text=V\u00e4lj position f\u00f6r valda torrents: MyTorrentsView.menu.reposition.manual=Byt plats... ConfigView.section.connection.advanced.info.link=G\u00e5 till f\u00f6r ytterligare information ConfigView.section.connection.advanced.socket.group=Socket Options ConfigView.section.connection.advanced.bind_port=L\u00e5s till port [0: Inaktiverad] ConfigView.section.connection.advanced.bind_port.tooltip=Utg\u00e5ende anslutningar l\u00e5ses lokalt till vald port.\nDetta kan hj\u00e4lpa till om routern beter sig instabilt. ConfigView.section.proxy.group.tracker=Tracker ConfigView.section.proxy.group.peer=Klienter Pieces.column.Requested=Beg\u00e4rt Pieces.column.Requested.info=Visar om flera beg\u00e4ran kan g\u00f6ras f\u00f6r delen (*) ConfigView.label.maxuploadsseeding=Annan standard n\u00e4r du laddar upp MyTorrentsView.filter=Filter: popup.error.hideall=D\u00f6lj alla ConfigView.section.style.dataStatsOnly=Visa endast datastatistik (G\u00f6m protokollstatistik) ConfigView.section.style.separateProtDataStats=Separarera statistik f\u00f6r data och protokoll s\u00e5 h\u00e4r: "Data (Protokoll)" MyTorrentsView.dialog.setFilter.title=\u00c4ndra filter MyTorrentsView.dialog.setFilter.text=%1 kommer att filtreras med nedan angiven text. Anv\u00e4nd tecknet | f\u00f6r att separera fraser. MyTorrentsView.filter.tooltip=Anv\u00e4nd Ctrl+X f\u00f6r att byta mellan RegEx och normalt l\u00e4ge.\nAnv\u00e4nd tecknet | f\u00f6r att separera fraser. MyTorrentsView.clearFilter.tooltip=Rensa filter MyTorrentsView.menu.filter=Filter... ConfigView.section.file.resume.recheck.all=Vid onstart efter krash kontrollera alla delar i hela filen (Annars kontrolleras endast delar som var aktiva n\u00e4r Spara utf\u00f6rdes senast) ConfigureWizard.language.choose=V\u00e4lj ett spr\u00e5k i listan: popup.closing.in=F\u00f6nstret st\u00e4ngs automatiskt om %1 sekunder popup.more.waiting=%1 meddelande(n) till.. # > 2402 popup.download.finished=H\u00e4mtningen av "%1" \u00e4r slutf\u00f6rd. popup.file.finished=H\u00e4mtningen av "%1" \u00e4r slutf\u00f6rd. ConfigView.auto=Auto Plugin.localtracker.autoadd.info=L\u00e4gg till dessa lokala klienter automatiskt [separera adresserna med semikolon, 1.2.3.4] Plugin.localtracker.autoadd=Automatiskt tillagda klienter Plugin.localtracker.networks.info=Betrakta f\u00f6ljande n\u00e4tverk som lokala [separera med semikolon, 145.227.*.*] Plugin.localtracker.networks=Lokala n\u00e4tverk MainWindow.menu.view.plugins.logViews=Loggvisningar SpeedView.stats.autospeed=Automatisk uppladdningshastighet SpeedView.stats.autospeed.disabled=Denna funktion \u00e4r antingen inaktiverad (du beh\u00f6ver DHT) eller inte i bruk (manuell uppladdningshastighet vald). SpeedView.stats.idlePing=Ping vid inaktivitet: SpeedView.stats.currentPing=Nuvarande Ping: SpeedView.stats.maxUp=Max uppladdningshastighet: ConfigView.pluginlist.unloadSelected=Ladda ur markerad ConfigView.pluginlist.scan=S\u00f6k efter nya plugins ConfigView.section.transfer.autospeed=Auto-Speed (Klassisk) ConfigView.section.transfer.autospeed.tooltip=Inst\u00e4llningar f\u00f6r Auto-speed ConfigView.section.transfer.autospeed.info=Auto-speed justerar automatiskt uppladdningshastigheten f\u00f6r att undvika att n\u00e4tverket blir \u00f6verbelastat.\n\nDessa begr\u00e4nsningar fungerar endast n\u00e4r automatisk uppladdninghastighet och den distribuerande databasen \u00e4r aktiverad. ConfigView.section.transfer.autospeed.minupload=%1 min uppladdningshastighet ConfigView.section.transfer.autospeed.minupload.tooltip=Uppladdningshastigheten kommer inte automatiskt att sjunka under detta v\u00e4rde ConfigView.section.transfer.autospeed.maxupload=%1 max uppladdningshastighet [0: Obegr\u00e4nsat] ConfigView.section.transfer.autospeed.maxupload.tooltip=Uppladdningshastigheten kommer inte automatiskt att stiga \u00f6ver detta v\u00e4rde ConfigView.section.transfer.autospeed.chokeping=Choking ping time [ms] ConfigView.section.transfer.autospeed.chokeping.tooltip=Om pingtiden \u00f6verstiger detta v\u00e4rde antas det att n\u00e4tverket \u00e4r fullbelastat ConfigView.section.transfer.autospeed.enableauto=Aktivera vid nedladdning och uppladdning ConfigView.section.transfer.autospeed.enableautoseeding=Aktivera n\u00e4r endast uppladdning sker ConfigView.pluginlist.column.unloadable=Kan laddas ur ConfigView.section.transfer.lan.enable=Aktivera hastighetsbegr\u00e4nsningar f\u00f6r LAN-anslutningar TableColumn.header.filesdone=F\u00e4rdiga filer TableColumn.header.filesdone.info=F\u00e4rdigt antal filer/Totalt antal filer MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=v\u00e4ntar p\u00e5 DDB-initialisering... MagnetPlugin.report.searching=s\u00f6ker... MagnetPlugin.report.found=funnet %1 MagnetPlugin.report.alive=%1 lever MagnetPlugin.report.dead=%1 \u00e4r d\u00f6d MagnetPlugin.report.tunnel=skickar till %1 MagnetPlugin.report.downloading=laddar ned fr\u00e5n %1 MagnetPlugin.report.error=fel %1 MagnetURLHandler.report.no_sources=inga k\u00e4llor funna MagnetURLHandler.report.torrent_size=storlek: %1 MagnetURLHandler.report.percent=f\u00e4rdig: %1% MagnetURLHandler.report.error=fel %1 DHTTransport.report.request_all=beg\u00e4r hela \u00f6verf\u00f6ringen fr\u00e5n %1 DHTTransport.report.received_bit=mottagit %1 till %2 fr\u00e5n %3 DHTTransport.report.complete=komplett DHTTransport.report.timeout=timeout, inget svar fr\u00e5n %1 DHTTransport.report.rerequest_all=beg\u00e4r p\u00e5 nytt hela \u00f6verf\u00f6ringen fr\u00e5n %1 DHTTransport.report.rerequest_bit=beg\u00e4r p\u00e5 nytt %1 till %2 fr\u00e5n %3 DHTTransport.report.timeout_some=timeout, %1 paket mottagna fr\u00e5n %2 men ej kompletta DHTTransport.report.sending=s\u00e4nder data DHTTransport.report.resending=s\u00e4nder data p\u00e5 nytt DHTTransport.report.send_complete=s\u00e4ndning f\u00e4rdig DHTTransport.report.send_timeout=timeout vid s\u00e4ndning ConfigView.section.transfer.autospeed.enabledebug=Logga debug-information TableColumn.header.date_added=Tillagd TableColumn.header.date_added.info=Vilket datum torrenten lades till ConfigView.section.file.hashchecking.smallestfirst=Kontrollera de minsta nedladdningarna f\u00f6rst platform.win32.baddll.info=Vuze har uppt\u00e4ckt att "%1" \u00e4r installerat. Det \u00e4r den del av "%2" och \u00e4r k\u00e4nt f\u00f6r att skapa stora problem s\u00e5som programkrascher och h\u00f6g CPU anv\u00e4ndning. Om n\u00e5gra problem uppst\u00e5r b\u00f6r du avinstallera programmet eller konfigurera det s\u00e5 att inte st\u00f6r Vuze. upnp.ignorebaddevices=Ignorera enheter som inte svarar korrekt upnp.ignorebaddevices.info=Ignorerade enheter: %1 upnp.ignorebaddevices.reset=\u00c5terst\u00e4ll listan \u00f6ver ignorerade enheter upnp.ignorebaddevices.reset.action=\u00c5terst\u00e4ll upnp.ignorebaddevices.alert=UPnP-enhet p\u00e5 position %1 ignoreras p\u00e5 grund av flera felaktigheter. Se inst\u00e4llningar f\u00f6r UPnP-pluginen f\u00f6r alternativ. TorrentOptionsView.param.max.uploads.when.busy=KB/s max uppladdningshastighet n\u00e4r maxhastigheten totalt \u00e4r uppn\u00e5dd [0: Inaktiverad] UpdateMonitor.messagebox.verification.failed.title=Verifikationen av installationen misslyckades UpdateMonitor.messagebox.verification.failed.text=Verifikation av "%1" misslyckades: %2 UpdateMonitor.messagebox.accept.unverified.title=Acceptera overifierad installation UpdateMonitor.messagebox.accept.unverified.text="%1" \u00e4r troligen inte ett officiellt plugin till Vuze.\nDu b\u00f6r inte forts\u00e4tta.\nVill du trots det forts\u00e4tta? FileView.BlockView.title=Fildelar FileView.BlockView.Done=F\u00e4rdig FileView.BlockView.Skipped=\u00d6verhoppad FileView.BlockView.Active=Aktiv ConfigView.label.tcplistenport=Inkommande TCP-port ConfigView.label.udplistenport=Inommande UDP-port upnp.portchange.alert=F\u00f6ljande portar har \u00e4ndrats f\u00f6r att undvika problem med UPnP-enheter: %1 [tidigare port=%2] %3 [tidigare port=%4] ConfigView.section.proxy.username.info=Anv\u00e4nd str\u00e4ngen "" aom anv\u00e4ndarnamn om proxyserver kr\u00e4ver autenticering, . ConfigView.label.maxuploadswhenbusymin=Max uppladdningshastighet when busy timer [sec] MainWindow.menu.help.debug=Generera Debug Info (Crash Log) DownloadManager.error.badsize=Felaktig storlek ConfigView.section.NATPMP=NAT-PMP natpmp.info=NAT-PMP \u00e4r Apples motsvarighet till UPnP och st\u00f6ds av senare Airportstationer. natpmp.enable=Aktivera (Observera att du \u00e4ven m\u00e5ste aktivera i Airport) ConfigView.section.tracker.host.addurls=Se till att denna trackerns adress finns i torrentinformationen ConfigView.filter=S\u00f6k efter inst\u00e4llningar ConfigView.section.files.move=Flytta n\u00e4r f\u00e4rdigladdat ConfigView.section.file.defaultdir.section=Standardkataloginst\u00e4llningar ConfigView.section.file.defaultdir.auto=Ladda automatiskt ned till standardkatalogen ConfigView.section.file.defaultdir.bestguess=Anv\u00e4nd den mest anv\u00e4nda vid val av standardkatalog f\u00f6r nedladdning ConfigView.section.file.defaultdir.ask=Standardkatalog: ConfigView.section.file.defaultdir.lastused=S\u00e4tt standardkatalog till den katalog du senast laddade ned till ConfigView.section.file.config.section=Konfigurationsinst\u00e4llningar ConfigView.section.file.config.currentdir=Vald konfigurationskatalog: ConfigView.section.torrent.decoding=Teckenkodningstabell ConfigView.section.logging.udptransport=Aktivera ut\u00f6kad sp\u00e5rning av UDP-\u00f6verf\u00f6rng Tracker.announce.ignorePeerSeed=Ignorera klient/k\u00e4llresultat. %1 ConfigView.section.connection.encryption.use_crypto_port=Anv\u00e4nd 'cryptoport' f\u00f6r att f\u00f6rhindra anv\u00e4ndning av 'plain' vid inkommande anslutningsf\u00f6rs\u00f6k.\nVissa trackers till\u00e5ter inte detta utan ger felmeddelanden som "Invalid Port" eller "Illegal Argument" TorrentOptionsView.param.reset.to.default=\u00c5terst\u00e4ll inst\u00e4llningarna till deras standardv\u00e4rden TorrentOptionsView.param.reset.button=\u00c5terst\u00e4ll natpmp.routeraddress=Stationsadress [Tom: automatiskt] ConfigView.section.style.disableAlertSliding=Inaktivera animering f\u00f6r varningsmeddelanden ConfigView.section.transfer.autospeed.maxinc=%1 max \u00f6kning per cykel ConfigView.section.transfer.autospeed.maxdec=%1 max reducering per cykel ConfigView.section.transfer.autospeed.enabledownadj=Aktivera justering av nedladdningshastighet ConfigView.section.transfer.autospeed.downadjratio=F\u00f6rh\u00e5llande ned/uppladdningshastighet (t ex 2.0 -> Nedladdningshastighet \u00e4r dubbelt s\u00e5 h\u00f6g som uppladdningshastighet ConfigView.section.transfer.autospeed.reset=\u00c5terst\u00e4ll avancerade v\u00e4rden ConfigView.section.transfer.autospeed.reset.button=\u00c5terst\u00e4ll PeerColumn.activationCount=Klienter som f\u00f6rs\u00f6ker att ansluta: %1 TableColumn.header.timesincedownload.info=Tiden senast n\u00e5got laddades ned f\u00f6r denna torrent TableColumn.header.timesincedownload=Ingen nedladdning p\u00e5g\u00e5r TableColumn.header.timesinceupload.info=Tiden senast n\u00e5got laddades upp f\u00f6r denna torrent TableColumn.header.timesinceupload=Ingen uppladdning p\u00e5g\u00e5r PeersView.incomingreqcount=Beg\u00e4rt in PeersView.incomingreqcount.info=Beg\u00e4rt av klient PeersView.outgoingreqcount=Beg\u00e4rt ut PeersView.outgoingreqcount.info=Beg\u00e4rt av klient upnp.mapping.trackerclientudp=UDP Tracker klientport upnp.mapping.dhtudp=Distribuerad databas ConfigView.section.connection.nondata.udp.same=Anv\u00e4nd samma UDP-port f\u00f6r den distribuerande databasen och UDP-trackern ConfigView.section.connection.tcp.enable=Aktivera TCP ConfigView.section.connection.udp.enable=Aktivera UDP ConfigView.section.style.showiconbar=Visa verktygsrad MainWindow.menu.view.iconbar=Verktygsf\u00e4lt MyTorrentsView.menu.rename=Byt namn MyTorrentsView.menu.rename.displayed=Byt Visningsnamn MyTorrentsView.menu.rename.save_path=Byt namn p\u00e5 m\u00e5lkatalog MyTorrentsView.menu.rename.displayed.enter.title=Byt Visningsnamn MyTorrentsView.menu.rename.displayed.enter.message=Skriv nytt namn f\u00f6r denna nedladdning\nOm inget skrivs anv\u00e4nds det ursprungliga namnet MyTorrentsView.menu.edit_comment=Ange kommentar MyTorrentsView.menu.edit_comment.enter.title=Ange kommentar MyTorrentsView.menu.edit_comment.enter.message=Skriv en kommentar f\u00f6r nedladdningen/nedladdningarna h\u00e4r. UIDebugGenerator.messageask.text=Fyll i en beskrivning av felet du vill rapportera UIDebugGenerator.complete.title=Debugging f\u00e4rdig UIDebugGenerator.complete.text=Var v\u00e4nlig s\u00e4nd filen "%1".\n\nKlicka p\u00e5 Ok f\u00f6r att \u00f6ppna ett nytt f\u00f6nster med filen. ConfigView.section.style.showProgramIcon=Visa programikon i namnkolumnen ConfigView.section.style.showProgramIcon.tooltip=Du kanske m\u00e5ste \u00f6ppna p\u00e5 nytt f\u00f6r att \u00e4ndringarna skall fungera swt.alert.cant.update=SWT-bibliotek laddat fr\u00e5n "%3" kan inte automatiskt uppdateras fr\u00e5n version %1 till %2 (m\u00e5ste laddas fr\u00e5n "%4"). G\u00e5 till wikisidanSWT Can't Auto Update f\u00f6r ytterligare information. authenticator.savepassword=Kom ih\u00e5g mitt l\u00f6senord ConfigView.section.security.clearpasswords=\u00c5terst\u00e4ll sparat l\u00f6senord ConfigView.section.security.clearpasswords.button=\u00c5terst\u00e4ll Content.alert.notuploaded.title=Uppladdning ofullst\u00e4ndig Content.alert.notuploaded.text='%1' \u00e4r inte f\u00e4rdigladdad. Om du %2 nu kommer inte klienterna att kunna ladda ned hela materialet. Content.alert.notuploaded.multi.title=Ofullst\u00e4ndigt material Content.alert.notuploaded.multi.text=%1 av ditt publicerade material \u00e4r ej komplett uppladdat. Om du %2 nu kommer inte klienterna att kunna ladda ned hela materialet. \u00c4r du s\u00e4ker p\u00e5 att du vill %2?\n\nOfullst\u00e4ndig m\u00e4ngd:\n%3 Content.alert.notuploaded.stop=Stoppa Content.alert.notuploaded.quit=St\u00e4ng Vuze TorrentInfoView.torrent.encoding=Kodning TorrentInfoView.columns=Kolumner progress.window.title=\u00c5tg\u00e4rder progress.window.msg.filemove=Var v\u00e4nlig och v\u00e4nta medans flytt/omd\u00f6pning av fil(er) utf\u00f6rs ConfigView.label.popup.timestamp=Visa tid p\u00e5 varningar ConfigView.label.popup.autohide=G\u00f6m automatiskt popupf\u00f6nster som inte \u00e4r felmeddelanden (s\u00e4tt 0 f\u00f6r att koppla bort funktionen) ConfigView.label.popup.suppress_alerts=Visa inte varningar ConfigView.label.popup.show=Visa alla popupvarningar som loggats hittills ConfigView.label.popup.show.button=Visa ConfigView.label.please.visit.here=F\u00f6r ytterligare information: ConfigView.section.ipfilter.enable.descriptionCache=Lagra IP-beskrivningar i buffert ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Beskriivningar kommer inte att sparas om funktionen \u00e4r avaktiverad OpenTorrentWindow.filesInfo=%1 av %2 kommer att laddas ned OpenTorrentWindow.diskUsage=%1 av %2 ConfigView.label.openmytorrents=Visa "Mina torrents" n\u00e4r programmet startas ConfigView.label.open_transfer_bar_on_start=Visa \u00f6verf\u00f6ringf\u00e4ltet n\u00e4r programmet startas ConfigView.section.style.DNDalwaysInIncomplete=Visa alltid torrents med filer som ej skall laddas ned som inkompletta i "Mina torrents" OpenTorrentWindow.mb.noGlobalDestDir.title=M\u00e5lkatalog OpenTorrentWindow.mb.noGlobalDestDir.text=M\u00e5lkatalogen "%1" \u00e4r ogiltig. OpenTorrentWindow.mb.noDestDir.title=M\u00e5lkatalog ej funnen OpenTorrentWindow.mb.noDestDir.text=M\u00e5lkatalogen "%1" f\u00f6r torrent "%2" finns inte eller \u00e4r ogiltig. OpenTorrentWindow.mb.notValid.title=\u00d6ppna torrent OpenTorrentWindow.mb.notValid.text=Kunde inte \u00f6ppna torrent '%1'. Om du \u00f6ppnar i uppladdningsl\u00e4ge m\u00e5ste du se till att datafilerna finns. OpenTorrentWindow.mb.notTorrent.title=\u00d6ppna torrent OpenTorrentWindow.mb.notTorrent.text=Kunde inte \u00f6ppna '%1'. Det verkar inte vara en giltig .torrentfil.\n\nMottagen data:\n%2 ConfigView.label.pause.downloads.on.exit=Pausa nedladdningar n\u00e4r programmet st\u00e4ngs ConfigView.label.resume.downloads.on.start=\u00c5teruppta pausade nedladdningar efter initialisation n\u00e4r programmet startas UIDebugGenerator.message.cancel.title=Debugging avbruten UIDebugGenerator.message.cancel.text=Du har inte fyllt i en beskrivning av felet som du vill rapportera.Felet \u00e4r kanske uppenbart f\u00f6r dig, men utan en riktig beskrivning kan vi bara gissa oss var felet ligger.\n\nOperationen avbryts. ConfigView.section.connection.group.http=HTTP ConfigView.section.connection.group.http.info=St\u00f6d f\u00f6r HTTP-uppladdning. ConfigView.section.connection.http.enable=Till\u00e5t ConfigView.section.connection.http.port=Inkommande portnummer ConfigView.section.connection.http.portoverride=\u00c4sidos\u00e4tt port f\u00f6r Tracker HTTP [0: none] window.update.noupdates.title=Resultat f\u00f6r s\u00f6kning efter uppdateringar window.update.noupdates.text=Det finns inga uppdateringar tillg\u00e4ngliga. ConfigView.label.mindownloads=Min samtidiga nedladdningar UI.cannot_submit_blank_text=Du m\u00e5ste fylla i ett v\u00e4rde. crypto.alert.as.warning=N\u00e4tverket '%1' \u00e4r k\u00e4nt f\u00f6r att begr\u00e4nsa trafiken. Kryptering har automatiskt aktiverats. Detta kan st\u00e4ngas av eller modifieras i inst\u00e4llningarna. ConfigView.section.interface.alerts=Varningar ConfigView.label.popupdownloadadded=Visa n\u00e4r en nedladdning l\u00e4ggs till popup.download.added="%1" har lagts till din nedladdningslista. MessageBoxWindow.nomoreprompting=Fr\u00e5ga mig inte om detta igen TorrentOptionsView.param.max.seeds=Max antal anslutningar till k\u00e4llor [0: Anslutningsbegr\u00e4nsning] TorrentOptionsView.param.alternative.value.enable=Alternativt v\u00e4rde n\u00e4r du endast laddar upp ConfigView.section.proxy.check.on.start=Kontrollera status f\u00f6r proxy n\u00e4r programmet startar TransferStatsView.legend.pingaverage=Genomsnitt TransferStatsView.legend.ping1=M\u00e5l 1 TransferStatsView.legend.ping2=M\u00e5l 2 TransferStatsView.legend.ping3=M\u00e5l 3 ConfigView.section.interface.enabletray._mac=Visa ikon i statusf\u00e4ltet [Omstart kr\u00e4vs] ConfigView.label.closetotray._mac=St\u00e4ng minimerar till statusf\u00e4ltet ConfigView.label.minimizetotray._mac=Minimera minimerar till statusf\u00e4ltet OpenTorrentWindow.mb.existingFiles.title=Filen/filerna finns redan! OpenTorrentWindow.mb.existingFiles.text=Vissa filer finns redan i den katalog fu vill spara i:\n\n%1\nOm du forts\u00e4tter kommer Vuze att kontrollera filerna och skriva \u00f6ver de som inte inneh\u00e5ller korrekt data. splash.unloadingTorrents=Tar bort torrents splash.unloadingTorrent=Tar bort torrent ConfigView.section.file.defaultdir.autorename=Byt namn automatiskt p\u00e5 torrentdata om filerna ser olika ut ConfigView.section.file.defaultdir.autorename.tooltip=Detta f\u00f6rhindrar att en torrent skriver \u00f6ver en annan torrent n\u00e4r de har samma namn alert.raised.at.close=(Meddelande fr\u00e5n en tidigare st\u00e4ngning av programmet) Plugin.trackerpeerauth.name=Klientauktorisation Plugin.trackerpeerauth.info=Detta plugin arbetar med trackers f\u00f6r att verifiera att klienterna \u00e4r giltiga medlemmar i sv\u00e4rmen Peers.column.maxupspeed=Max uppladdningshastighet Peers.column.maxdownspeed=Max nedladdningshastighet MyTorrents.items.DownSpeedLimit.disabled=Ingen nedladdning Peers.column.lan=LAN upnp.selectedaddresses=Adresser (Separera med semikolon, "-"=till\u00e5t ej, "+" =till\u00e5t) [tomt: alla] upnp.alert.multipledevice.warning=Flera UPnP-enheter har uppt\u00e4ckts - kontrollera om alla beh\u00f6ver portmappning (Se UPnP-loggen och inst\u00e4llningarna) UpdateMonitor.messagebox.restart.title=Uppdatering av mjukvara UpdateMonitor.messagebox.restart.text=Vuze har precis slutf\u00f6rt nedladdningen av en viktig uppdatering och m\u00e5ste nu startas om f\u00f6r att uppdateringen skall installeras. PiecesView.BlockView.Have=Har PiecesView.BlockView.NoHave=Har inte PiecesView.BlockView.Header=%1 kolumn(er), %2 rad(er), %3 delar ConfigView.section.update.autodownload=Ladda ned uppdateringar automatiskt och fr\u00e5ga om de skall installeras Peers.column.peer_id=Klient-ID Peers.column.peer_id.info=Klient-ID i textformat Peers.column.peer_byte_id=Klient-ID Peers.column.peer_byte_id.info=Klient-ID i digital form Peers.column.handshake_reserved=Reserverat i handskakning Peers.column.handshake_reserved.info=Visar vad som \u00e4r reserverat i handskakning Peers.column.client_identification=Klientidentification Peers.column.client_identification.info=Visar r\u00e5data om klientnamn som Vuze mottagit - anv\u00e4ndbart f\u00f6r debugging dht.warn.user=Varna vid potentiella NAT/portmappnings problem ConfigView.label.openbar.incomplete=Nedladdningsrutor: \u00d6ppna nedladdningar automatiskt ConfigView.label.openbar.complete=\u00d6ppna uppladdningar automatiskt ConfigView.label.transferbar.remember_location=Kom ih\u00e5g senaste postitionen p\u00e5 \u00f6verf\u00f6ringsf\u00e4ltet MainWindow.menu.tools.speedtest=Hastighetstest... speedtest.wizard.title=Hastighetstest speedtest.wizard.run=Utf\u00f6r ett hastighetstest speedtest.wizard.test.mode.updown=upp- och nedladdning speedtest.wizard.test.mode.up=uppladdning speedtest.wizard.test.mode.down=nedladdning SpeedTestWizard.test.panel.currinfo=Bandbreddstest SpeedTestWizard.test.panel.label=Vuze hastighetstest SpeedTestWizard.test.panel.already.running=Testet k\u00f6rs redan! SpeedTestWizard.test.panel.not.accepted=Testbeg\u00e4ran inte accepterad: SpeedTestWizard.test.panel.abort=Avbryt SpeedTestWizard.test.panel.abort.countdown=avbryter om: SpeedTestWizard.test.panel.test.countdown=testet avslutas om: SpeedTestWizard.test.panel.testfailed=Testet misslyckades SpeedTestWizard.test.panel.aborted=Testet manuellt avbrutet SpeedTestWizard.test.panel.enc.label=V\u00e4lj test med kryptering SpeedTestWizard.test.panel.encrypted=krypterat SpeedTestWizard.set.upload.button.apply=&Verkst\u00e4ll SpeedTestWizard.set.upload.result=Senaste testresultat SpeedTestWizard.set.upload.bytes.per.sec=kBytes/sek SpeedTestWizard.set.upload.bits.per.sec=bits/sek SpeedTestWizard.finish.panel.title=Hastighetstest f\u00e4rdigt! SpeedTestWizard.finish.panel.click.close=Guiden \u00e4r f\u00e4rdig. Klicka p\u00e5 st\u00e4ng f\u00f6r att avsluta. SpeedTestWizard.finish.panel.max.upload=Max upp: SpeedTestWizard.finish.panel.max.seeding.upload=Max uppladdning n\u00e4r du inte laddar ner: SpeedTestWizard.finish.panel.max.download=Max nedladdning: SpeedTestWizard.finish.panel.enabled=aktiverad SpeedTestWizard.finish.panel.disabled=inaktiverad SpeedTestWizard.abort.message.scheduled.in=Testet b\u00f6rjar om ... %1 sekunder SpeedTestWizard.abort.message.unsupported.type=Felaktig testtyp!!!! SpeedTestWizard.abort.message.manual.abort=Avbr\u00f6ts av anv\u00e4ndare SpeedTestWizard.abort.message.scheduling.failed=Schemal\u00e4ggning misslyckades SpeedTestWizard.abort.message.download.added=Nedladdning %1 tillagd under test SpeedTestWizard.abort.message.entered.error=Testnedladdning gav felkod "%1" SpeedTestWizard.abort.message.entered.queued=Testnedladdning gick in i k\u00f6at/stoppat l\u00e4ge SpeedTestWizard.abort.message.interrupted="TorrentSpeedTestMonitorThread" avbr\u00f6ts innan test kunde slutf\u00f6ras SpeedTestWizard.abort.message.execution.failed=Test misslyckades SpeedTestWizard.abort.message.failed.peers=Kunde inte ansluta till n\u00e5gra klienter SpeedTestWizard.abort.message.insufficient.slots=Kunde inte ladda upp till n\u00e5gra klienter SpeedTestWizard.abort.message.not.unchoked=Kunde inte ladda ned fr\u00e5n n\u00e5gra klienter SpeedTestWizard.stage.message.requesting=beg\u00e4r test... SpeedTestWizard.stage.message.preparing=f\u00f6rbereder test... SpeedTestWizard.stage.message.starting=startar test... SpeedTestWizard.stage.message.connect.stats=Anslutningsstatistik: klienter=%1, ned, ok=%2, upp, ok=%3 window.uiswitcher.title=Vuze UI-v\u00e4ljaren window.uiswitcher.text=V\u00e4lj det gr\u00e4nssnitt som passar dig b\u00e4st window.uiswitcher.NewUI.text=* Rekommenderas f\u00f6r nyb\u00f6rjare.\n\n* Enkelt, intuitivt grafiskt gr\u00e4nssnitt.\n\n* Det h\u00e4r gr\u00e4nssnittet kr\u00e4vs f\u00f6r att kunna publicera p\u00e5 Vuze. window.uiswitcher.ClassicUI.title=Klassiskt utseende window.uiswitcher.ClassicUI.text=* Bibeh\u00e5ller funktionaliteten f\u00f6r klienter version 2.x\n\n* Vuze kommer inte att laddas in window.uiswitcher.bottom.text=Ditt val kan enkelt \u00e4ndras igen genom att klicka p\u00e5 "Vuze UI-v\u00e4ljaren" knappen. iconBar.switch.tooltip=Vuze UI-v\u00e4ljaren VivaldiView.notAvailable=Visningsl\u00e4ge Vivaldi inte tillg\u00e4ngligt restart.error=Omstart misslyckades:\n%1\nSe mer: restarting issues. restart.error.oom=F\u00f6r litet minne restart.error.fnf="%1" hittades inte i "%2" restart.error.pnf=S\u00f6kv\u00e4g "%1" hittades inte restart.error.bad=Fel filformat f\u00f6r '%1' restart.error.denied=Det gick inte att starta "%1". Se till att du har r\u00e4ttighet att k\u00f6ra programmet. TableColumn.header.date_completed=Slutf\u00f6rdes TableColumn.menu.date_added.reset=\u00c5terst\u00e4ll datum ConfigView.section.ipfilter.discardbanning=Blockera klienter vars ratio \u00f6verstiger [0: Inaktiverad] ConfigView.section.ipfilter.discardminkb=Minst %1 bortkastat f\u00f6re ratiokrav anv\u00e4nds ConfigView.interface.start.advanced=Starta i Avancerat l\u00e4ge (AZ 2.x) MyTorrents.column.ColumnQuality=Kvalitet MyTorrents.column.ColumnSpeed=Hastighet MyTorrents.column.ColumnProgressETA.2ndLine=F\u00e4rdigt: %1 %2 MyTorrents.column.ColumnProgressETA.StreamReady=F\u00e4rdig f\u00f6r streaming om %1 MyTorrents.column.ColumnProgressETA.PlayableIn=Spelbart om %1 %2 TableColumn.header.Quality=Kvalitet TableColumn.header.Speed=Hastighet TableColumn.header.RateIt=Gradering TableColumn.header.Rating=Gradering TableColumn.header.SpeedGraphic=Hastighet TableColumn.header.AzProduct=Fr\u00e5n TableColumn.header.ProgressETA=F\u00f6rlopp #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=Filtyp: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} TableColumn.header.DateCompleted=Slutf\u00f6rdes v3.MainWindow.tab.library=Bibliotek v3.MainWindow.tab.publish=Publicera v3.MainWindow.tab.advanced=Avancerad v3.MainWindow.menu.library=&Bibliotek v3.MainWindow.menu.publish=&Publicera v3.MainWindow.menu.advanced=&Avancerad v3.MainWindow.menu.view.searchbar=S\u00f6kf\u00e4lt v3.MainWindow.menu.view.tabbar=Flikar v3.MainWindow.currentDL=P\u00e5g\u00e5ende nedladdningar v3.MainWindow.button.stream=Str\u00f6mma v3.MainWindow.button.stop=Stoppa v3.MainWindow.button.start=Starta v3.MainWindow.button.pause=Paus v3.MainWindow.button.resume=Forts\u00e4tt v3.MainWindow.button.delete=Radera v3.MainWindow.button.comment=Kommentar v3.MainWindow.button.viewdetails=Visa Detaljer v3.MainWindow.button.play=Spela Upp v3.MainWindow.button.cancel=Avbryt v3.MainWindow.button.preview=F\u00f6rhandsvisning v3.MainWindow.view.wait=Initialiserar vy, v\u00e4nligen v\u00e4nta... v3.MainWindow.xofx=%1 av %2 v3.MainWindow.Loading=Laddar... V\u00e4nligen v\u00e4nta v3.filter-bar=Titelfilter: v3.MainWindow.search.defaultText=S\u00f6k i Vuze... v3.mb.delPublished.title=Stoppa uppladdning v3.mb.delPublished.text=VARNING: Detta tar INTE bort ditt publicerade inneh\u00e5ll "%1" fr\u00e5n %3.\n\nKlicka p\u00e5 "Radera" om du vill beh\u00e5lla ditt material publicerat och nedladdningsbart, men bara frig\u00f6ra bandbredd. F\u00f6rs\u00e4kra dig om att materialet \u00e4r f\u00e4rdiguppladdat f\u00f6rst. (hur?).\n\nKlicka "Avbryt" om du vill ta bort ditt publicerade material fr\u00e5n %3, och anv\u00e4nd ist\u00e4llet knappen (X) i panelen "Publicerat inneh\u00e5ll" under fliken "Publicera".\n\nMer hj\u00e4lp.\n\n v3.mb.delPublished.delete=Ra&dera v3.mb.delPublished.cancel=Avbryt v3.mb.openFile.title=\u00d6ppna v3.mb.openFile.text.known=Det h\u00e4r inneh\u00e5llet st\u00f6ds f\u00f6r tillf\u00e4llet inte av Vuze Player. L\u00e4s Uppspelningsguiden f\u00f6r ytterliggare information och hj\u00e4lp.\n\nFiltypen verkar vara: %2 (%3)\n v3.mb.openFile.text.unknown=Det h\u00e4r inneh\u00e5llet st\u00f6ds f\u00f6r tillf\u00e4llet inte av Vuze Player. L\u00e4s Uppspelningsguiden f\u00f6r ytterliggare information och hj\u00e4lp.\n\nFil\u00e4ndelse: %2\n v3.mb.openFile.button.play=Spela Upp v3.mb.openFile.button.cancel=Avbryt v3.mb.openFile.button.guide=L\u00e4s Uppspelningsguiden v3.mb.openFile.remember=\u00d6ppna alltid filer utan att fr\u00e5ga mig v3.mb.PlayFileNotFound.title=Filen hittades inte v3.mb.PlayFileNotFound.text=Filerna "%1" saknas eller \u00e4r raderade. v3.mb.PlayFileNotFound.button.remove=Ta bort fr\u00e5n Vuze v3.mb.PlayFileNotFound.button.redownload=Ladda ned p\u00e5 nytt v3.mb.PlayFileNotFound.button.find=S\u00f6k manuellt.. v3.mb.deletePurchased.title=Radera ink\u00f6pt material v3.mb.deletePurchased.text=\u00c4r du s\u00e4ker p\u00e5 att du vill radera "%1"?\n\nAntingen har du k\u00f6pt detta material eller s\u00e5 var du tvungen att logga in f\u00f6r att ladda ned. v3.mb.deletePurchased.button.delete=Ra&dera v3.mb.deletePurchased.button.cancel=Avbryt v3.topbar.menu.show.plugin=Pluginomr\u00e5de v3.topbar.menu.show.search=S\u00f6k splash.initializeCore=Initialiserar k\u00e4rna splash.initializeUIElements=Initialiserar UI ConfigView.section.transfer.autospeedbeta=Auto-Speed (Beta) # ConfigView.section.ipfilter.peerblocking.group=K\u00e4llblockering ConfigView.section.ipfilter.autoload.group=Ladda automatiskt ConfigView.section.ipfilter.autoload.file=Fil med IP-filter ConfigView.section.ipfilter.autoload.info=St\u00f6d f\u00f6r DAT (eMule), P2P (PeerGuardian, splist), och P2B v1,2,3 (PeerGuardian 2). Filen kan vara lokal eller som URL, zippad, gzippad eller text. URL-adresser kommer automatiskt atta laddas ned p\u00e5 nytt efter 7 dagar, filer kommer att laddas om strax efter de \u00e4ndras/ers\u00e4tts. ConfigView.section.ipfilter.autoload.loadnow=Ladda nu splash.loadIpFilters=L\u00e4ser in IP-filter... SpeedTestWizard.set.upload.title=St\u00e4ll in upp- och nedladdningsbegr\u00e4nsningar SpeedTestWizard.set.download.label=Hastighetsgr\u00e4ns f\u00f6r nedladdning: SpeedTestWizard.set.upload.label=Hastighetsgr\u00e4ns f\u00f6r uppladdning SpeedTestWizard.name.conf.level.absolute=Absolut SpeedTestWizard.name.conf.level.high=H\u00f6g SpeedTestWizard.name.conf.level.low=L\u00e5g SpeedTestWizard.name.conf.level.none=Ingen ConfigView.section.transfer.select=Auto-Speed ConfigView.section.transfer.select.v2=Auto-Speed (beta) mb.azmustclose.title=Fel vid programstart mb.azmustclose.text=Vuze har st\u00f6tt p\u00e5 problem och m\u00e5ste avslutas. Detta beror troligen p\u00e5 att programmet startades i Administrat\u00f6rsl\u00e4ge vid senaste omstart.\n\nDu m\u00e5ste starta programet sj\u00e4lv. network.ipv6.prefer.addresses=F\u00f6redra IPv6-adresser n\u00e4r b\u00e5de IPv6 och IPv4 \u00e4r tillg\u00e4ngliga DHTView.title.full_v6=Distribuerad database IPv6 ConfigView.pluginlist.loadSelected=Ladda in valda SpeedView.stats.asn=N\u00e4tverk: SpeedView.stats.estupcap=Uppladdningsgr\u00e4ns: SpeedView.stats.estdowncap=Nedladdningsgr\u00e4ns: SpeedView.stats.unknown=Ok\u00e4nt SpeedView.stats.estimate=Uppskattat SpeedView.stats.measured=Uppm\u00e4tt SpeedView.stats.measuredmin=Uppm\u00e4tt minimum SpeedView.stats.manual=Fast ConfigView.section.transfer.autospeed.networks=N\u00e4tverksinformation ConfigView.section.transfer.autospeed.resetnetwork=\u00c5terst\u00e4ll n\u00e4tverksinformation ConfigView.section.transfer.autospeed.network.info=V\u00e4rdena ovan \u00e4r normalt baserade p\u00e5 en kalkyl gjord vid nedladdning eller som ett resultat av ett hastighetstest. Om du vill justera manuellt g\u00f6r du det nedan. dialog.uiswitcher.restart.title=Byte av UI: Vuze m\u00e5ste startas om dialog.uiswitcher.restart.text=Vuze m\u00e5ste startas om innan \u00e4ndringarna b\u00f6rjar g\u00e4lla. TrayWindow.menu.close=St\u00e4ng nedladdningsruta # Used for peers which we can't determine. PeerSocket.unknown=Ok\u00e4nd PeerSocket.fake_client=FALSK PeerSocket.bad_peer_id=Felaktigt klient-ID PeerSocket.mismatch_id=st\u00e4mmer inte PeerSocket.unknown_az_style=Ok\u00e4nd %1/%2 PeerSocket.unknown_shadow_style=Ok\u00e4nd %1/%2 OpenTorrentWindow.mb.askCreateDir.title=M\u00e5lkatalogen finns inte OpenTorrentWindow.mb.askCreateDir.text=Katalogen du vill spara i finns inte.\n SpeedView.stats.estimatechoke=Uppskattat (strypt) ConfigTransferAutoSpeed.upload.capacity.usage=Anv\u00e4nd uppladdningskapacitet ConfigTransferAutoSpeed.mode=L\u00e4ge: ConfigTransferAutoSpeed.capacity.used=% Anv\u00e4nd kapacitet ConfigTransferAutoSpeed.while.downloading=Laddar ner: ConfigTransferAutoSpeed.set.dht.ping=Pinginst\u00e4llningar f\u00f6r DHT ConfigTransferAutoSpeed.set.point=V\u00e4rde (ms) ConfigTransferAutoSpeed.set.tolerance=Tolerans (ms) ConfigTransferAutoSpeed.ping.time.good=Bra: ConfigTransferAutoSpeed.ping.time.bad=D\u00e5ligt: ConfigTransferAutoSpeed.adjustment.interval=Justeringsintervall ConfigTransferAutoSpeed.skip.after.adjust=V\u00e4lj bort efter korrigering GeneralView.label.distributedCopies=Distribuerade kopior: PiecesView.DistributionView.title=F\u00f6rdelning av delar PiecesView.DistributionView.NoAvl=Ej tillg\u00e4ngliga delar PiecesView.DistributionView.SeedAvl=Andel fullst\u00e4ndiga k\u00e4llor PiecesView.DistributionView.PeerAvl=Andel ofullst\u00e4ndiga k\u00e4llor PiecesView.DistributionView.RarestAvl=Mest s\u00e4llsynta delar: %1 (Tillg\u00e4nglighet:%2) PiecesView.DistributionView.weHave=Delar du har PiecesView.DistributionView.theyHave=Delar klienten har PiecesView.DistributionView.weDownload=Delar du inte laddar ner PeersView.gain=Erh\u00e5llet PeersView.gain.info=Nedladdad minus uppladdad data unix.script.new.title=Ett nytt uppstartningsskript finns tillg\u00e4ngligt. unix.script.new.text=Ett nytt uppstartningsskript finns tillg\u00e4ngligt och har sparats p\u00e5 "%1".\n\nDu b\u00f6r avluta Vuze och byta till det nya skriptet ("%2").\n\nOm du sj\u00e4lv har modifierat ditt uppstartningsskript, g\u00e5 till AzureusWiki: Unix Script.\n\nOm du har installerat Vuze fr\u00e5n ett distro (yum, apt-get, etc), rekommenderas du att installera om Vuze med paketet du kan h\u00e4mta h\u00e4r: Vuze Sourceforge Page (Du kommer att f\u00e5 samma UI som du har nu) unix.script.new.button.quit=Avsluta nu unix.script.new.button.continue=Jag g\u00f6r det senare unix.script.new.button.asknomore=Fr\u00e5ga mig inte igen unix.script.new.auto.title=Nytt uppstartningsskript unix.script.new.auto.text=Ett nytt uppstartningsskript finns tillg\u00e4ngligt. Content.alert.notuploaded.button.stop=&Stoppa Content.alert.notuploaded.button.continue=&Forts\u00e4tta ladda upp Content.alert.notuploaded.button.abort=&St\u00e4ng inte ConfigView.label.checkOnSeeding=G\u00f6r en l\u00e5gniv\u00e5kontroll av delarna n\u00e4r de laddas upp ConfigView.label.ui_switcher=Visa Vuze UI-v\u00e4ljaren ConfigView.label.ui_switcher_button=Visa SpeedTestWizard.test.panel.explain=M\u00e4t din hastighet i Vuze. V\u00e4lj typ av test och krypteringsl\u00e4ge. G\u00e5 till Vuze Wikisida f\u00f6r ytterligare information om testet. Testet avslutas automatiskt om det tar l\u00e4ngre tid \u00e4n tv\u00e5 minuter. Normalt avslutas testet inom en minut. SpeedTestWizard.set.upload.hint=St\u00e4ll in hastighetsgr\u00e4nserna som Vuze AutoSpeedalgoritm skall anv\u00e4nda. SpeedTestWizard.set.upload.panel.explain=De v\u00e4rden du skriver h\u00e4r anv\u00e4nds av Vuze n\u00e4r programmet ber\u00e4knar hastigheten St\u00e4ll in gr\u00e4nser och tillf\u00f6rllillighet.\n\nObservera att bredbandshastigheter oftast anges i "bits/sekund". H\u00e4r nedan anges dock hastigheten i "kilobytes/sekund". SpeedTestWizard.set.limit.conf.level=Tillf\u00f6rlitlighet SpeedTestWizard.finish.panel.auto.speed=AutoSpeed \u00e4r: SpeedTestWizard.finish.panel.auto.speed.seeding=AutoSpeed n\u00e4r du laddar upp \u00e4r: ConfigTransferAutoSpeed.add.comment.to.log.group=L\u00e4gg till kommentar i Debug Log ConfigTransferAutoSpeed.add.comment.to.log=L\u00e4gg till kommentar: ConfigTransferAutoSpeed.log.button=Logg ConfigTransferAutoSpeed.algorithm.selector=V\u00e4lj Auto-Speed ConfigTransferAutoSpeed.algorithm=Algoritm: ConfigTransferAutoSpeed.auto.speed.classic=Auto-Speed (Klassisk) ConfigTransferAutoSpeed.auto.speed.beta=Auto-Speed (beta) ConfigTransferAutoSpeed.data.update.frequency=Uppdateringsfrekvens Alert.failed.update=En eller fler komponenter kunde inte installeras. G\u00e5 till AzureusWiki: Failed Update OpenTorrentWindow.mb.existingFiles.partialList=(Detta \u00e4r inte hela listan. Det finns fler filer som redan existerar.) TableColumn.header.bad_avail_time.info=Senast en komplett kopia fanns tillg\u00e4nglig TableColumn.header.bad_avail_time=Komplett kopia finns MyTorrentsView.menu.exporthttpseeds=Exportera HTTP-adresser till urklipp SWT.alert.erroringuithread=Ett ohanterat fel uppstod i GUI. F\u00f6ljdfel kan uppst\u00e5. ConfigView.label.minannounce=Minsta tid mellan tracker announces (sekunder) ConfigView.label.maxnumwant=Begr\u00e4nsa antalet klienter trackern kan skicka ConfigView.label.announceport=\u00c5sidos\u00e4tt annonserad TCP-port f\u00f6r tracker announces, pex och dht\n[Tom: Ingen \u00e5sidos\u00e4ttning, 0: inga inkommande anslutningar] ConfigView.label.noportannounce=S\u00e4nd inte portnummer till trackern (g\u00e4ller ej pex, dht) ConfigView.label.maxseedspertorrent=Max k\u00e4llor per torrent [0: obegr\u00e4nsat] wizard.webseed=L\u00e4gg till HTTP-uppladdning f\u00f6r torrent wizard.webseed.title=HTTP-uppladdning wizard.webseed.configuration=Inst\u00e4llningar f\u00f6r HTTP-uppladdning wizard.webseed.adding=L\u00e4gger till HTTP-uppladdning GeneralView.label.private=Privat Torrent: GeneralView.yes=Ja GeneralView.no=Nej Peers.column.timetocomplete=\u00c5terst\u00e5ende tid Progress.reporting.status.canceled=Avbruten Progress.reporting.status.finished=Slutf\u00f6rd Progress.reporting.status.retrying=F\u00f6rs\u00f6ker igen... Progress.reporting.action.label.remove.tooltip=Ta bort den h\u00e4r \u00c5tg\u00e4rdsrapporten fr\u00e5n historiken Progress.reporting.action.label.cancel.tooltip=Avbryt \u00e5tg\u00e4rden Progress.reporting.action.label.detail=Detaljer Progress.reporting.default.error=Misslyckades Progress.reporting.no.reports.to.display=Det finns inga \u00e5tg\u00e4rdsrapporter att visa just nu. Progress.reporting.statusbar.button.tooltip=Visa f\u00f6nstret med \u00c5tg\u00e4rdsrapporterna v3.MainWindow.text.log.in=Logga In v3.MainWindow.text.log.out=Logga Ut v3.MainWindow.text.get.started=Registrera dig v3.MainWindow.text.my.account=Kontoinformation v3.MainWindow.text.my.profile=Profil Progress.reporting.window.remove.auto=Ta bort inaktiva poster automatiskt Progress.reporting.window.remove.now=Ta bort inaktiva poster Progress.reporting.window.remove.now.tooltip=Ta bort alla slutf\u00f6rda, misslyckade eller avbrutna \u00e5tg\u00e4rder fr\u00e5n vyn TorrentOptionsView.multi.title.short=Egenskaper f\u00f6r Torrent TorrentOptionsView.multi.title.full=Egenskaper f\u00f6r Torrent MyTorrentsView.menu.open_parent_folder=\u00d6ppna mappen ConfigView.section.stats.exportfiles=Exportera fildetaljer updater.cant.write.to.app.details=Mappen "%1" \u00e4r inte skrivbar.\n\nDetta kommer att f\u00f6rhindra framtida programuppdateringar fr\u00e5n att till\u00e4mpas.\n\nL\u00e4s wikisidanFailed Update f\u00f6r mer detaljer. plugin.install.class_version_error=Detta plugin kr\u00e4ver en nyare version av Java f\u00f6r att k\u00f6ras. v3.MainWindow.tab.minilibrary=Neddladdningar v3.MainWindow.tab.events=Notifieringar v3.activity.remove.title=Radera Notifiering #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=St&\u00e4ng Menu.show.torrent.menu=Visa menyn Torrent Menu.show.torrent.menu.tooltip=Visar menyn Torrent i programmets menyf\u00e4lt #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=N\u00e4tverksstatus menu.sortByColumn=Sortera efter %1 MyTorrentsView.menu.manual.shared_peers=Manuellt (alla k\u00e4llor) v3.button.removeActivityEntry=Ta Bort Notifiering MainWindow.menu.window.zoom.maximize=Maximera MainWindow.menu.window.zoom.restore=\u00c5terst\u00e4ll security.crypto.password=L\u00f6senord security.crypto.persist_for.dont_save=Spara inte security.crypto.persist_for.session=Den h\u00e4r sessionen security.crypto.persist_for.day=1 dag security.crypto.persist_for.week=1 vecka security.crypto.persist_for.30days=30 dagar security.crypto.password.mismatch.title=L\u00f6senordsfel ConfigView.section.security.group.crypto=Publika/privata nycklar ConfigView.section.security.resetkey=\u00c5terst\u00e4ll nycklar ConfigView.section.security.publickey=Publik nyckel ConfigView.section.security.resetkey.error.title=\u00c5tg\u00e4rd Misslyckades ConfigView.section.security.resetkey.error=Misslyckades att \u00e5terst\u00e4lla nycklar ConfigView.copy.to.clipboard.tooltip=Kopiera till urklipp Views.plugins.azbuddy.title=V\u00e4nner ConfigView.label.queue.stoponcebandwidthmet=Om hastighetsgr\u00e4nsen f\u00f6r upp/nedladdning har n\u00e5tts starta inte flera torrents. ConfigView.section.style.xulRunnerPath=Specificera s\u00f6kv\u00e4gen f\u00f6r XulRunner / Firefox manuellt [kr\u00e4vs f\u00f6r FF3; omstart kr\u00e4vs] azbuddy.name=V\u00e4nner azbuddy.enabled=Aktiverad azbuddy.msglog.title=Information om V\u00e4n azbuddy.addtorrent.title=Acceptera nedladdning? azbuddy.addtorrent.msg=V\u00e4nnen '%1' har skickat '%2' till dig.\nVill du l\u00e4gga till nedladdningen? azbuddy.contextmenu=Skicka till V\u00e4n azbuddy.ui.mykey=Min nyckel: azbuddy.ui.add=L\u00e4gg till azbuddy.ui.table.name=Namn azbuddy.ui.table.last_msg=Senaste Meddelandet azbuddy.ui.menu.remove=Ta bort azbuddy.ui.menu.copypk=Kopiera Publika Nyckeln azbuddy.ui.menu.send=Skicka Meddelande azbuddy.ui.table.lastseen=S\u00e5gs senast Button.retry=F\u00f6&rs\u00f6k igen Button.ignore=&Ignorera ConfigView.section.security.backupkeys=S\u00e4kerhetskopiera nycklar till en fil ConfigView.section.security.backupkeys.button=S\u00e4kerhetskopiera ConfigView.section.security.restorekeys=\u00c5terst\u00e4ll nycklar fr\u00e5n en fil ConfigView.section.security.restorekeys.button=\u00c5terst\u00e4ll ConfigView.section.security.op.error.title=\u00c5tg\u00e4rd Misslyckades ConfigView.section.security.op.error=Misslyckades att slutf\u00f6ra \u00e5tg\u00e4rden:\n %1 ConfigView.section.security.restart.title=Kr\u00e4ver Omstart azbuddy.ui.menu.chat=Chatt azbuddy.chat.title=Vuze Chatt azbuddy.chat.says=%1 s\u00e4ger: Button.bar.show=Visa Button.bar.hide=D\u00f6lj Button.bar.share=Dela Button.bar.add=L\u00e4gg till Button.bar.edit=Redigera Button.bar.edit.cancel=St\u00e4ng redigering v3.MainWindow.menu.view.pluginbar=Pluginpanelen MainWindow.dialog.select.vuze.file=V\u00e4lj Vuze Fil MainWindow.menu.file.open.vuze=Vuze Fil... metasearch.addtemplate.title=Installera S\u00f6kmall? metasearch.addtemplate.desc=\u00c4r du s\u00e4ker att du vill installera s\u00f6kmallen som heter '%1'? v3.share.private.title=Dela Ut Torrent v3.share.private.text=Den torrent du har valt \u00e4r uppm\u00e4rkt "Privat Torrent".\n\nDu kan inte dela ut privata torrent filer. metasearch.addtemplate.dup.title=Kopiera Mall metasearch.addtemplate.dup.desc=S\u00f6kmallen %1 \u00e4r redan installerad metasearch.export.select.template.file=Spara Mall metasearch.import.select.template.file=\u00d6ppna Mall dialog.uiswitch.title=V\u00e4xla till Vuze UI dialog.uiswitch.text=Du m\u00e5ste k\u00f6ra Vuze gr\u00e4nssnittet f\u00f6r att anv\u00e4nda den h\u00e4r funktionen\n\nVuze m\u00e5ste startas om. dialog.uiswitch.button=V\u00e4xla till Vuze UI v3.MainWindow.button.download=Ladda ned v3.MainWindow.button.run=\u00d6ppna det h\u00e4mtade objektet. v3.activity.header.downloads=Nedladdningar v3.activity.header.vuze.news=Vuze Nyheter azbuddy.tracker.bbb.status.title.tooltip=Dubbelklicka f\u00f6r detaljer azbuddy.tracker.bbb.status.nli=Inloggning kr\u00e4vs v3.MainWindow.search.go.tooltip=Utf\u00f6r s\u00f6kningen v3.MainWindow.search.last.tooltip=G\u00e5 tillbaka till s\u00f6kresultaten metasearch.addtemplate.done.title=Mall Tillagd metasearch.addtemplate.done.desc=Mallen '%1' las till.\nDen kommer att anv\u00e4ndas n\u00e4sta g\u00e5ng du s\u00f6ker! ConfigView.section.security.nopw=Inget l\u00f6senord angavs fileplugininstall.install.title=Installera Plugin? fileplugininstall.install.desc=\u00c4r du s\u00e4ker att du vill installera plugin '%1', version %2? fileplugininstall.duplicate.title=Duplicera Plugin fileplugininstall.duplicate.desc=Plugin '%1', version %2 \u00e4r redan installerad azbuddy.os_not_avail=Inte Tillg\u00e4nglig azbuddy.os_busy=Upptagen azbuddy.enable_chat_notif=Aktivera Chatt notifieringar progress.window.msg.progress=Var v\u00e4nlig och v\u00e4nta medans \u00e5tg\u00e4rden utf\u00f6rs DetailedListView.title=Detaljerad Lista plugins.init.force_enabled=Vuze har uppt\u00e4ckt att plugin "%1" var inaktiverat - det har aktiverats s\u00e5 att Vuze kan fungera korrekt. ConfigView.section.connection.prefer.udp=F\u00f6redra UDP anslutningar subscript.add.title=Installera Prenumeration? subscript.add.dup.title=Kopiera Prenumeration subscript.add.dup.desc=Prenumerationen '%1' \u00e4r redan installerad. subscript.add.upgrade.title=Uppgradera Prenumerationen? iconBar.start=Starta iconBar.stop=Stoppa iconBar.remove=Radera iconBar.up=Upp iconBar.down=Ned iconBar.run=\u00d6ppna iconBar.queue=Starta iconBar.open=L\u00e4gg till Torrent iconBar.share=Dela iconBar.share.tooltip=Dela ut inneh\u00e5ll iconBar.details=Detaljer iconBar.comment=Kommentar iconBar.play=Spela Upp iconBar.queue.tooltip=K\u00f6 v3.MainWindow.menu.view.sidebar=Sidpanelen v3.MainWindow.menu.view.actionbar=Verktygsf\u00e4lt v3.MainWindow.menu.view.toolbars=Verktygsf\u00e4lt ump.install=Snabb uppdatering utf\u00f6rs:\nInstallerar ett litet till\u00e4gg f\u00f6r uppspelning som kr\u00e4vs f\u00f6r den h\u00e4r videon. subscriptions.listwindow.autochecktext=Vuze kan hitta prenumerationer som tillh\u00f6r inneh\u00e5ll i ditt bibliotek. Vill du aktivera den h\u00e4r funktionen? subscriptions.listwindow.loadingtext=Letar efter prenumerationer tillh\u00f6rande %1 subscriptions.listwindow.failed=Inga prenumerationer hittades subscriptions.listwindow.popularity=Popularitet subscriptions.listwindow.popularity.unknown=Ok\u00e4nd subscriptions.listwindow.name=Namn subscriptions.listwindow.subscribe=Prenumerera TableColumn.header.azsubs.ui.column.subs=Prenumerera subscriptions.listwindow.popularity.reading=L\u00e4ser... PluginDeprecation.alert=Ett plugin har f\u00f6rs\u00f6kt anv\u00e4nda funktionalitet som kommer att tas bort i framtiden - \u00f6ppna 'Plugin Debug log' vyn f\u00f6r mer information. TableColumn.header.Thumbnail=Ikon v3.MainWindow.menu.getting_started=Komma ig\u00e5n&g MainWindow.menu.help.faq=&FAQ MainWindow.menu.community.blog=Vuze &Blogg MainWindow.menu.help.support=&Hj\u00e4lp och Support externalLogin.title=Inloggning kr\u00e4vs Button.done=F\u00e4rdig GeneralView.torrent_created_on_and_by=%1 av %2 Button.continue=Forts\u00e4tt Button.preview=F\u00f6rhandsgranska Subscription.menu.forcecheck=Uppdatera Nu Subscription.menu.clearall=Markera Alla Resultat som L\u00e4sta Subscription.menu.remove=Radera sidebar.Library=Mitt Bibliotek sidebar.LibraryDL=Laddar ner authenticator.details=Detaljer v3.MainWindow.menu.showActionBarText=Visa text i verktygsf\u00e4ltet subscript.import.fail.title=Import Misslyckades subscript.import.fail.desc=Detaljer: %1 Subscription.menu.export=Exportera subscript.export.select.template.file=Spara Prenumerationen Button.remove=Ta bort Button.send=Skicka Button.back=Tillbaka sidebar.LibraryUnopened=Osedda TableColumn.header.unopened=Ny Unopened.bigView.header=Ny Subscription.menu.deleteall=Radera Alla Resultat Subscription.menu.reset=\u00c5terst\u00e4ll till Utg\u00e5ngsl\u00e4get ConfigView.section.Subscriptions=Prenumerationer subscriptions.config.maxresults=Max antal resultat som sparas per prenumeration [0: obegr\u00e4nsat] v3.activity.button.readall=Markera Alla som L\u00e4sta TableColumn.header.activityNew=Ny TableColumn.header.activityType=Typ TableColumn.header.activityText=Meddelande Search.menu.engines=Mallar Wizard.Subscription.title=Prenumerera Wizard.Subscription.optin.title=Aktivera prenumerationer #what you've watched? Discover more with a single click... Wizard.Subscription.subscribe.title=Tillg\u00e4ngliga prenumerationer Wizard.Subscription.create.title=Skapa en ny prenumeration Button.search=S\u00f6k Button.save=Spara Button.add=L\u00e4gg till Button.createNewSubscription=Skapa ny prenumeration Button.availableSubscriptions=Tillg\u00e4ngliga prenumerationer Wizard.Subscription.optin.description=Om Prenumerationer \u00e4r aktiverat kommer Vuze att visa prenumerationer (RSS fl\u00f6den) som finns f\u00f6r inneh\u00e5llet i ditt bibliotek och dessutom visa n\u00e4r det finns n\u00e5got nytt tillg\u00e4ngligt f\u00f6r nedladdning.\n\nVill du aktivera st\u00f6d f\u00f6r prenumerationer? Wizard.Subscription.create.search=S\u00f6k Wizard.Subscription.search.subtitle1=Skriv in s\u00f6kord f\u00f6r att b\u00f6rja skapa din prenumeration : Wizard.Subscription.search.subtitle2=Vad kan jag s\u00f6ka efter? Wizard.Subscription.search.subtitle2.sub1=HD filmer, TV program, Filmer, Trailers p\u00e5 Vuze N\u00e4tverket Wizard.Subscription.search.subtitle2.sub2=Torrents fr\u00e5n olika platser p\u00e5 webben Wizard.Subscription.search.subtitle3=N\u00e4r din prenumeration \u00e4r f\u00e4rdig f\u00e5r du uppdateringar live i din sidpanel n\u00e4r nya resultat \u00e4r tillg\u00e4ngliga f\u00f6r din s\u00f6kning. Wizard.Subscription.rss.subtitle1=Skriv eller klistra in adressen (URL:en) i rutan nedanf\u00f6r: Wizard.Subscription.rss.subtitle2=M\u00e5nga publicerar RSS fl\u00f6den av sitt inneh\u00e5ll. Leta upp adressen f\u00f6r RSS fl\u00f6det p\u00e5 deras webbsida, kopiera och klistra in i f\u00e4ltet ovanf\u00f6r och klicka sen p\u00e5 Spara. Wizard.Subscription.rss.subtitle3=N\u00e4r du har sparat f\u00e5r du uppdateringar live via ditt RSS fl\u00f6de i sidpanelen n\u00e4r nya resultat \u00e4r tillg\u00e4ngliga. Wizard.Subscription.subscribe.library=Inneh\u00e5ll i ditt bibliotek Wizard.Subscription.subscribe.subscriptions=Tillh\u00f6rande prenumerationer Wizard.Subscription.subscribe.library.empty=\u00c4r inga prenumerationer tillg\u00e5ngliga?\n \nTitta efter den oranga prenumerationsknappen p\u00e5 Vuze HD N\u00e4tverket.\n \nL\u00e4s mer message.confirm.delete.title=Bekr\u00e4fta Radering message.confirm.delete.text=Vill du verkligen radera '%1'? Subscription.menu.properties=Egenskaper props.window.title=Egenskaper f\u00f6r '%1' subs.prop.is_auto=Ladda ned nya resultat automatiskt subs.prop.num_read=Antal l\u00e4sta resultat subs.prop.num_unread=Antal ol\u00e4sta resultat subs.prop.template=Mall subs.prop.auth=Autentisering kr\u00e4vs externalLogin.wait=V\u00e4nta medans sidan laddas... TableColumn.menu.date_added.time=Visa/D\u00f6lj tid sidebar.VuzeHDNetwork=Vuze HD N\u00e4tverk subs.prop.next_scan=N\u00e4sta s\u00f6kning utf\u00f6rs subscriptions.column.name=Prenumeration subscriptions.column.nb-results=Antal Resultat subscriptions.column.nb-new-results=Nya Resultat subscriptions.column.last-checked=Senast kontrollerad subscriptions.view.title=Prenumerationer subs.prop.is_public=Publik metasearch.template.version.bad=S\u00f6kmallen '%1' kan inte installeras f\u00f6rr\u00e4n du har uppgrad3erat Vuze metasearch.addtemplate.failed.title=Installation misslyckades metasearch.addtemplate.failed.desc=Installationen av den h\u00e4r s\u00f6kmallen misslyckades: %1 statusbar.feedback=Skicka Feedback statusbar.feedback.tooltip=Klicka h\u00e4r f\u00f6r att skicka feedback sidebar.Activity=Notifieringar v3.activity.button.watchall=Markera Alla som Sedda subscriptions.view.help.1=Du kan l\u00e4gga till Prenumerationer d\u00e4r du ser subscriptions.view.help.2=F\u00e5 gratis och aktuell information om n\u00e4r nytt inneh\u00e5ll \u00e4r tillg\u00e4ngligt f\u00f6r nedladdning. L\u00e4s mer. sidebar.sash.tooltip=F7 f\u00f6r att snabbt visa/d\u00f6lja sidpanelen sidebar.expand.tooltip=Expandera Sidpanelen sidebar.dropdown.tooltip=Visa sidpanelen i menyformat subscript.all.subscribed=Du prenumererar redan p\u00e5 inneh\u00e5ll h\u00e4rifr\u00e5n subscript.some.subscribed=Du prenumererar redan p\u00e5 n\u00e5gra av prenumerationerna\nsom finns f\u00f6r det h\u00e4r inneh\u00e5llet.\nKlicka f\u00f6r att se fler som \u00e4r tillg\u00e4ngliga subscript.none.subscribed=Klicka f\u00f6r att se prenumerationer som\n\u00e4r tillg\u00e4ngliga f\u00f6r det h\u00e4r inneh\u00e5llet. v3.iconBar.up.tooltip=Flytta upp\u00e5t\nH\u00e5ll ned musknappen f\u00f6r att flytta till toppen v3.iconBar.down.tooltip=Flytta ned\nH\u00e5ll ned musknappen f\u00f6r att flytta till botten Button.deleteContent.fromLibrary=Ta bort fr\u00e5n Biblioteket Button.deleteContent.fromComputer=Radera fr\u00e5n Datorn v3.deleteContent.message=\nVill du radera '%1' fr\u00e5n din dator eller bara ta bort den fr\u00e5n ditt Vuze Bibliotek? v3.MainWindow.menu.view.toolbartext=Text i Verktygsf\u00e4ltet v3.MainWindow.menu.view.asSimpleList=Enkel Lista v3.MainWindow.menu.view.asAdvancedList=Avancerad Lista v3.MainWindow.menu.view.statusbar=Statusf\u00e4lt Subscription.menu.dirtyall=Markera Alla Resultat som Ol\u00e4sta ConfigView.label.seeding.firstPriority.ignoreIdleHours=Torrents som inte laddat upp n\u00e5got p\u00e5 v3.MainWindow.menu.contentnetworks=HD &N\u00e4tverk v3.MainWindow.menu.contentnetworks.about=Om HD N\u00e4tverk ConfigView.label.autoopen.downloadbars=\u00d6ppna nedladdningsrutor automatiskt n\u00e4r ConfigView.label.autoopen=\u00d6ppna automatiskt ConfigView.label.autoopen.detailstab=\u00d6ppna fliken Detaljer n\u00e4r ConfigView.label.systray=Meddelandef\u00e4ltet ConfigView.label.systray._mac=Ikon f\u00f6r Statusf\u00e4ltet v3.MainWindow.menu.contentnetworks.manage=Hantera HD N\u00e4tverk azbuddy.ui.menu.cat=Kategorier azbuddy.ui.menu.cat.set_msg=Kommaseparerad lista av kategorier eller 'Alla' azbuddy.ui.menu.cat_subs=Prenumerera v3.dialog.cnmanage.title=Hantera menyn f\u00f6r HD N\u00e4tverk TableColumn.header.TableColumnChosenColumn=Vald Kolumn ColumnSetup.chosencolumns=Valda Kolumner ColumnSetup.categories=Kategorier: ColumnSetup.filters=Filter MainWindow.menu.help.donate=G\u00f6r en donation ($2,$5,...) azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_tr_TR.properties0000644000175000017500000040044211301156004026125 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torrent Dosyas\u0131... Main.parameter.usage=Kullan\u0131m : java org.gudy.azureus2.cl.Main [de\u011fi\u015ftirgeler] "file.torrent" "kay\u0131t yolu" Main.parameter.maxUploads=En Fazla E\u015fanl\u0131 G\u00f6nderme say\u0131s\u0131 Main.parameter.maxSpeed=G\u00f6ndermelerin bayt/san olarak en fazla h\u0131z\u0131 MainWindow.menu.file=Dosya MainWindow.menu.file.open=A\u00e7 MainWindow.menu.file.create=Torrent Olu\u015ftur MainWindow.menu.file.create.fromfile=Bir Dosyadan MainWindow.menu.file.create.fromdir=Bir Dizinden MainWindow.menu.file.export=Torrent Ver... MainWindow.menu.file.import=Torrent Al... MainWindow.menu.file.closetab=Sekmeyi Kapat MainWindow.menu.file.closewindow=Pencereyi Kapat MainWindow.menu.file.exit=\u00c7\u0131k\u0131\u015f MainWindow.dialog.choose.file=Torrent Dosyas\u0131n\u0131 Se\u00e7 MainWindow.menu.file.folder=Dizin MainWindow.dialog.choose.folder=Torrent dosyalar\u0131n\u0131 i\u00e7eren dizini se\u00e7 MainWindow.menu.view=&G\u00f6r\u00fcn\u00fcm MainWindow.menu.view.show=G\u00f6ster MainWindow.menu.view.mytorrents=Torrentlerim MainWindow.menu.view.configuration=Se\u00e7enekler... MainWindow.menu.view.console=U\u00e7birim MainWindow.menu.view.irc=Irc MainWindow.menu.closealldetails=T\u00fcm Ayr\u0131nt\u0131lar\u0131 Kapat MainWindow.menu.closealldownloadbars=T\u00fcm \u0130ndirme \u00c7ubuklar\u0131n\u0131 Kapat MainWindow.menu.language=Dil ConfigView.section.language=Dil MainWindow.menu.window=Pencere MainWindow.menu.window.minimize=K\u00fc\u00e7\u00fclt MainWindow.menu.window.zoom=Yak\u0131nla\u015ft\u0131r MainWindow.menu.window.alltofront=T\u00fcm\u00fcn\u00fc \u00d6ne Getir MainWindow.menu.help=Yard\u0131m MainWindow.menu.help.about=Vuze Hakk\u0131nda MainWindow.about.title=Hakk\u0131nda MainWindow.about.section.developers=Geli\u015ftiriciler MainWindow.about.section.translators=\u00c7evirmenler MainWindow.about.section.system=Sistem MainWindow.about.section.internet=\u0130nternet MainWindow.about.internet.homepage=Vuze Anasayfas\u0131 MainWindow.about.internet.sourceforge=Sourceforge Proje Sayfas\u0131 MainWindow.about.internet.sourceforgedownloads=Sourceforge \u0130ndirmeleri MainWindow.about.internet.bugreports=Hata Bildirme MainWindow.about.internet.forumdiscussion=Forumlar MainWindow.about.internet.wiki=Vuze Viki SSS MainWindow.dialog.choose.savepath=Kaydetme yolunu Se\u00e7 MainWindow.dialog.choose.savepath_forallfiles=T\u00fcm dosyalar i\u00e7in kaydetme yolunu se\u00e7 MainWindow.status.latestversion=En son s\u00fcr\u00fcm MainWindow.status.latestversion.clickupdate=G\u00fcncelle\u015ftirmek i\u00e7in t\u0131klay\u0131n MainWindow.status.unknown=Bilinmiyor MainWindow.status.checking=Denetleniyor MyTorrentsView.mytorrents=Torrentlerim TableColumn.header.name=Ad TableColumn.header.size=B\u00fcy\u00fckl\u00fck TableColumn.header.done=Tamamlanma TableColumn.header.done.info=Ge\u00e7erli g\u00f6revin tamamlanma y\u00fczdesi TableColumn.header.status=Durum TableColumn.header.status.info=Torrent ne yap\u0131yor TableColumn.header.seeds=Ortaklar TableColumn.header.seeds.info=# tane ba\u011flan\u0131lm\u0131\u015f ortak (# tane toplam ortak) TableColumn.header.peers=E\u015fler TableColumn.header.peers.info=# tane ba\u011flan\u0131lm\u0131\u015f olan e\u015f (# tane toplam e\u015f) TableColumn.header.downspeed=\u0130ndirme H\u0131z\u0131 TableColumn.header.upspeed=G\u00f6nderme H\u0131z\u0131 TableColumn.header.eta=Kalan S\u00fcre TableColumn.header.tracker=\u0130zleyici Durumu TableColumn.header.tracker.info=\u0130zleyici durumu TableColumn.header.trackernextaccess=Sonraki \u0130zleyici Eri\u015fimi TableColumn.header.trackernextaccess.info=Sonraki izleyici eri\u015fimi olu\u015ftu\u011funda TableColumn.header.priority=\u00d6ncelik TableColumn.header.priority.info=Torrent i\u00e7in izin verilen g\u00f6nderme bant geni\u015fli\u011fini belirtir MyTorrentsView.menu.showdetails=Ayr\u0131nt\u0131lar\u0131 G\u00f6ster MyTorrentsView.menu.showdownloadbar=\u0130ndirme \u00c7ubu\u011funu G\u00f6ster MyTorrentsView.menu.open=Dosyay\u0131 A\u00e7 MyTorrentsView.menu.setpriority=\u00d6ncelik Ayarla MyTorrentsView.menu.setpriority.high=Y\u00fcksek MyTorrentsView.menu.setpriority.low=D\u00fc\u015f\u00fck MyTorrentsView.menu.start=Ba\u015flat MyTorrentsView.menu.stop=Durdur MyTorrentsView.menu.remove=Kald\u0131r MyTorrentsView.menu.changeTracker=\u0130zleyici Adresi Ekle TrayWindow.menu.exit=\u00c7\u0131k\u0131\u015f TrayWindow.menu.show=Vuze u G\u00f6ster SystemTray.menu.exit=\u00c7\u0131k\u0131\u015f SystemTray.menu.closealldownloadbars=T\u00fcm \u0130ndirme \u00c7ubuklar\u0131n\u0131 Kapat SystemTray.menu.show=Vuze u G\u00f6ster PeersView.ip.info=E\u015fin IP adresi PeersView.port=Ba\u011flant\u0131 Noktas\u0131 PeersView.port.info=Ba\u011flant\u0131 noktas\u0131 kullan\u0131l\u0131yor PeersView.T.info=l (yerel): ba\u011flant\u0131 kurdunuz, r (uzak): e\u015f ba\u011flant\u0131 kurdu. PeersView.T.L.tooltip=ba\u011flant\u0131 kurdunuz PeersView.T.R.tooltip=e\u015f ba\u011flant\u0131 kurdu. PeersView.I1=\u0130 (E\u015f [i]lgilenmi\u015fmi) PeersView.I1.info=Di\u011fer e\u015flerin sahip olduklar\u0131yla ilgileniyor musunuz? PeersView.C1=T (E\u015f [t]\u0131kam\u0131\u015f m\u0131) PeersView.C1.info=E\u015fin indirme i\u015fleminizi durdurup durdurmad\u0131\u011f\u0131 PeersView.pieces=Par\u00e7alar PeersView.%=% PeersView.downloadspeed=\u0130ndirme H\u0131z\u0131 PeersView.download=\u0130ndirme PeersView.I2=\u0130 (E\u015fle [i]lgilenilmi\u015fmi) PeersView.I2.info=E\u015f, sizin sahip olduklar\u0131n\u0131zla ilgileniyor mu? PeersView.C2=T (E\u015f [t]\u0131kanm\u0131\u015f m\u0131) PeersView.C2.info=E\u015fin indirme i\u015flemini durdurup durdurmad\u0131\u011f\u0131n\u0131z PeersView.uploadspeed=G\u00f6nderme H\u0131z\u0131 PeersView.uploadspeed.info=E\u015fe g\u00f6nderme h\u0131z\u0131n\u0131z PeersView.upload=Giden PeersView.upload.info=E\u015fe yapt\u0131\u011f\u0131n\u0131z t\u00fcm g\u00f6nderme PeersView.statup.info=E\u015fin g\u00f6nderme h\u0131z\u0131n\u0131n tahmini de\u011feri PeersView.downloadspeedoverall=Genel \u0130ndirme H\u0131z\u0131 PeersView.optunchoke=Opt. Unchoke PeersView.client=\u0130stemci PeersView.client.info=E\u015fin kulland\u0131\u011f\u0131 BT istemci t\u00fcr\u00fc PeersView.menu.snubbed=K\u00fc\u00e7\u00fcmsenmi\u015f PeersView.title.short=E\u015fler PeersView.title.full=E\u015fler ConfigView.section.files=Dosyalar ConfigView.label.usefastresume=H\u0131zl\u0131 s\u00fcrd\u00fcrme kipini kullan ConfigView.label.incrementalfile=Art\u0131r\u0131ml\u0131 dosya olu\u015fturmay\u0131 etkinle\u015ftir [Linux alt\u0131nda FAT32 gerektirir] ConfigView.label.defaultsavepath=Varsay\u0131lan veri dizinine kaydet ConfigView.button.browse=G\u00f6z at... ConfigView.dialog.choosedefaultsavepath=L\u00fctfen Varsay\u0131lan veri kaydetme dizinini se\u00e7in ConfigView.section.server=Ba\u011flant\u0131 ConfigView.section.global=Genel ConfigView.label.disconnetseed=Yay\u0131mlarken ortaklarla ba\u011flant\u0131y\u0131 kes ConfigView.label.switchpriority=Yay\u0131mlarken d\u00fc\u015f\u00fck-\u00f6nceli\u011fe otomatik ge\u00e7 ConfigView.label.maxdownloads=En fazla e\u015fanl\u0131 indirmeler ConfigView.label.maxactivetorrents=Etkin torrent en \u00e7ok say\u0131s\u0131 (0 : s\u0131n\u0131rs\u0131z)\nListede daha fazla varsa yeni torrentler ba\u015flamayacakt\u0131r. ConfigView.label.priorityExtensions=\u00d6ncelik verilecek dosya uzant\u0131lar\u0131\n(\u00d6rnek: .txt; .nfo; .jpg) ConfigView.section.transfer=Aktar\u0131m ConfigView.label.maxuploads=Torrent ba\u015f\u0131na varsay\u0131lan en fazla g\u00f6nderme say\u0131s\u0131 ConfigView.label.maxuploadspeed=En y\u00fcksek g\u00f6nderme h\u0131z\u0131 (toplam) ConfigView.label.saveresumeinterval=S\u00fcrd\u00fcrme verisini g\u00fcncelleme s\u0131kl\u0131\u011f\u0131 ConfigView.unlimited=S\u0131n\u0131rs\u0131z ConfigView.section.display=G\u00f6r\u00fcn\u00fcm ConfigView.label.opendetails=Ayr\u0131nt\u0131lar penceresini otomatik a\u00e7 ConfigView.label.openbar=\u0130ndirme \u00e7ubu\u011funu otomatik a\u00e7 ConfigView.label.closetotray=Kapat\u0131nca bildirim alan\u0131na git ConfigView.label.minimizetotray=K\u00fc\u00e7\u00fclt\u00fcnce bildirim alan\u0131na git ConfigView.section.general=Genel ConfigView.section.start=Ba\u015flang\u0131\u00e7 ConfigView.label.showsplash=Ba\u015flang\u0131\u00e7 penceresini g\u00f6ster ConfigView.label.autoupdate=Yeni s\u00fcr\u00fcm oldu\u011funda G\u00fcncelle\u015ftirme \u0130leti\u015fim Kutusunu G\u00f6ster ConfigView.label.openconsole=Ba\u015flang\u0131\u00e7ta u\u00e7birim sekmesini a\u00e7 ConfigView.label.openconfig=Ba\u015flang\u0131\u00e7ta yap\u0131land\u0131rma sekmesini a\u00e7 ConfigView.label.startminimized=Bildirim alan\u0131nda simge olarak ba\u015fla ConfigView.section.irc=Irc ConfigView.label.ircwiki=L\u00fctfen \u015funu okuyun: http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Sunucu ConfigView.label.ircchannel=Kanal ConfigView.label.irclogin=Takma Ad ConfigView.group.irctitle=IRC Ayarlar\u0131 ConfigView.boolean.ircsendinfo=Ayarlar\u0131n, kanal y\u00f6neticilerine, onlara yard\u0131mc\u0131 olmas\u0131 i\u00e7in\nanonim olarak g\u00f6nderilmesine izin ver ConfigView.boolean.irclog=Kanal ekinli\u011fi g\u00fcnl\u00fc\u011f\u00fcn\u00fc tutmay\u0131 etkinle\u015ftir (IRC_log.htm dosyas\u0131nda) ConfigView.section.security=G\u00fcvenlik ConfigView.label.password=Vuze u \u015fifre kullanarak koru\n(Aray\u00fcz ekrana gelmeden hemen \u00f6nce sorulur) ConfigView.label.passwordconfirm=\u015eifre (do\u011frula) ConfigView.label.passwordmatch=\u015eifre etkinle\u015ftirildi : ConfigView.label.passwordmatchnone=Hay\u0131r ConfigView.label.passwordmatchno=Hay\u0131r / \u015eifre do\u011frulanmad\u0131 ConfigView.label.passwordmatchyes=Evet ConfigView.button.save=Kaydet ConfigView.title.short=Se\u00e7enekler ConfigView.title.full=Se\u00e7enekler ConsoleView.title.short=U\u00e7birim ConsoleView.title.full=U\u00e7birim FileItem.write=yaz FileItem.read=oku FileItem.normal=normal FileItem.high=y\u00fcksek FileItem.donotdownload=\u0130ndirme FilesView.name=Ad FilesView.size=B\u00fcy\u00fckl\u00fck FilesView.done=Tamamlanma FilesView.%=% FilesView.firstpiece=\u0130lk Par\u00e7a # FilesView.numberofpieces=Par\u00e7a Say\u0131s\u0131 FilesView.pieces=Par\u00e7alar FilesView.mode=Kip FilesView.priority=\u00d6ncelik FilesView.menu.open=A\u00e7 FilesView.menu.setpriority=\u00d6ncelik Ayarla FilesView.menu.setpriority.high=Y\u00fcksek FilesView.menu.setpriority.normal=Normal FilesView.menu.setpriority.skipped=\u0130ndirme FilesView.title.short=Dosyalar FilesView.title.full=Dosyalar GeneralView.section.downloaded=\u0130ndirilen GeneralView.label.status.file=Dosyan\u0131n Durumu GeneralView.label.status.pieces=Par\u00e7alar\u0131n Durumu GeneralView.section.availability=Bulunabilirlik GeneralView.label.status.pieces_available=Par\u00e7alar\u0131n Durumu GeneralView.section.transfer=Aktar\u0131m GeneralView.section.info=Bilgi GeneralView.title.short=Genel GeneralView.title.full=Genel GeneralView.label.timeelapsed=Ge\u00e7en S\u00fcre : GeneralView.label.remaining=Kalan S\u00fcre: GeneralView.label.downloaded=\u0130ndirilen : GeneralView.label.downloadspeed=\u0130ndirme H\u0131z\u0131: GeneralView.label.maxuploads=En fazla G\u00f6nderme : GeneralView.label.uploaded=G\u00f6nderilen : GeneralView.label.uploadspeed=G\u00f6nderme H\u0131z\u0131 : GeneralView.label.seeds=Ortaklar : GeneralView.label.peers=E\u015fler : GeneralView.label.totalspeed=Toplam H\u0131z : GeneralView.label.totalspeed.tooltip=Ba\u011fl\u0131 oldu\u011funuz t\u00fcm istemcilerin toplam (ve ortamalama) h\u0131z\u0131 GeneralView.label.averagespeed=yay\u0131mlama h\u0131z\u0131 GeneralView.label.filename=Dosya Ad\u0131 : GeneralView.label.totalsize=Toplam B\u00fcy\u00fckl\u00fck : GeneralView.label.savein=Kaydedilen Yer : GeneralView.label.hash=Do\u011frulama Verisi : GeneralView.label.numberofpieces=Par\u00e7alar\u0131n Say\u0131s\u0131 : GeneralView.label.size=B\u00fcy\u00fckl\u00fck : GeneralView.label.tracker=\u0130zleyici Durumu: GeneralView.label.updatein=Sonraki G\u00fcncelleme : GeneralView.label.trackerurl=\u0130zleyici Adresi : GeneralView.label.trackerurlupdate=\u0130zleyiciyi G\u00fcncelle GeneralView.label.comment=Yorum : ManagerItem.waiting=Bekliyor ManagerItem.allocating=Ay\u0131r\u0131yor ManagerItem.checking=Denetliyor ManagerItem.ready=Haz\u0131r ManagerItem.downloading=\u0130ndiriyor ManagerItem.seeding=Yay\u0131mlan\u0131yor ManagerItem.stopped=\u00c7al\u0131\u015fm\u0131yor ManagerItem.error=Hata ManagerItem.high=y\u00fcksek ManagerItem.low=d\u00fc\u015f\u00fck MinimizedWindow.name=Ad: PiecesView.#=# PiecesView.size=B\u00fcy\u00fckl\u00fck PiecesView.numberofblocks=\u00d6bek Say\u0131s\u0131 PiecesView.blocks=\u00d6bekler: PiecesView.completed=Tamamland\u0131 PiecesView.availability=Bulunabilirlik PiecesView.reservedby=Ayr\u0131ld\u0131 PiecesView.writers=\u00d6bek Sa\u011flay\u0131c\u0131lar\u0131 PiecesView.title.short=Par\u00e7alar PiecesView.title.full=Par\u00e7alar SystemTray.tooltip.seeding=%1 yay\u0131mlan\u0131yor, SystemTray.tooltip.downloading=%1 indiriliyor, DownloadManager.error.filenotfound=Dosya Bulunamad\u0131 DownloadManager.error.fileempty=Torrent dosyas\u0131 bo\u015f DownloadManager.error.filetoobig=Torrent dosyas\u0131 \u00e7ok b\u00fcy\u00fck DownloadManager.error.filewithouttorrentinfo=Dosyan\u0131n i\u00e7inde Torrent bilgisi bulunamad\u0131 DownloadManager.error.unsupportedencoding=Desteklenmeyen Kodlama DownloadManager.error.ioerror=I/O Hatas\u0131 DownloadManager.error.sha1=Bulunmayan Algoritma (SHA1) hatas\u0131 PeerManager.status.offline=Ba\u011flant\u0131 Hatas\u0131 PeerManager.status.ok=Tamam PeerManager.status.checking=Denetliyor PeerManager.status.finished=Tamamland\u0131 PeerManager.status.finishedin=S\u00fcre MainWindow.upgrade.assistant=Y\u00fckseltme Yard\u0131mc\u0131s\u0131 MainWindow.upgrade.newerversion=Vuze un indirilmeye haz\u0131r yeni bir s\u00fcr\u00fcm\u00fc mevcut MainWindow.upgrade.explanation=Bu yard\u0131mc\u0131, yeni s\u00fcr\u00fcm\u00fc Vuze dizininin i\u00e7ine indirecek ve Vuze \u00fc yeniden ba\u015flatacak MainWindow.upgrade.explanation.manual=Vuze \u00fc kapat\u0131p, yeni s\u00fcr\u00fcm\u00fc indirip ve Vuze \u00fc yeniden ba\u015flat\u0131p kendiniz g\u00fcncelleyebilirsiniz MainWindow.upgrade.step1=Ad\u0131m 1: Yeni s\u00fcr\u00fcm\u00fc indirin MainWindow.upgrade.step2=Ad\u0131m 2: Bu s\u00fcr\u00fcm\u00fc kapat\u0131n ve Vuze \u00fcn Yeni S\u00fcr\u00fcm\u00fcn\u00fc ba\u015flat\u0131n. MainWindow.upgrade.hint1=\u0130pucu:\tBitir d\u00fc\u011fmesine basmak her\u015feyi otomatik halleder MainWindow.upgrade.hint2=\u0130pucu:\tE\u011fer Vuze u sonra kapatmak istiyorsan\u0131z l\u00fctfen \u0130ptal butonuna bas\u0131n ve\n\tkapatt\u0131ktan sonra Azureus2-new.jar\u2018\u0131 Azureus2.jar olarak yeniden adland\u0131r\u0131n MainWindow.upgrade.error.downloading.hint=Hata:\tYeni s\u00fcr\u00fcm\u00fc indirmek olanaks\u0131z. L\u00fctfen kendiniz g\u00fcncelle\u015ftirin. MainWindow.upgrade.section.info=Yeni S\u00fcr\u00fcm Mevcut MainWindow.upgrade.section.manual=Elle G\u00fcncelle\u015ftirme MainWindow.upgrade.section.automatic=Otomatik G\u00fcncelle\u015ftirme MainWindow.upgrade.tooltip.progressbar=\u0130ndirme durumu burada g\u00f6steriliyor Button.next=\u0130leri Button.finish=Bitir Button.cancel=\u0130ptal LocaleUtil.title=Kodlama Se\u00e7 LocaleUtil.section.chooseencoding=Dosya ad\u0131 i\u00e7in kodlama se\u00e7 LocaleUtil.label.chooseencoding=L\u00fctfen kodlama i\u00e7in en uyumluyu se\u00e7in LocaleUtil.label.hint.doubleclick=\u0130pucu: Bir sat\u0131ra \u00e7ift t\u0131klamak kodlama se\u00e7er ve ileti\u015fim kutusunu kapat\u0131r LocaleUtil.label.checkbox.rememberdecision=Kalan dosya adlar\u0131 i\u00e7in verilen karar\u0131 hat\u0131rla LocaleUtil.column.encoding=Kodlama IrcClient.copyright=PircBot Java IRC API kullan\u0131l\u0131yor - http://www.jibble.org/pircbot.php IrcClient.connecting=Ba\u011flan\u0131yor IrcClient.connected=Ba\u011fl\u0131 IrcClient.joining=Giriliyor IrcClient.channel=Kanal IrcClient.joined=Girildi IrcClient.error=Hata IrcClient.hasjoined=kat\u0131ld\u0131 IrcClient.haskicked=att\u0131 IrcClient.hasleft=terketti IrcClient.nowknown=Ad de\u011fi\u015ftirdi : IrcClient.topicforchannel=Kanal konusu IrcClient.disconnected=...ile ba\u011flant\u0131 kesildi IrcClient.noNick=Takma Ad belirtilmedi. L\u00fctfen 'Yap\u0131land\u0131rma' G\u00f6r\u00fcn\u00fcm e gidin IrcView.actionnotsupported=Bu komut desteklenmiyor IrcView.clientsconnected=kullan\u0131c\u0131lar IrcView.privateto=Kime IrcView.privatefrom=Kimden IrcView.noticefrom=Bildirim : IrcView.errormsg=Tanl\u0131\u015f s\u00f6zdizim /msg : /msg kullan\u0131c\u0131 mesaj IrcView.help=Ge\u00e7erli komutlar :\n . /help : bu mesaj\u0131 g\u00f6sterir\n . /nick | /name : ad\u0131n\u0131z\u0131 de\u011fi\u015ftirir \n . /me komut : bir komut g\u00f6nderir \n . /msg takma ad mesaj : birine \u00f6zel mesaj g\u00f6nderir \n . /r mesaj : son gelen \u00f6zel mesaja cevap g\u00f6nderir\n . /join #kanal : bunulunan kanal\u0131 de\u011fi\u015ftirir PasswordWindow.title=Vuze Kilitlendi PasswordWindow.passwordprotected=Vuze \u015fifreyle korunuyor.\nVuze penceresini g\u00f6rmek i\u00e7in l\u00fctfen buraya \u015fifrenizi girin : Button.ok=Tamam TrackerChangerWindow.title=\u0130zleyici Ekle TrackerChangerWindow.newtracker=Yeni izleyici adresi ekle PeersView.discarded=Vazge\u00e7ildi PeersView.discarded.info=Her ne kadar ihtiyac\u0131n\u0131z olmasa da bir \u015fekilde ald\u0131\u011f\u0131n\u0131z veri, dolay\u0131s\u0131yla ondan kurtulabilirsiniz. discarded=vazge\u00e7ildi MyTorrentsView.#=# MyTorrentsView.menu.move=Ta\u015f\u0131 MyTorrentsView.menu.moveUp=Yukar\u0131 MyTorrentsView.menu.moveDown=A\u015fa\u011f\u0131 GeneralView.label.hashfails=Veri Do\u011frulama Hatas\u0131: GeneralView.label.shareRatio=Payla\u015f\u0131m Oran\u0131 : ConfigView.section.downloadManagement=\u0130ndirme Y\u00f6netimi ConfigView.label.startRatioPeers=... e\u015f i\u00e7in 1 ortakdan az varsa yay\u0131mlamaya ba\u015fla ConfigView.text.neverStop=Asla Durma ConfigView.text.neverStart=Asla Ba\u015flama ConfigView.text.peers=E\u015f ConfigView.label.checkOncompletion=\u0130ndirme tamamland\u0131\u011f\u0131nda tekrar denetle wizard.title=Torrent Olu\u015ftur wizard.previous=< Geri wizard.next=\u0130leri > wizard.finish=Bitir wizard.mode=\u0130zleyici / Kip wizard.tracker=\u0130zleyici: wizard.invalidurl=Bu adres ge\u00e7erli de\u011fil wizard.singlefile=Tek dosya wizard.singlefile.help=Tek bir dosyadan torrent olu\u015ftur wizard.directory=Dizin wizard.directory.help=Bir dizinden torrent dosyas\u0131 olu\u015ftur wizard.choosefile=Dosya Se\u00e7 wizard.file=Dosya : wizard.browse=G\u00f6z at... wizard.choosedirectory=Dizin Se\u00e7 wizard.invalidfile=Ge\u00e7ersiz Dosya! wizard.invaliddirectory=Ge\u00e7ersiz Dizin! wizard.torrentFile=Torrent Dosyas\u0131 wizard.choosetorrent=L\u00fctfen yarat\u0131lacak torrent dosyas\u0131n\u0131 se\u00e7in wizard.information=Bilgi wizard.notimplemented=Daha y\u00fcr\u00fct\u00fclmedi wizard.progresstitle=Torrent Dosyas\u0131 Olu\u015fturuluyor wizard.savingfile=Dosya Kaydediliyor... wizard.filesaved=Dosya kaydedildi. wizard.close=Kapat Torrent.create.progress.piecelength=Par\u00e7a uzunlu\u011fu: Torrent.create.progress.piececount=Par\u00e7a say\u0131s\u0131: Torrent.create.progress.totalfilesize=Toplam dosya boyutu: Torrent.create.progress.totalfilecount=Toplam dosya say\u0131s\u0131: Torrent.create.progress.parsingfiles=Dosyalar ayr\u0131\u015ft\u0131r\u0131l\u0131yor Torrent.create.progress.hashing=Dosyalar\u0131n hesaba dayal\u0131 adreslemesi ger\u00e7ekle\u015ftiriliyor MainWindow.upgrade.downloadingfrom=Buradan \u0130ndiriliyor : MainWindow.menu.view.ipFilter=IP S\u00fczge\u00e7leri ConfigView.section.ipfilter=IP S\u00fczge\u00e7leri ConfigView.section.ipfilter.description=Tan\u0131m ConfigView.section.ipfilter.start=Ba\u015flang\u0131\u00e7 IP'si ConfigView.section.ipfilter.end=Biti\u015f IP'si ConfigView.section.ipfilter.add=Ekle ConfigView.section.ipfilter.remove=Kald\u0131r ConfigView.section.ipfilter.edit=D\u00fczenle ConfigView.section.ipfilter.save=Kaydet ConfigView.section.ipfilter.editFilter=S\u00fczge\u00e7 d\u00fczenle ConfigView.section.ipfilter.enable=Etkinle\u015ftir PeersView.menu.close=Kapat seedmore.title=Torrent yeterince seed edilmedi seedmore.shareratio=Bu torrentteki payla\u015f\u0131m oran\u0131n\u0131z: seedmore.uploadmore=%100'\u00fcn alt\u0131nda payla\u015f\u0131m oran\u0131 bittorrent a\u011f\u0131 i\u00e7in iyi de\u011fildir.\nBu torrenti biraz daha yay\u0131mlamal\u0131s\u0131n\u0131z.\nDurdurmak istedi\u011finize emin misiniz? ConfigView.label.showpopuponclose=Payla\u015f\u0131m oran\u0131 1'den d\u00fc\u015f\u00fck yay\u0131mlamalar\u0131 durdurmadan \u00f6nce bir onay kutucu\u011fu g\u00f6ster. ConfigView.label.startNumSeeds=\nE\u011fer ...dan az varsa yay\u0131mlamaya ba\u015fla\n \u2013 T\u00fcm di\u011fer komutlar\u0131 \u00e7i\u011fner ConfigView.label.seeds=ortak ConfigView.section.seeding=Yay\u0131mlama MyTorrentsView.menu.removeand=Kald\u0131r\u0131rken... MyTorrentsView.menu.removeand.deletetorrent=Torrent Dosyas\u0131n\u0131 Sil MyTorrentsView.menu.removeand.deletedata=Veriyi Sil MyTorrentsView.menu.removeand.deleteboth=Her \u0130kisini de Sil deletedata.title=Uyar\u0131 deletedata.message1=Buradaki VER\u0130'yi silmek \u00fczeresiniz :\n MainWindow.menu.file.configure=Yap\u0131land\u0131rma Sihirbaz\u0131 configureWizard.title=Yap\u0131land\u0131rma Sihirbaz\u0131 configureWizard.welcome.title=Vuze Yap\u0131land\u0131rma Sihirbaz\u0131na Ho\u015f Geldiniz configureWizard.welcome.message=Bu sihirbaz Vuze u genel kullan\u0131ma ayarlaman\u0131za yard\u0131m edecektir. \u0130leri d\u00fczeyde yap\u0131land\u0131rma i\u00e7in G\u00f6r\u00fcn\u00fcm > Yap\u0131land\u0131rma se\u00e7imini kullan\u0131n configureWizard.transfer.title=Aktar\u0131m ve Ba\u011flant\u0131 ayarlar\u0131 configureWizard.transfer.hint=\u0130pucu: Hatt\u0131n\u0131z\u0131n ger\u00e7ek h\u0131z\u0131n\u0131 biraz az g\u00f6stermek en iyi ayarlardand\u0131r. configureWizard.transfer.message=L\u00fctfen a\u015fa\u011f\u0131daki ba\u011flant\u0131lardan birini se\u00e7in. G\u00f6nderme h\u0131z\u0131n\u0131z\u0131n d\u00fc\u015f\u00fck olmas\u0131 indirme h\u0131z\u0131n\u0131z\u0131 olumsuz etkileyecektir. G\u00f6nderme h\u0131z\u0131 SADECE indirdi\u011finiz Torrent dosyas\u0131 i\u00e7in say\u0131ld\u0131\u011f\u0131ndan, ayn\u0131 anda \u00e7ok say\u0131da torrent dosyas\u0131 indirmek, yava\u015f bir ba\u011flant\u0131 h\u0131z\u0131yla sonu\u00e7lanacakt\u0131r. Biz, Torrent ba\u015f\u0131na en az 5KB/s kullanman\u0131z\u0131 \u00f6neriyoruz. [c1]Ne kadar h\u0131zl\u0131 g\u00f6nderirseniz o kadar h\u0131zl\u0131 indirirsiniz (torrent h\u0131z\u0131na ba\u011fl\u0131 olarak). configureWizard.transfer.connection=Ba\u011flant\u0131 t\u00fcr\u00fc: configureWizard.transfer.connection.0=\u00d6zel configureWizard.transfer.connection.1=modem/isdn configureWizard.transfer.connection.2=adsl/kablo xxx/128 kbps configureWizard.transfer.connection.3=adsl/kablo xxx/256 kbps configureWizard.transfer.connection.4=adsl/kablo xxx/384 kbps configureWizard.transfer.connection.5=adsl/kablo xxx/512 kbps configureWizard.transfer.connection.6=adsl/kablo xxx/768 kbps configureWizard.transfer.connection.7=adsl/kablo xxx/1024 kbps configureWizard.transfer.maxUpSpeed=En y\u00fcksek g\u00f6nderme h\u0131z\u0131 (KB/s): configureWizard.transfer.maxActiveTorrents=En fazla etkin torrent: configureWizard.transfer.maxDownloads=En fazla indirme say\u0131s\u0131: configureWizard.transfer.maxUploadsPerTorrent=Torrent ba\u015f\u0131na en fazla g\u00f6nderme say\u0131s\u0131: configureWizard.nat.title=NAT / Sunucu Ba\u011flant\u0131 Noktalar\u0131 configureWizard.nat.message=Bittorrent'ten en iyi verimi alabilmek i\u00e7in internet eri\u015fimine tam izin verilmesi \u0131srarla tavsiye edilir. Varsay\u0131lan bittorrent ba\u011flant\u0131 noktas\u0131 aral\u0131\u011f\u0131 6881'den 6889'a kadard\u0131r. Bu ara\u00e7 sizin varsay\u0131lan ba\u011flant\u0131 noktalar\u0131n\u0131 s\u0131naman\u0131za ve/veya de\u011fi\u015ftirmenize olanak verir. E\u011fer etkin indirmeleriniz varsa, baz\u0131 ba\u011flant\u0131 noktalar\u0131 eri\u015filemez olabilir. configureWizard.nat.test=S\u0131na configureWizard.nat.testing=Ba\u011flant\u0131 Noktas\u0131 s\u0131nan\u0131yor configureWizard.nat.ok=Tamam configureWizard.nat.ko=NAT Hatas\u0131 configureWizard.nat.unable=S\u0131nama olanaks\u0131z configureWizard.file.title=Torrentler / Dosyalar configureWizard.file.message1=Vuze indirilecek torrentleri \u00f6zel bir dizine kaydedecek. Bu dizini a\u015fa\u011f\u0131da belirleyebilirsiniz: configureWizard.file.path=Yol configureWizard.file.browse=G\u00f6z at configureWizard.file.message2=Vuze torrent dosyalar\u0131n\u0131za biraz veri ekleyerek dosyalar\u0131n\u0131z\u0131n s\u00fcrd\u00fcr\u00fcm\u00fcn\u00fc an\u0131nda yapabilir. Bu \u00f6zelli\u011fi kullanarak yar\u0131 indirilmi\u015f par\u00e7alar\u0131 bile s\u00fcrd\u00fcrebilirsiniz. configureWizard.file.fastResume=H\u0131zl\u0131 s\u00fcrd\u00fcrmeyi etkinle\u015ftir configureWizard.file.invalidPath=Ge\u00e7ersiz dizin configureWizard.finish.title=Tamamland\u0131 configureWizard.finish.message=Vuze yap\u0131land\u0131r\u0131ld\u0131, iyi e\u011flenceler ! wizard.close.confirmation=Onay wizard.close.message=Vuze tekrar ba\u015flad\u0131\u011f\u0131nda bu sihirbaz\u0131n yine g\u00f6r\u00fcnmesini istiyor musunuz? exportTorrentWizard.title=Torrent Ver exportTorrentWizard.torrentfile.title=Torrent Se\u00e7imi Giri\u015fi exportTorrentWizard.torrentfile.message=Verilecek torrenti se\u00e7in exportTorrentWizard.torrentfile.path=Yol exportTorrentWizard.torrentfile.browse=G\u00f6z at exportTorrentWizard.torrentfile.invalidPath=Ge\u00e7ersiz Torrent Dosyas\u0131 exportTorrentWizard.exportfile.title=Torrent se\u00e7imini Ver exportTorrentWizard.exportfile.message=Verilecek dosyay\u0131 girin exportTorrentWizard.exportfile.path=Yol exportTorrentWizard.exportfile.browse=G\u00f6z at exportTorrentWizard.exportfile.invalidPath=Ge\u00e7ersiz Verme Dosyas\u0131 exportTorrentWizard.finish.title=Tamamland\u0131 exportTorrentWizard.finish.message=Verme ba\u015far\u0131yla tamamland\u0131 exportTorrentWizard.process.inputfilebad.title=Torrent dosyas\u0131 ge\u00e7ersiz exportTorrentWizard.process.inputfilebad.message=Giri\u015f Dosyas\u0131na eri\u015filirken bir hata olu\u015ftu: exportTorrentWizard.process.outputfileexists.title=Dosya zaten var exportTorrentWizard.process.outputfileexists.message=\u00c7\u0131k\u0131\u015f dosyas\u0131 zaten var \u2013 \u00fczerine yaz? exportTorrentWizard.process.torrentfail.title=Torrent Okuma ba\u015far\u0131s\u0131z exportTorrentWizard.process.exportfail.title=Torrent Verme ba\u015far\u0131s\u0131z exportTorrentWizard.process.unknownfail.title=Beklenmeyen Hata importTorrentWizard.title=XML torrenti al importTorrentWizard.torrentfile.title=Torrent Se\u00e7imini Gir importTorrentWizard.torrentfile.message=Torrent Dosyas\u0131n\u0131n al\u0131naca\u011f\u0131 yeri girin importTorrentWizard.torrentfile.path=Yol importTorrentWizard.torrentfile.browse=G\u00f6z at importTorrentWizard.torrentfile.invalidPath=Ge\u00e7ersiz torrent dosyas\u0131 importTorrentWizard.importfile.title=Dosya Se\u00e7imini Al importTorrentWizard.importfile.message=Al\u0131nacak xml dosyas\u0131n\u0131 se\u00e7 importTorrentWizard.importfile.path=Yol importTorrentWizard.importfile.browse=G\u00f6z at importTorrentWizard.importfile.invalidPath=Ge\u00e7ersiz alma dosyas\u0131 importTorrentWizard.finish.title=Tamamland\u0131 importTorrentWizard.finish.message=Alma ba\u015far\u0131yla tamamland\u0131 importTorrentWizard.process.inputfilebad.title=Alma Dosyas\u0131 Ge\u00e7ersiz importTorrentWizard.process.inputfilebad.message=Giri\u015f dosyas\u0131na eri\u015firken bir hata olu\u015ftu : importTorrentWizard.process.outputfileexists.title=Dosya Zaten Var importTorrentWizard.process.outputfileexists.message=\u00c7\u0131kt\u0131 dosyas\u0131 zaten var - \u00fczerine yaz\u0131ls\u0131n m\u0131? importTorrentWizard.process.torrentfail.title=Torrent'i Yazma Ba\u015far\u0131s\u0131z importTorrentWizard.process.importfail.title=Torrent'i Alma Ba\u015far\u0131s\u0131z importTorrentWizard.process.unknownfail.title=Beklenmeyen Hata ConfigView.label.bindip=Yerel IP adresine ba\u011fla or interface ConfigView.label.zeronewfiles=Yeni dosyalar i\u00e7in disk alan\u0131 ay\u0131r ConfigView.label.zeronewfiles.tooltip=Disk birle\u015ftirme ihtiyac\u0131n\u0131 azalt\u0131r ConfigView.section.stats=\u0130statistikler ConfigView.section.stats.enable=Etkinle\u015ftir ConfigView.section.stats.defaultsavepath=\u0130statistikleri kaydetme dizini ConfigView.section.stats.choosedefaultsavepath=L\u00fctfen istatistikleri kaydetme dizinini se\u00e7in ConfigView.section.stats.savefreq=Kaydetme s\u0131kl\u0131\u011f\u0131 ConfigView.section.stats.minutes=dk ConfigView.section.stats.hours=sa ConfigView.section.stats.seconds=sn ConfigView.section.stats.savefile=\u0130statistik dosya ad\u0131 MyTorrentsView.menu.export=XML Torrenti... MyTorrentsView.menu.host=Bar\u0131nd\u0131r... ManagerItem.finishing=Bitiriliyor ConfigView.dialog.choosedefaulttorrentpath=L\u00fctfen varsay\u0131lan torrent dizinini se\u00e7in ConfigView.dialog.choosemovepath=L\u00fctfen dizinin ta\u015f\u0131n\u0131laca\u011f\u0131 yeri se\u00e7in ConfigView.label.movecompleted=Tamamlanan dosyalar\u0131 ta\u015f\u0131 (\u0130ndirme i\u015flemi bittikten sonra) ConfigView.label.moveremoved=Tamamlanan dosyalar\u0131 ta\u015f\u0131 (kald\u0131r\u0131ld\u0131\u011f\u0131nda) ConfigView.label.savetorrents='.torrent' dosyalar\u0131n\u0131 kaydet MainWindow.menu.view.mytracker=\u0130zleyicim MyTrackerView.title.full=\u0130zleyicim MyTrackerView.name=Ad MyTrackerView.tracker=\u0130zleyici MyTrackerView.status=Durum MyTrackerView.status.started=\u00c7al\u0131\u015f\u0131yor MyTrackerView.status.stopped=Durdu MyTrackerView.peers=E\u015fler MyTrackerView.seeds=Ortaklar MyTrackerView.announces=Duyurular MyTrackerView.uploaded=G\u00f6nderilen MyTrackerView.downloaded=\u0130ndirilen MyTrackerView.left=Sol ConfigView.section.style=Arabirim ConfigView.label.set_ui_transfer_speeds=Se\u00e7ilebilir Aktar\u0131m H\u0131zlar\u0131n\u0131 Ayarla ConfigView.label.set_ui_transfer_speeds.description=Durum \u00e7ubu\u011fu ve bildirim alan\u0131ndaki \u00f6ntan\u0131ml\u0131 indirme ve g\u00f6nderme h\u0131zlar\u0131n\u0131 elle belirlemeyi se\u00e7ebilirsiniz.\nDe\u011ferler virg\u00fclle ayr\u0131lm\u0131\u015f olmal\u0131d\u0131r. ConfigView.label.set_ui_transfer_speeds.description.download=\u0130ndirme h\u0131zlar\u0131n\u0131 ayarla (KB/s olarak) ConfigView.label.set_ui_transfer_speeds.description.upload=G\u00f6nderme h\u0131zlar\u0131n\u0131 ayarla (KB/s olarak) ConfigView.section.style.useCustomTabs=Kapanabilen sekmeleri kullan (Yeniden ba\u015flatma gerektirir) MainWindow.menu.view.plugins=Eklentiler fileDownloadWindow.saveTorrentIn=Torrent dosyalar\u0131n\u0131 kaydet... fileDownloadWindow.title=Vuze - Torrent \u0130ndirici fileDownloadWindow.downloading=\u0130ndiriliyor : fileDownloadWindow.status=Durum : fileDownloadWindow.state_initializing=Ba\u015flat\u0131l\u0131yor fileDownloadWindow.state_downloading=\u0130ndiriliyor fileDownloadWindow.state_error=Hata : MainWindow.menu.file.open.url=Adres openUrl.url=Adres : MyTorrentsView.menu.host.error.title=Torrent Bar\u0131nd\u0131rma Ba\u015far\u0131s\u0131z Oldu MyTorrentsView.menu.host.error.message=Torrent bar\u0131nd\u0131r\u0131l\u0131rken a\u015fa\u011f\u0131daki hata olu\u015ftu ConfigView.section.tracker=\u0130zleyici ConfigView.section.tracker.pollinterval=\u0130zleyici \u0130stemcisi Yoklama Aral\u0131\u011f\u0131 (sn) ConfigView.section.tracker.publishenable=Torrent ayr\u0131nt\u0131lar\u0131n\u0131 "" adresine yay\u0131mla ConfigView.section.tracker.ip=\u0130zleyicinin d\u0131\u015f IP adresi ConfigView.section.style.enableXPStyle=XP bi\u00e7emini etkinle\u015ftir (Yeniden ba\u015flatma gerektirir) IPChecker.external.service.dyndns.name=DynDNS IPChecker.external.service.dyndns.url=http://www.dyndns.org/ IPChecker.external.service.dyndns.description=Dynamic DNS Network Services, LLC ConfigView.section.tracker.checkip=D\u0131\u015fsal IP adresini otomatik bul... ipCheckerWizard.title=IP Denetleyicisi Sihirbaz\u0131 ipCheckerWizard.service=Hizmet ipCheckerWizard.chooseService=L\u00fctfen listedeki hizmetlerden bir IP Denetleyicisi Hizmeti se\u00e7in ipCheckerWizard.explanations=Bu sihirbaz\u0131 kullanarak d\u0131\u015f IP adresinizin ne oldu\u011funu bulabilirsiniz. IP adresiniz devingense, bir devingen DNS hizmetinde hesap a\u00e7man\u0131z\u0131 \u00f6neririz. Baz\u0131 hizmetler a\u015fa\u011f\u0131da listelenmi\u015ftir. Ba\u011flant\u0131lara t\u0131klayarak hesap a\u00e7abilirsiniz. Sonra IP adresi b\u00f6l\u00fcm\u00fcne kendi devingen sunucu ad\u0131n\u0131z\u0131 girin (\u00f6r: hostadim.dyndns.org). Kendi devingen DNS hizmetinizde IP adresinizi g\u00fcncelle\u015ftirmek i\u00e7in bir programa ihtiyac\u0131n\u0131z olacak. Bu yolla IP numaran\u0131z de\u011fi\u015fse bile, torrentleri bulundurabilirsiniz. ipCheckerWizard.service.description=Tan\u0131m : ipCheckerWizard.service.url=Link : ipCheckerWizard.progresstitle=IP Denetleniyor ipCheckerWizard.checkComplete=Tamamland\u0131 : ipCheckerWizard.checkFailed=Ba\u015far\u0131s\u0131z, \u00e7\u00fcnk\u00fc : wizard.tracker.local=Vuze i\u00e7indeki izleyiciyi kullan wizard.tracker.external=D\u0131\u015fsal izleyici kullan wizard.tracker.howToLocal=\tEtkinle\u015ftirmek i\u00e7in 'Ara\u00e7lar -> Se\u00e7enekler -> \u0130zleyici'ye gidin wizard.announceUrl=Duyuru Adresi : IPChecker.external.service.discoveryvip.name=Discoveryvip IPChecker.external.service.discoveryvip.url=http://ip.discoveryvip.com/ IPChecker.external.service.discoveryvip.description=Discoveryvip - Sadece IP adresi denetimi IPChecker.external.httpinvalidresponse=Ge\u00e7ersiz HTTP cevab\u0131 IPChecker.external.loadingwebpage=Web sayfas\u0131 y\u00fckleniyor IPChecker.external.analysingresponse=Yan\u0131t \u00e7\u00f6z\u00fcmleniyor IPChecker.external.addressextracted=\u00c7\u0131kar\u0131lm\u0131\u015f IP adresi IPChecker.external.httploadfail=Sayfa y\u00fcklemesi ba\u015far\u0131s\u0131z IPChecker.external.timeout=Zaman a\u015f\u0131m\u0131 IPChecker.external.ipnotfound=IP adresi bulunamad\u0131 ConfigView.section.tracker.pollintervalmin=En D\u00fc\u015f\u00fck ConfigView.section.tracker.pollintervalmax=En Y\u00fcksek ConfigView.section.tracker.pollintervalincby=.. kadar y\u00fckselt ConfigView.section.tracker.pollintervalincper=Her 'n' istemcide splash.loadingImages=Resimler Y\u00fckleniyor splash.initializeGui=Ana Pencere Ba\u015flat\u0131l\u0131yor splash.openViews=G\u00f6r\u00fcn\u00fcmler A\u00e7\u0131l\u0131yor splash.plugin=Eklenti y\u00fckleniyor : configureWizard.nat.tooManyPorts=S\u0131nanamayacak kadar \u00e7ok say\u0131da ba\u011flant\u0131 nokas\u0131 (en fazla 9) ConfigView.section.color=Renk \u015eemas\u0131 MyTorrentsView.menu.publish=Yay\u0131mla... MyTrackerView.status.published=Yay\u0131mland\u0131 MyTrackerView.completed=Tamamland\u0131 MainWindow.menu.file.open.torrentnodefault='.torrent' Dosyas\u0131 (Varsay\u0131lan kaydetmesiz) wizard.comment=Yorum ConfigView.label.movetorrent='.torrent' dosyas\u0131n\u0131 ta\u015f\u0131 ConfigView.label.movepartialdownloads=Baz\u0131 dosyalar 'indirilmeyecek' olarak i\u015faretlendi\u011finde ta\u015f\u0131 ConfigView.section.file.decoder.label=Bir se\u00e7im gerekti\u011finde kullan\u0131lacak varsay\u0131lan torrent kodlamas\u0131 ConfigView.section.file.decoder.nodecoder=Yok IPChecker.external.service.no-ip.name=No-IP IPChecker.external.service.no-ip.url=http://www.no-ip.com/ IPChecker.external.service.no-ip.description=Devingen ve dura\u011fan DNS hizmet sa\u011flay\u0131c\u0131s\u0131\n(serbest adres denetimi hizmeti bulunmuyor) ConfigView.section.tracker.publicenable=D\u0131\u015f torrentleri etkinle\u015ftir ConfigView.label.playdownloadspeech=\u0130ndirme i\u015flemi itti\u011finde konu\u015f ConfigView.label.playdownloadspeech.info=Konu\u015fma hizmeti \u015fu an i\u00e7in en iyi \u0130ngilizce olarak \u00e7al\u0131\u015f\u0131yor # # Tooltips # GeneralView.label.trackerurl.tooltip=Duyuru adresini panoya kopyalamak i\u00e7in t\u0131klay\u0131n GeneralView.label.trackerurlopen.tooltip=\u0130zleyici anasayfas\u0131n\u0131 a\u00e7mak i\u00e7in t\u0131klay\u0131n # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Grafik aray\u00fcz\u00fc g\u00fcncelleme s\u0131kl\u0131\u011f\u0131 ConfigView.section.style.graphicsUpdate=Grafik aray\u00fczle birlikte grafiksel \u00e7ubuklar\u0131n g\u00fcncellenme s\u0131kl\u0131\u011f\u0131 ConfigView.section.style.reOrderDelay=Grafik aray\u00fczle birlikte tablolar\u0131n yeniden d\u00fczenlenme s\u0131kl\u0131\u011f\u0131 [0: asla] ConfigView.section.style.reOrderDelay.never=Asla ConfigView.section.logging=G\u00fcnl\u00fck ConfigView.section.logging.enable=Tutulan g\u00fcnl\u00fc\u011f\u00fc dosyaya kaydet ConfigView.section.logging.logdir=G\u00fcnl\u00fck dosyas\u0131 dizini ConfigView.section.logging.choosedefaultsavepath=L\u00fctfen kaydedilecek dizini se\u00e7in GeneralView.label.updatein.querying=sorgulan\u0131yor... configureWizard.nat.sharePort=T\u00fcm torrentler i\u00e7in bir tek payla\u015f\u0131lan gelen ba\u011flant\u0131 noktas\u0131 kullan ConfigView.section.logging.maxsize=G\u00fcnl\u00fck dosyas\u0131 en b\u00fcy\u00fck boyutu ConfigView.section.tracker.passwordenableweb=A\u011f \u0130zleyicisi i\u00e7in parolay\u0131 etkinle\u015ftir ConfigView.section.tracker.passwordenabletorrent=Torrentler i\u00e7in parolay\u0131 etkinle\u015ftir ConfigView.section.tracker.username=Kullan\u0131c\u0131 ad\u0131 ConfigView.section.tracker.password=Parola columnChooser.title=S\u00fctun Ayarlar\u0131 columnChooser.move=Yer de\u011fi\u015ftirmek istedi\u011finiz sat\u0131rlar\u0131 s\u00fcr\u00fckleyip b\u0131rak\u0131n columnChooser.apply=Uygula columnChooser.columnname=S\u00fctun Ad\u0131 columnChooser.columndescription=Tan\u0131m TableColumn.header.shareRatio=Payla\u015f\u0131m Oran\u0131 MyTorrentsView.menu.editTableColumns=G\u00f6r\u00fcnt\u00fclenecek S\u00fctunlar\u0131 Se\u00e7 wizard.operationfailed=\u0130\u015flem ba\u015far\u0131s\u0131z authenticator.title=\u0130zin gerekli authenticator.realm=Realm authenticator.tracker=\u0130zleyici authenticator.user=Kullan\u0131c\u0131 ad\u0131 authenticator.password=\u015eifre ConfigView.label.allowSendVersion=Azurerus'un anonim s\u00fcr\u00fcm numaras\u0131 g\u00f6ndermesine ve yeni s\u00fcr\u00fcm ararken rassal kimlik numaras\u0131 g\u00f6ndermesine izin ver wizard.hint.mode=\u0130pucu:\tBir dosya veya dizin se\u00e7mek i\u00e7in bu sihirbaz \u00fczerine\n\ttek bir dosya veya dizini s\u00fcr\u00fckleyip b\u0131rakabilirsiniz wizard.hint.file=\u0130pucu:\tS\u00fcr\u00fckleyip b\u0131rakarak tek bir dosyay\u0131 se\u00e7ebilirsiniz wizard.hint.directory=\u0130pucu:\tS\u00fcr\u00fckleyip b\u0131rakarak tek bir dizini se\u00e7ebilirsiniz MainWindow.menu.help.checkupdate=G\u00fcncellemeleri Denetle TableColumn.header.down=\u0130ndirilen Veri TableColumn.header.up=G\u00f6nderilen Veri ConfigView.section.tracker.passwordenabletorrent.info=Uygun Bittorrent istemcisi gerekir (\u00f6r: Vuze ConfigView.section.style.confirmationOnExit=\u00c7\u0131k\u0131\u015fta onay penceresi g\u00f6ster MainWindow.dialog.exitconfirmation.title=Vuze kapat\u0131ls\u0131n m\u0131? MainWindow.dialog.exitconfirmation.text=Program\u0131n kapat\u0131lmas\u0131n\u0131 ger\u00e7ekten istiyor musunuz? SystemTray.menu.stopalltransfers=T\u00fcm Aktar\u0131mlar\u0131 Durdur TrayWindow.menu.stopalldownloads=T\u00fcm \u0130ndirmeleri Durdur ConfigView.section.tracker.sslport.info=Daha fazla bilgi i\u00e7in SSS'a bak\u0131n wizard.tracker.ssl=SSL kullan ConfigView.label.playdownloadfinished=\u0130ndirme bitti\u011finde sesli uyar\u0131 ver ConfigView.label.popupdownloadfinished=\u0130ndirme tamamland\u0131\u011f\u0131nda a\u00e7\u0131l\u0131r uyar\u0131 g\u00f6ster ConfigView.label.popupfilefinished=Dosya tamamland\u0131\u011f\u0131nda a\u00e7\u0131l\u0131r uyar\u0131 g\u00f6ster TableColumn.header.pieces=Par\u00e7alar TableColumn.header.pieces.info=\u0130ndirmi\u015f oldu\u011funuz par\u00e7alar\u0131 g\u00f6steren \u00e7ubuk grafik TableColumn.header.completion=Tamamlanma TableColumn.header.completion.info=Tamamlanma y\u00fczdesinin grafiksel tasviri ConfigView.section.style.showdownloadbasket=\u0130ndirme sepetini g\u00f6ster (.torrentleri s\u00fcr\u00fckle ve b\u0131rak) ConfigView.section.style.alwaysShowTorrentFiles=Torrent dosyalar\u0131n\u0131 her zaman Ayr\u0131nt\u0131lar/Dosyalar'da g\u00f6ster wizard.multitracker=Torrent'e \u00c7oklu-\u0130zleyici bilgisi ekle wizard.multitracker.title=\u00c7oklu-\u0130zleyici wizard.multitracker.configuration=\u00c7oklu-\u0130zleyici Yap\u0131land\u0131rmas\u0131 wizard.multitracker.new=Yeni... wizard.multitracker.edit=D\u00fczenle... wizard.multitracker.delete=Sil wizard.multitracker.group=\u0130zleyici Grubu wizard.multitracker.edit.title=\u00c7oklu-\u0130zleyici D\u00fczenleyicisi wizard.multitracker.edit.name=Ad wizard.multitracker.edit.save=Kaydet wizard.multitracker.edit.newgroup=Yeni Grup wizard.multitracker.edit.deletegroup=Sil wizard.multitracker.edit.newtracker=Yeni \u0130zleyici wizard.multitracker.edit.deletetracker=Sil wizard.multitracker.edit.edit=D\u00fczenle wizard.addingmt=\u00c7oklu \u0130zleyici bilgisi ekleniyor.. wizard.multitracker.noannounce=Duyuru URL'si izleyici listenizde bulunmuyor MyTorrentsView.menu.recheck=Veri Do\u011frulamas\u0131 Yap iconBar.showDownloadBar.tooltip=\u0130ndirme \u00c7ubu\u011funu G\u00f6ster iconBar.start.tooltip=Ba\u015flat iconBar.stop.tooltip=Durdur iconBar.remove.tooltip=Kald\u0131r iconBar.openNoDefault.tooltip='.torrent' dosyas\u0131 a\u00e7 (Varsay\u0131lan kaydetmesiz) iconBar.openURL.tooltip=URL a\u00e7 iconBar.openFolder.tooltip=Dizin a\u00e7 iconBar.new.tooltip=Torrent olu\u015ftur iconBar.up.tooltip=Yukar\u0131 ta\u015f\u0131 iconBar.down.tooltip=A\u015fa\u011f\u0131 ta\u015f\u0131 iconBar.run.tooltip=A\u00e7 iconBar.host.tooltip=Bar\u0131nd\u0131r iconBar.publish.tooltip=Yay\u0131nla MyTorrentsView.menu.editTracker=\u0130zleyici Adres(ler)ini D\u00fczenle GeneralView.menu.selectTracker=Se\u00e7 ConfigView.section.stats.xslfile=XSL dosya ad\u0131 ConfigView.section.stats.xslfiledetails=\u0130statistik dosyas\u0131 \u00fcst ba\u015fl\u0131\u011f\u0131nda etiketine eklenecek ConfigView.label.savetorrentbackup=Yedekle ConfigView.section.tracker.forceport=D\u0131\u015fsal torrentleri \u00f6ntan\u0131ml\u0131 ba\u011f. noktas\u0131na zorla ConfigView.section.ipfilter.allow=Bu aral\u0131\u011fa \u0130Z\u0130N ver (Varsay\u0131lan\u0131: REDDET) ConfigView.section.ipfilter.list.inrange=aral\u0131kta ConfigView.section.ipfilter.list.notinrange=aral\u0131kta de\u011fil ConfigView.section.ipfilter.list.title=Engellenmi\u015f IP'lerin Listesi ConfigView.label.allowsameip=Ayn\u0131 IP'den \u00e7oklu ba\u011flant\u0131ya izin ver ConfigView.label.allowsameip.tooltip=Sadece GEREKL\u0130YSE i\u015faretleyin.\nBu bir s\u00f6m\u00fcr\u00fcc\u00fc korumas\u0131d\u0131r (ge\u00e7ersiz durumdayken). ManagerItem.superseeding=S\u00fcper-Yay\u0131mlama ConfigView.label.userSuperSeeding=S\u00fcper yay\u0131mlama kipini kullan PeersView.uniquepiece=Par\u00e7a (S\u00fcper-Yay\u0131mlama Kipi) PeersView.uniquepiece.none=Yok PeersView.timetosend=Par\u00e7ay\u0131 tekrar g\u00f6nderme zaman\u0131 (S\u00fcper-Yay\u0131mlama Kipi) ConfigView.section.style.addurlsilently=Ge\u00e7ilen URL'leri sessizce a\u00e7 ConfigView.section.style.addurlsilently.tooltip=Ge\u00e7ilen/d\u00fc\u015f\u00fcr\u00fclen '.torrent' adreslerini ileti\u015fim kutusunu a\u00e7madan otomatik indirmeye ba\u015flar. ConfigView.section.file.decoder.prompt=E\u011fer kodlama se\u00e7imi olanakl\u0131ysa her zaman se\u00e7imi onaylat. ConfigView.section.file.decoder.prompt.tooltip=E\u011fer kodlama se\u00e7imi olanakl\u0131ysa her zaman bir ileti\u015fim kutusu g\u00f6ster MyTorrentsView.menu.moveTop=En \u00dcste MyTorrentsView.menu.moveEnd=En Alta ConfigView.label.moveonlyusingdefaultsave=Sadece varsay\u0131lan dizindeyse ConfigView.label.moveonlyusingdefaultsave.tooltip='.torrent' dosyas\u0131n\u0131 sadece varsay\u0131lan dizindeyse ta\u015f\u0131 ConfigView.label.watchtorrentfolder=Yeni '.torrent' dosyalar\u0131 i\u00e7in tara ConfigView.label.watchtorrentfolder.tooltip=Belirlenen dizinde d\u00fczenli olarak yeni torrent arar ConfigView.label.watchtorrentfolderinterval=S\u0131kl\u0131k ConfigView.label.watchtorrentfolderinterval.tooltip=Se\u00e7ilen dizinin taranma s\u0131kl\u0131\u011f\u0131 ConfigView.dialog.choosewatchtorrentfolderpath=L\u00fctfen '.torrent' alma dizinini se\u00e7in. ConfigView.label.startwatchedtorrentsstopped=\u00c7al\u0131\u015fm\u0131yor durumunda ba\u015fla ConfigView.label.startwatchedtorrentsstopped.tooltip=Yeni torrentleri \u00c7ALI\u015eMIYOR olarak ekler ConfigView.section.plugins=Eklentiler wizard.maketorrent.filesize=Dosya Boyutu wizard.maketorrent.piececount=Par\u00e7a Say\u0131s\u0131 wizard.maketorrent.piecesize=Par\u00e7a Boyutu wizard.maketorrent.auto=Otomatik MainWindow.menu.view.stats=\u0130statistikler SpeedView.title.full=Etkinlik SpeedView.downloadSpeed.title=\u0130ndirme H\u0131z\u0131 SpeedView.uploadSpeed.title=G\u00f6nderme H\u0131z\u0131 ConfigView.section.style.useSIUnits=IEC birimlerini kullan (KB yerine KiB gibi) iconBar.top.tooltip=En \u00fcste ta\u015f\u0131 iconBar.bottom.tooltip=En alta ta\u015f\u0131 TableColumn.header.health=Sa\u011fl\u0131k MyTorrentsView.menu.health=Sa\u011fl\u0131k Hakk\u0131nda health.explain.grey=Torrentin \u00e7al\u0131\u015fmad\u0131\u011f\u0131 anlam\u0131na gelir. health.explain.red=\u0130ndirirken hi\u00e7bir e\u015fe ba\u011fl\u0131 olmad\u0131\u011f\u0131n\u0131z anlam\u0131na gelir. health.explain.blue=\u0130ndirirken, birka\u00e7 e\u015fe ba\u011fl\u0131 oldu\u011funuz ama izleyicinin \u00e7evrimd\u0131\u015f\u0131 oldu\u011fu anlam\u0131na;\nyay\u0131mlarken de hen\u00fcz hi\u00e7bir e\u015fe ba\u011fl\u0131 olmad\u0131\u011f\u0131n\u0131z anlam\u0131na gelir. health.explain.yellow=\u0130zleyicinin sa\u011fl\u0131kl\u0131 oldu\u011fu ve e\u015flere ba\u011fl\u0131 oldu\u011funuz, fakat hi\u00e7 uzak ba\u011flant\u0131n\u0131z olmad\u0131\u011f\u0131 anlam\u0131na gelir.\nE\u011fer torrentleriniz hep sar\u0131 durumdaysa, bir NAT sorununuz olabilir. health.explain.green=Her\u015fey yolunda yani sa\u011fl\u0131kl\u0131s\u0131n\u0131z demektir. ConfigView.section.style.alwaysRefreshMyTorrents=Torrentlerimi her zaman yenile ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Bu se\u00e7enek, g\u00f6sterilmese bile Torrentlerimin g\u00f6r\u00fcn\u00fcm\u00fcn\u00fc yeniler (baz\u0131 mirc eklentileri i\u00e7in faydal\u0131d\u0131r) # #2.0.7.0 # security.certtruster.title=G\u00fcvenlik Sertifika Uyar\u0131s\u0131 security.certtruster.intro=G\u00fcvenlik sertifikas\u0131 g\u00fcvenmedi\u011finiz bir \u015firket taraf\u0131ndan yay\u0131nlanm\u0131\u015f security.certtruster.resource=Kaynak: security.certtruster.prompt=Ona g\u00fcvenmek istiyor musunuz? security.certtruster.yes=Evet security.certtruster.no=Hay\u0131r ConfigView.section.tracker.torrentsperpage=Sayfa ba\u015f\u0131na ka\u00e7 tane torrent ? [0: s\u0131n\u0131rs\u0131z] MainWindow.menu.file.share=Payla\u015f MainWindow.menu.file.share.file=Dosya... MainWindow.menu.file.share.dir=Dizin... MainWindow.menu.file.share.dircontents=Dizin \u0130\u00e7erikleri... MainWindow.menu.file.share.dircontentsrecursive=Dizin \u0130\u00e7erikleri... (\u00d6zyineli) MainWindow.dialog.share.sharefile=Payla\u015f\u0131lacak Dosya Se\u00e7in MainWindow.dialog.share.sharedir=Payla\u015f\u0131lacak Dizin Se\u00e7in MainWindow.dialog.share.sharedircontents=Payla\u015f\u0131lacak Dizin \u0130\u00e7eriklerini Se\u00e7in MainWindow.dialog.share.sharedircontents.recursive=\u00d6zyineli globalmanager.download.remove.veto=Kald\u0131rma \u0130\u015flemi Veto Edildi plugin.sharing.download.remove.veto=Bu indirme payla\u015f\u0131lan bir kayna\u011f\u0131n sonucu.\n\u0130ndirmeyi kald\u0131rmak i\u00e7in ili\u015fkili payla\u015f\u0131m\u0131 kald\u0131r\u0131n: go to Tools->My Classic-Shares. ConfigView.label.prioritizefirstpiece=\u00d6nceli\u011fi ilk ve son dosya(lar)a ver ConfigView.section.file.confirm_data_delete=Veri silerken onay iste ConfigView.section.file.confirm_data_delete.tooltip='Kald\u0131r\u0131rken...' se\u00e7ene\u011fini kullan\u0131rken veri silinmeden \u00f6nce onay ister TrayWindow.menu.startalldownloads=T\u00fcm \u0130ndirmeleri Ba\u015flat SystemTray.menu.startalltransfers=T\u00fcm Aktar\u0131mlar\u0131 Ba\u015flat sharing.progress.title=Payla\u015f\u0131m Oran\u0131 sharing.progress.hide=Gizle MainWindow.menu.view.myshares=Payla\u015f\u0131mlar\u0131m MySharesView.title.full=Payla\u015f\u0131mlar\u0131m MySharesView.name=Ad MySharesView.type=T\u00fcr MySharesView.type.file=Dosya MySharesView.type.dir=Dizin MySharesView.type.dircontents=Dizin i\u00e7erikleri MySharesView.type.dircontentsrecursive=Dizin i\u00e7erikleri (\u00f6zyineli) MySharesView.menu.remove=Kald\u0131r ConfigView.section.tracker.extensions=Uzant\u0131lar ConfigView.section.tracker.sendpeerids=\u0130ndirenlere e\u015f kimlik bilgisini g\u00f6nder ConfigView.section.tracker.enableudp=\u0130zleyici UDP ileti\u015fim kural\u0131n\u0131 etkinle\u015ftir plugin.sharing.torrent.remove.veto=Bu izleyici kayd\u0131, payla\u015f\u0131lan bir kayna\u011f\u0131n sonucu.\n\u0130ndirmeyi kald\u0131rmak i\u00e7in ili\u015fkili payla\u015f\u0131m\u0131 kald\u0131r: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=\u0130ndirme kald\u0131r\u0131lamaz, zira durdurulmad\u0131 plugin.sharing.remove.veto=Bu payla\u015f\u0131m, bir 'dizin i\u00e7erikleri' payla\u015f\u0131m\u0131n\u0131n bir alt payla\u015f\u0131m\u0131 ve silinemez.\n K\u00f6k payla\u015f\u0131m\u0131 silin GeneralView.label.hash.tooltip=Do\u011frulama verisini panoya kopyalamak i\u00e7in t\u0131klay\u0131n ConfigView.section.tracker.maxpeersreturned=Geri d\u00f6nen en fazla e\u015f say\u0131s\u0131 [0: s\u0131n\u0131rs\u0131z] ConfigView.label.serverport=Ba\u011flant\u0131 noktas\u0131 configureWizard.nat.server.tcp_listen_port=Gelen TCP Ba\u011flant\u0131 Noktas\u0131 ConfigView.section.sharing=Payla\u015f\u0131m ConfigView.section.sharing.usessl=Payla\u015f\u0131lan kaynaklar i\u00e7in SSL kullan (\u0130zleyici yap\u0131land\u0131rmas\u0131 gerektirir) ConfigView.section.style.dropdiraction=Dizinler i\u00e7in s\u00fcr\u00fckle ve b\u0131rak eylemi ConfigView.section.style.dropdiraction.opentorrents=A\u00e7\u0131k Torrentler ConfigView.section.style.dropdiraction.sharefolder=Payla\u015f\u0131m Dizini ConfigView.section.style.dropdiraction.sharefoldercontents=Payla\u015f\u0131m \u0130\u00e7eri\u011fi # # 2.0.7.x # Categories.all=T\u00fcm\u00fc Categories.uncategorized=Ulams\u0131z CategoryAddWindow.message=Yeni ulam i\u00e7in bir ad girin CategoryAddWindow.title=Yeni Ulam Ekle ConfigView.label.autoSeedingIgnoreInfo=Yoksay\u0131lan torrentler, yay\u0131mlama listesinin en alt\u0131na giderler. Otomatik ba\u015flamazlar.\nYoksayma kurallar\u0131 birincil \u00f6ncelik \u00f6l\u00e7\u00fct\u00fcyle uyu\u015fan torrentlere uygulanmaz.\nAksi ifade edilmedik\u00e7e, kural\u0131 etkisizle\u015ftirmek i\u00e7in 0 de\u011ferini kullan\u0131n. ConfigView.label.directory=Dizin ConfigView.label.ignoreCase=B\u00dcY\u00dcK/k\u00fc\u00e7\u00fck \u00f6nemsiz ConfigView.label.ignoreSeeds=Belirtilenden az say\u0131da oldu\u011funda yoksay: ConfigView.label.importdirectory=Dizini \u0130\u00e7e Aktar ConfigView.label.minPeersToBoostNoSeeds=Hi\u00e7bir kayna\u011f\u0131 olmayan ve belirtilenden daha az e\u015fe sahip torrentlerin Yay\u0131mlama S\u0131ras\u0131n\u0131 d\u00fc\u015f\u00fcr : ConfigView.label.minSeedingTime.tooltip=Seeding Ranks can fluctuate often in a short period time, sometimes causing the torrent to automatically start, only to be stopped && queued immediately afterwards.\nThis alleviates the problem by forcing the torrent to stay seeding for a given period of time. You can still stop it manually if you want. ConfigView.label.minSeedingTime=En d\u00fc\u015f\u00fck yay\u0131mlama s\u00fcresi (saniye) ConfigView.label.minSpeedForActiveDL=\u015eu h\u0131z\u0131n alt\u0131ndaki torrentleri indiriliyor olarak sayma: ConfigView.label.peers=e\u015f ConfigView.label.queue.debuglog=Hata ay\u0131klama bilgisini kaydet ConfigView.label.queue.minQueueingShareRatio=Torrenti, payla\u015f\u0131m oran\u0131na ula\u015f\u0131ncaya dek durdurma veya s\u0131raya koyma ConfigView.label.ratio=oran ConfigView.label.removeOnStop=Torrent, otomatik durduktan sonra listeden kald\u0131r ConfigView.label.savedirectory=Kaydedilecek Dizin ConfigView.label.seeding.autoReposition=Torrentleri, Yay\u0131mlama S\u0131ras\u0131na g\u00f6re yeniden konumland\u0131r. ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Often, torrents with low seed counts and high peer counts means that there probably isn't a full copy amoungst the peers.\nTherefore, you may not want the seeding rules pretending there's a full copy (and thus incorrectly reducing its rank) ConfigView.label.seeding.fakeFullCopySeedStart=Fakat sadece ortak say\u0131s\u0131 \u015fu kadar olan torrentler i\u00e7in : ConfigView.label.seeding.ignore=Yoksayma Kurallar\u0131 ConfigView.label.seeding.ignore0Peers=Hi\u00e7bir e\u015fe sahip olmayan torrentleri yoksay ConfigView.label.seeding.ignoreRatioPeers=Ortak say\u0131s\u0131 herbir \u015fu kadar e\u015f say\u0131s\u0131 i\u00e7in en az 1 olanlar\u0131 yoksay: ConfigView.label.seeding.ignoreShareRatio=Yoksay\u0131lacak torrent i\u00e7in en d\u00fc\u015f\u00fck payla\u015f\u0131m oran\u0131: ConfigView.label.seeding.ignore.header.rule=Kural ConfigView.label.seeding.ignore.header.value=De\u011fer ConfigView.label.seeding.firstPriority.info=Birincil \u00f6ncelikli torrentler daima s\u0131ran\u0131n en \u00fcst\u00fcnde olacakt\u0131r.\nBirincil \u00f6ncelik \u00f6l\u00e7\u00fct\u00fcne uyan herhangi bir torrent otomatik olarak durdurulup s\u0131raya konmayacakt\u0131r.\nBirincil \u00f6ncelik \u00f6l\u00e7\u00fct\u00fcne uyan bir torrent ihtiya\u00e7 duydu\u011fu taktirde E\u015fanl\u0131 \u0130ndirme yuvas\u0131 alacakt\u0131r. ConfigView.label.seeding.firstPriority.FP=Birincil \u00d6ncelik ConfigView.label.seeding.firstPriority=Birincil \u00f6ncelik uygulanacak torrentler a\u015fa\u011f\u0131daki \u00f6l\u00e7\u00fctlerin ConfigView.label.seeding.firstPriority.following=ile uyumlu olmal\u0131: ConfigView.label.seeding.firstPriority.shareRatio=Belirtilen payla\u015f\u0131m oran\u0131n\u0131n alt\u0131 : ConfigView.label.seeding.firstPriority.seedingMinutes=\u0130ndirme i\u015fleminin ba\u015flamas\u0131ndan itibaren ge\u00e7en s\u00fcre : ConfigView.label.seeding.firstPriority.DLMinutes=\u0130ndirme i\u015flemi ard\u0131ndan yay\u0131mlama s\u00fcrecine ba\u015flama sonras\u0131 ge\u00e7en s\u00fcre : ConfigView.label.seeding.numPeersAsFullCopy=Herbir \u015fu kadar e\u015f say\u0131s\u0131 i\u00e7in tam bir kopya varm\u0131\u015f gibi yap :\n(0 : Asla tam bir kopya varm\u0131\u015f gibi yapma) ConfigView.label.seeding.preferLargerSwarms=Torrentler ayn\u0131 s\u0131ralamada olduklar\u0131nda, daha geni\u015f k\u00fcmeye sahip olan\u0131 se\u00e7 ConfigView.label.seeding.rankType.none=Hi\u00e7biri ConfigView.label.seeding.rankType.peerSeed.options=Ortaklar:E\u015fler Oran Se\u00e7enekleri ConfigView.label.seeding.rankType.peerSeed.tooltip=Y\u00fcksek Oran = Y\u00fcksek S\u0131ra ConfigView.label.seeding.rankType.peerSeed=E\u015f:Ortak Oran\u0131 ConfigView.label.seeding.rankType.seed.fallback=\u015eu ortak say\u0131s\u0131ndan sonra E\u015f:Ortak se\u00e7ene\u011fine ge\u00e7i\u015f yap \n(0 : Asla ge\u00e7i\u015f yapma) ConfigView.label.seeding.rankType.seed.options=Sadece E\u015f Say\u0131s\u0131 Se\u00e7enekleri ConfigView.label.seeding.rankType.seed.tooltip=Az Ortak = Y\u00fcksek S\u0131ra ConfigView.label.seeding.rankType.seed=Sadece E\u015f Say\u0131s\u0131 ConfigView.label.seeding.rankType.timedRotation=Zamanlanm\u0131\u015f D\u00f6n\u00fc\u015f\u00fcm ConfigView.label.seeding.rankType=S\u0131ras\u0131 Tamamlanm\u0131\u015f Torrentleri Otomatik Ba\u015flatma Temeli: ConfigView.pluginlist.info=A\u015fa\u011f\u0131daki eklentiler saptand\u0131. Baz\u0131 eklentilerin t\u00fcm\u00fcn\u00fcn yap\u0131land\u0131rma ayar\u0131 olmayabilir. ConfigView.section.pluginslist=Liste ConfigView.section.queue.seeding=Yay\u0131mlama ConfigView.section.queue.seeding.autoStarting=Otomatik Ba\u015flat ConfigView.section.queue.seeding.ignore=Yoksayma Kurallar\u0131 ConfigView.section.queue.seeding.firstPriority=Birincil \u00d6ncelik ConfigView.section.queue.main=Ana ConfigView.section.queue=S\u0131ra ConfigView.section.torrents=Torrentler ConfigView.text.all=t\u00fcm\u00fc ConfigView.text.hours=saat ConfigView.text.ignoreRule=Kural\u0131 Yoksay ConfigView.text.ignore=Yoksay ConfigView.text.minutes=dakika ConfigView.text.neverIgnore=Asla Yoksayma ConfigView.text.any=herhangi biri DownloadManager.error.datamissing=Kay\u0131p Veri MainWindow.menu.file.open.torrentforseeding=Torrent Dosyas\u0131... (Yay\u0131mlamak \u0130\u00e7in) MainWindow.menu.language.refresh=Yenile ManagerItem.forced=Zorlayarak ManagerItem.queued=S\u0131rada MySeedersView.header=Tamamlanan Torrentler TableColumn.header.availability=Bulunulabilirlik TableColumn.header.category=Ulam MyTorrentsView.header=Tamamlanmam\u0131\u015f Torrentler TableColumn.header.maxuploads=En Fazla G\u00f6nderme # MyTorrentsView.menu.category.delete=Ulam Sil MyTorrentsView.menu.forceStart=Ba\u015flamaya Zorla MyTorrentsView.menu.queue=S\u0131raya koy MyTorrentsView.menu.setCategory.add=Ulam Ekle... MyTorrentsView.menu.setCategory=Ulam Ata TableColumn.header.savepath=Kay\u0131t Yolu TableColumn.header.SeedingRank=Yay\u0131mlama S\u0131ras\u0131 TableColumn.header.totalspeed.info=Ba\u011fl\u0131 oldu\u011funuz t\u00fcm e\u015flerin Toplam H\u0131z\u0131 TableColumn.header.totalspeed=Toplam H\u0131z splash.initializePlugins=Eklentiler Ba\u015flat\u0131l\u0131yor StartStopRules.SPratioMet=FP / S:P Ratio OK StartStopRules.FP0Peers=FP / 0 E\u015f StartStopRules.0Peers=0 E\u015f StartStopRules.shareRatioMet=Payla\u015f\u0131m Oran\u0131 TAMAM StartStopRules.waiting=Bekliyor StartStopRules.firstPriority=1. \u00d6ncelik ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Payla\u015f\u0131m \u0130\u00e7eri\u011fi (\u00d6zyineli) DownloadManager.error.unabletostartserver=Sunucu Ba\u015flat\u0131lam\u0131yor - gelen ba\u011flant\u0131 noktas\u0131 yap\u0131land\u0131rmas\u0131n\u0131 / uygulaman\u0131n sunucu olarak \u00e7al\u0131\u015fmas\u0131 i\u00e7in g\u00fcvenlik duvar\u0131 izinlerini denetleyin GeneralView.label.creationdate=Olu\u015fturulma Tarihi : ManagerItem.stopping=Durduruluyor ConfigView.section.tracker.scrapeandcache=Durum S\u0131namas\u0131 ve \u00d6nbellek MyTrackerView.scrapes=Durum S\u0131namalar\u0131 fileDownloadWindow.retry=Yeniden Dene MyTrackerView.bytesin=Gelen Byte MyTrackerView.bytesinave=Gelen Ort. MyTrackerView.bytesout=Giden Byte MyTrackerView.bytesoutave=Giden Ort. ConfigView.section.file.max_open_files=Okuma/Yazma i\u00e7in a\u00e7\u0131lm\u0131\u015f en fazla dosya say\u0131s\u0131\n[0: s\u0131n\u0131rs\u0131z] ConfigView.section.proxy=Vekil Sunucu Se\u00e7enekleri ConfigView.section.proxy.enable_proxy=\u0130zleyici ileti\u015fiminde vekil sunucuyu etkinle\u015ftir [Yeniden ba\u015flatma gerektirir] ConfigView.section.proxy.host=Sunucu ConfigView.section.proxy.port=Ba\u011flant\u0131 Noktas\u0131 ConfigView.section.proxy.username=Kullan\u0131c\u0131 Ad\u0131 ConfigView.section.proxy.password=Parola ConfigView.section.proxy.enable_socks=SOCKS t\u00fcr\u00fc vekil sunucu kullan\u0131yorum wizard.createtorrent.extrahashes=Di\u011fer a\u011flar i\u00e7in do\u011frulama verisini ekle (\u00d6rne\u011fin Gnutella2, eDonkey2000) GeneralView.label.connected=ba\u011fland\u0131 GeneralView.label.in_swarm=tanesi k\u00fcmede ManagerItem.initializing=Ba\u015flat\u0131l\u0131yor AlertMessageBox.error=Hata AlertMessageBox.warning=Uyar\u0131 AlertMessageBox.comment=Bilgi AlertMessageBox.information=Bilgi SharedPortServer.alert.selectorfailed=Gelen veri i\u00e7in dinleyici kurma ba\u015far\u0131s\u0131z oldu.\nG\u00fcvenlik duvar\u0131 ayarlar\u0131n\u0131n java(w).exe uygulamas\u0131n\u0131n 'sunucu' olarak davranmas\u0131na izin verip vermedi\u011fini denetleyin Tracker.alert.listenfail=%1 nolu ba\u011flant\u0131 noktas\u0131nda dinleme ger\u00e7ekle\u015ftirilemedi.\nDi\u011fer uygulamalar\u0131n bu ba\u011flant\u0131 noktas\u0131n\u0131 kullan\u0131p kullanmad\u0131\u011f\u0131n\u0131 denetleyin.\nAyn\u0131 zamanda Vuze un ba\u015fka bir kopyas\u0131n\u0131n \u00e7al\u0131\u015f\u0131p \u00e7al\u0131\u015fmad\u0131\u011f\u0131n\u0131 da denetleyin. DiskManager.alert.movefileexists=Tamamlanm\u0131\u015f dosyalar\u0131 ta\u015f\u0131rken hata olu\u015ftu\n%1 adl\u0131 dosya MoveTo hedef dizininde zaten var DiskManager.alert.movefilefails=Tamamlanm\u0131\u015f dosyalar\u0131 ta\u015f\u0131rken hata olu\u015ftu\n%1 adl\u0131 dosyan\u0131n ta\u015f\u0131nmas\u0131 ba\u015far\u0131s\u0131z oldu, %2 DiskManager.alert.movefilerecoveryfails=Ta\u015f\u0131ma i\u015flemi ba\u015far\u0131s\u0131zl\u0131\u011f\u0131n\u0131n ard\u0131ndan yap\u0131lan kurtarma i\u015fleminde hata olu\u015ftu\n%1 adl\u0131 dosyan\u0131n kurtar\u0131lmas\u0131 ba\u015far\u0131s\u0131z oldu, %2 ConfigView.section.tracker.logenable=Devresel istatistikleri 'tracker.log' g\u00fcnl\u00fck dosyas\u0131na kaydet SpeedView.stats.title=\u0130statistikler SpeedView.stats.total=Toplam SpeedView.stats.session=Bu Oturum SpeedView.stats.session.tooltip=Toplam (\u0130leti\u015fim Kural\u0131) SpeedView.stats.downloaded=\u0130ndirilen (\u0130leti\u015fim Kural\u0131) SpeedView.stats.uploaded=G\u00f6nderilen (\u0130leti\u015fim Kural\u0131) SpeedView.stats.ratio=Oran SpeedView.stats.uptime=\u00c7al\u0131\u015fma S\u00fcresi SpeedView.stats.now=\u015eimdi SpeedView.stats.now.tooltip=Toplam (\u0130leti\u015fim Kural\u0131) # # > 2.0.8.0 # OpenTorrentWindow.title=Torrent(ler)i A\u00e7 OpenTorrentWindow.message=Deneysel OpenTorrentWindow.addFiles=Dosyalar\u0131 Ekle OpenTorrentWindow.dataLocation=Verinin kaydedilece\u011fi yer: OpenTorrentWindow.startMode=Kip ekle OpenTorrentWindow.startMode.queued=S\u0131rada OpenTorrentWindow.startMode.stopped=Durduruldu OpenTorrentWindow.startMode.forceStarted=Ba\u015flamaya Zorland\u0131 OpenTorrentWindow.addPosition=S\u0131ra Konumu OpenTorrentWindow.addPosition.first=\u0130lk OpenTorrentWindow.addPosition.last=Son TableColumn.header.remaining.info=Kalan indirme miktar\u0131 TableColumn.header.remaining=Kalan ConfigView.section.tracker.enablekey=Geli\u015ftirilmi\u015f g\u00fcvenlik i\u00e7in izleyiciye anahtar ge\u00e7i\u015fini etkinle\u015ftir ConfigView.section.file.perf=Ba\u015far\u0131m Se\u00e7enekleri ConfigView.section.file.perf.explain=Uyar\u0131: Bu de\u011fi\u015ftirgeler \u00fczerinde bilgisizce yap\u0131lacak de\u011fi\u015fiklikler indirme ba\u015far\u0131m\u0131na ters etkide bulunabilir. (Yeniden ba\u015flatma gerektirir)\nE\u011fer "yetersiz bellek" sorunlar\u0131n\u0131z varsa, torrent ba\u015f\u0131na ba\u011flant\u0131lar\u0131 s\u0131n\u0131rland\u0131rmay\u0131 deneyin. (Aktar\u0131m ayarlar\u0131na bak\u0131n) popup.error.hide=Gizle popup.error.details=Ayr\u0131nt\u0131lar ConfigView.section.style.colorOverrides=Renk Tercihi ConfigView.section.style.colorOverride.progressBar=\u0130lerleme \u00c7ubu\u011fu ConfigView.section.style.colorOverride.error=Hata MainWindow.status.tooOld=eski, l\u00fctfen g\u00fcncelle\u015ftirin. ConfigView.section.style.colorOverride.warning=Uyar\u0131 ConfigView.section.style.colorOverride.altRow=\u00d6teki Sat\u0131rlar ConfigView.section.file.save.peers.enable=E\u015f ba\u011flant\u0131lar\u0131n\u0131 daha h\u0131zl\u0131 yeniden ba\u011flanabilmek i\u00e7in kaydet ConfigView.section.file.save.peers.max=Torrent ba\u015f\u0131na kaydedilecek en fazla e\u015f say\u0131s\u0131 [0: s\u0131n\u0131rs\u0131z] ConfigView.section.file.save.peers.pertorrent= ConfigView.label.max_peers_per_torrent=Torrent ba\u015f\u0131na yap\u0131lacak en fazla ba\u011flant\u0131 say\u0131s\u0131 [0: s\u0131n\u0131rs\u0131z] ConfigView.label.max_peers_total=Toplam en fazla ba\u011flant\u0131 say\u0131s\u0131 [0: s\u0131n\u0131rs\u0131z] ConfigView.section.style.colorOverrides.reset=Rengi \u0130lk Duruma Getir ConfigView.section.language.UpdateURL=Adresi G\u00fcncelle ConfigView.section.language.UpdateNow=\u015eimdi G\u00fcncelle! Button.revert=Geri Al MyTorrentsView.menu.changeDirectory=Veri Dizinini De\u011fi\u015ftir GenericText.column=S\u00fctunu MyTorrentsView.menu.thisColumn.remove=S\u00fctunu Kald\u0131r MyTorrentsView.menu.thisColumn.toClipboard=Metni Panoya Kopyala MyTorrentsView.menu.tracker=\u0130zleyici TableColumn.header.secondsseeding=Yay\u0131mlama S\u00fcresi TableColumn.header.secondsdownloading=\u0130ndirme S\u00fcresi TableColumn.header.secondsdownloading.info=\u0130ndirmekte oldu\u011funuz s\u00fcre miktar\u0131. ConfigView.section.tracker.udpversion=UDP \u0130leti\u015fim Kural\u0131 S\u00fcr\u00fcm (1 or 2) window.updateswt.title=SWT S\u00fcr\u00fcm\u00fc \u00e7ok eski! window.updateswt.text=SWT S\u00fcr\u00fcm\u00fc olduk\u00e7a eski!\nSWT, Vuze taraf\u0131ndan kullan\u0131lan grafik k\u00fct\u00fcphanesidir ve sahip oldu\u011funuz s\u00fcr\u00fcm Vuze un en son s\u00fcr\u00fcm\u00fcn\u00fc \u00e7al\u0131\u015ft\u0131rmayacak kadar eskidir. SWT k\u00fct\u00fcphanesini g\u00fcncelle\u015ftirmek i\u00e7in Tamam d\u00fc\u011fmesine t\u0131klay\u0131n. window.updateswt.status=Durum window.updateswt.failed=G\u00fcncelleme ba\u015far\u0131s\u0131z oldu, yeniden ba\u015flatmak i\u00e7in Tamam d\u00fc\u011fmesine t\u0131klay\u0131n. window.updateswt.status.downloading.updater=G\u00fcncelle\u015ftirme Birimi \u0130ndiriliyor window.updateswt.status.finding=En Son SWT S\u00fcr\u00fcm\u00fcn\u00fc Ar\u0131yor window.updateswt.status.downloading=En Son SWT S\u00fcr\u00fcm\u00fcn\u00fc \u0130ndiriyor window.updateswt.status.done=Yeninden Ba\u015flat\u0131yor window.updateswt.ok=Tamam window.updateswt.cancel=\u0130ptal window.updateswt.ignore=Yoksay ConfigView.section.style.useFancyTabs=S\u00fcsl\u00fc sekmeleri kullan splash.initializeGM=Genel Torrent Y\u00f6neticisi Ba\u015flat\u0131l\u0131yor splash.loadingTorrents=Torrentler Y\u00fckleniyor MyTorrentsView.menu.thisColumn.sort=S\u0131rala Scrape.status.ok=Durum S\u0131namas\u0131 TAMAM Scrape.status.error=Durum S\u0131nama Hatas\u0131: Scrape.status.nextScrapeAt=Sonraki durum s\u0131namas\u0131: %1 Scrape.status.scraping=Durum s\u0131nan\u0131yor.. Scrape.status.initializing=Durum s\u0131namas\u0131 i\u00e7in bekleniyor ConfigView.label.minSpeedForActiveSeeding=\u015eu h\u0131z\u0131n alt\u0131ndaki bitmi\u015f torrentleri yay\u0131mlan\u0131yor olarak sayma: ConfigView.section.stats.exportpeers=E\u015f ayr\u0131nt\u0131lar\u0131n\u0131 d\u0131\u015far\u0131 aktar MainWindow.menu.view.irc.moved=Irc \u015fimdi bir eklenti olarak kullan\u0131labilir, http://azureus.sourceforge.net/plugin_list.php adresini inceleyin. Kuruldu\u011funda eri\u015fmek i\u00e7in g\u00f6r\u00fcn\u00fcm->eklentiler->IRC men\u00fcs\u00fcn\u00fc kullan\u0131n. MyTrackerView.webui.contextmenu.copyurl=Torrent adresini panoya kopyala ConfigView.section.file.torrent.ignorefiles=Torrentler olu\u015fturulurken g\u00f6zard\u0131 edilecek dosyalar\n(\u00d6rne\u011fin .DS_Store;Thumbs.db) Torrent.create.progress.ignoringfile=Dosya yoksay\u0131l\u0131yor ConfigView.section.style.useUnitsRateBits=Byte tabanl\u0131 h\u0131z de\u011ferleri i\u00e7in byte yerine bit kullan (KiB/s -> Kbit/s gibi) ConfigView.section.interface.resetassoc='.torrent' dosya uzant\u0131s\u0131yla ili\u015fkilendirme ConfigView.section.interface.resetassocbutton=\u0130li\u015fkilendir ConfigView.section.interface.checkassoc=Ba\u015flang\u0131\u00e7ta dosya uzant\u0131s\u0131 ili\u015fkisini denetle dialog.associations.title=\u0130li\u015fkilendirme Denetimi Button.yes=Evet Button.no=Hay\u0131r ConfigView.label.seeding.autoStart0Peers=Tamamlanm\u0131\u015f t\u00fcm, hi\u00e7 e\u015fe sahip olmayan torrentleri otomatik ba\u015flat dialog.associations.prompt=Vuze BitTorrent dosyalar\u0131 i\u00e7in varsay\u0131lan uygulama de\u011fil.\n.torrent dosyalar\u0131n\u0131 Vuze ile ili\u015fkilendirmek ister misiniz? dialog.associations.askagain=Ba\u015flang\u0131\u00e7ta kontrol et ConfigView.section.plugins.update=Eklenti G\u00fcncelle\u015ftirme Plugin.pluginupdate.enablecheck=Eklenti g\u00fcncelle\u015ftirme denetimini etkinle\u015ftir plugins.basicview.status=Durum: plugins.basicview.activity=Etkinlik: plugins.basicview.progress=\u0130lerleme: plugins.basicview.log=G\u00fcnl\u00fck: ConfigView.label.maxdownloadspeed=Toplam en y\u00fcksek indirme h\u0131z\u0131 (KB/s) [0: s\u0131n\u0131rs\u0131z] splash.loadingTorrent=Torrent Y\u00fckleniyor UpdateWindow.title=Vuze G\u00fcncelleme Yard\u0131mc\u0131s\u0131 UpdateWindow.header=A\u015fa\u011f\u0131daki bile\u015fenlerin g\u00fcncelleri bulundu : UpdateWindow.columns.install=Kur UpdateWindow.columns.name=Ad UpdateWindow.columns.version=S\u00fcr\u00fcm UpdateWindow.columns.size=B\u00fcy\u00fckl\u00fck UpdateWindow.cancel=\u0130ptal UpdateWindow.quit=\u00c7\u0131k UpdateWindow.close=Kapat UpdateWindow.ok=G\u00fcncelle UpdateWindow.restart=Yeniden Ba\u015flat UpdateWindow.status.downloading=\u0130ndiriliyor UpdateWindow.status.done=Tamamland\u0131 UpdateWindow.status.failed=Ba\u015far\u0131s\u0131z Oldu UpdateWindow.status.restartNeeded=Yeniden ba\u015flatma gerekecek! ConfigView.pluginlist.whereToPut=Kullan\u0131c\u0131ya \u00f6zel herhangi bir eklentiyi kullan\u0131c\u0131 dizinine kaydedin: ConfigView.pluginlist.whereToPutOr=Payla\u015f\u0131lan eklentiler i\u00e7in: MainWindow.statusText.checking=G\u00fcncellemeler Kontrol Ediliyor TableColumn.header.OnlyCDing4=Sadece Yay\u0131mlanma TableColumn.header.OnlyCDing4.info=Sadece yay\u0131mlanma s\u00fcresini g\u00f6sterir. \u0130ndirmek i\u00e7in ge\u00e7en s\u00fcreyi g\u00f6stermez. ConfigView.section.style.alternateTablePainting=Grafik tablo s\u00fctunlar\u0131n\u0131 boyamak i\u00e7in \u00f6teki y\u00f6ntemi kullan (Yeniden ba\u015flatma gerektirebilir) UpdateWindow.status.restartMaybeNeeded=Yeniden ba\u015flatma gerekebilir MainWindow.menu.help.whatsnew=Yenilikler ConfigView.label.checkonstart=Ba\u015flang\u0131\u00e7ta son s\u00fcr\u00fcm denetimi yap ConfigView.label.periodiccheck=D\u00fczenli olarak yeni s\u00fcr\u00fcm denetimi yap ConfigView.label.opendialog=Yeni bir g\u00fcncelleme buldu\u011funda 'G\u00fcncelleme Yard\u0131mc\u0131s\u0131n\u0131' otomatik ba\u015flat MainWindow.updateavail=G\u00fcncellemeler i\u00e7in buraya t\u0131klay\u0131n MainWindow.status.latestversionunchecked=S\u00fcr\u00fcm denetimi iptal edildi GeneralView.label.updatein.stopped=Durdu StartStopRules.menu.viewDebug=Hata Ay\u0131klama Bilgisini G\u00f6ster ConfigView.section.style.doNotUseGB=GigaByte birimini asla kullanma ConfigView.section.style.doNotUseGB.tooltip=\u0130\u015faretlenirse, Vuze 1024MB'tan daha b\u00fcy\u00fck boyutlar i\u00e7in MB kullanmaya devam edecek. MainWindow.menu.help.plugins=Eklentileri Al ConfigView.section.tracker.enablecategories=Torrentleri ulamlar\u0131na g\u00f6re ay\u0131r health.explain.share=Torrentin bar\u0131nd\u0131r\u0131ld\u0131\u011f\u0131 ya da yay\u0131mland\u0131\u011f\u0131 anlam\u0131na gelir. ConfigView.section.tracker.createcert=Kendinden imzal\u0131 sertifika olu\u015ftur ConfigView.section.tracker.createbutton=Olu\u015ftur security.certcreate.title=Ki\u015fisel \u0130mzal\u0131 Sertifika Olu\u015ftur security.certcreate.intro=Bu ileti\u015fim kutusu, ki\u015fisel imzal\u0131 bir sertifika olu\u015fturman\u0131z\u0131 sa\u011flar. security.certcreate.alias=Takma ad security.certcreate.strength=\u015eifreleme seviyesi security.certcreate.firstlastname=Ad ve soyad security.certcreate.orgunit=\u00d6rg\u00fctsel birim security.certcreate.org=\u00d6rg\u00fct/Firma security.certcreate.city=\u015eehir veya semt security.certcreate.state=Eyalet veya il security.certcreate.country=\u0130ki harfli \u00fclke kodu security.certcreate.ok=Olu\u015ftur security.certcreate.cancel=\u0130ptal security.certcreate.createok=Sertifika ba\u015far\u0131yla olu\u015fturuldu security.certcreate.createfail=Sertifika olu\u015fturma ba\u015far\u0131s\u0131z oldu webui.passwordenable=Parolay\u0131 etkinle\u015ftir webui.user=Kullan\u0131c\u0131 ad\u0131 webui.password=Parola webui.port=Ba\u011flant\u0131 Noktas\u0131 (*) webui.protocol=\u0130leti\u015fim Kural\u0131 (*) webui.homepage=Ana sayfa (*) webui.rootdir=K\u00f6k dizin (*) webui.rootres=K\u00f6k kaynak (*) webui.mode=Kip (*) webui.access=Eri\u015fim (*) GeneralView.label.maxdownloadspeed=En Y\u00fcksek \u0130ndirme webui.restart.info=(*) i\u015fareti olan parametreler de\u011fi\u015ftiridi\u011finde, yap\u0131lan de\u011fi\u015fikliklerin etkili olabilmesi i\u00e7in yeniden ba\u015flatma gerekir. GeneralView.label.maxdownloadspeed.tooltip=olarak en y\u00fcksek indirme h\u0131z\u0131 [0: s\u0131n\u0131rs\u0131z] upnp.enable=UPnP'yi etkinle\u015ftir upnp.info=Evrensel Tak ve Kullan (UPnP), UPnP'nin etkinle\u015ftirildi\u011fi y\u00f6nlendiriciler \u00fczerindeki ba\u011flant\u0131 noktalar\u0131n\u0131n otomatik olarak e\u015flenmesine izin verir. upnp.mapping.dataport=Gelen E\u015f Veri Ba\u011flant\u0131 Noktas\u0131 upnp.mapping.tcptrackerport=TCP \u0130zleyici Ba\u011flant\u0131 Noktas\u0131 upnp.mapping.udptrackerport=UDP \u0130zleyici Ba\u011flant\u0131 Noktas\u0131 upnp.alert.differenthost=UPnP: '%1' y\u00f6nlendirmesi '%2' zaten ayr\u0131lm\u0131\u015f durumda. L\u00fctfen ba\u015fka bir ba\u011flant\u0131 noktas\u0131 se\u00e7in. upnp.alert.mappingok=UPnP: '%1' y\u00f6nlendirmesi kuruldu upnp.alert.mappingfailed=UPnP: '%1' y\u00f6nlendirmesi ba\u015far\u0131s\u0131z upnp.alertsuccess=Ba\u015far\u0131l\u0131 e\u015flemeleri raporla upnp.grabports=Ba\u015fka bir bilgisayara ait olsa da ba\u011flant\u0131 noktalar\u0131n\u0131 e\u015fle upnp.refresh.label=E\u015flemeleri yenile upnp.refresh.button=Yenile upnp.mapping.tcpssltrackerport=TCP SSL \u0130zleyici Ba\u011flant\u0131 Noktas\u0131 upnp.alertothermappings=Di\u011fer bilgisayara ait ba\u011flant\u0131 noktalar\u0131n\u0131 raporla upnp.alertdeviceproblems=UPnP ayg\u0131t\u0131 ile ilgili sorunlar\u0131 raporla ConfigView.pluginlist.coreplugins=A\u015fa\u011f\u0131daki yerle\u015fik eklentiler y\u00fcklendi: Peers.column.DLedFromOthers=Di\u011ferlerinden Peers.column.DLedFromOthers.info=Size ba\u011fl\u0131 iken di\u011ferlerinden indirilmi\u015f veri miktar\u0131 Peers.column.UpDownRatio=G\u00f6nderme:\u0130ndirme Peers.column.UpDownRatio.info=E\u015fin "G\u00f6nderilen : \u0130ndirilen" Oran\u0131 Peers.column.UpRatio=G\u00f6nderme Oran\u0131 Peers.column.UpRatio.info=E\u015fin "Sizden y\u00fckledi\u011fi : Di\u011ferinden y\u00fckledi\u011fi" oran\u0131 upnp.releasemappings=Kapat\u0131l\u0131rken e\u015flemeleri kald\u0131r webui.upnpenable=Bu ba\u011flant\u0131 noktas\u0131 i\u00e7in UPnP'yi etkinle\u015ftir (*) ConfigView.section.file.friendly.hashchecking=Yumu\u015fak veri do\u011frulamas\u0131 yap ConfigView.section.file.friendly.hashchecking.tooltip=Biraz daha yava\u015f, ancak i\u015flemci ve sistem \u00fczerinde daha az y\u00fck bindirecek \u015fekilde veri do\u011frulamas\u0131 yapma kipi ConfigView.section.tracker.port=\u0130zleyiciyi HTTP ba\u011flant\u0131 noktas\u0131nda etkinle\u015ftir ConfigView.section.tracker.sslport=HTTPS ba\u011flant\u0131 noktas\u0131nda izleyiciyi etkinle\u015ftir Button.clear=Temizle MainWindow.IPs.tooltip=Ip s\u00fczge\u00e7i listesinde say\u0131 aral\u0131\u011f\u0131 \u2013 Engellenmi\u015f IP'lerin say\u0131s\u0131.\nAyr\u0131nt\u0131lar i\u00e7in \u00e7ift t\u0131klay\u0131n ConfigView.section.ipfilter.list.banned=yasakland\u0131 ConfigView.section.ipfilter.list.baddata=bozuk veri g\u00f6nderdi: olaylar = Button.reset=S\u0131f\u0131rla ConfigView.section.ipfilter.bannedinfo=Bozuk veri g\u00f6nderen IP adresleri (S\u0131n\u0131r\u0131 a\u015farlarsa engellenirler) ConfigView.section.ipfilter.blockedinfo=IP s\u00fczge\u00e7i nedeniyle engellenmi\u015f IP adresleri download.removerules.name=Kald\u0131rma Kurallar\u0131 download.removerules.unauthorised.info=Duyuru yan\u0131t\u0131nda "not authoris(z)ed" veya "unauthoris(z)ed" ba\u015far\u0131s\u0131zl\u0131k yan\u0131t\u0131 i\u00e7eren yetkilendirilmemi\u015f torrentler download.removerules.unauthorised=Yetkilendirilmemi\u015f torrentleri otomatik olarak kald\u0131r download.removerules.unauthorised.seedingonly=\tSadece yay\u0131mlan\u0131yorsa download.removerules.removed.ok='%1' torrentinin otomatik kald\u0131r\u0131lmas\u0131 ba\u015far\u0131yla tamamland\u0131. Bu, torrent kald\u0131rma kurallar\u0131 do\u011frultusunda ger\u00e7ekle\u015ftirildi. download.removerules.updatetorrents=Vuze g\u00fcncelleme torrentlerini k\u00fcmenin iste\u011fi do\u011frultusunda kald\u0131r ConfigView.label.defaultstarttorrentsstopped=Varsay\u0131lan olarak yeni eklenen torrentleri \u00e7al\u0131\u015fm\u0131yor olarak i\u015faretle ConfigView.section.server.enableudp=UDP izleyici istemci ileti\u015fim kural\u0131n\u0131 etkinle\u015ftir upnp.mapping.dataportudp=UDP izleyici istemci ba\u011flant\u0131 noktas\u0131 ConfigView.section.file.decoder.showlax=Benzerli\u011fi az kodlamalar\u0131 g\u00f6ster ConfigView.section.file.decoder.showall=Olas\u0131 t\u00fcm kodlamalar\u0131 dikkate al MainWindow.status.updowndetails.tooltip=G\u00f6nderme/\u0130ndirme h\u0131z ayr\u0131nt\u0131lar\u0131 (De\u011fi\u015ftirmek i\u00e7in sa\u011f t\u0131klay\u0131n) TrackerClient.announce.warningmessage='%1' i\u00e7in izleyici '%2' uyar\u0131s\u0131 d\u00f6nd\u00fcrd\u00fc ConfigView.section.tracker.publishenabledetails=T\u00fcm torrent ayr\u0131nt\u0131lar\u0131n\u0131 yay\u0131mla ConfigView.section.tracker.publishenablepeerdetails=E\u015f ayr\u0131nt\u0131lar\u0131n\u0131 yay\u0131mla MyTrackerView.badnat=Ge\u00e7ersiz NAT ConfigView.section.tracker.natchecktimeout=Zaman a\u015f\u0131m\u0131n\u0131 kontrol et (sn) ConfigView.section.file.perf.cache.enable=Disk \u00f6nbelle\u011fini etkinle\u015ftir ConfigView.section.file.perf.cache.size=%1 olarak \u00f6nbellek boyutu #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=Aktar\u0131mlar MainWindow.menu.transfers.startalltransfers=T\u00fcm\u00fcn\u00fc Ba\u015flat MainWindow.menu.transfers.stopalltransfers=T\u00fcm\u00fcn\u00fc Durdur MainWindow.menu.transfers.pausetransfers=Duraklat MainWindow.menu.transfers.resumetransfers=Devam Et SystemTray.menu.pausetransfers=Aktar\u0131mlar\u0131 Duraklat SystemTray.menu.resumetransfers=Aktar\u0131mlara Devam Et ConfigView.section.file.truncate.too.large=Varolan \u00e7ok geni\u015f dosyalar\u0131 k\u00fc\u00e7\u00fclt ConfigView.section.file.perf.cache.trace=\u00d6nbellek i\u015flemlerini te\u015fhis ama\u00e7l\u0131 kaydet ConfigView.section.interface.enabletray=Bildirim alan\u0131nda simge g\u00f6ster [Tekrar ba\u015flatma gerektirir] PeerManager.status.error=Hata Stats.title.full=\u0130statistikler TransferStatsView.title.full=Aktar\u0131mlar CacheView.title.full=\u00d6nbellek CacheView.general.size=Toplam Boyut CacheView.general.inUse=Kullan\u0131mda CacheView.general.title=\u00d6nbellek Bilgisi CacheView.reads.title=Giri\u015f/\u00c7\u0131k\u0131\u015f Okuma CacheView.reads.fromFile=Dosyadan CacheView.reads.fromCache=\u00d6nbellekten CacheView.reads.hits=Ba\u015far\u0131l\u0131 CacheView.writes.title=Giri\u015f/\u00c7\u0131k\u0131\u015f Yazma CacheView.writes.toCache=\u00d6nbelle\u011fe CacheView.writes.toFile=Dosyaya CacheView.writes.hits=Kaydedildi CacheView.speeds.title=Veri Oranlar\u0131 CacheView.speeds.reads=Okuma CacheView.speeds.writes=Yazma CacheView.speeds.fromCache=\u00d6nbellekten \u00d6nbelle\u011fe CacheView.speeds.fromFile=Dosyadan Dosyaya CacheView.reads.amount=Miktar CacheView.reads.avgsize=Ortalama Boyut openUrl.referrer=Yollayan sayfan\u0131n adresi : openUrl.referrer.info=Yaln\u0131zca, bunu gerektiren web siteleri i\u00e7in ge\u00e7erlidir ConfigView.label.maxuploadspeedseeding=Sadece yay\u0131mlama yap\u0131l\u0131yorsa (KB/s) [0: s\u0131n\u0131rs\u0131z] ConfigView.label.transfer.ignorepeerports=Bu ba\u011flant\u0131 noktas\u0131na sahip kullan\u0131c\u0131lar\u0131 yoksay: (';' ile ayr\u0131lm\u0131\u015f, \u00f6rne\u011fin 0;25) ConfigView.section.proxy.enable_socks.peer=E\u015f ileti\u015fiminde vekil sunucuyu etkinle\u015ftir (Sadece giden ba\u011flant\u0131lar i\u00e7in) [Yeniden ba\u015flatma gerektirir] ConfigView.section.proxy.peer.informtracker=\u0130zleyiciyi, s\u0131n\u0131rland\u0131rmalar hakk\u0131nda bilgilendir ConfigView.section.proxy.socks.version=SOCKS s\u00fcr\u00fcm\u00fc PiecesView.legend.written=Yaz\u0131ld\u0131 PiecesView.legend.requested=Talep edildi PiecesView.legend.downloaded=\u0130ndirildi, yazma bekliyor PiecesView.legend.incache=Veri \u00f6nbellekte PiecesView.typeItem.0=Yava\u015f PiecesView.typeItem.1=H\u0131zl\u0131 PiecesView.type=T\u00fcr Security.jar.tools_not_found=JAR imzalama ba\u015far\u0131s\u0131z - %1 i\u00e7inde 'tools.jar' bulunamad\u0131. Ayr\u0131nt\u0131lar i\u00e7in Ara\u00e7lar->Se\u00e7enekler->G\u00fcvenlik b\u00f6l\u00fcm\u00fcne bakabilirsiniz. Security.jar.signfail=JAR imzalama ba\u015far\u0131s\u0131z - %1 ConfigView.section.security.toolsdir='tools.jar' dosyas\u0131n\u0131 i\u00e7eren dizin ConfigView.section.security.choosetoolssavedir='tools.jar' dosyas\u0131n\u0131 i\u00e7eren dizini se\u00e7 ConfigView.section.proxy.peer.same=\u0130zleyici ve e\u015f ileti\u015fim vekil sunucusu i\u00e7in ayn\u0131 vekil sunucu ayarlar\u0131n\u0131 kullan ConfigView.section.connection.network.max.simultaneous.connect.attempts=En fazla e\u015fanl\u0131 d\u0131\u015f ba\u011flant\u0131 giri\u015fimi say\u0131s\u0131 [0: d\u0131\u015f ba\u011flant\u0131 etkisiz] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Max number of new outbound connection establishments Vuze should attempt any given time.\nNOTE: WindowsXP Service Pack 2 (SP2) imposes a system-wide limit of 10 simultaneous connect attempts.\nDefault value is 8. Value of 0 disables outbound connects entirely. ConfigView.section.file.perf.cache.size.explain=The cache is used to reduce reads from/writes to disk. Unless you are using the java option '-XX:MaxDirectMemorySize' to explicitly set the memory available for cache and network IO use, you should keep this value at least %1 below your maximum VM size. The current maximum VM size is %2. For instructions on how to change this, see MemoryUsage in the wiki on %3. Failure to use sensible settings will result on 'out of memory' errors. More than 32MB of cache is probably overkill. MyTorrentsView.menu.setSpeed.unlimit=S\u0131n\u0131r yok MyTorrentsView.menu.setSpeed.unlimited=S\u0131n\u0131rs\u0131z MyTorrentsView.menu.setSpeed.disable=G\u00f6ndermeyi Devreden \u00c7\u0131kart MyTorrentsView.menu.setSpeed.disabled=Devreden \u00c7\u0131kart\u0131ld\u0131 GeneralView.label.maxuploadspeed=En Y\u00fcksek G\u00f6nderme GeneralView.label.maxuploadspeed.tooltip=olarak en y\u00fcksek g\u00f6nderme h\u0131z\u0131 [0: s\u0131n\u0131rs\u0131z] MyTorrents.items.UpSpeedLimit.disabled=G\u00f6nderme yok MyTorrents.items.UpSpeedLimit.unlimited=S\u0131n\u0131rs\u0131z TableColumn.header.maxupspeed=En y\u00fcksek g\u00f6nderme h\u0131z\u0131 TableColumn.header.maxupspeed.info=Torrent ba\u015f\u0131na en y\u00fcksek g\u00f6nderme h\u0131z\u0131 ConfigView.section.tracker.separatepeerids=\u0130zleyici ve veri ileti\u015fimi i\u00e7in farkl\u0131 e\u015f kimli\u011fi kullan ConfigView.section.tracker.separatepeerids.info= ConfigView.section.interface.wavlocation='.wav' dosyas\u0131n\u0131n konumu ConfigView.section.interface.wavlocation.info='.wav' dosyas\u0131n\u0131 se\u00e7in veya varsay\u0131lan ses i\u00e7in bo\u015f b\u0131rak\u0131n ConfigView.section.tracker.server=Sunucu ConfigView.section.tracker.client=\u0130stemci ConfigView.section.tracker.client.connecttimeout=Ba\u011flanma zaman a\u015f\u0131m\u0131 (sn) ConfigView.section.tracker.client.readtimeout=Okuma zaman a\u015f\u0131m\u0131 (sn) MainWindow.menu.tools=Ara\u00e7lar FilesView.path=Yol FilesView.fullpath=Tam Yolu G\u00f6ster FilesView.remaining=Kalan Par\u00e7alar TableColumn.header.trackername=\u0130zleyici Ad\u0131 TableColumn.header.trackername.info=Duyuru adresinden elde edilen izleyici ad\u0131 ConfigView.group.override=Ge\u00e7ersiz K\u0131lma Se\u00e7enekleri ConfigView.section.file.perf.cache.notsmallerthan=\u00d6nbelle\u011fe al\u0131nacak en k\u00fc\u00e7\u00fck dosya b\u00fcy\u00fckl\u00fc\u011f\u00fc (%1 olarak) PeersView.menu.blockupload=G\u00f6ndermeyi Engelle PeersView.menu.kickandban=Kov ve Yasakla PeersView.menu.kickandban.reason=E\u015f, el ile yasakland\u0131 PeersView.state=Durum PeersView.state.info=E\u015f ba\u011flant\u0131s\u0131n\u0131n durumu PeersView.state.pending=Beklemede PeersView.state.connecting=Ba\u011flan\u0131yor PeersView.state.handshake=El s\u0131k\u0131\u015fmas\u0131 bekleniyor PeersView.state.established=Tamamen kuruldu ConfigView.section.tracker.processinglimits=\u0130\u015flem S\u0131n\u0131rlar\u0131 ConfigView.section.tracker.maxgettime=GET i\u015flemi i\u00e7in en y\u00fcksek zaman (sn) [0: s\u0131n\u0131rs\u0131z] ConfigView.section.tracker.maxgettime.info=Duyuru ve durum s\u0131namas\u0131 i\u00e7in kullan\u0131l\u0131r ConfigView.section.tracker.maxposttimemultiplier=POST i\u015flemi i\u00e7in GET s\u00fcre \u00e7arpan\u0131 [0: s\u0131n\u0131rs\u0131z] ConfigView.section.tracker.maxposttimemultiplier.info=Form onaylamalar\u0131 ve y\u00fcklemeleri i\u00e7in kullan\u0131l\u0131r ConfigView.section.tracker.maxthreads=En fazla e\u015fanl\u0131 istek DownloadManager.error.operationcancancelled=\u0130\u015flem iptal edildi Torrent.create.progress.cancelled=\u0130\u015flem iptal edildi sharing.progress.cancel=\u0130ptal wizard.maketorrents.autoopen=Bitti\u011finde, torrenti yay\u0131mlamak i\u00e7in a\u00e7 ConfigView.section.sharing.rescanenable=Payla\u015f\u0131mlardaki de\u011fi\u015fiklikleri devresel olarak yeniden taramay\u0131 etkinle\u015ftir ConfigView.section.sharing.rescanperiod=Yeniden tarama s\u0131kl\u0131\u011f\u0131 (sn) ConfigView.section.connection.advanced=Geli\u015fmi\u015f A\u011f Ayarlar\u0131 ConfigView.section.connection.advanced.mtu=Hat en y\u00fcksek iletim birimi (MTU) ConfigView.section.connection.advanced.SO_RCVBUF=SO_RCVBUF yuva b\u00fcy\u00fckl\u00fc\u011f\u00fc [0: \u0130\u015f. Sis. varsay\u0131lan\u0131n\u0131 kullan] ConfigView.section.connection.advanced.SO_SNDBUF=SO_SNDBUF yuva b\u00fcy\u00fckl\u00fc\u011f\u00fc [0: \u0130\u015f. Sis. varsay\u0131lan\u0131n\u0131 kullan] ConfigView.section.interface.confirm_torrent_removal=Torrenti kald\u0131r\u0131rken onay ileti\u015fim kutusunu g\u00f6ster MyTorrentsView.confirm_torrent_removal=Kald\u0131rmak istedi\u011finizden emin misiniz?\n TableColumn.header.seed_to_peer_ratio=OrtaktanE\u015fe Oran TableColumn.header.seed_to_peer_ratio.info=K\u00fcme toplam ortaktan e\u015fe oran\u0131 PeersView.connected_time=Ba\u011flant\u0131 S\u00fcresi PeersView.connected_time.info=E\u015f ile ba\u011fl\u0131 kal\u0131nan toplam zaman ConfigView.section.interface.display.add_torrents_silently=Torrentleri sessizce ekle ConfigView.section.interface.display.add_torrents_silently.tooltip=Ana Vuze penceresini a\u00e7madan torrentleri ekler. TableColumn.header.maxdownspeed=En Y\u00fcksek \u0130nd. H\u0131z\u0131 TableColumn.header.maxdownspeed.info=Torrent ba\u015f\u0131na en y\u00fcksek indirme h\u0131z\u0131 PeersGraphicView.title=K\u00fcme ConfigView.section.tracker.passwordwebhttpsonly=Yaln\u0131zca HTTPS ile eri\u015fime izin ver TableColumn.header.torrentpath=Torrent Yeri TableColumn.header.torrentpath.info=Torrentin disk \u00fczerindeki yeri ConfigView.section.sharing.torrentcomment=Olu\u015fturulmu\u015f torrentler i\u00e7in yorum ConfigView.label.copyanddeleteratherthanmove=Tek i\u015flemde dosyay\u0131 ta\u015f\u0131mak yerine \u00f6nce kopyala ve sonra \u00f6zg\u00fcn dosyay\u0131 sil (Baz\u0131 dosya sistemlerinde veri kayb\u0131n\u0131 \u00f6nleyebilir) ConfigView.label.openstatsonstart=Ba\u015flang\u0131\u00e7ta istatistik sekmesini a\u00e7 swt.install.window.title=Vuze Eklenti Kurucu swt.install.window.ok=Kur swt.install.window.header=A\u015fa\u011f\u0131daki bile\u015fenler kurulum i\u00e7in se\u00e7ildi : swt.uninstall.window.title=Vuze Eklenti Kald\u0131r\u0131c\u0131 swt.uninstall.window.ok=Kald\u0131r swt.uninstall.window.header=Takip eden bile\u015fenler kald\u0131r\u0131lmak i\u00e7in se\u00e7ildi : installPluginsWizard.title=Eklentileri Kur installPluginsWizard.mode.title=L\u00fctfen bir kurulum y\u00f6ntemi se\u00e7in installPluginsWizard.mode.list=sourceforge.net adresindeki listeden se\u00e7 installPluginsWizard.list.title=Kurulabilir Eklenti Listesi installPluginsWizard.list.loading=Eklenti listesi y\u00fcklenirken l\u00fctfen bekleyin. installPluginsWizard.list.loaded=L\u00fctfen kuraca\u011f\u0131n\u0131z eklentileri se\u00e7in. installPluginsWizard.list.name=Ad installPluginsWizard.list.version=S\u00fcr\u00fcm installPluginsWizard.list.description=Eklenti a\u00e7\u0131klamas\u0131 installPluginsWizard.finish.title=Kurulum Devam Ediyor installPluginsWizard.finish.explanation=Se\u00e7ilen Eklentiler, G\u00fcncelleme Asistan\u0131 kullan\u0131larak kurulacak.\n\nL\u00fctfen bekleyin, g\u00f6r\u00fcnmesi biraz zaman alabilir.\n\n\u0130lerleme raporu i\u00e7in durum \u00e7ubu\u011funun sol tarar\u0131na \u00e7ift t\u0131klay\u0131n. installPluginsWizard.details.loading=Ayr\u0131nt\u0131lar y\u00fckleniyor, l\u00fctfen bekleyin... installPluginsWizard.mode.file=Eklentiyi dosyadan kur installPluginsWizard.installMode.title=L\u00fctfen kurulum t\u00fcr\u00fcn\u00fc se\u00e7in installPluginsWizard.installMode.user=Eklenti(ler) yaln\u0131zca sizin i\u00e7in kuruluyor installPluginsWizard.installMode.shared=Eklentiyi/eklentileri t\u00fcm kullan\u0131c\u0131lar i\u00e7in kur installPluginsWizard.file.title=L\u00fctfen kuraca\u011f\u0131n\u0131z eklenti i\u00e7in g\u00f6z at\u0131n installPluginsWizard.file.file=Dosya : installPluginsWizard.file.invalidfile=Dosya ge\u00e7erli bir Vuze eklenti de\u011fil. installPluginsWizard.file.browse=G\u00f6z at... uninstallPluginsWizard.title=Eklentileri Kald\u0131r uninstallPluginsWizard.list.title=Kurulmu\u015f Eklenti Listesi uninstallPluginsWizard.list.loaded=L\u00fctfen kald\u0131rmak istedi\u011finiz eklentileri se\u00e7in. installPluginsWizard.list.nullversion=S\u00fcr\u00fcm Yok uninstallPluginsWizard.finish.title=Kald\u0131rma Devam Ediyor uninstallPluginsWizard.finish.explanation=Se\u00e7ilen eklentiler, 'G\u00fcncelleme Yard\u0131mc\u0131s\u0131' kullan\u0131larak kald\u0131r\u0131lacak. MainWindow.menu.plugins.installPlugins=Kurulum Sihirbaz\u0131... MainWindow.menu.plugins.uninstallPlugins=Kald\u0131rma Sihirbaz\u0131... ConfigView.section.ipfilter.totalIPs=\u0130nternetteki %2 adresten, toplamda %1 tane IP engellendi. update.instance.install=Kurulum Denetleniyor update.instance.uninstall=Kald\u0131rma Denetleniyor update.instance.update=G\u00fcncellemeler denetleniyor MainWindow.status.update.tooltip=\u0130lerleme bilgisi i\u00e7in \u00e7ift t\u0131klay\u0131n updater.progress.window.title=Ge\u00e7erli Kurulum G\u00f6revleri updater.progress.window.info=Bekleyen t\u00fcm g\u00f6revleri durdumak i\u00e7in 'Durdur' d\u00fc\u011fmesine t\u0131klay\u0131n Button.abort=Durdur ConfigView.section.ipfilter.enablebanning=S\u00fcrekli olarak bozuk veri g\u00f6nderen e\u015fleri engelle MyShares.column.category=Ulam UpdateWindow.restartLater=Daha Sonra Yeniden Ba\u015flat MainWindow.menu.file.restart=Vuze u Yeniden Ba\u015flat MainWindow.dialog.restartconfirmation.title=Vuze Yeniden Ba\u015flat\u0131ls\u0131n m\u0131? MainWindow.dialog.restartconfirmation.text=Vuze u ger\u00e7ekten yeniden ba\u015flatmak istiyor musunuz? deletetorrent.message1=TORRENT silmek \u00fczeresiniz :\n deletetorrent.message2=\nDevam etmek istedi\u011finizden emin misiniz? ConfigView.label.prioritizemostcompletedfiles=\u00d6nceli\u011fi en \u00e7ok tamamlanm\u0131\u015f dosyalara ver splash.plugin.init=Eklenti Ba\u015flat\u0131l\u0131yor: ConfigView.section.style.osx_small_fonts=K\u00fc\u00e7\u00fck yaz\u0131 tipleri kullan [Yeniden ba\u015flatma gerekir] ConfigView.section.tracker.tcpnonblocking=\u0130zleyici i\u015flemi i\u00e7in engellenmemi\u015f G/\u00c7 kullan. ConfigView.section.tracker.nonblocking=Engellenmemi\u015f Se\u00e7enekleri ConfigView.section.tracker.nonblockingconcmax=En y\u00fcksek e\u015fanl\u0131 ba\u011flant\u0131 [0: s\u0131n\u0131rs\u0131z] MyTorrentsView.menu.exportmenu=Ver ConfigView.group.scrape=Durum S\u0131namas\u0131 ConfigView.section.tracker.client.scrapeinfo=Durum s\u0131namas\u0131n\u0131 etkisizle\u015ftirme, izleyicilerden al\u0131nacak k\u00fcme bilgisine ba\u011fl\u0131 olarak \u00e7al\u0131\u015fan\nbir\u00e7ok torrentin s\u0131raya konamamas\u0131na neden olur. ConfigView.section.tracker.client.scrapeenable=Durum s\u0131namas\u0131n\u0131 etkinle\u015ftir ConfigView.section.tracker.client.scrapestoppedenable=\u00c7al\u0131\u015fmayan torrentleri s\u0131na Scrape.status.disabled=Durum s\u0131namas\u0131 etkisizle\u015ftirildi MyTorrentsView.menu.explore=Dosyay\u0131 G\u00f6ster MyTorrentsView.menu.explore._mac=Bulucu Uygulamas\u0131nda G\u00f6ster MyTorrentsView.menu.explore._windows=G\u00f6zat\u0131c\u0131da G\u00f6ster wizard.maketorrents.autohost=Yerle\u015fik izleyicide torrent bar\u0131nd\u0131r ConfigView.label.overrideip=\u0130zleyiciye g\u00f6nderilen IP adresini ge\u00e7ersiz k\u0131l\n(Bazen NAT'lar i\u00e7in gereklidir) ConfigView.section.connection.group.networks=A\u011flar ConfigView.section.connection.group.networks.info=E\u015fler aras\u0131 veri iletimi i\u00e7in varsay\u0131lan olarak izin verilen a\u011flar\u0131 se\u00e7in ConfigView.section.connection.networks.prompt=Anonim bir izleyici i\u00e7eren bir indirme i\u015flemi eklendi\u011finde kullan\u0131c\u0131dan se\u00e7im iste ConfigView.section.connection.networks.Public=Genel IP a\u011f\u0131 (Anonim olmayan) ConfigView.section.connection.networks.I2P=I2P a\u011f\u0131 ConfigView.section.connection.networks.Tor=The Onion Router (Tor) a\u011f\u0131 TableColumn.header.networks=A\u011flar TableColumn.header.networks.info=E\u015f-e\u015f veri ileti\u015fimi i\u00e7in izin verilmi\u015f olan a\u011flar Scrape.status.networkdisabled=A\u011f etkin de\u011fil ConfigView.section.tracker.server.group.networks=A\u011flar ConfigView.section.tracker.server.group.networks.info=\u0130zleyicinin e\u015fleri kabul edece\u011fi a\u011flar\u0131 se\u00e7 window.networkselection.title=A\u011f Se\u00e7imi window.networkselection.info=A\u015fa\u011f\u0131da listelenen torrent, a\u015fa\u011f\u0131daki a\u011flar\u0131 destekleyen izleyiciye/izleyicilere sahiptir.\n\u0130zleyici ve e\u015f ba\u011flant\u0131s\u0131 i\u00e7in etkinle\u015ftirmek istediklerinizi se\u00e7in.\nE\u011fer halka a\u00e7\u0131k istemcileri destekleyen anonim bir izleyici ise hem anonim ve hem de halka a\u00e7\u0131k a\u011flar\u0131 se\u00e7in.\nHalka a\u00e7\u0131k a\u011f\u0131 etkinle\u015ftirmek, gizlili\u011fi kald\u0131rmak anlam\u0131na gelir! plugins.basicview.clear=Temizle ConfigView.section.connection.group.peersources=E\u015f Kaynaklar\u0131 ConfigView.section.connection.group.peersources.info=E\u015flere ba\u011flant\u0131 i\u00e7in varsay\u0131lan olarak izin verilen kaynaklar\u0131 se\u00e7in ConfigView.section.connection.peersource.Tracker=Bir izleyiciden ConfigView.section.connection.peersource.DHT=Da\u011f\u0131t\u0131lm\u0131\u015f izleme ConfigView.section.connection.peersource.PeerExchange=Ba\u015fka bir e\u015f taraf\u0131ndan sa\u011flanan ConfigView.section.connection.peersource.Plugin=Bir eklenti taraf\u0131ndan eklenen ConfigView.section.connection.peersource.Incoming=Gelen ba\u011flant\u0131 PeersView.source=Kaynak PeersView.source.info=Bu e\u015fin kayna\u011f\u0131 TableColumn.header.peersources=E\u015f Kaynaklar\u0131 TableColumn.header.peersources.info=E\u015f ba\u011flant\u0131s\u0131 kurmak i\u00e7in izin verilmi\u015f olan e\u015f kaynaklar\u0131 wizard.tracker.dht=Da\u011f\u0131t\u0131lm\u0131\u015f (Sadece Vuze istemcileri) MyTorrentsView.menu.advancedmenu=Geli\u015fmi\u015f MyTorrentsView.menu.networks=A\u011flar MyTorrentsView.menu.peersource=E\u015f Kaynaklar\u0131 ConfigView.section.sharing.permitdht=\u0130zleyiciye eri\u015filemedi\u011finde da\u011f\u0131t\u0131lm\u0131\u015f izlemeye izin ver. ConfigView.section.sharing.protocol=Payla\u015f\u0131lan kaynaklar i\u00e7in ileti\u015fim kural\u0131 (izleyici yap\u0131land\u0131rmas\u0131 gerektirir) PeersView.Messaging=Mesajla\u015fma PeersView.Messaging.info=Geli\u015fmi\u015f mesajla\u015fma API'sini destekler. ConfigView.label.queue.newseedsmovetop=Yenice bitmi\u015f torrentleri yay\u0131mlananlar listesinin ba\u015f\u0131na ta\u015f\u0131 ConfigView.label.seeding.firstPriority.ignore.info=Bu kurallar\u0131n, \u00e7al\u0131\u015fan bir torrenti, indirme i\u015flemi bitti\u011finde durdurma olas\u0131l\u0131\u011f\u0131n\u0131 g\u00f6z \u00f6n\u00fcnde bulundurun. ConfigView.label.seeding.firstPriority.ignore=Yukar\u0131daki Birincil \u00d6ncelik Kurallar\u0131n\u0131 Yoksayma Ko\u015fullar\u0131 ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrentin Ortaktan E\u015fe oran\u0131 en az : ConfigView.label.seeding.firstPriority.ignore0Peer=0 tane e\u015fe sahip torrentler ConfigView.section.tracker.sendjavaversionandos=Java s\u00fcr\u00fcm\u00fcn\u00fc ve i\u015fletim sistemi ad\u0131n\u0131 g\u00f6nder MagnetPlugin.contextmenu.exporturi=Magnet URI'yi Panoya Kopyala ConfigView.section.plugins.dht=Da\u011f\u0131t\u0131ml\u0131 VT dht.info=Bu eklenti, di\u011fer \u015feylerin yan\u0131 s\u0131ra da\u011f\u0131t\u0131lm\u0131\u015f izlemeyi destekler (devre d\u0131\u015f\u0131 b\u0131rakmak indirme kabiliyetinizi azaltacakt\u0131r) dht.enabled=Da\u011f\u0131t\u0131ml\u0131 veritaban\u0131n\u0131 etkinle\u015ftir dht.portdefault=Varsay\u0131lan ba\u011flant\u0131 noktas\u0131n\u0131 kullan dht.port=Veritaban\u0131 i\u00e7in UDP ba\u011flant\u0131 noktas\u0131 dht.execute.command=Sistem denetim komutu dht.execute.info=Komutu \u00e7al\u0131\u015ft\u0131rmak i\u00e7in t\u0131klay\u0131n dht.execute=\u00c7al\u0131\u015ft\u0131r dht.logging=Olay izlenmeyi etkinle\u015ftir ConfigView.section.plugins.dhttracker=Da\u011f\u0131t\u0131ml\u0131 \u0130zleyici dhttracker.tracknormalwhenoffline=\u0130zleyicisi kullan\u0131lamaz oldu\u011funda yaln\u0131zca normal torrentleri izle ConfigView.section.file.nativedelete._mac=Dosyalar\u0131 silerken \u00c7\u00f6p\u00fc kullan ConfigView.section.file.nativedelete._windows=Silinen dosyalar\u0131 Geri D\u00f6n\u00fc\u015f\u00fcm Kutusuna ta\u015f\u0131 ConfigView.section.logging.generatediagnostics=Olu\u015ftur ConfigView.section.logging.generatediagnostics.info=Te\u015fhis bilgisini olu\u015ftur ve panoya; e\u011fer yap\u0131land\u0131r\u0131ld\u0131ysa da g\u00fcnl\u00fck dosyas\u0131na kopyala ConfigView.section.sharing.privatetorrent=\u00d6zel torrent (sadece belirtilen izleyicideki e\u015fler kabul edilir) MainWindow.menu.tools.nattest=NAT / G\u00fcvenlik Duvar\u0131 S\u0131namas\u0131 Button.apply=Uygula Button.close=Kapat window.welcome.title=Vuze %1'e Ho\u015f Geldiniz #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=S\u00fcr\u00fcm Notlar\u0131 dht.reseed.group=Tekrar Yay\u0131mla dht.reseed.ip=IP adresi dht.reseed.port=Ba\u011flant\u0131 noktas\u0131 dht.reseed=Tekrar Yay\u0131mla dht.reseed.info=Veritaban\u0131n\u0131 tekrar yay\u0131mla dht.diagnostics.group=Sistem Denetimi DHTView.title.full=Da\u011f\u0131t\u0131ml\u0131 Veritaban\u0131 DHTView.title.fullcvs=Da\u011f\u0131t\u0131ml\u0131 Veritaban\u0131 CVS DHTView.general.title=Genel DHTView.general.uptime=\u00c7al\u0131\u015fma s\u00fcresi: DHTView.general.users=Kullan\u0131c\u0131lar: DHTView.general.nodes=D\u00fc\u011f\u00fcmler DHTView.general.leaves=Ayr\u0131lmalar: DHTView.general.contacts=Ba\u011flant\u0131lar: DHTView.general.replacements=De\u011fi\u015ftirmeler: DHTView.general.live=Canl\u0131: DHTView.general.unknown=Bilinmeyen: DHTView.general.dying=\u00d6l\u00fcyor: DHTView.transport.title=Ta\u015f\u0131ma Ayr\u0131nt\u0131lar\u0131 DHTView.transport.packets=Paketler DHTView.transport.bytes=Byte DHTView.transport.received=\u0130ndirilen DHTView.transport.sent=G\u00f6nderilen DHTView.transport.in=Giri\u015f : DHTView.transport.out=\u00c7\u0131k\u0131\u015f : DHTView.operations.title=\u0130\u015flem Ayr\u0131nt\u0131lar\u0131 DHTView.operations.sent=G\u00f6nderildi DHTView.operations.ok=Tamam DHTView.operations.failed=Ba\u015far\u0131s\u0131z DHTView.operations.received=Al\u0131nd\u0131 DHTView.operations.findNode=D\u00fc\u011f\u00fcm Bul DHTView.operations.findValue=De\u011fer Bul DHTView.operations.store=Depo DHTView.activity.title=Etkinlik DHTView.activity.status=Durum DHTView.activity.status.true=S\u0131rada DHTView.activity.status.false=\u00c7al\u0131\u015f\u0131yor DHTView.activity.type=T\u00fcr DHTView.activity.target=Hedef DHTView.activity.details=Ayr\u0131nt\u0131lar DHTView.db.title=Veritaban\u0131 DHTView.db.keys=Anahtarlar DHTView.db.values=De\u011ferler DHTView.db.local=Yerel DHTView.db.direct=Do\u011frudan DHTView.db.indirect=Dolayl\u0131 MainWindow.dht.status.tooltip=Da\u011f\u0131t\u0131ml\u0131 veritaban\u0131 \u00e7al\u0131\u015f\u0131yorken, halen \u00e7evrimi\u00e7i olan tahmini kullan\u0131c\u0131 say\u0131s\u0131n\u0131 g\u00f6sterir MainWindow.dht.status.disabled=\u0130ptal edildi MainWindow.dht.status.failed=DHT ba\u015far\u0131s\u0131z oldu MainWindow.dht.status.initializing=DHT Ba\u015flat\u0131l\u0131yor MainWindow.dht.status.users=%1 tane kullan\u0131c\u0131 MainWindow.dht.status.unreachable=DHT G\u00fcvenlik Duvarl\u0131 MainWindow.dht.status.unreachabletooltip=Da\u011f\u0131t\u0131ml\u0131 veritaban\u0131n\u0131n UDP ba\u011flant\u0131 noktas\u0131 y\u00f6nlendirmesinde bir sorun var gibi g\u00f6r\u00fcn\u00fcyor (NAT/G\u00fcvenlik Duvar\u0131) MyTorrentsView.menu.setUpSpeed=G\u00f6nderme H\u0131z\u0131n\u0131 Ayarla MyTorrentsView.menu.setDownSpeed=\u0130ndirme H\u0131z\u0131n\u0131 Ayarla ConfigView.section.tracker.client.showwarnings=\u0130zleyici taraf\u0131ndan raporlanan uyar\u0131 iletilerini g\u00f6ster dht.advanced=Geli\u015fmi\u015f ayarlar\u0131 etkinle\u015ftir dht.advanced.group=Geli\u015fmi\u015f ayarlar dht.advanced.label=Yaln\u0131zca, ger\u00e7ekten ne yapt\u0131\u011f\u0131n\u0131z\u0131 biliyorsan\u0131z bu de\u011ferleri de\u011fi\u015ftirin dht.override.ip=D\u0131\u015fsal IP adresini ge\u00e7ersiz k\u0131l ConfigView.section.logging.loggerenable=G\u00fcnl\u00fck tutmay\u0131 etkinle\u015ftir ConfigView.section.ipfilter.blockbanning=256 adreslik bir \u00f6be\u011fi engellemek i\u00e7in bu \u00f6be\u011fe ba\u011fl\u0131 \u00f6nceden engellenmi\u015f en az adres say\u0131s\u0131 : MyTrackerView.passive=Edilgen TableColumn.header.swarm_average_speed=K\u00fcme Ortalama H\u0131z\u0131 TableColumn.header.swarm_average_speed.info=K\u00fcmedeki e\u015flerin ortalama h\u0131z\u0131 MyTrackerView.category=Ulam MainWindow.menu.file.open.torrentfortracking=Torrent Dosyas\u0131... (\u0130zleme Ama\u00e7l\u0131) VivaldiView.title.full=Sanal Konumland\u0131rma MyTrackerView.date_added=Eklenme Tarihi ConfigView.section.tracker.portbackup=Yedek ba\u011f. noktalar\u0131 (';' ile ayr\u0131lm\u0131\u015f) ConfigView.label.playfilespeech=Bir dosya tamamland\u0131\u011f\u0131nda konu\u015f ConfigView.label.playfilespeech.info=Konu\u015fma hizmeti \u015fu anda en iyi sadece \u0130ngilizce \u00e7al\u0131\u015fabiliyor ConfigView.label.playfilefinished=Bir dosya tamamland\u0131\u011f\u0131nda bir ses \u00e7al ConfigView.label.backupconfigfiles=Yap\u0131land\u0131rma dosyalar\u0131n\u0131 kurtarma ama\u00e7l\u0131 olarak yedekle ConfigView.section.tracker.client.scrapesingleonly=Herbir izleyici durum s\u0131nama k\u00fcmele\u015fmesini etkisizle\u015ftir ActivityView.legend.limit=Oran s\u0131n\u0131r\u0131 ActivityView.legend.achieved=Ula\u015f\u0131lan oran ActivityView.legend.peeraverage=Yay\u0131mlama ActivityView.legend.swarmaverage=K\u00fcme yay\u0131mlamas\u0131 ActivityView.legend.trimmed=K\u0131rp\u0131lm\u0131\u015f (Noktal\u0131) MyTorrentsView.menu.movemenu=Dosyalar\u0131 Ta\u015f\u0131 MyTorrentsView.menu.movedata=Veri Dosyalar\u0131n\u0131 Ta\u015f\u0131... MyTorrentsView.menu.movetorrent=Torrent Dosyas\u0131n\u0131 Ta\u015f\u0131... MyTorrentsView.menu.movedata.dialog=Yeni konmu se\u00e7 DHTView.operations.data=Veri DHTView.general.reachable=Bulunabilir: DHTView.general.rendezvous=Bulu\u015fma: ConfigView.label.queue.maxactivetorrentswhenseeding=Sadece yay\u0131mlarken en fazla [0:s\u0131n\u0131rs\u0131z] Views.plugins.IRC.title=IRC - \u00c7evrimi\u00e7i Teknik Destek ConfigView.section.ipfilter.persistblocking=Engellenen IP ayr\u0131nt\u0131lar\u0131n\u0131 yeniden ba\u015flat\u0131rken kaydet FilesView.menu.rename=Yeniden adland\u0131r veya hedefle FilesView.rename.choose.path=Yeni veya varolan dosyay\u0131 se\u00e7in FilesView.rename.confirm.delete.title=Silme Onay\u0131 FilesView.rename.confirm.delete.text='%1' \u00f6zg\u00fcn dosyas\u0131n\u0131 silmeyi onaylay\u0131n ConfigView.section.mode=Kip ConfigView.section.mode.title=Kullan\u0131c\u0131 Yeterlili\u011fi ConfigView.section.mode.beginner=Acemi ConfigView.section.mode.beginner.wiki.definitions=BitTorrent S\u00f6zc\u00fck Da\u011farc\u0131\u011f\u0131 ConfigView.section.mode.intermediate=Orta ConfigView.section.mode.intermediate.wiki.host=Dosya Bulundurma ConfigView.section.mode.intermediate.wiki.publish=Dosya Yay\u0131mlama ConfigView.section.mode.advanced=Deneyimli ConfigView.section.mode.advanced.wiki.main=Viki Ana Sayfa ConfigView.section.mode.beginner.text=Torrentleri indirmek i\u00e7in gerekli olan her\u015feye eri\u015febilir.\nT\u00fcm istedi\u011finiz torrentlerinizi idare etmekse bu kipi kullan\u0131n. ConfigView.section.mode.intermediate.text=\u0130zleyici i\u015flevlerine eri\u015febilir.\nKendi izleyicinizi olu\u015fturmak ve dosyalar\u0131n\u0131z\u0131 bulundurmak/yay\u0131mlamak istiyorsan\u0131z bu kipi kullan\u0131n. ConfigView.section.mode.advanced.text=A\u011f ayarlar\u0131na eri\u015febilir.\nMTU ya da engellenmemi\u015f G/\u00c7 kavramlar\u0131n\u0131n ne oldu\u011funu biliyorsan\u0131z bunu kullan\u0131n... Files.column.storagetype=Depolama T\u00fcr\u00fc FileItem.storage.linear=Do\u011frusal FileItem.storage.compact=Yo\u011fun MessageBoxWindow.rememberdecision=Tercihimi hat\u0131rla ConfigView.section.interface.cleardecisions=Kaydedilen ileti\u015fim kutusu tercihlerimi temizle ConfigView.section.interface.cleardecisionsbutton=Temizle configureWizard.welcome.usermodes=Bu, Kullan\u0131c\u0131 Yeterlili\u011fi ayar\u0131, Ara\u00e7lar > Se\u00e7enekler i\u00e7erisindeki se\u00e7eneklerin belirlenmesini sa\u011flayacak. Uygun bir \u015fekilde yap\u0131land\u0131rman\u0131z sizin yarar\u0131n\u0131za olacakt\u0131r. FilesView.skip.confirm.delete.text=Disk alan\u0131ndan kazanmak i\u00e7in '%1' dosyas\u0131 k\u00fc\u00e7\u00fclt\u00fcls\u00fcn m\u00fc? FilesView.rename.failed.title=Yeniden adland\u0131rma/ta\u015f\u0131ma ba\u015far\u0131s\u0131z FilesView.rename.failed.text=\u0130\u015flem, olas\u0131 yanl\u0131\u015f hedef se\u00e7iminden dolay\u0131 ba\u015far\u0131s\u0131z oldu diagnostics.log_found=Vuzedid not shutdown tidily. Check %1 for diagnostic log files and consider reporting them to the Vuze team if this is the result of an application error. Also check the Wiki (see the Help menu) for 'Vuze Disappears' ManagerItem.paused=Duraklat\u0131ld\u0131 Utils.link.visit=Buray\u0131 ziyaret edin ConfigView.section.connection.serverport.wiki=\u0130yi Ba\u011flant\u0131 Noktas\u0131 Tercihleri ConfigView.section.transfer.speeds.wiki=\u0130yi H\u0131z Ayarlar\u0131 installPluginsWizard.installMode.info.title=Bilgi Views.plugins.Distributed.DB.title=Da\u011f\u0131t\u0131ml\u0131 Veritaban\u0131 Views.plugins.Distributed.Tracker.title=Da\u011f\u0131t\u0131ml\u0131 \u0130zleyici Views.plugins.Plugin.Update.title=Eklenti G\u00fcncelleme Views.plugins.UPnP.title.tooltip=Evrensel Tak ve \u00c7al\u0131\u015ft\u0131r openUrl.url.info=http, https, magnet ve raw hex infohash dizgilerini destekler TableColumn.header.swarm_average_completion=E\u015flerdeki Ortalama Tamamlanma GeneralView.label.swarm_average_completion=Ortalama Tamamlanma: MainWindow.nat.status.tooltip.unknown=G\u00fcvenlik Duvar\u0131/NAT ula\u015f\u0131labilirlik durumu bilinmiyor (TCP) MainWindow.nat.status.ok=NAT Sorunsuz MainWindow.nat.status.tooltip.ok=Ula\u015f\u0131labilirlik TAMAM (TCP) MainWindow.nat.status.probok=NAT Durumu? MainWindow.nat.status.tooltip.probok=Ula\u015f\u0131labilirlik sorunsuz; yine de g\u00fcncel gelen TCP ba\u011flant\u0131s\u0131 yok. MainWindow.nat.status.bad=G\u00fcvenlik Duvarl\u0131 MainWindow.nat.status.tooltip.bad=G\u00fcvenlik Duvar\u0131/NAT (TCP) ula\u015f\u0131labilirlik sorunu. Yard\u0131m i\u00e7in Viki'ye ba\u015fvurunuz. LoggerView.pause=G\u00fcnl\u00fck tutmay\u0131 duraklat LoggerView.clear=&Temizle LoggerView.filter=S\u00fczge\u00e7 LoggerView.filter.uncheckAll=T\u00fcm\u00fcn\u00fcn i\u015faretini kald\u0131r LoggerView.filter.checkAll=T\u00fcm\u00fcn\u00fc i\u015faretle LoggerView.loggingDisabled=G\u00fcnl\u00fck tutma etkinle\u015ftirilmedi ConfigView.section.logging.log0type=bilgileri ConfigView.section.logging.log1type=uyar\u0131lar\u0131 ConfigView.section.logging.log2type=hatalar\u0131 ConfigView.section.logging.filter=G\u00fcnl\u00fc\u011f\u00fc dosyaya kaydederken s\u00fcz ConfigView.section.logging.level=Seviye ConfigView.section.logging.showLogsFor=A\u015fa\u011f\u0131daki ulamlar i\u00e7in %1 g\u00f6ster: ConfigView.pluginlist.column.loadAtStartup=Ba\u015flang\u0131\u00e7ta Y\u00fckle ConfigView.pluginlist.column.type=T\u00fcr ConfigView.pluginlist.column.type.perUser=Herbir Kullan\u0131c\u0131 ConfigView.pluginlist.column.type.shared=Payla\u015f\u0131lm\u0131\u015f ConfigView.pluginlist.column.type.builtIn=Yerle\u015fik ConfigView.pluginlist.column.name=Ad ConfigView.pluginlist.column.version=S\u00fcr\u00fcm ConfigView.pluginlist.column.directory=Dizin ConfigView.pluginlist.column.isOperational=\u0130\u015flemsel? PeersView.BlockView.Avail.Have=\u0130kinizde de var PeersView.BlockView.Avail.NoHave=E\u015fte var; sende yok PeersView.BlockView.NoAvail.Have=Sende var; e\u015fte yok PeersView.BlockView.NoAvail.NoHave=\u0130kinizde de yok PeersView.BlockView.Transfer=Aktar\u0131l\u0131yor PeersView.BlockView.NextRequest=Sonraki istek PeersView.BlockView.title=Par\u00e7a Haritas\u0131 PeersView.BlockView.AvailCount=Kullan\u0131l\u0131rl\u0131k kapsam\u0131 MyTorrentsView.dialog.NumberError.title=Ge\u00e7ersiz ya da bilinmeyen say\u0131 MyTorrentsView.dialog.NumberError.text=Ge\u00e7ersiz ya da bilinmeyen bir say\u0131 girdiniz. MyTorrentsView.menu.manual=&El ile... # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.upload=g\u00f6nderme MyTorrentsView.dialog.setNumber.download=indirme MyTorrentsView.dialog.setNumber.inKbps=in kb/s OpenTorrentWindow.torrentLocation=Torrent Dosyalar\u0131: OpenTorrentWindow.addFiles.URL=&URL Ekle OpenTorrentWindow.addFiles.Folder=&Dizin Ekle OpenTorrentWindow.addFiles.Clipboard=&Panodan Ekle OpenTorrentWindow.changeDestination=Hedef Dizini De\u011fi\u015ftir OpenTorrentWindow.fileList=Torrentin \u0130\u00e7erdi\u011fi Dosyalar: OpenTorrentWindow.torrentTable.name=Ad OpenTorrentWindow.torrentTable.saveLocation=Kaydetme Yeri OpenTorrentWindow.fileTable.fileName=Dosya Ad\u0131 OpenTorrentWindow.fileTable.size=B\u00fcy\u00fckl\u00fck OpenTorrentWindow.fileTable.destinationName=Hedef Ad OpenTorrentWindow.startMode.seeding=Yay\u0131mlan\u0131yor OpenTorrentWindow.fileList.changeDestination=Hedef Dizini De\u011fi\u015ftir OpenTorrentWindow.mb.badSize.title=Uyumsuz Dosya OpenTorrentWindow.mb.badSize.text='%1', '%2' de\u011fil ve yay\u0131mlama i\u00e7in kullan\u0131lamaz OpenTorrentWindow.mb.alreadyExists.text=%1' torrenti '%2' olarak zaten eklenmi\u015f OpenTorrentWindow.mb.alreadyExists.title=Torrent zaten mevcut OpenTorrentWindow.mb.openError.title=A\u00e7ma Hatas\u0131 OpenTorrentWindow.mb.openError.text='%1' a\u00e7\u0131lamad\u0131: OpenTorrentWindow.torrent.remove=Torrenti listeden kald\u0131r OpenTorrentWindow.torrent.options=A\u015fa\u011f\u0131daki ayarlar yukar\u0131da se\u00e7ilmi\u015f olan torrentlere uygulanacak: OpenTorrentWindow.xOfTotal=(%2'de %1) iconBar.open.tooltip=Torrent(ler)i A\u00e7 LocaleUtil.column.text=Bilinmeyen Metin Tracker.tooltip.MultiSupport=Bu izleyici tek istemde \u00e7oklu durum s\u0131namay\u0131 destekliyor. Tracker.tooltip.NoMultiSupport=Bu izleyici tek istemde \u00e7oklu durum s\u0131namay\u0131 desteklemiyor. ConfigView.label.lazybitfield=Tembel ikil alan kullan LoggerView.realtime=Ger\u00e7ek zamanl\u0131 g\u00fcncelleme ConfigView.section.file.writemblimit=En fazla yazma istek s\u0131ras\u0131 (%1 olarak) ConfigView.section.file.readmblimit=En fazla okuma istek s\u0131ras\u0131 (%1 olarak) Button.moveUp=Yukar\u0131 ta\u015f\u0131 Button.moveDown=A\u015fa\u011f\u0131 ta\u015f\u0131 ConfigView.notAvailableForMode=Bu k\u0131s\u0131m %1 ya da daha \u00fcst kipler i\u00e7in tasarlanm\u0131\u015ft\u0131r. %2 kipinde bu k\u0131s\u0131ma ula\u015f\u0131lamaz. health.explain.error=Bu torrentle ilgili bir sorun var. Durum s\u00fctununa ya da hata simgesindeki ipucu metnine bak\u0131n. GeneralView.label.trackerscrapeupdate=\u0130zleyicide Durum S\u0131namas\u0131 Yap PeersView.piece=Par\u00e7a PiecesView.priority=\u00d6ncelik PiecesView.speed=H\u0131z ConfigView.label.strictfilelocking=\u0130ndirilmekte olan dosyalara d\u0131\u015fsal yazma eri\u015fimini kilitle MyTorrentsView.menu.rescanfile=Tamamlanmam\u0131\u015f Par\u00e7alar\u0131 S\u0131kl\u0131kla Denetle Plugin.extseed.name=D\u0131\u015fsal Ortaklar Plugin.localtracker.name=LAN E\u015f Bulucu ConfigView.section.transfer.lan.uploadrate=KB/s olarak LAN i\u00e7in en y\u00fcksek g\u00f6nderme h\u0131z\u0131 [0: s\u0131n\u0131rs\u0131z] ConfigView.section.transfer.lan.downloadrate=KB/s olarak LAN i\u00e7in en y\u00fcksek indirme h\u0131z\u0131 [0: s\u0131n\u0131rs\u0131z] TorrentOptionsView.title.short=Se\u00e7enekler TorrentOptionsView.title.full=Se\u00e7enekler TorrentOptionsView.param.max.peers=En fazla ba\u011flant\u0131 say\u0131s\u0131 [0: S\u0131n\u0131rs\u0131z] ConfigView.section.connection.encryption.require_encrypted_transport=\u015eifrelenmi\u015f ta\u015f\u0131ma iste ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Di\u011fer e\u015flerle \u015fifrelenmi\u015f ba\u011flant\u0131 kullan\u0131m\u0131n\u0131 zorla. ConfigView.section.connection.encryption.min_encryption_level=En d\u00fc\u015f\u00fck \u015fifreleme seviyesi ConfigView.section.connection.encryption.min_encryption_level.tooltip=D\u00fcz - sadece anla\u015fma\nRC4 - tam ak\u0131m\nY\u00fcksek \u015fifreleme daha fazla i\u015flemci g\u00fcc\u00fc gerektirir. Peers.column.Encryption=\u015eifreleme Peers.column.Encryption.info=Kullan\u0131mdaki \u015fifreleme seviyesi ConfigView.section.connection.encryption.encrypt.info=\u015eifreleme etkinse, ge\u00e7i\u015f se\u00e7eneklerini yap\u0131land\u0131rmad\u0131\u011f\u0131n\u0131z s\u00fcrece uyumsuz istemcilere ba\u011flanamazs\u0131n\u0131z. ConfigView.section.connection.encryption.encrypt.info.link=Ayr\u0131nt\u0131lar i\u00e7in l\u00fctfen buraya t\u0131klay\u0131p a\u00e7\u0131lan sayfaya bak\u0131n MainWindow.sr.status.tooltip.ok=%1 Oran\u0131ndaki Payla\u015f\u0131m UYGUN MainWindow.sr.status.tooltip.poor=Payla\u015f\u0131m Oran\u0131 %1 zay\u0131f: < 0.9 MainWindow.sr.status.tooltip.bad=Payla\u015f\u0131m Oran\u0131 %1 k\u00f6t\u00fc: < 0.5 ConfigView.section.style.status=Durum \u00c7ubu\u011fu: ConfigView.section.style.status.show_sr=Payla\u015f\u0131m Oran\u0131 ConfigView.section.style.status.show_nat=NAT Durumu ConfigView.section.style.status.show_ddb=DVT Durumu ConfigView.section.connection.encryption.encrypt.group=Ta\u015f\u0131ma \u015eifreleme/Karma\u015f\u0131kla\u015ft\u0131rma ConfigView.section.connection.encryption.encrypt.fallback_info=Her iki ge\u00e7i\u015f se\u00e7ene\u011fini de etkinle\u015ftirmek uyumsuz istemcilerle ba\u011flant\u0131ya izin verir fakat ba\u011flant\u0131lar\u0131n \u015fifrelenmemesi sonucunu do\u011furur ConfigView.section.connection.encryption.encrypt.fallback_outgoing=\u015eifrelenmi\u015f ba\u011flant\u0131 giri\u015fimi ba\u015far\u0131s\u0131z olursa \u015fifrelenmemi\u015f giden ba\u011flant\u0131lara izin ver ConfigView.section.connection.encryption.encrypt.fallback_incoming=\u015eifrelenmemi\u015f gelen ba\u011flant\u0131lara izin ver ConfigView.section.connection.encryption=Ta\u015f\u0131ma \u015eifreleme upnp.selectedinterfaces=Se\u00e7ilmi\u015f aray\u00fczler (';' ile ayr\u0131lm\u0131\u015f, \u00f6rne\u011fin eth0;eth1) [bo\u015f: t\u00fcm\u00fc] ConfigView.section.style.defaultSortOrder=Varsay\u0131lan s\u0131ralama d\u00fczeni ConfigView.section.style.defaultSortOrder.desc=Azalarak ConfigView.section.style.defaultSortOrder.asc=Artarak ConfigView.section.style.defaultSortOrder.flip=\u00d6nceki d\u00fczenin tersi LoggerView.autoscroll=Otomatik kayd\u0131r Button.selectAll=T\u00fcm\u00fcn\u00fc Se\u00e7 Button.markSelected=Se\u00e7ileni \u0130\u015faretle Button.unmarkSelected=Se\u00e7ilenin \u0130\u015faretini Kald\u0131r plugins.basicview.config=Yap\u0131land\u0131r TorrentOptionsView.param.max.uploads=En fazla g\u00f6nderme yuva say\u0131s\u0131 [en az: 2] MyTorrentsView.dialog.setPosition.title=Konumu Ayarla MyTorrentsView.dialog.setPosition.text=Se\u00e7ilen torrent i\u00e7in yeni bir konum girin MyTorrentsView.menu.reposition.manual=Tekrar Konumland\u0131r.. ConfigView.section.connection.advanced.info.link=Ayr\u0131nt\u0131lar i\u00e7in l\u00fctfen buray\u0131 t\u0131klay\u0131p a\u00e7\u0131lan siteyi ziyaret edin ConfigView.section.connection.advanced.socket.group=Yuva Se\u00e7enekleri ConfigView.section.connection.advanced.bind_port=Yerel ba\u011flant\u0131 noktas\u0131na ba\u011fla [0: Etkisiz] ConfigView.section.proxy.group.tracker=\u0130zleyici \u0130leti\u015fimi ConfigView.section.proxy.group.peer=E\u015f \u0130leti\u015fimi ConfigView.label.maxuploadsseeding=Sadece yay\u0131mlama yap\u0131l\u0131yorsa MyTorrentsView.filter=S\u00fczge\u00e7: popup.error.hideall=T\u00fcm\u00fcn\u00fc Gizle ConfigView.section.style.dataStatsOnly=Sadece veri istatistiklerini g\u00f6ster (\u0130leti\u015fim kural\u0131 istatistiklerini gizler) ConfigView.section.style.separateProtDataStats='Veri (ileti\u015fim kural\u0131)' \u015feklinde ayr\u0131 ayr\u0131 veri ve ileti\u015fim kural\u0131 istatistikleri g\u00f6ster MyTorrentsView.dialog.setFilter.title=S\u00fczge\u00e7i De\u011fi\u015ftir MyTorrentsView.dialog.setFilter.text='%1' b\u00f6l\u00fcm\u00fc a\u015fa\u011f\u0131da belirtece\u011finiz metine g\u00f6re s\u00fcz\u00fclecek. \u00c7oklu t\u00fcmcecikleri s\u00fczmek i\u00e7in '|' (boru) simgesini kullan\u0131n. MyTorrentsView.clearFilter.tooltip=S\u00fczge\u00e7i Temizle MyTorrentsView.menu.filter=S\u00fczge\u00e7 Listesi... ConfigView.section.file.resume.recheck.all=\u00c7\u00f6k\u00fc\u015f sonras\u0131nda program\u0131 tekrar ba\u015flat\u0131nca tamamlanm\u0131\u015f par\u00e7alar i\u00e7in t\u00fcm dosyay\u0131 denetle ConfigureWizard.language.choose=A\u015fa\u011f\u0131daki listeden bir dil se\u00e7in: popup.closing.in=Pencere %1 saniye i\u00e7inde kapanacak popup.more.waiting=%1 ileti daha.. # > 2402 popup.download.finished="%1" i\u015flemi tamamland\u0131. popup.file.finished="%1" dosyas\u0131 indirildi. ConfigView.auto=Otomatik Plugin.localtracker.autoadd.info=Bu yerel e\u015fleri otomatik ekle [';' ile ayr\u0131lm\u0131\u015f adresler, \u00f6rne\u011fin 1.2.3.4] Plugin.localtracker.autoadd=Belirgin e\u015fler Plugin.localtracker.networks.info=A\u015fa\u011f\u0131daki a\u011flar\u0131n yerel oldu\u011funu varsay [';' ile ayr\u0131lm\u0131\u015f a\u011flar, \u00f6rne\u011fin 145.227.*.*] Plugin.localtracker.networks=Yerel a\u011flar MainWindow.menu.view.plugins.logViews=G\u00fcnl\u00fcklere G\u00f6z At SpeedView.stats.autospeed=Otomatik G\u00f6nderme H\u0131z\u0131 SpeedView.stats.autospeed.disabled=Bu \u00f6zellik etkin de\u011fil (DHT'ye ihtiyac\u0131n\u0131z var) veya kullan\u0131mda de\u011fil (g\u00f6nderme h\u0131z\u0131 elle ayarlanm\u0131\u015f) SpeedView.stats.idlePing=Bo\u015fta Pingi: SpeedView.stats.maxPing=En Fazla Ping: SpeedView.stats.currentPing=Ge\u00e7erli Ping: SpeedView.stats.maxUp=En Y\u00fcksek G\u00f6n. H\u0131z\u0131: ConfigView.pluginlist.unloadSelected=Se\u00e7ileni kald\u0131r ConfigView.pluginlist.scan=Yeni eklentileri ara\u015ft\u0131r ConfigView.section.transfer.autospeed=Otomatik H\u0131z ConfigView.section.transfer.autospeed.tooltip=Otomatik h\u0131z ayarlar\u0131 ConfigView.section.transfer.autospeed.info=Otomatik h\u0131z, g\u00f6nderme h\u0131z s\u0131n\u0131r\u0131n\u0131, a\u011f ba\u011flant\u0131s\u0131na fazla y\u00fck bindirmekten ka\u00e7\u0131nacak \u015fekilde kendisi ayarlar.\n\nBu ayar sadece otomatik g\u00f6nderme h\u0131z\u0131 ve da\u011f\u0131t\u0131ml\u0131 veritaban\u0131 etkinse etkinle\u015ftirilir.\n ConfigView.section.transfer.autospeed.minupload=%1 en d\u00fc\u015f\u00fck g\u00f6nderme h\u0131z\u0131 ConfigView.section.transfer.autospeed.minupload.tooltip=G\u00f6nderme h\u0131z\u0131 bu s\u0131n\u0131r\u0131n alt\u0131na otomatik azalt\u0131lmayacak ConfigView.section.transfer.autospeed.maxupload=%1 en y\u00fcksek g\u00f6nderme h\u0131z\u0131 [0: s\u0131n\u0131rs\u0131z] ConfigView.section.transfer.autospeed.maxupload.tooltip=G\u00f6nderme h\u0131z\u0131 bu s\u0131n\u0131r\u0131n \u00fczerine otomatik y\u00fckseltilmeyecek ConfigView.section.transfer.autospeed.chokeping=Ping bo\u011fulma s\u00fcresi [millisaniye] ConfigView.section.transfer.autospeed.enableauto=\u0130ndirme ve yay\u0131mlama s\u0131ras\u0131nda etkinle\u015ftir ConfigView.section.transfer.autospeed.enableautoseeding=Sadece yay\u0131mlama s\u0131ras\u0131nda etkinle\u015ftir ConfigView.pluginlist.column.unloadable=Kald\u0131r\u0131lamama ConfigView.section.transfer.lan.enable=LAN ba\u011flant\u0131lar\u0131 i\u00e7in ayr\u0131 ayr\u0131 h\u0131z s\u0131n\u0131rlamay\u0131 etkinle\u015ftir TableColumn.header.filesdone=Tamamlanan Dosyalar MagnetPlugin.private_torrent=<\u00f6zel torrent> MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.searching=ara\u015ft\u0131r\u0131l\u0131yor... MagnetPlugin.report.found=%1 bulundu MagnetPlugin.report.alive=%1 canl\u0131 MagnetPlugin.report.dead=%1 \u00f6l\u00fc MagnetPlugin.report.downloading=indirilen yer: %1 MagnetPlugin.report.error=hata %1 MagnetURLHandler.report.no_sources=torrent i\u00e7in hi\u00e7 kaynak bulunamad\u0131 MagnetURLHandler.report.torrent_size=torrent b\u00fcy\u00fckl\u00fc\u011f\u00fc: %1 MagnetURLHandler.report.percent=tamamland\u0131: %1% MagnetURLHandler.report.error=hata %1 ConfigView.section.transfer.autospeed.enabledebug=Hata ay\u0131klama bilgisini g\u00fcnl\u00fc\u011fe kaydet TableColumn.header.date_added=Eklenme Tarihi TableColumn.header.date_added.info=Torrentin listeye eklenme tarihi ConfigView.section.file.hashchecking.smallestfirst=K\u00fc\u00e7\u00fck indirmeleri ilk \u00f6nce tekrar denetle platform.win32.baddll.nvappfilter=NVidia G\u00fcvenlik Duvar\u0131 platform.win32.baddll.netdog=Armor2net Ki\u015fisel G\u00fcvenlik Duvar\u0131 platform.win32.baddll.sarah=FRITZ! Uygulama Katman\u0131 G\u00fcvenlik Duvar\u0131 upnp.ignorebaddevices.reset.action=S\u0131f\u0131rla TorrentOptionsView.param.max.uploads.when.busy=Toplam s\u0131n\u0131ra ula\u015f\u0131ld\u0131\u011f\u0131nda KB/s olarak en y\u00fcksek g\u00f6nderme h\u0131z\u0131 [0: etkisiz] FileView.BlockView.title=Dosya Par\u00e7alar\u0131 FileView.BlockView.Done=Bitmi\u015f FileView.BlockView.Skipped=Atlanm\u0131\u015f FileView.BlockView.Active=Etkin FileView.BlockView.Outstanding=\u00d6nemli ConfigView.label.tcplistenport=Gelen TCP Ba\u011flant\u0131 Noktas\u0131 ConfigView.label.udplistenport=UDP Dinleme Ba\u011flant\u0131 Noktas\u0131 ConfigView.section.proxy.username.info=Hi\u00e7biri tan\u0131mlanmam\u0131\u015f dahi olsa, e\u011fer vekil sunucu kimlik denetimi talep ederse, kullan\u0131c\u0131 ad\u0131 olarak "" dizgisini kullan\u0131n MainWindow.menu.help.debug=Hata Ay\u0131klama Bilgisi Olu\u015ftur DownloadManager.error.badsize=Yanl\u0131\u015f B\u00fcy\u00fckl\u00fck ConfigView.section.tracker.host.addurls=Torrentlerin i\u00e7erdi\u011fi adresin denetimi ConfigView.filter=ay\u0131klanacak metni girin ConfigView.section.files.move=Dosya Ta\u015f\u0131ma ConfigView.section.file.defaultdir.section=Varsay\u0131lan Dizin Se\u00e7enekleri ConfigView.section.file.defaultdir.auto=Otomatik olarak varsay\u0131lan dizine indir (Uyarmaks\u0131z\u0131n) ConfigView.section.file.defaultdir.bestguess=Varsay\u0131lan dizin se\u00e7ilirken en iyi tahmini kullan ConfigView.section.file.defaultdir.ask=Varsay\u0131lan Dizin: ConfigView.section.file.defaultdir.lastused=Varsay\u0131lan dizini, kaydedilen son dizin olacak \u015fekilde g\u00fcncelle\u015ftir ConfigView.section.torrent.decoding=Karakter D\u00fczeni Ayr\u0131\u015ft\u0131rma ConfigView.section.logging.udptransport=\u00c7ok ayr\u0131nt\u0131l\u0131 UDP ta\u015f\u0131ma izi TorrentOptionsView.param.reset.to.default=Se\u00e7enekleri, \u00f6ntan\u0131ml\u0131 de\u011ferlerine geri getir TorrentOptionsView.param.reset.button=S\u0131f\u0131rla natpmp.routeraddress=\u0130stasy\u0131n adresi [bo\u015f: otomatik] ConfigView.section.style.disableAlertSliding=A\u00e7\u0131l\u0131r uyar\u0131lar\u0131 en \u00fcstte kayd\u0131rmay\u0131 devre d\u0131\u015f\u0131 b\u0131rak ConfigView.section.transfer.autospeed.maxinc=%1 olarak saniyedeki en b\u00fcy\u00fck art\u0131\u015f ConfigView.section.transfer.autospeed.maxdec=%1 olarak saniyedeki en b\u00fcy\u00fck d\u00fc\u015f\u00fc\u015f ConfigView.section.transfer.autospeed.enabledownadj=\u0130ndirme h\u0131z\u0131 ayarlamas\u0131n\u0131 etkinle\u015ftir ConfigView.section.transfer.autospeed.downadjratio=\u0130ndirme : G\u00f6nderme h\u0131z oran\u0131 ConfigView.section.transfer.autospeed.latencyfactor=H\u0131z de\u011fi\u015fikliklerine ba\u011flant\u0131 gecikme de\u011fi\u015fikli\u011fi etkeni ConfigView.section.transfer.autospeed.reset=Geli\u015fmi\u015f de\u011ferleri s\u0131f\u0131rla ConfigView.section.transfer.autospeed.reset.button=S\u0131f\u0131rla PeersView.incomingreqcount=Gelen \u0130stekler PeersView.incomingreqcount.info=E\u015f taraf\u0131ndan yap\u0131lan gelen istek say\u0131s\u0131 PeersView.outgoingreqcount=Giden \u0130stekler PeersView.outgoingreqcount.info=E\u015fe yap\u0131lan giden istek say\u0131s\u0131 upnp.mapping.trackerclientudp=UDP \u0130zleyici \u0130stemci Ba\u011flant\u0131 Noktas\u0131 upnp.mapping.dhtudp=Da\u011f\u0131t\u0131ml\u0131 Veritaban\u0131 ConfigView.section.connection.nondata.udp.same=Da\u011f\u0131t\u0131ml\u0131 veritaban\u0131 ve UDP izleyici i\u00e7in ayn\u0131 ba\u011flant\u0131 noktas\u0131n\u0131 kullan ConfigView.section.connection.tcp.enable=TCP Etkin ConfigView.section.connection.udp.enable=UDP Etkin ConfigView.section.style.showiconbar=Ara\u00e7 \u00e7ubu\u011funu g\u00f6ster MainWindow.menu.view.iconbar=Ara\u00e7 \u00c7ubu\u011fu MyTorrentsView.menu.rename=Ad De\u011fi\u015ftir MyTorrentsView.menu.rename.displayed=G\u00f6r\u00fcnen Ad\u0131 De\u011fi\u015ftir MyTorrentsView.menu.rename.save_path=Kay\u0131t Yolunu De\u011fi\u015ftir UIDebugGenerator.messageask.title=Hata Ay\u0131klama Bilgisi Olu\u015fturucu UIDebugGenerator.messageask.text=Rapor etmek istedi\u011finiz hata i\u00e7in bir tan\u0131mlama girin UIDebugGenerator.complete.title=Hata Ay\u0131klama Bilgisi Olu\u015fturma Tamamland\u0131 UIDebugGenerator.complete.text=L\u00fctfen '%1' dosyas\u0131n\u0131.\n\nBu dosyay\u0131 g\u00f6rebilece\u011finiz bir pencere a\u00e7mak i\u00e7in Tamam butonuna t\u0131klay\u0131n. ConfigView.section.style.showProgramIcon=Ad s\u00fctununda program simgesini g\u00f6ster ConfigView.section.style.showProgramIcon.tooltip=De\u011fi\u015fikliklerin etkin olabilmesi i\u00e7in yeniden ba\u015flatma gerekebilir authenticator.savepassword=Parolalar\u0131m\u0131 kaydet ConfigView.section.security.clearpasswords=Kaydedilmi\u015f parolalar\u0131 s\u0131f\u0131rla ConfigView.section.security.clearpasswords.button=S\u0131f\u0131rla Content.alert.notuploaded.title=G\u00f6nderme \u0130\u015flemi Tamamlanmad\u0131 Content.alert.notuploaded.text=%1' dosyas\u0131n\u0131n g\u00f6nderilmesi tamamlanmad\u0131. If you %2 now, people will not be able to completely download your published work.\n\nAre you sure you want to %2? Content.alert.notuploaded.multi.title=G\u00f6nderme \u0130\u015flemleri Tamamlanmad\u0131 Content.alert.notuploaded.stop=Dur Content.alert.notuploaded.quit=Vuze u kapat TorrentInfoView.torrent.encoding=Torrent \u00e7\u00f6z\u00fcmleme TorrentInfoView.columns='Torrentlerim' Penceresi S\u00fctunlar\u0131 progress.window.title=\u0130\u015flem Y\u00fcr\u00fct\u00fcl\u00fcyor progress.window.msg.filemove=L\u00fctfen, dosya ta\u015f\u0131ma/ad de\u011fi\u015ftirme tamamlan\u0131rken bekleyin ConfigView.label.popup.timestamp=A\u00e7\u0131l\u0131r uyar\u0131lara zaman damgas\u0131 ekle ConfigView.label.popup.autohide=Hata bildirmeyen uyar\u0131lar\u0131 \u015fu s\u00fcreden sonra otomatik gizle: ConfigView.label.please.visit.here=L\u00fctfen ayr\u0131nt\u0131lar i\u00e7in buray\u0131 ziyaret edin ConfigView.section.ipfilter.enable.descriptionCache=IP tan\u0131mlar\u0131n\u0131 ge\u00e7ici k\u00fct\u00fckte sakla ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Devre d\u0131\u015f\u0131 oldu\u011funda tan\u0131mlar hat\u0131rlanmaz # Used for peers which we can't determine. PeerSocket.unknown=Bilinmiyor ConfigView.label.announceport=\u0130zleyici duyuru ba\u011flant\u0131 noktas\u0131n\u0131 ge\u00e7ersiz k\u0131l iconBar.queue.tooltip=S\u0131ra MainWindow.menu.help.faq=S\u0131k\u00e7a Sorulan Sorular #what you've watched? Discover more with a single click... MainWindow.menu.help.donate=Ba\u011f\u0131\u015f Yap azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_th_TH.properties0000644000175000017500000066463411301156004026120 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 .torrent Main.parameter.usage=\u0e43\u0e0a\u0e49 : java org.gudy.azureus2.cl.Main [parameters] "file.torrent" "save path" Main.parameter.maxUploads=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e43\u0e19\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14 Main.parameter.maxSpeed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e40\u0e1b\u0e47\u0e19 bytes/\u0e27\u0e34 MainWindow.menu.file=&\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 MainWindow.menu.file.open=&\u0e40\u0e1b\u0e34\u0e14 MainWindow.menu.file.create=&\u0e2a\u0e23\u0e49\u0e32\u0e07 Torrent MainWindow.menu.file.create.fromfile=\u0e08\u0e32\u0e01&\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 MainWindow.menu.file.create.fromdir=\u0e08\u0e32\u0e01&\u0e17\u0e35\u0e48 MainWindow.menu.file.export=\u0e19\u0e33\u0e2d\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Torrent \u0e41\u0e1a\u0e1a &XML... MainWindow.menu.file.import=\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Torrent \u0e41\u0e1a\u0e1a &XML... MainWindow.menu.file.closetab=\u0e1b\u0e34\u0e14 &Tab MainWindow.menu.file.closewindow=\u0e1b\u0e34\u0e14 &Window MainWindow.menu.file.exit=\u0e2d&\u0e2d\u0e01 MainWindow.dialog.choose.file=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 torrent MainWindow.menu.file.folder=&\u0e41\u0e1f\u0e49\u0e21 MainWindow.dialog.choose.folder=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e17\u0e35\u0e48\u0e21\u0e35\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 torrent MainWindow.menu.view=&\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a MainWindow.menu.view.show=\u0e41\u0e2a\u0e14\u0e07 MainWindow.menu.view.mytorrents=&Torrents \u0e02\u0e2d\u0e07\u0e09\u0e31\u0e19 MainWindow.menu.view.configuration=&\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07 MainWindow.menu.view.console=\u0e04&\u0e2d\u0e19\u0e42\u0e0b\u0e25 MainWindow.menu.view.irc=&Irc MainWindow.menu.closealldetails=\u0e1b\u0e34\u0e14 &\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 MainWindow.menu.closealldownloadbars=\u0e1b\u0e34\u0e14\u0e41\u0e16\u0e1a\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 &\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 MainWindow.menu.language=&\u0e20\u0e32\u0e29\u0e32 ConfigView.section.language=\u0e20\u0e32\u0e29\u0e32 MainWindow.menu.window.minimize=&\u0e22\u0e48\u0e2d\u0e02\u0e19\u0e32\u0e14 MainWindow.menu.window.zoom=&\u0e02\u0e22\u0e32\u0e22 MainWindow.menu.window.alltofront=\u0e40\u0e2d\u0e32\u0e02\u0e36\u0e49\u0e19\u0e2b\u0e19\u0e49\u0e32 &\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 MainWindow.menu.help=&\u0e0a\u0e48\u0e27\u0e22\u0e40\u0e2b\u0e25\u0e37\u0e2d MainWindow.menu.help.about=\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a Vuze MainWindow.about.title=\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a MainWindow.about.section.developers=\u0e1c\u0e39\u0e49\u0e1e\u0e31\u0e12\u0e19\u0e32 MainWindow.about.section.translators=\u0e1c\u0e39\u0e49\u0e41\u0e1b\u0e25 MainWindow.about.section.internet=\u0e2d\u0e34\u0e19\u0e40\u0e15\u0e2d\u0e40\u0e19\u0e47\u0e15 MainWindow.about.internet.homepage=Homepage \u0e02\u0e2d\u0e07 Vuze MainWindow.about.internet.sourceforge=\u0e2b\u0e19\u0e49\u0e32\u0e42\u0e04\u0e23\u0e07\u0e01\u0e32\u0e23\u0e02\u0e2d\u0e07 Sourceforge MainWindow.about.internet.sourceforgedownloads=\u0e2b\u0e19\u0e49\u0e32\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e02\u0e2d\u0e07 Sourceforge MainWindow.about.internet.bugreports=\u0e41\u0e08\u0e49\u0e07\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 MainWindow.about.internet.forumdiscussion=\u0e2d\u0e20\u0e34\u0e1b\u0e23\u0e32\u0e22 MainWindow.about.internet.wiki=Wiki \u0e04\u0e33\u0e16\u0e32\u0e21\u0e17\u0e35\u0e48\u0e16\u0e39\u0e01\u0e16\u0e32\u0e21\u0e1a\u0e48\u0e2d\u0e22\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a Vuze MainWindow.dialog.choose.savepath=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e17\u0e35\u0e48\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 MainWindow.dialog.choose.savepath_forallfiles=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e17\u0e38\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 MainWindow.status.latestversion=\u0e43\u0e2b\u0e21\u0e48\u0e2a\u0e38\u0e14 MainWindow.status.latestversion.clickupdate=\u0e04\u0e25\u0e34\u0e01\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 MainWindow.status.unknown=\u0e44\u0e21\u0e48\u0e23\u0e39\u0e49 MainWindow.status.checking=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a MyTorrentsView.mytorrents=Torrents \u0e02\u0e2d\u0e07\u0e09\u0e31\u0e19 TableColumn.header.name=\u0e0a\u0e37\u0e48\u0e2d TableColumn.header.size=\u0e02\u0e19\u0e32\u0e14 TableColumn.header.done=\u0e40\u0e2a\u0e23\u0e47\u0e08 TableColumn.header.done.info=\u0e40\u0e1b\u0e2d\u0e23\u0e4c\u0e40\u0e0b\u0e47\u0e19\u0e17\u0e35\u0e48\u0e2a\u0e33\u0e40\u0e23\u0e47\u0e08\u0e43\u0e19\u0e07\u0e32\u0e19\u0e1b\u0e31\u0e08\u0e08\u0e38\u0e1a\u0e31\u0e19 TableColumn.header.status=\u0e2a\u0e16\u0e32\u0e19\u0e30 TableColumn.header.status.info=torrent \u0e01\u0e33\u0e25\u0e31\u0e07\u0e17\u0e33\u0e2d\u0e30\u0e44\u0e23 TableColumn.header.seeds.info=# seeds \u0e17\u0e35\u0e48\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e14\u0e49\u0e27\u0e22 (# seeds \u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14) TableColumn.header.peers.info=# peers \u0e17\u0e35\u0e48\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d (# peers \u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14) TableColumn.header.downspeed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 TableColumn.header.upspeed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14 TableColumn.header.eta=\u0e40\u0e27\u0e25\u0e32\u0e1b\u0e23\u0e30\u0e21\u0e32\u0e13 TableColumn.header.tracker=Tracker TableColumn.header.tracker.info=\u0e2a\u0e16\u0e32\u0e19\u0e30\u0e02\u0e2d\u0e07 tracker TableColumn.header.trackernextaccess=\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32 Tracker \u0e04\u0e23\u0e31\u0e49\u0e07\u0e2b\u0e19\u0e49\u0e32 TableColumn.header.trackernextaccess.info=\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e44\u0e2b\u0e23\u0e48\u0e17\u0e35\u0e48\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32 tracker \u0e04\u0e23\u0e31\u0e49\u0e07\u0e2b\u0e19\u0e49\u0e32\u0e08\u0e30\u0e40\u0e01\u0e34\u0e14 TableColumn.header.priority=\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d TableColumn.header.priority.info=\u0e08\u0e33\u0e19\u0e27\u0e19 bandwidth \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e17\u0e35\u0e48\u0e43\u0e2b\u0e49\u0e15\u0e48\u0e2d torrent MyTorrentsView.menu.showdetails=\u0e41\u0e2a\u0e14\u0e07 &\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 MyTorrentsView.menu.showdownloadbar=\u0e41\u0e2a\u0e14\u0e07\u0e41\u0e16\u0e1a\u0e14\u0e32\u0e27 &\u0e42\u0e2b\u0e25\u0e14 MyTorrentsView.menu.open=&\u0e40\u0e1b\u0e34\u0e14 MyTorrentsView.menu.setpriority=\u0e15\u0e31\u0e49\u0e07 &\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d MyTorrentsView.menu.setpriority.high=&\u0e2a\u0e39\u0e07 MyTorrentsView.menu.setpriority.low=&\u0e15\u0e33 MyTorrentsView.menu.start=&\u0e40\u0e23\u0e34\u0e48\u0e21 MyTorrentsView.menu.stop=\u0e2b\u0e22\u0e38&\u0e14 MyTorrentsView.menu.remove=&\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01 MyTorrentsView.menu.changeTracker=&\u0e40\u0e1e\u0e34\u0e48\u0e21 Tracker URL TrayWindow.menu.exit=\u0e2d&\u0e2d\u0e01 TrayWindow.menu.show=&\u0e41\u0e2a\u0e14\u0e07 Vuze SystemTray.menu.exit=\u0e2d&\u0e2d\u0e01 SystemTray.menu.closealldownloadbars=\u0e1b\u0e34\u0e14&\u0e41\u0e16\u0e1a\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 SystemTray.menu.show=&\u0e41\u0e2a\u0e14\u0e07 Vuze PeersView.ip.info=IP \u0e02\u0e2d\u0e07 peer PeersView.port=\u0e1e\u0e2d\u0e23\u0e4c\u0e15 PeersView.port.info=\u0e1e\u0e2d\u0e23\u0e4c\u0e15\u0e01\u0e33\u0e25\u0e31\u0e07\u0e16\u0e39\u0e01\u0e43\u0e0a\u0e49 PeersView.T.info=l (\u0e17\u0e49\u0e2d\u0e07\u0e16\u0e34\u0e48\u0e19): \u0e04\u0e38\u0e13\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d, r (\u0e17\u0e32\u0e07\u0e44\u0e01\u0e25): peer \u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d PeersView.T.L.tooltip=\u0e04\u0e38\u0e13\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d PeersView.T.R.tooltip=peer \u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d PeersView.I1=I (\u0e2a\u0e19\u0e42\u0e14\u0e22 peer) PeersView.I1.info=\u0e04\u0e38\u0e13\u0e2a\u0e19\u0e43\u0e19\u0e2a\u0e34\u0e48\u0e07\u0e17\u0e35\u0e48 peer \u0e2d\u0e37\u0e48\u0e19\u0e21\u0e35\u0e2b\u0e23\u0e37\u0e2d\u0e44\u0e21\u0e48 \u0e26 PeersView.C1=C (\u0e15\u0e31\u0e19\u0e42\u0e14\u0e22 peer) PeersView.C1.info=\u0e23\u0e27\u0e21 peer \u0e17\u0e35\u0e48\u0e2b\u0e22\u0e38\u0e14\u0e04\u0e38\u0e13\u0e08\u0e32\u0e01\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 PeersView.pieces=\u0e2a\u0e48\u0e27\u0e19 PeersView.downloadspeed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 PeersView.download=\u0e14\u0e32\u0e27 PeersView.I2=I (\u0e2a\u0e19\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a peer) PeersView.I2.info=peer \u0e19\u0e31\u0e49\u0e19\u0e2a\u0e19\u0e43\u0e19\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e21\u0e35\u0e2b\u0e23\u0e37\u0e2d\u0e44\u0e21\u0e48 ? PeersView.C2=C (\u0e15\u0e31\u0e19\u0e42\u0e14\u0e22 peer) PeersView.C2.info=\u0e23\u0e27\u0e21 peer \u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e01\u0e31\u0e19\u0e08\u0e32\u0e01\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 PeersView.uploadspeed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14 PeersView.uploadspeed.info=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e44\u0e1b\u0e17\u0e35\u0e48 peer PeersView.upload=\u0e2d\u0e31\u0e1e PeersView.upload.info=\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e42\u0e14\u0e22\u0e23\u0e27\u0e21\u0e44\u0e1b\u0e17\u0e35\u0e48 peer PeersView.statup=\u0e2a\u0e15\u0e34\u0e16\u0e34\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14 PeersView.statup.info=\u0e04\u0e48\u0e32\u0e2a\u0e15\u0e34\u0e16\u0e34\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e42\u0e14\u0e22\u0e23\u0e27\u0e21\u0e43\u0e19\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e02\u0e2d\u0e07 peer PeersView.S.info=Snubbed: peer \u0e17\u0e35\u0e48\u0e16\u0e39\u0e01 "snubbed" \u0e40\u0e2d\u0e07, \u0e2b\u0e23\u0e37\u0e2d\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 (\u0e43\u0e19\u0e01\u0e32\u0e23\u0e44\u0e21\u0e48\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e43\u0e19\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e17\u0e35\u0e48\u0e2a\u0e39\u0e07\u0e1e\u0e2d) PeersView.downloadspeedoverall=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 PeersView.optunchoke=Opt. \u0e44\u0e21\u0e48\u0e15\u0e31\u0e19 PeersView.client=\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21 PeersView.client.info=\u0e1b\u0e23\u0e30\u0e40\u0e20\u0e17\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21 BT \u0e17\u0e35\u0e48 peer\u0e43\u0e0a\u0e49 PeersView.title.short=\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 PeersView.title.full=\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 ConfigView.section.files=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 ConfigView.label.usefastresume=\u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e15\u0e48\u0e2d\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e23\u0e27\u0e14\u0e40\u0e23\u0e47\u0e27 ConfigView.label.incrementalfile=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e02\u0e19\u0e32\u0e14 ConfigView.label.defaultsavepath=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e44\u0e1b\u0e17\u0e35\u0e48\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e1e\u0e37\u0e49\u0e19\u0e10\u0e32\u0e19 ConfigView.button.browse=\u0e04\u0e49\u0e19... ConfigView.dialog.choosedefaultsavepath=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e1e\u0e37\u0e49\u0e19\u0e10\u0e32\u0e19\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 ConfigView.section.server=Server ConfigView.section.global=\u0e17\u0e31\u0e48\u0e27\u0e44\u0e1b ConfigView.label.disconnetseed=\u0e15\u0e31\u0e14\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e01\u0e31\u0e1a seeds \u0e40\u0e21\u0e37\u0e48\u0e2d seeding ConfigView.label.switchpriority=\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e44\u0e1b\u0e17\u0e35\u0e48\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e19\u0e49\u0e2d\u0e22\u0e40\u0e21\u0e37\u0e48\u0e2d seeding ConfigView.label.maxdownloads=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e40\u0e27\u0e25\u0e32\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] ConfigView.label.maxdownloads.tooltip=\u0e04\u0e38\u0e13\u0e08\u0e30\u0e17\u0e33\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e44\u0e14\u0e49\u0e21\u0e32\u0e01\u0e17\u0e35\u0e48\u0e2a\u0e38\u0e14\u0e1e\u0e23\u0e49\u0e2d\u0e21\u0e01\u0e31\u0e19\u0e40\u0e17\u0e48\u0e32\u0e01\u0e31\u0e1a\u0e08\u0e33\u0e19\u0e27\u0e19\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e43\u0e2b\u0e49, \u0e42\u0e14\u0e22\u0e21\u0e35\u0e02\u0e49\u0e2d\u0e41\u0e21\u0e49\u0e27\u0e48\u0e32\ntorrent \u0e17\u0e35\u0e48\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e17\u0e35\u0e48\u0e15\u0e23\u0e07\u0e01\u0e31\u0e1a\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e43\u0e2b\u0e49\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 \u0e2d\u0e32\u0e08\u0e08\u0e30\u0e43\u0e0a\u0e49\u0e0a\u0e48\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e44\u0e14\u0e49\u0e16\u0e49\u0e32\u0e08\u0e33\u0e40\u0e1b\u0e47\u0e19 ConfigView.label.maxactivetorrents=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e02\u0e2d\u0e07 torrents \u0e17\u0e35\u0e48\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23\u0e2d\u0e22\u0e39\u0e48 [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14]\n - torrents \u0e43\u0e2b\u0e21\u0e48\u0e08\u0e30\u0e44\u0e21\u0e48\u0e40\u0e23\u0e34\u0e48\u0e21\u0e01\u0e49\u0e32\u0e04\u0e38\u0e13\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14/seeding \u0e21\u0e32\u0e01\u0e01\u0e27\u0e48\u0e32 ConfigView.label.priorityExtensions=\u0e43\u0e2b\u0e49\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e01\u0e31\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e15\u0e48\u0e2d\u0e17\u0e49\u0e32\u0e22\u0e14\u0e49\u0e27\u0e22\u0e2a\u0e01\u0e38\u0e25\u0e14\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34\n - \u0e15\u0e31\u0e27\u0e2d\u0e22\u0e48\u0e32\u0e07: .txt;.nfo;.jpg ConfigView.section.transfer=\u0e40\u0e04\u0e25\u0e37\u0e48\u0e2d\u0e19\u0e22\u0e49\u0e32\u0e22 ConfigView.label.maxuploads=\u0e04\u0e48\u0e32\u0e1e\u0e37\u0e49\u0e19\u0e10\u0e32\u0e19\u0e0a\u0e48\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e15\u0e48\u0e2d torrent ConfigView.label.maxuploadspeed=KB/s \u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e43\u0e19\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e42\u0e14\u0e22\u0e23\u0e27\u0e21 [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] ConfigView.label.saveresumeinterval=\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e01\u0e32\u0e23\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e15\u0e48\u0e2d\u0e17\u0e38\u0e01 ConfigView.unlimited=\u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14 ConfigView.section.display=\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25 ConfigView.label.opendetails=\u0e40\u0e1b\u0e34\u0e14\u0e41\u0e16\u0e1a\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 ConfigView.label.openbar=\u0e40\u0e1b\u0e34\u0e14\u0e41\u0e16\u0e1a\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 ConfigView.label.closetotray=\u0e1b\u0e34\u0e14\u0e22\u0e48\u0e2d\u0e44\u0e1b\u0e17\u0e35\u0e48 System Tray ConfigView.label.minimizetotray=\u0e40\u0e27\u0e25\u0e32\u0e22\u0e48\u0e2d \u0e22\u0e48\u0e2d\u0e44\u0e1b\u0e17\u0e35\u0e48 System Tray ConfigView.section.general=\u0e17\u0e31\u0e48\u0e27\u0e44\u0e1b ConfigView.section.start=\u0e40\u0e23\u0e34\u0e48\u0e21 ConfigView.label.showsplash=\u0e41\u0e2a\u0e14\u0e07\u0e2b\u0e19\u0e49\u0e32\u0e08\u0e2d\u0e40\u0e23\u0e34\u0e48\u0e21\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21 ConfigView.label.autoupdate=\u0e40\u0e1b\u0e34\u0e14\u0e2b\u0e19\u0e49\u0e32\u0e08\u0e2d\u0e2d\u0e31\u0e1e\u0e40\u0e01\u0e23\u0e14\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e1e\u0e1a\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e43\u0e2b\u0e21\u0e48 ConfigView.label.openconsole=\u0e40\u0e1b\u0e34\u0e14\u0e04\u0e2d\u0e19\u0e42\u0e0b\u0e25\u0e15\u0e2d\u0e19\u0e40\u0e23\u0e34\u0e48\u0e21 ConfigView.label.openconfig=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07\u0e15\u0e2d\u0e19\u0e40\u0e23\u0e34\u0e48\u0e21 ConfigView.label.startminimized=\u0e40\u0e23\u0e34\u0e48\u0e21\u0e41\u0e1a\u0e1a\u0e22\u0e48\u0e2d ConfigView.section.irc=Irc ConfigView.label.ircserver=\u0e40\u0e0b\u0e34\u0e1f\u0e40\u0e27\u0e2d\u0e23\u0e4c ConfigView.label.ircchannel=\u0e0a\u0e48\u0e2d\u0e07 ConfigView.label.irclogin=\u0e0a\u0e37\u0e48\u0e2d\u0e40\u0e25\u0e48\u0e19 ConfigView.section.security=\u0e23\u0e31\u0e01\u0e29\u0e32\u0e04\u0e27\u0e32\u0e21\u0e1b\u0e25\u0e2d\u0e14\u0e20\u0e31\u0e22 ConfigView.label.password=\u0e1b\u0e49\u0e2d\u0e07\u0e01\u0e31\u0e19 Vuze \u0e42\u0e14\u0e22\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19\n - \u0e16\u0e32\u0e21\u0e40\u0e21\u0e37\u0e48\u0e2d de-iconifying \u0e41\u0e25\u0e30\u0e15\u0e2d\u0e19\u0e40\u0e23\u0e34\u0e48\u0e21 ConfigView.label.passwordconfirm=\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19 (\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19) ConfigView.label.passwordmatch=\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19\u0e40\u0e1b\u0e34\u0e14\u0e43\u0e0a\u0e49 : ConfigView.label.passwordmatchnone=\u0e44\u0e21\u0e48 ConfigView.label.passwordmatchno=\u0e44\u0e21\u0e48 / \u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19\u0e44\u0e21\u0e48\u0e15\u0e23\u0e07\u0e01\u0e31\u0e19 ConfigView.label.passwordmatchyes=\u0e43\u0e0a\u0e48 ConfigView.button.save=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 ConfigView.title.short=\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07 ConfigView.title.full=\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07 ConsoleView.title.short=\u0e04\u0e2d\u0e19\u0e42\u0e0b\u0e25 ConsoleView.title.full=\u0e04\u0e2d\u0e19\u0e42\u0e0b\u0e25 FileItem.write=\u0e40\u0e02\u0e35\u0e22\u0e19 FileItem.read=\u0e2d\u0e48\u0e32\u0e19 FileItem.normal=\u0e1b\u0e01\u0e15\u0e34 FileItem.high=\u0e2a\u0e39\u0e07 FileItem.donotdownload=\u0e44\u0e21\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 FilesView.name=\u0e0a\u0e37\u0e48\u0e2d FilesView.size=\u0e02\u0e19\u0e32\u0e14 FilesView.done=\u0e40\u0e2a\u0e23\u0e47\u0e08 FilesView.firstpiece=\u0e2a\u0e48\u0e27\u0e19\u0e41\u0e23\u0e01 # FilesView.numberofpieces=# \u0e02\u0e2d\u0e07\u0e2a\u0e48\u0e27\u0e19 FilesView.pieces=\u0e2a\u0e48\u0e27\u0e19 FilesView.mode=\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a FilesView.priority=\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d FilesView.menu.open=&\u0e40\u0e1b\u0e34\u0e14 FilesView.menu.setpriority=&\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d FilesView.menu.setpriority.high=&\u0e2a\u0e39\u0e07 FilesView.menu.setpriority.normal=&\u0e1b\u0e01\u0e15\u0e34 FilesView.menu.setpriority.skipped=&\u0e44\u0e21\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 FilesView.title.short=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 FilesView.title.full=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 GeneralView.section.downloaded=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 GeneralView.label.status.file=\u0e2a\u0e16\u0e32\u0e19\u0e30\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 GeneralView.label.status.pieces=\u0e2a\u0e16\u0e32\u0e19\u0e30\u0e2a\u0e48\u0e27\u0e19 GeneralView.section.availability=\u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48 GeneralView.label.status.pieces_available=\u0e2a\u0e16\u0e32\u0e19\u0e30\u0e2a\u0e48\u0e27\u0e19 GeneralView.section.transfer=\u0e02\u0e19\u0e2a\u0e48\u0e07 GeneralView.section.info=\u0e02\u0e48\u0e32\u0e27\u0e2a\u0e32\u0e23 GeneralView.title.short=\u0e17\u0e31\u0e48\u0e27\u0e44\u0e1b GeneralView.title.full=\u0e17\u0e31\u0e48\u0e27\u0e44\u0e1b GeneralView.label.timeelapsed=\u0e40\u0e27\u0e25\u0e32\u0e1c\u0e48\u0e32\u0e19\u0e44\u0e1b : GeneralView.label.remaining=\u0e40\u0e2b\u0e25\u0e37\u0e2d: GeneralView.label.downloaded=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 : GeneralView.label.downloadspeed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14: GeneralView.label.maxuploads=\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 : GeneralView.label.maxuploads.tooltip=\u0e08\u0e33\u0e19\u0e27\u0e19 peers \u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e17\u0e35\u0e48\u0e08\u0e30 unchoked \u0e43\u0e19\u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48\u0e01\u0e33\u0e2b\u0e19\u0e14 GeneralView.label.uploaded=\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14 : GeneralView.label.uploadspeed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14 : GeneralView.label.totalspeed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e42\u0e14\u0e22\u0e23\u0e27\u0e21 : GeneralView.label.totalspeed.tooltip=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e02\u0e2d\u0e07 clients \u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e14\u0e49\u0e27\u0e22 GeneralView.label.averagespeed=\u0e04\u0e48\u0e32\u0e40\u0e09\u0e25\u0e35\u0e48\u0e22 GeneralView.label.filename=\u0e0a\u0e37\u0e48\u0e2d\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 : GeneralView.label.totalsize=\u0e02\u0e19\u0e32\u0e14\u0e42\u0e14\u0e22\u0e23\u0e27\u0e21 : GeneralView.label.savein=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e43\u0e19 : GeneralView.label.hash=\u0e2a\u0e48\u0e27\u0e19 : GeneralView.label.numberofpieces=# \u0e02\u0e2d\u0e07\u0e2a\u0e48\u0e27\u0e19 : GeneralView.label.size=\u0e02\u0e19\u0e32\u0e14 : GeneralView.label.tracker=\u0e2a\u0e16\u0e32\u0e19\u0e30 Tracker : GeneralView.label.updatein=\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e43\u0e19 : GeneralView.label.trackerurlupdate=\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 Tracker GeneralView.label.comment=\u0e04\u0e34\u0e14\u0e40\u0e2b\u0e47\u0e19 : ManagerItem.waiting=\u0e23\u0e2d ManagerItem.allocating=\u0e41\u0e1a\u0e48\u0e07 ManagerItem.checking=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a ManagerItem.ready=\u0e1e\u0e23\u0e49\u0e2d\u0e21 ManagerItem.downloading=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 ManagerItem.stopped=\u0e2b\u0e22\u0e38\u0e14\u0e41\u0e25\u0e49\u0e27 ManagerItem.error=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 ManagerItem.high=\u0e21\u0e32\u0e01 ManagerItem.low=\u0e19\u0e49\u0e2d\u0e22 MinimizedWindow.name=\u0e0a\u0e37\u0e48\u0e2d : PiecesView.size=\u0e02\u0e19\u0e32\u0e14 PiecesView.numberofblocks=# \u0e02\u0e2d\u0e07\u0e0a\u0e48\u0e27\u0e07 PiecesView.blocks=\u0e0a\u0e48\u0e27\u0e07 PiecesView.completed=\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19 PiecesView.availability=\u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48 PiecesView.reservedby=\u0e2a\u0e07\u0e27\u0e19 PiecesView.writers=\u0e01\u0e31\u0e19 Contributors PiecesView.title.short=\u0e2a\u0e48\u0e27\u0e19 PiecesView.title.full=\u0e2a\u0e48\u0e27\u0e19 SystemTray.tooltip.seeding=%1 seeding, SystemTray.tooltip.downloading=%1 downloading, DownloadManager.error.filenotfound=\u0e44\u0e21\u0e48\u0e1e\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 DownloadManager.error.fileempty=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Torrent \u0e27\u0e48\u0e32\u0e07\u0e40\u0e1b\u0e25\u0e48\u0e32 DownloadManager.error.filetoobig=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Torrent \u0e43\u0e2b\u0e0d\u0e48\u0e40\u0e01\u0e34\u0e19\u0e44\u0e1b DownloadManager.error.filewithouttorrentinfo=\u0e44\u0e21\u0e48\u0e21\u0e35\u0e1e\u0e1a\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 Torrent \u0e43\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 DownloadManager.error.unsupportedencoding=\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32\u0e23\u0e2b\u0e31\u0e2a\u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e2a\u0e19\u0e31\u0e1a\u0e2a\u0e19\u0e38\u0e19 DownloadManager.error.ioerror=IO \u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 DownloadManager.error.sha1=\u0e44\u0e21\u0e48\u0e21\u0e35\u0e0a\u0e38\u0e14\u0e04\u0e33\u0e2a\u0e31\u0e48\u0e07 (SHA1) \u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 PeerManager.status.offline=\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49 PeerManager.status.ok=\u0e15\u0e01\u0e25\u0e07 PeerManager.status.checking=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a PeerManager.status.finished=\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19 PeerManager.status.finishedin=\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19\u0e43\u0e19 MainWindow.upgrade.assistant=\u0e1c\u0e39\u0e49\u0e0a\u0e48\u0e27\u0e22\u0e2d\u0e31\u0e1e\u0e40\u0e01\u0e23\u0e14 MainWindow.upgrade.newerversion=\u0e21\u0e35 Vuze \u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e43\u0e2b\u0e21\u0e48\u0e1e\u0e23\u0e49\u0e2d\u0e21\u0e17\u0e35\u0e48\u0e08\u0e30\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 MainWindow.upgrade.explanation=\u0e1c\u0e39\u0e49\u0e0a\u0e48\u0e27\u0e22\u0e40\u0e2b\u0e25\u0e37\u0e2d\u0e19\u0e35\u0e49\u0e08\u0e30\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e43\u0e2b\u0e21\u0e48\u0e44\u0e1b\u0e17\u0e35\u0e48\u0e41\u0e1f\u0e49\u0e21 Vuze \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13 \u0e41\u0e25\u0e30\u0e40\u0e23\u0e34\u0e48\u0e21 Vuze \u0e43\u0e2b\u0e21\u0e48 MainWindow.upgrade.explanation.manual=\u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e14\u0e49\u0e27\u0e22\u0e15\u0e19\u0e40\u0e2d\u0e07 \u0e42\u0e14\u0e22\u0e01\u0e32\u0e23\u0e1b\u0e34\u0e14 Vuze \u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e43\u0e2b\u0e21\u0e48 \u0e41\u0e25\u0e30\u0e40\u0e23\u0e34\u0e48\u0e21 Vuze \u0e43\u0e2b\u0e21\u0e48 MainWindow.upgrade.step1=\u0e02\u0e31\u0e49\u0e19 1: \u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e43\u0e2b\u0e21\u0e48 MainWindow.upgrade.step2=\u0e02\u0e31\u0e49\u0e19 2: \u0e1b\u0e34\u0e14\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e19\u0e35\u0e49 \u0e41\u0e25\u0e30\u0e40\u0e23\u0e34\u0e48\u0e21 Vuze \u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e43\u0e2b\u0e21\u0e48 MainWindow.upgrade.hint1=\u0e43\u0e1a\u0e49:\t\u0e01\u0e14\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19\u0e08\u0e30\u0e17\u0e33\u0e17\u0e38\u0e01\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 MainWindow.upgrade.hint2=\u0e43\u0e1a\u0e49:\tI\u0e16\u0e49\u0e32\u0e04\u0e38\u0e13\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e1b\u0e34\u0e14 Vuze \u0e20\u0e32\u0e22\u0e2b\u0e25\u0e31\u0e07, \u0e01\u0e14\u0e1b\u0e0f\u0e34\u0e40\u0e2a\u0e18\n\tr\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e0a\u0e37\u0e48\u0e2d Azureus2-new.jar \u0e40\u0e1b\u0e47\u0e19 Azureus2.jar \u0e01\u0e48\u0e2d\u0e19\u0e1b\u0e34\u0e14 MainWindow.upgrade.error.downloading.hint=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14:\t\u0e44\u0e21\u0e48\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e43\u0e2b\u0e21\u0e48\u0e44\u0e14\u0e49, \u0e42\u0e1b\u0e23\u0e14\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e14\u0e49\u0e27\u0e22\u0e15\u0e19\u0e40\u0e2d\u0e07 MainWindow.upgrade.section.info=\u0e21\u0e35\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e43\u0e2b\u0e21\u0e48 MainWindow.upgrade.section.manual=\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e40\u0e2d\u0e07 MainWindow.upgrade.section.automatic=\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 MainWindow.upgrade.tooltip.progressbar=\u0e04\u0e27\u0e32\u0e21\u0e01\u0e49\u0e32\u0e27\u0e2b\u0e19\u0e49\u0e32\u0e43\u0e19\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e41\u0e2a\u0e14\u0e07\u0e17\u0e35\u0e48\u0e19\u0e35\u0e48 Button.next=\u0e15\u0e48\u0e2d\u0e44\u0e1b Button.finish=\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19 Button.cancel=\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01 LocaleUtil.title=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32\u0e23\u0e2b\u0e31\u0e2a LocaleUtil.section.chooseencoding=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32\u0e23\u0e2b\u0e31\u0e2a\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e0a\u0e37\u0e48\u0e2d\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 LocaleUtil.label.chooseencoding=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32\u0e23\u0e2b\u0e31\u0e2a\u0e17\u0e35\u0e48\u0e15\u0e23\u0e07\u0e17\u0e35\u0e48\u0e2a\u0e38\u0e14 LocaleUtil.label.hint.doubleclick=\u0e43\u0e1a\u0e49: \u0e14\u0e31\u0e1a\u0e40\u0e1a\u0e34\u0e49\u0e25\u0e04\u0e25\u0e34\u0e01\u0e1a\u0e19\u0e41\u0e16\u0e27 \u0e40\u0e1b\u0e47\u0e19\u0e01\u0e32\u0e23\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32\u0e23\u0e2b\u0e31\u0e2a \u0e41\u0e25\u0e30\u0e1b\u0e34\u0e14\u0e01\u0e25\u0e48\u0e2d\u0e07\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21 LocaleUtil.label.checkbox.rememberdecision=\u0e08\u0e33\u0e01\u0e32\u0e23\u0e15\u0e31\u0e14\u0e2a\u0e34\u0e19\u0e43\u0e08\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e0a\u0e37\u0e48\u0e2d\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e40\u0e2b\u0e25\u0e37\u0e2d LocaleUtil.column.encoding=\u0e40\u0e02\u0e49\u0e32\u0e23\u0e2b\u0e31\u0e2a IrcClient.copyright=\u0e43\u0e0a\u0e49 PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e44\u0e1b\u0e17\u0e35\u0e48 IrcClient.connected=\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e44\u0e1b\u0e17\u0e35\u0e48 IrcClient.joining=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e40\u0e02\u0e49\u0e32\u0e23\u0e48\u0e27\u0e21 IrcClient.channel=\u0e0a\u0e48\u0e2d\u0e07 IrcClient.joined=\u0e40\u0e02\u0e49\u0e32\u0e23\u0e48\u0e27\u0e21\u0e41\u0e25\u0e49\u0e27 IrcClient.error=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 IrcClient.hasjoined=\u0e44\u0e14\u0e49\u0e40\u0e02\u0e49\u0e32\u0e23\u0e48\u0e27\u0e21 IrcClient.haskicked=\u0e16\u0e39\u0e01\u0e40\u0e15\u0e30 IrcClient.hasleft=\u0e44\u0e14\u0e49\u0e2d\u0e2d\u0e01 IrcClient.nowknown=\u0e44\u0e14\u0e49\u0e23\u0e39\u0e49\u0e08\u0e31\u0e01\u0e43\u0e19\u0e0a\u0e37\u0e48\u0e2d IrcClient.topicforchannel=\u0e2b\u0e31\u0e27\u0e02\u0e49\u0e2d\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e0a\u0e48\u0e2d\u0e07 IrcClient.disconnected=\u0e15\u0e31\u0e14\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e08\u0e32\u0e01 IrcClient.noNick=\u0e44\u0e21\u0e48\u0e21\u0e35\u0e0a\u0e37\u0e48\u0e2d\u0e40\u0e25\u0e48\u0e19\u0e23\u0e30\u0e1a\u0e38. \u0e42\u0e1b\u0e23\u0e14\u0e44\u0e1b\u0e17\u0e35\u0e48 '\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07' IrcView.actionnotsupported=\u0e01\u0e32\u0e23\u0e01\u0e23\u0e30\u0e17\u0e33\u0e19\u0e35\u0e49\u0e44\u0e21\u0e48\u0e2a\u0e19\u0e31\u0e1a\u0e2a\u0e19\u0e38\u0e19 IrcView.clientsconnected=\u0e1c\u0e39\u0e49\u0e43\u0e0a\u0e49 IrcView.privateto=\u0e44\u0e1b IrcView.privatefrom=\u0e08\u0e32\u0e01 IrcView.noticefrom=\u0e2a\u0e31\u0e07\u0e40\u0e01\u0e15 : IrcView.errormsg=Syntax \u0e1c\u0e34\u0e14\u0e1a\u0e19 /msg : /msg user text IrcView.help=\u0e04\u0e33\u0e2a\u0e31\u0e48\u0e07\u0e17\u0e35\u0e48\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07\u0e04\u0e37\u0e2d :\n . /help : \u0e41\u0e2a\u0e14\u0e07\u0e2b\u0e19\u0e49\u0e32\u0e08\u0e2d\u0e19\u0e35\u0e49\n . /nick | /name : \u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e0a\u0e37\u0e48\u0e2d\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13 \n . /me action : \u0e2a\u0e48\u0e07\u0e01\u0e32\u0e23\u0e01\u0e23\u0e30\u0e17\u0e33 \n . /msg nick message : \u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e48\u0e27\u0e19\u0e15\u0e31\u0e27\u0e43\u0e2b\u0e49 \n . /r message : \u0e15\u0e2d\u0e1a\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e48\u0e27\u0e19\u0e15\u0e31\u0e27\u0e25\u0e48\u0e32\u0e2a\u0e38\u0e14\n . /join #channel : \u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e0a\u0e48\u0e2d\u0e07 PasswordWindow.title=Vuze \u0e16\u0e39\u0e01\u0e25\u0e47\u0e2d\u0e01 PasswordWindow.passwordprotected=Vuze \u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e1b\u0e49\u0e2d\u0e07\u0e01\u0e31\u0e19\u0e08\u0e32\u0e01\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19\n\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e17\u0e35\u0e48\u0e08\u0e30\u0e41\u0e2a\u0e14\u0e07\u0e2b\u0e19\u0e49\u0e32\u0e15\u0e48\u0e32\u0e07 Vuze \u0e42\u0e1b\u0e23\u0e14\u0e43\u0e2a\u0e48\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e17\u0e35\u0e48\u0e19\u0e35\u0e48 : Button.ok=\u0e15\u0e01\u0e25\u0e07 TrackerChangerWindow.title=\u0e40\u0e1e\u0e34\u0e48\u0e21 Tracker TrackerChangerWindow.newtracker=\u0e43\u0e2a\u0e48 tracker url \u0e43\u0e2b\u0e21\u0e48 PeersView.discarded=\u0e25\u0e30\u0e17\u0e34\u0e49\u0e07 PeersView.discarded.info=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e41\u0e21\u0e49\u0e44\u0e21\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23, \u0e04\u0e38\u0e13\u0e40\u0e2d\u0e32\u0e21\u0e31\u0e19\u0e2d\u0e2d\u0e01 discarded=\u0e17\u0e34\u0e49\u0e07 MyTorrentsView.menu.move=&\u0e40\u0e04\u0e25\u0e37\u0e48\u0e2d\u0e19 MyTorrentsView.menu.moveUp=&\u0e02\u0e36\u0e49\u0e19 MyTorrentsView.menu.moveDown=&\u0e25\u0e48\u0e32\u0e07 GeneralView.label.hashfails=\u0e2a\u0e48\u0e27\u0e19\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27 : GeneralView.label.shareRatio=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 : ConfigView.section.downloadManagement=\u0e1a\u0e23\u0e34\u0e2b\u0e32\u0e23\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 ConfigView.label.startRatioPeers=\u0e40\u0e23\u0e34\u0e48\u0e21 seeding \u0e40\u0e21\u0e37\u0e48\u0e2d\u0e21\u0e35 seed \u0e19\u0e49\u0e2d\u0e22\u0e01\u0e27\u0e48\u0e32 1 \u0e40\u0e21\u0e37\u0e48\u0e2d ConfigView.text.neverStop=\u0e44\u0e21\u0e48\u0e2b\u0e22\u0e38\u0e14 ConfigView.text.neverStart=\u0e44\u0e21\u0e48\u0e40\u0e23\u0e34\u0e48\u0e21 ConfigView.label.checkOncompletion=\u0e40\u0e0a\u0e47\u0e04\u0e2a\u0e48\u0e27\u0e19\u0e0b\u0e33\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e2a\u0e23\u0e47\u0e08 wizard.title=\u0e2a\u0e23\u0e49\u0e32\u0e07 torrent wizard.previous=< \u0e22\u0e49\u0e2d\u0e19\u0e01\u0e25\u0e31\u0e1a wizard.next=\u0e15\u0e48\u0e2d\u0e44\u0e1b > wizard.finish=\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19 wizard.mode=Tracker / \u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a wizard.invalidurl=URL \u0e19\u0e35\u0e49\u0e44\u0e21\u0e48\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07 wizard.singlefile=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e14\u0e35\u0e48\u0e22\u0e27 wizard.singlefile.help=\u0e2a\u0e23\u0e49\u0e32\u0e07 torrent \u0e08\u0e32\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e14\u0e35\u0e48\u0e22\u0e27 wizard.directory=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 wizard.directory.help=\u0e2a\u0e23\u0e49\u0e32\u0e07 torrent \u0e08\u0e32\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 wizard.choosefile=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 wizard.file=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 : wizard.browse=\u0e04\u0e49\u0e19\u0e2b\u0e32... wizard.choosedirectory=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 wizard.invalidfile=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e44\u0e21\u0e48\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07 ! wizard.invaliddirectory=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e44\u0e21\u0e48\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07 ! wizard.torrentFile=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Torrent wizard.choosetorrent=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 torrent \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e2a\u0e23\u0e49\u0e32\u0e07 wizard.information=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 wizard.notimplemented=\u0e22\u0e31\u0e07\u0e44\u0e21\u0e48\u0e40\u0e01\u0e34\u0e14\u0e1c\u0e25 wizard.progresstitle=\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Torrent wizard.savingfile=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25... wizard.filesaved=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 wizard.close=\u0e1b\u0e34\u0e14 Torrent.create.progress.piecelength=\u0e02\u0e19\u0e32\u0e14\u0e0a\u0e34\u0e49\u0e19: Torrent.create.progress.piececount=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e0a\u0e34\u0e49\u0e19: Torrent.create.progress.totalfilesize=\u0e02\u0e19\u0e32\u0e14\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14: Torrent.create.progress.totalfilecount=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14: Torrent.create.progress.parsingfiles=\u0e27\u0e34\u0e40\u0e04\u0e23\u0e32\u0e30\u0e2b\u0e4c\u0e2a\u0e48\u0e27\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Torrent.create.progress.hashing=\u0e41\u0e1a\u0e48\u0e07\u0e2a\u0e48\u0e27\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 MainWindow.upgrade.downloadingfrom=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e08\u0e32\u0e01 : MainWindow.menu.view.ipFilter=&\u0e01\u0e23\u0e2d\u0e07 Ip ConfigView.section.ipfilter=\u0e01\u0e23\u0e2d\u0e07 Ip ConfigView.section.ipfilter.description=\u0e2d\u0e18\u0e34\u0e1a\u0e32\u0e22 ConfigView.section.ipfilter.start=Ip \u0e40\u0e23\u0e34\u0e48\u0e21 ConfigView.section.ipfilter.end=Ip \u0e17\u0e49\u0e32\u0e22 ConfigView.section.ipfilter.add=\u0e40\u0e1e\u0e34\u0e48\u0e21 ConfigView.section.ipfilter.remove=\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01 ConfigView.section.ipfilter.edit=\u0e41\u0e01\u0e49\u0e44\u0e02 ConfigView.section.ipfilter.save=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 ConfigView.section.ipfilter.editFilter=\u0e41\u0e01\u0e49\u0e44\u0e02\u0e01\u0e32\u0e23\u0e01\u0e23\u0e2d\u0e07 ConfigView.section.ipfilter.enable=\u0e40\u0e1b\u0e34\u0e14\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19 PeersView.menu.close=&\u0e1b\u0e34\u0e14 seedmore.title=Torrent \u0e44\u0e21\u0e48\u0e44\u0e14\u0e49 seeded \u0e40\u0e1e\u0e35\u0e22\u0e07\u0e1e\u0e2d seedmore.shareratio=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e43\u0e19 torrent \u0e02\u0e2d\u0e07 seedmore.uploadmore=\u0e21\u0e35\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e15\u0e33\u0e01\u0e27\u0e48\u0e32 100% \u0e0b\u0e36\u0e48\u0e07\u0e44\u0e21\u0e48\u0e40\u0e1b\u0e47\u0e19\u0e1c\u0e25\u0e14\u0e35\u0e15\u0e48\u0e2d\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22 bittorrent\n\u0e04\u0e38\u0e13\u0e04\u0e27\u0e23\u0e43\u0e2b\u0e49 torrent seed \u0e2d\u0e35\u0e01\u0e2a\u0e31\u0e01\u0e23\u0e30\u0e22\u0e30\u0e2b\u0e19\u0e36\u0e48\u0e07\n\u0e04\u0e38\u0e13\u0e41\u0e19\u0e48\u0e43\u0e08\u0e2b\u0e23\u0e37\u0e2d\u0e27\u0e48\u0e32\u0e08\u0e30\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23\u0e15\u0e48\u0e2d ? ConfigView.label.showpopuponclose=\u0e41\u0e2a\u0e14\u0e07\u0e2b\u0e19\u0e49\u0e32\u0e15\u0e48\u0e32\u0e07\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e01\u0e32\u0e23\u0e2b\u0e22\u0e38\u0e14 seeding \u0e17\u0e35\u0e48\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e15\u0e33\u0e01\u0e27\u0e48\u0e32 1 ConfigView.label.startNumSeeds=\n\u0e40\u0e23\u0e34\u0e48\u0e21 seeding \u0e16\u0e49\u0e32\u0e15\u0e33\u0e01\u0e27\u0e48\u0e32\n - \u0e40\u0e02\u0e35\u0e22\u0e19\u0e17\u0e31\u0e1a\u0e01\u0e0e\u0e2d\u0e37\u0e48\u0e19\u0e46 MyTorrentsView.menu.removeand=\u0e40\u0e2d\u0e32&\u0e2d\u0e2d\u0e01 \u0e41\u0e25\u0e30 MyTorrentsView.menu.removeand.deletetorrent=\u0e25\u0e1a .&torrent MyTorrentsView.menu.removeand.deletedata=\u0e25\u0e1a &\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 MyTorrentsView.menu.removeand.deleteboth=\u0e25\u0e1a &\u0e17\u0e31\u0e49\u0e07\u0e04\u0e39\u0e48 deletedata.title=!!! \u0e04\u0e33\u0e40\u0e15\u0e37\u0e2d\u0e19 !!! deletedata.message1=\u0e04\u0e38\u0e13\u0e01\u0e33\u0e25\u0e31\u0e07\u0e08\u0e30\u0e25\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e08\u0e32\u0e01 :\n MainWindow.menu.file.configure=\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07 &\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 configureWizard.title=\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 configureWizard.welcome.title=\u0e22\u0e34\u0e19\u0e14\u0e35\u0e15\u0e49\u0e2d\u0e19\u0e23\u0e31\u0e1a\u0e2a\u0e39\u0e48\u0e23\u0e30\u0e1a\u0e1a\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34\u0e02\u0e2d\u0e07 Vuze configureWizard.welcome.message=\u0e23\u0e30\u0e1a\u0e1a\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34\u0e19\u0e35\u0e49\u0e08\u0e30\u0e0a\u0e48\u0e27\u0e22\u0e04\u0e38\u0e13\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07 Vuze \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e41\u0e1a\u0e1a\u0e1e\u0e37\u0e49\u0e19\u0e10\u0e32\u0e19.\u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e41\u0e01\u0e49\u0e44\u0e02\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14\u0e43\u0e19\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07 \u0e42\u0e14\u0e22\u0e44\u0e1b\u0e17\u0e35\u0e48 \u0e41\u0e2a\u0e14\u0e07>\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07 configureWizard.transfer.title=\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e01\u0e32\u0e23\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 \u0e41\u0e25\u0e30\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d configureWizard.transfer.hint=\u0e43\u0e1a\u0e49 : \u0e43\u0e0a\u0e49\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e15\u0e33\u0e01\u0e27\u0e48\u0e32\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e40\u0e25\u0e47\u0e01\u0e19\u0e49\u0e2d\u0e22\u0e40\u0e1b\u0e47\u0e19\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e17\u0e35\u0e48\u0e14\u0e35\u0e17\u0e35\u0e48\u0e2a\u0e38\u0e14 configureWizard.transfer.message=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e01\u0e32\u0e23\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e15\u0e48\u0e2d\u0e02\u0e49\u0e32\u0e07\u0e25\u0e48\u0e32\u0e07 \u0e02\u0e2d\u0e43\u0e2b\u0e49\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e17\u0e23\u0e32\u0e1a\u0e01\u0e31\u0e19\u0e27\u0e48\u0e32\u0e01\u0e32\u0e23\u0e44\u0e21\u0e48\u0e43\u0e2b\u0e49\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e43\u0e19\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e17\u0e35\u0e48\u0e40\u0e1e\u0e35\u0e22\u0e07\u0e1e\u0e2d \u0e08\u0e30\u0e17\u0e33\u0e43\u0e2b\u0e49\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e43\u0e19\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e0a\u0e49\u0e32\u0e25\u0e07 \u0e41\u0e25\u0e30\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e19\u0e31\u0e1a\u0e15\u0e48\u0e2d torrent \u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14,\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e24\u0e2b\u0e25\u0e32\u0e22\u0e46 torrents \u0e43\u0e19\u0e40\u0e27\u0e25\u0e32\u0e40\u0e14\u0e35\u0e22\u0e27\u0e01\u0e31\u0e19\u0e21\u0e35\u0e1c\u0e25\u0e43\u0e2b\u0e49\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e25\u0e14\u0e25\u0e07 \u0e40\u0e23\u0e32\u0e41\u0e19\u0e30\u0e19\u0e33\u0e43\u0e2b\u0e49\u0e43\u0e0a\u0e49 5KB/s \u0e15\u0e48\u0e2d torrent \u0e40\u0e1b\u0e47\u0e19\u0e02\u0e49\u0e2d\u0e1a\u0e31\u0e07\u0e04\u0e31\u0e1a\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e15\u0e33 \u0e22\u0e34\u0e48\u0e07\u0e04\u0e38\u0e13\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e23\u0e47\u0e27\u0e40\u0e17\u0e48\u0e32\u0e44\u0e23, \u0e04\u0e38\u0e13\u0e01\u0e47\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e23\u0e49\u0e27\u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19 (\u0e02\u0e36\u0e49\u0e19\u0e01\u0e31\u0e1a\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e02\u0e2d\u0e07 torrent) configureWizard.transfer.connection=\u0e01\u0e32\u0e23\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e15\u0e48\u0e2d configureWizard.transfer.connection.0=\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e40\u0e2d\u0e07 configureWizard.transfer.connection.1=\u0e42\u0e21\u0e40\u0e14\u0e47\u0e21 configureWizard.transfer.maxUpSpeed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e43\u0e19\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 (KB/s) configureWizard.transfer.maxActiveTorrents=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e01\u0e32\u0e23\u0e17\u0e33\u0e07\u0e32\u0e19\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 configureWizard.transfer.maxDownloads=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 configureWizard.transfer.maxUploadsPerTorrent=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e15\u0e48\u0e2d Torrent configureWizard.nat.title=NAT / Server \u0e1e\u0e2d\u0e23\u0e4c\u0e15 configureWizard.nat.message=\u0e43\u0e19\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49 BitTorrent \u0e17\u0e35\u0e48\u0e08\u0e30\u0e44\u0e14\u0e49\u0e1c\u0e25\u0e14\u0e35\u0e17\u0e35\u0e48\u0e2a\u0e38\u0e14\u0e02\u0e2d\u0e07, \u0e02\u0e2d\u0e41\u0e19\u0e30\u0e19\u0e33\u0e43\u0e2b\u0e49\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e2d\u0e34\u0e19\u0e40\u0e15\u0e2d\u0e23\u0e4c\u0e40\u0e19\u0e47\u0e15\u0e44\u0e14\u0e49\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e40\u0e15\u0e47\u0e21\u0e17\u0e35\u0e48 \u0e1e\u0e2d\u0e23\u0e4c\u0e15 bittorrent \u0e1e\u0e37\u0e49\u0e19\u0e10\u0e32\u0e19\u0e04\u0e37\u0e2d 6881. \u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e19\u0e35\u0e49\u0e08\u0e30\u0e0a\u0e48\u0e27\u0e22\u0e04\u0e38\u0e13\u0e17\u0e14\u0e2a\u0e2d\u0e1a / \u0e2b\u0e23\u0e37\u0e2d\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e1e\u0e2d\u0e23\u0e4c\u0e15. configureWizard.nat.test=\u0e17\u0e14\u0e2a\u0e2d\u0e1a configureWizard.nat.testing=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e17\u0e14\u0e2a\u0e2d\u0e1a\u0e1e\u0e2d\u0e23\u0e4c\u0e15 configureWizard.nat.ok=\u0e40\u0e23\u0e35\u0e22\u0e1a\u0e23\u0e49\u0e2d\u0e22 ! configureWizard.nat.ko=NAT \u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 configureWizard.nat.unable=\u0e44\u0e21\u0e48\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e17\u0e14\u0e2a\u0e2d\u0e1a\u0e44\u0e14\u0e49 configureWizard.file.title=Torrents / \u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 configureWizard.file.message1=Vuze \u0e08\u0e30\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 torrents \u0e17\u0e35\u0e48\u0e40\u0e1b\u0e34\u0e14\u0e43\u0e19\u0e41\u0e1f\u0e49\u0e21\u0e17\u0e35\u0e48\u0e23\u0e30\u0e1a\u0e38, \u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e41\u0e1f\u0e49\u0e21\u0e44\u0e14\u0e49\u0e17\u0e35\u0e48\u0e19\u0e35\u0e48: configureWizard.file.path=\u0e17\u0e35\u0e48 configureWizard.file.browse=\u0e04\u0e49\u0e19 configureWizard.file.message2=Vuze \u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e15\u0e48\u0e2d\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e44\u0e14\u0e49\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e17\u0e31\u0e19\u0e17\u0e35, \u0e42\u0e14\u0e22\u0e01\u0e32\u0e23\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e15\u0e48\u0e2d\u0e1a\u0e32\u0e07\u0e2a\u0e48\u0e27\u0e19\u0e43\u0e2b\u0e49\u0e01\u0e31\u0e1a torrents \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13 \u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e19\u0e35\u0e49, \u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23\u0e15\u0e48\u0e2d\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e08\u0e32\u0e01\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e1a\u0e32\u0e07\u0e2a\u0e48\u0e27\u0e19\u0e44\u0e14\u0e49 configureWizard.file.fastResume=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e15\u0e48\u0e2d\u0e44\u0e1b\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e23\u0e27\u0e14\u0e40\u0e23\u0e47\u0e27 configureWizard.file.invalidPath=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 configureWizard.finish.title=\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c configureWizard.finish.message=Vuze \u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07\u0e41\u0e25\u0e49\u0e27, \u0e02\u0e2d\u0e43\u0e2b\u0e49\u0e2a\u0e19\u0e38\u0e01 ! wizard.close.confirmation=\u0e01\u0e32\u0e23\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19 wizard.close.message=\u0e04\u0e38\u0e13\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e43\u0e2b\u0e49\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34\u0e19\u0e35\u0e49\u0e40\u0e1b\u0e34\u0e14\u0e02\u0e36\u0e49\u0e19 \u0e40\u0e21\u0e37\u0e48\u0e2d Vuze \u0e17\u0e33\u0e07\u0e32\u0e19\u0e04\u0e23\u0e31\u0e49\u0e07\u0e2b\u0e19\u0e49\u0e32\u0e2b\u0e23\u0e37\u0e2d\u0e44\u0e21\u0e48 ? exportTorrentWizard.title=\u0e19\u0e33\u0e2d\u0e2d\u0e01 torrent \u0e41\u0e1a\u0e1a XML exportTorrentWizard.torrentfile.title=\u0e43\u0e2a\u0e48 Torrent \u0e17\u0e35\u0e48\u0e40\u0e25\u0e37\u0e2d\u0e01 exportTorrentWizard.torrentfile.message=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 torrent \u0e17\u0e35\u0e48\u0e08\u0e30\u0e19\u0e33\u0e2d\u0e2d\u0e01 exportTorrentWizard.torrentfile.path=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 exportTorrentWizard.torrentfile.browse=\u0e04\u0e49\u0e19 exportTorrentWizard.torrentfile.invalidPath=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 torrent \u0e44\u0e21\u0e48\u0e16\u0e39\u0e01\u0e01\u0e15\u0e49\u0e2d\u0e07 exportTorrentWizard.exportfile.title=\u0e19\u0e33\u0e2d\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e40\u0e25\u0e37\u0e2d\u0e01 exportTorrentWizard.exportfile.message=\u0e43\u0e2a\u0e48\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 xml \u0e17\u0e35\u0e48\u0e19\u0e33\u0e2d\u0e2d\u0e01\u0e44\u0e1b\u0e17\u0e35\u0e48 exportTorrentWizard.exportfile.path=\u0e17\u0e35\u0e48 exportTorrentWizard.exportfile.browse=\u0e04\u0e49\u0e19 exportTorrentWizard.exportfile.invalidPath=\u0e19\u0e33\u0e2d\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 exportTorrentWizard.finish.title=\u0e40\u0e2a\u0e23\u0e47\u0e08 exportTorrentWizard.finish.message=\u0e01\u0e32\u0e23\u0e19\u0e33\u0e2d\u0e2d\u0e01\u0e2a\u0e33\u0e40\u0e23\u0e47\u0e08 exportTorrentWizard.process.inputfilebad.title=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Torrent \u0e44\u0e21\u0e48\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07 exportTorrentWizard.process.inputfilebad.message=\u0e04\u0e27\u0e32\u0e21\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e40\u0e01\u0e34\u0e14\u0e08\u0e32\u0e01\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25: exportTorrentWizard.process.outputfileexists.title=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48\u0e41\u0e25\u0e49\u0e27 exportTorrentWizard.process.outputfileexists.message=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e2a\u0e48\u0e07\u0e2d\u0e2d\u0e01\u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48\u0e41\u0e25\u0e49\u0e27 - \u0e40\u0e02\u0e35\u0e22\u0e19\u0e17\u0e31\u0e1a\u0e2b\u0e23\u0e37\u0e2d\u0e44\u0e21\u0e48 ? exportTorrentWizard.process.torrentfail.title=\u0e2d\u0e48\u0e32\u0e19 Torrent \u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27 exportTorrentWizard.process.exportfail.title=\u0e19\u0e33\u0e2d\u0e2d\u0e01 Torrent \u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27 exportTorrentWizard.process.unknownfail.title=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e44\u0e21\u0e48\u0e04\u0e32\u0e14\u0e04\u0e34\u0e14 importTorrentWizard.title=\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32 torrent \u0e41\u0e1a\u0e1a XML importTorrentWizard.torrentfile.title=\u0e43\u0e2a\u0e48 Torrent \u0e17\u0e35\u0e48\u0e40\u0e25\u0e37\u0e2d\u0e01 importTorrentWizard.torrentfile.message=\u0e43\u0e2a\u0e48\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 torrent \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01\u0e44\u0e1b\u0e22\u0e31\u0e07 importTorrentWizard.torrentfile.path=\u0e17\u0e35\u0e48 importTorrentWizard.torrentfile.browse=\u0e04\u0e49\u0e19 importTorrentWizard.torrentfile.invalidPath=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 torrent \u0e1a\u0e01\u0e1e\u0e23\u0e48\u0e2d\u0e07 importTorrentWizard.importfile.title=\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e40\u0e25\u0e37\u0e2d\u0e01 importTorrentWizard.importfile.message=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 xml \u0e17\u0e35\u0e48\u0e08\u0e30\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32 importTorrentWizard.importfile.path=\u0e17\u0e35\u0e48 importTorrentWizard.importfile.browse=\u0e04\u0e49\u0e19 importTorrentWizard.importfile.invalidPath=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32\u0e44\u0e21\u0e48\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07 importTorrentWizard.finish.title=\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c importTorrentWizard.finish.message=\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c importTorrentWizard.process.inputfilebad.title=\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 importTorrentWizard.process.inputfilebad.message=\u0e04\u0e27\u0e32\u0e21\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e40\u0e01\u0e34\u0e14\u0e08\u0e32\u0e01\u0e04\u0e27\u0e32\u0e21\u0e1e\u0e22\u0e32\u0e22\u0e32\u0e21\u0e40\u0e02\u0e49\u0e32\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25: importTorrentWizard.process.outputfileexists.title=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48 importTorrentWizard.process.outputfileexists.message=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e2d\u0e2d\u0e01\u0e21\u0e32\u0e21\u0e35\u0e41\u0e25\u0e49\u0e27 - \u0e40\u0e02\u0e35\u0e22\u0e19\u0e17\u0e31\u0e1a \u0e2b\u0e23\u0e37\u0e2d\u0e44\u0e21\u0e48? importTorrentWizard.process.torrentfail.title=\u0e40\u0e02\u0e35\u0e22\u0e19 Torrent \u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 importTorrentWizard.process.importfail.title=\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32 Torrent \u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27 importTorrentWizard.process.unknownfail.title=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e44\u0e21\u0e48\u0e04\u0e32\u0e14\u0e04\u0e34\u0e14 ConfigView.label.bindip=\u0e15\u0e48\u0e2d\u0e01\u0e31\u0e1a local IP or interface ConfigView.label.zeronewfiles=\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e01\u0e32\u0e23\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e41\u0e1a\u0e48\u0e07 \u0e41\u0e25\u0e30\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 0 ConfigView.label.zeronewfiles.tooltip=\u0e25\u0e14\u0e1b\u0e23\u0e34\u0e21\u0e32\u0e13\u0e01\u0e32\u0e23\u0e41\u0e15\u0e01\u0e0a\u0e34\u0e49\u0e19\u0e2a\u0e48\u0e27\u0e19 ConfigView.section.stats=\u0e2a\u0e15\u0e34\u0e16\u0e34 ConfigView.section.stats.enable=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19 ConfigView.section.stats.defaultsavepath=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e2a\u0e15\u0e34\u0e16\u0e34\u0e17\u0e35\u0e48 ConfigView.section.stats.choosedefaultsavepath=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e40\u0e1b\u0e49\u0e32\u0e2b\u0e21\u0e32\u0e22\u0e17\u0e35\u0e48\u0e08\u0e30\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e2a\u0e15\u0e34\u0e16\u0e34 ConfigView.section.stats.savefreq=\u0e04\u0e27\u0e32\u0e21\u0e1a\u0e48\u0e2d\u0e22\u0e04\u0e23\u0e31\u0e49\u0e07\u0e43\u0e19\u0e01\u0e32\u0e23\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 ConfigView.section.stats.minutes=\u0e19. ConfigView.section.stats.hours=\u0e0a\u0e21. ConfigView.section.stats.seconds=\u0e27\u0e34. ConfigView.section.stats.savefile=\u0e0a\u0e37\u0e48\u0e2d\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e2a\u0e15\u0e34\u0e16\u0e34 MyTorrentsView.menu.export=XML &\u0e19\u0e33\u0e2d\u0e2d\u0e01... ManagerItem.finishing=\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19 ConfigView.dialog.choosedefaulttorrentpath=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 torrent \u0e1e\u0e37\u0e49\u0e19\u0e10\u0e32\u0e19 ConfigView.dialog.choosemovepath=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e17\u0e35\u0e48\u0e08\u0e30\u0e40\u0e04\u0e25\u0e37\u0e48\u0e2d\u0e19\u0e22\u0e49\u0e32\u0e22\u0e44\u0e1b ConfigView.label.movecompleted=\u0e22\u0e49\u0e32\u0e22\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e41\u0e25\u0e49\u0e27 ConfigView.label.savetorrents=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 .torrent MainWindow.menu.view.mytracker=&Tracker \u0e02\u0e2d\u0e07\u0e09\u0e31\u0e19 MyTrackerView.title.full=Tracker \u0e02\u0e2d\u0e07\u0e09\u0e31\u0e19 MyTrackerView.name=\u0e0a\u0e37\u0e48\u0e2d MyTrackerView.status=\u0e2a\u0e16\u0e32\u0e19\u0e30 MyTrackerView.status.started=\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23 MyTrackerView.status.stopped=\u0e2b\u0e22\u0e38\u0e14 MyTrackerView.announces=\u0e41\u0e08\u0e49\u0e07 MyTrackerView.uploaded=\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14 MyTrackerView.downloaded=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 MyTrackerView.left=\u0e40\u0e2b\u0e25\u0e37\u0e2d ConfigView.section.style=\u0e01\u0e32\u0e23\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25 ConfigView.section.style.useCustomTabs=\u0e43\u0e0a\u0e49\u0e41\u0e16\u0e1a\u0e17\u0e35\u0e48\u0e1b\u0e34\u0e14\u0e44\u0e14\u0e49 (\u0e15\u0e49\u0e2d\u0e07\u0e40\u0e23\u0e34\u0e48\u0e21\u0e17\u0e33\u0e07\u0e32\u0e19\u0e43\u0e2b\u0e21\u0e48) MainWindow.menu.view.plugins=&\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21 fileDownloadWindow.saveTorrentIn=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Torrent \u0e43\u0e19 fileDownloadWindow.downloading=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e08\u0e32\u0e01 : fileDownloadWindow.status=\u0e2a\u0e16\u0e32\u0e19\u0e30 : fileDownloadWindow.state_initializing=\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e02\u0e31\u0e49\u0e19\u0e15\u0e49\u0e19 fileDownloadWindow.state_downloading=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 fileDownloadWindow.state_error=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 : MainWindow.menu.file.open.url=&URL openUrl.title=Vuze - \u0e40\u0e1b\u0e34\u0e14 Url MyTorrentsView.menu.host.error.title=Torrent Hosting \u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27 MyTorrentsView.menu.host.error.message=\u0e04\u0e27\u0e32\u0e21\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e14\u0e31\u0e07\u0e01\u0e25\u0e48\u0e32\u0e27\u0e40\u0e01\u0e34\u0e14\u0e08\u0e32\u0e01 hosting torrent ConfigView.section.tracker.pollinterval=Tracker client poll interval (\u0e27\u0e34\u0e19\u0e32\u0e17\u0e35) ConfigView.section.tracker.publishenable=\u0e2d\u0e2d\u0e01\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 torrent \u0e17\u0e35\u0e48 "" ConfigView.section.tracker.ip=Tracker \u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02 IP \u0e20\u0e32\u0e22\u0e19\u0e2d\u0e01 ConfigView.section.style.enableXPStyle=\u0e43\u0e0a\u0e49\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a XP (\u0e15\u0e49\u0e2d\u0e07\u0e40\u0e23\u0e34\u0e48\u0e21\u0e17\u0e33\u0e07\u0e32\u0e19\u0e43\u0e2b\u0e21\u0e48) ConfigView.section.tracker.checkip=\u0e04\u0e49\u0e19\u0e1e\u0e1a\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02 IP \u0e20\u0e32\u0e22\u0e19\u0e2d\u0e01\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34... ipCheckerWizard.title=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a IP \u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 ipCheckerWizard.service=\u0e1a\u0e23\u0e34\u0e01\u0e32\u0e23 ipCheckerWizard.chooseService=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e01\u0e32\u0e23\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a IP \u0e08\u0e32\u0e01\u0e1a\u0e23\u0e34\u0e01\u0e32\u0e23\u0e17\u0e35\u0e48\u0e21\u0e35 ipCheckerWizard.explanations=\u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e43\u0e0a\u0e49\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34\u0e04\u0e49\u0e19\u0e2b\u0e32\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02 IP \u0e20\u0e32\u0e22\u0e19\u0e2d\u0e01\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13 \u0e16\u0e49\u0e32\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02 IP \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e40\u0e1b\u0e47\u0e19 dynamic \u0e02\u0e2d\u0e41\u0e19\u0e30\u0e19\u0e33\u0e43\u0e2b\u0e49\u0e40\u0e1b\u0e34\u0e14 account \u0e01\u0e31\u0e1a Dynamic DNS Service \u0e1a\u0e32\u0e07\u0e1a\u0e23\u0e34\u0e01\u0e32\u0e23\u0e02\u0e49\u0e32\u0e07\u0e25\u0e48\u0e32\u0e07\u0e43\u0e0a\u0e49 link \u0e17\u0e35\u0e48\u0e21\u0e35\u0e43\u0e2b\u0e49\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e25\u0e07 \u0e17\u0e30\u0e40\u0e1a\u0e35\u0e22\u0e19\u0e44\u0e14\u0e49 (\u0e17\u0e35\u0e48\u0e2a\u0e19\u0e31\u0e1a\u0e2a\u0e19\u0e38\u0e19) \u0e41\u0e25\u0e49\u0e27\u0e43\u0e2a\u0e48\u0e0a\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22 IP \u0e14\u0e49\u0e27\u0e22\u0e0a\u0e37\u0e48\u0e2d host \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e41\u0e1a\u0e1a dynamic (\u0e15\u0e31\u0e27\u0e2d\u0e22\u0e48\u0e32\u0e07 myhostname.dyndns.org) \u0e04\u0e38\u0e13\u0e15\u0e49\u0e2d\u0e07\u0e43\u0e0a\u0e49\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 Dynamic DNS Service \u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e14\u0e49\u0e27\u0e22\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02 IP \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13 \u0e2b\u0e32\u0e01\u0e17\u0e33\u0e40\u0e0a\u0e48\u0e19\u0e19\u0e35\u0e49\u0e08\u0e30\u0e17\u0e33\u0e43\u0e2b\u0e49\u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16 host torrents \u0e41\u0e21\u0e49\u0e27\u0e48\u0e32 IP \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e08\u0e30\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e44\u0e1b ipCheckerWizard.service.description=\u0e2d\u0e18\u0e34\u0e1a\u0e32\u0e22 : ipCheckerWizard.progresstitle=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a IP ipCheckerWizard.checkComplete=IP \u0e17\u0e35\u0e48\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c: ipCheckerWizard.checkFailed=\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27, \u0e40\u0e2b\u0e15\u0e38\u0e1c\u0e25 : wizard.tracker.local=\u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e1d\u0e31\u0e07 Tracker \u0e02\u0e2d\u0e07 Vuze wizard.tracker.external=\u0e43\u0e0a\u0e49 Tracker \u0e20\u0e32\u0e22\u0e19\u0e2d\u0e01 wizard.tracker.howToLocal=\t\u0e44\u0e1b\u0e17\u0e35\u0e48 '\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07>Tracker' \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19 wizard.announceUrl=URL \u0e17\u0e35\u0e48\u0e41\u0e08\u0e49\u0e07: IPChecker.external.service.discoveryvip.description=Discoveryvip - \u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02 IP \u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19 IPChecker.external.httpinvalidresponse=\u0e27\u0e34\u0e40\u0e04\u0e23\u0e32\u0e30\u0e2b\u0e4c\u0e01\u0e32\u0e23\u0e15\u0e2d\u0e1a\u0e23\u0e31\u0e1a\u0e02\u0e2d\u0e07 HTTP IPChecker.external.loadingwebpage=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e42\u0e2b\u0e25\u0e14 web page IPChecker.external.analysingresponse=\u0e27\u0e34\u0e40\u0e04\u0e23\u0e32\u0e30\u0e2b\u0e4c\u0e01\u0e32\u0e23\u0e15\u0e2d\u0e1a\u0e23\u0e31\u0e1a IPChecker.external.addressextracted=\u0e41\u0e22\u0e01\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02 IP IPChecker.external.httploadfail=load page \u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 IPChecker.external.timeout=\u0e40\u0e01\u0e34\u0e14 Timeout IPChecker.external.ipnotfound=\u0e44\u0e21\u0e48\u0e1e\u0e1a\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02 IP ConfigView.section.tracker.pollintervalmin=\u0e15\u0e33\u0e2a\u0e38\u0e14 ConfigView.section.tracker.pollintervalmax=\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 ConfigView.section.tracker.pollintervalincby=\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e17\u0e35\u0e25\u0e30 ConfigView.section.tracker.pollintervalincper=\u0e17\u0e38\u0e01\u0e46 'n' clients splash.loadingImages=\u0e42\u0e2b\u0e25\u0e14\u0e23\u0e39\u0e1b splash.initializeGui=\u0e2b\u0e19\u0e49\u0e32\u0e15\u0e48\u0e32\u0e07\u0e2b\u0e25\u0e31\u0e01\u0e02\u0e31\u0e49\u0e19\u0e15\u0e49\u0e19 splash.openViews=\u0e40\u0e1b\u0e34\u0e14\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25 splash.plugin=\u0e42\u0e2b\u0e25\u0e14\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21 : configureWizard.nat.tooManyPorts=\u0e1b\u0e23\u0e34\u0e21\u0e32\u0e13\u0e1e\u0e2d\u0e23\u0e4c\u0e15\u0e21\u0e32\u0e01\u0e40\u0e01\u0e34\u0e19\u0e01\u0e27\u0e48\u0e32\u0e17\u0e35\u0e48\u0e08\u0e30\u0e17\u0e14\u0e2a\u0e2d\u0e1a (\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 9) ConfigView.section.color=\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a\u0e2a\u0e35 MyTorrentsView.menu.publish=&\u0e2d\u0e2d\u0e01... MyTrackerView.status.published=\u0e2d\u0e2d\u0e01 MyTrackerView.completed=\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19 MainWindow.menu.file.open.torrentnodefault=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 .torrent (\u0e44\u0e21\u0e48\u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e41\u0e1a\u0e1a\u0e1e\u0e37\u0e49\u0e19\u0e10\u0e32\u0e19) wizard.comment=\u0e02\u0e49\u0e2d\u0e04\u0e34\u0e14\u0e40\u0e2b\u0e47\u0e19 ConfigView.label.movetorrent=\u0e22\u0e49\u0e32\u0e22 .torrent ConfigView.section.file.decoder.label=torrent \u0e1e\u0e37\u0e49\u0e19\u0e10\u0e32\u0e19\u0e40\u0e02\u0e49\u0e32\u0e23\u0e2b\u0e31\u0e2a\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e08\u0e33\u0e40\u0e1b\u0e47\u0e19 ConfigView.section.file.decoder.nodecoder=\u0e44\u0e21\u0e48\u0e21\u0e35 IPChecker.external.service.no-ip.name=\u0e44\u0e21\u0e48\u0e21\u0e35-IP IPChecker.external.service.no-ip.description=Dynamic and Static DNS service provider\n('check address' \u0e44\u0e21\u0e48\u0e21\u0e35\u0e1a\u0e23\u0e34\u0e01\u0e32\u0e23\u0e1f\u0e23\u0e35) ConfigView.section.tracker.publicenable=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19 torrents \u0e20\u0e32\u0e22\u0e19\u0e2d\u0e01 ConfigView.label.playdownloadspeech=\u0e1e\u0e39\u0e14\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19 ConfigView.label.playdownloadspeech.info=\u0e01\u0e32\u0e23\u0e1a\u0e23\u0e34\u0e01\u0e32\u0e23\u0e40\u0e2a\u0e35\u0e22\u0e07\u0e43\u0e0a\u0e49\u0e14\u0e35\u0e17\u0e35\u0e48\u0e2a\u0e38\u0e14\u0e01\u0e31\u0e1a\u0e20\u0e32\u0e29\u0e32\u0e2d\u0e31\u0e07\u0e01\u0e24\u0e29 # # Tooltips # GeneralView.label.status.pieces_available.tooltip=\u0e41\u0e2a\u0e14\u0e07\u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e33\u0e40\u0e19\u0e32\u0e17\u0e35\u0e48\u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48\n\u0e16\u0e49\u0e32\u0e08\u0e33\u0e19\u0e27\u0e19\u0e14\u0e49\u0e32\u0e19\u0e02\u0e27\u0e32\u0e19\u0e49\u0e2d\u0e22\u0e01\u0e27\u0e48\u0e32 1, \u0e04\u0e38\u0e13\u0e44\u0e21\u0e48\u0e40\u0e2b\u0e47\u0e19\u0e2a\u0e33\u0e40\u0e19\u0e32\u0e2b\u0e21\u0e14\u0e43\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 (\u0e41\u0e25\u0e30\u0e2d\u0e32\u0e08\u0e21\u0e35\u0e1b\u0e31\u0e0d\u0e2b\u0e32\u0e43\u0e19\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e43\u0e2b\u0e49\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c) GeneralView.label.trackerurl.tooltip=\u0e04\u0e25\u0e34\u0e01\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e2a\u0e33\u0e40\u0e19\u0e32 url \u0e17\u0e35\u0e48\u0e41\u0e08\u0e49\u0e07\u0e44\u0e1b\u0e17\u0e35\u0e48 clipboard GeneralView.label.trackerurlopen.tooltip=\u0e04\u0e25\u0e34\u0e01\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e40\u0e1b\u0e34\u0e14\u0e2b\u0e19\u0e49\u0e32\u0e2b\u0e25\u0e31\u0e01\u0e02\u0e2d\u0e07 tracker # # 2.0.4.4 # ConfigView.section.style.guiUpdate=\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 GUI \u0e17\u0e38\u0e01\u0e46 ConfigView.section.style.graphicsUpdate=\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e41\u0e16\u0e1a\u0e01\u0e23\u0e32\u0e1f\u0e1f\u0e34\u0e01\u0e17\u0e38\u0e01\u0e46 N GUI \u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 ConfigView.section.style.reOrderDelay=\u0e08\u0e31\u0e14\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e15\u0e32\u0e23\u0e32\u0e07\u0e43\u0e2b\u0e21\u0e48\u0e17\u0e38\u0e01\u0e46 N GUI \u0e2d\u0e31\u0e15\u0e40\u0e14\u0e17 [0: \u0e44\u0e21\u0e48\u0e15\u0e49\u0e2d\u0e07] ConfigView.section.style.reOrderDelay.never=\u0e44\u0e21\u0e48\u0e40\u0e25\u0e22 ConfigView.section.logging=\u0e01\u0e32\u0e23\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 ConfigView.section.logging.enable=\u0e40\u0e1b\u0e34\u0e14\u0e23\u0e30\u0e1a\u0e30\u0e01\u0e32\u0e23\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 ConfigView.section.logging.logdir=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 ConfigView.section.logging.choosedefaultsavepath=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e17\u0e35\u0e48\u0e08\u0e30\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 GeneralView.label.updatein.querying=\u0e40\u0e23\u0e35\u0e22\u0e07\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a... configureWizard.nat.sharePort=\u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e40\u0e14\u0e35\u0e22\u0e27\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e08\u0e32\u0e01\u0e1e\u0e2d\u0e23\u0e4c\u0e15\u0e15\u0e48\u0e2d\u0e17\u0e38\u0e01 torrents ConfigView.section.logging.maxsize=\u0e02\u0e19\u0e32\u0e14\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 ConfigView.section.tracker.passwordenableweb=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19\u0e1a\u0e19 tracker web ConfigView.section.tracker.passwordenabletorrent=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19\u0e1a\u0e19 torrents ConfigView.section.tracker.username=\u0e0a\u0e37\u0e48\u0e2d\u0e1c\u0e39\u0e43\u0e0a\u0e49 ConfigView.section.tracker.password=\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19 columnChooser.title=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e04\u0e2d\u0e25\u0e31\u0e21\u0e19\u0e4c\u0e17\u0e35\u0e48\u0e08\u0e30\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25 columnChooser.move=\u0e25\u0e32\u0e01\u0e41\u0e16\u0e27\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e08\u0e31\u0e14\u0e25\u0e33\u0e14\u0e31\u0e1a\u0e43\u0e2b\u0e21\u0e48 columnChooser.apply=\u0e43\u0e0a\u0e49 columnChooser.columnname=\u0e0a\u0e37\u0e48\u0e2d\u0e04\u0e2d\u0e25\u0e31\u0e21\u0e19\u0e4c columnChooser.columndescription=\u0e04\u0e33\u0e2d\u0e18\u0e34\u0e1a\u0e32\u0e22 TableColumn.header.shareRatio=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 MyTorrentsView.menu.editTableColumns=&\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07\u0e41\u0e16\u0e27 wizard.operationfailed=\u0e1b\u0e0f\u0e34\u0e1a\u0e31\u0e15\u0e34\u0e01\u0e32\u0e23\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27 authenticator.title=\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15 authenticator.realm=\u0e02\u0e2d\u0e1a\u0e40\u0e02\u0e15 authenticator.user=\u0e0a\u0e37\u0e48\u0e2d\u0e1c\u0e39\u0e43\u0e0a\u0e49 authenticator.password=\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19 ConfigView.label.allowSendVersion=\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e43\u0e2b\u0e49 Vuze \u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e19\u0e34\u0e23\u0e19\u0e32\u0e21 \u0e41\u0e25\u0e30\u0e2a\u0e38\u0e48\u0e21 id \u0e02\u0e13\u0e30\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e2b\u0e32\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e43\u0e2b\u0e21\u0e48 wizard.hint.mode=\u0e43\u0e1a\u0e49:\t\u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16 Drag \u0e41\u0e25\u0e30 Drop \u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e14\u0e35\u0e22\u0e27 \u0e2b\u0e23\u0e37\u0e2d\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e40\u0e14\u0e35\u0e22\u0e27\u0e1a\u0e19\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34\u0e19\u0e35\u0e49\n\t\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e2b\u0e23\u0e37\u0e2d\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 wizard.hint.file=\u0e43\u0e1a\u0e49:\t\u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e14\u0e35\u0e22\u0e27\u0e14\u0e49\u0e27\u0e22\u0e01\u0e32\u0e23 Drag \u0e41\u0e25\u0e30 Drop wizard.hint.directory=\u0e43\u0e1a\u0e49:\t\u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e40\u0e14\u0e35\u0e48\u0e22\u0e27\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23 Drag \u0e41\u0e25\u0e30 Drop MainWindow.menu.help.checkupdate=&\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21 TableColumn.header.down=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 TableColumn.header.up=\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14 ConfigView.section.tracker.passwordenabletorrent.info=\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21 BitTorrent \u0e17\u0e35\u0e48\u0e40\u0e2b\u0e21\u0e32\u0e30\u0e2a\u0e21 (\u0e15\u0e31\u0e27\u0e2d\u0e22\u0e48\u0e32\u0e07 Vuze ConfigView.section.style.confirmationOnExit=\u0e41\u0e2a\u0e14\u0e07\u0e2b\u0e19\u0e49\u0e32\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e40\u0e27\u0e25\u0e32\u0e2d\u0e2d\u0e01 MainWindow.dialog.exitconfirmation.title=\u0e2d\u0e2d\u0e01\u0e08\u0e32\u0e01 Vuze MainWindow.dialog.exitconfirmation.text=\u0e04\u0e38\u0e13\u0e41\u0e19\u0e48\u0e43\u0e08\u0e27\u0e48\u0e32\u0e08\u0e30\u0e2d\u0e2d\u0e01\u0e08\u0e32\u0e01 Vuze \u0e08\u0e23\u0e34\u0e07\u0e2b\u0e23\u0e37\u0e2d ? SystemTray.menu.stopalltransfers=\u0e2b\u0e22\u0e38\u0e14\u0e01\u0e32\u0e23\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 TrayWindow.menu.stopalldownloads=\u0e2b\u0e22\u0e38\u0e14\u0e01\u0e32\u0e23 &\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e17\u0e38\u0e01\u0e2d\u0e31\u0e19 ConfigView.section.tracker.sslport.info=\u0e14\u0e39\u0e17\u0e35\u0e48 FAQ \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e40\u0e15\u0e34\u0e21 wizard.tracker.ssl=\u0e43\u0e0a\u0e49 SSL ConfigView.label.playdownloadfinished=\u0e40\u0e25\u0e48\u0e19\u0e40\u0e2a\u0e35\u0e22\u0e07\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e2a\u0e23\u0e47\u0e08 TableColumn.header.pieces=\u0e2a\u0e48\u0e27\u0e19 TableColumn.header.pieces.info=\u0e01\u0e23\u0e32\u0e1f\u0e41\u0e2a\u0e14\u0e07\u0e27\u0e48\u0e32\u0e2a\u0e48\u0e27\u0e19\u0e44\u0e2b\u0e19\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e41\u0e25\u0e49\u0e27 TableColumn.header.completion=\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19 TableColumn.header.completion.info=\u0e01\u0e23\u0e32\u0e1f\u0e41\u0e2a\u0e14\u0e07 % \u0e43\u0e19\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 ConfigView.section.style.showdownloadbasket=\u0e41\u0e2a\u0e14\u0e07\u0e15\u0e23\u0e30\u0e01\u0e23\u0e49\u0e32\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 (Drag \u0e41\u0e25\u0e30 Drop .torrents) ConfigView.section.style.alwaysShowTorrentFiles=\u0e41\u0e2a\u0e14\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Torrent \u0e43\u0e19\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14/\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 \u0e40\u0e2a\u0e21\u0e2d wizard.multitracker=\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 Multi-Tracker \u0e1a\u0e19 torrent wizard.multitracker.configuration=\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07 Multi-Tracker wizard.multitracker.new=\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e43\u0e2b\u0e21\u0e48... wizard.multitracker.edit=\u0e41\u0e01\u0e49\u0e44\u0e02... wizard.multitracker.delete=\u0e25\u0e1a wizard.multitracker.group=\u0e01\u0e25\u0e38\u0e48\u0e21 Tracker wizard.multitracker.edit.title=\u0e41\u0e01\u0e49\u0e44\u0e02 Multi-Tracker wizard.multitracker.edit.name=\u0e0a\u0e37\u0e48\u0e2d wizard.multitracker.edit.save=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 wizard.multitracker.edit.newgroup=\u0e01\u0e25\u0e38\u0e48\u0e21\u0e43\u0e2b\u0e21\u0e48 wizard.multitracker.edit.deletegroup=\u0e25\u0e1a wizard.multitracker.edit.newtracker=Tracker \u0e43\u0e2b\u0e21\u0e48 wizard.multitracker.edit.deletetracker=\u0e25\u0e1a wizard.multitracker.edit.edit=\u0e41\u0e01\u0e49\u0e44\u0e02 wizard.addingmt=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 Multi-Tracker wizard.multitracker.noannounce=\u0e01\u0e32\u0e23\u0e41\u0e08\u0e49\u0e07 URL \u0e44\u0e21\u0e48\u0e1b\u0e23\u0e32\u0e01\u0e0f\u0e1a\u0e19\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d trackers \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13 MyTorrentsView.menu.recheck=\u0e1a\u0e31\u0e07\u0e04\u0e31\u0e1a\u0e15\u0e23\u0e27\u0e08\u0e43\u0e2b&\u0e21\u0e48 iconBar.showDownloadBar.tooltip=\u0e41\u0e2a\u0e14\u0e07\u0e41\u0e16\u0e1a\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 iconBar.start.tooltip=\u0e40\u0e23\u0e34\u0e48\u0e21 iconBar.stop.tooltip=\u0e2b\u0e22\u0e38\u0e14 iconBar.remove.tooltip=\u0e25\u0e1a\u0e2d\u0e2d\u0e01 iconBar.openNoDefault.tooltip=\u0e40\u0e1b\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 .torrent (\u0e44\u0e21\u0e48\u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e41\u0e1a\u0e1a\u0e1e\u0e37\u0e49\u0e19\u0e10\u0e32\u0e19) iconBar.openURL.tooltip=\u0e40\u0e1b\u0e34\u0e14 URL iconBar.openFolder.tooltip=\u0e40\u0e1b\u0e34\u0e14\u0e41\u0e1f\u0e49\u0e21 iconBar.new.tooltip=\u0e2a\u0e23\u0e49\u0e32\u0e07 torrent iconBar.up.tooltip=\u0e22\u0e49\u0e32\u0e22\u0e02\u0e36\u0e49\u0e19 iconBar.down.tooltip=\u0e22\u0e49\u0e32\u0e22\u0e44\u0e1b\u0e25\u0e07 iconBar.run.tooltip=\u0e40\u0e1b\u0e34\u0e14 iconBar.publish.tooltip=\u0e2d\u0e2d\u0e01 MyTorrentsView.menu.editTracker=&\u0e41\u0e01\u0e49\u0e44\u0e02 Tracker URL(s) GeneralView.menu.selectTracker=\u0e40\u0e25\u0e37\u0e2d\u0e01 ConfigView.section.stats.xslfile=\u0e0a\u0e37\u0e48\u0e2d\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 XSL ConfigView.section.stats.xslfiledetails=\u0e19\u0e35\u0e48\u0e08\u0e30\u0e23\u0e27\u0e21\u0e2d\u0e22\u0e39\u0e48\u0e43\u0e19\u0e2b\u0e31\u0e27\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e2a\u0e15\u0e34\u0e16\u0e34\u0e41\u0e16\u0e1a ConfigView.label.savetorrentbackup=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e2a\u0e33\u0e23\u0e2d\u0e07 ConfigView.section.tracker.forceport=\u0e1a\u0e31\u0e07\u0e04\u0e31\u0e1a hosted torrents \u0e20\u0e32\u0e22\u0e19\u0e2d\u0e01\u0e44\u0e1b\u0e17\u0e35\u0e48\u0e1e\u0e2d\u0e23\u0e4c\u0e15\u0e1e\u0e37\u0e49\u0e19\u0e10\u0e32\u0e19 ConfigView.section.ipfilter.allow=\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e34\u0e0a\u0e48\u0e27\u0e07\u0e40\u0e2b\u0e25\u0e48\u0e32\u0e19\u0e35\u0e49 (\u0e04\u0e48\u0e32\u0e21\u0e32\u0e15\u0e23\u0e32\u0e10\u0e32\u0e19 \u0e04\u0e37\u0e2d \u0e1b\u0e0f\u0e34\u0e40\u0e2a\u0e18) ConfigView.section.ipfilter.list.inrange=\u0e40\u0e04\u0e22\u0e2d\u0e22\u0e39\u0e48\u0e43\u0e19\u0e0a\u0e48\u0e27\u0e07 ConfigView.section.ipfilter.list.notinrange=\u0e44\u0e21\u0e48\u0e40\u0e04\u0e22\u0e2d\u0e22\u0e39\u0e48\u0e43\u0e19\u0e0a\u0e48\u0e27\u0e07\u0e44\u0e2b\u0e19 ConfigView.section.ipfilter.list.title=\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d IP \u0e17\u0e35\u0e48\u0e16\u0e39\u0e01\u0e1a\u0e25\u0e47\u0e2d\u0e01 ConfigView.label.allowsameip=\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e34\u0e43\u0e2b\u0e49\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e2b\u0e25\u0e32\u0e22\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e08\u0e32\u0e01 IP \u0e40\u0e14\u0e35\u0e22\u0e27\u0e01\u0e31\u0e19 ConfigView.label.allowsameip.tooltip=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e04\u0e38\u0e13\u0e08\u0e33\u0e40\u0e1b\u0e47\u0e19\u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19\n\u0e19\u0e35\u0e48\u0e40\u0e1b\u0e47\u0e19\u0e01\u0e32\u0e23\u0e1b\u0e49\u0e2d\u0e07\u0e01\u0e31\u0e19 leecher (\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e40\u0e25\u0e37\u0e2d\u0e01) ConfigView.label.userSuperSeeding=\u0e43\u0e0a\u0e49 Super Seeding PeersView.uniquepiece=\u0e2a\u0e48\u0e27\u0e19 (\u0e41\u0e1a\u0e1a Super-Seed) PeersView.uniquepiece.none=\u0e44\u0e21\u0e48\u0e21\u0e35 PeersView.timetosend=\u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48\u0e2a\u0e48\u0e07\u0e2a\u0e48\u0e27\u0e19\u0e43\u0e2b\u0e21\u0e48 (\u0e41\u0e1a\u0e1a Super-Seed) ConfigView.section.style.addurlsilently=\u0e40\u0e1b\u0e34\u0e14 URL \u0e41\u0e1a\u0e1a\u0e40\u0e07\u0e35\u0e22\u0e1a (\u0e44\u0e21\u0e48\u0e21\u0e35\u0e01\u0e25\u0e48\u0e2d\u0e07\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21) ConfigView.section.style.addurlsilently.tooltip=\u0e04\u0e33\u0e40\u0e15\u0e37\u0e2d\u0e19: \u0e2b\u0e19\u0e49\u0e32\u0e15\u0e48\u0e32\u0e07\u0e2b\u0e25\u0e31\u0e01\u0e08\u0e30\u0e21\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e40\u0e2b\u0e47\u0e19\u0e16\u0e49\u0e32\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e2d\u0e22\u0e39\u0e48 !\n\u0e16\u0e49\u0e32\u0e04\u0e38\u0e13\u0e44\u0e21\u0e48\u0e21\u0e35\u0e01\u0e32\u0e23\u0e41\u0e2a\u0e14\u0e07\u0e15\u0e31\u0e27\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e17\u0e35\u0e48 tray, \u0e04\u0e38\u0e13\u0e04\u0e27\u0e23\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e19\u0e35\u0e49 ConfigView.section.file.decoder.prompt=\u0e40\u0e15\u0e37\u0e2d\u0e19\u0e40\u0e2a\u0e21\u0e2d\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e21\u0e35\u0e17\u0e32\u0e07\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e43\u0e19\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32\u0e23\u0e2b\u0e31\u0e2a ConfigView.section.file.decoder.prompt.tooltip=\u0e41\u0e2a\u0e14\u0e07\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14\u0e15\u0e25\u0e2d\u0e14\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e40\u0e02\u0e49\u0e32\u0e23\u0e2b\u0e31\u0e2a\u0e44\u0e14\u0e49 MyTorrentsView.menu.moveTop=&\u0e1a\u0e19\u0e2a\u0e38\u0e14 MyTorrentsView.menu.moveEnd=&\u0e25\u0e48\u0e32\u0e07\u0e2a\u0e38\u0e14 ConfigView.label.moveonlyusingdefaultsave=\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e17\u0e35\u0e48\u0e2d\u0e22\u0e39\u0e48\u0e43\u0e19\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e40\u0e1a\u0e37\u0e49\u0e2d\u0e07\u0e15\u0e49\u0e19\u0e17\u0e35\u0e48\u0e01\u0e33\u0e2b\u0e19\u0e14 ConfigView.label.moveonlyusingdefaultsave.tooltip=\u0e22\u0e49\u0e32\u0e22\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e17\u0e35\u0e48\u0e2d\u0e22\u0e39\u0e48\u0e43\u0e19\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e1a\u0e34\u0e49\u0e2d\u0e07\u0e15\u0e49\u0e19\u0e17\u0e35\u0e48\u0e01\u0e33\u0e2b\u0e19\u0e14 ConfigView.label.watchtorrentfolder=\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32 .torrents \u0e43\u0e2b\u0e21\u0e48\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 ConfigView.label.watchtorrentfolder.tooltip=\u0e2b\u0e32 .torrents \u0e43\u0e2b\u0e21\u0e48\u0e40\u0e1b\u0e47\u0e19\u0e23\u0e30\u0e22\u0e30 ConfigView.label.watchtorrentfolderinterval=\u0e0a\u0e48\u0e27\u0e07\u0e40\u0e27\u0e25\u0e32\u0e1e\u0e31\u0e01 ConfigView.label.watchtorrentfolderinterval.tooltip=\u0e2b\u0e22\u0e38\u0e14\u0e0a\u0e31\u0e48\u0e27\u0e04\u0e23\u0e32\u0e27\u0e08\u0e19\u0e01\u0e27\u0e48\u0e32\u0e41\u0e1f\u0e49\u0e21\u0e08\u0e30\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e15\u0e23\u0e27\u0e08\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07 ConfigView.dialog.choosewatchtorrentfolderpath=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e17\u0e35\u0e48\u0e08\u0e30\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32 .torrent ConfigView.label.startwatchedtorrentsstopped=\u0e40\u0e23\u0e34\u0e48\u0e21\u0e01\u0e32\u0e23\u0e2b\u0e22\u0e38\u0e14 ConfigView.label.startwatchedtorrentsstopped.tooltip=\u0e40\u0e1e\u0e34\u0e48\u0e21 .torrents \u0e43\u0e2b\u0e21\u0e48\u0e43\u0e19\u0e2a\u0e20\u0e32\u0e27\u0e30\u0e2b\u0e22\u0e38\u0e14 ConfigView.section.plugins=\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21 wizard.maketorrent.filesize=\u0e02\u0e19\u0e32\u0e14\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 wizard.maketorrent.piececount=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e48\u0e27\u0e19 wizard.maketorrent.piecesize=\u0e02\u0e19\u0e32\u0e14\u0e02\u0e2d\u0e07\u0e2a\u0e48\u0e27\u0e19 wizard.maketorrent.auto=\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 MainWindow.menu.view.stats=&\u0e2a\u0e16\u0e34\u0e15\u0e34 SpeedView.title.full=\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21 SpeedView.downloadSpeed.title=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 SpeedView.uploadSpeed.title=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14 ConfigView.section.style.useSIUnits=\u0e43\u0e0a\u0e49\u0e2b\u0e19\u0e48\u0e27\u0e22 IEC (KB -> KiB \u0e2d\u0e37\u0e48\u0e19\u0e46) iconBar.top.tooltip=\u0e22\u0e49\u0e32\u0e22\u0e44\u0e1b\u0e1a\u0e19\u0e2a\u0e38\u0e14 iconBar.bottom.tooltip=\u0e22\u0e49\u0e32\u0e22\u0e44\u0e1b\u0e25\u0e48\u0e32\u0e07\u0e2a\u0e38\u0e14 TableColumn.header.health=\u0e2a\u0e38\u0e02\u0e20\u0e32\u0e1e MyTorrentsView.menu.health=\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e2a\u0e38\u0e02\u0e20\u0e32\u0e1e health.explain.grey=\u0e2b\u0e21\u0e32\u0e22\u0e04\u0e27\u0e32\u0e21\u0e27\u0e48\u0e32 torrent \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23 (\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 \u0e2b\u0e23\u0e37\u0e2d\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14) health.explain.red=\u0e2b\u0e21\u0e32\u0e22\u0e04\u0e27\u0e32\u0e21\u0e27\u0e48\u0e32\u0e04\u0e38\u0e13\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e15\u0e34\u0e15\u0e14\u0e48\u0e2d\u0e01\u0e31\u0e1a peer \u0e43\u0e14\u0e46 \u0e40\u0e27\u0e25\u0e32\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 health.explain.blue=\u0e40\u0e21\u0e37\u0e48\u0e2d seeding, \u0e2b\u0e21\u0e32\u0e22\u0e04\u0e27\u0e32\u0e21\u0e27\u0e48\u0e32\u0e04\u0e38\u0e13\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e01\u0e31\u0e1a peer \u0e43\u0e14\u0e46\n\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14,\u0e2b\u0e21\u0e32\u0e22\u0e04\u0e27\u0e32\u0e21\u0e27\u0e48\u0e32\u0e04\u0e38\u0e13\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e01\u0e31\u0e1a\u0e1a\u0e32\u0e07 peers \u0e41\u0e15\u0e48 tracker \u0e25\u0e49\u0e21 health.explain.yellow=\u0e2b\u0e21\u0e32\u0e22\u0e04\u0e27\u0e32\u0e21\u0e27\u0e48\u0e32 tracker \u0e40\u0e1b\u0e47\u0e19\u0e1b\u0e01\u0e15\u0e34, \u0e04\u0e38\u0e13\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e01\u0e31\u0e1a peers, \u0e41\u0e15\u0e48\u0e04\u0e38\u0e13\u0e44\u0e21\u0e48\u0e21\u0e35\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e17\u0e32\u0e07\u0e44\u0e01\u0e25\u0e43\u0e14\u0e46\n\u0e04\u0e38\u0e13\u0e2d\u0e32\u0e08\u0e21\u0e35\u0e1b\u0e31\u0e0d\u0e2b\u0e32 NAT \u0e16\u0e49\u0e32 torrents \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e2d\u0e22\u0e39\u0e48\u0e43\u0e19\u0e2a\u0e16\u0e32\u0e19\u0e30 \u0e40\u0e2b\u0e25\u0e37\u0e2d\u0e07 \u0e15\u0e25\u0e2d\u0e14\u0e40\u0e27\u0e25\u0e32 health.explain.green=\u0e2b\u0e21\u0e32\u0e22\u0e04\u0e27\u0e32\u0e21\u0e27\u0e48\u0e32\u0e17\u0e38\u0e01\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e40\u0e1b\u0e47\u0e19\u0e44\u0e1b\u0e14\u0e49\u0e27\u0e22\u0e14\u0e35 ConfigView.section.style.alwaysRefreshMyTorrents=\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25\u0e43\u0e2b\u0e21\u0e48 Torrents \u0e02\u0e2d\u0e07\u0e09\u0e31\u0e19\u0e40\u0e2a\u0e21\u0e2d ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=\u0e15\u0e31\u0e27\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e19\u0e35\u0e49\u0e08\u0e30\u0e17\u0e33\u0e43\u0e2b\u0e49 Torrents \u0e02\u0e2d\u0e07\u0e09\u0e31\u0e19\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25\u0e43\u0e2b\u0e21\u0e48\u0e17\u0e38\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07\u0e41\u0e21\u0e49\u0e27\u0e48\u0e32\u0e08\u0e30\u0e44\u0e21\u0e48\u0e1b\u0e23\u0e32\u0e01\u0e0e (\u0e21\u0e35\u0e1b\u0e23\u0e30\u0e42\u0e22\u0e0a\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21 mirc) # #2.0.7.0 # security.certtruster.title=\u0e40\u0e15\u0e37\u0e2d\u0e19\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e04\u0e27\u0e32\u0e21\u0e1b\u0e25\u0e2d\u0e14\u0e20\u0e31\u0e22 security.certtruster.intro=\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e2d\u0e2d\u0e01\u0e42\u0e14\u0e22\u0e1a\u0e23\u0e34\u0e29\u0e31\u0e17\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e44\u0e21\u0e48\u0e40\u0e0a\u0e37\u0e48\u0e2d security.certtruster.resource=\u0e17\u0e23\u0e31\u0e1e\u0e22\u0e32\u0e01\u0e23: security.certtruster.issuedto=\u0e2d\u0e2d\u0e01\u0e43\u0e2b\u0e49: security.certtruster.issuedby=\u0e2d\u0e2d\u0e01\u0e42\u0e14\u0e22: security.certtruster.prompt=\u0e04\u0e38\u0e13\u0e08\u0e30\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e2b\u0e23\u0e37\u0e2d\u0e44\u0e21\u0e48 ? security.certtruster.yes=\u0e43\u0e0a\u0e48 security.certtruster.no=\u0e44\u0e21\u0e48 ConfigView.section.tracker.torrentsperpage=\u0e01\u0e35\u0e48 torrents \u0e15\u0e48\u0e2d\u0e2b\u0e19\u0e49\u0e32 ? [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] MainWindow.menu.file.share=&\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 MainWindow.menu.file.share.file=&\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25... MainWindow.menu.file.share.dir=\u0e41&\u0e1f\u0e49\u0e21... MainWindow.menu.file.share.dircontents=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e43\u0e19&\u0e41\u0e1f\u0e49\u0e21... MainWindow.menu.file.share.dircontentsrecursive=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e43\u0e19\u0e41\u0e1f\u0e49\u0e21 (&Recursive)... MainWindow.dialog.share.sharefile=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e08\u0e30\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 MainWindow.dialog.share.sharedir=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e41\u0e1f\u0e49\u0e21\u0e17\u0e35\u0e48\u0e08\u0e30\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 MainWindow.dialog.share.sharedircontents=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e41\u0e1f\u0e49\u0e21\u0e17\u0e35\u0e48\u0e08\u0e30\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 globalmanager.download.remove.veto=\u0e1b\u0e0f\u0e34\u0e40\u0e2a\u0e18\u0e01\u0e32\u0e23\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01 plugin.sharing.download.remove.veto=\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e19\u0e35\u0e49\u0e40\u0e1b\u0e47\u0e19\u0e1c\u0e25\u0e02\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e17\u0e23\u0e31\u0e1e\u0e22\u0e32\u0e01\u0e23\n\u0e01\u0e32\u0e23\u0e40\u0e2d\u0e32\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e2d\u0e2d\u0e01\u0e40\u0e1b\u0e47\u0e19\u0e01\u0e32\u0e23\u0e40\u0e2d\u0e32\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e2d\u0e2d\u0e01: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=\u0e2b\u0e25\u0e31\u0e01 ConfigView.section.tracker.web=\u0e40\u0e27\u0e47\u0e1a ConfigView.label.prioritizefirstpiece=\u0e43\u0e2b\u0e49\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e01\u0e31\u0e1a\u0e2a\u0e48\u0e27\u0e19\u0e15\u0e49\u0e19\u0e02\u0e2d\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 ConfigView.label.prioritizefirstpiece.tooltip=\u0e1e\u0e22\u0e32\u0e22\u0e32\u0e21\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e2a\u0e48\u0e27\u0e19\u0e41\u0e23\u0e01\u0e02\u0e2d\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e01\u0e48\u0e2d\u0e19\n\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e2a\u0e19\u0e31\u0e1a\u0e2a\u0e19\u0e38\u0e19\u0e01\u0e32\u0e23\u0e14\u0e39\u0e01\u0e48\u0e2d\u0e19\u0e25\u0e48\u0e27\u0e07\u0e2b\u0e19\u0e49\u0e32 ConfigView.section.file.confirm_data_delete=\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e25\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 ConfigView.section.file.confirm_data_delete.tooltip=\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e01\u0e32\u0e23\u0e25\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e43\u0e0a\u0e49 '\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01 \u0e41\u0e25\u0e30\u0e25\u0e1a...' TrayWindow.menu.startalldownloads=\u0e40\u0e23\u0e34\u0e48\u0e21\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e17\u0e38\u0e01\u0e2d\u0e31\u0e19 SystemTray.menu.startalltransfers=\u0e40\u0e23\u0e34\u0e48\u0e21\u0e01\u0e32\u0e23\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 sharing.progress.title=\u0e04\u0e27\u0e32\u0e21\u0e01\u0e49\u0e32\u0e27\u0e2b\u0e19\u0e49\u0e32\u0e43\u0e19\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 sharing.progress.hide=\u0e0b\u0e48\u0e2d\u0e19 MainWindow.menu.view.myshares=\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e02\u0e2d\u0e07\u0e09\u0e31\u0e19 MySharesView.title.full=\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e02\u0e2d\u0e07\u0e09\u0e31\u0e19 MySharesView.name=\u0e0a\u0e37\u0e48\u0e2d MySharesView.type=\u0e1b\u0e23\u0e30\u0e40\u0e20\u0e17 MySharesView.type.file=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 MySharesView.type.dir=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 MySharesView.type.dircontents=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e43\u0e19\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 MySharesView.type.dircontentsrecursive=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e43\u0e19\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 (recursive) MySharesView.menu.remove=\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01 ConfigView.section.tracker.extensions=\u0e2a\u0e01\u0e38\u0e25 ConfigView.section.tracker.sendpeerids=\u0e2a\u0e48\u0e07\u0e25\u0e31\u0e01\u0e29\u0e13\u0e30\u0e02\u0e2d\u0e07 peer\u0e43\u0e2b\u0e49\u0e1c\u0e39\u0e49\u0e17\u0e35\u0e48\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 ConfigView.section.tracker.enableudp=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19 UDP tracker \u0e42\u0e1b\u0e23\u0e42\u0e15\u0e04\u0e2d\u0e25 plugin.sharing.torrent.remove.veto=\u0e01\u0e32\u0e23\u0e25\u0e07\u0e17\u0e30\u0e40\u0e1a\u0e35\u0e22\u0e19 tracker \u0e19\u0e35\u0e49\u0e40\u0e1b\u0e47\u0e19\u0e1c\u0e25\u0e02\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e17\u0e23\u0e31\u0e1e\u0e22\u0e32\u0e01\u0e23\n\u0e01\u0e32\u0e23\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e1b\u0e47\u0e19\u0e01\u0e32\u0e23\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e44\u0e21\u0e48\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01\u0e44\u0e14\u0e49\u0e16\u0e49\u0e32\u0e22\u0e31\u0e07\u0e44\u0e21\u0e48\u0e2b\u0e22\u0e38\u0e14 plugin.sharing.remove.veto=\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e19\u0e35\u0e49\u0e40\u0e1b\u0e47\u0e19\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e22\u0e48\u0e2d\u0e22\u0e02\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 '\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e43\u0e19\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07' \u0e44\u0e21\u0e48\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e25\u0e1a\u0e44\u0e14\u0e49\n \u0e25\u0e1a\u0e17\u0e35\u0e48\u0e17\u0e35\u0e48\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 GeneralView.label.hash.tooltip=\u0e04\u0e25\u0e34\u0e01\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e2a\u0e33\u0e40\u0e19\u0e32\u0e27\u0e19\u0e44\u0e1b\u0e17\u0e35\u0e48 clipboard ConfigView.section.tracker.maxpeersreturned=peers \u0e15\u0e2d\u0e1a\u0e01\u0e25\u0e31\u0e1a\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] ConfigView.label.serverport=\u0e23\u0e31\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e08\u0e32\u0e01 TCP \u0e1e\u0e2d\u0e23\u0e4c\u0e15 ConfigView.label.serverport.tooltip=Port \u0e15\u0e49\u0e2d\u0e07\u0e2d\u0e22\u0e39\u0e48\u0e23\u0e30\u0e2b\u0e27\u0e48\u0e32\u0e07\u0e0a\u0e48\u0e27\u0e07 1-65535 , \u0e41\u0e25\u0e30\u0e44\u0e21\u0e48\u0e43\u0e0a\u0e48 6880 \u0e17\u0e35\u0e48\u0e40\u0e2d\u0e32\u0e44\u0e27\u0e49\u0e43\u0e0a\u0e49\u0e01\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e20\u0e32\u0e22\u0e43\u0e19\u0e02\u0e2d\u0e07 Vuze \u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19. configureWizard.nat.server.tcp_listen_port=\u0e23\u0e31\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 TCP \u0e1e\u0e2d\u0e23\u0e4c\u0e15 ConfigView.section.sharing=\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 ConfigView.section.sharing.usessl=\u0e43\u0e0a\u0e49 SSL \u0e43\u0e19\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e17\u0e23\u0e31\u0e1e\u0e22\u0e32\u0e01\u0e23 (\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07 Tracker) ConfigView.section.style.dropdiraction=\u0e01\u0e32\u0e23\u0e01\u0e23\u0e30\u0e17\u0e33 Drag \u0e41\u0e25\u0e30 Drop \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e17\u0e35\u0e48 ConfigView.section.style.dropdiraction.opentorrents=\u0e40\u0e1b\u0e34\u0e14 Torrents ConfigView.section.style.dropdiraction.sharefolder=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 ConfigView.section.style.dropdiraction.sharefoldercontents=\u0e2a\u0e34\u0e48\u0e07\u0e17\u0e35\u0e48\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 # # 2.0.7.x # Categories.all=\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 Categories.uncategorized=\u0e44\u0e21\u0e48\u0e41\u0e1a\u0e48\u0e07\u0e2b\u0e21\u0e27\u0e14\u0e2b\u0e21\u0e39\u0e48 CategoryAddWindow.message=\u0e43\u0e2a\u0e48\u0e0a\u0e37\u0e48\u0e2d\u0e2b\u0e21\u0e27\u0e14\u0e2b\u0e21\u0e39\u0e48\u0e43\u0e2b\u0e21\u0e48 CategoryAddWindow.title=\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e2b\u0e21\u0e27\u0e14\u0e2b\u0e21\u0e39\u0e48\u0e43\u0e2b\u0e21\u0e48 ConfigView.label.autoSeedingIgnoreInfo=torrents \u0e17\u0e35\u0e48\u0e16\u0e39\u0e01\u0e40\u0e1e\u0e34\u0e01\u0e40\u0e09\u0e22\u0e22\u0e49\u0e32\u0e22\u0e44\u0e1b\u0e25\u0e48\u0e32\u0e07\u0e2a\u0e38\u0e14\u0e02\u0e2d\u0e07\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 seeding \u0e41\u0e25\u0e30\u0e44\u0e21\u0e48\u0e40\u0e23\u0e34\u0e48\u0e21\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 \u0e01\u0e0f\u0e01\u0e32\u0e23\u0e25\u0e30\u0e40\u0e25\u0e22\u0e08\u0e30\u0e44\u0e21\u0e48\u0e43\u0e0a\u0e49\u0e01\u0e31\u0e1a torrents \u0e17\u0e35\u0e48\u0e2d\u0e22\u0e39\u0e48\u0e43\u0e19\u0e40\u0e01\u0e13\u0e11\u0e4c\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e41\u0e23\u0e01 \u0e40\u0e27\u0e49\u0e19\u0e41\u0e15\u0e48\u0e27\u0e48\u0e32\u0e08\u0e30\u0e40\u0e1b\u0e47\u0e19\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e2d\u0e37\u0e48\u0e19, \u0e43\u0e0a\u0e49\u0e04\u0e48\u0e32 0 \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e1b\u0e34\u0e14\u0e01\u0e0e ConfigView.label.directory=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 ConfigView.label.disconnetseed.tooltip=\u0e40\u0e21\u0e37\u0e48\u0e2d seeding torrent, \u0e15\u0e31\u0e14\u0e01\u0e32\u0e23\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e15\u0e48\u0e2d\u0e01\u0e31\u0e1a clients \u0e17\u0e35\u0e48 seeding.\n\u0e1e\u0e27\u0e01\u0e40\u0e02\u0e32\u0e44\u0e21\u0e48\u0e08\u0e33\u0e40\u0e1b\u0e47\u0e19\u0e15\u0e49\u0e2d\u0e07\u0e40\u0e23\u0e35\u0e22\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e08\u0e32\u0e01\u0e04\u0e38\u0e13. ConfigView.label.ignoreCase=\u0e01\u0e23\u0e13\u0e35\u0e25\u0e30\u0e40\u0e27\u0e49\u0e19 ConfigView.label.ignoreSeeds=\u0e25\u0e30\u0e40\u0e27\u0e49\u0e19 torrents \u0e17\u0e35\u0e48\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e19\u0e49\u0e2d\u0e22 ConfigView.label.importdirectory=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e01\u0e32\u0e23\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32 ConfigView.label.minPeersToBoostNoSeeds.tooltip=torrents \u0e43\u0e14\u0e01\u0e47\u0e15\u0e32\u0e21\u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e21\u0e35 seeds \u0e41\u0e25\u0e30 peers \u0e19\u0e49\u0e2d\u0e22\u0e01\u0e27\u0e48\u0e32\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e23\u0e30\u0e1a\u0e38\n\u0e08\u0e30\u0e16\u0e39\u0e01\u0e22\u0e49\u0e32\u0e22\u0e44\u0e1b\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e25\u0e48\u0e32\u0e07 ConfigView.label.minPeersToBoostNoSeeds=\u0e25\u0e14\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e43\u0e19\u0e01\u0e32\u0e23 Seeding \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a torrents \u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e21\u0e35 seeds \u0e41\u0e25\u0e30\u0e15\u0e33\u0e01\u0e27\u0e48\u0e32 ConfigView.label.minSeedingTime.tooltip=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e43\u0e19\u0e01\u0e32\u0e23 Seeding \u0e1c\u0e31\u0e19\u0e1c\u0e27\u0e19\u0e44\u0e14\u0e49\u0e1a\u0e48\u0e2d\u0e22\u0e04\u0e23\u0e31\u0e49\u0e07\u0e43\u0e19\u0e40\u0e27\u0e25\u0e32\u0e2a\u0e31\u0e49\u0e19\u0e46, \u0e0b\u0e36\u0e48\u0e07\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e17\u0e33\u0e43\u0e2b\u0e49 torrent \u0e40\u0e23\u0e34\u0e48\u0e21\u0e15\u0e49\u0e19\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34\u0e43\u0e19\u0e1a\u0e32\u0e07\u0e04\u0e23\u0e31\u0e49\u0e07, \u0e41\u0e25\u0e49\u0e27\u0e01\u0e47\u0e16\u0e39\u0e01\u0e2b\u0e22\u0e38\u0e14 \u0e41\u0e25\u0e30\u0e22\u0e49\u0e32\u0e22\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e17\u0e31\u0e19\u0e17\u0e35\n\u0e2a\u0e34\u0e48\u0e07\u0e19\u0e35\u0e49\u0e08\u0e30\u0e25\u0e14\u0e1b\u0e31\u0e0d\u0e2b\u0e32\u0e42\u0e14\u0e22\u0e01\u0e32\u0e23\u0e1a\u0e31\u0e07\u0e04\u0e31\u0e1a\u0e43\u0e2b\u0e49 seeding \u0e08\u0e19\u0e16\u0e36\u0e07\u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48\u0e01\u0e33\u0e2b\u0e19\u0e14 \u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e2b\u0e22\u0e38\u0e14\u0e21\u0e31\u0e19\u0e44\u0e14\u0e49\u0e14\u0e49\u0e27\u0e22\u0e15\u0e19\u0e40\u0e2d\u0e07\u0e16\u0e49\u0e32\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23 ConfigView.label.minSeedingTime=\u0e40\u0e27\u0e25\u0e32\u0e43\u0e19\u0e01\u0e32\u0e23 seeding \u0e2d\u0e22\u0e48\u0e32\u0e07\u0e19\u0e49\u0e2d\u0e22\u0e40\u0e1b\u0e47\u0e19\u0e27\u0e34\u0e19\u0e32\u0e17\u0e35 ConfigView.label.minSpeedForActiveDL.tooltip=\u0e0a\u0e48\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e16\u0e39\u0e01\u0e43\u0e0a\u0e49\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e2a\u0e21\u0e2d\n\u0e2b\u0e25\u0e31\u0e07 torrent \u0e17\u0e35\u0e48\u0e22\u0e31\u0e07\u0e44\u0e21\u0e48\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e40\u0e23\u0e34\u0e48\u0e21 ConfigView.label.minSpeedForActiveDL=\u0e44\u0e21\u0e48\u0e19\u0e31\u0e1a torrent \u0e27\u0e48\u0e32\u0e43\u0e0a\u0e49\u0e0a\u0e48\u0e2d\u0e07\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e16\u0e49\u0e32\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e15\u0e33\u0e01\u0e27\u0e48\u0e32 ConfigView.label.queue.debuglog=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e01\u0e32\u0e23 debug ConfigView.label.queue.debuglog.info=\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e01\u0e32\u0e23\u0e40\u0e23\u0e35\u0e22\u0e07\u0e25\u0e33\u0e14\u0e31\u0e1a\u0e02\u0e2d\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e01\u0e32\u0e23 debug \u0e43\u0e19\u0e04\u0e2d\u0e19\u0e42\u0e0b\u0e25/\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\n\u0e41\u0e21\u0e49\u0e27\u0e48\u0e32\u0e40\u0e02\u0e49\u0e32\u0e23\u0e2b\u0e31\u0e2a, \u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e01\u0e32\u0e23 debug \u0e08\u0e30\u0e1a\u0e2d\u0e01\u0e04\u0e38\u0e13\u0e16\u0e36\u0e07\u0e2a\u0e20\u0e32\u0e1e torrents \u0e41\u0e25\u0e30\u0e17\u0e33\u0e44\u0e21\u0e21\u0e31\u0e19\u0e16\u0e36\u0e07/\u0e44\u0e21\u0e48 \u0e40\u0e23\u0e34\u0e48\u0e21/\u0e43\u0e2b\u0e49\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d ConfigView.label.queue.minQueueingShareRatio=\u0e44\u0e21\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e40\u0e23\u0e35\u0e22\u0e07\u0e25\u0e33\u0e14\u0e31\u0e1a\u0e2b\u0e23\u0e37\u0e2d\u0e2b\u0e22\u0e38\u0e14 torrent \u0e08\u0e19\u0e01\u0e27\u0e48\u0e32\u0e08\u0e30\u0e16\u0e36\u0e07\u0e2a\u0e31\u0e14\u0e2a\u0e48\u0e27\u0e19\u0e17\u0e35\u0e48\u0e01\u0e33\u0e2b\u0e19\u0e14 ConfigView.label.ratio=\u0e2a\u0e31\u0e14\u0e2a\u0e48\u0e27\u0e19 ConfigView.label.removeOnStop=\u0e40\u0e2d\u0e32 torrent \u0e2d\u0e2d\u0e01\u0e08\u0e32\u0e01\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d\u0e2b\u0e25\u0e31\u0e07\u0e01\u0e32\u0e23\u0e2b\u0e22\u0e38\u0e14\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 ConfigView.label.savedirectory=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 ConfigView.label.seeding.autoReposition.tooltip=\u0e16\u0e49\u0e32\u0e40\u0e1b\u0e34\u0e14\u0e43\u0e0a\u0e49, \u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e02\u0e2d\u0e07 torrents (\u0e41\u0e16\u0e27 '#') \u0e08\u0e30\u0e16\u0e39\u0e01\u0e1b\u0e23\u0e31\u0e1a\u0e43\u0e2b\u0e49\u0e40\u0e02\u0e49\u0e32\u0e01\u0e31\u0e1a\u0e25\u0e33\u0e14\u0e31\u0e1a\u0e01\u0e32\u0e23 Seeding \n\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e17\u0e33\u0e07\u0e32\u0e19\u0e19\u0e35\u0e49\u0e21\u0e35\u0e1b\u0e23\u0e30\u0e42\u0e22\u0e0a\u0e19\u0e4c\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e04\u0e38\u0e13\u0e44\u0e21\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e14\u0e39\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02\u0e01\u0e32\u0e23 Seeding Rank, \u0e41\u0e15\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e23\u0e39\u0e49\u0e23\u0e30\u0e14\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e02\u0e2d\u0e07 torrents \u0e17\u0e35\u0e48\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e08\u0e30\u0e40\u0e23\u0e34\u0e48\u0e21 ConfigView.label.seeding.autoReposition=\u0e40\u0e23\u0e35\u0e22\u0e07\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 torrents \u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 \u0e42\u0e14\u0e22\u0e43\u0e0a\u0e49\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e02\u0e2d\u0e07\u0e01\u0e32\u0e23 Seeding ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u0e1a\u0e48\u0e2d\u0e22\u0e04\u0e23\u0e31\u0e49\u0e07, torrents \u0e17\u0e35\u0e48\u0e21\u0e35 seed \u0e19\u0e49\u0e2d\u0e22 \u0e41\u0e25\u0e30 peer \u0e21\u0e32\u0e01\u0e1a\u0e32\u0e07\u0e17\u0e35\u0e2d\u0e32\u0e08\u0e08\u0e30\u0e44\u0e21\u0e48\u0e21\u0e35\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e23\u0e30\u0e2b\u0e27\u0e48\u0e32\u0e07 peers\n\u0e14\u0e31\u0e07\u0e19\u0e31\u0e49\u0e19, \u0e04\u0e38\u0e13\u0e2d\u0e32\u0e08\u0e08\u0e30\u0e44\u0e21\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e01\u0e0e\u0e01\u0e32\u0e23 seeding \u0e41\u0e2a\u0e14\u0e07\u0e27\u0e48\u0e32\u0e21\u0e35\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c (\u0e41\u0e25\u0e30\u0e14\u0e31\u0e07\u0e19\u0e31\u0e49\u0e19\u0e25\u0e14\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e42\u0e14\u0e22\u0e44\u0e21\u0e48\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07) ConfigView.label.seeding.fakeFullCopySeedStart=\u0e41\u0e15\u0e48\u0e40\u0e09\u0e1e\u0e32\u0e30 torrents \u0e17\u0e35\u0e48\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e15\u0e33 ConfigView.label.seeding.ignore=\u0e25\u0e30\u0e40\u0e27\u0e49\u0e19\u0e01\u0e0f ConfigView.label.seeding.ignore0Peers=\u0e25\u0e30\u0e40\u0e27\u0e49\u0e19 torrents \u0e17\u0e35\u0e48\u0e21\u0e35 0 peers ConfigView.label.seeding.ignoreRatioPeers=\u0e25\u0e30\u0e40\u0e27\u0e49\u0e19 torrents\u0e17\u0e35\u0e48\u0e21\u0e35\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e15\u0e33 1 seed \u0e15\u0e48\u0e2d\u0e17\u0e38\u0e01\u0e46 ConfigView.label.seeding.ignoreShareRatio=\u0e25\u0e30\u0e40\u0e27\u0e49\u0e19 torrents \u0e17\u0e35\u0e48\u0e21\u0e35\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07 ConfigView.label.seeding.ignore.header.evenFirstPriority=\u0e25\u0e30\u0e40\u0e27\u0e49\u0e19 torrent \u0e41\u0e21\u0e49\u0e27\u0e48\u0e32\n\u0e43\u0e0a\u0e49\u0e01\u0e0e\u0e02\u0e2d\u0e07\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e41\u0e23\u0e01 ConfigView.label.seeding.ignore.header.rule=\u0e01\u0e0e ConfigView.label.seeding.firstPriority.info=torrents \u0e17\u0e35\u0e48\u0e21\u0e35\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e17\u0e35\u0e48\u0e2a\u0e38\u0e14\u0e08\u0e30\u0e2d\u0e22\u0e39\u0e48\u0e1a\u0e19\u0e2a\u0e38\u0e14\u0e02\u0e2d\u0e07\u0e25\u0e33\u0e14\u0e31\u0e1a\u0e41\u0e25\u0e30\u0e08\u0e30\u0e44\u0e21\u0e48\u0e16\u0e39\u0e01\u0e2b\u0e22\u0e38\u0e14 \u0e2b\u0e23\u0e37\u0e2d\u0e08\u0e31\u0e14\u0e2d\u0e31\u0e1a\u0e14\u0e31\u0e1a\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 \u0e41\u0e25\u0e30\u0e22\u0e31\u0e07\u0e08\u0e30\u0e44\u0e14\u0e49\u0e43\u0e0a\u0e49\u0e0a\u0e48\u0e2d\u0e07\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e16\u0e49\u0e32\u0e08\u0e33\u0e40\u0e1b\u0e47\u0e19 ConfigView.label.seeding.firstPriority.FP=\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e41\u0e23\u0e01 ConfigView.label.seeding.firstPriority=\u0e43\u0e2b\u0e49\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e41\u0e01\u0e48 torrents \u0e17\u0e35\u0e48 ConfigView.label.seeding.firstPriority.following=\u0e14\u0e31\u0e07\u0e19\u0e35\u0e49: ConfigView.label.seeding.firstPriority.shareRatio=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e15\u0e33\u0e01\u0e27\u0e48\u0e32 ConfigView.label.seeding.firstPriority.seedingMinutes=\u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48\u0e43\u0e0a\u0e49\u0e44\u0e1b\u0e2b\u0e25\u0e31\u0e07\u0e08\u0e32\u0e01\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e08\u0e32\u0e01\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e1b\u0e47\u0e19 seeding ConfigView.label.seeding.firstPriority.DLMinutes=\u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48\u0e43\u0e0a\u0e49\u0e44\u0e1b\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14\u0e15\u0e31\u0e49\u0e07\u0e41\u0e15\u0e48\u0e40\u0e23\u0e34\u0e48\u0e21\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 ConfigView.label.seeding.numPeersAsFullCopy.tooltip=\u0e41\u0e2a\u0e14\u0e07\u0e27\u0e48\u0e32\u0e21\u0e35\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e17\u0e38\u0e01\u0e15\u0e48\u0e2d X peers, \u0e04\u0e38\u0e13\u0e25\u0e14\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 torrents \u0e17\u0e35\u0e48\u0e21\u0e35\u0e08\u0e33\u0e19\u0e27\u0e19 peer \u0e21\u0e32\u0e01\n\u0e2a\u0e48\u0e27\u0e19\u0e43\u0e2b\u0e0d\u0e48, torrents \u0e17\u0e35\u0e48\u0e21\u0e35\u0e08\u0e33\u0e19\u0e27\u0e19 peer \u0e21\u0e32\u0e01\u0e01\u0e47\u0e21\u0e35\u0e01\u0e32\u0e23\u0e2a\u0e37\u0e48\u0e2d\u0e2a\u0e32\u0e23\u0e01\u0e31\u0e19\u0e21\u0e32\u0e01\n\u0e19\u0e35\u0e48\u0e08\u0e30\u0e44\u0e21\u0e48\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e01\u0e32\u0e23\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25 '# \u0e02\u0e2d\u0e07 seeds' ConfigView.label.seeding.numPeersAsFullCopy=\u0e41\u0e2a\u0e14\u0e07\u0e27\u0e48\u0e32\u0e21\u0e35\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e17\u0e38\u0e01\u0e46\n(0 :\u0e44\u0e21\u0e48\u0e41\u0e2a\u0e14\u0e07) ConfigView.label.seeding.preferLargerSwarms.tooltip=\u0e16\u0e49\u0e32\u0e04\u0e38\u0e13\u0e40\u0e19\u0e49\u0e19\u0e01\u0e32\u0e23 seeding torrents \u0e17\u0e35\u0e48\u0e21\u0e35 peers "\u0e22\u0e31\u0e07\u0e42\u0e2b\u0e25\u0e14\u0e44\u0e21\u0e48\u0e40\u0e2a\u0e23\u0e47\u0e08", \u0e01\u0e32\u0e23\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e17\u0e35\u0e48\u0e21\u0e35 swarms \u0e21\u0e32\u0e01\u0e01\u0e27\u0e48\u0e32\u0e08\u0e30\u0e40\u0e1b\u0e47\u0e19\u0e01\u0e32\u0e23\u0e14\u0e35\n\u0e16\u0e49\u0e32\u0e04\u0e38\u0e13\u0e40\u0e19\u0e49\u0e19\u0e01\u0e32\u0e23 seeding torrents \u0e21\u0e35\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e21\u0e32\u0e01, \u0e01\u0e32\u0e23\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e17\u0e35\u0e48\u0e21\u0e35 swarms \u0e19\u0e49\u0e2d\u0e22\u0e01\u0e27\u0e48\u0e32\u0e08\u0e30\u0e40\u0e1b\u0e47\u0e19\u0e01\u0e32\u0e23\u0e14\u0e35 ConfigView.label.seeding.preferLargerSwarms=\u0e40\u0e21\u0e37\u0e48\u0e2d torrents \u0e21\u0e35\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e40\u0e14\u0e35\u0e22\u0e27\u0e01\u0e31\u0e19, \u0e40\u0e25\u0e37\u0e2d\u0e01\u0e17\u0e35\u0e48\u0e21\u0e35 swarms \u0e21\u0e32\u0e01\u0e01\u0e27\u0e48\u0e32 ConfigView.label.seeding.rankType.none.tooltip=\u0e01\u0e32\u0e23\u0e40\u0e23\u0e35\u0e22\u0e07\u0e25\u0e33\u0e14\u0e31\u0e1a\u0e1a\u0e19\u0e41\u0e16\u0e27 # ConfigView.label.seeding.rankType.none=\u0e44\u0e21\u0e48\u0e21\u0e35 ConfigView.label.seeding.rankType.peerSeed.options=\u0e15\u0e31\u0e27\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19 Seeds:Peers ConfigView.label.seeding.rankType.peerSeed.tooltip=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19\u0e21\u0e32\u0e01 = \u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e21\u0e32\u0e01 ConfigView.label.seeding.rankType.peerSeed=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19 Peers:Seed ConfigView.label.seeding.rankType.seed.fallback=\u0e16\u0e2d\u0e22\u0e01\u0e25\u0e31\u0e1a\u0e44\u0e1b\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19 Peers:Seed \u0e2b\u0e25\u0e31\u0e07\u0e08\u0e32\u0e01\n(0 : \u0e44\u0e21\u0e48\u0e16\u0e2d\u0e22\u0e01\u0e25\u0e31\u0e1a) ConfigView.label.seeding.rankType.seed.options=\u0e15\u0e31\u0e27\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e01\u0e32\u0e23\u0e19\u0e31\u0e1a\u0e40\u0e09\u0e1e\u0e32\u0e30 Seed \u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19 ConfigView.label.seeding.rankType.seed.tooltip=Seeds \u0e19\u0e49\u0e2d\u0e22 = \u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e21\u0e32\u0e01 ConfigView.label.seeding.rankType.seed=\u0e19\u0e31\u0e1a\u0e40\u0e09\u0e1e\u0e32\u0e30 Seed ConfigView.label.seeding.rankType.timedRotation.tooltip=torrents \u0e17\u0e35\u0e48\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e17\u0e38\u0e01\u0e2d\u0e31\u0e19\u0e43\u0e19\u0e25\u0e33\u0e14\u0e31\u0e1a\u0e08\u0e30\u0e16\u0e39\u0e01\u0e22\u0e49\u0e32\u0e22\u0e44\u0e1b\u0e17\u0e33\u0e07\u0e32\u0e19\u0e41\u0e1a\u0e1a seeding\n\u0e0a\u0e48\u0e27\u0e07\u0e40\u0e27\u0e25\u0e32\u0e43\u0e19\u0e01\u0e32\u0e23 seeding \u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07\u0e43\u0e19 '\u0e40\u0e27\u0e25\u0e32\u0e43\u0e19\u0e01\u0e32\u0e23 Seeding \u0e2d\u0e22\u0e48\u0e32\u0e07\u0e19\u0e49\u0e2d\u0e22' ConfigView.label.seeding.rankType.timedRotation=\u0e40\u0e27\u0e25\u0e32\u0e43\u0e19\u0e01\u0e32\u0e23\u0e2b\u0e21\u0e38\u0e19\u0e40\u0e27\u0e35\u0e22\u0e19 ConfigView.label.seeding.rankType.tooltip=torrents \u0e17\u0e35\u0e48\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e08\u0e30\u0e40\u0e23\u0e34\u0e48\u0e21\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 \u0e40\u0e21\u0e37\u0e48\u0e2d torrent \u0e2d\u0e37\u0e48\u0e19\u0e44\u0e14\u0e49\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e2a\u0e39\u0e07\u0e01\u0e27\u0e48\u0e32 \u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e17\u0e35\u0e48\u0e15\u0e33\u0e01\u0e27\u0e48\u0e32\u0e08\u0e30\u0e2b\u0e22\u0e38\u0e14\u0e41\u0e25\u0e30\u0e01\u0e25\u0e31\u0e1a\u0e2d\u0e22\u0e39\u0e48\u0e43\u0e19\u0e25\u0e33\u0e14\u0e31\u0e1a\n \u0e40\u0e09\u0e1e\u0e32\u0e30 torrents \u0e43\u0e19\u0e25\u0e33\u0e14\u0e31\u0e1a\u0e08\u0e30\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e40\u0e23\u0e34\u0e48\u0e21\u0e15\u0e49\u0e19\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34\u0e44\u0e14\u0e49 torrents \u0e17\u0e35\u0e48\u0e2b\u0e22\u0e38\u0e14\u0e08\u0e30\u0e44\u0e21\u0e48\u0e40\u0e23\u0e34\u0e48\u0e21\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 ConfigView.label.seeding.rankType=\u0e08\u0e31\u0e14\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 torrents \u0e17\u0e35\u0e48\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e40\u0e23\u0e34\u0e48\u0e21\u0e15\u0e49\u0e19\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 \u0e14\u0e39\u0e08\u0e32\u0e01: ConfigView.label.stopAfterMinutes=\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e1b\u0e23\u0e31\u0e1a\u0e44\u0e1b\u0e22\u0e31\u0e07 seeding, \u0e2b\u0e22\u0e38\u0e14\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e16\u0e36\u0e07\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e40\u0e27\u0e25\u0e32 ConfigView.label.switchpriority.tooltip=\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e19\u0e49\u0e2d\u0e22\u0e25\u0e14\u0e1b\u0e23\u0e34\u0e21\u0e32\u0e13\u0e43\u0e19\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e2a\u0e39\u0e48\u0e2d\u0e34\u0e19\u0e40\u0e15\u0e2d\u0e40\u0e19\u0e47\u0e15 ConfigView.pluginlist.info=\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e14\u0e31\u0e07\u0e01\u0e25\u0e48\u0e32\u0e27\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e23\u0e30\u0e1a\u0e38\u0e41\u0e25\u0e49\u0e27. \u0e1a\u0e32\u0e07\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e2d\u0e32\u0e08\u0e44\u0e21\u0e48\u0e21\u0e35\u0e41\u0e16\u0e1a\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07 ConfigView.pluginlist.noplugins=\u0e44\u0e21\u0e48\u0e1e\u0e1a\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21 ConfigView.section.pluginslist=\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d ConfigView.section.queue.seeding.autoStarting=\u0e40\u0e23\u0e34\u0e48\u0e21\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 ConfigView.section.queue.seeding.ignore=\u0e25\u0e30\u0e40\u0e27\u0e49\u0e19\u0e01\u0e0f ConfigView.section.queue.seeding.firstPriority=\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e41\u0e23\u0e01 ConfigView.section.queue.main=\u0e2b\u0e25\u0e31\u0e01 ConfigView.section.queue=\u0e25\u0e33\u0e14\u0e31\u0e1a ConfigView.text.all=\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 ConfigView.text.hours=\u0e0a\u0e31\u0e48\u0e27\u0e42\u0e21\u0e07 ConfigView.text.ignoreRule=\u0e25\u0e30\u0e40\u0e25\u0e22\u0e01\u0e0e ConfigView.text.ignore=\u0e25\u0e30\u0e40\u0e25\u0e22 ConfigView.text.minutes=\u0e19\u0e32\u0e17\u0e35 ConfigView.text.neverIgnore=\u0e44\u0e21\u0e48\u0e25\u0e30\u0e40\u0e25\u0e22 ConfigView.text.any=\u0e2d\u0e31\u0e19\u0e44\u0e2b\u0e19\u0e01\u0e47\u0e44\u0e14\u0e49 DownloadManager.error.datamissing=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e2a\u0e39\u0e0d\u0e2b\u0e32\u0e22 MainWindow.menu.file.open.torrentforseeding=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 .torrent(\u0e40\u0e1e\u0e37\u0e48\u0e2d Seeding) MainWindow.menu.language.refresh=&\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25\u0e43\u0e2b\u0e21\u0e48 ManagerItem.forced=\u0e1a\u0e31\u0e07\u0e04\u0e31\u0e1a ManagerItem.queued=\u0e25\u0e33\u0e14\u0e31\u0e1a MySeedersView.header=\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c/Seeding Torrents TableColumn.header.availability.info=# \u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e33\u0e40\u0e19\u0e32\u0e40\u0e15\u0e47\u0e21\u0e17\u0e35\u0e48\u0e40\u0e2b\u0e47\u0e19 TableColumn.header.availability=\u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48 TableColumn.header.category=\u0e1b\u0e23\u0e30\u0e40\u0e20\u0e17 MyTorrentsView.header=Torrents \u0e17\u0e35\u0e48\u0e22\u0e31\u0e07\u0e44\u0e21\u0e48\u0e40\u0e2a\u0e23\u0e47\u0e08/\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 TableColumn.header.maxuploads=# \u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 MyTorrentsView.menu.category.delete=&\u0e25\u0e1a\u0e2b\u0e21\u0e27\u0e14\u0e2b\u0e21\u0e39\u0e48 MyTorrentsView.menu.forceStart=&\u0e1a\u0e31\u0e07\u0e04\u0e31\u0e1a\u0e40\u0e23\u0e34\u0e48\u0e21 MyTorrentsView.menu.queue=&\u0e25\u0e33\u0e14\u0e31\u0e1a MyTorrentsView.menu.setCategory.add=&\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e1b\u0e23\u0e30\u0e40\u0e20\u0e17.. MyTorrentsView.menu.setCategory=\u0e15\u0e31\u0e49\u0e07\u0e1b\u0e23\u0e30\u0e40\u0e20\u0e17 TableColumn.header.savepath=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 TableColumn.header.SeedingRank=\u0e25\u0e33\u0e14\u0e31\u0e1a\u0e01\u0e32\u0e23 Seeding TableColumn.header.totalspeed.info=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14\u0e02\u0e2d\u0e07\u0e17\u0e38\u0e01 peers \u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e14\u0e49\u0e27\u0e22 TableColumn.header.totalspeed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e42\u0e14\u0e22\u0e23\u0e27\u0e21 splash.initializePlugins=\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e02\u0e31\u0e49\u0e19\u0e15\u0e49\u0e19 StartStopRules.SPratioMet=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19 S:P OK StartStopRules.shareRatioMet=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 Ok StartStopRules.waiting=\u0e23\u0e2d StartStopRules.firstPriority=\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e41\u0e23\u0e01 ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\u0e2a\u0e34\u0e48\u0e07\u0e17\u0e35\u0e48\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 (\u0e2d\u0e31\u0e01\u0e29\u0e23\u0e43\u0e2b\u0e21\u0e48) DownloadManager.error.unabletostartserver=\u0e44\u0e21\u0e48\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e40\u0e23\u0e34\u0e48\u0e21 Server - \u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e02\u0e2d\u0e07\u0e1e\u0e2d\u0e23\u0e4c\u0e15 / \u0e01\u0e32\u0e23\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e02\u0e2d\u0e07 firewall \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e17\u0e35\u0e48\u0e1b\u0e0f\u0e34\u0e1a\u0e31\u0e15\u0e34\u0e41\u0e1a\u0e1a server GeneralView.label.creationdate=\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e40\u0e21\u0e37\u0e48\u0e2d : ConfigView.section.tracker.announcescrapepercentage=\u0e0a\u0e48\u0e27\u0e07 Scrape \u0e40\u0e1b\u0e47\u0e19 %\u0e2d\u0e32\u0e22\u0e38\u0e01\u0e32\u0e23\u0e41\u0e08\u0e49\u0e07\n\u0e15\u0e31\u0e27\u0e2d\u0e22\u0e48\u0e32\u0e07 200 = 2:1. 0 = \u0e43\u0e2b\u0e49 peer \u0e15\u0e31\u0e14\u0e2a\u0e34\u0e19 ManagerItem.stopping=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e2b\u0e22\u0e38\u0e14 ConfigView.section.tracker.announcecacheperiod=\u0e41\u0e08\u0e49\u0e07 cache (\u0e21\u0e34\u0e25\u0e25\u0e34) ConfigView.section.tracker.scrapecacheperiod=Scrape cache (\u0e21\u0e34\u0e25\u0e25\u0e34) ConfigView.section.tracker.scrapeandcache=Scrape \u0e41\u0e25\u0e30 cache ConfigView.section.tracker.announcecacheminpeers=\u0e41\u0e08\u0e49\u0e07 cache \u0e40\u0e1b\u0e34\u0e14 peer threshold MyTrackerView.scrapes=\u0e2a\u0e48\u0e27\u0e19 fileDownloadWindow.retry=\u0e25\u0e2d\u0e07\u0e43\u0e2b\u0e21\u0e48 MyTrackerView.bytesin=Bytes \u0e40\u0e02\u0e49\u0e32 MyTrackerView.bytesinave=\u0e40\u0e02\u0e49\u0e32\u0e23\u0e27\u0e21 MyTrackerView.bytesout=Bytes \u0e2d\u0e2d\u0e01 MyTrackerView.bytesoutave=\u0e2d\u0e2d\u0e01\u0e23\u0e27\u0e21 ConfigView.section.file.max_open_files=\u0e40\u0e1b\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23 \u0e2d\u0e48\u0e32\u0e19/\u0e40\u0e02\u0e35\u0e22\u0e19\n[0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] ConfigView.section.file.max_open_files.tooltip=\u0e21\u0e35\u0e1b\u0e23\u0e30\u0e42\u0e1a\u0e0a\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e04\u0e38\u0e13\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 torrents \u0e17\u0e35\u0e48\u0e21\u0e35\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e23\u0e49\u0e2d\u0e22/\u0e1e\u0e31\u0e19 \u0e43\u0e19\u0e19\u0e31\u0e49\u0e19, \u0e41\u0e25\u0e30\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e04\u0e38\u0e13\u0e16\u0e36\u0e07\u0e02\u0e35\u0e14\u0e08\u0e33\u0e01\u0e31\u0e14\u0e02\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e08\u0e31\u0e14\u0e01\u0e32\u0e23\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e02\u0e2d\u0e07 OS ConfigView.section.proxy=\u0e15\u0e31\u0e27\u0e40\u0e25\u0e37\u0e2d\u0e01 Proxy ConfigView.section.proxy.enable_proxy=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e1e\u0e23\u0e2d\u0e01\u0e0b\u0e35\u0e48 ConfigView.section.proxy.port=\u0e1e\u0e2d\u0e23\u0e4c\u0e15 ConfigView.section.proxy.username=\u0e0a\u0e37\u0e48\u0e2d\u0e1c\u0e39\u0e49\u0e43\u0e0a\u0e49 ConfigView.section.proxy.password=\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19 ConfigView.section.proxy.enable_socks=\u0e09\u0e31\u0e19\u0e21\u0e35 SOCKS \u0e1e\u0e23\u0e2d\u0e01\u0e0b\u0e35\u0e48 wizard.createtorrent.extrahashes=\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e2a\u0e48\u0e27\u0e19\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22\u0e2d\u0e37\u0e48\u0e19 (\u0e15\u0e31\u0e27\u0e2d\u0e22\u0e48\u0e32\u0e07 Gnutella2, eDonkey2000) GeneralView.label.connected=\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d GeneralView.label.in_swarm=\u0e43\u0e19 swarm ManagerItem.initializing=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e40\u0e23\u0e34\u0e48\u0e21 AlertMessageBox.error=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 AlertMessageBox.warning=\u0e04\u0e33\u0e40\u0e15\u0e37\u0e2d\u0e19 AlertMessageBox.comment=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 AlertMessageBox.information=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 SharedPortServer.alert.selectorfailed=\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27\n\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07 firewall \u0e27\u0e48\u0e32\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15 java(w).exe \u0e43\u0e2b\u0e49\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e1a 'server' Tracker.alert.listenfail=\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e1e\u0e2d\u0e23\u0e4c\u0e15 %1 \u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27\n\u0e15\u0e23\u0e27\u0e08\u0e14\u0e39\u0e27\u0e48\u0e32\u0e21\u0e35\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e2d\u0e37\u0e48\u0e19\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e43\u0e0a\u0e49\u0e1e\u0e2d\u0e23\u0e4c\u0e15\u0e19\u0e35\u0e49.\n\u0e41\u0e25\u0e30\u0e15\u0e23\u0e27\u0e08\u0e27\u0e48\u0e32\u0e44\u0e21\u0e48\u0e21\u0e35 Vuze \u0e15\u0e31\u0e27\u0e2d\u0e37\u0e48\u0e19\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23\u0e2d\u0e22\u0e39\u0e48 DiskManager.alert.movefileexists=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e43\u0e19\u0e01\u0e32\u0e23\u0e40\u0e04\u0e25\u0e37\u0e48\u0e2d\u0e19\u0e22\u0e49\u0e32\u0e22\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\n\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 %1 \u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48\u0e43\u0e19\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e40\u0e1b\u0e49\u0e32\u0e2b\u0e21\u0e32\u0e22\u0e41\u0e25\u0e49\u0e27 DiskManager.alert.movefilefails=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e43\u0e19\u0e01\u0e32\u0e23\u0e40\u0e04\u0e25\u0e37\u0e48\u0e2d\u0e19\u0e22\u0e49\u0e32\u0e22\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\n\u0e01\u0e32\u0e23\u0e40\u0e04\u0e25\u0e37\u0e48\u0e2d\u0e19\u0e22\u0e49\u0e32\u0e22\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 %1 \u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27, %2 DiskManager.alert.movefilerecoveryfails=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e43\u0e19\u0e01\u0e32\u0e23\u0e01\u0e39\u0e49\u0e02\u0e49\u0e21\u0e39\u0e25\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e04\u0e25\u0e37\u0e48\u0e2d\u0e19\u0e22\u0e49\u0e32\u0e22\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27\n\u0e01\u0e32\u0e23\u0e0b\u0e48\u0e2d\u0e21\u0e41\u0e0b\u0e21\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 %1 \u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27, %2 ConfigView.section.tracker.logenable=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e2a\u0e15\u0e34\u0e16\u0e34\u0e40\u0e1b\u0e47\u0e19\u0e23\u0e30\u0e22\u0e30\u0e17\u0e35\u0e48 'tracker.log' SpeedView.stats.title=\u0e2a\u0e15\u0e34\u0e16\u0e34 SpeedView.stats.total=\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 SpeedView.stats.session=\u0e0a\u0e48\u0e27\u0e07\u0e19\u0e35\u0e49 SpeedView.stats.session.tooltip=\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 (Protocol) SpeedView.stats.downloaded=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 SpeedView.stats.uploaded=\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14 SpeedView.stats.ratio=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19 SpeedView.stats.uptime=\u0e40\u0e27\u0e25\u0e32\u0e2d\u0e31\u0e1e (\u0e0a\u0e31\u0e48\u0e27\u0e42\u0e21\u0e07) SpeedView.stats.now=\u0e17\u0e31\u0e19\u0e17\u0e35 SpeedView.stats.now.tooltip=\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 (Protocol) AutoMigration.useralert=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07\u0e02\u0e2d\u0e07\u0e1c\u0e39\u0e43\u0e0a\u0e49 Vuze /dirs \u0e1c\u0e25\u0e02\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e40\u0e04\u0e25\u0e37\u0e48\u0e2d\u0e19\u0e22\u0e49\u0e32\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34:\n\n%1\n\u0e41\u0e15\u0e48\u0e25\u0e30\u0e04\u0e27\u0e32\u0e21\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 \u0e15\u0e49\u0e2d\u0e07\u0e17\u0e33\u0e01\u0e32\u0e23\u0e40\u0e04\u0e25\u0e37\u0e48\u0e2d\u0e19\u0e22\u0e49\u0e32\u0e22\u0e14\u0e49\u0e27\u0e22\u0e15\u0e19\u0e40\u0e2d\u0e07\n\u0e2d\u0e22\u0e48\u0e32\u0e25\u0e37\u0e21\u0e17\u0e35\u0e48\u0e08\u0e30\u0e1b\u0e23\u0e31\u0e1a\u0e1b\u0e23\u0e38\u0e07\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e01\u0e32\u0e23\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e43\u0e19\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07 \u0e16\u0e49\u0e32\u0e21\u0e31\u0e19\u0e16\u0e39\u0e01\u0e40\u0e04\u0e25\u0e35\u0e48\u0e22\u0e19\u0e22\u0e49\u0e32\u0e22 ! # # > 2.0.8.0 # OpenTorrentWindow.title=\u0e40\u0e1b\u0e34\u0e14 Torrent(s) OpenTorrentWindow.message=\u0e17\u0e14\u0e25\u0e2d\u0e07 OpenTorrentWindow.addFiles=&\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 OpenTorrentWindow.dataLocation=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25: OpenTorrentWindow.startMode=\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a\u0e40\u0e1e\u0e34\u0e48\u0e21 OpenTorrentWindow.startMode.queued=\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a OpenTorrentWindow.startMode.stopped=\u0e2b\u0e22\u0e38\u0e14 OpenTorrentWindow.startMode.forceStarted=\u0e1a\u0e31\u0e07\u0e04\u0e31\u0e1a\u0e40\u0e23\u0e34\u0e48\u0e21 OpenTorrentWindow.addPosition=\u0e25\u0e33\u0e14\u0e31\u0e1a\u0e17\u0e35\u0e48 OpenTorrentWindow.addPosition.first=\u0e41\u0e23\u0e01 OpenTorrentWindow.addPosition.last=\u0e17\u0e49\u0e32\u0e22 TableColumn.header.remaining.info=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e17\u0e35\u0e48\u0e40\u0e2b\u0e25\u0e37\u0e2d\u0e43\u0e19\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 TableColumn.header.remaining=\u0e40\u0e2b\u0e25\u0e37\u0e2d ConfigView.section.tracker.enablecompact=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e01\u0e32\u0e23\u0e41\u0e08\u0e49\u0e07\u0e42\u0e1b\u0e23\u0e42\u0e15\u0e04\u0e2d\u0e25\u0e41\u0e1a\u0e1a\u0e1a\u0e35\u0e1a\u0e2d\u0e31\u0e14 ConfigView.section.tracker.enablekey=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e1c\u0e48\u0e32\u0e19\u0e23\u0e2b\u0e31\u0e2a\u0e44\u0e1b\u0e17\u0e35\u0e48 tracker \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e1b\u0e25\u0e2d\u0e14\u0e20\u0e31\u0e22\u0e21\u0e32\u0e01\u0e22\u0e34\u0e48\u0e07\u0e02\u0e36\u0e49\u0e19 ConfigView.section.file.perf=\u0e15\u0e31\u0e27\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e14\u0e49\u0e32\u0e19\u0e1b\u0e23\u0e30\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e20\u0e32\u0e1e ConfigView.section.file.perf.explain=\u0e04\u0e33\u0e40\u0e15\u0e37\u0e2d\u0e19 - \u0e01\u0e32\u0e23\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e04\u0e48\u0e32\u0e19\u0e35\u0e49\u0e42\u0e14\u0e22\u0e44\u0e21\u0e48\u0e21\u0e35\u0e04\u0e27\u0e32\u0e21\u0e23\u0e39\u0e49 \u0e2d\u0e32\u0e08\u0e21\u0e35\u0e1c\u0e25\u0e15\u0e48\u0e2d\u0e1b\u0e23\u0e30\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e20\u0e32\u0e1e\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 \u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e40\u0e23\u0e34\u0e48\u0e21\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e43\u0e2b\u0e21\u0e48\n\u0e16\u0e49\u0e32\u0e04\u0e38\u0e13\u0e21\u0e35\u0e1b\u0e31\u0e0d\u0e2b\u0e32 "\u0e2b\u0e19\u0e48\u0e27\u0e22\u0e04\u0e27\u0e32\u0e21\u0e08\u0e33\u0e44\u0e21\u0e48\u0e1e\u0e2d" \u0e04\u0e27\u0e23\u0e08\u0e33\u0e01\u0e31\u0e14\u0e01\u0e32\u0e23\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e15\u0e48\u0e2d\u0e15\u0e48\u0e2d torrent (\u0e14\u0e39\u0e17\u0e35\u0e48\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07\u0e01\u0e32\u0e23\u0e02\u0e19\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25) ConfigView.section.file.max_open_files.explain=\u0e01\u0e32\u0e23\u0e40\u0e1b\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e21\u0e32\u0e01\u0e40\u0e01\u0e34\u0e19\u0e44\u0e1b\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e17\u0e33\u0e43\u0e2b\u0e49\u0e23\u0e30\u0e1a\u0e1a\u0e1b\u0e0e\u0e34\u0e1a\u0e31\u0e15\u0e34\u0e01\u0e32\u0e23\u0e40\u0e01\u0e34\u0e14\u0e1b\u0e31\u0e0d\u0e2b\u0e32\u0e08\u0e32\u0e01\u0e17\u0e23\u0e31\u0e1e\u0e22\u0e32\u0e01\u0e23\u0e17\u0e35\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14 \u0e40\u0e0a\u0e48\u0e19 \u0e01\u0e32\u0e23\u0e08\u0e31\u0e14\u0e01\u0e32\u0e23\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 \u0e19\u0e35\u0e48\u0e08\u0e30\u0e08\u0e33\u0e01\u0e31\u0e14\u0e1b\u0e23\u0e34\u0e21\u0e32\u0e13\u0e02\u0e2d\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e27\u0e25\u0e32\u0e40\u0e1b\u0e34\u0e14 popup.error.hide=\u0e0b\u0e48\u0e2d\u0e19 popup.error.details=\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 ConfigView.section.style.colorOverrides=\u0e40\u0e02\u0e35\u0e22\u0e19\u0e17\u0e31\u0e1a\u0e2a\u0e35 ConfigView.section.style.colorOverride.progressBar=\u0e41\u0e16\u0e1a\u0e04\u0e27\u0e32\u0e21\u0e04\u0e37\u0e1a\u0e2b\u0e19\u0e49\u0e32 ConfigView.section.style.colorOverride.error=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 MainWindow.status.tooOld=\u0e40\u0e01\u0e48\u0e32\u0e41\u0e25\u0e49\u0e27, \u0e42\u0e1b\u0e23\u0e14\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 ConfigView.section.style.colorOverride.warning=\u0e04\u0e33\u0e40\u0e15\u0e37\u0e2d\u0e19 ConfigView.section.style.colorOverride.altRow=\u0e41\u0e16\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21 ConfigView.section.file.save.peers.enable=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e01\u0e31\u0e1a peer \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e23\u0e27\u0e14\u0e40\u0e23\u0e47\u0e27\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07 ConfigView.section.file.save.peers.max=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e02\u0e2d\u0e07 peers \u0e17\u0e35\u0e48\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] ConfigView.section.file.save.peers.pertorrent=\u0e15\u0e48\u0e2d torrent ConfigView.label.max_peers_per_torrent=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e43\u0e19\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e15\u0e48\u0e2d torrent [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] ConfigView.label.max_peers_total=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e43\u0e19\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] ConfigView.section.style.colorOverrides.reset=\u0e25\u0e49\u0e32\u0e07\u0e2a\u0e35\u0e43\u0e2b\u0e21\u0e48 ConfigView.section.language.info=\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e40\u0e1b\u0e34\u0e14\u0e43\u0e0a\u0e49, \u0e08\u0e30\u0e15\u0e23\u0e27\u0e08\u0e2b\u0e32\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e17\u0e38\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07\u0e17\u0e35\u0e48 Vuze \u0e40\u0e23\u0e34\u0e48\u0e21 ConfigView.section.language.enableUpdate=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e1c\u0e48\u0e32\u0e19\u0e40\u0e27\u0e47\u0e1a ConfigView.section.language.UpdateURL=\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 URL ConfigView.section.language.UpdateNow=\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e40\u0e25\u0e22! Button.revert=\u0e01\u0e25\u0e31\u0e1a\u0e14\u0e31\u0e07\u0e40\u0e14\u0e34\u0e21 MyTorrentsView.menu.changeDirectory=\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 GenericText.column=\u0e41\u0e16\u0e27 MyTorrentsView.menu.thisColumn.remove=\u0e40\u0e2d\u0e32\u0e41\u0e16\u0e27\u0e2d\u0e2d\u0e01 MyTorrentsView.menu.thisColumn.toClipboard=\u0e2a\u0e33\u0e40\u0e19\u0e32\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e44\u0e1b\u0e17\u0e35\u0e48 Clipboard TableColumn.header.secondsseeding=Seeding \u0e19\u0e32\u0e19 TableColumn.header.secondsseeding.info=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e40\u0e27\u0e25\u0e32\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13 seeding TableColumn.header.secondsdownloading=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e19\u0e32\u0e19 TableColumn.header.secondsdownloading.info=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 ConfigView.section.tracker.udpversion=UDP \u0e42\u0e1b\u0e23\u0e42\u0e15\u0e04\u0e2d\u0e25 \u0e23\u0e38\u0e48\u0e19 (1 \u0e2b\u0e23\u0e37\u0e2d 2) window.updateswt.title=\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19 SWT \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e40\u0e01\u0e48\u0e32\u0e40\u0e01\u0e34\u0e19\u0e44\u0e1b ! window.updateswt.text=\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19 SWT \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e40\u0e01\u0e48\u0e32\u0e40\u0e01\u0e34\u0e19\u0e44\u0e1b !\nSWT \u0e04\u0e37\u0e2d graphic library \u0e17\u0e35\u0e48\u0e43\u0e0a\u0e49\u0e42\u0e14\u0e22 Vuze \u0e41\u0e25\u0e30\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e21\u0e35\u0e40\u0e01\u0e48\u0e32\u0e40\u0e01\u0e34\u0e19\u0e01\u0e27\u0e48\u0e32\u0e17\u0e35\u0e48\u0e08\u0e30\u0e40\u0e23\u0e34\u0e48\u0e21 Vuze \u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e25\u0e48\u0e32\u0e2a\u0e38\u0e14 \u0e01\u0e14\u0e1b\u0e38\u0e48\u0e21\u0e15\u0e01\u0e25\u0e07\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 SWT \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13 window.updateswt.status=\u0e2a\u0e16\u0e32\u0e19\u0e30 window.updateswt.failed=\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27, \u0e01\u0e14\u0e15\u0e01\u0e25\u0e07\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e40\u0e23\u0e34\u0e48\u0e21\u0e15\u0e49\u0e19\u0e43\u0e2b\u0e21\u0e48 window.updateswt.status.downloading.updater=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e2a\u0e48\u0e27\u0e19\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 window.updateswt.status.finding=\u0e2b\u0e32 SWT \u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e43\u0e2b\u0e21\u0e48\u0e17\u0e35\u0e48\u0e2a\u0e38\u0e14 window.updateswt.status.downloading=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 SWT \u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e25\u0e48\u0e32\u0e2a\u0e38\u0e14 window.updateswt.status.done=\u0e40\u0e23\u0e34\u0e48\u0e21\u0e15\u0e49\u0e19\u0e43\u0e2b\u0e21\u0e48 window.updateswt.ok=\u0e15\u0e01\u0e25\u0e07 window.updateswt.cancel=\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01 swt.updater.downloader.downloading=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 SWT \u0e08\u0e32\u0e01 swt.updater.urlsgetter.downloading=\u0e40\u0e2d\u0e32\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d mirrors \u0e08\u0e32\u0e01 swt.updater.urlsgetter.platform=SWT\u0e40\u0e1e\u0e37\u0e48\u0e2d platform : window.updateswt.ignore=\u0e25\u0e30\u0e40\u0e27\u0e49\u0e19 ConfigView.section.style.useFancyTabs=\u0e43\u0e0a\u0e49\u0e41\u0e16\u0e1a\u0e41\u0e1a\u0e1a\u0e2a\u0e35\u0e2a\u0e31\u0e19 splash.initializeGM=\u0e01\u0e32\u0e23\u0e1a\u0e23\u0e34\u0e2b\u0e32\u0e23 Torrent \u0e42\u0e14\u0e22\u0e23\u0e27\u0e21\u0e02\u0e31\u0e49\u0e19\u0e15\u0e49\u0e19 splash.loadingTorrents=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e42\u0e2b\u0e25\u0e14 Torrents MyTorrentsView.menu.thisColumn.sort=&\u0e40\u0e23\u0e35\u0e22\u0e07 Scrape.status.ok=\u0e2a\u0e48\u0e27\u0e19\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c Scrape.status.error=\u0e2a\u0e48\u0e27\u0e19\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14: Scrape.status.error.badURL=URL \u0e17\u0e35\u0e48\u0e41\u0e08\u0e49\u0e07\u0e44\u0e21\u0e48\u0e17\u0e33\u0e01\u0e32\u0e23\u0e41\u0e1a\u0e48\u0e07\u0e2a\u0e48\u0e27\u0e19\u0e15\u0e32\u0e21\u0e17\u0e35\u0e48\u0e01\u0e33\u0e2b\u0e19\u0e14 Scrape.status.error.nohash=\u0e2a\u0e48\u0e27\u0e19\u0e2b\u0e32\u0e22\u0e08\u0e32\u0e01\u0e01\u0e32\u0e23\u0e15\u0e2d\u0e1a\u0e01\u0e25\u0e31\u0e1a Scrape.status.error.invalid=\u0e15\u0e2d\u0e1a\u0e23\u0e31\u0e1a\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 Scrape.status.nextScrapeAt=\u0e2a\u0e48\u0e27\u0e19\u0e15\u0e48\u0e2d\u0e44\u0e1b %1 Scrape.status.scraping=\u0e41\u0e1a\u0e48\u0e07\u0e2a\u0e48\u0e27\u0e19.. Scrape.status.initializing=\u0e23\u0e2d\u0e0a\u0e34\u0e49\u0e19\u0e2a\u0e48\u0e27\u0e19 ConfigView.label.minSpeedForActiveSeeding=\u0e44\u0e21\u0e48\u0e19\u0e31\u0e1a torrent \u0e17\u0e35\u0e48\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e41\u0e25\u0e49\u0e27\u0e27\u0e48\u0e32\u0e43\u0e0a\u0e49\u0e0a\u0e48\u0e2d\u0e07 \u0e16\u0e49\u0e32\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e15\u0e33\u0e01\u0e27\u0e48\u0e32 ConfigView.section.stats.exportpeers=\u0e19\u0e33\u0e2d\u0e2d\u0e01\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 peer MainWindow.menu.view.irc.moved=Irc \u0e21\u0e35\u0e1e\u0e23\u0e49\u0e2d\u0e21\u0e43\u0e19\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21, \u0e14\u0e39\u0e17\u0e35\u0e48 http://azureus.sourceforge.net/plugin_list.php \u0e40\u0e21\u0e37\u0e48\u0e2d\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07\u0e44\u0e1b\u0e17\u0e35\u0e48 \u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25->\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21->\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23 IRC \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e40\u0e02\u0e49\u0e32 MyTrackerView.webui.contextmenu.copyurl=\u0e2a\u0e33\u0e40\u0e19\u0e32 torrent URL \u0e44\u0e1b\u0e22\u0e31\u0e07 clipboard ConfigView.section.file.torrent.ignorefiles=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e25\u0e30\u0e40\u0e25\u0e22\u0e40\u0e27\u0e25\u0e32\u0e2a\u0e23\u0e49\u0e32\u0e07 torrents\n\u0e40\u0e0a\u0e48\u0e19 .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=\u0e25\u0e30\u0e40\u0e27\u0e49\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 ConfigView.section.style.useUnitsRateBits=\u0e43\u0e0a\u0e49 bits \u0e41\u0e17\u0e19 bytes \u0e04\u0e48\u0e32\u0e41\u0e1a\u0e1a byte (KiB/s->Kibit/s \u0e2d\u0e37\u0e48\u0e19\u0e46.) ConfigView.section.interface.resetassoc=\u0e40\u0e23\u0e34\u0e48\u0e21\u0e04\u0e27\u0e32\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e02\u0e49\u0e2d\u0e07\u0e43\u0e19 explorer \u0e43\u0e2b\u0e21\u0e48 (.torrent) ConfigView.section.interface.resetassocbutton=\u0e40\u0e23\u0e34\u0e48\u0e21\u0e43\u0e2b\u0e21\u0e48 ConfigView.section.interface.checkassoc=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e04\u0e27\u0e32\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e02\u0e49\u0e2d\u0e07\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e40\u0e23\u0e34\u0e48\u0e21\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21 dialog.associations.title=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e01\u0e32\u0e23\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e42\u0e22\u0e07 Button.yes=\u0e43\u0e0a\u0e48 Button.no=\u0e44\u0e21\u0e48 ConfigView.label.seeding.autoStart0Peers=\u0e40\u0e23\u0e34\u0e48\u0e21 torrents \u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34\u0e17\u0e35\u0e48\u0e21\u0e35 0 peers ConfigView.label.seeding.autoStart0Peers.tooltip=\u0e40\u0e1b\u0e34\u0e14\u0e43\u0e0a\u0e49\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e04\u0e38\u0e13\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e43\u0e2b\u0e49 tracker \u0e41\u0e2a\u0e14\u0e07\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d seeds \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a 0 peer torrents dialog.associations.prompt=Vuze \u0e44\u0e21\u0e48\u0e43\u0e0a\u0e48\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e21\u0e17\u0e35\u0e48\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e44\u0e27\u0e49\u0e08\u0e31\u0e14\u0e01\u0e32\u0e23\u0e01\u0e31\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 BitTorrent\n\u0e04\u0e38\u0e13\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e17\u0e35\u0e48\u0e08\u0e30\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e42\u0e22\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 .torrent \u0e01\u0e31\u0e1a Vuze \u0e2b\u0e23\u0e37\u0e2d\u0e44\u0e21\u0e48? dialog.associations.askagain=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e15\u0e2d\u0e19\u0e40\u0e23\u0e34\u0e48\u0e21\u0e15\u0e49\u0e19 ConfigView.section.plugins.update=\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e42\u0e1b\u0e23\u0e41\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21 Plugin.pluginupdate.enablecheck=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21 plugins.basicview.status=\u0e2a\u0e16\u0e32\u0e19\u0e30: plugins.basicview.activity=\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21: plugins.basicview.progress=\u0e04\u0e37\u0e1a\u0e2b\u0e19\u0e49\u0e32: plugins.basicview.log=\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01: ConfigView.label.maxdownloadspeed=KB/s \u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e43\u0e19\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e42\u0e14\u0e22\u0e23\u0e27\u0e21 [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] splash.loadingTorrent=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e42\u0e2b\u0e25\u0e14 Torrent splash.of=\u0e02\u0e2d\u0e07 UpdateWindow.title=\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 Vuze UpdateWindow.header=\u0e2a\u0e48\u0e27\u0e19\u0e40\u0e2b\u0e25\u0e48\u0e32\u0e19\u0e35\u0e49\u0e08\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 : UpdateWindow.columns.install=\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07 UpdateWindow.columns.name=\u0e0a\u0e37\u0e48\u0e2d UpdateWindow.columns.version=\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19 UpdateWindow.columns.size=\u0e02\u0e19\u0e32\u0e14 UpdateWindow.cancel=\u0e1b\u0e0f\u0e34\u0e40\u0e2a\u0e18 UpdateWindow.quit=\u0e2d\u0e2d\u0e01 UpdateWindow.close=\u0e1b\u0e34\u0e14 UpdateWindow.ok=\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 UpdateWindow.restart=\u0e40\u0e23\u0e34\u0e48\u0e21\u0e43\u0e2b\u0e21\u0e48 UpdateWindow.status.downloading=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 UpdateWindow.status.done=\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19 UpdateWindow.status.failed=\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27 UpdateWindow.status.restartNeeded=\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e40\u0e23\u0e34\u0e48\u0e21\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e43\u0e2b\u0e21\u0e48 ! ConfigView.pluginlist.broken=\u0e40\u0e2a\u0e35\u0e22 ConfigView.pluginlist.whereToPut=\u0e27\u0e32\u0e07\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e1a\u0e38\u0e04\u0e04\u0e25\u0e43\u0e19\u0e41\u0e1f\u0e49\u0e21\u0e02\u0e2d\u0e07\u0e15\u0e31\u0e27\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2d\u0e07 \u0e43\u0e19: ConfigView.pluginlist.whereToPutOr=\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e43\u0e0a\u0e49: MainWindow.statusText.checking=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 TableColumn.header.OnlyCDing4=\u0e40\u0e09\u0e1e\u0e32\u0e30 Seeding TableColumn.header.OnlyCDing4.info=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48 torrent seeding \u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19. \u0e44\u0e21\u0e48\u0e23\u0e27\u0e21\u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14 (\u0e41\u0e25\u0e30 seeding) ConfigView.section.style.alternateTablePainting=\u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e23\u0e30\u0e1a\u0e32\u0e22\u0e15\u0e32\u0e23\u0e32\u0e07\u0e41\u0e1c\u0e19\u0e20\u0e39\u0e21\u0e34\u0e2d\u0e35\u0e01\u0e41\u0e1a\u0e1a\u0e2b\u0e19\u0e36\u0e48\u0e07 (\u0e2d\u0e32\u0e08\u0e15\u0e49\u0e2d\u0e07\u0e40\u0e23\u0e34\u0e48\u0e21\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e43\u0e2b\u0e21\u0e48) UpdateWindow.status.restartMaybeNeeded=\u0e2d\u0e32\u0e08\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e40\u0e23\u0e34\u0e48\u0e21\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e43\u0e2b\u0e21\u0e48 ConfigView.pluginlist.shared=\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19 PeersView.host=\u0e0a\u0e37\u0e48\u0e2d Host PeersView.host.info=\u0e0a\u0e37\u0e48\u0e2d host \u0e02\u0e2d\u0e07 peer, \u0e17\u0e35\u0e48\u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48 (\u0e21\u0e35\u0e1c\u0e25\u0e15\u0e48\u0e2d\u0e1b\u0e23\u0e30\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e20\u0e32\u0e1e) MainWindow.menu.help.whatsnew=\u0e21\u0e35\u0e2d\u0e30\u0e44\u0e23\u0e43\u0e2b\u0e21\u0e48 ConfigView.label.checkonstart=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e43\u0e2b\u0e21\u0e48\u0e40\u0e21\u0e37\u0e48\u0e2d Vuze \u0e17\u0e33\u0e07\u0e32\u0e19 ConfigView.label.periodiccheck=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e2b\u0e32\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19\u0e43\u0e2b\u0e21\u0e48\u0e40\u0e1b\u0e47\u0e19\u0e23\u0e30\u0e22\u0e30 ConfigView.label.opendialog=\u0e40\u0e1b\u0e34\u0e14\u0e04\u0e27\u0e32\u0e21\u0e0a\u0e48\u0e27\u0e22\u0e40\u0e2b\u0e25\u0e37\u0e2d\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 \u0e40\u0e21\u0e37\u0e48\u0e2d\u0e21\u0e35\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 MainWindow.updateavail=(\u0e21\u0e35\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17) MainWindow.status.latestversionunchecked=\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e48\u0e19 GeneralView.label.updatein.stopped=\u0e2b\u0e22\u0e38\u0e14 StartStopRules.menu.viewDebug=\u0e14\u0e39\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Debug ConfigView.section.style.doNotUseGB=\u0e44\u0e21\u0e48\u0e43\u0e0a\u0e49\u0e2b\u0e19\u0e48\u0e27\u0e22 GB ConfigView.section.style.doNotUseGB.tooltip=\u0e16\u0e49\u0e32\u0e40\u0e25\u0e37\u0e2d\u0e01, Vuze \u0e08\u0e30\u0e22\u0e31\u0e07\u0e43\u0e0a\u0e49\u0e2b\u0e19\u0e48\u0e27\u0e22 MB \u0e41\u0e21\u0e49\u0e02\u0e19\u0e32\u0e14\u0e08\u0e30\u0e21\u0e32\u0e01\u0e01\u0e27\u0e48\u0e32 1024MB MainWindow.menu.help.plugins=\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21 ConfigView.section.plugins.TrackerWeb=Tracker \u0e40\u0e27\u0e47\u0e1a ConfigView.section.tracker.enablecategories=\u0e41\u0e22\u0e01 torrents \u0e15\u0e32\u0e21\u0e1b\u0e23\u0e30\u0e40\u0e20\u0e17 health.explain.share=\u0e2b\u0e21\u0e32\u0e22\u0e04\u0e27\u0e32\u0e21\u0e27\u0e48\u0e32 torrent \u0e44\u0e21\u0e48\u0e44\u0e14\u0e49 hosted \u0e2b\u0e23\u0e37\u0e2d \u0e2d\u0e2d\u0e01 ConfigView.section.tracker.createcert=\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e02\u0e2d\u0e07\u0e15\u0e31\u0e27\u0e40\u0e2d\u0e07 ConfigView.section.tracker.createbutton=\u0e2a\u0e23\u0e49\u0e32\u0e07 security.certcreate.title=\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e14\u0e49\u0e27\u0e22\u0e15\u0e19\u0e40\u0e2d\u0e07 security.certcreate.intro=\u0e2b\u0e19\u0e49\u0e32\u0e15\u0e48\u0e32\u0e07\u0e19\u0e35\u0e49\u0e43\u0e2b\u0e49\u0e04\u0e38\u0e13\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e14\u0e49\u0e27\u0e22\u0e15\u0e19\u0e40\u0e2d\u0e07 security.certcreate.alias=\u0e19\u0e32\u0e21\u0e41\u0e1d\u0e07 security.certcreate.strength=\u0e41\u0e02\u0e47\u0e07\u0e41\u0e23\u0e07 security.certcreate.firstlastname=\u0e0a\u0e37\u0e48\u0e2d\u0e41\u0e23\u0e01 \u0e41\u0e25\u0e30\u0e17\u0e49\u0e32\u0e22 security.certcreate.orgunit=\u0e2b\u0e19\u0e48\u0e27\u0e22\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e13\u0e4c security.certcreate.org=\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e13\u0e4c security.certcreate.city=\u0e40\u0e21\u0e37\u0e2d\u0e07 \u0e2b\u0e23\u0e37\u0e2d\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 security.certcreate.state=\u0e23\u0e31\u0e10 \u0e2b\u0e23\u0e37\u0e2d\u0e40\u0e02\u0e15 security.certcreate.country=\u0e23\u0e2b\u0e31\u0e2a\u0e1b\u0e23\u0e30\u0e40\u0e17\u0e28 2 \u0e15\u0e31\u0e27\u0e2d\u0e31\u0e01\u0e29\u0e23 security.certcreate.ok=\u0e2a\u0e23\u0e49\u0e32\u0e07 security.certcreate.cancel=\u0e1b\u0e0f\u0e34\u0e40\u0e2a\u0e18 security.certcreate.createok=\u0e01\u0e32\u0e23\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e2a\u0e33\u0e40\u0e23\u0e47\u0e08 security.certcreate.createfail=\u0e01\u0e32\u0e23\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27 ConfigView.section.plugins.webui=\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25\u0e41\u0e1a\u0e1a\u0e2a\u0e27\u0e34\u0e07\u0e40\u0e27\u0e47\u0e1a ConfigView.section.plugins.xml_http_if=\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25\u0e41\u0e1a\u0e1a XML/HTTP webui.passwordenable=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19 webui.user=\u0e0a\u0e37\u0e48\u0e2d\u0e1c\u0e39\u0e49\u0e43\u0e0a\u0e49 webui.password=\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19 webui.port=\u0e1e\u0e2d\u0e23\u0e4c\u0e15 (*) webui.protocol=\u0e42\u0e1b\u0e23\u0e42\u0e15\u0e04\u0e2d\u0e25 (*) webui.rootdir=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e2b\u0e25\u0e31\u0e01 (*) webui.rootres=\u0e17\u0e23\u0e31\u0e1e\u0e22\u0e32\u0e01\u0e23\u0e2b\u0e25\u0e31\u0e01(*) webui.mode=\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a (*) webui.mode.info=\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e40\u0e1b\u0e47\u0e19\n\t"full"\t= \u0e21\u0e35\u0e17\u0e38\u0e01\u0e1b\u0e0f\u0e34\u0e1a\u0e31\u0e15\u0e34\u0e01\u0e32\u0e23 (\u0e04\u0e48\u0e32\u0e40\u0e23\u0e34\u0e48\u0e21\u0e15\u0e49\u0e19)\n\t"view"\t= \u0e14\u0e39\u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19 (\u0e41\u0e15\u0e48\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25\u0e43\u0e2b\u0e21\u0e48\u0e44\u0e14\u0e49\u0e1a\u0e48\u0e2d\u0e22\u0e04\u0e23\u0e31\u0e49\u0e07) webui.access=\u0e40\u0e02\u0e49\u0e32 (*) webui.access.info=\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e40\u0e1b\u0e47\u0e19\n\t"local"\t= \u0e2b\u0e21\u0e32\u0e22\u0e04\u0e27\u0e32\u0e21\u0e27\u0e48\u0e32\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e17\u0e35\u0e48\u0e17\u0e49\u0e2d\u0e07\u0e16\u0e34\u0e48\u0e19\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e44\u0e14\u0e49\n\t"all"\t= \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14\u0e01\u0e2a\u0e23\u0e40\u0e02\u0e49\u0e32 (\u0e04\u0e48\u0e32\u0e40\u0e23\u0e34\u0e48\u0e21\u0e15\u0e49\u0e19)\n\tIP\t= \u0e15\u0e31\u0e27\u0e2d\u0e22\u0e48\u0e32\u0e07 192.168.0.2\t\t\tone \u0e40\u0e09\u0e1e\u0e32\u0e30 IP\n\tIP1-IP2\t= \u0e15\u0e31\u0e27\u0e2d\u0e22\u0e48\u0e32\u0e07 192.168.0.1-192.168.0.255\t\u0e23\u0e27\u0e21\u0e0a\u0e48\u0e27\u0e07 IPs GeneralView.label.maxdownloadspeed=\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 Security.keystore.corrupt=\u0e44\u0e21\u0e48\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e42\u0e2b\u0e25\u0e14\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e40\u0e01\u0e47\u0e1a '%1' \u0e44\u0e14\u0e49, \u0e42\u0e1b\u0e23\u0e14\u0e25\u0e49\u0e32\u0e07\u0e41\u0e25\u0e30\u0e2a\u0e23\u0e49\u0e32\u0e07/\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e43\u0e2b\u0e21\u0e48 Security.keystore.empty=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e40\u0e01\u0e47\u0e1a\u0e44\u0e27\u0e49\u0e27\u0e48\u0e32\u0e07\u0e40\u0e1b\u0e25\u0e48\u0e32. \u0e42\u0e1b\u0e23\u0e14\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e14\u0e49\u0e27\u0e22\u0e15\u0e19\u0e40\u0e2d\u0e07 (\u0e17\u0e35\u0e48 \u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e41\u0e15\u0e48\u0e07->\u0e04\u0e27\u0e32\u0e21\u0e1b\u0e25\u0e2d\u0e14\u0e20\u0e31\u0e22) \u0e2b\u0e23\u0e37\u0e2d\u0e19\u0e33\u0e40\u0e02\u0e49\u0e32\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e17\u0e35\u0e48\u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48\u0e41\u0e25\u0e49\u0e27\u0e40\u0e02\u0e49\u0e32\u0e43\u0e19 '%1' webui.restart.info=\u0e01\u0e32\u0e23\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e15\u0e31\u0e27\u0e41\u0e1b\u0e23\u0e17\u0e35\u0e48\u0e21\u0e35 (*) \u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e40\u0e23\u0e34\u0e48\u0e21\u0e43\u0e2b\u0e21\u0e48\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e08\u0e30\u0e40\u0e01\u0e34\u0e14\u0e1c\u0e25 GeneralView.label.maxdownloadspeed.tooltip=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e43\u0e19\u0e01\u0e32\u0e23\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] upnp.enable=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49 UPnP upnp.info=Universal Plug and Play (UPnP) \u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15 mapping \u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34\u0e1a\u0e19\u0e1e\u0e2d\u0e23\u0e4c\u0e15\u0e02\u0e2d\u0e07 routers \u0e17\u0e35\u0e48\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15 UPnP upnp.mapping.dataport=\u0e23\u0e31\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Peer \u0e17\u0e35\u0e48\u0e1e\u0e2d\u0e23\u0e4c\u0e15 upnp.mapping.tcptrackerport=TCP Tracker \u0e1e\u0e2d\u0e23\u0e4c\u0e15 upnp.mapping.udptrackerport=UDP Tracker \u0e1e\u0e2d\u0e23\u0e4c\u0e15 upnp.alert.differenthost=UPnP: Mapping '%1' \u0e16\u0e39\u0e01\u0e40\u0e01\u0e47\u0e1a\u0e42\u0e14\u0e22 '%2' - \u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e1e\u0e2d\u0e23\u0e4c\u0e15\u0e2d\u0e37\u0e48\u0e19 upnp.alert.mappingok=UPnP: Mapping '%1' \u0e40\u0e2a\u0e23\u0e49\u0e08\u0e2a\u0e34\u0e49\u0e19 upnp.alert.mappingfailed=UPnP: Mapping '%1' \u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27 upnp.alertsuccess=\u0e23\u0e32\u0e22\u0e07\u0e32\u0e19l mappings \u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c upnp.alert.lostdevice=UPnP:\u0e02\u0e32\u0e14\u0e01\u0e32\u0e23\u0e15\u0e34\u0e15\u0e14\u0e48\u0e2d\u0e01\u0e31\u0e1a\u0e1a\u0e23\u0e34\u0e01\u0e32\u0e23 '%1' \u0e1a\u0e19\u0e2d\u0e38\u0e1b\u0e01\u0e23\u0e13\u0e4c UPnP '%2' upnp.grabports=Map\u0e1e\u0e2d\u0e23\u0e4c\u0e15\u0e41\u0e21\u0e49\u0e27\u0e48\u0e32\u0e40\u0e1b\u0e47\u0e19\u0e1e\u0e2d\u0e23\u0e4c\u0e15\u0e17\u0e35\u0e48\u0e04\u0e2d\u0e21\u0e1e\u0e34\u0e27\u0e40\u0e15\u0e2d\u0e23\u0e4c\u0e2d\u0e37\u0e48\u0e19\u0e40\u0e1b\u0e47\u0e19\u0e40\u0e08\u0e49\u0e32\u0e02\u0e2d\u0e07 upnp.refresh.label=\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25 mappings \u0e43\u0e2b\u0e21\u0e48 upnp.refresh.button=\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25\u0e43\u0e2b\u0e21\u0e48 upnp.alert.mappinggrabbed=UPnP: Mapping '%1' \u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19 - \u0e14\u0e36\u0e07\u0e08\u0e32\u0e01 '%2' upnp.mapping.tcpssltrackerport=TCP SSL Tracker \u0e1e\u0e2d\u0e23\u0e4c\u0e15 upnp.alertothermappings=\u0e23\u0e32\u0e22\u0e07\u0e32\u0e19\u0e1e\u0e2d\u0e23\u0e4c\u0e15\u0e17\u0e35\u0e48\u0e04\u0e2d\u0e21\u0e1e\u0e34\u0e27\u0e40\u0e15\u0e2d\u0e23\u0e4c\u0e2d\u0e37\u0e48\u0e19\u0e40\u0e1b\u0e47\u0e19\u0e40\u0e08\u0e49\u0e32\u0e02\u0e2d\u0e07 upnp.alertdeviceproblems=\u0e23\u0e32\u0e22\u0e07\u0e32\u0e19\u0e1b\u0e31\u0e0d\u0e2b\u0e32\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e2d\u0e38\u0e1b\u0e01\u0e23\u0e13\u0e4c UPnP ConfigView.pluginlist.coreplugins=\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e43\u0e19\u0e15\u0e31\u0e27\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e17\u0e35\u0e48\u0e42\u0e2b\u0e25\u0e14\u0e41\u0e25\u0e49\u0e27 \u0e14\u0e31\u0e07\u0e19\u0e35\u0e49: Peers.column.DLedFromOthers=\u0e08\u0e32\u0e01\u0e17\u0e35\u0e48\u0e2d\u0e37\u0e48\u0e19 Peers.column.DLedFromOthers.info=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e08\u0e32\u0e01\u0e17\u0e35\u0e48\u0e2d\u0e37\u0e48\u0e19\u0e23\u0e30\u0e2b\u0e27\u0e48\u0e32\u0e07\u0e17\u0e35\u0e48\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e01\u0e31\u0e1a\u0e04\u0e38\u0e13 Peers.column.UpDownRatio=\u0e2d\u0e31\u0e1e:\u0e14\u0e32\u0e27 Peers.column.UpDownRatio.info=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19 "\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14 : \u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14" \u0e02\u0e2d\u0e07 Peer Peers.column.UpRatio=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2d\u0e31\u0e1e Peers.column.UpRatio.info=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19 "\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e08\u0e32\u0e01\u0e04\u0e38\u0e13 : \u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e08\u0e32\u0e01\u0e17\u0e35\u0e48\u0e2d\u0e37\u0e48\u0e19" \u0e02\u0e2d\u0e07 Peer upnp.releasemappings=\u0e40\u0e25\u0e34\u0e01 mappings \u0e40\u0e21\u0e37\u0e48\u0e2d\u0e1b\u0e34\u0e14 webui.upnpenable=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19 UPnP \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e1e\u0e2d\u0e23\u0e4c\u0e15\u0e19\u0e35\u0e49 (*) ConfigView.section.file.friendly.hashchecking=\u0e04\u0e48\u0e2d\u0e22\u0e46 \u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 ConfigView.section.file.friendly.hashchecking.tooltip=\u0e0a\u0e49\u0e32\u0e01\u0e27\u0e48\u0e32, \u0e41\u0e15\u0e48\u0e43\u0e0a\u0e49 cpu/system \u0e19\u0e49\u0e2d\u0e22\u0e01\u0e27\u0e48\u0e32, \u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e41\u0e1a\u0e1a\u0e0a\u0e34\u0e49\u0e19\u0e2a\u0e48\u0e27\u0e19 ConfigView.section.tracker.seedretention=seeds \u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e17\u0e35\u0e48\u0e40\u0e01\u0e47\u0e1a\u0e44\u0e27\u0e49\u0e15\u0e48\u0e2d torrent [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] ConfigView.section.tracker.seedretention.info=\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e2b\u0e15\u0e38: \u0e2a\u0e15\u0e34\u0e16\u0e34\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a seeds \u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e40\u0e01\u0e47\u0e1a\u0e44\u0e27\u0e49\u0e08\u0e30\u0e2a\u0e39\u0e0d\u0e2b\u0e32\u0e22 ConfigView.section.tracker.port=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19 tracker \u0e1a\u0e19\u0e1e\u0e2d\u0e23\u0e4c\u0e15 HTTP ConfigView.section.tracker.sslport=\u0e40\u0e1b\u0e34\u0e14 tracker \u0e1a\u0e19 HTTPS \u0e1e\u0e2d\u0e23\u0e4c\u0e15\u0e44\u0e14\u0e49 ConfigView.section.tracker.publicenable.info=\u0e19\u0e35\u0e48\u0e40\u0e1b\u0e47\u0e19\u0e01\u0e32\u0e23\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e43\u0e2b\u0e49\u0e1c\u0e39\u0e49\u0e2d\u0e37\u0e48\u0e19\u0e2a\u0e23\u0e49\u0e32\u0e07 torrents \u0e17\u0e35\u0e48\u0e43\u0e0a\u0e49 tracker\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\n\u0e42\u0e14\u0e22\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e44\u0e21\u0e48\u0e15\u0e49\u0e2d\u0e07 hosting/publishing Button.clear=\u0e25\u0e49\u0e32\u0e07 MainWindow.IPs.tooltip=\u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d\u0e01\u0e23\u0e2d\u0e07\u0e25\u0e48\u0e32\u0e2a\u0e38\u0e14: %1\n\u0e08\u0e33\u0e19\u0e27\u0e19\u0e23\u0e27\u0e21\u0e02\u0e2d\u0e07 IP \u0e17\u0e35\u0e48\u0e01\u0e23\u0e2d\u0e07 - \u0e08\u0e33\u0e19\u0e27\u0e19\u0e17\u0e35\u0e48\u0e01\u0e31\u0e19/\u0e2b\u0e49\u0e32\u0e21/IPs \u0e40\u0e2a\u0e35\u0e22 \u0e23\u0e30\u0e22\u0e30\u0e19\u0e35\u0e49\n\u0e14\u0e31\u0e1a\u0e40\u0e1a\u0e34\u0e49\u0e25\u0e04\u0e25\u0e34\u0e01\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 ConfigView.section.ipfilter.list.banned=\u0e16\u0e39\u0e01\u0e01\u0e31\u0e19\u0e08\u0e32\u0e01\u0e01\u0e32\u0e23\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e2a\u0e35\u0e22 ConfigView.section.ipfilter.list.baddata=\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e2a\u0e35\u0e22: \u0e40\u0e01\u0e34\u0e14\u0e02\u0e36\u0e49\u0e19 = Button.reset=\u0e1b\u0e23\u0e31\u0e1a\u0e43\u0e2b\u0e21\u0e48 ConfigView.section.ipfilter.bannedinfo=IPs \u0e17\u0e35\u0e48\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e2a\u0e35\u0e22 - \u0e2b\u0e49\u0e32\u0e21\u0e16\u0e49\u0e32\u0e16\u0e36\u0e07\u0e17\u0e35\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14 ConfigView.section.ipfilter.blockedinfo=IPs \u0e17\u0e35\u0e48\u0e16\u0e39\u0e01\u0e01\u0e31\u0e19\u0e08\u0e32\u0e01\u0e01\u0e32\u0e23\u0e01\u0e23\u0e2d\u0e07 IP download.removerules.name=\u0e01\u0e0e\u0e01\u0e32\u0e23\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01 download.removerules.unauthorised.info=torrents \u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15 \u0e04\u0e37\u0e2d \u0e1e\u0e27\u0e01\u0e17\u0e35\u0e48\u0e41\u0e08\u0e49\u0e07\u0e01\u0e32\u0e23\u0e15\u0e2d\u0e1a\u0e01\u0e25\u0e31\u0e1a\u0e27\u0e48\u0e32 "\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15" \u0e2b\u0e23\u0e37\u0e2d "\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15" \u0e43\u0e19 "\u0e01\u0e32\u0e23\u0e15\u0e2d\u0e1a\u0e01\u0e25\u0e31\u0e1a\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14" download.removerules.unauthorised=\u0e40\u0e2d\u0e32 torrents \u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e2d\u0e2d\u0e01\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 download.removerules.unauthorised.seedingonly=\t\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e40\u0e21\u0e37\u0e48\u0e2d seeding download.removerules.removed.ok=\u0e40\u0e2d\u0e32 torrent '%1' \u0e17\u0e35\u0e48\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e2d\u0e2d\u0e01\u0e42\u0e14\u0e22\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34 \u0e19\u0e35\u0e48\u0e40\u0e01\u0e34\u0e14\u0e08\u0e32\u0e01\u0e01\u0e0f\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01\u0e02\u0e2d\u0e07 torrent download.removerules.updatetorrents=\u0e40\u0e2d\u0e32 Vuze \u0e2d\u0e31\u0e1e\u0e40\u0e14\u0e17 torrents \u0e2d\u0e2d\u0e01 \u0e16\u0e49\u0e32 swarm \u0e08\u0e33\u0e40\u0e1b\u0e47\u0e19 ConfigView.label.defaultstarttorrentsstopped=\u0e42\u0e14\u0e22\u0e1e\u0e37\u0e49\u0e19\u0e10\u0e32\u0e19\u0e40\u0e1e\u0e34\u0e48\u0e21 torrents \u0e43\u0e2b\u0e21\u0e48\u0e43\u0e19\u0e2a\u0e20\u0e32\u0e1e\u0e2b\u0e22\u0e38\u0e14 ConfigView.section.server.enableudp=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23 UDP tracker client upnp.mapping.dataportudp=UDP tracker client \u0e1e\u0e2d\u0e23\u0e4c\u0e15 ConfigView.section.file.decoder.showlax=\u0e41\u0e2a\u0e14\u0e07\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32\u0e23\u0e2b\u0e31\u0e2a\u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e19\u0e48\u0e32\u0e08\u0e30\u0e43\u0e0a\u0e48 ConfigView.section.file.decoder.showall=\u0e14\u0e39\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32\u0e23\u0e2b\u0e31\u0e2a\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 MainWindow.status.updowndetails.tooltip=\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27 Upload/download - \u0e04\u0e25\u0e34\u0e01\u0e02\u0e27\u0e32\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19 ConfigView.section.tracker.natcheckenable=\u0e15\u0e23\u0e27\u0e08\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e02\u0e2d\u0e07 'port \u0e23\u0e31\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25' \u0e41\u0e25\u0e30\u0e41\u0e08\u0e49\u0e07\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e41\u0e01\u0e48 peers ConfigView.section.tracker.publishenabledetails=\u0e2d\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 torrent \u0e41\u0e25\u0e30\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 peer ConfigView.section.tracker.publishenablepeerdetails=\u0e41\u0e2a\u0e14\u0e07\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 peer MyTrackerView.badnat=NAT \u0e40\u0e2a\u0e35\u0e22 MyTrackerView.badnat.info=Seeds/Peers \u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e1c\u0e48\u0e32\u0e19\u0e01\u0e32\u0e23\u0e15\u0e23\u0e27\u0e08 NAT, \u0e16\u0e49\u0e32\u0e40\u0e1b\u0e34\u0e14\u0e43\u0e0a\u0e49 ConfigView.section.tracker.natchecktimeout=\u0e01\u0e32\u0e23\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e02\u0e32\u0e14\u0e2b\u0e32\u0e22 (\u0e27\u0e34\u0e19\u0e32\u0e17\u0e35) ConfigView.section.file.perf.cache.enable=\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19 disk cache ConfigView.section.file.perf.cache.size=\u0e02\u0e19\u0e32\u0e14\u0e02\u0e2d\u0e07 cache \u0e43\u0e19 %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u0e2a\u0e48\u0e07& MainWindow.menu.transfers.startalltransfers=\u0e40\u0e23\u0e34\u0e48&\u0e21\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 MainWindow.menu.transfers.stopalltransfers=\u0e2b\u0e22\u0e38&\u0e14\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 MainWindow.menu.transfers.pausetransfers=&\u0e2b\u0e22\u0e38\u0e14 MainWindow.menu.transfers.resumetransfers=&\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e15\u0e48\u0e2d ConfigView.label.experimental.osx.kernel.panic.fix=\u0e17\u0e14\u0e25\u0e2d\u0e07\u0e0b\u0e48\u0e2d\u0e21 kernel panics \u0e1a\u0e19\u0e23\u0e30\u0e1a\u0e1a dual-cpu OSX [\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e40\u0e23\u0e34\u0e48\u0e21\u0e43\u0e2b\u0e21\u0e48] SystemTray.menu.pausetransfers=\u0e2b\u0e22\u0e38\u0e14\u0e01\u0e32\u0e23\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 SystemTray.menu.resumetransfers=\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e15\u0e48\u0e2d ConfigView.section.file.truncate.too.large=\u0e15\u0e31\u0e14\u0e02\u0e19\u0e32\u0e14\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48\u0e17\u0e35\u0e48\u0e43\u0e2b\u0e0d\u0e48\u0e40\u0e01\u0e34\u0e19\u0e44\u0e1b ConfigView.section.file.perf.cache.trace=\u0e14\u0e39\u0e01\u0e32\u0e23\u0e1b\u0e0f\u0e34\u0e1a\u0e31\u0e15\u0e34\u0e01\u0e32\u0e23\u0e02\u0e2d\u0e07 cache \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e01\u0e32\u0e23\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a ConfigView.section.interface.enabletray=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e1a\u0e19 System Tray [\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e40\u0e23\u0e34\u0e48\u0e21\u0e43\u0e2b\u0e21\u0e48] PeerManager.status.error=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 Stats.title.full=\u0e2a\u0e15\u0e34\u0e16\u0e34 TransferStatsView.title.full=\u0e01\u0e32\u0e23\u0e2a\u0e48\u0e07 CacheView.general.size=\u0e02\u0e19\u0e32\u0e14\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 CacheView.general.inUse=\u0e43\u0e0a\u0e49\u0e2d\u0e22\u0e39\u0e48 CacheView.general.title=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Cache CacheView.reads.title=\u0e01\u0e32\u0e23\u0e2d\u0e48\u0e32\u0e19 I/O CacheView.reads.fromFile=\u0e08\u0e32\u0e01 File CacheView.reads.fromCache=\u0e08\u0e32\u0e01 Cache CacheView.reads.hits=\u0e40\u0e02\u0e49\u0e32\u0e16\u0e36\u0e07 CacheView.writes.title=\u0e40\u0e02\u0e35\u0e22\u0e19 I/O CacheView.writes.toCache=\u0e16\u0e36\u0e07 Cache CacheView.writes.toFile=\u0e16\u0e36\u0e07 File CacheView.writes.hits=\u0e1a\u0e31\u0e19\u0e17\u0e35\u0e01\u0e41\u0e25\u0e49\u0e27 CacheView.speeds.title=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 CacheView.speeds.reads=\u0e2d\u0e48\u0e32\u0e19 CacheView.speeds.writes=\u0e40\u0e02\u0e35\u0e22\u0e19 CacheView.speeds.fromCache=\u0e08\u0e32\u0e01/\u0e16\u0e36\u0e07 Cache CacheView.speeds.fromFile=\u0e08\u0e32\u0e01/\u0e16\u0e36\u0e07 File CacheView.reads.amount=\u0e08\u0e33\u0e19\u0e27\u0e19 CacheView.reads.avgsize=\u0e02\u0e19\u0e32\u0e14\u0e40\u0e09\u0e25\u0e35\u0e48\u0e22 openUrl.referrer=\u0e2b\u0e19\u0e49\u0e32 URL \u0e2d\u0e49\u0e32\u0e07\u0e2d\u0e34\u0e07 : openUrl.referrer.info=\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e40\u0e27\u0e47\u0e1a\u0e17\u0e35\u0e48\u0e1a\u0e31\u0e07\u0e04\u0e31\u0e1a\u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19 ConfigView.label.maxuploadspeedseeding=KB/s global max \u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27 upload \u0e40\u0e21\u0e37\u0e48\u0e2d seeding \u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19 [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] ConfigView.label.transfer.ignorepeerports=\u0e25\u0e30\u0e40\u0e27\u0e49\u0e19 peers \u0e17\u0e35\u0e48\u0e21\u0e35 ports \u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 (';' \u0e15\u0e31\u0e27\u0e41\u0e1a\u0e48\u0e07, \u0e15\u0e31\u0e27\u0e2d\u0e22\u0e48\u0e32\u0e07. 0;25) ConfigView.section.proxy.enable_socks.peer=\u0e43\u0e0a\u0e49 proxying \u0e43\u0e19\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d peer (\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e2d\u0e01\u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19) [\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e40\u0e23\u0e34\u0e48\u0e21\u0e43\u0e2b\u0e21\u0e48] ConfigView.section.proxy.peer.informtracker=\u0e40\u0e15\u0e37\u0e2d\u0e19\u0e02\u0e49\u0e2d\u0e08\u0e33\u0e01\u0e31\u0e14\u0e02\u0e2d\u0e07 tracker ConfigView.section.proxy.socks.version=\u0e23\u0e38\u0e48\u0e19\u0e02\u0e2d\u0e07 SOCKS PiecesView.legend.written=\u0e40\u0e02\u0e35\u0e22\u0e19 PiecesView.legend.requested=\u0e23\u0e49\u0e2d\u0e07\u0e02\u0e2d PiecesView.legend.downloaded=Downloaded,\u0e01\u0e33\u0e25\u0e31\u0e07\u0e23\u0e2d\u0e40\u0e02\u0e35\u0e22\u0e19 PiecesView.legend.incache=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e43\u0e19 Cache PiecesView.typeItem.0=\u0e0a\u0e49\u0e32 PiecesView.typeItem.1=\u0e40\u0e23\u0e47\u0e27 PiecesView.type=\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a Security.jar.tools_not_found=JAR signing \u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27 - \u0e44\u0e21\u0e48\u0e1e\u0e1a 'tools.jar' \u0e43\u0e19 %1. \u0e14\u0e39\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14\u0e17\u0e35\u0e48 Tools->Options->Security. Security.jar.signfail=JAR signing \u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27 - %1 ConfigView.section.security.toolsinfo=Signed \u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 JAR \u0e43\u0e0a\u0e49\u0e23\u0e2d\u0e07\u0e23\u0e31\u0e1a\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e1a\u0e32\u0e07\u0e15\u0e31\u0e27, \u0e22\u0e01\u0e15\u0e31\u0e27\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a the Swing Web Interface (\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e15\u0e31\u0e49\u0e07).\n\u0e43\u0e19\u0e01\u0e32\u0e23\u0e17\u0e35\u0e48\u0e08\u0e30 sign \u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 JAR \u0e08\u0e33\u0e40\u0e1b\u0e47\u0e19\u0e17\u0e35\u0e48\u0e08\u0e30\u0e15\u0e49\u0e2d\u0e07\u0e40\u0e02\u0e49\u0e32\u0e16\u0e36\u0e07 'tools.jar' \u0e0b\u0e36\u0e48\u0e07\u0e21\u0e32\u0e1e\u0e23\u0e49\u0e2d\u0e21\u0e01\u0e31\u0e1a\u0e15\u0e31\u0e27\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07 Sun JDK (\u0e44\u0e21\u0e48\u0e43\u0e0a\u0e48 JRE).\n\u0e16\u0e49\u0e32\u0e04\u0e38\u0e13\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07\u0e40\u0e09\u0e1e\u0e32\u0e30 JRE \u0e42\u0e1b\u0e23\u0e14\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07 JDK.\n\u0e42\u0e14\u0e22\u0e1b\u0e01\u0e15\u0e34 Vuze \u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e2b\u0e32\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e43\u0e2b\u0e49\u0e01\u0e31\u0e1a\u0e04\u0e38\u0e13 \u0e41\u0e15\u0e48\u0e16\u0e49\u0e32\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27\u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e15\u0e31\u0e49\u0e07\u0e41\u0e1f\u0e49\u0e21\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e44\u0e14\u0e49\u0e17\u0e35\u0e48\u0e19\u0e35\u0e48 ConfigView.section.security.toolsdir=\u0e41\u0e1f\u0e49\u0e21\u0e17\u0e35\u0e48\u0e21\u0e35 'tools.jar' ConfigView.section.security.choosetoolssavedir=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e41\u0e1f\u0e49\u0e21\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e21\u0e35 'tools.jar' ConfigView.section.proxy.peer.same=\u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32 proxy \u0e41\u0e1a\u0e1a\u0e40\u0e14\u0e35\u0e22\u0e27\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e17\u0e31\u0e49\u0e07\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d tracker \u0e41\u0e25\u0e30 peer proxy ConfigView.section.connection.network.max.simultaneous.connect.attempts=\u0e04\u0e27\u0e32\u0e21\u0e1e\u0e22\u0e32\u0e22\u0e32\u0e21\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e41\u0e1a\u0e1a outbound \u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 [0: \u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19 outbound] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e04\u0e23\u0e31\u0e49\u0e07\u0e17\u0e35\u0e48\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d outbound \u0e04\u0e23\u0e31\u0e49\u0e07\u0e43\u0e2b\u0e21\u0e48 Vuze \u0e08\u0e30\u0e1e\u0e22\u0e32\u0e22\u0e32\u0e21\u0e17\u0e33\u0e15\u0e32\u0e21\u0e17\u0e35\u0e48\u0e01\u0e33\u0e2b\u0e19\u0e14\n\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e2b\u0e15\u0e38: WindowsXP Service Pack 2 (SP2) \u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e08\u0e33\u0e01\u0e31\u0e14\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d system-wide 10 \u0e04\u0e23\u0e31\u0e49\u0e07\n\u0e04\u0e48\u0e32\u0e21\u0e32\u0e15\u0e23\u0e32\u0e10\u0e32\u0e19\u0e04\u0e37\u0e2d 8. \u0e04\u0e48\u0e32 0 \u0e22\u0e01\u0e40\u0e25\u0e34\u0e01\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d outbound \u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14. ConfigView.section.file.perf.cache.size.explain=cache \u0e43\u0e0a\u0e49\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e25\u0e14\u0e01\u0e32\u0e23\u0e2d\u0e48\u0e32\u0e19\u0e08\u0e32\u0e01/\u0e40\u0e02\u0e35\u0e22\u0e19\u0e44\u0e1b disk. \u0e40\u0e27\u0e49\u0e19\u0e41\u0e15\u0e48\u0e27\u0e48\u0e32\u0e04\u0e38\u0e13\u0e43\u0e0a\u0e49\u0e15\u0e31\u0e27\u0e40\u0e25\u0e37\u0e2d\u0e01 java '-XX:MaxDirectMemorySize' \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32\u0e04\u0e27\u0e32\u0e21\u0e08\u0e33 cache \u0e41\u0e25\u0e30\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49 network IO, \u0e04\u0e38\u0e13\u0e04\u0e27\u0e23\u0e43\u0e0a\u0e49\u0e04\u0e48\u0e32\u0e19\u0e35\u0e49\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e15\u0e33 %1 \u0e19\u0e49\u0e2d\u0e22\u0e01\u0e27\u0e48\u0e32\u0e04\u0e48\u0e32\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e02\u0e2d\u0e07 VM. \u0e04\u0e48\u0e32 VM \u0e02\u0e19\u0e32\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e17\u0e31\u0e48\u0e27\u0e44\u0e1b\u0e04\u0e37\u0e2d %2. \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e04\u0e33\u0e41\u0e19\u0e30\u0e19\u0e33\u0e43\u0e19\u0e01\u0e32\u0e23\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32, \u0e14\u0e39\u0e17\u0e35\u0e48 MemoryUsage \u0e43\u0e19 the wiki \u0e1a\u0e19 %3. \u0e2b\u0e32\u0e01\u0e15\u0e31\u0e49\u0e07\u0e41\u0e1a\u0e1a\u0e44\u0e21\u0e48\u0e2a\u0e21\u0e40\u0e2b\u0e15\u0e38\u0e1c\u0e25\u0e2d\u0e32\u0e08 \u0e17\u0e33\u0e43\u0e2b\u0e49\u0e40\u0e01\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1c\u0e25\u0e32\u0e14 '\u0e04\u0e27\u0e32\u0e21\u0e08\u0e33\u0e44\u0e21\u0e48\u0e40\u0e1e\u0e35\u0e22\u0e07\u0e1e\u0e2d'. \u0e21\u0e32\u0e01\u0e01\u0e27\u0e48\u0e32 32MB \u0e02\u0e2d\u0e07 cache\u0e01\u0e47\u0e2d\u0e32\u0e08\u0e08\u0e30\u0e40\u0e01\u0e34\u0e19\u0e1e\u0e2d\u0e14\u0e35. MyTorrentsView.menu.setSpeed.unlimit=\u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14 MyTorrentsView.menu.setSpeed.unlimited=\u0e44\u0e21\u0e48\u0e01\u0e33\u0e2b\u0e19\u0e14 MyTorrentsView.menu.setSpeed.disable=\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01 Upload MyTorrentsView.menu.setSpeed.disabled=\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01 MyTorrentsView.menu.setSpeed.in=\u0e43\u0e19 MyTorrentsView.menu.setSpeed.slots=slots \u0e02\u0e2d\u0e07 GeneralView.label.maxuploadspeed=Up \u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 GeneralView.label.maxuploadspeed.tooltip=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27 Upload \u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 [0 : \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] MyTorrents.items.UpSpeedLimit.disabled=\u0e44\u0e21\u0e48 upload MyTorrents.items.UpSpeedLimit.unlimited=\u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14 TableColumn.header.maxupspeed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27 Up \u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 TableColumn.header.maxupspeed.info=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27 Upload \u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e15\u0e48\u0e2d torrent ConfigView.section.file.perf.cache.enable.write=Cache \u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 download \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e25\u0e14\u0e01\u0e32\u0e23\u0e40\u0e02\u0e35\u0e22\u0e19 disk \u0e41\u0e25\u0e30\u0e25\u0e14\u0e01\u0e32\u0e23\u0e2d\u0e48\u0e32\u0e19 disk \u0e17\u0e35\u0e48\u0e08\u0e33\u0e40\u0e1b\u0e47\u0e19\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e15\u0e23\u0e27\u0e08\u0e0a\u0e34\u0e49\u0e19\u0e2a\u0e48\u0e27\u0e19 ConfigView.section.file.perf.cache.enable.read=\u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e2d\u0e48\u0e32\u0e19\u0e25\u0e48\u0e27\u0e07\u0e2b\u0e19\u0e49\u0e32 \u0e25\u0e14\u0e01\u0e32\u0e23\u0e2d\u0e48\u0e32\u0e19disk reads \u0e40\u0e21\u0e37\u0e48\u0e2d uploading ConfigView.section.tracker.separatepeerids=\u0e43\u0e0a\u0e49\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a peer \u0e15\u0e48\u0e32\u0e07\u0e01\u0e31\u0e19\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a tracker \u0e41\u0e25\u0e30\u0e01\u0e32\u0e23\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 ConfigView.section.tracker.separatepeerids.info=\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e04\u0e27\u0e32\u0e21 anonymity \u0e16\u0e49\u0e32 downloading/seeding anonymously\n\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e01\u0e31\u0e1a tracker \u0e17\u0e35\u0e48\u0e44\u0e21\u0e48 anonymous ConfigView.section.interface.wavlocation=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e02\u0e2d\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 .wav ConfigView.section.interface.wavlocation.info=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 .wav \u0e2b\u0e23\u0e37\u0e2d\u0e1b\u0e25\u0e48\u0e2d\u0e22\u0e27\u0e48\u0e32\u0e07\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e43\u0e0a\u0e49\u0e40\u0e2a\u0e35\u0e22\u0e07\u0e21\u0e32\u0e15\u0e23\u0e32\u0e10\u0e32\u0e19 ConfigView.section.tracker.client.connecttimeout=\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e02\u0e32\u0e14\u0e2b\u0e32\u0e22 (\u0e27\u0e34\u0e19\u0e32\u0e17\u0e35) ConfigView.section.tracker.client.readtimeout=\u0e01\u0e32\u0e23\u0e2d\u0e48\u0e32\u0e19\u0e02\u0e32\u0e14\u0e2b\u0e32\u0e22 (\u0e27\u0e34\u0e19\u0e32\u0e17\u0e35) MainWindow.menu.tools=&\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e21\u0e37\u0e2d FilesView.path=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 FilesView.fullpath=\u0e41\u0e2a\u0e14\u0e07\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e40\u0e15\u0e47\u0e21 FilesView.remaining=\u0e2a\u0e48\u0e27\u0e19\u0e17\u0e35\u0e48\u0e40\u0e2b\u0e25\u0e37\u0e2d TableColumn.header.trackername=\u0e0a\u0e37\u0e48\u0e2d Tracker TableColumn.header.trackername.info=\u0e0a\u0e37\u0e48\u0e2d\u0e02\u0e2d\u0e07 tracker \u0e15\u0e32\u0e21 URL \u0e17\u0e35\u0e48\u0e41\u0e08\u0e49\u0e07 ConfigView.group.override=\u0e15\u0e31\u0e27\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e01\u0e32\u0e23\u0e40\u0e02\u0e35\u0e22\u0e19\u0e17\u0e31\u0e1a ConfigView.section.file.perf.cache.notsmallerthan=\u0e44\u0e21\u0e48 cache \u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e02\u0e19\u0e32\u0e14\u0e40\u0e25\u0e47\u0e01\u0e01\u0e27\u0e48\u0e32 (in %1) PeersView.menu.blockupload=\u0e01\u0e31\u0e19 Upload PeersView.menu.kickandban.reason=banned Peer \u0e40\u0e2d\u0e07 PeersView.state=\u0e2a\u0e20\u0e32\u0e1e PeersView.state.info=\u0e2a\u0e20\u0e32\u0e1e\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d peer PeersView.state.pending=\u0e23\u0e2d PeersView.state.connecting=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d PeersView.state.handshake=\u0e23\u0e2d\u0e08\u0e31\u0e1a\u0e21\u0e37\u0e2d PeersView.state.established=\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c ConfigView.section.tracker.processinglimits=\u0e01\u0e32\u0e23\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23\u0e08\u0e33\u0e01\u0e31\u0e14 ConfigView.section.tracker.maxgettime=\u0e40\u0e27\u0e25\u0e32\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e43\u0e19\u0e01\u0e32\u0e23 GET (\u0e27\u0e34\u0e19\u0e32\u0e17\u0e35) [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] ConfigView.section.tracker.maxgettime.info=\u0e43\u0e0a\u0e49\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e41\u0e08\u0e49\u0e07 \u0e41\u0e25\u0e30 scrapes ConfigView.section.tracker.maxposttimemultiplier=\u0e15\u0e31\u0e27\u0e04\u0e39\u0e13\u0e40\u0e27\u0e25\u0e32 GET\u0e40\u0e1e\u0e37\u0e48\u0e2d POST processing [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] ConfigView.section.tracker.maxposttimemultiplier.info=\u0e43\u0e0a\u0e49\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e2a\u0e48\u0e07 form \u0e41\u0e25\u0e30 uploads ConfigView.section.tracker.maxthreads=\u0e08\u0e33\u0e19\u0e27\u0e19\u0e23\u0e49\u0e2d\u0e07\u0e02\u0e2d\u0e1e\u0e23\u0e49\u0e2d\u0e21\u0e01\u0e31\u0e19\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 DownloadManager.error.operationcancancelled=\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01\u0e1b\u0e0f\u0e34\u0e1a\u0e31\u0e15\u0e34\u0e01\u0e32\u0e23 Torrent.create.progress.cancelled=\u0e22\u0e01\u0e40\u0e25\u0e37\u0e01\u0e01\u0e32\u0e23\u0e1b\u0e0f\u0e34\u0e1a\u0e31\u0e15\u0e34\u0e01\u0e32\u0e23 sharing.progress.cancel=\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01 wizard.maketorrents.autoopen=\u0e40\u0e1b\u0e34\u0e14 torrent \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e01\u0e32\u0e23 seeding \u0e40\u0e21\u0e37\u0e48\u0e2d\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e2a\u0e34\u0e49\u0e19 ConfigView.section.sharing.rescanenable=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e04\u0e49\u0e19\u0e2b\u0e32\u0e40\u0e1b\u0e49\u0e19\u0e23\u0e30\u0e22\u0e30\u0e02\u0e2d\u0e07\u0e2a\u0e48\u0e27\u0e19\u0e17\u0e35\u0e48\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e15\u0e34\u0e14\u0e15\u0e32\u0e21\u0e01\u0e32\u0e23\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e41\u0e1b\u0e25\u0e07 ConfigView.section.sharing.rescanperiod=\u0e0a\u0e48\u0e27\u0e07\u0e43\u0e19\u0e01\u0e32\u0e23\u0e04\u0e49\u0e19\u0e2b\u0e32\u0e43\u0e2b\u0e21\u0e48 (\u0e27\u0e34\u0e19\u0e32\u0e17\u0e35) ConfigView.section.connection.advanced=\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22\u0e0a\u0e31\u0e49\u0e19\u0e2a\u0e39\u0e07 ConfigView.section.connection.advanced.mtu.tooltip=\u0e02\u0e19\u0e32\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e02\u0e2d\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e2a\u0e48\u0e07\u0e1c\u0e48\u0e32\u0e19\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22\u0e43\u0e19\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e04\u0e23\u0e31\u0e49\u0e07\nVuze \u0e43\u0e0a\u0e49 MTU-40 (MSS) \u0e40\u0e1e\u0e37\u0e48\u0e2d upload packet-payload \u0e2d\u0e22\u0e48\u0e32\u0e07\u0e21\u0e35\u0e1b\u0e23\u0e30\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e20\u0e32\u0e1e\n\u0e04\u0e48\u0e32\u0e41\u0e19\u0e30\u0e19\u0e33:\n 576 - \u0e01\u0e32\u0e23\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e15\u0e48\u0e2d\u0e41\u0e1a\u0e1a Dial-up \n1492 - \u0e01\u0e32\u0e23\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e15\u0e48\u0e2d\u0e41\u0e1a\u0e1a PPPoE broadband\n1500 - \u0e01\u0e32\u0e23\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e15\u0e48\u0e2d\u0e41\u0e1a\u0e1a Ethernet, DSL \u0e41\u0e25\u0e30 Cable broadband ConfigView.section.connection.advanced.SO_RCVBUF=Socket SO_RCVBUF size [0: \u0e43\u0e0a\u0e49\u0e04\u0e48\u0e32\u0e21\u0e32\u0e15\u0e23\u0e32\u0e10\u0e32\u0e19\u0e02\u0e2d\u0e07 OS] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32 standard socket SO_RCVBUF (\u0e2b\u0e19\u0e48\u0e27\u0e22 bytes), \u0e15\u0e31\u0e27\u0e2d\u0e22\u0e48\u0e32\u0e07. TCP \u0e23\u0e31\u0e1a\u0e02\u0e19\u0e32\u0e14 window \u0e41\u0e25\u0e30 \u0e2a\u0e31\u0e14\u0e2a\u0e48\u0e27\u0e19\nVuze \u0e40\u0e27\u0e49\u0e19\u0e0a\u0e48\u0e2d\u0e07\u0e19\u0e35\u0e49\u0e44\u0e27\u0e49\u0e40\u0e1b\u0e47\u0e19\u0e04\u0e48\u0e32\u0e21\u0e32\u0e15\u0e23\u0e32\u0e10\u0e32\u0e19, \u0e2b\u0e21\u0e32\u0e22\u0e04\u0e27\u0e32\u0e21\u0e27\u0e48\u0e32\u0e43\u0e0a\u0e49\u0e04\u0e48\u0e32\u0e21\u0e32\u0e15\u0e23\u0e32\u0e10\u0e32\u0e19\u0e02\u0e2d\u0e07 underlying OS .\n\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e2b\u0e15\u0e38: Linux \u0e22\u0e01\u0e01\u0e33\u0e25\u0e31\u0e07\u0e2a\u0e2d\u0e07\u0e04\u0e48\u0e32\u0e17\u0e35\u0e48\u0e43\u0e2b\u0e49. ConfigView.section.connection.advanced.SO_SNDBUF=\u0e02\u0e19\u0e32\u0e14 Socket SO_SNDBUF [0: \u0e43\u0e0a\u0e49\u0e04\u0e48\u0e32\u0e21\u0e32\u0e15\u0e23\u0e32\u0e10\u0e32\u0e19\u0e02\u0e2d\u0e07 OS] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32 the standard socket SO_SNDBUF (\u0e43\u0e19 bytes), \u0e15.\u0e22.. TCP \u0e2a\u0e48\u0e07\u0e02\u0e19\u0e32\u0e14 window\nVuze \u0e40\u0e27\u0e49\u0e19\u0e04\u0e48\u0e32\u0e19\u0e35\u0e49\u0e44\u0e27\u0e49\u0e40\u0e1b\u0e47\u0e19\u0e21\u0e32\u0e15\u0e23\u0e32\u0e10\u0e32\u0e19,\u0e2b\u0e21\u0e32\u0e22\u0e04\u0e27\u0e32\u0e21\u0e27\u0e48\u0e32\u0e43\u0e0a\u0e49\u0e04\u0e48\u0e32 underlying OS\n\u0e2b\u0e21\u0e32\u0e02\u0e40\u0e2b\u0e15\u0e38: Linux \u0e01\u0e33\u0e25\u0e31\u0e07\u0e2a\u0e2d\u0e07\u0e04\u0e48\u0e32\u0e17\u0e35\u0e48\u0e43\u0e2b\u0e49 ConfigView.section.interface.confirm_torrent_removal=\u0e41\u0e2a\u0e14\u0e07\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e43\u0e19\u0e01\u0e32\u0e23\u0e40\u0e2d\u0e32 torrent \u0e2d\u0e2d\u0e01 ConfigView.section.interface.confirm_torrent_removal.tooltip=\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e40\u0e2d\u0e32 torrent \u0e2d\u0e2d\u0e01\u0e08\u0e32\u0e01 Torrents \u0e02\u0e2d\u0e07\u0e09\u0e31\u0e19 MyTorrentsView.confirm_torrent_removal=\u0e04\u0e38\u0e13\u0e41\u0e19\u0e48\u0e43\u0e08\u0e40\u0e2b\u0e23\u0e2d\u0e17\u0e35\u0e48\u0e08\u0e30\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01?\n TableColumn.header.seed_to_peer_ratio=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19 Seed2Peer TableColumn.header.seed_to_peer_ratio.info=\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19 seeds \u0e15\u0e48\u0e2d peers \u0e1a\u0e19 swarm PeersView.connected_time=\u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d PeersView.connected_time.info=\u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14\u0e01\u0e31\u0e1a peer ConfigView.section.interface.display.add_torrents_silently=\u0e40\u0e1e\u0e34\u0e48\u0e21 torrents silently ConfigView.section.interface.display.add_torrents_silently.tooltip=\u0e40\u0e1e\u0e34\u0e48\u0e21 torrent downloads \u0e42\u0e14\u0e22\u0e44\u0e21\u0e48\u0e01\u0e25\u0e31\u0e1a\u0e44\u0e1b\u0e17\u0e35\u0e48\u0e2b\u0e19\u0e49\u0e32\u0e15\u0e48\u0e32\u0e07 Vuze TableColumn.header.maxdownspeed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27 Down \u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 TableColumn.header.maxdownspeed.info=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27 Download \u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14\u0e15\u0e48\u0e2d torrent ConfigView.section.tracker.passwordwebhttpsonly=\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e34\u0e01\u0e32\u0e23\u0e40\u0e02\u0e49\u0e32\u0e17\u0e32\u0e07 HTTPS \u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19 TableColumn.header.torrentpath=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 Torrent TableColumn.header.torrentpath.info=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07\u0e02\u0e2d\u0e07 Torrent \u0e1a\u0e19 disk ConfigView.section.sharing.torrentcomment=\u0e02\u0e49\u0e2d\u0e1a\u0e48\u0e07\u0e0a\u0e35\u0e49\u0e43\u0e19\u0e01\u0e32\u0e23\u0e2a\u0e23\u0e49\u0e32\u0e07 torrents ConfigView.label.copyanddeleteratherthanmove=\u0e04\u0e48\u0e2d\u0e22\u0e46\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e41\u0e25\u0e49\u0e27\u0e25\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e14\u0e34\u0e21\u0e21\u0e32\u0e01\u0e01\u0e27\u0e48\u0e32\u0e08\u0e30\u0e22\u0e49\u0e32\u0e22\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14\u0e43\u0e19\u0e17\u0e35\u0e40\u0e14\u0e35\u0e22\u0e27 - \u0e0a\u0e48\u0e27\u0e22\u0e25\u0e14\u0e01\u0e32\u0e23\u0e40\u0e2a\u0e35\u0e22\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e1a\u0e19\u0e1a\u0e32\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e23\u0e30\u0e1a\u0e1a ConfigView.label.openstatsonstart=\u0e40\u0e1b\u0e34\u0e14\u0e2a\u0e16\u0e34\u0e15\u0e34\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e40\u0e23\u0e34\u0e48\u0e21\u0e17\u0e33\u0e07\u0e32\u0e19 swt.install.window.title=\u0e15\u0e31\u0e27\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21 Vuze swt.install.window.ok=\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07 swt.install.window.header=\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07\u0e2a\u0e48\u0e27\u0e19\u0e1b\u0e23\u0e30\u0e01\u0e2d\u0e1a\u0e14\u0e31\u0e07\u0e19\u0e35\u0e49 : swt.uninstall.window.title=\u0e15\u0e31\u0e27\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21 Vuze swt.uninstall.window.ok=\u0e40\u0e2d\u0e32\u0e2d\u0e2d\u0e01 swt.uninstall.window.header=\u0e16\u0e2d\u0e14\u0e16\u0e2d\u0e19\u0e2a\u0e48\u0e27\u0e19\u0e1b\u0e23\u0e30\u0e01\u0e2d\u0e1a\u0e14\u0e31\u0e07\u0e19\u0e35\u0e49 : installPluginsWizard.title=\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21 installPluginsWizard.mode.title=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e27\u0e34\u0e18\u0e35\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07 installPluginsWizard.mode.list=\u0e42\u0e14\u0e22\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d\u0e08\u0e32\u0e01 sourceforge.net installPluginsWizard.list.title=\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e17\u0e35\u0e48\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07\u0e44\u0e14\u0e49 installPluginsWizard.list.loading=\u0e42\u0e1b\u0e23\u0e14\u0e23\u0e2d\u0e01\u0e33\u0e25\u0e31\u0e07\u0e40\u0e23\u0e35\u0e22\u0e01\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21 installPluginsWizard.list.loaded=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e17\u0e35\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07 installPluginsWizard.list.name=\u0e0a\u0e37\u0e48\u0e2d installPluginsWizard.list.version=\u0e23\u0e38\u0e48\u0e19 installPluginsWizard.list.description=\u0e2d\u0e18\u0e34\u0e1a\u0e32\u0e22\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21 installPluginsWizard.finish.title=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07 installPluginsWizard.finish.explanation=\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e01\u0e33\u0e25\u0e31\u0e07\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07\u0e42\u0e14\u0e22\u0e15\u0e31\u0e27\u0e0a\u0e48\u0e27\u0e22\u0e01\u0e32\u0e23\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e38\u0e25\n\n\u0e42\u0e1b\u0e23\u0e14\u0e23\u0e2d, \u0e2d\u0e32\u0e08\u0e43\u0e0a\u0e49\u0e40\u0e27\u0e25\u0e32\u0e2a\u0e31\u0e01\u0e04\u0e23\u0e39\u0e48.\n\n\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e23\u0e32\u0e22\u0e07\u0e32\u0e19\u0e2a\u0e16\u0e32\u0e19\u0e30, \u0e14\u0e31\u0e1a\u0e40\u0e1a\u0e34\u0e49\u0e25\u0e04\u0e25\u0e34\u0e01\u0e0b\u0e49\u0e32\u0e22\u0e02\u0e2d\u0e07 status bar. installPluginsWizard.details.loading=\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 loading, \u0e42\u0e1b\u0e23\u0e14\u0e23\u0e2d... installPluginsWizard.mode.file=\u0e42\u0e14\u0e22 file installPluginsWizard.installMode.title=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07 installPluginsWizard.installMode.user=\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e04\u0e38\u0e13\u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19 installPluginsWizard.installMode.shared=\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e1c\u0e39\u0e49\u0e43\u0e0a\u0e49\u0e17\u0e38\u0e01\u0e04\u0e19 installPluginsWizard.file.title=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e17\u0e35\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07 installPluginsWizard.file.invalidfile=\u0e19\u0e35\u0e48\u0e44\u0e21\u0e48\u0e43\u0e0a\u0e48\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21 Vuze \u0e17\u0e35\u0e48\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07 installPluginsWizard.file.browse=\u0e40\u0e25\u0e37\u0e2d\u0e01... uninstallPluginsWizard.title=\u0e16\u0e2d\u0e14\u0e16\u0e2d\u0e19\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21 uninstallPluginsWizard.list.title=\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e17\u0e35\u0e48\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07 uninstallPluginsWizard.list.loaded=\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e34\u0e01\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e17\u0e35\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e16\u0e2d\u0e14\u0e16\u0e2d\u0e19 installPluginsWizard.list.nullversion=\u0e44\u0e21\u0e48\u0e41\u0e2a\u0e14\u0e07\u0e23\u0e38\u0e48\u0e19 uninstallPluginsWizard.finish.title=\u0e01\u0e33\u0e25\u0e31\u0e07\u0e16\u0e2d\u0e14\u0e16\u0e2d\u0e19 uninstallPluginsWizard.finish.explanation=\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e17\u0e35\u0e48\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e08\u0e30\u0e16\u0e39\u0e01\u0e16\u0e2d\u0e14\u0e16\u0e2d\u0e19\u0e42\u0e14\u0e22\u0e15\u0e31\u0e27\u0e0a\u0e48\u0e27\u0e22\u0e01\u0e32\u0e23\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 MainWindow.menu.plugins.installPlugins=\u0e15\u0e31\u0e27\u0e0a\u0e48\u0e27\u0e22\u0e01\u0e32\u0e23\u0e15\u0e34\u0e15\u0e15\u0e31\u0e49\u0e07... MainWindow.menu.plugins.uninstallPlugins=\u0e15\u0e31\u0e27\u0e0a\u0e48\u0e27\u0e22\u0e01\u0e32\u0e23\u0e16\u0e2d\u0e14\u0e16\u0e2d\u0e19... ConfigView.section.ipfilter.totalIPs=%1 IPs \u0e17\u0e35\u0e48\u0e01\u0e31\u0e19\u0e42\u0e14\u0e22\u0e23\u0e27\u0e21l, \u0e0b\u0e36\u0e48\u0e07\u0e40\u0e1b\u0e47\u0e19 %2 \u0e02\u0e2d\u0e07 internet. update.instance.install=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07 update.instance.uninstall=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e01\u0e32\u0e23\u0e16\u0e2d\u0e14\u0e16\u0e2d\u0e19 update.instance.update=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e43\u0e2b\u0e21\u0e48 MainWindow.status.update.tooltip=\u0e14\u0e31\u0e1a\u0e40\u0e1a\u0e34\u0e49\u0e25\u0e04\u0e25\u0e34\u0e01\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e41\u0e2a\u0e14\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e01\u0e32\u0e23\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23 updater.progress.window.title=\u0e2b\u0e19\u0e49\u0e32\u0e17\u0e35\u0e48\u0e15\u0e34\u0e14\u0e15\u0e31\u0e49\u0e07\u0e1b\u0e31\u0e08\u0e38\u0e1a\u0e31\u0e19 updater.progress.window.info=\u0e01\u0e14 '\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01' \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e1b\u0e34\u0e14\u0e2b\u0e19\u0e49\u0e32\u0e17\u0e35\u0e48\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14 Button.abort=\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01 ConfigView.section.ipfilter.enablebanning=\u0e01\u0e31\u0e19 peers \u0e17\u0e35\u0e48\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e40\u0e2a\u0e35\u0e22 Network.alert.acceptfail=\u0e21\u0e35\u0e01\u0e32\u0e23\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e01\u0e31\u0e19\u0e40\u0e01\u0e34\u0e14\u0e02\u0e35\u0e49\u0e19\u0e17\u0e35\u0e48 port %1, %2 - \u0e22\u0e01\u0e40\u0e25\u0e34\u0e01\u0e01\u0e32\u0e23\u0e1b\u0e0f\u0e34\u0e1a\u0e31\u0e15\u0e34. \u0e42\u0e1b\u0e23\u0e14\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e04\u0e48\u0e32 firewall \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a port \u0e19\u0e35\u0e49\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e43\u0e2b\u0e49\u0e41\u0e19\u0e48\u0e43\u0e08\u0e27\u0e48\u0e32\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e44\u0e27\u0e49 MyShares.column.category=\u0e1b\u0e23\u0e30\u0e40\u0e20\u0e17 UpdateWindow.restartLater=\u0e40\u0e23\u0e34\u0e48\u0e21\u0e17\u0e35\u0e2b\u0e25\u0e31\u0e07 MainWindow.menu.file.restart=\u0e40\u0e23\u0e34\u0e48\u0e21 Vuze \u0e43\u0e2b\u0e21\u0e48 MainWindow.dialog.restartconfirmation.title=\u0e40\u0e23\u0e34\u0e48\u0e21 Vuze \u0e43\u0e2b\u0e21\u0e48? MainWindow.dialog.restartconfirmation.text=\u0e04\u0e38\u0e13\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e17\u0e35\u0e48\u0e08\u0e30\u0e40\u0e23\u0e34\u0e48\u0e21 Vuze \u0e43\u0e2b\u0e21\u0e48? deletetorrent.message1=\u0e04\u0e38\u0e13\u0e01\u0e33\u0e25\u0e31\u0e07\u0e08\u0e30\u0e25\u0e1a TORRENT\u0e40\u0e1e\u0e37\u0e48\u0e2d :\n deletetorrent.message2=\n\u0e04\u0e38\u0e13\u0e41\u0e19\u0e48\u0e43\u0e08\u0e17\u0e35\u0e48\u0e08\u0e30\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23\u0e15\u0e48\u0e2d? ConfigView.label.prioritizemostcompletedfiles=\u0e08\u0e31\u0e14\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e01\u0e31\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e48\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e17\u0e35\u0e48\u0e2a\u0e38\u0e14 splash.plugin.init=\u0e40\u0e23\u0e34\u0e48\u0e21\u0e15\u0e31\u0e27\u0e40\u0e2a\u0e23\u0e34\u0e21: ConfigView.section.style.osx_small_fonts=\u0e43\u0e0a\u0e49\u0e2d\u0e31\u0e01\u0e29\u0e23\u0e40\u0e25\u0e47\u0e01 [\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e40\u0e23\u0e34\u0e48\u0e21\u0e43\u0e2b\u0e21\u0e48] ConfigView.section.tracker.tcpnonblocking=\u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e44\u0e21\u0e48\u0e1a\u0e31\u0e07 I/O \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23 TCP tracker. \u0e43\u0e0a\u0e49\u0e15\u0e31\u0e27\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e19\u0e35\u0e49\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23 tracker web\u0e17\u0e35\u0e48\u0e17\u0e33\u0e07\u0e32\u0e19\u0e1a\u0e19 alternative port. \u0e01\u0e33\u0e25\u0e31\u0e07\u0e17\u0e14\u0e25\u0e2d\u0e07! ConfigView.section.tracker.nonblocking=\u0e15\u0e31\u0e27\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e44\u0e21\u0e48\u0e1b\u0e34\u0e14\u0e01\u0e31\u0e19 ConfigView.section.tracker.nonblockingconcmax=\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e1e\u0e23\u0e49\u0e2d\u0e21\u0e01\u0e31\u0e19\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 [0: \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14] MyTorrentsView.menu.exportmenu=\u0e2a\u0e48\u0e07\u0e2d\u0e2d\u0e01 ConfigView.section.tracker.client.scrapeinfo=\u0e40\u0e25\u0e34\u0e01\u0e43\u0e0a\u0e49 scraping \u0e08\u0e30\u0e01\u0e31\u0e19\u0e01\u0e0f\u0e01\u0e32\u0e23\u0e40\u0e23\u0e35\u0e22\u0e07\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a torrent \u0e44\u0e21\u0e48\u0e43\u0e2b\u0e49\u0e17\u0e33\u0e07\u0e32\u0e19 \u0e40\u0e19\u0e37\u0e48\u0e2d\u0e07\u0e08\u0e32\u0e01\u0e15\u0e49\u0e2d\u0e07\u0e43\u0e0a\u0e49\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 swarm \u0e42\u0e14\u0e22 scraping trackers. ConfigView.section.tracker.client.scrapeenable=\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19 scraping ConfigView.section.tracker.client.scrapestoppedenable=Scrape torrents \u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23 Scrape.status.disabled=\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01 Scrape MyTorrentsView.menu.explore=\u0e41\u0e2a\u0e14\u0e07 File MyTorrentsView.menu.explore._mac=\u0e41\u0e2a\u0e14\u0e07\u0e43\u0e19 Finder MyTorrentsView.menu.explore._windows=\u0e41\u0e2a\u0e14\u0e07\u0e43\u0e19 Explorer wizard.maketorrents.autohost=\u0e40\u0e1c\u0e22\u0e41\u0e1e\u0e23\u0e48 torrent \u0e1a\u0e19 tracker \u0e43\u0e19\u0e15\u0e31\u0e27 ConfigView.label.overrideip=\u0e40\u0e02\u0e35\u0e22\u0e19\u0e17\u0e31\u0e1a IP address \u0e17\u0e35\u0e48\u0e2a\u0e48\u0e07\u0e44\u0e1b tracker - \u0e43\u0e0a\u0e49\u0e15\u0e48\u0e2d\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e04\u0e38\u0e13\u0e23\u0e39\u0e49\u0e41\u0e19\u0e48\u0e27\u0e48\u0e32\u0e17\u0e33\u0e44\u0e21\u0e04\u0e38\u0e13\u0e08\u0e33\u0e40\u0e1b\u0e47\u0e19\u0e15\u0e49\u0e2d\u0e07\u0e17\u0e33\u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19! ConfigView.label.overrideip.tooltip=\u0e1a\u0e2d\u0e01 tracker \u0e02\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02 IP \u0e2d\u0e37\u0e48\u0e19 \u0e19\u0e2d\u0e01\u0e40\u0e2b\u0e19\u0e37\u0e2d\u0e08\u0e32\u0e01\u0e2d\u0e31\u0e19\u0e17\u0e35\u0e48\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e2a\u0e48\u0e07\u0e21\u0e32. \u0e1b\u0e25\u0e48\u0e2d\u0e22\u0e27\u0e48\u0e32\u0e07\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e19\u0e35\u0e49 ConfigView.section.connection.group.networks=\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22 ConfigView.section.connection.group.networks.info=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22\u0e17\u0e35\u0e48\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e34\u0e42\u0e14\u0e22\u0e21\u0e32\u0e15\u0e23\u0e32\u0e10\u0e32\u0e19 \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e41\u0e1a\u0e1a peer-peer ConfigView.section.connection.networks.prompt=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e01\u0e32\u0e23 download \u0e42\u0e14\u0e22 anonymous tracker \u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e40\u0e1e\u0e34\u0e48\u0e21 ConfigView.section.connection.networks.Public=\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22 IP \u0e2a\u0e32\u0e18\u0e32\u0e23\u0e13\u0e30 (\u0e44\u0e21\u0e48 anonymous) ConfigView.section.connection.networks.I2P=\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22 I2P TableColumn.header.networks=\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22 TableColumn.header.networks.info=\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22\u0e17\u0e35\u0e48\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e34\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e41\u0e1a\u0e1a peer-peer Scrape.status.networkdisabled=\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e40\u0e1b\u0e34\u0e14\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22 ConfigView.section.tracker.server.group.networks.info=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22\u0e17\u0e35\u0e48 tracker \u0e08\u0e30\u0e22\u0e2d\u0e21\u0e23\u0e31\u0e1a peers window.networkselection.title=\u0e40\u0e25\u0e37\u0e2d\u0e01 Network window.networkselection.info=Torrent \u0e17\u0e35\u0e48\u0e41\u0e2a\u0e14\u0e07\u0e02\u0e49\u0e32\u0e07\u0e25\u0e48\u0e32\u0e07\u0e21\u0e35 tracker(s) \u0e17\u0e35\u0e48\u0e2a\u0e19\u0e31\u0e1a\u0e2a\u0e19\u0e38\u0e19\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22\u0e15\u0e48\u0e2d\u0e44\u0e1b\u0e19\u0e35\u0e49\n\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e2d\u0e31\u0e19\u0e17\u0e35\u0e48\u0e08\u0e30\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e02\u0e2d\u0e07 tracker \u0e41\u0e25\u0e30 peer\n\u0e16\u0e49\u0e32\u0e40\u0e1b\u0e47\u0e19 anonymous tracker\u0e17\u0e35\u0e48\u0e2a\u0e19\u0e31\u0e1a\u0e2a\u0e19\u0e38\u0e19\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e2d\u0e37\u0e48\u0e19\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e17\u0e31\u0e49\u0e07\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22 anonymous \u0e41\u0e25\u0e30 \u0e2a\u0e32\u0e18\u0e32\u0e23\u0e13\u0e30\n\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22\u0e2a\u0e32\u0e18\u0e32\u0e23\u0e13\u0e30\u0e21\u0e35\u0e1c\u0e25\u0e43\u0e19\u0e01\u0e32\u0e23\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01 anonymity! plugins.basicview.clear=\u0e25\u0e49\u0e32\u0e07 ConfigView.section.connection.group.peersources=\u0e41\u0e2b\u0e25\u0e48\u0e07 Peer ConfigView.section.connection.group.peersources.info=\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e41\u0e2b\u0e25\u0e48\u0e07\u0e17\u0e35\u0e48\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e34\u0e42\u0e14\u0e22\u0e21\u0e32\u0e15\u0e23\u0e32\u0e10\u0e32\u0e19\u0e43\u0e19\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d peer ConfigView.section.connection.peersource.Tracker=\u0e08\u0e32\u0e01 tracker ConfigView.section.connection.peersource.DHT=tracking \u0e41\u0e1a\u0e1a\u0e01\u0e23\u0e30\u0e08\u0e32\u0e22 ConfigView.section.connection.peersource.PeerExchange=\u0e41\u0e1a\u0e48\u0e07\u0e42\u0e14\u0e22 peer \u0e2d\u0e37\u0e48\u0e19 ConfigView.section.connection.peersource.Plugin=\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21 ConfigView.section.connection.peersource.Incoming=\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e40\u0e02\u0e49\u0e32 PeersView.source=\u0e41\u0e2b\u0e25\u0e48\u0e07 PeersView.source.info=\u0e41\u0e2b\u0e25\u0e48\u0e07\u0e02\u0e2d\u0e07 peer \u0e19\u0e35\u0e49 TableColumn.header.peersources=\u0e41\u0e2b\u0e25\u0e48\u0e07 Peer TableColumn.header.peersources.info=\u0e41\u0e2b\u0e25\u0e48\u0e07 Peer \u0e17\u0e35\u0e48\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e34\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e02\u0e2d\u0e07 peer wizard.tracker.dht=Decentralized (\u0e43\u0e0a\u0e49\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21 Vuze MyTorrentsView.menu.advancedmenu=\u0e02\u0e31\u0e49\u0e19\u0e2a\u0e39\u0e07 MyTorrentsView.menu.networks=\u0e40\u0e04\u0e23\u0e37\u0e2d\u0e02\u0e48\u0e32\u0e22 MyTorrentsView.menu.peersource=\u0e41\u0e2b\u0e25\u0e48\u0e07 Peers ConfigView.section.sharing.permitdht=\u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e01\u0e23\u0e30\u0e08\u0e32\u0e22 tracking\u0e40\u0e21\u0e37\u0e48\u0e2d tracker \u0e44\u0e21\u0e48\u0e41\u0e2a\u0e14\u0e07 ConfigView.section.sharing.protocol=Protocol \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e41\u0e1a\u0e48\u0e07\u0e1b\u0e31\u0e19\u0e17\u0e23\u0e31\u0e1e\u0e22\u0e32\u0e01\u0e23 PeersView.Messaging=\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21 PeersView.Messaging.info=\u0e2a\u0e19\u0e31\u0e1a\u0e2a\u0e19\u0e38\u0e19\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21 API \u0e0a\u0e31\u0e49\u0e19\u0e2a\u0e39\u0e07. ConfigView.label.queue.newseedsmovetop=\u0e22\u0e49\u0e32\u0e22 torrents \u0e17\u0e35\u0e48\u0e1e\u0e36\u0e48\u0e07\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e44\u0e1b\u0e1a\u0e19\u0e2a\u0e38\u0e14\u0e02\u0e2d\u0e07\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d seeding ConfigView.label.seeding.firstPriority.ignore.info=\u0e1e\u0e36\u0e07\u0e23\u0e30\u0e27\u0e31\u0e07\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e01\u0e0f\u0e19\u0e35\u0e49\u0e2d\u0e32\u0e08\u0e2b\u0e22\u0e38\u0e14 torrent\nas \u0e40\u0e21\u0e37\u0e48\u0e2d\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e2a\u0e23\u0e47\u0e08\u0e17\u0e31\u0e19\u0e17\u0e35 ConfigView.label.seeding.firstPriority.ignore=\u0e25\u0e30\u0e40\u0e27\u0e49\u0e19\u0e01\u0e0f\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e04\u0e31\u0e0d\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e41\u0e23\u0e01\u0e14\u0e49\u0e32\u0e19\u0e1a\u0e19\u0e40\u0e1e\u0e37\u0e48\u0e2d : ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents \u0e17\u0e35\u0e48\u0e2d\u0e31\u0e15\u0e23\u0e32\u0e2a\u0e48\u0e27\u0e19 Seeds \u0e15\u0e48\u0e2d Peers \u0e40\u0e01\u0e34\u0e19 ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents \u0e17\u0e35\u0e48\u0e21\u0e35 0 Peers ConfigView.section.tracker.sendjavaversionandos=\u0e2a\u0e48\u0e07\u0e23\u0e38\u0e48\u0e19\u0e02\u0e2d\u0e07 Java \u0e41\u0e25\u0e30\u0e0a\u0e37\u0e48\u0e2d OS MagnetPlugin.contextmenu.exporturi=Copy Magnet URI \u0e44\u0e1b\u0e17\u0e35\u0e48 Clipboard ConfigView.section.plugins.dht=\u0e01\u0e23\u0e30\u0e08\u0e32\u0e22 DB dht.info=\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e40\u0e2a\u0e23\u0e34\u0e21\u0e19\u0e35\u0e49\u0e23\u0e2d\u0e07\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e01\u0e23\u0e30\u0e08\u0e32\u0e22tracking, \u0e19\u0e2d\u0e01\u0e08\u0e32\u0e01\u0e2d\u0e37\u0e48\u0e19\u0e46, - \u0e01\u0e32\u0e23\u0e1b\u0e34\u0e14\u0e08\u0e30\u0e25\u0e14\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e43\u0e19\u0e01\u0e32\u0e23 download dht.enabled=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e01\u0e32\u0e23\u0e01\u0e23\u0e30\u0e08\u0e32\u0e22\u0e10\u0e32\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 dht.portdefault=\u0e43\u0e0a\u0e49 port \u0e21\u0e32\u0e15\u0e23\u0e32\u0e10\u0e32\u0e19 dht.port=UDP port\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e10\u0e32\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 dht.execute.command=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e04\u0e33\u0e2a\u0e31\u0e48\u0e07 dht.execute.info=\u0e01\u0e14\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e04\u0e33\u0e2a\u0e31\u0e48\u0e07 dht.execute=\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23 dht.logging=\u0e40\u0e1b\u0e34\u0e14\u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e15\u0e34\u0e14\u0e15\u0e32\u0e21\u0e01\u0e32\u0e23\u0e1b\u0e0f\u0e34\u0e1a\u0e31\u0e15\u0e34 ConfigView.section.plugins.dhttracker=\u0e01\u0e23\u0e30\u0e08\u0e32\u0e22 Tracker dhttracker.tracknormalwhenoffline=\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e15\u0e34\u0e14\u0e15\u0e32\u0e21l torrents \u0e17\u0e31\u0e48\u0e27\u0e44\u0e1b\u0e40\u0e21\u0e37\u0e48\u0e2d tracker \u0e44\u0e21\u0e48\u0e41\u0e2a\u0e14\u0e07\u0e15\u0e19 ConfigView.section.file.nativedelete._mac=\u0e43\u0e0a\u0e49 Trash \u0e40\u0e21\u0e37\u0e48\u0e2d\u0e25\u0e1a\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 ConfigView.section.file.nativedelete._windows=\u0e22\u0e49\u0e32\u0e22\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e17\u0e35\u0e48\u0e25\u0e1a\u0e44\u0e1b\u0e17\u0e35\u0e48 Recycle Bin ConfigView.section.logging.generatediagnostics=\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25 ConfigView.section.logging.generatediagnostics.info=\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e01\u0e32\u0e23\u0e15\u0e23\u0e27\u0e08\u0e08\u0e2a\u0e2d\u0e1a \u0e41\u0e25\u0e30\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e25\u0e07 clipboard \u0e41\u0e25\u0e30\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 \u0e16\u0e49\u0e32\u0e15\u0e31\u0e49\u0e07\u0e44\u0e27\u0e49 ConfigView.section.sharing.privatetorrent=Private torrent - \u0e23\u0e31\u0e1a\u0e40\u0e09\u0e1e\u0e32\u0e30 peers \u0e08\u0e32\u0e01 tracker MainWindow.menu.tools.nattest=&\u0e17\u0e14\u0e2a\u0e2d\u0e1a NAT / Firewall Button.apply=\u0e15\u0e01\u0e25\u0e07\u0e43\u0e0a\u0e49 Button.close=\u0e1b\u0e34\u0e14 window.welcome.title=\u0e22\u0e34\u0e19\u0e14\u0e35\u0e15\u0e49\u0e2d\u0e19\u0e23\u0e31\u0e1a\u0e2a\u0e39\u0e48 Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e2b\u0e15\u0e38\u0e23\u0e38\u0e48\u0e19 dht.reseed.label=\u0e42\u0e14\u0e22\u0e1b\u0e01\u0e15\u0e34 reseeding \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e01\u0e23\u0e30\u0e08\u0e32\u0e22\u0e10\u0e32\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e19\u0e31\u0e49\u0e19\u0e44\u0e21\u0e48\u0e08\u0e33\u0e40\u0e1b\u0e47\u0e19\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e44\u0e23\u0e01\u0e47\u0e15\u0e32\u0e21\u0e16\u0e49\u0e32\u0e08\u0e33\u0e19\u0e27\u0e19\u0e17\u0e35\u0e48\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e15\u0e33\u0e19\u0e35\u0e48\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e43\u0e0a\u0e49\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e44\u0e14\u0e49.\n\u0e1b\u0e25\u0e48\u0e2d\u0e22\u0e0a\u0e48\u0e2d\u0e07\u0e19\u0e35\u0e49\u0e27\u0e48\u0e32\u0e07\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e43\u0e2b\u0e21\u0e48\u0e01\u0e31\u0e1a peers \u0e2b\u0e23\u0e37\u0e2d\u0e43\u0e2a\u0e48 IP \u0e41\u0e25\u0e30 port \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e43\u0e2b\u0e21\u0e48\u0e01\u0e31\u0e1a peer \u0e17\u0e35\u0e48\u0e23\u0e39\u0e49\u0e08\u0e31\u0e01\u0e41\u0e25\u0e49\u0e27. dht.reseed.ip=\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02 IP dht.reseed.info=Reseed \u0e10\u0e32\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 dht.diagnostics.group=\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a DHTView.title.full=\u0e01\u0e23\u0e30\u0e08\u0e32\u0e22\u0e10\u0e32\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 DHTView.title.fullcvs=\u0e01\u0e23\u0e30\u0e08\u0e32\u0e22\u0e10\u0e32\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 CVS DHTView.general.title=\u0e17\u0e31\u0e48\u0e27\u0e44\u0e1b DHTView.general.uptime=\u0e40\u0e27\u0e25\u0e32Up: DHTView.general.users=\u0e1c\u0e39\u0e49\u0e43\u0e0a\u0e49: DHTView.general.contacts=\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d: DHTView.general.replacements=\u0e41\u0e17\u0e19: DHTView.general.unknown=\u0e44\u0e21\u0e48\u0e17\u0e23\u0e32\u0e1a: DHTView.transport.title=\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14\u0e01\u0e32\u0e23\u0e02\u0e19\u0e2a\u0e48\u0e07 DHTView.transport.packets=\u0e0a\u0e34\u0e49\u0e19 DHTView.transport.received=\u0e23\u0e31\u0e1a DHTView.transport.sent=\u0e2a\u0e48\u0e07 DHTView.transport.in=\u0e40\u0e02\u0e49\u0e32 : DHTView.transport.out=\u0e2d\u0e2d\u0e01 : DHTView.operations.title=\u0e23\u0e32\u0e22\u0e23\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14\u0e01\u0e32\u0e23\u0e1b\u0e0f\u0e34\u0e1a\u0e31\u0e15\u0e34\u0e01\u0e32\u0e23 DHTView.operations.sent=\u0e2a\u0e48\u0e07 DHTView.operations.failed=\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 DHTView.operations.received=\u0e23\u0e31\u0e1a DHTView.operations.findNode=\u0e2b\u0e32 Node DHTView.operations.findValue=\u0e2b\u0e32\u0e04\u0e48\u0e32 DHTView.operations.store=\u0e40\u0e01\u0e47\u0e1a DHTView.activity.title=\u0e01\u0e32\u0e23\u0e1b\u0e0f\u0e34\u0e1a\u0e31\u0e15\u0e34 DHTView.activity.status=\u0e2a\u0e16\u0e32\u0e19\u0e30 DHTView.activity.status.true=\u0e2d\u0e31\u0e19\u0e14\u0e31\u0e1a\u0e15\u0e48\u0e2d DHTView.activity.status.false=\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23 DHTView.activity.type=\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a DHTView.activity.type.1=\u0e20\u0e32\u0e22\u0e43\u0e19 Get DHTView.activity.type.2=\u0e20\u0e32\u0e22\u0e19\u0e2d\u0e01 Get DHTView.activity.type.3=\u0e20\u0e32\u0e22\u0e43\u0e19 Put DHTView.activity.type.4=\u0e20\u0e32\u0e22\u0e19\u0e2d\u0e01 Put DHTView.activity.target=\u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 DHTView.activity.details=\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14 DHTView.db.title=\u0e10\u0e32\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 DHTView.db.values=\u0e04\u0e48\u0e32 DHTView.db.direct=\u0e17\u0e32\u0e07\u0e15\u0e23\u0e07 DHTView.db.indirect=\u0e17\u0e32\u0e07\u0e2d\u0e49\u0e2d\u0e21 DHTView.db.divfreq=\u0e04\u0e27\u0e32\u0e21\u0e16\u0e35\u0e48 Div. DHTView.db.divsize=\u0e02\u0e19\u0e32\u0e14 Div. MainWindow.dht.status.tooltip=\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e01\u0e32\u0e23\u0e01\u0e23\u0e30\u0e08\u0e32\u0e22\u0e10\u0e32\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e14\u0e33\u0e40\u0e19\u0e34\u0e19\u0e01\u0e32\u0e23\u0e19\u0e35\u0e48\u0e08\u0e30\u0e41\u0e2a\u0e14\u0e07\u0e08\u0e33\u0e19\u0e27\u0e19\u0e1b\u0e23\u0e30\u0e21\u0e32\u0e13\u0e02\u0e2d\u0e07\u0e1c\u0e39\u0e49\u0e43\u0e0a\u0e49\u0e17\u0e35\u0e48\u0e15\u0e2d\u0e19\u0e19\u0e35\u0e49 online MainWindow.dht.status.disabled=\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e43\u0e0a\u0e49 MainWindow.dht.status.failed=\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27 MainWindow.dht.status.initializing=\u0e40\u0e23\u0e34\u0e48\u0e21 MainWindow.dht.status.users=%1 \u0e1c\u0e39\u0e49\u0e43\u0e0a\u0e49 MyTorrentsView.menu.setUpSpeed=\u0e15\u0e31\u0e49\u0e07\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27 MyTorrentsView.menu.setDownSpeed=\u0e15\u0e31\u0e49\u0e07\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27 Down ConfigView.section.tracker.client.showwarnings=\u0e41\u0e2a\u0e14\u0e07\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e40\u0e15\u0e37\u0e2d\u0e19\u0e17\u0e35\u0e48\u0e41\u0e08\u0e49\u0e07\u0e42\u0e14\u0e22 trackers dht.advanced=\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e32\u0e23\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32\u0e02\u0e31\u0e49\u0e19\u0e2a\u0e39\u0e07 dht.advanced.group=\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32\u0e02\u0e31\u0e49\u0e19\u0e2a\u0e39\u0e07 dht.advanced.label=\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e04\u0e48\u0e32\u0e19\u0e35\u0e49\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e04\u0e38\u0e13\u0e23\u0e39\u0e49\u0e27\u0e48\u0e32\u0e17\u0e33\u0e2d\u0e30\u0e44\u0e23\u0e2d\u0e22\u0e39\u0e48\u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19 dht.override.ip=\u0e40\u0e02\u0e35\u0e22\u0e19\u0e17\u0e31\u0e1a\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02l IP \u0e20\u0e32\u0e22\u0e19\u0e2d\u0e01 ConfigView.section.logging.loggerenable=\u0e40\u0e1b\u0e34\u0e14\u0e43\u0e0a\u0e49\u0e01\u0e32\u0e23\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e2a\u0e16\u0e32\u0e19\u0e30 ConfigView.section.ipfilter.blockbanning=Ban \u0e0a\u0e48\u0e27\u0e07\u0e02\u0e2d\u0e07\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02 256 \u0e15\u0e33\u0e41\u0e2b\u0e19\u0e48\u0e07 \u0e40\u0e21\u0e37\u0e48\u0e2d\u0e21\u0e35\u0e08\u0e33\u0e19\u0e27\u0e19\u0e40\u0e01\u0e34\u0e19 TableColumn.header.swarm_average_speed=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e40\u0e09\u0e25\u0e35\u0e48\u0e22 Swarm TableColumn.header.swarm_average_speed.info=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27\u0e40\u0e09\u0e25\u0e35\u0e48\u0e22\u0e02\u0e2d\u0e07 peers \u0e43\u0e19 swarm MyTrackerView.category=\u0e1b\u0e23\u0e30\u0e40\u0e20\u0e17 MainWindow.menu.file.open.torrentfortracking=Torrent File... (\u0e40\u0e09\u0e1e\u0e32\u0e30 Tracking) diagnostics.log_found=Vuze \u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e1b\u0e34\u0e14\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07. \u0e42\u0e1b\u0e23\u0e14\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a %1 \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e14\u0e39\u0e23\u0e32\u0e22\u0e07\u0e32\u0e19\u0e17\u0e35\u0e48\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01 \u0e41\u0e25\u0e30\u0e2d\u0e32\u0e08\u0e2a\u0e48\u0e07\u0e21\u0e32\u0e43\u0e2b\u0e49\u0e17\u0e35\u0e21\u0e07\u0e32\u0e19 Vuze \u0e16\u0e49\u0e32\u0e40\u0e01\u0e34\u0e14\u0e08\u0e32\u0e01\u0e42\u0e1b\u0e23\u0e41\u0e01\u0e23\u0e21\u0e17\u0e33\u0e07\u0e32\u0e19\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 ConfigView.section.logging.log0type=\u0e02\u0e48\u0e32\u0e27\u0e2a\u0e32\u0e23 OpenTorrentWindow.torrentLocation=\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 Torrent: Button.moveUp=\u0e22\u0e49\u0e32\u0e22\u0e02\u0e36\u0e49\u0e19 Button.moveDown=\u0e22\u0e49\u0e32\u0e22\u0e44\u0e1b\u0e25\u0e07 # > 2402 # Used for peers which we can't determine. PeerSocket.unknown=\u0e44\u0e21\u0e48\u0e23\u0e39\u0e49 ConfigView.label.announceport=\u0e40\u0e02\u0e35\u0e22\u0e19\u0e17\u0e31\u0e1a tracker \u0e43\u0e19 port \u0e17\u0e35\u0e48\u0e41\u0e08\u0e49\u0e07 iconBar.queue.tooltip=\u0e25\u0e33\u0e14\u0e31\u0e1a MainWindow.menu.help.faq=&Wiki \u0e04\u0e33\u0e16\u0e32\u0e21\u0e17\u0e35\u0e48\u0e16\u0e39\u0e01\u0e16\u0e32\u0e21\u0e1a\u0e48\u0e2d\u0e22 #what you've watched? Discover more with a single click... MainWindow.menu.help.donate=&\u0e1a\u0e23\u0e34\u0e08\u0e32\u0e04 !!! azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_ko_KR.properties0000644000175000017500000065746611301156004026124 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c... Main.parameter.usage=\uc0ac\uc6a9\ubc95: java org.gudy.azureus2.cl.Main [parameters] "file.torrent" "save path" Main.parameter.maxUploads=\ub3d9\uc2dc \uc62c\ub9ac\uae30\ud560 \ucd5c\ub300 \uc218 Main.parameter.maxSpeed=\ucd5c\uace0 \uc62c\ub9ac\uae30 \uc18d\ub3c4 (\ubc14\uc774\ud2b8/\ucd08) MainWindow.menu.file=\ud30c\uc77c(&F) MainWindow.menu.file.open=\uc5f4\uae30(&O) MainWindow.menu.file.create=\ud1a0\ub7f0\ud2b8 \ub9cc\ub4e4\uae30...(&C) MainWindow.menu.file.create.fromfile=\ud30c\uc77c\uc5d0\uc11c(&F) MainWindow.menu.file.create.fromdir=\ud3f4\ub354\uc5d0\uc11c(&D) MainWindow.menu.file.export=XML \ud1a0\ub7f0\ud2b8\ub97c \ub0b4\ubcf4\ub0b4\uae30...(&E) MainWindow.menu.file.import=XML \ud1a0\ub7f0\ud2b8\ub97c \ub4e4\uc5ec\uc624\uae30...(&I) MainWindow.menu.file.closetab=\ud0ed \ub2eb\uae30(&T) MainWindow.menu.file.closewindow=\ucc3d \ub2eb\uae30(&W) MainWindow.menu.file.exit=\ub05d\ub0b4\uae30(&X) MainWindow.dialog.choose.file=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c \uace0\ub974\uae30 MainWindow.menu.file.folder=\ud3f4\ub354...(&F) MainWindow.dialog.choose.folder=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc774 \uc788\ub294 \ud3f4\ub354 \uace0\ub974\uae30 MainWindow.menu.view=\ubcf4\uae30(&V) MainWindow.menu.view.show=\ubcf4\uc774\uae30 MainWindow.menu.view.mytorrents=\ub0b4 \ud1a0\ub7f0\ud2b8(&M) MainWindow.menu.view.mytorrents.keybinding=\uba54\ud0c0+1 MainWindow.menu.view.open_global_transfer_bar=\uad50\ud658 \ud45c\uc2dc\uc904 MainWindow.menu.view.configuration=\uc120\ud0dd\uc0ac\ud56d...(&O) MainWindow.menu.view.configuration.keybinding=\uba54\ud0c0+, MainWindow.menu.view.console=\ucf58\uc194(&O) MainWindow.menu.view.console.keybinding=\uba54\ud0c0+4 MainWindow.menu.view.irc=IRC(&I) MainWindow.menu.view.allpeers=\ubaa8\ub4e0 \ub3d9\ub8cc MainWindow.menu.view.detailedlist=&\uc138\ubd80 \ubaa9\ub85d MainWindow.menu.closealldetails=\ubaa8\ub4e0 \uc0c1\uc138 \uc815\ubcf4 \ub2eb\uae30(&A) MainWindow.menu.closealldownloadbars=\ubaa8\ub4e0 \ub0b4\ub824\ubc1b\uae30 \ub9c9\ub300 \ub2eb\uae30(&B) MainWindow.menu.language=\ub9d0(&L) ConfigView.section.language=\uc5b8\uc5b4 MainWindow.menu.window=\ucc3d(&W) MainWindow.menu.window.minimize=\ucd5c\uc18c\ud654(&M) MainWindow.menu.window.minimize.keybinding=\uba54\ud0c0+M MainWindow.menu.window.zoom=\ud655\ub300(&Z) MainWindow.menu.window.alltofront=\ubaa8\ub450 \uc55e\uc73c\ub85c \uac00\uc838\uc624\uae30(&F) MainWindow.menu.help=\ub3c4\uc6c0\ub9d0(&H) MainWindow.menu.help.about=Vuze \uc815\ubcf4 MainWindow.menu.torrent=\ud1a0\ub7f0\ud2b8 (T&) MainWindow.about.title=\uc815\ubcf4 MainWindow.about.section.developers=\uac1c\ubc1c\uc790 MainWindow.about.section.translators=\uc5ed\uc790 MainWindow.about.section.system=\uc2dc\uc2a4\ud15c MainWindow.about.section.internet=\uc778\ud130\ub137 MainWindow.about.internet.homepage=Vuze \ud648\ud398\uc774\uc9c0 MainWindow.about.internet.sourceforge=Sourceforge \ud504\ub85c\uc81d\ud2b8 \ud398\uc774\uc9c0 MainWindow.about.internet.sourceforgedownloads=Sourceforge \ub0b4\ub824\ubc1b\uae30 MainWindow.about.internet.bugreports=\ubc84\uadf8 \ub9ac\ud3ec\ud2b8 MainWindow.about.internet.forumdiscussion=\ud3ec\ub7fc MainWindow.about.internet.wiki=Vuze \uc704\ud0a4\uc704\ud0a4 \uc790\uc8fc \ubb3b\ub294 \ubb3c\uc74c MainWindow.dialog.choose.savepath=\uc800\uc7a5 \uc704\uce58 \uace0\ub974\uae30 MainWindow.dialog.choose.savepath_forallfiles=\ubaa8\ub4e0 \ud30c\uc77c\uc758 \uc800\uc7a5 \uc704\uce58 \uace0\ub974\uae30 MainWindow.status.latestversion=\ucd5c\uc2e0 \ubc84\uc804 MainWindow.status.latestversion.clickupdate=\uc5c5\ub370\uc774\ud2b8\ud558\ub824\uba74 \ud074\ub9ad MainWindow.status.unknown=\uc54c\uc218\uc5c6\uc74c MainWindow.status.checking=\uac80\uc0ac\ud558\uace0 \uc788\uc74c MyTorrentsView.mytorrents=\ub0b4 \ud1a0\ub7f0\ud2b8 TableColumn.header.name=\uc774\ub984 TableColumn.header.size=\ud06c\uae30 TableColumn.header.done=\ub9c8\uce68 TableColumn.header.done.info=\uc9c0\uae08\uc758 \uc791\uc5c5\uc5d0\uc11c \ub9c8\uce5c \ubc31\ubd84\uc728 TableColumn.header.status=\uc0c1\ud0dc TableColumn.header.status.info=\ud1a0\ub7f0\ud2b8\uac00 \ud558\uace0 \uc788\ub294 \uac83 TableColumn.header.seeds=\uc528\uc557 TableColumn.header.seeds.info=\uc528\uc557 \uc218 \uc5f0\uacb0\ub428 (\ucd1d \uc528\uc557 \uc218) TableColumn.header.peers=\ub3d9\ub8cc TableColumn.header.peers.info=\uc5f0\uacb0\ub41c \ub3d9\ub8cc\uc218 (\ucd1d \ub3d9\ub8cc \uc218) TableColumn.header.downspeed=\ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4 TableColumn.header.upspeed=\uc62c\ub9ac\uae30 \uc18d\ub3c4 TableColumn.header.eta=\ub9c8\uce68 \uc608\uc815 \uc2dc\uac01 TableColumn.header.tracker=\ub354\ub4ec\uc774 \uc0c1\ud0dc TableColumn.header.tracker.info=\ub354\ub4ec\uc774\uc758 \uc0c1\ud0dc TableColumn.header.trackernextaccess=\ub2e4\uc74c \ub354\ub4ec\uc774 \uc811\uadfc TableColumn.header.trackernextaccess.info=\ub2e4\uc74c \ub354\ub4ec\uc774 \uc811\uadfc\uc774 \uc77c\uc5b4\ub0a0 \ub54c TableColumn.header.priority=\uc6b0\uc120\uad8c TableColumn.header.priority.info=\uc62c\ub9ac\uae30 \ub300\uc5ed\ud3ed\uc774 \uc5bc\ub9c8\ub9cc\ud07c \ud1a0\ub7f0\ud2b8\uc5d0 \uc8fc\uc5b4\uc9c0\ub294\uc9c0 \uc815\ud569\ub2c8\ub2e4. MyTorrentsView.menu.showdetails=\uc0c1\uc138 \uc815\ubcf4 \ubcf4\uc774\uae30(&D) MyTorrentsView.menu.showdownloadbar=\ub0b4\ub824\ubc1b\uae30 \ub9c9\ub300 \ubcf4\uc774\uae30(&B) MyTorrentsView.menu.open=\ud30c\uc77c \uc5f4\uae30(&O) MyTorrentsView.menu.setpriority=\uc6b0\uc120\uad8c \uc9c0\uc815(&P) MyTorrentsView.menu.setpriority.high=\ub192\uc74c(&H) MyTorrentsView.menu.setpriority.low=\ub0ae\uc74c(&L) MyTorrentsView.menu.start=\uc2dc\uc791(&S) MyTorrentsView.menu.stop=\uba48\ucda4(&P) MyTorrentsView.menu.remove=\uc9c0\uc6b0\uae30(&R) MyTorrentsView.menu.changeTracker=\ub354\ub4ec\uc774 \uc8fc\uc18c \ub354\ud558\uae30(&A) TrayWindow.menu.exit=\ub05d\ub0b4\uae30(&X) TrayWindow.menu.show=Vuze \ubcf4\uc774\uae30(&S) SystemTray.menu.exit=\ub05d\ub0b4\uae30(&X) SystemTray.menu.closealldownloadbars=\ubaa8\ub4e0 \ub0b4\ub824\ubc1b\uae30 \ub9c9\ub300 \ub2eb\uae30(&A) SystemTray.menu.show=Vuze \ubcf4\uc774\uae30(&S) PeersView.ip.info=\ub3d9\ub8cc\uc758 IP PeersView.port=\ud3ec\ud2b8 PeersView.port.info=\uc4f0\uc774\ub294 \ud3ec\ud2b8 PeersView.T=\uac78\uae30 PeersView.T.info=L(\uc5ec\uae30): \ub2f9\uc2e0\uc774 \uc5f0\uacb0\ud558\uc600\uc2b5\ub2c8\ub2e4. R(\uc800\uae30): \ub3d9\ub8cc\uac00 \uc5f0\uacb0\ud558\uc600\uc2b5\ub2c8\ub2e4. PeersView.I1=\ub04c (\ub3d9\ub8cc\uc5d0\uac8c \ub04c\ub9bc) PeersView.I1.info=\ub2f9\uc2e0\uc740 \ub2e4\ub978 \ub3d9\ub8cc\uc5d0\uac8c \uc788\ub294 \uac83\uc5d0 \ub04c\ub9bd\ub2c8\uae4c? PeersView.C1=\ub9c9 (\ub3d9\ub8cc\uc5d0\uac8c \ub9c9\ud798) PeersView.C1.info=\ub3d9\ub8cc\uac00 \ub098\uc758 \ub0b4\ub824\ubc1b\uae30\ub97c \ub9c9\uc558\ub294\uc9c0 \ubcf4\uc5ec\uc90c PeersView.pieces=\uc870\uac01 PeersView.downloadspeed=\ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4 PeersView.download=\ub0b4\ub824\ubc1b\uae30 PeersView.I2=\ub04c (\ub3d9\ub8cc\ub97c \ub04e) PeersView.I2.info=\ub3d9\ub8cc\ub294 \ub2f9\uc2e0\uc5d0\uac8c \uc788\ub294 \uac83\uc5d0 \ub04c\ub9bd\ub2c8\uae4c? PeersView.C2=\ub9c9 (\ub3d9\ub8cc\ub97c \ub9c9\uc74c) PeersView.C2.info=\ub0b4\uac00 \ub3d9\ub8cc\uc758 \ub0b4\ub824\ubc1b\uae30\ub97c \ub9c9\uc558\ub294\uc9c0 \ubcf4\uc5ec\uc90c PeersView.uploadspeed=\uc62c\ub9ac\uae30 \uc18d\ub3c4 PeersView.uploadspeed.info=\ub2f9\uc2e0\uc774 \ub3d9\ub8cc\uc5d0\uac8c \uc62c\ub9b0 \uc18d\ub3c4 PeersView.upload=\uc62c\ub9ac\uae30 PeersView.upload.info=\ub2f9\uc2e0\uc774 \ub3d9\ub8cc\uc5d0\uac8c \uc62c\ub9ac\uae30 \ubaa8\ub450 PeersView.statup=\uc62c\ub9ac\uae30 \ud1b5\uacc4\ub7c9 PeersView.statup.info=\ub3d9\ub8cc\uc758 \uc62c\ub9ac\uae30 \uc18d\ub3c4\ub97c \uc5b4\ub9bc\uc7a1\uc740 \uac12 PeersView.S=\uba48\uce6b PeersView.S.info=\uba48\ucdb0\uc9d0: \ub3d9\ub8cc\uac00 \uc190\uc218 \ub610\ub294 (\uadf8\ub2e4\uc9c0 \ub109\ub109\ud55c \uc18d\ub3c4\ub85c \ub370\uc774\ud130\ub97c \ub118\uae30\uc9c0 \ubabb\ud558\uc5ec\uc11c) \uc800\uc808\ub85c \uba48\ucdb0\uc9c8 \uc218 \uc788\uc2b5\ub2c8\ub2e4. PeersView.downloadspeedoverall=\ubaa8\ub4e0 \ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4 PeersView.optunchoke=\uace8\ub77c\uc11c \ub9c9\uc9c0 \uc54a\uc74c PeersView.client=\uc811\uc18d \ud504\ub85c\uadf8\ub7a8 PeersView.client.info=\ub3d9\ub8cc\uac00 \uc4f0\uace0 \uc788\ub294 BitTorrent \uc811\uc18d \ud504\ub85c\uadf8\ub7a8 PeersView.menu.snubbed=\uba48\ucdb0\uc9d0(&S) PeersView.title.short=\ub3d9\ub8cc PeersView.title.full=\ub3d9\ub8cc AllPeersView.title.full=\ubaa8\ub4e0 \ub3d9\ub8cc ConfigView.section.files=\ud30c\uc77c ConfigView.label.usefastresume=\ube60\ub978 \ub2e4\uc2dc \uc2dc\uc791 \ubc29\uc2dd \uc4f0\uae30 ConfigView.label.incrementalfile=\ub298\uc5b4\ub098\ub294 \ud30c\uc77c \ub9cc\ub4e4\uae30 \uc791\ub3d9 [Linux\uc5d0\uc11c FAT32\uc5d0 \ud544\uc694\ud568] ConfigView.label.defaultsavepath=\uae30\ubcf8 \ub370\uc774\ud130 \ud3f4\ub354\ub85c \uc800\uc7a5 ConfigView.button.browse=\ucc3e\uc544\ubcf4\uae30... ConfigView.dialog.choosedefaultsavepath=\uae30\ubcf8 \uc800\uc7a5 \ud3f4\ub354\ub97c \uace0\ub974\uc2ed\uc2dc\uc694. ConfigView.section.server=\uc5f0\uacb0 ConfigView.section.global=\uc77c\ubc18 ConfigView.label.disconnetseed=\ubfcc\ub9ac\ub294 \uc911 \uc528\uc557\uacfc \ub04a\uae30 ConfigView.label.switchpriority=\ubfcc\ub9b4 \ub54c \ub0ae\uc740 \uc6b0\uc120\uad8c\uc73c\ub85c \uc800\uc808\ub85c \ubc14\uafc8 ConfigView.label.maxdownloads=\ucd5c\ub300 \ub3d9\uc2dc \ub0b4\ub824\ubc1b\uae30 [0: \ubb34\uc81c\ud55c] ConfigView.label.maxdownloads.tooltip=\uc5ec\uae30\uc5d0 \uc815\ud55c \uc218\ub9cc\ud07c \ub0b4\ub824\ubc1b\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n\uc608\uc678\ub85c\ub294 \uc644\ub8cc\ub41c \ud1a0\ub7f0\ud2b8\uac00 \uccab\ubc88\uc9f8 \uc6b0\uc120\uad8c\uc5d0 \uc801\ud569\ud558\ub2e4\uba74 \ud65c\uc131\ud654\ub41c \ub0b4\ub824\ubc1b\uae30 \uc790\ub9ac\ub97c \ucc28\uc9c0\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. ConfigView.label.maxactivetorrents=\ucd5c\ub300 \ud65c\uc131 \ud1a0\ub7f0\ud2b8 [0: \ubb34\uc81c\ud55c]\n - \uc0c8\ub85c \ub0b4\ub824\ubc1b\uac70\ub098 \ubfcc\ub9b4 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. ConfigView.label.priorityExtensions=\ub2e4\uc74c \ud655\uc7a5\uc790\uc778 \ud30c\uc77c\uc744 \uc800\uc808\ub85c \uc6b0\uc120\uc2dc\ud0b4\n - \uc608: .txt;.nfo;.jpg ConfigView.section.transfer=\uc804\uc1a1 ConfigView.label.maxuploads=\ud1a0\ub7f0\ud2b8\ub9c8\ub2e4\uc758 \ucd5c\ub300 \uae30\ubcf8 \uc62c\ub9ac\uae30 \uc790\ub9ac ConfigView.label.maxuploadspeed=KB/s \ucd5c\uace0 \ucd1d \uc62c\ub9ac\uae30 \uc18d\ub3c4 [0: \ubb34\uc81c\ud55c] ConfigView.label.saveresumeinterval=\ub2e4\uc74c\ub9c8\ub2e4 \ub2e4\uc2dc \uc2dc\uc791 \ub370\uc774\ud130 \uc5c5\ub370\uc774\ud2b8 ConfigView.unlimited=\ubb34\uc81c\ud55c ConfigView.section.display=\ub514\uc2a4\ud50c\ub808\uc774 ConfigView.label.opendetails=\uc0c1\uc138 \uc815\ubcf4 \ud0ed \uc800\uc808\ub85c \uc5f4\ub9ac\uae30 ConfigView.label.openbar=\ub0b4\ub824\ubc1b\uae30 \ub9c9\ub300 \uc800\uc808\ub85c \uc5f4\ub9ac\uae30 ConfigView.label.closetotray=\uc54c\ub9bc \uc601\uc5ed\uc73c\ub85c \ucd5c\uc18c\ud654 ConfigView.label.minimizetotray=\ucd5c\uc18c\ud654\ub97c \uc54c\ub9bc \uc601\uc5ed\uc73c\ub85c \ud569\ub2c8\ub2e4. ConfigView.section.general=\uc77c\ubc18 ConfigView.section.start=\uc2dc\uc791 ConfigView.label.showsplash=\ud654\ub824\ud55c \ud654\uba74\uc744 \ubcf4\uc5ec\uc90c ConfigView.label.autoupdate=\uc0c8 \ubc84\uc804\uc774 \uc788\uc744 \ub54c \uc5c5\uadf8\ub808\uc774\ub4dc \ub300\ud654 \ucc3d \uc5f4\uae30 ConfigView.label.openconsole=\uc2dc\uc791\ud560 \ub54c \ucf58\uc194 \uc5f4\uae30 ConfigView.label.openconfig=\uc2dc\uc791\ud560 \ub54c \uc120\ud0dd\uc0ac\ud56d \uc5f4\uae30 ConfigView.label.startminimized=\ucd5c\uc18c\ud654\ub85c \uc2dc\uc791 ConfigView.label.ircwiki=\ub2e4\uc74c\uc744 \uc77d\uc5b4\uc8fc\uc138\uc694 http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=\uc11c\ubc84 ConfigView.label.ircchannel=\ucc44\ub110 ConfigView.label.irclogin=\ub300\ud654\uba85 ConfigView.group.irctitle=IRC \uc124\uc815 ConfigView.boolean.ircsendinfo=\uc775\uba85\uc73c\ub85c \ucc44\ub110 \uad00\ub9ac\uc790\uac00 \ub2f9\uc2e0\uc744 \ub3c4\uc6b8 \uc218 \uc788\ub3c4\ub85d \n\uc124\uc815\uc815\ubcf4\ub97c \ubcf4\ub0c5\ub2c8\ub2e4 ConfigView.boolean.irclog=\ucc44\ub110\uc5d0\uc11c \ud65c\ub3d9\uc744 \uae30\ub85d\ud558\ub3c4\ub85d \uc791\ub3d9\ud569\ub2c8\ub2e4. (IRC_log.htm\uc5d0 \uae30\ub85d) ConfigView.section.security=\ubcf4\uc548 ConfigView.label.password=\uc554\ud638\ub97c \uc368\uc11c Vuze ub97c \uc9c0\ud0b4\n - \uc2dc\uc791\ud560 \ub54c\uc640 \uc774\uc804 \ud06c\uae30\ub85c \ub420 \ub54c \ubb3c\uc5b4\ubcfc \uac83\uc785\ub2c8\ub2e4. ConfigView.label.passwordconfirm=\uc554\ud638 (\ud655\uc778) ConfigView.label.passwordmatch=\ud65c\uc131\ud654\ub41c \uc554\ud638: ConfigView.label.passwordmatchnone=\uc544\ub2c8\uc624 ConfigView.label.passwordmatchno=\uc544\ub2c8\uc624 / \uc554\ud638\uac00 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4 ConfigView.label.passwordmatchyes=\uc608 ConfigView.button.save=\uc800\uc7a5 ConfigView.title.short=\uc120\ud0dd\uc0ac\ud56d ConfigView.title.full=\uc120\ud0dd\uc0ac\ud56d ConfigView.title.full._mac=\uc120\ud0dd\uc0ac\ud56d ConsoleView.title.short=\ucf58\uc194 ConsoleView.title.full=\ucf58\uc194 FileItem.write=\uc4f0\uae30 FileItem.read=\uc77d\uae30 FileItem.normal=\ubcf4\ud1b5 FileItem.high=\ub192\uc74c FileItem.donotdownload=\ub0b4\ub824\ubc1b\uae30\ud558\uc9c0 \uc54a\uc74c FileItem.delete=\uc0ad\uc81c FilesView.name=\uc774\ub984 FilesView.name.fastRename=\ube60\ub978 \uc774\ub984\ubc14\uafb8\uae30 FilesView.size=\ud06c\uae30 FilesView.done=\ub9c8\uce68 FilesView.firstpiece=\uccab \uc870\uac01 \ubc88\ud638 FilesView.numberofpieces=\uc870\uac01 \uc218 FilesView.pieces=\uc870\uac01 FilesView.mode=\ubc29\uc2dd FilesView.priority=\uc6b0\uc120\uad8c FilesView.menu.open=\uc5f4\uae30(&O) FilesView.menu.setpriority=\uc6b0\uc120\uad8c \uc9c0\uc815(&P) FilesView.menu.setpriority.high=\ub192\uc74c(&H) FilesView.menu.setpriority.normal=\ubcf4\ud1b5(&N) FilesView.menu.setpriority.skipped=\ub0b4\ub824\ubc1b\uae30\ud558\uc9c0 \uc54a\uc74c(&D) FilesView.title.short=\ud30c\uc77c FilesView.title.full=\ud30c\uc77c GeneralView.section.downloaded=\ub0b4\ub824\ubc1b\uae30\ub428 GeneralView.label.status.file=\ud30c\uc77c \uc0c1\ud0dc GeneralView.label.status.pieces=\uc870\uac01 \uc0c1\ud0dc GeneralView.section.availability=\uc4f8 \uc218 \uc788\uc74c GeneralView.label.status.pieces_available=\uc870\uac01 \uc0c1\ud0dc GeneralView.section.transfer=\uc804\uc1a1 GeneralView.section.info=\uc815\ubcf4 GeneralView.title.short=\uc77c\ubc18 GeneralView.title.full=\uc77c\ubc18 GeneralView.label.timeelapsed=\uc9c0\ub09c \uc2dc\uac04: GeneralView.label.remaining=\ub0a8\uc74c: GeneralView.label.downloaded=\ub0b4\ub824\ubc1b\uae30: GeneralView.label.downloadspeed=\ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4: GeneralView.label.maxuploads=\uc62c\ub9ac\uae30 \uc790\ub9ac: GeneralView.label.maxuploads.tooltip=\uc8fc\uc5b4\uc9c4 \uc2dc\uac04\uc5d0 \ub9c9\uc9c0 \uc54a\uc744 \ucd5c\ub300 \ub3d9\ub8cc \uc218 GeneralView.label.uploaded=\uc62c\ub9ac\uae30: GeneralView.label.uploadspeed=\uc62c\ub9ac\uae30 \uc18d\ub3c4: GeneralView.label.seeds=\uc528\uc557: GeneralView.label.peers=\ub3d9\ub8cc: GeneralView.label.completed=\uc644\ub8cc : GeneralView.label.totalspeed=\ub5bc \uc18d\ub3c4: GeneralView.label.totalspeed.tooltip=\ub2f9\uc2e0\uacfc \uc5f0\uacb0\ub41c \ubaa8\ub4e0 \uc811\uc18d \ucef4\ud4e8\ud130\uc758 \ucd1d (\uadf8\ub9ac\uace0 \ud3c9\uade0) \uc18d\ub3c4 GeneralView.label.averagespeed=\ud3c9\uade0 GeneralView.label.filename=\uc774\ub984: GeneralView.label.totalsize=\ucd1d \ud06c\uae30: GeneralView.label.savein=\uc800\uc7a5 \uc704\uce58: GeneralView.label.hash=\ud574\uc2dc: GeneralView.label.numberofpieces=\uc870\uac01 \uc218: GeneralView.label.size=\ud06c\uae30: GeneralView.label.tracker=\ub354\ub4ec\uc774 \uc0c1\ud0dc: GeneralView.label.updatein=\uc5c5\ub370\uc774\ud2b8 \ub0a8\uc740 \uc2dc\uac04: GeneralView.label.trackerurl=\ub354\ub4ec\uc774 \uc8fc\uc18c: GeneralView.label.trackerurlupdate=\ub354\ub4ec\uc774 \uc5c5\ub370\uc774\ud2b8 GeneralView.label.comment=\ud1a0\ub7f0\ud2b8 \ub367\ub9d0: GeneralView.label.user_comment=\uc0ac\uc6a9\uc790 \ub367\ub9d0: GeneralView.label.status=\uc0c1\ud0dc : ManagerItem.waiting=\uae30\ub2e4\ub9ac\uace0 \uc788\uc74c ManagerItem.allocating=\ud560\ub2f9\ud558\uace0 \uc788\uc74c ManagerItem.checking=\uac80\uc0ac\ud558\uace0 \uc788\uc74c ManagerItem.ready=\uc900\ube44 ManagerItem.downloading=\ub0b4\ub824\ubc1b\uae30 \uc911 ManagerItem.seeding=\ubfcc\ub9ac\uace0 \uc788\uc74c ManagerItem.stopped=\uba48\ucda4 ManagerItem.error=\uc624\ub958 ManagerItem.high=\ub192\uc74c ManagerItem.low=\ub0ae\uc74c MinimizedWindow.name=\ud30c\uc77c \uc774\ub984: MinimizedWindow.all_transfers=Vuze \uad50\ud658 PiecesView.#=\ubc88\ud638 PiecesView.size=\ud06c\uae30 PiecesView.numberofblocks=\ud1a0\ub9c9 \uc218 PiecesView.blocks=\ud1a0\ub9c9 PiecesView.completed=\ub9c8\uce68 PiecesView.availability=\uc4f8 \uc218 \uc788\uc74c PiecesView.reservedby=\ub9c8\ub828 PiecesView.writers=\ud1a0\ub9c9 \ubcf4\ub0b4\ub294 \uc0ac\ub78c PiecesView.title.short=\uc870\uac01 PiecesView.title.full=\uc870\uac01 SystemTray.tooltip.seeding=%1 \uac1c \ubfcc\ub9ac\uace0 \uc788\uc74c, SystemTray.tooltip.downloading=%1 \uac1c \ub0b4\ub824\ubc1b\uace0 \uc788\uc74c, DownloadManager.error.filenotfound=\ud30c\uc77c\uc744 \ucc3e\uc9c0 \ubabb\ud568 DownloadManager.error.fileempty=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc774 \ube44\uc5b4\uc788\uc74c DownloadManager.error.filetoobig=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc774 \ub108\ubb34 \ud07c DownloadManager.error.filewithouttorrentinfo=\ud30c\uc77c\uc5d0\uc11c \uc544\ubb34 \ud1a0\ub7f0\ud2b8 \uc815\ubcf4\ub3c4 \ucc3e\uc9c0 \ubabb\ud568 DownloadManager.error.unsupportedencoding=\uc9c0\uc6d0\ud558\uc9c0 \uc54a\ub294 \uc778\ucf54\ub529 DownloadManager.error.ioerror=\uc785\ucd9c\ub825 \uc624\ub958 DownloadManager.error.sha1=\uadf8\ub7f0 \uc5f0\uc0b0 \uc5c6\uc74c(SHA1) \uc624\ub958 PeerManager.status.offline=\uc5f0\uacb0 \uc624\ub958 PeerManager.status.ok=\ud655\uc778 PeerManager.status.checking=\uac80\uc0ac\ud558\uace0 \uc788\uc74c PeerManager.status.finished=\ub9c8\uce68 PeerManager.status.finishedin=\ub9c8\uce68 MainWindow.upgrade.assistant=\uc5c5\uadf8\ub808\uc774\ub4dc \ub3c4\uc6b0\ubbf8 MainWindow.upgrade.newerversion=\ub0b4\ub824\ubc1b\uc744 \uc218 \uc788\ub294 \uc0c8 Vuze \ubc84\uc804\uc774 \uc788\uc2b5\ub2c8\ub2e4. MainWindow.upgrade.explanation=\uc774 \ub3c4\uc6b0\ubbf8\ub294 \ub2f9\uc2e0\uc758 Vuze \ud3f4\ub354\uc5d0 \uc0c8 \ubc84\uc804\uc744 \ub0b4\ub824\ubc1b\uace0 \ub098\uc11c Vuze\ub97c \ub2e4\uc2dc \uc2dc\uc791\ud560 \uac83\uc785\ub2c8\ub2e4. MainWindow.upgrade.explanation.manual=Vuze\uc744 \ub2eb\uace0 \uc0c8 \ubc84\uc804\uc744 \ub0b4\ub824\ubc1b\uace0\uc11c Vuze\ub97c \ub2e4\uc2dc \uc2dc\uc791\ud558\uc5ec \uc190\uc218 \uc5c5\ub370\uc774\ud2b8\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. MainWindow.upgrade.step1=1 \ub2e8\uacc4: \uc0c8 \ubc84\uc804\uc744 \ub0b4\ub824\ubc1b\uc73c\uc138\uc694. MainWindow.upgrade.step2=2 \ub2e8\uacc4: \uc774 \ubc84\uc804\uc744 \ub2eb\uace0 \uc0c8 \ubc84\uc804\uc758 Vuze\ub97c \ub2e4\uc2dc \uc2dc\uc791 \ud558\uc2ed\uc2dc\uc694. MainWindow.upgrade.hint1=\uadc0\ub754:\t\ub9c8\uce68\uc744 \ub20c\ub7ec \ubaa8\ub4e0 \uac83\uc774 \uc800\uc808\ub85c \ub418\uac8c \ud568 MainWindow.upgrade.hint2=\uadc0\ub754:\tVuze\ub97c \ub098\uc911\uc5d0 \ub2eb\uc73c\ub824\uba74, \ucde8\uc18c\ub97c \ub204\ub974\uace0 \ub098\uc11c\n\t\ub2eb\ud78c \ub2e4\uc74c\uc5d0 Azureus2-new.jar\uc5d0\uc11c Azureus2.jar\ub85c \uc774\ub984\uc744 \ubc14\uafb8\uc2ed\uc2dc\uc694. MainWindow.upgrade.error.downloading.hint=\uc624\ub958:\t\uc0c8 \ubc84\uc804\uc744 \ub0b4\ub824\ubc1b\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. \uc190\uc218 \uc5c5\ub370\uc774\ud2b8\ud558\uc2ed\uc2dc\uc694. MainWindow.upgrade.section.info=\uc0c8 \ubc84\uc804 \uc4f8 \uc218 \uc788\uc74c MainWindow.upgrade.section.manual=\uc190\uc218 \uc5c5\ub370\uc774\ud2b8 MainWindow.upgrade.section.automatic=\uc790\ub3d9 \uc5c5\ub370\uc774\ud2b8 MainWindow.upgrade.tooltip.progressbar=\ub0b4\ub824\ubc1b\uae30 \uc9c4\ud589\uc744 \uc5ec\uae30 \ubcf4\uc785\ub2c8\ub2e4. Button.next=\ub2e4\uc74c Button.finish=\ub9c8\uce68 Button.cancel=\ucde8\uc18c &C LocaleUtil.title=\uc778\ucf54\ub529 \uace0\ub974\uae30 LocaleUtil.section.chooseencoding=\ud30c\uc77c \uc774\ub984\uc5d0 \ub9de\ub294 \uc778\ucf54\ub529\uc744 \uace0\ub974\uc2ed\uc2dc\uc694. LocaleUtil.label.chooseencoding=\uac00\uc7a5 \uc798 \uc5b4\uc6b8\ub9ac\ub294 \uc778\ucf54\ub529\uc744 \uace0\ub974\uc2ed\uc2dc\uc694. LocaleUtil.label.hint.doubleclick=\uadc0\ub754: \uc904\uc5d0 \ub354\ube14 \ud074\ub9ad\ud558\uc5ec\uc11c \uc778\ucf54\ub529\uc744 \uace0\ub974\uace0 \uba54\uc138\uc9c0 \uc0c1\uc790\ub97c \ub2eb\uc2b5\ub2c8\ub2e4. LocaleUtil.label.checkbox.rememberdecision=\ub0a8\uc740 \ud30c\uc77c \uc774\ub984\uc744 \uc78a\uc9c0 \uc54a\uae30\ub85c \uacb0\uc815 LocaleUtil.column.encoding=\uc778\ucf54\ub529 IrcClient.copyright=PircBot Java IRC API\ub97c \uc4f0\uace0 \uc788\uc74c - http://www.jibble.org/pircbot.php IrcClient.connecting=\ub2e4\uc74c\uc73c\ub85c \uc5f0\uacb0\ud558\uace0 \uc788\uc74c IrcClient.connected=\ub2e4\uc74c\uc73c\ub85c \uc5f0\uacb0\ub428 IrcClient.joining=\ucc38\uac00\ud558\uace0 \uc788\uc74c IrcClient.channel=\ucc44\ub110 IrcClient.joined=\ucc38\uac00\ud568 IrcClient.error=\uc624\ub958 IrcClient.hasjoined=\ucc38\uac00\ud568 IrcClient.haskicked=\ucad3\uaca8\ub0a8 IrcClient.hasleft=\ub098\uac10 IrcClient.nowknown=\ub2e4\uc74c\ucc98\ub7fc \uc9c0\uae08 \uc54c\ub824\uc9d0 IrcClient.topicforchannel=\ucc44\ub110\uc758 \uc774\uc57c\uae43\uac70\ub9ac IrcClient.disconnected=\ub2e4\uc74c\uc5d0\uc11c \uc5f0\uacb0\uc774 \ub04a\uae40 IrcClient.noNick=\uc544\ubb34 \ub300\ud654\uba85\ub3c4 \uc815\ud574\uc9c0\uc9c0 \uc54a\uc74c. \uba54\ub274 \ubaa8\uc74c\uc5d0\uc11c '\uc120\ud0dd\uc0ac\ud56d' \uba54\ub274\ub85c \uac00\uc2ed\uc2dc\uc694. IrcView.actionnotsupported=\uc774 \ub3d9\uc791\uc740 \uc9c0\uc6d0\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. IrcView.clientsconnected=\uc0ac\uc6a9\uc790 IrcView.privateto=\ubc1b\ub294 \uc774 IrcView.privatefrom=\ubcf4\ub0b8 \uc774 IrcView.noticefrom=\uc54c\ub9bc: IrcView.errormsg=/msg\uc5d0\uc11c \uc798\ubabb\ub41c \ubb38\ubc95: /msg \uc0ac\uc6a9\uc790 \uae00 IrcView.help=\uc815\ud655\ud55c \uba85\ub839\uc5b4\ub4e4\uc740:\n . /help: \uc774 \uba54\uc138\uc9c0\ub97c \ubcf4\uc784\n . /nick | /name: \ub300\ud654\uba85\uc744 \ubc14\uafc8\n . /me action: \ub3d9\uc791\uc744 \ubcf4\ub0c4\n . /msg nick message: \uc5d0\uac8c \uadd3\uc18d\ub9d0\uc744 \ubcf4\ub0c4\n . /r message: \ub9c8\uc9c0\ub9c9 \uadd3\uc18d\ub9d0\uc5d0 \ub2f5\ud568\n . /join #channel: \uc9c0\uae08\uc758 \ucc44\ub110\uc744 \ubc14\uafc8 PasswordWindow.title=Vuze\uac00 \uc7a0\uacbc\uc74c PasswordWindow.passwordprotected=Vuze\uac00 \uc554\ud638\ub85c \ub9c9\ud614\uc2b5\ub2c8\ub2e4.\nVuze \ucc3d\uc744 \ubcf4\ub824\uba74 \uc5ec\uae30\uc5d0 \uc554\ud638\ub97c \uc368\ub123\uc73c\uc2ed\uc2dc\uc694.: Button.ok=\ud655\uc778 &O TrackerChangerWindow.title=\ub354\ub4ec\uc774 \ub354\ud558\uae30 TrackerChangerWindow.newtracker=\uc0c8 \ub354\ub4ec\uc774 \uc8fc\uc18c\ub97c \uc368\ub123\uc73c\uc2ed\uc2dc\uc694. PeersView.discarded=\ubc84\ub824\uc9d0 PeersView.discarded.info=\ub2f9\uc2e0\uc5d0\uac8c \ud544\uc694\ud558\uc9c0 \uc54a\uc558\ub354\ub77c\ub3c4 \uc5b4\ub5bb\uac8c \ud558\ub4e0\uc9c0 \ud574\uc11c \ubc1b\uc740 \ub370\uc774\ud130\uc785\ub2c8\ub2e4. \uadf8\ub798\uc11c \uadf8 \ub370\uc774\ud130\ub97c \uc9c0\uc6e0\uc2b5\ub2c8\ub2e4. discarded=\ubc84\ub824\uc9d0 MyTorrentsView.#=\ubc88\ud638 MyTorrentsView.menu.move=\uc62e\uae30\uae30(&M) MyTorrentsView.menu.moveUp=\uc704\ub85c(&U) MyTorrentsView.menu.moveDown=\uc544\ub798\ub85c(&D) GeneralView.label.hashfails=\ud574\uc2dc\ud558\uc9c0 \ubabb\ud568: GeneralView.label.shareRatio=\uacf5\uc720 \ube44: ConfigView.section.downloadManagement=\ub0b4\ub824\ubc1b\uae30 \uad00\ub9ac ConfigView.label.startRatioPeers=\ub2e4\uc74c \ub3d9\ub8cc\uc5d0 1 \uc528\uc557\ubcf4\ub2e4 \uc801\uc73c\uba74 \ubfcc\ub9ac\uae30 \uc2dc\uc791 ConfigView.text.neverStop=\uacb0\ucf54 \uba48\ucd94\uc9c0 \uc54a\uc74c ConfigView.text.neverStart=\uacb0\ucf54 \uc2dc\uc791\ud558\uc9c0 \uc54a\uc74c ConfigView.text.peers=\ub3d9\ub8cc ConfigView.label.checkOncompletion=\ub0b4\ub824\ubc1b\uae30 \uc644\ub8cc\ub418\uba74 \uc870\uac01\ub4e4\uc744 \ub2e4\uc2dc \uac80\uc0ac wizard.title=\ud1a0\ub7f0\ud2b8 \ub9cc\ub4e4\uae30 wizard.previous=< \ub4a4\ub85c wizard.next=\ub2e4\uc74c > wizard.finish=\ub9c8\uce68 wizard.mode=\ub354\ub4ec\uc774 / \ubc29\uc2dd wizard.tracker=\ub354\ub4ec\uc774: wizard.invalidurl=\uc774 \uc8fc\uc18c\ub294 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. wizard.singlefile=\ud55c \uac1c \ud30c\uc77c wizard.singlefile.help=\ud55c \uac1c \ud30c\uc77c\ub85c \ud1a0\ub7f0\ud2b8 \ub9cc\ub4e4\uae30 wizard.directory=\ud3f4\ub354 wizard.directory.help=\ud3f4\ub354\ub85c \ud1a0\ub7f0\ud2b8 \ub9cc\ub4e4\uae30 wizard.choosefile=\ud30c\uc77c \uace0\ub974\uae30 wizard.file=\ud30c\uc77c: wizard.browse=\ucc3e\uc544\ubcf4\uae30... wizard.choosedirectory=\ud3f4\ub354 \uace0\ub974\uae30 wizard.invalidfile=\uc798\ubabb\ub41c \ud30c\uc77c wizard.invaliddirectory=\uc798\ubabb\ub41c \ud3f4\ub354 wizard.torrentFile=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c wizard.choosetorrent=\ub9cc\ub4e4 \ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc744 \uace0\ub974\uc2ed\uc2dc\uc694. wizard.information=\uc815\ubcf4 wizard.notimplemented=\uc791\uc5c5 \uc9c4\ud589\uc911 wizard.progresstitle=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c \ub9cc\ub4e4\uace0 \uc788\uc74c wizard.savingfile=\ud30c\uc77c \uc800\uc7a5... wizard.filesaved=\ud30c\uc77c \uc800\uc7a5\ud588\uc2b5\ub2c8\ub2e4. wizard.close=\ub2eb\uae30 Torrent.create.progress.piecelength=\uc870\uac01 \uae38\uc774: Torrent.create.progress.piececount=\uc870\uac01 \uc218: Torrent.create.progress.totalfilesize=\ucd1d \ud30c\uc77c \ud06c\uae30: Torrent.create.progress.totalfilecount=\ucd1d \ud30c\uc77c \uc218: Torrent.create.progress.parsingfiles=\ud30c\uc77c \ubd84\uc11d\ud558\uace0 \uc788\uc74c Torrent.create.progress.hashing=\ud30c\uc77c \ud574\uc2dc\ud558\uace0 \uc788\uc74c MainWindow.upgrade.downloadingfrom=\ub2e4\uc74c\uc5d0\uc11c \ub0b4\ub824\ubc1b\uace0 \uc788\uc74c: MainWindow.menu.view.ipFilter=IP \ud544\ud130(&I) ConfigView.section.ipfilter=IP \ud544\ud130 ConfigView.section.ipfilter.description=\uc124\uba85 ConfigView.section.ipfilter.start=\ucc98\uc74c IP ConfigView.section.ipfilter.end=\ub9c8\uc9c0\ub9c9 IP ConfigView.section.ipfilter.add=\ub354\ud558\uae30 ConfigView.section.ipfilter.remove=\uc9c0\uc6b0\uae30 ConfigView.section.ipfilter.edit=\ud3b8\uc9d1 ConfigView.section.ipfilter.save=\uc800\uc7a5 ConfigView.section.ipfilter.editFilter=\ud544\ud130 \ud3b8\uc9d1 ConfigView.section.ipfilter.enable=\uc791\ub3d9 PeersView.menu.close=\ub2eb\uae30(&C) seedmore.title=\ud1a0\ub7f0\ud2b8\uac00 \uadf8\ub2e4\uc9c0 \ucda9\ubd84\ud558\uc9c0 \uc54a\uac8c \ubfcc\ub824\uc84c\uc2b5\ub2c8\ub2e4. seedmore.shareratio=\uc774 \ud1a0\ub7f0\ud2b8\uc5d0 \ub300\ud55c \ub2f9\uc2e0\uc758 \uacf5\uc720 \ube44\ub294 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4. - seedmore.uploadmore=100%\ubcf4\ub2e4 \ub0ae\uc740 \uacf5\uc720 \ube44\ub85c \ub9c8\uce58\ub294 \uac83\uc740 bittorrent \ub124\ud2b8\uc6cc\ud06c\uc5d0\uc11c \uadf8\ub2e4\uc9c0 \uc88b\uc740 \uc0dd\uac01\uc774 \uc544\ub2d9\ub2c8\ub2e4.\n\uc774 \ud1a0\ub7f0\ud2b8\ub97c \uc870\uae08 \ub354 \ubfcc\ub824\uc57c \ud569\ub2c8\ub2e4.\n\uc815\ub9d0 \uacc4\uc18d\ud558\uaca0\uc2b5\ub2c8\uae4c? ConfigView.label.showpopuponclose=1\ubcf4\ub2e4 \ub0ae\uc740 \uacf5\uc720 \ube44\uc778 \ucc44\ub85c \ubfcc\ub9ac\uae30\ub97c \uba48\ucd9c \ub54c \ud655\uc778 \uba54\uc138\uc9c0 \uc0c1\uc790\ub97c \ubcf4\uc5ec\uc90c ConfigView.label.startNumSeeds=\n\ub2e4\uc74c\ubcf4\ub2e4 \uc801\uc73c\uba74 \ubfcc\ub9ac\uae30 \uc2dc\uc791\n - \ub2e4\ub978 \ubaa8\ub4e0 \uaddc\uce59\ub4e4\uc744 \ubb34\uc2dc ConfigView.label.seeds=\uc528\uc557 ConfigView.section.seeding=\ubfcc\ub9ac\uae30 MyTorrentsView.menu.removeand=\uc9c0\uc6b0\uace0 \ub098\uc11c(&V) MyTorrentsView.menu.removeand.deletetorrent=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c \uc9c0\uc6b0\uae30(&T) MyTorrentsView.menu.removeand.deletedata=\ub370\uc774\ud130 \uc9c0\uc6b0\uae30(&D) MyTorrentsView.menu.removeand.deleteboth=\ub458 \ub2e4 \uc9c0\uc6b0\uae30(&B) deletedata.title=!!! \uacbd\uace0 !!! deletedata.message1=\ub2e4\uc74c\uc5d0\uc11c \ub370\uc774\ud130\ub97c \uc9c0\uae08 \uc9c0\uc6b0\ub824\uace0 \ud569\ub2c8\ub2e4:\n deletedata.noprompt=\ub2e4\uc2dc \ud45c\uc2dc\ud558\uc9c0 \uc54a\uc74c MainWindow.menu.file.configure=\uad6c\uc131 \ub9c8\ubc95\uc0ac...(&W) configureWizard.title=\uad6c\uc131 \ub9c8\ubc95\uc0ac configureWizard.welcome.title=Vuze \uad6c\uc131 \ub9c8\ubc95\uc0ac\uc5d0 \uc5b4\uc11c \uc624\uc2ed\uc2dc\uc694 configureWizard.welcome.message=\uc774 \ub9c8\ubc95\uc0ac\ub294 \uac00\uc7a5 \uc77c\ubc18\uc801\uc778 \uc6a9\ub3c4\ub85c Vuze\ub97c \uad6c\uc131\ud558\ub3c4\ub85d \ud574\uc904 \uac83\uc785\ub2c8\ub2e4. \ub3c4\uad6c->\uc120\ud0dd\uc0ac\ud56d \uba54\ub274\ub97c \uc368\uc11c \ubcf4\ub2e4 \uc790\uc138\ud55c \uad6c\uc131\uc744 \ubc14\uafc0 \uc218 \uc788\uc2b5\ub2c8\ub2e4. configureWizard.transfer.title=\uc804\uc1a1\uacfc \uc5f0\uacb0 \uad6c\uc131 configureWizard.transfer.hint=\uadc0\ub754: \ub2f9\uc2e0\uc758 \ud1b5\uc2e0 \uc18d\ub3c4\ubcf4\ub2e4 \uc870\uae08 \ub0ae\uac8c \uc4f0\ub294 \uac83\uc774 \uac00\uc7a5 \uc88b\uc2b5\ub2c8\ub2e4. configureWizard.transfer.message=\uc544\ub798\uc5d0\uc11c \uc5f0\uacb0\uc744 \uace0\ub974\uc2ed\uc2dc\uc694. \uc62c\ub9ac\uae30 \uc18d\ub3c4\ub97c \ucda9\ubd84\ud788 \ub450\uc9c0 \uc54a\uc73c\uba74 \ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4\uac00 \ub290\ub824\uc9c8 \uc218\ub3c4 \uc788\uc2b5\ub2c8\ub2e4. \ub0b4\ub824\ubc1b\ub294 \ud1a0\ub7f0\ud2b8\ub85c\ub9cc \uc62c\ub9ac\uae30 \uc18d\ub3c4\uac00 \uacc4\uc0b0\ub418\ubbc0\ub85c, \ud55c\ubc88\uc5d0 \ub108\ubb34 \ub9ce\uc740 \ud1a0\ub7f0\ud2b8\ub97c \ub0b4\ub824\ubc1b\uc73c\ub824 \ud558\uba74 \uc18d\ub3c4\uac00 \uc5ed\uc2dc \ub290\ub824\uc9c8 \uac83\uc785\ub2c8\ub2e4. \uc801\uc5b4\ub3c4 \ud1a0\ub7f0\ud2b8\ub9c8\ub2e4 \ucd5c\uc800 5KB/s\ub294 \ub418\uc5b4\uc57c \ud569\ub2c8\ub2e4. \ud1a0\ub7f0\ud2b8 \uc18d\ub3c4\ub294 \uc62c\ub9ac\uae30 \uc18d\ub3c4\uac00 \ube60\ub97c\uc218\ub85d \ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4\ub3c4 \ube68\ub77c\uc9d1\ub2c8\ub2e4. configureWizard.transfer.connection=\ud1b5\uc2e0\uc120 configureWizard.transfer.connection.0=\uc0ac\uc6a9\uc790 \uc9c0\uc815 configureWizard.transfer.connection.1=\ubaa8\ub380 configureWizard.transfer.connection.2=DSL/\ucf00\uc774\ube14 \ucd5c\ub300 128 kbps configureWizard.transfer.connection.3=DSL/\ucf00\uc774\ube14 \ucd5c\ub300 256 kbps configureWizard.transfer.connection.4=DSL/\ucf00\uc774\ube14 \ucd5c\ub300 384 kbps configureWizard.transfer.connection.5=DSL/\ucf00\uc774\ube14 \ucd5c\ub300 512 kbps configureWizard.transfer.connection.6=DSL/\ucf00\uc774\ube14 \ucd5c\ub300 768 kbps configureWizard.transfer.connection.7=DSL/\ucf00\uc774\ube14 \ucd5c\ub300 1024 kbps configureWizard.transfer.maxUpSpeed=\ucd5c\uace0 \uc62c\ub9ac\uae30 \uc18d\ub3c4 (KB/s) configureWizard.transfer.maxActiveTorrents=\ucd5c\ub300 \ud65c\ub3d9 \uc911 configureWizard.transfer.maxDownloads=\ucd5c\ub300 \ub0b4\ub824\ubc1b\uae30 configureWizard.transfer.maxUploadsPerTorrent=\ud1a0\ub7f0\ud2b8\ub9c8\ub2e4 \ucd5c\ub300 \uc62c\ub9ac\uae30 configureWizard.nat.title=\uacf5\uc720\uae30 / \uc11c\ubc84 \ud3ec\ud2b8 configureWizard.nat.message=Vuze\uc5d0\uc11c \uc7ac\uc131\ub2a5\uc744 \ub0bc\ub824\uba74 \uc778\ud130\ub137\uc811\uc18d\uc774 \uc6d0\ud560\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4. \uc774 \ub3c4\uad6c\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub3d9\ub8cc\ub4e4\uc774 \ub0b4 \ucef4\ud4e8\ud130\ub85c \uc811\uc18d\ud558\ub294 \ud3ec\ud2b8\ub97c \ubcc0\uacbd\ud558\uac70\ub098 \uc811\uc18d\uc774 \uc6d0\ud560\ud55c\uc9c0 \uac80\uc0ac\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \n\n\uadc0\ub754 : \uc774 \ub3c4\uad6c\ub294 TCP\uc811\uc18d \uc5f0\uacb0\ub9cc \uac80\uc0ac\ud569\ub2c8\ub2e4. \ubc30\ud3ec\ub41c DB(The Distributed DB)\ub294 \ub4e4\uc5b4\uc624\ub294 UDP \uc811\uc18d\uc774 \ud544\uc694\ud55c\ub370, \ub9cc\uc57d \ubc29\ud654\ubcbd\ub4f1\uc774 \ub9c9\uace0\uc788\ub294\uac8c \ubc1c\uacac\ub418\uba74 \uc790\ub3d9\uc73c\ub85c \uc54c\ub824\uc904 \uac83\uc785\ub2c8\ub2e4.\n\n\uadc0\ub754: TCP \ud3ec\ud2b8 6880 \ub0b4\ubd80\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\uae30\ub54c\ubb38\uc5d0 \uc0ac\uc6a9\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. configureWizard.nat.test=\uac80\uc0ac configureWizard.nat.testing=\ud3ec\ud2b8 \uac80\uc0ac \uc911 configureWizard.nat.ok=\ud655\uc778 configureWizard.nat.ko=\uacf5\uc720\uae30 \uc624\ub958 configureWizard.nat.unable=\uac80\uc0ac\uac00 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc74c configureWizard.file.title=\ud1a0\ub7f0\ud2b8 / \ud30c\uc77c configureWizard.file.message1=Vuze\uac00 \ud2b9\uc815\ud55c \ud3f4\ub354\uc5d0 \uc5f4\ub9b0 \ud1a0\ub7f0\ud2b8\ub97c \uc800\uc7a5\ud560 \uac83\uc785\ub2c8\ub2e4. \uc774 \ud3f4\ub354\ub97c \uc5ec\uae30\uc5d0\uc11c \uace0\ub97c \uc218 \uc788\uc2b5\ub2c8\ub2e4: configureWizard.file.path=\uc704\uce58 configureWizard.file.browse=\ucc3e\uc544\ubcf4\uae30 configureWizard.file.message2=Vuze\uac00 \ub2f9\uc2e0\uc758 \ud1a0\ub7f0\ud2b8\ub4e4\uc5d0 \ub2e4\uc2dc \uc2dc\uc791 \ub370\uc774\ud130\ub97c \ub354\ud574\uc11c \ud30c\uc77c\ub4e4\uc744 \ubc14\ub85c \ub2e4\uc2dc \uc2dc\uc791\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc774 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uba74, \ubd80\ubd84\uc801\uc73c\ub85c \ub0b4\ub824\ubc1b\uc740 \uc870\uac01\ub4e4\ub3c4 \ub2e4\uc2dc \uc2dc\uc791\ud560 \uac83\uc785\ub2c8\ub2e4. configureWizard.file.fastResume=\ube60\ub978 \ub2e4\uc2dc \uc2dc\uc791\ud558\uae30 \uc791\ub3d9 configureWizard.file.invalidPath=\uc798\ubabb\ub41c \ud3f4\ub354 configureWizard.finish.title=\ub9c8\uce68 configureWizard.finish.message=Vuze\uac00 \uc774\uc81c \uad6c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \uc990\uae30\uc138\uc694! wizard.close.confirmation=\ud655\uc778 wizard.close.message=\ub2e4\uc74c\uc5d0 Vuze\ub97c \uc2dc\uc791\ud560 \ub54c \uc774 \ub9c8\ubc95\uc0ac\ub97c \ubd80\ub974\uaca0\uc2b5\ub2c8\uae4c? exportTorrentWizard.title=\ud1a0\ub7f0\ud2b8\ub97c XML\ub85c \ub0b4\ubcf4\ub0b4\uae30 exportTorrentWizard.torrentfile.title=\uc785\ub825 \ud1a0\ub7f0\ud2b8 \uace0\ub974\uae30 exportTorrentWizard.torrentfile.message=\ub0b4\ubcf4\ub0bc \ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc744 \uace0\ub974\uc2ed\uc2dc\uc694. exportTorrentWizard.torrentfile.path=\uc704\uce58 exportTorrentWizard.torrentfile.browse=\ucc3e\uc544\ubcf4\uae30 exportTorrentWizard.torrentfile.invalidPath=\uc798\ubabb\ub41c \ud1a0\ub7f0\ud2b8 \ud30c\uc77c exportTorrentWizard.exportfile.title=\ub0b4\ubcf4\ub0b4\uae30 \ud30c\uc77c \uace0\ub974\uae30 exportTorrentWizard.exportfile.message=\ub0b4\ubcf4\ub0bc xml \ud30c\uc77c \uc774\ub984\uc744 \uc368\ub123\uc73c\uc2ed\uc2dc\uc694. exportTorrentWizard.exportfile.path=\uc704\uce58 exportTorrentWizard.exportfile.browse=\ucc3e\uc544\ubcf4\uae30 exportTorrentWizard.exportfile.invalidPath=\uc798\ubabb\ub41c \ub0b4\ubcf4\ub0b4\uae30 \ud30c\uc77c exportTorrentWizard.finish.title=\ub05d\ub9c8\uce68 exportTorrentWizard.finish.message=\ub0b4\ubcf4\ub0b4\uae30\ub97c \uc81c\ub300\ub85c \ub05d\ub9c8\uce68 exportTorrentWizard.process.inputfilebad.title=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc774 \ub9de\uc9c0 \uc54a\uc74c exportTorrentWizard.process.inputfilebad.message=\uc785\ub825 \ud30c\uc77c\uc5d0 \uc811\uadfc\ud558\uc9c0 \ubabb\ud568: exportTorrentWizard.process.outputfileexists.title=\ud30c\uc77c\uc774 \uc788\uc74c exportTorrentWizard.process.outputfileexists.message=\ucd9c\ub825 \ud30c\uc77c\uc774 \uc788\uc74c - \ub36e\uc5b4 \uc4f0\uaca0\uc2b5\ub2c8\uae4c? exportTorrentWizard.process.torrentfail.title=\ud1a0\ub7f0\ud2b8\ub97c \uc77d\uc9c0 \ubabb\ud568 exportTorrentWizard.process.exportfail.title=\ud1a0\ub7f0\ud2b8\ub97c \ub0b4\ubcf4\ub0b4\uc9c0 \ubabb\ud568 exportTorrentWizard.process.unknownfail.title=\ub73b\ubc16\uc758 \uc624\ub958 importTorrentWizard.title=XML \ud1a0\ub7f0\ud2b8\ub97c \ub4e4\uc5ec\uc624\uae30 importTorrentWizard.torrentfile.title=\uc785\ub825 \ud1a0\ub7f0\ud2b8 \uace0\ub974\uae30 importTorrentWizard.torrentfile.message=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc5d0 \ub4e4\uc5ec\uc62c \ud1a0\ub7f0\ud2b8 \ud30c\uc77c \uc774\ub984\uc744 \uc368\ub123\uc73c\uc2ed\uc2dc\uc694. importTorrentWizard.torrentfile.path=\uc704\uce58 importTorrentWizard.torrentfile.browse=\ucc3e\uc544\ubcf4\uae30 importTorrentWizard.torrentfile.invalidPath=\uc798\ubabb\ub41c \ud1a0\ub7f0\ud2b8 \ud30c\uc77c importTorrentWizard.importfile.title=\ub4e4\uc5ec\uc624\uae30 \ud30c\uc77c \uace0\ub974\uae30 importTorrentWizard.importfile.message=\ub4e4\uc5ec\uc62c xml \ud30c\uc77c\uc744 \uace0\ub974\uc2ed\uc2dc\uc694. importTorrentWizard.importfile.path=\uc704\uce58 importTorrentWizard.importfile.browse=\ucc3e\uc544\ubcf4\uae30 importTorrentWizard.importfile.invalidPath=\uc798\ubabb\ub41c \ub4e4\uc5ec\uc624\uae30 \ud30c\uc77c importTorrentWizard.finish.title=\ub05d\ub9c8\uce68 importTorrentWizard.finish.message=\ub4e4\uc5ec\uc624\uae30\ub97c \uc81c\ub300\ub85c \ub05d\ub9c8\uce68 importTorrentWizard.process.inputfilebad.title=\uc798\ubabb\ub41c \ub4e4\uc5ec\uc624\uae30 \ud30c\uc77c importTorrentWizard.process.inputfilebad.message=\uc785\ub825 \ud30c\uc77c\uc5d0 \uc811\uadfc\ud558\uc9c0 \ubabb\ud568: importTorrentWizard.process.outputfileexists.title=\ud30c\uc77c\uc774 \uc788\uc74c importTorrentWizard.process.outputfileexists.message=\ucd9c\ub825 \ud30c\uc77c\uc774 \uc788\uc74c - \ub36e\uc5b4 \uc4f0\uaca0\uc2b5\ub2c8\uae4c? importTorrentWizard.process.torrentfail.title=\ud1a0\ub7f0\ud2b8\ub97c \uc4f0\uc9c0 \ubabb\ud568 importTorrentWizard.process.importfail.title=\ud1a0\ub7f0\ud2b8\ub97c \ub4e4\uc5ec\uc624\uc9c0 \ubabb\ud568 importTorrentWizard.process.unknownfail.title=\ub73b\ubc16\uc758 \uc624\ub958 ConfigView.label.bindip=\ub85c\uceec IP \uc8fc\uc18c\ub85c \uc5f0\uacb0 or interface xfs.allocation.xfs_io.not.found=/usr/sbin/xfs_io\uac00 \uc791\ub3d9\ud558\uc9c0 \uc54a\uc544 XFS\ud30c\uc77c \ud560\ub2f9\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4. \uc2dc\uc2a4\ud15c\uc5d0 \uc124\uce58\uac00 \uc548\ub418\uc5b4 \uc788\uc744 \uc218\ub3c4 \uc788\uc2b5\ub2c8\ub2e4. \uc624\ub958 \uba54\uc138\uc9c0 : "%1". ConfigView.label.zeronewfiles=\ub9cc\ub4e4 \ub54c \uc0c8 \ud30c\uc77c\uc744 \ud560\ub2f9\ud558\uace0 0\uc5d0 \ub9de\ucda4 ConfigView.label.zeronewfiles.tooltip=\uc870\uac01 \ucd5c\uc18c\ub85c \ud568 ConfigView.section.stats=\ud1b5\uacc4 ConfigView.section.stats.enable=\uc791\ub3d9 ConfigView.section.stats.defaultsavepath=\ud1b5\uacc4 \uc800\uc7a5 \ud3f4\ub354 ConfigView.section.stats.choosedefaultsavepath=\ud1b5\uacc4 \uc800\uc7a5 \ud3f4\ub354\ub97c \uace0\ub974\uc2ed\uc2dc\uc694. ConfigView.section.stats.savefreq=\ube48\ub3c4 \uc800\uc7a5 ConfigView.section.stats.minutes=\ubd84 ConfigView.section.stats.hours=\uc2dc\uac04 ConfigView.section.stats.seconds=\ucd08 ConfigView.section.stats.savefile=\ud1b5\uacc4 \ud30c\uc77c \uc774\ub984 MyTorrentsView.menu.export=XML \ud1a0\ub7f0\ud2b8...(&X) MyTorrentsView.menu.host=\ud638\uc2a4\ud2b8...(&H) ManagerItem.finishing=\ub9c8\uce58\uace0 \uc788\uc74c ConfigView.dialog.choosedefaulttorrentpath=\uae30\ubcf8 \ud1a0\ub7f0\ud2b8 \ud3f4\ub354\ub97c \uace0\ub974\uc2ed\uc2dc\uc694. ConfigView.dialog.choosemovepath=\uc62e\uae38 \ud3f4\ub354\ub97c \uace0\ub974\uc2ed\uc2dc\uc694. ConfigView.label.movecompleted=\ub05d\ub9c8\uce5c \ud30c\uc77c \uc62e\uae40 ConfigView.label.moveremoved=\uc644\ub8cc\ub41c \ud30c\uc77c \uc62e\uae30\uae30 (\uc62e\uae30\uae30 \uc2dc\uc791\ud560\ub54c) ConfigView.label.savetorrents=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c \uc800\uc7a5 MainWindow.menu.view.mytracker=\ub0b4 \ub354\ub4ec\uc774(&T) MainWindow.menu.view.mytracker.keybinding=\uba54\ud0c0+2 MyTrackerView.title.full=\ub0b4 \ub354\ub4ec\uc774 MyTrackerView.name=\uc774\ub984 MyTrackerView.tracker=\ub354\ub4ec\uc774 MyTrackerView.status=\uc0c1\ud0dc MyTrackerView.status.started=\uc2dc\uc791 MyTrackerView.status.stopped=\uba48\ucda4 MyTrackerView.peers=\ub3d9\ub8cc MyTrackerView.seeds=\uc528\uc557 MyTrackerView.announces=\ub354\ub4ec\uc774 \uc54c\ub9ac\uae30 MyTrackerView.uploaded=\uc62c\ub824\uc9d0 MyTrackerView.downloaded=\ub0b4\ub824\ubc1b\uc74c MyTrackerView.left=\ub0a8\uc74c ConfigView.section.style=\uc778\ud130\ud398\uc774\uc2a4 ConfigView.section.style.useCustomTabs=\ub2eb\uc744 \uc218 \uc788\ub294 \ud0ed \uc4f0\uae30 (\ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud568) MainWindow.menu.view.plugins=\ucd94\uac00\uae30\ub2a5(&P) fileDownloadWindow.saveTorrentIn=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c \uc800\uc7a5 \uc704\uce58 fileDownloadWindow.title=Vuze - \ud1a0\ub7f0\ud2b8 \ub0b4\ub824\ubc1b\uae30 \ud504\ub85c\uadf8\ub7a8 fileDownloadWindow.downloading=\ub0b4\ub824\ubc1b\uae30\ud558\uace0 \uc788\ub294 \uacf3: fileDownloadWindow.status=\uc0c1\ud0dc: fileDownloadWindow.state_initializing=\ucd08\uae30\uac12\uc5d0 \ub9de\ucd94\uace0 \uc788\uc74c fileDownloadWindow.state_downloading=\ub0b4\ub824\ubc1b\uae30\ud558\uace0 \uc788\uc74c fileDownloadWindow.state_error=\uc624\ub958: MainWindow.menu.file.open.url=\uc8fc\uc18c(&U) openUrl.title=\uc8fc\uc18c \uc5f4\uae30 openUrl.url=\uc8fc\uc18c: MyTorrentsView.menu.host.error.title=\ud1a0\ub7f0\ud2b8 \ud638\uc2a4\ud2b8\ud558\uc9c0 \ubabb\ud568 MyTorrentsView.menu.host.error.message=\ud1a0\ub7f0\ud2b8\ub97c \ud638\uc2a4\ud2b8\ud558\ub2e4\uac00 \ub2e4\uc74c \uc624\ub958\uac00 \uc0dd\uacbc\uc2b5\ub2c8\ub2e4. ConfigView.section.tracker=\ub354\ub4ec\uc774 ConfigView.section.tracker.pollinterval=\ub354\ub4ec\uc774 \uc811\uc18d \ucef4\ud4e8\ud130 \ud3f4\ub9c1 \uac04\uaca9 (\ucd08) ConfigView.section.tracker.publishenable=""\ub85c \ud1a0\ub7f0\ud2b8 \uc0c1\uc138 \uc815\ubcf4 \uc54c\ub9bc ConfigView.section.tracker.ip=\uc678\ubd80 IP \uc8fc\uc18c \ud2b8\ub798\ucee4 ConfigView.section.style.enableXPStyle=XP \uc2a4\ud0c0\uc77c \uc791\ub3d9 (\ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud568) IPChecker.external.service.dyndns.description=\uc720\ub3d9 DNS \ub124\ud2b8\uc6cc\ud06c \uc11c\ube44\uc2a4, \uc720\ud55c \ucc45\uc784 \ud68c\uc0ac ConfigView.section.tracker.checkip=\uc678\ubd80 IP \uc8fc\uc18c\ub97c \uc800\uc808\ub85c \uc54c\uc544\ucc54... ipCheckerWizard.title=IP \uac80\uc0ac \ub9c8\ubc95\uc0ac ipCheckerWizard.service=\uc11c\ube44\uc2a4 ipCheckerWizard.chooseService=\ub4e4\uace0 \uc788\ub294 \uc11c\ube44\uc2a4\uc5d0\uc11c IP \uac80\uc0ac \uc11c\ube44\uc2a4\ub97c \uace0\ub974\uc2ed\uc2dc\uc694. ipCheckerWizard.explanations=\uc774 \ub9c8\ubc95\uc0ac\ub97c \uc368\uc11c \uc774 \ucef4\ud4e8\ud130\uc758 \uc678\ubd80 IP \uc8fc\uc18c\uac00 \ubb34\uc5c7\uc778\uc9c0 \uc54c\uc544\ub0bc \uc218 \uc788\uc2b5\ub2c8\ub2e4. IP \uc8fc\uc18c\uac00 \uc720\ub3d9 IP\uc774\uba74 DDNS \uc11c\ube44\uc2a4\ub85c IP\uc8fc\uc18c\ub97c \uc5f0\uacb0 \uc2dc\ucf1c \ud638\uc2a4\ud2b8 \uc774\ub984\uc744 \ub9cc\ub4e4 \uac83\uc744 \uad8c\ud569\ub2c8\ub2e4. \uc544\ub798\uc758 \ubb34\ub8cc \uc11c\ube44\uc2a4 \uc81c\uacf5\uc790\ub4e4\uc744 \ucc38\uace0\ud558\uc5ec \uacc4\uc815\uc744 \ub9cc\ub4e4\uace0 \ub098\uc11c \uc0ac\uc6a9\ud560 \uc720\ub3d9 \ud638\uc2a4\ud2b8 \uc774\ub984(\uc608 myhostname.dyndns.org)\uc744 \ub9cc\ub4e4\uc5b4 \uc774 \ucef4\ud4e8\ud130\uc758 \uc678\ubd80IP \uc8fc\uc18c\uc640 \uc5f0\uacb0 \uc2dc\ud0a4\uc138\uc694. DDNS \uc11c\ube44\uc2a4\ub97c \uc790\ub3d9\uc73c\ub85c \uc720\uc9c0 \uc2dc\ud0a4\ub824\uba74 \ud504\ub85c\uadf8\ub7a8\uc744 \uc0c1\uc8fc\ud560 \uc218 \ub3c4 \uc788\uc2b5\ub2c8\ub2e4. \uc124\uc815\uc774 \uc644\ub8cc\ub418\uba74 IP\uac00 \ubc14\ub00c\uc5b4\ub3c4 \ud1a0\ub7f0\ud2b8\ub97c \ud638\uc2a4\ud2b8\ud558\uac8c \ub420 \uac83\uc785\ub2c8\ub2e4. ipCheckerWizard.service.description=\uc124\uba85: ipCheckerWizard.service.url=\uc8fc\uc18c: ipCheckerWizard.progresstitle=IP \uac80\uc0ac\ud558\uace0 \uc788\uc74c ipCheckerWizard.checkComplete=\ub05d\ub9c8\uce5c IP: ipCheckerWizard.checkFailed=\uc791\ub3d9\ud558\uc9c0 \uc54a\ub294 IP, \uae4c\ub2ed: wizard.tracker.local=Vuze\uc5d0 \ub0b4\uc7a5\ub41c \ub354\ub4ec\uc774\ub97c \uc500 wizard.tracker.external=\uc678\ubd80 \ub354\ub4ec\uc774\ub97c \uc500 wizard.tracker.howToLocal=\t\uc791\ub3d9\uc2dc\ud0a4\ub824\uba74 '\ub3c4\uad6c->\uc120\ud0dd\uc0ac\ud56d->\ub354\ub4ec\uc774'\ub85c \uac00\uc2ed\uc2dc\uc694. wizard.announceUrl=\ub354\ub4ec\uc774 \uc54c\ub9bc \uc8fc\uc18c(Announce URL): IPChecker.external.service.discoveryvip.description=Discoveryvip - IP \uc8fc\uc18c \uac80\uc0ac\ub9cc IPChecker.external.httpinvalidresponse=\uc798\ubabb\ub41c HTTP \ubc18\uc751 IPChecker.external.loadingwebpage=\uc6f9 \ud398\uc774\uc9c0\ub97c \uc5f4\uace0 \uc788\uc74c IPChecker.external.analysingresponse=\ubc18\uc751\uc744 \ubd84\uc11d\ud558\uace0 \uc788\uc74c IPChecker.external.addressextracted=\ubf51\uc544\ub0b8 IP \uc8fc\uc18c IPChecker.external.httploadfail=\ud398\uc774\uc9c0\ub97c \uc5f4\uc9c0 \ubabb\ud568 IPChecker.external.timeout=\uc2dc\uac04\uc744 \ub118\uacbc\uc2b5\ub2c8\ub2e4. IPChecker.external.ipnotfound=IP \uc8fc\uc18c\ub97c \ucc3e\uc9c0 \ubabb\ud568 ConfigView.section.tracker.pollintervalmin=\ucd5c\uc18c ConfigView.section.tracker.pollintervalmax=\ucd5c\ub300 ConfigView.section.tracker.pollintervalincby=\ub2e4\uc74c \uc218\ub9cc\ud07c\uc529 \ub29a ConfigView.section.tracker.pollintervalincper=\ub2e4\uc74c \uc218\uc758 \uc811\uc18d \ucef4\ud4e8\ud130\ub9c8\ub2e4 splash.loadingImages=\uc774\ubbf8\uc9c0\ub97c \ubd88\ub7ec\uc624\uace0 \uc788\uc74c splash.initializeGui=\uc8fc \ucc3d\uc744 \ucd08\uae30\uac12\uc5d0 \ub9de\ucd94\uace0 \uc788\uc74c splash.openViews=\ubcf4\uc784\uc0c8\ub97c \uc5f4\uace0 \uc788\uc74c splash.plugin=\ucd94\uac00\uae30\ub2a5\uc744 \uc2dc\uc791\ud558\uace0 \uc788\uc74c: configureWizard.nat.tooManyPorts=\uac80\uc0ac\ud560 \ud3ec\ud2b8\uac00 \ub108\ubb34 \ub9ce\uc74c (\ucd5c\ub300 9) ConfigView.section.color=\ube5b\uae54 \uad6c\uc131\ud45c MyTorrentsView.menu.publish=\ubc1c\ud589..(&P) MyTrackerView.status.published=\ubc1c\ud589 MyTrackerView.completed=\ub9c8\uce68 MainWindow.menu.file.open.torrentnodefault=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c... (\uae30\ubcf8 \uc800\uc7a5 \uc5c6\uc74c) wizard.comment=\ub367\ub9d0 ConfigView.label.movetorrent=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c \uc62e\uae40 ConfigView.label.movepartialdownloads=\uba87\uba87 \ud30c\uc77c\uc774 "\ub2e4\uc6b4\ub85c\ub4dc \ud558\uc9c0 \ub9c8\uc138\uc694"\ub85c \ub418\uc5b4\uc788\uc5b4\ub3c4 \uc62e\uae40 ConfigView.section.file.decoder.label=\uace0\ub978 \uac83\uc5d0 \ud544\uc694\ud560 \ub54c\uc758 \uae30\ubcf8 \ud1a0\ub7f0\ud2b8 \uc778\ucf54\ub529 ConfigView.section.file.decoder.nodecoder=\uace0\ub974\uc9c0 \uc54a\uc74c IPChecker.external.service.no-ip.description=\uc720\ub3d9 \ubc0f \uace0\uc815 DNS \uc11c\ube44\uc2a4 \uacf5\uae09\uc790\n(\uc790\uc720\ub85c\uc774 \uc4f8 \uc218 \uc5c6\ub294 '\uc8fc\uc18c \uac80\uc0ac' \uc11c\ube44\uc2a4) ConfigView.section.tracker.publicenable=\uc678\ubd80 \ud1a0\ub7f0\ud2b8 \uc791\ub3d9 ConfigView.label.playdownloadspeech=\ub0b4\ub824\ubc1b\uae30\uac00 \ub05d\ub0a0 \ub54c \uc6b8\ub9bc ConfigView.label.playdownloadspeech.info=\uc6b8\ub9bc \uc11c\ube44\uc2a4\ub294 \uc9c0\uae08 \uc601\uc5b4\ub85c \uac00\uc7a5 \uc798 \uc791\ub3d9\ud569\ub2c8\ub2e4 # # Tooltips # GeneralView.label.status.pieces_available.tooltip=\uc4f8 \uc218 \uc788\ub294 \ub0b1\ub0b1\uc758 \uc870\uac01 \uc218\ub97c \ub098\ud0c0\ub0c5\ub2c8\ub2e4.\n\uc624\ub978\ucabd\uc758 \uc218\uac00 1\ubcf4\ub2e4 \uc791\uc73c\uba74 \uc644\uc804\ud55c \ud30c\uc77c\uc744 \ubcfc \uc218 \uc5c6\uace0 (\ub0b4\ub824\ubc1b\uae30\ub97c \ub9c8\uce60 \uc218) \uc5c6\uc744 \uac83\uc785\ub2c8\ub2e4. GeneralView.label.trackerurl.tooltip=\ub354\ub4ec\uc774 \uc54c\ub9bc \uc8fc\uc18c(Announce URL)\ub97c \ud074\ub9bd\ubcf4\ub4dc\ub85c \ubcf5\uc0ac\ud558\ub824\uba74 \ud074\ub9ad GeneralView.label.trackerurlopen.tooltip=\ub354\ub4ec\uc774 \uba54\uc778 \ud398\uc774\uc9c0\ub97c \uc5f4\ub824\uba74 \ud074\ub9ad # # 2.0.4.4 # ConfigView.section.style.guiUpdate=\ub2e4\uc74c \uc2dc\uac04\ub9c8\ub2e4 GUI \uc5c5\ub370\uc774\ud2b8 ConfigView.section.style.graphicsUpdate=\ub2e4\uc74c \uc218\uc758 GUI \uc5c5\ub370\uc774\ud2b8\ub9c8\ub2e4 \uadf8\ub798\ud53d \ub9c9\ub300 \uc5c5\ub370\uc774\ud2b8 ConfigView.section.style.reOrderDelay=\ub2e4\uc74c \uc218\uc758 GUI \uc5c5\ub370\uc774\ud2b8\ub9c8\ub2e4 \ubaa9\ub85d \ub2e4\uc2dc \uc815\ub82c [0: \uacb0\ucf54 \ud558\uc9c0 \uc54a\uc74c] ConfigView.section.style.reOrderDelay.never=\uacb0\ucf54 \ud558\uc9c0 \uc54a\uc74c ConfigView.section.logging=\uae30\ub85d \ub0a8\uae30\uae30 ConfigView.section.logging.enable=\ud30c\uc77c\ub85c \uae30\ub85d \ub0a8\uae30\uae30 \uc791\ub3d9 ConfigView.section.logging.logdir=\ud30c\uc77c \ud3f4\ub354 \uae30\ub85d ConfigView.section.logging.choosedefaultsavepath=\uc800\uc7a5 \ud3f4\ub354\ub97c \uace0\ub974\uc2ed\uc2dc\uc694. GeneralView.label.updatein.querying=\uc54c\uc544 \ubcf4\uace0 \uc788\uc74c... configureWizard.nat.sharePort=\ubaa8\ub4e0 \ud1a0\ub7f0\ud2b8\uc5d0 \ub2e8 \ud558\ub098\uc758 \uacf5\uc720\ub41c \ub4e4\uc5b4\uc624\ub294 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9 ConfigView.section.logging.maxsize=\uae30\ub85d \ud30c\uc77c \ucd5c\ub300 \ud06c\uae30 ConfigView.section.tracker.passwordenableweb=\ub354\ub4ec\uc774 \uc6f9\uc5d0 \uc554\ud638 \uc791\ub3d9 ConfigView.section.tracker.passwordenabletorrent=\ud1a0\ub7f0\ud2b8\uc5d0 \uc554\ud638 \uc791\ub3d9 ConfigView.section.tracker.username=\uc0ac\uc6a9\uc790 \uc774\ub984 ConfigView.section.tracker.password=\uc554\ud638 columnChooser.title=\ud45c\uc2dc\ud560 \uc138\ub85c\uc904\uc744 \uace0\ub974\uc2ed\uc2dc\uc624 columnChooser.move=\ub2e4\uc2dc \uc815\ub9ac\ud558\ub824\uba74 \uc904\uc744 \ub044\uc2ed\uc2dc\uc624 columnChooser.apply=\uc801\uc6a9 columnChooser.columnname=\uc138\ub85c\uc904 \uc774\ub984 columnChooser.columndescription=\uc124\uba85 TableColumn.header.shareRatio=\uacf5\uc720 \ube44 MyTorrentsView.menu.editTableColumns=\uc138\ub85c\uc904 \uad6c\uc131(&C) wizard.operationfailed=\uc791\uc5c5 \uc2e4\ud328 authenticator.title=\uc778\uc99d \ud544\uc694 authenticator.realm=\uc601\uc5ed authenticator.tracker=\ub354\ub4ec\uc774 authenticator.user=\uc0ac\uc6a9\uc790 \uc774\ub984 authenticator.password=\uc554\ud638 ConfigView.label.allowSendVersion=\uc0c8 \ubc84\uc804\uc744 \uac80\uc0ac\ud558\ub294 \ub3d9\uc548 Vuze\uac00 \uc775\uba85\uc758 \ubc84\uc804 \ubc88\ud638\uc640 \uc784\uc758\uc758 \uc544\uc774\ub514\ub97c \ubcf4\ub0b4\ub3c4\ub85d \ud5c8\uc6a9 wizard.hint.mode=\uadc0\ub754:\t\ud30c\uc77c\uc774\ub098 \ud3f4\ub354\ub97c \uace0\ub974\ub824\uba74 \uc774 \ub9c8\ubc95\uc0ac\uc5d0 \ud55c \uac1c \ud30c\uc77c\uc774\ub098 \ud3f4\ub354\ub97c\n\t\ub04c\uc5b4\ub2e4\uac00 \ub193\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4. wizard.hint.file=\uadc0\ub754:\t\ub04c\uc5b4\ub2e4\uac00 \ub193\uae30\ub85c \ud55c \uac1c \ud30c\uc77c\uc744 \uace0\ub97c \uc218 \uc788\uc2b5\ub2c8\ub2e4. wizard.hint.directory=\uadc0\ub754:\t\ub04c\uc5b4\ub2e4\uac00 \ub193\uae30\ub85c \ud55c \uac1c \ud3f4\ub354\ub97c \uace0\ub97c \uc218 \uc788\uc2b5\ub2c8\ub2e4. MainWindow.menu.help.checkupdate=\uc5c5\ub370\uc774\ud2b8 \uac80\uc0ac...(&C) TableColumn.header.down=\ub0b4\ub824\ubc1b\uc74c TableColumn.header.up=\uc62c\ub824\uc9d0 ConfigView.section.tracker.passwordenabletorrent.info=\uc54c\ub9de\uc740 BitTorrent \uc811\uc18d \ud504\ub85c\uadf8\ub7a8\uc774 \uc788\uc5b4\uc57c \ud568 (\uc608 Vuze ConfigView.section.style.confirmationOnExit=\ub05d\ub0bc \ub54c \ud655\uc778 \uba54\uc138\uc9c0 \uc0c1\uc790 \ubcf4\uc774\uae30 MainWindow.dialog.exitconfirmation.title=Vuze\ub97c \ub05d\ub0b4\uaca0\uc2b5\ub2c8\uae4c? MainWindow.dialog.exitconfirmation.text=Vuze\ub97c \uc815\ub9d0 \ub05d\ub0b4\uaca0\uc2b5\ub2c8\uae4c? SystemTray.menu.stopalltransfers=\ubaa8\ub4e0 \uc804\uc1a1 \uba48\ucda4(&A) TrayWindow.menu.stopalldownloads=\ubaa8\ub4e0 \ub0b4\ub824\ubc1b\uae30 \uba48\ucda4(&A) ConfigView.section.tracker.sslport.info=\ud55c\uacb0 \ub354\ud55c \uc815\ubcf4\ub294 \uc790\uc8fc \ubb3b\ub294 \ubb3c\uc74c\uc744 \ubcf4\uc2ed\uc2dc\uc694. wizard.tracker.ssl=SSL\uc744 \uc500 ConfigView.label.playdownloadfinished=\ub0b4\ub824\ubc1b\uae30\uac00 \ub05d\ub0a0 \ub54c \uc18c\ub9ac\ub0b4\uae30 TableColumn.header.pieces=\uc870\uac01 TableColumn.header.pieces.info=\uadf8\ub798\ud53d \ub9c9\ub300\ub294 \uc5b4\ub290 \uc870\uac01\uc744 \ub0b4\ub824\ubc1b\uc558\ub294\uc9c0 \ubcf4\uc5ec\uc90d\ub2c8\ub2e4. TableColumn.header.completion=\ub05d\ub9c8\uce68 TableColumn.header.completion.info=\ub0b4\ub824\ubc1b\uc740 %\uc758 \uadf8\ub798\ud53d \ud45c\uc2dc ConfigView.section.style.showdownloadbasket=\ub0b4\ub824\ubc1b\uae30 \ubc14\uad6c\ub2c8 \ubcf4\uc774\uae30 (\ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc744 \ub04c\uc5b4\ub2e4\uac00 \ub193\uae30) ConfigView.section.style.alwaysShowTorrentFiles=\uc0c1\uc138 \uc815\ubcf4/\ud30c\uc77c\uc5d0 \ud1a0\ub7f0\ud2b8 \ud30c\uc77c \ub298 \ubcf4\uc774\uae30 wizard.multitracker=\ud1a0\ub7f0\ud2b8\uc5d0 \uc5ec\ub7ec \ub354\ub4ec\uc774 \uc815\ubcf4\ub97c \ub354\ud558\uae30 wizard.multitracker.title=\uc5ec\ub7ec \ub354\ub4ec\uc774 wizard.multitracker.configuration=\uc5ec\ub7ec \ub354\ub4ec\uc774 \uc124\uc815 wizard.multitracker.new=\uc0c8\ub85c\uc6b4... wizard.multitracker.edit=\ud3b8\uc9d1... wizard.multitracker.delete=\uc9c0\uc6b0\uae30 wizard.multitracker.group=\ub354\ub4ec\uc774 \ubb36\uc74c wizard.multitracker.edit.title=\uc5ec\ub7ec \ub354\ub4ec\uc774 \ud3b8\uc9d1\uae30 wizard.multitracker.edit.name=\uc774\ub984 wizard.multitracker.edit.save=\uc800\uc7a5 wizard.multitracker.edit.newgroup=\uc0c8 \ubb36\uc74c wizard.multitracker.edit.deletegroup=\uc9c0\uc6b0\uae30 wizard.multitracker.edit.newtracker=\uc0c8 \ub354\ub4ec\uc774 wizard.multitracker.edit.deletetracker=\uc9c0\uc6b0\uae30 wizard.multitracker.edit.edit=\ud3b8\uc9d1 wizard.addingmt=\uc5ec\ub7ec \ub354\ub4ec\uc774 \uc815\ubcf4 \ub354\ud558\uace0 \uc788\uc74c wizard.multitracker.noannounce=\ub354\ub4ec\uc774 \uc54c\ub9bc \uc8fc\uc18c(Announce URL)\uac00 \ub354\ub4ec\uc774 \ubaa9\ub85d\uc5d0 \uc788\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. MyTorrentsView.menu.recheck=\uc5b5\uc9c0\ub85c \ub2e4\uc2dc \uac80\uc0ac(&K) iconBar.showDownloadBar.tooltip=\ub0b4\ub824\ubc1b\uae30 \ub9c9\ub300 \ubcf4\uc774\uae30 iconBar.start.tooltip=\uc120\ud0dd\ud55c \ud1a0\ub7f0\ud2b8 \uc2dc\uc791 iconBar.stop.tooltip=\uc120\ud0dd\ud55c \ud1a0\ub7f0\ud2b8 \uba48\ucda4 iconBar.remove.tooltip=\uc9c0\uc6b0\uae30 iconBar.openNoDefault.tooltip=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c \uc5f4\uae30 (\uae30\ubcf8 \uc800\uc7a5 \uc5c6\uc74c) iconBar.openURL.tooltip=\uc8fc\uc18c \uc5f4\uae30 iconBar.openFolder.tooltip=\ud3f4\ub354 \uc5f4\uae30 iconBar.new.tooltip=\ud1a0\ub7f0\ud2b8 \ub9cc\ub4e4\uae30 iconBar.up.tooltip=\uc704\ub85c \uc62e\uae40 iconBar.down.tooltip=\uc544\ub798\ub85c \uc62e\uae40 iconBar.run.tooltip=\uc5f4\uae30 iconBar.host.tooltip=\ud638\uc2a4\ud2b8 iconBar.publish.tooltip=\ubc1c\ud589 iconBar.editcolumns.tooltip=\uc138\ub85c\uc904 \uc124\uc815 MyTorrentsView.menu.editTracker=\ub354\ub4ec\uc774 \uc8fc\uc18c \ud3b8\uc9d1(&E) GeneralView.menu.selectTracker=\uace0\ub974\uae30 ConfigView.section.stats.xslfile=XSL \ud30c\uc77c \uc774\ub984 ConfigView.section.stats.xslfiledetails=\uc774\uac83\uc740 \ud0dc\uadf8\ub97c \ud1b5\ud558\uc5ec\uc11c \ud1b5\uacc4 \ud30c\uc77c \ud5e4\ub354\uc5d0 \ub07c\uc6cc\uc9c8 \uac83\uc785\ub2c8\ub2e4. ConfigView.label.savetorrentbackup=\ubc31\uc5c5 \uc800\uc7a5 ConfigView.section.tracker.forceport=\uae30\ubcf8 \ud3ec\ud2b8\ub85c \uc678\ubd80 \ud1a0\ub7f0\ud2b8\ub97c \uc5b5\uc9c0\ub85c \ud638\uc2a4\ud2b8 ConfigView.section.ipfilter.allow=\uc774 \ubc94\uc704 \ud5c8\uc6a9 (\uae30\ubcf8\uac12\uc740 \uac70\ubd80) ConfigView.section.ipfilter.list.inrange=\ubc94\uc704 \uc548\uc5d0 \uc788\uc74c ConfigView.section.ipfilter.list.notinrange=\uc544\ubb34 \ubc94\uc704\uc5d0\ub3c4 \uc788\uc9c0 \uc54a\uc74c ConfigView.section.ipfilter.list.title=\ub9c9\uc740 IP \ubaa9\ub85d ConfigView.label.allowsameip=\uac19\uc740 IP\ub85c\ubd80\ud130\uc758 \ub2e4\uc218 \uc5f0\uacb0 \ud5c8\uc6a9 ConfigView.label.allowsameip.tooltip=\uc815\ub9d0 \ud544\uc694\ud560 \ub54c\ub9cc \uace0\ub974\uc2ed\uc2dc\uc694.\n(\uace0\ub974\uc9c0 \uc54a\uc558\uc744 \ub54c\ub294) \uc774\uac83\uc740 \uac70\uba38\ub9ac \ubc29\uc9c0\uc6a9 \uc785\ub2c8\ub2e4. ManagerItem.superseeding=\ub9ce\uc774 \ubfcc\ub9ac\uace0 \uc788\uc74c ConfigView.label.userSuperSeeding=\ub300\ub2e8\ud55c \ubfcc\ub9ac\uae30 \uc4f0\uae30 PeersView.uniquepiece=\uc870\uac01 (\ub9ce\uc774 \ubfcc\ub9ac\uae30 \ubc29\uc2dd) PeersView.uniquepiece.none=\uc5c6\uc74c PeersView.timetosend=\uc870\uac01\uc744 \ub2e4\uc2dc \ubcf4\ub0b4\ub294 \uc2dc\uac04 (\ub9ce\uc774 \ubfcc\ub9ac\uae30 \ubc29\uc2dd) ConfigView.section.style.addurlsilently=\uc7a0\uc790\ucf54 \uc9c0\ub098\uac04 \uc8fc\uc18c \uc5f4\uae30 ConfigView.section.style.addurlsilently.tooltip=\uba54\uc138\uc9c0 \uc0c1\uc790\ub97c \ubc14\ub85c \uc5f4\uc9c0 \uc54a\uace0\uc11c \uc9c0\ub098\uac00\uac70\ub098 \ub5a8\uc5b4\ub728\ub9b0 \ud1a0\ub7f0\ud2b8 \ud30c\uc77c \uc8fc\uc18c\ub4e4\uc744 \uc800\uc808\ub85c \ub0b4\ub824\ubc1b\uae30\ud569\ub2c8\ub2e4. ConfigView.section.file.decoder.prompt=\uc778\ucf54\ub529 \uace0\ub97c \uc77c\uc774 \uc0dd\uae30\uba74 \ub298 \uc0dd\uac01\ub098\uac8c \ud568 ConfigView.section.file.decoder.prompt.tooltip=\uc778\ucf54\ub529 \uace0\ub974\uae30\ub97c \uc4f8 \uc218 \uc788\uc744 \ub54c \uba54\uc138\uc9c0 \uc0c1\uc790\ub97c \ub298 \ubcf4\uc774\uae30 MyTorrentsView.menu.moveTop=\ub9e8 \uc704(&T) MyTorrentsView.menu.moveEnd=\ub9e8 \uc544\ub798(&B) ConfigView.label.moveonlyusingdefaultsave=\uae30\ubcf8 \ub370\uc774\ud130 \ud3f4\ub354\uc5d0 \uc788\uc744 \ub54c\ub9cc ConfigView.label.moveonlyusingdefaultsave.tooltip=\ub0b4\ub824\ubc1b\uae30 \uc790\ub8cc\uac00 \uae30\ubcf8 \ub370\uc774\ud130 \ud3f4\ub354\uc5d0 \uc788\uc744 \ub54c\ub9cc \uc62e\uae40 ConfigView.label.watchtorrentfolder=\uc0c8 \ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc744 \uc800\uc808\ub85c \ub4e4\uc5ec\uc624\uae30 ConfigView.label.watchtorrentfolder.tooltip=\uc0c8 \ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc744 \uc815\uae30\uc801\uc73c\ub85c \ucc3e\uc74c ConfigView.label.watchtorrentfolderinterval=\ud2c8 ConfigView.label.watchtorrentfolderinterval.tooltip=\ud3f4\ub354\ub97c \ub2e4\uc2dc \ud6d1\uc744 \ub54c\uae4c\uc9c0 \uc7a0\uc2dc \uba48\ucda4 ConfigView.dialog.choosewatchtorrentfolderpath=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc744 \ub4e4\uc5ec\uc62c \ud3f4\ub354\ub97c \uace0\ub974\uc2ed\uc2dc\uc694. ConfigView.label.startwatchedtorrentsstopped=\uba48\ucd98 \ucc44\ub85c \uc2dc\uc791 ConfigView.label.startwatchedtorrentsstopped.tooltip=\uba48\ucd98 \uc0c1\ud0dc\ub85c \uc0c8 \ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc744 \ub354\ud558\uae30 ConfigView.section.plugins=\ucd94\uac00\uae30\ub2a5 wizard.maketorrent.filesize=\ud30c\uc77c \ud06c\uae30 wizard.maketorrent.piececount=\uc870\uac01 \uc218 wizard.maketorrent.piecesize=\uc870\uac01 \ud06c\uae30 wizard.maketorrent.auto=\uc790\ub3d9 MainWindow.menu.view.stats=\ud1b5\uacc4(&S) MainWindow.menu.view.stats.keybinding=\uba54\ud0c0+5 SpeedView.title.full=\ud65c\ub3d9 SpeedView.downloadSpeed.title=\ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4 SpeedView.uploadSpeed.title=\uc62c\ub9ac\uae30 \uc18d\ub3c4 ConfigView.section.style.useSIUnits=\uad6d\uc81c \ud1b5\uc77c \ub2e8\uc704\uacc4 \ub2e8\uc704\ub97c \uc500 (KB -> KiB \ub4e4) iconBar.top.tooltip=\ub9e8 \uc704\ub85c \uc62e\uae40 iconBar.bottom.tooltip=\ub9e8 \uc544\ub798\ub85c \uc62e\uae40 TableColumn.header.health=\ud1a0\ub7f0\ud2b8 \uc0c1\ud0dc MyTorrentsView.menu.health=\ud1a0\ub7f0\ud2b8 \uc0c1\ud0dc \uc815\ubcf4 health.explain.grey=\ud1a0\ub7f0\ud2b8\uac00 \ub3cc\uc544\uac00\uace0 \uc788\uc9c0 \uc54a\ub294 \uac83\uc744 \ub73b\ud569\ub2c8\ub2e4.(\ub0b4\ub824\ubc1b\uae30 \ub610\ub294 \uc62c\ub9ac\uae30) health.explain.red=\ub0b4\ub824\ubc1b\uae30\ud558\uace0 \uc788\uc73c\uba74\uc11c \uc544\ubb34 \ub3d9\ub8cc\uc5d0\ub3c4 \uc5f0\uacb0\ub418\uc9c0 \uc54a\uc740 \uac83\uc744 \ub73b\ud569\ub2c8\ub2e4. health.explain.blue=\ubfcc\ub9ac\uace0 \uc788\uc73c\uba74 \uc544\uc9c1 \ud55c \ub3d9\ub8cc\uc5d0\ub3c4 \uc5f0\uacb0\ub418\uc9c0 \uc54a\uc740 \uac83\uc744 \ub73b\ud569\ub2c8\ub2e4.\n\ub0b4\ub824\ubc1b\uae30\ud558\uace0 \uc788\uc73c\uba74 \uba87\uba87 \ub3d9\ub8cc\ub4e4\uc5d0 \uc5f0\uacb0\ub418\uc5c8\uc9c0\ub9cc \ub354\ub4ec\uc774\uac00 \uace0\uc7a5\uc774 \ub09c \uac83\uc744 \ub73b\ud569\ub2c8\ub2e4. health.explain.yellow=\ub354\ub4ec\uc774\ub294 \uad1c\ucc2e\uace0 \ub3d9\ub8cc\ub4e4\uc5d0 \uc5f0\uacb0\ub418\uc5c8\uc9c0\ub9cc \uc544\ubb34 \uc6d0\uaca9 \uc5f0\uacb0\ub3c4 \uc5c6\ub294 \uac83\uc744 \ub73b\ud569\ub2c8\ub2e4.\n\ud1a0\ub7f0\ud2b8\uac00 \uc904\uace7 \ub178\ub780 \uc0c1\ud0dc\uc5d0 \uba38\ubb34\ub974\uace0 \uc788\uc73c\uba74 NAT \ubb38\uc81c\uc77c \uac83\uc785\ub2c8\ub2e4. health.explain.green=\ubaa8\ub450 \ud6cc\ub96d\ud558\uac8c \ub418\uace0 \uc788\ub294 \uac83\uc744 \ub73b\ud569\ub2c8\ub2e4. ConfigView.section.style.alwaysRefreshMyTorrents=\ub0b4 \ud1a0\ub7f0\ud2b8 \ub298 \uc0c8\ub85c \uace0\uce68 ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=\uc774 \uc120\ud0dd\uc0ac\ud56d\uc740 \ub098\ud0c0\ub098\uc9c0 \uc54a\ub354\ub77c\ub3c4 \ub0b4 \ud1a0\ub7f0\ud2b8 \ubcf4\uae30\ub97c \uc0c8\ub85c \uace0\uce60 \uac83\uc785\ub2c8\ub2e4. (mIRC \ucd94\uac00\uae30\ub2a5\uc5d0 \uc4f8\ubaa8 \uc788\uc74c) # #2.0.7.0 # security.certtruster.title=\ubcf4\uc548 \uc778\uc99d\uc11c \uacbd\uace0 security.certtruster.intro=\ubcf4\uc548 \uc778\uc99d\uc11c\uac00 \uc2e0\ub8b0\ub418\uc9c0 \uc54a\uc740 \uae30\uad00\uc5d0\uc11c \ubc1c\uae09\ub418\uc5c8\uc2b5\ub2c8\ub2e4. security.certtruster.resource=\uc790\uc6d0: security.certtruster.issuedto=\ubc1c\uae09 \ub300\uc0c1: security.certtruster.issuedby=\ubc1c\uae09\uc790: security.certtruster.prompt=\uc2e0\ub8b0\ud558\uaca0\uc2b5\ub2c8\uae4c? security.certtruster.yes=\uc608 security.certtruster.no=\uc544\ub2c8\uc624 ConfigView.section.tracker.torrentsperpage=\ud398\uc774\uc9c0\ub9c8\ub2e4 \ud1a0\ub7f0\ud2b8\uac00 \uc5bc\ub9c8\ub098 \uc788\uc2b5\ub2c8\uae4c? [0: \ubb34\uc81c\ud55c] MainWindow.menu.file.share=\uacf5\uc720(&S) MainWindow.menu.file.share.file=\ud30c\uc77c...(&F) MainWindow.menu.file.share.dir=\ud3f4\ub354...(&O) MainWindow.menu.file.share.dircontents=\ud3f4\ub354 \ub0b4\uc6a9...(&C) MainWindow.menu.file.share.dircontentsrecursive=\ud3f4\ub354 \ub0b4\uc6a9... (\ub418\ud480\uc774)(&R) MainWindow.dialog.share.sharefile=\uacf5\uc720\ud560 \ud30c\uc77c \uace0\ub974\uae30 MainWindow.dialog.share.sharedir=\uacf5\uc720\ud560 \ud3f4\ub354 \uace0\ub974\uae30 MainWindow.dialog.share.sharedircontents=\uacf5\uc720\ud560 \ud3f4\ub354 \ub0b4\uc6a9 \uace0\ub974\uae30 MainWindow.dialog.share.sharedircontents.recursive=\ub418\ud480\uc774 globalmanager.download.remove.veto=\uc9c0\uc6b0\uae30\uac00 \uac70\ubd80\ub428 plugin.sharing.download.remove.veto=\uc774 \ub0b4\ub824\ubc1b\uae30\ub294 \uacf5\uc720\ub418\uace0 \uc788\ub294 \uc790\uc6d0\uc758 \uacb0\uacfc\uc785\ub2c8\ub2e4.\n\ub0b4\ub824\ubc1b\uae30\ub97c \uc9c0\uc6b0\ub824\uba74 \uad00\uacc4\ub41c \uacf5\uc720\ub97c \uc9c0\uc6b0\uc2ed\uc2dc\uc694. ConfigView.section.tracker.main=\uc8fc\uc694 \ubd80\ubd84 ConfigView.section.tracker.web=\uc6f9 ConfigView.label.prioritizefirstpiece=\ud30c\uc77c \uccab \uc870\uac01\uc744 \uc6b0\uc120\uc2dc\ud0b4 ConfigView.label.prioritizefirstpiece.tooltip=\uc2dc\uc791\ud560 \ub54c \ud30c\uc77c\uc758 \ub9e8 \ucc98\uc74c\ubd80\ud130 \ub0b4\ub824\ubc1b\uae30\ud558\ub3c4\ub85d \ud569\ub2c8\ub2e4.\n\uc77c\ucc0c\uac10\uce58 \ubbf8\ub9ac\ubcf4\uae30\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. ConfigView.section.file.confirm_data_delete=\ub370\uc774\ud130\ub97c \uc9c0\uc6b8 \ub54c \ud655\uc778 ConfigView.section.file.confirm_data_delete.tooltip='\uc9c0\uc6b0\uace0 \ub098\uc11c \u2026\u2026 \uc9c0\uc6b0\uae30'\ud560 \ub54c \ub370\uc774\ud130 \uc9c0\uc6b0\uae30 \ud655\uc778 TrayWindow.menu.startalldownloads=\ubaa8\ub4e0\ub0b4\ub824\ubc1b\uae30 \uc2dc\uc791 SystemTray.menu.startalltransfers=\ubaa8\ub4e0 \uc804\uc1a1 \uc2dc\uc791 sharing.progress.title=\uacf5\uc720 \uc9c4\ud589 sharing.progress.hide=\uc228\uae40 MainWindow.menu.view.myshares=\ub0b4 \uacf5\uc720 MainWindow.menu.view.myshares.keybinding=\uba54\ud0c0+3 MySharesView.title.full=\ub0b4 \uacf5\uc720 MySharesView.name=\ud30c\uc77c \uc774\ub984 MySharesView.type=\uc591\uc2dd MySharesView.type.file=\ud30c\uc77c MySharesView.type.dir=\ud3f4\ub354 MySharesView.type.dircontents=\ud3f4\ub354 \ub0b4\uc6a9 MySharesView.type.dircontentsrecursive=\ud3f4\ub354 \ub0b4\uc6a9 (\ub418\ud480\uc774) MySharesView.menu.remove=\uc9c0\uc6b0\uae30 ConfigView.section.tracker.extensions=\ud655\uc7a5\uc790 ConfigView.section.tracker.sendpeerids=\ub3d9\ub8cc \uc2e0\uc6d0\uc744 \ub0b4\ub824\ubc1b\uae30 \ud504\ub85c\uadf8\ub7a8\uc73c\ub85c \ubcf4\ub0c4 ConfigView.section.tracker.enableudp=UDP \ub354\ub4ec\uc774 \ud504\ub85c\ud1a0\ucf5c \uc791\ub3d9 plugin.sharing.torrent.remove.veto=\uc774 \ub354\ub4ec\uc774 \ub4f1\ub85d\uc740 \uacf5\uc720\ub418\uace0 \uc788\ub294 \uc790\uc6d0\uc758 \uacb0\uacfc\uc785\ub2c8\ub2e4.\n\ub0b4\ub824\ubc1b\uae30\ub97c \uc9c0\uc6b0\ub824\uba74 \uad00\uacc4\ub41c \uacf5\uc720\ub97c \uc9c0\uc6b0\uc2ed\uc2dc\uc694. plugin.download.remove.veto.notstopped=\ub0b4\ub824\ubc1b\uae30\uac00 \uba48\ucd94\uc9c0 \uc54a\uc558\uc73c\ubbc0\ub85c \uc9c0\uc6b8 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. plugin.sharing.remove.veto=\uc774 \uacf5\uc720\ub294 '\ud3f4\ub354 \ub0b4\uc6a9' \uacf5\uc720\uc5d0 \ubc84\uae08\uac00\ub294 \uacf5\uc720\ub85c\uc11c \ub4dc\ub7ec\ub0b8 \ucc44\ub85c \uc9c0\uc6cc\uc9c8 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\n \ubfcc\ub9ac\uac00 \ub418\ub294 \uacf5\uc720\ub97c \uc9c0\uc6b0\uc2ed\uc2dc\uc694. GeneralView.label.hash.tooltip=\ud074\ub9bd\ubcf4\ub4dc\uc5d0 \ud574\uc2dc\ub97c \ubcf5\uc0ac\ud558\ub824\uba74 \ud074\ub9ad ConfigView.section.tracker.maxpeersreturned=\ub3cc\ub824 \ubcf4\ub0b4\uc9c4 \ucd5c\ub300 \ub3d9\ub8cc \uc218 [0: \ubb34\uc81c\ud55c] ConfigView.label.serverport=\ub4e4\uc5b4\uc624\ub294 TCP \ub4e3\uae30 \ud3ec\ud2b8 ConfigView.label.serverport.tooltip=\ud3ec\ud2b8\ub294 \ubc18\ub4dc\uc2dc 1-65535\uc758 \ubc94\uc704 \uc548\uc5d0 \uc788\uc5b4\uc57c \ud558\uace0, 6880 \ud3ec\ud2b8\ub294 Vuze \uc548\uc5d0\uc11c \uc4f0\ub824\uace0 \ub0a8\uaca8 \ub461\ub2c8\ub2e4. configureWizard.nat.server.tcp_listen_port=\ub4e4\uc5b4\uc624\ub294 TCP \ub4e3\uae30 \ud3ec\ud2b8 ConfigView.section.sharing=\uacf5\uc720 ConfigView.section.sharing.usessl=\uacf5\uc720\ub41c \uc790\uc6d0\uc5d0 SSL \uc0ac\uc6a9 (\ub354\ub4ec\uc774 \uad6c\uc131\uc774 \ud544\uc694\ud568) ConfigView.section.style.dropdiraction=\ud3f4\ub354\uc5d0 \ub04c\uc5b4\ub2e4\uac00 \ub193\uae30 ConfigView.section.style.dropdiraction.opentorrents=\ud1a0\ub7f0\ud2b8 \uc5f4\uae30 ConfigView.section.style.dropdiraction.sharefolder=\ud3f4\ub354 \uacf5\uc720 ConfigView.section.style.dropdiraction.sharefoldercontents=\ub0b4\uc6a9 \uacf5\uc720 # # 2.0.7.x # Categories.all=\ubaa8\ub450 Categories.uncategorized=\ubd84\ub958\ub418\uc9c0 \uc54a\uc74c CategoryAddWindow.message=\uc0c8 \ubd84\ub958 \uc774\ub984\uc744 \uc368\ub123\uc73c\uc2ed\uc2dc\uc694 CategoryAddWindow.title=\uc0c8 \ubd84\ub958 \ucd94\uac00\ud558\uae30 ConfigView.label.autoSeedingIgnoreInfo=\ubb34\uc2dc\ub41c \ud1a0\ub7f0\ud2b8\ub4e4\uc740 \ubfcc\ub9ac\ub294 \ucc28\ub840\uc758 \ubc11\uc73c\ub85c \uac11\ub2c8\ub2e4. \uc790\ub3d9\uc73c\ub85c \uc2dc\uc791\ub418\uc9c0\ub294 \uc54a\uc2b5\ub2c8\ub2e4.\n\ubb34\uc2dc \uaddc\uce59\ub4e4\uc740 \uccab\ubc88\uc9f8 \uc6b0\uc120\uad8c \uae30\uc900\uc5d0 \ub9de\ub294 \ud1a0\ub7f0\ud2b8\ub4e4\uc5d0 \uc801\uc6a9\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.\n\ub2ec\ub9ac \uc815\ud574\uc9c0\uc9c0 \uc54a\uc558\uc73c\uba74, 0 \uac12\uc744 \uc368\uc11c \uaddc\uce59\uc744 \uc4f8\ubaa8 \uc5c6\uac8c \ud558\uc2ed\uc2dc\uc694. ConfigView.label.directory=\ud3f4\ub354 ConfigView.label.disconnetseed.tooltip=\ud1a0\ub7f0\ud2b8\ub97c \ubfcc\ub9b4 \ub54c, \ub9c8\ucc2c\uac00\uc9c0\ub85c \ubfcc\ub9ac\uace0 \uc788\ub294 \uc811\uc18d \ucef4\ud4e8\ud130\ub97c \ub04a\uc2b5\ub2c8\ub2e4.\n\uadf8\ub4e4\uc774 \ub2f9\uc2e0\uacfc \ud1b5\uc2e0\ud560 \ud544\uc694\ub3c4 \uc5c6\uc2b5\ub2c8\ub2e4. ConfigView.label.ignoreCase=\ub300\uc18c\ubb38\uc790 \ubb34\uc2dc ConfigView.label.ignoreSeeds=\uc801\uc5b4\ub3c4 \ub2e4\uc74c\ub9cc\ud07c \uc788\ub294 \ud1a0\ub7f0\ud2b8\ub97c \ubb34\uc2dc ConfigView.label.importdirectory=\ud3f4\ub354 \ub4e4\uc5ec\uc624\uae30 ConfigView.label.minPeersToBoostNoSeeds.tooltip=\ubfcc\ub9ac\uae30\uac00 \uc5c6\uac70\ub098 \ud544\uc694\ud55c \uc778\uc6d0\ubcf4\ub2e4 \uc801\uc740 \ud1a0\ub7f0\ud2b8\ub294 \ucc28\ub840\uc758 \ub05d\uc5d0 \ub193\uc785\ub2c8\ub2e4. ConfigView.label.minPeersToBoostNoSeeds=\ubfcc\ub9ac\uae30\uac00 \uc5c6\uac70\ub098 \uadf8\uc640 \ube44\uc2b7\ud55c \ud1a0\ub7f0\ud2b8\uc758 \ubfcc\ub9ac\uae30 \uc21c\uc704 \ub0ae\ucda4 ConfigView.label.minSeedingTime.tooltip=\ubfcc\ub9ac\uae30 \uc21c\uc704\ub294 \uc9e7\uc740 \uc2dc\uac04\uc5d0 \uc790\uc8fc \uc624\ub974\ub0b4\ub9b4 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc774\ub85c \uc778\ud574 \uc774\ub530\uae08 \ud1a0\ub7f0\ud2b8\uac00 \uc800\uc808\ub85c \uc2dc\uc791\ud558\uace0\uc11c \ubc14\ub85c \ub2e4\uc74c\uc5d0 \uba48\ucd94\uace0 \ub300\uae30\ud558\uae30\ub3c4 \ud569\ub2c8\ub2e4.\n\uc774 \ubb38\uc81c\ub294 \ud1a0\ub7f0\ud2b8\uac00 \uc8fc\uc5b4\uc9c4 \uc2dc\uac04 \ub3d9\uc548 \ubfcc\ub9ac\ub294 \ucc44\ub85c \uc788\ub3c4\ub85d \ud574\uc11c \ud489\ub2c8\ub2e4. \uc5b8\uc81c\ub4e0\uc9c0 \uc9c1\uc811 \uba48\ucd9c \uc218 \uc788\uc2b5\ub2c8\ub2e4. ConfigView.label.minSeedingTime=\ucd5c\uc18c \ubfcc\ub9ac\uae30 \uc2dc\uac04 (\ucd08) ConfigView.label.minSpeedForActiveDL.tooltip=\ub05d\ub9c8\uce58\uc9c0 \ubabb\ud55c \ud1a0\ub7f0\ud2b8\uac00 \uc2dc\uc791\ud558\uace0\uc11c \ucc98\uc74c 30\ucd08 \ub3d9\uc548\n\ub0b4\ub824\ubc1b\uae30 \uc790\ub9ac\uac00 \ub298 \uc4f0\uc785\ub2c8\ub2e4. ConfigView.label.minSpeedForActiveDL=\uc18d\ub3c4\uac00 \uc774\ubcf4\ub2e4 \ub5a8\uc5b4\uc9c0\uba74 \ub0b4\ub824\ubc1b\uae30 \uc790\ub9ac\ub97c \uc4f0\uace0 \uc788\ub294 \ud1a0\ub7f0\ud2b8\ub97c \uc138\uc9c0 \uc54a\uc74c ConfigView.label.peers=\ub3d9\ub8cc ConfigView.label.queue.debuglog=\ub514\ubc84\uadf8 \uc815\ubcf4 \ub85c\uadf8 ConfigView.label.queue.debuglog.info=\ucf58\uc194/\ub85c\uadf8 \ud30c\uc77c\uc5d0 \ub300\uae30 \ub514\ubc84\uadf8 \uc815\ubcf4\ub97c \ub354\ud569\ub2c8\ub2e4.\n\uc554\ud638\ubb38\uc774\uc9c0\ub9cc, \ub514\ubc84\uadf8 \uc815\ubcf4\ub294 \ud1a0\ub7f0\ud2b8\uc758 \uc0c1\ud0dc\uc640 \uadf8\uac83\ub4e4\uc774 \uc2dc\uc791/\ub300\uae30\ud558\uac70\ub098 \ud558\uc9c0 \uc54a\ub294 \uc774\uc720\ub97c \uc54c\ub824 \uc90d\ub2c8\ub2e4. ConfigView.label.queue.minQueueingShareRatio=\ud1a0\ub7f0\ud2b8\uc758 \uacf5\uc720 \ube44\uac00 \ub2e4\uc74c\uc5d0 \uc774\ub97c \ub54c\uae4c\uc9c0 \ud1a0\ub7f0\ud2b8\ub97c \ub300\uae30\ud558\uac70\ub098 \uba48\ucd94\uc9c0 \uc54a\uc74c ConfigView.label.ratio=\ube44 ConfigView.label.removeOnStop=\ud1a0\ub7f0\ud2b8\uac00 \uc800\uc808\ub85c \uba48\ucd94\uace0 \ub098\uc11c \ubaa9\ub85d\uc5d0\uc11c \ud1a0\ub7f0\ud2b8 \uc9c0\uc6b0\uae30 ConfigView.label.savedirectory=\ud3f4\ub354 \uc800\uc7a5 ConfigView.label.seeding.autoReposition.tooltip=\uc791\ub3d9\uc2dc\ud0a4\uba74 \ud1a0\ub7f0\ud2b8\uc758 \uc21c\uc11c('\ubc88\ud638' \uc138\ub85c\uc904)\uac00 \ubfcc\ub9ac\uae30 \uc21c\uc704\uc5d0 \ub9de\ucd94\uc5b4\uc11c \ubc14\ub014 \uac83\uc785\ub2c8\ub2e4.\n\ub2f9\uc2e0\uc774 \ubfcc\ub9ac\uae30 \uc21c\uc704 \uc22b\uc790\ub97c \ubcf4\uace0 \uc2f6\uc9c0 \uc54a\uc73c\ub098, \uadf8\ub798\ub3c4 \ub05d\ub9c8\uce5c \ud1a0\ub7f0\ud2b8\uac00 \uc2dc\uc791\ud560 \uc21c\uc11c\ub97c \uc54c\uace0 \uc2f6\uc744 \ub54c \uc4f8\ubaa8 \uc788\uc2b5\ub2c8\ub2e4. ConfigView.label.seeding.autoReposition=\ubfcc\ub9ac\uae30 \uc21c\uc704\uc5d0 \ub530\ub77c \ud1a0\ub7f0\ud2b8\uc758 \uc790\ub9ac\ub97c \uc800\uc808\ub85c \ubc14\uafc8 ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\uac00\ub054 \ub0ae\uc740 \uc528\uc557 \uc218\uc640 \ub192\uc740 \ub3d9\ub8cc \uc218\uc778 \ud1a0\ub7f0\ud2b8\ub294 \uc544\ub9c8 \ub3d9\ub8cc\ub4e4 \uc911\uc5d0\uc11c \uc644\uc804\ubcf8\uc774 \uc5c6\ub2e4\ub294 \uac83\uc744 \ub73b\ud569\ub2c8\ub2e4.\n\uadf8\ub7ec\ubbc0\ub85c \uc544\ub9c8 \uc644\uc804\ubcf8\uc774 \uc788\ub294 \uac83\ucc98\ub7fc \uad74\uc5b4\uc11c (\uadf8 \uc21c\uc704\ub97c \ubc14\ub974\uc9c0 \uc54a\uac8c \ub0b4\ub9ac\ub294) \ubfcc\ub9ac\uae30 \uaddc\uce59\uc744 \ubc14\ub77c\uc9c0 \uc54a\uc744 \uac83\uc785\ub2c8\ub2e4. ConfigView.label.seeding.fakeFullCopySeedStart=\uadf8\ub807\uc9c0\ub9cc \uc801\uc5b4\ub3c4 \ub2e4\uc74c\ub9cc\ud07c \uc788\ub294 \ud1a0\ub7f0\ud2b8\uc5d0\ub9cc ConfigView.label.seeding.ignore=\uaddc\uce59 \ubb34\uc2dc ConfigView.label.seeding.ignore0Peers=0 \ub3d9\ub8cc\uc778 \ud1a0\ub7f0\ud2b8 \ubb34\uc2dc ConfigView.label.seeding.ignoreRatioPeers=\uc801\uc5b4\ub3c4 \ub2e4\uc74c\ub9c8\ub2e4 1 \uc528\uc557\uc774 \uc788\ub294 \ud1a0\ub7f0\ud2b8 \ubb34\uc2dc ConfigView.label.seeding.ignoreShareRatio=\ub2e4\uc74c\uacfc \uac19\uc740 \uacf5\uc720 \ube44\uc778 \ud1a0\ub7f0\ud2b8 \ubb34\uc2dc ConfigView.label.seeding.ignore.header.evenFirstPriority=\uccab\ubc88\uc9f8 \uc6b0\uad8c\uc120 \uaddc\uce59\uc5d0 \ub9de\ub354\ub77c\ub3c4\n\ud1a0\ub7f0\ud2b8\ub97c \ubb34\uc2dc\ud569\ub2c8\ub2e4. ConfigView.label.seeding.ignore.header.rule=\uaddc\uce59 ConfigView.label.seeding.ignore.header.value=\uac12 ConfigView.label.seeding.firstPriority.info=\uccab\ubc88\uc9f8 \uc6b0\uc120\uad8c \ud1a0\ub7f0\ud2b8\ub294 \ub298 \ub300\uae30\uc21c\uc11c\uc758 \ub9e8 \uc704\uc5d0 \uc788\uc744 \uac83\uc785\ub2c8\ub2e4. \uccab\ubc88\uc9f8 \uc6b0\uc120\uad8c \uae30\uc900\uc5d0 \ub9de\ub294 \ud1a0\ub7f0\ud2b8\ub294 \uc5b4\ub5a4 \uac83\uc774\ub77c\ub3c4 \uc800\uc808\ub85c \uba48\ucd94\uac70\ub098 \ub300\uae30\ud558\uc9c0 \uc54a\uc744 \uac83\uc785\ub2c8\ub2e4. \uccab\ubc88\uc9f8 \uc6b0\uc120\uad8c \uae30\uc900\uc5d0 \ub9de\ub294 \ud1a0\ub7f0\ud2b8\ub294 \ud544\uc694\ud558\ub2e4\uba74 \ub3d9\uc2dc \ub0b4\ub824\ubc1b\uae30 \uc790\ub9ac\ub97c \ucc28\uc9c0\ud560 \uac83\uc785\ub2c8\ub2e4. ConfigView.label.seeding.firstPriority.FP=\uccab\ubc88\uc9f8 \uc6b0\uc120\uad8c ConfigView.label.seeding.firstPriority=\uccab\ubc88\uc9f8 \uc6b0\uc120\uad8c\uc774 \ub2e4\uc74c \uac00\uc6b4\ub370 ConfigView.label.seeding.firstPriority.following=\u3000\uc788\ub294 \ud1a0\ub7f0\ud2b8\uc5d0 \ubbf8\uce5c\ub2e4: ConfigView.label.seeding.firstPriority.shareRatio=\ub2e4\uc74c\ubcf4\ub2e4 \ubabb\ud55c \uacf5\uc720 \ube44 ConfigView.label.seeding.firstPriority.seedingMinutes=\ub0b4\ub824\ubc1b\uae30\uc5d0\uc11c \ubfcc\ub9ac\uae30\ub85c \ubc14\ub00c\uace0\ub098\uc11c \uc9c0\ub09c \uc2dc\uac04 ConfigView.label.seeding.firstPriority.DLMinutes=\ub0b4\ub824\ubc1b\uae30\ub97c \uc2dc\uc791\ud558\uace0\uc11c \uc9c0\ub09c \uc2dc\uac04 ConfigView.label.seeding.numPeersAsFullCopy.tooltip=X \ub3d9\ub8cc\ub9c8\ub2e4 1 \uc644\uc804\ubcf8\uc774 \uc788\ub294 \uccb4\ud558\uc5ec\uc11c, \ub2f9\uc2e0\uc740 \ub192\uc740 \ub3d9\ub8cc \uc218\uac00 \uc788\ub294 \ud1a0\ub7f0\ud2b8\uc758 \uc21c\uc704\ub97c \ub0ae\ucda5\ub2c8\ub2e4.\n\uc544\ub9c8 \ub192\uc740 \ub3d9\ub8cc \uc218\uac00 \uc788\ub294 \ud1a0\ub7f0\ud2b8\ub294 \ub192\uc740 \uc804\uc1a1\ub7c9\ub3c4 \uc788\uc744 \uac83\uc785\ub2c8\ub2e4.\n\uc774\uac83\uc740 \uc5b4\ub5a4 '\uc528\uc557\uc758 \uc218' \ub514\uc2a4\ud50c\ub808\uc774\ub3c4 \ubc14\uafb8\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. ConfigView.label.seeding.numPeersAsFullCopy=\ub2e4\uc74c\ub9c8\ub2e4 1 \uc644\uc804\ubcf8\uc774 \uc788\ub294 \uccb4\ud568\n(0: \uc18d\uc774\uc9c0 \uc54a\uc74c) ConfigView.label.seeding.preferLargerSwarms.tooltip=\ub3d9\ub8cc\ub4e4\uc774 \ubd99\uc5b4 \uc788\ub294 \ud1a0\ub7f0\ud2b8\ub97c \uc8fc\ub85c \ubfcc\ub9b4 \ub54c\ub294 \ub354 \ud070 \ub5bc\ub97c \uace0\ub974\ub294 \uac83\uc774 \ub2f9\uc5f0\ud569\ub2c8\ub2e4.\n\ucda9\ubd84\ud788 \uc5bb\uc744 \uc218 \uc788\ub294 \ud1a0\ub7f0\ud2b8\ub97c \uc8fc\ub85c \ubfcc\ub9b4 \ub54c\ub294 \ub354 \uc791\uc740 \ub5bc\ub97c \uace0\ub974\ub294 \uac83\uc774 \ub2f9\uc5f0\ud569\ub2c8\ub2e4. ConfigView.label.seeding.preferLargerSwarms=\ud1a0\ub7f0\ud2b8\ub4e4\uc774 \uac19\uc740 \uc21c\uc704\uc774\uba74 \ub354 \ub9ce\uc740 \ub5bc\ub97c \uace0\ub985\ub2c8\ub2e4. ConfigView.label.seeding.rankType.none.tooltip=\ubc88\ud638 \uc138\ub85c\uc904\uc5d0 \ub530\ub77c\uc11c \uc7a1\uc74c ConfigView.label.seeding.rankType.none=\uc544\ubb34 \uac83\ub3c4 \uc5c6\uc74c ConfigView.label.seeding.rankType.peerSeed.options=\uc528\uc557:\ub3d9\ub8cc \ube44\uc758 \uc120\ud0dd\uc0ac\ud56d ConfigView.label.seeding.rankType.peerSeed.tooltip=\ub192\uc740 \ube44 = \ub192\uc740 \uc21c\uc704 ConfigView.label.seeding.rankType.peerSeed=\ub3d9\ub8cc:\uc528\uc557 \ube44 ConfigView.label.seeding.rankType.seed.fallback=\ub2e4\uc74c\ubcf4\ub2e4 \uc801\uc73c\uba74 \ub3d9\ub8cc:\uc528\uc557 \ube44\ub85c \ub300\ube44\n(0: \ub300\ube44\ud558\uc9c0 \uc54a\uc74c) ConfigView.label.seeding.rankType.seed.options=\uc528\uc557 \uc218\ub9cc\uc758 \uc120\ud0dd\uc0ac\ud56d ConfigView.label.seeding.rankType.seed.tooltip=\uc801\uc740 \uc528\uc557 = \ub192\uc740 \uc21c\uc704 ConfigView.label.seeding.rankType.seed=\uc528\uc557 \uc218\ub9cc ConfigView.label.seeding.rankType.timedRotation.tooltip=\ub300\uae30\ud558\ub294 \ubaa8\ub4e0 \ub05d\ub9c8\uce5c \ud1a0\ub7f0\ud2b8\ub294 \ubfcc\ub9ac\uae30 \ubc29\uc2dd\uc5d0\uc11c \ubc88\uac08\uc544 \ubc14\ub014 \uac83\uc785\ub2c8\ub2e4.\n\uc774\uc5b4\uc9c0\ub294 \ubfcc\ub9ac\uae30 \uc2dc\uac04\uc740 '\ucd5c\uc18c \ubfcc\ub9ac\uae30 \uc2dc\uac04'\uc73c\ub85c \uc7a1\uc2b5\ub2c8\ub2e4. ConfigView.label.seeding.rankType.timedRotation=\uc815\uae30\uc801\uc778 \ubc88\uac08\uc544 \ubc14\uafc8 ConfigView.label.seeding.rankType.tooltip=\uac00\uc7a5 \ub192\uac8c \ub9e4\uaca8\uc9c4 \ud1a0\ub7f0\ud2b8\ub294 \uc800\uc808\ub85c \uc2dc\uc791\ud569\ub2c8\ub2e4.\n\ub2e4\ub978 \ud1a0\ub7f0\ud2b8\uac00 \ub354 \ub192\uac8c \ub9e4\uaca8\uc9c0\uba74, \ub0ae\uac8c \ub9e4\uaca8\uc9c4 \uac83\uc740 \uba48\ucd94\uace0 \ub300\uae30\ub85c \ub3cc\uc544\uac11\ub2c8\ub2e4.\n\n\ub300\uae30 \uc0c1\ud0dc\uc758 \ud1a0\ub7f0\ud2b8\ub9cc \uc800\uc808\ub85c \uc2dc\uc791\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n\uba48\ucd98 \ud1a0\ub7f0\ud2b8\ub294 \uacb0\ucf54 \uc800\uc808\ub85c \uc2dc\uc791\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. ConfigView.label.seeding.rankType=\ub2e4\uc74c\uc5d0 \ub530\ub77c\uc11c \uc800\uc808\ub85c \uc2dc\uc791\ud560 \ub05d\ub9c8\uce5c \ud1a0\ub7f0\ud2b8\uc758 \ucc28\ub840\ub97c \ub9e4\uae41\ub2c8\ub2e4: ConfigView.label.stopAfterMinutes=\ud55c\ubc88 \ubfcc\ub9ac\uae30\ub85c \ubc14\ub00c\uba74, \uc774\uc5b4\uc9c4 \uc2dc\uac04 \ud6c4\uc5d0 \uba48\ucda4 ConfigView.label.switchpriority.tooltip=\ub0ae\uc740 \uc6b0\uc120\uad8c\uc740 \ud1a0\ub7f0\ud2b8\uc5d0 \ud560\ub2f9\ud558\ub294 \uc62c\ub9ac\uae30 \ub300\uc5ed\ud3ed\uc758 \uc591\uc744 \uc904\uc785\ub2c8\ub2e4. ConfigView.pluginlist.info=\ub2e4\uc74c \ucd94\uac00\uae30\ub2a5\uc774 \ud655\uc778\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \uba87\uba87 \ucd94\uac00\uae30\ub2a5\uc740 \uad6c\uc131 \ud0ed\uc774 \uc5c6\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4. ConfigView.pluginlist.noplugins=\uc544\ubb34 \ucd94\uac00\uae30\ub2a5\ub3c4 \ucc3e\uc9c0 \ubabb\ud558\uc600\uc2b5\ub2c8\ub2e4. ConfigView.section.pluginslist=\ubaa9\ub85d ConfigView.section.queue.seeding=\ubfcc\ub9ac\uae30 ConfigView.section.queue.seeding.autoStarting=\uc800\uc808\ub85c \uc2dc\uc791 ConfigView.section.queue.seeding.ignore=\uaddc\uce59 \ubb34\uc2dc ConfigView.section.queue.seeding.firstPriority=\uccab\ubc88\uc9f8 \uc6b0\uc120\uad8c ConfigView.section.queue.main=\uc8fc\uc694 \ubd80\ubd84 ConfigView.section.queue=\ub300\uae30 ConfigView.section.torrents=\ud1a0\ub7f0\ud2b8 ConfigView.text.all=\ubaa8\ub450 ConfigView.text.hours=\uc2dc\uac04 ConfigView.text.ignoreRule=\ubb34\uc2dc \uaddc\uce59 ConfigView.text.ignore=\ubb34\uc2dc ConfigView.text.minutes=\ubd84 ConfigView.text.neverIgnore=\uacb0\ucf54 \ubb34\uc2dc\ud558\uc9c0 \uc54a\uc74c ConfigView.text.any=\ubb34\uc5c7\uc774\ub4e0\uc9c0 DownloadManager.error.datamissing=\ub370\uc774\ud130\uac00 \uc5c6\uc5b4\uc9d0 MainWindow.menu.file.open.torrentforseeding=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c... (\ubfcc\ub9ac\uae30\uc5d0 \uc500) MainWindow.menu.language.refresh=\uc0c8\ub85c \uace0\uce68(&R) ManagerItem.forced=\uc5b5\uc9c0\ub85c ManagerItem.queued=\ub300\uae30 MySeedersView.header=\ub05d\ub9c8\uce5c \ud1a0\ub7f0\ud2b8 TableColumn.header.availability.info=\uc644\uc804\ubcf8 \uba87 \uac1c\uac00 \ubcf4\uc784 TableColumn.header.availability=\uc4f8 \uc218 \uc788\uc74c TableColumn.header.category=\ubd84\ub958 MyTorrentsView.header=\ub05d\ub9c8\uce58\uc9c0 \ubabb\ud55c \ud1a0\ub7f0\ud2b8 TableColumn.header.maxuploads=\ucd5c\uace0 \uc62c\ub9ac\uae30 \uc218 MyTorrentsView.menu.category.delete=\ubd84\ub958 \uc9c0\uc6b0\uae30(&D) MyTorrentsView.menu.forceStart=\uc5b5\uc9c0\ub85c \uc2dc\uc791(&F) MyTorrentsView.menu.queue=\ub300\uae30(&Q) MyTorrentsView.menu.setCategory.add=\ubd84\ub958 \ub354\ud558\uae30...(&A) MyTorrentsView.menu.setCategory=\ubd84\ub958 \uc815\ud558\uae30 TableColumn.header.savepath=\uc800\uc7a5 \uc704\uce58 TableColumn.header.SeedingRank=\ubfcc\ub9ac\uae30 \uc21c\uc704 TableColumn.header.totalspeed.info=\ub2f9\uc2e0\uacfc \uc5f0\uacb0\ub41c \ubaa8\ub4e0 \ub3d9\ub8cc\ub4e4\uc758 \ucd1d \uc18d\ub3c4 TableColumn.header.totalspeed=\ucd1d \uc18d\ub3c4 splash.initializePlugins=\ucd94\uac00\uae30\ub2a5\uc744 \ucd08\uae30\uac12\uc5d0 \ub9de\ucd94\uace0 \uc788\uc74c StartStopRules.SPratioMet=\uc528\uc557:\ub3d9\ub8cc \ube44 \uc88b\uc74c StartStopRules.FP0Peers=FP / 0 \ub3d9\ub8cc StartStopRules.0Peers=0 \ub3d9\ub8cc StartStopRules.numSeedsMet=\uc528\uc557 \uc218 \uc88b\uc2b5\ub2c8\ub2e4 StartStopRules.ratioMet=\ub3d9\ub8cc:\uc528\uc557 \uc88b\uc2b5\ub2c8\ub2e4 StartStopRules.shareRatioMet=\uacf5\uc720 \ube44 \uc88b\uc2b5\ub2c8\ub2e4 StartStopRules.waiting=\uae30\ub2e4\ub9ac\uace0 \uc788\uc74c StartStopRules.firstPriority=\uccab\ubc88\uc9f8 \uc6b0\uc120\uad8c ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\ub0b4\uc6a9 \uacf5\uc720 (\ub418\ud480\uc774) DownloadManager.error.unabletostartserver=\uc11c\ubc84\ub97c \uc2dc\uc791\ud560 \uc218 \uc5c6\uc74c - \ub4e4\uc5b4\uc624\ub294 \ud3ec\ud2b8 \uad6c\uc131\uacfc \uc11c\ubc84\ub85c \uc791\ub3d9\ud558\ub294 \ud504\ub85c\uadf8\ub7a8\uc5d0 \ubc29\ud654\ubcbd \ud5c8\uc6a9 \uac80\uc0ac GeneralView.label.creationdate=\ub9cc\ub4e4\uc5b4\uc9c4 \uc2dc\uac01: ConfigView.section.tracker.announcescrapepercentage=\uc54c\ub9ac\uae30\uc758 %age\uc5d0 \ub530\ub978 \ubaa8\uc73c\uae30 \uac04\uaca9\n\uc608 200 = 2:1. 0 = \ub3d9\ub8cc\uac00 \uc815\ud558\ub3c4\ub85d \ud568 ManagerItem.stopping=\uba48\ucd94\uace0 \uc788\uc74c ConfigView.section.tracker.announcecacheperiod=\uc54c\ub9bc \uce90\uc2dc (\ubc00\ub9ac\ucd08) ConfigView.section.tracker.scrapecacheperiod=\ubaa8\uc73c\uae30 \uce90\uc2dc (\ubc00\ub9ac\ucd08) ConfigView.section.tracker.scrapeandcache=\ubaa8\uc73c\uae30\uc640 \uce90\uc2dc ConfigView.section.tracker.announcecacheminpeers=\uc54c\ub9bc \uce90\uc2dc\uac00 \uc791\ub3d9\ud558\ub294 \ub3d9\ub8cc \uacbd\uacc4 MyTrackerView.scrapes=\ubaa8\uc740 \uac83 fileDownloadWindow.retry=\ub2e4\uc2dc \ud574 \ubd04 MyTrackerView.bytesin=\ub4e4\uc5b4\uc628 \ubc14\uc774\ud2b8 MyTrackerView.bytesinave=\ub4e4\uc5b4\uc628 \ud3c9\uade0 MyTrackerView.bytesout=\ub098\uac04 \ubc14\uc774\ud2b8 MyTrackerView.bytesoutave=\ub098\uac04 \ud3c9\uade0 ConfigView.section.file.max_open_files=\uc77d\uae30/\uc4f0\uae30\ub97c \ud558\ub824\uace0 \uc5ec\ub294 \ucd5c\ub300 \ud30c\uc77c \uc218\n[0: \ubb34\uc81c\ud55c] ConfigView.section.file.max_open_files.tooltip=\ub2f9\uc2e0\uc774 \uc218\ubc31 \uc218\ucc9c \uac1c\uc758 \ud30c\uc77c\ub85c \ub41c \ud1a0\ub7f0\ud2b8\ub97c \ub0b4\ub824\ubc1b\uac70\ub098, OS\uc758 \ud30c\uc77c \ub2e4\ub8e8\uae30 \ud55c\uacc4(FAT\uc758 2\uae30\uac00 \ud55c\uacc4\ub4f1)\uc5d0 \ub2e4\ub2e4\ub974\uba74 \uc4f8\ubaa8 \uc788\uc2b5\ub2c8\ub2e4. ConfigView.section.proxy=\ud504\ub85d\uc2dc \uc120\ud0dd\uc0ac\ud56d ConfigView.section.proxy.enable_proxy=\ub354\ub4ec\uc774 \ud1b5\uc2e0 \ud504\ub85d\uc2dc \uc791\ub3d9 [\ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud568] ConfigView.section.proxy.host=\ud638\uc2a4\ud2b8 ConfigView.section.proxy.port=\ud3ec\ud2b8 ConfigView.section.proxy.username=\uc0ac\uc6a9\uc790 \uc774\ub984 ConfigView.section.proxy.password=\uc554\ud638 ConfigView.section.proxy.enable_socks=SOCKS \ud504\ub85d\uc2dc\uac00 \uc788\uc2b5\ub2c8\ub2e4. wizard.createtorrent.extrahashes=\ub2e4\ub978 \ub124\ud2b8\uc6cc\ud06c\uc5d0 \ub9de\ub294 \ud574\uc2dc\ub97c \ub354\ud558\uae30(\uc608: Gnutella2, eDonkey2000) GeneralView.label.connected=\uc5f0\uacb0\ub428 GeneralView.label.in_swarm=\uac1c\uac00 \uc9d3\ub294 \ub5bc ManagerItem.initializing=\ucd08\uae30\uac12\uc5d0 \ub9de\ucd94\uace0 \uc788\uc74c AlertMessageBox.error=\uc624\ub958 AlertMessageBox.warning=\uacbd\uace0 AlertMessageBox.comment=\uc54c\ub9bc AlertMessageBox.information=\uc54c\ub9bc AlertMessageBox.unread=\uc77d\uc9c0 \uc54a\uc740 \uacbd\uace0 \uc54c\ub9bc\uc774 \uc788\uc2b5\ub2c8\ub2e4 - \ub20c\ub7ec\uc11c \ud655\uc778\ud558\uc138\uc694. SharedPortServer.alert.selectorfailed=\ub4e4\uc5b4\uc624\ub294 \ub370\uc774\ud130 \ub4e3\uae30\ub97c \ub9c8\ub828\ud558\uc9c0 \ubabb\ud568.\n\ubc29\ud654\ubcbd \uc124\uc815\uc5d0\uc11c java(w).exe\uc774 '\uc11c\ubc84'\ub85c \ub3cc\uc544\uac00\uac8c \ub450\uace0 \uc788\ub294\uc9c0 \uac80\uc0ac. Tracker.alert.listenfail=%1 \ud3ec\ud2b8\uc5d0 \ub4e3\uae30 \ud3ec\ud2b8 \ub9c8\ub828\ud558\uc9c0 \ubabb\ud568.\n\ub2e4\ub978 \ud504\ub85c\uadf8\ub7a8\uc774 \uc774 \ud3ec\ud2b8\ub97c \uc774\ubbf8 \uc4f0\uace0 \uc788\ub294\uc9c0 \uac80\uc0ac.\n\ub610\ud55c Vuze uc758 \ub2e4\ub978 \ubcf8\uc774 \uc2e4\ud589\ub418\uace0 \uc788\ub294\uc9c0\ub3c4 \uac80\uc0ac. DiskManager.alert.movefileexists=\ub05d\ub9c8\uce5c \ud30c\uc77c \uc62e\uae30\uae30 \uc624\ub958\n%1 \ud30c\uc77c\uc740 \uc62e\uae38 \ub300\uc0c1 \ud3f4\ub354\uc5d0 \uc774\ubbf8 \uc788\uc2b5\ub2c8\ub2e4. DiskManager.alert.movefilefails=\ub05d\ub9c8\uce5c \ud30c\uc77c \uc62e\uae30\uae30 \uc624\ub958\n%1 \ud30c\uc77c\uc744 \uc62e\uae30\uc9c0 \ubabb\ud568, %2 DiskManager.alert.movefilerecoveryfails=\uc62e\uae30\uc9c0 \ubabb\ud558\uace0 \ub098\uc11c \ub418\ucc3e\uae30 \uc624\ub958\n%1 \ud30c\uc77c\uc744 \ub418\ub3cc\ub9ac\uc9c0 \ubabb\ud568, %2 ConfigView.section.tracker.logenable='tracker.log'\ub85c \uc8fc\uae30\uc801\uc778 \ud1b5\uacc4 \ub85c\uadf8 \uc801\uae30 SpeedView.stats.title=\ud1b5\uacc4 SpeedView.stats.total=\ucd1d SpeedView.stats.session=\uc774 \uc138\uc158 SpeedView.stats.session.tooltip=\ucd1d (\ud504\ub85c\ud1a0\ucf5c) SpeedView.stats.downloaded=\ub0b4\ub824\ubc1b\uc74c (\ud504\ub85c\ud1a0\ucf5c) SpeedView.stats.uploaded=\uc62c\ub824\uc9d0 (\ud504\ub85c\ud1a0\ucf5c) SpeedView.stats.ratio=\ube44 SpeedView.stats.uptime=\uc62c\ub9ac\uae30 \uc2dc\uac04 SpeedView.stats.now=\uc9c0\uae08 SpeedView.stats.now.tooltip=\ucd1d (\ud504\ub85c\ud1a0\ucf5c) AutoMigration.useralert=Vuze \uc0ac\uc6a9\uc790 \uad6c\uc131 \ud30c\uc77c/\ud3f4\ub354\uc758 \uc790\ub3d9 \uc774\ub3d9 \uacb0\uacfc:\n\n%1\n\uba87 \uac00\uc9c0 \uc798\ubabb\ub41c \uac83\ub4e4\uc740 \uc190\uc218 \uc62e\uaca8\uc57c \ud569\ub2c8\ub2e4.\n\uc62e\uae34 \ub2e4\uc74c\uc5d0\ub294 \ubc18\ub4dc\uc2dc \uc120\ud0dd\uc0ac\ud56d\uc5d0\uc11c \ub2f9\uc2e0\uc758 \uc800\uc7a5 \uc704\uce58\ub97c \uc0c8\ub85c \uc124\uc815\ud558\uc138\uc694! # # > 2.0.8.0 # OpenTorrentWindow.title=\ud1a0\ub7f0\ud2b8 \uc5f4\uae30 OpenTorrentWindow.message=\uc2dc\ud5d8 OpenTorrentWindow.addFiles=\ud30c\uc77c \ucd94\uac00 OpenTorrentWindow.dataLocation=\uc790\ub8cc\ub97c \uc800\uc7a5\ud560 \uc704\uce58: OpenTorrentWindow.startMode=\ubc29\uc2dd \ub354\ud558\uae30 OpenTorrentWindow.startMode.queued=\ub300\uae30 OpenTorrentWindow.startMode.stopped=\uba48\ucda4 OpenTorrentWindow.startMode.forceStarted=\uc5b5\uc9c0\ub85c \uc2dc\uc791\ud568 OpenTorrentWindow.addPosition=\ub300\uae30\uc5f4 \uc704\uce58 OpenTorrentWindow.addPosition.first=\ucc98\uc74c OpenTorrentWindow.addPosition.last=\ub9c8\uc9c0\ub9c9 TableColumn.header.remaining.info=\ub0b4\ub824\ubc1b\uc544\uc57c \ud560 \uc591 TableColumn.header.remaining=\ub0a8\uc74c ConfigView.section.tracker.enablecompact=\uc870\uadf8\ub9c8\ud55c \uc54c\ub9ac\uae30 \ud504\ub85c\ud1a0\ucf5c \uc791\ub3d9 ConfigView.section.tracker.enablekey=\ub192\uc740 \ubcf4\uc548\uc744 \uc704\ud574\uc11c \uc5f4\uc1e0\ub85c \ub354\ub4ec\uc774 \uc9c0\ub098\uae30 \uc791\ub3d9 ConfigView.section.file.perf=\uc2e4\ud589 \uc120\ud0dd\uc0ac\ud56d ConfigView.section.file.perf.explain=\uacbd\uace0 - \uc774 \ub9e4\uac1c \ubcc0\uc218\ub4e4\uc744 \uc54c\ub9de\uc9c0 \uc54a\uac8c \ubc14\uafb8\uba74 \ub0b4\ub824\ubc1b\uae30 \uc131\ub2a5\uc5d0 \uac70\uc2a4\ub974\ub294 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud569\ub2c8\ub2e4.\n\ud639\uc2dc "out of memory(\uba54\ubaa8\ub9ac \ubc16\uc73c\ub85c)" \ubb38\uc81c\uac00 \uc0dd\uae30\uba74, \ud1a0\ub7f0\ud2b8\ub9c8\ub2e4\uc758 \uc5f0\uacb0 \uc81c\ud55c\uc744 \ud5e4\uc544\ub9ac\uc2ed\uc2dc\uc694.(\uc804\uc1a1 \uad6c\uc131\uc744 \ubcf4\uc2ed\uc2dc\uc694.) ConfigView.section.file.max_open_files.explain=\ub108\ubb34 \ub9ce\uc740 \ud30c\uc77c\uc744 \uc5ec\ub294 \uac83\uc740 \ud30c\uc77c \ub2e4\ub8e8\uae30\uc640 \uac19\uc740 \ud55c\uc815\ub41c \uc790\uc6d0 \ub54c\ubb38\uc5d0 \uc6b4\uc601 \uccb4\uacc4 \ubb38\uc81c\ub97c \uc77c\uc73c\ud0ac \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc774\uac83\uc740 \ud568\uaed8 \uc5ec\ub294 \ud30c\uc77c\uc758 \uc218\ub97c \uc81c\ud55c\ud569\ub2c8\ub2e4. popup.error.hide=\uc228\uae30\uae30 popup.error.details=\uc0c1\uc138 \uc815\ubcf4 ConfigView.section.style.colorOverrides=\ube5b\uae54 \ubb34\uc2dc ConfigView.section.style.colorOverride.progressBar=\uc9c4\ud589 \ub9c9\ub300 ConfigView.section.style.colorOverride.error=\uc624\ub958 MainWindow.status.tooOld=\uc624\ub798\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \uc5c5\ub370\uc774\ud2b8\ud558\uc2ed\uc2dc\uc694. ConfigView.section.style.colorOverride.warning=\uacbd\uace0 ConfigView.section.style.colorOverride.altRow=\ubc88\uac08\uc544 \uc788\ub294 \uc904 ConfigView.section.file.save.peers.enable=\ube60\ub978 \ub2e4\uc2dc \uc787\uae30\ub97c \ud558\ub824\uace0 \ub3d9\ub8cc \uc5f0\uacb0\uc744 \uc800\uc7a5 ConfigView.section.file.save.peers.max=\uc800\uc7a5\ud560 \ucd5c\ub300 \ub3d9\ub8cc \uc218 [0: \ubb34\uc81c\ud55c] ConfigView.section.file.save.peers.pertorrent=\ud1a0\ub7f0\ud2b8\ub9c8\ub2e4\uc758 \ub3d9\ub8cc \uc218 ConfigView.label.max_peers_per_torrent=\ud1a0\ub7f0\ud2b8\ub9c8\ub2e4\uc758 \ucd5c\ub300 \uc5f0\uacb0 \uc218 [0: \ubb34\uc81c\ud55c] ConfigView.label.max_peers_total=\ucd5c\ub300 \ucd1d \uc5f0\uacb0 \uc218 [0: \ubb34\uc81c\ud55c] ConfigView.section.style.colorOverrides.reset=\ube5b\uae54 \ucc98\uc74c \uac12\uc73c\ub85c ConfigView.section.language.info=\uc791\ub3d9\ud558\uba74 Vuze uac00 \uc2dc\uc791\ud560 \ub54c\ub9c8\ub2e4 \uc5c5\ub370\uc774\ud2b8 \uac80\uc0ac\ub97c \ud569\ub2c8\ub2e4. ConfigView.section.language.enableUpdate=\uc6f9 \uc5c5\ub370\uc774\ud2b8 \uc791\ub3d9 ConfigView.section.language.UpdateURL=\uc5c5\ub370\uc774\ud2b8 \uc8fc\uc18c ConfigView.section.language.UpdateNow=\uc9c0\uae08 \uc5c5\ub370\uc774\ud2b8 Button.revert=\ubcf5\uad6c MyTorrentsView.menu.changeDirectory=\ub370\uc774\ud130 \ud3f4\ub354 \ubc14\uafb8\uae30 GenericText.column=\uc138\ub85c\uc904 MyTorrentsView.menu.thisColumn.remove=\uc138\ub85c\uc904 \uc9c0\uc6b0\uae30 MyTorrentsView.menu.thisColumn.toClipboard=\ud14d\uc2a4\ud2b8\ub97c \ud074\ub9bd\ubcf4\ub4dc\ub85c \ubcf5\uc0ac MyTorrentsView.menu.thisColumn.autoTooltip=\ud56d\uc0c1 \uadc0\ub754 \ubcf4\uc5ec\uc8fc\uae30 MyTorrentsView.menu.tracker=\ub354\ub4ec\uc774 ConfigView.download.abbreviated=\ub0b4\ub9bc: ConfigView.upload.abbreviated=\uc62c\ub9bc: ConfigView.complete.abbreviated=\ub05d: TableColumn.header.secondsseeding=\ub2e4\uc74c\uc5d0 \ubfcc\ub9ac\uae30 TableColumn.header.secondsseeding.info=\uc774\uc81c\uae4c\uc9c0 \ubfcc\ub9b0 \uc804\uccb4 \uc2dc\uac04 TableColumn.header.secondsdownloading=\ub2e4\uc74c\uc5d0 \ub0b4\ub824\ubc1b\uae30 TableColumn.header.secondsdownloading.info=\uc774\uc81c\uae4c\uc9c0 \ub0b4\ub824\ubc1b\uc740 \uc2dc\uac04 ConfigView.section.tracker.udpversion=UDP \ud504\ub85c\ud1a0\ucf5c \ubc84\uc804 (1 \ub610\ub294 2) window.updateswt.title=SWT \ubc84\uc804\uc774 \ub108\ubb34 \uc624\ub798\ub418\uc5c8\uc2b5\ub2c8\ub2e4. window.updateswt.text=SWT \ubc84\uc804\uc774 \ub108\ubb34 \uc624\ub798\ub418\uc5c8\uc2b5\ub2c8\ub2e4.\nSWT\ub294 Vuze \uc5d0\uc11c \uc4f0\uc774\ub294 \uadf8\ub798\ud53d \ub77c\uc774\ube0c\ub7ec\ub9ac\ub85c, \uac00\uc9c0\uace0 \uc788\ub294 \ubc84\uc804\uc774 \ucd5c\uc2e0 Vuze \ubc84\uc804\uc744 \uc2e4\ud589\ud558\uae30\uc5d0\ub294 \ub108\ubb34 \uc624\ub798\ub418\uc5c8\uc2b5\ub2c8\ub2e4. SWT\ub97c \uc5c5\ub370\uc774\ud2b8\ud558\ub824\uba74 \ud655\uc778 \ub2e8\ucd94\ub97c \ub204\ub974\uc2ed\uc2dc\uc694. window.updateswt.status=\uc0c1\ud0dc window.updateswt.failed=\uc5c5\ub370\uc774\ud2b8\ud558\uc9c0 \ubabb\ud558\uc600\uc2b5\ub2c8\ub2e4. \ub2e4\uc2dc \uc2dc\uc791\ud558\ub824\uba74 \ud655\uc778\uc744 \ub204\ub974\uc2ed\uc2dc\uc694. window.updateswt.status.downloading.updater=\uc5c5\ub370\uc774\ud2b8 \ubaa8\ub4c8\uc744 \ub0b4\ub824\ubc1b\uace0 \uc788\uc74c window.updateswt.status.finding=\ucd5c\uc2e0 SWT \ubc84\uc804\uc744 \ucc3e\uace0 \uc788\uc74c window.updateswt.status.downloading=\ucd5c\uc2e0 SWT \ubc84\uc804\uc744 \ub0b4\ub824\ubc1b\uace0 \uc788\uc74c window.updateswt.status.done=\ub2e4\uc2dc \uc2dc\uc791\ud558\uace0 \uc788\uc74c window.updateswt.ok=\ud655\uc778 window.updateswt.cancel=\ucde8\uc18c swt.updater.downloader.downloading=\ub2e4\uc74c\uc5d0\uc11c SWT \ub0b4\ub824\ubc1b\uae30 swt.updater.urlsgetter.downloading=\ub2e4\uc74c\uc5d0\uc11c \ubbf8\ub7ec \ub9ac\uc2a4\ud2b8 \uc5bb\uc74c swt.updater.urlsgetter.platform=\uc6b4\uc601 \uccb4\uacc4\uc5d0 \ub9de\ub294 SWT: window.updateswt.ignore=\ubb34\uc2dc ConfigView.section.style.useFancyTabs=\ud654\ub824\ud55c \ud0ed\uc744 \uc500 splash.initializeGM=\uc804\uccb4 \ud1a0\ub7f0\ud2b8 \uad00\ub9ac\uc790\ub97c \ucd08\uae30\uac12\uc5d0 \ub9de\ucd94\uace0 \uc788\uc74c splash.loadingTorrents=\ud1a0\ub7f0\ud2b8\ub4e4\uc744 \ubd88\ub7ec\uc624\uace0 \uc788\uc74c MyTorrentsView.menu.thisColumn.sort=\uc815\ub82c(&S) Scrape.status.ok=\ubaa8\uc73c\uae30 \uc88b\uc74c Scrape.status.error=\ubaa8\uc73c\uae30 \uc624\ub958: Scrape.status.error.badURL=\ub354\ub4ec\uc774 \uc54c\ub9bc \uc8fc\uc18c(Announce URL)\uac00 \ubaa8\uc73c\uae30 \uc591\uc2dd\uc744 \ub530\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Scrape.status.error.nohash=\ud574\uc2dc\uac00 \ub2f5\uc5d0\uc11c \ube60\uc9d0 Scrape.status.error.invalid=\uc798\ubabb\ub41c \ub2f5 Scrape.status.nextScrapeAt=%1\uc5d0\uc11c \ub2e4\uc74c \ubaa8\uc73c\uae30 Scrape.status.scraping=\ubaa8\uc73c\uace0 \uc788\uc74c.. Scrape.status.initializing=\ubaa8\uc73c\ub824\uace0 \ud558\uace0 \uc788\uc74c Scrape.status.scraping.queued=\ubaa8\uc73c\uae30 \ub300\uae30 \uc21c\uc11c.. ConfigView.label.minSpeedForActiveSeeding=\uc18d\ub3c4\uac00 \uc774\ubcf4\ub2e4 \ub5a8\uc5b4\uc9c0\uba74 \uc790\ub9ac\ub97c \uc4f0\uace0 \uc788\ub294 \ub05d\ub9c8\uce5c \ud1a0\ub7f0\ud2b8\ub97c \uc138\uc9c0 \uc54a\uc74c ConfigView.section.stats.exportpeers=\ub3d9\ub8cc \uc0c1\uc138 \uc815\ubcf4 \ub0b4\ubcf4\ub0b4\uae30 MainWindow.menu.view.irc.moved=IRC\ub294 \ucd94\uac00\uae30\ub2a5\uc73c\ub85c \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4. http://azureus.sourceforge.net/plugin_list.php\ub97c \ucc38\uace0\ud558\uc138\uc694. \ucd94\uac00\uae30\ub2a5\uc774 \uc124\uce58\ub418\uc5c8\uc73c\uba74 \uba54\ub274 \ubaa8\uc74c\uc5d0\uc11c \ucd94\uac00\uae30\ub2a5->IRC \uba54\ub274\ub97c \uc4f0\uc2ed\uc2dc\uc694. MyTrackerView.webui.contextmenu.copyurl=\ud074\ub9bd\ubcf4\ub4dc\uc5d0 \ud1a0\ub7f0\ud2b8 \uc8fc\uc18c\ub97c \ubcf5\uc0ac ConfigView.section.file.torrent.ignorefiles=\ud1a0\ub7f0\ud2b8 \ub9cc\ub4e4 \ub54c \ubb34\uc2dc\ud560 \ud30c\uc77c\ub4e4\n\uc608 .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=\ud30c\uc77c \ubb34\uc2dc\ud558\uace0 \uc788\uc74c ConfigView.section.style.useUnitsRateBits=\ubc14\uc774\ud2b8\uc5d0 \ubc14\ud0d5\uc744 \ub454 \uc18d\ub3c4 \uac12\uc5d0 \ubc14\uc774\ud2b8 \ub300\uc2e0\uc5d0 \ube44\ud2b8\ub97c \uc500 (KiB/s -> Kibit/s \ub4e4) ConfigView.section.interface.resetassoc=\ud30c\uc77c(.torrent) \uc5f0\uacb0 \ud504\ub85c\uadf8\ub7a8 \ucc98\uc74c \uac12\uc73c\ub85c ConfigView.section.interface.resetassocbutton=\ucc98\uc74c \uac12\uc73c\ub85c ConfigView.section.interface.checkassoc=\uc2dc\uc791\ud560 \ub54c \uc5f0\uacb0 \ud504\ub85c\uadf8\ub7a8 \uac80\uc0ac dialog.associations.title=\uc5f0\uacb0 \uac80\uc0ac Button.yes=\uc608 &Y Button.no=\uc544\ub2c8\uc624 &N ConfigView.label.seeding.autoStart0Peers=0 \ub3d9\ub8cc\uc778 \ub05d\ub9c8\uce5c \ubaa8\ub4e0 \ud1a0\ub7f0\ud2b8\ub97c \uc800\uc808\ub85c \uc2dc\uc791 ConfigView.label.seeding.autoStart0Peers.tooltip=0 \ub3d9\ub8cc\uc778 \ud1a0\ub7f0\ud2b8\uc5d0 \ub354\ub4ec\uc774\uac00 \ub298 \uc528\uc557\uc744 \uc62c\ub9ac\ub824\uba74 \ucf1c\uc2ed\uc2dc\uc694. dialog.associations.prompt=Vuze\uac00 BitTorrent \ud30c\uc77c\uc758 \uae30\ubcf8 \uc751\uc6a9\ud504\ub85c\uadf8\ub7a8\uc774 \uc544\ub2d9\ub2c8\ub2e4.\n\ud1a0\ub7f0\ud2b8 \ud30c\uc77c\uc744 Vuze\uc5d0 \uc5f0\uacb0\ud558\uaca0\uc2b5\ub2c8\uae4c? dialog.associations.askagain=\uc2dc\uc791\ud560 \ub54c \uac80\uc0ac ConfigView.section.plugins.update=\ucd94\uac00\uae30\ub2a5 \uc5c5\ub370\uc774\ud2b8 Plugin.pluginupdate.enablecheck=\ucd94\uac00\uae30\ub2a5 \uc5c5\ub370\uc774\ud2b8 \ud655\uc778 \ud65c\uc131\ud654 plugins.basicview.status=\uc0c1\ud0dc: plugins.basicview.activity=\ud65c\ub3d9: plugins.basicview.progress=\uc9c4\ud589 plugins.basicview.log=\ub85c\uadf8: ConfigView.label.maxdownloadspeed=KB/s \ucd5c\uace0 \ucd1d \ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4 [0: \ubb34\uc81c\ud55c] splash.loadingTorrent=\ud1a0\ub7f0\ud2b8\ub97c \ubd88\ub7ec\uc624\uace0 \uc788\uc74c splash.of=: UpdateWindow.title=Vuze \uc5c5\ub370\uc774\ud2b8 UpdateWindow.header=\ub2e4\uc74c \uad6c\uc131 \uc694\uc18c\ub4e4\uc744 \uc5c5\ub370\uc774\ud2b8\ud574\uc57c \ud569\ub2c8\ub2e4.: UpdateWindow.columns.install=\uc124\uce58 UpdateWindow.columns.name=\uc774\ub984 UpdateWindow.columns.version=\ubc84\uc804 UpdateWindow.columns.size=\ud06c\uae30 UpdateWindow.cancel=\ucde8\uc18c UpdateWindow.quit=\ub098\uac00\uae30 UpdateWindow.close=\ub2eb\uae30 UpdateWindow.ok=\uc5c5\ub370\uc774\ud2b8 UpdateWindow.restart=\ub2e4\uc2dc \uc2dc\uc791 UpdateWindow.status.downloading=\ub0b4\ub824\ubc1b\uae30\ud558\uace0 \uc788\uc74c UpdateWindow.status.done=\ub9c8\uce68 UpdateWindow.status.failed=\ud558\uc9c0 \ubabb\ud568 UpdateWindow.status.restartNeeded=\ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud569\ub2c8\ub2e4. ConfigView.pluginlist.broken=\uae68\uc9d0 ConfigView.pluginlist.whereToPut=\uc0ac\uc6a9\uc790 \ucd94\uac00\uae30\ub2a5\uc744 \uc544\ub798\uc640 \uac19\uc740 \uc0ac\uc6a9\uc790 \ud3f4\ub354\uc5d0 \ub123\uc73c\uc2ed\uc2dc\uc694: ConfigView.pluginlist.whereToPutOr=\uacf5\uc720 \ucd94\uac00\uae30\ub2a5\uc744 \uc4f0\ub824\uba74 \uc544\ub798\uc640 \uac19\uc740 \ud3f4\ub354\uc5d0 \ub123\uc73c\uc2ed\uc2dc\uc694: MainWindow.statusText.checking=\uc5c5\ub370\uc774\ud2b8 \uac80\uc0ac\ud558\uace0 \uc788\uc74c TableColumn.header.OnlyCDing4=\ub2e4\uc74c\uc5d0 \ubfcc\ub9ac\uae30\ub9cc TableColumn.header.OnlyCDing4.info=\uc774\uc81c\uae4c\uc9c0 \ubfcc\ub9ac\uae30\ub9cc \ud55c \uc2dc\uac04. \ub0b4\ub824\ubc1b\uae30\ud558\uace0 \ub098\uc11c (\ubfcc\ub9b0) \uc2dc\uac04\uc740 \ube8c. ConfigView.section.style.alternateTablePainting=\uadf8\ub798\ud53d \ubaa9\ub85d \uc138\ub85c\uc904\uc744 \uafb8\ubbf8\ub824\uace0 \ubc88\uac08\uc544 \ud558\ub294 \ubc29\ubc95\uc744 \uc500 (\ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud560 \uc218 \uc788\uc74c) UpdateWindow.status.restartMaybeNeeded=\ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. ConfigView.pluginlist.shared=\uacf5\uc720\ub428 PeersView.host=\ud638\uc2a4\ud2b8 \uc774\ub984 PeersView.host.info=\ub3d9\ub8cc\uc758 \uc4f8 \uc218 \uc788\ub294 \ud638\uc2a4\ud2b8 \uc774\ub984 (\uc2e4\ud589\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60\uc9c0\ub3c4 \ubaa8\ub984) MainWindow.menu.help.whatsnew=\uc0c8 \uc18c\uc2dd ConfigView.label.checkonstart=Vuze\ub97c \uc2dc\uc791\ud560 \ub54c \ucd5c\uc2e0 \ubc84\uc804 \uac80\uc0ac ConfigView.label.periodiccheck=\uc815\uae30\uc801\uc73c\ub85c \ucd5c\uc2e0 \ubc84\uc804 \uac80\uc0ac ConfigView.label.opendialog=\uc5c5\ub370\uc774\ud2b8\uac00 \uac00\ub2a5\ud560 \ub54c \uc5c5\ub370\uc774\ud2b8 \uc800\uc808\ub85c \uc5f4\ub9ac\uae30 MainWindow.updateavail=\uc5c5\ub370\uc774\ud2b8\ud558\ub824\uba74 \uc5ec\uae30\ub97c \ud074\ub9ad MainWindow.status.unofficialversion=Vuze \ubca0\ud0c0 MainWindow.status.latestversionunchecked=\ubc84\uc804 \uac80\uc0ac\uac00 \uc791\ub3d9\ud558\uc9c0 \uc54a\uc74c GeneralView.label.updatein.stopped=\uba48\ucda4 StartStopRules.menu.viewDebug=\ub514\ubc84\uadf8 \uc815\ubcf4 \ubcf4\uae30 ConfigView.section.style.doNotUseGB=GB \ub2e8\uc704 \uc4f0\uc9c0 \uc54a\uc74c ConfigView.section.style.doNotUseGB.tooltip=\uace0\ub974\uba74 Vuze ub294 1024MB\ubcf4\ub2e4 \ud070 \ud06c\uae30\uc5d0\ub3c4 MB\ub97c \uacc4\uc18d \uc4f8 \uac83\uc785\ub2c8\ub2e4. MainWindow.menu.help.plugins=\ucd94\uac00\uae30\ub2a5 \uc5bb\uae30 ConfigView.section.plugins.TrackerWeb=\ub354\ub4ec\uc774 \uc6f9 ConfigView.section.tracker.enablecategories=\ubd84\ub958\ub85c \ud1a0\ub7f0\ud2b8 \ub098\ub204\uae30 health.explain.share=\ud1a0\ub7f0\ud2b8\uac00 \ud638\uc2a4\ud2b8\ub098 \ubc1c\ud589 \uc911 \ud558\ub098\uac00 \ub418\ub294 \uac83\uc744 \ub73b\ud569\ub2c8\ub2e4. ConfigView.section.tracker.createcert=\uc2a4\uc2a4\ub85c \uc11c\uba85\ud55c \uc778\uc99d\uc11c \ub9cc\ub4e4\uae30 ConfigView.section.tracker.createbutton=\ub9cc\ub4e4\uae30 security.certcreate.title=\uc2a4\uc2a4\ub85c \uc11c\uba85\ud55c \uc778\uc99d\uc11c \ub9cc\ub4e4\uae30 security.certcreate.intro=\uc774 \uba54\uc138\uc9c0 \uc0c1\uc790\ub294 \uc2a4\uc2a4\ub85c \uc11c\uba85\ud55c \uc778\uc99d\uc11c\ub97c \ub9cc\ub4e4\ub3c4\ub85d \ub3c4\uc640\uc90d\ub2c8\ub2e4. security.certcreate.alias=\ubcc4\uba85 security.certcreate.strength=\uc778\uc6d0 security.certcreate.firstlastname=\uc131\uacfc \uc774\ub984 security.certcreate.orgunit=\uc9c1\ud568 security.certcreate.org=\uc870\uc9c1 security.certcreate.city=\uc2dc\uad70\uad6c \ub610\ub294 \uc74d\uba74\ub9ac\ub3d9 security.certcreate.state=\ub098\ub77c \ub610\ub294 \uc2dc\ub3c4 security.certcreate.country=\ub450 \uae00\uc790\uc758 \ub098\ub77c \ubd80\ud638 security.certcreate.ok=\ub9cc\ub4e4\uae30 security.certcreate.cancel=\ucde8\uc18c security.certcreate.createok=\uc778\uc99d\uc11c\ub97c \uc81c\ub300\ub85c \ub9cc\ub4e6 security.certcreate.createfail=\uc778\uc99d\uc11c\ub97c \ub9cc\ub4e4\uc9c0 \ubabb\ud568 ConfigView.section.plugins.webui=\ucca8\ub2e8 \uc6f9 \uc778\ud130\ud398\uc774\uc2a4 ConfigView.section.plugins.xml_http_if=XML/HTTP \uc778\ud130\ud398\uc774\uc2a4 webui.passwordenable=\uc554\ud638 \uc791\ub3d9 webui.user=\uc0ac\uc6a9\uc790 \uc774\ub984 webui.password=\uc554\ud638 webui.port=\ud3ec\ud2b8 (*) webui.protocol=\ud504\ub85c\ud1a0\ucf5c (*) webui.homepage=\ud648\ud398\uc774\uc9c0 (*) webui.rootdir=\ub8e8\ud2b8 \ud3f4\ub354 (*) webui.rootres=\ub8e8\ud2b8 \uc790\uc6d0 (*) webui.mode=\ubc29\uc2dd (*) webui.mode.info=\ubc29\uc2dd\uc740\n\t"full"\t= \ubaa8\ub4e0 \uc791\uc5c5\uc744 \uc4f8 \uc218 \uc788\uc74c(\uae30\ubcf8\uac12)\n\t"view"\t= \ubcf4\uae30\ub9cc \ud560 \uc218 \uc788\uc74c(\uadf8\ub7ec\ub098 \uc0c8\ub85c \uace0\uce68 \ube48\ub3c4\ub97c \uc5c5\ub370\uc774\ud2b8\ud560 \uc218 \uc788\uc74c) webui.access=\uc811\uadfc (*) webui.access.info=\uc811\uadfc\uc740\n\t"local"\t= \ub85c\uceec \ucef4\ud4e8\ud130\ub9cc \uc5f0\uacb0\ud560 \uc218 \uc788\uc74c\n\t"all"\t= \uc790\uc720\ub85c\uc6b4 \uc811\uadfc (\uae30\ubcf8\uac12)\n\tIP\t= \uc608 192.168.0.2\t\t\t\ud55c IP\ub9cc\n\tIP1-IP2\t= \uc608 192.168.0.1-192.168.0.255\tIP\uc758 \ubaa8\ub4e0 \ubc94\uc704 GeneralView.label.maxdownloadspeed=\ucd5c\uace0 \ub0b4\ub824\ubc1b\uae30 Security.keystore.corrupt='%1' \uac08\ubb34\ub9ac \uc554\ud638\ub97c \ubd88\ub7ec\uc624\uc9c0 \ubabb\ud568. \uadf8\uac83\uc744 \uc9c0\uc6b0\uace0 \uc778\uc99d\uc11c\ub97c \ub2e4\uc2dc \ub9cc\ub4e4\uac70\ub098 \ub2e4\uc2dc \ub4e4\uc5ec\uc624\uc2ed\uc2dc\uc694. Security.keystore.empty=\uac08\ubb34\ub9ac \uc554\ud638\uac00 \ube44\uc5b4 \uc788\uc2b5\ub2c8\ub2e4. \uc2a4\uc2a4\ub85c \uc11c\uba85\ud55c \uc778\uc99d\uc11c\ub97c \ub9cc\ub4e4\uac70\ub098(\ub3c4\uad6c->\uc120\ud0dd\uc0ac\ud56d->\ubcf4\uc548\uc744 \ubcf4\uc2ed\uc2dc\uc694.) '%1'\ub85c \uc774\ubbf8 \uc788\ub358 \uc778\uc99d\uc11c\ub97c \ub4e4\uc5ec \uc624\uc2ed\uc2dc\uc694. webui.restart.info=(*)\ub77c\uace0 \ud45c\uc2dc\ub41c \ub9e4\uac1c \ubcc0\uc218\ub97c \ubc14\uafbc \uac83\uc740 \ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud6a8\ub825\uc774 \ub098\ud0c0\ub0a9\ub2c8\ub2e4. GeneralView.label.maxdownloadspeed.tooltip=\ucd5c\uace0 \ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4 [0: \ubb34\uc81c\ud55c] upnp.enable=UPnP \uc791\ub3d9 upnp.info=\uc77c\ubc18\uc801\uc778 \ud50c\ub7ec\uadf8 \uc564 \ud50c\ub808\uc774(UPnP)\ub294 UPnP\uc774 \uc791\ub3d9\ud558\ub294 \ub77c\uc6b0\ud130\uc5d0\uc11c \ud3ec\ud2b8\ub97c \uc800\uc808\ub85c \uc0ac\uc0c1(\u5beb\u50cf)\ud558\ub3c4\ub85d \ud569\ub2c8\ub2e4. upnp.mapping.dataport=\ub4e4\uc5b4\uc624\ub294 \ub3d9\ub8cc \ub370\uc774\ud130 \ud3ec\ud2b8 upnp.mapping.tcptrackerport=TCP \ub354\ub4ec\uc774 \ud3ec\ud2b8 upnp.mapping.udptrackerport=UDP \ub354\ub4ec\uc774 \ud3ec\ud2b8 upnp.alert.differenthost=UPnP: '%1'\uc758 \uc0ac\uc0c1(\u5beb\u50cf)\uc774 '%2'\uc5d0\uc11c \ubbf8\ub8e8\uc5b4\uc84c\uc2b5\ub2c8\ub2e4. - \ub2e4\ub978 \ud3ec\ud2b8\ub97c \uace0\ub974\uc2ed\uc2dc\uc694. upnp.alert.mappingok=UPnP: '%1'\uc758 \uc0ac\uc0c1(\u5beb\u50cf)\uc744 \ub9c8\ub828\ud568 upnp.alert.mappingfailed=UPnP: '%1'\uc758 \uc0ac\uc0c1(\u5beb\u50cf)\uc744 \ubabb\ud568 upnp.alertsuccess=\uc798\ub41c \uc0ac\uc0c1(\u5beb\u50cf)\ub4e4\uc744 \uae30\ub85d\ud568 upnp.alert.lostdevice=UPnP: UPnP '%2' \uc7a5\uce58\uc5d0\uc11c '%1' \uc11c\ube44\uc2a4\uc758 \uc5f0\uacb0\uc744 \uc783\uc74c upnp.grabports=\ub2e4\ub978 \ucef4\ud4e8\ud130\uac00 \uac00\uc9c0\uace0 \uc788\ub294 \ud3ec\ud2b8\ub77c\ub3c4 \uc0ac\uc0c1(\u5beb\u50cf) upnp.refresh.label=\uc0ac\uc0c1(\u5beb\u50cf) \uc0c8\ub85c \uace0\uce68 upnp.refresh.button=\uc0c8\ub85c \uace0\uce68 upnp.alert.mappinggrabbed=UPnP: '%1'\uc758 \uc0ac\uc0c1(\u5beb\u50cf)\uc744 '%2'\uc5d0\uc11c \ub9c8\ub828\ud558\uace0 \uac00\ub85c\ucc54 upnp.mapping.tcpssltrackerport=TCP SSL \ub354\ub4ec\uc774 \ud3ec\ud2b8 upnp.alertothermappings=\ub2e4\ub978 \ucef4\ud4e8\ud130\uac00 \uac00\uc9c0\uac8c \ub41c \ud3ec\ud2b8\ub97c \uae30\ub85d\ud568 upnp.alertdeviceproblems=UPnP \uc7a5\uce58\uc758 \ubb38\uc81c\ub4e4\uc744 \uae30\ub85d\ud568 upnp.trace_to_log=\uc804\uccb4 \uc624\ub958\ubc0f \uc138\ubd80\ub0b4\uc6a9 \uae30\ub85d upnp.wiki_link=UPnP\uc5d0\uc11c Vuze \uc704\ud0a4 \ud398\uc774\uc9c0 ConfigView.pluginlist.coreplugins=\ub2e4\uc74c \ubcf8\ub798 \uac16\ucdb0\uc9c4 \ucd94\uac00\uae30\ub2a5\uc774 \uc2dc\uc791\ub428: Peers.column.DLedFromOthers=\ub2e4\ub978 \ub3d9\ub8cc\uc5d0\uac8c\uc11c Peers.column.DLedFromOthers.info=\uc5f0\uacb0\ub41c \ub3d9\uc548 \ub2e4\ub978 \ub3d9\ub8cc\ub4e4\uc5d0\uac8c\uc11c \ub0b4\ub824\ubc1b\uc740 \ub370\uc774\ud130 \uc591 Peers.column.UpDownRatio=\uc62c\ub9ac\uae30:\ub0b4\ub824\ubc1b\uae30 Peers.column.UpDownRatio.info=\ub3d9\ub8cc\uc758 "\uc62c\ub9ac\uae30 : \ub0b4\ub824\ubc1b\uae30" \ube44 Peers.column.UpRatio=\uc62c\ub9ac\uae30 \ube44 Peers.column.UpRatio.info=\ub3d9\ub8cc\uc758 "\ub2f9\uc2e0\uc5d0\uac8c\uc11c \uc62c\ub9ac\uae30 : \ub2e4\ub978 \ub3d9\ub8cc\uc5d0\uac8c\uc11c \uc62c\ub9ac\uae30" \ube44 upnp.releasemappings=\ub2eb\uae30\uc5d0\uc11c \uc0ac\uc0c1(\u5beb\u50cf) \ud480\uc5b4 \ub193\uc74c webui.upnpenable=\uc774 \ud3ec\ud2b8\uc5d0 UPnP \uc791\ub3d9 (*) ConfigView.section.file.friendly.hashchecking=\uc4f8\ubaa8 \uc788\ub294 \ud574\uc2dc \uac80\uc0ac ConfigView.section.file.friendly.hashchecking.tooltip=CPU/\uc2dc\uc2a4\ud15c\uc5d0\uc11c \uc870\uae08 \ub354 \ub290\ub9ac\ub098 \ud6e8\uc52c \ub354 \uc801\uac8c \uc790\uadf9 \ubc1b\ub294 \uc870\uac01 \ud574\uc2dc \uac80\uc0ac \ubc29\uc2dd ConfigView.section.tracker.seedretention=\ud1a0\ub7f0\ud2b8\ub9c8\ub2e4 \uc787\ub2ec\uc544 \uac00\uc9c0\uace0 \uc788\ub294 \ucd5c\ub300 \uc528\uc557 \uc218 [0: \ubb34\uc81c\ud55c] ConfigView.section.tracker.seedretention.info=\uadc0\ub754: \uc787\ub2ec\uc544 \uac00\uc9c0\uace0 \uc788\uc9c0 \uc54a\uc740 \uc528\uc557\uc5d0\uc11c\ub294 \uc62c\ub9ac\uae30 \ud1b5\uacc4\ub97c \uc783\uc744 \uac83\uc785\ub2c8\ub2e4. ConfigView.section.tracker.port=\ub2e4\uc74c HTTP \ud3ec\ud2b8\uc5d0\uc11c \ub354\ub4ec\uc774 \uc791\ub3d9 ConfigView.section.tracker.sslport=\ub2e4\uc74c HTTPS \ud3ec\ud2b8\uc5d0\uc11c \ub354\ub4ec\uc774 \uc791\ub3d9 ConfigView.section.tracker.publicenable.info=\uc774\uac83\uc740 \ub0a8\ub4e4\uc774 \ud638\uc2a4\ud2b8/\ubc1c\ud589 \uc5c6\uc774 \ub2f9\uc2e0\uc758 \ub354\ub4ec\uc774\ub97c \uc4f0\ub294 \ud1a0\ub7f0\ud2b8\ub97c\n\ub9cc\ub4e4\uac8c \ub0b4\ubc84\ub824 \ub461\ub2c8\ub2e4. Button.clear=\uc9c0\uc6b0\uae30 MainWindow.IPs.tooltip=\uace8\ub77c\ubcf4\uae30 \ubaa9\ub85d \ucd5c\uc2e0 \uc5c5\ub370\uc774\ud2b8: %1\n\ubaa9\ub85d\uc758 \ubaa8\ub4e0 IP \ud544\ud130 - \uc774 \uc138\uc158\uc5d0\uc11c \ucc28\ub2e8/\ucd94\ubc29/\uc545\uc131 IP\uc758 \uc218\n\uc0c1\uc138\ud55c \uc124\uba85\uc744 \ubcf4\ub824\uba74 \ub354\ube14 \ud074\ub9ad ConfigView.section.ipfilter.list.banned=\uc545\uc131 \ub370\uc774\ud130\ub97c \ubcf4\ub0b4\uc11c \ubab0\uc544\ub0c4 ConfigView.section.ipfilter.list.baddata=\uc545\uc131 \ub370\uc774\ud130\ub97c \ubcf4\ub0c4: \uc77c\uc5b4\ub09c \uc77c = Button.reset=\ucc98\uc74c \uac12\uc73c\ub85c ConfigView.section.ipfilter.bannedinfo=\uc545\uc131 \ub370\uc774\ud130\ub97c \ubcf4\ub0b8 IP\ub4e4 - \ud55c\ub3c4\ub97c \ub118\uc73c\uba74 \ubab0\uc544\ub0c4 ConfigView.section.ipfilter.blockedinfo=IP \ud544\ud130\ub85c \ubab0\uc544\ub0b8 IP\ub4e4 download.removerules.name=\uc9c0\uc6b0\uae30 \uaddc\uce59 download.removerules.unauthorised.info=\uad8c\ud55c\uc774 \uc5c6\ub294 \ud1a0\ub7f0\ud2b8\ub294 "\uc2e4\ud328 \ubc18\uc751"\uc5d0\uc11c" "\uad8c\ud55c\uc744 \ubc1b\uc9c0 \ubabb\ud55c"\uc774\ub098 "\uad8c\ud55c\uc774 \uc5c6\ub294" \uc911 \ud558\ub098\ub97c \ub2f4\uace0 \uc788\ub294 \uc54c\ub9ac\uae30 \ubc18\uc751\uc5d0 \uc788\ub294 \uac83\uc774\ub2e4. download.removerules.unauthorised=\uad8c\ud55c\uc774 \uc5c6\ub294 \ud1a0\ub7f0\ud2b8 \uc800\uc808\ub85c \uc9c0\uc6b0\uae30 download.removerules.unauthorised.seedingonly=\t\ubfcc\ub9ac\uace0 \uc788\uae30\ub9cc \ud558\uba74 download.removerules.removed.ok=\ud1a0\ub7f0\ud2b8 \uc9c0\uc6b0\uae30 \uaddc\uce59\uc5d0 \ub530\ub77c \ud1a0\ub7f0\ud2b8 '%1'\ub97c \uc800\uc808\ub85c \uc9c0\uc6e0\uc2b5\ub2c8\ub2e4. download.removerules.updatetorrents=\ub5bc\uc5d0 \ud544\uc694\ud558\uc5ec\uc11c Vuze \uc5c5\ub370\uc774\ud2b8 \ud1a0\ub7f0\ud2b8 \uc9c0\uc6b0\uae30 ConfigView.label.defaultstarttorrentsstopped=\uae30\ubcf8\uac12\uc73c\ub85c \uba48\ucd98 \ucc44\ub85c \uc0c8 \ud1a0\ub7f0\ud2b8\ub97c \ub354\ud558\uae30 ConfigView.section.server.enableudp=UDP \ub354\ub4ec\uc774 \uc811\uc18d \ucef4\ud4e8\ud130 \ud504\ub85c\ud1a0\ucf5c \uc791\ub3d9. upnp.mapping.dataportudp=UDP \ub354\ub4ec\uc774 \uc811\uc18d \ucef4\ud4e8\ud130 \ud3ec\ud2b8 ConfigView.section.file.decoder.showlax=\ubcc4\ub85c \uc54c\ub9de\uc9c0 \uc54a\uc740 \uc778\ucf54\ub529\uae4c\uc9c0 \ubcf4\uc774\uae30 ConfigView.section.file.decoder.showall=\ubaa8\ub4e0 \uc5b4\uc6b8\ub9ac\ub294 \uc778\ucf54\ub529\uc744 \uc54c\ub9de\uac8c \ud5e4\uc544\ub9bc MainWindow.status.updowndetails.tooltip=\uc62c\ub9ac\uae30/\ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4 \uc0c1\uc138 \uc815\ubcf4 - \ubc14\uafb8\ub824\uba74 \uc624\ub978\ucabd \ub2e8\ucd94\ub97c \ub204\ub974\uc2ed\uc2dc\uc694. TrackerClient.announce.warningmessage='%1'\uc758 \ub354\ub4ec\uc774\uc5d0\uc11c '%2'\uc640 \uac19\uc740 \uacbd\uace0\uac00 \ub3cc\uc544\uc634 ConfigView.section.tracker.natcheckenable='\ub4e4\uc5b4\uc624\ub294 \ub370\uc774\ud130 \ud3ec\ud2b8'\ub97c \uc5f0\uacb0\ud560 \uc218 \uc788\ub294\uc9c0 \uac80\uc0ac\ud558\uace0 \ub3d9\ub8cc\uc5d0\uac8c \uc2e4\ud328\ub97c \uc804\ud568 ConfigView.section.tracker.publishenabledetails=\ubaa8\ub4e0 \ud1a0\ub7f0\ud2b8 \uc0c1\uc138 \uc815\ubcf4 \uc54c\ub9bc ConfigView.section.tracker.publishenablepeerdetails=\ub3d9\ub8cc \uc0c1\uc138 \uc815\ubcf4 \uc54c\ub9bc MyTrackerView.badnat=\uc545\uc131 NAT MyTrackerView.badnat.info=\uc791\ub3d9\ud558\uc5ec\uc11c \uc528\uc557/NAT \uac80\uc0ac\uc5d0\uc11c \ub5a8\uc5b4\uc9c4 \ub3d9\ub8cc ConfigView.section.tracker.natchecktimeout=\uac80\uc0ac \uc2dc\uac04 \uc81c\ud55c (\ucd08) ConfigView.section.file.perf.cache.enable=\ub514\uc2a4\ud06c \uce90\uc2dc \uc791\ub3d9 ConfigView.section.file.perf.cache.size=%1\ub85c \uce90\uc2dc \ud06c\uae30 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\uc804\uc1a1(&R) MainWindow.menu.transfers.startalltransfers=\ubaa8\ub450 \uc2dc\uc791(&A) MainWindow.menu.transfers.stopalltransfers=\ubaa8\ub450 \uba48\ucda4(&O) MainWindow.menu.transfers.pausetransfers=\uc7a0\uc2dc \uba48\ucda4(&P) MainWindow.menu.transfers.pausetransfers.keybinding.mac=\uba54\ud0c0+. MainWindow.menu.transfers.resumetransfers=\ub2e4\uc2dc \uc2dc\uc791(&R) ConfigView.label.experimental.osx.kernel.panic.fix=\ub4c0\uc5bc CPU OSX \uc2dc\uc2a4\ud15c\uc5d0\uc11c \ucee4\ub110 \ud328\ub2c9\uc758 \uc2dc\ud5d8\uc801\uc778 \ud574\uacb0 [\ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud568] SystemTray.menu.pausetransfers=\uc804\uc1a1 \uc7a0\uc2dc \uba48\ucda4 SystemTray.menu.resumetransfers=\uc804\uc1a1 \ub2e4\uc2dc \uc2dc\uc791 ConfigView.section.file.truncate.too.large=\uc9c0\uae08 \uc788\ub294 \ub108\ubb34 \ud070 \ud30c\uc77c\uc744 \uc790\ub984 ConfigView.section.file.perf.cache.trace=\uc9c4\ub2e8\uc5d0 \ub3c4\uc6c0\uc774 \ub418\ub294 \ubaa9\uc801\uc73c\ub85c \uce90\uc2dc \uc791\uc5c5\uc744 \uae30\ub85d ConfigView.section.interface.enabletray=\uc54c\ub9bc \uc601\uc5ed \uc791\ub3d9 [\ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud568] PeerManager.status.error=\uc624\ub958 Stats.title.full=\ud1b5\uacc4 TransferStatsView.title.full=\uc804\uc1a1 CacheView.title.full=\uce90\uc2dc CacheView.general.size=\ucd1d \ud06c\uae30 CacheView.general.inUse=\uc4f0\uace0 \uc788\uc74c CacheView.general.title=\uce90\uc2dc \uc815\ubcf4 CacheView.reads.title=\uc785\ucd9c\ub825 \uc77d\uae30 CacheView.reads.fromFile=\ud30c\uc77c\ub85c\ubd80\ud130 CacheView.reads.fromCache=\uce90\uc2dc\ub85c\ubd80\ud130 CacheView.reads.hits=\ub9de\ud798 CacheView.writes.title=\uc785\ucd9c\ub825 \uc4f0\uae30 CacheView.writes.toCache=\uce90\uc2dc\ub85c CacheView.writes.toFile=\ud30c\uc77c\ub85c CacheView.writes.hits=\uc800\uc7a5 CacheView.speeds.title=\ub370\uc774\ud130 \uc18d\ub3c4 CacheView.speeds.reads=\uc77d\uae30 CacheView.speeds.writes=\uc4f0\uae30 CacheView.speeds.fromCache=\uce90\uc2dc\ub85c\ubd80\ud130/\uce90\uc2dc\ub85c CacheView.speeds.fromFile=\ud30c\uc77c\ub85c\ubd80\ud130/\ud30c\uc77c\ub85c CacheView.reads.#=\ubc88\ud638 CacheView.reads.amount=\uc591 CacheView.reads.avgsize=\ud3c9\uade0 \ud06c\uae30 openUrl.referrer=\ub9e1\uae38 \ud398\uc774\uc9c0 \uc8fc\uc18c: openUrl.referrer.info=\ub9e1\uae38 \uc6f9 \uc0ac\uc774\ud2b8\uac00 \ud544\uc694\ud560 \ub54c\ub9cc ConfigView.label.maxuploadspeedseeding=KB/s \ubfcc\ub9ac\uae30\ub9cc \ud560 \ub54c\uc758 \ucd5c\uace0 \ucd1d \uc62c\ub9ac\uae30 \uc18d\ub3c4 [0: \ubb34\uc81c\ud55c] ConfigView.label.transfer.ignorepeerports=\uc774 \ub370\uc774\ud130 \ud3ec\ud2b8\uc744 \uc4f4 \ub3d9\ub8cc \ubb34\uc2dc (';'\uc73c\ub85c \ub098\ub214, \uc608 0;25) ConfigView.section.proxy.enable_socks.peer=\ub3d9\ub8cc \ud1b5\uc2e0 \ud504\ub85d\uc2dc \uc791\ub3d9 (\ub098\uac00\ub294 \uc5f0\uacb0\ub9cc) [\ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud568] ConfigView.section.proxy.peer.informtracker=\uc81c\ud55c\uc774 \uc788\ub294 \ub354\ub4ec\uc774\ub97c \uc54c\ub9bc ConfigView.section.proxy.socks.version=SOCKS \ubc84\uc804 PiecesView.legend.written=\uc4f0\uc784 PiecesView.legend.requested=\uc694\uad6c\ub428 PiecesView.legend.downloaded=\ub0b4\ub824\ubc1b\uae30\ub418\uace0 \uace7 \uc500 PiecesView.legend.incache=\ub370\uc774\ud130\uac00 \uce90\uc2dc\uc5d0 \uc788\uc74c PiecesView.typeItem.0=\ub290\ub9bc PiecesView.typeItem.1=\ube60\ub984 PiecesView.type=\uc885\ub958 Security.jar.tools_not_found=JAR \ud30c\uc77c\uc5d0 \uc11c\uba85\ud558\uc9c0 \ubabb\ud568 - %1\uc5d0\uc11c 'tools.jar'\ub97c \ucc3e\uc9c0 \ubabb\ud568. \uc0c1\uc138\ud55c \uc124\uba85\uc740 \ub3c4\uad6c->\uc120\ud0dd\uc0ac\ud56d->\ubcf4\uc548\uc744 \ubcf4\uc2ed\uc2dc\uc694. Security.jar.signfail=JAR \ud30c\uc77c\uc5d0 \uc11c\uba85\ud558\uc9c0 \ubabb\ud568 - %1 ConfigView.section.security.toolsinfo=\uc11c\uba85\ub41c JAR \ud30c\uc77c\ub4e4\uc740, \uc608\ub97c \ub4e4\uc5b4 (\uadf8\ub807\uac8c \ud558\ub3c4\ub85d \uad6c\uc131\ud588\uc744 \ub54c) Swing Web Interface\uc640 \uac19\uc740 \ucd94\uac00\uae30\ub2a5\ub4e4\uc744 \ub4b7\ubc1b\uce68\ud558\ub294\ub370 \uc4f0\uc785\ub2c8\ub2e4.\nJAR \ud30c\uc77c\ub4e4\uc5d0 \uc11c\uba85\ud558\ub824\uba74 Sun JDK(JRE \uc544\ub2d8)\ub97c \uc124\uce58\ud558\uc5ec\uc11c \uc788\ub294 'tools.jar' \ud30c\uc77c\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\uc5b4\uc57c \ud569\ub2c8\ub2e4.\nJRE\ub9cc \uc124\uce58\ub418\uc5c8\ub2e4\uba74 JDK\ub97c \uc124\uce58\ud558\uc2dc\uae30 \ubc14\ub78d\ub2c8\ub2e4.\nVuze ub294 \ud754\ud788 \ub2f9\uc2e0\uc5d0\uac8c \ud30c\uc77c\uc744 \ucc3e\uc544 \uc904 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uadf8\ub7ec\ub098 \uadf8\ub807\uc9c0 \ubabb\ud558\uba74 \ub4e4\uc5b4 \uc788\ub294 \ud3f4\ub354\ub97c \uc5ec\uae30\uc5d0 \ub69c\ub837\ud558\uac8c \uad6c\uc131\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. ConfigView.section.security.toolsdir='tools.jar'\uac00 \uc788\ub294 \ud3f4\ub354 ConfigView.section.security.choosetoolssavedir='tools.jar'\uac00 \uc788\ub294 \ud3f4\ub354\ub97c \uace0\ub974\uae30 authenticator.torrent=\ud1a0\ub7f0\ud2b8 ConfigView.section.proxy.peer.same=\ub354\ub4ec\uc774\uc640 \ub3d9\ub8cc \ud1b5\uc2e0 \ud504\ub85d\uc2dc\uc5d0 \uac19\uc740 \ud504\ub85d\uc2dc \uc124\uc815\uc744 \uc500 ConfigView.section.connection.network.max.simultaneous.connect.attempts=\ucd5c\ub300 \ub3d9\uc2dc \ub098\uac00\ub294 \uc5f0\uacb0 \uc2dc\ub3c4 [0: \ub098\uac00\ub294 \uc5f0\uacb0\uc774 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc74c] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Vuze uac00 \uc8fc\uc5b4\uc9c4 \uc2dc\uac04\uc5d0 \uc2dc\ub3c4\ud574\uc57c \ud558\ub294 \uc0c8 \ub098\uac00\ub294 \uc5f0\uacb0 \uc124\uc815\uc758 \ucd5c\ub300 \uc218.\n\uc8fc\uc758: Windows XP Service Pack 2 (SP2)\ub294 \uc2dc\uc2a4\ud15c \uc804\uccb4\uc5d0 \uac78\uccd0 10 \uac1c\uc758 \ub3d9\uc2dc \uc5f0\uacb0 \uc2dc\ub3c4\ub85c \uc81c\ud55c\ud569\ub2c8\ub2e4.\n\uae30\ubcf8\uac12\uc740 8\uc785\ub2c8\ub2e4. \uac12\uc774 0\uc774\uba74 \ub098\uac00\ub294 \uc5f0\uacb0\uc774 \uc804\ud600 \ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. ConfigView.section.file.perf.cache.size.explain=\uce90\uc2dc\ub294 \ub514\uc2a4\ud06c\uc5d0\uc11c \uc77d\uace0 \uc4f0\uae30\ub97c \uc904\uc774\ub824\uace0 \uc4f0\uc785\ub2c8\ub2e4. \ub2f9\uc2e0\uc774 \uc790\ubc14 \uc635\uc158 '-XX:MaxDirectMemorySize'\ub97c \uc368\uc11c \uce90\uc2dc\uc640 \ub124\ud2b8\uc6cc\ud06c \uc785\ucd9c\ub825\uc5d0 \uc4f8 \uba54\ubaa8\ub9ac\ub97c \ub69c\ub837\ud558\uac8c \uad6c\uc131\ud558\uace0 \uc788\uc9c0 \uc54a\ub2e4\uba74, \uc774 \uac12\uc744 \uc801\uc5b4\ub3c4 \ucd5c\ub300 \uac00\uc0c1 \uba38\uc2e0 \ud06c\uae30\ubcf4\ub2e4 \uc544\ub798\uc778 %1\ub85c \uc9c0\ucf1c \uac00\uc57c \ud569\ub2c8\ub2e4. \uc9c0\uae08\uc758 \ucd5c\ub300 \uac00\uc0c1 \uba38\uc2e0 \ud06c\uae30\ub294 %2\uc785\ub2c8\ub2e4. \uc774\uac83\uc744 \ubc14\uafb8\ub294 \ubc29\ubc95\uc758 \uc124\uba85\uc11c\ub294 %3\uc758 \uc704\ud0a4\uc704\ud0a4\uc5d0\uc11c MemoryUsage(\uba54\ubaa8\ub9ac \uc0ac\uc6a9)\uc744 \ubcf4\uc2ed\uc2dc\uc694. \ub611\ub611\ud55c \uc124\uc815\uc744 \uc4f0\uc9c0 \ubabb\ud558\uba74 'out of memory(\uba54\ubaa8\ub9ac \ubc16\uc73c\ub85c)' \uc624\ub958\uac00 \uc77c\uc5b4\ub0a0 \uac83\uc785\ub2c8\ub2e4. \uce90\uc2dc\uac00 32MB\ubcf4\ub2e4 \ud06c\uba74 \uc544\ub9c8 \uc9c0\ub098\uce5c \uac83\uc785\ub2c8\ub2e4. MyTorrentsView.menu.setSpeed.unlimit=\ubb34\uc81c\ud55c MyTorrentsView.menu.setSpeed.unlimited=\ubb34\uc81c\ud55c MyTorrentsView.menu.setSpeed.disable=\uc62c\ub9ac\uae30\ub97c \ud560 \uc218 \uc5c6\uc74c MyTorrentsView.menu.setSpeed.disabled=\uac00\ub2a5\ud558\uc9c0 \uc54a\uc74c MyTorrentsView.menu.setSpeed.in=\ucd1d \uc18d\ub3c4\uc774\uace0 MyTorrentsView.menu.setSpeed.slots=\uc790\ub9ac\ub85c \ud558\ub098\ub9c8\ub2e4 GeneralView.label.maxuploadspeed=\ucd5c\uace0 \uc62c\ub9ac\uae30 GeneralView.label.maxuploadspeed.tooltip=\ucd5c\uace0 \uc62c\ub9ac\uae30 \uc18d\ub3c4 [0: \ubb34\uc81c\ud55c] MyTorrents.items.UpSpeedLimit.disabled=\uc62c\ub9ac\uae30\ud560 \uc218 \uc5c6\uc74c MyTorrents.items.UpSpeedLimit.unlimited=\ubb34\uc81c\ud55c TableColumn.header.maxupspeed=\uc62c\ub9ac\uae30 \ucd5c\uace0 \uc18d\ub3c4 TableColumn.header.maxupspeed.info=\ud1a0\ub7f0\ud2b8\ub9c8\ub2e4\uc758 \uc62c\ub9ac\uae30 \ucd5c\uace0 \uc18d\ub3c4 ConfigView.section.file.perf.cache.enable.write=\ub514\uc2a4\ud06c \uc4f0\uae30\ub97c \uc904\uc774\uace0 \uc870\uac01 \uac80\uc0ac\uc5d0 \ud544\uc694\ud55c \ub514\uc2a4\ud06c \uc77d\uae30\ub3c4 \uc904\uc774\ub824\uace0 \ub0b4\ub824\ubc1b\uae30 \ub370\uc774\ud130\ub97c \uce90\uc2dc ConfigView.section.file.perf.cache.enable.read=\uc62c\ub9ac\uae30\ud560 \ub54c \ub514\uc2a4\ud06c \uc77d\uae30\ub97c \uc904\uc774\ub824\uace0 \uc55e\ubd80\ud130 \uc77d\uae30\ub97c \uc2e4\ud589 ConfigView.section.tracker.separatepeerids=\ub354\ub4ec\uc774\uc640 \ub370\uc774\ud130 \ud1b5\uc2e0\uc5d0\uc11c \ub2e4\ub978 \ub3d9\ub8cc \uc2e0\uc6d0\uc744 \uc4f0\uae30 ConfigView.section.tracker.separatepeerids.info=\uc775\uba85\uc774 \uc544\ub2cc \ub354\ub4ec\uc774 \uc5f0\uacb0\uc744 \uc4f0\uba74\uc11c \uc775\uba85\uc73c\ub85c \ub0b4\ub824\ubc1b\uae30/\ubfcc\ub9ac\uae30\ub97c \ud558\uba74\n\uc815\uccb4 \ubd88\uba85\uc758 \uc0ac\uc6a9\uc790\ub97c \ub298\ub9bd\ub2c8\ub2e4. ConfigView.section.interface.wavlocation=\uc18c\ub9ac \ucc3e\uc544\ubcf4\uae30 ConfigView.section.interface.wavlocation.info=\uc18c\ub9ac \ud30c\uc77c\uc744 \uace0\ub974\uac70\ub098 \uae30\ubcf8 \uc18c\ub9ac\ub85c \ube44\uc6cc \ub460 ConfigView.section.tracker.server=\uc11c\ubc84 ConfigView.section.tracker.client=\uc811\uc18d \ucef4\ud4e8\ud130 ConfigView.section.tracker.client.connecttimeout=\uc5f0\uacb0 \uc2dc\uac04 \uc81c\ud55c (\ucd08) ConfigView.section.tracker.client.readtimeout=\uc77d\uae30 \uc2dc\uac04 \uc81c\ud55c (\ucd08) MainWindow.menu.tools=\ub3c4\uad6c(&T) FilesView.path=\uc704\uce58 FilesView.fullpath=\uc804\uccb4 \uc704\uce58 \ubcf4\uae30 FilesView.remaining=\ub0a8\uc740 \uc870\uac01 TableColumn.header.trackername=\ub354\ub4ec\uc774 \uc774\ub984 TableColumn.header.trackername.info=\ub354\ub4ec\uc774 \uc54c\ub9bc \uc8fc\uc18c(Announce URL)\uc5d0 \ub530\ub978 \ub354\ub4ec\uc774\uc758 \uc774\ub984 ConfigView.group.override=\ubb34\uc2dc \uc120\ud0dd\uc0ac\ud56d ConfigView.section.file.perf.cache.notsmallerthan=(%1\ub85c \ubcf4\uc774\ub294) \uc774\ubcf4\ub2e4 \ub354 \uc791\uc740 \ud30c\uc77c\ub4e4\uc744 \uce90\uc2dc\ud558\uc9c0 \uc54a\uc74c PeersView.menu.blockupload=\uc62c\ub9ac\uae30 \ub9c9\uc74c PeersView.menu.kickandban=\ubab0\uc544\ub0c4 PeersView.menu.kickandban.reason=\uc190\uc218 \ubab0\uc544\ub0b8 \ub3d9\ub8cc PeersView.state=\uc0c1\ud0dc PeersView.state.info=\ub3d9\ub8cc \uc5f0\uacb0\uc758 \uc0c1\ud0dc PeersView.state.pending=\uac78\ub824 \uc788\uc74c PeersView.state.connecting=\uc5f0\uacb0\ud558\uace0 \uc788\uc74c PeersView.state.handshake=\uc5f0\uacb0 \uc815\ubcf4 \uc804\uc1a1\uc744 \uae30\ub2e4\ub9ac\uace0 \uc788\uc74c PeersView.state.established=\ub109\ub109\ud788 \ub9c8\ub828\ub428 ConfigView.section.tracker.processinglimits=\ucc98\ub9ac \uc81c\ud55c ConfigView.section.tracker.maxgettime=GET \ucc98\ub9ac\uc5d0 \ub4dc\ub294 \ucd5c\ub300 \uc2dc\uac04 (\ucd08) [0: \ubb34\uc81c\ud55c] ConfigView.section.tracker.maxgettime.info=\uc54c\ub9ac\uae30\uc640 \ubaa8\uc73c\uae30\uc5d0 \uc4f0\uc784 ConfigView.section.tracker.maxposttimemultiplier=POST \ucc98\ub9ac\uc5d0 \ub4dc\ub294 GET \uc2dc\uac04 \uacf1\uc218 [0: \ubb34\uc81c\ud55c] ConfigView.section.tracker.maxposttimemultiplier.info=\uc591\uc2dd \uc758\ub8b0\uc640 \uc62c\ub9ac\uae30\uc5d0 \uc4f0\uc784 ConfigView.section.tracker.maxthreads=\ud55c\uaebc\ubc88\uc5d0 \uc0dd\uae30\ub294 \ucd5c\ub300 \uc694\uad6c DownloadManager.error.operationcancancelled=\uc791\uc5c5\uc774 \ucde8\uc18c\ub428 Torrent.create.progress.cancelled=\uc791\uc5c5\uc774 \ucde8\uc18c\ub428 sharing.progress.cancel=\ucde8\uc18c wizard.maketorrents.autoopen=\ub9c8\uce58\uba74 \ubfcc\ub9b4 \ud1a0\ub7f0\ud2b8\ub97c \uc5f4\uae30 ConfigView.section.sharing.rescanenable=\ubc14\ub010 \uac83\ub4e4\uc744 \uacf5\uc720\ud558\ub824\ub294 \uc8fc\uae30\uc801\uc778 \ub2e4\uc2dc \ud6d1\uae30 \uc791\ub3d9 ConfigView.section.sharing.rescanperiod=\ub2e4\uc2dc \ud6d1\ub294 \uc8fc\uae30(secs) ConfigView.section.connection.advanced=\uace0\uae09 \ub124\ud2b8\uc6cc\ud06c \uc124\uc815 ConfigView.section.connection.advanced.mtu=\ud68c\uc120 \ucd5c\ub300 \uc804\uc1a1 \ub2e8\uc704(MTU) ConfigView.section.connection.advanced.mtu.tooltip=\ub124\ud2b8\uc6cc\ud06c\uc5d0\uc11c \ud55c \ud504\ub808\uc784\uc5d0 \uc804\uc1a1\ud560 \uc218 \uc788\ub294 \ud328\ud0b7\uc758 \ucd5c\ub300 \ud06c\uae30\nVuze \uc62c\ub9ac\uae30 \ud328\ud0b7 \ud0d1\uc7ac\ub7c9\uc744 \ucd5c\uc801\ud654\ud558\ub824\uace0 MTU-40(MSS)\uc744 \uc501\ub2c8\ub2e4.\n\uad8c\ud558\ub294 \uac12:\n 576 - \uc804\ud654 \uc811\uc18d \ubaa8\ub380\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc5f0\uacb0\n1492 - \uc0ac\uc6a9\uc790 \uc774\ub984 \ubc0f \uc554\ud638\ub97c \ud544\uc694\ub85c \ud558\ub294 \uad11\ub300\uc5ed \uc5f0\uacb0\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc5f0\uacb0 - \uc774\ub354\ub137\uc744 \ud1b5\ud55c \uc9c0\uc810\uac04 \ud504\ub85c\ud1a0\ucf5c(PPPoE)\n1500 - \ud56d\uc0c1 \ucf1c\uc838 \uc788\ub294 \uad11\ub300\uc5ed \uc5f0\uacb0\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc5f0\uacb0 - \ucf00\uc774\ube14 \ubaa8\ub380, DSL \ub610\ub294 LAN \uc5f0\uacb0 ConfigView.section.connection.advanced.SO_RCVBUF=\uc18c\ucf13 SO_RCVBUF \ud06c\uae30 [0: \uc6b4\uc601 \uccb4\uacc4 \uae30\ubcf8\uac12\uc744 \uc500] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=(\ubc14\uc774\ud2b8\ub85c \ubcf4\uc774\ub294) \ud45c\uc900 \uc18c\ucf13 SO_RCVBUF \uac12\uc744 \uc124\uc815\ud569\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4 TCP \uc218\uc2e0 \uc708\ub3c4\uc6b0 \ud06c\uae30\uc640 \ud06c\uae30 \uc870\uc815\uc774 \uc788\uc2b5\ub2c8\ub2e4.\nVuze ub294 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\uc740 \ucc44 \ub461\ub2c8\ub2e4. \uae30\ubcf8\uac12\uc740 \ubc11\uc744 \uc774\ub8e8\ub294 \uc6b4\uc601 \uccb4\uacc4\uc5d0\uc11c \uc4f0\uc774\ub294 \uac12\uc744 \ub73b\ud569\ub2c8\ub2e4.\n\uadc0\ub754: \ub9ac\ub205\uc2a4\uc5d0\uc11c\ub294 \uc8fc\uc5b4\uc9c4 \uac12\uc774 \ub450 \ubc30\uac00 \ub429\ub2c8\ub2e4. ConfigView.section.connection.advanced.SO_SNDBUF=\uc18c\ucf13 SO_SNDBUF \ud06c\uae30 [0: \uc6b4\uc601 \uccb4\uacc4 \uae30\ubcf8\uac12\uc744 \uc500] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=(\ubc14\uc774\ud2b8\ub85c \ubcf4\uc774\ub294) \ud45c\uc900 \uc18c\ucf13 SO_SNDBUF \uac12\uc744 \uc124\uc815\ud569\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4 TCP \uc1a1\uc2e0 \uc708\ub3c4\uc6b0 \ud06c\uae30\uac00 \uc788\uc2b5\ub2c8\ub2e4.\nVuze ub294 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\uc740 \ucc44 \ub461\ub2c8\ub2e4. \uae30\ubcf8\uac12\uc740 \ubc11\uc744 \uc774\ub8e8\ub294 \uc6b4\uc601 \uccb4\uacc4\uc5d0\uc11c \uc4f0\uc774\ub294 \uac12\uc744 \ub73b\ud569\ub2c8\ub2e4.\n\uadc0\ub754: \ub9ac\ub205\uc2a4\uc5d0\uc11c\ub294 \uc8fc\uc5b4\uc9c4 \uac12\uc774 \ub450 \ubc30\uac00 \ub429\ub2c8\ub2e4. ConfigView.section.interface.confirm_torrent_removal=\ud1a0\ub7f0\ud2b8\ub97c \uc9c0\uc6b8 \ub54c \ud655\uc778 \uba54\uc138\uc9c0 \uc0c1\uc790\ub97c \ubcf4\uc774\uae30 ConfigView.section.interface.confirm_torrent_removal.tooltip=\ub0b4 \ud1a0\ub7f0\ud2b8 \ubcf4\uc784\uc0c8\uc5d0\uc11c \ud1a0\ub7f0\ud2b8\ub97c \uc9c0\uc6b8 \ub54c \ud655\uc778\ud569\ub2c8\ub2e4. MyTorrentsView.confirm_torrent_removal=\uc815\ub9d0 \uc9c0\uc6b0\uaca0\uc2b5\ub2c8\uae4c?\n TableColumn.header.seed_to_peer_ratio=\uc528\uc557\uacfc \ub3d9\ub8cc\uc758 \ube44 TableColumn.header.seed_to_peer_ratio.info=\ucd1d \ub5bc\uc758 \uc528\uc557\uacfc \ub3d9\ub8cc\ub4e4\uc758 \ube44 PeersView.connected_time=\uc5f0\uacb0\ub41c \uc2dc\uac04 PeersView.connected_time.info=\ub3d9\ub8cc\uc640 \uc5f0\uacb0\ub41c \ucd1d \uc2dc\uac04 ConfigView.section.interface.display.add_torrents_silently=\uc7a0\uc790\ucf54 \ud1a0\ub7f0\ud2b8 \ub354\ud558\uae30 ConfigView.section.interface.display.add_torrents_silently.tooltip=Vuze \uc8fc \ucc3d\uc744 \ud65c\uc131\ud654\ud558\uc9c0 \uc54a\uace0 \ud1a0\ub7f0\ud2b8 \ub0b4\ub824\ubc1b\uae30\ub97c \ub354\ud569\ub2c8\ub2e4. TableColumn.header.maxdownspeed=\ub0b4\ub824\ubc1b\uae30 \ucd5c\uace0 \uc18d\ub3c4 TableColumn.header.maxdownspeed.info=\ud1a0\ub7f0\ud2b8\ub9c8\ub2e4\uc758 \ub0b4\ub824\ubc1b\uae30 \ucd5c\uace0 \uc18d\ub3c4 PeersGraphicView.title=\ub5bc ConfigView.section.tracker.passwordwebhttpsonly=HTTPS\ub85c\ub9cc \uc811\uadfc \ud5c8\uc6a9 TableColumn.header.torrentpath=\ud1a0\ub7f0\ud2b8 \uc704\uce58 TableColumn.header.torrentpath.info=\ub514\uc2a4\ud06c\uc5d0 \uc788\ub294 \ud1a0\ub7f0\ud2b8\uc758 \uc704\uce58 ConfigView.section.sharing.torrentcomment=\ub9cc\ub4e0 \ud1a0\ub7f0\ud2b8\uc5d0 \ub367\ub9d0 \uc791\uc131 ConfigView.label.copyanddeleteratherthanmove=\ud55c \uc791\uc5c5\uc5d0\uc11c \ubcf8\ub514 \ub370\uc774\ud130\ub97c \uc62e\uae30\uae30\ubcf4\ub2e4 \uc624\ud788\ub824 \ubcf5\uc0ac\ud558\uace0\uc11c \ubcf8\ub514 \ub370\uc774\ud130\ub97c \uc9c0\uc6b0\uae30 - \uba87\uba87 \ud30c\uc77c \uc2dc\uc2a4\ud15c\uc5d0\uc11c \ub370\uc774\ud130 \ubd84\uc2e4\uc744 \ud53c\ud558\ub3c4\ub85d \ub3c4\uc640\uc904 \uc218 \uc788\uc2b5\ub2c8\ub2e4. ConfigView.label.openstatsonstart=\uc2dc\uc791\ud560 \ub54c \ud1b5\uacc4 \uc5f4\uae30 swt.install.window.title=Vuze \ucd94\uac00\uae30\ub2a5 \uc124\uce58 \ud504\ub85c\uadf8\ub7a8 swt.install.window.ok=\uc124\uce58 swt.install.window.header=\ub2e4\uc74c \uad6c\uc131 \uc694\uc18c\ub4e4\uc744 \uc124\uce58\ud558\ub824\uace0 \uace8\ub790\uc2b5\ub2c8\ub2e4.: swt.uninstall.window.title=Vuze \ucd94\uac00\uae30\ub2a5 \uc9c0\uc6b0\uae30 \ud504\ub85c\uadf8\ub7a8 swt.uninstall.window.ok=\uc9c0\uc6b0\uae30 swt.uninstall.window.header=\ub2e4\uc74c \uad6c\uc131 \uc694\uc18c\ub4e4\uc744 \uc9c0\uc6b0\ub824\uace0 \uace8\ub790\uc2b5\ub2c8\ub2e4.: installPluginsWizard.title=\ucd94\uac00\uae30\ub2a5 \uc124\uce58 installPluginsWizard.mode.title=\uc124\uce58 \ubc29\ubc95\uc744 \uace0\ub974\uc2ed\uc2dc\uc694. installPluginsWizard.mode.list=sourceforge.net\uc758 \ubaa9\ub85d\uc73c\ub85c installPluginsWizard.list.title=\uc124\uce58\ud560 \uc218 \uc788\ub294 \ucd94\uac00\uae30\ub2a5 \ubaa9\ub85d installPluginsWizard.list.loading=\ucd94\uac00\uae30\ub2a5 \ubaa9\ub85d\uc744 \ubd88\ub7ec\uc624\ub294 \ub3d9\uc548 \uae30\ub2e4\ub9ac\uc2ed\uc2dc\uc694. installPluginsWizard.list.loaded=\uc124\uce58\ud558\ub824\ub294 \ucd94\uac00\uae30\ub2a5\uc744 \uace0\ub974\uc2ed\uc2dc\uc694. installPluginsWizard.list.name=\uc774\ub984 installPluginsWizard.list.version=\ubc84\uc804 installPluginsWizard.list.description=\ucd94\uac00\uae30\ub2a5\uc758 \uc124\uba85 installPluginsWizard.finish.title=\uc9c4\ud589\ud558\uace0 \uc788\ub294 \uc124\uce58 installPluginsWizard.finish.explanation=\uc120\ud0dd\ud55c \ucd94\uac00\uae30\ub2a5\ub4e4\uc740 \uc5c5\ub370\uc774\ud2b8 \ub3c4\uc6b0\ubbf8\ub97c \uc368\uc11c \uc124\uce58\ub420 \uac83\uc785\ub2c8\ub2e4.\n\n\ub290\uae0b\ud558\uac8c \uae30\ub2e4\ub9ac\uba74 \uae08\ubc29 \ub098\ud0c0\ub0a0 \uac83\uc785\ub2c8\ub2e4.\n\n\uc9c4\ud589 \uae30\ub85d\uc744 \ubcf4\ub824\uba74 \uc0c1\ud0dc \ud45c\uc2dc\uc904\uc758 \uc67c\ucabd\uc744 \ub354\ube14 \ud074\ub9ad\ud558\uc2ed\uc2dc\uc694. installPluginsWizard.details.loading=\uc0c1\uc138 \uc815\ubcf4\ub97c \ubd88\ub7ec\uc624\uace0 \uc788\uc2b5\ub2c8\ub2e4. \uae30\ub2e4\ub9ac\uc2ed\uc2dc\uc694... installPluginsWizard.mode.file=\ud30c\uc77c\ub85c installPluginsWizard.installMode.title=\uc124\uce58 \uc591\uc2dd\uc744 \uace0\ub974\uc2ed\uc2dc\uc694. installPluginsWizard.installMode.user=\ub2f9\uc2e0\ub9cc \uc4f0\uac8c\ub054 \ucd94\uac00\uae30\ub2a5\uc744 \uc124\uce58 installPluginsWizard.installMode.shared=\ubaa8\ub4e0 \uc0ac\uc6a9\uc790\ub4e4\uc774 \uc4f0\uac8c\ub054 \ucd94\uac00\uae30\ub2a5\uc744 \uc124\uce58 installPluginsWizard.file.title=\uc124\uce58\ud560 \ucd94\uac00\uae30\ub2a5\uc744 \ucc3e\uc544\ubcf4\uc2ed\uc2dc\uc694. installPluginsWizard.file.file=\ud30c\uc77c: installPluginsWizard.file.invalidfile=\uc774 \ud30c\uc77c\uc740 Vuze \ucd94\uac00\uae30\ub2a5\uc774 \uc544\ub2d9\ub2c8\ub2e4. installPluginsWizard.file.browse=\ucc3e\uc544\ubcf4\uae30... uninstallPluginsWizard.title=\ucd94\uac00\uae30\ub2a5 \uc81c\uac70 uninstallPluginsWizard.list.title=\uc124\uce58\ub41c \ucd94\uac00\uae30\ub2a5 \ubaa9\ub85d uninstallPluginsWizard.list.loaded=\uc81c\uac70\ud558\ub824\ub294 \ucd94\uac00\uae30\ub2a5\uc744 \uace0\ub974\uc2ed\uc2dc\uc694. installPluginsWizard.list.nullversion=\ubc84\uc804 \uc5c6\uc74c uninstallPluginsWizard.finish.title=\uc9c4\ud589\ud558\uace0 \uc788\ub294 \uc81c\uac70 uninstallPluginsWizard.finish.explanation=\uc0ac\uc6a9\ud558\uace0 \uc788\ub294 \ucd94\uac00\uae30\ub2a5\ub4e4\uc740 \uc5c5\ub370\uc774\ud2b8 \ub3c4\uc6b0\ubbf8\ub97c \uc368\uc11c \uc81c\uac70\ub420 \uac83\uc785\ub2c8\ub2e4. MainWindow.menu.plugins.installPlugins=\uc124\uce58 \ub9c8\ubc95\uc0ac... MainWindow.menu.plugins.uninstallPlugins=\uc81c\uac70 \ub9c8\ubc95\uc0ac... ConfigView.section.ipfilter.totalIPs=\uc804\uccb4\uc5d0\uc11c %1 IP\ub4e4\uc744 \ub9c9\uc558\uc2b5\ub2c8\ub2e4. \uc804\uccb4\ub294 \uc778\ud130\ub137\uc758 %2\uc785\ub2c8\ub2e4. update.instance.install=\uc124\uce58\ub97c \uac80\uc0ac\ud558\uace0 \uc788\uc74c update.instance.uninstall=\uc81c\uac70\ub97c \uac80\uc0ac\ud558\uace0 \uc788\uc74c update.instance.update=\uc5c5\ub370\uc774\ud2b8\ub97c \uac80\uc0ac\ud558\uace0 \uc788\uc74c MainWindow.status.update.tooltip=\uc9c4\ud589 \uc815\ubcf4\ub97c \ubcf4\ub824\uba74 \ub354\ube14 \ud074\ub9ad updater.progress.window.title=\uc9c0\uae08\uc758 \uc124\uce58 \uc791\uc5c5 updater.progress.window.info=\uc544\uc9c1 \ud574\uacb0\ud558\uc9c0 \ubabb\ud55c \ubaa8\ub4e0 \uc791\uc5c5\uc744 \ub05d\ub0b4\ub824\uba74 '\uadf8\ub9cc\ub460'\uc744 \ub204\ub974\uc2ed\uc2dc\uc694. Button.abort=\uadf8\ub9cc\ub460 ConfigView.section.ipfilter.enablebanning=\ud55c\uacb0\uac19\uc774 \uc545\uc131 \ub370\uc774\ud130\ub97c \ubcf4\ub0b4\ub294 \ub3d9\ub8cc \ub9c9\uc74c Network.alert.acceptfail=%1, %2 \ud3ec\ud2b8\uc5d0\uc11c \ub108\ubb34 \ub9ce\uc774 \uc787\ub530\ub978 \uc798\ubabb\ub41c \uac83\ub4e4\uc774 \uc77c\uc5b4\ub0ac\uc2b5\ub2c8\ub2e4. - \ucc98\ub9ac\uac00 \ubc84\ub824\uc9d0. \uc774 \ud3ec\ud2b8\uc758 \ubc29\ud654\ubcbd \uc124\uc815\uc744 \uc0b4\ud3b4\ubcf4\uace0 \ub098\uc11c \uc218\uc2e0 \uc5f0\uacb0\uc5d0\uc11c \uc774 \ud3ec\ud2b8\uac00 \uc791\ub3d9\ud558\ub3c4\ub85d \ud558\uc2ed\uc2dc\uc694. MyShares.column.category=\ubd84\ub958 UpdateWindow.restartLater=\ub098\uc911\uc5d0 \ub2e4\uc2dc \uc2dc\uc791 MainWindow.menu.file.restart=Vuze \ub2e4\uc2dc \uc2dc\uc791 MainWindow.dialog.restartconfirmation.title=Vuze\ub97c \ub2e4\uc2dc \uc2dc\uc791\ud558\uaca0\uc2b5\ub2c8\uae4c? MainWindow.dialog.restartconfirmation.text=Vuze\ub97c \uc815\ub9d0 \ub2e4\uc2dc \uc2dc\uc791\ud558\uaca0\uc2b5\ub2c8\uae4c? deletetorrent.message1=\ub2e4\uc74c\uc758 \ud1a0\ub7f0\ud2b8\ub97c \uc9c0\uae08 \uc9c0\uc6b0\ub824\uace0 \ud569\ub2c8\ub2e4:\n deletetorrent.message2=\n\uc815\ub9d0 \uacc4\uc18d\ud558\uaca0\uc2b5\ub2c8\uae4c? ConfigView.label.prioritizemostcompletedfiles=\uac00\uc7a5 \ub9ce\uc774 \ub05d\ub9c8\uce5c \ud30c\uc77c\uc744 \uc6b0\uc120\uc2dc\ud0b4 splash.plugin.init=\ucd94\uac00\uae30\ub2a5\uc744 \uc900\ube44\ud558\uace0 \uc788\uc74c: splash.plugin.UIinit=GUI \ucd94\uac00\uae30\ub2a5\uc744 \uc900\ube44\ud558\uace0 \uc788\uc74c: %1 ConfigView.section.style.osx_small_fonts=\uc791\uc740 \uae00\uaf34\uc744 \uc500 [\ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud568] ConfigView.section.tracker.tcpnonblocking=TCP \ub354\ub4ec\uc774 \ucc98\ub9ac\uc5d0 \ub9c9\uc9c0 \uc54a\uc744 \uc785\ucd9c\ub825\uc744 \uc501\ub2c8\ub2e4. \uc774 \uc120\ud0dd\uc0ac\ud56d\uc744 \uace0\ub974\ub824\uba74 \ub2e4\ub978 \ud3ec\ud2b8\uc5d0\uc11c \ub3cc\uc544\uac08 \ub354\ub4ec\uc774 \uc6f9\uc774 \ud544\uc694\ud569\ub2c8\ub2e4. \uc2dc\ud5d8\uc801\uc784 ConfigView.section.tracker.nonblocking=\ub9c9\uc9c0 \uc54a\uae30 \uc120\ud0dd\uc0ac\ud56d ConfigView.section.tracker.nonblockingconcmax=\ud55c\uaebc\ubc88\uc5d0 \uc0dd\uae30\ub294 \ucd5c\ub300 \uc5f0\uacb0 [0: \ubb34\uc81c\ud55c] MyTorrentsView.menu.exportmenu=\ub0b4\ubcf4\ub0b4\uae30 MyTorrentsView.menu.exporttorrent=\ud1a0\ub7f0\ud2b8... ConfigView.group.scrape=\ubaa8\uc73c\uae30 ConfigView.section.tracker.client.scrapeinfo=\ubaa8\uc73c\uae30\ub97c \ud558\uc9c0 \uc54a\uc73c\uba74 \ub9ce\uc740 \ud1a0\ub7f0\ud2b8 \ub300\uae30 \uaddc\uce59\ub4e4\uc774 \ubaa8\uc73c\uae30 \ub354\ub4ec\uc774\ub4e4\ub85c \ub418\ucc3e\ub294 \ub5bc \uc815\ubcf4\uc5d0 \uc758\uc9c0\ud558\ub294 \ub9cc\ud07c \uc791\ub3d9\ud558\uc9c0 \ubabb\ud558\uac8c \ud560 \uac83\uc785\ub2c8\ub2e4. ConfigView.section.tracker.client.scrapeenable=\ubaa8\uc73c\uae30 \uc791\ub3d9 ConfigView.section.tracker.client.scrapestoppedenable=\uc6c0\uc9c1\uc774\uace0 \uc788\uc9c0 \uc54a\uc740 \ud1a0\ub7f0\ud2b8\ub4e4 \ubaa8\uc73c\uae30 Scrape.status.disabled=\ubaa8\uc744 \uc218 \uc5c6\uc74c MyTorrentsView.menu.explore=\ud30c\uc77c \ubcf4\uc774\uae30 MyTorrentsView.menu.explore._mac=\uac80\uc0c9\uc73c\ub85c \ubcf4\uc774\uae30 MyTorrentsView.menu.explore._windows=\ud0d0\uc0c9\uae30\ub85c \ubcf4\uc774\uae30 wizard.maketorrents.autohost=\ubcf8\ub798 \uac16\ucdb0\uc9c4 \ub354\ub4ec\uc774\uc5d0 \ud1a0\ub7f0\ud2b8\ub97c \ud638\uc2a4\ud2b8\ud558\uae30 ConfigView.label.overrideip=\ub354\ub4ec\uc774 \uc54c\ub9bc IP \uc8fc\uc18c \ubb34\uc2dc ConfigView.label.overrideip.tooltip=\uc5b4\ub5a4 IP \uc8fc\uc18c\uc5d0\uc11c \ub098\uac00\ub294 \ud328\ud0b7\uacfc \ub2e4\ub978 IP \uc8fc\uc18c\uc758 \ub354\ub4ec\uc774\ub97c \uc54c\ub824 \uc90d\ub2c8\ub2e4. \uc120\ud0dd\uc0ac\ud56d\uc744 \uc4f0\uc9c0 \uc54a\uc73c\ub824\uba74 \ube44\uc6cc \ub450\uc2ed\uc2dc\uc694. ConfigView.section.connection.group.networks=\ub124\ud2b8\uc6cc\ud06c ConfigView.section.connection.group.networks.info=\ub3d9\ub8cc-\ub3d9\ub8cc \ub370\uc774\ud130 \uc804\uc1a1\uc5d0 \uae30\ubcf8\uc73c\ub85c \ud5c8\uc6a9\ub41c \ub124\ud2b8\uc6cc\ud06c\ub4e4\uc744 \uace0\ub974\uc2ed\uc2dc\uc694 ConfigView.section.connection.networks.prompt=\uc775\uba85\uc758 \ub354\ub4ec\uc774\ub85c \ub0b4\ub824\ubc1b\uae30\uac00 \ub354\ud574\uc9c8 \ub54c \uace0\ub974\uae30\ub97c \ub744\uc6c0 ConfigView.section.connection.networks.Public=\uacf5\uacf5\uc758 IP \ub124\ud2b8\uc6cc\ud06c (\uc775\uba85 \uc544\ub2d8) ConfigView.section.connection.networks.I2P=I2P \ub124\ud2b8\uc6cc\ud06c ConfigView.section.connection.networks.Tor=The Onion Router (Tor) \ub124\ud2b8\uc6cc\ud06c TableColumn.header.networks=\ub124\ud2b8\uc6cc\ud06c TableColumn.header.networks.info=\ub3d9\ub8cc-\ub3d9\ub8cc \ub370\uc774\ud130 \ud1b5\uc2e0\uc774 \ud5c8\uc6a9\ub41c \ub124\ud2b8\uc6cc\ud06c Scrape.status.networkdisabled=\ub124\ud2b8\uc6cc\ud06c\uac00 \uc791\ub3d9\ud558\uc9c0 \uc54a\uc74c ConfigView.section.tracker.server.group.networks=\ub124\ud2b8\uc6cc\ud06c ConfigView.section.tracker.server.group.networks.info=\ub354\ub4ec\uc774\uac00 \ub3d9\ub8cc\ub4e4\uc744 \ud5c8\uc6a9\ud560 \ub124\ud2b8\uc6cc\ud06c\ub4e4\uc744 \uace0\ub974\uc2ed\uc2dc\uc694 window.networkselection.title=\ub124\ud2b8\uc6cc\ud06c \uace0\ub974\uae30 window.networkselection.info=\uc544\ub798 \uc2e4\ub9b0 \ud1a0\ub7f0\ud2b8\ub4e4\uc740 \ub2e4\uc74c \ub124\ud2b8\uc6cc\ud06c\ub4e4\uc744 \uc9c0\uc6d0\ud558\ub294 \ub354\ub4ec\uc774\ub4e4\uc774 \uc788\uc2b5\ub2c8\ub2e4.\n\ub354\ub4ec\uc774\uc640 \ub3d9\ub8cc \ud1b5\uc2e0\uc5d0 \uc4f8 \uac83\ub4e4\uc744 \uace0\ub974\uc2ed\uc2dc\uc694.\n\uacf5\uacf5\uc758 \ucef4\ud4e8\ud130\ub4e4\uc744 \uc9c0\uc6d0\ud558\ub294 \uc775\uba85\uc758 \ub354\ub4ec\uc774\ub77c\uba74 \uc775\uba85\uacfc \uacf5\uacf5\uc758 \ub124\ud2b8\uc6cc\ud06c \ub458 \ub2e4 \uc791\ub3d9\uc2dc\ud0a4\uc2ed\uc2dc\uc694.\n\uacf5\uac1c \ub124\ud2b8\uc6cc\ud06c\ub97c \uc791\ub3d9\uc2dc\ud0a4\uba74 \uc775\uba85\uc73c\ub85c \uc791\ub3d9\ud558\uc9c0 \uc54a\uc73c\ub2c8 \uc8fc\uc758\ud558\uc138\uc694! window.networkselection.description=\ud1a0\ub7f0\ud2b8: plugins.basicview.clear=\uc9c0\uc6b0\uae30 ConfigView.section.connection.group.peersources=\ub3d9\ub8cc \uc18c\uc2a4 ConfigView.section.connection.group.peersources.info=\ub3d9\ub8cc \uc5f0\uacb0\ub4e4\uc5d0 \uae30\ubcf8\uc73c\ub85c \ud5c8\uc6a9\ub41c \uc18c\uc2a4\ub4e4\uc744 \uace0\ub974\uc2ed\uc2dc\uc694. ConfigView.section.connection.peersource.Tracker=\ub354\ub4ec\uc774\uc5d0\uc11c ConfigView.section.connection.peersource.DHT=\ubd84\uc0b0\ub41c \ub354\ub4ec\uae30 ConfigView.section.connection.peersource.PeerExchange=\ub2e4\ub978 \ub3d9\ub8cc\uc5d0\uac8c \ubc1b\uc74c ConfigView.section.connection.peersource.Plugin=\ucd94\uac00\uae30\ub2a5\uc73c\ub85c \ub354\ud574\uc9d0 ConfigView.section.connection.peersource.Incoming=\ub4e4\uc5b4\uc624\ub294 \uc5f0\uacb0 PeersView.source=\uc18c\uc2a4 PeersView.source.info=\uc774 \ub3d9\ub8cc\uc758 \uc18c\uc2a4 TableColumn.header.peersources=\ub3d9\ub8cc \uc18c\uc2a4 TableColumn.header.peersources.info=\ub3d9\ub8cc \uc5f0\uacb0\uc758 \uc218\ub9bd\uc774 \ud5c8\uc6a9\ub41c \ub3d9\ub8cc \uc18c\uc2a4 wizard.tracker.dht=\ubd84\uc0b0\ub428 (Vuze \ud074\ub77c\uc774\uc5b8\ud2b8 \ud504\ub85c\uadf8\ub7a8\ub9cc) MyTorrentsView.menu.advancedmenu=\uace0\uae09 MyTorrentsView.menu.networks=\ub124\ud2b8\uc6cc\ud06c MyTorrentsView.menu.peersource=\ub3d9\ub8cc \uc18c\uc2a4 ConfigView.section.sharing.permitdht=\ub354\ub4ec\uc774\ub97c \uc4f8 \uc218 \uc5c6\uc744 \ub54c \ubd84\uc0b0\ub41c \ub354\ub4ec\uae30\ub97c \ud5c8\uc6a9 ConfigView.section.sharing.protocol=\uacf5\uc720\ub41c \uc790\uc6d0\ub4e4\uc758 \ud504\ub85c\ud1a0\ucf5c PeersView.Messaging=\ud1b5\uc2e0 PeersView.Messaging.info=\uace0\uae09 \ud1b5\uc2e0 API\ub97c \uc9c0\uc6d0 ConfigView.label.queue.newseedsmovetop=\uc0c8\ub85c \ub9c8\uce5c \ud1a0\ub7f0\ud2b8\ub4e4\uc744 \ubfcc\ub9ac\uae30 \ubaa9\ub85d\uc758 \uc55e\uc73c\ub85c \uc62e\uae40 ConfigView.label.seeding.firstPriority.ignore.info=\uc774 \uaddc\uce59\ub4e4\uc744 \uc4f0\ub294 \uac83\uc774 \ub0b4\ub824\ubc1b\uae30\uac00 \ub05d\ub098\uc790\ub9c8\uc790 \ud1a0\ub7f0\ud2b8\ub97c\n\uba48\ucd94\uac8c \ud560 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc8fc\uc758\ud558\uc138\uc694. ConfigView.label.seeding.firstPriority.ignore=\ub2e4\uc74c\uc758 \ud1a0\ub7f0\ud2b8\uc5d0 \uc704\uc758 \uccab\ubc88\uc9f8 \uc6b0\uc120\uad8c \uaddc\uce59\ub4e4\uc744 \ubb34\uc2dc: ConfigView.label.seeding.firstPriority.ignoreSPRatio=\uc528\uc557\uacfc \ub3d9\ub8cc \ube44\uac00 \ub2e4\uc74c\uc744 \ub118\uc740 \ud1a0\ub7f0\ud2b8\ub4e4 ConfigView.label.seeding.firstPriority.ignore0Peer=0 \ub3d9\ub8cc\uc778 \ud1a0\ub7f0\ud2b8\ub4e4 ConfigView.section.tracker.sendjavaversionandos=Java \ubc84\uc804\uacfc OS \uc774\ub984 \ubcf4\ub0b4\uae30 MagnetPlugin.contextmenu.exporturi=Magnet URI\ub97c \ud074\ub9bd\ubcf4\ub4dc\ub85c \ubcf5\uc0ac ConfigView.section.plugins.dht=\ubd84\ud3ec\ub41c \ub370\uc774\ud130\ubca0\uc774\uc2a4 dht.info=\uc774 \ucd94\uac00\uae30\ub2a5\uc740 \ub2e4\ub978 \uac83\ub4e4 \uc911\uc5d0\uc11c \ubd84\uc0b0\ub41c \ub354\ub4ec\uae30\ub97c \uc9c0\uc6d0\ud569\ub2c8\ub2e4. - \uc774\uac83\uc744 \uba48\ucd94\uba74 \ub0b4\ub824\ubc1b\uae30\ud558\ub294 \ub2a5\ub825\uc774 \uc904\uc5b4\ub4e4 \uac83\uc785\ub2c8\ub2e4. dht.enabled=\ubd84\ud3ec\ub41c \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc791\ub3d9 dht.portdefault=\uae30\ubcf8 \ud3ec\ud2b8 \uc500 dht.port=\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 UDP \ud3ec\ud2b8 dht.execute.command=\uc9c4\ub2e8 \uba85\ub839 dht.execute.info=\uba85\ub839\uc744 \uc2e4\ud589\ud558\ub824\uba74 \ub204\ub974\uc2ed\uc2dc\uc694 dht.execute=\uc2e4\ud589 dht.logging=\ud65c\ub3d9\uc758 \uae30\ub85d \uc791\ub3d9 ConfigView.section.plugins.dhttracker=\ubd84\ud3ec\ub41c \ub354\ub4ec\uc774 dhttracker.tracknormalwhenoffline=\ub354\ub4ec\uc774\ub97c \uc4f8 \uc218 \uc5c6\uc744 \ub54c \ubcf4\ud1b5 \ud1a0\ub7f0\ud2b8\ub4e4\uc744 \ub354\ub4ec\uae30\ub9cc \ud568 ConfigView.section.file.nativedelete._mac=\ud30c\uc77c\ub4e4\uc744 \uc9c0\uc6b8 \ub54c \ud734\uc9c0\ud1b5 \uc4f0\uae30 ConfigView.section.file.nativedelete._windows=\uc9c0\uc6b4 \ud30c\uc77c\ub4e4\uc744 \ud734\uc9c0\ud1b5\uc73c\ub85c \uc62e\uae30\uae30 ConfigView.section.logging.generatediagnostics=\uc0dd\uc131 ConfigView.section.logging.statsinfo=\uc0c1\ud0dc \uc815\ubcf4 \ub9cc\ub4e4\uae30 ConfigView.section.logging.generatediagnostics.info=\uc124\uc815\ub418\uc5c8\uc73c\uba74, \uc9c4\ub2e8 \uc815\ubcf4\ub97c \uc0dd\uc131\ud558\uace0 \ud074\ub9bd\ubcf4\ub4dc\uc640 \uae30\ub85d \ud30c\uc77c\ub85c \ubcf5\uc0ac\ud569\ub2c8\ub2e4 ConfigView.section.sharing.privatetorrent=\uac1c\uc778\uc758 \ud1a0\ub7f0\ud2b8 - \ub354\ub4ec\uc774\uc5d0\uc11c \ubc1b\uc544\ub4e4\uc778 \ub3d9\ub8cc\ub4e4\ub9cc MainWindow.menu.tools.nattest=NAT / \ubc29\ud654\ubcbd \uac80\uc0ac(&N) Button.apply=\uc801\uc6a9 Button.close=\ub2eb\uae30 window.welcome.title=Vuze %1\uc5d0 \uc5b4\uc11c \uc624\uc2ed\uc2dc\uc694. #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=\ubc1c\ud45c \uae30\ub85d dht.reseed.label=\ubcf4\ud1b5 \ubd84\ud3ec\ub41c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \ub2e4\uc2dc \ubfcc\ub9ac\uae30\ub294 \ud544\uc694\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uadf8\ub7ec\ub098 \uc811\ucd09\uc758 \uc218\uac00 \ub0ae\uc73c\uba74 \ub2e4\uc2dc \uc644\uc804\ud558\uac8c \ud558\ub294 \ub370\uc5d0 \uc774\uac83\uc744 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n\uc5f0\uacb0\ub41c \ub3d9\ub8cc\ub4e4\uc744 \uc2a4\uc2a4\ub85c \ub04a\uc73c\ub824\uba74 \ube44\uc6cc \ub450\uac70\ub098 \uc54c\ub824\uc9c4 \ub3d9\ub8cc\uc5d0\uc11c \uba85\ucf8c\ud558\uac8c \ube60\uc838\ub098\uc62c IP\uc640 \ud3ec\ud2b8\ub97c \uc368\ub123\uc73c\uc2ed\uc2dc\uc694. dht.reseed.group=\ub2e4\uc2dc \ubfcc\ub9ac\uae30 dht.reseed.ip=IP \uc8fc\uc18c dht.reseed.port=\ud3ec\ud2b8 dht.reseed=\ub2e4\uc2dc \ubfcc\ub9ac\uae30 dht.reseed.info=\ub370\uc774\ud130\ubca0\uc774\uc2a4\ub97c \ub2e4\uc2dc \ubfcc\ub9ac\uae30 dht.diagnostics.group=\uc9c4\ub2e8 DHTView.title.full=\ubd84\ud3ec\ub41c \ub370\uc774\ud130\ubca0\uc774\uc2a4 DHTView.title.fullcvs=\ubd84\ud3ec\ub41c CVS \ub370\uc774\ud130\ubca0\uc774\uc2a4 DHTView.general.title=\uc77c\ubc18 DHTView.general.uptime=\uc62c\ub9ac\uae30 \uc2dc\uac04: DHTView.general.users=\uc0ac\uc6a9\uc790: DHTView.general.nodes=\ub178\ub4dc: DHTView.general.leaves=\ud5c8\uac00: DHTView.general.contacts=\uc811\ucd09: DHTView.general.replacements=\ubc18\ud658: DHTView.general.live=\uc720\ud6a8: DHTView.general.unknown=\uc54c \uc218 \uc5c6\uc74c: DHTView.general.dying=\uc8fd\uc74c: DHTView.transport.title=\uc138\ubd80 \uc804\uc1a1 DHTView.transport.packets=\ud328\ud0b7 DHTView.transport.bytes=\ubc14\uc774\ud2b8 DHTView.transport.received=\ubc1b\uc74c DHTView.transport.sent=\ubcf4\ub0c4 DHTView.transport.in=\ub4e4\uc5b4\uc624\uae30: DHTView.transport.out=\ub098\uac00\uae30: DHTView.operations.title=\uc138\ubd80 \uc791\ub3d9 DHTView.operations.sent=\ubcf4\ub0c4 DHTView.operations.ok=\uc88b\uc74c DHTView.operations.failed=\uc2e4\ud328 DHTView.operations.received=\ubc1b\uc74c DHTView.operations.ping=\ud551 DHTView.operations.findNode=\ub178\ub4dc \ucc3e\uae30 DHTView.operations.findValue=\uc720\uc6a9\uc131 \ucc3e\uae30 DHTView.operations.store=\uc800\uc7a5 DHTView.activity.title=\ud65c\ub3d9 DHTView.activity.status=\uc0c1\ud0dc DHTView.activity.status.true=\ub300\uae30 DHTView.activity.status.false=\ub3cc\uace0 \uc788\uc74c DHTView.activity.type=\uc885\ub958 DHTView.activity.type.1=\ub0b4\ubd80 \uc5bb\uae30 DHTView.activity.type.2=\uc678\ubd80 \uc5bb\uae30 DHTView.activity.type.3=\ub0b4\ubd80 \uc8fc\uae30 DHTView.activity.type.4=\uc678\ubd80 \uc8fc\uae30 DHTView.activity.target=\ubaa9\ud45c DHTView.activity.details=\uc124\uba85 DHTView.db.title=\ub370\uc774\ud130\ubca0\uc774\uc2a4 DHTView.db.keys=\uc694\uc18c DHTView.db.values=\uc720\uc6a9\uc131 DHTView.db.local=\ub85c\uceec DHTView.db.direct=\uc9c1\uc811 DHTView.db.indirect=\uac04\uc811 DHTView.db.divfreq=\ub3c4\uc218 \ubd84\ud560 DHTView.db.divsize=\ud06c\uae30 \ubd84\ud560 MainWindow.dht.status.tooltip=\ubd84\ud3ec\ub41c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \ub3cc\uc544\uac00\uba74 \uc774\uac83\uc740 \uc9c0\uae08 \uc628\ub77c\uc778 \uc0ac\uc6a9\uc790\uc758 \uc608\uc0c1 \uc218\ub97c \ubcf4\uc785\ub2c8\ub2e4. MainWindow.dht.status.disabled=\uc791\ub3d9\ud558\uc9c0 \uc54a\uc74c MainWindow.dht.status.failed=\uc2e4\ud328\ud568 MainWindow.dht.status.initializing=\uc900\ube44\ud558\uace0 \uc788\uc74c MainWindow.dht.status.users=%1 \uc0ac\uc6a9\uc790 MainWindow.dht.status.unreachable=DHT \ubc29\ud654\ubcbd MyTorrentsView.menu.setUpSpeed=\uc62c\ub9ac\uae30 \uc18d\ub3c4 \uc815\ud558\uae30 MyTorrentsView.menu.setDownSpeed=\ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4 \uc815\ud558\uae30 ConfigView.section.tracker.client.showwarnings=\ub354\ub4ec\uc774\ub4e4\uc5d0\uac8c\uc11c \ubcf4\uace0\ub41c \uacbd\uace0 \uba54\uc2dc\uc9c0\ub4e4 \ubcf4\uc774\uae30 dht.advanced=\uace0\uae09 \uc124\uc815 \uc791\ub3d9 dht.advanced.group=\uace0\uae09 \uc124\uc815 dht.advanced.label=\ubc29\ubc95\uc744 \ub611\ubc14\ub85c \uc54c \ub54c\ub9cc \uc774 \uac12\ub4e4\uc744 \uace0\uce58\uc2ed\uc2dc\uc694 dht.override.ip=\uc678\ubd80 IP \uc8fc\uc18c \ubb34\uc2dc ConfigView.section.logging.loggerenable=\uae30\ub85d \ub0a8\uae30\uae30 \uc791\ub3d9 ConfigView.section.ipfilter.blockbanning=\ud55c \ud1a0\ub9c9\uc5d0\uc11c \uc801\uc5b4\ub3c4 \uba87 \uac1c \uc815\ub3c4\ub97c \ubab0\uc544\ub0b4\uba74 256 \uac1c \uc8fc\uc18c\uc758 \ud55c \ud1a0\ub9c9\uc744 \ubab0\uc544\ub0c5\ub2c8\ub2e4 MyTrackerView.passive=\uc218\ub3d9 TableColumn.header.swarm_average_speed=\ub5bc \ud3c9\uade0 \uc18d\ub3c4 TableColumn.header.swarm_average_speed.info=\ub5bc\uc5d0 \uc788\ub294 \ub3d9\ub8cc\ub4e4\uc758 \ud3c9\uade0 \uc18d\ub3c4 TableColumn.header.comment=\ub367\ub9d0 TableColumn.header.comment.info=\ub0b4\ub824\ubc1b\uc740 \uc790\ub8cc\uc758 \uc0ac\uc6a9\uc790 \ub367\ub9d0 TableColumn.header.commenticon=\ub367\ub9d0 TableColumn.header.commenticon.info=\uc790\ub8cc\uc5d0 \uc0ac\uc6a9\uc790 \uc785\ub825 \ub367\ub9d0\uc774 \uc788\uc744\uc2dc \uc544\uc774\ucf58 \ud45c\uc2dc MyTrackerView.category=\ubd84\ub958 MainWindow.menu.file.open.torrentfortracking=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c... (\ub354\ub4ec\uae30\ub9cc) VivaldiView.title.full=\ube44\ubc1c\ub514 \ubcf4\uae30 VivaldiView.title.fullcvs=\ube44\ubc1c\ub514 CVS VivaldiView.title.full_v6=\ube44\ubc1c\ub514 IPv6 MyTrackerView.date_added=\ucd94\uac00 ConfigView.label.playfilespeech=\ud30c\uc77c\uc774 \ub05d\ub9c8\uccd0 \uc84c\uc73c\uba74 \ub9d0\ud574\uc8fc\uae30 ConfigView.label.playfilespeech.info=\ub9d0\ud574\uc8fc\uae30 \uae30\ub2a5\uc740 \uc601\uc5b4\uc0b0\ud0dc\uc5d0\uc11c \uc798 \uc791\ub3d9\ud569\ub2c8\ub2e4. ConfigView.label.backupconfigfiles=\ubcf5\uad6c\ub97c \uc704\ud574 \uc124\uc815\ud30c\uc77c \ubc31\uc5c5 ActivityView.legend.limit=\ud55c\uacc4 \ube44\uc728 ActivityView.legend.achieved=\ub2ec\uc131 \ube44\uc728 ActivityView.legend.overhead=\uc624\ubc84\ud5e4\ub4dc \ube44\uc728 ActivityView.legend.peeraverage=\ud3c9\uade0 ActivityView.legend.swarmaverage=\ub5bc \ud3c9\uade0 ActivityView.legend.trimmed=\uc18c\uc218\uc810\uc774\ud558 \uc0dd\ub7b5 MyTorrentsView.menu.movemenu=\ud30c\uc77c \uc62e\uae30\uae30 MyTorrentsView.menu.movetorrent=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c \uc62e\uae30\uae30... DHTView.operations.data=\ub370\uc774\ud130 DHTView.general.reachable=\ub3c4\ub2ec\uc728: DHTView.general.rendezvous=\ub791\ub370\ubdf0: Views.plugins.IRC.title=IRC - \uc628\ub77c\uc778 \uae30\uc220\uc9c0\uc6d0 Formats.units.persec=/\ucd08 Formats.units.TiB=\ud14c\ub77c\ubc14\uc774\ud2b8 Formats.units.Tibit=\ud14c\ub77c\ube44\ud2b8 Formats.units.TB=\ud14c\ub77c\ubc14\uc774\ud2b8 Formats.units.Tbit=\ud14c\ub77c\ube44\ud2b8 Formats.units.GiB=\uae30\uac00\ubc14\uc774\ud2b8 Formats.units.Gibit=\uae30\uac00\ube44\ud2b8 Formats.units.GB=\uae30\uac00\ubc14\uc774\ud2b8 Formats.units.Gbit=\uae30\uac00\ube44\ud2b8 Formats.units.MiB=\uba54\uac00\ubc14\uc774\ud2b8 Formats.units.Mibit=\uba54\uac00\ube44\ud2b8 Formats.units.MB=\uba54\uac00\ubc14\uc774\ud2b8 Formats.units.Mbit=\uba54\uac00\ube44\ud2b8 Formats.units.KiB=\ud0ac\ub85c\ube44\ud2b8 Formats.units.Kibit=\ud0ac\ub85c\ube44\ud2b8 Formats.units.kB=\ud0ac\ub85c\ubc14\uc774\ud2b8 Formats.units.KB=\ud0ac\ub85c\ubc14\uc774\ud2b8 Formats.units.kbit=\ud0ac\ub85c\ube44\ud2b8 Formats.units.B=\ubc14\uc774\ud2b8 Formats.units.bit=\ube44\ud2b8 Formats.units.alot=\ub9e4\uc6b0 \ub9ce\uc2b5\ub2c8\ub2e4 !!! FilesView.menu.rename=\uc774\ub984\ubc14\uafb8\uae30 \ud639\uc740 \ubaa9\ud45c\uc7ac\uc124\uc815 FilesView.menu.rename_only=\ube60\ub978 \uc774\ub984\ubc14\uafb8\uae30 FilesView.menu.retarget=\ud30c\uc77c \uc62e\uae30\uae30 FilesView.rename.choose.path=\uc0c8 \ud30c\uc77c\uc774\ub098 \uae30\uc874 \ud30c\uc77c \uc120\ud0dd FilesView.rename.choose.path.dir=\uc0c8 \ud3f4\ub354\ub098 \uae30\uc874 \ud3f4\ub354 \uc120\ud0dd FilesView.rename.confirm.delete.title=\uc0ad\uc81c \ud655\uc778 FilesView.rename.confirm.delete.text='%1'\uc758 \uc6d0\ubcf8\ud30c\uc77c\uc744 \uc0ad\uc81c\ud558\ub294\uac83\uc744 \ud655\uc778\ud574 \uc8fc\uc2ed\uc2dc\uc624. FilesView.rename.filename.title=\uc774\ub984 \ubc14\uafb8\uae30 FilesView.rename.filename.text=\ud30c\uc77c\uc758 \uc0c8\uc774\ub984 \uc120\ud0dd ConfigView.higher.mode.available=\uace0\uae09 \uc0ac\uc6a9\uc790\ub97c \uc704\ud55c \uc120\ud0dd\uc0ac\ud56d \ud45c\uc2dc ConfigView.section.mode=\ubaa8\ub4dc ConfigView.section.mode.beginner=\ucd08\uc2ec\uc790 ConfigView.section.mode.beginner.wiki.definitions=\ube44\ud2b8 \ud1a0\ub7f0\ud2b8 \uc0ac\uc6a9 \ub2e8\uc5b4 ConfigView.section.mode.intermediate=\uc911\uae09\uc790 ConfigView.section.mode.intermediate.wiki.host=\ud30c\uc77c \ud638\uc2a4\ud305 ConfigView.section.mode.intermediate.wiki.publish=\ud30c\uc77c \ubc30\ud3ec ConfigView.section.mode.advanced=\uace0\uae09 ConfigView.section.mode.advanced.wiki.main=\uc704\ud0a4 \ub300\ubb38 Files.column.storagetype=\uc800\uc7a5\uc18c \uc720\ud615 Files.column.fileext=\uc720\ud615 MessageBoxWindow.rememberdecision=\uc120\ud0dd\ub0b4\uc6a9\uc744 \uae30\uc5b5\ud574 \ub461\ub2c8\ub2e4. configureWizard.welcome.usermodes=\ub3c4\uad6c > \uc120\ud0dd\uc0ac\ud56d\uc5d0\uc11c \uc0ac\uc6a9\uc790\uc758 \uc218\uc900\uc5d0 \uc801\ub2f9\ud55c \ub2e8\uacc4\ub85c \uc124\uc815\ud558\uba74 \ud45c\uc2dc\ub418\ub294 \uc815\ubcf4\uc758 \uc591\uc744 \uc870\uc808 \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. diagnostics.log_found=Vuze\uac00 \uae54\ub054\ud558\uac8c \ub05d\ub098\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. \uc9c4\ub2e8\uc5d0 \ub3c4\uc6c0\uc774 \ub418\ub294 \ub85c\uadf8 \ud30c\uc77c\ub4e4\uc5d0\uc11c %1\uc744 \uac80\uc0ac\ud558\uace0 \ud504\ub85c\uadf8\ub7a8 \uc624\ub958 \ub54c\ubb38\uc774\uba74 Vuze \ud300\uc5d0\uac8c \uc804\ud560 \uac83\uc744 \uc0dd\uac01\ud558\uc2ed\uc2dc\uc694. ManagerItem.paused=\uc7a0\uc2dc \uba48\ucda4 Utils.link.visit=\ubc29\ubb38\ud574 \uc8fc\uc138\uc694 ConfigView.section.transfer.speeds.wiki=\uad8c\uc7a5\ud558\ub294 \uc18d\ub3c4 \uc124\uc815 installPluginsWizard.installMode.info.title=\uc815\ubcf4 Views.plugins.Distributed.DB.title=\ubc30\ud3ec DB Views.plugins.Distributed.Tracker.title=\ubc30\ud3ec \ub354\ub4ec\uc774 Views.plugins.Plugin.Update.title=\ucd94\uac00\uae30\ub2a5 \uc5c5\ub370\uc774\ud2b8 Views.plugins.UPnP.title.tooltip=\uc720\ub2c8\ubc84\uc15c \ud504\ub7ec\uadf8 \uc564 \ud50c\ub808\uc774 MainWindow.nat.status.unknown=\uacf5\uc720\uae30 MainWindow.nat.status.tooltip.unknown=\ubc29\ud654\ubcbd/\uacf5\uc720\uae30 \uc811\uadfc\uc5ec\ubd80 \uc0c1\ud0dc\ub97c \uc54c\uc218 \uc5c6\uc74c (TCP) MainWindow.nat.status.ok=\uacf5\uc720\uae30 OK MainWindow.nat.status.tooltip.ok=\uc811\uadfc\uc5ec\ubd80 OK (TCP) MainWindow.nat.status.probok=\uacf5\uc720\uae30 OK? MainWindow.nat.status.tooltip.probok=\uc811\uadfc\uc740 \uac00\ub2a5\ud558\ub098 \uc0c8\ub86d\uac8c \ub4e4\uc5b4\uc624\ub294 TCP\uc5f0\uacb0\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. MainWindow.nat.status.bad=\ubc29\ud654\ubcbd MainWindow.nat.status.tooltip.bad=\ubc29\ud654\ubcbd/\uacf5\uc720\uae30 (TCP)\uc5d0 \uc811\uadfc\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. \uc704\ud0a4\uc758 \ub3c4\uc6c0\ub9d0\uc744 \uc0b4\ud3b4\ubcf4\uc138\uc694. LoggerView.pause=\uae30\ub85d \uc7a0\uc2dc\uc911\uc9c0 LoggerView.filter=\ud544\ud130 LoggerView.filter.uncheckAll=\ubaa8\ub4e0 \uad6c\ubd84 \ud655\uc778\ud558\uc9c0 \uc54a\uc74c LoggerView.filter.checkAll=\ubaa8\ub4e0 \uad6c\ubd84 \ud655\uc778 LoggerView.loggingDisabled=\uae30\ub85d\uc774 \uc791\ub3d9\uc911\uc774\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. ConfigView.section.logging.log0type=\uc815\ubcf4 ConfigView.section.logging.log1type=\uacbd\uace0 ConfigView.section.logging.log2type=\uc624\ub958 ConfigView.section.logging.filter=\ud30c\uc77c\uc5d0 \uae30\ub85d\ud560\ub54c \ud544\ud130 ConfigView.pluginlist.column.loadAtStartup=\uc2dc\uc791\uc2dc \ubd88\ub7ec\uc62e ConfigView.pluginlist.column.type=\uc885\ub958 ConfigView.pluginlist.column.type.perUser=\uc0ac\uc6a9\uc790\ub2f9 \ube44\uc728 ConfigView.pluginlist.column.type.shared=\uacf5\uc720 ConfigView.pluginlist.column.name=\uc774\ub984 ConfigView.pluginlist.column.version=\ubc84\uc804 ConfigView.pluginlist.column.directory=\ud3f4\ub354 ConfigView.pluginlist.column.isOperational=\uc0ac\uc6a9\ud560\uc218 \uc788\uc2b5\ub2c8\uae4c? PeersView.BlockView.Avail.Have=\ub458\ub2e4 \uc788\uc74c PeersView.BlockView.Avail.NoHave=\ub3d9\ub8cc \uc788\uc74c; \ub098\ub294 \uc5c6\uc74c PeersView.BlockView.NoAvail.Have=\ub098\ub294 \uc788\uc74c; \ub3d9\ub8cc \uc5c6\uc74c PeersView.BlockView.Transfer=\uc804\uc1a1 PeersView.BlockView.NextRequest=\ub2e4\uc74c \uc694\uccad PeersView.BlockView.title=\uc870\uac01 \uc9c0\ub3c4 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.upload=\uc62c\ub9ac\uae30 MyTorrentsView.dialog.setNumber.download=\ub0b4\ub824\ubc1b\uae30 OpenTorrentWindow.torrentLocation=\ud1a0\ub7f0\ud2b8 \ud30c\uc77c: OpenTorrentWindow.addFiles.URL=\ucd94\uac00 &URL OpenTorrentWindow.addFiles.Folder=\ucd94\uac00 &Folder OpenTorrentWindow.addFiles.Clipboard=\ucd94\uac00 Clip&board OpenTorrentWindow.fileList=\ud1a0\ub7f0\ud2b8 \ub0b4 \ud30c\uc77c: OpenTorrentWindow.torrentTable.name=\uc774\ub984 OpenTorrentWindow.torrentTable.saveLocation=\uc704\uce58 \uc800\uc7a5 OpenTorrentWindow.fileTable.fileName=\ud30c\uc77c \uc774\ub984 OpenTorrentWindow.fileTable.size=\ud06c\uae30 OpenTorrentWindow.startMode.seeding=\ubfcc\ub9ac\uae30 OpenTorrentWindow.mb.alreadyExists.default.name=\ubbf8\ub514\uc5b4 OpenTorrentWindow.mb.openError.title=\uc624\ub958 \uc5f4\uae30 OpenTorrentWindow.torrent.remove=\ubaa9\ub85d\uc5d0\uc11c \ud1a0\ub7f0\ud2b8 \uc0ad\uc81c iconBar.open.tooltip=\ud1a0\ub7f0\ud2b8 \uc5f4\uae30 LocaleUtil.column.text=\uc54c\uc218\uc5c6\ub294 \ubb38\uc790 ConfigView.label.lazybitfield=\ube44\ud6a8\uc728\uc801\uc778 \ube44\ud2b8\ud544\ub4dc \uc0ac\uc6a9 (\ub124\ud2b8\uc6cd\uc5d0\uc11c \ube44\ud2b8\ud544\ub4dc\uae30\ubc18\uc758 \ucc28\ub2e8\uc744 \uc0ac\uc6a9\ud558\uc5ec \ubfcc\ub9b4\ub54c \ub3c4\uc6c0\uc774 \ub428) LoggerView.realtime=\uc2e4\uc2dc\uac04 \uc5c5\ub370\uc774\ud2b8 Button.moveUp=\uc704\ub85c \uc62e\uae40 &U Button.moveDown=\uc544\ub798\ub85c \uc62e\uae40 &D PeersView.piece=\uc870\uac01 PiecesView.priority=\uc21c\uc704 PiecesView.speed=\ud06c\uae30 MyTorrentsView.menu.checkfilesexist=\ud30c\uc77c \uc704\uce58 \ud655\uc778 MyTorrentsView.menu.clear_resume_data=\ub2e4\uc2dc\uc2dc\ub3c4\ud55c \ub370\uc774\ud130 \uc9c0\uc6b0\uae30 azinstancehandler.alert.portclash=\uc0ac\uc6a9\uc911\uc778 \ub124\ud2b8\uc6cd\uc758 \ud3ec\ud2b8\uc5d0\uc11c \ucda9\ub3cc\uc774 \ubc1c\uacac\ub418\uc5c8\uc2b5\ub2c8\ub2e4: %1 \uc774\ubbf8 \ub2e4\ub978 Vuze \uc0ac\uc6a9\uc790\uac00 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub294 \uac83 \uac19\uc2b5\ub2c8\ub2e4. TCP / UDP \ub4e3\uae30\uc6a9 \ub2e4\ub978 \ud3ec\ud2b8\ub97c \uc120\ud0dd\ud574 \uc8fc\uc138\uc694. [%2 \uc5d0\uc11c %3 \uc0ac\uc774]. TorrentOptionsView.title.short=\ud1a0\ub7f0\ud2b8 \uc120\ud0dd\uc0ac\ud56d TorrentOptionsView.title.full=\ud1a0\ub7f0\ud2b8 \uc120\ud0dd\uc0ac\ud56d MainWindow.sr.status.tooltip.ok=\uacf5\uc720\ube44\uc728 %1 OK MainWindow.sr.status.tooltip.poor=\uacf5\uc720\ube44\uc728 %1 \uc5f4\uc545: < 0.9 MainWindow.sr.status.tooltip.bad=\uacf5\uc720\ube44\uc728 %1 \ub098\uc068: < 0.5 ConfigView.section.style.status.show_ipf=IP \ud544\ud130 \uc0c1\ud0dc ConfigView.section.connection.encryption=\uc554\ud638\ud654 LoggerView.autoscroll=\uc790\ub3d9 \uc2a4\ud06c\ub864 Button.selectAll=\ubaa8\ub450 \uc120\ud0dd Button.markSelected=\uc120\ud0dd Button.unmarkSelected=\uc120\ud0dd\uc548\ud568 plugins.basicview.config=\uc124\uc815 ConfigView.section.connection.advanced.info.link=\uc138\ubd80\ud56d\ubaa9\uc744 \ubcf4\uc2dc\ub824\uba74 \ubc29\ubb38\ud574 \uc8fc\uc138\uc694 ConfigView.section.connection.advanced.socket.group=\uc18c\ucf13 \uc120\ud0dd\uc0ac\ud56d ConfigView.section.connection.advanced.bind_port=\ub85c\uceec\ud3ec\ud2b8\ub85c \uc9c0\uc815 [0: \uc791\ub3d9 \uc911\uc9c0] ConfigView.section.proxy.group.tracker=\ub354\ub4ec\uc774 \ud1b5\uc2e0 ConfigView.section.proxy.group.peer=\ub3d9\ub8cc \ud1b5\uc2e0 Pieces.column.Requested=\uc694\uccad\ub428 ConfigView.label.maxuploadsseeding=\ubfcc\ub9b4\ub54c \ub300\uccb4\ud560 \uae30\ubcf8\uac12 MyTorrentsView.filter=\uace8\ub77c\ubcf4\uae30: popup.error.hideall=\ubaa8\ub450 \uc228\uae30\uae30 MyTorrentsView.dialog.setFilter.title=\uace8\ub77c\ubcf4\uae30 \ud3b8\uc9d1 MyTorrentsView.menu.filter=\uace8\ub77c\ubcf4\uae30 \ubaa9\ub85d... ConfigureWizard.language.choose=\uc544\ub798\uc5d0\uc11c \uc5b8\uc5b4\ub97c \uc120\ud0dd\ud558\uc138\uc694: # > 2402 ConfigView.auto=\uc790\ub3d9 MainWindow.menu.view.plugins.logViews=\uae30\ub85d \ubcf4\uae30 SpeedView.stats.autospeed=\uc790\ub3d9 \uc62c\ub9ac\uae30 \uc18d\ub3c4 SpeedView.stats.idlePing=\ud734\uc9c0\uae30 \ud551: SpeedView.stats.maxPing=\ud551 \ucd5c\ub300\uac12: SpeedView.stats.currentPing=\ud604\uc7ac\uae4c\uc9c0 \ud551: SpeedView.stats.maxUp=\uc62c\ub9ac\uae30 \uc18d\ub3c4 \ucd5c\ub300\uac12: ConfigView.pluginlist.unloadSelected=\uc120\ud0dd\ud55c\uac83 \ubd88\ub7ec\uc624\uae30 \ucde8\uc18c ConfigView.pluginlist.scan=\uc0c8\ub85c\uc6b4 \ucd94\uac00\uae30\ub2a5 \ucc3e\uc544\ubcf4\uae30 ConfigView.section.transfer.autospeed=\uc790\ub3d9 \uc18d\ub3c4 (\uae30\ubcf8) ConfigView.pluginlist.column.unloadable=\ubd88\ub7ec\uc62c\uc218 \uc5c6\uc74c TableColumn.header.filesdone=\ud30c\uc77c \uc644\ub8cc MagnetPlugin.report.searching=\uac80\uc0c9... MagnetPlugin.report.alive=%1 \uc0b4\uc544\uc788\uc74c MagnetPlugin.report.dead=%1 \uc8fd\uc5b4\uc788\uc74c MagnetPlugin.report.downloading=%1\uc5d0\uc11c \ub0b4\ub824\ubc1b\uae30 \uc911 MagnetPlugin.report.error=\uc624\ub958 %1 MagnetURLHandler.report.no_sources=\ud1a0\ub7f0\ud2b8\uc5d0\uc11c \uc18c\uc2a4\ub97c \ucc3e\uc9c0 \ubabb\ud568 MagnetURLHandler.report.torrent_size=\ud1a0\ub7f0\ud2b8 \ud06c\uae30: %1 MagnetURLHandler.report.percent=\uc644\ub8cc: %1% DHTTransport.report.complete=\uc644\ub8cc DHTTransport.report.sending=\ub370\uc774\ud130 \ubcf4\ub0b4\uae30 DHTTransport.report.resending=\ub370\uc774\ud130 \ub2e4\uc2dc\ubcf4\ub0b4\uae30 DHTTransport.report.send_complete=\uc644\ub8cc \ubcf4\ub0b4\uae30 DHTTransport.report.send_timeout=\uc2dc\uac04\ucd08\uacfc \ubcf4\ub0b4\uae30 TableColumn.header.date_added=\ucd94\uac00 \ub0a0\uc9dc TableColumn.header.date_added.info=\ud1a0\ub7f0\ud2b8\uac00 \ucd94\uac00\ub41c \ub0a0\uc9dc platform.win32.baddll.nvappfilter=NVidia \ubc29\ud654\ubcbd platform.win32.baddll.vlsp=Venturi \ubc29\ud654\ubcbd platform.win32.baddll.radhslib=Naomi \uc778\ud130\ub137 \ud544\ud130 (Radiant) platform.win32.baddll.winsflt=PureSight \uc778\ud130\ub137 \ud544\ud130 platform.win32.baddll.iFW_Xfilter=iolo \uac1c\uc778\uc6a9 \ubc29\ud654\ubcbd upnp.ignorebaddevices.reset.action=\ucd08\uae30\ud654 FileView.BlockView.title=\ud30c\uc77c \uc870\uac01 FileView.BlockView.Done=\uc644\ub8cc FileView.BlockView.Skipped=\ubb34\uc2dc\ub428 FileView.BlockView.Active=\ud65c\uc131 ConfigView.label.maxuploadswhenbusymin=\ubc14\uc05c \uc0c1\ud669\uc5d0 \ud1a0\ub7f0\ud2b8\ubcc4 \ucd5c\ub300 \uc62c\ub9ac\uae30 \uc18d\ub3c4 [\ucd08] DownloadManager.error.badsize=\ubd80\uc815\ud655\ud55c \ud06c\uae30 ConfigView.filter=\uac80\uc0c9 \uc120\ud0dd\uc0ac\ud56d \uc124\uc815 ConfigView.section.file.defaultdir.section=\uae30\ubcf8 \ud3f4\ub354 \uc120\ud0dd\uc0ac\ud56d ConfigView.section.file.config.currentdir=\uae30\uc874 \uc120\ud0dd\uc0ac\ud56d \ud3f4\ub354: Tracker.announce.ignorePeerSeed=\ub3d9\ub8cc/\uc528\uc557 \ud69f\uc218 \ubb34\uc2dc. %1 TorrentOptionsView.param.reset.button=\ucd08\uae30\ud654 ConfigView.section.connection.tcp.enable=TCP \uc791\ub3d9 ConfigView.section.connection.udp.enable=UDP \uc791\ub3d9 ConfigView.section.style.showiconbar=\ub3c4\uad6c \ud45c\uc2dc\uc904 \ubcf4\uae30 MainWindow.menu.view.iconbar=\ub3c4\uad6c \ud45c\uc2dc\uc904 MyTorrentsView.menu.rename=\uc774\ub984\ubc14\uafb8\uae30 MyTorrentsView.menu.rename.displayed=\ubcf4\uc774\ub294 \uc774\ub984\ubc14\uafb8\uae30 MyTorrentsView.menu.rename.displayed.enter.title=\ubcf4\uc774\ub294 \uc774\ub984\ubc14\uafb8\uae30 MyTorrentsView.menu.edit_comment=\ub367\ub9d0 \uc218\uc815 MyTorrentsView.menu.edit_comment.enter.title=\ub367\ub9d0 \uc218\uc815 MyTorrentsView.menu.edit_comment.enter.message=\ub0b4\ub824\ubc1b\uae30 \uc790\ub8cc\uc5d0 \ub367\ub9d0\uc744 \uc785\ub825 \ud569\ub2c8\ub2e4. UIDebugGenerator.messageask.title=\uc624\ub958\uc7a1\uc774 \ucd94\uc801\uae30 UIDebugGenerator.complete.title=\uc624\ub958\uc7a1\uc774 \ucd94\uc801 \uc644\ub8cc authenticator.savepassword=\uc554\ud638 \uc800\uc7a5 ConfigView.section.security.clearpasswords=\uae30\uc5b5\ud558\uace0 \uc788\ub294 \uc554\ud638 \ucd08\uae30\ud654 ConfigView.section.security.clearpasswords.button=\ucd08\uae30\ud654 Content.alert.notuploaded.title=\uc62c\ub9ac\uae30\uac00 \ub05d\ub098\uc9c0 \uc54a\uc558\uc74c Content.alert.notuploaded.text='%1'\ub294 \uc62c\ub9ac\uae30\uac00 \ub05d\ub098\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. %2\ub97c \uc9c0\uae08 \ud558\uba74\uc740 \uc0ac\ub78c\ub4e4\uc774 \ub0b4\uac00 \ucd9c\ud310\ud55c \ub0b4\uc6a9\uc744 \uc644\uc804\ud788 \ub0b4\ub824\ubc1b\uc9c0 \ubabb \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \n\n\uadf8\ub798\ub3c4 %2\ub97c \ud560\uae4c\uc694? Content.alert.notuploaded.multi.title=\uc62c\ub9ac\uae30\uac00 \ub05d\ub098\uc9c0 \uc54a\uc558\uc74c Content.alert.notuploaded.stop=\uba48\ucda4 Content.alert.notuploaded.quit=Vuze \uc885\ub8cc ConfigView.label.popup.autohide=\uc624\ub958 \uc54c\ub9bc\uc774 \uc544\ub2cc\uacbd\uc6b0 x\ucd08\ud6c4 \uc790\ub3d9\uc73c\ub85c \ud31d\uc5c5\ucc3d \uc228\uae30\uae30 (0\uc73c\ub85c \uc124\uc815\uc2dc \uc790\ub3d9 \uc228\uae30\uae30 \uc791\ub3d9\uc548\ud568) ConfigView.label.popup.show=\uae30\ub85d\ub418\ub294 \uc54c\ub9bc \ubcf4\uc5ec\uc8fc\uae30 ConfigView.label.popup.show.button=\ubcf4\uae30 ConfigView.label.please.visit.here=\uc790\uc138\ud55c \ub0b4\uc6a9\uc744 \uc54c\uace0\uc2f6\uc73c\uba74 \uc774\uacf3\uc744 \ubc29\ubb38\ud574 \uc8fc\uc138\uc694 ConfigView.label.openmytorrents=\uc2dc\uc791\uc2dc '\ub0b4 \ud1a0\ub7f0\ud2b8' \uc5f4\uae30 ConfigView.label.open_transfer_bar_on_start=\uc2dc\uc791\uc2dc \uc804\uc1a1 \ud45c\uc2dc\uc904 \uc5f4\uae30 OpenTorrentWindow.mb.notValid.title=\ud1a0\ub7f0\ud2b8 \uc5f4\uae30 OpenTorrentWindow.mb.notTorrent.title=\ud1a0\ub7f0\ud2b8 \uc5f4\uae30 ConfigView.label.pause.downloads.on.exit=Vauz\ub97c \ub098\uac08\ub54c \ub0b4\ub824\ubc1b\uae30 \uc911\uc9c0 UIDebugGenerator.message.cancel.title=\uc624\ub958\uc7a1\uc774 \uc815\ubcf4 \ucd94\uc801 \ucde8\uc18c ConfigView.section.connection.http.enable=\uc791\ub3d9 ConfigView.section.connection.http.port=\ub4e4\uc5b4\uc624\ub294 \ud3ec\ud2b8 \ubc88\ud638 window.update.noupdates.title=\uc5c5\ub370\uc774\ud2b8 \uacb0\uacfc\ud655\uc778 window.update.noupdates.text=\uc0c8\ub85c\uc6b4 \uc5c5\ub370\uc774\ud2b8\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. ConfigView.label.mindownloads=\ucd5c\uc18c \ub3d9\uc2dc \ub0b4\ub824\ubc1b\uae30 UI.cannot_submit_blank_text=\uac12\uc744 \uc785\ub825\ud558\uc154\uc57c \ud569\ub2c8\ub2e4. ConfigView.section.interface.alerts=\uacbd\uace0 MessageBoxWindow.nomoreprompting=\ub2e4\uc2dc \ubcf4\uc5ec\uc8fc\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. TransferStatsView.legend.pingaverage=\ud3c9\uade0 TransferStatsView.legend.ping1=\ubaa9\ud45c 1 TransferStatsView.legend.ping2=\ubaa9\ud45c 2 TransferStatsView.legend.ping3=\ubaa9\ud45c 3 ConfigView.label.closetotray._mac=\ucd5c\uc18c\ud654 \ud560\ub54c \uc0c1\ud0dc \ud45c\uc2dc\uc904 \uc544\uc774\ucf58\uc73c\ub85c splash.unloadingTorrents=\ud1a0\ub7f0\ud2b8 \uc62c\ub9ac\uae30 \uc911 splash.unloadingTorrent=\ud1a0\ub7f0\ud2b8 \uc62c\ub9ac\uae30 \uc911 alert.raised.at.close=(Vuze\uac00 \ub9c8\uc9c0\ub9c9 \uc2e4\ud589 \ub418\uc5c8\uc744\ub54c \uc54c\ub9bc) Peers.column.maxupspeed=\uc5c5\uc18d\ub3c4 \ucd5c\ub300\uac12 Peers.column.maxdownspeed=\ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4 \ucd5c\ub300\uac12 MyTorrents.items.DownSpeedLimit.disabled=\ub0b4\ub824\ubc1b\uae30 \uc5c6\uc74c UpdateMonitor.messagebox.restart.title=\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc5c5\ub370\uc774\ud2b8 PiecesView.BlockView.Have=\uc788\uc74c PiecesView.BlockView.NoHave=\uc5c6\uc74c ConfigView.section.update.autodownload=\uc5c5\ub370\uc774\ud2b8\ub97c \uc790\ub3d9\uc73c\ub85c \ub0b4\ub824\ubc1b\uace0 \uc124\uce58\uc900\ube44\uac00 \ub418\uba74 \uc54c\ub9ac\uae30 Peers.column.peer_id=\ub3d9\ub8cc ID Peers.column.peer_id.info=\ub3d9\ub8cc ID in readable form Peers.column.peer_byte_id=\ub3d9\ub8cc ID Peers.column.peer_byte_id.info=\ub3d9\ub8ccr ID in byte form ConfigView.label.openbar.incomplete=\ub0b4\ub824\ubc1b\uae30 \ud45c\uc2dc\uc904: \ub0b4\ub824\ubc1b\uae30 \uc790\ub3d9 \uc5f4\uae30 ConfigView.label.openbar.complete=\uc528\uc557 \uc790\ub3d9\uc73c\ub85c \uc5f4\uae30 MainWindow.menu.tools.speedtest=\uc18d\ub3c4 \uac80\uc0ac.. speedtest.wizard.title=\uc18d\ub3c4 \uac80\uc0ac speedtest.wizard.run=\uc18d\ub3c4 \uac80\uc0ac \uc2e4\ud589 speedtest.wizard.test.mode.updown=\uc62c\ub9ac\uae30/\ub0b4\ub824\ubc1b\uae30 speedtest.wizard.test.mode.up=\uc62c\ub9ac\uae30 speedtest.wizard.test.mode.down=\ub0b4\ub824\ubc1b\uae30 SpeedTestWizard.test.panel.currinfo=\ud1a0\ub7f0\ud2b8 \ub300\uc5ed\ud3ed \uac80\uc0ac. SpeedTestWizard.test.panel.label=Vuze \uc18d\ub3c4 \uac80\uc0ac: SpeedTestWizard.test.panel.already.running=\uac80\uc0ac\uac00 \uc774\ubbf8 \uc9c4\ud589\uc911\uc785\ub2c8\ub2e4. SpeedTestWizard.test.panel.not.accepted=\uac80\uc0ac \uc694\uccad\uc774 \uc218\ub77d\ub428: SpeedTestWizard.test.panel.abort=\ucde8\uc18c SpeedTestWizard.test.panel.abort.countdown=\uac80\uc0ac \ucde8\uc18c: SpeedTestWizard.test.panel.test.countdown=\uac80\uc0ac \uc885\ub8cc: SpeedTestWizard.test.panel.testfailed=\uac80\uc0ac \uc2e4\ud328 SpeedTestWizard.test.panel.standard=\uae30\ubcf8 SpeedTestWizard.set.upload.button.apply=\uc801\uc6a9 SpeedTestWizard.set.upload.result=\ub9c8\uc9c0\ub9c9 \uac80\uc0ac \uacb0\uacfc SpeedTestWizard.finish.panel.title=\uc18d\ub3c4 \uac80\uc0ac\uac00 \ub05d\ub0ac\uc2b5\ub2c8\ub2e4 SpeedTestWizard.finish.panel.max.upload=\ucd5c\ub300 \uc62c\ub9ac\uae30 : SpeedTestWizard.finish.panel.max.seeding.upload=\ubfcc\ub9ac\ub294 \ub3d9\uc548 \ucd5c\ub300 \uc62c\ub9ac\uae30 : SpeedTestWizard.finish.panel.max.download=\ucd5c\ub300 \ub0b4\ub824\ubc1b\uae30 : SpeedTestWizard.finish.panel.enabled=\uc791\ub3d9 SpeedTestWizard.finish.panel.disabled=\uc791\ub3d9\uba48\ucda4 SpeedTestWizard.abort.message.manual.abort=\uc218\ub3d9\uc73c\ub85c \ucde8\uc18c SpeedTestWizard.abort.message.failed.peers=\ubaa8\ub4e0 \ub3d9\ub8cc\uc640 \uc5f0\uacb0 \uc2e4\ud328 SpeedTestWizard.stage.message.requesting=\uac80\uc0ac \uc694\uccad.. SpeedTestWizard.stage.message.preparing=\uac80\uc0ac \uc900\ube44.. SpeedTestWizard.stage.message.starting=\uac80\uc0ac \uc2dc\uc791.. SpeedTestWizard.stage.message.connect.stats=\uc5f0\uacb0 \uc0c1\ud669 : \ub3d9\ub8cc=%1, \ub0b4\ub824\ubc1b\uae30 \uc591\ud638=%2, \uc62c\ub9ac\uae30 \uc591\ud638=%3 window.uiswitcher.title=Vuze UI \uc120\ud0dd\ud558\uae30 window.uiswitcher.text=\uc544\ub798\uc5d0\uc11c \uac00\uc7a5 \uc801\ud569\ud55c \uc720\uc800 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uace0\ub974\uc138\uc694. window.uiswitcher.NewUI.title=Vuze \uc778\ud130\ud398\uc774\uc2a4 window.uiswitcher.NewUI.text=* \ucc98\uc74c\uc0ac\uc6a9\uc790\uc640 \ucd08\ubcf4\uc790\uc5d0\uac8c \uad8c\uc7a5\ud569\ub2c8\ub2e4.\n\n* \uc27d\uace0 \uc9c1\uad00\uc801\uc778 \uadf8\ub798\ud53d \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc81c\uacf5\ud569\ub2c8\ub2e4.\n\n* Vuze\uac00 \uc81c\uacf5\ud558\ub294 \ub2e4\uc591\ud55c \uc11c\ube44\uc2a4\ub97c \uc0ac\uc6a9\ud558\uae30\uc5d0 \uc88b\uc2b5\ub2c8\ub2e4. window.uiswitcher.ClassicUI.title=\ud074\ub808\uc2dd \uc778\ud130\ud398\uc774\uc2a4 window.uiswitcher.ClassicUI.text=* 2.x \ubc84\uc804\uc758 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc720\uc9c0\ud569\ub2c8\ub2e4.\n\n* Vuze\uc758 HD \ub124\ud2b8\uc6cc\ud06c\ub4f1 \ucee8\ud150\ud2b8 \uad00\ub828 \uae30\ub2a5\uc740 \uc0ac\uc6a9\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. window.uiswitcher.bottom.text=Vuze UI \uc120\ud0dd\ud558\uae30 \ub2e8\ucd94\ub97c \ud1b5\ud574 \uc5b8\uc81c\ub4e0\uc9c0 UI\ub97c \ubc14\uafc0 \uc218 \uc788\uc2b5\ub2c8\ub2e4. iconBar.switch.tooltip=Vuze UI \uc120\ud0dd\uae30 VivaldiView.notAvailable=\ube44\ubc1c\ub514 \ubcf4\uae30\uac00 \ud65c\uc131\ud654 \ub418 \uc788\uc9c0 \uc54a\uc74c restart.error.oom=\uc608\uc0b0 \ucd08\uacfc TableColumn.menu.date_added.reset=\ub0a0\uc9dc \ucd08\uae30\ud654 ConfigView.interface.start.advanced=\uace0\uae09 \uc120\ud0dd\uc0ac\ud56d \ud45c\uc2dc (AZ 2.x) MyTorrents.column.ColumnQuality=\ud488\uc9c8 TableColumn.header.Quality=\ud488\uc9c8 TableColumn.header.Speed=\uc18d\ub3c4 TableColumn.header.RateIt=\uc21c\uc704 TableColumn.header.Rating=\uc21c\uc704 TableColumn.header.SpeedGraphic=\uc18d\ub3c4 TableColumn.header.AzProduct=\ubcf4\ub0b8 \uc774 TableColumn.header.MediaThumb=\ubbf8\ub514\uc5b4 TableColumn.header.ProgressETA=\uc9c4\ud589\uc0c1\ud669 #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=\ud30c\uc77c \uc885\ub958: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=\ub300\uc26c\ubcf4\ub4dc v3.MainWindow.tab.browse=Vuze\uc5d0\uc11c v3.MainWindow.tab.library=\ub77c\uc774\ube0c\ub7ec\ub9ac v3.MainWindow.tab.publish=\ubc30\ud3ec v3.MainWindow.tab.advanced=\uace0\uae09 v3.MainWindow.menu.home=&\ub300\uc26c\ubcf4\ub4dc v3.MainWindow.menu.browse=&Vuze\uc5d0\uc11c v3.MainWindow.menu.library=&\ub77c\uc774\ube0c\ub7ec\ub9ac v3.MainWindow.menu.publish=&\ubc30\ud3ec v3.MainWindow.menu.advanced=&\uace0\uae09 v3.MainWindow.menu.view.searchbar=\uac80\uc0c9 \ud45c\uc2dc\uc904 v3.MainWindow.menu.view.tabbar=\ud0ed \ud45c\uc2dc\uc904 v3.MainWindow.currentDL=\ud604\uc7ac \ub0b4\ub824\ubc1b\uae30 \uc911\uc778 \uc790\ub8cc v3.MainWindow.button.stream=\uc2a4\ud2b8\ub9bc v3.MainWindow.button.stop=\uc911\uc9c0 v3.MainWindow.button.start=\uc2dc\uc791 v3.MainWindow.button.pause=\uba48\ucda4 v3.MainWindow.button.resume=\uacc4\uc18d v3.MainWindow.button.delete=\uc0ad\uc81c v3.MainWindow.button.comment=\ub367\ub9d0 v3.MainWindow.button.viewdetails=\uc18d\uc131 v3.MainWindow.button.play=\uc7ac\uc0dd v3.MainWindow.button.cancel=\ucde8\uc18c v3.MainWindow.button.preview=\ud504\ub9ac\ubdf0 v3.MainWindow.view.wait=\uc678\ud615\uc744 \ucd08\uae30\ud654\uc911\uc785\ub2c8\ub2e4. \uc7a0\uc2dc\ub9cc \uae30\ub2e4\ub824 \uc8fc\uc138\uc694. v3.MainWindow.xofx=%1 \uc758 %2 v3.MainWindow.Loading=\ubd88\ub7ec\uc624\ub294\uc911.. \uc7a0\uc2dc \uae30\ub2e4\ub824\uc8fc\uc138\uc694. v3.filter-bar=\uc81c\ubaa9 \uace8\ub77c\ubcf4\uae30: v3.MainWindow.search.defaultText=\ucc3e\uae30... v3.mb.delPublished.title=\uc528\uc557 \ubfcc\ub9ac\uae30 \uc911\ub2e8 v3.mb.delPublished.text=\uacbd\uace0: \uc774\uc791\uc5c5\uc774 %3\ub85c\ubd80\ud130 \uacf5\uc720\ud55c \ucee8\ud150\uce20 '%1'\ub97c \uc81c\uac70\ud558\ub294\uac83\uc740 \uc544\ub2d9\ub2c8\ub2e4.\n\n\ub0a8\ub294 \ub300\uc5ed\ud3ed\uc744 \ud65c\uc6a9\ud574 \uc790\ub8cc\ub97c \ubc30\ud3ec\ud558\uac70\ub098 \ub0b4\ub824\ubc1b\uae30 \uac00\ub2a5\ud558\uac8c \ud558\ub824\uba74 "\uc0ad\uc81c"\ub97c \ub204\ub974\uc138\uc694. (\uc5b4\ub5bb\uac8c?)\ub97c \ucc38\uace0\ud558\uc5ec \uc774 \uc791\uc5c5\uc744 \ud558\uae30\uc804\uc5d0 \uc62c\ub9ac\uae30 \uc791\uc5c5\uc774 \uc644\uc804\ud788 \uc644\ub8cc\ub42c\ub294\uc9c0 \ub2e4\uc2dc\ud55c\ubc88 \ud655\uc778\ud558\uc138\uc694. \n\n%3\ub85c \ubd80\ud130 \ubc30\ud3ec\ud558\uace0 \uc788\ub294 \uc790\ub8cc\ub97c \uc644\uc804\ud788 \uc81c\uac70 \ud558\uace0 \uc2f6\uc73c\uba74 "\ucde8\uc18c"\ub97c \ud074\ub9ad\ud558\uac70\ub098 \ubc30\ud3ec \ud0ed\ub0b4\uc758 \ubc30\ud3ec\uc790\ub8cc \ud328\ub110\uc5d0\uc11c (X)\ub2e8\ucd94\ub97c \ub204\ub974\uba74 \ub429\ub2c8\ub2e4.\n\n\ub3c4\uc6c0\ub9d0.\n\n v3.mb.delPublished.delete=&\uc0ad\uc81c v3.mb.delPublished.cancel=&\ucde8\uc18c v3.mb.openFile.title=\ud30c\uc77c \uc5f4\uae30 v3.mb.openFile.text.known=\uc774\uc790\ub8cc\ub294 Vuze \ud50c\ub808\uc774\uc5b4\uc5d0\uc11c \uc7ac\uc0dd\ud560 \uc218 \uc5c6\ub294 \uc790\ub8cc\uc785\ub2c8\ub2e4. \ucee4\ubba4\ub2c8\ud2f0\uc5d0\uc11c \ud30c\uc77c\uc7ac\uc0dd \uac00\uc774\ub4dc \ub97c \ucc38\uace0\ud558\uc138\uc694.\n\n\ud30c\uc77c\ud0c0\uc785: %2 (%3)\n v3.mb.openFile.text.unknown=\uc774\uc790\ub8cc\ub294 Vuze \ud50c\ub808\uc774\uc5b4\uc5d0\uc11c \uc9c0\uc6d0\ud558\uc9c0 \uc54a\ub294 \uc790\ub8cc\uc785\ub2c8\ub2e4. \ucee4\ubba4\ub2c8\ud2f0\uc5d0\uc11c \ud30c\uc77c\uc7ac\uc0dd \uac00\uc774\ub4dc \ub97c \ud655\uc778\ud558\uc138\uc694.\n\n\ud30c\uc77c \ud615\uc2dd : %2\n v3.mb.openFile.button.play=\uc7ac\uc0dd v3.mb.openFile.button.cancel=\ucde8\uc18c v3.mb.openFile.button.guide=\ud30c\uc77c\uc7ac\uc0dd \uac00\uc774\ub4dc \uc77d\uae30 v3.mb.openFile.remember=\ubb3c\uc5b4\ubcf4\uc9c0 \uc54a\uace0 \ud56d\uc0c1 \ud30c\uc77c \uc5f4\uae30 v3.mb.PlayFileNotFound.title=\ud30c\uc77c\uc774 \uc5c6\uc74c v3.mb.PlayFileNotFound.text='%1'\uc758 \ud30c\uc77c\uc774 \uc9c0\uc6cc\uc84c\uac70\ub098 \uc704\uce58\uc5d0 \uc5c6\uc2b5\ub2c8\ub2e4. v3.mb.PlayFileNotFound.button.remove=Vuze\uc5d0\uc11c \uc81c\uac70 v3.mb.PlayFileNotFound.button.redownload=\ub2e4\uc2dc \ub0b4\ub824\ubc1b\uae30 v3.mb.PlayFileNotFound.button.find=\uc9c1\uc811 \ucc3e\uae30.. v3.mb.deletePurchased.title=\uad6c\uc785\ud55c \ucee8\ud150\uce20 \uc81c\uac70 v3.mb.deletePurchased.text='%1' \uc790\ub8cc\ub97c \uc0ad\uc81c\ud558\uae30\ub97c \uc6d0\ud558\uc138\uc694?\n\n\uc774 \uc790\ub8cc\ub294 \uad6c\ub9e4\ud558\uc600\uac70\ub098, \ub0b4\ub824\ubc1b\uae30\uc704\ud574 \ub85c\uadf8\uc778\uc774 \ud544\uc694\ud55c \uc790\ub8cc \uc785\ub2c8\ub2e4. v3.mb.deletePurchased.button.delete=&\uc0ad\uc81c v3.mb.deletePurchased.button.cancel=&\ucde8\uc18c v3.topbar.menu.show.logo=\ub85c\uace0 v3.topbar.menu.show.plugin=\ucd94\uac00\uae30\ub2a5 \uc601\uc5ed v3.topbar.menu.show.search=\uac80\uc0c9 v3.topbar.menu.show.frog=\ud30c\ub780 \uac1c\uad6c\ub9ac splash.initializeCore=\ud575\uc2ec\ubd80\ubd84\uc744 \ucd08\uae30\uac12\uc5d0 \ub9de\ucd94\uace0 \uc788\uc74c splash.initializeUIElements=UI \uc694\uc18c\ub97c \ucd08\uae30\uac12\uc5d0 \ub9de\ucd94\uace0 \uc788\uc74c ConfigView.section.transfer.autospeedbeta=\uc790\ub3d9 \uc18d\ub3c4 (\ubca0\ud0c0) # ConfigView.section.ipfilter.peerblocking.group=\ub3d9\ub8cc \ub9c9\uae30 ConfigView.section.ipfilter.autoload.group=\uc790\ub3d9 \ubd88\ub7ec\ub4e4\uc774\uae30 ConfigView.section.ipfilter.autoload.file=IP \ud544\ud130 \ud30c\uc77c \uc790\ub3d9 \ubd88\ub7ec\uc624\uae30 ConfigView.section.ipfilter.autoload.loadnow=\uc9c0\uae08 \ubd88\ub7ec\ub4e4\uc774\uae30 splash.loadIpFilters=IP \ud544\ud130 \ubd88\ub7ec\uc624\uae30.. SpeedTestWizard.set.upload.title=\ub0b4\ub824\ubc1b\uae30 \uc62c\ub9ac\uae30 \uc81c\ud55c \uc124\uc815 SpeedTestWizard.set.download.label=\ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4 \uc81c\ud55c: SpeedTestWizard.set.upload.label=\uc62c\ub9ac\uae30 \uc18d\ub3c4 \uc81c\ud55c: SpeedTestWizard.name.conf.level.absolute=\uc808\ub300\uc801 SpeedTestWizard.name.conf.level.high=\ub192\uc74c SpeedTestWizard.name.conf.level.med=\uc911\uac04 SpeedTestWizard.name.conf.level.low=\ub0ae\uc74c SpeedTestWizard.name.conf.level.none=\uc544\ub2d8 ConfigView.section.transfer.select=\uc790\ub3d9 \uc18d\ub3c4 ConfigView.section.transfer.select.v2=\uc790\ub3d9 \uc18d\ub3c4 (\ubca0\ud0c0) mb.azmustclose.title=\uc2dc\uc791\uc2dc \uc624\ub958 DHTView.title.full_v6=\ubd84\ud3ec\ub41c IPv6 \ub370\uc774\ud130\ubca0\uc774\uc2a4 ConfigView.pluginlist.loadSelected=\uc120\ud0dd\ud55c\uac83 \ubd88\ub7ec\uc624\uae30 SpeedView.stats.asn=\ub124\ud2b8\uc6cc\ud06c: SpeedView.stats.estupcap=\uc62c\ub9ac\uae30 \uc81c\ud55c: SpeedView.stats.estdowncap=\ub0b4\ub824\ubc1b\uae30 \uc81c\ud55c: SpeedView.stats.unknown=\uc54c\uc218 \uc5c6\uc74c SpeedView.stats.manual=\uace0\uce68 dialog.uiswitcher.restart.title=UI \uc120\ud0dd\uae30: Vuze \uc7ac\uc2dc\uc791 \ud544\uc694 # Used for peers which we can't determine. PeerSocket.unknown=\uc54c\uc218\uc5c6\uc74c PeerSocket.unknown_az_style=\uc54c\uc218\uc5c6\uc74c %1/%2 PeerSocket.unknown_shadow_style=\uc54c\uc218\uc5c6\uc74c %1/%2 ConfigTransferAutoSpeed.upload.capacity.usage=\uc62c\ub9ac\uae30 \uc0ac\uc6a9\ub7c9 ConfigTransferAutoSpeed.mode=\ubaa8\ub4dc: ConfigTransferAutoSpeed.capacity.used=% \uc0ac\uc6a9 \uc6a9\ub7c9 ConfigTransferAutoSpeed.while.downloading=\ub0b4\ub9ac\uae30: ConfigTransferAutoSpeed.set.dht.ping=DHT \ud551 \uc124\uc815: ConfigTransferAutoSpeed.set.point=\uc124\uc815 \uc9c0\uc810 (ms) ConfigTransferAutoSpeed.set.tolerance=\uad00\uc6a9\uc131 (ms) ConfigTransferAutoSpeed.ping.time.good=\uc88b\uc740: ConfigTransferAutoSpeed.ping.time.bad=\ub098\uc05c: ConfigTransferAutoSpeed.adjustment.interval=\uc870\uc815 \uac04\uaca9: ConfigTransferAutoSpeed.skip.after.adjust=\uc870\uc815 \ud6c4 \uc0dd\ub7b5: PiecesView.DistributionView.NoAvl=\ud65c\uc131\ud654 \uc870\uac01 PiecesView.DistributionView.weHave=\ub0b4\uac00 \uac00\uc9c4 \uc870\uac01 PiecesView.DistributionView.theyHave=\ub3d9\ub8cc\uac00 \uac00\uc9c4 \uc870\uac01 PiecesView.DistributionView.weDownload=\ub0b4\uac00 \ub0b4\ub824\ubc1b\uace0\uc788\ub294 \uc870\uac01 unix.script.new.title=\uc0c8\ub85c\uc6b4 Vuze \uc2dc\uc791 \uc2a4\ud06c\ub9bd\uc774 \uc788\uc2b5\ub2c8\ub2e4. unix.script.new.button.quit=\uc9c0\uae08 \ub05d\ub124\uae30 unix.script.new.button.continue=\ub2e4\uc74c\uc5d0 \ud558\uaca0\uc2b5\ub2c8\ub2e4 unix.script.new.button.asknomore=\ub2e4\uc2dc \uc54c\ub9ac\uc9c0 \ub9d0\uc544\uc8fc\uc138\uc694 unix.script.new.auto.title=\uc0c8\ub85c\uc6b4 Vuze \uc2dc\uc791 \uc2a4\ud06c\ub9bd Content.alert.notuploaded.button.stop=&\uba48\ucda4 Content.alert.notuploaded.button.continue=&\ubfcc\ub9ac\uae30 \uacc4\uc18d Content.alert.notuploaded.button.abort=&\ub05d\ub0b4\uc9c0 \uc54a\uc74c ConfigView.label.checkOnSeeding=\ubfcc\ub9b4\ub54c \ub0ae\uc740 \uc6d0\ubcf8\uc758 \uc870\uac01\uc744 \ub2e4\uc2dc\ud655\uc778 \ud55c\ub2e4\ub294 \uac83\uc744 \uc54c\ub9bc SpeedTestWizard.finish.panel.auto.speed=\uc790\ub3d9 \uc18d\ub3c4 : SpeedTestWizard.finish.panel.auto.speed.seeding=\ubfcc\ub9ac\ub294 \ub3d9\uc548 \uc790\ub3d9 \uc18d\ub3c4 : ConfigTransferAutoSpeed.add.comment.to.log.group=\ub514\ubc84\uadf8 \ub85c\uadf8\uc5d0 \ub367\ub9d0 \uc791\uc131 ConfigTransferAutoSpeed.add.comment.to.log=\ub367\ub9d0 \uc791\uc131: ConfigTransferAutoSpeed.log.button=\uae30\ub85d ConfigTransferAutoSpeed.algorithm.selector=\uc790\ub3d9 \uc18d\ub3c4 \uc870\uc808\uae30 ConfigTransferAutoSpeed.algorithm=\uc5f0\uc0b0 \ubc29\ubc95: ConfigTransferAutoSpeed.auto.speed.classic=\uc790\ub3d9 \uc18d\ub3c4 \uc870\uc808(\uc774\uc804\ubc84\uc804) ConfigTransferAutoSpeed.auto.speed.beta=\uc790\ub3d9 \uc18d\ub3c4 \uc870\uc808(\ubca0\ud0c0) ConfigTransferAutoSpeed.data.update.frequency=\uc5c5\ub370\uc774\ud2b8 \uac04\uaca9 Alert.failed.update=\ucd5c\uc18c \ud558\ub098 \uc774\uc0c1\uc758 \ucef4\ud3ec\ub10c\ud2b8 \uc124\uce58\uac00 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. Azureus\uc704\ud0a4: \uc5c5\ub370\uc774\ud2b8 \uc2e4\ud328 [%1]\ub97c \ucc38\uace0 \ud558\uc138\uc694. MyTorrentsView.menu.exporthttpseeds=HTTP \uc528\uc557 \uc8fc\uc18c\ub97c \ud06c\ub9ac\ub9bd\ubcf4\ub4dc\ub85c \ub0b4\ubcf4\ub0b4\uae30 ConfigView.label.minannounce=\ub354\ub4ec\uc774 \uc54c\ub9ac\uae30 \uc0ac\uc774\uc758 \ucd5c\uc18c\uc2dc\uac04 (\ucd08) ConfigView.label.maxnumwant=\ub354\ub4ec\uc774\uac00 \ub2e4\uc2dc \ub3cc\uc544\uc62c\ub54c \uc81c\ud55c\ub41c \uc218\uc758 \ub3d9\ub8cc ConfigView.label.announceport=\ub354\ub4ec\uc774 \uc54c\ub9ac\uae30\ub97c \uc704\ud574\uc11c \uc54c\ub9ac\uae30 TCP\ud3ec\ud2b8\ub97c \uc624\ubc84\ub77c\uc774\ub4dc \ud568(PEX\uc640 DHT)\n[\ube48\uce78\uc73c\ub85c \ub0a8\uaca8\ub460: \uc624\ubc84\ub77c\uc774\ub4dc \uc5c6\uc74c, 0: \ub4e4\uc5b4\uc624\ub294 \uc5f0\uacb0 \uc5c6\uc74c] ConfigView.label.noportannounce=\ub354\ub4ec\uc774\uc5d0\uac8c \ub4e3\uae30\ud3ec\ud2b8 \uc54c\ub9ac\uc9c0 \uc54a\uc74c (PEX, DHT\uc5d0 \uc601\ud5a5\uc5c6\uc74c) ConfigView.label.maxseedspertorrent=\ud1a0\ub7f0\ud2b8\ubcc4 \uae30\ubcf8 \ucd5c\uace0 \uc528\uc557\uc218 [0: \ubb34\uc81c\ud55c] wizard.webseed=HTTP \uc528\uc557\uc744 \ud1a0\ub7f0\ud2b8\uc5d0 \ucd94\uac00 wizard.webseed.title=HTTP \uc528\uc557 wizard.webseed.configuration=HTTP \uc528\uc557 \uc124\uc815 wizard.webseed.adding=HTTP \uc528\uc557 \ucd94\uac00 GeneralView.label.private=\ube44\uacf5\uac1c \ud1a0\ub7f0\ud2b8 : GeneralView.yes=\ub124 GeneralView.no=\uc544\ub2c8\uc624 Peers.column.timetocomplete=\ub0a8\uc740\uc2dc\uac04 Peers.column.timetocomplete.info=\ub3d9\ub8cc\uac00 \ub2e4\ubc1b\uae30 \uc804\uae4c\uc9c0 \ub0a8\uc740\uc2dc\uac04 Progress.reporting.status.canceled=\ucde8\uc18c\ub428 Progress.reporting.status.retrying=\uc7ac\uc2dc\ub3c4.. Progress.reporting.action.label.retry.tooltip=\uc791\uc5c5 \uc7ac\uc2dc\ub3c4 Progress.reporting.action.label.cancel.tooltip=\uc791\uc5c5 \ucde8\uc18c Progress.reporting.action.label.detail=\uc138\ubd80\ub0b4\uc6a9 Progress.reporting.default.error=\uc2e4\ud328 webui.bindip=IP \uc228\uae30\uae30 - \uc77c\ubc18\uc801\uc73c\ub85c \uad8c\uc7a5\ub418\uc9c0 \uc54a\uc74c (*) v3.MainWindow.text.log.in=\ub85c\uadf8\uc778 v3.MainWindow.text.log.out=\ub85c\uadf8\uc544\uc6c3 v3.MainWindow.text.get.started=\uac00\uc785 v3.MainWindow.text.my.account=\uacc4\uc815 \uc815\ubcf4 v3.MainWindow.text.my.profile=\ud504\ub85c\ud544 OpenTorrentWindow.simple.open=\ud1a0\ub7f0\ud2b8 \uc704\uce58 (\ud30c\uc77c, URL, \ud574\uc26c) Progress.reporting.window.remove.auto=\ud65c\uc131\ud654 \ub418\uc9c0 \uc54a\uc740 \uc544\uc774\ud15c \uc790\ub3d9 \uc0ad\uc81c Progress.reporting.window.remove.now=\ud65c\uc131\ud654 \ub418\uc9c0 \uc54a\uc740 \uc544\uc774\ud15c \uc0ad\uc81c TorrentOptionsView.multi.title.short=\ud1a0\ub7f0\ud2b8 \uc120\ud0dd\uc0ac\ud56d TorrentOptionsView.multi.title.full=\ud1a0\ub7f0\ud2b8 \uc120\ud0dd\uc0ac\ud56d MyTorrentsView.menu.open_parent_folder=\uc800\uc7a5 \ud3f4\ub354 \uc5f4\uae30 ConfigView.section.stats.exportfiles=\ud30c\uc77c \uc138\ubd80\uc815\ubcf4 \ub0b4\ubcf4\ub0b4\uae30 v3.MainWindow.tab.minilibrary=\ub0b4\ub824\ubc1b\uae30 v3.MainWindow.tab.events=\uc54c\ub9bc button.columnsetup.tooltip=\uc138\ub85c\uc904 \uc124\uc815 v3.activity.remove.title=\uc54c\ub9bc \uc0ad\uc81c v3.activity.remove.text=\uc774 \ub0b4\uc6a9\uc744 \uc54c\ub9bc\uc5d0\uc11c \uc0ad\uc81c\ud560\uae4c\uc694? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=\ub2eb\uae30 Menu.show.torrent.menu=\ud1a0\ub7f0\ud2b8 \uba54\ub274 \ubcf4\uae30 #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=\ub124\ud2b8\uc6cc\ud06c \uc0c1\ud0dc menu.sortByColumn=%1\ub85c \uc815\ub82c v3.button.removeActivityEntry=\uc54c\ub9bc\uc5d0\uc11c \uc81c\uac70 v3.splash.initSkin=UI \uc2a4\ud0a8 \ucd08\uae30\ud654 v3.splash.hookPluginUI=\ucd94\uac00\uae30\ub2a5 UI \uace0\uc815 MainWindow.menu.window.zoom.maximize=\ucd5c\ub300\ud654 MainWindow.menu.window.zoom.restore=\ub418\ub3cc\ub9ac\uae30 security.crypto.password=\uc554\ud638 security.crypto.password2=\uc554\ud638 \uc7ac\uc785\ub825 security.crypto.persist_for.session=\uc774\ubc88 \uc138\uc158 security.crypto.persist_for.day=\ud558\ub8e8 security.crypto.persist_for.week=\ud55c\uc8fc security.crypto.persist_for.30days=\ud55c\ub2ec security.crypto.persist_for.forever=\uc885\ud569 security.crypto.password.mismatch.title=\uc554\ud638 \uc624\ub958 ConfigView.section.security.group.crypto=\uacf5\uac1c/\ube44\uacf5\uac1c \ud0a4 ConfigView.section.security.resetkey=\ud0a4 \ucd08\uae30\ud654 ConfigView.section.security.resetkey.warning.title=\ub370\uc774\ud0c0 \uc720\uc2e4 \uacbd\uace0 ConfigView.section.security.unlockkey.button=\uc7a0\uae08\ud574\uc81c ConfigView.section.security.publickey=\uacf5\uac1c \ud0a4 ConfigView.section.security.publickey.undef=\uc815\uc758 \ub418\uc9c0 \uc54a\uc74c ConfigView.section.security.resetkey.error.title=\uc791\ub3d9 \uc2e4\ud328 ConfigView.section.security.resetkey.error=\ud0a4 \ucd08\uae30\ud654 \uc2e4\ud328 ConfigView.copy.to.clipboard.tooltip=\ud074\ub9bd\ubcf4\ub4dc\ub85c \ubcf5\uc0ac Views.plugins.azbuddy.title=\uce5c\uad6c Browser.popup.error.no.access=\uc6d0\uaca9 \uc811\uc18d\uc744 \ud558\ub294\ub3d9\uc548 \uc624\ub958\uac00 \ubc1c\uc0dd\ud558\uc600\uc2b5\ub2c8\ub2e4.\n\uc7a0\uc2dc \ud6c4 \ub2e4\uc2dc \ud55c\ubc88 \uc2dc\ub3c4\ud574 \uc8fc\uc138\uc694. azbuddy.name=\uce5c\uad6c azbuddy.enabled=\uc791\ub3d9 azbuddy.disabled=\ucd94\uac00\uae30\ub2a5\uc774 \uc791\ub3d9\uc911\uc9c0\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ucd94\uac00\uae30\ub2a5 \uc120\ud0dd\uc0ac\ud56d\uc744 \ucc38\uace0\ud558\uc138\uc694. azbuddy.nickname=\ubcc4\uba85 azbuddy.msglog.title=\uce5c\uad6c \uc815\ubcf4 azbuddy.addtorrent.title=\uc790\ub8cc\ub97c \ub0b4\ub824\ubc1b\uc73c\uc2dc\uaca0\uc2b5\ub2c8\uae4c? azbuddy.addtorrent.msg='%1' \uac00 '%2'\ub97c \ubcf4\ub0c8\uc2b5\ub2c8\ub2e4.\n\uc790\ub8cc\ub97c \ub0b4\ub824\ubc1b\uc73c\uc2dc\uaca0\uc2b5\ub2c8\uae4c? azbuddy.contextmenu=\uce5c\uad6c\uc5d0\uac8c \ubcf4\ub0b4\uae30 azbuddy.ui.mykey=\ud0a4: azbuddy.ui.add=\ub354\ud558\uae30 azbuddy.ui.new_buddy=\uc0c8 \uce5c\uad6c\uc758 \ud0a4: azbuddy.ui.table.name=\uc774\ub984 azbuddy.ui.table.online=\uc628\ub77c\uc778 azbuddy.ui.table.last_msg=\ub9c8\uc9c0\ub9c9 \ucabd\uc9c0 azbuddy.ui.menu.remove=\uc81c\uac70 azbuddy.ui.menu.copypk=\uacf5\uac1c\ud0a4 \ubcf5\uc0ac azbuddy.ui.menu.send=\ucabd\uc9c0 \ubcf4\ub0b4\uae30 azbuddy.ui.menu.send_msg=\uce5c\uad6c\uc5d0\uac8c \ubcf4\ub0bc \ucabd\uc9c0\ub0b4\uc6a9\uc744 \uc785\ub825\ud558\uc138\uc694 azbuddy.ui.menu.ping=\ud551 azbuddy.ui.menu.ygm=YGM\ubcf4\ub0b4\uae30 azbuddy.ui.menu.enc=\uac8c\uc2dc\ud310 \uc554\ud638\ud654 azbuddy.ui.menu.dec=\uac8c\uc2dc\ud310 \uc554\ud638\ud574\uc81c azbuddy.ui.menu.sign=\uac8c\uc2dc\ud310\uc5d0 \uc4f0\uae30 azbuddy.ui.menu.verify=\uac8c\uc2dc\ud310 \ud655\uc778 azbuddy.ui.table.lastseen=\ub9c8\uc9c0\ub9c9 \uc811\uc18d Button.retry=\ub2e4\uc2dc\uc2dc\ub3c4 &R Button.ignore=\ubb34\uc2dc &I azbuddy.ui.table.msg_in=\ubc1b\uc740 \ucabd\uc9c0 azbuddy.ui.table.msg_out=\ubcf4\ub0b8 \ucabd\uc9c0 v3.MainWindow.menu.view.footer=\uaf2c\ub9ac\ub9d0 azbuddy.downspeed=\uce5c\uad6c\ub85c\ubd80\ud130 \ub0b4\ub824\ubc1b\uae30 \uc18d\ub3c4 \ucd5c\ub300\uac12 KB/s [0: \ubb34\uc81c\ud55c] ConfigView.section.security.backupkeys=\ud0a4\ub97c \ud30c\uc77c\ub85c \ubc31\uc5c5 ConfigView.section.security.backupkeys.button=\ubc31\uc5c5 ConfigView.section.security.restorekeys=\ud30c\uc77c\ub85c \ubd80\ud130 \ud0a4 \ubcf5\uad6c ConfigView.section.security.restorekeys.button=\ubcf5\uad6c ConfigView.section.security.op.error.title=\uc791\ub3d9 \uc2e4\ud328 ConfigView.section.security.restart.title=\uc7ac\uc2dc\uc791\uc774 \ud544\uc694\ud568 azbuddy.ui.table.msg_queued=\ub300\uae30 azbuddy.ui.menu.chat=\ub300\ud654 azbuddy.chat.title=Vuze \ub300\ud654\uc2e4 azbuddy.chat.says=%1 : Button.bar.show=\ubcf4\uc774\uae30 Button.bar.hide=\uc228\uae30\uae30 Button.bar.share=\uacf5\uc720 Button.bar.add=\ucd94\uac00 Button.bar.edit=\ud3b8\uc9d1 Button.bar.edit.cancel=\ud3b8\uc9d1 \uc644\ub8cc v3.MainWindow.menu.view.pluginbar=\ucd94\uac00\uae30\ub2a5 \ud45c\uc2dc\uc904 MainWindow.dialog.select.vuze.file=Vuze \ud30c\uc77c \uc120\ud0dd MainWindow.menu.file.open.vuze=Vuze \ud30c\uc77c... metasearch.addtemplate.title=\uac80\uc0c9\ud55c \uc591\uc2dd\uc744 \uc124\uce58\ud560\uae4c\uc694? v3.share.private.title=\ud1a0\ub7f0\ud2b8 \uacf5\uc720 v3.share.private.text=\uc120\ud0dd\ub41c \ud1a0\ub7f0\ud2b8\ub294 \ube44\uacf5\uac1c \ud1a0\ub7f0\ud2b8 \uc785\ub2c8\ub2e4.\n\n\ube44\uacf5\uac1c \ud1a0\ub7f0\ud2b8\ub294 \uacf5\uc720\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. metasearch.addtemplate.dup.title=\uc591\uc2dd \ubcf5\uc0ac metasearch.addtemplate.dup.desc=\uac80\uc0c9\ud55c \uc591\uc2dd %1\uc740 \uc774\ubbf8 \uc124\uce58\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4. metasearch.export.select.template.file=\uc591\uc2dd \uc800\uc7a5 metasearch.import.select.template.file=\uc591\uc2dd \uc5f4\uae30 dialog.uiswitch.title=Vuze UI \ubcc0\uacbd dialog.uiswitch.text=\uc774 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\ub824\uba74 Vuze UI\ub97c \uc791\ub3d9\uc2dc\ucf1c\uc57c \ud569\ub2c8\ub2e4.\n\nVuze\ub97c \ub2e4\uc2dc\uc2dc\uc791 \ud569\ub2c8\ub2e4. dialog.uiswitch.button=Vuze UI\ub85c \ubcc0\uacbd azbuddy.tracker.enabled=\uce5c\uad6c\uc640 \ub0b4\ub824\ubc1b\uae30\uc2dc '\uce5c\uad6c \uac00\uc18d' \uae30\ub2a5\uc744 \uc791\ub3d9\ud569\ub2c8\ub2e4 azbuddy.protocolspeed=\uce5c\uad6c\ub85c\ubd80\ud130 \uc624\ubc84\ud5e4\ub4dc \ud504\ub85c\ud1a0\ucf5c \ucd5c\ub300\uac12 KB/s v3.MainWindow.button.download=\ub0b4\ub824\ubc1b\uae30 v3.MainWindow.button.run=\ub0b4\ub824\ubc1b\uc740 \ud30c\uc77c \uc2e4\ud589 v3.activity.header.downloads=\ub0b4\ub824\ubc1b\uae30 v3.activity.header.vuze.news=Vuze \uc0c8\uc18c\uc2dd message.status.success=\uc131\uacf5 azbuddy.tracker.bbb.status.title=\uce5c\uad6c \uac00\uc18d azbuddy.tracker.bbb.status.title.tooltip=\uc138\ubd80\ub0b4\uc6a9\uc744 \ubcf4\uc2dc\ub824\uba74 \ub354\ube14\ud074\ub9ad \ud558\uc138\uc694 azbuddy.tracker.bbb.status.idle=\uac00\uc18d \uc5c6\uc74c azbuddy.tracker.bbb.status.nli=\ub85c\uadf8\uc778\uc774 \ud544\uc694\ud568 azbuddy.tracker.bbb.status.in=\uac00\uc18d \uc2dc\uc791 azbuddy.tracker.bbb.status.out=\uc774\ubbf8 \uac00\uc18d\ub41c \uce5c\uad6c v3.MainWindow.search.go.tooltip=\uac80\uc0c9 \uc2e4\ud589 v3.MainWindow.search.last.tooltip=\uac80\uc0c9\uacb0\uacfc\ub85c \uc774\ub3d9 metasearch.addtemplate.done.title=\ud15c\ud50c\ub9bf \ucd94\uac00 fileplugininstall.install.title=\ucd94\uac00\uae30\ub2a5\uc744 \uc124\uce58 \ud560\uae4c\uc694? fileplugininstall.duplicate.title=\ucd94\uac00\uae30\ub2a5 \ubcf5\uc0ac azbuddy.online_status=\uc811\uc18d \uc0c1\ud0dc azbuddy.os_online=\uc628\ub77c\uc778 azbuddy.os_away=\uc790\ub9ac\ube44\uc6c0 azbuddy.os_not_avail=\ube44\ud65c\uc131 azbuddy.os_busy=\ubc14\uc068 azbuddy.os_offline=\uc624\ud504\ub77c\uc778 azbuddy.ui.menu.disconnect=\uc5f0\uacb0\ub04a\uae30 azbuddy.enable_chat_notif=\ub300\ud654 \uc54c\ub9bc \uc791\ub3d9 DetailedListView.title=\uc138\ubd80 \ubaa9\ub85d subscript.add.title=\uad6c\ub3c5\uc744 \uc124\uce58\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? subscript.add.desc='%1'\ub97c \uad6c\ub3c5\ud558\uc5ec \uc124\uce58\ud558\uc2dc\uae38 \uc6d0\ud558\uc2ed\ub2c8\uae4c? subscript.add.dup.title=\ubcf5\uc0ac\ud558\uae30 subscript.add.dup.desc='%1'\ub294 \uc774\ubbf8 \uad6c\ub3c5\ud558\uc5ec \uc124\uce58\ud558\uc600\uc2b5\ub2c8\ub2e4. subscript.add.upgrade.title=\uad6c\ub3c5\uc744 \uc5c5\ub370\uc774\ud2b8 \ud560\uae4c\uc694? subscript.add.upgrade.desc='%1'\uc744 \uc5c5\ub370\uc774\ud2b8 \ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? subscript.add.upgradeto.desc=\uad6c\ub3c5\uc911\uc778 %1 \ubc84\uc804\uc758 \uc0c8 \ubc84\uc804\uc778 '%2'\uc744 \uc5c5\ub370\uc774\ud2b8 \uac00\ub2a5\ud569\ub2c8\ub2e4.\n\uc5c5\ub370\uc774\ud2b8 \ud560\uae4c\uc694? azsubs.contextmenu.addassoc=\uc0c8 \uad6c\ub3c5 \uc5f0\ub3d9 \ucd94\uac00\ud558\uae30 azsubs.contextmenu.lookupassoc=\uad6c\ub3c5 \uc5f0\ub3d9 \ubcf4\uae30 iconBar.start=\uc2dc\uc791 iconBar.stop=\uba48\ucda4 iconBar.remove=\uc0ad\uc81c iconBar.up=\uc704\ub85c iconBar.down=\uc544\ub798\ub85c iconBar.run=\uc2e4\ud589 iconBar.editcolumns=\uc138\ub85c\uc904 \uc124\uc815 iconBar.top=\uc704\ub85c \uc62e\uae40 iconBar.bottom=\uc544\ub798\ub85c \uc62e\uae40 iconBar.queue=\uc2dc\uc791 iconBar.open=\ud1a0\ub7f0\ud2b8 \ucd94\uac00 iconBar.share=\uacf5\uc720 iconBar.share.tooltip=\uacf5\uc720 \uc790\ub8cc iconBar.details=\uc138\ubd80\ub0b4\uc6a9 iconBar.comment=\ub367\ub9d0 iconBar.play=\uc7ac\uc0dd iconBar.queue.tooltip=\ub300\uae30 v3.MainWindow.menu.view.sidebar=\uce21\uba74 \ud45c\uc2dc\uc904 v3.MainWindow.menu.view.actionbar=\uc2e4\ud589 \ud45c\uc2dc\uc904 v3.MainWindow.menu.view.toolbars=\ub3c4\uad6c \ud45c\uc2dc\uc904 subscriptions.listwindow.title=\uad6c\ub3c5\uac00\ub2a5\ud55c \uc790\ub8cc \ucc3e\uae30 subscriptions.listwindow.autochecktext=Vuze\ub294 \uc790\ub3d9\uc73c\ub85c \ub77c\uc774\ube0c\ub7ec\ub9ac\uc5d0 \uc788\ub294 \uc790\ub8cc\uc640 \uc720\uc0ac\ud55c \uad6c\ub3c5\uc744 \ucc3e\uc544 \uc81c\uc2dc\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc774\uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? subscriptions.listwindow.loadingtext=%1\uacfc \uc5f0\uad00\ub41c \uad6c\ub3c5\uc744 \ucc3e\uc544\ubcf4\uae30 subscriptions.listwindow.failed=\uad6c\ub3c5\uac00\ub2a5\ud55c \uc790\ub8cc\uac00 \uc5c6\uc74c subscriptions.listwindow.popularity=\uc778\uae30\ub3c4 subscriptions.listwindow.popularity.unknown=\uc54c\uc218\uc5c6\uc74c subscriptions.listwindow.name=\uc774\ub984 subscriptions.listwindow.subscribe=\uad6c\ub3c5 TableColumn.header.azsubs.ui.column.subs=\uad6c\ub3c5 subscriptions.listwindow.popularity.reading=\uc77d\ub294\uc911... PluginDeprecation.view=\uc624\ub958\ucd94\uc801 \ucd94\uac00\uae30\ub2a5 TableColumn.header.Thumbnail=\uc544\uc774\ucf58 v3.MainWindow.menu.getting_started=&\uc2dc\uc791\ud558\uae30 MainWindow.menu.community=&\ucee4\ubba4\ub2c8\ud2f0 MainWindow.menu.help.faq=\uc790\uc8fc \ubb3b\ub294 \ubb3c\uc74c(&F) MainWindow.menu.community.wiki=\ucee4\ubba4\ub2c8\ud2f0 &\uc704\ud0a4 MainWindow.menu.community.forums=\ucee4\ubba4\ub2c8\ud2f0 Fo&rums MainWindow.menu.community.blog=Vuze &\ube14\ub85c\uadf8 externalLogin.title=\ub85c\uadf8\uc778 \ud544\uc694 Button.done=\uc644\ub8cc Button.continue=\uacc4\uc18d Button.preview=\ubbf8\ub9ac\ubcf4\uae30 Subscription.menu.forcecheck=\uc9c0\uae08 \uc5c5\ub370\uc774\ud2b8 Subscription.menu.clearall=\ubaa8\ub4e0 \uc790\ub8cc\ub97c "\uc77d\uc74c" \uc0c1\ud0dc\ub85c \ud45c\uc2dc Subscription.menu.remove=\uc0ad\uc81c sidebar.Library=\ub77c\uc774\ube0c\ub7ec\ub9ac sidebar.LibraryDL=\ub0b4\ub824\ubc1b\ub294 \uc911 sidebar.LibraryCD=\uc644\ub8cc authenticator.location=\uc704\uce58 authenticator.details=\uc138\ubd80\uc815\ubcf4 v3.MainWindow.menu.showActionBarText=\ubb38\uc790\ubcf4\uae30 Subscription.menu.export=\ub0b4\ubcf4\ub0b4\uae30 subscript.export.select.template.file=\uad6c\ub3c5 \uc800\uc7a5 Button.remove=\uc81c\uac70 Button.send=\ubcf4\ub0b4\uae30 Button.back=\ub4a4\ub85c sidebar.LibraryUnopened=\ub0b4\ub824\ubc1b\uae30 \uc644\ub8cc TableColumn.header.unopened=\uc2e0\uaddc Unopened.bigView.header=\uc2e0\uaddc Subscription.menu.deleteall=\ubaa8\ub4e0 \uc790\ub8cc \uc0ad\uc81c Subscription.menu.reset=\ucc98\uc74c \uc0c1\ud0dc\ub85c \ucd08\uae30\ud654 ConfigView.section.Subscriptions=\uad6c\ub3c5 subscriptions.config.maxresults=\uad6c\ub3c5\ubcc4 \uc720\uc9c0\ud558\uace0 \uc788\ub294 \uc790\ub8cc\uc758 \ucd5c\ub300\uac12 [0: \ubb34\uc81c\ud55c] v3.activity.button.readall=\ubaa8\ub450 \uc77d\uc5c8\uc74c\uc73c\ub85c \ud45c\uc2dc TableColumn.header.activityNew=\uc2e0\uaddc TableColumn.header.activityType=\uc885\ub958 TableColumn.header.activityText=\ub0b4\uc6a9 TableColumn.header.activityDate=\ucd94\uac00 \ub0a0\uc9dc TableColumn.header.activityActions=\ud3c9\uac00 Subscription.menu.resetauth=\uc778\uc99d \uc815\ubcf4 \ucd08\uae30\ud654 Search.menu.engines=\uc591\uc2dd Wizard.Subscription.title=\uad6c\ub3c5 Wizard.Subscription.optin.title=\uad6c\ub3c5\uc791\ub3d9 #what you've watched? Discover more with a single click... Wizard.Subscription.subscribe.title=\ud65c\uc131\ud654 \uad6c\ub3c5 Wizard.Subscription.create.title=\uc0c8 \uad6c\ub3c5 \ub9cc\ub4e4\uae30 Button.search=\uac80\uc0c9 Button.save=\uc800\uc7a5 Button.add=\ucd94\uac00 Button.createNewSubscription=\uc0c8\ub85c\uc6b4 \uc790\ub8cc \uad6c\ub3c5 \ud558\uae30 Button.availableSubscriptions=\uc0ac\uc6a9\uac00\ub2a5\ud55c \uad6c\ub3c5 Wizard.Subscription.optin.description=\uad6c\ub3c5\uae30\ub2a5\uc744 \uc791\ub3d9\uc2dc\ud0a4\uba74, Vuze\ub294 \uc790\ub3d9\uc73c\ub85c \uad6c\ub3c5\ud55c \uc790\ub8cc\ub97c \ub77c\uc774\ube0c\ub7ec\ub9ac\uc5d0 \ud45c\uc2dc\ud558\uc5ec \uc190\uc27d\uac8c \ub0b4\ub824\ubc1b\uc744 \ud560 \uc218 \uc788\ub3c4\ub85d \ud569\ub2c8\ub2e4.\n\n\uad6c\ub3c5\uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? Wizard.Subscription.create.search=\uac80\uc0c9 Wizard.Subscription.search.subtitle1=\uac80\uc0c9\uc744 \ud1b5\ud574 \uc790\ub8cc\ub97c \uad6c\ub3c5\ud558\uc138\uc694 : Wizard.Subscription.search.subtitle2=\uc5b4\ub5a4\uc790\ub8cc\ub97c \uad6c\ub3c5\ud560 \uc218 \uc788\uc744\uae4c\uc694? Wizard.Subscription.search.subtitle2.sub1=Vuze \ub124\ud2b8\uc6cc\ud06c\uc758 \ub2e4\uc591\ud55c HD \uc601\ud654, TV \uc1fc, \ub4dc\ub77c\ub9c8 \uc608\uace0\ud3b8\ub97c \uad6c\ub3c5\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. Wizard.Subscription.search.subtitle2.sub2=\uc778\ud130\ub137\uc5d0 \uc788\ub294 \ud1a0\ub7f0\ud2b8\ub97c \uad6c\ub3c5\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. Wizard.Subscription.search.subtitle3=\uad6c\ub3c5\uc744 \uc2dc\uc791\ud558\uba74, \uc0c8\ub85c\uc6b4 \uc790\ub8cc\uac00 \uc62c\ub77c\uc62c\ub54c \ub9c8\ub2e4 \uce21\uba74 \ud45c\uc2dc\uc904\uc5d0\uc11c \uace7\ubc14\ub85c \ud655\uc778\ud558\uc2e4 \uc218 \uc788\uc2b5\ub2c8\ub2e4. Wizard.Subscription.rss.subtitle1=\uad6c\ub3c5\ud560 URL\uc744 \uc544\ub798\uc5d0 \uc801\uc73c\uc138\uc694 : Wizard.Subscription.rss.subtitle2=\ub9ce\uc740 \uc790\ub8cc\uac00 RSS\ud53c\ub4dc\ub85c \ubc30\ud3ec\ub418\uace0 \uc788\uc2b5\ub2c8\ub2e4. \uc6f9\uc0ac\uc774\ud2b8\uc5d0\uc11c URL\uc8fc\uc18c\ub97c \ucc3e\uc544 \uc717\uce78\uc5d0 \ub123\uace0, \uc800\uc7a5\uc744 \ub20c\ub7ec\uc8fc\uc138\uc694. Wizard.Subscription.rss.subtitle3=\uc790\ub8cc \ubc30\ud3ec\uc790\uac00 RSS \ud53c\ub4dc\ub97c \ud1b5\ud574 \uc0c8\ub85c\uc6b4 \uc790\ub8cc\ub97c \uacf5\uc9c0\ud558\uba74, \uce21\uba74 \ud45c\uc2dc\uc904\uc5d0\uc11c \uc2e4\uc2dc\uac04\uc73c\ub85c \ub0b4\ub824\ubc1b\uae30 \uac00\ub2a5\ud55c \uc790\ub8cc\uac00 \uc5c5\ub370\uc774\ud2b8\ub429\ub2c8\ub2e4. Wizard.Subscription.subscribe.library=\ub77c\uc774\ube0c\ub7ec\ub9ac\uc758 \uc790\ub8cc Wizard.Subscription.subscribe.subscriptions=\uc5f0\uad00\ub41c \uad6c\ub3c5 Wizard.Subscription.subscribe.library.empty=\uc544\uc9c1 \uad6c\ub3c5\ud558\ub294 \uc790\ub8cc\uac00 \uc5c6\uc73c\uc138\uc694?\n \nVuze HD \ub124\ud2b8\uc6cc\ud06c\uc5d0\uc11c \ub178\ub780\uc0c9\uc73c\ub85c \ub41c RSS \uad6c\ub3c5 \ub2e8\ucd94\ub97c \ub20c\ub7ec\ubcf4\uc138\uc694.\n \n\uad00\ub828\ub0b4\uc6a9 message.confirm.delete.title=\uc0ad\uc81c \ud655\uc778 message.confirm.delete.text='%1'\ub97c \uc815\ub9d0\ub85c \uc9c0\uc6b0\uc2dc\uaca0\uc2b5\ub2c8\uae4c? Subscription.menu.properties=\uc6b0\uc120\uc21c\uc704 subs.prop.is_auto=\uc0c8 \uacb0\uacfc\uc5d0 \ub300\ud574 \uc790\ub3d9 \ub0b4\ub824\ubc1b\uae30 subs.prop.last_scan=\ub9c8\uc9c0\ub9c9 \uc131\uacf5 \uc5c5\ub370\uc774\ud2b8 subs.prop.last_result=\ub9c8\uc9c0\ub9c9 \uc0c8 \uacb0\uacfc \ucc3e\uae30 subs.prop.last_error=\ub9c8\uc9c0\ub9c9 \uc624\ub958 subs.prop.num_read=\uc77d\uc740 \uc790\ub8cc\uc218 subs.prop.num_unread=\uc54a\uc77d\uc740 \uc790\ub8cc\uc218 subs.prop.template=\uc591\uc2dd externalLogin.wait=\ud654\uba74 \ubd88\ub7ec\uc624\ub294\uc911, \uc7a0\uc2dc\ub9cc \uae30\ub2e4\ub824 \uc8fc\uc138\uc694. TableColumn.menu.date_added.time=\uc2dc\uac04 \ubcf4\uc774\uae30/\uc228\uae30\uae30 sidebar.VuzeHDNetwork=Vuze HD \ub124\ud2b8\uc6cc\ud06c subs.prop.version=\ubc84\uc804 subscriptions.column.new.info=\uc0c8\ub85c\uc6b4 \uacb0\uacfc\uac00 \uc788\uc73c\uba74 \ud45c\uc2dc\ud568 subscriptions.column.name=\uc774\ub984 subscriptions.column.nb-results=\ubaa8\ub4e0 \uc790\ub8cc subscriptions.column.nb-new-results=\uc0c8 \uc790\ub8cc subscriptions.column.last-checked=\ub9c8\uc9c0\ub9c9 \ud655\uc778 subscriptions.view.title=\uad6c\ub3c5 subs.prop.is_public=\uacf5\uac1c\ub428 Subscription.menu.upgrade=\ucd5c\uc2e0 \ubc84\uc804\uc73c\ub85c \uc790\ub3d9 \uc5c5\ub370\uc774\ud2b8 \uae30\ub2a5 \uc0ac\uc6a9 metasearch.addtemplate.failed.title=\uc124\uce58 \uc2e4\ud328 metasearch.addtemplate.failed.desc=\uac80\uc0c9\ud55c \uc591\uc2dd\uc744 \uc124\uce58\ud558\ub294\ub370 \uc2e4\ud328\ud568: %1 subscription.version.bad=Vuze\ub97c \uc5c5\ub370\uc774\ud2b8 \ud558\uae30\uc804\uae4c\uc9c0 '%1'\uac00 \uc124\uce58 \ub420 \uc218 \uc5c6\uc74c statusbar.feedback=\uc758\uacac \ubcf4\ub124\uae30 statusbar.feedback.tooltip=\uc5ec\uae30\ub97c \ub20c\ub7ec\uc11c \uc81c\uc791\uc9c4\uc5d0\uac8c \uc870\uc5b8/\uc758\uacac\uc744 \ubcf4\ub0c5\ub2c8\ub2e4. sidebar.Activity=\uc54c\ub9bc v3.activity.button.watchall=\ubaa8\ub4dc \ubcf4\uc558\uc74c\uc73c\ub85c \ud45c\uc2dc subscriptions.view.help.1=\ubcf4\uace0\uc2f6\uc740 \uc790\ub8cc\ub97c \uad6c\ub3c5\ud558\uc138\uc694 subscriptions.view.help.2=\ub0b4\ub824\ubc1b\uae30 \uac00\ub2a5\ud55c \uc0c8\uc790\ub8cc\ub97c \uc2e4\uc2dc\uac04\uc73c\ub85c \uc5c5\ub370\uc774\ud2b8 \ud558\ub294 \ubc29\ubc95\uc744 \ud65c\uc6a9\ud558\uc138\uc694. \ub354 \uc54c\uc544\ubcf4\uae30. sidebar.sash.tooltip=F7\ub85c \uce21\uba74 \ud45c\uc2dc\uc904 \ubcf4\uc774\uae30/\uc228\uae30\uae30 sidebar.expand.tooltip=\uce21\uba74 \ud45c\uc2dc\uc904 \ud3bc\uce58\uae30 sidebar.dropdown.tooltip=\uba54\ub274\uc5d0\uc11c \uce21\uba74 \ud45c\uc2dc\uc904 \ud45c\uc2dc subscript.all.subscribed=\uc774 \uc790\ub8cc\ub97c \uad6c\ub3c5\ud588\uc2b5\ub2c8\ub2e4 subscript.some.subscribed=\uc774 \uc790\ub8cc\ub97c \uc704\ud574\uc11c \uc774\ubbf8 \uad6c\ub3c5\ud558\uace0 \uc788\ub294\uac83\uc774 \uc788\uc2b5\ub2c8\ub2e4.\n\ub0b4\uc6a9\uc744 \ubcf4\uc2dc\ub824\uba74 \ud074\ub9ac\ud558\uc138\uc694 subscript.none.subscribed=\uc774 \uc790\ub8cc\uc640 \uc5f0\uad00\ub41c \uad6c\ub3c5\uc744 \ubcf4\uc2dc\ub824\uba74 \ud074\ub9ad\ud558\uc138\uc694 v3.iconBar.up.tooltip=\uc704\ub85c \uc62c\ub9ac\uc138\uc694.\n\ub9c8\uc6b0\uc2a4 \ub2e8\ucd94\ub97c \ub204\ub978\ucc44\ub85c \uc704\ub85c \uc62c\ub9ac\uc138\uc694. v3.iconBar.down.tooltip=\uc544\ub798\ub85c \ub0b4\ub9ac\uc138\uc694.\n\ub9c8\uc6b0\uc2a4 \ub2e8\ucd94\ub97c \ub204\ub978\ucc44\ub85c \uc544\ub798\ub85c \ub0b4\ub9ac\uc138\uc694. TableColumn.header.azsubs.ui.column.subs_link.info=\uad6c\ub3c5\uacfc \ud568\uaed8 \uc5f0\ub3d9 Button.deleteContent.fromLibrary=\ub77c\uc774\ube0c\ub7ec\ub9ac\uc5d0\uc11c \uc81c\uac70 Button.deleteContent.fromComputer=\ub514\uc2a4\ud06c\uc5d0\uc11c \uc9c0\uc6b0\uae30 v3.deleteContent.message=\n'%1'\ub97c \ub514\uc2a4\ud06c\uc5d0\uc11c \uc9c0\uc6b0\uc2dc\uaca0\uc2b5\ub2c8\uae4c? \uc544\ub2c8\uba74 Vuze \ub77c\uc774\ube0c\ub7ec\ub9ac\uc5d0\uc11c \ud45c\uc2dc\uac00 \uc548\ub418\uac8c \uc81c\uac70\ub9cc \ud560 \uc218\ub3c4 \uc788\uc2b5\ub2c8\ub2e4. v3.MainWindow.menu.view.toolbartext=\ub3c4\uad6c \ud45c\uc2dc\uc904 \ubb38\uc790 v3.MainWindow.menu.view.asSimpleList=\uac04\ub2e8\ubaa9\ub85d v3.MainWindow.menu.view.asAdvancedList=\uace0\uae09\ubaa9\ub85d v3.MainWindow.menu.view.statusbar=\uc0c1\ud0dc \ud45c\uc2dc\uc904 Subscription.menu.dirtyall=\ubaa8\ub4e0 \uc790\ub8cc\ub97c "\uc77d\uc9c0 \uc54a\uc74c" \uc0c1\ud0dc\ub85c \ud45c\uc2dc configureWizard.file.message3=Vuze\uc5d0\uc11c \ub0b4\ub824\ubc1b\uc740 \ud30c\uc77c\uc744 \ubcf4\uad00\ud560 \ud3f4\ub354\ub97c \uc9c0\uc815\ud558\uc138\uc694: v3.deleteContent.applyToAll=\uc120\ud0dd\ub41c \ubaa8\ub4e0 %1\uc5d0 \uc801\uc6a9\ud569\ub2c8\ub2e4. v3.MainWindow.menu.contentnetworks=HD &\ub124\ud2b8\uc6cc\ud06c v3.MainWindow.menu.contentnetworks.about=HD \ub124\ud2b8\uc6cc\ud06c\uc5d0 \uad00\ud558\uc5ec ConfigTransferAutoSpeed.auto.speed.neural=\uc77c\ubc18 \uc790\ub3d9 \uc18d\ub3c4 \uc870\uc808(\uad6c\ub514 \uc54c\ud30c) ConfigView.label.autoopen.downloadbars=\ub0b4\ub824\ubc1b\uae30 \ud45c\uc2dc\uc904 \uc790\ub3d9\uc5f4\uae30 ConfigView.label.autoopen=\uc790\ub3d9 \uc5f4\uae30 ConfigView.label.autoopen.detailstab=\uc138\ubd80\ub0b4\uc6a9 \ud45c\uc2dc\uc904 \uc790\ub3d9\uc5f4\uae30 v3.MainWindow.menu.contentnetworks.manage=&HD \ub124\ud2b8\uc6cc\ud06c \uad00\ub9ac azbuddy.ui.menu.cat=\ubaa9\ub85d azbuddy.ui.menu.cat.share=\uce5c\uad6c\uc640 \ud568\uaed8 \uad6c\ub3c5 \uc791\ub3d9 azbuddy.ui.menu.cat.set=\ubaa9\ub85d \uc785\ub825 azbuddy.ui.menu.cat.set_msg=\uc27c\ud45c\ub85c \ubaa9\ub85d\uc744 \ub098\ub20c \uc218 \uc788\uc73c\uba70 '\uc804\ubd80' \uc0ac\uc6a9\ud560 \uc218 \ub3c4 \uc788\uc2b5\ub2c8\ub2e4 azbuddy.ui.menu.cat_subs=\uad6c\ub3c5 subs.prop.update_period=\uc5c5\ub370\uc774\ud2b8 \uac04\uaca9 azbuddy.enable_cat_pub=\ubaa8\ub4e0 \uce5c\uad6c\uac00 \uacf5\uac1c\ub41c \ubd84\ub958\ub97c \uad6c\ub3c5\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4 (','\ub85c \uad6c\ubd84\ud568) v3.dialog.cnclose.title=%1 \ub2eb\ud798 v3.dialog.cnclose.subtitle=\uc54c\ub9bc v3.dialog.cnclose.info1=HD \ub124\ud2b8\uc6cd\uc73c\ub85c\uc758 \uc811\uc18d\uc744 \ub2eb\uc73c\uc168\uc2b5\ub2c8\ub2e4. v3.dialog.cnclose.info2=HD \ub124\ud2b8\uc6cd\uc5d0 \ub2e4\uc2dc \uc811\uadfc\ud558\uc2dc\ub824\uba74, \ud654\uba74 \uc717\ubd80\ubd84\uc5d0 "HD \ub124\ud2b8\uc6cd" \uba54\ub274\uc5d0\uc11c "HD \ub124\ud2b8\uc6cd"\uc744 \ub204\ub974\uc2dc\uba74 \ub429\ub2c8\ub2e4. v3.dialog.cnclose.noshow=\ub2e4\uc2dc \ubcf4\uc5ec\uc8fc\uc9c0 \uc54a\uc74c v3.dialog.cnmanage.title=HD \ub124\ud2b8\uc6cc\ud06c \uad00\ub9ac \uba54\ub274 v3.dialog.cnmanage.intro="HD \ub124\ud2b8\uc6cc\ud06c" \uba54\ub274\uc5d0\uc11c \ubcf4\uc774\uace0 \uc2f6\uc740 \uc790\ub8cc\ub97c \uc544\ub798\uc5d0\uc11c \uc120\ud0dd\ud558\uc138\uc694 TableColumn.header.name.info=\ud1a0\ub7f0\ud2b8 \uc774\ub984 TableColumn.header.size.info=\ub514\uc2a4\ud06c\uc5d0\uc11c \ud1a0\ub7f0\ud2b8 \uc790\ub8cc\uc758 \ud06c\uae30 TableColumn.header.azsubs.ui.column.subs.info=\uc774 \ub2e8\ucd94\ub85c \uc5f0\uad00\ub41c \ud1a0\ub7f0\ud2b8\ub97c \uad6c\ub3c5\ubc1b\uc744 \uc218 \uc788\uc74c TableColumn.header.upspeed.info=\ud604\uc7ac\uae4c\uc9c0 \uc62c\ub9ac\uae30 \uc18d\ub3c4 TableColumn.header.downspeed.info=\ud604\uc7ac\uae4c\uc9c0 \ub0b4\ub824\ubc1b\uc740 \uc18d\ub3c4 TableColumn.header.up.info=\ud604\uc7ac\uae4c\uc9c0\ub2e4\ub978 \uc0ac\uc6a9\uc790\uc5d0\uac8c \ubcf4\ub0b8 \ub370\uc774\ud130\uc591 TableColumn.header.down.info=\ud604\uc7ac\uae4c\uc9c0 \ub2e4\ub978 \uc0ac\uc6a9\uc790\ub85c\ubd80\ud130 \ubc1b\uc740 \ub370\uc774\ud130 \uc591 Pieces.column.#.info=\uc870\uac01 \ubc88\ud638 TableColumn.header.TableColumnNameInfo=\uc138\ub85c\uc904 \uc774\ub984\uacfc \uc124\uba85 TableColumn.header.TableColumnSample=\uacac\ubcf8 TableColumn.header.TableColumnInfo=\uc138\ub85c\uc904 \uc124\uba85 TableColumn.header.TableColumnChosenColumn=\uc138\ub85c\uc904 \uc120\ud0dd label.learnmore=\ub354 \uc54c\uc544\ubcf4\uae30 ColumnSetup.title='%1' \uc138\ub85c\uc904 \uc124\uc815 ColumnSetup.explain=\uc67c\ucabd\uc5d0 \ud65c\uc6a9\uac00\ub2a5\ud55c \uc138\ub85c\uc904 \ubaa9\ub85d\uc744 \uc624\ub978\ucabd\uc5d0 \ucd94\uac00\ud558\uc5ec \ubaa9\ub85d\uc5d0\uc11c \ud45c\uc2dc\ud558\uc138\uc694. \uc67c\ucabd \uc704\uc5d0 \uc5ed\uc0bc\uac01\ud615\uc744 \ud3bc\uce58\uba74 \uace8\ub77c\ubcfc\uc218 \uc788\ub294 \uc138\ub85c\uc904 \ubaa9\ub85d\uc774 \ud3bc\uccd0\uc9d1\ub2c8\ub2e4. \ub9c8\uc6b0\uc2a4 \ub04c\uc5b4\uc624\uae30\uc640 \ub2e8\ucd95\ud0a4\ub3c4 \uc9c0\uc6d0\ud569\ub2c8\ub2e4. ColumnSetup.chosencolumns=\uc138\ub85c\uc904 \uc120\ud0dd ColumnSetup.proficiency=\uc219\ub828\ub3c4: ColumnSetup.categories=\ubd84\ub958: ColumnSetup.filters=\uace8\ub77c\ubcf4\uae30 ColumnSetup.availcolumns=%1 \uc138\ub85c\uc904 \ud65c\uc131\ud654 ColumnSetup.availcolumns.filteredby=%2\ub97c \uace8\ub77c\uc11c %1 \uc138\ub85c\uc904 \ud65c\uc131\ud654 devices.view.title=\uc7a5\uce58 device.renderer.view.title=\ub80c\ub354\ub7ec device.mediaserver.view.title=\ubbf8\ub514\uc5b4 \uc11c\ubc84 device.router.view.title=\ub77c\uc6b0\ud130 device.model.desc=\ubaa8\ub378 \uc124\uba85 device.model.name=\ubaa8\ub378 \uba85 device.model.num=\ubaa8\ub378 \ubc88\ud638 device.manu.desc=\uc81c\uc870\uc0ac device.router.is_mapping=\uc790\ub3d9\uc73c\ub85c \ud3ec\ud2b8 \ub9e4\ud551 device.router.req_map=\uc694\uad6c\ub418\ub294 \ud3ec\ud2b8 \ub9e4\ud551 device.router.configure=UPnP \uc124\uc815 device.mediaserver.configure=\ubbf8\ub514\uc5b4 \uc11c\ubc84 \uc124\uc815 device.hide=\uc7a5\uce58 \uac10\ucd94\uae30 device.show=\uc228\uaca8\uc9c4 \uc7a5\uce58 \ud45c\uc2dc device.search=\uc7a5\uce58 \uac80\uc0c9 device.router.con_type=\uc5f0\uacb0: %1 device.browse=\ud0d0\uc0c9 device.upnp.desc_url=\uc7a5\uce58 \uc124\uba85 device.upnp.present_url=\uc7a5\uce58 \uad00\ub9ac\uc790 ConfigView.label.maxStalledSeeding='\ubc1c\ube8c\ud558\uae30(stalled)' \ucd5c\ub300\uac12 [0:\ubb34\uc81c\ud55c] device.search.auto=\uc790\ub3d9\uc73c\ub85c \uc7a5\uce58 \uac80\uc0c9 devices.sidebar.simple=\uac04\ub2e8\ud788 \ubcf4\uae30 devices.xcode.working_dir=\uc790\ub3d9\ubcc0\ud658 \uc601\uc5ed devices.xcode.prof_def=\uc790\ub3d9\ubcc0\ud658 \uae30\ubcf8 \ud504\ub85c\ud544 devices.xcode.profs=\uc790\ub3d9\ubcc0\ud658 \ud504\ub85c\ud544 \ud65c\uc131\ud654 device.lastseen=\ub9c8\uc9c0\ub9c9 \uc52c devices.contextmenu.xcode=\uc678\ubd80\uc7a5\uce58\uc6a9\uc73c\ub85c \uc790\ub8cc \uc790\ub3d9\ubcc0\ud658 devices.device=\uc7a5\uce58 devices.profile=\ud504\ub85c\ud544 General.percent=\ud37c\uc13c\ud2b8 devices.installed=\uc124\uce58\ub428 devices.state=\uc0c1\ud0dc MainWindow.menu.help.donate=\uae30\ubd80\uae08 \ub0b4\uae30 devices.xcode.only.show=\uc7a5\uce58\ub0b4 \uc790\ub3d9\ubcc0\ud658\ub41c \ud30c\uc77c\ub9cc \ud45c\uc2dc device.quit.transcoding.title=\uc790\ub3d9\ubcc0\ud658 \uc9c4\ud589 device.quit.transcoding.text='%1'\uac00 '%2'\uc6a9\uc73c\ub85c \uc790\ub3d9\ubcc0\ud658 \ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ub3d9\uc2dc\uc5d0 %3% \ub85c \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.\n\ub2e4\uc74c \uc2dc\uc791\uc804\uae4c\uc9c0 \uc774 \uc791\uc5c5\uc73c\ub85c \ubd80\ud130 \ubc97\uc5b4\ub0a0 \uc218 \uc788\uc2b5\ub2c8\ub2e4. download.removerules.unauthorised.data=\t\uc81c\uac70\ub41c \ub370\uc774\ud130 device.config.xcode.maxbps=\uc790\ub3d9\ubcc0\ud658 \ube44\uc728 \ucd5c\ub300\uac12 KB/sec [0: \ubb34\uc81c\ud55c] device.xcode=\uc678\ubd80\uc7a5\uce58\uc6a9 \uc790\ub8cc \uc790\ub3d9\ubcc0\ud658 device.xcode.always=\ud56d\uc0c1 \uc608 device.xcode.whenreq=\ud5c8\uc6a9\uc2dc\uc5d0\ub9cc device.xcode.never=\ud56d\uc0c1 \uc544\ub2c8\uc694 devices.sidebar.hide.rend.generic=\uc77c\ubc18\uc7a5\uce58 \uc228\uae30\uae30 v3.devicesview.infobar.text2=\uc678\ubd80\uc7a5\uce58\uc5d0 \uc0ac\uc6a9\ud560 \uc790\ub8cc\ub97c \uc790\ub3d9\ubcc0\ud658\ud558\ub824\uba74, \ub77c\uc774\ube0c\ub7ec\ub9ac\uc5d0\uc11c \uc790\ub8cc\ub97c \ub4dc\ub808\uadf8\ud574\uc11c \uce21\uba74 \ud45c\uc2dc\uc904\uc758 \uc678\ubd80\uc7a5\uce58\uc5d0 \ub5a8\uad6c\uba74 \ub429\ub2c8\ub2e4. \uc790\ub3d9\ubcc0\ud658\uc758 \uc0c1\ud0dc\ub97c \uc54c\uace0\uc2f6\uc73c\uba74 \ud574\ub2f9 \uc678\ubd80\uc7a5\uce58\uc5d0\uc11c \uc624\ub978\ucabd \ud074\ub9ad\uc744 \ud574\ubcf4\uc138\uc694. iconBar.transcode=\uc7a5\uce58 iconBar.transcode.tooltip=\ub0b4\ub824\ubc1b\uc740 \uc790\ub8cc\ub97c \uc678\ubd80\uc7a5\uce58\uc5d0\uc11c\ub3c4 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ubcc0\ud658\uc2dc\ud0a4\uc138\uc694. device.retry.copy=\ubcf5\uc0ac \ub2e4\uc2dc\uc2dc\ub3c4 devices.copy.fail=\uc7a5\uce58\ub85c \ubcf5\uc0ac\uac00 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4 devices.ready=\uc900\ube44 TableColumn.header.trancode_qpos.info=\uc790\ub3d9\ubcc0\ud658 \ub300\uae30\uc21c\uc11c TableColumn.header.profile=\uc7a5\uce58 TableColumn.header.profile.info=\uc790\ub3d9\ubcc0\ud658 \ud504\ub85c\ud544 \uc0ac\uc6a9 TableColumn.header.device=\uc7a5\uce58 TableColumn.header.device.info=\ubaa9\ud45c \uc7a5\uce58 # This is the beginning of the word "View". It's right aligned under the icon bar item v3.iconBar.view.big.tooltip=\uac04\ub2e8\ubaa9\ub85d\uc73c\ub85c \ubcf4\uae30 # This is the end of the word "View". It's left aligned under the icon bar item v3.iconBar.view.small.tooltip=\uace0\uae09\ubaa9\ub85d\uc73c\ub85c \ubcf4\uae30 general.dont.ask.again=\ub2e4\uc2dc \ubb3b\uc9c0 \uc54a\uae30 general.na.short=\uc6a9\ub3c4\uc5c6\uc74c v3.menu.device.exploreTranscodes=\ud30c\uc77c \ubcf4\uae30 v3.menu.device.exploreTranscodes._windows=\ud0d0\uc0c9\uae30\uc5d0\uc11c \ud30c\uc77c\uc704\uce58 \ubcf4\uae30 v3.menu.device.exploreTranscodes._mac=\ud30c\uc778\ub354\uc5d0\uc11c \ud30c\uc77c\uc704\uce58 \ubcf4\uae30 v3.menu.device.defaultprofile=\uae30\ubcf8 \ud504\ub85c\ud544 devices.button.installitunes=iTunes \ud1b5\ud569 \ucd94\uac00\uae30\ub2a5 \uc124\uce58 device.itunes.install=iTunes\ub97c \uc124\uce58 \ud558\uc154\uc57c \ud569\ub2c8\ub2e4. device.itunes.start=iTunes\ub97c \uc2dc\uc791\ud558\uac70\ub098 \uc790\ub3d9 \uc2dc\uc791\uc744 \uc791\ub3d9\uc2dc\ucf1c\uc57c \ud569\ub2c8\ub2e4 device.itunes.install_problem=iTunes\uc640 \ud1b5\ud569\uc774 \ubb38\uc81c\ub97c \uc77c\uc73c\ud0ac \uc218\ub3c4 \uc788\uc2b5\ub2c8\ub2e4. devices.downloading=\ub0b4\ub824\ubc1b\uae30 \uc911 TableColumn.header.duration=\uc9c0\uc18d\uc2dc\uac04 devices.xcode.autoStart=\ud544\uc694\ud558\uba74 \uc790\ub3d9\uc73c\ub85c \uc2dc\uc791 option.askeverytime=\ub9e4\ubc88 \ubb3b\uae30 option.rememberthis=\uc774\uc124\uc815 \uae30\uc5b5 devices.associate=\uc5f0\ub3d9\ud558\uae30 devices.associate.already=\uc774\ubbf8 \uc5f0\ub3d9\ub428 devices.always.cache=\uc790\ub3d9\ubcc0\ud658\ub418\uc9c0 \uc54a\uc740 \ud30c\uc77c\uc744 \uce90\uc26c devices.turnon.title=\uc7a5\uce58 \uc9c0\uc6d0\uc744 \uc791\ub3d9 devices.choose.profile.info.title.selected=%1 \uc138\ubd80\ub0b4\uc6a9: devices.view.heading=\uc7a5\uce58\uc758 \uc7ac\uc0dd\ubc29\uc2dd\uc5d0 \uc54c\ub9de\uac8c \uc790\ub8cc \ubcc0\ud658 device.view.heading=%1\uc6a9 \uc790\ub8cc devices.choose.device.info.title=\uc7a5\uce58 \uadc0\ub754 Button.turnon=\uc791\ub3d9 ConfigView.label.dm.dblclick=\ub354\ube14\ud074\ub9ad\ud560 \ub54c \ud1a0\ub7f0\ud2b8 \ubcf4\uae30: ConfigView.option.dm.dblclick.play=\uc790\ub8cc \uc7ac\uc0dd ConfigView.option.dm.dblclick.details=\ud1a0\ub7f0\ud2b8 \uc138\ubd80\uc0ac\ud56d \ubcf4\uae30 \uc5f4\uae30 ConfigView.option.dm.dblclick.show=\ud30c\uc77c \ubcf4\uae30 ConfigView.option.dm.dblclick.show._mac=\ud30c\uc778\ub354\uc5d0\uc11c \ud30c\uc77c \uc704\uce58 \ubcf4\uae30 ConfigView.option.dm.dblclick.show._windows=\ud0d0\uc0c9\uae30\uc5d0\uc11c \ud30c\uc77c \uc704\uce58 \ubcf4\uae30 subscriptions.column.auto-download=\uc790\ub3d9 \ub0b4\ub824\ubc1b\uae30 xcode.deletedata.title=\uc790\ub3d9\ubcc0\ud658 \uc790\ub8cc \uc0ad\uc81c xcode.deletedata.message='%2'%3\uc6a9 \uc790\ub3d9\ubcc0\ud658 \uc790\ub8cc '%1'\uc758 \ubcf5\uc0ac\ubcf8\uc744 \uc644\uc804\ud788 \uc0ad\uc81c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? xcode.deletedata.message.2=\n('%1'\uc758 \ubcf5\uc0ac\ubcf8\uc774 \ub0a8\uc544\uc788\uc744 \uc218 \uc788\uc74c) v3.deviceview.infobar.line1=\ub77c\uc774\ube0c\ub7ec\ub9ac\uc5d0\uc11c \uc7a5\uce58\ub85c \uc62e\uae38 \uc790\ub8cc\ub97c \ub4dc\ub85c\uadf8 \uc564 \ub4dc\ub86d \ud558\uc138\uc694. v3.deviceview.infobar.line2=\ub0b4\ub824\ubc1b\uc740 \uc790\ub8cc\ub97c \uc5b4\ub5a4\uae30\uae30\uc758 \uc5b4\ub5a4\uc2a4\ud06c\ub9b0\uc5d0\uc11c\ub3c4 \ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4 - iPhone, iPod, TV v3.deviceview.infobar.line1.generic=\uce21\uba74 \ud45c\uc2dc\uc904\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\uc5d0\uc11c %1\ub85c \uc790\ub8cc\ub97c \ub04c\uc5b4 \uc624\uc138\uc694. v3.deviceview.infobar.line2.itunes=\uc790\ub8cc \uc7ac\uc0dd\uc900\ube44\uac00 \ub2e4 \ub418\uba74 iTunes Movies\uc5d0\uc11c \uc790\ub8cc\uac00 \ubcf4\uc77c\uac83\uc785\ub2c8\ub2e4. v3.deviceview.infobar.line2.xbox=Xbox 360\uc73c\ub85c \uc2a4\ud2b8\ub9ac\ubc0d \uc790\ub8cc\ub97c \ubcf4\ub0b4\uc2dc\ub824\uba74 Xbox360\uc5d0\uc11c My XBox -> Video Library -> Vuze\ub97c \uc120\ud0dd\ud558\uc138\uc694. v3.deviceview.infobar.line2.ps3=\uc2a4\ud2b8\ub9ac\ubc0d \uc790\ub8cc\ub97c PS3\uc5d0\uc11c \ubcf4\uc2dc\ub824\uba74 PS3\uc5d0\uc11c Videos -> Vuze\ub97c \uc120\ud0dd\ud558\uc138\uc694. devices.converting=\ubcc0\ud658 \uc911 Button.reload=\uc0c8\ub85c\uace0\uce68 devices.auto.start=\uc790\ub3d9\uc2dc\uc791 general.enter.cookies=\ucfe0\ud0a4\uc5d0 \uae30\ub85d MyTorrentsView.menu.clear_alloc_data=\ud560\ub2f9 \uc0c1\ud0dc \uc9c0\uc6b0\uae30 subscriptions.config.auto=\uc790\ub3d9 \ub0b4\ub824\ubc1b\uae30 azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_de_DE.properties0000644000175000017500000062477511301156004026054 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=&Torrent-Datei... Main.parameter.usage=Benutze: java org.gudy.azureus2.cl.Main [Parameter] "Datei.torrent" "Pfad\u005czum\u005cSpeichern" Main.parameter.maxUploads=max. Anzahl gleichzeitiger Uploads Main.parameter.maxSpeed=max. Upload-Geschwindigkeit in B/s MainWindow.menu.file=&Datei MainWindow.menu.file.open=\u00d6ffn&en MainWindow.menu.file.create=Torre&nt erstellen... MainWindow.menu.file.create.fromfile=aus Datei MainWindow.menu.file.create.fromdir=aus Verzeichnis MainWindow.menu.file.export=XML E&xport eines Torrents... MainWindow.menu.file.import=XML &Import eines Torrents... MainWindow.menu.file.closetab=&Tab schlie\u00dfen MainWindow.menu.file.closewindow=&Fenster schlie\u00dfen MainWindow.menu.file.exit=&Beenden MainWindow.dialog.choose.file=W\u00e4hle Torrent-Datei MainWindow.menu.file.folder=&Verzeichnis... MainWindow.dialog.choose.folder=W\u00e4hle Verzeichnis der Torrent-Dateien MainWindow.menu.view=&Ansicht MainWindow.menu.view.show=Anzeigen MainWindow.menu.view.mytorrents=Meine T&orrents MainWindow.menu.view.open_global_transfer_bar=\u00dcbertragungsleiste MainWindow.menu.view.configuration=&Konfiguration MainWindow.menu.view.console=K&onsole MainWindow.menu.view.irc=IRC MainWindow.menu.view.allpeers=Alle Quellen MainWindow.menu.view.detailedlist=&Detailierte Liste MainWindow.menu.closealldetails=Alle Details schlie\u00dfen MainWindow.menu.closealldownloadbars=Alle Download-Leisten schlie\u00dfen MainWindow.menu.language=Sprache ConfigView.section.language=Sprache MainWindow.menu.window=&Fenster MainWindow.menu.window.minimize=&Minimieren MainWindow.menu.window.alltofront=Alle in den &Vordergrund bringen MainWindow.menu.help=&Hilfe MainWindow.menu.help.about=\u00dcber Vu&ze MainWindow.about.title=\u00dcber MainWindow.about.section.developers=Entwickler MainWindow.about.section.translators=\u00dcbersetzer MainWindow.about.internet.homepage=Vuze-Homepage MainWindow.about.internet.sourceforge=Sourceforge-Projekt-Homepage MainWindow.about.internet.sourceforgedownloads=Sourceforge-Downloads MainWindow.about.internet.bugreports=Bug-Reporte MainWindow.about.internet.forumdiscussion=Foren MainWindow.about.internet.wiki= MainWindow.dialog.choose.savepath=W\u00e4hle Verzeichnis zum Speichern MainWindow.dialog.choose.savepath_forallfiles=W\u00e4hle Verzeichnis zum Speichern ALLER Dateien MainWindow.status.latestversion=Neuste MainWindow.status.latestversion.clickupdate=Aktualisieren MainWindow.status.unknown=unbekannt MainWindow.status.checking=\u00dcberpr\u00fcfen MyTorrentsView.mytorrents=Meine Torrents TableColumn.header.size=Gr\u00f6\u00dfe TableColumn.header.done=Fertig TableColumn.header.done.info=Zeigt an, wie viel Prozent der aktuellen Aufgabe fertiggestellt sind. TableColumn.header.status.info=Was der Torrent gerade macht TableColumn.header.seeds=v Quellen TableColumn.header.seeds.info=Anzahl der verbundenen vollst\u00e4ndigen Quellen (Anzahl der vollst\u00e4ndige Quellen, die der Tracker sieht) TableColumn.header.peers=uv Quellen TableColumn.header.peers.info=Anzahl der verbundenen unvollst\u00e4ndigen Quellen (Anzahl der unvollst\u00e4ndige Quellen, die der Tracker sieht) TableColumn.header.completed=Vervollst\u00e4ndigt TableColumn.header.completed.info=Anzahl der Quellen, die den Torrent laut Tracker vollst\u00e4ndig heruntergeladen haben TableColumn.header.downspeed=DL-Geschw. TableColumn.header.upspeed=UL-Geschw. TableColumn.header.eta=Restzeit TableColumn.header.tracker=Tracker-Status TableColumn.header.tracker.info=Status des Trackers TableColumn.header.trackernextaccess=Tracker-Zugriff TableColumn.header.trackernextaccess.info=Zeit bis zum n\u00e4chster Tracker-Zugriff TableColumn.header.priority=Priorit\u00e4t TableColumn.header.priority.info=Bestimmt die Upload-Bandbreite eines Torrent TableColumn.header.seeds.fullcopycalc=Nehme %2 komplette Kopien f\u00fcr %1 unvollst\u00e4ndige Quellen an MyTorrentsView.menu.showdetails=Zeige Details MyTorrentsView.menu.showdownloadbar=Zeige Download-Leiste MyTorrentsView.menu.open=\u00d6ffne Datei MyTorrentsView.menu.setpriority=Setze Priorit\u00e4t fest MyTorrentsView.menu.setpriority.high=Hoch MyTorrentsView.menu.setpriority.low=Niedrig MyTorrentsView.menu.start=Start MyTorrentsView.menu.stop=Stopp MyTorrentsView.menu.remove=Entferne aus Liste MyTorrentsView.menu.changeTracker=F\u00fcge Tracker-URL hinzu TrayWindow.menu.exit=Beenden TrayWindow.menu.show=Zeige Vuze SystemTray.menu.exit=Beenden SystemTray.menu.closealldownloadbars=Schlie\u00dfe alle Download-Leisten SystemTray.menu.open_global_transfer_bar=Zeige \u00dcbertragungsleiste SystemTray.menu.show=Zeige Vuze PeersView.ip.info=IP-Adresse der Quelle PeersView.port=Port PeersView.port.info=benutzter Port PeersView.T.info=Typ des Verbindungsaufbaus - L (lokal): durch uns, R (remote): durch die Quelle PeersView.T.L.tooltip=Verbindung durch uns hergestellt PeersView.T.R.tooltip=Verbindung durch die Quelle hergestellt. PeersView.I1=I (an Quelle interessiert) PeersView.I1.info=Zeigt an, ob Interesse an den Daten der Quelle besteht PeersView.C1=C (von Quelle unterdr\u00fcckt) PeersView.C1.info=Zeigt an, ob die Quelle den Download unterbindet PeersView.pieces=Teile PeersView.downloadspeed=DL-Geschw. PeersView.download=Herunter PeersView.I2=I (Quelle ist interessiert) PeersView.I2.info=Zeigt an, ob die Quelle Interesse an den bereitgestellten Daten hat PeersView.C2=C (Quelle unterdr\u00fccken) PeersView.C2.info=Zeigt an, ob der Upload zur Quelle unterbunden wird PeersView.uploadspeed=UL-Geschw. PeersView.uploadspeed.info=Die Upload-Geschwindigkeit zur Quelle PeersView.upload=Hoch PeersView.upload.info=Datenmenge, die zur Quelle gesendet wurde PeersView.statup=m\u00f6gliche UL-Geschw. PeersView.statup.info=Der angenommene Wert der Upload-Geschwindigkeit der Quelle PeersView.S.info=Zurechtweisen: Eine Quelle kann manuell oder automatisch "zurechtgewiesen" werden (bei zu langsamen bzw. \u00fcberhaupt keiner Daten\u00fcbertragung) PeersView.downloadspeedoverall=ges. DL-Geschw. PeersView.client=BitTorrent-Client PeersView.client.info=Typ der BitTorrent-Anwendung der Quelle PeersView.menu.snubbed=Unzuverl\u00e4ssig PeersView.title.short=Details PeersView.title.full=Details AllPeersView.title.full=Alle Quellen ConfigView.section.files=Dateien ConfigView.label.usefastresume=Benutze schnelles Fortsetzen von Downloads ConfigView.label.incrementalfile=Speicherplatz inkrementell reservieren (erforderlich bei Benutzung von FAT32 unter Linux) ConfigView.label.defaultsavepath=In vorgegebenen Daten-Verzeichnis speichern ConfigView.button.browse=Suche... ConfigView.dialog.choosedefaultsavepath=Bitte w\u00e4hle das Standardverzeichnis f\u00fcr Downloads ConfigView.section.server=Verbindung ConfigView.section.global=Allgemein ConfigView.label.disconnetseed=Trenne vollst\u00e4ndige Quellen, wenn fertige Torrents hochgeladen werden ConfigView.label.switchpriority=automatisch auf niedrige Priorit\u00e4t wechseln, wenn Torrent verteilt wird ConfigView.label.maxdownloads=max. gleichzeitige Downloads\n - Kann nicht h\u00f6her sein, als die Anzahl der aktiven Torrents ConfigView.label.maxdownloads.tooltip=Sie werden immer in der Lage sein die angegebene Anzahl herunterzuladen. Ausnahme:\n Ein kompletter Torrent, der die Oberste Priorit\u00e4t besitzt, kann einen Slot \u00fcbernehmen, wenn es unbedingt notwendig ist. ConfigView.label.maxactivetorrents=max. aktive Torrents\n - Neue Torrents werden nicht gestartet, solange es noch aktive\n Downloads/hochladenen fertige Torrents gibt ConfigView.label.priorityExtensions=Priorisiere Dateien mit folgenden Erweiterungen\n - z.B.: .txt;.nfo;.jpg ConfigView.section.transfer=\u00dcbertragung ConfigView.label.maxuploads=max. Upload-Verbindungen pro Torrent ConfigView.label.maxuploadspeed=kB/s globale max. Upload-Geschwindigkeit ConfigView.label.saveresumeinterval=Intervall f\u00fcr Speicherung der Fortsetzungsdaten ConfigView.unlimited=Unbegrenzt ConfigView.section.display=Ansicht ConfigView.label.opendetails=\u00d6ffne Details automatisch ConfigView.label.openbar=\u00d6ffne Download-Leiste automatisch ConfigView.label.use_old_speed_menus=Nutze altes Aussehen der Geschwindigkeitsmen\u00fcs [Neustart ben\u00f6tigt] ConfigView.label.closetotray='Schlie\u00dfen' minimiert Vuze in den Tray ConfigView.label.minimizetotray='Minimieren' minimiert Vuze in den Tray ConfigView.section.general=Allgemein ConfigView.label.showsplash=Startbildschirm zeigen ConfigView.label.autoupdate=Aktualisierungsfenster zeigen, wenn neuere Version verf\u00fcgbar ist ConfigView.label.openconsole=\u00d6ffne Konsole beim Start ConfigView.label.openconfig=\u00d6ffne Konfiguration beim Start ConfigView.label.startminimized=Vuze minimiert starten ConfigView.label.ircwiki=Bitte lese http://www.azureuswiki.com/index.php/Rules_for_IRC sowie http://www.azureuswiki.com ConfigView.label.ircchannel=Kanal ConfigView.label.irclogin=Spitzname ConfigView.group.irctitle=IRC Einstellungen ConfigView.boolean.ircsendinfo=Erlaube Senden von (anonymen) Einstellungen an die Helfer im IRC, um ihnen bei Problemen den Support zu erleichtern. ConfigView.boolean.irclog=Logge alle Aktivit\u00e4ten im Kanal (in die Datei IRC_log.htm) ConfigView.section.security=Sicherheit ConfigView.label.password=Passwort\n - Abfrage beim Vergr\u00f6\u00dfern aus dem Tray und Programmstart ConfigView.label.passwordconfirm=Passwort (best\u00e4tigen) ConfigView.label.passwordmatch=Passwort aktiviert: ConfigView.label.passwordmatchnone=Nein ConfigView.label.passwordmatchno=Nein / Passw\u00f6rter stimmen nicht \u00fcberein ConfigView.label.passwordmatchyes=Ja ConfigView.button.save=Speichern ConfigView.title.short=Konfiguration ConfigView.title.full=Konfiguration ConfigView.title.full._mac=Einstellungen ConsoleView.title.short=Konsole ConsoleView.title.full=Konsole FileItem.write=schreiben FileItem.read=lesen FileItem.high=hoch FileItem.donotdownload=nicht herunterladen FileItem.delete=L\u00f6schen FilesView.name.fastRename=Schnelles Umbenennen FilesView.size=Gr\u00f6\u00dfe FilesView.done=Fertig FilesView.firstpiece=Erstes Teil FilesView.numberofpieces=Teilanzahl FilesView.pieces=Teile FilesView.mode=Modus FilesView.priority=Priorit\u00e4t FilesView.menu.open=\u00d6&ffnen FilesView.menu.setpriority=&Setze Priorit\u00e4t FilesView.menu.setpriority.high=&Hoch FilesView.menu.setpriority.skipped=Nicht herunterladen FilesView.title.short=Dateien FilesView.title.full=Dateien GeneralView.section.downloaded=Heruntergeladen GeneralView.label.status.file=Dateistatus GeneralView.label.status.pieces=Teilstatus GeneralView.section.availability=Verf\u00fcgbarkeit GeneralView.label.status.pieces_available=Teilstatus GeneralView.section.transfer=\u00dcbertragung GeneralView.section.info=Informationen GeneralView.title.short=Allgemein GeneralView.title.full=Allgemein GeneralView.label.timeelapsed=Vergangene Zeit: GeneralView.label.remaining=Verbleibend: GeneralView.label.downloaded=Heruntergeladen: GeneralView.label.downloadspeed=Download-Geschwindigkeit: GeneralView.label.maxuploads=Upload-Verbindungen: GeneralView.label.maxuploads.tooltip=H\u00f6chstzahl der Quellen die auf einmal Daten anfordern d\u00fcrfen. GeneralView.label.uploaded=Hochgeladen: GeneralView.label.uploadspeed=Upload-Geschwindigkeit: GeneralView.label.seeds=Vollst\u00e4ndige Quellen: GeneralView.label.peers=Unvollst\u00e4ndige Quellen: GeneralView.label.completed=Vervollst\u00e4ndigt: GeneralView.label.totalspeed=Schwarmgeschwindigkeit: GeneralView.label.totalspeed.tooltip=Gesamtgeschwindigkeit aller Quellen, zu denen man im Moment verbunden ist. GeneralView.label.averagespeed=Durchschnitt GeneralView.label.filename=Name: GeneralView.label.totalsize=Gesamtgr\u00f6\u00dfe: GeneralView.label.savein=Speichern unter: GeneralView.label.hash=Hash: GeneralView.label.numberofpieces=Anzahl der Teile: GeneralView.label.size=Gr\u00f6\u00dfe eines Teiles: GeneralView.label.tracker=Tracker-Status: GeneralView.label.updatein=Aktualisierung in: GeneralView.label.trackerurl=Tracker-URL: GeneralView.label.trackerurlupdate=Aktualisiere Tracker GeneralView.label.comment=Kommentar: GeneralView.label.user_comment=Benutzerkommentar: GeneralView.label.status=Status: ManagerItem.waiting=Warten ManagerItem.allocating=Reservieren ManagerItem.checking=\u00dcberpr\u00fcfen ManagerItem.ready=Bereit ManagerItem.downloading=Herunterladen ManagerItem.seeding=Verteilen ManagerItem.stopped=Angehalten ManagerItem.error=Fehler ManagerItem.high=hoch ManagerItem.low=niedrig MinimizedWindow.name=Name: MinimizedWindow.all_transfers=Vuze-\u00dcbertragungen PiecesView.#=Nr. PiecesView.size=Gr\u00f6\u00dfe PiecesView.numberofblocks=Anzahl der Bl\u00f6cke PiecesView.blocks=Bl\u00f6cke PiecesView.completed=Fertig PiecesView.availability=Verf\u00fcgbarkeit PiecesView.reservedby=Reserviert PiecesView.writers=Block-Quellen PiecesView.title.short=Teile PiecesView.title.full=Teile SystemTray.tooltip.seeding=%1 verteilen, SystemTray.tooltip.downloading=%1 herunterladen, DownloadManager.error.filenotfound=Datei nicht gefunden DownloadManager.error.fileempty=Torrent-Datei ist leer DownloadManager.error.filetoobig=Torrent-Datei zu gro\u00df DownloadManager.error.filewithouttorrentinfo=Keine Torrent-Information in Datei gefunden DownloadManager.error.unsupportedencoding=Kodierung wird nicht unterst\u00fctzt DownloadManager.error.ioerror=Ein-/Ausgabefehler DownloadManager.error.sha1=unbekannter Algorithmus (SHA1) PeerManager.status.offline=Verbindungsfehler PeerManager.status.checking=\u00dcberpr\u00fcfen PeerManager.status.finished=Beendet PeerManager.status.finishedin=Beendet in MainWindow.upgrade.assistant=Upgrade-Assistent MainWindow.upgrade.newerversion=Es ist eine neuere Version von Vuze verf\u00fcgbar. MainWindow.upgrade.explanation=Der Assistent wird die neue Version in den Vuze-Ordner herunterladen und Vuze neu starten. MainWindow.upgrade.explanation.manual=Man kann Vuzemanuell aktualisieren, indem man Vuze schlie\u00dft, die neue Version herunterl\u00e4d und Vuze neu startet. MainWindow.upgrade.step1=Schritt 1: Die neue Version herunterladen MainWindow.upgrade.step2=Schritt 2: Diese Version schlie\u00dfen und die neue Vuze-Version starten. MainWindow.upgrade.hint1=Hinweis:\tDurch Dr\u00fccken von 'Fertig' wird alles automatisch ausgef\u00fchrt MainWindow.upgrade.hint2=Hinweis: Wenn Vuze sp\u00e4ter geschlo\u00dfen werden soll, 'Abbrechen' dr\u00fccken und\n\t Azureus2-new.jar in Azureus2.jar nach dem Schlie\u00dfen umbenennen. MainWindow.upgrade.error.downloading.hint=Fehler:\tHerunterladen der neuen Version nicht m\u00f6glich, bitte manuell aktualisieren. MainWindow.upgrade.section.info=Neue Version verf\u00fcgbar MainWindow.upgrade.section.manual=Manuelle Aktualisierung MainWindow.upgrade.section.automatic=Automatische Aktualisierung MainWindow.upgrade.tooltip.progressbar=Fortschritt des Downloads hier Button.next=Weiter Button.finish=Beenden Button.cancel=&Abbrechen LocaleUtil.title=W\u00e4hle Zeichensatzkodierung LocaleUtil.section.chooseencoding=W\u00e4hle Kodierung f\u00fcr Dateinamen LocaleUtil.label.chooseencoding=Bitte die Kodierung w\u00e4hlen, die am besten passt LocaleUtil.label.hint.doubleclick=Hinweis: Doppelklick auf eine Zeile f\u00fchrt zur Auswahl und schlie\u00dft das Fenster LocaleUtil.label.checkbox.rememberdecision=Auswahl f\u00fcr verbleibende Dateien merken LocaleUtil.column.encoding=Kodierung IrcClient.defaultChannel=#Azureus-German IrcClient.connecting=Verbinde zu IrcClient.connected=Verbunden mit IrcClient.joining=Betrete IrcClient.channel=Kanal IrcClient.joined=betreten IrcClient.error=Fehler IrcClient.hasjoined=betrat den Kanal IrcClient.haskicked=entfernte IrcClient.hasleft=verlie\u00df den Kanal IrcClient.nowknown=hei\u00dft jetzt IrcClient.topicforchannel=Thema von IrcClient.disconnected=Getrennt von IrcClient.noNick=Kein Spitzname festgelegt. Bitte unter 'Tools -> Konfiguration -> Plugins -> IRC' einstellen. IrcView.actionnotsupported=Aktion wird nicht unterst\u00fctzt IrcView.clientsconnected=Benutzer IrcView.privateto=Zu IrcView.privatefrom=Von IrcView.noticefrom=Nachricht von IrcView.errormsg=Falsche Syntax von /msg: /msg IrcView.help=Erlaubte Befehle sind:\n . /help : zeigt diese Nachricht\n . /nick | /name : \u00e4ndert den Nick \n . /me action : sendet eine Aktion \n . /msg Benutzer Nachricht : sendet eine private Nachricht an \n . /r : antworten auf letzte private Nachricht\n . /join #kanal : Kanal betreten PasswordWindow.title=Vuze ist gesperrt PasswordWindow.passwordprotected=Vuze ist passwortgesch\u00fctzt.\nF\u00fcr die Anzeige des Fensters bitte hier das Passwort eingeben: TrackerChangerWindow.title=Tracker hinzuf\u00fcgen TrackerChangerWindow.newtracker=Neue Tracker-URL eingeben PeersView.discarded=Verworfen PeersView.discarded.info=Daten, die empfangen wurden, ohne ben\u00f6tigt zu werden und daher gel\u00f6scht wurden. discarded=verworfen MyTorrentsView.#=Nr. MyTorrentsView.menu.move=Bewegen MyTorrentsView.menu.moveUp=Auf MyTorrentsView.menu.moveDown=Ab GeneralView.label.hashfails=Hash-Fehler: GeneralView.label.shareRatio=Verh\u00e4ltnis: ConfigView.section.downloadManagement=Downloadverwaltung ConfigView.label.startRatioPeers=Starte Verteilen, falls es weniger als eine vollst\u00e4ndige Quelle gibt f\u00fcr ConfigView.text.neverStop=Niemals stoppen ConfigView.text.neverStart=Niemals starten ConfigView.text.peers=unvollst\u00e4ndige Quellen ConfigView.label.checkOncompletion=\u00dcberpr\u00fcfe erneut einzelne Teile, wenn der Download beendet ist wizard.title=Erstelle ein Torrent wizard.previous=< Zur\u00fcck wizard.next=Weiter > wizard.finish=Fertig wizard.mode=Tracker / Modus wizard.invalidurl=Ung\u00fcltige URL wizard.singlefile=Eine Datei wizard.singlefile.help=Erstelle Torrent aus einer Datei wizard.directory=Verzeichnis wizard.directory.help=Erstelle Torrent aus einem Verzeichnis wizard.choosefile=W\u00e4hle die Datei wizard.file=Datei: wizard.browse=Suche... wizard.choosedirectory=W\u00e4hle ein Verzeichnis wizard.invalidfile=Ung\u00fcltige Datei! wizard.invaliddirectory=Ung\u00fcltiges Verzeichnis! wizard.torrentFile=Torrent-Datei wizard.choosetorrent=Bitte die Torrent-Datei w\u00e4hlen, die erstellt werden soll wizard.information=Informationen wizard.notimplemented=Noch nicht unterst\u00fctzt wizard.progresstitle=Erstelle Torrent wizard.savingfile=Speichere Datei... wizard.filesaved=Datei gespeichert. wizard.close=Schlie\u00dfen Torrent.create.progress.piecelength=Teilgr\u00f6\u00dfe: Torrent.create.progress.piececount=Teilanzahl: Torrent.create.progress.totalfilesize=Gesamte Dateigr\u00f6\u00dfe: Torrent.create.progress.totalfilecount=Gesamte Dateianzahl: Torrent.create.progress.parsingfiles=Analysiere Dateien Torrent.create.progress.hashing=Erstelle Pr\u00fcfsummen der Teile... MainWindow.upgrade.downloadingfrom=Download von: MainWindow.menu.view.ipFilter=IP-Filter ConfigView.section.ipfilter=IP-Filter ConfigView.section.ipfilter.description=Beschreibung ConfigView.section.ipfilter.start=Start-IP ConfigView.section.ipfilter.end=End-IP ConfigView.section.ipfilter.add=Hinzuf\u00fcgen ConfigView.section.ipfilter.remove=Entfernen ConfigView.section.ipfilter.edit=Bearbeiten ConfigView.section.ipfilter.save=Speichern ConfigView.section.ipfilter.editFilter=Filter bearbeiten ConfigView.section.ipfilter.enable=Aktivieren PeersView.menu.close=Schlie\u00dfen seedmore.title=Verteilung des Torrent zu gering seedmore.shareratio=Das Verh\u00e4ltnis dieses Torrents betr\u00e4gt seedmore.uploadmore=Ein Verh\u00e4ltnis von unter 100% ist schlecht f\u00fcr das Bittorrent-\nNetzwerk. Dieser Torrent sollte noch etwas laufen gelassen\nwerden. Wirklich fortfahren? ConfigView.label.showpopuponclose=Zeige Best\u00e4tigungsfenster, wenn das Verteilen bei einem Verh\u00e4ltnis von weniger als eins angehalten worden soll ConfigView.label.startNumSeeds=\nStarte Verteilen, falls es weniger vollst\u00e4ndige Quellen gibt als\n - \u00fcberschreibt alle anderen Regeln ConfigView.label.seeds=vollst\u00e4ndigen Quellen ConfigView.section.seeding=Verteilen MyTorrentsView.menu.removeand=Entferne und MyTorrentsView.menu.removeand.deletetorrent=L\u00f6sche Torrent MyTorrentsView.menu.removeand.deletedata=L\u00f6sche Daten MyTorrentsView.menu.removeand.deleteboth=L\u00f6sche beides deletedata.title=L\u00f6sche Inhalt deletedata.message1=Sicher, dass '%1' gel\u00f6scht werden soll? deletedata.noprompt=Nicht nochmal nachfragen MainWindow.menu.file.configure=Konfigurations&assistent... configureWizard.title=Konfigurationsassistent configureWizard.welcome.title=Willkommen beim Vuze-Konfigurationsassistent configureWizard.welcome.message=Dieser Assistent wird helfen, allgemeine Einstellungen f\u00fcr Vuze festzulegen. F\u00fcr eine umfassende Konfiguration benutze das Men\u00fc 'Tools -> Konfiguration'. Lese dazu bitte auch www.azureuswiki.com . configureWizard.transfer.title=\u00dcbertragungs- und Verbindungseinstellungen configureWizard.transfer.hint=Tipp: Etwas geringere Geschwindkeit als die maximale verf\u00fcgbare Upload-Bandbreite der Internetverbindung w\u00e4hlen (ca. 80%). Siehe auch: www.azureuswiki.com configureWizard.transfer.message=Bitte w\u00e4hle einen der unten angezeigten Verbindungstypen. Es sei darauf hingewiesen, dass eine zu geringe Upload-Geschwindigkeit zu einer schlechten Download-Geschwindigkeit f\u00fchrt. Da die Upload-Geschwindigkeit nur pro aktivem Torrent z\u00e4hlt, wird das Herunterladen zu vieler Torrents gleichtig ebenfalls in geringen Geschwindigkeiten resultieren. Als Minimum empfehlen wir 5 KB/s _pro aktiven Torrent_. Je schneller hochgeladen wird, desto schneller kann herunterladen werden (in Abh\u00e4ngigkeit der Torrent-Geschwindigkeit). configureWizard.transfer.connection=Verbindung configureWizard.transfer.connection.0=Benutzerdefiniert configureWizard.transfer.connection.1=Modem configureWizard.transfer.connection.2=ADSL/Kabel xxx/128 kbps configureWizard.transfer.connection.3=ADSL/Kabel xxx/256 kbps configureWizard.transfer.connection.4=ADSL/Kabel xxx/384 kbps configureWizard.transfer.connection.5=ADSL/Kabel xxx/512 kbps configureWizard.transfer.connection.6=ADSL/Kabel xxx/768 kbps configureWizard.transfer.connection.7=ADSL/Kabel xxx/1024 kbps configureWizard.transfer.maxUpSpeed=max. Upload-Geschwindigkeit (kB/s) configureWizard.transfer.maxActiveTorrents=max. aktive Torrents configureWizard.transfer.maxDownloads=max. Downloads configureWizard.transfer.maxUploadsPerTorrent=max. Uploads pro Torrent configureWizard.nat.title=NAT- / Server-Port configureWizard.nat.message=Um das Beste aus Vuze herauszuholen, wird empfohlen, vollst\u00e4ndig aus dem Internet erreichbar zu sein. Dieses Tool testet und/oder \u00e4ndert den Port f\u00fcr eingehende Verbindungen. \nHinweise:\n1) Es werden nur TCP-Verbindungen getestet. Die verteilte Datenbank erfordert zus\u00e4tzlich einen UDP-Port, ist er geschlossen, wird dies separat angezeigt.\n2) Der TCP-Port 6880 ist f\u00fcr interne Vorg\u00e4nge reserviert und kann nicht benutzt werden. configureWizard.nat.test=Testen configureWizard.nat.testing=Teste Port configureWizard.nat.ok=OK! configureWizard.nat.ko=NAT-Fehler configureWizard.nat.unable=Test nicht m\u00f6glich: Entwerder ung\u00fcltigen Port angegeben oder Test im Moment nicht verf\u00fcgbar.\n Es ist auch m\u00f6glich, dass eine andere Anwendung diesen Port gerade benutzt. configureWizard.file.title=Torrents / Dateien configureWizard.file.message1=Vuze wird alle ge\u00f6ffneten Torrents in diesem Verzeichnis speichern: configureWizard.file.path=Pfad configureWizard.file.browse=Suchen configureWizard.file.message2=Durch Hinzuf\u00fcgen einiger Informationen zu den Torrents ist Vuze in der Lage, sowohl die Daten als auch unvollst\u00e4ndig heruntergeladene Teile, augenblicklich fortzusetzen. configureWizard.file.fastResume=Schnelles Fortsetzen aktivieren configureWizard.file.invalidPath=Ung\u00fcltiges Verzeichnis configureWizard.finish.title=Fertig configureWizard.finish.message=Vuze ist jetzt konfiguriert. Viel Spa\u00df! wizard.close.confirmation=Best\u00e4tigung wizard.close.message=Soll dieser Assistent geladen werden, wenn Vuze das n\u00e4chste Mal gestartet wird? exportTorrentWizard.title=XML-Export eines Torrent exportTorrentWizard.torrentfile.title=Eingabe der Torrent-Auswahl exportTorrentWizard.torrentfile.message=W\u00e4hle den zu exportierenden Torrent exportTorrentWizard.torrentfile.path=Verzeichnis exportTorrentWizard.torrentfile.browse=Suchen exportTorrentWizard.torrentfile.invalidPath=Ung\u00fcltige Torrent-Datei exportTorrentWizard.exportfile.title=Dateiauswahl exportieren exportTorrentWizard.exportfile.message=Eingabe der XML-Datei in die exportiert werden soll exportTorrentWizard.exportfile.path=Verzeichnis exportTorrentWizard.exportfile.browse=Suchen exportTorrentWizard.exportfile.invalidPath=Ung\u00fcltige Export-Datei exportTorrentWizard.finish.title=Fertig exportTorrentWizard.finish.message=Export erfolgreich abgeschlossen exportTorrentWizard.process.inputfilebad.title=Torrent-Datei ung\u00fcltig exportTorrentWizard.process.inputfilebad.message=Fehler aufgetreten beim Zugriff auf die Datei: exportTorrentWizard.process.outputfileexists.title=Datei existiert bereits exportTorrentWizard.process.outputfileexists.message=Ausgabedatei existiert bereits - \u00dcberschreiben? exportTorrentWizard.process.torrentfail.title=Lesen des Torrents fehlgeschlagen exportTorrentWizard.process.exportfail.title=Torrent-Export fehlgeschlagen exportTorrentWizard.process.unknownfail.title=Unerwarteter Fehler importTorrentWizard.title=XML-Import eines Torrent importTorrentWizard.torrentfile.title=Torrent ausw\u00e4hlen importTorrentWizard.torrentfile.message=W\u00e4hle den zu importierenden Torrent importTorrentWizard.torrentfile.path=Verzeichnis importTorrentWizard.torrentfile.browse=Suchen importTorrentWizard.torrentfile.invalidPath=Ung\u00fcltige Torrent-Datei importTorrentWizard.importfile.title=Importdateiauswahl importTorrentWizard.importfile.message=W\u00e4hle die zu importierende XML-Datei importTorrentWizard.importfile.path=Verzeichnis importTorrentWizard.importfile.browse=Suchen importTorrentWizard.importfile.invalidPath=Ung\u00fcltige Importdatei importTorrentWizard.finish.title=Fertig importTorrentWizard.finish.message=Import erfolgreich abgeschlossen importTorrentWizard.process.inputfilebad.title=Import-Datei ung\u00fcltig importTorrentWizard.process.inputfilebad.message=Fehler aufgetreten beim Zugriff auf die Datei: importTorrentWizard.process.outputfileexists.title=Datei existiert bereits importTorrentWizard.process.outputfileexists.message=Ausgabedatei existiert bereits - \u00dcberschreiben? importTorrentWizard.process.torrentfail.title=Torrent-Schreiben fehlgeschlagen importTorrentWizard.process.importfail.title=Torrent-Import fehlgeschlagen importTorrentWizard.process.unknownfail.title=Unerwarteter Fehler ConfigView.label.bindip=An lokale IP-Adresse binden ConfigView.label.xfs.allocation=Lege neue Dateien nach einer Methode an, die speziell f\u00fcr das XFS-Dateisystem ist. ConfigView.label.xfs.allocation.tooltip=Stelle sicher, dass /usr/sbin/xfs_io korrekt installiert ist. Bei den meisten Linux-Distributionen ist es im Paket "xfsprogs" enthalten. xfs.allocation.xfs_io.not.found=XFS-Dateizuordnung fehlgeschlagen, /usr/sbin/xfs_io kann nicht ausgef\u00fchrt werden. Stelle sicher, dass es korrekt installiert ist. Fehlermeldung war: "%1". ConfigView.label.zeronewfiles=Speicherplatz bei der Erstellung neuer Dateien zuweisen und mit Nullen f\u00fcllen ConfigView.label.zeronewfiles.tooltip=Minimiert die Fragmentierung ConfigView.section.stats=Statistiken ConfigView.section.stats.enable=Aktivieren ConfigView.section.stats.defaultsavepath=Verzeichnis f\u00fcr Statistiken ConfigView.section.stats.choosedefaultsavepath=Bitte das Standardsicherungsverzeichnis f\u00fcr Statistiken w\u00e4hlen ConfigView.section.stats.savefreq=Speicherintervall ConfigView.section.stats.hours=h ConfigView.section.stats.seconds=s ConfigView.section.stats.savefile=Dateiname ConfigView.section.stats.graph_update_dividers=Zeige vertikale Linien alle 60 Aktualisierungen MyTorrentsView.menu.export=XML-Torrent... MyTorrentsView.menu.host=Host... ManagerItem.finishing=Beende ConfigView.dialog.choosedefaulttorrentpath=Bitte w\u00e4hle das Standardverzeichnis f\u00fcr Torrents ConfigView.dialog.choosemovepath=Bitte w\u00e4hle das Verzeichnis, in welches vollst\u00e4ndige Downloads verschoben werden sollen ConfigView.label.movecompleted=Verschiebe fertige Dateien ConfigView.label.moveremoved=Verschiebe fertige Dateien, wenn der Torrent entfernt wird ConfigView.label.savetorrents=Speichere .torrent-Dateien MainWindow.menu.view.mytracker=Mein &Tracker MyTrackerView.title.full=Mein Tracker MyTrackerView.status.started=L\u00e4uft MyTrackerView.status.stopped=Angehalten MyTrackerView.peers=uv Quellen MyTrackerView.seeds=v Quellen MyTrackerView.announces=Ank\u00fcndigungen MyTrackerView.uploaded=Hochgeladen MyTrackerView.downloaded=Heruntergeladen MyTrackerView.left=Verbleibend ConfigView.section.style=Oberfl\u00e4che ConfigView.label.set_ui_transfer_speeds=\u00dcberschreibe w\u00e4hlbare \u00dcbertragunggeschwindigkeiten ConfigView.label.set_ui_transfer_speeds.description=Die in der Statuszeile und im Tray w\u00e4hlbaren Download- und Uploadgeschwindigkeiten\nk\u00f6nnen manuell definiert werden. Die Werte m\u00fcssen durch Komma getrennt sein. ConfigView.label.set_ui_transfer_speeds.description.download=Downloadgeschwindigkeiten in kB/s ConfigView.label.set_ui_transfer_speeds.description.upload=Uploadgeschwindigkeiten in kB/s ConfigView.section.style.useCustomTabs=Benutze schlie\u00dfbare Tabs [Neustart ben\u00f6tigt] fileDownloadWindow.saveTorrentIn=Speichere Torrent-Datei in fileDownloadWindow.title=Vuze - Torrent-Downloader fileDownloadWindow.downloading=Download von: fileDownloadWindow.status=Status: fileDownloadWindow.state_initializing=Initialisiere fileDownloadWindow.state_downloading=Download fileDownloadWindow.state_error=Fehler: MainWindow.menu.file.open.url=&URL... openUrl.title=URL \u00f6ffnen openUrl.url=URL: MyTorrentsView.menu.host.error.title=Torrent-Hosten fehlgeschlagen MyTorrentsView.menu.host.error.message=Folgender Fehler trat beim Hosten des Torrent auf ConfigView.section.tracker.pollinterval=Tracker-Client-Anfrageintervall (in s) ConfigView.section.tracker.publishenable=Ver\u00f6ffentliche Torrent-Details an "" ConfigView.section.tracker.ip=Externe IP-Adresse des Trackers ConfigView.section.style.enableXPStyle=Aktiviere XP-Stil [Neustart ben\u00f6tigt] ConfigView.section.tracker.checkip=Ermittle externe IP-Adresse... ipCheckerWizard.title=IP-Pr\u00fcfassistent ipCheckerWizard.service=Dienst ipCheckerWizard.chooseService=Bitte w\u00e4hle einen IP-Pr\u00fcfdienst aus der Liste ipCheckerWizard.explanations=Dieser Assistent kann benutzen werden, um die externe IP-Adresse herauszufinden. Falls die IP-Adresse dynamisch ist, empfehlen wir die Nutzung eines dynamische DNS-Dienstes. Solche Dienste sind hier aufgelistet. Benutze den Link f\u00fcr eine Anmeldung. Gib dann den dynamischen Hostnamen in das Feld der IP-Adresse ein (z.B. meinhostname.dyndns.org). Es wird es Programm ben\u00f6tigt, um die IP-Adresse beim DNS-Dienst automatisch aktualisieren zu lassen. Wenn ein DNS-Dienst genutzt wird, kann der interne Tracker auch genutzt werden, falls sich die IP-Adresse \u00e4ndert. ipCheckerWizard.service.description=Beschreibung: ipCheckerWizard.service.url=Link: ipCheckerWizard.progresstitle=\u00dcberpr\u00fcfe IP ipCheckerWizard.checkComplete=Fertige IP: ipCheckerWizard.checkFailed=Fehlgeschlagen, Grund: wizard.tracker.local=Benutze den internen Tracker von Vuze wizard.tracker.external=Benutze einen externen Tracker wizard.tracker.howToLocal=\tAktivierung unter 'Tools -> Konfiguration -> Tracker -> Server' wizard.announceUrl=Ank\u00fcndigungs-URL: IPChecker.external.service.discoveryvip.name=discoveryvip IPChecker.external.service.discoveryvip.description=Discoveryvip - nur IP-Adresspr\u00fcfung IPChecker.external.httpinvalidresponse=Ung\u00fcltige HTTP-Antwort IPChecker.external.loadingwebpage=Lade Webseite IPChecker.external.analysingresponse=Analysiere Antwort IPChecker.external.addressextracted=Extrahierte IP-Adresse IPChecker.external.httploadfail=Laden der Seite fehlgeschlagen IPChecker.external.timeout=Zeit\u00fcberschreitung aufgetreten IPChecker.external.ipnotfound=IP-Adresse nicht gefunden ConfigView.section.tracker.pollintervalincby=Erh\u00f6he um ConfigView.section.tracker.pollintervalincper=alle 'n' Clients splash.loadingImages=Lade Bilder splash.initializeGui=Initialisiere Hauptfenster splash.openViews=\u00d6ffne Ansichten splash.plugin=Lade Plugin: configureWizard.nat.tooManyPorts=Zu viele Ports zum Testen (max. 9) ConfigView.section.color=Farbschema MyTorrentsView.menu.publish=Ver\u00f6ffentliche... MyTrackerView.status.published=Ver\u00f6ffentlicht MyTrackerView.completed=Fertig MainWindow.menu.file.open.torrentnodefault=Torrent-Datei... (&Zielverzeichnis w\u00e4hlen) wizard.comment=Kommentar ConfigView.label.movetorrent=Verschiebe Torrent ConfigView.label.movepartialdownloads=Verschiebe auch, wenn einige Dateien als 'nicht herunterladen' markiert sind. ConfigView.label.subdir_is_in_default=Wenn angenommen wird, dass Download im Standardverzeichnis existiert, auch Unterverzeichnisse ber\u00fccksichtigen ConfigView.section.file.decoder.label=Standard-Torrent-Kodierung, wenn Auswahl erforderlich ConfigView.section.file.decoder.nodecoder=Keine IPChecker.external.service.no-ip.description=Dynamischer und statischer DNS Dienst Anbieter\n(kein kostenloser Adresspr\u00fcfdienst) ConfigView.section.tracker.publicenable=Erlaube externe Torrents ConfigView.label.playdownloadspeech=Sprachausgabe, wenn ein Torrent fertig ist ConfigView.label.playdownloadspeech.info=Die Sprachausgabe funktioniert im Moment am besten auf Englisch # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Zeigt die Anzahl verf\u00fcgbarer Kopien jedes Teils an.\nSollte die Zahl rechts kleiner als 1 sein, ist keine\nkomplette Kopie der Datei vorhanden (was zu Problemen\nbei der Fertigstellung des Torrents f\u00fchren kann). GeneralView.label.trackerurl.tooltip=Kopiere die Ank\u00fcndigungs-URL in die Zwischenablage GeneralView.label.trackerurlopen.tooltip=\u00d6ffne Tracker-Hauptseite # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Aktualisiere Oberfl\u00e4che alle ConfigView.section.style.inactiveUpdate=Aktualisiere Hauptfenster alle 'n' Oberfl\u00e4chenaktualisierungen, wenn es nicht das aktive Fenster ist ConfigView.section.style.graphicsUpdate=Aktualisiere grafische Leisten alle 'n' Oberfl\u00e4chenaktualisierungen ConfigView.section.style.reOrderDelay=Ordne Tabellen alle 'n' Oberfl\u00e4chenaktualisierungen [0: niemals] ConfigView.section.style.reOrderDelay.never=Niemals ConfigView.section.logging=Protokoll ConfigView.section.logging.enable=Aktiviere Protokollierung in Datei ConfigView.section.logging.logdir=Verzeichnis f\u00fcr Protokolldatei ConfigView.section.logging.choosedefaultsavepath=Bitte das Speicherverzeichnis w\u00e4hlen GeneralView.label.updatein.querying=Anfragen... configureWizard.nat.sharePort=Benutze einen einzigen eingehenden TCP-Port f\u00fcr alle Torrents ConfigView.section.logging.maxsize=max. Gr\u00f6\u00dfe der Protokolldatei ConfigView.section.tracker.passwordenableweb=Verwende Passwort f\u00fcr Tracker-Web ConfigView.section.tracker.passwordenabletorrent=Verwende Passwort f\u00fcr Torrents ConfigView.section.tracker.username=Benutzername ConfigView.section.tracker.password=Passwort columnChooser.title=W\u00e4hle anzuzeigende Spalten columnChooser.move=Zeilen zum Neuordnen ziehen columnChooser.apply=\u00dcbernehmen columnChooser.columnname=Spaltenname columnChooser.columndescription=Beschreibung TableColumn.header.shareRatio=Verh\u00e4ltnis MyTorrentsView.menu.editTableColumns=&Spalteneinstellung wizard.operationfailed=Operation fehlgeschlagen authenticator.title=Authentifikation ben\u00f6tigt authenticator.realm=Bereich authenticator.user=Benutzername authenticator.password=Passwort ConfigView.label.allowSendVersion=Erlaube Vuze das Senden einer anonymen Versionsnummer und einer zuf\u00e4lligen ID, w\u00e4hrend auf neue Version \u00fcberpr\u00fcft wird ConfigView.label.version.info.link=Informationen \u00fcber die w\u00e4hrend der Versionspr\u00fcfung \u00fcbermittelten Daten wizard.hint.mode=Hinweis: Per Drag und Drop kann eine einzelne Datei oder\n\t ein einzelnes Verzeichnis ausgew\u00e4hlt werden. wizard.hint.file=Hinweis: Eine einzelne Datei kann per Drag und Drop ausgew\u00e4hlt werden wizard.hint.directory=Hinweis: Ein einzelnes Verzeichnis kann per Drag und Drop ausgew\u00e4hlt werden. MainWindow.menu.help.checkupdate=S&uche nach Aktualisierungen... TableColumn.header.down=Heruntergeladen TableColumn.header.up=Hochgeladen ConfigView.section.tracker.passwordenabletorrent.info=Erfordert ein dazu f\u00e4higes BitTorrent-Programm (z.B. Vuze) ConfigView.section.style.confirmationOnExit=Zeige Best\u00e4tigungsdialog beim Beenden MainWindow.dialog.exitconfirmation.title=Vuze beenden? MainWindow.dialog.exitconfirmation.text=Soll Vuze wirklich beenden werden? SystemTray.menu.stopalltransfers=Stoppe alle \u00dcbertragungen TrayWindow.menu.stopalldownloads=Stoppe alle Downloads ConfigView.section.tracker.sslport.info=Weitere Information in der FAQ von www.azureuswiki.com wizard.tracker.ssl=Benutze SSL ConfigView.label.playdownloadfinished=Sound spielen, wenn ein Torrent fertig ist ConfigView.label.popupdownloadfinished=Zeige eine Meldung, wenn ein Torrent fertig ist ConfigView.label.popupfilefinished=Zeige eine Meldung, wenn eine Datei eines Torrents fertig ist TableColumn.header.pieces=Teile TableColumn.header.pieces.info=Grafische Leiste, die zeigt, welche Teile man schon heruntergeladen hat TableColumn.header.completion=Fortschrittsbalken TableColumn.header.completion.info=Grafische Darstellung des prozentualen Fortschritts ConfigView.section.style.showdownloadbasket=Zeige Download-Korb (f\u00fcr Drag and Drop von Torrents) ConfigView.section.style.alwaysShowTorrentFiles=Zeige immer Torrent-Dateien in Details/Dateien wizard.multitracker=F\u00fcge Informationen f\u00fcr mehrere Tracker dem Torrent hinzu wizard.multitracker.title=Mehrere Tracker wizard.multitracker.configuration=Konfiguration f\u00fcr mehrere Tracker wizard.multitracker.new=Neu... wizard.multitracker.edit=Bearbeiten... wizard.multitracker.delete=L\u00f6schen wizard.multitracker.group=Trackergruppe wizard.multitracker.edit.title=Editor f\u00fcr mehrere Tracker wizard.multitracker.edit.name=Name wizard.multitracker.edit.save=Speichern wizard.multitracker.edit.newgroup=Neue Gruppe wizard.multitracker.edit.deletegroup=L\u00f6schen wizard.multitracker.edit.newtracker=Neuer Tracker wizard.multitracker.edit.deletetracker=L\u00f6schen wizard.multitracker.edit.edit=Bearbeiten wizard.addingmt=F\u00fcge Informationen f\u00fcr mehrere Tracker hinzu wizard.multitracker.noannounce=Ank\u00fcndigungs-URL ist nicht in der Tracker-Liste vorhanden MyTorrentsView.menu.recheck=Erzwinge erneute \u00dcberpr\u00fcfung iconBar.showDownloadBar.tooltip=Zeige Download-Leiste iconBar.start.tooltip=Starte ausgew\u00e4hlte Torrents iconBar.stop.tooltip=Stoppe ausgew\u00e4hlte Torrents iconBar.remove.tooltip=Entferne ausgew\u00e4hlte Torrents iconBar.openNoDefault.tooltip=\u00d6ffne Torrent-Datei (kein Standardspeichern) iconBar.openURL.tooltip=\u00d6ffne URL iconBar.openFolder.tooltip=\u00d6ffne Verzeichnis iconBar.new.tooltip=Torrent erzeugen iconBar.up.tooltip=Verschiebe hoch iconBar.down.tooltip=Verschiebe runter iconBar.run.tooltip=\u00d6ffne mit der Standardanwendung iconBar.host.tooltip=Hosten iconBar.publish.tooltip=Ver\u00f6ffentlichen iconBar.editcolumns.tooltip=Spalteneinstellung MyTorrentsView.menu.editTracker=Bearbeite Tracker-URL(s) GeneralView.menu.selectTracker=W\u00e4hlen ConfigView.section.stats.xslfile=XSL-Dateiname ConfigView.section.stats.xslfiledetails=Dies wird dem Statistik-Dateikopf via Tag hinzugef\u00fcgt ConfigView.label.savetorrentbackup=Speichere Backup ConfigView.section.tracker.forceport=Zwinge gehostete externe Torrents auf den Standardport ConfigView.section.ipfilter.allow=Erlaube nachfolgende Bereiche (Standard ist: Blockiere) ConfigView.section.ipfilter.list.inrange=war im Bereich ConfigView.section.ipfilter.list.notinrange=war in keinem Bereich ConfigView.section.ipfilter.list.title=Liste blockierter IPs ConfigView.label.allowsameip=Erlaube mehrere Verbindungen von derselben IP ConfigView.label.allowsameip.tooltip=Nur aktivieren, wenn WIRKLICH ben\u00f6tigt.\nDas ist ein Schutz vor Leechern (wenn deaktiviert). ConfigView.label.userSuperSeeding=Benutze Super-Seeding PeersView.uniquepiece=Teil (Super-Seed Modus) PeersView.uniquepiece.none=Keins PeersView.timetosend=Zeit bis zum erneuten Senden des Teils (Super-Seed Modus) ConfigView.section.style.addurlsilently=\u00d6ffne URL direkt (ohne Dialog) ConfigView.section.style.addurlsilently.tooltip=Automatisches Herunterladen an Vuze geleiteter .torrent-URLs, ohne zuvor die entsprechende Dialogbox zu \u00f6ffnen. ConfigView.section.file.decoder.prompt=Kodierungsauswahl immer anzeigen ConfigView.section.file.decoder.prompt.tooltip=Immer nachfragen, wenn eine Kodierungsauwahl verf\u00fcgbar ist MyTorrentsView.menu.moveTop=Anfang MyTorrentsView.menu.moveEnd=Ende ConfigView.label.moveonlyusingdefaultsave=nur, falls im Standardverzeichnis ConfigView.label.moveonlyusingdefaultsave.tooltip=Dateien werden nur verschoben, falls die Torrent-Daten im Standardverzeichnis gespeichert worden sind. ConfigView.label.watchtorrentfolder=Importiere neue Torrents automatisch ConfigView.label.watchtorrentfolder.tooltip=Schaut regelm\u00e4\u00dfig nach neuen Torrents ConfigView.label.watchtorrentfolderinterval=Intervall ConfigView.label.watchtorrentfolderinterval.tooltip=Intervall, in welchem das Verzeichnis auf neue Torrents durchsucht wird ConfigView.dialog.choosewatchtorrentfolderpath=Bitte w\u00e4hle das Torrent-Importverzeichnis ConfigView.label.startwatchedtorrentsstopped=Angehalten starten ConfigView.label.startwatchedtorrentsstopped.tooltip=Neue Torrents in angehaltenem Zustand der Warteschlange hinzuf\u00fcgen wizard.maketorrent.filesize=Dateigr\u00f6\u00dfe wizard.maketorrent.piececount=Anzahl der Teile wizard.maketorrent.piecesize=Gr\u00f6\u00dfe der Teile MainWindow.menu.view.stats=&Statistiken SpeedView.title.full=Aktivit\u00e4t SpeedView.downloadSpeed.title=Download-Geschwindigkeit SpeedView.uploadSpeed.title=Upload-Geschwindigkeit ConfigView.section.style.useSIUnits=Benutze IEC-Einheiten (kB -> KiB etc.) iconBar.top.tooltip=Verschiebe an Anfang iconBar.bottom.tooltip=Verschiebe ans Ende TableColumn.header.health=Fitness MyTorrentsView.menu.health=\u00dcber Torrent-Fitness health.explain.grey=Bedeutet, dass das Torrent inaktiv ist (weder Download noch Upload) health.explain.red=Bedeutet, dass beim Herunterladen keine Verbindungen zu anderen Quellen aufgebaut wurden. health.explain.blue=Beim Verteilen bedeutet es, dass noch keine Verbindungen zu anderen Quelle aufgebaut wurden.\nBeim Herunterladen bedeutet es, dass es zwar einigige Verbindungen zu Quellen gibt, der Tracker\njedoch nicht erreichbar ist. health.explain.yellow=Bedeutet, dass der Tracker ok ist, ausgehende Verbindungen mit Quellen vorliegen, jedoch keine\neingehenden Verbindungen aufgebaut werden k\u00f6nnen. M\u00f6glicherweise liegt ein NAT-Problem vor,\nwenn die Torrents diesen Status die ganze Zeit zeigen. health.explain.green=Bedeutet, dass alles ok ist. ConfigView.section.style.alwaysRefreshMyTorrents=Aktualisiere 'Meine Torrents' immer ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Diese Option wird die 'Meine Torrents'-Ansicht immer aktualisieren, auch wenn sie nicht angezeigt wird. (n\u00fctzlich bei einigen mIRC-Plugins) # #2.0.7.0 # security.certtruster.title=Sicherheitszertifikatswarnung security.certtruster.intro=Das Sicherheitszertifikat wurde von einer Firma ausgestellt, der Du nicht vertraust security.certtruster.resource=Ressource: security.certtruster.issuedto=Ausgestellt an: security.certtruster.issuedby=Ausgestellt von: security.certtruster.prompt=Diesem Zertifikat vertrauen? security.certtruster.yes=Ja security.certtruster.no=Nein ConfigView.section.tracker.torrentsperpage=Anzahl der Torrents pro Seite [0: unbegrenzt] MainWindow.menu.file.share=&Verteilen MainWindow.menu.file.share.file=&Datei... MainWindow.menu.file.share.dir=&Verzeichnis... MainWindow.menu.file.share.dircontents=V&erzeichnisinhalte... MainWindow.menu.file.share.dircontentsrecursive=Verzeichnisinhalte (&rekursiv)... MainWindow.dialog.share.sharefile=W\u00e4hle Datei zum Verteilen MainWindow.dialog.share.sharedir=W\u00e4hle Verzeichnis zum Verteilen MainWindow.dialog.share.sharedircontents=W\u00e4hle Verzeichnisinhalte zum Verteilen MainWindow.dialog.share.sharedircontents.recursive=Rekursiv globalmanager.download.remove.veto=Widerspruch gegen Entfernen eingelegt plugin.sharing.download.remove.veto=Dieser Download ist dadurch entstanden, da eine Ressource verteilt wird.\nUm den Download zu entfernen, muss der dazugeh\u00f6rige Share entfernt werden.: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Haupt ConfigView.label.prioritizefirstpiece=Priorisiere erstes und letztes Teil von Datei(en) ConfigView.label.prioritizefirstpiece.tooltip=Versucht den Anfang und das Ende von Dateien zuerst herunterzuladen, um eine fr\u00fchzeitige Vorschau der Daten zu erlauben. ConfigView.section.file.confirm_data_delete=L\u00f6schen von Daten best\u00e4tigen ConfigView.section.file.confirm_data_delete.tooltip=L\u00f6schen von Daten bei Benutzung von 'Entfernen und L\u00f6schen...' best\u00e4tigen ConfigView.section.file.delete.include_files_outside_save_dir=Beim L\u00f6schen von Daten, erlaube auch das L\u00f6schen von Dateien, die ausserhalb des Speicherverzeichnisses verlinkt sind TrayWindow.menu.startalldownloads=Starte alle Downloads SystemTray.menu.startalltransfers=Starte alle \u00dcbertragungen sharing.progress.title=Verteilungsfortschritt sharing.progress.hide=Ausblenden MainWindow.menu.view.myshares=Mein Share MySharesView.title.full=Mein Share MySharesView.type=Typ MySharesView.type.file=Datei MySharesView.type.dir=Verzeichnis MySharesView.type.dircontents=Verzeichnisinhalte MySharesView.type.dircontentsrecursive=Verzeichnisinhalte (rekursiv) MySharesView.menu.remove=Entfernen ConfigView.section.tracker.extensions=Erweiterungen ConfigView.section.tracker.sendpeerids=Sende Identit\u00e4t der Quelle an Downloader ConfigView.section.tracker.enableudp=Aktiviere UDP-Trackerprotokoll plugin.sharing.torrent.remove.veto=Die Registrierung dieses Trackers ist dadurch entstanden, dass eine Ressource verteilt wird.\nUm den Download zu entfernen, muss der dazugeh\u00f6rige Share entfernt werden: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Download kann nicht entfernt werden, da er nicht angehalten wurde plugin.sharing.remove.veto=Dieser Share ist ein Unter-Share des Shares eines Verzeichnisinhaltes und kann so nicht gel\u00f6scht werden.\nEntferne den \u00fcbergeordneten Share GeneralView.label.hash.tooltip=Kopiere den Hash in die Zwischenablage ConfigView.section.tracker.maxpeersreturned=max. zur\u00fcckgelieferte Quellen [0: unbegrenzt] ConfigView.label.serverport=Eingehender TCP- und UDP-Port ConfigView.label.serverport.tooltip=Port muss im Bereich zwischen 1 und 65535 liegen. TCP-Port 6880 ist f\u00fcr internet Zwecke reserviert und darf nicht benutzt werden. configureWizard.nat.server.tcp_listen_port=Eingehender TCP-Port ConfigView.section.sharing=Verteilen ConfigView.section.sharing.usessl=Benutze SSL f\u00fcr verteilte Ressourcen (ben\u00f6tigt Tracker-Konfiguration) ConfigView.section.style.dropdiraction=Drag and Drop f\u00fcr Verzeichnisse ConfigView.section.style.dropdiraction.opentorrents=\u00d6ffne Torrents ConfigView.section.style.dropdiraction.sharefolder=Verteile Verzeichnis ConfigView.section.style.dropdiraction.sharefoldercontents=Verteile Verzeichnisinhalt # # 2.0.7.x # Categories.all=Alle Categories.uncategorized=Unkategorisiert CategoryAddWindow.message=Neuen Kategorienamen eingeben CategoryAddWindow.title=Neue Kategorie hinzuf\u00fcgen ConfigView.label.autoSeedingIgnoreInfo=Ignorierte Torrents werden an das Ende der Warteschlange zu verteilender Daten verschoben. Sie werden nicht automatisch gestartet. Ignorierregeln werden nicht auf Torrents angewandt, die dem Kriterium der Obersten Priorit\u00e4t entsprechen. Solange nicht anders angegeben, benutze den Wert 0 um eine Regel zu deaktivieren. ConfigView.label.directory=Verzeichnis ConfigView.label.disconnetseed.tooltip=Wenn ein Torrent fertig heruntergeladen ist, trenne Verbindungen zu allen anderen vollst\u00e4ndigen Quellen.\nMit ihnen muss nicht mehr kommuniziert werden. ConfigView.label.ignoreCase=Ignorieren wenn ConfigView.label.ignoreSeeds=Ignoriere Torrents mit mindestens ConfigView.label.importdirectory=Import-Verzeichnis ConfigView.label.minPeersToBoostNoSeeds.tooltip=Jeder Torrent, der keine vollst\u00e4ndigen Quellen und weniger unvollst\u00e4ndigen Quellen, als angegeben, besitzt, wird an das Ende der Warteschlange gestellt. ConfigView.label.minPeersToBoostNoSeeds=Verringere Verteilungsrang f\u00fcr Torrents mit keinen Quellen oder weniger als ConfigView.label.minSeedingTime.tooltip=Verteilungsr\u00e4nge k\u00f6nnen oft in einer kurzen Zeitspanne fluktuieren, was manchmal dazu f\u00fchrt, dass der Torrent automatisch startet, aber sofort wieder stoppt, um danach wieder in der Warteschlange zu landen.\nDiese Einstellung verringert das Problem, indem sie den Torrent dazu zwingt, f\u00fcr eine gewisse Zeit gestartet zu bleiben und verteilt zu werden. Der Torrent kann jederzeit manuell gestoppt werden. ConfigView.label.minSeedingTime=min. Verteilungszeit in Sekunden ConfigView.label.minSpeedForActiveDL.tooltip=Ein Download-Slot wird immer f\u00fcr die ersten 30 Sekunden benutzt, nachdem der unfertige Torrent startet. ConfigView.label.minSpeedForActiveDL=Unfertiger Torrent benutzt keinen Download-Slot, falls Geschwindigkeit kleiner als ConfigView.label.peers=unvollst\u00e4ndige Quellen ConfigView.label.queue.debuglog=Protokolliere Debug-Informationen ConfigView.label.queue.debuglog.info=F\u00fcgt Warteschlangen-Debug-Informationen der Konsole bzw. dem Log hinzu.\nAuch wenn es kryptisch erscheint, zeigen Debug-Informationen den Status der Torrents und m\u00f6glicherweise auftretende Probleme. ConfigView.label.queue.minQueueingShareRatio=Torrent erst der Warteschlange hinzuf\u00fcgen oder anhalten,\n wenn das Verh\u00e4ltnis folgenden Wert erreicht ConfigView.label.ratio=Verh\u00e4ltnis ConfigView.label.removeOnStop=Nachdem ein Torrent automatisch angehalten wurde, von der Liste entfernen ConfigView.label.savedirectory=Verzeichnis zum Speichern ConfigView.label.seeding.autoReposition.tooltip=Wenn aktiviert, wird die Reihenfolge der Torrents (Spalte '#') entsprechend des Verteilungsranges ge\u00e4ndert.\nDies ist n\u00fctzlich, falls man die Rangnummern nicht sehen m\u00f6chte, aber trotzdem \u00fcber die Startreihenfolge\nvollst\u00e4ndiger Torrents informiert sein will. ConfigView.label.seeding.autoReposition=Automatische Positionierung der Torrents ausgehend von ihrem Verteilungsrang ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Torrents mit wenigen vollst\u00e4ndigen Quellen und vielen unvollst\u00e4ndigen Quellen bedeuten meistens, dass keine komplette Kopie unter den unvollst\u00e4ndigen Quellen vorhanden ist.\nDeswegen m\u00f6chte man eventuell, dass die Verteilungsregeln eine komplette Kopie vort\u00e4uschen (und somit den Rang ungerechtfertigt verringern) ConfigView.label.seeding.fakeFullCopySeedStart=aber nur f\u00fcr Torrents mit mindestens ConfigView.label.seeding.ignore=Ignorierregeln ConfigView.label.seeding.ignore0Peers=Ignoriere Torrents ohne unvollst\u00e4ndige Quellen ConfigView.label.seeding.ignoreRatioPeers=Ignoriere Torrents mit mindestens einer vollst\u00e4ndigen Quelle f\u00fcr je ConfigView.label.seeding.ignoreShareRatio=Ignoriere Torrents mit einem Verh\u00e4ltnis von ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignoriere Torrent auch wenn \nOberste Priorit\u00e4tsregeln angewandt sind ConfigView.label.seeding.ignore.header.rule=Regel ConfigView.label.seeding.ignore.header.value=Wert ConfigView.label.seeding.firstPriority.info=Torrents mit oberster Priorit\u00e4t werden immer an den Anfang der Warteschlange gestellt.\n Alle Torrents die dem obersten Priorit\u00e4tskriterium entsprechen werden nicht automatisch\n angehalten und in die Warteschlange gestellt. Ein Torrent, der dem obersten\n Priorit\u00e4tskriterium entspricht, wird einen simultanen Download-Slot verwenden,\n falls er ihn ben\u00f6tigt.\n ConfigView.label.seeding.firstPriority.FP=Oberste Priorit\u00e4t ConfigView.label.seeding.firstPriority=Oberste Priorit\u00e4t f\u00fcr Torrents mit ConfigView.label.seeding.firstPriority.following=folgenden Regel(n): ConfigView.label.seeding.firstPriority.shareRatio=Bei einem Verh\u00e4ltnis von unter ConfigView.label.seeding.firstPriority.seedingMinutes=Einer vergangenen Zeit seit dem Wechsel von Download zu Verteilen von ConfigView.label.seeding.firstPriority.DLMinutes=Einer vergangenen Zeit seit dem Start des Downloads von ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Durch das Vort\u00e4uschen des Vorhandenseins von einer kompletten Kopie f\u00fcr 'n' unvollst\u00e4ndige Quellen, wird der Rang von Torrents mit sehr vielen unvollst\u00e4ndigen Quellen reduziert.\nMeistens verursachen Torrents mit sehr vielen unvollst\u00e4ndigen Quellen auch viel Datenverkehr.\nDas \u00e4ndert nicht die Anzeige der Anzahl vollst\u00e4ndiger Quellen. ConfigView.label.seeding.numPeersAsFullCopy=T\u00e4usche vor, es gibt jeweils eine komplette Kopie f\u00fcr je\n(0: kein Vort\u00e4uschen) ConfigView.label.seeding.preferLargerSwarms.tooltip=Die Bevorzugung gro\u00dfer Schw\u00e4rme macht bei Torrents Sinn, deren unvollst\u00e4ndige Quellen "feststecken".\nDie Bevorzugung kleiner Schw\u00e4rme macht bei Torrents Sinn, die eine hohe Verf\u00fcgbarkeit haben. ConfigView.label.seeding.preferLargerSwarms=Bevorzuge gro\u00dfe Schw\u00e4rme bei Torrents gleichen Ranges ConfigView.label.seeding.rankType.none.tooltip=Reihenfolge anhand der #-Spalte ConfigView.label.seeding.rankType.none=Keine ConfigView.label.seeding.rankType.peer.tooltip=mehr uvQ und weniger vQ = h\u00f6herer Rang\nDiese R\u00e4nge minimieren die Anzahl der Torrents, die aktiv gehalten werden m\u00fcssen, um den Upload auszulasten. ConfigView.label.seeding.rankType.peer=Gewichtete Quellenanzahl ConfigView.label.seeding.rankType.peerSeed.options=Einstellungen f\u00fcr Verh\u00e4ltnis von unvollst\u00e4ndigen zu vollst\u00e4ndigen Quellen ConfigView.label.seeding.rankType.peerSeed.tooltip=H\u00f6heres Verh\u00e4ltnis = H\u00f6herer Rang ConfigView.label.seeding.rankType.peerSeed=Verh\u00e4ltnis von unvollst\u00e4ndigen zu vollst\u00e4ndigen Quellen ConfigView.label.seeding.rankType.seed.fallback=R\u00fcckfall auf Verh\u00e4ltnis unvollst\u00e4ndige zu vollst\u00e4ndige Quellen nach\n(0: nie r\u00fcckfallen) ConfigView.label.seeding.rankType.seed.options=Einstellungen, bei denen nur die Anzahl der vollst\u00e4ndigen Quellen wichtig ist ConfigView.label.seeding.rankType.seed.tooltip=Wenigere vollst\u00e4ndige Quellen = H\u00f6herer Rang ConfigView.label.seeding.rankType.seed=nur vollst\u00e4ndige Quellen z\u00e4hlen ConfigView.label.seeding.rankType.timedRotation.tooltip=Alle fertigen Torrents in der Warteschlange rotieren im Verteilungsmodus.\nDie Dauer der Verteilung wird durch 'min. Verteilungszeit' bestimmt ConfigView.label.seeding.rankType.timedRotation=Zeitliche Rotation ConfigView.label.seeding.rankType.tooltip=Torrents mit den h\u00f6chsten R\u00e4ngen werden automatisch gestartet.\nBekommt ein Torrent einen h\u00f6heren Rang, wird der rangniedere Torrent angehalten.\n\nNur Torrents im Wartezustand sind f\u00fcr den automatischen Start verf\u00fcgbar.\nAngehaltene Torrents werden niemals automatisch gestartet. ConfigView.label.seeding.rankType=Der Rang fertiger Torrents f\u00fcr das automatische Starten basiert auf: ConfigView.label.stopAfterMinutes=Zeit in Minuten, nach welcher ein Torrent gestoppt wird, welches von Herunterladen zu Verteilen gewechselt hat ConfigView.label.switchpriority.tooltip=Niedrige Priorit\u00e4t reduziert die zugewiesene Upload-Bandbreite eines Torrents. ConfigView.pluginlist.info=Die folgenden Plugins wurden identifiziert. Einige Plugins haben m\u00f6glicherweise keine Konfigurationsm\u00f6glichkeit. ConfigView.pluginlist.noplugins=Keine Plugins gefunden. ConfigView.section.pluginslist=Liste ConfigView.section.queue.seeding=Verteilen ConfigView.section.queue.seeding.autoStarting=Autostart ConfigView.section.queue.seeding.ignore=Ignorierregeln ConfigView.section.queue.seeding.firstPriority=Oberste Priorit\u00e4t ConfigView.section.queue.main=Haupt ConfigView.section.queue=Warteschlange ConfigView.text.all=allen ConfigView.text.hours=Stunden ConfigView.text.ignoreRule=Ignorierregel ConfigView.text.ignore=Ignorieren ConfigView.text.minutes=Minuten ConfigView.text.neverIgnore=Niemals ignorieren ConfigView.text.any=irgendeiner DownloadManager.error.datamissing=Daten fehlen MainWindow.menu.file.open.torrentforseeding=Torrent-Datei... (zum V&erteilen) MainWindow.menu.language.refresh=Aktualisieren ManagerItem.forced=Erzwungenes ManagerItem.queued=in Warteschlange MySeedersView.header=Fertige Torrents TableColumn.header.availability.info=Anzahl sichtbarer kompletter Kopien TableColumn.header.availability=Verf\u00fcgbarkeit TableColumn.header.category=Kategorie MyTorrentsView.header=Unvollst\u00e4ndige Torrents TableColumn.header.maxuploads=Uploadslots MyTorrentsView.menu.category.delete=L\u00f6sche Kategorie MyTorrentsView.menu.forceStart=Start erzwingen MyTorrentsView.menu.queue=Start - in Warteschlange MyTorrentsView.menu.setCategory.add=F\u00fcge Kategorie hinzu... MyTorrentsView.menu.setCategory=Weise Kategorie zu TableColumn.header.savepath=Speichern unter TableColumn.header.SeedingRank=Verteilungsrang TableColumn.header.totalspeed.info=Summe der Downloadgeschwindigkeiten aller Quellen, mit denen man im Moment verbunden ist TableColumn.header.totalspeed=Schwarmgeschw. splash.initializePlugins=Initialisiere Plugins StartStopRules.SPratioMet=S:P Verh\u00e4ltnis OK StartStopRules.FP0Peers=OP / 0 uv Quellen StartStopRules.0Peers=0 unvollst\u00e4ndige Quellen StartStopRules.numSeedsMet=Anzahl vollst. Quellen OK StartStopRules.ratioMet=uvQ:vQ OK StartStopRules.shareRatioMet=Verh\u00e4ltnis OK StartStopRules.waiting=Warten StartStopRules.firstPriority=Oberste Priorit\u00e4t ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Verteile Verzeichnisinhalt (rekursiv) DownloadManager.error.unabletostartserver=Kann Server nicht starten - \u00dcberpr\u00fcfe die Konfiguration der eingehenden Ports / Firewalleinstellungen f\u00fcr Anwendungen, um als Server zu agieren GeneralView.label.creationdate=Erstellt am: ConfigView.section.tracker.announcescrapepercentage=Scrape-Intervall in Prozent der Ank\u00fcndigung\nz.B. 200 = 2:1. [0 = lasse Quelle entscheiden] ManagerItem.stopping=Stoppe ConfigView.section.tracker.announcecacheperiod=K\u00fcndige Cache an alle (in ms) ConfigView.section.tracker.scrapecacheperiod=Scrape Cache (in ms) ConfigView.section.tracker.scrapeandcache=Scrape und Cache ConfigView.section.tracker.announcecacheminpeers=K\u00fcndige cache-aktivierten Quellenschwellwert an fileDownloadWindow.retry=Wiederholen MyTrackerView.bytesin=Bytes rein MyTrackerView.bytesinave=\u00d8 rein MyTrackerView.bytesout=Bytes raus MyTrackerView.bytesoutave=\u00d8 raus ConfigView.section.file.max_open_files=max. Anzahl ge\u00f6ffneter Dateien zum Lesen/Schreiben\n[0: unbegrenzt] ConfigView.section.file.max_open_files.tooltip=N\u00fctzlich, wenn Torrents heruntergeladen werden, die Hunderte/Tausende von Dateien\nenthalten und die Grenze der Dateihandhabung des Betriebssystem erreicht wird. ConfigView.section.proxy=Proxy-Einstellungen ConfigView.section.proxy.enable_proxy=Aktiviere Proxy-Nutzung f\u00fcr Tracker-Kommunikation [Neustart ben\u00f6tigt] ConfigView.section.proxy.username=Benutzername ConfigView.section.proxy.password=Passwort ConfigView.section.proxy.enable_socks=Ich habe einen SOCKS Proxy wizard.createtorrent.extrahashes=F\u00fcge Pr\u00fcfsummen f\u00fcr andere Netzwerke hinzu (z.B. Gnutella2, eDonkey2000) GeneralView.label.connected=verbunden GeneralView.label.in_swarm=sieht Tracker ManagerItem.initializing=Initialisiere AlertMessageBox.error=Fehler AlertMessageBox.warning=Warnung AlertMessageBox.comment=Informationen AlertMessageBox.information=Informationen AlertMessageBox.unread=Es liegen ungelesene Warnmeldungen vor - bitte hier klicken, um sie anzuzeigen. SharedPortServer.alert.selectorfailed=Aufbau der wartenden Verbindung f\u00fcr ankommende Daten fehlgeschlagen.\n\u00dcberpr\u00fcfe die Firewall und erlaube java(w).exe als 'Server' zu agieren. Tracker.alert.listenfail=Aufbau der Verbindung zum angegebenen Port %1 fehlgeschlagen.\n\u00dcberpr\u00fcfe, ob andere Anwendungen diesen Port benutzen.\nM\u00f6glicherweise l\u00e4uft eine weitere Instanz von Vuze. DiskManager.alert.movefileexists=Fehler beim Verschieben fertiger Dateien\nDie Datei %1 existiert bereits im Zielverzeichnis DiskManager.alert.movefilefails=Fehler beim Verschieben fertiger Dateien\nDas Verschieben von Datei %1 ist fehlgeschlagen, %2 DiskManager.alert.movefilerecoveryfails=Fehler beim Wiederherstellen nach dem fehlgeschlagenen Verschieben\nWiederherstellung von Datei %1 fehlgeschlagen, %2 ConfigView.section.tracker.logenable=Periodisches Protokollieren der Statistiken in 'tracker.log' SpeedView.stats.title=Statistiken SpeedView.stats.total=Gesamt SpeedView.stats.session=Diese Sitzung SpeedView.stats.session.tooltip=Total (Protokoll) SpeedView.stats.downloaded=Heruntergeladen (Protokoll) SpeedView.stats.uploaded=Hochgeladen (Protokoll) SpeedView.stats.ratio=Verh\u00e4ltnis SpeedView.stats.uptime=Laufzeit SpeedView.stats.now=Momentan SpeedView.stats.now.tooltip=Gesamt (Protokoll) AutoMigration.useralert=Vuze-Benutzerkonfigurationsdateien/-verzeichnisse-Auto-Migrationsergebnis:\n\n%1\nAlle Fehlschl\u00e4ge m\u00fcssen manuell verschoben werden.\nVERGESSE NICHT DIE SPEICHERVERZEICHNISSE IN DER KONFIGURATION ZU AKTUALISIEREN, FALLS DIESE AUCH VERSCHOBEN WORDEN SIND! # # > 2.0.8.0 # OpenTorrentWindow.title=\u00d6ffne Torrent(s) OpenTorrentWindow.message=Experimentell OpenTorrentWindow.addFiles=Dateien hinzuf\u00fcgen OpenTorrentWindow.dataLocation=Ort zur Speicherung der Daten: OpenTorrentWindow.startMode=Hinzuf\u00fcgemodus OpenTorrentWindow.startMode.queued=Wartend OpenTorrentWindow.startMode.stopped=Angehalten OpenTorrentWindow.startMode.forceStarted=Erzwungener Start OpenTorrentWindow.addPosition=Warteschlangenposition OpenTorrentWindow.addPosition.first=Erste OpenTorrentWindow.addPosition.last=Letzte TableColumn.header.remaining.info=Verbleibende Datenmenge des Downloads TableColumn.header.remaining=Verbleibend ConfigView.section.tracker.enablecompact=Aktiviere das 'Kompakte Ank\u00fcndigungsprotokoll' (compact announce protocol) ConfigView.section.tracker.enablekey=Aktiviere die \u00dcbermittlung von Schl\u00fcsseln an\nden Tracker f\u00fcr verbesserte Sicherheit ConfigView.section.file.perf=Erweiterte Einstellungen ConfigView.section.file.perf.explain=Achtung - unsachgem\u00e4\u00dfer Gebrauch dieser Parameter kann sich nachteilig auf die Download-Geschwindigkeit auswirken. Neustart ben\u00f6tigt.\nSollten 'out of memory' Probleme auftreten, ist die Verbindungsanzahl pro Torrent zu begrenzen (Siehe \u00dcbertragung). ConfigView.section.file.max_open_files.explain=Das \u00d6ffnen zu vieler Dateien kann durch limitierte Ressourcen zu Problemen mit dem Betriebssystem f\u00fchren. Dies begrenzt die Anzahl gleichzeitig ge\u00f6ffneter Dateien. popup.error.hide=Ausblenden ConfigView.section.style.colorOverrides=Farbzuweisung ConfigView.section.style.colorOverride.progressBar=Fortschrittsbalken ConfigView.section.style.colorOverride.error=Fehler MainWindow.status.tooOld=ist zu alt, bitte aktualisieren. ConfigView.section.style.colorOverride.warning=Warnung ConfigView.section.style.colorOverride.altRow=Andere Zeilen ConfigView.section.file.save.peers.enable=Speichere Quellenverbindung f\u00fcr schnelles Wiederverbinden ConfigView.section.file.save.peers.max=max. zu speichernde Quellen [0: unbegrenzt] ConfigView.section.file.save.peers.pertorrent=pro Torrent ConfigView.label.max_peers_per_torrent=max. Verbindungen pro Torrent ConfigView.label.max_peers_total=max. globale Verbindungen ConfigView.section.style.colorOverrides.reset=Farbe zur\u00fccksetzen ConfigView.section.language.info=Wenn aktiviert, wird bei jedem Start von Vuze nach einer aktuellen Version gesucht. ConfigView.section.language.enableUpdate=Aktiviere Webaktualisierung ConfigView.section.language.UpdateURL=Update-URL ConfigView.section.language.UpdateNow=Jetzt aktualisieren! Button.revert=Zur\u00fcck MyTorrentsView.menu.changeDirectory=\u00c4ndere Datenverzeichnis GenericText.column=Spalte MyTorrentsView.menu.thisColumn.remove=Entferne Spalte MyTorrentsView.menu.thisColumn.toClipboard=Text in die Zwischenablage kopieren MyTorrentsView.menu.thisColumn.autoTooltip=Zeige immer Tooltip TableColumn.header.secondsseeding=Verteilen seit TableColumn.header.secondsseeding.info=Zeit, seit der Daten verteilt werden TableColumn.header.secondsdownloading=DL seit TableColumn.header.secondsdownloading.info=Dauer des Downloads. ConfigView.section.tracker.udpversion=UDP-Protokoll-Version (1 oder 2) window.updateswt.title=Ihre SWT-Version ist zu alt! window.updateswt.text=Ihre SWT-Version ist zu alt!\nSWT ist die graphische Bibliothek, die von Vuze genutzt wird. Ihre Version ist zu alt um die neueste Version von Vuze zu starten. Klicken Sie auf OK f\u00fcr die Aktualisierung. window.updateswt.failed=Aktualisierung fehlgeschlagen, dr\u00fccken Sie OK f\u00fcr einen Neustart. window.updateswt.status.downloading.updater=Updater-Modul wird heruntergeladen window.updateswt.status.finding=Neueste SWT-Version wird gesucht window.updateswt.status.downloading=Neueste SWT-Version wird heruntergeladen window.updateswt.status.done=Starte neu window.updateswt.cancel=Abbrechen swt.updater.downloader.downloading=SWT wird heruntergeladen von swt.updater.urlsgetter.downloading=Empfange eine Mirror-Liste von swt.updater.urlsgetter.platform=SWT f\u00fcr: window.updateswt.ignore=Ignorieren ConfigView.section.style.useFancyTabs=Benutze abgerundete Tabs splash.initializeGM=Initialisiere Global Torrent Manager splash.loadingTorrents=Lade Torrents MyTorrentsView.menu.thisColumn.sort=Sortieren Scrape.status.ok=Scrape OK. Scrape.status.error=Scrape-Fehler: Scrape.status.error.badURL=Ank\u00fcndigungs-URL h\u00e4lt Scrape-Spezifikationen nicht ein. Scrape.status.error.nohash=Fehlender Hash von Antwort. Scrape.status.error.invalid=Ung\u00fcltige Antwort. Scrape.status.nextScrapeAt=N\u00e4chster Scrape um %1 Scrape.status.initializing=Warte auf Scrape Scrape.status.scraping.queued=Scrape in K\u00fcrze... ConfigView.label.minSpeedForActiveSeeding=Fertiger Torrent benutzt keinen Upload-Slot, falls Geschwindigkeit kleiner als ConfigView.section.stats.exportpeers=Exportiere Quellendetails MainWindow.menu.view.irc.moved=IRC ist nun als Plugin verf\u00fcgbar, http://azureus.sourceforge.net/plugin_list.php . Nach der Installation k\u00f6nnen Sie \u00fcber Plugins->IRC darauf zugreifen. MyTrackerView.webui.contextmenu.copyurl=Kopiere Torrent-URL in die Zwischenablage ConfigView.section.file.torrent.ignorefiles=Folgenden Dateien bei der Erstellung von Torrents ignorieren\nz.B. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignoriere Datei ConfigView.section.style.useUnitsRateBits=Benutze Bits anstelle von Bytes f\u00fcr Byte-basierte Werte (KiB/s->KiBit/s etc.) ConfigView.section.interface.resetassoc=Torrent-Dateizuweisung f\u00fcr Explorer zur\u00fccksetzen ConfigView.section.interface.resetassocbutton=Zur\u00fccksetzen ConfigView.section.interface.checkassoc=\u00dcberpr\u00fcfe Zuweisungen beim Start dialog.associations.title=\u00dcberpr\u00fcfung der Dateiverkn\u00fcpfungen Button.yes=&Ja Button.no=&Nein ConfigView.label.seeding.autoStart0Peers=Alle fertigen Torrents mit 0 unvollst\u00e4ndigen Quellen automatisch starten ConfigView.label.seeding.autoStart0Peers.tooltip=Aktiviere diese Option, falls der Tracker auch f\u00fcr Torrents ohne unvollst\u00e4ndige Quellen fertige Torrents anzeigen soll. dialog.associations.prompt=Vuze ist nicht die Standardanwendung f\u00fcr BitTorrent-Dateien.\nSollen .torrent-Dateien mit Vuze verkn\u00fcpft werden? dialog.associations.askagain=Beim Start \u00fcberpr\u00fcfen ConfigView.section.plugins.update=Plugin-Aktualisierung Plugin.pluginupdate.enablecheck=Regelm\u00e4\u00dfige \u00dcberpr\u00fcfung auf Plugin-Updates plugins.basicview.status=Status: plugins.basicview.activity=Aktivit\u00e4t: plugins.basicview.progress=Fotschritt: plugins.basicview.log=Protokoll: ConfigView.label.maxdownloadspeed=kB/s globale max. Download-Geschwindigkeit [0: unbegrenzt] splash.loadingTorrent=Lade Torrent splash.of=von UpdateWindow.title=Vuze-Updater UpdateWindow.header=Die folgenden Komponenten ben\u00f6tigen eine Aktualisierung: UpdateWindow.columns.install=Installieren UpdateWindow.columns.size=Gr\u00f6\u00dfe UpdateWindow.cancel=Abbrechen UpdateWindow.quit=Beenden UpdateWindow.close=Schlie\u00dfen UpdateWindow.ok=Aktualisieren UpdateWindow.restart=Jetzt neustarten UpdateWindow.status.downloading=Herunterladen UpdateWindow.status.done=Fertig UpdateWindow.status.failed=Fehlgeschlagen UpdateWindow.status.restartNeeded=Neustart ben\u00f6tigt! ConfigView.pluginlist.broken=Defekt ConfigView.pluginlist.whereToPut=Lege alle benutzerspezifischen Plugins in ihr eigenes Verzeichnis unter: ConfigView.pluginlist.whereToPutOr=Plugins f\u00fcr alle Benutzer werden installiert in: MainWindow.statusText.checking=\u00dcberpr\u00fcfe auf Updates TableColumn.header.OnlyCDing4=Nur verteilen seit TableColumn.header.OnlyCDing4.info=Zeit, seit der Daten nur noch verteilt werden (ohne Dauer des Downloads) ConfigView.section.style.alternateTablePainting=Benutze alternative Methode zum Zeichnen von Tabellenspalten (m\u00f6glicherweise Neustart ben\u00f6tigt) UpdateWindow.status.restartMaybeNeeded=Neustart k\u00f6nnte ben\u00f6tigt werden ConfigView.pluginlist.shared=F\u00fcr alle Benutzer PeersView.host=Hostname PeersView.host.info=Der Hostname der Quelle, wenn verf\u00fcgbar (hat m\u00f6glicherweise Einfluss auf Performance) MainWindow.menu.help.whatsnew=Was ist &neu ConfigView.label.checkonstart=\u00dcberpr\u00fcfe beim Start von Vuze ob eine neuere Version verf\u00fcgbar ist ConfigView.label.periodiccheck=\u00dcberpr\u00fcfe periodisch auf neue Version ConfigView.label.opendialog=\u00d6ffne den Update-Assistenten automatisch, sobald ein Update verf\u00fcgbar ist MainWindow.updateavail=(Update verf\u00fcgbar) MainWindow.status.unofficialversion=Vuze-Beta MainWindow.status.latestversionunchecked=Versions\u00fcberpr\u00fcfung deaktiviert GeneralView.label.updatein.stopped=Angehalten StartStopRules.menu.viewDebug=Zeige Debug-Info ConfigView.section.style.doNotUseGB=GB nicht als Einheit benutzen ConfigView.section.style.doNotUseGB.tooltip=Wenn aktiviert, wird Vuze die Einheit MB auch f\u00fcr Angaben gr\u00f6\u00dfer als 1024 MB benutzen MainWindow.menu.help.plugins=&Pluginliste im Internet ConfigView.section.plugins.TrackerWeb=Tracker-Web ConfigView.section.tracker.enablecategories=Trenne Torrents je nach Kategorie health.explain.share=Bedeutet, dass der Torrent gehosted oder ver\u00f6ffentlicht wird. ConfigView.section.tracker.createcert=Erzeuge selbstsigniertes Zertifikat ConfigView.section.tracker.createbutton=Erzeugen security.certcreate.title=Erzeuge selbstsigniertes Zertifikat security.certcreate.intro=Dieser Dialog erm\u00f6glicht, ein selbstsigniertes Zertifikat zu erzeugen security.certcreate.strength=St\u00e4rke security.certcreate.firstlastname=Vor- und Nachname security.certcreate.orgunit=Organisationseinheit security.certcreate.city=Stadt oder Ort security.certcreate.state=Bundesland oder Staat security.certcreate.country=L\u00e4ndercode (2 Buchstaben) security.certcreate.ok=Erzeugen security.certcreate.cancel=Abbrechen security.certcreate.createok=Zertifikat erfolgreich erstellt security.certcreate.createfail=Zertifikatserstellung fehlgeschlagen ConfigView.section.plugins.webui=Swing Web-Interface ConfigView.section.plugins.xml_http_if=XML/HTTP-Interface webui.passwordenable=Passwort aktivieren webui.user=Benutzername webui.password=Passwort webui.protocol=Protokoll (*) webui.homepage=Homepage (*) webui.rootdir=Wurzelverzeichnis (*) webui.rootres=Wurzelressource (*) webui.mode=Modus (*) webui.mode.info=Modus kann folgender sein\n\t"full"\t= alle Operationen verf\u00fcgbar (Standard)\n\t"view"\t= nur Ansicht (Aktualisierungsspanne kann festgelegt werden) webui.access=Zugriff (*) webui.access.info=Zugriff kann folgender sein\n\t"local"\t= nur der lokale Rechner kann sich verbinden\n\t"all"\t= uneingeschr\u00e4nkter Zugriff (Standard)\n\tIP\t= z.B. 192.168.0.2\t\t\tnur eine IP\n\tIP1-IP2\t= z.B. 192.168.0.1-192.168.0.255\tinklusive der Spanne von IPs dazwischen GeneralView.label.maxdownloadspeed=Down-Limit Security.keystore.corrupt=Laden des Schl\u00fcsselspeichers '%1' fehlgeschlagen. Bitte l\u00f6sche ihn und erstellen/importieren die Zertifikate neu Security.keystore.empty=Schl\u00fcsselspeicher ist leer. Erzeuge bitte ein selbstsigniertes Zertifikat (Konfiguration->Sicherheit) oder importiere ein bereits vorhandenes nach '%1' webui.restart.info=\u00c4nderungen von Parametern die mit (*) markiert sind, ben\u00f6tigen einen Neustart, um sie zu aktivieren. GeneralView.label.maxdownloadspeed.tooltip=max. Download-Geschwindigkeit [0: unbegrenzt] upnp.enable=UPnP aktivieren upnp.info=Universelles Plug and Play (UPnP) erlaubt die automatische Zuweisung von Ports, wenn der Router UPnP unterst\u00fctzt. upnp.mapping.dataport=Eingehender Datenport f\u00fcr Quellen upnp.mapping.tcptrackerport=TCP-Tracker-Port upnp.mapping.udptrackerport=UDP-Tracker-Port upnp.alert.differenthost=UPnP: Zuordnung '%1' wurde durch '%2' reserviert - bitte einen anderen Port w\u00e4hlen upnp.alert.mappingok=UPnP: Zuordnung '%1' hergestellt upnp.alert.mappingfailed=UPnP: Zuordnung '%1' fehlgeschlagen upnp.alertsuccess=Melde erfolgreiche Zuordnungen upnp.alert.lostdevice=UPnP: Verbindung zum Service '%1' auf UPnP-Ger\u00e4t '%2' verloren upnp.grabports=Auch zuordnen, wenn Ports einem anderen Computer geh\u00f6ren upnp.refresh.label=Zuordnungen aktualisieren upnp.refresh.button=Aktualisieren upnp.alert.mappinggrabbed=UPnP: Zuordnung '%1' hergestellet - von '%2' genommen upnp.mapping.tcpssltrackerport=TCP-SSL-Tracker-Port upnp.alertothermappings=Melde Ports, die einem anderen Computer geh\u00f6ren upnp.alertdeviceproblems=Melde Probleme mit dem UPnP-Ger\u00e4t upnp.trace_to_log=Protokolliere alle Debug-Informationen upnp.wiki_link=Seite der Vuze-Wiki \u00fcber UPnP upnp.refresh_mappings_on_bad_nat=Mappings automatisch auffrischen, wenn ein NAT-Problem vorliegt ConfigView.pluginlist.coreplugins=Die folgenden fest eingebauten Plugins sind geladen: Peers.column.DLedFromOthers=Von anderen Peers.column.DLedFromOthers.info=Datenvolumen, das von anderen Quellen heruntergeladen wurde, solange mit ihnen eine Verbindung besteht Peers.column.UpDownRatio=UL:DL Peers.column.UpDownRatio.info=Verh\u00e4ltnis hochgeladener zu heruntergeladenen Daten mit dieser Quelle Peers.column.UpRatio=Up-Ratio Peers.column.UpRatio.info=Verh\u00e4ltnis der zu dieser Quelle hochgeladenen Datenmenge zu der Datenmenge, die diese Quelle von anderen Quellen erhalten hat upnp.releasemappings=Gib Zuordnungen beim Schlie\u00dfen wieder frei webui.upnpenable=UPnP f\u00fcr diesen Port aktivieren (*) ConfigView.section.file.friendly.hashchecking=Freundliche Hash\u00fcberpr\u00fcfung ConfigView.section.file.friendly.hashchecking.tooltip=Eine geringf\u00fcgig langsamere Methode der Kontrolle der Pr\u00fcfsumme von\nheruntergeladenen Teilen, die jedoch weniger CPU-/System-Last verursacht. ConfigView.section.tracker.seedretention=max. behaltene komplette Quellen pro Torrent [0: unbegrenzt] ConfigView.section.tracker.seedretention.info=Hinweis: Upload-Statistiken werden f\u00fcr nicht\nbehaltene komplette Quellen verloren ConfigView.section.tracker.port=Aktiviere Tracker auf HTTP-Port ConfigView.section.tracker.sslport=Aktiviere Tracker auf HTTPS-Port ConfigView.section.tracker.publicenable.info=Dies erm\u00f6glicht anderen Nutzern die Erstellung von Torrents, die diesen Tracker benutzen,\nohne dass man die Torrents selber verteilen oder ver\u00f6ffentlichen muss. Button.clear=L\u00f6schen MainWindow.IPs.tooltip=Letzte Aktualisierung der Filterliste: %1\nAnzahl der IP-Filter in der Liste - Anzahl geblockter/gebannter/schlechter IPs in dieser Sitzung.\nDoppelklicken f\u00fcr Details. ConfigView.section.ipfilter.list.banned=wurde gebannt ConfigView.section.ipfilter.list.baddata=hat falsche Daten gesendet: Vorf\u00e4lle = Button.reset=Zur\u00fccksetzen ConfigView.section.ipfilter.bannedinfo=IPs, die falsche Daten gesendet haben - geblockt nach Limit-\u00dcberschreitung ConfigView.section.ipfilter.blockedinfo=IPs, die aufgrund des IP-Filters geblockt wurden download.removerules.name=Entfernregeln download.removerules.unauthorised.info=Unautorisierte Torrents sind solche, bei denen die Ank\u00fcndigungantwort "not authoris(z)ed" oder "unauthoris(z)ed" in der Fehlermeldung enth\u00e4lt. download.removerules.unauthorised=Unautorisierte Torrents automatisch entfernen download.removerules.unauthorised.seedingonly=\tNur wenn verteilt wird download.removerules.removed.ok=Automatisches Entfernen des Torrents '%1' erfolgreich. Dies wurde durch die Entfernregeln verursacht. download.removerules.updatetorrents=Entferne Torrents von Vuze-Updates, wenn es der Schwarm ben\u00f6tigt ConfigView.label.defaultstarttorrentsstopped=Neue Torrents immer in angehaltenem Zustand hinzuf\u00fcgen ConfigView.section.server.enableudp=Aktiviere UDP-Tracker-Client-Protokoll upnp.mapping.dataportudp=UDP-Tracker-Client-Port ConfigView.section.file.decoder.showlax=Zeige unwahrscheinlichere Kodierungen ConfigView.section.file.decoder.showall=Ber\u00fccksichtige alle m\u00f6glichen Kodierungen MainWindow.status.updowndetails.tooltip=Upload-/Download-Geschwindigkeitsbegrenzungen\nRechtsklick zum \u00c4ndern\nDoppelklick, um die Statistiken zu \u00f6ffnen TrackerClient.announce.warningmessage=Tracker f\u00fcr '%1' lieferte Warnung '%2' ConfigView.section.tracker.natcheckenable=\u00dcberpr\u00fcfe Status eingehender Daten-Ports und benachrichtige bei Problemen die Quellen ConfigView.section.tracker.publishenabledetails=Ver\u00f6ffentliche Torrent-Details ConfigView.section.tracker.publishenablepeerdetails=Ver\u00f6ffentliche Quellendetails MyTrackerView.badnat=NAT fehlerhaft MyTrackerView.badnat.info=Quellen, bei denen ein NAT-Check fehlgeschlagen ist, wenn aktiviert ConfigView.section.tracker.natchecktimeout=Zeit\u00fcberschreitung der \u00dcberpr\u00fcfung (in s) ConfigView.section.file.perf.cache.enable=Disk-Cache aktivieren ConfigView.section.file.perf.cache.size=Cachegr\u00f6\u00dfe in %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u00dcbe&rtragungen MainWindow.menu.transfers.startalltransfers=Alle st&arten MainWindow.menu.transfers.stopalltransfers=Alle st&oppen MainWindow.menu.transfers.pausetransfers=&Pausieren MainWindow.menu.transfers.resumetransfers=&Fortsetzen ConfigView.label.experimental.osx.kernel.panic.fix=Experimenteller Fix f\u00fcr Kernelprobleme auf Dual-CPU OSX Systemen [Neustart ben\u00f6tigt] SystemTray.menu.pausetransfers=\u00dcbertragungen pausieren SystemTray.menu.resumetransfers=\u00dcbertragungen fortsetzen ConfigView.section.file.truncate.too.large=K\u00fcrze existierende Dateien, die zu gro\u00df sind ConfigView.section.file.perf.cache.trace=Verfolge Cache-Operationen zu Diagnosezwecken ConfigView.section.interface.enabletray=Aktiviere System-Tray [Neustart ben\u00f6tigt] PeerManager.status.error=Fehler Stats.title.full=Statistiken TransferStatsView.title.full=\u00dcbertragungen CacheView.general.size=Gesamtgr\u00f6\u00dfe CacheView.general.inUse=Benutzt CacheView.general.title=Cache-Info CacheView.reads.title=I/O Lesezugriffe CacheView.reads.fromFile=Aus Datei CacheView.reads.fromCache=Aus Cache CacheView.reads.hits=Treffer CacheView.writes.title=I/O Schreibzugriffe CacheView.writes.toCache=In Cache CacheView.writes.toFile=In Datei CacheView.writes.hits=Gespeichert CacheView.speeds.title=Datenraten CacheView.speeds.reads=Lesezugriffe CacheView.speeds.writes=Schreibzugriffe CacheView.speeds.fromCache=Aus/In Cache CacheView.speeds.fromFile=Aus/In Datei CacheView.reads.#=Anzahl CacheView.reads.amount=Menge CacheView.reads.avgsize=\u00d8 Gr\u00f6\u00dfe openUrl.referrer=Darauf verweisende Seiten-URL: openUrl.referrer.info=Nur erforderlich bei Webseiten, die den Referrer \u00fcberpr\u00fcfen ConfigView.label.maxuploadspeedseeding=Alternativer Wert, wenn nur noch verteilt wird ConfigView.label.transfer.ignorepeerports=Ignoriere Quellen mit folgenden Datenports\n(Ports mit Semikolon getrennt, Bereiche mit Bindestrich. Bsp: 1;25-43;70;72) ConfigView.section.proxy.enable_socks.peer=Aktiviere Proxy-Nutzung f\u00fcr Quellenkommunikation (nur ausgehende Verbindungen) [Neustart ben\u00f6tigt] ConfigView.section.proxy.peer.informtracker=Benachrichtige Tracker \u00fcber die Beschr\u00e4nkung ConfigView.section.proxy.socks.version=SOCKS Version PiecesView.legend.written=Geschrieben PiecesView.legend.requested=Angefordert PiecesView.legend.downloaded=Heruntergeladen, Schreiben steht bevor PiecesView.legend.incache=Daten sind im Cache PiecesView.typeItem.0=Langsam PiecesView.typeItem.1=Schnell PiecesView.type=Typ Security.jar.tools_not_found=JAR-Signierung fehlgeschlagen - 'tools.jar' nicht gefunden in %1. Siehe Tools->Optionen->Sicherheit f\u00fcr Details. Security.jar.signfail=JAR-Signierung fehlgeschlagen - %1 ConfigView.section.security.toolsinfo=Signierte JAR-Dateien werden zur Unterst\u00fctzung einiger Plugins benutzt, z.B. das Swing Web Interface (falls so konfiguriert).\nUm JAR-Dateien zu signieren ist es notwendig Zugriff auf die 'tools.jar' zu haben, die mit dem Sun JDK (nicht JRE) installiert\nwird. Sollte nur das JRE installiert sein, dann ist das JDK auch zu installieren. Vuze kann diese Datei normalerweise automatisch\nfinden. Sollte dies jedoch nicht funktionieren, kann der Pfad daf\u00fcr hier explizit angegeben werden. ConfigView.section.security.toolsdir=Verzeichnis, das die 'tools.jar' beinhaltet ConfigView.section.security.choosetoolssavedir=W\u00e4hle Verzeichnis, welches die 'tools.jar' beinhaltet authenticator.torrent=Torrent ConfigView.section.proxy.peer.same=Benutze gleiche Proxy-Einstellungen f\u00fcr Tracker- und Quellenkommunikation ConfigView.section.connection.network.max.simultaneous.connect.attempts=max. gleichzeitig ausgehende Verbindungsversuche ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Maximale Anzahl von neuen ausgehenden Verbindungen, die Vuze versuchen sollte, zu beliebiger Zeit aufzubauen.\nAchtung: WindowsXP Service Pack 2 (SP2) verh\u00e4ngt eine systemweite Begrenzung auf 10 gleichzeitige Verbindungsversuche.\nStandardwert ist 8. ConfigView.section.file.perf.cache.size.explain=Der Cache wird zur Reduzierung von Lese- und Schreibzugriffen auf die Festplatte benutzt.\nSofern nicht die Java-Option '-XX:MaxDirectMemorySize' benutzt wird, um den verf\u00fcgbaren\nSpeicher f\u00fcr Cache und Netzwerk-IO explizit festzulegen, sollten der Wert mindestens %1 \nunter der maximalen VM-Gr\u00f6\u00dfe gehalten werden. Das momentane Maximum der VM-Gr\u00f6\u00dfe\nist %2. F\u00fcr Anweisungen, wie dies zu \u00e4ndern ist, sieh unter 'MemoryUsage' im Wiki auf %3 nach. Falsche Einstellungen werden in 'out of memory' Fehlern resultieren. Mehr als 32 MB\nCache sind h\u00f6chstwahrscheinlich zu viel. MyTorrentsView.menu.setSpeed.unlimit=Kein Limit MyTorrentsView.menu.setSpeed.unlimited=Unbegrenzt MyTorrentsView.menu.setSpeed.disable=Deaktiviere Upload MyTorrentsView.menu.setSpeed.disabled=Deaktiviert MyTorrentsView.menu.setSpeed.in=in MyTorrentsView.menu.setSpeed.slots=slots von GeneralView.label.maxuploadspeed=Up-Limit GeneralView.label.maxuploadspeed.tooltip=max. Upload-Geschwindigkeit MyTorrents.items.UpSpeedLimit.disabled=Kein Upload MyTorrents.items.UpSpeedLimit.unlimited=Unbegrenzt TableColumn.header.maxupspeed=max. UL-Geschw. TableColumn.header.maxupspeed.info=Maximale Upload-Geschwindigkeit pro Torrent ConfigView.section.file.perf.cache.enable.write=Nutze Cache f\u00fcr Downloaddaten, um sowohl Schreibzugriffe, als auch Lesezugriffe, welche f\u00fcr die \u00dcberpr\u00fcfung der Teile ben\u00f6tigt werden, zu reduzieren. ConfigView.section.file.perf.cache.enable.read=Liest pr\u00e4ventiv Daten zur Reduzierung der Lesezugriffe beim Upload ConfigView.section.tracker.separatepeerids=Benutze unterschiedliche Quellenidentifikationen\nf\u00fcr Tracker- und Datenkommunikation ConfigView.section.tracker.separatepeerids.info=Erh\u00f6ht Anonymit\u00e4t, wenn herunterladen/verteilen anonym\nerfolgt, w\u00e4hrend eine nicht-anonyme Trackerverbindung benutzt wird ConfigView.section.interface.wavlocation=Ort der .wav-Datei ConfigView.section.interface.wavlocation.info=W\u00e4hle .wav-Datei oder leer lassen f\u00fcr Standardsound ConfigView.section.tracker.client.connecttimeout=Zeit\u00fcberschreitung f\u00fcr Verbindung (in s) ConfigView.section.tracker.client.readtimeout=Zeit\u00fcberschreitung f\u00fcr Lesen (in s) FilesView.path=Pfad FilesView.fullpath=Zeige vollst\u00e4ndigen Pfad FilesView.remaining=Verbleibende Teile TableColumn.header.trackername=Trackername TableColumn.header.trackername.info=Name des Tracker basierend auf der Ank\u00fcndigungs-URL ConfigView.group.override=Optionen \u00fcberschreiben ConfigView.section.file.perf.cache.notsmallerthan=Benutze den Cache nicht f\u00fcr Dateien kleiner als (in %1) PeersView.menu.blockupload=Blockiere Upload PeersView.menu.kickandban=Kicken und bannen PeersView.menu.kickandban.reason=Quelle manuell gebannt PeersView.state=Status PeersView.state.info=Verbindungsstatus PeersView.state.pending=Warte auf Daten PeersView.state.connecting=Verbinde PeersView.state.handshake=Warte auf Aushandlung PeersView.state.established=Verbindung hergestellt ConfigView.section.tracker.processinglimits=Bearbeitungsgrenzen ConfigView.section.tracker.maxgettime=max. Zeit f\u00fcr Verarbeitung von GET-Befehlen (in s) [0: unbegrenzt] ConfigView.section.tracker.maxgettime.info=Zeit, die f\u00fcr Announces and Scrapes benutzt wird ConfigView.section.tracker.maxposttimemultiplier=GET-Zeitmultiplikator f\u00fcr POST Processing [0: unbegrenzt] ConfigView.section.tracker.maxposttimemultiplier.info=Benutzt f\u00fcr Formular\u00fcbermittlungen und Uploads ConfigView.section.tracker.maxthreads=max. gleichzeitige Verbindungsanfragen DownloadManager.error.operationcancancelled=Vorgang abgebrochen Torrent.create.progress.cancelled=Vorgang abgebrochen sharing.progress.cancel=Abbrechen wizard.maketorrents.autoopen=\u00d6ffne den Torrent zur Verteilung, wenn fertig ConfigView.section.sharing.rescanenable=Aktiviere periodisches Durchsuchen von Shares auf \u00c4nderungen. ConfigView.section.sharing.rescanperiod=Durchsuchungsintervall in Sekunden ConfigView.section.connection.advanced=Erweiterte Einstellungen ConfigView.section.connection.advanced.mtu=Maximum Transmission Unit (MTU) der Verbindung ConfigView.section.connection.advanced.mtu.tooltip=Maximale Paketgr\u00f6\u00dfe, die in einem Frame \u00fcber das Netzwerk \u00fcbertragen werden kann.\nVuze benutzt MTU-40 (MSS) f\u00fcr die Optimierung der Upload Pakete.\nEmpfohlende Werte:\n 576 - Dial-up Verbindungen\n1492 - PPPoE Breitband Verbindungen\n1500 - Ethernet, DSL and Kabel Breitband Verbindungen ConfigView.section.connection.advanced.SO_RCVBUF=Socket SO_RCVBUF Gr\u00f6\u00dfe in Byte [0: nutzt Einstellung des Betriebssystems] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Sets the standard socket SO_RCVBUF value (in bytes), i.e. TCP receive window size and scale.\nVuze leaves this unset by default, meaning the defaults for the underlying OS are used.\nNOTE: Linux doubles the given value. ConfigView.section.connection.advanced.SO_SNDBUF=Socket SO_SNDBUF Gr\u00f6\u00dfe in Byte [0: nutzt Einstellung des Betriebssystems] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Sets the standard socket SO_SNDBUF value (in bytes), i.e. the TCP send window size.\nVuze leaves this unset by default, meaning the defaults for the underlying OS are used.\nNOTE: Linux doubles the given value. ConfigView.section.connection.advanced.IPDiffServ=DiffServ-Wert ausgehender Pakete (TOS-Feld) ConfigView.section.connection.advanced.IPDiffServ.tooltip=Setzt den DiffServ-Teil des Type-Of-Service (TOS) Feldes im IP-Header f\u00fcr ausgehende Pakete.\nHexadezimale Werte k\u00f6nnen mit dem Pr\u00e4fix '0x' eingegeben werden.\nVuze nutzt standardm\u00e4ssig die Einstellungen des Betriebssystems.\nACHTUNG: Die unterliegende Netzwerkimplementation kann diese Werte ignorieren, die Einstellung ist sehr stark abh\u00e4ngig vom benutzten Betriebssystem und der JAVA-Version. ConfigView.section.interface.confirm_torrent_removal=Zeige Best\u00e4tigungsdialog beim Entfernen eines Torrents ConfigView.section.interface.confirm_torrent_removal.tooltip=Verlangt eine Best\u00e4tigung beim Entfernen von Torrents aus 'Meine Torrents'. MyTorrentsView.confirm_torrent_removal=Soll der Torrent wirklich entfernt werden?\n TableColumn.header.seed_to_peer_ratio=Verh\u00e4ltnis vQ/uvQ TableColumn.header.seed_to_peer_ratio.info=Verh\u00e4ltnis der vollst\u00e4ndigen zu unvollst\u00e4ndigen Quellen des gesamten Schwarmes PeersView.connected_time=Verbunden seit PeersView.connected_time.info=Gesamtzeit verbunden mit unvollst\u00e4ndiger Quelle ConfigView.section.interface.display.add_torrents_silently=F\u00fcge Torrents unbemerkt hinzu ConfigView.section.interface.display.add_torrents_silently.tooltip=F\u00fcgt neue Downloads ohne Aktivierung des Vuze-Hauptfensters hinzu. TableColumn.header.maxdownspeed=max. DL-Geschw. TableColumn.header.maxdownspeed.info=Maximale Download-Geschwindigkeit pro Torrent PeersGraphicView.title=Schwarm ConfigView.section.tracker.passwordwebhttpsonly=Erlaube Zugriff nur \u00fcber HTTPS TableColumn.header.torrentpath=Torrentdatei TableColumn.header.torrentpath.info=Speicherort der Torrentdatei ConfigView.section.sharing.torrentcomment=Kommentar f\u00fcr erstellte Torrents ConfigView.label.copyanddeleteratherthanmove=Kopieren und anschlie\u00dfendes L\u00f6schen der Originaldaten anstelle von "Verschieben" - kann bei einigen Dateisystemen helfen, Datenverlust zu vermeiden. ConfigView.label.openstatsonstart=\u00d6ffne Statistiken beim Start swt.install.window.title=Vuze-Plugin installieren swt.install.window.ok=Installiere swt.install.window.header=Die folgenden Komponenten wurden zur Installation ausgew\u00e4hlt: swt.uninstall.window.title=Vuze-Plugin entfernen swt.uninstall.window.ok=Entferne swt.uninstall.window.header=Die folgenden Komponenten wurden zum Entfernen ausgew\u00e4hlt: installPluginsWizard.title=Installiere Plugins installPluginsWizard.mode.title=Bitte eine Installationsmethode w\u00e4hlen installPluginsWizard.mode.list=Pluginliste aus dem Internet laden und Plugin ausw\u00e4hlen installPluginsWizard.list.title=Liste der verf\u00fcgbaren Plugins installPluginsWizard.list.loading=Bitte warten, w\u00e4hrend das Plugin geladen wird. installPluginsWizard.list.loaded=Bitte die gew\u00fcnschten Plugins ausw\u00e4hlen. installPluginsWizard.list.name=Name installPluginsWizard.list.description=Beschreibung des Plugins installPluginsWizard.finish.title=Installation l\u00e4uft installPluginsWizard.finish.explanation=Das ausgew\u00e4hlte Plugin wird mit Hilfe des Update-Assistenten installiert.\n\nBitte habe etwas Geduld, dies kann eine Weile dauern.\n\nF\u00fcr einen Fortschrittsbericht bitte auf die linke Seite der Statusanzeige doppelklicken. installPluginsWizard.details.loading=Details werden geladen, bitte warten... installPluginsWizard.mode.file=lokale Plugin-Datei ausw\u00e4hlen installPluginsWizard.installMode.title=Bitte die Art der Installation w\u00e4hlen installPluginsWizard.installMode.user=Installiere das/die Plugin(s) nur f\u00fcr diesen Benutzer installPluginsWizard.installMode.shared=Installiere das/die Plugin(s) f\u00fcr alle Benutzer installPluginsWizard.file.title=Bitte w\u00e4hlen Sie ein Plugin f\u00fcr die Installation aus installPluginsWizard.file.file=Datei: installPluginsWizard.file.invalidfile=Die Datei ist kein Vuze-Plugin. installPluginsWizard.file.no_such_file=Es existiert keine Datei mit diesem Namen. installPluginsWizard.file.browse=Suchen... uninstallPluginsWizard.title=Deinstalliere Plugins uninstallPluginsWizard.list.title=Liste der installierten Plugins uninstallPluginsWizard.list.loaded=Bitte die Plugins ausw\u00e4hlen, die entfernt werden sollen. installPluginsWizard.list.nullversion=Keine Version uninstallPluginsWizard.finish.title=Deinstallation l\u00e4uft uninstallPluginsWizard.finish.explanation=Die ausgew\u00e4hlten Plugins werden durch den Update-Assistenten entfernt. MainWindow.menu.plugins.installPlugins=Plugins &installieren... MainWindow.menu.plugins.uninstallPlugins=Plugins &entfernen... ConfigView.section.ipfilter.totalIPs=%1 blockierte IPs gesamt, das sind %2 des Internets. update.instance.install=\u00dcberpr\u00fcfe Installation update.instance.uninstall=\u00dcberpr\u00fcfe Deinstallation update.instance.update=Suche nach Updates MainWindow.status.update.tooltip=Doppelklick f\u00fcr Fortschrittsinformationen updater.progress.window.title=Aktuelle Installationsvorg\u00e4nge updater.progress.window.info='Abbrechen' dr\u00fccken, um alle noch laufenden Prozesse zu beenden. Button.abort=Abbrechen ConfigView.section.ipfilter.enablebanning=Blockiere Quellen, die fortlaufend fehlerhafte Daten senden Network.alert.acceptfail=Es traten zu viele aufeinander folgende Fehler an Port %1 auf, %2 - Vorgang abgebrochen. Bitte die Einstellungen der Firewall f\u00fcr diesen Port \u00fcberpr\u00fcfen, um sicherzugehen, dass er f\u00fcr eingehende Verbindungen freigegeben ist. MyShares.column.category=Kategorie UpdateWindow.restartLater=Sp\u00e4ter neustarten MainWindow.menu.file.restart=Neustart MainWindow.dialog.restartconfirmation.title=Vuze neu starten? MainWindow.dialog.restartconfirmation.text=Soll Vuze wirklich neugestartet werden? deletetorrent.message1=Es wird der TORRENT gel\u00f6scht von:\n deletetorrent.message2=\nSoll wirklich fortgefahren werden? ConfigView.label.prioritizemostcompletedfiles=Weitere Priorisierung von Dateien hoher Priorit\u00e4t, in Abh\u00e4ngigkeit ihres Vollst\u00e4ndigkeitsgrades und der Dateigr\u00f6\u00dfe splash.plugin.init=Initialisiere Plugin: splash.plugin.UIinit=Initialisiere Plugin GUI: %1 ConfigView.section.style.osx_small_fonts=Benutze kleine Fonts [Neustart ben\u00f6tigt] ConfigView.section.tracker.tcpnonblocking=Benutze non-blocking I/O f\u00fcr TCP Trackerausf\u00fchrung. Um diese Options zu benutzen, muss Tracker Web auf einem anderen Port ausgef\u00fchrt werden. Experimentell! ConfigView.section.tracker.nonblocking=Non-blocking Einstellungen ConfigView.section.tracker.nonblockingconcmax=max. gleichzeitige Verbindungen [0: unbegrenzt] MyTorrentsView.menu.exportmenu=Exportiere ConfigView.section.tracker.client.scrapeinfo=Deaktivieren des Scrapens verhindert den Einsatz der Warteschlangenregeln, da\ndiese auf Informationen \u00fcber den Schwarm zur\u00fcckgreifen, die durch das Scrapen\nvon Trackern gewonnen werden. ConfigView.section.tracker.client.scrapeenable=Aktiviere Scraping ConfigView.section.tracker.client.scrapestoppedenable=Scrape Torrents, die nicht aktiv sind Scrape.status.disabled=Scrape deaktiviert MyTorrentsView.menu.explore=Zeige Datei MyTorrentsView.menu.explore._mac=Im Finder anzeigen MyTorrentsView.menu.explore._windows=Im Explorer anzeigen wizard.maketorrents.autohost=Hoste den Torrent auf dem internen Tracker ConfigView.label.overrideip=An Tracker gesendete IP-Adresse(n) \u00fcberschreiben. Mit Semikolon abgetrennt, falls\nmehrere f\u00fcr verschiedene Netzwerke angegeben werden. ConfigView.label.overrideip.tooltip=Benachrichtige den Tracker \u00fcber verschiedene IP-Adresse(n), von welcher/n ausgehende Datenpakete kommen. Leer lassen, wenn Option nicht benutzt werden soll. ConfigView.section.connection.group.networks=Netzwerke ConfigView.section.connection.group.networks.info=W\u00e4hle die standardm\u00e4\u00dfig zugelassenen Netzwerke f\u00fcr Daten\u00fcbertragung zwischen Quellen ConfigView.section.connection.networks.prompt=Auswahl aufrufen, wenn ein Download mit einem anonymen Tracker hinzugef\u00fcgt wird ConfigView.section.connection.networks.Public=\u00d6ffentliches IP-Netzwerk (nicht anonym) ConfigView.section.connection.networks.I2P=I2P Netzwerk ConfigView.section.connection.networks.Tor=The Onion Router (Tor) Netzwerk TableColumn.header.networks=Netzwerke TableColumn.header.networks.info=F\u00fcr Quellenkommunikation zugelassene Netzwerke Scrape.status.networkdisabled=Netzwerk nicht aktiviert ConfigView.section.tracker.server.group.networks=Netzwerke ConfigView.section.tracker.server.group.networks.info=W\u00e4hle die Netzwerke aus, f\u00fcr die der Tracker Quellen erlauben soll window.networkselection.title=Netzwerkauswahl window.networkselection.info=Das Torrent, das hierunter gezeigt wird, hat Tracker, die folgende Netzwerke unterst\u00fctzen.\nWenn es ein anonymer Tracker ist der \u00f6ffentliche Clients unterst\u00fctzt, aktiviere beides, anonyme und \u00f6ffentliche Netzwerke.\nDas aktivieren des \u00f6ffentlichen Netzwerk hat die offensichtliche Konsequens, dass die Anonymit\u00e4t aufgehoben wird! window.networkselection.description=Torrent: plugins.basicview.clear=l\u00f6schen ConfigView.section.connection.group.peersources=Ursprung der Quellen ConfigView.section.connection.group.peersources.info=W\u00e4hle die standardm\u00e4\u00dfig zugelassenen Urspr\u00fcnge f\u00fcr Verbindungen mit Quellen ConfigView.section.connection.peersource.Tracker=Von einem Tracker ConfigView.section.connection.peersource.DHT=Dezentralisiertes Tracken (DHT) ConfigView.section.connection.peersource.PeerExchange=Geliefert von anderer Quelle (PEX) ConfigView.section.connection.peersource.Plugin=Hinzugef\u00fcgt von einem Plugin ConfigView.section.connection.peersource.Incoming=Eingehende Verbindung PeersView.source=Ursprung PeersView.source.info=Der Ursprung dieser Quelle TableColumn.header.peersources=Urspr\u00fcnge der Quellen TableColumn.header.peersources.info=Urspr\u00fcnge der Quellen, die f\u00fcr den Aufbau von Quellenverbindungen erlaubt sind wizard.tracker.dht=Dezentralisiert (NUR Vuze-Clients) MyTorrentsView.menu.advancedmenu=Erweitert MyTorrentsView.menu.networks=Netzwerke MyTorrentsView.menu.peersource=Ursprung der Quellen ConfigView.section.sharing.permitdht=Erlaube dezentralisiertes Tracken, wenn der Tracker nicht verf\u00fcgbar ist ConfigView.section.sharing.protocol=Protokoll f\u00fcr verteilte Ressourcen PeersView.Messaging=Nachrichten PeersView.Messaging.info=Unterst\u00fctzt erweiterte Nachrichten-Schnittstelle ConfigView.label.queue.newseedsmovetop=Verschiebe neu fertig gewordene Torrents an den Anfang der Verteilliste ConfigView.label.seeding.firstPriority.ignore.info=Bedenke, dass die Benutzung dieser Regeln darin resultieren kann, dass ein Torrent direkt nach dem Download gestoppt wird. ConfigView.label.seeding.firstPriority.ignore=Ignoriere die oben genannten Regeln f\u00fcr Oberste Priorit\u00e4t, f\u00fcr: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents mit einem Verh\u00e4ltinis von vollst\u00e4ndigen zu unvollst\u00e4ndigen Quellen von ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents mit keinen unvollst\u00e4ndigen Quellen ConfigView.section.tracker.sendjavaversionandos=Sende Java-Version und Name des Betriebssystems MagnetPlugin.contextmenu.exporturi=Kopiere Magnet-URI in die Zwischenablage ConfigView.section.plugins.dht=Verteilte Datenbank dht.info=Dieses Plugin unterst\u00fctzt dezentralisiertes Tracken. Wenn es deaktiviert\nwird, schr\u00e4nkt das die M\u00f6glichkeiten zum Herunterladen von Torrents ein.\n dht.enabled=Aktiviere die verteilte Datenbank (DHT) dht.portdefault=Standardport benutzen dht.port=UDP-Port f\u00fcr die verteilte Datenbank dht.execute.command=Diagnosebefehl dht.execute.info=Dr\u00fccken, um den Befehl auszuf\u00fchren dht.execute=Ausf\u00fchren dht.logging=Aktiviere Verfolgung aller Aktivit\u00e4ten ConfigView.section.plugins.dhttracker=Verteilter Tracker dhttracker.tracknormalwhenoffline=Normale Torrents nur dann mit dem verteilten Tracker verwalten, wenn ihr eigener Tracker nicht erreichbar ist ConfigView.section.file.nativedelete._mac=Den Papierkorb beim L\u00f6schen von Dateien verwenden ConfigView.section.file.nativedelete._windows=Gel\u00f6schte Dateien in den Papierkorb verschieben ConfigView.section.logging.generatediagnostics=Erzeugen ConfigView.section.logging.netinfo=Generiere Netzwerk-Info ConfigView.section.logging.statsinfo=Generiere Statistik-Info ConfigView.section.logging.generatediagnostics.info=Diagnoseinformationen erzeugen und in die Zwischenablage sowie, sofern konfiguriert,\ndie Protokolldatei kopieren ConfigView.section.sharing.privatetorrent=Privater Torrent - nur Quellen vom Tracker annehmen MainWindow.menu.tools.nattest=&NAT-/Firewall-Test Button.apply=\u00dcbernehmen Button.close=Schlie\u00dfen window.welcome.title=Willkommen zu Vuze %1 #file can be a URL or a path in the jar window.welcome.file=whatsnew.german.stf MainWindow.menu.help.releasenotes=&Versionshinweise dht.reseed.label=Normalerweise ist eine erneute Einwahl in die verteilten Datenbank nicht notwendig. Wenn jedoch die Anzahl\nder Kontakte sehr niedrig ist, kann dies f\u00fcr eine Reintegration genutzt werden. Textfeld leer lassen, um bei\nden verbundenen Quellen zu starten oder IP-Adresse und Port eintragen, um den Vorgang explizit von einer\nbekannten Quelle zu starten. dht.reseed.group=Starte die verteilte Datenbank dht.reseed.ip=IP-Adresse dht.reseed=Start dht.reseed.info=Starte die verteilte Datenbank dht.diagnostics.group=Diagnose DHTView.title.full=Verteilte Datenbank DHTView.title.fullcvs=Verteilte Datenbank (CVS) DHTView.general.title=Allgemein DHTView.general.uptime=Laufzeit: DHTView.general.users=Benutzer: DHTView.general.nodes=Knoten: DHTView.general.leaves=Bl\u00e4tter: DHTView.general.contacts=Kontakte: DHTView.general.replacements=Ersetzungen: DHTView.general.live=Lebend: DHTView.general.unknown=Unbekannt: DHTView.general.dying=Sterbend: DHTView.transport.title=Transportdetails DHTView.transport.packets=Pakete DHTView.transport.received=Empfangen DHTView.transport.sent=Gesendet DHTView.transport.in=Eingehender Datenverkehr: DHTView.transport.out=Ausgehender Datenverkehr: DHTView.operations.title=Vorg\u00e4nge DHTView.operations.sent=Gesendet DHTView.operations.failed=Fehlgeschlagen DHTView.operations.received=Empfangen DHTView.operations.findNode=Finde Knoten DHTView.operations.findValue=Finde Wert DHTView.operations.store=Speichern DHTView.activity.title=Aktivit\u00e4ten DHTView.activity.status.true=Wartend DHTView.activity.status.false=Wird ausgef\u00fchrt DHTView.activity.type=Typ DHTView.activity.type.1=Internes Lesen DHTView.activity.type.2=Externes Lesen DHTView.activity.type.3=Internes Schreiben DHTView.activity.type.4=Externes Schreiben DHTView.activity.target=Ziel DHTView.db.title=Datenbank DHTView.db.keys=Schl\u00fcssel DHTView.db.values=Werte DHTView.db.local=Lokal DHTView.db.direct=Direkt DHTView.db.indirect=Indirekt MainWindow.dht.status.tooltip=Wenn die verteilte Datenbank aktiviert ist, wird\nhier die ungef\u00e4hre Anzahl der Benutzer gezeigt,\ndie gerade online sind. MainWindow.dht.status.disabled=DHT deaktiviert MainWindow.dht.status.failed=DHT fehlgeschlagen MainWindow.dht.status.initializing=DHT wird initialisiert... MainWindow.dht.status.users=%1 Benutzer MainWindow.dht.status.unreachable=DHT nicht erreichbar MainWindow.dht.status.unreachabletooltip=Es konnte keine Verbindung zur verteilten Datenbank aufgebaut werden. Sicherstellen, dass der\neingehende UDP-Port vom Internet aus erreichbar ist. (Router-/Firewalleinstellungen pr\u00fcfen) MyTorrentsView.menu.setUpSpeed=Setze UL-Geschw. MyTorrentsView.menu.setDownSpeed=Setze DL-Geschw. ConfigView.section.tracker.client.showwarnings=Zeige Warnmeldungen von Trackern dht.advanced=Erweiterte Einstellungen aktivieren dht.advanced.group=Erweiterte Einstellungen dht.advanced.label=Diese Werte nur \u00e4ndern, wenn man wirklich wei\u00df, was man tut. dht.override.ip=Nach au\u00dfen sichtbare IP-Adresse \u00fcberschreiben ConfigView.section.logging.loggerenable=Aktiviere Protokollierung ConfigView.section.ipfilter.blockbanning=256er-Adressblock bannen, wenn mindestens so viele IPs aus diesem Block gebannt worden sind MyTrackerView.passive=Passiv TableColumn.header.swarm_average_speed=\u00d8 Schwarmgeschw. TableColumn.header.swarm_average_speed.info=Durchschnittliche Geschwindigkeit aller Quellen des Schwarmes. TableColumn.header.comment=Kommentar TableColumn.header.comment.info=Benutzerdefinierter Kommentar f\u00fcr den Download TableColumn.header.commenticon=Kommentarsymbol TableColumn.header.commenticon.info=Zeigt ein Symbol, wenn der Download einen benutzerdefinierten Kommentar besitzt. MyTrackerView.category=Kategorie MainWindow.menu.file.open.torrentfortracking=Torrent-Datei... (nur T&racken) MyTrackerView.date_added=Hinzugef\u00fcgt ConfigView.section.tracker.portbackup=Backup-Ports (getrennt durch Semikolon) ConfigView.label.playfilespeech=Sprachausgabe, wenn eine Datei eines Torrents fertig ist ConfigView.label.playfilespeech.info=Die Sprachausgabe funktioniert im Moment am besten auf Englisch ConfigView.label.playfilefinished=Sound spielen, wenn eine Datei eines Torrents fertig ist ConfigView.label.backupconfigfiles=Sicherheitskopien der Konfigurationsdateien erstellen ConfigView.section.tracker.client.scrapesingleonly=Deaktiviere die Ansammlung von Scrape-Informationen pro Tracker (kann bei\nTrackern helfen, die 'URL too long' (414) Fehler melden) dht.ipfilter.log=Protokolliere Treffer des IP-Filters ConfigView.label.seeding.addForSeedingDLCopyCount=Nehme an, 'zum Verteilen' gestartete Torrents wurden zuvor so oft heruntergeladen ActivityView.legend.limit=Geschwindigkeitsbegrenzung ActivityView.legend.achieved=Erreichte Geschwindigkeit ActivityView.legend.overhead=Protokolldaten ActivityView.legend.peeraverage=Durchschnitt ActivityView.legend.swarmaverage=Schwarmdurchschnitt ActivityView.legend.trimmed=abgeschnitten (gepunktet) MyTorrentsView.menu.movemenu=Verschiebe Dateien MyTorrentsView.menu.movedata=Verschiebe Daten... MyTorrentsView.menu.movetorrent=Verschiebe Torrent-Datei... MyTorrentsView.menu.movedata.dialog=W\u00e4hle neues Ziel DHTView.operations.data=Daten DHTView.general.reachable=Erreichbar: ConfigView.label.queue.maxactivetorrentswhenseeding=Alternativer Wert, wenn nur noch verteilt wird Views.plugins.IRC.title=IRC - Online-Hilfe Formats.units.KB=kB Formats.units.alot=Viel! ConfigView.section.ipfilter.persistblocking=Blockierte IPs dauerhaft speichern FilesView.menu.rename=Umbenennen oder Verschieben FilesView.menu.rename_only=Umbenennen FilesView.menu.retarget=Verschieben FilesView.rename.choose.path=Neue oder vorhandene Datei w\u00e4hlen FilesView.rename.choose.path.dir=W\u00e4hle ein neues oder existierendes Verzeichnis FilesView.rename.confirm.delete.title=L\u00f6schen best\u00e4tigen FilesView.rename.confirm.delete.text=Das L\u00f6schen von '%1' best\u00e4tigen FilesView.rename.filename.title=Benenne Datei um FilesView.rename.filename.text=W\u00e4hle einen neuen Namen f\u00fcr die Datei ConfigView.higher.mode.available=Weitere Optionen gibt es in h\u00f6heren Nutzer-Modi ConfigView.section.mode=Modus ConfigView.section.mode.title=Erfahrungsstufe ConfigView.section.mode.beginner=Anf\u00e4nger ConfigView.section.mode.beginner.wiki.definitions=BitTorrent Vokabular ConfigView.section.mode.intermediate=Fortgeschritten ConfigView.section.mode.intermediate.wiki.host=Dateien hosten ConfigView.section.mode.intermediate.wiki.publish=Dateien ver\u00f6ffentlichen ConfigView.section.mode.advanced=Experte ConfigView.section.mode.advanced.wiki.main=Wiki Hauptseite ConfigView.section.mode.beginner.text=Alles was man zum runterladen ben\u00f6tigt.\nDiesen Modus benutzen, wenn die Verwaltung von Torrents alles ist, wozu Vuze benutzt werden soll. ConfigView.section.mode.intermediate.text=Zugriff auf die Tracker-Funktionen\nDiesen Modus benutzen, wenn ein eigener Tracker betrieben und Dateien dar\u00fcber verteilt werden sollen. ConfigView.section.mode.advanced.text=Zugriff auf die Netzwerkeinstellungen\nDiesen Modus nur benutzen, wenn klar ist, was MTU und non blocking IO bedeuten. Files.column.storagetype=Speicherart Files.column.fileext=Typ FileItem.storage.linear=linear FileItem.storage.compact=kompakt MessageBoxWindow.rememberdecision=Entscheidung merken ConfigView.section.interface.cleardecisions=L\u00f6sche gespeicherte Dialogentscheidungen ConfigView.section.interface.cleardecisionsbutton=L\u00f6schen ConfigView.section.interface.cleartrackers=L\u00f6sche gespeicherte Tracker ConfigView.section.interface.cleartrackersbutton=L\u00f6schen ConfigView.section.interface.clearsavepaths=L\u00f6sche gespeicherte Pfade ConfigView.section.interface.clearsavepathsbutton=L\u00f6schen configureWizard.welcome.usermodes=Die Einstellung der Erfahrungsstufe entscheidet dar\u00fcber, welche Optionen unter Tools -> Konfiguration ver\u00e4ndert werden k\u00f6nnen. Diese Option sollte aus eigenem Interesse korrekt eingestellt werden. FilesView.skip.confirm.delete.text=Datei '%1' l\u00f6schen, um Platz zu sparen? FilesView.rename.failed.title=Umbenennen/Verschieben fehlgeschlagen FilesView.rename.failed.text=Operation fehlgeschlagen, vermutlich aufgrund einer falschen Zielangabe diagnostics.log_found=Vuze wurde nicht korrekt beendet. \u00dcberpr\u00fcfe die Diagnose-Logdateien. Suche auch in der Wiki nach 'Vuze Disappears'. ManagerItem.paused=Pausiert Utils.link.visit=Weitere Informationen ConfigView.section.connection.serverport.wiki=Gute Ports installPluginsWizard.installMode.info.title=Information installPluginsWizard.installMode.info.text=Plugins sind nicht notwendig, damit Vuze korrekt arbeitet. Sie erg\u00e4nzen es nur um informative,\nautomatisierende Features oder Fernwartungsm\u00f6glichkeiten.Beachte also die Beschreibungen der\nPlugins, bevor sich entscheiden wird, ob eins installiert werden soll. Die meisten kann man ohne\nProbleme ausprobieren. Aber es ist besser, Vuze nicht mit ungenutzten Plugins zu \u00fcberladen. Views.plugins.Distributed.DB.title=Verteilte Datenbank Views.plugins.Distributed.Tracker.title=Verteilter Tracker Views.plugins.Plugin.Update.title=Plugin-Aktualisierung openUrl.url.info=Unterst\u00fctzt http-, https-, magnet- und hexadezimale Infohash-Angaben TableColumn.header.swarm_average_completion=\u00d8 Fortschritt TableColumn.header.swarm_average_completion.info=Durchschnittlicher Fortschritt aller Quellen des Schwarmes. GeneralView.label.swarm_average_completion=Durchschnittlicher Fortschritt: GeneralView.label.swarm_average_completion.tooltip=Der durchschnittliche Fortschritt der unvollst\u00e4ndigen Quellen im Schwarm MainWindow.nat.status.tooltip.unknown=NAT-Status unbekannt MainWindow.nat.status.tooltip.ok=NAT-Status OK. Eingehende und ausgehende Verbindungen sind vorhanden. MainWindow.nat.status.tooltip.probok=NAT-Status war OK, jedoch gibt es im Moment keine eingehenden Verbindungen. MainWindow.nat.status.bad=NAT-Problem! MainWindow.nat.status.tooltip.bad=M\u00f6gliches NAT-Problem! Keine eingehenden Datenverbindungen \u00fcber den TCP-Port\nvorhanden. Bitte im Wiki nachlesen, wenn das Problem weiterhin besteht. plugin.installer.recommended.plugin=Empfohlenes Plugin - bitte genauer ansehen und wenn n\u00f6tig installieren LoggerView.pause=Pausiere Protokollierung LoggerView.clear=L\u00f6sche Bildschirm LoggerView.filter.uncheckAll=Markiere keine Kategorie LoggerView.filter.checkAll=Markiere alle Kategorien LoggerView.loggingDisabled=Protokollierung ist nicht aktiviert. LoggerView.includeOnly=Zeige nur Zeilen, die dem regul\u00e4rem Ausdruck entsprechen: LoggerView.excludeAll=Zeige keine Zeilen, die dem regul\u00e4ren Ausdruck entsprechen: ConfigView.section.logging.log0type=Informations- ConfigView.section.logging.log1type=Warnungs- ConfigView.section.logging.log2type=Fehler- ConfigView.section.logging.filter=Filter f\u00fcr Protokollierung in Datei ConfigView.section.logging.level=Protokoll ConfigView.section.logging.showLogsFor=Zeige %1 Protokolle f\u00fcr die folgenden Kategorien: ConfigView.pluginlist.column.loadAtStartup=Beim Start laden ConfigView.pluginlist.column.type=Typ ConfigView.pluginlist.column.type.perUser=F\u00fcr diesen Benutzer ConfigView.pluginlist.column.type.shared=F\u00fcr alle Benutzer ConfigView.pluginlist.column.type.builtIn=Fest eingebaut ConfigView.pluginlist.column.directory=Verzeichnis ConfigView.pluginlist.column.isOperational=Einsatzbereit? PeersView.BlockView.Avail.Have=Haben beide PeersView.BlockView.Avail.NoHave=Hat Quelle, man selber nicht PeersView.BlockView.NoAvail.Have=Hat man selber, Quelle nicht PeersView.BlockView.NoAvail.NoHave=Hat keiner PeersView.BlockView.Transfer=Wird \u00fcbertragen PeersView.BlockView.NextRequest=N\u00e4chste Anfrage PeersView.BlockView.title=\u00dcbersicht der Teile PeersView.BlockView.AvailCount=Verf\u00fcgbarkeitsz\u00e4hler MyTorrentsView.dialog.NumberError.title=Ung\u00fcltige oder unbekannte Nummer MyTorrentsView.dialog.NumberError.text=Die Nummber, die eingegeben wurde, ist ung\u00fcltig oder unbekannt. MyTorrentsView.menu.manual=Manuell... MyTorrentsView.menu.manual.per_torrent=Manuell (pro Torrent) MyTorrentsView.menu.manual.shared_torrents=Manuell (f\u00fcr mehrere Torrents) MyTorrentsView.dialog.setSpeed.title=Geschwindigkeitsbegrenzung %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Begrenze die %2-Geschwindigkeit auf: MyTorrentsView.dialog.setNumber.upload=Upload MyTorrentsView.dialog.setNumber.download=Download OpenTorrentWindow.torrentLocation=Torrent-Dateien: OpenTorrentWindow.addFiles.URL=Hinzuf\u00fcgen von URL OpenTorrentWindow.addFiles.Folder=Hinzuf\u00fcgen aus Verzeichnis OpenTorrentWindow.addFiles.Clipboard=Hinzuf\u00fcgen aus Zwischenablage OpenTorrentWindow.changeDestination=\u00c4ndere Ziel OpenTorrentWindow.fileList=Dateien in Torrents: OpenTorrentWindow.torrentTable.saveLocation=Speicherort OpenTorrentWindow.fileTable.fileName=Dateiname OpenTorrentWindow.fileTable.size=Gr\u00f6\u00dfe OpenTorrentWindow.fileTable.destinationName=Zielname OpenTorrentWindow.startMode.seeding=Verteilen OpenTorrentWindow.fileList.changeDestination=\u00c4ndere Ziel OpenTorrentWindow.mb.badSize.title=Inkompatibele Datei OpenTorrentWindow.mb.badSize.text='%1' ist nicht '%2' und kann nicht zum Verteilen benutzt werden OpenTorrentWindow.mb.alreadyExists.text=%3 wurde bereits hinzugef\u00fcgt als '%2' OpenTorrentWindow.mb.alreadyExists.default.name=Medien OpenTorrentWindow.mb.alreadyExists.title=Torrent existiert bereits OpenTorrentWindow.mb.openError.title=Fehler beim \u00d6ffnen OpenTorrentWindow.mb.openError.text='%1' konnte nicht ge\u00f6ffnet werden:\n%2 OpenTorrentWindow.torrent.remove=Entferne Torrent aus der Liste OpenTorrentWindow.torrent.options=Die folgenden Einstellungen werden auf die oben markierten Torrents angewandt. OpenTorrentWindow.xOfTotal=(%1 von %2) iconBar.open.tooltip=\u00d6ffne Torrent(s) LocaleUtil.column.text=Unbekannter Text Tracker.tooltip.MultiSupport=Dieser Tracker unterst\u00fctzt mehrere Hash-Scrapes pro Anfrage. Tracker.tooltip.NoMultiSupport=Dieser Tracker unterst\u00fctzt nicht mehrere Hash-Scrapes pro Anfrage. ConfigView.label.lazybitfield=Benutze 'lazy bitfield' (hilft beim Seeden in Netzwerken, die bitfield-basierendes Blocken anwenden) LoggerView.realtime=Aktualisiere in Echtzeit ConfigView.section.file.perf.cache.flushpieces=Schreibe fertige Teile sofort. Dies macht den Festplattenzugriff fl\u00fcssiger, kann aber mehr Schreiboperationen zur Folge haben. ConfigView.section.file.writemblimit=Max. Speicher f\u00fcr gepufferte Schreibanfragen (in %1) ConfigView.section.file.writemblimit.explain=Wenn die Schreibgeschwindigkeit geringer als die Download-Geschwindigkeit ist, gibt dieser Parameter\nan, wie viele Daten zwischengelagert werden, bevor die Downloadgeschwindigkeit reduziert wird. ConfigView.section.file.readmblimit=Max. Speicher f\u00fcr gepufferte Leseanfragen (in %1) ConfigView.section.file.readmblimit.explain=Dieser Parameter gibt an, wie viel Speicher f\u00fcr noch anstehende Lesezugriffe reserviert wird. Button.moveUp=Verschiebe hoch Button.moveDown=Verschiebe runter ConfigView.notAvailableForMode=Dieser Abschnitt ist f\u00fcr den Modus %1 oder h\u00f6her gedacht. Er ist nicht verf\u00fcgbar in Modus %2 . health.explain.error=Bei dem Torrent ist ein Fehler aufgetreten. Schaue in das Statusfeld\noder auf den Tooltip des Icons f\u00fcr eine Fehlerbeschreibung. PeersView.piece=Teil PeersView.piece.info=Nummer des letzten Teiles, was von dieser Quelle angefordert wurde PiecesView.priority=Priorit\u00e4t PiecesView.priority.info=Priorit\u00e4t der Fertigstellung dieses Teiles. Nicht viel Beachtung schenken. PiecesView.speed=Geschwindigkeit PiecesView.speed.info=Langsame Quellen werden daran gehindert schnelle Downloads von Teilen zu st\u00f6ren TableColumn.header.AvgAvail.info=Summe der Verf\u00fcgbarkeit aller Teile geteilt durch die Anzahl der Teile und durch die Anzahl der Verbindungen TableColumn.header.AvgAvail=\u00d8 Verf\u00fcgb./Teil ConfigView.label.strictfilelocking=Erzwinge exklusives Sperren von Dateischreibzugriff zwischen Torrents MyTorrentsView.menu.checkfilesexist=\u00dcberpr\u00fcfe, ob Dateien existieren MyTorrentsView.menu.rescanfile=\u00dcberpr\u00fcfe unfertige Teile periodisch MyTorrentsView.menu.clear_resume_data=L\u00f6sche Fortsetzungsdaten Plugin.extseed.name=Externe vollst\u00e4ndige Quellen Plugin.localtracker.name=LAN-Peer-Finder Plugin.localtracker.info=Der LAN-Peer-Finder erlaubt mehreren Kopien von Vuze hinter einer Firewall\nund in einem gemeinsamen Netzwerk, effizient Torrents herunterzuladen, indem\ner direkte Verbindungen zwischen ihnen aufbaut. Plugin.localtracker.enable=Aktiviere LAN-Peer-Finder azinstancehandler.alert.portclash=Portkollision im LAN entdeckt: %1 wird schon von einem anderen Nutzer verwendet. W\u00e4hle neue zuf\u00e4llige Ports f\u00fcr eingehende TCP- und UDP-Verbindungen [zwischen %2 und %3]. ConfigView.section.transfer.lan.tooltip=Spezifische Einstellungen f\u00fcr LAN ConfigView.section.transfer.lan.uploadrate=kB/s LAN max. Upload-Geschwindigkeit [0: unbegrenzt] ConfigView.section.transfer.lan.uploadrate.tooltip=Quellenverbindungen innerhalb des selben LANs haben eine\nseparate Begrenzung der Upload-Geschwindigkeit. ConfigView.section.transfer.lan.downloadrate=kB/s LAN max. Download-Geschwindigkeit [0: unbegrenzt] ConfigView.section.transfer.lan.downloadrate.tooltip=Quellenverbindungen innerhalb des selben LANs haben eine\nseparate Begrenzung der Download-Geschwindigkeit. TorrentOptionsView.title.short=Optionen TorrentOptionsView.title.full=Optionen TorrentOptionsView.param.max.peers=Max.Verbindungszahl [0: unbegrenzt] ConfigView.section.connection.encryption.require_encrypted_transport=Ben\u00f6tige verschl\u00fcsselten Transport ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Erzwinge die Nutzung verschl\u00fcsselter Verbindungen mit anderen Quellen. ConfigView.section.connection.encryption.min_encryption_level=Minimale Verschl\u00fcsselungsstufe ConfigView.section.connection.encryption.min_encryption_level.tooltip=Plain - nur Aushandlung\nRC4 - kompletter Datenstrom\nBessere Verschl\u00fcsselung ben\u00f6tigt mehr Rechenleistung. Peers.column.Encryption=Verschl\u00fcsselung Peers.column.Encryption.info=Stufe der benutzten Verschl\u00fcsselung ConfigView.section.connection.encryption.encrypt.info=Bei aktivierter Verschl\u00fcsselung sind keine Verbindungen mehr zu inkompatibelen BitTorrent-Programmen\nm\u00f6glich. Es sei denn, es wurden R\u00fcckfalloptionen konfiguriert. ConfigView.section.connection.encryption.encrypt.info.link=F\u00fcr Details bitte hier schauen MainWindow.sr.status.tooltip.ok=Verh\u00e4ltnis von %1 ist OK! MainWindow.sr.status.tooltip.poor=Verh\u00e4ltnis von %1 k\u00f6nnte besser sein: < 0.9 MainWindow.sr.status.tooltip.bad=Verh\u00e4ltnis von %1 ist schlecht: < 0.5 ConfigView.section.style.status=In Statuszeile zeige: ConfigView.section.style.status.show_sr=Verh\u00e4ltnis ConfigView.section.style.status.show_nat=NAT ConfigView.section.style.status.show_ddb=Verteilte Datenbank (DHT) ConfigView.section.style.status.show_ipf=IPFilter-Status ConfigView.section.connection.encryption.encrypt.group=Transportverschl\u00fcsselung/-verschleierung ConfigView.section.connection.encryption.encrypt.fallback_info=Aktivieren von R\u00fcckfalloptionen erlaubt Verbindungen mit inkompatibelen BitTorrent-Programmen,\nwas jedoch in unverschl\u00fcsselten Verbindungen resultiert. ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Erlaube unverschl\u00fcsselte ausgehende Verbindungen, wenn der verschl\u00fcsselte Verbindungsaufbau fehlschl\u00e4gt ConfigView.section.connection.encryption.encrypt.fallback_incoming=Erlaube unverschl\u00fcsselte eingehende Verbindungen ConfigView.section.connection.encryption=Transportverschl\u00fcsselung upnp.selectedinterfaces=W\u00e4hle Ger\u00e4te (mit Semikolon getrennt, z.B. eth0;eth1) [leer: alle] ConfigView.section.style.defaultSortOrder=Standardsortierreihenfolge ConfigView.section.style.defaultSortOrder.desc=Absteigend ConfigView.section.style.defaultSortOrder.asc=Aufsteigend ConfigView.section.style.defaultSortOrder.flip=Entgegen der vorherigen Sortierung LoggerView.autoscroll=Auto-Scrollen Button.selectAll=Alles ausw\u00e4hlen Button.markSelected=Ausw\u00e4hlen Button.unmarkSelected=Auswahl aufheben plugins.basicview.config=Konfiguration TorrentOptionsView.param.max.uploads=Max.Uploadslots [minimum: 2] MyTorrentsView.dialog.setPosition.title=Neue Position MyTorrentsView.dialog.setPosition.text=Gebe die neue Position der markierten Torrents an: MyTorrentsView.menu.reposition.manual=Neue Position... ConfigView.section.connection.advanced.info.link=F\u00fcr Details bitte hier schauen ConfigView.section.connection.advanced.socket.group=Socket-Einstellungen ConfigView.section.connection.advanced.bind_port=An lokalen Port binden [0: deaktiviert] ConfigView.section.connection.advanced.bind_port.tooltip=Ausgehende Socket-Verbindungen werden lokal an den angegebenen Port gebunden.\nAktiviert, k\u00f6nnte diese Funktion bei instabilen Routern helfen. ConfigView.section.proxy.group.tracker=Tracker-Kommunikation ConfigView.section.proxy.group.peer=Quellenkommunikation Pieces.column.Requested=Angefordert Pieces.column.Requested.info=Zeigt, ob mehr Anfragen nach diesem Teil gemacht werden k\u00f6nnen oder nicht (*) ConfigView.label.maxuploadsseeding=Alternativer Wert, wenn nur noch verteilt wird popup.error.hideall=Alle Ausblenden ConfigView.section.style.dataStatsOnly=Zeige nur Datenstatistiken (Protokollstatistiken werden versteckt) ConfigView.section.style.separateProtDataStats=Zeige getrennte Daten- und Protokollstatistiken als 'Daten (Protokoll)' MyTorrentsView.dialog.setFilter.title=Durchsuche Liste nach... MyTorrentsView.dialog.setFilter.text=Der Bereich f\u00fcr %1 wird nach dem unten eingegebenen Text durchsucht. Benutze das Pipe-Symbol "|", um mehrere Filterbegriffe anzugeben. MyTorrentsView.filter.tooltip=Dr\u00fccke Ctrl+X, um zwischen Regul\u00e4ren Ausdr\u00fccken und normalem Suchmodus umzuschalten. Benutze das Pipe-Symbol "|", um mehrere Filterbegriffe anzugeben. MyTorrentsView.clearFilter.tooltip=L\u00f6sche Filter MyTorrentsView.menu.filter=Durchsuche Liste nach... ConfigView.section.file.resume.recheck.all=\u00dcberpr\u00fcfe erneut alle fertigen Teile nach einem Absturz (sonst werden nur die Teile \u00fcberpr\u00fcft, die beim letzten Speichern aktiv waren) ConfigureWizard.language.choose=Bitte eine Sprache ausw\u00e4hlen: popup.closing.in=Fenster schlie\u00dft in %1 Sekunden popup.more.waiting=%1 weitere Meldung(en)... # > 2402 popup.download.finished="%1" wurde heruntergeladen. popup.file.finished="%1" wurde heruntergeladen. Plugin.localtracker.autoadd.info=F\u00fcge automatisch diese lokalen Quellen hinzu [mit Semikolon getrennt] Plugin.localtracker.autoadd=Ausdr\u00fccklich diese Quellen Plugin.localtracker.networks.info=Betrachte die folgenden Netzwerke als lokal [mit Semikolon getrennt, z.B. 145.227.*.*] Plugin.localtracker.networks=Lokale Netzwerke MainWindow.menu.view.plugins.logViews=Protokolle anschauen SpeedView.stats.autospeed=Automatische Upload-Geschwindigkeit SpeedView.stats.autospeed.disabled=Diese Funktion ist entweder deaktiviert (die verteilte Datenbank muss aktiviert sein (DHT)) oder ist nicht in Benutzung (Upload-Geschwindigkeit manuell eingestellt) SpeedView.stats.idlePing=Leerlaufping: SpeedView.stats.maxPing=Max. Ping: SpeedView.stats.currentPing=Ping momentan: SpeedView.stats.maxUp=max. UL-Geschw. ConfigView.pluginlist.unloadSelected=Gew\u00e4hltes Plugin deaktivieren ConfigView.pluginlist.scan=Suche nach neuen Plugins ConfigView.section.transfer.autospeed.tooltip=Spezifische Einstellungen f\u00fcr Auto-Speed ConfigView.section.transfer.autospeed.info=Auto-Speed passt automatisch die Upload-Geschwindigkeit an, um eine \u00dcberlastung der Netzwerkverbindung zu verhindern.\n\nDiese Begrenzungen werden nur angewandt, wenn die automatische Upload-Geschwindigkeit aktiviert ist. Auch muss die\nVerteilte Datenbank aktiv sein, damit Auto-Speed funktioniert. ConfigView.section.transfer.autospeed.minupload=%1 min. Upload-Geschwindigkeit ConfigView.section.transfer.autospeed.minupload.tooltip=Die Upload-Geschwindigkeit wird nicht automatisch unter diesen Wert hinaus verringert. ConfigView.section.transfer.autospeed.maxupload=%1 max. Upload-Geschwindigkeit [0: unbegrenzt] ConfigView.section.transfer.autospeed.maxupload.tooltip=Die Upload-Geschwindigkeit wird nicht automatisch \u00fcber diesen Wert hinaus erh\u00f6ht. ConfigView.section.transfer.autospeed.chokeping=Drosselping [in ms] ConfigView.section.transfer.autospeed.chokeping.tooltip=Pingzeiten, die diesen Wert \u00fcberschreiben, werden\nals Indikator der Netzwerks\u00e4ttigung betrachtet. ConfigView.section.transfer.autospeed.enableauto=Aktiviere beim Herunterladen und Verteilen ConfigView.section.transfer.autospeed.enableautoseeding=Aktiviere nur, wenn verteilt wird ConfigView.pluginlist.column.unloadable=Deaktivierbar ConfigView.section.transfer.lan.enable=Aktiviere separate Geschwindigkeitsbegrenzungen f\u00fcr LAN-Verbindungen. Plugin.localtracker.wellknownlocals=Beziehe bekannte lokale Netzwerke automatisch mit ein (loopback/link/site (192.168 etc)) TableColumn.header.filesdone=Fertige Dateien TableColumn.header.filesdone.info='fertige Dateien/alle Dateien' -ODER- 'fertige nicht \u00fcbersprungene Dateien (fertige Dateien) / alle nicht \u00fcbersprungenen Dateien (alle Dateien) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=Warte auf Initialisierung der verteilten Datenbank... MagnetPlugin.report.searching=suche... MagnetPlugin.report.found=fand %1 MagnetPlugin.report.alive=%1 lebt MagnetPlugin.report.dead=%1 ist tot MagnetPlugin.report.tunnel=tunneln zu %1 MagnetPlugin.report.downloading=herunterladen von %1 MagnetPlugin.report.error=Fehler %1 MagnetURLHandler.report.no_sources=es wurden keine Quellen f\u00fcr den Torrent gefunden MagnetURLHandler.report.torrent_size=Torrentgr\u00f6\u00dfe: %1 MagnetURLHandler.report.percent=fertig: %1% MagnetURLHandler.report.error=Fehler %1 DHTTransport.report.request_all=fordere gesamte \u00dcbertragung von %1 an DHTTransport.report.received_bit=%1 bis %2 von %3 erhalten DHTTransport.report.complete=fertig DHTTransport.report.timeout=Zeit\u00fcberschreitung, keine Antwort von %1 DHTTransport.report.rerequest_all=fordere gesamte \u00dcbertragung erneut von %1 an DHTTransport.report.rerequest_bit=fordere erneut %1 bis %2 von %3 an DHTTransport.report.timeout_some=Zeit\u00fcberschreitung, %1 Pakete von %2 erhalten, jedoch unvollst\u00e4ndig DHTTransport.report.sending=sende Daten DHTTransport.report.resending=sende Daten erneut DHTTransport.report.send_complete=Senden fertig DHTTransport.report.send_timeout=Zeit\u00fcberschreitung beim Senden ConfigView.section.transfer.autospeed.enabledebug=Protokolliere Debug-Informationen TableColumn.header.date_added=Einstelldatum TableColumn.header.date_added.info=Das Datum, an dem der Torrent in die Liste aufgenommen wurde. ConfigView.section.file.hashchecking.smallestfirst=\u00dcberpr\u00fcfe kleinste Downloads zuerst platform.win32.baddll.info=Vuze hat festgestellt, dass '%1' installiert ist. Dies ist Teil von '%2' und ist bekannt daf\u00fcr, gro\u00dfe Probleme wie Programmabst\u00fcrze und hohe CPU-Last zu verursachen. Falls solche Probleme auftreten sollten, deinstalliere diese Software oder konfiguriere sie so, dass Vuze nicht behindert wird. upnp.ignorebaddevices=Ignoriere Ger\u00e4te, die nicht korrekt antworten upnp.ignorebaddevices.info=Momentan ignorierte Ger\u00e4te: %1 upnp.ignorebaddevices.reset=Liste der ignorierten Ger\u00e4te zur\u00fccksetzen upnp.ignorebaddevices.reset.action=Zur\u00fccksetzen upnp.ignorebaddevices.alert=UPnP-Ger\u00e4t an Position %1 wird aufgrund von wiederholten Fehlern ignoriert. In die Konfiguration des UPnP-Plugins schauen, f\u00fcr Einstellungen, die sich darauf beziehen. TorrentOptionsView.param.max.uploads.when.busy=kB/s max. Upload-Geschwindigkeit, wenn das globale Limit erreicht ist [0: deaktiviert] UpdateMonitor.messagebox.verification.failed.title=\u00dcberpr\u00fcfung der Installation fehlgeschlagen UpdateMonitor.messagebox.verification.failed.text=\u00dcberpr\u00fcfung von '%1' fehlgeschlagen: %2 UpdateMonitor.messagebox.accept.unverified.title=Erlaube nicht identifizierte Installation UpdateMonitor.messagebox.accept.unverified.text='%1' konnte nicht als offizielles Vuze-Plugin identifiziert werden.\nFalls es ein solches Plugin ist, dann sollte NICHT fortgefahren werden.\nMit der Installation fortfahren? FileView.BlockView.title=Dateiteile FileView.BlockView.Done=Fertig FileView.BlockView.Skipped=Ausgelassen FileView.BlockView.Active=Aktiv FileView.BlockView.Outstanding=Ausstehend ConfigView.label.tcplistenport=Eingehender TCP-Port ConfigView.label.udplistenport=UDP-Port upnp.portchange.alert=Die folgenden Ports wurden ge\u00e4ndert, um UPnP-Ger\u00e4teprobleme zu verhindern: %1 [alter Port=%2] %3 [alter Port=%4] ConfigView.section.proxy.username.info=Wenn der Proxy-Server eine Authentifikation verlangt, obwohl keine definiert ist, benutze die Zeichenkette "" als Benutzernamen. ConfigView.label.maxuploadswhenbusymin=Zeitraum in Sekunden, in welchem \u00fcberpr\u00fcft wird, ob die Begrenzung\nder Uploadgeschwindigkeit pro Torrent erreicht wurde MainWindow.menu.help.debug=Erstelle Debug-Informationen DownloadManager.error.badsize=Falsche Gr\u00f6\u00dfe natpmp.info=NAT-PMP ist Apples Alternative zu UPnP und wird von den aktuellen Aitport-Stationen\nunterst\u00fctzt. Beachte, dass im Moment UPnP aktiviert sein muss, um NAT-PMP zu\naktivieren, da das NAT-PMP-Ger\u00e4t als eine spezielle Art von UPnP-Ger\u00e4t behandelt wird. natpmp.enable=Aktivieren (beachte, dass es auch in den Airport-Einstellungen aktiviert sein muss, um zu funktionieren) ConfigView.section.tracker.host.addurls=Stelle sicher, dass die URL dieses Trackers in den gehosteten Torrents enthalten ist ConfigView.filter=Suche Optionen hier ConfigView.section.files.move=Verschieben fertiger Daten ConfigView.section.file.defaultdir.section=Standardverzeichniseinstellungen ConfigView.section.file.defaultdir.auto=Automatisches Herunterladen in das Standardverzeichnis (ohne Nachfrage) ConfigView.section.file.defaultdir.bestguess=Benutze 'Bestes Raten', bei der Auswahl des Standard-Speicherverzeichnisses ConfigView.section.file.defaultdir.ask=Standardverzeichnis: ConfigView.section.file.defaultdir.lastused=Benutze das zuvor gew\u00e4hlte Speicherverzeichnis als Standardverzeichnis ConfigView.section.file.config.section=Konfigurationseinstellungen ConfigView.section.file.config.currentdir=Aktuelles Konfigurationsverzeichnis: ConfigView.section.torrent.decoding=Zeichensatz ConfigView.section.logging.udptransport=Aktiviere umfangreiche UDP-Transport-Verfolgung Tracker.announce.ignorePeerSeed=Anzahl ignorierte Quellen. %1 ConfigView.section.connection.encryption.use_crypto_port=Benutze Cryptoport-Tracker-Erweiterung, um eingehende Verbindungen im Klartext zu unterbinden. Einige Tracker unterst\u00fctzen dies nicht und geben Fehlermeldungen wie "Invalid Port" oder "Illegal Argument" wieder. TorrentOptionsView.param.reset.to.default=Optionen auf Standardeinstellungen zur\u00fccksetzen TorrentOptionsView.param.reset.button=Zur\u00fccksetzen natpmp.routeraddress=Stationsadresse [leer: automatische Zuweisung] ConfigView.section.style.disableAlertSliding=Deaktiviere Hinein- und Hinausgleiten des Mitteilungsfensters ConfigView.section.transfer.autospeed.maxinc=%1 max. Erh\u00f6hung pro Durchlauf ConfigView.section.transfer.autospeed.maxdec=%1 max. Reduzierung pro Durchlauf ConfigView.section.transfer.autospeed.enabledownadj=Aktiviere Anpassung der Download-Geschwindigleit ConfigView.section.transfer.autospeed.downadjratio=Verh\u00e4ltnis von Download- zu Uploadgeschwindigkeit (z.B. 2.0 -> die\nDownload-Begrenzung ist das Doppelte der Upload-Begrenzung) ConfigView.section.transfer.autospeed.latencyfactor=Faktor, der benutzt wird, um Ver\u00e4nderungen der Reaktionszeit mit den\nGeschwindigkeits\u00e4nderungen zu verkn\u00fcpfen (gr\u00f6\u00dfere Zahlen vermindern\ndie Empfindlichkeit) ConfigView.section.transfer.autospeed.reset=Setze auf Standardwerte zur\u00fcck ConfigView.section.transfer.autospeed.reset.button=Zur\u00fccksetzen PeerColumn.activationCount=Quellen, die versuchen, sich zu verbinden: %1 TableColumn.header.timesincedownload.info=Zeit, seit welcher keine Daten mehr f\u00fcr den Torrent heruntergeladen worden sind TableColumn.header.timesincedownload=DL-Leerlauf TableColumn.header.timesinceupload.info=Zeit, seit welcher keine Daten mehr f\u00fcr den Torrent hochgeladen worden sind TableColumn.header.timesinceupload=UL-Leerlauf PeersView.incomingreqcount=Anfragen (ein) PeersView.incomingreqcount.info=Z\u00e4hler der Anfragen, die die Quelle gemacht hat PeersView.outgoingreqcount=Anfragen (aus) PeersView.outgoingreqcount.info=Anzahl der Anfragen, die an die Quelle gemacht wurden upnp.mapping.trackerclientudp=UDP-Tracker-Client-Port upnp.mapping.dhtudp=Verteilte Datenbank ConfigView.section.connection.nondata.udp.same=Nutze den gleichen UDP-Port f\u00fcr die Verteilte Datenbank und auch den UDP-Tracker ConfigView.section.connection.tcp.enable=Aktiviere TCP ConfigView.section.connection.udp.enable=Aktiviere UDP ConfigView.section.style.showiconbar=Zeige Werkzeugleiste MainWindow.menu.view.iconbar=Werkzeugleiste MyTorrentsView.menu.rename=Umbenennen MyTorrentsView.menu.rename.displayed=Benenne angezeigten Namen um MyTorrentsView.menu.rename.save_path=Benenne Verzeichnis/Datei um AdvRenameWindow.title=Benenne Download um AdvRenameWindow.message=Neuen Namen f\u00fcr diesen Download eingeben. AdvRenameWindow.rename.torrent=Benenne Torrent um MyTorrentsView.menu.rename.displayed.enter.title=Umbenennung des angezeigten Namens MyTorrentsView.menu.rename.displayed.enter.message=Neuer Name, unter dem der Download in der Liste angezeigt wird.\nWird kein Text eingegeben, wird der Originalname verwendet. MyTorrentsView.menu.edit_comment=Editiere Kommentar MyTorrentsView.menu.edit_comment.enter.title=Editiere Kommentar MyTorrentsView.menu.edit_comment.enter.message=Kommentiere diesen Download. UIDebugGenerator.messageask.title=Erstelle Debug-Informationen UIDebugGenerator.messageask.text=Bitte eine detailierte Problembeschreibung (auf Englisch) eingeben UIDebugGenerator.complete.title=Erstellung der Debug-Informationen fertig UIDebugGenerator.complete.text=Die Debug-Datei kann unter '%1' gefunden werden.\n\nOK klicken, um ein Fenster dorthin zu \u00f6ffnen. ConfigView.section.style.showProgramIcon=Zeige Programmsymbol in der Spalte 'Name' ConfigView.section.style.showProgramIcon.tooltip='Meine Torrents' muss m\u00f6glicher Weise erneut ge\u00f6ffnet\nwerden, damit die \u00c4nderung wirksam wird. swt.alert.cant.update=SWT-Bibliothek von "%3" geladen kann nicht automatisch von Version %1 auf %2 aktualisiert werden (muss von "%4" geladen werden). Bitte f\u00fcr weitere Details in die Wiki schauen. authenticator.savepassword=Erinnere mein Passwort ConfigView.section.security.clearpasswords=L\u00f6sche gespeicherte Passw\u00f6rter ConfigView.section.security.clearpasswords.button=Zur\u00fccksetzen Content.alert.notuploaded.title=Upload unvollst\u00e4ndig Content.alert.notuploaded.text=Das Hochladen von '%1' ist nicht vollst\u00e4ndig. Wenn jetzt %2 wird, werden Nutzer nicht in der Lage sein, das Ver\u00f6ffentlichte komplett herunterzuladen. Sicher, dass %2 wird? Content.alert.notuploaded.multi.title=Uploads unvollst\u00e4ndig Content.alert.notuploaded.multi.text=%1 des ver\u00f6ffentlichten Inhaltes sind noch nicht vollst\u00e4ndig verteilt. Wenn jetzt %2 wird, werden Nutzer nicht in der Lage sein, das Ver\u00f6ffentlichte komplett herunterzuladen. Sicher, dass %2 wird?\n\nNicht vollst\u00e4ndig verteilt:\n%3 Content.alert.notuploaded.stop=gestoppt Content.alert.notuploaded.quit=Vuze beendet TorrentInfoView.torrent.encoding=Torrent-Kodierung TorrentInfoView.columns=Spalten der Ansicht 'Meine Torrents' progress.window.title=Aufgabe wird durchgef\u00fchrt progress.window.msg.filemove=Bitte warten, bis das Verschieben/Umbenennen abgeschlossen ist ConfigView.label.popup.timestamp=F\u00fcge Zeitpunkt der Meldungen hinzu ConfigView.label.popup.autohide=Sekunden, nach denen eine Meldung automatisch ausgeblendet\nwerden soll (0: deaktiviert automatisches Ausblenden) ConfigView.label.popup.suppress_alerts=Unterdr\u00fccke Warnungen ConfigView.label.popup.use_message_boxes=Nutze Popups anstatt der Standardwarnmeldungen ConfigView.label.popup.show=Zeige alle protokollierten Popup-Warnmeldungen (falls vorhanden) ConfigView.label.popup.show.button=Anzeigen ConfigView.label.please.visit.here=F\u00fcr Details bitte hier schauen ConfigView.section.ipfilter.enable.descriptionCache=Speichere IP-Beschreibungen in einer Scratch-Datei ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Wenn deaktiviert, werden Beschreibungen nicht erinnert OpenTorrentWindow.filesInfo=%1 von %2 werden heruntergeladen. OpenTorrentWindow.diskUsage=%1 von %2 ConfigView.label.openmytorrents=\u00d6ffne 'Meine Torrents' beim Start ConfigView.label.open_transfer_bar_on_start=\u00d6ffne \u00dcbertragungsleiste beim Start ConfigView.section.style.DNDalwaysInIncomplete=Behandele Torrents mit Dateien der Priorit\u00e4t 'nicht herunterladen' immer als unvollst\u00e4ndig in 'Meine Torrents' OpenTorrentWindow.mb.noGlobalDestDir.title=Zielverzeichnis OpenTorrentWindow.mb.noGlobalDestDir.text=Das Zielverzeichnis '%1' ist ung\u00fcltig. OpenTorrentWindow.mb.noDestDir.title=Zielverzeichnis nicht gefunden OpenTorrentWindow.mb.noDestDir.text=Das Zielverzeichnis '%1' f\u00fcr Torrent '%2' existiert nicht oder ist ung\u00fcltig. OpenTorrentWindow.mb.notValid.title=\u00d6ffne Torrent OpenTorrentWindow.mb.notValid.text=Torrent '%1' konnte nicht ge\u00f6ffnet werden. Beim \u00d6ffnen im Verteil-Modus bitte sicherstellen, dass die zuverteilenden Daten existieren. OpenTorrentWindow.mb.notTorrent.title=\u00d6ffne Torrent OpenTorrentWindow.mb.notTorrent.text=Konnte '%1' nicht \u00f6ffnen. Es scheint keine Torrent-Datei zu sein.\n\nAuszug der empfangenen Daten:\n%2 ConfigView.label.pause.downloads.on.exit=Pausiere Downloads beim Beenden ConfigView.label.resume.downloads.on.start=Setze pausierte Downloads beim Start fort, nachdem die Initialisierung abgeschlossen wurde UIDebugGenerator.message.cancel.title=Generierung von Debug-Informationen abgebrochen UIDebugGenerator.message.cancel.text=Es wurde keine Beschreibung (Englisch) f\u00fcr das Problem eingegeben, dass versucht wird zu melden. Das Problem mag offensichtlich erscheinen, aber ohne n\u00e4here Beschreibung, k\u00f6nnten wir es selber nur raten.\n\nGenerierung von Debug-Informationen wurde abgebrochen. ConfigView.section.connection.group.http.info=Unterst\u00fctzung f\u00fcr die Verteilung per HTTP. ConfigView.section.connection.http.enable=Aktiviere ConfigView.section.connection.http.port=Eingehender TCP-Port window.update.noupdates.title=Suche nach Aktualisierungen window.update.noupdates.text=Es sind keine neuen Aktualisierungen verf\u00fcgbar. ConfigView.label.bindip.details=Beispiel: 192.168.1.5;eth0;eth1[2] wird die angegebene IP an alle IPs des ersten Interface und die dritte IP des zweiten Interface binden.\n Die erste IP wird f\u00fcr alle Services benutzt, alle anderen nur f\u00fcr Load Balancing.\nDie folgenden Interfaces sind verf\u00fcgbar:\n%1 ConfigView.label.mindownloads=Minimale Anzahl gleichzeitiger Downloads UI.cannot_submit_blank_text=Textfeld darf nicht leer sein. crypto.alert.as.warning=Das Netzwerk '%1' ist bekannt daf\u00fcr, Traffic-Shaping einzusetzen und damit die Download-Geschwindigkeit zu reduzieren. Die Transportverschl\u00fcsselung wurde automatisch aktiviert. Sie kann unter Tools -> Konfiguration -> Verbindung -> Transportverschl\u00fcsselung wieder deaktiviert bzw. ver\u00e4ndert werden. ConfigView.section.interface.alerts=Meldungen ConfigView.label.popupdownloadadded=Zeige eine Meldung, wenn ein Download hinzugef\u00fcgt wurde popup.download.added="%1" wurde zur Download-Liste hinzugef\u00fcgt. MessageBoxWindow.nomoreprompting=Nicht erneut anzeigen TorrentOptionsView.param.max.seeds=Maximale Anzahl von Verbindungen mit vollst\u00e4ndigen Quellen [0: wie max. Verbindungszahl] TorrentOptionsView.param.alternative.value.enable=Alternativer Wert, wenn nur verteilt wird ConfigView.section.proxy.check.on.start=\u00dcberpr\u00fcfe Proxy-Status beim Starten TransferStatsView.legend.pingaverage=Durchschnitt TransferStatsView.legend.ping1=Ziel 1 TransferStatsView.legend.ping2=Ziel 2 TransferStatsView.legend.ping3=Ziel 3 ConfigView.section.interface.enabletray._mac=Aktiviere Statuszeilen-Symbol [Neustart ben\u00f6tigt] ConfigView.label.closetotray._mac='Schlie\u00dfen' minimiert zum Statuszeilen-Symbol ConfigView.label.minimizetotray._mac='Minimieren' minimiert zum Statuszeilen-Symbol OpenTorrentWindow.mb.existingFiles.title=Datei(en) bereits vorhanden! OpenTorrentWindow.mb.existingFiles.text=Einige der Dateien existieren bereits in dem angegebenen Verzeichnis:\n\n%1\nWird weiter gemacht, dann wird Vuze die oben aufgef\u00fchrten Dateien auf korrekte Daten \u00fcberpr\u00fcfen und diese, wenn n\u00f6tig, \u00fcberschreiben bzw. fortsetzen. splash.unloadingTorrents=Entlade Torrents splash.unloadingTorrent=Entlade Torrent ConfigView.section.file.defaultdir.autorename=Benenne Torrent-Daten automatisch um, wenn die Dateien im Verzeichnis anders aussehen ConfigView.section.file.defaultdir.autorename.tooltip=Dies verhindert, dass ein Torrent bei identischen Namen die Dateien eines anderen Torrents \u00fcberschreibt. alert.raised.at.close=(Meldung, als Vuze zuvor beendet wurde) Plugin.trackerpeerauth.name=Tracker-Quellen-Autorisation Plugin.trackerpeerauth.info=Dieses Plugin arbeitet mit Trackern zusammen, um zu \u00fcberpr\u00fcfen, ob Quellen g\u00fcltige Mitglieder des Schwarms sind Peers.column.maxupspeed=max. UL-Geschw. Peers.column.maxdownspeed=max. DL-Geschw. MyTorrents.items.DownSpeedLimit.disabled=Nicht herunterladen upnp.selectedaddresses=Adressen (Trennzeichen: ';', Vorzeichen: '-'=verwehren, '+' =erlauben) [leer: irgendeine] upnp.alert.multipledevice.warning=Es wurden mehrere UPnP-Ger\u00e4te entdeckt - \u00fcberpr\u00fcfe, ob alle Portmapping ben\u00f6tigen (siehe UPnP-Log und Konfiguration) UpdateMonitor.messagebox.restart.title=Software-Aktualisierung UpdateMonitor.messagebox.restart.text=Vuze hat soeben eine wichtige Aktualisierung heruntergeladen und muss nun neugestartet werden, damit diese installiert werden kann. PiecesView.BlockView.Have=Vorhanden PiecesView.BlockView.NoHave=Nicht vorhanden PiecesView.BlockView.Header=%1 Spalte(n), %2 Zeile(n), %3 Teile ConfigView.section.update.autodownload=Lade Aktualisierungen automatisch herunter und zeige einen Dialog, wenn deren Installation bereit ist Peers.column.peer_id=Quell-ID Peers.column.peer_id.info=Quell-ID in lesbarer Form Peers.column.peer_byte_id=Quell-ID Peers.column.peer_byte_id.info=Quell-ID in Byte-Form Peers.column.handshake_reserved.info=Zeige, welche reservierten Bits im BT-Handshake gesetzt wurden Peers.column.client_identification=Client-Identifikation Peers.column.client_identification.info=Zeige rohe Client-Namen, die von Vuze empfangen werden - n\u00fctzlich zum Debuggen dht.warn.user=Warne vor potentiellen NAT-/Portproblemen ConfigView.label.openbar.incomplete=Zeige Info-Leisten automatisch beim Herunterladen ConfigView.label.openbar.complete=beim Verteilen ConfigView.label.transferbar.remember_location=Merke letzte Position der \u00dcbertragungsleiste ConfigView.section.transfer.autospeed.forcemin=%1 erzwungene Upload-Geschwindigkeit beim Initialisieren der Verbindung MainWindow.menu.tools.speedtest=Geschwindigkeitstest... speedtest.wizard.title=Geschwindigkeitstest speedtest.wizard.run=Durchf\u00fchrung eines Geschwindigkeitstests speedtest.wizard.test.mode.updown=Up- und Download speedtest.wizard.test.mode.up=Upload speedtest.wizard.test.mode.down=Download SpeedTestWizard.test.panel.currinfo=Testen der BitTorrent-Bandbreite. SpeedTestWizard.test.panel.label=Vuze-Geschwindigkeitstest: SpeedTestWizard.test.panel.already.running=Test l\u00e4uft bereits! SpeedTestWizard.test.panel.not.accepted=Testanfrage nicht akzeptiert: SpeedTestWizard.test.panel.abort=Abbrechen SpeedTestWizard.test.panel.abort.countdown=Testabbruch in: SpeedTestWizard.test.panel.test.countdown=Test endet in: SpeedTestWizard.test.panel.testfailed=Test fehlgeschlagen SpeedTestWizard.test.panel.aborted=Test wurde manuell abgebrochen. SpeedTestWizard.test.panel.enc.label=Auswahl der Verschl\u00fcsselung: SpeedTestWizard.test.panel.standard=Standard SpeedTestWizard.test.panel.encrypted=Verschl\u00fcsselt SpeedTestWizard.set.upload.button.apply=Verwenden SpeedTestWizard.set.upload.result=Vorheriges Testresultat SpeedTestWizard.set.upload.bytes.per.sec=kB/s SpeedTestWizard.set.upload.bits.per.sec=Bit/s SpeedTestWizard.finish.panel.title=Geschwindigkeitstest beendet! SpeedTestWizard.finish.panel.click.close=Der Geschwindigkeitstest-Assistent wurde beendet. Zum Verlassen auf Schlie\u00dfen klicken. SpeedTestWizard.finish.panel.max.upload=Max. UL-Geschwindigkeit: SpeedTestWizard.finish.panel.max.seeding.upload=Max. UL-Geschwindigkeit, wenn nur verteilt wird: SpeedTestWizard.finish.panel.max.download=Max. DL-Geschwindigkeit: SpeedTestWizard.finish.panel.enabled=aktiviert SpeedTestWizard.finish.panel.disabled=deaktiviert SpeedTestWizard.abort.message.scheduled.in=Test geplant in: %1 Sekunden SpeedTestWizard.abort.message.unsupported.type=Nicht unterst\u00fctzter Test-Typ! SpeedTestWizard.abort.message.manual.abort=Manuell abgebrochen SpeedTestWizard.abort.message.scheduling.failed=Planung des Testes fehlgeschlagen SpeedTestWizard.abort.message.download.added=Download %1 w\u00e4hrend des Testes hinzugef\u00fcgt SpeedTestWizard.abort.message.entered.error=Test-Download betrat Fehlerzustand '%1' SpeedTestWizard.abort.message.entered.queued=Test-Download betrat Warte-/Stoppzustand SpeedTestWizard.abort.message.interrupted=TorrentSpeedTestMonitorThread wurde unterbrochen bevor der Test endete SpeedTestWizard.abort.message.execution.failed=Test-Ausf\u00fchrung fehlgeschlagen SpeedTestWizard.abort.message.failed.peers=Verbindungsaufbau zu Quellen fehlgeschlagen SpeedTestWizard.abort.message.insufficient.slots=Konnte zu keinen Quellen hochladen - ungen\u00fcgende Uploadslots? SpeedTestWizard.abort.message.not.unchoked=Konnte nicht von Quellen herunterladen, bekam kein Unchoked-Signal von ihnen SpeedTestWizard.stage.message.requesting=Fordere Test an... SpeedTestWizard.stage.message.preparing=Bereite Test vor... SpeedTestWizard.stage.message.starting=Starte Test... SpeedTestWizard.stage.message.connect.stats=Verbindungsstatistik : Quellen=%1, runter_ok=%2, hoch_ok=%3 window.uiswitcher.title=Auswahl der Vuze-Benutzeroberfl\u00e4che window.uiswitcher.text=Bitte eine passende Benutzeroberfl\u00e4che ausw\u00e4hlen. window.uiswitcher.NewUI.text=* Empfohlen f\u00fcr Anf\u00e4nger und neue Nutzer.\n\n* Einfache, intuitive grafische Oberfl\u00e4che\n\n * Ben\u00f6tigt, um Inhalte auf der Vuze-Plattform zu ver\u00f6ffentlichen window.uiswitcher.ClassicUI.title=Klassische Oberfl\u00e4che window.uiswitcher.ClassicUI.text=* Bewahrt die Funktionalit\u00e4t der 2.x Serie von Azureus\n\n* Vuze-Inhaltsebene wird nicht geladen window.uiswitcher.bottom.text=Die Einstellung kann durch Nutzung der Vuze-Oberfl\u00e4chenauswahl einfach wieder ge\u00e4ndert werden. iconBar.switch.tooltip=Vuze-Oberfl\u00e4chenauswahl VivaldiView.notAvailable=Vivaldi-Ansicht nicht verf\u00fcgbar restart.error=Neustart fehlgeschlagen:\n%1\nSiehe restarting issues. restart.error.oom=Ungen\u00fcgender Arbeitsspeicher restart.error.fnf='%1' nicht gefunden in '%2' restart.error.pnf=Pfad '%1' nicht gefunden restart.error.bad=Schlechtes Dateiformat f\u00fcr '%1' restart.error.denied=Zugriff wurde verweigert, als versucht wurde '%1' zu starten. Sicherstellen, dass die Rechte zur Ausf\u00fchrung dieses Programmes vorliegen. TableColumn.header.date_completed=Vervollst\u00e4ndigt am TableColumn.menu.date_added.reset=Datum zur\u00fccksetzen ConfigView.section.ipfilter.discardbanning=Blockiere Quellen, deren Verh\u00e4ltnis von verworfenen zu guten Daten folgenden Wert \u00fcberschreitet [0: deaktivieren] ConfigView.section.ipfilter.discardminkb=Minimale verworfene Datenmenge in %1, bevor das Verh\u00e4ltnis angewendet wird ConfigView.interface.start.advanced=Starte in fortgeschrittener Ansicht (AZ 2.x) MyTorrents.column.ColumnQuality=Qualit\u00e4t MyTorrents.column.ColumnSpeed=Geschwindigkeit MyTorrents.column.ColumnProgressETA.2ndLine=Restzeit: %1 MyTorrents.column.ColumnProgressETA.StreamReady=Zum Streamen bereit MyTorrents.column.ColumnProgressETA.PlayableIn=Abspielbar in %1 TableColumn.header.Quality=Qualit\u00e4t TableColumn.header.Speed=Geschwindigkeit TableColumn.header.RateIt=Bewerten TableColumn.header.Rating=Bewertung TableColumn.header.SpeedGraphic=Geschwindigkeit TableColumn.header.AzProduct=Von TableColumn.header.MediaThumb=Medien TableColumn.header.ProgressETA=Fortschritt #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=Dateityp: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=Anzeigetafel v3.MainWindow.tab.browse=Auf Vuze v3.MainWindow.tab.library=Meine Bibliothek v3.MainWindow.tab.publish=Ver\u00f6ffentlichen v3.MainWindow.tab.advanced=Fortgeschritten v3.MainWindow.menu.home=&Anzeigetafel v3.MainWindow.menu.browse=Auf &Vuze v3.MainWindow.menu.library=Meine &Bibliothek v3.MainWindow.menu.publish=V&er\u00f6ffentlichen v3.MainWindow.menu.advanced=&Fortgeschritten v3.MainWindow.menu.view.searchbar=Suchleiste v3.MainWindow.menu.view.tabbar=Tab-Leiste v3.MainWindow.currentDL=Momentane Downloads v3.MainWindow.button.stop=Stopp v3.MainWindow.button.resume=Fortsetzen v3.MainWindow.button.delete=L\u00f6schen v3.MainWindow.button.comment=Kommentar v3.MainWindow.button.viewdetails=Detailansicht v3.MainWindow.button.play=Abspielen v3.MainWindow.button.cancel=Abbrechen v3.MainWindow.button.preview=Vorschau v3.MainWindow.view.wait=Initialisiere Ansicht, bitte warten. v3.MainWindow.xofx=%1 von %2 v3.MainWindow.Loading=Lade... Bitte warten v3.filter-bar=Titelfilter: v3.MainWindow.search.defaultText=finden... v3.mb.delPublished.title=Stoppe Verteilen des Inhaltes v3.mb.delPublished.text=WARNUNG: Diese Aktion wird NICHT den ver\u00f6ffentlichten Inhalt '%1' von %3 entfernen.\n\nNur auf 'L\u00f6schen' klicken, wenn der Inhalt ver\u00f6ffentlicht und herunterladbar bleiben, jedoch Bandbreite freigemacht werden soll. Sicherstellen, dass zuvor der Upload-Prozess abgeschlossen wurde. (Wie?).\n\nAuf 'Abbrechen' klicken, wenn der ver\u00f6ffentlichte Inhalt vollst\u00e4ndig von %3 entfernt werden soll und den (X)-Knopf auf der Schaltfl\u00e4che 'Ver\u00f6ffentliche Inhalt' des Ver\u00f6ffentlichen-Tab nutzen.\n\nWeitere Hilfe.\n\n v3.mb.delPublished.delete=&L\u00f6schen v3.mb.delPublished.cancel=&Abbrechen v3.mb.openFile.title=\u00d6ffne Datei v3.mb.openFile.text.known=Dieser Inhalt wird zur Zeit nicht von Vuze unterst\u00fctzt. F\u00fcr weiter Informationen kann in die Wiedergabeanleitung (engl.) geschaut werden.\n\nDateityp: %2 (%3)\n v3.mb.openFile.text.unknown=Dieser Inhalt wird zur Zeit nicht von Vuze unterst\u00fctzt. F\u00fcr weiter Informationen kann in die Wiedergabeanleitung (engl.) geschaut werden.\n\nDateityp: %2\n v3.mb.openFile.button.play=Abspielen v3.mb.openFile.button.cancel=Abbrechen v3.mb.openFile.button.guide=Wiedergabeanleitung lesen v3.mb.openFile.remember=Dateien immer \u00f6ffnen, ohne zu fragen v3.mb.PlayFileNotFound.title=Datei nicht gefunden v3.mb.PlayFileNotFound.text=Die Dateien von '%1' sind gel\u00f6scht oder fehlen. v3.mb.PlayFileNotFound.button.remove=Entferne aus Vuze v3.mb.PlayFileNotFound.button.redownload=Erneut heruntergeladenene Daten v3.mb.PlayFileNotFound.button.find=Manuelle Suche.. v3.mb.deletePurchased.title=Entferne gekauften Inhalt v3.mb.deletePurchased.text=Sicher, dass der Inhalt '%1' gel\u00f6scht werden soll?\n\nDieser Inhalt wurde entweder gekauft, oder es war eine Anmeldung erforderlich, um ihn herunterzuladen. v3.mb.deletePurchased.button.delete=&L\u00f6schen v3.mb.deletePurchased.button.cancel=&Abbrechen v3.topbar.menu.show.plugin=Plugin-Bereich v3.topbar.menu.show.search=Suchen v3.topbar.menu.show.frog=Der blaue Frosch splash.initializeCore=Initialisiere Kern splash.initializeUIElements=Initialisiere Benutzerschnittstellenelemente # ConfigView.section.ipfilter.peerblocking.group=Quellen-Blockierung ConfigView.section.ipfilter.autoload.group=Automatisches Laden ConfigView.section.ipfilter.autoload.file=IP-Filter-Datei, die automatisch geladen werden soll ConfigView.section.ipfilter.autoload.info=Unterst\u00fctzt folgende Formate: DAT (eMule), P2P (PeerGardian, splist) und P2B v1,2,3 (Peer Gardian 2). Die Datei kann lokal vorhanden sein oder als URL, gepackt als zip, gzip oder in Klartext vorliegen. URLs werden automatisch nach 7 Tagen neu geladen. Dateien werden innerhalb einer Minute neu geladen, nachdem sie ersetzt oder ver\u00e4ndert worden sind. ConfigView.section.ipfilter.autoload.loadnow=Jetzt Laden splash.loadIpFilters=Lade IP-Filter... SpeedTestWizard.set.upload.title=Setze Upload- und Download-Beschr\u00e4nkungen SpeedTestWizard.set.download.label=Empfohlenes Limit der Download-Geschwindigkeit: SpeedTestWizard.set.upload.label=Upload-Geschwindigkeitsbeschr\u00e4nkung: SpeedTestWizard.name.conf.level.absolute=Absolut SpeedTestWizard.name.conf.level.high=Hoch SpeedTestWizard.name.conf.level.med=Mittel SpeedTestWizard.name.conf.level.low=Gering SpeedTestWizard.name.conf.level.none=Kein mb.azmustclose.title=Fehler beim Starten mb.azmustclose.text=Vuze muss aufgrund eines Problems beim Starten beendet werden, welches h\u00f6chstwahrscheinlich dazu f\u00fchrte, dass das Programm als Administrator ausgef\u00fchrt wird.\n\nNachdem es beendet wurde, bitte Vuze erneut manuell starten. network.ipv6.prefer.addresses=Bevorzuge IPv6-Adressen, wenn IPv6 und IPv4 verf\u00fcgbar sind network.enforce.ipbinding=Erzwinge IP-Bindungen, selbst wenn keine Schnittstellen verf\u00fcgbar sind. Verhindert alle Verbindungen, wenn keine der angegebenen Schnittstellen verf\u00fcgbar sind. DHTView.title.full_v6=Verteilte Datenbank IPv6 ConfigView.pluginlist.loadSelected=Lade Auswahl SpeedView.stats.asn=Netzwerk: SpeedView.stats.estupcap=Upload-Limit: SpeedView.stats.estdowncap=Download-Limit: SpeedView.stats.unknown=Unbekannt SpeedView.stats.estimate=Gesch\u00e4tzt SpeedView.stats.measured=Gemessen SpeedView.stats.measuredmin=Gemessenes Minimum SpeedView.stats.manual=Fest ConfigView.section.transfer.autospeed.networks=Netzwerkdetails ConfigView.section.transfer.autospeed.resetnetwork=Netzwerkdetails zur\u00fccksetzen ConfigView.section.transfer.autospeed.network.info=Die oben angegebenen Limits werden normaler Weise automatisch beim Herunterladen berechnet oder sind das Resultat eines Geschwindigkeitstestes. Wenn sie manuell eingestellt werden sollen, bitte die nachfolgenden Optionen nutzen.\nAlle Limits, die nicht 'Fest' sind, werden nach und nach automatisch angepasst, wenn es notwendig werden sollte.\nWerte eingeben und dann den Typ ausw\u00e4hlen. Geschwindigkeiten sind in %1 angegeben. dialog.uiswitcher.restart.title=UI Switcher: Neustart von Vuze erforderlich dialog.uiswitcher.restart.text=Vuze ben\u00f6tigt einen Neustart, um in den neuen Oberfl\u00e4chemodus zu wechseln. TrayWindow.menu.close=Schlie\u00dfe Download-Korb # Used for peers which we can't determine. PeerSocket.unknown=Unbekannt PeerSocket.fake_client=F\u00c4LSCHUNG PeerSocket.bad_peer_id=Schlechte Quell-ID PeerSocket.mismatch_id=Keine \u00dcbereinstimmung PeerSocket.unknown_az_style=Unbekannt %1/%2 PeerSocket.unknown_shadow_style=Unbekannt %1/%2 OpenTorrentWindow.mb.askCreateDir.title=Speicherverzeichnis existiert nicht OpenTorrentWindow.mb.askCreateDir.text=Das Speicherverzeichnis '%1' existiert nicht.\n\nJetzt erstellen? SpeedView.stats.estimatechoke=Gesch\u00e4tzt (gedrosselt) ConfigTransferAutoSpeed.upload.capacity.usage=Upload-Kapazit\u00e4tsnutzung ConfigTransferAutoSpeed.mode=Modus: ConfigTransferAutoSpeed.capacity.used=% genutze Kapazit\u00e4t ConfigTransferAutoSpeed.while.downloading=Beim Herunterladen: ConfigTransferAutoSpeed.set.dht.ping=DHT-Ping-Einstellung: ConfigTransferAutoSpeed.set.point=Wert (ms) ConfigTransferAutoSpeed.set.tolerance=Toleranz (ms) ConfigTransferAutoSpeed.ping.time.good=Gut: ConfigTransferAutoSpeed.ping.time.bad=Schlecht: ConfigTransferAutoSpeed.adjustment.interval=Anpassungsintervall: ConfigTransferAutoSpeed.skip.after.adjust=Nach Anpassung auslassen: GeneralView.label.distributedCopies=Verteilte Kopien: PiecesView.DistributionView.title=Verteilung der Teile PiecesView.DistributionView.NoAvl=Nicht verf\u00fcgbare Teile PiecesView.DistributionView.SeedAvl=Anteil vollst\u00e4ndiger Quellen PiecesView.DistributionView.PeerAvl=Anteil unvollst\u00e4ndiger Quellen PiecesView.DistributionView.RarestAvl=Seltenste Teile: %1 (Verf\u00fcgbarkeit: %2) PiecesView.DistributionView.weHave=vorhandene Teile PiecesView.DistributionView.theyHave=Teile der Quelle PiecesView.DistributionView.weDownload=herunterladene Teile PeersView.gain=Gewinn PeersView.gain.info=Differenz von heruntergeladener und hochgeladener Datenmenge unix.script.new.title=Neues Vuze-Startskript verf\u00fcgbar unix.script.new.text=Ein neues Vuze-Startskript ist verf\u00fcgbar und wurde unter '%1' gespeichert.\n\nEs wird empfohlen, Vuze jetzt zu beenden und zu diesem Skript zu wechseln ('%2').\n\nFalls das Vuze-Startskript stark ver\u00e4ndert wurde, bitte folgendes lesen AzureusWiki: Unix Script.\n\nWenn Vuze als Paket einer Distribution installiert wurde (yum, apt-get, etc), ist es sehr empfehlenswert, Vuze neu zu installieren und dazu das Paket von Vuze Sourceforge Page zu nutzen. (Die verwendete Benutzeroberfl\u00e4che wird beibehalten) unix.script.new.button.quit=Jetzt beenden unix.script.new.button.continue=Sp\u00e4ter durchf\u00fchren unix.script.new.button.asknomore=Nicht noch einmal fragen unix.script.new.auto.title=Neues Vuze-Startskript unix.script.new.auto.text=Ein neues Vuze-Startskript ist verf\u00fcgbar.\n\nEs wird empfohlen, Vuze jetzt neuzustarten. Content.alert.notuploaded.button.stop=&Stopp Content.alert.notuploaded.button.continue=&Verteilen fortsetzen Content.alert.notuploaded.button.abort=&Nicht beenden ConfigView.label.checkOnSeeding=Erneute ressourcenschonende \u00dcberpr\u00fcfung der Teile, wenn nur verteilt wird ConfigView.label.ui_switcher=Zeige Oberfl\u00e4chenauswahl ConfigView.label.ui_switcher_button=Anzeigen SpeedTestWizard.test.panel.explain=Teste die Upload- und Download-Geschwindigkeit mit dem BitTorrent-Protokoll. W\u00e4hle einen Test-Typ und die Methode der Verschl\u00fcsselung. Klicke dann auf Ausf\u00fchren. W\u00e4hle Abbrechen w\u00e4hrend der Test l\u00e4uft, um ihn zu stoppen. Der Test l\u00e4uft f\u00fcr maximal zwei Minuten, normalerweise liegt die Testdauer unter einer Minute. Sobald der Test korrekt beendet wurde, wird auf der n\u00e4chsten Seite eine Empfehlung f\u00fcr die maximale Upload-Geschwindigkeit angegeben. SpeedTestWizard.set.upload.hint=Setze die Upload- und Download-Beschr\u00e4nkungen, die vom Vuze-AutoSpeed-Algorithmus benutzt werden. SpeedTestWizard.set.upload.panel.explain=Die Beschr\u00e4nkungen hier werden vom Vuze-AutoSpeed-Algorithmus benutzt. Einstellen der \u00dcbertragungsbeschr\u00e4nkungen und der Vertauensstufen.\n\nGeschwindigkeiten werden oft in "Bit pro Sekunde" angegeben - jedoch ist der nachfolgende Wert in "Kilobyte pro Sekunde" gegeben! SpeedTestWizard.set.limit.conf.level=Vertauensstufe SpeedTestWizard.finish.panel.auto.speed=Auto-Speed ist: SpeedTestWizard.finish.panel.auto.speed.seeding=Auto-Speed, wenn nur verteilt wird, ist: ConfigTransferAutoSpeed.add.comment.to.log.group=Kommentar zum Debug-Log hinzuf\u00fcgen: ConfigTransferAutoSpeed.add.comment.to.log=Kommentar hinzuf\u00fcgen: ConfigTransferAutoSpeed.algorithm.selector=Auto-Speed-Auswahl ConfigTransferAutoSpeed.algorithm=Algorithmus: ConfigTransferAutoSpeed.data.update.frequency=Update-Frequenz Alert.failed.update=Installation von mindestens einer Komponete fehlgeschlagen, Siehe AzureusWiki: Failed Update OpenTorrentWindow.mb.existingFiles.partialList=(Partielle Liste. Mehrere Dateien existieren bereits.) TableColumn.header.bad_avail_time.info=Zeit, zu der zuletzt eine vollst\u00e4ndige Kopie der Torrent-Daten verf\u00fcgbar war TableColumn.header.bad_avail_time=Vollst. Kopie gesehen MyTorrentsView.menu.exporthttpseeds=Exportiere HTTP-Seed-URLs in die Zwischenablage SWT.alert.erroringuithread=Ein unhandhabbarer Fehler trat in der GUI auf, weitere Fehler k\u00f6nnen gemeldet werden. ConfigView.label.minannounce=Minimale Zeit zwischen den Tracker-Ank\u00fcndigungen (Announces) in Sekunden ConfigView.label.maxnumwant=Limitiere Anzahl unvollst\u00e4ndiger Quellen, die der Tracker meldet ConfigView.label.announceport=\u00dcberschreibe Tracker-Announce-Port ConfigView.label.noportannounce=Sende nicht Nummer des eingehenden Ports zum Tracker (betrifft nicht PEX, DHT) ConfigView.label.maxseedspertorrent=Max. Anzahl vollst\u00e4ndiger Quellen pro Torrent [0: unbegrenzt] wizard.webseed=F\u00fcge HTTP-Quellen dem Torrent zu wizard.webseed.title=HTTP-Quellen wizard.webseed.configuration=HTTP-Quellen-Konfiguration wizard.webseed.adding=F\u00fcge HTTP-Quellen hinzu GeneralView.label.private=Privater Torrent: GeneralView.yes=ja GeneralView.no=nein ConfigView.label.userequestlimiting=Begrenze die Anfragen anstatt das Lesen zu verz\u00f6gern, um die Download-Geschwindigkeit zu limitieren [kein Effekt bei unbegrenzter Download-Geschwindigkeit] ConfigView.label.userequestlimiting.tooltip=Anfragenbegrenzung ist nicht ganz so geschmeidig wie das verz\u00f6gerte Lesen, erlaubt aber eine Priorisierung des Downloads basierend auf der Position in der Wartenschlage und verbessert wom\u00f6glich die Netzwerkperformance. ConfigView.label.userequestlimitingpriorities=Fokusiere Download-Geschwindigkeit im oberen Bereich der Download-Warteschlange, wenn das Limit der Download-Geschwindigkeit erreicht wurde ConfigView.section.logging.timestamp=Zeitstempelformat in Log-Dateien Peers.column.timetocomplete=Restzeit Peers.column.timetocomplete.info=Zeit bis zur Vervollst\u00e4ndigung der Quelle ConfigView.section.interface.display.suppress.file.download.dialog=Unterdr\u00fccke Datei-Download-Popup-Dialog ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Zeige Download-Fortschritt im Statusbalken anstatt als Popup-Dialog FileDownload.canceled=Ein Torrent-Datei-Download wurde erfolgreich durch Nutzerinteraktion abgebrochen: %1 Progress.reporting.status.canceled=Abgebrochen Progress.reporting.status.finished=Beendet Progress.reporting.status.retrying=Wiederhole... Progress.reporting.action.label.retry.tooltip=Wiederhole Operation Progress.reporting.action.label.remove.tooltip=Entferne diesen Fortschrittsreport Progress.reporting.action.label.cancel.tooltip=Breche Operation ab Progress.reporting.default.error=Fehlgeschlagen Progress.reporting.no.reports.to.display=Es gibt zur Zeit keinen Fortschrittsreport anzuzeigen. Progress.reporting.no.history.to.display=Es gibt keine Meldungen anzuzeigen. Progress.reporting.detail.history.limit=Das Limit f\u00fcr Detailmeldungen des Fortschrittsreporters wurde erreicht, weitere Meldungen werden nicht mehr hinzugef\u00fcgt. Progress.reporting.statusbar.button.tooltip=Zeige das Fortschrittsreportfenster webui.bindip=Binde an IP - normalerweise nicht ben\u00f6tigt (*) v3.MainWindow.text.log.in=Einloggen v3.MainWindow.text.log.out=Ausloggen v3.MainWindow.text.get.started=Registrieren v3.MainWindow.text.my.account=Account-Informationen v3.MainWindow.text.my.profile=Profil OpenTorrentWindow.simple.open=Torrent-Position (Datei, URL, Hash) Progress.reporting.window.remove.auto=Entferne inaktive Meldungen automatisch Progress.reporting.window.remove.auto.tooltip=Entferne fertige, fehlgeschlagene oder abgebrochene Prozesse automatisch aus der Ansicht Progress.reporting.window.remove.now=Entferne inaktive Meldungen Progress.reporting.window.remove.now.tooltip=Entferne alle fertigen, fehlgeschlagenen oder abgebrochenen Prozesse aus der Ansicht dhttracker.tracklimitedwhenonline=F\u00fchre jedoch, wenn online, geringf\u00fcgiges Tracken durch, um Torrent-Schw\u00e4rme zu verbinden TorrentOptionsView.multi.title.short=Torrenteinstellungen TorrentOptionsView.multi.title.full=Torrenteinstellungen MyTorrentsView.menu.open_parent_folder=\u00d6ffne Zielverzeichnis ConfigView.section.style.use_show_parent_folder=Nutze "%1" anstatt "%2" in Torrent-Men\u00fcs ConfigView.section.style.use_show_parent_folder.tooltip=Aktivieren dieser Optione erlaubt es, das Zielverzeichnis im korrekten Dateimanager zu \u00f6ffnen.\nJedoch kann es dazu f\u00fchren, dass die Download-Spiecherposition nicht automatisch gew\u00e4hlt wird. ConfigView.section.stats.exportfiles=Exportiere Dateidetails updater.cant.write.to.app.title=Kann nicht im Anwendungsverzeichnis schreiben updater.cant.write.to.app.details=Das Verzeichnis "%1" ist nicht beschreibbar.\n\nDies wird zuk\u00fcnftige Software-Aktualisierungen verhindern.\n\nBitte im Wiki f\u00fcr Details nachschauen. plugin.install.class_version_error=Dieses Plugin ben\u00f6tigt eine neuere Version von Java. v3.MainWindow.tab.events=Benachrichtigungen button.columnsetup.tooltip=Spalteneinstellung v3.activity.remove.title=L\u00f6sche Benachrichtigung v3.activity.remove.text=Sicher, dass die Benachrichtigung gel\u00f6scht werden soll? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=Schlie\u00dfen Menu.show.torrent.menu=Zeige Torrent-Men\u00fc Menu.show.torrent.menu.tooltip=Zeigt das Torrent-Men\u00fc im oberen Men\u00fcbalken #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=Netzwerkstatus plugin.aznetstatus.pingtarget=Ziel f\u00fcr Ping/trace route ConfigView.section.style.usePathFinder=Nutze 'Path Finder' anstatt 'Finder' menu.sortByColumn=Sortiere nach %1 MyTorrentsView.menu.manual.per_peer=Manuell (pro Quelle) MyTorrentsView.menu.manual.shared_peers=Manuell (\u00fcber mehrere Quellen) v3.button.removeActivityEntry=Entferne Benachrichtigung v3.splash.initSkin=Initialisiere Oberfl\u00e4chenaussehen v3.splash.hookPluginUI=Hinzuf\u00fcgen der Plugin-Oberfl\u00e4che OpenTorrentWindow.mb.notTorrent.cannot.display=Unf\u00e4hig Daten korrekt anzuzeigen MainWindow.menu.window.zoom.maximize=Maximieren MainWindow.menu.window.zoom.restore=Wiederherstellen ImageResizer.image.too.small=Das benutzte Bild ist zu klein, bitte ein anderes w\u00e4hlen (mind. %1 x %2 ) ImageResizer.title=Dieses Tool bietet eine Vorschau, wie das Bild auf der Vuze -Plattform aussehen wird. ImageResizer.move.image=Bewege Bild durch ziehen ImageResizer.move.image.with.slider=Bewege Bild durch ziehen, ver\u00e4ndere die Gr\u00f6\u00dfe mit dem Schieberegler unten security.crypto.title=Zugriff auf Schl\u00fcssel security.crypto.encrypt=Bitte Passwort eingeben, um neu generierten Schl\u00fcssel zu sch\u00fctzen. Bitte das Passwort nicht vergessen, es gibt keine M\u00f6glichkeit es wiederherzustellen! security.crypto.decrypt=Bitte Passwort eingeben, um eigenen Schl\u00fcssel zu entsperren. security.crypto.reason=Grund f\u00fcr Aufgabe security.crypto.password=Passwort security.crypto.password2=Passwort erneut eingeben security.crypto.persist_for=Passwort speichern f\u00fcr security.crypto.persist_for.dont_save=Nicht speichern security.crypto.persist_for.session=Diese Sitzung security.crypto.persist_for.day=1 Tag security.crypto.persist_for.week=1 Woche security.crypto.persist_for.30days=30 Tage security.crypto.persist_for.forever=Immer security.crypto.password.mismatch.title=Passwortfehler security.crypto.password.mismatch=Passw\u00f6rter stimmen nicht \u00fcberein, bitte neu eingeben. ConfigView.section.security.group.crypto=\u00d6ffentliche/Private Schl\u00fcssel ConfigView.section.security.resetkey=Setze Schl\u00fcssel zur\u00fcck ConfigView.section.security.resetkey.warning.title=Datenverlustwarnung ConfigView.section.security.resetkey.warning=Sicher, dass die eigenen Schl\u00fcssel zur\u00fcckgesetzt werden sollen? Falls ja, dann sind alle Informationen, welche damit verschl\u00fcsselt worden, F\u00dcR IMMER VERLOREN. Auch werden Quellen, die den dazugeh\u00f6rigen \u00f6ffentlichen Schl\u00fcssel besitzen, nicht l\u00e4nger zur Daten\u00fcbertragung in der Lage sein, ohne einen neuen Schl\u00fcssel zu erhalten. ConfigView.section.security.unlockkey=Entsperre Schl\u00fcssel ConfigView.section.security.unlockkey.button=Entsperren ConfigView.section.security.publickey=\u00d6ffentlicher Schl\u00fcssel ConfigView.section.security.publickey.undef=Noch nicht definiert ConfigView.section.security.resetkey.error.title=Aufgabe fehlgeschlagen ConfigView.section.security.resetkey.error=Zur\u00fccksetzen der Schl\u00fcssel fehlgeschlagen ConfigView.section.security.unlockkey.error=Entsperren fehlgeschlagen - Passwort falsch ConfigView.copy.to.clipboard.tooltip=Kopiere in Zwischenablage Views.plugins.azbuddy.title=Freunde Browser.popup.error.no.access=Es trat ein Fehler auf, bei dem Versuch einen externen Service aufzurufen.\nBitte sp\u00e4ter noch einmal probieren.\n ConfigView.label.queue.stoponcebandwidthmet=Starte keine neuen Torrents, wenn Upload/Download-Geschwindigkeitslimit erreicht wird. ConfigView.section.style.forceMozilla=Zwinge Vuze Mozilla f\u00fcr Browser-Widgets zu nutzen [Xulrunner oder Firefox 3, sowie Neustart ben\u00f6tigt] ConfigView.section.style.xulRunnerPath=Angabe von XulRunner / Firefox-Pfad [ben\u00f6tigt f\u00fcr FF3; Neustart ben\u00f6tigt] azbuddy.name=Freunde azbuddy.enabled=Aktiviert azbuddy.disabled=Plugin ist deaktiviert, siehe Plugin-Konfiguration, um dies zu \u00e4ndern. azbuddy.nickname=Eigener Spitzname azbuddy.msglog.title=Freund-Informationen azbuddy.addtorrent.title=Akzeptiere Download? azbuddy.addtorrent.msg=Freund '%1' hat '%2' gesendet.\nSoll der Download hinzugef\u00fcgt werden? azbuddy.contextmenu=Sende zu Freund azbuddy.ui.mykey=Mein Schl\u00fcssel: azbuddy.ui.add=Hinzuf\u00fcgen azbuddy.ui.new_buddy=Neuer Freund-Schl\u00fcssel: azbuddy.ui.table.last_ygm=Nachricht azbuddy.ui.table.last_msg=Letze Nachricht azbuddy.ui.menu.remove=Entfernen azbuddy.ui.menu.copypk=Kopiere \u00f6ffentlichen Schl\u00fcssel azbuddy.ui.menu.send=Sende Nachricht azbuddy.ui.menu.send_msg=Zu sendenen Text eingeben azbuddy.ui.menu.ygm=Sende YGM azbuddy.ui.menu.enc=Verschl\u00fcssele Zwischenablage azbuddy.ui.menu.dec=Entschl\u00fcssele Zwischenablage azbuddy.ui.menu.sign=Signiere Zwischenablage azbuddy.ui.menu.verify=Verifiziere Zwischenablage azbuddy.ui.table.lastseen=Zuletzt gesehen Button.retry=&Nochmal Button.ignore=&Ignorieren azbuddy.ui.table.msg_in=Nachr. rein azbuddy.ui.table.msg_out=Nachr. raus v3.MainWindow.menu.view.footer=Freund-Leiste azbuddy.downspeed=kB/s max. Freund-Download-Geschwindigkeit [0: unbegrenzt] security.crypto.badpw=Das angegebene Passwort ist falsch ConfigView.section.security.backupkeys=Sichere Schl\u00fcssel in Datei ConfigView.section.security.backupkeys.button=Sicherheitskopie ConfigView.section.security.restorekeys=Wiederherstellen der Schl\u00fcssel aus Datei ConfigView.section.security.restorekeys.button=Wiederherstellen ConfigView.section.security.op.error.title=Aufgabe fehlgeschlagen ConfigView.section.security.op.error=Durchf\u00fchrung der Aufgabe fehlgeschlagen:\n %1 ConfigView.section.security.restart.title=Neustart ben\u00f6tigt ConfigView.section.security.restart.msg=Vuze wird nun neustarten, um die Aufgabe abzuschliessen. ConfigView.section.security.system.managed=Systemverwalteter Schl\u00fcsselschutz azbuddy.ui.table.msg_queued=In Warteschlage azbuddy.chat.title=Vuze-Chat azbuddy.chat.says=%1 sagt: Button.bar.show=Zeigen Button.bar.hide=Verstecken Button.bar.share=Verteilen Button.bar.add=Hinzuf\u00fcgen Button.bar.edit=Editieren Button.bar.edit.cancel=Editieren abbrechen v3.MainWindow.menu.view.pluginbar=Plugin-Leiste MainWindow.dialog.select.vuze.file=W\u00e4hle Vuze-Datei MainWindow.menu.file.open.vuze=Vuze-Datei... metasearch.addtemplate.title=Suchmaske installieren? metasearch.addtemplate.desc=Sicher, dass die Suchmaske '%1' installiert werden soll? v3.share.private.title=Zu tauschender Torrent v3.share.private.text=Der gew\u00e4hlte Torrent ist als privat markiert.\n\nSolche Torrents k\u00f6nnen nicht getauscht werden. metasearch.addtemplate.dup.title=Maske vorhanden metasearch.addtemplate.dup.desc=Suchmaske %1 ist bereits installiert. metasearch.export.select.template.file=Maske speichern metasearch.import.select.template.file=Maske \u00f6ffnen dialog.uiswitch.title=Wechsel zur Vuze-Oberfl\u00e4che dialog.uiswitch.text=Dieses Merkmal ben\u00f6tigt die Vuze-Oberfl\u00e4che.\n\nVuze wird einen Neustart ben\u00f6tigen. dialog.uiswitch.button=Wechsel zur Vuze-Oberfl\u00e4che azbuddy.tracker.enabled=Aktiviere 'Freund-Beschleunigung', um das Herunterladen mit Freunden zu priorisieren. azbuddy.protocolspeed=max. kB/s Freund-Protokolldaten v3.MainWindow.button.download=Herunterladen v3.MainWindow.button.run=Starte heruntergeladene Datei message.taking.too.long=Es scheint, dass dies mehr Zeit ben\u00f6tigt, als erwartet.\n'ESC' dr\u00fccken, wenn diese Aktion abgebrochen werden soll. message.status.success=Erfolg azbuddy.tracker.bbb.status.title=Freund-Beschleunigung azbuddy.tracker.bbb.status.title.tooltip=Doppelklick f\u00fcr Details azbuddy.tracker.bbb.status.idle=Kein Beschleunigen azbuddy.tracker.bbb.status.nli=Login ben\u00f6tigt azbuddy.tracker.bbb.status.in=Man wird beschleunigt azbuddy.tracker.bbb.status.out=Beschleunigen von Freunden v3.MainWindow.search.go.tooltip=Suche ausf\u00fchren v3.MainWindow.search.last.tooltip=Zur\u00fcck zu den Suchergebnissen metasearch.addtemplate.done.title=Maske hinzugef\u00fcgt metasearch.addtemplate.done.desc=Maske '%1' erfolgreich hinzugef\u00fcgt.\nSie wird bei der n\u00e4chsten Suche benutzt. ConfigView.section.security.nopw=Kein Passwort angegeben ConfigView.section.security.nopw_v=Kein Passwort verf\u00fcgbar, bitte in Vuze einloggen fileplugininstall.install.title=Plugin installieren? fileplugininstall.install.desc=Sicher, dass Plugin '%1', Version %2 installiert werden soll? fileplugininstall.duplicate.title=Plugin vorhanden fileplugininstall.duplicate.desc=Plugin '%1', Version %2 ist schon installiert azbuddy.online_status=Online-Status azbuddy.os_away=Weg azbuddy.os_not_avail=Nicht erreichbar azbuddy.os_busy=Besch\u00e4ftigt azbuddy.ui.menu.disconnect=Trennen azbuddy.enable_chat_notif=Aktiviere Chat-Benachrichtigungen progress.window.msg.progress=Bitte warten, bis die Aktion abgeschlossen ist DetailedListView.title=Detailierte Liste ConfigView.section.connection.network.max.outstanding.connect.attempts=Max. Anzahl ausstehender ausgehender Verbindungen plugins.init.force_enabled=Vuze hat erkannt, dass das Plugin "%1" deaktiviert worden ist. Es wurde wieder aktiviert, damit Vuze korrekt arbeiten kann. ConfigView.section.connection.prefer.udp=Bevorzuge UDP-Verbindungen subscript.add.title=Abonnement installieren? subscript.add.desc=Sicher, dass das Abonnement '%1' installiert werden soll? subscript.add.dup.title=Vorhandenes Abonnement subscript.add.dup.desc=Abonnement '%1' ist bereits installiert. subscript.add.upgrade.title=Abonnement aktualisieren? subscript.add.upgrade.desc=Sicher, dass das Abonnement '%1' aktualisiert werden soll? subscript.add.upgradeto.desc=Version %1 des Abonnements '%2' verf\u00fcgbar.\nSoll es aktualisiert werden? azsubs.contextmenu.addassoc=F\u00fcge Abonnementverbindung hinzu azsubs.contextmenu.lookupassoc=Suche Abonnementverbindungen iconBar.stop=Stopp iconBar.remove=Entfernen iconBar.up=Hoch iconBar.down=Runter iconBar.run=\u00d6ffnen iconBar.editcolumns=Spalteneinstellung iconBar.top=An Anfang iconBar.bottom=Ans Ende iconBar.queue=In Warteschlage iconBar.open=Torrent hinzuf\u00fcgen iconBar.share=Tauschen iconBar.share.tooltip=Tausche Inhalt iconBar.comment=Kommentar iconBar.play=Abspielen iconBar.queue.tooltip=Warteschlange v3.MainWindow.menu.view.sidebar=Seitenleiste v3.MainWindow.menu.view.actionbar=Aktionsleiste v3.MainWindow.menu.view.toolbars=Werkzeugleiste ump.install=Dieses Video ben\u00f6tigt weitere Komponenten zum Abspielen. Installation wird durchgef\u00fchrt. Bitte warten. subscriptions.listwindow.title=Finde Abonnements subscriptions.listwindow.autochecktext=Vuze kann Abonnements finden, die sich auf Inhalte der Bibliothek beziehen. Soll dieses Merkmal aktiviert werden? subscriptions.listwindow.loadingtext=Suche Abonnements bez\u00fcglich %1 subscriptions.listwindow.failed=Keine Abonnements gefunden subscriptions.listwindow.popularity=Popularit\u00e4t subscriptions.listwindow.popularity.unknown=Unbekannt subscriptions.listwindow.subscribe=Abonieren TableColumn.header.azsubs.ui.column.subs=Abo subscriptions.listwindow.popularity.reading=Lese... PluginDeprecation.log.start=Dieses Fenster enth\u00e4lt Informationen \u00fcber Plugins, die Funktionen nutzen, welche in kommenden Versionen von Vuze entfernt werden.\nDie Plugins m\u00fcssen nicht deinstalliert, jedoch sollten sie auf die neusten Versionen aktualisiert werden.\nFalls die aktuellste Version schon installiert sein sollte, kopiere den Inhalt dieses Fensters und schreibe ihn ins Forum:\n \t%1\n\n PluginDeprecation.view=Plugin-Debug PluginDeprecation.alert=Ein Plugin versuchte Funktionen zu nutzen, welche in Zukunft entfernt werden - bitte \u00f6ffne das Plugin-Debug-Log f\u00fcr weitere Informationen. TableColumn.header.Thumbnail=Symbol TableColumn.header.Thumbnail.info=Das Vorschaubild f\u00fcr Vuze-Inhalt; f\u00fcr andere Inhalte bietet das Betriebssystem die Bilder. v3.MainWindow.menu.getting_started=&Beginnen MainWindow.menu.help.faq=H\u00e4ufige &Fragen (FAQ) MainWindow.menu.community.wiki=Community-&Wiki MainWindow.menu.community.forums=Community-Fo&ren MainWindow.menu.community.blog=Vuze-&Blog MainWindow.menu.help.support=&Hilfe und Support externalLogin.title=Einloggen notwendig externalLogin.explanation=Die Maske "%1" ben\u00f6tigt es, eingeloggt zu sein. Dieses Fenster schliesst sich nach dem Einloggen automatisch. Falls nicht, bitte auf "Fertig" klicken. externalLogin.explanation.capture=Man muss eingeloggt sein, um diese Maske zu erstellen. Sobald dies geschehen ist, bitte auf "Fertig" klicken. Button.done=Fertig GeneralView.torrent_created_on_and_by=%1 mit %2 Button.continue=Weiter Button.preview=Vorschau Subscription.menu.forcecheck=Jetzt aktualisieren Subscription.menu.clearall=Alle Ergebnisse als gelesen markieren Subscription.menu.remove=Entfernen sidebar.Library=Meine Bibliothek sidebar.LibraryDL=Unvollst\u00e4ndig sidebar.LibraryCD=Vollst\u00e4ndig authenticator.location=Ort v3.MainWindow.menu.showActionBarText=Zeige Text subscript.import.fail.title=Importierung fehlgeschlagen Subscription.menu.export=Exportieren subscript.export.select.template.file=Abonnement speichern Button.remove=Entfernen Button.send=Sende Button.back=Zur\u00fcck sidebar.LibraryUnopened=Ungesehen TableColumn.header.unopened=Neu Unopened.bigView.header=Neu Subscription.menu.deleteall=L\u00f6sche alle Ergebnisse Subscription.menu.reset=Zur\u00fccksetzen in Ausgangszustand ConfigView.section.Subscriptions=Abonnements subscriptions.config.maxresults=Maximale Anzahl gespeicherter Ergebnissen pro Abonnement [0: unbegrenzt] v3.activity.button.readall=Alle als gelesen markieren TableColumn.header.activityNew=Neu TableColumn.header.activityType=Typ TableColumn.header.activityText=Nachricht TableColumn.header.activityDate=Hinzugef\u00fcgt TableColumn.header.activityActions=Aktionen Subscription.menu.resetauth=Authentifikationsdetails zur\u00fccksetzen Search.menu.engines=Masken Wizard.Subscription.title=Abonnieren Wizard.Subscription.optin.title=Aktiviere Abonnements #what you've watched? Discover more with a single click... Wizard.Subscription.subscribe.title=Verf\u00fcgbare Abonnements Wizard.Subscription.create.title=Erstelle neues Abonnement Button.search=Suchen Button.save=Speichern Button.add=Hinzuf\u00fcgen Button.createNewSubscription=Erstelle neues Abonnement Button.availableSubscriptions=Verf\u00fcgbare Abonnements Wizard.Subscription.optin.description=Wenn Abonnements aktiviert sind, wird Vuze Abonnements anzeigen, die sich auf Inhalte in der Bibliothek beziehen. Sobald ein neuer abonnierter Inhalt zum Herunterladen verf\u00fcgbar ist, wird dies von Vuze angezeigt.\n\nSollen Abonnements aktiviert werden? Wizard.Subscription.create.search=Suchen Wizard.Subscription.search.subtitle1=Gib eine Suche ein und erstelle ein Abonnement: Wizard.Subscription.search.subtitle2=Wonach kann ich suchen? Wizard.Subscription.search.subtitle2.sub1=Filme in HD, TV-Serien, Filme, Trailer im Vuze-Netzwerk Wizard.Subscription.search.subtitle2.sub2=Torrents aus dem Internet Wizard.Subscription.search.subtitle3=Sobald neue Ergebnisse f\u00fcr die Suche verf\u00fcgbar sind, werden diese in der Seitenleiste angezeigt. Wizard.Subscription.rss.subtitle1=URL eingeben oder einf\u00fcgen: Wizard.Subscription.rss.subtitle2=Viele Anbieter geben f\u00fcr ihre Ver\u00f6ffentlichungen RSS-Feeds an. Kopiere die Feed-Adresse, f\u00fcge sie im oberen Feld ein und klicke auf Speichern. Wizard.Subscription.rss.subtitle3=Sobald neue Ergebnisse durch den RSS-Feed verf\u00fcgbar sind, werden diese in der Seitenleiste angezeigt. Wizard.Subscription.subscribe.library=Inhalt der Bibliothek Wizard.Subscription.subscribe.subscriptions=Relevante Abonnements Wizard.Subscription.subscribe.library.empty=Keine Abonnements verf\u00fcgbar?\n \nSuche das orangene Abonnementsymbol im Vuze-Netzwerk.\n \nWeitere Informationen message.confirm.delete.title=L\u00f6schen best\u00e4tigen message.confirm.delete.text=Sicher, dass '%1' gel\u00f6scht werden soll? Subscription.menu.properties=Eigenschaften props.window.title=Eigenschaften f\u00fcr '%1' subs.prop.is_auto=Automatisches Herunterladen neuer Ergebnisse subs.prop.last_scan=Letzte erfolgreiche Aktualisierung subs.prop.last_result=Letztes Ergebnis gefunden subs.prop.last_error=Letzter Fehler subs.prop.num_read=Anzahl gelesener Ergebnisse subs.prop.num_unread=Anzahl ungelesener Ergebnisse subs.prop.template=Maske subs.prop.auth=Authentifikation erforderlich externalLogin.wait=Seite wird geladen, bitte warten... TableColumn.menu.date_added.time=Zeige/Verstecke Zeit sidebar.VuzeHDNetwork=Vuze HD-Netzwerk subs.prop.next_scan=N\u00e4chster Scan subs.prop.assoc=Assoziationen subscriptions.column.new.info=Zeigt Verf\u00fcgbarkeit neuer Ergebnisse subscriptions.column.name=Abonnement subscriptions.column.nb-results=Gesamte Ergebnisse subscriptions.column.nb-new-results=Neue Ergebnisse subscriptions.column.last-checked=Letzte \u00dcberpr\u00fcfung subscriptions.view.title=Abonnements subs.prop.is_public=\u00d6ffentlich subs.prop.high_version=H\u00f6chste gefundene Version Subscription.menu.upgrade=Aktiviere Aktualisierung auf h\u00f6here Version metasearch.template.version.bad=Installation von Suchmaske '%1' erfordert Aktualisierung von Vuze metasearch.addtemplate.failed.title=Installation fehlgeschlagen metasearch.addtemplate.failed.desc=Installation fehlgeschlagen von Suchmaske: %1 subscription.version.bad=Installation von Abonnement '%1' erfordert Aktualisierung von Vuze statusbar.feedback=Sende Feedback statusbar.feedback.tooltip=Hier klicken, um Feedback zu senden sidebar.Activity=Benachrichtigungen v3.activity.button.watchall=Alle als gesehen markieren subscriptions.view.help.1=Abonnements hinzuf\u00fcgen mit subscriptions.view.help.2=Erhalte Mitteilungen, wenn es neue Inhalte zum Herunterladen gibt. Weitere Informationen. sidebar.sash.tooltip=F7 zeigt/versteckt Seitenleiste sidebar.expand.tooltip=Seitenleiste ausfahren sidebar.dropdown.tooltip=Zeige Seitenleiste in Men\u00fcformat subscript.all.subscribed=Dieser Inhalt ist abonniert subscript.some.subscribed=Einige Abonnements f\u00fcr diesen Inhalt schon vorhanden.\nKlicken, um weitere zu sehen. subscript.none.subscribed=Klicken, um verf\u00fcgbare Abonnements des Inhaltes zu sehen v3.iconBar.up.tooltip=Nach oben bewegen\nMaustaste halten, um an den Anfang zu bewegen v3.iconBar.down.tooltip=Nach unten bewegen\nMaustaste halten, um an das Ende zu bewegen TableColumn.header.azsubs.ui.column.subs_link=Verbindung TableColumn.header.azsubs.ui.column.subs_link.info=Verbindung mit Abonnements Button.deleteContent.fromLibrary=Entferne aus Bibliothek Button.deleteContent.fromComputer=L\u00f6sche von Computer v3.deleteContent.message=\nSoll '%1' vom Computer gel\u00f6scht, oder nur aus der Vuze-Bibliothek entfernt werden? v3.MainWindow.menu.view.toolbartext=Werkzeugleistentext v3.MainWindow.menu.view.asSimpleList=Einfache Liste v3.MainWindow.menu.view.asAdvancedList=Erweiterte Liste v3.MainWindow.menu.view.statusbar=Statusleiste Subscription.menu.dirtyall=Markiere alle Ergebnisse als ungelesen configureWizard.file.message3=Vuze wird Dateien in einem speziellen Ordner speichern, welcher hier gew\u00e4hlt werden kann: v3.deleteContent.applyToAll=Ausf\u00fchren f\u00fcr alle %1 gew\u00e4hlten Eintr\u00e4ge ConfigView.label.seeding.firstPriority.ignoreIdleHours=Torrents, die nichts hochladen f\u00fcr v3.MainWindow.menu.contentnetworks=HD-&Netzwerke v3.MainWindow.menu.contentnetworks.about=\u00dcber HD-Netzwerke Peers.column.as.info=Details des Automomen Systems der Quelle ConfigView.label.autoopen.downloadbars=Automatisches \u00d6ffnen der Download-Leisten, wenn ConfigView.label.autoopen=Autom. \u00d6ffnen ConfigView.label.autoopen.detailstab=Automatisches \u00d6ffnen der Details, wenn ConfigView.label.systray= ConfigView.label.systray._mac=Statusleisten-Symbol v3.MainWindow.menu.contentnetworks.manage=&Verwalte HD-Netzwerke azbuddy.ui.table.loc_cat=Kat. raus azbuddy.ui.table.rem_cat=Kat. rein azbuddy.ui.menu.cat=Kategorien azbuddy.ui.menu.cat.share=Aktiviere Abonnements mit Freunden azbuddy.ui.menu.cat.set=Kategorien eingeben azbuddy.ui.menu.cat.set_msg=Mit Komma getrennte Liste von Kategorien, oder alle mit 'All' azbuddy.ui.menu.cat_subs=Abonniere subs.prop.update_period=Aktualisierungsperiode azbuddy.enable_cat_pub=\u00d6ffentliche Kategorien, die ALLE Freunde abonnieren k\u00f6nnen (getrennt durch Komma) v3.dialog.cnclose.title=%1 geschlossen v3.dialog.cnclose.subtitle=Benachrichtigung v3.dialog.cnclose.info1=Ein HD-Netzwerk wurde geschlossen. v3.dialog.cnclose.info2=Es wurde ein HD-Netzwerk in der Seitenleiste geschlossen.\n\nFalls es wieder ge\u00f6ffnet werden soll, kann dies \u00fcber das Men\u00fc "HD Networks" auf der rechten Seite geschehen. v3.dialog.cnclose.noshow=Nicht noch einmal zeigen v3.dialog.cnmanage.title=Verwalte Netzwerke f\u00fcr HD Inhalte v3.dialog.cnmanage.intro=Die untere Liste zeigt eine Auswahl von Netzwerken, die im Men\u00fc "HD-Netzwerke" angezeigt werden k\u00f6nnen. azbuddy.ui.table.read_cat=Kat. gelesen TableColumn.header.#.info=Position/Ordnungsnummer TableColumn.header.category.info=Name der Kategorie des Torrents TableColumn.header.DateCompleted.info=Zeitpunkt der Vervollst\u00e4ndigung des Downloads TableColumn.header.AzProduct.info=Ursprungsnetzwerk des Torrents TableColumn.header.health.info=Fitness der Verbindung zum Torrentschwarm TableColumn.header.maxuploads.info=Maximale Anzahl von Quellen, zu denen gleichzeitig hochgeladen wird TableColumn.header.name.info=Name des Torrents TableColumn.header.unopened.info=Symbol, das zeigt, ob Torrent abgespielt (ge\u00f6ffnet) wurde TableColumn.header.savepath.info=Zielverzeichnis oder -datei der Torrentdaten TableColumn.header.SeedingRank.info=Wert, der die Dringlichkeit f\u00fcr Upload anzeigt. Je h\u00f6her der Wert, desto gr\u00f6\u00dfer der Bedarf. TableColumn.header.shareRatio.info=Verh\u00e4lnis von hochgeladener zu heruntergeladener Datenmenge TableColumn.header.size.info=Gr\u00f6\u00dfe des Torrentinhaltes auf der Festplatte TableColumn.header.azsubs.ui.column.subs.info=Knopf erlaubt das Abonnieren von Feed mit \u00e4hnlichen Torrents TableColumn.header.upspeed.info=Aktuelle Uploadgeschwindigkeit TableColumn.header.downspeed.info=Aktuelle Downloadgeschwindigkeit TableColumn.header.up.info=Aktuelle hochgeladene Datenmenge TableColumn.header.down.info=Datenmenge, die bis jetzt von anderen Nutzer erhalten wurde TableColumn.header.ProgressETA.info=Kombiniert Status, Vervollst\u00e4ndigung, ETA und Downloadgeschwindigkeit in einer Spalte TableColumn.header.eta.info=Gesch\u00e4tzte Zeit bis zur Vervollst\u00e4ndigung des Downloads Pieces.column.#.info=Teilnummer Peers.column.%.info=Prozent des Torrents, die die Quelle heruntergeladen hat TableColumn.header.download.info=Datenmenge, von Quelle erhalten TableColumn.header.upload.info=Datenmenge, die zur Quelle gesendet wurde TableColumn.header.downloadspeed.info=Geschwindigkeit, mit der Daten von Quelle empfangen werden TableColumn.header.uploadspeed.info=Uploadgeschwindigkeit zur Quelle TableColumn.header.lan.info=Flag, das anzeigt, ob sich Quelle im LAN befindet TableColumn.header.downloadspeedoverall.info=Gesch\u00e4tzte Downloadgeschwindigkeit der Quelle Peers.column.pieces.info=Grafische Leiste f\u00fcr Teile, die die Quelle heruntergeladen hat TableColumn.header.TableColumnNameInfo=Spaltenname und Beschreibung TableColumn.header.TableColumnSample=Beispiel TableColumn.header.TableColumnInfo=Spaltenbeschreibung TableColumn.header.TableColumnChosenColumn=Gew\u00e4hlte Spalte subs.prop.is_auto_ok=Auto-Download erlaubt label.learnmore=Weitere Infos ColumnSetup.title=Spalteneinstellung f\u00fcr '%1' ColumnSetup.explain=Links befindet sich die Liste der verf\u00fcgbaren Spalten, die der Liste der anzuzeigenden Spalten auf der recht Seite hinzugef\u00fcgt werden k\u00f6nnen. Der Filter unten links kann das Auffinden geeigneter Spalten erleichtern. ColumnSetup.chosencolumns=Gew\u00e4hlte Spalten ColumnSetup.proficiency=Kenntnisstand: ColumnSetup.categories=Kategorien: ColumnSetup.filters=Filter ColumnSetup.availcolumns=Verf\u00fcgbare Spalten f\u00fcr %1 ColumnSetup.availcolumns.filteredby=Verf\u00fcgbare Spalten f\u00fcr %1, gefiltert nach %2 devices.view.title=Ger\u00e4te device.mediaserver.view.title=Medienserver device.router.view.title=Router device.model.desc=Modelbeschreibung device.model.name=Modelname device.model.num=Modelnummer device.manu.desc=Hersteller device.router.is_mapping=Automatische Portweiterleitung device.router.req_map=Ben\u00f6tigt Portweiterleitung device.router.configure=Konfiguriere UPnP device.mediaserver.configure=Konfiguriere Medienserver device.hide=Verstecke Ger\u00e4t device.show=Zeige versteckte Ger\u00e4te device.search=Suche nach Ger\u00e4ten device.router.con_type=Verbindung: %1 device.browse=Durchsuchen device.upnp.desc_url=Ger\u00e4tebeschreibung device.upnp.present_url=Ger\u00e4teverwaltung device.search.auto=Automatische Suche nach Ger\u00e4ten devices.sidebar.simple=Einfache Ansicht devices.xcode.working_dir=Umwandlungsbereich devices.xcode.prof_def=Standardumwandlungsprofil devices.xcode.profs=Vorhandene Umwandlungsprofile device.lastseen=Zuletzt gesehen devices.contextmenu.xcode=Umwandeln f\u00fcr Ger\u00e4t devices.device=Ger\u00e4t devices.profile=Profil General.percent=Prozent devices.installed=Installiert devices.comp.missing=Vuze-Unterst\u00fctzung nicht installiert devices.state=Zustand MainWindow.menu.help.donate=&Spenden !!! DonationWindow.noload.title=Spenden DonationWindow.noload.text=Das Spenden-Fenster konnte nicht geladen werden. Bitte versuche es sp\u00e4ter noch einmal. devices.xcode.only.show=Zeige nur umgewandelte Dateien auf Ger\u00e4t device.quit.transcoding.title=Umwandlung wird durchgef\u00fchrt device.quit.transcoding.text='%1' wird gerade f\u00fcr '%2' ungewandelt und ist %3% fertig.\nFalls jetzt beendet wird, muss der gesamte Vorgang beim n\u00e4chsten Start erneut durchgef\u00fchrt werden. download.removerules.unauthorised.data=\tEntferne Daten device.config.xcode.maxbps=Max kB/s Umwandlungsrate [0: unbegrenzt] device.xcode=Umwandeln device.xcode.always=Immer device.xcode.whenreq=Wenn n\u00f6tig device.xcode.never=Nie devices.copy.pending=Dateikopie ausstehend devices.sidebar.hide.rend.generic=Verstecke generische Ger\u00e4te v3.devicesview.infobar.text2=Um Inhalte f\u00fcr ein Ger\u00e4t umzuwandeln, einfach den Inhalt aus der Bibliothek auf das Ger\u00e4t in der Seitenleiste ziehen. Um fertige Umwandlungen zu sehen, das jeweilige Ger\u00e4t auf der rechten Seite anklicken. iconBar.transcode=Ger\u00e4t iconBar.transcode.tooltip=Medien f\u00fcr ein Ger\u00e4t verf\u00fcgbar machen device.retry.copy=Erneuter Kopierversuch devices.copy.fail=Kopieren zum Ger\u00e4t fehlgeschlagen devices.on.demand=Auf Abruf devices.ready=Bereit TableColumn.header.trancode_qpos.info=Position in Umwandlungswarteschlage TableColumn.header.profile=Ger\u00e4t TableColumn.header.profile.info=Benutztes Umwandlungsprofil TableColumn.header.copied=Kopiert TableColumn.header.device=Ger\u00e4t TableColumn.header.device.info=Zielger\u00e4t TableColumn.header.trancode_completion=Umwandlungsfortschritt # This is the beginning of the word "View". It's right aligned under the icon bar item v3.iconBar.view.big=Ans v3.iconBar.view.big.tooltip=Ansicht als einfache Liste # This is the end of the word "View". It's left aligned under the icon bar item v3.iconBar.view.small=icht v3.iconBar.view.small.tooltip=Ansicht als erweiterte Liste general.dont.ask.again=Nicht nochmal fragen v3.menu.device.exploreTranscodes=Zeige Dateien v3.menu.device.exploreTranscodes._windows=Zeige Dateien im Explorer v3.menu.device.exploreTranscodes._mac=Zeige Dateien im Finder v3.menu.device.defaultprofile=Standardprofil devices.button.installitunes=Installiere iTunes-Einbindung device.itunes.install=Es muss iTunes installiert sein device.itunes.start=iTunes muss gestartet oder Auto-Start aktiviert sein device.itunes.install_problem=Es scheint ein Problem mit der iTunes-Einbindung zu geben devices.downloading=Herunterladen TableColumn.header.duration=Dauer TableColumn.header.resolution=Aufl\u00f6sung devices.xcode.autoStart=Wenn n\u00f6tig, automatisch starten option.askeverytime=Jedes Mal nachfragen option.rememberthis=Merke diese Einstellung devices.associate=Verbinde mit devices.associate.already=Schon verbunden devices.always.cache=Cache nicht umgewandelte Dateien devices.turnon.prepageload=F\u00fcr die Aktivierung dieses Merkmales ist die Installation weiterer Komponenten notwendig. devices.turnon.itunes=iTunes-Unterst\u00fctzung aktivieren (ben\u00f6tigt f\u00fcr Apple-Ger\u00e4te) devices.turnon.qos=Erlaube senden anonymer Ger\u00e4testatistiken an Vuze devices.turnon.title=Ger\u00e4teunterst\u00fctzung anschalten devices.choose.device.title=Setze Wiedergabeger\u00e4t f\u00fcr dieses Video: devices.choose.profile.info.text=Nach der Auswahl wird Vuze erkennen, ob das Videoformat auf dem gew\u00e4hlten Ger\u00e4t abgespielt werden kann und wird, wenn n\u00f6tig, eine mit dem Ger\u00e4t kompatible Kopie erstellen.\n\nF\u00fcr weitere Details die Maus \u00fcber das gew\u00e4hlte Ger\u00e4t bewegen. devices.choose.profile.info.title.selected=%1 Details: devices.view.heading=Medien f\u00fcr Ger\u00e4tewiedergabe-Umwandlung device.view.heading=Medien f\u00fcr %1 devices.choose.device.info.title=Ger\u00e4te-Tipp devices.choose.device.info.text=Das n\u00e4chste Mal einfach die Dateien auf das Ger\u00e4t der Wahl in der Seiteleiste ziehen. Button.turnon=Anschalten ConfigView.label.dm.dblclick=Doppelklick in Torrent-Ansichten: ConfigView.option.dm.dblclick.play=Inhalt abspielen ConfigView.option.dm.dblclick.details=Detailansicht des Torrents \u00f6ffnen ConfigView.option.dm.dblclick.show=Zeige Datei ConfigView.option.dm.dblclick.show._mac=Zeige Datei(en) im Finder ConfigView.option.dm.dblclick.show._windows=Zeige Datei(en) im Explorer subscriptions.column.auto-download=Auto-Download xcode.deletedata.title=L\u00f6sche umgewandelten Inhalt xcode.deletedata.message=Sicher, dass die Kopie von '%1', umgewandelt f\u00fcr '%2'%3 gel\u00f6scht werden soll? xcode.deletedata.message.2=\n(Eine Kopie k\u00f6nnte noch in '%1' existieren.) v3.deviceview.infobar.line1=Ziehe Videos aus der Bibliothek zum Ger\u00e4t der Wahl. v3.deviceview.infobar.line2=Spiele Videos auf allem m\u00f6glichen Ger\u00e4ten ab - iPhone, iPod, TV v3.deviceview.infobar.line1.generic=Ziehe Videos von der Bibliothek nach %1 im Seitenmen\u00fc. v3.deviceview.infobar.line2.itunes=Videos werden im iTunes-Film-Verzeichnis erscheinen, wenn sie zum Abspielen bereit sind. v3.deviceview.infobar.line2.xbox=Abspielen der Videos durch Auswahl von My XBox -> Video Library -> Vuze auf der Xbox 360. v3.deviceview.infobar.line2.ps3=Abspielen der Videos durch Auswahl von Videos -> Vuze auf der PS3. devices.copy_url=Kopiere Stream-URL in Zwischenablage devices.converting=Konvertieren Button.reload=Neuladen devices.auto.start=Auto-Start Subscription.menu.setcookies=Setze Cookies device.config.xcode.workdir=Standardverzeichnis f\u00fcr umgewandelte Dateien DiskManager.error.nospace=Ungen\u00fcgender Speicherplatz ConfigView.section.file.rename.incomplete=H\u00e4nge Suffix an unvollst\u00e4ndige Dateien subscriptions.config.auto=Auto-Download subscriptions.config.autostartdls=Starte neuhinzugef\u00fcgte Downloads automatisch subscriptions.config.autostart.min=Nur starten, wenn >= MB [0: unbegrenzt] subscriptions.config.autostart.max=Nur starten, wenn <= MB [0: unbegrenzt] dlg.corewait.title=Initialisiere Kern dlg.corewait.text=Einen Augenblick bitte...\n\nDie Anfrage wird bearbeitet, sobald Vuze die Initialisierung abgeschlossen hat library.core.wait=Einen Augenblick bitte...\nVuze wird initialisiert ConfigView.label.StartUIBeforeCore=Starte Oberfl\u00e4che vor Kerninitialisierung general.add.friends=F\u00fcge Freunde hinzu! general.all.friends=Alle Freunde friend.mod.subs=Rechtsklick, um das Abonnement zu \u00e4ndern TableColumn.header.class=Klasse device.rss.group=Lokaler RSS-Feed devices.xcode.rsspub=Ver\u00f6ffentliche RSS-Feed device.rss.enable=Erzeuge RSS-Feed von umgewandeltem Inhalt - macht den Inhalt f\u00fcr RSS-Feed-Betrachter verf\u00fcgbar device.rss.port=RSS-Feed-Port device.rss.view=Klicken, um RSS-Feed anzusehen device.rss.localonly=Beschr\u00e4nke Zugriff auf nur diesen Computer rcm.rc_tracker.tt=Klicken, um Tracker zu durchsuchen rcm.rc_hash.tt=Klicken, um diesen Inhalt herunterzuladen rcm.rc_title.tt=Klicken, um nach diesen Inhalt zu suchen devices.xcode.autoCopy=Automatisch in das Zielverzeichnis kopieren devices.xcode.setcopyto=Setze Zielverzeichnis... devices.xcode.setcopyto.title=W\u00e4hle Zielverzeichnis devices.copy.folder.auto=Kopiere Dateien automatisch in das Zielverzeichnis devices.copy.folder.dest=Zielverzeichnis devices.xcode.mancopy=Kopiere Dateien manuell devices.xcode.show.cat=Nach Kategorie trennen ConfigView.label.alwaysShowLibraryHeader=Zeige immer Tabellenbezeichnung in Bibliothek (Meine Torrents) devices.cat.show=Zeige Kategorien devices.tivo.machine=TiVo-Ger\u00e4tename devices.info.copypending=%1 Datei(en) wartet/warten auf Kopiervorgang device.error.xcodefail=Umwandlung fehlgeschlagen device.error.copyfail=Dateien konnten nicht in das Zielverzeichnis kopiert werden device.error.copytonotset='Zielverzeichnis' nicht gesetzt device.error.copytomissing='Zielverzeichnis' "%1" nicht gefunden device.error.copytonowrite='Zielverzeichnis' "%1" nicht schreibbar device.error.copyfail2=Dateien konnten nicht auf das Zielger\u00e4t kopiert werden v3.deviceview.infobar.line2.psp=Videos werden auf die PSP kopiert, wenn diese verbunden ist. devices.info.copypending2=%1 Datei(en) wartet/warten auf Kopiervorgang. Bitte Ger\u00e4t verbinden. subscriptions.column.nb-subscribers=Abonnementen device.offlinedownloader.view.title= device.od.enable=Aktiviere Offline-Download-Ger\u00e4te device.odauto.enable=Verwalte Downloads automatisch device.odpt.enable=Private Torrents einschliessen devices.contextmenu.od=Offline-Downloading devices.contextmenu.od.auto= devices.contextmenu.od.enable=Aktivieren devices.contextmenu.od.enabled=Aktiviert devices.od.view.heading=Downloads f\u00fcr Offline-Downloading eingeplant DevicesOD.column.od_completion=\u00dcbertragungsfortschritt device.od.turnon.title=Aktiviere Offline-Downloader-Unterst\u00fctzung device.is.disabled=Ger\u00e4te ist deaktiviert device.configure=Konfigurieren... device.od.error.notfound=Ger\u00e4t scheinbar ausgeschaltet device.od.error.opfailstatus=Ger\u00e4tefehler bei Befehl %1: Status %2 device.od.error.opfailexcep=Ger\u00e4tefehler bei Befehl %1: Ausnahme %2 device.od.error.nospace=Kein Speicherplatz auf Ger\u00e4t verf\u00fcgbar oder kein externes Laufwerk verbunden device.od.space=Verf\u00fcgbarer Speicherplatz ConfigView.section.style.forceSIValues=Zeige Zahlen als IEC-Werte entgegen der angezeigten Einheit (z.B. 1MB = 1MiB = 1048576B) ConfigView.label.enableSystrayToolTip=Zeige Download-Statistiken auf Hover devices.activation=Ger\u00e4teaktivierung button.nothanks=Nein danke devices.od.turnon.text1=Es wurde erkannt, dass eine Verbindung mit %1 besteht. devices.od.turnon.text2=Soll %1 das Herunterladen der Dateien fortsetzen, wenn der Computer offline ist? devices.od.turnon.text3=Bitte eine Festplatte mit %1 verbinden, damit dieses Merkmal aktiviert werden kann. devices.od.turnon.learn=Mehr erfahren > devices.router=Router devices.od=Offline-Downloader webui.pairingenable=Aktiviere Paarung webui.group.access=Zugiffskontrolle ConfigView.section.Pairing=Paarung pairing.accesscode=Zugangscode pairing.ac.getnew=Teile neuen Zugangscode zu pairing.ac.getnew.create=Erstellen pairing.host=Hostadresse (DNS-Name) pairing.group.explicit=Ausf\u00fchrliche Attribute pairing.explicit.enable=Aktivieren pairing.explicit.info=Normalerweise m\u00fcssen ausf\u00fchrliche IP-Attribute nicht angegeben werden, da diese automatisch abgeleitet werden k\u00f6nnen.\nDas 'host'-Attribut kann benutzt werden, falls ein DynDNS-Konto und die zugeh\u00f6rige Software vorhanden sind, um die dynamische IP korrekt zu registrieren. pairing.op.fail=Paarung fehlgeschlagen pairing.alloc.fail=Zuteilung von Zugangscode fehlgeschlagen\n%1 pairing.enable=Aktiviere Paarung von Vuze und entfernten Anwendungen / Oberfl\u00e4chen pairing.status.registered=Aktualisierung erfolgreich (%1) pairing.status.pending=Aktualisierung erfolgt um %1 pairing.status.initialising=Initialisieren pairing.status.disabled=Deaktiviert pairing.view.registered=Anklicken, um aktuelle Registrierungsdetails zu sehen webui.pairing.info.n=Paarung deaktiviert. Weitere Informationen unter Verbindung -> Paarung. webui.pairing.info.y=Paarung aktiviert. Weitere Informationen unter Verbindung -> Paarung. webui.enable=Aktivieren (*) ConfigView.section.rss=Lokales RSS subscriptions.rss.enable=Erstelle RSS-Feeds von Abos device.tivo.enable=Aktiviere TiVo-Unterst\u00fctzung Button.removeAll=Alle entfernen label.rename=Bennen %1 um RCM.column.rc_rank=Rang RCM.column.rc_created=Erstellt RCM.column.rc_lastseen=Zuletzt gesehen RCM.column.rc_level=Stufe rcm.view.heading=Schwarmentdeckungen rcm.config.enabled=Aktivieren rcm.config.max_results=Maximale Ergebnisse rcm.config.max_level=Maximale Stufe rcm.search.provider=Schwarm azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_sl_SI.properties0000644000175000017500000020666011301156004026112 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=.torrent Datoteka Main.parameter.usage=Uporaba : java org.gudy.azureus2.cl.Main [oparametri] "Datoteka.torrent" "ciljna pot" Main.parameter.maxUploads=Max \u0161tevilo isto\u010dasnih Oddajanj Main.parameter.maxSpeed=Max Oddajna hitrost v Bajtov/sek MainWindow.menu.file=Datoteka MainWindow.menu.file.open=Odpri MainWindow.menu.file.create=Ustvari Torrent MainWindow.menu.file.create.fromfile=Iz Datoteke MainWindow.menu.file.create.fromdir=Iz Direktorija MainWindow.menu.file.export=Izvozi Torrent... MainWindow.menu.file.import=Uvozi Torrent... MainWindow.menu.file.exit=Izhod MainWindow.dialog.choose.file=Izberi torrent datoteko MainWindow.menu.file.folder=Mapa MainWindow.dialog.choose.folder=Izberi direktorij, ki vsebuje torrent datoteke MainWindow.menu.view=Pogled MainWindow.menu.view.mytorrents=&Moji Torrenti MainWindow.menu.view.configuration=Nastavitve MainWindow.menu.view.console=Konzola MainWindow.menu.view.irc=Irc MainWindow.menu.closealldetails=Zapri vse Podrobnosti MainWindow.menu.closealldownloadbars=Zapri vse Vrstice Prenosov MainWindow.menu.language=Jezik ConfigView.section.language=Jezik MainWindow.menu.help=Pomo\u010d MainWindow.menu.help.about=O Azureusu MainWindow.about.title=O Programu... MainWindow.about.section.developers=Ustvarjalci MainWindow.about.section.translators=Prevajalci MainWindow.about.section.internet=Splet MainWindow.about.internet.homepage=Doma\u010da stran MainWindow.about.internet.sourceforge=Sourceforge Stran MainWindow.about.internet.sourceforgedownloads=Sourceforge datoteke MainWindow.about.internet.bugreports=Prijava hro\u0161\u010dev MainWindow.about.internet.forumdiscussion=Glavni forum MainWindow.about.internet.wiki=Vuze Wiki FAQ (pogosto zastavljena vpra\u0161anja) MainWindow.dialog.choose.savepath=Izberi ciljno pot MainWindow.dialog.choose.savepath_forallfiles=Izberi ciljno pot za VSE datoteke MainWindow.status.latestversion=Zadnja MainWindow.status.latestversion.clickupdate=Poglej za novo verzijo MainWindow.status.unknown=neznano MainWindow.status.checking=preverjam MyTorrentsView.mytorrents=Moji Torrenti TableColumn.header.name=Ime TableColumn.header.size=Velikost TableColumn.header.done=Kon\u010dano TableColumn.header.done.info=Procenti narejene trenutne naloge TableColumn.header.status=Stanje TableColumn.header.status.info=Kaj torrent dela TableColumn.header.seeds=Semena TableColumn.header.seeds.info=# povezanih semen (# vseh semen) TableColumn.header.peers=Sole\u017eniki TableColumn.header.peers.info=# povezanih sole\u017enikov (# vseh sole\u017enikov) TableColumn.header.downspeed=Dol Hitrost TableColumn.header.upspeed=Gor Hitrost TableColumn.header.eta=Do konca TableColumn.header.tracker=Sledilnik TableColumn.header.tracker.info=Stanje sledilnika TableColumn.header.trackernextaccess=Nsalednji dostop sledilnika TableColumn.header.trackernextaccess.info=Kdaj se bo zgosil naslednji dostop do sledilnika TableColumn.header.priority=Prioriteta TableColumn.header.priority.info=Dolo\u010di koliko oddajne pasovne \u0161irine je dano torrentu MyTorrentsView.menu.showdetails=Prika\u017ei &podrobnosti MyTorrentsView.menu.showdownloadbar=Prika\u017ei Vstico Prenosov MyTorrentsView.menu.open=&Odpri MyTorrentsView.menu.setpriority=Nastavi Prioriteto MyTorrentsView.menu.setpriority.high=&Visoka MyTorrentsView.menu.setpriority.low=&Nizka MyTorrentsView.menu.start=Za\u010dni MyTorrentsView.menu.stop=Ustavi MyTorrentsView.menu.remove=&Odstrani MyTorrentsView.menu.changeTracker=Dodaj URL Sledilnika TrayWindow.menu.exit=Izhod TrayWindow.menu.show=Poka\u017ei Vuze SystemTray.menu.exit=Izhod SystemTray.menu.closealldownloadbars=Zapri vse vrstice prenosov SystemTray.menu.show=Prika\u017ei Vuze PeersView.ip=Ip PeersView.ip.info=IP sole\u017enika PeersView.port.info=Port v uporabi PeersView.T.info=l (lokalno): vzpostavil si povezavo, r (odro\u010dno): sole\u017enik je vzpostavil povezavo. PeersView.T.L.tooltip=vzpostavil si povezavo PeersView.T.R.tooltip=sole\u017enik je vzpostavil povezavo. PeersView.I1=Z (Zanimv sole\u017enik) PeersView.I1.info=Te zanima kaj ima drug sole\u017enik? PeersView.C1=Z (zadu\u0161eno s strani sole\u017enika) PeersView.C1.info=\u010ce te sole\u017enik ustavlja pri odjemanju PeersView.pieces=Kosi PeersView.downloadspeed=Dol Hitrost PeersView.download=Dol PeersView.I2=Z (Zanimiv za sole\u017enika) PeersView.I2.info=Je sole\u017enik zainteresiran v kaj ima\u0161? PeersView.C2=D (du\u0161im sole\u017enika) PeersView.C2.info=\u010ce blokira\u0161 sole\u017enik pri odjemanju PeersView.uploadspeed=Gor Hitrost PeersView.uploadspeed.info=Tvoja oddajna hitrost sole\u017eniku PeersView.upload=Gor PeersView.upload.info=Tvoje skupno oddajanje sole\u017eniku. PeersView.statup=Stat Gor PeersView.statup.info=Ocenjena hitrost oddajne hitrosti sole\u017enika PeersView.S.info=Snubbed: Sole\u017enik je lahko "snubbed" ro\u010dno ali avtomati\u010dno (ker ni prina\u0161al podatkov v dovolj visoki hitrosti) PeersView.downloadspeedoverall=Skupna Prenosna Hitrost PeersView.optunchoke=Opcija Nehaj du\u0161iti PeersView.client=Klient PeersView.client.info=Tip BT klienta, ki ga sole\u017enik uporablja PeersView.menu.snubbed=&Prezrt PeersView.title.short=Podrobnosti PeersView.title.full=Podrobnosti ConfigView.section.files=Datoteke ConfigView.label.usefastresume=Uporabi Hitro Nadaljevalni Na\u010din ConfigView.label.incrementalfile=Omogo\u010di prirastno zapisovanje datoteke ConfigView.label.defaultsavepath=Shrani v privzeti direktorij ConfigView.button.browse=Brskaj... ConfigView.dialog.choosedefaultsavepath=Izberi privzeto ciljno mapo ConfigView.section.server=Stre\u017enik ConfigView.section.global=Splo\u0161no ConfigView.label.disconnetseed=Pri setvi odklopi semena ConfigView.label.switchpriority=Pri setvi samodejno-preklopi na ni\u017ejo-prioriteto ConfigView.label.maxdownloads=Max isto\u010dasnih odjemanj ConfigView.label.maxdownloads.tooltip=Vedno bo\u0161 lahko aktivno odjemal \u0161tevilo, ki jo navede\u0161 tukaj, z eno izjemo.\nKon\u010dan torrent s prvo prioriteto lahko odvzame aktivno odjemno mesto, \u010de je to nujno potrebno. ConfigView.label.maxactivetorrents=Max aktivnih torrentov (0 : neomejeno)\n - Novi torrenti nebodo pri\u010deli, \u010de odjema\u0161/oddaja\u0161 ve\u010d ConfigView.label.priorityExtensions=Samodejno-prioritiziraj datoteke s kon\u010dnico\n - npr.: .txt;.nfo;.jpg ConfigView.section.transfer=Prenos ConfigView.label.maxuploads=Privzeto max oddajanj na torrent ConfigView.label.maxuploadspeed=Max oddajna hitrost (skupna) ConfigView.label.saveresumeinterval=Posodobi nadaljevalne podatke vsake ConfigView.unlimited=Neomejeno ConfigView.section.display=Pogled ConfigView.label.opendetails=Samodejno odpri zavihek s podrobnosti ConfigView.label.openbar=Samodejno odpri vrstico prenosov ConfigView.label.closetotray=Zapri - minimira v Odlo\u017ei\u0161\u010de ConfigView.label.minimizetotray=Minimiraj - minimira v Odlo\u017ei\u0161\u010de ConfigView.section.general=Splo\u0161no ConfigView.section.start=Za\u010dni ConfigView.label.showsplash=Prika\u017ei pozdravno okno ConfigView.label.autoupdate=Odpri posodobitveno okno, \u010de je nova razli\u010dica na razpolago ConfigView.label.openconsole=Pri zagonu odpri Konzolo ConfigView.label.openconfig=Pri zagonu odpri Nastavitve ConfigView.label.startminimized=Program za\u017eeni minimiran ConfigView.section.irc=Irc ConfigView.label.ircserver=Stre\u017enik ConfigView.label.ircchannel=Kanal ConfigView.label.irclogin=Psevdonim (nick) ConfigView.section.security=Varnost ConfigView.label.password=Vuze za\u0161\u010diti z geslom\n - Pri zagonu bo program vpra\u0161al za geslo. ConfigView.label.passwordconfirm=Geslo (potrdi) ConfigView.label.passwordmatch=Geslo aktivirano : ConfigView.label.passwordmatchnone=Ne ConfigView.label.passwordmatchno=Ne / Gesla se ne ujemata ConfigView.label.passwordmatchyes=Da ConfigView.button.save=Shrani ConfigView.title.short=Nastavitve ConfigView.title.full=Nastavitve ConsoleView.title.short=Konzola ConsoleView.title.full=Konzola FileItem.write=pi\u0161em FileItem.read=berem FileItem.normal=normalna FileItem.high=visoka FileItem.donotdownload=Ne prenesi FilesView.name=Ime FilesView.size=Velikost FilesView.done=Kon\u010dano FilesView.firstpiece=Prvi kos # FilesView.numberofpieces=# kosov FilesView.pieces=Kosi FilesView.mode=Na\u010din FilesView.priority=Prioriteta FilesView.menu.open=Odpri FilesView.menu.setpriority=Nastavi Prioriteto FilesView.menu.setpriority.high=Visoka FilesView.menu.setpriority.normal=Normalna FilesView.menu.setpriority.skipped=Ne prenesi FilesView.title.short=Datoteke FilesView.title.full=Datoteke GeneralView.section.downloaded=Preneseno GeneralView.label.status.file=Stanje datoteke GeneralView.label.status.pieces=Stanje Kosov GeneralView.section.availability=Razpolo\u017eljivost GeneralView.label.status.pieces_available=Stanje Kosov GeneralView.section.transfer=Prenos GeneralView.section.info=Informacije GeneralView.title.short=Splo\u0161no GeneralView.title.full=Splo\u0161no GeneralView.label.timeelapsed=Preteklo : GeneralView.label.remaining=Do konca: GeneralView.label.downloaded=Odjeto : GeneralView.label.downloadspeed=Odjemalna Hitrost: GeneralView.label.maxuploads=Max Oddajanj : GeneralView.label.uploaded=Oddano : GeneralView.label.uploadspeed=Oddajalna Hitrost : GeneralView.label.seeds=Semena : GeneralView.label.peers=Sole\u017eniki : GeneralView.label.totalspeed=Skupna Hitrost : GeneralView.label.totalspeed.tooltip=Skupna hitrost vseh klientov s katerimi si povezan. GeneralView.label.filename=Ime : GeneralView.label.totalsize=Skupna Velikost : GeneralView.label.savein=Shrani v : GeneralView.label.hash=Zgo\u0161\u010deno sp. : GeneralView.label.numberofpieces=# Kosov : GeneralView.label.size=Velikost : GeneralView.label.tracker=Sledilnik : GeneralView.label.updatein=Posodobitev \u010dez : GeneralView.label.trackerurl=Sledilnikov URL : GeneralView.label.trackerurlupdate=Ro\u010dna Posodobitev GeneralView.label.comment=Komentarji : ManagerItem.waiting=\u010cakam ManagerItem.allocating=Razporejam ManagerItem.checking=Preverjam ManagerItem.ready=Pripravljen ManagerItem.downloading=Odjemam ManagerItem.seeding=Sejem ManagerItem.stopped=Ustavljen ManagerItem.error=Napaka ManagerItem.high=visoka ManagerItem.low=nizka MinimizedWindow.name=Ime: PiecesView.size=Velikost PiecesView.numberofblocks=# Blokov PiecesView.blocks=Bloki PiecesView.completed=Kon\u010dano PiecesView.availability=Razpolo\u017eljivost PiecesView.title.short=Kosi PiecesView.title.full=Kosi SystemTray.tooltip.seeding=%1 sejem, SystemTray.tooltip.downloading=%1 odjemam, DownloadManager.error.filenotfound=Datoteke ni najdena DownloadManager.error.fileempty=Datoteka torrent je prazna DownloadManager.error.filetoobig=Torrent datoteka je prevelika DownloadManager.error.filewithouttorrentinfo=V datoteki ni Torrent informacije DownloadManager.error.unsupportedencoding=Nepodprto kodiranje DownloadManager.error.ioerror=IO Napaka DownloadManager.error.sha1=Algoritem ne obstaja (SHA1) Napaka PeerManager.status.offline=Stanje brez Povezave PeerManager.status.ok=V redu PeerManager.status.checking=preverjam PeerManager.status.finished=Kon\u010dano PeerManager.status.finishedin=Kon\u010dano v MainWindow.upgrade.assistant=Posodobitveni Asistent MainWindow.upgrade.newerversion=Nova razli\u010dica Azureusa je na voljo za prenos MainWindow.upgrade.explanation=Ta asistent bo prenesel novo razli\u010dico v glavno mapo in ponovno zagnal Vuze MainWindow.upgrade.explanation.manual=Posodobite lahko ro\u010dno, tako da zaprete Vuze prenesete novo razli\u010dico in ponovno za\u017eenete Vuze MainWindow.upgrade.step1=Korak 1: Prenese novo razli\u010dico MainWindow.upgrade.step2=Korak 2: Zapre to razli\u010dico in za\u017eene novo razli\u010dico Azureusa MainWindow.upgrade.hint1=Namig:\tKlik na Kon\u010daj naredi vse samodejno MainWindow.upgrade.hint2=Namig:\t\u010ce bi radi Vuze zaprli kasneje, pritisni Prekli\u010di in\n\tpreimenujte Azureus2-new.jar v Azureus2.jar po zaprtju MainWindow.upgrade.error.downloading.hint=Napaka:\tPrenos nove razli\u010dice ni uspel, prosim posodobi ro\u010dno MainWindow.upgrade.section.info=Nova razli\u010dica je na voljo MainWindow.upgrade.section.manual=Ro\u010dna Posodobitev MainWindow.upgrade.section.automatic=Samodejna Posodobitev MainWindow.upgrade.tooltip.progressbar=Potek prenosa je prikazan tukaj Button.next=Naprej Button.finish=Kon\u010daj Button.cancel=Prekli\u010di LocaleUtil.title=Izberi Kodiranje LocaleUtil.section.chooseencoding=Izberi kodiranje za Ime datoteke LocaleUtil.label.chooseencoding=Izberi najbolj prilagojeno kodiranje LocaleUtil.label.hint.doubleclick=Namig: dvoklik na vrstico izbere kodiranje in zapre okno LocaleUtil.label.checkbox.rememberdecision=Zapomni si izbiro za ostala Imena datotek LocaleUtil.column.encoding=Kodiranje IrcClient.copyright=Uporabljam PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Povezujem na IrcClient.connected=Povezan na IrcClient.joining=Se pridru\u017euje IrcClient.channel=Kanal IrcClient.joined=pridru\u017een IrcClient.error=Napaka IrcClient.hasjoined=se je pridru\u017eil IrcClient.haskicked=je brcnil IrcClient.hasleft=je od\u0161el IrcClient.nowknown=je poznan kot IrcClient.topicforchannel=Tema za kanal IrcClient.disconnected=Izgubil povezavo od IrcClient.noNick=Nisi nastavil psevdonima (nick). To lahko nastavi\u0161 v Nastavitvah IrcView.actionnotsupported=Ta akcija ni podprta IrcView.clientsconnected=uporabniki IrcView.privateto=Za IrcView.privatefrom=Od IrcView.noticefrom=Opozorilo : IrcView.errormsg=Napa\u010den Syntax na /msg : /msg uporabni\u0161ki text IrcView.help=Veljavni ukazi so :\n . /help : prika\u017ee to sporo\u010dilo\n . /nick | /name : spremeni tvoje ime \n . /me action : po\u0161lje akcijo \n . /msg nick message : po\u0161lje privatno sporo\u010dilo osebi \n . /r message : odgovori na zadnje privatno sporo\u010dilo\n . /join #channel : spremeni trenutni kanal PasswordWindow.title=Vuze je zaklenjen PasswordWindow.passwordprotected=Vuze je za\u0161\u010diten z geslom.\nZa prikaz Vuze ovega okna, vnesi geslo tukaj : Button.ok=V Redu TrackerChangerWindow.title=Dodaj Sledilnik TrackerChangerWindow.newtracker=Vnesi nov url sledilnika PeersView.discarded=Zavr\u017eeno PeersView.discarded.info=Podatki, ki si jih nekako dobil, \u010deprav jih nisi potreboval, zato si se jih znebil. discarded=zavr\u017eeno MyTorrentsView.menu.move=&Prestavi MyTorrentsView.menu.moveUp=&Gor MyTorrentsView.menu.moveDown=&Dol GeneralView.label.hashfails=Hash Odpoved : GeneralView.label.shareRatio=Delilno Razmerje : ConfigView.section.downloadManagement=Upravljanje Prenosov ConfigView.label.startRatioPeers=Pri\u010dni setev, ko je manj kot 1 seme za ConfigView.text.neverStop=Ne Ustavi ConfigView.text.neverStart=Ne Za\u010dni ConfigView.text.peers=Sole\u017eniki ConfigView.label.checkOncompletion=Preveri kose, ko se prenos kon\u010da wizard.title=Ustvari torrent wizard.previous=< Nazaj wizard.next=Naprej > wizard.finish=Kon\u010daj wizard.mode=Sledilnik / Na\u010din wizard.tracker=Sledilnik: wizard.invalidurl=Ta URL ni pravilen wizard.singlefile=Ena datoteka wizard.singlefile.help=Ustvari torrent iz datoteke wizard.directory=Mapa wizard.directory.help=Ustvari torrent iz mape wizard.choosefile=Izberi datoteko wizard.file=Datoteka : wizard.browse=Brskaj... wizard.choosedirectory=Izberi direktorij wizard.invalidfile=Nepravilna Datoteka! wizard.invaliddirectory=Nepravilen Direktorij! wizard.torrentFile=Torrent datoteka wizard.choosetorrent=Izberi torrent datoteko, ki bo ustvarjena wizard.information=Informacija wizard.notimplemented=\u0160e ni implementirano wizard.progresstitle=Ustvarjam Torrent datoteko wizard.savingfile=Shranjujem Datoteko... wizard.filesaved=Datoteka shranjena. wizard.close=Zapri Torrent.create.progress.piecelength=Dol\u017eina kosa: Torrent.create.progress.piececount=\u0160tevilo kosov: Torrent.create.progress.totalfilesize=Skupna velikost: Torrent.create.progress.totalfilecount=Skupno \u0161tevilo datotek: Torrent.create.progress.parsingfiles=Raz\u010dlenjujem datoteke Torrent.create.progress.hashing=Razpr\u0161ujem datoteke MainWindow.upgrade.downloadingfrom=Odjemam iz : MainWindow.menu.view.ipFilter=IP Filtri ConfigView.section.ipfilter=IP Filtri ConfigView.section.ipfilter.description=Opis ConfigView.section.ipfilter.start=Za\u010detni Ip ConfigView.section.ipfilter.end=Kon\u010dni Ip ConfigView.section.ipfilter.add=Dodaj ConfigView.section.ipfilter.remove=Odstrani ConfigView.section.ipfilter.edit=Uredi ConfigView.section.ipfilter.save=Shrani ConfigView.section.ipfilter.editFilter=Uredi Filter ConfigView.section.ipfilter.enable=Omogo\u010di PeersView.menu.close=Zapri seedmore.title=Torrent ni dovolj sejen (deljen) seedmore.shareratio=Tvoje delilno razmerje s tem torrentom je seedmore.uploadmore=Delilno razmerje datoteke pod 100%, slabo vpliva na BitTorent omre\u017eje. Bolje,da to\n datoteko deli\u0161 \u0161e nekaj \u010dasa.\nSigurno \u017eeli\u0161 Nadaljevati? ConfigView.label.showpopuponclose=Prika\u017ei potrdilno okno pri ustavitvi setve z delilnim razmerjem manj kot 1 ConfigView.label.startNumSeeds=\nPri\u010dni setev, \u010de je manj kot\n - Razveljavi vsa pravila ConfigView.label.seeds=semena ConfigView.section.seeding=Sejem MyTorrentsView.menu.removeand=Odstrani in MyTorrentsView.menu.removeand.deletetorrent=Izbri\u0161i .torrent MyTorrentsView.menu.removeand.deletedata=Izbri\u0161i Datoteke MyTorrentsView.menu.removeand.deleteboth=Izbri\u0161i Oboje deletedata.title=!!! Opozorilo !!! deletedata.message1=Izbrisali boste vse PODATKE iz :\n MainWindow.menu.file.configure=Nastavitveni \u010carovnik configureWizard.title=Nastavitveni \u010carovnik configureWizard.welcome.title=Dobrodo\u0161li v Azureusov Nastavitveni \u010carovnik configureWizard.welcome.message=Ta \u010darovnik ti bo pomagal nastaviti Vuze za vsakdanjo uporabo. Napredne Nastavitve lahko spremni\u0161 v meniju Pogled>Nastavitve. configureWizard.transfer.title=Nastavitve za Prenos in Povezave configureWizard.transfer.hint=Namig : Uporaba malo manj od celotne hitrostne zmo\u017enosti tvoje povezave je najbolj\u0161a nastavitev. configureWizard.transfer.message=Spodaj izberi primerno povezavo. Izberi povezavo, ki bo dovolila dovolj oddajanja, druga\u010de se bo upo\u010dasnila hitrost odjemanja. Ker se hitrost oddajanja nana\u0161a na EN torrent, ki ga odjema\u0161, se lahko pri ve\u010dih isto\u010dasno odjemanih torrentih pojavi upad hitrosti odjemanja. Priporo\u010dam uporabo 5KB/s na torrent kot NUJNI minimum. Hitreje kot oddaja\u0161, hitreje lahko odjema\u0161 (glede na torrentovo hitrost). configureWizard.transfer.connection=Povezava configureWizard.transfer.connection.0=Prilagojeno configureWizard.transfer.connection.2=adsl/kabel xxx/128kbps configureWizard.transfer.connection.3=adsl/kabel xxx/256kbps configureWizard.transfer.connection.4=adsl/kabel xxx/384 kbps configureWizard.transfer.connection.5=adsl/kabel xxx/512 kbps configureWizard.transfer.connection.6=adsl/kabel xxx/768 kbps configureWizard.transfer.connection.7=adsl/kabel xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Max Hitrost Gor (KB/s) configureWizard.transfer.maxActiveTorrents=Max Aktivnih configureWizard.transfer.maxDownloads=Max Odjemanj configureWizard.transfer.maxUploadsPerTorrent=Max Oddajanj na Torrent configureWizard.nat.title=NAT / Stre\u017enikovi porti configureWizard.nat.message=Da iz BitTorrenta iztisne\u0161 najve\u010d, je priporo\u010dljivo, da je klient s spleta popolno dostopen. Obseg privzetih bittorent portov je od 6881 do 6889. To orodje testira in / ali spremeni privzete porte. \u010ce potekajo aktivni prenosi, nekateri porti ne bodo dostopni. configureWizard.nat.test=Testiraj configureWizard.nat.testing=Testiram port configureWizard.nat.ok=V Redu configureWizard.nat.ko=NAT Napaka configureWizard.nat.unable=Ni mo\u017eno testirati configureWizard.file.title=Torrenti / Datoteke configureWizard.file.message1=Vuze bo shranil torrente v dolo\u010deno mapo, ki jo lahko izberete tukaj: configureWizard.file.path=Ciljna Pot configureWizard.file.browse=Brskaj configureWizard.file.message2=Vuze je sposoben takoj\u0161njega nadeljevanja datotek, tako da v tvoje torrente doda podatke za nadaljevanje. Z uporabo te mo\u017enosti, lahko program nadaljuje tudi deloma prene\u0161ene kose. configureWizard.file.fastResume=Omogo\u010di hitro Nadaljevanje configureWizard.file.invalidPath=Napa\u010den direktorij configureWizard.finish.title=Kon\u010dano configureWizard.finish.message=Vuze je zdaj nastavljen, u\u017eivaj! wizard.close.confirmation=Potrditev wizard.close.message=\u017deli\u0161, da se ta \u010darovnik nalo\u017ei naslednji\u010d ko po\u017eene\u0161 Vuze exportTorrentWizard.title=Izvozi Torrent v XML exportTorrentWizard.torrentfile.title=Izbira Vhodnega Torrenta exportTorrentWizard.torrentfile.message=Izberi torrent za izvoz exportTorrentWizard.torrentfile.path=Ciljna Pot exportTorrentWizard.torrentfile.browse=Brskaj exportTorrentWizard.torrentfile.invalidPath=Napa\u010dna .torrent datoteka exportTorrentWizard.exportfile.title=Izbira Izvozne Datoteke exportTorrentWizard.exportfile.message=Izberi datoteko za izvoz v exportTorrentWizard.exportfile.path=Ciljna Pot exportTorrentWizard.exportfile.browse=Brskaj exportTorrentWizard.exportfile.invalidPath=Napa\u010dna izvozna datoteka exportTorrentWizard.finish.title=Kon\u010dano exportTorrentWizard.finish.message=Izvoz uspe\u0161no zaklju\u010den exportTorrentWizard.process.inputfilebad.title=Napa\u010dna Torrent Datoteka exportTorrentWizard.process.inputfilebad.message=Pri dostopanju vhodne datoteke je pri\u0161lo do napake: exportTorrentWizard.process.outputfileexists.title=Datoteka \u017ee obstaja exportTorrentWizard.process.outputfileexists.message=Datoteka \u017ee obstaja - prepi\u0161em? exportTorrentWizard.process.torrentfail.title=Odpoved Branja Torrenta exportTorrentWizard.process.exportfail.title=Odpoved Izvoza Torrenta exportTorrentWizard.process.unknownfail.title=Nepri\u010dakovana napaka importTorrentWizard.title=Uvozi torrent importTorrentWizard.torrentfile.title=Izbira Vhodnega Torrenta importTorrentWizard.torrentfile.message=Izberi, torrent v katerega bo izvo\u017een importTorrentWizard.torrentfile.path=Ciljna Pot importTorrentWizard.torrentfile.browse=Brskaj importTorrentWizard.torrentfile.invalidPath=Napa\u010dna .torrent datoteka importTorrentWizard.importfile.title=Izbira Uvozne Datoteke importTorrentWizard.importfile.message=Izberi datoteko za uvoz importTorrentWizard.importfile.path=Ciljna Pot importTorrentWizard.importfile.browse=Brskaj importTorrentWizard.importfile.invalidPath=Napa\u010dna uvozna datoteka importTorrentWizard.finish.title=Kon\u010dano importTorrentWizard.finish.message=Uvoz uspe\u0161no zaklju\u010den importTorrentWizard.process.inputfilebad.title=Napa\u010dna uvozna datoteka importTorrentWizard.process.inputfilebad.message=Pri dostopanju vhodne datoteke je pri\u0161lo do napake: importTorrentWizard.process.outputfileexists.title=Datoteka \u017ee obstaja importTorrentWizard.process.outputfileexists.message=Datoteka \u017ee obstaja - prepi\u0161em? importTorrentWizard.process.torrentfail.title=Odpoved Zapisa Torrenta importTorrentWizard.process.importfail.title=Odpoved Uvoza Torrenta importTorrentWizard.process.unknownfail.title=Nepri\u010dakovana napaka ConfigView.label.bindip=Ve\u017ei na lokalni IP naslov or interface ConfigView.label.zeronewfiles=Razporedi in ni\u010di nove datoteke ConfigView.label.zeronewfiles.tooltip=Minimira drobitev (fragmentation) ConfigView.section.stats=Statistike ConfigView.section.stats.enable=Omogo\u010di ConfigView.section.stats.defaultsavepath=Ciljna pot za Statistike ConfigView.section.stats.choosedefaultsavepath=Izberi ciljno mapo za statistike ConfigView.section.stats.savefreq=Shrani frekvenco ConfigView.section.stats.hours=ure ConfigView.section.stats.seconds=sek ConfigView.section.stats.savefile=Ime datoteke statistik MyTorrentsView.menu.export=&Izvozi XML... MyTorrentsView.menu.host=&Gostovanje... ManagerItem.finishing=Kon\u010dujem ConfigView.dialog.choosedefaulttorrentpath=Izberi privzeti torrent direktorij ConfigView.dialog.choosemovepath=Izberi direktorij za prestavitev ConfigView.label.movecompleted=Prestavi kon\u010dane datoteke ConfigView.label.savetorrents=Shrani torrent datoteke MainWindow.menu.view.mytracker=Moj &Sledilnik MyTrackerView.title.full=Moj Sledilnik MyTrackerView.name=Ime MyTrackerView.tracker=Sledilnik MyTrackerView.status=Stanje MyTrackerView.status.started=V teku MyTrackerView.status.stopped=Ustavljen MyTrackerView.peers=Sole\u017eniki MyTrackerView.seeds=Semena MyTrackerView.announces=Obvestila MyTrackerView.uploaded=Oddano MyTrackerView.downloaded=Odjeto MyTrackerView.left=Ostalo ConfigView.section.style=Vmesnik ConfigView.section.style.useCustomTabs=Uporabi zapirajo\u010de zavihke (potreben ponovni zagon) MainWindow.menu.view.plugins=&Vklju\u010dki fileDownloadWindow.saveTorrentIn=Shrani Torrent datoteko v fileDownloadWindow.title=Vuze - Torrent Odjemalnik fileDownloadWindow.downloading=Odjemam Iz : fileDownloadWindow.status=Stanje : fileDownloadWindow.state_initializing=Inicializacija fileDownloadWindow.state_downloading=Odjemam fileDownloadWindow.state_error=Napaka : MainWindow.menu.file.open.url=URL openUrl.title=Vuze - Odpri URL MyTorrentsView.menu.host.error.title=Torrent Gostovanje je Odpovedalo MyTorrentsView.menu.host.error.message=Slednja napaka se je pojavila pri gostovanju torrenta ConfigView.section.tracker=Sledilnik ConfigView.section.tracker.pollinterval=Povpra\u0161evalni interval Sledilnega klienta (sek) ConfigView.section.tracker.publishenable=Objavi torrent podrobnosti "" ConfigView.section.tracker.ip=Sledilnikov zunanji IP naslov ConfigView.section.style.enableXPStyle=Omogo\u010di XP stil (potreben ponovni zagon) ConfigView.section.tracker.checkip=Preveri Naslov... ipCheckerWizard.title=Preveri IP - \u010carovnik ipCheckerWizard.service=Storitev ipCheckerWizard.chooseService=Izberi eno od nanizanih IP preverjevalnih storitev ipCheckerWizard.explanations=Ta \u010darovnik lahko uporabi\u0161 pri poizvedbi svojega zunanjega IP naslova. \u010ce ima\u0161 dinami\u010den IP naslov, ti priporo\u010dam, da odpre\u0161 ra\u010dun z Dynamic DNS Service. Ponudniki teh storitev so napisani spodaj, uporabi povezave za odprtje ra\u010duna (kjer je podprto). Potem izpolni polje IP naslova s tvojim dinami\u010dnim imenom gostujo\u010dega ra\u010dunalnika (hostname) (npr. myhostname.dyndns.org). Za to je potreben program, ki samodejno posodobi tvojo Dinami\u010dno DNS Storitev s tvojim IP naslovom. Tako lahko gosti\u0161 torrente, \u010deprav se tvoj IP naslov spreminja. ipCheckerWizard.service.description=Opis : ipCheckerWizard.service.url=Povezava : ipCheckerWizard.progresstitle=Preverjam IP ipCheckerWizard.checkComplete=Zaklju\u010den IP : ipCheckerWizard.checkFailed=Odpovedal, razlog : wizard.tracker.local=Uporabi Azureusov Vgrajeni Tracker wizard.tracker.external=Uporabi zunanji Tracker wizard.tracker.howToLocal=\tPojdi na 'Nastavitve>Tracker', da ga omogo\u010di\u0161 wizard.announceUrl=Objavi URL : IPChecker.external.service.discoveryvip.description=Discoveryvip - samo preverjanje IP naslova IPChecker.external.httpinvalidresponse=Napa\u010den HTTP odziv IPChecker.external.loadingwebpage=Nalaganje strani IPChecker.external.analysingresponse=Analiziram odziv IPChecker.external.addressextracted=Izvle\u010den IP naslov IPChecker.external.httploadfail=Napaka pri nalaganju strani IPChecker.external.timeout=\u010casovni iztek IPChecker.external.ipnotfound=IP naslov ne obstaja ConfigView.section.tracker.pollintervalmax=Maksimum ConfigView.section.tracker.pollintervalincby=Pove\u010daj za ConfigView.section.tracker.pollintervalincper=Vsakih 'n' klientov splash.loadingImages=Nalagam Slike splash.initializeGui=Inicializiram Glavno Okno splash.openViews=Odpiram Poglede splash.plugin=Nalagam Vklju\u010dke : configureWizard.nat.tooManyPorts=Preve\u010d portov za test (9 max) ConfigView.section.color=Barvna Shema MyTorrentsView.menu.publish=&Objavi... MyTrackerView.status.published=Objavljeno MyTrackerView.completed=Kon\u010dano MainWindow.menu.file.open.torrentnodefault=.torrent datoteka (Ne Shrani privzeto) wizard.comment=Komentarji ConfigView.label.movetorrent=Prestavi .torrent ConfigView.section.file.decoder.label=Privzeto torrent kodiranje ko \npotrebna izbira ConfigView.section.file.decoder.nodecoder=Nobeden IPChecker.external.service.no-ip.name=Ni-IPja IPChecker.external.service.no-ip.description=Dinami\u010dni in stati\u010dni DNS ponudnik\n(ni zastonj dostopne 'preveri naslov' storitve) ConfigView.section.tracker.publicenable=Omogo\u010di zunanje torrente # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Prika\u017ee \u0161tevilo dostopnih kopij vsakega kosa.\n\u010de je to \u0161tevilo manj kot 1, ne vidi\u0161 ene cele kopije datoteke (in bo\u0161 morda imel te\u017eave pri odjemanju) GeneralView.label.trackerurl.tooltip=Klikni, da kopira\u0161 objavitveni url v odlo\u017ei\u0161\u010de GeneralView.label.trackerurlopen.tooltip=Klikni, da odpre\u0161 glavno stran sledilnika # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Posodobi GUI vsakih ConfigView.section.style.graphicsUpdate=Posodobi Grafi\u010dne vrstice vsakih N GUI posodobitev ConfigView.section.style.reOrderDelay=Preuredi tabele vsakih N GUI posodobitev [0: nikoli] ConfigView.section.style.reOrderDelay.never=Nikoli ConfigView.section.logging=Bele\u017eim ConfigView.section.logging.enable=Omogo\u010di bele\u017eenje v datoteko ConfigView.section.logging.logdir=Direktorij datoteke z dnevnikom ConfigView.section.logging.choosedefaultsavepath=Izberi direktorij za shranitev GeneralView.label.updatein.querying=povpra\u0161ujem... configureWizard.nat.sharePort=Uporabi en sam deljen dohodni port za vse torrente ConfigView.section.logging.maxsize=Maksimalna velikost dnevnika ConfigView.section.tracker.passwordenableweb=Omogo\u010di geslo na sledilni\u0161ki mre\u017ei ConfigView.section.tracker.passwordenabletorrent=Omogo\u010di geslo za torrente ConfigView.section.tracker.username=Uporabni\u0161ko ime ConfigView.section.tracker.password=Geslo columnChooser.title=Izberi stolpce za prikaz columnChooser.move=Povleci vrstice, da jih preuredi\u0161 columnChooser.apply=Uveljavi columnChooser.columnname=Ime stolpca columnChooser.columndescription=Opis TableColumn.header.shareRatio=Delitveni nivo MyTorrentsView.menu.editTableColumns=Choose the columns to display wizard.operationfailed=Operacija neuspe\u0161na authenticator.title=Potrebna avtentikacija authenticator.tracker=Sledilnik authenticator.user=Uporabni\u0161ko ime authenticator.password=Geslo ConfigView.label.allowSendVersion=Dovoli Azureusu da anonimno po\u0161lje \u0161tevilko verzije in naklju\u010dni ID, ko preverja za novo verzijo wizard.hint.mode=Namig:\tLahko Povle\u010de\u0161 in Spusti\u0161 eno datoteko ali mapo v ta \u010darovnik\n\tda izbere\u0161 datoteko ali mapo wizard.hint.file=Namig:\tLahko izbere\u0161 eno datoteko s Povleci in Spusti wizard.hint.directory=Namig:\tLahko izbere\u0161 eno mapo s Povleci in Spusti MainWindow.menu.help.checkupdate=Check for program update TableColumn.header.down=Odjeto TableColumn.header.up=Oddano ConfigView.section.tracker.passwordenabletorrent.info=Potrebuje primeren BitTorrent klient (npr. Vuze ConfigView.section.style.confirmationOnExit=Poka\u017ei pritrditveni dialog ob izhodu MainWindow.dialog.exitconfirmation.title=Zapusti Vuze MainWindow.dialog.exitconfirmation.text=Res \u017eeli\u0161 zapustiti Vuze TrayWindow.menu.stopalldownloads=Ustavi vse odjemke ConfigView.section.tracker.sslport.info=Glej FAQ za nadalnje informacije wizard.tracker.ssl=Uporabi SSL ConfigView.label.playdownloadfinished=Predvajaj zvok, ko je odjem kon\u010dan TableColumn.header.pieces=Kosov TableColumn.header.pieces.info=Grafi\u010dna vrstica, ki predstavlja katere kose si \u017ee odjel TableColumn.header.completion=Kon\u010dano TableColumn.header.completion.info=Grafi\u010dna reprezentacija % odjetega ConfigView.section.style.showdownloadbasket=Prika\u017ei Odjemni ko\u0161 (Povleci in Spusti .torrente) ConfigView.section.style.alwaysShowTorrentFiles=Vedno prika\u017ei Torrent datoteke v Podrobnosti/Datoteke wizard.multitracker=Dodaj Multi-Sledilnikovo informacijo v torrent wizard.multitracker.title=Multi-Sledilnik wizard.multitracker.configuration=Nastavitve Multi-Sledilnika wizard.multitracker.new=Nov... wizard.multitracker.delete=Izbri\u0161i wizard.multitracker.group=Skupina sledilnikov wizard.multitracker.edit.title=Urejevalnik Multi-Sledilnikov wizard.multitracker.edit.name=Ime wizard.multitracker.edit.save=Shrani wizard.multitracker.edit.newgroup=Nova skupina wizard.multitracker.edit.deletegroup=Izbri\u0161i wizard.multitracker.edit.newtracker=Nov sledilnik wizard.multitracker.edit.deletetracker=Izbri\u0161i wizard.multitracker.edit.edit=Uredi wizard.addingmt=Dodajam Multi-Sledilnikov info wizard.multitracker.noannounce=Objavljen URL ni prisoten na tvojem seznamu sledilnikov MyTorrentsView.menu.recheck=Ponovno preveri iconBar.showDownloadBar.tooltip=Prika\u017ei vrstico odjemanja iconBar.start.tooltip=Za\u010dni iconBar.stop.tooltip=Ustavi iconBar.remove.tooltip=Odstrani iconBar.openNoDefault.tooltip=Odpri .torrent datoteko (brez privzetega shranjevanja) iconBar.openURL.tooltip=Odpri URL iconBar.openFolder.tooltip=Odpri mapo iconBar.new.tooltip=Ustvari torrent iconBar.up.tooltip=Prestavi gor iconBar.down.tooltip=Prestavi dol iconBar.run.tooltip=Odpri iconBar.host.tooltip=Gostuj iconBar.publish.tooltip=Objavi MyTorrentsView.menu.editTracker=&Uredi sledilnikov URL(je) GeneralView.menu.selectTracker=Izberi ConfigView.section.stats.xslfile=XSL ime datoteke ConfigView.section.stats.xslfiledetails=To bo vklju\u010deno v statistiko pod zavihtek ConfigView.label.savetorrentbackup=Shrani Backup ConfigView.section.tracker.forceport=Prisili gostujo\u010de zunanje torrente na privzeti port ConfigView.section.ipfilter.allow=DOVOLI te vrednosti (privzeto je NE DOVOLI) ConfigView.section.ipfilter.list.inrange=je bil v dosegu ConfigView.section.ipfilter.list.notinrange=ni bil v dosegu ConfigView.section.ipfilter.list.title=Seznam blokiranih IPjev ConfigView.label.allowsameip=Dovoli ve\u010d povezav iz istega IPja ConfigView.label.allowsameip.tooltip=Vklju\u010di samo \u010de potrebuje\u0161.\nTo je za\u0161\u010dita pred pijavkami (ko izklju\u010deno). ManagerItem.superseeding=Super-sejem ConfigView.label.userSuperSeeding=Uporabi super sejanje PeersView.uniquepiece=Kos (Super-sejalni na\u010din) PeersView.uniquepiece.none=Nobeden PeersView.timetosend=\u010cas do ponovnega po\u0161iljanja kosa (Super-sejalni na\u010din) ConfigView.section.style.addurlsilently=Odpri URL tiho (brez dialoga) ConfigView.section.style.addurlsilently.tooltip=Opozorilo: glavno okno ne bo spet vidno \u010de aktivira\u0161!\n\u010ce izgubi\u0161 sistemsko ikono (zraven ure), mora\u0161 deaktivirati to nastavitev. ConfigView.section.file.decoder.prompt=Vedno vpra\u0161aj, ko je na voljo izbira kodiranja ConfigView.section.file.decoder.prompt.tooltip=Vedno prika\u017ei dialog, ko je na voljo izbira kodiranja MyTorrentsView.menu.moveTop=&Vrh MyTorrentsView.menu.moveEnd=&Dno ConfigView.label.moveonlyusingdefaultsave=samo \u010de v privzet podatkovni direktorij ConfigView.label.moveonlyusingdefaultsave.tooltip=Prestavi samo, \u010de so odjeti podatki v privzetem podatkovnem direktoriju ConfigView.label.watchtorrentfolder=Uvozi nove .torrente avtomati\u010dno ConfigView.label.watchtorrentfolder.tooltip=Redno preverjaj zaa nove .torrente ConfigView.label.watchtorrentfolderinterval.tooltip=Premor dokler ne bo mapa \u0161e enkrat pregledana ConfigView.dialog.choosewatchtorrentfolderpath=Prosim izberi .torrent mapo za uvoz ConfigView.label.startwatchedtorrentsstopped=Za\u010dni ustavljeno ConfigView.label.startwatchedtorrentsstopped.tooltip=Dodaj nove torrente v USTAVLJENEM stanju ConfigView.section.plugins=Vklju\u010dki wizard.maketorrent.filesize=Velikost datotek(e) wizard.maketorrent.piececount=\u0160tevilo kosov wizard.maketorrent.piecesize=Velikost kosa wizard.maketorrent.auto=Avto MainWindow.menu.view.stats=&Statistika SpeedView.title.full=Aktivnost SpeedView.downloadSpeed.title=Hitrost odjemanja SpeedView.uploadSpeed.title=Oddajna hitrost ConfigView.section.style.useSIUnits=Uporabi IEC enote (KB -> KiB itd.) iconBar.top.tooltip=Prestavi na vrh iconBar.bottom.tooltip=Prestavi na dno TableColumn.header.health=Zdravje MyTorrentsView.menu.health=O Zdravju health.explain.grey=pomeni, da torrent ne deluje (odjema ali oddaja) health.explain.red=pomeni, da nisi povezan z nobenim sole\u017enikom pri odjemanju health.explain.blue=pri odjemanju pomeni, da si povezan z nekaj sole\u017eniki vendar sledilnik ne deluje\npri sejanju pomeni, da \u0161e nisi povezan z nobenim sole\u017enikom health.explain.yellow=pomeni, da je sledilnik vredu, da si povezan s sole\u017eniki toda nima\u0161 oddaljene povezave.\nMorda ima\u0161 NAT problem, \u010de so tvoji torrenti vedno v rumenem stanju. health.explain.green=pomeni, da je vse vredu. ConfigView.section.style.alwaysRefreshMyTorrents=Vedno osve\u017ei Moje Torrente ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Ta mo\u017enost bo osve\u017eila pogled Moji Torrenti tudi, \u010de niso prikazani (uporabno za dolo\u010dene mIRC vklju\u010dke) # #2.0.7.0 # security.certtruster.title=Opozorilo varnostnega certifikata security.certtruster.intro=Varnostni certifikat je bil izdan v dru\u017ebi, ki ji ne zaupa\u0161 security.certtruster.resource=Surovina: security.certtruster.issuedto=Izdano: security.certtruster.issuedby=Izdal: security.certtruster.prompt=Mu \u017eeli\u0161 zaupati? security.certtruster.yes=Da security.certtruster.no=Ne ConfigView.section.tracker.torrentsperpage=Koliko torrentov na stran? [0: neomejeno] MainWindow.menu.file.share=&Deli MainWindow.menu.file.share.file=&Datoteka... MainWindow.menu.file.share.dir=M&apa... MainWindow.menu.file.share.dircontents=Vsebina mape... MainWindow.menu.file.share.dircontentsrecursive=Vsebina mape (&ponavljajo\u010de)... MainWindow.dialog.share.sharefile=Izberi datoteko za deljenje MainWindow.dialog.share.sharedir=Izberi mapo za deljenje MainWindow.dialog.share.sharedircontents=Izberi vsebino mape za deljenje MainWindow.dialog.share.sharedircontents.recursive=Ponavljajo\u010d globalmanager.download.remove.veto=Akcija odstranjevanja je dobila veto plugin.sharing.download.remove.veto=Ta odjemek je rezultat deljenih potreb\u0161\u010din.\nDa odstrani\u0161 odjemek, odstrani asociirane deljene potreb\u0161\u010dine.: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Glavni ConfigView.section.tracker.web=Internet ConfigView.label.prioritizefirstpiece=Daj prioriteto prvemu kosu datotek(e) ConfigView.label.prioritizefirstpiece.tooltip=Posku\u0161a najprej odjeti za\u010detek datoteke.\nZa podporo zgodnjemu predogledu ConfigView.section.file.confirm_data_delete=Potrdi pri brisanju podatkov ConfigView.section.file.confirm_data_delete.tooltip=Potrdi brisanje podatkov pri uporabi 'Odstrani in izbri\u0161i...' TrayWindow.menu.startalldownloads=Za\u010dni vse odjemke sharing.progress.title=Delitveni napredek sharing.progress.hide=Skrij MainWindow.menu.view.myshares=Moje deljeno MySharesView.title.full=Moje deljeno MySharesView.name=Ime MySharesView.type=Tip MySharesView.type.file=Datoteka MySharesView.type.dir=Mapa MySharesView.type.dircontents=Vsebina mape MySharesView.type.dircontentsrecursive=Vsebina mape (ponavljajo\u010de) MySharesView.menu.remove=Odstrani ConfigView.section.tracker.extensions=Kon\u010dnice ConfigView.section.tracker.sendpeerids=Po\u0161lji identiteto sole\u017enika odjemnikom ConfigView.section.tracker.enableudp=Omogo\u010di UDP sledilni\u0161ki protokol plugin.sharing.torrent.remove.veto=Ta registracija sledilnika je rezultat deljene surovine.\nDa odstrani\u0161 odjemek odstrani povezane deljenke.: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Odjem ne more biti odstranjen, ker \u0161e ni ustavljen plugin.sharing.remove.veto=Te deljene potreb\u0161\u010dine so pod-deljene potreb\u0161\u010dine 'vsebine mape' deljenjih potreb\u0161\u010din in zato ne morejo biti izbrisane.\nIzbri\u0161i glavni deljeni meni. GeneralView.label.hash.tooltip=Klikni, da kopira\u0161 hash v odlo\u017ei\u0161\u010de ConfigView.section.tracker.maxpeersreturned=Maksimum vrnjenih peerov [0: neomejeno] ConfigView.label.serverport=Dohodni TCP poslu\u0161alni port configureWizard.nat.server.tcp_listen_port=Dohodni TCP poslu\u0161alni Port ConfigView.section.sharing=Deljenje ConfigView.section.sharing.usessl=Uporabi SSL za deljene potreb\u0161\u010dine (potrebuje konfiguracijo sledilnika) ConfigView.section.style.dropdiraction=Povleci in Spusti akcija za mape ConfigView.section.style.dropdiraction.opentorrents=Odpri Torrente ConfigView.section.style.dropdiraction.sharefolder=Delitvena mapa ConfigView.section.style.dropdiraction.sharefoldercontents=Delitvena vsebina # # 2.0.7.x # Categories.all=Vse Categories.uncategorized=Nekategorizirano CategoryAddWindow.message=Napi\u0161i ime nove kategorije CategoryAddWindow.title=Dodaj novo kategorijo ConfigView.label.autoSeedingIgnoreInfo=ignorirani torrenti grejo na dno sejalne vrste. Ne za\u017eenejo se avtomati\u010dno. Pravila ignoriranja ne veljajo za torrente, ki imajo prvo prioriteto. \u010ce ni druga\u010de povedano, uporabi vrednost 0, da onesposobi\u0161 pravilo. ConfigView.label.directory=Mapa ConfigView.label.disconnetseed.tooltip=Pri sejanju torrenta izklju\u010di kakr\u0161nekoli druge kliente, ki prav tako sejejo.\nNi potrebno, da se pogovarjajo s tabo. ConfigView.label.ignoreCase=Ignoriraj veliko/malo za\u010detnico ConfigView.label.ignoreSeeds=Ignoriraj torrente z vsaj ConfigView.label.importdirectory=Mapa za donos ConfigView.label.minPeersToBoostNoSeeds.tooltip=Torrenti brez semen ali z manj semen kot dolo\u010di\u0161\n bodo na dnu vrste. ConfigView.label.minPeersToBoostNoSeeds=Ni\u017eji sejalni rank za torrente brez semen ali z manj kot ConfigView.label.minSeedingTime.tooltip=Sejalni ranki lahko valovijo pogosto v kratkem \u010desovnem intervalu, kar v\u010dasih povzro\u010di, da se torrent avtomati\u010dno za\u010dne in ustavi ter da na \u010dakanje takoj zatem.\nTo razre\u0161i problem, tako da torrent prisili ostati v sejalnem stanju za dolo\u010den \u010das. \u0160e vedno pa ga lahko ustavi\u0161 ro\u010dno. ConfigView.label.minSeedingTime=Minimalni sejalni \u010das v sekundah ConfigView.label.minSpeedForActiveDL.tooltip=Odjemno mesto je vedno v uporabi prvih 30 sekund\npo za\u010detku nedokon\u010danega torrenta. ConfigView.label.minSpeedForActiveDL=Ne \u0161tej torrente, kot da uporabljajo odjemno mesto, \u010de je njihova hitrost pod ConfigView.label.peers=sole\u017eniki ConfigView.label.queue.debuglog=Zapisnik informacije debug ConfigView.label.queue.debuglog.info=Doda \u010dakalni debug info v console/log datoteko.\n\u010ceprav kriptiran, ti debug info pove stanje torrentov in zakaj (ne) za\u010denjajo/so na \u010dakanju. ConfigView.label.queue.minQueueingShareRatio=Ne ustavi torrenta ali ga daj na \u010dakanje dokler njegovo delilno razmerje ne dose\u017ee ConfigView.label.ratio=razmerje ConfigView.label.removeOnStop=Odstrani torrent z seznama, ko se avtomati\u010dno ustavi ConfigView.label.savedirectory=Mapa Shrani ConfigView.label.seeding.autoReposition.tooltip=\u010ce omogo\u010deno, bo vrstni red torrentov ('#' stolpec) spremenjen, da se bo ujemal s sejalnim rangom\nTo je uporabno, \u010de ne \u017eeli\u0161 videti \u0161tevilk sejalnega ranga vendar \u0161e vedno \u017eeli\u0161 vedeti vrstni red v katerem bodo za\u010deli kon\u010dani torrenti. ConfigView.label.seeding.autoReposition=Avtomati\u010dno razvrsti torrente glede na sejalni rank ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Pogosto torrenti z malo semeni in veliko sole\u017eniki pomeni, da najverjetneje ni cele kopije med sole\u017eniki.\nZato bo\u0161 morda \u017eelel, da se sejalna pravila ne pretvarjajo, da obstaja cela kopija (in tako nepravilno zni\u017ea njegov rank) ConfigView.label.seeding.fakeFullCopySeedStart=toda samo za torrente z vsaj ConfigView.label.seeding.ignore0Peers=Ignoriraj torrente z 0 peeri ConfigView.label.seeding.ignoreRatioPeers=ignoriraj torrente, ki imajo vsaj 1 seme za vsak(e) ConfigView.label.seeding.ignoreShareRatio=ignoriraj torrente, ki imajo delitveni nivo ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignoriraj torrente tudi \u010de\nveljajo pravila Prve prioritete ConfigView.label.seeding.ignore.header.rule=Pravilo ConfigView.label.seeding.ignore.header.value=Vrednost ConfigView.label.seeding.firstPriority.info=Torrenti s prvo prioriteto bodo vedno na vrhu \u010dakalne vrste. Torrenti, ki imajo prvo prioriteto ne bodo avtomati\u010dno ustavljeni in dani na \u010dakanje. Torrent, ki ima prvo prioriteto bo vzel isto\u010dasno odjemno mesto, \u010de bo to potrebno. ConfigView.label.seeding.firstPriority=Prva prioriteta je za torrente z ConfigView.label.seeding.firstPriority.following=od na\u0161tetih: ConfigView.label.seeding.firstPriority.shareRatio=Delitveni nivo pod ConfigView.label.seeding.firstPriority.seedingMinutes=Pretekel \u010das od spremembe iz odjemanja v sejanje ConfigView.label.seeding.firstPriority.DLMinutes=Pretekel \u010das od za\u010detka odjema ConfigView.label.seeding.numPeersAsFullCopy.tooltip=S pretvarjanjem, da obstaja 1 cela kopija na X sole\u017enikov, zmanj\u0161a\u0161 rank torrentov z veliko sole\u017eniki.\nZelo verjetno imajo torrenti z veliko sole\u017eniki tudi veliko prometa.\nTo ne spremeni prikaz \u0161tevila semen. ConfigView.label.seeding.numPeersAsFullCopy=Pretvarjaj se, da obstaja 1 cela kopija za vsak\n(0: Ne pretvarjaj se) ConfigView.label.seeding.preferLargerSwarms.tooltip=\u010ce v glavnem seje\u0161 torrente, ki so ''obti\u010dali'', bo pomagalo \u010de preferira\u0161 ve\u010dje jate.\n\u010ce v glavnem seje\u0161 torrente, ki imajo visoko dostopnost, bo bolje \u010de preferira\u0161 manj\u0161e jate. ConfigView.label.seeding.preferLargerSwarms=Ko imajo torrenti isti rank, daj prednost ve\u010djim jatam ConfigView.label.seeding.rankType.none.tooltip=Uredi glede na # stolpec ConfigView.label.seeding.rankType.none=Nobeden ConfigView.label.seeding.rankType.peerSeed.options=Mo\u017enosti Semena:Sole\u017eni\u0161ki nivo ConfigView.label.seeding.rankType.peerSeed.tooltip=Vi\u0161ji nivo = Vi\u0161ji rank ConfigView.label.seeding.rankType.peerSeed=Sole\u017eniki:Sejalni nivo ConfigView.label.seeding.rankType.seed.fallback=Padec nazaj na Sole\u017enike:Sejalni nivo po\n(0: Nikoli ne padi nazaj) ConfigView.label.seeding.rankType.seed.options=Mo\u017enosti Samo \u0161tetja semen ConfigView.label.seeding.rankType.seed.tooltip=Manj semen = Vi\u0161ji rank ConfigView.label.seeding.rankType.seed=Samo \u0161tetje semen ConfigView.label.seeding.rankType.timedRotation.tooltip=Vsi kon\u010dani torrenti na \u010dakanju se bodo obrnili v sejalni na\u010din.\nTrajanje sejalnega \u010dasa se nastavi v 'Minimalni sejalni \u010das' ConfigView.label.seeding.rankType.timedRotation=\u010casovno merjeno obra\u010danje ConfigView.label.seeding.rankType.tooltip=Torenti z najvi\u0161jim rangom so avtomati\u010dno za\u010deti.\nKo drug torrent dobi vi\u0161ji rank, se torrent z ni\u017ejim rankom ustavi in gre nazaj na \u010dakanje.\n\nSamo torrenti na \u010dakanju so na voljo za avtomati\u010dni za\u010detek.\nUstavljeni torrenti se nikoli ne za\u010dnejo avtomati\u010dno. ConfigView.label.seeding.rankType=Rangiraj kon\u010dane torrente za avto-start glede na: ConfigView.label.stopAfterMinutes=Po obratu na sejanje, se ustavi po preteku \u010dasa ConfigView.label.switchpriority.tooltip=Nizka prioriteta zmanj\u0161a koli\u010dino oddajne pasovne \u0161irine dodeljene torrentu. ConfigView.pluginlist.info=Naslednji vklju\u010dki so bili identificirani. Nekateri vklju\u010dki morda nimajo nastavitev. ConfigView.pluginlist.noplugins=Ni bilo najdenih vklju\u010dkov. ConfigView.section.pluginslist=Seznam ConfigView.section.queue.seeding=Sejanje ConfigView.section.queue.seeding.autoStarting=Avto za\u010detek ConfigView.section.queue.seeding.ignore=Pravila ignoriranja ConfigView.section.queue.seeding.firstPriority=Prva prioriteta ConfigView.section.queue.main=Glavna ConfigView.section.queue=\u010cakalna vrsta ConfigView.section.torrents=Torrenti ConfigView.text.all=vse ConfigView.text.hours=ure ConfigView.text.ignoreRule=Pravilo ignoriranja ConfigView.text.ignore=Ignoriraj ConfigView.text.minutes=minute ConfigView.text.neverIgnore=Nikoli ne ignoriraj ConfigView.text.any=katerikoli DownloadManager.error.datamissing=Manjkajo podatki MainWindow.menu.file.open.torrentforseeding=.torrent datoteka (za sejanje) MainWindow.menu.language.refresh=&Osve\u017ei ManagerItem.forced=Prisiljen ManagerItem.queued=Na \u010dakanju MySeedersView.header=Kon\u010dani/sejalni torrenti TableColumn.header.availability.info=# videnih polnih kopij TableColumn.header.availability=Razpolo\u017eljivost TableColumn.header.category=Kategorija MyTorrentsView.header=Nedokon\u010dani/Odjemalni Torrenti TableColumn.header.maxuploads=Max # oddajkov MyTorrentsView.menu.category.delete=&Izbri\u0161i kategorija MyTorrentsView.menu.forceStart=&Prisilni zagon MyTorrentsView.menu.queue=&Na \u010dakanje MyTorrentsView.menu.setCategory.add=&Dodaj kategorijo... MyTorrentsView.menu.setCategory=Nastavi kategorijo TableColumn.header.savepath=Pot shrambe TableColumn.header.SeedingRank=Sejalni rank TableColumn.header.totalspeed.info=Skupna hitrost vseh sole\u017enikov s katerimi si povezan TableColumn.header.totalspeed=Skupna hitrost splash.initializePlugins=Zaganjam vklju\u010dke StartStopRules.0Peers=0 sole\u017enikov StartStopRules.numSeedsMet=# Semena vredu StartStopRules.ratioMet=Sole\u017eniki:Seme vredu StartStopRules.shareRatioMet=Delitveni nivo vredu StartStopRules.waiting=\u010cakam StartStopRules.firstPriority=Prva prioriteta ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Delitvena vsebina (ponavljajo\u010de) DownloadManager.error.unabletostartserver=Ne morem za\u010deti stre\u017enika - preveri konfiguracijo dohodnih portov / dovoljenje po\u017earnega zidu, da program deluje kot stre\u017enik. GeneralView.label.creationdate=Ustvarjeno : ConfigView.section.tracker.announcescrapepercentage=Scrape interval kot %starosti objave\nnpr. 200 = 2:1. 0 = naj se sole\u017enik odlo\u010di ManagerItem.stopping=Ustavljam ConfigView.section.tracker.announcecacheperiod=Objavi cache (millis) ConfigView.section.tracker.announcecacheminpeers=Objavi cache omogo\u010di sole\u017enikov prag fileDownloadWindow.retry=Poskusi ponovno MyTrackerView.bytesin=Bytov Noter MyTrackerView.bytesinave=Ave Noter MyTrackerView.bytesout=Bytov Ven MyTrackerView.bytesoutave=Ave Ven ConfigView.section.file.max_open_files=Maksimum datotek odprtih za branje/pisanje\n[0: neomejeno] ConfigView.section.file.max_open_files.tooltip=Uporabno za torrente z stotimi/tiso\u010dimi datotekami in \u010de bo\u0161 kmalu dosegel limit datote\u010dnih kontrolnikov OSa. ConfigView.section.proxy=Proxy ConfigView.section.proxy.enable_proxy=Omogo\u010di proxy ConfigView.section.proxy.host=Gostitelj ConfigView.section.proxy.username=Uporabni\u0161ko ime ConfigView.section.proxy.password=Geslo ConfigView.section.proxy.enable_socks=Imam SOCKS proxy wizard.createtorrent.extrahashes=Dodaj hashe za druga omre\u017eja (npr. Gnutella2, eDonkey2000) GeneralView.label.connected=povezan GeneralView.label.in_swarm=v jati ManagerItem.initializing=Zaganjam AlertMessageBox.error=Napaka AlertMessageBox.warning=Opozorilo AlertMessageBox.comment=Informacije AlertMessageBox.information=Informacije SharedPortServer.alert.selectorfailed=Neuspeh pri vzpostavljanju poslu\u0161alca za dohodne podatke.\nPreveri nastavitve tvojega po\u017earnega zidu, \u010de dovoli programu java(w).exe da deluje kot stre\u017enik. Tracker.alert.listenfail=Neuspeh pri vzpostavljanju poslu\u0161anja na portu %1.\nPreveri, da druge aplikacije ne uporabljajo ta port.\nPreveri tudi, \u010de deluje \u0161e ena verzija Azureusa. DiskManager.alert.movefileexists=Napaka pri premikanju kon\u010danih datotek\nDatoteka %1 \u017ee obstaja v Premakni V kon\u010dni mapi DiskManager.alert.movefilefails=Napaka pri premikanju kon\u010danih datotek\nPremikanje datoteke %1 neuspe\u0161no, %2 DiskManager.alert.movefilerecoveryfails=Napaka pri okrevanju po napaki pri premikanju\nPovrnitev datoteke %1 neuspe\u0161no, %2 ConfigView.section.tracker.logenable=Bele\u017ei periodi\u010dne statistike v 'tracker.log' SpeedView.stats.title=Statistika SpeedView.stats.total=Skupno SpeedView.stats.session=To sre\u010danje SpeedView.stats.downloaded=Odjeto SpeedView.stats.uploaded=Oddano SpeedView.stats.uptime=Gor \u010das (ure) AutoMigration.useralert=Avto-migracijski razultati Azureusovih uporabni\u0161kih konfiguracijskih datotek/map:\n\n%1\nKakr\u0161ikoli neuspehi morajo biti prestavljeni ro\u010dno.\nNE POZABI POSODOBITI SHRANITVENIH POTI V NASTAVITVAH, \u010cE SO BILE PRESTAVLJENE! # # > 2.0.8.0 # OpenTorrentWindow.title=Odpri Torrent(e) OpenTorrentWindow.message=Eksperimentalno OpenTorrentWindow.addFiles=&Dodaj datoteke OpenTorrentWindow.dataLocation=Lokacija za shraniti podatke: OpenTorrentWindow.startMode=Dodaj na\u010din OpenTorrentWindow.startMode.queued=Na \u010dakanju OpenTorrentWindow.startMode.stopped=Ustavljeno OpenTorrentWindow.startMode.forceStarted=Prisilno za\u010deto OpenTorrentWindow.addPosition=Polo\u017eaj na \u010dakalni vrsti OpenTorrentWindow.addPosition.first=Prvi OpenTorrentWindow.addPosition.last=Zadnji TableColumn.header.remaining.info=Koli\u010dina podatkov, ki jih je treba \u0161e odjeti TableColumn.header.remaining=Ostalo ConfigView.section.tracker.enablecompact=Omogo\u010di kompakten najavitveni protokol ConfigView.section.tracker.enablekey=Omogo\u010di podajanje klju\u010da za pove\u010dano varnost ConfigView.section.file.perf=Mo\u017enosti delovanja ConfigView.section.file.perf.explain=Opozorilo - nekvalificirane spremembe teh parametrov lahko zelo vplivajo na uspeh odjemanja. Ponovni zagon potreben.\n\u010ce ima\u0161 ''premalo spomina'' (out of memory) probleme, pomisli o omejevanju povezav na torrent (glej Nastavitve prenosa) ConfigView.section.file.max_open_files.explain=Odpiranje preve\u010d datotek lahko povzro\u010di te\u017eave OS (Windows) zaradi omejenih potreb\u0161\u010din, kot so datote\u010dni kontrolniki. To omeji \u0161tevilo isto\u010dasno odprtih datotek. popup.error.hide=Skrij popup.error.details=Podrobnosti ConfigView.section.style.colorOverrides=Barvni prepisi ConfigView.section.style.colorOverride.progressBar=Vrstica napredka ConfigView.section.style.colorOverride.error=Napaka MainWindow.status.tooOld=je star, prosim posodobi. ConfigView.section.style.colorOverride.warning=Opozorilo ConfigView.section.style.colorOverride.altRow=Alternativne vrstice ConfigView.section.file.save.peers.enable=Shrani povezave s peeri za hitre ponovne povezave ConfigView.section.file.save.peers.max=Maksimum peerov za shrambo [0: neomejeno] ConfigView.section.file.save.peers.pertorrent=na torrent ConfigView.label.max_peers_per_torrent=Maksimalno \u0161tevilo povezav na torrent [0: neomejeno] ConfigView.label.max_peers_total=Maksimalno \u0161tevilo vseh povezav [0: neomejeno] ConfigView.section.style.colorOverrides.reset=Resetiraj barvo ConfigView.section.language.info=Ko omogo\u010deno, se bo ob vsakem zagonu Azureusa preverilo za posodobitve. ConfigView.section.language.enableUpdate=Omogo\u010di Internetno posodobitev ConfigView.section.language.UpdateURL=Posodobi URL ConfigView.section.language.UpdateNow=Posodobi zdaj! Button.revert=Povrni MyTorrentsView.menu.changeDirectory=Spremeni podatkovno mapo GenericText.column=stolpec MyTorrentsView.menu.thisColumn.remove=Odstrani stolpec MyTorrentsView.menu.thisColumn.toClipboard=Kopiraj tekst v odlo\u017ei\u0161\u010de MyTorrentsView.menu.tracker=Sledilnik ConfigView.download.abbreviated=Dol: ConfigView.upload.abbreviated=Gor: ConfigView.complete.abbreviated=& Kon: TableColumn.header.secondsseeding=Sejem za TableColumn.header.secondsseeding.info=Skupna koli\u010dina \u010dasa sejanja TableColumn.header.secondsdownloading=DLing za TableColumn.header.secondsdownloading.info=Koli\u010dina \u010dasa odjemanja ConfigView.section.tracker.udpversion=UDP protokol verzija (1 ali 2) window.updateswt.title=Tvoja SWT verzija je prestara! window.updateswt.text=Tvoja SWT verzija je prestara!\nSWT je grafi\u010dna knji\u017enica, ki jo uporablja Vuze in tvoja verzija je prestara za najnovej\u0161o verzijo Azureusa. Pritisni Vredu da posodobi\u0161 tvoj SWT. window.updateswt.status=Stanje window.updateswt.failed=Posodobitev neuspe\u0161na, pritisni vredu za ponovni zagon. window.updateswt.status.downloading.updater=Odjemam Posodobitveni Modul window.updateswt.status.finding=I\u0161\u010dem najnovej\u0161o SWT verzijo window.updateswt.status.downloading=Odjemam najnovej\u0161o SWT verzijo window.updateswt.status.done=Ponovno zaganjam window.updateswt.ok=Vredu window.updateswt.cancel=Prekini swt.updater.downloader.downloading=Odjemam SWT od swt.updater.urlsgetter.downloading=Prejemam seznam ogledal od swt.updater.urlsgetter.platform=SWT za platformo: window.updateswt.ignore=Inoriraj ConfigView.section.style.useFancyTabs=Uporabi posebne zavihtke splash.initializeGM=Zaganjam Globalni Torrent Manager splash.loadingTorrents=Nalagam Torrente MyTorrentsView.menu.thisColumn.sort=&Razvrsti Scrape.status.ok=Scrape vredu. Scrape.status.error=Scrape Napaka: Scrape.status.error.badURL=Objavljen URL ne sledi scrape specifikacij. Scrape.status.error.nohash=Hash manjka v odgovoru. Scrape.status.error.invalid=Nepravilen odgovor. Scrape.status.nextScrapeAt=Naslednji scrape ob %1 Scrape.status.initializing=\u010cakam za Scrape ConfigView.label.minSpeedForActiveSeeding=Ne \u0161tej kon\u010danih torrentov, kot da uporabljajo mesto, \u010de je hitorst pod ConfigView.section.stats.exportpeers=Podrobnosti izvoza peera MainWindow.menu.view.irc.moved=Irc je zdaj na voljo kot vklju\u010dek, glej http://azureus.sourceforge.net/plugin_list.php Po instalaciji pojdi na pogled->vklju\u010dki->Irc za dostop. MyTrackerView.webui.contextmenu.copyurl=Kopiraj torrentov URL v odlo\u017ei\u0161\u010de ConfigView.section.file.torrent.ignorefiles=Datoteke za ignoriranje pri ustvarjanju torrenta\nnpr. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignoriram datoteko ConfigView.section.style.useUnitsRateBits=Uporabi bite namesto bytov za vrednote, ki bazirajo na bytih (KiB/s->Kibit/s itd.) ConfigView.section.interface.resetassoc=Resetiraj explorerjeve datote\u010dne asociacije (.torrent) ConfigView.section.interface.resetassocbutton=Resetiraj ConfigView.section.interface.checkassoc=preveri asociacije ob zagonu dialog.associations.title=Preverjam asociacije Button.yes=Da Button.no=Ne ConfigView.label.seeding.autoStart0Peers=Avtomati\u010dno za\u017eeni vse kon\u010dane torrent z 0 peeri ConfigView.label.seeding.autoStart0Peers.tooltip=Izklju\u010di, \u010de \u017eeli\u0161 da sledilnik vedno prika\u017ee semena za torrente z 0 peeri. dialog.associations.prompt=Vuze ni privzeta aplikacija za BitTorrent datoteke.\nBi \u017eelel asociirati .torrent datoteke z Azureusom? dialog.associations.askagain=Preveri ob zagonu ConfigView.section.plugins.update=Posodobitev vklju\u010dkov Plugin.pluginupdate.enablecheck=Omogo\u010di preverjanje posodobitve vklju\u010dkov plugins.basicview.status=Stanje: plugins.basicview.activity=Dejavnost: plugins.basicview.progress=Napredek: plugins.basicview.log=Dnevnik: ConfigView.label.maxdownloadspeed=KB/s maksimalna skupna odjemna hitrost [0: neomejeno] splash.loadingTorrent=Nalagam Torrent splash.of=od UpdateWindow.title=Vuze Posodobilnik UpdateWindow.header=Naslednje komponente potrebujejo posodobitev: UpdateWindow.columns.install=Instaliraj UpdateWindow.columns.name=Ime UpdateWindow.columns.version=Verzija UpdateWindow.columns.size=Velikost UpdateWindow.cancel=Prekini UpdateWindow.quit=Nehaj UpdateWindow.close=Zapri UpdateWindow.ok=Posodobi UpdateWindow.restart=Ponovni zagon UpdateWindow.status.downloading=Odjemam UpdateWindow.status.done=Kon\u010dano UpdateWindow.status.failed=Neuspe\u0161no UpdateWindow.status.restartNeeded=ponvni zagon bo potreben! ConfigView.pluginlist.broken=Pokvarjen ConfigView.pluginlist.whereToPut=Postavi kakr\u0161nekoli uporabniku-specifi\u010dne vklju\u010dke v njihovo lastno mapo pod: ConfigView.pluginlist.whereToPutOr=Za deljeno uporabo vklju\u010dkov: MainWindow.statusText.checking=Preverjam za posodobitve TableColumn.header.OnlyCDing4=SamoCDing4 TableColumn.header.OnlyCDing4.info=Koli\u010dina \u010dasa, ko je torrent sejal. Ne pri\u0161teje koli\u010dine \u010dasa ko je torrent odjemal(in isto\u010dasno sejal). ConfigView.section.style.alternateTablePainting=Uporabi alternativno metodo risanja grafi\u010dnih stolpcev (lahko potrebuje ponovni zagon) UpdateWindow.status.restartMaybeNeeded=Ponovni zagon bo lahko potreben ConfigView.pluginlist.shared=deljeni PeersView.host=Ime gostitelja PeersView.host.info=Ime gostitelja sole\u017enika, kjer na voljo (lahko vpliva na delovanje) MainWindow.menu.help.whatsnew=Kaj je novega ConfigView.label.checkonstart=Preveri za novej\u0161o verzijo, ko se Vuze za\u017eene ConfigView.label.periodiccheck=Preveri za novej\u0161o verzijo periodi\u010dno ConfigView.label.opendialog=Avtomati\u010dno odpri posodobitvenega pomo\u010dnika, ko je na voljo posodobitev MainWindow.updateavail=(Posodobitev na voljo) MainWindow.status.latestversionunchecked=Preverjanje vezije izklju\u010deno GeneralView.label.updatein.stopped=Ustavljeno StartStopRules.menu.viewDebug=Glej Debug Informacije ConfigView.section.style.doNotUseGB=Ne uporabi enote GB ConfigView.section.style.doNotUseGB.tooltip=\u010ce ozna\u010deno, bo Vuze uporabljal MB tudi za velikosti ve\u010dje od 1024 MB. MainWindow.menu.help.plugins=Vklju\u010dki ConfigView.section.plugins.TrackerWeb=Internetni sledilnik ConfigView.section.tracker.enablecategories=Lo\u010di torrente po kategorijah health.explain.share=pomeni, da je torrent gostujo\u010d ali objavljen ConfigView.section.tracker.createcert=Ustvari samo-podpisan certifikat ConfigView.section.tracker.createbutton=Ustvari security.certcreate.title=Ustvari samo-podpisan certifikat security.certcreate.intro=Ta dialog ti dovoli ustvariti samo-podpisan certifikat security.certcreate.strength=Mo\u010d security.certcreate.firstlastname=Ime in Priimek security.certcreate.orgunit=Organizacijska enota security.certcreate.org=Organizacija security.certcreate.city=Mesto ali lokalnost security.certcreate.state=Mesto ali provinca security.certcreate.country=Dvoznakovna koda dr\u017eave security.certcreate.ok=Ustvari security.certcreate.cancel=Prekini security.certcreate.createok=Certifikat uspe\u0161no ustvarjen security.certcreate.createfail=Ustvaritev certifikata ni uspela ConfigView.section.plugins.webui=Swing internetni vmesnik ConfigView.section.plugins.xml_http_if=XML/HTTP vmesnik webui.passwordenable=Omogo\u010di geslo webui.user=Uporabni\u0161ko ime webui.password=Geslo webui.protocol=Protokol (*) webui.homepage=Doma\u010da stran (*) webui.rootdir=Glavna mapa (*) webui.rootres=Glavna surovina (*) webui.mode=Na\u010din (*) webui.mode.info=Na\u010din je lahko\n\t"polni"\t= vse operacije na voljo (privzeto)\n\t"glej"\t= samo glej (toda lahko posodobi osve\u017eevalno frekvenco) webui.access=Dostop (*) webui.access.info=Dostop je lahko\n\t"lokalni"\t= pomeni, da se lahko pove\u017ee samo lokalni ra\u010dunalnik\n\t"vsi"\t= neomejen dostop (privzeto)\n\tIP\t= npr. 192.168.0.2\t\t\tsamo en IP\n\tIP1-IP2\t= npr. 192.168.0.1-192.168.0.255\tvklju\u010deno \u0161tevilo IPjev GeneralView.label.maxdownloadspeed=Max Dol Security.keystore.corrupt=Keystore '%1' ni mogel biti nalo\u017een, prosim izbri\u0161i ga in ponovno ustvari/uvozi certifikate Security.keystore.empty=Keystore je prazen. Prosim ustvari samo-podpisan certifikat (glej Nastavitve->Varnost) ali uvozi obstoje\u010d certifikat v '%1' webui.restart.info=Sspremembe parametrom ozna\u010denim z (*) potrebujejo ponovni zagon GeneralView.label.maxdownloadspeed.tooltip=Max odjemna hitrost [0: neomejeno] upnp.enable=Omogo\u010di UPnP upnp.info=Universal Plug and Play (UPnP) dovoli avtomati\u010dni mapping portov na UpnP omogo\u010denih ruterjih. upnp.mapping.dataport=Dohodni sole\u017enikov podatkovni port upnp.mapping.tcptrackerport=TCP Sledilnikov Port upnp.mapping.udptrackerport=UDP Sledilnikov Port upnp.alert.differenthost=UPnP: Mapping '%1' je bil rezerviran od '%2' - prosim izberi drug port upnp.alert.mappingok=UPnP: Mapping '%1' vzpostavljeno upnp.alert.mappingfailed=UPnP: Mapping '%1' neuspe\u0161no upnp.alertsuccess=Javi uspe\u0161ne mappings upnp.alert.lostdevice=UPnP: Izgubil povezavo storitve '%1' na UPnP napravi '%2' upnp.grabports=Mapiraj porte tudi \u010de jih lasti drug ra\u010dunalnik upnp.refresh.label=Osve\u017ei mappings upnp.refresh.button=Osve\u017ei upnp.alert.mappinggrabbed=UPnP: Mapping '%1' vzpostavljeno - zgrabljeno od '%2' upnp.mapping.tcpssltrackerport=TCP SSL sledilnikov Port upnp.alertothermappings=Javi sole\u017enike, ki jih lastijo drugi ra\u010dunalniki upnp.alertdeviceproblems=Javi probleme z UPnP napravo ConfigView.pluginlist.coreplugins=Naslednji vgrajeni vklju\u010dki so nalo\u017eeni: Peers.column.DLedFromOthers=Od drugih Peers.column.DLedFromOthers.info=koli\u010dina podatkov odjetih od drugih, medtem ko so bili povezani s tabo. Peers.column.UpDownRatio=Gor:Dol Peers.column.UpDownRatio.info=Sole\u017enikov ''Oddano:Odjeto'' nivo Peers.column.UpRatio=Gor nivo Peers.column.UpRatio.info=Sole\u017enikov ''Oddano od tebe : Oddano od drugih'' nivo upnp.releasemappings=Sprosti mappings ob zaprtju webui.upnpenable=Omogo\u010di UPnP za ta port (*) ConfigView.section.file.friendly.hashchecking=Prijazno preverjanje hasha ConfigView.section.file.friendly.hashchecking.tooltip=Rahlo po\u010dasnej\u0161i, toda veliko manj stresni za procesor/sistem, kosovni na\u010din preverjanja hasha. ConfigView.section.tracker.seedretention=Max semen obdr\u017eanih na torrent [0: neomejeno] ConfigView.section.tracker.seedretention.info=Oddajne statistike bodo izgubljene za neobdr\u017eana semena ConfigView.section.tracker.port=Omogo\u010di sledilnik na HTTP portu ConfigView.section.tracker.sslport=Omogo\u010di sledilnik na HTTPS portu ConfigView.section.tracker.publicenable.info=To dovoljuje drugim, da ustvarijo torrente, ki uporabljajo tvoj sledilnik\u005cbrez da jih ti gostuje\u0161/objavlja\u0161 Button.clear=Izbri\u0161i MainWindow.IPs.tooltip=Zadnja posodobitev seznama filtrov: %1\nVseh IP filtrov na seznamu -\u0160tevilo blokiranih/prezrtih/slabih IPjev to sre\u010danje.\nDvojni-klik za podrobnosti. ConfigView.section.ipfilter.list.banned=je bil izklju\u010den zaradi po\u0161iljanja slabih podatkov ConfigView.section.ipfilter.list.baddata=je poslal slabe podatke: dogodki = Button.reset=Resetiraj ConfigView.section.ipfilter.bannedinfo=IPji, ki so poslali slabe podatke - bodo zavr\u017eeni \u010de limiti presegajo ConfigView.section.ipfilter.blockedinfo=IPji, ki so bili blokirani zaradi IP filtrov download.removerules.name=Pravila odstranjevanja download.removerules.unauthorised.info=Neavtorizirani torrenti so tisti, pri katerih je objavljen odgovor ''not authoris(z)ed'' ali ''unauthoris(z)ed'' v ''failure response'' download.removerules.unauthorised=Avtomati\u010dno odstrani neavtorizirane torrent download.removerules.unauthorised.seedingonly=\tSamo \u010de sejem download.removerules.removed.ok=Avtomati\u010dno odstranjenje torrenta '%1' uspe\u0161no. To se je zgodilo zaradi pravil odstranjevanja torrentov. download.removerules.updatetorrents=Odstrani Azureusove posodobitvene torrente, kot zahteva jata ConfigView.label.defaultstarttorrentsstopped=Privzeto dodaj nove torrente v ustavljenem stanju ConfigView.section.server.enableudp=Omogo\u010di UDP sledilni klientov protokol. upnp.mapping.dataportudp=UDP sledilnikov klientov port ConfigView.section.tracker.publishenabledetails=Objavi podrobnosti torrent datoteke in peera ConfigView.label.overrideip=Razveljavi IP naslov poslan sledilniku\n - V\u010dasih potrebno za NAT #file can be a URL or a path in the jar ConfigView.section.logging.log0type=Informacije # %1 = "in kbps" or ""; %2 = "upload" or "download" OpenTorrentWindow.torrentLocation=Torrent datoteke: Button.moveUp=Prestavi gor Button.moveDown=Prestavi dol # > 2402 # Used for peers which we can't determine. PeerSocket.unknown=Neznano iconBar.queue.tooltip=Daj na \u010dakalno vrsto MainWindow.menu.help.faq=Wiki FAQ MainWindow.menu.help.donate=Prispevaj ($2,$5,...) azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_ka_GE.properties0000644000175000017500000066314211301156004026051 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=.torrent \u10e4\u10d0\u10d8\u10da\u10d8 Main.parameter.maxUploads=\u10d4\u10e0\u10d7\u10d3\u10e0\u10dd\u10e3\u10da\u10d8 \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d4\u10d1\u10e1\u10d8 \u10db\u10d0\u10e5\u10e1. \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 Main.parameter.maxSpeed=\u10db\u10d0\u10e5\u10e1. \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 \u10d1\u10d0\u10d8\u10e2\u10d8/\u10ec\u10db MainWindow.menu.file=\u10e4\u10d0\u10d8\u10da\u10d8 MainWindow.menu.file.open=\u10d2\u10d0\u10ee\u10e1\u10dc\u10d0 MainWindow.menu.file.create=\u10e8\u10d4\u10e5\u10db\u10d4\u10dc\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 MainWindow.menu.file.create.fromfile=\u10e4\u10d0\u10d8\u10da\u10d8\u10d3\u10d0\u10dc MainWindow.menu.file.create.fromdir=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8\u10d3\u10d0\u10dc MainWindow.menu.file.export=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10d4\u10e5\u10de\u10dd\u10e0\u10e2\u10d8 XML \u10e4\u10dd\u10e0\u10db\u10d0\u10e2\u10e8\u10d8... MainWindow.menu.file.import=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10d8\u10db\u10de\u10dd\u10e0\u10e2\u10d8 XML \u10e4\u10dd\u10e0\u10db\u10d0\u10e2\u10e8\u10d8... MainWindow.menu.file.closetab=\u10d3\u10d0\u10ee\u10e3\u10e0\u10d4 \u10e9\u10d0\u10dc\u10d0\u10e0\u10d7\u10d8 MainWindow.menu.file.closewindow=\u10d3\u10d0\u10ee\u10e3\u10e0\u10d4 \u10e4\u10d0\u10dc\u10ef\u10d0\u10e0\u10d0 MainWindow.menu.file.exit=\u10d2\u10d0\u10db\u10dd\u10e1\u10d5\u10da\u10d0 MainWindow.dialog.choose.file=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d8 MainWindow.menu.file.folder=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 MainWindow.dialog.choose.folder=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 \u10e1\u10d0\u10d3\u10d0\u10ea \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10d0 \u10db\u10dd\u10d7\u10d0\u10d5\u10e1\u10d4\u10d1\u10e3\u10da\u10d8 MainWindow.menu.view=\u10ee\u10d4\u10d3\u10d8 MainWindow.menu.view.show=\u10e9\u10d5\u10d4\u10dc\u10d4\u10d1\u10d0 MainWindow.menu.view.mytorrents=\u10e9\u10d4\u10db\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 MainWindow.menu.view.configuration=\u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8... MainWindow.menu.view.console=\u10d9\u10dd\u10dc\u10e1\u10dd\u10da\u10d8 MainWindow.menu.view.irc=&Irc MainWindow.menu.closealldetails=\u10d3\u10d0\u10ee\u10e3\u10e0\u10d4 \u10e7\u10d5\u10d4\u10da\u10d0 \u10d3\u10d4\u10e2\u10d0\u10da\u10d8 MainWindow.menu.closealldownloadbars=\u10d3\u10d0\u10ee\u10e3\u10e0\u10d4 \u10e7\u10d5\u10d4\u10da\u10d0 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d4\u10d1\u10d8\u10e1 \u10d6\u10dd\u10da\u10d8 MainWindow.menu.language=\u10d4\u10dc\u10d0 ConfigView.section.language=\u10d4\u10dc\u10d0 MainWindow.menu.window=\u10e4\u10d0\u10dc\u10ef\u10d0\u10e0\u10d0 MainWindow.menu.window.minimize=\u10e9\u10d0\u10db\u10dd\u10eb\u10d8\u10dc\u10d4\u10d1\u10d0 MainWindow.menu.window.zoom=\u10d2\u10d0\u10d3\u10d8\u10d3\u10d4\u10d1\u10d0 MainWindow.menu.help=\u10d3\u10dd\u10d9\u10e3\u10db\u10d4\u10dc\u10e2\u10d0\u10ea\u10d8\u10d0 MainWindow.menu.help.about=Vuze u2013\u10d8\u10e1 \u10e8\u10d4\u10e1\u10d0\u10ee\u10d4\u10d1 MainWindow.about.title=\u10e9\u10d5\u10d4\u10dc\u10e1 \u10e8\u10d4\u10e1\u10d0\u10ee\u10d4\u10d1 MainWindow.about.section.developers=\u10de\u10e0\u10dd\u10d2\u10e0\u10d0\u10db\u10d8\u10e1\u10e2\u10d4\u10d1\u10d8 MainWindow.about.section.translators=\u10db\u10d7\u10d0\u10e0\u10d2\u10db\u10dc\u10d4\u10da\u10d4\u10d1\u10d8 MainWindow.about.section.internet=\u10d8\u10dc\u10e2\u10d4\u10e0\u10dc\u10d4\u10e2\u10d8 MainWindow.about.internet.homepage=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10e1\u10d0\u10e8\u10d8\u10dc\u10d0\u10dd \u10d2\u10d5\u10d4\u10e0\u10d3\u10d8 MainWindow.about.internet.sourceforge=\u10de\u10e0\u10dd\u10d4\u10e5\u10e2\u10d8\u10e1 \u10d2\u10d5\u10d4\u10e0\u10d3\u10d8 Sourceforge\u2013\u10d6\u10d4 MainWindow.about.internet.sourceforgedownloads=Sourceforge\u2013\u10e1 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d4\u10d1\u10d8 MainWindow.about.internet.bugreports=Bug \u10e0\u10d4\u10de\u10dd\u10e0\u10e2\u10d4\u10d1\u10d8 MainWindow.about.internet.forumdiscussion=\u10e4\u10dd\u10e0\u10e3\u10db\u10d4\u10d1\u10d8 MainWindow.about.internet.wiki=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10d5\u10d8\u10d9\u10d8 \u10ee.\u10d3.\u10d9. MainWindow.dialog.choose.savepath=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d8\u10e1 \u10d2\u10d6\u10d0 MainWindow.dialog.choose.savepath_forallfiles=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d8\u10e1 \u10d2\u10d6\u10d0 \u10e7\u10d5\u10d4\u10da\u10d0 \u10e4\u10d0\u10d8\u10da\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 MainWindow.status.latestversion=\u10e3\u10d0\u10ee\u10da\u10d4\u10e1\u10d8 MainWindow.status.latestversion.clickupdate=\u10d3\u10d0\u10ec\u10d9\u10d0\u10de\u10d4\u10d7 \u10d2\u10dc\u10e1\u10d0\u10d0\u10ee\u10da\u10d4\u10d1\u10da\u10d0\u10d3 MainWindow.status.unknown=\u10e3\u10ea\u10dc\u10dd\u10d1\u10d8\u10d0 MainWindow.status.checking=\u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 MyTorrentsView.mytorrents=\u10e9\u10d4\u10db\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 TableColumn.header.name=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8 TableColumn.header.size=\u10d6\u10dd\u10db\u10d0 TableColumn.header.done=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8 TableColumn.header.done.info=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10de\u10e0\u10dd\u10ea\u10d4\u10dc\u10e2\u10e3\u10da\u10d8 \u10db\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4\u10d1\u10d4\u10da\u10d8 TableColumn.header.status=\u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8 TableColumn.header.status.info=\u10e0\u10d0\u10e1 \u10e8\u10d5\u10d4\u10d1\u10d0 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 TableColumn.header.seeds=\u10db\u10d7\u10d4\u10e1\u10d5\u10d4\u10da\u10d4\u10d1\u10d8 TableColumn.header.peers=\u10de\u10d8\u10e0\u10d4\u10d1\u10d8 TableColumn.header.peers.info=# \u10de\u10d8\u10e0\u10d8 \u10db\u10d8\u10d4\u10e0\u10d7\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 (# \u10e1\u10e3\u10da \u10de\u10d8\u10e0\u10d4\u10d1\u10d8) TableColumn.header.downspeed=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 TableColumn.header.upspeed=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 TableColumn.header.eta=\u10d3\u10d0\u10e0\u10e9\u10d4\u10dc\u10d8\u10da\u10d8 \u10d3\u10e0\u10dd TableColumn.header.tracker=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8 TableColumn.header.tracker.info=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8 TableColumn.header.trackernextaccess=\u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10db\u10d8\u10db\u10d0\u10e0\u10d7\u10d5\u10d0 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4\u10d6\u10d4 TableColumn.header.priority=\u10de\u10e0\u10d8\u10dd\u10e0\u10d8\u10e2\u10d4\u10e2\u10d8 MyTorrentsView.menu.showdetails=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 \u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8 MyTorrentsView.menu.showdownloadbar=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10d6\u10dd\u10da\u10d8 MyTorrentsView.menu.open=\u10d2\u10d0\u10ee\u10e1\u10dc\u10d0 MyTorrentsView.menu.setpriority=\u10de\u10e0\u10d8\u10dd\u10e0\u10d8\u10e2\u10d4\u10e2\u10d8\u10e1 \u10db\u10d8\u10d7\u10d8\u10d7\u10d4\u10d1\u10d0 MyTorrentsView.menu.setpriority.high=\u10db\u10d0\u10e6\u10d0\u10da\u10d8 MyTorrentsView.menu.setpriority.low=\u10d3\u10d0\u10d1\u10d0\u10da\u10d8 MyTorrentsView.menu.start=\u10e1\u10e2\u10d0\u10e0\u10e2\u10d8 MyTorrentsView.menu.stop=\u10e1\u10e2\u10dd\u10de\u10d8 MyTorrentsView.menu.remove=\u10d0\u10db\u10dd\u10d2\u10d3\u10d4\u10d1\u10d0 MyTorrentsView.menu.changeTracker=\u10d3\u10d0\u10d0\u10db\u10d0\u10e2\u10d4 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 URL TrayWindow.menu.exit=\u10d2\u10d0\u10e1\u10d5\u10da\u10d0 TrayWindow.menu.show=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8 SystemTray.menu.exit=\u10d2\u10d0\u10db\u10dd\u10e1\u10d5\u10da\u10d0 SystemTray.menu.closealldownloadbars=\u10d3\u10d0\u10ee\u10e3\u10e0\u10d4 \u10e7\u10d5\u10d4\u10da\u10d0 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10d6\u10dd\u10da\u10d4\u10d1\u10d8 SystemTray.menu.show=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8 PeersView.ip.info=\u10de\u10d8\u10e0\u10d8\u10e1 IP PeersView.port=\u10de\u10dd\u10e0\u10e2\u10d8 PeersView.port.info=\u10d2\u10d0\u10db\u10dd\u10e7\u10d4\u10dc\u10d4\u10d1\u10d0\u10d3\u10d8 \u10de\u10dd\u10e0\u10e2\u10d8 PeersView.pieces=\u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8 PeersView.downloadspeed=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 PeersView.download=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 PeersView.uploadspeed=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 PeersView.statup=\u10d2\u10d0\u10e8\u10d5\u10d4\u10d1\u10d0 PeersView.downloadspeedoverall=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10e0\u10e3\u10da\u10d8 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 PeersView.client=\u10d9\u10da\u10d8\u10d4\u10dc\u10e2\u10d8 PeersView.client.info=\u10de\u10d8\u10e0\u10d8\u10e1 \u10db\u10d8\u10d4\u10e0 \u10d2\u10d0\u10db\u10dd\u10e7\u10d4\u10dc\u10d4\u10d1\u10d0\u10d3\u10d8 \u10d1\u10d8\u10e2\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10d9\u10da\u10d8\u10d4\u10dc\u10e2\u10d8\u10e1 \u10e2\u10d8\u10de\u10d8 PeersView.title.short=\u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8 PeersView.title.full=\u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8 ConfigView.section.files=\u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 ConfigView.label.usefastresume=\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4 \u10e1\u10ec\u10e0\u10d0\u10e4\u10d8 \u10d2\u10d0\u10d2\u10e0\u10eb\u10d4\u10da\u10d4\u10d1\u10d8\u10e1 \u10e0\u10d4\u10df\u10d8\u10db\u10d8 ConfigView.label.incrementalfile=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10d8\u10dc\u10d9\u10e0\u10d4\u10db\u10d4\u10dc\u10e2\u10d0\u10da\u10e3\u10e0\u10d8 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10e8\u10d4\u10e5\u10db\u10dc\u10d0 [\u10e1\u10d0\u10ed\u10d8\u10e0\u10dd\u10d0 FAT32 \u10e1\u10d8\u10e1\u10e2\u10d4\u10db\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10da\u10d8\u10dc\u10e3\u10e5\u10e1\u10d6\u10d4] ConfigView.label.defaultsavepath=\u10e8\u10d4\u10d8\u10dc\u10d0\u10ee\u10d4 \u10ec\u10d8\u10dc\u10d0\u10e1\u10ec\u10d0\u10e0 \u10d2\u10d0\u10dc\u10e1\u10d0\u10d6\u10e6\u10d5\u10e0\u10e3\u10da \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10e8\u10d8 ConfigView.button.browse=\u10db\u10d8\u10db\u10dd\u10ee\u10d8\u10da\u10d5\u10d0... ConfigView.dialog.choosedefaultsavepath=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4\u10d7 \u10e1\u10e2\u10d0\u10dc\u10d3\u10d0\u10e0\u10e2\u10e3\u10da\u10d8 \u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d8\u10e1 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 ConfigView.section.server=\u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d0 ConfigView.section.global=\u10db\u10d7\u10d0\u10d5\u10d0\u10e0\u10d8 ConfigView.label.disconnetseed=\u10d2\u10d0\u10ec\u10e7\u10d5\u10d8\u10e2\u10d4 \u10d9\u10d0\u10d5\u10e8\u10d8\u10e0\u10d8 \u10d7\u10d4\u10e1\u10da\u10d4\u10d1\u10d7\u10d0\u10dc \u10e0\u10dd\u10ea\u10d0 \u10d7\u10d4\u10e1\u10d0\u10d5 ConfigView.label.maxdownloads=\u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10d4\u10e0\u10d7\u10d3\u10e0\u10dd\u10da\u10d8 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d4\u10d1\u10d8 [0: \u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4] ConfigView.label.maxdownloads.tooltip=\u10e7\u10dd\u10d4\u10da\u10d7\u10d5\u10d8\u10e1 \u10e8\u10d4\u10e1\u10d0\u10eb\u10da\u10d4\u10d1\u10d4\u10da\u10d8 \u10d8\u10e5\u10dc\u10d4\u10d1\u10d0 \u10d0\u10e5\u10e2\u10d8\u10e3\u10e0\u10d0\u10d3 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10dd \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 \u10e0\u10dd\u10db\u10d4\u10da\u10e1\u10d0\u10ea \u10db\u10d8\u10e3\u10d7\u10d8\u10d7\u10d4\u10d1 \u10d0\u10e5, \u10d4\u10e0\u10d7\u10d8 \u10e8\u10d4\u10db\u10d7\u10ee\u10d5\u10d4\u10d5\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d3\u10d0.\n\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 \u10de\u10d8\u10e0\u10d5\u10d4\u10da\u10d0\u10d3\u10d8 \u10de\u10e0\u10d8\u10dd\u10e0\u10d8\u10e2\u10d4\u10e2\u10d8\u10d7 \u10d0\u10ef\u10dd\u10d1\u10d4\u10d1\u10e1 \u10d0\u10e5\u10e2\u10d8\u10e3\u10e0\u10d8 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10da\u10dd\u10e2\u10e1 \u10d7\u10e3 \u10d0\u10d1\u10e1\u10dd\u10da\u10e3\u10e2\u10e3\u10e0\u10d0\u10d3 \u10db\u10dd\u10d8\u10d7\u10ee\u10dd\u10d5\u10d4\u10d1\u10d0. ConfigView.label.maxactivetorrents=\u10d0\u10e5\u10e2\u10d8\u10e3\u10e0\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8\u10e1 \u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 [0: \u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4]\n - \u10d0\u10ee\u10d0\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 \u10d0\u10e0 \u10d2\u10d0\u10d0\u10e5\u10e2\u10d8\u10e3\u10e0\u10d3\u10d4\u10d1\u10d0 \u10d7\u10e3 \u10d7\u10e5\u10d5\u10d4\u10dc \u10e3\u10d9\u10d4\u10d5 \u10d7\u10d5\u10d8\u10e0\u10d7\u10d0\u10d5\u10d7/\u10d7\u10d4\u10e1\u10d0\u10d5\u10d7 \u10e3\u10e4\u10e0\u10dd \u10db\u10d4\u10e2\u10e1 ConfigView.label.priorityExtensions=\u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 \u10de\u10e0\u10d8\u10dd\u10e0\u10d8\u10d6\u10d4\u10d1\u10d0 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10d2\u10d0\u10d0\u10e0\u10d7\u10dd\u10d4\u10d1\u10d8\u10d7\n - \u10db\u10d0\u10d2: .txt;.nfo;.jpg ConfigView.section.transfer=\u10e2\u10e0\u10d0\u10dc\u10e1\u10e4\u10d4\u10e0\u10d8 ConfigView.label.maxuploads=\u10ec\u10d8\u10dc\u10d0\u10e1\u10ec\u10d0\u10e0 \u10d2\u10d0\u10dc\u10e1\u10d0\u10d6\u10e6\u10d5\u10e0\u10e3\u10da\u10d8 \u10e1\u10da\u10dd\u10e2\u10d4\u10d1\u10d8\u10e1 \u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d6\u10d4 ConfigView.label.maxuploadspeed=\u10d9\u10d1/\u10ec\u10db \u10d2\u10da\u10dd\u10d1\u10d0\u10da\u10e3\u10e0\u10d8 \u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 [0: \u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4] ConfigView.label.saveresumeinterval=\u10d2\u10d0\u10dc\u10d0\u10d0\u10ee\u10da\u10d4 \u10d2\u10d0\u10d2\u10e0\u10eb\u10da\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d0\u10ed\u10d8\u10e0\u10dd \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 \u10e7\u10dd\u10d5\u10d4\u10da ConfigView.unlimited=\u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 ConfigView.section.display=\u10d4\u10d9\u10e0\u10d0\u10dc\u10d8 ConfigView.label.opendetails=\u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d0\u10d3 \u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 \u10d3\u10d4\u10e2\u10d4\u10da\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d0\u10dc\u10d8\u10e8\u10dc\u10d4 ConfigView.label.openbar=\u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d0\u10d3 \u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d4\u10d1\u10d8\u10e1 \u10d6\u10dd\u10da\u10d8 ConfigView.label.closetotray=\u10d3\u10d0\u10ee\u10e3\u10e0\u10d5\u10d0 \u10d8\u10ec\u10d5\u10d4\u10d5\u10e1 \u10e1\u10d8\u10e1\u10e2\u10d4\u10db\u10e3\u10e0 \u10de\u10d0\u10dc\u10d4\u10da\u10e8\u10d8 \u10db\u10d8\u10dc\u10d8\u10db\u10d8\u10d6\u10d0\u10ea\u10d8\u10d0\u10e1 ConfigView.label.minimizetotray=\u10e4\u10d0\u10dc\u10ef\u10e0\u10d8\u10e1 \u10e9\u10d0\u10db\u10dd\u10eb\u10d8\u10dc\u10d4\u10d1\u10d0 \u10d8\u10ec\u10d5\u10d4\u10d5\u10e1 \u10d2\u10d0\u10d3\u10d0\u10e1\u10d5\u10da\u10d0\u10e1 \u10e1\u10d8\u10e1\u10e2\u10d4\u10db\u10e3\u10e0 \u10de\u10d0\u10dc\u10d4\u10da\u10e8\u10d8 ConfigView.section.general=\u10db\u10d7\u10d0\u10d5\u10d0\u10e0\u10d8 ConfigView.section.start=\u10e1\u10e2\u10d0\u10e0\u10e2\u10d8 ConfigView.label.showsplash=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 \u10de\u10e0\u10dd\u10d2\u10e0\u10d0\u10db\u10d8\u10e1 \u10d0\u10d1\u10e0\u10d0 ConfigView.label.autoupdate=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d8\u10e1 \u10e4\u10d0\u10dc\u10ef\u10d0\u10e0\u10d0 \u10e0\u10dd\u10ea\u10d0 \u10ee\u10d0\u10da\u10d8 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d0 \u10d0\u10e0\u10d8\u10e1 \u10ee\u10d4\u10da\u10db\u10d8\u10e1\u10d0\u10ec\u10d5\u10d3\u10dd\u10db\u10d8 ConfigView.label.openconsole=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 \u10d9\u10dd\u10dc\u10e1\u10dd\u10da\u10d8 \u10d2\u10d0\u10e8\u10d5\u10d4\u10d1\u10d8\u10e1\u10d0\u10e1 ConfigView.label.openconfig=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8\u10e1 \u10e4\u10d0\u10dc\u10ef\u10d0\u10e0\u10d0 \u10e9\u10d0\u10e8\u10d5\u10d4\u10d1\u10d8\u10e1\u10d0\u10e1 ConfigView.label.startminimized=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10db\u10d8\u10dc\u10d8\u10db\u10d8\u10d6\u10d4\u10d1\u10e3\u10da\u10d0\u10d3 ConfigView.section.irc=Irc ConfigView.label.ircwiki=\u10d2\u10d7\u10ee\u10dd\u10d5\u10d7 \u10ec\u10d0\u10d8\u10d9\u10d8\u10d7\u10ee\u10dd\u10d7 http://www.azureuswiki.com/index.php/Rules_for_IRC ConfigView.label.ircserver=\u10e1\u10d4\u10e0\u10d5\u10d4\u10e0\u10d8 ConfigView.label.ircchannel=\u10d0\u10e0\u10ee\u10d8 ConfigView.label.irclogin=\u10db\u10d4\u10e2\u10e1\u10d0\u10ee\u10d4\u10da\u10d8 ConfigView.group.irctitle=IRC \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8 ConfigView.boolean.ircsendinfo=\u10dc\u10d4\u10d1\u10d0 \u10d3\u10d0\u10e0\u10d7\u10d4\u10d7 \u10d0\u10dc\u10dd\u10dc\u10d8\u10db\u10e3\u10e0\u10d0\u10d3 \u10d2\u10d0\u10d8\u10d2\u10d6\u10d0\u10d5\u10dc\u10dd\u10e1 \u10d7\u10e5\u10d5\u10d4\u10dc\u10d8 \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8\n \u10d0\u10e0\u10ee\u10d8\u10e1 \u10dd\u10de\u10d4\u10e0\u10d0\u10e2\u10dd\u10e0\u10d4\u10d1\u10e1, \u10e0\u10d0\u10d7\u10d0 \u10d2\u10d0\u10e3\u10d0\u10d3\u10d5\u10d8\u10da\u10d3\u10d4\u10d7 \u10d3\u10d0\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10d0. ConfigView.boolean.irclog=\u10d0\u10e0\u10ee\u10d4\u10d1\u10d8\u10e1 \u10d0\u10e5\u10e2\u10d8\u10d5\u10dd\u10d1\u10d8\u10e1 \u10df\u10e3\u10e0\u10dc\u10d0\u10da\u10d8\u10d6\u10d4\u10d1\u10d0 (IRC_log.htm\u2013\u10e8\u10d8) ConfigView.section.security=\u10e3\u10e1\u10d0\u10e4\u10e0\u10d7\u10ee\u10dd\u10d4\u10d1\u10d0 ConfigView.label.password=Vuze u2013\u10d8\u10e1 \u10d3\u10d0\u10ea\u10d5\u10d0 \u10de\u10d0\u10e0\u10dd\u10da\u10d8\u10e1 \u10e1\u10d0\u10e8\u10e3\u10d0\u10da\u10d4\u10d1\u10d8\u10d7\n - \u10d0\u10e5\u10e2\u10d8\u10e3\u10e0\u10d3\u10d4\u10d1\u10d0 \u10d2\u10d0\u10e8\u10d5\u10d4\u10d1\u10d8\u10e1\u10d0\u10e1 \u10d3\u10d0 \u10e1\u10d8\u10e1\u10e2\u10d4\u10db\u10e3\u10e0\u10d8 \u10de\u10d0\u10dc\u10d4\u10da\u10d8\u10d3\u10d0\u10dc \u10d2\u10d0\u10ee\u10e1\u10dc\u10d8\u10e1 \u10db\u10ea\u10d3\u10d4\u10da\u10dd\u10d1\u10d8\u10e1\u10d0\u10e1. ConfigView.label.passwordconfirm=\u10de\u10d0\u10e0\u10dd\u10da\u10d8 (\u10d3\u10d0\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0) ConfigView.label.passwordmatch=\u10de\u10d0\u10e0\u10dd\u10da\u10d8 \u10d0\u10e5\u10e2\u10d8\u10d5\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 : ConfigView.label.passwordmatchnone=\u10d0\u10e0\u10d0 ConfigView.label.passwordmatchno=\u10d0\u10e0\u10d0 / \u10de\u10d0\u10e0\u10dd\u10da\u10d4\u10d1\u10d8 \u10d0\u10e0 \u10d4\u10db\u10d7\u10ee\u10d5\u10d4\u10d5\u10d0 ConfigView.label.passwordmatchyes=\u10d9\u10d8 ConfigView.button.save=\u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d0 ConfigView.title.short=\u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8 ConfigView.title.full=\u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8 ConsoleView.title.short=\u10d9\u10dd\u10dc\u10e1\u10dd\u10da\u10d8 ConsoleView.title.full=\u10d9\u10dd\u10dc\u10e1\u10dd\u10da\u10d8 FileItem.write=\u10e9\u10d0\u10ec\u10d4\u10e0\u10d0 FileItem.read=\u10ec\u10d0\u10d9\u10d8\u10d7\u10ee\u10d5\u10d0 FileItem.normal=\u10dc\u10dd\u10e0\u10db\u10d0\u10da\u10e3\u10e0\u10d8 FileItem.high=\u10db\u10d0\u10e6\u10d0\u10da\u10d8 FileItem.donotdownload=\u10d0\u10e0 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10dd FilesView.name=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8 FilesView.size=\u10d6\u10dd\u10db\u10d0 FilesView.done=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d3\u10d0 FilesView.firstpiece=\u10de\u10d8\u10e0\u10d5\u10d4\u10da\u10d8 \u10dc\u10d0\u10ed\u10d4\u10e0\u10d8 # FilesView.numberofpieces=# \u10dc\u10d0\u10ed\u10d4\u10e0\u10d8 FilesView.pieces=\u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8 FilesView.mode=\u10e0\u10d4\u10df\u10d8\u10db\u10d8 FilesView.priority=\u10de\u10e0\u10d8\u10dd\u10e0\u10d8\u10e2\u10d4\u10e2\u10d8 FilesView.menu.open=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 FilesView.menu.setpriority=\u10de\u10d8\u10dd\u10e0\u10d8\u10e2\u10d4\u10e2\u10d8\u10e1 \u10db\u10d8\u10d7\u10d8\u10d7\u10d4\u10d1\u10d0 FilesView.menu.setpriority.high=\u10db\u10d0\u10e6\u10d0\u10da\u10d8 FilesView.menu.setpriority.normal=\u10dc\u10dd\u10e0\u10db\u10d0\u10da\u10e3\u10e0\u10d8 FilesView.menu.setpriority.skipped=\u10d0\u10e0 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10dd FilesView.title.short=\u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 FilesView.title.full=\u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 GeneralView.section.downloaded=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 GeneralView.label.status.file=\u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8 GeneralView.label.status.pieces=\u10dc\u10d0\u10ed\u10d4\u10e0\u10d8\u10e1 \u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8 GeneralView.section.availability=\u10ee\u10d4\u10da\u10db\u10d8\u10e1\u10d0\u10ec\u10d5\u10d3\u10dd\u10db\u10d8\u10d0 GeneralView.label.status.pieces_available=\u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8\u10e1 \u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8 GeneralView.section.transfer=\u10e2\u10e0\u10d0\u10dc\u10e1\u10e4\u10d4\u10e0\u10d8 GeneralView.section.info=\u10d8\u10dc\u10e4\u10dd GeneralView.title.short=\u10db\u10d7\u10d0\u10d5\u10d0\u10e0\u10d8 GeneralView.title.full=\u10db\u10d7\u10d0\u10d5\u10d0\u10e0\u10d8 GeneralView.label.timeelapsed=\u10d3\u10e0\u10dd : GeneralView.label.remaining=\u10d3\u10d0\u10e0\u10e9\u10d4\u10dc\u10d8\u10da\u10d8 : GeneralView.label.downloaded=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 : GeneralView.label.downloadspeed=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4: GeneralView.label.maxuploads=\u10db\u10d0\u10e5\u10e1. \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 : GeneralView.label.uploaded=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 : GeneralView.label.uploadspeed=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 : GeneralView.label.seeds=\u10db\u10d7\u10d4\u10e1\u10d5\u10d4\u10da\u10d4\u10d1\u10d8 : GeneralView.label.peers=\u10de\u10d8\u10e0\u10d4\u10d1\u10d8: GeneralView.label.totalspeed=\u10e1\u10e0\u10e3\u10da\u10d8 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 : GeneralView.label.totalspeed.tooltip=\u10e1\u10e0\u10e3\u10da\u10d8 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 \u10e0\u10dd\u10db\u10d4\u10da\u10d8\u10ea \u10e7\u10d5\u10d4\u10da\u10d0 \u10d9\u10da\u10d8\u10d4\u10dc\u10e2\u10d7\u10d0\u10dc \u10d2\u10d0\u10d9\u10d0\u10d5\u10e8\u10d8\u10e0\u10d4\u10d1\u10d7. GeneralView.label.averagespeed=\u10e1\u10d0\u10e8\u10e3\u10d0\u10da\u10dd GeneralView.label.filename=\u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10e1\u10d0\u10ee\u10d4\u10da\u10d8 : GeneralView.label.totalsize=\u10e1\u10e0\u10e3\u10da\u10d8 \u10d6\u10dd\u10db\u10d0 : GeneralView.label.savein=\u10d8\u10dc\u10d0\u10ee\u10d4\u10d1\u10d0 : GeneralView.label.hash=\u10f0\u10d4\u10e8\u10d4\u10d1\u10d8 : GeneralView.label.numberofpieces=# \u10dc\u10d0\u10ed\u10d4\u10e0\u10d8 : GeneralView.label.size=\u10d6\u10dd\u10db\u10d0 : GeneralView.label.tracker=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8: GeneralView.label.updatein=\u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10d2\u10d0\u10d3\u10d0\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 : GeneralView.label.trackerurl=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 URL : GeneralView.label.trackerurlupdate=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10d2\u10d0\u10d3\u10d0\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 GeneralView.label.comment=\u10d9\u10dd\u10db\u10d4\u10dc\u10e2\u10d0\u10e0\u10d8 : ManagerItem.waiting=\u10db\u10dd\u10da\u10dd\u10d3\u10d8\u10dc\u10d8 ManagerItem.allocating=\u10da\u10dd\u10d9\u10d0\u10ea\u10d8\u10d0 ManagerItem.checking=\u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 ManagerItem.ready=\u10db\u10d6\u10d0\u10d3\u10d0\u10d0 ManagerItem.downloading=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 ManagerItem.seeding=\u10d3\u10d0\u10d7\u10d4\u10e1\u10d5\u10d0 ManagerItem.stopped=\u10e8\u10d4\u10e9\u10d4\u10e0\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 ManagerItem.error=\u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 ManagerItem.high=\u10db\u10d0\u10e6\u10d0\u10da\u10d8 ManagerItem.low=\u10d3\u10d0\u10d1\u10d0\u10da\u10d8 MinimizedWindow.name=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8: PiecesView.size=\u10d6\u10dd\u10db\u10d0 PiecesView.numberofblocks=# \u10d1\u10da\u10dd\u10d9\u10d8 PiecesView.blocks=\u10d1\u10da\u10dd\u10d9\u10d4\u10d1\u10d8 PiecesView.completed=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8 PiecesView.availability=\u10ee\u10d4\u10da\u10db\u10d8\u10e1\u10d0\u10ec\u10d5\u10d3\u10dd\u10db\u10d8\u10d0 PiecesView.reservedby=\u10e0\u10d4\u10d6\u10d4\u10e0\u10d5\u10e8\u10d8\u10d0 PiecesView.writers=\u10d1\u10da\u10dd\u10d9\u10d4\u10d1\u10d8\u10e1 \u10d9\u10dd\u10dc\u10e2\u10e0\u10d8\u10d1\u10e3\u10e2\u10dd\u10e0\u10d4\u10d1\u10d8 PiecesView.title.short=\u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8 PiecesView.title.full=\u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8 SystemTray.tooltip.seeding=%1 \u10db\u10d8\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4\u10dd\u10d1\u10e1 \u10d3\u10d0\u10d7\u10d4\u10e1\u10d5\u10d0, SystemTray.tooltip.downloading=%1 \u10db\u10d8\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4\u10dd\u10d1\u10e1 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 DownloadManager.error.filenotfound=\u10e4\u10d0\u10d8\u10da\u10d8 \u10d5\u10d4\u10e0 \u10d5\u10d8\u10de\u10dd\u10d5\u10d4 DownloadManager.error.fileempty=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d8 \u10ea\u10d0\u10e0\u10d8\u10d4\u10da\u10d8\u10d0 DownloadManager.error.filetoobig=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d8 \u10eb\u10d0\u10da\u10d8\u10d0\u10dc \u10d3\u10d8\u10d3\u10d8\u10d0 DownloadManager.error.filewithouttorrentinfo=\u10e4\u10d0\u10d8\u10da\u10e8\u10d8 \u10dc\u10d0\u10de\u10dd\u10d5\u10dc\u10d8 \u10d0\u10e0\u10d0\u10d0 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 DownloadManager.error.unsupportedencoding=\u10d9\u10dd\u10d3\u10d8\u10e0\u10d4\u10d1\u10d0\u10e1 \u10db\u10ee\u10d0\u10e0\u10d3\u10d0\u10ed\u10d4\u10e0\u10d0 \u10d0\u10e0\u10d0 \u10d0\u10e5\u10d5\u10e1 DownloadManager.error.ioerror=IO \u10e8\u10ea\u10d3\u10dd\u10db\u10d0 DownloadManager.error.sha1=\u10d0\u10e0 \u10d0\u10e0\u10e1\u10d4\u10d1\u10dd\u10d1\u10e1 \u10d0\u10da\u10d2\u10dd\u10e0\u10d8\u10d7\u10db\u10d8 (SHA1) \u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 PeerManager.status.offline=\u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d8\u10e1 \u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 PeerManager.status.checking=\u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 PeerManager.status.finished=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 PeerManager.status.finishedin=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d3\u10d0 MainWindow.upgrade.assistant=\u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d8\u10e1 \u10d0\u10e1\u10d8\u10e1\u10e2\u10d4\u10dc\u10e2\u10d8 MainWindow.upgrade.newerversion=\u10d2\u10d0\u10db\u10dd\u10e1\u10e3\u10da\u10d8\u10d0 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10e3\u10d0\u10ee\u10da\u10d4\u10e1\u10d8 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d0 \u10e9\u10d0\u10db\u10dd\u10e1\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d0\u10d3 MainWindow.upgrade.explanation=\u10d0\u10e1\u10d8\u10e1\u10e2\u10d4\u10dc\u10e2\u10d8 \u10d2\u10d0\u10d3\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d0\u10d5\u10e1 \u10d0\u10ee\u10d0\u10da \u10d5\u10d4\u10e0\u10e1\u10d8\u10d0\u10e1 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10e8\u10d8 \u10d3\u10d0 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10e1 \u10de\u10e0\u10dd\u10d2\u10e0\u10d0\u10db\u10d0\u10e1 MainWindow.upgrade.step1=\u10dc\u10d0\u10d1\u10d8\u10ef\u10d8 1: \u10d0\u10ee\u10d0\u10da\u10d8 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d8\u10e1 \u10d2\u10d0\u10dc\u10d0\u10da\u10d4\u10d1\u10d0 MainWindow.upgrade.step2=\u10dc\u10d0\u10d1\u10d8\u10ef\u10d8 2: \u10d3\u10d0\u10ee\u10e3\u10e0\u10d4 \u10db\u10d8\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d0 \u10d3\u10d0 \u10e9\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d4 Azureusis \u10d0\u10ee\u10d0\u10da\u10d8 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d0 MainWindow.upgrade.hint1=\u10e0\u10e9\u10d4\u10d5\u10d0:\t\u10e4\u10d8\u10dc\u10d8\u10e8\u10d6\u10d4 \u10d3\u10d0\u10ed\u10d4\u10e0\u10d0 \u10d2\u10d0\u10dc\u10d0\u10de\u10e0\u10dd\u10d1\u10d4\u10d1\u10e1 \u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d0\u10e1 MainWindow.upgrade.hint2=\u10e0\u10e9\u10d4\u10d5\u10d0:\t\u10d7\u10e3 \u10d2\u10e1\u10e3\u10e0\u10d7 \u10db\u10dd\u10d2\u10d5\u10d8\u10d0\u10dc\u10d4\u10d1\u10d8\u10d7 \u10d3\u10d0\u10ee\u10e3\u10e0\u10dd\u10d7 Vuze \u10d3\u10d0\u10d0\u10ed\u10d8\u10e0\u10d4\u10d7 \u10d2\u10d0\u10e3\u10e5\u10db\u10d4\u10d1\u10d0\u10e1 \u10d3\u10d0\n\t\u10d3\u10d0\u10ee\u10e3\u10e0\u10d5\u10d8\u10e1 \u10e8\u10d4\u10db\u10d3\u10d4\u10d2 Azureus2-new.jar\u2013\u10e1 \u10d2\u10d0\u10d3\u10d0\u10d0\u10e0\u10e5\u10d5\u10d8\u10d7 \u10e1\u10d0\u10ee\u10d4\u10da\u10d8 to Azureus2.jar\u2013\u10d6\u10d4 MainWindow.upgrade.error.downloading.hint=\u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0:\t\u10e8\u10d4\u10e3\u10eb\u10da\u10d4\u10d1\u10d0\u10da\u10d8\u10d0 \u10d0\u10ee\u10d0\u10da\u10d8 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d8\u10e1 \u10d2\u10d0\u10d3\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0, \u10e1\u10ea\u10d0\u10d3\u10d4\u10d7 \u10ee\u10da\u10dd\u10d5\u10dc\u10e3\u10e0\u10d0\u10d3 MainWindow.upgrade.section.info=\u10ee\u10d4\u10da\u10db\u10d8\u10e1\u10d0\u10ec\u10d5\u10d3\u10dd\u10db\u10d8\u10d0 \u10d0\u10d0\u10da\u10d8 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d0 MainWindow.upgrade.section.manual=\u10ee\u10d4\u10da\u10dd\u10d5\u10dc\u10e3\u10e0\u10d8 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 MainWindow.upgrade.section.automatic=\u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 MainWindow.upgrade.tooltip.progressbar=\u10d2\u10d0\u10d3\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10de\u10e0\u10dd\u10d2\u10e0\u10d4\u10e1\u10d8\u10e1 \u10d5\u10d8\u10d6\u10e3\u10d0\u10da\u10d8\u10d6\u10d0\u10ea\u10d8\u10d0 Button.next=\u10e8\u10d4\u10db\u10d3\u10d4\u10d2 Button.finish=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d0 Button.cancel=\u10d2\u10d0\u10e3\u10e5\u10db\u10d4\u10d1\u10d0 LocaleUtil.title=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10d9\u10dd\u10d3\u10d8\u10e0\u10d4\u10d1\u10d0 LocaleUtil.section.chooseencoding=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10d9\u10dd\u10d3\u10d8\u10e0\u10d4\u10d1\u10d0 LocaleUtil.label.chooseencoding=\u10d2\u10d7\u10ee\u10dd\u10d5 \u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10dd \u10e1\u10d0\u10e3\u10d9\u10d4\u10d7\u10d4\u10e1\u10dd \u10d7\u10d0\u10dc\u10ee\u10d5\u10d3\u10d4\u10dc\u10d8\u10da\u10d8 \u10d9\u10dd\u10d3\u10d8\u10e0\u10d4\u10d1\u10d0 LocaleUtil.label.checkbox.rememberdecision=\u10d3\u10d0\u10d8\u10db\u10d0\u10ee\u10e1\u10dd\u10d5\u10e0\u10d4 \u10d0\u10e0\u10e9\u10d4\u10d5\u10d0\u10dc\u10d8 \u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 LocaleUtil.column.encoding=\u10d9\u10dd\u10d3\u10d8\u10e0\u10d4\u10d1\u10d0 IrcClient.copyright=\u10d5\u10d8\u10e7\u10d4\u10dc\u10d4\u10d1 PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=\u10d5\u10e3\u10d4\u10e0\u10d7\u10d3\u10d4\u10d1\u10d8 IrcClient.connected=\u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 IrcClient.joining=\u10e8\u10d4\u10d5\u10d3\u10d8\u10d5\u10d0\u10e0 IrcClient.channel=\u10d0\u10e0\u10ee\u10d8 IrcClient.joined=\u10e8\u10d4\u10db\u10d4\u10d5\u10d8 IrcClient.error=\u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 IrcClient.hasjoined=\u10e8\u10d4\u10d5\u10d4\u10d3\u10d8 IrcClient.haskicked=\u10d2\u10d0\u10db\u10d0\u10d2\u10d3\u10d4\u10e1 IrcClient.hasleft=\u10d2\u10d0\u10d5\u10d4\u10d3\u10d8 IrcClient.nowknown=\u10ea\u10dc\u10dd\u10d1\u10d8\u10da\u10d8\u10d0 \u10e0\u10dd\u10d2\u10dd\u10e0\u10ea IrcClient.topicforchannel=\u10d0\u10e0\u10ee\u10d8\u10e1 \u10d7\u10d4\u10db\u10d0\u10e2\u10d8\u10d9\u10d0 IrcClient.disconnected=\u10d2\u10d0\u10db\u10dd\u10d5\u10d4\u10e0\u10d7\u10d4 IrcClient.noNick=\u10d0\u10e0 \u10d0\u10e0\u10d8\u10e1 \u10db\u10d8\u10d7\u10d8\u10d7\u10d4\u10d1\u10e3\u10da\u10d8 \u10dc\u10d8\u10d9\u10d8. \u10d2\u10d7\u10ee\u10dd\u10d5\u10d7 \u10e8\u10d4\u10ee\u10d5\u10d8\u10d3\u10d4\u10d7 \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10d4\u10d1\u10d8\u10e1 \u10e4\u10d0\u10dc\u10ef\u10d0\u10e0\u10d0\u10e8\u10d8 IrcView.actionnotsupported=\u10d4\u10e1 \u10db\u10dd\u10e5\u10db\u10d4\u10d3\u10d4\u10d1\u10d0 \u10d0\u10e0 \u10d0\u10e0\u10d8\u10e1 \u10db\u10ee\u10d0\u10e0\u10d3\u10d0\u10ed\u10d4\u10e0\u10d8\u10da\u10d8 IrcView.clientsconnected=\u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d4\u10d1\u10d8 IrcView.privateto=\u10d5\u10d8\u10e1 IrcView.privatefrom=\u10d5\u10d8\u10e1\u10d2\u10d0\u10dc IrcView.noticefrom=\u10e8\u10d4\u10e2\u10ec\u10dd\u10d1\u10d8\u10dc\u10d4\u10d1\u10d0 : IrcView.errormsg=\u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8 \u10e1\u10d8\u10dc\u10e2\u10d0\u10e5\u10e1\u10d8 /msg : /msg \u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d8\u10e1 \u10e2\u10d4\u10e5\u10e1\u10e2\u10d8 IrcView.help=Valid commands are :\n . /help : displays this message\n . /nick | /name : changes your name \n . /me action : sends an action \n . /msg nick message : sends a private message to \n . /r message : reply to last private message\n . /join #channel : changes current channel PasswordWindow.title=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8 \u10d3\u10d0\u10d1\u10da\u10dd\u10d9\u10d8\u10da\u10d8\u10d0 PasswordWindow.passwordprotected=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8 \u10d3\u10d0\u10ea\u10e3\u10da\u10d8\u10d0 \u10de\u10d0\u10e0\u10dd\u10da\u10d8\u10d7.\n\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10e4\u10d0\u10dc\u10ef\u10e0\u10d8\u10e1 \u10d2\u10d0\u10e1\u10d0\u10ee\u10e1\u10dc\u10d4\u10da\u10d0\u10d3 \u10e8\u10d4\u10d8\u10e7\u10d5\u10d4\u10dc\u10d4\u10d7 \u10d7\u10e5\u10d5\u10d4\u10dc\u10d8 \u10de\u10d0\u10e0\u10dd\u10da\u10d8 : Button.ok=\u10d3\u10d8\u10d0\u10ee TrackerChangerWindow.title=\u10d3\u10d0\u10d0\u10db\u10d0\u10e2\u10d4 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 TrackerChangerWindow.newtracker=\u10e8\u10d4\u10d8\u10e7\u10d5\u10d0\u10dc\u10d4 \u10d0\u10ee\u10d0\u10da\u10d8 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 url PeersView.discarded=\u10e3\u10d0\u10e0\u10e7\u10dd\u10e4\u10d8\u10da\u10d8\u10d0 PeersView.discarded.info=\u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 \u10e0\u10dd\u10db\u10d4\u10da\u10d8\u10ea \u10d7\u10e5\u10d5\u10d4\u10dc\u10d7\u10d0\u10dc \u10e0\u10d0\u10e6\u10d0\u10ea\u10dc\u10d0\u10d8\u10e0\u10d0\u10d3 \u10db\u10dd\u10ee\u10d5\u10d3\u10d0, \u10d0\u10db\u10d8\u10e2\u10dd\u10db\u10d0\u10ea \u10d5\u10d8\u10e8\u10dd\u10e0\u10d4\u10d1\u10d7 \u10d7\u10d0\u10d5\u10d8\u10d3\u10d0. discarded=\u10e3\u10d0\u10e0\u10e7\u10dd\u10e4\u10d8\u10da\u10d8\u10d0 MyTorrentsView.menu.move=\u10d2\u10d0\u10d3\u10d0\u10e2\u10d0\u10dc\u10d0 MyTorrentsView.menu.moveUp=\u10d6\u10d4\u10d5\u10d8\u10d7 MyTorrentsView.menu.moveDown=\u10e5\u10d5\u10d4\u10d5\u10d8\u10d7 GeneralView.label.hashfails=\u10f0\u10d4\u10e8\u10d8\u10e1 \u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 : GeneralView.label.shareRatio=\u10d6\u10d8\u10d0\u10e0\u10d8 \u10e0\u10d4\u10d8\u10e2\u10d8\u10dc\u10d2\u10d8 : ConfigView.section.downloadManagement=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d4\u10d1\u10d8\u10e1 \u10db\u10d4\u10dc\u10d4\u10ef\u10db\u10d4\u10dc\u10e2\u10d8 ConfigView.text.peers=\u10de\u10d8\u10e0\u10d4\u10d1\u10d8 ConfigView.label.checkOncompletion=\u10d2\u10d0\u10d3\u10d0\u10d0\u10db\u10dd\u10ec\u10db\u10d4 \u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8 \u10e0\u10dd\u10ea\u10d0 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d3\u10d4\u10d1\u10d0 wizard.title=\u10e8\u10d4\u10e5\u10db\u10d4\u10dc\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 wizard.previous=< \u10e3\u10d9\u10d0\u10dc wizard.next=\u10ec\u10d8\u10dc > wizard.finish=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d0 wizard.mode=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 / \u10e0\u10d4\u10df\u10d8\u10db\u10d8 wizard.tracker=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4: wizard.invalidurl=\u10d4\u10e1 URL \u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8\u10d0 wizard.singlefile=\u10d4\u10e0\u10d7\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8 wizard.singlefile.help=\u10e8\u10d4\u10e5\u10db\u10d4\u10d1\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 \u10d4\u10e0\u10d7\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8\u10e1\u10d0\u10d2\u10d0\u10dc wizard.directory=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 wizard.directory.help=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8\u10d3\u10d0\u10dc \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10e8\u10d4\u10e5\u10db\u10dc\u10d0 wizard.choosefile=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10e4\u10d0\u10d8\u10da\u10d8 wizard.file=\u10e4\u10d0\u10d8\u10da\u10d8 : wizard.browse=\u10db\u10d8\u10db\u10dd\u10ee\u10d8\u10da\u10d5\u10d0... wizard.choosedirectory=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 wizard.invalidfile=\u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8! wizard.invaliddirectory=\u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 wizard.torrentFile=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d8 wizard.choosetorrent=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10e8\u10d4\u10e1\u10d0\u10e5\u10db\u10d4\u10dc\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d8 wizard.information=\u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 wizard.notimplemented=\u10ef\u10d4\u10e0 \u10ef\u10d4\u10e0\u10dd\u10d1\u10d8\u10d7 \u10d0\u10e0 \u10db\u10e3\u10e8\u10d0\u10dd\u10d1\u10e1 wizard.progresstitle=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10e8\u10d4\u10e5\u10db\u10dc\u10d0 wizard.savingfile=\u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d0... wizard.filesaved=\u10e4\u10d0\u10d8\u10da\u10d8 \u10e8\u10d4\u10dc\u10d0\u10ee\u10e3\u10da\u10d8\u10d0. wizard.close=\u10d3\u10d0\u10ee\u10e3\u10e0\u10d4 Torrent.create.progress.piecelength=\u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d8\u10d2\u10e0\u10eb\u10d4: Torrent.create.progress.piececount=\u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8\u10e1 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0: Torrent.create.progress.totalfilesize=\u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d0\u10d4\u10e0\u10d7\u10dd \u10d6\u10dd\u10db\u10d0: Torrent.create.progress.totalfilecount=\u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d0\u10d4\u10e0\u10d7\u10dd \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0: Torrent.create.progress.parsingfiles=\u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10de\u10d0\u10e0\u10e1\u10d8\u10e0\u10d4\u10d1\u10d0 Torrent.create.progress.hashing=\u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10f0\u10d4\u10e8\u10d8\u10e0\u10d4\u10d1\u10d0 MainWindow.upgrade.downloadingfrom=\u10d8\u10e2\u10d5\u10d8\u10e0\u10d7\u10d4\u10d1\u10d0 : MainWindow.menu.view.ipFilter=Ip \u10e4\u10d8\u10da\u10e2\u10e0\u10d4\u10d1\u10d8 ConfigView.section.ipfilter=Ip \u10e4\u10d8\u10da\u10e2\u10e0\u10d4\u10d1\u10d8 ConfigView.section.ipfilter.description=\u10d0\u10e6\u10ec\u10d4\u10e0\u10d0 ConfigView.section.ipfilter.start=\u10e1\u10d0\u10ec\u10e7\u10d8\u10e1\u10d8 Ip ConfigView.section.ipfilter.end=\u10d1\u10dd\u10da\u10dd Ip ConfigView.section.ipfilter.add=\u10d3\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10d0 ConfigView.section.ipfilter.remove=\u10d0\u10db\u10dd\u10d0\u10d2\u10d3\u10d4 ConfigView.section.ipfilter.edit=\u10e8\u10d4\u10ea\u10d5\u10da\u10d0 ConfigView.section.ipfilter.save=\u10e8\u10d4\u10d8\u10dc\u10d0\u10ee\u10d4 ConfigView.section.ipfilter.editFilter=\u10e4\u10d8\u10da\u10e2\u10e0\u10d8\u10e1 \u10e8\u10d4\u10ea\u10d5\u10da\u10d0 ConfigView.section.ipfilter.enable=\u10e9\u10d0\u10e0\u10d7\u10d5\u10d0 PeersView.menu.close=&\u10d3\u10d0\u10ee\u10e3\u10e0\u10d4 seedmore.title=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 \u10e3\u10d9\u10d5\u10d4 \u10d0\u10e0 \u10d8\u10d7\u10d4\u10e1\u10d4\u10d1\u10d0 seedmore.uploadmore=Having a share ratio under 100% is not a good thing for the bittorrent network.\nYou should let this torrent seed a little bit more.\nAre you sure you want to proceed? ConfigView.label.showpopuponclose=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 \u10d3\u10d0\u10e1\u10e2\u10e3\u10e0\u10d8\u10e1 \u10d3\u10d8\u10d0\u10da\u10dd\u10d2\u10d8 \u10e0\u10dd\u10ea\u10d0 \u10e9\u10d4\u10e0\u10d3\u10d4\u10d1\u10d0 \u10d3\u10d0\u10d7\u10d4\u10e1\u10d5\u10d0 1\u2013\u10d6\u10d4 \u10dc\u10d0\u10d9\u10da\u10d4\u10d1\u10d8 \u10d6\u10d8\u10d0\u10e0\u10d8 \u10e0\u10d4\u10d8\u10e2\u10d8\u10dc\u10d2\u10d8\u10d7 ConfigView.label.startNumSeeds=\n\u10d3\u10d0\u10d8\u10ec\u10e7\u10d4 \u10d3\u10d0\u10d7\u10d4\u10e1\u10d5\u10d0 \u10d7\u10e3 \u10dc\u10d0\u10d9\u10da\u10d4\u10d1\u10d8\u10d0\n \u10d6\u10d4 - \u10d0\u10e3\u10e5\u10db\u10d4\u10d1\u10e1 \u10e1\u10ee\u10d5\u10d0 \u10e7\u10d5\u10d4\u10da\u10d0 \u10ec\u10d4\u10e1\u10e1 ConfigView.label.seeds=\u10db\u10d7\u10d4\u10e1\u10d5\u10d4\u10da\u10d4\u10d1\u10d8 ConfigView.section.seeding=\u10d7\u10d4\u10e1\u10d5\u10d0 MyTorrentsView.menu.removeand=\u10d0\u10db\u10dd\u10d2\u10d3\u10d4\u10d1\u10d0 \u10d3\u10d0 MyTorrentsView.menu.removeand.deletetorrent=.torrent\u2013\u10d8\u10e1 \u10ec\u10d0\u10e8\u10da\u10d0 MyTorrentsView.menu.removeand.deletedata=\u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d8\u10e1 \u10ec\u10d0\u10e8\u10da\u10d0 MyTorrentsView.menu.removeand.deleteboth=\u10dd\u10e0\u10d8\u10d5\u10d4\u10e1 \u10ec\u10d0\u10e8\u10da\u10d0 deletedata.title=!!! Warning !!! MainWindow.menu.file.configure=\u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10d8\u10e1 \u10dd\u10e1\u10e2\u10d0\u10e2\u10d8 configureWizard.title=\u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10d8\u10e1 \u10dd\u10e1\u10e2\u10d0\u10e2\u10d8 configureWizard.welcome.title=\u10db\u10dd\u10d2\u10d4\u10e1\u10d0\u10da\u10db\u10d4\u10d1\u10d0\u10d7 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10d8\u10e1 \u10dd\u10e1\u10e2\u10d0\u10e2\u10d8 configureWizard.welcome.message=\u10d4\u10e1 \u10dd\u10e1\u10e2\u10d0\u10e2\u10d8 \u10d3\u10d0\u10d2\u10d4\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10d0\u10d7 \u10db\u10dd\u10d0\u10ec\u10e7\u10dd\u10d7 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8. \u10d3\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10d8\u10d7\u10d8 \u10dd\u10e4\u10ea\u10d8\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10db\u10d8\u10db\u10d0\u10e0\u10d7\u10d4\u10d7 \u10d8\u10dc\u10e1\u10e2\u10e0\u10e3\u10db\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8->\u10de\u10d0\u10e0\u10d4\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8\u10e1 \u10db\u10d4\u10dc\u10d8\u10e3\u10e1. configureWizard.transfer.title=\u10e2\u10e0\u10d0\u10dc\u10e1\u10e4\u10d4\u10e0\u10d4\u10d1\u10d8\u10e1 \u10d3\u10d0 \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d8\u10e1 \u10db\u10dd\u10ec\u10e7\u10dd\u10d1\u10d0 configureWizard.transfer.hint=\u10e0\u10e9\u10d4\u10d5\u10d0 : \u10e3\u10db\u10ef\u10dd\u10d1\u10d4\u10e1\u10d8\u10d0 \u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10dd\u10d7 \u10e0\u10d4\u10d0\u10da\u10e3\u10e0\u10d6\u10d4 \u10dd\u10d3\u10dc\u10d0\u10d5 \u10d3\u10d0\u10d1\u10d0\u10da\u10d8 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d8\u10e1 \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d0. configureWizard.transfer.message=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4\u10d7 \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d8\u10e1 \u10e2\u10d8\u10de\u10d8. \u10d2\u10d8\u10d7\u10d5\u10d0\u10da\u10d8\u10e1\u10ec\u10d8\u10dc\u10d4\u10d7, \u10e0\u10dd\u10db \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d8\u10e1 \u10e8\u10d4\u10d6\u10e6\u10e3\u10d3\u10d5\u10d0 \u10e8\u10d4\u10e1\u10d0\u10d1\u10d0\u10db\u10d8\u10e1\u10d0\u10d3 \u10e3\u10d0\u10e0\u10e7\u10dd\u10e4\u10d8\u10d7\u10d0\u10d3 \u10db\u10dd\u10e5\u10db\u10d4\u10d3\u10d4\u10d1\u10e1 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4\u10d6\u10d4. \u10e0\u10d0\u10db\u10dd\u10d3\u10d4\u10dc\u10d8\u10db\u10d4 torrent-\u10d8\u10e1 \u10d4\u10e0\u10d7\u10d3\u10e0\u10dd\u10e3\u10da\u10d8 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0\u10ea \u10d0\u10dc\u10d4\u10da\u10d4\u10d1\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4\u10e1 \u10e1\u10d0\u10d2\u10e0\u10eb\u10dc\u10dd\u10d1\u10da\u10d0\u10d3. \u10e9\u10d5\u10d4\u10dc\u10d8 \u10e0\u10d4\u10d9\u10dd\u10db\u10d4\u10dc\u10d3\u10d0\u10ea\u10d8\u10d0\u10d0 5\u10d9\u10d1/\u10ec\u10db \u10d4\u10e0\u10d7 torrent-\u10d6\u10d4 \u10e0\u10dd\u10d2\u10dd\u10e0\u10ea \u10d1\u10dd\u10da\u10dd \u10db\u10d8\u10dc\u10d8\u10db\u10e3\u10db\u10d8. \u10e0\u10d0\u10ea \u10e3\u10e4\u10dd\u10e0 \u10e9\u10e5\u10d0\u10e0\u10d0 \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d0\u10d5\u10d7,\u10db\u10d8\u10d7 \u10e3\u10e4\u10dd\u10e0 \u10e9\u10e5\u10d0\u10e0\u10d0 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d0\u10d5 (torrent \u10e5\u10e1\u10d4\u10da\u10d4\u10d1\u10d8\u10e1 \u10de\u10d0\u10e2\u10d8\u10d5\u10d8\u10e1\u10ea\u10d4\u10db\u10d8\u10d3\u10d0\u10dc \u10d2\u10d0\u10db\u10dd\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4). configureWizard.transfer.connection=\u10ee\u10d0\u10d6\u10d8 configureWizard.transfer.connection.0=\u10ee\u10d4\u10da\u10dd\u10d5\u10dc\u10e3\u10e0\u10d8 configureWizard.transfer.connection.1=\u10db\u10dd\u10d3\u10d4\u10db\u10d8 configureWizard.transfer.connection.2=adsl/cable xxx/128 \u10d9\u10d1\u10ec\u10db configureWizard.transfer.connection.3=adsl/cable xxx/256 \u10d9\u10d1\u10ec\u10db configureWizard.transfer.connection.4=adsl/cable xxx/384 \u10d9\u10d1\u10ec\u10db configureWizard.transfer.connection.5=adsl/cable xxx/512 \u10d9\u10d1\u10ec\u10db configureWizard.transfer.connection.6=adsl/cable xxx/768 \u10d9\u10d1\u10ec\u10db configureWizard.transfer.connection.7=adsl/cable xxx/1024 \u10d9\u10d1\u10ec\u10db configureWizard.transfer.maxUpSpeed=\u10db\u10d0\u10e5\u10e1. \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 (\u10d9\u10d1/\u10ec\u10db) configureWizard.transfer.maxActiveTorrents=\u10d0\u10e5\u10e2\u10d8\u10e3\u10e0\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8\u10e1 \u10db\u10d0\u10e5\u10e1. \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 configureWizard.transfer.maxDownloads=\u10d2\u10d0\u10d3\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d4\u10d1\u10d8\u10e1 \u10db\u10d0\u10e5\u10e1. \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 configureWizard.transfer.maxUploadsPerTorrent=\u10db\u10d0\u10e5\u10e1. \u10d0\u10d7\u10d5\u10d8\u10e0\u10d7\u10d5\u10d4\u10d1\u10d8 \u10d4\u10e0\u10d7 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d6\u10d4 configureWizard.nat.title=NAT / \u10e1\u10d4\u10e0\u10d5\u10d4\u10e0\u10d8\u10e1 \u10de\u10dd\u10e0\u10e2\u10d8 configureWizard.nat.message=\u10d1\u10d8\u10e2\u2013\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10db\u10d0\u10e5\u10e1\u10d8\u10d0\u10db\u10d0\u10da\u10e3\u10e0\u10d0\u10d3 \u10e1\u10d0\u10e1\u10d0\u10e0\u10d2\u10d4\u10d1\u10da\u10dd \u10db\u10dd\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1, \u10e0\u10d4\u10d9\u10dd\u10db\u10d4\u10dc\u10d3\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 \u10e0\u10dd\u10db \u10d8\u10e7\u10dd\u10d7 \u10e1\u10e0\u10e3\u10da\u10d0\u10d3 \u10ee\u10d4\u10da\u10db\u10d8\u10e1\u10d0\u10ec\u10d5\u10d3\u10dd\u10db\u10d8 \u10d8\u10dc\u10e2\u10d4\u10e0\u10dc\u10d4\u10e2\u10d8\u10d3\u10d0\u10dc. \u10ec\u10d8\u10dc\u10d0\u10e1\u10ec\u10d0\u10e0\u10d8 \u10de\u10dd\u10e0\u10e2\u10d8 \u10d1\u10d8\u10e2\u2013\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10d0\u10e0\u10d8\u10e1 6881. \u10d4\u10e1 \u10d8\u10e1\u10dc\u10e1\u10e2\u10e0\u10e3\u10db\u10d4\u10dc\u10e2\u10d8 \u10e2\u10d4\u10e1\u10e2\u10d8\u10e0\u10d0\u10d1\u10d0\u10e1 \u10e3\u10e2\u10d0\u10e0\u10d4\u10d1\u10e1 \u10d0\u10dc \u10ea\u10d5\u10da\u10d8\u10e1 \u10de\u10dd\u10e0\u10e2\u10d8\u10e1 \u10dc\u10dd\u10db\u10d4\u10e0\u10e1. configureWizard.nat.test=\u10e2\u10d4\u10e1\u10e2\u10d8 configureWizard.nat.testing=\u10de\u10dd\u10e0\u10e2\u10d8\u10e1 \u10e2\u10d4\u10e1\u10e2\u10d8\u10e0\u10d4\u10d1\u10d0 configureWizard.nat.ok=\u10d0\u10e0\u10d8\u10e1 ! configureWizard.nat.ko=NAT \u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 configureWizard.nat.unable=\u10e2\u10d4\u10e1\u10e2\u10d8\u10e0\u10d4\u10d1\u10d0 \u10e8\u10d4\u10e3\u10eb\u10da\u10d4\u10d1\u10d4\u10da\u10d8\u10d0 configureWizard.file.title=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 / \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 configureWizard.file.message1=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8 \u10e8\u10d4\u10d8\u10dc\u10d0\u10ee\u10d0\u10d5\u10e1 \u10d2\u10d0\u10ee\u10e1\u10dc\u10d8\u10da \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10e1 \u10db\u10d8\u10d7\u10d8\u10d7\u10d4\u10d1\u10e3\u10da \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10e8\u10d8, \u10e8\u10d4\u10d2\u10d8\u10eb\u10da\u10d8\u10d0 \u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10dd \u10e0\u10dd\u10db\u10d4\u10da\u10e8\u10d8: configureWizard.file.path=\u10d2\u10d6\u10d0 configureWizard.file.browse=\u10db\u10d8\u10db\u10dd\u10ee\u10d8\u10da\u10d5\u10d0 configureWizard.file.message2=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10e1 \u10e8\u10d4\u10e3\u10eb\u10da\u10d8\u10d0 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10d2\u10d0\u10d2\u10e0\u10eb\u10d4\u10da\u10d4\u10d1\u10d0 \u10db\u10e7\u10d4\u10e1\u10d4\u10e3\u10da\u10d0\u10d3, \u10d0\u10db\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10e1 \u10d3\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10d8\u10d7\u10d8 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 \u10e9\u10d0\u10d4\u10db\u10d0\u10e2\u10d4\u10d1\u10d0 \u10ee\u10dd\u10da\u10db\u10d4. \u10d0\u10db \u10e4\u10e3\u10dc\u10e5\u10ea\u10d8\u10d8\u10e1 \u10d2\u10d0\u10db\u10dd\u10e7\u10d4\u10dc\u10d4\u10d1\u10d8\u10e1\u10d0\u10e1, \u10e8\u10d4\u10d2\u10d8\u10eb\u10da\u10d8\u10d0 \u10dc\u10d0\u10ec\u10d8\u10da\u10dd\u10d1\u10e0\u10d8\u10d5 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8 \u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8\u10e1 \u10d2\u10d0\u10d2\u10e0\u10eb\u10d4\u10da\u10d4\u10d1\u10d0\u10ea. configureWizard.file.fastResume=\u10e9\u10d0\u10e0\u10d7\u10d4 "\u10e1\u10ec\u10e0\u10d0\u10e4\u10d8 \u10d2\u10d0\u10d2\u10e0\u10eb\u10d4\u10da\u10d4\u10d1\u10d0" configureWizard.file.invalidPath=\u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 configureWizard.finish.title=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 configureWizard.finish.message=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8 \u10db\u10dd\u10ec\u10e7\u10dd\u10d1\u10d8\u10da\u10d8\u10d0, \u10e8\u10d4\u10d2\u10d0\u10e0\u10d2\u10dd\u10d7! wizard.close.confirmation=\u10d3\u10d0\u10e1\u10e2\u10e3\u10e0\u10d8 wizard.close.message=\u10d2\u10e1\u10e3\u10e0\u10d7 \u10d0\u10db \u10dd\u10e1\u10e2\u10d0\u10e2\u10d8\u10e1 \u10e9\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10d2\u10d0\u10e8\u10d5\u10d4\u10d1\u10d8\u10e1\u10d0\u10e1? exportTorrentWizard.title=XML Export a torrent exportTorrentWizard.torrentfile.title=\u10e8\u10d4\u10db\u10dd\u10db\u10d0\u10d5\u10d0\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10e8\u10d4\u10e0\u10e9\u10d4\u10d5\u10d0 exportTorrentWizard.torrentfile.message=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d8 \u10d4\u10e5\u10e1\u10de\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 exportTorrentWizard.torrentfile.path=\u10d2\u10d6\u10d0 exportTorrentWizard.torrentfile.browse=\u10db\u10d8\u10db\u10dd\u10ee\u10d8\u10da\u10d5\u10d0 exportTorrentWizard.torrentfile.invalidPath=\u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d8 exportTorrentWizard.exportfile.title=\u10e8\u10d4\u10e0\u10e9\u10d4\u10e3\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10d4\u10e5\u10e1\u10de\u10dd\u10e0\u10e2\u10d8 exportTorrentWizard.exportfile.message=\u10e8\u10d4\u10d8\u10e7\u10d5\u10d0\u10dc\u10d4 xml \u10e4\u10d0\u10d8\u10da\u10d8 \u10d4\u10e5\u10e1\u10de\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 exportTorrentWizard.exportfile.path=\u10d2\u10d6\u10d0 exportTorrentWizard.exportfile.browse=\u10db\u10d8\u10db\u10dd\u10ee\u10d8\u10da\u10d5\u10d0 exportTorrentWizard.exportfile.invalidPath=\u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8 \u10e1\u10d0\u10d4\u10e5\u10e1\u10de\u10dd\u10e0\u10e2\u10dd \u10e4\u10d0\u10d8\u10da\u10d8 exportTorrentWizard.finish.title=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 exportTorrentWizard.finish.message=\u10d4\u10e5\u10e1\u10de\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d0 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d3\u10d0 \u10ec\u10d0\u10e0\u10db\u10d0\u10e2\u10d4\u10d1\u10d8\u10d7 exportTorrentWizard.process.inputfilebad.title=\u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d8 exportTorrentWizard.process.inputfilebad.message=\u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 \u10d3\u10d0\u10e4\u10d8\u10e5\u10e1\u10d8\u10e0\u10d3\u10d0 \u10e8\u10d4\u10db\u10dd\u10db\u10d0\u10d5\u10d0\u10da \u10e4\u10d0\u10d8\u10d6\u10d4 \u10db\u10d8\u10db\u10d0\u10e0\u10d7\u10d5\u10d8\u10e1\u10d0\u10e1: exportTorrentWizard.process.outputfileexists.title=\u10e4\u10d0\u10d8\u10da\u10d8 \u10d0\u10e0\u10e1\u10d4\u10d1\u10dd\u10d1\u10e1 exportTorrentWizard.process.outputfileexists.message=\u10d2\u10d0\u10db\u10dd\u10e1\u10d0\u10d5\u10d0\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8 \u10d0\u10e0\u10e1\u10d4\u10d1\u10dd\u10d1\u10e1 - \u10d2\u10d0\u10d3\u10d0\u10d5\u10d0\u10ec\u10d4\u10e0\u10dd? exportTorrentWizard.process.torrentfail.title=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10ec\u10d0\u10d9\u10d8\u10d7\u10ee\u10d5\u10d0 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 exportTorrentWizard.process.exportfail.title=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10d4\u10e5\u10de\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d0 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 exportTorrentWizard.process.unknownfail.title=\u10d2\u10d0\u10e3\u10d7\u10d5\u10d0\u10da\u10d8\u10e1\u10ec\u10d8\u10dc\u10d4\u10d1\u10d4\u10da\u10d8 \u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 importTorrentWizard.title=XML \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10d8\u10db\u10de\u10dd\u10e0\u10e2\u10d8 importTorrentWizard.torrentfile.title=\u10e8\u10d4\u10e1\u10d0\u10d5\u10d0\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10e8\u10d4\u10e0\u10e9\u10d4\u10d5\u10d0 importTorrentWizard.torrentfile.message=\u10e8\u10d4\u10d8\u10e7\u10d5\u10d0\u10dc\u10d4 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d8 \u10d8\u10db\u10de\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 importTorrentWizard.torrentfile.path=\u10d2\u10d6\u10d0 importTorrentWizard.torrentfile.browse=\u10db\u10d8\u10db\u10dd\u10ee\u10d8\u10da\u10d5\u10d0 importTorrentWizard.torrentfile.invalidPath=\u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d8 importTorrentWizard.importfile.title=\u10e8\u10d4\u10db\u10dd\u10d8\u10e2\u10d0\u10dc\u10d4 \u10db\u10dd\u10dc\u10d8\u10e8\u10dc\u10e3\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 importTorrentWizard.importfile.message=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 xml \u10e4\u10d0\u10d8\u10da\u10d8 \u10d8\u10db\u10de\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 importTorrentWizard.importfile.path=\u10d2\u10d6\u10d0 importTorrentWizard.importfile.browse=\u10db\u10d8\u10db\u10dd\u10ee\u10d8\u10da\u10d5\u10d0 importTorrentWizard.importfile.invalidPath=\u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8 \u10d8\u10db\u10de\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d0\u10d3\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8 importTorrentWizard.finish.title=\u10d3\u10d0\u10e1\u10d0\u10e1\u10e0\u10e3\u10da\u10d8 importTorrentWizard.finish.message=\u10d8\u10db\u10de\u10dd\u10e0\u10e2\u10d8 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d3\u10d0 \u10ec\u10d0\u10e0\u10db\u10d0\u10e2\u10d4\u10d1\u10d8\u10d7 importTorrentWizard.process.inputfilebad.title=\u10e8\u10d4\u10db\u10dd\u10e1\u10d0\u10e2\u10d0\u10dc\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8 \u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8\u10d0 importTorrentWizard.process.inputfilebad.message=\u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0\u10d0 \u10e8\u10d4\u10e1\u10d0\u10d5\u10d0\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10db\u10d8\u10db\u10d0\u10e0\u10d7\u10d5\u10d8\u10e1\u10d0\u10e1 : importTorrentWizard.process.outputfileexists.title=\u10e4\u10d0\u10d8\u10da\u10d8 \u10d0\u10e0\u10e1\u10d4\u10d1\u10dd\u10d1\u10e1 importTorrentWizard.process.outputfileexists.message=\u10d2\u10d0\u10db\u10dd\u10e1\u10d0\u10d5\u10d0\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8 \u10e3\u10d9\u10d5\u10d4 \u10d0\u10e0\u10e1\u10d4\u10d1\u10dd\u10d1\u10e1 - \u10d2\u10d0\u10d3\u10d0\u10d5\u10d0\u10ec\u10d4\u10e0\u10dd? importTorrentWizard.process.torrentfail.title=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10e9\u10d0\u10ec\u10d4\u10e0\u10d0 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 importTorrentWizard.process.importfail.title=\u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1\u10d8\u10db\u10de\u10dd\u10e0\u10e2\u10d8 importTorrentWizard.process.unknownfail.title=\u10d2\u10d0\u10e3\u10d7\u10d5\u10d0\u10da\u10d8\u10e1\u10ec\u10d8\u10d4\u10dc\u10d1\u10d4\u10da\u10d8 \u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 ConfigView.label.bindip=\u10db\u10d8\u10d0\u10d1\u10d8 \u10da\u10dd\u10d9\u10d0\u10da\u10e3\u10e0\u10d8 IP \u10db\u10d8\u10e1\u10d0\u10db\u10d0\u10e0\u10d7\u10e1 or interface ConfigView.label.zeronewfiles=\u10d2\u10d0\u10dc\u10d0\u10d7\u10d0\u10d5\u10e1\u10d4 \u10d3\u10d0 \u10e8\u10d4\u10d0\u10d5\u10e1\u10d4 \u10dc\u10e3\u10da\u10d4\u10d1\u10d8\u10d7 \u10d0\u10ee\u10d0\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 \u10e8\u10d4\u10e5\u10db\u10dc\u10d8\u10e1\u10d0\u10e1 ConfigView.label.zeronewfiles.tooltip=\u10ee\u10d4\u10da\u10e1 \u10e3\u10ec\u10e7\u10dd\u10d1\u10e1 \u10e4\u10e0\u10d0\u10d2\u10db\u10d4\u10dc\u10e2\u10d0\u10ea\u10d8\u10d8\u10e1 \u10e8\u10d4\u10db\u10ea\u10d8\u10e0\u10d4\u10d1\u10d0\u10e1 ConfigView.section.stats=\u10e1\u10e2\u10d0\u10e2\u10d8\u10e1\u10e2\u10d8\u10d9\u10d0 ConfigView.section.stats.enable=\u10e9\u10d0\u10e0\u10d7\u10d4 ConfigView.section.stats.defaultsavepath=\u10e1\u10e2\u10d0\u10e2\u10d8\u10e1\u10e2\u10d8\u10d9\u10d8\u10e1 \u10e8\u10d4\u10e1\u10d0\u10dc\u10d0\u10ee\u10d8 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 ConfigView.section.stats.choosedefaultsavepath=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4\u10d7 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 \u10e1\u10e2\u10d0\u10e2\u10d8\u10e1\u10e2\u10d8\u10d9\u10d8\u10e1 \u10e8\u10d4\u10e1\u10d0\u10dc\u10d0\u10ee\u10d0\u10d3 ConfigView.section.stats.savefreq=\u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d8\u10e1 \u10e1\u10d8\u10ee\u10e8\u10d8\u10e0\u10d4 ConfigView.section.stats.minutes=\u10ec\u10d7 ConfigView.section.stats.hours=\u10e1\u10d7 ConfigView.section.stats.seconds=\u10ec\u10db ConfigView.section.stats.savefile=\u10e1\u10e2\u10d0\u10e2\u10d8\u10e1\u10e2\u10d8\u10d9\u10d8\u10e1 \u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10e1\u10d0\u10ee\u10d4\u10da\u10d8 MyTorrentsView.menu.export=XML\u2013\u10d8\u10e1 \u10d4\u10e5\u10e1\u10de\u10dd\u10e0\u10e2\u10d8.. MyTorrentsView.menu.host=\u10f0\u10dd\u10e1\u10e2\u10d8... ManagerItem.finishing=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d0 ConfigView.dialog.choosedefaulttorrentpath=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4\u10d7 \u10e1\u10e2\u10d0\u10dc\u10d3\u10d0\u10e0\u10e2\u10e3\u10da\u10d8 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 ConfigView.dialog.choosemovepath=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4\u10d7 \u10d2\u10d0\u10d3\u10d0\u10e1\u10d0\u10e2\u10d0\u10dc\u10d0\u10d3 \u10d2\u10d0\u10dc\u10d9\u10e3\u10d7\u10d5\u10dc\u10d8\u10da\u10d8 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 ConfigView.label.movecompleted=\u10d2\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10d4 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 ConfigView.label.savetorrents=\u10e8\u10d4\u10d8\u10dc\u10d0\u10ee\u10d4 .torrent \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 MainWindow.menu.view.mytracker=\u10e9\u10d4\u10db\u10d8 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 MyTrackerView.title.full=\u10e9\u10d4\u10db\u10d8 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 MyTrackerView.name=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8 MyTrackerView.tracker=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 MyTrackerView.status=\u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8 MyTrackerView.status.started=\u10db\u10d8\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4\u10dd\u10d1\u10e1 MyTrackerView.status.stopped=\u10e8\u10d4\u10e9\u10d4\u10e0\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 MyTrackerView.peers=\u10de\u10d8\u10e0\u10d4\u10d1\u10d8 MyTrackerView.seeds=\u10db\u10d7\u10d4\u10e1\u10d5\u10d4\u10da\u10d4\u10d1\u10d8 MyTrackerView.announces=\u10d0\u10dc\u10dd\u10dc\u10e1\u10d4\u10d1\u10d8 MyTrackerView.uploaded=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 MyTrackerView.downloaded=\u10e9\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 MyTrackerView.left=\u10d3\u10d0\u10e0\u10e9\u10d0 ConfigView.section.style=\u10d8\u10dc\u10e2\u10d4\u10e0\u10e4\u10d4\u10d8\u10e1\u10d8 MainWindow.menu.view.plugins=\u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8 fileDownloadWindow.saveTorrentIn=\u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d0 \u10db\u10d8\u10e1\u10d0\u10db\u10d0\u10e0\u10d7\u10d6\u10d4 fileDownloadWindow.title=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8 - \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 fileDownloadWindow.downloading=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 \u10db\u10d8\u10e1\u10d0\u10db\u10d0\u10e0\u10d7\u10d8\u10d3\u10d0\u10dc : fileDownloadWindow.status=\u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8 : fileDownloadWindow.state_initializing=\u10d8\u10dc\u10d8\u10ea\u10d8\u10d0\u10da\u10d8\u10d6\u10d0\u10ea\u10d8\u10d0 fileDownloadWindow.state_downloading=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 fileDownloadWindow.state_error=\u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 : MainWindow.menu.file.open.url=&URL openUrl.title=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8 - \u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 Url openUrl.url=\u10d1\u10db\u10e3\u10da\u10d8 : MyTorrentsView.menu.host.error.title=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10f0\u10dd\u10e1\u10e2\u10d8\u10dc\u10d2\u10d8 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 MyTorrentsView.menu.host.error.message=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10f0\u10dd\u10e1\u10e2\u10d8\u10dc\u10d2\u10d8\u10e1\u10d0\u10e1 \u10e8\u10d4\u10d8\u10e5\u10db\u10dc\u10d0 \u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10de\u10e0\u10dd\u10d1\u10da\u10d4\u10db\u10d0 ConfigView.section.tracker=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 ConfigView.section.style.enableXPStyle=XP \u10e1\u10e2\u10d8\u10da\u10d8\u10e1 \u10e9\u10d0\u10e0\u10d7\u10d5\u10d0 (\u10e1\u10d0\u10ed\u10d8\u10e0\u10dd\u10d0 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0) ipCheckerWizard.explanations=\u10e8\u10d4\u10d2\u10d8\u10eb\u10da\u10d8\u10d0\u10d7 \u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d7\u10dd\u10d7 \u10d4\u10e1 \u10dd\u10e1\u10e2\u10d0\u10e2\u10d8 \u10e0\u10d0\u10d7\u10d0 \u10d3\u10d0\u10d0\u10d3\u10d2\u10d8\u10dc\u10dd\u10d7 \u10d7\u10e5\u10d5\u10d4\u10dc\u10d8 \u10d2\u10d0\u10e0\u10d4 IP \u10db\u10d8\u10e1\u10d0\u10db\u10d0\u10e0\u10d7\u10d8. \u10d7\u10e3 \u10d7\u10e5\u10d5\u10d4\u10dc\u10d8 IP \u10d3\u10d8\u10dc\u10d0\u10db\u10d8\u10e3\u10e0\u10d8\u10d0 \u10d2\u10d8\u10e0\u10e9\u10d4\u10d5\u10d7 \u10d3\u10d0\u10e0\u10d4\u10d2\u10d8\u10e1\u10e2\u10e0\u10d8\u10e0\u10d3\u10d4\u10d7 Dynamic DNS \u10e1\u10d4\u10e0\u10d5\u10d8\u10e1\u10d6\u10d4. \u10e5\u10d5\u10d4\u10d5\u10d8\u10d7 \u10db\u10dd\u10e7\u10d5\u10d0\u10dc\u10d8\u10da\u10d8\u10d0 \u10e0\u10d0\u10db\u10dd\u10d3\u10d4\u10dc\u10d8\u10db\u10d4 \u10d0\u10e1\u10d4\u10d7\u10d8 \u10e1\u10d4\u10e0\u10d5\u10d8\u10e1\u10d8\u10e1 \u10db\u10d8\u10e1\u10d0\u10db\u10d0\u10e0\u10d7\u10d8. \u10e8\u10d4\u10db\u10d3\u10d4\u10d2 \u10e8\u10d8\u10e7\u10d5\u10d0\u10dc\u10d4\u10d7 IP \u10db\u10d8\u10e1\u10d0\u10db\u10d0\u10e0\u10d7\u10d8\u10e1 \u10dc\u10d0\u10ea\u10d5\u10da\u10d0\u10d3 \u10d7\u10e5\u10d5\u10d4\u10dc\u10d8 \u10d3\u10d8\u10dc\u10d0\u10db\u10d8\u10e3\u10e0\u10d8 \u10f0\u10dd\u10e1\u10e2\u10d8\u10e1 \u10e1\u10d0\u10ee\u10d4\u10da\u10d8 (\u10db\u10d0\u10d2. chemihostissaxeli.dyndns.org). \u10d8\u10db\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10e0\u10dd\u10db IP \u10db\u10d8\u10e1\u10d0\u10db\u10d0\u10e0\u10d7\u10d8\u10e1 \u10d3\u10d8\u10dc\u10d0\u10db\u10d8\u10e3\u10e0\u10db\u10d0 \u10ea\u10d5\u10da\u10d8\u10da\u10d4\u10d1\u10d0\u10db \u10d0\u10e0 \u10e8\u10d4\u10e5\u10dc\u10d0\u10e1 \u10de\u10e0\u10dd\u10d1\u10da\u10d4\u10db\u10d4\u10d1\u10d8 \u10d3\u10d0\u10d2\u10ed\u10d8\u10e0\u10d3\u10d4\u10d1\u10d0\u10d7 \u10de\u10e0\u10dd\u10d2\u10e0\u10d0\u10db\u10d0 \u10e0\u10dd\u10db\u10d4\u10da\u10d8\u10ea \u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d0\u10d3 \u10d2\u10d0\u10dc\u10d0\u10d0\u10ee\u10da\u10d4\u10d1\u10e1 \u10d7\u10e5\u10d5\u10d4\u10dc\u10e1 \u10d3\u10d8\u10dc\u10d0\u10db\u10d8\u10e3\u10e0 DNS \u10e1\u10d4\u10e0\u10d5\u10d8\u10e1\u10e1. wizard.tracker.local=\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10e8\u10d8 \u10e9\u10d0\u10db\u10dd\u10dc\u10e2\u10d0\u10df\u10d4\u10d1\u10e3\u10da\u10d8 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 wizard.tracker.external=\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 wizard.tracker.howToLocal=\t\u10e9\u10d0\u10e1\u10d0\u10e0\u10d7\u10d0\u10d5\u10d0\u10d3 \u10d2\u10d0\u10d3\u10d0\u10d3\u10d8 '\u10d8\u10dc\u10e1\u10e2\u10e0\u10e3\u10db\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8->\u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8->\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4' wizard.announceUrl=\u10d0\u10dc\u10dd\u10dc\u10e1\u10d8\u10e1 URL : IPChecker.external.httpinvalidresponse=\u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8 HTTP \u10d2\u10d0\u10db\u10dd\u10ee\u10db\u10d0\u10e3\u10e0\u10d4\u10d1\u10d0 IPChecker.external.loadingwebpage=\u10d5\u10d4\u10d1\u2013\u10d2\u10d5\u10d4\u10e0\u10d3\u10d8\u10e1 \u10e9\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 IPChecker.external.analysingresponse=\u10d2\u10d0\u10db\u10dd\u10ee\u10db\u10d0\u10e3\u10e0\u10d4\u10d1\u10d8\u10e1 \u10d0\u10dc\u10d0\u10da\u10d8\u10d6\u10d8 IPChecker.external.httploadfail=\u10d2\u10d5\u10d4\u10e0\u10d3\u10d8\u10e1 \u10e9\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 IPChecker.external.ipnotfound=\u10d5\u10d4\u10e0 \u10d5\u10d8\u10de\u10dd\u10d5\u10d4 IP \u10db\u10d8\u10e1\u10d0\u10db\u10d0\u10e0\u10d7\u10d8 ConfigView.section.tracker.pollintervalmin=\u10db\u10d8\u10dc\u10d8\u10db\u10e3\u10db\u10d8 ConfigView.section.tracker.pollintervalmax=\u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10e3\u10db\u10d8 ConfigView.section.tracker.pollintervalincper=\u10e7\u10dd\u10d5\u10d4\u10da\u10d8 'n' \u10d9\u10da\u10d8\u10d4\u10dc\u10e2\u10d8 splash.loadingImages=\u10dc\u10d0\u10ee\u10d0\u10e2\u10d4\u10d1\u10d8\u10e1 \u10e9\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 splash.initializeGui=\u10db\u10d7\u10d5\u10d0\u10e0\u10d8 \u10e4\u10d0\u10dc\u10ef\u10e0\u10d8\u10e1 \u10d8\u10dc\u10d8\u10ea\u10d8\u10d0\u10da\u10d8\u10d6\u10d0\u10ea\u10d8\u10d0 splash.openViews=\u10ee\u10d4\u10d3\u10d8\u10e1 \u10d2\u10d0\u10ee\u10e1\u10dc\u10d0 splash.plugin=\u10d8\u10e2\u10d5\u10d8\u10e0\u10d7\u10d4\u10d1\u10d0 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d8 : configureWizard.nat.tooManyPorts=\u10e2\u10d4\u10e1\u10e2\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1\u10d7\u10d5\u10d8\u10e1 \u10e8\u10d4\u10e0\u10e9\u10d4\u10e3\u10da\u10d8\u10d0 \u10eb\u10d0\u10da\u10d8\u10d0\u10dc \u10d1\u10d4\u10d5\u10e0\u10d8 \u10de\u10dd\u10e0\u10e2\u10d8 (\u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10e3\u10db\u10d8\u10d0 9) ConfigView.section.color=\u10e4\u10d4\u10e0\u10d7\u10d0 \u10e1\u10e5\u10d4\u10db\u10d0 MyTorrentsView.menu.publish=\u10d2\u10d0\u10db\u10dd\u10d0\u10e5\u10d5\u10d4\u10e7\u10dc\u10d4... MyTrackerView.status.published=\u10d2\u10d0\u10db\u10dd\u10e5\u10d5\u10d4\u10e7\u10dc\u10d3\u10d0 MyTrackerView.completed=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 MainWindow.menu.file.open.torrentnodefault=.torrent \u10e4\u10d0\u10d8\u10da\u10d8 (\u10d2\u10d0\u10dc\u10e1\u10d0\u10d6\u10e6\u10d5\u10e0\u10e3\u10da\u10d8 \u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4) wizard.comment=\u10d9\u10dd\u10db\u10d4\u10dc\u10e2\u10d0\u10e0\u10d8 ConfigView.label.movetorrent=\u10d2\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10d4 .torrent ConfigView.section.file.decoder.nodecoder=\u10d0\u10e0\u10ea\u10d4\u10e0\u10d7\u10d8 ConfigView.section.tracker.publicenable=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 ConfigView.label.playdownloadspeech=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d8\u10e1\u10d0\u10e1 \u10e8\u10d4\u10db\u10d0\u10e2\u10e7\u10dd\u10d1\u10d8\u10dc\u10d4 \u10e1\u10d8\u10e2\u10e7\u10d5\u10d8\u10d4\u10e0\u10d0\u10d3 ConfigView.label.playdownloadspeech.info=\u10db\u10d4\u10e2\u10e7\u10d5\u10d4\u10da\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d4\u10e0\u10d5\u10d8\u10e1\u10d4\u10d1\u10d8 \u10e1\u10d0\u10e3\u10d9\u10d4\u10d7\u10d4\u10e1\u10dd\u10d3 \u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10d8\u10dc\u10d2\u10da\u10d8\u10e1\u10e3\u10e0\u10d0\u10d3 \u10db\u10e3\u10e8\u10d0\u10dd\u10d1\u10e1 # # Tooltips # GeneralView.label.status.pieces_available.tooltip=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4\u10d1\u10e1 \u10ee\u10d4\u10da\u10db\u10d8\u10e1\u10d0\u10ec\u10d5\u10d3\u10dd\u10db\u10d8 \u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8\u10e1 \u10d0\u10e1\u10da\u10d4\u10d1\u10d8\u10e1 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0\u10e1.\n\u10db\u10d0\u10e0\u10ef\u10d5\u10dc\u10d8\u10d5 \u10d2\u10d0\u10db\u10dd\u10e1\u10d0\u10ee\u10e3\u10da\u10d8 \u10e0\u10ea\u10ee\u10d5\u10d8 \u10d7\u10e3 1\u2013\u10d6\u10d4 \u10dc\u10d0\u10d9\u10da\u10d4\u10d1\u10d8\u10d0, \u10e8\u10d4\u10e1\u10d0\u10eb\u10da\u10dd\u10d0 \u10e8\u10d4\u10d2\u10d4\u10e5\u10db\u10dc\u10d0\u10d7 \u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10e1\u10e0\u10e3\u10da\u10d0\u10d3 \u10e9\u10d0\u10db\u10dd\u10e5\u10d0\u10e9\u10d5\u10d8\u10e1 \u10de\u10e0\u10dd\u10d1\u10da\u10d4\u10db\u10d0. GeneralView.label.trackerurl.tooltip=\u10d3\u10d0\u10ec\u10d9\u10d0\u10de\u10d4\u10d7 \u10d0\u10dc\u10dd\u10dc\u10e1\u10d8\u10e1 URL-\u10d8\u10e1 \u10d1\u10e3\u10e4\u10d4\u10e0\u10e8\u10d8 \u10d9\u10dd\u10de\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 GeneralView.label.trackerurlopen.tooltip=\u10d3\u10d0\u10ec\u10d9\u10d0\u10de\u10d4\u10d7 \u10db\u10d4\u10d7\u10d5\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10db\u10d7\u10d0\u10d5\u10d0\u10e0 \u10d2\u10d5\u10d4\u10e0\u10d3\u10d6\u10d4 \u10d2\u10d0\u10e1\u10d0\u10e1\u10d5\u10da\u10d4\u10da\u10d0\u10d3 # # 2.0.4.4 # ConfigView.section.style.guiUpdate=\u10d2\u10e0\u10d0\u10e4\u10d8\u10d9\u10e3\u10da\u10d8 \u10d8\u10dc\u10e2\u10d4\u10e0\u10e4\u10d4\u10d8\u10e1\u10d8\u10e1 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 \u10e7\u10dd\u10d5\u10d4\u10da ConfigView.section.style.reOrderDelay.never=\u10d0\u10e0\u10d0\u10e1\u10dd\u10d3\u10d4\u10e1 ConfigView.section.logging=\u10df\u10e3\u10e0\u10dc\u10d0\u10da\u10d8 ConfigView.section.logging.enable=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10df\u10e3\u10e0\u10dc\u10d0\u10da\u10d8\u10e1 \u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d0 \u10e4\u10d0\u10d8\u10da\u10e8\u10d8 ConfigView.section.logging.logdir=\u10d0\u10ec\u10d0\u10e0\u10db\u10dd\u10d4 \u10df\u10e3\u10e0\u10dc\u10d0\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d6\u10d4 ConfigView.section.logging.choosedefaultsavepath=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4\u10d7 \u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d8\u10e1 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 GeneralView.label.updatein.querying=\u10d2\u10d0\u10db\u10dd\u10d9\u10d8\u10d7\u10ee\u10d5\u10d0... configureWizard.nat.sharePort=\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4 \u10d4\u10e0\u10d7\u10d0\u10d3\u10d4\u10e0\u10d7\u10d8 \u10d6\u10d8\u10d0\u10e0\u10d8 \u10de\u10dd\u10e0\u10e2\u10d8 \u10e7\u10d5\u10d4\u10da\u10d0 \u10d0\u10e5\u10e2\u10d8\u10e3\u10e0\u10d8 torrent\u2013\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1. ConfigView.section.logging.maxsize=\u10df\u10e3\u10e0\u10dc\u10d0\u10da\u10d8\u10e1 \u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10db\u10d0\u10e5\u10e1\u10d8\u10d0\u10db\u10da\u10e3\u10e0\u10d8 \u10d6\u10dd\u10db\u10d0 ConfigView.section.tracker.passwordenabletorrent=\u10de\u10d0\u10e0\u10dd\u10da\u10d4\u10d1\u10d8\u10e1 \u10e9\u10d0\u10e0\u10d7\u10d5\u10d0 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d6\u10d4 ConfigView.section.tracker.username=\u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d8\u10e1 \u10e1\u10d0\u10ee\u10d4\u10da\u10d8 ConfigView.section.tracker.password=\u10de\u10d0\u10e0\u10dd\u10da\u10d8 columnChooser.title=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10d9\u10dd\u10da\u10dd\u10dc\u10d4\u10d1\u10d8 columnChooser.move=\u10d2\u10d0\u10d3\u10d0\u10d0\u10ea\u10dd\u10ea\u10d4 \u10e1\u10e2\u10e0\u10d8\u10e5\u10dd\u10dc\u10d4\u10d1\u10d8 \u10db\u10d0\u10d7\u10d8 \u10dd\u10e0\u10d2\u10d0\u10dc\u10d8\u10d6\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 columnChooser.apply=\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4 columnChooser.columnname=\u10d9\u10dd\u10da\u10dd\u10dc\u10d8\u10e1 \u10e1\u10d0\u10ee\u10d4\u10da\u10d8 columnChooser.columndescription=\u10d0\u10e6\u10ec\u10d4\u10e0\u10d0 TableColumn.header.shareRatio=\u10d6\u10d8\u10d0\u10e0\u10d8 \u10e0\u10d4\u10d8\u10e2\u10d8\u10dc\u10d2\u10d8 MyTorrentsView.menu.editTableColumns=\u10d9\u10dd\u10da\u10dd\u10dc\u10d4\u10d1\u10d8\u10e1 \u10db\u10dd\u10ec\u10e7\u10dd\u10d1\u10d0 wizard.operationfailed=\u10dd\u10de\u10d4\u10e0\u10d0\u10ea\u10d8\u10d0 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 authenticator.title=\u10e1\u10d0\u10ed\u10d8\u10e0\u10dd\u10d0 \u10d0\u10e3\u10e2\u10d4\u10dc\u10d7\u10d8\u10e4\u10d8\u10d9\u10d0\u10ea\u10d8\u10d0 authenticator.realm=\u10e0\u10d4\u10d0\u10da\u10db\u10d8 authenticator.tracker=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 authenticator.user=\u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10d4\u10da\u10d8 authenticator.password=\u10de\u10d0\u10e0\u10dd\u10da\u10d8 ConfigView.label.allowSendVersion=\u10dc\u10d4\u10d1\u10d0 \u10d3\u10d0\u10e0\u10d7\u10d4 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10e1 \u10d2\u10d0\u10d0\u10d2\u10d6\u10d0\u10d5\u10dc\u10dd\u10e1 \u10d0\u10dc\u10dd\u10dc\u10d8\u10db\u10e3\u10e0\u10d8 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d8\u10e1 \u10e8\u10d4\u10e1\u10d0\u10ee\u10d4\u10d1, \u10e0\u10dd\u10ea\u10d0 \u10db\u10dd\u10ec\u10db\u10d3\u10d4\u10d1\u10d0 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d4\u10d1\u10d8. wizard.hint.mode=\u10e0\u10e9\u10d4\u10d5\u10d0:\t\u10e8\u10d4\u10d2\u10d8\u10da\u10d8\u10d0 \u10d2\u10d0\u10d3\u10d3\u10d0\u10ea\u10dd\u10ea\u10dd \u10d3\u10d0 \u10d2\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10dd \u10d4\u10e0\u10d7\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8 \u10d0\u10dc \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 \u10d0\u10db \u10dd\u10e1\u10e2\u10d0\u10d6\u10d4 \n\t\u10e0\u10dd\u10db \u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10dd wizard.hint.file=\u10e0\u10e9\u10d4\u10d5\u10d0:\t\u10e8\u10d4\u10d2\u10d8\u10da\u10d8\u10d0 \u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10dd \u10d4\u10e0\u10d7\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8 \u10d2\u10d0\u10d3\u10d0\u10ea\u10dd\u10ea\u10d4\u10d1\u10d0 \u10d3\u10d0 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d0\u10dc\u10d8\u10e1 \u10db\u10d4\u10e8\u10d5\u10d4\u10dd\u10d1\u10d8\u10d7 wizard.hint.directory=\u10e0\u10e9\u10d4\u10d5\u10d0:\t\u10e8\u10d4\u10d2\u10d8\u10da\u10d8\u10d0 \u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10dd \u10d4\u10e0\u10d7\u10d8 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 \u10d2\u10d0\u10d3\u10d0\u10ea\u10dd\u10ea\u10d4\u10d1\u10d0 \u10d3\u10d0 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d0\u10dc\u10d8\u10e1 \u10db\u10d4\u10e8\u10d5\u10d4\u10dd\u10d1\u10d8\u10d7 MainWindow.menu.help.checkupdate=\u10e8\u10d4\u10d0\u10db\u10dd\u10ec\u10db\u10d4 \u10de\u10e0\u10dd\u10d2\u10e0\u10d0\u10db\u10d8\u10e1 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 TableColumn.header.down=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 TableColumn.header.up=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 MainWindow.dialog.exitconfirmation.title=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10d3\u10d0\u10ee\u10e3\u10e0\u10d5\u10d0 MainWindow.dialog.exitconfirmation.text=\u10d3\u10d0\u10d5\u10ee\u10e3\u10e0\u10dd \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8? SystemTray.menu.stopalltransfers=\u10e8\u10d4\u10d0\u10e9\u10d4\u10e0\u10d4 \u10e7\u10d5\u10d4\u10da\u10d0 \u10e2\u10e0\u10d0\u10dc\u10e4\u10d4\u10e0\u10d8 TrayWindow.menu.stopalldownloads=\u10d2\u10d0\u10db\u10dd\u10e0\u10d7\u10d4 \u10e7\u10d5\u10d4\u10da\u10d0 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 wizard.tracker.ssl=\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4 SSL ConfigView.label.playdownloadfinished=\u10d3\u10d0\u10e3\u10d9\u10d0\u10e0\u10d8 \u10ee\u10db\u10dd\u10d5\u10d0\u10dc\u10d8 \u10e8\u10d4\u10e7\u10dd\u10d1\u10d8\u10dc\u10d4\u10d1\u10d0 \u10e0\u10dd\u10ea\u10d0 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d3\u10d4\u10d1\u10d0 TableColumn.header.pieces=\u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8 TableColumn.header.pieces.info=\u10d2\u10e0\u10d0\u10e4\u10d8\u10d9\u10e3\u10da\u10d8 \u10de\u10d0\u10dc\u10d4\u10da\u10d8 \u10e1\u10d3\u10d0\u10ea \u10d2\u10d0\u10db\u10dd\u10e1\u10d0\u10ee\u10e3\u10da\u10d8\u10d0 \u10d7\u10e5\u10d5\u10d4\u10dc\u10e1 \u10db\u10d8\u10d4\u10e0 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8 \u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8 TableColumn.header.completion=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d0 TableColumn.header.completion.info=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d1\u10e3\u10da\u10d8 % \u10d2\u10e0\u10d0\u10e4\u10d8\u10d9\u10e3\u10da\u10d8 \u10d5\u10d8\u10d6\u10e3\u10d0\u10da\u10d8\u10d6\u10d0\u10ea\u10d8\u10d0 wizard.multitracker=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10e8\u10d8 \u10e9\u10d0\u10d0\u10db\u10d0\u10e2\u10d4 \u10db\u10e3\u10da\u10e2\u10d8\u2013\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 wizard.multitracker.title=\u10db\u10e3\u10da\u10e2\u10d8 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 wizard.multitracker.configuration=\u10db\u10e3\u10da\u10e2\u10d8\u2013\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10d0 wizard.multitracker.new=\u10d0\u10ee\u10d0\u10da\u10d8... wizard.multitracker.edit=\u10e8\u10d4\u10ea\u10d5\u10da\u10d0.. wizard.multitracker.delete=\u10ec\u10d0\u10e8\u10da\u10d0 wizard.multitracker.group=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4\u10d7\u10d0 \u10ef\u10d2\u10e3\u10e4\u10d8 wizard.multitracker.edit.title=\u10db\u10e3\u10da\u10e2\u10d8\u2013\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10e0\u10d4\u10d3\u10d0\u10e5\u10e2\u10dd\u10e0\u10d8 wizard.multitracker.edit.name=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8 wizard.multitracker.edit.save=\u10e8\u10d4\u10d8\u10dc\u10d0\u10ee\u10d4 wizard.multitracker.edit.newgroup=\u10d0\u10ee\u10d0\u10da\u10d8 \u10ef\u10d2\u10e3\u10e4\u10d8 wizard.multitracker.edit.deletegroup=\u10ec\u10d0\u10e8\u10da\u10d0 wizard.multitracker.edit.newtracker=\u10d0\u10ee\u10d0\u10da\u10d8 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 wizard.multitracker.edit.deletetracker=\u10ec\u10d0\u10e8\u10d0\u10da\u10d4 wizard.multitracker.edit.edit=\u10e8\u10d4\u10ea\u10d5\u10da\u10d0 wizard.addingmt=\u10db\u10e3\u10da\u10e2\u10d8\u2013\u10db\u10db\u10d0\u10e0\u10d7\u10d5\u10d4\u10da\u10d8\u10e1 \u10d3\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10d0 wizard.multitracker.noannounce=\u10d0\u10dc\u10dd\u10dc\u10e1\u10d8\u10e1 URL \u10e3\u10d9\u10d5\u10d4 \u10d0\u10e0\u10d8\u10e1 \u10e8\u10d4\u10dc\u10e1 \u10db\u10d4\u10d7\u10d5\u10da\u10e7\u10e3\u10e0\u10d4\u10d7\u10d0 \u10e1\u10d8\u10d0\u10e8\u10d8 MyTorrentsView.menu.recheck=\u10e4\u10dd\u10e0\u10e1\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8 \u10d2\u10d0\u10d3\u10d0\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 iconBar.showDownloadBar.tooltip=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10d6\u10dd\u10da\u10d8 iconBar.start.tooltip=\u10e1\u10e2\u10d0\u10e0\u10e2\u10d8 iconBar.stop.tooltip=\u10e1\u10e2\u10dd\u10de\u10d8 iconBar.remove.tooltip=\u10d0\u10db\u10dd\u10d0\u10d2\u10d3\u10d4 iconBar.openNoDefault.tooltip=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 .torrent \u10e4\u10d0\u10d8\u10da\u10d8 (\u10e8\u10d4\u10e0\u10e9\u10d4\u10e3\u10da\u10d8 \u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4) iconBar.openURL.tooltip=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 URL iconBar.openFolder.tooltip=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 iconBar.new.tooltip=\u10e8\u10d4\u10e5\u10db\u10d4\u10dc\u10d8 torrent iconBar.up.tooltip=\u10d2\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10d4 \u10d6\u10d4\u10d5\u10d8\u10d7 iconBar.down.tooltip=\u10d2\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10d4 \u10e5\u10d5\u10d4\u10d5\u10d8\u10d7 iconBar.run.tooltip=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 iconBar.host.tooltip=\u10f0\u10dd\u10e1\u10e2\u10d8 iconBar.publish.tooltip=\u10d2\u10d0\u10db\u10dd\u10d0\u10e5\u10d5\u10d4\u10e7\u10dc\u10d4 MyTorrentsView.menu.editTracker=\u10e8\u10d4\u10ea\u10d5\u10d0\u10da\u10d4 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 URL(\u10d4\u10d1\u10d8) GeneralView.menu.selectTracker=\u10e8\u10d4\u10e0\u10e9\u10d4\u10d5\u10d0 ConfigView.section.stats.xslfile=XSL \u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10e1\u10d0\u10ee\u10d4\u10da\u10d8 ConfigView.label.savetorrentbackup=\u10e8\u10d4\u10d8\u10dc\u10d0\u10ee\u10d4 \u10e0\u10d4\u10d6\u10d4\u10e0\u10d5\u10d8 ConfigView.section.ipfilter.allow=\u10dc\u10d4\u10d1\u10d0 \u10d3\u10d0\u10e0\u10d7\u10d4 \u10d4\u10e1 \u10d3\u10d8\u10d0\u10de\u10d0\u10d6\u10dd\u10dc\u10d4\u10d1\u10d8 (\u10e1\u10e2\u10d0\u10dc\u10d3\u10d0\u10e0\u10e2\u10e3\u10da\u10d0\u10d3 \u10dc\u10d8\u10e8\u10dc\u10d0\u10d5\u10e1 \u10d0\u10d9\u10e0\u10eb\u10d0\u10da\u10d5\u10d0\u10e1) ConfigView.section.ipfilter.list.inrange=\u10e8\u10d4\u10d8\u10ea\u10d0\u10d5\u10d3\u10d0 \u10d3\u10d8\u10d0\u10de\u10d0\u10d6\u10dd\u10dc\u10d8 ConfigView.section.ipfilter.list.notinrange=\u10d0\u10e0 \u10d8\u10e7\u10dd \u10d0\u10e0\u10ea \u10d4\u10e0\u10d7 \u10d3\u10d8\u10d0\u10de\u10d0\u10d6\u10dd\u10dc\u10e8\u10d8 ConfigView.section.ipfilter.list.title=\u10d3\u10d0\u10d1\u10da\u10dd\u10d9\u10d8\u10da\u10d8 IP\u2013\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d8\u10d0 ConfigView.label.allowsameip=\u10d3\u10d0\u10e3\u10e8\u10d5\u10d8 \u10db\u10e0\u10d0\u10d5\u10d0\u10da\u10d8 \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d0 \u10d4\u10e0\u10d7 IP \u10db\u10d8\u10e1\u10d0\u10db\u10d0\u10e0\u10d7\u10d7\u10d0\u10dc ConfigView.label.allowsameip.tooltip=\u10db\u10dd\u10dc\u10d8\u10e8\u10dc\u10d4 \u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10db\u10d0\u10e8\u10d8\u10dc \u10e0\u10dd\u10ea\u10d0 \u10e1\u10d0\u10ed\u10d8\u10e0\u10dd\u10d4\u10d1\u10d0 \u10db\u10dd\u10d8\u10d7\u10ee\u10dd\u10d5\u10e1.\n\u10d4\u10e1 \u10d0\u10e0\u10d8\u10e1 \u10da\u10d8\u10e9\u10d4\u10e0\u10d8\u10e1 \u10d3\u10d0\u10ea\u10d5\u10d0 (\u10e0\u10dd\u10ea\u10d0 \u10d2\u10d0\u10db\u10dd\u10e0\u10d7\u10e3\u10da\u10d8\u10d0). ManagerItem.superseeding=\u10e1\u10e3\u10de\u10d4\u10e0\u2013\u10d3\u10d0\u10d7\u10d4\u10e1\u10d5\u10d0 ConfigView.label.userSuperSeeding=\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4 \u10e1\u10e3\u10de\u10d4\u10e0 \u10d3\u10d0\u10d7\u10d4\u10e1\u10d5\u10d0 ConfigView.section.style.addurlsilently=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 \u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10e3\u10da\u10d8 URL\u2013\u10d4\u10d1\u10d8 \u10e3\u10ee\u10db\u10d0\u10e3\u10e0\u10dd\u10d3 MyTorrentsView.menu.moveTop=\u10d7\u10d0\u10d5\u10e8\u10d8 MyTorrentsView.menu.moveEnd=\u10d1\u10dd\u10da\u10dd\u10e8\u10d8 ConfigView.label.moveonlyusingdefaultsave=\u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10db\u10d0\u10e8\u10d8\u10dc \u10e0\u10dd\u10ea\u10d0 \u10ec\u10d8\u10dc\u10d0\u10e1\u10ec\u10d0\u10e0 \u10d2\u10d0\u10dc\u10e1\u10d0\u10d6\u10e6\u10d5\u10e0\u10e3\u10da \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10e8\u10d8\u10d0 ConfigView.label.moveonlyusingdefaultsave.tooltip=\u10d2\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10d4 \u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10db\u10d0\u10e8\u10d8\u10dc \u10e0\u10dd\u10ea\u10d0 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 \u10ec\u10d8\u10dc\u10d0\u10e1\u10ec\u10d0\u10e0 \u10d2\u10d0\u10dc\u10e1\u10d0\u10d6\u10e6\u10d5\u10e0\u10e3\u10da \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10e8\u10d8\u10d0 ConfigView.label.watchtorrentfolder=\u10d0\u10ee\u10d0\u10da\u10d8 .torrent\u2013\u10d4\u10d1\u10d8\u10e1 \u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e0\u10e3\u10d8 \u10d8\u10db\u10de\u10dd\u10e0\u10e2\u10d8 ConfigView.label.watchtorrentfolder.tooltip=\u10d0\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10e1 \u10d0\u10ee\u10d0\u10da .torrent\u2013\u10d4\u10d1\u10e1 \u10e0\u10d4\u10d2\u10e3\u10da\u10d0\u10e0\u10e3\u10da\u10d0\u10d3 ConfigView.label.watchtorrentfolderinterval=\u10d8\u10dc\u10e2\u10d4\u10e0\u10d5\u10d0\u10da\u10d8 ConfigView.label.watchtorrentfolderinterval.tooltip=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8\u10e1 \u10d2\u10d0\u10d3\u10d0\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d4\u10d1\u10e1 \u10e8\u10dd\u10e0\u10d8\u10e1 \u10d3\u10e0\u10dd ConfigView.dialog.choosewatchtorrentfolderpath=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4\u10d7 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10d8\u10db\u10de\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 ConfigView.label.startwatchedtorrentsstopped=\u10d3\u10d0\u10d8\u10ec\u10e7\u10d4 \u10e8\u10d4\u10e9\u10d4\u10e0\u10d4\u10d1\u10e3\u10da\u10d0\u10d3 ConfigView.section.plugins=\u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8 wizard.maketorrent.filesize=\u10e4\u10d0\u10d8\u10da\u10d8\u10e1(\u10d4\u10d1\u10d8\u10e1) \u10d6\u10dd\u10db\u10d0 wizard.maketorrent.piececount=\u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8\u10e1 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 wizard.maketorrent.piecesize=\u10dc\u10d0\u10ed\u10e0\u10d8\u10e1 \u10d6\u10dd\u10db\u10d0 wizard.maketorrent.auto=\u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 MainWindow.menu.view.stats=\u10e1\u10e2\u10d0\u10e2\u10d8\u10e1\u10e2\u10d8\u10d9\u10d0 SpeedView.title.full=\u10d0\u10e5\u10e2\u10d8\u10e3\u10e0\u10dd\u10d1\u10d0 SpeedView.downloadSpeed.title=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 SpeedView.uploadSpeed.title=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 iconBar.top.tooltip=\u10d3\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10d4 \u10d7\u10d0\u10d5\u10e8\u10d8 iconBar.bottom.tooltip=\u10d2\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10d4 \u10d1\u10dd\u10da\u10dd\u10e8\u10d8 TableColumn.header.health=\u10ef\u10d0\u10dc\u10db\u10e0\u10d7\u10d4\u10da\u10dd\u10d1\u10d0 MyTorrentsView.menu.health=\u10da\u10d4\u10d2\u10d4\u10dc\u10d3\u10d0 # #2.0.7.0 # security.certtruster.title=\u10e3\u10e1\u10d0\u10e4\u10e0\u10d7\u10ee\u10dd\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d4\u10e0\u10d7\u10d8\u10e4\u10d8\u10d9\u10d0\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e4\u10e0\u10d7\u10ee\u10d8\u10da\u10d4\u10d1\u10d0 security.certtruster.intro=\u10e3\u10e1\u10e4\u10e0\u10d7\u10ee\u10dd\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d4\u10e0\u10d7\u10d8\u10e4\u10d8\u10d9\u10d0\u10e2\u10d8 \u10d2\u10d0\u10ea\u10d4\u10db\u10e3\u10da\u10d8\u10d0 \u10d9\u10dd\u10db\u10de\u10d0\u10dc\u10d8\u10d8\u10e1 \u10db\u10d8\u10d4\u10e0, \u10e0\u10dd\u10db\u10d4\u10da\u10e1\u10d0\u10ea \u10d7\u10e5\u10d5\u10d4\u10dc \u10d0\u10e0 \u10d4\u10dc\u10d3\u10dd\u10d1\u10d8\u10d7 security.certtruster.resource=\u10e0\u10d4\u10e1\u10e3\u10e0\u10e1\u10d8: security.certtruster.issuedto=\u10d2\u10d0\u10e1\u10ea\u10d4\u10e1 : security.certtruster.issuedby=\u10d2\u10d0\u10ea\u10d4\u10db\u10e3\u10da\u10d8\u10d0: security.certtruster.prompt=\u10d2\u10e1\u10e3\u10e0\u10d7 \u10d4\u10dc\u10d3\u10dd\u10d7? security.certtruster.yes=\u10d9\u10d8 security.certtruster.no=\u10d0\u10e0\u10d0 MainWindow.menu.file.share=\u10d2\u10d0\u10d6\u10d8\u10d0\u10e0\u10d4\u10d1\u10d0 MainWindow.menu.file.share.file=\u10e4\u10d0\u10d8\u10da\u10d8... MainWindow.menu.file.share.dir=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8... MainWindow.menu.file.share.dircontents=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8\u10e1 \u10e8\u10d8\u10d2\u10d7\u10d0\u10d5\u10e1\u10d8... MainWindow.menu.file.share.dircontentsrecursive=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8\u10e1 \u10e8\u10d8\u10d2\u10d7\u10d0\u10d5\u10e1\u10d8 (\u10e0\u10d4\u10d9\u10e3\u10e0\u10e1\u10d8\u10d5\u10d8)... MainWindow.dialog.share.sharefile=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10e1\u10d0\u10d6\u10d8\u10d0\u10e0\u10dd \u10e4\u10d0\u10d8\u10da\u10d8 MainWindow.dialog.share.sharedir=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10e1\u10d0\u10d6\u10d8\u10d0\u10e0\u10dd \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 MainWindow.dialog.share.sharedircontents=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8\u10e1 \u10e8\u10d4\u10db\u10d0\u10d3\u10d2\u10d4\u10dc\u10da\u10dd\u10d1\u10d0 \u10e1\u10d0\u10d6\u10d8\u10d0\u10e0\u10dd\u10d3 MainWindow.dialog.share.sharedircontents.recursive=\u10e0\u10d4\u10d9\u10e3\u10e0\u10e1\u10d8\u10d5\u10d8 globalmanager.download.remove.veto=\u10d0\u10db\u10dd\u10d2\u10d3\u10d4\u10d1\u10d8\u10e1 \u10dd\u10de\u10d4\u10e0\u10d0\u10ea\u10d8\u10d0\u10e1 \u10d5\u10d4\u10e2\u10dd \u10d3\u10d0\u10d4\u10d3\u10dd ConfigView.section.tracker.main=\u10db\u10d7\u10d0\u10d5\u10d0\u10e0\u10d8 ConfigView.section.tracker.web=\u10d5\u10d4\u10d1\u10d8 ConfigView.label.prioritizefirstpiece=\u10e4\u10d0\u10d8\u10da\u10d8\u10e1(\u10d4\u10d1\u10d8\u10e1) \u10de\u10d8\u10e0\u10d5\u10d4\u10da\u10d8 \u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8\u10e1 \u10de\u10e0\u10d8\u10dd\u10e0\u10d8\u10d6\u10d4\u10d1\u10d0. ConfigView.label.prioritizefirstpiece.tooltip=\u10e8\u10d4\u10d4\u10ea\u10d0\u10d3\u10d4 \u10de\u10d8\u10e0\u10d5\u10d4\u10da \u10e0\u10d8\u10d2\u10e8\u10d8 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10dd \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10d3\u10d0\u10e1\u10d0\u10ec\u10e7\u10d8\u10e1\u10d8.\n\u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10ec\u10d8\u10dc\u10d0\u10e1\u10ec\u10d0\u10e0\u10d8 \u10d3\u10d0\u10d7\u10d5\u10d0\u10da\u10d8\u10d4\u10e0\u10d4\u10d1\u10d8\u10e1 \u10e4\u10e3\u10dc\u10e5\u10ea\u10d8\u10dd\u10dc\u10d0\u10da\u10dd\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 TrayWindow.menu.startalldownloads=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10e7\u10d5\u10d4\u10da\u10d0 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 SystemTray.menu.startalltransfers=\u10d2\u10d0\u10e3\u10e8\u10d5\u10d8 \u10e7\u10d5\u10d4\u10da\u10d0 \u10e2\u10e0\u10d0\u10dc\u10e1\u10e4\u10d4\u10e0\u10d8 sharing.progress.title=\u10d2\u10d0\u10d6\u10d8\u10d0\u10e0\u10d4\u10d1\u10d8\u10e1 \u10de\u10e0\u10dd\u10ea\u10d4\u10e1\u10d8 sharing.progress.hide=\u10d3\u10d0\u10db\u10d0\u10da\u10d5\u10d0 MainWindow.menu.view.myshares=\u10e9\u10d4\u10db\u10d8 \u10e1\u10d0\u10d6\u10d8\u10d0\u10e0\u10dd \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 MySharesView.title.full=\u10e1\u10d0\u10d6\u10d8\u10d0\u10e0\u10dd MySharesView.name=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8 MySharesView.type=\u10e2\u10d8\u10de\u10d8 MySharesView.type.file=\u10e4\u10d0\u10d8\u10da\u10d8 MySharesView.type.dir=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 MySharesView.type.dircontents=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8\u10e1 \u10e8\u10d8\u10d2\u10d7\u10d0\u10d5\u10e1\u10d8 MySharesView.type.dircontentsrecursive=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8\u10e1 \u10e8\u10d8\u10d2\u10d7\u10d0\u10d5\u10e1\u10d8 (\u10e0\u10d4\u10d9\u10e3\u10e0\u10e1\u10d8\u10d5\u10d8) MySharesView.menu.remove=\u10d0\u10db\u10dd\u10d0\u10d2\u10d3\u10d4 ConfigView.section.tracker.extensions=\u10d2\u10d0\u10e4\u10d0\u10e0\u10d7\u10d4\u10dd\u10d4\u10d1\u10d4\u10d1\u10d8 ConfigView.section.tracker.enableudp=\u10e9\u10d0\u10e0\u10d7\u10d4 UDP \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10de\u10e0\u10dd\u10e2\u10dd\u10d9\u10dd\u10da\u10d8 GeneralView.label.hash.tooltip=\u10d3\u10d0\u10ec\u10d9\u10d0\u10de\u10d4\u10d7 Hash-\u10d8\u10e1 \u10d1\u10e3\u10e4\u10d4\u10e0\u10e8\u10d8 \u10d9\u10dd\u10de\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 ConfigView.label.serverport=\u10e8\u10d4\u10db\u10dd\u10db\u10d0\u10d5\u10d0\u10da\u10d8 TCP \u10de\u10dd\u10e0\u10e2\u10d8 configureWizard.nat.server.tcp_listen_port=\u10e8\u10d4\u10db\u10dd\u10db\u10d0\u10d5\u10d0\u10da\u10d8 \u10db\u10dd\u10e1\u10d0\u10db\u10d4\u10dc\u10d8 TCP \u10de\u10dd\u10e0\u10e2\u10d8 ConfigView.section.sharing=\u10d2\u10d0\u10d6\u10d8\u10d0\u10e0\u10d4\u10d1\u10d0 ConfigView.section.style.dropdiraction.sharefolder=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8\u10e1 \u10d2\u10d0\u10d6\u10d8\u10d0\u10e0\u10d4\u10d1\u10d0 ConfigView.section.style.dropdiraction.sharefoldercontents=\u10e8\u10d4\u10db\u10ea\u10d5\u10d4\u10da\u10dd\u10d1\u10d8\u10e1 \u10d2\u10d0\u10d6\u10d8\u10d0\u10e0\u10d4\u10d1\u10d0 # # 2.0.7.x # Categories.all=\u10e7\u10d5\u10d4\u10da\u10d0 Categories.uncategorized=\u10d9\u10d0\u10e2\u10d4\u10d2\u10dd\u10e0\u10d8\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 CategoryAddWindow.message=\u10e8\u10d4\u10d8\u10e7\u10d5\u10d0\u10dc\u10d4 \u10d9\u10d0\u10e2\u10d4\u10d2\u10dd\u10e0\u10d8\u10d8\u10e1 \u10d3\u10d0\u10e1\u10d0\u10ee\u10d4\u10da\u10d4\u10d1\u10d0 CategoryAddWindow.title=\u10d3\u10d0\u10d0\u10db\u10d0\u10e2\u10d4 \u10d0\u10ee\u10d0\u10da\u10d8 \u10d9\u10d0\u10e2\u10d4\u10d2\u10dd\u10e0\u10d8\u10d0 ConfigView.label.autoSeedingIgnoreInfo=\u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 \u10d2\u10d0\u10d3\u10d0\u10d3\u10d8\u10e1 \u10e0\u10d8\u10d2\u10d8\u10e1 \u10d1\u10dd\u10da\u10dd\u10e8\u10d8. \u10d8\u10e1\u10d8\u10dc\u10d8 \u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d0\u10d3 \u10d0\u10e0 \u10d8\u10e0\u10d7\u10d5\u10d4\u10d1\u10d8\u10d0\u10dc. \u10d0\u10d9\u10e0\u10eb\u10d0\u10da\u10d5\u10d8\u10e1 \u10ec\u10d4\u10e1\u10d4\u10d1\u10d8 \u10d0\u10e0 \u10db\u10dd\u10e5\u10db\u10d4\u10d3\u10d4\u10d1\u10e1 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d6\u10d4 \u10e0\u10dd\u10db\u10da\u10d4\u10d1\u10d8\u10ea \u10de\u10d8\u10e0\u10d5\u10d4\u10da\u10d0\u10d3\u10d8 \u10de\u10e0\u10d8\u10dd\u10e0\u10d8\u10e2\u10d4\u10e2\u10d8\u10e1 \u10d9\u10e0\u10d8\u10e2\u10d4\u10e0\u10d8\u10e3\u10db\u10d4\u10d1\u10e8\u10d8\u10d0. \u10e1\u10ee\u10d5\u10d0 \u10e8\u10d4\u10db\u10d7\u10ee\u10d5\u10d4\u10d5\u10d0\u10e8\u10d8, \u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4\u10d7 \u10db\u10dc\u10d8\u10e8\u10d5\u10dc\u10d4\u10da\u10dd\u10d1\u10d0 0 \u10ec\u10d4\u10e1\u10d4\u10d1\u10d8\u10e1 \u10d2\u10d0\u10e1\u10d0\u10e3\u10e5\u10db\u10d4\u10d1\u10da\u10d0\u10d3. ConfigView.label.directory=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 ConfigView.label.disconnetseed.tooltip=\u10e0\u10dd\u10ea\u10d0 \u10d7\u10d4\u10e1\u10d0\u10d5, \u10d2\u10d0\u10db\u10dd\u10e0\u10d7\u10d4 \u10e7\u10d5\u10d4\u10da\u10d0 \u10d9\u10da\u10d8\u10d4\u10dc\u10e2\u10d8 \u10e0\u10dd\u10db\u10d4\u10da\u10d8\u10ea \u10d0\u10d2\u10e0\u10d4\u10d7\u10d5\u10d4 \u10d7\u10d4\u10e1\u10d0\u10d5\u10e1.\n\u10db\u10d0\u10d7 \u10e8\u10d4\u10dc\u10d7\u10d0\u10dc \u10d9\u10d0\u10d5\u10e8\u10d8\u10e0\u10d8 \u10d0\u10e0 \u10e1\u10ed\u10d8\u10e0\u10d3\u10d4\u10d1\u10d0\u10d7. ConfigView.label.ignoreCase=\u10e0\u10d4\u10d2\u10d8\u10e1\u10e2\u10e0\u10d8\u10e1 \u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10d0 ConfigView.label.ignoreSeeds=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8\u10e1 \u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10d0 \u10d0\u10e0\u10d0\u10dc\u10d0\u10d9\u10da\u10d4\u10d1 ConfigView.label.importdirectory=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8\u10e1 \u10d8\u10db\u10de\u10dd\u10e0\u10e2\u10d8 ConfigView.label.minPeersToBoostNoSeeds.tooltip=\u10dc\u10d4\u10d1\u10d8\u10e1\u10db\u10d8\u10d4\u10e0\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 \u10d7\u10d4\u10e1\u10da\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 \u10d0\u10dc peer\u2013\u10d4\u10d1\u10d8\u10e1 \u10e3\u10e4\u10e0\u10dd \u10dc\u10d0\u10d9\u10da\u10d4\u10d1\u10d8 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10de\u10d1\u10d8\u10d7 \u10d5\u10d8\u10d3\u10e0\u10d4 \u10db\u10d8\u10d7\u10d8\u10d7\u10d4\u10d1\u10e3\u10da\u10d8\u10d0\n\u10d2\u10d0\u10d3\u10d0\u10d5\u10d0 \u10e0\u10d8\u10d2\u10d8\u10e1 \u10d1\u10dd\u10da\u10dd\u10e8\u10d8. ConfigView.label.minPeersToBoostNoSeeds=\u10db\u10d8\u10e3\u10d7\u10d8\u10d7\u10d4 \u10d3\u10d0\u10d1\u10d0\u10da\u10d8 \u10d3\u10d0\u10d7\u10d4\u10e1\u10d5\u10d8\u10e1 \u10e0\u10d4\u10d8\u10e2\u10d8\u10dc\u10d2\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10e1, \u10e0\u10dd\u10db\u10da\u10d4\u10d1\u10e1\u10d0\u10ea \u10d0\u10e0 \u10d0\u10e5\u10d5\u10d7 \u10d7\u10d4\u10e1\u10da\u10d8 \u10d0\u10dc \u10d0\u10e5\u10d5\u10d7 \u10e3\u10e4\u10dd \u10dc\u10d0\u10d9\u10da\u10d4\u10d1\u10d8 \u10d5\u10d8\u10d3\u10e0\u10d4 ConfigView.label.minSeedingTime.tooltip=Seeding Ranks can fluctuate often in a short period time, sometimes causing the torrent to automatically start, only to be stopped && queued immediately afterwards.\nThis alleviates the problem by forcing the torrent to stay seeding for a given period of time. You can still stop it manually if you want. ConfigView.label.minSeedingTime=\u10d3\u10d0\u10d7\u10d4\u10e1\u10d5\u10d8\u10e1 \u10db\u10d8\u10dc\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10d3\u10e0\u10dd \u10ec\u10d0\u10db\u10d4\u10d1\u10e8\u10d8 ConfigView.label.minSpeedForActiveDL.tooltip=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10da\u10dd\u10e2\u10d8 \u10e7\u10dd\u10d5\u10d4\u10da\u10d7\u10d5\u10d8\u10e1 \u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10dc\u10d4\u10d1\u10d0 \u10e1\u10d0\u10ec\u10e7\u10d8\u10e1\u10d8 30 \u10ec\u10d0\u10db\u10d8\u10e1 \u10d2\u10d0\u10dc\u10d0\u10db\u10d0\u10d5\u10da\u10dd\u10d1\u10d0\u10e8\u10d8\n\u10db\u10d0\u10e1 \u10e8\u10d4\u10db\u10d3\u10d4\u10d2 \u10e0\u10d0\u10ea \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d4\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 \u10d3\u10d0\u10d8\u10ec\u10e7\u10d4\u10d1\u10d0 ConfigView.label.minSpeedForActiveDL=\u10d0\u10e0\u10e9\u10d0\u10d7\u10d5\u10d0\u10da\u10dd \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 \u10e1\u10da\u10dd\u10e2\u10d8\u10e1 \u10d3\u10d0\u10db\u10d9\u10d0\u10d5\u10d4\u10d1\u10da\u10d0\u10d3 \u10d7\u10e3 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 \u10d3\u10d0\u10d1\u10d0\u10da\u10d8\u10d0 \u10d5\u10d8\u10d3\u10e0\u10d4 ConfigView.label.peers=\u10de\u10d8\u10e0\u10d4\u10d1\u10d8 ConfigView.label.queue.debuglog=\u10df\u10e3\u10e0\u10dc\u10d0\u10da\u10e8\u10d8 \u10e8\u10d4\u10d8\u10e2\u10d0\u10dc\u10d4 debug \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 ConfigView.label.queue.debuglog.info=\u10d3\u10d0\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10e1 \u10e0\u10d8\u10d2\u10d8\u10e1 \u10d3\u10d4\u10d1\u10d0\u10d2 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0\u10e1 \u10d9\u10dd\u10dc\u10e1\u10dd\u10da\u10e8\u10d8/\u10df\u10e3\u10e0\u10dc\u10d0\u10da\u10e8\u10d8.\n\u10d3\u10d4\u10d1\u10d0\u10d2 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 \u10d2\u10d5\u10d4\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10d0 \u10d2\u10d0\u10d5\u10d0\u10e0\u10d9\u10d5\u10d8\u10dd\u10d7 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10db\u10d3\u10d2\u10dd\u10db\u10d0\u10e0\u10d4\u10dd\u10d1\u10d0 \u10d3\u10d0 \u10db\u10d0\u10d7\u10d8 \u10d0\u10e0 \u10d3\u10d0\u10ec\u10e7\u10d4\u10d1\u10d8\u10e1 \u10db\u10d8\u10d6\u10d4\u10d6\u10d4\u10d1\u10d8. ConfigView.label.queue.minQueueingShareRatio=\u10d0\u10e0 \u10e8\u10d4\u10d0\u10e9\u10d4\u10e0\u10dd \u10d0\u10dc \u10d2\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10dd \u10e0\u10d8\u10d2\u10e8\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 \u10e1\u10d0\u10dc\u10d0\u10db \u10db\u10d8\u10e1\u10d8 \u10d6\u10d8\u10d0\u10e0\u10d8 \u10e0\u10d4\u10d8\u10e2\u10d8\u10dc\u10d2\u10d8 \u10d0\u10e0 \u10db\u10d8\u10d0\u10e6\u10ec\u10d4\u10d5\u10e1 ConfigView.label.ratio=\u10e0\u10d4\u10d8\u10e2\u10d8\u10dc\u10d2\u10d8 ConfigView.label.removeOnStop=\u10d0\u10db\u10dd\u10d8\u10e6\u10d4 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 \u10e1\u10d8\u10d8\u10d3\u10d0\u10dc \u10e0\u10dd\u10ea\u10d0 \u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d0\u10d3 \u10e8\u10d4\u10e9\u10d4\u10e0\u10d3\u10d4\u10d1\u10d0 ConfigView.label.savedirectory=\u10e8\u10d4\u10d8\u10dc\u10d0\u10ee\u10d4 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 ConfigView.label.seeding.autoReposition=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8\u10e1 \u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 \u10e0\u10d4\u10de\u10dd\u10d6\u10d8\u10ea\u10d8\u10d0 \u10d3\u10d0\u10d7\u10d4\u10e1\u10d5\u10d8\u10e1 \u10e0\u10d4\u10d8\u10e2\u10d8\u10dc\u10d2\u10d6\u10d4 \u10d3\u10d0\u10e7\u10e0\u10d3\u10dd\u10dc\u10dd\u10d1\u10d8\u10d7 ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Often, torrents with low seed counts and high peer counts means that there probably isn't a full copy amoungst the peers.\nTherefore, you may not want the seeding rules pretending there's a full copy (and thus incorrectly reducing its rank) ConfigView.label.seeding.ignore=\u10ec\u10d4\u10e1\u10d4\u10d1\u10d8\u10e1 \u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10d0 ConfigView.label.seeding.ignore0Peers=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8\u10e1 \u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10d0 0 \u10de\u10d8\u10e0\u10d8\u10d7 ConfigView.label.seeding.ignore.header.rule=\u10ec\u10d4\u10e1\u10d8 ConfigView.label.seeding.ignore.header.value=\u10db\u10dc\u10d8\u10e8\u10d5\u10dc\u10d4\u10da\u10dd\u10d1\u10d0 ConfigView.label.seeding.firstPriority.info=First Priority torrents will always be at the top of the queue. Any torrents matching the First Priority criteria will not be automatically stopped and queued. A torrent matching First Priority criteria will take a Simultaneous Download slot if it needs to. ConfigView.label.seeding.firstPriority.FP=\u10de\u10d8\u10e0\u10d5\u10d4\u10da\u10d0\u10d3\u10d8 \u10de\u10e0\u10d8\u10dd\u10e0\u10d8\u10e2\u10d4\u10e2\u10d8 ConfigView.pluginlist.info=\u10db\u10dd\u10ee\u10d4\u10e0\u10ee\u10d3\u10d0 \u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10d8\u10d3\u10d4\u10dc\u10e2\u10d8\u10e4\u10d8\u10d9\u10d0\u10ea\u10d8\u10d0. \u10d6\u10dd\u10d2\u10d8\u10d4\u10e0\u10d7 \u10db\u10dd\u10d3\u10e3\u10da\u10e1 \u10d0\u10e0\u10d0 \u10d0\u10e5\u10d5\u10e1 \u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10e1 \u10e1\u10d0\u10dc\u10d8\u10e8\u10dc\u10d8. ConfigView.pluginlist.noplugins=\u10d5\u10d4\u10e0 \u10d5\u10d8\u10de\u10dd\u10d5\u10d4 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8. ConfigView.section.pluginslist=\u10e1\u10d8\u10d0 ConfigView.section.queue.seeding=\u10d7\u10d4\u10e1\u10d5\u10d0 ConfigView.section.queue.seeding.autoStarting=\u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 \u10e1\u10e2\u10d0\u10e0\u10e2\u10d8 ConfigView.section.queue.seeding.ignore=\u10ec\u10d4\u10e1\u10d4\u10d1\u10d8\u10e1 \u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10d0 ConfigView.section.queue.seeding.firstPriority=\u10de\u10d8\u10e0\u10d5\u10d4\u10da\u10d8 \u10de\u10e0\u10d8\u10dd\u10e0\u10d8\u10e2\u10d4\u10e2\u10d8 ConfigView.section.queue.main=\u10db\u10d7\u10d0\u10d5\u10d0\u10e0\u10d8 ConfigView.section.queue=\u10e0\u10d8\u10d2\u10d8 ConfigView.section.torrents=Torrent\u2013\u10d4\u10d1\u10d8 ConfigView.text.all=\u10e7\u10d5\u10d4\u10da\u10d0 ConfigView.text.hours=\u10e1\u10d0\u10d0\u10d7\u10d4\u10d1\u10d8 ConfigView.text.ignoreRule=\u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1 \u10ec\u10d4\u10e1\u10d4\u10d1\u10d8 ConfigView.text.ignore=\u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10d0 ConfigView.text.minutes=\u10ec\u10e3\u10d7\u10d4\u10d1\u10d8 ConfigView.text.any=\u10dc\u10d4\u10d1\u10d8\u10e1\u10db\u10d8\u10d4\u10e0\u10d8 DownloadManager.error.datamissing=\u10d3\u10d0\u10d9\u10d0\u10e0\u10d2\u10e3\u10da\u10d8\u10d0 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 MainWindow.menu.file.open.torrentforseeding=.torrent \u10e4\u10d0\u10d8\u10da\u10d8 (\u10d3\u10d0\u10e1\u10d0\u10d7\u10d4\u10e1\u10d0\u10d3) MainWindow.menu.language.refresh=\u10d2\u10d0\u10dc\u10ee\u10da\u10d4\u10d1\u10d0 ManagerItem.forced=\u10e4\u10dd\u10e0\u10e1\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 ManagerItem.queued=\u10e0\u10d8\u10d2\u10e8\u10d8\u10d0 MySeedersView.header=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d8\u10da\u10d8/\u10d3\u10d0\u10d7\u10d4\u10e1\u10d8\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 TableColumn.header.availability.info=# \u10e1\u10e0\u10e3\u10da\u10d8 \u10d0\u10e1\u10da\u10d4\u10d1\u10d8 \u10dc\u10d0\u10de\u10dd\u10d5\u10dc\u10d8\u10d0 TableColumn.header.availability=\u10ee\u10d4\u10da\u10db\u10d8\u10e1\u10d0\u10ec\u10d5\u10d3\u10dd\u10db\u10d8\u10d0 TableColumn.header.category=\u10d9\u10d0\u10e2\u10d4\u10d2\u10dd\u10e0\u10d8\u10d0 MyTorrentsView.header=\u10d3\u10d0\u10e3\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d4\u10da\u10d8/\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e0\u10d4\u10df\u10d8\u10db\u10e8\u10d8 TableColumn.header.maxuploads=\u10db\u10d0\u10e5\u10e1 # \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d4\u10d1\u10d8 MyTorrentsView.menu.category.delete=&\u10ec\u10d0\u10e8\u10d0\u10da\u10d4 \u10d9\u10d0\u10e2\u10d4\u10d2\u10dd\u10e0\u10d8\u10d0 MyTorrentsView.menu.forceStart=\u10e4\u10dd\u10e0\u10e1\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8 \u10e1\u10e2\u10d0\u10e0\u10e2\u10d8 MyTorrentsView.menu.queue=\u10e0\u10d8\u10d2\u10d8 MyTorrentsView.menu.setCategory.add=\u10d9\u10d0\u10e2\u10d4\u10d2\u10dd\u10e0\u10d8\u10d8\u10e1 \u10d3\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10d0.. MyTorrentsView.menu.setCategory=\u10d9\u10d0\u10e2\u10d4\u10d2\u10dd\u10e0\u10d8\u10d8\u10e1 \u10db\u10d8\u10d7\u10d8\u10d7\u10d4\u10d1\u10d0 TableColumn.header.savepath=\u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d8\u10e1 \u10d2\u10d6\u10d0 TableColumn.header.SeedingRank=\u10d7\u10d4\u10e1\u10d5\u10d8\u10e1 \u10e0\u10d0\u10dc\u10d2\u10d8 TableColumn.header.totalspeed=\u10e1\u10e0\u10e3\u10da\u10d8 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 splash.initializePlugins=\u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10d8\u10dc\u10d8\u10ea\u10d8\u10d0\u10da\u10d8\u10d6\u10d0\u10ea\u10d8\u10d0 StartStopRules.0Peers=0 peer StartStopRules.numSeedsMet=# \u10d7\u10d4\u10e1\u10da\u10d8 OK StartStopRules.ratioMet=Peer\u2013\u10d4\u10d1\u10d8:\u10d7\u10d4\u10e1\u10da\u10d8 OK StartStopRules.shareRatioMet=\u10d6\u10d8\u10d0\u10e0\u10d8 \u10e0\u10d4\u10d8\u10e2\u10d8\u10dc\u10d2\u10d8 OK StartStopRules.waiting=\u10db\u10dd\u10da\u10dd\u10d3\u10d8\u10dc\u10d8 StartStopRules.firstPriority=1\u2013\u10da\u10d8 \u10de\u10e0\u10d8\u10dd\u10e0\u10d8\u10e2\u10d4\u10e2\u10d8 ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\u10e8\u10d4\u10db\u10ea\u10d5\u10d4\u10da\u10dd\u10d1\u10d8\u10e1 \u10d2\u10d0\u10d6\u10d8\u10d0\u10e0\u10d4\u10d1\u10d0 (\u10e0\u10d4\u10d9\u10e3\u10e0\u10e1\u10d8\u10d5\u10d8) DownloadManager.error.unabletostartserver=\u10e1\u10d4\u10e0\u10d5\u10d4\u10e0\u10d8 \u10d5\u10d4\u10e0 \u10d2\u10d0\u10d4\u10e8\u10d5\u10d0 - \u10d2\u10d0\u10d3\u10d0\u10d0\u10db\u10dd\u10ec\u10db\u10d4\u10d7 \u10e8\u10d4\u10db\u10dd\u10db\u10d0\u10d5\u10d0\u10da\u10d8 \u10de\u10dd\u10e0\u10e2\u10d8\u10e1 \u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10d0 / \u10e5\u10e1\u10d4\u10da\u10e3\u10e0\u10d8 \u10d4\u10d9\u10e0\u10d0\u10dc\u10d8\u10e1 \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8 \u10de\u10e0\u10dd\u10d2\u10e0\u10d0\u10db\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d4\u10e0\u10d5\u10d4\u10e0\u10d0\u10d3 \u10db\u10e3\u10e8\u10d0\u10dd\u10d1\u10d8\u10e1 \u10dc\u10d4\u10d1\u10d0\u10e0\u10d7\u10d5\u10d0\u10d6\u10d4. GeneralView.label.creationdate=\u10e8\u10d4\u10e5\u10db\u10dc\u10d8\u10da\u10d8\u10d0 : ManagerItem.stopping=\u10e9\u10d4\u10e0\u10d3\u10d4\u10d1\u10d0 ConfigView.section.tracker.scrapeandcache=\u10e1\u10e5\u10e0\u10d4\u10d8\u10de\u10d8 \u10d3\u10d0 \u10e5\u10d4\u10e8\u10d8 MyTrackerView.scrapes=Scrap\u2013\u10d4\u10d1\u10d8 fileDownloadWindow.retry=\u10d9\u10d8\u10d3\u10d4\u10d5 \u10e1\u10ea\u10d0\u10d3\u10d4\u10d7 MyTrackerView.bytesin=\u10d1\u10d0\u10d8\u10e2\u10d8 \u10d0\u10e5\u10d4\u10d7 MyTrackerView.bytesinave=Ave \u10d8\u10e5\u10d8\u10d7 MyTrackerView.bytesout=\u10d1\u10d0\u10d8\u10e2\u10d8 \u10d8\u10e5\u10d8\u10d7 MyTrackerView.bytesoutave=Ave \u10d0\u10e5\u10d4\u10d7 ConfigView.section.proxy=\u10de\u10e0\u10dd\u10e5\u10e1\u10d8\u10e1 \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8 ConfigView.section.proxy.enable_proxy=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10de\u10e0\u10dd\u10e5\u10e1\u10d8 \u10db\u10db\u10d0\u10e0\u10d7\u10d4\u10d5\u10da\u10d8\u10e1 \u10ea\u10dd\u10db\u10e3\u10dc\u10d8\u10d9\u10d0\u10ea\u10d8\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 [\u10e1\u10d0\u10ed\u10d8\u10e0\u10dd\u10d0 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0] ConfigView.section.proxy.host=\u10f0\u10dd\u10e1\u10e2\u10d8 ConfigView.section.proxy.port=\u10de\u10dd\u10e0\u10e2\u10d8 ConfigView.section.proxy.username=\u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d8\u10e1 \u10e1\u10d0\u10ee\u10d4\u10da\u10d8 ConfigView.section.proxy.password=\u10de\u10d0\u10e0\u10dd\u10da\u10d8 ConfigView.section.proxy.enable_socks=SOCKS \u10de\u10e0\u10dd\u10e5\u10e1\u10d8 wizard.createtorrent.extrahashes=\u10d3\u10d0\u10d0\u10db\u10d0\u10e2\u10d4 \u10f0\u10d4\u10e8\u10d4\u10d1\u10d8 \u10e1\u10ee\u10d5\u10d0 \u10e5\u10e1\u10d4\u10da\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 (\u10db\u10d0\u10d2. Gnutella2, eDonkey2000) GeneralView.label.connected=\u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 ManagerItem.initializing=\u10d8\u10dc\u10d8\u10ea\u10d8\u10d0\u10da\u10d8\u10d6\u10d0\u10ea\u10d8\u10d0 AlertMessageBox.error=\u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 AlertMessageBox.warning=\u10d2\u10d0\u10e4\u10e0\u10d7\u10ee\u10d8\u10da\u10d4\u10d1\u10d0 AlertMessageBox.comment=\u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 AlertMessageBox.information=\u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 SharedPortServer.alert.selectorfailed=\u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 \u10e8\u10d4\u10db\u10dd\u10db\u10d0\u10d5\u10d0\u10da\u10d8 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d8\u10e1 \u10db\u10dd\u10e1\u10d0\u10e1\u10db\u10d4\u10dc\u10d8\u10e1 \u10e9\u10d0\u10e0\u10d7\u10d5\u10d0.\n\u10e8\u10d4\u10d0\u10db\u10dd\u10e5\u10db\u10d4 \u10d8\u10e5\u10dc\u10d4\u10d1 \u10e5\u10e1\u10d4\u10da\u10e3\u10e0\u10d8 \u10d4\u10d9\u10e0\u10d0\u10dc\u10d8\u10e1 \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8 \u10d9\u10e0\u10eb\u10d0\u10da\u10d0\u10d5\u10e1 java(w).exe\u2013\u10e1 'server'\u2013\u10d0\u10d3 \u10db\u10e3\u10e8\u10dd\u10d1\u10d8\u10e1 \u10e0\u10d4\u10df\u10d8\u10db\u10e1 Tracker.alert.listenfail=\u10e8\u10d4\u10e3\u10eb\u10da\u10d4\u10d1\u10d4\u10da\u10d8\u10d0 \u10db\u10dd\u10e1\u10d0\u10e1\u10db\u10d4\u10dc\u10d8 \u10de\u10dd\u10e0\u10e2\u10d8\u10e1 \u10e9\u10d0\u10e0\u10d7\u10d5\u10d0 %1.\n\u10e8\u10d4\u10d0\u10db\u10dd\u10ec\u10db\u10d4 \u10d8\u10e5\u10dc\u10d4\u10d1 \u10e0\u10dd\u10db\u10d4\u10da\u10d8\u10db\u10d4 \u10e1\u10ee\u10d5\u10d0 \u10de\u10e0\u10dd\u10d2\u10e0\u10d0\u10db\u10d0 \u10d8\u10e7\u10d4\u10dc\u10d4\u10d1\u10e1 \u10d0\u10db \u10de\u10dd\u10e0\u10e2\u10e1.\n\u10d0\u10d2\u10e0\u10d4\u10d7\u10d5\u10d4 \u10e8\u10d4\u10d0\u10db\u10dd\u10ec\u10db\u10d4 \u10d8\u10e5\u10dc\u10d4\u10d1 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10e1\u10ee\u10d5\u10d0 \u10d0\u10e1\u10da\u10d8 \u10e3\u10d9\u10d5\u10d4 \u10db\u10e3\u10e8\u10d0\u10dd\u10d1\u10e1. DiskManager.alert.movefileexists=\u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d0\u10dc\u10d8\u10e1\u10d0\u10e1\n\u10e4\u10d0\u10d8\u10da\u10d8 %1 \u10e4\u10d0\u10d8\u10da\u10d8 \u10e3\u10d9\u10d5\u10d4 \u10d0\u10e0\u10e1\u10d4\u10d1\u10dd\u10d1\u10e1 \u10d2\u10d0\u10d3\u10d0\u10e1\u10d0\u10e2\u10d0\u10dc \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10e8\u10d8 DiskManager.alert.movefilefails=\u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d0\u10dc\u10d8\u10e1\u10d0\u10e1\n %1 \u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d0\u10dc\u10d0 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0, %2 DiskManager.alert.movefilerecoveryfails=\u10d2\u10d0\u10d3\u10d0\u10e2\u10d0\u10dc\u10d8\u10e1 \u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d8\u10e1 \u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10d0\u10e6\u10d3\u10d2\u10d4\u10dc\u10d8\u10e1 \u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0\n\u10e4\u10d0\u10d8\u10da\u10d8\u10e1 %1 \u10d0\u10e6\u10d3\u10d2\u10d4\u10dc\u10d0 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0, %2 SpeedView.stats.title=\u10e1\u10e2\u10d0\u10e2\u10d8\u10e1\u10e2\u10d8\u10d9\u10d0 SpeedView.stats.total=\u10e1\u10e3\u10da SpeedView.stats.session=\u10d4\u10e1 \u10e1\u10d4\u10e1\u10d8\u10d0 SpeedView.stats.session.tooltip=\u10e1\u10e3\u10da (\u10de\u10e0\u10dd\u10e2\u10dd\u10d9\u10dd\u10da\u10d8) SpeedView.stats.downloaded=\u10e9\u10d0\u10db\u10dd\u10d8\u10e2\u10d5\u10d8\u10e0\u10d7\u10d0 (\u10de\u10e0\u10dd\u10e2\u10dd\u10d9\u10dd\u10da\u10d8) SpeedView.stats.uploaded=\u10d0\u10d8\u10e2\u10d5\u10d8\u10e0\u10d7\u10d0 (\u10de\u10e0\u10dd\u10e2\u10dd\u10d9\u10dd\u10da\u10d8) SpeedView.stats.ratio=\u10e0\u10d4\u10d8\u10e2\u10d8\u10dc\u10d2\u10d8 SpeedView.stats.uptime=\u10e1\u10d0\u10db\u10e3\u10e8\u10d0\u10dd \u10d3\u10e0\u10dd SpeedView.stats.now=\u10d0\u10ee\u10da\u10d0 SpeedView.stats.now.tooltip=\u10ef\u10d0\u10db\u10e3\u10e0\u10d8 (\u10de\u10e0\u10dd\u10e2\u10dd\u10d9\u10dd\u10da\u10d8) AutoMigration.useralert=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d8\u10e1 \u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10d8\u10e1 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1/\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d4\u10d1\u10d8\u10e1 \u10d0\u10d5\u10e2\u10dd\u2013\u10db\u10d8\u10d2\u10e0\u10d0\u10ea\u10d8\u10d8\u10e1 \u10e8\u10d4\u10d3\u10d4\u10d2\u10d4\u10d1\u10d8s:\n\n%1\n\u10e7\u10d5\u10d4\u10da\u10d0\u10dc\u10d0\u10d8\u10e0\u10d8 \u10e8\u10ea\u10d3\u10dd\u10db\u10d0 \u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d0\u10d3 \u10db\u10d8\u10d2\u10e0\u10d8\u10e0\u10d3\u10d4\u10d1\u10d0.\n\u10dc\u10e3 \u10d3\u10d0\u10d2\u10d0\u10d5\u10d8\u10ec\u10e7\u10d3\u10d4\u10d1\u10d0\u10d7 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 \u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d8\u10e1 \u10d2\u10d6\u10d4\u10d1\u10d8\u10e1 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 \u10d7\u10e3 \u10db\u10d0\u10d7\u10d8 \u10db\u10d8\u10d2\u10e0\u10d0\u10ea\u10d8\u10d0 \u10d2\u10e1\u10e3\u10e0\u10d7! # # > 2.0.8.0 # OpenTorrentWindow.title=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8(\u10d4\u10d1\u10d8) OpenTorrentWindow.message=\u10d4\u10e5\u10e1\u10de\u10d4\u10e0\u10d8\u10db\u10d4\u10dc\u10e2\u10d8 OpenTorrentWindow.addFiles=\u10d3\u10d0\u10d0\u10db\u10d0\u10e2\u10d4 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 OpenTorrentWindow.dataLocation=\u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d8\u10e1 \u10e8\u10d4\u10e1\u10d0\u10dc\u10d0\u10ee\u10d8 \u10d0\u10d3\u10d2\u10d8\u10da\u10d8: OpenTorrentWindow.startMode=\u10d3\u10d0\u10d0\u10db\u10d0\u10e2\u10d4 \u10e0\u10d4\u10df\u10d8\u10db\u10d8 OpenTorrentWindow.startMode.queued=\u10e0\u10d8\u10d2\u10e8\u10d8\u10d0 OpenTorrentWindow.startMode.stopped=\u10e8\u10d4\u10e9\u10d4\u10e0\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 OpenTorrentWindow.startMode.forceStarted=\u10e4\u10dd\u10e0\u10e1\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8 \u10e1\u10e2\u10d0\u10e0\u10e2\u10d8 OpenTorrentWindow.addPosition=\u10de\u10dd\u10d6\u10d8\u10ea\u10d8\u10d0 \u10e0\u10d8\u10d2\u10e8\u10d8 OpenTorrentWindow.addPosition.first=\u10de\u10d8\u10e0\u10d5\u10d4\u10da\u10d8 OpenTorrentWindow.addPosition.last=\u10e3\u10d9\u10d0\u10dc\u10d0\u10e1\u10d9\u10dc\u10d4\u10da\u10d8 TableColumn.header.remaining=\u10d3\u10d0\u10e0\u10e9\u10d4\u10dc\u10d8\u10da\u10d8\u10d0 popup.error.hide=\u10d3\u10d0\u10db\u10d0\u10da\u10d4 popup.error.details=\u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8 ConfigView.section.style.colorOverride.progressBar=\u10de\u10e0\u10dd\u10d2\u10e0\u10d4\u10e1\u10d8\u10e1 \u10db\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4\u10d1\u10d4\u10da\u10d8 ConfigView.section.style.colorOverride.error=\u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 MainWindow.status.tooOld=\u10de\u10e0\u10dd\u10d2\u10e0\u10d0\u10db\u10d0 \u10db\u10dd\u10eb\u10d5\u10d4\u10da\u10d3\u10d0, \u10d2\u10d7\u10ee\u10dd\u10d5\u10d7 \u10d2\u10d0\u10dc\u10d0\u10d0\u10ee\u10da\u10dd\u10d7. ConfigView.section.style.colorOverride.warning=\u10d2\u10d0\u10e4\u10e0\u10d7\u10ee\u10d8\u10da\u10d4\u10d1\u10d0 ConfigView.section.style.colorOverride.altRow=\u10d0\u10da\u10e2\u10d4\u10e0\u10dc\u10d0\u10e2\u10d8\u10e3\u10da\u10d8 \u10e0\u10d8\u10d2\u10d4\u10d1\u10d8 ConfigView.section.file.save.peers.pertorrent=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d6\u10d4 ConfigView.label.max_peers_per_torrent=\u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d0\u10d7\u10d0 \u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 \u10d4\u10e0\u10d7 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d6\u10d4 [0: \u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4] ConfigView.label.max_peers_total=\u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d0\u10d7\u10d0 \u10db\u10d8\u10dc\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 \u10d2\u10da\u10dd\u10d1\u10d0\u10da\u10e3\u10e0\u10d0\u10d3 [0: \u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4] ConfigView.section.language.info=\u10e0\u10dd\u10ea\u10d0 \u10e9\u10d0\u10e0\u10d7\u10e3\u10da\u10d8\u10d0, \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0\u10d7\u10d0 \u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 \u10db\u10dd\u10ee\u10d3\u10d4\u10d1\u10d0 Vuze u2013\u10d8\u10e1 \u10e7\u10dd\u10d5\u10d4\u10da \u10e9\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0\u10d6\u10d4 ConfigView.section.language.enableUpdate=\u10e9\u10d0\u10e0\u10d7\u10d4 Web \u10d2\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 ConfigView.section.language.UpdateURL=URL\u2013\u10d8\u10e1 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 ConfigView.section.language.UpdateNow=\u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0! Button.revert=\u10d3\u10d0\u10d1\u10e0\u10e3\u10dc\u10d4\u10d1\u10d0 MyTorrentsView.menu.changeDirectory=\u10e8\u10d4\u10ea\u10d5\u10d0\u10da\u10d4 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d8\u10e1 \u10d9\u10d0\u10e2\u10d4\u10da\u10dd\u10d2\u10d8 GenericText.column=\u10d9\u10dd\u10da\u10dd\u10dc\u10d0 MyTorrentsView.menu.thisColumn.remove=\u10d0\u10db\u10dd\u10d0\u10d2\u10d3\u10d4 \u10d9\u10dd\u10da\u10dd\u10dc\u10d0 MyTorrentsView.menu.thisColumn.toClipboard=\u10e2\u10d4\u10e5\u10e1\u10e2\u10d8\u10e1 \u10d0\u10e1\u10da\u10d8 \u10d0\u10d8\u10e6\u10d4 \u10d1\u10e3\u10e4\u10d4\u10e0\u10e8\u10d8 MyTorrentsView.menu.tracker=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 window.updateswt.status=\u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8 window.updateswt.failed=\u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0, \u10d3\u10d0\u10ec\u10d9\u10d0\u10de\u10d4 '\u10d3\u10d8\u10d0\u10ee' \u10ee\u10d4\u10da\u10d0\u10ee\u10da\u10d0 \u10d2\u10d0\u10d3\u10d0\u10e1\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d0\u10d3. window.updateswt.status.downloading.updater=\u10e3\u10d5\u10d8\u10e0\u10d7\u10d4\u10d1\u10d0 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d8\u10e1 \u10db\u10dd\u10d3\u10e3\u10da\u10d8 window.updateswt.status.finding=SWT\u2013\u10e1 \u10d1\u10dd\u10da\u10dd \u10d5\u10d4\u10e0\u10e1\u10d8\u10d8\u10e1 \u10eb\u10d8\u10d4\u10d1\u10d0 window.updateswt.status.downloading=\u10d8\u10e2\u10d5\u10d8\u10e0\u10d7\u10d4\u10d1\u10d0 SWT\u2013\u10e1 \u10d1\u10dd\u10da\u10dd \u10d5\u10d4\u10e0\u10e1\u10d8\u10d0 window.updateswt.status.done=\u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 window.updateswt.ok=\u10d3\u10d8\u10d0\u10ee window.updateswt.cancel=\u10d2\u10d0\u10e3\u10e5\u10db\u10d4\u10d1\u10d0 swt.updater.downloader.downloading=SWT \u10d8\u10e2\u10d5\u10d8\u10e0\u10d7\u10d4\u10d1\u10d0 swt.updater.urlsgetter.downloading=\u10d8\u10e2\u10d5\u10d8\u10e0\u10d7\u10d4\u10d1\u10d0 \u10e1\u10d0\u10e0\u10d9\u10e3\u10da\u10d8 \u10d0\u10e1\u10da\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d8\u10d0 swt.updater.urlsgetter.platform=SWT \u10de\u10da\u10d0\u10e2\u10e4\u10dd\u10e0\u10db\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 : window.updateswt.ignore=\u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10d0 splash.initializeGM=\u10d2\u10da\u10dd\u10d1\u10d0\u10da\u10e3\u10e0\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u2013\u10db\u10d4\u10dc\u10d4\u10ef\u10db\u10d4\u10dc\u10e2\u10d8\u10e1 \u10d8\u10dc\u10d8\u10ea\u10d8\u10d0\u10da\u10d8\u10d6\u10d0\u10ea\u10d8\u10d0 splash.loadingTorrents=\u10d8\u10e2\u10d5\u10d8\u10e0\u10d7\u10d4\u10d1\u10d0 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 splash.firstMessageNoI18N=(: \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8 :) MyTorrentsView.menu.thisColumn.sort=\u10e1\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d0 Scrape.status.ok=\u10e1\u10e5\u10e0\u10d4\u10d8\u10de\u10d8 OK Scrape.status.error=\u10e1\u10e5\u10e0\u10d4\u10d8\u10de\u10d8\u10e1 \u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0: Scrape.status.error.invalid=\u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8 \u10de\u10d0\u10e1\u10e3\u10ee\u10d8. Scrape.status.nextScrapeAt=\u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10e1\u10e5\u10e0\u10d4\u10d8\u10de\u10d8 %1 Scrape.status.scraping=\u10e1\u10e5\u10e0\u10d4\u10d8\u10de\u10d8.. Scrape.status.initializing=\u10e1\u10e5\u10e0\u10d4\u10d8\u10de\u10d8\u10e1 \u10db\u10dd\u10da\u10dd\u10d3\u10d8\u10dc\u10d8 ConfigView.label.minSpeedForActiveSeeding=\u10d0\u10e0\u10e9\u10d0\u10d7\u10d5\u10d0\u10da\u10dd \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d8\u10e3\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 \u10e1\u10da\u10dd\u10e2\u10d8\u10e1 \u10d3\u10d0\u10db\u10d9\u10d0\u10d5\u10d4\u10d1\u10da\u10d0\u10d3 \u10d7\u10e3 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 \u10d3\u10d0\u10d1\u10d0\u10da\u10d8\u10d0 \u10d5\u10d8\u10d3\u10e0\u10d4 ConfigView.section.stats.exportpeers=\u10de\u10d8\u10e0\u10d8\u10e1 \u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8\u10e1 \u10d4\u10e5\u10e1\u10de\u10dd\u10e0\u10e2\u10d8 MainWindow.menu.view.irc.moved=Irc \u10e3\u10d9\u10d5\u10d4 \u10ee\u10d4\u10da\u10db\u10d8\u10e1\u10d0\u10ec\u10d5\u10d3\u10dd\u10db\u10d8\u10d0 \u10e0\u10dd\u10d2\u10dd\u10e0\u10ea \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d8, \u10d8\u10ee\u10d8\u10da\u10d4\u10d7 http://azureus.sourceforge.net/plugin_list.php. \u10d7\u10e3 \u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 \u10dc\u10d0\u10ee\u10d4\u10d7 \u10ee\u10d4\u10d3\u10d8>\u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8->IRC \u10db\u10d4\u10dc\u10d8\u10e3 \u10db\u10d8\u10e1 \u10d2\u10d0\u10e1\u10d0\u10d0\u10e5\u10e2\u10d8\u10e3\u10e0\u10d4\u10d1\u10da\u10d0\u10d3. MyTrackerView.webui.contextmenu.copyurl=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 URL\u2013\u10d8\u10e1 \u10d9\u10dd\u10de\u10d8\u10e0\u10d4\u10d1\u10d0 Torrent.create.progress.ignoringfile=\u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10d0 ConfigView.section.interface.resetassoc=\u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d4 \u10d4\u10e5\u10e1\u10de\u10da\u10dd\u10e0\u10d4\u10e0\u10d8\u10e1 \u10e4\u10d0\u10da\u10e3\u10e0\u10d8 \u10d0\u10e1\u10dd\u10ea\u10d8\u10d0\u10ea\u10d8\u10d4\u10d1\u10d8 (.torrent) ConfigView.section.interface.resetassocbutton=\u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 ConfigView.section.interface.checkassoc=\u10d0\u10e1\u10dd\u10ea\u10d8\u10d4\u10ea\u10d8\u10d4\u10d1\u10d8\u10e1 \u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 \u10e9\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1\u10d0\u10e1 dialog.associations.title=\u10d0\u10e1\u10dd\u10ea\u10d8\u10d0\u10ea\u10d8\u10d8\u10e1 \u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 Button.yes=\u10d9\u10d8 Button.no=\u10d0\u10e0\u10d0 dialog.associations.prompt=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1 \u10d0\u10e0 \u10d0\u10e0\u10d8\u10e1 \u10e1\u10e2\u10d0\u10dc\u10d3\u10d0\u10e0\u10e2\u10e3\u10da\u10d8 \u10de\u10e0\u10dd\u10d2\u10e0\u10d0\u10db\u10d0 \u10d1\u10d8\u10e2 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1.\n\u10d2\u10e1\u10e3\u10e0\u10d7 \u10db\u10d8\u10e1\u10d8 \u10d0\u10e1\u10dd\u10ea\u10d8\u10e0\u10d4\u10d1\u10d0 .torrent \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d7\u10d0\u10dc? dialog.associations.askagain=\u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 \u10d2\u10d0\u10e8\u10d5\u10d4\u10d1\u10d8\u10e1\u10d0\u10e1 ConfigView.section.plugins.update=\u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 Plugin.pluginupdate.enablecheck=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d8\u10e1 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d8\u10e1 \u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 plugins.basicview.status=\u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8: plugins.basicview.activity=\u10d0\u10e5\u10e2\u10d8\u10e3\u10e0\u10dd\u10d1\u10d0 : plugins.basicview.progress=\u10de\u10e0\u10dd\u10d2\u10e0\u10d4\u10e1\u10d8: plugins.basicview.log=\u10df\u10e3\u10e0\u10dc\u10d0\u10da\u10d8: ConfigView.label.maxdownloadspeed=\u10d9\u10d1/\u10ec\u10db \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10d2\u10da\u10dd\u10d1\u10d0\u10da\u10e3\u10e0\u10d8 \u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 [0: \u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4] splash.loadingTorrent=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10e9\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 splash.of=\u10d3\u10d0\u10dc UpdateWindow.title=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 UpdateWindow.header=\u10e9\u10d0\u10db\u10dd\u10d7\u10d5\u10da\u10d8\u10da \u10d9\u10dd\u10db\u10de\u10dd\u10dc\u10d4\u10dc\u10e2\u10d4\u10d1\u10e1 \u10e1\u10ed\u10d8\u10e0\u10d3\u10d4\u10d1\u10d0\u10d7 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 : UpdateWindow.columns.install=\u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10d0 UpdateWindow.columns.name=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8 UpdateWindow.columns.version=\u10d5\u10d4\u10e0\u10e1\u10d8\u10d0 UpdateWindow.columns.size=\u10d6\u10dd\u10db\u10d0 UpdateWindow.cancel=\u10d2\u10d0\u10e3\u10e5\u10db\u10d4\u10d1\u10d0 UpdateWindow.quit=\u10d2\u10d0\u10db\u10dd\u10e1\u10d5\u10da\u10d0 UpdateWindow.close=\u10d3\u10d0\u10ee\u10e3\u10e0\u10d4 UpdateWindow.ok=\u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 UpdateWindow.restart=\u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 UpdateWindow.status.downloading=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 UpdateWindow.status.done=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 UpdateWindow.status.failed=\u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 UpdateWindow.status.restartNeeded=\u10e1\u10d0\u10ed\u10d8\u10e0\u10dd \u10d8\u10e5\u10dc\u10d4\u10d1\u10d0 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 ConfigView.pluginlist.broken=\u10d3\u10d0\u10d6\u10d8\u10d0\u10dc\u10d4\u10d1\u10e3\u10da\u10d8 ConfigView.pluginlist.whereToPut=\u10e8\u10d4\u10d8\u10dc\u10d0\u10ee\u10d4 \u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d8\u10e1-\u10e1\u10de\u10d4\u10ea\u10d8\u10e4\u10d8\u10e3\u10e0\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8 \u10db\u10d0\u10d7\u10e1\u10d0\u10d5\u10d4 \u10de\u10d4\u10e0\u10e1\u10dd\u10dc\u10d0\u10da\u10e3\u10e0 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10e8\u10d8: ConfigView.pluginlist.whereToPutOr=\u10d6\u10d8\u10d0\u10e0\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4: MainWindow.statusText.checking=\u10db\u10d8\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4\u10dd\u10d1\u10e1 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10e3\u10da\u10d8 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d8\u10e1 \u10eb\u10d8\u10d4\u10d1\u10d0 UpdateWindow.status.restartMaybeNeeded=\u10e8\u10d4\u10e1\u10d0\u10eb\u10da\u10dd\u10d0 \u10db\u10dd\u10d8\u10d7\u10ee\u10dd\u10d5\u10dd\u10e1 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d5\u10d0 ConfigView.pluginlist.shared=\u10d2\u10d0\u10d6\u10d8\u10d0\u10e0\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 PeersView.host=\u10f0\u10dd\u10e1\u10e2\u10d8\u10e1 \u10e1\u10d0\u10ee\u10d4\u10da\u10d8 MainWindow.menu.help.whatsnew=\u10e1\u10d8\u10d0\u10ee\u10da\u10d4 ConfigView.label.checkonstart=\u10d0\u10ee\u10d0\u10da\u10d8 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d8\u10e1 \u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1\u10d8 \u10d2\u10d0\u10e8\u10d5\u10d4\u10d1\u10d8\u10e1\u10d0\u10e1 ConfigView.label.periodiccheck=\u10de\u10e0\u10dd\u10d2\u10e0\u10d0\u10db\u10d8\u10e1 \u10d0\u10ee\u10d0\u10da\u10d8 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d8\u10e1 \u10de\u10d4\u10e0\u10d8\u10dd\u10d3\u10e3\u10da\u10d8 \u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 ConfigView.label.opendialog=\u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d0\u10d3 \u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d8\u10e1 \u10d0\u10e1\u10d8\u10e1\u10e2\u10d4\u10dc\u10e2\u10d8 \u10e0\u10dd\u10ea\u10d0 \u10d0\u10ee\u10d0\u10da\u10d8 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d0\u10d0 \u10ee\u10d4\u10da\u10db\u10d8\u10e1\u10d0\u10ec\u10d5\u10d3\u10dd\u10db\u10d8 MainWindow.updateavail=(\u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 \u10e8\u10d4\u10e1\u10d0\u10eb\u10da\u10d4\u10d1\u10d0\u10da\u10d8\u10d0) MainWindow.status.unofficialversion=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10d1\u10d4\u10e2\u10d0 MainWindow.status.latestversionunchecked=\u10d5\u10d4\u10e0\u10e1\u10d8\u10d8\u10e1 \u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 \u10d2\u10d0\u10db\u10dd\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 GeneralView.label.updatein.stopped=\u10e8\u10d4\u10e9\u10d4\u10e0\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 StartStopRules.menu.viewDebug=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 Debug \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 MainWindow.menu.help.plugins=\u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8\u2013\u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8 ConfigView.section.plugins.TrackerWeb=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10d5\u10d4\u10d1\u10d8 ConfigView.section.tracker.createbutton=\u10e8\u10d4\u10e5\u10db\u10dc\u10d0 security.certcreate.title=\u10e8\u10d4\u10e5\u10db\u10d4\u10dc\u10d8 \u10d7\u10d5\u10d8\u10e1\u2013\u10ee\u10d4\u10db\u10dd\u10ec\u10d4\u10e0\u10d8\u10da\u10d8 \u10e1\u10d4\u10e0\u10d7\u10d8\u10e4\u10d8\u10d9\u10d0\u10e2\u10d8 security.certcreate.intro=\u10d0\u10e5 \u10e8\u10d8\u10d4\u10eb\u10da\u10d4\u10d1\u10d0 \u10d7\u10d5\u10d8\u10d7\u2013\u10ee\u10d4\u10da\u10db\u10dd\u10ec\u10d4\u10e0\u10d8\u10da\u10d8 \u10e1\u10d4\u10e0\u10d7\u10d8\u10e4\u10d8\u10d9\u10d0\u10e2\u10d8\u10e1 \u10e8\u10d4\u10e5\u10db\u10dc\u10d0 security.certcreate.strength=\u10db\u10d3\u10d2\u10e0\u10d0\u10d3\u10dd\u10d1\u10d0 security.certcreate.firstlastname=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8 \u10d3\u10d0 \u10d2\u10d5\u10d0\u10e0\u10d8 security.certcreate.orgunit=\u10e1\u10d0\u10dd\u10e0\u10d2\u10d0\u10dc\u10d8\u10d6\u10d0\u10ea\u10d8\u10dd \u10d4\u10e0\u10d7\u10d4\u10e3\u10da\u10d8 security.certcreate.org=\u10dd\u10e0\u10d2\u10d0\u10dc\u10d8\u10d6\u10d0\u10ea\u10d8\u10d0 security.certcreate.city=\u10e5\u10d0\u10da\u10d0\u10e5\u10d8 \u10d0\u10dc \u10d3\u10d0\u10e1\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 security.certcreate.state=\u10e8\u10e2\u10d0\u10e2\u10d8 \u10d0\u10dc \u10de\u10e0\u10dd\u10d5\u10d8\u10dc\u10ea\u10d8\u10d0 security.certcreate.country=\u10e5\u10d5\u10d4\u10e7\u10dc\u10d8\u10e1 \u10dd\u10e0\u2013\u10dc\u10d8\u10e8\u10dc\u10d0 \u10d9\u10dd\u10d3\u10d8 security.certcreate.ok=\u10e8\u10d4\u10e5\u10db\u10d4\u10dc\u10d8 security.certcreate.cancel=\u10d2\u10d0\u10e3\u10e5\u10db\u10d4\u10d1\u10d0 security.certcreate.createok=\u10e1\u10d4\u10e0\u10d7\u10d8\u10e4\u10d8\u10d9\u10d0\u10e2\u10d8 \u10ec\u10d0\u10e0\u10db\u10d0\u10e2\u10d4\u10d1\u10d8\u10d7 \u10e8\u10d4\u10d8\u10e5\u10db\u10dc\u10d0 security.certcreate.createfail=\u10e1\u10d4\u10e0\u10d7\u10d8\u10e4\u10d8\u10d9\u10d0\u10e2\u10d8\u10e1 \u10e8\u10d4\u10e5\u10db\u10dc\u10d0 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 ConfigView.section.plugins.webui=Swing Web \u10d8\u10dc\u10e2\u10d4\u10e0\u10e4\u10d4\u10d8\u10e1\u10d8 ConfigView.section.plugins.xml_http_if=XML/HTTP \u10d8\u10dc\u10e2\u10d4\u10e0\u10e4\u10d4\u10d8\u10e1\u10d8 webui.passwordenable=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10de\u10d0\u10e0\u10dd\u10da\u10d8 webui.user=\u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d8\u10e1 \u10e1\u10d0\u10ee\u10da\u10d8 webui.password=\u10de\u10d0\u10e0\u10dd\u10da\u10d8 webui.port=\u10de\u10dd\u10e0\u10e2\u10d8 (*) webui.protocol=\u10de\u10e0\u10dd\u10e2\u10dd\u10d9\u10dd\u10da\u10d8 (*) webui.homepage=\u10d7\u10d0\u10d5\u10e4\u10e3\u10e0\u10ea\u10d4\u10da\u10d8 (*) webui.rootdir=\u10eb\u10d8\u10e0\u10d4\u10e3\u10da\u10d8 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 (*) webui.rootres=\u10eb\u10d8\u10e0\u10d4\u10e3\u10da\u10d8 \u10e0\u10d4\u10e1\u10e3\u10e0\u10e1\u10d8 (*) webui.mode=\u10e0\u10d4\u10df\u10d8\u10db\u10d8 (*) webui.mode.info=\u10e0\u10d4\u10df\u10d8\u10db\u10d8 \u10e8\u10d4\u10e1\u10d0\u10eb\u10da\u10dd\u10d0 \u10d8\u10e7\u10dd\u10e1\n\t"\u10e1\u10e0\u10e3\u10da\u10d8"\t= \u10d3\u10d0\u10e1\u10d0\u10e8\u10d5\u10d4\u10d1\u10d8\u10d0 \u10e7\u10d5\u10d4\u10da\u10d0 \u10dd\u10de\u10d4\u10e0\u10d0\u10ea\u10d8\u10d0 (\u10e1\u10e2\u10d0\u10dc\u10d3\u10d0\u10e0\u10e2\u10e3\u10da\u10d0\u10d3)\n\t"\u10d3\u10d0\u10d7\u10d5\u10d0\u10da\u10d8\u10d4\u10e0\u10d4\u10d1\u10d0"\t= \u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10d3\u10d0\u10d7\u10d5\u10d0\u10da\u10d8\u10d4\u10e0\u10d4\u10d1\u10d0 (\u10db\u10d0\u10d2\u10e0\u10d0\u10db \u10e8\u10d4\u10e1\u10d0\u10eb\u10da\u10dd\u10d0 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d8\u10ee\u10e8\u10d8\u10e0\u10d8\u10e1 \u10ea\u10d5\u10da\u10d8\u10da\u10d4\u10d1\u10d0) webui.access=\u10d3\u10d0\u10e8\u10d5\u10d4\u10d1\u10d0 (*) webui.access.info=\u10d3\u10d0\u10e8\u10d5\u10d4\u10d1\u10d0 \u10e8\u10d4\u10e1\u10d0\u10eb\u10da\u10dd\u10d0 \u10d8\u10e7\u10dd\u10e1\n\t"\u10da\u10dd\u10d9\u10d0\u10da\u10e3\u10e0\u10d8"\t= \u10dc\u10d8\u10e8\u10dc\u10d0\u10d5\u10e1 \u10e0\u10dd\u10db \u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10da\u10dd\u10d9\u10d0\u10da\u10e3\u10e0\u10d8 \u10db\u10d0\u10dc\u10e5\u10d0\u10dc\u10d8\u10d3\u10d0\u10dc \u10d0\u10e0\u10d8\u10e1 \u10e8\u10d4\u10e1\u10d0\u10eb\u10da\u10d4\u10d1\u10d4\u10da\u10d8 \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d0\n\t"\u10e7\u10d5\u10d4\u10da\u10d0"\t= \u10e8\u10d4\u10e3\u10d6\u10e6\u10e3\u10d3\u10d0\u10d5\u10d8 \u10d3\u10d0\u10e8\u10d5\u10d4\u10d1\u10d0 (\u10e1\u10e2\u10d0\u10dc\u10d3\u10d0\u10e0\u10e2\u10e3\u10da\u10d0\u10d3)\n\tIP\t= \u10db\u10d0\u10d2. 192.168.0.2\t\t\t\u10d4\u10e0\u10d7\u10d8 IP \u10db\u10ee\u10dd\u10da\u10dd\u10d3\n\tIP1-IP2\t= \u10db\u10d0\u10d2. 192.168.0.1-192.168.0.255\t\u10d8\u10dc\u10d9\u10da\u10e3\u10d6\u10d8\u10e3\u10e0\u10d8 IP \u10e0\u10d0\u10dc\u10d2\u10d8. GeneralView.label.maxdownloadspeed=\u10db\u10d0\u10e5\u10e1. \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 webui.restart.info=\u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8\u10e1 \u10ea\u10d5\u10da\u10d8\u10da\u10d4\u10d1\u10d0, \u10e0\u10dd\u10db\u10da\u10d4\u10d1\u10d8\u10ea \u10db\u10dd\u10dc\u10d8\u10e8\u10dc\u10e3\u10da\u10d8\u10d0 (*) \u10db\u10dd\u10d8\u10d7\u10ee\u10dd\u10d5\u10e1 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0\u10e1 GeneralView.label.maxdownloadspeed.tooltip=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 [0: \u10d2\u10d0\u10dc\u10e3\u10e1\u10d0\u10d6\u10e6\u10d5\u10e0\u10d4\u10da\u10d8] upnp.enable=\u10e9\u10d0\u10e0\u10d7\u10d4 UPnP upnp.info=Universal Plug and Play (UPnP) \u10d2\u10d5\u10d0\u10eb\u10da\u10d4\u10d5\u10e1 \u10e1\u10d0\u10e8\u10e3\u10d0\u10da\u10d4\u10d1\u10d0\u10e1 \u10de\u10dd\u10e0\u10e2\u10d4\u10d1\u10d8\u10e1 \u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 \u10db\u10d8\u10d1\u10db\u10d8\u10e1 \u10d2\u10d0\u10dc\u10e1\u10d0\u10ee\u10dd\u10e0\u10ea\u10d8\u10d4\u10da\u10d4\u10d1\u10da\u10d0\u10d3 UPnP\u2013\u10e9\u10d0\u10e0\u10d7\u10e3\u10da \u10db\u10d0\u10e0\u10e8\u10e0\u10e3\u10e2\u10d8\u10d6\u10d0\u10e2\u10dd\u10e0\u10d4\u10d1\u10d6\u10d4. upnp.mapping.dataport=\u10e8\u10d4\u10db\u10dd\u10db\u10d0\u10d5\u10d0\u10da\u10d8 peer\u2013\u10d8\u10e1 \u10e1\u10d0\u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10dd \u10de\u10dd\u10e0\u10e2\u10d8 upnp.mapping.tcptrackerport=TCP \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10de\u10dd\u10e0\u10e2\u10d8 upnp.mapping.udptrackerport=UDP \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10de\u10dd\u10e0\u10e2\u10d8 upnp.alert.differenthost=UPnP: \u10db\u10d8\u10d1\u10db\u10d0 '%1' \u10e0\u10d4\u10d6\u10d4\u10e0\u10d5\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 '%2' - \u10d2\u10d7\u10ee\u10dd\u10d5\u10d7 \u10db\u10d8\u10e3\u10d7\u10d8\u10d7\u10d4\u10d7 \u10e1\u10ee\u10d5\u10d0 \u10de\u10dd\u10e0\u10e2\u10d8 upnp.alert.mappingok=UPnP: \u10db\u10d8\u10d1\u10db\u10d0 '%1' \u10e9\u10d0\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 upnp.alert.mappingfailed=UPnP: \u10db\u10d8\u10d1\u10db\u10d0 '%1' \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 upnp.alertsuccess=\u10ec\u10d0\u10e0\u10db\u10d0\u10e2\u10d4\u10d1\u10e3\u10da\u10d8 \u10db\u10d8\u10d1\u10db\u10d4\u10d1\u10d8\u10e1 \u10e0\u10d4\u10de\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d0 upnp.alert.lostdevice=UPnP: \u10e1\u10d4\u10e0\u10d5\u10d8\u10e1\u10d7\u10d0\u10dc \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d0 \u10d3\u10d0\u10d9\u10d0\u10e0\u10d2\u10e3\u10da\u10d8\u10d0 '%1' UPnP \u10db\u10dd\u10ec\u10e7\u10dd\u10d1\u10d8\u10da\u10dd\u10d1\u10d0\u10d6\u10d4 '%2' upnp.grabports=\u10db\u10d8\u10d0\u10d1\u10d8 \u10de\u10dd\u10e0\u10e2\u10d4\u10d1\u10d8 \u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10db\u10d0\u10e8\u10d8\u10dc \u10e0\u10dd\u10ea\u10d0 \u10e1\u10ee\u10d5\u10d0 \u10d9\u10dd\u10db\u10de\u10d8\u10e3\u10e2\u10d4\u10e0\u10d8 \u10d8\u10e7\u10d4\u10dc\u10d4\u10d1\u10e1 upnp.refresh.label=\u10d2\u10d0\u10dc\u10d0\u10d0\u10ee\u10da\u10d4 \u10db\u10d8\u10d1\u10db\u10d4\u10d1\u10d8 upnp.refresh.button=\u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 upnp.alert.mappinggrabbed=UPnP: \u10db\u10d8\u10d1\u10db\u10d0 '%1' \u10e9\u10d0\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 - \u10db\u10d8\u10e6\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 '%2' upnp.mapping.tcpssltrackerport=TCP SSL \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10de\u10dd\u10e0\u10e2\u10d8 upnp.alertothermappings=\u10e1\u10ee\u10d5\u10d0 \u10d9\u10dd\u10db\u10de\u10d8\u10e3\u10e2\u10d4\u10e0\u10d8\u10e1 \u10de\u10dd\u10e0\u10e2\u10d4\u10d1\u10d8\u10e1 \u10e0\u10d4\u10de\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d0 upnp.alertdeviceproblems=\u10de\u10e0\u10dd\u10d1\u10da\u10d4\u10db\u10d4\u10d1\u10d8\u10e1 \u10e0\u10d4\u10de\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d0 UPnP \u10db\u10dd\u10ec\u10e7\u10dd\u10d1\u10d8\u10da\u10dd\u10d1\u10d8\u10d3\u10d0\u10dc blank.resource=\u10e0\u10d4\u10e1\u10e3\u10e0\u10e1\u10d8 ConfigView.pluginlist.coreplugins=\u10e9\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 \u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10de\u10d8\u10e0\u10d5\u10d4\u10da\u10d0\u10d3\u10d8 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8: Peers.column.DLedFromOthers=\u10e1\u10ee\u10d5\u10d4\u10d1\u10d8\u10e1\u10d2\u10d0\u10dc Peers.column.UpDownRatio=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0:\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 Peers.column.UpDownRatio.info=\u10de\u10d8\u10e0\u10d8\u10e1 "\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 : \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1" \u10e8\u10d4\u10e4\u10d0\u10e0\u10d3\u10d4\u10d1\u10d0 Peers.column.UpRatio.info=\u10de\u10d8\u10e0\u10d8\u10e1 \u10db\u10d8\u10d4\u10e0 "\u10d7\u10e5\u10d5\u10d4\u10dc\u10d2\u10d0\u10dc \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10d0\u10da\u10d8 : \u10e1\u10ee\u10d5\u10d8\u10e1\u10d2\u10d0\u10dc \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8" \u10e8\u10d4\u10e4\u10d0\u10e0\u10d3\u10d4\u10d1\u10d0 upnp.releasemappings=\u10d2\u10d0\u10dc\u10d0\u10d0\u10ee\u10da\u10d4 \u10db\u10d8\u10d1\u10db\u10d4\u10d1\u10d8 closedown\u2013\u10d8\u10e1 \u10d3\u10e0\u10dd\u10e1 webui.upnpenable=\u10e9\u10d0\u10e0\u10d7\u10d4 UPnP \u10d0\u10db \u10de\u10dd\u10e0\u10e2\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 (*) ConfigView.section.file.friendly.hashchecking=hash-\u10d4\u10d1\u10d8\u10e1 \u10db\u10d4\u10d2\u10dd\u10d1\u10e0\u10e3\u10da\u10d8 \u10d2\u10d0\u10d3\u10d0\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 Button.clear=\u10d2\u10d0\u10e1\u10e3\u10e4\u10d7\u10d0\u10d5\u10d4\u10d1\u10d0 MainWindow.IPs.tooltip={\u10e4\u10d8\u10da\u10e2\u10e0\u10d8\u10e1 \u10e1\u10d8\u10d8\u10e1 \u10d1\u10dd\u10da\u10dd \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0} \u10e1\u10d0\u10d4\u10e0\u10d7\u10dd IP\u10e4\u10d8\u10da\u10e2\u10e0\u10d4\u10d1\u10d8 \u10e1\u10d8\u10d0\u10e8\u10d8 - \u10d3\u10d0\u10d1\u10da\u10dd\u10d9\u10d8\u10da\u10d8/\u10d1\u10d0\u10dc\u2013\u10d3\u10d0\u10d3\u10d4\u10d1\u10e3\u10da\u10d8/\u10ea\u10e3\u10d3\u10d8 IP\u2013\u10d4\u10d1\u10d8 \u10d0\u10db \u10e1\u10d4\u10e1\u10d8\u10d0\u10e8\u10d8.\n\u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10dd\u10e0\u10db\u10d0\u10d2\u10d8 \u10ec\u10d9\u10d0\u10de\u10d8. ConfigView.section.ipfilter.list.banned=\u10d0\u10d8\u10d9\u10e0\u10eb\u10d0\u10da\u10d0 ConfigView.section.ipfilter.list.baddata=\u10d2\u10d0\u10db\u10dd\u10d0\u10d2\u10d6\u10d0\u10d5\u10dc\u10d0 \u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0: occurrences = Button.reset=\u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 ConfigView.section.ipfilter.bannedinfo=IP\u2013\u10d4\u10d1\u10d8 \u10e0\u10dd\u10db\u10da\u10d4\u10d1\u10db\u10d0\u10ea \u10d2\u10d0\u10db\u10dd\u10d0\u10d2\u10d6\u10d0\u10d5\u10dc\u10d0 \u10d0\u10e0\u10d0\u10ec\u10dd\u10e0\u10d8 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 - \u10d0\u10d8\u10d9\u10e0\u10eb\u10d0\u10da\u10d4\u10d1\u10d0 \u10d7\u10e3 \u10da\u10d8\u10db\u10d8\u10e2\u10e1 \u10d2\u10d0\u10d3\u10d0\u10d0\u10ed\u10d0\u10e0\u10d1\u10d4\u10d1\u10e1. ConfigView.section.ipfilter.blockedinfo=IP\u2013\u10d4\u10d1\u10d8 \u10e0\u10dd\u10db\u10da\u10d4\u10d1\u10d8\u10ea IP \u10e4\u10d8\u10da\u10e2\u10e0\u10d0\u10ea\u10d8\u10d8\u10e1 \u10d2\u10d0\u10db\u10dd \u10d3\u10d0\u10d8\u10d1\u10da\u10dd\u10d9\u10d0 download.removerules.name=\u10d0\u10db\u10dd\u10d2\u10d3\u10d4\u10d1\u10d8\u10e1 \u10ec\u10d4\u10e1\u10d4\u10d1\u10d8 download.removerules.unauthorised.info=Unauthorised torrents are those where the announce response contains either "not authoris(z)ed" or "unauthoris(z)ed" in the "failure response" download.removerules.unauthorised=Automatically remove unauthorised torrents download.removerules.unauthorised.seedingonly=\t\u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10d7\u10e3 \u10d8\u10d7\u10d4\u10e1\u10d4\u10d1\u10d0 download.removerules.removed.ok='%1' \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 \u10d0\u10db\u10dd\u10d2\u10d3\u10d4\u10d1\u10d0 \u10ec\u10d0\u10e0\u10db\u10d0\u10e2\u10d4\u10d1\u10d8\u10d7 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d3\u10d0. \u10d0\u10db\u10dd\u10d2\u10d3\u10d4\u10d1\u10d8\u10e1 \u10ec\u10e1\u10d4\u10d1\u10d8\u10e1 \u10d7\u10d0\u10dc\u10d0\u10ee\u10db\u10d0\u10d3. download.removerules.updatetorrents=\u10d0\u10db\u10dd\u10d0\u10d2\u10d3\u10d4 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d8 \u10e0\u10dd\u10d2\u10dd\u10e0\u10ea \u10e1\u10e5\u10d4\u10db\u10d0 \u10db\u10dd\u10d8\u10d7\u10ee\u10dd\u10d5\u10e1 ConfigView.label.defaultstarttorrentsstopped=\u10e0\u10dd\u10d2\u10dd\u10e0\u10ea \u10e1\u10e2\u10d0\u10dc\u10d3\u10d0\u10e0\u10e2\u10d8 \u10d3\u10d0\u10d0\u10db\u10d0\u10e2\u10d4 \u10d0\u10ee\u10d0\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 \u10e8\u10d4\u10e9\u10d4\u10e0\u10d4\u10d1\u10e3\u10da \u10e0\u10d4\u10df\u10d8\u10db\u10e8\u10d8 upnp.mapping.dataportudp=UDP \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10d9\u10da\u10d8\u10d4\u10dc\u10e2\u10d8\u10e1 \u10de\u10dd\u10e0\u10e2\u10d8 ConfigView.section.file.decoder.showall=\u10d2\u10d0\u10d8\u10d7\u10d5\u10d0\u10da\u10d8\u10e1\u10ec\u10d8\u10dc\u10d4 \u10e7\u10d5\u10d4\u10da\u10d0 \u10e8\u10d4\u10e1\u10d0\u10eb\u10da\u10dd \u10d9\u10dd\u10d3\u10d8\u10e0\u10d4\u10d1\u10d0 MainWindow.status.updowndetails.tooltip=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0/\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d8\u10e1 \u10d3\u10d4\u10e2\u10d0\u10da\u10e3\u10e0\u10d8 \u10d2\u10d0\u10dc\u10ee\u10d8\u10da\u10d5\u10d0 - \u10db\u10d0\u10e0\u10ef\u10d5\u10d4\u10dc\u10d0 \u10ec\u10d9\u10d0\u10de\u10d8 -\u10d3\u10d0\u10ec\u10d9\u10d0\u10de\u10d4 \u10e8\u10d4\u10e1\u10d0\u10ea\u10d5\u10da\u10d4\u10da\u10d0\u10d3 TrackerClient.announce.warningmessage='%1' \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4\u10db \u10d3\u10d0\u10d0\u10d1\u10e0\u10e3\u10dc\u10d0 \u10d2\u10d0\u10e4\u10e0\u10d7\u10ee\u10d8\u10da\u10d4\u10d1\u10d0 '%2' ConfigView.section.tracker.publishenabledetails=\u10e7\u10d5\u10d4\u10da\u10d0 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8\u10e1 \u10de\u10e3\u10d1\u10da\u10d8\u10d9\u10d0\u10ea\u10d8\u10d0 ConfigView.section.tracker.publishenablepeerdetails=\u10de\u10d8\u10e0\u10d8\u10e1 \u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8\u10e1 \u10de\u10e3\u10d1\u10da\u10d8\u10d9\u10d0\u10ea\u10d8\u10d0 MyTrackerView.badnat=\u10ea\u10e3\u10d3\u10d8 NAT MyTrackerView.badnat.info=\u10db\u10d7\u10d4\u10e1\u10d5\u10d4\u10da\u10d4\u10d1\u10d8/\u10de\u10d8\u10e0\u10d4\u10d1\u10d8 \u10e0\u10dd\u10db\u10da\u10d4\u10d1\u10db\u10d0\u10ea \u10d5\u10d4\u10e0 \u10d2\u10d0\u10d8\u10d0\u10e0\u10d4\u10e1 NAT \u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0, \u10d7\u10e3 \u10e9\u10d0\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 ConfigView.section.file.perf.cache.enable=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10e5\u10d4\u10e8\u10d8 \u10d3\u10d8\u10e1\u10d9\u10d6\u10d4 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u10e2\u10e0\u10d0\u10dc\u10e1\u10e4\u10d4\u10e0\u10d4\u10d1\u10d8 MainWindow.menu.transfers.startalltransfers=\u10e7\u10d5\u10d4\u10da\u10d0 \u10d3\u10d0\u10d8\u10ec\u10e7\u10d4 MainWindow.menu.transfers.stopalltransfers=\u10e7\u10d5\u10d4\u10da\u10d0 \u10e8\u10d4\u10d0\u10e9\u10d4\u10e0\u10d4 MainWindow.menu.transfers.pausetransfers=\u10de\u10d0\u10e3\u10d6\u10d0 MainWindow.menu.transfers.resumetransfers=\u10d2\u10d0\u10d0\u10d2\u10e0\u10eb\u10d4\u10da\u10d4 ConfigView.label.experimental.osx.kernel.panic.fix=\u10e1\u10d0\u10d4\u10e5\u10e1\u10de\u10d4\u10e0\u10d8\u10db\u10d4\u10dc\u10e2\u10dd \u10e9\u10d0\u10e1\u10ec\u10dd\u10e0\u10d4\u10d1\u10d0 kernel panics \u10dd\u10e0\u10db\u10d2-\u10de\u10e0\u10dd\u10ea\u10d4\u10e1\u10dd\u10e0\u10d8\u10d0\u10dc OSX \u10e1\u10d8\u10e1\u10e2\u10d4\u10db\u10d0\u10d6\u10d4 [\u10e1\u10d0\u10ed\u10d8\u10e0\u10dd\u10d4\u10d1\u10e1 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0\u10e1] SystemTray.menu.pausetransfers=\u10e2\u10e0\u10d0\u10e1\u10e4\u10d4\u10e0\u10d4\u10d1\u10d8\u10e1 \u10de\u10d0\u10e3\u10d6\u10d0 SystemTray.menu.resumetransfers=\u10e2\u10e0\u10d0\u10dc\u10e1\u10e4\u10d4\u10e0\u10d4\u10d1\u10d8\u10e1 \u10d2\u10d0\u10d2\u10e0\u10eb\u10da\u10d4\u10d1\u10d0 ConfigView.section.interface.enabletray=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10e1\u10d8\u10e1\u10e2\u10d4\u10db\u10e3\u10e0\u10d8 \u10de\u10d0\u10dc\u10d4\u10da\u10d8 [\u10e1\u10d0\u10ed\u10d8\u10e0\u10dd\u10d0 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0] Stats.title.full=\u10e1\u10e2\u10d0\u10e2\u10d8\u10e1\u10e2\u10d8\u10d9\u10d0 TransferStatsView.title.full=\u10e2\u10e0\u10d0\u10dc\u10e1\u10e4\u10d4\u10e0\u10d4\u10d1\u10d8 CacheView.title.full=\u10e5\u10d4\u10e8\u10d8 CacheView.general.size=\u10d6\u10e0\u10e3\u10da\u10d8 \u10d6\u10dd\u10db\u10d0 CacheView.general.inUse=\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4\u10d1\u10d0 CacheView.general.title=\u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 \u10e5\u10d4\u10e8\u10d6\u10d4 CacheView.reads.title=I/O \u10ec\u10d0\u10d9\u10d8\u10d7\u10ee\u10d5\u10d0 CacheView.reads.fromFile=\u10e4\u10d0\u10d8\u10da\u10d8\u10d3\u10d0\u10dc CacheView.reads.fromCache=\u10e5\u10d4\u10e8\u10d8\u10d3\u10d0\u10dc CacheView.reads.hits=\u10f0\u10d8\u10e2\u10d4\u10d1\u10d8! CacheView.writes.title=I/O \u10e9\u10d0\u10ec\u10d4\u10e0\u10d4\u10d1\u10d8 CacheView.writes.toCache=\u10e5\u10d4\u10e8\u10e8\u10d8 CacheView.writes.toFile=\u10e4\u10d0\u10d8\u10da\u10e8\u10d8 CacheView.writes.hits=\u10e8\u10d4\u10dc\u10d0\u10ee\u10e3\u10da\u10d8\u10d0 CacheView.speeds.title=\u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d8\u10e1 \u10e0\u10d0\u10d8\u10e2\u10d8\u10dc\u10d2\u10d8 CacheView.speeds.reads=\u10ec\u10d0\u10d9\u10d8\u10d7\u10ee\u10d5\u10d4\u10d1\u10d8 CacheView.speeds.writes=\u10e9\u10d0\u10ec\u10d4\u10e0\u10d4\u10d1\u10d8 CacheView.speeds.fromCache=\u10e5\u10d4\u10e8\u10d8\u10d3\u10d0\u10dc/\u10e5\u10d4\u10e8\u10e8\u10d8 CacheView.speeds.fromFile=\u10e4\u10d0\u10d8\u10da\u10d8\u10d3\u10d0\u10dc/\u10e4\u10d0\u10d8\u10da\u10e8\u10d8 CacheView.reads.amount=\u10e1\u10e3\u10da CacheView.reads.avgsize=\u10e1\u10d0\u10e8\u10e3\u10d0\u10da\u10dd \u10d6\u10dd\u10db\u10d0 openUrl.referrer=\u10e0\u10d4\u10e4\u10d4\u10e0\u10d0\u10e2\u10d8 \u10d2\u10d5\u10d4\u10e0\u10d3\u10d8\u10e1 URL : openUrl.referrer.info=\u10e1\u10d0\u10ed\u10d8\u10e0\u10dd\u10d0 \u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10e1\u10d0\u10d8\u10e2\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10e0\u10dd\u10db\u10da\u10d4\u10d1\u10d8\u10ea \u10db\u10dd\u10d8\u10d7\u10ee\u10dd\u10d5\u10d4\u10dc \u10db\u10d0\u10e1 ConfigView.label.maxuploadspeedseeding=\u10d9\u10d1/\u10ec\u10db \u10d2\u10da\u10dd\u10d1\u10d0\u10da\u10e3\u10e0\u10d8 \u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4, \u10e0\u10dd\u10ea\u10d0 \u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10d7\u10d4\u10e1\u10d0\u10d5\u10d7 [0: \u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4] ConfigView.label.transfer.ignorepeerports=\u10de\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1 \u10d8\u10d2\u10dc\u10d8\u10e0\u10d8\u10e0\u10d4\u10d1\u10d0 \u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10de\u10e0\u10dd\u10e2\u10d4\u10d1\u10d8\u10d7 (';' \u10d2\u10d0\u10db\u10dd\u10e7\u10dd\u10e4\u10d8, \u10db\u10d0\u10d2 0;25) ConfigView.section.proxy.enable_socks.peer=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10de\u10d8\u10e0\u10d7\u10d0 \u10d9\u10dd\u10db\u10e3\u10dc\u10d8\u10d9\u10d0\u10ea\u10d8\u10d4\u10d1\u10d8 \u10de\u10e0\u10dd\u10e5\u10e1\u10d8\u10e1 \u10d2\u10d0\u10d5\u10da\u10d8\u10d7 (\u10d2\u10d0\u10db\u10d0\u10d5\u10d0\u10da\u10d8 \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d4\u10d1\u10d8 \u10db\u10ee\u10dd\u10da\u10dd\u10d3) [\u10e1\u10d0\u10ed\u10d8\u10e0\u10dd\u10d0 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0] ConfigView.section.proxy.peer.informtracker=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d8\u10e0\u10d4\u10d1\u10d0 \u10da\u10d8\u10db\u10d8\u10e2\u10d4\u10d1\u10d8\u10e1 \u10e8\u10d4\u10e1\u10d0\u10ee\u10d4\u10d1 ConfigView.section.proxy.socks.version=SOCKS\u2013\u10d8\u10e1 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d0 PiecesView.legend.written=\u10e9\u10d0\u10ec\u10d4\u10e0\u10d8\u10da\u10d8 PiecesView.legend.requested=\u10db\u10dd\u10d7\u10ee\u10dd\u10d5\u10dc\u10d8\u10da\u10d8 PiecesView.legend.downloaded=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8, \u10e9\u10d0\u10ec\u10d4\u10e0\u10d8\u10e1 \u10db\u10dd\u10da\u10dd\u10d3\u10d8\u10dc\u10e8\u10d8 PiecesView.legend.incache=\u10d8\u10dc\u10e4\u10dd\u10db\u10d0\u10ea\u10d8\u10d0 \u10e5\u10d4\u10e8\u10e8\u10d8 PiecesView.typeItem.0=\u10dc\u10d4\u10da\u10d8 PiecesView.typeItem.1=\u10e9\u10e5\u10d0\u10e0\u10d8 PiecesView.type=\u10e2\u10d8\u10de\u10d8 Security.jar.tools_not_found=JAR \u10ee\u10d4\u10da\u10db\u10dd\u10ec\u10d4\u10e0\u10d0 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 - 'tools.jar' \u10d5\u10d4\u10e0 \u10d5\u10d8\u10de\u10dd\u10d5\u10d4 %1. \u10dc\u10d0\u10ee\u10d4 \u10d8\u10dc\u10e1\u10e2\u10e0\u10e3\u10db\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8->\u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8->\u10e3\u10e1\u10d0\u10e4\u10e0\u10d7\u10ee\u10dd\u10d4\u10d1\u10d0 \u10d3\u10d4\u10e2\u10d0\u10da\u10e3\u10e0\u10d8 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1. Security.jar.signfail=JAR \u10ee\u10d4\u10da\u10db\u10dd\u10ec\u10d4\u10e0\u10d0 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 - %1 ConfigView.section.security.toolsdir=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 \u10e0\u10dd\u10db\u10d4\u10da\u10e8\u10d8\u10ea \u10d2\u10d0\u10dc\u10d7\u10d0\u10d5\u10e1\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 'tools.jar' ConfigView.section.security.choosetoolssavedir=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 \u10e1\u10d0\u10d3\u10d0\u10ea \u10d2\u10d0\u10dc\u10d7\u10d0\u10d5\u10e1\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 'tools.jar' authenticator.torrent=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 ConfigView.section.proxy.peer.same=\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4 \u10d4\u10e0\u10d7\u10d8 \u10d3\u10d0 \u10d8\u10d2\u10d8\u10d5\u10d4 \u10de\u10e0\u10dd\u10e5\u10e1\u10d8\u10e1 \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10d4\u10d1\u10d8 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1\u10d0 \u10d3\u10d0 peer\u2013\u10d8\u10e1 \u10d9\u10dd\u10db\u10e3\u10dc\u10d8\u10d9\u10d0\u10ea\u10d8\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1. ConfigView.section.connection.network.max.simultaneous.connect.attempts=\u10db\u10d0\u10e5\u10e1\u10d8\u10d0\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10d4\u10e0\u10d7\u10d3\u10e0\u10dd\u10e3\u10da\u10d8 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 \u10e5\u10e1\u10d4\u10da\u10e3\u10e0\u10d8 \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d8\u10e1 \u10db\u10ea\u10d3\u10d4\u10da\u10dd\u10d1\u10d4\u10d1\u10d8 [0: \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d4\u10d1\u10d8 \u10d0\u10d9\u10e0\u10eb\u10d0\u10da\u10e3\u10da\u10d8\u10d0] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Max number of new outbound connection establishments Vuze should attempt any given time.\nNOTE: WindowsXP Service Pack 2 (SP2) imposes a system-wide limit of 10 simultaneous connect attempts.\nDefault value is 8. Value of 0 disables outbound connects entirely. ConfigView.section.file.perf.cache.size.explain=The cache is used to reduce reads from/writes to disk. Unless you are using the java option '-XX:MaxDirectMemorySize' to explicitly set the memory available for cache and network IO use, you should keep this value at least %1 below your maximum VM size. The current maximum VM size is %2. For instructions on how to change this, see MemoryUsage in the wiki on %3. Failure to use sensible settings will result on 'out of memory' errors. More than 32MB of cache is probably overkill. MyTorrentsView.menu.setSpeed.unlimit=\u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 MyTorrentsView.menu.setSpeed.unlimited=\u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 MyTorrentsView.menu.setSpeed.disable=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10d0\u10d9\u10e0\u10eb\u10d0\u10da\u10d5\u10d0 MyTorrentsView.menu.setSpeed.disabled=\u10d2\u10d0\u10db\u10dd\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 MyTorrentsView.menu.setSpeed.in=\u10e9\u10d4\u10db\u10dd\u10db\u10d0\u10d5\u10d0\u10da\u10d8 MyTorrentsView.menu.setSpeed.slots=\u10e1\u10da\u10dd\u10e2\u10d4\u10d1\u10d8 GeneralView.label.maxuploadspeed=\u10db\u10d0\u10e5\u10e1. \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 GeneralView.label.maxuploadspeed.tooltip=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 [0: \u10d2\u10d0\u10dc\u10e3\u10e1\u10d0\u10d6\u10e6\u10d5\u10e0\u10d4\u10da\u10d8] MyTorrents.items.UpSpeedLimit.disabled=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10d0\u10d9\u10e0\u10eb\u10d0\u10da\u10d5\u10d0 MyTorrents.items.UpSpeedLimit.unlimited=\u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 TableColumn.header.maxupspeed=\u10db\u10d0\u10e5\u10e1. \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 TableColumn.header.maxupspeed.info=\u10db\u10d0\u10e5\u10e1. \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 \u10d7\u10d8\u10d7\u10dd\u10d4\u10e3\u10da \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d6\u10d4 ConfigView.section.interface.wavlocation=.wav \u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10db\u10d3\u10d4\u10d1\u10d0\u10e0\u10d4\u10dd\u10d1\u10d0 ConfigView.section.interface.wavlocation.info=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 .wav \u10e4\u10d0\u10d8\u10da\u10d8 \u10d0\u10dc \u10d3\u10d0\u10e2\u10dd\u10d5\u10d4 \u10ea\u10d0\u10e0\u10d8\u10d4\u10da\u10d8 \u10ec\u10d8\u10dc\u10d0\u10e1\u10ec\u10d0\u10e0 \u10d2\u10d0\u10e1\u10d0\u10d6\u10e6\u10d5\u10e0\u10e3\u10da\u10d8 \u10ee\u10db\u10dd\u10d5\u10d0\u10dc\u10d8 \u10e1\u10d8\u10d2\u10dc\u10d0\u10da\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 ConfigView.section.tracker.server=\u10e1\u10d4\u10e0\u10d5\u10d4\u10e0\u10d8 ConfigView.section.tracker.client=\u10d9\u10da\u10d8\u10d4\u10dc\u10e2\u10d8 MainWindow.menu.tools=\u10d8\u10dc\u10e1\u10e2\u10e0\u10e3\u10db\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 FilesView.path=\u10d2\u10d6\u10d0 FilesView.fullpath=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 \u10e1\u10e0\u10e3\u10da\u10d8 \u10d2\u10d6\u10d0 FilesView.remaining=\u10d3\u10d0\u10e0\u10e9\u10d4\u10dc\u10d8\u10da\u10d8 \u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8 TableColumn.header.trackername=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10e1\u10d0\u10ee\u10d4\u10da\u10d8 ConfigView.group.override=\u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8\u10e1 \u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10d0 PeersView.menu.blockupload=\u10d1\u10da\u10dd\u10d9\u10d8\u10e1 \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 PeersView.state=\u10db\u10d3\u10d2\u10dd\u10db\u10d0\u10e0\u10d4\u10dd\u10d1\u10d0 PeersView.state.connecting=\u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d0 PeersView.state.handshake=\u10d5\u10d4\u10da\u10dd\u10d3\u10d4\u10d1\u10d8 \u10ee\u10d4\u10da\u10d8\u10e1 \u10e9\u10d0\u10db\u10dd\u10e0\u10d7\u10db\u10d4\u10d5\u10d0\u10e1 PeersView.state.established=\u10e1\u10e0\u10e3\u10da\u10d8 \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d0 DownloadManager.error.operationcancancelled=\u10dd\u10de\u10d4\u10e0\u10d0\u10ea\u10d8\u10d0 \u10d2\u10d0\u10e3\u10e5\u10db\u10d3\u10d0 Torrent.create.progress.cancelled=\u10dd\u10de\u10d4\u10e0\u10d0\u10ea\u10d8\u10d0 \u10d2\u10d0\u10e3\u10e5\u10db\u10d3\u10d0 sharing.progress.cancel=\u10d2\u10d0\u10e3\u10e5\u10db\u10d4\u10d1\u10d0 wizard.maketorrents.autoopen=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 \u10d3\u10d0\u10e1\u10d0\u10d7\u10d4\u10e1\u10d0\u10d3 \u10e0\u10dd\u10ea\u10d0 \u10d3\u10d0\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1 ConfigView.section.connection.advanced=\u10e5\u10e1\u10d4\u10da\u10d8\u10e1 \u10d3\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10d8\u10d7\u10d8 \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8 ConfigView.section.connection.advanced.mtu=\u10db\u10d0\u10e5\u10e1\u10d8\u10d0\u10db\u10da\u10e3\u10e0\u10d8 \u10d2\u10d0\u10d3\u10d0\u10e1\u10d0\u10ea\u10d4\u10db\u10d8 \u10d4\u10e0\u10d7\u10d4\u10e3\u10da\u10d8 (MTU) ConfigView.section.connection.advanced.SO_RCVBUF=\u10e1\u10dd\u10d9\u10d4\u10e2\u10d8\u10e1 SO_RCVBUF \u10d6\u10dd\u10db\u10d0 [0: use OS default] ConfigView.section.connection.advanced.SO_SNDBUF=\u10e1\u10dd\u10d9\u10d4\u10e2\u10d8\u10e1 SO_SNDBUF \u10d6\u10dd\u10db\u10d0 [0: use OS default] ConfigView.section.interface.confirm_torrent_removal=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 \u10d3\u10d0\u10d3\u10d0\u10e1\u10e2\u10e3\u10e0\u10d4\u10d1\u10d8\u10e1 \u10d3\u10d8\u10d0\u10da\u10dd\u10d2\u10d8 torrent\u2013\u10d8\u10e1 \u10ec\u10d0\u10e8\u10da\u10d8\u10e1\u10d0\u10e1 ConfigView.section.interface.confirm_torrent_removal.tooltip=\u10d3\u10d0\u10d0\u10d3\u10d0\u10e1\u10e2\u10e3\u10e0\u10d4 \u10e0\u10dd\u10ea\u10d0 \u10e8\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10e1 \u10e9\u10d4\u10db\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8\u10e1 \u10e4\u10d0\u10dc\u10ef\u10e0\u10d8\u10d3\u10d0\u10dc. MyTorrentsView.confirm_torrent_removal=\u10d3\u10d0\u10ec\u10e0\u10db\u10e3\u10dc\u10d4\u10d1\u10e3\u10da\u10d8 \u10ee\u10d0\u10e0 \u10ec\u10d0\u10e8\u10d0\u10da\u10dd?\n PeersView.connected_time=\u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d8\u10e1 \u10d3\u10e0\u10dd PeersView.connected_time.info=\u10de\u10d8\u10e0\u10d7\u10d0\u10dc \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d8\u10e1 \u10e1\u10e0\u10e3\u10da\u10d8 \u10d3\u10e0\u10dd ConfigView.section.interface.display.add_torrents_silently=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8\u10e1 \u10e3\u10ee\u10db\u10d0\u10e3\u10e0\u10dd\u10d3 \u10e9\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10d0 ConfigView.section.interface.display.add_torrents_silently.tooltip=\u10d3\u10d0\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10e1 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10e1 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10db\u10d7\u10d0\u10d5\u10d0\u10e0\u10d8 \u10e4\u10d0\u10dc\u10ef\u10e0\u10d8\u10e1 \u10d2\u10d0\u10db\u10dd\u10e9\u10d4\u10dc\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 TableColumn.header.maxdownspeed=\u10db\u10d0\u10e5\u10e1. \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 TableColumn.header.maxdownspeed.info=\u10db\u10d0\u10e5\u10e1. \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 \u10d7\u10d8\u10d7\u10dd\u10d4\u10e3\u10da \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d6\u10d4 PeersGraphicView.title=\u10e1\u10e5\u10d4\u10db\u10d0 TableColumn.header.torrentpath=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10db\u10d3\u10d4\u10d1\u10d0\u10e0\u10d4\u10dd\u10d1\u10d0 TableColumn.header.torrentpath.info=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10db\u10d3\u10d4\u10d1\u10d0\u10e0\u10d4\u10dd\u10d1\u10d0 \u10d3\u10d8\u10e1\u10d9\u10d6\u10d4 ConfigView.section.sharing.torrentcomment=\u10d9\u10dd\u10db\u10d4\u10dc\u10e2\u10d0\u10e0\u10d8 \u10d2\u10d4\u10dc\u10d4\u10e0\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 ConfigView.label.copyanddeleteratherthanmove=\u10d2\u10d0\u10d3\u10d0\u10d0\u10d9\u10dd\u10de\u10d8\u10e0\u10d4 \u10d3\u10d0 \u10e8\u10d4\u10db\u10d3\u10d4\u10d2 \u10ec\u10d0\u10e8\u10d0\u10da\u10d4 \u10dd\u10e0\u10d8\u10d2\u10d8\u10dc\u10d0\u10da\u10e3\u10e0\u10d8 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 \u10d5\u10d8\u10d3\u10e0\u10d4 \u10d4\u10e0\u10d7\u10d8 \u10dd\u10de\u10d4\u10e0\u10d0\u10ea\u10d8\u10d8\u10d7 \u10d2\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10dd \u10e1\u10ee\u10d5\u10d0 \u10d0\u10d3\u10d2\u10d8\u10da\u10d0\u10e1 \u2013 \u10d3\u10d0\u10d2\u10d4\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10d0 \u10d7\u10d0\u10d5\u10d8\u10d3\u10d0\u10dc \u10d0\u10d8\u10ea\u10d8\u10da\u10dd \u10d2\u10d0\u10e3\u10d7\u10d5\u10d0\u10da\u10d8\u10e1\u10ec\u10d8\u10d4\u10dc\u10d1\u10d4\u10da\u10d8 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d8\u10e1 \u10d3\u10d0\u10d9\u10d0\u10e0\u10d2\u10d5\u10d0 \u10d6\u10dd\u10d2\u10d8\u10d4\u10e0\u10d7 \u10e4\u10d0\u10d8\u10da\u10e3\u10e0 \u10e1\u10d8\u10e1\u10e2\u10d4\u10db\u10d4\u10d1\u10e8\u10d8. ConfigView.label.openstatsonstart=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8\u10e1\u10e2\u10d0\u10e2\u10d8\u10e1\u10e2\u10d8\u10d9\u10d0 \u10d2\u10d0\u10e8\u10d5\u10d4\u10d1\u10d8\u10e1\u10d0\u10e1 swt.install.window.title=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10e2\u10dd\u10e0\u10d8 swt.install.window.ok=\u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10d0 swt.install.window.header=\u10db\u10dd\u10ea\u10d4\u10db\u10e3\u10da\u10d8 \u10d9\u10dd\u10db\u10de\u10dd\u10dc\u10d4\u10e2\u10d4\u10d1\u10d8 \u10e8\u10d4\u10e0\u10e9\u10d4\u10e3\u10da \u10d8\u10e5\u10dc\u10d0 \u10e1\u10d0\u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10dd\u10d3 : swt.uninstall.window.title=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10d0\u10db\u10dd\u10d2\u10d3\u10d4\u10d1\u10d0 swt.uninstall.window.ok=\u10d0\u10db\u10dd\u10d0\u10d2\u10d3\u10d4 swt.uninstall.window.header=\u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10d9\u10dd\u10db\u10de\u10dd\u10dc\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 \u10db\u10dd\u10dc\u10d8\u10e8\u10dc\u10e3\u10da\u10d8\u10d0 \u10d0\u10db\u10dd\u10e1\u10d0\u10d2\u10d3\u10d4\u10d1\u10d0\u10d3 : installPluginsWizard.title=\u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10d0 installPluginsWizard.mode.title=\u10d2\u10d7\u10ee\u10dd\u10d5\u10d7 \u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10dd\u10d7 \u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10d8\u10e1 \u10db\u10d4\u10d7\u10dd\u10d3\u10d8 installPluginsWizard.mode.list=\u10e1\u10d8\u10d8\u10d7 sourceforge.net\u2013\u10d3\u10d0\u10dc installPluginsWizard.list.title=\u10e9\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0\u10d3\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d8\u10d0 installPluginsWizard.list.loading=\u10db\u10dd\u10d8\u10d7\u10db\u10d8\u10dc\u10d4\u10d7 \u10e1\u10d0\u10dc\u10d0\u10db \u10e1\u10d8\u10d0 \u10e9\u10d0\u10d8\u10e2\u10d5\u10d8\u10e0\u10d7\u10d4\u10d1\u10d0. installPluginsWizard.list.loaded=\u10d2\u10d7\u10ee\u10dd\u10d5\u10d7 \u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10dd\u10d7 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8 \u10e0\u10dd\u10db\u10da\u10d8\u10e1 \u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10d0\u10ea \u10d2\u10e1\u10e3\u10e0\u10d7. installPluginsWizard.list.name=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8 installPluginsWizard.list.version=\u10d5\u10d4\u10e0\u10e1\u10d8\u10d0 installPluginsWizard.list.description=\u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d8\u10e1 \u10d0\u10e6\u10ec\u10d4\u10e0\u10d0 installPluginsWizard.finish.title=\u10db\u10d8\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4\u10dd\u10d1\u10e1 \u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10d0 installPluginsWizard.finish.explanation=\u10e8\u10d4\u10e0\u10e9\u10d4\u10e3\u10da\u10d8 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8 \u10d3\u10d0\u10e7\u10d4\u10dc\u10d3\u10d4\u10d1\u10d0 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d8\u10e1 \u10d0\u10e1\u10d8\u10e1\u10e2\u10d4\u10dc\u10e2\u10d8\u10e1 \u10db\u10d8\u10d4\u10e0.\n\n\u10d2\u10d7\u10ee\u10dd\u10d5\u10d7 \u10db\u10dd\u10d8\u10d7\u10db\u10d8\u10dc\u10dd\u10d7, \u10e1\u10d0\u10ed\u10d8\u10e0\u10dd\u10d0 \u10db\u10ea\u10d8\u10e0\u10d4 \u10ee\u10d0\u10dc\u10d8 \u10d8\u10dc\u10e4\u10dd\u10e1 \u10d2\u10d0\u10db\u10dd\u10e1\u10d0\u10e9\u10d4\u10dc\u10d0\u10d3.\n\n\u10de\u10e0\u10dd\u10ea\u10d4\u10e1\u10d8\u10e1 \u10db\u10d8\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4\u10dd\u10d1\u10d8\u10e1 \u10e8\u10d4\u10e1\u10d0\u10ee\u10d4\u10d1 \u10d3\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10d8\u10d7\u10d8 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0, \u10d8\u10ee\u10d8\u10da\u10d4\u10d7 \u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8\u10e1 \u10d6\u10dd\u10da\u10d6\u10d4 \u10dd\u10e0\u10db\u10d0\u10d2\u10d8 \u10ec\u10d9\u10d0\u10de\u10d8\u10d7. installPluginsWizard.details.loading=\u10d3\u10d4\u10e2\u10d0\u10da\u10e3\u10e0\u10d8 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d8\u10e1 \u10e9\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0, \u10d2\u10d7\u10ee\u10dd\u10d5\u10d7 \u10db\u10dd\u10d8\u10ea\u10d0\u10d3\u10dd\u10d7... installPluginsWizard.mode.file=\u10e4\u10d0\u10d8\u10da\u10d8\u10d7 installPluginsWizard.installMode.title=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10d8\u10e1 \u10e2\u10d8\u10de\u10d8 installPluginsWizard.installMode.user=\u10d3\u10d0\u10d0\u10e7\u10d4\u10dc\u10d4 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d8(\u10d4\u10d1\u10d8) \u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10d7\u10e5\u10d5\u10d4\u10dc\u10d7\u10d5\u10d8\u10e1 installPluginsWizard.installMode.shared=\u10d3\u10d0\u10d0\u10e7\u10d4\u10dc\u10d4 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d8(\u10d4\u10d1\u10d8) \u10e7\u10d5\u10d4\u10da\u10d0 \u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 installPluginsWizard.file.title=\u10d2\u10d7\u10ee\u10dd\u10d5\u10d7 \u10d2\u10d0\u10dc\u10d8\u10ee\u10d8\u10da\u10dd\u10d7 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d8\u10e1 \u10e4\u10d0\u10d8\u10da\u10d8 \u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 installPluginsWizard.file.file=\u10e4\u10d0\u10d8\u10da\u10d8 : installPluginsWizard.file.invalidfile=\u10d4\u10e1 \u10e4\u10d0\u10d8\u10da\u10d8\u10d0\u10e0 \u10d0\u10e0\u10d8\u10e1 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10d9\u10dd\u10e0\u10d4\u10e5\u10e2\u10e3\u10da\u10d8 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d8. installPluginsWizard.file.browse=\u10db\u10d8\u10db\u10dd\u10ee\u10d8\u10da\u10d5\u10d0... uninstallPluginsWizard.title=\u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10d0\u10db\u10dd\u10d2\u10d3\u10d4\u10d1\u10d0 uninstallPluginsWizard.list.title=\u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d8\u10d0 uninstallPluginsWizard.list.loaded=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8 \u10e0\u10dd\u10db\u10da\u10d8\u10e1 \u10d0\u10db\u10dd\u10d2\u10d3\u10d4\u10d1\u10d0\u10ea \u10d2\u10e1\u10e3\u10e0\u10e1. installPluginsWizard.list.nullversion=\u10d5\u10d4\u10e0\u10e1\u10d8\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 uninstallPluginsWizard.finish.title=\u10ec\u10d0\u10e8\u10da\u10d8\u10e1 \u10de\u10e0\u10dd\u10ea\u10d4\u10e1\u10d8 uninstallPluginsWizard.finish.explanation=\u10e8\u10d4\u10e0\u10e9\u10d4\u10e3\u10da\u10d8 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d4\u10d1\u10d8 \u10ec\u10d0\u10d8\u10e8\u10da\u10d4\u10d1\u10d0 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d8\u10e1 \u10d0\u10e1\u10d8\u10e1\u10e2\u10d4\u10dc\u10e2\u10d8\u10e1 \u10e1\u10d0\u10e8\u10e3\u10d0\u10da\u10d4\u10d1\u10d8\u10d7. MainWindow.menu.plugins.installPlugins=\u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10d8\u10e1 \u10dd\u10e1\u10e2\u10d0\u10e2\u10d8 MainWindow.menu.plugins.uninstallPlugins=\u10d0\u10db\u10dd\u10e8\u10da\u10d8\u10e1 \u10dd\u10e1\u10e2\u10d0\u10e2\u10d8 ConfigView.section.ipfilter.totalIPs=%1 IP\u10d3\u10d0\u10d8\u10d1\u10da\u10dd\u10d9\u10d0 \u10e1\u10e3\u10da, \u10e0\u10dd\u10db\u10d4\u10da\u10d8\u10ea \u10d0\u10e0\u10d8\u10e1 %2 \u10d8\u10dc\u10e2\u10d4\u10e0\u10dc\u10d4\u10e2\u10e8\u10d8. update.instance.install=\u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10d8\u10e1 \u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 update.instance.uninstall=\u10d0\u10db\u10dd\u10d2\u10d3\u10d4\u10d1\u10d8\u10e1 \u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 update.instance.update=\u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d8\u10e1 \u10e8\u10d4\u10db\u10dd\u10ec\u10db\u10d4\u10d1\u10d0 MainWindow.status.update.tooltip=\u10d3\u10d0\u10ec\u10d9\u10d0\u10de\u10d4\u10d7 \u10dd\u10e0\u10db\u10d0\u10d2\u10d0\u10d3, \u10de\u10e0\u10dd\u10ea\u10d4\u10e1\u10d8\u10e1 \u10db\u10d8\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4\u10dd\u10d1\u10d8\u10e1 \u10d3\u10d4\u10e2\u10d0\u10da\u10e3\u10e0\u10d8 \u10d2\u10d0\u10dc\u10ee\u10d8\u10da\u10d5\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1. updater.progress.window.title=\u10db\u10d8\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4 \u10e1\u10d0\u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10dd \u10d3\u10d0\u10d5\u10d0\u10da\u10d4\u10d1\u10d4\u10d1\u10d8 updater.progress.window.info=\u10d3\u10d0\u10d0\u10ed\u10d8\u10e0\u10d4 '\u10e8\u10d4\u10ec\u10e7\u10d5\u10d4\u10e2\u10d0\u10e1' \u10e0\u10dd\u10db \u10d2\u10d0\u10d0\u10e3\u10e5\u10db\u10dd \u10e7\u10d5\u10d4\u10da\u10d0 \u10db\u10d8\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4 \u10d3\u10d0\u10d5\u10d0\u10da\u10d4\u10d1\u10d0 Button.abort=\u10e8\u10d4\u10ec\u10e7\u10d5\u10d4\u10e2\u10d0 ConfigView.section.ipfilter.enablebanning=peer\u2013\u10d4\u10d1\u10d8\u10e1 \u10d1\u10da\u10dd\u10d9\u10d8\u10e0\u10d4\u10d1\u10d0 \u10e0\u10dd\u10db\u10da\u10d4\u10d1\u10db\u10d0\u10ea \u10d2\u10d0\u10db\u10dd\u10d0\u10d2\u10d6\u10d0\u10d5\u10dc\u10d4\u10e1 \u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d8\u10e1 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 MyShares.column.category=\u10d9\u10d0\u10e2\u10d4\u10d2\u10dd\u10e0\u10d8\u10d0 UpdateWindow.restartLater=\u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d4 \u10db\u10dd\u10d2\u10d5\u10d8\u10d0\u10dc\u10d4\u10d1\u10d8\u10d7 MainWindow.menu.file.restart=\u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 MainWindow.dialog.restartconfirmation.title=\u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 MainWindow.dialog.restartconfirmation.text=\u10d3\u10d0\u10d2\u10d0\u10d5\u10e2\u10d5\u10d8\u10e0\u10d7\u10dd \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8? ConfigView.label.prioritizemostcompletedfiles=\u10e8\u10d4\u10d3\u10d0\u10e0\u10d4\u10d1\u10d8\u10d7 \u10e3\u10e4\u10dd\u10e0 \u10db\u10d4\u10e2\u10d0\u10d3 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10de\u10e0\u10d8\u10dd\u10e0\u10d8\u10d6\u10d4\u10d1\u10d0 splash.plugin.init=\u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d8\u10e1 \u10d8\u10dc\u10d8\u10ea\u10d8\u10d0\u10da\u10d8\u10d6\u10d0\u10ea\u10d8\u10d0: MyTorrentsView.menu.exportmenu=\u10d4\u10e5\u10e1\u10de\u10dd\u10e0\u10e2\u10d8 MyTorrentsView.menu.exporttorrent=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8... ConfigView.group.scrape=\u10e1\u10e5\u10e0\u10d4\u10d8\u10de\u10d8 ConfigView.section.tracker.client.scrapeenable=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10e1\u10e5\u10e0\u10d4\u10d8\u10de\u10d8 Scrape.status.disabled=\u10e1\u10e5\u10e0\u10d4\u10d8\u10de\u10d8 \u10d2\u10d0\u10db\u10dd\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 MyTorrentsView.menu.explore=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 \u10e4\u10d0\u10d8\u10da\u10d8 MyTorrentsView.menu.explore._mac=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 Finder-\u10e8\u10d8 MyTorrentsView.menu.explore._windows=\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4 \u10d4\u10e5\u10e1\u10de\u10da\u10dd\u10e0\u10d4\u10e0\u10e8\u10d8 wizard.maketorrents.autohost=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10f0\u10dd\u10e1\u10e2\u10d8\u10dc\u10d2\u10d8 \u10e9\u10db\u10dd\u10dc\u10e2\u10d0\u10df\u10d4\u10d1\u10e3\u10da\u10d8 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10d1\u10d0\u10d6\u10d0\u10d6\u10d4 ConfigView.label.overrideip=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10d0\u10dc\u10dd\u10dc\u10e1\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1 IP \u10db\u10d8\u10e1\u10d0\u10db\u10d0\u10e0\u10d7\u10d8\u10e1 \u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10d0 ConfigView.label.overrideip.tooltip=\u10e8\u10d4\u10d0\u10e2\u10e7\u10dd\u10d1\u10d8\u10dc\u10d4 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4\u10e1 \u10d2\u10d0\u10db\u10d0\u10d5\u10d0\u10da\u10d8 \u10de\u10d0\u10d9\u10d4\u10e2\u10d4\u10d1\u10d8\u10e1\u10d0\u10d2\u10d0\u10dc \u10d2\u10d0\u10dc\u10e1\u10ee\u10d5\u10d0\u10d5\u10d4\u10d1\u10e3\u10da\u10d8 IP \u10db\u10d8\u10e1\u10d0\u10db\u10d0\u10e0\u10d7\u10d8\u10e1 \u10e8\u10d4\u10e1\u10d0\u10ee\u10d4\u10d1. \u10d3\u10d0\u10e2\u10dd\u10d5\u10d4 \u10ea\u10d0\u10e0\u10d8\u10d4\u10da\u10d8 \u10d7\u10e3 \u10d0\u10e0 \u10d2\u10d8\u10dc\u10d3\u10d0 \u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10dd \u10d4\u10e1 \u10dd\u10e4\u10ea\u10d8\u10d0. ConfigView.section.connection.group.networks=\u10e5\u10e1\u10d4\u10da\u10d4\u10d1\u10d8 ConfigView.section.connection.group.networks.info=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10ec\u10d8\u10dc\u10d0\u10e1\u10ec\u10d0\u10e0 \u10d2\u10d0\u10dc\u10e1\u10d0\u10d6\u10e6\u10d5\u10e0\u10e3\u10da\u10d8 \u10d3\u10d0\u10e1\u10d0\u10e8\u10d5\u10d4\u10d1\u10d8 \u10e5\u10e1\u10d4\u10da\u10d4\u10d1\u10d8 p2p \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d8\u10e1 \u10d2\u10d0\u10d3\u10d0\u10e1\u10d0\u10ea\u10d4\u10db\u10d0\u10d3 ConfigView.section.connection.networks.Public=\u10e1\u10d0\u10d4\u10e0\u10d7\u10dd IP \u10e5\u10e1\u10d4\u10da\u10d8 (\u10d0\u10e0\u10d0 \u10d0\u10dc\u10dd\u10dc\u10d8\u10db\u10e3\u10e0\u10d8) ConfigView.section.connection.networks.I2P=I2P \u10e5\u10e1\u10d4\u10da\u10d8 ConfigView.section.connection.networks.Tor=The Onion Router (Tor) \u10e5\u10e1\u10d4\u10da\u10d8 TableColumn.header.networks=\u10e5\u10e1\u10d4\u10da\u10d4\u10d1\u10d8 TableColumn.header.networks.info=\u10e5\u10e1\u10d4\u10da\u10d4\u10d1\u10d8 \u10e0\u10dd\u10db\u10da\u10d4\u10d1\u10e8\u10d8\u10ea \u10dc\u10d4\u10d1\u10d0 \u10d3\u10d0\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 p2p \u10d9\u10dd\u10db\u10e3\u10dc\u10d8\u10d9\u10d0\u10ea\u10d8\u10d4\u10d1\u10d8 Scrape.status.networkdisabled=\u10e5\u10e1\u10d4\u10da\u10d8 \u10d0\u10e0 \u10d0\u10e0\u10d8\u10e1 \u10e9\u10d0\u10e0\u10d7\u10e3\u10da\u10d8 ConfigView.section.tracker.server.group.networks=\u10e5\u10e1\u10d4\u10da\u10d4\u10d1\u10d8 window.networkselection.title=\u10e5\u10e1\u10d4\u10da\u10d8\u10e1 \u10e8\u10d4\u10e0\u10e9\u10d4\u10d5\u10d0 window.networkselection.info=\u10e5\u10d5\u10d4\u10db\u10dd\u10d7 \u10db\u10dd\u10e7\u10d5\u10d0\u10dc\u10d8\u10da \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10e1 \u10d0\u10e5\u10d5\u10e1 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4(\u10d4\u10d1\u10d8) \u10e0\u10dd\u10db\u10da\u10d4\u10d1\u10d8\u10ea \u10db\u10e3\u10e8\u10d0\u10dd\u10d1\u10d4\u10dc \u10e8\u10d4\u10db\u10d3\u10d4\u10d2 \u10e5\u10e1\u10d4\u10da\u10d4\u10d1\u10e8\u10d8.\n\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10e0\u10d0\u10db\u10dd\u10d3\u10d4\u10dc\u10d8\u10db\u10d4 \u10e0\u10dd\u10db \u10e9\u10d0\u10e0\u10d7\u10dd \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1\u10d0 \u10d3\u10d0 \u10de\u10d8\u10e0\u10d8\u10e1 \u10d9\u10dd\u10db\u10e3\u10dc\u10d8\u10d9\u10d0\u10ea\u10d8\u10d0.\n\u10d7\u10e3 \u10d4\u10e1 \u10d0\u10e0\u10d8\u10e1 \u10d0\u10dc\u10dd\u10dc\u10d8\u10db\u10e3\u10e0\u10d8 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4, \u10e0\u10dd\u10db\u10d4\u10da\u10d8\u10ea \u10db\u10e3\u10e8\u10d0\u10dd\u10d1\u10e1 \u10e1\u10d0\u10d6\u10dd\u10d2\u10d0\u10d3\u10dd\u2013\u10d9\u10da\u10d8\u10d4\u10dc\u10e2\u10d4\u10d1\u10d7\u10d0\u10dc \u10e9\u10d0\u10e0\u10d7\u10d4 \u10d0\u10dc\u10dd\u10dc\u10d8\u10db\u10e3\u10e0\u10d8 \u10d3\u10d0 \u10e1\u10d0\u10d6\u10dd\u10d2\u10d0\u10d3\u10dd \u10e5\u10e1\u10d4\u10da\u10d4\u10d1\u10d8.\n\u10e1\u10d0\u10d6\u10dd\u10d2\u10d0\u10d3\u10dd \u10e5\u10e1\u10d4\u10da\u10d4\u10d1\u10d8\u10e1 \u10e9\u10d0\u10e0\u10d7\u10d5\u10d0 \u10d8\u10ec\u10d5\u10d4\u10d5\u10e1 \u10d0\u10dc\u10dd\u10dc\u10d8\u10db\u10e3\u10e0\u10dd\u10d1\u10d8\u10e1 \u10e8\u10d4\u10d6\u10e6\u10e3\u10d3\u10d5\u10d0\u10e1. window.networkselection.description=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8 : plugins.basicview.clear=\u10d2\u10d0\u10d0\u10e1\u10e3\u10e4\u10d7\u10d0\u10d5\u10d4 ConfigView.section.connection.group.peersources=peer\u2013\u10d8\u10e1 \u10ec\u10e7\u10d0\u10e0\u10dd\u10d4\u10d1\u10d8 ConfigView.section.connection.peersource.Tracker=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10db\u10d8\u10d4\u10e0 ConfigView.section.connection.peersource.DHT=\u10d3\u10d4\u10ea\u10d4\u10dc\u10e2\u10e0\u10d0\u10da\u10d8\u10d6\u10d4\u10d1\u10e3\u10da\u10d8 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4\u10dd\u10d1\u10d0 ConfigView.section.connection.peersource.PeerExchange=\u10e3\u10d6\u10e0\u10e3\u10dc\u10d5\u10d4\u10da\u10e7\u10dd\u10e4\u10e1 \u10e1\u10ee\u10d5\u10d0 peer ConfigView.section.connection.peersource.Plugin=\u10e9\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10e3\u10da\u10d8 \u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d8\u10e1 \u10db\u10d8\u10d4\u10e0 ConfigView.section.connection.peersource.Incoming=\u10e8\u10d4\u10db\u10dd\u10db\u10d0\u10d5\u10d0\u10da\u10d8 \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d0 PeersView.source=\u10ec\u10e7\u10d0\u10e0\u10dd TableColumn.header.peersources=\u10de\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1 \u10ec\u10e7\u10d0\u10e0\u10dd\u10d4\u10d1\u10d8 wizard.tracker.dht=\u10d3\u10d4\u10ea\u10d4\u10dc\u10e2\u10e0\u10d0\u10da\u10d8\u10d6\u10d4\u10d1\u10e3\u10da\u10d8 (\u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10d9\u10da\u10d8\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8) MyTorrentsView.menu.networks=\u10e5\u10e1\u10d4\u10da\u10d4\u10d1\u10d8 MyTorrentsView.menu.peersource=\u10de\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1 \u10ec\u10e7\u10d0\u10e0\u10dd\u10d4\u10d1\u10d8 PeersView.Messaging=\u10e8\u10d4\u10e2\u10e7\u10dd\u10d1\u10d8\u10dc\u10d4\u10d1\u10d4\u10d1\u10d8 ConfigView.label.queue.newseedsmovetop=\u10d2\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10d4 \u10d0\u10ee\u10da\u10d0\u10d3 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 \u10d3\u10d0\u10d7\u10d4\u10e1\u10d5\u10d8\u10e1 \u10e1\u10d8\u10d8\u10e1 \u10d7\u10d0\u10d5\u10e8\u10d8 ConfigView.label.seeding.firstPriority.ignore0Peer=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 0 \u10de\u10d8\u10e0\u10d8\u10d7 MagnetPlugin.contextmenu.exporturi=Magnet URI\u2013\u10e1 \u10d9\u10dd\u10de\u10d8\u10e0\u10d4\u10d1\u10d0 \u10d1\u10e3\u10e4\u10d4\u10e0\u10e8\u10d8 ConfigView.section.plugins.dht=\u10d3\u10d8\u10e1\u10e2\u10e0\u10d8\u10d1\u10e3\u10ea\u10d8\u10e3\u10da\u10d8 \u10db\u10dd\u10dc\u10d0\u10ea\u10db\u10d4\u10d7\u10d0 \u10d1\u10d0\u10d6\u10d0 dht.enabled=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10d3\u10d8\u10e1\u10e2\u10e0\u10d8\u10d1\u10e3\u10ea\u10d8\u10e3\u10da\u10d8 \u10db\u10dd\u10dc\u10d0\u10ea\u10d4\u10db\u10d7\u10d0 \u10d1\u10d0\u10d6\u10d0 dht.portdefault=\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4 \u10e1\u10e2\u10d0\u10dc\u10d3\u10d0\u10e0\u10e2\u10e3\u10da\u10d8 \u10de\u10dd\u10e0\u10e2\u10d8 dht.execute.command=\u10d3\u10d8\u10d0\u10d2\u10dc\u10dd\u10e1\u10e2\u10d8\u10d9\u10e3\u10e0\u10d8 \u10d1\u10e0\u10eb\u10d0\u10dc\u10d4\u10d1\u10d0 dht.execute=\u10d2\u10d0\u10e8\u10d5\u10d4\u10d1\u10d0 ConfigView.section.plugins.dhttracker=\u10d3\u10d8\u10e1\u10e2\u10e0\u10d8\u10d1\u10e3\u10ea\u10d8\u10e3\u10da\u10d8 \u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d4 ConfigView.section.file.nativedelete._mac=\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4 \u10e1\u10d0\u10dc\u10d0\u10d2\u10d5\u10d4 \u10e7\u10e3\u10d7\u10d8 \u10e0\u10dd\u10ea\u10d0 \u10e8\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10e1 ConfigView.section.file.nativedelete._windows=\u10d2\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10d4 \u10ec\u10d0\u10e8\u10da\u10d8\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 \u10e1\u10d0\u10dc\u10d0\u10d2\u10d5\u10d4 \u10e7\u10e3\u10d7\u10e8\u10d8 ConfigView.section.logging.generatediagnostics=\u10d2\u10d4\u10dc\u10d4\u10e0\u10d0\u10ea\u10d8\u10d0 MainWindow.menu.tools.nattest=NAT / \u10e5\u10e1\u10d4\u10da\u10e3\u10e0\u10d8 \u10d4\u10d9\u10e0\u10d0\u10dc\u10d8\u10e1 \u10e2\u10d4\u10e1\u10e2\u10d8 Button.apply=\u10d2\u10d0\u10db\u10dd\u10e7\u10d4\u10dc\u10d4\u10d1\u10d0 Button.close=\u10d3\u10d0\u10ee\u10e3\u10e0\u10d5\u10d0 window.welcome.title=\u10db\u10dd\u10d2\u10d4\u10e1\u10d0\u10da\u10db\u10d4\u10d1\u10d0\u10d7 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8 %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=\u10e0\u10d4\u10da\u10d8\u10d6\u10d8\u10e1 \u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8 DHTView.transport.title=\u10e2\u10e0\u10d0\u10dc\u10e1\u10de\u10dd\u10e0\u10e2\u10d8\u10e1 \u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8 DHTView.operations.title=\u10dd\u10de\u10d4\u10e0\u10d0\u10ea\u10d8\u10d8\u10e1 \u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8 DHTView.activity.details=\u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8 MainWindow.dht.status.tooltip=\u10e0\u10dd\u10ea\u10d0 \u10e1\u10d0\u10d3\u10d8\u10e1\u10e2\u10e0\u10d8\u10d1\u10e3\u10ea\u10d8\u10dd \u10db\u10dd\u10dc\u10d0\u10ea\u10d4\u10db\u10d7\u10d0 \u10d1\u10d0\u10d6\u10d0 \u10d2\u10d0\u10e8\u10d5\u10d4\u10d1\u10e3\u10da\u10d8\u10d0, \u10d0\u10e9\u10d5\u10d4\u10dc\u10d4\u10d1\u10e1 \u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d4\u10d1\u10d8\u10e1 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0\u10e1 \u10e0\u10dd\u10db\u10da\u10d4\u10d1\u10d8\u10ea \u10d0\u10ee\u10da\u10d0 \u10ee\u10d0\u10d6\u10d6\u10d4\u10d0. MainWindow.dht.status.disabled=\u10d2\u10d0\u10db\u10dd\u10e0\u10d7\u10e3\u10da\u10d8\u10d0 MainWindow.dht.status.failed=\u10e9\u10d0\u10e8\u10da\u10d8\u10da\u10d8\u10d0 MainWindow.dht.status.initializing=\u10d8\u10dc\u10d8\u10ea\u10d8\u10d0\u10da\u10d8\u10d6\u10d0\u10ea\u10d8\u10d0 MainWindow.dht.status.users=%1 \u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d4\u10d1\u10d8 MyTorrentsView.menu.setDownSpeed=\u10db\u10d8\u10e3\u10d7\u10d8\u10d7\u10d4 \u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 ConfigView.section.logging.loggerenable=\u10e9\u10d0\u10e0\u10d7\u10d4 \u10df\u10e3\u10e0\u10dc\u10d0\u10da\u10d8\u10d6\u10d4\u10d1\u10d0 MyTrackerView.passive=\u10de\u10d0\u10e1\u10d8\u10e3\u10e0\u10d8 TableColumn.header.swarm_average_speed=\u10e1\u10d0\u10e8\u10e3\u10d0\u10da\u10dd \u10e1\u10e5\u10d4\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 MyTrackerView.category=\u10d9\u10d0\u10e2\u10d4\u10d2\u10dd\u10e0\u10d8\u10d0 VivaldiView.title.full=\u10d5\u10d8\u10d5\u10d0\u10da\u10d3\u10d8 MyTrackerView.date_added=\u10d3\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 ConfigView.label.playfilespeech=\u10d8\u10e1\u10d0\u10e3\u10d1\u10e0\u10d4 \u10e0\u10dd\u10ea\u10d0 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d3\u10d4\u10d1\u10d0 \u10e4\u10d0\u10d8\u10da\u10d8 ConfigView.label.playfilespeech.info=\u10e1\u10d0\u10e3\u10d1\u10e0\u10d8\u10e1 \u10e1\u10d4\u10e0\u10d5\u10d8\u10e1\u10d4\u10d1\u10d8 \u10db\u10e3\u10e8\u10d0\u10dd\u10d1\u10e1 \u10d9\u10d0\u10e0\u10d2\u10d0\u10d3 \u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10d8\u10dc\u10d2\u10da\u10d8\u10e1\u10e3\u10e0\u10d7\u10d0\u10dc ConfigView.label.playfilefinished=\u10d3\u10d0\u10e3\u10d9\u10d0\u10e0\u10d8 \u10ee\u10db\u10dd\u10d5\u10d0\u10dc\u10d8 \u10e8\u10d4\u10e2\u10e7\u10dd\u10d1\u10d8\u10dc\u10d4\u10d1\u10d0 \u10e0\u10dd\u10ea\u10d0 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d3\u10d4\u10d1\u10d0 ConfigView.label.backupconfigfiles=\u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10d8\u10e1 \u10e8\u10d4\u10db\u10ea\u10d5\u10d4\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8\u10e1 \u10e0\u10d4\u10d6\u10d4\u10e0\u10d5\u10d8\u10e0\u10d4\u10d1\u10d0 \u10d0\u10e6\u10d2\u10d4\u10dc\u10d8\u10e1 \u10e8\u10d4\u10db\u10d3\u10d2\u10dd\u10db\u10d8 \u10d0\u10e6\u10d3\u10d2\u10d4\u10dc\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 ActivityView.legend.limit=\u10e0\u10d4\u10d8\u10e2\u10d8\u10dc\u10d2\u10d8\u10e1 \u10da\u10d8\u10db\u10d8\u10e2\u10d8 ActivityView.legend.achieved=\u10e0\u10d4\u10d8\u10e2\u10d8\u10dc\u10d2\u10d8 \u10db\u10d8\u10e6\u10d4\u10d1\u10e3\u10da\u10d8\u10d0 ActivityView.legend.peeraverage=\u10e1\u10d0\u10e8\u10e3\u10d0\u10da\u10dd ActivityView.legend.swarmaverage=\u10e1\u10d0\u10e8\u10e3\u10d0\u10da\u10dd \u10e1\u10e5\u10d4\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 ActivityView.legend.trimmed=\u10db\u10dd\u10ed\u10e0\u10d8\u10da\u10d8 (dotted) MyTorrentsView.menu.movetorrent=\u10d2\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10d4 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d8... ConfigView.label.queue.maxactivetorrentswhenseeding=\u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10e3\u10db\u10d8 \u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10d7\u10d4\u10e1\u10d5\u10d8\u10e1\u10d0\u10e1 [0:\u10e8\u10d4\u10e3\u10d6\u10e6\u10e3\u10d3\u10d0\u10d5\u10d0\u10d3] Views.plugins.IRC.title=IRC - \u10dd\u10dc\u10da\u10d0\u10d8\u10dc \u10e2\u10d4\u10d0\u10dc\u10d8\u10d9\u10e3\u10e0\u10d8 \u10db\u10dd\u10db\u10e1\u10d0\u10ee\u10e3\u10e0\u10d4\u10dd\u10d1\u10d0 ConfigView.section.ipfilter.persistblocking=\u10d3\u10d0\u10d1\u10da\u10dd\u10d9\u10d8\u10da\u10d8 IP \u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8\u10e1 \u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d0 \u10d2\u10d0\u10d3\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d4\u10d1\u10d8\u10e1\u10d0\u10e1 FilesView.menu.rename=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8\u10e1 \u10d0\u10dc \u10db\u10d3\u10d4\u10d1\u10d0\u10e0\u10d4\u10dd\u10d1\u10d8\u10e1 \u10e8\u10d4\u10ea\u10d5\u10da\u10d0 FilesView.rename.choose.path=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10d0\u10ee\u10d0\u10da\u10d8 \u10d0\u10dc \u10d0\u10e0\u10e1\u10d4\u10d1\u10e3\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8 FilesView.rename.confirm.delete.title=\u10d3\u10d0\u10d3\u10d0\u10e1\u10e2\u10e3\u10e0\u10d4\u10d7 \u10ec\u10d0\u10e8\u10da\u10d0 FilesView.rename.confirm.delete.text=\u10d3\u10d0\u10d0\u10d3\u10d0\u10e1\u10e2\u10e3\u10e0\u10d4\u10d7 \u10dd\u10e0\u10d8\u10d2\u10d8\u10dc\u10d0\u10da\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8\u10e1 '%1' \u10ec\u10d0\u10e8\u10da\u10d0 ConfigView.section.mode=\u10e0\u10d4\u10df\u10d8\u10db\u10d8 ConfigView.section.mode.title=\u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d8\u10e1 \u10de\u10e0\u10dd\u10e4\u10d4\u10e1\u10d8\u10e3\u10da\u10d8 \u10d3\u10dd\u10dc\u10d4 ConfigView.section.mode.beginner=\u10d3\u10d0\u10db\u10ec\u10e7\u10d4\u10d1\u10d8 ConfigView.section.mode.beginner.wiki.definitions=\u10d1\u10d8\u10e2\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10da\u10d4\u10e5\u10e1\u10d8\u10d9\u10dd\u10dc\u10d8 ConfigView.section.mode.intermediate=\u10e1\u10d0\u10e8\u10e3\u10d0\u10da\u10dd ConfigView.section.mode.advanced=\u10de\u10e0\u10dd\u10e4\u10d4\u10e1\u10d8\u10dd\u10dc\u10d0\u10da\u10d8 ConfigView.section.mode.advanced.wiki.main=Wiki \u10db\u10d7\u10d0\u10d5\u10d0\u10e0\u10d8 \u10d2\u10d5\u10d4\u10e0\u10d3\u10d8 Files.column.storagetype=\u10e1\u10d0\u10ea\u10d0\u10d5\u10d8\u10e1 \u10e2\u10d8\u10de\u10d8 FileItem.storage.linear=\u10ec\u10e0\u10e4\u10d8\u10d5\u10d8 FileItem.storage.compact=\u10d9\u10dd\u10db\u10de\u10d0\u10e5\u10e2\u10e3\u10e0\u10d8 MessageBoxWindow.rememberdecision=\u10d3\u10d0\u10d8\u10ee\u10e1\u10dd\u10db\u10d4 \u10e9\u10d4\u10db\u10d8 \u10d2\u10d0\u10d3\u10d0\u10ec\u10e7\u10d5\u10d4\u10e2\u10d8\u10da\u10d4\u10d1\u10d0 ConfigView.section.interface.cleardecisions=\u10d2\u10d0\u10ec\u10db\u10d8\u10dc\u10d3\u10d4 \u10d3\u10d8\u10d0\u10da\u10dd\u10d2\u10e3\u10e0 \u10e4\u10d0\u10dc\u10ef\u10e0\u10d4\u10d1\u10d6\u10d4 \u10d3\u10d0\u10db\u10d0\u10ee\u10e1\u10dd\u10d5\u10e0\u10d4\u10d1\u10e3\u10da\u10d8 \u10d2\u10d0\u10d3\u10d0\u10ec\u10e7\u10d5\u10d4\u10e2\u10d8\u10d4\u10da\u10d4\u10d1\u10d4\u10d1\u10d8 ConfigView.section.interface.cleardecisionsbutton=\u10d2\u10d0\u10ec\u10db\u10d4\u10dc\u10d3\u10d0 configureWizard.welcome.usermodes=\u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d8\u10e1 \u10d9\u10d5\u10d0\u10da\u10d8\u10e4\u10d8\u10d9\u10d0\u10ea\u10d8\u10d8\u10e1 \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8 \u10d2\u10d0\u10dc\u10e1\u10d0\u10d6\u10e6\u10d5\u10e0\u10d0\u10d5\u10e1 \u10dd\u10e4\u10ea\u10d8\u10d4\u10d1\u10d8\u10e1 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0\u10e1 '\u10d8\u10dc\u10e1\u10e2\u10e0\u10e3\u10db\u10d4\u10dc\u10e2\u10d4\u10d1\u10d8 > \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8' \u10db\u10d4\u10dc\u10d8\u10e3\u10e8\u10d8. \u10e7\u10e3\u10e0\u10d0\u10e0\u10d4\u10d1\u10d8\u10d7 \u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4\u10d7 \u10e8\u10d4\u10e1\u10d0\u10d1\u10d0\u10db\u10d8\u10e1\u10d8 \u10d3\u10dd\u10dc\u10d4. FilesView.rename.failed.title=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8\u10e1/\u10db\u10d3\u10d4\u10d1\u10d0\u10e0\u10d4\u10dd\u10d1\u10d8\u10e1 \u10e8\u10d4\u10ea\u10d5\u10da\u10d0 FilesView.rename.failed.text=\u10dd\u10de\u10d4\u10e0\u10d0\u10ea\u10d8\u10d0 \u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0, \u10e8\u10d4\u10e1\u10d0\u10eb\u10da\u10dd\u10d0 \u10d0\u10e0\u10d0\u10e1\u10ec\u10dd\u10e0\u10d0\u10d3 \u10e8\u10d4\u10d8\u10e0\u10e9\u10d0 \u10d2\u10d0\u10dc\u10d7\u10d0\u10d5\u10e1\u10d4\u10d1\u10d8\u10e1 \u10d0\u10d3\u10d2\u10d8\u10da\u10d8 diagnostics.log_found=Vuze did not shutdown tidily. Please check %1 for diagnostic log files and consider reporting them to the Vuze team if this is the result of an application error. ManagerItem.paused=\u10de\u10d0\u10e3\u10d6\u10d0 Utils.link.visit=\u10d2\u10d7\u10ee\u10dd\u10d5\u10d7 \u10dc\u10d0\u10ee\u10dd\u10d7 ConfigView.section.connection.serverport.wiki=\u10de\u10dd\u10e0\u10e2\u10d4\u10d1\u10d8\u10e1 \u10d9\u10d0\u10e0\u10d2\u10d8 \u10d0\u10e0\u10e9\u10d4\u10d5\u10d0\u10dc\u10d8 installPluginsWizard.installMode.info.title=\u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 Views.plugins.Distributed.DB.title=\u10e1\u10d0\u10d3\u10d8\u10e1\u10e2\u10e0\u10d8\u10d1\u10e3\u10ea\u10d8\u10dd \u10db\u10dd\u10dc\u10d0\u10ea\u10d4\u10db\u10d7\u10d0 \u10d1\u10d0\u10d6\u10d0 Views.plugins.Distributed.Tracker.title=\u10e1\u10d0\u10d3\u10d8\u10e1\u10e2\u10e0\u10d8\u10d1\u10e3\u10ea\u10d8\u10dd \u10db\u10db\u10d0\u10e0\u10d7\u10d5\u10d4\u10da\u10d8 Views.plugins.Plugin.Update.title=\u10e9\u10d0\u10e1\u10db\u10e3\u10da\u10d8 \u10db\u10dd\u10d3\u10e3\u10da\u10d8\u10e1 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d4\u10d1\u10d0 Views.plugins.UPnP.title.tooltip=\u10e3\u10dc\u10d8\u10d5\u10d4\u10e0\u10e1\u10d0\u10da\u10e3\u10e0\u10d8 Plug and Play TableColumn.header.swarm_average_completion=\u10de\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d0\u10e8\u10e3\u10d0\u10da\u10dd\u10d3 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d0 TableColumn.header.swarm_average_completion.info=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10de\u10e0\u10dd\u10ea\u10d4\u10dc\u10e2\u10e3\u10da\u10d8 \u10db\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4\u10d1\u10d4\u10da\u10d8 \u10de\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10e5\u10d4\u10db\u10d0\u10e8\u10d8 GeneralView.label.swarm_average_completion=\u10e1\u10d0\u10e8\u10e3\u10d0\u10da\u10dd\u10d3 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8: GeneralView.label.swarm_average_completion.tooltip=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10de\u10e0\u10dd\u10ea\u10d4\u10dc\u10e2\u10e3\u10da\u10d8 \u10db\u10d0\u10e9\u10d5\u10d4\u10dc\u10d4\u10d1\u10d4\u10da\u10d8 \u10de\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10e5\u10d4\u10db\u10d0\u10e8\u10d8 ConfigView.section.logging.log0type=\u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d0 ConfigView.section.logging.log1type=\u10d2\u10d0\u10e4\u10e0\u10d7\u10ee\u10d8\u10da\u10d4\u10d1\u10d0 ConfigView.section.logging.log2type=\u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 ConfigView.section.logging.filter=\u10d2\u10d0\u10e4\u10d8\u10da\u10e2\u10e0\u10d4 \u10d7\u10e3 \u10df\u10e3\u10e0\u10dc\u10d0\u10da\u10d8 \u10d8\u10dc\u10d0\u10ee\u10d4\u10d1\u10d0 \u10e4\u10d0\u10d8\u10da\u10e8\u10d8 ConfigView.section.logging.level=\u10df\u10e3\u10e0\u10dc\u10d0\u10da\u10d8\u10e1 \u10d3\u10dd\u10dc\u10d4 ConfigView.pluginlist.column.loadAtStartup=\u10e9\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0@\u10d2\u10d0\u10e8\u10d5\u10d4\u10d1\u10d0 ConfigView.pluginlist.column.type=\u10e2\u10d8\u10de\u10d8 ConfigView.pluginlist.column.type.perUser=\u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10d4\u10da\u10d6\u10d4 ConfigView.pluginlist.column.type.shared=\u10d6\u10d8\u10d0\u10e0\u10d8 ConfigView.pluginlist.column.type.builtIn=\u10e9\u10d0\u10db\u10dd\u10dc\u10e2\u10d0\u10df\u10d4\u10d1\u10e3\u10da\u10d8 ConfigView.pluginlist.column.name=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8 ConfigView.pluginlist.column.version=\u10d5\u10d4\u10e0\u10e1\u10d8\u10d0 ConfigView.pluginlist.column.directory=\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 ConfigView.pluginlist.column.isOperational=\u10e1\u10d0\u10dd\u10de\u10d4\u10e0\u10d0\u10ea\u10d8\u10dd? PeersView.BlockView.Avail.Have=\u10dd\u10e0\u10d8\u10d5\u10d4\u10e1 \u10d0\u10e5\u10d5\u10e1 PeersView.BlockView.Avail.NoHave=\u10de\u10d8\u10e0\u10e1 \u10d0\u10e5\u10d5\u10e1; \u10e8\u10d4\u10dc \u10d0\u10e0\u10d0 PeersView.BlockView.NoAvail.Have=\u10e8\u10d4\u10dc \u10d2\u10d0\u10e5\u10d5\u10e1; \u10de\u10d8\u10e0\u10e1 \u10d0\u10e0\u10d0 PeersView.BlockView.NoAvail.NoHave=\u10d0\u10e0\u10ea \u10d4\u10e0\u10d7\u10e1 \u10d0\u10e0\u10d0 \u10d0\u10e5\u10d5\u10e1 PeersView.BlockView.Transfer=\u10e2\u10e0\u10d0\u10dc\u10e1\u10e4\u10d4\u10e0\u10d8 PeersView.BlockView.NextRequest=\u10e8\u10d4\u10db\u10d3\u10d4\u10d2\u10d8 \u10db\u10dd\u10d7\u10ee\u10dd\u10d5\u10dc\u10d0 PeersView.BlockView.title=\u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8\u10e1 \u10e0\u10e3\u10e5\u10d0 PeersView.BlockView.AvailCount=\u10ee\u10d4\u10da\u10db\u10d8\u10e1\u10d0\u10ec\u10d5\u10d3\u10dd\u10db\u10d8 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.download=\u10e9\u10d0\u10db\u10dd\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 OpenTorrentWindow.torrentLocation=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2 \u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8: OpenTorrentWindow.addFiles.URL=\u10d3\u10d0\u10d0\u10db\u10d0\u10e2\u10d0 &URL OpenTorrentWindow.addFiles.Folder=\u10d3\u10d0\u10d0\u10db\u10d0\u10e2\u10d4 &\u10d9\u10d0\u10e2\u10d0\u10da\u10dd\u10d2\u10d8 OpenTorrentWindow.addFiles.Clipboard=\u10d3\u10d0\u10d0\u10db\u10d0\u10e2\u10d4 &\u10d1\u10e3\u10e4\u10d4\u10e0\u10d8\u10d3\u10d0\u10dc OpenTorrentWindow.changeDestination=\u10e8\u10d4\u10ea\u10d5\u10d0\u10da\u10d4 \u10d3\u10d0\u10dc\u10d8\u10e8\u10dc\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10d0\u10d3\u10d2\u10d8\u10da\u10d8 OpenTorrentWindow.fileList=\u10e4\u10d0\u10d8\u10da\u10d4\u10d1\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10e8\u10d8: OpenTorrentWindow.torrentTable.name=\u10e1\u10d0\u10ee\u10d4\u10da\u10d8 OpenTorrentWindow.fileTable.fileName=\u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10e1\u10d0\u10ee\u10d4\u10da\u10d8 OpenTorrentWindow.fileTable.size=\u10d6\u10dd\u10db\u10d0 OpenTorrentWindow.startMode.seeding=\u10d7\u10d4\u10e1\u10d5\u10d0 OpenTorrentWindow.fileList.changeDestination=\u10e8\u10d4\u10ea\u10d5\u10d0\u10da\u10d4 \u10d3\u10d0\u10dc\u10d8\u10e8\u10dc\u10e3\u10da\u10d4\u10d1\u10d8\u10e1 \u10d0\u10d3\u10d2\u10d8\u10da\u10d8 OpenTorrentWindow.mb.badSize.title=\u10d0\u10e0\u10d0\u10d7\u10d0\u10d5\u10e1\u10d4\u10d1\u10d0\u10d3\u10d8 \u10e4\u10d0\u10d8\u10da\u10d8 OpenTorrentWindow.mb.openError.title=\u10e8\u10d4\u10ea\u10d3\u10dd\u10db\u10d0 \u10d2\u10d0\u10ee\u10e1\u10dc\u10d8\u10e1\u10d0\u10e1 OpenTorrentWindow.mb.openError.text='%1' could not be opened: OpenTorrentWindow.torrent.remove=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10e1\u10d8\u10d8\u10d3\u10d0\u10dc \u10d0\u10db\u10dd\u10d2\u10d3\u10d4\u10d1\u10d0 iconBar.open.tooltip=\u10d2\u10d0\u10ee\u10e1\u10d4\u10dc\u10d8 \u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8(\u10d4\u10d1\u10d8) LocaleUtil.column.text=\u10e3\u10ea\u10dc\u10dd\u10d1\u10d8 \u10e2\u10d4\u10e5\u10e1\u10e2\u10d8 ConfigView.label.lazybitfield=\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4 \u10d6\u10d0\u10e0\u10db\u10d0\u10ea\u10d8 \u10d1\u10d8\u10e2\u10e4\u10d8\u10da\u10d3\u10d8 (\u10d4\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10d0 \u10d7\u10d4\u10e1\u10d5\u10d0\u10e1 \u10d1\u10d8\u10e2\u10e4\u10d8\u10da\u10d3\u10d6\u10d4 \u10d1\u10d0\u10d6\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8 \u10d1\u10da\u10dd\u10d9\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1\u10d0\u10e1) Button.moveUp=\u10d2\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10d4 \u10d6\u10d4\u10d5\u10d8\u10d7 Button.moveDown=\u10d2\u10d0\u10d3\u10d0\u10d8\u10e2\u10d0\u10dc\u10d4 \u10e5\u10d5\u10d4\u10d5\u10d8\u10d7 PeersView.piece=\u10dc\u10d0\u10ed\u10d4\u10e0\u10d8 PiecesView.priority=\u10de\u10e0\u10d8\u10dd\u10e0\u10d8\u10e2\u10d4\u10e2\u10d8 PiecesView.speed=\u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 Plugin.extseed.name=\u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 \u10db\u10d7\u10d4\u10e1\u10d5\u10d4\u10da\u10d4\u10d1\u10d8 Plugin.localtracker.name=\u10de\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1 \u10eb\u10d8\u10d4\u10d1\u10d0 \u10da\u10dd\u10d9\u10d0\u10da\u10e3\u10e0 \u10e5\u10e1\u10d4\u10da\u10e8\u10d8 Plugin.localtracker.enable=\u10de\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1 \u10eb\u10d8\u10d4\u10d1\u10d0 \u10da\u10dd\u10d9\u10d0\u10da\u10e3\u10e0 \u10e5\u10e1\u10d4\u10da\u10e8\u10d8 azinstancehandler.alert.portclash=\u10d3\u10d0\u10e4\u10d8\u10e5\u10e1\u10d8\u10e0\u10d3\u10d0 \u10de\u10dd\u10e0\u10e2\u10d4\u10d1\u10d8\u10e1 \u10e8\u10d4\u10ef\u10d0\u10ee\u10d4\u10d1\u10d0 LAN: %1 \u10e3\u10d9\u10d5\u10d4 \u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4\u10d1\u10d0 \u10e1\u10ee\u10d5\u10d0 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8\u10e1 \u10db\u10dd\u10db\u10ee\u10db\u10d0\u10e0\u10d4\u10d1\u10da\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1, \u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10d0\u10ee\u10d0\u10da\u10d8 \u10dc\u10d4\u10d1\u10e1\u10d8\u10db\u10d8\u10d4\u10e0\u10d8 \u10de\u10dd\u10e0\u10e2\u10d8(s) \u10e8\u10d4\u10db\u10dd\u10db\u10d0\u10d5\u10d0\u10da\u10d8 TCP / UDP \u10db\u10dd\u10e1\u10d0\u10e1\u10db\u10d4\u10dc\u10d0\u10d3 [%2\u2013\u10e1\u10d0 \u10d3\u10d0 %3 \u10e8\u10dd\u10e0\u10d8\u10e1]. ConfigView.section.transfer.lan=\u10da\u10dd\u10d9\u10d0\u10da\u10e3\u10e0\u10d8 \u10e5\u10e1\u10d4\u10da\u10d8 ConfigView.section.transfer.lan.tooltip=\u10da\u10dd\u10d9\u10d0\u10da\u10e3\u10e0 \u10e5\u10e1\u10d4\u10da\u10d7\u10d0\u10dc \u10d3\u10d0\u10d9\u10d0\u10d5\u10e8\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8 \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8 ConfigView.section.transfer.lan.uploadrate=\u10d9\u10d8\u10da\u10dd\u10d1\u10d0\u10d8\u10e2\u10d8/\u10ec\u10db. \u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 \u10da\u10dd\u10d9\u10d0\u10da\u10e3\u10e0 \u10e5\u10e1\u10d4\u10da\u10e8\u10d8 [0: \u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4] ConfigView.section.transfer.lan.downloadrate=\u10d9\u10d8\u10da\u10dd\u10d1\u10d0\u10d8\u10e2\u10d8/\u10ec\u10db. \u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 \u10da\u10dd\u10d9\u10d0\u10da\u10e3\u10e0 \u10e5\u10e1\u10d4\u10da\u10e8\u10d8 [0: \u10da\u10d8\u10db\u10d8\u10e2\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4] TorrentOptionsView.title.short=\u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8 TorrentOptionsView.title.full=\u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8 TorrentOptionsView.param.max.peers=\u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d4\u10d1\u10d8\u10e1 \u10db\u10d0\u10e5\u10e1\u10d8\u10d0\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 [0: unlimited] ConfigView.section.connection.encryption.require_encrypted_transport=\u10db\u10dd\u10d8\u10d7\u10ee\u10dd\u10d5\u10d4 \u10d3\u10d0\u10e8\u10d8\u10e4\u10e0\u10e3\u10da\u10d8 \u10e2\u10e0\u10d0\u10dc\u10e1\u10de\u10dd\u10e0\u10e2\u10d8 ConfigView.section.connection.encryption.min_encryption_level=\u10d3\u10d0\u10ed\u10d8\u10e4\u10e0\u10d5\u10d8\u10e1 \u10db\u10d8\u10dc\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10d3\u10dd\u10dc\u10d4 Peers.column.Encryption=\u10d3\u10d0\u10e8\u10d8\u10e4\u10e0\u10d5\u10d0 Peers.column.Encryption.info=\u10d2\u10d0\u10db\u10dd\u10e7\u10d4\u10dc\u10d4\u10d1\u10d0\u10d3\u10d8 \u10d3\u10d0\u10e8\u10d8\u10e4\u10e0\u10d5\u10d8\u10e1 \u10d3\u10dd\u10dc\u10d4 ConfigView.section.connection.encryption.encrypt.info.link=\u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8\u10e1\u10d7\u10d5\u10d8\u10e1 \u10d8\u10ee\u10d8\u10da\u10d4\u10d7 ConfigView.section.style.status=\u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8\u10e1 \u10d0\u10e0\u10d4: ConfigView.section.style.status.show_sr=\u10d6\u10d8\u10d0\u10e0\u10d8 \u10e0\u10d4\u10d8\u10e2\u10d8\u10dc\u10d2\u10d8 ConfigView.section.style.status.show_nat=NAT \u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8 ConfigView.section.style.status.show_ddb=DDB \u10e1\u10e2\u10d0\u10e2\u10e3\u10e1\u10d8 ConfigView.section.connection.encryption.encrypt.fallback_incoming=\u10dc\u10d4\u10d1\u10d0 \u10d3\u10d0\u10e0\u10d7\u10d4 \u10d3\u10d0\u10e3\u10e8\u10d8\u10e4\u10e0\u10d0\u10d5\u10d8 \u10e8\u10d4\u10db\u10dd\u10db\u10d0\u10d5\u10d0\u10da\u10d8 \u10e8\u10d4\u10d4\u10e0\u10d7\u10d4\u10d1\u10d4\u10d1\u10d8 ConfigView.section.connection.encryption=\u10e2\u10e0\u10d0\u10dc\u10e1\u10de\u10dd\u10e0\u10e2\u10d8\u10e1 \u10d3\u10d0\u10e8\u10d8\u10e4\u10e0\u10d5\u10d0 ConfigView.section.style.defaultSortOrder=\u10e1\u10dd\u10e0\u10e2\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1 \u10e1\u10e2\u10d0\u10dc\u10d3\u10d0\u10e0\u10e2\u10e3\u10da\u10d8 \u10db\u10d8\u10db\u10d0\u10e0\u10d7\u10e3\u10da\u10d4\u10d1\u10d0 ConfigView.section.style.defaultSortOrder.desc=\u10d9\u10da\u10d4\u10d1\u10d0\u10d3\u10dd\u10d1\u10d8\u10e1 \u10db\u10d8\u10ee\u10d4\u10d3\u10d5\u10d8\u10d7 ConfigView.section.style.defaultSortOrder.asc=\u10d6\u10e0\u10d3\u10d0\u10d3\u10dd\u10d1\u10d8\u10e1 \u10db\u10d8\u10ee\u10d4\u10d3\u10d5\u10d8\u10d7 Button.selectAll=\u10db\u10dd\u10dc\u10d8\u10e8\u10dc\u10d4 \u10e7\u10d5\u10d4\u10da\u10d0 Button.markSelected=\u10db\u10dd\u10dc\u10d8\u10e8\u10dc\u10d4 \u10e8\u10d4\u10e0\u10e9\u10d4\u10e3\u10da\u10d8 Button.unmarkSelected=\u10d2\u10d0\u10d0\u10e3\u10e5\u10db\u10d4 \u10db\u10dd\u10dc\u10d8\u10e8\u10dc\u10d5\u10d0 plugins.basicview.config=\u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10d0 TorrentOptionsView.param.max.uploads=\u10d0\u10e1\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d8 \u10e1\u10da\u10dd\u10e2\u10d4\u10d1\u10d8\u10e1 \u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10e0\u10d0\u10dd\u10d3\u10d4\u10dc\u10dd\u10d1\u10d0 [minimum: 2] ConfigView.section.connection.advanced.info.link=\u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8\u10e1\u10d7\u10d5\u10d8\u10e1 \u10d8\u10ee\u10d8\u10da\u10d4\u10d7 ConfigView.section.connection.advanced.socket.group=\u10e1\u10dd\u10d9\u10d4\u10e2\u10d8\u10e1 \u10de\u10d0\u10e0\u10d0\u10db\u10d4\u10e2\u10e0\u10d4\u10d1\u10d8 ConfigView.section.connection.advanced.bind_port=\u10db\u10d8\u10d0\u10d1\u10d8 \u10da\u10dd\u10d9\u10d0\u10da\u10e3\u10e0 \u10de\u10dd\u10e0\u10e2\u10e1 [0: \u10d2\u10d0\u10db\u10dd\u10e0\u10d7\u10e3\u10da\u10d8\u10d0] ConfigView.section.proxy.group.tracker=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10d9\u10dd\u10db\u10e3\u10dc\u10d8\u10d9\u10d0\u10ea\u10d8\u10d4\u10d1\u10d8 ConfigView.section.proxy.group.peer=\u10de\u10d8\u10e0\u10d7\u10d0 \u10d9\u10dd\u10db\u10e3\u10dc\u10d8\u10d9\u10d0\u10ea\u10d8\u10d4\u10d1\u10d8 Pieces.column.Requested=\u10db\u10dd\u10d7\u10ee\u10dd\u10d5\u10dc\u10d8\u10da\u10d8\u10d0 MyTorrentsView.filter=Filter: [%1] MyTorrentsView.dialog.setFilter.title=\u10e4\u10d8\u10da\u10e2\u10e0\u10d8\u10e1 \u10e8\u10d4\u10ea\u10d5\u10da\u10d0 MyTorrentsView.clearFilter.tooltip=\u10e4\u10d8\u10da\u10e2\u10e0\u10d8\u10e1 \u10d2\u10d0\u10e1\u10e3\u10e4\u10d7\u10d0\u10d5\u10d4\u10d1\u10d0 ConfigureWizard.language.choose=\u10e8\u10d4\u10d0\u10e0\u10e9\u10d8\u10d4 \u10d4\u10dc\u10d0 \u10e5\u10d5\u10d4\u10db\u10dd\u10d7 \u10db\u10dd\u10ea\u10d4\u10db\u10e3\u10da\u10d8 \u10e1\u10d8\u10d8\u10d3\u10d0\u10dc: popup.closing.in=\u10e4\u10d0\u10dc\u10ef\u10e0\u10d8\u10e1 \u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 \u10d3\u10d0\u10ee\u10e3\u10e0\u10d5\u10d0 %1 \u10ec\u10d0\u10db\u10e8\u10d8 # > 2402 ConfigView.auto=\u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 Plugin.localtracker.autoadd.info=\u10d0\u10db \u10da\u10dd\u10d9\u10d0\u10da\u10e3\u10e0\u10d8 \u10de\u10d8\u10e0\u10d4\u10d1\u10d8\u10e1 \u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 \u10d3\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10d0 [';' \u10d2\u10d0\u10db\u10dd\u10e7\u10dd\u10e4\u10d8\u10da\u10d8 \u10db\u10d8\u10e1\u10d0\u10db\u10d0\u10e0\u10d7\u10d4\u10d1\u10d8, \u10db\u10d0\u10d2. 1.2.3.4] Plugin.localtracker.networks=\u10da\u10dd\u10d9\u10d0\u10da\u10e3\u10e0\u10d8 \u10e5\u10e1\u10d4\u10da\u10d4\u10d1\u10d8 SpeedView.stats.autospeed=\u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d8 \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 SpeedView.stats.currentPing=\u10db\u10d8\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4 \u10de\u10d8\u10dc\u10d2\u10d8: ConfigView.section.transfer.autospeed=\u10d0\u10d5\u10e2\u10dd\u10db\u10d0\u10e2\u10e3\u10e0\u10d8\u2013\u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 DHTTransport.report.sending=\u10db\u10dd\u10dc\u10d0\u10ea\u10d4\u10db\u10d4\u10d1\u10d8\u10e1 \u10d2\u10d0\u10d2\u10d6\u10d0\u10d5\u10dc\u10d0 DHTTransport.report.send_complete=\u10d2\u10d0\u10d2\u10d6\u10d0\u10d5\u10dc\u10d0 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d3\u10d0 TableColumn.header.date_added=\u10d3\u10d0\u10db\u10d0\u10e2\u10d4\u10d1\u10d8\u10e1 \u10d7\u10d0\u10e0\u10d8\u10e6\u10d8 platform.win32.baddll.niphk=Norman \u10d0\u10dc\u10e2\u10d8\u2013\u10d5\u10d8\u10e0\u10e3\u10e1\u10d8 platform.win32.baddll.nvappfilter=NVidia \u10e5\u10e1\u10d4\u10da\u10e3\u10e0\u10d8 \u10d4\u10d9\u10e0\u10d0\u10dc\u10d8 upnp.ignorebaddevices.info=\u10d0\u10db\u10df\u10d0\u10db\u10d0\u10d3 \u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8 \u10db\u10dd\u10ec\u10e7\u10dd\u10d1\u10d8\u10da\u10dd\u10d1\u10d4\u10d1\u10d8: %1 upnp.ignorebaddevices.reset=\u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8 \u10db\u10dd\u10ec\u10e7\u10dd\u10d1\u10d8\u10da\u10dd\u10d1\u10d4\u10d1\u10d8\u10e1 \u10e1\u10d8\u10d8\u10e1 \u10d2\u10d0\u10dc\u10e3\u10da\u10d4\u10d1\u10d0 upnp.ignorebaddevices.reset.action=\u10d2\u10d0\u10dc\u10e3\u10da\u10d4\u10d1\u10d0 UpdateMonitor.messagebox.verification.failed.title=\u10e9\u10d0\u10d8\u10e8\u10d0\u10da\u10d0 \u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10e1 \u10d5\u10d4\u10e0\u10d8\u10e4\u10d8\u10d9\u10d0\u10ea\u10d8\u10d0 UpdateMonitor.messagebox.accept.unverified.title=\u10db\u10d8\u10d5\u10d8\u10e6\u10dd\u10d7 \u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d0\u10ea\u10d8\u10d0 \u10d5\u10d4\u10e0\u10d8\u10e4\u10d8\u10d9\u10d0\u10ea\u10d8\u10d8\u10e1 \u10d2\u10d0\u10e0\u10d4\u10e8\u10d4 FileView.BlockView.title=\u10e4\u10d0\u10d8\u10da\u10d8\u10e1 \u10dc\u10d0\u10ed\u10e0\u10d4\u10d1\u10d8 FileView.BlockView.Done=\u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d8 FileView.BlockView.Skipped=\u10d2\u10d0\u10db\u10dd\u10e2\u10dd\u10d5\u10d4\u10d1\u10e3\u10da\u10d8 FileView.BlockView.Active=\u10d0\u10e5\u10e2\u10d8\u10e3\u10e0\u10d8 MainWindow.menu.help.debug=\u10d3\u10d0\u10d1\u10d0\u10d2 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d8\u10e1 \u10d2\u10d4\u10dc\u10d4\u10e0\u10d0\u10ea\u10d8\u10d0 ConfigView.filter=\u10d0\u10d9\u10e0\u10d8\u10e4\u10d4 \u10d2\u10d0\u10e1\u10d0\u10e4\u10d8\u10da\u10e2\u10e0\u10d8 \u10e2\u10d4\u10e5\u10e1\u10e2\u10d8 upnp.mapping.dhtudp=\u10d3\u10d8\u10e1\u10e2\u10e0\u10d8\u10d1\u10e3\u10ea\u10d8\u10e3\u10da\u10d8 \u10db\u10dd\u10dc\u10d0\u10ea\u10d4\u10db\u10d7\u10d0 \u10d1\u10d0\u10d6\u10d0 ConfigView.section.style.showiconbar=\u10de\u10d0\u10dc\u10d4\u10da\u10d8\u10e1 \u10e9\u10d5\u10d4\u10dc\u10d4\u10d1\u10d0 MainWindow.menu.view.iconbar=\u10de\u10d0\u10dc\u10d4\u10da\u10d8 swt.alert.cant.update="%3"\u2013\u10d3\u10d0\u10dc \u10e9\u10d0\u10db\u10dd\u10d8\u10e2\u10d5\u10d8\u10e0\u10d7\u10e3\u10da\u10d8 SWT \u10d1\u10d8\u10d1\u10da\u10d8\u10dd\u10d7\u10d4\u10d9\u10d0 \u10d5\u10d4\u10e0 \u10d2\u10d0\u10dc\u10d0\u10ee\u10da\u10d3\u10d4\u10d1\u10d0 %1 \u10d5\u10d4\u10e0\u10e1\u10d8\u10d8\u10d3\u10d0\u10dc %2\u2013\u10db\u10d3\u10d4 (\u10e3\u10dc\u10d3\u10d0 \u10e9\u10d0\u10db\u10dd\u10d8\u10e2\u10d5\u10d8\u10e0\u10d7\u10dd\u10e1 "%4"\u2013\u10d3\u10d0\u10dc). \u10d8\u10ee\u10d8\u10da\u10d4\u10d7 \u10d5\u10d8\u10d9\u10d8 \u10d3\u10d4\u10e2\u10d0\u10da\u10e3\u10e0\u10d8 \u10d8\u10dc\u10e4\u10dd\u10e0\u10db\u10d0\u10ea\u10d8\u10d8\u10e1\u10d0\u10d7\u10d5\u10d8\u10e1. authenticator.savepassword=\u10de\u10d0\u10e0\u10dd\u10da\u10d8\u10e1 \u10e8\u10d4\u10dc\u10d0\u10ee\u10d5\u10d0 Content.alert.notuploaded.title=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0 \u10d0\u10e0 \u10d3\u10d0\u10e1\u10e0\u10e3\u10da\u10d4\u10d1\u10e3\u10da\u10d0 Content.alert.notuploaded.quit=\u10d3\u10d0\u10ee\u10e3\u10e0\u10d4 \u10d0\u10d6\u10e3\u10e0\u10d4\u10e3\u10e1\u10d8 TorrentInfoView.torrent.encoding=\u10e2\u10dd\u10e0\u10d4\u10dc\u10e2\u10d8\u10e1 \u10d9\u10dd\u10d3\u10d8\u10e0\u10d4\u10d1\u10d0 progress.window.title=\u10db\u10d8\u10db\u10d3\u10d8\u10dc\u10d0\u10e0\u10d4\u10dd\u10d1\u10e1 \u10dd\u10de\u10d4\u10e0\u10d0\u10ea\u10d8\u10d0 ConfigView.label.please.visit.here=\u10d3\u10d4\u10e2\u10d0\u10da\u10d4\u10d1\u10d8\u10e1\u10d7\u10d5\u10d8\u10e1 \u10d8\u10ee\u10d8\u10da\u10d4\u10d7 # Used for peers which we can't determine. PeerSocket.unknown=\u10e3\u10ea\u10dc\u10dd\u10d1\u10d8 ConfigView.label.announceport=\u10db\u10d4\u10d7\u10d5\u10d0\u10da\u10e7\u10e3\u10e0\u10d8\u10e1 \u10d0\u10dc\u10dd\u10dc\u10e1\u10d8\u10e0\u10d4\u10d1\u10d0\u10d3\u10d8 \u10de\u10dd\u10e0\u10e2\u10d8\u10e1 \u10d8\u10d2\u10dc\u10dd\u10e0\u10d8\u10e0\u10d4\u10d1\u10d0 iconBar.queue.tooltip=\u10db\u10dd\u10da\u10dd\u10d3\u10d8\u10dc\u10d8\u10e1 \u10e1\u10d8\u10d0 MainWindow.menu.help.faq=\u10d5\u10d8\u10d9\u10d8 \u10ee.\u10d3.\u10d9. MainWindow.menu.help.donate=\u10d2\u10d0\u10d0\u10d9\u10d4\u10d7\u10d4 \u10e4\u10e3\u10da\u10d0\u10d3\u10d8 \u10e8\u10d4\u10db\u10dd\u10ec\u10d8\u10e0\u10e3\u10da\u10dd\u10d1\u10d0 !!! azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_li_NL.properties0000644000175000017500000051243511301156004026076 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torrent-besjtandj... Main.parameter.usage="Gebroek: java org.gudy.azureus2.cl.Main [parameters] "besjtandj.torrent" "Bewaarpaad" Main.parameter.maxUploads=Max. aantal geliektiedige uploads Main.parameter.maxSpeed=Max. uploadsjnelheid in bytes/sek MainWindow.menu.file=&Besjtandj MainWindow.menu.file.open=\u00c4\u00f6&pene MainWindow.menu.file.create=&Nuuj torrentbesjtandj make... MainWindow.menu.file.create.fromfile=Van een &besjtandj MainWindow.menu.file.create.fromdir=Van een &map MainWindow.menu.file.export=XML-torrent &exportere... MainWindow.menu.file.import=XML-torrent &importere... MainWindow.menu.file.closetab=&Tab sjloete MainWindow.menu.file.closewindow=&V\u00e8nster sjloete MainWindow.menu.file.exit=&Aafsjloete MainWindow.dialog.choose.file=Kees 't torrentbesjtandj MainWindow.menu.file.folder=&Map... MainWindow.dialog.choose.folder=Kees de map wo de torrents zich bev\u00e8nje MainWindow.menu.view=&Weergaaf MainWindow.menu.view.show=Laote zeen MainWindow.menu.view.mytorrents=&Mien torrents MainWindow.menu.view.open_global_transfer_bar=Euverdrachtebalk MainWindow.menu.view.configuration=&K\u00f3ngfiggerasie... MainWindow.menu.view.allpeers=Alle peers MainWindow.menu.closealldetails=Sjloet &alle details MainWindow.menu.closealldownloadbars=Sjloet alle download&belk MainWindow.menu.language=Taa&l ConfigView.section.language=Taal MainWindow.menu.window=&Sjirm MainWindow.menu.window.minimize=&Minimalisere MainWindow.menu.window.zoom=In&zoeme MainWindow.menu.window.alltofront=Alles nao &veure bringe MainWindow.menu.help=&Help MainWindow.menu.help.about=Euver Vuze MainWindow.menu.torrent=T&orrentbesjturing MainWindow.about.title=Euver Vuze MainWindow.about.section.developers=\u00d3ntwikkeliers MainWindow.about.section.translators=Vertalers MainWindow.about.section.system=Systeem MainWindow.about.section.internet=Internet MainWindow.about.internet.sourceforge=Sourceforge Projectpagina MainWindow.about.internet.sourceforgedownloads=Sourceforge Downloads. MainWindow.about.internet.bugreports=Foutreporte MainWindow.about.internet.wiki=Vuze Wiki FAQ. MainWindow.dialog.choose.savepath=Kees 't paad veur opsjlaag MainWindow.dialog.choose.savepath_forallfiles=Kees 't paad veur opsjlaag van ALLE besjtenj MainWindow.status.latestversion=L\u00e8ste versie MainWindow.status.latestversion.clickupdate=Klik \u00f3m bie te wirke MainWindow.status.unknown=\u00f3nbek\u00e8nd MainWindow.status.checking=k\u00f3nterlere TableColumn.header.name=Naam TableColumn.header.size=Gruutde TableColumn.header.done=Vaerdig TableColumn.header.done.info=Percentage gedaon van hujige taak TableColumn.header.status=Sjtatus TableColumn.header.status.info=Waat de torrent duit TableColumn.header.seeds=Seeders TableColumn.header.seeds.info=Aantal seeders womit se b\u00f6s verb\u00f3nje (aantal seeders totaal) TableColumn.header.peers=Leechers TableColumn.header.peers.info=Aantal leechers womit se verb\u00f3nje b\u00f6s (aantal leechers totaal) TableColumn.header.completed=Vaerdig TableColumn.header.completed.info=# van peers die vaerdig zeen mit downlaode wie gerapperteerd door de tracker TableColumn.header.downspeed=Downloadsjnelheid TableColumn.header.upspeed=Uploadsjnelheid TableColumn.header.tracker=Tracker TableColumn.header.tracker.info=Sjtatus van de tracker TableColumn.header.trackernextaccess=Tracker-update TableColumn.header.trackernextaccess.info=Wen de volgende trackerverb\u00e8njing plaats z\u00f3l v\u00e8nje TableColumn.header.priority=Prioriteit TableColumn.header.priority.info=Bepaolt wiev\u00e4\u00f6l uploadbandjbreide aan torrents weurt gegaeve TableColumn.header.seeds.fullcopycalc=%2 ganse kopie\u00eb besjt\u00f6mp veur %1 peers MyTorrentsView.menu.showdetails=&Details bekieke MyTorrentsView.menu.showdownloadbar=Download&balk laote zeen MyTorrentsView.menu.open=Besjtandj \u00c4\u00f6&pene MyTorrentsView.menu.setpriority=&Prioriteit verangere MyTorrentsView.menu.setpriority.high=&Hoeg MyTorrentsView.menu.setpriority.low=&Lieg MyTorrentsView.menu.start=&Sjtarte MyTorrentsView.menu.stop=Sjto&ppe MyTorrentsView.menu.remove=Weghaole MyTorrentsView.menu.changeTracker=Tr&acker-URL toevoege TrayWindow.menu.exit=Aafsjloete TrayWindow.menu.show=Vuze \u00e4\u00f6pene SystemTray.menu.exit=Aafsjloete SystemTray.menu.closealldownloadbars=&Alle downloadbelk sjloete SystemTray.menu.open_global_transfer_bar=Euverdrachsbalk \u00e4\u00f6pene SystemTray.menu.show=Vuze \u00e4\u00f6pene PeersView.ip.info=IP van de peer PeersView.port=Paort PeersView.port.info=Paort in gebroek PeersView.T.info=L (lokaal): doe h\u00f6bs verb\u00e8njing gemaak, R (aafsjtandj): de downloader haet verb\u00e8njing gemaak. PeersView.T.L.tooltip=Je hebt de verbinding gemaakt PeersView.T.R.tooltip=De peer heeft de verbinding gemaakt PeersView.I1=I1 (Ge\u00efnteresseerd door de downloader) PeersView.I1.info=B\u00f6s te ge\u00efnteresseerd in waat de angere downloader haet? PeersView.C1=V1 (Verstop door de downloader) PeersView.C1.info=Of de downloader dich blokkeert bie 't downloade PeersView.pieces=Sjt\u00f6kskes PeersView.downloadspeed=Downloadsjnelheid PeersView.download=\u00d3mlieg PeersView.I2=I2 (Interessant veur de downloader) PeersView.I2.info=Is de angere downloader ge\u00efnteresseerd in waat-s dich h\u00f6bs? PeersView.C2=V2 (De downloader verstoppe) PeersView.C2.info=Of-s doe de downloader blokkeers bie 't downloade PeersView.uploadspeed=Uploadsjnelheid PeersView.uploadspeed.info=Dien uploadsjnelheid nao de downloader PeersView.upload.info=Je totale upload naar de downloader. PeersView.statup=Up-sjtatus PeersView.statup.info='n Geschatde waerd van de uploadsjnelheid van de downloader PeersView.S.info=Aafwieze: 'ne Downloader kan handjmaotig waere \u201caafgeweze\u201d, of autematis (veur 't neet levere van data mit 'n waarde die hoeg gen\u00f3g is) PeersView.downloadspeedoverall=Gemiddelde downloadsjnelheid PeersView.optunchoke=Opt. Ontsjtop PeersView.client=Cli\u00ebnt PeersView.client.info=Het type BT-cli\u00ebnt det de downloader gebroek PeersView.menu.snubbed=Aafwieze AllPeersView.title.full=Alle Peers ConfigView.section.files=Besjtenj ConfigView.label.usefastresume=Downloads sjnel hersjtarte ConfigView.label.incrementalfile=Sjakel opluipende bestanjsgruutde in [Vereis veur FAT32 \u00f3nger Linux] ConfigView.label.defaultsavepath=Beware in sjtanderddatamap ConfigView.button.browse=&Blajere... ConfigView.dialog.choosedefaultsavepath=Kees de sjtanderd-opsjlaagmap ConfigView.section.server=Verbindingen ConfigView.section.global=Globaal ConfigView.label.disconnetseed=Verbraek verb\u00e8njing mit zenders tiedes uploade ConfigView.label.switchpriority=Autematis \u00f3msjakele nao lieg prioriteit tiedes sjikke ConfigView.label.maxdownloads=Maximum geliektiedige downloads [0: ongelimiteerd] ConfigView.label.maxdownloads.tooltip=Doe k\u00f3ns ummer 't aantal downloads aan h\u00f6bbe sjtaon geliek aan de n\u00f3mmer hie aangegaeve, mit 1 oetz\u00f3njering.\n'ne Complete torrent dae de Ierste Prioriteit-criteria haet, kin 'n actief downloadsjlot euvern\u00f6mme, es deze 't absoluut vereis. ConfigView.label.maxactivetorrents=Maximum actieve torrents [0 : ongelimiteerd]\n - Nuje torrents starte neet es te mier versjiks/\u00f3ntvings ConfigView.label.priorityExtensions=Gaef veurrang aan files mit bepaolde extensies \n- wie: .txt;.nfo;.jpg ConfigView.section.transfer=Overdracht ConfigView.label.maxuploads=Sjtanderdmaximum uploads sjlots per torrent ConfigView.label.maxuploadspeed=Globaal maximum uploadsjnelheid in KB/s [0: ongelimiteerd] ConfigView.label.saveresumeinterval=Update hervatten data jedere ConfigView.unlimited=Ongelimiteerd ConfigView.section.display=Weergaaf ConfigView.label.opendetails=Autematis details-tab \u00e4\u00f6pene ConfigView.label.openbar=Autematis downloadbalk \u00e4\u00f6pene ConfigView.label.use_old_speed_menus=Gebroek sjnelheidsmenu in auwe stiel [hersjtart vereis] ConfigView.label.closetotray=Sjloete minimaliseert nao systeemvak ConfigView.label.minimizetotray=Minimalisere minimaliseert nao systeemvak ConfigView.section.general=Algemein ConfigView.section.start=Sjtarte ConfigView.label.showsplash=Laot opstartsjirm zeen ConfigView.label.autoupdate=Laot de Updatedialoog zeen wen d'r 'n nuuj versie is ConfigView.label.openconsole=Console \u00e4\u00f6pene tiedes 't sjtarte ConfigView.label.openconfig=K\u00f3ngfiggerasie \u00e4\u00f6pene tiedes 't sjtarte ConfigView.label.startminimized=Start geminimaliseerd ConfigView.section.irc=Irc ConfigView.label.ircwiki=Laes estebleef http://wiki.vuze.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Server ConfigView.label.ircchannel=Kanaal ConfigView.label.irclogin=Sjirmnaam ConfigView.group.irctitle=IRC-inst\u00e8llinge ConfigView.boolean.ircsendinfo=Sjikke van dien inst\u00e8llinge toestaon (anoniem) nao\n de kanaaloperators in 't IRC-kanaal \u00f3m h\u00e4\u00f6r in sjtaot te sjt\u00e8lle dich te helpe ConfigView.boolean.irclog=Logge insjakele van de IRC-kanaalactiviteit (in IRC_log.htm) ConfigView.section.security=Beveiliging ConfigView.label.password=Besjirm Vuze mit 'n wachwaord\n - Z\u00f3l \u00f3m gevraog waere tiedes 't sjtarte en oet 't systeemvak haole. ConfigView.label.passwordconfirm=Wachwaord (bevestige) ConfigView.label.passwordmatch=Wachwaord geactiveerd: ConfigView.label.passwordmatchnone=Nei ConfigView.label.passwordmatchno=Nei / Wachw\u00e4\u00f6rd k\u00f3mme neet euverein ConfigView.label.passwordmatchyes=Jao ConfigView.button.save=Beware ConfigView.title.short=K\u00f3ngfiggerasie ConfigView.title.full=K\u00f3ngfiggerasie ConsoleView.title.short=Console ConsoleView.title.full=Console FileItem.write=Sjrieve FileItem.read=Laeze FileItem.normal=Normaal FileItem.high=Hoeg FileItem.donotdownload=Neet downloade FilesView.name=Naam FilesView.name.fastRename=Flot herneume FilesView.size=Gruutde FilesView.done=Vaerdig FilesView.%=% FilesView.firstpiece=Ierste sjt\u00f6kske nr.: FilesView.numberofpieces=Aantal sjt\u00f6kskes FilesView.pieces=Sjt\u00f6kskes FilesView.mode=Modus FilesView.priority=Prioriteit FilesView.menu.open=\u00c4\u00f6&pene FilesView.menu.setpriority=Prioriteit in&sjt\u00e8lle FilesView.menu.setpriority.high=&Hoeg FilesView.menu.setpriority.normal=&Normaal FilesView.menu.setpriority.skipped=Neet &downloade FilesView.title.short=Besjtenj FilesView.title.full=Besjtenj GeneralView.section.downloaded=Gedownload GeneralView.label.status.file=Bestandjsjtatus GeneralView.label.status.pieces=St\u00f6kskessjtatus GeneralView.section.availability=Besjikbaarheid GeneralView.label.status.pieces_available=St\u00f6kskessjtatus GeneralView.section.transfer=Euverdrach GeneralView.title.short=Algemein GeneralView.title.full=Algemein GeneralView.label.timeelapsed=Versjtreke tied: GeneralView.label.remaining=Resterend: GeneralView.label.downloaded=Gedownload: GeneralView.label.downloadspeed=Downloadsjnelheid: GeneralView.label.maxuploads=Upload Slots : GeneralView.label.maxuploads.tooltip=Maximumaantal leechers die geliektiedig \u00f3ntsjtop waere. GeneralView.label.uploaded=Ge\u00fcpload: GeneralView.label.uploadspeed=Uploadsjnelheid: GeneralView.label.seeds=Seeds: GeneralView.label.peers=Peers: GeneralView.label.completed=Vaerdig: GeneralView.label.totalspeed=Totale sjnelheid: GeneralView.label.totalspeed.tooltip=Totale (en gemiddelde) sjnelheid van alle cli\u00ebnte womit se verb\u00f3nje b\u00f6s. GeneralView.label.averagespeed=gemiddeld GeneralView.label.filename=Naam: GeneralView.label.totalsize=Totale gruutde: GeneralView.label.savein=Opsjlaon in: GeneralView.label.hash=Hash: GeneralView.label.numberofpieces=Aantal sjt\u00f6kskes: GeneralView.label.size=Gruutde: GeneralView.label.tracker=Trackersjtatus: GeneralView.label.updatein=Geupdate in: GeneralView.label.trackerurl=Tracker URL: GeneralView.label.trackerurlupdate=Update de Tracker GeneralView.label.comment=Commentaar: GeneralView.label.user_comment=Gebroekersk\u00f3mmentaar: GeneralView.label.status=Sjtatus: ManagerItem.waiting=Wachte ManagerItem.allocating=Reservere ManagerItem.checking=Controlere ManagerItem.ready=Wachten op angere torrent(s) in wachtrie plaatse ManagerItem.downloading=Downloade ManagerItem.seeding=Uploade ManagerItem.stopped=Gesjtop ManagerItem.error=Fout ManagerItem.high=hoeg ManagerItem.low=lieg MinimizedWindow.name=Naam: MinimizedWindow.all_transfers=Vuze-euverdrachte PiecesView.#=Nr: PiecesView.size=Gruutde PiecesView.numberofblocks=Aantal bl\u00f6k PiecesView.blocks=Bl\u00f6k PiecesView.completed=Vaerdig PiecesView.availability=Besjikbaarheid PiecesView.reservedby=Gereserveerd PiecesView.writers=Biedragers blokkere PiecesView.title.short=Sjt\u00f6kskes PiecesView.title.full=Sjt\u00f6kskes SystemTray.tooltip.seeding=%1 uploade, SystemTray.tooltip.downloading=%1 downloade, DownloadManager.error.filenotfound=Besjtandj neet gev\u00f3nje DownloadManager.error.fileempty=Torrentbesjtandj is laeg DownloadManager.error.filetoobig=Torrentbesjtandj is te groet DownloadManager.error.filewithouttorrentinfo=Gein torrentinformatie gev\u00f3nje in besjtandj DownloadManager.error.unsupportedencoding=Neet-\u00f3ngersteunde codering DownloadManager.error.ioerror=I/O-fout DownloadManager.error.sha1=\u00d3nbek\u00e8nd algoritme (SHA1)-fout PeerManager.status.offline=Connectiefout PeerManager.status.checking=K\u00f3nterlere PeerManager.status.finished=Vaerdig PeerManager.status.finishedin=Vaerdig in MainWindow.upgrade.assistant=Update-assistent MainWindow.upgrade.newerversion='t Geuf 'n nuuj versie van Vuze \u00f3m te downloade MainWindow.upgrade.explanation=Deze assistent z\u00f3l de l\u00e8ste versie downloaden in diene Vuze map en Vuze hersjtarte MainWindow.upgrade.explanation.manual=Doe k\u00f3ns handjmaotig update door Vuze te sjloete, de nuje versie te downloaden en Vuze weer te sjtarte MainWindow.upgrade.step1=Stap 1: Download de nuuj versie MainWindow.upgrade.step2=Stap 2: Sjloet dees versie en sjtart de nuuj versie van Vuze MainWindow.upgrade.hint1=Hint:\tDoor op Aafr\u00f3nje te duje z\u00f3l alles autematis gaon MainWindow.upgrade.hint2=Hint:\tEs se Vuze later wils aafsjloete, duuj dan op Annulere en\n\therneum Azureus2-new.jar nao Azureus2.jar nao 't sjloete MainWindow.upgrade.error.downloading.hint=Fout:\tKan gein nuuj versie downloade, update Vuze handjmaotig MainWindow.upgrade.section.info=Nuuj versie besjikbaar MainWindow.upgrade.section.manual=Handjmaotige update MainWindow.upgrade.section.automatic=Autematis update MainWindow.upgrade.tooltip.progressbar=De downloadveurtgank is hie te zeen Button.next=Volgende Button.finish=Voltooie Button.cancel=Annulere LocaleUtil.title=Codering keze LocaleUtil.section.chooseencoding=Kees codering veur besjtanjsnaam LocaleUtil.label.chooseencoding=Kees de b\u00e8s passende codering LocaleUtil.label.hint.doubleclick=Hint: D\u00f6bbelklikke op 'n regel kees codering en sjluut de dialoog LocaleUtil.label.checkbox.rememberdecision=Besjlissing ouch veur euverige besjtanjsname broeke LocaleUtil.column.encoding=Codering IrcClient.defaultChannel=#Azureus-Dutch IrcClient.copyright=Gebroek van PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Verb\u00e8nje mit IrcClient.connected=Verb\u00f3nje mit IrcClient.joining=Inlogge IrcClient.channel=Kenaal IrcClient.joined=ingelogd IrcClient.error=Fout IrcClient.hasjoined=is verb\u00f3nje IrcClient.haskicked=is gekick IrcClient.hasleft=is vertroch IrcClient.nowknown=is noe bek\u00e8nd es IrcClient.topicforchannel=\u00d3nderwerp van dit kenaal IrcClient.disconnected=Verb\u00e8njing verlaore mit IrcClient.noNick=G\u00e8nne sjirmnaam opgegaeve. Gank nao 't 'K\u00f3ngfiggerasie'-sjirm IrcView.actionnotsupported=Dees actie weurt neet \u00f3ngersteund IrcView.clientsconnected=gebroekers IrcView.privateto=Nao IrcView.privatefrom=Van IrcView.noticefrom=L\u00e8t op: IrcView.errormsg=Verkierde syntaxis bie /msg : /msg gebroekersteks IrcView.help=Geljige commando's zeen :\n . /help : geuf dit berich weer\n . /Nick | /naam : verangert diene naam \n . /me actie : sjik 'n actie \n . /msg naam berich : sjik 'n priv\u00e9berich nao \n . /r berich : antwaordt op l\u00e8ste priv\u00e9berich\n . /join #kenaal : verangert 't hujige kenaal PasswordWindow.title=Vuze is vergrendeld PasswordWindow.passwordprotected=Vuze is besjirmp mit e wachwaord.\nV\u00f6l hie dien wachwaord in, \u00f3m 't v\u00e8nster te laote zeen: TrackerChangerWindow.title=Voeg Tracker toe TrackerChangerWindow.newtracker=V\u00f6l 'n nuuj trackeradres in PeersView.discarded=Verworpe PeersView.discarded.info=Data die se waal h\u00f6bs \u00f3ntvange, meh neet nudig hads, dus h\u00f6bs weggedaon. discarded=aafgedank MyTorrentsView.menu.move=Verplaatse MyTorrentsView.menu.moveUp=\u00d3mhoeg MyTorrentsView.menu.moveDown=\u00d3mlieg GeneralView.label.hashfails=Hashfoute: GeneralView.label.shareRatio=Deilverhauwing: ConfigView.section.downloadManagement=Downloadbehier ConfigView.label.startRatioPeers=Start mit uploade wen 't minder es 1 uploader geuf veur ConfigView.text.neverStop=Noets sjtoppe ConfigView.text.neverStart=Noets sjtarte ConfigView.text.peers=Peers ConfigView.label.checkOncompletion=De sjt\u00f6kskes herk\u00f3nterlere wen de download vaerdig is wizard.title='ne Torrent make wizard.previous=< Veurige wizard.next=Volgende > wizard.finish=Aafr\u00f3nje wizard.mode=Tracker / Modus wizard.tracker=Tracker: wizard.invalidurl=Dit adres is neet geljig wizard.singlefile=Inkel besjtandj wizard.singlefile.help=Maak 'ne torrent aan van 'n inkel besjtandj wizard.directory=Map wizard.directory.help=Maak 'ne torrent aan van 'n map wizard.choosefile=Selecteer 't besjtandj wizard.file=Besjtandj: wizard.browse=Blajere... wizard.choosedirectory=Kees 'n map wizard.invalidfile=Ongeljig besjtandj! wizard.invaliddirectory=Ongeljige map! wizard.torrentFile=Torrentbesjtandj wizard.choosetorrent=Kees 't torrentbesjtandj \u00f3m aan te make wizard.information=Infermatie wizard.notimplemented=Nog neet ge\u00efmplementeerd wizard.progresstitle=Torrentbesjtandj aan 't make wizard.savingfile=Aan 't opsjlaon... wizard.filesaved=Besjtandj opgesjlage. wizard.close=Sjloete Torrent.create.progress.piecelength=Sjt\u00f6klingde: Torrent.create.progress.piececount=Aantal sjt\u00f6k: Torrent.create.progress.totalfilesize=Totale besjtanjsgruutde: Torrent.create.progress.totalfilecount=Totaalaantal besjtenj: Torrent.create.progress.parsingfiles=Besjtenj parsere Torrent.create.progress.hashing=Besjtenj beraekene MainWindow.upgrade.downloadingfrom=Downloaden van: ConfigView.section.ipfilter.description=Omsjrieving ConfigView.section.ipfilter.start=Begin-IP ConfigView.section.ipfilter.end=Inj-IP ConfigView.section.ipfilter.add=Toevoege ConfigView.section.ipfilter.remove=Verwijderen ConfigView.section.ipfilter.edit=Bewirke ConfigView.section.ipfilter.save=Beware ConfigView.section.ipfilter.editFilter=Bewirk filter ConfigView.section.ipfilter.enable=Insjakele PeersView.menu.close=Sjloete seedmore.title=Torrent weurt neet gen\u00f3g verspreid seedmore.shareratio=Dien deelverhauwing veur deze torrent is seedmore.uploadmore='n Deelverhauding van minder es 100% is neet goed voor 't Bittorrent-netwerk.\nDoe z\u00f3ts deze torrent nog get langer mote uploade.\nW\u00e8ts te zeker det-s te door wils gaon? ConfigView.label.showpopuponclose=Laot 'n popup zeen wen se stops mit uploaden mit 'n deilverhauwing lieger dan 1 ConfigView.label.startNumSeeds=\nBegin mit uploade es d'r minder dan\n - Vervink alle angere regels ConfigView.label.seeds=seeders ConfigView.section.seeding=Uploade MyTorrentsView.menu.removeand=&Weghaole en MyTorrentsView.menu.removeand.deletetorrent=&Torrentbesjtandj weghaole MyTorrentsView.menu.removeand.deletedata=&Data weghaole MyTorrentsView.menu.removeand.deleteboth=Alle&bei weghaole deletedata.title=Waarsjuwing deletedata.message1=Doe sjteis op 't puntj de DATA weg te haole van :\n MainWindow.menu.file.configure=K\u00f3ngfiggerasie-&wizard... configureWizard.title=K\u00f3ngfiggerasiewizard configureWizard.welcome.title=Welk\u00f3m biej de Vuze-k\u00f3ngfiggerasiewizard configureWizard.welcome.message=Deze wizard hulp mit 't inst\u00e8lle van Vuze veur algemein gebroek. 't Is m\u00e4\u00f6gelik \u00f3m via 't menu Gereidsjappe->K\u00f3ngfiggerasie Vuze mier gedetailleerd in te st\u00e8lle configureWizard.transfer.title=Verb\u00e8njings- en euverdrachinst\u00e8lling configureWizard.transfer.hint=Hint: 'n klein bietje minder es dien verb\u00e8njingsjnelheid is de b\u00e8ste inst\u00e8lling. configureWizard.transfer.message=Kees hiej\u00f3nger 'n verb\u00e8njing. Haud d'r raekening mit det 'ne kleine upload resulteert in lieg downloadsjnelhede. \u00d3mdet de uploadsjnelheid inkel PER torrent geldtj, z\u00f3l 't downloade van tev\u00e4\u00f6l torrents ouch in lieg sjnelhede resultere. V'r raoje aan 5kB/s per torrent es minimum te broeke. Wie sjneller dienen upload, des te sjneller se z\u00f3ls downloade (raekening hauwend mit de torrentsjnelheid). configureWizard.transfer.connection=Lien configureWizard.transfer.connection.0=Handjmaotig configureWizard.transfer.connection.2=adsl/kabel xxx/128 kbps configureWizard.transfer.connection.3=adsl/kabel xxx/256 kbps configureWizard.transfer.connection.4=adsl/kabel xxx/384 kbps configureWizard.transfer.connection.5=adsl/kabel xxx/512 kbps configureWizard.transfer.connection.6=adsl/kabel xxx/768 kbps configureWizard.transfer.connection.7=adsl/kabel xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Max. uploadsjnelheid (KB/s) configureWizard.transfer.maxActiveTorrents=Max. actief configureWizard.transfer.maxDownloads=Max. downloads configureWizard.transfer.maxUploadsPerTorrent=Max. uploads per torrent configureWizard.nat.title=NAT- / serverpaort configureWizard.nat.message=Om het b\u00e8ste oet Vuze te haole is 't raodzaam \u00f3m good bereikbaar te zeen vanaaf 't internet. De standaardpaort is 6881. Dit program help mit 't teste / verangere van de paort.\n\nOpmirking: Dit program test allein TCP-verb\u00e8njinge. De versjpreide database vereis ouch ink\u00f3mmende UDP-verb\u00e8njinge, meh z\u00f3l dich automatisch notificere es 't 'ne firewall \u00f3ntd\u00e8k.\n\nOpmirking: TCP-paort 6880 is intern gereserveerd, dus kan neet waere gebroek. configureWizard.nat.testing=Paort weurt getes configureWizard.nat.ok=OK! configureWizard.nat.ko=NAT-fout configureWizard.nat.unable=Kan neet teste: Verkeerde paort opgegaeve, of de tesservice is misl\u00f6k.\n'n Anger program maak missjien gebroek van dees paort. configureWizard.file.title=Torrents / bestenj configureWizard.file.message1=Vuze z\u00f3l ge\u00e4\u00f6pende torrents in 'n speciale map beware. Doe k\u00f3ns deze map hiej aangaeve: configureWizard.file.path=Paad configureWizard.file.browse=Blajere configureWizard.file.message2=Vuze kan gedownloade besjtenj drek hervatte door gegaeves toe te voege aan de torrents. Door 't gebroek van dees functie k\u00f3ns te ouch gedeiltelik gedownloade st\u00f6kskes hervatte. configureWizard.file.fastResume=Sjakel flot hervatten in configureWizard.file.invalidPath=\u00d3ngeljige map configureWizard.finish.title=Vaerdig configureWizard.finish.message=Vuze is noe geconfigureerd. V\u00e4\u00f6l plezeer! wizard.close.confirmation=Bevestiging wizard.close.message=Wils te deze wizard sjtarte es Vuze de volgende kier sjtart? exportTorrentWizard.title=Exporteer 'ne XML-torrent exportTorrentWizard.torrentfile.title=Inveur torrentselectie exportTorrentWizard.torrentfile.message=Selecteer 't te exportere torrentbesjtandj exportTorrentWizard.torrentfile.path=Paad exportTorrentWizard.torrentfile.browse=Blajere exportTorrentWizard.torrentfile.invalidPath=\u00d3ngeljig torrentbesjtandj exportTorrentWizard.exportfile.title=Exporteer besjtanjselectie exportTorrentWizard.exportfile.message=Veur de naam van 't te exportere XML-besjtandj in exportTorrentWizard.exportfile.path=Paad exportTorrentWizard.exportfile.browse=Blajere exportTorrentWizard.exportfile.invalidPath=\u00d3ngeljig exportbesjtandj exportTorrentWizard.finish.title=Vaerdig exportTorrentWizard.finish.message=Exportere is succesvol aafger\u00f3nd exportTorrentWizard.process.inputfilebad.title=Torrentbesjtandj \u00f3ngeljig exportTorrentWizard.process.inputfilebad.message='n Fout is opgetraoje tiedes 't \u00e4\u00f6pene van inveurbesjtandj: exportTorrentWizard.process.outputfileexists.title=Besjtandj besjteit al exportTorrentWizard.process.outputfileexists.message=Oetveurbesjtandj besjteit al - euversjrieve? exportTorrentWizard.process.torrentfail.title=Torrent laeze misl\u00f6k exportTorrentWizard.process.exportfail.title=Torrent exporteren misl\u00f6k exportTorrentWizard.process.unknownfail.title=\u00d3nverwachde fout importTorrentWizard.title='ne XML-torrent importere importTorrentWizard.torrentfile.title=Torrentselectie inveure importTorrentWizard.torrentfile.message=Veur 't torrentbesjtandj in \u00f3m nao te importere importTorrentWizard.torrentfile.path=Paad importTorrentWizard.torrentfile.browse=Blajere importTorrentWizard.torrentfile.invalidPath=\u00d3ngeljig torrentbesjtandj importTorrentWizard.importfile.title=Selectie importeerbesjtandj importTorrentWizard.importfile.message=Selecteer 't XML-besjtandj \u00f3m te importere importTorrentWizard.importfile.path=Paad importTorrentWizard.importfile.browse=Blajere importTorrentWizard.importfile.invalidPath=\u00d3ngeljig importbesjtandj importTorrentWizard.finish.title=Vaerdig importTorrentWizard.finish.message=Importere succesvol aafger\u00f3nd importTorrentWizard.process.inputfilebad.title='t Importbesjtandj is \u00f3ngeljig importTorrentWizard.process.inputfilebad.message=D'r is 'n fout opgetraoje tiedes 't \u00e4\u00f6pene van inveurbesjtandj: importTorrentWizard.process.outputfileexists.title=Besjtandj besjteit importTorrentWizard.process.outputfileexists.message=Oetveurbesjtandj besjteit - euversjrieve? importTorrentWizard.process.torrentfail.title=Torrent sjrieve misl\u00f6k importTorrentWizard.process.importfail.title=Torrent importere misl\u00f6k importTorrentWizard.process.unknownfail.title=\u00d3nverwachde fout ConfigView.label.bindip=Koppel aan lokaal IP-adres of interface ConfigView.label.xfs.allocation=Wies nuje files toe mit gebroekmaking van 'n specifieke methode veur 't XFS-bestanjssysteem ConfigView.label.xfs.allocation.tooltip=Z\u00f6rg d'r estebleef veur det /usr/sbin/xfs_io fatsoendelik ge\u00efnstalleerd is op eur systeem. Veur de meiste distributies van Linux, is 't inbegrepen in 't "xfsprogs"-pakket. xfs.allocation.xfs_io.not.found=XFS-bestjanjstoewiezing \u00f3ntbrook \u00f3mdet /usr/sbin/xfs_io neet gesjtart k\u00f3s waere. Z\u00f6rg d'r veur det 't fetsoendelik ge\u00efnstalleerd is op eur systeem. De origineel fout waas: "%1". ConfigView.label.zeronewfiles=Besjtenj van gruutde 0 bie aanmake ConfigView.label.zeronewfiles.tooltip=Minimaliseert fragmentatie ConfigView.section.stats=Sjtatistieke ConfigView.section.stats.enable=Insjakele ConfigView.section.stats.defaultsavepath=Opsjlaagmap veur statistieken ConfigView.section.stats.choosedefaultsavepath=Kees de opsjlaaglocatie veur de sjtatistieke ConfigView.section.stats.savefreq=Opsjlaagfrequentie ConfigView.section.stats.minutes=men ConfigView.section.stats.hours=oer ConfigView.section.stats.seconds=sek ConfigView.section.stats.savefile=Besjtanjsnaam sjtatistieke ConfigView.section.stats.graph_update_dividers=Maak 'n vertikale lien bie jedere 60 updates. MyTorrentsView.menu.export=&XML exportere... ManagerItem.finishing=Aafr\u00f3nje ConfigView.dialog.choosedefaulttorrentpath=Kees de sjtanderdmap veur opsjlaag van torrents ConfigView.dialog.choosemovepath=Kees de sjtanderdmap \u00f3m nao te verplaatse ConfigView.label.movecompleted=Verplaats aafger\u00f3nde besjtenj ConfigView.label.moveremoved=Verplaats vaerdige besjtenj (es ze waere verwijderd) ConfigView.label.savetorrents=Bewaar .torrent-besjtenj MainWindow.menu.view.mytracker=Miene &tracker MyTrackerView.title.full=Miene Tracker MyTrackerView.name=Naam MyTrackerView.status.started=Bezig MyTrackerView.status.stopped=Gesjtop MyTrackerView.peers=Leechers MyTrackerView.seeds=Seeders MyTrackerView.announces=Aank\u00f3ndiginge MyTrackerView.uploaded=Ge\u00fcpload MyTrackerView.downloaded=Gedownload MyTrackerView.left=Resterend ConfigView.section.style=Oeterlik ConfigView.label.set_ui_transfer_speeds=Euversjrie selecteerbare euverdrachsjnelhede ConfigView.label.set_ui_transfer_speeds.description=Doe k\u00f3ns d'r veur keze \u00f3m de sjtanderd besjikbare download- en uploadsjnelhede aan te passe, besjikbaar in de statusbalk in 't systeemvak.\nDe waerd m\u00f3t kommagesjeie zeen. ConfigView.label.set_ui_transfer_speeds.description.download=Sjt\u00e8l downloadsjnelheid in (in KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Sjt\u00e8l uploadsjnelheid in (in KB/s) ConfigView.section.style.useCustomTabs=Sjloetbare tabs gebroeke (hersjtart vereis) fileDownloadWindow.saveTorrentIn=Torrentbesjtandj bewaren in fileDownloadWindow.downloading=Downloade vanaaf: fileDownloadWindow.status=Status: fileDownloadWindow.state_initializing=Initialisere fileDownloadWindow.state_downloading=Downloade fileDownloadWindow.state_error=Fout: MainWindow.menu.file.open.url=&Locatie... openUrl.title=Locatie \u00e4\u00f6pene MyTorrentsView.menu.host.error.title=Torrent-hosting misl\u00f6k MyTorrentsView.menu.host.error.message=De volgende foutmelding traoj op tiedes 't hoste van de torrent ConfigView.section.tracker=Tracker ConfigView.section.tracker.pollinterval=Tracker-cli\u00ebnt-aafsjt\u00f6mmingsinterval (sek\u00f3nd) ConfigView.section.tracker.publishenable=Publiceer torrentdetails nao "" ConfigView.section.tracker.ip=IP-adres van externe tracker ConfigView.section.style.enableXPStyle=XP- of Vista-stiel activere (hersjtart vereis) ConfigView.section.tracker.checkip=Autematis extern IP adres opzeuke... ipCheckerWizard.title=Wizard IP-k\u00f3ntrol ipCheckerWizard.service=Deens ipCheckerWizard.chooseService=Kees 'n IP-k\u00f3ntroldeens oet de lies hie-\u00f3nger ipCheckerWizard.explanations=Doe k\u00f3ns deze wizard broeke, \u00f3m oet te v\u00e8nje waat dien externe IP-adres is. Es dien IP-adres dynamisch is, raoje veer dich aan det-s te 'n account \u00e4\u00f6pens bie 'ne dynamische DNS-service. Inkele van dees deenste zeen hie-\u00f3nger aangegaeve, gebroek de link \u00f3m 'n account te make (wo meugelik). V\u00f6l daonao 't IP-adresveldj mit diene dynamische hostnaam (bv.: myhostname.dyndns.org). Doe h\u00f6bs 'n program nudig \u00f3m autematis diene dynamische DNS-service te update mit dien IP-adres. Op die manieer k\u00f3ns te torrents hoste, zelfs es dien IP verangert. ipCheckerWizard.service.description=\u00d3msjrieving: ipCheckerWizard.service.url=Link: ipCheckerWizard.progresstitle=IP k\u00f3nterlere ipCheckerWizard.checkComplete=Aafger\u00f3nd IP: ipCheckerWizard.checkFailed=Misl\u00f6k, raeje: wizard.tracker.local=Ingeboewde tracker gebroeke wizard.tracker.external='nen Externe tracker broeke wizard.tracker.howToLocal=\tGank nao 'Gereidsjappe -> K\u00f3ngfiggeratie -> Tracker' \u00f3m 't in te sjakele wizard.announceUrl=Mitdeil-URL: IPChecker.external.service.discoveryvip.description=Discoveryvip - IP-adres allein k\u00f3nterlere IPChecker.external.httpinvalidresponse=\u00d3ngeljig HTTP-antwaord IPChecker.external.loadingwebpage=Webpazjena laje IPChecker.external.analysingresponse=Antwaord analysere IPChecker.external.addressextracted=IP-adres gev\u00f3nje IPChecker.external.httploadfail=Pazjena laje misl\u00f6k IPChecker.external.timeout=Time-out opgetraoje IPChecker.external.ipnotfound=IP-adres neet gev\u00f3nje ConfigView.section.tracker.pollintervalmin=Minimum ConfigView.section.tracker.pollintervalmax=Maximum ConfigView.section.tracker.pollintervalincby=Ophoege mit ConfigView.section.tracker.pollintervalincper=Jedere ' x ' cli\u00ebnte splash.loadingImages=Plaetjes aan 't laje splash.initializeGui=Hoofvenster aan 't laje splash.openViews=Sjirme aan 't \u00e4\u00f6pene splash.plugin=Plugin aan 't laje: configureWizard.nat.tooManyPorts=Te v\u00e4\u00f6l paorte \u00f3m te teste (9 max) ConfigView.section.color=Kleuresjema MyTorrentsView.menu.publish=&Publicere... MyTrackerView.status.published=Gepubliceerd MyTrackerView.completed=Vaerdig MainWindow.menu.file.open.torrentnodefault=Torrent-besjtandj... (gein sjtanderdopsjlaag) wizard.comment=K\u00f3mmentaar ConfigView.label.movetorrent=Verplaats .torrent ConfigView.label.movepartialdownloads=Verplaats zelfs es sommige files zeen gemarkeerd mit "Neet downloade". ConfigView.label.subdir_is_in_default=Wen euverwaoge weurt det downloads besjtaon in een standaardmap, euverwaeg dan ouch de submappe ConfigView.section.file.decoder.label=Sjtanderd torrentcodering wen selectie vereis is ConfigView.section.file.decoder.nodecoder=Gein IPChecker.external.service.no-ip.description=Dynamic en Static DNS-serviceprovider\n(neet vrie besjikbare 'adresk\u00f3ntrol'-service) ConfigView.section.tracker.publicenable=Externe torrents toesjtaon ConfigView.label.playdownloadspeech=Kal wen 'ne download vaerdig is ConfigView.label.playdownloadspeech.info=De Sjpraokservice wirk 't b\u00e8ste mit Ingels # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Geuf 't aantal besjikbare kopie\u00eb aan van jeder deil.\nEs de n\u00f3mmer rechts kleiner dan 1 is, dan zuus se gein volledige kopie van 't besjtandj (en k\u00f3ns se perbleme h\u00f6bbe bie 't voltooie van de download). GeneralView.label.trackerurl.tooltip=Klik \u00f3m de url nao 't klembord te kopi\u00ebre GeneralView.label.trackerurlopen.tooltip=Klik \u00f3m de hoofpazjena van de tracker te \u00e4\u00f6pene # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Ververs GUI jedere ConfigView.section.style.inactiveUpdate=Hoofsjirm jedere N GUI update(s) ververse wen 't neet 't active sjirm is. ConfigView.section.style.graphicsUpdate=Grafische belk jedere N GUI-update(s) ververse ConfigView.section.style.reOrderDelay=De tabelle jedere N GUI update(s) opnuuj indeile [0: noets] ConfigView.section.style.reOrderDelay.never=Noets ConfigView.section.logging=Logging ConfigView.section.logging.enable=Logbesjtandj insjakele ConfigView.section.logging.logdir=Logbesjtanjsmap ConfigView.section.logging.choosedefaultsavepath=Kees de opsjlaaglocatie GeneralView.label.updatein.querying=Wachte... configureWizard.nat.sharePort=Gebroek 'n inkel gedeilde paort veur alle torrents ConfigView.section.logging.maxsize=Maximale gruutde van logbesjtandj ConfigView.section.tracker.passwordenableweb=Sjakel trackerweb wachwaord in ConfigView.section.tracker.passwordenabletorrent=Torrentwachwaord insjakele ConfigView.section.tracker.username=Gebroekersnaam ConfigView.section.tracker.password=Wachwaord columnChooser.title=Kees de weer te gaeve kel\u00f3mme columnChooser.move=Sleip de rieje \u00f3m ze opnuuj in te deile columnChooser.apply=Toepasse columnChooser.columnname=Kel\u00f3mnaam columnChooser.columndescription=Besjrieving TableColumn.header.shareRatio=Deilverhauwing MyTorrentsView.menu.editTableColumns=&Kel\u00f3mme insjt\u00e8lle wizard.operationfailed=Bewirking misl\u00f6k authenticator.title=Verificatie vereis authenticator.realm=Domein authenticator.tracker=Tracker authenticator.user=Gebroekersnaam authenticator.password=Wachwaord ConfigView.label.allowSendVersion=Gaef Vuze toesjt\u00f6mming \u00f3m anoniem 't versien\u00f3mmer en 'n willek\u00e4\u00f6rig ID door te gaeve bie 't zeuke nao 'n nuuj versie ConfigView.label.version.info.link=Kiek hie veur details euver welke data is gesjik nao de versiek\u00f3ntrol-server. wizard.hint.mode=Hint:\tDoe k\u00f3ns 'n inkele map of besjtandj op deze wizard sjleipe\n\t\u00f3m 'n map of besjtandj te keze wizard.hint.file=Hint:\tDoe k\u00f3ns 'n inkel besjtandj keze door te sjleipe wizard.hint.directory=Hint:\tDoe k\u00f3ns 'nen inkele map keze door te sjleipe MainWindow.menu.help.checkupdate=&K\u00f3nterleer op nuuj versie... TableColumn.header.down=Gedownload TableColumn.header.up=Ge\u00fcpload ConfigView.section.tracker.passwordenabletorrent.info=Hie is 'ne goje Bittorrent-cli\u00ebnt veur vereis (zoals Vuze) ConfigView.section.style.confirmationOnExit=Bevestigingsv\u00e8nster laote zeen bie aafsjloete MainWindow.dialog.exitconfirmation.title=Vuze aafsjloete MainWindow.dialog.exitconfirmation.text=Wils se Vuze ech aafsjloete? SystemTray.menu.stopalltransfers=&Alle euverdrachte sjtoppe TrayWindow.menu.stopalldownloads=&Alle downloads sjtoppe ConfigView.section.tracker.sslport.info=Laes de FAQ veur mier infermatie wizard.tracker.ssl=SSL gebroeke ConfigView.label.playdownloadfinished=Sjpeel 'n geluid aaf wen 'ne download vaerdig is ConfigView.label.popupdownloadfinished=Laot 'n waarsjuwingspopup zeen es 'ne download vaerdig is ConfigView.label.popupfilefinished=Laot 'n waarsjuwingspopup zeen es 'n deil van 'n besjtandj vaerdig is TableColumn.header.pieces=Sjt\u00f6kskes TableColumn.header.pieces.info=Grafische balk vertaengeweurdigt welke deile se h\u00f6bs gedownload TableColumn.header.completion=Vaerdig TableColumn.header.completion.info=Grafische vertaengeweurdiging van % gedownload ConfigView.section.style.showdownloadbasket=Downloadmandj laote zeen (sjleipen-en-neerz\u00e8tte .torrents) ConfigView.section.style.alwaysShowTorrentFiles=Laat ummer Torrent-besjtenj zeen in Details/Besjtenj wizard.multitracker=Multi-Tracker-infermatie aan de torrent toevoege wizard.multitracker.title=Multi Tracker wizard.multitracker.configuration=Multi-Tracker-k\u00f3ngfiggeratie wizard.multitracker.new=Nuuj... wizard.multitracker.edit=Bewirke.. wizard.multitracker.delete=Weghaole wizard.multitracker.group=Trackergroep wizard.multitracker.edit.title=Multi-Tracker-editor wizard.multitracker.edit.name=Naam wizard.multitracker.edit.save=Beware wizard.multitracker.edit.newgroup=Nuje groep wizard.multitracker.edit.deletegroup=Weghaole wizard.multitracker.edit.newtracker=Nuje tracker wizard.multitracker.edit.deletetracker=Weghaole wizard.multitracker.edit.edit=Bewirke wizard.addingmt=Multi-Trackerinfermatie aan 't toevoege wizard.multitracker.noannounce=Mitdeil-URL sjteit neet op dien trackerlies MyTorrentsView.menu.recheck=Her&k\u00f3ntrol forcere iconBar.showDownloadBar.tooltip=Downloadbalk laote zeen iconBar.start.tooltip=Sjtarte iconBar.stop.tooltip=Sjtoppe iconBar.remove.tooltip=Weghaole iconBar.openNoDefault.tooltip='n .torrent-besjtandj \u00e4\u00f6pene (gein sjtanderdopsjlaag) iconBar.openURL.tooltip='nen URL \u00e4\u00f6pene iconBar.openFolder.tooltip='ne Map \u00e4\u00f6pene iconBar.new.tooltip='ne Torrent make iconBar.up.tooltip=\u00d3mhoeg verplaatse iconBar.down.tooltip=\u00d3mlieg verplaatse iconBar.run.tooltip=\u00c4\u00f6pene iconBar.publish.tooltip=Publicere MyTorrentsView.menu.editTracker=Tracker-URL('s) bew&irke GeneralView.menu.selectTracker=Selecteer ConfigView.section.stats.xslfile=XSL-besjtanjsnaam ConfigView.section.stats.xslfiledetails=Deze weurt opgen\u00f3mmen in de header van 't sjtatistiekebesjtandj\nvia de -tag ConfigView.label.savetorrentbackup=Reservekopie beware ConfigView.section.tracker.forceport=Forceer gehoste externe torrents nao sjtanderdpaort ConfigView.section.ipfilter.allow=TOESJTAON van dees gebiede (sjtanderd is WEIGERE) ConfigView.section.ipfilter.list.inrange=zoot b\u00e8nne 't gebied ConfigView.section.ipfilter.list.notinrange=zoot neet b\u00e8nne 'n gebied ConfigView.section.ipfilter.list.title=Lies geblokkeerde IP's ConfigView.label.allowsameip=Mierdere verb\u00e8njinge van 't zelfde IP toesjtaon ConfigView.label.allowsameip.tooltip=Allein aanvinke indeen NUDIG.\nDit is 'n leecherbesjirming (indeen oetgesjakeld). ManagerItem.superseeding=Super-Seede ConfigView.label.userSuperSeeding=Gebroek Super-Seeden (wirk alleen bie ierste en es enige seeder) PeersView.uniquepiece=Deilke (Super-Seed-modus) PeersView.uniquepiece.none=Gein PeersView.timetosend=Tied t\u00f3t 't opnuuj sjikke van sjt\u00f6kske (Super-Seed-modus) ConfigView.section.style.addurlsilently=\u00c4\u00f6pen gesjlaagde URL's sjtilzwiegend ConfigView.section.style.addurlsilently.tooltip=Autematis gepaseerde/gevalle .torrent-URL's downloade z\u00f3nger e dialoogv\u00e8nster te \u00e4\u00f6pene. ConfigView.section.file.decoder.prompt=Ummer vraoge wen coderingkeuze besjikbaar is ConfigView.section.file.decoder.prompt.tooltip=Laot ummer 'n dialoog zeen wen coderingkeuze besjikbaar is MyTorrentsView.menu.moveTop=Nao d'n &top verplaatse MyTorrentsView.menu.moveEnd=Nao de &baom verplaatse ConfigView.label.moveonlyusingdefaultsave=allein es in de stjanderddatamap ConfigView.label.moveonlyusingdefaultsave.tooltip=allein verplaatse es de gedownloade data zich in de sjtanderddata map bevindtj ConfigView.label.watchtorrentfolder=Importeer autematis nuje torrents ConfigView.label.watchtorrentfolder.tooltip=Zeukt regelmaotig nao nuje .torrents ConfigView.label.watchtorrentfolderinterval=T\u00f6sjepauze ConfigView.label.watchtorrentfolderinterval.tooltip=T\u00f6sjepauze t\u00f3t de map opnuuj gescand weurt ConfigView.dialog.choosewatchtorrentfolderpath=Kees de .torrent-importeermap ConfigView.label.startwatchedtorrentsstopped=Begin gesjtop ConfigView.label.startwatchedtorrentsstopped.tooltip=Voeg nuje torrents toe mit es status GESJTOP ConfigView.section.plugins=Plugins wizard.maketorrent.filesize=Besjtanjsgruutde wizard.maketorrent.piececount=Aantal sjt\u00f6k wizard.maketorrent.piecesize=Sjtr\u00f6kgruutde wizard.maketorrent.auto=Autematis MainWindow.menu.view.stats=&Sjtatistieke SpeedView.title.full=Activiteit SpeedView.downloadSpeed.title=Downloadsjnelheid SpeedView.uploadSpeed.title=Uploadsjnelheid ConfigView.section.style.useSIUnits=Gebruik IEC-einhede (KB -> KiB enz.) iconBar.top.tooltip=Baovenaan z\u00e8tte iconBar.bottom.tooltip=\u00d3ngeraan z\u00e8tte TableColumn.header.health=Status MyTorrentsView.menu.health=Sjtatusinfermatie health.explain.grey=beteikent det diene torrent neet aansjteit (upload of download) health.explain.red=beteikent des se neet mit 'ne peer verb\u00f3nje b\u00f6s tiedes downloaden health.explain.blue=Wen se uploads beteikent dit des se neet mit 'ne peer b\u00f6s verb\u00f3nje\nWen se uploads beteikent dit des se waal verb\u00f3nje b\u00f6s mit 'n aantal peers, mer det de tracker neet verb\u00f3njen is health.explain.yellow=beteikent det de tracker good is, des se mit peers verb\u00f3nje b\u00f6s, mer des se gein verb\u00e8njing op aafsjtandj h\u00f6bs.\nDoe k\u00f3ns 'n NAT-perbleem h\u00f6bben es de torrents ummer gael blieve. health.explain.green=beteikent det alles good geit. ConfigView.section.style.alwaysRefreshMyTorrents=Mien Torrents ummer ververse ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Dees optie ververs 't Mien Torrents-sjirm, ouch es 't v\u00e8nster neet weergegaeve weurt(henjig veur inkele mIRC-plugins) # #2.0.7.0 # security.certtruster.title=Beveiligingscertificaat-waarsjuwing security.certtruster.intro='t Beveiligingscertificaat is vriegegaeve door 'n bedrief det-s te neet vertroets security.certtruster.resource=Br\u00f3n: security.certtruster.issuedto=Vriegagaeve aan: security.certtruster.issuedby=Vriegegaeve door: security.certtruster.prompt=Wils se-'n 't vertroewe? security.certtruster.yes=Jao security.certtruster.no=Nei ConfigView.section.tracker.torrentsperpage=Maximumaantal torrents per pagina? [0: ongelimiteerd] MainWindow.menu.file.share=&Deile MainWindow.menu.file.share.file=&Besjtandj... MainWindow.menu.file.share.dir=&Map... MainWindow.menu.file.share.dircontents=Map&inhaud... MainWindow.menu.file.share.dircontentsrecursive=Mapinhaud (&Recursief/mit submappe) MainWindow.dialog.share.sharefile=Selecteer 't te deile besjtandj MainWindow.dialog.share.sharedir=Selecteer de te deile map MainWindow.dialog.share.sharedircontents=Selecteer de te deile mapinhaud MainWindow.dialog.share.sharedircontents.recursive=Recursief globalmanager.download.remove.veto=Weghaolactie geweigerd plugin.sharing.download.remove.veto=Deze download is 't resultaat van 'n gedeilde br\u00f3n.\nHaol de biebehurende gedeilde bron \u00f3m 'm weg te haole: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Hoof ConfigView.section.tracker.web=Web ConfigView.label.prioritizefirstpiece=Gaef 't ierste deil van besjtenj veurrang ConfigView.label.prioritizefirstpiece.tooltip=Perbeert 't ierste deil van 'n besjtandj iers te downloade.\n\u00d3m previews te \u00f3ngersteune. ConfigView.section.file.confirm_data_delete=Weghaole van data bevestige ConfigView.section.file.confirm_data_delete.tooltip=Bevestig 't wusje van data bie 't gebroek van 'Verplaatsen en weghaole...' ConfigView.section.file.delete.include_files_outside_save_dir=Wen data d'r vanaaf waere gehaold, torrents die gelink zeen in 'n opsjlaagmap ouch d'r vanaaf haole TrayWindow.menu.startalldownloads=Alle downloads sjtarte SystemTray.menu.startalltransfers=Alle euverdrachte sjtarte sharing.progress.title=Veurtgank van het deile sharing.progress.hide=Verberge MainWindow.menu.view.myshares=Mien gedeelde br\u00f3nne MySharesView.title.full=Mien Gedeilde Br\u00f3nne MySharesView.name=Naam MySharesView.type=Type MySharesView.type.file=Besjtandj MySharesView.type.dir=Map MySharesView.type.dircontents=Mapinhaud MySharesView.type.dircontentsrecursive=Mapinhaud (recursief/mit submappe) MySharesView.menu.remove=Weghaole ConfigView.section.tracker.extensions=Extensies ConfigView.section.tracker.sendpeerids=Sjik peer-identiteit nao leechers ConfigView.section.tracker.enableudp=Activeer UDP-trackerprotocol plugin.sharing.torrent.remove.veto=Deze trackerregistratie is 't resultaat van 'n gedeilde br\u00f3n.\nHaol de biebehurende gedeilde bron \u00f3m 'm weg te haole: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Deze download kan neet weggehaold waere \u00f3mdet d'r neet gesjtop is plugin.sharing.remove.veto=Deze deiling is 'n subdeiling van 'n gedeilde 'mapinhaud' en kan neet expliciet weggehaold waere.\nHaol de hoofdeiling eweg. GeneralView.label.hash.tooltip=Klik \u00f3m de hash nao 't klembord te kopi\u00ebre ConfigView.section.tracker.maxpeersreturned=Maximumaantal tr\u00f6k te kriege peers [0: ongelimiteerd] ConfigView.label.serverport=Ink\u00f3mmende TCP-/UDP-loesterpaort ConfigView.label.serverport.tooltip=Paort m\u00f3t in 'n bereik van 1-65535 zeen en neet 6880, \u00f3mdet die veur intern gebruik van Vuze is gereserveerd. configureWizard.nat.server.tcp_listen_port=Ink\u00f3mmende TCP-loesterpaort ConfigView.section.sharing=Deile (klassiek) ConfigView.section.sharing.usessl=Gebroek SSL veur gedeilde br\u00f3nne (vereis Trackerk\u00f3ngfiggerasie) ConfigView.section.style.dropdiraction='Sjleipen-en-neerz\u00e8tte' gebroeke veur mappe ConfigView.section.style.dropdiraction.opentorrents=Open Torrents ConfigView.section.style.dropdiraction.sharefolder=Deel map ConfigView.section.style.dropdiraction.sharefoldercontents=Deel inhoud # # 2.0.7.x # Categories.all=Alle Categories.uncategorized=\u00d3ngecategoriseerdj CategoryAddWindow.message=Veur 'n nuuj categorienaam in CategoryAddWindow.title=Voeg 'n nuuj categorie toe ConfigView.label.autoSeedingIgnoreInfo=Genegeerde torrents gaon nao de baom van de uploadrie. Ze starte neet autematis.\nGenegeerde regels zeen neet van toepassing op torrents die de Ierste Prioriteit criteria h\u00f6bbe.\nBehauve es anges aangegaeve, gebroek 'n waerd van 0 \u00f3m de regel oet te sjakele. ConfigView.label.directory=Map ConfigView.label.disconnetseed.tooltip=Wen se-n 'n torrent aan 't uploade bis, verbraek dan de verb\u00e8njing mit cli\u00ebnts die ouch aan 't uploade zeen.\nZe hove neet mit dich te communicere. ConfigView.label.ignoreCase=Hooflettergebroek negere ConfigView.label.ignoreSeeds=Negeer torrents mit tenminste ConfigView.label.importdirectory=Importeermap ConfigView.label.minPeersToBoostNoSeeds.tooltip=Alle torrents z\u00f3nger seeders en die minder leechers h\u00f6bbe es te specificeers\ngaon nao de baom van de wachrie. ConfigView.label.minPeersToBoostNoSeeds=Verlieg uploadwaerd veur torrents z\u00f3nger seeders en minder dan ConfigView.label.minSeedingTime.tooltip=De uplaodwaerd kan flot wissele in 'ne korte tied, wodoor torrents aaf en toe autematis waere gesjtart \u00f3m daonao drek te sjtoppe en in de wachrie gezat te waere.\nDit verlich 't probleem door de torrent te dwinge om 'n bepaolde tied te blieve uploade. Doe k\u00f3ns 't handjmaotig sjtoppe es te det wils. ConfigView.label.minSeedingTime=Minimale uploadtied in sek\u00f3nd ConfigView.label.minSpeedForActiveDL.tooltip='n Downloadsjlot weurt ummer voor de ierste 30 sek\u00f3nd\ngebroek nao 't starte van 'n onvolledige torrent. ConfigView.label.minSpeedForActiveDL=Torrent gebroek gein downloadsjlot es de sjnelheid lieger is dan ConfigView.label.queue.debuglog=Debuginfermatielog beware ConfigView.label.queue.debuglog.info=Voeg wachriedebuginfo aan 't console-/logbesjtandj toe.\nWiewaal cryptisch, vert\u00e8lt de debuginfo dich de sjtatus van de torrents en worom ze waal/neet sjtarte of in de wachrie k\u00f3mme. ConfigView.label.queue.minQueueingShareRatio=Sjtop neet of z\u00e8t torrents neet in de wach t\u00f3tdet de deilverhauwing is bereik ConfigView.label.ratio=verhauwing ConfigView.label.removeOnStop=Haol torrent van de lies aaf naodet d'r autematis gesjtop is ConfigView.label.savedirectory=Opsjlaagmap ConfigView.label.seeding.autoReposition.tooltip=De volgorde van de torrents (de 'Nr:'-kel\u00f3m) weurt verangerd op basis van de uploadwaerde, indeen ingesjakeld\nDit is henjig es se uploadwaerdn\u00f3mmere neet wils zeen, mer waal wils weite in welke volgorde de vaerdige torrents sjtarte. ConfigView.label.seeding.autoReposition=Herpositioneer torrents autematis gebaseerd op de uploadwaerd ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=D\u00e8ks beteikene torrents mit weinig seeders en v\u00e4\u00f6l peers, det d'r waarsjienlik gein volledige kopie \u00f3nger de peers is.\nHiedoor wils se missjiens neet det de uploadregels doon of d'r 'n volledige kopie is (en daodoor de rangorde onterech verliege) ConfigView.label.seeding.fakeFullCopySeedStart=maar alleen voor torrents met minstens ConfigView.label.seeding.ignore=Negeer regels ConfigView.label.seeding.ignore0Peers=Negeer torrents mit 0 leechers ConfigView.label.seeding.ignoreRatioPeers=Negeer torrents die minstens eine upload h\u00f6bbe veur jedere ConfigView.label.seeding.ignoreShareRatio=Negeer torrents die 'n deilverhauwing h\u00f6bbe van ConfigView.label.seeding.ignore.header.evenFirstPriority=Negeer torrent zelfs es\nIerste Prioriteit-regel van toepassing is ConfigView.label.seeding.ignore.header.rule=Regel ConfigView.label.seeding.ignore.header.value=Waerd ConfigView.label.seeding.firstPriority.info=Torrents mit de Ierste Prioriteit waere ummer baove in de rie gezat.\nAlle torrents die aan de Ierste Prioriteit-criteria voldoon, waere neet autematis gesjtop en in de wachrie gezat.\n'ne Torrent dae aan de Eerste Prioriteit-criteria volduit, krieg 'n geliektiedig downloadsjlot indeen nudig. ConfigView.label.seeding.firstPriority.FP=Ierste Prioriteit ConfigView.label.seeding.firstPriority=Ierste prioriteit geit nao torrents mit ConfigView.label.seeding.firstPriority.following=van de volgende k\u00e8nmerke: ConfigView.label.seeding.firstPriority.shareRatio='n Deilverhauwing \u00f3nger ConfigView.label.seeding.firstPriority.seedingMinutes='ne Verloupe tied sins 't verangere van downloade nao uploade van ConfigView.label.seeding.firstPriority.DLMinutes='ne Verloupe tied sins 't sjtarte van downloade van ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Door te doon es of d'r 1 volledige kopie per X peers is, verliegs se de waerd van torrents mit 'n hoeg aantal peers.\nMeistal h\u00f6bbe torrents mit v\u00e4\u00f6l peers, v\u00e4\u00f6l verkier.\nDit verangert nieks aan 'Nr:' van uploads'. ConfigView.label.seeding.numPeersAsFullCopy=Doot es of d'r 1 volledige kopie veur jedere\n(0 : Doot neet es of) ConfigView.label.seeding.preferLargerSwarms.tooltip=Es se veurnamelik torrents uploads mit peers die "vas zitte", dan is 'n hoegere prioriteit gaeve aan groete zjwerme logisch\nWen se veurnamelik torrents uploads mit 'n hoeg toegankelijkheid, is 't logischer \u00f3m de prioriteit te gaeven aan kleine zjwerme. ConfigView.label.seeding.preferLargerSwarms=Gaef hoegere prioriteit aan groete zjwerme, wen torrents dezelfde waerd h\u00f6bbe. ConfigView.label.seeding.rankType.none.tooltip=Volgorde gebaseerd op Nr:-kel\u00f3m ConfigView.label.seeding.rankType.none=Gein ConfigView.label.seeding.rankType.peer.tooltip=Mier peers en minder seeds = hoegere uploadwaerd\nDit minimaliseert 't aantal torrents die actief gehauwe m\u00f3tte blieve waere \u00f3m de upload te maximalisere ConfigView.label.seeding.rankType.peer=Gewaoge peeraantal ConfigView.label.seeding.rankType.peerSeed.options=Seeders:Leechers Verhauwingsopties ConfigView.label.seeding.rankType.peerSeed.tooltip=Hoegere verhauwing = hoegere waerd ConfigView.label.seeding.rankType.peerSeed=Leechers:Uploadverhauwing ConfigView.label.seeding.rankType.seed.fallback=Tr\u00f6kvalle nao Leechers:Seeders nao\n(0: Noets tr\u00f6kvalle) ConfigView.label.seeding.rankType.seed.options=Allein-uploadaantal-opties ConfigView.label.seeding.rankType.seed.tooltip=Minder uploads, hoeagere waerd ConfigView.label.seeding.rankType.seed=Allein uploadaantal ConfigView.label.seeding.rankType.timedRotation.tooltip=Alle vaerdige torrents in de wachrie omz\u00e8tte nao uploadmodus.\nTiedsdoer van uploade is ingesjt\u00e8ld bie 'Minimale Uploadtied' ConfigView.label.seeding.rankType.timedRotation=Geklokde rotatie ConfigView.label.seeding.rankType.tooltip=Torrents mit de hoegste waerd sjtarten autematis.\nWen 'nen angere torrent 'n hoegere waerd krieg, sjtop de torrent mit 'n liegere waerd en geit tr\u00f6k in de wachrie.\n\nAllein torrents in 'n wachrie kinne automatisch starte.\nTorrents die gesjtop zeen sjtarte noets automatisch. ConfigView.label.seeding.rankType=Waerd complete torrents veur auto-starte gebaseerd op: ConfigView.label.stopAfterMinutes=Wen euvergesjakeld nao uploade, sjtop nao 'ne tied van ConfigView.label.switchpriority.tooltip=Lieg prioriteit vermindert 't heugte van uploadbandbreidte die 'ne torrent kan gebroeke. ConfigView.pluginlist.info=De volgende plugins zeen ge\u00efdentificeerd. Sommige plugins h\u00f6bbe m\u00e4\u00f6gelik gein k\u00f3ngfiggerasietabs. ConfigView.pluginlist.noplugins=D'r zeen gein plugins gev\u00f3nje. ConfigView.section.pluginslist=Lies ConfigView.section.queue.seeding=Sjikke ConfigView.section.queue.seeding.autoStarting=Autematis sjtarte ConfigView.section.queue.seeding.ignore=Regels negere ConfigView.section.queue.seeding.firstPriority=Ierste Prioriteit ConfigView.section.queue.main=Hoof ConfigView.section.queue=Wachrie ConfigView.section.torrents=Torrents ConfigView.text.all=alle ConfigView.text.hours=oere ConfigView.text.ignoreRule=Regel negere ConfigView.text.ignore=Negere ConfigView.text.minutes=menuut ConfigView.text.neverIgnore=Noets negere ConfigView.text.any=ein DownloadManager.error.datamissing=Gegaeves \u00f3ntbraeke MainWindow.menu.file.open.torrentforseeding=Torrent-besjtandj... (veur uploade) MainWindow.menu.language.refresh=Ve&rnuje ManagerItem.forced=Geforceerd ManagerItem.queued=In de wach MySeedersView.header=Vaerdige torrents TableColumn.header.availability.info=aantal ganse kopie\u00eb te zeen TableColumn.header.availability=Besjikbaarheid TableColumn.header.category=Categorie MyTorrentsView.header=Ink\u00f3mplete torrents TableColumn.header.maxuploads=Maximumaantal uploads MyTorrentsView.menu.category.delete=Categorie weg&doon MyTorrentsView.menu.forceStart=Sjtart &forcere MyTorrentsView.menu.queue=In de &wach z\u00e8tte MyTorrentsView.menu.setCategory.add=C&ategorie toevoege... MyTorrentsView.menu.setCategory=Categorie toewieze TableColumn.header.savepath=Opsjlaagpad TableColumn.header.SeedingRank=Uploadwaerd TableColumn.header.totalspeed.info=Totale sjnelheid van alle leechers womit se verb\u00f3nje b\u00f6s TableColumn.header.totalspeed=Totale sjnelheid splash.initializePlugins=Plug-ins aan 't laje StartStopRules.SPratioMet=S:P Verh. OK StartStopRules.FP0Peers=E.P. / 0 Leechers StartStopRules.numSeedsMet=Nr: Uploads OK StartStopRules.ratioMet=Peers:Upload OK StartStopRules.shareRatioMet=Deilverhauwing OK StartStopRules.waiting=Wachte StartStopRules.firstPriority=1e Prioriteit ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Deel Inhoud (Recursief) DownloadManager.error.unabletostartserver=Kan server neet sjtarte - k\u00f3nteleer ink\u00f3mmende paortk\u00f3ngfiggerasie- / Firewall-insjt\u00e8llinge zoedet 't program 'ne server kan zeen GeneralView.label.creationdate=Gemaak op: ConfigView.section.tracker.announcescrapepercentage=Deilkes t\u00f6sjepauze es %laeftied van mitdeiling\nwie 200 ; 2:1. 0 ; laot peer besjlisse ManagerItem.stopping=Bezig mit sjtoppe ConfigView.section.tracker.announcecacheperiod=Cache mitdeile jedere (millisek\u00f3nd) ConfigView.section.tracker.scrapecacheperiod=Deilkescache (millisek\u00f3nd) ConfigView.section.tracker.scrapeandcache=Deilkes en cache ConfigView.section.tracker.announcecacheminpeers=Peerdrempelwaarde mitdeile aan cache MyTrackerView.scrapes=Deilkes fileDownloadWindow.retry=Opnuuj perbere MyTrackerView.bytesin=Bytes in MyTrackerView.bytesinave=Gemiddeld in MyTrackerView.bytesout=Bytes oet MyTrackerView.bytesoutave=Gemiddeld oet ConfigView.section.file.max_open_files=Maximumaantal ge\u00e4\u00f6pende besjtenj veur laezen en sjrieve\n[0: ongelimiteerd] ConfigView.section.file.max_open_files.tooltip=Henjig es se torrents downloads mit h\u00f3ngerde/doezende besjtenj, en es se-n 't maximaal aantal besjtenj det 't besjturingssysteem kan verwirke h\u00f6bs bereik. ConfigView.section.proxy=Proxy ConfigView.section.proxy.enable_proxy=Sjakel proxy veur trackercommunicaties in [hersjtart vereis] ConfigView.section.proxy.port=Paort ConfigView.section.proxy.username=Gebroekersnaam ConfigView.section.proxy.password=Wachwaord ConfigView.section.proxy.enable_socks=Ich h\u00f6b 'ne SOCKS-proxy wizard.createtorrent.extrahashes=Hashes toevoege veur anger netwerke (wie Gnutella2, eDonkey2000) GeneralView.label.connected=verb\u00f3nje GeneralView.label.in_swarm=in zjwerm ManagerItem.initializing=Initialisere AlertMessageBox.error=Fout AlertMessageBox.warning=Waarsjuwing AlertMessageBox.comment=Infermatie AlertMessageBox.information=Infermatie AlertMessageBox.unread=Doe h\u00f6bs ongelaeze waarsjuwingsberichte - klik hie \u00f3m dees te laeze. SharedPortServer.alert.selectorfailed=K\u00f3s g\u00e8nne listener veur ink\u00f3mmende data make.\nK\u00f3nterleer dien Firewall-insjt\u00e8llinge en gaef java(w).exe toesjt\u00f6mming \u00f3m zich te gedrage es 'server' Tracker.alert.listenfail=Misl\u00f6k \u00f3m te loestere op paort %1.\nK\u00f3nterleer of anger applicaties dees paort neet broeke.\nK\u00f3nterleer ouch of 'n anger kopie van Vuze driet. DiskManager.alert.movefileexists=Verplaatse vaerdige besjtenj misl\u00f6k\nBesjtandj %1 besjteit al in de doelmap DiskManager.alert.movefilefails=Verplaatse vaerdige besjtenj misl\u00f6k\nVerplaatse van besjtandj %1 misl\u00f6k, %2 DiskManager.alert.movefilerecoveryfails=Fouthersjt\u00e8l nao misl\u00f6kde verplaatsing.\nHersjt\u00e8lle van bestand %1 misl\u00f6k, %2 ConfigView.section.tracker.logenable=Log periodieke sjtatistieke nao 'tracker.log' SpeedView.stats.title=Sjtatistieke SpeedView.stats.total=Totaal SpeedView.stats.session=Dees sessie SpeedView.stats.session.tooltip=Totaal (Protocol) SpeedView.stats.downloaded=Gedownload SpeedView.stats.uploaded=Ge\u00fcpload (Protocol) SpeedView.stats.ratio=Verh. SpeedView.stats.uptime=On-line tied SpeedView.stats.now=Noe SpeedView.stats.now.tooltip=Totaal (Protocol) AutoMigration.useralert=Vuze gebroekersk\u00f3ngfiggerasiebesjtenj/-mappe auto-migratie resultate:\n\n%1\nAlle misl\u00f6kde m\u00f3tte handjmatig waere gemigreerd.\nVERGAET NEET DIEN OPSJLAAGPAAD TE UPDATEN IN DIEN CONFIGURATIE ES DET IS GEMIGREERD! # # > 2.0.8.0 # OpenTorrentWindow.title=Torrent(s) \u00e4\u00f6pene OpenTorrentWindow.message=Experimenteel OpenTorrentWindow.addFiles=Besjtenj toevoege OpenTorrentWindow.dataLocation=Locatie \u00f3m data op te sjlaon: OpenTorrentWindow.startMode=Modus toevoege OpenTorrentWindow.startMode.queued=In wachrie OpenTorrentWindow.startMode.stopped=Gesjtop OpenTorrentWindow.startMode.forceStarted=Geforceerd sjtarte OpenTorrentWindow.addPosition=Wachriepositie OpenTorrentWindow.addPosition.first=Ierste OpenTorrentWindow.addPosition.last=L\u00e8ste TableColumn.header.remaining.info=Nog te downloade data TableColumn.header.remaining=Te gaon ConfigView.section.tracker.enablecompact=Compactmitdeilingsprotocol insjakele ConfigView.section.tracker.enablekey=Doorgaeve van sjleutel aan de tracker insjakele veur verbaeterde beveiliging ConfigView.section.file.perf=Prestatie-opties ConfigView.section.file.perf.explain=Waarsjuwing - \u00f3ngekwalificeerde verangeringe aan dees parameters kinne naodeilige effecte op de downloadprestaties h\u00f6bbe. Hersjtart vereis.\nEs se-n 'n "out of memory"-perbleem h\u00f6bs, euverwaeg dan 't aantal verb\u00e8njinge per torrent te limitere (Zuug euverdrachsk\u00f3ngfiggerasie) ConfigView.section.file.max_open_files.explain='t \u00c4\u00f6pene van te v\u00e4\u00f6l besjtenj kan perbleme oplevere mit 't besjturingssysteem door 'n gelimiteerd aantal br\u00f3nne veur besjtanjshanjelinge. Dit limiteert 't aantal tegeliek ge\u00e4\u00f6pende besjtenj. popup.error.hide=Verberge ConfigView.section.style.colorOverrides=Kleurinsjt\u00e8llinge ConfigView.section.style.colorOverride.progressBar=Veurtgangsbalk ConfigView.section.style.colorOverride.error=Fout MainWindow.status.tooOld=is te aud, update 't e.u.b. ConfigView.section.style.colorOverride.warning=Waarsjuwing ConfigView.section.style.colorOverride.altRow=Alternatieve rieje ConfigView.section.file.save.peers.enable=Peerverb\u00e8njinge beware veur sjnelle herverb\u00e8njing ConfigView.section.file.save.peers.max=Maximumaantal peers \u00f3m te beware [0: ongelimiteerd] ConfigView.label.max_peers_per_torrent=Maximum aantal connecties per torrent [0: ongelimiteerd] ConfigView.label.max_peers_total=Maximum aantal connecties globaal [0: ongelimiteerd] ConfigView.section.style.colorOverrides.reset=Kleur hersjt\u00e8lle ConfigView.section.language.info=Wen ingeschakeld, weurt op 'n update gek\u00f3nterleerd tiedes 't sjtarte van Vuze ConfigView.section.language.enableUpdate=Web-update insjakele ConfigView.section.language.UpdateNow=Update noe! Button.revert=Ongedaon make MyTorrentsView.menu.changeDirectory=Datamap verangere GenericText.column=kel\u00f3m MyTorrentsView.menu.thisColumn.remove=Kel\u00f3m weghaole MyTorrentsView.menu.thisColumn.toClipboard=Teks nao klembord kopi\u00ebre MyTorrentsView.menu.thisColumn.autoTooltip=Ummer moeshints laote zeen TableColumn.header.secondsseeding=Uploadtied TableColumn.header.secondsseeding.info=Tiedsdoer det-s te aan 't uploade b\u00f6s. TableColumn.header.secondsdownloading=Downloadtied TableColumn.header.secondsdownloading.info=Tiedsdoer det-s te aan 't downloade b\u00f6s. ConfigView.section.tracker.udpversion=UDP-protocolversie (1 of 2) window.updateswt.title=Dien SWT-versie is te aud! window.updateswt.text=Dien SWT-versie is te aud!\nSWT is de grafische bibliotheek dae Vuze gebroek, de versie die-s te h\u00f6bs is te aud \u00f3m de l\u00e8ste Vuze-versie te drieje. Klik op OK \u00f3m diene SWT te update. window.updateswt.status=Sjtatus window.updateswt.failed=Update misl\u00f6k, duuj opnuuj op OK \u00f3m te hersjtarte. window.updateswt.status.downloading.updater=Updatemodule aan 't downloade window.updateswt.status.finding=L\u00e8ste SWT-versie aan 't zeuke window.updateswt.status.downloading=L\u00e8ste SWT-versie aan 't downloade window.updateswt.status.done=Aan 't hersjtarte window.updateswt.ok=Ok window.updateswt.cancel=Aafbraeke swt.updater.downloader.downloading=SWT aan 't downloade van swt.updater.urlsgetter.downloading=Mirrorlies aan 't ophaole van swt.updater.urlsgetter.platform=SWT veur platform: window.updateswt.ignore=Negere ConfigView.section.style.useFancyTabs=Fancy Tabs gebroeke splash.initializeGM=Globaal torrentbehier aan 't laje splash.loadingTorrents=Torrents aan 't laje MyTorrentsView.menu.thisColumn.sort=&Sortere Scrape.status.error=Scrapefout: Scrape.status.error.badURL=Announce-URL volg neet de scrape specificaties. Scrape.status.error.nohash=Hash \u00f3ntbrik in antwaord. Scrape.status.error.invalid=\u00d3ngeljig antwaord. Scrape.status.nextScrapeAt=Volgende scrape op %1 Scrape.status.scraping=Aan 't scrape... Scrape.status.initializing=Wachte \u00f3m te scrape Scrape.status.scraping.queued=Scrape gesjtop... ConfigView.label.minSpeedForActiveSeeding=T\u00e8l aafger\u00f3nde torrents neet mit es de sjnelheid lieger is dan ConfigView.section.stats.exportpeers=Peer-details exportere MainWindow.menu.view.irc.moved=IRC is noe besjikbaar es 'ne plugin, laes http://vuze.sourceforge.net/plugin_list.php. Wen ge\u00efnstalleerd gebroek 't Plugins ->IRC-menu \u00f3m 't te \u00e4\u00f6pene. MyTrackerView.webui.contextmenu.copyurl=Torrent URL nao klembord kopi\u00ebre ConfigView.section.file.torrent.ignorefiles=Besjtenj \u00f3m te negere wen torrents gemaak waere\nwie: .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Besjtandj negere ConfigView.section.style.useUnitsRateBits=Gebroek bits in plaats van bytes veur byte-gebaseerde waerd (KiB/s->Kibit/s enz.) ConfigView.section.interface.resetassoc=Hersjt\u00e8l besjtandjsassociaties verk\u00e8nner (.torrent) ConfigView.section.interface.resetassocbutton=Hersjt\u00e8lle ConfigView.section.interface.checkassoc=Associaties k\u00f3nterlere tiedes opsjtarte dialog.associations.title=Associatiek\u00f3ntrol Button.yes=Jao Button.no=&Nei ConfigView.label.seeding.autoStart0Peers=Start alle vaerdige torrents autematis mit 0 seeders ConfigView.label.seeding.autoStart0Peers.tooltip=Sjakel in, es se wils det de tracker ummer seeds geuf veur torrents z\u00f3nger peers. dialog.associations.prompt=Vuze is neet 't sjtanderdprogram veur Bittorrent-besjtenj.\nWils se Vuze mit .torrent-besjtenj associ\u00ebre? dialog.associations.askagain=Tiedes opsjtarte k\u00f3nterlere ConfigView.section.plugins.update=Plugin Update. Plugin.pluginupdate.enablecheck=Plugin-updatek\u00f3ntrol insjakele plugins.basicview.status=Sjtatus: plugins.basicview.activity=Activiteit: plugins.basicview.progress=Veurtgank: plugins.basicview.log=Log: ConfigView.label.maxdownloadspeed=Globale maximum downloadsjnelheid in KB/s [0: ongelimiteerd] splash.loadingTorrent=Torrent aan 't laje splash.of=van UpdateWindow.title=Vuze-updater UpdateWindow.header=De volgende componenten h\u00f6bbe 'n update nudig: UpdateWindow.columns.install=Installere UpdateWindow.columns.name=Naam UpdateWindow.columns.version=Versie UpdateWindow.columns.size=Gruutde UpdateWindow.cancel=Aafbraeke UpdateWindow.quit=Aafsjloete UpdateWindow.close=Sjloete UpdateWindow.restart=Noe hersjtarte UpdateWindow.status.downloading=Downloade UpdateWindow.status.done=Vaerdig UpdateWindow.status.failed=Misl\u00f6k UpdateWindow.status.restartNeeded=Hersjtarte is vereis! ConfigView.pluginlist.broken=Defec ConfigView.pluginlist.whereToPut=Plaats alle gebroeker-specifieke plugins in h\u00e4\u00f6r eige map \u00f3nger: ConfigView.pluginlist.whereToPutOr=Gebroek veur gedeilde plugins: MainWindow.statusText.checking=Controleren op updates TableColumn.header.OnlyCDing4=Allein uploade TableColumn.header.OnlyCDing4.info=Tiedsdoer wo-in de torrent allein aan 't uploade waas.\nExclusief d'n tied det de torrent aan 't downloade waas (en uploade). ConfigView.section.style.alternateTablePainting=Gebroek 'n alternatieve methode \u00f3m grafische tabelkel\u00f3mme te teikene (kan hersjtart vereise) UpdateWindow.status.restartMaybeNeeded=Hersjtart kan vereis zeen ConfigView.pluginlist.shared=gedeild PeersView.host=Hostnaam PeersView.host.info=De hostnaam van de downloader, wo bescjikbaar (kan de prestaties be\u00efnvloede) MainWindow.menu.help.whatsnew=Waat is nuuj ConfigView.label.checkonstart=Op nuje versies k\u00f3nterlere wen Vuze sjtart ConfigView.label.periodiccheck=Periodiek k\u00f3nterlere op de l\u00e8ste versie ConfigView.label.opendialog=\u00c4\u00f6pen autematis de Update-assistent wen 'nen update besjikbaar is MainWindow.updateavail=Klik hie veur updates MainWindow.status.latestversionunchecked=Versiek\u00f3ntrol oetgezat GeneralView.label.updatein.stopped=Gesjtop StartStopRules.menu.viewDebug=Debuginfermatie ConfigView.section.style.doNotUseGB=Gebroek gein GB-einheid ConfigView.section.style.doNotUseGB.tooltip=Vuze z\u00f3l, wen aangevink, de MB's blieve broeke, zelfs es de greutte mie is dan 1024MB MainWindow.menu.help.plugins=Plugins ConfigView.section.plugins.TrackerWeb=Tracker Web. ConfigView.section.tracker.enablecategories=Torrents groepere op categorie health.explain.share=beteikent det de torrent gehost of gepubliceerd is ConfigView.section.tracker.createcert=Maak zelf\u00f3ngerteikend certificaat ConfigView.section.tracker.createbutton=Make security.certcreate.title=Zelf\u00f3ngerteikend certificaat make security.certcreate.intro=Deze dialoog leut dich 'n zelf\u00f3ngerteikend certificaat make security.certcreate.alias=Pseudoniem security.certcreate.strength=Sterkde security.certcreate.firstlastname=Veur- en achternaam security.certcreate.orgunit=Organisatie-einheid security.certcreate.org=Organisatie security.certcreate.city=Sjtad of sjtreek security.certcreate.state=Sjtaot of provincie security.certcreate.country=Twieletterige landjcode security.certcreate.ok=Make security.certcreate.cancel=Aafbraeke security.certcreate.createok=Certificaat vaerdig security.certcreate.createfail=Certificaat make misl\u00f6k ConfigView.section.plugins.webui=Swing Web Interface. ConfigView.section.plugins.xml_http_if=XML/HTTP Interface. webui.passwordenable=Wachwaord insjakele webui.user=Gebroekersnaam webui.password=Wachwaord webui.port=Paort (*) webui.homepage=Sjtartpazjena (*) webui.rootdir=Hoofmap (*) webui.rootres=Haofbr\u00f3n (*) webui.mode=Modus (*) webui.mode.info=Modus kan zeen:\n\t"full"\t";" alle operaties zeen toegankelik (sjtanderd)\n\t"view"\t= allein bekieke (meh kan vernuujfrequentie update) webui.access=Toegank (*) webui.access.info=Toegank kan zeen:\n\t"local"\t= allein 't lokaal werksjtation kan verb\u00e8nje\n\t"all"\t= \u00f3ngeregistreerde toegank (sjtanderd)\n\tIP\t= wie: 192.168.0.1\t\t1allein tone-IP\n\tIP1-IP2\t= wie: 192.168.0.1-192.168.0.255\tinclusief bereik van IP's GeneralView.label.maxdownloadspeed=Max. Down Security.keystore.corrupt=K\u00f3s de sjleutelreeks '%1' neet laje, haol 't estebleef weg en maak/importeer 't certificaat opnuuj Security.keystore.empty=Sjleutelreeks is laeg. Maak 'n zelf\u00f3ngerteikend certificaat (zuug Gereidsjappe -> K\u00f3ngfiggerasie -> Beveiliging) of importeer 'n besjtaond certificaat in '%1' webui.restart.info=Verangeringe aan parameters mit 'n (*) vereise 'ne hersjtart \u00f3m van krach te waere GeneralView.label.maxdownloadspeed.tooltip=Maximum downloadsjnelheid [0: ongelimiteerd] upnp.enable=UPnP insjakele upnp.info=Universele Plug and Play (UPnP) maak 't meugelik autematis paorte te mappen op UPnP-ingesjakelde routers. upnp.mapping.dataport=Ink\u00f3mmende peer-datapaort upnp.mapping.tcptrackerport=TCP-trackerpaort upnp.mapping.udptrackerport=UDP-trackerpaort upnp.alert.differenthost=UPnP: Mapping '%1' is gereserveerd door '%2' - selecteer 'n anger paort upnp.alert.mappingok=UPnP: Mapping '%1' ingesjt\u00e8ld upnp.alert.mappingfailed=UPnP: Mapping '%1' misl\u00f6k upnp.alertsuccess=Succesvolle mappings rappertere upnp.alert.lostdevice=UPnP: Verb\u00e8njing verlaore mit service '%1' op UPnP-apperaat '%2' upnp.grabports=Paorte mappe zelfs es dees van 'ne angere computer zeen upnp.refresh.label=De mappings vernuje upnp.refresh.button=Vernuje upnp.alert.mappinggrabbed=UPnP: Mapping '%1' ingesjt\u00e8ld - verkrege van '%2' upnp.mapping.tcpssltrackerport=TCP SSL-trackerpaort upnp.alertothermappings=Paorte van anger computers rappertere upnp.alertdeviceproblems=Perbleme mit 't UPnP-apperaat rappertere upnp.trace_to_log=Ganse debuginfermasie biehauwe upnp.wiki_link=Vuze Wiki-pazjena euver UPnP ConfigView.pluginlist.coreplugins=De volgende ingeboewde plugins zeen gelaje: Peers.column.DLedFromOthers=Van angere Peers.column.DLedFromOthers.info=Wiev\u00e4\u00f6lheid data gedownload van angere terwiel die verb\u00f3nje zeen mit dich Peers.column.UpDownRatio=Up/Down Peers.column.UpDownRatio.info=Leechers "Upload : Download"-verh. Peers.column.UpRatio=Uploadverh. Peers.column.UpRatio.info=Leechers "Upload van dich : Geupload van angere"-verh. upnp.releasemappings=De mappings vriegaeve en aafsjloete webui.upnpenable=UPnP insjakele veur dees paort (*) ConfigView.section.file.friendly.hashchecking=Vruntelikke hashk\u00f3ntrol ConfigView.section.file.friendly.hashchecking.tooltip='n Sjt\u00f6k lanksemmer, meh z\u00f6rgt veur minder belasting van de CPU, 't systeem en deilkes-hashk\u00f3ntrolmodus. ConfigView.section.tracker.seedretention=Maximumaantal uploads per torrent beperke [0: ongelimiteerd] ConfigView.section.tracker.seedretention.info=Opmirking: Uploadsjtatistieke rake verlaore veur neet-beperkde uploads ConfigView.section.tracker.port=Tracker op HTTP-paort insjakele ConfigView.section.tracker.sslport=Tracker op HTTPS-paort insjakele ConfigView.section.tracker.publicenable.info=Dit sjteit angere toe \u00f3m torrents te make die diene tracker broeke\nz\u00f3nger des doe ze hosts/publiceers Button.clear=Verwijdere MainWindow.IPs.tooltip=L\u00e8ste update van filterlies: %1\nTotaalaantal IP-filters in lies - Aantal geblokkeerde IP-adresse dees sessie.\nD\u00f6bbelklik veur details. ConfigView.section.ipfilter.list.banned=is verbanne veur 't sjikke van corrupte data ConfigView.section.ipfilter.list.baddata=haet corrupte data gesjik: veurval = Button.reset=Hersjt\u00e8lle ConfigView.section.ipfilter.bannedinfo=IP's die corrupte data h\u00f6bbe gesjik verbannen es de limiet is euversjrede ConfigView.section.ipfilter.blockedinfo=IP's die zeen geblokkeerd door IP-filters download.removerules.name=Weghaolregels download.removerules.unauthorised.info=\u00d3ngeautoriseerde torrents zeen torrents wo-in de mitgedeilde reactie\n"neet geautoriseerd" of "\u00f3ngeautoriseerd" in de "misl\u00f6kreactie" sjteit download.removerules.unauthorised=Haol ongeautoriseerde torrents autematis d'r vanaaf. download.removerules.unauthorised.seedingonly=\tAllein tiedes uploade download.removerules.removed.ok=Torrent '%1' autematis d'r vanaaf gehaold. Dit is oetgeveurd door de torrent-weghaolregels. download.removerules.updatetorrents=Vuze-updatetorrents oet de lies haole es de zjwerm dit vereis ConfigView.label.defaultstarttorrentsstopped=Voeg torrents sjtanderd in gesjtopte sjtatus toe ConfigView.section.server.enableudp=UDP-trackercli\u00ebntprotocol insjakele. Dit gebroek dezelfde paort es de TCP-server upnp.mapping.dataportudp=UDP-tracker-cli\u00ebntpaort ConfigView.section.file.decoder.showlax=Laot minder gebroekelikke coderinge zeen ConfigView.section.file.decoder.showall=Overwaeg alle m\u00e4\u00f6gelikke coderinge MainWindow.status.updowndetails.tooltip=Upload-/downloadsjnelheidsdetails - klik rechtermoes \u00f3m te verangere TrackerClient.announce.warningmessage=Tracker veur '%1' geuf waarsjuwing '%2' ConfigView.section.tracker.natcheckenable=K\u00f3nterleer 'ink\u00f3mmende datapaort'-verb\u00e8njingsmeugelikheid en rapporteer foute aan de peers ConfigView.section.tracker.publishenabledetails=Publiceer torrentbesjtandj en peerdetails ConfigView.section.tracker.publishenablepeerdetails=Publiceer downloaddetails MyTrackerView.badnat=Sjlechte NAT MyTrackerView.badnat.info=Seeders/Leechers die de NAT-k\u00f3ntrol gefaald h\u00f6bbe, es ingesjakeld ConfigView.section.tracker.natchecktimeout=K\u00f3ntrol-time-out (sek\u00f3nd) ConfigView.section.file.perf.cache.enable=Sjiefcache insjakele ConfigView.section.file.perf.cache.size=gruutde van cache in %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=Euve&rdrachte MainWindow.menu.transfers.startalltransfers=Alles sjt&arte MainWindow.menu.transfers.stopalltransfers=Alles sjt&oppe MainWindow.menu.transfers.pausetransfers=&Pauzere MainWindow.menu.transfers.resumetransfers=Wieje&r gaon ConfigView.label.experimental.osx.kernel.panic.fix=Experimentele oplossing veur kernelprobleme op dual processor OSX systemen [hersjtart vereis] SystemTray.menu.pausetransfers=Euverdrachte pauzere SystemTray.menu.resumetransfers=Euverdrachte hervatte ConfigView.section.file.truncate.too.large=Kap besjtaonde besjtenj die te groet zeen aaf ConfigView.section.file.perf.cache.trace=Traceer cache-operaties veur diagnostische doelinj ConfigView.section.interface.enabletray=Sjakel systeemvak in [hersjtart vereis] PeerManager.status.error=Fout Stats.title.full=Sjtatistieke TransferStatsView.title.full=Dataverkier CacheView.general.size=Totale gruutde CacheView.general.inUse=In gebroek CacheView.general.title=Cache-infermatie CacheView.reads.title=I/O-laesbew\u00e8rkinge CacheView.reads.fromFile=Van besjtandj CacheView.reads.fromCache=Van cache CacheView.writes.title=I/O-sjriefbew\u00e8rkinge CacheView.writes.toCache=Nao cache CacheView.writes.toFile=Nao besjtandj CacheView.writes.hits=Hits CacheView.speeds.title=Datasnelhede CacheView.speeds.reads=Laesbew\u00e8rkinge CacheView.speeds.writes=Sjriefbew\u00e8rkinge CacheView.speeds.fromCache=Van/nao cache CacheView.speeds.fromFile=Van/nao besjtandj CacheView.reads.#=Nr: CacheView.reads.amount=Aantal CacheView.reads.avgsize=Gemiddelde gruutde openUrl.referrer=URL-paginaverwiezing: openUrl.referrer.info=Alleen vereis veur websites die dit aafdwinge ConfigView.label.maxuploadspeedseeding=Globaal maximum uploadsjnelheid wen d'r allein weurt geupload in KB/s [0: ongelimiteerd] ConfigView.label.transfer.ignorepeerports=Negeer leechers mit de volgende datapaorte (gescheie mit ';') wie: 0;25) ConfigView.section.proxy.enable_socks.peer=Sjakel proxy veur peer-communicaties in (Allein oetgaonde verb\u00e8njinge) [hersjtart vereis] ConfigView.section.proxy.peer.informtracker=Informeer tracker euver beperking ConfigView.section.proxy.socks.version=SOCKS-versie PiecesView.legend.written=Weggesjreve PiecesView.legend.requested=Aangevraog PiecesView.legend.downloaded=Gedownload,\n nog neet weggesjreve PiecesView.legend.incache=Data is in de cache PiecesView.typeItem.0=Lanksem PiecesView.typeItem.1=Hel Security.jar.tools_not_found=JAR-\u00f3ngerteikening misl\u00f6k - 'tools.jar' neet gev\u00f3njen in %1. Zuug Gereidsjappe -> K\u00f3ngfiggerasie -> Beveiliging veur details. Security.jar.signfail=JAR-\u00f3ngerteikening misl\u00f6k - %1 ConfigView.section.security.toolsinfo=\u00d3ngerteikende JAR-besjtenj waere gebroek \u00f3m sommige plugins wie de Swing Web Interface \n(wen geconfigureerd) te \u00f3ngersteune.\nOm JAR-besjtenj te \u00f3nderteikene, is 't noedwendig toegank te h\u00f6bbe t\u00f3t 't 'tools.jar'-besjtandj.\nDit besjtandj weurt mitgeleverd mit de Sun JDG-installatie (neet JRE).\nEs se allein de JRE h\u00f6bs ge\u00efnstalleerd, m\u00f3s se de JDK installere.\nVuze kan dit besjtandj veur dich v\u00e8nje, es dit neet l\u00f6k, k\u00f3ns se hie esnog de map aangaeve. ConfigView.section.security.toolsdir=Locatie van 'tools.jar' ConfigView.section.security.choosetoolssavedir=Selecteer de map mit 'tools.jar' authenticator.torrent=Torrent ConfigView.section.proxy.peer.same=Gebroek dezelfde proxy-insjt\u00e8llinge veur tracker en peercommunicatie proxy ConfigView.section.connection.network.max.simultaneous.connect.attempts=Maximum geliektiedige oetgaonde verb\u00e8njingspoginge [0: oetgesjakeld] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Maximumaantal nuje oetgaonde verb\u00e8njinge die Vuze op jeder mem\u00e8nt kan make.\nOpmirking: Windows XP Service Pack 2 (SP2) bevat 'n limiet van 10 geliektiedige verb\u00e8njingspoginge euver 't ganse systeem.\nSjtanderdwaerd is 8. 'n Waerde van 0 sjakelt dit volledig oet. ConfigView.section.file.perf.cache.size.explain=De cache weurt gebroek \u00f3m 't aantal sjiefbewirkinge te verkleine. Behauve es se de java-optie '- XX:MaxDirectMemorySize' gebroeks \u00f3m 't geheugen speciaal veur cache en netwerk-IO te gebroeke, m\u00f3s se dees waerd r\u00f3ndj %1 \u00f3nger dien maximum VM-gruutde hauwe. De hujige maximum VM-greutte is %2. Laes MemoryUsage in de Wiki op %3 \u00f3m te zeen wie dit aangepas kan waere. Onversjtenjige insjt\u00e8llinge kinne leije t\u00f3t 'out of memory'-foute. Mie es 32MB cache is waarsjienlik euverkil. MyTorrentsView.menu.setSpeed.unlimit=Gein limiet MyTorrentsView.menu.setSpeed.unlimited=Ongelimiteerd MyTorrentsView.menu.setSpeed.disable=Upload oetsjakele MyTorrentsView.menu.setSpeed.disabled=Oetgesjakeld MyTorrentsView.menu.setSpeed.slots=sjlaote van GeneralView.label.maxuploadspeed=Max. Up GeneralView.label.maxuploadspeed.tooltip=Maximum uploadsjnelheid [0 : ongelimiteerd] MyTorrents.items.UpSpeedLimit.disabled=G\u00e8nnen upload MyTorrents.items.UpSpeedLimit.unlimited=\u00d3ngelimiteerd TableColumn.header.maxupspeed=Max. uploadsjnelheid TableColumn.header.maxupspeed.info=Max. uploadsjnelheid per torrent ConfigView.section.file.perf.cache.enable.write=Data gecache downloade \u00f3m 't aantal sjriefbewirkinge te verkleinen en laesbewirkinge veur sjt\u00f6kskesk\u00f3ntrol te verkleine ConfigView.section.file.perf.cache.enable.read=Sjakel veuroet-laezen in, \u00f3m sjiefactiviteit tiedes 't uploade te vermindere ConfigView.section.tracker.separatepeerids=Gebroek versjillende peer-identiteite veur tracker- en datacommunicatie ConfigView.section.tracker.separatepeerids.info=Verhoeg anonimiteit tiedes anoniem downloade/uploade\nterwiel se-n 'n neet-anonieme trackerverb\u00e8njing broeks ConfigView.section.interface.wavlocation=Locatie van .wav-besjtandj ConfigView.section.interface.wavlocation.info=Selecteer 'n .wav-besjtandj of laot dit laeg veur 't sjtanderdgeluid ConfigView.section.tracker.client=Cli\u00ebnt ConfigView.section.tracker.client.connecttimeout=Connectie-time-out (sek\u00f3nd) ConfigView.section.tracker.client.readtimeout=Laes-time-out (sek\u00f3nd) MainWindow.menu.tools=&Gereidsjappe FilesView.path=Paad FilesView.fullpath=Gans paad laote zeen FilesView.remaining=Sjt\u00f6kskes te gaon TableColumn.header.trackername=Trackernaam TableColumn.header.trackername.info=Naam van de tracker gebaseerd op de mitgedeilde URL ConfigView.group.override=Euverbr\u00f6k-opties ConfigView.section.file.perf.cache.notsmallerthan=Cache gein besjtenj die kl\u00e8nder zeen es dit (in %1) PeersView.menu.blockupload=Upload blokkere PeersView.menu.kickandban=Kicke en Banne PeersView.menu.kickandban.reason=Peer handjmaotig verbanne PeersView.state=Sjtatus PeersView.state.info=Sjtatus van de peerverb\u00e8njing PeersView.state.pending=Hangend PeersView.state.connecting=Bezig mit verb\u00e8nje PeersView.state.handshake=Wachten op handshake PeersView.state.established=Gans verb\u00f3nje ConfigView.section.tracker.processinglimits=Verwirking limiete ConfigView.section.tracker.maxgettime=Max. tied veur GET-verwerking (sek\u00f3nd) [0: ongelimiteerd] ConfigView.section.tracker.maxgettime.info=Gebroek voor mitdeilinge en scrapes ConfigView.section.tracker.maxposttimemultiplier=GET-tied vermenigvuldigingsfactor veur POST-verwerking [0: ongelimiteerd] ConfigView.section.tracker.maxposttimemultiplier.info=Gebroek veur formeleerverzendinge en uploads ConfigView.section.tracker.maxthreads=Max. gezamenlijke verzeuke DownloadManager.error.operationcancancelled=Operatie geannuleerd Torrent.create.progress.cancelled=Bewirking aafgebraoke sharing.progress.cancel=Aafbraeke wizard.maketorrents.autoopen=De torrent \u00e4\u00f6pene veur uploade wen vaerdig ConfigView.section.sharing.rescanenable=Periodiek herscannen insjakele veur verangeringe ConfigView.section.sharing.rescanperiod=Herscanperiode (sek\u00f3nd) ConfigView.section.connection.advanced=Geavanceerde Netwerkinst\u00e8llinge ConfigView.section.connection.advanced.mtu=Lien maximumeuverdrachseinheid (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Maximumgruutde van 'n pakket det verz\u00f3nje kan waere in 1 frame euver 'n netwerk.\nVuze gebroek MTU-40 (MSS) veur uploadpakket-payload-optimalisaties.\nAanbevaole waerdes:\n 576 - Telefoonverb\u00e8njingen\n1792 - PPPoE-breidbandjverb\u00e8njinge\n1500 - Ethernet-, DSL- en kabel-breidbandjverb\u00e8njinge ConfigView.section.connection.advanced.SO_RCVBUF=Socket SO_RCVBUF-gruutde [0: gebroek OS-sjtanderd] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Sjt\u00e8lt de sjtanderdsocket SO_RCVBUF waerde (in bytes) in, wie TCP \u00f3ntvangv\u00e8nstergruutde en sjaol.\nVuze leut dit sjtanderd \u00f3ning\u00e8steld, dit beteikent det de sjtanderd OS-inst\u00e8llinge waere gebroek.\nOpmirking: Linux verdubbelt de gegaeve waerd. ConfigView.section.connection.advanced.SO_SNDBUF=Socket SO_SNDBUF-gruutde [0: gebroek OS-sjtanderd] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Sjtelt de sjtanderdsocket SO_SNDBUF waerde (in bytes) in, wie TCP \u00f3ntvangv\u00e8nstergruutde en sjaol.\nVuze leut dit sjtanderd \u00f3ning\u00e8steld, dit beteikent det de sjtanderd OS-inst\u00e8llinge waere gebroek.\nOpmirking: Linux verdubbelt de gegaeve waerd. ConfigView.section.connection.advanced.IPDiffServ=Oetg\u00e4\u00f6ndj pakket DiffServ waerd (TOS veldj) ConfigView.section.connection.advanced.IPDiffServ.tooltip=Sjt\u00e8lt 't DiffServ-deil in van 't type-of-service(TOS)-veldj in de IP header veur oetgaonde pakkette.\nHexadecimaal waerdes kinne gespecificeerd waere door deze te veuraaf te laote gaon mit '0x', bv. 0x10.\nVuze leut dit sjtanderd ongebroek, dit beteikent det de sjtanderd van 't \u00f3ngerlikgend OS weurt gebroek.\nOpmirking: \u00d3ngerligkende netwerkimplmentaties kinne dees waerdes negere, dus dees optie is afhankelik van 't OS en JRE-versie. ConfigView.section.interface.confirm_torrent_removal=Bevestigingsv\u00e8nster laote zeen es torrent d'r vanaaf weurt gehaold ConfigView.section.interface.confirm_torrent_removal.tooltip=Bevestig wen 'n torrent oet Mien Torrents weurt weggehaold. TableColumn.header.seed_to_peer_ratio=Seed2Peer-verh. TableColumn.header.seed_to_peer_ratio.info=Totale zjwerm-seeders-nao-leechers-verhaajing PeersView.connected_time=Verb\u00f3nje tied PeersView.connected_time.info=Totale tied verb\u00f3nje mit de peer ConfigView.section.interface.display.add_torrents_silently=Voeg torrents sjtil toe ConfigView.section.interface.display.add_torrents_silently.tooltip=Voeg torrent downloads toe, z\u00f3nger 't hoofv\u00e8nster te activere. TableColumn.header.maxdownspeed=Max. downloadsjnelheid TableColumn.header.maxdownspeed.info=Max. downloadsjnelheid per torrent PeersGraphicView.title=Zjwerm ConfigView.section.tracker.passwordwebhttpsonly=Sjtaon toegank allein toe via HTTPS TableColumn.header.torrentpath=Torrentlocatie TableColumn.header.torrentpath.info=Locatie van de torrent op de sjief ConfigView.section.sharing.torrentcomment=Opmirking veur gegenereerde torrents. ConfigView.label.copyanddeleteratherthanmove=Kopi\u00ebre en verwijdere van de originele data, in plaats van dees te verplaatse - kan helpe dataverlies te veurk\u00f3mme op s\u00f3mmige bestanjssysteme ConfigView.label.openstatsonstart=\u00c4open sjtatistieke tiedes 't starte swt.install.window.title=Vuze Plug-in-installatie swt.install.window.ok=Installere swt.install.window.header=De volgende componente zeen geselecteerd veur installatie: swt.uninstall.window.title=Vuze Plug-in-de\u00efnstallatie swt.uninstall.window.ok=Weghaole swt.uninstall.window.header=De volgende componenten zeen geselecteerd om weg te haole: installPluginsWizard.title=Plugins installere installPluginsWizard.mode.title=Kees 'n installatiemethode installPluginsWizard.mode.list=Oet een lies van sourceforge.net installPluginsWizard.list.title=Installeerbare Plugin-lies installPluginsWizard.list.loading='n Ougeblik ged\u00f6ldj t\u00f3t de Plugin-lies gelajen is. installPluginsWizard.list.loaded=Kees de plugins die se wils installere. installPluginsWizard.list.name=Naam installPluginsWizard.list.version=Versie installPluginsWizard.list.description=Plugins-besjrieving installPluginsWizard.finish.title=Bezig mit installere installPluginsWizard.finish.explanation=De geselecteerde Plugins waere ge\u00efnstalleerd door de Update-assistent.\n\n'n Ougeblik ged\u00f6ldj, 't kan 'n tiedje doere veur dees versjiene.\n\nD\u00f6bbelklik op de sjtatusbalk veur 't veurtganksreport. installPluginsWizard.details.loading=Details waere gelaje, 'n ougeblik ged\u00f6ldj.... installPluginsWizard.mode.file=Oet besjtandj installPluginsWizard.installMode.title=Kees 't installatietype installPluginsWizard.installMode.user=Installeer de plugin(s) allein veur deze gebroeker installPluginsWizard.installMode.shared=Installeer de plugin(s) veur alle gebroekers installPluginsWizard.file.title=Zeuk de plugin dae se wils installere installPluginsWizard.file.file=Besjtandj: installPluginsWizard.file.invalidfile=Dit besjtandj is gein geljige Vuze-plugin. installPluginsWizard.file.no_such_file='t Besjtandj mit de opgegaeve naam besjteit neet. installPluginsWizard.file.browse=Blajere... uninstallPluginsWizard.title=Plug-ins de\u00efnstallere uninstallPluginsWizard.list.title=Ge\u00efnstalleerde Plug-in-lies uninstallPluginsWizard.list.loaded=Kees de plugins die-s te wils de\u00efnstallere. installPluginsWizard.list.nullversion=Gei versie uninstallPluginsWizard.finish.title=Bezig mit de de\u00efnstallatie uninstallPluginsWizard.finish.explanation=De geselecteerde Plugins waere gede\u00efnstalleerd door de Update-assistent. MainWindow.menu.plugins.installPlugins=Installatiewizard... MainWindow.menu.plugins.uninstallPlugins=Uninstallatiewizard... ConfigView.section.ipfilter.totalIPs=%1 IP's geblokkeerd in totaal, det is %2 van 't internet. update.instance.install=Installatie controlere update.instance.uninstall=De\u00efnstallatie controlere update.instance.update=Controlere op updates MainWindow.status.update.tooltip=D\u00f6bbelklik veur veurtganksinfermatie updater.progress.window.title=Hujige installatietake updater.progress.window.info=Duuj op 'Aafbraeke' \u00f3m alle oetsjtaonde take te be\u00ebindige Button.abort=Aafbraeke ConfigView.section.ipfilter.enablebanning=Blokkeer seeders die constant corrupte data sjikke Network.alert.acceptfail=Te v\u00e4\u00f6l opeinvolgende misl\u00f6kkinge op paort %1, %2 - verwirking gesjtop. K\u00f3nterleer dien Firewall-insjt\u00e8llinge veur dees paort \u00f3m zeker te zeen det deze is ingesjt\u00e8ld veur 't \u00f3ntvange van verb\u00e8ndinge. MyShares.column.category=Categorie UpdateWindow.restartLater=Later hersjtarte MainWindow.menu.file.restart=Vuze hersjtarte MainWindow.dialog.restartconfirmation.title=Vuze opnuuj opsjtarte MainWindow.dialog.restartconfirmation.text=W\u00e8ts je zeker des se Vuze opnuuj wils opsjtarte? deletetorrent.message1=Doe sjteis op 't puntj de TORRENT weg te haole veur :\n deletetorrent.message2=\nW\u00e8ts se zeker des se wiejer wils gaon? ConfigView.label.prioritizemostcompletedfiles=Gaef veurrang mit hoeg prioriteit aan besjtenj volges % compleet en de gruutde van 't besjtandj splash.plugin.init=Plugin initialisere: splash.plugin.UIinit=Plug-in GUI aan 't laje: %1 ConfigView.section.style.osx_small_fonts=Broek klein lettertype [hersjtart vereis] ConfigView.section.tracker.tcpnonblocking=Gebroek neet-blokkerende I/O veur TCP-trackerverwirking. 't Selectere van dees optie vereis det de trackerweb op 'n alternatieve paort driejt. Experimenteel! ConfigView.section.tracker.nonblocking=Neet-blokkeer-opties ConfigView.section.tracker.nonblockingconcmax=Max. gezamenlijke verb\u00e8njinge [0: ongelimiteerd] MyTorrentsView.menu.exportmenu=Exportere ConfigView.group.scrape=K\u00f3ntrol ConfigView.section.tracker.client.scrapeinfo='t Oetsjakele van scraping z\u00f3l veurk\u00f3mme det v\u00e4\u00f6l van de torrentwachrieregels wirke, \u00f3mdet dees infermatie vereise die verkrege weurt door 't scrape van trackers. ConfigView.section.tracker.client.scrapeenable=Scraping insjakele ConfigView.section.tracker.client.scrapestoppedenable=Scrape torrents die neet drieje Scrape.status.disabled=Scrape oetgesjakeld MyTorrentsView.menu.explore=Besjtandj laote zeen MyTorrentsView.menu.explore._mac=In Finder laote zeen MyTorrentsView.menu.explore._windows=In verk\u00e8nner laote zeen wizard.maketorrents.autohost=De torrent hoste op de ingeboewde tracker ConfigView.label.overrideip=Vervang tracker annouce-IP(s) - gebroek ; es d'r mier verjillende netwerke zeen ConfigView.label.overrideip.tooltip=Informeer de tracker van ander(e) IP adres(sen) dan het adres waar uitgaande pakketjes vandaan komen. Laat de optie leeg als je deze niet wil gebruiken. ConfigView.section.connection.group.networks=Netwerke ConfigView.section.connection.group.networks.info=Selecteer de sjtanderd toegesjtaone netwerke veur peer-peer data-euverdrach ConfigView.section.connection.networks.prompt=Vraog \u00f3m 'n selectie wen 'n download mit 'nen anonieme tracker is toegevoeg ConfigView.section.connection.networks.Public=Publiek IP-netwerk (neet anoniem) ConfigView.section.connection.networks.I2P=I2P-netwerk ConfigView.section.connection.networks.Tor='t Onion Router (Tor) netwerk TableColumn.header.networks=Netwerke TableColumn.header.networks.info=Netwerke toegesjtaan veur peer-peer-datacommunicatie Scrape.status.networkdisabled=Netwerke neet ingesjakeld ConfigView.section.tracker.server.group.networks=Netwerken ConfigView.section.tracker.server.group.networks.info=Selecteer de netwerken waarvan de tracker peers accepteert window.networkselection.title=Netwerkselectie window.networkselection.info=De torrent hie-\u00f3nger haet tracker(s) die de volgende netwerke \u00f3ngersteune.\nSelecteer de protocolle veur tracker- en peercommunicatie.\nEs 't 'ne anonieme tracker is dae publieke cli\u00ebnts \u00f3ngersteunt, sjakel dan zoewaal de anonieme es publieke netwerke in.\nInsjakele van 'n publiek netwerk haet allich es consequentie det de anonimiteit weurt weggehaold! window.networkselection.description=Torrent: plugins.basicview.clear=Laegmake ConfigView.section.connection.group.peersources=Peerbr\u00f3nne ConfigView.section.connection.group.peersources.info=Selecteer de sjtanderd toegesjtaone br\u00f3nne veur peerverb\u00e8njinge ConfigView.section.connection.peersource.Tracker=Van 'ne tracker ConfigView.section.connection.peersource.DHT=Ongecentraliseerde tracking ConfigView.section.connection.peersource.PeerExchange=Geleverd door 'nen angere downloader ConfigView.section.connection.peersource.Plugin=Toegevoeg door 'ne plugin ConfigView.section.connection.peersource.Incoming=Ink\u00f3mmende verb\u00e8njing PeersView.source=Br\u00f3n PeersView.source.info=De br\u00f3n van deze downloader TableColumn.header.peersources=Leechers Bronnen TableColumn.header.peersources.info=Leechersbr\u00f3nne toegesjtaon veur 't make van peerverb\u00e8njinge wizard.tracker.dht=Ongecentraliseerd (allein Vuze-cli\u00ebnte) MyTorrentsView.menu.advancedmenu=Geavanceerd MyTorrentsView.menu.networks=Netwerke MyTorrentsView.menu.peersource=Peerbr\u00f3nne ConfigView.section.sharing.permitdht=\u00d3ngecentraliseerde tracking toesjtaon wen 'ne tracker neet besjikbaar is ConfigView.section.sharing.protocol=Protocol veur gedeilde br\u00f3nne PeersView.Messaging=Communicere PeersView.Messaging.info=\u00d3ngersteunt geavanceerde communicatie-API. ConfigView.label.queue.newseedsmovetop=Verplaats nuje complete torrents nao 't begin van de uploadlies ConfigView.label.seeding.firstPriority.ignore.info='t Gebruik van deze regels kan d'r veur z\u00f6rge det 'n torrent\nsjtop es de download vaerdig is. ConfigView.label.seeding.firstPriority.ignore=Negeer Ierste Prioriteit-regels hiebaove veur: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents mit een upload-nao-download-verhauwing baove ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents mit 0 Leechers ConfigView.section.tracker.sendjavaversionandos=Sjik Java-versie en besjturingssysteemnaam MagnetPlugin.contextmenu.exporturi=Magneet-URI nao klembord kopi\u00ebre ConfigView.section.plugins.dht=Versjpreide database dht.info=Deze plugin ondersteunt \u00f3nger angere \u00f3ngecentraliseerde tracking.\n't Oetsjakele hievan z\u00f3l eure downloadmeugelikhede verkleine. dht.enabled=De verspreide database insjakele dht.portdefault=De sjtanderdpaort gebroeke dht.port=UDP-paort veur de database dht.execute.command=Diagnosecommando dht.execute.info=Duuj \u00f3m 't commando oet te veure dht.execute=Oetveure dht.logging=Tracere van activiteit insjakele ConfigView.section.plugins.dhttracker=Versjpreide tracker dhttracker.tracknormalwhenoffline=Traceer allein normale torrents wen h\u00e4\u00f6re tracker neet besjikbaar is ConfigView.section.file.nativedelete._mac=Gebroek pr\u00f6llebak wen besjtenj d'r vanaaf waere gehaold ConfigView.section.file.nativedelete._windows=Verplaats gewiste besjtenj nao de Pr\u00f6llebak ConfigView.section.logging.generatediagnostics=Generere ConfigView.section.logging.netinfo=Netwerkinfermatie generere ConfigView.section.logging.statsinfo=Statistische infermatie generere ConfigView.section.logging.generatediagnostics.info=Genereer diagnostische infermatie en kopieer die nao 't klembord en 'n log-besjtandj, es dit ingesjt\u00e8ld is ConfigView.section.sharing.privatetorrent=Priv\u00e9-torrent - accepteert allein downloaders van de tracker MainWindow.menu.tools.nattest=&NAT/Firewall-tes Button.apply=Toepasse Button.close=Sjloete window.welcome.title=Welk\u00f3m bie Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Versiedetails dht.reseed.label=Normaal is 't opnuuj seede van de Verspreide Database neet noedwendig. Es 't aantal contacte lieg is, kan dit gebroek waere veur herintegratie.\nLaot laeg \u00f3m mit verb\u00f3nje peers te deile, of v\u00f6l 'n IP en paort in \u00f3m te seede aan 'n bekende peer. dht.reseed.group=Opnuuj seede dht.reseed.ip=IP-adres dht.reseed.port=Paort dht.reseed=Opnuuj seede dht.reseed.info=De database opnuuj uploade dht.diagnostics.group=Diagnose DHTView.title.full=Versjpreide database DHTView.title.fullcvs=Versjpreide database CVS DHTView.general.title=Algemein DHTView.general.uptime=On-line tied: DHTView.general.users=Gebroekers: DHTView.general.contacts=K\u00f3ntakte: DHTView.general.replacements=Vervanginge: DHTView.general.live=Laeve: DHTView.general.unknown=\u00d3nbek\u00e8ndj: DHTView.general.dying=Sjtervend: DHTView.transport.title=Transportdetails DHTView.transport.packets=Pakketjes DHTView.transport.received=\u00d3ntvange DHTView.transport.sent=Gesjik DHTView.transport.in=In: DHTView.transport.out=Oet: DHTView.operations.title=Operatiedetails DHTView.operations.sent=Gesjik DHTView.operations.ok=OK DHTView.operations.failed=Misl\u00f6k DHTView.operations.received=\u00d3ntvange DHTView.operations.ping=Pinge DHTView.operations.findNode=Node zeuke DHTView.operations.findValue=Waerd zeuke DHTView.operations.store=Opsjlaag DHTView.activity.title=Activiteit DHTView.activity.status.true=Gesjtop DHTView.activity.status.false=Bezig DHTView.activity.type.1=Interne \u00f3ntvangs DHTView.activity.type.2=Externe \u00f3ntvangs DHTView.activity.type.3=Interne plaatsing DHTView.activity.type.4=Externe plaatsing DHTView.activity.target=Doel DHTView.db.keys=Sjleutels DHTView.db.values=Waerd DHTView.db.local=Lokaal DHTView.db.direct=Direk DHTView.db.indirect=Indirek DHTView.db.divfreq=Freq.-versjil DHTView.db.divsize=Gruutdeversjil MainWindow.dht.status.tooltip=Wen de Verspreide Database driejt, weurt hie 't gesjatte aantal gebroekers det on-line is aangegaeve. MainWindow.dht.status.disabled=DDB oetgesjakeld MainWindow.dht.status.failed=Misl\u00f6k MainWindow.dht.status.initializing=Initialisere MainWindow.dht.status.users=%1 gebroekers MainWindow.dht.status.unreachable=DHT ge-firewalld MainWindow.dht.status.unreachabletooltip=D'r bliek 'n perbleem te zeen mit de UDP-paortmapping van de verspreide database MyTorrentsView.menu.setUpSpeed=Uploadsjnelheid verangere MyTorrentsView.menu.setDownSpeed=Downloadsjnelheid verangere ConfigView.section.tracker.client.showwarnings=Laot waarsjuwberichte zeen gerapperteerd door trackers dht.advanced=Geavanceerde insjt\u00e8llinge insjakele dht.advanced.group=Geavanceerde insjt\u00e8llinge dht.advanced.label=Veranger dees waerd allein es se w\u00e8ts waat se duis dht.override.ip=Externe IP-adresse vervange ConfigView.section.logging.loggerenable=Logging insjakele ConfigView.section.ipfilter.blockbanning=Ban 'n blok van 256 adresse, wen minstens 't volgende aantal in det blok is verbanne MyTrackerView.passive=Passief TableColumn.header.swarm_average_speed=Gem. zjwermsjnelheid TableColumn.header.swarm_average_speed.info=De gemiddelde sjnelheid van peers in de zjwerm TableColumn.header.comment=K\u00f3mmentaar TableColumn.header.comment.info=Door gebroeker gedefinieerd k\u00f3mmentaar veur deze download TableColumn.header.commenticon=K\u00f3mmentaaricoon TableColumn.header.commenticon.info=Laot 't icoon zeen es gebroekerscommentaar bie de torrent geplaats is. MyTrackerView.category=Categorie MainWindow.menu.file.open.torrentfortracking=Torrent-besjtandj... (allein tracking) MyTrackerView.date_added=Toegevoeg ConfigView.section.tracker.portbackup=Backuppaorte ( gesjeije door ; ) ConfigView.label.playfilespeech=Kal es 'n besjtandj vaerdig is ConfigView.label.playfilespeech.info=De Sjpraokservice wirk 't b\u00e8ste mit Ingels ConfigView.label.playfilefinished=Sjpeel 'n geluid/meziekske es 'n sjt\u00f6kske van 't besjtandj vaerdig is ConfigView.label.backupconfigfiles=Backupk\u00f3ngfiggerasiebesjtenj veur hersjt\u00e8lopties ConfigView.section.tracker.client.scrapesingleonly=Per-tracker scrape-aggregatie oetz\u00e8tte (kan helpe bie trackers die rapportere det de 'URL te lank is ' (414) foute) dht.ipfilter.log=IP-filtereuvertraejinge logge ConfigView.label.seeding.addForSeedingDLCopyCount=Besjoew 'toevoegen veur seeden'-downloads of ze dit aantal kopie\u00eb h\u00f6bbe gedownload ActivityView.legend.limit=Sjnelheidslimiet ActivityView.legend.achieved=Sjnelheidsbereik ActivityView.legend.overhead=Algemeine beoerdeiling ActivityView.legend.peeraverage=Gemiddeld ActivityView.legend.swarmaverage=Zwerm gemiddelde ActivityView.legend.trimmed=Op orde gezat (gesjtippeld) MyTorrentsView.menu.movemenu=Besjtenj verplaatse MyTorrentsView.menu.movedata=Databesjtenj verplaatse... MyTorrentsView.menu.movetorrent=Torrentbesjtandj verplaatse... MyTorrentsView.menu.movedata.dialog=Kees nuuj locatie DHTView.general.reachable=Bereikbaar: DHTView.general.rendezvous=Aafsjpraoke: ConfigView.label.queue.maxactivetorrentswhenseeding=Max. bie allein seede [0:ongelimiteerd] Views.plugins.IRC.title=IRC - Online technische \u00f3ngersteuning Formats.units.persec=/sek. Formats.units.alot=Hiel v\u00e4\u00f6l! ConfigView.section.ipfilter.persistblocking=Bewaar geblokkeerde IP-details tiedes hersjtart FilesView.menu.rename=Herneume of verplaatse FilesView.menu.rename_only=Herneume FilesView.menu.retarget=Besjtenj verplaatse FilesView.rename.choose.path=Kees nuuj of besjtaond besjtandj FilesView.rename.choose.path.dir=Kees 'ne nuje of besjtaonde map FilesView.rename.confirm.delete.title=Weghaole bevestige FilesView.rename.confirm.delete.text=Bevestig weghaole van 't origineel besjtandj '%1' FilesView.rename.filename.title=Besjtandj herneume FilesView.rename.filename.text=Kees 'ne nuje naam veur 't besjtandj ConfigView.higher.mode.available=Mier opties zeen besjikbaar in hoeger gebroekersmodes. ConfigView.section.mode=Modus ConfigView.section.mode.title=Gebroekerskinnes ConfigView.section.mode.beginner=Beginner. ConfigView.section.mode.beginner.wiki.definitions=Bittorrentwaordebook (in 't Ingels) ConfigView.section.mode.intermediate=Gevorderd (behier tracker) ConfigView.section.mode.intermediate.wiki.host=Hoste van besjtenj ConfigView.section.mode.intermediate.wiki.publish=Publicere van besjtenj ConfigView.section.mode.advanced=Experts (behier tracker en netwerk) ConfigView.section.mode.advanced.wiki.main=Wikihoofpazjena ConfigView.section.mode.beginner.text=Allein waat se nudig h\u00f6bs \u00f3m torrents te downloade.\nGebroek dees modus \u00f3m allein dien torrents te behiere. ConfigView.section.mode.intermediate.text=Toegank t\u00f3t trackerfuncties.\nGebroek dees modus es se zelf de ingeboewde tracker wils gebroeke en dien besjtenj wils hoste/publicere. ConfigView.section.mode.advanced.text=Toegank t\u00f3t netwerkinsjt\u00e8llinge.\nGebroek dees modus es se w\u00e8ts waat MTU en non blocking I/O zeen... Files.column.storagetype=Opsjlaagtype FileItem.storage.linear=Lineair FileItem.storage.compact=Kompakt MessageBoxWindow.rememberdecision=Mien besjlissing beware ConfigView.section.interface.cleardecisions=De bewaarde dialoogbesjloete vergaete ConfigView.section.interface.cleardecisionsbutton=Vergaete ConfigView.section.interface.cleartrackers=De bewaarde trackers vergaete ConfigView.section.interface.cleartrackersbutton=Vergaete ConfigView.section.interface.clearsavepaths=De bewaarde opgjslaagpajer vergaete ConfigView.section.interface.clearsavepathsbutton=Vergaete configureWizard.welcome.usermodes=Dees Gebruiker-Vaardigheidsinst\u00e8lling bepaolt 't niveau van de opties te zeen in Gereidjsappe > K\u00f3ngfiggerasie. 't Is in dien eige belang dit good in te st\u00e8lle. FilesView.skip.confirm.delete.text=Besjtandj '%1' aafkappe \u00f3m ruumde te spare? FilesView.rename.failed.title=Herneume/verplaatsing misl\u00f6k FilesView.rename.failed.text=De bewirking misl\u00f6kde, waarsjienlik door 'n foute keuze van 't doel diagnostics.log_found=Vuze is neet fatsoendelik aafgesjlaote. K\u00f3nterleer op < A HREF="%1">diagnostische logbesjtenj. Laes ouch 't wiki-artikel Vuze Disappears veur mier infermatie. (Ingels) ManagerItem.paused=Gepauzeerd Utils.link.visit=Bezeuk estebleef ConfigView.section.connection.serverport.wiki=Gooj paortkeuzes ConfigView.section.transfer.speeds.wiki=Gooj sjnelheidinsjt\u00e8llinge installPluginsWizard.installMode.info.title=Infermatie installPluginsWizard.installMode.info.text=Doe h\u00f6bs gein plugins nudig \u00f3m Vuze good te laote wirke, ze zeen alleen bedoeld veur get extra sjpas, automatisering en bedening op aafsjtandj.\nLaes daor\u00f3m de besjrieving van de plugins good veurdet se besluuts dees te installere.\nDe meiste plugins zeen veilig oet te perbere, mer euverlaaj dien k\u00f3ngfiggerasie neet mit plugins die se toch neet geis broeke. Views.plugins.Distributed.DB.title=Versjpreide database Views.plugins.Distributed.Tracker.title=Versjpreide tracker Views.plugins.Plugin.Update.title=Plug-in-update Views.plugins.UPnP.title.tooltip=Universele Plug en Play openUrl.url.info=\u00d3ngersteunt http, https, magnet en raw hex infohash strings TableColumn.header.swarm_average_completion=Aafr\u00f3njingsgemiddelde zjwerm TableColumn.header.swarm_average_completion.info=Gemiddeld aafr\u00f3njingspercentage van peers in de zjwerm GeneralView.label.swarm_average_completion=Gemiddeld compleet GeneralView.label.swarm_average_completion.tooltip='t Complete gemiddelde in percente van de peers in de zjwerm. MainWindow.nat.status.unknown=NAT \u00d3nbek\u00e8nd MainWindow.nat.status.tooltip.unknown=NAT-sjatus \u00f3nbek\u00e8nd (TCP) MainWindow.nat.status.tooltip.ok=NAT OK (TCP) MainWindow.nat.status.tooltip.probok=NAT woor OK, allewaal gein recente b\u00e8nnek\u00f3mmende TCP-connecties MainWindow.nat.status.bad=Gefirewalld MainWindow.nat.status.tooltip.bad=Firewall/NAT (TCP) bereikbaarheidsperbleem. Kiek op de Wiki-pazjena es dit zoe blief plugin.installer.recommended.plugin=Aanbevaole plugin - bekiek deze en installeer indeen vereis LoggerView.pause=Logge pauzere LoggerView.clear=&Laeg make LoggerView.filter.uncheckAll=Alle categorie\u00eb oetvinke LoggerView.filter.checkAll=Alle categorie\u00eb aanvinke LoggerView.loggingDisabled=Loggen is neet aangezat. LoggerView.includeOnly=Laot alleen regels zeen die euvereink\u00f3mme mit de sjtanderdoetdr\u00f6kking(e): LoggerView.excludeAll=Laot gein regels zeen die euvereink\u00f3mme mit de sjtanderdoetdr\u00f6kking(e): ConfigView.section.logging.log0type=Infermatie ConfigView.section.logging.log1type=Waarsjuwing ConfigView.section.logging.log2type=Fout ConfigView.section.logging.filter=Filter wen 't besjtandj gelog weurt ConfigView.section.logging.level=Logniveau ConfigView.section.logging.showLogsFor=Laot %1 logs zeen veur de volgende categorie: ConfigView.pluginlist.column.loadAtStartup=Laje bie opsjtarte ConfigView.pluginlist.column.type.perUser=Per gebroeker ConfigView.pluginlist.column.type.shared=Gedeild ConfigView.pluginlist.column.type.builtIn=Ingeboewd ConfigView.pluginlist.column.name=Naam ConfigView.pluginlist.column.version=Versie ConfigView.pluginlist.column.directory=Map ConfigView.pluginlist.column.isOperational=Operationeel? PeersView.BlockView.Avail.Have=H\u00f6bbe allebei PeersView.BlockView.Avail.NoHave=Peer haet, doe neet PeersView.BlockView.NoAvail.Have=Doe h\u00f6bs, peer neet PeersView.BlockView.NoAvail.NoHave=Nemes haet PeersView.BlockView.Transfer=Versjikke PeersView.BlockView.NextRequest=Volgend verzeuk PeersView.BlockView.title=Sjt\u00f6kskesmap PeersView.BlockView.AvailCount=Besjikbaarheidst\u00e8ller MyTorrentsView.menu.manual=&Handjmaotig... MyTorrentsView.menu.manual.per_torrent=Handjmaotig (per torrent) MyTorrentsView.menu.manual.shared_torrents=Handjmaotig (door de torrents) # %1 = "in kbps" or ""; %2 = "upload" or "download" OpenTorrentWindow.torrentLocation=Te downloade torrent(s): OpenTorrentWindow.addFiles.URL=Nuje &URL OpenTorrentWindow.addFiles.Folder=Nuje map OpenTorrentWindow.addFiles.Clipboard=Van klem&bord toevoege OpenTorrentWindow.changeDestination=Besjt\u00f6mming verangere OpenTorrentWindow.fileList=Besjtenj in de torrents: OpenTorrentWindow.torrentTable.name=Naam OpenTorrentWindow.torrentTable.saveLocation=Bewaarlocatie OpenTorrentWindow.fileTable.fileName=Besjtanjsnaam: OpenTorrentWindow.fileTable.size=Gruutde: OpenTorrentWindow.fileTable.destinationName=Besjt\u00f6m.naam: OpenTorrentWindow.startMode.seeding=Seede OpenTorrentWindow.fileList.changeDestination=Besjt\u00f6mming verangere OpenTorrentWindow.mb.badSize.title=Incompatibel besjtandj OpenTorrentWindow.mb.badSize.text='%1' is neet '%2' en kan neet gebroek waere \u00f3m te seede OpenTorrentWindow.mb.alreadyExists.text=%3 is al toegevoeg es '%2' OpenTorrentWindow.mb.alreadyExists.title=Torrent besjteit al OpenTorrentWindow.mb.openError.title=\u00c4\u00f6peningsfout OpenTorrentWindow.mb.openError.text='%1' kon niet geopend worden: OpenTorrentWindow.torrent.remove=Torrent oet de lies haole OpenTorrentWindow.torrent.options=De volgende insjt\u00e8llinge z\u00f3lle gebroek waere veur de baovestaonde torrents: OpenTorrentWindow.xOfTotal=(%1 van %2) iconBar.open.tooltip='n .Torrent-besjtandj \u00e4\u00f6pene LocaleUtil.column.text=\u00d3nbek\u00e8nde teks Tracker.tooltip.MultiSupport=Deze tracker \u00f3ngersteunt multiple hash scrapes per verzeuk. Tracker.tooltip.NoMultiSupport=Deze tracker \u00f3ngersteunt gein multiple hash scrapes per verzeuk. ConfigView.label.lazybitfield=Gebroek lazy bitfield (help seede op netwerken die gebroek make van bitfield-based blocking) ConfigView.section.file.perf.cache.flushpieces=Sjrief complete sjt\u00f6kskes drek nao de sjief. Dit veroorzaak 'n r\u00f6stigere toegank t\u00f3t de sjief, meh kan t\u00f3t mie schriefbewirkinge leije. ConfigView.section.file.writemblimit=Maximumaantal sjriefverzeuke in wachtrie (in %1) ConfigView.section.file.writemblimit.explain=Wen de sjiefsjriefsjnelheid lieger is es de downloadsjnelheid, z\u00e8t deze parameter de weg te sjrieve data in 'n wachrie zoedet de downloadsjnelheid neet nog lieger weurt. ConfigView.section.file.readmblimit=Maximumaantal leesverzeuke in wachrie (in %1) ConfigView.section.file.readmblimit.explain=Deze parameter limiteert wiev\u00e4\u00f6l geheuge gebroek weurt veur 't beware van laesbewirkinge veur CPU-gebroek. Button.moveUp=\u00d3m&hoeg verplaatse Button.moveDown=\u00d3m&lieg verplaatse ConfigView.notAvailableForMode=Dees sectie is bedoeld veur %1-modus of hoeger. 't Is neet besjikbaar in %2-modus. health.explain.error=D'r is get mis mit deze torrent. Bekiek de sjtatuskel\u00f3m, of de tooltip op 't icoontje veur de oetl\u00e8k van de fout. GeneralView.label.trackerscrapeupdate=Scrape de Tracker PeersView.piece=Sjt\u00f6kske PeersView.piece.info=L\u00e8ste sjt\u00f6kskesaantal gevraog door deze peer PiecesView.priority=Prioriteit PiecesView.priority.info=dit sjt\u00f6kske zien compleetheidsprioriteit, meh besjtaej hie neet te v\u00e4\u00f6l aandach aan PiecesView.speed=Sjnelheid PiecesView.speed.info=Langzame peers waere gewaerd inzake verwirking van sjnellere sjt\u00f6kskes TableColumn.header.AvgAvail.info=S\u00f3m van de besjikbare sjt\u00f6kskes gedeild door aantal stukjes, gedeild door aantal verb\u00e8njinge TableColumn.header.AvgAvail=Gemid. besjikb./sjt\u00f6k ConfigView.label.strictfilelocking=Forceer exclusieve besjtandjssjrieftoegankblokkering veur alle torrents MyTorrentsView.menu.checkfilesexist=Controleer of besjtenj besjtaon MyTorrentsView.menu.rescanfile=Periodiek herk\u00f3nterlere op ink\u00f3mplete sjt\u00f6kskes MyTorrentsView.menu.clear_resume_data=Hervatdata wegdoon Plugin.extseed.name=Externe seeds Plugin.localtracker.name=LAN-peerzeuker Plugin.localtracker.info=De LAN-peerzeuker sjteit mie kopie\u00eb toe es Vuze achter 'ne firewall zit of 'n normaal netwerk\ndoor effectief te downloade door 'n direc k\u00f3ntak t\u00f6sje de twie. Plugin.localtracker.enable=De LAN-peerzeuker insjakele azinstancehandler.alert.portclash=Paortconflic gedetecteerd op LAN: %1 weurt al gebroek door 'nen angere Vuze-gebroeker, selecteer ('n) nuuj willek\u00e4\u00f6rige paort(e) veur ink\u00f3mmende TCP- / UDP-lieste [t\u00f6sje %2 en %3]. ConfigView.section.transfer.lan=LAN. ConfigView.section.transfer.lan.tooltip=LAN-specifieke insjt\u00e8llinge ConfigView.section.transfer.lan.uploadrate=KB/s LAN max. uploadsjnelheid [0: ongelimiteerd] ConfigView.section.transfer.lan.uploadrate.tooltip=Peerverb\u00e8njinge binne 'tzelfde interne LAN h\u00f6bben 'n gesjeije uploadgrenslimiet. ConfigView.section.transfer.lan.downloadrate=KB/s LAN max. downloadsjnelheid [0: ongelimiteerd] ConfigView.section.transfer.lan.downloadrate.tooltip=Peerverb\u00e8njinge in 'tzelfde interne LAN h\u00f6bben 'n gesjeije downloadgrenslimiet. TorrentOptionsView.title.short=Opties TorrentOptionsView.title.full=Opties TorrentOptionsView.param.max.peers=Maximumaantal verb\u00e8njinge [0: ongelimiteerd] ConfigView.section.connection.encryption.require_encrypted_transport=Encryptietransport vereise ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Forceer gebroek van versjleutelde connecties mit angere peers. ConfigView.section.connection.encryption.min_encryption_level=Minimumencryptieniveau ConfigView.section.connection.encryption.min_encryption_level.tooltip=Allein Normaal - handshake\nRC4 - full stream\nHoegere encryptie vereis mier CPU. Peers.column.Encryption=Encryptie Peers.column.Encryption.info=Huugde van encryptie in gebroek ConfigView.section.connection.encryption.encrypt.info=Es encryptie weurt gebroek k\u00f3ns se gein contac make mit neet geliekwaerdige cli\u00ebnte. ConfigView.section.connection.encryption.encrypt.info.link=Gank hie haer veur details MainWindow.sr.status.tooltip.ok=Deilverh. %1 OK > 1.1 MainWindow.sr.status.tooltip.poor=Deilverh. %1 lieg: < 0.9 MainWindow.sr.status.tooltip.bad=Deilverh. %1 sjlech: < 0.5 ConfigView.section.style.status=Sjtatusgebied: ConfigView.section.style.status.show_sr=Deelverhauwing ConfigView.section.style.status.show_nat=NAT-sjtatus ConfigView.section.style.status.show_ddb=DDB-sjtatus ConfigView.section.style.status.show_ipf=IPFilter-sjtatus ConfigView.section.connection.encryption.encrypt.fallback_info='t Insjakele van 'n tr\u00f6kvaloptie z\u00f3l verb\u00e8njinge toesjtaon nao incompatibele cli\u00ebnte MER z\u00f3l resultere in \u00f3nversjleutelde verb\u00e8njinge ConfigView.section.connection.encryption.encrypt.fallback_outgoing=\u00d3nversjleutelde oetgaonde verb\u00e8njinge toesjtaon es versjleutelde verb\u00e8njingspoginge fale ConfigView.section.connection.encryption.encrypt.fallback_incoming=\u00d3nversjleutelde ink\u00f3mmende connecties toesjtaon upnp.selectedinterfaces=Geselecteerde interfaces (gesjeije door ';', bv. eth0;eth1) [Laeg: alle]" ConfigView.section.style.defaultSortOrder=Sjtanderdsorteervolgorde ConfigView.section.style.defaultSortOrder.desc=Oploupend ConfigView.section.style.defaultSortOrder.asc=Aafloupend ConfigView.section.style.defaultSortOrder.flip=Taengegest\u00e8ld aan de veurige volgorde LoggerView.autoscroll=Autematis sjuve Button.selectAll=Alles selectere Button.markSelected=Geselecteerde markere Button.unmarkSelected=Geselecteerde demarkere plugins.basicview.config=K\u00f3ngfiggerasie TorrentOptionsView.param.max.uploads=Maximumaantal uploadsjlots [minimum: 2] MyTorrentsView.menu.reposition.manual=Herpositionere.. ConfigView.section.connection.advanced.info.link=Bezeuk estebleef deze link veur details ConfigView.section.connection.advanced.socket.group=Socket-opties ConfigView.section.connection.advanced.bind_port=Koppel oetgaonde verb\u00e8njinge aan dezelfde lokale paort ConfigView.section.connection.advanced.bind_port.tooltip=Oetgaonde socketverb\u00e8njinge z\u00f3lle lokaal gezat waere op dezelfde paort es de ink\u00f3mmende connecties.\nInsjakele kan helpe mit 'n NAT, es de router onsjtabiel is. ConfigView.section.proxy.group.tracker=Tracker-communicaties ConfigView.section.proxy.group.peer=Peer-communicaties Pieces.column.Requested=Gevraog Pieces.column.Requested.info=Geuf aan of mie verzeuke gedaon k\u00f3nne waere op 't sjt\u00f6kske of neet (*) ConfigView.label.maxuploadsseeding=Alternatieve sjtanderd bie seede popup.error.hideall=Alles verberge ConfigView.section.style.dataStatsOnly=Alleen datasjtatistieke laote zeen (gein protocolsjtatistieke) ConfigView.section.style.separateProtDataStats=Data- en protocolsjtatistieken sjeije es 'data (protocol)' MyTorrentsView.menu.filter=Lies filtere... ConfigView.section.file.resume.recheck.all=Nao crash-hersjtart k\u00f3nterleer totale besjtandj veur complete sjt\u00f6kskes (Anges allein sjt\u00f6kskes die actief wore nao l\u00e8ste gek\u00f3nterleerde opsjlaag) ConfigureWizard.language.choose=Kees 'n taal oet de \u00f3ngersjtaonde lies: popup.closing.in=Sjirm sjluut autematis in %1 sek\u00f3nd popup.more.waiting=Nog %1 berich(te)... # > 2402 popup.download.finished="%1" is vaerdig mit downlaode. popup.file.finished="%1" is vaerdig mit downlaode. ConfigView.auto=Autematis Plugin.localtracker.autoadd.info=Dees lokale peers autematis plaatse [';' gesjeije adresse, bv. 1.2.3.4] Plugin.localtracker.autoadd=Expliciete peers Plugin.localtracker.networks.info=Besjoew de volgende netwerke es local [';' gescheije netwerke, bv. 145.227.*.*] Plugin.localtracker.networks=Lokaal netwerke MainWindow.menu.view.plugins.logViews=Log-inzages SpeedView.stats.autospeed=Autematise uploadsjnelheid SpeedView.stats.autospeed.disabled=Dees eigesjap is \u00f2f oetgezat (doe h\u00f6bs DHT nudig) \u00f2f neet in gebroek (handjmaotig geselecteerde uploadsjnelheid) SpeedView.stats.currentPing=Hujige ping: SpeedView.stats.maxUp=Max.upl.sjnelheid: ConfigView.pluginlist.unloadSelected=\u00d3ntlaaj geselecteerde ConfigView.pluginlist.scan=Op nuje plugins k\u00f3nterlere ConfigView.section.transfer.autospeed=Auto-sjnelheid (klassiek) ConfigView.section.transfer.autospeed.tooltip=Auto-sjnelheid-specifieke insjt\u00e8llinge ConfigView.section.transfer.autospeed.info=De Auto-sjnelheid pas autematis de uploadsjnelheidsgrens aan, \u00f3m euverbelasting van de netwerkverb\u00e8njing te vermieje.\n\nDees limiet z\u00f3l sjlechts van toepassing zeen wen autematise uploadsjnelheid is aangezat en ouch de versjpreide database aansjteit.\n ConfigView.section.transfer.autospeed.minupload=%1 minimum uploadsjnelheid ConfigView.section.transfer.autospeed.minupload.tooltip=Uploadsjnelheid z\u00f3l neet autematis dale \u00f3nger dees grens ConfigView.section.transfer.autospeed.maxupload=%1 maximum uploadsjnelheid [0: ongelimiteerd] ConfigView.section.transfer.autospeed.maxupload.tooltip=Uploadsjnelheid z\u00f3l neet autematis sjtiege baove dees grens ConfigView.section.transfer.autospeed.chokeping=Choking pingtied [millisek\u00f3nd] ConfigView.section.transfer.autospeed.chokeping.tooltip=Pingtieje in dees waerd z\u00f3llen es indicator van netwerkverzadiging besjoewd waere ConfigView.section.transfer.autospeed.enableauto=Gebroek mit downloade en uploade ConfigView.section.transfer.autospeed.enableautoseeding=Gebroek allein mit seede ConfigView.pluginlist.column.unloadable=Neet laajbaar ConfigView.section.transfer.lan.enable=Gescheije sjnelheidslimiet veur LAN connecties insjakele Plugin.localtracker.wellknownlocals=Loopback/link/site local networks autematis gebroeke (192.168 etc) TableColumn.header.filesdone=Besjtenj vaerdig TableColumn.header.filesdone.info=(Neet-euvergesjlage) Besjtenj vaerdig / totaalaantal (neet-euvergesjlage) besjtenj MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=wachte op DDB-initialisatie... MagnetPlugin.report.searching=zeuke... MagnetPlugin.report.found=%1 gev\u00f3nje MagnetPlugin.report.alive=%1 is laevend/aanwezig MagnetPlugin.report.dead=%1 is doed/aafwezig MagnetPlugin.report.tunnel=op zeuk nao %1 MagnetPlugin.report.downloading=downloade van %1 MagnetPlugin.report.error=fout %1 MagnetURLHandler.report.no_sources=Gein br\u00f3nne gev\u00f3nje veur torrent MagnetURLHandler.report.torrent_size=torrentgroette: %1 MagnetURLHandler.report.percent=compleet: %1% MagnetURLHandler.report.error=fout %1 DHTTransport.report.request_all=verzeuk gansen euverdrach van %1 DHTTransport.report.received_bit=\u00f3ntvange %1 nao %2 van %3 DHTTransport.report.complete=vaerdig DHTTransport.report.timeout=time-out, gein antwaord van %1 DHTTransport.report.rerequest_all=herverzeuk gansen euverdrach van %1 DHTTransport.report.rerequest_bit=herverzeuk %1 nao %2 van %3 DHTTransport.report.timeout_some=time-out, %1 pakkete \u00f3ntvange van %2 mer ink\u00f3mpleet DHTTransport.report.sending=data sjikke DHTTransport.report.resending=data hersjikke DHTTransport.report.send_complete=sjikke vaerdig DHTTransport.report.send_timeout=sjik-time-out ConfigView.section.transfer.autospeed.enabledebug=Log debuginfermatie TableColumn.header.date_added=Datum gemaak TableColumn.header.date_added.info=Datum det de torrent is gemaak ConfigView.section.file.hashchecking.smallestfirst=De kl\u00e8nste downloads iers herk\u00f3nterlere platform.win32.baddll.info=Vuze haet de aanwezigheid \u00f3ntd\u00e8k van '%1'. Dit is 'n deil van '%2' en sjteit bek\u00e8nd \u00f3m serverperbleme te veroorzake wie applicatiecrashes en hoeg CPU-gebroek. Es te dit constateers, de\u00efnstalleer dan de sofware of configureer 't zoe det 't gein invloed haet op Vuze. platform.win32.baddll.winsflt=PureSight internet-inhaudfilter upnp.ignorebaddevices=Apperate negere die neet fetsoendelik reagere upnp.ignorebaddevices.info=Op 't mem\u00e8nt genegeerde apperate: %1 upnp.ignorebaddevices.reset=Hersjt\u00e8l de genegeerde apperatelies upnp.ignorebaddevices.reset.action=Hersjt\u00e8l upnp.ignorebaddevices.alert=UPnP-apperate op locatie %1 weurt genegeerd door herhaolde misl\u00f6kkinge. Bekiek de UPnP-plug-in-k\u00f3ngfiggeratie veur meugelikhede waat betr\u00f6f dees actie. TorrentOptionsView.param.max.uploads.when.busy=KB/s max. uploadsjnelheid wen de globale uploadlimiet is bereik [0: oetgezat] UpdateMonitor.messagebox.verification.failed.title=Installatiek\u00f3ntrol misl\u00f6k UpdateMonitor.messagebox.verification.failed.text=K\u00f3ntrol van '%1' misl\u00f6k : %2 UpdateMonitor.messagebox.accept.unverified.title=\u00d3ngek\u00f3nterleerde installatie acceptere UpdateMonitor.messagebox.accept.unverified.text='%1' k\u00f3s neet bevestig waere es 'nen offici\u00eble Vuze plugin.\nEs 't gein offici\u00eble is z\u00f3ts te NEET door mote gaon.\nDoorgaon mit installere? FileView.BlockView.title=Besjtanjsjt\u00f6kskes FileView.BlockView.Done=Vaerdig FileView.BlockView.Skipped=Euvergesjlage FileView.BlockView.Active=Actief FileView.BlockView.Outstanding=Achtersjtallig ConfigView.label.tcplistenport=Ink\u00f3mmende TCP-loesterpaort ConfigView.label.udplistenport=UDP-loesterpaort upnp.portchange.alert=De volgende paorte zeen verangerd \u00f3m UPnP-apperaatperbleme te veurk\u00f3mme: %1 [auw paort=%2] %3 [auw paort=%4] ConfigView.section.proxy.username.info=Es de proxy server authentificatie eis, zelfs es gein is gedefinieerd, gebroek dan de teikenreeks "" es de gebroekersnaam/-name. ConfigView.label.maxuploadswhenbusymin=Per torrent max. uploadsjnelheid, gebroek tiedopn\u00f6mmer [sec] MainWindow.menu.help.debug=Genereer debuginfermasie (crashlog) DownloadManager.error.badsize=Verkierde gruutde ConfigView.section.NATPMP=NAT - PMP natpmp.info=NAT-PMP is Apple's alternatief veur UPnP en weurt \u00f3ngersteund door recente vleegveldjsjtations\n\nDink draan det UPnP op 't mem\u00e8nt aangezat m\u00f3t zeen veur gebroek van NAT-PMP, \u00f3mdet 't NAT-PMP-apperaat behanjeld weurt es 'n speciaal type UPnP-apperaat natpmp.enable=Insjakele (dink draan det 't aan m\u00f3t sjtaon op de vleegveldjk\u00f3ngfiggerasie \u00f3m te wirke) ConfigView.section.tracker.host.addurls=Z\u00f6rg d'rveur det de tracker-URL's aanwezig zeen in gehoste torrents ConfigView.filter=zeuk hie veur opties ConfigView.section.files.move=Verplaatse van torrent (compleet) ConfigView.section.file.defaultdir.section=Sjtanderdmapopties ConfigView.section.file.defaultdir.auto=Autematis downloade nao sjtanderdmap (z\u00f3nger te vraoge) ConfigView.section.file.defaultdir.bestguess=Gebroek de b\u00e8ste keuze bie 't keze van 'n sjtanderdopsjlaaglocatie ConfigView.section.file.defaultdir.ask=Sjtanderdmap: ConfigView.section.file.defaultdir.lastused=Update sjtanderdmap nao de locatie wo 't l\u00e8s opgesjlagen is ConfigView.section.file.config.section=K\u00f3ngfiggerasie-insjt\u00e8llinge ConfigView.section.file.config.currentdir=Hujige k\u00f3ngfiggerasiemap: ConfigView.section.torrent.decoding=Karaktersets decodere ConfigView.section.logging.udptransport=Verbose UDP-transporttracering insjakele Tracker.announce.ignorePeerSeed=Negere Peer/Seed-aantal. %1 ConfigView.section.connection.encryption.use_crypto_port=Gebroek de 'crypto-paort', \u00f3m ondudelikke ink\u00f3mmende tracker-verb\u00e8njingspoginge te verhinjere.\nSommige trackers keure dit neet good en \u00f3ngerbraeke mit foute wie "OngeljigePaort" of "illegaal Argument" TorrentOptionsView.param.reset.to.default=Hersjt\u00e8l opties nao h\u00e4\u00f6r sjtanderdwaerd TorrentOptionsView.param.reset.button=Hersjt\u00e8lle natpmp.routeraddress=Sjtationsadres [Laeg: autom.] ConfigView.section.style.disableAlertSliding=Glitsj-animatie oetsjakele van 't animatiesjrimke mit waarsjuwingsberichte. ConfigView.section.transfer.autospeed.maxinc=%1 maximum verlieging per runj ConfigView.section.transfer.autospeed.maxdec=%1 maximum verhoeging per runj ConfigView.section.transfer.autospeed.enabledownadj=Gebroek downloadsjnelheid-gelieksjt\u00e8lling ConfigView.section.transfer.autospeed.downadjratio=Download : Upload sjnelheidsverhauwing (bv. 2.0 -> downloadsjnelheidslimiet is d\u00f6bbeluploadlimiet) ConfigView.section.transfer.autospeed.latencyfactor=Factor gebroek \u00f3m latencyverangeringe aan sjnelheidverangeringe te koppele (hoegere n\u00f3mmere verliege de geveuligheid) ConfigView.section.transfer.autospeed.reset=Hersjt\u00e8l geavanceerde waerd ConfigView.section.transfer.autospeed.reset.button=Hersjt\u00e8lle PeerColumn.activationCount=Peers die perbere te verb\u00e8nje: %1 TableColumn.header.timesincedownload.info=Verstreke tied sins de data van de torrent is gedownload TableColumn.header.timesincedownload=Downl. Idle TableColumn.header.timesinceupload.info=Verstreke tied sins de data van de torrent waas geupload TableColumn.header.timesinceupload=Upl. Idle PeersView.incomingreqcount=Ingaonde verzeuke PeersView.incomingreqcount.info=Aantal binnenk\u00f3mmende verzeuke gemaak door peer PeersView.outgoingreqcount=Oetgaonde verzeuke PeersView.outgoingreqcount.info=Aantal oetgaonde verzeuke gemaak door peer upnp.mapping.trackerclientudp=UDP-tracker-cli\u00ebntpaort upnp.mapping.dhtudp=Versjpreide database ConfigView.section.connection.nondata.udp.same=Gebroek dezelfde UDP-paort veur de versjpreide database en UDP-Tracker ConfigView.section.connection.tcp.enable=TCP insjakele ConfigView.section.connection.udp.enable=UDP insjakele ConfigView.section.style.showiconbar=Gereidsjapsbalk laote zeen MainWindow.menu.view.iconbar=Wirkbalk MyTorrentsView.menu.rename=Herneume MyTorrentsView.menu.rename.displayed=De zichbare naam verangere MyTorrentsView.menu.rename.save_path=Opsjlaagpaad verangere MyTorrentsView.menu.rename.displayed.enter.title=De zichbare naam verangere MyTorrentsView.menu.rename.displayed.enter.message=Gaef 'ne nuje zichbare naam veur deze download.\nEs gein teks geplaats is, weurt de originele naam gebroek. MyTorrentsView.menu.edit_comment=K\u00f3mmentaar bewirke MyTorrentsView.menu.edit_comment.enter.title=Sjrief k\u00f3mmentaar MyTorrentsView.menu.edit_comment.enter.message=Plaats 'n k\u00f3mmentaar veur deze download UIDebugGenerator.messageask.title=Debuggenerator UIDebugGenerator.messageask.text=Gaef estebleef 'n besjrieving van de bug die-s te wils rappertere. UIDebugGenerator.complete.title=Debuggeneratie vaerdig UIDebugGenerator.complete.text=Sjik 't besjtandj '%1' estebleef nao az-bugreports@azureus-inc.com\n\nKlik op OK \u00f3m 'n sjerm te \u00e4\u00f6pene nao dit besjtandj. ConfigView.section.style.showProgramIcon=Programicoon laote zeen in de naam kel\u00f3m. ConfigView.section.style.showProgramIcon.tooltip=Weergaaf vereis misjiens her\u00e4\u00f6pening veur de verangeringe wirke. swt.alert.cant.update=SWT-bibliotheek gelaje van "%3" kan neet autematis geupdate waere van versie %1 nao %2 (m\u00f3t gelaje waere van "%4"). Bekiek estebleef de wiki veur details (Ingels). authenticator.savepassword=Mien wachwaord beware ConfigView.section.security.clearpasswords=Opgesjlage wachw\u00e4\u00f6rd vergaete ConfigView.section.security.clearpasswords.button=Vergaete Content.alert.notuploaded.title=Uploads neet vaerdig Content.alert.notuploaded.text=Upload van '%1' is niet vaerdig. Es se noe duis %2, z\u00f3lle persone neet de meugelikheid h\u00f6bben \u00f3m waat se gepubliceerd h\u00f6bs, compleet te kinne downloade. W\u00e8ts se zeker des se wils %2? Content.alert.notuploaded.multi.title=Uploads neet compleet Content.alert.notuploaded.multi.text=%1 es de inhaud van 't gepubliceerde neet compleet is geseed. Es se noe duis %2, z\u00f3lle persone neet de meugelikheid h\u00f6bben \u00f3m waat se gepubliceerd h\u00f6bs, compleet te kinne downloade. W\u00e8ts se zeker des se wils %2?\n\nInhoud neet compleet geseed: %3 Content.alert.notuploaded.stop=sjtop Content.alert.notuploaded.quit=sjtop Vuze TorrentInfoView.torrent.encoding=Torrentcodering TorrentInfoView.columns=Kel\u00f3mme van 'Mien Torrents'-sjirm progress.window.title=Bewirking in oetveuring progress.window.msg.filemove='n Ougeblik ged\u00f6ldj terwiel 't besjtandj verplaats/herneump weurt ConfigView.label.popup.timestamp=Plaats 'n tiedsdoer veur popupmeljinge ConfigView.label.popup.autohide=Autematis versjtoppe van neet-kritische popupwaarsjuwinge nao x sek\u00f3nd.\n (Z\u00e8t op 0 veur oetsjakele automatisch versjtoppe) ConfigView.label.popup.suppress_alerts=\u00d3ngerdr\u00f6k waarsjuwinge ConfigView.label.popup.use_message_boxes=Gebroek lever popupberichboxe dan de sjtanderdpopupwaarsjuwingsbox. ConfigView.label.popup.show=Laot alle popupmeljinge zeen die t\u00f3t noe toe gelog zeen (es dees d'r zeen) ConfigView.label.popup.show.button=Laote zeen ConfigView.label.please.visit.here=Bezeuk dees site estebleef veur details (link). ConfigView.section.ipfilter.enable.descriptionCache=IP-besjrievinge in scratchbesjtandj beware (tiedelik besjtandj). ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Wen oetgezat, z\u00f3lle de besjrievinge neet opgesjlage waere OpenTorrentWindow.filesInfo=%1 van %2 z\u00f3l gedownload waere. OpenTorrentWindow.diskUsage=%1 van %2 ConfigView.label.openmytorrents=\u00c4\u00f6pen 'Mijn Torrents' bie opsjtarte. ConfigView.label.open_transfer_bar_on_start=\u00c4\u00f6pen de euverdrachbalk bie opsjtarte. ConfigView.section.style.DNDalwaysInIncomplete=Ummer de torrents mit de status 'Neet downloade' laote zeen in 't "neet compleet"-deil van 't Mien Torrents-sjirm (download). OpenTorrentWindow.mb.noGlobalDestDir.title=Besjt\u00f6mmingsmap OpenTorrentWindow.mb.noGlobalDestDir.text=De besjt\u00f6mmingsmap '%1' besjteit neet of is neet besjikbaar. OpenTorrentWindow.mb.noDestDir.title=Besjt\u00f6mmingsmap neet gev\u00f3nje OpenTorrentWindow.mb.noDestDir.text=De besjt\u00f6mmingsmap '%1' veur torrent '%2' besjteit neet of is neet besjikbaar. OpenTorrentWindow.mb.notValid.title=Torrent \u00e4\u00f6pene OpenTorrentWindow.mb.notValid.text=Kon torrent '%1' niet openen. Als je deze in de seeding mode wil openen, wees dan zeker dat de data file bestaat. OpenTorrentWindow.mb.notTorrent.title=Torrent \u00e4\u00f6pene OpenTorrentWindow.mb.notTorrent.text=Kan '%1' neet \u00e4\u00f6pene. 't Liek gein .torrent-besjtandj te zeen.\n\nGedeiltelikke data \u00f3ntvange:\n%2 ConfigView.label.pause.downloads.on.exit=Pauzeer downloads bie 't aafsjloete ConfigView.label.resume.downloads.on.start=Hervat gepauzeerde downloads bie opsjtarte, naodat de initialisatie vaerdig is. UIDebugGenerator.message.cancel.title=Generatie debuginfo aafgebraoke UIDebugGenerator.message.cancel.text=Doe h\u00f6bs gein \u00f3msjrieving van de bug gegaeve dae se wils rappertere. De bug moog dan veur dich dudelik zeen, meh z\u00f3nger 'ne dudelike \u00f3msjrieving mote veer meh raoje nao 't perbleem.\n\nGeneratie van de Debuginfermatie is aafgebraoke. ConfigView.section.connection.group.http.info=\u00d3ngersteuning veur HTTP-seeding. ConfigView.section.connection.http.enable=Toesjtaon ConfigView.section.connection.http.port=Ink\u00f3mmende paortn\u00f3mmer ConfigView.section.connection.http.portoverride=Tracker HTTP-paorteuversjrieving [0: gein] window.update.noupdates.title=Resultate veur k\u00f3ntrol op 'n nuuj versie. window.update.noupdates.text=Gein nuuj updates besjikbaar veur dich.\n\nGefilleseteerd! ConfigView.label.bindip.details=Veurbild: 192.168.1.5;eth0;eth1[2] verb\u00e8nj 't gespecificeerde IP-adres, nao alle IPs van de 1e interface en de 2e IP van de 2de interface.\n't 1e IP adres z\u00f3l gebroek waere veur alle services, alle angere waere allein gebroek \u00f3m de balans te hauwe.\n\nDe volgende interfaces zeen besjikbaar:\n%1 ConfigView.label.mindownloads=Min. geliektiedige downloads UI.cannot_submit_blank_text=Doe m\u00f3s 'n waerd opgaeve. crypto.alert.as.warning='t Netwerk '%1' is bek\u00e8nd veur 't aafdwinge van vermindering van de downloadprestatie. Transportencryptie is autematis aangezat, dit kan oetgezat of gemodificeerd waere via de k\u00f3ngfiggerasie-insjt\u00e8llinge. ConfigView.section.interface.alerts=Waarsjuwinge ConfigView.label.popupdownloadadded=Laot 'n waarsjuwingspopup zeen es 'ne download is toegevoeg. popup.download.added="%1" is geplaats in dien downloadlies. MessageBoxWindow.nomoreprompting=Dit berich neet mie weergaeve TorrentOptionsView.param.max.seeds=Maximumaantal uploadverb\u00e8njinge [0: verb\u00e8njingslimiet] TorrentOptionsView.param.alternative.value.enable=Alternatieve waerd bie seede ConfigView.section.proxy.check.on.start=Proxystatus k\u00f3nterlere bie opsjtarte TransferStatsView.legend.pingaverage=Gemiddeld TransferStatsView.legend.ping1=Doel 1 TransferStatsView.legend.ping2=Doel 2 TransferStatsView.legend.ping3=Doel 3 ConfigView.section.interface.enabletray._mac=Gebroek statusbalkicoon [hersjtart vereis] ConfigView.label.closetotray._mac=Sjloete minimaliseert nao sjtatusbalkicoon ConfigView.label.minimizetotray._mac=Minimaliseer minimaliseert naar Status Bar Icon OpenTorrentWindow.mb.existingFiles.title=Besjtenj besjtaon al! OpenTorrentWindow.mb.existingFiles.text=Inkele van de besjtenj besjtaon al in de besjt\u00f6mmingsmappe die se gespecificeerd h\u00f6bs:\n\n%1\nes se doorgeis, z\u00f3l Vuze de baovestaonde besjtenj k\u00f3nterlere op juusheid van data en dees euversjrieve es 't noedwendig is. splash.unloadingTorrents=Torrents aan 't oetsjakele splash.unloadingTorrent=Torrent aan 't oetsjakele ConfigView.section.file.defaultdir.autorename=Torrentgegaeve autematis herneume es besjtenj in 't paad versjillend lieke te zeen. ConfigView.section.file.defaultdir.autorename.tooltip=Dit veurkump det 'ne torrent euversjreve weurt door de besjtenj van 'nen angere torrent wen de besjtanjsname 'tzelfde zeen. alert.raised.at.close=(Berich van vurge sjloete van Vuze) Plugin.trackerpeerauth.name=Tracker-peer-autorisatie Plugin.trackerpeerauth.info=Deze plugin wirk mit trackers \u00f3m te k\u00f3nterlere det peers geljige zjwermlede zeen. Peers.column.maxupspeed=Max. Upl.sjnelheid Peers.column.maxdownspeed=Max. Downl.sjnelheid MyTorrents.items.DownSpeedLimit.disabled=G\u00e8nne download upnp.selectedaddresses=Adresse (gesjeije door ';', '-'-prefix=neet toesjtaon, '+' =toesjtaon) [laeg: inkele] upnp.alert.multipledevice.warning=Multiple UPnP-apperate zeen gedetecteerd - k\u00f3nterleer of alle benudigde paorte ge\u00e4\u00f6pend zeen (bekiek de UPnP-log en k\u00f3ngfiggeratie) UpdateMonitor.messagebox.restart.title=Software-update UpdateMonitor.messagebox.restart.text=Vuze haet juus 'n belangrieke update gedowload en m\u00f3t noe waere hersjtart zoedet de update kan waere ge\u00efnstalleerd. PiecesView.BlockView.Have=Haet PiecesView.BlockView.NoHave=Haet neet PiecesView.BlockView.Header=%1 kel\u00f3m(me), %2 rie(je), %3 sjt\u00f6kskes ConfigView.section.update.autodownload=Updates autematis downlaode en z\u00e8kge wen de installatie vaerdig is Peers.column.peer_id.info=Peer ID in laesbaar formaat Peers.column.peer_byte_id=Peerbits ID Peers.column.peer_byte_id.info=Peer ID in byteformaat Peers.column.handshake_reserved=Handshake gereserveerde Bytes Peers.column.handshake_reserved.info=Indiceert welke gereserveerde bits zeen ingesjt\u00e8ld in de BT handshake Peers.column.client_identification=Cli\u00ebntidentificatie Peers.column.client_identification.info=Indiceert de ruwe clientname \u00f3ntvange door Vuze - n\u00f6ttig veur debugging dht.warn.user=Waarsjuwing veur potentieel NAT/paort-mappingperbleme ConfigView.label.openbar.incomplete=Downloadbalke: auto-\u00e4\u00f6pene downloads ConfigView.label.openbar.complete=auto-\u00e4\u00f6pene seeds ConfigView.label.transferbar.remember_location=\u00d3nthauw de l\u00e8ste locatie van de euverdrachsbalk. ConfigView.section.transfer.autospeed.forcemin=%1 uploadsjnelheid geforceerd mit analisere van de verb\u00e8njing. MainWindow.menu.tools.speedtest=Sjnelheidstes... speedtest.wizard.title=Sjnelheidstes speedtest.wizard.run=Sjtart 'n sjnelheidstes. speedtest.wizard.test.mode.updown=upload en download SpeedTestWizard.test.panel.currinfo=BitTorrent bandjbreide teste. SpeedTestWizard.test.panel.label=Vuze-sjnelheidtes: SpeedTestWizard.test.panel.already.running=De tes l\u00f6p al! SpeedTestWizard.test.panel.not.accepted=Tesverzeuk neet geaccepteerd: SpeedTestWizard.test.panel.abort=Aafbraeke SpeedTestWizard.test.panel.abort.countdown=Tes aafbraeke nao: SpeedTestWizard.test.panel.test.countdown=tes vaerdig nao: SpeedTestWizard.test.panel.testfailed=Tes misl\u00f6k SpeedTestWizard.test.panel.aborted=Tes handjmaotig aafgebraoke. SpeedTestWizard.test.panel.enc.label=Klik \u00f3m te teste mit encryptie: SpeedTestWizard.test.panel.standard=sjtanderd SpeedTestWizard.test.panel.encrypted=versjleuteld SpeedTestWizard.set.upload.button.apply=Toepasse SpeedTestWizard.set.upload.result=L\u00e8ste testresultaat SpeedTestWizard.set.upload.bytes.per.sec=kB/sek\u00f3nd SpeedTestWizard.set.upload.bits.per.sec=b/sek\u00f3nd SpeedTestWizard.finish.panel.title=Sjnelheidstes vaerdig! SpeedTestWizard.finish.panel.click.close=De sjnelheidsteswizard is vaerdig. Klik op Aafr\u00f3nje \u00f3m te sjtoppe. SpeedTestWizard.finish.panel.max.seeding.upload=Max upload tiedes seede : SpeedTestWizard.finish.panel.enabled=ingesjakeld SpeedTestWizard.finish.panel.disabled=oetgesjakeld SpeedTestWizard.abort.message.scheduled.in=tes gepland in ... %1 sek\u00f3nd" SpeedTestWizard.abort.message.unsupported.type=Neet \u00f3ngersteund testype!!!! SpeedTestWizard.abort.message.manual.abort=Handjmaotig gesjtop SpeedTestWizard.abort.message.scheduling.failed=Planne van de test is misl\u00f6k SpeedTestWizard.abort.message.download.added=Download %1 geplaats tiedes de tes SpeedTestWizard.abort.message.entered.error=Tesdownload kreeg foutsjtatus '%1' SpeedTestWizard.abort.message.entered.queued=Tesdownload kreeg sjtatus inne wach gezat/gesjtop SpeedTestWizard.abort.message.interrupted=Torrent-sjnelheidstesmonitor-bewirking waas \u00f3ngerbraoke veur de tes vaerdig waas SpeedTestWizard.abort.message.execution.failed=Tesoetveuring misl\u00f6k SpeedTestWizard.abort.message.failed.peers=Verb\u00e8njing misl\u00f6k nao peers SpeedTestWizard.abort.message.insufficient.slots=K\u00f3s neet upload nao peers - neet gen\u00f3g uploadsjlots? SpeedTestWizard.abort.message.not.unchoked=K\u00f3s neet downloade van peers esof zie de verb\u00e8njing noets unchoked h\u00f6be SpeedTestWizard.stage.message.requesting=verzeuke \u00f3m 'n tes... SpeedTestWizard.stage.message.preparing=tes veurbereije... SpeedTestWizard.stage.message.starting=tes aan''t sjtarte... SpeedTestWizard.stage.message.connect.stats=Verb\u00e8njingssjtatus: peers=%1, down_ok=%2, up_ok=%3 window.uiswitcher.title=Vuze-interfacekezer window.uiswitcher.text=Selecteer de gew\u00e8nste gebruikersinterface (UI). window.uiswitcher.NewUI.text=* Aanbevaole veur beginners en nuje gebroekers.\n\n* 'n Mekkelikm, intu\u00eftief grafisch oeterlik.\n\n* Vereiste oeterlik veur 't publicere op 't Vuze-platform. window.uiswitcher.ClassicUI.title=Klassiek oeterlik window.uiswitcher.ClassicUI.text=* Behauwt de functionaliteit van de 2.x versies.\n\n* Vuze skin weurt neet gelaje. window.uiswitcher.bottom.text=Dien selectie kan mekkelik waere aangepas door op de Vuze-interfacekezerkn\u00f3p te duje iconBar.switch.tooltip=Vuze Interfacekezer VivaldiView.notAvailable=Vivaldiweergaaf neet besjikbaar restart.error=Hersjtart misl\u00f6k:\n%1\nZuug hersjtartperbleme. restart.error.oom=Te min geheuge restart.error.fnf='%1' neet gev\u00f3njen in '%2' restart.error.pnf=Paad '%1' neet gev\u00f3nje restart.error.bad=Verkie\u00ebrd besjtanjsformaat veur '%1' restart.error.denied=Toegank geblokkeerd bie opsjtarte van '%1'. K\u00f3nterleer of-s te rechte h\u00f6bs \u00f3m dit program te broeke. TableColumn.header.date_completed=Vaerdig op TableColumn.menu.date_added.reset=Datum hersjt\u00e8lle ConfigView.section.ipfilter.discardbanning=Blokkeer peers wovan de verworpe data/goje data-verhauwing dit euvertref [0: uitgezet] ConfigView.section.ipfilter.discardminkb=Minimum %1 verworpe veur geljende verhauwing ConfigView.interface.start.advanced=Start in geavanceerde weergaaf (AZ 2.x) MyTorrents.column.ColumnQuality=Kwaliteit MyTorrents.column.ColumnSpeed=Sjnelheid MyTorrents.column.ColumnProgressETA.StreamReady=Streaming vaerdig MyTorrents.column.ColumnProgressETA.PlayableIn=Sjpeelbaar in %1 %2 TableColumn.header.Quality=Kwaliteit TableColumn.header.Speed=Sjnelheid TableColumn.header.RateIt=Waardere TableColumn.header.Rating=Waardering TableColumn.header.SpeedGraphic=Sjnelheid TableColumn.header.AzProduct=Van TableColumn.header.ProgressETA=Veurtgank #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=Besjtanjstype: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=Sjtart-tab v3.MainWindow.tab.browse=Blajere v3.MainWindow.tab.library=Mien Bibliotheek v3.MainWindow.tab.publish=Publicere v3.MainWindow.tab.advanced=geavanceerd v3.MainWindow.menu.home=&Sjtart-tab v3.MainWindow.menu.browse=&Blajere v3.MainWindow.menu.library=Mien Bib&liotheek v3.MainWindow.menu.publish=&Publicere v3.MainWindow.menu.advanced=&Geavanceerd v3.MainWindow.menu.view.searchbar=Zeukbalk v3.MainWindow.menu.view.tabbar=Tabbalk v3.MainWindow.currentDL=Op 't mem\u00e8nt aan 't downloade v3.MainWindow.button.stream=Streame v3.MainWindow.button.stop=Sjtoppe v3.MainWindow.button.start=Sjtarte v3.MainWindow.button.pause=Pauzere v3.MainWindow.button.resume=Hervatte v3.MainWindow.button.delete=Weghaole v3.MainWindow.button.comment=K\u00f3mmentaar v3.MainWindow.button.viewdetails=Details bekieke v3.MainWindow.button.play=Aafsjpele v3.MainWindow.button.cancel=Aafbraeke v3.MainWindow.button.preview=Veurbild v3.MainWindow.view.wait='n Ougeblik ged\u00f6ldj estebleef... v3.MainWindow.xofx=%1 van %2 v3.MainWindow.Loading='n Ougeblik ged\u00f6ldj... v3.filter-bar=Titelfilter: v3.MainWindow.search.defaultText=Torrentsites doorzeuke v3.mb.delPublished.title=Inhaud uploade sjtoppe v3.mb.delPublished.text=WAARSJUWING: Dees actie z\u00f3l neet de gepubliceerde inhaud '%1' weghaole van %3 \n\nKlik allein op "Weghaole" es te de gepubliceerde inhaud besjikbaar wils hauwe \u00f3m te downloade, meh waal bandjbreide vrie wils make. Z\u00f6rg waal det de uploads good aafgesjlaote zeen veurdet-s te det duis.(wie?).\n\nKlik op "Aafbraeke" es te de ganse gepubliceerde inhaud weg wils haole van %3, en gebroek de (X)-kn\u00f3p op 't Gepubliceerde Inhaud-peniel in de Publiceertab.\n\nMie hulp.\n\n v3.mb.delPublished.delete=&Weghaole v3.mb.delPublished.cancel=&Aafbraeke v3.mb.openFile.title=Besjtandj \u00e4\u00f6pene v3.mb.openFile.button.play=Aafsjpele v3.mb.openFile.button.cancel=Aafbraeke v3.mb.openFile.remember=Besjtenj ummer \u00e4\u00f6pene z\u00f3nger te vraoge v3.mb.PlayFileNotFound.title=Besjtandj neet gev\u00f3nje v3.mb.PlayFileNotFound.text=De besjtenj veur '%1' zeen weggehaold of \u00f3ntbraeke. v3.mb.PlayFileNotFound.button.remove=Oet Vuze weghaole v3.mb.PlayFileNotFound.button.redownload=Data opnuuj downloade v3.mb.PlayFileNotFound.button.find=Handjmaotig zeuke... v3.mb.deletePurchased.title=De gekochde inhaud weghaole v3.mb.deletePurchased.text=W\u00e8ts te zeker det-s te deze inhaud '%1' weg wils haole?\n\nDit is inhaud dae se \u00f2f gekoch h\u00f6bs, \u00f2f woveur-s te h\u00f6bs mote inlogge \u00f3m 't te downloade. v3.mb.deletePurchased.button.delete=&Weghaole v3.mb.deletePurchased.button.cancel=&Aafbraeke v3.topbar.menu.show.plugin=Plug-in-gebied v3.topbar.menu.show.search=Zeuke splash.initializeCore=Kern aan 't laje splash.initializeUIElements=Interface aan 't laje ConfigView.section.transfer.autospeedbeta=Auto-sjnelheid (Beta) # ConfigView.section.ipfilter.peerblocking.group=Peerblokkade ConfigView.section.ipfilter.autoload.group=Autematis laje ConfigView.section.ipfilter.autoload.file=IP-filter file veur autoload ConfigView.section.ipfilter.autoload.info=\u00d3ngersteunt de formate DAT (eMule), P2P (PeerGardian, splist), en P2B v1,2,3 (Peer Gardian 2). 't Besjtandj kan lokaal of 'nen URL zeen, gezip, ge-gzip of geweun teks. URLs z\u00f3l autematis her-downloade nao 7 daag, wonao besjtenj z\u00f3lle weure herlaje b\u00e8nne 'n minuut of herplaats. ConfigView.section.ipfilter.autoload.loadnow=Noe laje splash.loadIpFilters=IP-filters aan 't laje... SpeedTestWizard.set.upload.title=Upload- en downloadgrens insjt\u00e8lle SpeedTestWizard.set.download.label=Downloadsjnelheidslimiet: SpeedTestWizard.set.upload.label=Uploadsjnelheidgrens: SpeedTestWizard.name.conf.level.absolute=Absoluut SpeedTestWizard.name.conf.level.high=Hoeg SpeedTestWizard.name.conf.level.med=Gemiddeld SpeedTestWizard.name.conf.level.low=Lieg SpeedTestWizard.name.conf.level.none=Gein ConfigView.section.transfer.select=Auto-sjnelheid ConfigView.section.transfer.select.v2=Auto-sjnelheid (beta) mb.azmustclose.title=Opsjtartfout mb.azmustclose.text=Vuze m\u00f3t sjtoppe door 'n perbleem mit 't (her)sjtarte van Vuze wodoor waarsjienlik 't program es Administrator opgesjtart is.\n\nHer\u00e4\u00f6pen 't program hanjmaotig naodet Vuze gesjlaoten is. network.ipv6.prefer.addresses=Prefereer IPV6-adresse wen zoewaal IPV6 es IPV4 besjikbaar zeen network.enforce.ipbinding=Forceer IP verb\u00e8njinge zelfs wen gein interfaces besjikbaar zeen, veurk\u00f3m jedere verb\u00e8njing wen gein gespecificeerde verb\u00e8njinge besjikbaar zeen. DHTView.title.full_v6=Versjpreide database IPv6 ConfigView.pluginlist.loadSelected=Laaj geselecteerde SpeedView.stats.asn=Netwerk: SpeedView.stats.estupcap=Uploadlimiet: SpeedView.stats.estdowncap=Downloadlimiet: SpeedView.stats.unknown=\u00d3nbek\u00e8nd SpeedView.stats.estimate=Getaxeerd SpeedView.stats.measured=Gemaete SpeedView.stats.measuredmin=Gemaete min. SpeedView.stats.manual=Handjmaotig ConfigView.section.transfer.autospeed.networks=Netwerkdetails ConfigView.section.transfer.autospeed.resetnetwork=Hersjt\u00e8l netwerkdetails ConfigView.section.transfer.autospeed.network.info=De baovestaonde limiete waere gewoen autematis tiedes de euverdrach oetgeraekend of zeen 't resultaat van 'n sjnelheidtes.\nEs se dees handjmatig wils specificere gebroek dan de optie hie-\u00f3nger.\nAlle limiete anges es 'vasgesjt\u00e8ld' z\u00f3lle achteraaf autematis biegesjteld waere es det nudig is. \nGeef 'n waerd en selecteer 't type. Dink d'raan det de sjnelhede in %1 zeen.\n dialog.uiswitcher.restart.title=Interfacekezer: Hersjtart Vuze vereis dialog.uiswitcher.restart.text='ne Hersjtart is vereis \u00f3m te kinne euvergaon nao de nuje gebroekersinterface. TrayWindow.menu.close=Sjloet de Downloadmanj # Used for peers which we can't determine. PeerSocket.unknown=\u00d3nbek\u00e8nd PeerSocket.fake_client=VERVALSING PeerSocket.bad_peer_id=sjlechte peer-ID PeerSocket.mismatch_id=kump neet euverein PeerSocket.unknown_az_style=\u00d3nbek\u00e8nd %1/%2 PeerSocket.unknown_shadow_style=\u00d3nbek\u00e8nd %1/%2 OpenTorrentWindow.mb.askCreateDir.title=Besjt\u00f6mmingsmap besjteit neet OpenTorrentWindow.mb.askCreateDir.text=De besjt\u00f6mmingsmap '%1' besjteit neet.\n\nDeze aanmake? SpeedView.stats.estimatechoke=Sjatting (choke) ConfigTransferAutoSpeed.upload.capacity.usage=Uploadcapaciteitgebroek ConfigTransferAutoSpeed.capacity.used=% c\u005capaciteit gebroek ConfigTransferAutoSpeed.while.downloading=Downloade: ConfigTransferAutoSpeed.set.dht.ping=DHT-ping-inst\u00e8lling: ConfigTransferAutoSpeed.set.point=Inst\u00e8lpuntj (ms) ConfigTransferAutoSpeed.set.tolerance=Tolerantie (ms) ConfigTransferAutoSpeed.ping.time.bad=Sjlech: ConfigTransferAutoSpeed.adjustment.interval=Inst\u00e8lling interval: ConfigTransferAutoSpeed.skip.after.adjust=Euversjlaon nao aanpassing: GeneralView.label.distributedCopies=Versjpreide kopie\u00eb: PiecesView.DistributionView.title=Sjt\u00f6kskesverdeiling PiecesView.DistributionView.NoAvl=Neet besjikbare sjt\u00f6kskes PiecesView.DistributionView.SeedAvl=Seed gem. biedraag PiecesView.DistributionView.PeerAvl=Peer gem. biedraag PiecesView.DistributionView.RarestAvl=Zeldzaamste sjt\u00f6kskes: %1 (Gem.:%2) PiecesView.DistributionView.weHave=Sjt\u00f6kskes die-s doe h\u00f6bs PiecesView.DistributionView.theyHave=Sjt\u00f6kskes die peer haet PiecesView.DistributionView.weDownload=Sjt\u00f6kskes die-s te gedownload h\u00f6bs PeersView.gain=Resultaat PeersView.gain.info=Som van gedownloade - geuploade data. unix.script.new.title=Nuuj Vuze-opsjtartscrip besjikbaar unix.script.new.text='n Nuuj Vuze-opsjtartscrip is besjikbaar, en is opgeslage nao '%1'.\n\n't Is aanbevaole det-s te Vuze sjtops en euver geis op dit scrip ('%2').\n\nEs te dien Vuze-opsjtartscrip erg h\u00f6bs aangepas, zuug dan VuzeWiki: Unix Script (Ingels).\n\nEs te Vuze h\u00f6bs ge\u00efnstalleerd van 'n distro (yum, apt-get, etc), is 't aanbevaole Vuze opnuuj te installere gebroekmakende van 't pakket op Vuze' Sourceforge Page (Doe kriegs dan dezelfde interface dae-s te noe ouch h\u00f6bs). unix.script.new.button.quit=Noe sjtoppe unix.script.new.button.continue=Ich doon 't later unix.script.new.button.asknomore=Vert\u00e8l 't mich neet mie unix.script.new.auto.title=Nuuj Vuze-opsjtartscrip unix.script.new.auto.text='n Nuuj Vuze-opjstartscrip is besjikbaar.\n\n't Is aanbevaole det-s te Vuze noe hersjtarts. Content.alert.notuploaded.button.stop=&Sjtoppe Content.alert.notuploaded.button.continue=&Doorgaon mit uploade Content.alert.notuploaded.button.abort=&Neet sjtoppe ConfigView.label.checkOnSeeding='n Herk\u00f3ntrol oetveure mit lieg br\u00f3nne van sjt\u00f6kskes bie 't seede. ConfigView.label.ui_switcher=Laot UI-sjakelier zeen ConfigView.label.ui_switcher_button=Laote zeen SpeedTestWizard.test.panel.explain=Maet dien Vuze-protocolsjnelheid. Selecteer 't sjnelheidstestype en de encryptiemodus. Gank nao de Vuze-wikipazjena veur details euver dees tes. De tes sjtop autematis es hae langer es twie menuut doert. Normale teste zeen in minder es e menuut vaerdig. SpeedTestWizard.set.upload.hint=Sjt\u00e8l de upload- en downloadbepirkinge in \u00f3m te broeke mit 't Vuze-Speedsense-algoritme. SpeedTestWizard.set.upload.panel.explain=De hie ingesjt\u00e8lde limiete waere gebroek door 't Vuze-AutoSpeed-algoritme. Sjt\u00e8l de euverdrachslimiete en de vertroeweslimiete in.\n\nDink draan det de liensjnelheid d\u00e8k aangegaeve weurt in "bits per sek\u00f3nd" - allewaal de waerd hie-\u00f3nger is weergegaeven in "kilobytes per sek\u00f3nd". SpeedTestWizard.set.limit.conf.level=Vertroewe SpeedTestWizard.finish.panel.auto.speed=Autosjnelheid is: SpeedTestWizard.finish.panel.auto.speed.seeding=Autosjnelheid tiedes seede is: ConfigTransferAutoSpeed.add.comment.to.log.group=Plaats k\u00f3mmentaar naar de debug log ConfigTransferAutoSpeed.add.comment.to.log=Plaats k\u00f3mmentaar: ConfigTransferAutoSpeed.algorithm.selector=Auto-sjnelheidsselector ConfigTransferAutoSpeed.algorithm=Algoritme: ConfigTransferAutoSpeed.auto.speed.classic=Auto-sjnelheid(classic) ConfigTransferAutoSpeed.auto.speed.beta=Auto-sjnelheid(beta) ConfigTransferAutoSpeed.data.update.frequency=Update-frequentie Alert.failed.update=Installatie van minstens ein component misl\u00f6k. Bekiek VuzeWiki: Failed Update OpenTorrentWindow.mb.existingFiles.partialList=(Gedeiltelikke lies. Mier besjtenj besjtaon al) TableColumn.header.bad_avail_time.info=L\u00e8ste kier det 'n ganse kopie van de download besjikbaar waas TableColumn.header.bad_avail_time=Ganse kopie gezeen MyTorrentsView.menu.exporthttpseeds=HTTP-seed-URL's nao 't klembord exportere SWT.alert.erroringuithread='n \u00d3nbek\u00e8nde fout versjeen in de GUI, mierdere foute k\u00f3nne gerapperteerd waere. ConfigView.label.minannounce=Minimumtied t\u00f6sje trackeraank\u00f3ndiginge in sek\u00f3nd ConfigView.label.maxnumwant=Limiteer de n\u00f3mmers van peers die de tracker tr\u00f6k moog sjikke. ConfigView.label.announceport=Vervang tracker announce-poort ConfigView.label.noportannounce=K\u00f3ndig de loesterpaort neet aan de tracker aan (haet g\u00e8n effec op pex, dht) ConfigView.label.maxseedspertorrent=Max. seeds per torrent sjtanderd [0: ongelimiteerd] wizard.webseed=HTTP-seeds aan de torrent toevoege wizard.webseed.title=HTTP-seeds wizard.webseed.configuration=HTTP-seed-k\u00f3ngfiggeratie wizard.webseed.adding=HTTP-seeds toevoege GeneralView.label.private=Priv\u00e9-torrent: GeneralView.yes=Jao GeneralView.no=Nei ConfigView.label.userequestlimiting=Broek 't verzeuk t\u00f3t vermindering in plaats van vertraog laeze veur 't limitere van de downloadsjnelheid [haet gein effec wen de downloadsjnelheid ongelimiteerd is] ConfigView.label.userequestlimiting.tooltip=Verzeuk t\u00f3t limitere is neet zoe stabiel ese vertraog laeze, mer sjteit downloadveurkeure toe gebaseerd op de wachriepositie en kan de netwerkprestatie verbaetere. ConfigView.label.userequestlimitingpriorities=Focus downloadsjnelheid op de baovekantj van de downloadrie wen de downloadsjnelheidslimiet is bereik ConfigView.section.logging.timestamp=Tiedsindeilingsformaat veur logbesjtenj Peers.column.timetocomplete=Resterende tied Peers.column.timetocomplete.info=Tied dae nog te gaon is t\u00f3tdet de peer vaerdig is. ConfigView.section.interface.display.suppress.file.download.dialog=\u00d3nderdr\u00f6k Besjtanjsdownload-popupdialoog ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Laot alle besjtanjsdownloadveurtgange in de statusbalk zeen in plaats van 'n popupdialoog FileDownload.canceled='n Torrenbesjtanjsdownload is succesvol geannuleerd door gebroekersactie: %1 Progress.reporting.status.canceled=Aafgebraoke Progress.reporting.status.finished=Vaerdig Progress.reporting.status.retrying=Opnuuj aan 't perbere... Progress.reporting.action.label.retry.tooltip=Bewirking opnuuj perbere Progress.reporting.action.label.remove.tooltip=Haol dit Veurtganksreport oet de historie. Progress.reporting.action.label.cancel.tooltip=De bewirking aafbraeke Progress.reporting.default.error=Misl\u00f6k Progress.reporting.no.reports.to.display='t Geuf gein Veurtganksreporte \u00f3m te laote zeen op 't mem\u00e8nt. Progress.reporting.no.history.to.display='t Geuf gein detailberichte \u00f3m te laote zeen. Progress.reporting.detail.history.limit=De detailberichlimiet (%1) veur de Veurtganksrapperteerder is euversjrede; volgende detailberichte z\u00f3lle neet in de historielies geplaats waere. Progress.reporting.statusbar.button.tooltip='t Veurtgankrappertagesjirm laote zeen webui.bindip=IP koppele - normaal neet vereis (*) v3.MainWindow.text.log.in=Aanmelje v3.MainWindow.text.log.out=Aafmelje v3.MainWindow.text.get.started=Insjrieve v3.MainWindow.text.my.account=Mien account OpenTorrentWindow.simple.open=Torrentlocatie (besjtandj, URL, hash) Progress.reporting.window.remove.auto=Autematis inactieve \u00f3ngerdeile weghaole Progress.reporting.window.remove.auto.tooltip=Autematis alle complete, misl\u00f6kde of aafgebraoke processe van de weergaaf aafhaole Progress.reporting.window.remove.now=Inactive \u00f3ngerdeile weghaole Progress.reporting.window.remove.now.tooltip=Alle complete, misl\u00f6kde of aafgebraoke processe van de weergaaf aafhaole dhttracker.tracklimitedwhenonline=Allewaal, veur lieg gebroek van br\u00f3ntracering oet, bie 'n online zjwerm kruuts-populatie. TorrentOptionsView.multi.title.short=Torrent-opties TorrentOptionsView.multi.title.full=Torrent-opties MyTorrentsView.menu.open_parent_folder=Besjtanjslocatie \u00e4\u00f6pene ConfigView.section.style.use_show_parent_folder=Gebroek "%1" in plaats van "%2" in torrentmenu's ConfigView.section.style.use_show_parent_folder.tooltip=Insjakele van dees optie z\u00f3l dich toesjtaon \u00f3m de bewaarmap te \u00e4\u00f6pene mit 't juiste bestjanjsbehiersprogram.\nAllewaal, 't kan zoe zeen det de bewaarmap neet autematis weurt geselecteerd. PeerManager.status.ps_disabled=Tracker-peerbr\u00f3n is oetgezat. ConfigView.section.stats.exportfiles=Besjtanjsdetails exportere updater.cant.write.to.app.title=Kan neet nao de programmap sjrieve updater.cant.write.to.app.details=De map "%1" is neet besjriefbaar.\n\nDit z\u00f3l veurkomme det toekomstige updates k\u00f3nne waere toegevoegd.\n\nLaes de wiki veur details (Ingels). plugin.install.class_version_error=Deze plugin vereis 'n nuujer Java-versie \u00f3m te wirke. v3.MainWindow.tab.events=Activiteit button.columnsetup.tooltip=Kel\u00f3minst\u00e8lling v3.activity.remove.title=De activiteitgegaeves weghaole v3.activity.remove.text=W\u00e8ts te zeker det-s te de activiteitgeb\u00e4\u00f6rtenis '%1' weg wils haole? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=Sjloete Menu.show.torrent.menu=Laot 't torrents-menu zeen Menu.show.torrent.menu.tooltip=Toon torrent-besjturingsmenu in de menubalk. #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=Netwerksjtatus plugin.aznetstatus.pingtarget=Trac\u00e9doel pinge/tracere ConfigView.section.style.usePathFinder=Gebroek 'Paadv\u00e8njer' in plaats van 'Zeuker' menu.sortByColumn=Sortere op %1 MyTorrentsView.menu.manual.per_peer=Handjmaotig (per peer) MyTorrentsView.menu.manual.shared_peers=Handjmaotig (mierdere peers) v3.button.removeActivityEntry=Activiteitspecificaties weghaole v3.splash.initSkin=Thema aan 't laje v3.splash.hookPluginUI=Plug-in-UI in aan 't h\u00e4\u00f6ke OpenTorrentWindow.mb.notTorrent.cannot.display=Kan de data neet fetsoendelik laote zeen MainWindow.menu.window.zoom.maximize=Maximalisere MainWindow.menu.window.zoom.restore=Hersjt\u00e8lle ImageResizer.image.too.small='t Aangegaeve plaetje is te klein, kees estebleef 'n anger ('t m\u00f3t tenminste %1 x %2 zeen) ImageResizer.title=Dit sjt\u00f6kske gereidsjap leut de miniatuur zeen wie dae op 't Vuze Platform geplaats weurt ImageResizer.move.image=Verplaats 't plaetje door 't te sjleipe ImageResizer.move.image.with.slider=Verplaats 't plaetje door 't te sjleipe, veur versjaole gebroek de sjaof hie-\u00f3nger security.crypto.title=Encryptiesjleuteltoegank security.crypto.encrypt=Gaef 't wachwaord veur 't besjrime van de nuuj gemaakde encryptiesjleutel. Vergaet dit wachwaord neet, 't geuf gein maneer \u00f3m dit tr\u00f6k te haole es det gebeurt! security.crypto.decrypt=Gaef 't wachwaord veur 't \u00f3ntgrendel van de encryptiesjleutel. security.crypto.reason=Raeje veur bewirking security.crypto.password=Wachwaord security.crypto.password2=Herhaol 't wachwaord security.crypto.persist_for=Wachwaordherinneringsperiode security.crypto.persist_for.dont_save=Neet opsjlaon security.crypto.persist_for.session=Dees sessie security.crypto.persist_for.day=Eine daag security.crypto.persist_for.week=Ein waek security.crypto.persist_for.30days=30 daag security.crypto.persist_for.forever=Veur altied security.crypto.password.mismatch.title=Wachwaordfout security.crypto.password.mismatch=Gegaeve wachw\u00e4\u00f6rd k\u00f3mme neet euverein, gaef ze opnuuj. ConfigView.section.security.group.crypto=Publieke of priv\u00e9sjleutels ConfigView.section.security.resetkey=Sjleutels hersjt\u00e8lle ConfigView.section.security.resetkey.warning.title=Dataverlees-waarsjuwing ConfigView.section.security.resetkey.warning=W\u00e8ts se zeker des se dien encryptiesjleutels tr\u00f6k wils z\u00e8tte? Es se dit duis, z\u00f3l alle infermatie dae versjleuteld is veurgood verlaore gaon! Ouch kinne peers die in 't bezit zeen van diene publieke sjleutel, dan neet langer mit diene computer communicere t\u00f3tdet zie 'ne nuje sjleutel h\u00f6bbe van dich. Dus es se gaar neet w\u00e8ts waat se eigentlik duis, doot dit dan neet. ConfigView.section.security.unlockkey=Sjleutels expliciet \u00f3ntgrendele ConfigView.section.security.unlockkey.button=\u00d3ntgrendele ConfigView.section.security.publickey=Publieke sjleutel ConfigView.section.security.publickey.undef=Nog neet gedefinieerd ConfigView.section.security.resetkey.error.title=Bewirking misl\u00f6k ConfigView.section.security.resetkey.error=Hersjt\u00e8lle van de sjleutels misl\u00f6k ConfigView.section.security.unlockkey.error=\u00d3ntgrendele van sjleutel is misl\u00f6k - wachwaord incorrec ConfigView.copy.to.clipboard.tooltip=Nao klembord kopi\u00ebre Views.plugins.azbuddy.title=Vrunj Browser.popup.error.no.access=D'r is 'n fout opgetraeje tiedens 't contac make mit 'n br\u00f3n op aafsjtandj.\nPerbeer 't later nog \u00e8ns ! ConfigView.label.queue.stoponcebandwidthmet=Sjtart gein torrents wen de upload-/downloadsjnelheidslimiet is bereik ConfigView.section.style.forceMozilla=Dwing Vuze Mozilla te broeke veur browserwidgets [xulrunner of firefox 3 en Vuze hersjtarte vereis] ConfigView.section.style.xulRunnerPath=Specificeer de XulRunner- / Firefox-map handjmaotig [vereis veur FF3; Vuze hersjtart vereis] azbuddy.name=Vrunj azbuddy.enabled=Ingesjakeld azbuddy.disabled=Plugin is oetgesjakeld, bekiek de plug-in-k\u00f3ngfiggerasie veur verangere. azbuddy.nickname=Diene weergavenaam azbuddy.msglog.title=Vrundj-infermatie azbuddy.addtorrent.title=Download acceptere? azbuddy.addtorrent.msg=Diene vrundj '%1' haet dich '%2' gesjik.\nWils te deze download plaatse? azbuddy.contextmenu=Sjik nao 'ne vrundj azbuddy.ui.mykey=Miene sjleutel azbuddy.ui.add=Plaats azbuddy.ui.new_buddy=Nuje vrundjsjleutel azbuddy.ui.table.name=Naam azbuddy.ui.table.last_msg=L\u00e8ste berich azbuddy.ui.menu.remove=Verwijder azbuddy.ui.menu.copypk=Kopieer publieke sjleutel azbuddy.ui.menu.send=Sjik berich azbuddy.ui.menu.send_msg=Plaats de teks \u00f3m nao dien(e) vrun(d)j te sjikke azbuddy.ui.menu.ygm=Sjik YGM azbuddy.ui.menu.enc=Klembord versjleutele azbuddy.ui.menu.dec=Klembord \u00f3ntsjleutele azbuddy.ui.menu.sign=\u00d3ngerteiken klembord azbuddy.ui.menu.verify=Verifieer klembord azbuddy.ui.table.lastseen=L\u00e8s gezeen Button.retry=&Opnuuj perbere Button.ignore=&Negere v3.MainWindow.menu.view.footer=Vrunjbalk azbuddy.downspeed=KB/s max. downloadsjnelheid vrundj [0: onbeperk] security.crypto.badpw='t Opgegaeve wachwaord is neet juus ConfigView.section.security.backupkeys=Reservekopie\u00eb make van sjleutels ConfigView.section.security.backupkeys.button=Reservekopie\u00eb make ConfigView.section.security.restorekeys=Sjleutels hersjt\u00e8lle oet e besjtandj ConfigView.section.security.restorekeys.button=Hersjt\u00e8lle ConfigView.section.security.op.error.title=Bewirking misl\u00f6k ConfigView.section.security.op.error=Misl\u00f6k \u00f3m de bewirking aaf te make: %1 ConfigView.section.security.restart.title=Hersjtart vereis ConfigView.section.security.restart.msg=Vuze zal noe hersjtarten \u00f3m de bewirking compleet te make. ConfigView.section.security.system.managed=Systeembehierde sjleutelbesjirming azbuddy.ui.table.msg_queued=In rie azbuddy.chat.says=%1 zaet: Button.bar.show=Laote zeen Button.bar.hide=Verberg Button.bar.share=Deil Button.bar.add=Vrunj toevoege Button.bar.edit=Bew\u00e8rke Button.bar.edit.cancel=Vaerdig mit bew\u00e8rke v3.MainWindow.menu.view.pluginbar=Plug-in-balk MainWindow.dialog.select.vuze.file=Selecteer Vuze-besjtandj metasearch.addtemplate.title=Zeuktemplate installere? metasearch.addtemplate.desc=Wits te zeker des se de zeuktemplate mit de naam '%1' wils insjtallere? v3.share.private.title=Torrent aan 't deile v3.share.private.text=De geselecteerde torrent is gemarkeerd es 'ne priv\u00e9torrent.\n\nDoe k\u00f3ns gein priv\u00e9torrents deile. metasearch.addtemplate.dup.desc=Zeuktemplate %1 is al ge\u00efnstalleerd metasearch.export.select.template.file=Template beware metasearch.import.select.template.file=Template \u00e4\u00f6pene dialog.uiswitch.title=Nao de Vuze-interface \u00f3msjakele dialog.uiswitch.text=Doe m\u00f3s de Vuze-interface gebroeke \u00f3m gebroek te kinne make van dees meugelikheid. dialog.uiswitch.button=Nao de Vuze-interface \u00f3msjakele azbuddy.tracker.enabled=Gaef prioriteit aan vrunj mit 't downloade van dezelfde inhawd azbuddy.protocolspeed=KB/s max vrundj protocol overhead v3.MainWindow.button.download=Downloade v3.MainWindow.button.run=Gedownload besjtandj sjtarte v3.activity.header.vuze.news=Vuze-nuuts v3.MainWindow.search.go.tooltip=Zeuke oetveure v3.MainWindow.search.last.tooltip=Tr\u00f6kgaon nao zeukresultate ConfigView.section.security.nopw=Gei wachwaord opgegaeve ConfigView.section.security.nopw_v=Gei wachwaord besjikbaar, log dich esteblief in bie Vuze fileplugininstall.install.title=Plugin installere? fileplugininstall.install.desc=W\u00e8ts se zeker des se plugin '%1', version %2 wils installere? fileplugininstall.duplicate.title=Plugin duplicere fileplugininstall.duplicate.desc=Plugin '%1', versie %2 is al ge\u00efnstalleerd azbuddy.online_status=Online-status azbuddy.os_away=Eweg azbuddy.os_not_avail=Neet besjikbaar azbuddy.os_busy=Bezig azbuddy.ui.menu.disconnect=Verb\u00e8njing verbraeke iconBar.queue.tooltip=In de wach z\u00e8tte MainWindow.menu.help.faq=D\u00e8k gesjt\u00e8lde vraoge (FAQ) #what you've watched? Discover more with a single click... TableColumn.header.#=Nr: azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_sk_SK.properties0000644000175000017500000033437611301156004026121 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=.torrent s\u00fabor Main.parameter.usage=Pou\u017eitie : java org.gudy.azureus2.cl.Main [parametre] "s\u00fabor.torrent" "cie\u013eov\u00e1 zlo\u017eka" Main.parameter.maxUploads=Max. po\u010det simult\u00e1lnnych uploadov Main.parameter.maxSpeed=Max. r\u00fdchlos\u0165 uploadu v bajtoch/sek MainWindow.menu.file=&S\u00fabor MainWindow.menu.file.open=&Otvori\u0165 MainWindow.menu.file.create=&Vytvori\u0165 Torrent MainWindow.menu.file.create.fromfile=Zo &s\u00faboru MainWindow.menu.file.create.fromdir=Zo z&lo\u017eky MainWindow.menu.file.export=&Exportova\u0165 Torrent do XML... MainWindow.menu.file.import=&Importova\u0165 Torrent z XML... MainWindow.menu.file.closetab=Zatvori\u0165 z\u00e1&lo\u017eku MainWindow.menu.file.closewindow=Zatvori\u0165 &okno MainWindow.menu.file.exit=&Koniec MainWindow.dialog.choose.file=Vyberte .torrent s\u00fabor MainWindow.menu.file.folder=Z&lo\u017eku MainWindow.dialog.choose.folder=Vyberte zlo\u017eku s .torrent s\u00fabormi MainWindow.menu.view=&Zobrazi\u0165 MainWindow.menu.view.show=Zobrazi\u0165 MainWindow.menu.view.mytorrents=&Moje Torrenty MainWindow.menu.view.configuration=&Nastavenie MainWindow.menu.view.console=&Konzola MainWindow.menu.closealldetails=Schova\u0165 v\u0161etky &Detaily MainWindow.menu.closealldownloadbars=Schova\u0165 v\u0161etky &Panely s\u0165ahovania MainWindow.menu.language=&Jazyk ConfigView.section.language=Jazyk MainWindow.menu.window=&Okno MainWindow.menu.window.minimize=&Minimalizova\u0165 MainWindow.menu.window.zoom=&Zv\u00e4\u010d\u0161i\u0165 MainWindow.menu.window.alltofront=Zobrazi\u0165 v\u0161etky navrchu MainWindow.menu.help=&N\u00e1poveda MainWindow.menu.help.about=&O programe Vuze MainWindow.about.title=O programe Vuze MainWindow.about.section.developers=V\u00fdvoj\u00e1ri MainWindow.about.section.translators=Prekladatelia MainWindow.about.internet.homepage=Domovsk\u00e1 str\u00e1nka programu Vuze MainWindow.about.internet.sourceforge=Sourceforge - Str\u00e1nka projektu MainWindow.about.internet.sourceforgedownloads=Sourceforge - Downloady MainWindow.about.internet.bugreports=Hl\u00e1senie ch\u00fdb MainWindow.about.internet.forumdiscussion=Diskusn\u00e9 f\u00f3ra MainWindow.dialog.choose.savepath=Vyberte cie\u013eov\u00fa zlo\u017eku MainWindow.dialog.choose.savepath_forallfiles=Vyberte cie\u013eov\u00fa zlo\u017eku pre V\u0160ETKY s\u00fabory MainWindow.status.latestversion=Najnov\u0161\u00ed MainWindow.status.latestversion.clickupdate=Kliknite pre aktualiz\u00e1ciu MainWindow.status.unknown=nezn\u00e1my MainWindow.status.checking=zis\u0165ujem MyTorrentsView.mytorrents=Moje Torrenty TableColumn.header.name=N\u00e1zov TableColumn.header.size=Ve\u013ekos\u0165 TableColumn.header.done=Hotovo TableColumn.header.done.info=Ud\u00e1va, na ko\u013eko percent je pr\u00e1ve prebiehaj\u00faca \u00faloha dokon\u010den\u00e1 TableColumn.header.status=Stav TableColumn.header.status.info=Ud\u00e1va, \u010do sa s Torrentom pr\u00e1ve deje TableColumn.header.seeds=Zdroje TableColumn.header.seeds.info=Ud\u00e1va po\u010det pripojen\u00fdch zdrojov (celkov\u00fd po\u010det zdrojov) TableColumn.header.peers=Klienti TableColumn.header.peers.info=Ud\u00e1va po\u010det pripojen\u00fdch klientov (celkov\u00fd po\u010det klientov) TableColumn.header.downspeed=Download r\u00fdchlos\u0165 TableColumn.header.upspeed=Upload r\u00fdchlos\u0165 TableColumn.header.eta=Zost\u00e1va TableColumn.header.tracker=Tracker TableColumn.header.tracker.info=Ud\u00e1va stav Trackera TableColumn.header.trackernextaccess=\u010eal\u0161\u00ed pr\u00edstup k Trackeru TableColumn.header.trackernextaccess.info=Kedy nastane \u010fal\u0161\u00ed pr\u00edstup k Trackeru TableColumn.header.priority=Priorita TableColumn.header.priority.info=Ur\u010duje, ako ve\u013ek\u00fd d\u00e1tov\u00fd tok pre upload je vyhraden\u00fd pre Torrent MyTorrentsView.menu.showdetails=&Zobrazi\u0165 Detaily MyTorrentsView.menu.showdownloadbar=Zobrazi\u0165 &Panel s\u0165ahovania MyTorrentsView.menu.open=&Otvori\u0165 MyTorrentsView.menu.setpriority=Nastavi\u0165 &prioritu MyTorrentsView.menu.setpriority.high=&Vysok\u00e1 MyTorrentsView.menu.setpriority.low=&N\u00edzka MyTorrentsView.menu.start=&Spusti\u0165 MyTorrentsView.menu.stop=Za&stavi\u0165 MyTorrentsView.menu.remove=O&dobra\u0165 MyTorrentsView.menu.changeTracker=Prida\u0165 URL &Trackera TrayWindow.menu.exit=&Koniec TrayWindow.menu.show=&Zobrazi\u0165 Vuze SystemTray.menu.exit=&Koniec SystemTray.menu.closealldownloadbars=Schova\u0165 v\u0161etky &Panely s\u0165ahovania SystemTray.menu.show=&Zobrazi\u0165 Vuze PeersView.ip.info=IP adresa pripojen\u00e9ho klienta PeersView.port.info=Pou\u017eit\u00fd port PeersView.T.info=L (local): Pripojenie bolo nadviazan\u00e9 odtia\u013eto, R (remote): Pripojenie bolo nadviazan\u00e9 zvonku PeersView.T.L.tooltip=Pripojenie bolo nadviazan\u00e9 odtia\u013eto PeersView.T.R.tooltip=Pripojenie bolo nadviazan\u00e9 zvonku PeersView.I1=I (Klient m\u00e1 pre n\u00e1s zauj\u00edmav\u00e9 \u010dasti) PeersView.I1.info=M\u00e1 klient pre n\u00e1s zauj\u00edmav\u00e9 \u010dasti? PeersView.C1=C (Vybran\u00fd klientom) PeersView.C1.info=Ud\u00e1va, \u010di klient zastavuje va\u0161e s\u0165ahovanie od neho PeersView.pieces=Diely PeersView.downloadspeed=Download r\u00fdchlos\u0165 PeersView.download=Prijat\u00fdch PeersView.I2=I (Klient sa zauj\u00edma o na\u0161e \u010dasti) PeersView.I2.info=Zauj\u00edma sa klient o na\u0161e \u010dasti? PeersView.C2=C (Klient je vybran\u00fd) PeersView.C2.info=Ud\u00e1va, \u010di blokujete klienta od s\u0165ahovania PeersView.uploadspeed=Upload r\u00fdchlos\u0165 PeersView.uploadspeed.info=R\u00fdchlos\u0165 odosielania ku klientovi PeersView.upload=Odoslan\u00fdch PeersView.upload.info=Celkov\u00e9 mno\u017estvo odoslan\u00fdch d\u00e1t klientovi PeersView.statup=Odhad Up PeersView.statup.info=Odhadovan\u00e1 celkov\u00e1 r\u00fdchlos\u0165 odosielania klienta PeersView.S.info=Nespo\u013eahliv\u00fd: Klient m\u00f4\u017ee by\u0165 ozna\u010den\u00fd "nespo\u013eahliv\u00fdm" manu\u00e1lne alebo automaticky (za nedostato\u010dne r\u00fdchle odosielanie d\u00e1t) PeersView.downloadspeedoverall=Celkov\u00e1 Download r\u00fdchlos\u0165 PeersView.optunchoke=Unchoke PeersView.client=Klient PeersView.client.info=BitTorrent program, ktor\u00fd klient pou\u017e\u00edva PeersView.menu.snubbed=&Ned\u00f4veryhodn\u00fd PeersView.title.short=Zdroje PeersView.title.full=Zdroje ConfigView.section.files=S\u00fabory ConfigView.label.usefastresume=Pou\u017e\u00edva\u0165 m\u00f3d R\u00fdchleho obnovenia ConfigView.label.incrementalfile=Povoli\u0165 postupn\u00e9 vytv\u00e1ranie s\u00faborov ConfigView.label.defaultsavepath=Uklada\u0165 do predvolenej zlo\u017eky ConfigView.button.browse=Prech\u00e1dza\u0165... ConfigView.dialog.choosedefaultsavepath=Vyberte predvolen\u00fa cie\u013eov\u00fa zlo\u017eku ConfigView.section.server=Server ConfigView.section.global=V\u0161eobecn\u00e9 ConfigView.label.disconnetseed=Ke\u010f som zdroj, odpoji\u0165 ostatn\u00e9 zdroje ConfigView.label.switchpriority=Ke\u010f som zdroj, automaticky prepn\u00fa\u0165 na n\u00edzku prioritu ConfigView.label.maxdownloads=Max. po\u010det simult\u00e1lnnych downloadov [0: neobmedzen\u00fd] ConfigView.label.maxdownloads.tooltip=V\u017edy budete m\u00f4c\u0165 akt\u00edvne s\u0165ahova\u0165 zadan\u00fd po\u010det s jednou v\u00fdnimkou.\nDokon\u010den\u00fd Torrent vyhovuj\u00faci Top Priorite m\u00f4\u017ee prevzia\u0165 akt\u00edvny download slot ak je to naozaj nutn\u00e9. ConfigView.label.maxactivetorrents=Max. po\u010det akt\u00edvnych Torrentov [0: neobmedzen\u00fd]\n - Nov\u00e9 Torrenty sa automaticky nespustia, pokia\u013e ich s\u0165ahujete/distribuujete viac ConfigView.label.priorityExtensions=Zv\u00fd\u0161i\u0165 prioritu pre s\u00fabory s pr\u00edponou\n - napr\u00edklad: .txt;.nfo;.jpg ConfigView.section.transfer=Prenos ConfigView.label.maxuploads=Predvolen\u00fd max. po\u010det uploadov na Torrent ConfigView.label.maxuploadspeed=Celkov\u00e1 maxim\u00e1lna r\u00fdchlos\u0165 uploadu v kB/s [0: neobmedzen\u00e1] ConfigView.label.saveresumeinterval=Uklada\u0165 d\u00e1ta pre obnovenie ka\u017ed\u00fdch ConfigView.unlimited=Neobmedzene ConfigView.section.display=Zobrazenie ConfigView.label.opendetails=Automaticky zobrazova\u0165 Detaily ConfigView.label.openbar=Automaticky zobrazova\u0165 Panel s\u0165ahovania ConfigView.label.closetotray=Zatvorenie minimalizuje do System Tray ConfigView.label.minimizetotray=Minimalizovanie minimalizuje do System Tray ConfigView.section.general=V\u0161eobecn\u00e9 ConfigView.section.start=Spustenie ConfigView.label.showsplash=Zobrazi\u0165 uv\u00edtaciu obrazovku (Splash Screen) ConfigView.label.autoupdate=Zobrazi\u0165 dial\u00f3g s aktualiz\u00e1ciou, ak je dostupn\u00e1 ConfigView.label.openconsole=Po spusten\u00ed otvori\u0165 Konzolu ConfigView.label.openconfig=Po spusten\u00ed otvori\u0165 Nastavenia ConfigView.label.startminimized=Spusti\u0165 Vuze minimalizovan\u00fd ConfigView.section.irc=IRC ConfigView.label.ircserver=Server ConfigView.label.ircchannel=Kan\u00e1l ConfigView.label.irclogin=Prez\u00fdvka ConfigView.section.security=Zabezpe\u010denie ConfigView.label.password=Chr\u00e1ni\u0165 Vuze heslom\n - Bude po\u017eadovan\u00e9 pri obnoven\u00ed z ikonky a pri spusten\u00ed. ConfigView.label.passwordconfirm=Heslo (znovu - potvrdenie) ConfigView.label.passwordmatch=Heslo je akt\u00edvne : ConfigView.label.passwordmatchnone=Nie ConfigView.label.passwordmatchno=Nie / Hesl\u00e1 sa nezhoduj\u00fa ConfigView.label.passwordmatchyes=\u00c1no ConfigView.button.save=Ulo\u017ei\u0165 ConfigView.title.short=Nastavenie ConfigView.title.full=Nastavenie ConsoleView.title.short=Konzola ConsoleView.title.full=Konzola FileItem.write=Z\u00e1pis FileItem.read=\u010c\u00edtanie FileItem.normal=norm\u00e1lna FileItem.high=vysok\u00e1 FileItem.donotdownload=Nes\u0165ahova\u0165 FilesView.name=Meno FilesView.size=Ve\u013ekos\u0165 FilesView.done=Hotovo FilesView.%=% FilesView.firstpiece=Prv\u00fd diel \u010d. FilesView.numberofpieces=Po\u010det dielov FilesView.pieces=Diely FilesView.mode=M\u00f3d FilesView.priority=Priorita FilesView.menu.open=&Otvori\u0165 FilesView.menu.setpriority=Nastavi\u0165 &prioritu FilesView.menu.setpriority.high=&Vysok\u00e1 FilesView.menu.setpriority.normal=&Norm\u00e1lna FilesView.menu.setpriority.skipped=Ne&s\u0165ahova\u0165 FilesView.title.short=S\u00fabory FilesView.title.full=S\u00fabory GeneralView.section.downloaded=Stiahnut\u00fdch GeneralView.label.status.file=Stav s\u00faboru GeneralView.label.status.pieces=Stiahnut\u00e9 diely GeneralView.section.availability=Dostupnos\u0165 GeneralView.label.status.pieces_available=Dostupnos\u0165 dielov GeneralView.section.transfer=Presun GeneralView.section.info=Inform\u00e1cie GeneralView.title.short=Torrent GeneralView.title.full=Torrent GeneralView.label.timeelapsed=Uplynut\u00fd \u010das : GeneralView.label.remaining=Zost\u00e1vaj\u00faci \u010das : GeneralView.label.downloaded=Stiahnut\u00fdch : GeneralView.label.downloadspeed=R\u00fdchlos\u0165 downloadu : GeneralView.label.maxuploads=Max. po\u010det uploadov : GeneralView.label.maxuploads.tooltip=Maxim\u00e1lny po\u010det klientov, ktor\u00ed bud\u00fa obsl\u00fa\u017een\u00ed v danom \u010dase. GeneralView.label.uploaded=Odoslan\u00fdch : GeneralView.label.uploadspeed=R\u00fdchlos\u0165 uploadu : GeneralView.label.seeds=Zdroje : GeneralView.label.peers=Klienti : GeneralView.label.totalspeed=Celkov\u00e1 r\u00fdchlos\u0165 : GeneralView.label.totalspeed.tooltip=Celkov\u00e1 r\u00fdchlos\u0165 v\u0161etk\u00fdch pripojen\u00fdch klientov GeneralView.label.averagespeed=priemerne GeneralView.label.filename=N\u00e1zov : GeneralView.label.totalsize=Celkov\u00e1 ve\u013ekos\u0165 : GeneralView.label.savein=Cie\u013e : GeneralView.label.numberofpieces=Po\u010det dielov : GeneralView.label.size=Ve\u013ekos\u0165 dielu : GeneralView.label.tracker=Stav Trackera : GeneralView.label.updatein=Aktualizova\u0165 za : GeneralView.label.trackerurl=URL Trackera : GeneralView.label.trackerurlupdate=Aktualizova\u0165 Tracker GeneralView.label.comment=Koment\u00e1r : ManagerItem.waiting=\u010cakanie ManagerItem.allocating=Alok\u00e1cia miesta ManagerItem.checking=Overovanie ManagerItem.ready=Pripraven\u00fd ManagerItem.downloading=S\u0165ahovanie ManagerItem.seeding=Distrib\u00facia ManagerItem.stopped=Zastaven\u00e9 ManagerItem.error=Chyba ManagerItem.high=vysok\u00e1 ManagerItem.low=n\u00edzka MinimizedWindow.name=N\u00e1zov: PiecesView.size=Ve\u013ekos\u0165 PiecesView.numberofblocks=Po\u010det blokov PiecesView.blocks=Bloky PiecesView.completed=Prijat\u00fdch PiecesView.availability=Dostupnos\u0165 PiecesView.reservedby=Rezervovan\u00e9 PiecesView.writers=Blok \u00fa\u010dastn\u00edkov PiecesView.title.short=Diely PiecesView.title.full=Diely SystemTray.tooltip.seeding=%1 distribuovan\u00fdch, SystemTray.tooltip.downloading=%1 s\u0165ahovan\u00fdch, DownloadManager.error.filenotfound=S\u00fabor nen\u00e1jden\u00fd DownloadManager.error.fileempty=Torrent s\u00fabor je pr\u00e1zdny DownloadManager.error.filetoobig=Torrent s\u00fabor je prive\u013ek\u00fd DownloadManager.error.filewithouttorrentinfo=Inform\u00e1cie o Torrente neboli v s\u00fabore n\u00e1jden\u00e9 DownloadManager.error.unsupportedencoding=Nepodporovan\u00e9 k\u00f3dovanie DownloadManager.error.ioerror=Chyba V/V DownloadManager.error.sha1=Algoritmus nie je podporovan\u00fd (SHA1) PeerManager.status.offline=Offline PeerManager.status.checking=Aktualiz\u00e1cia PeerManager.status.finished=Dokon\u010den\u00e9 PeerManager.status.finishedin=Dokon\u010den\u00e9 za MainWindow.upgrade.assistant=Asistent aktualiz\u00e1cie MainWindow.upgrade.newerversion=Je k dispoz\u00edcii nov\u00e1 verzia programu Azureus. MainWindow.upgrade.explanation=Tento asistent v\u00e1m pom\u00f4\u017ee aktualizova\u0165 Azureus. Stiahne nov\u00fa verziu a re\u0161tartuje program. MainWindow.upgrade.explanation.manual=Nov\u00fa verziu m\u00f4\u017eete nain\u0161talova\u0165 ru\u010dne, zavret\u00edm programu, stiahnut\u00edm novej verzie do zlo\u017eky programu a jeho op\u00e4tovn\u00fdm spusten\u00edm. MainWindow.upgrade.step1=Krok 1: Stiahnutie novej verzie MainWindow.upgrade.step2=Krok 2: Zavretie tejto verzie a spustenie novej verzie programu MainWindow.upgrade.hint1=Tip: Tla\u010didlom Dokon\u010di\u0165 umo\u017en\u00edte vykona\u0165 cel\u00fd proces automaticky MainWindow.upgrade.hint2=Tip: Ak chcete ukon\u010di\u0165 Vuze nesk\u00f4r, pou\u017eite tla\u010didlo Storno.\n\tPo ukon\u010den\u00ed programu potom prejmenujte s\u00fabor Azureus2-new.jar na Azureus2.jar MainWindow.upgrade.error.downloading.hint=Chyba: Nepodarilo sa stiahnu\u0165 nov\u00fa verziu, pros\u00edm aktualizujte ru\u010dne. MainWindow.upgrade.section.info=Dostupn\u00e1 nov\u00e1 verzia programu MainWindow.upgrade.section.manual=Ru\u010dn\u00e1 aktualiz\u00e1cia MainWindow.upgrade.section.automatic=Automatick\u00e1 aktualiz\u00e1cia MainWindow.upgrade.tooltip.progressbar=Priebeh s\u0165ahovania je zobrazen\u00fd tu Button.next=\u010ealej Button.finish=Dokon\u010di\u0165 Button.cancel=Storno LocaleUtil.title=Vyberte k\u00f3dovanie LocaleUtil.section.chooseencoding=Vyberte k\u00f3dovanie pre s\u00fabor LocaleUtil.label.chooseencoding=Vyberte k\u00f3dovanie, ktor\u00e9 najviac zodpoved\u00e1 LocaleUtil.label.hint.doubleclick=Tip : Poklikanie na riadok vyberie k\u00f3dovanie a zavrie dial\u00f3g LocaleUtil.label.checkbox.rememberdecision=Zapam\u00e4ta\u0165 si nastavenie pre ostatn\u00e9 s\u00fabory LocaleUtil.column.encoding=K\u00f3dovanie IrcClient.copyright=Vuze pou\u017e\u00edva PircBot Java IRC API - http://www.jibble.org/pircbot.php IrcClient.connecting=Prip\u00e1janie k IrcClient.connected=Pripojen\u00e9 k IrcClient.joining=Otv\u00e1ranie kan\u00e1lu IrcClient.channel=Kan\u00e1l IrcClient.joined=otvoren\u00fd IrcClient.error=Chyba IrcClient.hasjoined=vst\u00fapil IrcClient.haskicked=bol vyhoden\u00fd IrcClient.hasleft=odi\u0161iel IrcClient.nowknown=je teraz zn\u00e1my ako IrcClient.topicforchannel=T\u00e9ma pre kan\u00e1l IrcClient.disconnected=Odpojen\u00e9 od IrcClient.noNick=Prez\u00fdvka nie je nastaven\u00e1. Pou\u017eite 'Nastavenie' IrcView.actionnotsupported=T\u00e1to akcia nie je podporovan\u00e1 IrcView.clientsconnected=pou\u017e\u00edvate\u013eov IrcView.privateto=Pre IrcView.privatefrom=Od IrcView.noticefrom=Ozn\u00e1menie : IrcView.errormsg=Zl\u00e1 syntax /msg : /msg pou\u017e\u00edvate\u013e spr\u00e1va IrcView.help=Pou\u017eite\u013en\u00e9 pr\u00edkazy s\u00fa :\n . /help : zobraz\u00ed t\u00fato n\u00e1povedu\n . /nick | /name : zmen\u00ed va\u0161u prez\u00fdvku \n . /me \u00fakon : po\u0161le ako \u00fakon \n . /msg pou\u017e\u00edvate\u013e spr\u00e1va : po\u0161le priv\u00e1tnu spr\u00e1vu \n . /r message : odpove\u010f na posledn\u00fa priv\u00e1tnu spr\u00e1vu\n . /join #kan\u00e1l : zmen\u00ed aktu\u00e1lny kan\u00e1l PasswordWindow.title=Vuze je uzamknut\u00fd PasswordWindow.passwordprotected=Vuze je chr\u00e1nen\u00fd heslom.\nPre zobrazenie hlavn\u00e9ho okna, vypl\u0148te heslo : TrackerChangerWindow.title=Prida\u0165 Tracker TrackerChangerWindow.newtracker=Nov\u00e1 URL Trackera PeersView.discarded=Zahoden\u00fdch PeersView.discarded.info=D\u00e1ta, ktor\u00e9 v\u00e1m boli doru\u010den\u00e9 a pritom neboli potrebn\u00e9 a tak boli zahoden\u00e9 discarded=zahoden\u00fdch MyTorrentsView.menu.move=Posun\u00fa\u0165 MyTorrentsView.menu.moveUp=&Nahor MyTorrentsView.menu.moveDown=Na&dol GeneralView.label.hashfails=Nes\u00fahlasiace hashe : GeneralView.label.shareRatio=Pomer zdie\u013eania : ConfigView.section.downloadManagement=Spr\u00e1vca s\u0165ahovania ConfigView.label.startRatioPeers=Za\u010da\u0165 zdie\u013ea\u0165, ke\u010f je menej ako 1 zdroj na ConfigView.text.neverStop=Nikdy neukon\u010di\u0165 ConfigView.text.neverStart=Nikdy neza\u010da\u0165 ConfigView.text.peers=klientov ConfigView.label.checkOncompletion=Po dokon\u010den\u00ed znovu skontrolova\u0165 diely wizard.title=Vytvori\u0165 Torrent wizard.previous=< Sp\u00e4\u0165 wizard.next=\u010ealej > wizard.finish=Dokon\u010di\u0165 wizard.mode=Tracker / M\u00f3d wizard.tracker=Tracker: wizard.invalidurl=T\u00e1to URL nie je platn\u00e1 wizard.singlefile=Jeden s\u00fabor wizard.singlefile.help=Vytvori\u0165 Torrent z jedn\u00e9ho s\u00faboru wizard.directory=Zlo\u017eka wizard.directory.help=Vytvori\u0165 Torrent zo zlo\u017eky wizard.choosefile=Vyberte s\u00fabor wizard.file=S\u00fabor : wizard.browse=Prech\u00e1dza\u0165... wizard.choosedirectory=Vyberte zlo\u017eku wizard.invalidfile=Neplatn\u00fd s\u00fabor! wizard.invaliddirectory=Neplatn\u00e1 zlo\u017eka! wizard.torrentFile=Torrent s\u00fabor wizard.choosetorrent=Ulo\u017ei\u0165 Torrent s\u00fabor ako wizard.information=Inform\u00e1cia wizard.notimplemented=Zatia\u013e nie je implementovan\u00e9 wizard.progresstitle=Vytv\u00e1ranie Torrent s\u00faboru wizard.savingfile=Ukladanie s\u00faboru... wizard.filesaved=S\u00fabor ulo\u017een\u00fd. wizard.close=Zavrie\u0165 Torrent.create.progress.piecelength=Ve\u013ekos\u0165 dielu: Torrent.create.progress.piececount=Po\u010det dielov: Torrent.create.progress.totalfilesize=Celkov\u00e1 ve\u013ekos\u0165: Torrent.create.progress.totalfilecount=Po\u010det s\u00faborov: Torrent.create.progress.parsingfiles=Anal\u00fdza s\u00faborov Torrent.create.progress.hashing=Vytv\u00e1ranie hashov MainWindow.upgrade.downloadingfrom=S\u0165ahovanie z : MainWindow.menu.view.ipFilter=&IP filtre ConfigView.section.ipfilter=IP filtre ConfigView.section.ipfilter.description=Popis ConfigView.section.ipfilter.start=Za\u010diato\u010dn\u00e1 IP ConfigView.section.ipfilter.end=Kone\u010dn\u00e1 IP ConfigView.section.ipfilter.add=Prida\u0165 ConfigView.section.ipfilter.remove=Odobra\u0165 ConfigView.section.ipfilter.edit=Upravi\u0165 ConfigView.section.ipfilter.save=Ulo\u017ei\u0165 ConfigView.section.ipfilter.editFilter=Upravi\u0165 filter ConfigView.section.ipfilter.enable=Povoli\u0165 PeersView.menu.close=&Zavrie\u0165 seedmore.title=Torrent nie je dostato\u010dne distribuovan\u00fd seedmore.shareratio=Pomer s\u0165ahovania tohto Torrentu je seedmore.uploadmore=Pre BitTorrent sie\u0165 nie je dobr\u00e9 ma\u0165 pomer zdie\u013eania pod 100%.\nNechajte tento Torrent zdie\u013ea\u0165 e\u0161te chv\u00ed\u013eu.\nNaozaj si prajete Torrent zastavi\u0165? ConfigView.label.showpopuponclose=Zobrazi\u0165 potvrdenie pri ukon\u010den\u00ed zdie\u013eania, ak m\u00e1te pomer zdie\u013eania men\u0161\u00ed ako 1 ConfigView.label.startNumSeeds=\nZa\u010da\u0165 zdie\u013ea\u0165, ak je menej ne\u017e\n - Anuluje ostatn\u00e9 nastavenia ConfigView.label.seeds=zdrojmi ConfigView.section.seeding=Distrib\u00facia MyTorrentsView.menu.removeand=Odobra\u0165 a MyTorrentsView.menu.removeand.deletetorrent=Zmaza\u0165 .&torrent MyTorrentsView.menu.removeand.deletedata=Zmaza\u0165 &d\u00e1ta MyTorrentsView.menu.removeand.deleteboth=Zmaza\u0165 .torrent &aj d\u00e1ta deletedata.title=!!! Upozornenie !!! deletedata.message1=Chyst\u00e1te sa zmaza\u0165 D\u00c1TA z :\n MainWindow.menu.file.configure=Sprievodca &nastaven\u00edm configureWizard.title=Sprievodca nastaven\u00edm configureWizard.welcome.title=Vitajte v Sprievodcovi nastaven\u00edm configureWizard.welcome.message=Tento sprievodca v\u00e1m pom\u00f4\u017ee nastavi\u0165 Vuze pre ka\u017edodenn\u00e9 pou\u017e\u00edvanie. Podrobnej\u0161ie nastavenie m\u00f4\u017eete urobi\u0165 v menu N\u00e1stroje -> Nastavenie configureWizard.transfer.title=Nastavenie Pripojenia a Prenosov configureWizard.transfer.hint=Tip : Najlep\u0161ie je nastavi\u0165 o nie\u010do pomal\u0161iu linku, ne\u017e je v skuto\u010dnosti. configureWizard.transfer.message=Vyberte sp\u00f4sob pripojenia. Majte v\u0161ak na pam\u00e4ti, \u017ee nepovolenie r\u00fdchleho uploadu m\u00f4\u017ee vies\u0165 k pomal\u00fdm downloadom. Ke\u010f\u017ee sa uploady po\u010d\u00edtaj\u00fa pre ka\u017ed\u00fd Torrent ZVL\u00c1\u0160\u0164, vedie snaha stiahnu\u0165 prive\u013ea Torrentov naraz tie\u017e k pomal\u0161iemu s\u0165ahovaniu. Odpor\u00fa\u010dame nastavenie 5kB/s ako MINIMUM. \u010c\u00edm r\u00fdchlej\u0161ie budete d\u00e1ta odosiela\u0165, t\u00fdm r\u00fdchlej\u0161ie ich budete i s\u0165ahova\u0165 (s oh\u013eadom na r\u00fdchlos\u0165 Torrentu). configureWizard.transfer.connection=Pripojenie configureWizard.transfer.connection.0=Vlastn\u00e9 configureWizard.transfer.connection.1=Modem configureWizard.transfer.connection.2=ADSL/K\u00e1bel xxx/128 kbps configureWizard.transfer.connection.3=ADSL/K\u00e1bel xxx/256 kbps configureWizard.transfer.connection.4=ADSL/K\u00e1bel xxx/384 kbps configureWizard.transfer.connection.5=ADSL/K\u00e1bel xxx/512 kbps configureWizard.transfer.connection.6=ADSL/K\u00e1bel xxx/768 kbps configureWizard.transfer.connection.7=ADSL/K\u00e1bel xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Max. r\u00fdchlos\u0165 uploadu (KB/s) configureWizard.transfer.maxActiveTorrents=Max. akt\u00edvnych Torrentov configureWizard.transfer.maxDownloads=Max. s\u0165ahovan\u00fdch Torrentov configureWizard.transfer.maxUploadsPerTorrent=Max. uploadov na Torrent configureWizard.nat.title=NAT / Port servera configureWizard.nat.message=Aby ste z\u00edskali \u010do najviac z BitTorrent siete, mali by ste by\u0165 pristupn\u00ed z internetu. V\u00fdchodz\u00ed port BitTorrentu je 6881.\nTento n\u00e1stroj v\u00e1m umo\u017en\u00ed tento port zmeni\u0165 a n\u00e1sledne ho otestova\u0165. configureWizard.nat.test=Sk\u00fasi\u0165 configureWizard.nat.testing=Testujem port configureWizard.nat.ko=Chyba NAT configureWizard.nat.unable=Nem\u00f4\u017eem otestova\u0165 configureWizard.file.title=Torrenty / S\u00fabory configureWizard.file.message1=Vuze bude uklada\u0165 v\u0161etky otvoren\u00e9 Torrenty do \u0161pecifickej zlo\u017eky, ktor\u00fa m\u00f4\u017eete ur\u010di\u0165 tu: configureWizard.file.path=Cesta: configureWizard.file.browse=Prech\u00e1dza\u0165... configureWizard.file.message2=Vuze je schopn\u00fd r\u00fdchlo obnovi\u0165 Torrent a takmer okam\u017eite pokra\u010dova\u0165 v distrib\u00facii/s\u0165ahovan\u00ed. Aby tak mohol fungova\u0165, mus\u00ed si k Torrentom uklada\u0165 dodato\u010dn\u00e9 d\u00e1ta. Takto je mo\u017en\u00e9 obnovi\u0165 aj \u010diasto\u010dne stiahnut\u00e9 diely. configureWizard.file.fastResume=Povoli\u0165 R\u00fdchle obnovenie configureWizard.file.invalidPath=Neplatn\u00e1 zlo\u017eka configureWizard.finish.title=Hotovo configureWizard.finish.message=Vuze je nastaven\u00fd, prajeme pr\u00edjemn\u00fa z\u00e1bavu! wizard.close.confirmation=Potvrdenie wizard.close.message=Naozaj chcete otvori\u0165 tohto sprievodcu pri \u010fal\u0161om spusten\u00ed? exportTorrentWizard.title=Exportova\u0165 Torrent do XML exportTorrentWizard.torrentfile.title=V\u00fdber Torrentu exportTorrentWizard.torrentfile.message=Vyberte Torrent s\u00fabor pre export exportTorrentWizard.torrentfile.path=Cesta: exportTorrentWizard.torrentfile.browse=Prech\u00e1dza\u0165... exportTorrentWizard.torrentfile.invalidPath=Neplatn\u00fd Torrent s\u00fabor exportTorrentWizard.exportfile.title=Exportovan\u00fd s\u00fabor exportTorrentWizard.exportfile.message=Vypl\u0148te n\u00e1zov exportovan\u00e9ho xml s\u00faboru exportTorrentWizard.exportfile.path=Cesta: exportTorrentWizard.exportfile.browse=Prech\u00e1dza\u0165... exportTorrentWizard.exportfile.invalidPath=Neplatn\u00fd exportovan\u00fd s\u00fabor exportTorrentWizard.finish.title=Hotovo exportTorrentWizard.finish.message=Export bol \u00faspe\u0161ne dokon\u010den\u00fd exportTorrentWizard.process.inputfilebad.title=S\u00fabor Torrentu je chybn\u00fd exportTorrentWizard.process.inputfilebad.message=Chyba pri \u010d\u00edtan\u00ed vstupn\u00e9ho s\u00faboru: exportTorrentWizard.process.outputfileexists.title=S\u00fabor existuje exportTorrentWizard.process.outputfileexists.message=V\u00fdstupn\u00fd s\u00fabor u\u017e existuje - prep\u00edsa\u0165? exportTorrentWizard.process.torrentfail.title=Chyba pri \u010d\u00edtan\u00ed Torrentu exportTorrentWizard.process.exportfail.title=Chyba pri exporte Torrentu exportTorrentWizard.process.unknownfail.title=Neo\u010dak\u00e1van\u00e1 chyba importTorrentWizard.title=Importova\u0165 Torrent z XML importTorrentWizard.torrentfile.title=V\u00fdber Torrentu importTorrentWizard.torrentfile.message=Vyberte Torrent s\u00fabor na import importTorrentWizard.torrentfile.path=Cesta: importTorrentWizard.torrentfile.browse=Prech\u00e1dza\u0165... importTorrentWizard.torrentfile.invalidPath=Neplatn\u00fd .torrent s\u00fabor importTorrentWizard.importfile.title=Importovan\u00fd s\u00fabor importTorrentWizard.importfile.message=Vypl\u0148te n\u00e1zov importovan\u00e9ho xml s\u00faboru importTorrentWizard.importfile.path=Cesta: importTorrentWizard.importfile.browse=Prech\u00e1dza\u0165... importTorrentWizard.importfile.invalidPath=Neplatn\u00fd importovan\u00fd s\u00fabor importTorrentWizard.finish.title=Hotovo importTorrentWizard.finish.message=Import bol \u00faspe\u0161ne dokon\u010den\u00fd importTorrentWizard.process.inputfilebad.title=Neplatn\u00fd s\u00fabor importu importTorrentWizard.process.inputfilebad.message=Chyba pri \u010d\u00edtan\u00ed vstupn\u00e9ho s\u00faboru: importTorrentWizard.process.outputfileexists.title=S\u00fabor existuje importTorrentWizard.process.outputfileexists.message=V\u00fdstupn\u00fd s\u00fabor u\u017e existuje - prep\u00edsa\u0165? importTorrentWizard.process.torrentfail.title=Chyba pri z\u00e1pise Torrentu importTorrentWizard.process.importfail.title=Chyba pri importe Torrentu importTorrentWizard.process.unknownfail.title=Neo\u010dak\u00e1van\u00e1 chyba ConfigView.label.bindip=Zviaza\u0165 s lok\u00e1lnou IP adresou or interface ConfigView.label.zeronewfiles=Pri vytv\u00e1ran\u00ed alokova\u0165 a vynulova\u0165 s\u00fabory ConfigView.label.zeronewfiles.tooltip=Zni\u017euje fragment\u00e1ciu ConfigView.section.stats=\u0160tatistiky ConfigView.section.stats.enable=Povoli\u0165 ConfigView.section.stats.defaultsavepath=Zlo\u017eka pre \u0161tatistiky ConfigView.section.stats.choosedefaultsavepath=Vyberte zlo\u017eku, kam sa bud\u00fa uklada\u0165 \u0161tatistick\u00e9 inform\u00e1cie ConfigView.section.stats.savefreq=Frekvencia ukladania ConfigView.section.stats.minutes=min ConfigView.section.stats.hours=hod ConfigView.section.stats.seconds=sek ConfigView.section.stats.savefile=Meno s\u00faboru so \u0161tatistikami MyTorrentsView.menu.export=&Exportova\u0165 do XML... MyTorrentsView.menu.host=&Hos\u0165ova\u0165... ManagerItem.finishing=Dokon\u010dovanie ConfigView.dialog.choosedefaulttorrentpath=Vyberte predvolen\u00fa zlo\u017eku pre Torrenty ConfigView.dialog.choosemovepath=Vyberte zlo\u017eku, kam chcete pres\u00fava\u0165 ConfigView.label.movecompleted=Presun\u00fa\u0165 dokon\u010den\u00e9 s\u00fabory ConfigView.label.savetorrents=Uklada\u0165 .torrent s\u00fabory MainWindow.menu.view.mytracker=M\u00f4j &Tracker MyTrackerView.title.full=M\u00f4j Tracker MyTrackerView.name=N\u00e1zov MyTrackerView.tracker=Tracker MyTrackerView.status=Stav MyTrackerView.status.started=Be\u017e\u00ed MyTrackerView.status.stopped=Zastaven\u00fd MyTrackerView.peers=Klienti MyTrackerView.seeds=Zdroje MyTrackerView.announces=Oznamy MyTrackerView.uploaded=Odoslan\u00fdch MyTrackerView.downloaded=Prijat\u00fdch MyTrackerView.left=Zost\u00e1va ConfigView.section.style=Rozhranie ConfigView.section.style.useCustomTabs=Pou\u017e\u00edva\u0165 zatv\u00e1rate\u013en\u00e9 z\u00e1lo\u017eky [nutn\u00fd re\u0161tart] MainWindow.menu.view.plugins=&Pluginy fileDownloadWindow.saveTorrentIn=Ulo\u017ei\u0165 Torrent do s\u00faboru fileDownloadWindow.title=Vuze - S\u0165ahovanie Torrentu fileDownloadWindow.downloading=S\u0165ahovanie od : fileDownloadWindow.status=Stav : fileDownloadWindow.state_initializing=Inicializ\u00e1cia fileDownloadWindow.state_downloading=S\u0165ahovanie fileDownloadWindow.state_error=Chyba : MainWindow.menu.file.open.url=&URL MainWindow.menu.file.open.url.keybinding=Meta+U openUrl.title=Vuze - Otvori\u0165 URL openUrl.url=URL : MyTorrentsView.menu.host.error.title=Hos\u0165ovanie Torrentu sa nepodarilo MyTorrentsView.menu.host.error.message=Pri hos\u0165ovan\u00ed Torrentu nastala nasleduj\u00faca chyba ConfigView.section.tracker=Tracker ConfigView.section.tracker.pollinterval=Interval medzi po\u017eiadavkami klienta Trackeru (sek) ConfigView.section.tracker.publishenable=Publikova\u0165 detaily o Torrentoch v "" ConfigView.section.tracker.ip=Verejn\u00e1 IP adresa Trackera ConfigView.section.style.enableXPStyle=Povoli\u0165 XP \u0161t\u00fdl [nutn\u00fd re\u0161tart] ConfigView.section.tracker.checkip=Zisti\u0165 verejn\u00fa IP adresu... ipCheckerWizard.title=Sprievodca kontrolou IP adresy ipCheckerWizard.service=Slu\u017eba ipCheckerWizard.chooseService=Vyberte slu\u017ebu, ktor\u00e1 bude pou\u017eit\u00e1 pri kontrole IP adresy ipCheckerWizard.explanations=Tento sprievodca V\u00e1m pom\u00f4\u017ee zisti\u0165 Va\u0161u verejn\u00fa IP adresu. Ak m\u00e1te dynamick\u00fa IP adresu, odpor\u00fa\u010dame V\u00e1m zalo\u017ei\u0165 si \u00fa\u010det v niektorej spolo\u010dnosti poskytuj\u00facej dynamick\u00e9 DNS z\u00e1znamy. Na pomoc je tu zoznam nieko\u013ek\u00fdch spolo\u010dnost\u00ed s odkazmi, kde si tak\u00fato slu\u017ebu m\u00f4\u017eete zriadi\u0165 (pokia\u013e t\u00fato slu\u017ebu pon\u00faka). Potom vypl\u0148te pole IP adresy va\u0161im dynamick\u00fdm DNS z\u00e1znamom (napr.: myhostname.dyndns.org). Aby sa DNS z\u00e1znam automaticky aktualizoval, budete potrebova\u0165 program, ktor\u00fd poskytovate\u013e slu\u017eby dod\u00e1va. T\u00fdmto sp\u00f4sobom budete schopn\u00fd prev\u00e1dzkova\u0165 Tracker, aj ke\u010f sa Va\u0161a IP adresa zmen\u00ed. ipCheckerWizard.service.description=Popis : ipCheckerWizard.service.url=Odkaz : ipCheckerWizard.progresstitle=Kontrola IP adresy ipCheckerWizard.checkComplete=Zisten\u00e1 IP adresa : ipCheckerWizard.checkFailed=Chyba : wizard.tracker.local=Pou\u017e\u00edva\u0165 vstavan\u00fd Tracker wizard.tracker.external=Pou\u017e\u00edva\u0165 verejn\u00fd Tracker wizard.tracker.howToLocal=\tPovol\u00edte v 'N\u00e1stroje->Nastavenie->Tracker' wizard.announceUrl=Oznamovacia URL : IPChecker.external.service.discoveryvip.description=Discoveryvip - Iba zistenie IP adresy IPChecker.external.httpinvalidresponse=Neplatn\u00e1 odozva HTTP IPChecker.external.loadingwebpage=Na\u010d\u00edtanie str\u00e1nky IPChecker.external.analysingresponse=Anal\u00fdza odpovede IPChecker.external.addressextracted=N\u00e1jden\u00e1 IP adresa IPChecker.external.httploadfail=Nepodarilo sa na\u010d\u00edta\u0165 str\u00e1nku IPChecker.external.timeout=Vypr\u0161al \u010dasov\u00fd limit IPChecker.external.ipnotfound=IP adresa nen\u00e1jden\u00e1 ConfigView.section.tracker.pollintervalincby=Zvy\u0161ova\u0165 o ConfigView.section.tracker.pollintervalincper=Ka\u017ed\u00fdch 'n' klientov splash.loadingImages=Na\u010d\u00edtanie obr\u00e1zkov splash.initializeGui=Inicializ\u00e1cia hlavn\u00e9ho okna splash.openViews=Otv\u00e1ranie z\u00e1lo\u017eiek splash.plugin=Na\u010d\u00edtanie pluginu : configureWizard.nat.tooManyPorts=Prive\u013ea portov na testovanie (maxim\u00e1lne 9) ConfigView.section.color=Farebn\u00e1 Sch\u00e9ma MyTorrentsView.menu.publish=Publikova\u0165... MyTrackerView.status.published=Publikovan\u00fd MyTrackerView.completed=Dokon\u010den\u00fdch MainWindow.menu.file.open.torrentnodefault=.torrent s\u00fabor (nes\u0165ahova\u0165 do predvolenej zlo\u017eky) wizard.comment=Koment\u00e1r ConfigView.label.movetorrent=Presun\u00fa\u0165 .torrent ConfigView.section.file.decoder.label=Prednastaven\u00e9 k\u00f3dovanie .torrent s\u00faboru ConfigView.section.file.decoder.nodecoder=\u017diadne IPChecker.external.service.no-ip.name=No-IP IPChecker.external.service.no-ip.url=http://www.no-ip.com/ IPChecker.external.service.no-ip.description=Poskytovate\u013e dynamick\u00e9ho a statick\u00e9ho DNS\n(nepodporuje vo\u013ene slu\u017ebu zistenia adresy) ConfigView.section.tracker.publicenable=Povoli\u0165 extern\u00e9 Torrenty ConfigView.label.playdownloadspeech=Hovori\u0165 po dokon\u010den\u00ed s\u0165ahovania ConfigView.label.playdownloadspeech.info=Re\u010dov\u00e9 slu\u017eby moment\u00e1lne najlep\u0161ie funguj\u00fa v angli\u010dtine # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Zobrazuje po\u010det dostupn\u00fdch k\u00f3pi\u00ed ka\u017ed\u00e9ho dielu.\nAk je \u010d\u00edslo vpravo men\u0161ie ne\u017e 1, nie s\u00fa dostupn\u00e9 v\u0161etky diely s\u00faboru (a m\u00f4\u017eete ma\u0165 probl\u00e9m dokon\u010di\u0165 s\u0165ahovanie) GeneralView.label.trackerurl.tooltip=Kliknut\u00edm skop\u00edrujete oznamovaciu URL do schr\u00e1nky GeneralView.label.trackerurlopen.tooltip=Kliknut\u00edm otvor\u00edte hlavn\u00fa str\u00e1nku Trackera # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Aktualizova\u0165 UI (pou\u017e\u00edvate\u013esk\u00e9 rozhranie) ka\u017ed\u00fdch ConfigView.section.style.graphicsUpdate=Aktualizova\u0165 grafy ka\u017ed\u00fdch N aktualiz\u00e1ci\u00ed UI ConfigView.section.style.reOrderDelay=Zora\u010fova\u0165 tabu\u013eky ka\u017ed\u00fdch N aktualiz\u00e1ci\u00ed UI [0: nikdy] ConfigView.section.style.reOrderDelay.never=Nikdy ConfigView.section.logging=Protokoly ConfigView.section.logging.enable=Zapisova\u0165 protokoly do s\u00faboru ConfigView.section.logging.logdir=Zlo\u017eka s protokolmi ConfigView.section.logging.choosedefaultsavepath=Vyberte zlo\u017eku pre ulo\u017eenie GeneralView.label.updatein.querying=Zis\u0165ujem... configureWizard.nat.sharePort=Pou\u017e\u00edva\u0165 jeden zdie\u013ean\u00fd port pre v\u0161etky Torrenty ConfigView.section.logging.maxsize=Max. ve\u013ekos\u0165 s\u00faboru protokolu ConfigView.section.tracker.passwordenableweb=Zaheslova\u0165 web Trackera ConfigView.section.tracker.passwordenabletorrent=Zaheslova\u0165 Torrenty ConfigView.section.tracker.username=Pou\u017e\u00edvate\u013esk\u00e9 meno ConfigView.section.tracker.password=Heslo columnChooser.title=Zobrazovan\u00e9 st\u013apce columnChooser.move=Poradie st\u013apcov zmen\u00edte pretiahnut\u00edm polo\u017eiek columnChooser.apply=Pou\u017ei\u0165 columnChooser.columnname=N\u00e1zov st\u013apca columnChooser.columndescription=Popis TableColumn.header.shareRatio=Pomer zdie\u013eania MyTorrentsView.menu.editTableColumns=Nastavenie st\u013apcov wizard.operationfailed=Oper\u00e1cia sa nepodarila authenticator.title=Po\u017eadovan\u00e1 autentifik\u00e1cia authenticator.user=Pou\u017e\u00edvate\u013esk\u00e9 meno authenticator.password=Heslo ConfigView.label.allowSendVersion=Pri zis\u0165ovan\u00ed aktualiz\u00e1cie povoli\u0165 odoslanie anonymn\u00e9ho \u010d\u00edsla verzie a n\u00e1hodn\u00e9ho ID wizard.hint.mode=Tip:\tS\u00fabor alebo zlo\u017eku m\u00f4\u017eete vybra\u0165 aj ich pretiahnut\u00edm\n\t(Drag && Drop) na toto okno wizard.hint.file=Tip:\tS\u00fabor m\u00f4\u017eete vybra\u0165 aj jeho pretiahnut\u00edm na toto okno wizard.hint.directory=Tip:\tZlo\u017eku m\u00f4\u017eete vybra\u0165 aj jej pretiahnut\u00edm na toto okno MainWindow.menu.help.checkupdate=&Aktualiz\u00e1cia TableColumn.header.down=Prijat\u00fdch TableColumn.header.up=Odoslan\u00fdch ConfigView.section.tracker.passwordenabletorrent.info=Vy\u017eaduje podporu BitTorrent klienta (napr.: Vuze ConfigView.section.style.confirmationOnExit=Potvrdzova\u0165 ukon\u010denie programu MainWindow.dialog.exitconfirmation.title=Ukon\u010di\u0165 Vuze MainWindow.dialog.exitconfirmation.text=Naozaj chcete ukon\u010di\u0165 Vuze SystemTray.menu.stopalltransfers=Zastavi\u0165 v\u0161etky prenosy TrayWindow.menu.stopalldownloads=Zastavi\u0165 v\u0161etky Torrenty ConfigView.section.tracker.sslport.info=Pre viac inform\u00e1ci\u00ed sa pozrite do FAQ wizard.tracker.ssl=Pou\u017e\u00edva\u0165 SSL ConfigView.label.playdownloadfinished=Zahra\u0165 zvuk po dokon\u010den\u00ed s\u0165ahovania TableColumn.header.pieces=Diely TableColumn.header.pieces.info=Grafick\u00e1 reprezent\u00e1cia inform\u00e1cie o stiahnut\u00fdch dieloch TableColumn.header.completion=Dokon\u010den\u00e9 TableColumn.header.completion.info=Grafick\u00e1 reprezent\u00e1cia ko\u013eko % m\u00e1te stiahnut\u00fdch ConfigView.section.style.showdownloadbasket=Zobrazi\u0165 Drag && Drop cie\u013e pre .torrent s\u00fabory ConfigView.section.style.alwaysShowTorrentFiles=V\u017edy zobrazova\u0165 zoznam s\u00faborov v okne Detaily/S\u00fabory wizard.multitracker=K Torrentu prida\u0165 inform\u00e1ciu o Multi-Trackeri wizard.multitracker.title=Multi-Tracker wizard.multitracker.configuration=Nastavenie Multi-Trackera wizard.multitracker.new=Nov\u00fd... wizard.multitracker.edit=Upravi\u0165... wizard.multitracker.delete=Zmaza\u0165 wizard.multitracker.group=Skupina Trackerov wizard.multitracker.edit.title=Editor Multi-Trackera wizard.multitracker.edit.name=N\u00e1zov wizard.multitracker.edit.save=Ulo\u017ei\u0165 wizard.multitracker.edit.newgroup=Nov\u00e1 skupina wizard.multitracker.edit.deletegroup=Zmaza\u0165 wizard.multitracker.edit.newtracker=Nov\u00fd Tracker wizard.multitracker.edit.deletetracker=Zmaza\u0165 wizard.multitracker.edit.edit=Upravi\u0165 wizard.addingmt=Prid\u00e1vanie inform\u00e1ci\u00ed o Multi-Trackeri wizard.multitracker.noannounce=Oznamovacia URL nie je pr\u00edtomn\u00e1 vo va\u0161om zozname Trackerov MyTorrentsView.menu.recheck=Prekontrolova\u0165 iconBar.showDownloadBar.tooltip=Zobrazi\u0165 Panel s\u0165ahovania iconBar.start.tooltip=Spusti\u0165 iconBar.stop.tooltip=Zastavi\u0165 iconBar.remove.tooltip=Odobra\u0165 iconBar.openNoDefault.tooltip=Otvori\u0165 .torrent s\u00fabor (nes\u0165ahova\u0165 do predvolenej zlo\u017eky) iconBar.openURL.tooltip=Otvori\u0165 URL iconBar.openFolder.tooltip=Otvori\u0165 zlo\u017eku iconBar.new.tooltip=Vytvori\u0165 Torrent iconBar.up.tooltip=Posun\u00fa\u0165 nahor iconBar.down.tooltip=Posun\u00fa\u0165 nadol iconBar.run.tooltip=Otvori\u0165 iconBar.host.tooltip=Hos\u0165ova\u0165 iconBar.publish.tooltip=Publikova\u0165 MyTorrentsView.menu.editTracker=Zmeni\u0165 URL Trackera(ov) GeneralView.menu.selectTracker=Vybra\u0165 ConfigView.section.stats.xslfile=Meno XSL s\u00faboru ConfigView.section.stats.xslfiledetails=Bude priamo zahrnut\u00e9 v hlavi\u010dke s\u00faboru \u0161tatist\u00edk pomocou tagu ConfigView.label.savetorrentbackup=Vytv\u00e1ra\u0165 z\u00e1lohy ConfigView.section.tracker.forceport=Don\u00fati\u0165 extern\u00e9 Torrenty pou\u017e\u00edva\u0165 predvolen\u00fd port ConfigView.section.ipfilter.allow=POVOLI\u0164 iba tieto rozsahy (norm\u00e1lne s\u00fa ZAK\u00c1ZAN\u00c9) ConfigView.section.ipfilter.list.inrange=bola v rozsahu ConfigView.section.ipfilter.list.notinrange=nebola v \u017eiadnom rozsahu ConfigView.section.ipfilter.list.title=Zoznam zablokovan\u00fdch IP adries ConfigView.label.allowsameip=Povoli\u0165 viac pripojen\u00ed z jednej IP adresy ConfigView.label.allowsameip.tooltip=Zapnite iba ak to NAOZAJ potrebujete.\nSl\u00fa\u017ei ako ochrana proti podvodn\u00edkom (ke\u010f je vypnut\u00e9). ManagerItem.superseeding=Super-Distrib\u00facia ConfigView.label.userSuperSeeding=Pou\u017e\u00edva\u0165 Super-Distrib\u00faciu PeersView.uniquepiece=Diel (m\u00f3d Super-Distrib\u00facie) PeersView.uniquepiece.none=\u017diadny PeersView.timetosend=\u010cas do znovuposlania dielu (m\u00f3d Super-Distrib\u00facie) ConfigView.section.style.addurlsilently=Otv\u00e1ra\u0165 URL bez dial\u00f3gu ConfigView.section.style.addurlsilently.tooltip=Automaticky stiahne zadan\u00fa URL .torrent s\u00faboru bez otvorenia potvrdzovacieho okna. ConfigView.section.file.decoder.prompt=V\u017edy, ke\u010f je to mo\u017en\u00e9, op\u00fdta\u0165 sa na k\u00f3dovanie ConfigView.section.file.decoder.prompt.tooltip=V\u017edy, ke\u010f je mo\u017en\u00e9 vybra\u0165 k\u00f3dovanie, bude zobrazen\u00fd dial\u00f3g s jeho v\u00fdberom MyTorrentsView.menu.moveTop=Naj&vy\u0161\u0161ie MyTorrentsView.menu.moveEnd=Naj&ni\u017e\u0161ie ConfigView.label.moveonlyusingdefaultsave=Iba z predvolenej zlo\u017eky ConfigView.label.moveonlyusingdefaultsave.tooltip=Presun\u00fa\u0165 iba ak s\u00fa stiahnut\u00e9 d\u00e1ta v predvolenej zlo\u017eke ConfigView.label.watchtorrentfolder=Automaticky importova\u0165 nov\u00e9 Torrenty ConfigView.label.watchtorrentfolder.tooltip=Pravidelne kontroluje zlo\u017eku na pr\u00edtomnos\u0165 nov\u00fdch .torrent s\u00faborov ConfigView.label.watchtorrentfolderinterval=Interval ConfigView.label.watchtorrentfolderinterval.tooltip=Doba medzi kontrolami zlo\u017eky na nov\u00e9 Torrenty ConfigView.dialog.choosewatchtorrentfolderpath=Vyberte zlo\u017eku pre import .torrent s\u00faborov ConfigView.label.startwatchedtorrentsstopped=Prida\u0165 zastaven\u00e9 ConfigView.label.startwatchedtorrentsstopped.tooltip=Prid\u00e1 nov\u00e9 Torrenty v ZASTAVENOM stave ConfigView.section.plugins=Pluginy wizard.maketorrent.filesize=Ve\u013ekos\u0165 s\u00faboru(ov) wizard.maketorrent.piececount=Po\u010det dielov wizard.maketorrent.piecesize=Ve\u013ekos\u0165 dielu wizard.maketorrent.auto=Auto MainWindow.menu.view.stats=\u0160tatistiky SpeedView.title.full=Aktivita SpeedView.downloadSpeed.title=R\u00fdchlos\u0165 downloadu SpeedView.uploadSpeed.title=R\u00fdchlos\u0165 uploadu ConfigView.section.style.useSIUnits=Pou\u017e\u00edva\u0165 jednotky IEC (KB -> KiB at\u010f.) iconBar.top.tooltip=Presun\u00fa\u0165 \u00faplne nahor iconBar.bottom.tooltip=Presun\u00fa\u0165 \u00faplne nadol TableColumn.header.health=Zdravie MyTorrentsView.menu.health=O zdrav\u00ed Torrentu health.explain.grey=znamen\u00e1, \u017ee v\u00e1\u0161 Torrent nebe\u017e\u00ed (ani download, ani upload) health.explain.red=znamen\u00e1, \u017ee nie ste pri s\u0165ahovan\u00ed pripojen\u00fd k \u017eiadnemu klientovi health.explain.blue=pri distrib\u00facii znamen\u00e1, \u017ee nie ste pripojen\u00fd k \u017eiadnemu klientovi\npri s\u0165ahovan\u00ed znamen\u00e1, \u017ee ste pripojen\u00fd k nejak\u00fdm klientom, ale Tracker nie je dostupn\u00fd health.explain.yellow=znamen\u00e1, \u017ee Tracker je v poriadku, ste pripojen\u00fd ku klientom, ale neexistuje \u017eiadne pripojenie zvonku.\nAk st\u00e1le vid\u00edte t\u00fato \u017elt\u00fa pri va\u0161ich Torrentoch, tak m\u00e1te asi probl\u00e9my s NAT health.explain.green=znamen\u00e1, \u017ee v\u0161etko je v poriadku ConfigView.section.style.alwaysRefreshMyTorrents=Neust\u00e1le obnovova\u0165 Moje Torrenty ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Obnovova\u0165 okno Moje Torrenty, aj ke\u010f nie je zobrazen\u00e9 [pre niektor\u00e9 pluginy mIrc] # #2.0.7.0 # security.certtruster.title=Varovanie bezpe\u010dnostn\u00e9ho certifik\u00e1tu security.certtruster.intro=Certifik\u00e1t bol vydan\u00fd spolo\u010dnos\u0165ou, ktorej ned\u00f4verujete security.certtruster.resource=Zdroj: security.certtruster.issuedto=Vydan\u00e9 pre: security.certtruster.issuedby=Vydal: security.certtruster.prompt=Chcete certifik\u00e1tu d\u00f4verova\u0165? security.certtruster.yes=\u00c1no security.certtruster.no=Nie ConfigView.section.tracker.torrentsperpage=Ko\u013eko Torrentov na str\u00e1nku ? [0: neobmedzene] MainWindow.menu.file.share=&Zdie\u013ea\u0165 MainWindow.menu.file.share.file=&S\u00fabor... MainWindow.menu.file.share.dir=Z&lo\u017eku... MainWindow.menu.file.share.dircontents=&Obsah zlo\u017eky... MainWindow.menu.file.share.dircontentsrecursive=Obsah zlo\u017eky (&rekurz\u00edvne)... MainWindow.dialog.share.sharefile=Vyberte s\u00fabor na zdie\u013eanie MainWindow.dialog.share.sharedir=Vyberte zlo\u017eku na zdie\u013eanie MainWindow.dialog.share.sharedircontents=Vyberte zlo\u017eku, ktorej obsah bude zdie\u013ean\u00fd MainWindow.dialog.share.sharedircontents.recursive=rekurz\u00edvne globalmanager.download.remove.veto=Odobranie zamietnut\u00e9 plugin.sharing.download.remove.veto=T\u00e1to polo\u017eka vznikla zdie\u013ean\u00edm.\nPre odobranie polo\u017eky je treba odobra\u0165 pridru\u017een\u00e9 zdie\u013eanie: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=Hlavn\u00fd ConfigView.label.prioritizefirstpiece=V\u00e4\u010d\u0161ia priorita pre prv\u00e9 diely s\u00faborov ConfigView.label.prioritizefirstpiece.tooltip=Vuze sa pok\u00fasi stiahnu\u0165 za\u010diatok s\u00faboru ako prv\u00fd.\nUmo\u017en\u00ed tak r\u00fdchly n\u00e1h\u013ead. ConfigView.section.file.confirm_data_delete=Potvrdi\u0165 zmazanie d\u00e1t ConfigView.section.file.confirm_data_delete.tooltip=Vy\u017eadova\u0165 potvrdenie akcie pri pou\u017eit\u00ed "Odobra\u0165 a zmaza\u0165 ..." TrayWindow.menu.startalldownloads=Spusti\u0165 v\u0161etky Torrenty SystemTray.menu.startalltransfers=Spusti\u0165 v\u0161etky prenosy sharing.progress.title=Proces zdie\u013eania sharing.progress.hide=Skry\u0165 MainWindow.menu.view.myshares=Moje Zdie\u013eania MySharesView.title.full=Moje Zdie\u013eania MySharesView.name=N\u00e1zov MySharesView.type=Typ MySharesView.type.file=S\u00fabor MySharesView.type.dir=Zlo\u017eka MySharesView.type.dircontents=Obsah zlo\u017eky MySharesView.type.dircontentsrecursive=Obsah zlo\u017eky (rekurz\u00edvne) MySharesView.menu.remove=Odobra\u0165 ConfigView.section.tracker.extensions=Roz\u0161\u00edrenia ConfigView.section.tracker.sendpeerids=Posiela\u0165 s\u0165ahova\u010dom identitu klientov ConfigView.section.tracker.enableudp=Povoli\u0165 UDP protokol Trackeru plugin.sharing.torrent.remove.veto=T\u00e1to polo\u017eka Trackera vznikla zdie\u013ean\u00edm.\nPre odobranie polo\u017eky je treba odobra\u0165 pridru\u017een\u00e9 zdie\u013eanie: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=Torrent nem\u00f4\u017ee by\u0165 odobran\u00fd, preto\u017ee nie je zastaven\u00fd plugin.sharing.remove.veto=T\u00e1to zdie\u013ean\u00e1 polo\u017eka je v\u00fdsledok "Zdie\u013eanej zlo\u017eky" a nem\u00f4\u017ee by\u0165 samostatne odstr\u00e1nen\u00e1.\n Odoberte kore\u0148ov\u00fa zlo\u017eku GeneralView.label.hash.tooltip=Kliknut\u00edm skop\u00edrujete hash do schr\u00e1nky ConfigView.section.tracker.maxpeersreturned=Max. po\u010det vr\u00e1ten\u00fdch klientov [0: neobmedzen\u00fd] ConfigView.label.serverport=Pr\u00edchodz\u00ed TCP port ConfigView.label.serverport.tooltip=Port mus\u00ed by\u0165 v rozsahu 1-65535, a nesmie to by\u0165 6880, ktor\u00fd je vyhraden\u00fd pre intern\u00e9 pou\u017eitie. configureWizard.nat.server.tcp_listen_port=Pr\u00edchodz\u00ed TCP port ConfigView.section.sharing=Zdie\u013eanie ConfigView.section.sharing.usessl=Pre zdie\u013ean\u00e9 s\u00fabory pou\u017e\u00edva\u0165 SSL (vy\u017eaduje nastavenie Trackera) ConfigView.section.style.dropdiraction=Pretiahnutie (Drag && Drop) zlo\u017eky ConfigView.section.style.dropdiraction.opentorrents=Otv\u00e1ra Torrenty ConfigView.section.style.dropdiraction.sharefolder=Zdie\u013ea zlo\u017eku ConfigView.section.style.dropdiraction.sharefoldercontents=Zdie\u013ea obsah zlo\u017eky # # 2.0.7.x # Categories.all=V\u0161etko Categories.uncategorized=Nezaraden\u00e9 CategoryAddWindow.message=Meno novej kateg\u00f3rie CategoryAddWindow.title=Prida\u0165 nov\u00fa kateg\u00f3riu ConfigView.label.autoSeedingIgnoreInfo=Ignorovan\u00e9 Torrenty id\u00fa na koniec distribu\u010dnej fronty. A nie s\u00fa automaticky sp\u00fa\u0161\u0165an\u00e9. Pravidl\u00e1 ignorovania sa nevz\u0165ahuj\u00fa na Torrenty, pre ktor\u00e9 platia pravidl\u00e1 Top Priority. Pokia\u013e nie je uveden\u00e9 inak, hodnota 0 znamen\u00e1 vypnutie pravidla. ConfigView.label.directory=Zlo\u017eka ConfigView.label.disconnetseed.tooltip=Pri distrib\u00facii odpoji\u0165 v\u0161etk\u00fdch distribuj\u00facich klientov.\nNie je nutn\u00e9 by\u0165 s nimi v kontakte (ni\u017e\u0161\u00ed prenos d\u00e1t). ConfigView.label.ignoreCase=Ignorova\u0165 ve\u013ekos\u0165 p\u00edsmen ConfigView.label.ignoreSeeds=Ignorova\u0165 Torrenty s aspo\u0148 ConfigView.label.importdirectory=Zlo\u017eka importu ConfigView.label.minPeersToBoostNoSeeds.tooltip=Ak\u00fdko\u013evek Torrent bez zdrojov maj\u00faci menej s\u0165ahova\u010dov ne\u017e nastav\u00edte,\nbude posunut\u00fd ku koncu fronty. ConfigView.label.minPeersToBoostNoSeeds=Ni\u017e\u0161ie hodnotenie pre Torrenty bez zdrojov alebo s menej ne\u017e ConfigView.label.minSeedingTime.tooltip=Hodnotenie sa m\u00f4\u017ee \u010dasto v kr\u00e1tkych intervaloch meni\u0165; niekedy s\u00fa Torrenty sp\u00fa\u0161\u0165an\u00e9, len aby sa hne\u010f ukon\u010dili a boli zaraden\u00e9 sp\u00e4\u0165 do fronty.\nToto nastavenie obch\u00e1dza probl\u00e9m don\u00faten\u00edm Torrentov zosta\u0165 v distrib\u00facii nastaven\u00fd \u010das.\nPokia\u013e chcete, m\u00f4\u017eete Torrent kedyko\u013evek zastavi\u0165 ru\u010dne. ConfigView.label.minSeedingTime=Minim\u00e1lny \u010das distrib\u00facie v sekund\u00e1ch ConfigView.label.minSpeedForActiveDL.tooltip=Prv\u00fdch 30 sek\u00fand je ka\u017ed\u00fd nedokon\u010den\u00fd Torrent pova\u017eovan\u00fd za s\u0165ahuj\u00faci. ConfigView.label.minSpeedForActiveDL=Nepo\u010d\u00edta\u0165 Torrent ako s\u0165ahuj\u00faci, ak je r\u00fdchlos\u0165 s\u0165ahovania pod ConfigView.label.peers=klientov ConfigView.label.queue.debuglog=Zapisova\u0165 debug inform\u00e1cie ConfigView.label.queue.debuglog.info=Prid\u00e1 na v\u00fdstup konzoly/log s\u00faboru debug inform\u00e1cie o fronte.\nAj ke\u010f \u00fase\u010dne, debug inform\u00e1cie ud\u00e1vaj\u00fa stav Torrentov a pre\u010do boli/neboli spusten\u00e9/zaraden\u00e9 do fronty. ConfigView.label.queue.minQueueingShareRatio=Nezara\u010fova\u0165 do fronty ani nezastavova\u0165 Torrent, dok\u00fdm pomer zdie\u013eania nedosiahne ConfigView.label.ratio=pomer ConfigView.label.removeOnStop=Odobra\u0165 Torrent zo zoznamu po tom, \u010do automaticky zastal ConfigView.label.savedirectory=Zlo\u017eka pre Torrenty ConfigView.label.seeding.autoReposition.tooltip=Pokia\u013e je povolen\u00e9, poradie Torrentov (st\u013apec '#') je upravovan\u00e9 pod\u013ea hodnotenia (Seeding Rank)\nPokia\u013e v\u00e1s nezauj\u00edmaj\u00fa hodnoty Seeding Rank, potom t\u00fdmto sp\u00f4sobom vid\u00edte, v akom porad\u00ed bud\u00fa dokon\u010den\u00e9 Torrenty sp\u00fa\u0161\u0165an\u00e9. ConfigView.label.seeding.autoReposition=Automaticky preusporiad\u00e1va\u0165 Torrenty pod\u013ea ich hodnoten\u00ed ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u010casto Torrenty s m\u00e1lo zdrojmi a ve\u013ea klientami znamenaj\u00fa, \u017ee nie je medzi klientami roz\u0161\u00edren\u00e1 cel\u00e1 k\u00f3pia s\u00faboru.\nPreto nie je vhodn\u00e9, aby pravidl\u00e1 distrib\u00facie predpokladali \u010fal\u0161ie cel\u00e9 k\u00f3pie (a tak nespr\u00e1vne zni\u017eovali hodnotenie Torrentu) ConfigView.label.seeding.fakeFullCopySeedStart=ale iba pre Torrenty s aspo\u0148 ConfigView.label.seeding.ignore=Pravidl\u00e1 ignorovania ConfigView.label.seeding.ignore0Peers=Ignorova\u0165 Torrenty s 0 klientami ConfigView.label.seeding.ignoreRatioPeers=Ignorova\u0165 Torrenty s aspo\u0148 1 zdrojom na ConfigView.label.seeding.ignoreShareRatio=Ignorova\u0165 Torrenty s pomerom zdie\u013eania ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorova\u0165 Torrent, aj ke\u010f\n platia pravidl\u00e1 Top Priority ConfigView.label.seeding.ignore.header.rule=Pravidlo ConfigView.label.seeding.ignore.header.value=Hodnota ConfigView.label.seeding.firstPriority.info=Torrenty ur\u010den\u00e9 pravidlami Top Priority bud\u00fa v\u017edy na za\u010diatku fronty. \u017diadny z t\u00fdchto Torrentov nebude automaticky zastaven\u00fd a zaraden\u00fd sp\u00e4\u0165 do fronty. Torrenty s Top Prioritou si tie\u017e vezm\u00fa simult\u00e1nny download slot, pokia\u013e ho potrebuj\u00fa. ConfigView.label.seeding.firstPriority.FP=Top Priorita ConfigView.label.seeding.firstPriority=Top Priorita plat\u00ed pre Torrenty s ConfigView.label.seeding.firstPriority.following=z nasleduj\u00facich pravidiel: ConfigView.label.seeding.firstPriority.shareRatio=Pomer zdie\u013eania pod ConfigView.label.seeding.firstPriority.seedingMinutes=\u010cas od zmeny s\u0165ahovania na distrib\u00faciu ConfigView.label.seeding.firstPriority.DLMinutes=\u010cas od za\u010diatku s\u0165ahovania ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Predpokladan\u00edm existencie jednej celej k\u00f3pie na X klientov zn\u00ed\u017eite hodnotenia Torrentov s ve\u013ek\u00fdm po\u010dtom klientov.\nTieto Torrenty pravdepodobne bud\u00fa ma\u0165 aj ve\u013ek\u00fd traffic.\nToto nastavenie nezmen\u00ed zobrazenie inform\u00e1cie "po\u010det zdrojov" ConfigView.label.seeding.numPeersAsFullCopy=Predpoklada\u0165 existenciu aspo\u0148 jednej celej k\u00f3pie pre ka\u017ed\u00fdch\n[0 : nepredpoklada\u0165] ConfigView.label.seeding.preferLargerSwarms.tooltip=Pokia\u013e distribuujete Torrenty "zaseknut\u00fdm" klientom, pom\u00f4\u017ee preferovanie Torrentov s v\u00e4\u010d\u0161\u00edm po\u010dtom \u00fa\u010dastn\u00edkov.\nPokia\u013e distribuujete Torrenty s ve\u013ekou roz\u0161\u00edrenos\u0165ou dielov, potom je v\u00fdhodn\u00e9 preferova\u0165 Torrenty s men\u0161\u00edm po\u010dtom \u00fa\u010dastn\u00edkov. ConfigView.label.seeding.preferLargerSwarms=Ke\u010f maj\u00fa dva Torrenty rovnak\u00e9 hodnotenie, preferova\u0165 ten s v\u00e4\u010d\u0161\u00edm po\u010dtom \u00fa\u010dastn\u00edkov ConfigView.label.seeding.rankType.none.tooltip=Poradie zalo\u017een\u00e9 na st\u013apci '#' ConfigView.label.seeding.rankType.none=\u017diadne ConfigView.label.seeding.rankType.peerSeed.options=Nastavenia pomeru Zdroje:Klienti ConfigView.label.seeding.rankType.peerSeed.tooltip=Vy\u0161\u0161\u00ed pomer = vy\u0161\u0161ie hodnotenie ConfigView.label.seeding.rankType.peerSeed=Pomer Klienti:Zdroje ConfigView.label.seeding.rankType.seed.fallback=Vr\u00e1ti\u0165 sa k pomeru Klienti:Zdroje po\n[0 : nikdy] ConfigView.label.seeding.rankType.seed.options=Nastavenia po\u010dtu zdrojov ConfigView.label.seeding.rankType.seed.tooltip=Menej zdrojov = vy\u0161\u0161ie hodnotenie ConfigView.label.seeding.rankType.seed=Po\u010det zdrojov ConfigView.label.seeding.rankType.timedRotation.tooltip=V\u0161etky dokon\u010den\u00e9 Torrenty vo fronte sa bud\u00fa strieda\u0165 v distrib\u00facii.\n\u010cas, po ktor\u00fd bud\u00fa distribuovan\u00e9 je nastaven\u00fd pomocou vo\u013eby 'Minim\u00e1lny \u010das distrib\u00facie' ConfigView.label.seeding.rankType.timedRotation=Striedanie po \u010dasov\u00fdch intervaloch ConfigView.label.seeding.rankType.tooltip=Automaticky s\u00fa spusten\u00e9 Torrenty s najvy\u0161\u0161\u00edm ohodnoten\u00edm.\nPokia\u013e niektor\u00fd Torrent dosiahne vy\u0161\u0161ie hodnotenie, je ten s ni\u017e\u0161\u00edm pozastaven\u00fd a vracia sa sp\u00e4\u0165 do fronty.\n\nAutomatick\u00e9 spustenie je umo\u017enen\u00e9 len Torrentom vo fronte.\nZastaven\u00e9 Torrenty nie s\u00fa nikdy automaticky spusten\u00e9. ConfigView.label.seeding.rankType=Hodnotenie dokon\u010den\u00fdch Torrentov pre automatick\u00e9 spustenie zalo\u017een\u00e9 na: ConfigView.label.stopAfterMinutes=Zastavi\u0165 distrib\u00faciu po ur\u010denom \u010dase ConfigView.label.switchpriority.tooltip=N\u00edzka priorita zni\u017euje Torrentu pridelen\u00fd prietok d\u00e1t smerom von ConfigView.pluginlist.info=Boli n\u00e1jden\u00e9 nasleduj\u00face pluginy. Niektor\u00e9 z nich nemusia ma\u0165 konfigura\u010dn\u00fd dial\u00f3g. ConfigView.pluginlist.noplugins=Neboli n\u00e1jden\u00e9 \u017eiadne pluginy. ConfigView.section.pluginslist=Zoznam ConfigView.section.queue.seeding=Distrib\u00facia ConfigView.section.queue.seeding.autoStarting=Automatick\u00e9 sp\u00fa\u0161\u0165anie ConfigView.section.queue.seeding.ignore=Pravidl\u00e1 ignorovania ConfigView.section.queue.seeding.firstPriority=Top priorita ConfigView.section.queue.main=Hlavn\u00e9 ConfigView.section.queue=Fronta ConfigView.section.torrents=Torrenty ConfigView.text.all=v\u0161etky ConfigView.text.hours=hod\u00edn ConfigView.text.ignoreRule=Ignorova\u0165 pravidlo ConfigView.text.ignore=Ignorova\u0165 ConfigView.text.minutes=min\u00fat ConfigView.text.neverIgnore=Nikdy neignorova\u0165 ConfigView.text.any=ak\u00fdko\u013evek DownloadManager.error.datamissing=Chybaj\u00face d\u00e1ta MainWindow.menu.file.open.torrentforseeding=.torrent s\u00fabor (pre distrib\u00faciu) MainWindow.menu.language.refresh=&Obnovi\u0165 ManagerItem.forced=Vyn\u00faten\u00e9 ManagerItem.queued=Vo fronte MySeedersView.header=Dokon\u010den\u00e9/Distribuovan\u00e9 Torrenty TableColumn.header.availability.info=Po\u010det dostupn\u00fdch k\u00f3pi\u00ed TableColumn.header.availability=Dostupnos\u0165 TableColumn.header.category=Kateg\u00f3ria MyTorrentsView.header=Nedokon\u010den\u00e9/S\u0165ahovan\u00e9 Torrenty TableColumn.header.maxuploads=Maximum uploadov MyTorrentsView.menu.category.delete=O&dobra\u0165 kateg\u00f3riu MyTorrentsView.menu.forceStart=&Vyn\u00fati\u0165 spustenie MyTorrentsView.menu.queue=Zaradi\u0165 do &fronty MyTorrentsView.menu.setCategory.add=&Prida\u0165 kateg\u00f3riu.. MyTorrentsView.menu.setCategory=Nastavi\u0165 kateg\u00f3riu TableColumn.header.savepath=Cie\u013eov\u00e1 zlo\u017eka TableColumn.header.SeedingRank=Hodnotenie TableColumn.header.totalspeed.info=Celkov\u00e1 r\u00fdchlos\u0165 klientov, ku ktor\u00fdm ste pripojen\u00fd TableColumn.header.totalspeed=Celkov\u00e1 r\u00fdchlos\u0165 splash.initializePlugins=Inicializ\u00e1cia Pluginov StartStopRules.SPratioMet=S:P pomer OK StartStopRules.FP0Peers=FP / 0 klientov StartStopRules.0Peers=0 klientov StartStopRules.numSeedsMet=# klientov OK StartStopRules.ratioMet=Klienti:Zdroje OK StartStopRules.shareRatioMet=Pomer zdie\u013eania OK StartStopRules.waiting=\u010cakanie StartStopRules.firstPriority=Top Priorita ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Zdie\u013ea obsah zlo\u017eky (rekurz\u00edvne) DownloadManager.error.unabletostartserver=Nemo\u017eno spusti\u0165 server - skontrolujte nastavenie pr\u00edchodzieho portu / nastavenie firewallu, aby umo\u017enil aplik\u00e1cii by\u0165 serverom GeneralView.label.creationdate=Vytvoren\u00e9 : ConfigView.section.tracker.announcescrapepercentage=Interval medzi Scrapmi v % ozn\u00e1menia\nnapr. 200 = 2:1. 0 = nech rozhodne klient ManagerItem.stopping=Zastavovanie ConfigView.section.tracker.announcecacheperiod=Oznamovacia cache (ms) ConfigView.section.tracker.scrapecacheperiod=Scrapov\u00e1 cache (ms) ConfigView.section.tracker.scrapeandcache=Scrapy a cache ConfigView.section.tracker.announcecacheminpeers=Prah zapnutia oznamovacej cache MyTrackerView.scrapes=Scrapy fileDownloadWindow.retry=Znovu MyTrackerView.bytesin=Bajty In MyTrackerView.bytesinave=Priem. In MyTrackerView.bytesout=Bajty Out MyTrackerView.bytesoutave=Priem. Out ConfigView.section.file.max_open_files=Max. otvoren\u00fdch s\u00faborov pre \u010d\u00edtanie/z\u00e1pis\n[0: neobmedzene] ConfigView.section.file.max_open_files.tooltip=Pou\u017eite v pr\u00edpade, \u017ee s\u0165ahujete Torrenty so stovkami/tis\u00edcmi s\u00faborov a dosahujete limit OS pre po\u010det otvoren\u00fdch s\u00faborov. ConfigView.section.proxy=Mo\u017enosti proxy ConfigView.section.proxy.enable_proxy=Pou\u017ei\u0165 proxy server ConfigView.section.proxy.host=Server ConfigView.section.proxy.username=Pou\u017e\u00edvate\u013esk\u00e9 meno ConfigView.section.proxy.password=Heslo ConfigView.section.proxy.enable_socks=M\u00e1m SOCKS proxy server wizard.createtorrent.extrahashes=Prida\u0165 hash hodnoty pre ostatn\u00e9 siete (napr.: Gnutella2, eDonkey2000) GeneralView.label.connected=pripojen\u00fdch GeneralView.label.in_swarm=celkom ManagerItem.initializing=Inicializ\u00e1cia AlertMessageBox.error=Chyba AlertMessageBox.warning=Varovanie AlertMessageBox.comment=Inform\u00e1cia AlertMessageBox.information=Inform\u00e1cia SharedPortServer.alert.selectorfailed=Nepodarilo sa otvori\u0165 port pre prich\u00e1dzaj\u00face d\u00e1ta.\nSkontrolujte nastavenie firewallu, \u010di umo\u017enuje java(w).exe jedna\u0165 ako 'server' Tracker.alert.listenfail=Nepodar\u00edlo sa na\u010d\u00fava\u0165 na porte %1.\nSkontrolujte, \u010di ostatn\u00e9 aplik\u00e1cie nepou\u017e\u00edvaj\u00fa tento port.\nTie\u017e skontrolujte, \u010di u\u017e in\u00fd Vuze nebe\u017e\u00ed. DiskManager.alert.movefileexists=Chyba pri presune dokon\u010den\u00fdch s\u00faborov\nS\u00fabor %1 v cie\u013eovej zlo\u017eke u\u017e existuje DiskManager.alert.movefilefails=Chyba pri presune dokon\u010den\u00fdch s\u00faborov\nPresun s\u00faboru %1 sa nepodaril, %2 DiskManager.alert.movefilerecoveryfails=Chyba pri obnove z nepodaren\u00e9ho presunu\nObnova s\u00faboru %1 sa nepodarila, %2 ConfigView.section.tracker.logenable=Periodicky zapisova\u0165 \u0161tatistiku do 'tracker.log' SpeedView.stats.title=\u0160tatistika SpeedView.stats.total=Celkom SpeedView.stats.session=Toto spustenie SpeedView.stats.session.tooltip=Celkovo (Protokol) SpeedView.stats.downloaded=Prijat\u00fdch SpeedView.stats.uploaded=Odoslan\u00fdch SpeedView.stats.ratio=Pomer SpeedView.stats.uptime=Spusten\u00e9 (hod) SpeedView.stats.now=Pr\u00e1ve teraz SpeedView.stats.now.tooltip=Celkovo (Protokol) AutoMigration.useralert=V\u00fdsledky automatickej migr\u00e1cie konfigura\u010dn\u00fdch s\u00faborov:\n\n%1\nNEPRESUNUT\u00c9 S\u00daBORY MUSIA BY\u0164 PRESUNUT\u00c9 RU\u010cNE. # # > 2.0.8.0 # OpenTorrentWindow.title=Otvori\u0165 Torrent(y) OpenTorrentWindow.message=Experiment\u00e1lny OpenTorrentWindow.addFiles=&Prida\u0165 s\u00fabory OpenTorrentWindow.dataLocation=Umiestnenie pre ulo\u017eenie d\u00e1t: OpenTorrentWindow.startMode=Stav OpenTorrentWindow.startMode.queued=Zaraden\u00fd do fronty OpenTorrentWindow.startMode.stopped=Zastaven\u00fd OpenTorrentWindow.startMode.forceStarted=Vyn\u00faten\u00e9 spustenie OpenTorrentWindow.addPosition=Prida\u0165 do fronty OpenTorrentWindow.addPosition.first=Na za\u010diatok OpenTorrentWindow.addPosition.last=Na koniec TableColumn.header.remaining.info=Objem d\u00e1t zost\u00e1vaj\u00faci na stiahnutie TableColumn.header.remaining=Zost\u00e1va ConfigView.section.tracker.enablecompact=Pou\u017e\u00edva\u0165 kompaktn\u00fd oznamovac\u00ed protokol ConfigView.section.tracker.enablekey=Pre v\u00e4\u010d\u0161iu bezpe\u010dnos\u0165 posiela\u0165 Trackeru k\u013e\u00fa\u010d ConfigView.section.file.perf=Nastavenie v\u00fdkonu ConfigView.section.file.perf.explain=Varovanie - neodborn\u00e9 zmeny t\u00fdchto parametrov m\u00f4\u017eu v\u00e1\u017ene ovplyvni\u0165 v\u00fdkon s\u0165ahovania. Po zmene je treba program re\u0161tartova\u0165.\nAk m\u00e1te probl\u00e9my s nedostatkom pam\u00e4ti, sk\u00faste obmedzi\u0165 po\u010det pripojen\u00ed na Torrent (viac v nastaven\u00ed Prenosu) ConfigView.section.file.max_open_files.explain=Ak je otvoren\u00fdch prive\u013ea s\u00faborov, m\u00f4\u017ee to sp\u00f4sobi\u0165 probl\u00e9my opera\u010dn\u00e9mu syst\u00e9mu kv\u00f4li nedostatku zdrojov. Toto obmedz\u00ed po\u010det naraz otvoren\u00fdch s\u00faborov. popup.error.hide=Skry\u0165 popup.error.details=Detaily ConfigView.section.style.colorOverrides=Zmena farieb ConfigView.section.style.colorOverride.progressBar=Indik\u00e1tor progresu ConfigView.section.style.colorOverride.error=Chyba MainWindow.status.tooOld=je pr\u00edli\u0161 star\u00fd, pros\u00edm aktualizujte ho. ConfigView.section.style.colorOverride.warning=Varovanie ConfigView.section.style.colorOverride.altRow=Nep\u00e1rne riadky ConfigView.section.file.save.peers.enable=Uklada\u0165 adresy pripojen\u00fdch klientov pre r\u00fdchlej\u0161ie sp\u00fa\u0161\u0165anie ConfigView.section.file.save.peers.max=Max. ulo\u017een\u00fdch klientov [0: neobmedzene] ConfigView.section.file.save.peers.pertorrent=na Torrent ConfigView.label.max_peers_per_torrent=Max. po\u010det pripojen\u00ed na Torrent [0: neobmedzen\u00fd] ConfigView.label.max_peers_total=Celkov\u00fd max. po\u010det pripojen\u00ed [0: neobmedzen\u00fd] ConfigView.section.style.colorOverrides.reset=P\u00f4vodn\u00e1 farba ConfigView.section.language.info=Ak je aktualiz\u00e1cia povolen\u00e1, bude vykonan\u00e1 pri ka\u017edom spusten\u00ed programu. ConfigView.section.language.enableUpdate=Povoli\u0165 aktualiz\u00e1cie z internetu ConfigView.section.language.UpdateURL=URL s aktualiz\u00e1ciou ConfigView.section.language.UpdateNow=Aktualizova\u0165! Button.revert=Vr\u00e1ti\u0165 MyTorrentsView.menu.changeDirectory=Zmeni\u0165 cestu k s\u00faborom GenericText.column=St\u013apec MyTorrentsView.menu.thisColumn.remove=Odobra\u0165 st\u013apec MyTorrentsView.menu.thisColumn.toClipboard=Kop\u00edrova\u0165 text do schr\u00e1nky TableColumn.header.secondsseeding=D\u013a\u017eka distrib\u00facie TableColumn.header.secondsseeding.info=Doba, po ktor\u00fa Torrent distribuujete TableColumn.header.secondsdownloading=D\u013a\u017eka s\u0165ahovania TableColumn.header.secondsdownloading.info=Doba, po ktor\u00fa Torrent s\u0165ahujete ConfigView.section.tracker.udpversion=Verzia UDP protokolu (1 alebo 2) window.updateswt.title=Va\u0161a verzia kni\u017enice SWT je zastaral\u00e1! window.updateswt.text=Va\u0161a verzia kni\u017enice SWT je zastaral\u00e1!\nSWT je grafick\u00e1 kni\u017enica pou\u017e\u00edvan\u00e1 programom Azureus. T\u00e1to kni\u017enica je zastaral\u00e1 pre beh najnov\u0161ej verzie programu Azureus. Tla\u010didlom OK aktualizujete Va\u0161u kni\u017enicu SWT. window.updateswt.status=Stav window.updateswt.failed=Aktualiz\u00e1cia zlyhala, stla\u010dte OK pre znovustiahnutie. window.updateswt.status.downloading.updater=S\u0165ahovanie Aktualiza\u010dn\u00e9ho modulu window.updateswt.status.finding=H\u013eadanie najnov\u0161ej verzie SWT window.updateswt.status.downloading=S\u0165ahovanie najnov\u0161ej verzie SWT window.updateswt.status.done=Re\u0161tartovanie window.updateswt.cancel=Storno swt.updater.downloader.downloading=S\u0165ahovanie SWT z swt.updater.urlsgetter.downloading=S\u0165ahujem zoznam mirrorov z swt.updater.urlsgetter.platform=SWT pre platformu : window.updateswt.ignore=Ignorova\u0165 ConfigView.section.style.useFancyTabs=Pou\u017e\u00edva\u0165 ozdobn\u00e9 z\u00e1lo\u017eky splash.initializeGM=Inicializ\u00e1cia Glob\u00e1lneho Torrent Managera splash.loadingTorrents=Na\u010d\u00edtanie Torrentov MyTorrentsView.menu.thisColumn.sort=&Zoradi\u0165 Scrape.status.error=Scrape Chyba: Scrape.status.error.badURL=Oznamovacia URL nezodpoved\u00e1 \u0161pecifik\u00e1cii Scrape. Scrape.status.error.nohash=V odpovedi ch\u00fdba hash hodnota. Scrape.status.error.invalid=Neplatn\u00e1 odpove\u010f. Scrape.status.nextScrapeAt=\u010eal\u0161\u00ed Scrape v %1 Scrape.status.scraping=Scrapujem... Scrape.status.initializing=\u010cakanie na Scrape ConfigView.label.minSpeedForActiveSeeding=Nepo\u010d\u00edta\u0165 dokon\u010den\u00fd Torrent ako vyu\u017e\u00edvaj\u00faci slot, ak je r\u00fdchlos\u0165 pod ConfigView.section.stats.exportpeers=Exportova\u0165 detaily o klientoch MainWindow.menu.view.irc.moved=IRC klient je teraz dostupn\u00fd ako plugin; nav\u0161t\u00edvte http://azureus.sourceforge.net/plugin_list.php. Po nain\u0161talovan\u00ed pou\u017eite menu Pluginy->IRC. MyTrackerView.webui.contextmenu.copyurl=Kop\u00edrova\u0165 URL Torrentu do schr\u00e1nky ConfigView.section.file.torrent.ignorefiles=Ignorovan\u00e9 s\u00fabory pri vytv\u00e1ran\u00ed Torrentov\nnapr. .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=Ignorovanie s\u00faborov ConfigView.section.style.useUnitsRateBits=Pre r\u00fdchlosti pou\u017e\u00edva\u0165 bity namiesto bajtov (KiB/s->Kibit/s at\u010f.) ConfigView.section.interface.resetassoc=Obnovi\u0165 nastavenie asoci\u00e1ci\u00ed s\u00faborov (.torrent) ConfigView.section.interface.resetassocbutton=Obnovi\u0165 ConfigView.section.interface.checkassoc=Pri \u0161tarte kontrolova\u0165 asoci\u00e1cie s\u00faborov dialog.associations.title=Kontrola asoci\u00e1cie s\u00faborov Button.yes=\u00c1no Button.no=Nie ConfigView.label.seeding.autoStart0Peers=Automaticky sp\u00fa\u0161\u0165a\u0165 v\u0161etky dokon\u010den\u00e9 Torrenty s 0 klientami ConfigView.label.seeding.autoStart0Peers.tooltip=Zapnite, ak chcete aby Tracker st\u00e1le vypisoval zoznam zdrojov pre Torrenty s 0 klientami. dialog.associations.prompt=Vuze nie je predvolen\u00e1 aplik\u00e1cia pre BitTorrent s\u00fabory.\nPrajete si nastavi\u0165 Vuze ako predvolen\u00fa aplik\u00e1ciu pre .torrent s\u00fabory? dialog.associations.askagain=Skontrolova\u0165 pri \u0161tarte ConfigView.section.plugins.update=Aktualiz\u00e1cia pluginov Plugin.pluginupdate.enablecheck=Povoli\u0165 aktualiz\u00e1ciu pluginov plugins.basicview.status=Stav: plugins.basicview.activity=Aktivita: plugins.basicview.progress=Progres: plugins.basicview.log=Protokol: ConfigView.label.maxdownloadspeed=Celkov\u00e1 maxim\u00e1lna r\u00fdchlos\u0165 downloadu v kB/s [0: neobmedzen\u00e1] splash.loadingTorrent=Na\u010d\u00edtanie Torrentu splash.of=z UpdateWindow.title=Aktualiz\u00e1cia programu Vuze UpdateWindow.header=Je treba aktualizova\u0165 nasleduj\u00face komponenty : UpdateWindow.columns.install=In\u0161talova\u0165 UpdateWindow.columns.name=N\u00e1zov UpdateWindow.columns.version=Verzia UpdateWindow.columns.size=Ve\u013ekos\u0165 UpdateWindow.cancel=Storno UpdateWindow.quit=Koniec UpdateWindow.close=Zavrie\u0165 UpdateWindow.ok=Aktualizova\u0165 UpdateWindow.restart=Re\u0161tartova\u0165 UpdateWindow.status.downloading=S\u0165ahovanie UpdateWindow.status.done=Hotovo UpdateWindow.status.failed=Chyba UpdateWindow.status.restartNeeded=Bude treba re\u0161tartova\u0165 Vuze ConfigView.pluginlist.broken=Nefunk\u010dn\u00fd ConfigView.pluginlist.whereToPut=Pou\u017e\u00edvate\u013esk\u00e9 pluginy umiestnite do zlo\u017eky (ka\u017ed\u00fd do vlastnej podzlo\u017eky): ConfigView.pluginlist.whereToPutOr=Pre zdie\u013ean\u00e9 pluginy pou\u017eite zlo\u017eku: MainWindow.statusText.checking=Kontrola aktualiz\u00e1ci\u00ed TableColumn.header.OnlyCDing4=Iba distribuovan\u00fd TableColumn.header.OnlyCDing4.info=Mno\u017estvo \u010dasu, po ktor\u00fd bol Torrent iba distribuovan\u00fd. Nezah\u0155\u0148a \u010das, po ktor\u00fd sa Torrent s\u0165ahoval (a distribuoval). ConfigView.section.style.alternateTablePainting=Pou\u017ei\u0165 n\u00e1hradn\u00fa met\u00f3du kreslenia st\u013apcov tabu\u013eky [m\u00f4\u017ee vy\u017eadova\u0165 re\u0161tart] UpdateWindow.status.restartMaybeNeeded=M\u00f4\u017ee by\u0165 potrebn\u00fd re\u0161tart ConfigView.pluginlist.shared=zdie\u013ean\u00fd PeersView.host=Meno stroja PeersView.host.info=Meno stroja klienta, ak je dostupn\u00e9 (m\u00f4\u017ee ovplyvni\u0165 v\u00fdkon) MainWindow.menu.help.whatsnew=\u010co je nov\u00e9ho ConfigView.label.checkonstart=Zis\u0165ova\u0165 aktualiz\u00e1cie ke\u010f Vuze \u0161tartuje ConfigView.label.periodiccheck=Periodicky zis\u0165ova\u0165 aktualiz\u00e1cie ConfigView.label.opendialog=Automaticky otvori\u0165 Asistenta aktualiz\u00e1cie ak je aktualiz\u00e1cia k dispoz\u00edcii MainWindow.updateavail=(Aktualiz\u00e1cia je k dispoz\u00edcii) MainWindow.status.latestversionunchecked=Zis\u0165ovanie verzie je vypnut\u00e9 GeneralView.label.updatein.stopped=Zastaven\u00fd StartStopRules.menu.viewDebug=Zobrazi\u0165 Debug info ConfigView.section.style.doNotUseGB=Nepou\u017e\u00edva\u0165 jednotku GB ConfigView.section.style.doNotUseGB.tooltip=Ak je za\u0161krtnut\u00e9, Vuze bude pou\u017e\u00edva\u0165 MB aj pre ve\u013ekosti v\u00e4\u010d\u0161ie ako 1024MB. MainWindow.menu.help.plugins=Pluginy ConfigView.section.tracker.enablecategories=Rozdeli\u0165 Torrenty pod\u013ea kateg\u00f3rie health.explain.share=znamen\u00e1, \u017ee Torrent je hos\u0165ovan\u00fd alebo publikovan\u00fd ConfigView.section.tracker.createcert=Vytvori\u0165 certifik\u00e1t podp\u00edsan\u00fd sebou sam\u00fdm ConfigView.section.tracker.createbutton=Vytvori\u0165 security.certcreate.title=Vytvori\u0165 certifik\u00e1t podp\u00edsan\u00fd sam\u00fdm sebou security.certcreate.intro=Tento dial\u00f3g V\u00e1m umo\u017en\u00ed vytvori\u0165 certifik\u00e1t podp\u00edsan\u00fd sam\u00fdm sebou security.certcreate.alias=Prez\u00fdvka security.certcreate.strength=Sila \u0161ifry security.certcreate.firstlastname=Prv\u00e9 a Posledn\u00e9 meno security.certcreate.orgunit=Organiza\u010dn\u00e1 jednotka security.certcreate.org=Organiz\u00e1cia security.certcreate.city=Mesto alebo Lokalita security.certcreate.state=\u0160t\u00e1t alebo Provincia security.certcreate.country=Dvojp\u00edsmenov\u00fd k\u00f3d krajiny security.certcreate.ok=Vytvori\u0165 security.certcreate.cancel=Zru\u0161i\u0165 security.certcreate.createok=Certifik\u00e1t bol \u00faspe\u0161ne vytvoren\u00fd security.certcreate.createfail=Vytv\u00e1ranie certifik\u00e1tu ne\u00faspe\u0161n\u00e9 webui.passwordenable=Povoli\u0165 heslo webui.user=Pou\u017e\u00edvate\u013esk\u00e9 meno webui.password=Heslo webui.protocol=Protokol (*) webui.homepage=Domovsk\u00e1 str\u00e1nka (*) webui.rootdir=Kore\u0148ov\u00fd adres\u00e1r (*) webui.rootres=Kore\u0148ov\u00fd zdroj (*) webui.mode=M\u00f3d (*) webui.mode.info=M\u00f3d m\u00f4\u017ee by\u0165\n\t"pln\u00fd (full)"\t= v\u0161etky oper\u00e1cie povolen\u00e9 (predvolen\u00e9)\n\t"prezeranie (view)"\t= iba prezeranie (ale m\u00f4\u017ee meni\u0165 obnovovaciu frekvenciu) webui.access=Pr\u00edstup (*) webui.access.info=Pr\u00edstup m\u00f4\u017ee by\u0165\n\t"lok\u00e1lny (local)"\t= teda iba lok\u00e1lny stroj sa m\u00f4\u017ee pripoji\u0165\n\t"v\u0161etky (all)"\t= neobmedzen\u00fd pr\u00edstup (predvolen\u00e9)\n\tIP\t= napr. 192.168.0.2\t\t\tiba 1 IP adresa\n\tIP1-IP2\t= napr. 192.168.0.1-192.168.0.255\trozsah IP adries GeneralView.label.maxdownloadspeed=Max. down Security.keystore.corrupt=\u00daschov\u0148a k\u013e\u00fa\u010dov '%1' nemohla by\u0165 nahran\u00e1, pros\u00edm zru\u0161te ju a znovu vytvorte/importujte certifik\u00e1ty Security.keystore.empty=\u00daschov\u0148a k\u013e\u00fa\u010dov je pr\u00e1zdna. Pros\u00edm vytvorte certifik\u00e1t podp\u00edsan\u00fd sam\u00fdm sebou (N\u00e1stroje->Nastavenie->Zabezpe\u010denie) alebo importujte existuj\u00faci certifik\u00e1t do '%1' webui.restart.info=Aby sa prejavili zmeny parametrov ozna\u010den\u00fdch (*), je potrebn\u00fd re\u0161tart GeneralView.label.maxdownloadspeed.tooltip=Max. r\u00fdchlos\u0165 s\u0165ahovania [0: neobmedzen\u00e1] upnp.enable=Povoli\u0165 UPnP upnp.info=Universal Plug and Play (UPnP) umo\u017e\u0148uje automatick\u00e9 mapovanie portov na smerova\u010doch s podporou UPnP. upnp.mapping.dataport=Pr\u00edchodz\u00ed d\u00e1tov\u00fd port klienta upnp.mapping.tcptrackerport=TCP port Trackera upnp.mapping.udptrackerport=UDP port Trackera upnp.alert.differenthost=UPnP: Mapovanie '%1' bolo rezervovan\u00e9 '%2' - pros\u00edm zvo\u013ete in\u00fd port upnp.alert.mappingok=UPnP: Mapovanie '%1' \u00faspe\u0161n\u00e9 upnp.alert.mappingfailed=UPnP: Mapovanie '%1' zlyhalo upnp.alertsuccess=Hl\u00e1si\u0165 \u00faspe\u0161n\u00e9 mapovania upnp.alert.lostdevice=UPnP: Stratilo sa spojenie so slu\u017ebou '%1' na UPnP zariaden\u00ed '%2' upnp.grabports=Mapova\u0165 porty aj ke\u010f ich vlastnia in\u00e9 po\u010d\u00edta\u010de upnp.refresh.label=Obnovi\u0165 mapovania upnp.refresh.button=Obnovi\u0165 upnp.alert.mappinggrabbed=UPnP: Mapovanie '%1' \u00faspe\u0161n\u00e9 - z\u00edskan\u00e9 od '%2' upnp.mapping.tcpssltrackerport=TCP SSL port Trackera upnp.alertothermappings=Hl\u00e1si\u0165 porty, ktor\u00e9 vlastnia in\u00e9 po\u010d\u00edta\u010de upnp.alertdeviceproblems=Hl\u00e1si\u0165 probl\u00e9my s UPnP zariaden\u00edm ConfigView.pluginlist.coreplugins=Nasleduj\u00face vstavan\u00e9 pluginy s\u00fa nahrat\u00e9: Peers.column.DLedFromOthers=Od ostatn\u00fdch Peers.column.DLedFromOthers.info=Mno\u017estvo d\u00e1t stiahnut\u00fdch od ostatn\u00fdch, k\u00fdm boli pripojen\u00ed na v\u00e1s Peers.column.UpDownRatio=Up:Down pomer Peers.column.UpDownRatio.info=Klientov pomer "Uploadovan\u00e9 : Downloadovan\u00e9" Peers.column.UpRatio=Up pomer Peers.column.UpRatio.info=Klientov pomer "Uploadovan\u00e9 od v\u00e1s : Uploadovan\u00e9 od in\u00fdch" upnp.releasemappings=Zru\u0161i\u0165 mapovania pri ukon\u010den\u00ed webui.upnpenable=Povoli\u0165 UPnP pre tento port (*) ConfigView.section.file.friendly.hashchecking=Priate\u013esk\u00e9 overovanie hashu ConfigView.section.file.friendly.hashchecking.tooltip=Overovanie hashu bude trochu pomal\u0161ie, av\u0161ak bude ove\u013ea menej za\u0165a\u017eova\u0165 cpu/syst\u00e9m. ConfigView.section.tracker.seedretention=Max. po\u010det zadr\u017ean\u00fdch zdrojov na Torrent [0: neobmedzen\u00fd] ConfigView.section.tracker.seedretention.info=Pozn.: \u0160tatistiky uploadu sa stratia pre nezadr\u017ean\u00e9 zdroje ConfigView.section.tracker.port=Povoli\u0165 Tracker na HTTP porte ConfigView.section.tracker.sslport=Povoli\u0165 Tracker na HTTPS porte ConfigView.section.tracker.publicenable.info=Dovol\u00ed in\u00fdm vytvori\u0165 Torrenty, ktor\u00e9 bud\u00fa pou\u017e\u00edva\u0165 v\u00e1\u0161 Tracker\nbez toho, aby ste ich museli hos\u0165ova\u0165/publikova\u0165 Button.clear=Vymaza\u0165 MainWindow.IPs.tooltip=Posledn\u00e1 aktualiz\u00e1cia zoznamu filtrov: %1\nPo\u010det IP Filtrov - Po\u010det blokovan\u00fdch/zak\u00e1zan\u00fdch/zl\u00fdch IP adries pri tomto spusten\u00ed\nDvojklikom zobraz\u00edte \u010fal\u0161ie inform\u00e1cie. ConfigView.section.ipfilter.list.banned=bol zak\u00e1zan\u00fd ConfigView.section.ipfilter.list.baddata=poslal zl\u00e9 d\u00e1ta: v\u00fdskyty = ConfigView.section.ipfilter.bannedinfo=IP adresy, ktor\u00e9 posielali zl\u00e9 d\u00e1ta - zak\u00e1zan\u00e9, ak prekro\u010dili limity ConfigView.section.ipfilter.blockedinfo=IP adresy, ktor\u00e9 boli blokovan\u00e9 IP filtrom download.removerules.name=Pravidl\u00e1 odoberania download.removerules.unauthorised.info=Neautorizovan\u00e9 Torrenty s\u00fa tak\u00e9, ktor\u00fdch odozva obsahuje "not authoris(z)ed" alebo "unautoris(z)ed" vo "failure response" download.removerules.unauthorised=Automaticky odobra\u0165 neautorizovan\u00e9 Torrenty download.removerules.unauthorised.seedingonly=\tIba pri distrib\u00facii download.removerules.removed.ok=Torrent '%1' bol automaticky odobran\u00fd. Bolo to sp\u00f4soben\u00e9 pravidlami odoberania Torrentu. download.removerules.updatetorrents=Odobra\u0165 Torrenty s aktualiz\u00e1ciou Azureusa, ak je to nutn\u00e9 ConfigView.label.defaultstarttorrentsstopped=Nov\u00e9 Torrenty prid\u00e1va\u0165 v zastavenom stave ConfigView.section.server.enableudp=Povoli\u0165 UDP protokol. upnp.mapping.dataportudp=UDP port klienta Trackera ConfigView.section.file.decoder.showlax=Zobrazi\u0165 menej pravdepodobn\u00e9 k\u00f3dovania ConfigView.section.file.decoder.showall=Uva\u017eova\u0165 v\u0161etky mo\u017en\u00e9 k\u00f3dovania MainWindow.status.updowndetails.tooltip=Detaily r\u00fdchlost\u00ed uploadu/downloadu - kliknite prav\u00fdm, ak chcete zmeni\u0165 TrackerClient.announce.warningmessage=Tracker pre '%1' vr\u00e1til varovanie '%2' ConfigView.section.tracker.natcheckenable=Testova\u0165 pripojite\u013enos\u0165 'prich\u00e1dzaj\u00faceho d\u00e1tov\u00e9ho portu' a hl\u00e1si\u0165 poruchy klientom ConfigView.section.tracker.publishenabledetails=Publikova\u0165 v\u0161etky detaily o Torrentoch ConfigView.section.tracker.publishenablepeerdetails=Publikova\u0165 detaily o klientoch MyTrackerView.badnat=Zl\u00e9 NAT MyTrackerView.badnat.info=Zdroje/Klienti, ktor\u00fdm sa nepodarilo otestova\u0165 NAT, ak je povolen\u00e9 ConfigView.section.tracker.natchecktimeout=\u010casov\u00fd limit testovania (sek) ConfigView.section.file.perf.cache.enable=Povoli\u0165 diskov\u00fa cache ConfigView.section.file.perf.cache.size=Ve\u013ekos\u0165 cache v %1 #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=&Prenosy MainWindow.menu.transfers.startalltransfers=&Spusti\u0165 v\u0161etky MainWindow.menu.transfers.stopalltransfers=&Zastavi\u0165 v\u0161etky MainWindow.menu.transfers.pausetransfers=&Preru\u0161i\u0165 MainWindow.menu.transfers.resumetransfers=P&okra\u010dova\u0165 ConfigView.label.experimental.osx.kernel.panic.fix=Experiment\u00e1lna oprava kv\u00f4li probl\u00e9mom na dvoj-procesorov\u00fdch OSX syst\u00e9moch [potrebuje re\u0161tart] SystemTray.menu.pausetransfers=Preru\u0161i\u0165 prenosy SystemTray.menu.resumetransfers=Pokra\u010dova\u0165 v prenosoch ConfigView.section.file.truncate.too.large=Skr\u00e1ti\u0165 existuj\u00face s\u00fabory ak s\u00fa pr\u00edli\u0161 dlh\u00e9 ConfigView.section.file.perf.cache.trace=Zaznamen\u00e1va\u0165 oper\u00e1cie cache pre diagnostick\u00e9 \u00fa\u010dely ConfigView.section.interface.enabletray=Povoli\u0165 ikonu v System Tray [nutn\u00fd re\u0161tart] PeerManager.status.error=Chyba Stats.title.full=\u0160tatistiky TransferStatsView.title.full=Prenosy CacheView.general.size=Celkov\u00e1 ve\u013ekos\u0165 CacheView.general.inUse=Pou\u017e\u00edva sa CacheView.general.title=Inform\u00e1cie o cache CacheView.reads.title=\u010c\u00edtanie CacheView.reads.fromFile=Zo s\u00faboru CacheView.reads.fromCache=Z cache CacheView.reads.hits=Z\u00e1sahov CacheView.writes.title=Z\u00e1pis CacheView.writes.toCache=Do cache CacheView.writes.toFile=Do s\u00faboru CacheView.writes.hits=Ulo\u017een\u00fdch CacheView.speeds.title=R\u00fdchlos\u0165 CacheView.speeds.reads=\u010c\u00edtanie CacheView.speeds.writes=Z\u00e1pis CacheView.speeds.fromCache=Cache CacheView.speeds.fromFile=S\u00fabory CacheView.reads.#=Po\u010det CacheView.reads.amount=Mno\u017estvo CacheView.reads.avgsize=Priemern\u00e1 ve\u013ekos\u0165 openUrl.referrer=Odkazuj\u00faca sa URL (refferer) : openUrl.referrer.info=Potrebn\u00e9 len pre web str\u00e1nky, ktor\u00e9 to vy\u017eaduj\u00fa ConfigView.label.maxuploadspeedseeding=Celkov\u00e1 maxim\u00e1lna r\u00fdchlos\u0165 uploadu v kB/s ke\u010f iba distribuujem [0: neobmedzen\u00e1] ConfigView.label.transfer.ignorepeerports=Ignoruj klientov s t\u00fdmito d\u00e1tov\u00fdmi portami (oddelen\u00e9 ';', napr. 0;25) ConfigView.section.proxy.enable_socks.peer=Povoli\u0165 pou\u017eitie proxy na komunik\u00e1ciu s klientami (iba odch\u00e1dzaj\u00face spojenia) [nutn\u00fd re\u0161tart] ConfigView.section.proxy.peer.informtracker=Informova\u0165 Tracker o obmedzen\u00ed ConfigView.section.proxy.socks.version=Verzia SOCKS PiecesView.legend.written=Zap\u00edsan\u00e9 PiecesView.legend.requested=Vy\u017eiadan\u00e9 PiecesView.legend.downloaded=Stiahnut\u00e9, zapisuje sa PiecesView.legend.incache=D\u00e1ta s\u00fa v cache PiecesView.typeItem.0=Pomal\u00fd PiecesView.typeItem.1=R\u00fdchly PiecesView.type=Typ Security.jar.tools_not_found=Podpisovanie JAR s\u00faboru zlyhalo - 'tools.jar' nebol n\u00e1jden\u00fd v %1. Detaily pozrite v N\u00e1stroje->Nastavenie->Zabezpe\u010denie. Security.jar.signfail=Podpisovanie JAR s\u00faboru zlyhalo - %1 ConfigView.section.security.toolsinfo=Podp\u00edsan\u00e9 JAR s\u00fabory sa pou\u017e\u00edvaj\u00fa na podporu niektor\u00fdch pluginov, napr\u00edklad Swing Web Interface (ke\u010f je tak nakonfigurovan\u00fd).\nAk chcete podp\u00edsa\u0165 JAR s\u00fabory, je nutn\u00e9 ma\u0165 pr\u00edstup k s\u00faboru 'tools.jar', ktor\u00fd je obsiahnut\u00fd v Sun JDK (nie JRE).\nAk m\u00e1te nain\u0161talovan\u00e9 iba JRE, tak potom pros\u00edm nain\u0161talujte JDK.\nVuze za norm\u00e1lnych okolnost\u00ed n\u00e1jde s\u00fabor s\u00e1m. Av\u0161ak, ak sa mu to nepodar\u00ed, m\u00f4\u017eete tu nastavi\u0165 zlo\u017eku kde m\u00e1 h\u013eada\u0165. ConfigView.section.security.toolsdir=Zlo\u017eka obsahuj\u00faca 'tools.jar' ConfigView.section.security.choosetoolssavedir=Vyberte zlo\u017eku obsahuj\u00facu 'tools.jar' ConfigView.section.proxy.peer.same=Pou\u017e\u00edva\u0165 rovnak\u00e9 nastavenia proxy servera pre komunik\u00e1ciu s Trackerom a klientami ConfigView.section.connection.network.max.simultaneous.connect.attempts=Max. po\u010det s\u00fa\u010dasn\u00fdch odch\u00e1dzaj\u00facich spojen\u00ed [0: \u017eiadne odch\u00e1dzaj\u00face spojenia] ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Max. po\u010det nov\u00fdch odch\u00e1dzaj\u00facich spojen\u00ed, o ktor\u00e9 sa m\u00f4\u017ee Vuze hocikedy pok\u00fasi\u0165.\nPozn.: WindowsXP Service Pack 2 (SP2) nastavuje syst\u00e9mov\u00fd limit 10 s\u00fa\u010dasn\u00fdch pokusov o spojenie.\n\u0160tandardn\u00e1 hodnota je 8. Hodnota 0 \u00faplne vypne odch\u00e1dzaj\u00face spojenia. ConfigView.section.file.perf.cache.size.explain=Cache sa pou\u017e\u00edva na obmedzenie \u010d\u00edtan\u00ed/z\u00e1pisov disku. Ak nepou\u017e\u00edvate vo\u013ebu javy '-XX:MaxDirectMemorySize' pre explicitn\u00e9 nastavenie pam\u00e4te dostupnej pre cache a sie\u0165ov\u00e9 oper\u00e1cie, mali by ste t\u00fato hodnotu ponecha\u0165 minim\u00e1lne o %1 men\u0161iu ako je maxim\u00e1lna ve\u013ekos\u0165 VM. Aktu\u00e1lna maxim\u00e1lna ve\u013ekos\u0165 VM je %2. Pre n\u00e1vod ako toto nastavi\u0165, pozrite MemoryUsage vo wiki na %3. Ak nepou\u017eijete rozumn\u00e9 hodnoty m\u00f4\u017ee to skon\u010di\u0165 chybov\u00fdmi hl\u00e1seniami 'out of memory'. Viac ako 32MB cache je pravdepodobne zbyto\u010dn\u00e9. MyTorrentsView.menu.setSpeed.unlimit=Bez limitu MyTorrentsView.menu.setSpeed.unlimited=Neobmedzene MyTorrentsView.menu.setSpeed.disable=Vypn\u00fa\u0165 upload MyTorrentsView.menu.setSpeed.disabled=Vypnut\u00fd MyTorrentsView.menu.setSpeed.in=v MyTorrentsView.menu.setSpeed.slots=slotoch GeneralView.label.maxuploadspeed=Max. up GeneralView.label.maxuploadspeed.tooltip=max. r\u00fdchlos\u0165 uploadu [0 : neobmedzen\u00e1] MyTorrents.items.UpSpeedLimit.disabled=\u017diadna MyTorrents.items.UpSpeedLimit.unlimited=Neobmedzen\u00e1 TableColumn.header.maxupspeed=Max Up r\u00fdchlos\u0165 TableColumn.header.maxupspeed.info=Max. r\u00fdchlos\u0165 uploadu na Torrent ConfigView.section.file.perf.cache.enable.write=Cacheova\u0165 stiahnut\u00e9 d\u00e1ta, aby sa obmedzili z\u00e1pisy na disk a tie\u017e \u010d\u00edtania z disku pri overovan\u00ed dielu ConfigView.section.file.perf.cache.enable.read=Pred\u010d\u00edtava\u0165 d\u00e1ta pri uploade, aby sa obmedzilo \u010d\u00edtanie z disku ConfigView.section.tracker.separatepeerids=Pou\u017ei\u0165 rozdielne identity klientov pre komunik\u00e1ciu s Trackerom a d\u00e1tov\u00fa komunik\u00e1ciu ConfigView.section.tracker.separatepeerids.info=Zv\u00fd\u0161i anonymitu, ak s\u0165ahujete/distribuujete anonymne\na pou\u017e\u00edvate neanonymn\u00e9 pripojenie k Trackeru ConfigView.section.interface.wavlocation=Umiestnenie .wav s\u00faboru ConfigView.section.interface.wavlocation.info=Zvo\u013ete .wav s\u00fabor ConfigView.section.tracker.client=Klient ConfigView.section.tracker.client.connecttimeout=\u010casov\u00fd limit spojenia (sek) ConfigView.section.tracker.client.readtimeout=\u010casov\u00fd limit \u010d\u00edtania (sek) MainWindow.menu.tools=&N\u00e1stroje FilesView.path=Cesta FilesView.fullpath=Pln\u00e1 cesta FilesView.remaining=Zost\u00e1va dielov TableColumn.header.trackername=Meno Trackera TableColumn.header.trackername.info=Meno Trackera zalo\u017een\u00e9 na oznamovacej URL ConfigView.group.override=Nastavenia ConfigView.section.file.perf.cache.notsmallerthan=Necacheova\u0165 s\u00fabory men\u0161ie ako (v %1) PeersView.menu.blockupload=Blokova\u0165 upload PeersView.menu.kickandban=Odpoji\u0165 a Zak\u00e1za\u0165 PeersView.menu.kickandban.reason=Klient bol manu\u00e1lne zak\u00e1zan\u00fd PeersView.state=Stav PeersView.state.info=Stav pripojenia klienta PeersView.state.pending=\u010cakanie PeersView.state.connecting=Prip\u00e1janie PeersView.state.handshake=\u010cakanie na potvrdenie PeersView.state.established=Plne pripojen\u00fd ConfigView.section.tracker.processinglimits=Limity spracovania ConfigView.section.tracker.maxgettime=Max. \u010das pre spracovanie GET (sek) [0: neobmedzen\u00fd] ConfigView.section.tracker.maxgettime.info=Pou\u017e\u00edva sa pre Oznamy a Scrapy ConfigView.section.tracker.maxposttimemultiplier=N\u00e1sobok \u010dasu GET pre spracovanie POST [0: neobmedzen\u00fd] ConfigView.section.tracker.maxposttimemultiplier.info=Pou\u017e\u00edva sa pre Odosielanie formul\u00e1rov a Uploady ConfigView.section.tracker.maxthreads=Max. po\u010det s\u00fa\u010dasn\u00fdch po\u017eiadaviek DownloadManager.error.operationcancancelled=Oper\u00e1cia zru\u0161en\u00e1 Torrent.create.progress.cancelled=Oper\u00e1cia zru\u0161en\u00e1 sharing.progress.cancel=Zru\u0161i\u0165 wizard.maketorrents.autoopen=Po dokon\u010den\u00ed za\u010dat distrib\u00faciu Torrentu ConfigView.section.sharing.rescanenable=Povoli\u0165 opakovan\u00e9 zis\u0165ovanie zmien zdie\u013ean\u00fdch s\u00faborov ConfigView.section.sharing.rescanperiod=Peri\u00f3da zis\u0165ovania (sek\u00fand) ConfigView.section.connection.advanced=Roz\u0161\u00edren\u00e9 nastavenia siete ConfigView.section.connection.advanced.mtu=Max. jednotka prenosu (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Maxim\u00e1lna ve\u013ekos\u0165 paketu, ktor\u00fd m\u00f4\u017ee by\u0165 prenesen\u00fd sie\u0165ou v jednom r\u00e1mci.\nVuze pou\u017e\u00edva MTU-40 (MSS) pre optimaliz\u00e1ciu uploadu.\nOdpor\u00fa\u010dan\u00e9 hodnoty s\u00fa:\n 576 - Dial-up pripojenia\n1492 - PPPoE \u0161irokop\u00e1smov\u00e9 pripojenia\n1500 - Ethernet, DSL a Cable \u0161irokop\u00e1smov\u00e9 pripojenia ConfigView.section.connection.advanced.SO_RCVBUF=Ve\u013ekos\u0165 SO_RCVBUF [0: pou\u017ei \u0161tandardn\u00fa hodnotu OS] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Nastav\u00ed \u0161tandardn\u00fa hodnotu SO_RCVBUF socketu (v bajtoch), tozn. ve\u013ekos\u0165 prij\u00edmacieho okna TCP.\nVuze toto \u0161tandardne nenastavuje, pou\u017e\u00edva sa teda hodnota, ktor\u00fa nastav\u00ed OS.\nPozn.: Linux zdvojn\u00e1sob\u00ed zadan\u00fa hodnotu. ConfigView.section.connection.advanced.SO_SNDBUF=Ve\u013ekos\u0165 SO_SNDBUF [0: pou\u017ei \u0161tandardn\u00fa hodnotu OS] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Nastav\u00ed \u0161tandardn\u00fa hodnotu SO_RCVBUF socketu (v bajtoch), tozn. ve\u013ekos\u0165 vysielacieho okna TCP.\nVuze toto \u0161tandardne nenastavuje, pou\u017e\u00edva sa teda hodnota, ktor\u00fa nastav\u00ed OS.\nPozn.: Linux zdvojn\u00e1sob\u00ed zadan\u00fa hodnotu. ConfigView.section.interface.confirm_torrent_removal=Zobrazi\u0165 potvrdzuj\u00faci dial\u00f3g pri odoberan\u00ed Torrentu ConfigView.section.interface.confirm_torrent_removal.tooltip=Potvrdenie pri odoberan\u00ed Torrentu zo zobrazenia 'Moje Torrenty'. MyTorrentsView.confirm_torrent_removal=Naozaj chcete odstr\u00e1ni\u0165?\n TableColumn.header.seed_to_peer_ratio=Zdroj:Klient pomer TableColumn.header.seed_to_peer_ratio.info=Celkov\u00fd pomer zdrojov ku klientom PeersView.connected_time=\u010cas pripojenia PeersView.connected_time.info=Celkov\u00fd \u010das pripojenia klienta ConfigView.section.interface.display.add_torrents_silently=Prid\u00e1va\u0165 Torrenty potichu ConfigView.section.interface.display.add_torrents_silently.tooltip=Prid\u00e1va\u0165 Torrenty bez aktiv\u00e1cie hlavn\u00e9ho okna Azureusa. TableColumn.header.maxdownspeed=Max Down r\u00fdchlos\u0165 TableColumn.header.maxdownspeed.info=Max. r\u00fdchlos\u0165 s\u0165ahovania na Torrent PeersGraphicView.title=\u00da\u010dastn\u00edci ConfigView.section.tracker.passwordwebhttpsonly=Povoli\u0165 pr\u00edstup iba cez HTTPS TableColumn.header.torrentpath=Umiestnenie Torrentu TableColumn.header.torrentpath.info=Umiestnenie Torrentu na disku ConfigView.section.sharing.torrentcomment=Koment\u00e1r pre generovan\u00e9 Torrenty ConfigView.label.copyanddeleteratherthanmove=Kop\u00edrova\u0165 a potom zmaza\u0165 origin\u00e1lne d\u00e1ta namiesto priameho presunu - m\u00f4\u017ee pred\u00eds\u0165 strate d\u00e1t na niektor\u00fdch s\u00faborov\u00fdch syst\u00e9moch ConfigView.label.openstatsonstart=Po spusten\u00ed otvori\u0165 \u0160tatistiky swt.install.window.title=Vuze - in\u0161tal\u00e1tor pluginov swt.install.window.ok=In\u0161talova\u0165 swt.install.window.header=Nasleduj\u00face komponenty boli vybran\u00e9 na in\u0161tal\u00e1ciu : swt.uninstall.window.title=Vuze - odobera\u010d pluginov swt.uninstall.window.ok=Odobra\u0165 swt.uninstall.window.header=Nasleduj\u00face komponenty boli vybran\u00e9 na odobratie : installPluginsWizard.title=In\u0161tal\u00e1cia pluginov installPluginsWizard.mode.title=Pros\u00edm vyberte met\u00f3du in\u0161tal\u00e1cie installPluginsWizard.mode.list=Zo sourceforge.net installPluginsWizard.list.title=Zoznam in\u0161talovate\u013en\u00fdch pluginov installPluginsWizard.list.loading=Pros\u00edm po\u010dkajte, k\u00fdm sa nahr\u00e1 zoznam pluginov. installPluginsWizard.list.loaded=Pros\u00edm zvo\u013ete pluginy, ktor\u00e9 chcete in\u0161talova\u0165. installPluginsWizard.list.name=Meno installPluginsWizard.list.version=Verzia installPluginsWizard.list.description=Popis pluginu installPluginsWizard.finish.title=Prebieha in\u0161tal\u00e1cia installPluginsWizard.finish.explanation=Vybran\u00e9 pluginy bud\u00fa nain\u0161talovan\u00e9 pomocou Asistenta aktualiz\u00e1cie.\n\nVydr\u017ete pros\u00edm, m\u00f4\u017ee to chv\u00ed\u013eu trva\u0165. installPluginsWizard.details.loading=Nahr\u00e1vam detaily, \u010dakajte pros\u00edm... installPluginsWizard.mode.file=Zo s\u00faboru installPluginsWizard.installMode.title=Pros\u00edm vyberte typ in\u0161tal\u00e1cie installPluginsWizard.installMode.user=In\u0161talova\u0165 plugin(y) iba pre seba installPluginsWizard.installMode.shared=In\u0161talova\u0165 plugin(y) pre v\u0161etk\u00fdch pou\u017e\u00edvate\u013eov installPluginsWizard.file.title=Pros\u00edm zvo\u013ete plugin, ktor\u00fd chcete in\u0161talova\u0165 installPluginsWizard.file.file=S\u00fabor : installPluginsWizard.file.invalidfile=S\u00fabor nie je platn\u00fd plugin pre Azureus. installPluginsWizard.file.browse=Prech\u00e1dza\u0165... uninstallPluginsWizard.title=Odin\u0161tal\u00e1cia pluginov uninstallPluginsWizard.list.title=Zoznam nain\u0161talovan\u00fdch pluginov uninstallPluginsWizard.list.loaded=Pros\u00edm vyberte pluginy, ktor\u00e9 chcete odin\u0161talova\u0165. installPluginsWizard.list.nullversion=\u017diadna uninstallPluginsWizard.finish.title=Prebieha odin\u0161tal\u00e1cia uninstallPluginsWizard.finish.explanation=Zvolen\u00e9 Pluginy bud\u00fa odin\u0161talovan\u00e9 pomocou Asistenta aktualiz\u00e1cie. MainWindow.menu.plugins.installPlugins=Sprievodca in\u0161tal\u00e1ciou MainWindow.menu.plugins.uninstallPlugins=Sprievodca odin\u0161tal\u00e1ciou ConfigView.section.ipfilter.totalIPs=%1 IP adries je celkovo blokovan\u00fdch, \u010do je %2 internetu. update.instance.install=Zis\u0165ovanie in\u0161tal\u00e1ci\u00ed update.instance.uninstall=Zis\u0165ovanie odin\u0161tal\u00e1ci\u00ed update.instance.update=Zis\u0165ovanie aktualiz\u00e1ci\u00ed MainWindow.status.update.tooltip=Dvojklik pre inform\u00e1cie o progrese updater.progress.window.title=Aktu\u00e1lne in\u0161tala\u010dn\u00e9 \u00falohy updater.progress.window.info=Stla\u010dte 'Zru\u0161i\u0165' pre skon\u010denie v\u0161etk\u00fdch prebiehaj\u00facich \u00faloh Button.abort=Preru\u0161i\u0165 ConfigView.section.ipfilter.enablebanning=Blokova\u0165 klientov, ktor\u00ed neust\u00e1le posielaj\u00fa zl\u00e9 d\u00e1ta Network.alert.acceptfail=Prive\u013ea po sebe nasleduj\u00facich v\u00fdpadkov nastalo na porte %1, %2 - spracovanie zru\u0161en\u00e9. Pros\u00edm pozrite si nastavenie firewallu pre tento port, \u010di m\u00e1 povolen\u00e9 prich\u00e1dzaj\u00face spojenia. MyShares.column.category=Kateg\u00f3ria UpdateWindow.restartLater=Re\u0161tartova\u0165 nesk\u00f4r MainWindow.menu.file.restart=Re\u0161tart MainWindow.dialog.restartconfirmation.title=Re\u0161tartova\u0165 Vuze MainWindow.dialog.restartconfirmation.text=Naozaj chcete re\u0161tartova\u0165 Vuze deletetorrent.message1=Chyst\u00e1te sa zmaza\u0165 TORRENT pre :\n deletetorrent.message2=\nNaozaj chcete pokra\u010dova\u0165? ConfigView.label.prioritizemostcompletedfiles=Viac dokon\u010den\u00e9 s\u00fabory maj\u00fa v\u00e4\u010d\u0161iu prioritu splash.plugin.init=Inicializ\u00e1cia pluginu: ConfigView.section.style.osx_small_fonts=Pou\u017e\u00edva\u0165 mal\u00e9 p\u00edsma [nutn\u00fd re\u0161tart] ConfigView.section.tracker.tcpnonblocking=Pou\u017e\u00edva\u0165 ne-blokuj\u00face I/O oper\u00e1cie pre TCP spracovanie. Ak zvol\u00edte t\u00fato mo\u017enos\u0165, web Trackera mus\u00ed be\u017ea\u0165 na inom porte. Experiment\u00e1lne! ConfigView.section.tracker.nonblocking=Ne-blokuj\u00face nastavenia ConfigView.section.tracker.nonblockingconcmax=Max. po\u010det s\u00fa\u010dasn\u00fdch spojen\u00ed [0: neobmedzen\u00fd] MyTorrentsView.menu.exporttorrent=Exportova\u0165 Torrent... ConfigView.section.tracker.client.scrapeinfo=Vypnutie Scrapovania obmedz\u00ed mnoh\u00e9 pravidl\u00e1 zara\u010fovania Torrentov do fronty, ke\u010f\u017ee tie z\u00e1visia na inform\u00e1ci\u00e1ch z\u00edskan\u00fdch od Scrapuj\u00facich Trackerov. ConfigView.section.tracker.client.scrapeenable=Povoli\u0165 scrapovanie ConfigView.section.tracker.client.scrapestoppedenable=Scrapova\u0165 Torrenty, ktor\u00e9 nebe\u017eia Scrape.status.disabled=Scrape vypnut\u00e9 MyTorrentsView.menu.explore=Otvori\u0165 cie\u013eov\u00fa zlo\u017eku MyTorrentsView.menu.explore._mac=Uk\u00e1\u017e vo Finderovi MyTorrentsView.menu.explore._windows=Uk\u00e1\u017e v Prieskumn\u00edkovi wizard.maketorrents.autohost=Hos\u0165ova\u0165 Torrent na vstavanom Trackeri ConfigView.label.overrideip=IP adresa posielan\u00e1 Trackeru ConfigView.label.overrideip.tooltip=Informuje Tracker o rozdielnej IP adrese namiesto tej odkia\u013e pri\u0161li pakety. ConfigView.section.connection.group.networks=Siete ConfigView.section.connection.group.networks.info=Vyberte siete, pre ktor\u00e9 m\u00e1 by\u0165 povolen\u00fd prenos d\u00e1t ConfigView.section.connection.networks.prompt=Op\u00fdta\u0165 sa na v\u00fdber, ak bolo pridan\u00e9 s\u0165ahovanie s anonymn\u00fdm Trackerom ConfigView.section.connection.networks.Public=Verejn\u00e1 IP sie\u0165 (ne-anonymn\u00e1) ConfigView.section.connection.networks.I2P=sie\u0165 I2P ConfigView.section.connection.networks.Tor=Sie\u0165 Onion Router (Tor) TableColumn.header.networks=Siete TableColumn.header.networks.info=Siete, pre ktor\u00e9 je povolen\u00e1 d\u00e1tov\u00e1 komunik\u00e1cia Scrape.status.networkdisabled=Sie\u0165 nie je povolen\u00e1 ConfigView.section.tracker.server.group.networks=Siete ConfigView.section.tracker.server.group.networks.info=Vyberte siete, pre ktor\u00e9 m\u00e1 Tracker akceptova\u0165 klientov window.networkselection.title=V\u00fdber siete window.networkselection.info=Dole vyp\u00edsan\u00fd Torrent m\u00e1 Tracker(y), ktor\u00fd podporuje nasledovn\u00e9 siete.\nVyberte tie, pre ktor\u00e9 m\u00e1 by\u0165 povolen\u00e1 komunik\u00e1cia s Trackerom a klientami.\nAk je to anonymn\u00fd Tracker podporuj\u00faci verejn\u00fdch klientov, povo\u013ete anonymn\u00e9 aj verejn\u00e9 siete.\nPovolenie verejnej siete m\u00e1 za n\u00e1sledok zru\u0161enie anonymity! plugins.basicview.clear=Vy\u010disti\u0165 ConfigView.section.connection.group.peersources=Zdroje klientov ConfigView.section.connection.group.peersources.info=Zvo\u013ete zdroje klientsk\u00fdch pripojen\u00ed ConfigView.section.connection.peersource.Tracker=Z trackera ConfigView.section.connection.peersource.DHT=Decentralizovan\u00e9 trackovanie ConfigView.section.connection.peersource.PeerExchange=Dodan\u00fd in\u00fdm klientom ConfigView.section.connection.peersource.Plugin=Pridan\u00fd pluginom ConfigView.section.connection.peersource.Incoming=Prich\u00e1dzaj\u00face spojenie PeersView.source=Zdroj PeersView.source.info=Zdroj tohto klienta TableColumn.header.peersources=Zdroje klientov TableColumn.header.peersources.info=Povolen\u00e9 zdoje klientov pre nadviazanie klientskeho spojenia wizard.tracker.dht=Decentralizovan\u00fd (iba klienti Vuze MyTorrentsView.menu.advancedmenu=Roz\u0161\u00edren\u00e9 MyTorrentsView.menu.networks=Siete MyTorrentsView.menu.peersource=Zdroje klientov ConfigView.section.sharing.permitdht=Povoli\u0165 decentralizovan\u00e9 trackovanie ke\u010f je tracker nedostupn\u00fd ConfigView.section.sharing.protocol=Protokol pre zdie\u013ean\u00e9 zdroje PeersView.Messaging=Spr\u00e1vy PeersView.Messaging.info=Podporuje roz\u0161\u00edren\u00e9 API spr\u00e1v. ConfigView.label.queue.newseedsmovetop=Presun\u00fa\u0165 novodokon\u010den\u00e9 torrenty na za\u010diatok distribu\u010dn\u00e9ho zoznamu ConfigView.label.seeding.firstPriority.ignore.info=Pou\u017eit\u00edm t\u00fdchto pravidiel sa m\u00f4\u017ee torrent zastavi\u0165\nlen \u010do sa dokon\u010d\u00ed jeho s\u0165ahovanie. ConfigView.label.seeding.firstPriority.ignore=Ignorova\u0165 pravidl\u00e1 Top Priority pre: ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrenty s pomerom Zdroje:Klienti v\u00e4\u010d\u0161\u00edm ako ConfigView.label.seeding.firstPriority.ignore0Peer=Torrenty s 0 klientami ConfigView.section.tracker.sendjavaversionandos=Posla\u0165 verziu Javy a meno OS MagnetPlugin.contextmenu.exporturi=Kop\u00edrova\u0165 URI Magnetu do schr\u00e1nky ConfigView.section.plugins.dht=Distribuovan\u00e1 Datab\u00e1za dht.info=Tento plugin podporuje decentralizovan\u00e9 sledovanie torrentov (okrem in\u00fdch vec\u00ed) - jeho vypnut\u00edm sa zhor\u0161ia schopnosti downloadu dht.enabled=Povoli\u0165 distribuovan\u00fa datab\u00e1zu dht.portdefault=Pou\u017ei\u0165 predvolen\u00fd port dht.port=UDP port pre datab\u00e1zu dht.execute.command=Diagnostick\u00fd pr\u00edkaz dht.execute.info=Stla\u010d pre vykonanie pr\u00edkazu dht.execute=Spusti\u0165 dht.logging=Povoli\u0165 sledovanie aktivity ConfigView.section.plugins.dhttracker=Distribuovan\u00fd Tracker dhttracker.tracknormalwhenoffline=Trackova\u0165 iba norm\u00e1lne torrenty, ak je ich Tracker nedostupn\u00fd ConfigView.section.file.nativedelete._mac=Pou\u017ei\u0165 K\u00f4\u0161 pri zmaz\u00e1van\u00ed s\u00faborov ConfigView.section.file.nativedelete._windows=Pres\u00fava\u0165 zmazan\u00e9 s\u00fabory do Ko\u0161a ConfigView.section.logging.generatediagnostics=Generova\u0165 ConfigView.section.logging.generatediagnostics.info=Generova\u0165 diagnostick\u00e9 info a skop\u00edrova\u0165 ho do schr\u00e1nky a log s\u00faboru, ak je nastaven\u00e9 ConfigView.section.sharing.privatetorrent=S\u00fakromn\u00fd torrent - akceptuje iba klientov z Trackera MainWindow.menu.tools.nattest=Test &NAT / Firewallu Button.apply=Pou\u017ei\u0165 Button.close=Zavrie\u0165 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=Pozn\u00e1mky k verzii dht.reseed.label=Za norm\u00e1lnych okolnost\u00ed nie je nutn\u00e9 op\u00e4tovne rozdistribuova\u0165 datab\u00e1zu. Av\u0161ak ak je po\u010det kontaktov mal\u00fd, m\u00f4\u017ee to pom\u00f4c\u0165 jej re-integr\u00e1cii.\nNevyplnen\u00e9 pol\u00ed\u010dko znamen\u00e1 zavedenie datab\u00e1zy z pripojen\u00fdch klientov, vyplnen\u00edm IP adresy zavediete datab\u00e1zu zo zn\u00e1meho klienta. dht.reseed.group=Op\u00e4tovn\u00e1 distib\u00facia dht.reseed.ip=IP adresa dht.reseed.port=Port dht.reseed=Distribuova\u0165 dht.reseed.info=Znovu rozdistribuova\u0165 datab\u00e1zu dht.diagnostics.group=Diagnostika DHTView.title.full=Distribuovan\u00e1 datab\u00e1za DHTView.title.fullcvs=Distribuovan\u00e1 datab\u00e1za CVS DHTView.general.title=V\u0161eobecn\u00e9 DHTView.general.uptime=\u010cas behu: DHTView.general.users=Pou\u017e\u00edvatelia: DHTView.general.nodes=Uzly: DHTView.general.leaves=Listy: DHTView.general.contacts=Kontakty: DHTView.general.replacements=Nahradenia: DHTView.general.live=\u017dije: DHTView.general.unknown=Nezn\u00e1me: DHTView.general.dying=Umiera: DHTView.transport.title=Detaily prenosu DHTView.transport.packets=Pakety DHTView.transport.bytes=Bajty DHTView.transport.received=Prijat\u00fdch DHTView.transport.sent=Odoslan\u00fdch DHTView.transport.in=Dovn\u00fatra : DHTView.transport.out=Von : DHTView.operations.title=Detaily oper\u00e1ci\u00ed DHTView.operations.sent=Odoslan\u00fdch DHTView.operations.ok=Ok DHTView.operations.failed=Ne\u00faspe\u0161n\u00fdch DHTView.operations.received=Prijat\u00fdch DHTView.operations.ping=Ping DHTView.operations.findNode=H\u013eadaj uzol DHTView.operations.findValue=H\u013eadaj hodnotu DHTView.operations.store=Ulo\u017e DHTView.activity.title=Aktivita DHTView.activity.status=Stav DHTView.activity.status.true=Vo fronte DHTView.activity.status.false=Be\u017e\u00ed DHTView.activity.type=Typ DHTView.activity.type.1=Intern\u00fd GET DHTView.activity.type.2=Extern\u00fd GET DHTView.activity.type.3=Intern\u00fd PUT DHTView.activity.type.4=Extern\u00fd PUT DHTView.activity.target=Cie\u013e DHTView.activity.details=Detaily DHTView.db.title=Datab\u00e1za DHTView.db.keys=K\u013e\u00fa\u010de DHTView.db.values=Hodnoty DHTView.db.local=Lok\u00e1lne DHTView.db.direct=Priame DHTView.db.indirect=Nepriame MainWindow.dht.status.tooltip=Ke\u010f je akt\u00edvna Distribuovan\u00e1 datab\u00e1za, tak tu je zobrazen\u00fd pribli\u017en\u00fd po\u010det pou\u017e\u00edvate\u013eov, ktor\u00ed s\u00fa pr\u00e1ve online MainWindow.dht.status.disabled=Vypnut\u00e9 MainWindow.dht.status.failed=Chyba MainWindow.dht.status.initializing=Inicializ\u00e1cia MainWindow.dht.status.users=%1 Pou\u017e\u00edvate\u013eov MainWindow.dht.status.unreachabletooltip=Zd\u00e1 sa, \u017ee je nejak\u00fd probl\u00e9m s mapovan\u00edm portov Distribuovanej datab\u00e1zy MyTorrentsView.menu.setUpSpeed=R\u00fdchlos\u0165 uploadu MyTorrentsView.menu.setDownSpeed=R\u00fdchlos\u0165 downloadu ConfigView.section.tracker.client.showwarnings=Zobrazova\u0165 varovn\u00e9 hl\u00e1senia od Trackerov dht.advanced=Povoli\u0165 roz\u0161\u00edren\u00e9 nastavenia dht.advanced.group=Roz\u0161\u00edren\u00e9 nastavenia dht.advanced.label=Tieto hodnoty me\u0148te iba ak naozaj viete \u010do rob\u00edte dht.override.ip=Nastavi\u0165 extern\u00fa IP adresu ConfigView.section.logging.loggerenable=Povoli\u0165 logovanie ConfigView.section.ipfilter.blockbanning=Zak\u00e1za\u0165 blok 256 adries, ak bolo v danom bloku zak\u00e1zan\u00fdch aspo\u0148 MyTrackerView.passive=Pas\u00edvny TableColumn.header.swarm_average_speed=Swarm priem. r\u00fdchlos\u0165 TableColumn.header.swarm_average_speed.info=Priemern\u00e1 r\u00fdchlos\u0165 \u00fa\u010dastn\u00edkov swarmu MyTrackerView.category=Kateg\u00f3ria MainWindow.menu.file.open.torrentfortracking=.torrent s\u00fabor (pre trackovanie) MyTrackerView.date_added=Pridan\u00fd ConfigView.section.tracker.portbackup=Z\u00e1lo\u017en\u00e9 porty (oddelen\u00e9 ';') ConfigView.label.playfilespeech=Skon\u010denie s\u00faboru ohl\u00e1si\u0165 hlasom ConfigView.label.playfilespeech.info=Hlasov\u00e9 slu\u017eby moment\u00e1lne funguj\u00fa najlep\u0161ie v angli\u010dtine ConfigView.label.playfilefinished=Zahra\u0165 zvuk po dokon\u010den\u00ed s\u00faboru ConfigView.label.backupconfigfiles=Z\u00e1lohova\u0165 konfigura\u010dn\u00e9 s\u00fabory dht.ipfilter.log=Protokolova\u0165 poru\u0161enia pravidiel IP filtra ActivityView.legend.limit=Limit ActivityView.legend.achieved=Dosiahnut\u00e1 ActivityView.legend.peeraverage=Priemern\u00e1 ActivityView.legend.swarmaverage=Priemer swarmu MyTorrentsView.menu.movemenu=Presun\u00fa\u0165 s\u00fabory MyTorrentsView.menu.movedata=Presun\u00fa\u0165 d\u00e1tov\u00e9 s\u00fabory... MyTorrentsView.menu.movetorrent=Presun\u00fa\u0165 torrent s\u00fabor... MyTorrentsView.menu.movedata.dialog=Zmeni\u0165 umiestnenie DHTView.operations.data=D\u00e1ta DHTView.general.reachable=Dosiahnute\u013en\u00e9: ConfigView.label.queue.maxactivetorrentswhenseeding=Max. po\u010det ak sa iba distribuuje [0:neobmedzen\u00fd] ConfigView.section.ipfilter.persistblocking=Uchova\u0165 detaily blokovan\u00fdch IP medzi re\u0161tartami FilesView.menu.rename=Premenova\u0165 alebo zmeni\u0165 cie\u013e FilesView.rename.choose.path=Vybra\u0165 nov\u00fd alebo existuj\u00faci s\u00fabor FilesView.rename.confirm.delete.title=Potvrdi\u0165 odobratie FilesView.rename.confirm.delete.text=Potvrdi\u0165 odobratie origin\u00e1lneho s\u00faboru %1 ConfigView.section.mode=M\u00f3d ConfigView.section.mode.title=\u00darove\u0148 pou\u017e\u00edvate\u013ea ConfigView.section.mode.beginner=Za\u010diato\u010dn\u00edk ConfigView.section.mode.intermediate=Pokro\u010dil\u00fd ConfigView.section.mode.advanced=Expert ConfigView.section.mode.beginner.text=V\u0161etko \u010do potrebuje\u0161 k s\u0165ahovaniu torrentov.\nPou\u017ei tento m\u00f3d, ak chce\u0161 iba spravova\u0165 svoje torrenty.\nPros\u00edm nav\u0161t\u00edv http://www.azureuswiki.com/index.php/This_funny_word, ak nie si kamar\u00e1t so slovn\u00edkom BitTorrentu. ConfigView.section.mode.intermediate.text=Poskytne pr\u00edstup k funkci\u00e1m trackera.\nPou\u017ei tento m\u00f3d, ak chce\u0161 vytvori\u0165 vlastn\u00fd tracker a hos\u0165ova\u0165/publikova\u0165 s\u00fabory.\nPros\u00edm nav\u0161t\u00edv http://www.azureuswiki.com/index.php/HostingFiles a http://www.azureuswiki.com/index.php/PublishingFiles ConfigView.section.mode.advanced.text=Umo\u017en\u00ed pr\u00edstup k sie\u0165ov\u00fdm nastaveniam.\nPou\u017ei tento m\u00f3d, ak vie\u0161 \u010do s\u00fa MTU, neblokuj\u00face I/O, ...\nPros\u00edm nav\u0161t\u00edv http://www.azureuswiki.com/index.php/Main_Page.\n\u010eakujem. Files.column.storagetype=Ulo\u017eenie FileItem.storage.linear=Line\u00e1rne FileItem.storage.compact=Kompaktn\u00e9 MessageBoxWindow.rememberdecision=Pam\u00e4ta\u0165 si rozhodnutie ConfigView.section.interface.cleardecisions=Vymaza\u0165 zapam\u00e4tan\u00e9 rozhodnutia dial\u00f3gov ConfigView.section.interface.cleardecisionsbutton=Vy\u010disti\u0165 configureWizard.welcome.usermodes=Nastavenie \u00darovne pou\u017e\u00edvate\u013ea ovplyvn\u00ed mno\u017estvo volieb zobrazen\u00fdch v menu N\u00e1stroje -> Nastavenie. Je v tvojom najlep\u0161om z\u00e1ujme spr\u00e1vne nastavi\u0165. diagnostics.log_found=Vuze nebol spr\u00e1vne ukon\u010den\u00fd. Pros\u00edm pozrite sa do diagnostick\u00fdch s\u00faborov v %1 a zv\u00e1\u017ete ich poslanie t\u00edmu Vuze ak to bolo zapr\u00ed\u010dinen\u00e9 chybou aplik\u00e1cie. ConfigView.section.logging.log0type=Inform\u00e1cie # %1 = "in kbps" or ""; %2 = "upload" or "download" OpenTorrentWindow.torrentLocation=Torrent s\u00fabory: Button.moveUp=Posun\u00fa\u0165 nahor Button.moveDown=Posun\u00fa\u0165 nadol # > 2402 # Used for peers which we can't determine. PeerSocket.unknown=Nezn\u00e1my ConfigView.label.announceport=Nastavi\u0165 port pre Tracker iconBar.queue.tooltip=Fronta MainWindow.menu.help.faq=&Wiki FAQ MainWindow.menu.help.donate=&Podpori\u0165 dot\u00e1ciou !!! azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_hu_HU.properties0000644000175000017500000062456111301156004026115 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php MainWindow.menu.file.open.torrent=Torrent f\u00e1jl... Main.parameter.usage=Haszn\u00e1lata : java org.gudy.azureus2.cl.Main [param\u00e9terek] "f\u00e1jl.torrent" "ment\u00e9si \u00fatvonal" Main.parameter.maxUploads=Maxim\u00e1lis egyidej\u0171 felt\u00f6lt\u00e9s Main.parameter.maxSpeed=Maxim\u00e1lis felt\u00f6lt\u00e9si sebess\u00e9g (byte/s) MainWindow.menu.file=&F\u00e1jl MainWindow.menu.file.open=Meg&nyit\u00e1s MainWindow.menu.file.create=&\u00daj Torrent... MainWindow.menu.file.create.fromfile=&F\u00e1jlb\u00f3l MainWindow.menu.file.create.fromdir=&Mapp\u00e1b\u00f3l MainWindow.menu.file.export=Export\u00e1l\u00e1s XML Torrent f\u00e1jlba... MainWindow.menu.file.import=XML Torrent import\u00e1l\u00e1sa... MainWindow.menu.file.closetab=F\u00fcl bez\u00e1r\u00e1sa MainWindow.menu.file.closewindow=Ablak bez\u00e1r\u00e1sa MainWindow.menu.file.exit=&Kil\u00e9p\u00e9s MainWindow.dialog.choose.file=V\u00e1lassza ki a torrent f\u00e1jlt MainWindow.menu.file.folder=&Mappa... MainWindow.dialog.choose.folder=Adja meg a torrent f\u00e1jl(oka)t tartalmaz\u00f3 mapp\u00e1t MainWindow.menu.view=&N\u00e9zet MainWindow.menu.view.show=Mutat MainWindow.menu.view.mytorrents=Torrentjei&m MainWindow.menu.view.open_global_transfer_bar=Folyamatjelz\u0151 MainWindow.menu.view.configuration=&Be\u00e1ll\u00edt\u00e1sok... MainWindow.menu.view.console=K&onzol MainWindow.menu.view.irc=IR&C MainWindow.menu.view.allpeers=Minden Peer MainWindow.menu.closealldetails=Minden &r\u00e9szlet bez\u00e1r\u00e1sa MainWindow.menu.closealldownloadbars=Minden &let\u00f6lt\u00e9si cs\u00edk bez\u00e1r\u00e1sa MainWindow.menu.language=Nye&lv ConfigView.section.language=Nyelv MainWindow.menu.window=Ablak MainWindow.menu.window.minimize=Kis &m\u00e9ret MainWindow.menu.window.zoom=&Nagy\u00edt MainWindow.menu.window.alltofront=Mindent el\u0151t\u00e9rben MainWindow.menu.help=&S\u00fag\u00f3 MainWindow.menu.help.about=Vuze N\u00e9vjegye MainWindow.about.title=N\u00e9vjegy MainWindow.about.section.developers=Fejleszt\u0151k MainWindow.about.section.translators=Ford\u00edt\u00f3k MainWindow.about.section.system=Rendszer MainWindow.about.internet.homepage=Vuze Honlapja MainWindow.about.internet.sourceforge=Sourceforge Project honlapja MainWindow.about.internet.sourceforgedownloads=Sourceforge Let\u00f6lt\u00e9sek MainWindow.about.internet.bugreports=Hibajelent\u00e9s MainWindow.about.internet.forumdiscussion=F\u00f3rumok MainWindow.about.internet.wiki=Vuze Wiki GYIK MainWindow.dialog.choose.savepath=Adja meg a ment\u00e9s hely\u00e9t MainWindow.dialog.choose.savepath_forallfiles=Adja meg a ment\u00e9s hely\u00e9t az \u00d6SSZES f\u00e1jlhoz MainWindow.status.latestversion=Leg\u00fajabb MainWindow.status.latestversion.clickupdate=Friss\u00edt\u00e9shez kattintson ide MainWindow.status.unknown=ismeretlen MainWindow.status.checking=keres\u00e9s MyTorrentsView.mytorrents=Torrentjeim TableColumn.header.name=N\u00e9v TableColumn.header.size=M\u00e9ret TableColumn.header.done=K\u00e9sz TableColumn.header.done.info=Aktu\u00e1lis folyamat let\u00f6lt\u00f6tt (%) TableColumn.header.status=\u00c1llapot TableColumn.header.status.info=Mit csin\u00e1l a torrent TableColumn.header.seeds=Seed TableColumn.header.seeds.info=# kapcsol\u00f3dott seed (# \u00f6sszes seed) TableColumn.header.peers=Peer TableColumn.header.peers.info=# kapcsol\u00f3dott peerek (# \u00f6sszes peer) TableColumn.header.completed=K\u00e9sz TableColumn.header.completed.info=# peer a tracker szerint let\u00f6lt\u00f6tte a torrentet TableColumn.header.downspeed=Let\u00f6lt\u00e9si Sebess\u00e9g TableColumn.header.upspeed=Sebess\u00e9g Fel TableColumn.header.tracker=Tracker \u00c1llapota TableColumn.header.tracker.info=A szerver jelenlegi \u00e1llapota TableColumn.header.trackernextaccess=K\u00f6vetkez\u0151 Tracker Lek\u00e9rdez\u00e9s TableColumn.header.trackernextaccess.info=Amikor a k\u00f6vetkez\u0151 k\u00e9r\u00e9s indul a szerverhez TableColumn.header.priority=Priorit\u00e1s TableColumn.header.priority.info=Meghat\u00e1rozza, hogy mekkora felt\u00f6lt\u00e9si s\u00e1vot kap a torrent TableColumn.header.seeds.fullcopycalc=%2 teljes m\u00e1solat el\u00e9rhet\u0151 %1 peern\u00e9l MyTorrentsView.menu.showdetails=R\u00e9szletek Mutat\u00e1&sa MyTorrentsView.menu.showdownloadbar=Let\u00f6lt\u0151 Cs\u00edk Mutat\u00e1sa MyTorrentsView.menu.open=F\u00e1jl Meg&nyit\u00e1sa MyTorrentsView.menu.setpriority=&Priorit\u00e1s MyTorrentsView.menu.setpriority.high=&Magas MyTorrentsView.menu.setpriority.low=&Alacsony MyTorrentsView.menu.start=&Ind\u00edt MyTorrentsView.menu.stop=Meg\u00e1ll MyTorrentsView.menu.remove=&Elt\u00e1vol\u00edt MyTorrentsView.menu.changeTracker=Tracker URL hozz\u00e1&ad\u00e1sa TrayWindow.menu.exit=&Kil\u00e9p\u00e9s TrayWindow.menu.show=Vuze mutat\u00e1s&a SystemTray.menu.exit=&Kil\u00e9p\u00e9s SystemTray.menu.closealldownloadbars=\u00d6sszes let\u00f6lt\u00e9si cs\u00edk bez\u00e1r\u00e1s&a SystemTray.menu.open_global_transfer_bar=Folyamat \u00e1llapot\u00e1nak mutat\u00e1sa SystemTray.menu.show=Vuze mutat\u00e1&sa PeersView.ip.info=\u00dcgyf\u00e9l IP c\u00edme PeersView.port.info=A Port m\u00e1r haszn\u00e1latban van PeersView.T=I PeersView.T.info=L (helyi): a kapcsolatot mi kezdem\u00e9nyezt\u00fck, R (t\u00e1voli): a kapcsolatot az \u00fcgyf\u00e9l kezdem\u00e9nyezte. PeersView.T.L.tooltip=A kapcsolatot mi kezdem\u00e9nyezt\u00fck PeersView.T.R.tooltip=A kapcsolatot az \u00fcgyf\u00e9l kezdem\u00e9nyezte. PeersView.I1=I (\u00dcgyf\u00e9l hasznos lehet) PeersView.I1.info=\u00c9rdekel, mi hasznosat tartogat az \u00fcgyf\u00e9l? PeersView.C1=C (\u00dcgyf\u00e9l elt\u00f6m\u0151d\u00f6tt) PeersView.C1.info=Amikor az \u00fcgyf\u00e9l abbahagyja a let\u00f6lt\u00e9st t\u0151l\u00fcnk PeersView.pieces=Szeletek PeersView.downloadspeed=Let\u00f6lt\u00e9s Sebess\u00e9ge PeersView.download=Le PeersView.I2=I (\u00dcgyf\u00e9l hasznosnak tart) PeersView.I2.info=Vajon mink van, ami az \u00fcgyfelet \u00e9rdekelheti? PeersView.C2=C (Elt\u00f6m\u0151dt\u00fcnk az \u00fcgyf\u00e9l fel\u00e9) PeersView.C2.info=Amikor adott \u00fcgyf\u00e9l fel\u00e9 besz\u00fcntetj\u00fck az ad\u00e1st PeersView.uploadspeed=Felt\u00f6lt\u00e9s Sebess\u00e9ge PeersView.uploadspeed.info=Felt\u00f6lt\u00e9s sebess\u00e9ge az \u00fcgyf\u00e9l fel\u00e9 PeersView.upload=Fel PeersView.upload.info=\u00c1tlagos felt\u00f6lt\u00e9si sebess\u00e9g az \u00fcgyf\u00e9l fel\u00e9 PeersView.statup=Felt\u00f6lt\u00e9si stat PeersView.statup.info=Az \u00fcgyf\u00e9l \u00f6sszes sz\u00e1m\u00edtott felt\u00f6lt\u00e9se PeersView.S.info=Elutas\u00edt\u00e1s: Egy \u00fcgyfelet (aki esetleg nem teljes\u00edt az elv\u00e1rt m\u00e9rt\u00e9kben) k\u00e9zzel vagy automatikusan el lehet utas\u00edtani. PeersView.downloadspeedoverall=Let\u00f6lt\u00e9s \u00c1tlagos Sebess\u00e9ge PeersView.optunchoke=Elt\u00f6m\u0151d\u00e9s enyh\u00edt\u00e9se PeersView.client=Kliens PeersView.client.info=A haszn\u00e1lt BT kliensprogram neve PeersView.menu.snubbed=Eluta&s\u00edt PeersView.title.short=\u00dcgyfelek PeersView.title.full=\u00dcgyfelek AllPeersView.title.full=Minden Kliens ConfigView.section.files=F\u00e1jlok ConfigView.label.usefastresume=Gyors folytat\u00e1s haszn\u00e1lata ConfigView.label.incrementalfile=Folyamatos f\u00e1jlfelt\u00f6lt\u00e9s [Aj\u00e1nlott Linuxon FAT32 eset\u00e9n] ConfigView.label.defaultsavepath=Alap\u00e9rtelmezett ment\u00e9si k\u00f6nyvt\u00e1r ConfigView.button.browse=&Tall\u00f3z\u00e1s... ConfigView.dialog.choosedefaultsavepath=K\u00e9rem adja meg az alap\u00e9rtelmezett ment\u00e9si k\u00f6nyvt\u00e1rat ConfigView.section.server=Kapcsolatok ConfigView.section.global=\u00c1ltal\u00e1nos ConfigView.label.disconnetseed=M\u00e1s k\u00e9szforr\u00e1sok eldob\u00e1sa K\u00e9szforr\u00e1s m\u00f3dban ConfigView.label.switchpriority=V\u00e1ltson alacsony priorit\u00e1sra k\u00e9szforr\u00e1skor ConfigView.label.maxdownloads=Max egyidej\u0171 let\u00f6lt\u00e9s [0: korl\u00e1tlan]\n - Nem lehet nagyobb mint a max akt\u00edv torrentek ConfigView.label.maxdownloads.tooltip=Ennyi let\u00f6lt\u00e9s egyidej\u0171 fut\u00e1s\u00e1t enged\u00e9lyezi. Egy kiv\u00e9tel van.\nSz\u00fcks\u00e9g eset\u00e9n egy befejezett, Magas Priorit\u00e1s\u00fa torrent \u00e1tveheti egy m\u00e1sik akt\u00edv torrent sz\u00e1l\u00e1s. ConfigView.label.maxactivetorrents=Max egyidej\u0171 akt\u00edv torrent [0: korl\u00e1tlan]\n - Nem indul \u00faj le/felt\u00f6lt\u00e9s ha m\u00e1r ennyi torrent folyamatban van. ConfigView.label.priorityExtensions=Els\u0151bbs\u00e9get \u00e9lvez\u0151 f\u00e1jlok let\u00f6lt\u00e9skor\n - pl: .txt;.nfo;.jpg ConfigView.section.transfer=\u00c1tvitel ConfigView.label.maxuploads=Maxim\u00e1lis felt\u00f6lt\u00e9si sz\u00e1l torrentenk\u00e9nt ConfigView.label.maxuploadspeed=Max. \u00f6sszes felt\u00f6lt\u00e9si sebess\u00e9g KB/mp-ben [0: korl\u00e1tlan] ConfigView.label.saveresumeinterval=Folytat\u00e1st seg\u00edt\u0151 adatok friss\u00edt\u00e9se ConfigView.unlimited=Korl\u00e1tlan ConfigView.section.display=Megjelen\u00edt\u00e9s ConfigView.label.opendetails=R\u00e9szletek f\u00fcl automatikus megnyit\u00e1sa ConfigView.label.openbar=Let\u00f6lt\u00e9si cs\u00edk automatikus megnyit\u00e1sa ConfigView.label.use_old_speed_menus=R\u00e9gi st\u00edlus\u00fa sebess\u00e9gmen\u00fc mutat\u00e1sa [\u00fajraind\u00edt\u00e1s sz\u00fcks\u00e9ges] ConfigView.label.closetotray=Bez\u00e1r\u00e1skor kicsiny\u00edt\u00e9s a T\u00e1lc\u00e1ra ConfigView.label.minimizetotray=Kicsin\u00edt\u00e9s a T\u00e1lc\u00e1ra ConfigView.section.general=\u00c1ltal\u00e1nos ConfigView.section.start=Ind\u00edt\u00e1s ConfigView.label.showsplash=\u00dcdv\u00f6zl\u0151k\u00e9perny\u0151 mutat\u00e1sa ind\u00edt\u00e1skor ConfigView.label.autoupdate=Friss\u00edt\u00e9s p\u00e1rbesz\u00e9dablak megnyit\u00e1sa \u00faj verzi\u00f3 \u00e9szlel\u00e9sekor ConfigView.label.openconsole=Konzol megnyit\u00e1sa ind\u00edt\u00e1skor ConfigView.label.openconfig=Be\u00e1ll\u00edt\u00e1sok megnyit\u00e1sa ind\u00edt\u00e1skor ConfigView.label.startminimized=Kis m\u00e9retben indul ConfigView.label.ircwiki=Tov\u00e1bbi inform\u00e1ci\u00f3k: http://wiki.vuze.com/index.php/Rules_for_IRC ConfigView.label.ircserver=Szerver ConfigView.label.ircchannel=Csatorna ConfigView.label.irclogin=Becen\u00e9v ConfigView.group.irctitle=IRC Be\u00e1ll\u00edt\u00e1sai ConfigView.boolean.ircsendinfo=Enged\u00e9lyezem, hogy a csatorn\u00e1k oper\u00e1torai n\u00e9vtelen inform\u00e1ci\u00f3kat\n kapjanak t\u0151lem, hogy seg\u00edthessenek, ha probl\u00e9m\u00e1m van ConfigView.boolean.irclog=Csatorna aktivit\u00e1s napl\u00f3z\u00e1sa (IRC_log.htm f\u00e1jlba) ConfigView.section.security=Biztons\u00e1g ConfigView.label.password=Vuze jelszavas v\u00e9delme\n - Minden ind\u00edt\u00e1sn\u00e1l \u00e9s teljes m\u00e9retre v\u00e1lt\u00e1sn\u00e1l meg kell adni ConfigView.label.passwordconfirm=Jelsz\u00f3 meger\u0151s\u00edt\u00e9se ConfigView.label.passwordmatch=Jelsz\u00f3 akt\u00edv : ConfigView.label.passwordmatchnone=Nem ConfigView.label.passwordmatchno=Nem / Jelsz\u00f3 nem egyezik ConfigView.label.passwordmatchyes=Igen ConfigView.button.save=Ment\u00e9s ConfigView.title.short=Be\u00e1ll\u00edt\u00e1s ConfigView.title.full=Be\u00e1ll\u00edt\u00e1s ConfigView.title.full._mac=Tulajdons\u00e1gok ConsoleView.title.short=Konzol ConsoleView.title.full=Konzol FileItem.write=\u00edr\u00e1s FileItem.read=olvas\u00e1s FileItem.normal=norm\u00e1l FileItem.high=magas FileItem.donotdownload=Ne t\u00f6ltse le FileItem.delete=T\u00f6r\u00f6l FilesView.name=N\u00e9v FilesView.name.fastRename=Gyors \u00e1tnevez\u00e9s FilesView.size=M\u00e9ret FilesView.done=K\u00e9sz FilesView.firstpiece=Els\u0151 szelet # FilesView.numberofpieces=# szelet FilesView.pieces=Szeletek FilesView.mode=M\u00f3d FilesView.priority=Priorit\u00e1s FilesView.menu.open=&Megnyit FilesView.menu.setpriority=Rang&sor Be\u00e1ll\u00edt\u00e1sa FilesView.menu.setpriority.high=&Magas FilesView.menu.setpriority.normal=&Norm\u00e1l FilesView.menu.setpriority.skipped=&Ne t\u00f6ltse le FilesView.title.short=F\u00e1jlok FilesView.title.full=F\u00e1jlok GeneralView.section.downloaded=Let\u00f6ltve GeneralView.label.status.file=F\u00e1jl \u00e1llapota GeneralView.label.status.pieces=Szelet \u00e1llapota GeneralView.section.availability=El\u00e9rhet\u0151s\u00e9g GeneralView.label.status.pieces_available=Szelet \u00e1llapota GeneralView.section.transfer=\u00c1tvitel GeneralView.section.info=Inform\u00e1ci\u00f3 GeneralView.title.short=\u00c1ltal\u00e1nos GeneralView.title.full=\u00c1ltal\u00e1nos GeneralView.label.timeelapsed=Eltelt id\u0151 : GeneralView.label.remaining=H\u00e1travan: GeneralView.label.downloaded=Let\u00f6ltve : GeneralView.label.downloadspeed=Let\u00f6lt\u00e9s sebess\u00e9ge: GeneralView.label.maxuploads=Felt\u00f6lt\u00e9si sz\u00e1lak: GeneralView.label.maxuploads.tooltip=Adott id\u0151ben dugul\u00e1smentes\u00edthet\u0151 \u00dcgyfelek maxim\u00e1lis sz\u00e1ma. GeneralView.label.uploaded=Felt\u00f6ltve : GeneralView.label.uploadspeed=Felt\u00f6lt\u00e9s sebess\u00e9ge : GeneralView.label.seeds=K\u00e9szforr\u00e1s : GeneralView.label.peers=\u00dcgyfelek : GeneralView.label.completed=Befejezve : GeneralView.label.totalspeed=Boly sebess\u00e9ge : GeneralView.label.totalspeed.tooltip=Az \u00f6sszes hozz\u00e1nk kapcsol\u00f3d\u00f3 \u00fcgyf\u00e9l sebess\u00e9ge (\u00e1tlaguk). GeneralView.label.averagespeed=\u00e1tlag GeneralView.label.filename=N\u00e9v : GeneralView.label.totalsize=Teljes m\u00e9ret : GeneralView.label.savein=Ment\u00e9s helye: GeneralView.label.numberofpieces=# szeletek : GeneralView.label.size=M\u00e9ret : GeneralView.label.tracker=Tracker \u00c1llapota: GeneralView.label.updatein=A friss\u00edt\u00e9sig : GeneralView.label.trackerurlupdate=Tracker friss\u00edt\u00e9se GeneralView.label.comment=Megjegyz\u00e9s : GeneralView.label.user_comment=Felhaszn\u00e1l\u00f3 Kommentje: GeneralView.label.status=\u00c1llapot : ManagerItem.waiting=V\u00e1r... ManagerItem.allocating=Helyfoglal\u00e1s ManagerItem.checking=Ellen\u0151rz\u00e9s ManagerItem.ready=V\u00e1rakoz\u00e1s a t\u00f6bbi torrentre ManagerItem.downloading=Let\u00f6lt\u00e9s ManagerItem.seeding=K\u00e9szforr\u00e1s ManagerItem.stopped=Meg\u00e1llt ManagerItem.error=Hiba ManagerItem.high=magas ManagerItem.low=alacsony MinimizedWindow.name=N\u00e9v: MinimizedWindow.all_transfers=Vuze \u00c1tvitel PiecesView.size=M\u00e9ret PiecesView.numberofblocks=# t\u00f6mb PiecesView.blocks=T\u00f6mb PiecesView.completed=K\u00e9sz PiecesView.availability=El\u00e9rhet\u0151s\u00e9g PiecesView.reservedby=Fenntartva PiecesView.writers=T\u00f6mb\u00f6t birtokl\u00f3k PiecesView.title.short=Szeletek PiecesView.title.full=Szeletek SystemTray.tooltip.seeding=%1 k\u00e9szforr\u00e1s, SystemTray.tooltip.downloading=%1 let\u00f6lt\u00e9s, DownloadManager.error.filenotfound=F\u00e1jl nem l\u00e9tezik DownloadManager.error.fileempty=A Torrent f\u00e1jl \u00fcres DownloadManager.error.filetoobig=Torrent f\u00e1jl t\u00fal nagy DownloadManager.error.filewithouttorrentinfo=A f\u00e1jl nem tartalmaz Torrent adatot DownloadManager.error.unsupportedencoding=Nem t\u00e1mogatott k\u00f3dol\u00e1s DownloadManager.error.ioerror=I/O Hiba DownloadManager.error.sha1=Nincs ilyen algoritmus (SHA1) Hiba PeerManager.status.offline=Nincs Kapcsolat PeerManager.status.checking=Ellen\u0151rz\u00e9s PeerManager.status.finished=Befejezve PeerManager.status.finishedin=M\u0171velet id\u0151tartama MainWindow.upgrade.assistant=Friss\u00edt\u00e9s Seg\u00e9d MainWindow.upgrade.newerversion=Let\u00f6lthet\u0151 az Vuze egy \u00fajabb v\u00e1ltozata MainWindow.upgrade.explanation=A Seg\u00e9d most let\u00f6lti a leg\u00fajabb Vuze v\u00e1ltozatot \u00e9s \u00fajraind\u00edtja Azureust. MainWindow.upgrade.explanation.manual=A friss\u00edt\u00e9st \u00f6n\u00e1ll\u00f3an is elv\u00e9gezheti, ha kil\u00e9p Azureusb\u00f3l, let\u00f6lti a leg\u00fajabb v\u00e1ltozatot, telep\u00edti, majd \u00fajra elind\u00edtja. MainWindow.upgrade.step1=1. l\u00e9p\u00e9s: T\u00f6ltse le az \u00faj v\u00e1ltozatot MainWindow.upgrade.step2=2. l\u00e9p\u00e9s: Z\u00e1rd be az Azureust majd ind\u00edtsd el az \u00fajat MainWindow.upgrade.hint1=Tipp:\tHa a Befejez-re kattint, a t\u00f6bbi m\u00e1r megy mag\u00e1t\u00f3l. MainWindow.upgrade.hint2=Tipp:\tHa k\u00e9s\u0151bb szeretne csak kil\u00e9pni Azureus-b\u00f3l, kattintson a M\u00e9gsem gombra \u00e9s\n\tkil\u00e9p\u00e9s ut\u00e1n majd nevezd \u00e1t az Azureus2-new.jar-t Azureus2.jar-ra MainWindow.upgrade.error.downloading.hint=Hiba:\tNem lehet let\u00f6lteni az \u00fajabb v\u00e1ltozatot. K\u00e9rem, t\u00f6ltse le k\u00fcl\u00f6n. MainWindow.upgrade.section.info=\u00daj Verzi\u00f3t Tal\u00e1ltam MainWindow.upgrade.section.manual=K\u00e9zi Friss\u00edt\u00e9s MainWindow.upgrade.section.automatic=Automatikus Friss\u00edt\u00e9s MainWindow.upgrade.tooltip.progressbar=Itt l\u00e1tja a let\u00f6lt\u00e9si folyamatot Button.next=K\u00f6vetkez\u0151 Button.finish=Befejez Button.cancel=M\u00e9gsem LocaleUtil.title=V\u00e1lasszon k\u00f3dol\u00e1st LocaleUtil.section.chooseencoding=V\u00e1lasszon k\u00f3dol\u00e1st a f\u00e1jlhoz LocaleUtil.label.chooseencoding=K\u00e9rem v\u00e1lassza ki a legmegfelel\u0151bb k\u00f3dol\u00e1st LocaleUtil.label.hint.doubleclick=Tipp: dupla kattint\u00e1s egy sorra kiv\u00e1lasztja a k\u00f3dol\u00e1st \u00e9s bez\u00e1rja az ablakot LocaleUtil.label.checkbox.rememberdecision=Eml\u00e9kezzen a v\u00e1laszra a t\u00f6bbi f\u00e1jln\u00e1l LocaleUtil.column.encoding=K\u00f3dol\u00e1s IrcClient.copyright=PircBot Java IRC alkalmaz\u00e1s - http://www.jibble.org/pircbot.php IrcClient.connecting=Csatlakoz\u00e1s: IrcClient.connected=Csatlakoztatva IrcClient.joining=Csatlakoz\u00e1s IrcClient.channel=Csatorna IrcClient.joined=bel\u00e9pve IrcClient.error=Hiba IrcClient.hasjoined=bel\u00e9pett IrcClient.haskicked=kir\u00fagva IrcClient.hasleft=t\u00e1vozott IrcClient.nowknown=neve mostant\u00f3l IrcClient.topicforchannel=Napi t\u00e9ma IrcClient.disconnected=Sz\u00e9tkapcsolva IrcClient.noNick=Nem adott meg becenevet. A N\u00e9zet --> Be\u00e1ll\u00edt\u00e1sok --> B\u0151v\u00edtm\u00e9nyek --> IRC men\u00fcpontban add meg. IrcView.actionnotsupported=A m\u0171velet nem t\u00e1mogatott IrcView.clientsconnected=felhaszn\u00e1l\u00f3(k) IrcView.privateto=C\u00edmzett IrcView.privatefrom=Felad\u00f3 IrcView.noticefrom=\u00c9rtes\u00edt\u00e9s : IrcView.errormsg=Hib\u00e1s szintaxis: helyes /msg \u00fczenet IrcView.help=\u00c9rv\u00e9nyes parancsok: \n . /help : megjelen\u00edti ert az \u00fczenetet\n . /nick | /name : becenevet v\u00e1ltoztat \n . /me sz\u00f6veg : cselekv\u00e9st imit\u00e1l \n . /msg becen\u00e9v \u00fczenet : szem\u00e9lyes \u00fczenetet k\u00fcld -nek\n . /r \u00fczenet : v\u00e1laszol az utols\u00f3 mag\u00e1n \u00fczenetre\n . /join #csatorna : \u00e1tv\u00e1lt egy m\u00e1sik szob\u00e1ba PasswordWindow.title=Vuze lez\u00e1rva PasswordWindow.passwordprotected=AZ Azureust jelsz\u00f3 v\u00e9di.\nHa l\u00e1tni k\u00edv\u00e1nja a kezel\u0151ablakot, k\u00e9rem adja meg a jelsz\u00f3t : TrackerChangerWindow.title=Tracker Hozz\u00e1ad\u00e1sa TrackerChangerWindow.newtracker=\u00cdrja be az \u00faj tracker c\u00edmet PeersView.discarded=Elvetve PeersView.discarded.info=Felesleges adatok, amire nincs sz\u00fcks\u00e9ges, ez\u00e9rt ezek el lettek t\u00e1vol\u00edtva discarded=elvetve MyTorrentsView.menu.move=\u00c1thelye&z MyTorrentsView.menu.moveUp=&Fel MyTorrentsView.menu.moveDown=&Le GeneralView.label.hashfails=Hib\u00e1s hash : GeneralView.label.shareRatio=Megoszt\u00e1si ar\u00e1ny : ConfigView.section.downloadManagement=Let\u00f6lt\u00e9skezel\u0151 ConfigView.label.startRatioPeers=K\u00e9szforr\u00e1s ind\u00edt\u00e1sa, ha kevesebb, mint 1 megoszt\u00e1s jut minden ConfigView.text.neverStop=Sosem \u00e1ll le ConfigView.text.neverStart=Sosem indul ConfigView.text.peers=\u00dcgyfelek ConfigView.label.checkOncompletion=Let\u00f6lt\u00e9s \u00fajraellen\u00f6rz\u00e9se, ha a let\u00f6lt\u00e9s k\u00e9sz wizard.title=Torrent l\u00e9trehoz\u00e1sa wizard.previous=< Vissza wizard.next=K\u00f6vetkez\u0151 > wizard.finish=Befejez wizard.mode=Tracker / M\u00f3d wizard.invalidurl=Az URL hib\u00e1s wizard.singlefile=Egyetlen f\u00e1jl wizard.singlefile.help=Torrent l\u00e9trehoz\u00e1sa egyetlen f\u00e1jlb\u00f3l wizard.directory=Mappa wizard.directory.help=Torrent l\u00e9trehoz\u00e1sa mapp\u00e1b\u00f3l wizard.choosefile=V\u00e1lassza ki a f\u00e1jlt wizard.file=F\u00e1jl : wizard.browse=Tall\u00f3z... wizard.choosedirectory=V\u00e1lasszon egy mapp\u00e1t wizard.invalidfile=\u00c9rv\u00e9nytelen f\u00e1jl! wizard.invaliddirectory=\u00c9rv\u00e9nytelen k\u00f6nyvt\u00e1r! wizard.torrentFile=Torrent f\u00e1jl wizard.choosetorrent=K\u00e9rem adja meg a l\u00e9trehozni k\u00edv\u00e1nt torrent nev\u00e9t wizard.information=Inform\u00e1ci\u00f3 wizard.notimplemented=M\u00e9g nincs beillesztve wizard.progresstitle=Torrent F\u00e1jl L\u00e9trehoz\u00e1sa wizard.savingfile=F\u00e1jl Ment\u00e9se... wizard.filesaved=F\u00e1jl elmentve. wizard.close=Bez\u00e1r\u00e1s Torrent.create.progress.piecelength=Szeletek hossza: Torrent.create.progress.piececount=Szeletek sz\u00e1ma: Torrent.create.progress.totalfilesize=Teljes m\u00e9ret: Torrent.create.progress.totalfilecount=\u00d6sszes f\u00e1jl: Torrent.create.progress.parsingfiles=F\u00e1jl feloszt\u00e1sa Torrent.create.progress.hashing=Ellen\u0151rz\u0151 \u00f6sszegek sz\u00e1m\u00edt\u00e1sa MainWindow.upgrade.downloadingfrom=Let\u00f6lt\u00e9s innen : MainWindow.menu.view.ipFilter=&IP Sz\u0171r\u00e9s ConfigView.section.ipfilter=Ip Sz\u0171r\u0151k ConfigView.section.ipfilter.description=Le\u00edr\u00e1s ConfigView.section.ipfilter.start=Els\u0151 IP ConfigView.section.ipfilter.end=Utols\u00f3 IP ConfigView.section.ipfilter.add=Hozz\u00e1ad ConfigView.section.ipfilter.remove=Elt\u00e1vol\u00edt ConfigView.section.ipfilter.edit=Szerkeszt\u00e9s ConfigView.section.ipfilter.save=Ment\u00e9s ConfigView.section.ipfilter.editFilter=Sz\u0171r\u0151 szerkeszt\u00e9se ConfigView.section.ipfilter.enable=Enged\u00e9lyezve PeersView.menu.close=Be&z\u00e1r seedmore.title=A torrent m\u00e9g t\u00fal kev\u00e9s ideig volt k\u00e9szforr\u00e1s seedmore.shareratio=A torrent megoszt\u00e1si ar\u00e1nya seedmore.uploadmore=100% alatti k\u00e9szforr\u00e1s ar\u00e1ny nem sz\u00e9p dolog a BitTorrent h\u00e1l\u00f3zat\u00e1n.\nHagyd m\u00e9g egy kicsit futni a k\u00e9szforr\u00e1st.\nBiztos folytatni akarja? ConfigView.label.showpopuponclose=K\u00e9rjen meger\u0151s\u00edt\u00e9st, ha egy 1-n\u00e9l alacsonyabb megoszt\u00e1si ar\u00e1ny\u00fa torrentet akar le\u00e1ll\u00edtani ConfigView.label.startNumSeeds=\nInd\u00edtsa a k\u00e9szforr\u00e1st, ha a t\u00f6bbi forr\u00e1s kevesebb, mint\n - Minden m\u00e1s szab\u00e1lyt fel\u00fcl\u00edr ConfigView.label.seeds=k\u00e9szforr\u00e1s ConfigView.section.seeding=K\u00e9szforr\u00e1s MyTorrentsView.menu.removeand=Elt\u00e1vol\u00edt \u00e9s MyTorrentsView.menu.removeand.deletetorrent=Torrent F\u00e1jl T\u00f6rl\u00e9se MyTorrentsView.menu.removeand.deletedata=A&dat t\u00f6rl\u00e9se MyTorrentsView.menu.removeand.deleteboth=Mind t\u00f6rl\u00e9se deletedata.title=Figyelem deletedata.message1=Az al\u00e1bbi helyen l\u00e9v\u0151 ADATOT t\u00f6rl\u00e9se :\n MainWindow.menu.file.configure=Be\u00e1ll\u00edt\u00e1s &Var\u00e1zsl\u00f3... configureWizard.title=Be\u00e1ll\u00edt\u00e1s Var\u00e1zsl\u00f3 configureWizard.welcome.title=\u00dcdv\u00f6zli az Vuze Be\u00e1ll\u00edt\u00e1s Var\u00e1zsl\u00f3ja configureWizard.welcome.message=A var\u00e1zsl\u00f3 seg\u00edt az Vuze fontosabb be\u00e1ll\u00edt\u00e1saiban. B\u0151vebb be\u00e1ll\u00edt\u00e1sokhoz a N\u00e9zet>Be\u00e1ll\u00edt\u00e1sok men\u00fcpontban ny\u00edlik lehet\u0151s\u00e9g. configureWizard.transfer.title=\u00c1tvitel \u00e9s Kapcsolat be\u00e1ll\u00edt\u00e1sai configureWizard.transfer.hint=Tipp : A val\u00f3s sebess\u00e9gn\u00e9l kicsivel kissebb be\u00e1ll\u00edt\u00e1sa aj\u00e1nlott. configureWizard.transfer.message=V\u00e1laszd ki a kapcsolatod t\u00edpus\u00e1t. \u00dcgyelj arra, hogy nem kev\u00e9s felt\u00f6lt\u00e9si sebess\u00e9g lass\u00edtja a let\u00f6lt\u00e9st. Ugyanezt eredm\u00e9nyezi a t\u00fal sok egyidej\u0171 let\u00f6lt\u00e9s is, mivel t\u00f6bb adat sz\u00fcks\u00e9ges a kapcsolat fenntart\u00e1s\u00e1hoz. Torrentenk\u00e9nt MINIMUM 5KB/s sebess\u00e9g aj\u00e1nlott. Min\u00e9l gyorsabban t\u00f6lt fel, ann\u00e1l gyorsabban t\u00f6lthet majd le (tekintettel a teljes s\u00e1vsz\u00e9lre). configureWizard.transfer.connection=Vonalsebess\u00e9g configureWizard.transfer.connection.0=Egy\u00e9ni configureWizard.transfer.connection.1=Modem configureWizard.transfer.connection.2=ADSL/K\u00e1bel xxx/128 kbps configureWizard.transfer.connection.3=ADSL/K\u00e1bel xxx/256 kbps configureWizard.transfer.connection.4=ADSL/K\u00e1bel xxx/384 kbps configureWizard.transfer.connection.5=ADSL/K\u00e1bel xxx/512 kbps configureWizard.transfer.connection.6=ADSL/K\u00e1bel xxx/768 kbps configureWizard.transfer.connection.7=ADSL/K\u00e1bel xxx/1024 kbps configureWizard.transfer.maxUpSpeed=Max Felt\u00f6lt\u00e9si Sebess\u00e9g (KB/s) configureWizard.transfer.maxActiveTorrents=Max Akt\u00edv configureWizard.transfer.maxDownloads=Max Let\u00f6lt\u00e9s configureWizard.transfer.maxUploadsPerTorrent=Max Felt\u00f6lt\u00e9s Torrentenk\u00e9nt configureWizard.nat.title=NAT / Szerver Port configureWizard.nat.message=Ahhoz hogy az Vuze a legjobban m\u0171k\u00f6dj\u00f6n, aj\u00e1nlott a teljes el\u00e9r\u00e9s az internetr\u0151l. Itt letesztelheted \u00e9s/vagy megv\u00e1ltoztathatod a bej\u00f6v\u0151 kapcsolathoz haszn\u00e1lt portot.\n\nMegjegyz\u00e9s: Csak a TCP kapcsolatot teszteli. Az Elosztott Adatv\u00e1zishoz bej\u00f6v\u0151 UDP kapcsolat sz\u00fcks\u00e9ges, de hiba eset\u00e9n visszajelz\u00e9st fogsz kapni.\n\nMegjegyz\u00e9s: 6880 TCP port m\u00e1r le van foglalva, ez\u00e9rt ez nem haszn\u00e1lhat\u00f3! configureWizard.nat.test=Teszt configureWizard.nat.testing=Port tesztel\u00e9se configureWizard.nat.ok=OK! configureWizard.nat.ko=NAT Hiba configureWizard.nat.unable=Nem lehet tesztelni: Hib\u00e1s port, vagy sikertelen teszt.\nM\u00e1s program tal\u00e1n m\u00e1r haszn\u00e1lja ezt a portot. configureWizard.file.title=Torrentek / F\u00e1jlok configureWizard.file.message1=Vuze az itt megadott k\u00f6nyvt\u00e1rba menti majd el a megnyitott torrenteket: configureWizard.file.path=\u00datvonal configureWizard.file.browse=Tall\u00f3z\u00e1s configureWizard.file.message2=Vuze k\u00eds\u00e9r\u0151 adatok l\u00e9trehoz\u00e1s\u00e1val k\u00e9pes gyorsan folytatni megkezdett let\u00f6lt\u00e9seit. Ha akt\u00edv\u00e1lja ezt a szolg\u00e1ltat\u00e1st, az a r\u00e9szben let\u00f6lt\u00f6tt adatokra is m\u0171k\u00f6dni fog. configureWizard.file.fastResume=Gyors Folytat\u00e1s bekapcsol\u00e1sa configureWizard.file.invalidPath=\u00c9rv\u00e9nytelen k\u00f6nyvt\u00e1r configureWizard.finish.title=K\u00e9sz configureWizard.finish.message=Vuze be\u00e1ll\u00edt\u00e1sa befejez\u0151d\u00f6tt, j\u00f3 sz\u00f3rakoz\u00e1st ! wizard.close.confirmation=Meger\u0151s\u00edt\u00e9s wizard.close.message=K\u00edv\u00e1nja, hogy a Var\u00e1zsl\u00f3 az Vuze k\u00f6vetkez\u0151 ind\u00edt\u00e1s\u00e1n\u00e1l megjelenjen? exportTorrentWizard.title=Torrent export\u00e1l\u00e1sa XML-be exportTorrentWizard.torrentfile.title=Forr\u00e1s torrent kiv\u00e1laszt\u00e1sa exportTorrentWizard.torrentfile.message=V\u00e1laszd ki export\u00e1l\u00e1sra a torrent f\u00e1jlt exportTorrentWizard.torrentfile.path=\u00datvonal exportTorrentWizard.torrentfile.browse=Tall\u00f3z\u00e1s exportTorrentWizard.torrentfile.invalidPath=\u00c9rv\u00e9nytelen torrent f\u00e1jl exportTorrentWizard.exportfile.title=Export f\u00e1jl kiv\u00e1laszt\u00e1sa exportTorrentWizard.exportfile.message=Adja meg az xml export f\u00e1jl nev\u00e9t exportTorrentWizard.exportfile.path=\u00datvonal exportTorrentWizard.exportfile.browse=Tall\u00f3z\u00e1s exportTorrentWizard.exportfile.invalidPath=\u00c9rv\u00e9nytelen export f\u00e1jl exportTorrentWizard.finish.title=K\u00e9sz exportTorrentWizard.finish.message=Export\u00e1l\u00e1s siker\u00fclt exportTorrentWizard.process.inputfilebad.title=\u00c9rv\u00e9nytelen torrent f\u00e1jl exportTorrentWizard.process.inputfilebad.message=Hiba t\u00f6rt\u00e9nt az \u00e1llom\u00e1ny olvas\u00e1s\u00e1n\u00e1l: exportTorrentWizard.process.outputfileexists.title=A f\u00e1jl m\u00e1r l\u00e9tetik exportTorrentWizard.process.outputfileexists.message=A f\u00e1jl m\u00e1r l\u00e9tezik - fel\u00fcl\u00edrja? exportTorrentWizard.process.torrentfail.title=Torrent olvas\u00e1sa sikertelen exportTorrentWizard.process.exportfail.title=Export\u00e1l\u00e1s sikertelen exportTorrentWizard.process.unknownfail.title=Ismeretlen hiba importTorrentWizard.title=XML torretn import\u00e1l\u00e1sa importTorrentWizard.torrentfile.title=Torrent kiv\u00e1laszt\u00e1sa importTorrentWizard.torrentfile.message=Torretn f\u00e1jl import\u00e1l\u00e1s\u00e1nak a c\u00e9lja importTorrentWizard.torrentfile.path=\u00datvonal importTorrentWizard.torrentfile.browse=Tall\u00f3z importTorrentWizard.torrentfile.invalidPath=\u00c9rv\u00e9nytelen torrent f\u00e1jl importTorrentWizard.importfile.title=Import f\u00e1jl kiv\u00e1laszt\u00e1sa importTorrentWizard.importfile.message=V\u00e1lassza ki az import\u00e1lni k\u00edv\u00e1nt XML f\u00e1jlt importTorrentWizard.importfile.path=\u00datvonal importTorrentWizard.importfile.browse=Tall\u00f3z importTorrentWizard.importfile.invalidPath=\u00c9rv\u00e9nytelen import f\u00e1jl importTorrentWizard.finish.title=K\u00e9sz importTorrentWizard.finish.message=Import\u00e1l\u00e1s sikeres importTorrentWizard.process.inputfilebad.title=Import f\u00e1jl \u00e9rv\u00e9nytelen importTorrentWizard.process.inputfilebad.message=Hiba t\u00f6rt\u00e9nt a f\u00e1jl megnyit\u00e1sakor: importTorrentWizard.process.outputfileexists.title=L\u00e9tez\u0151 f\u00e1jl importTorrentWizard.process.outputfileexists.message=A f\u00e1jl m\u00e1r l\u00e9tezik - fel\u00fcl\u00edrja? importTorrentWizard.process.torrentfail.title=Torrent \u00edr\u00e1sa sikertelen importTorrentWizard.process.importfail.title=Import\u00e1l\u00e1s sikertelen importTorrentWizard.process.unknownfail.title=Ismeretlen hiba ConfigView.label.bindip=Helyi IP-c\u00edmhez/Interf\u00e9szhez k\u00f6t\u00e9s ConfigView.label.xfs.allocation=\u00daj f\u00e1jlok l\u00e9trehoz\u00e1sa XFS f\u00e1jlrendszer m\u00f3dszer\u00e9vel ConfigView.label.xfs.allocation.tooltip=Ellen\u0151rizd, hogy a /usr/sbin/xfs_io megfelel\u0151en telep\u00edtve van a rendszeren. A legt\u00f6bb Linux kiad\u00e1sban az "xfsprogs" csomag tartalmazza. xfs.allocation.xfs_io.not.found=XFS f\u00e1jl l\u00e9trehoz\u00e1si hiba, mert /usr/sbin/xfs_io nem tal\u00e1lhat\u00f3. Ellen\u0151rizd, hogy megfelel\u0151en telep\u00edtve van a rendszeren. Eredeti hiba : "%1". ConfigView.label.zeronewfiles=A f\u00e1jlok l\u00e9trehoz\u00e1sakor foglalja le a teljes m\u00e9retet ConfigView.label.zeronewfiles.tooltip=Cs\u00f6kkenthet\u0151 a lemez t\u00f6redezetts\u00e9ge ConfigView.section.stats=Statisztika ConfigView.section.stats.enable=Enged\u00e9lyezve ConfigView.section.stats.defaultsavepath=Statisztik\u00e1k ment\u00e9s\u00e9nek helye ConfigView.section.stats.choosedefaultsavepath=Add meg a Statisztik\u00e1k ment\u00e9s\u00e9hez a mapp\u00e1t ConfigView.section.stats.savefreq=Ment\u00e9s gyakoris\u00e1ga ConfigView.section.stats.minutes=perc ConfigView.section.stats.hours=\u00f3ra ConfigView.section.stats.seconds=m\u00e1sodperc ConfigView.section.stats.savefile=Statisztikai f\u00e1jl neve ConfigView.section.stats.graph_update_dividers=F\u00fcgg\u0151leges vonal mutat\u00e1sa minden 60 friss\u00edt\u00e9sn\u00e9l MyTorrentsView.menu.host=&Kiszolg\u00e1l (host)... ManagerItem.finishing=Befejez\u00e9s ConfigView.dialog.choosedefaulttorrentpath=V\u00e1lassza ki a torrent-\u00e1llom\u00e1nyok alap\u00e9rtelmezett hely\u00e9t ConfigView.dialog.choosemovepath=K\u00e9rem adja meg az c\u00e9lk\u00f6nyvt\u00e1rat ConfigView.label.movecompleted=K\u00e9sz f\u00e1jlok \u00e1thelyez\u00e9se (ha a let\u00f6lt\u00e9s elk\u00e9sz\u00fclt) ConfigView.label.moveremoved=K\u00e9sz f\u00e1jlok \u00e1thelyez\u00e9se (mikor t\u00f6rl\u00f6m \u0151ket) ConfigView.label.savetorrents=Torrent f\u00e1jlok ment\u00e9se MainWindow.menu.view.mytracker=&Trackerem MyTrackerView.title.full=Trackerem MyTrackerView.name=N\u00e9v MyTrackerView.status=\u00c1llapot MyTrackerView.status.started=Fut MyTrackerView.status.stopped=\u00c1ll MyTrackerView.peers=\u00dcgyfelek MyTrackerView.seeds=K\u00e9szforr\u00e1sok MyTrackerView.announces=Ig\u00e9nybejelent\u00e9sek MyTrackerView.uploaded=Felt\u00f6ltve MyTrackerView.downloaded=Let\u00f6ltve MyTrackerView.left=Maradt ConfigView.section.style=Kezel\u0151fel\u00fclet ConfigView.label.set_ui_transfer_speeds=Kiv\u00e1laszthat\u00f3 \u00e1tviteli sebess\u00e9gek fel\u00fclb\u00edr\u00e1l\u00e1sa ConfigView.label.set_ui_transfer_speeds.description=Fel\u00fclb\u00edr\u00e1lhatod az \u00e1llapotsorn\u00e1l v\u00e1laszthat\u00f3 le- \u00e9s felt\u00f6lt\u00e9si sebess\u00e9geket.\nAz \u00e9rt\u00e9keket ponttal kell elv\u00e1lasztani. ConfigView.label.set_ui_transfer_speeds.description.download=Let\u00f6lt\u00e9si sebess\u00e9g (KB/s) ConfigView.label.set_ui_transfer_speeds.description.upload=Felt\u00f6lt\u00e9si sebess\u00e9g (KB/s) ConfigView.section.style.useCustomTabs=Bez\u00e1rhat\u00f3 f\u00fclek (\u00fajraind\u00edt\u00e1s sz\u00fcks\u00e9ges) MainWindow.menu.view.plugins=&B\u0151v\u00edtm\u00e9nyek fileDownloadWindow.saveTorrentIn=Torrent ment\u00e9se fileDownloadWindow.title=Vuze - Torrent Let\u00f6lt\u0151 fileDownloadWindow.downloading=Let\u00f6lt\u00e9s innen : fileDownloadWindow.status=St\u00e1tusz : fileDownloadWindow.state_initializing=El\u0151k\u00e9sz\u00edt\u00e9s fileDownloadWindow.state_downloading=Let\u00f6lt\u00e9s fileDownloadWindow.state_error=Hiba : MainWindow.menu.file.open.url=&Hely... openUrl.title=Hely Megnyit\u00e1sa MyTorrentsView.menu.host.error.title=Torrent Kiszolg\u00e1l\u00e1sa Sikertelen MyTorrentsView.menu.host.error.message=A k\u00f6vetkez\u0151 hiba l\u00e9pett fel a torrent kiszolg\u00e1l\u00e1sa k\u00f6zben ConfigView.section.tracker.pollinterval=Kliensek v\u00e9gigk\u00e9rdez\u00e9se (mp) ConfigView.section.tracker.publishenable=Torrentek adatainak k\u00f6zz\u00e9t\u00e9tele " ConfigView.section.tracker.ip=Tracker k\u00fcls\u0151 IP c\u00edme ConfigView.section.style.enableXPStyle=XP st\u00edlus enged\u00e9lyez\u00e9se (\u00fajraind\u00edt\u00e1s sz\u00fcks\u00e9ges ConfigView.section.tracker.checkip=K\u00fcls\u0151 IP c\u00edm automatikus meg\u00e1ll\u00edp\u00edt\u00e1sa... ipCheckerWizard.title=IP Ellen\u0151rz\u0151 Var\u00e1zsl\u00f3 ipCheckerWizard.service=Szolg\u00e1ltat\u00e1s ipCheckerWizard.chooseService=V\u00e1laszd ki az IP Ellen\u0151rz\u0151 szolg\u00e1ltat\u00e1st az al\u00e1bbi list\u00e1b\u00f3l ipCheckerWizard.explanations=A Var\u00e1zsl\u00f3val meg\u00e1llap\u00edthatja a k\u00fcls\u0151 IP c\u00edmed. Ha IP c\u00edmed dinamikus kioszt\u00e1s\u00fa, aj\u00e1nlott regisztr\u00e1lni valamelyik Dinamikus N\u00e9vkiszolg\u00e1l\u00f3n\u00e1l. Al\u00e1bb n\u00e9h\u00e1ny ilyet szedt\u00fcnk csokorba, a linkek (amelyik t\u00e1mogatja) a regisztr\u00e1ci\u00f3s oldalukra mutatnak. Regisztr\u00e1ci\u00f3 ut\u00e1n az IP c\u00edm mez\u0151ben a kapott szimbolikus c\u00edm\u00e9t nev\u00e9t kell megadnia (pl. valaki.dyndns.org). Sz\u00fcks\u00e9ged lesz egy programra, ami mindig elk\u00fcldi az aktu\u00e1lis IP c\u00edmet a szolg\u00e1ltat\u00f3 fel\u00e9. Ilyen m\u00f3don dinamikus IP c\u00edmmel is lehet szervert \u00fczemeltetni. ipCheckerWizard.service.description=Le\u00edr\u00e1s : ipCheckerWizard.progresstitle=IP ellen\u0151rz\u00e9se ipCheckerWizard.checkComplete=Teljes IP : ipCheckerWizard.checkFailed=Sikertelen, mert : wizard.tracker.local=Vuze be\u00e9p\u00edtett tracker-\u00e9nek haszn\u00e1lata wizard.tracker.external=K\u00fcls\u0151 Tracker haszn\u00e1lata wizard.tracker.howToLocal=\tA 'Be\u00e1ll\u00edt\u00e1sok>Tracker' men\u00fcpontban enged\u00e9lyezheti wizard.announceUrl=Bejelent\u0151 URL : IPChecker.external.service.discoveryvip.description=Discoveryvip - Csak IP c\u00edm ellen\u0151rz\u00e9s IPChecker.external.httpinvalidresponse=\u00c9rv\u00e9nytelen HTTP v\u00e1lasz IPChecker.external.loadingwebpage=Honlap bet\u00f6lt\u00e9se IPChecker.external.analysingresponse=V\u00e1lasz elemz\u00e9se IPChecker.external.addressextracted=Meg\u00e1llap\u00edtott IP c\u00edm IPChecker.external.httploadfail=Oldal bet\u00f6lt\u00e9se sikertelen IPChecker.external.timeout=Id\u0151t\u00fall\u00e9p\u00e9s t\u00f6rt\u00e9nt IPChecker.external.ipnotfound=Nem tal\u00e1ltam IP c\u00edmet ConfigView.section.tracker.pollintervalincby=N\u00f6vekedett: ConfigView.section.tracker.pollintervalincper=Minden ennyi kliens ut\u00e1n splash.loadingImages=K\u00e9pek bet\u00f6lt\u00e9se splash.initializeGui=F\u0151ablak el\u0151k\u00e9sz\u00edt\u00e9se splash.openViews=N\u00e9zetek megnyit\u00e1sa splash.plugin=B\u0151v\u00edtm\u00e9ny bet\u00f6lt\u00e9se : configureWizard.nat.tooManyPorts=T\u00fal sok port van tesztel\u00e9shez (max. 9) ConfigView.section.color=Sz\u00edns\u00e9m\u00e1k MyTorrentsView.menu.publish=&K\u00f6zz\u00e9tesz... MyTrackerView.status.published=K\u00f6zz\u00e9tett MyTrackerView.completed=K\u00e9sz MainWindow.menu.file.open.torrentnodefault=Torrent f\u00e1jl (Nem alap\u00e9rtelmezett helyre menti) wizard.comment=Megjegyz\u00e9s ConfigView.label.movetorrent=A .torrent f\u00e1jlok \u00e1thelyez\u00e9se ConfigView.label.movepartialdownloads=\u00c1thelyez\u00e9s akkor is, ha vannak kihagyott f\u00e1jlok a let\u00f6l\u00e9sben ConfigView.label.subdir_is_in_default=Ha a let\u00f6lt\u00e9s az alap\u00e9rtelmezett k\u00f6nxyvt\u00e1rban van, figyelje az alap\u00e9rtelmezett almapp\u00e1kat is ConfigView.section.file.decoder.label=Alap\u00e9rtelmezett torrent k\u00f3dol\u00e1s, ha v\u00e1lasztani kell ConfigView.section.file.decoder.nodecoder=Nincs IPChecker.external.service.no-ip.description=Dinamikus \u00e9s Statikus DNS szolg\u00e1ltat\u00f3\n(nem ingyenes) ConfigView.section.tracker.publicenable=K\u00fcls\u0151 torrentek enged\u00e9lyez\u00e9se ConfigView.label.playdownloadspeech=Sz\u00f3beli \u00e9rtes\u00edt\u00e9s let\u00f6lt\u00e9s befejez\u0151d\u00e9s\u00e9r\u0151l ConfigView.label.playdownloadspeech.info=A Besz\u00e9dszolg\u00e1ltat\u00e1s legjobban angolul m\u0171k\u00f6dik # # Tooltips # GeneralView.label.status.pieces_available.tooltip=Megmutatja, hogy az egyes szeletek milyen mennyis\u00e9gben \u00e1llnak rendelkez\u00e9sre.\nHa a jobb sz\u00e9len lev\u0151 sz\u00e1m 1-n\u00e9l kisebb, akkor nem l\u00e1tja a teljes megoszt\u00e1st (\u00e9s tal\u00e1n nem tudja sikeresen let\u00f6lteni ). GeneralView.label.trackerurl.tooltip=Kattints ide ha a c\u00edmet v\u00e1g\u00f3lapra szeretn\u00e9d m\u00e1solni GeneralView.label.trackerurlopen.tooltip=Kattints ide ha meg k\u00edv\u00e1nja l\u00e1togatni a tracker honlapj\u00e1t # # 2.0.4.4 # ConfigView.section.style.guiUpdate=Felhaszn\u00e1l\u00f3i fel\u00fclet friss\u00edt\u00e9se ConfigView.section.style.inactiveUpdate=F\u0151ablak friss\u00edt\u00e9se minden N-dik GUI friss\u00edt\u00e9skor, amikor nem akt\u00edv az ablak ConfigView.section.style.graphicsUpdate=Grafikus l\u00e1tv\u00e1nyelemek friss\u00edt\u00e9se a felhaszn\u00e1l\u00f3i fel\u00fclet minden N-ik friss\u00edt\u00e9se ut\u00e1n ConfigView.section.style.reOrderDelay=T\u00e1bl\u00e1zatok aorbarendez\u00e9se minden N-ik GUI friss\u00edt\u00e9s ut\u00e1n [0: soha] ConfigView.section.style.reOrderDelay.never=Soha ConfigView.section.logging=Napl\u00f3z\u00e1s ConfigView.section.logging.enable=Napl\u00f3z\u00e1s bekapcsol\u00e1sa ConfigView.section.logging.logdir=Napl\u00f3 k\u00f6nyvt\u00e1ra ConfigView.section.logging.choosedefaultsavepath=K\u00e9rem, v\u00e1lasszon egy ment\u00e9si k\u00f6nyvt\u00e1rat GeneralView.label.updatein.querying=K\u00e9rdez\u00e9s... configureWizard.nat.sharePort=Egyetlen megosztott port haszn\u00e1lata minden torrenthez ConfigView.section.logging.maxsize=Napl\u00f3 maxim\u00e1lis m\u00e9rete ConfigView.section.tracker.passwordenableweb=Tracker webes fel\u00fclet\u00e9nek jelszavas v\u00e9delme ConfigView.section.tracker.passwordenabletorrent=Torrentek jelszavas v\u00e9delme ConfigView.section.tracker.username=Felhaszn\u00e1l\u00f3n\u00e9v ConfigView.section.tracker.password=Jelsz\u00f3 columnChooser.title=V\u00e1lassza ki a megjelen\u00edtend\u0151 oszlopot columnChooser.move=\u00c1trendez\u00e9shez h\u00fazza a sorokat az \u00faj hely\u00fckre columnChooser.apply=Alkalmaz columnChooser.columnname=Oszlop neve columnChooser.columndescription=Le\u00edr\u00e1s TableColumn.header.shareRatio=Megoszt\u00e1si Ar\u00e1ny MyTorrentsView.menu.editTableColumns=&Oszlop be\u00e1ll\u00edt\u00e1sok wizard.operationfailed=A M\u0171velet sikertelen authenticator.title=Hiteles\u00edt\u00e9s sz\u00fcks\u00e9ges authenticator.realm=Tartom\u00e1ny authenticator.user=Felhaszn\u00e1l\u00f3n\u00e9v authenticator.password=Jelsz\u00f3 ConfigView.label.allowSendVersion=Az Vuze n\u00e9vtelen inform\u00e1ci\u00f3kat k\u00fcldhet az \u00faj verzi\u00f3 keres\u00e9sekor ConfigView.label.version.info.link=L\u00e1togass el ide, a szervernek k\u00fcld\u00f6tt adatok r\u00e9szletez\u00e9s\u00e9\u00e9rt wizard.hint.mode=Tipp:\tA var\u00e1zsl\u00f3ban Fogd \u00e9s Vidd m\u00f3dszerrel is kijel\u00f6lhet\n\tegy mapp\u00e1t vagy egy f\u00e1jlt wizard.hint.file=Tipp:\tFogd \u00e9s Vidd m\u00f3don is kijel\u00f6lhet egy f\u00e1jlt wizard.hint.directory=Tipp:\tFogd \u00e9s Vidd m\u00f3don is kijel\u00f6lhet egy mapp\u00e1t MainWindow.menu.help.checkupdate=&Friss\u00edt\u00e9sek Keres\u00e9se TableColumn.header.down=Let\u00f6ltve TableColumn.header.up=Felt\u00f6ltve ConfigView.section.tracker.passwordenabletorrent.info=Megfelel\u0151 klienst ig\u00e9nyel (pl. Vuze ConfigView.section.style.confirmationOnExit=Meger\u0151s\u00edt\u00e9s k\u00e9r\u00e9se kil\u00e9p\u00e9skor MainWindow.dialog.exitconfirmation.title=Kil\u00e9p? MainWindow.dialog.exitconfirmation.text=Be akarja z\u00e1rni az Azureust? SystemTray.menu.stopalltransfers=\u00d6sszes \u00e1tvitel le\u00e1ll\u00edt\u00e1sa TrayWindow.menu.stopalldownloads=\u00d6sszes Let\u00f6lt\u00e9s Le\u00e1ll\u00edt\u00e1s&a ConfigView.section.tracker.sslport.info=Tov\u00e1bbi inform\u00e1ci\u00f3k\u00e9rt olvasd el a GYIK-ot wizard.tracker.ssl=SSL haszn\u00e1lata ConfigView.label.playdownloadfinished=Hangjelz\u00e9s, ha egy let\u00f6lt\u00e9s befejez\u0151d\u00f6tt ConfigView.label.popupdownloadfinished=Felugr\u00f3 \u00fczenet ha egy let\u00f6lt\u00e9s elk\u00e9sz\u00fcl ConfigView.label.popupfilefinished=Felugr\u00f3 \u00fczenet ha egy f\u00e1jl elk\u00e9sz\u00fcl TableColumn.header.pieces=Darab TableColumn.header.pieces.info=Grafikus megjelen\u00edt\u00e9se, hogy \u00e9ppen melyik darabot t\u00f6lt\u00f6d TableColumn.header.completion=Befejez\u00e9s TableColumn.header.completion.info=A let\u00f6lt\u00e9si \u00e1llapot grafik\u00e1val kijelezve ConfigView.section.style.showdownloadbasket=Let\u00f6lt\u00e9si Kos\u00e1r mutat\u00e1sa (Fogd \u00e9s Vidd) ConfigView.section.style.alwaysShowTorrentFiles=R\u00e9szletek/F\u00e1jlok n\u00e9zetben mindig mutassa a torrent f\u00e1jlokat wizard.multitracker=Multi-Tracker inform\u00e1ci\u00f3 hozz\u00e1ad\u00e1sa a torrenthez wizard.multitracker.configuration=Multi-Tracker Be\u00e1ll\u00edt\u00e1sok wizard.multitracker.new=\u00daj... wizard.multitracker.edit=Szerkeszt\u00e9s... wizard.multitracker.delete=T\u00f6rl\u00e9s wizard.multitracker.group=Tracker Csoport wizard.multitracker.edit.title=Multi-Tracker Szerkeszt\u0151 wizard.multitracker.edit.name=N\u00e9v wizard.multitracker.edit.save=Ment\u00e9s wizard.multitracker.edit.newgroup=\u00daj Csoport wizard.multitracker.edit.deletegroup=T\u00f6rl\u00e9s wizard.multitracker.edit.newtracker=\u00daj Tracker wizard.multitracker.edit.deletetracker=T\u00f6rl\u00e9s wizard.multitracker.edit.edit=Szerkeszt\u00e9s wizard.addingmt=Multi-Tracker inform\u00e1ci\u00f3 hozz\u00e1ad\u00e1sa wizard.multitracker.noannounce=Nincs bejelent\u0151 URL a tracker list\u00e1ban MyTorrentsView.menu.recheck=\u00da&jraellen\u0151rz\u00e9s iconBar.showDownloadBar.tooltip=Let\u00f6lt\u00e9si Cs\u00edk mutat\u00e1sa iconBar.start.tooltip=Ind\u00edt iconBar.stop.tooltip=Le\u00e1ll\u00edt iconBar.remove.tooltip=Elt\u00e1vol\u00edt iconBar.openNoDefault.tooltip=.torrent f\u00e1jl megnyit\u00e1sa (nem alap\u00e9rtelmezett mapp\u00e1ba) iconBar.openURL.tooltip=URL megnyit\u00e1sa iconBar.openFolder.tooltip=Mappa megnyit\u00e1sa iconBar.new.tooltip=Torrent l\u00e9trehoz\u00e1sa iconBar.up.tooltip=Feljebb helyez iconBar.down.tooltip=Lejjebb helyez iconBar.run.tooltip=Megnyit iconBar.host.tooltip=Kiszolg\u00e1l iconBar.publish.tooltip=K\u00f6zz\u00e9tesz iconBar.editcolumns.tooltip=Oszlop be\u00e1ll\u00edt\u00e1sa MyTorrentsView.menu.editTracker=Tracker URL sz&erkeszt\u00e9se GeneralView.menu.selectTracker=Kiv\u00e1laszt ConfigView.section.stats.xslfile=XSL f\u00e1jl neve ConfigView.section.stats.xslfiledetails=Ez is beleker\u00fcl a statisztikaf\u00e1jl fejl\u00e9c\u00e9be, mint bejegyz\u00e9s ConfigView.label.savetorrentbackup=Biztons\u00e1gi m\u00e1solatok k\u00e9sz\u00edt\u00e9se ConfigView.section.tracker.forceport=Kiszolg\u00e1lt k\u00fcls\u0151 torrentek k\u00e9nyszer\u00edt\u00e9se az alap\u00e9rtelmezett portra ConfigView.section.ipfilter.allow=Az itt tal\u00e1lhat\u00f3 tartom\u00e1nyok enged\u00e9lyez\u00e9se (alap\u00e9rtelmez\u00e9sben Tiltva) ConfigView.section.ipfilter.list.inrange=az al\u00e1bbi tartom\u00e1nyban szerepel: ConfigView.section.ipfilter.list.notinrange=egyik tartom\u00e1nyban sem szerepel ConfigView.section.ipfilter.list.title=Blokkolt IP-k list\u00e1ja ConfigView.label.allowsameip=T\u00f6bbsz\u00f6r\u00f6s csatlakoz\u00e1s enged\u00e9lyez\u00e9se azonos IP-r\u0151l ConfigView.label.allowsameip.tooltip=Csak akkor kapcsolja be, ha NAGYON MUSZ\u00c1LY.\nKikapcsolt \u00e1llapotban v\u00e9d a hi\u00e9n\u00e1kt\u00f3l. ManagerItem.superseeding=Szuper-K\u00e9szforr\u00e1s ConfigView.label.userSuperSeeding=Szuper K\u00e9szforr\u00e1s m\u00f3d PeersView.uniquepiece=Szeletek (Szuper-K\u00e9szforr\u00e1s M\u00f3d) PeersView.uniquepiece.none=Nincs PeersView.timetosend=A szeletek \u00fajrak\u00fcld\u00e9s\u00e9nek az ideje (Szuper K\u00e9szforr\u00e1s M\u00f3d) ConfigView.section.style.addurlsilently=URL C\u00edmek csendes megnyit\u00e1sa ConfigView.section.style.addurlsilently.tooltip=Automatikusan megnyitott/\u00e1th\u00fazott torrent c\u00edmek megnyit\u00e1sa p\u00e1rbesz\u00e9dablak n\u00e9lk\u00fcl. ConfigView.section.file.decoder.prompt=K\u00e9rdezze meg ha van v\u00e1laszt\u00e1si lehet\u0151s\u00e9g ConfigView.section.file.decoder.prompt.tooltip=Mindig megk\u00e9rdezi a k\u00f3dol\u00e1st, ha t\u00f6bb lehet\u0151s\u00e9g van MyTorrentsView.menu.moveTop=&Tetej\u00e9re MyTorrentsView.menu.moveEnd=&Alulra ConfigView.label.moveonlyusingdefaultsave=csak ha az alap\u00e9rtelmezett k\u00f6nyvt\u00e1rban vannak ConfigView.label.moveonlyusingdefaultsave.tooltip=Let\u00f6lt\u00f6tt adatokat csak akkor helyezze \u00e1t, ha az alap\u00e9rtelmezett k\u00f6nyvt\u00e1rban vannak ConfigView.label.watchtorrentfolder=\u00daj torrentek automatikus import\u00e1l\u00e1sa ConfigView.label.watchtorrentfolder.tooltip=\u00daj .torrent f\u00e1jlok folyamatos keres\u00e9se ConfigView.label.watchtorrentfolderinterval=Id\u0151k\u00f6z ConfigView.label.watchtorrentfolderinterval.tooltip=Az ellen\u0151rz\u00e9sek k\u00f6zt eltelt id\u0151 ConfigView.dialog.choosewatchtorrentfolderpath=K\u00e9rem adja meg a .torrent import k\u00f6nyvt\u00e1rat ConfigView.label.startwatchedtorrentsstopped=Ne ind\u00edtsa el automatikusan az \u00faj torrenteket ConfigView.label.startwatchedtorrentsstopped.tooltip=\u00daj torrenteket \u00c1LL\u00d3 \u00e1llapotban veszi fel ConfigView.section.plugins=Pluginek wizard.maketorrent.filesize=F\u00e1jl(ok) m\u00e9rete wizard.maketorrent.piececount=Szeleket sz\u00e1ma wizard.maketorrent.piecesize=Szeletek m\u00e9rete MainWindow.menu.view.stats=&Statisztik\u00e1k SpeedView.title.full=Aktivit\u00e1s SpeedView.downloadSpeed.title=Let\u00f6lt\u00e9si Sebess\u00e9g SpeedView.uploadSpeed.title=Felt\u00f6lt\u00e9si Sebess\u00e9g ConfigView.section.style.useSIUnits=IEC m\u00e9rt\u00e9kegys\u00e9gek haszn\u00e1lata (KB -> KiB, stb.) iconBar.top.tooltip=Fel\u00fclre helyez iconBar.bottom.tooltip=Alulra helyez TableColumn.header.health=Er\u0151nl\u00e9t MyTorrentsView.menu.health=Az Er\u0151nl\u00e9t Magyar\u00e1zata health.explain.grey=azt jelenti, hogy a torrent nem fut (nincs le- vagy felt\u00f6lt\u00e9s) health.explain.red=azt jelenti, hogy egyetlen \u00fcgyf\u00e9lhez sem csatlakozik let\u00f6lt\u00e9s k\u00f6zben health.explain.blue=Ha csak megoszt ez azt jelenti, hogy m\u00e9g nrm kapcsol\u00f3dik m\u00e1s \u00fcgyfelekhez.\nHa let\u00f6lt, akkor ez azt jelenti, hogy l\u00e1t p\u00e1r \u00fcgyfelet, de nem l\u00e1tja a trackert. health.explain.yellow=azt jelenti, hogy a tracker fel\u0151l minden rendben, kapcsol\u00f3dt\u00e1l \u00fcgyfelekhez, de nincs felt\u00f6lt\u00e9s.\nHa marad a sz\u00edn s\u00e1rga, az azt jelezheti, hogy a NAT rosszul van be\u00e1ll\u00edtva health.explain.green=azt jelenti, hogy minden rendben van ConfigView.section.style.alwaysRefreshMyTorrents=Saj\u00e1t Torrentjeim folyamatos friss\u00edt\u00e9se ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Ha enged\u00e9lyezed a Saj\u00e1t Torrentjeim n\u00e9zet akkor is friss\u00fcl, ha az ablak \u00e9pp nincs el\u0151t\u00e9rben (egyes mIRC b\u0151v\u00edtm\u00e9nyekn\u00e9l hasznos) # #2.0.7.0 # security.certtruster.title=Biztons\u00e1gi figyelmeztet\u00e9s security.certtruster.intro=A biztons\u00e1gi tan\u00fas\u00edtv\u00e1nyt olyan t\u00e1rsas\u00e1g \u00e1ll\u00edtotta ki, mely nem kapott bizalmat security.certtruster.resource=Forr\u00e1s: security.certtruster.issuedto=Birtokos: security.certtruster.issuedby=Kibocs\u00e1jt\u00f3: security.certtruster.prompt=Megb\u00edzik benne? security.certtruster.yes=Igen security.certtruster.no=Nem ConfigView.section.tracker.torrentsperpage=H\u00e1ny torrent jelenjen meg egy oldalon? [0: korl\u00e1tlan] MainWindow.menu.file.share=Me&goszt MainWindow.menu.file.share.file=&F\u00e1jl... MainWindow.menu.file.share.dir=&Mapp\u00e1t... MainWindow.menu.file.share.dircontents=Mappa t&artalm\u00e1t... MainWindow.menu.file.share.dircontentsrecursive=Mappa ta&rtalm\u00e1t (almapp\u00e1kat is)... MainWindow.dialog.share.sharefile=V\u00e1lassza ki a megosztani k\u00edv\u00e1nt f\u00e1jlt MainWindow.dialog.share.sharedir=V\u00e1lassza ki a megosztani k\u00edv\u00e1nt mapp\u00e1t MainWindow.dialog.share.sharedircontents=V\u00e1lassza ki a mappa megosztani k\u00edv\u00e1nt tartalm\u00e1t MainWindow.dialog.share.sharedircontents.recursive=Almapp\u00e1ban is globalmanager.download.remove.veto=Elt\u00e1vol\u00edt\u00e1s megtagadva plugin.sharing.download.remove.veto=Ez a let\u00f6lt\u00e9s megosztott forr\u00e1s(ok) eredm\u00e9nye.\nA t\u00f6rl\u00e9s\u00e9hez el\u0151bb a forr\u00e1s(oka)t sz\u00fcntesse meg.: go to Tools->My Classic-Shares. ConfigView.section.tracker.main=F\u0151oldal ConfigView.label.prioritizefirstpiece=A f\u00e1jl(ok) els\u0151 \u00e9s utols\u00f3 darabjait t\u00f6ltse le el\u0151sz\u00f6r ConfigView.label.prioritizefirstpiece.tooltip=El\u0151sz\u00f6r minden \u00e1llom\u00e1ny elej\u00e9t \u00e9s v\u00e9g\u00e9t pr\u00f3b\u00e1lja let\u00f6lteni.\nEl\u0151bb belen\u00e9zhetsz a f\u00e1jlba. ConfigView.section.file.confirm_data_delete=Meger\u0151s\u00edt\u00e9s k\u00e9r\u00e9se adatok t\u00f6rl\u00e9n\u00e9l ConfigView.section.file.confirm_data_delete.tooltip=Meger\u0151s\u00edt\u00e9s k\u00e9r\u00e9se, adatok v\u00e9gleges t\u00f6rl\u00e9se el\u0151tt (Remove&Delete)... ConfigView.section.file.delete.include_files_outside_save_dir=Adatok t\u00f6rl\u00e9sekor a torrent mapp\u00e1n k\u00edv\u00fcl es\u0151 f\u00e1jlok \u00e9s t\u00f6rl\u0151dnek TrayWindow.menu.startalldownloads=\u00d6sszes Let\u00f6lt\u00e9s Ind\u00edt\u00e1sa SystemTray.menu.startalltransfers=\u00d6sszes \u00e1tvitel ind\u00edt\u00e1sa sharing.progress.title=Megoszt\u00e1s Folyamata sharing.progress.hide=Elrejt MainWindow.menu.view.myshares=Megoszt\u00e1saim MySharesView.title.full=Megoszt\u00e1saim MySharesView.name=N\u00e9v MySharesView.type=T\u00edpus MySharesView.type.file=F\u00e1jl MySharesView.type.dir=Mappa MySharesView.type.dircontents=Mappa tartalom MySharesView.type.dircontentsrecursive=Mappa tartalom (almapp\u00e1kban is) MySharesView.menu.remove=Elt\u00e1vol\u00edt ConfigView.section.tracker.extensions=Kiterjeszt\u00e9sek ConfigView.section.tracker.sendpeerids=\u00dcgyf\u00e9l adatainak k\u00fcld\u00e9se a let\u00f6lt\u0151knek ConfigView.section.tracker.enableudp=UDP tracker protokoll enged\u00e9lyez\u00e9se plugin.sharing.torrent.remove.veto=Ez a tracker bejegyz\u00e9s megosztott forr\u00e1s(ok)on alapul. T\u00f6rl\u00e9s\u00e9hez el\u0151bb sz\u00fcntesse meg a forr\u00e1s\u00e1ul szolg\u00e1l\u00f3 megoszt\u00e1st.: go to Tools->My Classic-Shares. plugin.download.remove.veto.notstopped=A let\u00f6lt\u00e9st nem lehet t\u00f6r\u00f6lni, mert nem \u00e1ll. plugin.sharing.remove.veto=Ezt a megoszt\u00e1st egy m\u00e1sik megoszt\u00e1sb\u00f3l sz\u00e1rmaztattuk \u00e9s nem lehet t\u00f6r\u00f6lni.\nElt\u00e1vol\u00edt\u00e1s\u00e1hoz t\u00f6r\u00f6lje a f\u0151 megoszt\u00e1st. GeneralView.label.hash.tooltip=Az ellen\u0151rz\u0151\u00f6sszeg m\u00e1sol\u00e1sa a v\u00e1g\u00f3lapra ConfigView.section.tracker.maxpeersreturned=\u00dcgyfelek maxim\u00e1lis sz\u00e1ma [0: korl\u00e1tlan] ConfigView.label.serverport=Bej\u00f6v\u0151 TCP / UDP port ConfigView.label.serverport.tooltip=A portnak 1-65535 tartom\u00e1nyba kell esnie, de nem lehet 6880, mivel ezt az Vuze saj\u00e1t haszn\u00e1latra tartja fenn. configureWizard.nat.server.tcp_listen_port=Bej\u00f6v\u0151 TCP Port ConfigView.section.sharing=Megoszt\u00e1s ConfigView.section.sharing.usessl=Osztott forr\u00e1sokkal SSL kapcsolat (sz\u00fcks\u00e9ges a Tracker be\u00e1ll\u00edt\u00e1sa) ConfigView.section.style.dropdiraction=Fogd \u00e9s Vidd k\u00f6nyvt\u00e1rakn\u00e1l (Drag & Drop m\u00f3dszer) ConfigView.section.style.dropdiraction.opentorrents=Torrent megnyit\u00e1sa ConfigView.section.style.dropdiraction.sharefolder=K\u00f6nyvt\u00e1r Megoszt\u00e1sa ConfigView.section.style.dropdiraction.sharefoldercontents=F\u00e1jlok Megoszt\u00e1sa # # 2.0.7.x # Categories.all=Mind Categories.uncategorized=Kategoriz\u00e1latlan CategoryAddWindow.message=K\u00e9rem az \u00faj kateg\u00f3ria nev\u00e9t CategoryAddWindow.title=\u00daj kateg\u00f3ria l\u00e9trehoz\u00e1sa ConfigView.label.autoSeedingIgnoreInfo=Figyelmen k\u00edv\u00fcl hagyott torrentek a k\u00e9szforr\u00e1s lista alj\u00e1ra ker\u00fclnek. Nem indulnak el automatikusan.\n Ez a szab\u00e1ly nem \u00e9rv\u00e9nyes az Els\u0151 Priorit\u00e1s\u00fa torrentekre\nAm\u00edg m\u00e1st nem \u00e1ll\u00edtassz be, hagyd 0-n ami kikapcsolja ezt a funkci\u00f3t. ConfigView.label.directory=Mappa ConfigView.label.disconnetseed.tooltip=Felt\u00f6lt\u00e9s eset\u00e9n megszak\u00edtja a kapcsolatot m\u00e1s K\u00e9szforr\u00e1sokkal.\nNincs sz\u00fcks\u00e9g a kapcsolatfenntart\u00e1sra. ConfigView.label.ignoreCase=Kis- \u00e9s nagybet\u0171k azonosak ConfigView.label.ignoreSeeds=Hagyjon ki minden torrentet legal\u00e1bb ConfigView.label.importdirectory=Import Mappa ConfigView.label.minPeersToBoostNoSeeds.tooltip=Amelyik torrenthez senkin\u00e9l sem tartozik teljes f\u00e1jl, \u00e9s a megadottn\u00e1l kevesebb \u00fcgyf\u00e9l v\u00e1r,\na v\u00e1r\u00f3lista alj\u00e1ra ker\u00fcl. ConfigView.label.minPeersToBoostNoSeeds=Felt\u00f6lt\u00e9si rang cs\u00f6kkent\u00e9se, ha nincs k\u00e9szforr\u00e1s \u00e9s \u00fcgyfelek sz\u00e1ma kevesebb, mint ConfigView.label.minSeedingTime.tooltip=A felt\u00f6lt\u00e9si rang r\u00f6vid id\u0151n bel\u00fcl is gyorsan v\u00e1ltozhat, emiatt egy torrent r\u00f6gt\u00f6n le is \u00e1llhat, amint automatikusan elindult.\nEzzel a be\u00e1ll\u00edt\u00e1ssal viszont kik\u00fcsz\u00f6b\u00f6lheti ezt a probl\u00e9m\u00e1t. Minden felt\u00f6lt\u00e9s legal\u00e1bb ennyi ideig menni fog, lej\u00e1rta el\u0151tt esetleg saj\u00e1t kez\u00fcleg le\u00e1ll\u00edthatja. ConfigView.label.minSeedingTime=Minim\u00e1lis k\u00e9szforr\u00e1si id\u0151 m\u00e1sodpercben ConfigView.label.minSpeedForActiveDL.tooltip=Befejezetlen torrent ind\u00edt\u00e1sa ut\u00e1n\nminden let\u00f6lt\u00e9si hely legal\u00e1bb 30 m\u00e1sodpercig foglalt. ConfigView.label.minSpeedForActiveDL=Ne tekintse \u00fagy, hogy a torrent let\u00f6lt\u00e9st foglal, ha lassabb, mint ConfigView.label.peers=\u00fcgyf\u00e9l ConfigView.label.queue.debuglog=Hibafelder\u00edt\u00e9st seg\u00edt\u0151 napl\u00f3z\u00e1s ConfigView.label.queue.debuglog.info=V\u00e1r\u00f3lista inform\u00e1ci\u00f3k csatol\u00e1sa a konzol/napl\u00f3 f\u00e1jlhoz.\nK\u00f3dolt, de seg\u00edt nyomon k\u00f6vetni let\u00f6lt\u00e9seink viselked\u00e9s\u00e9t, \u00e9s esetleg azt, hogy vajon mi\u00e9rt \u00e1llnak le folyton. ConfigView.label.queue.minQueueingShareRatio=Ne tegye v\u00e1r\u00f3list\u00e1ra \u00e9s ne \u00e1ll\u00edtsa le a torrentet, m\u00edg a megoszt\u00e1si ar\u00e1ny kisebb, mint ConfigView.label.ratio=ar\u00e1ny ConfigView.label.removeOnStop=Az automatikusan le\u00e1llt torrenteket vegye ki a v\u00e1r\u00f3list\u00e1b\u00f3l ConfigView.label.savedirectory=Ment\u00e9s helye ConfigView.label.seeding.autoReposition.tooltip=Akt\u00edv \u00e1llapotban a k\u00e9szforr\u00e1sok sorrendj\u00e9t ('#' oszlop) a K\u00e9szforr\u00e1s Ranghoz igaz\u00edtja.\nHasznos, ha nem szereti figyelemmel k\u00eds\u00e9rni a Rang alakul\u00e1s\u00e1t, de tudni szeretn\u00e9, milyen sorrendben v\u00e1rhat\u00f3 a k\u00e9szforr\u00e1sok ind\u00edt\u00e1sa. ConfigView.label.seeding.autoReposition=Torrentek automatikus \u00e1trendez\u00e9se K\u00e9szforr\u00e1s rang szerint ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Kev\u00e9s K\u00e9szforr\u00e1ssal (Seed) \u00e9s sok \u00fcgyf\u00e9llel (Peer) rendelkez\u0151 torrent sokszor azt jelenti, hogy nem \u00e9rhet\u0151 el teljes f\u00e1jl.\nEmiatt esetleg el k\u00edv\u00e1nja ker\u00fclni, hogy a k\u00e9szforr\u00e1s szab\u00e1lyok teljes f\u00e1jlt imit\u00e1ljanak. (cs\u00f6kkentve a f\u00e1jl rangj\u00e1t) ConfigView.label.seeding.fakeFullCopySeedStart=de csak akkor, ha van minimum ConfigView.label.seeding.ignore=Szab\u00e1lyok mell\u0151z\u00e9se ConfigView.label.seeding.ignore0Peers=Hagyja ki a 0 \u00fcgyf\u00e9llel rendelkez\u0151 torrenteket ConfigView.label.seeding.ignoreRatioPeers=Torrent kihagy\u00e1sa, ha minden k\u00e9szforr\u00e1sra jut legfeljebb ConfigView.label.seeding.ignoreShareRatio=Torrent kihagy\u00e1sa, ha a megoszt\u00e1s ar\u00e1nya ConfigView.label.seeding.ignore.header.evenFirstPriority=Torrentek kihagy\u00e1sa akkor is\nMagas Priorit\u00e1s szab\u00e1llyal egyezik ConfigView.label.seeding.ignore.header.rule=Szab\u00e1ly ConfigView.label.seeding.ignore.header.value=\u00c9rt\u00e9k ConfigView.label.seeding.firstPriority.info=Magas Priorit\u00e1s\u00fa torrentek mindig a v\u00e1r\u00f3lista tetej\u00e9re ker\u00fcl.\nA Magas Priortt\u00e1s felt\u00e9teleinek megfelel\u0151 torrentek nem \u00e1llnak le automatikusan.\nEls\u0151bbs\u00e9ggel rendelkez\u0151 torrent sz\u00fcks\u00e9g eset\u00e9n elfoglal egy let\u00f6lt\u00e9si sz\u00e1lat. ConfigView.label.seeding.firstPriority.FP=Magas Priorit\u00e1s ConfigView.label.seeding.firstPriority=Els\u0151bbs\u00e9ggel rendelkez\u0151 torrentek ConfigView.label.seeding.firstPriority.following=tekintetben megfelel a k\u00f6vetkez\u0151knek: ConfigView.label.seeding.firstPriority.shareRatio=K\u00e9szforr\u00e1s ar\u00e1ny kevesebb, mint ConfigView.label.seeding.firstPriority.seedingMinutes=Ennyi ideje v\u00e1ltott let\u00f6lt\u00e9sr\u0151l k\u00e9szforr\u00e1sra ConfigView.label.seeding.firstPriority.DLMinutes=A let\u00f6lt\u00e9s ind\u00edt\u00e1sa \u00f3ta eltelt id\u0151 ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Ha X \u00fcgyfelenk\u00e9nt egy teljes f\u00e1jlt sz\u00ednlel, akkor cs\u00f6kkenti a magas \u00fcgyf\u00e9lsz\u00e1m\u00fa torrentek rangj\u00e1t.\nSok \u00fcgyf\u00e9llel b\u00edr\u00f3 torrentek \u00e1ltal\u00e1ban magas forgalmat is gener\u00e1lnak.\nEz a be\u00e1ll\u00edt\u00e1s nincs hat\u00e1ssal a t\u00e9nyleges k\u00e9szforr\u00e1sok kijelz\u00e9s\u00e9re. ConfigView.label.seeding.numPeersAsFullCopy=Sz\u00ednleljen 1 teljes f\u00e1jlt minden\n(0 : nem sz\u00ednlel) ConfigView.label.seeding.preferLargerSwarms.tooltip=Ha legink\u00e1bb "beszorult" \u00fcgyfeleknek ad k\u00e9szforr\u00e1st, \u00e9rdemes lehet nagyobb l\u00e9tsz\u00e1m\u00fa csoportokat el\u0151nyben r\u00e9szes\u00edteni.\nHa viszont nagy hozz\u00e1f\u00e9rhet\u0151s\u00e9ggel rendelkez\u0151 f\u00e1jlt oszt meg, kisebb csoportokat \u00e9rdemes el\u0151nyben r\u00e9szes\u00edteni. ConfigView.label.seeding.preferLargerSwarms=Egyforma rang\u00fa torrentek k\u00f6z\u00fcl a nagyobb bolyt r\u00e9szes\u00edtse el\u0151nyben. ConfigView.label.seeding.rankType.none.tooltip=# oszlop szerinti sorrend ConfigView.label.seeding.rankType.none=Nincs ConfigView.label.seeding.rankType.peer.tooltip=t\u00f6bb let\u00f6lt\u0151 \u00e9s kevesebb felt\u00f6lt\u0151 = magasabb rang\nEz a rang minimaliz\u00e1lja a a maxim\u00e1lis felt\u00f6lt\u00e9shez sz\u00fcks\u00e9ges torrentek sz\u00e1m\u00e1t ConfigView.label.seeding.rankType.peer=S\u00falyozott Peer sz\u00e1m ConfigView.label.seeding.rankType.peerSeed.options=K\u00e9szforr\u00e1s:\u00dcgyf\u00e9l ar\u00e1ny Be\u00e1ll\u00edt\u00e1sok ConfigView.label.seeding.rankType.peerSeed.tooltip=Nagyobb ar\u00e1ny = Nagyobb rang ConfigView.label.seeding.rankType.peerSeed=\u00dcgyf\u00e9l:K\u00e9szforr\u00e1s ar\u00e1ny ConfigView.label.seeding.rankType.seed.fallback=Visszat\u00e9r\u00e9s az \u00dcgyf\u00e9l:K\u00e9szforr\u00e1s ar\u00e1ny elv\u00e9hez, ha megvan\n(0 : soha) ConfigView.label.seeding.rankType.seed.options=Csak K\u00e9szforr\u00e1s Sz\u00e1m\u00edt\u00e1s\u00e1nak Be\u00e1ll\u00edt\u00e1sai ConfigView.label.seeding.rankType.seed.tooltip=Kevesebb K\u00e9szforr\u00e1s = Magasabb rang ConfigView.label.seeding.rankType.seed=Csak a K\u00e9szforr\u00e1sokat sz\u00e1molja ConfigView.label.seeding.rankType.timedRotation.tooltip=Minden v\u00e1r\u00f3list\u00e1n lev\u0151 torrent K\u00e9szforr\u00e1s m\u00f3dba ker\u00fcl.\nA megoszt\u00e1s idej\u00e9t a "Minim\u00e1lis K\u00e9szforr\u00e1sid\u0151n\u00e9l"-n\u00e9l kell megadni. ConfigView.label.seeding.rankType.timedRotation=Id\u0151 alap\u00fa k\u00f6rforg\u00e1s ConfigView.label.seeding.rankType.tooltip=A Magasabb rang\u00fa torrentek automatikusan elindulnak.\nHa egy m\u00e1sik torrent magasabb rangot kap, az alacsonyabb rang\u00fa meg\u00e1ll, \u00e9s visszat\u00e9r a v\u00e1r\u00f3sorba.\n\nCsak a V\u00e1r\u00f3list\u00e1n szerepl\u0151 torrentek indulhatnak automatikusan.\n\u00c1ll\u00f3 torrentek nem indulnak el. ConfigView.label.seeding.rankType=Befejezett torrentek rangsorol\u00e1sa az al\u00e1bbiak szerint: ConfigView.label.stopAfterMinutes=Miut\u00e1n megoszt\u00e1sra v\u00e1ltott, adott id\u0151 ut\u00e1n hagyja abba ConfigView.label.switchpriority.tooltip=Alacsony riorit\u00e1s cs\u00f6kkenti a torrenthez rendelt felt\u00f6lt\u00e9s s\u00e1vsz\u00e9less\u00e9g\u00e9t ConfigView.pluginlist.info=Az al\u00e1bbi pluginokat siker\u00fcl beazonos\u00edtani. N\u00e9h\u00e1ny pluginhoz nem tartozik be\u00e1ll\u00edt\u00e1si lehet\u0151s\u00e9g. ConfigView.pluginlist.noplugins=Nem tal\u00e1ltam Plugint. ConfigView.section.pluginslist=Lista ConfigView.section.queue.seeding=K\u00e9szforr\u00e1s ConfigView.section.queue.seeding.autoStarting=Automatikus ind\u00edt\u00e1s ConfigView.section.queue.seeding.ignore=Kihagy\u00e1s ConfigView.section.queue.seeding.firstPriority=Magas Priorit\u00e1s ConfigView.section.queue.main=F\u0151ablak ConfigView.section.queue=V\u00e1r\u00f3sor ConfigView.section.torrents=Torrentek ConfigView.text.all=minden ConfigView.text.hours=\u00f3ra ConfigView.text.ignoreRule=Kihagy\u00e1s felt\u00e9telei ConfigView.text.ignore=Kihagy\u00e1s ConfigView.text.minutes=percenk\u00e9nt ConfigView.text.neverIgnore=Nincs Kihagy\u00e1s ConfigView.text.any=b\u00e1rmely DownloadManager.error.datamissing=Hi\u00e1nyz\u00f3 adat MainWindow.menu.file.open.torrentforseeding=Torrent F\u00e1jl... (Seedel\u00e9shez) MainWindow.menu.language.refresh=F&riss\u00edt ManagerItem.forced=Fel\u00fclb\u00edr\u00e1lt ManagerItem.queued=V\u00e1rakozik MySeedersView.header=Befejezett Torrentek TableColumn.header.availability.info=# el\u00e9rhet\u0151 teljes m\u00e1solat TableColumn.header.availability=El\u00e9rhet\u0151s\u00e9g TableColumn.header.category=Kateg\u00f3ria MyTorrentsView.header=Befejezetlen Torrentek TableColumn.header.maxuploads=Max # Felt\u00f6lt\u00e9s MyTorrentsView.menu.category.delete=Kateg\u00f3ria &t\u00f6rl\u00e9se MyTorrentsView.menu.forceStart=&K\u00e9nyszer\u00edtett ind\u00edt\u00e1s MyTorrentsView.menu.queue=&V\u00e1rakoztat MyTorrentsView.menu.setCategory.add=Kateg\u00f3ria hozz\u00e1ad\u00e1s&a... MyTorrentsView.menu.setCategory=Kateg\u00f3ria Megad\u00e1sa TableColumn.header.savepath=Ment\u00e9s helye TableColumn.header.SeedingRank=Seed Rang TableColumn.header.totalspeed.info=A kapcsol\u00f3dott peerek teljes sebess\u00e9ge TableColumn.header.totalspeed=Teljes Sebess\u00e9g splash.initializePlugins=B\u0151v\u00edtm\u00e9nyek el\u0151k\u00e9sz\u00edt\u00e9se StartStopRules.SPratioMet=KF:\u00dc Ar\u00e1ny OK StartStopRules.FP0Peers=FP / 0 \u00dcgyf\u00e9l StartStopRules.0Peers=0 \u00dcgyf\u00e9l StartStopRules.numSeedsMet=# K\u00e9szforr\u00e1s OK StartStopRules.ratioMet=\u00dcgyf\u00e9l:K\u00e9szforr\u00e1s OK StartStopRules.shareRatioMet=Megoszt\u00e1si Ar\u00e1ny OK StartStopRules.waiting=V\u00e1r StartStopRules.firstPriority=Magas Priorit\u00e1s ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=F\u00e1jlok Megoszt\u00e1sa (alk\u00f6nyvt\u00e1rakkal egy\u00fctt) DownloadManager.error.unabletostartserver=Szerver ind\u00edt\u00e1sa sikertelen - ellen\u0151rizze a bej\u00f6v\u0151 port / t\u0171zfal be\u00e1ll\u00edt\u00e1sait, hogy a program szerverk\u00e9nt m\u0171k\u00f6dhessen GeneralView.label.creationdate=L\u00e9trehozva : ConfigView.section.tracker.announcescrapepercentage=V\u00e9gigk\u00e9rdez\u00e9sek az ig\u00e9nyl\u0151k sz\u00e1zal\u00e9k\u00e1ban \npl. 200 = 2:1. 0 = \u00fcgyf\u00e9l d\u00f6nt ManagerItem.stopping=Meg\u00e1ll... ConfigView.section.tracker.announcecacheperiod=\u00c1tmeneti t\u00e1r (milisec) ConfigView.section.tracker.scrapecacheperiod=V\u00e9gigk\u00e9rdez\u00e9s elavul (milisec) ConfigView.section.tracker.scrapeandcache=V\u00e9gigk\u00e9rdez\u00e9s \u00e9s \u00e1tmeneti t\u00e1r ConfigView.section.tracker.announcecacheminpeers=Minimum ennyi Ig\u00e9nybejelent\u00e9s (Announce) adatainak \u00e1tmeneti t\u00e1rol\u00e1sa MyTrackerView.scrapes=V\u00e9gigk\u00e9rdez\u00e9sek fileDownloadWindow.retry=\u00dajra MyTrackerView.bytesin=Bej\u00f6v\u0151 B\u00e1jtok MyTrackerView.bytesinave=Bej\u00f6v\u0151 \u00c1tlag MyTrackerView.bytesout=Kimen\u0151 B\u00e1jtok MyTrackerView.bytesoutave=Kimen\u0151 \u00c1tlag ConfigView.section.file.max_open_files=\u00cdr\u00e1sra/olvas\u00e1sra egyszerre megnyithat\u00f3 f\u00e1jlok sz\u00e1ma\n[0: korl\u00e1tlan] ConfigView.section.file.max_open_files.tooltip=Hasznos lehet, ha olyan torrentet t\u00f6ltesz le, amely t\u00f6bb sz\u00e1z/ezer f\u00e1jlt tartalmaz, \u00e9s az oper\u00e1ci\u00f3s rendszer m\u00e1r nem tudn\u00e1 ezeket kezelni. ConfigView.section.proxy=Proxy Be\u00e1ll\u00edt\u00e1sok ConfigView.section.proxy.enable_proxy=Proxy enged\u00e9lyez\u00e9se a trackerrel val\u00f3 kommunik\u00e1ci\u00f3hoz [\u00fajraind\u00edt\u00e1s sz\u00fcks\u00e9ges] ConfigView.section.proxy.host=Kiszolg\u00e1l\u00f3 ConfigView.section.proxy.username=Felhaszn\u00e1l\u00f3n\u00e9v ConfigView.section.proxy.password=Jelsz\u00f3 ConfigView.section.proxy.enable_socks=SOCKS proxy-t haszn\u00e1lata wizard.createtorrent.extrahashes=Ellen\u0151rz\u0151 \u00f6sszeg sz\u00e1m\u00edt\u00e1sa m\u00e1s h\u00e1l\u00f3zatokhoz (pl. Gnutella2, eDonkey2000) GeneralView.label.connected=csatlakozva GeneralView.label.in_swarm=a bolyban ManagerItem.initializing=El\u0151k\u00e9sz\u00edt\u00e9s AlertMessageBox.error=Hiba AlertMessageBox.warning=Figyelem AlertMessageBox.comment=Inform\u00e1ci\u00f3 AlertMessageBox.information=Inform\u00e1ci\u00f3 AlertMessageBox.unread=Olvasatlan figyelmeztet\u00e9sek - kattints ide, hogy megn\u00e9zd \u0151ket. SharedPortServer.alert.selectorfailed=Nem siker\u00fclt figyel\u0151portot l\u00e9tes\u00edteni a bej\u00f6v\u0151 adatok sz\u00e1m\u00e1ra.\nEllen\u0151rizze a t\u0171zfala be\u00e1ll\u00edt\u00e1sait, \u00e9s enged\u00e9lyezze az 'azureus.exe'-t, szerverk\u00e9nt val\u00f3 m\u0171k\u00f6d\u00e9s\u00e9t. Tracker.alert.listenfail=Nem siker\u00fclt %1 portot fogad\u00e1sra be\u00e1ll\u00edtani.\nEllen\u0151rizze, nem haszn\u00e1lj\u00e1k-e m\u00e1r m\u00e1s alkalmaz\u00e1sok,\nvagy nem fut-e Vuze m\u00e9g egy p\u00e9ld\u00e1nyban. DiskManager.alert.movefileexists=Hiba a befejezett f\u00e1jlok \u00e1thelyez\u00e9se k\u00f6zben.\n%1 m\u00e1r van a c\u00e9lk\u00f6nyvt\u00e1rban DiskManager.alert.movefilefails=Hiba a befejezett f\u00e1jlok \u00e1thelyez\u00e9se k\u00f6zben\n%1 f\u00e1jl m\u00e1sol\u00e1sa sikertelen, %2 DiskManager.alert.movefilerecoveryfails=Hiba az \u00e1thelyezhetetlen f\u00e1jl vissza\u00e1ll\u00edt\u00e1sa k\u00f6zben\n%1 vissza\u00e1ll\u00edt\u00e1sa sikertelen, %2 ConfigView.section.tracker.logenable=Statisztik\u00e1k k\u00e9sz\u00edt\u00e9se a 'tracker.log' \u00e1llom\u00e1nyba SpeedView.stats.title=Statisztika SpeedView.stats.total=Teljes SpeedView.stats.session=Jelen folyamat SpeedView.stats.session.tooltip=Teljes (Protokol) SpeedView.stats.downloaded=Let\u00f6ltve (Protokoll) SpeedView.stats.uploaded=Felt\u00f6ltve (Protokoll) SpeedView.stats.ratio=Megoszt\u00e1si ar\u00e1ny SpeedView.stats.uptime=Felt\u00f6lt\u00e9s Ideje SpeedView.stats.now=Jelenleg SpeedView.stats.now.tooltip=Teljes (Protokol) AutoMigration.useralert=Vuze felhaszn\u00e1l\u00f3i be\u00e1ll\u00edt\u00e1sainak \u00e1tv\u00e9tele az al\u00e1bbi eredm\u00e9nnyel z\u00e1rult:\n\n%1\nAz elveszett be\u00e1ll\u00edt\u00e1sokat \u00fajra el kell v\u00e9gezni.\nNE FELEJTSE FRISS\u00cdTENI A MENT\u00c9SI \u00daTVONALAKAT, HA AZOK ID\u0150K\u00d6ZBEN V\u00c1LTOZTAK! # # > 2.0.8.0 # OpenTorrentWindow.title=Torrent(ek) megnyit\u00e1sa OpenTorrentWindow.message=K\u00eds\u00e9rleti OpenTorrentWindow.addFiles=F\u00e1jl(ok) hozz\u00e1&ad\u00e1sa OpenTorrentWindow.dataLocation=Az adatokat mentse ide: OpenTorrentWindow.startMode=M\u00f3d Hozz\u00e1ad\u00e1sa OpenTorrentWindow.startMode.queued=V\u00e1rakozik OpenTorrentWindow.startMode.stopped=\u00c1ll OpenTorrentWindow.startMode.forceStarted=K\u00e9nyszer\u00edtett Ind\u00edt\u00e1s OpenTorrentWindow.addPosition=Helye a v\u00e1r\u00f3sorban OpenTorrentWindow.addPosition.first=Els\u0151 OpenTorrentWindow.addPosition.last=Utols\u00f3 TableColumn.header.remaining.info=H\u00e1tralev\u0151 let\u00f6lt\u00e9s TableColumn.header.remaining=Marad\u00e9k ConfigView.section.tracker.enablecompact=Egyszer\u0171 Bejelent\u0151 Protokoll (Compact Announce Protocol) ConfigView.section.tracker.enablekey=Kulccsere a trackerrel a nagyobb biztons\u00e1g el\u00e9r\u00e9s\u00e9hez ConfigView.section.file.perf=Teljes\u00edtm\u00e9ny Be\u00e1ll\u00edt\u00e1sai ConfigView.section.file.perf.explain=Figyelem! - Ezen be\u00e1ll\u00edt\u00e1sok szakszer\u0171tlen megv\u00e1ltoztat\u00e1sa durv\u00e1n visszavetheti a let\u00f6lt\u00e9si teljes\u00edtm\u00e9nyt.\nHa a mem\u00f3ria elfogy\u00e1s\u00e1r\u00f3l kapsz hiba\u00fczenetet, pr\u00f3b\u00e1ld korl\u00e1tozni az egy torrenthez rendelhet\u0151 kapcsolatok sz\u00e1m\u00e1t. (L\u00e1sd: \u00c1tvitel Be\u00e1ll\u00edt\u00e1sai) ConfigView.section.file.max_open_files.explain=T\u00fal sok f\u00e1jl egyidej\u0171 megnyit\u00e1sa az er\u0151forr\u00e1sok v\u00e9gess\u00e9ge miatt zavarokat okozhat az oper\u00e1ci\u00f3s rendszer m\u0171k\u00f6d\u00e9s\u00e9ben. Itt korl\u00e1tozhatod az egyidej\u0171leg megnyithat\u00f3 \u00e1llom\u00e1nyok sz\u00e1m\u00e1t. popup.error.hide=Elrejt popup.error.details=R\u00e9szletek ConfigView.section.style.colorOverrides=Sz\u00ednek fel\u00fclb\u00edr\u00e1l\u00e1sa ConfigView.section.style.colorOverride.progressBar=Folyamats\u00e1v ConfigView.section.style.colorOverride.error=Hiba MainWindow.status.tooOld=r\u00e9gi, k\u00e9rem friss\u00edtse. ConfigView.section.style.colorOverride.warning=Figyelmeztet\u00e9s ConfigView.section.style.colorOverride.altRow=Kihagyhat\u00f3 Sorok ConfigView.section.file.save.peers.enable=Mentse el az \u00fcgyf\u00e9lkapcsolatok adatait a gyors \u00fajrakapcsol\u00f3d\u00e1shoz ConfigView.section.file.save.peers.max=Maximum ennyi \u00fcgyf\u00e9lig [0: korl\u00e1tlan] ConfigView.section.file.save.peers.pertorrent=torrentenk\u00e9nt ConfigView.label.max_peers_per_torrent=Maxim\u00e1lis kapcsolatok sz\u00e1ma torrentenk\u00e9nt [0: korl\u00e1tlan] ConfigView.label.max_peers_total=\u00d6sszes l\u00e9trehozhat\u00f3 kapcsolat [0: korl\u00e1tlan] ConfigView.section.style.colorOverrides.reset=Sz\u00ednek vissza\u00e1ll\u00edt\u00e1sa ConfigView.section.language.info=Ha enged\u00e9lyezed, az Vuze minden ind\u00edt\u00e1s\u00e1n\u00e1l ellen\u0151rzi, hogy van-e friss\u00edt\u00e9s ConfigView.section.language.enableUpdate=Webes friss\u00edt\u00e9s haszn\u00e1lata ConfigView.section.language.UpdateURL=Keres\u00e9si C\u00edm ConfigView.section.language.UpdateNow=Friss\u00edt\u00e9s Most! Button.revert=Visszavon MyTorrentsView.menu.changeDirectory=K\u00f6nyvt\u00e1r M\u00f3dos\u00edt\u00e1sa GenericText.column=oszlop MyTorrentsView.menu.thisColumn.remove=Oszlop elt\u00e1vol\u00edt\u00e1sa MyTorrentsView.menu.thisColumn.toClipboard=Sz\u00f6veg m\u00e1sol\u00e1sa a V\u00e1g\u00f3lapra MyTorrentsView.menu.thisColumn.autoTooltip=Eszk\u00f6ztippek mutat\u00e1sa mindig ConfigView.download.abbreviated=LE: ConfigView.upload.abbreviated=FEL: ConfigView.complete.abbreviated=K\u00c9SZ: TableColumn.header.secondsseeding=Seed TableColumn.header.secondsseeding.info=A seed teljes ideje. TableColumn.header.secondsdownloading=Let\u00f6lt\u00e9s TableColumn.header.secondsdownloading.info=A let\u00f6lt\u00e9s teljes ideje ConfigView.section.tracker.udpversion=UDP Protokoll verzi\u00f3ja (1 vagy 2) window.updateswt.title=Jelen SWT verzi\u00f3ja r\u00e9gi! window.updateswt.text=Jelen SWT verzi\u00f3ja nagyon r\u00e9gi!\nSWT az Vuze \u00e1ltal haszn\u00e1lt grafikus csomag, \u00e9s a jelen v\u00e1ltozat m\u00e1r t\u00fal r\u00e9gi a jelenlegi Vuze verzi\u00f3hoz. A friss\u00edt\u00e9shez kattintson az OK-ra. window.updateswt.status=St\u00e1tusz window.updateswt.failed=Friss\u00edt\u00e9s sikertelen, nyomjon OK-t az \u00fajrakezd\u00e9shez. window.updateswt.status.downloading.updater=Friss\u00edt\u0151 Modul let\u00f6lt\u00e9se window.updateswt.status.finding=SWT legfrissebb v\u00e1ltozat\u00e1nak keres\u00e9se window.updateswt.status.downloading=SWT legfrissebb v\u00e1ltozat\u00e1nak let\u00f6lt\u00e9se window.updateswt.status.done=\u00dajraind\u00edt\u00e1s window.updateswt.cancel=M\u00e9gsem swt.updater.downloader.downloading=SWT let\u00f6lt\u00e9se innen: swt.updater.urlsgetter.downloading=T\u00fck\u00f6rlista fogad\u00e1sa innen: swt.updater.urlsgetter.platform=SWT az al\u00e1bbi platformra : window.updateswt.ignore=Kihagy ConfigView.section.style.useFancyTabs=Csics\u00e1s f\u00fclek haszn\u00e1lata splash.initializeGM=Glob\u00e1lis Torrent Menedzser el\u0151k\u00e9sz\u00edt\u00e9se splash.loadingTorrents=Torrentek bet\u00f6lt\u00e9se MyTorrentsView.menu.thisColumn.sort=&Sorba rendez\u00e9s Scrape.status.ok=Kik\u00e9rdez\u00e9s rendben. Scrape.status.error=V\u00e9gigk\u00e9rdez\u00e9si Hiba: Scrape.status.error.badURL=Az ig\u00e9nybejelent\u0151 c\u00edm nem felel meg a v\u00e9gigk\u00e9rdez\u00e9sre vonatkoz\u00f3 aj\u00e1nl\u00e1soknak. Scrape.status.error.nohash=A v\u00e1laszb\u00f3l hi\u00e1nyzik az ellen\u0151rz\u0151 \u00f6sszeg. Scrape.status.error.invalid=\u00c9rv\u00e9nytelen v\u00e1lasz. Scrape.status.nextScrapeAt=K\u00f6vetkez\u0151 kik\u00e9rdez\u00e9s %1 Scrape.status.scraping=K\u00e9rdez\u00e9s... Scrape.status.initializing=Kik\u00e9rdez\u00e9sre v\u00e1rok... Scrape.status.scraping.queued=Kik\u00e9rdez\u00e9s be\u00fctemezbe... ConfigView.label.minSpeedForActiveSeeding=Ne tekintse let\u00f6lt\u00e9si helyet foglal\u00f3nak a befejezett torrentet, ha az lassabb, mint ConfigView.section.stats.exportpeers=\u00dcgyfelek tulajdons\u00e1gainak export\u00e1l\u00e1sa MainWindow.menu.view.irc.moved=IRC mostant\u00f3l b\u0151v\u00edtm\u00e9nyk\u00e9nt \u00e9rhet\u0151 el, ld. http://azureus.sourceforge.net/plugin_list.php. Telep\u00edt\u00e9s ut\u00e1n a N\u00e9zet->B\u0151v\u00edtm\u00e9nyek->IRC men\u00fcb\u0151l \u00e9rhet\u0151 el. MyTrackerView.webui.contextmenu.copyurl=Torrent URL m\u00e1sol\u00e1sa a V\u00e1g\u00f3lapra ConfigView.section.file.torrent.ignorefiles=Torrent l\u00e9trehoz\u00e1sakor kihagyhat\u00f3 f\u00e1jlok\npl: .DS_Store;Thumbs.db Torrent.create.progress.ignoringfile=F\u00e1jl kihagy\u00e1sa ConfigView.section.style.useUnitsRateBits=B\u00e1jt helyett bit alap\u00fa kijelz\u00e9s (KiB/s->Kibit/s, stb.) ConfigView.section.interface.resetassoc=Torrentf\u00e1jlok t\u00e1rs\u00edt\u00e1sa az Azureushoz ConfigView.section.interface.resetassocbutton=T\u00e1rs\u00edt ConfigView.section.interface.checkassoc=Ind\u00edt\u00e1skor a f\u00e1jlhozz\u00e1rendel\u00e9s ellen\u0151rz\u00e9se dialog.associations.title=T\u00e1rs\u00edt\u00e1s ellen\u0151rz\u00e9se Button.yes=Igen Button.no=Nem ConfigView.label.seeding.autoStart0Peers=Minden befejezett torrentet automatikusan ind\u00edtson el 0 \u00fcgyf\u00e9l eset\u00e9n ConfigView.label.seeding.autoStart0Peers.tooltip=Kapcsold be, hogy egy K\u00e9szforr\u00e1s akkor is elinduljon, ha nem v\u00e1r r\u00e1 \u00fcgyf\u00e9l (peer). dialog.associations.prompt=Nem Vuze az alap\u00e9rtelmezett BitTorrent kliens.\nSzeretn\u00e9 t\u00e1rs\u00edtani a .torrent f\u00e1jlokat? dialog.associations.askagain=Ind\u00edt\u00e1sn\u00e1l ellen\u0151rizze ConfigView.section.plugins.update=Pluginekek friss\u00edt\u00e9se Plugin.pluginupdate.enablecheck=B\u0151v\u00edtm\u00e9nyek friss\u00edt\u00e9seinek automatikus keres\u00e9se plugins.basicview.status=St\u00e1tusz: plugins.basicview.activity=Aktivit\u00e1s: plugins.basicview.progress=Folyamat: plugins.basicview.log=Napl\u00f3: ConfigView.label.maxdownloadspeed=Maxim\u00e1lis \u00f6sszes let\u00f6lt\u00e9si sebess\u00e9g KB/s-ben [0: korl\u00e1tlan] splash.loadingTorrent=Torrent bet\u00f6lt\u00e9se splash.of=innen UpdateWindow.title=Vuze Friss\u00edt\u0151 UpdateWindow.header=A k\u00f6vetkez\u0151 \u00f6sszetev\u0151ket kell friss\u00edteni : UpdateWindow.columns.install=Telep\u00edt UpdateWindow.columns.name=N\u00e9v UpdateWindow.columns.version=Verzi\u00f3 UpdateWindow.columns.size=M\u00e9ret UpdateWindow.cancel=M\u00e9gsem UpdateWindow.quit=Kil\u00e9p\u00e9s UpdateWindow.close=Bez\u00e1r UpdateWindow.ok=Friss\u00edt\u00e9s UpdateWindow.restart=\u00dajraind\u00edt\u00e1s UpdateWindow.status.downloading=Let\u00f6lt\u00e9s UpdateWindow.status.done=K\u00e9sz UpdateWindow.status.failed=Sikertelen UpdateWindow.status.restartNeeded=\u00dajraind\u00edt\u00e1s sz\u00fcks\u00e9ges! ConfigView.pluginlist.broken=S\u00e9r\u00fclt ConfigView.pluginlist.whereToPut=A felhaszn\u00e1l\u00f3 saj\u00e1t b\u0151v\u00edtm\u00e9nyeit ide tegye: ConfigView.pluginlist.whereToPutOr=A megosztott b\u0151v\u00edtm\u00e9nyeket ide tegye: MainWindow.statusText.checking=Friss\u00edt\u00e9sek Keres\u00e9se TableColumn.header.OnlyCDing4=Csak Seed TableColumn.header.OnlyCDing4.info=Csak a seedel\u00e9s ideje. Nem sz\u00e1molja belea let\u00f6lt\u00e9s idej\u00e9t (akkori felt\u00f6lt\u00e9st). ConfigView.section.style.alternateTablePainting=Alternat\u00edv t\u00e1bl\u00e1zat-rajzol\u00e1si m\u00f3dszer az oszlopokhoz (\u00fajraind\u00edt\u00e1s sz\u00fcks\u00e9ges) UpdateWindow.status.restartMaybeNeeded=\u00dajraind\u00edt\u00e1s aj\u00e1nlott ConfigView.pluginlist.shared=megosztott PeersView.host=Kiszolg\u00e1l\u00f3 Neve PeersView.host.info=A kiszolg\u00e1l\u00f3 neve, ha el\u00e9rhet\u0151 (hat\u00e1ssal lehet a teljes\u00edtm\u00e9nyre) MainWindow.menu.help.whatsnew=\u00dajdons\u00e1gok ConfigView.label.checkonstart=Vuze \u00faj verzi\u00f3j\u00e1nak keres\u00e9se ind\u00edt\u00e1skor ConfigView.label.periodiccheck=Leg\u00fajabb verzi\u00f3 folyamatos figyel\u00e9se ConfigView.label.opendialog=Friss\u00edt\u00e9s Seg\u00e9d automatikus megnyit\u00e1sa ha \u00faj friss\u00edt\u00e9s \u00e9rhet\u0151 el MainWindow.updateavail=Kattints ide a friss\u00edt\u00e9sekhez MainWindow.status.unofficialversion=Vuze B\u00e9ta MainWindow.status.latestversionunchecked=Verzi\u00f3ellen\u0151rz\u00e9s kikapcsolva GeneralView.label.updatein.stopped=Meg\u00e1ll\u00edtva StartStopRules.menu.viewDebug=Hibakeres\u0151 inform\u00e1ci\u00f3k megtekint\u00e9se ConfigView.section.style.doNotUseGB=Ne haszn\u00e1lja a GB m\u00e9rt\u00e9kegys\u00e9get ConfigView.section.style.doNotUseGB.tooltip=Az Vuze 1024MB felett is MB-ban \u00edrja ki az \u00e9rt\u00e9keket MainWindow.menu.help.plugins=Pluginek Bezserz\u00e9se ConfigView.section.plugins.TrackerWeb=Web tracker ConfigView.section.tracker.enablecategories=Torrentek kateg\u00f3ri\u00e1kba v\u00e1logat\u00e1sa health.explain.share=azt jelenti, hogy a torrentet nyilv\u00e1noss\u00e1 tetted ConfigView.section.tracker.createcert=Saj\u00e1t al\u00e1\u00edrt tan\u00fas\u00edtv\u00e1ny l\u00e9trehoz\u00e1sa ConfigView.section.tracker.createbutton=L\u00e9trehoz\u00e1s security.certcreate.title=Al\u00e1\u00edrt hiteles\u00edt\u00e9si bizony\u00edtv\u00e1ny l\u00e9trehoz\u00e1sa. security.certcreate.intro=Ez a p\u00e1rbesz\u00e9d seg\u00edti a saj\u00e1t hiteles\u00edt\u00e9si bizony\u00edtv\u00e1ny l\u00e9trehoz\u00e1s\u00e1ban. security.certcreate.alias=\u00c1ln\u00e9v security.certcreate.strength=Er\u0151ss\u00e9g security.certcreate.firstlastname=Kereszt- \u00e9s vezet\u00e9kn\u00e9v security.certcreate.orgunit=Szervezeti egys\u00e9g security.certcreate.org=Szervezet security.certcreate.city=V\u00e1ros vagy lak\u00f3hely security.certcreate.state=\u00c1llam vagy tartom\u00e1ny security.certcreate.country=K\u00e9tbet\u0171s orsz\u00e1gk\u00f3d security.certcreate.ok=L\u00e9trehoz security.certcreate.cancel=M\u00e9gsem security.certcreate.createok=Hiteles\u00edt\u00e9si bizony\u00edtv\u00e1ny l\u00e9trehozva. security.certcreate.createfail=Hiteles\u00edt\u00e9si bizony\u00edtv\u00e1ny l\u00e9trehoz\u00e1sa sikertelen ConfigView.section.plugins.webui=Swing Webes Fel\u00fclet ConfigView.section.plugins.xml_http_if=XML/HTTP fel\u00fclet webui.passwordenable=Jelsz\u00f3 enged\u00e9lyez\u00e9se webui.user=Felhaszn\u00e1l\u00f3n\u00e9v webui.password=Jelsz\u00f3 webui.protocol=Protokoll (*) webui.homepage=Honlap (*) webui.rootdir=Gy\u00f6k\u00e9rk\u00f6nyvt\u00e1r (*) webui.rootres=Gy\u00f6k\u00e9r forr\u00e1s (*) webui.mode=M\u00f3d (*) webui.mode.info=M\u00f3d lehet\n\t"teljes (full)"\t= alap\u00e9rtelmezett, minden m\u0171velet hozz\u00e1f\u00e9rhet\u0151\n\t"n\u00e9zet (view)"\t= csak megfigyel\u0151 (de a friss\u00edt\u00e9s gyakoris\u00e1g\u00e1t m\u00f3dos\u00edthatja) webui.access=Hozz\u00e1f\u00e9r\u00e9s (*) webui.access.info=A hozz\u00e1f\u00e9r\u00e9s lehet\n\t"helyi (local)"\t= vagyis csak a helyi sz\u00e1m\u00edt\u00f3g\u00e9p haszn\u00e1lhatja\n\t"mind (all)"\t= alap\u00e9rtelmezett korl\u00e1tlan hozz\u00e1f\u00e9r\u00e9s\n\tIP\t= pl. 192.168.0.2\t\t\tcsak egy IP-c\u00edmr\u0151l\n\tIP1-IP2\t= pl. 192.168.0.1-192.168.0.255\tcsak egy IP-tartom\u00e1nyb\u00f3l GeneralView.label.maxdownloadspeed=Max Let\u00f6lt\u00e9s Security.keystore.corrupt='%1' kulcst\u00e1r bet\u00f6lt\u00e9se sikertelen, k\u00e9rem t\u00f6r\u00f6lje, \u00e9s hozza l\u00e9tre/import\u00e1lja \u00fajra a tan\u00fas\u00edtv\u00e1nyt. Security.keystore.empty=Kulcst\u00e1r \u00fcres. K\u00e9rem, hozzon l\u00e9tre saj\u00e1t al\u00e1\u00edrt tan\u00fas\u00edtv\u00e1nyt (ld. Be\u00e1ll\u00edt\u00e1sok -> Biztons\u00e1g) vagy import\u00e1ljon egyet '%1'-be. webui.restart.info=A (*)-al jel\u00f6lt param\u00e9terek v\u00e1ltoz\u00e1sai csak \u00fajraind\u00edt\u00e1s ut\u00e1n l\u00e9pnek \u00e9rv\u00e9nybe GeneralView.label.maxdownloadspeed.tooltip=Let\u00f6lt\u00e9s maxim\u00e1lis sebess\u00e9ge [0: korl\u00e1tlan] upnp.enable=UPnP Enged\u00e9lyez\u00e9se upnp.info=Az Univerz\u00e1lis Plug and Play (UPnP) lehet\u0151v\u00e9 teszi a portok automatikus \u00e1tir\u00e1ny\u00edt\u00e1s\u00e1t az UPnP-k\u00e9pes \u00fatvonalv\u00e1laszt\u00f3kon (router). upnp.mapping.dataport=Bej\u00f6v\u0151 \u00fcgyf\u00e9l adatport upnp.alert.differenthost=UPnP: '%1' c\u00e9lport '%2' sz\u00e1m\u00e1ra van fenntartva - v\u00e1lasszon m\u00e1sik portot upnp.alert.mappingok=UPnP: '%1' kioszt\u00e1s sikeres upnp.alert.mappingfailed=UPnP: '%1' kioszt\u00e1sa sikertelen upnp.alertsuccess=Jelentse a sikeres kioszt\u00e1sokat upnp.alert.lostdevice=UPnP: Elvesztettem a kapcsolatot '%1' szolg\u00e1ltat\u00e1ssal a '%2' UPnP eszk\u00f6z\u00f6n upnp.grabports=Akkor is ossza ki a portot, ha azt m\u00e1s sz\u00e1m\u00edt\u00f3g\u00e9p haszn\u00e1lja upnp.refresh.label=Kioszt\u00e1sok friss\u00edt\u00e9se upnp.refresh.button=Friss\u00edt upnp.alert.mappinggrabbed=UPnP: '%1' kioszt\u00e1s sikeres - \u00e1tvette '%2'-t\u0151l upnp.alertothermappings=Jelentse a m\u00e1s sz\u00e1m\u00edt\u00f3g\u00e9pek \u00e1ltal haszn\u00e1lt portokat upnp.alertdeviceproblems=Jelentse az UPnP eszk\u00f6zzel felmer\u00fclt probl\u00e9m\u00e1kat upnp.trace_to_log=Kimeneti hibainform\u00e1ci\u00f3 a napl\u00f3ba upnp.wiki_link=Vuze Wiki oldal az UPnP-r\u0151l upnp.refresh_mappings_on_bad_nat=Automatikusan friss\u00edti a c\u00edmford\u00edt\u00e1st, ha a NAT \u00e1llapota "T\u0171zfal m\u00f6g\u00fcl" ConfigView.pluginlist.coreplugins=Az al\u00e1bbi be\u00e9p\u00edtett plugin vannak bet\u00f6ltve: Peers.column.DLedFromOthers=M\u00e1sokt\u00f3l Peers.column.DLedFromOthers.info=M\u00e1sok \u00e1ltal t\u0151led let\u00f6lt\u00f6tt adatmennyis\u00e9g Peers.column.UpDownRatio=Fel:Le Peers.column.UpDownRatio.info=\u00dcgyf\u00e9l "Let\u00f6lt\u00f6tt : Felt\u00f6lt\u00f6tt" adatainak ar\u00e1nya Peers.column.UpRatio=Felt\u00f6lt\u00e9si Ar\u00e1ny Peers.column.UpRatio.info=\u00dcgyf\u00e9l "T\u0151l\u00fcnk fogadott : M\u00e1sokt\u00f3l fogadott" adatainak ar\u00e1nya upnp.releasemappings=Kioszt\u00e1s t\u00f6rl\u00e9se bez\u00e1r\u00e1skor webui.upnpenable=UPnP enged\u00e9lyez\u00e9se ezen a porton (*) ConfigView.section.file.friendly.hashchecking=K\u00edm\u00e9l\u0151 adatellen\u0151rz\u00e9s ConfigView.section.file.friendly.hashchecking.tooltip=Kicsit lassabban ellen\u0151ri le a szeleteket, de a processzort \u00e9s a rendszert kev\u00e9sb\u00e9 terheli. ConfigView.section.tracker.seedretention=Torrentenk\u00e9nt maximum ennyi seeder elfogad\u00e1sa [0: korl\u00e1tlan] ConfigView.section.tracker.seedretention.info=Megjegyz\u00e9s: az elvetett k\u00e9szforr\u00e1sok ut\u00e1ni felt\u00f6lt\u00e9si statisztik\u00e1k elvesznek ConfigView.section.tracker.port=Tracker enged\u00e9lyez\u00e9se a HTTP porton ConfigView.section.tracker.sslport=Tracker enged\u00e9lyez\u00e9se a HTTPS porton ConfigView.section.tracker.publicenable.info=\u00cdgy lehet\u0151v\u00e9 v\u00e1lik m\u00e1sok sz\u00e1m\u00e1ra, hogy ezt a trackert haszn\u00e1lj\u00e1k,\nde a torrent f\u00e1jlokat ne azon t\u00e1rolj\u00e1k/tegy\u00e9k k\u00f6zz\u00e9. Button.clear=T\u00f6r\u00f6l MainWindow.IPs.tooltip=Utolj\u00e1ra friss\u00edtett filterlista: %1\n Az \u00f6sszes IPFilter a list\u00e1ban - Blokkolt/bannolt/rossz IP-k.\nDupla kattint\u00e1s a r\u00e9szletek\u00e9rt ConfigView.section.ipfilter.list.banned=tiltva ConfigView.section.ipfilter.list.baddata=hib\u00e1s adatokat k\u00fcld\u00f6tt: gyakoris\u00e1g = ConfigView.section.ipfilter.bannedinfo=Hib\u00e1s adatokat k\u00fcld\u0151 IP-k - adott t\u0171r\u00e9shat\u00e1r felett tilt\u00f3list\u00e1ra ker\u00fclnek ConfigView.section.ipfilter.blockedinfo=Sz\u0171r\u0151list\u00e1n lev\u0151, \u00edgy felt\u00e9tel n\u00e9lk\u00fcl blokkolt IP c\u00edmek download.removerules.name=T\u00f6rl\u00e9si szab\u00e1lyok download.removerules.unauthorised.info=Egy torrent jogtalan, ha az adatv\u00e1lt\u00e1s k\u00f6vet\u0151en a tracker "nem azonos\u00edthat\u00f3" vagy "nem jogosult" (unauthorized) v\u00e1laszt ad, vagy hib\u00e1san v\u00e1laszol download.removerules.unauthorised=Jogtalan torrentek automatikus t\u00f6rl\u00e9se download.removerules.unauthorised.seedingonly=\tCsak ha m\u00e1r elk\u00e9sz\u00fclt download.removerules.removed.ok=A T\u00f6rl\u00e9si Szab\u00e1lyok \u00e9rtelm\u00e9ben '%1' darab torrent sikeresen elt\u00e1vol\u00edtva. download.removerules.updatetorrents=Automatikusan t\u00f6r\u00f6lje az Vuze friss\u00edt\u00e9s\u00e9re szolg\u00e1l\u00f3 torrenteket, ha a boly megk\u00f6veteli ConfigView.label.defaultstarttorrentsstopped=Az \u00faj torrentek nem indulnak el ConfigView.section.server.enableudp=UDP kliens tracker protokoll enged\u00e9lyez\u00e9se upnp.mapping.dataportudp=UDP tracker \u00fcgyf\u00e9l port ConfigView.section.file.decoder.showlax=Mutassa a kev\u00e9sb\u00e9 kedvelt k\u00f3dol\u00e1si lehet\u0151s\u00e9geket ConfigView.section.file.decoder.showall=Vizsg\u00e1ljon meg minden k\u00f3dol\u00e1si lehet\u0151s\u00e9get MainWindow.status.updowndetails.tooltip=Let\u00f6lt\u00e9si/Felt\u00f6lt\u00e9si sebess\u00e9g r\u00e9szletez\u00e9se\nJobb klikk a v\u00e1ltoztat\u00e1shoz, Dupla kattint\u00e1s a statisztika megnyit\u00e1s\u00e1hoz TrackerClient.announce.warningmessage='%1' tracker '%2' figyelmeztet\u00e9st k\u00fcld\u00f6tt ConfigView.section.tracker.natcheckenable=Bej\u00f6v\u0151 port ellen\u0151rz\u00e9se \u00e9s hiba jelent\u00e9s az \u00fcgyfelek fel\u00e9 ConfigView.section.tracker.publishenabledetails=A torrent minden tulajdons\u00e1g\u00e1nak k\u00f6zz\u00e9t\u00e9tele ConfigView.section.tracker.publishenablepeerdetails=\u00dcgyf\u00e9ladatok k\u00f6zz\u00e9t\u00e9tele MyTrackerView.badnat=Hib\u00e1s NAT MyTrackerView.badnat.info=K\u00e9szforr\u00e1sok/\u00dcgyfelek akikn\u00e9l nem siker\u00fclt a NAT ellen\u0151rz\u00e9s, ha be van kapcsolva ConfigView.section.tracker.natchecktimeout=Ellen\u0151rz\u00e9s id\u0151t\u00fall\u00e9p\u00e9se (mp) ConfigView.section.file.perf.cache.enable=\u00c1tmeneti t\u00e1r enged\u00e9lyez\u00e9se ConfigView.section.file.perf.cache.size=Az \u00e1tmeneti mem\u00f3riat\u00e1r m\u00e9rete %1-ban #Removed #MyTorrentsView.menu.setSpeed=Set Upload Speed MainWindow.menu.transfers=\u00c1t&vitel MainWindow.menu.transfers.startalltransfers=\u00d6sszes ind\u00edt&\u00e1sa MainWindow.menu.transfers.stopalltransfers=\u00d6sszes meg\u00e1ll\u00edt&\u00e1sa MainWindow.menu.transfers.pausetransfers=Sz\u00fcnet MainWindow.menu.transfers.resumetransfers=&Folytat ConfigView.label.experimental.osx.kernel.panic.fix=K\u00eds\u00e9rleti jav\u00edt\u00e1s a k\u00e9tprocesszoros OSX rendszerek alatt tapasztalhat\u00f3 kernel\u00f6sszeoml\u00e1sokra [\u00fajraind\u00edt\u00e1s sz\u00fcks\u00e9ges] SystemTray.menu.pausetransfers=\u00c1tvitel sz\u00fcneteltet\u00e9se SystemTray.menu.resumetransfers=\u00c1tvitel folytat\u00e1sa ConfigView.section.file.truncate.too.large=Nagy f\u00e1jlok visszav\u00e1g\u00e1sa ConfigView.section.file.perf.cache.trace=\u00c1tmeneti t\u00e1r m\u0171veleteinek diagnosztikai napl\u00f3z\u00e1sa ConfigView.section.interface.enabletray=T\u00e1lcaikon enged\u00e9lyez\u00e9se [\u00fajraind\u00edt\u00e1st ig\u00e9nyel] PeerManager.status.error=Hiba Stats.title.full=Statisztika TransferStatsView.title.full=\u00c1tvitelek CacheView.title.full=\u00c1tmeneti t\u00e1r CacheView.general.size=Teljes m\u00e9ret CacheView.general.inUse=Haszn\u00e1latban CacheView.general.title=\u00c1tmeneti t\u00e1r inf\u00f3 CacheView.reads.title=I/O Olvas\u00e1s CacheView.reads.fromFile=F\u00e1jlb\u00f3l CacheView.reads.fromCache=\u00c1tmeneti t\u00e1rb\u00f3l CacheView.reads.hits=Tal\u00e1latok CacheView.writes.title=I/O \u00cdr\u00e1s CacheView.writes.toCache=\u00c1tmeneti t\u00e1rba CacheView.writes.toFile=F\u00e1jlba CacheView.writes.hits=Elmentve CacheView.speeds.title=Adatsebess\u00e9g CacheView.speeds.reads=Olvas\u00e1s CacheView.speeds.writes=\u00cdr\u00e1s CacheView.speeds.fromCache=\u00c1tmeneti t\u00e1rba/-b\u00f3l CacheView.speeds.fromFile=F\u00e1jlba/-b\u00f3l CacheView.reads.amount=Mennyis\u00e9g CacheView.reads.avgsize=\u00c1tlagos m\u00e9ret openUrl.referrer=Hivatkoz\u00f3 oldal URL c\u00edme : openUrl.referrer.info=Csak azon oldalakn\u00e1l sz\u00fcks\u00e9ges, melyek megk\u00f6vetelik ConfigView.label.maxuploadspeedseeding=Csak felt\u00f6lt\u00e9s eset\u00e9n ConfigView.label.transfer.ignorepeerports=Mell\u0151zze az al\u00e1bbi portokat haszn\u00e1l\u00f3 \u00fcgyfeleket (';'-tall elv\u00e1lasztva, pl.: 0;25) ConfigView.section.proxy.enable_socks.peer=Proxy enged\u00e9lyez\u00e9se a peerekkel val\u00f3 (csak kimen\u0151 kapcsolatokhoz) kommunik\u00e1ci\u00f3ra [\u00fajraind\u00edt\u00e1s sz\u00fcks\u00e9ges] ConfigView.section.proxy.peer.informtracker=Tracker t\u00e1j\u00e9koztat\u00e1sa a korl\u00e1toz\u00e1sokr\u00f3l ConfigView.section.proxy.socks.version=SOCKS verzi\u00f3 PiecesView.legend.written=Ki\u00edrva PiecesView.legend.requested=K\u00e9rve PiecesView.legend.downloaded=Let\u00f6ltve, ki\u00edr\u00e1sra v\u00e1r PiecesView.legend.incache=\u00c1tmeneti Mem\u00f3ri\u00e1ban PiecesView.typeItem.0=Lass\u00fa PiecesView.typeItem.1=Gyors PiecesView.type=T\u00edpus Security.jar.tools_not_found=JAR hiteles\u00edt\u00e9s sikertelen - 'tools.jar' nem tal\u00e1lhat\u00f3 %1 mapp\u00e1ban. Ld. Eszk\u00f6z\u00f6k->Be\u00e1ll\u00edt\u00e1sok->Biztons\u00e1g. Security.jar.signfail=JAR hiteles\u00edt\u00e9s sikertelen - %1 ConfigView.section.security.toolsinfo=A hiteles\u00edtett JAR f\u00e1jlok be\u00e1ll\u00edt\u00e1st\u00f3l f\u00fcgg\u0151en bizonyos b\u0151v\u00edtm\u00e9nyek kiszolg\u00e1l\u00e1s\u00e1ra k\u00e9sz\u00fcltek.\nJAR f\u00e1jlok hiteles\u00edt\u00e9s\u00e9hez sz\u00fcks\u00e9g van a 'tools.jar' \u00e1llom\u00e1nyra, mely a Sun JDK (nem JRE) telep\u00edt\u00e9s r\u00e9sze.\nHa csak a JRE-t telep\u00edtette, k\u00e9rj\u00fck, telep\u00edtse a JDK (Java Developers' Kit)-t is.\nVuze \u00e1ltal\u00e1ban mag\u00e1t\u00f3l is megtal\u00e1lja az \u00e1llom\u00e1nyt. Ha nem, akkor itt \u00e1ll\u00edthatja be az azt tartalmaz\u00f3 mappa nev\u00e9t. ConfigView.section.security.toolsdir='tools.jar'-t tartalmaz\u00f3 mappa ConfigView.section.security.choosetoolssavedir=Adja meg a 'tools.jar'-t tartalmaz\u00f3 mappa hely\u00e9t ConfigView.section.proxy.peer.same=Anazon proxy be\u00e1ll\u00edt\u00e1sok haszn\u00e1lata a tracker \u00e9s az \u00fcgyfelek fel\u00e9 ConfigView.section.connection.network.max.simultaneous.connect.attempts=Egyidej\u0171leg kezdem\u00e9nyezhet\u0151 kimen\u0151 kapcsolatok ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Vuze maximum ennyi kimen\u0151 kapcsolat l\u00e9tes\u00edt\u00e9s\u00e9vel pr\u00f3b\u00e1lkozik egyszerre.\nMEGJEGYZ\u00c9S: A Windows XP 2-es jav\u00edt\u00f3csomag alapbe\u00e1ll\u00edt\u00e1sa 10.\nVuze javasolt alapbe\u00e1ll\u00edt\u00e1sa 8. ConfigView.section.file.perf.cache.size.explain=Az \u00e1tmeneti mem\u00f3riat\u00e1r a lemezm\u0171veleteket hivatott cs\u00f6kkenteni. "-XX: MaxDirectMemorySize" JAVA kapcsol\u00f3 eset\u00e9n ne adj meg a teljes rendelkez\u00e9sre \u00e1ll\u00f3 virtu\u00e1lis mem\u00f3ria m\u00ednusz %1-n\u00e1l nagyobb \u00e9rt\u00e9ket. A jelenleg rendelkez\u00e9sre \u00e1ll\u00f3 virtu\u00e1lis mem\u00f3ria: %2. Ennek megv\u00e1ltoztat\u00e1s\u00e1hoz keresd fel a 'wiki' oldal (%3) Memory Usage r\u00e9sz\u00e9t. A hib\u00e1s be\u00e1ll\u00edt\u00e1sok mem\u00f3riat\u00falcsordul\u00e1shoz vezethetnek. T\u00f6bb, mint 32MB \u00e1tmeneti t\u00e1r \u00e1ltal\u00e1ban a rendszer azonnali \u00f6sszeoml\u00e1s\u00e1hoz vezet. MyTorrentsView.menu.setSpeed.unlimit=Nincs limit MyTorrentsView.menu.setSpeed.unlimited=Korl\u00e1tlan MyTorrentsView.menu.setSpeed.disable=Felt\u00f6lt\u00e9s Kikapcsol\u00e1sa MyTorrentsView.menu.setSpeed.disabled=Letiltva MyTorrentsView.menu.setSpeed.in=-ben MyTorrentsView.menu.setSpeed.slots=sz\u00e1lak GeneralView.label.maxuploadspeed=Max Fel GeneralView.label.maxuploadspeed.tooltip=maxim\u00e1lis felt\u00f6lt\u00e9si sebess\u00e9g [0 : korl\u00e1tlan] MyTorrents.items.UpSpeedLimit.disabled=Nincs felt\u00f6lt\u00e9s MyTorrents.items.UpSpeedLimit.unlimited=Korl\u00e1tlan TableColumn.header.maxupspeed=Max Felt\u00f6lt\u00e9si Sebess\u00e9g TableColumn.header.maxupspeed.info=Max Felt\u00f6lt\u00e9si Sebess\u00e9g torrentenk\u00e9nt ConfigView.section.file.perf.cache.enable.write=Gyors\u00edt\u00f3t\u00e1razza a let\u00f6lt\u00f6tt adatokat, hogy cs\u00f6kkenjen a lemezre \u00edr\u00e1sok \u00e9s olvas\u00e1sok sz\u00e1ma a szeletek ellen\u0151rz\u00e9s\u00e9n\u00e9l ConfigView.section.file.perf.cache.enable.read=Felt\u00f6lt\u00e9skor v\u00e9gezzen el\u0151olvas\u00e1st a lemezm\u0171veletek cs\u00f6kkent\u00e9se \u00e9rdek\u00e9ben ConfigView.section.tracker.separatepeerids=Elt\u00e9r\u0151 szem\u00e9lyazonoss\u00e1g haszn\u00e1lata a tracker \u00e9s az \u00fcgyfelek fel\u00e9 ConfigView.section.tracker.separatepeerids.info=Nagyobb n\u00e9vtelens\u00e9get biztos\u00edt n\u00e9vtelen let\u00f6lt\u00e9s \u00e9s k\u00e9szforr\u00e1s eset\u00e9n\nmik\u00f6zben a tracker fel\u00e9 fel kell fedni a kil\u00e9t\u00e9t ConfigView.section.interface.wavlocation=WAV f\u00e1jl helye ConfigView.section.interface.wavlocation.info=Adj meg egy .wav f\u00e1jlt, vagy hagyd \u00fcresen a mez\u0151t ConfigView.section.tracker.server=Szerver ConfigView.section.tracker.client=Kliens ConfigView.section.tracker.client.connecttimeout=Kapcsolat id\u0151t\u00fall\u00e9p\u00e9se (mp) ConfigView.section.tracker.client.readtimeout=Olvas\u00e1s id\u0151t\u00fall\u00e9p\u00e9se (mp) MainWindow.menu.tools=&Eszk\u00f6z\u00f6k FilesView.path=\u00datvonal FilesView.fullpath=Teljes \u00fatvonal mutat\u00e1sa FilesView.remaining=H\u00e1tralev\u0151 szeletek TableColumn.header.trackername=Tracker Neve TableColumn.header.trackername.info=A szerver neve a c\u00edme (URL) alapj\u00e1n ConfigView.group.override=Fel\u00fclb\u00edr\u00e1l\u00e1s be\u00e1ll\u00edt\u00e1sai ConfigView.section.file.perf.cache.notsmallerthan=Enn\u00e9l kisebb m\u00e9ret\u0171 f\u00e1jlokat ne gyors\u00edt\u00f3t\u00e1razza (%1-ban) PeersView.menu.blockupload=Felt\u00f6lt\u00e9s Blokkol\u00e1sa PeersView.menu.kickandban=Kir\u00fag \u00e9s Kitilt PeersView.menu.kickandban.reason=Az \u00dcgyf\u00e9l k\u00e9zzel tiltva PeersView.state=\u00c1llapot PeersView.state.info=\u00dcgyf\u00e9lkapcsolatok \u00e1llapota PeersView.state.pending=F\u00fcgg\u0151ben PeersView.state.connecting=Kapcsol\u00f3d\u00e1s PeersView.state.handshake=K\u00e9zfog\u00e1sra v\u00e1rok PeersView.state.established=Teljesen l\u00e9trej\u00f6tt ConfigView.section.tracker.processinglimits=Feldolgoz\u00e1si hat\u00e1r ConfigView.section.tracker.maxgettime=GET (fogad\u00e1s) maxim\u00e1lis v\u00e1rakoz\u00e1si ideje (mp) [0: korl\u00e1tlan] ConfigView.section.tracker.maxgettime.info=Bejelent\u00e9sekhez \u00e9s lek\u00e9rdez\u00e9sekhez ConfigView.section.tracker.maxposttimemultiplier=GET id\u0151szorz\u00f3 POST m\u0171velethez [0: korl\u00e1tlan] ConfigView.section.tracker.maxposttimemultiplier.info=K\u00f6zz\u00e9t\u00e9telhez \u00e9s felt\u00f6lt\u00e9shez ConfigView.section.tracker.maxthreads=Egyidej\u0171 k\u00e9relmek maxim\u00e1lis sz\u00e1ma DownloadManager.error.operationcancancelled=M\u0171velet megszak\u00edtva Torrent.create.progress.cancelled=M\u0171velet megszak\u00edtva sharing.progress.cancel=M\u00e9gsem wizard.maketorrents.autoopen=Torrent megnyit\u00e1sa k\u00e9szforr\u00e1sk\u00e9nt, ha v\u00e9gzett ConfigView.section.sharing.rescanenable=Megosztott anyagok rendszeres \u00fajravizsg\u00e1l\u00e1s\u00e1nak enged\u00e9lyez\u00e9se ConfigView.section.sharing.rescanperiod=\u00dajravizsg\u00e1l\u00e1s gyakoris\u00e1ga (mp) ConfigView.section.connection.advanced=Halad\u00f3 H\u00e1l\u00f3zati Be\u00e1ll\u00edt\u00e1sok ConfigView.section.connection.advanced.url=Let\u00f6lt\u00e9si sebess\u00e9g f\u00fakusz\u00e1l\u00e1sa a let\u00f6lt\u00e9si sor elej\u00e9re, ha a sebess\u00e9g el\u00e9rte a let\u00f6lt\u00e9si korl\u00e1tot ConfigView.section.connection.advanced.mtu=Maxim\u00e1lis \u00c1tviteli Egys\u00e9g (MTU) ConfigView.section.connection.advanced.mtu.tooltip=Egy keretben \u00e1tvihet\u0151 adat maxim\u00e1lis m\u00e9rete.\nVuze MTU-40 (MSS)-t haszn\u00e1l az optim\u00e1lis felt\u00f6lt\u00e9si csomag el\u00e9r\u00e9s\u00e9hez.\nAj\u00e1nlott \u00e9rt\u00e9kek:\n 576 - Bet\u00e1rcs\u00e1z\u00f3s kapcsolatokhoz\n1492 - PPPoE sz\u00e9less\u00e1v\u00fa kapcsolatokhoz\n1500 - Ethernet, DSL \u00e9s K\u00e1bel alap\u00fa sz\u00e9less\u00e1v\u00fa kapcsolatokhoz ConfigView.section.connection.advanced.SO_RCVBUF=SO_RCVBUF socket m\u00e9rete [0: OP rendszer alap\u00e9rt\u00e9ke] ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Az alap SO_RCVBUF socket m\u00e9ret\u00e9nek be\u00e1ll\u00edt\u00e1sa (b\u00e1jtban), pl.: TCP fogad\u00e1si keret m\u00e9rete \u00e9s sk\u00e1l\u00e1zhat\u00f3s\u00e1ga.\nVuze alapesetben nem haszn\u00e1lja, ekkor az oper\u00e1ci\u00f3s rendszer haszn\u00e1lja.\nMEGJEGYZ\u00c9S: a Linux megdupl\u00e1zza a megadott \u00e9rt\u00e9ket. ConfigView.section.connection.advanced.SO_SNDBUF=SO_SNDBUF socket m\u00e9rete [0: OP rendszer alap\u00e9rt\u00e9ke] ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Az alap SO_SNDBUF socket m\u00e9ret\u00e9nek be\u00e1ll\u00edt\u00e1sa (b\u00e1jtban), pl.: TCP k\u00fcld\u00e9si keret m\u00e9rete.\nVuze alapesetben nem haszn\u00e1lja, ekkor az oper\u00e1ci\u00f3s rendszer \u00e1l\u00edtja be.\nMEGJEGYZ\u00c9S: a Linux megdupl\u00e1zza a megadott \u00e9rt\u00e9ket. ConfigView.section.connection.advanced.IPDiffServ=Kimen\u0151 csomagok DiffServ \u00e9rt\u00e9ke (TOS mez\u0151) ConfigView.section.connection.advanced.IPDiffServ.tooltip=Be\u00e1ll\u00edtja a DiffServ r\u00e9szt a type-of-service (TOS) mez\u0151ben az IP csomagok fejl\u00e9c\u00e9ben.\nHexadecim\u00e1lis sz\u00e1mot lehet haszn\u00e1lni '0x kezdve', pl. 0x10.\nA Vuze nem haszn\u00e1lja ezt az \u00e9rt\u00e9ket alapbe\u00e1ll\u00edt\u00e1sban, vagyis az OS \u00e1ll\u00edtja be.\nNOTE: A h\u00e1l\u00f3zat figyelmen k\u00edv\u00fcl hagyhatja ezt az \u00e9rt\u00e9ket, teh\u00e1t nagyban f\u00fcgg az OS \u00e9s a JRE verzi\u00f3kt\u00f3l. ConfigView.section.interface.confirm_torrent_removal=Meger\u0151s\u00edt\u00e9s k\u00e9r\u00e9se torrent elt\u00e1vol\u00edt\u00e1sakor ConfigView.section.interface.confirm_torrent_removal.tooltip=A program meger\u0151s\u00edt\u00e9st k\u00e9r, ha a Torrentjeim list\u00e1b\u00f3l el akarsz t\u00e1vol\u00edtanie egy torrentet MyTorrentsView.confirm_torrent_removal=Val\u00f3ban el akarja t\u00e1vol\u00edtani?\n TableColumn.header.seed_to_peer_ratio=Seed/Peer Ar\u00e1ny TableColumn.header.seed_to_peer_ratio.info=A boly teljes felt\u00f6lt\u0151k/let\u00f6lt\u0151k ar\u00e1nya PeersView.connected_time=Kapcsolat Ideje PeersView.connected_time.info=Ennyi ideje kapcsol\u00f3dik az \u00fcgyf\u00e9lhez ConfigView.section.interface.display.add_torrents_silently=Torrentek hozz\u00e1ad\u00e1sa a h\u00e1tt\u00e9rben ConfigView.section.interface.display.add_torrents_silently.tooltip=Torrentek hozz\u00e1ad\u00e1sa Vuze f\u0151ablak\u00e1nak megnyit\u00e1sa n\u00e9lk\u00fcl. TableColumn.header.maxdownspeed=Max Let\u00f6lt\u00e9si Sebess\u00e9g TableColumn.header.maxdownspeed.info=Max Let\u00f6lt\u00e9si Sebess\u00e9g torrentenk\u00e9nt PeersGraphicView.title=Boly ConfigView.section.tracker.passwordwebhttpsonly=Csak HTTPS-en kereszt\u00fcl \u00e9rkez\u0151 kapcsolatok enged\u00e9lyez\u00e9se TableColumn.header.torrentpath=Torrent Helye TableColumn.header.torrentpath.info=A torrent helye a lemezen ConfigView.section.sharing.torrentcomment=Megjegyz\u00e9s hozz\u00e1ad\u00e1sa a l\u00e9trehozott torrentekhez ConfigView.label.copyanddeleteratherthanmove=El\u0151sz\u00f6r m\u00e1solja, majd t\u00f6r\u00f6lje az eredeti adatokat egyetlen f\u00e1jlm\u0171velet helyett - elker\u00fclheted az adatveszt\u00e9st bizonyos f\u00e1jlrendszereken. ConfigView.label.openstatsonstart=Statisztika megnyit\u00e1sa ind\u00edt\u00e1skor swt.install.window.title=Vuze B\u0151v\u00edtm\u00e9ny Telep\u00edt\u0151 swt.install.window.ok=Telep\u00edt\u00e9s swt.install.window.header=A k\u00f6vetkez\u0151 \u00f6sszetev\u0151ket jel\u00f6lte ki telep\u00edt\u00e9sre : swt.uninstall.window.title=Vuze B\u0151v\u00edtm\u00e9ny Elt\u00e1vol\u00edt\u00f3 swt.uninstall.window.ok=Elt\u00e1vol\u00edt\u00e1s swt.uninstall.window.header=A k\u00f6vetkez\u0151 \u00f6sszetev\u0151ket jel\u00f6lte ki elt\u00e1vol\u00edt\u00e1sra : installPluginsWizard.title=Pluginek Telep\u00edt\u00e9se installPluginsWizard.mode.title=K\u00e9rem v\u00e1lassza ki a telep\u00edt\u00e9s m\u00f3dj\u00e1t installPluginsWizard.mode.list=sourceforge.net list\u00e1j\u00e1b\u00f3l installPluginsWizard.list.title=Telep\u00edthet\u0151 Pluginek installPluginsWizard.list.loading=K\u00e9rem v\u00e1rjon, am\u00edg a plugin bet\u00f6lt\u00e9se zajlik. installPluginsWizard.list.loaded=V\u00e1laszd ki a telep\u00edteni k\u00edv\u00e1nt plugint. installPluginsWizard.list.name=N\u00e9v installPluginsWizard.list.version=Verzi\u00f3 installPluginsWizard.list.description=Plugin le\u00edr\u00e1sa installPluginsWizard.finish.title=Telep\u00edt\u00e9s folyamatban installPluginsWizard.finish.explanation=A Friss\u00edt\u00e9s Seg\u00e9d telep\u00edteni fogja a kiv\u00e1lasztott b\u0151v\u00edtm\u00e9nyt.\n\nKis t\u00fcrelmet, ez eltarthat egy darabig.\n\nA folyamatjelz\u0151 bal sz\u00e9l\u00e9re kattintva megjelen\u00edtheti a pillanatnyi \u00e1llapotot. installPluginsWizard.details.loading=R\u00e9szletek t\u00f6lt\u00e9se, k\u00e9rem v\u00e1rjon... installPluginsWizard.mode.file=F\u00e1jlb\u00f3l installPluginsWizard.installMode.title=K\u00e9rem v\u00e1lassza ki a telep\u00edt\u00e9s t\u00edpus\u00e1t installPluginsWizard.installMode.user=A b\u0151v\u00edtm\u00e9ny(ek) telep\u00edt\u00e9se csak nekem installPluginsWizard.installMode.shared=A plugin(ek) telep\u00edt\u00e9se mindenki sz\u00e1m\u00e1ra installPluginsWizard.file.title=Jel\u00f6ld ki a telep\u00edteni k\u00edv\u00e1nt plugint installPluginsWizard.file.file=F\u00e1jl : installPluginsWizard.file.invalidfile=A f\u00e1jl nem Vuze plugin. installPluginsWizard.file.no_such_file=A megadott nev\u0171 f\u00e1jl nem l\u00e9tezik. installPluginsWizard.file.browse=Tall\u00f3z\u00e1s... uninstallPluginsWizard.title=B\u0151v\u00edtm\u00e9nyek elt\u00e1vol\u00edt\u00e1sa uninstallPluginsWizard.list.title=Telep\u00edtett b\u0151v\u00edtm\u00e9nyek uninstallPluginsWizard.list.loaded=K\u00e9rem v\u00e1lassza ki az elt\u00e1vol\u00edtani k\u00edv\u00e1nt b\u0151v\u00edtm\u00e9nyt. installPluginsWizard.list.nullversion=Verzi\u00f3 n\u00e9lk\u00fcl uninstallPluginsWizard.finish.title=Elt\u00e1vol\u00edt\u00e1s folyamatban uninstallPluginsWizard.finish.explanation=A kiv\u00e1lasztott b\u0151v\u00edtm\u00e9ny elt\u00e1vol\u00edt\u00e1sa a Friss\u00edt\u00e9s Seg\u00e9ddel. MainWindow.menu.plugins.installPlugins=Telep\u00edt\u00e9s Var\u00e1zsl\u00f3... MainWindow.menu.plugins.uninstallPlugins=Elt\u00e1vol\u00edt\u00e1s Var\u00e1zsl\u00f3... ConfigView.section.ipfilter.totalIPs=\u00d6sszesen %1 IP-c\u00edm blokkolva, ami az internet %2-\u00e1t teszi ki. update.instance.install=Telep\u00edt\u00e9s ellen\u0151rz\u00e9se update.instance.uninstall=Elt\u00e1vol\u00edt\u00e1s ellen\u0151rz\u00e9se update.instance.update=Friss\u00edt\u00e9sek ellen\u0151rz\u00e9se MainWindow.status.update.tooltip=Kattints dupl\u00e1n a folyamat megjelen\u00edt\u00e9s\u00e9hez updater.progress.window.title=Jelenlegi telep\u00edt\u00e9si folyamatok updater.progress.window.info=Nyomja meg a 'Megszak\u00edt' gombot a beragadt feladatok le\u00e1ll\u00edt\u00e1s\u00e1hoz Button.abort=Megszak\u00edt\u00e1s ConfigView.section.ipfilter.enablebanning=A folyamatosan hib\u00e1s adatokat k\u00fcld\u0151 \u00fcgyfelek blokkol\u00e1sa Network.alert.acceptfail=T\u00fal sok egym\u00e1st k\u00f6vet\u0151 hiba a %1 porton, %2 - m\u0171velet elvetve. K\u00e9rem ellen\u0151rizze a t\u0171zfal be\u00e1ll\u00edt\u00e1sait a bej\u00f6v\u0151 kapcsolatok enged\u00e9lyez\u00e9se \u00e9rdek\u00e9ben. MyShares.column.category=Kateg\u00f3ria UpdateWindow.restartLater=\u00dajraind\u00edt\u00e1s k\u00e9s\u0151bb MainWindow.menu.file.restart=Vuze \u00dajraind\u00edt\u00e1sa MainWindow.dialog.restartconfirmation.title=Vuze \u00fajraind\u00edt\u00e1sa? MainWindow.dialog.restartconfirmation.text=\u00dajra akarja ind\u00edtani az Azureust? deletetorrent.message1=TORRENT t\u00f6rl\u00e9se :\n deletetorrent.message2=\nBiztos t\u00f6rl\u00f6d? ConfigView.label.prioritizemostcompletedfiles=Magas priorit\u00e1s\u00fa f\u00e1jlok rangsorol\u00e1sa a f\u00e1jl m\u00e9rete \u00e9s a let\u00f6lt\u00e9s \u00e1llapota szerint splash.plugin.init=B\u0151v\u00edtm\u00e9ny el\u0151k\u00e9sz\u00edt\u00e9se: splash.plugin.UIinit=B\u0151v\u00edtm\u00e9ny GUI ind\u00edt\u00e1sa: %1 ConfigView.section.style.osx_small_fonts=Kis bet\u00fck haszn\u00e1lata [\u00fajraind\u00edt\u00e1s sz\u00fcks\u00e9ges] ConfigView.section.tracker.tcpnonblocking=Nem-blokkol\u00f3 I/O haszn\u00e1lata a TCP tracker m\u0171veletekhez. Enged\u00e9lyez\u00e9s\u00e9hez a webes trackert k\u00fcl\u00f6n porton kell futtatni. K\u00eds\u00e9rleti! ConfigView.section.tracker.nonblocking=Nem-blokkol\u00f3 be\u00e1ll\u00edt\u00e1sok ConfigView.section.tracker.nonblockingconcmax=Max egyidej\u0171 kapcsolatok [0: korl\u00e1tlan] MyTorrentsView.menu.exportmenu=Export\u00e1l\u00e1s ConfigView.group.scrape=V\u00e9gigk\u00e9rdez\u00e9s ConfigView.section.tracker.client.scrapeinfo=A v\u00e9gigk\u00e9rdez\u00e9s letilt\u00e1sa t\u00f6bb olyan v\u00e1rosor szab\u00e1lyt letilt , melyek a bolyr\u00f3l \u00edgy nyert inform\u00e1ci\u00f3n alapulnak ConfigView.section.tracker.client.scrapeenable=V\u00e9gigk\u00e9rdez\u00e9s enged\u00e9lyez\u00e9se ConfigView.section.tracker.client.scrapestoppedenable=Nem fut\u00f3 torrentek v\u00e9gigk\u00e9rdez\u00e9se Scrape.status.disabled=V\u00e9gigk\u00e9rdez\u00e9s Kikapcsolva MyTorrentsView.menu.explore=F\u00e1jl megjelen\u00edt\u00e9se MyTorrentsView.menu.explore._mac=Megjelen\u00edt\u00e9s a keres\u0151ben MyTorrentsView.menu.explore._windows=Megjelen\u00edt\u00e9s az Int\u00e9z\u0151ben wizard.maketorrents.autohost=Torrent elhelyez\u00e9se a be\u00e9p\u00edtett trackeren ConfigView.label.overrideip=A tracker fel\u00e9 k\u00fcld\u00f6tt IP fel\u00fclb\u00edr\u00e1l\u00e1sa - pontosvessz\u0151vel elv\u00e1lasztva t\u00f6bb c\u00edm eset\u00e9n ConfigView.label.overrideip.tooltip=\u00c9rtes\u00edti a trackert egy kimen\u0151 adatok forr\u00e1sc\u00edm\u00e9t\u0151l elt\u00e9r\u0151 IP-c\u00edm haszn\u00e1lat\u00e1r\u00f3l. Hagyja \u00fcresen, ha nem haszn\u00e1lod. ConfigView.section.connection.group.networks=H\u00e1l\u00f3zatok ConfigView.section.connection.group.networks.info=V\u00e1laszd ki az enged\u00e9lyezett h\u00e1l\u00f3zatot az \u00fcgyf\u00e9l-\u00fcgyf\u00e9l adat\u00e1tvitelre ConfigView.section.connection.networks.prompt=V\u00e1laszt\u00e1s felaj\u00e1nl\u00e1sa n\u00e9vtelen trackerrel rendelkez\u0151 let\u00f6lt\u00e9s megnyit\u00e1sakor ConfigView.section.connection.networks.Public=Publikus IP h\u00e1l\u00f3zat (nem n\u00e9vtelen) ConfigView.section.connection.networks.I2P=I2P h\u00e1l\u00f3zat ConfigView.section.connection.networks.Tor=The Onion Router (Tor) h\u00e1l\u00f3zat TableColumn.header.networks=H\u00e1l\u00f3zat TableColumn.header.networks.info=Peer-peer kommunik\u00e1ci\u00f3ra enged\u00e9lyezett h\u00e1l\u00f3zatok Scrape.status.networkdisabled=H\u00e1l\u00f3zat nincs enged\u00e9lyezve ConfigView.section.tracker.server.group.networks=H\u00e1l\u00f3zatok ConfigView.section.tracker.server.group.networks.info=V\u00e1lassza ki azt a h\u00e1l\u00f3zatot, ahonnan a tracker \u00fcgyfeleket fogadhat window.networkselection.title=H\u00e1l\u00f3zat Kiv\u00e1laszt\u00e1sa window.networkselection.info=Az al\u00e1bbi torrent a k\u00f6vetkez\u0151 h\u00e1l\u00f3zat(ok)hoz tartoz\u00f3 trackereket t\u00e1mogatja.\nV\u00e1lassza ki, melyiket k\u00edv\u00e1nja a haszn\u00e1lni a tracker \u00e9s az \u00fcgyfelek fel\u00e9 ir\u00e1nyul\u00f3 kommunik\u00e1ci\u00f3hoz.\nNyilv\u00e1nos \u00fcgyfeleket t\u00e1mogat\u00f3 n\u00e9vtelen tracker eset\u00e9ben p\u00e9ld\u00e1ul enged\u00e9lyezze mind a nyilv\u00e1nos, mind a n\u00e9vtelen h\u00e1l\u00f3zatokat.\nNy\u00edlt h\u00e1l\u00f3zat enged\u00e9lyez\u00e9se \u00e9rtelemszer\u0171en a n\u00e9vtelens\u00e9g elveszt\u00e9s\u00e9vel j\u00e1r! plugins.basicview.clear=T\u00f6r\u00f6l ConfigView.section.connection.group.peersources=\u00dcgyf\u00e9l forr\u00e1sok ConfigView.section.connection.group.peersources.info=V\u00e1laszd ki az \u00fcgyfelek fogad\u00e1s\u00e1nak alap\u00e9rtelmezett hely\u00e9t ConfigView.section.connection.peersource.Tracker=Trackert\u0151l ConfigView.section.connection.peersource.DHT=K\u00f6zpontos\u00edtatlan k\u00f6vetls ConfigView.section.connection.peersource.PeerExchange=M\u00e1sik \u00fcgyf\u00e9l \u00e1ltal rendelkez\u00e9sre bocs\u00e1tva ConfigView.section.connection.peersource.Plugin=Plugin adta ConfigView.section.connection.peersource.Incoming=Bej\u00f6v\u0151 kapcsolat PeersView.source=Forr\u00e1s PeersView.source.info=Az \u00fcgyf\u00e9l forr\u00e1sa TableColumn.header.peersources=Peer Forr\u00e1s TableColumn.header.peersources.info=Peer kapcsolatok l\u00e9trehoz\u00e1s\u00e1ra haszn\u00e1lt forr\u00e1sok wizard.tracker.dht=K\u00f6zpontos\u00edtatlan (csak Vuze kliensek sz\u00e1m\u00e1ra) MyTorrentsView.menu.advancedmenu=Halad\u00f3 MyTorrentsView.menu.networks=H\u00e1l\u00f3zatok MyTorrentsView.menu.peersource=\u00dcgyf\u00e9lforr\u00e1sok ConfigView.section.sharing.permitdht=K\u00f6zpontos\u00edtatlan k\u00f6vet\u00e9s enged\u00e9lyez\u00e9se, ha a tracker nem el\u00e9rhet\u0151 ConfigView.section.sharing.protocol=Megosztott er\u0151forr\u00e1s protokoll PeersView.Messaging=\u00dczenetk\u00fcld\u00e9s PeersView.Messaging.info=Fejlett \u00fczenetk\u00fcld\u0151 fel\u00fclet t\u00e1mogat\u00e1sa. ConfigView.label.queue.newseedsmovetop=A frissen befejezett let\u00f6lt\u00e9sek ker\u00fcljenek a K\u00e9szforr\u00e1s lista elej\u00e9re ConfigView.label.seeding.firstPriority.ignore.info=Vegye figyelembe, hogy ezen szab\u00e1lyok haszn\u00e1lata a torrent azonnali le\u00e1ll\u00e1s\u00e1t okozhatja,\nha a let\u00f6lt\u00e9s befejez\u0151d\u00f6tt ConfigView.label.seeding.firstPriority.ignore=Magas Priorit\u00e1s\u00fa szab\u00e1lyok elhagy\u00e1sa, ha: ConfigView.label.seeding.firstPriority.ignoreSPRatio=A torrent K\u00e9szforr\u00e1s:\u00dcgyf\u00e9l ar\u00e1nya nagyobb, mint ConfigView.label.seeding.firstPriority.ignore0Peer=Torrent 0 \u00dcgyf\u00e9llel (Peers) ConfigView.section.tracker.sendjavaversionandos=Java verzi\u00f3 \u00e9s OP rendszer nev\u00e9nek elk\u00fcld\u00e9se MagnetPlugin.contextmenu.exporturi=M\u00e1gnes URI m\u00e1sol\u00e1sa a V\u00e1g\u00f3lapra ConfigView.section.plugins.dht=Elosztott Adatb\u00e1zis dht.info=Ez a plugin, t\u00f6bbek k\u00f6z\u00f6tt, t\u00e1mogatja a k\u00f6zpontos\u00edtatlan k\u00f6vet\u00e9st (DHT) - kikapcsol\u00e1sa cs\u00f6kkenti a let\u00f6lt\u00e9si lehet\u0151s\u00e9geket dht.enabled=Elosztott adatb\u00e1zis enged\u00e9lyez\u00e9se dht.portdefault=Alap\u00e9rtelmezett port haszn\u00e1lata dht.port=Adatb\u00e1zishoz rendelt UDP port dht.execute.command=Diagnosztikai parancs dht.execute.info=Nyomd meg ezt a gombot a parancs v\u00e9grehajt\u00e1s\u00e1hoz dht.execute=Futtat\u00e1s dht.logging=Tev\u00e9kenys\u00e9g nyomonk\u00f6vet\u00e9se ConfigView.section.plugins.dhttracker=Elosztott Tracker dhttracker.tracknormalwhenoffline=Norm\u00e1l torrenteket csak akkor k\u00f6vesse, ha a tracker el\u00e9rhetetlen ConfigView.section.file.nativedelete._mac=Lomt\u00e1rba dob\u00e1s ConfigView.section.file.nativedelete._windows=T\u00f6r\u00f6lt f\u00e1jlok Lomt\u00e1rba helyez\u00e9se ConfigView.section.logging.generatediagnostics=L\u00e9trehoz\u00e1s ConfigView.section.logging.netinfo=H\u00e1l\u00f3zati adatok gener\u00e1l\u00e1sa ConfigView.section.logging.statsinfo=Statisztika gener\u00e1l\u00e1sa ConfigView.section.logging.generatediagnostics.info=Diagnosztikai inform\u00e1ci\u00f3k l\u00e9trehoz\u00e1sa, \u00e9s be\u00e1ll\u00edt\u00e1st\u00f3l f\u00fcgg\u0151en m\u00e1solja a v\u00e1g\u00f3lapon \u00e9s mentse el f\u00e1jlba ConfigView.section.sharing.privatetorrent=Priv\u00e1t torrent - csak a trackert\u0151l fogad \u00fcgyfeleket MainWindow.menu.tools.nattest=&NAT / T\u0171zfal Teszt Button.apply=Alkalmaz Button.close=Bez\u00e1r window.welcome.title=\u00dcdv\u00f6zli az Vuze %1 #file can be a URL or a path in the jar MainWindow.menu.help.releasenotes=V\u00e1ltoz\u00e1sok dht.reseed.label=Az elosztott (DHT) adatb\u00e1zis \u00fajb\u00f3li k\u00f6zz\u00e9t\u00e9tel\u00e9re \u00e1ltal\u00e1ban nincs sz\u00fcks\u00e9g, viszont a kapcsolatok fogyatkoz\u00e1sa eset\u00e9n seg\u00edtheti azok \u00fajraszervez\u00e9s\u00e9t.\nHa itt megadsz egy ismert \u00fcgyf\u00e9l IP c\u00edm\u00e9t \u00e9s portsz\u00e1m\u00e1t, akkor annak seg\u00edts\u00e9g\u00e9vel, ha nem \u00edrsz be semmit, akkor az \u00e9ppen kapcsol\u00f3dott \u00fcgyfelek seg\u00edts\u00e9g\u00e9vel val\u00f3s\u00edthatja ezt meg a program. dht.reseed.group=Felt\u00f6lt\u00e9s \u00fajraind\u00edt\u00e1sa dht.reseed.ip=IP c\u00edmek dht.reseed=Felt\u00f6lt\u00e9s \u00fajraind\u00edt\u00e1sa dht.reseed.info=Adatb\u00e1zis megoszt\u00e1sa dht.diagnostics.group=Diagnosztika DHTView.title.full=Elosztott Adatb\u00e1zis DHTView.title.fullcvs=Elosztott Adatb\u00e1zis CVS DHTView.general.title=\u00c1ltal\u00e1nos DHTView.general.uptime=\u00dczemid\u0151: DHTView.general.users=Felhaszn\u00e1l\u00f3k: DHTView.general.nodes=Csom\u00f3pont: DHTView.general.leaves=Kil\u00e9p\u0151k: DHTView.general.contacts=Kapcsolatok: DHTView.general.replacements=Tartal\u00e9kos: DHTView.general.live=M\u0171k\u00f6dik: DHTView.general.unknown=Ismeretlen: DHTView.general.dying=Haldoklik: DHTView.transport.title=\u00c1tvitel r\u00e9szletei DHTView.transport.packets=Csomag DHTView.transport.bytes=B\u00e1jt DHTView.transport.received=Fogadva DHTView.transport.sent=Elk\u00fcldve DHTView.transport.in=Be : DHTView.transport.out=Ki : DHTView.operations.title=M\u0171velet r\u00e9szletei DHTView.operations.sent=Elk\u00fcldve DHTView.operations.ok=OK DHTView.operations.failed=Sikertelen DHTView.operations.received=Fogadva DHTView.operations.findNode=Csom\u00f3pont keres\u00e9se DHTView.operations.findValue=\u00c9rt\u00e9k keres\u00e9se DHTView.operations.store=T\u00e1rol\u00e1s DHTView.activity.title=Tev\u00e9kenys\u00e9g DHTView.activity.status=\u00c1llapot DHTView.activity.status.true=V\u00e1r\u00f3sorban DHTView.activity.status.false=Fut DHTView.activity.type=T\u00edpus DHTView.activity.type.1=Bels\u0151 K\u00e9r\u00e9s DHTView.activity.type.2=K\u00fcls\u0151 K\u00e9r\u00e9s DHTView.activity.type.3=Bels\u0151 K\u00fcld\u00e9s DHTView.activity.type.4=K\u00fcls\u0151 K\u00fcld\u00e9s DHTView.activity.target=C\u00e9l DHTView.activity.details=R\u00e9szletek DHTView.db.title=Adatb\u00e1zis DHTView.db.keys=Kulcsok DHTView.db.values=\u00c9rt\u00e9kek DHTView.db.local=Helyi DHTView.db.direct=K\u00f6zvetlen DHTView.db.indirect=K\u00f6zvetett DHTView.db.divfreq=Frek. Oszt. DHTView.db.divsize=M\u00e9ret Oszt. MainWindow.dht.status.tooltip=Az Elosztott Adatb\u00e1zis fut\u00e1sa k\u00f6zben itt jelenik meg az online felhaszn\u00e1l\u00f3k becs\u00fclt sz\u00e1ma MainWindow.dht.status.disabled=DHT Kikapcsolva MainWindow.dht.status.failed=DHT Sikertelen MainWindow.dht.status.initializing=DHT El\u0151k\u00e9sz\u00edt\u00e9se MainWindow.dht.status.users=%1 felhaszn\u00e1l\u00f3 MainWindow.dht.status.unreachable=DHT blokkolva MainWindow.dht.status.unreachabletooltip=\u00dagy t\u0171nik gond van az Elosztott Adatb\u00e1zis UDP port kioszt\u00e1s\u00e1val (NAT/T\u0171zfal) MyTorrentsView.menu.setUpSpeed=Felt\u00f6lt\u00e9si Sebess\u00e9g MyTorrentsView.menu.setDownSpeed=Let\u00f6lt\u00e9si Sebess\u00e9g ConfigView.section.tracker.client.showwarnings=Trackerek \u00e1ltal k\u00fcld\u00f6tt hiba\u00fczenetek megjelen\u00edt\u00e9se dht.advanced=Halad\u00f3 be\u00e1ll\u00edt\u00e1sok enged\u00e9lyez\u00e9se dht.advanced.group=Halad\u00f3 be\u00e1ll\u00edt\u00e1sok dht.advanced.label=Csak akkor m\u00f3dos\u00edtsd ezeket az \u00e9rt\u00e9keket, ha biztosan tudod mit csin\u00e1lsz! dht.override.ip=K\u00fcls\u0151 IP c\u00edm fel\u00fclb\u00edr\u00e1l\u00e1sa ConfigView.section.logging.loggerenable=Napl\u00f3z\u00e1s enged\u00e9lyez\u00e9se ConfigView.section.ipfilter.blockbanning=Teljes 256 c\u00edmb\u0151l \u00e1ll\u00f3 t\u00f6mb blokkol\u00e1sa, ha abb\u00f3l legal\u00e1bb ennyi c\u00edm tilt\u00f3list\u00e1ra ker\u00fclt. MyTrackerView.passive=Passz\u00edv TableColumn.header.swarm_average_speed=Boly \u00e1tlagsebess\u00e9ge TableColumn.header.swarm_average_speed.info=A bolyban lev\u0151 peerek \u00e1tlagsebess\u00e9ge TableColumn.header.comment=Megjegyz\u00e9s TableColumn.header.comment.info=Felhaszn\u00e1l\u00f3i megjegyz\u00e9s a let\u00f6lt\u00e9shez TableColumn.header.commenticon=Megjegyz\u00e9s ikon TableColumn.header.commenticon.info=Ikon megjelen\u00edt\u00e9se, ha van felhaszn\u00e1l\u00f3i megjegyz\u00e9suser-defined comment MyTrackerView.category=Kateg\u00f3ria MainWindow.menu.file.open.torrentfortracking=Torrent F\u00e1jl... (Csak K\u00f6vet\u00e9s) MyTrackerView.date_added=Hozz\u00e1adva ConfigView.section.tracker.portbackup=Tartal\u00e9k portok (';'-val elv\u00e1lasztva) ConfigView.label.playfilespeech=Besz\u00e9d ha egy f\u00e1jl elk\u00e9sz\u00fclt ConfigView.label.playfilespeech.info=A besz\u00e9dszolg\u00e1ltat\u00e1s legjobban angolul m\u0171k\u00f6dik ConfigView.label.playfilefinished=Hangjelz\u00e9s, ha egy feladat elk\u00e9sz\u00fclt ConfigView.label.backupconfigfiles=Be\u00e1ll\u00edt\u00e1si f\u00e1jl ment\u00e9se vissza\u00e1ll\u00edthat\u00f3s c\u00e9lj\u00e1b\u00f3l ConfigView.section.tracker.client.scrapesingleonly=Trackerenk\u00e9nti s\u00e9rt\u00e9s felhazmoz\u00e1s tilt\u00e1sa (seg\u00edt ha a tracker 'Az URL t\u00fal hossz\u00fa' (414) \u00fczentet k\u00fcld) dht.ipfilter.log=IP-sz\u0171r\u0151 \u00e1ltal \u00e9rz\u00e9kelt t\u00e1mad\u00e1sok napl\u00f3z\u00e1sa ConfigView.label.seeding.addForSeedingDLCopyCount=Vedd figyelembe, hogy a 'hozz\u00e1ad\u00e1s seederk\u00e9nt' let\u00f6lt\u00e9seket m\u00e1sok sz\u00e1m\u00e1ra el\u00e9rhet\u0151v\u00e9 teszed ActivityView.legend.limit=Limit ActivityView.legend.achieved=El\u00e9rt sebess\u00e9g ActivityView.legend.overhead=Fejr\u00e9sz ar\u00e1ny ActivityView.legend.peeraverage=\u00c1tlag ActivityView.legend.swarmaverage=Boly sebess\u00e9ge ActivityView.legend.trimmed=Rendezett (pont) MyTorrentsView.menu.movemenu=F\u00e1jlok mozgat\u00e1sa MyTorrentsView.menu.movedata=F\u00e1jlok Mozgat\u00e1sa... MyTorrentsView.menu.movetorrent=Torrent F\u00e1jl Mozgat\u00e1sa... MyTorrentsView.menu.movedata.dialog=\u00daj hely megad\u00e1sa DHTView.operations.data=Adat DHTView.general.reachable=El\u00e9rhet\u0151: DHTView.general.rendezvous=Randev\u00fa: ConfigView.label.queue.maxactivetorrentswhenseeding=Max seedel\u00e9skor [0:v\u00e9gtelen] Views.plugins.IRC.title=IRC - Online Technikai T\u00e1mogat\u00e1s Formats.units.alot=Sok !!! ConfigView.section.ipfilter.persistblocking=Blokkolt IP-c\u00edmek ment\u00e9se a program \u00fajraind\u00edt\u00e1sakor FilesView.menu.rename=\u00c1tnevez vagy \u00c1thelyez FilesView.menu.rename_only=\u00c1tnevez FilesView.menu.retarget=\u00c1thelyez FilesView.rename.choose.path=V\u00e1lassz \u00faj vagy l\u00e9tez\u0151 f\u00e1jlt FilesView.rename.choose.path.dir=V\u00e1lassz \u00faj vagy l\u00e9tez\u0151 mapp\u00e1t FilesView.rename.confirm.delete.title=T\u00f6rl\u00e9s Meger\u0151s\u00edt\u00e9se FilesView.rename.confirm.delete.text='%1' f\u00e1jlt t\u00f6rl\u00e9s\u00e9nek meger\u0151s\u00edt\u00e9se FilesView.rename.filename.title=F\u00e1jl \u00e1tnevez\u00e9se FilesView.rename.filename.text=Adja meg a f\u00e1jl \u00faj nev\u00e9t ConfigView.higher.mode.available=Tov\u00e1bbi be\u00e1ll\u00edt\u00e1s \u00e9rhet\u0151 el a halad\u00f3 n\u00e9zetben ConfigView.section.mode=Felhaszn\u00e1l\u00f3i fel\u00fclet ConfigView.section.mode.title=Felhaszn\u00e1l\u00f3 j\u00e1rtass\u00e1ga ConfigView.section.mode.beginner=Kezd\u0151 ConfigView.section.mode.beginner.wiki.definitions=BitTorrent sz\u00f3t\u00e1r ConfigView.section.mode.intermediate=Halad\u00f3 ConfigView.section.mode.intermediate.wiki.host=Kiszolg\u00e1lt f\u00e1jlok ConfigView.section.mode.intermediate.wiki.publish=K\u00f6zz\u00e9tett f\u00e1jlok ConfigView.section.mode.advanced=Fejlett ConfigView.section.mode.advanced.wiki.main=Wiki f\u0151oldala ConfigView.section.mode.beginner.text=Mind ami a torrentek let\u00f6lt\u00e9s\u00e9hez sz\u00fcks\u00e9ges.\nV\u00e1laszd ezt a be\u00e1ll\u00edt\u00e1st, ha csak a let\u00f6lt\u00e9seket szeretn\u00e9d kezelni. ConfigView.section.mode.intermediate.text=Hozz\u00e1f\u00e9rhetsz a tracket be\u00e1ll\u00edt\u00e1saihoz.\nV\u00e1laszd ezt a be\u00e1ll\u00edt\u00e1st, ha saj\u00e1t Trackert szeretn\u00e9l a f\u00e1jlok megoszt\u00e1s\u00e1hoz. ConfigView.section.mode.advanced.text=Hozz\u00e1f\u00e9rhetsz a h\u00e1l\u00f3zati be\u00e1ll\u00edt\u00e1sokhoz is.\nV\u00e1laszd ezt, ha az MTU \u00e9s az I/O be\u00e1ll\u00edt\u00e1sokhoz is \u00e9rtessz. Files.column.storagetype=T\u00e1rol\u00f3 t\u00edpusa Files.column.fileext=T\u00edpus FileItem.storage.linear=Line\u00e1ris FileItem.storage.compact=T\u00f6m\u00f6r MessageBoxWindow.rememberdecision=Eml\u00e9kezzen erre a be\u00e1ll\u00edt\u00e1sra ConfigView.section.interface.cleardecisions=P\u00e1rbesz\u00e9dablakok megjegyzett kiv\u00e1laszt\u00e1sainak t\u00f6rl\u00e9se ConfigView.section.interface.cleardecisionsbutton=\u00dcr\u00edt ConfigView.section.interface.cleartrackers=Megjegyzett trackerek t\u00f6rl\u00e9se ConfigView.section.interface.cleartrackersbutton=T\u00f6r\u00f6l ConfigView.section.interface.clearsavepaths=Megjegyzett \u00fatvonalak t\u00f6rl\u00e9se ConfigView.section.interface.clearsavepathsbutton=T\u00f6r\u00f6l configureWizard.welcome.usermodes=A Felhaszn\u00e1l\u00f3 J\u00e1rtass\u00e1g be\u00e1ll\u00edt\u00e1s meghat\u00e1rozza a megjelen\u0151 be\u00e1ll\u00edt\u00e1sokat az Eszk\u00f6z\u00f6k > Be\u00e1ll\u00edt\u00e1sok r\u00e9szben. Neked megfelel\u0151en \u00e1ll\u00edtsd be. FilesView.skip.confirm.delete.text=Megcsonk\u00edtja a '%1' f\u00e1jlt, hogy helyet szabad\u00edtson fel? FilesView.rename.failed.title=\u00c1tnevez\u00e9s/\u00c1thelyez\u00e9s hiba FilesView.rename.failed.text=A m\u0171velet sikertelen, val\u00f3sz\u00edn\u0171leg rossz a c\u00e9l diagnostics.log_found=Vuzenem megfelel\u0151en lett le\u00e1ll\u00edtva. N\u00e9zd meg a napl\u00f3f\u00e1jlt, \u00e9s jelentheted a hiba ok\u00e1t az Vuze csapatnak. Tov\u00e1bb\u00e1 elolvashatod a Wiki-ben (S\u00fag\u00f3 Men\u00fc) az 'Vuze Dissapers' r\u00e9szt. ManagerItem.paused=Sz\u00fcnet Utils.link.visit=L\u00e1togass el ConfigView.section.connection.serverport.wiki=J\u00f3 portv\u00e1laszt\u00e1s ConfigView.section.transfer.speeds.wiki=J\u00f3 sebess\u00e9gbe\u00e1ll\u00edt\u00e1s installPluginsWizard.installMode.info.title=Inform\u00e1ci\u00f3 installPluginsWizard.installMode.info.text=Nincs sz\u00fcks\u00e9ges a pluginekre az Vuze megfelel\u0151 m\u0171k\u00f6d\u00e9s\u00e9hez, de sok hasznos szolg\u00e1ltat\u00e1st hoznak, automatiz\u00e1l\u00e1s vagy t\u00e1voli vez\u00e9rl\u00e9s.Q\nEz\u00e9rt figyelmesen olvasd el a pluginek le\u00edr\u00e1s\u00e1t, miel\u0151tt telep\u00edten\u00e9d azokat.\nA legtobb plugin nyugodtan kipr\u00f3b\u00e1lhat\u00f3, de ne terheld le a rendszert sok nem haszn\u00e1lt pluginnal. Views.plugins.Distributed.DB.title=Elosztott DB Views.plugins.Distributed.Tracker.title=Elosztott Kiszolg\u00e1l\u00f3 Views.plugins.Plugin.Update.title=Plugin Friss\u00edt\u00e9s openUrl.url.info=T\u00e1mogatja a http, https, magnet \u00e9s nyers infohash kulcsokat TableColumn.header.swarm_average_completion=Peer \u00c1tlagos \u00c1llapota TableColumn.header.swarm_average_completion.info=A bolyban lev\u0151 peerek \u00e1llapota sz\u00e1zal\u00e9kban GeneralView.label.swarm_average_completion=\u00c1tlagos Befejez\u00e9s: GeneralView.label.swarm_average_completion.tooltip=A befejezett \u00fcgyfelek sz\u00e1zal\u00e9kos \u00e1tlaga a bolybanban MainWindow.nat.status.tooltip.unknown=T\u0171zfall/NAT el\u00e9rhet\u0151s\u00e9g \u00e1llapota ismeretlen (TCP) MainWindow.nat.status.tooltip.ok=El\u00e9rhet\u0151s\u00e9g OK (TCP) MainWindow.nat.status.tooltip.probok=El\u00e9rhet\u0151s\u00e9g Rendben, azonban nincs bej\u00f6v\u0151 TCP adat MainWindow.nat.status.bad=Passz\u00edv MainWindow.nat.status.tooltip.bad=T\u0171zfall/NAT (TCP) el\u00e9rhet\u0151s\u00e9gi hiba. N\u00e9zd meg a Wiki-t a seg\u00edts\u00e9ghez plugin.installer.recommended.plugin=Aj\u00e1nlott plugin - k\u00e9rlek olvasd el \u00e9s telep\u00edtsd, ha sz\u00fcks\u00e9ges LoggerView.pause=Napl\u00f3z\u00e1s Sz\u00fcneteltet\u00e9se LoggerView.clear=&Tiszt\u00edt LoggerView.filter=Sz\u0171r\u0151 LoggerView.filter.uncheckAll=Minden kateg\u00f3ria jel\u00f6l\u00e9s t\u00f6rl\u00e9se LoggerView.filter.checkAll=Minden kateg\u00f3ria bejel\u00f6l\u00e9se LoggerView.loggingDisabled=Napl\u00f3z\u00e1s nincs bekapcsolva. LoggerView.includeOnly=Csak az ezzel egyez\u0151 soregyez\u00e9st mutassa: LoggerView.excludeAll=Ne mutassa a soregyez\u00e9st enn\u00e9l a kifejez\u00e9sn\u00e9l: ConfigView.section.logging.log0type=Inform\u00e1ci\u00f3 ConfigView.section.logging.log1type=Figyelmeztet\u00e9s ConfigView.section.logging.log2type=Hiba ConfigView.section.logging.filter=Napl\u00f3z\u00e1s f\u00e1jlba sz\u0171r\u00e9se ConfigView.section.logging.level=Napl\u00f3z\u00e1s szintje ConfigView.section.logging.showLogsFor=%1 napl\u00f3k mutat\u00e1sa a k\u00f6vetkez\u0151 kateg\u00f3ri\u00e1ban: ConfigView.pluginlist.column.loadAtStartup=Bet\u00f6lt\u00e9s Ind\u00edt\u00e1skor ConfigView.pluginlist.column.type=T\u00edpus ConfigView.pluginlist.column.type.perUser=Felhaszn\u00e1l\u00f3nk\u00e9nt ConfigView.pluginlist.column.type.shared=Megosztott ConfigView.pluginlist.column.type.builtIn=Be\u00e9p\u00edtett ConfigView.pluginlist.column.name=N\u00e9v ConfigView.pluginlist.column.version=Verzi\u00f3 ConfigView.pluginlist.column.directory=K\u00f6nyvt\u00e1r ConfigView.pluginlist.column.isOperational=M\u0171k\u00f6d\u0151? PeersView.BlockView.Avail.Have=Mindenkinek megvan PeersView.BlockView.Avail.NoHave=\u00dcgyf\u00e9lnek megvan; Neked nincs PeersView.BlockView.NoAvail.Have=Neked megvan; \u00dcgyf\u00e9lnek nincs PeersView.BlockView.NoAvail.NoHave=Nincs meg senkinek PeersView.BlockView.Transfer=\u00c1tvitel PeersView.BlockView.NextRequest=K\u00f6vetkez\u0151 K\u00e9r\u00e9s PeersView.BlockView.title=Szelet t\u00e9rk\u00e9p PeersView.BlockView.AvailCount=El\u00e9rhet\u0151s\u00e9g MyTorrentsView.dialog.NumberError.title=Nem megfelel\u0151 vagy Ismeretlen Sz\u00e1m MyTorrentsView.dialog.NumberError.text=A be\u00edrt sz\u00e1m nem megfelel\u0151 MyTorrentsView.menu.manual=&K\u00e9zi... MyTorrentsView.menu.manual.per_torrent=K\u00e9zi (torrentenk\u00e9nt) MyTorrentsView.menu.manual.shared_torrents=K\u00e9zi (torrentek k\u00f6z\u00f6tt) MyTorrentsView.dialog.setSpeed.title=Sebess\u00e9g: %1 # %1 = "in kbps" or ""; %2 = "upload" or "download" MyTorrentsView.dialog.setNumber.text=Add meg a %2 \u00e9rt\u00e9k\u00e9t %1-ben: MyTorrentsView.dialog.setNumber.upload=felt\u00f6lt MyTorrentsView.dialog.setNumber.download=let\u00f6lt\u00e9s MyTorrentsView.dialog.setNumber.inKbps=%1 alatt OpenTorrentWindow.torrentLocation=Let\u00f6lt\u00e9sre kijel\u00f6lt torrentek: OpenTorrentWindow.addFiles.URL=&URL Hozz\u00e1ad\u00e1sa OpenTorrentWindow.addFiles.Folder=&Mappa Hozz\u00e1ad\u00e1sa OpenTorrentWindow.addFiles.Clipboard=&Beilleszt\u00e9s a V\u00e1g\u00f3lapr\u00f3l OpenTorrentWindow.changeDestination=C\u00e9l Megv\u00e1ltoztat\u00e1sa OpenTorrentWindow.fileList=F\u00e1jlok sz\u00e1ma a torrentben: OpenTorrentWindow.torrentTable.name=N\u00e9v OpenTorrentWindow.torrentTable.saveLocation=Ment\u00e9s Helye OpenTorrentWindow.fileTable.fileName=F\u00e1jln\u00e9v OpenTorrentWindow.fileTable.size=M\u00e9ret OpenTorrentWindow.fileTable.destinationName=C\u00e9l Neve OpenTorrentWindow.startMode.seeding=K\u00e9szforr\u00e1s OpenTorrentWindow.fileList.changeDestination=C\u00e9l Megv\u00e1ltoztat\u00e1sa OpenTorrentWindow.mb.badSize.title=Nem megfelel\u0151 f\u00e1jl OpenTorrentWindow.mb.badSize.text=A '%1' \u00e9s a '%2' nem egyezik, \u00e9s nem lehet haszn\u00e1lni seedel\u00e9shez OpenTorrentWindow.mb.alreadyExists.text='%1' torrent m\u00e1r hozz\u00e1 van adva '%2' n\u00e9ven OpenTorrentWindow.mb.alreadyExists.default.name=M\u00e9dia OpenTorrentWindow.mb.alreadyExists.title=A torrent m\u00e1r l\u00e9tezik OpenTorrentWindow.mb.openError.title=Megnyit\u00e1si Hiba OpenTorrentWindow.mb.openError.text='%1' nem lehet megnyitni:\n%2 OpenTorrentWindow.torrent.remove=Torrent elt\u00e1vol\u00edt\u00e1sa a list\u00e1b\u00f3l OpenTorrentWindow.torrent.options=A k\u00f6vetkez\u0151 be\u00e1ll\u00edt\u00e1sok a kijel\u00f6lt torrentekn\u00e9l l\u00e9pnek \u00e9rv\u00e9nybe: OpenTorrentWindow.xOfTotal=(%1 a %2-b\u00f3l) iconBar.open.tooltip=Torrent(ek) megynit\u00e1sa LocaleUtil.column.text=Ismeretlen Sz\u00f6veg Tracker.tooltip.MultiSupport=A tracker t\u00e1mogatja a t\u00f6bbsz\u00e1l\u00fa hash kik\u00e9rdez\u00e9st k\u00e9r\u00e9senk\u00e9nt. Tracker.tooltip.NoMultiSupport=A tracker nem t\u00e1mogatja a t\u00f6bbsz\u00e1las hash kik\u00e9rdez\u00e9st k\u00e9r\u00e9senk\u00e9nt..\nEz nem hat a teljes\u00edtm\u00e9nyedre, de t\u00f6bb terhet r\u00f3 a trackerre. ConfigView.label.lazybitfield=Use lazy bitfield (seg\u00edti a seedel\u00e9st, ahol bitfiels alap\u00fa blokkol\u00e1st haszn\u00e1lnak) LoggerView.realtime=Friss\u00edt\u00e9s val\u00f3s id\u0151ben ConfigView.section.file.perf.cache.flushpieces=Befejezett szeletek azonnali lemezre \u00edr\u00e1sa. Cs\u00f6kkenti a lemezhozz\u00e1f\u00e9r\u00e9st, de t\u00f6bb \u00edr\u00e1si m\u0171veletet eredm\u00e9nyez ConfigView.section.file.writemblimit=Maxim\u00e1lis \u00edr\u00e1si k\u00e9relem (%1-ban) ConfigView.section.file.writemblimit.explain=Ha a lemezre \u00edr\u00e1s sebess\u00e9ge kisebb, mint a let\u00f6lt\u00e9si sebess\u00e9g, akkor ezzel a be\u00e1ll\u00edt\u00e1ssal szab\u00e1lyozhatod, hogy mennyi adat legyen sorba\u00e1ll\u00edtva, miel\u0151tt a let\u00f6l\u00e9si sebess\u00e9g lecs\u00f6kken. ConfigView.section.file.readmblimit=Maxim\u00e1lis olvas\u00e1si k\u00e9relem (%1-ban) ConfigView.section.file.readmblimit.explain=Be\u00e1ll\u00edthatod az olvas\u00e1shoz haszn\u00e1lt mem\u00f3ria m\u00e9ret\u00e9t. Button.moveUp=Le Button.moveDown=Fel ConfigView.notAvailableForMode=Ez a r\u00e9sz a %1 m\u00f3dhoz vagy magasabbhoz val\u00f3. Nem \u00e9rhet\u0151 el %2 m\u00f3dban. health.explain.error=Hiba t\u00f6rt\u00e9nt a torrenttel. N\u00e9zd meg az \u00c1llapot oszlopot vagy a gyorstippet a hiba\u00fczeneten. GeneralView.label.trackerscrapeupdate=Tracker Lek\u00e9rdez\u00e9se PeersView.piece=Szelet PeersView.piece.info=Utols\u00f3 \u00e9rkezett szelet # PiecesView.priority=Priorit\u00e1s PiecesView.priority.info=a szeletek priorit\u00e1sa, nem olyan pontos PiecesView.speed=Sebess\u00e9g PiecesView.speed.info=Lass\u00fa szeletek mell\u0151z\u00e9se a gyorsabb szeletekkel szemben TableColumn.header.AvgAvail.info=Az \u00f6sszes darab el\u00e9rhet\u0151s\u00e9ge osztva # darabsz\u00e1mmal, osztva # kapcsolatok sz\u00e1m\u00e1val TableColumn.header.AvgAvail=\u00c1tl El\u00e9rhet\u0151/db ConfigView.label.strictfilelocking=F\u00e1jl\u00edr\u00e1s z\u00e1rol\u00e1sa a torrenteken kereszt\u00fcl MyTorrentsView.menu.checkfilesexist=F\u00e1jl L\u00e9tezik? MyTorrentsView.menu.rescanfile=Befejezetlen Szeletek Folyamatos Ellen\u0151rz\u00e9se MyTorrentsView.menu.clear_resume_data=Folytat\u00e1si adatok t\u00f6rl\u00e9se Plugin.extseed.name=K\u00fcls\u0151 Kiszolg\u00e1l\u00f3 Plugin.localtracker.name=Helyi \u00dcgyf\u00e9lkeres\u0151 Plugin.localtracker.info=A Helyi \u00dcgyf\u00e9lkeres\u0151 k\u00f6zvetlen kapcsolatot hoz l\u00e9tre az azonos helyi h\u00e1l\u00f3zaton m\u0171k\u00f6d\u0151 Azureusok k\u00f6z\u00f6tt.\n\u00cdgy jelent\u0151sen megn\u00f6vekedhet a let\u00f6lt\u00e9si sebess\u00e9g Plugin.localtracker.enable=Helyi \u00dcgyf\u00e9lkeres\u0151 enged\u00e9lyez\u00e9se azinstancehandler.alert.portclash=Port \u00fctk\u00f6z\u00e9st \u00e9szleltem: %1 portot m\u00e1r egy m\u00e1sik program haszn\u00e1lja, v\u00e1lassz egy \u00faj portot a bej\u00f6v\u0151 TCP / UDP kapcsolatok figyel\u00e9s\u00e9hez [%2 \u00e9s %3 k\u00f6z\u00f6tt]. ConfigView.section.transfer.lan.tooltip=LAN-f\u00fcgg\u0151 Be\u00e1ll\u00edt\u00e1sok ConfigView.section.transfer.lan.uploadrate=Max felt\u00f6lt\u00e9si sebess\u00e9g a helyi h\u00e1l\u00f3zaton [0: korl\u00e1tlan] ConfigView.section.transfer.lan.uploadrate.tooltip=Azonos helyi h\u00e1l\u00f3zaton lev\u0151 \u00fcgyfelek m\u00e1s felt\u00f6lt\u00e9si limitet kapnak. ConfigView.section.transfer.lan.downloadrate=KB/s max. let\u00f6lt\u00e9si sebess\u00e9g a bels\u0151 h\u00e1l\u00f3zaton [0: korl\u00e1tlan] ConfigView.section.transfer.lan.downloadrate.tooltip=Azonos helyi h\u00e1l\u00f3zaton lev\u0151 \u00fcgyfelek m\u00e1s let\u00f6lt\u00e9si limitet kapnak. TorrentOptionsView.title.short=Be\u00e1ll\u00edts\u00e1sok TorrentOptionsView.title.full=Be\u00e1ll\u00edts\u00e1sok TorrentOptionsView.param.max.peers=Kapcsolatok maxim\u00e1lis sz\u00e1ma [0: v\u00e9gtelen] ConfigView.section.connection.encryption.require_encrypted_transport=Titkos\u00edtott \u00e1tvitel haszn\u00e1lata ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Titkos\u00edtott kapcsolatok k\u00e9nyszer\u00edt\u00e9se m\u00e1s \u00fcgyfelekkel. ConfigView.section.connection.encryption.min_encryption_level=Titkos\u00edt\u00e1s minim\u00e1lis szintje ConfigView.section.connection.encryption.min_encryption_level.tooltip=Egyszer\u0171 - csak k\u00e9zfog\u00e1s\nRC4 - teljes kapcsolat\nMagasabb titkos\u00edt\u00e1s t\u00f6bb CPU-t ig\u00e9nyel. Peers.column.Encryption=Titkos\u00edt\u00e1s Peers.column.Encryption.info=Haszn\u00e1lt titkos\u00edt\u00e1s szintje ConfigView.section.connection.encryption.encrypt.info=Ha a titkos\u00edt\u00e1s enged\u00e9lyezve van, akkor nem tudsz csatlakozni a nem t\u00e1mogatott kliensekhez, hacsak nem kapcsolod be visszal\u00e9p\u00e9s funkci\u00f3t ConfigView.section.connection.encryption.encrypt.info.link=Kattintson ide tov\u00e1bbi inform\u00e1ci\u00f3k\u00e9rt MainWindow.sr.status.tooltip.ok=Megoszt\u00e1si ar\u00e1nyod %1 OK MainWindow.sr.status.tooltip.poor=Megoszt\u00e1si r\u00e1nyod %1 < 0.9 -> Gyenge MainWindow.sr.status.tooltip.bad=Megoszt\u00e1si ar\u00e1nyod %1 < 0.5 -> Rossz ConfigView.section.style.status=\u00c1llapotk\u00f6rzet: ConfigView.section.style.status.show_sr=Megoszt\u00e1si ar\u00e1ny ConfigView.section.style.status.show_nat=NAT \u00c1llapota ConfigView.section.style.status.show_ddb=DDB \u00c1llapota ConfigView.section.style.status.show_ipf=IPFilter \u00c1llapota ConfigView.section.connection.encryption.encrypt.group=\u00c1tvitel titkos\u00edt\u00e1sa/zavar\u00e1sa ConfigView.section.connection.encryption.encrypt.fallback_info=A visszal\u00e9p\u00e9s fuckci\u00f3 alkalmaz\u00e1s\u00e1val enged\u00e9lyezheted a nem t\u00e1mogatott kliensek csatlakoz\u00e1s\u00e1t, DE ez titkos\u00edtatlan kapcsolatokat fog eredm\u00e9nyezni ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Titkos\u00edtatlan kimen\u0151 kapcsolatok enged\u00e9lyez\u00e9se, ha a titkos\u00edtott kapcsolat nem lehets\u00e9ges ConfigView.section.connection.encryption.encrypt.fallback_incoming=Titkos\u00edtatlan bej\u00f6v\u0151 kapcsolatok enged\u00e9lyez\u00e9se ConfigView.section.connection.encryption=\u00c1tvitel Titkos\u00edt\u00e1sa upnp.selectedinterfaces=Kiv\u00e1lasztott csatol\u00f3k (';'-vel elv\u00e1lasztva, Pl.: eth0;eth1) [\u00fcres: mind] ConfigView.section.style.defaultSortOrder=Rendez\u00e9si elv ConfigView.section.style.defaultSortOrder.desc=N\u00f6vekv\u0151 ConfigView.section.style.defaultSortOrder.asc=Emelked\u0151 ConfigView.section.style.defaultSortOrder.flip=Ford\u00edtott az el\u0151z\u0151 rendez\u00e9ssel LoggerView.autoscroll=Auto-g\u00f6rget\u00e9s Button.selectAll=\u00d6sszes kijel\u00f6l\u00e9se Button.markSelected=Kiv\u00e1lasztottak bejel\u00f6l\u00e9se Button.unmarkSelected=Kiv\u00e1lasztottak elvet\u00e9se plugins.basicview.config=Be\u00e1ll\u00edt TorrentOptionsView.param.max.uploads=Felt\u00f6lt\u00e9si sz\u00e1lak maxim\u00e1lis sz\u00e1ma [minimum: 2] MyTorrentsView.dialog.setPosition.title=Poz\u00edci\u00f3 be\u00e1ll\u00edt\u00e1sa MyTorrentsView.dialog.setPosition.text=Add meg a kiv\u00e1lasztott torrent hely\u00e9t: MyTorrentsView.menu.reposition.manual=\u00c1thelyez\u00e9s... ConfigView.section.connection.advanced.info.link=Kattintson ide tov\u00e1bbi inform\u00e1ci\u00f3k\u00e9rt ConfigView.section.connection.advanced.socket.group=Socket Be\u00e1ll\u00edt\u00e1sok ConfigView.section.connection.advanced.bind_port=Helyi IP c\u00edmhez k\u00f6t\u00e9s [0: tilt\u00e1s] ConfigView.section.connection.advanced.bind_port.tooltip=A kimen\u0151 socket kapcsolatok a megadott porttal lesznek \u00f6sszek\u00f6tve.\u005cEnnek az enged\u00e9lyez\u00e9se seg\u00edthet kik\u00fcsz\u00f6b\u00f6lni a NAT routerekkel val\u00f3 inkompatibilit\u00e1sokat. ConfigView.section.proxy.group.tracker=Kommunik\u00e1l\u00e1s a treckerrel ConfigView.section.proxy.group.peer=Kommunik\u00e1l\u00e1s a peerekkel Pieces.column.Requested=K\u00e9rve Pieces.column.Requested.info=Mutassa, ha t\u00f6bb k\u00e9r\u00e9s is lehet egy szeletre vagy nem (*) ConfigView.label.maxuploadsseeding=Felt\u00f6lt\u00e9s eset\u00e9n MyTorrentsView.filter=Sz\u0171r\u0151: popup.error.hideall=Mindet Elrejti ConfigView.section.style.dataStatsOnly=Csak adatstatisztika megjelen\u00edt\u00e9se (protokollstatisztika elrejt\u00e9se) ConfigView.section.style.separateProtDataStats=Mutassa k\u00fcl\u00f6n az adat- \u00e9s protokollstatistik\u00e1t, mint 'Adat' (protokoll) MyTorrentsView.dialog.setFilter.title=Sz\u0171r\u0151 M\u00f3dos\u00edt\u00e1sa MyTorrentsView.dialog.setFilter.text=A %1 r\u00e9sz a lent megadott sz\u00f6veggel lesz megsz\u0171rve. Haszn\u00e1ld a | (vonal) szimbolumot a t\u00f6bb menet\u0171 sz\u0171r\u00e9shez. MyTorrentsView.filter.tooltip=Ctrl+X-szel v\u00e1lthatsz a RegEx \u00e9s a norm\u00e1l keres\u00e9s k\u00f6z\u00f6tt.\nHaszn\u00e1ld a | (vonal) szimbolumot a t\u00f6bbl\u00e9pcs\u0151s sz\u0171r\u00e9shez. MyTorrentsView.clearFilter.tooltip=Sz\u0171r\u0151 T\u00f6rl\u00e9se MyTorrentsView.menu.filter=F\u00e1jllista... ConfigView.section.file.resume.recheck.all=Hiba eset\u00e9n a k\u00f6vetkez\u0151 ind\u00edt\u00e1skor az \u00f6sszes csomagot leellen\u0151rzi. (Egy\u00e9bk\u00e9nt csak az \u00e9ppen akt\u00edv csomagokat vizsg\u00e1lja \u00fajra - gyorsabb) ConfigureWizard.language.choose=V\u00e1lasszon egy nyelvet a lenti list\u00e1b\u00f3l: popup.closing.in=Ablak bez\u00e1r\u00e1sa %1 mp m\u00falva popup.more.waiting=%1 \u00fczenet van m\u00e9g.. # > 2402 popup.download.finished="%1" let\u00f6lt\u00e9se befejezve. popup.file.finished="%1" let\u00f6lt\u00e9se befejezve. Plugin.localtracker.autoadd.info=Automatikusan adja hozz\u00e1 a k\u00f6vetkez\u0151 helyi \u00fcgyfeleket [a c\u00edmek ';'-al elv\u00e1lasztva, pl. 1.2.3.4] Plugin.localtracker.autoadd=Ny\u00edlt \u00fcgyfelek Plugin.localtracker.networks.info=A k\u00f6vetkez\u0151 helyi kapcsolatokat vegye figyelembe [a c\u00edmek ';'-al elv\u00e1lasztva , pl.: 145.227.*.*] Plugin.localtracker.networks=Helyi h\u00e1l\u00f3zatok MainWindow.menu.view.plugins.logViews=Napl\u00f3 SpeedView.stats.autospeed=Automatikus Felt\u00f6lt\u00e9si Sebess\u00e9g SpeedView.stats.autospeed.disabled=Ez a Tulajdons\u00e1g vagy ki van kapcsolva (sz\u00fcks\u00e9ges a DHT), vagy nincs haszn\u00e1latban (k\u00e9zi felt\u00f6lt\u00e9si sebess\u00e9g lett be\u00e1ll\u00edtva) SpeedView.stats.idlePing=\u00dcresj\u00e1rati Ping: SpeedView.stats.currentPing=Jelenlegi Ping: SpeedView.stats.maxUp=Max Felt\u00f6lt\u00e9si Sebess\u00e9g: ConfigView.pluginlist.unloadSelected=Kiv\u00e1lasztottak le\u00e1ll\u00edt\u00e1sa ConfigView.pluginlist.scan=Pluginek keres\u00e9se ConfigView.section.transfer.autospeed=Automatikus sebess\u00e9g ConfigView.section.transfer.autospeed.tooltip=Automatikus sebess\u00e9gszab\u00e1lyoz\u00e1s be\u00e1ll\u00edt\u00e1sa ConfigView.section.transfer.autospeed.info=Az automatikus sebess\u00e9gszab\u00e1lyoz\u00e1s automatikusan lekorl\u00e1tozza a felt\u00f6lt\u00e9si sebess\u00e9get, hogy megakad\u00e1lyozza az internetkapcsolat t\u00falterhel\u00e9s\u00e9t.\n\nA korl\u00e1toz\u00e1sok csak akkor l\u00e9pnek \u00e9rv\u00e9nybe, ha enged\u00e9lyezed ezt a lehet\u0151s\u00e9get \u00e9s az elosztott adatb\u00e1zis enged\u00e9lyezve van.\n ConfigView.section.transfer.autospeed.minupload=%1 minim\u00e1lis felt\u00f6lt\u00e9si sebess\u00e9g ConfigView.section.transfer.autospeed.minupload.tooltip=A felt\u00f6lt\u00e9si sebess\u00e9g nem cs\u00f6kken lentebb ConfigView.section.transfer.autospeed.maxupload=%1 maxim\u00e1lis felt\u00f6lt\u00e9si sebess\u00e9g [0: korl\u00e1tlan] ConfigView.section.transfer.autospeed.maxupload.tooltip=A felt\u00f6lt\u00e9si sebess\u00e9g nem n\u00f6vekszik tov\u00e1bb ConfigView.section.transfer.autospeed.chokeping=Elt\u00f6m\u0151d\u00e9s Pind ideje [milisec] ConfigView.section.transfer.autospeed.chokeping.tooltip=Ha a Ping ideje meghaladja ezt az \u00e9rt\u00e9ket, akkor a h\u00e1l\u00f3zatot tel\u00edtettnek tekinti ConfigView.section.transfer.autospeed.enableauto=Enged\u00e9lyez\u00e9s let\u00f6lt\u00e9sn\u00e9l \u00e9s felt\u00f6lt\u00e9sn\u00e9l ConfigView.section.transfer.autospeed.enableautoseeding=Enged\u00e9lyez\u00e9s csak felt\u00f6lt\u00e9sn\u00e9l ConfigView.pluginlist.column.unloadable=Nem beolvashat\u00f3 ConfigView.section.transfer.lan.enable=K\u00fcl\u00f6nb\u00f6z\u0151 sebess\u00e9gkorl\u00e1toz\u00e1s a h\u00e1l\u00f3zati kapcsolatokhoz Plugin.localtracker.wellknownlocals=Automatikusan vegye figyelembe a hurkokat/linkeket/helyi c\u00edmeket (192.168.*.*, stb.) TableColumn.header.filesdone=K\u00e9sz F\u00e1jlok TableColumn.header.filesdone.info=K\u00e9sz F\u00e1jlok/Minden f\u00e1jl *vagy* nem kihagyott k\u00e9sz f\u00e1jlok (K\u00e9sz f\u00e1jlok)/Minden nem kihagyott f\u00e1jl (Minden f\u00e1jl) MagnetPlugin.private_torrent= MagnetPlugin.decentral_disabled= MagnetPlugin.decentral_backup_disabled= MagnetPlugin.report.waiting_ddb=v\u00e1rakotz\u00e1s a DDB fel\u00e9p\u00edt\u00e9s\u00e9re... MagnetPlugin.report.searching=keres\u00e9s... MagnetPlugin.report.found=tal\u00e1lt %1 MagnetPlugin.report.alive=%1 el\u00e9rhet\u0151 MagnetPlugin.report.dead=%1 halott MagnetPlugin.report.tunnel=csatorna l\u00e9trehoz\u00e1sa %1 MagnetPlugin.report.downloading=let\u00f6lt\u00e9s a k\u00f6vetkez\u0151t\u0151l: %1 MagnetPlugin.report.error=hiba %1 MagnetURLHandler.report.no_sources=nem tal\u00e1lhat\u00f3 forr\u00e1s a torrenthez MagnetURLHandler.report.torrent_size=torrent m\u00e9rete: %1 MagnetURLHandler.report.percent=befejezve: %1% MagnetURLHandler.report.error=hiba %1 DHTTransport.report.request_all=teljes adat\u00e1tvitel k\u00e9r\u00e9se: %1 DHTTransport.report.received_bit=fogadott %1 - %2 felad\u00f3: %3 DHTTransport.report.complete=befejezve DHTTransport.report.timeout=id\u0151t\u00fall\u00e9p\u00e9s, nincs v\u00e1lasz: %1 DHTTransport.report.rerequest_all=teljes adat\u00e1tvitel \u00fajrak\u00e9r\u00e9se: %1 DHTTransport.report.rerequest_bit=\u00fajrak\u00e9r\u00e9s %1 - %2 felad\u00f3: %3 DHTTransport.report.timeout_some=id\u0151t\u00fall\u00e9p\u00e9s, %1 csomag \u00e9rkezett %2-t\u0151l, de nincs k\u00e9sz DHTTransport.report.sending=adat k\u00fcld\u00e9se DHTTransport.report.resending=adat \u00fajrak\u00fcld\u00e9se DHTTransport.report.send_complete=k\u00fcld\u00e9s k\u00e9sz DHTTransport.report.send_timeout=id\u0151t\u00fall\u00e9p\u00e9s ConfigView.section.transfer.autospeed.enabledebug=K\u00e9s\u0151bbi hibafelder\u00edt\u00e9st seg\u00edt\u0151 napl\u00f3z\u00e1s TableColumn.header.date_added=D\u00e1tum hozz\u00e1adva TableColumn.header.date_added.info=A torrent hozz\u00e1adva ConfigView.section.file.hashchecking.smallestfirst=A kisebb let\u00f6lt\u00e9seket ellen\u0151rizze el\u0151sz\u00f6r platform.win32.baddll.info=Vuze \u00e9szlelte a '%1'-t. Ez a '%2' r\u00e9sze, ami sok hib\u00e1t okoz, mintp\u00e9ld\u00e1ul program\u00f6sszeoml\u00e1s, vagy magas CPU haszn\u00e1lat. Ha tiszt\u00e1ba vagy ezekkel, akkor t\u00e1vol\u00edtsd el a programot, vagy \u00e1ll\u00edtsd be, hogy ne zavarja az Azureust. upnp.ignorebaddevices=Ne vegye figyelembe azokat az eszk\u00f6z\u00f6ket, amelyek hib\u00e1san v\u00e1laszolnak a k\u00e9r\u00e9sre upnp.ignorebaddevices.info=Jelenleg figyelmen k\u00edv\u00fcl hagyott eszk\u00f6z\u00f6k: %1 upnp.ignorebaddevices.reset=Kihagyott eszk\u00f6z\u00f6k list\u00e1j\u00e1nak t\u00f6rl\u00e9se upnp.ignorebaddevices.reset.action=T\u00f6rl\u00e9s upnp.ignorebaddevices.alert=UPnP eszk\u00f6z, %1 c\u00edmen mell\u0151zve, t\u00f6bbsz\u00f6ri hiba miatt.. N\u00e9zd meg az UPnP plugin ide ill\u0151 be\u00e1ll\u00edt\u00e1sait. TorrentOptionsView.param.max.uploads.when.busy=Max felt\u00f6lt\u00e9si sebess\u00e9g (KB/s), amikor a Glob\u00e1lis felt\u00f6lt\u00e9si sebess\u00e9get el\u00e9rte [0: tiltva] UpdateMonitor.messagebox.verification.failed.title=Ellen\u0151rz\u00e9s Telep\u00edt\u00e9si Hiba UpdateMonitor.messagebox.verification.failed.text='%1' ellen\u0151rz\u00e9se nem siker\u00fclt: %2 UpdateMonitor.messagebox.accept.unverified.title=Ellen\u0151rizetlen Telep\u00edt\u00e9s Elfogadva UpdateMonitor.messagebox.accept.unverified.text='%1' nem lehet ellen\u0151rizni, mint eredeti Vuze plugin.\nLehet, hogy egy nem megb\u00edzhat\u00f3 plugin.\nFolytatod a telep\u00edt\u00e9st? FileView.BlockView.title=Csomag FileView.BlockView.Done=K\u00e9sz FileView.BlockView.Skipped=Kihagyott FileView.BlockView.Active=Akt\u00edv FileView.BlockView.Outstanding=Esed\u00e9kes ConfigView.label.tcplistenport=Bej\u00f6v\u0151 TCP port ConfigView.label.udplistenport=Bej\u00f6v\u0151 UDP port upnp.portchange.alert=A k\u00f6vetkez\u0151 port megv\u00e1ltozott, egy UPnP hiba elker\u00fcl\u00e9se miatts: %1 [r\u00e9gi port=%2] %3 [r\u00e9gi port=%4] ConfigView.section.proxy.username.info=Ha a proxy szerver hiteles\u00edt\u00e9st k\u00e9r akkor is amikor nincsen adat megadva, akkor haszn\u00e1ld a "" sz\u00f6veget felhaszn\u00e1l\u00f3n\u00e9vk\u00e9nt ConfigView.label.maxuploadswhenbusymin=Torrentenk\u00e9nti max felt\u00f6lt\u00e9si sebess\u00e9g foglalt id\u0151ben [sec] MainWindow.menu.help.debug=Hibakeres\u00e9si Inf\u00f3 K\u00e9sz\u00edt\u00e9se DownloadManager.error.badsize=Hib\u00e1s m\u00e9ret natpmp.info=A NAT-PMP az Apple alternat\u00edv megold\u00e1sa az UPnP-re, amely a legt\u00f6bb rept\u00e9ren t\u00e1mogatott elj\u00e1r\u00e1s.\n\nJegyezd meg, hogy a sima UPnP lehet\u0151s\u00e9gnek enged\u00e9lyzeve kell lennie ahhoz, hogy a NAT-PMP haszn\u00e1lhat\u00f3 legyen. (A NAT-PMP eszk\u00f6z a sima UPnP eszk\u00f6z\u00f6k speci\u00e1lis v\u00e1ltozatai) natpmp.enable=Enged\u00e9lyezve (a rept\u00e9ri be\u00e1ll\u00edt\u00e1sok haszn\u00e1lat\u00e1hoz mindenk\u00e9ppen enged\u00e9lyezned kell) ConfigView.section.tracker.host.addurls=Ellen\u00f6rizze, hogy a tracker URL jelen van a kiszolg\u00e1lt torrentekn\u00e9l ConfigView.filter=Sz\u0171rend\u0151 sz\u00f6veg ConfigView.section.files.move=Elk\u00e9sz\u00fclt f\u00e1jlok mozgat\u00e1sa ConfigView.section.file.defaultdir.section=Alap\u00e9rtelmezett K\u00f6nyvt\u00e1r Be\u00e1ll\u00edt\u00e1sai ConfigView.section.file.defaultdir.auto=Let\u00f6lt\u00e9s az alap\u00e9rtelmezett k\u00f6nyvt\u00e1rba (Meger\u0151s\u00edt\u00e9s n\u00e9lk\u00fcl) ConfigView.section.file.defaultdir.bestguess=Haszn\u00e1lja a legjobb becsl\u00e9st az alap\u00e9rtelmezett mappa v\u00e1laszt\u00e1sakor ConfigView.section.file.defaultdir.ask=Alap\u00e9rtelmezett mappa: ConfigView.section.file.defaultdir.lastused=Az utolj\u00e1ra haszn\u00e1lt k\u00f6nyvt\u00e1r legyen az alap\u00e9rtelmezett ment\u00e9s helye ConfigView.section.file.config.section=Be\u00e1ll\u00edt\u00e1sok ConfigView.section.file.config.currentdir=Aktu\u00e1lis be\u00e1ll\u00edt\u00e1sok k\u00f6nyvt\u00e1r: ConfigView.section.torrent.decoding=Karakter k\u00f3dol\u00e1sa ConfigView.section.logging.udptransport=B\u0151 UDP adat\u00e1tvitel k\u00f6vet\u00e9s enged\u00e9lyez\u00e9se Tracker.announce.ignorePeerSeed=Kihagyott \u00dcgyf\u00e9lek/K\u00e9szforr\u00e1sok sz\u00e1ma. %1 ConfigView.section.connection.encryption.use_crypto_port=Haszn\u00e1lja a 'cryptoport' tracker kiterjeszt\u00e9st a ny\u00edlt bej\u00f6v\u0151 kapcsolatok megakad\u00e1lyoz\u00e1s\u00e1ra. N\u00e9h\u00e1ny torrent hib\u00e1val (Helytelen port) reag\u00e1l ennek a haszn\u00e1lat\u00e1ra TorrentOptionsView.param.reset.to.default=Alap\u00e9rtelmezett be\u00e1ll\u00edt\u00e1sok vissza\u00e1ll\u00edt\u00e1sa TorrentOptionsView.param.reset.button=T\u00f6r\u00f6l natpmp.routeraddress=Rept\u00e9r c\u00edme [\u00fcres: auto] ConfigView.section.style.disableAlertSliding=Becs\u00fasz\u00f3 anim\u00e1ci\u00f3/mindig fel\u00fcl st\u00edlus\u00fa figyelmeztet\u00e9sek tilt\u00e1sa ConfigView.section.transfer.autospeed.maxinc=%1 maxim\u00e1lis n\u00f6vel\u00e9s k\u00f6r\u00f6nk\u00e9nt ConfigView.section.transfer.autospeed.maxdec=%1 maxim\u00e1lis cs\u00f6kkent\u00e9s k\u00f6r\u00f6nk\u00e9nt ConfigView.section.transfer.autospeed.enabledownadj=Let\u00f6lt\u00e9si sebess\u00e9g szab\u00e1lyoz\u00e1sa ConfigView.section.transfer.autospeed.downadjratio=Let\u00f6lt\u00e9s : Felt\u00f6lt\u00e9s sebess\u00e9g\u00e9nek ar\u00e1nya (Pl.: 2.0 -> let\u00f6lt\u00e9si sebess\u00e9g k\u00e9tszer akkora mint a felt\u00f6lt\u00e9si sebess\u00e9g) ConfigView.section.transfer.autospeed.latencyfactor=A kapcsolat k\u00e9sleltet\u00e9se, melyb\u0151l a sebess\u00e9gv\u00e1ltoz\u00e1s kisz\u00e1m\u00edthat\u00f3 (nagy \u00e9rt\u00e9k cs\u00f6kkenti az \u00e9rz\u00e9kenys\u00e9get) ConfigView.section.transfer.autospeed.reset=Alap\u00e9rtelmezett \u00e9rt\u00e9kek vissza\u00e1ll\u00edt\u00e1sa ConfigView.section.transfer.autospeed.reset.button=T\u00f6r\u00f6l PeerColumn.activationCount=Kapcsol\u00f3d\u00f3 \u00fcgyfelek: %1 TableColumn.header.timesincedownload.info=Utols\u00f3 let\u00f6lt\u00e9s \u00f3ta eltelt id\u0151 TableColumn.header.timesincedownload=Let\u00f6lt\u00e9s ideje TableColumn.header.timesinceupload.info=Utols\u00f3 felt\u00f6lt\u00e9s \u00f3ta eltelt id\u0151 TableColumn.header.timesinceupload=Felt\u00f6lt\u00e9s ideje PeersView.incomingreqcount=K\u00e9r\u00e9s(be) PeersView.incomingreqcount.info=\u00dcgyf\u00e9l bej\u00f6v\u0151 k\u00e9r\u00e9seinek sz\u00e1ma PeersView.outgoingreqcount=K\u00e9r\u00e9s(ki) PeersView.outgoingreqcount.info=\u00dcgyf\u00e9l kimen\u0151 k\u00e9r\u00e9seinek sz\u00e1ma upnp.mapping.trackerclientudp=UDP Tracker Kliens Port upnp.mapping.dhtudp=Elosztott Adatb\u00e1zis ConfigView.section.connection.nondata.udp.same=Azonos UDP port haszn\u00e1lata az ElosztottAadatb\u00e1zis \u00e9s az UDP Tracker fel\u00e9 ConfigView.section.connection.tcp.enable=TCP Enged\u00e9lyez\u00e9se ConfigView.section.connection.udp.enable=UDP Enged\u00e9lyez\u00e9se ConfigView.section.style.showiconbar=Eszk\u00f6zt\u00e1r mutat\u00e1sa MainWindow.menu.view.iconbar=Eszk\u00f6zt\u00e1r MyTorrentsView.menu.rename=\u00c1tnevez MyTorrentsView.menu.rename.displayed=Megjelen\u0151 N\u00e9v \u00c1tnevez\u00e9se MyTorrentsView.menu.rename.save_path=Ment\u00e9si \u00dat \u00c1tnevez\u00e9se MyTorrentsView.menu.rename.displayed.enter.title=Megjelen\u0151 N\u00e9v \u00c1tnevez\u00e9se MyTorrentsView.menu.rename.displayed.enter.message=Add meg a let\u00f6lt\u00e9s \u00faj nev\u00e9t\nHa nem adsz be semmit, akkor az eredeti fog megjelenni. MyTorrentsView.menu.edit_comment=Megjegyz\u00e9s szerkeszt\u00e9se MyTorrentsView.menu.edit_comment.enter.title=Megjegyz\u00e9s szerkezt\u00e9se MyTorrentsView.menu.edit_comment.enter.message=\u00cdrj be egy megjegyz\u00e9st a let\u00f6lt\u00e9shez UIDebugGenerator.messageask.title=Hibakeres\u0151 Gener\u00e1l\u00f3 UIDebugGenerator.messageask.text=K\u00e9sz\u00edts egy le\u00edr\u00e1st a hib\u00e1r\u00f3l, amit jelenteni szeretn\u00e9l UIDebugGenerator.complete.title=Hibakeres\u00e9s Gener\u00e1l\u00e1sa Befejezve UIDebugGenerator.complete.text=K\u00fcld el a '%1' f\u00e1jlt a az-bugreports@azureus-inc.com c\u00edmre\n\n Az OK gombbal a f\u00e1jlhoz ugrassz. ConfigView.section.style.showProgramIcon=Program ikonj\u00e1nak mutat\u00e1sa a n\u00e9v oszlopban ConfigView.section.style.showProgramIcon.tooltip=\u00dajranyit\u00e1s sz\u00fcks\u00e9ges a be\u00e1ll\u00edt\u00e1sok \u00e9rv\u00e9nyes\u00edt\u00e9s\u00e9hez swt.alert.cant.update="%3" helyr\u0151l bet\u00f6lt\u00f6tt SWT k\u00f6nyvt\u00e1rat nem lehet automatikusan friss\u00edteni a %1 verzi\u00f3r\u00f3l a %2 verzi\u00f3ra (innen kell let\u00f6lteni: "%4"). N\u00e9zd meg a wiki-t a r\u00e9szletek\u00e9rt. authenticator.savepassword=Jelsz\u00f3 megjegyz\u00e9se ConfigView.section.security.clearpasswords=T\u00e1rolt jelszavak t\u00f6rl\u00e9se ConfigView.section.security.clearpasswords.button=T\u00f6r\u00f6l Content.alert.notuploaded.title=A Felt\u00f6lt\u00e9s Nem Teljes Content.alert.notuploaded.text=A '%1' felt\u00f6lt\u00e9s nincsen befejezve. Ha most %2, nem lehet majd let\u00f6lteni a k\u00f6zz\u00e9tett anyagot.\n\nBizosan %2? Content.alert.notuploaded.multi.title=Felt\u00f6lt\u00e9s nem teljes Content.alert.notuploaded.multi.text=%1 k\u00f6z\u00e9tett anyaghoz nincs felt\u00f6lt\u0151. Ha most %2 , nem tudj\u00e1k teljesen befejezni az \u00e1ltalad megosztott munk\u00e1t. Biztoan %2?\n\nNincs m\u00e1s Seeder:\n%3 Content.alert.notuploaded.stop=\u00e1llj Content.alert.notuploaded.quit=Vuze bez\u00e1r\u00e1sa TorrentInfoView.torrent.encoding=Torrent k\u00f3dol\u00e1sa TorrentInfoView.columns=Oszlopok a 'Torrentjeim' n\u00e9zetb\u0151l progress.window.title=Feldolgoz\u00e1s folyamatban progress.window.msg.filemove=K\u00e9rem v\u00e1rjon, am\u00edg a f\u00e1jl \u00e1tnevez\u00e9se/\u00e1thelyez\u00e9se be nem fejez\u0151dik ConfigView.label.popup.timestamp=Id\u0151 hozz\u00e1ad\u00e1sa az \u00fczenetekhez ConfigView.label.popup.autohide=Automatikusan rejtse el az \u00fczeneteket x m\u00e1sodperc ut\u00e1n (0 = automatikus bez\u00e1r\u00e1s tilt\u00e1sa) ConfigView.label.popup.suppress_alerts=Figyelmeztet\u00e9sek eldob\u00e1sa ConfigView.label.popup.use_message_boxes=Felugr\u00f3 ablakok hazsn\u00e1lata az alap felugr\u00f3 figyelmeztet\u00e9sek helyett. ConfigView.label.popup.show=Minden napl\u00f3zott felugr\u00f3 figyelmeztet\u00e9s megjelen\u00edt\u00e9se (ha van) ConfigView.label.popup.show.button=Mutat ConfigView.label.please.visit.here=Kattintson ide tov\u00e1bbi inform\u00e1ci\u00f3k\u00e9rt ConfigView.section.ipfilter.enable.descriptionCache=IP-c\u00edmek tulajdons\u00e1gainak t\u00e1rol\u00e1sa egy le\u00edr\u00f3f\u00e1jlban ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Ha kikapcsolod, akkor a megjegyz\u00e9sek elvesznek OpenTorrentWindow.filesInfo=%1 -b\u00f3l %2 lesz let\u00f6ltve. OpenTorrentWindow.diskUsage=%1 a %2-b\u00f3l/b\u0151l ConfigView.label.openmytorrents='Torrentjeim' megnyit\u00e1sa ind\u00edt\u00e1skor ConfigView.label.open_transfer_bar_on_start=\u00c1tvitel S\u00e1v megnyit\u00e1sa ind\u00edt\u00e1skor ConfigView.section.style.DNDalwaysInIncomplete=Mindig mutassa a torrenteket a Befejezettlen r\u00e9szben, ha van a 'Ne t\u00f6ltse le' f\u00e1jl OpenTorrentWindow.mb.noGlobalDestDir.title=Megadott Mappa nem tal\u00e1lhat\u00f3 OpenTorrentWindow.mb.noGlobalDestDir.text=A megadott mapaa '%1' nem l\u00e9tezik vagy hib\u00e1s. OpenTorrentWindow.mb.noDestDir.title=Megadott Mappa nem tal\u00e1lhat\u00f3 OpenTorrentWindow.mb.noDestDir.text=A '%2' torrenthez megadott mappa '%1' nem l\u00e9tezik vagy hib\u00e1s. OpenTorrentWindow.mb.notValid.title=Torrent Megnyit\u00e1sa OpenTorrentWindow.mb.notValid.text=Nem lehet megnyitni a torrentet '%1'. Ha seedel\u00e9shez nyitot meg, akkor ellen\u0151rizd, hogy a f\u00e1jl(ok) l\u00e9tezik-e. OpenTorrentWindow.mb.notTorrent.title=Torrent Megnyit\u00e1sa OpenTorrentWindow.mb.notTorrent.text=Nem lehet megnyitni '%1'. Val\u00f3sz\u00edn\u0171leg nem torrent f\u00e1jl.\n\nN\u00e9h\u00e1ny adat feldolgozva:\n%2 ConfigView.label.pause.downloads.on.exit=Let\u00f6lt\u00e9sek sz\u00fcneteltet\u00e9se kil\u00e9p\u00e9sn\u00e9l ConfigView.label.resume.downloads.on.start=Let\u00f6lt\u00e9sek folytat\u00e1sa ind\u00edt\u00e1sn\u00e1l UIDebugGenerator.message.cancel.title=Hibakeres\u00e9si Inform\u00e1ci\u00f3 Gener\u00e1l\u00e1sa Kihagyva UIDebugGenerator.message.cancel.text=Nem adt\u00e1l meg le\u00edr\u00e1st a hib\u00e1hoz, amit jelenteni akarsz. A hiba egy\u00e9rtelm\u0171 lehet a sz\u00e1modra, de le\u00edr\u00e1s n\u00e9lk\u00fcl nem tudjuk meghat\u00e1rozni.\n\nHibakeres\u00e9si Inform\u00e1ci\u00f3 Gener\u00e1l\u00e1sa mell\u0151zve. ConfigView.section.connection.group.http.info=HTTP seed t\u00e1mogat\u00e1sa. ConfigView.section.connection.http.enable=Enged\u00e9lyez ConfigView.section.connection.http.port=Bej\u00f6v\u0151 port sz\u00e1ma ConfigView.section.connection.http.portoverride=Kiszolg\u00e1l\u00f3 HTTP Port fel\u00fcl\u00edr\u00e1sa [0: nincs] window.update.noupdates.title=Friss\u00edt\u00e9s Eredm\u00e9ny\u00e9nek megtekint\u00e9se window.update.noupdates.text=Nincs el\u00e9rhet\u0151 friss\u00edt\u00e9s.\n\nGratul\u00e1lok! ConfigView.label.bindip.details=P\u00e9ld\u00e1ul: 192.168.1.5;eth0;eth1[2] a megadott IP-hez fogja k\u00f6tni az els\u0151 interf\u00e9szn\u00e9l.\nAz els\u0151 IP-t minden szolg\u00e1ltat\u00e1s haszn\u00e1lja, t\u00f6bbit a forgalom eloszt\u00e1s\u00e1ra haszn\u00e1lj\u00e1k.\nA k\u00f6vetkez\u0151 interf\u00e9szek \u00e9rhet\u0151k el:\n%1 ConfigView.label.mindownloads=Min egyidej\u0171 let\u00f6lt\u00e9s UI.cannot_submit_blank_text=\u00cdrj be egy \u00e9rt\u00e9ket. crypto.alert.as.warning=H\u00e1l\u00f3zat '%1' m\u00f3dos\u00edtja a forgalom zervez\u0151t, hogy cs\u00f6kkentse a let\u00f6lt\u00e9st. A titkos\u00edt\u00e1s automatikusan bekapcsol - ezt ki lehet kapcsolni/m\u00f3dos\u00edtani a be\u00e1ll\u00edt\u00e1sokban. ConfigView.section.interface.alerts=Figyelmztet\u00e9sek ConfigView.label.popupdownloadadded=Felugr\u00f3 \u00fczenet egy torrent hozz\u00e1ad\u00e1sakor popup.download.added="%1" hozz\u00e1adva a let\u00f6lt\u00e9si list\u00e1hoz. MessageBoxWindow.nomoreprompting=Ne k\u00e9rdezze meg \u00fajb\u00f3l TorrentOptionsView.param.max.seeds=K\u00e9szforr\u00e1s kapcsolatok maxim\u00e1lis sz\u00e1ma [0: kapcsolatlimit] TorrentOptionsView.param.alternative.value.enable=Alternat\u00edv \u00e9rt\u00e9k k\u00e9szforr\u00e1s m\u00f3dban ConfigView.section.proxy.check.on.start=Proxy \u00e1llapot ellen\u0151rz\u00e9se ind\u00edt\u00e1skor TransferStatsView.legend.pingaverage=\u00c1tlag TransferStatsView.legend.ping1=C\u00e9l 1 TransferStatsView.legend.ping2=C\u00e9l 2 TransferStatsView.legend.ping3=C\u00e9l 3 ConfigView.section.interface.enabletray._mac=\u00c1llapotikon enged\u00e9lyez\u00e9se [\u00fajraind\u00edt\u00e1st ig\u00e9nyel] ConfigView.label.closetotray._mac=Kicsiny\u00edt\u00e9s bez\u00e1r\u00e1sa \u00c1llapotsor ikonba ConfigView.label.minimizetotray._mac=Kicsiny\u00edt\u00e9s \u00c1llapotsor ikonba OpenTorrentWindow.mb.existingFiles.title=A f\u00e1jl m\u00e1r l\u00e9tezik! OpenTorrentWindow.mb.existingFiles.text=N\u00e9h\u00e1ny f\u00e1jl m\u00e1r l\u00e9tezik a megadott c\u00e9lmapp\u00e1ban:\n\nHa folytatod, akkor az Vuze leellen\u0151rzi az eml\u00edtett f\u00e1jlokat, \u00e9s m\u00f3dos\u00edtja ha sz\u00fcks\u00e9ges. splash.unloadingTorrents=Torrentek Felt\u00f6lt\u00e9se splash.unloadingTorrent=Torrent Felt\u00f6lt\u00e9se ConfigView.section.file.defaultdir.autorename=Torrent adatok automatikus \u00e1tnevez\u00e9se, ha a f\u00e1jl el\u00e9r\u00e9si \u00fat m\u00e1s ConfigView.section.file.defaultdir.autorename.tooltip=Ez megakad\u00e1lyozza, hogy egy torrent fel\u00fcl\u00edrja a m\u00e1sik torrent f\u00e1jljait, ha a f\u00e1jln\u00e9v egyezik alert.raised.at.close=(\u00dczenet az Vuze kor\u00e1bbi bez\u00e1r\u00e1sakor) Plugin.trackerpeerauth.name=Tracker Peer Hiteles\u00edt\u00e9s Plugin.trackerpeerauth.info=A b\u0151v\u00edtm\u00e9ny a tracker seg\u00edts\u00e9g\u00e9vel ellen\u0151rzi, hogy az \u00fcgyf\u00e9l \u00e9rv\u00e9nyes tag-e a bolyban Peers.column.maxupspeed=Max Let\u00f6lt\u00e9s Peers.column.maxdownspeed=Max Felt\u00f6lt\u00e9s MyTorrents.items.DownSpeedLimit.disabled=Nincs let\u00f6lt\u00e9s upnp.selectedaddresses=C\u00edm (';' elv\u00e1laszt\u00f3, '-' el\u0151tag=tilt, '+' =enged [\u00fcres: mind] upnp.alert.multipledevice.warning=T\u00f6bb UPnP eszk\u00f6z tal\u00e1lhat\u00f3 - ellen\u0151rizd, hogy mindegyikhez sz\u00fcks\u00e9ges-e portkioszt\u00e1s ( UPnP napl\u00f3 \u00e9s be\u00e1ll\u00edt\u00e1s) UpdateMonitor.messagebox.restart.title=Szoftware Friss\u00edt\u00e9s UpdateMonitor.messagebox.restart.text=Az Vuze befejezte egy fontos friss\u00edt\u00e9s let\u00f6lt\u00e9s\u00e9t, a telep\u00edt\u00e9shez \u00fajraind\u00edt\u00e1s sz\u00fcks\u00e9ges. PiecesView.BlockView.Have=Van PiecesView.BlockView.NoHave=Nincs PiecesView.BlockView.Header=%1 sor, %2 oszlop, %3 darab ConfigView.section.update.autodownload=Friss\u00edt\u00e9sek automatikus let\u00f6lt\u00e9se, \u00e9s figyelmeztessen ha a telep\u00edt\u00e9s befejez\u0151d\u00f6tt Peers.column.peer_id.info=Peer ID olvashat\u00f3 form\u00e1ban Peers.column.peer_byte_id.info=Peer ID b\u00e1jtban Peers.column.handshake_reserved=K\u00e9zfog\u00e1sra Lefoglalt Byte Peers.column.handshake_reserved.info=Mutatja, hogy mely bitek vannak lefoglalva BT k\u00e9zfog\u00e1sra Peers.column.client_identification=Kliens Azonos\u00edt\u00f3 Peers.column.client_identification.info=Mutassa a nyers kliensnevet, amit az Vuze kapott - hasznos hibakeres\u00e9sn\u00e9l dht.warn.user=Poteci\u00e1lis NAT/port kioszt\u00e1si hiba jelz\u00e9se ConfigView.label.openbar.incomplete=Let\u00f6lt\u00e9s: let\u00f6lt\u00e9sek automatikus megnyit\u00e1sa ConfigView.label.openbar.complete=seedek automatkus megnyit\u00e1sa ConfigView.label.transferbar.remember_location=Jegyezze meg az \u00c1tviteli S\u00e1v poz\u00edci\u00f3j\u00e1t ConfigView.section.transfer.autospeed.forcemin=%1 felt\u00f6lt\u00e9si sebes\u00e9g be\u00e1ll\u00edtva, alap kapcsolatn\u00e1l MainWindow.menu.tools.speedtest=Sebess\u00e9gteszt... speedtest.wizard.title=Sebess\u00e9gteszt speedtest.wizard.run=Sebess\u00e9gteszt futtat\u00e1sa speedtest.wizard.test.mode.updown=felt\u00f6lt\u00e9s \u00e9s let\u00f6lt\u00e9s speedtest.wizard.test.mode.up=felt\u00f6lt\u00e9s speedtest.wizard.test.mode.down=let\u00f6lt\u00e9s SpeedTestWizard.test.panel.currinfo=BitTorrent sebess\u00e9gtesz. SpeedTestWizard.test.panel.label=Vuze sebess\u00e9gteszt: SpeedTestWizard.test.panel.already.running=A teszt m\u00e1r fut! SpeedTestWizard.test.panel.not.accepted=A teszt k\u00e9r\u00e9se nem elfogadhat\u00f3: SpeedTestWizard.test.panel.abort=M\u00e9gsem SpeedTestWizard.test.panel.abort.countdown=Teszt le\u00e1ll: SpeedTestWizard.test.panel.test.countdown=teszt k\u00e9sz: SpeedTestWizard.test.panel.testfailed=Teszt sikertelen SpeedTestWizard.test.panel.aborted=A tesztet a felhaszn\u00e1l\u00f3 megszak\u00edtotta. SpeedTestWizard.test.panel.enc.label=Kattints ide a titkos\u00edtott tesztel\u00e9shez: SpeedTestWizard.test.panel.standard=alap SpeedTestWizard.test.panel.encrypted=titkos\u00edtva SpeedTestWizard.set.upload.button.apply=Alkalmaz SpeedTestWizard.set.upload.result=Utols\u00f3 Tezst Eredm\u00e9nye SpeedTestWizard.finish.panel.title=Sebess\u00e9gteszt Befejezve! SpeedTestWizard.finish.panel.click.close=A Sebess\u00e9gtezst var\u00e1zsl\u00f3 v\u00e9get \u00e9rt. Kattints a bez\u00e1r\u00e1sra. SpeedTestWizard.finish.panel.max.upload=Max felt\u00f6lt\u00e9s : SpeedTestWizard.finish.panel.max.seeding.upload=Max felt\u00f6lt\u00e9s seedel\u00e9skor : SpeedTestWizard.finish.panel.max.download=Max let\u00f6lt\u00e9s : SpeedTestWizard.finish.panel.enabled=enged\u00e9lyzve SpeedTestWizard.finish.panel.disabled=tiltva SpeedTestWizard.abort.message.scheduled.in=teszt \u00fctemezve ... %1 mp m\u00falva" SpeedTestWizard.abort.message.unsupported.type=Nem t\u00e1mogatott teszt t\u00edpus!!!! SpeedTestWizard.abort.message.manual.abort=Felhaszn\u00e1l\u00f3 megszak\u00edtotta SpeedTestWizard.abort.message.scheduling.failed=Teszt \u00fctemez\u00e9se sikertelen SpeedTestWizard.abort.message.download.added=%1 let\u00f6lt\u00e9s hozz\u00e1adva a teszt sor\u00e1n SpeedTestWizard.abort.message.entered.error=Tesztlet\u00f6lt\u00e9s hiba: '%1' SpeedTestWizard.abort.message.entered.queued=Tezstlet\u00f6lt\u00e9s sorba\u00e1ll\u00e1s/meg\u00e1llt SpeedTestWizard.abort.message.interrupted=TorrentSebess\u00e9gTezstMonitor f\u00e9lbeszakad a v\u00e9ge el\u0151tt SpeedTestWizard.abort.message.execution.failed=Teszt v\u00e9grehajt\u00e1sa sikertelen SpeedTestWizard.abort.message.failed.peers=Nem siker\u00fclt \u00fcgyf\u00e9lhez kapcsol\u00f3dni SpeedTestWizard.abort.message.insufficient.slots=Nem lehet \u00fcgyf\u00e9lhez felt\u00f6lteni - el\u00e9gtelen felt\u00f6lt\u00e9si sz\u00e1l? SpeedTestWizard.abort.message.not.unchoked=Nem lehet let\u00f6lt\u00e9ni az \u00fcgyfelekt\u0151lby them SpeedTestWizard.stage.message.requesting=teszt k\u00e9r\u00e9se... SpeedTestWizard.stage.message.preparing=teszt el\u0151k\u00e9sz\u00edt\u00e9se... SpeedTestWizard.stage.message.starting=teszt ind\u00edt\u00e1sa... SpeedTestWizard.stage.message.connect.stats=Kapcsolat stat: \u00fcgyf\u00e9l=%1, le_ok=%2, fel_ok=%3 window.uiswitcher.title=Vuze UI V\u00e1laszt\u00f3 window.uiswitcher.text=V\u00e1laszd ki a hozz\u00e1d legjobban ill\u0151 megjelen\u00e9si m\u00f3dot window.uiswitcher.NewUI.text=* Aj\u00e1nlott a kezd\u0151 \u00e9s \u00faj felhazsn\u00e1l\u00f3knak.\n\n* Egyszer\u0171, intuit\u00edv grafikai fel\u00fclet\n\n* Sz\u00fcks\u00e9ges interf\u00e9sz megoszt\u00e1shoz a Vuze platformon window.uiswitcher.ClassicUI.title=Klasszikus Fel\u00fclet window.uiswitcher.ClassicUI.text=* Aj\u00e1nlott halad\u00f3 felhaszn\u00e1l\u00f3knak\n\n* A 2.x sz\u00e9ria funkci\u00f3it tartalmazza\n\n* Vuze tartalom nem lesz bet\u00f6ltve window.uiswitcher.bottom.text=A v\u00e1laszt\u00e1sod k\u00f6nynen megv\u00e1ltoztathat\u00f3 az Vuze UI v\u00e1laszt\u00f3 ikonnal iconBar.switch.tooltip=Vuze UI V\u00e1laszt\u00f3 VivaldiView.notAvailable=Vivaldi N\u00e9zet nem el\u00e9rhet\u0151 restart.error=\u00dajraind\u00edt\u00e1s sikertelen:\n%1\nSee restarting issues. restart.error.oom=Kev\u00e9s a mem\u00f3ria restart.error.fnf='%1' nem tal\u00e1lhat\u00f3 a '%2'-ban/ben restart.error.pnf=\u00datvonal '%1' nem tal\u00e1lhat\u00f3 restart.error.bad=Rossz f\u00e1jlform\u00e1tum: '%1' restart.error.denied=Hozz\u00e1f\u00e9r\u00e9s sikertelen, a '%1' futtat\u00e1sakor. Ellen\u0151rizd, hogy van-e jogod futtatni a programot. TableColumn.header.date_completed=Befejezve TableColumn.menu.date_added.reset=D\u00e1tum t\u00f6rl\u00e9se ConfigView.section.ipfilter.discardbanning=Rossz adatot k\u00fcld\u0151 \u00fcgyfelek blokkol\u00e1sa/j\u00f3 adatar\u00e1ny n\u00f6vekedni fog [0: disabled] ConfigView.section.ipfilter.discardminkb=Minimum %1 eldobva, miel\u0151tt az ar\u00e1nyban megjelenne ConfigView.interface.start.advanced=Ind\u00edt\u00e1s Halad\u00f3 N\u00e9zetben (AZ 2.x) MyTorrents.column.ColumnQuality=Min\u0151s\u00e9g MyTorrents.column.ColumnSpeed=Sebess\u00e9g MyTorrents.column.ColumnProgressETA.StreamReady=Streaming K\u00e9sz %1 MyTorrents.column.ColumnProgressETA.PlayableIn=Lej\u00e1tszhat\u00f3 %1 %2 TableColumn.header.Quality=Min\u0151s\u00e9g TableColumn.header.Speed=Sebess\u00e9g TableColumn.header.RateIt=Ar\u00e1ny TableColumn.header.Rating=Szavaz\u00e1s TableColumn.header.SpeedGraphic=Sebess\u00e9g TableColumn.header.AzProduct=forr\u00e1s TableColumn.header.MediaThumb=M\u00e9dia TableColumn.header.ProgressETA=\u00c1llapot #TableColumn.header.size={MyTorrentsView.size} #TableColumn.header.up={MyTorrentsView.up} #TableColumn.header.date_added={MyTorrentsView.date_added} #TableColumn.header.name={MyTorrentsView.name} TableColumn.header.name.ext=F\u00e1jlt\u00edpus: %1 #TableColumn.header.shareRatio={MyTorrentsView.shareRatio} v3.MainWindow.tab.home=Kezd\u0151lap v3.MainWindow.tab.browse=Vuze-ban v3.MainWindow.tab.library=K\u00f6nyvt\u00e1ram v3.MainWindow.tab.publish=K\u00f6zz\u00e9tesz v3.MainWindow.tab.advanced=Halad\u00f3 v3.MainWindow.menu.home=&Kezd\u0151lap v3.MainWindow.menu.browse=&Tartalom B\u00f6ng\u00e9sz\u00e9se v3.MainWindow.menu.library=K\u00f6nyvt\u00e1ra&m v3.MainWindow.menu.publish=&K\u00f6zz\u00e9tesz v3.MainWindow.menu.advanced=&Halad\u00f3 v3.MainWindow.menu.view.searchbar=Keres\u0151 v3.MainWindow.menu.view.tabbar=F\u00fcl eszk\u00f6zt\u00e1r v3.MainWindow.currentDL=Let\u00f6lt\u00e9s alatt v3.MainWindow.button.stream=Folyam v3.MainWindow.button.stop=\u00c1lllj v3.MainWindow.button.start=Ind\u00edt v3.MainWindow.button.pause=Sz\u00fcnet v3.MainWindow.button.resume=Folytat v3.MainWindow.button.delete=T\u00f6r\u00f6l v3.MainWindow.button.comment=Megjegyz\u00e9s v3.MainWindow.button.viewdetails=R\u00e9szletek v3.MainWindow.button.play=Lej\u00e1tsz\u00e1s v3.MainWindow.button.cancel=M\u00e9gsem v3.MainWindow.button.preview=El\u0151n\u00e9zet v3.MainWindow.view.wait=Bet\u00f6lt\u00e9s, k\u00e9rem v\u00e1rjon. v3.MainWindow.xofx=%1 a %2-b\u00f3l v3.MainWindow.Loading=Betolt\u00e9s.. K\u00e9rem v\u00e1rjon v3.filter-bar=C\u00edm Sz\u0171r\u0151: v3.MainWindow.search.defaultText=Keres\u00e9s Vuze v3.mb.delPublished.title=Seedel\u00e9s le\u00e1ll\u00edt\u00e1sa v3.mb.delPublished.text=FIGYELEM: Ezzel nem t\u00f6rl\u0151dik a let\u00f6lt\u00f6tt tartalom '%1', %3 .\n\nV\u00e1laszd a "T\u00f6rl\u00e9s"-t ha azt szeretn\u00e9d, hogy a tartalom m\u00e9g el\u00e9rhet\u0151, let\u00f6lthet\u0151 maradjon, de fel akarod szabad\u00edtani a felt\u00f6t\u00e9si s\u00e1vodat. Ellen\u0151rizd, hogy a let\u00f6lt\u00e9s befejez\u0151d\u00f6tt (how?).\n\nKattints a M\u00e9gsem-re, ha teljesen el akarod t\u00e1vol\u00edtani a megosztott anyagot a %3 helyr\u0151l, vagy haszn\u00e1ld a(X) gombot a Megosztott Tartalom ablakon a Megoszt\u00e1s ablakon.\n\nSeg\u00edts\u00e9g.\n\n v3.mb.delPublished.delete=&T\u00f6r\u00f6l v3.mb.delPublished.cancel=&M\u00e9gsem v3.mb.openFile.title=F\u00e1jl megnyit\u00e1sa v3.mb.openFile.text.known=A Vuze Lej\u00e1tsz\u00f3 nem t\u00e1mogatja ezt a form\u00e1tumot. B\u0151vebb inf\u00f3-created Lej\u00e1tsz\u00e1s \u00datmutat\u00f3\n\nF\u00e1jlt\u00edpus: %2 (%3)\n v3.mb.openFile.text.unknown=A Vuze Lej\u00e1tsz\u00f3 nem t\u00e1mogatja ezt a form\u00e1tumot. B\u0151vebb inf\u00f3 Playback Guide\n\nKiterjeszt\u00e9s : %2\n v3.mb.openFile.button.play=Lej\u00e1tsz\u00e1s v3.mb.openFile.button.cancel=M\u00e9gsem v3.mb.openFile.button.guide=\u00datmutat\u00f3 olvas\u00e1sa v3.mb.openFile.remember=Mindig nyissa meg k\u00e9rd\u00e9s n\u00e9lk\u00fcl a f\u00e1jlokat v3.mb.PlayFileNotFound.title=A f\u00e1jl nemtal\u00e1lhat\u00f3 v3.mb.PlayFileNotFound.text=A '%1' f\u00e1jl hi\u00e1nyzik vagy t\u00f6r\u00f6lve lett. v3.mb.PlayFileNotFound.button.remove=T\u00f6rl\u00e9s az Azureusb\u00f3l v3.mb.PlayFileNotFound.button.redownload=Adatok \u00dajrat\u00f6lt\u00e9se v3.mb.PlayFileNotFound.button.find=K\u00e9zi keres\u00e9s.. v3.mb.deletePurchased.title=Let\u00f6lt\u00f6tt Elem T\u00f6rl\u00e9se v3.mb.deletePurchased.text=Biztosan t\u00f6r\u00f6lni akarod a k\u00f6vetkez\u0151 elemet? '%1'?\n\n Az elem megosztott, vagy bel\u00e9p\u00e9s sz\u00fcks\u00e9ges a let\u00f6lt\u00e9s\u00e9hez. v3.mb.deletePurchased.button.delete=&T\u00f6r\u00f6l v3.mb.deletePurchased.button.cancel=&M\u00e9gsem v3.topbar.menu.show.plugin=B\u0151v\u00edtm\u00e9nyek v3.topbar.menu.show.search=Keres splash.initializeCore=Mag Ind\u00edt\u00e1sa splash.initializeUIElements=UI Elemek Ind\u00edt\u00e1sa ConfigView.section.transfer.autospeedbeta=Auto-Speed-B\u00e9ta # ConfigView.section.ipfilter.peerblocking.group=\u00dcgyf\u00e9l blokkol\u00e1sa ConfigView.section.ipfilter.autoload.group=Automatikus Bet\u00f6lt\u00e9s ConfigView.section.ipfilter.autoload.file=IP sz\u0171r\u0151 f\u00e1jl automatikus bet\u00f6lt\u00e9se ConfigView.section.ipfilter.autoload.info=T\u00e1mogatja DAT (eMule), P2P (PeerGuardian, splist) \u00e9s P2B v1,2,3 (PeerGuardian 2) form\u00e1tumokat. F\u00e1jlok lehetnek helyiek, vagy URL, zip'd, gzip'd vagy sima sz\u00f6veg. URL-ek 7 nap ut\u00e1n automatikusan \u00fajra lesznek let\u00f6ltve, \u00e9s a f\u00e1jlok friss\u00edtve lesznek. ConfigView.section.ipfilter.autoload.loadnow=Bet\u00f6lt\u00e9s Most splash.loadIpFilters=IP Sz\u0171r\u0151k bet\u00f6lt\u00e9se.. SpeedTestWizard.set.upload.title=Felt\u00f6lt\u00e9si \u00e9s Let\u00f6lt\u00e9si Hat\u00e1rok SpeedTestWizard.set.download.label=Let\u00f6lt\u00e9si Sebess\u00e9g Hat\u00e1r: SpeedTestWizard.set.upload.label=Felt\u00f6lt\u00e9si Sebess\u00e9ghat\u00e1r: SpeedTestWizard.name.conf.level.absolute=Abszol\u00fat SpeedTestWizard.name.conf.level.high=Magas SpeedTestWizard.name.conf.level.med=K\u00f6zepes SpeedTestWizard.name.conf.level.low=Alacsony SpeedTestWizard.name.conf.level.none=Nincs ConfigView.section.transfer.select.v2=Auto-Speed (b\u00e9ta) mb.azmustclose.title=Ind\u00edt\u00e1si Hiba mb.azmustclose.text=Az Vuze hiba miatt le\u00e1ll, val\u00f3sz\u00edn\u0171leg egy Rendszergazdak\u00e9nt futtatott program miatt.\n\nMiut\u00e1n az Vuze kil\u00e9pett, k\u00e9zzel kell \u00fajraind\u00edtani a programot. network.ipv6.prefer.addresses=IPv6 c\u00edmek el\u0151nyben r\u00e9szes\u00edt\u00e9se, ha IPv6 \u00e9s IPv4 is el\u00e9rhet\u0151 network.bindError=K\u00f6t\u00f6tt kiszolg\u00e1l\u00f3 hiba, nincs el\u00e9rhet\u0151 kompatibilis c\u00edm, k\u00e9rem ellen\u0151rizze a bind-to-ip be\u00e1ll\u00edt\u00e1sokat. network.enforce.ipbinding=IP k\u00f6t\u00e9s er\u0151ltet\u00e9se, ha az interf\u00e9sz nem el\u00e9rhet\u0151 letiltja a kapcsolatokat, ha egyik megjel\u00f6lt interf\u00e9sz sem \u00e9rhet\u0151 el DHTView.title.full_v6=Elosztott Adatb\u00e1zis IPv6 ConfigView.pluginlist.loadSelected=Kijel\u00f6ltek bet\u00f6lt\u00e9se SpeedView.stats.asn=H\u00e1l\u00f3zat: SpeedView.stats.estupcap=Felt\u00f6lt\u00e9s limit: SpeedView.stats.estdowncap=Let\u00f6lt\u00e9s limt: SpeedView.stats.unknown=Ismeretlen SpeedView.stats.estimate=becs\u00fclt SpeedView.stats.measured=M\u00e9rve SpeedView.stats.measuredmin=Min M\u00e9rt SpeedView.stats.manual=Fix ConfigView.section.transfer.autospeed.networks=H\u00e1l\u00f3zat Tulajdons\u00e1gai ConfigView.section.transfer.autospeed.resetnetwork=H\u00e1l\u00f3zati tulajdons\u00e1gok t\u00f6rl\u00e9se ConfigView.section.transfer.autospeed.network.info=A fenti \u00e9rt\u00e9keket let\u00f6lt\u00e9s k\u00f6zben sz\u00e1molja ki a program, vagy egy sebess\u00e9gteszt ut\u00e1n. Ha k\u00e9zzel szeretn\u00e9d be\u00e1ll\u00edtani, akkor haszn\u00e1ld a lenti be\u00e1ll\u00edt\u00e1sokat.\nMinden nem 'fix' limit rendszeresen \u00fajrasz\u00e1mol\u00e1sra ker\u00fcl, ha sz\u00fcks\u00e9ges. \n\u00c1ll\u00edts be egy \u00e9rt\u00e9ket, majd v\u00e1laszd ki a t\u00edpus\u00e1t. Megjegyz\u00e9s: a sebess\u00e9g m\u00e9rt\u00e9kegys\u00e9ge %1. dialog.uiswitcher.restart.title=UI V\u00e1lt\u00f3: Vuze \u00dajraind\u00edt\u00e1s Sz\u00fcks\u00e9ges dialog.uiswitcher.restart.text=Az \u00faj fel\u00fclet hazsn\u00e1lat\u00e1hoz az Azureus-t \u00fajra kell ind\u00edtani. TrayWindow.menu.close=Let\u00f6lt\u00e9si kos\u00e1r bez\u00e1r\u00e1sa # Used for peers which we can't determine. PeerSocket.unknown=Ismeretlen PeerSocket.fake_client=HAMIS PeerSocket.bad_peer_id=rossz peer ID PeerSocket.mismatch_id=ellentmond\u00e1s PeerSocket.unknown_az_style=Ismeretlen %1/%2 PeerSocket.unknown_shadow_style=Ismeretlen %1/%2 OpenTorrentWindow.mb.askCreateDir.title=A c\u00e9lmappa nem l\u00e9tezik OpenTorrentWindow.mb.askCreateDir.text=A c\u00e9lmappa nem l\u00e9tezik: '%1' .\n\nL\u00e9trehozza? SpeedView.stats.estimatechoke=Becs\u00fclt (choke) ConfigTransferAutoSpeed.upload.capacity.usage=Haszn\u00e1lt felt\u00f6lt\u00e9si kapacit\u00e1s ConfigTransferAutoSpeed.mode=M\u00f3d: ConfigTransferAutoSpeed.capacity.used=% Kapacit\u00e1s haszn\u00e1latban ConfigTransferAutoSpeed.while.downloading=Let\u00f6lt\u00e9s: ConfigTransferAutoSpeed.set.dht.ping=DHT Ping Be\u00e1ll\u00edt\u00e1s: ConfigTransferAutoSpeed.set.point=cs\u00facs (ms) ConfigTransferAutoSpeed.set.tolerance=tolerancia (ms) ConfigTransferAutoSpeed.ping.time.good=J\u00f3: ConfigTransferAutoSpeed.ping.time.bad=Rossz: ConfigTransferAutoSpeed.adjustment.interval=Be\u00e1ll\u00edt\u00e1si id\u0151k\u00f6z: ConfigTransferAutoSpeed.skip.after.adjust=Szab\u00e1lyz\u00e1s ut\u00e1n kihagyja: GeneralView.label.distributedCopies=Elosztott p\u00e9ld\u00e1nyok: PiecesView.DistributionView.title=Szelet kioszt\u00e1s PiecesView.DistributionView.NoAvl=Nem el\u00e9rhet\u0151 szeletek PiecesView.DistributionView.SeedAvl=El\u00e9rhet\u0151 Seed PiecesView.DistributionView.PeerAvl=El\u00e9rhet\u0151 \u00dcgyf\u00e9l PiecesView.DistributionView.RarestAvl=Legritk\u00e1bb Szeletek: %1 (El\u00e9rh.:%2) PiecesView.DistributionView.weHave=Let\u00f6lt\u00f6tt Szeletek PiecesView.DistributionView.theyHave=Megl\u00e9v\u0151 szeletek PiecesView.DistributionView.weDownload=T\u00f6lt\u00f6tt Szeletek PeersView.gain=El\u0151ny PeersView.gain.info=Let\u00f6lt\u00f6tt - felt\u00f6lt\u00f6tt adat unix.script.new.title=\u00daj Vuze ind\u00edt\u00f3parancs \u00e9rhet\u0151 el unix.script.new.text=\u00daj Vuze ind\u00edt\u00f3parancs \u00e9rhet\u0151 el, \u00e9s elmentve a '%1'.\n\nEr\u0151sen aj\u00e1nlott, hogy most z\u00e1rja be az Azureust \u00e9s v\u00e1ltson \u00e1t a parancsra ('%2').\n\nHa m\u00f3dos\u00edtottad az Vuze ind\u00edt\u00f3parancsot, akkor l\u00e1togass el ide: AzureusWiki: Unix Script.\n\nha az azureust distro-b\u00f3l telep\u00edtetted (yum, apt-get, etc), akkor aj\u00e1nlott az azureust \u00fajratelep\u00edteni a Vuze Sourceforge Page csomagb\u00f3l (Megmarad a jelenlegi UI) unix.script.new.button.quit=Kil\u00e9p most unix.script.new.button.continue=Majd k\u00e9s\u0151bb unix.script.new.button.asknomore=Ne mutassa ism\u00e9t unix.script.new.auto.title=\u00daj Vuze ind\u00edt\u00f3parancs unix.script.new.auto.text=\u00daj Vuze ind\u00edt\u00f3parancs \u00e9rhet\u0151 el.\n\nVuze \u00fajraind\u00edt\u00e1sa er\u0151sen aj\u00e1nlott. Content.alert.notuploaded.button.stop=&\u00c1llj Content.alert.notuploaded.button.continue=&Seedel\u00e9s folytat\u00e1sa Content.alert.notuploaded.button.abort=&Ne l\u00e9pjen ki ConfigView.label.checkOnSeeding=Kev\u00e9s er\u0151fforr\u00e1st haszn\u00e1l\u00f3 szelet-ellen\u0151rz\u00e9s seedel\u00e9skor ConfigView.label.ui_switcher=Mutassa az UI v\u00e1lt\u00f3t ConfigView.label.ui_switcher_button=Mutat SpeedTestWizard.test.panel.explain=M\u00e9rd meg az Vuze protokoll sebess\u00e9ged. V\u00e1lasdz ki a sebess\u00e9gm\u00e9r\u00e9s t\u00edpus\u00e1t \u00e9s a titkos\u00edt\u00e1s m\u00f3dj\u00e1t. L\u00e1togass el az Vuze wiki oldal\u00e1ra a r\u00e9szletek\u00e9rt. A teszt automatikusan le\u00e1ll 2 perc ut\u00e1n. \u00c1ltal\u00e1ban egy percen bel\u00fcl lezajlik. SpeedTestWizard.set.upload.hint=\u00c1ll\u00edtsd be az Vuze AutoSpeed algoritmus \u00e1ltal haszn\u00e1lt fel- \u00e9s let\u00f6lt\u00e9si hat\u00e1rt. SpeedTestWizard.set.upload.panel.explain=A limiteket az Vuze AutoSpeed algoritmus hazsn\u00e1lja. \u00c1ll\u00edtsd be az \u00e1tvitel hat\u00e1rait \u00e9s a biztons\u00e1gi hat\u00e1rt. \n\n Fontos! A vonalsebess\u00e9g gyakran "bit/sec"-ben szerepel - azonban az itt tal\u00e1lhat\u00f3 \u00e9rt\u00e9kk "kilobyte/sec"-ban. SpeedTestWizard.set.limit.conf.level=Bizonyoss\u00e1g SpeedTestWizard.finish.panel.auto.speed=AutoSebess\u00e9g : SpeedTestWizard.finish.panel.auto.speed.seeding=AutoSebess\u00e9g seedel\u00e9skor: ConfigTransferAutoSpeed.add.comment.to.log.group=Komment a hibakeres\u0151 napl\u00f3hoz ConfigTransferAutoSpeed.add.comment.to.log=Komment hozz\u00e1ad\u00e1sa: ConfigTransferAutoSpeed.log.button=Napl\u00f3 ConfigTransferAutoSpeed.algorithm.selector=Auto-Speed v\u00e1laszt\u00f3 ConfigTransferAutoSpeed.algorithm=Algoritmus: ConfigTransferAutoSpeed.auto.speed.classic=Auto-Speed(klasszikus) ConfigTransferAutoSpeed.auto.speed.beta=Auto-Speed(b\u00e9ta) ConfigTransferAutoSpeed.data.update.frequency=Friss\u00edt\u00e9si Frekvencia Alert.failed.update=Legal\u00e1bb egy komponens telep\u00edt\u00e9se sikertelen. Seg\u00edts\u00e9g: AzureusWiki: Failed Update [%1] OpenTorrentWindow.mb.existingFiles.partialList=(R\u00e9szleges lista. T\u00f6bb f\u00e1jl m\u00e1r l\u00e9tezik) TableColumn.header.bad_avail_time.info=Utols\u00f3 id\u0151, amikor a teljes m\u00e1solat el\u00e9rhet\u0151 volt TableColumn.header.bad_avail_time=El\u00e9rhetp Teljes M\u00e1solat MyTorrentsView.menu.exporthttpseeds=HTTP seed URL-ek m\u00e1sol\u00e1sa a v\u00e1g\u00f3lapra SWT.alert.erroringuithread=Egy ismeretlen hiba keletkezett a GUI-ban, tov\u00e1bbi hib\u00e1kat jelentsd. ConfigView.label.minannounce=Minim\u00e1lis id\u0151 a kiszolg\u00e1l\u00f3hoz t\u00f6rt\u00e9n\u0151 bejelentkez\u00e9sek k\u00f6z\u00f6tt (mp) ConfigView.label.maxnumwant=Tracker \u00e1ltal k\u00fcld\u00f6tt \u00fcgyfelek sz\u00e1m\u00e1nak korl\u00e1toz\u00e1sa ConfigView.label.announceport=Tracker bejelentkez\u00e9si port fel\u00fclb\u00edr\u00e1l\u00e1sa ConfigView.label.noportannounce=Ne haszn\u00e1lja a kiszolg\u00e1l\u00f3hoz t\u00f6rt\u00e9n\u0151 bejelentkez\u00e9sre a figyel\u0151portot (nem \u00e9rv\u00e9nyes pex, dht eset\u00e9n) ConfigView.label.maxseedspertorrent=Max k\u00e9szforr\u00e1s torrentenk\u00e9nt [0: korl\u00e1tlan] wizard.webseed=HTTP K\u00e9szforr\u00e1s hozz\u00e1ad\u00e1sa torrenthez wizard.webseed.title=HTTP K\u00e9szforr\u00e1s wizard.webseed.configuration=HTTP K\u00e9szforr\u00e1s Be\u00e1ll\u00edt\u00e1sok wizard.webseed.adding=HTTP K\u00e9szforr\u00e1s hozz\u00e1ad\u00e1sa GeneralView.label.private=Priv\u00e1t Torrent: GeneralView.yes=Nem GeneralView.no=Igen ConfigView.label.userequestlimiting=Korl\u00e1toz\u00e1s alkalmaz\u00e1sa az olvas\u00e1s k\u00e9sleltes\u00e9se helyett, a let\u00f6lt\u00e9si sebess\u00e9g korl\u00e1toz\u00e1s\u00e1n\u00e1l [nincs hat\u00e1sa, ha a let\u00f6lt\u00e9si sebess\u00e9g korl\u00e1tlan] ConfigView.label.userequestlimiting.tooltip=Aj\u00e1nlott korl\u00e1toz\u00e1s nem olyan finom, mint az olvas\u00e1s k\u00e9sleltet\u00e9se, de enged\u00e9lyezi a let\u00f6lt\u00e9s prioriz\u00e1l\u00e1s\u00e1t a let\u00f6lt\u00e9si sorban, \u00e9s n\u00f6velheti a h\u00e1l\u00f3zat teljes\u00edtm\u00e9ny\u00e9t ConfigView.label.userequestlimitingpriorities=R\u00e9szes\u00edtse el\u0151nyben a let\u00f6lt\u00e9si sor elej\u00e9t, amikor a let\u00f6lt\u00e9si sebess\u00e9g el\u00e9ri a limitet ConfigView.section.logging.timestamp=Id\u0151form\u00e1tum a Napl\u00f3f\u00e1jlokban Peers.column.timetocomplete=Marad\u00e9k Id\u0151 Peers.column.timetocomplete.info=H\u00e1tralev\u0151 id\u0151, am\u00edg az \u00fcgyf\u00e9l be nem fejezi ConfigView.section.interface.display.suppress.file.download.dialog=F\u00e1jl Let\u00f6lt\u00e9se ablak elrejt\u00e9se ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Minden f\u00e1jllet\u00f6lt\u00e9s megjelen\u00edt\u00e9se az \u00e1llapots\u00e1vban a felugr\u00f3 ablakok helyett FileDownload.canceled=A torrent f\u00e1jl t\u00f6lt\u00e9s\u00e9s\u00e9t a felhaszn\u00e1l\u00f3 sikeresen megszak\u00edtotta: %1 Progress.reporting.status.canceled=Megszak\u00edtva Progress.reporting.status.finished=Befejezve Progress.reporting.status.retrying=Ism\u00e9tl\u00e9s... Progress.reporting.action.label.retry.tooltip=Feladat ism\u00e9t Progress.reporting.action.label.remove.tooltip=Folyamatbejegyz\u00e9s t\u00f6rl\u00e9se a napl\u00f3b\u00f3l Progress.reporting.action.label.cancel.tooltip=Feladat Megszak\u00edt\u00e1sa Progress.reporting.action.label.detail=R\u00e9szletek Progress.reporting.default.error=Sikertelen Progress.reporting.no.reports.to.display=Nincs megjelen\u00edthet\u0151 FolyamatRiport Progress.reporting.no.history.to.display=Nincs megjelen\u00edthet\u0151 \u00fczenet Progress.reporting.detail.history.limit=A Maxim\u00e1lis bejegyz\u00e9st (%1) FolyamatRiporthoz el\u00e9rte; Tov\u00e1bbi \u00fczenetek nem ker\u00fclnek napl\u00f3z\u00e1sra Progress.reporting.statusbar.button.tooltip=Folyamat Riport ablak mutat\u00e1sa webui.bindip=IP k\u00f6t\u00e9s - nem k\u00f6telez\u0151 (*) v3.MainWindow.text.log.in=Bejelentkez\u00e9s v3.MainWindow.text.log.out=Kijeletkez\u00e9s v3.MainWindow.text.get.started=Kezdj\u00fck v3.MainWindow.text.my.account=Felhaszn\u00e1l\u00f3 v3.MainWindow.text.my.profile=Profil OpenTorrentWindow.simple.open=Torrent Helye (F\u00e1jl, URL, Hash) Progress.reporting.window.remove.auto=Inakt\u00edv elemek automatikus t\u00f6rl\u00e9se Progress.reporting.window.remove.auto.tooltip=Inakt\u00edv, befejezett \u00e9s hib\u00e1s elemek automatikus t\u00f6rl\u00e9se a n\u00e9zetb\u0151l Progress.reporting.window.remove.now=Inakt\u00edv elemek t\u00f6rl\u00e9se Progress.reporting.window.remove.now.tooltip=Inakt\u00edv, befejezett \u00e9s hib\u00e1s elemek t\u00f6rl\u00e9se a n\u00e9zetb\u0151l dhttracker.tracklimitedwhenonline=Azonban lass\u00fa k\u00f6vet\u00e9sn\u00e9l, amikor online for swarm cross-population TorrentOptionsView.multi.title.short=Torrent Be\u00e1ll\u00edt\u00e1sai TorrentOptionsView.multi.title.full=Torrent Be\u00e1ll\u00edt\u00e1sai MyTorrentsView.menu.open_parent_folder=Tartalmaz\u00f3 mappa megnyit\u00e1sa ConfigView.section.style.use_show_parent_folder=Haszn\u00e1lja "%1" a "%2" helyett a torrent men\u00fcben ConfigView.section.style.use_show_parent_folder.tooltip=Ezzel a be\u00e1ll\u00edt\u00e1ssal a helyes f\u00e1jlmenedzserrel nyitja meg a tartalmaz\u00f3 mapp\u00e1t.\nAzonban ez azt is jelenti, hogy a let\u00f6lt\u00e9s helye nem lesz automatikusan kiv\u00e1lasztva. PeerManager.status.ps_disabled=Tracker peer forr\u00e1s tiltva ConfigView.section.stats.exportfiles=F\u00e1jladatok export\u00e1l\u00e1sa updater.cant.write.to.app.title=Nem lehet \u00edrni az alkalmaz\u00e1s mapp\u00e1j\u00e1ba updater.cant.write.to.app.details=A "%1" mappa nem \u00edrhat\u00f3.\n\nEz megakad\u00e1lyozza a \u00f6v\u0151beni friss\u00edt\u00e9sek telep\u00edt\u00e9s\u00e9t.\n\nL\u00e1togass el a c\u00edmre a r\u00e9szletek\u00e9rt (Angol). plugin.install.class_version_error=A b\u0151v\u00edtm\u00e9ny futtat\u00e1s\u00e1hoz \u00fajabb Java sz\u00fcks\u00e9ges. v3.MainWindow.tab.minilibrary=Let\u00f6lt\u00e9s v3.MainWindow.tab.events=Aktivit\u00e1s button.columnsetup.tooltip=Oszlopbe\u00e1ll\u00edt\u00e1s v3.activity.remove.title=Bejegyz\u00e9s T\u00f6rl\u00e9se v3.activity.remove.text=Biztosan el akarod t\u00e1vol\u00edtani '%1'? #v3.MainWindow.menu.view.configuration=Preferences #v3.MainWindow.menu.view.configuration.keybinding=Meta+, v3.MainWindow.menu.file.closewindow=Bez\u00e1r Menu.show.torrent.menu=Torrent men\u00fc mutat\u00e1sa Menu.show.torrent.menu.tooltip=Torrent men\u00fc mutat\u00e1sa az ablak tetej\u00e9n #v3.TorrentOptionsView.title.short=Preferences #v3.TorrentOptionsView.title.full=Preferences #v3.ConfigView.title.short=Preferences #v3.ConfigView.title.full=Preferences Views.plugins.aznetstatus.title=H\u00e1l\u00f3zat \u00c1llapota plugin.aznetstatus.pingtarget=Ping/trace c\u00e9lc\u00edme ConfigView.section.style.usePathFinder='\u00datvonal Keres\u0151' haszn\u00e1lata 'Keres\u0151' helyett menu.sortByColumn=Rendez\u00e9s %1 szerint MyTorrentsView.menu.manual.per_peer=K\u00e9zi (per peer) MyTorrentsView.menu.manual.shared_peers=K\u00e9zi (peerek k\u00f6z\u00f6tt) v3.button.removeActivityEntry=Bejegyz\u00e9s t\u00f6rl\u00e9se v3.splash.initSkin=UI Skin ind\u00edt\u00e1sa v3.splash.hookPluginUI=Hurok a Plugin UI-ban OpenTorrentWindow.mb.notTorrent.cannot.display=Az adatokat nem lehet helyesen megjelen\u00edteni MainWindow.menu.window.zoom.maximize=Teljes m\u00e9ret MainWindow.menu.window.zoom.restore=Vissza\u00e1ll\u00edt ImageResizer.image.too.small=A kiv\u00e1lasztott k\u00e9p t\u00fal kicsil, adj meg egy m\u00e1sikat (legal\u00e1bb %1 x %2) ImageResizer.title=Az eszk\u00f6z megmutatja, hogy hogyan fog kin\u00e9zni a mozaikod a Vuze Platformon ImageResizer.move.image=K\u00e9p mozgat\u00e1sa h\u00faz\u00e1ssal ImageResizer.move.image.with.slider=K\u00e9p mozgat\u00e1sa h\u00faz\u00e1ssal, \u00e1tm\u00e9retez\u00e9s a lentebb l\u00e9v\u0151 cs\u00faszk\u00e1val security.crypto.title=Titkos\u00edt\u00f3 Kulcs security.crypto.encrypt=\u00cdrj be egy jelsz\u00f3t, ami v\u00e9di a gener\u00e1lt titkos\u00edt\u00e1si kulcsot. Ne felejtsd el a jelsz\u00f3t, nem lehet vissza\u00e1ll\u00edtani! security.crypto.decrypt=\u00cdrd be a jelsz\u00f3t a titkos\u00edt\u00f3 kulcs kinyit\u00e1s\u00e1hoz. security.crypto.reason=M\u0171k\u00f6d\u00e9s c\u00e9lja security.crypto.password=Jelsz\u00f3 security.crypto.password2=Jelsz\u00f3 m\u00e9gegyszer security.crypto.persist_for=A jelsz\u00f3 \u00e9rv\u00e9nyess\u00e9ge security.crypto.persist_for.dont_save=Ne mentse security.crypto.persist_for.session=Aktu\u00e1lis folyamat security.crypto.persist_for.day=1 nap security.crypto.persist_for.week=1 h\u00e9t security.crypto.persist_for.30days=30 nap security.crypto.persist_for.forever=Mind\u00f6r\u00f6kre security.crypto.password.mismatch.title=Jelsz\u00f3 hiba security.crypto.password.mismatch=A be\u00edrt jelsz\u00f3 nem egyezik, add meg \u00fajra. ConfigView.section.security.group.crypto=Ny\u00edlt/Priv\u00e1t Kulcsok ConfigView.section.security.resetkey=Kulcsok t\u00f6rl\u00e9se ConfigView.section.security.resetkey.warning.title=Figyelmeztet\u00e9s Adatveszt\u00e9sre ConfigView.section.security.resetkey.warning=Biztosan vissza akarod \u00e1ll\u00edtani a titkos\u00edt\u00e1si kulcsokat? Ezzel minden olyan adat, mely ezzel a kulccsal lett k\u00f3dolva V\u00c9GLEG ELV\u00c9SZ. Valamint m\u00e1s peerekkel is meg kell osztanod az \u00faj publikus kulcsodat, k\u00fcl\u00f6nben nem tudsz kommunik\u00e1lni vel\u00fck. Teh\u00e1t, ha nem vagy biztos a dolgodban, akkor ne tedd. ConfigView.section.security.unlockkey=Kulcsok kinyer\u00e9se ConfigView.section.security.unlockkey.button=Kinyit ConfigView.section.security.publickey=Nyilv\u00e1nos kulcs ConfigView.section.security.publickey.undef=Nincs megadva ConfigView.section.security.resetkey.error.title=M\u0171velet sikertelen ConfigView.section.security.resetkey.error=Hiba a kulcsok t\u00f6rl\u00e9sekor ConfigView.section.security.unlockkey.error=Kulcsok kinyit\u00e1sa sikertelen - rossz jelsz\u00f3 ConfigView.copy.to.clipboard.tooltip=M\u00e1sol\u00e1s a v\u00e1g\u00f3lapra Views.plugins.azbuddy.title=Bar\u00e1tok Browser.popup.error.no.access=Hiba l\u00e9pet fel a t\u00e1voli er\u0151forr\u00e1s el\u00e9r\u00e9se k\u00f6zbene.\nK\u00e9rlek pr\u00f3b\u00e1ld meg k\u00e9s\u0151bb.\n ConfigView.label.queue.stoponcebandwidthmet=Ne ind\u00edtson \u00faj torrentet, ha a fel-/let\u00f6lt\u00e9si sebess\u00e9g el\u00e9rte a limitet ConfigView.section.style.forceMozilla=Vuze k\u00e9nyszer\u00edt\u00e9se a Mozilla haszn\u00e1lat\u00e1ras [xulrunner vagy firefox 3 sz\u00fcks\u00e9ges; \u00fajraind\u00edt\u00e1s sz\u00fcks\u00e9ges] ConfigView.section.style.xulRunnerPath=Add meg a XulRunner / Firefox el\u00e9r\u00e9i \u00fatj\u00e1t [min FF3; \u00fajraind\u00edt\u00e1s sz\u00fcks\u00e9ges] azbuddy.name=Bar\u00e1tok azbuddy.enabled=Enged\u00e9lyezve azbuddy.disabled=B\u0151v\u00edtm\u00e9ny kikapcsolva, n\u00e9zd meg a be\u00e1ll\u00edt\u00e1sokat. azbuddy.nickname=Beceneved azbuddy.msglog.title=Bar\u00e1t Adatai azbuddy.addtorrent.title=Elfogadod a let\u00f6lt\u00e9st? azbuddy.addtorrent.msg='%1' k\u00fcldte a '%2'.\nLe akarod t\u00f6lteni? azbuddy.contextmenu=K\u00fcld\u00e9s Bar\u00e1tnak azbuddy.ui.mykey=Kulcsom: azbuddy.ui.add=Hozz\u00e1ad azbuddy.ui.new_buddy=\u00daj bar\u00e1tkulcs: azbuddy.ui.table.name=N\u00e9v azbuddy.ui.table.last_msg=Utols\u00f3 \u00fczenet azbuddy.ui.menu.remove=T\u00f6r\u00f6l azbuddy.ui.menu.copypk=Publikus Kulcs M\u00e1sol\u00e1sa azbuddy.ui.menu.send=\u00dczenet k\u00fcld\u00e9se azbuddy.ui.menu.send_msg=A bar\u00e1todnak k\u00fcld\u00f6tt \u00fczenet sz\u00f6vege azbuddy.ui.menu.ygm=YGM K\u00fcld\u00e9se azbuddy.ui.menu.enc=V\u00e1g\u00f3lap k\u00f3dol\u00e1sa azbuddy.ui.menu.dec=V\u00e1g\u00f3lap dek\u00f3dol\u00e1sa azbuddy.ui.menu.sign=V\u00e1g\u00f3lap al\u00e1\u00edr\u00e1sa azbuddy.ui.menu.verify=V\u00e1g\u00f3lap ellen\u0151rz\u00e9se azbuddy.ui.table.lastseen=Utolj\u00e1ra akt\u00edv Button.retry=&\u00dajra Button.ignore=&Mell\u0151z azbuddy.ui.table.msg_in=Bej\u00f6v\u0151 azbuddy.ui.table.msg_out=Kimen\u0151 v3.MainWindow.menu.view.footer=Bar\u00e1t eszk\u00f6zt\u00e1r azbuddy.downspeed=KB/s a bar\u00e1tos max let\u00f6lt\u00e9si sebess\u00e9ge [0: v\u00e9gtelen] security.crypto.badpw=A megadott jelsz\u00f3 \u00e9rv\u00e9nytelen ConfigView.section.security.backupkeys=Kulcs ment\u00e9se f\u00e1jlba ConfigView.section.security.backupkeys.button=Ment\u00e9s ConfigView.section.security.restorekeys=Kulcsok vissza\u00e1ll\u00edt\u00e1sa f\u00e1jlb\u00f3l ConfigView.section.security.restorekeys.button=Vissza\u00e1ll\u00edt ConfigView.section.security.op.error.title=M\u0171velet sikertelen ConfigView.section.security.op.error=Nem siker\u00fclt befejezni a k\u00f6evetkez\u0151 m\u0171veletet:\n %1 ConfigView.section.security.restart.title=\u00dajraind\u00edt\u00e1s Sz\u00fcks\u00e9ges ConfigView.section.security.restart.msg=A Vuze most \u00fajraindul, hogy v\u00e9grehatsa a m\u0171veletet. ConfigView.section.security.system.managed=Rendszerkulcs azbuddy.ui.table.msg_queued=Sorban azbuddy.chat.says=%1 mondja: Button.bar.show=Mutat Button.bar.hide=Elrejt Button.bar.share=Megoszt Button.bar.add=Bar\u00e1t hozz\u00e1ad\u00e1sa Button.bar.edit=Szerkeszt Button.bar.edit.cancel=Szerkeszt\u00e9s k\u00e9sz v3.MainWindow.menu.view.pluginbar=B\u0151v\u00edtm\u00e9nyek eszk\u00f6zt\u00e1r MainWindow.dialog.select.vuze.file=Vuze f\u00e1jl kiv\u00e1laszt\u00e1sa MainWindow.menu.file.open.vuze=Vuze \u00e1jl... metasearch.addtemplate.title=Telep\u00edted a Keres\u00e9si Sablont? metasearch.addtemplate.desc=Biztosan telep\u00edteni szeretn\u00e9d a '%1' keres\u00e9si sablont? v3.share.private.title=Torrent megoszt\u00e1sa v3.share.private.text=A kiv\u00e1lasztott torrent priv\u00e1t torrent.\n\nNem oszthatsz meg priv\u00e1t torrentet. metasearch.addtemplate.dup.title=Sablon m\u00e1sol\u00e1sa metasearch.addtemplate.dup.desc=A %1 keres\u00e9si sablon m\u00e1r telep\u00edtve van metasearch.export.select.template.file=Sablon Ment\u00e9se metasearch.import.select.template.file=Sablon Megnyit\u00e1sa dialog.uiswitch.title=V\u00e1lt\u00e1s Vuze UI-ra dialog.uiswitch.text=A funkci\u00f3hoz Vuze fel\u00fclet sz\u00fcks\u00e9ge.\n\n\u00dajraind\u00edt\u00e1s sz\u00fcks\u00e9ges. dialog.uiswitch.button=V\u00e1lt\u00e1s Vuze UI-ra azbuddy.tracker.enabled='Bar\u00e1t gyors\u00edt\u00e1sa' nagyobb priorit\u00e1sban r\u00e9szes\u00edti a bar\u00e1taidat azbuddy.protocolspeed=KB/s a bar\u00e1tod max protokoll fejr\u00e9sz v3.MainWindow.button.download=Let\u00f6lt\u00e9s v3.MainWindow.button.run=Let\u00f6lt\u00e9si F\u00e1jl Ind\u00edt\u00e1sa v3.activity.header.downloads=Let\u00f6lt\u00e9s v3.activity.header.vuze.news=Vuze H\u00edrek message.taking.too.long=Ez el fog tartani egy ideig\nNyomd meg az 'ESC' gombot, ha meg akarod szak\u00edtani a m\u0171veletet message.status.success=Sikeres azbuddy.tracker.bbb.status.title=Bar\u00e1t gyors\u00edt\u00e1sa azbuddy.tracker.bbb.status.title.tooltip=Dupla katt a r\u00e9szletek\u00e9rt azbuddy.tracker.bbb.status.idle=Nincs gyors\u00edt\u00e1s azbuddy.tracker.bbb.status.nli=Jelentkezz be azbuddy.tracker.bbb.status.in=Gyors\u00edtva azbuddy.tracker.bbb.status.out=Gyors\u00edtott Bar\u00e1tok v3.MainWindow.search.go.tooltip=Elv\u00e9gzett Keres\u00e9s v3.MainWindow.search.last.tooltip=Vissza az eredm\u00e9nyekhez metasearch.addtemplate.done.title=Sablon Hozz\u00e1adva metasearch.addtemplate.done.desc='%1' sablon sikeresen hozz\u00e1adva.\nA k\u00f6vetkez\u0151 keres\u00e9sn\u00e9l haszn\u00e1lhat\u00f3! ConfigView.section.security.nopw=Nincs jelsz\u00f3 be\u00e1ll\u00edtva ConfigView.section.security.nopw_v=A jelsz\u00f3 nem el\u00e9rhet\u0151, l\u00e9pj be a Vuze-ba fileplugininstall.install.title=B\u0151v\u00edtm\u00e9ny telep\u00edt\u00e9se? fileplugininstall.install.desc=Biztosan szeretn\u00e9d telep\u00edteni? B\u0151v\u00edtm\u00e9ny: '%1', verzi\u00f3 %2 fileplugininstall.duplicate.title=B\u0151v\u00edtm\u00e9ny duplik\u00e1l\u00e1sa fileplugininstall.duplicate.desc=%2 verzi\u00f3j\u00fa '%1' b\u0151v\u00edtm\u00e9ny m\u00e1r telep\u00edtve van azbuddy.online_status=Online \u00c1llapot azbuddy.os_away=Nincs a g\u00e9pn\u00e9l azbuddy.os_not_avail=Nem el\u00e9rhet\u0151 azbuddy.os_busy=Elfoglalt azbuddy.ui.menu.disconnect=Sz\u00e9tkapcsol azbuddy.enable_chat_notif=Chat figyelmeztet\u00e9sek enged\u00e9lyez\u00e9se progress.window.msg.progress=V\u00e1rj am\u00edg a m\u0171velet be nem fejez\u0151dik DetailedListView.title=R\u00e9szletes Lista ConfigView.section.connection.network.max.outstanding.connect.attempts=Max sorban\u00e1ll\u00f3 kimen\u0151 kapcsolat plugins.init.force_enabled=Vuze \u00e9szlelte, hogy a "%1" plugin le lett tiltva - a Vuze helyes m\u0171k\u00f6d\u00e9s\u00e9hez \u00fajb\u00f3l enged\u00e9lyezve lett. ConfigView.section.connection.prefer.udp=UDP kapcsolat haszn\u00e1lata subscript.add.title=Telep\u00edted az el\u0151fizet\u00e9s? subscript.add.desc=Biztosan telep\u00edted az el\u0151fizet\u00e9st '%1'? subscript.add.dup.title=El\u0151fizet\u00e9s m\u00e1sol\u00e1sa subscript.add.dup.desc='%1' el\u0151fizet\u00e9s m\u00e1r telep\u00edtve. subscript.add.upgrade.title=Friss\u00edted az el\u0151fizet\u00e9s? subscript.add.upgrade.desc=Biztosan friss\u00edted az el\u0151fizet\u00e9s? '%1' subscript.add.upgradeto.desc='%2' %1 verzi\u00f3j\u00fa el\u0151fizet\u00e9s el\u00e9rhet\u0151.\nFriss\u00edted? azsubs.contextmenu.addassoc=El\u0151fizet\u00e9s hozz\u00e1rendel\u00e9s hozz\u00e1ad\u00e1sa azsubs.contextmenu.lookupassoc=El\u0151fizet\u00e9s hozz\u00e1rendel\u00e9s keres\u00e9se iconBar.remove=T\u00f6r\u00f6l iconBar.down=Le iconBar.run=Futtat iconBar.editcolumns=Oszlop be\u00e1ll\u00edt\u00e1sa iconBar.top=Tetej\u00e9re iconBar.bottom=Alj\u00e1ra iconBar.open=Torrent hozz\u00e1ad\u00e1sa iconBar.share=megoszt iconBar.details=R\u00e9szletek iconBar.comment=Megjegyz\u00e9s iconBar.play=Lej\u00e1tsz\u00e1s iconBar.queue.tooltip=V\u00e1r\u00f3list\u00e1ra v\u00e9tel v3.MainWindow.menu.view.sidebar=Oldals\u00e1v v3.MainWindow.menu.view.actionbar=Tev\u00e9kenys\u00e9g s\u00e1v v3.MainWindow.menu.view.toolbars=Eszk\u00f6zt\u00e1r ump.install=A vide\u00f3hoz tov\u00e1bbi komponensek sz\u00fcks\u00e9gesek. A telep\u00edt\u00e9s folyamatban. K\u00e9rlek v\u00e1rj. subscriptions.listwindow.title=El\u0151fizet\u00e9s Keres\u0151 subscriptions.listwindow.autochecktext=Vuze megkeresi az ehhez kapcsol\u00f3do el\u0151fizet\u00e9seket. Enged\u00e9lyezed ezt a funkci\u00f3t? subscriptions.listwindow.loadingtext=%1-val kapcsolatos el\u0151fizet\u00e9s keres\u00e9se subscriptions.listwindow.failed=Nem tal\u00e1lhat\u00f3 el\u0151fizet\u00e9s subscriptions.listwindow.popularity=N\u00e9pszer\u0171s\u00e9g subscriptions.listwindow.popularity.unknown=Ismeretlen subscriptions.listwindow.name=N\u00e9v subscriptions.listwindow.subscribe=El\u0151fizet\u00e9s TableColumn.header.azsubs.ui.column.subs=El\u0151fizet\u00e9s subscriptions.listwindow.popularity.reading=Olvas\u00e1s... PluginDeprecation.log.start=Ez az ablak r\u00e9szleteket tartalmaz a plugin \u00e1ltal haszn\u00e1lt, de nemsok\u00e1ra megsz\u0171n\u0151 funkci\u00f3r\u00f3l.\nNem sz\u00fcks\u00e9ges t\u00f6r\u00f6ln\u00f6d a plugint, csak friss\u00edtsd a leg\u00fajabb verzi\u00f3ra.\nHa a leg\u00fajabb verzi\u00f3t hasz\u00e1lod, akkor m\u00e1sold az al\u00e1bbi bejegyz\u00e9st a forumba:\n \t%1\n\n PluginDeprecation.log.details=---------\nIDENTIFIER: %1\nCONTEXT: %2\n\n*** KERES\u00c9S ***\n%3*** V\u00c9GE ***\n\n PluginDeprecation.view=Plugin Hbakeres\u00e9s PluginDeprecation.alert=A plugin egy megsz\u00fcn\u0151 funkci\u00f3t akar haszn\u00e1lni -n\u00e9zd meg a Plugin Debug napl\u00f3t a r\u00e9szletek\u00e9rt. TableColumn.header.Thumbnail=Ikon TableColumn.header.Thumbnail.info=Mozaik k\u00e9p Vuze tartalomn\u00e1l; minden egy\u00e9bhez az oper\u00e1ci\u00f3s rendszerben be\u00e1ll\u00edtott ikonok jelennek meg. v3.MainWindow.menu.getting_started=&Bemutat\u00f3 MainWindow.menu.help.faq=&Gyakran Ism\u00e9telt K\u00e9rd\u00e9sek MainWindow.menu.help.support=&Seg\u00edts\u00e9g \u00e9s T\u00e1mogat\u00e1s externalLogin.title=Bejeletkez\u00e9s sz\u00fcks\u00e9ges externalLogin.explanation="%1" sablonhoz be kell jeletkeznek. Ha bejelentkezt\u00e9l, akkor ez az ablak elt\u0171nik. Ha m\u00e9gsem akkor kattint a 'K\u00e9sz' gombra. externalLogin.explanation.capture=Be kell jeletkezned a sablon elk\u00e9sz\u00edt\u00e9s\u00e9hez. Ha k\u00e9szen vagy, kattints a "K\u00e9sz" gombra. Button.done=K\u00e9sz GeneralView.torrent_created_on_and_by=%1 %2-b\u00f3l/b\u0151l Button.continue=Folytat Button.preview=El\u0151n\u00e9zet Subscription.menu.forcecheck=Friss\u00edt "%1" Subscription.menu.clearall=Eredm\u00e9nyek megjel\u00f6l\u00e9se olvasottk\u00e9nt Subscription.menu.remove=T\u00f6r\u00f6l sidebar.Library=K\u00f6nyvt\u00e1ram sidebar.LibraryDL=Let\u00f6tl\u00e9s sidebar.LibraryCD=Befejezve authenticator.location=Hely authenticator.details=R\u00e9szletek subscript.import.fail.title=Import\u00e1l\u00e1s Sikertelen subscript.import.fail.desc=R\u00e9szletek: %1 Subscription.menu.export=Export\u00e1l subscript.export.select.template.file=El\u0151fizet\u00e9s ment\u00e9se MainWindow.menu.help.donate=A&dom\u00e1ny !!! azureus-4.3.0.6/org/gudy/azureus2/internat/MessagesBundle_km_KH.properties0000644000175000017500000001754211301156004026071 0ustar adrianadrian#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php ConfigView.section.files=\u17af\u1780\u179f\u17b6\u179a FileItem.write=\u179f\u179a\u179f\u17c1\u179a FileItem.read=\u1791\u17b6\u1794 FileItem.normal=\u1792\u1798\u17d2\u1798\u178f\u17b6 FileItem.high=\u1781\u17d2\u1796\u179f\u17cb FilesView.name=\u1788\u17d2\u1798\u17c4\u17c7 FilesView.done=\u1792\u17d2\u179c\u17be\u179a\u17bd\u1785 FilesView.mode=\u179a\u1794\u17c0\u1794 FilesView.priority=\u17a2\u17b6\u1791\u17b7\u1797\u17b6\u1796 FilesView.menu.open=&\u1794\u17be\u1780 FilesView.menu.setpriority=&\u1780\u17c6\u178e\u178f\u17cb\u17a2\u17b6\u1791\u17b7\u1797\u17b6\u1796 FilesView.menu.setpriority.high=&\u1781\u17d2\u1796\u179f\u17cb FilesView.menu.setpriority.normal=&\u1792\u1798\u17d2\u1798\u178f\u17b6 FilesView.menu.setpriority.skipped=&\u1798\u17b7\u1793\u1794\u17b6\u1785\u17cb\u1791\u17b6\u1789\u1799\u1780 FilesView.title.short=\u17af\u1780\u179f\u17b6\u179a FilesView.title.full=\u17af\u1780\u179f\u17b6\u179a GeneralView.label.status.file=\u179f\u17d2\u1790\u17b6\u1793\u1797\u17b6\u1796\u17af\u1780\u179f\u17b6\u179a GeneralView.label.filename=\u1788\u17d2\u1798\u17c4\u17c7 : Button.next=\u1794\u1793\u17d2\u1791\u17b6\u1794\u17cb Button.finish=\u1794\u1789\u17d2\u1785\u1794\u17cb Button.cancel=\u1794\u17c4\u17c7\u1794\u1784\u17cb Button.ok=\u1799\u179b\u17cb\u1796\u17d2\u179a\u1798 configureWizard.nat.ko=NAT \u1798\u17b6\u1793\u1780\u17c6\u17a0\u17bb\u179f configureWizard.file.title=Torrents / \u17af\u1780\u179f\u17b6\u179a configureWizard.file.message1=Vuze \u1793\u17b9\u1784\u179a\u1780\u17d2\u179f\u17b6 torrents \u1780\u17d2\u1793\u17bb\u1784\u1790\u178f\u178a\u17c2\u179b\u1781\u17d2\u179b\u17bd\u1793\u1794\u17b6\u1793\u1794\u17be\u1780, \u17a2\u17d2\u1793\u1780\u17a2\u17b6\u1785\u1787\u17d2\u179a\u17be\u179f\u179a\u17be\u179f\u1790\u178f\u1793\u17c5\u1791\u17b8\u1793\u17c1\u17c7 configureWizard.file.path=\u1795\u17d2\u179b\u17bc\u179c configureWizard.file.browse=\u179a\u1780\u1798\u17be\u179b configureWizard.file.fastResume=\u17a2\u1793\u17bb\u1789\u17d2\u1789\u17b6\u178f\u1792\u17d2\u179c\u17be\u1794\u1793\u17d2\u178f\u1799\u17c9\u17b6\u1784\u179b\u17bf\u1793 configureWizard.file.invalidPath=\u1790\u178f\u1798\u17b7\u1793\u178f\u17d2\u179a\u17b9\u1798\u178f\u17d2\u179a\u17bc\u179c configureWizard.finish.title=\u1794\u17b6\u1793\u179f\u1798\u17d2\u179a\u17c1\u1785 configureWizard.finish.message=Vuze \u1794\u17b6\u1793\u1791\u1791\u17bd\u179b\u1780\u17b6\u179a\u1780\u17c2\u179f\u1798\u17d2\u179a\u17bd\u179b\u17a0\u17be\u1799, \u179f\u17bc\u1798\u17a2\u17c4\u1799\u179a\u17b8\u1780\u179a\u17b6\u1799! exportTorrentWizard.torrentfile.path=\u1795\u17d2\u179b\u17bc\u179c exportTorrentWizard.torrentfile.browse=\u179a\u1780\u1798\u17be\u179b exportTorrentWizard.exportfile.path=\u1795\u17d2\u179b\u17bc\u179c exportTorrentWizard.exportfile.browse=\u179a\u1780\u1798\u17be\u179b importTorrentWizard.importfile.path=\u1795\u17d2\u179b\u17bc\u179c importTorrentWizard.importfile.browse=\u179a\u1780\u1798\u17be\u179b fileDownloadWindow.status=\u179f\u17d2\u1790\u17b6\u1793\u1797\u17b6\u1796 : fileDownloadWindow.state_error=\u1780\u17c6\u17a0\u17bb\u179f : # # Tooltips # # # 2.0.4.4 # columnChooser.title=\u1787\u17d2\u179a\u17be\u179f\u1787\u17bd\u179a\u1788\u179a\u178a\u17be\u1798\u17d2\u1794\u17b8\u1794\u1784\u17d2\u17a0\u17b6\u1789 columnChooser.move=\u1791\u17b6\u1789\u1787\u17bd\u179a\u178a\u17c1\u1780\u178a\u17be\u1798\u17d2\u1794\u17b8\u1785\u17b6\u178f\u17cb\u179b\u17c6\u178a\u17b6\u1794\u17cb columnChooser.apply=\u17a2\u1793\u17bb\u179c\u178f\u17d2\u178f\u17b7 columnChooser.columnname=\u1788\u17d2\u1798\u17c4\u17c7\u1787\u17bd\u179a\u1788\u179a columnChooser.columndescription=\u1796\u17b7\u1796\u178e\u17cc\u1793\u17b6 authenticator.title=\u178f\u17d2\u179a\u17bc\u179c\u1780\u17b6\u179a\u1780\u17b6\u179a\u17a2\u1793\u17bb\u1789\u17d2\u1789\u17b6\u178f authenticator.realm=\u1796\u17d2\u179a\u17c6\u178a\u17c2\u1793 authenticator.user=\u1788\u17d2\u1798\u17c4\u17c7\u17a2\u17d2\u1793\u1780\u1794\u17d2\u179a\u17be authenticator.password=\u1796\u17b6\u1780\u17d2\u1799\u179f\u1798\u17d2\u1784\u17b6\u178f\u17cb # #2.0.7.0 # # # 2.0.7.x # Categories.all=\u1791\u17b6\u17c6\u1784\u17a2\u179f\u17cb Categories.uncategorized=\u1798\u17b7\u1793\u1794\u17c2\u1784\u1785\u17c2\u1780\u1794\u17d2\u179a\u1797\u17c1\u1791 CategoryAddWindow.message=\u178a\u17b6\u1780\u17cb\u1788\u17d2\u1798\u17c4\u17c7\u1794\u17d2\u179a\u1797\u17c1\u1791 \u1790\u17d2\u1798\u17b8 CategoryAddWindow.title=\u1794\u1793\u17d2\u1790\u17c2\u1798\u1794\u17d2\u179a\u1797\u17c1\u1791 \u1790\u17d2\u1798\u17b8 AlertMessageBox.error=\u1780\u17c6\u17a0\u17bb\u179f AlertMessageBox.warning=\u1780\u17b6\u179a\u1796\u17d2\u179a\u1798\u17b6\u1793 AlertMessageBox.comment=\u1796\u178f\u17cc\u1798\u17b6\u1793 AlertMessageBox.information=\u1796\u178f\u17cc\u1798\u17b6\u1793 AutoMigration.useralert=\u1796\u178f\u17cc\u1798\u17b6\u1793\u1780\u17c2\u179f\u1798\u17d2\u179a\u17bd\u179b\u179a\u1794\u179f\u17cb\u17a2\u17d2\u1793\u1780\u1794\u17d2\u179a\u17be Vuze /dirs \u1795\u179b\u179a\u1794\u179f\u17cb\u1780\u17b6\u179a\u1795\u17d2\u179b\u17b6\u179f\u17cb\u1791\u17b8\u178a\u17c4\u1799\u179f\u17d2\u179c\u17d0\u1799\u1794\u17d2\u179a\u179c\u178f\u17d2\u178f\u17b7:\n\n%1\n\u1780\u17d2\u1793\u17bb\u1784\u1780\u17c6\u17a0\u17bb\u179f\u1793\u17b7\u1798\u17bd\u1799\u17d7 \u178f\u17d2\u179a\u17bc\u179c\u1792\u17d2\u179c\u17be\u1780\u17b6\u179a\u1795\u17d2\u179b\u17b6\u179f\u17cb\u1791\u17b8\u178a\u17c4\u1799\u1781\u17d2\u179b\u17bd\u1793\u17af\u1784\n\u1780\u17bb\u17c6\u1797\u17d2\u179b\u17c1\u1785\u1780\u17c2\u179f\u1798\u17d2\u179a\u17bd\u179b\u1790\u178f\u179f\u1798\u17d2\u179a\u17b6\u1794\u17cb\u1795\u17d2\u1791\u17bb\u1780\u1780\u17b6\u179a\u1780\u17c2\u1794\u17d2\u179a\u17c2 \u1794\u17be\u179f\u17b7\u1793\u1787\u17b6\u179c\u17b6\u178f\u17d2\u179a\u17bc\u179c\u1794\u17b6\u1793\u1795\u17d2\u179b\u17b6\u179f\u17cb\u1791\u17b8 # # > 2.0.8.0 # Button.revert=\u178f\u17d2\u179a\u17a1\u1794\u17cb\u1791\u17c5\u178a\u17be\u1798 Button.yes=\u1794\u17b6\u1791 Button.no=\u1791\u17c1 Button.clear=\u179f\u1798\u17d2\u17a2\u17b6\u178f Button.reset=\u1780\u17c6\u178e\u178f\u17cb\u17a1\u17be\u1784\u179c\u17b7\u1789 CacheView.general.size=\u1791\u17c6\u17a0\u17c6\u1791\u17b6\u17c6\u1784\u17a2\u179f\u17cb CacheView.general.inUse=\u1780\u17c6\u1796\u17bb\u1784\u1794\u17d2\u179a\u17be CacheView.general.title=\u1796\u178f\u17cc\u1798\u17b6\u1793 Cache CacheView.reads.title=\u17a2\u17b6\u1793 I/O CacheView.reads.fromFile=\u1796\u17b8 \u17af\u1780\u179f\u17b6\u179a CacheView.reads.fromCache=\u1796\u17b8 Cache CacheView.reads.hits=\u1785\u17bc\u179b\u178a\u179b\u17cb CacheView.writes.title=\u179f\u179a\u179f\u17c1\u179a I/O CacheView.writes.toCache=\u1791\u17c5 Cache CacheView.writes.toFile=\u1791\u17c5 \u17af\u1780\u179f\u17b6\u179a CacheView.writes.hits=\u179a\u1780\u17d2\u179f\u17b6\u1791\u17bb\u1780\u17a0\u17be\u1799 CacheView.speeds.title=\u17a2\u178f\u17d2\u179a\u17b6\u1791\u17b7\u1793\u17d2\u1793\u17d0\u1799 CacheView.speeds.reads=\u17a2\u17b6\u1793 CacheView.speeds.writes=\u179f\u179a\u179f\u17c1\u179a CacheView.speeds.fromCache=\u1796\u17b8/\u1791\u17c5 Cache CacheView.speeds.fromFile=\u1796\u17b8/\u1791\u17c5 \u17af\u1780\u179f\u17b6\u179a CacheView.reads.amount=\u1785\u17c6\u1793\u17bd\u1793 CacheView.reads.avgsize=\u1791\u17c6\u17a0\u17c6\u1798\u1792\u17d2\u1799\u1798 FilesView.path=\u1795\u17d2\u179b\u17bc\u179c Button.abort=\u1794\u17c4\u17c7\u1794\u1784\u17cb Button.apply=\u17a2\u1793\u17bb\u179c\u178f\u17d2\u178f Button.close=\u1794\u17b7\u1791 #file can be a URL or a path in the jar ActivityView.legend.limit=\u1780\u17c6\u178e\u178f\u17cb\u17a2\u178f\u17d2\u179a\u17b6 ActivityView.legend.peeraverage=\u1798\u1792\u17d2\u1799\u1798 # %1 = "in kbps" or ""; %2 = "upload" or "download" Button.moveUp=\u1795\u17d2\u179b\u17b6\u179f\u17cb\u1791\u17b8\u17a1\u17be\u1784 Button.moveDown=\u1795\u17d2\u179b\u17b6\u179f\u17cb\u1791\u17b8\u1785\u17bb\u17c7 azureus-4.3.0.6/org/gudy/azureus2/applet/0000755000175000017500000000000011310377334017444 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/0000755000175000017500000000000011310377634020525 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/remote/0000755000175000017500000000000011310377634022020 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/remote/RPException.java0000644000175000017500000000401110727156470025063 0ustar adrianadrian/* * File : RPException.java * Created : 28-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.remote; import org.gudy.azureus2.core3.util.Debug; /** * @author parg * */ public class RPException extends RuntimeException { private static void checkErrorType(Throwable e) { if (e instanceof RPException) { Debug.outNoStack("RPExceptions chained together - stack trace, followed by other RPException stack trace."); Debug.outStackTrace(); Debug.printStackTrace(e); throw new RuntimeException("cannot chain RPException instances together"); } } public RPException(String str) { super(str); } public RPException(String str, Throwable e) { super(str, e); checkErrorType(e); } public RPException(Throwable e) { super(e); checkErrorType(e); } public String getRPType() { return null; } public Throwable getSerialisableObject() { Throwable t = this.getCause(); if (t == null) { return this; } else { return t; } } public Class getErrorClass() { Throwable t = this.getCause(); if (t == null) {return null;} return t.getClass(); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/remote/tracker/0000755000175000017500000000000011310377634023453 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/remote/tracker/RPTrackerTorrent.java0000644000175000017500000001473110373051052027526 0ustar adrianadrian/* * Created on 21-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.remote.tracker; import org.gudy.azureus2.plugins.tracker.*; import org.gudy.azureus2.plugins.torrent.*; import org.gudy.azureus2.pluginsimpl.remote.*; import org.gudy.azureus2.pluginsimpl.remote.torrent.RPTorrent; /** * @author parg * */ public class RPTrackerTorrent extends RPObject implements TrackerTorrent { protected transient TrackerTorrent delegate; // don't change the names of these, they appear in XML serialisation public RPTorrent torrent; public int status; public long total_uploaded; public long total_downloaded; public long average_uploaded; public long average_downloaded; public long total_left; public long completed_count; public long total_bytes_in; public long average_bytes_in; public long total_bytes_out; public long average_bytes_out; public long scrape_count; public long average_scrape_count; public long announce_count; public long average_announce_count; public int seed_count; public int leecher_count; public int bad_NAT_count; public static RPTrackerTorrent create( TrackerTorrent _delegate ) { RPTrackerTorrent res =(RPTrackerTorrent)_lookupLocal( _delegate ); if ( res == null ){ res = new RPTrackerTorrent( _delegate ); } return( res ); } protected RPTrackerTorrent( TrackerTorrent _delegate ) { super( _delegate ); if ( delegate.getTorrent() != null ){ torrent = (RPTorrent)_lookupLocal( delegate.getTorrent()); if ( torrent == null ){ torrent = RPTorrent.create( delegate.getTorrent()); } } } protected void _setDelegate( Object _delegate ) { delegate = (TrackerTorrent)_delegate; status = delegate.getStatus(); total_uploaded = delegate.getTotalUploaded(); total_downloaded = delegate.getTotalDownloaded(); average_uploaded = delegate.getAverageUploaded(); average_downloaded = delegate.getAverageDownloaded(); total_left = delegate.getTotalLeft(); completed_count = delegate.getCompletedCount(); total_bytes_in = delegate.getTotalBytesIn(); average_bytes_in = delegate.getAverageBytesIn(); total_bytes_out = delegate.getTotalBytesOut(); average_bytes_out = delegate.getAverageBytesOut(); scrape_count = delegate.getScrapeCount(); average_scrape_count = delegate.getAverageScrapeCount(); announce_count = delegate.getAnnounceCount(); average_announce_count = delegate.getAverageAnnounceCount(); seed_count = delegate.getSeedCount(); leecher_count = delegate.getLeecherCount(); bad_NAT_count = delegate.getBadNATCount(); } public Object _setLocal() throws RPException { Object res = _fixupLocal(); if ( torrent != null ){ torrent._setLocal(); } return( res ); } public void _setRemote( RPRequestDispatcher dispatcher ) { super._setRemote( dispatcher ); if ( torrent != null ){ torrent._setRemote( dispatcher ); } } public RPReply _process( RPRequest request ) { String method = request.getMethod(); // Object[] params = request.getParams(); throw( new RPException( "Unknown method: " + method )); } //***************************************************************************8 public void start() throws TrackerException { notSupported(); } public void stop() throws TrackerException { notSupported(); } public void remove() throws TrackerTorrentRemovalVetoException { notSupported(); } public boolean canBeRemoved() throws TrackerTorrentRemovalVetoException { notSupported(); return( false ); } public Torrent getTorrent() { return( torrent ); } public TrackerPeer[] getPeers() { notSupported(); return( null ); } public int getStatus() { return( status ); } public long getTotalUploaded() { return( total_uploaded ); } public long getTotalDownloaded() { return( total_downloaded ); } public long getAverageUploaded() { return( average_uploaded ); } public long getAverageDownloaded() { return( average_downloaded ); } public long getTotalLeft() { return( total_left ); } public long getCompletedCount() { return( completed_count ); } public long getTotalBytesIn() { return( total_bytes_in ); } public long getAverageBytesIn() { return( average_bytes_in ); } public long getTotalBytesOut() { return( total_bytes_out ); } public long getAverageBytesOut() { return( average_bytes_out ); } public long getScrapeCount() { return( scrape_count ); } public long getAverageScrapeCount() { return( average_scrape_count ); } public long getAnnounceCount() { return( announce_count ); } public long getAverageAnnounceCount() { return( average_announce_count ); } public int getSeedCount() { return( seed_count ); } public int getLeecherCount() { return( leecher_count); } public int getBadNATCount() { return( bad_NAT_count ); } public void disableReplyCaching() { notSupported(); } public boolean isPassive() { notSupported(); return( false ); } public long getDateAdded() { notSupported(); return( 0 ); } public void addListener( TrackerTorrentListener listener ) { notSupported(); } public void removeListener( TrackerTorrentListener listener ) { notSupported(); } public void addRemovalListener( TrackerTorrentWillBeRemovedListener listener ) { notSupported(); } public void removeRemovalListener( TrackerTorrentWillBeRemovedListener listener ) { notSupported(); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/remote/tracker/RPTracker.java0000644000175000017500000001323411223045276026153 0ustar adrianadrian/* * Created on 21-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.remote.tracker; /** * @author parg * */ import java.net.InetAddress; import java.net.URL; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.pluginsimpl.remote.torrent.RPTorrent; import org.gudy.azureus2.plugins.tracker.*; import org.gudy.azureus2.plugins.tracker.web.*; import org.gudy.azureus2.pluginsimpl.remote.*; public class RPTracker extends RPObject implements Tracker { protected transient Tracker delegate; public static RPTracker create( Tracker _delegate ) { RPTracker res =(RPTracker)_lookupLocal( _delegate ); if ( res == null ){ res = new RPTracker( _delegate ); } return( res ); } protected RPTracker( Tracker _delegate ) { super( _delegate ); } protected void _setDelegate( Object _delegate ) { delegate = (Tracker)_delegate; } public Object _setLocal() throws RPException { return( _fixupLocal()); } public RPReply _process( RPRequest request ) { String method = request.getMethod(); Object[] params = request.getParams(); if ( method.equals( "host[Torrent,boolean]")){ try{ Torrent torrent = params[0]==null?null:(Torrent)((RPTorrent)params[0])._setLocal(); if ( torrent == null ){ throw( new RPException( "Invalid torrent" )); } TrackerTorrent tt = delegate.host(torrent,((Boolean)params[1]).booleanValue()); RPTrackerTorrent res = RPTrackerTorrent.create( tt ); return( new RPReply( res )); }catch( TrackerException e ){ return( new RPReply( e )); } }else if ( method.equals( "getTorrents")){ TrackerTorrent[] torrents = delegate.getTorrents(); RPTrackerTorrent[] res = new RPTrackerTorrent[torrents.length]; for (int i=0;i no connection for singleton calls); if ( _connection_id == 0 ){ _connection_id = connection_id_next++; } } } protected long _getConectionId() { return( _connection_id ); } protected long _getNextRequestId() { synchronized( this ){ return( request_id_next++ ); } } protected void _setDelegate( Object _delegate ) { delegate = (PluginInterface)_delegate; } public Object _setLocal() throws RPException { return( _fixupLocal()); } public RPReply _process( RPRequest request ) { String method = request.getMethod(); if ( method.equals( "getPluginProperties")){ // must copy properties as actual return is subtype + non serialisable Properties p = new Properties(); Properties x = delegate.getPluginProperties(); Iterator it = x.keySet().iterator(); while(it.hasNext()){ Object key = it.next(); p.put( key, x.get(key)); } return( new RPReply( p )); }else if ( method.equals( "getDownloadManager")){ return( new RPReply( RPDownloadManager.create(delegate.getDownloadManager()))); }else if ( method.equals( "getTorrentManager")){ return( new RPReply( RPTorrentManager.create(delegate.getTorrentManager()))); }else if ( method.equals( "getPluginconfig")){ return( new RPReply( RPPluginConfig.create(delegate.getPluginconfig()))); }else if ( method.equals( "getIPFilter")){ return( new RPReply( RPIPFilter.create(delegate.getIPFilter()))); }else if ( method.equals( "getShortCuts")){ return( new RPReply( RPShortCuts.create(delegate.getShortCuts()))); }else if ( method.equals( "getTracker")){ return( new RPReply( RPTracker.create(delegate.getTracker()))); } throw( new RPException( "Unknown method: " + method )); } // ****************************************** public PluginManager getPluginManager() { notSupported(); return( null ); } public Plugin getPlugin() { notSupported(); return( null ); } public String getAzureusName() { return( azureus_name ); } public String getAzureusVersion() { return( azureus_version ); } public String getApplicationName() { return Constants.APP_NAME; } public void addView(PluginView view) { notSupported(); } public void addConfigUIParameters(Parameter[] parameters, String displayName) { notSupported(); } public void addConfigSection(ConfigSection tab) { notSupported(); } public void removeConfigSection(ConfigSection tab) { notSupported(); } public Tracker getTracker() { RPTracker res = (RPTracker)_dispatcher.dispatch( new RPRequest( this, "getTracker", null )).getResponse(); res._setRemote( _dispatcher ); return( res ); } public Logger getLogger() { notSupported(); return( null ); } public IPFilter getIPFilter() { RPIPFilter res = (RPIPFilter)_dispatcher.dispatch( new RPRequest( this, "getIPFilter", null )).getResponse(); res._setRemote( _dispatcher ); return( res ); } public DownloadManager getDownloadManager() { RPDownloadManager res = (RPDownloadManager)_dispatcher.dispatch( new RPRequest( this, "getDownloadManager", null )).getResponse(); res._setRemote( _dispatcher ); return( res ); } public ShareManager getShareManager() throws ShareException { notSupported(); return( null ); } public Utilities getUtilities() { notSupported(); return( null ); } public ShortCuts getShortCuts() { RPShortCuts res = (RPShortCuts)_dispatcher.dispatch( new RPRequest( this, "getShortCuts", null )).getResponse(); res._setRemote( _dispatcher ); return( res ); } public UIManager getUIManager() { notSupported(); return( null ); } public TorrentManager getTorrentManager() { RPTorrentManager res = (RPTorrentManager)_dispatcher.dispatch( new RPRequest( this, "getTorrentManager", null )).getResponse(); res._setRemote( _dispatcher ); return( res ); } /** * @deprecated */ public void openTorrentFile(String fileName) { notSupported(); } /** * @deprecated */ public void openTorrentURL(String url) { notSupported(); } public Properties getPluginProperties() { return((Properties)_dispatcher.dispatch( new RPRequest( this, "getPluginProperties", null )).getResponse()); } public String getPluginDirectoryName() { notSupported(); return( null ); } public boolean isShared() { notSupported(); return( false ); } public String getPluginName() { notSupported(); return( null ); } public String getPluginID() { notSupported(); return( null ); } public boolean isMandatory() { notSupported(); return( false ); } public boolean isBuiltIn() { notSupported(); return( false ); } public boolean isSigned() { notSupported(); return( false ); } public boolean isOperational() { notSupported(); return( false ); } public void setDisabled( boolean disabled ) { notSupported(); } public boolean isDisabled() { notSupported(); return( false ); } public String getPluginVersion() { notSupported(); return( null ); } public PluginConfig getPluginconfig() { RPPluginConfig res = (RPPluginConfig)_dispatcher.dispatch( new RPRequest( this, "getPluginconfig", null )).getResponse(); res._setRemote( _dispatcher ); return( res ); } public PluginConfigUIFactory getPluginConfigUIFactory() { notSupported(); return( null ); } public ClassLoader getPluginClassLoader() { notSupported(); return( null ); } public PluginInterface getLocalPluginInterface( Class plugin, String id ) { notSupported(); return( null ); } public IPCInterface getIPC () { notSupported(); return( null ); } public UpdateManager getUpdateManager() { notSupported(); return( null ); } public boolean isUnloadable() { notSupported(); return( false ); } public void unload() throws PluginException { notSupported(); } public void reload() throws PluginException { notSupported(); } public void uninstall() throws PluginException { notSupported(); } public boolean isInitialisationThread() { notSupported(); return( false ); } public ClientIDManager getClientIDManager() { notSupported(); return( null ); } public ConnectionManager getConnectionManager() { notSupported(); return null; } public MessageManager getMessageManager() { notSupported(); return null; } public DistributedDatabase getDistributedDatabase() { notSupported(); return null; } public PlatformManager getPlatformManager() { notSupported(); return null; } public void addListener( PluginListener l ) { notSupported(); } public void removeListener( PluginListener l ) { notSupported(); } public void firePluginEvent( PluginEvent event ) { notSupported(); } public void addEventListener( PluginEventListener l ) { notSupported(); } public void removeEventListener( PluginEventListener l ) { notSupported(); } public ConfigSection[] getConfigSections() { // TODO Auto-generated method stub return null; } public MainlineDHTManager getMainlineDHTManager() {notSupported(); return null;} public PluginState getPluginState() {notSupported(); return null;} } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/remote/RPRequest.java0000644000175000017500000000640610727156636024573 0ustar adrianadrian/* * File : RPRequest.java * Created : 28-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.remote; import java.io.Serializable; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.logging.LoggerChannel; /** * @author parg * */ public class RPRequest implements Serializable { // don't change these names as they end up in XML serialised data public RPObject object; public String method; public Object[] params; protected transient PluginInterface plugin_interface; protected transient LoggerChannel channel; public long connection_id; public long request_id; protected transient String client_ip; // public constructor for XML deserialiser public RPRequest() { } public RPRequest( RPObject _object, String _method, Object[] _params ) { object = _object; method = _method; params = _params; if ( object != null ){ RPPluginInterface pi = object.getDispatcher().getPlugin(); connection_id = pi._getConectionId(); request_id = pi._getNextRequestId(); plugin_interface = (PluginInterface)pi._getDelegate(); } } public void setClientIP( String str ) { client_ip = str; } public String getClientIP() { return( client_ip ); } public long getConnectionId() { return( connection_id ); } public long getRequestId() { return( request_id ); } public String getString() { return( "object=" + object + ", method=" + method + ", params=" + params ); } public RPObject getObject() { return( object ); } public String getMethod() { return( method ); } public Object[] getParams() { return( params ); } public PluginInterface getPluginInterface() { return this.plugin_interface; } public void setPluginInterface(PluginInterface pi) { this.plugin_interface = pi; } public LoggerChannel getRPLoggerChannel() { return this.channel; } public void setRPLoggerChannel(LoggerChannel channel) { this.channel = channel; } // Can be overridden by subclasses. public RPPluginInterface createRemotePluginInterface(PluginInterface pi) { return RPPluginInterface.create(pi); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/remote/download/0000755000175000017500000000000011310377634023627 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadScrapeResult.java0000644000175000017500000000547010207131716031037 0ustar adrianadrian/* * File : RPDownloadAnnounceResult.java * Created : 30-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.remote.download; /** * @author parg * */ import java.net.URL; import org.gudy.azureus2.plugins.download.*; import org.gudy.azureus2.pluginsimpl.remote.*; public class RPDownloadScrapeResult extends RPObject implements DownloadScrapeResult { protected transient DownloadScrapeResult delegate; // don't change these field names as they are visible on XML serialisation public int seed_count; public int non_seed_count; public static RPDownloadScrapeResult create( DownloadScrapeResult _delegate ) { RPDownloadScrapeResult res =(RPDownloadScrapeResult)_lookupLocal( _delegate ); if ( res == null ){ res = new RPDownloadScrapeResult( _delegate ); } return( res ); } protected RPDownloadScrapeResult( DownloadScrapeResult _delegate ) { super( _delegate ); } protected void _setDelegate( Object _delegate ) { delegate = (DownloadScrapeResult)_delegate; seed_count = delegate.getSeedCount(); non_seed_count = delegate.getNonSeedCount(); } public Object _setLocal() throws RPException { return( _fixupLocal()); } public RPReply _process( RPRequest request ) { String method = request.getMethod(); throw( new RPException( "Unknown method: " + method )); } // *************************************************** public Download getDownload() { notSupported(); return( null ); } public int getResponseType() { notSupported(); return( 0 ); } public int getSeedCount() { return( seed_count ); } public int getNonSeedCount() { return( non_seed_count ); } public long getScrapeStartTime() { notSupported(); return( 0 ); } public void setNextScrapeStartTime( long nextScrapeStartTime) { notSupported(); } public long getNextScrapeStartTime() { notSupported(); return(0); } public String getStatus() { notSupported(); return( null ); } public URL getURL() { notSupported(); return( null ); } }azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadAnnounceResult.java0000644000175000017500000000564710222135714031375 0ustar adrianadrian/* * File : RPDownloadAnnounceResult.java * Created : 30-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.remote.download; /** * @author parg * */ import java.net.URL; import java.util.Map; import org.gudy.azureus2.plugins.download.*; import org.gudy.azureus2.pluginsimpl.remote.*; public class RPDownloadAnnounceResult extends RPObject implements DownloadAnnounceResult { protected transient DownloadAnnounceResult delegate; // don't change these field names as they are visible on XML serialisation public int seed_count; public int non_seed_count; public static RPDownloadAnnounceResult create( DownloadAnnounceResult _delegate ) { RPDownloadAnnounceResult res =(RPDownloadAnnounceResult)_lookupLocal( _delegate ); if ( res == null ){ res = new RPDownloadAnnounceResult( _delegate ); } return( res ); } protected RPDownloadAnnounceResult( DownloadAnnounceResult _delegate ) { super( _delegate ); } protected void _setDelegate( Object _delegate ) { delegate = (DownloadAnnounceResult)_delegate; seed_count = delegate.getSeedCount(); non_seed_count = delegate.getNonSeedCount(); } public Object _setLocal() throws RPException { return( _fixupLocal()); } public RPReply _process( RPRequest request ) { String method = request.getMethod(); throw( new RPException( "Unknown method: " + method )); } // *************************************************** public Download getDownload() { notSupported(); return( null ); } public int getResponseType() { notSupported(); return( 0 ); } public int getReportedPeerCount() { notSupported(); return( 0 ); } public int getSeedCount() { return( seed_count ); } public int getNonSeedCount() { return( non_seed_count ); } public String getError() { notSupported(); return( null ); } public URL getURL() { notSupported(); return( null ); } public DownloadAnnounceResultPeer[] getPeers() { notSupported(); return( null ); } public long getTimeToWait() { notSupported(); return( 0 ); } public Map getExtensions() { notSupported(); return( null ); } }azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadStats.java0000644000175000017500000001172011224751004027512 0ustar adrianadrian/* * File : PRDownloadStats.java * Created : 30-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.remote.download; /** * @author parg * */ import org.gudy.azureus2.plugins.download.*; import org.gudy.azureus2.pluginsimpl.remote.*; public class RPDownloadStats extends RPObject implements DownloadStats { protected transient DownloadStats delegate; // don't change these field names as they are visible on XML serialisation public long downloaded; public long uploaded; public int completed; public int downloadCompletedLive; public int downloadCompletedStored; public String status; public String status_localised; public long upload_average; public long download_average; public String eta; public int share_ratio; public float availability; public int health; public static RPDownloadStats create( DownloadStats _delegate ) { RPDownloadStats res =(RPDownloadStats)_lookupLocal( _delegate ); if ( res == null ){ res = new RPDownloadStats( _delegate ); } return( res ); } protected RPDownloadStats( DownloadStats _delegate ) { super( _delegate ); } protected void _setDelegate( Object _delegate ) { delegate = (DownloadStats)_delegate; downloaded = delegate.getDownloaded(); uploaded = delegate.getUploaded(); completed = delegate.getCompleted(); downloadCompletedLive = delegate.getDownloadCompleted(true); downloadCompletedStored = delegate.getDownloadCompleted(false); status = delegate.getStatus(); status_localised = delegate.getStatus(true); upload_average = delegate.getUploadAverage(); download_average = delegate.getDownloadAverage(); eta = delegate.getETA(); share_ratio = delegate.getShareRatio(); availability = delegate.getAvailability(); health = delegate.getHealth(); } public Object _setLocal() throws RPException { return( _fixupLocal()); } public RPReply _process( RPRequest request ) { String method = request.getMethod(); throw( new RPException( "Unknown method: " + method )); } // *************************************************** public String getStatus() { return( status ); } public String getStatus(boolean localised) { return (localised)? status_localised : status; } public String getDownloadDirectory() { notSupported(); return( null ); } public String getTargetFileOrDir() { notSupported(); return( null ); } public String getTrackerStatus() { notSupported(); return( null ); } public int getCompleted() { return( completed ); } public int getDownloadCompleted(boolean bLive) { return( bLive ? downloadCompletedLive : downloadCompletedStored ); } public int getCheckingDoneInThousandNotation() { notSupported(); return( 0 ); } public long getDownloaded() { return( downloaded ); } public long getUploaded() { return( uploaded ); } public long getRemaining() { notSupported(); return( 0 ); } public long getDiscarded() { notSupported(); return( 0 ); } public long getDownloadAverage() { return( download_average ); } public long getUploadAverage() { return( upload_average ); } public long getTotalAverage() { notSupported(); return( 0 ); } public String getElapsedTime() { notSupported(); return( null ); } public String getETA() { return( eta ); } public long getETASecs() { notSupported(); return(0); } public long getHashFails() { notSupported(); return( 0 ); } public int getShareRatio() { return( share_ratio ); } public long getTimeStarted() { notSupported(); return ( 0 ); } public float getAvailability() { return( availability ); } public long getSecondsDownloading() { notSupported(); return ( 0 ); } public long getSecondsOnlySeeding() { notSupported(); return ( 0 ); } public long getTimeStartedSeeding() { notSupported(); return ( 0 ); } public long getSecondsSinceLastDownload() { notSupported(); return ( 0 ); } public long getSecondsSinceLastUpload() { notSupported(); return ( 0 ); } public int getHealth() { return( health ); } }azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/remote/download/RPDownload.java0000644000175000017500000004262411263244650026511 0ustar adrianadrian/* * File : PRDownload.java * Created : 28-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.remote.download; /** * @author parg * */ import java.io.File; import java.util.Map; import org.gudy.azureus2.plugins.disk.DiskManager; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.download.*; import org.gudy.azureus2.plugins.download.savelocation.*; import org.gudy.azureus2.plugins.peers.PeerManager; import org.gudy.azureus2.plugins.torrent.*; import org.gudy.azureus2.pluginsimpl.remote.*; import org.gudy.azureus2.pluginsimpl.remote.disk.RPDiskManagerFileInfo; import org.gudy.azureus2.pluginsimpl.remote.torrent.*; public class RPDownload extends RPObject implements Download { protected transient Download delegate; // don't change these field names as they are visible on XML serialisation public RPTorrent torrent; public RPDownloadStats stats; public RPDownloadAnnounceResult announce_result; public RPDownloadScrapeResult scrape_result; public int position; public boolean force_start; public static RPDownload create( Download _delegate ) { RPDownload res =(RPDownload)_lookupLocal( _delegate ); if ( res == null ){ res = new RPDownload( _delegate ); } return( res ); } protected RPDownload( Download _delegate ) { super( _delegate ); // torrent can be null if broken if ( delegate.getTorrent() != null ){ torrent = (RPTorrent)_lookupLocal( delegate.getTorrent()); if ( torrent == null ){ torrent = RPTorrent.create( delegate.getTorrent()); } } stats = (RPDownloadStats)_lookupLocal( delegate.getStats()); if ( stats == null ){ stats = RPDownloadStats.create( delegate.getStats()); } announce_result = (RPDownloadAnnounceResult)_lookupLocal( delegate.getLastAnnounceResult()); if ( announce_result == null ){ announce_result = RPDownloadAnnounceResult.create( delegate.getLastAnnounceResult()); } scrape_result = (RPDownloadScrapeResult)_lookupLocal( delegate.getLastScrapeResult()); if ( scrape_result == null ){ scrape_result = RPDownloadScrapeResult.create( delegate.getLastScrapeResult()); } } protected void _setDelegate( Object _delegate ) { delegate = (Download)_delegate; position = delegate.getPosition(); force_start = delegate.isForceStart(); } public Object _setLocal() throws RPException { Object res = _fixupLocal(); if ( torrent != null ){ torrent._setLocal(); } stats._setLocal(); announce_result._setLocal(); scrape_result._setLocal(); return( res ); } public void _setRemote( RPRequestDispatcher dispatcher ) { super._setRemote( dispatcher ); if ( torrent != null ){ torrent._setRemote( dispatcher ); } stats._setRemote( dispatcher ); announce_result._setRemote( dispatcher ); scrape_result._setRemote( dispatcher ); } public RPReply _process( RPRequest request ) { String method = request.getMethod(); if ( method.equals( "initialize")){ try{ delegate.initialize(); }catch( DownloadException e ){ return( new RPReply(e)); } return( null ); }else if ( method.equals( "start")){ try{ delegate.start(); }catch( DownloadException e ){ return( new RPReply(e)); } return( null ); }else if ( method.equals( "restart")){ try{ delegate.restart(); }catch( DownloadException e ){ return( new RPReply(e)); } return( null ); }else if ( method.equals( "stop")){ try{ delegate.stop(); }catch( DownloadException e ){ return( new RPReply(e)); } return( null ); }else if ( method.equals( "remove")){ try{ delegate.remove(); }catch( Throwable e ){ return( new RPReply(e)); } return( null ); }else if ( method.equals( "setForceStart[boolean]")){ boolean b = ((Boolean)request.getParams()[0]).booleanValue(); delegate.setForceStart( b ); return( null ); }else if ( method.equals( "setPosition[int]")){ int p = ((Integer)request.getParams()[0]).intValue(); delegate.setPosition( p ); return( null ); }else if ( method.equals( "moveUp")){ delegate.moveUp(); return( null ); }else if ( method.equals( "moveDown")){ delegate.moveDown(); return( null ); }else if ( method.equals( "moveTo[int]")){ int p = ((Integer)request.getParams()[0]).intValue(); delegate.setPosition( p ); return( null ); }else if ( method.equals( "setPriority[int]")){ delegate.setPriority(((Integer)request.getParams()[0]).intValue()); return( null ); }else if ( method.equals( "requestTrackerAnnounce")){ delegate.requestTrackerAnnounce(); return( null ); }else if ( method.equals( "getDiskManagerFileInfo")){ DiskManagerFileInfo[] info = delegate.getDiskManagerFileInfo(); RPDiskManagerFileInfo[] rp_info = new RPDiskManagerFileInfo[info.length]; for (int i=0;i listeners = new CopyOnWriteList(); private Set init_complete_fired_set = new HashSet(); private CopyOnWriteList event_listeners = new CopyOnWriteList(); private String key; private String pluginConfigKey; private Properties props; private String pluginDir; private PluginConfigImpl config; private String plugin_version; private Logger logger; private IPCInterfaceImpl ipc_interface; protected List children = new ArrayList(); private List configSections = new ArrayList(); private PluginStateImpl state; /** * This is the plugin ID value we were given when we were created. * * We might use it, but it depends what value is the plugins properties * (which will override this value). */ private String given_plugin_id; /** * We store this value as soon as someone calls getPluginID(), meaning * we will return a consistent value for the plugin's lifetime. */ private String plugin_id_to_use; public PluginInterfaceImpl( Plugin _plugin, PluginInitializer _initialiser, Object _initialiser_key, ClassLoader _class_loader, String _key, Properties _props, String _pluginDir, String _plugin_id, String _plugin_version ) { plugin = _plugin; initialiser = _initialiser; initialiser_key = _initialiser_key; class_loader = _class_loader; key = _key; pluginConfigKey = "Plugin." + _key; props = new propertyWrapper(_props ); pluginDir = _pluginDir; config = new PluginConfigImpl(this,pluginConfigKey); given_plugin_id = _plugin_id; plugin_version = _plugin_version; ipc_interface = new IPCInterfaceImpl( initialiser, plugin ); state = new PluginStateImpl(this, initialiser); } public Plugin getPlugin() { return( plugin ); } public boolean isOperational() { PluginDeprecation.call("isOperational", this.given_plugin_id); return getPluginState().isOperational(); } public Object getInitializerKey() { return( initialiser_key ); } public PluginManager getPluginManager() { return( initialiser.getPluginManager()); } public String getApplicationName() { return Constants.APP_NAME; } public String getAzureusName() { return( Constants.AZUREUS_NAME ); } public String getAzureusVersion() { return( Constants.AZUREUS_VERSION ); } /** * @deprecated */ public void addView(PluginView view) { getUIManager().getSWTManager().addView(view); } public void addConfigSection(ConfigSection section) { // Method is used by autocat. ConfigSectionRepository.getInstance().addConfigSection(section); configSections.add(section); } public void removeConfigSection(ConfigSection section) { ConfigSectionRepository.getInstance().removeConfigSection(section); configSections.remove(section); } public ConfigSection[] getConfigSections() { return (ConfigSection[]) configSections.toArray(new ConfigSection[0]); } /** * @deprecated */ public void openTorrentFile(String fileName) { PluginDeprecation.call("openTorrentFile", this.getPluginID()); try{ getDownloadManager().addDownload( new File(fileName)); }catch( DownloadException e ){ throw( new RuntimeException(e)); } } /** * @deprecated */ public void openTorrentURL(String url) { PluginDeprecation.call("openTorrentURL", this.getPluginID()); try{ getDownloadManager().addDownload( new URL( url )); }catch( Throwable e ){ throw( new RuntimeException(e)); } } public void setPluginName( String name ) { props.put( "plugin.name", name ); } public String getPluginName() { String name = null; if ( props != null ){ name = (String)props.get( "plugin.name"); } if ( name == null ){ try{ name = new File(pluginDir).getName(); }catch( Throwable e ){ } } if ( name == null || name.length() == 0 ){ name = plugin.getClass().getName(); } return( name ); } public void setPluginVersion( String version ) { props.put( "plugin.version", version ); } public String getPluginVersion() { String version = (String)props.get("plugin.version"); if ( version == null ){ version = plugin_version; } return( version ); } public String getPluginID() { String id = (String)props.get("plugin.id"); // hack alert - azupdater needs to change its plugin id due to general hackage if ( id != null && id.equals( "azupdater" )){ plugin_id_to_use = id; } if (plugin_id_to_use != null) {return plugin_id_to_use;} // Calculate what plugin ID value to use - look at the properties file // first, and if that isn't correct, base it on the given plugin ID // value we were given. if (id == null) {id = given_plugin_id;} if (id == null) {id = "";} plugin_id_to_use = id; return plugin_id_to_use; } public boolean isMandatory() { PluginDeprecation.call("isMandatory", this.given_plugin_id); return getPluginState().isMandatory(); } public boolean isBuiltIn() { PluginDeprecation.call("isBuiltIn", this.given_plugin_id); return getPluginState().isBuiltIn(); } public Properties getPluginProperties() { return(props); } public String getPluginDirectoryName() { return pluginDir; } public void setPluginDirectoryName( String name ) { initialiser_key = new File(name); pluginDir = name; } public void addConfigUIParameters(Parameter[] parameters, String displayName) { ParameterRepository.getInstance().addPlugin(parameters, displayName); } public PluginConfig getPluginconfig() { return config; } public PluginConfigUIFactory getPluginConfigUIFactory() { return new PluginConfigUIFactoryImpl(config,pluginConfigKey); } public String getPluginConfigKey() { return( pluginConfigKey ); } public Tracker getTracker() { return( TrackerImpl.getSingleton()); } public ShareManager getShareManager() throws ShareException { return( ShareManagerImpl.getSingleton()); } public DownloadManager getDownloadManager() { return( DownloadManagerImpl.getSingleton(initialiser.getAzureusCore())); } public MainlineDHTManager getMainlineDHTManager() { return new MainlineDHTManagerImpl(initialiser.getAzureusCore()); } public TorrentManager getTorrentManager() { return( TorrentManagerImpl.getSingleton().specialise( this )); } public Logger getLogger() { if ( logger == null ){ logger = new LoggerImpl( this ); } return( logger ); } public IPFilter getIPFilter() { return( new IPFilterImpl()); } public Utilities getUtilities() { return( new UtilitiesImpl( initialiser.getAzureusCore(), this )); } public ShortCuts getShortCuts() { return( new ShortCutsImpl(this)); } public UIManager getUIManager() { return( new UIManagerImpl( this )); } public UpdateManager getUpdateManager() { return( UpdateManagerImpl.getSingleton( initialiser.getAzureusCore())); } protected void unloadSupport() { ipc_interface.unload(); UIManagerImpl.unload( this ); } public boolean isUnloadable() { PluginDeprecation.call("unloadable", this.given_plugin_id); return getPluginState().isUnloadable(); } public void reload() throws PluginException { PluginDeprecation.call("reload", this.given_plugin_id); getPluginState().reload(); } public void unload() throws PluginException { PluginDeprecation.call("unload", this.given_plugin_id); getPluginState().unload(); } public void uninstall() throws PluginException { PluginDeprecation.call("uninstall", this.given_plugin_id); getPluginState().uninstall(); } public boolean isInitialisationThread() { return( initialiser.isInitialisationThread()); } public ClientIDManager getClientIDManager() { return( ClientIDManagerImpl.getSingleton()); } public ConnectionManager getConnectionManager() { return ConnectionManagerImpl.getSingleton( initialiser.getAzureusCore()); } public MessageManager getMessageManager() { return MessageManagerImpl.getSingleton( initialiser.getAzureusCore() ); } public DistributedDatabase getDistributedDatabase() { return( DDBaseImpl.getSingleton(initialiser.getAzureusCore())); } public PlatformManager getPlatformManager() { return( PlatformManagerFactory.getPlatformManager()); } protected void initialisationComplete() { Iterator it = listeners.iterator(); while( it.hasNext()){ try{ fireInitComplete( it.next()); }catch( Throwable e ){ Debug.printStackTrace( e ); } } for (int i=0;i= 0); } public PluginInterface getAlreadyInstalledPlugin() { return( installer.getAlreadyInstalledPlugin( getId())); } public void install( boolean shared ) throws PluginException { installer.install( this, shared ); } public void install( boolean shared, boolean low_noise, final boolean wait_until_done ) throws PluginException { final AESemaphore sem = new AESemaphore( "FPI" ); final PluginException[] error = { null }; installer.install( new InstallablePlugin[]{ this }, shared, low_noise, null, new PluginInstallationListener() { public void completed() { sem.release(); } public void cancelled() { failed( new PluginException( "Install cancelled" )); } public void failed( PluginException e ) { error[0] = e; sem.release(); if ( !wait_until_done ){ Debug.out( "Install failed", e ); } } }); if ( wait_until_done ){ sem.reserve(); if ( error[0] != null ){ throw( error[0] ); } } } public void uninstall() throws PluginException { installer.uninstall( this ); } public PluginInstaller getInstaller() { return( installer ); } public abstract void addUpdate( UpdateCheckInstance inst, PluginUpdatePlugin plugin_update_plugin, Plugin plugin, PluginInterface plugin_interface ); } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/installer/FilePluginInstallerImpl.java0000644000175000017500000002367211166774660031240 0ustar adrianadrian/* * Created on 30-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.installer; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.Plugin; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.installer.FilePluginInstaller; import org.gudy.azureus2.plugins.update.UpdatableComponent; import org.gudy.azureus2.plugins.update.Update; import org.gudy.azureus2.plugins.update.UpdateCheckInstance; import org.gudy.azureus2.plugins.update.UpdateChecker; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.update.PluginUpdatePlugin; import org.gudy.azureus2.pluginsimpl.update.sf.SFPluginDetailsLoader; import org.gudy.azureus2.pluginsimpl.update.sf.SFPluginDetailsLoaderFactory; /** * @author parg * */ public class FilePluginInstallerImpl extends InstallablePluginImpl implements FilePluginInstaller { protected PluginInstallerImpl installer; protected File file; protected String id; protected String version; protected String name; protected boolean is_jar; protected FilePluginInstallerImpl( PluginInstallerImpl _installer, File _file ) throws PluginException { super( _installer ); installer = _installer; file = _file; String name = file.getName(); int pos = name.lastIndexOf( "." ); boolean ok = false; if ( pos != -1 ){ String prefix = name.substring(0,pos); String suffix = name.substring(pos+1); // If the name part contains "_src" in it, then strip it out, // it'll just cause us more hassle to deal with it later. if (prefix.lastIndexOf("_src") != -1) { if (prefix.endsWith("_src")) { prefix = prefix.substring(0, prefix.length()-4); } else { int src_bit_pos = prefix.lastIndexOf("_src"); prefix = prefix.substring(0, src_bit_pos) + prefix.substring(src_bit_pos+1); } } if ( suffix.toLowerCase(MessageText.LOCALE_ENGLISH).equals( "jar") || suffix.toLowerCase(MessageText.LOCALE_ENGLISH).equals( "zip" )){ is_jar = suffix.toLowerCase(MessageText.LOCALE_ENGLISH).equals( "jar"); // See if we can get at the plugin.properties in the file Properties properties = null; ZipInputStream zis = null; try{ zis = new ZipInputStream( new BufferedInputStream( new FileInputStream( file ) )); while( properties == null ){ ZipEntry entry = zis.getNextEntry(); if ( entry == null ){ break; } String zip_name = entry.getName().toLowerCase( MessageText.LOCALE_ENGLISH ); // System.out.println( "zis1:" + zip_name ); if ( zip_name.equals( "plugin.properties" ) || zip_name.endsWith( "/plugin.properties")){ properties = new Properties(); properties.load( zis ); }else if ( zip_name.endsWith( ".jar" )){ ZipInputStream zis2 = new ZipInputStream( zis ); while( properties == null ){ ZipEntry entry2 = zis2.getNextEntry(); if ( entry2 == null ){ break; } String zip_name2 = entry2.getName().toLowerCase( MessageText.LOCALE_ENGLISH ); // System.out.println( " zis2:" + zip_name2 ); if ( zip_name2.equals( "plugin.properties" )){ properties = new Properties(); properties.load( zis2 ); } } } } }catch( Throwable e ){ throw( new PluginException( "Failed to read plugin file", e )); }finally{ if ( zis != null ){ try{ zis.close(); }catch( Throwable e ){ Debug.printStackTrace(e); } } } pos = prefix.lastIndexOf("_"); String filename_id = null, filename_version = null; if ( pos != -1 ){ filename_id = prefix.substring(0,pos); filename_version = prefix.substring(pos+1); } if ( properties == null ){ // one valid possibility here, this is a built-in plugin. this doesn't have // a plugin.properties if (filename_id != null) { id = filename_id; version = filename_version; PluginInterface pi = installer.getPluginManager().getPluginInterfaceByID( id ); ok = pi != null && ( pi.getPluginDirectoryName() == null || pi.getPluginDirectoryName().length() == 0 ); } if ( !ok ){ throw( new PluginException( "Mandatory file 'plugin.properties' not found in plugin file" )); } }else{ // properties != null // unfortunately plugin.id isn't mandatory for the properties, and neither is plugin.version PluginInitializer.checkJDKVersion( "", properties, false ); PluginInitializer.checkAzureusVersion("", properties, false); id = properties.getProperty( "plugin.id" ); version = properties.getProperty( "plugin.version" ); // Force both versions to be the same if they are both defined. String prop_version = version; if (prop_version != null && filename_version != null && !filename_version.equals(prop_version)) { throw new PluginException("inconsistent versions [file=" + filename_version + ", prop=" + prop_version + "]"); } } if ( id == null ){ // see if plugin is already loaded, if so we can get the id from it String plugin_class = properties.getProperty("plugin.class"); if ( plugin_class == null ){ String plugin_classes = properties.getProperty( "plugin.classes" ); if ( plugin_classes != null ){ int semi_pos = plugin_classes.indexOf(";"); if ( semi_pos == -1 ){ plugin_class = plugin_classes; }else{ plugin_class = plugin_classes.substring( 0, semi_pos ); } } } if ( plugin_class != null ){ try{ PluginInterface pi = installer.getPluginManager().getPluginInterfaceByClass( plugin_class ); if ( pi != null ){ id = pi.getPluginID(); } }catch( Throwable ignore ){ } } } pos = prefix.lastIndexOf("_"); if ( pos != -1 ){ id = id==null?prefix.substring(0,pos):id; // see if we can normalise the ID based on SF values try{ SFPluginDetailsLoader loader = SFPluginDetailsLoaderFactory.getSingleton(); String[] ids = loader.getPluginIDs(); for (int i=0;i_.[jar|zip]" )); } } public File getFile() { return( file ); } public String getId() { return( id ); } public String getVersion() { return( version ); } public String getName() { return( name ); } public String getDescription() { return( file.toString()); } public String getRelativeURLBase() { return( "" ); } public void addUpdate( UpdateCheckInstance inst, final PluginUpdatePlugin plugin_update_plugin, final Plugin plugin, final PluginInterface plugin_interface ) { inst.addUpdatableComponent( new UpdatableComponent() { public String getName() { return( name ); } public int getMaximumCheckTime() { return( 0 ); } public void checkForUpdate( UpdateChecker checker ) { try{ ResourceDownloader rd = plugin_interface.getUtilities().getResourceDownloaderFactory().create( file ); plugin_update_plugin.addUpdate( plugin_interface, checker, getName(), new String[]{"Installation from file: " + file.toString()}, version, rd, is_jar, plugin_interface.getPluginState().isUnloadable()?Update.RESTART_REQUIRED_NO:Update.RESTART_REQUIRED_YES, false ); }finally{ checker.completed(); } } }, false ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/installer/PluginInstallerImpl.java0000644000175000017500000005507311155331574030427 0ustar adrianadrian/* * Created on 28-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.installer; /** * @author parg * */ import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.util.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AETemporaryFileHandler; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.AsyncDispatcher; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.installer.*; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.UIManagerEvent; import org.gudy.azureus2.plugins.update.*; import org.gudy.azureus2.plugins.utils.StaticUtilities; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderAdapter; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException; import org.gudy.azureus2.pluginsimpl.local.FailedPlugin; import org.gudy.azureus2.pluginsimpl.local.update.UpdateCheckInstanceImpl; import org.gudy.azureus2.pluginsimpl.local.update.UpdateManagerImpl; import org.gudy.azureus2.pluginsimpl.update.sf.*; import org.gudy.azureus2.pluginsimpl.update.PluginUpdatePlugin; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.core.vuzefile.VuzeFileComponent; import com.aelitis.azureus.core.vuzefile.VuzeFileHandler; import com.aelitis.azureus.core.vuzefile.VuzeFileProcessor; public class PluginInstallerImpl implements PluginInstaller { protected static PluginInstallerImpl singleton; public static PluginInstallerImpl getSingleton( PluginManager _manager ) { if ( singleton == null ){ singleton = new PluginInstallerImpl( _manager ); } return( singleton ); } private PluginManager manager; private List listeners = new ArrayList(); private AsyncDispatcher add_file_install_dispatcher; protected PluginInstallerImpl( PluginManager _manager ) { manager = _manager; VuzeFileHandler.getSingleton().addProcessor( new VuzeFileProcessor() { public void process( VuzeFile[] files, int expected_types ) { for (int i=0;i 0 ){ Debug.out( "File plugin install operation queued pending completion of previous" ); } } }catch( Throwable e ){ Debug.printStackTrace(e); } } }); } } protected PluginManager getPluginManager() { return( manager ); } public StandardPlugin[] getStandardPlugins() throws PluginException { try{ SFPluginDetailsLoader loader = SFPluginDetailsLoaderFactory.getSingleton(); SFPluginDetails[] details = loader.getPluginDetails(); List res = new ArrayList(); for (int i=0;i properties, final PluginInstallationListener listener ) throws PluginException { install( plugins, shared, false, properties, listener ); } protected void install( InstallablePlugin[] plugins, boolean shared, boolean low_noise, Map properties, final PluginInstallationListener listener ) throws PluginException { PluginUpdatePlugin pup = (PluginUpdatePlugin)manager.getPluginInterfaceByClass( PluginUpdatePlugin.class ).getPlugin(); UpdateManagerImpl uman = (UpdateManagerImpl)manager.getDefaultPluginInterface().getUpdateManager(); UpdateCheckInstanceImpl inst = uman.createEmptyUpdateCheckInstance( UpdateCheckInstance.UCI_INSTALL, "update.instance.install", low_noise ); if ( properties != null ){ for ( Map.Entry entry: properties.entrySet()){ inst.setProperty( entry.getKey(), entry.getValue()); } } if ( listener != null ){ inst.addListener( new UpdateCheckInstanceListener() { public void cancelled( UpdateCheckInstance instance ) { listener.cancelled(); } public void complete( UpdateCheckInstance instance ) { final Update[] updates = instance.getUpdates(); if ( updates.length == 0 ){ listener.failed( new PluginException( "No updates were added during check process" )); }else{ for (int i=0;i 1 plugin interfaces, make the name up appropriately String update_name = ""; PluginInterface[] ifs = manager.getPluginInterfaces(); Arrays.sort( ifs, new Comparator() { public int compare( Object o1, Object o2) { return(((PluginInterface)o1).getPluginName().compareTo(((PluginInterface)o2).getPluginName())); } }); for (int i=0;i() { public Boolean run() throws IOException { TrackerWebPageRequestImpl request = new TrackerWebPageRequestImpl( tracker, TrackerWCHelper.this, external_request ); TrackerWebPageResponseImpl reply = new TrackerWebPageResponseImpl( request ); for (int i=0;i= generators.size()){ break; } generator = (TrackerWebPageGenerator)generators.get(i); }finally{ this_mon.exit(); } if ( generator.generate( request, reply )){ reply.complete(); return( true ); } } return( false ); } })); } public TrackerWebPageGenerator[] getPageGenerators() { TrackerWebPageGenerator[] res = new TrackerWebPageGenerator[generators.size()]; generators.toArray( res ); return( res ); } public void addPageGenerator( TrackerWebPageGenerator generator ) { try{ this_mon.enter(); generators.add( generator ); }finally{ this_mon.exit(); } } public void removePageGenerator( TrackerWebPageGenerator generator ) { try{ this_mon.enter(); generators.remove( generator ); }finally{ this_mon.exit(); } } public void destroy() { generators.clear(); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebContextImpl.java0000644000175000017500000001056311223045276030337 0ustar adrianadrian/* * File : TrackerWebContextImpl.java * Created : 23-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.tracker; /** * @author parg * */ import java.util.*; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URL; import org.gudy.azureus2.plugins.tracker.*; import org.gudy.azureus2.plugins.tracker.web.*; import org.gudy.azureus2.core3.tracker.server.*; import org.gudy.azureus2.core3.util.Debug; public class TrackerWebContextImpl extends TrackerWCHelper implements TRTrackerServerListener2, TRTrackerServerAuthenticationListener { protected TRTrackerServer server; protected List auth_listeners = new ArrayList(); public TrackerWebContextImpl( TrackerImpl _tracker, String name, int port, int protocol, InetAddress bind_ip ) throws TrackerException { setTracker( _tracker ); try{ if ( protocol == Tracker.PR_HTTP ){ server = TRTrackerServerFactory.create( name, TRTrackerServerFactory.PR_TCP, port, bind_ip, false, false ); }else{ server = TRTrackerServerFactory.createSSL( name, TRTrackerServerFactory.PR_TCP, port, bind_ip, false, false ); } server.addListener2( this ); }catch( TRTrackerServerException e ){ throw( new TrackerException("TRTrackerServerFactory failed", e )); } } public String getName() { return( server.getName()); } public void setEnableKeepAlive( boolean enable ) { server.setEnableKeepAlive( enable ); } public URL[] getURLs() { try{ URL url = new URL((server.isSSL()?"https":"http") + "://" + server.getHost() + ":" + server.getPort() + "/" ); // quick fix for badly specified host whereby a valid URL is constructed but the port lost. For example, if# // someone has entered http://1.2.3.4 as the host if ( url.getPort() != server.getPort()){ Debug.out( "Invalid URL '" + url + "' - check tracker configuration" ); url = new URL( "http://i.am.invalid:" + server.getPort() + "/" ); } return( new URL[]{ url }); }catch( MalformedURLException e ){ Debug.printStackTrace( e ); return( null ); } } public boolean authenticate( URL resource, String user, String password ) { for (int i=0;i header_map = new LinkedHashMap(); private TrackerWebPageRequestImpl request; private boolean is_async; private int explicit_gzip = 0; // not set, 1 = gzip, 2 = no gzip private boolean is_gzipped; protected TrackerWebPageResponseImpl( TrackerWebPageRequestImpl _request ) { request = _request; String formatted_date_now = TimeFormatter.getHTTPDate( SystemTime.getCurrentTime()); setHeader( "Last-Modified", formatted_date_now ); setHeader( "Expires", formatted_date_now ); } public void setLastModified( long time ) { String formatted_date = TimeFormatter.getHTTPDate( time ); setHeader( "Last-Modified", formatted_date ); } public void setExpires( long time ) { String formatted_date = TimeFormatter.getHTTPDate( time ); setHeader( "Expires", formatted_date ); } public void setContentType( String type ) { content_type = type; } public void setReplyStatus( int status ) { reply_status = status; } public void setHeader( String name, String value ) { addHeader( name, value, true ); } public void setGZIP( boolean gzip ) { explicit_gzip = gzip?1:2; } protected String addHeader( String name, String value, boolean replace ) { Iterator it = header_map.keySet().iterator(); while( it.hasNext()){ String key = it.next(); if ( key.equalsIgnoreCase( name )){ if ( replace ){ it.remove(); }else{ return( header_map.get( key )); } } } header_map.put( name, value ); return( value ); } public OutputStream getOutputStream() { return( baos ); } protected void complete() throws IOException { if ( is_async ){ return; } byte[] reply_bytes = baos.toByteArray(); // System.out.println( "TrackerWebPageResponse::complete: data = " + reply_bytes.length ); String status_string = "BAD"; // random collection if ( reply_status == 200 ){ status_string = "OK"; }else if ( reply_status == 204 ){ status_string = "No Content"; }else if ( reply_status == 206 ){ status_string = "Partial Content"; }else if ( reply_status == 401 ){ status_string = "Unauthorized"; }else if ( reply_status == 404 ){ status_string = "Not Found"; }else if ( reply_status == 501 ){ status_string = "Not Implemented"; } String reply_header = "HTTP/1.1 " + reply_status + " " + status_string + NL; // add header fields if not already present addHeader( "Server", Constants.AZUREUS_NAME + " " + Constants.AZUREUS_VERSION, false ); if ( request.canKeepAlive()){ String applied_value = addHeader( "Connection", "keep-alive", false ); if ( applied_value.equalsIgnoreCase( "keep-alive" )){ request.setKeepAlive( true ); } }else{ addHeader( "Connection", "close", true ); } addHeader( "Content-Type", content_type, false ); boolean do_gzip = false; if ( explicit_gzip == 1 && !is_gzipped ){ Map headers = request.getHeaders(); String accept_encoding = (String)headers.get("accept-encoding"); if ( HTTPUtils.canGZIP(accept_encoding)){ is_gzipped = do_gzip = true; header_map.put("Content-Encoding", "gzip"); } } Iterator it = header_map.keySet().iterator(); while( it.hasNext()){ String name = (String)it.next(); String value = (String)header_map.get(name); reply_header += name + ": " + value + NL; } if ( do_gzip ){ // try and set the content-length to that of the compressed data if ( reply_bytes.length < 512*1024 ){ ByteArrayOutputStream temp = new ByteArrayOutputStream( reply_bytes.length ); GZIPOutputStream gzos = new GZIPOutputStream(temp); gzos.write( reply_bytes ); gzos.finish(); reply_bytes = temp.toByteArray(); do_gzip = false; } } reply_header += "Content-Length: " + reply_bytes.length + NL + NL; // System.out.println( "writing reply:" + reply_header ); OutputStream os = request.getOutputStream(); os.write( reply_header.getBytes()); if ( do_gzip ){ GZIPOutputStream gzos = new GZIPOutputStream(os); gzos.write( reply_bytes ); gzos.finish(); }else{ os.write( reply_bytes ); } os.flush(); } public boolean useFile( String root_dir, String relative_url ) throws IOException { String target = root_dir + relative_url.replace('/',File.separatorChar); File canonical_file = new File(target).getCanonicalFile(); // make sure some fool isn't trying to use ../../ to escape from web dir if ( !canonical_file.toString().toLowerCase().startsWith( root_dir.toLowerCase())){ return( false ); } if ( canonical_file.isDirectory()){ return( false ); } if ( canonical_file.canRead()){ String str = canonical_file.toString().toLowerCase(); int pos = str.lastIndexOf( "." ); if ( pos == -1 ){ return( false ); } String file_type = str.substring(pos+1); FileInputStream fis = null; try{ fis = new FileInputStream(canonical_file); useStream( file_type, fis ); return( true ); }finally{ if ( fis != null ){ fis.close(); } } } return( false ); } public void useStream( String file_type, InputStream input_stream ) throws IOException { OutputStream os = getOutputStream(); String response_type = HTTPUtils.guessContentTypeFromFileType(file_type); if ( explicit_gzip != 2 && HTTPUtils.useCompressionForFileType(response_type)){ Map headers = request.getHeaders(); String accept_encoding = (String)headers.get("accept-encoding"); if ( HTTPUtils.canGZIP(accept_encoding)){ is_gzipped = true; os = new GZIPOutputStream(os); header_map.put("Content-Encoding", "gzip"); } } setContentType( response_type ); byte[] buffer = new byte[4096]; while(true){ int len = input_stream.read(buffer); if ( len <= 0 ){ break; } os.write( buffer, 0, len ); } if ( os instanceof GZIPOutputStream ){ ((GZIPOutputStream)os).finish(); } } public void writeTorrent( TrackerTorrent tracker_torrent ) throws IOException { try{ TRHostTorrent host_torrent = ((TrackerTorrentImpl)tracker_torrent).getHostTorrent(); TOTorrent torrent = host_torrent.getTorrent(); // make a copy of the torrent TOTorrent torrent_to_send = TOTorrentFactory.deserialiseFromMap(torrent.serialiseToMap()); // remove any non-standard stuff (e.g. resume data) torrent_to_send.removeAdditionalProperties(); if ( !TorrentUtils.isDecentralised( torrent_to_send )){ URL[][] url_sets = TRTrackerUtils.getAnnounceURLs(); // if tracker ip not set then assume they know what they're doing if ( host_torrent.getStatus() != TRHostTorrent.TS_PUBLISHED && url_sets.length > 0 ){ // if the user has disabled the mangling of urls when hosting then don't do it here // either if ( COConfigurationManager.getBooleanParameter("Tracker Host Add Our Announce URLs")){ String protocol = torrent_to_send.getAnnounceURL().getProtocol(); for (int i=0;i initialising -> initialized -> // disk states: allocating -> checking -> ready -> // dm states: downloading -> finishing -> seeding -> stopping -> stopped // "initialize" call takes from waiting -> initialising -> waiting (no port) or initialized (ok) // if initialized then disk manager runs through to ready // "startdownload" takes ready -> dl etc. // "stopIt" takes to stopped which is equiv to ready int our_state; switch( dm_state ){ case DownloadManager.STATE_WAITING: { our_state = ST_WAITING; break; } case DownloadManager.STATE_INITIALIZING: case DownloadManager.STATE_INITIALIZED: case DownloadManager.STATE_ALLOCATING: case DownloadManager.STATE_CHECKING: { our_state = ST_PREPARING; break; } case DownloadManager.STATE_READY: { our_state = ST_READY; break; } case DownloadManager.STATE_DOWNLOADING: case DownloadManager.STATE_FINISHING: // finishing download - transit to seeding { our_state = ST_DOWNLOADING; break; } case DownloadManager.STATE_SEEDING: { our_state = ST_SEEDING; break; } case DownloadManager.STATE_STOPPING: { our_state = ST_STOPPING; break; } case DownloadManager.STATE_STOPPED: { our_state = ST_STOPPED; break; } case DownloadManager.STATE_QUEUED: { our_state = ST_QUEUED; break; } case DownloadManager.STATE_ERROR: { our_state = ST_ERROR; break; } default: { our_state = ST_ERROR; } } return( our_state ); } public String getErrorStateDetails() { return( download_manager.getErrorDetails()); } public long getFlags() { return( download_manager.getDownloadState().getFlags()); } public boolean getFlag( long flag ) { return( download_manager.getDownloadState().getFlag( flag )); } public void setFlag(long flag, boolean set) { download_manager.getDownloadState().setFlag(flag, set); } public int getIndex() { GlobalManager globalManager = download_manager.getGlobalManager(); return globalManager.getIndexOf(download_manager); } public Torrent getTorrent() { if (this.torrent != null) {return this.torrent;} TOTorrent torrent = download_manager.getTorrent(); if (torrent == null) {return null;} this.torrent = new TorrentImpl(torrent); return this.torrent; } public void initialize() throws DownloadException { int state = download_manager.getState(); if ( state == DownloadManager.STATE_WAITING ){ download_manager.initialize(); }else{ throw( new DownloadException( "Download::initialize: download not waiting (state=" + state + ")" )); } } public void start() throws DownloadException { int state = download_manager.getState(); if ( state == DownloadManager.STATE_READY ){ download_manager.startDownload(); }else{ throw( new DownloadException( "Download::start: download not ready (state=" + state + ")" )); } } public void restart() throws DownloadException { int state = download_manager.getState(); if ( state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_QUEUED ){ download_manager.setStateWaiting(); }else{ throw( new DownloadException( "Download::restart: download already running (state=" + state + ")" )); } } public void stop() throws DownloadException { if ( download_manager.getState() != DownloadManager.STATE_STOPPED){ download_manager.stopIt( DownloadManager.STATE_STOPPED, false, false ); }else{ throw( new DownloadException( "Download::stop: download already stopped" )); } } public void stopAndQueue() throws DownloadException { if ( download_manager.getState() != DownloadManager.STATE_QUEUED){ download_manager.stopIt( DownloadManager.STATE_QUEUED, false, false ); }else{ throw( new DownloadException( "Download::stopAndQueue: download already queued" )); } } public void recheckData() throws DownloadException { if ( !download_manager.canForceRecheck()){ throw( new DownloadException( "Download::recheckData: download must be stopped, queued or in error state" )); } download_manager.forceRecheck(); } public boolean isStartStopLocked() { return( download_manager.getState() == DownloadManager.STATE_STOPPED ); } public boolean isForceStart() { return download_manager.isForceStart(); } public void setForceStart(boolean forceStart) { download_manager.setForceStart(forceStart); } public boolean isPaused() { return( download_manager.isPaused()); } public void pause() { download_manager.pause(); } public void resume() { download_manager.resume(); } public int getPosition() { return download_manager.getPosition(); } public long getCreationTime() { return( download_manager.getCreationTime()); } public void setPosition(int newPosition) { download_manager.setPosition(newPosition); } public void moveUp() { download_manager.getGlobalManager().moveUp(download_manager); } public void moveDown() { download_manager.getGlobalManager().moveDown(download_manager); } public void moveTo( int pos ) { download_manager.getGlobalManager().moveTo( download_manager, pos ); } public String getName() { return download_manager.getDisplayName(); } public String getTorrentFileName() { return download_manager.getTorrentFileName(); } public String getCategoryName() { Category category = download_manager.getDownloadState().getCategory(); if (category == null) category = CategoryManager.getCategory(Category.TYPE_UNCATEGORIZED); if (category == null) return null; return category.getName(); } public String getAttribute( TorrentAttribute attribute ) { String name = convertAttribute( attribute ); if ( name != null ){ return( download_manager.getDownloadState().getAttribute( name )); } return( null ); } public String[] getListAttribute( TorrentAttribute attribute ) { String name = convertAttribute( attribute ); if ( name != null ){ return( download_manager.getDownloadState().getListAttribute( name )); } return( null ); } public void setListAttribute( TorrentAttribute attribute, String[] value) { String name = convertAttribute(attribute); if (name != null) { download_manager.getDownloadState().setListAttribute(name, value); } } public void setMapAttribute( TorrentAttribute attribute, Map value ) { String name = convertAttribute( attribute ); if ( name != null ){ // gotta clone before updating in case user has read values and then just // updated them - setter code optimises out sets of the same values... download_manager.getDownloadState().setMapAttribute( name, BEncoder.cloneMap( value )); } } public Map getMapAttribute( TorrentAttribute attribute ) { String name = convertAttribute( attribute ); if ( name != null ){ return( download_manager.getDownloadState().getMapAttribute( name )); } return( null ); } public void setAttribute( TorrentAttribute attribute, String value ) { String name = convertAttribute( attribute ); if ( name != null ){ download_manager.getDownloadState().setAttribute( name, value ); } } public boolean hasAttribute(TorrentAttribute attribute) { String name = convertAttribute(attribute); if (name == null) {return false;} return download_manager.getDownloadState().hasAttribute(name); } public boolean getBooleanAttribute(TorrentAttribute attribute) { String name = convertAttribute(attribute); if (name == null) {return false;} // Default value return download_manager.getDownloadState().getBooleanAttribute(name); } public void setBooleanAttribute(TorrentAttribute attribute, boolean value) { String name = convertAttribute(attribute); if (name != null) { download_manager.getDownloadState().setBooleanAttribute(name, value); } } public int getIntAttribute(TorrentAttribute attribute) { String name = convertAttribute(attribute); if (name == null) {return 0;} // Default value return download_manager.getDownloadState().getIntAttribute(name); } public void setIntAttribute(TorrentAttribute attribute, int value) { String name = convertAttribute(attribute); if (name != null) { download_manager.getDownloadState().setIntAttribute(name, value); } } public long getLongAttribute(TorrentAttribute attribute) { String name = convertAttribute(attribute); if (name == null) {return 0L;} // Default value return download_manager.getDownloadState().getLongAttribute(name); } public void setLongAttribute(TorrentAttribute attribute, long value) { String name = convertAttribute(attribute); if (name != null) { download_manager.getDownloadState().setLongAttribute(name, value); } } protected String convertAttribute( TorrentAttribute attribute ) { if ( attribute.getName() == TorrentAttribute.TA_CATEGORY ){ return( DownloadManagerState.AT_CATEGORY ); }else if ( attribute.getName() == TorrentAttribute.TA_NETWORKS ){ return( DownloadManagerState.AT_NETWORKS ); }else if ( attribute.getName() == TorrentAttribute.TA_TRACKER_CLIENT_EXTENSIONS ){ return( DownloadManagerState.AT_TRACKER_CLIENT_EXTENSIONS ); }else if ( attribute.getName() == TorrentAttribute.TA_PEER_SOURCES ){ return( DownloadManagerState.AT_PEER_SOURCES ); }else if ( attribute.getName() == TorrentAttribute.TA_DISPLAY_NAME ){ return( DownloadManagerState.AT_DISPLAY_NAME ); }else if ( attribute.getName() == TorrentAttribute.TA_USER_COMMENT ){ return( DownloadManagerState.AT_USER_COMMENT ); }else if ( attribute.getName() == TorrentAttribute.TA_RELATIVE_SAVE_PATH ){ return( DownloadManagerState.AT_RELATIVE_SAVE_PATH ); }else if ( attribute.getName() == TorrentAttribute.TA_SHARE_PROPERTIES ){ // this is a share-level attribute only, not propagated to individual downloads return( null ); }else if ( attribute.getName().startsWith( "Plugin." )){ return( attribute.getName()); }else{ Debug.out( "Can't convert attribute '" + attribute.getName() + "'" ); return( null ); } } protected TorrentAttribute convertAttribute( String name ) { if ( name.equals( DownloadManagerState.AT_CATEGORY )){ return( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_CATEGORY )); }else if ( name.equals( DownloadManagerState.AT_NETWORKS )){ return( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_NETWORKS )); }else if ( name.equals( DownloadManagerState.AT_PEER_SOURCES )){ return( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_PEER_SOURCES )); }else if ( name.equals( DownloadManagerState.AT_TRACKER_CLIENT_EXTENSIONS )){ return( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_TRACKER_CLIENT_EXTENSIONS )); }else if ( name.equals ( DownloadManagerState.AT_DISPLAY_NAME)){ return ( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_DISPLAY_NAME )); }else if ( name.equals ( DownloadManagerState.AT_USER_COMMENT)){ return ( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_USER_COMMENT )); }else if ( name.equals ( DownloadManagerState.AT_RELATIVE_SAVE_PATH)){ return ( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_RELATIVE_SAVE_PATH )); }else if ( name.startsWith( "Plugin." )){ return( TorrentManagerImpl.getSingleton().getAttribute( name )); }else{ return( null ); } } public void setCategory(String sName) { Category category = CategoryManager.getCategory(sName); if (category == null) category = CategoryManager.createCategory(sName); download_manager.getDownloadState().setCategory(category); } public boolean isPersistent() { return download_manager.isPersistent(); } public void remove() throws DownloadException, DownloadRemovalVetoException { remove( false, false ); } public void remove( boolean delete_torrent, boolean delete_data ) throws DownloadException, DownloadRemovalVetoException { int dl_state = download_manager.getState(); if ( dl_state == DownloadManager.STATE_STOPPED || dl_state == DownloadManager.STATE_ERROR || dl_state == DownloadManager.STATE_QUEUED ){ GlobalManager globalManager = download_manager.getGlobalManager(); try{ globalManager.removeDownloadManager(download_manager, delete_torrent, delete_data); }catch( GlobalManagerDownloadRemovalVetoException e ){ throw( new DownloadRemovalVetoException( e.getMessage())); } }else{ throw( new DownloadRemovalVetoException( MessageText.getString("plugin.download.remove.veto.notstopped"))); } } public boolean canBeRemoved() throws DownloadRemovalVetoException { int dl_state = download_manager.getState(); if ( dl_state == DownloadManager.STATE_STOPPED || dl_state == DownloadManager.STATE_ERROR || dl_state == DownloadManager.STATE_QUEUED ){ GlobalManager globalManager = download_manager.getGlobalManager(); try{ globalManager.canDownloadManagerBeRemoved(download_manager, false, false); }catch( GlobalManagerDownloadRemovalVetoException e ){ throw( new DownloadRemovalVetoException( e.getMessage(),e.isSilent())); } }else{ throw( new DownloadRemovalVetoException( MessageText.getString("plugin.download.remove.veto.notstopped"))); } return( true ); } public DownloadStats getStats() { return( download_stats ); } public boolean isComplete() { return download_manager.isDownloadComplete(false); } public boolean isComplete(boolean bIncludeDND) { return download_manager.isDownloadComplete(bIncludeDND); } public boolean isChecking() { return( download_stats.getCheckingDoneInThousandNotation() != -1 ); } protected void isRemovable() throws DownloadRemovalVetoException { // no sync required, see update code for (int i=0;i 1000) { System.out.println("Plugin should move long processes (" + diff + "ms) off of Download's onCompletion listener trigger. " + dcl); } } } public void completionChanged( DownloadManager manager, boolean bCompleted) { } public void filePriorityChanged( DownloadManager download, org.gudy.azureus2.core3.disk.DiskManagerFileInfo file ) { } public void positionChanged( DownloadManager download, int oldPosition, int newPosition) { for (int i = 0; i < listeners.size(); i++) { try { long startTime = SystemTime.getCurrentTime(); DownloadListener listener = (DownloadListener)listeners.get(i); listener.positionChanged(this, oldPosition, newPosition); long diff = SystemTime.getCurrentTime() - startTime; if (diff > 1000) { System.out.println("Plugin should move long processes (" + diff + "ms) off of Download's positionChanged listener trigger. " + listener); } } catch (Throwable e) { Debug.printStackTrace( e ); } } } public void addListener( DownloadListener l ) { try{ listeners_mon.enter(); List new_listeners = new ArrayList( listeners ); new_listeners.add(l); listeners = new_listeners; }finally{ listeners_mon.exit(); } } public void removeListener( DownloadListener l ) { try{ listeners_mon.enter(); List new_listeners = new ArrayList(listeners); new_listeners.remove(l); listeners = new_listeners; }finally{ listeners_mon.exit(); } } public void addAttributeListener(DownloadAttributeListener listener, TorrentAttribute attr, int event_type) { String attribute = convertAttribute(attr); if (attribute == null) {return;} CopyOnWriteMap attr_map = this.getAttributeMapForType(event_type); CopyOnWriteList listener_list = (CopyOnWriteList)attr_map.get(attribute); boolean add_self = false; if (listener_list == null) { listener_list = new CopyOnWriteList(); attr_map.put(attribute, listener_list); } add_self = listener_list.isEmpty(); listener_list.add(listener); if (add_self) { download_manager.getDownloadState().addListener(this, attribute, event_type); } } public void removeAttributeListener(DownloadAttributeListener listener, TorrentAttribute attr, int event_type) { String attribute = convertAttribute(attr); if (attribute == null) {return;} CopyOnWriteMap attr_map = this.getAttributeMapForType(event_type); CopyOnWriteList listener_list = (CopyOnWriteList)attr_map.get(attribute); boolean remove_self = false; if (listener_list != null) { listener_list.remove(listener); remove_self = listener_list.isEmpty(); } if (remove_self) { download_manager.getDownloadState().removeListener(this, attribute, event_type); } } public DownloadAnnounceResult getLastAnnounceResult() { TRTrackerAnnouncer tc = download_manager.getTrackerClient(); if ( tc != null ){ last_announce_result.setContent( tc.getLastResponse()); } return( last_announce_result ); } public DownloadScrapeResult getLastScrapeResult() { TRTrackerScraperResponse response = download_manager.getTrackerScrapeResponse(); last_scrape_result.setContent( response ); return( last_scrape_result ); } public void scrapeResult( TRTrackerScraperResponse response ) { last_scrape_result.setContent( response ); for (int i=0;i 0 ? (name+" "):""; String msg = "Plugin " + plugin_name_bit + "requires " + Constants.APP_NAME + " version " + required_version + " or higher"; if (alert_on_fail) { Logger.log(new LogAlert(LogAlert.REPEATABLE, LogAlert.AT_ERROR, msg)); } throw new PluginException(msg); } } public static void checkJDKVersion( String name, Properties props, boolean alert_on_fail ) throws PluginException { String required_jdk = (String)props.get( "plugin.jdk.min_version" ); if ( required_jdk != null ){ String actual_jdk = System.getProperty( "java.version" ); required_jdk = normaliseJDK( required_jdk ); actual_jdk = normaliseJDK( actual_jdk ); if ( required_jdk.length() == 0 || actual_jdk.length() == 0 ){ return; } if ( Constants.compareVersions( actual_jdk, required_jdk ) < 0 ){ String msg = "Plugin " + (name.length()>0?(name+" "):"" ) + "requires Java version " + required_jdk + " or higher"; if ( alert_on_fail ){ Logger.log(new LogAlert(LogAlert.REPEATABLE, LogAlert.AT_ERROR, msg)); } throw( new PluginException( msg )); } } } protected static String normaliseJDK( String jdk ) { try{ String str = ""; // take leading digit+. portion only for (int i=0;i 1 ){ str = "1." + str; } return( str ); }catch( Throwable e ){ return( "" ); } } protected PluginInitializer( AzureusCore _azureus_core, AzureusCoreOperation _core_operation ) { azureus_core = _azureus_core; AEDiagnostics.addEvidenceGenerator( this ); azureus_core.addLifecycleListener( new AzureusCoreLifecycleAdapter() { public void componentCreated( AzureusCore core, AzureusCoreComponent comp ) { if ( comp instanceof GlobalManager ){ GlobalManager gm = (GlobalManager)comp; gm.addListener( PluginInitializer.this ); } } }); core_operation = _core_operation; UpdateManagerImpl.getSingleton( azureus_core ); // initialise the update manager plugin_manager = PluginManagerImpl.getSingleton( this ); String dynamic_plugins = System.getProperty( "azureus.dynamic.plugins", null ); if ( dynamic_plugins != null ){ String[] classes = dynamic_plugins.split( ";" ); for ( String c: classes ){ try{ queueRegistration( Class.forName( c )); }catch( Throwable e ){ Debug.out( "Registration of dynamic plugin '" + c + "' failed", e ); } } } UpdaterUtils.checkBootstrapPlugins(); } protected void fireCreated( PluginInterfaceImpl pi ) { azureus_core.triggerLifeCycleComponentCreated( pi ); } protected void fireOperational( PluginInterfaceImpl pi, boolean op ) { fireEventSupport( op?PluginEvent.PEV_PLUGIN_OPERATIONAL:PluginEvent.PEV_PLUGIN_NOT_OPERATIONAL, pi ); } public static void addInitThread() { synchronized( initThreads ){ if ( initThreads.contains( Thread.currentThread())){ Debug.out( "Already added" ); } initThreads.add( Thread.currentThread()); } } public static void removeInitThread() { synchronized( initThreads ){ initThreads.remove( Thread.currentThread()); } } protected boolean isInitialisationThread() { synchronized( initThreads ){ return initThreads.contains(Thread.currentThread()); } } public List loadPlugins( AzureusCore core, boolean bSkipAlreadyLoaded, boolean load_external_plugins, boolean loading_for_startup, boolean initialise_plugins) { if ( bSkipAlreadyLoaded ){ // discard any failed ones List pis; synchronized( s_plugin_interfaces ){ pis = new ArrayList( s_plugin_interfaces ); } for (int i=0;i 1 ){ String name = jar_file.getName(); if ( name.startsWith( "i18nPlugin_" )){ // non-versioned version still there, rename it if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "renaming '" + name + "' to conform with versioning system")); jar_file.renameTo( new File( jar_file.getParent(), "i18nAZ_0.1.jar " )); continue; } } plugin_class_loader = PluginLauncherImpl.addFileToClassPath( root_class_loader, plugin_class_loader, jar_file); } String plugin_class_string = null; try { Properties props = new Properties(); File properties_file = new File(directory.toString() + File.separator + "plugin.properties"); try { // if properties file exists on its own then override any properties file // potentially held within a jar if ( properties_file.exists()){ FileInputStream fis = null; try{ fis = new FileInputStream( properties_file ); props.load( fis ); }finally{ if ( fis != null ){ fis.close(); } } }else{ if ( plugin_class_loader instanceof URLClassLoader ){ URLClassLoader current = (URLClassLoader)plugin_class_loader; URL url = current.findResource("plugin.properties"); if ( url != null ){ URLConnection connection = url.openConnection(); InputStream is = connection.getInputStream(); props.load(is); }else{ throw( new Exception( "failed to load plugin.properties from jars")); } }else{ throw( new Exception( "failed to load plugin.properties from dir or jars")); } } }catch( Throwable e ){ Debug.printStackTrace( e ); String msg = "Can't read 'plugin.properties' for plugin '" + pluginName + "': file may be missing"; Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, msg)); System.out.println( msg ); throw( new PluginException( msg, e )); } checkJDKVersion( pluginName, props, true ); checkAzureusVersion(pluginName, props, true); plugin_class_string = (String)props.get( "plugin.class"); if ( plugin_class_string == null ){ plugin_class_string = (String)props.get( "plugin.classes"); if ( plugin_class_string == null ){ // set so we don't bork later will npe plugin_class_string = ""; } } String plugin_name_string = (String)props.get( "plugin.name"); if ( plugin_name_string == null ){ plugin_name_string = (String)props.get( "plugin.names"); } int pos1 = 0; int pos2 = 0; while(true){ int p1 = plugin_class_string.indexOf( ";", pos1 ); String plugin_class; if ( p1 == -1 ){ plugin_class = plugin_class_string.substring(pos1).trim(); }else{ plugin_class = plugin_class_string.substring(pos1,p1).trim(); pos1 = p1+1; } PluginInterfaceImpl existing_pi = getPluginFromClass( plugin_class ); if ( existing_pi != null ){ if (bSkipAlreadyLoaded) { break; } // allow user dir entries to override app dir entries without warning File this_parent = directory.getParentFile(); File existing_parent = null; if ( existing_pi.getInitializerKey() instanceof File ){ existing_parent = ((File)existing_pi.getInitializerKey()).getParentFile(); } if ( this_parent.equals( FileUtil.getApplicationFile("plugins")) && existing_parent != null && existing_parent.equals( FileUtil.getUserFile( "plugins" ))){ // skip this overridden plugin if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Plugin '" + plugin_name_string + "/" + plugin_class + ": shared version overridden by user-specific one")); return( new ArrayList()); }else{ Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_WARNING, "Error loading '" + plugin_name_string + "', plugin class '" + plugin_class + "' is already loaded")); } }else{ String plugin_name = null; if ( plugin_name_string != null ){ int p2 = plugin_name_string.indexOf( ";", pos2 ); if ( p2 == -1 ){ plugin_name = plugin_name_string.substring(pos2).trim(); }else{ plugin_name = plugin_name_string.substring(pos2,p2).trim(); pos2 = p2+1; } } Properties new_props = (Properties)props.clone(); for (int j=0;j 0) { PluginInterfaceImpl plugin_interface = (PluginInterfaceImpl) l.get(0); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Initializing plugin '" + plugin_interface.getPluginName() + "'")); if (core_operation != null) { core_operation.reportCurrentTask(MessageText .getString("splash.plugin.init") + " " + plugin_interface.getPluginName()); } initialisePlugin(l); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Initialization of plugin '" + plugin_interface.getPluginName() + "' complete")); } } catch ( Throwable e ){ // already handled } finally { if (core_operation != null) { core_operation.reportPercent((100 * (idx + 1)) / loaded_pi_list.size()); } } // some plugins try and steal the logger stdout redirects. // re-establish them if needed Logger.doRedirects(); } }); } // now do built in ones initQueue.add(new Runnable() { public void run() { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Initializing built-in plugins")); } }); final PluginManagerDefaults def = PluginManager.getDefaults(); for (int i = 0; i < builtin_plugins.length; i++) { final int idx = i; initQueue.add(new Runnable() { public void run() { if (def.isDefaultPluginEnabled(builtin_plugins[idx][0])) { String id = builtin_plugins[idx][2]; String key = builtin_plugins[idx][3]; try { Class cla = root_class_loader.loadClass( builtin_plugins[idx][1]); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Initializing built-in plugin '" + builtin_plugins[idx][2] + "'" )); initializePluginFromClass(cla, id, key, "true".equals(builtin_plugins[idx][5]), true, true); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Initialization of built in plugin '" + builtin_plugins[idx][2] + "' complete")); } catch (Throwable e) { try { // replace it with a "broken" plugin instance initializePluginFromClass(FailedPlugin.class, id, key, false, false, true); } catch (Throwable f) { } if (builtin_plugins[idx][4].equalsIgnoreCase("true")) { Debug.printStackTrace(e); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "Initialization of built in plugin '" + builtin_plugins[idx][2] + "' fails", e)); } } } else { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Built-in plugin '" + builtin_plugins[idx][2] + "' is disabled")); } } }); } initQueue.add(new Runnable() { public void run() { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Initializing dynamically registered plugins")); } }); for (int i = 0; i < registration_queue.size(); i++) { final int idx = i; initQueue.add(new Runnable() { public void run() { try { Object entry = registration_queue.get(idx); if (entry instanceof Class) { Class cla = (Class) entry; singleton.initializePluginFromClass(cla, INTERNAL_PLUGIN_ID, cla .getName(), false, true, true); } else { Object[] x = (Object[]) entry; Plugin plugin = (Plugin) x[0]; singleton.initializePluginFromInstance(plugin, (String) x[1], plugin .getClass().getName()); } } catch (PluginException e) { } } }); } AEThread2 secondaryInitializer = new AEThread2("2nd PluginInitializer Thread",true) { public void run() { try{ addInitThread(); while( true ){ Runnable toRun; synchronized (initQueue){ if (initQueue.isEmpty()){ break; } toRun = (Runnable)initQueue.remove(0); } try{ toRun.run(); }catch( Throwable e ){ Debug.out(e); } } }finally{ removeInitThread(); } } }; secondaryInitializer.start(); while(true){ Runnable toRun; synchronized( initQueue ){ if( initQueue.isEmpty()){ break; } toRun = (Runnable)initQueue.remove(0); } try{ toRun.run(); }catch( Throwable e ){ Debug.out(e); } } secondaryInitializer.join(); registration_queue.clear(); plugins_initialised = true; fireEvent( PluginEvent.PEV_ALL_PLUGINS_INITIALISED ); }finally{ removeInitThread(); } } protected void checkPluginsInitialised() { if ( !plugins_initialised ){ Debug.out( "Wait until plugin initialisation is complete until doing this!" ); } } private void initialisePlugin( List l ) throws PluginException { PluginException last_load_failure = null; for (int i=0;i() { public void run() throws PluginException { fireCreated( plugin_interface ); plugin.initialize(plugin_interface); if (!(plugin instanceof FailedPlugin)){ plugin_interface.getPluginStateImpl().setOperational( true, false ); } } }); }catch( Throwable e ){ load_failure = e; } synchronized( s_plugin_interfaces ){ s_plugins.add( plugin ); s_plugin_interfaces.add( plugin_interface ); } if ( load_failure != null ){ Debug.printStackTrace( load_failure ); String msg = "Error initializing plugin '" + plugin_interface.getPluginName() + "'"; Logger.log(new LogAlert(LogAlert.UNREPEATABLE, msg, load_failure)); System.out.println( msg + " : " + load_failure); last_load_failure = new PluginException( msg, load_failure ); } } if ( last_load_failure != null ){ throw( last_load_failure ); } } protected void initializePluginFromClass( final Class plugin_class, final String plugin_id, String plugin_config_key, boolean force_enabled, boolean loading_for_startup, boolean initialise) throws PluginException { if ( plugin_class != FailedPlugin.class && getPluginFromClass( plugin_class ) != null ){ Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_WARNING, "Error loading '" + plugin_id + "', plugin class '" + plugin_class.getName() + "' is already loaded")); return; } try{ final Plugin plugin = (Plugin) plugin_class.newInstance(); String plugin_name; if ( plugin_config_key.length() == 0 ){ plugin_name = plugin_class.getName(); int pos = plugin_name.lastIndexOf("."); if ( pos != -1 ){ plugin_name = plugin_name.substring( pos+1 ); } }else{ plugin_name = plugin_config_key; } Properties properties = new Properties(); // default plugin name properties.put( "plugin.name", plugin_name ); final PluginInterfaceImpl plugin_interface = new PluginInterfaceImpl( plugin, this, plugin_class, plugin_class.getClassLoader(), plugin_config_key, properties, "", plugin_id, null ); boolean bEnabled = (loading_for_startup) ? plugin_interface.getPluginState().isLoadedAtStartup() : initialise; /** * For some plugins, override any config setting which disables the plugin. */ if (force_enabled && !bEnabled) { plugin_interface.getPluginState().setLoadedAtStartup(true); bEnabled = true; Logger.log(new LogAlert(false, LogAlert.AT_WARNING, MessageText.getString( "plugins.init.force_enabled", new String[] {plugin_id} ))); } plugin_interface.getPluginState().setDisabled(!bEnabled); final boolean f_enabled = bEnabled; UtilitiesImpl.callWithPluginThreadContext( plugin_interface, new runnableWithException() { public void run() throws PluginException { try{ Method load_method = plugin_class.getMethod( "load", new Class[]{ PluginInterface.class }); load_method.invoke( plugin, new Object[]{ plugin_interface }); }catch( NoSuchMethodException e ){ }catch( Throwable e ){ Debug.printStackTrace( e ); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "Load of built in plugin '" + plugin_id + "' fails", e)); } if (f_enabled) { if ( core_operation != null ){ core_operation.reportCurrentTask(MessageText.getString("splash.plugin.init") + " " + plugin_interface.getPluginName()); } fireCreated( plugin_interface ); plugin.initialize(plugin_interface); if (!(plugin instanceof FailedPlugin)){ plugin_interface.getPluginStateImpl().setOperational( true, false ); } } } }); synchronized( s_plugin_interfaces ){ s_plugins.add( plugin ); s_plugin_interfaces.add( plugin_interface ); } }catch(Throwable e){ Debug.printStackTrace( e ); String msg = "Error loading internal plugin '" + plugin_class.getName() + "'"; Logger.log(new LogAlert(LogAlert.UNREPEATABLE, msg, e)); System.out.println(msg + " : " + e); throw( new PluginException( msg, e )); } } protected void initializePluginFromInstance( final Plugin plugin, String plugin_id, String plugin_config_key ) throws PluginException { try{ final PluginInterfaceImpl plugin_interface = new PluginInterfaceImpl( plugin, this, plugin.getClass(), plugin.getClass().getClassLoader(), plugin_config_key, new Properties(), "", plugin_id, null ); UtilitiesImpl.callWithPluginThreadContext( plugin_interface, new UtilitiesImpl.runnableWithException() { public void run() throws PluginException { fireCreated( plugin_interface ); plugin.initialize(plugin_interface); if (!(plugin instanceof FailedPlugin)){ plugin_interface.getPluginStateImpl().setOperational( true, false ); } } }); synchronized( s_plugin_interfaces ){ s_plugins.add( plugin ); s_plugin_interfaces.add( plugin_interface ); } }catch(Throwable e){ Debug.printStackTrace( e ); String msg = "Error loading internal plugin '" + plugin.getClass().getName() + "'"; Logger.log(new LogAlert(LogAlert.UNREPEATABLE, msg, e)); System.out.println(msg + " : " + e); throw( new PluginException( msg, e )); } } protected void unloadPlugin( PluginInterfaceImpl pi ) { synchronized( s_plugin_interfaces ){ s_plugins.remove( pi.getPlugin()); s_plugin_interfaces.remove( pi ); } pi.unloadSupport(); for (int i=0;i 1 ){ listener.messageLogged( LoggerChannel.LT_ERROR, "Multiple launchable plugins found, running first" ); } try{ // set default details for restarter SystemProperties.setApplicationEntryPoint( "org.gudy.azureus2.plugins.PluginLauncher" ); launchables[0].setDefaults( args ); // see if we're a secondary instance if ( PluginSingleInstanceHandler.process( listener, args )){ return; } // we have to run the core startup on a separate thread and then effectively pass "this thread" // through to the launchable "process" method Thread core_thread = new Thread( "PluginLauncher" ) { public void run() { try{ // give 'process' call below some time to start up Thread.sleep(500); AzureusCore azureus_core = AzureusCoreFactory.create(); azureus_core.start(); }catch( Throwable e ){ listener.messageLogged( "PluginLauncher: launch fails", e ); } } }; core_thread.setDaemon( true ); core_thread.start(); boolean restart = false; boolean process_succeeded = false; try{ restart = launchables[0].process(); process_succeeded = true; }finally{ try{ if ( restart ){ AzureusCoreFactory.getSingleton().restart(); }else{ AzureusCoreFactory.getSingleton().stop(); } }catch( Throwable e ){ // only report this exception if we're not already failing if ( process_succeeded ){ throw( e ); } } } }catch( Throwable e ){ listener.messageLogged( "PluginLauncher: launch fails", e ); } } private static LaunchablePlugin[] findLaunchablePlugins( LoggerChannelListener listener ) { // CAREFUL - this is called BEFORE any AZ initialisation has been performed and must // therefore NOT use anything that relies on this (such as logging, debug....) List res = new ArrayList(); File app_dir = getApplicationFile("plugins"); if ( !( app_dir.exists()) && app_dir.isDirectory()){ listener.messageLogged( LoggerChannel.LT_ERROR, "Application dir '" + app_dir + "' not found" ); return( new LaunchablePlugin[0] ); } File[] plugins = app_dir.listFiles(); if ( plugins == null || plugins.length == 0 ){ listener.messageLogged( LoggerChannel.LT_ERROR, "Application dir '" + app_dir + "' empty" ); return( new LaunchablePlugin[0] ); } for ( int i=0;i 0 && discard_non_versioned_when_versioned_found ){ res.clear(); } // fix a problem we had with the rating plugin. It went out as rating_x.jar when it should // have been azrating_x.jar. If there are any azrating entries then we remove any rating ones // to avoid load problems if ( version_map.containsKey( "azrating" )){ version_map.remove( "rating" ); } Iterator it = version_map.keySet().iterator(); while(it.hasNext()){ String prefix = (String)it.next(); String version = (String)version_map.get(prefix); String target = prefix + "_" + version; version_out[0] = version; id_out[0] = prefix; for (int i=0;i 1 ){ filter_override = true; use_filter = true; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "ClientIDManager: overriding filter " + "option to support local bind IP")); } } } if ( use_filter ){ try{ thread_pool = new ThreadPool( "ClientIDManager", 32 ); String connect_timeout = System.getProperty("sun.net.client.defaultConnectTimeout"); String read_timeout = System.getProperty("sun.net.client.defaultReadTimeout"); int timeout = Integer.parseInt( connect_timeout ) + Integer.parseInt( read_timeout ); thread_pool.setExecutionLimit( timeout ); final ServerSocket ss = new ServerSocket( 0, 1024, InetAddress.getByName("127.0.0.1")); filter_port = ss.getLocalPort(); ss.setReuseAddress(true); Thread accept_thread = new AEThread("ClientIDManager::filterloop") { public void runSupport() { long successfull_accepts = 0; long failed_accepts = 0; while(true){ try{ Socket socket = ss.accept(); successfull_accepts++; thread_pool.run( new httpFilter( socket )); }catch( Throwable e ){ failed_accepts++; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "ClientIDManager: listener failed on port " + filter_port, e )); if ( failed_accepts > 100 && successfull_accepts == 0 ){ // looks like its not going to work... // some kind of socket problem Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Network.alert.acceptfail"), new String[] { "" + filter_port, "TCP" }); use_filter = false; break; } } } } }; accept_thread.setDaemon( true ); accept_thread.start(); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "ClientIDManager: listener established on port " + filter_port)); }catch( Throwable e){ Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Tracker.alert.listenfail"), new String[] { "" + filter_port }); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "ClientIDManager: listener failed on port " + filter_port, e)); use_filter = false; } } } public ClientIDGenerator getGenerator() { checkGenerator( generator_user_accessor ); return( generator_user_accessor ); } protected void checkGenerator( ClientIDGenerator gen ) { ClassLoader cl = gen.getClass().getClassLoader(); if ( cl != null && cl != ClientIDManager.class.getClassLoader()){ Debug.out( "Generator isn't trusted - " + gen ); throw( new RuntimeException( "Generator isn't trusted" )); } } public byte[] generatePeerID( TOTorrent torrent, boolean for_tracker ) throws ClientIDException { return( getGenerator().generatePeerID( new TorrentImpl( torrent ), for_tracker )); } public void generateHTTPProperties( Properties properties ) throws ClientIDException { if ( use_filter ){ // to support SSL here we would need to substitute the https url with an https one // and then drive the SSL in the filter appropriately URL url = (URL)properties.get( ClientIDGenerator.PR_URL ); if ( !url.getProtocol().toLowerCase().equals( "http" )){ Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "ClientIDManager only supports filtering of http, not https")); return; } try{ String url_str = url.toString(); String target_host = url.getHost(); int target_port = url.getPort(); if ( target_port == -1 ){ target_port = url.getDefaultPort(); } int host_pos = url_str.indexOf( target_host ); String new_url = url_str.substring(0,host_pos) + "127.0.0.1:" + filter_port; String rem = url_str.substring( host_pos + target_host.length()); if ( rem.charAt(0) == ':' ){ rem = rem.substring( (""+ target_port ).length() + 1 ); } int q_pos = rem.indexOf( '?' ); new_url += rem.substring(0,q_pos+1) + "cid=" + target_host + ":" + target_port + "&" + rem.substring(q_pos+1); properties.put( ClientIDGenerator.PR_URL, new URL( new_url )); }catch( Throwable e ){ Debug.printStackTrace(e); } }else{ getGenerator().generateHTTPProperties( properties ); } } protected class httpFilter extends ThreadPoolTask { private Socket socket; protected httpFilter( Socket _socket ) { socket = _socket; } public void runSupport() { String report_error = null; int written = 0; try{ setTaskState( "reading header" ); InputStream is = socket.getInputStream(); byte[] buffer = new byte[1024]; String header = ""; while(true ){ int len = is.read(buffer); if ( len == -1 ){ break; } header += new String( buffer, 0, len, Constants.BYTE_ENCODING ); if ( header.endsWith( NL+NL ) || header.indexOf( NL+NL ) != -1 ){ break; } } List lines = new ArrayList(); int pos = 0; while( true){ int p1 = header.indexOf( NL, pos ); String line; if ( p1 == -1 ){ line = header.substring(pos); }else{ line = header.substring( pos, p1 ); } line = line.trim(); if ( line.length() > 0 ){ lines.add( line ); } if ( p1 == -1 ){ break; } pos = p1+2; } String[] lines_in = new String[ lines.size()]; lines.toArray( lines_in ); String get = lines_in[0]; int p1 = get.indexOf( "?cid=" ); int p2 = get.indexOf( "&", p1 ); String cid = get.substring( p1+5, p2 ); int p3 = cid.indexOf( ":" ); String target_host = cid.substring( 0, p3 ); int target_port = Integer.parseInt( cid.substring(p3+1)); // fix up the Host: entry with the target details for (int i=1;i getMaximumMessageSize()){ throw( new MessageException( "Message is too large: supplied is " + size + ", maximum is " + getMaximumMessageSize())); } delegate.send( message ); } protected void receive( GenericMessage message ) { boolean handled = false; for (int i=0;i read_lim ){ length_buffer.limit( length_buffer.position() + read_lim ); } bytes_read = transport.read( buffers, 0, 1 ); length_buffer.limit( lim ); protocol_bytes_last_read += bytes_read; if ( length_buffer.hasRemaining()){ total_read += bytes_read; break; }else{ length_buffer.flip(); int size = length_buffer.getInt(); if ( size > MAX_MESSAGE_LENGTH ){ Debug.out( "Message too large for generic payload" ); throw( new IOException( "message too large" )); } buffers[1] = ByteBuffer.allocate( size ); length_buffer.flip(); } }else{ int rem = payload_buffer.remaining(); int lim = payload_buffer.limit(); if ( rem > read_lim ){ payload_buffer.limit( payload_buffer.position() + read_lim ); } bytes_read = transport.read( buffers, 1, 1 ); payload_buffer.limit( lim ); data_bytes_last_read += bytes_read; if ( payload_buffer.hasRemaining()){ total_read += bytes_read; break; } payload_buffer.flip(); messages.add( new GenericMessage( msg_type, msg_desc, new DirectByteBuffer( payload_buffer ), false )); buffers[1] = null; } total_read += bytes_read; } if ( destroyed ){ throw( new IOException( "decoder has been destroyed" )); } return((int) total_read ); } public Message[] removeDecodedMessages() { if( messages.isEmpty() ) return null; Message[] msgs = (Message[])messages.toArray( new Message[messages.size()] ); messages.clear(); return( msgs ); } public int getProtocolBytesDecoded() { return( protocol_bytes_last_read ); } public int getDataBytesDecoded() { return( data_bytes_last_read ); } public int getPercentDoneOfCurrentMessage() { return( 0 ); } public void pauseDecoding() { } public void resumeDecoding() { } public ByteBuffer destroy() { destroyed = true; return( null ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageEndpointImpl.java0000644000175000017500000000514110453514544031644 0ustar adrianadrian/* * Created on 19 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.messaging; import java.net.InetSocketAddress; import org.gudy.azureus2.plugins.messaging.generic.GenericMessageEndpoint; import com.aelitis.azureus.core.networkmanager.ConnectionEndpoint; import com.aelitis.azureus.core.networkmanager.ProtocolEndpoint; import com.aelitis.azureus.core.networkmanager.impl.tcp.ProtocolEndpointTCP; import com.aelitis.azureus.core.networkmanager.impl.udp.ProtocolEndpointUDP; public class GenericMessageEndpointImpl implements GenericMessageEndpoint { private ConnectionEndpoint ce; public GenericMessageEndpointImpl( ConnectionEndpoint _ce ) { ce = _ce; } public GenericMessageEndpointImpl( InetSocketAddress _ne ) { ce = new ConnectionEndpoint( _ne ); } public InetSocketAddress getNotionalAddress() { return( ce.getNotionalAddress()); } protected ConnectionEndpoint getConnectionEndpoint() { return( ce ); } public void addTCP( InetSocketAddress target ) { ce.addProtocol( new ProtocolEndpointTCP( target )); } public InetSocketAddress getTCP() { ProtocolEndpoint[] pes = ce.getProtocols(); for (int i=0;i 0){ // queue as a *raw* message as already encoded connection.getOutgoingMessageQueue().addMessage( new GenericMessage( msg_id, msg_desc, new DirectByteBuffer( remaining_initial_data ), true), false ); } listener.connectSuccess(); startProcessing(); }catch( Throwable e ){ connectFailure( e ); } } public void connectFailure( Throwable failure_msg ) { listener.connectFailure( failure_msg ); connection.close(); } public void exceptionThrown( Throwable error ) { listener.connectFailure( error ); connection.close(); } public String getDescription() { return( "generic connection"); } }); } protected void startProcessing() { connection.getIncomingMessageQueue().registerQueueListener( new IncomingMessageQueue.MessageQueueListener() { public boolean messageReceived( Message _message ) { GenericMessage message = (GenericMessage)_message; owner.receive( message ); return( true ); } public void protocolBytesReceived( int byte_count ) { } public void dataBytesReceived( int byte_count ) { } }); connection.getOutgoingMessageQueue().registerQueueListener( new OutgoingMessageQueue.MessageQueueListener() { public boolean messageAdded( Message message ) { //System.out.println( " added: " + message ); return( true ); } public void messageQueued( Message message ) { //System.out.println( " queued: " + message ); } public void messageRemoved( Message message ) { //System.out.println( " removed: " + message ); } public void messageSent( Message message ) { //System.out.println( " sent: " + message ); } public void protocolBytesSent( int byte_count ) { } public void dataBytesSent( int byte_count ) { } public void flush(){} }); connection.startMessageProcessing(); connection.enableEnhancedMessageProcessing( true, -1 ); synchronized( this ){ if ( inbound_rls != null ){ for (int i=0;i 0 ){ log( "local=" + local_total + " [" + getLocalConnectionStatus() + "], remote=" + remote_total + " [" + getRemoteConnectionStatus() + "]" ); } } } if ( tick_count % KEEP_ALIVE_CHECK_TICKS == 0 ){ synchronized( local_connections ){ Iterator it = local_connections.values().iterator(); while( it.hasNext()){ final GenericMessageConnectionIndirect con = (GenericMessageConnectionIndirect)it.next(); if ( con.prepareForKeepAlive( false )){ keep_alive_pool.run( new AERunnable() { public void runSupport() { con.keepAlive(); } }); } } } long now = SystemTime.getCurrentTime(); synchronized( remote_connections ){ if ( remote_connections.size() > 0 ){ // copy the connections here as we can recursively modify the set when closing Iterator it = new ArrayList( remote_connections.values()).iterator(); while( it.hasNext()){ GenericMessageConnectionIndirect con = (GenericMessageConnectionIndirect)it.next(); long last_receive = con.getLastMessageReceivedTime(); if ( now - last_receive > KEEP_ALIVE_MIN * 3 ){ try{ con.close( new Throwable( "Timeout" )); }catch( Throwable e ){ Debug.printStackTrace(e); } } } } } } } }); } protected static Map receive( MessageManagerImpl message_manager, InetSocketAddress originator, Map message ) { if (TRACE ){ System.out.println( "receive:" + originator + "/" + message ); } // if this purely a NAT traversal request then bail out if ( !message.containsKey( "type" )){ return( null ); } int type = ((Long)message.get("type")).intValue(); if ( type == MESSAGE_TYPE_CONNECT ){ String msg_id = new String((byte[])message.get( "msg_id" )); String msg_desc = new String((byte[])message.get( "msg_desc" )); GenericMessageEndpointImpl endpoint = new GenericMessageEndpointImpl( originator ); endpoint.addUDP( originator ); GenericMessageHandler handler = message_manager.getHandler( msg_id ); if ( handler == null ){ Debug.out( "No message handler registered for '" + msg_id + "'" ); return( null ); } try{ Long con_id; synchronized( remote_connections ){ if ( remote_connections.size() >= MAX_REMOTE_CONNECTIONS ){ Debug.out( "Maximum remote connections exceeded - request from " + originator + " denied [" + getRemoteConnectionStatus() + "]" ); return( null ); } int num_from_this_ip = 0; Iterator it = remote_connections.values().iterator(); while( it.hasNext()){ GenericMessageConnectionIndirect con = (GenericMessageConnectionIndirect)it.next(); if ( con.getEndpoint().getNotionalAddress().getAddress().equals( originator.getAddress())){ num_from_this_ip++; } } if ( num_from_this_ip >= MAX_REMOTE_CONNECTIONS_PER_IP ){ Debug.out( "Maximum remote connections per-ip exceeded - request from " + originator + " denied [" + getRemoteConnectionStatus() + "]" ); return( null ); } con_id = new Long( connection_id_next++ ); } GenericMessageConnectionIndirect indirect_connection = new GenericMessageConnectionIndirect( message_manager, msg_id, msg_desc, endpoint, con_id.longValue()); GenericMessageConnectionImpl new_connection = new GenericMessageConnectionImpl( message_manager, indirect_connection ); if ( handler.accept( new_connection )){ new_connection.accepted(); synchronized( remote_connections ){ remote_connections.put( con_id, indirect_connection ); } List replies = indirect_connection.receive((List)message.get( "data" )); Map reply = new HashMap(); reply.put( "type", new Long( MESSAGE_TYPE_CONNECT )); reply.put( "con_id", con_id ); reply.put( "data", replies ); return( reply ); }else{ return( null ); } }catch( MessageException e ){ Debug.out( "Error accepting message", e); return( null ); } }else if ( type == MESSAGE_TYPE_DATA ){ Long con_id = (Long)message.get( "con_id" ); GenericMessageConnectionIndirect indirect_connection; synchronized( remote_connections ){ indirect_connection = (GenericMessageConnectionIndirect)remote_connections.get( con_id ); } if ( indirect_connection == null ){ return( null ); } Map reply = new HashMap(); if ( indirect_connection.isClosed()){ reply.put( "type", new Long( MESSAGE_TYPE_DISCONNECT )); }else{ List replies = indirect_connection.receive((List)message.get( "data" )); reply.put( "type", new Long( MESSAGE_TYPE_DATA )); reply.put( "data", replies ); if ( indirect_connection.receiveIncomplete()){ reply.put( "more_data", new Long(1)); } } return( reply ); }else{ // error or disconnect Long con_id = (Long)message.get( "con_id" ); GenericMessageConnectionIndirect indirect_connection; synchronized( remote_connections ){ indirect_connection = (GenericMessageConnectionIndirect)remote_connections.get( con_id ); } if ( indirect_connection != null ){ try{ indirect_connection.close( new Throwable( "Remote closed connection" ) ); }catch( Throwable e ){ Debug.printStackTrace(e); } } return( null ); } } protected static String getRemoteConnectionStatus() { return( getConnectionStatus( remote_connections )); } protected static String getLocalConnectionStatus() { return( getConnectionStatus( local_connections )); } protected static String getConnectionStatus( Map connections ) { Map totals = new HashMap(); synchronized( connections ){ Iterator it = connections.values().iterator(); while( it.hasNext()){ GenericMessageConnectionIndirect con = (GenericMessageConnectionIndirect)it.next(); InetAddress originator = con.getEndpoint().getNotionalAddress().getAddress(); Integer i = (Integer)totals.get( originator ); if ( i == null ){ i = new Integer(1); }else{ i = new Integer(i.intValue() + 1 ); } totals.put( originator, i ); } } String str = ""; Iterator it = totals.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); str += (str.length()==0?"":",") + entry.getKey() + ":" + entry.getValue(); } return( str ); } private MessageManagerImpl message_manager; private String msg_id; private String msg_desc; private GenericMessageEndpoint endpoint; private NATTraverser nat_traverser; private GenericMessageConnectionImpl owner; private InetSocketAddress rendezvous; private InetSocketAddress target; private long connection_id; private boolean incoming; private boolean closed; private LinkedList send_queue = new LinkedList(); private AESemaphore send_queue_sem = new AESemaphore( "GenericMessageConnectionIndirect:sendq" ); private volatile long last_message_sent; private volatile long last_message_received; private volatile boolean keep_alive_in_progress; protected GenericMessageConnectionIndirect( MessageManagerImpl _message_manager, String _msg_id, String _msg_desc, GenericMessageEndpoint _endpoint, InetSocketAddress _rendezvous, InetSocketAddress _target ) { // outgoing message_manager = _message_manager; msg_id = _msg_id; msg_desc = _msg_desc; endpoint = _endpoint; rendezvous = _rendezvous; target = _target; nat_traverser = message_manager.getNATTraverser(); log( "outgoing connection to " + endpoint.getNotionalAddress()); } protected GenericMessageConnectionIndirect( MessageManagerImpl _message_manager, String _msg_id, String _msg_desc, GenericMessageEndpoint _endpoint, long _connection_id ) { // incoming message_manager = _message_manager; msg_id = _msg_id; msg_desc = _msg_desc; endpoint = _endpoint; connection_id = _connection_id; incoming = true; last_message_received = SystemTime.getCurrentTime(); if ( TRACE ){ trace( "inbound connect from " + endpoint.getNotionalAddress()); } log( "incoming connection from " + endpoint.getNotionalAddress()); } public void setOwner( GenericMessageConnectionImpl _owner ) { owner = _owner; } public int getMaximumMessageSize() { return( MAX_MESSAGE_SIZE ); } public String getType() { return( "Tunnel" ); } public int getTransportType() { return( GenericMessageConnection.TT_INDIRECT ); } public long getLastMessageReceivedTime() { long now = SystemTime.getCurrentTime(); if ( now < last_message_received ){ last_message_received = now; } return( last_message_received ); } public GenericMessageEndpoint getEndpoint() { return( endpoint ); } public void addInboundRateLimiter( RateLimiter limiter ) { // no support for this here } public void removeInboundRateLimiter( RateLimiter limiter ) { // no support for this here } public void addOutboundRateLimiter( RateLimiter limiter ) { // no support for this here } public void removeOutboundRateLimiter( RateLimiter limiter ) { // no support for this here } public void connect( ByteBuffer initial_data, ConnectionListener listener ) { if ( TRACE ){ trace( "outbound connect to " + endpoint.getNotionalAddress()); } try{ Map message = new HashMap(); byte[] initial_data_bytes = new byte[ initial_data.remaining()]; initial_data.get( initial_data_bytes ); List initial_messages = new ArrayList(); initial_messages.add( initial_data_bytes ); message.put( "type", new Long( MESSAGE_TYPE_CONNECT )); message.put( "msg_id", msg_id ); message.put( "msg_desc", msg_desc ); message.put( "data", initial_messages ); Map reply = nat_traverser.sendMessage( message_manager, rendezvous, target, message ); last_message_sent = SystemTime.getCurrentTime(); if ( reply == null || !reply.containsKey( "type") ){ listener.connectFailure( new Throwable( "Indirect connect failed (response=" + reply + ")" )); }else{ int reply_type = ((Long)reply.get( "type" )).intValue(); if ( reply_type == MESSAGE_TYPE_ERROR ){ listener.connectFailure( new Throwable( new String((byte[])reply.get( "error" )))); }else if ( reply_type == MESSAGE_TYPE_DISCONNECT ){ listener.connectFailure( new Throwable( "Disconnected" )); }else if ( reply_type == MESSAGE_TYPE_CONNECT ){ connection_id = ((Long)reply.get( "con_id" )).longValue(); synchronized( local_connections ){ local_connections.put( new Long( connection_id ), this ); } listener.connectSuccess(); List replies = (List)reply.get( "data" ); for (int i=0;i 64 ){ throw( new MessageException( "Send queue limit exceeded" )); } send_queue.add( bytes ); } send_queue_sem.release(); }else{ List messages = new ArrayList(); messages.add( bytes ); send( messages ); } } protected void send( List messages ) { if ( TRACE ){ trace( " send " + messages ); } try{ Map message = new HashMap(); message.put( "con_id", new Long( connection_id )); message.put( "type", new Long( MESSAGE_TYPE_DATA )); message.put( "data", messages ); Map reply = nat_traverser.sendMessage( message_manager, rendezvous, target, message ); last_message_sent = SystemTime.getCurrentTime(); if ( reply == null || !reply.containsKey( "type")){ owner.reportFailed( new Throwable( "Indirect message send failed (response=" + reply + ")" )); }else{ int reply_type = ((Long)reply.get( "type" )).intValue(); if ( reply_type == MESSAGE_TYPE_ERROR ){ owner.reportFailed( new Throwable( new String((byte[])reply.get( "error" )))); }else if ( reply_type == MESSAGE_TYPE_DATA ){ List replies = (List)reply.get( "data" ); for (int i=0;i receive( List messages ) { if ( TRACE ){ trace( "receive: " + messages ); } last_message_received = SystemTime.getCurrentTime(); for (int i=0;i reply = new ArrayList(); // hang around a bit to see if we can piggyback a reply if ( send_queue_sem.reserve( 2500 )){ // give a little more time in case async > 1 message is being queued try{ Thread.sleep(250); }catch( Throwable e ){ } int max = getMaximumMessageSize(); int total = 0; synchronized( send_queue ){ while( send_queue.size() > 0 ){ byte[] data = send_queue.getFirst(); if ( total > 0 && total + data.length > max ){ break; } reply.add( send_queue.removeFirst()); total += data.length; } if ( TRACE ){ trace( " messages returned = " + reply.size() + " (" + total + "), more=" + (send_queue.size() > 0 )); } } if ( reply.size() == 0 ){ // another thread stole our reply, release semaphore we grabbed above that // doesn't have a matching queue removal send_queue_sem.release(); }else{ // grab sems for any entries other than the initial one grabbed above for (int i=1;i 0 ); } } public void close() throws MessageException { close( null ); } protected void close( Throwable close_cause ) throws MessageException { if ( closed ){ return; } if ( TRACE ){ if ( close_cause == null ){ trace( "close[local]" ); }else{ trace( "close[" + close_cause.getMessage() + "]" ); } } log( "connection to " + endpoint.getNotionalAddress() + " closed" + (close_cause==null?"":(" (" + close_cause + ")"))); try{ closed = true; if ( incoming ){ synchronized( remote_connections ){ remote_connections.remove( new Long( connection_id )); } }else{ synchronized( local_connections ){ local_connections.remove( new Long( connection_id )); } Map message = new HashMap(); message.put( "con_id", new Long( connection_id )); message.put( "type", new Long( MESSAGE_TYPE_DISCONNECT )); try{ nat_traverser.sendMessage( message_manager, rendezvous, target, message ); last_message_sent = SystemTime.getCurrentTime(); }catch( Throwable e ){ throw( new MessageException( "Close operation failed", e )); } } }finally{ if ( close_cause != null ){ owner.reportFailed( close_cause ); } } } protected boolean isClosed() { return( closed ); } protected boolean prepareForKeepAlive( boolean force ) { if ( keep_alive_in_progress ){ return( false ); } long now = SystemTime.getCurrentTime(); if ( force || now < last_message_sent || now - last_message_sent > KEEP_ALIVE_MIN ){ keep_alive_in_progress = true; return( true ); } return( false ); } protected void keepAlive() { if (TRACE ){ trace( "keepAlive" ); } try{ send( new ArrayList()); }finally{ keep_alive_in_progress = false; } } protected static void log( String str ) { if ( Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "GenericMessaging (indirect):" + str )); } } protected void trace( String str ) { if ( TRACE ){ System.out.println( "GMCI[" +(incoming?"R":"L") + "/" + connection_id + "] " + str ); } } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessage.java0000644000175000017500000000465410572775040027333 0ustar adrianadrian/* * Created on 19 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.messaging; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; public class GenericMessage implements Message { private DirectByteBuffer buffer = null; private final String id; private final String desc; private final boolean already_encoded; protected GenericMessage( String _id, String _desc, DirectByteBuffer _buffer, boolean _already_encoded ) { id = _id; desc = _desc; buffer = _buffer; already_encoded = _already_encoded; } protected boolean isAlreadyEncoded() { return( already_encoded ); } public String getID() { return( id ); } public byte[] getIDBytes() { return( id.getBytes()); } public String getFeatureID() { return( null ); } public int getFeatureSubID() { return(0); } public int getType() { return( TYPE_DATA_PAYLOAD ); } public String getDescription() { return( desc ); } public byte getVersion() { return( 1 ); } public DirectByteBuffer getPayload() { return( buffer ); } public DirectByteBuffer[] getData() { return new DirectByteBuffer[]{ buffer }; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { throw( new MessageException( "not imp" )); } public void destroy() { buffer.returnToPool(); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/0000755000175000017500000000000011310377634022234 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/0000755000175000017500000000000011310377634023501 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/IntParameterImpl.java0000644000175000017500000000434711011410142027545 0ustar adrianadrian/* * File : GenericParameter.java * Created : Nov 21, 2003 * By : epall * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.config; /** * @author Olivier * */ import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.plugins.ui.config.IntParameter; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; public class IntParameterImpl extends ParameterImpl implements IntParameter { private int defaultValue; private boolean limited; private int min_value; private int max_value; public IntParameterImpl(PluginConfigImpl config,String key, String label, int defaultValue) { super(config,key, label); config.notifyParamExists(getKey()); COConfigurationManager.setIntDefault( getKey(), defaultValue ); this.defaultValue = defaultValue; this.limited = false; } public IntParameterImpl(PluginConfigImpl config,String key, String label, int defaultValue, int min_value, int max_value) { this(config,key, label, defaultValue); this.min_value = min_value; this.max_value = max_value; this.limited = true; } /** * @return Returns the defaultValue. */ public int getDefaultValue() { return defaultValue; } public int getValue() { return( config.getUnsafeIntParameter( getKey(), getDefaultValue())); } public void setValue( int b ) { config.setUnsafeIntParameter( getKey(), b ); } public boolean isLimited() {return limited;} public int getMinValue() {return this.min_value;} public int getMaxValue() {return this.max_value;} } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/FileParameter.java0000644000175000017500000000372611011410142027050 0ustar adrianadrian/* * File : GenericParameter.java * Created : Nov 21, 2003 * By : epall * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.config; /** * @author epall * */ import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; public class FileParameter extends ParameterImpl implements org.gudy.azureus2.plugins.ui.config.FileParameter { private String defaultValue; private String[] file_extensions; public FileParameter(PluginConfigImpl config,String key, String label, String defaultValue) { this(config, key, label, defaultValue, null); } public FileParameter(PluginConfigImpl config,String key, String label, String defaultValue, String[] file_extensions) { super(config, key, label); this.defaultValue = defaultValue; this.file_extensions = file_extensions; config.notifyParamExists(getKey()); COConfigurationManager.setStringDefault(getKey(), getDefaultValue()); } /** * @return Returns the defaultValue. */ public String getDefaultValue() { return defaultValue; } public String getValue() { return( config.getUnsafeStringParameter( getKey(), getDefaultValue())); } public String[] getFileExtensions() { return this.file_extensions; } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/IntsParameter.java0000644000175000017500000000321111011410142027073 0ustar adrianadrian/* * File : GenericParameter.java * Created : Nov 21, 2003 * By : epall * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.config; /** * @author epall * */ import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; public class IntsParameter extends ParameterImpl { private int defaultValue; private int[] values; private String[] labels; public IntsParameter( PluginConfigImpl config, String key, String label, int defaultValue, int[] values, String[] labels) { super(config,key, label); this.defaultValue = defaultValue; this.values = values; this.labels = labels; COConfigurationManager.setIntDefault(getKey(), getDefaultValue()); } public int getDefaultValue() { return defaultValue; } public int[] getValues() { return values; } public String[] getLabels() { return labels; } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterGroupImpl.java0000644000175000017500000000247410373051040030116 0ustar adrianadrian/* * Created on 10-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import org.gudy.azureus2.plugins.ui.config.ParameterGroup; /** * @author parg * */ public class ParameterGroupImpl implements ParameterGroup { private String resource; public ParameterGroupImpl( String _resource ) { resource = _resource; } public String getResourceName() { return( resource ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/PluginConfigUIFactoryImpl.java0000644000175000017500000000611411011410142031316 0ustar adrianadrian/* * File : PluginConfigUIFactoryImpl.java * Created : Nov 21, 2003 * By : epall * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import org.gudy.azureus2.plugins.ui.config.EnablerParameter; import org.gudy.azureus2.plugins.ui.config.Parameter; import org.gudy.azureus2.plugins.ui.config.PluginConfigUIFactory; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; /** * @author epall * */ public class PluginConfigUIFactoryImpl implements PluginConfigUIFactory { String pluginKey; PluginConfigImpl config; public PluginConfigUIFactoryImpl( PluginConfigImpl _config, String _pluginKey) { config = _config; pluginKey = _pluginKey; } public Parameter createIntParameter( String key, String label, int defaultValue, int[] values, String[] labels) { return new IntsParameter(config,pluginKey + "." + key,label,defaultValue,values,labels); } public EnablerParameter createBooleanParameter( String key, String label, boolean defaultValue) { return new BooleanParameterImpl(config,pluginKey + "." + key, label, defaultValue); } public Parameter createIntParameter( String key, String label, int defaultValue) { return new IntParameterImpl(config,pluginKey + "." + key, label, defaultValue); } public Parameter createStringParameter( String key, String label, String defaultValue) { return new StringParameterImpl(config,pluginKey + "." + key, label, defaultValue); } public Parameter createStringParameter( String key, String label, String defaultValue, String[] values, String[] labels) { return new StringListParameterImpl(config,pluginKey + "." + key,label,defaultValue,values,labels); } public Parameter createFileParameter( String key, String label, String defaultValue) { return new FileParameter(config,pluginKey + "." + key, label, defaultValue); } public Parameter createDirectoryParameter( String key, String label, String defaultValue) { return new DirectoryParameterImpl(config,pluginKey + "." + key, label, defaultValue); } public Parameter createColorParameter( String key, String label, int defaultValueRed, int defaultValueGreen, int defaultValueBlue) { return new ColorParameter(config,pluginKey + "." + key,label,defaultValueRed,defaultValueGreen,defaultValueBlue); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/BooleanParameterImpl.java0000644000175000017500000000341111011410142030361 0ustar adrianadrian/* * File : GenericParameter.java * Created : Nov 21, 2003 * By : epall * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; import org.gudy.azureus2.plugins.ui.config.BooleanParameter; /** * @author Olivier * */ public class BooleanParameterImpl extends ParameterImpl implements BooleanParameter { private boolean default_value; public BooleanParameterImpl( PluginConfigImpl config, String key, String label, boolean defaultValue) { super( config, key, label); this.default_value = defaultValue; config.notifyParamExists(getKey()); COConfigurationManager.setBooleanDefault( getKey(), defaultValue ); } public boolean getDefaultValue() { return this.default_value; } public boolean getValue() { return config.getUnsafeBooleanParameter(getKey(), getDefaultValue()); } public void setValue(boolean b) { config.setUnsafeBooleanParameter(getKey(), b); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/StringParameterImpl.java0000644000175000017500000000335611011410142030260 0ustar adrianadrian/* * File : GenericParameter.java * Created : Nov 21, 2003 * By : epall * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; import org.gudy.azureus2.plugins.ui.config.StringParameter; public class StringParameterImpl extends ParameterImpl implements StringParameter { private String defaultValue; public StringParameterImpl(PluginConfigImpl config,String key, String label, String defaultValue) { super(config,key, label); config.notifyParamExists(getKey()); COConfigurationManager.setStringDefault(getKey(), defaultValue); this.defaultValue = defaultValue; } /** * @return Returns the defaultValue. */ public String getDefaultValue() { return defaultValue; } public String getValue() { return( config.getUnsafeStringParameter( getKey(), getDefaultValue())); } public void setValue( String s ) { config.setUnsafeStringParameter(getKey(), s); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/InfoParameterImpl.java0000644000175000017500000000312311135305412027707 0ustar adrianadrian/* * Created on 04-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ui.config; /** * @author parg * */ import org.gudy.azureus2.plugins.ui.config.InfoParameter; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; public class InfoParameterImpl extends ParameterImpl implements InfoParameter { public InfoParameterImpl( PluginConfigImpl config, String key, String label, String value ) { super( config, key, label); setValue( value ); } public String getValue() { return( config.getUnsafeStringParameter( getKey(), "" )); } public void setValue( String s ) { config.setUnsafeStringParameter(getKey(), s); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterImplListener.java0000644000175000017500000000231710373051042030605 0ustar adrianadrian/* * Created on 03-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ui.config; /** * @author parg * */ public interface ParameterImplListener { public void enabledChanged( ParameterImpl parameter ); public void labelChanged(ParameterImpl parameter, String text, boolean bIsKey); } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/ConfigSectionRepository.java0000644000175000017500000000402510323625434031174 0ustar adrianadrian/* * File : ConfigSectionRepository.java * Created : 1 feb. 2004 * By : TuxPaper * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import java.util.ArrayList; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.core3.util.*; public class ConfigSectionRepository { private static ConfigSectionRepository instance; private static AEMonitor class_mon = new AEMonitor( "ConfigSectionRepository:class"); private ArrayList items; private ConfigSectionRepository() { items = new ArrayList(); } public static ConfigSectionRepository getInstance() { try{ class_mon.enter(); if(instance == null) instance = new ConfigSectionRepository(); return instance; }finally{ class_mon.exit(); } } public void addConfigSection(ConfigSection item) { try{ class_mon.enter(); items.add(item); }finally{ class_mon.exit(); } } public void removeConfigSection(ConfigSection item) { try{ class_mon.enter(); items.remove(item); }finally{ class_mon.exit(); } } public ArrayList getList() { try{ class_mon.enter(); return (ArrayList)items.clone(); }finally{ class_mon.exit(); } } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/ColorParameterImpl.java0000644000175000017500000000523111011410142030062 0ustar adrianadrian/* * Created on 23 Oct 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.plugins.ui.config.ColorParameter; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; /** * @author Allan Crooks * */ public class ColorParameterImpl extends ParameterImpl implements ColorParameter { private int r; private int g; private int b; private final int orig_r; private final int orig_g; private final int orig_b; public ColorParameterImpl(PluginConfigImpl config, String key, String label, int _r, int _g, int _b) { super(config, key, label); config.notifyRGBParamExists(getKey()); COConfigurationManager.setIntDefault(getKey() + ".red", r); COConfigurationManager.setIntDefault(getKey() + ".green", g); COConfigurationManager.setIntDefault(getKey() + ".blue", b); COConfigurationManager.setBooleanDefault(getKey() + ".override", false); orig_r = r = _r; orig_g = g = _g; orig_b = b = _b; } public int getRedValue() {return this.r;} public int getGreenValue() {return this.g;} public int getBlueValue() {return this.b;} public void reloadParamDataFromConfig(boolean override) { int[] rgb = config.getUnsafeColorParameter(getKey()); this.r = rgb[0]; this.g = rgb[1]; this.b = rgb[2]; config.setUnsafeBooleanParameter(getKey() + ".override", override); } public void setRGBValue(int r, int g, int b) { this.r = r; this.g = g; this.b = b; config.setUnsafeColorParameter(getKey(), new int[] {r, g, b}, true); } public void resetToDefault() { config.setUnsafeColorParameter(getKey(), new int[] {orig_r, orig_g, orig_b}, false); } public boolean isOverridden() { return config.getUnsafeBooleanParameter(getKey() + ".override"); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/ActionParameterImpl.java0000644000175000017500000000333311012730176030237 0ustar adrianadrian/* * Created on 17-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import org.gudy.azureus2.plugins.ui.config.ActionParameter; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; /** * @author parg * */ public class ActionParameterImpl extends ParameterImpl implements ActionParameter { private String action_resource; private int style = STYLE_BUTTON; public ActionParameterImpl( PluginConfigImpl config, String label_resource_name, String action_resource_name ) { super( config, label_resource_name, label_resource_name); action_resource = action_resource_name; } public String getActionResource() { return( action_resource ); } public void setStyle( int _style ) { style = _style; } public int getStyle() { return( style ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/HyperlinkParameterImpl.java0000644000175000017500000000126411226745146031002 0ustar adrianadrian/** * */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import org.gudy.azureus2.plugins.ui.config.HyperlinkParameter; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; /** * @author Allan Crooks * */ public class HyperlinkParameterImpl extends LabelParameterImpl implements HyperlinkParameter { private String hyperlink; public HyperlinkParameterImpl(PluginConfigImpl config, String key, String label, String hyperlink) { super(config, key, label); this.hyperlink = hyperlink; } public String getHyperlink() { return hyperlink; } public void setHyperlink(String url_location) { this.hyperlink = url_location; fireParameterChanged(); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/DirectoryParameterImpl.java0000644000175000017500000000351611173215444030775 0ustar adrianadrian/* * File : GenericParameter.java * Created : Nov 21, 2003 * By : epall * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.config; /** * @author epall * */ import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.plugins.ui.config.DirectoryParameter; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; public class DirectoryParameterImpl extends ParameterImpl implements DirectoryParameter { private String defaultValue; public DirectoryParameterImpl( PluginConfigImpl config, String key, String label, String defaultValue) { super( config, key, label ); this.defaultValue = defaultValue; config.notifyParamExists(getKey()); COConfigurationManager.setStringDefault(getKey(), getDefaultValue()); } /** * @return Returns the defaultValue. */ public String getDefaultValue() { return defaultValue; } public String getValue() { return( config.getUnsafeStringParameter( getKey(), getDefaultValue())); } public void setValue( String str ) { config.setUnsafeStringParameter( getKey(), str ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/PasswordParameterImpl.java0000644000175000017500000000504511011410142030611 0ustar adrianadrian/* * Created on 10-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ui.config; /** * @author parg * */ import java.security.MessageDigest; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SHA1Hasher; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.plugins.ui.config.PasswordParameter; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; public class PasswordParameterImpl extends ParameterImpl implements PasswordParameter { protected byte[] defaultValue; protected int encoding_type; public PasswordParameterImpl( PluginConfigImpl config, String key, String label, int _encoding_type, byte[] _defaultValue) { super(config,key, label); if ( _defaultValue == null ){ defaultValue = new byte[0]; }else{ defaultValue = _defaultValue; if ( _encoding_type == ET_SHA1 ){ SHA1Hasher hasher = new SHA1Hasher(); defaultValue = hasher.calculateHash(defaultValue); }else if ( _encoding_type == ET_MD5 ){ try{ defaultValue = MessageDigest.getInstance( "md5").digest( defaultValue ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } config.notifyParamExists(getKey()); COConfigurationManager.setByteDefault( getKey(), defaultValue ); encoding_type = _encoding_type; } public byte[] getDefaultValue() { return defaultValue; } public int getEncodingType() { return( encoding_type ); } public byte[] getValue() { return config.getUnsafeByteParameter(getKey(), getDefaultValue()); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/LabelParameterImpl.java0000644000175000017500000000255511011410142030031 0ustar adrianadrian/* * Created on 04-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ui.config; /** * @author parg * */ import org.gudy.azureus2.plugins.ui.config.LabelParameter; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; public class LabelParameterImpl extends ParameterImpl implements LabelParameter { public LabelParameterImpl( PluginConfigImpl config, String key, String label) { super( config, key, label); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterRepository.java0000644000175000017500000000743510123637664030400 0ustar adrianadrian/* * File : ParameterRepository.java * Created : Nov 21, 2003 * By : epall * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import java.util.HashMap; import java.util.Set; import org.gudy.azureus2.plugins.ui.config.*; import org.gudy.azureus2.core3.config.impl.ConfigurationDefaults; import org.gudy.azureus2.core3.util.AEMonitor; /** * @author epall * */ public class ParameterRepository { private static ParameterRepository instance; private static AEMonitor class_mon = new AEMonitor( "ParameterRepository:class" ); private HashMap params; private ParameterRepository() { params = new HashMap(); } public static ParameterRepository getInstance() { try{ class_mon.enter(); if(instance == null) instance = new ParameterRepository(); return instance; }finally{ class_mon.exit(); } } public void addPlugin(Parameter[] parameters, String displayName) { params.put(displayName, parameters); // set the defaults ConfigurationDefaults def = ConfigurationDefaults.getInstance(); if (def == null) return; for (int i = 0; i < parameters.length; i++) { Parameter parameter = parameters[i]; if (!(parameter instanceof ParameterImpl)) continue; String sKey = ((ParameterImpl)parameter).getKey(); if(parameter instanceof StringParameterImpl) { def.addParameter(sKey, ((StringParameterImpl)parameter).getDefaultValue()); } else if(parameter instanceof IntParameterImpl) { def.addParameter(sKey, ((IntParameterImpl)parameter).getDefaultValue()); } else if(parameter instanceof BooleanParameterImpl) { def.addParameter(sKey, ((BooleanParameterImpl)parameter).getDefaultValue()); } else if(parameter instanceof FileParameter) { def.addParameter(sKey, ((FileParameter)parameter).getDefaultValue()); } else if(parameter instanceof DirectoryParameterImpl) { def.addParameter(sKey, ((DirectoryParameterImpl)parameter).getDefaultValue()); } else if(parameter instanceof IntsParameter) { def.addParameter(sKey, ((IntsParameter)parameter).getDefaultValue()); } else if(parameter instanceof StringListParameterImpl) { def.addParameter(sKey, ((StringListParameterImpl)parameter).getDefaultValue()); } else if(parameter instanceof ColorParameter) { def.addParameter(sKey + ".red", ((ColorParameter)parameter).getDefaultRed()); def.addParameter(sKey + ".green", ((ColorParameter)parameter).getDefaultGreen()); def.addParameter(sKey + ".blue", ((ColorParameter)parameter).getDefaultBlue()); } } } public String[] getNames() { Set keys = params.keySet(); return (String[])(keys.toArray(new String[keys.size()])); } public Parameter[] getParameterBlock(String key) { return (Parameter[])params.get(key); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/ColorParameter.java0000644000175000017500000000352111011410142027240 0ustar adrianadrian/* * File : GenericParameter.java * Created : Nov 21, 2003 * By : epall * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; /** * @author Olivier * */ public class ColorParameter extends ParameterImpl { private int defaultRed; private int defaultGreen; private int defaultBlue; public ColorParameter(PluginConfigImpl config,String key, String label, int red,int green,int blue) { super(config,key, label); this.defaultRed = red; this.defaultGreen = green; this.defaultBlue = blue; config.notifyRGBParamExists(getKey()); COConfigurationManager.setIntDefault(getKey() + ".red", getDefaultRed()); COConfigurationManager.setIntDefault(getKey() + ".green", getDefaultGreen()); COConfigurationManager.setIntDefault(getKey() + ".blue", getDefaultBlue()); } public int getDefaultRed() { return defaultRed; } public int getDefaultGreen() { return defaultGreen; } public int getDefaultBlue() { return defaultBlue; } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/UIParameterImpl.java0000644000175000017500000000305011016651770027341 0ustar adrianadrian/* * Created on 25 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import org.gudy.azureus2.plugins.ui.config.UIParameter; import org.gudy.azureus2.plugins.ui.config.UIParameterContext; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; /** * @author Allan Crooks * */ public class UIParameterImpl extends ParameterImpl implements UIParameter { private UIParameterContext context; public UIParameterImpl(PluginConfigImpl _config, UIParameterContext _context, String _key, String _label) { super(_config, _key, _label); this.context = _context; } public UIParameterContext getContext() { return this.context; } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/StringListParameterImpl.java0000644000175000017500000000404611030342712031121 0ustar adrianadrian/* * File : GenericParameter.java * Created : Nov 21, 2003 * By : epall * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; import org.gudy.azureus2.plugins.ui.config.StringListParameter; public class StringListParameterImpl extends ParameterImpl implements StringListParameter { private String defaultValue; private String[] values; private String[] labels; public StringListParameterImpl( PluginConfigImpl config, String key, String label, String defaultValue, String[] values, String[] labels) { super(config,key, label); this.defaultValue = defaultValue; this.values = values; this.labels = labels; config.notifyParamExists(getKey()); COConfigurationManager.setStringDefault(getKey(), defaultValue); } public String getDefaultValue() { return defaultValue; } public String[] getValues() { return values; } public String[] getLabels() { return labels; } public void setLabels( String[] _labels ) { labels = _labels; } public String getValue() { return( config.getUnsafeStringParameter(getKey(), getDefaultValue())); } public void setValue( String s ) { config.setUnsafeStringParameter(getKey(), s); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterImpl.java0000644000175000017500000001440311226745146027113 0ustar adrianadrian/* * File : GenericParameter.java * Created : Nov 21, 2003 * By : epall * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.config; import java.util.*; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.config.*; import org.gudy.azureus2.plugins.ui.config.EnablerParameter; import org.gudy.azureus2.plugins.ui.config.Parameter; import org.gudy.azureus2.plugins.ui.config.ParameterListener; /** * @author epall * */ public class ParameterImpl implements EnablerParameter, org.gudy.azureus2.core3.config.ParameterListener { protected PluginConfigImpl config; private String key; private String labelKey; private String label; private int mode = MODE_BEGINNER; private boolean enabled = true; private boolean visible = true; private boolean generate_intermediate_events = true; private List toDisable = new ArrayList(); private List toEnable = new ArrayList(); private List listeners = new ArrayList(); private List impl_listeners = new ArrayList(); private ParameterGroupImpl parameter_group; public ParameterImpl( PluginConfigImpl _config, String _key, String _label ) { config = _config; key = _key; labelKey = _label; if ("_blank".equals(labelKey)) { labelKey = "!!"; } label = MessageText.getString(labelKey); } /** * @return Returns the key. */ public String getKey() { return key; } public void addDisabledOnSelection(Parameter parameter) { toDisable.add(parameter); } public void addEnabledOnSelection(Parameter parameter) { toEnable.add(parameter); } public List getDisabledOnSelectionParameters() { return toDisable; } public List getEnabledOnSelectionParameters() { return toEnable; } public void parameterChanged( String key ) { fireParameterChanged(); } protected void fireParameterChanged() { // toArray() since listener trigger may remove listeners Object[] listenerArray = listeners.toArray(); for (int i = 0; i < listenerArray.length; i++) { try { Object o = listenerArray[i]; if (o instanceof ParameterListener) { ((ParameterListener) o).parameterChanged(this); } else { ((ConfigParameterListener) o).configParameterChanged(this); } } catch (Throwable f) { Debug.printStackTrace(f); } } } public void setEnabled( boolean e ) { enabled = e; // toArray() since listener trigger may remove listeners Object[] listenersArray = impl_listeners.toArray(); for (int i = 0; i < listenersArray.length; i++) { try { ParameterImplListener l = (ParameterImplListener) listenersArray[i]; l.enabledChanged(this); } catch (Throwable f) { Debug.printStackTrace(f); } } } public boolean isEnabled() { return( enabled ); } public int getMinimumRequiredUserMode() { return( mode ); } public void setMinimumRequiredUserMode( int _mode ) { mode = _mode; } public void setVisible( boolean _visible ) { visible = _visible; } public boolean isVisible() { return( visible ); } public void setGenerateIntermediateEvents( boolean b ) { generate_intermediate_events = b; } public boolean getGenerateIntermediateEvents() { return( generate_intermediate_events ); } public void setGroup( ParameterGroupImpl _group ) { parameter_group = _group; } public ParameterGroupImpl getGroup() { return( parameter_group ); } public void addListener( ParameterListener l ) { listeners.add(l); if ( listeners.size() == 1 ){ COConfigurationManager.addParameterListener( key, this ); } } public void removeListener( ParameterListener l ) { listeners.remove(l); if ( listeners.size() == 0 ){ COConfigurationManager.removeParameterListener( key, this ); } } public void addImplListener( ParameterImplListener l ) { impl_listeners.add(l); } public void removeImplListener( ParameterImplListener l ) { impl_listeners.remove(l); } public void addConfigParameterListener( ConfigParameterListener l ) { listeners.add(l); if ( listeners.size() == 1 ){ COConfigurationManager.addParameterListener( key, this ); } } public void removeConfigParameterListener( ConfigParameterListener l ) { listeners.remove(l); if ( listeners.size() == 0 ){ COConfigurationManager.removeParameterListener( key, this ); } } public String getLabelText() { return label; } public void setLabelText(String sText) { labelKey = null; label = sText; triggerLabelChanged(sText, false); } public String getLabelKey() { return labelKey; } public void setLabelKey(String sLabelKey) { labelKey = sLabelKey; label = MessageText.getString(sLabelKey); triggerLabelChanged(labelKey, true); } private void triggerLabelChanged(String text, boolean isKey) { // toArray() since listener trigger may remove listeners Object[] listenersArray = impl_listeners.toArray(); for (int i = 0; i < listenersArray.length; i++) { try { ParameterImplListener l = (ParameterImplListener) listenersArray[i]; l.labelChanged(this, text, isKey); } catch (Throwable f) { Debug.printStackTrace(f); } } } public void destroy() { listeners.clear(); impl_listeners.clear(); toDisable.clear(); toEnable.clear(); COConfigurationManager.removeParameterListener( key, this ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/UIManagerEventAdapter.java0000644000175000017500000000336711117627364027226 0ustar adrianadrian/* * Created on 10-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ui; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ui.UIManagerEvent; public class UIManagerEventAdapter implements UIManagerEvent { private PluginInterface pi; private int type; private Object data; private Object result; public UIManagerEventAdapter( PluginInterface _pi, int _type, Object _data ) { pi = _pi; type = _type; data = _data; } /** * @return very occasionally this may be NULL */ protected PluginInterface getPluginInterface() { return( pi ); } public int getType() { return( type ); } public Object getData() { return( data ); } public void setResult( Object _result ) { result = _result; } public Object getResult() { return( result ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/model/0000755000175000017500000000000011310377634023334 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginConfigModelImpl.java0000644000175000017500000002146111263475444031341 0ustar adrianadrian/* * Created on 28-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ui.model; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.plugins.ui.config.ActionParameter; import org.gudy.azureus2.plugins.ui.config.InfoParameter; import org.gudy.azureus2.plugins.ui.config.LabelParameter; import org.gudy.azureus2.plugins.ui.config.Parameter; import org.gudy.azureus2.plugins.ui.config.ParameterGroup; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; import org.gudy.azureus2.pluginsimpl.local.ui.UIManagerImpl; import org.gudy.azureus2.pluginsimpl.local.ui.config.*; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.ui.model.*; public class BasicPluginConfigModelImpl implements BasicPluginConfigModel { private UIManagerImpl ui_manager; private String parent_section; private String section; private PluginInterface pi; private ArrayList parameters = new ArrayList(); private String key_prefix; private PluginConfigImpl configobj; public BasicPluginConfigModelImpl( UIManagerImpl _ui_manager, String _parent_section, String _section ) { ui_manager = _ui_manager; parent_section = _parent_section; section = _section; pi = ui_manager.getPluginInterface(); key_prefix = pi.getPluginconfig().getPluginConfigKeyPrefix(); configobj = (PluginConfigImpl)pi.getPluginconfig(); } public String getParentSection() { return( parent_section ); } public String getSection() { return( section ); } public PluginInterface getPluginInterface() { return( pi ); } public Parameter[] getParameters() { Parameter[] res = new Parameter[parameters.size()]; parameters.toArray( res ); return( res ); } public void addBooleanParameter( String key, String resource_name, boolean defaultValue ) { addBooleanParameter2( key, resource_name, defaultValue ); } public org.gudy.azureus2.plugins.ui.config.BooleanParameter addBooleanParameter2( String key, String resource_name, boolean defaultValue ) { BooleanParameterImpl res = new BooleanParameterImpl(configobj, resolveKey(key), resource_name, defaultValue ); parameters.add( res ); return( res ); } public void addStringParameter( String key, String resource_name, String defaultValue ) { addStringParameter2( key, resource_name, defaultValue ); } public org.gudy.azureus2.plugins.ui.config.StringParameter addStringParameter2( String key, String resource_name, String defaultValue ) { StringParameterImpl res = new StringParameterImpl(configobj, resolveKey(key), resource_name, defaultValue ); parameters.add( res ); return( res ); } public org.gudy.azureus2.plugins.ui.config.StringListParameter addStringListParameter2( String key, String resource_name, String[] values, String defaultValue ) { StringListParameterImpl res = new StringListParameterImpl(configobj, resolveKey(key), resource_name, defaultValue, values, values ); parameters.add( res ); return( res ); } public org.gudy.azureus2.plugins.ui.config.StringListParameter addStringListParameter2( String key, String resource_name, String[] values, String[] labels, String defaultValue ) { StringListParameterImpl res = new StringListParameterImpl(configobj, resolveKey(key), resource_name, defaultValue, values, labels); parameters.add(res); return (res); } public org.gudy.azureus2.plugins.ui.config.PasswordParameter addPasswordParameter2( String key, String resource_name, int encoding_type, byte[] defaultValue ) { PasswordParameterImpl res = new PasswordParameterImpl(configobj, resolveKey(key), resource_name, encoding_type, defaultValue ); parameters.add( res ); return( res ); } public org.gudy.azureus2.plugins.ui.config.IntParameter addIntParameter2( String key, String resource_name, int defaultValue ) { IntParameterImpl res = new IntParameterImpl(configobj, resolveKey(key), resource_name, defaultValue ); parameters.add( res ); return( res ); } public org.gudy.azureus2.plugins.ui.config.IntParameter addIntParameter2( String key, String resource_name, int defaultValue, int min_value, int max_value) { IntParameterImpl res = new IntParameterImpl(configobj, resolveKey(key), resource_name, defaultValue, min_value, max_value ); parameters.add( res ); return( res ); } public org.gudy.azureus2.plugins.ui.config.DirectoryParameter addDirectoryParameter2( String key, String resource_name, String defaultValue ) { DirectoryParameterImpl res = new DirectoryParameterImpl(configobj, resolveKey(key), resource_name, defaultValue ); parameters.add( res ); return( res ); } public org.gudy.azureus2.plugins.ui.config.FileParameter addFileParameter2( String key, String resource_name, String defaultValue ) { return addFileParameter2(key, resource_name, defaultValue, null); } public org.gudy.azureus2.plugins.ui.config.FileParameter addFileParameter2( String key, String resource_name, String defaultValue, String[] file_extensions) { FileParameter res = new FileParameter(configobj, resolveKey(key), resource_name, defaultValue, file_extensions); parameters.add(res); return res; } public LabelParameter addLabelParameter2( String resource_name ) { LabelParameterImpl res = new LabelParameterImpl(configobj, key_prefix, resource_name ); parameters.add( res ); return( res ); } public InfoParameter addInfoParameter2( String resource_name, String value ) { InfoParameterImpl res = new InfoParameterImpl(configobj, resolveKey(resource_name), resource_name, value ); parameters.add( res ); return( res ); } public org.gudy.azureus2.plugins.ui.config.HyperlinkParameter addHyperlinkParameter2(String resource_name, String url_location) { HyperlinkParameterImpl res = new HyperlinkParameterImpl(configobj, key_prefix, resource_name, url_location); parameters.add(res); return res; } public org.gudy.azureus2.plugins.ui.config.ColorParameter addColorParameter2(String key, String resource_name, int r, int g, int b) { ColorParameterImpl res = new ColorParameterImpl(configobj, resolveKey(key), resource_name, r, g, b); parameters.add(res); return res; } public org.gudy.azureus2.plugins.ui.config.UIParameter addUIParameter2(org.gudy.azureus2.plugins.ui.config.UIParameterContext context, String resource_name) { UIParameterImpl res = new UIParameterImpl(configobj, context, key_prefix, resource_name); parameters.add(res); return res; } public ActionParameter addActionParameter2( String label_resource_name, String action_resource_name ) { ActionParameterImpl res = new ActionParameterImpl(configobj, label_resource_name, action_resource_name ); parameters.add( res ); return( res ); } public ParameterGroup createGroup( String _resource_name, org.gudy.azureus2.plugins.ui.config.Parameter[] _parameters ) { ParameterGroupImpl pg = new ParameterGroupImpl( _resource_name ); for (int i=0;i<_parameters.length;i++){ ParameterImpl parameter = (ParameterImpl)_parameters[i]; if ( parameter != null ){ parameter.setGroup( pg ); } } return( pg ); } public void destroy() { ui_manager.destroy( this ); for (int i=0;i delay_text = new LinkedList(); int delay_size = 0; FrequencyLimitedDispatcher dispatcher = new FrequencyLimitedDispatcher( new AERunnable() { public void runSupport() { delayAppend(); } }, 500 ); public UITextAreaImpl() { setText(""); } public void setText( String text ) { if ( useFile ){ try{ file_mon.enter(); if ( pw == null ){ pw = new PoopWriter(); pw.print(text); current_file_size = text.length(); return; } }finally{ file_mon.exit(); } } // has property change listener, or error while doing file (fallthrough) if ( text.length() > max_size ){ int size_to_show = max_size - 10000; if ( size_to_show < 0 ){ size_to_show = max_size; } text = text.substring( text.length() - size_to_show ); } setProperty( PT_VALUE, text ); } public void appendText( String text ) { if ( useFile && pw != null ){ try{ file_mon.enter(); // shrink the file occasionally if ( current_file_size > max_file_size ){ current_file_size = getFileText().length(); } pw.print(text); current_file_size += text.length(); return; }finally{ file_mon.exit(); } } synchronized( this ){ delay_text.addLast( text ); delay_size += text.length(); while( delay_size > max_size ){ if ( delay_text.size() == 0 ){ break; } String s = (String)delay_text.removeFirst(); delay_size -= s.length(); } } dispatcher.dispatch(); } protected void delayAppend() { String str = getText(); String text; synchronized( this ){ if ( delay_text.size() == 1 ){ text = (String)delay_text.get(0); }else{ StringBuffer sb = new StringBuffer( delay_size ); Iterator it = delay_text.iterator(); while( it.hasNext()){ sb.append( it.next()); } text = sb.toString(); } delay_text.clear(); delay_size = 0; } if ( str == null ){ setText( text ); }else{ setText( str + text ); } } public String getText() { if ( useFile && pw != null ){ return( getFileText()); } return((String)getProperty( PT_VALUE )); } public void setMaximumSize( int _max_size ) { max_size = _max_size; } private String getFileText() { try{ file_mon.enter(); String text = null; if ( pw != null ){ pw.close(); text = pw.getText(); } if ( text == null ){ text = ""; } pw = null; if ( useFile ){ pw = new PoopWriter(); pw.print(text); current_file_size = text.length(); } return text; }finally{ file_mon.exit(); } } public void addPropertyChangeListener( UIPropertyChangeListener l ) { if ( useFile ){ useFile = false; setText( getFileText()); } super.addPropertyChangeListener(l); } protected class PoopWriter { private StringBuffer buffer = new StringBuffer(256); private PrintWriter pw; public void print( String text ) { if ( pw == null ){ buffer.append( text ); if ( buffer.length() > 8*1024 ){ if ( poop_file == null ){ try{ poop_file = AETemporaryFileHandler.createTempFile(); }catch( Throwable e ){ } } if ( poop_file != null ){ try{ pw = new PrintWriter( poop_file ); pw.print( buffer.toString()); }catch( Throwable e ){ } } buffer.setLength( 0 ); } }else{ pw.print( text ); } } public String getText() { if ( poop_file == null ){ return( buffer.toString()); }else{ try{ return( FileUtil.readFileEndAsString( poop_file, max_size )); }catch( Throwable e ){ return( "" ); } } } public void close() { if ( pw != null ){ pw.close(); pw = null; } } } }azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/components/UIComponentImpl.java0000644000175000017500000000554410373051032030303 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ui.components; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.plugins.ui.components.*; public class UIComponentImpl implements UIComponent { protected Properties properties = new Properties(); protected List listeners = new ArrayList(); protected UIComponentImpl() { properties.put( PT_ENABLED, new Boolean( true )); properties.put( PT_VISIBLE, new Boolean( true )); } public void setEnabled( boolean enabled ) { setProperty( PT_ENABLED, new Boolean( enabled )); } public boolean getEnabled() { return(((Boolean)getProperty( PT_ENABLED )).booleanValue()); } public void setVisible( boolean visible ) { setProperty( PT_VISIBLE, new Boolean( visible )); } public boolean getVisible() { return(((Boolean)getProperty( PT_VISIBLE )).booleanValue()); } public void setProperty( final String property_type, final Object property_value ) { final Object old_value = properties.get( property_type ); properties.put( property_type, property_value ); UIPropertyChangeEvent ev = new UIPropertyChangeEvent() { public UIComponent getSource() { return( UIComponentImpl.this ); } public String getPropertyType() { return( property_type ); } public Object getNewPropertyValue() { return( property_value ); } public Object getOldPropertyValue() { return( old_value ); } }; for (int i=0;i ui_factories = new ArrayList(); protected static List ui_event_history = new ArrayList(); protected static List configModels = new ArrayList(); protected PluginInterface pi; protected PluginConfig plugin_config; protected String key_prefix; protected TableManager table_manager; protected MenuManager menu_manager; public UIManagerImpl( PluginInterface _pi ) { pi =_pi; plugin_config = pi.getPluginconfig(); key_prefix = plugin_config.getPluginConfigKeyPrefix(); table_manager = new TableManagerImpl( this ); menu_manager = new MenuManagerImpl( this ); } public PluginInterface getPluginInterface() { return( pi ); } public BasicPluginViewModel getBasicPluginViewModel( String name ) { // grrr, RSSImport plugin directly uses this method return( createBasicPluginViewModel( name )); // throw( new RuntimeException( "Deprecated method - use createBasicPluginViewModel")); } public PluginView createPluginView( PluginViewModel model ) { try{ return( SWTManagerImpl.getSingleton().createPluginView( model )); }catch( Throwable e ){ e.printStackTrace(); return( null ); } } public BasicPluginViewModel createBasicPluginViewModel( String name ) { final BasicPluginViewModel model = new BasicPluginViewModelImpl( this, name ); fireEvent( pi, UIManagerEvent.ET_PLUGIN_VIEW_MODEL_CREATED, model ); return( model ); } public void destroy( final BasicPluginViewModel model ) { fireEvent( pi, UIManagerEvent.ET_PLUGIN_VIEW_MODEL_DESTROYED, model ); } public BasicPluginConfigModel createBasicPluginConfigModel( String section_name ) { return( createBasicPluginConfigModel( ConfigSection.SECTION_PLUGINS, section_name )); } public BasicPluginConfigModel createBasicPluginConfigModel( String parent_section, String section_name ) { final BasicPluginConfigModel model = new BasicPluginConfigModelImpl( this, parent_section, section_name ); try{ class_mon.enter(); configModels.add(model); }finally{ class_mon.exit(); } fireEvent( pi, UIManagerEvent.ET_PLUGIN_CONFIG_MODEL_CREATED, model ); return( model ); } public void destroy( final BasicPluginConfigModel model ) { try{ class_mon.enter(); configModels.remove(model); }finally{ class_mon.exit(); } fireEvent( pi, UIManagerEvent.ET_PLUGIN_CONFIG_MODEL_DESTROYED, model ); } public PluginConfigModel[] getPluginConfigModels() { try{ class_mon.enter(); return (PluginConfigModel[]) configModels.toArray(new PluginConfigModel[0]); }finally{ class_mon.exit(); } } public void copyToClipBoard( final String data ) throws UIException { boolean ok = fireEvent( pi, UIManagerEvent.ET_COPY_TO_CLIPBOARD, data ); if ( !ok ){ throw( new UIException("Failed to deliver request to UI" )); } } public void openURL( final URL url ) throws UIException { boolean ok = fireEvent( pi, UIManagerEvent.ET_OPEN_URL, url ); if ( !ok ){ throw( new UIException("Failed to deliver request to UI" )); } } public TableManager getTableManager() { return( table_manager ); } public MenuManager getMenuManager() { return menu_manager; } public SWTManager getSWTManager() { PluginDeprecation.call("getSWTManager", pi.getPluginID()); return SWTManagerImpl.getSingleton(); } public static void initialisationComplete() { try{ class_mon.enter(); initialisation_complete = true; for (int j=0;j ev_it = ui_event_history.iterator(); while( ev_it.hasNext()){ UIManagerEventAdapter event = ev_it.next(); if ( event.getPluginInterface() == pi ){ ev_it.remove(); } } }finally{ class_mon.exit(); } } }azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/tables/0000755000175000017500000000000011310377634023506 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/tables/TableContextMenuItemImpl.java0000644000175000017500000000332611232522030031220 0ustar adrianadrian/* * Azureus - a Java Bittorrent client * 2004/May/16 TuxPaper * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ui.tables; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ui.UIManagerEvent; import org.gudy.azureus2.plugins.ui.menus.MenuManager; import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem; import org.gudy.azureus2.pluginsimpl.local.ui.menus.MenuItemImpl; public class TableContextMenuItemImpl extends MenuItemImpl implements TableContextMenuItem { private String sTableID; public TableContextMenuItemImpl(PluginInterface pi, String tableID, String key) { super(pi, MenuManager.MENU_TABLE, key); sTableID = tableID; } public TableContextMenuItemImpl(TableContextMenuItemImpl ti, String key) { super(ti, key); this.sTableID = ti.getTableID(); } public String getTableID() { return sTableID; } public void remove() { removeWithEvents(UIManagerEvent.ET_REMOVE_TABLE_CONTEXT_MENU_ITEM, UIManagerEvent.ET_REMOVE_TABLE_CONTEXT_SUBMENU_ITEM); } }azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/tables/TableManagerImpl.java0000644000175000017500000001147711232522030027510 0ustar adrianadrian/** * Created on 19-Apr-2004 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ui.tables; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.impl.TableColumnImpl; import org.gudy.azureus2.plugins.ui.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.pluginsimpl.local.ui.UIManagerEventAdapter; import org.gudy.azureus2.pluginsimpl.local.ui.UIManagerImpl; /** Manage Tables * * There's a TableManager per plugin interface * * @author TuxPaper * @since 2.0.8.5 */ public class TableManagerImpl implements TableManager { private UIManagerImpl ui_manager; public TableManagerImpl(UIManagerImpl _ui_manager) { ui_manager = _ui_manager; } public TableColumn createColumn(final String tableID, final String cellID) { final TableColumnImpl column = new TableColumnImpl(tableID, cellID); ui_manager.addUIListener(new UIManagerListener() { public void UIDetached(UIInstance instance) { } public void UIAttached(UIInstance instance) { UIManagerEventAdapter event = new UIManagerEventAdapter( ui_manager.getPluginInterface(), UIManagerEvent.ET_CREATE_TABLE_COLUMN, column); UIManagerImpl.fireEvent(event); // event.result used to have the TableColumn which we would populate // with info. } }); return column; } public void registerColumn(final Class forDataSourceType, final String cellID, final TableColumnCreationListener listener) { ui_manager.addUIListener(new UIManagerListener() { public void UIDetached(UIInstance instance) { } public void UIAttached(UIInstance instance) { UIManagerEventAdapter event = new UIManagerEventAdapter( ui_manager.getPluginInterface(), UIManagerEvent.ET_REGISTER_COLUMN, new Object[]{ forDataSourceType, cellID, listener }); UIManagerImpl.fireEvent(event); } }); } public void unregisterColumn(final Class forDataSourceType, final String cellID, final TableColumnCreationListener listener) { ui_manager.addUIListener(new UIManagerListener() { public void UIDetached(UIInstance instance) { } public void UIAttached(UIInstance instance) { UIManagerEventAdapter event = new UIManagerEventAdapter( ui_manager.getPluginInterface(), UIManagerEvent.ET_UNREGISTER_COLUMN, new Object[]{ forDataSourceType, cellID, listener }); UIManagerImpl.fireEvent(event); } }); } public void addColumn(final TableColumn tableColumn) { if (!(tableColumn instanceof TableColumnCore)) throw (new UIRuntimeException( "TableManager.addColumn(..) can only add columns created by createColumn(..)")); ui_manager.addUIListener(new UIManagerListener() { public void UIDetached(UIInstance instance) { } public void UIAttached(UIInstance instance) { UIManagerEventAdapter event = new UIManagerEventAdapter( ui_manager.getPluginInterface(), UIManagerEvent.ET_ADD_TABLE_COLUMN, tableColumn); UIManagerImpl.fireEvent(event); } }); } public TableContextMenuItem addContextMenuItem(TableContextMenuItem parent, String resourceKey) { if (!(parent instanceof TableContextMenuItemImpl)) { throw new UIRuntimeException( "parent must have been created by addContextMenuItem"); } if (parent.getStyle() != TableContextMenuItemImpl.STYLE_MENU) { throw new UIRuntimeException( "parent menu item must have the menu style associated"); } TableContextMenuItemImpl item = new TableContextMenuItemImpl( (TableContextMenuItemImpl) parent, resourceKey); UIManagerImpl.fireEvent(ui_manager.getPluginInterface(), UIManagerEvent.ET_ADD_TABLE_CONTEXT_SUBMENU_ITEM, new Object[] {item, parent}); return item; } public TableContextMenuItem addContextMenuItem(String tableID, String resourceKey) { TableContextMenuItemImpl item = new TableContextMenuItemImpl(ui_manager.getPluginInterface(), tableID, resourceKey); // this event is replayed for us on UI attaches so no extra work UIManagerImpl.fireEvent(ui_manager.getPluginInterface(), UIManagerEvent.ET_ADD_TABLE_CONTEXT_MENU_ITEM, item); return item; } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIInputReceiver.java0000644000175000017500000001306611267524616027620 0ustar adrianadrian/* * Created on 13-Nov-2006 * Created by Allan Crooks * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.pluginsimpl.local.ui; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.plugins.ui.UIInputReceiver; import org.gudy.azureus2.plugins.ui.UIInputReceiverListener; import org.gudy.azureus2.plugins.ui.UIInputValidator; /** * Abstract class to make it easy for class to implement UIInputReceiver classes. * * The common convention is that it has all the necessary set methods needed, and * all settings passed are accessible through protected attributes. * * Checks are made to ensure only certain methods are called at the right time. */ public abstract class AbstractUIInputReceiver implements UIInputReceiver { public AbstractUIInputReceiver() { } private boolean prompted = false; // Helper methods. protected final void assertPrePrompt() { if (prompted) { throw new RuntimeException("cannot invoke after prompt has been called"); } } protected final void assertPostPrompt() { if (!prompted) { throw new RuntimeException("cannot before after prompt has been called"); } } public void setLocalisedMessage(String message) { this.setLocalisedMessages(new String[]{message}); } protected String[] messages = new String[0]; public void setLocalisedMessages(String[] messages) { assertPrePrompt(); this.messages = messages; } protected String title = null; public void setLocalisedTitle(String title) { assertPrePrompt(); this.title = title; } public void setMessage(String message) { this.setLocalisedMessage(this.localise(message)); } public void setMessages(String[] messages) { String[] new_messages = new String[messages.length]; for (int i=0; i 0) { String encoding = torrent.getAdditionalStringProperty("encoding"); torrent.removeAdditionalProperties(); if (encoding != null) torrent.setAdditionalStringProperty("encoding", encoding); } else if (preserve == TorrentManager.PRESERVE_NONE) { torrent.removeAdditionalProperties(); } return torrent; } public void reportProgress( int percent_complete ) { } public void reportCurrentTask( final String task_description ) { for (Iterator it = listeners.iterator();it.hasNext();){ ((TorrentManagerListener)it.next()).event( new TorrentManagerEvent() { public Object getData() { return( task_description ); } }); } } protected void tryToSetTorrentEncoding( TOTorrent torrent, String encoding ) throws TorrentEncodingException { try{ LocaleTorrentUtil.setTorrentEncoding( torrent, encoding ); }catch( LocaleUtilEncodingException e ){ String[] charsets = e.getValidCharsets(); if ( charsets == null ){ throw( new TorrentEncodingException("Failed to set requested encoding", e)); }else{ throw( new TorrentEncodingException(charsets,e.getValidTorrentNames())); } } } protected void tryToSetDefaultTorrentEncoding( TOTorrent torrent ) throws TorrentException { try{ LocaleTorrentUtil.setDefaultTorrentEncoding( torrent ); }catch( LocaleUtilEncodingException e ){ String[] charsets = e.getValidCharsets(); if ( charsets == null ){ throw( new TorrentEncodingException("Failed to set default encoding", e)); }else{ throw( new TorrentEncodingException(charsets,e.getValidTorrentNames())); } } } public void addListener( TorrentManagerListener l ) { try{ class_mon.enter(); ArrayList new_listeners = new ArrayList( listeners ); new_listeners.add( l ); listeners = new_listeners; }finally{ class_mon.exit(); } } public void removeListener( TorrentManagerListener l ) { try{ class_mon.enter(); ArrayList new_listeners = new ArrayList( listeners ); new_listeners.remove( l ); listeners = new_listeners; }finally{ class_mon.exit(); } } }azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentDownloaderImpl.java0000644000175000017500000000717310343557142030464 0ustar adrianadrian/* * File : TorrentDownloaderImpl.java * Created : 28-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.torrent; /** * @author parg * */ import java.net.*; import java.io.*; import org.gudy.azureus2.plugins.torrent.*; import org.gudy.azureus2.plugins.utils.resourcedownloader.*; import org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader.ResourceDownloaderFactoryImpl; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.util.*; public class TorrentDownloaderImpl implements TorrentDownloader { private static final LogIDs LOGID = LogIDs.PLUGIN; protected TorrentManagerImpl manager; protected URL url; protected ResourceDownloader downloader; protected boolean encoding_requested; protected String requested_encoding; protected boolean set_encoding; protected TorrentDownloaderImpl( TorrentManagerImpl _manager, URL _url ) { manager = _manager; url = _url; downloader = ResourceDownloaderFactoryImpl.getSingleton().create( url ); } protected TorrentDownloaderImpl( TorrentManagerImpl _manager, URL _url, String _user_name, String _password ) { manager = _manager; url = _url; // assumption here is that if we have a user name and password supplied // then user-interaction is NOT required. Thus we set the default encoding // to ensure that in the unlikely event of the torrent having multiple // encodings the SWT UI isn't kicked off to get an encoding when the user // is absent. set_encoding = true; downloader = ResourceDownloaderFactoryImpl.getSingleton().create( url, _user_name, _password ); downloader.addListener(new ResourceDownloaderAdapter() { public void reportActivity(ResourceDownloader downloader, String activity) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "TorrentDownloader:" + activity)); } }); } public Torrent download() throws TorrentException { InputStream is = null; try{ is = downloader.download(); TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedInputStream(is); if ( encoding_requested ){ manager.tryToSetTorrentEncoding( torrent, requested_encoding ); }else{ if ( set_encoding ){ manager.tryToSetDefaultTorrentEncoding( torrent ); } } return( new TorrentImpl(torrent )); }catch( TorrentException e ){ throw( e ); }catch( Throwable e ){ throw( new TorrentException( "TorrentDownloader: download fails", e )); }finally{ if ( is != null ){ try{ is.close(); }catch( IOException e ){ Debug.printStackTrace( e ); } } } } public Torrent download( String encoding ) throws TorrentException { encoding_requested = true; requested_encoding = encoding; return( download()); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributePluginImpl.java0000644000175000017500000000252410551551426031503 0ustar adrianadrian/* * Created on 23-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.torrent; /** * @author parg * */ public class TorrentAttributePluginImpl extends BaseTorrentAttributeImpl { private String name; protected TorrentAttributePluginImpl(String _name) { this.name = _name; } public String getName() { return this.name; } public String[] getDefinedValues() { throw new RuntimeException("not supported"); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeDisplayNameImpl.java0000644000175000017500000000224510460603622032446 0ustar adrianadrian/** * Created on 19-Jul-2006 * Created by Allan Crooks * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.torrent; public class TorrentAttributeDisplayNameImpl extends BaseTorrentAttributeImpl { protected TorrentAttributeDisplayNameImpl() {} public String getName() { return TA_DISPLAY_NAME; } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentFileImpl.java0000644000175000017500000000235510043341654027236 0ustar adrianadrian/* * File : TorrentFileImpl.java * Created : 12-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.torrent; /** * @author parg * */ import org.gudy.azureus2.plugins.torrent.*; public class TorrentFileImpl implements TorrentFile { protected String name; protected long size; protected TorrentFileImpl( String _name, long _size ) { name = _name; size = _size; } public String getName() { return( name ); } public long getSize() { return( size ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/torrent/BaseTorrentAttributeImpl.java0000644000175000017500000000455510460603424031120 0ustar adrianadrian/** * Created on 19-Jul-2006 * Created by Allan Crooks * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.torrent; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.torrent.TorrentAttributeEvent; import org.gudy.azureus2.plugins.torrent.TorrentAttributeListener; abstract class BaseTorrentAttributeImpl implements TorrentAttribute { private List listeners; protected BaseTorrentAttributeImpl() { listeners = new ArrayList(); } public abstract String getName(); public String[] getDefinedValues() { return new String[0]; } public void addDefinedValue(String name) { throw new RuntimeException("not supported"); } public void removeDefinedValue(String name) { throw new RuntimeException("not supported"); } public void addTorrentAttributeListener(TorrentAttributeListener l) { this.listeners.add(l); } public void removeTorrentAttributeListener(TorrentAttributeListener l) { this.listeners.remove(l); } protected List getTorrentAttributeListeners() { return this.listeners; } protected void notifyListeners(TorrentAttributeEvent ev) { Iterator itr = this.listeners.iterator(); while (itr.hasNext()) { try { ((TorrentAttributeListener)itr.next()).event(ev); } catch (Throwable t) { // Does it need to be Throwable? Debug.printStackTrace(t); } } } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributePeerSourcesImpl.java0000644000175000017500000000252110460603536032500 0ustar adrianadrian/* * Created on 23-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.torrent; /** * @author parg * */ import org.gudy.azureus2.core3.peer.PEPeerSource; public class TorrentAttributePeerSourcesImpl extends BaseTorrentAttributeImpl { protected TorrentAttributePeerSourcesImpl() {} public String getName() { return TA_PEER_SOURCES; } public String[] getDefinedValues() { return PEPeerSource.PS_SOURCES; } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeUserCommentImpl.java0000644000175000017500000000224510520315076032501 0ustar adrianadrian/** * Created on 26-Oct-2006 * Created by Allan Crooks * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.torrent; public class TorrentAttributeUserCommentImpl extends BaseTorrentAttributeImpl { protected TorrentAttributeUserCommentImpl() {} public String getName() { return TA_USER_COMMENT; } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAnnounceURLListSetImpl.java0000644000175000017500000000306410043341654032016 0ustar adrianadrian/* * File : TOTorrentAnnounceURLSetImpl.java * Created : 03-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.torrent; /** * @author parg * */ import java.net.URL; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.plugins.torrent.*; public class TorrentAnnounceURLListSetImpl implements TorrentAnnounceURLListSet { protected TorrentAnnounceURLListImpl list; protected TOTorrentAnnounceURLSet set; protected TorrentAnnounceURLListSetImpl( TorrentAnnounceURLListImpl _list, TOTorrentAnnounceURLSet _set ) { list = _list; set = _set; } protected TOTorrentAnnounceURLSet getSet() { return( set ); } public URL[] getURLs() { return( set.getAnnounceURLs()); } public void setURLs( URL[] urls ) { set.setAnnounceURLs( urls ); list.updated(); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/PluginManagerDefaultsImpl.java0000644000175000017500000000542510373051006027521 0ustar adrianadrian/* * Created on 13-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.pluginsimpl.local.launch.PluginSingleInstanceHandler; public class PluginManagerDefaultsImpl implements PluginManagerDefaults { protected static PluginManagerDefaultsImpl singleton = new PluginManagerDefaultsImpl(); private PluginManagerArgumentHandler arg_handler; public static PluginManagerDefaults getSingleton() { return( singleton ); } protected List disabled = new ArrayList(); public String[] getDefaultPlugins() { return( PLUGIN_IDS ); } public void setDefaultPluginEnabled( String plugin_id, boolean enabled ) { if ( enabled ){ disabled.remove( plugin_id ); }else if ( !disabled.contains( plugin_id )){ disabled.add( plugin_id ); } } public boolean isDefaultPluginEnabled( String plugin_id ) { return( !disabled.contains( plugin_id)); } public void setApplicationName( String name ) { SystemProperties.setApplicationName( name ); } public String getApplicationName() { return( SystemProperties.getApplicationName()); } public void setApplicationIdentifier( String id ) { SystemProperties.setApplicationIdentifier( id ); } public String getApplicationIdentifier() { return( SystemProperties.getApplicationIdentifier()); } public void setApplicationEntryPoint( String ep ) { SystemProperties.setApplicationEntryPoint( ep ); } public String getApplicationEntryPoint() { return( SystemProperties.getApplicationEntryPoint()); } public void setSingleInstanceHandler( int single_instance_port, PluginManagerArgumentHandler handler ) { PluginSingleInstanceHandler.initialise( single_instance_port, handler ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/FailedPlugin.java0000644000175000017500000000363411027021622025017 0ustar adrianadrian/* * File : FailedPlugin.java * Created : Dec 2, 2005 * By : TuxPaper * * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.pluginsimpl.local; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.UnloadablePlugin; public class FailedPlugin implements UnloadablePlugin { protected String plugin_name; protected String plugin_dir; protected PluginInterfaceImpl plugin_interface; public FailedPlugin() { plugin_name = null; plugin_dir = null; } public FailedPlugin(String _name, String _target_dir) { plugin_name = _name; plugin_dir = _target_dir; } public void initialize(PluginInterface pi) throws PluginException { plugin_interface = (PluginInterfaceImpl) pi; plugin_interface.setPluginVersion("0.0"); if (plugin_name == null) plugin_interface.setPluginName(plugin_interface.getPluginID()); else plugin_interface.setPluginName(plugin_name); if (plugin_dir != null) plugin_interface.setPluginDirectoryName(plugin_dir); } public void unload() { } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ipfilter/0000755000175000017500000000000011310377634023435 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPBlockedImpl.java0000644000175000017500000000304710060700704026707 0ustar adrianadrian/* * File : IPBlocked.java * Created : 05-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ipfilter; /** * @author parg * */ import org.gudy.azureus2.plugins.ipfilter.*; import org.gudy.azureus2.core3.ipfilter.*; public class IPBlockedImpl implements IPBlocked { protected IPFilter filter; protected BlockedIp blocked; protected IPBlockedImpl( IPFilter _filter, BlockedIp _blocked ) { filter = _filter; blocked = _blocked; } public String getBlockedIP() { return( blocked.getBlockedIp()); } public String getBlockedTorrentName() { return(blocked.getTorrentName()); } public long getBlockedTime() { return( blocked.getBlockedTime()); } public IPRange getBlockingRange() { return( new IPRangeImpl( filter, blocked.getBlockingRange())); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPFilterImpl.java0000644000175000017500000001063010560475516026604 0ustar adrianadrian/* * File : IPFilterImpl.java * Created : 02-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.ipfilter; /** * @author parg * */ import java.io.File; import org.gudy.azureus2.plugins.ipfilter.*; import org.gudy.azureus2.core3.ipfilter.*; public class IPFilterImpl implements IPFilter { protected IpFilter filter; public IPFilterImpl() { filter = IpFilterManagerFactory.getSingleton().getIPFilter(); } public File getFile() { return( filter.getFile()); } public void reload() throws IPFilterException { try{ filter.reload(); }catch( Throwable e ){ throw( new IPFilterException( "IPFilter::reload fails", e )); } } public void save() throws IPFilterException { try{ filter.save(); }catch( Throwable e ){ throw( new IPFilterException( "IPFilter::reload fails", e )); } } public IPRange[] getRanges() { IpRange[] l = filter.getRanges(); IPRange[] res = new IPRange[l.length]; for (int i=0;i", false ); } public IPBanned[] getBannedIPs() { BannedIp[] l = filter.getBannedIps(); IPBanned[] res = new IPBanned[l.length]; for (int i=0;i 0 || plugin_interface.getPluginState().isBuiltIn()) { key = _key; } else { throw (new RuntimeException("Can't set Plugin Config Key Prefix to '" + _key + "'")); } } // // // Helper methods which do everything required to get a parameter value. // // private boolean getBooleanParameter(String name, boolean _default, boolean map_name, boolean set_default) { Object obj = getFakeValueWhenDisabled(key,name); if ( obj != null ){ return(((Boolean)obj).booleanValue()); } if (map_name) {name = mapKeyName(name, false);} notifyParamExists(name); if (set_default) {COConfigurationManager.setBooleanDefault(name, _default);} else if (!hasParameter(name)) {return _default;} return COConfigurationManager.getBooleanParameter(name); } private int[] getColorParameter(String name, int[] _default, boolean map_name, boolean set_default) { Object obj = getFakeValueWhenDisabled(key, name); if (obj != null) {return (int[])obj;} if (map_name) {name = mapKeyName(name, false);} int[] result = getColorParameter0(name, _default, set_default); // Result array... if (result == null) {return null;} if (result.length == 3) { int[] result2 = new int[4]; System.arraycopy(result, 0, result2, 0, 3); // Not sure what's the default result to return here for the override flag. // // I've just chosen zero for now. result2[3] = getIntParameter(name, 0, false, false); result = result2; } return result; } private int[] getColorParameter0(String name, int[] _default, boolean set_default) { Object obj = getFakeValueWhenDisabled(key, name); if (obj != null){ return((int[])obj); } notifyRGBParamExists(name); if (set_default) { // No idea what to do with the override flag, and no idea what to do // when the value is null. if (_default != null) { COConfigurationManager.setIntDefault(name + ".red", _default[0]); COConfigurationManager.setIntDefault(name + ".green", _default[1]); COConfigurationManager.setIntDefault(name + ".blue", _default[2]); } else { // I'm not expecting this branch to be executed by any callers. throw new RuntimeException("color parameter default is null"); } } else if (!hasParameter(name + ".red")) {return _default;} return new int[] { COConfigurationManager.getIntParameter(name + ".red"), COConfigurationManager.getIntParameter(name + ".green"), COConfigurationManager.getIntParameter(name + ".blue"), COConfigurationManager.getIntParameter(name + ".override"), }; } private byte[] getByteParameter(String name, byte[] _default, boolean map_name, boolean set_default) { Object obj = getFakeValueWhenDisabled(key,name); if ( obj != null ){ return((byte[])obj); } if (map_name) {name = mapKeyName(name, false);} notifyParamExists(name); if (set_default) {COConfigurationManager.setByteDefault(name, _default);} else if (!hasParameter(name)) {return _default;} return COConfigurationManager.getByteParameter(name); } private float getFloatParameter(String name, float _default, boolean map_name, boolean set_default) { Object obj = getFakeValueWhenDisabled(key,name); if ( obj != null ){ return(((Float)obj).floatValue()); } if (map_name) {name = mapKeyName(name, false);} notifyParamExists(name); if (set_default) {COConfigurationManager.setFloatDefault(name, _default);} else if (!hasParameter(name)) {return _default;} return COConfigurationManager.getFloatParameter(name); } private int getIntParameter(String name, int _default, boolean map_name, boolean set_default) { Object obj = getFakeValueWhenDisabled(key,name); if ( obj != null ){ return(((Long)obj).intValue()); } if (map_name) {name = mapKeyName(name, false);} notifyParamExists(name); if (set_default) {COConfigurationManager.setIntDefault(name, _default);} else if (!hasParameter(name)) {return _default;} return COConfigurationManager.getIntParameter(name); } private long getLongParameter(String name, long _default, boolean map_name, boolean set_default) { Object obj = getFakeValueWhenDisabled(key,name); if ( obj != null ){ return(((Long)obj).longValue()); } if (map_name) {name = mapKeyName(name, false);} notifyParamExists(name); if (set_default) {COConfigurationManager.setLongDefault(name, _default);} else if (!hasParameter(name)) {return _default;} return COConfigurationManager.getLongParameter(name); } private String getStringParameter(String name, String _default, boolean map_name, boolean set_default) { Object obj = getFakeValueWhenDisabled(key,name); if ( obj != null ){ return((String)obj); } if (map_name) {name = mapKeyName(name, false);} notifyParamExists(name); if (set_default) {COConfigurationManager.setStringDefault(name, _default);} else if (!hasParameter(name)) {return _default;} return COConfigurationManager.getStringParameter(name); } // // // Variants of the methods above, but which use the values from ConfigurationDefaults. // // private boolean getDefaultedBooleanParameter(String name, boolean map_name) { Object obj = getFakeValueWhenDisabled(key,name); if ( obj != null ){ return(((Boolean)obj).booleanValue()); } return getBooleanParameter(name, ConfigurationDefaults.def_boolean == 1, map_name, false); } private byte[] getDefaultedByteParameter(String name, boolean map_name) { return getByteParameter(name, ConfigurationDefaults.def_bytes, map_name, false); } private int[] getDefaultedColorParameter(String name, boolean map_name) { int[] default_value = new int[] { ConfigurationDefaults.def_int, ConfigurationDefaults.def_int, ConfigurationDefaults.def_int, 1 }; return getColorParameter(name, default_value, map_name, false); } private float getDefaultedFloatParameter(String name, boolean map_name) { return getFloatParameter(name, ConfigurationDefaults.def_float, map_name, false); } private int getDefaultedIntParameter(String name, boolean map_name) { return getIntParameter(name, ConfigurationDefaults.def_int, map_name, false); } private long getDefaultedLongParameter(String name, boolean map_name) { return getLongParameter(name, ConfigurationDefaults.def_long, map_name, false); } private String getDefaultedStringParameter(String name, boolean map_name) { return getStringParameter(name, ConfigurationDefaults.def_String, map_name, false); } // // // Core get parameter methods (backwardly compatible). // // /** * @deprecated */ public boolean getBooleanParameter(String name) { return getDefaultedBooleanParameter(name, true); } /** * @deprecated */ public boolean getBooleanParameter(String name, boolean default_value) { return getBooleanParameter(name, default_value, true, false); } /** * @deprecated */ public byte[] getByteParameter(String name) { return getDefaultedByteParameter(name, true); } /** * @deprecated */ public byte[] getByteParameter(String name, byte[] default_value) { return getByteParameter(name, default_value, true, false); } /** * @deprecated */ public float getFloatParameter(String name) { return getDefaultedFloatParameter(name, true); } /** * @deprecated */ public float getFloatParameter(String name, float default_value) { return getFloatParameter(name, default_value, true, false); } /** * @deprecated */ public int getIntParameter(String name) { return getDefaultedIntParameter(name, true); } /** * @deprecated */ public int getIntParameter(String name, int default_value) { return getIntParameter(name, default_value, true, false); } /** * @deprecated */ public long getLongParameter(String name) { return getDefaultedLongParameter(name, true); } /** * @deprecated */ public long getLongParameter(String name, long default_value) { return getLongParameter(name, default_value, true, false); } /** * @deprecated */ public String getStringParameter(String name) { return getDefaultedStringParameter(name, true); } /** * @deprecated */ public String getStringParameter(String name, String default_value) { return getStringParameter(name, default_value, true, false); } // // // Core get parameter methods (newly named ones). // // public boolean getCoreBooleanParameter(String name) { checkValidCoreParam(name); return getDefaultedBooleanParameter(name, true); } public boolean getCoreBooleanParameter(String name, boolean default_value) { checkValidCoreParam(name); return getBooleanParameter(name, default_value, true, false); } public byte[] getCoreByteParameter(String name) { checkValidCoreParam(name); return getDefaultedByteParameter(name, true); } public byte[] getCoreByteParameter(String name, byte[] default_value) { checkValidCoreParam(name); return getByteParameter(name, default_value, true, false); } public int[] getCoreColorParameter(String name) { checkValidCoreParam(name); return getDefaultedColorParameter(name, true); } public int[] getCoreColorParameter(String name, int[] default_value) { checkValidCoreParam(name); return getColorParameter(name, default_value, true, false); } public float getCoreFloatParameter(String name) { checkValidCoreParam(name); return getDefaultedFloatParameter(name, true); } public float getCoreFloatParameter(String name, float default_value) { checkValidCoreParam(name); return getFloatParameter(name, default_value, true, false); } public int getCoreIntParameter(String name) { checkValidCoreParam(name); return getDefaultedIntParameter(name, true); } public int getCoreIntParameter(String name, int default_value) { checkValidCoreParam(name); return getIntParameter(name, default_value, true, false); } public long getCoreLongParameter(String name) { checkValidCoreParam(name); return getDefaultedLongParameter(name, true); } public long getCoreLongParameter(String name, long default_value) { checkValidCoreParam(name); return getLongParameter(name, default_value, true, false); } public String getCoreStringParameter(String name) { checkValidCoreParam(name); return getDefaultedStringParameter(name, true); } public String getCoreStringParameter(String name, String default_value) { checkValidCoreParam(name); return getStringParameter(name, default_value, true, false); } // // // Core set parameter methods (backwardly compatible). // // public void setBooleanParameter(String name, boolean value) { if ( setFakeValueWhenDisabled(key, name, new Boolean( value))){ return; } COConfigurationManager.setParameter(mapKeyName(name, true), value); } public void setByteParameter(String name, byte[] value) { if ( setFakeValueWhenDisabled(key, name, value )){ return; } COConfigurationManager.setParameter(mapKeyName(name, true), value); } public void setColorParameter(String name, int[] value) { setColorParameter(name, value, true); } public void setColorParameter(String name, int[] value, boolean override) { if ( setFakeValueWhenDisabled(key, name, value )){ return; } COConfigurationManager.setRGBParameter(mapKeyName(name, true), value, override); } public void setFloatParameter(String name, float value) { if ( setFakeValueWhenDisabled(key, name, new Float( value))){ return; } COConfigurationManager.setParameter(mapKeyName(name, true), value); } public void setIntParameter(String name, int value) { if ( setFakeValueWhenDisabled(key, name, new Long( value))){ return; } COConfigurationManager.setParameter(mapKeyName(name, true), value); } public void setLongParameter(String name, long value) { if ( setFakeValueWhenDisabled(key, name, new Long( value))){ return; } COConfigurationManager.setParameter(mapKeyName(name, true), value); } public void setStringParameter(String name, String value) { if ( setFakeValueWhenDisabled(key, name, value)){ return; } COConfigurationManager.setParameter(mapKeyName(name, true), value); } // // // Core set parameter methods (newly named ones). // // public void setCoreBooleanParameter(String name, boolean value) { checkValidCoreParam(name); if ( setFakeValueWhenDisabled(key, name, new Boolean( value))){ return; } COConfigurationManager.setParameter(mapKeyName(name, true), value); } public void setCoreByteParameter(String name, byte[] value) { checkValidCoreParam(name); if ( setFakeValueWhenDisabled(key, name, value )){ return; } COConfigurationManager.setParameter(mapKeyName(name, true), value); } public void setCoreColorParameter(String name, int[] value) { setCoreColorParameter(name, value, true); } public void setCoreColorParameter(String name, int[] value, boolean override) { checkValidCoreParam(name); if ( setFakeValueWhenDisabled(key, name, value)) { return; } COConfigurationManager.setRGBParameter(mapKeyName(name, true), value, override); } public void setCoreFloatParameter(String name, float value) { checkValidCoreParam(name); if ( setFakeValueWhenDisabled(key, name, new Float( value))){ return; } COConfigurationManager.setParameter(mapKeyName(name, true), value); } public void setCoreIntParameter(String name, int value) { checkValidCoreParam(name); if ( setFakeValueWhenDisabled(key, name, new Long( value))){ return; } COConfigurationManager.setParameter(mapKeyName(name, true), value); } public void setCoreLongParameter(String name, long value) { checkValidCoreParam(name); if ( setFakeValueWhenDisabled(key, name, new Long( value))){ return; } COConfigurationManager.setParameter(mapKeyName(name, true), value); } public void setCoreStringParameter(String name, String value) { checkValidCoreParam(name); if ( setFakeValueWhenDisabled(key, name, value)){ return; } COConfigurationManager.setParameter(mapKeyName(name, true), value); } // // // Plugin get parameter methods. // // public boolean getPluginBooleanParameter(String name) { return getDefaultedBooleanParameter(this.key + name, false); } public boolean getPluginBooleanParameter(String name, boolean default_value) { return getBooleanParameter(this.key + name, default_value, false, true); } public byte[] getPluginByteParameter(String name) { return getDefaultedByteParameter(this.key + name, false); } public byte[] getPluginByteParameter(String name, byte[] default_value) { return getByteParameter(this.key + name, default_value, false, true); } public int[] getPluginColorParameter(String name) { return getDefaultedColorParameter(this.key + name, false); } public int[] getPluginColorParameter(String name, int[] default_value) { return getColorParameter(this.key + name, default_value, false, true); } public float getPluginFloatParameter(String name) { return getDefaultedFloatParameter(this.key + name, false); } public float getPluginFloatParameter(String name, float default_value) { return getFloatParameter(this.key + name, default_value, false, true); } public int getPluginIntParameter(String name) { return getDefaultedIntParameter(this.key + name, false); } public int getPluginIntParameter(String name, int default_value) { return getIntParameter(this.key + name, default_value, false, true); } public long getPluginLongParameter(String name) { return getDefaultedLongParameter(this.key + name, false); } public long getPluginLongParameter(String name, long default_value) { return getLongParameter(this.key + name, default_value, false, true); } public String getPluginStringParameter(String name) { return getDefaultedStringParameter(this.key + name, false); } public String getPluginStringParameter(String name, String default_value) { return getStringParameter(this.key + name, default_value, false, true); } // // // Plugin set parameter methods. // // public void setPluginParameter(String name, boolean value) { notifyParamExists(this.key + name); COConfigurationManager.setParameter(this.key + name, value); } public void setPluginParameter(String name, byte[] value) { notifyParamExists(this.key + name); COConfigurationManager.setParameter(this.key + name, value); } public void setPluginParameter(String name, float value) { notifyParamExists(this.key + name); COConfigurationManager.setParameter(this.key + name, value); } public void setPluginParameter(String name, int value) { notifyParamExists(this.key + name); COConfigurationManager.setParameter(this.key + name, value); } public void setPluginParameter(String name, long value) { notifyParamExists(this.key + name); COConfigurationManager.setParameter(this.key + name, value); } public void setPluginParameter(String name, String value) { notifyParamExists(this.key + name); COConfigurationManager.setParameter(this.key + name, value); } public void setPluginColorParameter(String name, int[] value) { setPluginColorParameter(name, value, true); } public void setPluginColorParameter(String name, int[] value, boolean override) { notifyParamExists(this.key + name); COConfigurationManager.setRGBParameter(this.key + name, value, override); } // // // Core "unsafe" get parameter methods. // // public boolean getUnsafeBooleanParameter(String name) { return getDefaultedBooleanParameter(name, false); } public boolean getUnsafeBooleanParameter(String name, boolean default_value) { return getBooleanParameter(name, default_value, false, false); } public byte[] getUnsafeByteParameter(String name) { return getDefaultedByteParameter(name, false); } public byte[] getUnsafeByteParameter(String name, byte[] default_value) { return getByteParameter(name, default_value, false, false); } public int[] getUnsafeColorParameter(String name) { return getDefaultedColorParameter(name, false); } public int[] getUnsafeColorParameter(String name, int[] default_value) { return getColorParameter(name, default_value, false, false); } public float getUnsafeFloatParameter(String name) { return getDefaultedFloatParameter(name, false); } public float getUnsafeFloatParameter(String name, float default_value) { return getFloatParameter(name, default_value, false, false); } public int getUnsafeIntParameter(String name) { return getDefaultedIntParameter(name, false); } public int getUnsafeIntParameter(String name, int default_value) { return getIntParameter(name, default_value, false, false); } public long getUnsafeLongParameter(String name) { return getDefaultedLongParameter(name, false); } public long getUnsafeLongParameter(String name, long default_value) { return getLongParameter(name, default_value, false, false); } public String getUnsafeStringParameter(String name) { return getDefaultedStringParameter(name, false); } public String getUnsafeStringParameter(String name, String default_value) { return getStringParameter(name, default_value, false, false); } // // // Core "unsafe" set parameter methods. // // public void setUnsafeBooleanParameter(String name, boolean value) { if ( setFakeValueWhenDisabled(key, name, new Boolean( value))){ return; } notifyParamExists(name); COConfigurationManager.setParameter(name, value); } public void setUnsafeByteParameter(String name, byte[] value) { if ( setFakeValueWhenDisabled(key, name, value)){ return; } notifyParamExists(name); COConfigurationManager.setParameter(name, value); } public void setUnsafeColorParameter(String name, int[] value) { setUnsafeColorParameter(name, value, true); } public void setUnsafeColorParameter(String name, int[] value, boolean override) { if ( setFakeValueWhenDisabled(key, name, value)){ return; } notifyRGBParamExists(name); COConfigurationManager.setRGBParameter(name, value, override); } public void setUnsafeFloatParameter(String name, float value) { if ( setFakeValueWhenDisabled(key, name, new Float( value))){ return; } notifyParamExists(name); COConfigurationManager.setParameter(name, value); } public void setUnsafeIntParameter(String name, int value) { if ( setFakeValueWhenDisabled(key, name, new Long( value))){ return; } notifyParamExists(name); COConfigurationManager.setParameter(name, value); } public void setUnsafeLongParameter(String name, long value) { if ( setFakeValueWhenDisabled(key, name, new Long( value))){ return; } notifyParamExists(name); COConfigurationManager.setParameter(name, value); } public void setUnsafeStringParameter(String name, String value) { if ( setFakeValueWhenDisabled(key, name, value )){ return; } notifyParamExists(name); COConfigurationManager.setParameter(name, value); } // // // Get/set plugin list/map methods. // // public String[] getPluginStringListParameter(String key) { notifyParamExists(this.key + key); return COConfigurationManager.getStringListParameter(this.key + key).toArray(); } public void setPluginStringListParameter(String key, String[] value) { notifyParamExists(this.key + key); StringListImpl list_obj = new StringListImpl(Arrays.asList(value)); COConfigurationManager.setParameter(this.key+key, list_obj); } public List getPluginListParameter(String key, List default_value) { notifyParamExists(this.key + key); return COConfigurationManager.getListParameter(this.key+key, default_value); } public void setPluginListParameter(String key, List value) { notifyParamExists(this.key + key); COConfigurationManager.setParameter(this.key+key, value); } public Map getPluginMapParameter(String key, Map default_value) { notifyParamExists(this.key + key); return COConfigurationManager.getMapParameter(this.key+key, default_value); } public void setPluginMapParameter(String key, Map value) { notifyParamExists(this.key + key); COConfigurationManager.setParameter(this.key+key, value); } public void setPluginParameter(String key, int value, boolean global) { notifyParamExists(this.key + key); COConfigurationManager.setParameter(this.key+key, value); if (global) { MagnetURIHandler.getSingleton().addInfo(this.key+key, value); } } public ConfigParameter getParameter( String key ) { return( new ConfigParameterImpl( mapKeyName(key, false))); } public ConfigParameter getPluginParameter( String key ) { return( new ConfigParameterImpl( this.key+key )); } public boolean removePluginParameter(String key) { notifyParamExists(this.key + key); return COConfigurationManager.removeParameter(this.key + key); } public boolean removePluginColorParameter(String key) { notifyParamExists(this.key + key); return COConfigurationManager.removeRGBParameter(this.key + key); } public Map getUnsafeParameterList() { Set params = COConfigurationManager.getAllowedParameters(); Iterator it = params.iterator(); Map result = new HashMap(); while( it.hasNext()){ try{ String name = (String)it.next(); Object val = COConfigurationManager.getParameter( name ); if ( val instanceof String || val instanceof Long ){ }else if ( val instanceof byte[]){ val = new String((byte[])val, "UTF-8" ); }else if ( val instanceof Integer ){ val = new Long(((Integer)val).intValue()); }else if ( val instanceof List ){ val = null; }else if ( val instanceof Map ){ val = null; }else if ( val instanceof Boolean ){ val = new Long(((Boolean)val).booleanValue()?1:0); }else if ( val instanceof Float || val instanceof Double ){ val = val.toString(); } if ( val != null ){ result.put( name, val ); } }catch( Throwable e ){ Debug.printStackTrace(e); } } return( result ); } public void save() { /** * We won't redirect the save method to the external source if there is one * (despite that being the previous behaviour) - the plugin might be setting * core values. */ //if (this.external_source != null) {this.external_source.save(true);} COConfigurationManager.save(); } public File getPluginUserFile( String name ) { String dir = plugin_interface.getUtilities().getAzureusUserDir(); File file = new File( dir, "plugins" ); String p_dir = plugin_interface.getPluginDirectoryName(); if ( p_dir.length() != 0 ){ int lp = p_dir.lastIndexOf(File.separatorChar); if ( lp != -1 ){ p_dir = p_dir.substring(lp+1); } file = new File( file, p_dir ); }else{ String id = plugin_interface.getPluginID(); if ( id.length() > 0 && !id.equals( PluginInitializer.INTERNAL_PLUGIN_ID )){ file = new File( file, id ); }else{ throw( new RuntimeException( "Plugin was not loaded from a directory" )); } } FileUtil.mkdirs(file); return( new File( file, name )); } public void addListener( final PluginConfigListener l ) { COConfigurationManager.addListener( new COConfigurationListener() { public void configurationSaved() { l.configSaved(); } }); } private String mapKeyName(String key, boolean for_set) { String result = (String)external_to_internal_key_map.get(key); if (result == null) { if (for_set) { throw new RuntimeException("No permission to set the value of core parameter: " + key); } else { return key; } } return result; } public boolean hasParameter(String param_name) { // Don't see any reason why a plugin should care whether it is looking // at a system default setting or not, so we'll do an implicit check. return COConfigurationManager.hasParameter(param_name, false); } public boolean hasPluginParameter(String param_name) { // We should not have default settings for plugins in configuration // defaults, so we don't bother doing an implicit check. notifyParamExists(this.key + param_name); return COConfigurationManager.hasParameter(this.key + param_name, true); } public void notifyRGBParamExists(String param) { notifyParamExists(param + ".red"); notifyParamExists(param + ".blue"); notifyParamExists(param + ".green"); notifyParamExists(param + ".override"); } // Not exposed in the plugin API. public void notifyParamExists(String param) { if (allow_key_modification && param.startsWith(this.key)) { allow_key_modification = false; } if (external_source != null && param.startsWith(this.key)) { external_source.registerParameter(param); } } public PluginConfigSource enableExternalConfigSource() { PluginConfigSourceImpl source = new PluginConfigSourceImpl(this, this.plugin_interface.getPluginID()); setPluginConfigSource(source); return source; } public PluginConfigSource getPluginConfigSource() { return this.external_source; } public void setPluginConfigSource(PluginConfigSource source) { if (this.external_source != null) { throw new RuntimeException("external config source already associated!"); } // We need a common key prefix, otherwise this won't work correctly. PluginConfigSourceImpl source_impl = (PluginConfigSourceImpl)source; String used_key = source_impl.getUsedKeyPrefix(); if (used_key != null && !this.getPluginConfigKeyPrefix().startsWith(used_key)) { throw new RuntimeException("cannot use this config source object - incompatible prefix keys: " + used_key + " / " + this.getPluginConfigKeyPrefix()); } this.external_source = (PluginConfigSourceImpl)source; } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/disk/0000755000175000017500000000000011310377634022551 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerImpl.java0000644000175000017500000000242310611343400026407 0ustar adrianadrian/* * File : DiskManagerImpl.java * Created : 22-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.disk; /** * @author parg * */ import org.gudy.azureus2.plugins.disk.*; public class DiskManagerImpl implements DiskManager { private org.gudy.azureus2.core3.disk.DiskManager disk_manager; public DiskManagerImpl( org.gudy.azureus2.core3.disk.DiskManager _disk_manager ) { disk_manager = _disk_manager; } public org.gudy.azureus2.core3.disk.DiskManager getDiskmanager() { return( disk_manager ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerChannelImpl.java0000644000175000017500000004405111156364760027724 0ustar adrianadrian/* * Created on 29-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.disk; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.disk.DiskManagerFileInfoListener; import org.gudy.azureus2.core3.download.DownloadManagerPeerListener; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.Average; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.disk.DiskManagerChannel; import org.gudy.azureus2.plugins.disk.DiskManagerEvent; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.disk.DiskManagerListener; import org.gudy.azureus2.plugins.disk.DiskManagerRequest; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.utils.PooledByteBuffer; import org.gudy.azureus2.pluginsimpl.local.download.DownloadImpl; import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl; import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker; import com.aelitis.azureus.core.peermanager.piecepicker.PieceRTAProvider; import com.aelitis.azureus.core.util.CopyOnWriteList; public class DiskManagerChannelImpl implements DiskManagerChannel, DiskManagerFileInfoListener, DownloadManagerPeerListener, PieceRTAProvider { private static int BUFFER_MILLIS; private static int MIN_PIECES_TO_BUFFER; static{ COConfigurationManager.addAndFireParameterListeners( new String[]{ "filechannel.rt.buffer.millis", "filechannel.rt.buffer.pieces", }, new ParameterListener() { public void parameterChanged( String parameterName ) { BUFFER_MILLIS = COConfigurationManager.getIntParameter( "filechannel.rt.buffer.millis" ); MIN_PIECES_TO_BUFFER = COConfigurationManager.getIntParameter( "filechannel.rt.buffer.pieces" ); } }); } private static final boolean TRACE = false; private static final int COMPACT_DELAY = 32; private static final int MAX_READ_CHUNK_DEFAULT = 64*1024; private static final Comparator comparator = new Comparator() { public int compare( Object _o1, Object _o2) { dataEntry o1 = (dataEntry)_o1; dataEntry o2 = (dataEntry)_o2; long offset1 = o1.getOffset(); long length1 = o1.getLength(); long offset2 = o2.getOffset(); long length2 = o2.getLength(); long res; if ( offset1 == offset2 ){ res = length1 - length2; }else{ res = offset1 - offset2; } if ( res == 0 ){ return(0); }else if ( res < 0 ){ return(-1); }else{ return(1); } } }; private static final String channel_key = "DiskManagerChannel"; private static int channel_id_next; // hack to allow other components to be informed when channels are created private static CopyOnWriteList listeners = new CopyOnWriteList(); public static void addListener( channelCreateListener l ) { listeners.add( l ); } public static void removeListener( channelCreateListener l ) { listeners.remove( l ); } protected static void reportCreated( DiskManagerChannel channel ) { Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((channelCreateListener)it.next()).channelCreated( channel ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } public static interface channelCreateListener { public void channelCreated( DiskManagerChannel channel ); } private DownloadImpl download; private org.gudy.azureus2.pluginsimpl.local.disk.DiskManagerFileInfoImpl plugin_file; private org.gudy.azureus2.core3.disk.DiskManagerFileInfo core_file; private Set data_written = new TreeSet( comparator ); private int compact_delay = COMPACT_DELAY; private List waiters = new ArrayList(); private long file_offset_in_torrent; private long piece_size; private Average byte_rate = Average.getInstance( 1000, 20 ); private long start_position; private long start_time; private long current_position; private request current_request; private long buffer_millis; private PEPeerManager peer_manager; private long[] rtas; private int channel_id; protected DiskManagerChannelImpl( DownloadImpl _download, org.gudy.azureus2.pluginsimpl.local.disk.DiskManagerFileInfoImpl _plugin_file ) { download = _download; plugin_file = _plugin_file; core_file = plugin_file.getCore(); synchronized( DiskManagerChannelImpl.class ){ channel_id = channel_id_next++; } TOTorrentFile tf = core_file.getTorrentFile(); TOTorrent torrent = tf.getTorrent(); TOTorrentFile[] tfs = torrent.getFiles(); rtas = new long[torrent.getNumberOfPieces()]; core_file.getDownloadManager().addPeerListener(this); for (int i=0;i " + prev_e.getString()); } }else{ prev_e = this_e; } } } } for (int i=0;i current_position ){ break; } if ( entry_offset <= current_position && current_position < entry_offset + entry_length ){ last_entry = entry; } }else{ if ( last_entry.getOffset() + last_entry.getLength() == entry.getOffset()){ last_entry = entry; }else{ break; } } } if ( last_entry == null ){ return( 0 ); }else{ return( last_entry.getOffset() + last_entry.getLength() - current_position ); } } } public void run() { long rem = request_length; long pos = request_offset; try{ while( rem > 0 && !cancelled ){ int len = 0; synchronized( data_written ){ current_position = pos; Iterator it = data_written.iterator(); while( it.hasNext()){ dataEntry entry = (dataEntry)it.next(); long entry_offset = entry.getOffset(); if ( entry_offset > pos ){ break; } long entry_length = entry.getLength(); long available = entry_offset + entry_length - pos; if ( available > 0 ){ len = (int)available; break; } } } if ( len > 0 ){ if ( len > rem ){ len = (int)rem; } if ( len > max_read_chunk ){ len = max_read_chunk; } DirectByteBuffer buffer = core_file.read( pos, len ); inform( new event( new PooledByteBufferImpl( buffer ), pos, len )); pos += len; rem -= len; synchronized( data_written ){ byte_rate.addValue( len ); current_position = pos; } }else{ inform( new event( pos )); synchronized( data_written ){ waiters.add( wait_sem ); } try{ wait_sem.reserve(); }finally{ synchronized( data_written ){ waiters.remove( wait_sem ); } } } } }catch( Throwable e ){ inform( e ); } } public void cancel() { cancelled = true; inform( new Throwable( "Request cancelled" )); wait_sem.release(); } protected void inform( Throwable e ) { inform( new event( e )); } protected void inform( event ev ) { for (int i=0;i 0 ){ save_outstanding = true; return; } Map map = new HashMap(); List list = new ArrayList(); map.put("resources", list); ShareResource[] shares = manager.getShares(); for (int i=0;i 0 ){ to_torrent.setComment( comment ); } TorrentUtils.setDHTBackupEnabled( to_torrent, dht_backup_enabled ); TorrentUtils.setPrivate( to_torrent, private_torrent ); if ( TorrentUtils.isDecentralised(to_torrent)){ TorrentUtils.setDecentralised( to_torrent ); } DownloadManagerState download_manager_state = DownloadManagerStateFactory.getDownloadState( to_torrent ); TorrentUtils.setResumeDataCompletelyValid( download_manager_state ); download_manager_state.save(); if ( item == null ){ byte[] fingerprint = getFingerPrint(); item = new ShareItemImpl(this, fingerprint, new TorrentImpl(to_torrent)); }else{ item.setTorrent( new TorrentImpl(to_torrent)); item.writeTorrent(); } }catch( TOTorrentException e ){ if ( e.getReason() == TOTorrentException.RT_CANCELLED ){ throw( new ShareException("ShareResource: Operation cancelled", e)); }else{ throw( new ShareException("ShareResource: Torrent create failed", e)); } }catch( Throwable e ){ throw( new ShareException("ShareResource: Torrent create failed", e)); } } protected void checkConsistency() throws ShareException { try{ if ( Arrays.equals(getFingerPrint(), item.getFingerPrint())){ // check torrent file still exists if ( !manager.torrentExists( item )){ createTorrent(); } }else{ manager.addFileOrDir( null, file, getType()); } }catch( Throwable e ){ manager.delete( this, true ); } } protected static ShareResourceImpl deserialiseResource( ShareManagerImpl manager, Map map, int type ) throws ShareException { try{ File file = new File(new String((byte[])map.get("file"), Constants.DEFAULT_ENCODING )); if ( type == ST_FILE ){ return( new ShareResourceFileImpl( manager, file, map )); }else{ return( new ShareResourceDirImpl( manager, file, map )); } }catch( UnsupportedEncodingException e ){ throw( new ShareException( "internal error", e )); } } protected void serialiseResource( Map map ) { super.serialiseResource( map ); map.put( "type", new Long(getType())); try{ map.put( "file", file.toString().getBytes( Constants.DEFAULT_ENCODING)); }catch( UnsupportedEncodingException e ){ Debug.printStackTrace( e ); } item.serialiseItem( map ); } protected void deleteInternal() { item.delete(); } public String getName() { return( file.toString()); } public File getFile() { return( file ); } public ShareItem getItem() { return( item ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileImpl.java0000644000175000017500000000362710422227432030312 0ustar adrianadrian/* * File : ShareResourceFileImpl.java * Created : 02-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.sharing; /** * @author parg * */ import java.io.File; import java.util.Map; import org.gudy.azureus2.plugins.sharing.*; public class ShareResourceFileImpl extends ShareResourceFileOrDirImpl implements ShareResourceFile { protected static ShareResourceFileImpl getResource( ShareManagerImpl _manager, File _file ) throws ShareException { ShareResourceImpl res = ShareResourceFileOrDirImpl.getResourceSupport( _manager, _file ); if ( res instanceof ShareResourceFileImpl ){ return((ShareResourceFileImpl)res); } return( null ); } protected ShareResourceFileImpl( ShareManagerImpl _manager, ShareResourceDirContentsImpl _parent, File _file ) throws ShareException { super( _manager, _parent, ST_FILE, _file ); } protected ShareResourceFileImpl( ShareManagerImpl _manager, File _file, Map _map) throws ShareException { super( _manager, ST_FILE, _file, _map ); } protected byte[] getFingerPrint() throws ShareException { return( getFingerPrint( getFile())); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceImpl.java0000644000175000017500000002142611275142106027510 0ustar adrianadrian/* * File : ShareResourceImpl.java * Created : 31-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.sharing; /** * @author parg * */ import java.util.*; import java.io.*; import org.gudy.azureus2.plugins.sharing.*; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentManagerImpl; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.internat.*; public abstract class ShareResourceImpl implements ShareResource { protected static BrokenMd5Hasher hasher = new BrokenMd5Hasher(); protected ShareManagerImpl manager; protected int type; protected ShareResourceDirContents parent; protected Map attributes = new HashMap(); protected List change_listeners = new ArrayList(); protected List deletion_listeners = new ArrayList(); // new constructor protected ShareResourceImpl( ShareManagerImpl _manager, int _type ) { manager = _manager; type = _type; } // deserialised constructor protected ShareResourceImpl( ShareManagerImpl _manager, int _type, Map _map ) { manager = _manager; type = _type; Map attrs = (Map)_map.get( "attributes" ); if ( attrs != null ){ Iterator keys = attrs.keySet().iterator(); while( keys.hasNext()){ String key = (String)keys.next(); try{ String value = new String((byte[])attrs.get(key), Constants.DEFAULT_ENCODING ); TorrentAttribute ta = TorrentManagerImpl.getSingleton().getAttribute( key ); if ( ta == null ){ Debug.out( "Invalid attribute '" + key ); }else{ attributes.put( ta, value ); } }catch( Throwable e ){ Debug.printStackTrace(e); } } } } protected void serialiseResource( Map map ) { Iterator it = attributes.keySet().iterator(); Map attrs = new HashMap(); map.put( "attributes", attrs ); while( it.hasNext()){ TorrentAttribute ta = (TorrentAttribute)it.next(); String value = (String)attributes.get(ta); try{ if ( value != null ){ attrs.put( ta.getName(), value.getBytes( Constants.DEFAULT_ENCODING )); } }catch( Throwable e ){ Debug.printStackTrace(e); } } } public ShareResourceDirContents getParent() { return( parent ); } protected void setParent( ShareResourceDirContents _parent ) { parent = _parent; } public ShareResource[] getChildren() { return( new ShareResource[0] ); } public int getType() { return( type ); } public void setAttribute( final TorrentAttribute attribute, String value ) { ShareConfigImpl config = manager.getShareConfig(); try{ config.suspendSaving(); ShareResource[] kids = getChildren(); for (int i=0;i 0 ){ buffer.append( ":" ).append( sub_print ); } } } }else{ throw( new ShareException( "ShareResource::getFingerPrint: '" + file.toString() + "' doesn't exist" )); } }catch( Throwable e ){ if ( e instanceof ShareException ){ throw((ShareException)e); } Debug.printStackTrace( e ); throw( new ShareException( "ShareResource::getFingerPrint: fails", e )); } } protected String getNewTorrentLocation() throws ShareException { return( manager.getNewTorrentLocation()); } protected void writeTorrent( ShareItemImpl item ) throws ShareException { manager.writeTorrent( item ); } protected void readTorrent( ShareItemImpl item ) throws ShareException { manager.readTorrent( item ); } protected void deleteTorrent( ShareItemImpl item ) { manager.deleteTorrent( item ); } public File getTorrentFile( ShareItemImpl item ) { return( manager.getTorrentFile(item)); } protected abstract void checkConsistency() throws ShareException; public void addChangeListener( ShareResourceListener l ) { change_listeners.add( l ); } public void removeChangeListener( ShareResourceListener l ) { change_listeners.remove( l ); } public void addDeletionListener( ShareResourceWillBeDeletedListener l ) { deletion_listeners.add( l ); } public void removeDeletionListener( ShareResourceWillBeDeletedListener l ) { deletion_listeners.remove( l ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/sharing/ShareManagerImpl.java0000644000175000017500000005133711275142106027277 0ustar adrianadrian/* * File : ShareManagerImpl.java * Created : 30-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.sharing; /** * @author parg * */ import java.io.File; import java.io.IOException; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationListener; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.tracker.util.TRTrackerUtils; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.sharing.*; import org.gudy.azureus2.plugins.torrent.*; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl; import com.aelitis.azureus.core.AzureusCoreFactory; public class ShareManagerImpl implements ShareManager, TOTorrentProgressListener, ParameterListener, AEDiagnosticsEvidenceGenerator { private static final LogIDs LOGID = LogIDs.PLUGIN; public static final String TORRENT_STORE = "shares"; public static final String TORRENT_SUBSTORE = "cache"; public static final int MAX_FILES_PER_DIR = 1000; public static final int MAX_DIRS = 1000; protected static ShareManagerImpl singleton; private static AEMonitor class_mon = new AEMonitor( "ShareManager:class" ); protected AEMonitor this_mon = new AEMonitor( "ShareManager" ); protected TOTorrentCreator to_creator; public static ShareManagerImpl getSingleton() throws ShareException { try{ class_mon.enter(); if ( singleton == null ){ singleton = new ShareManagerImpl(); } return( singleton ); }finally{ class_mon.exit(); } } private volatile boolean initialised; private volatile boolean initialising; private File share_dir; private URL[] announce_urls; private ShareConfigImpl config; private Map shares = new HashMap(); private shareScanner current_scanner; private boolean scanning; private List listeners = new ArrayList(); protected ShareManagerImpl() throws ShareException { COConfigurationManager.addListener( new COConfigurationListener() { public void configurationSaved() { announce_urls = null; } }); AEDiagnostics.addEvidenceGenerator( this ); } public void initialise() throws ShareException { try{ this_mon.enter(); if ( !initialised ){ try{ initialising = true; initialised = true; share_dir = FileUtil.getUserFile( TORRENT_STORE ); FileUtil.mkdirs(share_dir); config = new ShareConfigImpl(); try{ config.suspendSaving(); config.loadConfig(this); }finally{ Iterator it = shares.values().iterator(); while(it.hasNext()){ ShareResourceImpl resource = it.next(); if ( resource.getType() == ShareResource.ST_DIR_CONTENTS ){ for (int i=0;i it = new HashSet(shares.values()).iterator(); while(it.hasNext()){ ShareResourceImpl resource = it.next(); try{ resource.checkConsistency(); }catch( ShareException e ){ Debug.printStackTrace(e); } } } protected void deserialiseResource( Map map ) { try{ ShareResourceImpl new_resource = null; int type = ((Long)map.get("type")).intValue(); if ( type == ShareResource.ST_FILE || type == ShareResource.ST_DIR ){ new_resource = ShareResourceFileOrDirImpl.deserialiseResource( this, map, type ); }else{ new_resource = ShareResourceDirContentsImpl.deserialiseResource( this, map ); } if ( new_resource != null ){ ShareResourceImpl old_resource = shares.get(new_resource.getName()); if ( old_resource != null ){ old_resource.delete(true); } shares.put( new_resource.getName(), new_resource ); // we delay the reporting of dir_contents until all recovery is complete so that // the resource reported is initialised correctly if ( type != ShareResource.ST_DIR_CONTENTS ){ for (int i=0;i " + cur + " (" + download + ")"); } public void positionChanged( Download download, int old, int cur) { System.out.println( "statechange:" + old + "-> " + cur + " (" + download + ")"); } }); download.addTrackerListener( new DownloadTrackerListener() { public void scrapeResult( DownloadScrapeResult result ) { System.out.println( "scrapeResult:" + result.getSeedCount() + "/" + result.getNonSeedCount()); } public void announceResult( DownloadAnnounceResult result ) { if ( result.getResponseType() == DownloadAnnounceResult.RT_SUCCESS ){ System.out.println( "announceResult:" + result.getReportedPeerCount() + "/" + result.getSeedCount() + "/" + result.getNonSeedCount()); }else{ System.out.println( "announceResult:" + result.getError()); } } }); download.addPeerListener( new DownloadPeerListener() { public void peerManagerAdded( Download download, PeerManager peer_manager ) { peer_manager.addListener( new PeerManagerListener() { public void peerAdded( PeerManager manager, Peer peer ) { System.out.println( "peerAdded:" + peer.getIp()); } public void peerRemoved( PeerManager manager, Peer peer ) { System.out.println( "peerRemoved:" + peer.getIp()); } }); } public void peerManagerRemoved( Download download, PeerManager peer_manager ) { } }); } public void downloadRemoved( Download download ) { System.out.println("downloadRemoved" + download ); } }); ShareManager sm = plugin_interface.getShareManager(); sm.addListener( this ); sm.initialise(); // ShareResourceFile res = sm.addFile( new File("c:\\temp\\shares\\test.wmf")); // ShareResourceDirContents res = sm.addDirContents( new File("D:\\music\\cd1"), false); //Torrent t = res.getItem().getTorrent(); //System.out.println( t.getHash()); }catch( ShareException e ){ Debug.printStackTrace( e ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } public void closedownInitiated() { } public void closedownComplete() { } public void resourceAdded( ShareResource resource ) { System.out.println( "resource added:" + resource.getName()); if ( resource.getType() == ShareResource.ST_DIR_CONTENTS ){ ShareResourceDirContents c = (ShareResourceDirContents)resource; ShareResource[] kids = c.getChildren(); for (int i=0;i now ){ connection.create_time = now; }else{ int time_allowed = connection.getConnectMethodCount() * CRYPTO_SETUP_TIMEOUT; if ( now - connection.create_time > time_allowed ){ to_close.add( connection ); } } } } for (int i=0;i BLOOM_RECREATE ){ generate_bloom = BloomFilterFactory.createAddRemove4Bit(generate_bloom.getSize()); generate_bloom_create_time = now; } if ( hit_count >= 15 ){ Logger.log( new LogEvent(LOGID, "STS bloom: too many recent connection attempts from " + originator )); Debug.out( "STS: too many recent connection attempts from " + originator ); throw( new IOException( "Too many recent connection attempts (sts)")); } long since_last = now - last_incoming_sts_create; long delay = 100 - since_last; // limit key gen operations to 10 a second if ( delay > 0 && delay < 100 ){ try{ Logger.log( new LogEvent(LOGID, "STS: too many recent connection attempts, delaying " + delay )); Thread.sleep( delay ); }catch( Throwable e ){ } } last_incoming_sts_create = now; } } public GenericMessageEndpoint getEndpoint() { return( connection.getEndpoint()); } public int getMaximumMessageSize() { int max = connection.getMaximumMessageSize(); if ( outgoing_cipher != null ){ max -= outgoing_cipher.getBlockSize(); } return( max ); } public String getType() { String con_type = connection.getType(); if ( con_type.length() == 0 ){ return( "" ); } return( "AES " + con_type ); } public int getTransportType() { return( connection.getTransportType()); } public void addInboundRateLimiter( RateLimiter limiter ) { connection.addInboundRateLimiter( limiter ); } public void removeInboundRateLimiter( RateLimiter limiter ) { connection.removeInboundRateLimiter( limiter ); } public void addOutboundRateLimiter( RateLimiter limiter ) { connection.addOutboundRateLimiter( limiter ); } public void removeOutboundRateLimiter( RateLimiter limiter ) { connection.removeOutboundRateLimiter( limiter ); } public void connect() throws MessageException { if ( connection.isIncoming()){ connection.connect(); }else{ try{ ByteBuffer buffer = ByteBuffer.allocate( 32*1024 ); sts_engine.getKeys( buffer ); buffer.flip(); sent_keys = true; connection.connect( buffer ); }catch( CryptoManagerException e ){ throw( new MessageException( "Failed to get initial keys", e )); } } } protected void setFailed() { failed = true; try{ cryptoComplete(); }catch( Throwable e ){ Debug.printStackTrace( e ); } } public void receive( PooledByteBuffer message ) throws MessageException { try{ boolean forward = false; boolean crypto_completed = false; ByteBuffer out_buffer = null; synchronized( this ){ if ( crypto_complete.isReleasedForever()){ forward = true; }else{ // basic sts flow: // a -> puba -> b // a <- pubb <- b // a -> auta -> b // a <- autb <- b // a -> data -> b // optimised // a -> puba -> b // a <- pubb + auta <- b // a -> autb + data -> b // therefore can be one or two messages in the payload // 1 crypto // 2 crypto (pub + auth) // crypto + data // initial a ->puba -> is done on first data send so data is ready for phase 3 ByteBuffer in_buffer = ByteBuffer.wrap( message.toByteArray()); message.returnToPool(); // piggyback pub key send if ( !sent_keys ){ // we've received // a -> puba -> b // reply with // a <- puba + auta <- b out_buffer = ByteBuffer.allocate( 64*1024 ); // write our keys sts_engine.getKeys( out_buffer ); sent_keys = true; // read their keys sts_engine.putKeys( in_buffer ); // write our auth sts_engine.getAuth( out_buffer ); sent_auth = true; }else if ( !sent_auth ){ out_buffer = ByteBuffer.allocate( 64*1024 ); // we've received // a <- puba + auta <- b // reply with // a -> autb + data -> b // read their keys sts_engine.putKeys( in_buffer ); // write our auth sts_engine.getAuth( out_buffer ); sent_auth = true; // read their auth sts_engine.putAuth( in_buffer ); // check we wanna talk to this person byte[] rem_key = sts_engine.getRemotePublicKey(); if ( !key_locator.accept( SESTSConnectionImpl.this, new SEPublicKeyImpl( my_public_key.getType(), rem_key ))){ throw( new MessageException( "remote public key not accepted" )); } setupBlockCrypto(); if ( pending_message != null ){ byte[] pending_bytes = pending_message.toByteArray(); int pending_size = pending_bytes.length; if ( outgoing_cipher != null ){ pending_size = (( pending_size + AES_KEY_SIZE_BYTES -1 )/AES_KEY_SIZE_BYTES)*AES_KEY_SIZE_BYTES; if ( pending_size == 0 ){ pending_size = AES_KEY_SIZE_BYTES; } } if ( out_buffer.remaining() >= pending_size ){ if ( outgoing_cipher != null ){ out_buffer.put( outgoing_cipher.doFinal( pending_bytes )); }else{ out_buffer.put( pending_bytes ); } // don't deallocate the pending message, the original caller does this pending_message = null; } } crypto_completed = true; }else{ // we've received // a -> autb + data -> b // read their auth sts_engine.putAuth( in_buffer ); // check we wanna talk to this person byte[] rem_key = sts_engine.getRemotePublicKey(); if ( !key_locator.accept( SESTSConnectionImpl.this, new SEPublicKeyImpl( my_public_key.getType(), rem_key ))){ // this is just here to prevent unwanted spew during closedown process connection.closing(); throw( new MessageException( "remote public key not accepted" )); } setupBlockCrypto(); crypto_completed = true; // pick up any remaining data for delivery if ( in_buffer.hasRemaining()){ message = new PooledByteBufferImpl( new DirectByteBuffer( in_buffer.slice())); forward = true; } } } } if ( out_buffer != null ){ out_buffer.flip(); connection.send( new PooledByteBufferImpl( new DirectByteBuffer( out_buffer ))); } if ( crypto_completed ){ cryptoComplete(); } if ( forward ){ receiveContent( message ); } }catch( Throwable e ){ reportFailed( e ); if ( e instanceof MessageException ){ throw((MessageException)e); }else{ throw( new MessageException( "Receive failed", e )); } } } protected void setupBlockCrypto() throws MessageException { if ( !failed ){ if ( block_crypto == SESecurityManager.BLOCK_ENCRYPTION_NONE ){ return; } try{ byte[] shared_secret = sts_engine.getSharedSecret(); SecretKeySpec secret_key_spec1 = new SecretKeySpec(shared_secret, 0, 16, "AES" ); SecretKeySpec secret_key_spec2 = new SecretKeySpec(shared_secret, 8, 16, "AES" ); AlgorithmParameterSpec param_spec1 = new IvParameterSpec( AES_IV1); AlgorithmParameterSpec param_spec2 = new IvParameterSpec( AES_IV2); Cipher cipher1 = Cipher.getInstance( "AES/CBC/PKCS5Padding" ); Cipher cipher2 = Cipher.getInstance( "AES/CBC/PKCS5Padding" ); if ( connection.isIncoming()){ cipher1.init( Cipher.ENCRYPT_MODE, secret_key_spec1, param_spec1 ); cipher2.init( Cipher.DECRYPT_MODE, secret_key_spec2, param_spec2 ); incoming_cipher = cipher2; outgoing_cipher = cipher1; }else{ cipher1.init( Cipher.DECRYPT_MODE, secret_key_spec1, param_spec1 ); cipher2.init( Cipher.ENCRYPT_MODE, secret_key_spec2, param_spec2 ); incoming_cipher = cipher1; outgoing_cipher = cipher2; } }catch( Throwable e ){ throw( new MessageException( "Failed to setup block encryption", e )); } } } protected void cryptoComplete() throws MessageException { crypto_complete.releaseForever(); } public void send( PooledByteBuffer message ) throws MessageException { if ( failed ){ throw( new MessageException( "Connection failed" )); } try{ if ( crypto_complete.isReleasedForever()){ sendContent( message ); }else{ // not complete, stash the message so it has a chance of being piggybacked on // the crypto protocol exchange synchronized( this ){ if ( pending_message == null ){ pending_message = message; } } } crypto_complete.reserve(); // if the pending message couldn't be piggy backed it'll still be allocated boolean send_it = false; synchronized( this ){ if ( pending_message == message ){ pending_message = null; send_it = true; } } if ( send_it ){ sendContent( message ); } }catch( Throwable e ){ setFailed(); if ( e instanceof MessageException ){ throw((MessageException)e); }else{ throw( new MessageException( "Send failed", e )); } } } protected void sendContent( PooledByteBuffer message ) throws MessageException { if ( outgoing_cipher != null ){ try{ byte[] plain = message.toByteArray(); byte[] enc = outgoing_cipher.doFinal( plain ); PooledByteBuffer temp = new PooledByteBufferImpl( enc ); try{ connection.send( temp ); // successfull send -> release caller's buffer message.returnToPool(); }catch( Throwable e ){ // failed semantics are to not release the caller's buffer temp.returnToPool(); throw( e ); } }catch( Throwable e ){ throw( new MessageException( "Failed to encrypt data", e )); } }else{ // sanity check - never allow unencrypted outbound if block enc selected if ( block_crypto != SESecurityManager.BLOCK_ENCRYPTION_NONE ){ connection.close(); throw( new MessageException( "Crypto isn't setup" )); } connection.send( message ); } } protected void receiveContent( PooledByteBuffer message ) throws MessageException { boolean buffer_handled = false; try{ if ( incoming_cipher != null ){ try{ byte[] enc = message.toByteArray(); byte[] plain = incoming_cipher.doFinal( enc ); PooledByteBuffer temp = new PooledByteBufferImpl( plain ); message.returnToPool(); buffer_handled = true; message = temp; }catch( Throwable e ){ throw( new MessageException( "Failed to decrypt data", e )); } }else if ( block_crypto != SESecurityManager.BLOCK_ENCRYPTION_NONE ){ throw( new MessageException( "Crypto isn't setup" )); } List listeners_ref = listeners.getList(); MessageException last_error = null; for (int i=0;i 1 receiver.... message_to_deliver = new PooledByteBufferImpl( message.toByteArray()); } try{ ((GenericMessageConnectionListener)listeners_ref.get(i)).receive( this, message_to_deliver ); if ( message_to_deliver == message ){ buffer_handled = true; } }catch( Throwable e ){ message_to_deliver.returnToPool(); if ( message_to_deliver == message ){ buffer_handled = true; } if ( e instanceof MessageException ){ last_error = (MessageException)e; }else{ last_error = new MessageException( "Failed to process message", e ); } } } if ( last_error != null ){ throw( last_error ); } }finally{ if ( !buffer_handled ){ message.returnToPool(); } } } public void close() throws MessageException { synchronized( connections ){ connections.remove( this ); } connection.close(); } protected void reportConnected() { // we've got to take this off the current thread to avoid the connection even causing immediate // submission of a message which then block this thread awaiting crypto completion. "this" thread // is currently the selector thread which then screws the crypto protocol... new AEThread2( "SESTSConnection:connected", true ) { public void run() { List listeners_ref = listeners.getList(); for (int i=0;i:" + error.getMessage()); } public ResourceDownloaderBaseImpl getClone( ResourceDownloaderBaseImpl parent ) { return( this ); } public InputStream download() throws ResourceDownloaderException { throw( error ); } public void asyncDownload() { } protected void setSize( long size ) { } public void setProperty( String name, Object value ) { setPropertySupport( name, value ); } public long getSize() throws ResourceDownloaderException { throw( error ); } public void cancel() { setCancelled(); } public void reportActivity( String activity ) { informActivity( activity ); } public void addListener( ResourceDownloaderListener l ) { super.addListener(l); informFailed( error ); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderDelayedImpl.javaazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderDelay0000644000175000017500000000673011010003420033353 0ustar adrianadrian/* * Created on 21-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader; /** * @author parg * */ import java.io.*; import org.gudy.azureus2.plugins.utils.resourcedownloader.*; public class ResourceDownloaderDelayedImpl extends ResourceDownloaderBaseImpl { protected ResourceDownloaderDelayedFactory factory; protected ResourceDownloaderBaseImpl delegate; protected long size = -2; protected ResourceDownloaderDelayedImpl( ResourceDownloaderBaseImpl _parent, ResourceDownloaderDelayedFactory _factory ) { super( _parent ); factory = _factory; } protected void getDelegate() { try{ this_mon.enter(); if ( delegate == null ){ try{ delegate = (ResourceDownloaderBaseImpl)factory.create(); delegate.setParent( this ); if ( size >= 0 ){ delegate.setSize( size ); } }catch( ResourceDownloaderException e ){ delegate = new ResourceDownloaderErrorImpl( this, e ); } } }finally{ this_mon.exit(); } } public String getName() { if ( delegate == null ){ return( "<...>" ); } return( delegate.getName()); } public ResourceDownloaderBaseImpl getClone( ResourceDownloaderBaseImpl parent ) { ResourceDownloaderDelayedImpl c = new ResourceDownloaderDelayedImpl( parent, factory ); c.setSize( size ); c.setProperties( this ); return( c ); } public InputStream download() throws ResourceDownloaderException { getDelegate(); return( delegate.download()); } public void asyncDownload() { getDelegate(); delegate.asyncDownload(); } protected void setSize( long _size ) { size = _size; if ( delegate != null && size >= 0){ delegate.setSize( size ); } } public void setProperty( String name, Object value ) throws ResourceDownloaderException { setPropertySupport( name, value ); if ( delegate != null ){ delegate.setProperty( name, value ); } } public long getSize() throws ResourceDownloaderException { getDelegate(); return( delegate.getSize()); } public void cancel() { setCancelled(); getDelegate(); delegate.cancel(); } public void reportActivity( String activity ) { getDelegate(); delegate.reportActivity( activity ); } public void addListener( ResourceDownloaderListener l ) { getDelegate(); delegate.addListener(l); } public void removeListener( ResourceDownloaderListener l ) { getDelegate(); delegate.removeListener(l); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderRetryImpl.javaazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderRetry0000644000175000017500000001124211010003420033414 0ustar adrianadrian/* * Created on 25-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader; /** * @author parg * */ import java.io.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.utils.resourcedownloader.*; public class ResourceDownloaderRetryImpl extends ResourceDownloaderBaseImpl implements ResourceDownloaderListener { protected ResourceDownloaderBaseImpl delegate; protected int retry_count; protected boolean cancelled; protected ResourceDownloader current_downloader; protected int done_count; protected Object result; protected AESemaphore done_sem = new AESemaphore("RDRretry"); protected long size = -2; public ResourceDownloaderRetryImpl( ResourceDownloaderBaseImpl _parent, ResourceDownloader _delegate, int _retry_count ) { super( _parent ); delegate = (ResourceDownloaderBaseImpl)_delegate; delegate.setParent( this ); retry_count = _retry_count; } public String getName() { return( delegate.getName() + ", retry=" + retry_count ); } public long getSize() throws ResourceDownloaderException { if ( size != -2 ){ return( size ); } try{ for (int i=0;i= 0 ){ delegate.setSize( size ); } } public void setProperty( String name, Object value ) throws ResourceDownloaderException { setPropertySupport( name, value ); delegate.setProperty( name, value ); } public ResourceDownloaderBaseImpl getClone( ResourceDownloaderBaseImpl parent ) { ResourceDownloaderRetryImpl c = new ResourceDownloaderRetryImpl( parent, delegate.getClone( this ), retry_count ); c.setSize(size); c.setProperties( this ); return( c ); } public InputStream download() throws ResourceDownloaderException { asyncDownload(); done_sem.reserve(); if ( result instanceof InputStream ){ return((InputStream)result); } throw((ResourceDownloaderException)result); } public void asyncDownload() { try{ this_mon.enter(); if ( done_count == retry_count || cancelled ){ done_sem.release(); informFailed((ResourceDownloaderException)result); }else{ done_count++; if ( done_count > 1 ){ informActivity( getLogIndent() + " attempt " + done_count + " of " + retry_count ); } current_downloader = delegate.getClone( this ); current_downloader.addListener( this ); current_downloader.asyncDownload(); } }finally{ this_mon.exit(); } } public void cancel() { setCancelled(); try{ this_mon.enter(); result = new ResourceDownloaderCancelledException(); cancelled = true; informFailed((ResourceDownloaderException)result ); done_sem.release(); if ( current_downloader != null ){ current_downloader.cancel(); } }finally{ this_mon.exit(); } } public boolean completed( ResourceDownloader downloader, InputStream data ) { if ( informComplete( data )){ result = data; done_sem.release(); return( true ); } return( false ); } public void failed( ResourceDownloader downloader, ResourceDownloaderException e ) { result = e; asyncDownload(); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderFileImpl.javaazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderFileI0000644000175000017500000001177011055176452033336 0ustar adrianadrian/* * Created on 29-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader; import java.io.*; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderCancelledException; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException; import com.aelitis.azureus.core.util.HTTPUtils; /** * @author parg * */ public class ResourceDownloaderFileImpl extends ResourceDownloaderBaseImpl { protected boolean cancelled; protected File file; protected Object result; protected AESemaphore done_sem = new AESemaphore("RDTimeout"); protected long size = -2; public ResourceDownloaderFileImpl( ResourceDownloaderBaseImpl _parent, File _file ) { super( _parent ); file = _file; } public String getName() { return( file.toString()); } protected void setSize( long size ) { } public long getSize() throws ResourceDownloaderException { String file_str = file.toString(); int pos = file_str.lastIndexOf( "." ); String file_type; if ( pos != -1 ){ file_type = file_str.substring(pos+1); }else{ file_type = null; } setProperty( ResourceDownloader.PR_STRING_CONTENT_TYPE, HTTPUtils.guessContentTypeFromFileType( file_type )); return( FileUtil.getFileOrDirectorySize( file )); } public void setProperty( String name, Object value ) { setPropertySupport( name, value ); } public ResourceDownloaderBaseImpl getClone( ResourceDownloaderBaseImpl parent ) { ResourceDownloaderFileImpl c = new ResourceDownloaderFileImpl( getParent(), file ); return( c ); } public InputStream download() throws ResourceDownloaderException { asyncDownload(); done_sem.reserve(); if ( result instanceof ResourceDownloaderException ){ throw((ResourceDownloaderException)result); } return((InputStream)result); } public void asyncDownload() { try{ this_mon.enter(); if ( !cancelled ){ informActivity( getLogIndent() + ( file.isDirectory()?"Processing: ":"Downloading: " ) + getName()); final Object parent_tls = TorrentUtils.getTLS(); AEThread2 t = new AEThread2( "ResourceDownloaderTimeout", true ) { public void run() { Object child_tls = TorrentUtils.getTLS(); TorrentUtils.setTLS( parent_tls ); try{ // download of a local dir -> null inputstream if ( file.isDirectory()){ completed( ResourceDownloaderFileImpl.this, null ); }else{ completed( ResourceDownloaderFileImpl.this, new FileInputStream( file )); } }catch( Throwable e ){ failed( ResourceDownloaderFileImpl.this, new ResourceDownloaderException( "Failed to read file", e )); Debug.printStackTrace( e ); }finally{ TorrentUtils.setTLS( child_tls ); } } }; t.start(); } }finally{ this_mon.exit(); } } public void cancel() { cancel( new ResourceDownloaderCancelledException()); } protected void cancel( ResourceDownloaderException reason ) { setCancelled(); try{ this_mon.enter(); result = reason; cancelled = true; informFailed((ResourceDownloaderException)result ); }finally{ this_mon.exit(); } } public boolean completed( ResourceDownloader downloader, InputStream data ) { if (informComplete( data )){ result = data; done_sem.release(); return( true ); } return( false ); } public void failed( ResourceDownloader downloader, ResourceDownloaderException e ) { result = e; done_sem.release(); informFailed( e ); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderURLImpl.javaazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderURLIm0000644000175000017500000005615611215660666033310 0ustar adrianadrian/* * File : TorrentDownloader2Impl.java * Created : 27-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader; /** * @author parg * */ import com.aelitis.azureus.core.util.Java15Utils; import java.io.*; import java.net.*; import javax.net.ssl.*; import java.net.PasswordAuthentication; import java.util.Iterator; import java.util.Map; import java.util.zip.GZIPInputStream; import java.util.zip.InflaterInputStream; import java.util.zip.ZipException; import org.gudy.azureus2.core3.util.AETemporaryFileHandler; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.AddressUtils; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.security.*; import org.gudy.azureus2.plugins.utils.resourcedownloader.*; import com.aelitis.azureus.core.util.DeleteFileOnCloseInputStream; public class ResourceDownloaderURLImpl extends ResourceDownloaderBaseImpl implements SEPasswordListener { private static final int BUFFER_SIZE = 32768; private static final int MAX_IN_MEM_READ_SIZE = 256*1024; protected URL original_url; protected boolean auth_supplied; protected String user_name; protected String password; protected InputStream input_stream; protected boolean cancel_download = false; protected boolean download_initiated; protected long size = -2; // -1 -> unknown protected boolean force_no_proxy = false; private final String post_data; public ResourceDownloaderURLImpl( ResourceDownloaderBaseImpl _parent, URL _url ) { this( _parent, _url, false, null, null ); } public ResourceDownloaderURLImpl( ResourceDownloaderBaseImpl _parent, URL _url, String _user_name, String _password ) { this( _parent, _url, true, _user_name, _password ); } public ResourceDownloaderURLImpl( ResourceDownloaderBaseImpl _parent, URL _url, boolean _auth_supplied, String _user_name, String _password ) { this(_parent, _url, null, _auth_supplied, _user_name, _password); } /** * * @param _parent * @param _url * @param _data if null, GET will be used, otherwise POST will be used with * the data supplied * @param _auth_supplied * @param _user_name * @param _password */ public ResourceDownloaderURLImpl( ResourceDownloaderBaseImpl _parent, URL _url, String _data, boolean _auth_supplied, String _user_name, String _password ) { super( _parent ); /* if ( _url.getHost().equals( "212.159.18.92")){ try{ _url = new URL(_url.getProtocol() + "://192.168.0.2:" + _url.getPort() + "/" + _url.getPath()); }catch( Throwable e ){ e.printStackTrace(); } } */ original_url = _url; post_data = _data; auth_supplied = _auth_supplied; user_name = _user_name; password = _password; } protected void setForceNoProxy(boolean force_no_proxy) { this.force_no_proxy = force_no_proxy; } protected URL getURL() { return( original_url ); } public String getName() { return( original_url.toString()); } public long getSize() throws ResourceDownloaderException { // only every try getting the size once if ( size == -2 ){ try{ ResourceDownloaderURLImpl c = (ResourceDownloaderURLImpl)getClone( this ); addReportListener( c ); size = c.getSizeSupport(); setProperties( c ); }finally{ if ( size == -2 ){ size = -1; } } } return( size ); } protected void setSize( long l ) { size = l; } public void setProperty( String name, Object value ) throws ResourceDownloaderException { setPropertySupport( name, value ); } protected long getSizeSupport() throws ResourceDownloaderException { // System.out.println("ResourceDownloader:getSize - " + getName()); try{ String protocol = original_url.getProtocol().toLowerCase(); if ( protocol.equals( "magnet" ) || protocol.equals( "dht" )){ return( -1 ); } reportActivity(this, "Getting size of " + original_url ); try{ URL url = new URL( original_url.toString().replaceAll( " ", "%20" )); url = AddressUtils.adjustURL( url ); try{ if ( auth_supplied ){ SESecurityManager.setPasswordHandler( url, this ); } for (int i=0;i<2;i++){ try{ HttpURLConnection con; if ( url.getProtocol().equalsIgnoreCase("https")){ // see ConfigurationChecker for SSL client defaults HttpsURLConnection ssl_con = (HttpsURLConnection)openConnection(url); // allow for certs that contain IP addresses rather than dns names ssl_con.setHostnameVerifier( new HostnameVerifier() { public boolean verify( String host, SSLSession session ) { return( true ); } }); con = ssl_con; }else{ con = (HttpURLConnection)openConnection(url); } con.setRequestMethod( "HEAD" ); con.setRequestProperty("User-Agent", Constants.AZUREUS_NAME + " " + Constants.AZUREUS_VERSION); setRequestProperties( con, false ); con.connect(); int response = con.getResponseCode(); if ((response != HttpURLConnection.HTTP_ACCEPTED) && (response != HttpURLConnection.HTTP_OK)) { setProperty( "URL_HTTP_Response", new Long( response )); throw( new ResourceDownloaderException("Error on connect for '" + trimForDisplay( url ) + "': " + Integer.toString(response) + " " + con.getResponseMessage())); } getRequestProperties( con ); return( UrlUtils.getContentLength( con )); }catch( SSLException e ){ if ( i == 0 ){ if ( SESecurityManager.installServerCertificates( url ) != null ){ // certificate has been installed continue; // retry with new certificate } } throw( e ); }catch( IOException e ){ if ( i == 0 ){ URL retry_url = UrlUtils.getIPV4Fallback( url ); if ( retry_url != null ){ url = retry_url; continue; } } throw( e ); } } throw( new ResourceDownloaderException("Should never get here" )); }finally{ if ( auth_supplied ){ SESecurityManager.setPasswordHandler( url, null ); } } }catch (java.net.MalformedURLException e){ throw( new ResourceDownloaderException("Exception while parsing URL '" + original_url + "':" + e.getMessage(), e)); }catch (java.net.UnknownHostException e){ throw( new ResourceDownloaderException("Exception while initializing download of '" + trimForDisplay( original_url ) + "': Unknown Host '" + e.getMessage() + "'", e)); }catch (java.io.IOException e ){ throw( new ResourceDownloaderException("I/O Exception while downloading '" + trimForDisplay( original_url )+ "'", e )); } }catch( Throwable e ){ ResourceDownloaderException rde; if ( e instanceof ResourceDownloaderException ){ rde = (ResourceDownloaderException)e; }else{ Debug.out(e); rde = new ResourceDownloaderException( "Unexpected error", e ); } throw( rde ); } } public ResourceDownloaderBaseImpl getClone( ResourceDownloaderBaseImpl parent ) { ResourceDownloaderURLImpl c = new ResourceDownloaderURLImpl( parent, original_url, post_data, auth_supplied, user_name, password ); c.setSize( size ); c.setProperties( this ); c.setForceNoProxy(force_no_proxy); return( c ); } public void asyncDownload() { final Object parent_tls = TorrentUtils.getTLS(); AEThread2 t = new AEThread2( "ResourceDownloader:asyncDownload - " + trimForDisplay( original_url ), true ) { public void run() { Object child_tls = TorrentUtils.getTLS(); TorrentUtils.setTLS( parent_tls ); try{ download(); }catch ( ResourceDownloaderException e ){ }finally{ TorrentUtils.setTLS( child_tls ); } } }; t.start(); } public InputStream download() throws ResourceDownloaderException { // System.out.println("ResourceDownloader:download - " + getName()); try{ reportActivity(this, getLogIndent() + "Downloading: " +trimForDisplay( original_url )); try{ this_mon.enter(); if ( download_initiated ){ throw( new ResourceDownloaderException("Download already initiated")); } download_initiated = true; }finally{ this_mon.exit(); } try{ URL url = new URL( original_url.toString().replaceAll( " ", "%20" )); // some authentications screw up without an explicit port number here String protocol = url.getProtocol().toLowerCase(); if ( url.getPort() == -1 && ! ( protocol.equals( "magnet" ) || protocol.equals( "dht" ))){ int target_port; if ( protocol.equals( "http" )){ target_port = 80; }else{ target_port = 443; } try{ String str = original_url.toString().replaceAll( " ", "%20" ); int pos = str.indexOf( "://" ); pos = str.indexOf( "/", pos+4 ); // might not have a trailing "/" if ( pos == -1 ){ url = new URL( str + ":" + target_port + "/" ); }else{ url = new URL( str.substring(0,pos) + ":" + target_port + str.substring(pos)); } }catch( Throwable e ){ Debug.printStackTrace( e ); } } url = AddressUtils.adjustURL( url ); try{ if ( auth_supplied ){ SESecurityManager.setPasswordHandler( url, this ); } boolean use_compression = true; boolean follow_redirect = true; redirect_label: for (int redirect_loop=0;redirect_loop<2&&follow_redirect; redirect_loop++ ){ follow_redirect = false; for (int connect_loop=0;connect_loop<2;connect_loop++){ File temp_file = null; try{ HttpURLConnection con; if ( url.getProtocol().equalsIgnoreCase("https")){ // see ConfigurationChecker for SSL client defaults HttpsURLConnection ssl_con = (HttpsURLConnection)openConnection(url); // allow for certs that contain IP addresses rather than dns names ssl_con.setHostnameVerifier( new HostnameVerifier() { public boolean verify( String host, SSLSession session ) { return( true ); } }); con = ssl_con; }else{ con = (HttpURLConnection)openConnection(url); } con.setRequestProperty("User-Agent", Constants.AZUREUS_NAME + " " + Constants.AZUREUS_VERSION); con.setRequestProperty( "Connection", "close" ); if ( use_compression ){ con.addRequestProperty( "Accept-Encoding", "gzip" ); } setRequestProperties( con, use_compression ); if ( post_data != null ){ con.setDoOutput(true); con.setRequestMethod("POST"); OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream()); wr.write(post_data); wr.flush(); } con.connect(); int response = con.getResponseCode(); if ( response == HttpURLConnection.HTTP_MOVED_TEMP || response == HttpURLConnection.HTTP_MOVED_PERM ){ // auto redirect doesn't work from http to https String move_to = con.getHeaderField( "location" ); if ( move_to != null && url.getProtocol().equalsIgnoreCase( "http" )){ try{ URL move_to_url = new URL( URLDecoder.decode( move_to, "UTF-8" )); if ( move_to_url.getProtocol().equalsIgnoreCase( "https" )){ url = move_to_url; follow_redirect = true; continue redirect_label; } }catch( Throwable e ){ } } } if ( response != HttpURLConnection.HTTP_ACCEPTED && response != HttpURLConnection.HTTP_OK ) { setProperty( "URL_HTTP_Response", new Long( response )); throw( new ResourceDownloaderException("Error on connect for '" + trimForDisplay( url ) + "': " + Integer.toString(response) + " " + con.getResponseMessage())); } getRequestProperties( con ); boolean compressed = false; try{ this_mon.enter(); input_stream = con.getInputStream(); String encoding = con.getHeaderField( "content-encoding"); if ( encoding != null ){ if ( encoding.equalsIgnoreCase( "gzip" )){ compressed = true; input_stream = new GZIPInputStream( input_stream ); }else if ( encoding.equalsIgnoreCase( "deflate" )){ compressed = true; input_stream = new InflaterInputStream( input_stream ); } } }finally{ this_mon.exit(); } ByteArrayOutputStream baos = null; FileOutputStream fos = null; try{ byte[] buf = new byte[BUFFER_SIZE]; long total_read = 0; // unfortunately not all servers set content length /* From Apache's mod_deflate doc: * http://httpd.apache.org/docs/2.0/mod/mod_deflate.html Note on Content-Length If you evaluate the request body yourself, don't trust the Content-Length header! The Content-Length header reflects the length of the incoming data from the client and not the byte count of the decompressed data stream. */ long size = compressed ? -1 : UrlUtils.getContentLength( con ); baos = size>0?new ByteArrayOutputStream(size>MAX_IN_MEM_READ_SIZE?MAX_IN_MEM_READ_SIZE:(int)size):new ByteArrayOutputStream(); while( !cancel_download ){ int read = input_stream.read(buf); if ( read > 0 ){ if ( total_read > MAX_IN_MEM_READ_SIZE ){ if ( fos == null ){ temp_file = AETemporaryFileHandler.createTempFile(); fos = new FileOutputStream( temp_file ); fos.write( baos.toByteArray()); baos = null; } fos.write( buf, 0, read ); }else{ baos.write(buf, 0, read); } total_read += read; informAmountComplete( total_read ); if ( size > 0){ informPercentDone((int)(( 100 * total_read ) / size )); } }else{ break; } } // if we've got a size, make sure we've read all of it if ( size > 0 && total_read != size ){ if ( total_read > size ){ // this has been seen with UPnP linksys - more data is read than // the content-length has us believe is coming (1 byte in fact...) Debug.outNoStack( "Inconsistent stream length for '" + trimForDisplay( original_url ) + "': expected = " + size + ", actual = " + total_read ); }else{ throw( new IOException( "Premature end of stream" )); } } }finally{ if ( fos != null ){ fos.close(); } input_stream.close(); } InputStream res; if ( temp_file != null ){ res = new DeleteFileOnCloseInputStream( temp_file ); temp_file = null; }else{ res = new ByteArrayInputStream( baos.toByteArray()); } boolean handed_over = false; try{ if ( informComplete( res )){ handed_over = true; return( res ); } }finally{ if ( !handed_over ){ res.close(); } } throw( new ResourceDownloaderException("Contents downloaded but rejected: '" + trimForDisplay( original_url ) + "'" )); }catch( SSLException e ){ if ( connect_loop == 0 ){ if ( SESecurityManager.installServerCertificates( url ) != null ){ // certificate has been installed continue; // retry with new certificate } } throw( e ); }catch( ZipException e ){ if ( connect_loop == 0 ){ use_compression = false; continue; } }catch( IOException e ){ if ( connect_loop == 0 ){ String msg = e.getMessage(); if ( msg != null ){ msg = msg.toLowerCase( MessageText.LOCALE_ENGLISH ); if ( msg.indexOf( "gzip" ) != -1 ){ use_compression = false; continue; } } URL retry_url = UrlUtils.getIPV4Fallback( url ); if ( retry_url != null ){ url = retry_url; continue; } } throw( e ); }finally{ if ( temp_file != null ){ temp_file.delete(); } } } } throw( new ResourceDownloaderException("Should never get here" )); }finally{ if ( auth_supplied ){ SESecurityManager.setPasswordHandler( url, null ); } } }catch (java.net.MalformedURLException e){ throw( new ResourceDownloaderException("Exception while parsing URL '" + trimForDisplay( original_url ) + "':" + e.getMessage(), e)); }catch (java.net.UnknownHostException e){ throw( new ResourceDownloaderException("Exception while initializing download of '" + trimForDisplay( original_url ) + "': Unknown Host '" + e.getMessage() + "'", e)); }catch (java.io.IOException e ){ throw( new ResourceDownloaderException("I/O Exception while downloading '" + trimForDisplay( original_url ) + "'", e )); } }catch( Throwable e ){ ResourceDownloaderException rde; if ( e instanceof ResourceDownloaderException ){ rde = (ResourceDownloaderException)e; }else{ Debug.out(e); rde = new ResourceDownloaderException( "Unexpected error", e ); } informFailed(rde); throw( rde ); } } public void cancel() { setCancelled(); cancel_download = true; try{ this_mon.enter(); if ( input_stream != null ){ try{ input_stream.close(); }catch( Throwable e ){ } } }finally{ this_mon.exit(); } informFailed( new ResourceDownloaderCancelledException()); } protected void setRequestProperties( HttpURLConnection con, boolean use_compression ) { Map properties = getLCKeyProperties(); Iterator it = properties.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); String key = (String)entry.getKey(); Object value = entry.getValue(); if ( key.startsWith( "url_" ) && value instanceof String ){ key = key.substring(4); if ( key.equals( "accept-encoding" ) && !use_compression ){ //skip }else{ con.setRequestProperty(key,(String)value); } } } } protected void getRequestProperties( HttpURLConnection con ) { try{ setProperty( ResourceDownloader.PR_STRING_CONTENT_TYPE, con.getContentType() ); setProperty( "URL_URL", con.getURL()); Map headers = con.getHeaderFields(); Iterator it = headers.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); String key = (String)entry.getKey(); Object val = entry.getValue(); if ( key != null ){ setProperty( "URL_" + key, val ); } } setPropertiesSet(); }catch( Throwable e ){ Debug.printStackTrace(e); } } public PasswordAuthentication getAuthentication( String realm, URL tracker ) { if ( user_name == null || password == null ){ String user_info = tracker.getUserInfo(); if ( user_info == null ){ return( null ); } String user_bit = user_info; String pw_bit = ""; int pos = user_info.indexOf(':'); if ( pos != -1 ){ user_bit = user_info.substring(0,pos); pw_bit = user_info.substring(pos+1); } return( new PasswordAuthentication( user_bit, pw_bit.toCharArray())); } return( new PasswordAuthentication( user_name, password.toCharArray())); } public void setAuthenticationOutcome( String realm, URL tracker, boolean success ) { } public void clearPasswords() { } private URLConnection openConnection(URL url) throws IOException { if (this.force_no_proxy) {return Java15Utils.openConnectionForceNoProxy(url);} else {return url.openConnection();} } protected String trimForDisplay( URL url ) { String str = url.toString(); int pos = str.indexOf( '?' ); if ( pos != -1 ){ str = str.substring( 0, pos ); } return( str ); } }././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderFactoryImpl.javaazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderFacto0000644000175000017500000001505111027644322033371 0ustar adrianadrian/* * Created on 03-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader; /** * @author parg * */ import java.io.File; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.util.*; import org.gudy.azureus2.plugins.utils.resourcedownloader.*; import org.gudy.azureus2.core3.logging.*; public class ResourceDownloaderFactoryImpl implements ResourceDownloaderFactory { private static final LogIDs LOGID = LogIDs.CORE; protected static ResourceDownloaderFactoryImpl singleton = new ResourceDownloaderFactoryImpl(); // A list of SourceForge mirrors. private static final String[] SF_MIRRORS = new String[] { "jaist", "nchc", "keihanna", "optusnet", "peterhost", "ovh", "puzzle", "switch", "mesh", "kent", "surfnet", "heanet", "citkit", "internap", "cogent", "umn", "easynews", "ufpr" }; public static ResourceDownloaderFactory getSingleton() { return( singleton ); } public ResourceDownloader create( File file ) { return( new ResourceDownloaderFileImpl( null, file )); } public ResourceDownloader create( URL url ) { if ( url.getProtocol().equalsIgnoreCase("file")){ try{ return( new ResourceDownloaderFileImpl( null, new File( new URI( url.toString())))); }catch( Throwable e ){ return( new ResourceDownloaderURLImpl( null, url )); } }else{ return( new ResourceDownloaderURLImpl( null, url )); } } public ResourceDownloader create(URL url, boolean force_no_proxy) { ResourceDownloader rd = create(url); if (force_no_proxy && rd instanceof ResourceDownloaderURLImpl) { ((ResourceDownloaderURLImpl)rd).setForceNoProxy(force_no_proxy); } return rd; } public ResourceDownloader create( URL url, String postData) { return new ResourceDownloaderURLImpl(null, url, postData, false, null, null); } public ResourceDownloader create( URL url, String user_name, String password ) { return( new ResourceDownloaderURLImpl( null, url, user_name, password )); } public ResourceDownloader create( ResourceDownloaderDelayedFactory factory ) { return( new ResourceDownloaderDelayedImpl( null, factory )); } public ResourceDownloader getRetryDownloader( ResourceDownloader downloader, int retry_count ) { ResourceDownloader res = new ResourceDownloaderRetryImpl( null, downloader, retry_count ); return( res ); } public ResourceDownloader getTimeoutDownloader( ResourceDownloader downloader, int timeout_millis ) { ResourceDownloader res = new ResourceDownloaderTimeoutImpl( null, downloader, timeout_millis ); return( res ); } public ResourceDownloader getAlternateDownloader( ResourceDownloader[] downloaders ) { return( getAlternateDownloader( downloaders, -1, false )); } public ResourceDownloader getAlternateDownloader( ResourceDownloader[] downloaders, int max_to_try ) { return( getAlternateDownloader( downloaders, max_to_try, false )); } public ResourceDownloader getRandomDownloader( ResourceDownloader[] downloaders ) { return( getAlternateDownloader( downloaders, -1, true )); } public ResourceDownloader getRandomDownloader( ResourceDownloader[] downloaders, int max_to_try ) { return( getAlternateDownloader( downloaders, max_to_try, true )); } protected ResourceDownloader getAlternateDownloader( ResourceDownloader[] downloaders, int max_to_try, boolean random ) { ResourceDownloader res = new ResourceDownloaderAlternateImpl( null, downloaders, max_to_try, random ); return( res ); } public ResourceDownloader getMetaRefreshDownloader( ResourceDownloader downloader ) { ResourceDownloader res = new ResourceDownloaderMetaRefreshImpl( null, downloader ); return( res ); } public ResourceDownloader getTorrentDownloader( ResourceDownloader downloader, boolean persistent ) { return( getTorrentDownloader( downloader, persistent, null )); } public ResourceDownloader getTorrentDownloader( ResourceDownloader downloader, boolean persistent, File download_directory ) { return( new ResourceDownloaderTorrentImpl( null, downloader, persistent, download_directory )); } public ResourceDownloader getSuffixBasedDownloader( ResourceDownloader _downloader ) { ResourceDownloaderBaseImpl dl = (ResourceDownloaderBaseImpl)_downloader; URL target = null; while( true ){ List kids = dl.getChildren(); if ( kids.size() == 0 ){ target = ((ResourceDownloaderURLImpl)dl).getURL(); break; } dl = (ResourceDownloaderBaseImpl)kids.get(0); } if ( target == null ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "ResourceDownloader: suffix " + "based downloader failed to find leaf")); return( _downloader ); } if ( target.getPath().toLowerCase().endsWith(".torrent")){ return( getTorrentDownloader( _downloader, true )); }else{ return( _downloader ); } } public ResourceDownloader[] getSourceforgeDownloaders(String project_name, String filename) { String template = "http://%s.dl.sourceforge.net/sourceforge/" + project_name + "/" + filename; ResourceDownloader[] result = new ResourceDownloader[SF_MIRRORS.length]; for (int i=0; i= 0 ){ delegate.setSize( size ); } } public void setProperty( String name, Object value ) throws ResourceDownloaderException { setPropertySupport( name, value ); delegate.setProperty( name, value ); } protected long getSizeSupport() throws ResourceDownloaderException { try{ ResourceDownloader x = delegate.getClone( this ); addReportListener( x ); HTMLPage page = HTMLPageFactory.loadPage( x.download()); URL redirect = page.getMetaRefreshURL(); if ( redirect == null ){ ResourceDownloaderBaseImpl c = delegate.getClone( this ); addReportListener( c ); long res = c.getSize(); setProperties( c ); return( res ); }else{ ResourceDownloaderURLImpl c = new ResourceDownloaderURLImpl( getParent(), redirect ); addReportListener( c ); long res = c.getSize(); setProperties( c ); return( res ); } }catch( HTMLException e ){ throw( new ResourceDownloaderException( "getSize failed", e )); } } public ResourceDownloaderBaseImpl getClone( ResourceDownloaderBaseImpl parent ) { ResourceDownloaderMetaRefreshImpl c = new ResourceDownloaderMetaRefreshImpl( parent, delegate.getClone( this )); c.setSize( size ); c.setProperties( this ); return( c ); } public InputStream download() throws ResourceDownloaderException { asyncDownload(); done_sem.reserve(); if ( result instanceof InputStream ){ return((InputStream)result); } throw((ResourceDownloaderException)result); } public void asyncDownload() { try{ this_mon.enter(); if ( cancelled ){ done_sem.release(); informFailed((ResourceDownloaderException)result); }else{ done_count++; current_downloader = current_delegate.getClone( this ); informActivity( getLogIndent() + "Downloading: " + getName()); current_downloader.addListener( this ); current_downloader.asyncDownload(); } }finally{ this_mon.exit(); } } public void cancel() { setCancelled(); try{ this_mon.enter(); result = new ResourceDownloaderCancelledException(); cancelled = true; informFailed((ResourceDownloaderException)result ); done_sem.release(); if ( current_downloader != null ){ current_downloader.cancel(); } }finally{ this_mon.exit(); } } public boolean completed( ResourceDownloader downloader, InputStream data ) { boolean complete = false; try{ if ( done_count == 1 ){ // assumption is that there is a refresh tag boolean marked = false; if ( data.markSupported()){ data.mark(data.available()); marked = true; } // leave file open if marked so we can recover HTMLPage page = HTMLPageFactory.loadPage( data, !marked ); URL redirect = page.getMetaRefreshURL(); if ( redirect == null ){ if ( !marked ){ failed( downloader, new ResourceDownloaderException( "meta refresh tag not found and input stream not recoverable")); }else{ data.reset(); complete = true; } }else{ current_delegate = new ResourceDownloaderURLImpl( this, redirect ); // informActivity( "meta-refresh -> " + current_delegate.getName()); asyncDownload(); } if ( marked && !complete){ data.close(); } }else{ complete = true; } if ( complete ){ if ( informComplete( data )){ result = data; done_sem.release(); } } }catch( Throwable e ){ failed( downloader, new ResourceDownloaderException("meta-refresh processing fails", e )); } return( true ); } public void failed( ResourceDownloader downloader, ResourceDownloaderException e ) { result = e; done_sem.release(); informFailed(e); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderBaseImpl.javaazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderBaseI0000644000175000017500000001756011166774660033344 0ustar adrianadrian/* * File : TorrentDownloader2Impl.java * Created : 27-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader; /** * @author parg * */ import java.util.*; import java.io.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.utils.resourcedownloader.*; public abstract class ResourceDownloaderBaseImpl implements ResourceDownloader { private static final String PR_PROPERTIES_SET = "!!!! properties set !!!!"; private List listeners = new ArrayList(); private boolean result_informed; private Object result_informed_data; private ResourceDownloaderBaseImpl parent; private List children = new ArrayList(); private boolean download_cancelled; private Map lc_key_properties = new HashMap(); protected AEMonitor this_mon = new AEMonitor( "ResourceDownloader" ); protected ResourceDownloaderBaseImpl( ResourceDownloaderBaseImpl _parent ) { parent = _parent; if ( parent != null ){ parent.addChild(this); } } public abstract ResourceDownloaderBaseImpl getClone( ResourceDownloaderBaseImpl _parent ); protected abstract void setSize( long size ); public Object getProperty( String name ) throws ResourceDownloaderException { Object res = getPropertySupport( name ); if ( res != null || getPropertySupport( PR_PROPERTIES_SET ) != null ){ return( res ); } // hack this, properties are read during size acquisition - should treat size as a property // too.... getSize(); return( getPropertySupport( name )); } protected Object getPropertySupport( String name ) { return( lc_key_properties.get( name.toLowerCase(MessageText.LOCALE_ENGLISH))); } protected Map getLCKeyProperties() { return( lc_key_properties ); } protected String getStringPropertySupport( String name ) { Object obj = lc_key_properties.get( name.toLowerCase(MessageText.LOCALE_ENGLISH)); if ( obj instanceof String ){ return((String)obj); } return( null ); } protected void setPropertiesSet() throws ResourceDownloaderException { setProperty( PR_PROPERTIES_SET, "true" ); } protected void setPropertySupport( String name, Object value ) { boolean already_set = lc_key_properties.put( name.toLowerCase(MessageText.LOCALE_ENGLISH), value ) == value; if ( parent != null && !already_set ){ try{ parent.setProperty( name, value ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected void setProperties( ResourceDownloaderBaseImpl other ) { Map p = other.lc_key_properties; Iterator it = p.keySet().iterator(); while( it.hasNext()){ String key = (String)it.next(); try{ setProperty( key, p.get(key)); }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected void setParent( ResourceDownloader _parent ) { ResourceDownloaderBaseImpl old_parent = parent; parent = (ResourceDownloaderBaseImpl)_parent; if( old_parent != null ){ old_parent.removeChild( this ); } if ( parent != null ){ parent.addChild( this ); } } protected ResourceDownloaderBaseImpl getParent() { return( parent ); } protected void addChild( ResourceDownloaderBaseImpl kid ) { children.add( kid ); } protected void removeChild( ResourceDownloaderBaseImpl kid ) { children.remove( kid ); } protected List getChildren() { return( children ); } protected String getLogIndent() { String indent = ""; ResourceDownloaderBaseImpl pos = parent; while( pos != null ){ indent += " "; pos = pos.getParent(); } return( indent ); } // adds a listener that simply logs messages. used during size getting protected void addReportListener( ResourceDownloader rd ) { rd.addListener( new ResourceDownloaderAdapter() { public void reportActivity( ResourceDownloader downloader, String activity ) { informActivity( activity ); } public void failed( ResourceDownloader downloader, ResourceDownloaderException e ) { informActivity( downloader.getName() + ":" + e.getMessage()); } }); } protected void informPercentDone( int percentage ) { for (int i=0;i= 0 ){ for (int i=0;i= 0 ){ delegate.setSize( size ); } } public void setProperty( String name, Object value ) throws ResourceDownloaderException { setPropertySupport( name, value ); delegate.setProperty( name, value ); } protected long getSizeSupport() throws ResourceDownloaderException { try{ if ( torrent_holder[0] == null ){ ResourceDownloader x = delegate.getClone( this ); addReportListener( x ); InputStream is = x.download(); try{ torrent_holder[0] = TOTorrentFactory.deserialiseFromBEncodedInputStream( is ); }finally{ try{ is.close(); }catch( IOException e ){ } } if( !torrent_holder[0].isSimpleTorrent()){ throw( new ResourceDownloaderException( "Only simple torrents supported" )); } } try{ String file_str = new String( torrent_holder[0].getName()); int pos = file_str.lastIndexOf( "." ); String file_type; if ( pos != -1 ){ file_type = file_str.substring(pos+1); }else{ file_type = null; } setProperty( ResourceDownloader.PR_STRING_CONTENT_TYPE, HTTPUtils.guessContentTypeFromFileType( file_type )); }catch( Throwable e ){ Debug.printStackTrace(e); } return( torrent_holder[0].getSize()); }catch( TOTorrentException e ){ throw( new ResourceDownloaderException( "Torrent deserialisation failed", e )); } } protected void setSizeAndTorrent( long _size, TOTorrent[] _torrent_holder ) { size = _size; torrent_holder = _torrent_holder; } public ResourceDownloaderBaseImpl getClone( ResourceDownloaderBaseImpl parent ) { ResourceDownloaderTorrentImpl c = new ResourceDownloaderTorrentImpl( parent, delegate.getClone( this ), persistent, download_dir ); c.setSizeAndTorrent( size, torrent_holder ); c.setProperties( this ); return( c ); } public InputStream download() throws ResourceDownloaderException { asyncDownload(); done_sem.reserve(); if ( result instanceof InputStream ){ return((InputStream)result); } throw((ResourceDownloaderException)result); } public void asyncDownload() { try{ this_mon.enter(); if ( cancelled ){ done_sem.release(); informFailed((ResourceDownloaderException)result); }else{ if ( torrent_holder[0] == null ){ current_downloader = delegate.getClone( this ); informActivity( getLogIndent() + "Downloading: " + getName()); current_downloader.addListener( this ); current_downloader.asyncDownload(); }else{ downloadTorrent(); } } }finally{ this_mon.exit(); } } protected void downloadTorrent() { try{ informActivity( getLogIndent() + "Downloading: " + new String( torrent_holder[0].getName(), Constants.DEFAULT_ENCODING )); // we *don't* want this temporary file to be deleted automatically as we're // going to use it across Azureus restarts to hold the download data and // to seed it afterwards. Therefore we don't use AETemporaryFileHandler!!!! final File torrent_file = File.createTempFile("AZU", null ); if ( download_dir != null && !download_dir.exists()){ FileUtil.mkdirs(download_dir); } final File data_dir = download_dir==null?torrent_file.getParentFile():download_dir; final TOTorrent torrent = torrent_holder[0]; TorrentUtils.setFlag( torrent, TorrentUtils.TORRENT_FLAG_LOW_NOISE, true ); torrent.serialiseToBEncodedFile( torrent_file ); if ( persistent ){ download = download_manager.addDownload( new TorrentImpl(torrent), torrent_file, data_dir ); }else{ download = download_manager.addNonPersistentDownload( new TorrentImpl(torrent), torrent_file, data_dir ); } download.moveTo(1); download.setForceStart( true ); // Prevents any move-on-completion or move-on-removal behaviour happening. download.setFlag(Download.FLAG_DISABLE_AUTO_FILE_MOVE, true); download_manager.addListener( new DownloadManagerListener() { public void downloadAdded( Download download ) { } public void downloadRemoved( Download _download ) { if ( download == _download ){ ResourceDownloaderTorrentImpl.this.downloadRemoved( torrent_file, data_dir ); } } }); download.addListener( new DownloadListener() { public void stateChanged( final Download download, int old_state, int new_state ) { // System.out.println( "state change:" + old_state + "->" + new_state ); if ( new_state == Download.ST_SEEDING ){ download.removeListener( this ); PluginInitializer.getDefaultInterface().getUtilities().createThread("resource complete event dispatcher", new Runnable() { public void run() { downloadSucceeded( download, torrent_file, data_dir ); } }); } } public void positionChanged( Download download, int oldPosition, int newPosition ) { } }); Thread t = new AEThread( "RDTorrent percentage checker") { public void runSupport() { int last_percentage = 0; while( result == null ){ int this_percentage = download.getStats().getCompleted()/10; long total = torrent.getSize(); if ( this_percentage != last_percentage ){ reportPercentComplete( ResourceDownloaderTorrentImpl.this, this_percentage ); last_percentage = this_percentage; } try{ Thread.sleep(1000); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } }; t.setDaemon( true ); t.start(); // its possible that the d/l has already occurred and it is seeding! if ( download.getState() == Download.ST_SEEDING ){ downloadSucceeded( download, torrent_file, data_dir ); } }catch( Throwable e ){ failed( this, new ResourceDownloaderException( "Torrent download failed", e )); } } protected void downloadSucceeded( Download download, File torrent_file, File data_dir ) { reportActivity("Torrent download complete"); // assumption is that this is a SIMPLE torrent File target_file = new File( data_dir, new String(torrent_holder[0].getFiles()[0].getPathComponents()[0])); if ( !target_file.exists()){ File actual_target_file = new File(download.getSavePath()); try{ if ( download_dir != null && actual_target_file.exists()){ FileUtil.copyFile( actual_target_file, target_file ); } }catch( Throwable e ){ Debug.printStackTrace(e); } target_file = actual_target_file; } try{ if ( !target_file.exists()){ throw( new Exception( "File '" + target_file.toString() + "' not found" )); } InputStream data = new FileInputStream( target_file ); informComplete( data ); result = data; done_sem.release(); }catch( Throwable e ){ Debug.printStackTrace( e ); failed( this, new ResourceDownloaderException( "Failed to read downloaded torrent data: " + e.getMessage(), e )); } } protected void downloadRemoved( File torrent_file, File data_dir ) { reportActivity( "Torrent removed" ); if (!( result instanceof InputStream )){ failed( this, new ResourceDownloaderException( "Download did not complete" )); } } public void cancel() { setCancelled(); try{ this_mon.enter(); result = new ResourceDownloaderCancelledException(); cancelled = true; informFailed((ResourceDownloaderException)result ); done_sem.release(); if ( current_downloader != null ){ current_downloader.cancel(); } }finally{ this_mon.exit(); } } public boolean completed( ResourceDownloader downloader, InputStream data ) { try{ torrent_holder[0] = TOTorrentFactory.deserialiseFromBEncodedInputStream( data ); if( torrent_holder[0].isSimpleTorrent()){ downloadTorrent(); }else{ failed( this, new ResourceDownloaderException( "Only simple torrents supported" )); } }catch( TOTorrentException e ){ failed( downloader, new ResourceDownloaderException( "Torrent deserialisation failed", e )); }finally{ try{ data.close(); }catch( IOException e ){ } } return( true ); } public void failed( ResourceDownloader downloader, ResourceDownloaderException e ) { result = e; done_sem.release(); informFailed(e); } public void reportPercentComplete( ResourceDownloader downloader, int percentage ) { if ( downloader == this ){ informPercentDone( percentage ); } } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/LocaleDecoderImpl.java0000644000175000017500000000304710124624560027130 0ustar adrianadrian/* * File : LocaleDecoderImpl.java * Created : 30-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.utils; /** * @author parg * */ import java.io.UnsupportedEncodingException; import org.gudy.azureus2.core3.internat.LocaleUtilDecoder; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.utils.*; public class LocaleDecoderImpl implements LocaleDecoder { LocaleUtilDecoder decoder; protected LocaleDecoderImpl( LocaleUtilDecoder _decoder ) { decoder = _decoder; } public String getName() { return( decoder.getName()); } public String decode( byte[] encoded_bytes ) { try{ return( decoder.decodeString( encoded_bytes )); }catch( UnsupportedEncodingException e ){ Debug.printStackTrace( e ); return( null ); } } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/LocaleUtilitiesImpl.java0000644000175000017500000000740411024630156027535 0ustar adrianadrian/* * File : LocaleUtilitiesImpl.java * Created : 30-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.utils; /** * @author parg * */ import java.io.*; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.internat.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.utils.*; import org.gudy.azureus2.plugins.*; public class LocaleUtilitiesImpl implements LocaleUtilities { private PluginInterface pi; private List listeners; public LocaleUtilitiesImpl( PluginInterface _pi ) { pi = _pi; } public void integrateLocalisedMessageBundle( String resource_bundle_prefix ) { MessageText.integratePluginMessages(resource_bundle_prefix,pi.getPluginClassLoader()); } public void integrateLocalisedMessageBundle(ResourceBundle rb) { MessageText.integratePluginMessages(rb); } public void integrateLocalisedMessageBundle(Properties p) { // Surely there's a more convenient way of doing this? ResourceBundle rb = null; try { PipedInputStream in_stream = new PipedInputStream(); PipedOutputStream out_stream = new PipedOutputStream(in_stream); p.store(out_stream, ""); out_stream.close(); rb = new PropertyResourceBundle(in_stream); in_stream.close(); } catch (IOException ioe) {return;} integrateLocalisedMessageBundle(rb); } public String getLocalisedMessageText( String key ) { return( MessageText.getString( key )); } public String getLocalisedMessageText( String key, String[] params ) { return( MessageText.getString( key, params )); } public boolean hasLocalisedMessageText(String key) { return MessageText.keyExists(key); } public String localise(String key) { String res = MessageText.getString(key); if (res.charAt(0) == '!' && !MessageText.keyExists(key)) { return null; } return res; } public Locale getCurrentLocale() { return MessageText.getCurrentLocale(); } public LocaleDecoder[] getDecoders() { LocaleUtilDecoder[] decs = LocaleUtil.getSingleton().getDecoders(); LocaleDecoder[] res = new LocaleDecoder[decs.length]; for (int i=0;i 0 ){ // // return( null); if ( node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE ){ return( node.getNodeValue()); } String res = ""; for (Node child = node.getFirstChild(); child != null;child = child.getNextSibling()){ int type = child.getNodeType(); if ( type == Node.CDATA_SECTION_NODE || type == Node.TEXT_NODE || type == Node.NOTATION_NODE ){ String str = child.getNodeValue(); res += str; } } return( res ); } public SimpleXMLParserDocumentAttribute getAttribute( String name ) { SimpleXMLParserDocumentAttribute[] attributes = getAttributes(); for (int i=0;i " + getValue()); SimpleXMLParserDocumentNode[] kids = getChildren(); for (int i=0;i 0 ){ return( value ); } } return( null ); } public SimpleXMLParserDocumentNode getNode() { return( node ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSFeedImpl.java0000644000175000017500000000622211050462752027305 0ustar adrianadrian/* * Created on 02-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.utils.xml.rss; import java.io.InputStream; import java.util.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.utils.Utilities; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException; import org.gudy.azureus2.plugins.utils.xml.rss.RSSChannel; import org.gudy.azureus2.plugins.utils.xml.rss.RSSFeed; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentException; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentNode; /** * @author parg * */ public class RSSFeedImpl implements RSSFeed { private boolean is_atom; private RSSChannel[] channels; public RSSFeedImpl( Utilities utilities, ResourceDownloader downloader ) throws ResourceDownloaderException, SimpleXMLParserDocumentException { this( utilities, downloader.download()); } public RSSFeedImpl( Utilities utilities, InputStream is ) throws SimpleXMLParserDocumentException { try{ SimpleXMLParserDocument doc = utilities.getSimpleXMLParserDocumentFactory().create( is ); String doc_name = doc.getName(); is_atom = doc_name != null && doc_name.equalsIgnoreCase( "feed" ); List chans = new ArrayList(); if ( is_atom ){ chans.add( new RSSChannelImpl( doc, true )); }else{ SimpleXMLParserDocumentNode[] xml_channels = doc.getChildren(); for (int i=0;i tls = new ThreadLocal() { public PluginInterface initialValue() { return( null ); } }; private static List search_managers = new ArrayList(); private static List search_providers = new ArrayList(); private static CopyOnWriteList feature_enablers = new CopyOnWriteList(); public UtilitiesImpl( AzureusCore _core, PluginInterface _pi ) { core = _core; pi = _pi; } public String getAzureusUserDir() { String res = SystemProperties.getUserPath(); if ( res.endsWith(File.separator )){ res = res.substring(0,res.length()-1); } return( res ); } public String getAzureusProgramDir() { String res = SystemProperties.getApplicationPath(); if ( res.endsWith(File.separator )){ res = res.substring(0,res.length()-1); } return( res ); } public boolean isWindows() { return( Constants.isWindows ); } public boolean isLinux() { return( Constants.isLinux ); } public boolean isUnix() { return( Constants.isUnix ); } public boolean isFreeBSD() { return( Constants.isFreeBSD ); } public boolean isSolaris() { return( Constants.isSolaris ); } public boolean isOSX() { return( Constants.isOSX ); } public boolean isCVSVersion() { return( Constants.isCVSVersion()); } public InputStream getImageAsStream( String image_name ) { return( UtilitiesImpl.class.getClassLoader().getResourceAsStream("org/gudy/azureus2/ui/icons/" + image_name)); } public Semaphore getSemaphore() { return( new SemaphoreImpl( pi )); } public Monitor getMonitor(){ return new MonitorImpl( pi ); } public ByteBuffer allocateDirectByteBuffer( int size ) { return( DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_EXTERNAL,size ).getBuffer(DirectByteBuffer.SS_EXTERNAL)); } public void freeDirectByteBuffer( ByteBuffer buffer ) { //DirectByteBufferPool.freeBuffer( buffer ); } public PooledByteBuffer allocatePooledByteBuffer( int length ) { return( new PooledByteBufferImpl( length )); } public PooledByteBuffer allocatePooledByteBuffer( byte[] data ) { return( new PooledByteBufferImpl( data )); } public PooledByteBuffer allocatePooledByteBuffer( Map map ) throws IOException { return( new PooledByteBufferImpl( BEncoder.encode( map ))); } public Formatters getFormatters() { return( new FormattersImpl()); } public LocaleUtilities getLocaleUtilities() { return( new LocaleUtilitiesImpl( pi )); } public UTTimer createTimer( String name ) { return( new UTTimerImpl( pi, name, false )); } public UTTimer createTimer( String name, boolean lightweight ) { return( new UTTimerImpl( pi, name, lightweight )); } public UTTimer createTimer( String name, int priority ) { return( new UTTimerImpl( pi, name, priority )); } public void createThread( String name, final Runnable target ) { AEThread2 t = new AEThread2( pi.getPluginName() + "::" + name, true ) { public void run() { callWithPluginThreadContext( pi, target ); } }; t.start(); } public void createProcess( String command_line ) throws PluginException { try{ // we need to spawn without inheriting handles PlatformManager pm = PlatformManagerFactory.getPlatformManager(); pm.createProcess( command_line, false ); }catch(Throwable e) { Debug.printStackTrace(e); try{ Runtime.getRuntime().exec( command_line ); }catch( Throwable f ){ throw( new PluginException("Failed to create process", f )); } } } public ResourceDownloaderFactory getResourceDownloaderFactory() { return( ResourceDownloaderFactoryImpl.getSingleton()); } public ResourceUploaderFactory getResourceUploaderFactory() { return( ResourceUploaderFactoryImpl.getSingleton()); } public SESecurityManager getSecurityManager() { return( new SESecurityManagerImpl( core )); } public SimpleXMLParserDocumentFactory getSimpleXMLParserDocumentFactory() { return( new SimpleXMLParserDocumentFactoryImpl()); } public RSSFeed getRSSFeed( InputStream is ) throws SimpleXMLParserDocumentException { try{ return( new RSSFeedImpl( this, is )); }finally{ try{ is.close(); }catch( Throwable e ){ } } } public RSSFeed getRSSFeed( URL feed_location ) throws ResourceDownloaderException, SimpleXMLParserDocumentException { return( getRSSFeed( getResourceDownloaderFactory().create( feed_location ))); } public RSSFeed getRSSFeed( ResourceDownloader feed_location ) throws ResourceDownloaderException, SimpleXMLParserDocumentException { return( new RSSFeedImpl( this, feed_location )); } public InetAddress getPublicAddress( boolean v6 ) { if ( v6 ){ String vc_ip = VersionCheckClient.getSingleton().getExternalIpAddress( false, true ); if ( vc_ip != null && vc_ip.length() > 0 ){ try{ return( InetAddress.getByName( vc_ip )); }catch( Throwable e ){ Debug.printStackTrace( e ); } } return( null ); }else{ return( getPublicAddress()); } } public InetAddress getPublicAddress() { long now = SystemTime.getCurrentTime(); if ( now < last_public_ip_address_time ){ last_public_ip_address_time = now; }else{ if ( last_public_ip_address != null && now - last_public_ip_address_time < 15*60*1000 ){ return( last_public_ip_address ); } } InetAddress res = null; try{ String vc_ip = VersionCheckClient.getSingleton().getExternalIpAddress( false, false ); if ( vc_ip != null && vc_ip.length() > 0 ){ res = InetAddress.getByName( vc_ip ); }else{ ExternalIPChecker checker = ExternalIPCheckerFactory.create(); ExternalIPCheckerService[] services = checker.getServices(); final String[] ip = new String[]{ null }; for (int i=0;i 0 && max_queue_size == list.size()){ dispatch_now = list; list = new ArrayList(); } list.add( obj ); // set up a timer to wakeup in required time period long now = SystemTime.getCurrentTime(); if ( event != null ){ event.cancel(); } event = timer.addEvent( now + idle_dispatch_time, new TimerEventPerformer() { public void perform( TimerEvent event ) { dispatch(); } }); }finally{ timer_mon.exit(); } if ( dispatch_now != null ){ dispatch( dispatch_now ); } } public Object remove( Object obj ) { Object res = null; try{ timer_mon.enter(); res = list.remove( obj )?obj:null; if ( res != null ){ long now = SystemTime.getCurrentTime(); if ( event != null ){ event.cancel(); } if ( list.size() == 0 ){ event = null; }else{ event = timer.addEvent( now + idle_dispatch_time, new TimerEventPerformer() { public void perform( TimerEvent event ) { dispatch(); } }); } } }finally{ timer_mon.exit(); } return( res ); } protected void dispatch() { List dispatch_list; try{ timer_mon.enter(); dispatch_list = list; list = new ArrayList(); }finally{ timer_mon.exit(); } dispatch( dispatch_list ); } protected void dispatch( List l ) { if ( l.size() > 0 ){ try{ acceptor.accept( l ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } public void destroy() { dispatch(); timer.destroy(); } }); } public static final void callWithPluginThreadContext( PluginInterface pi, Runnable target ) { PluginInterface existing = tls.get(); try{ tls.set( pi ); target.run(); }finally{ tls.set( existing ); } } public static final void callWithPluginThreadContext( PluginInterface pi, runnableWithException target ) throws T { PluginInterface existing = tls.get(); try{ tls.set( pi ); target.run(); }finally{ tls.set( existing ); } } public static final T callWithPluginThreadContext( PluginInterface pi, runnableWithReturn target ) { PluginInterface existing = tls.get(); try{ tls.set( pi ); return( target.run()); }finally{ tls.set( existing ); } } public static final T callWithPluginThreadContext( PluginInterface pi, runnableWithReturnAndException target ) throws S { PluginInterface existing = tls.get(); try{ tls.set( pi ); return( target.run()); }finally{ tls.set( existing ); } } public static PluginInterface getPluginThreadContext() { return((PluginInterface)tls.get()); } public Map readResilientBEncodedFile( File parent_dir, String file_name, boolean use_backup ) { return( FileUtil.readResilientFile( parent_dir, file_name, use_backup )); } public void writeResilientBEncodedFile( File parent_dir, String file_name, Map data, boolean use_backup ) { FileUtil.writeResilientFile( parent_dir, file_name, data, use_backup ); } public void deleteResilientBEncodedFile( File parent_dir, String file_name, boolean use_backup ) { FileUtil.deleteResilientFile( new File( parent_dir, file_name )); } public int compareVersions(String v1, String v2) { return Constants.compareVersions( v1, v2 ); } public String normaliseFileName(String f_name) { return FileUtil.convertOSSpecificChars(f_name,false); } public DelayedTask createDelayedTask(Runnable target) { return addDelayedTask(pi.getPluginName(), target); } private static List delayed_tasks = new ArrayList(); private static AESemaphore delayed_tasks_sem = new AESemaphore( "Utilities:delayedTask" ); private static AEThread2 delayed_task_thread; public static DelayedTask addDelayedTask(String name, Runnable r) { DelayedTaskImpl res = new DelayedTaskImpl(name); res.setTask(r); return res; } private static void queueTask( DelayedTaskImpl task, int pos) { synchronized( delayed_tasks ){ delayed_tasks.add( pos == -1 ? delayed_tasks.size() : pos, task ); delayed_tasks_sem.release(); if ( delayed_task_thread == null ){ delayed_task_thread = new AEThread2( "Utilities:delayedTask", true ) { public void run() { try{ PluginInitializer.addInitThread(); while( true ){ if ( !delayed_tasks_sem.reserve( 5*1000 )){ synchronized( delayed_tasks ){ if ( delayed_tasks.isEmpty()){ delayed_task_thread = null; break; } } }else{ DelayedTaskImpl task; synchronized( delayed_tasks ){ task = (DelayedTaskImpl)delayed_tasks.remove(0); } //System.out.println( TimeFormatter.milliStamp() + ": Running delayed task: " + task.getName()); task.run(); } } }finally{ PluginInitializer.removeInitThread(); } } }; delayed_task_thread.setPriority( Thread.MIN_PRIORITY ); delayed_task_thread.start(); } } } public void registerSearchProvider( SearchProvider provider ) throws SearchException { List managers; synchronized( UtilitiesImpl.class ){ search_providers.add( new Object[]{ pi, provider }); managers = new ArrayList( search_managers ); } for (int i=0;i managers; synchronized( UtilitiesImpl.class ){ managers = new ArrayList( search_managers ); } if ( managers.size() == 0 ){ throw( new SearchException( "No search managers registered - try later" )); } return( managers.get(0)); } public static void addSearchManager( searchManager manager ) { List providers; synchronized( UtilitiesImpl.class ){ search_managers.add( manager ); providers = new ArrayList( search_providers ); } for (int i=0;i feature_properties) { String pid = pi.getPluginID(); if ( !pid.endsWith( "_v" )){ return( false ); } for ( FeatureEnabler fe: feature_enablers ){ if ( fe.isFeatureEnabled( pid, feature_id, feature_properties)){ return( true ); } } return false; } public void registerFeatureEnabler( FeatureEnabler enabler ) { if ( !pi.getPluginID().endsWith( "_v" )){ return; } feature_enablers.add( enabler ); } public void unregisterFeatureEnabler( FeatureEnabler enabler ) { feature_enablers.remove( enabler ); } public interface searchManager extends SearchInitiator { public void addProvider( PluginInterface pi, SearchProvider provider ); } public SubscriptionManager getSubscriptionManager() throws SubscriptionException { try{ Method m = Class.forName( "com.aelitis.azureus.core.subs.SubscriptionManagerFactory" ).getMethod( "getSingleton" ); final PluginSubscriptionManager sm = (PluginSubscriptionManager)m.invoke( null ); return( new SubscriptionManager() { public Subscription[] getSubscriptions() { PluginSubscription[] p_subs = sm.getSubscriptions( true ); Subscription[] subs = new Subscription[ p_subs.length ]; for ( int i=0;i map = p_res.toPropertyMap(); public Object getProperty( int property_name ) { return( map.get( property_name )); } public boolean isRead() { return( p_res.getRead()); } public void setRead( boolean read ) { p_res.setRead( read ); } }; } return( results ); } }; } return( subs ); } }); }catch( Throwable e ){ throw( new SubscriptionException( "Subscriptions unavailable", e )); } } public interface PluginSubscriptionManager { public PluginSubscription[] getSubscriptions( boolean subscribed_only ); } public interface PluginSubscription { public String getID(); public String getName(); public PluginSubscriptionResult[] getResults( boolean include_deleted ); } public interface PluginSubscriptionResult { public Map toPropertyMap(); public void setRead( boolean read ); public boolean getRead(); } public interface runnableWithReturn { public T run(); } public interface runnableWithException { public void run() throws T; } public interface runnableWithReturnAndException { public T run() throws S; } static class DelayedTaskImpl implements DelayedTask { private String name; private Runnable target; private long create_time = SystemTime.getCurrentTime(); private long run_time; private DelayedTaskImpl( String _name ) { name = _name; } public void setTask( Runnable _target ) { target = _target; } public void queue() { if ( target == null ){ throw( new RuntimeException( "Target must be set before queueing" )); } queueTask( this, -1 ); } public void queueFirst() { if ( target == null ){ throw( new RuntimeException( "Target must be set before queueing" )); } queueTask( this, 0 ); } protected void run() { try{ run_time = SystemTime.getCurrentTime(); target.run(); long now = SystemTime.getCurrentTime(); if (Logger.isEnabled()) { Logger.log( new LogEvent( LogIDs.PLUGIN, LogEvent.LT_INFORMATION, "Delayed task '" + getName() + "': queue_time=" + ( run_time - create_time ) + ", exec_time=" + ( now - run_time ))); } }catch( Throwable e ){ Debug.out( "Initialisation task " + getName() + " failed to complete", e ); } } protected String getName() { return( name + " (" + target.getClass() + ")" ); } } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/UTTimerImpl.java0000644000175000017500000001115011133307710025762 0ustar adrianadrian/* * Created on 29-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.utils; /** * @author parg * */ import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.utils.*; import org.gudy.azureus2.core3.util.*; public class UTTimerImpl implements UTTimer { private PluginInterface plugin_interface; private Timer timer; private boolean destroyed; public UTTimerImpl( String name, boolean lightweight ) { // this constructor is for external (non-az) use, e.g. someone using the UPnP component // in their own app if ( !lightweight ){ timer = new Timer( name ); } } protected UTTimerImpl( PluginInterface pi, String name, boolean lightweight ) { plugin_interface = pi; if ( !lightweight ){ timer = new Timer( "Plugin " + pi.getPluginID() + ":" + name ); } } protected UTTimerImpl( PluginInterface pi, String name, int priority ) { plugin_interface = pi; timer = new Timer( "Plugin " + pi.getPluginID() + ":" + name, 1, priority ); } public UTTimerEvent addEvent( long when, final UTTimerEventPerformer ext_performer ) { if ( destroyed ){ throw( new RuntimeException( "Timer has been destroyed" )); } final timerEvent res = new timerEvent(); TimerEventPerformer performer = new TimerEventPerformer() { public void perform( TimerEvent ev ) { UtilitiesImpl.callWithPluginThreadContext( plugin_interface, new Runnable() { public void run() { res.perform( ext_performer ); } }); } }; if ( timer == null ){ res.setEvent( SimpleTimer.addEvent( "Plugin:" + ext_performer.getClass(), when, performer )); }else{ res.setEvent( timer.addEvent( "Plugin:" + ext_performer.getClass(), when, performer )); } return( res ); } public UTTimerEvent addPeriodicEvent( long periodic_millis, final UTTimerEventPerformer ext_performer ) { if ( destroyed ){ throw( new RuntimeException( "Timer has been destroyed" )); } final timerEvent res = new timerEvent(); TimerEventPerformer performer = new TimerEventPerformer() { public void perform( TimerEvent ev ) { UtilitiesImpl.callWithPluginThreadContext( plugin_interface, new Runnable() { public void run() { try{ res.perform( ext_performer ); }catch( Throwable e ){ Debug.out("Plugin '" + plugin_interface.getPluginName() + " (" + plugin_interface.getPluginID() + " " + plugin_interface.getPluginVersion() + ") caused an error while processing a timer event", e); } } }); } }; if ( timer == null ){ res.setEvent( SimpleTimer.addPeriodicEvent( "Plugin:" + ext_performer.getClass(), periodic_millis, performer )); }else{ res.setEvent( timer.addPeriodicEvent( "Plugin:" + ext_performer.getClass(), periodic_millis, performer )); } return( res ); } public void destroy() { destroyed = true; if ( timer != null ){ timer.destroy(); } } protected class timerEvent implements UTTimerEvent { protected TimerEvent ev; protected TimerEventPeriodic pev; protected void setEvent( TimerEventPeriodic _ev ) { pev = _ev; } protected void setEvent( TimerEvent _ev ) { ev = _ev; } protected void perform( UTTimerEventPerformer p ) { p.perform( this ); } public void cancel() { if ( ev != null ){ ev.cancel(); }else{ pev.cancel(); } } } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/MonitorImpl.java0000644000175000017500000000321110373051012026053 0ustar adrianadrian/* * Created on May 20, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.utils; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.utils.Monitor; public class MonitorImpl implements Monitor { private static long next_mon_id; private AEMonitor mon; protected MonitorImpl( PluginInterface pi ) { synchronized( MonitorImpl.class ){ mon = new AEMonitor("Plugin " + pi.getPluginID() + ":" + next_mon_id++ ); } } public void enter() { mon.enter(); } public void exit(){ mon.exit(); } public boolean isOwned() { return( mon.isHeld()); } public boolean hasWaiters() { return( mon.hasWaiters()); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/utils/FormattersImpl.java0000644000175000017500000001142211023365764026574 0ustar adrianadrian/* * File : FormattersImpl.java * Created : 30-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.utils; /** * @author parg * */ import java.io.IOException; import java.util.Comparator; import java.util.Map; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.utils.*; public class FormattersImpl implements Formatters { public FormattersImpl() { } public String formatByteCountToKiBEtc( long bytes ) { return( DisplayFormatters.formatByteCountToKiBEtc( bytes )); } public String formatByteCountToKiBEtcPerSec( long bytes ) { return( DisplayFormatters.formatByteCountToKiBEtcPerSec( bytes )); } public String formatPercentFromThousands( long thousands ) { return( DisplayFormatters.formatPercentFromThousands( (int)thousands )); } public String formatByteArray( byte[] data, boolean no_spaces ) { return( ByteFormatter.nicePrint( data, no_spaces )); } public String encodeBytesToString( byte[] bytes ) { return( ByteFormatter.encodeString( bytes )); } public byte[] decodeBytesFromString( String str ) { return( ByteFormatter.decodeString( str )); } public String formatDate(long millis) { return DisplayFormatters.formatCustomDateTime(millis); } public String formatTimeOnly(long millis) { return DisplayFormatters.formatCustomTimeOnly(millis); } public String formatTimeOnly(long millis, boolean with_secs) { return DisplayFormatters.formatCustomTimeOnly(millis, with_secs); } public String formatDateOnly(long millis) { return DisplayFormatters.formatCustomDateOnly(millis); } public String formatTimeFromSeconds( long seconds ) { return( DisplayFormatters.formatTime( seconds*1000 )); } public String formatETAFromSeconds( long seconds ) { return TimeFormatter.format( seconds ); } public byte[] bEncode( Map map ) throws IOException { return( BEncoder.encode( map )); } public Map bDecode( byte[] data ) throws IOException { return( BDecoder.decode( data )); } public String base32Encode( byte[] data ) { return( Base32.encode( data )); } public byte[] base32Decode( String data ) { return( Base32.decode( data )); } public Comparator getAlphanumericComparator( final boolean ignore_case ) { return( new Comparator() { public int compare( Object o1, Object o2 ) { if ( o1 instanceof String && o2 instanceof String ){ String s1 = (String)o1; String s2 = (String)o2; int l1 = s1.length(); int l2 = s2.length(); int c1_pos = 0; int c2_pos = 0; while( c1_pos < l1 && c2_pos < l2 ){ char c1 = s1.charAt( c1_pos++ ); char c2 = s2.charAt( c2_pos++ ); if ( Character.isDigit(c1) && Character.isDigit(c2)){ int n1_pos = c1_pos-1; int n2_pos = c2_pos-1; while( c1_pos < l1 ){ if ( !Character.isDigit( s1.charAt( c1_pos ))){ break; } c1_pos++; } while(c2_pos 0 ){ System.out.println( "Got results: " + results.length ); for ( SearchProviderResults result: results ){ System.out.println( " " + result.getProvider().getProperty( SearchProvider.PR_NAME ) + ": comp=" + result.isComplete() + ", error=" + result.getError()); SearchResult[] srs = result.getResults(); for ( SearchResult sr: srs ){ System.out.println( " " + sr.getProperty( SearchResult.PR_NAME )); } } } } break; } }catch( Throwable e){ e.printStackTrace(); } } */ } }; t.setDaemon(true); t.start(); } public void closedownInitiated() { } public void closedownComplete() { } }); } protected void testMessaging() { try{ AzureusCoreFactory.getSingleton().getCryptoManager().addPasswordHandler( new CryptoManagerPasswordHandler() { public int getHandlerType() { return( HANDLER_TYPE_USER ); } public passwordDetails getPassword( int handler_type, int action_type, boolean last_pw_incorrect, String reason ) { System.out.println( "CryptoPassword (" + reason + ")"); return( new passwordDetails() { public char[] getPassword() { return( "changeit".toCharArray()); } public int getPersistForSeconds() { return( 0 ); } }); } public void passwordOK( int handler_type, passwordDetails details) { } }); final SESecurityManager sec_man = plugin_interface.getUtilities().getSecurityManager(); final SEPublicKey my_key = sec_man.getPublicKey( SEPublicKey.KEY_TYPE_ECC_192, "test" ); final int stream_crypto = MessageManager.STREAM_ENCRYPTION_RC4_REQUIRED; final boolean use_sts = true; final int block_crypto = SESecurityManager.BLOCK_ENCRYPTION_AES; GenericMessageRegistration reg = plugin_interface.getMessageManager().registerGenericMessageType( "GENTEST", "Gen test desc", stream_crypto, new GenericMessageHandler() { public boolean accept( GenericMessageConnection connection ) throws MessageException { System.out.println( "accept" ); try{ if ( use_sts ){ connection = sec_man.getSTSConnection( connection, my_key, new SEPublicKeyLocator() { public boolean accept( Object context, SEPublicKey other_key ) { System.out.println( "acceptKey" ); return( true ); } }, "test", block_crypto ); } connection.addListener( new GenericMessageConnectionListener() { public void connected( GenericMessageConnection connection ) { } public void receive( GenericMessageConnection connection, PooledByteBuffer message ) throws MessageException { System.out.println( "receive: " + message.toByteArray().length ); PooledByteBuffer reply = plugin_interface.getUtilities().allocatePooledByteBuffer( new byte[connection.getMaximumMessageSize()]); connection.send( reply ); } public void failed( GenericMessageConnection connection, Throwable error ) throws MessageException { System.out.println( "Responder connection error:" ); error.printStackTrace(); } }); }catch( Throwable e ){ connection.close(); e.printStackTrace(); } return( true ); } }); InetSocketAddress tcp_target = new InetSocketAddress( "127.0.0.1", 6889 ); InetSocketAddress udp_target = new InetSocketAddress( "212.159.18.92", 6881 ); GenericMessageEndpoint endpoint = reg.createEndpoint( tcp_target ); endpoint.addTCP( tcp_target ); endpoint.addUDP( udp_target ); while( true ){ try{ for (int i=0;i<1000;i++){ System.out.println( "Test: initiating connection" ); final AESemaphore sem = new AESemaphore( "wait!" ); GenericMessageConnection con = reg.createConnection( endpoint ); if ( use_sts ){ con = sec_man.getSTSConnection( con, my_key, new SEPublicKeyLocator() { public boolean accept( Object context, SEPublicKey other_key ) { System.out.println( "acceptKey" ); return( true ); } }, "test", block_crypto ); } con.addListener( new GenericMessageConnectionListener() { public void connected( GenericMessageConnection connection ) { System.out.println( "connected" ); PooledByteBuffer data = plugin_interface.getUtilities().allocatePooledByteBuffer( "1234".getBytes()); try{ connection.send( data ); }catch( Throwable e ){ e.printStackTrace(); } } public void receive( GenericMessageConnection connection, PooledByteBuffer message ) throws MessageException { System.out.println( "receive: " + message.toByteArray().length ); try{ Thread.sleep(30000); }catch( Throwable e ){ } /* PooledByteBuffer reply = plugin_interface.getUtilities().allocatePooledByteBuffer( new byte[16*1024]); connection.send( reply ); */ System.out.println( "closing connection" ); connection.close(); sem.release(); } public void failed( GenericMessageConnection connection, Throwable error ) throws MessageException { System.out.println( "Initiator connection error:" ); error.printStackTrace(); sem.release(); } }); con.connect(); sem.reserve(); Thread.sleep( 1000 ); } }catch( Throwable e ){ e.printStackTrace(); try{ System.out.println( "Sleeping before retrying" ); Thread.sleep( 30000 ); }catch( Throwable f ){ } } } }catch( Throwable e ){ e.printStackTrace(); } } protected void testLinks() { plugin_interface.getDownloadManager().addListener( new DownloadManagerListener() { public void downloadAdded( Download download ) { DiskManagerFileInfo[] info = download.getDiskManagerFileInfo(); for (int i=0;i Peer link rather // than continually creating new PeerImpls... for (int i=0;i Peer link rather // than continually creating new PeerImpls... for (int i=0;i peer_map = new HashMap(); PEPeerManagerListener core_listener = new PEPeerManagerListener() { public void peerAdded( PEPeerManager manager, PEPeer peer ) { PeerImpl pi = getPeerForPEPeer( peer ); peer_map.put( peer, pi ); fireEvent( PeerManagerEvent.ET_PEER_ADDED, pi, null, null ); } public void peerRemoved( PEPeerManager manager, PEPeer peer ) { PeerImpl pi = (PeerImpl)peer_map.remove( peer ); if ( pi == null ){ }else{ fireEvent( PeerManagerEvent.ET_PEER_REMOVED, pi, null, null ); } } public void peerDiscovered( PEPeerManager manager, PeerItem peer_item, PEPeer finder ) { PeerImpl pi; if ( finder != null ){ pi = getPeerForPEPeer( finder ); peer_map.put( finder, pi ); }else{ pi = null; } fireEvent( PeerManagerEvent.ET_PEER_DISCOVERED, pi, peer_item, null ); } public void peerSentBadData( PEPeerManager manager, PEPeer peer, int pieceNumber) { PeerImpl pi = getPeerForPEPeer( peer ); peer_map.put( peer, pi ); fireEvent( PeerManagerEvent.ET_PEER_SENT_BAD_DATA, pi, null, new Integer( pieceNumber )); } protected void fireEvent( final int type, final Peer peer, final PeerItem peer_item, final Object data ) { l.eventOccurred( new PeerManagerEvent() { public PeerManager getPeerManager() { return( PeerManagerImpl.this ); } public int getType() { return( type ); } public Peer getPeer() { return( peer ); } public PeerDescriptor getPeerDescriptor() { return( peer_item ); } public Object getData() { return( data ); } }); } public void destroyed() { } }; listener_map.put( l, core_listener ); manager.addListener( core_listener ); }finally{ this_mon.exit(); } } public void removeListener( PeerManagerListener2 l ) { try{ this_mon.enter(); PEPeerManagerListener core_listener = (PEPeerManagerListener)listener_map.remove( l ); if ( core_listener != null ){ manager.removeListener( core_listener ); } }finally{ this_mon.exit(); } } protected class pieceFacade implements Piece { private final int index; protected pieceFacade( int _index ) { index = _index; } public boolean isDone() { return( dm_pieces[index].isDone()); } public boolean isNeeded() { return( dm_pieces[index].isNeeded()); } public boolean isDownloading() { return( pe_pieces[index] != null ); } public boolean isFullyAllocatable() { if ( pe_pieces[index] != null ){ return( false ); } return( dm_pieces[index].isInteresting()); } public int getAllocatableRequestCount() { PEPiece pe_piece = pe_pieces[index]; if ( pe_piece != null ){ return( pe_piece.getNbUnrequested()); } if ( dm_pieces[index].isInteresting() ){ return( dm_pieces[index].getNbBlocks()); } return( 0 ); } } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignDelegate.java0000644000175000017500000004244111257512376027451 0ustar adrianadrian/* * File : PeerForeignDelegate.java * Created : 22-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.pluginsimpl.local.peers; /** * @author parg * @author MjrTom * 2005/Oct/08: Add _lastPiece * */ import java.net.InetAddress; import java.util.HashMap; import java.util.List; import java.util.Map; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.disk.DiskManagerReadRequest; import org.gudy.azureus2.core3.peer.*; import org.gudy.azureus2.core3.peer.impl.PEPeerControl; import org.gudy.azureus2.core3.peer.impl.PEPeerTransport; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.network.Connection; import org.gudy.azureus2.plugins.peers.*; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.pluginsimpl.local.messaging.MessageAdapter; import com.aelitis.azureus.core.networkmanager.LimitedRateGroup; import com.aelitis.azureus.core.networkmanager.NetworkConnectionBase; import com.aelitis.azureus.core.networkmanager.NetworkManager; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.peerdb.PeerItem; import com.aelitis.azureus.core.peermanager.peerdb.PeerItemFactory; import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags; public class PeerForeignDelegate implements PEPeerTransport { // this implementation supports read-only peers (i.e. download only) protected volatile int _lastPiece =-1; private PeerManagerImpl manager; private Peer foreign; private NetworkConnectionBase network_connection; private long create_time = SystemTime.getCurrentTime(); private long last_data_received_time =-1; private long last_data_message_received_time =-1; private int reserved_piece = -1; private int consecutive_no_requests; private BitFlags bit_flags; private boolean priority_connection; private Map data; private HashMap peer_listeners; protected AEMonitor this_mon = new AEMonitor( "PeerForeignDelegate" ); protected PeerForeignDelegate( PeerManagerImpl _manager, Peer _foreign ) { manager = _manager; foreign = _foreign; PEPeerManager pm = manager.getDelegate(); network_connection = new PeerForeignNetworkConnection( foreign ); network_connection.addRateLimiter( pm.getUploadLimitedRateGroup(), true ); network_connection.addRateLimiter( pm.getDownloadLimitedRateGroup(), false ); } public void start() { NetworkManager.getSingleton().startTransferProcessing( network_connection ); NetworkManager.getSingleton().upgradeTransferProcessing( network_connection, manager.getPartitionID()); } protected void stop() { NetworkManager.getSingleton().stopTransferProcessing( network_connection ); } /** * Should never be called */ public void sendChoke() {} /** * Nothing to do if called */ public void sendHave(int piece) {} /** * Should never be called */ public void sendUnChoke() {} public InetAddress getAlternativeIPv6() { return null; } public boolean transferAvailable() { return( foreign.isTransferAvailable()); } public boolean isDownloadPossible() { return foreign.isDownloadPossible(); } public void sendCancel( DiskManagerReadRequest request ) { foreign.cancelRequest( request ); } /** * * @param pieceNumber * @param pieceOffset * @param pieceLength * @return true is the piece is really requested */ public DiskManagerReadRequest request( int pieceNumber, int pieceOffset, int pieceLength ) { DiskManagerReadRequest request = manager.getDelegate().getDiskManager().createReadRequest( pieceNumber, pieceOffset, pieceLength ); if ( foreign.addRequest( request )){ return( request ); }else{ return( null ); } } public int getRequestIndex( DiskManagerReadRequest request ) { return( foreign.getRequests().indexOf( request )); } protected void dataReceived() { last_data_received_time = SystemTime.getCurrentTime(); } public void closeConnection( String reason ) { try{ foreign.close( reason, false, false ); }finally{ stop(); } } public List getExpiredRequests() { return( foreign.getExpiredRequests()); } public int getMaxNbRequests() { return( foreign.getMaximumNumberOfRequests()); } public int getNbRequests() { return( foreign.getNumberOfRequests()); } public int[] getPriorityOffsets() { return( foreign.getPriorityOffsets()); } public boolean requestAllocationStarts( int[] base_priorities ) { return( foreign.requestAllocationStarts( base_priorities )); } public void requestAllocationComplete() { foreign.requestAllocationComplete(); } public PEPeerControl getControl() { return((PEPeerControl)manager.getDelegate()); } public void updatePeerExchange() { } public PeerItem getPeerItemIdentity() { return PeerItemFactory.createPeerItem( foreign.getIp(), foreign.getTCPListenPort(), PeerItemFactory.PEER_SOURCE_PLUGIN, PeerItemFactory.HANDSHAKE_TYPE_PLAIN, foreign.getUDPListenPort(), PeerItemFactory.CRYPTO_LEVEL_1, 0 ); } public int getConnectionState() { int peer_state = getPeerState(); if ( peer_state == Peer.CONNECTING ){ return( CONNECTION_CONNECTING ); }else if ( peer_state == Peer.HANDSHAKING ){ return( CONNECTION_WAITING_FOR_HANDSHAKE ); }else if ( peer_state == Peer.TRANSFERING ){ return( CONNECTION_FULLY_ESTABLISHED ); }else{ return( CONNECTION_FULLY_ESTABLISHED ); } } public void doKeepAliveCheck() { } public boolean doTimeoutChecks() { return false; } public void doPerformanceTuningCheck() { } public long getTimeSinceConnectionEstablished() { long now = SystemTime.getCurrentTime(); if ( now > create_time ){ return( now - create_time ); } return( 0 ); } public long getTimeSinceLastDataMessageReceived() { if (last_data_message_received_time ==-1) return -1; //never received final long now =SystemTime.getCurrentTime(); if (last_data_message_received_time " + to_file ); if ( from_file_or_resource.indexOf(File.separator) == -1 ){ from_file_or_resource = install_dir.toString() + File.separator + from_file_or_resource; } try{ // see if this action has a chance of succeeding File to_f = new File( to_file ); File parent = to_f.getParentFile(); if ( parent != null && !parent.exists()){ parent.mkdirs(); } if ( parent != null ){ // we're going to need write access to the parent, let's try if ( !parent.canWrite()){ // Vista install process goes through permissions elevation process // so don't warn about lack of write permissions if ( !Constants.isWindowsVistaOrHigher ){ Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_WARNING, "The location '" + parent.toString() + "' isn't writable, this update will probably fail." + " Check permissions and retry the update")); } } } try{ PlatformManager pm = PlatformManagerFactory.getPlatformManager(); if ( pm.hasCapability( PlatformManagerCapabilities.CopyFilePermissions )){ String parent_str = parent.getAbsolutePath(); PlatformManagerFactory.getPlatformManager().copyFilePermissions( parent_str, from_file_or_resource ); } }catch( Throwable e ){ Debug.out( e ); } }catch( Throwable e ){ } appendAction( "move," + from_file_or_resource + "," + to_file ); } public void addChangeRightsAction( String rights, String to_file ) throws UpdateException { appendAction( "chmod," + rights + "," + to_file ); } public void addRemoveAction( String file ) throws UpdateException { appendAction( "remove," + file ); } protected void appendAction( String data ) throws UpdateException { PrintWriter pw = null; try{ pw = new PrintWriter(new FileWriter( install_dir.toString() + File.separator + ACTIONS, true )); pw.println( data ); }catch( Throwable e ){ throw( new UpdateException( "Failed to write actions file", e )); }finally{ if ( pw != null ){ try{ pw.close(); }catch( Throwable e ){ throw( new UpdateException( "Failed to write actions file", e )); } } } } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/update/UpdateManagerImpl.java0000644000175000017500000001644211154423450027304 0ustar adrianadrian/* * Created on 07-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.update; /** * @author parg * */ import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AETemporaryFileHandler; import org.gudy.azureus2.core3.util.AEVerifier; import org.gudy.azureus2.core3.util.AEVerifierException; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.plugins.update.*; import com.aelitis.azureus.core.AzureusCore; public class UpdateManagerImpl implements UpdateManager { protected static UpdateManagerImpl singleton; public static UpdateManager getSingleton( AzureusCore core ) { if ( singleton == null ){ singleton = new UpdateManagerImpl( core ); } return( singleton ); } protected AzureusCore azureus_core; protected List components = new ArrayList(); protected List listeners = new ArrayList(); protected List verification_listeners = new ArrayList(); protected List installers = new ArrayList(); protected AEMonitor this_mon = new AEMonitor( "UpdateManager" ); protected UpdateManagerImpl( AzureusCore _azureus_core ) { azureus_core = _azureus_core; UpdateInstallerImpl.checkForFailedInstalls( this ); // cause the platform manager to register any updateable components try{ PlatformManagerFactory.getPlatformManager(); }catch( Throwable e ){ } } public void registerUpdatableComponent( UpdatableComponent component, boolean mandatory ) { try{ this_mon.enter(); components.add( new UpdatableComponentImpl( component, mandatory )); }finally{ this_mon.exit(); } } public UpdateCheckInstance createUpdateCheckInstance() { return( createUpdateCheckInstance( UpdateCheckInstance.UCI_UPDATE, "" )); } public UpdateCheckInstance createUpdateCheckInstance( int type, String name ) { try{ this_mon.enter(); UpdatableComponentImpl[] comps = new UpdatableComponentImpl[components.size()]; components.toArray( comps ); UpdateCheckInstance res = new UpdateCheckInstanceImpl( this, type, name, comps ); for (int i=0;i listeners = new ArrayList(); private List updates = new ArrayList(); private List decision_listeners = new ArrayList(); private AESemaphore sem = new AESemaphore("UpdateCheckInstance"); private UpdateManager manager; private int check_type; private String name; private UpdatableComponentImpl[] components; private UpdateCheckerImpl[] checkers; private boolean completed; private boolean cancelled; private boolean automatic = true; private boolean low_noise = false; protected AEMonitor this_mon = new AEMonitor( "UpdateCheckInstance" ); private Map properties = new HashMap(); { properties.put( PT_UI_STYLE, PT_UI_STYLE_DEFAULT ); } protected UpdateCheckInstanceImpl( UpdateManager _manager, int _check_type, String _name, UpdatableComponentImpl[] _components ) { manager = _manager; check_type = _check_type; name = _name; components = _components; checkers = new UpdateCheckerImpl[components.length]; for (int i=0;i target_updates = new ArrayList(); // if any mandatory checks failed then we can't do any more if ( mandatory_failed ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "Dropping all updates as a mandatory update check failed")); }else{ // If there are any manadatory updates then we just go ahead with them and drop the rest boolean mandatory_only = false; for (int i=0;i DDBaseValueImpl.MAX_VALUE_SIZE ){ throw( new DistributedDatabaseException("Value size limited to " + DDBaseValueImpl.MAX_VALUE_SIZE + " bytes" )); } } if ( values.length == 0 ){ delete( listener, key ); }else if ( values.length == 1 ){ getDHT().put( ((DDBaseKeyImpl)key).getBytes(), key.getDescription(), ((DDBaseValueImpl)values[0]).getBytes(), DHTPlugin.FLAG_SINGLE_VALUE, new listenerMapper( listener, DistributedDatabaseEvent.ET_VALUE_WRITTEN, key, 0, false, false )); }else{ // TODO: optimise re-publishing to avoid republishing everything each time /* DHTPluginValue old_value = dht.getLocalValue( ((DDBaseKeyImpl)key).getBytes()); List old_values = new ArrayList(); if ( old_value != null ){ if (( old_value.getFlags() & DHTPlugin.FLAG_MULTI_VALUE ) == 0 ){ old_values.add( old_value.getValue()); }else{ byte[] encoded = old_value.getValue(); } } */ byte[] current_key = ((DDBaseKeyImpl)key).getBytes(); // format is: byte[] payload = new byte[DHTPlugin.MAX_VALUE_SIZE]; int payload_length = 1; int pos = 0; while( pos < values.length ){ DDBaseValueImpl value = (DDBaseValueImpl)values[pos]; byte[] bytes = value.getBytes(); int len = bytes.length; if ( payload_length + len < payload.length - 2 ){ payload[payload_length++] = (byte)(( len & 0x0000ff00 ) >> 8); payload[payload_length++] = (byte) ( len & 0x000000ff ); System.arraycopy( bytes, 0, payload, payload_length, len ); payload_length += len; pos++; }else{ payload[0] = 1; final byte[] copy = new byte[payload_length]; System.arraycopy( payload, 0, copy, 0, copy.length ); final byte[] f_current_key = current_key; getDHT().put( f_current_key, key.getDescription(), copy, DHTPlugin.FLAG_MULTI_VALUE, new listenerMapper( listener, DistributedDatabaseEvent.ET_VALUE_WRITTEN, key, 0, false, false )); payload_length = 1; current_key = new SHA1Simple().calculateHash( current_key ); } } if ( payload_length > 1 ){ payload[0] = 0; final byte[] copy = new byte[payload_length]; System.arraycopy( payload, 0, copy, 0, copy.length ); final byte[] f_current_key = current_key; getDHT().put( f_current_key, key.getDescription(), copy, DHTPlugin.FLAG_MULTI_VALUE, new listenerMapper( listener, DistributedDatabaseEvent.ET_VALUE_WRITTEN, key, 0, false, false )); } } } public void read( DistributedDatabaseListener listener, DistributedDatabaseKey key, long timeout ) throws DistributedDatabaseException { read( listener, key, timeout, OP_NONE ); } public void read( final DistributedDatabaseListener listener, final DistributedDatabaseKey key, final long timeout, int options ) throws DistributedDatabaseException { throwIfNotAvailable(); boolean exhaustive = (options&OP_EXHAUSTIVE_READ)!=0; boolean high_priority = (options&OP_PRIORITY_HIGH)!=0; // TODO: max values? getDHT().get( ((DDBaseKeyImpl)key).getBytes(), key.getDescription(), (byte)0, 256, timeout, exhaustive, high_priority, new listenerMapper( listener, DistributedDatabaseEvent.ET_VALUE_READ, key, timeout, exhaustive, high_priority )); } public void readKeyStats( DistributedDatabaseListener listener, DistributedDatabaseKey key, long timeout ) throws DistributedDatabaseException { throwIfNotAvailable(); getDHT().get( ((DDBaseKeyImpl)key).getBytes(), key.getDescription(), DHTPlugin.FLAG_STATS, 256, timeout, false, false, new listenerMapper( listener, DistributedDatabaseEvent.ET_KEY_STATS_READ, key, timeout, false, false )); } public void delete( final DistributedDatabaseListener listener, final DistributedDatabaseKey key ) throws DistributedDatabaseException { throwIfNotAvailable(); getDHT().remove( ((DDBaseKeyImpl)key).getBytes(), key.getDescription(), new listenerMapper( listener, DistributedDatabaseEvent.ET_VALUE_DELETED, key, 0, false, false )); } public void delete( DistributedDatabaseListener listener, DistributedDatabaseKey key, DistributedDatabaseContact[] targets ) throws DistributedDatabaseException { throwIfNotAvailable(); DHTPluginContact[] plugin_targets = new DHTPluginContact[ targets.length ]; for (int i=0;i value.length - pos ){ Debug.out( "Invalid length: len = " + len + ", remaining = " + (value.length - pos )); break; } byte[] d = new byte[len]; System.arraycopy( value, pos, d, 0, len ); listener.event( new dbEvent( type, key, originator, d, _value.getCreationTime(), _value.getVersion())); pos += len; } if ( value[0] == 1 ){ // continuation exists final byte[] next_key_bytes = new SHA1Simple().calculateHash( key_bytes ); complete_disabled = true; grabDHT().get( next_key_bytes, key.getDescription() + " [continuation " + continuation_num + "]", (byte)0, 256, timeout, exhaustive, high_priority, new listenerMapper( listener, DistributedDatabaseEvent.ET_VALUE_READ, key, next_key_bytes, timeout, continuation_num+1 )); } }else{ listener.event( new dbEvent( type, key, originator, _value )); } } } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { listener.event( new dbEvent( type, key, target, value )); } public void complete( byte[] timeout_key, boolean timeout_occurred ) { if ( !complete_disabled ){ listener.event( new dbEvent( timeout_occurred?DistributedDatabaseEvent.ET_OPERATION_TIMEOUT:DistributedDatabaseEvent.ET_OPERATION_COMPLETE, key )); } } } protected class dbEvent implements DistributedDatabaseEvent { private int type; private DistributedDatabaseKey key; private DistributedDatabaseKeyStats key_stats; private DistributedDatabaseValue value; private DDBaseContactImpl contact; protected dbEvent( int _type ) { type = _type; } protected dbEvent( int _type, DistributedDatabaseKey _key ) { type = _type; key = _key; } protected dbEvent( int _type, DistributedDatabaseKey _key, DHTPluginContact _contact, DHTPluginValue _value ) { type = _type; key = _key; contact = new DDBaseContactImpl( DDBaseImpl.this, _contact ); value = new DDBaseValueImpl( contact, _value.getValue(), _value.getCreationTime(), _value.getVersion()); } protected dbEvent( int _type, DistributedDatabaseKey _key, DHTPluginContact _contact, DistributedDatabaseKeyStats _key_stats ) { type = _type; key = _key; contact = new DDBaseContactImpl( DDBaseImpl.this, _contact ); key_stats = _key_stats; } protected dbEvent( int _type, DistributedDatabaseKey _key, DHTPluginContact _contact, byte[] _value, long _ct, long _v ) { type = _type; key = _key; contact = new DDBaseContactImpl( DDBaseImpl.this, _contact ); value = new DDBaseValueImpl( contact, _value, _ct, _v ); } public int getType() { return( type ); } public DistributedDatabaseKey getKey() { return( key ); } public DistributedDatabaseKeyStats getKeyStats() { return( key_stats ); } public DistributedDatabaseValue getValue() { return( value ); } public DistributedDatabaseContact getContact() { return( contact ); } } }azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseHelpers.java0000644000175000017500000000740110373051006025610 0ustar adrianadrian/* * Created on 21-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ddb; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.UnsupportedEncodingException; import org.gudy.azureus2.core3.util.HashWrapper; import org.gudy.azureus2.core3.util.SHA1Simple; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseException; /** * @author parg * */ public class DDBaseHelpers { protected static byte[] encode( Object obj ) throws DistributedDatabaseException { byte[] res; if ( obj == null ){ throw( new DistributedDatabaseException( "null not supported" )); }else if ( obj instanceof byte[] ){ res = (byte[])obj; }else if ( obj instanceof String ){ try{ res = ((String)obj).getBytes("UTF-8"); }catch( UnsupportedEncodingException e ){ throw( new DistributedDatabaseException( "charset error", e )); } }else if ( obj instanceof Byte || obj instanceof Short || obj instanceof Integer || obj instanceof Long || obj instanceof Float || obj instanceof Double || obj instanceof Boolean ){ throw( new DistributedDatabaseException( "not supported yet!" )); }else{ try{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream( baos ); oos.writeObject( obj ); oos.close(); res = baos.toByteArray(); }catch( Throwable e ){ throw( new DistributedDatabaseException( "encoding fails", e )); } } return( res ); } protected static Object decode( Class target, byte[] data ) throws DistributedDatabaseException { if ( target == byte[].class ){ return( data ); }else if ( target == String.class ){ try{ return( new String( data, "UTF-8" )); }catch( UnsupportedEncodingException e ){ throw( new DistributedDatabaseException( "charset error", e )); } }else{ try{ ObjectInputStream iis = new ObjectInputStream( new ByteArrayInputStream( data )); Object res = iis.readObject(); if ( target.isInstance( res )){ return( res ); }else{ throw( new DistributedDatabaseException( "decoding fails, incompatible type" )); } }catch( DistributedDatabaseException e ){ throw( e ); }catch( Throwable e ){ throw( new DistributedDatabaseException( "decoding fails", e )); } } } protected static HashWrapper getKey( Class c ) throws DistributedDatabaseException { String name = c.getName(); if ( name == null ){ throw( new DistributedDatabaseException( "name doesn't exist for '" + c.getName() + "'" )); } return( new HashWrapper(new SHA1Simple().calculateHash(name.getBytes()))); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseTTTorrent.java0000644000175000017500000003002511171750562026123 0ustar adrianadrian/* * Created on 03-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ddb; import java.util.*; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ddb.*; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import com.aelitis.azureus.plugins.dht.DHTPluginProgressListener; /** * @author parg * */ public class DDBaseTTTorrent implements DistributedDatabaseTransferType, DistributedDatabaseTransferHandler { private static final boolean TRACE = false; private static final byte CRYPTO_VERSION = 1; static{ if ( TRACE ){ System.out.println( "**** Torrent xfer tracing on ****" ); } } private DDBaseImpl ddb; private TorrentAttribute ta_sha1; private boolean crypto_tested; private boolean crypto_available; private List external_downloads; private Map data_cache = new LinkedHashMap(5,0.75f,true) { protected boolean removeEldestEntry( Map.Entry eldest) { return size() > 5; } }; protected DDBaseTTTorrent( DDBaseImpl _ddb ) { ddb = _ddb; } public void addDownload( Download download ) { synchronized( this ){ if ( external_downloads == null ){ external_downloads = new ArrayList(); } external_downloads.add( download ); } } public void removeDownload( Download download ) { synchronized( this ){ if ( external_downloads != null ){ external_downloads.remove( download ); } if ( external_downloads.size() == 0 ){ external_downloads = null; } } } // server side read public DistributedDatabaseValue read( DistributedDatabaseContact contact, DistributedDatabaseTransferType type, DistributedDatabaseKey key ) throws DistributedDatabaseException { // We use sha1(hash) as the key for torrent downloads // and encrypt the torrent content using the hash as the basis for a key. This // prevents someone without the hash from downloading the torrent try{ byte[] search_key = ((DDBaseKeyImpl)key).getBytes(); Download download = null; PluginInterface pi = PluginInitializer.getDefaultInterface(); String search_sha1 = pi.getUtilities().getFormatters().encodeBytesToString( search_key ); if ( ta_sha1 == null ){ ta_sha1 = pi.getTorrentManager().getPluginAttribute( "DDBaseTTTorrent::sha1"); } // gotta look for the sha1(hash) Download[] downloads = pi.getDownloadManager().getDownloads(); for (int i=0;i 120*1000 ){ it.remove(); } } if ( data_cache.size() == 0 ){ pe[0].cancel(); } } } }); } data_cache.put( hw, new Object[]{ data, new Long( SystemTime.getCurrentTime())}); } return( ddb.createValue( data )); }catch( Throwable e ){ throw( new DistributedDatabaseException("Torrent write fails", e )); } } // server side write public void write( DistributedDatabaseContact contact, DistributedDatabaseTransferType type, DistributedDatabaseKey key, DistributedDatabaseValue value ) throws DistributedDatabaseException { throw( new DistributedDatabaseException( "not supported" )); } // client side read protected DistributedDatabaseValue read( DDBaseContactImpl contact, final DistributedDatabaseProgressListener listener, DistributedDatabaseTransferType type, DistributedDatabaseKey key, long timeout ) throws DistributedDatabaseException { byte[] torrent_hash = ((DDBaseKeyImpl)key).getBytes(); byte[] lookup_key = new SHA1Simple().calculateHash( torrent_hash ); if ( TRACE ){ System.out.println( "TorrentXfer: sending via sha1(hash)" ); } byte[] data = contact.getContact().read( new DHTPluginProgressListener() { public void reportSize( long size ) { listener.reportSize( size ); } public void reportActivity( String str ) { listener.reportActivity( str ); } public void reportCompleteness( int percent ) { listener.reportCompleteness( percent ); } }, DDBaseHelpers.getKey(type.getClass()).getHash(), lookup_key, timeout ); if ( data == null ){ return( null ); } data = decrypt( torrent_hash, data ); if ( data == null ){ return( null ); } return( new DDBaseValueImpl( contact, data, SystemTime.getCurrentTime(), -1)); } protected byte[] encrypt( byte[] hash, byte[] data ) { if ( !testCrypto()){ return( null ); } byte[] enc = doCrypt( Cipher.ENCRYPT_MODE, hash, data, 0 ); if ( enc == null ){ if ( TRACE ){ System.out.println( "TorrentXfer: encryption failed, using plain" ); } byte[] res = new byte[data.length+2]; res[0] = CRYPTO_VERSION; res[1] = 0; // not encrypted System.arraycopy( data, 0, res, 2, data.length ); return( res ); }else{ if ( TRACE ){ System.out.println( "TorrentXfer: encryption ok" ); } byte[] res = new byte[enc.length+2]; res[0] = CRYPTO_VERSION; res[1] = 1; // encrypted System.arraycopy( enc, 0, res, 2, enc.length ); return( res ); } } protected byte[] decrypt( byte[] hash, byte[] data ) { if ( !testCrypto()){ return( null ); } if ( data[0] != CRYPTO_VERSION ){ Debug.out( "Invalid crypto version received" ); return( data ); } if ( data[1] == 0 ){ // encryption failed, in plain if ( TRACE ){ System.out.println( "TorrentXfer: encryption failed, retrieving plain" ); } byte[] res = new byte[data.length-2]; System.arraycopy( data, 2, res, 0, res.length ); return( res ); }else{ if ( TRACE ){ System.out.println( "TorrentXfer: encryption ok, decrypting" ); } byte[] res = doCrypt( Cipher.DECRYPT_MODE, hash, data, 2 ); return( res ); } } protected byte[] doCrypt( int mode, byte[] hash, byte[] data, int data_offset ) { try{ byte[] key_data = new byte[24]; // hash is 20 bytes so we've got 4 zeros at the end. tough System.arraycopy( hash, 0, key_data, 0, hash.length ); SecretKey tdes_key = new SecretKeySpec( key_data, "DESede" ); Cipher cipher = Cipher.getInstance("DESede"); // Triple-DES encryption cipher.init(mode, tdes_key ); return( cipher.doFinal(data, data_offset, data.length - data_offset )); }catch( Throwable e ){ Debug.out( e ); return( null ); } } protected boolean testCrypto() { if ( !crypto_tested ){ crypto_tested = true; try{ Cipher.getInstance("DESede"); // Triple-DES encryption crypto_available = true; }catch( Throwable e ){ Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "Unable to initialise cryptographic framework for magnet-based " + "torrent downloads, please re-install Java", e)); } } return( crypto_available ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseValueImpl.java0000644000175000017500000000515210412370562026112 0ustar adrianadrian/* * Created on 18-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ddb; import org.gudy.azureus2.plugins.ddb.*; import com.aelitis.azureus.plugins.dht.DHTPlugin; /** * @author parg * */ public class DDBaseValueImpl implements DistributedDatabaseValue { private DDBaseContactImpl contact; private Object value; private byte[] value_bytes; private long creation_time; private long version; // we reserve 3 bytes for overflow marker and length encoding for multi-value values protected static int MAX_VALUE_SIZE = DHTPlugin.MAX_VALUE_SIZE -3; protected DDBaseValueImpl( DDBaseContactImpl _contact, Object _value, long _creation_time, long _version ) throws DistributedDatabaseException { contact = _contact; value = _value; creation_time = _creation_time; version = _version; value_bytes = DDBaseHelpers.encode( value ); // don't police value size limit here as temporary large objects can be // created when handling transfers } protected DDBaseValueImpl( DDBaseContactImpl _contact, byte[] _value_bytes, long _creation_time, long _version ) { contact = _contact; value_bytes = _value_bytes; creation_time = _creation_time; version = _version; } public Object getValue( Class c ) throws DistributedDatabaseException { if ( value == null ){ value = DDBaseHelpers.decode( c, value_bytes ); } return( value ); } protected byte[] getBytes() { return( value_bytes ); } public long getCreationTime() { return( creation_time ); } public long getVersion() { return( version ); } public DistributedDatabaseContact getContact() { return( contact ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseKeyImpl.java0000644000175000017500000000402210373051006025554 0ustar adrianadrian/* * Created on 18-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ddb; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseException; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseKey; /** * @author parg * */ public class DDBaseKeyImpl implements DistributedDatabaseKey { private Object key; private byte[] key_bytes; private String description; protected DDBaseKeyImpl( Object _key ) throws DistributedDatabaseException { this( _key, null ); } protected DDBaseKeyImpl( Object _key, String _description ) throws DistributedDatabaseException { key = _key; description = _description; key_bytes = DDBaseHelpers.encode( key ); if ( description == null ){ if ( key instanceof String ){ description = (String)key; }else{ description = "[" + ByteFormatter.nicePrint(key_bytes) + "]"; } } } public Object getKey() { return( key ); } protected byte[] getBytes() { return( key_bytes ); } public String getDescription() { return( description ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseContactImpl.java0000644000175000017500000001051111265520566026434 0ustar adrianadrian/* * Created on 22-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ddb; import java.net.InetSocketAddress; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseContact; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseEvent; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseException; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseKey; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseKeyStats; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseListener; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseProgressListener; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseTransferType; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseValue; import com.aelitis.azureus.plugins.dht.DHTPluginContact; import com.aelitis.azureus.plugins.dht.DHTPluginOperationListener; import com.aelitis.azureus.plugins.dht.DHTPluginValue; /** * @author parg * */ public class DDBaseContactImpl implements DistributedDatabaseContact { private DDBaseImpl ddb; private DHTPluginContact contact; protected DDBaseContactImpl( DDBaseImpl _ddb, DHTPluginContact _contact ) { ddb = _ddb; contact = _contact; } public String getName() { return( contact.getName()); } public InetSocketAddress getAddress() { return( contact.getAddress()); } public boolean isAlive( long timeout ) { return( contact.isAlive( timeout )); } public void isAlive( long timeout, final DistributedDatabaseListener listener ) { contact.isAlive( timeout, new DHTPluginOperationListener() { public void starts( byte[] key ) { } public void diversified() { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] key, final boolean timeout_occurred ) { listener.event( new DistributedDatabaseEvent() { public int getType() { return( timeout_occurred?ET_OPERATION_TIMEOUT:ET_OPERATION_COMPLETE ); } public DistributedDatabaseKey getKey() { return( null ); } public DistributedDatabaseKeyStats getKeyStats() { return( null ); } public DistributedDatabaseValue getValue() { return( null ); } public DistributedDatabaseContact getContact() { return( DDBaseContactImpl.this ); } }); } }); } public boolean isOrHasBeenLocal() { return( contact.isOrHasBeenLocal()); } public boolean openTunnel() { return( contact.openTunnel() != null ); } public void write( DistributedDatabaseTransferType type, DistributedDatabaseKey key, DistributedDatabaseValue data ) throws DistributedDatabaseException { throw( new DistributedDatabaseException( "not implemented" )); } public DistributedDatabaseValue read( final DistributedDatabaseProgressListener listener, DistributedDatabaseTransferType type, DistributedDatabaseKey key, long timeout ) throws DistributedDatabaseException { return( ddb.read( this, listener, type, key, timeout )); } protected DHTPluginContact getContact() { return( contact ); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/deprecate/0000755000175000017500000000000011310377634023553 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/deprecate/PluginDeprecation.java0000644000175000017500000001603211061147534030031 0ustar adrianadrian/* * Created on 5 Aug 2008 * Created by Allan Crooks * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.pluginsimpl.local.deprecate; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.impl.StringListImpl; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.logging.LoggerChannel; import org.gudy.azureus2.plugins.ui.UIInstance; import org.gudy.azureus2.plugins.ui.UIManagerListener; import org.gudy.azureus2.plugins.ui.model.BasicPluginViewModel; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.plugins.UISWTInstance; /** * @author Allan Crooks * */ public class PluginDeprecation { // // // // Call definitions. // // // private final static String CONFIG_KEY = "PluginDeprecationWarnings"; private final static String FORUM_STABLE_LINK = "http://forum.vuze.com/forum.jspa?forumID=3"; private final static String FORUM_BETA_LINK = "http://forum.vuze.com/forum.jspa?forumID=4"; private final static int IGNORE = 0; private final static int NOTIFY_ONCE = 1; private final static int NOTIFY_EVERY = 2; private final static int NOTIFY_AND_DIE = 3; private final static int DIE = 4; private static BasicPluginViewModel model = null; private static LoggerChannel channel = null; private static Map behaviour_mapping = new HashMap(); private static Set persistent_warnings = Collections.synchronizedSet(new HashSet()); private static Set instance_warnings = Collections.synchronizedSet(new HashSet()); private static void register(String identifier, int stable_behaviour, int beta_behaviour) { behaviour_mapping.put(identifier, new Integer( Constants.isCVSVersion() ? beta_behaviour : stable_behaviour )); } static { /** * Here is where we define all deprecated call definitions that we manage. */ register("property listener", IGNORE, NOTIFY_EVERY); register("createPluginView", IGNORE, NOTIFY_EVERY); register("getSWTManager", IGNORE, IGNORE); // autostop still uses this. :( register("openTorrentFile", IGNORE, NOTIFY_EVERY); register("openTorrentURL", IGNORE, NOTIFY_EVERY); // PluginInterface -> PluginState transition. register("setDisabled", IGNORE, NOTIFY_ONCE); register("isDisabled", IGNORE, NOTIFY_ONCE); register("isBuiltIn", IGNORE, NOTIFY_ONCE); register("isMandatory", IGNORE, NOTIFY_ONCE); register("isOperational", IGNORE, NOTIFY_ONCE); register("isShared", IGNORE, NOTIFY_ONCE); register("unload", IGNORE, NOTIFY_ONCE); register("reload", IGNORE, NOTIFY_ONCE); register("uninstall", IGNORE, NOTIFY_ONCE); register("isUnloadable", IGNORE, NOTIFY_ONCE); // Load up any values stored in the config. persistent_warnings.addAll(Arrays.asList( COConfigurationManager.getStringListParameter(CONFIG_KEY).toArray())); } public static void call(String identifier, Object context) { call(identifier, context.getClass().getName()); } public static void call(String identifier, String context) { Integer behaviour = (Integer)behaviour_mapping.get(identifier); if (behaviour == null) { throw new IllegalArgumentException("unknown deprecated call identifier: " + identifier); } int b = behaviour.intValue(); if (b == IGNORE) {return;} boolean persistent_notify = b == NOTIFY_ONCE; boolean notify = b != DIE; boolean raise_error = (b == NOTIFY_AND_DIE || b == DIE); String persistent_id = context + ":" + identifier; /** * The second check is done to make sure that we only ever test * persistent warnings if they are registered as being persistent. * * Previously, the code just added the persistent warnings to the * instance warnings list, but that then stops any warning that * gone from persistent (once only) to instance (every startup). */ if (notify && !instance_warnings.contains(context) && (!persistent_notify || !persistent_warnings.contains(persistent_id)) ) { instance_warnings.add(context); // If it's not persistent, then we'll remove it from the persistent // warnings list (in case it used to be a persistent warning and has // been "upgraded" in the meantime). if (!persistent_notify && persistent_warnings.remove(persistent_id)) { COConfigurationManager.setParameter(CONFIG_KEY, new StringListImpl(persistent_warnings)); } synchronized (PluginDeprecation.class) { if (model == null) { final PluginInterface pi = PluginInitializer.getDefaultInterface(); model = pi.getUIManager().createBasicPluginViewModel(MessageText.getString("PluginDeprecation.view")); model.getStatus().setVisible(false); model.getProgress().setVisible(false); model.getActivity().setVisible(false); model.getLogArea().appendText( MessageText.getString("PluginDeprecation.log.start", new String[] { Constants.isCVSVersion() ? FORUM_BETA_LINK : FORUM_STABLE_LINK }) ); // Force it to be auto-opened. UIManagerListener uiml = new UIManagerListener() { public void UIAttached(UIInstance inst) { if (inst instanceof UISWTInstance) { ((UISWTInstance)inst).openView(model); pi.getUIManager().removeUIListener(this); } } public void UIDetached(UIInstance inst) {} }; pi.getUIManager().addUIListener(uiml); } String log_details = MessageText.getString( "PluginDeprecation.log.details", new String[] {identifier, context, Debug.getStackTrace(false, false)} ); model.getLogArea().appendText(log_details); if (channel == null) { channel = PluginInitializer.getDefaultInterface().getLogger().getChannel("PluginDeprecation"); } // Maybe it should be repeatable, we'll see.. channel.logAlert( LoggerChannel.LT_WARNING, MessageText.getString("PluginDeprecation.alert") ); Debug.out(new PluginDeprecationException("Deprecated plugin call - " + persistent_id).fillInStackTrace()); } if (persistent_notify) { persistent_warnings.add(persistent_id); COConfigurationManager.setParameter(CONFIG_KEY, new StringListImpl(persistent_warnings)); } } if (raise_error) { throw new PluginDeprecationException(persistent_id); } } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/deprecate/PluginDeprecationException.java0000644000175000017500000000232711046216520031705 0ustar adrianadrian/* * Created on 5 Aug 2008 * Created by Allan Crooks * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.pluginsimpl.local.deprecate; /** * @author Allan Crooks * */ public class PluginDeprecationException extends RuntimeException { public PluginDeprecationException() {} public PluginDeprecationException(String arg0) {super(arg0);} public PluginDeprecationException(Throwable arg0) {super(arg0);} public PluginDeprecationException(String arg0, Throwable arg1) {super(arg0, arg1);} } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ipc/0000755000175000017500000000000011310377624022371 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/local/ipc/IPCInterfaceImpl.java0000644000175000017500000001256411234011306026305 0ustar adrianadrian/* * Created on 02-May-2006 * Created by Damokles * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.local.ipc; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.gudy.azureus2.plugins.Plugin; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ipc.IPCException; import org.gudy.azureus2.plugins.ipc.IPCInterface; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; /** * @author Damokles * */ public class IPCInterfaceImpl implements IPCInterface { private Object target_use_accessor; private String plugin_class; private PluginInitializer plugin_initializer; /** * Constructor for real plugin based providers. Supports plugin unloading * * @param _plugin_initializer * @param _target */ public IPCInterfaceImpl( PluginInitializer _plugin_initializer, Plugin _target ) { plugin_initializer = _plugin_initializer; target_use_accessor = _target; plugin_class = _target.getClass().getName(); } /** * Constructor for non-plugin providers * @param _target */ public IPCInterfaceImpl( Object _target ) { target_use_accessor = _target; plugin_class = _target.getClass().getName(); } public boolean canInvoke( String methodName, Object[] params ) { try{ Object target = getTarget(); Method mtd = getMethod( target, methodName, params ); mtd.setAccessible( true ); if ( mtd != null ){ return( true ); } }catch( Throwable e ){ } return( false ); } public Object invoke( String methodName, Object[] params ) throws IPCException { Object target = getTarget(); try{ Method mtd = getMethod( target, methodName, params ); mtd.setAccessible( true ); return mtd.invoke(target, params); }catch( Throwable e ){ if ( e instanceof InvocationTargetException ){ if ( e.getCause() != null ){ e = e.getCause(); } } throw new IPCException(e); } } protected Method getMethod( Object target, String methodName, Object[] params ) throws Throwable { if ( params == null ){ params = new Object[0]; } Class[] paramTypes = new Class[params.length]; for (int i=0;i 0 ){ diagnostic_logger.setMaxFileSize((int)max_file_size ); } diagnostic_logger.enableTimeStamp( timestamp ); addListener( new LoggerChannelListener() { public void messageLogged( int type, String content ) { diagnostic_logger.log( content ); } public void messageLogged( String str, Throwable error ) { diagnostic_logger.log( str ); diagnostic_logger.log( error ); } }); } } private int LogTypePluginToCore(int pluginLogType) { switch (pluginLogType) { case LT_INFORMATION: return LogEvent.LT_INFORMATION; case LT_WARNING: return LogEvent.LT_WARNING; case LT_ERROR: return LogEvent.LT_ERROR; } return LogEvent.LT_INFORMATION; } private void notifyListeners(int log_type, String data) { for (int i = 0; i < listeners.size(); i++) { try { LoggerChannelListener l = (LoggerChannelListener) listeners.get(i); l.messageLogged(log_type, data); } catch (Throwable e) { Debug.printStackTrace(e); } } } private void notifyListeners(String listenersText, Throwable error) { for (int i = 0; i < listeners.size(); i++) { try { LoggerChannelListener l = (LoggerChannelListener) listeners.get(i); l.messageLogged(listenersText, error); } catch (Throwable e) { Debug.printStackTrace(e); } } } public void log(int log_type, String data) { notifyListeners(log_type, addTimeStamp(data)); if (isEnabled() && !no_output) { data = "[" + name + "] " + data; org.gudy.azureus2.core3.logging.Logger.log(new LogEvent(LOGID, LogTypePluginToCore(log_type), data)); } } public void log( String data ) { log( LT_INFORMATION, data ); } public void log(Object[] relatedTo, int log_type, String data) { String listenerData = data; if (relatedTo != null) { StringBuffer text = new StringBuffer(); for (int i = 0; i < relatedTo.length; i++) { Object obj = relatedTo[i]; if (obj == null) continue; if (i > 0) text.append("; "); if (obj instanceof LogRelation) { text.append(((LogRelation) obj).getRelationText()); } else { text.append("RelatedTo[") .append(obj.toString()) .append("]"); } } listenerData += "\t" + text.toString() + "] " + data; } notifyListeners(log_type, addTimeStamp(listenerData)); if (isEnabled() && !no_output) { data = "[" + name + "] " + data; org.gudy.azureus2.core3.logging.Logger.log(new LogEvent(relatedTo, LOGID, LogTypePluginToCore(log_type), data)); } } public void log(Object relatedTo, int log_type, String data) { log(new Object[] { relatedTo }, log_type, data); } public void log(Throwable error) { log("", error); } public void log(String str, Throwable error) { notifyListeners(str.equals("") ? "" : addTimeStamp(str), error); if (!no_output) { LogEvent event = new LogEvent(LOGID, "[" + name + "] " + str, error); org.gudy.azureus2.core3.logging.Logger.log(event); } } public void log(Object[] relatedTo, String str, Throwable error) { notifyListeners(str.equals("") ? "" : addTimeStamp(str), error); if (isEnabled() && !no_output) { str = "[" + name + "] " + str; org.gudy.azureus2.core3.logging.Logger.log(new LogEvent(relatedTo, LOGID, str, error)); } } public void log(Object relatedTo, String str, Throwable error) { log(new Object[] { relatedTo }, str, error); } public void log(Object[] relatedTo, String data) { log(relatedTo, LT_INFORMATION, data); } public void log(Object relatedTo, String data) { log(relatedTo, LT_INFORMATION, data); } // Alert Functions // =============== protected void logAlert(int alert_type, String message, boolean repeatable) { // output as log message to any listeners for (int i = 0; i < listeners.size(); i++) { try { ((LoggerChannelListener) listeners.get(i)).messageLogged(alert_type, addTimeStamp(message)); } catch (Throwable e) { Debug.printStackTrace(e); } } if (!no_output) { int at; switch (alert_type) { case LoggerChannel.LT_INFORMATION: { at = LogAlert.AT_INFORMATION; break; } case LoggerChannel.LT_WARNING: { at = LogAlert.AT_WARNING; break; } default: { at = LogAlert.AT_ERROR; break; } } org.gudy.azureus2.core3.logging.Logger.log(new LogAlert(repeatable, at, message)); } } public void logAlert( int alert_type, String message ) { logAlert( alert_type, message, false ); } public void logAlertRepeatable( int alert_type, String message ) { logAlert( alert_type, message, true ); } public void logAlert( String message, Throwable e ) { for (int i=0;i 3) { category = (String) bits.get(3); } plugin_ids.add(plugin_id); plugin_map.put(plugin_id.toLowerCase(MessageText.LOCALE_ENGLISH), new SFPluginDetailsImpl(this, plugin_id, version, cvs_version, name, category)); } } plugin_ids_loaded = true; plugin_ids_loaded_at = SystemTime.getCurrentTime(); }catch( Throwable e ){ Debug.printStackTrace( e ); throw( new SFPluginDetailsException( "Plugin list load failed", e )); } } protected void loadPluginDetails( SFPluginDetailsImpl details ) throws SFPluginDetailsException { try{ ResourceDownloader p_dl = rd_factory.create( new URL( site_prefix + "plugin_details.php?plugin=" + details.getId() + "&" + base_url_params )); p_dl = rd_factory.getRetryDownloader( p_dl, 5 ); p_dl.addListener( this ); HTMLPage plugin_page = HTMLPageFactory.loadPage( p_dl.download(), "UTF-8" ); if ( !processPluginPage( details, plugin_page )){ throw( new SFPluginDetailsException( "Plugin details load fails for '" + details.getId() + "': data not found" )); } }catch( Throwable e ){ Debug.printStackTrace( e ); throw( new SFPluginDetailsException( "Plugin details load fails", e )); } } protected boolean processPluginPage( SFPluginDetailsImpl details, HTMLPage page ) throws SFPluginDetailsException { HTMLTable[] tables = page.getTables(); // dumpTables("", tables ); return( processPluginPage( details, tables )); } protected boolean processPluginPage( SFPluginDetailsImpl details, HTMLTable[] tables ) throws SFPluginDetailsException { for (int i=0;i 1) { info_url = rows[9].getCells()[1].getContent(); } // System.out.println( "got plugin:" + plugin_name + "/" + plugin_version + "/" + plugin_download + "/" + plugin_auth ); details.setDetails( plugin_download, plugin_auth, plugin_cvs_download, rows[6].getCells()[0].getContent(), rows[9].getCells()[0].getContent(), info_url); return( true ); } } HTMLTable[] sub_tables = table.getTables(); boolean res = processPluginPage( details, sub_tables ); if( res ){ return( res ); } } return( false ); } protected void dumpTables( String indent, HTMLTable[] tables ) { for (int i=0;i RELOAD_MIN_TIME ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "SFPluginDetailsLoader: resetting values")); plugin_ids_loaded = false; plugin_ids = new ArrayList(); plugin_map = new HashMap(); }else{ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "SFPluginDetailsLoader: not resetting, " + "cache still valid")); } }finally{ this_mon.exit(); } } public void addListener( SFPluginDetailsLoaderListener l ) { listeners.add( l ); } public void removeListener( SFPluginDetailsLoaderListener l ) { listeners.remove(l); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsException.java0000644000175000017500000000235611012742402030130 0ustar adrianadrian/* * Created on 28-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.update.sf; /** * @author parg * */ public class SFPluginDetailsException extends Exception { public SFPluginDetailsException( String str ) { super(str); } public SFPluginDetailsException( String str, Throwable e ) { super(str, e); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoader.java0000644000175000017500000000273310373051046027405 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.update.sf; /** * @author parg * */ public interface SFPluginDetailsLoader { public String[] getPluginIDs() throws SFPluginDetailsException; public SFPluginDetails getPluginDetails( String name ) throws SFPluginDetailsException; public SFPluginDetails[] getPluginDetails() throws SFPluginDetailsException; public void reset(); public void addListener( SFPluginDetailsLoaderListener l ); public void removeListener( SFPluginDetailsLoaderListener l ); } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetails.java0000644000175000017500000000340410647027276026266 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.update.sf; /** * @author parg * */ public interface SFPluginDetails { public String getId(); public String getName(); public String getCategory(); /** * * @return null if version number unknown */ public String getVersion(); public String getDownloadURL() throws SFPluginDetailsException; public String getAuthor() throws SFPluginDetailsException; public String getCVSVersion() throws SFPluginDetailsException; public String getCVSDownloadURL() throws SFPluginDetailsException; public String getDescription() throws SFPluginDetailsException; public String getComment() throws SFPluginDetailsException; public String getRelativeURLBase(); /** * @return * * @since 3.0.1.7 */ String getInfoURL(); } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoaderFactory.java0000644000175000017500000000234710373051046030736 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.update.sf; /** * @author parg * */ import org.gudy.azureus2.pluginsimpl.update.sf.impl2.*; public class SFPluginDetailsLoaderFactory { public static SFPluginDetailsLoader getSingleton() { return( SFPluginDetailsLoaderImpl.getSingleton()); } } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoaderListener.java0000644000175000017500000000214610373051046031111 0ustar adrianadrian/* * Created on 29-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.update.sf; /** * @author parg * */ public interface SFPluginDetailsLoaderListener { public void log( String log ); } azureus-4.3.0.6/org/gudy/azureus2/pluginsimpl/update/PluginUpdatePlugin.java0000644000175000017500000013141511225222414026425 0ustar adrianadrian/* * Created on 28-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.pluginsimpl.update; /** * @author parg * */ import java.util.*; import java.util.zip.*; import java.net.URL; import java.io.*; import org.gudy.azureus2.core3.html.HTMLUtils; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.installer.PluginInstaller; import org.gudy.azureus2.plugins.installer.StandardPlugin; import org.gudy.azureus2.plugins.logging.*; import org.gudy.azureus2.plugins.update.*; import org.gudy.azureus2.plugins.utils.resourcedownloader.*; import org.gudy.azureus2.plugins.ui.*; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.plugins.ui.model.*; import org.gudy.azureus2.pluginsimpl.*; import org.gudy.azureus2.pluginsimpl.update.sf.*; import org.gudy.azureus2.update.CorePatchChecker; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; public class PluginUpdatePlugin implements Plugin { private static final String PLUGIN_CONFIGSECTION_ID = "plugins.update"; private static final String PLUGIN_RESOURCE_ID = "ConfigView.section.plugins.update"; public static final int RD_SIZE_RETRIES = 3; public static final int RD_SIZE_TIMEOUT = 10000; private PluginInterface plugin_interface; private LoggerChannel log; private boolean loader_listener_added; private String last_id_info = ""; public void initialize( PluginInterface _plugin_interface ) { plugin_interface = _plugin_interface; plugin_interface.getPluginProperties().setProperty( "plugin.version", "1.0" ); plugin_interface.getPluginProperties().setProperty( "plugin.name", "Plugin Updater" ); log = plugin_interface.getLogger().getChannel("Plugin Update"); UIManager ui_manager = plugin_interface.getUIManager(); final BasicPluginViewModel model = ui_manager.createBasicPluginViewModel( PLUGIN_RESOURCE_ID ); final PluginConfig plugin_config = plugin_interface.getPluginconfig(); boolean enabled = plugin_config.getPluginBooleanParameter( "enable.update", true ); model.setConfigSectionID(PLUGIN_CONFIGSECTION_ID); model.getStatus().setText( enabled?"Running":"Optional checks disabled" ); model.getActivity().setVisible( false ); model.getProgress().setVisible( false ); log.addListener( new LoggerChannelListener() { public void messageLogged( int type, String message ) { model.getLogArea().appendText( message+"\n"); } public void messageLogged( String str, Throwable error ) { model.getLogArea().appendText( error.toString()+"\n"); } }); BasicPluginConfigModel config = ui_manager.createBasicPluginConfigModel(ConfigSection.SECTION_PLUGINS, PLUGIN_CONFIGSECTION_ID); config.addBooleanParameter2( "enable.update", "Plugin.pluginupdate.enablecheck", true ); plugin_interface.addEventListener( new PluginEventListener() { public void handleEvent( PluginEvent ev ) { if ( ev.getType() == PluginEvent.PEV_ALL_PLUGINS_INITIALISED ){ plugin_interface.removeEventListener( this ); initComplete( plugin_config ); } } }); } protected void initComplete( final PluginConfig plugin_config ) { UpdateManager update_manager = plugin_interface.getUpdateManager(); update_manager.addListener( new UpdateManagerListener() { public void checkInstanceCreated( UpdateCheckInstance inst ) { SFPluginDetailsLoaderFactory.getSingleton().reset(); } }); final PluginManager plugin_manager = plugin_interface.getPluginManager(); PluginInterface[] plugins = plugin_manager.getPlugins(); int mandatory_count = 0; int non_mandatory_count = 0; for (int i=0;i 0 ){ // sf cvs version ALWAYS ends in _CVS sf_plugin_version = sf_cvs_version; sf_comp_version = sf_plugin_version.substring(0,sf_plugin_version.length()-4); } } if ( sf_comp_version.length() == 0 || !Character.isDigit(sf_comp_version.charAt(0))){ log.log( LoggerChannel.LT_INFORMATION, "Skipping " + plugin_id + " as no valid version to check"); continue; } // System.out.println("comp version = " + sf_comp_version ); int comp = PluginUtils.comparePluginVersions( az_plugin_version, sf_comp_version ); // if they're the same version and latest is CVS then stick a _CVS on // the end of current to avoid confusion log.log( LoggerChannel.LT_INFORMATION, " Current: " + az_plugin_version + (comp==0&&sf_plugin_version.endsWith( "_CVS")?"_CVS":"")+ ", Latest: " + sf_plugin_version + (pi_version_info==null?"":" [" + pi_version_info + "]")); checker.reportProgress( " current=" + az_plugin_version + (comp==0&&sf_plugin_version.endsWith( "_CVS")?"_CVS":"") + ", latest=" + sf_plugin_version ); if ( comp < 0 && ! ( pi_being_checked.getPlugin() instanceof UpdatableComponent)){ // only update if newer verison + plugin itself doesn't handle // the update String sf_plugin_download = details.getDownloadURL(); if ( az_cvs ){ String sf_cvs_version = details.getCVSVersion(); if ( sf_cvs_version.length() > 0 ){ sf_plugin_download = details.getCVSDownloadURL(); } } log.log( LoggerChannel.LT_INFORMATION, " Description:" ); List update_desc = new ArrayList(); List desc_lines = HTMLUtils.convertHTMLToText( "", details.getDescription()); logMultiLine( " ", desc_lines ); update_desc.addAll( desc_lines ); log.log( LoggerChannel.LT_INFORMATION, " Comment:" ); List comment_lines = HTMLUtils.convertHTMLToText( " ", details.getComment()); logMultiLine( " ", comment_lines ); update_desc.addAll( comment_lines ); String msg = "A newer version (version " + sf_plugin_version + ") of plugin '" + plugin_id + "' " + (plugin_names.length()==0?"":"(" + plugin_names + ") " ) + "is available. "; log.log( LoggerChannel.LT_INFORMATION, "" ); log.log( LoggerChannel.LT_INFORMATION, " " + msg + "Download from "+ sf_plugin_download); ResourceDownloaderFactory rdf = plugin_interface.getUtilities().getResourceDownloaderFactory(); ResourceDownloader direct_rdl = rdf.create( new URL( sf_plugin_download )); // work out what the torrent download will be, if it exists // sf_plugin_download will be something like ../plugins/safepeer_2.4.zip // torrent is safepeer_2.4.zip.torrent String torrent_download = Constants.AELITIS_TORRENTS; int slash_pos = sf_plugin_download.lastIndexOf("/"); if ( slash_pos == -1 ){ torrent_download += sf_plugin_download; }else{ torrent_download += sf_plugin_download.substring( slash_pos + 1 ); } torrent_download += ".torrent"; ResourceDownloader torrent_rdl = rdf.create( new URL( torrent_download )); torrent_rdl = rdf.getSuffixBasedDownloader( torrent_rdl ); // create an alternate downloader with torrent attempt first ResourceDownloader alternate_rdl = rdf.getAlternateDownloader( new ResourceDownloader[]{ torrent_rdl, direct_rdl }); // get size so it is cached rdf.getTimeoutDownloader(rdf.getRetryDownloader(alternate_rdl,RD_SIZE_RETRIES),RD_SIZE_TIMEOUT).getSize(); String[] update_d = new String[update_desc.size()]; update_desc.toArray( update_d ); num_updates_found++; // see if unloadable boolean plugin_unloadable = true; for (int j=0;j 1 defined boolean unloadable, boolean is_jar, // false -> zip String version, InputStream data, boolean verify ) { log.log( LoggerChannel.LT_INFORMATION, "Installing plugin '" + update.getName() + "', version " + version ); String target_version = version.endsWith("_CVS")?version.substring(0,version.length()-4):version; UpdateInstaller installer = null; try{ data = update.verifyData( data, verify ); log.log( " Data verification stage complete" ); boolean update_txt_found = false; String plugin_dir_name = plugin.getPluginDirectoryName(); if ( plugin_dir_name == null || plugin_dir_name.length() == 0 ){ // update to a built-in plugin log.log( LoggerChannel.LT_INFORMATION, " This is a built-in plugin, updating core" ); CorePatchChecker.patchAzureus2( update.getCheckInstance(), data, plugin.getPluginID() + "_" + version, log ); // always need to restart for this update.setRestartRequired( Update.RESTART_REQUIRED_YES ); }else{ final File plugin_dir = new File( plugin_dir_name ); final File user_dir = new File( plugin_interface.getUtilities().getAzureusUserDir()); final File prog_dir = new File( plugin_interface.getUtilities().getAzureusProgramDir()); // .jar files get copied straight in with the right version number // .zip files need to be unzipped. There are various possibilities for // target dir depending on the contents of the zip file. Basically we // need to remove any zip paths to ensure it ends up in the right place // There's also the issue of overwriting stuff like "plugin.properties" // and any other config files.... boolean force_indirect_install = false; // for windows Vista we may not have write access to the plugin directory and have // to use an installer + restart to copy the files (as the restart can elevate // permissions) if ( Constants.isWindowsVistaOrHigher ){ // test with .dll as this will fail write to virtual-store as required File test_file = new File( plugin_dir, "_aztest45.dll" ); boolean ok = false; try{ if ( test_file.exists()){ test_file.delete(); } FileOutputStream os = new FileOutputStream(test_file); os.write(32); os.close(); ok = test_file.delete(); }catch( Throwable e ){ } if ( !ok ){ log.log( "Can't write directly to the plugin directroy, installing indirectly" ); force_indirect_install = true; } } File target_plugin_dir; File target_prog_dir; File target_user_dir; if ( force_indirect_install ){ File temp_dir = AETemporaryFileHandler.createTempDir(); target_plugin_dir = new File( temp_dir, "plugin" ); target_user_dir = new File( temp_dir, "user" ); target_prog_dir = new File( temp_dir, "prog" ); target_plugin_dir.mkdirs(); target_user_dir.mkdirs(); target_prog_dir.mkdirs(); installer = update.getCheckInstance().createInstaller(); update.setRestartRequired( Update.RESTART_REQUIRED_YES ); }else{ target_plugin_dir = plugin_dir; target_user_dir = user_dir; target_prog_dir = prog_dir; } File target_jar_zip = new File( target_plugin_dir, plugin.getPluginID() + "_" + target_version + (is_jar?".jar":".zip")); FileUtil.copyFile( data, new FileOutputStream(target_jar_zip)); if ( !is_jar ){ ZipInputStream zis = new ZipInputStream( new BufferedInputStream( new FileInputStream( target_jar_zip ) )); // first look for a common dir prefix and platform-specific stuff String common_prefix = null; String selected_platform = null; List selected_sub_platforms = new ArrayList(); try{ while( true ){ ZipEntry entry = zis.getNextEntry(); if ( entry == null ){ break; } String name = entry.getName(); if ( !( name.equals( "azureus.sig" ) || name.endsWith("/"))){ if ( common_prefix == null ){ common_prefix = name; }else{ int len = 0; for (int i=0;i 1 ){ String selected_sub_platform = (String) update.getDecision( UpdateManagerDecisionListener.DT_STRING_ARRAY_TO_STRING, "Select Platform", "Multiple platform options exist for this plugin, please select required one", options ); if ( selected_sub_platform == null ){ throw( new Exception( "Valid sub-platform selection not selected" )); }else{ selected_platform += "_" + selected_sub_platform; log.log( LoggerChannel.LT_INFORMATION, "platform is '" + selected_platform +"'" ); } } } if ( common_prefix != null ){ int pos = common_prefix.lastIndexOf("/"); if ( pos == -1 ){ common_prefix = ""; }else{ common_prefix = common_prefix.substring(0,pos+1); } zis = new ZipInputStream( new BufferedInputStream( new FileInputStream( target_jar_zip ) )); try{ while( true ){ ZipEntry entry = zis.getNextEntry(); if ( entry == null ){ break; } String name = entry.getName(); OutputStream entry_os = null; File origin = null; File initial_target = null; File final_target = null; boolean is_plugin_properties = false; try{ if ( name.length() >= common_prefix.length() && !( name.equals( "azureus.sig") || name.endsWith("/"))){ boolean skip_file = false; String file_name = entry.getName().substring( common_prefix.length()); if ( selected_platform != null ){ if ( file_name.indexOf( "platform/" ) != -1 ){ String bit_to_remove = "platform/" + selected_platform; int pp = file_name.indexOf( bit_to_remove ); if ( pp != -1 ){ file_name = file_name.substring(0,pp) + file_name.substring(pp+bit_to_remove.length()+1); }else{ // stuff from other platform, ignore it skip_file = true; } } } File install_root; File origin_root; if ( file_name.startsWith( "shared/lib" )){ // updating shared resources, force restart update.setRestartRequired( Update.RESTART_REQUIRED_YES ); // indicate that we can't go ahead and load the plugin // later in the code unloadable = false; if ( plugin.getPluginState().isShared()){ origin_root = prog_dir; install_root = target_prog_dir; }else{ origin_root = user_dir; install_root = target_user_dir; } }else{ origin_root = plugin_dir; install_root = target_plugin_dir; } origin = new File( origin_root, file_name ); initial_target = new File( install_root, file_name ); final_target = initial_target; if ( origin.exists()){ if ( file_name.indexOf( '/' ) == -1 && ( file_name.toLowerCase(MessageText.LOCALE_ENGLISH).endsWith(".properties") || file_name.toLowerCase(MessageText.LOCALE_ENGLISH).endsWith(".config" ))){ // don't trash properties and config files in root as users may well // have modified them is_plugin_properties = file_name.toLowerCase(MessageText.LOCALE_ENGLISH).equals("plugin.properties"); String old_file_name = file_name; file_name = file_name + "_" + target_version; final_target = new File( install_root, file_name ); log.log( LoggerChannel.LT_INFORMATION, "saving new file '" + old_file_name + "'as '" + file_name +"'" ); }else{ // if it is a versioned artifact then we don't need to do anything as the update contains // the same version of the file if ( isVersioned( file_name )){ log.log( LoggerChannel.LT_INFORMATION, "Version '" + file_name +"' already present, skipping" ); skip_file = true; }else{ log.log( LoggerChannel.LT_INFORMATION, "overwriting '" + file_name +"'" ); File backup = new File( origin.getParentFile(), origin.getName() + ".bak" ); // back up just in case if ( force_indirect_install ){ if ( backup.exists()){ installer.addRemoveAction( backup.getAbsolutePath()); } installer.addMoveAction( origin.getAbsolutePath(), backup.getAbsolutePath()); }else{ if ( backup.exists()){ backup.delete(); } if ( !initial_target.renameTo( backup )){ log.log( LoggerChannel.LT_INFORMATION, " failed to backup '" + file_name +"', deferring until restart" ); if ( installer == null ){ update.setRestartRequired( Update.RESTART_REQUIRED_YES ); installer = update.getCheckInstance().createInstaller(); } File tmp = new File( initial_target.getParentFile(), initial_target.getName() + ".tmp" ); tmp.delete(); installer.addMoveAction( tmp.getAbsolutePath(), initial_target.getAbsolutePath()); final_target = tmp; } } } } } if ( !skip_file ){ FileUtil.mkdirs(final_target.getParentFile()); entry_os = new FileOutputStream( final_target ); } } byte[] buffer = new byte[65536]; while( true ){ int len = zis.read( buffer ); if ( len <= 0 ){ break; } if ( entry_os != null ){ entry_os.write( buffer, 0, len ); } } }finally{ if ( entry_os != null ){ entry_os.close(); } } if ( is_plugin_properties ){ // we've got to modify the plugin.version in the existing // file (if it exists) otherwise we keep downloading the new // version! Or, if the key doesn't exist, add it! // if we were smarter we could merge values from the // old one into the new one, however this is too much like // hard work // hmm, we really need to at least merge in the new // predefined values such as // plugin.name, plugin.names // plugin.class, plugin.classes // plugin.langfile Properties old_props = new Properties(); Properties new_props = new Properties(); List props_to_delete = new ArrayList(); Map props_to_replace = new HashMap(); Map props_to_insert = new HashMap(); try{ FileInputStream fis = new FileInputStream( origin ); old_props.load( fis ); try{ fis.close(); }catch( Throwable e ){ } fis = new FileInputStream( final_target ); new_props.load( fis ); try{ fis.close(); }catch( Throwable e ){ } }catch( Throwable e ){ Debug.printStackTrace( e ); } new_props.put( "plugin.version", target_version ); String[] prop_names = { "plugin.name", "plugin.names", "plugin.class", "plugin.classes", "plugin.version", "plugin.langfile" }; for (int z=0;z 1 defined log.log( "... initialisation complete." ); } } Boolean b_disable = (Boolean)update.getCheckInstance().getProperty( UpdateCheckInstance.PT_UI_DISABLE_ON_SUCCESS_SLIDEY ); if ( update_txt_found || b_disable == null || !b_disable ){ String msg = "Version " + version + " of plugin '" + update.getName() + "' " + "installed successfully"; if ( update_txt_found ){ msg += " - See update log for details"; } log.logAlertRepeatable( update_txt_found?LoggerChannel.LT_WARNING:LoggerChannel.LT_INFORMATION, msg ); } }catch( Throwable e ){ String msg = "Version " + version + " of plugin '" + update.getName() + "' " + "failed to install - " + (e.getMessage()); log.logAlertRepeatable( LoggerChannel.LT_ERROR, msg ); }finally{ update.complete(); } } protected void addInstallationActions( UpdateInstaller installer, File from_file, File to_file ) throws UpdateException { if ( from_file.isDirectory()){ File[] files = from_file.listFiles(); if ( files != null ){ for (int i=0;i_. // where version is mixture of digits and .s int pos = name.lastIndexOf('_'); if ( pos == -1 || name.endsWith("_")){ return( false ); } // remove everything up to _ String rem = name.substring(pos+1); pos = rem.lastIndexOf( '.' ); // remove extension (e.g. .jar) if ( pos != -1 ){ rem = rem.substring(0,pos); } for (int i=0;i version_1 lower, 0 = same, +ve -> version_1 higher */ public static int comparePluginVersions( String version_1, String version_2 ) { return( Constants.compareVersions( version_1, version_2 )); } } azureus-4.3.0.6/org/gudy/azureus2/cl/0000755000175000017500000000000011310377634016560 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/cl/Main.java0000644000175000017500000001127010712572662020313 0ustar adrianadrian/* * Created on 11 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.cl; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.download.*; /** * @author Olivier * */ public class Main { public static void main(String args[]) { if (!parseParameters(args)) usage(); String torrentFile = args[args.length - 2]; String path = args[args.length - 1]; DownloadManager manager = DownloadManagerFactory.create(null, null, torrentFile, path, null, DownloadManager.STATE_WAITING, false, false, null, null ); manager.initialize(); while (true) { StringBuffer buf = new StringBuffer(); int state = manager.getState(); switch (state) { case DownloadManager.STATE_WAITING : buf.append("Waiting"); break; case DownloadManager.STATE_ALLOCATING : buf.append("Allocating"); break; case DownloadManager.STATE_CHECKING : buf.append("Checking"); break; case DownloadManager.STATE_READY : buf.append("Ready"); manager.startDownload(); break; case DownloadManager.STATE_DOWNLOADING : buf.append("Downloading"); break; case DownloadManager.STATE_SEEDING : buf.append("Seeding"); break; case DownloadManager.STATE_STOPPED : buf.append("Stopped"); break; case DownloadManager.STATE_ERROR : buf.append("Error : " + manager.getErrorDetails()); break; } buf.append(" C:"); DownloadManagerStats stats = manager.getStats(); int completed = stats.getCompleted(); buf.append(completed/10); buf.append('.'); buf.append(completed%10); buf.append('%'); buf.append(" S:"); buf.append(manager.getNbSeeds()); buf.append(" P:"); buf.append(manager.getNbPeers()); buf.append(" D:"); buf.append(DisplayFormatters.formatDownloaded(stats)); buf.append(" U:"); buf.append(DisplayFormatters.formatByteCountToKiBEtc(stats.getTotalDataBytesSent())); buf.append(" DS:"); buf.append(DisplayFormatters.formatByteCountToKiBEtcPerSec(stats.getDataReceiveRate())); buf.append(" US:"); buf.append(DisplayFormatters.formatByteCountToKiBEtcPerSec(stats.getDataSendRate())); buf.append(" T:"); buf.append(manager.getTrackerStatus()); while(buf.length() < 80) { buf.append(' '); } System.out.print("\r".concat(buf.toString())); if(state == DownloadManager.STATE_ERROR) return; try { Thread.sleep(500); } catch (Exception e) { //Do nothing } } } private static boolean parseParameters(String args[]) { if (args.length < 2) return false; if (args.length == 2) return true; if ((args.length % 2) != 0) return false; try { for (int i = 0; i < args.length - 2; i += 2) { String param = args[i]; String value = args[i + 1]; if (param.equals("--maxUploads")) COConfigurationManager.setParameter("Max Uploads", Integer.parseInt(value)); else if (param.equals("--maxSpeed")) COConfigurationManager.setParameter("Max Upload Speed KBs", Integer.parseInt(value)); else return false; } return true; } catch (Exception e) { return false; } } private static void usage() { System.out.println("Usage : java org.gudy.azureus2.cl.Main [parameters] \"file.torrent\" \"save path\""); System.out.println("--maxUploads :\t\t Max number of simultaneous uploads"); System.out.println("--maxSpeed :\t\t Max upload speed in KBytes/sec"); SESecurityManager.exitVM(0); } } azureus-4.3.0.6/org/gudy/azureus2/ui/0000755000175000017500000000000011310377516016576 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/splash/0000755000175000017500000000000011310377436020071 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/splash/splash_frog.jpg0000644000175000017500000003260611137765210023107 0ustar adrianadrianJFIFddDuckyPAdobed          !Qa1A"Vq2uBRb#t&r35E6Scs$4%CDTdUe' !1AQaq"2BR#r3$ ?Kz[fsX/-^yWUnK|JJI6.緾<ܗKXKy%V<ǀ{{{=tՏ=_Ǟr]/co|x.緾<ܗKXKy%V<ǀ{{{=tՏ=_Ǟr]/co|x.緾<ܗKXKy%V<ǀ{{{=tՏ=_Ǟr]/co|x.緾<ܗKXKy%V<ǀ{{{=tՏ=_Ǟr]/co|x.緾<ܗKXKy%V<ǀ{{{=tՏ=_Ǟr]/co|x.緾<ܗKXKy%V<ǀ{{{=tՏ=_Ǟr]/co|x.緾<ܗKXKy%V<ǀ{{{=tՏ=_Ǟr]/co|x Vt8+V:w{^wd@MTƓTG 5tL羛8 q8@ q8@ q8@ q8@ q8@ q8@ q8@ j/ԍeGѤpۢʧL~y鳉Ix<x<x<x<x<x<x<-U>z49 _*5eN$m@xP@xP@xP@xP@xP@xP@xP@xP@xP@xP@xP@xP@xP@xP]t^!8zz8t龜3'6s8p8p8p8p8p8p8p c[+3W}xy:eN~铀ٵ!!RT*@ HRT*@ H{M:Y$j K+Oc 2IlS6EfYڭwlpS#s>e[ܣzWsC-tn=U( g4:~ n>bۖfHgUrldzϬn~uzS~jdGSL;tm܈V ݜElR0'kyƶtX/"FXJDwY+hhQp2 E}3eU{y޻tfg}130gB:VGé6ڂ=5UG!22rycmm~9)}.xKwԆ *@ HRT*@ HRT*@ HRT*@ HRT*@ ε2Mտb<<^:uK        *7ſ[o:cmtm] HAR&;6 jFni$V=`1..>.AM*EK45*ԥ)[LiDR/t=U/JB%Z z'j0=T*SExD$ω Vc6ob~:;Y85ge193                 1hY ӧz{KH.p8p渓\V]"~n;1aqDGTVUB̿+GaVGmT*9<썑> zR!*פKۓOgE}umi A_8)p쳇wqp8p8p8p85~꿱`?D #/*&PT( BPT( BPT( BPúZUIN suJ)?Y Z43َ?T>чdLϬ]OwrEK<ڥJ3Lrض"#t9VYf^{[P T)pkpbh.M̷Rp(`u!L/Dz21bH^8P* @P* @P* @P* @P* @P* @P* @P* @P*޲? W=.I=\Fwqwqwqwqwqwqwq/[,ML jUħA{"]Ē!,M6[=k=Cm;gEikp T'pkpynSV#,vveW7T"Iy2Q[ƙ֚lۇ]5GzEu)'qqwqwqwqwqwqwqwqwqwqwqwqwqwqwqwqwqwޱW쎪}A cOz\638p=bн֙3;-mkQF]Rd,ϮV:z{k|?wsVIj%9P~d5B~oHKOߧ5o;~L{w7]%IfYE[MJRm-DRIpzNV'Kqw ViKTg1z{d΄3$LpjuiݒeN[qY;3ӭ֒|aqrʯ ]Ês-}etwGd;o+h4ᳳ|l ,8p8p8p8p5j/b sNҽ*`h BPT( BPT( BP--מњ˔siXU^*U&(dd_zc^Y~/Zs]ns.X'*ޒzU'p+^J8^nbOm?Qb1'C3/U#c6ݺmF=3ْtODHKB]"Q}ݣLQj @P*PkOz{u]/wĥYE*I(IBϊh9YI%ƴ%%ER2HHi-/ouf!22zp@0W9Y+Uqugs) J[MII@k}GG+sjv($TI5$gJl&uU9- %*STiQ,ФH$i#N#m3Lt3Zm$\[B *UOi˼@P* @P* @P* @PcdG@<@=)U4:     F@síT+\m^̸i~Ww0e+u9?W'Vϭg$˼ɑeΧ [PEmj:NN_ȍWZ _gc׋޸+x1[iX|$#4L%W2ԩ*?"'xئ&|ڭufȎƈga'*ޒzU'h+^JO`s:8:|EqI2, Y{3x-tDwϋ=>Lpcn#2ʤ- xViZF!I:21] }6ό;YE:_= Y,tKI', :yrc˧ӳU6Ёt4X]H3E`39YY2P }4w5eT+tU$-al[Ool pأc+[hʉJcNđ}#8}GVS^X/,kU4r{ 39?U-K`5QzǍ ˜j˸9,:;*Um7{=Nc)u9WH       dQAt`_zTFwqwqwqwqwqŸIԮewD)x\2uB_sFUuD}WSF};!Y zJ* [QJkPT{~ t56/b퓍\.Z|Iھv`(7IŒ1;GI&R0 #g"Q P~ n/P}{{>FO?m{'_^ݏXS;|z_t'r"wtt!{g5Id\U}:˖OjOmo /㸍ДDix]J=AC+XDI8eVШ[M;;;;;;;; {V즦{ F & JH5@*P TI~%~/4K#hqnZɊTW2"7i.9NdS.O/MF1#{I\ҬUGSRu33f:E6C_#aJ[q [p([pkHH5K4LqD3R$L&b"Z蛦ni,L&җwV-nd%fJ2Ӹqu_4D͑;=tb)>syqWymH/r5E"M*%`c≬SF;͹)1Isو~F9MXLYIW&5)R]Ne8lSta7}7DM[_t6v)b8 IH2QV!f]/D0CIfܬͻgusɧ)7M>>mA|)UG(fNk:G&nD5n5zq6۲DҞw4,E}WVgfI4>}ExE;l|+Q(sII~Mv]G}}qplwu3CXzEE+M)$|^kUmhEgu5˴iTF赪:ϜjۋOZwyQ]h =:?\rbDiRsЃNDGJSflYaimckEmg!%%$zjYkrܿBXYKr'-%R , 7ZG~icȎ/nmӝ;Y"UBt)qEJbS _ }4ܚ2r=$i/n{?݅L`w{i_DO(BT':Ok{DA220&xJԫH5Bk3X8vqQ\$x@4A4;ܭܺxL3 %adCU8ޤD$)IP @*P T@*P T?WS}{ G }SBJH8p|Jt5>5?:Zw7!) Ң{`\fُݓߔse p1ץ"zJoI&oI oJB ¯Co]Vtf.ˣI>[t~e?T= ,|jrc˹nDPsPA{mQ5# RROy8纝)Ŏcfb]ܑ$OE6MMy|W)Q Yd"c$RfL, #R6#]1qe0XO|mG@GDw[Y)w\M#3gx[feld"|j_⡟Q>ubdxmY3.a>3HybĘ0KlH*%6!L5/9٦}4S;mMvB>5ΎDQ$Il)JFD5Fҡ.{k8Uxk듳f䵑7f\WMQo>JꦗE~+;I9^R-ϔ]˱O\:;许W bMޞ̩ e<"*- #Ja?4`tl [ӳV2"Ur%![1JOVFH-ӘRV xT2JK#Bnu&}v,_Styxx/e]?l~pnHDBS c"$IvPry<xFsM\^bN;eԢ^Y!'M;6֦_t6^?rxm?}2P[qH8,AQݵ-\Ý͑ZH;~za.)J4^RSqhIVVا)uVg5#6ɮ+2VV̷;kŜ PPփ$R#(h[>~#nV6tinsnUԄ2Gڳ>5sBc=!&ݖ^p5KNRt-QL̀o'L,WcU bZG;giuZ$Sc"76(5'B/?MӨ]FRĨ2(GP[MnWoVx/%T)<\9 HI#>ٚ7DI lr-+}xnP 4M&DT E:r6V^[硂W+KSQGJf>WXll\}cKA."K)Sj;HMqy֙;8WRUD()2MOiH <x<]/ @4U4N9@go-----------5SSW~Ax̜'˺EG%U&F!6')|3o /u.kR]ara\KV.H#JuS̭wLwKPil!2=zJ!V={n莯B./5-,2*Gqh.T$&c5IY77i'w;lz|ĎS[5zUJDdo]+E1yLdD6()nŽ{ƶzGvf Sttr s@9h4s@9h4L]j*pi5ܑm2 /Ē$>Ǒm>ѴNɢ6]ֶз+ZnSJq׶hD| tm'1ꢸuZL'cc e8{HJKiMiwy'LVњ>Z%5b[Ko[FmMl> ݋h%Rm1U6]F_)F\Yu>Q?26t'[N|+^Vr"(RZJY$D -6[M7]OeC@ oӘhR[5)s!~YnNOd⵹Yڬ3.cg. au-$Wͳ>mOՏZYY/R>U8I9Еj"3*-%]7>82p1a4ӭg9Mu&|&ZI 4"*MH33U2Ե1[7.;c彲zI,tOsy8ώ q8@ q8@ q8@ q8@ Q(Wg]}Uh5Jb?$e`0s9`0s9RTJFGaQч{D,-ZNq[!{Tn8bdQls9`0s9`0s9`0s9`0s9uf~>C/YQ)*P T@*P T@*P T@*P T@*P T@*P T@*P T_\ oiaix<x<x<x<x<x<x<Vuuf Cqj[ No7,PPqATaPqATaPqATaPqATaPqATaPqATaPqATaPqATaPqATaPqATaPqATaPqATaPqATaPqATEeqj+ Κs7,Hɜ 8p8p8p8p8p8p8pҿo̧5b?$d#s_o5wL#%}Kk򫋉9pBITj3QT}BTd[ i;B21ŏ$YȘ賢HԨ]n2:-Qx5vDSJ8UT=VsX>+"W DH(̤J$4fԋ` 6b)Xgq(d.L1g}4"K<*U;J= .ⵕv&IAEU.$B3l#0A$[mo,6Em%4L^MTjTASٴ?gAͽVIQ)ԳY.I䲄&5u.͠$%aT6w9\J+o2 K nZL~#UM{ܹ{D]WIId*0}8eђ;KIQԕLR.#EHHQ'v'3$cNUƄD)Fdj"rLʡjlMz&حᓝW"K[F 3:eVIE$U*W[k/&S$O-0|sWw;oXb-36kveC\MdJ%$(} 2*;sm&BԎ]2(JS-⹼̭[bU̖j9 w kJJS"uh@$1(2ݫ!{q&/dL 3QFJju5,ԳQ6SbnFϓZjdjiTRf3}s[CyZA'N&KjCn3椔FDd~cWQ^C dLO,l9_,̋áT̊fC E:![nVK%$$ #BH3f`"јT^& n*5.Qֈ%ƤkUU{{(F +;3U%D1/ɖ̩? 25f#ictH"km ) Gi5*dpy;dIښJ5$uuOq ?[D̫{9y.WIȋ͆iK 4U68R5ń˥se$2%H&%%DVU3:3?uݾzgHl@=l@=l@=l@=l@=l@=l@=l@=l@=l@=l@=l@=l@=l@=s3'?4]kazureus-4.3.0.6/org/gudy/azureus2/ui/web2/0000755000175000017500000000000011310377516017435 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web2/stages/0000755000175000017500000000000011310377516020723 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web2/stages/hdapi/0000755000175000017500000000000011310377516022010 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web2/stages/hdapi/impl/0000755000175000017500000000000011310377516022751 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web2/stages/cache/0000755000175000017500000000000011310377516021766 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web2/stages/http/0000755000175000017500000000000011310377516021702 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web2/stages/net/0000755000175000017500000000000011310377516021511 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web2/util/0000755000175000017500000000000011310377516020412 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web2/http/0000755000175000017500000000000011310377516020414 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web2/http/parser/0000755000175000017500000000000011310377516021710 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web2/http/util/0000755000175000017500000000000011310377516021371 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web2/http/request/0000755000175000017500000000000011310377516022104 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web2/http/response/0000755000175000017500000000000011310377516022252 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/webplugin/0000755000175000017500000000000011310377640020570 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/webplugin/WebPlugin.java0000644000175000017500000007152011306167326023337 0ustar adrianadrian/* * File : WebPlugin.java * Created : 23-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.webplugin; /** * @author parg * */ import java.io.*; import java.util.*; import java.net.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.logging.*; import org.gudy.azureus2.plugins.ipfilter.*; import org.gudy.azureus2.plugins.tracker.*; import org.gudy.azureus2.plugins.tracker.web.*; import org.gudy.azureus2.plugins.ui.*; import org.gudy.azureus2.plugins.ui.config.*; import org.gudy.azureus2.plugins.ui.model.*; import com.aelitis.azureus.core.pairing.PairedService; import com.aelitis.azureus.core.pairing.PairingConnectionData; import com.aelitis.azureus.core.pairing.PairingManager; import com.aelitis.azureus.core.pairing.PairingManagerFactory; import com.aelitis.azureus.core.pairing.PairingManagerListener; import com.aelitis.azureus.plugins.upnp.UPnPPlugin; public class WebPlugin implements Plugin, TrackerWebPageGenerator { public static final String PR_ENABLE = "Enable"; // Boolean public static final String PR_DISABLABLE = "Disablable"; // Boolean public static final String PR_PORT = "Port"; // Integer public static final String PR_BIND_IP = "Bind IP"; // String public static final String PR_ROOT_RESOURCE = "Root Resource"; // String public static final String PR_ROOT_DIR = "Root Dir"; // String public static final String PR_ACCESS = "Access"; // String public static final String PR_LOG = "DefaultLoggerChannel"; // LoggerChannel public static final String PR_CONFIG_MODEL_PARAMS = "DefaultConfigModelParams"; // String[] params to use when creating config model public static final String PR_VIEW_MODEL = "DefaultViewModel"; // BasicPluginViewModel public static final String PR_HIDE_RESOURCE_CONFIG = "DefaultHideResourceConfig"; // Boolean public static final String PR_ENABLE_KEEP_ALIVE = "DefaultEnableKeepAlive"; // Boolean public static final String PR_PAIRING_SID = "PairingSID"; // String public static final String PROPERTIES_MIGRATED = "Properties Migrated"; public static final String CONFIG_MIGRATED = "Config Migrated"; public static final String CONFIG_PASSWORD_ENABLE = "Password Enable"; public static final boolean CONFIG_PASSWORD_ENABLE_DEFAULT = false; public static final String CONFIG_PAIRING_ENABLE = "Pairing Enable"; public static final boolean CONFIG_PAIRING_ENABLE_DEFAULT = true; public static final String CONFIG_ENABLE = PR_ENABLE; public boolean CONFIG_ENABLE_DEFAULT = true; public static final String CONFIG_USER = "User"; public static final String CONFIG_USER_DEFAULT = ""; public static final String CONFIG_PASSWORD = "Password"; public static final byte[] CONFIG_PASSWORD_DEFAULT = {}; public static final String CONFIG_PORT = PR_PORT; public int CONFIG_PORT_DEFAULT = 8089; public static final String CONFIG_BIND_IP = PR_BIND_IP; public String CONFIG_BIND_IP_DEFAULT = ""; public static final String CONFIG_PROTOCOL = "Protocol"; public static final String CONFIG_PROTOCOL_DEFAULT = "HTTP"; public static final String CONFIG_UPNP_ENABLE = "UPnP Enable"; public static final boolean CONFIG_UPNP_ENABLE_DEFAULT = true; public static final String CONFIG_HOME_PAGE = "Home Page"; public static final String CONFIG_HOME_PAGE_DEFAULT = "index.html"; public static final String CONFIG_ROOT_DIR = PR_ROOT_DIR; public String CONFIG_ROOT_DIR_DEFAULT = ""; public static final String CONFIG_ROOT_RESOURCE = PR_ROOT_RESOURCE; public String CONFIG_ROOT_RESOURCE_DEFAULT = ""; public static final String CONFIG_MODE = "Mode"; public static final String CONFIG_MODE_FULL = "full"; public static final String CONFIG_MODE_DEFAULT = CONFIG_MODE_FULL; public static final String CONFIG_ACCESS = PR_ACCESS; public String CONFIG_ACCESS_DEFAULT = "all"; protected static final String NL = "\r\n"; protected static final String[] welcome_pages = {"index.html", "index.htm", "index.php", "index.tmpl" }; protected static File[] welcome_files; protected PluginInterface plugin_interface; // unfortunately this is accessed by webui - fix sometime private LoggerChannel log; private Tracker tracker; private BasicPluginViewModel view_model; private BasicPluginConfigModel config_model; private IntParameter param_port; private StringListParameter param_protocol; private String home_page; private String file_root; private String resource_root; private boolean ip_range_all = false; private List ip_ranges; private Properties properties; public WebPlugin() { properties = new Properties(); } public WebPlugin( Properties defaults ) { properties = defaults; } public void initialize( PluginInterface _plugin_interface ) throws PluginException { plugin_interface = _plugin_interface; Boolean pr_enable = (Boolean)properties.get(PR_ENABLE); if ( pr_enable != null ){ CONFIG_ENABLE_DEFAULT = pr_enable.booleanValue(); } Integer pr_port = (Integer)properties.get(PR_PORT); if ( pr_port != null ){ CONFIG_PORT_DEFAULT = pr_port.intValue(); } String pr_bind_ip = (String)properties.get(PR_BIND_IP); if ( pr_bind_ip != null ){ CONFIG_BIND_IP_DEFAULT = pr_bind_ip.trim(); } String pr_root_resource = (String)properties.get( PR_ROOT_RESOURCE ); if( pr_root_resource != null ){ CONFIG_ROOT_RESOURCE_DEFAULT = pr_root_resource; } String pr_root_dir = (String)properties.get( PR_ROOT_DIR ); if( pr_root_dir != null ){ CONFIG_ROOT_DIR_DEFAULT = pr_root_dir; } String pr_access = (String)properties.get( PR_ACCESS ); if( pr_access != null ){ CONFIG_ACCESS_DEFAULT = pr_access; } Boolean pr_hide_resource_config = (Boolean)properties.get( PR_HIDE_RESOURCE_CONFIG ); log = (LoggerChannel)properties.get( PR_LOG ); if ( log == null ){ log = plugin_interface.getLogger().getChannel("WebPlugin"); } UIManager ui_manager = plugin_interface.getUIManager(); view_model = (BasicPluginViewModel)properties.get( PR_VIEW_MODEL ); if ( view_model == null ){ view_model = ui_manager.createBasicPluginViewModel( plugin_interface.getPluginName()); } String sConfigSectionID = "plugins." + plugin_interface.getPluginID(); view_model.setConfigSectionID(sConfigSectionID); view_model.getStatus().setText( "Running" ); view_model.getActivity().setVisible( false ); view_model.getProgress().setVisible( false ); log.addListener( new LoggerChannelListener() { public void messageLogged( int type, String message ) { view_model.getLogArea().appendText( message+"\n"); } public void messageLogged( String str, Throwable error ) { view_model.getLogArea().appendText( str + "\n" ); view_model.getLogArea().appendText( error.toString() + "\n" ); } }); PluginConfig plugin_config = plugin_interface.getPluginconfig(); String[] cm_params = (String[])properties.get( PR_CONFIG_MODEL_PARAMS ); if ( cm_params == null || cm_params.length == 0 ){ config_model = ui_manager.createBasicPluginConfigModel(ConfigSection.SECTION_PLUGINS, sConfigSectionID); }else if ( cm_params.length == 1 ){ config_model = ui_manager.createBasicPluginConfigModel( cm_params[0] ); }else{ config_model = ui_manager.createBasicPluginConfigModel( cm_params[0], cm_params[1] ); } boolean save_needed = false; if ( !plugin_config.getPluginBooleanParameter( CONFIG_MIGRATED, false )){ plugin_config.setPluginParameter( CONFIG_MIGRATED, true ); save_needed = true; plugin_config.setPluginParameter( CONFIG_PASSWORD_ENABLE, plugin_config.getBooleanParameter( "Tracker Password Enable Web", CONFIG_PASSWORD_ENABLE_DEFAULT )); plugin_config.setPluginParameter( CONFIG_USER, plugin_config.getStringParameter( "Tracker Username", CONFIG_USER_DEFAULT )); plugin_config.setPluginParameter( CONFIG_PASSWORD, plugin_config.getByteParameter( "Tracker Password", CONFIG_PASSWORD_DEFAULT )); } if ( !plugin_config.getPluginBooleanParameter( PROPERTIES_MIGRATED, false )){ plugin_config.setPluginParameter( PROPERTIES_MIGRATED, true ); Properties props = plugin_interface.getPluginProperties(); // make sure we've got an old properties file too if ( props.getProperty( "port", "" ).length() > 0 ){ save_needed = true; String prop_port = props.getProperty( "port", ""+CONFIG_PORT_DEFAULT ); String prop_protocol = props.getProperty( "protocol", CONFIG_PROTOCOL_DEFAULT ); String prop_home = props.getProperty( "homepage", CONFIG_HOME_PAGE_DEFAULT ); String prop_rootdir = props.getProperty( "rootdir", CONFIG_ROOT_DIR_DEFAULT ); String prop_rootres = props.getProperty( "rootresource", CONFIG_ROOT_RESOURCE_DEFAULT ); String prop_mode = props.getProperty( "mode", CONFIG_MODE_DEFAULT ); String prop_access = props.getProperty( "access", CONFIG_ACCESS_DEFAULT ); int prop_port_int = CONFIG_PORT_DEFAULT; try{ prop_port_int = Integer.parseInt( prop_port ); }catch( Throwable e ){ } plugin_config.setPluginParameter(CONFIG_PORT, prop_port_int ); plugin_config.setPluginParameter(CONFIG_PROTOCOL, prop_protocol ); plugin_config.setPluginParameter(CONFIG_HOME_PAGE, prop_home ); plugin_config.setPluginParameter(CONFIG_ROOT_DIR, prop_rootdir ); plugin_config.setPluginParameter(CONFIG_ROOT_RESOURCE, prop_rootres ); plugin_config.setPluginParameter(CONFIG_MODE, prop_mode ); plugin_config.setPluginParameter(CONFIG_ACCESS, prop_access ); File props_file = new File( plugin_interface.getPluginDirectoryName(), "plugin.properties" ); PrintWriter pw = null; try{ File backup = new File( plugin_interface.getPluginDirectoryName(), "plugin.properties.bak" ); props_file.renameTo( backup ); pw = new PrintWriter( new FileWriter( props_file )); pw.println( "plugin.class=" + props.getProperty( "plugin.class" )); pw.println( "plugin.name=" + props.getProperty( "plugin.name" )); pw.println( "plugin.version=" + props.getProperty( "plugin.version" )); pw.println( "plugin.id=" + props.getProperty( "plugin.id" )); pw.println( "" ); pw.println( "# configuration has been migrated to plugin config - see view->config->plugins" ); pw.println( "# in the SWT user interface" ); log.logAlert( LoggerChannel.LT_INFORMATION, plugin_interface.getPluginName() + " - plugin.properties settings migrated to plugin configuration." ); }catch( Throwable e ){ Debug.printStackTrace( e ); log.logAlert( LoggerChannel.LT_ERROR, plugin_interface.getPluginName() + " - plugin.properties settings migration failed." ); }finally{ if ( pw != null ){ pw.close(); } } } } if ( save_needed ){ plugin_config.save(); } final LabelParameter param_info = config_model.addLabelParameter2( "webui.restart.info" ); Boolean disablable = (Boolean)properties.get( PR_DISABLABLE ); boolean enabled = true; BooleanParameter param_enable = null; if ( disablable != null && disablable ){ param_enable = config_model.addBooleanParameter2( CONFIG_ENABLE, "webui.enable", CONFIG_ENABLE_DEFAULT ); enabled = param_enable.getValue(); } // connection group param_port = config_model.addIntParameter2( CONFIG_PORT, "webui.port", CONFIG_PORT_DEFAULT ); StringParameter param_bind = config_model.addStringParameter2( CONFIG_BIND_IP, "webui.bindip", CONFIG_BIND_IP_DEFAULT ); param_protocol = config_model.addStringListParameter2( CONFIG_PROTOCOL, "webui.protocol", new String[]{ "http", "https" }, CONFIG_PROTOCOL_DEFAULT ); final BooleanParameter upnp_enable = config_model.addBooleanParameter2( CONFIG_UPNP_ENABLE, "webui.upnpenable", CONFIG_UPNP_ENABLE_DEFAULT ); final String p_sid = (String)properties.get( PR_PAIRING_SID ); final LabelParameter pairing_info; final BooleanParameter pairing_enable; if ( p_sid != null ){ PairingManager pm = PairingManagerFactory.getSingleton(); pairing_info = config_model.addLabelParameter2( "webui.pairing.info." + (pm.isEnabled()?"y":"n")); pairing_enable = config_model.addBooleanParameter2( CONFIG_PAIRING_ENABLE, "webui.pairingenable", CONFIG_PAIRING_ENABLE_DEFAULT ); pairing_enable.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { setupPairing( p_sid, pairing_enable.getValue()); } }); pairing_enable.setEnabled( pm.isEnabled()); pm.addListener( new PairingManagerListener() { public void somethingChanged( PairingManager pm ) { pairing_info.setLabelKey( "webui.pairing.info." + (pm.isEnabled()?"y":"n")); pairing_enable.setEnabled( pm.isEnabled()); } }); setupPairing( p_sid, pairing_enable.getValue()); ParameterListener update_pairing_listener = new ParameterListener() { public void parameterChanged( Parameter param ) { updatePairing( p_sid ); } }; param_port.addListener( update_pairing_listener ); param_protocol.addListener( update_pairing_listener ); }else{ pairing_info = null; pairing_enable = null; } config_model.createGroup( "ConfigView.section.server", new Parameter[]{ param_port, param_bind, param_protocol, upnp_enable, pairing_info, pairing_enable, }); StringParameter param_home = config_model.addStringParameter2( CONFIG_HOME_PAGE, "webui.homepage", CONFIG_HOME_PAGE_DEFAULT ); StringParameter param_rootdir = config_model.addStringParameter2( CONFIG_ROOT_DIR, "webui.rootdir", CONFIG_ROOT_DIR_DEFAULT ); StringParameter param_rootres = config_model.addStringParameter2( CONFIG_ROOT_RESOURCE, "webui.rootres", CONFIG_ROOT_RESOURCE_DEFAULT ); if ( pr_hide_resource_config != null && pr_hide_resource_config.booleanValue()){ param_home.setVisible( false ); param_rootdir.setVisible( false ); param_rootres.setVisible( false ); } // access group LabelParameter a_label1 = config_model.addLabelParameter2( "webui.mode.info" ); StringListParameter param_mode = config_model.addStringListParameter2( CONFIG_MODE, "webui.mode", new String[]{ "full", "view" }, CONFIG_MODE_DEFAULT ); LabelParameter a_label2 = config_model.addLabelParameter2( "webui.access.info" ); StringParameter param_access = config_model.addStringParameter2( CONFIG_ACCESS, "webui.access", CONFIG_ACCESS_DEFAULT ); final BooleanParameter pw_enable = config_model.addBooleanParameter2( CONFIG_PASSWORD_ENABLE, "webui.passwordenable", CONFIG_PASSWORD_ENABLE_DEFAULT ); final StringParameter user_name = config_model.addStringParameter2( CONFIG_USER, "webui.user", CONFIG_USER_DEFAULT ); final PasswordParameter password = config_model.addPasswordParameter2( CONFIG_PASSWORD, "webui.password", PasswordParameter.ET_SHA1, CONFIG_PASSWORD_DEFAULT ); pw_enable.addEnabledOnSelection( user_name ); pw_enable.addEnabledOnSelection( password ); config_model.createGroup( "webui.group.access", new Parameter[]{ a_label1, param_mode, a_label2, param_access, pw_enable, user_name, password, }); if ( param_enable != null ){ final List changed_params = new ArrayList(); if ( !enabled ){ Parameter[] params = config_model.getParameters(); for ( Parameter param: params ){ if ( param == param_enable || param == param_info ){ continue; } if ( param.isEnabled()){ changed_params.add( param ); param.setEnabled( false ); } } } param_enable.addListener( new ParameterListener() { public void parameterChanged( Parameter e_p ) { // this doesn't quite work as tne enabler/disabler parameter logic is implemented // badly and only toggles the UI component, not the enabled state of the // underlying parameter. grr. better than nothing though boolean is_enabled = ((BooleanParameter)e_p).getValue(); if ( is_enabled ){ for ( Parameter p: changed_params ){ p.setEnabled( true ); } }else{ changed_params.clear(); Parameter[] params = config_model.getParameters(); for ( Parameter param: params ){ if ( param == e_p || param == param_info ){ continue; } if ( param.isEnabled()){ changed_params.add( param ); param.setEnabled( false ); } } } } }); if ( !enabled ){ return; } } // end config tracker = plugin_interface.getTracker(); home_page = param_home.getValue().trim(); if ( home_page.length() == 0 ){ home_page = null; }else if (!home_page.startsWith("/" )){ home_page = "/" + home_page; } resource_root = param_rootres.getValue().trim(); if ( resource_root.length() == 0 ){ resource_root = null; }else if ( resource_root.startsWith("/" )){ resource_root = resource_root.substring(1); } String root_dir = param_rootdir.getValue().trim(); if ( root_dir.length() == 0 ){ file_root = plugin_interface.getPluginDirectoryName(); if ( file_root == null ){ file_root = SystemProperties.getUserPath() + "web"; } }else{ // absolute or relative if ( root_dir.startsWith(File.separator) || root_dir.indexOf(":") != -1 ){ file_root = root_dir; }else{ if ( File.separatorChar != '/' && root_dir.contains( "/" )){ root_dir = root_dir.replace( '/', File.separatorChar ); } // try relative to plugin dir file_root = plugin_interface.getPluginDirectoryName(); if ( file_root != null ){ file_root = file_root + File.separator + root_dir; if ( !new File(file_root).exists()){ file_root = null; } } if ( file_root == null ){ file_root = SystemProperties.getUserPath() + "web" + File.separator + root_dir; } } } File f_root = new File( file_root ); if ( !f_root.exists()){ String error = "WebPlugin: root dir '" + file_root + "' doesn't exist"; log.log( LoggerChannel.LT_ERROR, error ); throw( new PluginException( error )); } if ( !f_root.isDirectory()){ String error = "WebPlugin: root dir '" + file_root + "' isn't a directory"; log.log( LoggerChannel.LT_ERROR, error ); throw( new PluginException( error )); } welcome_files = new File[welcome_pages.length]; for (int i=0;i 0 ){ try{ bind_ip = InetAddress.getByName( bind_ip_str ); }catch( Throwable e ){ log.log( LoggerChannel.LT_ERROR, "Bind IP parameter '" + bind_ip_str + "' is invalid" ); } } int protocol = protocol_str.equalsIgnoreCase( "HTTP")?Tracker.PR_HTTP:Tracker.PR_HTTPS; log.log( LoggerChannel.LT_INFORMATION, "Initialisation: port = " + port + (bind_ip == null?"":(", bind = " + bind_ip_str + ")")) + ", protocol = " + protocol_str + (root_dir.length()==0?"":(", root = " + root_dir ))); String access_str = param_access.getValue().trim(); String ip_ranges_str = ""; if ( access_str.length() > 7 && Character.isDigit(access_str.charAt(0))){ String[] ranges = access_str.replace( ';', ',' ).split( "," ); ip_ranges = new ArrayList(); for ( String range: ranges ){ range = range.trim(); if ( range.length() > 7 ){ IPRange ip_range = plugin_interface.getIPFilter().createRange(true); int sep = range.indexOf("-"); if ( sep == -1 ){ ip_range.setStartIP( range ); ip_range.setEndIP( range ); }else{ ip_range.setStartIP( range.substring(0,sep).trim()); ip_range.setEndIP( range.substring( sep+1 ).trim()); } ip_range.checkValid(); if (!ip_range.isValid()){ log.log( LoggerChannel.LT_ERROR, "Access parameter '" + range + "' is invalid" ); }else{ ip_ranges.add( ip_range ); ip_ranges_str += (ip_ranges_str.length()==0?"":", ") + ip_range.getStartIP() + " - " + ip_range.getEndIP(); } } } if ( ip_ranges.size() == 0 ){ ip_ranges = null; } }else{ if ( access_str.equalsIgnoreCase( "all" )){ ip_range_all = true; } } log.log( LoggerChannel.LT_INFORMATION, "Acceptable IP range = " + ( ip_ranges==null? (ip_range_all?"all":"local"): (ip_ranges_str))); try{ TrackerWebContext context = tracker.createWebContext( plugin_interface.getAzureusName() + " - " + plugin_interface.getPluginName(), port, protocol, bind_ip ); Boolean pr_enable_keep_alive = (Boolean)properties.get( PR_ENABLE_KEEP_ALIVE ); if ( pr_enable_keep_alive != null && pr_enable_keep_alive ){ context.setEnableKeepAlive( true ); } context.addPageGenerator( this ); context.addAuthenticationListener( new TrackerAuthenticationAdapter() { String last_pw = ""; byte[] last_hash = {}; AEMonitor this_mon = new AEMonitor( "WebPlugin:auth" ); public boolean authenticate( URL resource, String user, String pw ) { try{ this_mon.enter(); if ( !pw_enable.getValue()){ return( true ); } if ( !user.equals(user_name.getValue())){ return( false ); } byte[] hash = last_hash; if ( !last_pw.equals( pw )){ hash = plugin_interface.getUtilities().getSecurityManager().calculateSHA1( pw.getBytes()); last_pw = pw; last_hash = hash; } return( Arrays.equals( hash, password.getValue())); }finally{ this_mon.exit(); } } }); }catch( TrackerException e ){ log.log( "Plugin Initialisation Fails", e ); } plugin_interface.addListener( new PluginListener() { public void initializationComplete() { PluginInterface pi_upnp = plugin_interface.getPluginManager().getPluginInterfaceByClass( UPnPPlugin.class ); if ( pi_upnp == null ){ log.log( "No UPnP plugin available, not attempting port mapping"); }else{ if ( upnp_enable.getValue()){ ((UPnPPlugin)pi_upnp.getPlugin()).addMapping( plugin_interface.getPluginName(), true, port, true ); }else{ log.log( "UPnP disabled for the plugin, not attempting port mapping"); } } } public void closedownInitiated() { } public void closedownComplete() { } }); } protected void setupPairing( String sid, boolean enable ) { PairingManager pm = PairingManagerFactory.getSingleton(); PairedService service = pm.getService( sid ); if ( enable ){ if ( service == null ){ service = pm.addService( sid ); PairingConnectionData cd = service.getConnectionData(); try{ updatePairing( cd ); }finally{ cd.sync(); } } }else{ if ( service != null ){ service.remove(); } } } protected void updatePairing( String sid ) { PairingManager pm = PairingManagerFactory.getSingleton(); PairedService service = pm.getService( sid ); if ( service != null ){ PairingConnectionData cd = service.getConnectionData(); try{ updatePairing( cd ); }finally{ cd.sync(); } } } protected void updatePairing( PairingConnectionData cd ) { cd.setAttribute( PairingConnectionData.ATTR_PORT, String.valueOf( param_port.getValue())); cd.setAttribute( PairingConnectionData.ATTR_PROTOCOL, param_protocol.getValue()); } protected int getPort() { return( param_port.getValue()); } protected String getProtocol() { return( param_protocol.getValue()); } public boolean generateSupport( TrackerWebPageRequest request, TrackerWebPageResponse response ) throws IOException { return( false ); } public boolean generate( TrackerWebPageRequest request, TrackerWebPageResponse response ) throws IOException { if ( !ip_range_all ){ String client = request.getClientAddress(); // System.out.println( "client = " + client ); try{ boolean valid_ip = true; InetAddress ia = InetAddress.getByName( client ); if ( ip_ranges == null ){ if ( !ia.isLoopbackAddress()){ log.log( LoggerChannel.LT_ERROR, "Client '" + client + "' is not local, rejecting" ); valid_ip = false; } }else{ boolean ok = false; for ( IPRange range: ip_ranges ){ if ( range.isInRange( ia.getHostAddress())){ ok = true; } } if ( !ok ){ log.log( LoggerChannel.LT_ERROR, "Client '" + client + "' (" + ia.getHostAddress() + ") is not in range, rejecting" ); valid_ip = false; } } if (!valid_ip) { response.setReplyStatus(403); response.setContentType("text/plain"); PrintWriter pw = new PrintWriter(response.getOutputStream()); pw.println("Cannot access resource from this IP address."); pw.flush(); pw.close(); return true; } }catch( Throwable e ){ Debug.printStackTrace( e ); return( false ); } } if ( request.getURL().toString().endsWith(".class")){ System.out.println( "WebPlugin::generate:" + request.getURL()); } if ( generateSupport( request, response )){ return(true); } String url = request.getURL(); if (url.equals("/")){ if (home_page != null ){ url = home_page; }else{ for (int i=0;i" + is + ", url = " + url ); if (is != null ){ try{ response.useStream( type, is ); }finally{ is.close(); } return( true ); } } return( false ); } protected BasicPluginConfigModel getConfigModel() { return( config_model ); } protected BasicPluginViewModel getViewModel() { return this.view_model; } protected void log( String str ) { log.log( str ); } protected void log( String str, Throwable e ) { log.log( str, e ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/webplugin/WebPluginAccessController.java0000644000175000017500000000655510373051054026524 0ustar adrianadrian/* * Created on 15-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.webplugin; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.pluginsimpl.remote.*; import org.gudy.azureus2.pluginsimpl.remote.rpexceptions.*; /** * @author parg * */ public class WebPluginAccessController implements RPRequestAccessController { protected boolean view_mode; public WebPluginAccessController( PluginInterface pi ) { String mode_str = pi.getPluginconfig().getPluginStringParameter( WebPlugin.CONFIG_MODE, ((WebPlugin)pi.getPlugin()).CONFIG_MODE_DEFAULT ); view_mode = !mode_str.equalsIgnoreCase( WebPlugin.CONFIG_MODE_FULL ); } public void checkUploadAllowed() { if ( view_mode ){ throw new RPMethodAccessDeniedException(); } } public void checkAccess( String name, RPRequest request ) { String method = request.getMethod(); // System.out.println( "request: " + name + "/" + method ); if ( view_mode ){ /* request: PluginInterface/getDownloadManager request: PluginInterface/getPluginconfig request: PluginConfig/getPluginStringParameter[String,String] request: DownloadManager/getDownloads request: PluginConfig/getPluginIntParameter[String,int] request: PluginInterface/getIPFilter request: PluginConfig/setPluginParameter[String,int] request: PluginConfig/save */ boolean ok = false; if ( name.equals( "PluginInterface" )){ ok = method.equals( "getPluginconfig" ) || method.equals( "getDownloadManager" ) || method.equals( "getIPFilter" ); }else if ( name.equals( "DownloadManager" )){ ok = method.equals( "getDownloads" ); }else if ( name.equals( "PluginConfig" )){ if ( method.startsWith( "getPlugin") || method.equals( "save" )){ ok = true; }else if ( method.equals( "setPluginParameter[String,int]" )){ String param = (String)request.getParams()[0]; ok = param.equals( "MDConfigModel:refresh_period" ); } } if ( !ok ){ throw new RPMethodAccessDeniedException(); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/0000755000175000017500000000000011310377634020241 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/console/UserProfile.java0000644000175000017500000001213310746642262023347 0ustar adrianadrian/* * Created on 25/01/2005 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console; import org.gudy.azureus2.ui.console.util.StringEncrypter; import org.gudy.azureus2.ui.console.util.StringEncrypter.EncryptionException; import com.aelitis.azureus.core.AzureusCoreException; /** * the user profile contains the information about a user that is allowed to use the console ui. * Users may be assigned one of three profiles:
*
    *
  • ADMIN have full access to all commands and to torrents of all users *
  • USER have limited access to commands - can only add/modify their own torrents *
  • GUEST have no access - can only view the torrent download status *
* @author pauld */ public class UserProfile { private String username; private String userType; private String encryptedPassword; private String defaultSaveDirectory; public static final String ADMIN = "admin"; public static final String USER = "user"; public static final String GUEST = "guest"; public static final String DEFAULT_USER_TYPE = ADMIN; public static final UserProfile DEFAULT_USER_PROFILE = new UserProfile("admin", ADMIN); /** * returns true if the specified value is a valid user type * @param userType * @return */ public static boolean isValidUserType( String userType ) { return ADMIN.equals(userType) || USER.equals(userType) || GUEST.equals(userType); } /** * */ public UserProfile() { super(); this.userType = DEFAULT_USER_TYPE; } public UserProfile(String name, String userType) { this.username = name; setUserType(userType); } /** * returns true if the specified password is the password for this * user profile * @param password * @return */ public boolean authenticate(String password) { StringEncrypter encrypter; try { encrypter = new StringEncrypter(StringEncrypter.DES_ENCRYPTION_SCHEME); return encrypter.decrypt(encryptedPassword).equals(password); } catch (EncryptionException e) { throw new AzureusCoreException("Unable to decrypt password", e); } } /** * stores the specified password as an encrypted password * @param password The password to set. */ public void setPassword(String password) { try { StringEncrypter encrypter = new StringEncrypter(StringEncrypter.DES_ENCRYPTION_SCHEME); setEncryptedPassword(encrypter.encrypt(password)); } catch (EncryptionException e) { throw new AzureusCoreException("Unable to encrypt password", e); } } /** * @return Returns the username. */ public String getUsername() { return username; } /** * @param username The username to set. */ public void setUsername(String username) { this.username = username; } /** * @return Returns the userType. */ public String getUserType() { return userType; } /** * @param userType The userType to set. */ public void setUserType(String userType) { if(userType.equalsIgnoreCase(ADMIN)) userType = ADMIN; else if(userType.equalsIgnoreCase(USER)) userType = USER; else if(userType.equalsIgnoreCase(GUEST)) userType = GUEST; else userType = DEFAULT_USER_TYPE; this.userType = userType; } /** * check for equality with another user profile object */ public boolean equals(Object obj) { if( obj == null || ! (obj instanceof UserProfile) ) return false; UserProfile other = (UserProfile)obj; if( getUsername() != null ) return getUsername().equals(other.getUsername()); else if( other.getUsername() != null ) return false; if( getEncryptedPassword() != null ) return getEncryptedPassword().equals(other.getEncryptedPassword()); else if( other.getEncryptedPassword() != null ) return false; return true; } /** * @return Returns the encryptedPassword. */ public String getEncryptedPassword() { return encryptedPassword; } /** * @param encryptedPassword The encryptedPassword to set. */ public void setEncryptedPassword(String encryptedPassword) { this.encryptedPassword = encryptedPassword; } /** * @return the directory that torrents should be saved to for this user, by default */ public String getDefaultSaveDirectory() { return defaultSaveDirectory; } public void setDefaultSaveDirectory(String newValue) { this.defaultSaveDirectory = newValue; } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/CommandReader.java0000644000175000017500000000760710167023524023612 0ustar adrianadrian/* * CommandReader.java * * Created on 25. Oktober 2003, 03:03 */ package org.gudy.azureus2.ui.console; import java.io.IOException; import java.io.Reader; import java.util.List; import java.util.Vector; /** * * @author tobi */ public class CommandReader extends Reader { private final int ENTER = 0; private final int TAB = 1; private final int QUOTE = 3; private final int ESCAPE = 4; private final int NONQUOTEDESCAPE = 5; private Reader in; /** Creates a new instance of CommandReader */ public CommandReader(Reader _in) { super(); in = _in; } private void ensureOpen() throws java.io.IOException { if (in == null) throw new IOException("Stream closed"); } public void close() throws java.io.IOException { synchronized(lock) { if (in != null) { in.close(); in = null; } } } public int read() throws java.io.IOException { synchronized(lock) { ensureOpen(); return in.read(); } } public int read(char[] cbuf, int off, int len) throws java.io.IOException { synchronized(lock) { ensureOpen(); return in.read(cbuf, off, len); } } public String readLine() throws java.io.IOException { synchronized(lock) { ensureOpen(); StringBuffer line = new StringBuffer(); int ch; while( (char)(ch = in.read()) != '\n' ) { if( ch == -1 ) { throw new IOException("stream closed"); } line.append((char)ch); } return line.toString().trim(); } } public List parseCommandLine( String commandLine ) { StringBuffer current = new StringBuffer(); Vector args = new Vector(); boolean allowEmpty = false; boolean bailout = commandLine.length() == 0; int index = 0; int state = ENTER; while (!bailout) { int ch = commandLine.charAt(index++); bailout = (index == commandLine.length()); char c = (char) ch; // if (c!='\n'){ // // line.append( c ); // } // switch (state) { /*case SKIP: switch (c) { case ' ': case '\t': break; case '\"': mode = QUOTE; break; case '&': background = true; case ';': contLine = line.substring(pos +1); pos = line.length(); break; default: mode = READ; --pos; } break;*/ case ENTER: switch (c) { case '\"': state = QUOTE; break; /*case ' ': case '\t': mode = SKIP; break;*/ case '\\': state = NONQUOTEDESCAPE; break; // case '\n': // bailout = true; // break; case '\r': break; default: current.append(c); } if ((state == ENTER) && ((c==' ') || (bailout))) { String arg = current.toString().trim(); if( arg.length() > 0 || allowEmpty ) { args.addElement(arg); allowEmpty = false; } current = new StringBuffer(); } break; case QUOTE: switch (c) { case '\"': allowEmpty = true; state = ENTER; break; case '\\': state = ESCAPE; break; default: current.append(c); } break; case ESCAPE: switch (c) { case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; default: current.append('\\'); break; } state = QUOTE; current.append(c); break; case NONQUOTEDESCAPE: switch (c) { case ';': state = ENTER; current.append(c); break; default: // This is not a escaped char. state = ENTER; current.append('\\'); current.append(c); break; } break; } } if ((state == ENTER) && (current.toString().trim().length() > 0 || allowEmpty) ) { String arg = current.toString().trim(); args.addElement(arg); } return args; } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/MakeTorrent.java0000644000175000017500000001375010143462100023327 0ustar adrianadrian/* * File : MakeTorrent.java * Created : 16 nov. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.console; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentCreator; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.torrent.TOTorrentProgressListener; /** * @author Olivier * */ public class MakeTorrent implements TOTorrentProgressListener { private boolean verbose; private static final String[] validKeys = {"comment","announce-list","target","force_piece_size_pow2","verbose"}; public void reportCurrentTask(String task_description) { if(verbose) { System.out.println(task_description); } } public void reportProgress(int percent_complete) { if(verbose) { System.out.print("\r" + percent_complete + "% "); } } public MakeTorrent(String file,URL url,Map parameters) { File fSrc = new File(file); String torrentName = (String) parameters.get("target"); if(torrentName == null) torrentName = file + ".torrent"; File fDst = new File(torrentName); if(parameters.get("verbose") != null) verbose = true; TOTorrent torrent = null; String pieceSizeStr = (String) parameters.get("force_piece_size_pow2"); if(pieceSizeStr != null) { try { long pieceSize = 1l << Integer.parseInt(pieceSizeStr); TOTorrentCreator creator = TOTorrentFactory.createFromFileOrDirWithFixedPieceLength(fSrc,url,pieceSize); creator.addListener( this ); torrent = creator.create(); }catch(Exception e) { e.printStackTrace(); return; } } else { try { TOTorrentCreator creator = TOTorrentFactory.createFromFileOrDirWithComputedPieceLength(fSrc,url); creator.addListener( this ); torrent = creator.create(); } catch(Exception e) { e.printStackTrace(); return; } } String comment = (String) parameters.get("comment"); if(comment != null) { torrent.setComment(comment); } String announceList = (String) parameters.get("announce-list"); if(announceList != null) { StringTokenizer st = new StringTokenizer(announceList,"|"); List list = new ArrayList(); List urls = new ArrayList(); while(st.hasMoreTokens()) { String _url = st.nextToken(); urls.add(_url); } list.add(urls); TorrentUtils.listToAnnounceGroups(list, torrent); } try { torrent.serialiseToBEncodedFile(fDst); } catch(Exception e) { e.printStackTrace(); } } public static void main(String args[]) { if(args.length < 2) { usage(); System.exit(0); } Map parameters = new HashMap(); for(int i = 2 ; i < args.length ; i++) { boolean ok = parseParameter(args[i],parameters); if(!ok) System.exit(-1); } File f = new File(args[1]); if(!f.exists()) { System.out.println(args[1] + " is not a valid file / directory"); System.exit(-1); } URL url = null; try { url = new URL(args[0]); } catch(Exception e) { System.out.println(args[0] + " is not a valid url"); System.exit(-1); } new MakeTorrent(args[1],url,parameters); } public static void usage() { System.out.println("Usage :"); System.out.println("MakeTorrent [options]"); System.out.println("Options :"); System.out.println("--comment= Adds a comment to the torrent"); System.out.println("--force_piece_size_pow2= Specifies the piece size to use"); System.out.println("--target= Specifies a target torrent file"); System.out.println("--verbose Verbose"); System.out.println("--announce-list=url1[|url2|...] Use a list of trackers"); } public static boolean parseParameter(String parameter,Map parameters) { if(parameter == null) return false; if(parameter.equalsIgnoreCase("--v") || parameter.equalsIgnoreCase("--verbose")) { parameters.put("verbose",new Integer(1)); } if(parameter.startsWith("--")) { try { StringTokenizer st = new StringTokenizer(parameter.substring(2),"="); String key = st.nextToken(); String value = ""; String sep = ""; while(st.hasMoreTokens()) { value += sep + st.nextElement(); sep = "="; } boolean valid = false; for(int i = 0 ; i < validKeys.length ;i++) { if(validKeys[i].equalsIgnoreCase(key)) { valid = true; break; } } if(!valid) { System.out.println("Invalid parameter : " + key); return false; } parameters.put(key,value); return true; } catch(Exception e) { System.out.println("Cannot parse " + parameter); return false; } } System.out.println("Cannot parse " + parameter); return false; } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/0000755000175000017500000000000011310377636022044 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/TorrentFilter.java0000644000175000017500000001337010316000454025500 0ustar adrianadrian/* * Created on 26/09/2005 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.gudy.azureus2.core3.download.DownloadManager; import com.aelitis.azureus.core.AzureusCoreException; public class TorrentFilter { private static final Pattern rangePattern = Pattern.compile("([0-9]+)\\s*((-)|(-\\s*([0-9]+)))?"); public TorrentFilter() { super(); } /** * matches a range of torrents. eg: 3-5 or a single torrent. eg: 3. or from 3 onwards: 3- * @param torrents torrents to match * @param filter range expression * @return list of matched DownloadManager objects */ private List matchRange( List torrents, String filter ) { Matcher matcher = rangePattern.matcher(filter); List list = new ArrayList(); if( matcher.matches() ) { int minId = Integer.parseInt(matcher.group(1)); if( minId == 0 ) throw new AzureusCoreException("lower range must be greater than 0"); if( minId > torrents.size() ) throw new AzureusCoreException("lower range specified (" + minId + ") is outside number of torrents (" + torrents.size() + ")"); if( matcher.group(2) == null ) { // received a single number. eg: 3 list.add(torrents.get(minId-1)); return list; } int maxId; if( matcher.group(3) == null ) // received bound range. eg: 3-5 maxId = Integer.parseInt(matcher.group(5)); else // received open ended range. eg: 3- maxId = torrents.size(); if( minId > maxId ) throw new AzureusCoreException("when specifying a range, the max value must be greater than or equal to the min value"); for( int i = (minId-1) ; i < maxId && i < torrents.size() ; i++ ) { list.add(torrents.get(i)); } } return list; } /** * attempst to match a wildcard against the list of torrents by * checking their display name * @param torrents list of available torrents to match * @param filter wildcard (glob) filter * @return list of matched DownloadManager objects */ private List matchWildcard( List torrents, String filter ) { Pattern pattern = Pattern.compile(wildcardToPattern(filter), Pattern.CASE_INSENSITIVE); List list = new ArrayList(); for (Iterator iter = torrents.iterator(); iter.hasNext();) { DownloadManager dm = (DownloadManager) iter.next(); if( pattern.matcher(dm.getDisplayName()).matches() ) list.add(dm); } return list; } /** * converts the wildcard (eg: tran*) into a regular expression - (tran.*) * @param wild wildcard (glob) expression * @return regular expression string */ private String wildcardToPattern(String wild) { if (wild == null) return null; StringBuffer buffer = new StringBuffer(); char[] chars = wild.toCharArray(); for (int i = 0; i < chars.length; ++i) { if (chars[i] == '*') buffer.append(".*"); else if (chars[i] == '?') buffer.append("."); else if ("+()^$.{}[]|\\".indexOf(chars[i]) != -1) buffer.append('\\').append(chars[i]); // prefix all metacharacters // with backslash else buffer.append(chars[i]); } return buffer.toString().toLowerCase(); } /** * tries our two different matching algorithms using the * supplied filter against the list of torrents in the ConsoleInput object * @param torrentsToMatch list of DownloadManager objects to attempt to match against * @param filter filter - eg: range or glob filter * @return list of matched DownloadManager objects */ public List getTorrents(List torrentsToMatch, String filter) { List torrents = new ArrayList(); torrents.addAll(matchRange(torrentsToMatch, filter) ); torrents.addAll(matchWildcard(torrentsToMatch, filter) ); return torrents; } /** * first tries to match torrents by concatenating all of the arguments. * if that doesn't work, attempts to match each argument individually. * @param torrentsToMatch list of DownloadManager objects to attempt to match against * @param args arguments to try to match * @return list of matched DownloadManager objects */ public List getTorrents(List torrentsToMatch, List args) { // first, try to match the whole list concatenated as a string StringBuffer allArgs = new StringBuffer(); boolean first = true; for (Iterator iter = args.iterator(); iter.hasNext();) { if( ! first ) allArgs.append(","); else first = false; allArgs.append(iter.next()); } List torrents; torrents = matchWildcard(torrentsToMatch, allArgs.toString()); if( torrents.size() > 0 ) return torrents; torrents = matchRange(torrentsToMatch, allArgs.toString()); if( torrents.size() > 0 ) return torrents; // if no torrents then handle each argument individually for (Iterator iter = args.iterator(); iter.hasNext();) { torrents.addAll(getTorrents(torrentsToMatch, (String)iter.next()) ); } return torrents; } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/TorrentPublish.java0000644000175000017500000000461511021643236025670 0ustar adrianadrian/* * Created on 04/12/2004 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.util.List; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.tracker.host.TRHost; import org.gudy.azureus2.core3.tracker.host.TRHostException; import org.gudy.azureus2.core3.tracker.host.TRHostTorrent; import org.gudy.azureus2.ui.console.ConsoleInput; /** * console command to host a torrent. * extracted from the Torrent class written by tobias */ public class TorrentPublish extends TorrentCommand { public TorrentPublish() { super("publish", null, "Publishing"); } protected boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { TOTorrent torrent = dm.getTorrent(); if (torrent != null) { try { TRHost host = ci.azureus_core.getTrackerHost(); TRHostTorrent existing = host.getHostTorrent( torrent ); if ( existing == null ){ host.publishTorrent(torrent); }else{ try{ existing.remove(); }catch( Throwable e ){ e.printStackTrace(); } } } catch (TRHostException e) { e.printStackTrace(ci.out); return false; } return true; } return false; } public String getCommandDescriptions() { return("publish ()\t\tPublish or stop publishing torrent(s)."); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/TorrentRemove.java0000644000175000017500000000360611021643236025516 0ustar adrianadrian/* * Created on 04/12/2004 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.util.List; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManagerDownloadRemovalVetoException; import org.gudy.azureus2.ui.console.ConsoleInput; /** * console command to remove a torrent. * extracted from the Torrent command written by tobias */ public class TorrentRemove extends TorrentCommand { public TorrentRemove() { super("remove", "r", "Removing"); } protected boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { try { ci.getGlobalManager().removeDownloadManager(dm); } catch (GlobalManagerDownloadRemovalVetoException e) { ci.out.println("> Veto when removing torrent (" + e.getMessage() + ")"); return false; } catch (Exception e) { e.printStackTrace(ci.out); return false; } return true; } public String getCommandDescriptions() { return("remove ()\tr\tRemove torrent(s)."); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/AddFind.java0000644000175000017500000001704511021643236024176 0ustar adrianadrian/* * Written and copyright 2001-2003 Tobias Minich. Distributed under the GNU * General Public License; see the README file. This code comes with NO * WARRANTY. * * AddFind.java * * Created on 23.03.2004 * */ package org.gudy.azureus2.ui.console.commands; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.OptionBuilder; import org.gudy.azureus2.ui.console.ConsoleInput; import org.pf.file.FileFinder; import org.pf.text.StringUtil; import com.aelitis.azureus.core.AzureusCoreException; /** * this class allows the user to add and find torrents. * when adding, you may specify an output directory * when finding, it will cache the files it finds into the ConsoleInput object * so that they can then be added by id * @author tobi, fatal */ public class AddFind extends OptionsConsoleCommand { public AddFind() { super("add", "a"); OptionBuilder.withArgName("outputDir"); OptionBuilder.withLongOpt("output"); OptionBuilder.hasArg(); OptionBuilder.withDescription("override default download directory"); OptionBuilder.withType(File.class); getOptions().addOption( OptionBuilder.create('o') ); getOptions().addOption("r", "recurse", false, "recurse sub-directories."); getOptions().addOption("f", "find", false, "only find files, don't add."); getOptions().addOption("h", "help", false, "display help about this command"); getOptions().addOption("l", "list", false, "list previous find results"); } public String getCommandDescriptions() { return "add [addoptions] [.torrent path|url]\t\ta\tAdd a download from the given .torrent file path or url. Example: 'add /path/to/the.torrent' or 'add http://www.url.com/to/the.torrent'"; } public void execute(String commandName, ConsoleInput ci, CommandLine commands) { if( commands.hasOption('l') ) { ci.out.println("> -----"); showAdds(ci); ci.out.println("> -----"); return; } else if( commands.hasOption('h') || commands.getArgs().length == 0 ) { printHelp(ci.out, (String)null); return; } String outputDir = "."; if (commands.hasOption('o')) outputDir = commands.getOptionValue('o'); else outputDir = ci.getDefaultSaveDirectory(); File f = new File(outputDir); if( ! f.isAbsolute() ) { // make it relative to current directory try { outputDir = new File(".", outputDir).getCanonicalPath(); } catch (IOException e) { throw new AzureusCoreException("exception occurred while converting directory: ./" + outputDir + " to its canonical path"); } } boolean scansubdir = commands.hasOption('r'); boolean finding = commands.hasOption('f'); String[] whatelse = commands.getArgs(); for (int i = 0; i < whatelse.length; i++) { String arg = whatelse[i]; try { // firstly check if it is a valid URL new URL(arg); addRemote(ci, arg, outputDir); } catch (MalformedURLException e) { // assume that it's a local file or file id from a previous find addLocal(ci, arg, outputDir, scansubdir, finding); } } } /** * attempt to download the torrent specified by 'arg' and save the files * in the torrent to the specified output directory * @param ci * @param arg URL of torrent to download * @param outputDir directory to save files from torrent to */ protected void addRemote(ConsoleInput ci, String arg, String outputDir) { ci.out.println("> Starting Download of " + arg + " ..."); try { ci.downloadRemoteTorrent(arg, outputDir); } catch (Exception e) { ci.out.println("An error occurred while downloading torrent: " + e.getMessage()); e.printStackTrace(ci.out); } } /** * attempt a local add (arg may be a directory, a file or a pattern eg: d:/*.torrent) * @param ci * @param arg argument - could be directory, file or pattern eg: d:\*.torrent * @param outputDir directory to save files from torrent to * @param scansubdir if true, will recurse subdirectories looking for files to add * @param finding if true, don't start downloading the files; simply add them to the 'found' list */ protected void addLocal(ConsoleInput ci, String arg, String outputDir, boolean scansubdir, boolean finding) { // substitute ~ for home directory, if specified arg = transformLocalArgument(arg); // see if the argument is an existing file or directory File test = new File(arg); if (test.exists()) { if (test.isDirectory()) { File[] toadd = FileFinder.findFiles(arg, "*.torrent;*.tor", scansubdir); if ((toadd != null) && (toadd.length > 0)) { addFiles( ci, toadd, finding, outputDir ); } else { ci.adds = null; ci.out.println("> Directory '" + arg + "' seems to contain no torrent files."); } } else { ci.downloadTorrent(arg, outputDir); ci.out.println("> '" + arg + "' added."); ci.torrents.clear(); } return; } // check to see if they are numeric and if so, try and add them from the 'adds' in ci try { int id = Integer.parseInt(arg); if( ci.adds != null && ci.adds.length > id ) { String torrentPath = ci.adds[id].getAbsolutePath(); ci.downloadTorrent(torrentPath, outputDir); ci.out.println("> '" + torrentPath + "' added."); ci.torrents.clear(); } else { ci.out.println("> No such file id '" + id + "'. Try \"add -l\" to list available files"); } return; } catch (NumberFormatException e) { } // last resort - try to process it as a directory/pattern eg: c:/torrents/*.torrent String dirName = test.getParent(); if( dirName == null ) dirName = "."; String filePattern = test.getName(); File []files = FileFinder.findFiles(dirName, filePattern, false); if ((files != null) && (files.length > 0)) { addFiles(ci, files, finding, outputDir ); } else { ci.adds = null; ci.out.println("> No files found. Searched for '" + filePattern + "' in '" + dirName + "'"); } } /** * perform any transformations on the argument - in this case we are * replacing '~' with the user's home directory. * @param arg * @return */ protected String transformLocalArgument(String arg) { if( arg.startsWith("~/") || arg.equals("~") ) { arg = StringUtil.current().replaceAll(arg, "~", System.getProperty("user.home")); } return arg; } /** * if finding is set, just print the available files and add them to the 'add' list inside the consoleinput object, * otherwise actually add the torrents, saving to the specified output directory * @param toadd * @param finding * @param outputDir */ protected void addFiles(ConsoleInput ci, File[] toadd, boolean finding, String outputDir) { ci.out.println("> -----"); ci.out.println("> Found " + toadd.length + " files:"); if( finding ) { ci.adds = toadd; showAdds(ci); } else { for (int i = 0; i < toadd.length; i++) { ci.downloadTorrent(toadd[i].getAbsolutePath(), outputDir); ci.out.println("> '" + toadd[i].getAbsolutePath() + "' added."); ci.torrents.clear(); } } ci.out.println("> -----"); } /** * prints out the files in the 'add' list that is stored in the console input object. * @param ci */ private void showAdds(ConsoleInput ci) { if( ci.adds == null || ci.adds.length == 0 ) { ci.out.println("> No files found. Try \"add -f \" first"); return; } for (int i = 0; i < ci.adds.length; i++) { ci.out.print(">\t" + i + ":\t"); try { ci.out.println(ci.adds[i].getCanonicalPath()); } catch (Exception e) { ci.out.println(ci.adds[i].getAbsolutePath()); } } ci.out.println("> To add, simply type 'add '"); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/TorrentLog.java0000644000175000017500000001064511021643236025003 0ustar adrianadrian/** * */ package org.gudy.azureus2.ui.console.commands; import java.text.FieldPosition; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import java.util.Vector; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerAdapter; import org.gudy.azureus2.core3.logging.ILogEventListener; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogRelation; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.ui.console.ConsoleInput; import com.aelitis.azureus.core.AzureusCoreFactory; /** * @author TuxPaper * @created Dec 21, 2006 * */ public class TorrentLog extends TorrentCommand implements ILogEventListener { private static int MODE_OFF = 0; private static int MODE_ON = 1; private static int MODE_FLIP = 2; private static SimpleDateFormat dateFormatter; private static FieldPosition formatPos; private int mode = 0; private AEMonitor dms_mon = new AEMonitor("TorrentLog"); private ArrayList dms = new ArrayList(); private boolean gm_listener_added; static { dateFormatter = new SimpleDateFormat("[h:mm:ss.SSS] "); formatPos = new FieldPosition(0); } /** * @param commandNames * @param action */ public TorrentLog() { super("tlog", "tl", "Torrent Logging"); } public void execute(String commandName, ConsoleInput ci, List args) { mode = MODE_ON; Vector newargs = new Vector(args); if (newargs.isEmpty()) { mode = MODE_FLIP; } else if (newargs.contains("off")) { newargs.removeElement("off"); mode = MODE_OFF; } else if (!newargs.contains("on")) { mode = MODE_FLIP; } super.execute(commandName, ci, args); } protected boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { try { dms_mon.enter(); // defer this so that a non-running core doesn't prevent console ui init if ( !gm_listener_added ){ gm_listener_added = true; GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); gm.addListener(new GlobalManagerAdapter() { public void downloadManagerRemoved(DownloadManager dm) { dms.remove(dm); } }, false); } boolean turnOn; if (mode == MODE_FLIP) { turnOn = !dms.contains(dm); } else { turnOn = mode == MODE_ON; } if (turnOn) { ci.out.print("->on] "); if (dms.contains(dm)) { return true; } dms.add(dm); if (dms.size() == 1) { Logger.addListener(this); } } else { ci.out.print("->off] "); dms.remove(dm); if (dms.size() == 0) { Logger.removeListener(this); } } } catch (Exception e) { e.printStackTrace(ci.out); return false; } finally { dms_mon.exit(); } return true; } public String getCommandDescriptions() { return "tl [on|off]\tTorrentLogging"; } public void log(LogEvent event) { boolean bMatch = false; if (event.relatedTo == null) { return; } try { dms_mon.enter(); for (int i = 0; !bMatch && i < event.relatedTo.length; i++) { Object obj = event.relatedTo[i]; if (obj == null) continue; for (int j = 0; !bMatch && j < dms.size(); j++) { if (obj instanceof LogRelation) { //System.err.println(obj.getClass().getSimpleName() + " is Logrelation"); Object newObj = ((LogRelation) obj).queryForClass(DownloadManager.class); if (newObj != null) obj = newObj; } //System.err.println(obj.getClass().getName() + " matches " + filter[j].getClass().getSimpleName() + "?"); if (obj == dms.get(j)) bMatch = true; } // for filter } // for relatedTo } finally { dms_mon.exit(); } if (bMatch) { final StringBuffer buf = new StringBuffer(); dateFormatter.format(event.timeStamp, buf, formatPos); buf.append("{").append(event.logID).append("} "); buf.append(event.text); if (event.relatedTo != null) { buf.append("; \t| "); for (int j = 0; j < event.relatedTo.length; j++) { Object obj = event.relatedTo[j]; if (j > 0) buf.append("; "); if (obj instanceof LogRelation) { buf.append(((LogRelation) obj).getRelationText()); } else if (obj != null) { buf.append(obj.getClass().getName()).append(": '").append( obj.toString()).append("'"); } } } System.out.println(buf.toString()); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/TorrentStart.java0000644000175000017500000000465411021643236025362 0ustar adrianadrian/* * Created on 04/12/2004 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.util.List; import java.util.Vector; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.ui.console.ConsoleInput; /** * console command to start a torrent. * extracted from the Torrent class written by tobias */ public class TorrentStart extends TorrentCommand { // we use this flag to effectively pass data between the // execute() and the performCommand() methods, since execute // will call performCommand private boolean startNow; public TorrentStart() { super("start" , "s", "Starting"); } public void execute(String commandName, ConsoleInput console, List args) { startNow = false; Vector newargs = new Vector(args); if (!newargs.isEmpty() && newargs.contains("now") ) { newargs.removeElement("now"); startNow = true; } super.execute(commandName, console, args); } protected boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { try { int state = dm.getState(); if ( state != DownloadManager.STATE_STOPPED ){ ci.out.println( "Torrent isn't stopped" ); return( false ); } if ( startNow ){ ci.out.println( "'now' option has been deprecated, use forcestart" ); } dm.stopIt( DownloadManager.STATE_QUEUED, false, false ); } catch (Exception e) { e.printStackTrace(ci.out); return false; } return true; } public String getCommandDescriptions() { return "start () \ts\tStart torrent(s)."; } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/TorrentSubCommand.java0000644000175000017500000000311511021643236026304 0ustar adrianadrian/* * Created on 21/12/2004 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.util.List; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.ui.console.ConsoleInput; /** * simple subclass of TorrentCommand that publicises the performCommand * method. the execute() method is not necessarily used in these objects * @author pauld */ public abstract class TorrentSubCommand extends TorrentCommand { /** * @param commandNames * @param action */ public TorrentSubCommand(String command_name, String short_name) { super(command_name, short_name, null); } public abstract boolean performCommand(ConsoleInput ci, DownloadManager dm, List args); } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/CommandCollection.java0000644000175000017500000000617310307371054026301 0ustar adrianadrian/* * Created on 30/08/2005 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.io.PrintWriter; import java.io.StringWriter; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import org.gudy.azureus2.ui.console.ConsoleInput; /** * this class represents a collection of commands. it can be used by * command objects to house their subcommands. when execute() method * is called, the appropriate subcommand is looked up and executed * @author pauld */ public class CommandCollection { private final Map subCommands = new HashMap(); /** * determines the appropriate subcommand to execute and then * executes it, passing in the arguments that we received * @param commandName * @param ci * @param args */ public void execute(String commandName, ConsoleInput ci, List args) { IConsoleCommand command = get(commandName); command.execute(commandName, ci, args); } /** * constructs a string with the descriptions of all of the subcommands, * each separated by a newline * @return */ public String getCommandDescriptions() { StringWriter sw = new StringWriter(); PrintWriter out = new PrintWriter(sw); for (Iterator iter = iterator(); iter.hasNext();) { IConsoleCommand cmd = (IConsoleCommand) iter.next(); out.println(cmd.getCommandDescriptions()); } return sw.toString(); } /** * returns the sub command with the specified command name * @param commandName * @return */ public IConsoleCommand get(String commandName) { return (IConsoleCommand) subCommands.get(commandName); } /** * adds the specified console command as a subcommand to this object. * we will therefore respond to all of the subcommands command names * when passed as the first argument to this command * @param command */ public void add(IConsoleCommand command) { for (Iterator iter = command.getCommandNames().iterator(); iter.hasNext();) { String cmdName = (String) iter.next(); subCommands.put(cmdName, command); } } /** * gets the set of IConsoleCommand objects that are all * of the subcommands that this object owns * @return */ public Iterator iterator() { return new HashSet(subCommands.values()).iterator(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/XML.java0000644000175000017500000000300511021643236023334 0ustar adrianadrian/* * Written and copyright 2001-2004 Tobias Minich. Distributed under the GNU * General Public License; see the README file. This code comes with NO * WARRANTY. * * XML.java * * Created on 22.03.2004 * */ package org.gudy.azureus2.ui.console.commands; import java.io.FileOutputStream; import java.util.List; import org.gudy.azureus2.core3.stats.StatsWriterFactory; import org.gudy.azureus2.core3.stats.StatsWriterStreamer; import org.gudy.azureus2.ui.console.ConsoleInput; /** * @author tobi */ public class XML extends IConsoleCommand { public XML() { super("xml"); } public String getCommandDescriptions() { return("xml []\t\t\t\tOutput stats in xml format (to if given)"); } public void execute(String commandName, ConsoleInput ci, List args) { StatsWriterStreamer sws = StatsWriterFactory.createStreamer(ci.getCore()); String file = null; if ((args != null) && (!args.isEmpty())) file = (String) args.get(0); if (file == null) { try { ci.out.println("> -----"); sws.write(ci.out); ci.out.println("> -----"); } catch (Exception e) { ci.out.println("> Exception while trying to output xml stats:" + e.getMessage()); } } else { try { FileOutputStream os = new FileOutputStream(file); try { sws.write(os); } finally { os.close(); } ci.out.println("> XML stats successfully written to " + file); } catch (Exception e) { ci.out.println("> Exception while trying to write xml stats:" + e.getMessage()); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/Show.java0000644000175000017500000005407111307334272023631 0ustar adrianadrian/* * Written and copyright 2001-2003 Tobias Minich. Distributed under the GNU * General Public License; see the README file. This code comes with NO * WARRANTY. * * Show.java * * Created on 23.03.2004 * */ package org.gudy.azureus2.ui.console.commands; import java.io.FileWriter; import java.io.PrintStream; import java.io.PrintWriter; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerStats; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.peer.PEPeerManagerStats; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.ui.console.ConsoleInput; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.control.DHTControlStats; import com.aelitis.azureus.core.dht.db.DHTDBStats; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition; import com.aelitis.azureus.core.dht.router.DHTRouterStats; import com.aelitis.azureus.core.dht.transport.*; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker; import com.aelitis.azureus.core.stats.AzureusCoreStats; import com.aelitis.azureus.plugins.dht.DHTPlugin; /** * @author Tobias Minich */ public class Show extends IConsoleCommand { private static final class TorrentComparator implements Comparator { public final int compare(Object a, Object b) { DownloadManager aDL = (DownloadManager) a; DownloadManager bDL = (DownloadManager) b; boolean aIsComplete = aDL.getStats().getDownloadCompleted(false) == 1000; boolean bIsComplete = bDL.getStats().getDownloadCompleted(false) == 1000; if (aIsComplete && !bIsComplete) return 1; if (!aIsComplete && bIsComplete) return -1; return aDL.getPosition() - bDL.getPosition(); } } public Show() { super("show", "sh"); } public String getCommandDescriptions() { return("show []\tsh\tShow info. Use without parameter to get a list of available options."); } public void printHelpExtra(PrintStream out, List args) { out.println("> -----"); out.println("'show' options: "); out.println("<#>\t\t\t\tFurther info on a single torrent. Run 'show torrents' first for the number."); out.println("options\t\t\to\tShow list of options for 'set' (also available by 'set' without parameters)."); out.println("files\t\t\tf\tShow list of files found from the 'add -f' command (also available by 'add -l')"); out.println("dht\t\t\td\tShow distributed database statistics"); out.println("nat\t\t\tn\tShow NAT status"); out.println("stats [pattern] [on|off]\ts\tShow stats [with a given pattern] [turn averages on/off]"); out.println("torrents [opts] [expr]\tt\tShow list of torrents. torrent options may be any (or none) of:"); out.println("\t\ttransferring\tx\tShow only transferring torrents."); out.println("\t\tactive\t\ta\tShow only active torrents."); out.println("\t\tcomplete\tc\tShow only complete torrents."); out.println("\t\tincomplete\ti\tShow only incomplete torrents."); out.println("\te.g. show t a *Az* - shows all active torrents with 'Az' occurring in their name." ); out.println("> -----"); } public void execute(String commandName, ConsoleInput ci, List args) { if( args.isEmpty() ) { printHelp(ci.out, args); return; } String subCommand = (String) args.remove(0); if (subCommand.equalsIgnoreCase("options") || subCommand.equalsIgnoreCase("o")) { ci.invokeCommand("set", null); } else if(subCommand.equalsIgnoreCase("files") || subCommand.equalsIgnoreCase("f")) { ci.invokeCommand("add", Arrays.asList( new String[] { "--list"} )); } else if (subCommand.equalsIgnoreCase("torrents") || subCommand.equalsIgnoreCase("t")) { ci.out.println("> -----"); ci.torrents.clear(); ci.torrents.addAll(ci.getGlobalManager().getDownloadManagers()); Collections.sort(ci.torrents, new TorrentComparator()); if (ci.torrents.isEmpty()) { ci.out.println("No Torrents"); ci.out.println("> -----"); return; } long totalReceived = 0; long totalSent = 0; long totalDiscarded = 0; int connectedSeeds = 0; int connectedPeers = 0; PEPeerManagerStats ps; boolean bShowOnlyActive = false; boolean bShowOnlyComplete = false; boolean bShowOnlyIncomplete = false; boolean bShowOnlyTransferring = false; for (Iterator iter = args.iterator(); iter.hasNext();) { String arg = (String) iter.next(); if ("active".equalsIgnoreCase(arg) || "a".equalsIgnoreCase(arg)) { bShowOnlyActive = true; iter.remove(); } else if ("complete".equalsIgnoreCase(arg) || "c".equalsIgnoreCase(arg)) { bShowOnlyComplete = true; iter.remove(); } else if ("incomplete".equalsIgnoreCase(arg) || "i".equalsIgnoreCase(arg)) { bShowOnlyIncomplete = true; iter.remove(); } else if ("transferring".equalsIgnoreCase(arg) || "x".equalsIgnoreCase(arg)) { bShowOnlyTransferring = true; bShowOnlyActive = true; iter.remove(); } } Iterator torrent; if( args.size() > 0 ) { List matchedTorrents = new TorrentFilter().getTorrents(ci.torrents, args); torrent = matchedTorrents.iterator(); } else torrent = ci.torrents.iterator(); List shown_torrents = new ArrayList(); while (torrent.hasNext()) { DownloadManager dm = (DownloadManager) torrent.next(); DownloadManagerStats stats = dm.getStats(); boolean bDownloadCompleted = stats.getDownloadCompleted(false) == 1000; boolean bCanShow = ((bShowOnlyComplete == bShowOnlyIncomplete) || (bDownloadCompleted && bShowOnlyComplete) || (!bDownloadCompleted && bShowOnlyIncomplete)); if (bCanShow && bShowOnlyActive) { int dmstate = dm.getState(); bCanShow = (dmstate == DownloadManager.STATE_SEEDING) || (dmstate == DownloadManager.STATE_DOWNLOADING) || (dmstate == DownloadManager.STATE_CHECKING) || (dmstate == DownloadManager.STATE_INITIALIZING) || (dmstate == DownloadManager.STATE_ALLOCATING); } if (bCanShow && bShowOnlyTransferring) { try { ps = dm.getPeerManager().getStats(); bCanShow = ps.getDataSendRate() > 0 || ps.getDataReceiveRate() > 0; } catch (Exception e) {} } if (bCanShow) { shown_torrents.add( dm ); try { ps = dm.getPeerManager().getStats(); } catch (Exception e) { ps = null; } if (ps != null) { totalReceived += dm.getStats().getTotalDataBytesReceived(); totalSent += dm.getStats().getTotalDataBytesSent(); totalDiscarded += ps.getTotalDiscarded(); connectedSeeds += dm.getNbSeeds(); connectedPeers += dm.getNbPeers(); } ci.out.print(((shown_torrents.size() < 10) ? " " : "") + shown_torrents.size() + " "); ci.out.println(getTorrentSummary(dm)); ci.out.println(); } } ci.torrents.clear(); ci.torrents.addAll( shown_torrents ); GlobalManager gm = ci.getGlobalManager(); ci.out.println("Total Speed (down/up): " + DisplayFormatters.formatByteCountToKiBEtcPerSec(gm.getStats().getDataReceiveRate() + gm.getStats().getProtocolReceiveRate() ) + " / " + DisplayFormatters.formatByteCountToKiBEtcPerSec(gm.getStats().getDataSendRate() + gm.getStats().getProtocolSendRate() )); ci.out.println("Transferred Volume (down/up/discarded): " + DisplayFormatters.formatByteCountToKiBEtc(totalReceived) + " / " + DisplayFormatters.formatByteCountToKiBEtc(totalSent) + " / " + DisplayFormatters.formatByteCountToKiBEtc(totalDiscarded)); ci.out.println("Total Connected Peers (seeds/peers): " + Integer.toString(connectedSeeds) + " / " + Integer.toString(connectedPeers)); ci.out.println("> -----"); } else if (subCommand.equalsIgnoreCase("dht") || subCommand.equalsIgnoreCase("d")) { showDHTStats( ci ); } else if (subCommand.equalsIgnoreCase("nat") || subCommand.equalsIgnoreCase("n")) { IndentWriter iw = new IndentWriter( new PrintWriter( ci.out )); iw.setForce( true ); NetworkAdmin.getSingleton().logNATStatus( iw ); } else if (subCommand.equalsIgnoreCase("stats") || subCommand.equalsIgnoreCase("s")) { String pattern = AzureusCoreStats.ST_ALL; if( args.size() > 0 ){ pattern = (String)args.get(0); if ( pattern.equals("*")){ pattern = ".*"; } } if ( args.size() > 1 ){ AzureusCoreStats.setEnableAverages(((String)args.get(1)).equalsIgnoreCase( "on" )); } java.util.Set types = new HashSet(); types.add( pattern ); Map reply = AzureusCoreStats.getStats( types ); Iterator it = reply.entrySet().iterator(); List lines = new ArrayList(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); lines.add( entry.getKey() + " -> " + entry.getValue()); } Collections.sort( lines ); for ( int i=0;i Command 'show': No torrents in list (try 'show torrents' first)."); return; } try { int number = Integer.parseInt(subCommand); if ((number == 0) || (number > ci.torrents.size())) { ci.out.println("> Command 'show': Torrent #" + number + " unknown."); return; } DownloadManager dm = (DownloadManager) ci.torrents.get(number - 1); printTorrentDetails(ci.out, dm, number, args.size() > 0 ); } catch (Exception e) { ci.out.println("> Command 'show': Subcommand '" + subCommand + "' unknown."); return; } } } /** * returns the summary details for the specified torrent. - we do this by obtaining * the summary format and then performing variable substitution * NOTE: we currently reprocess * the summary format string each time however we could pre-parse this once.. its * probably not that important though. * @return */ protected String getTorrentSummary(DownloadManager dm) { StringBuffer tstate = new StringBuffer(); String summaryFormat = getDefaultSummaryFormat(); char lastch = '0'; char []summaryChars = summaryFormat.toCharArray(); for (int i = 0; i < summaryChars.length; i++) { char ch = summaryChars[i]; if( ch == '%' && lastch != '\\' ) { i++; if( i >= summaryChars.length ) tstate.append('%'); else tstate.append(expandVariable(summaryChars[i], dm)); } else tstate.append(ch); lastch = ch; } return tstate.toString(); } /** * expands the specified variable character into a string.
currently available * variables that can be expanded are:
*
* %a for state
* %c percentage complete
* %t torrent details - error message if error, otherwise torrent name
* %z size
* %e ETA
* %r progress, if we have disabled some files
* %d download speed
* %u upload speed
* %D amount downloaded
* %U amount uploaded
* %v upload slots * %s connected seeds
* %p connected peers
* %S tracker seeds
* %P tracker peers
* @param variable variable character, eg: 'e' for ETA * @param dm download manager object * @return string expansion of the variable */ protected String expandVariable( char variable, DownloadManager dm ) { switch( variable ) { case 'a': return getShortStateString(dm.getState()); case 'c': DecimalFormat df = new DecimalFormat("000.0%"); return df.format(dm.getStats().getCompleted() / 1000.0); case 't': if (dm.getState() == DownloadManager.STATE_ERROR) return dm.getErrorDetails(); else { if (dm.getDisplayName() == null) return "?"; else return dm.getDisplayName(); } case 'z': return DisplayFormatters.formatByteCountToKiBEtc(dm.getSize()); case 'e': return DisplayFormatters.formatETA(dm.getStats().getETA()); case 'r': long to = 0; long tot = 0; if (dm.getDiskManager() != null) { DiskManagerFileInfo files[] = dm.getDiskManager().getFiles(); if (files != null) { if (files.length>1) { int c=0; for (int i = 0; i < files.length; i++) { if (files[i] != null) { if (!files[i].isSkipped()) { c += 1; tot += files[i].getLength(); to += files[i].getDownloaded(); } } } if (c == files.length) tot = 0; } } } DecimalFormat df1 = new DecimalFormat("000.0%"); if (tot > 0) { return " ("+df1.format(to * 1.0 / tot)+")"; } else return "\t"; case 'd': return DisplayFormatters.formatByteCountToKiBEtcPerSec(dm.getStats().getDataReceiveRate()); case 'u': return DisplayFormatters.formatByteCountToKiBEtcPerSec(dm.getStats().getDataSendRate()); case 'D': return DisplayFormatters.formatDownloaded(dm.getStats()); case 'U': return DisplayFormatters.formatByteCountToKiBEtc(dm.getStats().getTotalDataBytesSent()); case 's': return Integer.toString(dm.getNbSeeds()); case 'p': return Integer.toString(dm.getNbPeers()); case 'v': return Integer.toString(dm.getMaxUploads()); case 'I': int downloadSpeed = dm.getStats().getDownloadRateLimitBytesPerSecond(); if( downloadSpeed <= 0 ) return ""; return "(max " + DisplayFormatters.formatByteCountToKiBEtcPerSec(downloadSpeed) + ")"; case 'O': int uploadSpeed = dm.getStats().getUploadRateLimitBytesPerSecond(); if( uploadSpeed <= 0 ) return ""; return "(max " + DisplayFormatters.formatByteCountToKiBEtcPerSec(uploadSpeed) + ")"; case 'S': case 'P': TRTrackerScraperResponse hd = dm.getTrackerScrapeResponse(); if (hd == null || !hd.isValid()) return "?"; else { if( variable == 'S' ) return Integer.toString(hd.getSeeds()); else return Integer.toString(hd.getPeers()); } default: return "??" + variable + "??"; } } /** * returns the format string (in printf style format) to use for displaying the torrent summary * @return */ protected String getDefaultSummaryFormat() { return "[%a] %c\t%t (%z) ETA: %e\r\n%r\tSpeed: %d%I / %u%O\tAmount: %D / %U\tConnections: %s(%S) / %p(%P)"; } /** * returns a string representation of the specified state number * suitable for inclusion in a torrent summary * @param dmstate * @return */ private static String getShortStateString(int dmstate) { switch( dmstate ) { case DownloadManager.STATE_INITIALIZING: return("I"); case DownloadManager.STATE_ALLOCATING: return("A"); case DownloadManager.STATE_CHECKING: return("C"); case DownloadManager.STATE_DOWNLOADING: return(">"); case DownloadManager.STATE_ERROR: return("E"); case DownloadManager.STATE_SEEDING: return("*"); case DownloadManager.STATE_STOPPED: return("!"); case DownloadManager.STATE_WAITING: return("."); case DownloadManager.STATE_READY: return(":"); case DownloadManager.STATE_QUEUED: return("-"); default: return("?"); } } /** * prints out the full details of a particular torrent * @param out * @param dm * @param torrentNum */ private static void printTorrentDetails( PrintStream out, DownloadManager dm, int torrentNum, boolean verbose) { String name = dm.getDisplayName(); if (name == null) name = "?"; out.println("> -----"); out.println("Info on Torrent #" + torrentNum + " (" + name + ")"); out.println("- General Info -"); String[] health = { "- no info -", "stopped", "no remote connections", "no tracker", "OK", "ko" }; try { out.println("Health: " + health[dm.getHealthStatus()]); } catch (Exception e) { out.println("Health: " + health[0]); } out.println("State: " + Integer.toString(dm.getState())); if (dm.getState() == DownloadManager.STATE_ERROR) out.println("Error: " + dm.getErrorDetails()); out.println("Hash: " + TorrentUtils.nicePrintTorrentHash(dm.getTorrent(), true)); out.println("- Torrent file -"); out.println("Torrent Filename: " + dm.getTorrentFileName()); out.println("Saving to: " + dm.getSaveLocation()); out.println("Created By: " + dm.getTorrentCreatedBy()); out.println("Comment: " + dm.getTorrentComment()); out.println("- Tracker Info -"); TRTrackerAnnouncer trackerclient = dm.getTrackerClient(); if (trackerclient != null) { out.println("URL: " + trackerclient.getTrackerURL()); String timestr; try { int time = trackerclient.getTimeUntilNextUpdate(); if (time < 0) { timestr = MessageText.getString("GeneralView.label.updatein.querying"); } else { int minutes = time / 60; int seconds = time % 60; String strSeconds = "" + seconds; if (seconds < 10) { strSeconds = "0" + seconds; //$NON-NLS-1$ } timestr = minutes + ":" + strSeconds; } } catch (Exception e) { timestr = "unknown"; } out.println("Time till next Update: " + timestr); out.println("Status: " + trackerclient.getStatusString()); } else out.println(" Not available"); out.println("- Files Info -"); DiskManagerFileInfo files[] = dm.getDiskManagerFileInfo(); if (files != null) { for (int i = 0; i < files.length; i++) { out.print(((i < 9) ? " " : " ") + Integer.toString(i + 1) + " ("); String tmp = ">"; if (files[i].isPriority()) tmp = "+"; if (files[i].isSkipped()) tmp = "!"; out.print(tmp + ") "); if (files[i] != null) { long fLen = files[i].getLength(); if (fLen > 0) { DecimalFormat df = new DecimalFormat("000.0%"); out.print(df.format(files[i].getDownloaded() * 1.0 / fLen)); out.println("\t" + files[i].getFile(true).getName()); } else out.println("Info not available."); } else out.println("Info not available."); } } else out.println(" Info not available."); if ( verbose ){ out.println( "Pieces" ); PEPeerManager pm = dm.getPeerManager(); if ( pm != null ){ PiecePicker picker = pm.getPiecePicker(); PEPiece[] pieces = pm.getPieces(); String line = ""; for (int i=0;i 0 ){ out.println( line ); } } } out.println("> -----"); } protected void showDHTStats( ConsoleInput ci ) { try{ PluginInterface def = ci.azureus_core.getPluginManager().getDefaultPluginInterface(); PluginInterface dht_pi = def.getPluginManager().getPluginInterfaceByClass(DHTPlugin.class ); if ( dht_pi == null ){ ci.out.println( "\tDHT isn't present" ); return; } DHTPlugin dht_plugin = (DHTPlugin)dht_pi.getPlugin(); if ( dht_plugin.getStatus() != DHTPlugin.STATUS_RUNNING ){ ci.out.println( "\tDHT isn't running yet (disabled or initialising)" ); return; } DHT[] dhts = dht_plugin.getDHTs(); for (int i=0;i 0 ){ ci.out.println(""); } DHT dht = dhts[i]; DHTTransport transport = dht.getTransport(); DHTTransportStats t_stats = transport.getStats(); DHTDBStats d_stats = dht.getDataBase().getStats(); DHTControlStats c_stats = dht.getControl().getStats(); DHTRouterStats r_stats = dht.getRouter().getStats(); long[] rs = r_stats.getStats(); DHTNetworkPosition[] nps = transport.getLocalContact().getNetworkPositions(); String np_str = ""; for (int j=0;j -----"); out.println("Usage: prio [torrent] [file(s)] [priority]"); out.println("Options:"); out.println("\t[torrent]\tThe torrent number from 'show torrents'"); out.println("\t[file(s)] is one of:"); out.println("\t\t\t#file:\tthe file number from 'show [#torrent]',"); out.println("\t\t\trange:\ta range of file numbers, i.e. 1-3 or 1-10,12-15 or 1,3,5-8 ,"); out.println("\t\t\tall:\t 'all' applies priority to all files of the torrent"); out.println("\t[priority] is one of:"); out.println("\t\t\tnormal\tNormal priority"); out.println("\t\t\thigh \tHigh priority"); out.println("\t\t\tdnd \tDo not download (skip)"); out.println("\t\t\tdel \tDo not download & delete file"); out.println("> -----"); } private static final int NORMAL=1; private static final int HIGH=2; private static final int DONOTDOWNLOAD=3; private static final int DELETE=4; private static final String[] priostr = { "Normal", "High", "DoNotDownload", "Delete" }; private int newprio; public void execute(String commandName, ConsoleInput console, CommandLine commandLine) { String tnumstr, fnumstr, newpriostr; int tnumber; DiskManagerFileInfo[] files; String[] sections; List args = commandLine.getArgList(); LinkedList fs,fe; DownloadManager dm; if( args.isEmpty() ) { console.out.println("Torrent # required!"); return; } else { tnumstr = (String) args.remove(0); } if( args.isEmpty() ) { console.out.println("File # required!"); return; } else { fnumstr = (String) args.remove(0); } if ((console.torrents == null) || console.torrents.isEmpty()) { console.out.println("> Command 'prio': No torrents in list (try 'show torrents' first)."); return; } try { tnumber = Integer.parseInt(tnumstr); if ((tnumber == 0) || (tnumber > console.torrents.size())) { console.out.println("> Command 'prio': Torrent #" + tnumber + " unknown."); return; } dm = (DownloadManager) console.torrents.get(tnumber - 1); files = dm.getDiskManagerFileInfo(); } catch (Exception e) { e.printStackTrace(); console.out.println("> Command 'prio': Torrent # '" + tnumstr + "' unknown."); return; } if( args.isEmpty() ) { console.out.println("> Command 'prio': missing parameter for new priority"); return; } else { newpriostr = (String) args.remove(0); } if (newpriostr.equalsIgnoreCase("normal")) { newprio = NORMAL; } else if (newpriostr.equalsIgnoreCase("high")) { newprio = HIGH; } else if (newpriostr.equalsIgnoreCase("dnd")) { newprio = DONOTDOWNLOAD; } else if (newpriostr.equalsIgnoreCase("del")) { newprio = DELETE; } else { console.out.println("> Command 'prio': unknown priority " + newpriostr); return; } if (fnumstr.equalsIgnoreCase("all")) { sections = new String[1]; sections[0] = "1-"+files.length; } else sections = fnumstr.split(","); fs = new LinkedList(); fe = new LinkedList(); int dash,start,end; for (int i=0; i files.length)) { console.out.println("> Command 'prio': Invalid file range " + sections[i]); return; } if (start > end) { console.out.println("> Command 'prio': Invalid file range '"+sections[i]+"'"); } // -1 compensates for 0-based offsets fs.add(new Integer(start - 1)); fe.add(new Integer(end - 1)); } catch (Exception e) { console.out.println("> Command 'prio': File # '" + sections[i] + "' unknown."); return; } } // console.out.println("DM was " + dm.getState()); if ((newprio == DELETE) && (dm.getState() != DownloadManager.STATE_STOPPED)) { try { dm.stopIt( DownloadManager.STATE_STOPPED, false, false ); } catch (Exception e) { console.out.println("Failed to stop torrent " + tnumber); return; } } // console.out.println("DM is " + dm.getState()); int nummod = 0; while (fs.size() > 0) { start = ((Integer) fs.removeFirst()).intValue(); end = ((Integer) fe.removeFirst()).intValue(); for (int i = start; i <= end; i++) { nummod++; // DEBUG // console.out.println("Setting priority for file " + i + " to " + newprio); if (newprio == NORMAL) { files[i].setPriority(false); files[i].setSkipped(false); } else if (newprio == HIGH) { files[i].setPriority(true); files[i].setSkipped(false); } else if (newprio == DONOTDOWNLOAD) { files[i].setPriority(false); files[i].setSkipped(true); } else if (newprio == DELETE) { if (files[i].setStorageType(DiskManagerFileInfo.ST_COMPACT)) { files[i].setPriority(false); files[i].setSkipped(true); } else { console.out.println("> Command 'prio': Failed to delete file " + (i+1)); nummod--; } } } } if ((newprio == DELETE) && (dm.getState() == DownloadManager.STATE_STOPPED)) { try { dm.stopIt( DownloadManager.STATE_QUEUED, false, false ); } catch (Exception e) { console.out.println("Failed to restart torrent " + tnumber); return; } } // console.out.println("DM is again " + dm.getState()); console.out.println(nummod + " file(s) priority set to " + priostr[newprio-1]); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/IConsoleCommand.java0000644000175000017500000000474111021643236025716 0ustar adrianadrian/* * Written and copyright 2001-2004 Tobias Minich. Distributed under the GNU * General Public License; see the README file. This code comes with NO * WARRANTY. * */ package org.gudy.azureus2.ui.console.commands; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.gudy.azureus2.ui.console.ConsoleInput; /** * base interface for all console commands * @author Tobias Minich */ public abstract class IConsoleCommand { private String main_name; private String short_name; private HashSet commands; public IConsoleCommand(String main_name) { this(main_name, null); } public IConsoleCommand(String main_name, String short_name) { this.commands = new HashSet(); this.main_name = main_name; this.short_name = short_name; if (main_name != null) {commands.add(main_name);} if (short_name != null) {commands.add(short_name);} } /** * execute the command with the specified name using the specified arguments * @param commandName * @param console * @param arguments */ public abstract void execute(String commandName, ConsoleInput console, List arguments); /** * return high-level help about the commands supported by this object. * @return */ public abstract String getCommandDescriptions(); /** * do nothing by default * @param out * @param args */ public final void printHelp(PrintStream out, List args) { out.println(getCommandDescriptions()); printHelpExtra(out, args); } public void printHelpExtra(PrintStream out, List args) { // Do nothing by default. } /** * helper method if subclasses want to print out help for a particular subcommand * @param out * @param arg */ protected final void printHelp(PrintStream out, String arg) { List args; if( arg != null ) { args = new ArrayList(); args.add(arg); } else args = Collections.EMPTY_LIST; printHelp(out, args); } /** * returns the set of command names that this command understands. * eg: the 'quit' command might understand 'quit', 'q', 'bye' * other commands might actually have several command names and * execute different code depending upon the command name * @return */ public Set getCommandNames() { return Collections.unmodifiableSet(commands); } public final String getCommandName() {return this.main_name;} public final String getShortCommandName() {return this.short_name;} } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/Move.java0000644000175000017500000000533611021643236023613 0ustar adrianadrian/* * Written and copyright 2001-2004 Tobias Minich. Distributed under the GNU * General Public License; see the README file. This code comes with NO * WARRANTY. * * Move.java * * Created on 23.03.2004 * */ package org.gudy.azureus2.ui.console.commands; import java.util.List; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.ui.console.ConsoleInput; /** * @author Tobias Minich */ public class Move extends IConsoleCommand { public Move() { super("move", "m"); } public String getCommandDescriptions() { return("move []\t\tm\tMove torrent from to to. If to is omitted, the torrent is moved to top or to the bottom if given negative."); } public void execute(String commandName, ConsoleInput ci, List args) { if( args.isEmpty() ) { ci.out.println("> Missing subcommand for 'move'\r\n> move syntax: move <#from> [<#to>]"); return; } if (ci.torrents.isEmpty()) { ci.out.println("> Command 'move': No torrents in list."); return; } int ncommand; int nmoveto = -1; boolean moveto = false; try { ncommand = Integer.parseInt((String) args.get(0)); if (args.size() > 1) { nmoveto = Integer.parseInt((String) args.get(1)); moveto = true; } } catch (NumberFormatException e) { ci.out.println("> Command 'move': Subcommand '" + args.get(0) + "' unknown."); return; } int number = Math.abs(ncommand); if (number == 0 || number > ci.torrents.size()) { ci.out.println("> Command 'move': Torrent #" + Integer.toString(number) + " unknown."); return; } DownloadManager dm = (DownloadManager) ci.torrents.get(number - 1); String name = dm.getDisplayName(); if (name == null) name = "?"; GlobalManager gm = dm.getGlobalManager(); if (moveto) { gm.moveTo(dm, nmoveto - 1); gm.fixUpDownloadManagerPositions(); ci.out.println("> Torrent #" + Integer.toString(number) + " (" + name + ") moved to #" + Integer.toString(nmoveto) + "."); } else if (ncommand > 0) { if (gm.isMoveableUp(dm)) { while (gm.isMoveableUp(dm)) gm.moveUp(dm); gm.fixUpDownloadManagerPositions(); ci.out.println("> Torrent #" + Integer.toString(number) + " (" + name + ") moved to top."); } else { ci.out.println("> Torrent #" + Integer.toString(number) + " (" + name + ") already at top."); } } else { if (gm.isMoveableDown(dm)) { while (gm.isMoveableDown(dm)) gm.moveDown(dm); gm.fixUpDownloadManagerPositions(); ci.out.println("> Torrent #" + Integer.toString(number) + " (" + name + ") moved to bottom."); } else { ci.out.println("> Torrent #" + Integer.toString(number) + " (" + name + ") already at bottom."); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/TorrentForceStart.java0000644000175000017500000000333611021643234026333 0ustar adrianadrian/* * Created on 04/12/2004 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.util.List; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.ui.console.ConsoleInput; /** * console command to force start a torrent. * extracted out of the Torrent class written by tobias */ public class TorrentForceStart extends TorrentCommand { public TorrentForceStart() { super("forcestart", null, "Force Starting"); } protected boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { try { dm.setForceStart(true); } catch (Exception e) { e.printStackTrace(ci.out); return false; } return true; } public String getCommandDescriptions() { return("forcestart ()\t\tStart torrent ignoring other limits/rules."); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/TorrentHost.java0000644000175000017500000000542511021643236025177 0ustar adrianadrian/* * Created on 04/12/2004 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.util.List; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.tracker.host.TRHost; import org.gudy.azureus2.core3.tracker.host.TRHostException; import org.gudy.azureus2.core3.tracker.host.TRHostTorrent; import org.gudy.azureus2.ui.console.ConsoleInput; /** * console command to host a torrent. * extracted from the Torrent class written by tobias */ public class TorrentHost extends TorrentCommand { public TorrentHost() { super("host", null, "Hosting"); } protected boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { TOTorrent torrent = dm.getTorrent(); if (torrent != null) { try { TRHost host = ci.azureus_core.getTrackerHost(); TRHostTorrent existing = host.getHostTorrent( torrent ); if ( existing == null ){ ci.azureus_core.getTrackerHost().hostTorrent(torrent,true, false); }else{ try{ existing.remove(); }catch( Throwable e ){ e.printStackTrace(); } } } catch (TRHostException e) { e.printStackTrace(ci.out); return false; } return true; } return false; } protected boolean performCommand(ConsoleInput ci, TRHostTorrent torrent, List args) { // get here when removing a passive torrent try{ torrent.remove(); return( true ); }catch( Throwable e ){ e.printStackTrace(); } return( false ); } public String getCommandDescriptions() { return("host ()\t\t\tHost or stop hosting torrent(s)."); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/OptionsConsoleCommand.java0000644000175000017500000000701411021643236027155 0ustar adrianadrian/* * Created on 14/12/2004 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.io.PrintStream; import java.io.PrintWriter; import java.util.Iterator; import java.util.List; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import org.gudy.azureus2.ui.console.ConsoleInput; /** * subclass of IConsoleCommand that allows the parameters to be defined using * an Options object * @see org.apache.commons.cli.Options * @author pauld */ public abstract class OptionsConsoleCommand extends IConsoleCommand { private Options options = new Options(); private CommandLineParser parser = null; public OptionsConsoleCommand(String main_name) { super(main_name); } public OptionsConsoleCommand(String main_name, String short_name) { super(main_name, short_name); } /** * take the args and try and create a command line object */ public void execute(String commandName, ConsoleInput console, List arguments) { CommandLineParser parser = getParser(); try { String []args = new String[arguments.size()]; int i = 0; for (Iterator iter = arguments.iterator(); iter.hasNext();) { String arg = (String) iter.next(); args[i++] = arg; } CommandLine line = parser.parse(getOptions(), args); execute( commandName, console, line ); } catch (ParseException e) { console.out.println(">> Invalid arguments: " + e.getMessage()); // printHelp(commandName, console.out); printHelp(console.out, arguments); } } /* (non-Javadoc) * @see org.gudy.azureus2.ui.console.commands.IConsoleCommand#printHelp(java.io.PrintStream, java.util.List) */ public void printHelpExtra(PrintStream out, List args) { HelpFormatter formatter = new HelpFormatter(); PrintWriter writer = new PrintWriter(out); writer.println("> -----"); writer.println(getCommandDescriptions()); // formatter.printHelp(writer, 80, getCommandDescriptions(), ">>>", getOptions(), 4, 4, ">>>", true); formatter.printOptions(writer, 80, getOptions(), 4, 4); writer.println("> -----"); writer.flush(); } /** * execute using the specified command line. * @param commandName * @param console * @param commandLine */ public abstract void execute(String commandName, ConsoleInput console, CommandLine commandLine); /** * @return */ protected CommandLineParser getParser() { if( parser == null ) parser = new PosixParser(); return parser; } protected Options getOptions() { return options; } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/Share.java0000644000175000017500000002477611237645566024001 0ustar adrianadrian/* * Written and copyright 2001-2003 Tobias Minich. Distributed under the GNU * General Public License; see the README file. This code comes with NO * WARRANTY. * * AddFind.java * * Created on 23.03.2004 * */ package org.gudy.azureus2.ui.console.commands; import java.io.File; import java.io.PrintStream; import java.util.*; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.sharing.*; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.torrent.TorrentManager; import org.gudy.azureus2.ui.console.ConsoleInput; /** * @author tobi * * To change the template for this generated type comment go to * Window - Preferences - Java - Code Generation - Code and Comments */ public class Share extends IConsoleCommand { public Share() { super("share"); } public String getCommandDescriptions() { return("share []\t\t\tShare a file or folder(s). Use without parameters to get a list of available options." ); } public void printHelpExtra(PrintStream out, List args) { out.println( "> -----" ); out.println( "[share []" ); out.println( "type options:" ); out.println( "file Share a single file." ); out.println( "folder Share a folder as a single multi-file torrent." ); out.println( "contents Share files and sub-dirs in a folder as single and multi-file torrents." ); out.println( "rcontents Share files and sub-dir files in a folder as separate torrents." ); out.println( "list List the shares (path not required)"); out.println( "remove Remove a share given its path"); out.println( "remove hash Remove a share given its hash"); out.println( " is semicolon separated = list."); out.println( " Defined values are 'category=', 'private=', 'dht_backup=' and 'comment=' ('_' in are replaced with spaces)"); out.println( " currently only 'category' can be applied to file/folder and the rest only apply to items added *after* the share has been defined" ); out.println( " For example: share contents /music category=music;private=true;comment=Great_Stuff"); out.println( "> -----" ); } public void execute(String commandName, final ConsoleInput ci, List args ) { if( args.isEmpty() ) { printHelp(ci.out, args); return; } final ShareManager share_manager; try{ share_manager = ci.azureus_core.getPluginManager().getDefaultPluginInterface().getShareManager(); }catch( ShareException e ){ ci.out.println( "ERROR: " + e.getMessage() + " ::"); Debug.printStackTrace( e ); return; } final String arg = (String) args.remove(0); if ( args.isEmpty() && ("list".equalsIgnoreCase(arg)) ) { ShareResource[] shares = share_manager.getShares(); if( shares.length == 0 ){ ci.out.println("> No shares found"); }else{ HashSet share_map = new HashSet(); int share_num = 0; for (int i=0;i " + share_num++ + ": " + shares[i].getName()); } } Iterator it = share_map.iterator(); TorrentManager tm = ci.azureus_core.getPluginManager().getDefaultPluginInterface().getTorrentManager(); TorrentAttribute category_attribute = tm.getAttribute( TorrentAttribute.TA_CATEGORY ); TorrentAttribute props_attribute = tm.getAttribute( TorrentAttribute.TA_SHARE_PROPERTIES ); while( it.hasNext()){ ShareResourceDirContents root = (ShareResourceDirContents)it.next(); String cat = root.getAttribute( category_attribute ); String props = root.getAttribute( props_attribute ); String extra = cat==null?"":(",cat=" + cat ); extra += props==null?"":(",props=" + props ); ci.out.println( "> " + share_num++ + ": " + root.getName() + extra ); outputChildren( ci, " ", root ); } } return; } String first_arg = (String)args.get(0); if ( first_arg.equals( "hash" ) && args.size() > 1 ){ byte[] hash = ByteFormatter.decodeString((String)args.get(1)); boolean force = false; if ( args.size() > 2 ){ force = ((String)args.get(2)).equalsIgnoreCase( "true" ); } if (( "remove".equalsIgnoreCase(arg))){ ShareResource[] shares = share_manager.getShares(); boolean done = false; for (int i=0;i Share " + share.getName() + " removed" ); done = true; break; } }catch( Throwable e ) { ci.out.println( "ERROR: " + e.getMessage() + " ::"); Debug.printStackTrace( e ); } } } if ( !done ){ ci.out.println( "> Share with hash " + ByteFormatter.encodeString( hash ) + " not found" ); } }else{ ci.out.println( "ERROR: Unsupported hash based command '" + arg + "'" ); } return; } final File path = new File( first_arg ); if( !path.exists() ) { ci.out.println( "ERROR: path [" +path+ "] does not exist." ); return; } if ( ("remove".equalsIgnoreCase(arg)) ) { ShareResource[] shares = share_manager.getShares(); boolean done = false; for (int i=0;i Share " + path.toString() + " removed" ); done = true; }catch( Throwable e ) { ci.out.println( "ERROR: " + e.getMessage() + " ::"); Debug.printStackTrace( e ); } break; } } if ( !done ){ ci.out.println( "> Share " + path.toString() + " not found" ); } return; } String category = null; String props = null; if ( args.size() == 2 ){ String properties = (String)args.get(1); StringTokenizer tok = new StringTokenizer( properties, ";" ); while( tok.hasMoreTokens()){ String token = tok.nextToken(); int pos = token.indexOf('='); if ( pos == -1 ){ ci.out.println( "ERROR: invalid properties string '" + properties + "'" ); return; }else{ String lhs = token.substring(0,pos).trim().toLowerCase(); String rhs = token.substring(pos+1).trim(); if ( lhs.equals( "category" )){ category = rhs; }else{ if ( lhs.equals( "private" ) || lhs.equals( "dht_backup" ) || lhs.equals( "comment" )){ if ( props == null ){ props = ""; } // _ are replaced with spaces if ( lhs.equals("comment")){ rhs = rhs.replace('_', ' ' ); } if ( rhs.length() > 0 ){ props += (props.length()==0?"":";") + lhs + "=" + rhs; } }else{ ci.out.println( "ERROR: invalid properties string '" + properties + "'" ); return; } } } } } final String f_category = category; final String f_props = props; new AEThread( "shareFile" ) { public void runSupport() { try{ ShareResource resource = share_manager.getShare( path ); if( "file".equalsIgnoreCase( arg ) ) { ci.out.println( "File [" +path+ "] share being processed in background..." ); if ( resource == null ){ resource = share_manager.addFile( path ); } }else if( "folder".equalsIgnoreCase( arg ) ) { ci.out.println( "Folder [" +path+ "] share being processed in background..." ); if ( resource == null ){ resource = share_manager.addDir( path ); } }else if( "contents".equalsIgnoreCase( arg ) ) { ci.out.println( "Folder contents [" +path+ "] share being processed in background..." ); if ( resource == null ){ resource = share_manager.addDirContents( path, false ); } }else if( "rcontents".equalsIgnoreCase( arg ) ) { ci.out.println( "Folder contents recursive [" +path+ "] share being processed in background..." ); if ( resource == null ){ resource = share_manager.addDirContents( path, true ); } }else{ ci.out.println( "ERROR: type '" + arg + "' unknown." ); } if ( resource != null ){ TorrentManager tm = ci.azureus_core.getPluginManager().getDefaultPluginInterface().getTorrentManager(); String cat = f_category; if ( cat != null ){ if ( cat.length() == 0 ){ cat = null; } resource.setAttribute( tm.getAttribute( TorrentAttribute.TA_CATEGORY), cat ); } String pro = f_props; if ( pro != null ){ if ( pro.length() == 0 ){ pro = null; } resource.setAttribute( tm.getAttribute( TorrentAttribute.TA_SHARE_PROPERTIES), pro ); } } if ( resource != null ){ ci.out.println( "... processing complete" ); } }catch( Throwable e ) { ci.out.println( "ERROR: " + e.getMessage() + " ::"); Debug.printStackTrace( e ); } } }.start(); } protected void outputChildren( ConsoleInput ci, String indent, ShareResourceDirContents node ) { ShareResource[] kids = node.getChildren(); for (int i=0;i -----"); out.println("'set' options: "); out.println("\t-export\t\tPrints all the options with non-defaut values."); } public void execute(String commandName,ConsoleInput ci, List args) { boolean non_defaults = false; Iterator it = args.iterator(); while( it.hasNext()){ String arg = (String)it.next(); if ( arg.equals( "-export" )){ non_defaults = true; it.remove(); } } if( args.isEmpty() ) { displayOptions(ci.out, new StringPattern("*"), non_defaults ); return; } String external_name = (String) args.get(0); String internal_name = (String) ExternalUIConst.parameterlegacy.get(external_name); if( internal_name == null || internal_name.length() == 0 ) { internal_name = external_name; } // else // ci.out.println("> converting " + origParamName + " to " + parameter); Parameter param; switch( args.size() ) { case 1: // allow wildcards : eg: Core* or *DHT* to shorten result list StringPattern sp = new StringPattern(internal_name); if( sp.hasWildcard() ) { displayOptions(ci.out, sp, non_defaults); } else { // try to display the value of the specified parameter if( ! COConfigurationManager.doesParameterDefaultExist( internal_name ) ) { ci.out.println("> Command 'set': Parameter '" + external_name + "' unknown."); return; } param = Parameter.get(internal_name,external_name); ci.out.println( param.getString( false ) ); } break; case 2: case 3: String setto = (String) args.get(1); String type; if( args.size() == 2 ) { // guess the parameter type by getting the current value and determining its type param = Parameter.get( internal_name, external_name ); type = param.getType(); } else type = (String) args.get(2); boolean success = false; if( type.equalsIgnoreCase("int") || type.equalsIgnoreCase("integer") ) { COConfigurationManager.setParameter( internal_name, Integer.parseInt( setto ) ); success = true; } else if( type.equalsIgnoreCase("bool") || type.equalsIgnoreCase("boolean") ) { boolean value; if ( setto.equalsIgnoreCase("true") || setto.equalsIgnoreCase("y") || setto.equals("1" )){ value = true; }else{ value = false; } COConfigurationManager.setParameter( internal_name, value ); success = true; } else if( type.equalsIgnoreCase("float") ) { COConfigurationManager.setParameter( internal_name, Float.parseFloat( setto ) ); success = true; } else if( type.equalsIgnoreCase("string") ) { COConfigurationManager.setParameter( internal_name, setto ); success = true; } else if( type.equalsIgnoreCase("password") ) { SHA1Hasher hasher = new SHA1Hasher(); byte[] password = setto.getBytes(); byte[] encoded; if(password.length > 0){ encoded = hasher.calculateHash(password); }else{ encoded = password; } COConfigurationManager.setParameter( internal_name, encoded ); success = true; } if( success ) { COConfigurationManager.save(); ci.out.println("> Parameter '" + external_name + "' set to '" + setto + "'. [" + type + "]"); } else ci.out.println("ERROR: invalid type given"); break; default: ci.out.println("Usage: 'set \"parameter\" value type', where type = int, bool, float, string, password"); break; } } private void displayOptions(PrintStream out, StringPattern sp, boolean non_defaults) { sp.setIgnoreCase(true); Iterator I = non_defaults?COConfigurationManager.getDefinedParameters().iterator():COConfigurationManager.getAllowedParameters().iterator(); Map backmap = new HashMap(); for (Iterator iter = ExternalUIConst.parameterlegacy.entrySet().iterator(); iter.hasNext();) { Map.Entry entry = (Map.Entry) iter.next(); backmap.put( entry.getValue(), entry.getKey() ); } TreeSet srt = new TreeSet(); while (I.hasNext()) { String internal_name = (String) I.next(); String external_name = (String) backmap.get(internal_name); if ( external_name == null ){ external_name = internal_name; } if( sp.matches(external_name) ) { Parameter param = Parameter.get( internal_name, external_name ); if ( non_defaults ){ if ( !param.isDefault()){ srt.add( param.getString( true )); } }else{ srt.add( param.getString( false )); } } } I = srt.iterator(); while (I.hasNext()) { out.println((String) I.next()); } } /** * class that represents a parameter. we can use one of these objects to * verify a parameter's type and value as well as whether or not a value has been set. * @author pauld */ private static class Parameter { private static final int PARAM_INT = 1; private static final int PARAM_BOOLEAN = 2; private static final int PARAM_STRING = 4; private static final int PARAM_OTHER = 8; /** * returns a new Parameter object reprenting the specified parameter name * @param parameter * @return */ public static Parameter get( String internal_name, String external_name ) { int underscoreIndex = external_name.indexOf('_'); int nextchar = external_name.charAt(underscoreIndex + 1); if ( internal_name != external_name && "ibs".indexOf(nextchar) >= 0 ){ try { if( nextchar == 'i' ) { int value = COConfigurationManager.getIntParameter(internal_name, Integer.MIN_VALUE); return new Parameter(internal_name, external_name, value == Integer.MIN_VALUE ? (Integer)null : new Integer(value) ); } else if( nextchar == 'b' ) { // firstly get it as an integer to make sure it is actually set to something if( COConfigurationManager.getIntParameter(internal_name, Integer.MIN_VALUE) != Integer.MIN_VALUE ) { boolean b = COConfigurationManager.getBooleanParameter(internal_name); return new Parameter(internal_name, external_name, Boolean.valueOf(b)); } else { return new Parameter(internal_name, external_name, (Boolean)null); } } else { String value = COConfigurationManager.getStringParameter(internal_name, NULL_STRING); return new Parameter( internal_name, external_name, NULL_STRING.equals(value) ? null : value); } } catch (Throwable e){ } } Object v = COConfigurationManager.getParameter( internal_name ); try { if ( v instanceof Long || v instanceof Integer ){ int value = COConfigurationManager.getIntParameter(internal_name, Integer.MIN_VALUE); return new Parameter(internal_name, external_name, value == Integer.MIN_VALUE ? (Integer)null : new Integer(value) ); }else if ( v instanceof Boolean ){ boolean value = COConfigurationManager.getBooleanParameter( internal_name ); return new Parameter( internal_name, external_name, Boolean.valueOf( value )); }else if ( v instanceof String || v instanceof byte[] ){ String value = COConfigurationManager.getStringParameter(internal_name); return new Parameter( internal_name, external_name, NULL_STRING.equals(value) ? null : value); }else{ return new Parameter( internal_name, external_name, v, PARAM_OTHER ); } }catch( Throwable e2 ){ return new Parameter( internal_name, external_name, v, PARAM_OTHER ); } } public Parameter( String iname, String ename, Boolean val ) { this(iname,ename, val, PARAM_BOOLEAN); } public Parameter( String iname, String ename, Integer val ) { this(iname,ename, val, PARAM_INT); } public Parameter( String iname, String ename, String val ) { this(iname,ename, val, PARAM_STRING); } private Parameter( String _iname, String _ename, Object _val, int _type ) { type = _type; iname = _iname; ename = _ename; value = _val; isSet = (value != null); if ( !isSet ){ def = COConfigurationManager.getDefault(iname); if ( def != null ){ if ( def instanceof Long ){ type = PARAM_INT; } } } } private int type; private String iname; private String ename; private Object value; private boolean isSet; private Object def; public String getType() { switch( type ) { case PARAM_BOOLEAN: return "bool"; case PARAM_INT: return "int"; case PARAM_STRING: return "string"; default: return "unknown"; } } public boolean isDefault() { return( !isSet ); } public String getString( boolean set_format ) { if( isSet ){ if ( set_format ){ return( "set " + quoteIfNeeded( ename ) + " " + quoteIfNeeded(value.toString()) + " " + getType()); }else{ return "> " + ename + ": " + value + " [" + getType() + "]"; } }else{ if ( def == null ){ return "> " + ename + " is not set. [" + getType() + "]"; }else{ return "> " + ename + " is not set. [" + getType() + ", default: " + def + "]"; } } } protected String quoteIfNeeded( String str ) { if ( str.indexOf(' ') == -1 ){ return( str ); } return( "\"" + str + "\"" ); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/Hack.java0000644000175000017500000002756611307334272023570 0ustar adrianadrian/* * Written and copyright 2001-2004 Tobias Minich. Distributed under the GNU * General Public License; see the README file. This code comes with NO * WARRANTY. * * Hack.java * * Created on 22.03.2004 * */ package org.gudy.azureus2.ui.console.commands; import java.io.PrintStream; import java.net.URI; import java.net.URL; import java.util.Iterator; import java.util.List; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.ui.console.ConsoleInput; /** * @author Tobias Minich */ public class Hack extends TorrentCommand { private final CommandCollection subCommands = new CommandCollection(); public Hack() { super("hack", "#", "Hacking"); subCommands.add(new HackFile()); subCommands.add(new HackTracker()); subCommands.add(new HackDownloadSpeed()); subCommands.add(new HackUploadSpeed()); subCommands.add(new HackUploads()); } public String getCommandDescriptions() { return "hack []\t#\tModify torrent settings. Use without parameters for further help."; } public void printHelpExtra(PrintStream out, List args) { out.println("> -----"); out.println("'hack' syntax:"); if( args.size() > 0 ) { String command = (String) args.remove(0); IConsoleCommand cmd = subCommands.get(command); if( cmd != null ) cmd.printHelp(out, args); return; } out.println("hack "); out.println(); out.println(" can be one of the following:"); out.println("<#>\t\tNumber of a torrent. You have to use 'show torrents' first as the number is taken from there."); out.println("hash \tApplied to torrent with the hash as given in the xml output or extended torrent info ('show <#>')."); out.println("help\t\tDetailed help for "); out.println(); out.println("Available s:"); for (Iterator iter = subCommands.iterator(); iter.hasNext();) { TorrentSubCommand cmd = (TorrentSubCommand) iter.next(); out.println(cmd.getCommandDescriptions()); } out.println("> -----"); } /** * finds the appropriate subcommand and executes it. * the execute() method will have taken care of finding/iterating over the * appropriate torrents */ protected boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { if (args.isEmpty()) { ci.out.println("> Not enough parameters for command '" + getCommandName() + "'."); return false; } String subCommandName = (String)args.remove(0); TorrentSubCommand cmd = (TorrentSubCommand) subCommands.get(subCommandName); if( cmd != null ) return cmd.performCommand(ci, dm, args); else { ci.out.println("> Command 'hack': Command parameter '" + subCommandName + "' unknown."); return false; } } private static class HackDownloadSpeed extends TorrentSubCommand { public HackDownloadSpeed() { super("downloadspeed", "d"); } public String getCommandDescriptions() { return "downloadspeed\td\tSet max download speed [in kbps]of a torrent (0 for unlimited)."; } /** * locate the appropriate subcommand and execute it */ public boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { if (args.isEmpty()) { ci.out.println("> Command 'hack': Not enough parameters for subcommand '" + getCommandName() + "'"); return false; } int newSpeed = Math.max(-1, Integer.parseInt((String) args.get(0))); dm.getStats().setDownloadRateLimitBytesPerSecond(newSpeed*1024); return true; } } private static class HackUploadSpeed extends TorrentSubCommand { public HackUploadSpeed() { super("uploadspeed", "u"); } public String getCommandDescriptions() { return "uploadspeed\tu\tSet max upload speed [in kbps] of a torrent (0 for unlimited)."; } /** * locate the appropriate subcommand and execute it */ public boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { if (args.isEmpty()) { ci.out.println("> Command 'hack': Not enough parameters for subcommand '" + getCommandName() + "'"); return false; } int newSpeed = Math.max(-1, Integer.parseInt((String) args.get(0))); dm.getStats().setUploadRateLimitBytesPerSecond(newSpeed*1024); return true; } } private static class HackUploads extends TorrentSubCommand { public HackUploads() { super("uploads", "v"); } public String getCommandDescriptions() { return "uploads\tv\tSet max upload slots of a torrent."; } /** * locate the appropriate subcommand and execute it */ public boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { if (args.isEmpty()) { ci.out.println("> Command 'hack': Not enough parameters for subcommand '" + getCommandName() + "'"); return false; } int newSlots = Math.max(-1, Integer.parseInt((String) args.get(0))); dm.setMaxUploads(newSlots); return true; } } private static class HackTracker extends TorrentSubCommand { private final CommandCollection subCommands = new CommandCollection(); public HackTracker() { super("tracker", "t"); subCommands.add(new HackHost()); subCommands.add(new HackPort()); subCommands.add(new HackURL()); } public void printHelpExtra(PrintStream out, List args) { out.println("hack tracker [command] "); out.println(); out.println("[command] can be one of the following:"); for (Iterator iter = subCommands.iterator(); iter.hasNext();) { TorrentSubCommand cmd = (TorrentSubCommand) iter.next(); out.println(cmd.getCommandDescriptions()); } out.println(); out.println("You can also omit [command] and only give a new full URL (just like the [command] 'url')."); out.println("> -----"); } /** * locate the appropriate subcommand and execute it */ public boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { if (args.isEmpty()) { ci.out.println("> Command 'hack': Not enough parameters for subcommand '" + getCommandName() + "'"); return false; } String trackercommand = (String) args.remove(0); TRTrackerAnnouncer client = dm.getTrackerClient(); //ci.out.println("> Command 'hack': Debug: '"+trackercommand+"'"); if (client == null) { ci.out.println("> Command 'hack': Tracker interface not available."); return false; } TorrentSubCommand cmd = (TorrentSubCommand) subCommands.get(trackercommand); if( cmd == null ) { args.add(trackercommand); cmd = (TorrentSubCommand) subCommands.get("url"); } return cmd.performCommand(ci, dm, args); } public String getCommandDescriptions() { return "tracker\t\tt\tModify Tracker URL of a torrent."; } } private static class HackFile extends TorrentSubCommand { public HackFile() { super("file", "f"); } public void printHelpExtra(PrintStream out, List args) { out.println("hack file <#> "); out.println(); out.println("<#> Number of the file."); out.println(); out.println(" can be one of the following:"); out.println("normal\t\tn\tNormal Priority"); out.println("high\t\th|+\tHigh Priority"); out.println("nodownload\t!|-\tDon't download this file."); out.println("> -----"); } public boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { if (args.size() < 2) { ci.out.println("> Command 'hack': Not enough parameters for subcommand 'file'."); return false; } try { DiskManager disk = dm.getDiskManager(); DiskManagerFileInfo files[] = disk.getFiles(); int file = Integer.parseInt((String) args.get(0)); String c = (String) args.get(1); if (c.equalsIgnoreCase("normal") || c.equalsIgnoreCase("n")) { files[file - 1].setSkipped(false); files[file - 1].setPriority(false); ci.out.println("> Set file '"+files[file - 1].getFile(true).getName()+"' to normal priority."); } else if (c.equalsIgnoreCase("high") || c.equalsIgnoreCase("h") || c.equalsIgnoreCase("+")) { files[file - 1].setSkipped(false); files[file - 1].setPriority(true); ci.out.println("> Set file '"+files[file - 1].getFile(true).getName()+"' to high priority."); } else if (c.equalsIgnoreCase("nodownload") || c.equalsIgnoreCase("!") || c.equalsIgnoreCase("-")) { files[file - 1].setSkipped(true); files[file - 1].setPriority(false); ci.out.println("> Stopped to download file '"+files[file - 1].getFile(true).getName()+"'."); } else { ci.out.println("> Command 'hack': Unknown priority '" + c + "' for command parameter 'file'."); return false; } return true; } catch (Exception e) { ci.out.println("> Command 'hack': Exception while executing subcommand 'file': " + e.getMessage()); return false; } } public String getCommandDescriptions() { return "file\t\tf\tModify priority of a single file of a batch torrent."; } } private static class HackPort extends TorrentSubCommand { public HackPort() { super("port", "p"); } public boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { if (args.isEmpty()) { ci.out.println("> Command 'hack': Not enough parameters for subcommand parameter 'port'."); return false; } TRTrackerAnnouncer client = dm.getTrackerClient(); try { URI uold = new URI(client.getTrackerURL().toString()); String portStr = (String) args.get(0); URI unew = new URI(uold.getScheme(), uold.getUserInfo(), uold.getHost(), Integer.parseInt(portStr), uold.getPath(), uold.getQuery(), uold.getFragment()); client.setTrackerURL(new URL(unew.toString())); ci.out.println("> Set Tracker URL for '"+dm.getSaveLocation()+"' to '"+unew.toString()+"'"); } catch (Exception e) { ci.out.println("> Command 'hack': Assembling new tracker url failed: "+e.getMessage()); return false; } return true; } public String getCommandDescriptions() { return "port\t\tp\tChange the port."; } } private static class HackHost extends TorrentSubCommand { public HackHost() { super("host", "h"); } public boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { if (args.isEmpty()) { ci.out.println("> Command 'hack': Not enough parameters for subcommand parameter 'host'."); return false; } TRTrackerAnnouncer client = dm.getTrackerClient(); try { URI uold = new URI(client.getTrackerURL().toString()); URI unew = new URI(uold.getScheme(), uold.getUserInfo(), (String)args.get(0), uold.getPort(), uold.getPath(), uold.getQuery(), uold.getFragment()); client.setTrackerURL(new URL(unew.toString())); ci.out.println("> Set Tracker URL for '"+dm.getSaveLocation()+"' to '"+unew.toString()+"'"); } catch (Exception e) { ci.out.println("> Command 'hack': Assembling new tracker url failed: "+e.getMessage()); return false; } return true; } public String getCommandDescriptions() { return "host\t\th\tChange the host."; } } private static class HackURL extends TorrentSubCommand { public HackURL() { super("url", "u"); } public boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { if (args.isEmpty()) { ci.out.println("> Command 'hack': Not enough parameters for subcommand parameter 'url'."); return false; } TRTrackerAnnouncer client = dm.getTrackerClient(); try { String uriStr = (String) args.get(0); URI uri = new URI(uriStr); client.setTrackerURL(new URL(uri.toString())); ci.out.println("> Set Tracker URL for '"+dm.getSaveLocation()+"' to '"+uri+"'"); } catch (Exception e) { ci.out.println("> Command 'hack': Parsing tracker url failed: "+e.getMessage()); return false; } return true; } public String getCommandDescriptions() { return "url\t\tu\tChange the full URL (Note: you have to include the '/announce' part)."; } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/TorrentQueue.java0000644000175000017500000000357211021643236025347 0ustar adrianadrian/* * Created on 04/12/2004 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.util.List; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.ui.console.ConsoleInput; /** * console command to queue a torrent. * extracted from the Torrent class written by tobias */ public class TorrentQueue extends TorrentCommand { public TorrentQueue() { super("queue", "q", "Queueing"); } protected boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { try { if (dm.getState() == DownloadManager.STATE_STOPPED) dm.setStateQueued(); else if (dm.getState() == DownloadManager.STATE_DOWNLOADING || dm.getState() == DownloadManager.STATE_SEEDING) dm.stopIt( DownloadManager.STATE_QUEUED, false, false ); else return false; } catch (Exception e) { e.printStackTrace(ci.out); return false; } return true; } public String getCommandDescriptions() { return("queue ()\tq\tQueue torrent(s)."); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/Alias.java0000644000175000017500000001012711021643236023730 0ustar adrianadrian/* * Created on 29/12/2004 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.util.Iterator; import java.util.List; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import org.gudy.azureus2.ui.console.ConsoleInput; /** * the alias command will add/remove/modify aliases to the CLI input reader. * aliases will be expanded and take priority over standard commands. * @author pauld */ public class Alias extends OptionsConsoleCommand { /** * @param _commandNames */ public Alias() { super("alias"); getOptions().addOption(new Option("d", "delete", false, "delete the specified alias")); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.console.commands.IConsoleCommand#getCommandDescriptions() */ public String getCommandDescriptions() { return "alias [-d] [aliasname] [arguments...]\tadd/modify/delete aliases. use with no argument to show existing aliases"; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.console.commands.OptionsConsoleCommand#execute(java.lang.String, org.gudy.azureus2.ui.console.ConsoleInput, org.apache.commons.cli.CommandLine) */ public void execute(String commandName, ConsoleInput console, CommandLine commandLine) { List args = commandLine.getArgList(); if( args.isEmpty() ) { if( commandLine.hasOption('d') ) console.out.println(commandName + " --delete requires the name of an alias to remove"); else printAliases(console); return; } if( commandLine.hasOption('d') ) deleteAlias(console, (String) args.get(0)); else { String aliasName = (String) args.remove(0); if( args.isEmpty() ) { printAlias(console, aliasName); } else addAlias( console, aliasName, args ); } } /** * @param aliasName */ private void printAlias(ConsoleInput ci, String aliasName) { String aliasText = (String) ci.aliases.get(aliasName); if( aliasText == null ) { ci.out.println("> Error: Alias '" + aliasName + "' does not exist"); } else { ci.out.println("> " + aliasName + "=" + aliasText); } } /** * @param object */ private void deleteAlias(ConsoleInput ci, String aliasName) { // ci.out.println("removing alias: " + aliasName); if( ci.aliases.remove(aliasName) == null ) { ci.out.println("> Error: Alias '" + aliasName + "' does not exist"); } else { ci.out.println("> Alias: '" + aliasName + "' deleted"); ci.saveAliases(); } } /** * @param object * @param argList */ private void addAlias(ConsoleInput ci, String aliasName, List argList) { // ci.out.println("adding alias: " + aliasName); StringBuffer aliasText = new StringBuffer(); for (Iterator iter = argList.iterator(); iter.hasNext();) { String arg = (String) iter.next(); if( arg.indexOf(" ") != -1 ) aliasText.append("\"").append(arg).append("\""); else aliasText.append(arg); aliasText.append(" "); } ci.aliases.put(aliasName, aliasText.toString()); ci.saveAliases(); printAlias(ci, aliasName); } /** * prints out a list of all the aliases * @param out */ private void printAliases(ConsoleInput ci) { for (Iterator iter = ci.aliases.keySet().iterator(); iter.hasNext();) { String aliasName = (String)iter.next(); printAlias(ci, aliasName); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/Plugin.java0000644000175000017500000001236311053722276024150 0ustar adrianadrian/* * Created on 22 Aug 2008 * Created by Allan Crooks * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.ui.console.commands; import java.io.File; import java.io.PrintStream; import java.util.List; import java.util.TreeSet; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.ui.console.ConsoleInput; import org.gudy.azureus2.ui.console.util.TextWrap; public class Plugin extends IConsoleCommand { public Plugin() { super("plugin"); } public String getCommandDescriptions() { return("plugin [various options]\t\tRun with no parameter for more help."); } public void printHelpExtra(PrintStream out, List args) { out.println("> -----"); out.println("Subcommands:"); out.println("location\t\tLists where plugins are being loaded from"); out.println("list\t\tList all running plugins"); out.println("listall\t\tList all plugins - running or not"); out.println("status pluginid\tPrints the status of a given plugin"); out.println("startup pluginid on|off\tEnables or disables the plugin running at startup"); out.println("> -----"); } public void execute(String commandName, ConsoleInput ci, List args) { if (args.isEmpty()) { printHelpExtra(ci.out, args); return; } String subcmd = (String)args.get(0); if (!java.util.Arrays.asList(new String[] { "location", "list", "listall", "status", "startup" }).contains(subcmd)) { ci.out.println("Invalid subcommand: " + subcmd); ci.out.println(); return; } if (subcmd.equals("list") || subcmd.equals("listall")) { boolean all_plugins = subcmd.equals("listall"); ci.out.println("> -----"); PluginInterface[] plugins = ci.getCore().getPluginManager().getPluginInterfaces(); TreeSet plugin_ids = new TreeSet(String.CASE_INSENSITIVE_ORDER); for (int i=0; i -----"); return; } if (subcmd.equals("location")) { // Taken from ConfigSectionPlugins. File fUserPluginDir = FileUtil.getUserFile("plugins"); String sep = File.separator; String sUserPluginDir; try{ sUserPluginDir = fUserPluginDir.getCanonicalPath(); }catch( Throwable e ){ sUserPluginDir = fUserPluginDir.toString(); } if (!sUserPluginDir.endsWith(sep)) { sUserPluginDir += sep; } File fAppPluginDir = FileUtil.getApplicationFile("plugins"); String sAppPluginDir; try{ sAppPluginDir = fAppPluginDir.getCanonicalPath(); }catch( Throwable e ){ sAppPluginDir = fAppPluginDir.toString(); } if (!sAppPluginDir.endsWith(sep)) { sAppPluginDir += sep; } ci.out.println("Shared plugin location:"); ci.out.println(" " + sAppPluginDir); ci.out.println("User plugin location:"); ci.out.println(" " + sUserPluginDir); ci.out.println(); return; } // Commands from this point require a plugin ID. if (args.size() == 1) { ci.out.println("No plugin ID given."); ci.out.println(); return; } String plugin_id = (String)args.get(1); PluginInterface plugin = ci.getCore().getPluginManager().getPluginInterfaceByID(plugin_id, false); if (plugin == null) { ci.out.println("Invalid plugin ID: " + plugin_id); ci.out.println(); return; } if (subcmd.equals("status")) { ci.out.println("ID : " + plugin.getPluginID()); ci.out.println("Name : " + plugin.getPluginName()); ci.out.println("Version: " + plugin.getPluginVersion()); ci.out.println("Running: " + plugin.getPluginState().isOperational()); ci.out.println("Runs at startup: " + plugin.getPluginState().isLoadedAtStartup()); if (!plugin.getPluginState().isBuiltIn()) { ci.out.println("Location: " + plugin.getPluginDirectoryName()); } ci.out.println(); return; } if (subcmd.equals("startup")) { if (args.size() == 2) { ci.out.println("Need to pass either \"on\" or \"off\""); ci.out.println(); return; } String enabled_mode = (String)args.get(2); if (enabled_mode.equals("on")) { plugin.getPluginState().setLoadedAtStartup(true); } else if (enabled_mode.equals("off")) { plugin.getPluginState().setLoadedAtStartup(false); } else { ci.out.println("Need to pass either \"on\" or \"off\""); ci.out.println(); return; } ci.out.println("Done."); ci.out.println(); return; } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/Log.java0000644000175000017500000001363011021643236023422 0ustar adrianadrian/* * Written and copyright 2001-2004 Tobias Minich. Distributed under the GNU * General Public License; see the README file. This code comes with NO * WARRANTY. * * Log.java * * Created on 23.03.2004 * */ package org.gudy.azureus2.ui.console.commands; import java.io.IOException; import java.util.*; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.log4j.Appender; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.FileAppender; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.varia.DenyAllFilter; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.logging.LoggerChannel; import org.gudy.azureus2.plugins.logging.LoggerChannelListener; import org.gudy.azureus2.ui.console.ConsoleInput; /** * @author Tobias Minich */ public class Log extends OptionsConsoleCommand { private Map channel_listener_map = new HashMap(); public Log() { super("log", "l"); } protected Options getOptions() { Options options = new Options(); options.addOption( new Option("f", "filename", true, "filename to write log to")); return options; } public void execute(String commandName, final ConsoleInput ci, CommandLine commandLine) { Appender con = Logger.getRootLogger().getAppender("ConsoleAppender"); List args = commandLine.getArgList(); if ((con != null) && (!args.isEmpty())) { String subcommand = (String) args.get(0); if ("off".equalsIgnoreCase(subcommand) ) { if ( args.size() == 1 ){ con.addFilter(new DenyAllFilter()); ci.out.println("> Console logging off"); }else{ String name = (String)args.get(1); Object[] entry = (Object[])channel_listener_map.remove( name ); if ( entry == null ){ ci.out.println( "> Channel '" + name + "' not being logged" ); }else{ ((LoggerChannel)entry[0]).removeListener((LoggerChannelListener)entry[1]); ci.out.println( "> Channel '" + name + "' logging off" ); } } } else if ("on".equalsIgnoreCase(subcommand) ) { if ( args.size() == 1 ){ if( commandLine.hasOption('f') ) { // send log output to a file String filename = commandLine.getOptionValue('f'); try { Appender newAppender = new FileAppender(new PatternLayout("%d{ISO8601} %c{1}-%p: %m%n"), filename, true); newAppender.setName("ConsoleAppender"); Logger.getRootLogger().removeAppender(con); Logger.getRootLogger().addAppender(newAppender); ci.out.println("> Logging to filename: " + filename); } catch (IOException e) { ci.out.println("> Unable to log to file: " + filename + ": " + e); } } else { if( ! (con instanceof ConsoleAppender) ) { Logger.getRootLogger().removeAppender(con); con = new ConsoleAppender(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN)); con.setName("ConsoleAppender"); Logger.getRootLogger().addAppender(con); } // switch back to console appender ci.out.println("> Console logging on"); } con.clearFilters(); }else{ // hack - dunno how to do plugin-specific logging using these damn appenders.. Map channel_map = getChannelMap( ci ); final String name = (String)args.get(1); LoggerChannel channel = (LoggerChannel)channel_map.get(name); if ( channel == null ){ ci.out.println( "> Channel '" + name + "' not found" ); }else if ( channel_listener_map.get(name) != null ){ ci.out.println( "> Channel '" + name + "' already being logged" ); }else{ LoggerChannelListener l = new LoggerChannelListener() { public void messageLogged( int type, String content ) { ci.out.println( "["+name+"] "+ content ); } public void messageLogged( String str, Throwable error ) { ci.out.println( "["+name+"] "+ str ); error.printStackTrace( ci.out ); } }; channel.addListener( l ); channel_listener_map.put( name, new Object[]{ channel, l }); ci.out.println( "> Channel '" + name + "' on" ); } } }else if ( subcommand.equalsIgnoreCase("list" )){ Map channel_map = getChannelMap( ci ); Iterator it = channel_map.keySet().iterator(); while( it.hasNext()){ String name = (String)it.next(); ci.out.println( " " + name + " [" + ( channel_listener_map.get( name ) == null?"off":"on") + "]" ); } } else { ci.out.println("> Command 'log': Subcommand '" + subcommand + "' unknown."); } } else { ci.out.println("> Console logger not found or missing subcommand for 'log'\r\n> log syntax: log [-f filename] (on [name]|off [name]|list)"); } } protected Map getChannelMap( ConsoleInput ci ) { Map channel_map = new HashMap(); PluginInterface[] pis = ci.azureus_core.getPluginManager().getPluginInterfaces(); for (int i=0;i 0 ){ if ( logs.length == 1 ){ channel_map.put( pis[i].getPluginName(),logs[0] ); }else{ for (int j=0;j)\t\th\tStop torrent(s)."); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/TorrentCheck.java0000644000175000017500000000334311021643236025274 0ustar adrianadrian/* * Created on 04/12/2004 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.util.List; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.ui.console.ConsoleInput; /** * console command to initiate recheck of a torrent. * code was originally in Torrent class authored by tobias */ public class TorrentCheck extends TorrentCommand { public TorrentCheck() { super("check", "c", "Initiating recheck of"); } protected boolean performCommand(ConsoleInput ci, DownloadManager dm, List args) { try { if (dm.canForceRecheck()) { dm.forceRecheck(); return true; } else return false; } catch (Exception e) { e.printStackTrace(ci.out); return false; } } public String getCommandDescriptions() { return("check ()\tc\tForce recheck on torrent(s)."); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/commands/TorrentCommand.java0000644000175000017500000001624711021643236025644 0ustar adrianadrian/* * Written and copyright 2001-2003 Tobias Minich. Distributed under the GNU * General Public License; see the README file. This code comes with NO * WARRANTY. * * Torrent.java * * Created on 23.03.2004 * */ package org.gudy.azureus2.ui.console.commands; import java.io.PrintStream; import java.util.Iterator; import java.util.List; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.tracker.host.TRHost; import org.gudy.azureus2.core3.tracker.host.TRHostTorrent; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.ui.console.ConsoleInput; import org.gudy.azureus2.ui.console.UserProfile; /** * base class for objects which need to operate on specific torrents. * this class allows the torrent to be identified by hash, number or * 'all' and will pass the appropriate torrent(s) to the subclasses 'performCommand' method * @author tobi */ public abstract class TorrentCommand extends IConsoleCommand { private final String action; /** * initializes the torrent command * @param commandNames (the first item in the array is regarded as the primary command name) * @param action a description to be used when this command is executed */ public TorrentCommand(String main_name, String short_name, String action) { super(main_name, short_name); this.action = action; } protected String getAction() { return action; } protected abstract boolean performCommand(ConsoleInput ci, DownloadManager dm, List args); /** * Stub for commands that operate on a hosted torrent rather than downloadmanager * @param ci * @param args * @return */ protected boolean performCommand(ConsoleInput ci, TRHostTorrent torrent, List args) { return( false ); } public void execute(String commandName, ConsoleInput ci, List args) { if (!args.isEmpty()) { String subcommand = (String) args.remove(0); if (ci.torrents.isEmpty()) { ci.out.println("> Command '" + getCommandName() + "': No torrents in list (Maybe you forgot to 'show torrents' first)."); } else { String name; DownloadManager dm; try { int number = Integer.parseInt(subcommand); if ((number > 0) && (number <= ci.torrents.size())) { dm = (DownloadManager) ci.torrents.get(number - 1); if (dm.getDisplayName() == null) name = "?"; else name = dm.getDisplayName(); performCommandIfAllowed(ci, args, dm, "#" + subcommand, name); } else ci.out.println("> Command '" + getCommandName() + "': Torrent #" + subcommand + " unknown."); } catch (NumberFormatException e) { if ("all".equalsIgnoreCase(subcommand)) { Iterator torrent = ci.torrents.iterator(); while (torrent.hasNext()) { dm = (DownloadManager) torrent.next(); if (dm.getDisplayName() == null) name = "?"; else name = dm.getDisplayName(); performCommandIfAllowed(ci, args, dm, subcommand, name); } } else if ("hash".equalsIgnoreCase(subcommand)) { String hash = (String) args.remove(0); List torrents = ci.getGlobalManager().getDownloadManagers(); boolean foundit = false; Iterator torrent = torrents.iterator(); while (torrent.hasNext()) { dm = (DownloadManager) torrent.next(); if (hash.equals(TorrentUtils.nicePrintTorrentHash(dm.getTorrent(), true))) { if (dm.getDisplayName() == null) name = "?"; else name = dm.getDisplayName(); // FIXME: check user permission here and fix it to take torrent hash instead of subcommand performCommandIfAllowed(ci, args, dm, hash, name); foundit = true; break; } } if ( !foundit ){ // second check for TRHost host = ci.getCore().getTrackerHost(); if ( host != null ){ TRHostTorrent[] h_torrents = host.getTorrents(); for (int i=0;i Command '" + getCommandName() + "': Hash '" + hash + "' unknown."); } } else { ci.out.println("> Command '" + getCommandName() + "': Subcommand '" + subcommand + "' unknown."); } } } } else { ci.out.println("> Missing subcommand for '" + getCommandName() + "'"); printHelp(ci.out, args); } } /** * checks the role of the user. if the user is a 'guest', they are not able to * perform any actions on the torrents. they are a 'read only' role. * if they are a 'user' role, they are only able to modify their own torrents. * users with the 'admin' role can modify anybody's torrents * @param ci * @param args * @param dm * @param name * @param subcommand */ private void performCommandIfAllowed(ConsoleInput ci, List args, DownloadManager dm, String desc, String name) { if( ! UserProfile.ADMIN.equals( ci.getUserProfile().getUserType() ) ) { if( UserProfile.USER.equals( ci.getUserProfile().getUserType() ) ) { String owner = dm.getDownloadState().getAttribute(DownloadManagerState.AT_USER); if(! ci.getUserProfile().getUsername().equals(owner) ) { ci.out.println("> " + getAction() + " torrent " + desc + " (" + name + ") failed: Permission Denied. Users can only modify their own torrents"); return; } } else { ci.out.println("> " + getAction() + " torrent " + desc + " (" + name + ") failed: Permission Denied. Guests cannot modify torrents"); return; } } if (performCommand(ci, dm, args)) ci.out.println("> " + getAction() + " Torrent " + desc + " (" + name + ") succeeded."); else ci.out.println("> " + getAction() + " Torrent " + desc + " (" + name + ") failed."); } private void performCommandIfAllowed(ConsoleInput ci, List args, TRHostTorrent torrent, String desc, String name) { if( ! UserProfile.ADMIN.equals( ci.getUserProfile().getUserType() ) ) { if( UserProfile.USER.equals( ci.getUserProfile().getUserType() ) ) { // TODO: we don't currently record user against host-torrent... } else { ci.out.println("> " + getAction() + " torrent " + desc + " (" + name + ") failed: Permission Denied. Guests cannot modify torrents"); return; } } if (performCommand(ci, torrent, args)) ci.out.println("> " + getAction() + " Torrent " + desc + " (" + name + ") succeeded."); else ci.out.println("> " + getAction() + " Torrent " + desc + " (" + name + ") failed."); } /** * prints out the syntax of this command */ public void printHelpExtra(PrintStream out, List args) { out.println("> " + getCommandName() + " syntax: " + getCommandName() + " (<#>|all|hash )"); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/UI.java0000644000175000017500000002003711053726622021422 0ustar adrianadrian/* Written and copyright 2001-2003 Tobias Minich. * Distributed under the GNU General Public License; see the README file. * This code comes with NO WARRANTY. * * * Main.java * * Created on 22. August 2003, 00:04 */ package org.gudy.azureus2.ui.console; import java.io.File; import java.io.PrintStream; import java.net.URL; import org.apache.log4j.Logger; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderFactory; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ui.UIException; import org.gudy.azureus2.plugins.ui.UIInputReceiver; import org.gudy.azureus2.plugins.ui.UIInstance; import org.gudy.azureus2.plugins.ui.UIInstanceFactory; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.UIManagerEvent; import org.gudy.azureus2.plugins.ui.UIManagerEventListener; import org.gudy.azureus2.plugins.ui.UIMessage; import org.gudy.azureus2.ui.common.IUserInterface; import org.gudy.azureus2.ui.common.UIConst; import org.gudy.azureus2.ui.console.multiuser.UserManager; import org.gudy.azureus2.ui.console.multiuser.commands.UserCommand; /** * * @author Tobias Minich */ public class UI extends org.gudy.azureus2.ui.common.UITemplateHeadless implements IUserInterface, UIInstanceFactory, UIInstance, UIManagerEventListener { private ConsoleInput console = null; /** Creates a new instance of Main */ /*public UI() { }*/ public void init(boolean first, boolean others) { super.init(first,others); System.setProperty("java.awt.headless", "true"); } public String[] processArgs(String[] args) { return args; } public void startUI() { super.startUI(); boolean created_console = false; if ((!isStarted()) || (console == null) || (!console.isAlive())) { // ConsoleInput.printconsolehelp(System.out); System.out.println(); PrintStream this_out = System.out; // Unless a system property tells us not to, we'll take stdout and stderr offline. if (!"on".equals(System.getProperty("azureus.console.noisy"))) { // We'll hide any output to stdout or stderr - we don't want to litter our // view. PrintStream ps = new PrintStream(new java.io.OutputStream() { public void write(int c) {} public void write(byte[] b, int i1, int i2) {} }); System.setOut(ps); System.setErr(ps); org.gudy.azureus2.core3.logging.Logger.allowLoggingToStdErr(false); } console = new ConsoleInput("Main", UIConst.getAzureusCore(), System.in, this_out, Boolean.TRUE); console.printwelcome(); console.printconsolehelp(); created_console = true; } PluginInterface pi = UIConst.getAzureusCore().getPluginManager().getDefaultPluginInterface(); UIManager ui_manager = pi.getUIManager(); ui_manager.addUIEventListener( this ); try{ ui_manager.attachUI( this ); }catch( UIException e ){ e.printStackTrace(); } TorrentDownloaderFactory.initManager(UIConst.getGlobalManager(), true, true, COConfigurationManager.getStringParameter("Default save path") ); if (created_console && System.getProperty("azureus.console.multiuser") != null) { UserManager manager = UserManager.getInstance(pi); console.registerCommand(new UserCommand(manager)); } } public void openRemoteTorrent(String url) { if (console != null) { console.downloadRemoteTorrent(url); return; } console.out.println( "Downloading torrent from url: " + url ); TorrentDownloaderFactory.downloadManaged(url); return; } public void openTorrent(String fileName) { if( console != null ) { // System.out.println("NOT NULL CONSOLE. CAN PASS STRAIGHT TO IT!"); console.downloadTorrent(fileName); return; } else { // System.out.println("NULL CONSOLE"); } if( fileName.toUpperCase().startsWith( "HTTP://" ) || fileName.toUpperCase().startsWith( "HTTPS://" )) { console.out.println( "Downloading torrent from url: " + fileName ); TorrentDownloaderFactory.downloadManaged( fileName ); return; } try { if (!TorrentUtils.isTorrentFile(fileName)) {//$NON-NLS-1$ Logger.getLogger("azureus2.ui.console").error(fileName+" doesn't seem to be a torrent file. Not added."); return; } } catch (Exception e) { Logger.getLogger("azureus2.ui.console").error("Something is wrong with "+fileName+". Not added. (Reason: "+e.getMessage()+")"); return; } if (UIConst.getGlobalManager()!=null) { try { String downloadDir = COConfigurationManager.getDirectoryParameter("Default save path"); console.out.println( "Adding torrent: " + fileName + " and saving to " + downloadDir); UIConst.getGlobalManager().addDownloadManager(fileName, downloadDir); } catch (Exception e) { Logger.getLogger("azureus2.ui.console").error("The torrent "+fileName+" could not be added.", e); } } } public UIInstance getInstance( PluginInterface plugin_interface ) { return( this ); } public void detach() throws UIException { } public boolean eventOccurred( UIManagerEvent event ) { Object data = event.getData(); switch( event.getType()){ case UIManagerEvent.ET_SHOW_TEXT_MESSAGE: // data is String[] - title, message, text { String[] bits = (String[])data; for (int i=0;i 79) { out.println(command_line_so_far); command_line_so_far.setLength(2); } command_line_so_far.append(next_command); command_line_so_far.append(space_between_commands); } if (command_line_so_far.length() > 2) { out.println(command_line_so_far); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/util/StringEncrypter.java0000644000175000017500000001003710323532366025222 0ustar adrianadrianpackage org.gudy.azureus2.ui.console.util; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.KeySpec; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.DESedeKeySpec; import org.bouncycastle.util.encoders.Base64; /** * utility class to encrypt strings. this class was taken from the examples at: * http://www.devx.com/Java/10MinuteSolution/21385/0/page/2 */ public class StringEncrypter { public static final String DESEDE_ENCRYPTION_SCHEME = "DESede"; public static final String DES_ENCRYPTION_SCHEME = "DES"; public static final String DEFAULT_ENCRYPTION_KEY = "Azureus users love their sensitive information to be encrypted"; private KeySpec keySpec; private SecretKeyFactory keyFactory; private Cipher cipher; private static final String UNICODE_FORMAT = "UTF8"; public StringEncrypter( String encryptionScheme ) throws EncryptionException { this( encryptionScheme, DEFAULT_ENCRYPTION_KEY ); } public StringEncrypter( String encryptionScheme, String encryptionKey ) throws EncryptionException { if ( encryptionKey == null ) throw new IllegalArgumentException( "encryption key was null" ); if ( encryptionKey.trim().length() < 24 ) throw new IllegalArgumentException( "encryption key was less than 24 characters" ); try { byte[] keyAsBytes = encryptionKey.getBytes( UNICODE_FORMAT ); if ( encryptionScheme.equals( DESEDE_ENCRYPTION_SCHEME) ) { keySpec = new DESedeKeySpec( keyAsBytes ); } else if ( encryptionScheme.equals( DES_ENCRYPTION_SCHEME ) ) { keySpec = new DESKeySpec( keyAsBytes ); } else { throw new IllegalArgumentException( "Encryption scheme not supported: " + encryptionScheme ); } keyFactory = SecretKeyFactory.getInstance( encryptionScheme ); cipher = Cipher.getInstance( encryptionScheme ); } catch (InvalidKeyException e) { throw new EncryptionException( e ); } catch (UnsupportedEncodingException e) { throw new EncryptionException( e ); } catch (NoSuchAlgorithmException e) { throw new EncryptionException( e ); } catch (NoSuchPaddingException e) { throw new EncryptionException( e ); } } public String encrypt( String unencryptedString ) throws EncryptionException { if ( unencryptedString == null || unencryptedString.trim().length() == 0 ) throw new IllegalArgumentException( "unencrypted string was null or empty" ); try { SecretKey key = keyFactory.generateSecret( keySpec ); cipher.init( Cipher.ENCRYPT_MODE, key ); byte[] cleartext = unencryptedString.getBytes( UNICODE_FORMAT ); byte[] ciphertext = cipher.doFinal( cleartext ); return new String( Base64.encode( ciphertext )); } catch (Exception e) { throw new EncryptionException( e ); } } public String decrypt( String encryptedString ) throws EncryptionException { if ( encryptedString == null || encryptedString.trim().length() <= 0 ) throw new IllegalArgumentException( "encrypted string was null or empty" ); try { SecretKey key = keyFactory.generateSecret( keySpec ); cipher.init( Cipher.DECRYPT_MODE, key ); byte[] cleartext = Base64.decode( encryptedString ); byte[] ciphertext = cipher.doFinal( cleartext ); return bytes2String( ciphertext ); } catch (Exception e) { throw new EncryptionException( e ); } } private static String bytes2String( byte[] bytes ) { StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { stringBuffer.append( (char) bytes[i] ); } return stringBuffer.toString(); } public static class EncryptionException extends Exception { /** * */ private static final long serialVersionUID = -8767982102667004210L; public EncryptionException( Throwable t ) { super( t ); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/multiuser/0000755000175000017500000000000011310377636022274 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/console/multiuser/UserManager.java0000644000175000017500000001377710472110742025356 0ustar adrianadrian/* * Created on 25/01/2005 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.multiuser; import java.beans.XMLDecoder; import java.beans.XMLEncoder; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.ui.console.UserProfile; import com.aelitis.azureus.core.AzureusCoreException; /** * The usermanager is responsible for reading the users configuration * file and loading in all of the possible users. It is also responsible * for authenticating a username/password * @author pauld */ public class UserManager { private static final String USER_DB_CONFIG_FILE = "console.users.properties"; private static UserManager instance; private Map usersMap = new HashMap(); private final String fileName; /** * @param configFile */ public UserManager(String fileName) { super(); this.fileName = fileName; } /** * attempts to locate a user with the specified username and then * verifies that the specified password is the same as the password * associated with that user * @param username * @param password * @return */ public UserProfile authenticate( String username, String password ) { UserProfile profile = getUser(username); if( profile != null) { if( profile.authenticate( password ) ) return profile; } return null; } /** * returns the profile for the user with the specified username * otherwise null if there is no such user * @param username * @return */ public UserProfile getUser(String username ) { return (UserProfile) usersMap.get(username.toLowerCase()); } /** * adds another user to the users list * @param user */ public void addUser(UserProfile user) { usersMap.put( user.getUsername().toLowerCase(), user ); } public Collection getUsers( ) { return Collections.unmodifiableCollection(usersMap.values()); } /** * load a new UserManager object from the specified input stream. * The input stream should contain an XML document as encoded by the * save() method * @param in * @return UserManager object * @throws FileNotFoundException */ public void load( ) throws FileNotFoundException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileName)); doLoad( bis ); } protected void doLoad( InputStream in ) { XMLDecoder decoder = new XMLDecoder( in ); UserManagerConfig managerConfig = (UserManagerConfig)decoder.readObject(); for (Iterator iter = managerConfig.getUsers().iterator(); iter.hasNext();) { UserProfile user = (UserProfile) iter.next(); usersMap.put(user.getUsername().toLowerCase(), user); } System.out.println("UserManager: registered " + usersMap.size() + " users"); decoder.close(); } /** * write the UserManager configuration out to the specified output stream. * the configuration is stored in XML format as specified by the XMLEncoder class * @param out * @throws FileNotFoundException * @see XMLEncoder */ public void save( ) throws FileNotFoundException { OutputStream out = new FileOutputStream(fileName); doSave(out); } protected void doSave( OutputStream out ) { UserManagerConfig config = new UserManagerConfig(); List users = new ArrayList( usersMap.values() ); config.setUsers(users); XMLEncoder encoder = new XMLEncoder( new BufferedOutputStream( out ) ); encoder.writeObject(config); encoder.close(); } public static UserManager getInstance(PluginInterface pi) { if( instance == null ) { String azureusUserDir = pi.getUtilities().getAzureusUserDir(); File dbFile = new File(azureusUserDir, USER_DB_CONFIG_FILE); try { instance = new UserManager(dbFile.getCanonicalPath()); if( dbFile.exists() ) { System.out.println("loading user configuration from: " + dbFile.getCanonicalPath()); instance.load(); } else { System.out.println("file: " + dbFile.getCanonicalPath() + " does not exist. using 'null' user manager"); } } catch (IOException e) { throw new AzureusCoreException("Unable to instantiate default user manager"); } } return instance; } public static final class UserManagerConfig { private List users = new ArrayList(); /** * @return Returns the users. */ public List getUsers() { return users; } /** * @param users The users to set. */ public void setUsers(List users) { this.users = users; } /** * adds another user to the users list * @param user */ public void addUser(UserProfile user) { users.add( user ); } public void clear() { users.clear(); } } /** * removes the user with the specified name * @param userName */ public void deleteUser(String userName) { usersMap.remove(userName.toLowerCase()); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/multiuser/commands/0000755000175000017500000000000011310377636024075 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/console/multiuser/commands/UserCommand.java0000644000175000017500000002411611021643236027150 0ustar adrianadrian/* * Created on 10/02/2005 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.multiuser.commands; import java.io.FileNotFoundException; import java.io.PrintStream; import java.util.Iterator; import java.util.List; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import org.gudy.azureus2.ui.console.ConsoleInput; import org.gudy.azureus2.ui.console.UserProfile; import org.gudy.azureus2.ui.console.commands.CommandCollection; import org.gudy.azureus2.ui.console.commands.IConsoleCommand; import org.gudy.azureus2.ui.console.commands.OptionsConsoleCommand; import org.gudy.azureus2.ui.console.multiuser.UserManager; /** * container command for commands that deal with the add/modify/delete of users * @author pauld */ public class UserCommand extends IConsoleCommand { private final CommandCollection subCommands = new CommandCollection(); private final UserManager userManager; /** * @param _commandNames */ public UserCommand(UserManager userManager) { super("user"); this.userManager = userManager; subCommands.add(new AddUserCommand()); subCommands.add(new DeleteUserCommand()); subCommands.add(new ModifyUserCommand()); subCommands.add(new ListUsersCommand()); } /** * returns the UserManager object that is used * by our subcommands * @return */ private UserManager getUserManager() { return userManager; } /** * write the user manager configuration back to the path that it was read from * @param out stream to print success/failure messages to */ private void saveUserManagerConfig(PrintStream out) { try { userManager.save(); out.println("> User Manager config saved"); } catch (FileNotFoundException e) { out.println("> Error saving User Manager config: " + e); e.printStackTrace(out); } } /** * returns the string describing how this command can be used */ public String getCommandDescriptions() { return "user add|delete|list|modify \tmanage users able to log in via telnet ui"; } /** * determine the correct subcommand and execute it */ public void execute(String commandName, ConsoleInput ci, List args) { if( args.isEmpty() ) { printHelp(ci.out, args); } else { commandName = (String) args.remove(0); subCommands.execute(commandName, ci, args); } } /** * prints out the help message showing the syntax for all subcommands */ public void printHelpExtra(PrintStream out, List args) { out.println("> -----"); out.println("'user' syntax:"); if( args.size() > 0 ) { String command = (String) args.remove(0); IConsoleCommand cmd = subCommands.get(command); if( cmd != null ) cmd.printHelp(out, args); return; } out.println("user "); out.println(); out.println("Available s:"); for (Iterator iter = subCommands.iterator(); iter.hasNext();) { IConsoleCommand cmd = (IConsoleCommand) iter.next(); out.println(cmd.getCommandDescriptions()); } out.println("try 'help user ' for more information about a particular user command"); out.println("> -----"); } /** * command that adds new users to the user manager * @author pauld */ private final class AddUserCommand extends OptionsConsoleCommand { public AddUserCommand() { super("add", "a"); getOptions().addOption(new Option("u", "username", true, "name of new user")); getOptions().addOption(new Option("p", "password", true, "password for new user")); getOptions().addOption(new Option("t", "type", true, "user type (Admin / User / Guest)")); getOptions().addOption(new Option("d", "savedirectory", true, "default torrent save directory for this user")); } /** * adds a new user */ public void execute(String commandName, ConsoleInput ci, CommandLine commandLine) { String userName = commandLine.getOptionValue('u'); if( userName == null ) { ci.out.println("> AddUser: (u)sername option not specified"); return; } String password = commandLine.getOptionValue('p'); if( password == null ) { ci.out.println("> AddUser: (p)assword option not specified"); return; } String userType = commandLine.getOptionValue('t', UserProfile.DEFAULT_USER_TYPE); if( ! UserProfile.isValidUserType(userType.toLowerCase())) { ci.out.println("> AddUser: invalid profile type '" + userType + "'. Valid values are: " + UserProfile.ADMIN + "," + UserProfile.USER + "," + UserProfile.GUEST); return; } // check that a user with that name doesnt already exist if( getUserManager().getUser(userName) != null ) { ci.out.println("> AddUser error: user '" + userName + "' already exists"); return; } UserProfile profile = new UserProfile(userName, userType); profile.setPassword(password); String defaultSaveDirectory = commandLine.getOptionValue('d', null); profile.setDefaultSaveDirectory(defaultSaveDirectory); getUserManager().addUser(profile); ci.out.println("> AddUser: user '" + userName + "' added"); saveUserManagerConfig(ci.out); } public String getCommandDescriptions() { return "add [-u user] \t\ta\tadds a new user"; } } /** * command that deletes a user from the user manager * @author pauld */ private final class DeleteUserCommand extends OptionsConsoleCommand { public DeleteUserCommand() { super("delete", "d"); getOptions().addOption(new Option("u", "username", true, "name of user to delete")); } public void execute(String commandName, ConsoleInput ci, CommandLine commandLine) { String userName = commandLine.getOptionValue('u'); if( userName == null ) { ci.out.println("> DeleteUser: (u)sername option not specified"); return; } if( getUserManager().getUser(userName) == null ) { ci.out.println("> DeleteUser: error - user '" + userName + "' not found"); return; } getUserManager().deleteUser( userName ); ci.out.println("> DeleteUser: user '" + userName + "' deleted"); saveUserManagerConfig(ci.out); } public String getCommandDescriptions() { return "delete [-u user]\t\td\tdeletes a user"; } } /** * command that changes user's password or level or default save directory * @author pauld */ private final class ModifyUserCommand extends OptionsConsoleCommand { public ModifyUserCommand() { super("modify", "m"); getOptions().addOption(new Option("u", "username", true, "name of user to modify")); getOptions().addOption(new Option("p", "password", true, "password for new user")); getOptions().addOption(new Option("t", "type", true, "user type (Admin / User / Guest)")); getOptions().addOption(new Option("d", "savedirectory", true, "default torrent save directory for this user")); } public void execute(String commandName, ConsoleInput ci, CommandLine commandLine) { String userName = commandLine.getOptionValue('u'); if( userName == null ) { ci.out.println("> ModifyUser: (u)sername option not specified"); return; } UserProfile profile = getUserManager().getUser(userName); if( profile == null ) { ci.out.println("> ModifyUser: error - user '" + userName + "' not found"); return; } boolean modified = false; String userType = commandLine.getOptionValue('t'); if( userType != null ) { if( UserProfile.isValidUserType(userType.toLowerCase())) { profile.setUserType(userType.toLowerCase()); modified = true; } else { ci.out.println("> ModifyUser: invalid profile type '" + userType + "'. Valid values are: " + UserProfile.ADMIN + "," + UserProfile.USER + "," + UserProfile.GUEST); return; } } String password = commandLine.getOptionValue('p'); if( password != null ) { profile.setPassword(password); modified = true; } String defaultSaveDirectory = commandLine.getOptionValue('d'); if( defaultSaveDirectory != null ){ modified = true; if ( defaultSaveDirectory.length() > 0 ){ profile.setDefaultSaveDirectory(defaultSaveDirectory); }else{ profile.setDefaultSaveDirectory(null); } } if( modified ) { ci.out.println("> ModifyUser: user '" + userName + "' modified"); saveUserManagerConfig(ci.out); } else printHelp(ci.out, commandLine.getArgList()); } public String getCommandDescriptions() { return "modify [-u user] \tm\tmodifies a user"; } } /** * command that prints out the list of users registered in this user manager * @author pauld */ private final class ListUsersCommand extends IConsoleCommand { public ListUsersCommand() { super("list", "l"); } public void execute(String commandName, ConsoleInput ci, List args) { ci.out.println("> -----"); ci.out.println("> Username\tProfile\t\tSave Directory"); for (Iterator iter = getUserManager().getUsers().iterator(); iter.hasNext();) { UserProfile profile = (UserProfile) iter.next(); String saveDir = profile.getDefaultSaveDirectory(); if( saveDir == null ) saveDir = "(default)"; ci.out.println("> " + profile.getUsername() + "\t\t" + profile.getUserType() + "\t\t" + saveDir); } ci.out.println("> -----"); } public String getCommandDescriptions() { return "list \t\t\t\tl lists all users"; } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/multiuser/commands/Show.java0000644000175000017500000000356310307370666025670 0ustar adrianadrian/* * Created on 2/02/2005 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.multiuser.commands; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; /** * subclass of Show command that is useful for multi-user * @author pauld */ public class Show extends org.gudy.azureus2.ui.console.commands.Show { /** * */ public Show() { super(); } /** * display a similar torrent summary to the superclass but also display the username */ protected String getDefaultSummaryFormat() { return "[%o] " + super.getDefaultSummaryFormat(); } /** * adds an additional variable 'o' for torrent owner */ protected String expandVariable(char variable, DownloadManager dm) { switch( variable ) { case 'o': String user = dm.getDownloadState().getAttribute(DownloadManagerState.AT_USER); if( user == null ) user = "admin"; return user; default: return super.expandVariable(variable, dm); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/multiuser/TestUserManager.java0000644000175000017500000000643310307370666026217 0ustar adrianadrian/* * Created on 26/01/2005 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.multiuser; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import junit.framework.TestCase; import org.gudy.azureus2.ui.console.UserProfile; /** * test class for the UserManager object * @author pauld */ public class TestUserManager extends TestCase { private InMemoryUserManager manager; private UserProfile profile1; private UserProfile profile2; /* * @see TestCase#setUp() */ protected void setUp() throws Exception { super.setUp(); manager = new InMemoryUserManager(null); profile1 = new UserProfile(); profile1.setUsername("myuser1"); profile1.setPassword("mypassword"); manager.addUser(profile1); profile2 = new UserProfile(); profile2.setUsername("myuser2"); profile2.setPassword("zigzag"); profile2.setUserType(UserProfile.USER); manager.addUser(profile2); } /* * @see TestCase#tearDown() */ protected void tearDown() throws Exception { super.tearDown(); } public void testLoadSave() { ByteArrayOutputStream out = new ByteArrayOutputStream(); manager.save(out); System.out.println("Saved to: " + new String(out.toByteArray())); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); InMemoryUserManager newManager = new InMemoryUserManager(null); newManager.load(in); UserProfile profile3 = new UserProfile(); profile3.setUserType(UserProfile.GUEST); profile3.setUsername("user3"); profile3.setPassword("whatever"); assertTrue( manager.getUsers().contains(profile1 ) ); assertTrue( manager.getUsers().contains(profile2 ) ); assertFalse( manager.getUsers().contains(profile3 ) ); assertTrue( newManager.getUsers().contains(profile1 ) ); assertTrue( newManager.getUsers().contains(profile2 ) ); assertFalse( newManager.getUsers().contains(profile3 ) ); } public void testAuthenticate() { assertEquals( "verify authentication succeeds", profile1, manager.authenticate("myuser1", "mypassword")); assertNull( "verify authentication fails", manager.authenticate("myuser1", "mypassword_shouldfail")); } private static final class InMemoryUserManager extends UserManager { public InMemoryUserManager(String fileName) { super(fileName); } public void save(OutputStream out) { doSave( out ); } public void load(InputStream in) { doLoad( in ); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/multiuser/MultiUserConsoleInput.java0000644000175000017500000000725510307370666027445 0ustar adrianadrian/* * Created on 3/02/2005 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.multiuser; import java.io.PrintStream; import java.io.Reader; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import org.gudy.azureus2.ui.console.ConsoleInput; import org.gudy.azureus2.ui.console.UserProfile; import org.gudy.azureus2.ui.console.commands.IConsoleCommand; import org.gudy.azureus2.ui.console.multiuser.commands.Show; import com.aelitis.azureus.core.AzureusCore; /** * subclass of the ConsoleInput object that is used for multi users. * in this particular subclass, we replace some commands with our own versions * and disable some commands. * @author pauld */ public class MultiUserConsoleInput extends ConsoleInput { // commands that are executable with admin role private List adminCommands; // commands that are executable with user role private List userCommands; /** * set up the lists of commands that we prohibit, based upon the user type. * @param con * @param _azureus_core * @param _in * @param _out * @param _controlling * @param profile */ public MultiUserConsoleInput(String con, AzureusCore _azureus_core, Reader _in, PrintStream _out, Boolean _controlling, UserProfile profile) { super(con, _azureus_core, _in, _out, _controlling, profile); } /** * initialize our list of commands that need specific roles */ protected void initialise() { adminCommands = new ArrayList(); adminCommands.add("quit"); adminCommands.add("share"); adminCommands.add("user"); // move command is admin only so that standard users cannot // prioritise their torrents adminCommands.add("move"); adminCommands.add("log"); adminCommands.add("ui"); userCommands = new ArrayList(); userCommands.add("set"); userCommands.add("alias"); userCommands.add("add"); super.initialise(); } /** * add some multi-user specific commands */ protected void registerCommands() { super.registerCommands(); // this will override the original Show command registerCommand(new Show()); } /** * check whether the specified command is one of our banned commands for * this particular user type. some commands are able to handle different * user types, others are not relevant to anybody but admin */ public void registerCommand(IConsoleCommand command) { if( ! UserProfile.ADMIN.equals( getUserProfile().getUserType() ) ) { Set commandNames = command.getCommandNames(); for (Iterator iter = commandNames.iterator(); iter.hasNext();) { String cmdName = (String) iter.next(); if( adminCommands.contains(cmdName) ) return; if( ! UserProfile.USER.equals( getUserProfile().getUserType() ) ) { if( userCommands.contains(cmdName)) return; } } } super.registerCommand(command); } } azureus-4.3.0.6/org/gudy/azureus2/ui/console/ConsoleInput.java0000644000175000017500000005272311055145544023536 0ustar adrianadrian/* * Written and copyright 2001-2004 Tobias Minich. Distributed under the GNU * General Public License; see the README file. This code comes with NO * WARRANTY. * * * ConsoleInput.java * * Created on 6. Oktober 2003, 23:26 */ package org.gudy.azureus2.ui.console; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.Reader; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Vector; import org.apache.log4j.Appender; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.varia.DenyAllFilter; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloader; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderCallBackInterface; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderFactory; import org.gudy.azureus2.core3.torrentdownloader.impl.TorrentDownloaderManager; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.PluginManager; import org.gudy.azureus2.plugins.installer.InstallablePlugin; import org.gudy.azureus2.plugins.installer.PluginInstallerListener; import org.gudy.azureus2.plugins.update.Update; import org.gudy.azureus2.plugins.update.UpdateCheckInstance; import org.gudy.azureus2.plugins.update.UpdateCheckInstanceListener; import org.gudy.azureus2.plugins.update.UpdateManager; import org.gudy.azureus2.ui.common.UIConst; import org.gudy.azureus2.ui.console.commands.*; import org.gudy.azureus2.ui.console.util.TextWrap; import org.gudy.azureus2.update.CorePatchChecker; import org.gudy.azureus2.update.UpdaterUpdateChecker; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter; /** * @author Tobias Minich */ public class ConsoleInput extends Thread { private static final String ALIASES_CONFIG_FILE = "console.aliases.properties"; public final AzureusCore azureus_core; public final PrintStream out; public final List torrents = new ArrayList(); public File[] adds = null; private final CommandReader br; private final boolean controlling; private boolean running; // previous command private final Vector oldcommand = new Vector(); private final static List pluginCommands = new ArrayList(); public final Properties aliases = new Properties(); private final Map commands = new LinkedHashMap(); private final List helpItems = new ArrayList(); private final UserProfile userProfile; /** * can be used by plugins to register console commands since they may not have access o * each ConsoleInput object that is created. */ public static void registerPluginCommand(Class clazz) { if( ! clazz.isInstance(IConsoleCommand.class) ) { throw new IllegalArgumentException("Class must be extend IConsoleCommand"); } pluginCommands.add( clazz ); } public static void unregisterPluginCommand(Class clazz) { pluginCommands.remove(clazz); } /** Creates a new instance of ConsoleInput */ public ConsoleInput( String con, AzureusCore _azureus_core, Reader _in, PrintStream _out, Boolean _controlling) { this( con, _azureus_core, _in, _out, _controlling, UserProfile.DEFAULT_USER_PROFILE); } public ConsoleInput( String con, AzureusCore _azureus_core, Reader _in, PrintStream _out, Boolean _controlling, UserProfile profile) { super("Console Input: " + con); this.out = _out; this.azureus_core = _azureus_core; this.userProfile = profile; this.controlling = _controlling.booleanValue(); this.br = new CommandReader(_in); System.out.println( "ConsoleInput: initializing..." ); initialise(); System.out.println( "ConsoleInput: initialized OK" ); System.out.println( "ConsoleInput: starting..." ); start(); System.out.println( "ConsoleInput: started OK" ); } /** * Simple constructor to allow other components to use the console commands such as "set" * @param con * @param _azureus_core * @param _out */ public ConsoleInput(AzureusCore _azureus_core, PrintStream _out ) { super( "" ); this.out = _out; this.azureus_core = _azureus_core; this.userProfile = UserProfile.DEFAULT_USER_PROFILE; this.controlling = false; this.br = new CommandReader( new InputStreamReader( new ByteArrayInputStream(new byte[0]))); if (Logger.getRootLogger().getAppender("ConsoleAppender")==null) { Appender app; app = new ConsoleAppender(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN)); app.setName("ConsoleAppender"); app.addFilter( new DenyAllFilter() ); //'log off' by default Logger.getRootLogger().addAppender(app); } initialise(); } protected void initialise() { registerAlertHandler(); registerCommands(); registerPluginCommands(); azureus_core.addLifecycleListener( new AzureusCoreLifecycleAdapter() { public void started( AzureusCore core ) { registerUpdateChecker(); } }); try { loadAliases(); } catch (IOException e) { out.println("Error while loading aliases: " + e.getMessage()); } // populate the old command so that '.' does something sensible first time around oldcommand.add("sh"); oldcommand.add("t"); } /** * begins the download of the torrent in the specified file, downloading * it to the specified output directory. We also annotate the download with the * current username * @param filename * @param outputDir */ public void downloadTorrent( String filename, String outputDir ) { DownloadManager manager = azureus_core.getGlobalManager().addDownloadManager(filename, outputDir); manager.getDownloadState().setAttribute(DownloadManagerState.AT_USER, getUserProfile().getUsername()); } /** * downloads the remote torrent file. once we have downloaded the .torrent file, we * pass the data to the downloadTorrent() method for further processing * @param url * @param outputDir */ public void downloadRemoteTorrent( String url, final String outputDir ) { TorrentDownloader downloader = TorrentDownloaderFactory.create(new TorrentDownloaderCallBackInterface() { public void TorrentDownloaderEvent(int state, TorrentDownloader inf) { if( state == TorrentDownloader.STATE_FINISHED ) { out.println("torrent file download complete. starting torrent"); TorrentDownloaderManager.getInstance().remove(inf); downloadTorrent( inf.getFile().getAbsolutePath(), outputDir ); } else TorrentDownloaderManager.getInstance().TorrentDownloaderEvent(state, inf); } }, url, null, null, true); TorrentDownloaderManager.getInstance().add(downloader); } /** * downloads a torrent on the local file system to the default save directory * @param fileName */ public void downloadTorrent(String fileName) { downloadTorrent(fileName, getDefaultSaveDirectory()); } /** * downloads the remote torrent file. once we have downloaded the .torrent file, we * pass the data to the downloadTorrent() method for further processing */ public void downloadRemoteTorrent(String url) { downloadRemoteTorrent(url, getDefaultSaveDirectory()); } /** * instantiates each of the plugin commands and registers t */ private void registerPluginCommands() { Class clazz; for (Iterator iter = pluginCommands.iterator(); iter.hasNext();) { clazz = (Class) iter.next(); try { IConsoleCommand command = (IConsoleCommand) clazz.newInstance(); registerCommand(command); } catch (InstantiationException e) { out.println("Error while registering plugin command: " + clazz.getName() + ":" + e.getMessage()); } catch (IllegalAccessException e) { out.println("Error while registering plugin command: " + clazz.getName() + ":" + e.getMessage()); } } } protected void registerAlertHandler() { org.gudy.azureus2.core3.logging.Logger.addListener(new ILogAlertListener() { private java.util.Set history = Collections.synchronizedSet( new HashSet()); public void alertRaised(LogAlert alert) { if (!alert.repeatable) { if ( history.contains( alert.text )){ return; } history.add( alert.text ); } out.println( alert.text ); if (alert.err != null) alert.err.printStackTrace( out ); } }); } /** * registers the commands available to be executed from this console */ protected void registerCommands() { registerCommand(new XML()); registerCommand(new Hack()); registerCommand(new AddFind()); registerCommand(new TorrentCheck()); registerCommand(new TorrentQueue()); registerCommand(new TorrentRemove()); registerCommand(new TorrentStart()); registerCommand(new TorrentStop()); registerCommand(new TorrentHost()); registerCommand(new TorrentPublish()); registerCommand(new TorrentForceStart()); registerCommand(new TorrentLog()); registerCommand(new Log()); registerCommand(new Move()); registerCommand(new Share()); registerCommand(new Set()); registerCommand(new Show()); registerCommand(new CommandUI()); registerCommand(new CommandLogout()); registerCommand(new CommandQuit()); registerCommand(new CommandHelp()); registerCommand(new Alias()); registerCommand(new Priority()); registerCommand(new Plugin()); } /** * @param set */ protected void registerCommand(IConsoleCommand command) { for (Iterator iter = command.getCommandNames().iterator(); iter.hasNext();) { String cmdName = (String) iter.next(); commands.put( cmdName, command); } helpItems.add(command); } protected void unregisterCommand(IConsoleCommand command) { for (Iterator iter = command.getCommandNames().iterator(); iter.hasNext();) { String cmdName = (String) iter.next(); if( command.equals(commands.get(cmdName)) ) commands.remove( cmdName ); } helpItems.remove(command); } protected void unregisterCommand(String commandName) { IConsoleCommand cmd = (IConsoleCommand)commands.get(commandName); if( cmd == null ) return; // check if there are any more commands registered to this command object, // otherwise remove it int numCommands = 0; for (Iterator iter = commands.entrySet().iterator(); iter.hasNext();) { Map.Entry entry = (Map.Entry) iter.next(); if( cmd.equals(entry.getValue()) ) numCommands++; } if( numCommands == 1) unregisterCommand(cmd); else commands.remove(commandName); } public ConsoleInput(String con, AzureusCore _azureus_core, InputStream _in, PrintStream _out, Boolean _controlling) { this(con, _azureus_core, new InputStreamReader(_in), _out, _controlling); } private static void quit(boolean finish) { if (finish) UIConst.shutdown(); } private class CommandHelp extends IConsoleCommand { public CommandHelp() { super("help", "?"); } public String getCommandDescriptions() { return("help [torrents]\t\t\t?\tShow this help. 'torrents' shows info about the show torrents display."); } public void execute(String commandName, ConsoleInput ci, List args) { if (args.isEmpty()){ printconsolehelp(ci.out); } else { String subcommand = (String) args.get(0); IConsoleCommand cmd = (IConsoleCommand) commands.get(subcommand); if( cmd != null ) { List newargs = new ArrayList(args); newargs.remove(0); cmd.printHelp(ci.out, newargs); //if (cmd.getHelpExtra()) } else if (subcommand.equalsIgnoreCase("torrents") || subcommand.equalsIgnoreCase("t")) { ci.out.println("> -----"); ci.out.println("# [state] PercentDone Name (Filesize) ETA\r\n\tDownSpeed / UpSpeed\tDownloaded/Uploaded\tConnectedSeeds(total) / ConnectedPeers(total)"); ci.out.println(); ci.out.println("States:"); ci.out.println(" > Downloading"); ci.out.println(" * Seeding"); ci.out.println(" ! Stopped"); ci.out.println(" . Waiting (for allocation/checking)"); ci.out.println(" : Ready"); ci.out.println(" - Queued"); ci.out.println(" A Allocating"); ci.out.println(" C Checking"); ci.out.println(" E Error"); ci.out.println(" I Initializing"); ci.out.println(" ? Unknown"); ci.out.println("> -----"); } else printconsolehelp(ci.out); } } } public void printwelcome() { out.println("Running " + Constants.APP_NAME + " " + Constants.AZUREUS_VERSION + "..."); out.println("Using configuration settings from:"); out.println(" " + SystemProperties.getUserPath()); } public void printconsolehelp() { printconsolehelp(out); } private void printconsolehelp(PrintStream os) { os.println("> -----"); os.println("Available console commands (use help for more details):"); os.println(); ArrayList cmd_lines = new ArrayList(); Iterator itr = helpItems.iterator(); while (itr.hasNext()) { StringBuffer line_so_far = new StringBuffer("["); IConsoleCommand cmd = (IConsoleCommand)itr.next(); String short_name = cmd.getShortCommandName(); if (short_name != null) { line_so_far.append(short_name); } line_so_far.append("] "); line_so_far.append(cmd.getCommandName()); cmd_lines.add(line_so_far.toString()); } TextWrap.printList(cmd_lines.iterator(), os, " "); os.println("> -----"); } private static class CommandQuit extends IConsoleCommand { public CommandQuit() { super("quit"); } public String getCommandDescriptions() { return("quit\t\t\t\t\tShutdown Azureus"); } public void execute(String commandName, ConsoleInput ci, List args) { if (ci.controlling) { ci.running = false; ci.out.print( "Exiting....." ); quit( true ); ci.out.println( "OK" ); } else { if (args.isEmpty() || (!args.get(0).toString().equalsIgnoreCase("IAMSURE"))) { ci.out.println("> The 'quit' command exits azureus. Since this is a non-controlling shell thats probably not what you wanted. Use 'logout' to quit it or 'quit iamsure' to really exit azureus."); } else { ci.out.print( "Exiting....." ); quit( true ); ci.out.println( "OK" ); } } } } private static class CommandLogout extends IConsoleCommand { public CommandLogout() { super("logout"); } public String getCommandDescriptions() { return "logout\t\t\t\t\tLog out of the CLI"; } public void execute(String commandName, ConsoleInput ci, List args) { try { if ( !ci.controlling ){ // we never want to close System.out - could be remote command exec if ( ci.out != System.out ){ ci.out.println( "Logged out" ); ci.out.close(); } ci.br.close(); } }catch (IOException ignored){ }finally{ ci.running = false; } } } private static class CommandUI extends IConsoleCommand { public CommandUI() { super("ui", "u"); } public String getCommandDescriptions() { return("ui \t\t\tu\tStart additional user interface."); } public void execute(String commandName, ConsoleInput ci, List args) { if (!args.isEmpty()){ UIConst.startUI(args.get(0).toString(), null); } else { ci.out.println("> Missing subcommand for 'ui'\r\n> ui syntax: ui "); } } } public boolean invokeCommand(String command, List cargs) { if( command.startsWith("\\") ) command = command.substring(1); else if( aliases.containsKey(command) ) { List list = br.parseCommandLine(aliases.getProperty(command)); String newCommand = list.remove(0).toString().toLowerCase(); list.addAll( cargs ); return invokeCommand(newCommand, list); } if (commands.containsKey(command)) { IConsoleCommand cmd = (IConsoleCommand) commands.get(command); try { if( cargs == null ) cargs = new ArrayList(); cmd.execute(command, this, cargs); return true; } catch (Exception e) { out.println("> Invoking Command '"+command+"' failed. Exception: "+ Debug.getNestedExceptionMessage(e)); return false; } } else return false; } public void run() { List comargs; running = true; while (running) { try { String line = br.readLine(); comargs = br.parseCommandLine(line); } catch (Exception e) { out.println("Stopping console input reader because of exception: " + e.getMessage()); running = false; break; } if (!comargs.isEmpty()) { String command = ((String) comargs.get(0)).toLowerCase(); if( ".".equals(command) ) { if (oldcommand != null) { comargs.clear(); comargs.addAll(oldcommand); command = ((String) comargs.get(0)).toLowerCase(); } else { out.println("No old command. Remove commands are not repeated to prevent errors"); } } oldcommand.clear(); oldcommand.addAll(comargs); comargs.remove(0); try { if (!invokeCommand(command, comargs)) { out.println("> Command '" + command + "' unknown (or . used without prior command)"); } } catch (Throwable e) { out.println("Exception occurred when executing command: '" + command + "'"); e.printStackTrace(out); } } } } private File getAliasesFile() { PluginInterface pi = azureus_core.getPluginManager().getDefaultPluginInterface(); String azureusUserDir = pi.getUtilities().getAzureusUserDir(); return new File(azureusUserDir, ALIASES_CONFIG_FILE); } /** * read in the aliases from the alias properties file * @throws IOException */ private void loadAliases() throws IOException { File aliasesFile = getAliasesFile(); out.println("Attempting to load aliases from: " + aliasesFile.getCanonicalPath()); if ( aliasesFile.exists() ) { FileInputStream fr = new FileInputStream(aliasesFile); aliases.clear(); try { aliases.load(fr); } finally { fr.close(); } } } /** * writes the aliases back out to the alias file */ public void saveAliases() { File aliasesFile = getAliasesFile(); try { out.println("Saving aliases to: " + aliasesFile.getCanonicalPath()); FileOutputStream fo = new FileOutputStream(aliasesFile); aliases.store(fo, "This aliases file was automatically written by Azureus"); } catch (IOException e) { out.println("> Error saving aliases to " + aliasesFile.getPath() + ":" + e.getMessage()); } } /** * @return Returns the userProfile. */ public UserProfile getUserProfile() { return userProfile; } /** * returns the default directory that torrents should be saved to unless otherwise specified * @return */ public String getDefaultSaveDirectory() { try { String saveDir = getUserProfile().getDefaultSaveDirectory(); if( saveDir == null ) { saveDir = COConfigurationManager.getDirectoryParameter("Default save path"); if( saveDir == null || saveDir.length() == 0 ) saveDir = "."; } return saveDir; } catch (Exception e) { e.printStackTrace(); return "."; } } protected void registerUpdateChecker() { boolean check_at_start = COConfigurationManager.getBooleanParameter( "update.start", true ); if ( !check_at_start ){ return; } // we've got to disable the auto-update components as we're not using them (yet...) PluginManager pm = azureus_core.getPluginManager(); pm.getPluginInstaller().addListener( new PluginInstallerListener() { public boolean installRequest( String reason, InstallablePlugin plugin ) throws PluginException { out.println( "Plugin installation request for '" + plugin.getName() + "' - " + reason ); String desc = plugin.getDescription(); String[] bits = desc.split( "\n" ); for (int i=0;iLabel to display the text for this twistie */ private Label titleLabel = null; /** * The Color to use for the twistie graphic itself; * defaults to the same as the foreground color of the titleLabel */ private Color twistieColor = null; /** * The state of the control; callers can check this state by calling {@link #isCollapsed()} */ private boolean isCollapsed = true; /** * An optional Label to display the description */ private Label descriptionLabel = null; private List listeners = new ArrayList(); /** * Create a twistie Label with the given style bit. *

Style bit can be one or more of:

*
    *
  • TwistieLabel.NONE
  • -- The default; does not show description and separator, and is collapsed *
  • TwistieLabel.SHOW_DESCRIPTION
  • -- Show the description below the separator (or title if separator s not shown) *
  • TwistieLabel.SHOW_SEPARATOR
  • -- Show a separator below the title *
  • TwistieLabel.SHOW_EXPANDED
  • -- Show a separator below the title *
* * @param parent * @param style */ public TwistieLabel(Composite parent, int style) { super(parent, SWT.NONE); setBackgroundMode(SWT.INHERIT_FORCE); this.style = style; GridLayout gLayout = new GridLayout(); gLayout.marginHeight = 0; gLayout.marginWidth = 0; gLayout.verticalSpacing = 0; gLayout.horizontalSpacing = 0; setLayout(gLayout); titleLabel = new Label(this, SWT.NONE); if ((this.style & SHOW_SEPARATOR) != 0) { Label separator = new Label(this, SWT.SEPARATOR | SWT.HORIZONTAL); GridData labelData = new GridData(SWT.FILL, SWT.CENTER, true, false); labelData.horizontalIndent = 10; separator.setLayoutData(labelData); } if ((this.style & SHOW_DESCRIPTION) != 0) { descriptionLabel = new Label(this, SWT.WRAP); GridData labelData = new GridData(SWT.FILL, SWT.FILL, true, false); labelData.horizontalIndent = 10; descriptionLabel.setLayoutData(labelData); /* * Change the font to be italic for the description */ Font initialFont = descriptionLabel.getFont(); FontData[] fontData = initialFont.getFontData(); for (int i = 0; i < fontData.length; i++) { fontData[i].setStyle(fontData[i].getStyle() | SWT.ITALIC); } descriptionLabel.setFont(new Font(getDisplay(), fontData)); } if ((this.style & SHOW_EXPANDED) != 0) { isCollapsed = false; } /* * Leaving a little margin on the left; this is where we draw the twistie graphic */ GridData labelData = new GridData(SWT.FILL, SWT.CENTER, true, false); labelData.horizontalIndent = 10; titleLabel.setLayoutData(labelData); /* * Add our mouse interceptor to the control and the title label */ MouseInterceptor interceptor = new MouseInterceptor(); super.addMouseListener(interceptor); titleLabel.addMouseListener(interceptor); /* * Listens to the paint event and do the drawing here */ addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { /* * The graphic is drawn to the left of the titleLabel so define the offset from the titleLabel */ int offsetX = titleLabel.getBounds().x - 10; int offsetY = titleLabel.getBounds().y + 3; if (null != twistieColor) { e.gc.setBackground(twistieColor); } else { e.gc.setBackground(getForeground()); } if (true == isCollapsed) { e.gc.fillPolygon(translate(points_for_collapsed, offsetX, offsetY)); } else { e.gc.fillPolygon(translate(points_for_expanded, offsetX, offsetY)); } } }); } /** * Translates the twistie points array to compensate for the given x and y offset * @param data * @param x * @param y * @return */ private int[] translate(int[] data, int x, int y) { int[] target = new int[data.length]; for (int i = 0; i < data.length; i += 2) { target[i] = data[i] + x; } for (int i = 1; i < data.length; i += 2) { target[i] = data[i] + y; } return target; } /** * Add a mouse listener to the control and also the titleLabel */ public void addMouseListener(MouseListener listener) { if (null != titleLabel) { titleLabel.addMouseListener(listener); } super.addMouseListener(listener); } /** * Remove the mouse listener from the control and also the titleLabel */ public void removeMouseListener(MouseListener listener) { if (null != titleLabel) { titleLabel.removeMouseListener(listener); } super.removeMouseListener(listener); } /** * Sets the color to be used for drawing the twistie graphic * @param color */ public void setTwistieForeground(Color color) { twistieColor = color; } /** * Sets the foreground color for the control and also all the text-base children */ public void setForeground(Color color) { if (null != titleLabel && false == titleLabel.isDisposed()) { titleLabel.setForeground(color); } if (null != descriptionLabel && false == descriptionLabel.isDisposed()) { descriptionLabel.setForeground(color); } if (null == twistieColor) { twistieColor = color; } super.setForeground(color); } /** * Sets the background color for the control and also all the text-base children */ public void setBackground(Color color) { if (null != titleLabel) { titleLabel.setBackground(color); } if (null != descriptionLabel) { descriptionLabel.setBackground(color); } super.setBackground(color); } /** * Sets the text to display as the title * @param string */ public void setTitle(String string) { if (null != titleLabel) { titleLabel.setText(string); } } /** * Sets the text to display as the description; this is not in effect unless the {@link #SHOW_DESCRIPTION} flag is also set * @param string */ public void setDescription(String string) { if (null != descriptionLabel) { descriptionLabel.setText(string); } } /** * Sets the tooltip for the control and also all the text-base children */ public void setToolTipText(String string) { if (null != titleLabel) { titleLabel.setToolTipText(string); } if (null != descriptionLabel) { descriptionLabel.setToolTipText(string); } super.setToolTipText(string); } /** * Sets the enablement for the control and also all the text-base children */ public void setEnabled(boolean enabled) { if (null != titleLabel) { titleLabel.setEnabled(enabled); } super.setEnabled(enabled); } /** * Returns whether this control is in a collapsed state * @return */ public boolean isCollapsed() { return isCollapsed; } /** * Add a listener to be notified whenever this control is collapsed or expanded; listeners * can check the collapsed/expanded state on the control and perform layout changes if need be. * @param listener */ public void addTwistieListener(ITwistieListener listener) { listeners.add(listener); } public void removeTwistieListener(ITwistieListener listener) { listeners.remove(listener); } private void notifyTwistieListeners() { for (Iterator iterator = listeners.iterator(); iterator.hasNext();) { ((ITwistieListener) iterator.next()).isCollapsed(isCollapsed()); } } /** * A listener that intercepts mouseDown events from the control and the title label so we can * fire a single event to the listener to signal that the control has been collapsed or expanded. * * * @author knguyen * */ private class MouseInterceptor extends MouseAdapter { /* * Listens to the mouse click and toggle the isCollapsed flag then force a redraw to update the control */ public void mouseDown(MouseEvent e) { isCollapsed = !isCollapsed; redraw(); notifyTwistieListeners(); } } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/0000755000175000017500000000000011310377636020663 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/IAdditionalActionPerformer.java0000644000175000017500000000230307741636162026732 0ustar adrianadrian/* * File : AdditionalActionPerformer.java * Created : 10 oct. 2003 15:36:00 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config; /** * @author Olivier * */ public interface IAdditionalActionPerformer { //The action to be performed public void performAction(); //Used by the calling class to set some values. public void setSelected(boolean selected); public void setIntValue(int value); public void setStringValue(String value); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/FileParameter.java0000644000175000017500000000432210530472124024236 0ustar adrianadrian/* * Created on 20-Nov-2006 * Created by Allan Crooks * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Shell; /** * This class inherits from the DirectoryParameter class and appears the same, * except for the dialog box that it opens. * * The reason for this is not because it is logically an extension of the * DirectoryParameter class, but because it's better to leave the existing code * where it is (for the sake of browsing CVS history). */ public class FileParameter extends DirectoryParameter { protected String[] extension_list; public FileParameter(Composite pluginGroup, String name, String defaultValue, String[] extension_list) { super(pluginGroup, name, defaultValue); this.extension_list = extension_list; } /** * We don't have a better resource for this at the moment. */ protected String getBrowseImageResource() { return "openFolderButton"; } protected String openDialog(Shell shell, String old_value) { FileDialog dialog = new FileDialog(shell, SWT.APPLICATION_MODAL); dialog.setFilterPath(old_value); if (this.extension_list != null) { dialog.setFilterExtensions(this.extension_list); } return dialog.open(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/IpFilterEditor.java0000644000175000017500000001102011127403350024372 0ustar adrianadrian/* * File : IpFilterEditor.java * Created : 8 oct. 2003 13:18:42 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.ipfilter.IpRange; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import com.aelitis.azureus.core.AzureusCore; /** * @author Olivier * */ public class IpFilterEditor { AzureusCore azureus_core; IpRange range; boolean newRange; public IpFilterEditor( AzureusCore _azureus_core, Shell parent, final IpRange _range) { azureus_core = _azureus_core; this.range = _range; if (range == null) { newRange = true; range = azureus_core.getIpFilterManager().getIPFilter().createRange(false); } final Shell shell = ShellFactory.createShell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); Messages.setLanguageText(shell,"ConfigView.section.ipfilter.editFilter"); Utils.setShellIcon(shell); GridLayout layout = new GridLayout(); layout.numColumns = 2; shell.setLayout(layout); Label label = new Label(shell, SWT.NULL); Messages.setLanguageText(label, "ConfigView.section.ipfilter.description"); final Text textDescription = new Text(shell, SWT.BORDER); GridData gridData = new GridData(); gridData.widthHint = 300; textDescription.setLayoutData(gridData); label = new Label(shell, SWT.NULL); Messages.setLanguageText(label, "ConfigView.section.ipfilter.start"); final Text textStartIp = new Text(shell, SWT.BORDER); gridData = new GridData(); gridData.widthHint = 120; textStartIp.setLayoutData(gridData); label = new Label(shell, SWT.NULL); Messages.setLanguageText(label, "ConfigView.section.ipfilter.end"); final Text textEndIp = new Text(shell, SWT.BORDER); gridData = new GridData(); gridData.widthHint = 120; textEndIp.setLayoutData(gridData); final Button ok = new Button(shell, SWT.PUSH); Messages.setLanguageText(ok, "Button.ok"); shell.setDefaultButton(ok); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; gridData.widthHint = 100; ok.setLayoutData(gridData); ok.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { range.setDescription( textDescription.getText()); range.setStartIp( textStartIp.getText()); range.setEndIp( textEndIp.getText()); range.checkValid(); if (newRange) { azureus_core.getIpFilterManager().getIPFilter().addRange(range); } shell.dispose(); } }); textStartIp.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent event) { range.setStartIp( textStartIp.getText()); range.checkValid(); if(range.isValid()) ok.setEnabled(true); else ok.setEnabled(false); } }); textEndIp.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent event) { range.setEndIp( textEndIp.getText()); range.checkValid(); if(range.isValid()) ok.setEnabled(true); else ok.setEnabled(false); } }); if (range != null) { textDescription.setText(range.getDescription()); textStartIp.setText(range.getStartIp()); textEndIp.setText(range.getEndIp()); } shell.pack(); Utils.centerWindowRelativeTo(shell, parent); shell.open(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/plugins/0000755000175000017500000000000011310377636022344 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/plugins/PluginIntParameter.java0000644000175000017500000000372310326233466026764 0ustar adrianadrian/* * File : PluginStringParameter.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.plugins; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.pluginsimpl.local.ui.config.IntParameterImpl; import org.gudy.azureus2.ui.swt.Messages; /** * @author Olivier * */ public class PluginIntParameter implements PluginParameterImpl { Control[] controls; public PluginIntParameter(Composite pluginGroup,IntParameterImpl parameter) { controls = new Control[2]; controls[0] = new Label(pluginGroup,SWT.NULL); Messages.setLanguageText(controls[0],parameter.getLabelKey()); org.gudy.azureus2.ui.swt.config.IntParameter ip = new org.gudy.azureus2.ui.swt.config.IntParameter( pluginGroup, parameter.getKey(), parameter.getDefaultValue()); controls[1] = ip.getControl(); GridData gridData = new GridData(); gridData.widthHint = 100; controls[1].setLayoutData(gridData); new Label(pluginGroup,SWT.NULL); } public Control[] getControls(){ return controls; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/plugins/PluginBooleanParameter.java0000644000175000017500000000414210326233466027605 0ustar adrianadrian/* * File : PluginStringParameter.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.plugins; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.pluginsimpl.local.ui.config.BooleanParameterImpl; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.config.IAdditionalActionPerformer; /** * @author Olivier * */ public class PluginBooleanParameter implements PluginParameterImpl { Control[] controls; org.gudy.azureus2.ui.swt.config.BooleanParameter booleanParameter; public PluginBooleanParameter(Composite pluginGroup,BooleanParameterImpl parameter) { controls = new Control[2]; controls[0] = new Label(pluginGroup,SWT.NULL); Messages.setLanguageText(controls[0],parameter.getLabelKey()); booleanParameter = new org.gudy.azureus2.ui.swt.config.BooleanParameter( pluginGroup, parameter.getKey(), parameter.getDefaultValue()); controls[1] = booleanParameter.getControl(); new Label(pluginGroup,SWT.NULL); } public Control[] getControls(){ return controls; } public void setAdditionalActionPerfomer(IAdditionalActionPerformer performer) { booleanParameter.setAdditionalActionPerformer(performer); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/plugins/PluginFileParameter.java0000644000175000017500000000506711127403350027103 0ustar adrianadrian/* * File : PluginStringParameter.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.plugins; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.pluginsimpl.local.ui.config.FileParameter; /** * @author Olivier * */ public class PluginFileParameter implements PluginParameterImpl { Control[] controls; public PluginFileParameter(final Composite pluginGroup,FileParameter parameter) { controls = new Control[3]; controls[0] = new Label(pluginGroup,SWT.NULL); Messages.setLanguageText(controls[0],parameter.getLabelKey()); final org.gudy.azureus2.ui.swt.config.StringParameter sp = new org.gudy.azureus2.ui.swt.config.StringParameter( pluginGroup, parameter.getKey(), parameter.getDefaultValue()); controls[1] = sp.getControl(); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); controls[1].setLayoutData(gridData); Button browse = new Button(pluginGroup, SWT.PUSH); ImageLoader.getInstance().setButtonImage(browse, "openFolderButton"); browse.setToolTipText(MessageText.getString("ConfigView.button.browse")); browse.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { FileDialog dialog = new FileDialog(pluginGroup.getShell(), SWT.APPLICATION_MODAL); dialog.setFilterPath(sp.getValue()); String path = dialog.open(); if (path != null) { sp.setValue(path); } } }); controls[2] = browse; } public Control[] getControls(){ return controls; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/plugins/PluginIntsParameter.java0000644000175000017500000000402110326233466027137 0ustar adrianadrian/* * File : PluginStringParameter.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.plugins; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.pluginsimpl.local.ui.config.IntsParameter; import org.gudy.azureus2.ui.swt.Messages; /** * @author Olivier * */ public class PluginIntsParameter implements PluginParameterImpl { Control[] controls; public PluginIntsParameter(Composite pluginGroup,IntsParameter parameter) { controls = new Control[2]; controls[0] = new Label(pluginGroup,SWT.NULL); Messages.setLanguageText(controls[0],parameter.getLabelKey()); org.gudy.azureus2.ui.swt.config.IntListParameter ilp = new org.gudy.azureus2.ui.swt.config.IntListParameter( pluginGroup, parameter.getKey(), parameter.getDefaultValue(), parameter.getLabels(), parameter.getValues()); controls[1] = ilp.getControl(); GridData gridData = new GridData(); gridData.widthHint = 100; controls[1].setLayoutData(gridData); new Label(pluginGroup,SWT.NULL); } public Control[] getControls(){ return controls; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/plugins/PluginColorParameter.java0000644000175000017500000000360110326233466027303 0ustar adrianadrian/* * File : PluginStringParameter.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.plugins; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.pluginsimpl.local.ui.config.ColorParameter; import org.gudy.azureus2.ui.swt.Messages; /** * @author Olivier * */ public class PluginColorParameter implements PluginParameterImpl { Control[] controls; public PluginColorParameter(Composite pluginGroup,ColorParameter parameter) { controls = new Control[2]; controls[0] = new Label(pluginGroup,SWT.NULL); Messages.setLanguageText(controls[0],parameter.getLabelKey()); org.gudy.azureus2.ui.swt.config.ColorParameter cp = new org.gudy.azureus2.ui.swt.config.ColorParameter( pluginGroup, parameter.getKey(), parameter.getDefaultRed(), parameter.getDefaultGreen(), parameter.getDefaultBlue()); controls[1] = cp.getControl(); new Label(pluginGroup,SWT.NULL); } public Control[] getControls(){ return controls; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/plugins/PluginStringsParameter.java0000644000175000017500000000406110326233466027657 0ustar adrianadrian/* * File : PluginStringParameter.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.plugins; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.pluginsimpl.local.ui.config.StringListParameterImpl; import org.gudy.azureus2.ui.swt.Messages; /** * @author Olivier * */ public class PluginStringsParameter implements PluginParameterImpl { Control[] controls; public PluginStringsParameter(Composite pluginGroup,StringListParameterImpl parameter) { controls = new Control[2]; controls[0] = new Label(pluginGroup,SWT.NULL); Messages.setLanguageText(controls[0],parameter.getLabelKey()); org.gudy.azureus2.ui.swt.config.StringListParameter slp = new org.gudy.azureus2.ui.swt.config.StringListParameter( pluginGroup, parameter.getKey(), parameter.getDefaultValue(), parameter.getLabels(), parameter.getValues()); controls[1] = slp.getControl(); GridData gridData = new GridData(); gridData.widthHint = 100; controls[1].setLayoutData(gridData); new Label(pluginGroup,SWT.NULL); } public Control[] getControls(){ return controls; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/plugins/PluginParameterImpl.java0000644000175000017500000000201007767447176027143 0ustar adrianadrian/* * File : PluginParameterImpl.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.plugins; import org.eclipse.swt.widgets.Control; /** * @author Olivier * */ public interface PluginParameterImpl { public Control[] getControls(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/plugins/PluginParameter.java0000644000175000017500000000644110062226472026305 0ustar adrianadrian/* * File : PluginParameter.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.plugins; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.plugins.ui.config.Parameter; import org.gudy.azureus2.pluginsimpl.local.ui.config.BooleanParameterImpl; import org.gudy.azureus2.pluginsimpl.local.ui.config.ColorParameter; import org.gudy.azureus2.pluginsimpl.local.ui.config.DirectoryParameterImpl; import org.gudy.azureus2.pluginsimpl.local.ui.config.FileParameter; import org.gudy.azureus2.pluginsimpl.local.ui.config.IntParameterImpl; import org.gudy.azureus2.pluginsimpl.local.ui.config.IntsParameter; import org.gudy.azureus2.pluginsimpl.local.ui.config.StringParameterImpl; import org.gudy.azureus2.pluginsimpl.local.ui.config.StringListParameterImpl; import org.gudy.azureus2.ui.swt.config.IAdditionalActionPerformer; /** * @author Olivier * */ public class PluginParameter { public PluginParameterImpl implementation; public PluginParameter(Composite pluginGroup,Parameter parameter) { if(parameter instanceof StringParameterImpl) { implementation = new PluginStringParameter(pluginGroup,(StringParameterImpl)parameter); } else if(parameter instanceof IntParameterImpl) { implementation = new PluginIntParameter(pluginGroup,(IntParameterImpl)parameter); } else if(parameter instanceof BooleanParameterImpl) { implementation = new PluginBooleanParameter(pluginGroup,(BooleanParameterImpl)parameter); } else if(parameter instanceof FileParameter) { implementation = new PluginFileParameter(pluginGroup,(FileParameter)parameter); } else if(parameter instanceof DirectoryParameterImpl) { implementation = new PluginDirectoryParameter(pluginGroup,(DirectoryParameterImpl)parameter); } else if(parameter instanceof IntsParameter) { implementation = new PluginIntsParameter(pluginGroup,(IntsParameter)parameter); } else if(parameter instanceof StringListParameterImpl) { implementation = new PluginStringsParameter(pluginGroup,(StringListParameterImpl)parameter); } else if(parameter instanceof ColorParameter) { implementation = new PluginColorParameter(pluginGroup,(ColorParameter)parameter); } } public Control[] getControls() { return implementation.getControls(); } public void setAdditionalActionPerfomer(IAdditionalActionPerformer performer) { if(implementation instanceof PluginBooleanParameter) { ((PluginBooleanParameter)implementation).setAdditionalActionPerfomer(performer); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/plugins/PluginStringParameter.java0000644000175000017500000000373710326233466027505 0ustar adrianadrian/* * File : PluginStringParameter.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.plugins; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.pluginsimpl.local.ui.config.StringParameterImpl; import org.gudy.azureus2.ui.swt.Messages; /** * @author Olivier * */ public class PluginStringParameter implements PluginParameterImpl { Control[] controls; public PluginStringParameter(Composite pluginGroup,StringParameterImpl parameter) { controls = new Control[2]; controls[0] = new Label(pluginGroup,SWT.NULL); Messages.setLanguageText(controls[0],parameter.getLabelKey()); org.gudy.azureus2.ui.swt.config.StringParameter sp = new org.gudy.azureus2.ui.swt.config.StringParameter( pluginGroup, parameter.getKey(), parameter.getDefaultValue()); controls[1] = sp.getControl(); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); controls[1].setLayoutData(gridData); new Label(pluginGroup,SWT.NULL); } public Control[] getControls(){ return controls; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/plugins/PluginDirectoryParameter.java0000644000175000017500000000512411127403350030162 0ustar adrianadrian/* * File : PluginStringParameter.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.plugins; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.pluginsimpl.local.ui.config.DirectoryParameterImpl; /** * @author Olivier * */ public class PluginDirectoryParameter implements PluginParameterImpl { Control[] controls; public PluginDirectoryParameter(final Composite pluginGroup,DirectoryParameterImpl parameter) { controls = new Control[3]; controls[0] = new Label(pluginGroup,SWT.NULL); Messages.setLanguageText(controls[0],parameter.getLabelKey()); final org.gudy.azureus2.ui.swt.config.StringParameter sp = new org.gudy.azureus2.ui.swt.config.StringParameter( pluginGroup, parameter.getKey(), parameter.getDefaultValue()); controls[1] = sp.getControl(); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); controls[1].setLayoutData(gridData); Button browse = new Button(pluginGroup, SWT.PUSH); ImageLoader.getInstance().setButtonImage(browse, "openFolderButton"); browse.setToolTipText(MessageText.getString("ConfigView.button.browse")); browse.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { DirectoryDialog dialog = new DirectoryDialog(pluginGroup.getShell(), SWT.APPLICATION_MODAL); dialog.setFilterPath(sp.getValue()); String path = dialog.open(); if (path != null) { sp.setValue(path); } } }); controls[2] = browse; } public Control[] getControls(){ return controls; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/RadioParameter.java0000644000175000017500000000627510553143404024427 0ustar adrianadrian/* * Created on 2004/02/15 * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.core3.config.*; /** * @author TuxPaper * */ public class RadioParameter extends Parameter{ Button radioButton; List performers = new ArrayList(); public RadioParameter(Composite composite, String sConfigName, int iButtonValue) { this(composite, sConfigName, iButtonValue, null); } public RadioParameter(Composite composite, final String sConfigName, final int iButtonValue, IAdditionalActionPerformer actionPerformer) { super(sConfigName); if ( actionPerformer != null ){ performers.add( actionPerformer ); } int iDefaultValue = COConfigurationManager.getIntParameter(sConfigName); radioButton = new Button(composite, SWT.RADIO); radioButton.setSelection(iDefaultValue == iButtonValue); radioButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { boolean selected = radioButton.getSelection(); if (selected) COConfigurationManager.setParameter(sConfigName, iButtonValue); if (performers.size() > 0 ) { for (int i = 0;i < performers.size(); i++) { IAdditionalActionPerformer performer = (IAdditionalActionPerformer)performers.get(i); performer.setSelected(selected); performer.performAction(); } } } }); } public void setLayoutData(Object layoutData) { radioButton.setLayoutData(layoutData); } public void setAdditionalActionPerformer(IAdditionalActionPerformer actionPerformer) { performers.add(actionPerformer); boolean selected = radioButton.getSelection(); actionPerformer.setSelected(selected); actionPerformer.performAction(); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IParameter#getControl() */ public Control getControl() { return radioButton; } public boolean isSelected() { return( radioButton.getSelection()); } public void setValue(Object value) { System.err.println("NOT IMPLEMENTED"); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/IntListParameter.java0000644000175000017500000000706710553143404024757 0ustar adrianadrian/* * Created on 10 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.Utils; /** * @author Olivier * */ public class IntListParameter extends Parameter { Combo list; private final int[] values; private final String name; public IntListParameter( Composite composite, final String name, final String labels[], final int values[]) { this(composite, name, COConfigurationManager.getIntParameter(name), labels, values); } public IntListParameter(Composite composite, final String name, int defaultValue, final String labels[], final int values[]) { super(name); this.name = name; this.values = values; if(labels.length != values.length) return; int value = COConfigurationManager.getIntParameter(name,defaultValue); int index = findIndex(value,values); list = new Combo(composite,SWT.SINGLE | SWT.READ_ONLY); for(int i = 0 ; i < labels.length ;i++) { list.add(labels[i]); } setIndex(index); list.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { setIndex(list.getSelectionIndex()); } }); } /** * @param index */ protected void setIndex(final int index) { int selected_value = values[index]; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (list == null || list.isDisposed()) { return; } if (list.getSelectionIndex() != index) { list.select(index); } } }); if (COConfigurationManager.getIntParameter(name) != selected_value) { COConfigurationManager.setParameter(name, selected_value); } } private int findIndex(int value,int values[]) { for(int i = 0 ; i < values.length ;i++) { if(values[i] == value) return i; } return 0; } public void setLayoutData(Object layoutData) { list.setLayoutData(layoutData); } public Control getControl() { return list; } public void setValue(Object value) { if (value instanceof Number) { int i = ((Number)value).intValue(); setIndex(findIndex(i, values)); } } public Object getValueObject() { return new Integer(COConfigurationManager.getIntParameter(name)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/GenericActionPerformer.java0000644000175000017500000000322710055071226026115 0ustar adrianadrian/* * File : GenericAdditionalActionPerformer.java * Created : 27-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config; /** * @author parg * */ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; public abstract class GenericActionPerformer implements IAdditionalActionPerformer { boolean selected = false; protected Control[] controls; public GenericActionPerformer(Control[] controls) { this.controls = controls; } public void setIntValue(int value) { } public void setSelected(boolean selected) { } public void setStringValue(String value) { } public void controlsSetEnabled(Control[] controls, boolean bEnabled) { for(int i = 0 ; i < controls.length ; i++) { if (controls[i] instanceof Composite) controlsSetEnabled(((Composite)controls[i]).getChildren(), bEnabled); controls[i].setEnabled(bEnabled); } } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/ParameterChangeListener.java0000644000175000017500000000411710526553224026262 0ustar adrianadrian/* * Created on 22-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; /** * @author parg * */ public interface ParameterChangeListener { public void parameterChanged( Parameter p, boolean caused_internally ); /** * An int parameter is about to change. *

* Not called when parameter set via COConfigurationManager.setParameter * * @param p * @param toValue */ public void intParameterChanging(Parameter p, int toValue); /** * A boolean parameter is about to change. *

* Not called when parameter set via COConfigurationManager.setParameter * * @param p * @param toValue */ public void booleanParameterChanging(Parameter p, boolean toValue); /** * A String parameter is about to change. *

* Not called when parameter set via COConfigurationManager.setParameter * * @param p * @param toValue */ public void stringParameterChanging(Parameter p, String toValue); /** * A double/float parameter is about to change. *

* Not called when parameter set via COConfigurationManager.setParameter * * @param p * @param toValue */ public void floatParameterChanging(Parameter owner, double toValue); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/ConfigParameterAdapter.java0000644000175000017500000001443511030557162026075 0ustar adrianadrian/* * Created on 16-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.config.generic.GenericParameterAdapter; public class ConfigParameterAdapter extends GenericParameterAdapter { private static final int CHANGINGCOUNT_BREAKER = 5; private Parameter owner; private int changingCount = 0; private boolean changedExternally = false; protected ConfigParameterAdapter(Parameter _owner, final String configID) { owner = _owner; COConfigurationManager.addParameterListener(configID, new ParameterListener() { public void parameterChanged(String parameterName) { try { if (!owner.isInitialised()){ return; } if (owner.isDisposed()) { COConfigurationManager.removeParameterListener(parameterName, this); return; } informChanged(true); Object valueObject = owner.getValueObject(); if (valueObject instanceof Boolean) { boolean b = COConfigurationManager.getBooleanParameter(parameterName); owner.setValue(new Boolean(b)); } else if (valueObject instanceof Integer) { int i = COConfigurationManager.getIntParameter(parameterName); owner.setValue(new Integer(i)); } else if (valueObject instanceof String) { String s = COConfigurationManager.getStringParameter(parameterName); owner.setValue(s); } } catch (Exception e) { Debug.out("parameterChanged trigger from ConfigParamAdapter " + configID, e); } } }); } public int getIntValue(String key) { return (COConfigurationManager.getIntParameter(key)); } public int getIntValue(String key, int def) { return (COConfigurationManager.getIntParameter(key, def)); } public void setIntValue(String key, int value) { if (changingCount == 0) { changedExternally = false; } changingCount++; try { if (getIntValue(key) == value) { changedExternally = true; return; } if (changingCount > CHANGINGCOUNT_BREAKER) { Debug.out("Preventing StackOverflow on setting " + key + " to " + value + " (was " + getIntValue(key) + ") via " + Debug.getCompressedStackTrace()); changingCount = 1; } else { informChanging(value); if (!changedExternally) { COConfigurationManager.setParameter(key, value); changedExternally = true; } } } finally { changingCount--; } } public boolean resetIntDefault(String key) { if (COConfigurationManager.doesParameterDefaultExist(key)) { COConfigurationManager.removeParameter(key); return (true); } return (false); } public boolean getBooleanValue(String key) { return (COConfigurationManager.getBooleanParameter(key)); } public boolean getBooleanValue(String key, boolean def) { return (COConfigurationManager.getBooleanParameter(key, def)); } public void setBooleanValue(String key, boolean value) { if (changingCount == 0) { changedExternally = false; } changingCount++; try { if (getBooleanValue(key) == value) { changedExternally = true; return; } if (changingCount > CHANGINGCOUNT_BREAKER) { Debug.out("Preventing StackOverflow on setting " + key + " to " + value + " (was " + getBooleanValue(key) + ") via " + Debug.getCompressedStackTrace()); changingCount = 1; } else { informChanging(value); if (!changedExternally) { COConfigurationManager.setParameter(key, value); changedExternally = true; } } } finally { changingCount--; } } public void informChanged(boolean internally) { if (owner.change_listeners != null) { for (int i = 0; i < owner.change_listeners.size(); i++) { try { ((ParameterChangeListener) owner.change_listeners.get(i)).parameterChanged( owner, internally); } catch (Exception e) { Debug.out(e); } } } } public void informChanging(int toValue) { if (owner.change_listeners != null) { for (int i = 0; i < owner.change_listeners.size(); i++) { try { ParameterChangeListener l = (ParameterChangeListener) owner.change_listeners.get(i); l.intParameterChanging(owner, toValue); } catch (Exception e) { Debug.out(e); } } } } public void informChanging(boolean toValue) { if (owner.change_listeners != null) { for (int i = 0; i < owner.change_listeners.size(); i++) { try { ParameterChangeListener l = (ParameterChangeListener) owner.change_listeners.get(i); l.booleanParameterChanging(owner, toValue); } catch (Exception e) { Debug.out(e); } } } } public void informChanging(String toValue) { if (owner.change_listeners != null) { for (int i = 0; i < owner.change_listeners.size(); i++) { try { ParameterChangeListener l = (ParameterChangeListener) owner.change_listeners.get(i); l.stringParameterChanging(owner, toValue); } catch (Exception e) { Debug.out(e); } } } } public void informChanging(double toValue) { if (owner.change_listeners != null) { for (int i = 0; i < owner.change_listeners.size(); i++) { try { ParameterChangeListener l = (ParameterChangeListener) owner.change_listeners.get(i); l.floatParameterChanging(owner, toValue); } catch (Exception e) { Debug.out(e); } } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/FloatParameter.java0000644000175000017500000001007610373051004024422 0ustar adrianadrian/* * Created on 10 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.core3.config.*; public class FloatParameter { Text inputField; float fMinValue = 0; float fMaxValue = -1; float fDefaultValue; int iDigitsAfterDecimal = 1; String sParamName; boolean allowZero = false; public FloatParameter(Composite composite, final String name) { fDefaultValue = COConfigurationManager.getFloatParameter(name); initialize(composite,name); } public FloatParameter(Composite composite, final String name, float minValue, float maxValue, boolean allowZero, int digitsAfterDecimal) { fDefaultValue = COConfigurationManager.getFloatParameter(name); initialize(composite,name); fMinValue = minValue; fMaxValue = maxValue; this.allowZero = allowZero; iDigitsAfterDecimal = digitsAfterDecimal; } public void initialize(Composite composite, final String name) { sParamName = name; inputField = new Text(composite, SWT.BORDER); float value = COConfigurationManager.getFloatParameter(name); inputField.setText(String.valueOf(value)); inputField.addListener(SWT.Verify, new Listener() { public void handleEvent(Event e) { String text = e.text; char[] chars = new char[text.length()]; text.getChars(0, chars.length, chars, 0); for (int i = 0; i < chars.length; i++) { if ( !((chars[i] >= '0' && chars[i] <= '9') || chars[i] == '.') ) { e.doit = false; return; } } } }); inputField.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { try { float val = Float.parseFloat(inputField.getText()); if (val < fMinValue) { if (!(allowZero && val == 0)) { val = fMinValue; } } if (val > fMaxValue) { if (fMaxValue > -1) { val = fMaxValue; } } COConfigurationManager.setParameter(name, val); } catch (Exception e) {} } }); inputField.addListener(SWT.FocusOut, new Listener() { public void handleEvent(Event event) { try { float val = Float.parseFloat(inputField.getText()); if (val < fMinValue) { if (!(allowZero && val == 0)) { inputField.setText(String.valueOf(fMinValue)); COConfigurationManager.setParameter(name, fMinValue); } } if (val > fMaxValue) { if (fMaxValue > -1) { inputField.setText(String.valueOf(fMaxValue)); COConfigurationManager.setParameter(name, fMaxValue); } } } catch (Exception e) {} } }); } public void setLayoutData(Object layoutData) { inputField.setLayoutData(layoutData); } public Control getControl() { return( inputField ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/BooleanParameter.java0000644000175000017500000000735411030557162024750 0ustar adrianadrian/* * Created on 9 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.ui.swt.config.generic.GenericBooleanParameter; /** * @author Olivier * */ public class BooleanParameter extends Parameter{ protected GenericBooleanParameter delegate; public BooleanParameter(Composite composite, final String name) { super(name); delegate = new GenericBooleanParameter( config_adapter, composite,name,COConfigurationManager.getBooleanParameter(name),null,null); } public BooleanParameter(Composite composite, final String name, String textKey) { super(name); delegate = new GenericBooleanParameter( config_adapter, composite, name, COConfigurationManager.getBooleanParameter(name), textKey, null); } /** * @deprecated defaultValue should be set via ConfigurationDefaults, not passed by the caller */ public BooleanParameter(Composite composite, final String name, boolean defaultValue, String textKey) { super(name); delegate = new GenericBooleanParameter( config_adapter, composite,name,defaultValue,textKey,null); } /** * @deprecated defaultValue should be set via ConfigurationDefaults, not passed by the caller */ public BooleanParameter(Composite composite, final String name, boolean defaultValue) { super(name); delegate = new GenericBooleanParameter( config_adapter, composite,name,defaultValue,null,null); } /** * @deprecated defaultValue should be set via ConfigurationDefaults, not passed by the caller */ public BooleanParameter( Composite composite, final String _name, boolean _defaultValue, String textKey, IAdditionalActionPerformer actionPerformer) { super(_name); delegate = new GenericBooleanParameter( config_adapter, composite, _name, _defaultValue, textKey, actionPerformer ); } public boolean isInitialised() { return( delegate != null ); } public void setLayoutData(Object layoutData) { delegate.setLayoutData( layoutData ); } public void setAdditionalActionPerformer(IAdditionalActionPerformer actionPerformer) { delegate.setAdditionalActionPerformer( actionPerformer ); } public Control getControl() { return delegate.getControl(); } public String getName() { return delegate.getName(); } public void setName(String newName) { delegate.setName( newName ); } public boolean isSelected() { return(delegate.isSelected()); } public void setSelected( boolean selected ) { delegate.setSelected( selected ); } public void setValue(Object value) { if (value instanceof Boolean) { setSelected(((Boolean)value).booleanValue()); } } public Object getValueObject() { return new Boolean(isSelected()); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/DirectoryParameter.java0000644000175000017500000000610211127403350025317 0ustar adrianadrian/* * Created on 08-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.internat.MessageText; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author parg * */ public class DirectoryParameter extends Parameter { Control[] controls; StringParameter sp; public DirectoryParameter( final Composite pluginGroup, String name, String defaultValue ) { super(name); controls = new Control[2]; sp = new StringParameter(pluginGroup, name, defaultValue); controls[0] = sp.getControl(); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); controls[0].setLayoutData(gridData); Button browse = new Button(pluginGroup, SWT.PUSH); ImageLoader.getInstance().setButtonImage(browse, getBrowseImageResource()); browse.setToolTipText(MessageText.getString("ConfigView.button.browse")); browse.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { String path = DirectoryParameter.this.openDialog(pluginGroup.getShell(), sp.getValue()); if (path != null) { sp.setValue(path); } } }); controls[1] = browse; } public void setLayoutData( Object layoutData) { } public Control getControl() { return( controls[0]); } public Control[] getControls() { return controls; } protected String getBrowseImageResource() { return "openFolderButton"; } protected String openDialog(Shell shell, String old_value) { DirectoryDialog dialog = new DirectoryDialog(shell, SWT.APPLICATION_MODAL); dialog.setFilterPath(old_value); return dialog.open(); } public void setValue(Object value) { if (value instanceof String) { sp.setValue((String)value); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/ButtonParameter.java0000644000175000017500000000367110714477572024660 0ustar adrianadrian/* * Created on 17-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; /** @author parg * */ import org.eclipse.swt.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.ui.swt.Messages; public class ButtonParameter extends Parameter { Button button; public ButtonParameter( Composite composite, final String name_resource ) { super(name_resource); button = new Button( composite, SWT.PUSH ); Messages.setLanguageText(button, name_resource); button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { if (change_listeners == null) {return;} for (int i=0;i= 0) { // no recursion, because this area only gets called again if i was < 0 setIndex(i); } else { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (list == null || list.isDisposed()) { return; } if (useCombo) { ((Combo)list).deselectAll(); } else { ((List)list).deselectAll(); } } }); } return; } String selected_value = values[index]; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (list == null || list.isDisposed()) { return; } if (useCombo) { if (((Combo)list).getSelectionIndex() != index) { ((Combo)list).select(index); } } else { if (((List)list).getSelectionIndex() != index) { ((List)list).select(index); } } } }); if (!COConfigurationManager.getStringParameter(name).equals(selected_value)) { COConfigurationManager.setParameter(name, selected_value); } } public void setLayoutData(Object layoutData) { list.setLayoutData(layoutData); } public Control getControl() { return list; } public String getValue() { return COConfigurationManager.getStringParameter( name, default_value ); } public void setValue(Object value) { if (value instanceof String) { String s = (String)value; setIndex(findIndex(s, values)); } } public Object getValueObject() { return getValue(); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/ParameterChangeAdapter.java0000644000175000017500000000262410526553224026056 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; /** * @author TuxPaper * @created Nov 13, 2006 * */ public class ParameterChangeAdapter implements ParameterChangeListener { public void booleanParameterChanging(Parameter p, boolean toValue) { } public void intParameterChanging(Parameter p, int toValue) { } public void parameterChanged(Parameter p, boolean caused_internally) { } public void stringParameterChanging(Parameter p, String toValue) { } public void floatParameterChanging(Parameter owner, double toValue) { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/PasswordParameter.java0000644000175000017500000000767410553143404025177 0ustar adrianadrian/* * Created on 8 september 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; import java.security.MessageDigest; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SHA1Hasher; import org.gudy.azureus2.ui.swt.Utils; /** * @author Olivier * */ public class PasswordParameter extends Parameter { String name; Text inputField; public PasswordParameter( Composite composite, final String name) { this( composite, name, org.gudy.azureus2.plugins.ui.config.PasswordParameter.ET_SHA1 ); } public PasswordParameter( Composite composite, final String name, final int encoding ) { super(name); this.name = name; inputField = new Text(composite, SWT.BORDER); inputField.setEchoChar('*'); byte[] value = COConfigurationManager.getByteParameter(name, "".getBytes()); if(value.length > 0) inputField.setText("***"); inputField.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { try{ String password_string = inputField.getText(); byte[] password = password_string.getBytes(); byte[] encoded; if(password.length > 0 ){ if ( encoding == org.gudy.azureus2.plugins.ui.config.PasswordParameter.ET_PLAIN ){ encoded = password; }else if ( encoding == org.gudy.azureus2.plugins.ui.config.PasswordParameter.ET_SHA1 ){ SHA1Hasher hasher = new SHA1Hasher(); encoded = hasher.calculateHash(password); }else{ // newly added, might as well go for UTF-8 encoded = MessageDigest.getInstance( "md5").digest( password_string.getBytes( "UTF-8" )); } }else{ encoded = password; } COConfigurationManager.setParameter(name, encoded); } catch(Exception e) { Debug.printStackTrace( e ); } } }); } public void setLayoutData(Object layoutData) { inputField.setLayoutData(layoutData); } public void setValue(final String value) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (inputField == null || inputField.isDisposed() || inputField.getText().equals(value)) { return; } inputField.setText(value); } }); if (!COConfigurationManager.getParameter(name).equals(value)) { COConfigurationManager.setParameter(name, value); } } public String getValue() { return inputField.getText(); } public Control getControl() { return inputField; } public void setValue(Object value) { if (value instanceof String) { setValue((String)value); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/UISWTParameter.java0000644000175000017500000000335211016651742024301 0ustar adrianadrian/* * Created on 26 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.config; import org.eclipse.swt.widgets.Control; /** * @author Allan Crooks * */ public class UISWTParameter extends Parameter { private Control control; public UISWTParameter(Control control, String name) { super(name); this.control = control; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.config.Parameter#setValue(java.lang.Object) */ public void setValue(Object value) { // TODO Auto-generated method stub } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.config.IParameter#getControl() */ public Control getControl() { return this.control; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.config.IParameter#setLayoutData(java.lang.Object) */ public void setLayoutData(Object layoutData) { this.control.setLayoutData(layoutData); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/generic/0000755000175000017500000000000011310377636022277 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/generic/GenericIntParameter.java0000644000175000017500000001650111247620542027031 0ustar adrianadrian/* * Created on 16-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config.generic; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; public class GenericIntParameter { private static boolean DEBUG = false; private GenericParameterAdapter adapter; private int iMinValue = 0; private int iMaxValue = -1; private int iDefaultValue; private String sParamName; private boolean bGenerateIntermediateEvents = false; // OSX doesn't send selection events while typing, so we need to trigger save // on focus out private boolean bTriggerOnFocusOut = Utils.isCarbon; private Spinner spinner; private TimerEvent timedSaveEvent = null; private TimerEventPerformer timerEventSave; private final boolean delayIntialSet = Utils.isCarbon && System.getProperty("os.version", "").startsWith("10.6"); public GenericIntParameter(GenericParameterAdapter adapter, Composite composite, final String name) { iDefaultValue = adapter.getIntValue(name); initialize(adapter, composite, name); } /** @deprecated */ public GenericIntParameter(GenericParameterAdapter adapter, Composite composite, final String name, int defaultValue) { iDefaultValue = defaultValue; initialize(adapter, composite, name); } public GenericIntParameter(GenericParameterAdapter adapter, Composite composite, String name, int minValue, int maxValue) { iDefaultValue = adapter.getIntValue(name); iMinValue = minValue; iMaxValue = maxValue; initialize(adapter, composite, name); } public void initialize(GenericParameterAdapter _adapter, Composite composite, String name) { adapter = _adapter; sParamName = name; timerEventSave = new TimerEventPerformer() { public void perform(TimerEvent event) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (spinner.isDisposed()) { return; } if (DEBUG) { debug("setIntValue to " + spinner.getSelection() + " via timeEventSave"); } adapter.setIntValue(sParamName, spinner.getSelection()); } }); } }; int value = adapter.getIntValue(name, iDefaultValue); spinner = new Spinner(composite, SWT.BORDER); setMinimumValue(iMinValue); setMaximumValue(iMaxValue); spinner.setSelection(value); if (delayIntialSet) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { spinner.setSelection(adapter.getIntValue(sParamName, iDefaultValue)); } }); } spinner.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { if (bGenerateIntermediateEvents || !spinner.isFocusControl()) { adapter.setIntValue(sParamName, spinner.getSelection()); } else { bTriggerOnFocusOut = true; cancelTimedSaveEvent(); if (DEBUG) { debug("create timeSaveEvent (" + spinner.getSelection() + ") "); } timedSaveEvent = SimpleTimer.addEvent("IntParam Saver", SystemTime.getOffsetTime(750), timerEventSave); } } }); /* * Primarily for OSX, since it doesn't validate or trigger selection * while typing numbers. * * Force into next tab, which will result in a selection */ spinner.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event event) { if (spinner.isFocusControl()) { if (DEBUG) { debug("next"); } spinner.traverse(SWT.TRAVERSE_TAB_NEXT); } } }); spinner.addListener(SWT.FocusOut, new Listener() { public void handleEvent(Event event) { if (bTriggerOnFocusOut) { if (DEBUG) { debug("focus out setIntValue(" + spinner.getSelection() + "/trigger"); } cancelTimedSaveEvent(); adapter.setIntValue(sParamName, spinner.getSelection()); } } }); } private void cancelTimedSaveEvent() { if (timedSaveEvent != null && (!timedSaveEvent.hasRun() || !timedSaveEvent.isCancelled())) { if (DEBUG) { debug("cancel timeSaveEvent"); } timedSaveEvent.cancel(); } } /** * @param string */ private void debug(String string) { System.out.println("[GenericIntParameter:" + sParamName + "] " + string); } public void setMinimumValue(final int value) { iMinValue = value; if (iMinValue > 0 && getValue() < iMinValue) { setValue(iMinValue); } Utils.execSWTThread(new AERunnable() { public void runSupport() { spinner.setMinimum(value); } }); } public void setMaximumValue(int value) { iMaxValue = value; if (iMaxValue != -1 && getValue() > iMaxValue) { setValue(iMaxValue); } Utils.execSWTThread(new AERunnable() { public void runSupport() { spinner.setMaximum(iMaxValue == -1 ? Integer.MAX_VALUE : iMaxValue); } }); } public String getName() { return (sParamName); } public void setValue(int value) { int newValue; if (iMaxValue != -1 && value > iMaxValue) { newValue = iMaxValue; } else if (iMinValue > 0 && value < iMinValue) { newValue = iMinValue; } else { newValue = value; } final int finalNewValue = newValue; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (!spinner.isDisposed()) { if (spinner.getSelection() != finalNewValue) { if (DEBUG) { debug("spinner.setSelection(" + finalNewValue + ")"); } spinner.setSelection(finalNewValue); } if (DEBUG) { debug("setIntValue to " + spinner.getSelection() + " via setValue(int)"); } } } }); if (finalNewValue != getValue()) { adapter.setIntValue(sParamName, finalNewValue); } } public void setValue(final int value, boolean force_adapter_set) { if (force_adapter_set) { setValue(value); } else { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (spinner.getSelection() != value) { spinner.setSelection(value); } } }); } } public int getValue() { return (adapter.getIntValue(sParamName, iDefaultValue)); } public void resetToDefault() { if (adapter.resetIntDefault(sParamName)) { setValue(adapter.getIntValue(sParamName)); } else { setValue(getValue()); } } public void setLayoutData(Object layoutData) { spinner.setLayoutData(layoutData); } public Control getControl() { return spinner; } public boolean isGeneratingIntermediateEvents() { return bGenerateIntermediateEvents; } public void setGenerateIntermediateEvents(boolean generateIntermediateEvents) { bGenerateIntermediateEvents = generateIntermediateEvents; } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/generic/GenericBooleanParameter.java0000644000175000017500000001171210644702456027662 0ustar adrianadrian/* * Created on 9 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config.generic; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.IAdditionalActionPerformer; /** * @author Olivier * */ public class GenericBooleanParameter { protected static final boolean DEBUG = false; GenericParameterAdapter adapter; String name; Button checkBox; boolean defaultValue; List performers = new ArrayList(); public GenericBooleanParameter(GenericParameterAdapter adapter, Composite composite, final String name) { this(adapter, composite, name, adapter.getBooleanValue(name), null, null); } public GenericBooleanParameter(GenericParameterAdapter adapter, Composite composite, final String name, String textKey) { this(adapter, composite, name, adapter.getBooleanValue(name), textKey, null); } public GenericBooleanParameter(GenericParameterAdapter adapter, Composite composite, final String name, boolean defaultValue, String textKey) { this(adapter, composite, name, defaultValue, textKey, null); } public GenericBooleanParameter(GenericParameterAdapter adapter, Composite composite, final String name, boolean defaultValue) { this(adapter, composite, name, defaultValue, null, null); } public GenericBooleanParameter(GenericParameterAdapter _adapter, Composite composite, final String _name, boolean _defaultValue, String textKey, IAdditionalActionPerformer actionPerformer) { adapter = _adapter; name = _name; defaultValue = _defaultValue; if (actionPerformer != null) { performers.add(actionPerformer); } boolean value = adapter.getBooleanValue(name, defaultValue); checkBox = new Button(composite, SWT.CHECK); if (textKey != null) Messages.setLanguageText(checkBox, textKey); checkBox.setSelection(value); checkBox.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { setSelected(checkBox.getSelection(), true); } }); } public void setLayoutData(Object layoutData) { checkBox.setLayoutData(layoutData); } public void setAdditionalActionPerformer( IAdditionalActionPerformer actionPerformer) { performers.add(actionPerformer); actionPerformer.setSelected(isSelected()); actionPerformer.performAction(); } public Control getControl() { return checkBox; } public String getName() { return name; } public void setName(String newName) { name = newName; } public boolean isSelected() { return adapter.getBooleanValue(name); } public void setSelected(final boolean selected) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (!checkBox.isDisposed()) { if (checkBox.getSelection() != selected) { if (DEBUG) { debug("bool.setSelection(" + selected + ")"); } checkBox.setSelection(selected); } if (DEBUG) { debug("setBooleanValue to " + checkBox.getSelection() + " via setValue(int)"); } adapter.setBooleanValue(name, checkBox.getSelection()); } else { adapter.setBooleanValue(name, selected); } if (performers.size() > 0) { for (int i = 0; i < performers.size(); i++) { IAdditionalActionPerformer performer = (IAdditionalActionPerformer) performers.get(i); performer.setSelected(selected); performer.performAction(); } } adapter.informChanged(false); } }); } protected void setSelected(final boolean selected, boolean force) { if (force) { setSelected(selected); } else { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (checkBox.getSelection() != selected) { checkBox.setSelection(selected); } } }); } } private void debug(String string) { System.out.println("[GenericBooleanParameter:" + name + "] " + string); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/generic/GenericParameterAdapter.java0000644000175000017500000000360510455333320027653 0ustar adrianadrian/* * Created on 16-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config.generic; public class GenericParameterAdapter { public int getIntValue( String key ) { throw( new RuntimeException( "Not implemented" )); } public int getIntValue( String key, int def ) { throw( new RuntimeException( "Not implemented" )); } public void setIntValue( String key, int value ) { throw( new RuntimeException( "Not implemented" )); } public boolean resetIntDefault( String key ) { throw( new RuntimeException( "Not implemented" )); } public boolean getBooleanValue( String key ) { throw( new RuntimeException( "Not implemented" )); } public boolean getBooleanValue( String key, boolean def ) { throw( new RuntimeException( "Not implemented" )); } public void setBooleanValue( String key, boolean value ) { throw( new RuntimeException( "Not implemented" )); } public void informChanged( boolean value_is_changing_internally ) { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/ColorParameter.java0000644000175000017500000001023010714501302024423 0ustar adrianadrian/* * File : ColorParameter.java * Created : 12 nov. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.ColorDialog; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import com.aelitis.azureus.ui.swt.utils.ColorCache; /** * @author Olivier * */ public class ColorParameter extends Parameter implements ParameterListener { private Button colorChooser; protected String sParamName; private Image img; private int r; private int g; private int b; public ColorParameter(final Composite composite, final String name, int _r, int _g, int _b) { super(name); sParamName = name; colorChooser = new Button(composite,SWT.PUSH); r = COConfigurationManager.getIntParameter(name+".red",_r); g = COConfigurationManager.getIntParameter(name+".green",_g); b = COConfigurationManager.getIntParameter(name+".blue",_b); updateButtonColor(composite.getDisplay(), r, g, b); COConfigurationManager.addParameterListener(sParamName, this); colorChooser.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event e) { COConfigurationManager.removeParameterListener(sParamName, ColorParameter.this); if(img != null && ! img.isDisposed()) { img.dispose(); } } }); colorChooser.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { ColorDialog cd = new ColorDialog(composite.getShell()); cd.setRGB(new RGB(r,g,b)); RGB newColor = cd.open(); if (newColor == null) return; newColorChosen(); COConfigurationManager.setRGBParameter(name, newColor.red, newColor.green, newColor.blue); newColorSet(); } }); } private void updateButtonColor(final Display display, final int rV, final int gV, final int bV) { Image oldImg = img; Color color = ColorCache.getColor(display, rV, gV, bV); img = new Image(display,25,10); GC gc = new GC(img); gc.setBackground(color); gc.fillRectangle(0,0,25,10); gc.dispose(); colorChooser.setImage(img); if(oldImg != null && ! oldImg.isDisposed()) oldImg.dispose(); } public Control getControl() { return colorChooser; } public void setLayoutData(Object layoutData) { colorChooser.setLayoutData(layoutData); } public void parameterChanged(String parameterName) { r = COConfigurationManager.getIntParameter(sParamName+".red"); g = COConfigurationManager.getIntParameter(sParamName+".green"); b = COConfigurationManager.getIntParameter(sParamName+".blue"); updateButtonColor(colorChooser.getDisplay(), r, g, b); } public void newColorChosen() { // subclasses can write their own code } public void newColorSet() { // subclasses can write their own code } public void setValue(Object value) { // not needed, we already trap external changes } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/InfoParameter.java0000644000175000017500000000520311135305412024246 0ustar adrianadrian/* * Created on 9 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.BufferedLabel; /** * @author parg * */ public class InfoParameter extends Parameter { private String name; private BufferedLabel label; public InfoParameter(Composite composite,String name) { this(composite, name, COConfigurationManager.getStringParameter(name)); } public InfoParameter(Composite composite,final String name, String defaultValue ) { super(name); this.name = name; this.label = new BufferedLabel(composite, SWT.NULL); String value = COConfigurationManager.getStringParameter(name, defaultValue); label.setText(value); } public void setValue(final String value) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (label == null || label.isDisposed() || label.getText().equals(value)) { return; } label.setText(value); } }); if (!COConfigurationManager.getStringParameter(name).equals(value)) { COConfigurationManager.setParameter(name, value); } } public void setLayoutData(Object layoutData) { label.setLayoutData(layoutData); } public String getValue() { return label.getText(); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IParameter#getControl() */ public Control getControl() { return label.getControl(); } public void setValue(Object value) { if (value instanceof String) { setValue((String)value); } } public Object getValueObject() { return COConfigurationManager.getStringParameter(name); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/IntParameter.java0000644000175000017500000000607711030557162024124 0ustar adrianadrian/* * Created on 10 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.gudy.azureus2.ui.swt.config.generic.GenericIntParameter; /** * @author Olivier * */ public class IntParameter extends Parameter { protected GenericIntParameter delegate; public IntParameter(Composite composite, final String name) { super(name); delegate = new GenericIntParameter(config_adapter, composite, name); } /** * @deprecated defaultValue should be set via ConfigurationDefaults, not passed by the caller */ public IntParameter(Composite composite, final String name, int defaultValue) { super(name); delegate = new GenericIntParameter(config_adapter, composite, name, defaultValue); } public IntParameter(Composite composite, final String name, int minValue, int maxValue) { super(name); delegate = new GenericIntParameter(config_adapter, composite, name, minValue, maxValue); } public boolean isInitialised() { return( delegate != null ); } public void setMinimumValue( int value ) { delegate.setMinimumValue( value ); } public void setMaximumValue( int value ) { delegate.setMaximumValue( value ); } public void setValue( int value ) { delegate.setValue( value ); } public void resetToDefault() { delegate.resetToDefault(); } public int getValue() { return( delegate.getValue()); } public void setLayoutData(Object layoutData) { delegate.setLayoutData( layoutData ); } public Control getControl() { return( delegate.getControl()); } public boolean isGeneratingIntermediateEvents() { return delegate.isGeneratingIntermediateEvents(); } public void setGenerateIntermediateEvents(boolean generateIntermediateEvents) { delegate.setGenerateIntermediateEvents(generateIntermediateEvents); } public void setValue(Object value) { if (value instanceof Number) { setValue(((Number)value).intValue()); } } public Object getValueObject() { return new Integer(getValue()); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/ExclusiveSelectionActionPerformer.java0000644000175000017500000000414207770443264030372 0ustar adrianadrian/* * File : ChangeSelectionActionPerformer.java * Created : 10 oct. 2003 15:38:53 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Event; /** * @author Olivier * */ public class ExclusiveSelectionActionPerformer implements IAdditionalActionPerformer{ boolean selected = false; Button[] buttons; public ExclusiveSelectionActionPerformer(Button[] buttons) { this.buttons = buttons; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.AdditionalActionPerformer#performAction() */ public void performAction() { if(buttons == null) return; if(!selected) return; for(int i = 0 ; i < buttons.length ; i++) { buttons[i].setSelection(false); buttons[i].notifyListeners(SWT.Selection,new Event()); } } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.AdditionalActionPerformer#setIntValue(int) */ public void setIntValue(int value) { } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.AdditionalActionPerformer#setSelected(boolean) */ public void setSelected(boolean selected) { this.selected = selected; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.AdditionalActionPerformer#setStringValue(java.lang.String) */ public void setStringValue(String value) { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/ChangeSelectionActionPerformer.java0000644000175000017500000000616410254035352027600 0ustar adrianadrian/* * File : ChangeSelectionActionPerformer.java * Created : 10 oct. 2003 15:38:53 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Composite; /** * @author Olivier * */ public class ChangeSelectionActionPerformer implements IAdditionalActionPerformer{ boolean selected = false; boolean reverse_sense = false; Control[] controls; public ChangeSelectionActionPerformer(Control[] controls) { this.controls = controls; } public ChangeSelectionActionPerformer(Control control) { this.controls = new Control[]{ control }; } public ChangeSelectionActionPerformer(Parameter p) { this.controls = p.getControls(); } public ChangeSelectionActionPerformer(Parameter p1, Parameter p2) { this( new Parameter[]{ p1, p2 }); } public ChangeSelectionActionPerformer(Parameter[] params ) { List c = new ArrayList(); for (int i=0;i 50) nbMaxUploads = 50; ((ConfigureWizard) wizard).maxActiveTorrents = nbMaxActive; ((ConfigureWizard) wizard).maxDownloads = nbMaxDownloads; ((ConfigureWizard) wizard).nbUploadsPerTorrent = nbMaxUploads; } else { ((ConfigureWizard) wizard).maxActiveTorrents = 0; ((ConfigureWizard) wizard).maxDownloads = 0; ((ConfigureWizard) wizard).nbUploadsPerTorrent = 4; } refresh(); } public void refresh() { nbMaxActive.setText("" + ((ConfigureWizard) wizard).maxActiveTorrents); nbMaxDownloads.setText("" + ((ConfigureWizard) wizard).maxDownloads); nbMaxUploadsPerTorrent.setText("" + ((ConfigureWizard) wizard).nbUploadsPerTorrent); } private int findIndex(int value, int values[]) { for (int i = 0; i < values.length; i++) { if (values[i] == value) return i; } return 0; } public boolean isNextEnabled() { return true; } public IWizardPanel getNextPanel() { return new NatPanel(((ConfigureWizard)wizard),this); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/wizard/LanguagePanel.java0000644000175000017500000001400311164361714025524 0ustar adrianadrian/* * Created on Feb 28, 2006 8:54:43 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.config.wizard; import java.util.Locale; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import org.gudy.azureus2.ui.swt.wizard.Wizard; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; /** * @author TuxPaper * @created Feb 28, 2006 * */ public class LanguagePanel extends AbstractWizardPanel { /** * @param wizard * @param previousPanel */ public LanguagePanel(Wizard wizard, IWizardPanel previousPanel) { super(wizard, previousPanel); } public void show() { GridData gridData; wizard.setTitleAsResourceID("configureWizard.welcome.title"); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); final Label lblChoose = new Label(rootPanel, SWT.WRAP); setChooseLabel(lblChoose); gridData = new GridData(GridData.FILL_HORIZONTAL); lblChoose.setLayoutData(gridData); final List lstLanguage = new List(rootPanel, SWT.BORDER | SWT.V_SCROLL | SWT.SINGLE); gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 200; lstLanguage.setLayoutData(gridData); final Locale[] locales = MessageText.getLocales(true); int iUsingLocale = -1; for (int i = 0; i < locales.length; i++) { Locale locale = locales[i]; lstLanguage.add(buildName(locale)); if (MessageText.isCurrentLocale(locale)) iUsingLocale = i; } lstLanguage.select(iUsingLocale); lstLanguage.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { int index = lstLanguage.getSelectionIndex(); if (index >= 0 && index < locales.length) { COConfigurationManager.setParameter("locale", locales[index] .toString()); MessageText.loadBundle(); DisplayFormatters.setUnits(); DisplayFormatters.loadMessages(); Shell shell = wizard.getWizardWindow(); Messages.updateLanguageForControl(shell); setChooseLabel(lblChoose); shell.layout(true, true); lstLanguage.setRedraw(false); for (int i = 0; i < locales.length; i++) { lstLanguage.setItem(i, buildName(locales[i])); } lstLanguage.setRedraw(true); try { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshLanguage(); } } catch (Exception ex) { } } } }); FontData[] fontData = lstLanguage.getFont().getFontData(); for (int i = 0; i < fontData.length; i++) { if (fontData[i].getHeight() < 10) fontData[i].setHeight(10); } final Font font = new Font(rootPanel.getDisplay(), fontData); lstLanguage.setFont(font); lstLanguage.getShell().addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { lstLanguage.showSelection(); } }); lstLanguage.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (font != null && !font.isDisposed()) font.dispose(); } }); } /** * @param lblChoose */ private void setChooseLabel(Label lblChoose) { String sLocaleChooseString = MessageText .getString("ConfigureWizard.language.choose"); String sDefChooseString = MessageText .getDefaultLocaleString("ConfigureWizard.language.choose"); if (sLocaleChooseString.equals(sDefChooseString)) { lblChoose.setText(sLocaleChooseString); } else { lblChoose.setText(sLocaleChooseString + "\n" + sDefChooseString); } } private String buildName(Locale locale) { StringBuffer sName = new StringBuffer(); String sName1 = locale.getDisplayLanguage(locale); String sName2 = locale.getDisplayLanguage(); sName.append(sName1); if (!sName1.equals(sName2)) { sName.append("/").append(sName2); } sName1 = locale.getDisplayCountry(locale); sName2 = locale.getDisplayCountry(); if (sName1.length() > 0 || sName2.length() > 0) { sName.append(" ("); if (sName1.length() > 0) sName.append(sName1); if (sName2.length() > 0 && !sName1.equals(sName2)) { sName.append("/").append(sName2); } sName1 = locale.getDisplayVariant(locale); sName2 = locale.getDisplayVariant(); if (sName1.length() > 0 || sName2.length() > 0) { sName.append(", "); if (sName1.length() > 0) sName.append(sName1); if (sName2.length() > 0 && !sName1.equals(sName2)) { sName.append("/").append(sName2); } } sName.append(")"); } return sName.toString(); } public boolean isNextEnabled() { return true; } public IWizardPanel getNextPanel() { return new WelcomePanel(((ConfigureWizard) wizard), this); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/wizard/FilePanel.java0000644000175000017500000001571411171750562024673 0ustar adrianadrian/* * File : FilePanel.java * Created : 13 oct. 2003 01:31:52 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.wizard; import java.io.File; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; /** * @author Olivier * */ public class FilePanel extends AbstractWizardPanel { public FilePanel(ConfigureWizard wizard, IWizardPanel previous) { super(wizard, previous); } public void show() { wizard.setTitle(MessageText.getString("configureWizard.file.title")); //wizard.setCurrentInfo(MessageText.getString("configureWizard.nat.hint")); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.FILL_BOTH); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); { // data Label label = new Label(panel, SWT.WRAP); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; label.setLayoutData(gridData); Messages.setLanguageText(label, "configureWizard.file.message3"); label = new Label(panel,SWT.NULL); label.setLayoutData(new GridData()); Messages.setLanguageText(label, "configureWizard.file.path"); final Text textPath = new Text(panel,SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.widthHint = 100; textPath.setLayoutData(gridData); textPath.setText(((ConfigureWizard)wizard).getDataPath()); Button browse = new Button(panel,SWT.PUSH); Messages.setLanguageText(browse, "configureWizard.file.browse"); browse.setLayoutData(new GridData()); browse.addListener(SWT.Selection,new Listener() { public void handleEvent(Event arg0) { DirectoryDialog dd = new DirectoryDialog(wizard.getWizardWindow()); dd.setFilterPath(textPath.getText()); String path = dd.open(); if(path != null) { textPath.setText(path); } } }); textPath.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { String path = textPath.getText(); ((ConfigureWizard)wizard).setDataPath( path ); try { File f = new File(path); if(f.exists() && f.isDirectory()) { wizard.setErrorMessage(""); wizard.setFinishEnabled(true); } else { wizard.setErrorMessage(MessageText.getString("configureWizard.file.invalidPath")); wizard.setFinishEnabled(false); } } catch(Exception e) { wizard.setErrorMessage(MessageText.getString("configureWizard.file.invalidPath")); wizard.setFinishEnabled(false); } } }); } { // torrents Label label = new Label(panel, SWT.WRAP); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; label.setLayoutData(gridData); Messages.setLanguageText(label, "configureWizard.file.message1"); label = new Label(panel,SWT.NULL); label.setLayoutData(new GridData()); Messages.setLanguageText(label, "configureWizard.file.path"); final Text textPath = new Text(panel,SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.widthHint = 100; textPath.setLayoutData(gridData); textPath.setText(((ConfigureWizard)wizard).torrentPath); Button browse = new Button(panel,SWT.PUSH); Messages.setLanguageText(browse, "configureWizard.file.browse"); browse.setLayoutData(new GridData()); browse.addListener(SWT.Selection,new Listener() { public void handleEvent(Event arg0) { DirectoryDialog dd = new DirectoryDialog(wizard.getWizardWindow()); dd.setFilterPath(textPath.getText()); String path = dd.open(); if(path != null) { textPath.setText(path); } } }); textPath.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { String path = textPath.getText(); ((ConfigureWizard)wizard).torrentPath = path; try { File f = new File(path); if(f.exists() && f.isDirectory()) { wizard.setErrorMessage(""); wizard.setFinishEnabled(true); } else { wizard.setErrorMessage(MessageText.getString("configureWizard.file.invalidPath")); wizard.setFinishEnabled(false); } } catch(Exception e) { wizard.setErrorMessage(MessageText.getString("configureWizard.file.invalidPath")); wizard.setFinishEnabled(false); } } }); textPath.setText(((ConfigureWizard)wizard).torrentPath); } /* during config we really shouldn't be confusing the user with questions about fast resume * It is extremely unlikely anyone will want to turn it off anyway label = new Label(panel, SWT.WRAP); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; label.setLayoutData(gridData); Messages.setLanguageText(label, "configureWizard.file.message2"); final Button fastResume = new Button(panel,SWT.CHECK); Messages.setLanguageText(fastResume, "configureWizard.file.fastResume"); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; fastResume.setLayoutData(gridData); fastResume.setSelection(((ConfigureWizard)wizard).fastResume); fastResume.addListener(SWT.Selection,new Listener() { public void handleEvent(Event arg0) { ((ConfigureWizard)wizard).fastResume = fastResume.getSelection(); } }); */ } public IWizardPanel getFinishPanel() { return new FinishPanel(((ConfigureWizard)wizard),this); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/wizard/NatPanel.java0000644000175000017500000002434511171750562024536 0ustar adrianadrian/* * File : NatPanel.java * Created : 12 oct. 2003 23:39:59 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.wizard; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.ipchecker.natchecker.NatChecker; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; /** * @author Olivier * */ public class NatPanel extends AbstractWizardPanel { StyledText textResults; Checker checker; Button bTest; Button bCancel; public class Checker extends AEThread { //private int lowPort; //private int highPort; private int TCPListenPort; private boolean bContinue; private final AzureusCore core; //public Checker(int lowPort, int highPort) { public Checker(AzureusCore core, int tcp_listen_port) { super("NAT Checker"); this.core = core; //this.lowPort = lowPort; //this.highPort = highPort; this.TCPListenPort = tcp_listen_port; this.bContinue = true; } public void runSupport() { //if (lowPort <= highPort && (highPort-lowPort < 10)) { //for (int port = lowPort; port <= highPort && bContinue; port++) { printMessage(MessageText.getString("configureWizard.nat.testing") + " " + TCPListenPort + " ... "); NatChecker checker = new NatChecker(core, NetworkAdmin.getSingleton().getMultiHomedServiceBindAddresses(true)[0], TCPListenPort, false ); switch (checker.getResult()) { case NatChecker.NAT_OK : String additional_info = checker.getAdditionalInfo(); printMessage(MessageText.getString("configureWizard.nat.ok") + "\n" + additional_info ); break; case NatChecker.NAT_KO : printMessage( "\n" + MessageText.getString("configureWizard.nat.ko") + " - " + checker.getAdditionalInfo()+".\n"); bContinue = false; break; default : printMessage( "\n" + MessageText.getString("configureWizard.nat.unable") + ". \n(" + checker.getAdditionalInfo()+").\n"); break; } //} //}else { // printMessage(MessageText.getString("configureWizard.nat.tooManyPorts") + "\n"); //} enableNext(); } public void stopIt() { bContinue = false; } } public NatPanel(ConfigureWizard wizard, IWizardPanel previous) { super(wizard, previous); } public void show() { wizard.setTitle(MessageText.getString("configureWizard.nat.title")); //wizard.setCurrentInfo(MessageText.getString("configureWizard.nat.hint")); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.FILL_BOTH); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 4; panel.setLayout(layout); Label label = new Label(panel, SWT.WRAP); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 4; label.setLayoutData(gridData); Messages.setLanguageText(label, "configureWizard.nat.message"); label = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 4; label.setLayoutData(gridData); label = new Label(panel, SWT.NULL); gridData = new GridData(); label.setLayoutData(gridData); Messages.setLanguageText(label, "configureWizard.nat.server.tcp_listen_port"); final Text textServerTCPListen = new Text(panel, SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.widthHint = 80; textServerTCPListen.setLayoutData(gridData); textServerTCPListen.setText("" + ((ConfigureWizard) wizard).serverTCPListenPort); textServerTCPListen.addListener(SWT.Verify, new Listener() { public void handleEvent(Event e) { String text = e.text; char[] chars = new char[text.length()]; text.getChars(0, chars.length, chars, 0); for (int i = 0; i < chars.length; i++) { if (!('0' <= chars[i] && chars[i] <= '9')) { e.doit = false; return; } } } }); textServerTCPListen.addListener(SWT.Modify, new Listener() { public void handleEvent(Event e) { try { final int TCPListenPort = Integer.parseInt(textServerTCPListen.getText()); ((ConfigureWizard) wizard).serverTCPListenPort = TCPListenPort; } catch (NumberFormatException ex) { // ignore } } }); /* label = new Label(panel, SWT.NULL); Messages.setLanguageText(label, "configureWizard.nat.serverhigh"); final Text textServerHigh = new Text(panel, SWT.BORDER); gridData = new GridData(); gridData.widthHint = 100; textServerHigh.setLayoutData(gridData); textServerHigh.setText("" + ((ConfigureWizard) wizard).serverMaxPort); textServerHigh.addListener(SWT.Verify, new Listener() { public void handleEvent(Event e) { String text = e.text; char[] chars = new char[text.length()]; text.getChars(0, chars.length, chars, 0); for (int i = 0; i < chars.length; i++) { if (!('0' <= chars[i] && chars[i] <= '9')) { e.doit = false; return; } } } }); textServerHigh.addListener(SWT.Modify, new Listener() { public void handleEvent(Event e) { int highPort = 0; try{ highPort = Integer.parseInt(textServerHigh.getText()); } catch(Exception ignore) { } ((ConfigureWizard) wizard).serverMaxPort = highPort; } }); final Button sharePort = new Button(panel,SWT.CHECK); sharePort.setSelection(((ConfigureWizard)wizard).serverSharePort); sharePort.addListener(SWT.Selection,new Listener() { public void handleEvent(Event arg0) { ((ConfigureWizard)wizard).serverSharePort = sharePort.getSelection(); textServerHigh.setEnabled(!((ConfigureWizard)wizard).serverSharePort); } }); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); sharePort.setLayoutData(gridData); label = new Label(panel,SWT.NULL); Messages.setLanguageText(label, "configureWizard.nat.sharePort"); textServerHigh.setEnabled(!((ConfigureWizard)wizard).serverSharePort); */ bTest = new Button(panel, SWT.PUSH); Messages.setLanguageText(bTest, "configureWizard.nat.test"); gridData = new GridData(); gridData.widthHint = 70; bTest.setLayoutData(gridData); bCancel = new Button(panel, SWT.PUSH); Messages.setLanguageText(bCancel, "Button.cancel"); gridData = new GridData(); gridData.widthHint = 70; bCancel.setLayoutData(gridData); bCancel.setEnabled(false); textResults = new StyledText(panel, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.WRAP ); gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 70; gridData.horizontalSpan = 4; textResults.setLayoutData(gridData); textResults.setBackground(panel.getDisplay().getSystemColor(SWT.COLOR_WHITE)); bTest.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { wizard.setNextEnabled(false); bTest.setEnabled(false); bCancel.setEnabled(true); textResults.setText(""); CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { ConfigureWizard cw = (ConfigureWizard) wizard; //int lowPort = cw.serverMinPort; //int highPort = cw.serverSharePort?cw.serverMinPort:cw.serverMaxPort; int TCPListenPort = cw.serverTCPListenPort; checker = new Checker(core, TCPListenPort); checker.start(); } }); } }); bCancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { if (checker != null) checker.stopIt(); bCancel.setEnabled(false); } }); } public void printMessage(final String message) { Display display = wizard.getDisplay(); if (display == null || display.isDisposed()) return; display.asyncExec(new AERunnable() { public void runSupport() { if (textResults == null || textResults.isDisposed()) return; textResults.append(message); } }); } private void enableNext() { Display display = wizard.getDisplay(); if (display == null || display.isDisposed()) return; display.asyncExec(new AERunnable(){ public void runSupport() { if (bTest == null || bTest.isDisposed()) { return; } if (wizard.getCurrentPanel().equals(this)) { return; } wizard.setNextEnabled(true); bTest.setEnabled(true); bCancel.setEnabled(false); } }); } public boolean isNextEnabled() { return true; } public IWizardPanel getNextPanel() { return new FilePanel(((ConfigureWizard)wizard),this); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/wizard/ConfigureWizard.java0000644000175000017500000000632111267524620026130 0ustar adrianadrian/* * File : ConfigureWizard.java * Created : 12 oct. 2003 16:06:44 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.config.wizard; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import org.gudy.azureus2.ui.swt.wizard.Wizard; import com.aelitis.azureus.ui.UserPrompterResultListener; /** * @author Olivier * */ public class ConfigureWizard extends Wizard { //Transfer settings int upSpeed = 4; int maxUpSpeed = 40; int maxActiveTorrents = 7; int maxDownloads = 5; int nbUploadsPerTorrent = 4; //Server / NAT Settings int serverTCPListenPort = COConfigurationManager.getIntParameter( "TCP.Listen.Port" ); //Files / Torrents private String _dataPath; private boolean _dataPathChanged; String torrentPath; boolean completed = false; public ConfigureWizard( boolean modal) { super("configureWizard.title",modal); IWizardPanel panel = new LanguagePanel(this,null); try { torrentPath = COConfigurationManager.getDirectoryParameter("General_sDefaultTorrent_Directory"); } catch(Exception e) { torrentPath = ""; } if ( COConfigurationManager.getBooleanParameter( "Use default data dir" )){ _dataPath = COConfigurationManager.getStringParameter( "Default save path" ); }else{ _dataPath = ""; } this.setFirstPanel(panel); } public void onClose() { try { if (!completed && !COConfigurationManager.getBooleanParameter("Wizard Completed")) { MessageBoxShell mb = new MessageBoxShell( MessageText.getString("wizard.close.confirmation"), MessageText.getString("wizard.close.message"), new String[] { MessageText.getString("Button.yes"), MessageText.getString("Button.no") }, 0); mb.open(new UserPrompterResultListener() { public void prompterClosed(int result) { if (result == 1) { COConfigurationManager.setParameter("Wizard Completed", true); COConfigurationManager.save(); } } }); } } catch (Exception e) { e.printStackTrace(); } super.onClose(); } protected String getDataPath() { return( _dataPath ); } protected void setDataPath( String s ) { _dataPath = s; _dataPathChanged = true; } protected boolean hasDataPathChanged() { return( _dataPathChanged ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/config/StringParameter.java0000644000175000017500000001142411264027746024641 0ustar adrianadrian/* * Created on 9 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.config; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.Utils; /** * @author Olivier * */ public class StringParameter extends Parameter{ private String name; private Text inputField; private String defaultValue; public StringParameter(Composite composite,final String name) { this(composite, name, COConfigurationManager.getStringParameter(name)); } public StringParameter(Composite composite,final String name, String defaultValue) { this( composite, name, defaultValue, true ); } public StringParameter(Composite composite,final String name, String defaultValue, boolean generateIntermediateEvents ) { super(name); this.name = name; this.defaultValue = defaultValue; inputField = new Text(composite, SWT.BORDER) { // I know what I'm doing. Maybe ;) public void checkSubclass() { } // @see org.eclipse.swt.widgets.Text#computeSize(int, int, boolean) public Point computeSize(int wHint, int hHint, boolean changed) { // Text widget, at least on Windows, forces the preferred width // to the width of the text inside of it // Fix this by forcing to LayoutData's minWidth if ( hHint==0 && !isVisible()){ return( new Point( 0, 0 )); } Point pt = super.computeSize(wHint, hHint, changed); if (wHint == SWT.DEFAULT) { Object ld = getLayoutData(); if (ld instanceof GridData) { if (((GridData)ld).grabExcessHorizontalSpace) { pt.x = 10; } } } return pt; } }; String value = COConfigurationManager.getStringParameter(name, defaultValue); inputField.setText(value); inputField.addListener(SWT.Verify, new Listener() { public void handleEvent(Event e) { e.doit = COConfigurationManager.verifyParameter(name, e.text ); } }); if ( generateIntermediateEvents ){ inputField.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { checkValue(); } }); } inputField.addListener(SWT.FocusOut, new Listener() { public void handleEvent(Event event) { checkValue(); } }); } protected void checkValue() { String old_value = COConfigurationManager.getStringParameter( name, defaultValue ); String new_value = inputField.getText(); if ( !old_value.equals( new_value )){ COConfigurationManager.setParameter(name,new_value ); if( change_listeners != null ) { for (int i=0;i" : t.getMessage(); System.out.println( "StartServer ERROR: unable" + " to bind to 127.0.0.1:6880 listening" + " for passed torrent info: " + reason); } } public void pollForConnections( final AzureusCore azureus_core ) { azureus_core.addLifecycleListener( new AzureusCoreLifecycleAdapter() { public void componentCreated( AzureusCore core, AzureusCoreComponent component) { if ( component instanceof UIFunctionsSWT ){ openQueuedTorrents(); } } }); if ( socket != null ){ Thread t = new AEThread("Start Server") { public void runSupport() { pollForConnectionsSupport(); } }; t.setDaemon(true); t.start(); } } private void pollForConnectionsSupport() { bContinue = true; while (bContinue) { BufferedReader br = null; try { Socket sck = socket.accept(); String address = sck.getInetAddress().getHostAddress(); if (address.equals("localhost") || address.equals("127.0.0.1")) { br = new BufferedReader(new InputStreamReader(sck.getInputStream(),Constants.DEFAULT_ENCODING)); String line = br.readLine(); //System.out.println("received : " + line); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Main::startServer: received '" + line + "'")); if (line != null) { String [] args = parseArgs(line); if (args != null && args.length > 0) { String debug_str = args[0]; for (int i=1; i 0) {parts.add(buf.toString());} return (String[])parts.toArray(new String[parts.size()]); } protected void processArgs( String args[]) { if (args.length < 1 || !args[0].equals( "args" )){ return; } boolean addSilent = COConfigurationManager.getBooleanParameter("add_torrents_silently"); boolean showMainWindow = !addSilent; boolean open = true; for (int i = 1; i < args.length; i++) { String arg = args[i]; if ( i == 1 ){ if ( arg.equalsIgnoreCase( "--closedown" )){ UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.dispose(false, false); } return; }else if ( arg.equalsIgnoreCase( "--open" )){ showMainWindow = true; continue; }else if ( arg.equalsIgnoreCase( "--share" )){ showMainWindow = true; open = false; continue; } } String file_name = arg; File file = new File(file_name); if ( !file.exists() && !isURI( file_name )){ String magnet_uri = UrlUtils.normaliseMagnetURI( file_name ); if ( magnet_uri != null ){ file_name = magnet_uri; } } if ( isURI( file_name )) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "StartServer: args[" + i + "] handling as a URI: " + file_name)); }else{ try { if (!file.exists()) { throw (new Exception("File not found")); } file_name = file.getCanonicalPath(); Logger.log(new LogEvent(LOGID, "StartServer: file = " + file_name)); } catch (Throwable e) { Logger.log(new LogAlert(LogAlert.REPEATABLE, LogAlert.AT_ERROR, "Failed to access torrent file '" + file_name + "'. Ensure sufficient temporary file space " + "available (check browser cache usage).")); } } boolean queued = false; try { this_mon.enter(); if (!core_started) { queued_torrents.add( new Object[]{ file_name, new Boolean( open )}); queued = true; } } finally { this_mon.exit(); } if ( !queued ){ handleFile( file_name, open ); } } if (showMainWindow) { showMainWindow(); } } protected boolean isURI( String file_name ) { String file_name_lower = file_name.toLowerCase(); return( file_name_lower.startsWith( "http:" ) || file_name_lower.startsWith( "https:" ) || file_name_lower.startsWith( "magnet:" ) || file_name_lower.startsWith( "dht:" )); } protected void handleFile( String file_name, boolean open ) { try { if ( open ){ TorrentOpener.openTorrent(file_name); }else{ File f = new File( file_name ); if ( f.isDirectory()){ ShareUtils.shareDir( file_name ); }else{ ShareUtils.shareFile( file_name ); } } } catch (Throwable e) { Debug.printStackTrace(e); } } protected void openQueuedTorrents() { try{ this_mon.enter(); core_started = true; }finally{ this_mon.exit(); } for (int i=0;i claOS; private static boolean useLong; private static Class claCallback; private static Constructor constCallBack; private static Method mCallback_getAddress; private static Method mSetWindowLongPtr; private static int OS_GWLP_WNDPROC; private static Method mOS_memmove_byte; private static Method mOS_memmove_int; static { try { claOS = Class.forName("org.eclipse.swt.internal.win32.OS"); // public Callback (Object object, String method, int argCount) claCallback = Class.forName("org.eclipse.swt.internal.Callback"); constCallBack = claCallback.getDeclaredConstructor(new Class[] { Object.class, String.class, int.class }); // public long /*int*/ getAddress () mCallback_getAddress = claCallback.getDeclaredMethod("getAddress", new Class[] {}); try { //int /*long*/ SetWindowLongPtr (int /*long*/ hWnd, int nIndex, int /*long*/ dwNewLong) { mSetWindowLongPtr = claOS.getMethod("SetWindowLongPtr", new Class[] { int.class, int.class, int.class }); useLong = false; mOS_memmove_byte = claOS.getMethod("memmove", new Class[] { byte[].class, int.class, int.class }); mOS_memmove_int = claOS.getMethod("memmove", new Class[] { int[].class, int.class, int.class }); } catch (Exception e) { //e.printStackTrace(); mSetWindowLongPtr = claOS.getMethod("SetWindowLongPtr", new Class[] { long.class, int.class, long.class }); useLong = true; mOS_memmove_byte = claOS.getMethod("memmove", new Class[] { byte[].class, long.class, long.class }); mOS_memmove_int = claOS.getMethod("memmove", new Class[] { int[].class, long.class, long.class }); } //OS.GWLP_WNDPROC OS_GWLP_WNDPROC = ((Integer) claOS.getField("GWLP_WNDPROC").get(null)).intValue(); } catch (Throwable e) { e.printStackTrace(); } } public static Image getFileIcon(File file, boolean big) { int flags = OS.SHGFI_ICON; flags |= big ? SHGFI_LARGEICON : OS.SHGFI_SMALLICON; if (!file.exists()) { flags |= OS.SHGFI_USEFILEATTRIBUTES; } SHFILEINFO shfi = OS.IsUnicode ? (SHFILEINFO) new SHFILEINFOW() : new SHFILEINFOA(); TCHAR pszPath = new TCHAR(0, file.getAbsolutePath(), true); OS.SHGetFileInfo(pszPath, file.isDirectory() ? 16 : OS.FILE_ATTRIBUTE_NORMAL, shfi, SHFILEINFO.sizeof, flags); if (shfi.hIcon != 0) { Image image = Image.win32_new(null, SWT.ICON, shfi.hIcon); return image; } return null; } public static void initMainShell(Shell shell) { //Canvas canvas = new Canvas(shell, SWT.NO_BACKGROUND | SWT.NO_TRIM); //canvas.setVisible(false); Shell subshell = new Shell(shell); try { messageCallback = constCallBack.newInstance(new Object[] { Win32UIEnhancer.class, "messageProc2", 4 }); if (useLong) { Number n = (Number) mCallback_getAddress.invoke(messageCallback, new Object[] {}); messageProcLong = n.longValue(); if (messageProcLong != 0) { mSetWindowLongPtr.invoke(null, new Object[] { subshell.handle, OS_GWLP_WNDPROC, messageProcLong }); } } else { Number n = (Number) mCallback_getAddress.invoke(messageCallback, new Object[] {}); messageProcInt = n.intValue(); if (messageProcInt != 0) { mSetWindowLongPtr.invoke(null, new Object[] { subshell.handle, OS_GWLP_WNDPROC, messageProcInt }); } } } catch (Exception ex) { ex.printStackTrace(); } File[] drives = AEWin32Manager.getAccessor(false).getUSBDrives(); if (drives != null) { for (File file : drives) { DriveDetectorFactory.getDeviceDetector().driveDetected(file); } } } static int /*long*/messageProc2(int /*long*/hwnd, int /*long*/msg, int /*long*/wParam, int /*long*/lParam) { return (int) messageProc2(hwnd, msg, (long) wParam, (long) lParam); } static long /*int*/messageProc2(long /*int*/hwnd, long /*int*/msg, long /*int*/wParam, long /*int*/lParam) { try { // I'll clean this up soon switch ((int) /*64*/msg) { case WM_DEVICECHANGE: if (wParam == DBT_DEVICEARRIVAL) { int[] st = new int[3]; if (useLong) { mOS_memmove_int.invoke(null, new Object[] { st, lParam, (long) 12 }); } else { mOS_memmove_int.invoke(null, new Object[] { st, (int) lParam, (int) 12 }); } if (DEBUG) { System.out.println("Arrival: " + st[0] + "/" + st[1] + "/" + st[2]); } if (st[1] == DBT_DEVTYP_VOLUME) { if (DEBUG) { System.out.println("NEW VOLUME!"); } byte b[] = new byte[st[0]]; if (useLong) { mOS_memmove_byte.invoke(null, new Object[] { b, lParam, (int) st[0] }); } else { mOS_memmove_byte.invoke(null, new Object[] { b, (int) lParam, (int) st[0] }); } long unitMask = b[12] + (b[13] << 8) + (b[14] << 16) + (b[14] << 24); char letter = '?'; for (int i = 0; i < 26; i++) { if (1 << i == unitMask) { letter = (char) ('A' + i); } } if (DEBUG) { System.out.println("Drive " + letter); } if (letter != '?') { DriveDetector driveDetector = DriveDetectorFactory.getDeviceDetector(); driveDetector.driveDetected(new File(letter + ":\\")); } } } else if (wParam == DBT_DEVICEREMOVECOMPLETE) { int[] st = new int[3]; if (useLong) { mOS_memmove_int.invoke(null, new Object[] { st, lParam, (long) 12 }); } else { mOS_memmove_int.invoke(null, new Object[] { st, (int) lParam, (int) 12 }); } if (DEBUG) { System.out.println("Remove: " + st[0] + "/" + st[1] + "/" + st[2]); } if (st[1] == DBT_DEVTYP_VOLUME) { if (DEBUG) { System.out.println("REMOVE VOLUME!"); } byte b[] = new byte[st[0]]; if (useLong) { mOS_memmove_byte.invoke(null, new Object[] { b, lParam, (int) st[0] }); } else { mOS_memmove_byte.invoke(null, new Object[] { b, (int) lParam, (int) st[0] }); } long unitMask = b[12] + (b[13] << 8) + (b[14] << 16) + (b[14] << 24); char letter = '?'; for (int i = 0; i < 26; i++) { if (1 << i == unitMask) { letter = (char) ('A' + i); } } if (DEBUG) { System.out.println("Drive " + letter); } if (letter != '?') { DriveDetector driveDetector = DriveDetectorFactory.getDeviceDetector(); driveDetector.driveRemoved(new File(letter + ":\\")); } } } if (DEBUG) { System.out.println("DEVICE CHANGE" + wParam + "/" + lParam); } break; } } catch (Exception e) { e.printStackTrace(); } return 0;// OS.DefWindowProc (hwnd, (int)/*64*/msg, wParam, lParam); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/OpenTorrentWindow.java0000644000175000017500000025311111306407136023725 0ustar adrianadrian/* * OpenTorrentWindow.java * * Created on February 23, 2004, 4:09 PM * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TableEditor; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.StringIterator; import org.gudy.azureus2.core3.config.StringList; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerInitialisationAdapter; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.internat.LocaleTorrentUtil; import org.gudy.azureus2.core3.internat.LocaleUtilDecoder; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloader; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderCallBackInterface; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.shells.MessageSlideShell; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT; /** * Torrent Opener Window. * * @author TuxPaper * * TODO Category Option */ public class OpenTorrentWindow implements TorrentDownloaderCallBackInterface, UIUpdatable { /** * We prevent users from unselecting small files to prevent them missing * out "signature" files from trackers (.nfo file, readme file etc) * * We define two constants to control this - one defines what a small file * is, and the other defines whether we believe a torrent has signature * files or not - we do this by seeing how many small files the torrent has. * * If it has several small files, then it would be silly for us to assume * that the torrent consists of multiple signature files. * * Note: I (amc1) have disabled this now, because it can force users who may want * to only download one file to download those small files, which may not be in * an overlapping piece. Since I've now seen comments from people who've complained * about this, I'm disabling it. */ //private final static int MIN_NODOWNLOAD_SIZE = 64 * 1024; //private final static int MAX_NODOWNLOAD_COUNT = 3; private final static int MIN_BUTTON_HEIGHT = -1; private final static String PARAM_DEFSAVEPATH = "Default save path"; private final static String PARAM_MOVEWHENDONE = "Move Completed When Done"; private static final String PARAM_VIEWMODE = "OpenTorrentWindow.viewMode"; private final static String MSG_ALREADY_EXISTS = "OpenTorrentWindow.mb.alreadyExists"; private final static String MSG_ALREADY_EXISTS_NAME = MSG_ALREADY_EXISTS + ".default.name"; private final static int STARTMODE_QUEUED = 0; private final static int STARTMODE_STOPPED = 1; private final static int STARTMODE_FORCESTARTED = 2; private final static int STARTMODE_SEEDING = 3; private final static int QUEUELOCATION_TOP = 0; private final static int QUEUELOCATION_BOTTOM = 1; private final static String[] startModes = { "queued", "stopped", "forceStarted", "seeding" }; private final static String[] queueLocations = { "first", "last" }; /** Only one window, since it can handle multiple torrents */ private static OpenTorrentWindow stOpenTorrentWindow = null; // SWT Stuff private Shell shell; private Table dataFileTable; private TableEditor dataFileTableEditor; private Table torrentTable; private Button ok; private Combo cmbDataDir; private Composite cSaveTo; private Combo cmbStartMode = null; private Combo cmbQueueLocation = null; // Link to the outside private GlobalManager gm; // Internal Stuff /** TorrentFileInfo list. All dataFiles currently in table, same order */ private ArrayList dataFiles = new ArrayList(); /** TorrentInfo list. All torrents to open, same order as table */ private ArrayList torrentList = new ArrayList(); /** List of torrents being downloaded. Stored so we don't close window * until they are done/aborted. */ private ArrayList downloaders = new ArrayList(); private boolean bOverrideStartModeToStopped = false; private boolean bDefaultForSeeding; /** Things to be disposed of when window closes */ private ArrayList disposeList = new ArrayList(); private boolean bClosed = false; /** Shell to use to open children (FileDialog, etc) */ private Shell shellForChildren; private String sDestDir; protected boolean bSkipDataDirModify = false; private StringList dirList; private Label dataFileTableLabel; private Composite diskspaceComp; /** * A counter to track torrent file downloads that are still active; * this is purely used to enable/disable the OK button */ private int activeTorrentCount = 0; /** * * @param parent * @param gm * @param sPathOfFilesToOpen * @param sFilesToOpen * @param bDefaultStopped * @param bForSeeding * @param bPopupOpenURL */ public synchronized static final void invoke(Shell parent, GlobalManager gm, String sPathOfFilesToOpen, String[] sFilesToOpen, boolean bDefaultStopped, boolean bForSeeding, boolean bPopupOpenURL) { String saveSilentlyDir = null; if (stOpenTorrentWindow == null) { boolean bMustOpen = (sPathOfFilesToOpen == null && sFilesToOpen == null) || bForSeeding; if (!bMustOpen) { saveSilentlyDir = getSaveSilentlyDir(); bMustOpen = saveSilentlyDir == null; } stOpenTorrentWindow = new OpenTorrentWindow(parent, gm, bMustOpen); } else { if (stOpenTorrentWindow.shell != null) stOpenTorrentWindow.shell.forceActive(); } if (stOpenTorrentWindow != null) { // local var because static may get set o null OpenTorrentWindow openTorrentWindow = stOpenTorrentWindow; openTorrentWindow.bOverrideStartModeToStopped = bDefaultStopped; openTorrentWindow.bDefaultForSeeding = bForSeeding; if (sFilesToOpen != null || sPathOfFilesToOpen != null) { // If none of the files sent to us were valid files, don't open the // window if (!bPopupOpenURL && openTorrentWindow.addTorrents(sPathOfFilesToOpen, sFilesToOpen) == 0 && openTorrentWindow.torrentList.size() == 0 && openTorrentWindow.downloaders.size() == 0) { openTorrentWindow.close(true, true); return; } } if (bPopupOpenURL) openTorrentWindow.browseURL(); if (saveSilentlyDir != null) { openTorrentWindow.sDestDir = saveSilentlyDir; for (int i = 0; i < openTorrentWindow.torrentList.size(); i++) { final TorrentInfo info = (TorrentInfo) openTorrentWindow.torrentList.get(i); info.renameDuplicates(); } openTorrentWindow.openTorrents(); openTorrentWindow.close(true, false); } } } /** * * @param parent * @param gm */ public synchronized static final void invoke(final Shell parent, GlobalManager gm) { invoke(parent, gm, null, null, false, false, false); } public synchronized static final void invokeURLPopup(final Shell parent, GlobalManager gm) { invoke(parent, gm, null, null, false, false, true); } /** * * @param parent * @param gm * @param bOpenWindow */ private OpenTorrentWindow(final Shell parent, GlobalManager gm, boolean bOpenWindow) { this.gm = gm; sDestDir = COConfigurationManager.getStringParameter(PARAM_DEFSAVEPATH); if (bOpenWindow) openWindow(parent); else shellForChildren = parent; } private void openWindow(Shell parent) { boolean bTorrentInClipboard = false; GridData gridData; Label label; Composite cArea; shell = ShellFactory.createShell(parent, SWT.RESIZE | SWT.DIALOG_TRIM); shellForChildren = shell; shell.setText(MessageText.getString("OpenTorrentWindow.title")); Utils.setShellIcon(shell); GridLayout layout = FixupLayout(new GridLayout(), false); shell.setLayout(layout); shell.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { resizeTables(3); } }); Clipboard clipboard = new Clipboard(shell.getDisplay()); String sClipText = (String) clipboard.getContents(TextTransfer.getInstance()); if (sClipText != null) bTorrentInClipboard = addTorrentsFromTextList(sClipText, true) > 0; // label = new Label(shell, SWT.BORDER | SWT.WRAP); // Messages.setLanguageText(label, "OpenTorrentWindow.message"); // gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL); // label.setLayoutData(gridData); // Torrents // ======== Composite cButtons = new Composite(shell, SWT.NONE); RowLayout rLayout = new RowLayout(SWT.HORIZONTAL); rLayout.marginBottom = 0; rLayout.marginLeft = 0; rLayout.marginRight = 0; rLayout.marginTop = 0; cButtons.setLayout(rLayout); // Buttons for tableTorrents Button browseTorrent = new Button(cButtons, SWT.PUSH); Messages.setLanguageText(browseTorrent, "OpenTorrentWindow.addFiles"); browseTorrent.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { FileDialog fDialog = new FileDialog(shell, SWT.OPEN | SWT.MULTI); fDialog.setFilterExtensions(new String[] { "*.torrent", "*.tor", Constants.FILE_WILDCARD }); fDialog.setFilterNames(new String[] { "*.torrent", "*.tor", Constants.FILE_WILDCARD }); fDialog.setFilterPath(TorrentOpener.getFilterPathTorrent()); fDialog.setText(MessageText.getString("MainWindow.dialog.choose.file")); String fileName = TorrentOpener.setFilterPathTorrent(fDialog.open()); if (fileName != null) { addTorrents(fDialog.getFilterPath(), fDialog.getFileNames()); } } }); Utils.setGridData(cButtons, GridData.FILL_HORIZONTAL, browseTorrent, MIN_BUTTON_HEIGHT); Button browseURL = new Button(cButtons, SWT.PUSH); Messages.setLanguageText(browseURL, "OpenTorrentWindow.addFiles.URL"); browseURL.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { browseURL(); } }); Button browseFolder = new Button(cButtons, SWT.PUSH); Messages.setLanguageText(browseFolder, "OpenTorrentWindow.addFiles.Folder"); browseFolder.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { DirectoryDialog fDialog = new DirectoryDialog(shell, SWT.NULL); fDialog.setFilterPath(TorrentOpener.getFilterPathTorrent()); fDialog.setMessage(MessageText.getString("MainWindow.dialog.choose.folder")); String path = TorrentOpener.setFilterPathTorrent(fDialog.open()); if (path != null) { addTorrents(path, null); } } }); if (bTorrentInClipboard) { Button pasteOpen = new Button(cButtons, SWT.PUSH); Messages.setLanguageText(pasteOpen, "OpenTorrentWindow.addFiles.Clipboard"); pasteOpen.setToolTipText(sClipText); pasteOpen.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { Clipboard clipboard = new Clipboard(shell.getDisplay()); String sClipText = (String) clipboard.getContents(TextTransfer.getInstance()); if (sClipText != null) { addTorrentsFromTextList(sClipText.trim(), false); } } }); } Group gTorrentsArea = new Group(shell, SWT.NONE); gridData = new GridData(GridData.FILL_HORIZONTAL); gTorrentsArea.setLayoutData(gridData); layout = FixupLayout(new GridLayout(), true); gTorrentsArea.setLayout(layout); Messages.setLanguageText(gTorrentsArea, "OpenTorrentWindow.torrentLocation"); Composite cTorrentList = new Composite(gTorrentsArea, SWT.NONE); gridData = new GridData(GridData.FILL_HORIZONTAL); cTorrentList.setLayoutData(gridData); createTorrentListArea(cTorrentList); Composite cTorrentOptions = new Composite(gTorrentsArea, SWT.NONE); gridData = new GridData(GridData.FILL_HORIZONTAL); cTorrentOptions.setLayoutData(gridData); layout = FixupLayout(new GridLayout(), true); layout.marginHeight = 0; layout.marginWidth = 0; cTorrentOptions.setLayout(layout); label = new Label(cTorrentOptions, SWT.NONE); gridData = new GridData(GridData.FILL_HORIZONTAL); label.setLayoutData(gridData); Messages.setLanguageText(label, "OpenTorrentWindow.torrent.options"); int userMode = COConfigurationManager.getIntParameter("User Mode"); if (userMode > 0) { Composite cTorrentModes = new Composite(cTorrentOptions, SWT.NONE); gridData = new GridData(GridData.FILL_HORIZONTAL); cTorrentModes.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 4; layout.marginWidth = 0; layout.marginHeight = 0; cTorrentModes.setLayout(layout); label = new Label(cTorrentModes, SWT.NONE); gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER); label.setLayoutData(gridData); Messages.setLanguageText(label, "OpenTorrentWindow.startMode"); cmbStartMode = new Combo(cTorrentModes, SWT.BORDER | SWT.READ_ONLY); gridData = new GridData(GridData.FILL_HORIZONTAL); cmbStartMode.setLayoutData(gridData); updateStartModeCombo(); cmbStartMode.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { setSelectedStartMode(cmbStartMode.getSelectionIndex()); } }); label = new Label(cTorrentModes, SWT.NONE); gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER); label.setLayoutData(gridData); Messages.setLanguageText(label, "OpenTorrentWindow.addPosition"); cmbQueueLocation = new Combo(cTorrentModes, SWT.BORDER | SWT.READ_ONLY); gridData = new GridData(GridData.FILL_HORIZONTAL); cmbQueueLocation.setLayoutData(gridData); updateQueueLocationCombo(); cmbQueueLocation.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { setSelectedQueueLocation(cmbQueueLocation.getSelectionIndex()); } }); } // Save To.. // ========= cSaveTo = new Composite(cTorrentOptions, SWT.NONE); layout = FixupLayout(new GridLayout(), false); layout.marginHeight = 0; layout.marginWidth = 0; layout.verticalSpacing = 0; layout.numColumns = 2; cSaveTo.setLayout(layout); Label lblDataDir = new Label(cSaveTo, SWT.NONE); gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan = 2; lblDataDir.setLayoutData(gridData); Messages.setLanguageText(lblDataDir, "OpenTorrentWindow.dataLocation"); cmbDataDir = new Combo(cSaveTo, SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); cmbDataDir.setLayoutData(gridData); cmbDataDir.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { cmbDataDirChanged(); } }); cmbDataDir.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { cmbDataDirChanged(); } }); updateDataDirCombo(); dirList = COConfigurationManager.getStringListParameter("saveTo_list"); StringIterator iter = dirList.iterator(); while (iter.hasNext()) { String s = iter.next(); if (!s.equals(sDestDir)) { cmbDataDir.add(s); } } Button browseData = new Button(cSaveTo, SWT.PUSH); Messages.setLanguageText(browseData, "ConfigView.button.browse"); browseData.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { String sSavePath; String sDefPath = cmbDataDir.getText(); File f = new File(sDefPath); if (sDefPath.length() > 0) { while (!f.exists()) { f = f.getParentFile(); if (f == null) { f = new File(sDefPath); break; } } } DirectoryDialog dDialog = new DirectoryDialog(shell, SWT.SYSTEM_MODAL); dDialog.setFilterPath(f.getAbsolutePath()); dDialog.setMessage(MessageText.getString("MainWindow.dialog.choose.savepath_forallfiles")); sSavePath = dDialog.open(); if (sSavePath != null) { cmbDataDir.setText(sSavePath); } } }); gridData = new GridData(GridData.FILL_HORIZONTAL); cSaveTo.setLayoutData(gridData); // File List // ========= Group gFilesArea = new Group(shell, SWT.NONE); gridData = new GridData(GridData.FILL_BOTH); gFilesArea.setLayoutData(gridData); layout = FixupLayout(new GridLayout(), true); gFilesArea.setLayout(layout); Messages.setLanguageText(gFilesArea, "OpenTorrentWindow.fileList"); createTableDataFiles(gFilesArea); // Ok, cancel cArea = new Composite(shell, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.numColumns = 2; cArea.setLayout(layout); ok = new Button(cArea, SWT.PUSH); Messages.setLanguageText(ok, "Button.ok"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); gridData.widthHint = 70; ok.setLayoutData(gridData); shell.setDefaultButton(ok); ok.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { okPressed(); } }); checkSeedingMode(); Button cancel = new Button(cArea, SWT.PUSH); Messages.setLanguageText(cancel, "Button.cancel"); gridData = new GridData(); gridData.widthHint = 70; cancel.setLayoutData(gridData); cancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { close(true, true); } }); Utils.setGridData(cArea, GridData.HORIZONTAL_ALIGN_END, ok, MIN_BUTTON_HEIGHT); shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (!bClosed) close(false, true); } }); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { close(true, true); } } }); KeyListener pasteKeyListener = new org.eclipse.swt.events.KeyAdapter() { public void keyPressed(KeyEvent e) { int key = e.character; if ((e.stateMask & SWT.MOD1) != 0 && e.character <= 26 && e.character > 0) key += 'a' - 1; if ((key == 'v' && (e.stateMask & SWT.MOD1) > 0) || (e.keyCode == SWT.INSERT && (e.stateMask & SWT.SHIFT) > 0)) { e.doit = false; // Paste Clipboard clipboard = new Clipboard(shell.getDisplay()); String sClipText = (String) clipboard.getContents(TextTransfer.getInstance()); if (sClipText != null) { addTorrentsFromTextList(sClipText, false); } } } }; setPasteKeyListener(shell, pasteKeyListener); Utils.createTorrentDropTarget(shell, false); shell.pack(); if (!Utils.linkShellMetricsToConfig(shell, "OpenTorrentWindow")) { Utils.centreWindow(shell); } resizeTables(3); shell.open(); if (cSaveTo != null && !cSaveTo.isDisposed()) { cSaveTo.setFocus(); } try { UIUpdaterSWT.getInstance().addUpdater(this); } catch (Exception e) { Debug.out(e); } } protected void cmbDataDirChanged() { if (bSkipDataDirModify) { return; } sDestDir = cmbDataDir.getText(); int[] indexes = torrentTable.getSelectionIndices(); for (int i = 0; i < indexes.length; i++) { TorrentInfo info = (TorrentInfo) torrentList.get(indexes[i]); //if (!info.allFilesMoving()) info.sDestDir = sDestDir; } torrentTable.clearAll(); checkSeedingMode(); if (!Utils.isCocoa || SWT.getVersion() > 3600) { // See Eclipse Bug 292449 File file = new File(sDestDir); if (!file.isDirectory()) { cmbDataDir.setBackground(Colors.colorErrorBG); } else { cmbDataDir.setBackground(null); } cmbDataDir.redraw(); cmbDataDir.update(); } diskFreeInfoRefreshPending = true; } protected void okPressed() { if (bClosed) { return; } if ((torrentList.size() == 0 && downloaders.size() == 0)) { close(true, false); return; } File file = new File(cmbDataDir.getText()); File fileDefSavePath = new File( COConfigurationManager.getStringParameter(PARAM_DEFSAVEPATH)); if (file.equals(fileDefSavePath) && !fileDefSavePath.isDirectory()) { FileUtil.mkdirs(fileDefSavePath); } boolean isPathInvalid = cmbDataDir.getText().length() == 0 || file.isFile(); if (!isPathInvalid && !file.isDirectory()) { MessageBoxShell mb = new MessageBoxShell(SWT.YES | SWT.NO | SWT.ICON_QUESTION, "OpenTorrentWindow.mb.askCreateDir", new String[] { file.toString() }); mb.open(null); int doCreate = mb.waitUntilClosed(); if (doCreate == SWT.YES) isPathInvalid = !FileUtil.mkdirs(file); else { cmbDataDir.setFocus(); return; } } if (isPathInvalid) { MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.ICON_ERROR, "OpenTorrentWindow.mb.noGlobalDestDir", new String[] { file.toString() }); mb.open(null); cmbDataDir.setFocus(); return; } String sExistingFiles = ""; int iNumExistingFiles = 0; for (int i = 0; i < torrentList.size(); i++) { TorrentInfo info = (TorrentInfo) torrentList.get(i); file = new File(info.getDataDir()); // Need to make directory now, or single file torrent will take the // "dest dir" as their filename. ie: // 1) Add single file torrent with named "hi.exe" // 2) type a non-existant directory c:\test\moo // 3) unselect the torrent // 4) change the global def directory to a real one // 5) click ok. "hi.exe" will be written as moo in c:\test if (!file.isDirectory() && !FileUtil.mkdirs(file)) { MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.ICON_ERROR, "OpenTorrentWindow.mb.noDestDir", new String[] { file.toString(), info.getTorrentName() }); mb.open(null); return; } if (!info.isValid) { MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.ICON_ERROR, "OpenTorrentWindow.mb.notValid", new String[] { info.getTorrentName() }); mb.open(null); return; } TorrentFileInfo[] files = info.getFiles(); for (int j = 0; j < files.length; j++) { TorrentFileInfo fileInfo = files[j]; if (fileInfo.getDestFileFullName().exists()) { sExistingFiles += fileInfo.orgFullName + " - " + info.getTorrentName() + "\n"; iNumExistingFiles++; if (iNumExistingFiles > 5) { // this has the potential effect of adding 5 files from the first // torrent and then 1 file from each of the remaining torrents break; } } } } if (sExistingFiles.length() > 0) { if (iNumExistingFiles > 5) { sExistingFiles += MessageText.getString( "OpenTorrentWindow.mb.existingFiles.partialList", new String[] { "" + iNumExistingFiles }) + "\n"; } MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.CANCEL | SWT.ICON_WARNING, "OpenTorrentWindow.mb.existingFiles", new String[] { sExistingFiles }); mb.open(null); if (mb.waitUntilClosed() != SWT.OK) { return; } } String sDefaultPath = COConfigurationManager.getStringParameter(PARAM_DEFSAVEPATH); if (!sDestDir.equals(sDefaultPath)) { // Move sDestDir to top of list // First, check to see if sDestDir is already in the list File fDestDir = new File(sDestDir); int iDirPos = -1; for (int i = 0; i < dirList.size(); i++) { String sDirName = dirList.get(i); File dir = new File(sDirName); if (dir.equals(fDestDir)) { iDirPos = i; break; } } // If already in list, remove it if (iDirPos > 0 && iDirPos < dirList.size()) dirList.remove(iDirPos); // and add it to the top dirList.add(0, sDestDir); // Limit if (dirList.size() > 15) dirList.remove(dirList.size() - 1); // Temporary list cleanup try { for (int j = 0; j < dirList.size(); j++) { File dirJ = new File(dirList.get(j)); for (int i = 0; i < dirList.size(); i++) { try { if (i == j) continue; File dirI = new File(dirList.get(i)); if (dirI.equals(dirJ)) { dirList.remove(i); // dirList shifted up, fix indexes if (j > i) j--; i--; } } catch (Exception e) { // Ignore } } } } catch (Exception e) { // Ignore } COConfigurationManager.setParameter("saveTo_list", dirList); COConfigurationManager.save(); } if (COConfigurationManager.getBooleanParameter("DefaultDir.AutoUpdate") && !COConfigurationManager.getBooleanParameter("Use default data dir")) COConfigurationManager.setParameter(PARAM_DEFSAVEPATH, sDestDir); openTorrents(); close(true, false); } /** * @param layout * @return */ private GridLayout FixupLayout(GridLayout layout, boolean bFixMargin) { if (Constants.isOSX) { layout.horizontalSpacing = 0; layout.verticalSpacing = 0; if (bFixMargin) { layout.marginHeight = 0; layout.marginWidth = 0; } } return layout; } private void updateDataDirCombo() { if (cmbDataDir == null) { return; } try { bSkipDataDirModify = true; int[] indexes = torrentTable.getSelectionIndices(); if (indexes.length == 0) { if (cmbDataDir.getItemCount() == 0) { cmbDataDir.add(sDestDir); } cmbDataDir.setText(sDestDir); return; } boolean allSame = true; String lastDir = null; for (int i = 0; i < indexes.length; i++) { TorrentInfo info = (TorrentInfo) torrentList.get(indexes[i]); if (lastDir != null && !info.sDestDir.equals(lastDir)) { allSame = false; break; } lastDir = info.sDestDir; } if (allSame && lastDir != null) { cmbDataDir.setText(lastDir); sDestDir = lastDir; } else { cmbDataDir.setText(""); } } finally { bSkipDataDirModify = false; } } private void updateStartModeCombo() { if (cmbStartMode == null) return; int[] indexes = torrentTable.getSelectionIndices(); String[] sItemsText = new String[startModes.length]; int iMaxMatches = 0; int iIndexToSelect = getDefaultStartMode(); for (int i = 0; i < startModes.length; i++) { int iMatches = 0; for (int j = 0; j < indexes.length; j++) { TorrentInfo info = (TorrentInfo) torrentList.get(indexes[j]); if (info.iStartID == i) iMatches++; } if (iMatches > iMaxMatches) { iMaxMatches = iMatches; iIndexToSelect = i; } String sText = MessageText.getString("OpenTorrentWindow.startMode." + startModes[i]); if (iMatches > 0) sText += " " + MessageText.getString("OpenTorrentWindow.xOfTotal", new String[] { Integer.toString(iMatches), Integer.toString(indexes.length) }); sItemsText[i] = sText; } cmbStartMode.setItems(sItemsText); cmbStartMode.select(iIndexToSelect); cmbStartMode.layout(true); } private void updateQueueLocationCombo() { if (cmbQueueLocation == null) return; int[] indexes = torrentTable.getSelectionIndices(); String[] sItemsText = new String[queueLocations.length]; int iMaxMatches = 0; int iIndexToSelect = QUEUELOCATION_BOTTOM; for (int i = 0; i < queueLocations.length; i++) { int iMatches = 0; for (int j = 0; j < indexes.length; j++) { TorrentInfo info = (TorrentInfo) torrentList.get(indexes[j]); if (info.iQueueLocation == i) iMatches++; } if (iMatches > iMaxMatches) { iMaxMatches = iMatches; iIndexToSelect = i; } String sText = MessageText.getString("OpenTorrentWindow.addPosition." + queueLocations[i]); if (iMatches > 0) sText += " " + MessageText.getString("OpenTorrentWindow.xOfTotal", new String[] { Integer.toString(iMatches), Integer.toString(indexes.length) }); sItemsText[i] = sText; } cmbQueueLocation.setItems(sItemsText); cmbQueueLocation.select(iIndexToSelect); } /** * @param c * @param keyListener */ private void setPasteKeyListener(Control c, KeyListener keyListener) { if (!(c instanceof Text) && !(c instanceof Combo) && !(c instanceof Composite) || (c instanceof Table)) { c.addKeyListener(keyListener); } if (c instanceof Composite) { Control[] controls = ((Composite) c).getChildren(); for (int i = 0; i < controls.length; i++) { setPasteKeyListener(controls[i], keyListener); } } } private void browseURL() { new OpenUrlWindow(shellForChildren, null, null, OpenTorrentWindow.this); } private void close(boolean dispose, boolean bCancel) { stOpenTorrentWindow = null; // Can't rely on (stOpenTorrentWindow == null) to check if we are closed // since another thread may create another OpenTorrentWindow while // we are closing this one. bClosed = true; try { UIUpdaterSWT.getInstance().removeUpdater(this); } catch (Exception e) { Debug.out(e); } if (dispose && shell != null && !shell.isDisposed()) { // We won't be recalled by disposal hook because we set bClosed shell.dispose(); } Utils.disposeSWTObjects(disposeList); if (bCancel) { List to_cancel; synchronized( downloaders ){ to_cancel = new ArrayList( downloaders ); downloaders.clear(); } if (to_cancel.size() > 0){ for (Iterator iter = to_cancel.iterator(); iter.hasNext();) { TorrentDownloader element = (TorrentDownloader) iter.next(); element.cancel(); } } for (Iterator iter = torrentList.iterator(); iter.hasNext();) { TorrentInfo info = (TorrentInfo) iter.next(); if (info.bDeleteFileOnCancel) { File file = new File(info.sFileName); if (file.exists()) file.delete(); } } torrentList.clear(); } } private void createTorrentListArea(Composite cArea) { GridData gridData; TableColumn tc; GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 2; cArea.setLayout(layout); torrentTable = new Table(cArea, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL); gridData.heightHint = 50; gridData.widthHint = 450; torrentTable.setLayoutData(gridData); tc = new TableColumn(torrentTable, SWT.NULL); Messages.setLanguageText(tc, "OpenTorrentWindow.torrentTable.name"); tc.setWidth(150); tc = new TableColumn(torrentTable, SWT.NULL); Messages.setLanguageText(tc, "OpenTorrentWindow.torrentTable.saveLocation"); tc.setWidth(150); tc = new TableColumn(torrentTable, SWT.NULL); Messages.setLanguageText(tc, "OpenTorrentWindow.startMode"); tc.setWidth(70); tc = new TableColumn(torrentTable, SWT.NULL); Messages.setLanguageText(tc, "OpenTorrentWindow.addPosition"); tc.setWidth(80); if (Utils.LAST_TABLECOLUMN_EXPANDS) tc.setData("Width", new Long(80)); torrentTable.addListener(SWT.SetData, new Listener() { public void handleEvent(Event event) { if (bClosed) return; TableItem item = (TableItem) event.item; int index = torrentTable.indexOf(item); if (index < 0) return; TorrentInfo info = (TorrentInfo) torrentList.get(index); item.setText(new String[] { info.getTorrentName(), info.getDataDir(), MessageText.getString("OpenTorrentWindow.startMode." + startModes[info.iStartID]), MessageText.getString("OpenTorrentWindow.addPosition." + queueLocations[info.iQueueLocation]) }); if (!info.isValid) { item.setForeground(Colors.red); Font font = item.getFont(); FontData[] fd = font.getFontData(); for (int i = 0; i < fd.length; i++) { fd[i].setStyle(SWT.ITALIC); } font = new Font(item.getDisplay(), fd); disposeList.add(font); item.setFont(font); } Utils.alternateRowBackground(item); } }); torrentTable.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { dataFiles.clear(); int[] indexes = torrentTable.getSelectionIndices(); for (int i = 0; i < indexes.length; i++) { TorrentInfo info = (TorrentInfo) torrentList.get(indexes[i]); TorrentFileInfo[] files = info.getFiles(); dataFiles.addAll(Arrays.asList(files)); } updateDataDirCombo(); updateStartModeCombo(); updateQueueLocationCombo(); dataFileTable.setItemCount(dataFiles.size()); dataFileTable.clearAll(); editCell(-1); updateSize(); resizeTables(2); } }); torrentTable.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.character == SWT.DEL) { deleteSelected(torrentTable, torrentList); e.doit = false; } } }); torrentTable.setHeaderVisible(true); // Menu for tableTorrents String sTitle; Menu menu = new Menu(torrentTable.getShell()); MenuItem item; sTitle = MessageText.getString("OpenTorrentWindow.startMode"); int userMode = COConfigurationManager.getIntParameter("User Mode"); for (int i = 0; i < startModes.length; i++) { if (i == STARTMODE_FORCESTARTED && userMode == 0) continue; item = new MenuItem(menu, SWT.PUSH); item.setData("Value", new Long(i)); item.setText(sTitle + ": " + MessageText.getString("OpenTorrentWindow.startMode." + startModes[i])); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Long l = (Long) e.widget.getData("Value"); if (l != null) { setSelectedStartMode(l.intValue()); checkSeedingMode(); } } }); } item = new MenuItem(menu, SWT.SEPARATOR); sTitle = MessageText.getString("OpenTorrentWindow.addPosition"); for (int i = 0; i < queueLocations.length; i++) { item = new MenuItem(menu, SWT.PUSH); item.setData("Value", new Long(i)); item.setText(sTitle + ": " + MessageText.getString("OpenTorrentWindow.addPosition." + queueLocations[i])); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Long l = (Long) e.widget.getData("Value"); if (l != null) { setSelectedQueueLocation(l.intValue()); } } }); } item = new MenuItem(menu, SWT.SEPARATOR); item = new MenuItem(menu, SWT.PUSH); // steal text Messages.setLanguageText(item, "MyTorrentsView.menu.remove"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { deleteSelected(torrentTable, torrentList); } }); item = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(item, "OpenTorrentWindow.fileList.changeDestination"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int[] indexes = torrentTable.getSelectionIndices(); String sDefPath = sDestDir; for (int i = 0; i < indexes.length; i++) { TorrentInfo info = (TorrentInfo) torrentList.get(indexes[i]); TorrentFileInfo[] files = info.getFiles(); if (files.length == 1 && info.torrent.isSimpleTorrent()) { changeFileDestination(new int[] { 0 }); } else { DirectoryDialog dDialog = new DirectoryDialog(shellForChildren, SWT.SYSTEM_MODAL); dDialog.setFilterPath(sDefPath); dDialog.setMessage(MessageText.getString("MainWindow.dialog.choose.savepath") + " (" + info.getTorrentName() + ")"); String sNewDir = dDialog.open(); if (sNewDir == null) return; File newDir = new File(sNewDir).getAbsoluteFile(); if(newDir.isDirectory()) sDefPath = sNewDir; info.sDestDir = newDir.getParent(); if (info.sDestDir == null) info.sDestDir = newDir.getPath(); info.sDestSubDir = newDir.getName(); for (int j = 0; j < files.length; j++) { TorrentFileInfo fileInfo = files[j]; fileInfo.setDestFileName(null); } } } // for i checkSeedingMode(); updateDataDirCombo(); diskFreeInfoRefreshPending = true; } }); torrentTable.setMenu(menu); Composite cTorrentListRight = new Composite(cArea, SWT.NONE); gridData = new GridData(); cTorrentListRight.setLayoutData(gridData); RowLayout rLayout = new RowLayout(SWT.VERTICAL); rLayout.marginBottom = 0; rLayout.marginLeft = 0; rLayout.marginRight = 0; rLayout.marginTop = 0; if (!Constants.isOSX) rLayout.spacing = 0; rLayout.fill = true; cTorrentListRight.setLayout(rLayout); ImageLoader imageLoader = ImageLoader.getInstance(); Button torMoveUp = new Button(cTorrentListRight, SWT.PUSH); imageLoader.setButtonImage(torMoveUp, "up"); torMoveUp.setToolTipText(MessageText.getString("Button.moveUp")); torMoveUp.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { int[] indices = torrentTable.getSelectionIndices(); if (indices.length == 0) return; Arrays.sort(indices); if (indices[0] == 0) return; for (int i = 0; i < indices.length; i++) { int pos = indices[i]; Object save = torrentList.get(pos - 1); torrentList.set(pos - 1, torrentList.get(pos)); torrentList.set(pos, save); indices[i]--; } torrentTable.setSelection(indices); torrentTable.clearAll(); } }); Button torMoveDown = new Button(cTorrentListRight, SWT.PUSH); imageLoader.setButtonImage(torMoveDown, "down"); torMoveDown.setToolTipText(MessageText.getString("Button.moveDown")); torMoveDown.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { int[] indices = torrentTable.getSelectionIndices(); if (indices.length == 0) return; Arrays.sort(indices); int max = indices.length - 1; if (indices[max] == torrentList.size() - 1) return; for (int i = max; i >= 0; i--) { int pos = indices[i]; Object save = torrentList.get(pos + 1); torrentList.set(pos + 1, torrentList.get(pos)); torrentList.set(pos, save); indices[i]++; } torrentTable.setSelection(indices); torrentTable.clearAll(); } }); Button torMoveRemove = new Button(cTorrentListRight, SWT.PUSH); torMoveRemove.setToolTipText(MessageText.getString("OpenTorrentWindow.torrent.remove")); imageLoader.setButtonImage(torMoveRemove, "delete"); torMoveRemove.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { deleteSelected(torrentTable, torrentList); } }); } /** * @param iLocation */ protected void setSelectedQueueLocation(int iLocation) { int[] indices = torrentTable.getSelectionIndices(); for (int i = 0; i < indices.length; i++) { TorrentInfo info = (TorrentInfo) torrentList.get(indices[i]); info.iQueueLocation = iLocation; } updateQueueLocationCombo(); torrentTable.clear(indices); } /** * @param iStartID */ protected void setSelectedStartMode(int iStartID) { int[] indices = torrentTable.getSelectionIndices(); for (int i = 0; i < indices.length; i++) { TorrentInfo info = (TorrentInfo) torrentList.get(indices[i]); info.iStartID = iStartID; } checkSeedingMode(); updateStartModeCombo(); torrentTable.clear(indices); } private void checkSeedingMode() { // Check for seeding for (int i = 0; i < torrentList.size(); i++) { boolean bTorrentValid = true; TorrentInfo info = (TorrentInfo) torrentList.get(i); if (info.iStartID == STARTMODE_SEEDING) { // check if all selected files exist TorrentFileInfo[] files = info.getFiles(); for (int j = 0; j < files.length; j++) { TorrentFileInfo fileInfo = files[j]; if (!fileInfo.bDownload) continue; File file = fileInfo.getDestFileFullName(); if (!file.exists()) { fileInfo.isValid = false; bTorrentValid = false; } else if (!fileInfo.isValid) { fileInfo.isValid = true; } } } info.isValid = bTorrentValid; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (torrentTable != null && !torrentTable.isDisposed()) { torrentTable.clearAll(); } if (dataFileTable != null && !dataFileTable.isDisposed()) { dataFileTable.clearAll(); editCell(-1); } } }); } private void deleteSelected(Table table, ArrayList list) { int[] indexes = table.getSelectionIndices(); Arrays.sort(indexes); for (int i = indexes.length - 1; i >= 0; i--) { if (list.get(indexes[i]) instanceof TorrentInfo) { TorrentInfo info = (TorrentInfo) list.get(indexes[i]); if (info.bDeleteFileOnCancel) { File file = new File(info.sFileName); if (file.exists()) file.delete(); } } list.remove(indexes[i]); } table.setItemCount(list.size()); table.clearAll(); table.notifyListeners(SWT.Selection, new Event()); } private void editCell(final int row) { Text oldEditor = (Text)dataFileTableEditor.getEditor(); if(row < 0 || row >= dataFileTable.getItemCount()) { if(oldEditor != null && !oldEditor.isDisposed()) oldEditor.dispose(); return; } final Text newEditor = oldEditor == null || oldEditor.isDisposed() ? new Text(dataFileTable,SWT.BORDER) : oldEditor; final TorrentFileInfo file = (TorrentFileInfo) dataFiles.get(row); final String uneditedName = file.getDestFileName(); TableItem item = dataFileTable.getItem(row); TableColumn column = dataFileTable.getColumn(EDIT_COLUMN_INDEX); newEditor.setText(uneditedName); newEditor.selectAll(); newEditor.forceFocus(); Rectangle leftAlignedBounds = item.getBounds(EDIT_COLUMN_INDEX); leftAlignedBounds.width = dataFileTableEditor.minimumWidth = newEditor.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; if(leftAlignedBounds.intersection(dataFileTable.getClientArea()).equals(leftAlignedBounds)) dataFileTableEditor.horizontalAlignment = SWT.LEFT; else dataFileTableEditor.horizontalAlignment = SWT.RIGHT; dataFileTable.deselectAll(); dataFileTable.select(row); dataFileTable.showItem(item); dataFileTable.showColumn(column); class QuickEditListener implements ModifyListener, SelectionListener, KeyListener, TraverseListener { public void modifyText(ModifyEvent e) { file.setDestFileName(newEditor.getText()); try { file.getDestFileFullName().getCanonicalFile(); newEditor.setBackground(null); } catch (IOException e1) { newEditor.setBackground(Colors.colorErrorBG); } } public void widgetDefaultSelected(SelectionEvent e) { try { file.getDestFileFullName().getCanonicalFile(); } catch (IOException e1) { file.setDestFileName(uneditedName); } move(row,1,(Text)e.widget); } public void widgetSelected(SelectionEvent e) {} public void keyReleased(KeyEvent e) {} public void keyPressed(KeyEvent e) { if(e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.ARROW_UP) { e.doit = false; move(row,e.keyCode == SWT.ARROW_DOWN ? 1 : -1,(Text)e.widget); } } public void keyTraversed(TraverseEvent e) { if(e.detail == SWT.TRAVERSE_ESCAPE || e.detail == SWT.TRAVERSE_RETURN) e.doit = false; if(e.detail == SWT.TRAVERSE_ESCAPE) editCell(-1); } private void move(int oldRow, int offset, Text current) { current.removeModifyListener(QuickEditListener.this); current.removeSelectionListener(QuickEditListener.this); current.removeKeyListener(QuickEditListener.this); current.removeTraverseListener(QuickEditListener.this); editCell(oldRow+offset); dataFileTable.clear(oldRow); } } QuickEditListener listener = new QuickEditListener(); newEditor.addModifyListener(listener); newEditor.addSelectionListener(listener); newEditor.addKeyListener(listener); newEditor.addTraverseListener(listener); dataFileTableEditor.setEditor(newEditor, dataFileTable.getItem(row), EDIT_COLUMN_INDEX); } private static final int EDIT_COLUMN_INDEX = 1; private void createTableDataFiles(Composite cArea) { GridData gridData; TableColumn tc; dataFileTable = new Table(cArea, SWT.BORDER | SWT.CHECK | SWT.FULL_SELECTION | SWT.VIRTUAL | SWT.MULTI); dataFileTableEditor = new TableEditor(dataFileTable); dataFileTableEditor.grabHorizontal = true; dataFileTableEditor.minimumWidth = 50; gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 80; gridData.widthHint = 100; dataFileTable.setLayoutData(gridData); tc = new TableColumn(dataFileTable, SWT.NULL); Messages.setLanguageText(tc, "OpenTorrentWindow.fileTable.fileName"); tc.setWidth(150); tc = new TableColumn(dataFileTable, SWT.NULL); Messages.setLanguageText(tc, "OpenTorrentWindow.fileTable.destinationName"); tc.setWidth(140); tc = new TableColumn(dataFileTable, SWT.NULL); Messages.setLanguageText(tc, "OpenTorrentWindow.fileTable.size"); tc.setAlignment(SWT.TRAIL); tc.setWidth(90); if (Utils.LAST_TABLECOLUMN_EXPANDS) tc.setData("Width", new Long(90)); dataFileTable.addListener(SWT.SetData, new Listener() { public void handleEvent(Event event) { if (bClosed) return; final TableItem item = (TableItem) event.item; int index = dataFileTable.indexOf(item); final TorrentFileInfo file = (TorrentFileInfo) dataFiles.get(index); item.setText(new String[] { file.orgFullName, file.isLinked() ? file.getDestFileFullName().toString() : file.getDestFileName(), DisplayFormatters.formatByteCountToKiBEtc(file.lSize) }); if (!file.isValid) { item.setForeground(Colors.red); Font font = item.getFont(); FontData[] fd = font.getFontData(); for (int i = 0; i < fd.length; i++) { fd[i].setStyle(SWT.ITALIC); } font = new Font(item.getDisplay(), fd); disposeList.add(font); item.setFont(font); } Utils.alternateRowBackground(item); Utils.setCheckedInSetData(item, file.bDownload); item.setGrayed(!file.okToDisable()); } }); dataFileTable.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { if (event.detail == SWT.CHECK) { TableItem item = (TableItem) event.item; int index = dataFileTable.indexOf(item); TorrentFileInfo file = (TorrentFileInfo) dataFiles.get(index); // don't allow disabling of small files // XXX Maybe warning prompt instead? if (!item.getChecked() && !file.okToDisable()) item.setChecked(true); else file.bDownload = item.getChecked(); updateSize(); } } }); dataFileTable.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { editCell(-1); // cleanup if(e.button != 1) return; TableItem[] items = dataFileTable.getItems(); boolean found = false; int i; outer: for (i = 0; i < items.length; i++) { TableItem item = items[i]; Rectangle rect = item.getBounds(); if (e.y < rect.y || (rect.y + rect.height) < e.y) continue; for (int j = 0; j < dataFileTable.getColumnCount(); j++) { if (!item.getBounds(j).contains(e.x, e.y)) continue; found = j == EDIT_COLUMN_INDEX; break outer; } } if(found) editCell(i); } }); dataFileTable.setHeaderVisible(true); Menu menu = new Menu(dataFileTable); dataFileTable.setMenu(menu); MenuItem item; item = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(item, "OpenTorrentWindow.fileList.changeDestination"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int[] indexes = dataFileTable.getSelectionIndices(); changeFileDestination(indexes); } }); Composite cBottomArea = new Composite(cArea, SWT.NONE); GridLayout gLayout = new GridLayout(); gLayout.marginHeight = 0; gLayout.marginWidth = 0; gLayout.numColumns = 2; gLayout.verticalSpacing = 0; cBottomArea.setLayout(gLayout); gridData = new GridData(GridData.FILL_HORIZONTAL); cBottomArea.setLayoutData(gridData); Composite cButtons = new Composite(cBottomArea, SWT.NONE); RowLayout rLayout = new RowLayout(SWT.HORIZONTAL); rLayout.wrap = false; rLayout.marginBottom = 0; rLayout.marginLeft = 0; rLayout.marginRight = 0; rLayout.marginTop = 0; cButtons.setLayout(rLayout); gridData = new GridData(SWT.END, SWT.BEGINNING, false, false); gridData.verticalSpan = 2; cButtons.setLayoutData(gridData); Button btnSelectAll = new Button(cButtons, SWT.PUSH); Messages.setLanguageText(btnSelectAll, "Button.selectAll"); btnSelectAll.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { dataFileTable.selectAll(); } }); Button btnMarkSelected = new Button(cButtons, SWT.PUSH); Messages.setLanguageText(btnMarkSelected, "Button.markSelected"); btnMarkSelected.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { int[] indexes = dataFileTable.getSelectionIndices(); for (int i = 0; i < indexes.length; i++) { TorrentFileInfo file = (TorrentFileInfo) dataFiles.get(indexes[i]); file.bDownload = true; } dataFileTable.clearAll(); updateSize(); } }); Button btnUnmarkSelected = new Button(cButtons, SWT.PUSH); Messages.setLanguageText(btnUnmarkSelected, "Button.unmarkSelected"); btnUnmarkSelected.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { int[] indexes = dataFileTable.getSelectionIndices(); for (int i = 0; i < indexes.length; i++) { TorrentFileInfo file = (TorrentFileInfo) dataFiles.get(indexes[i]); if (file.okToDisable()) file.bDownload = false; } dataFileTable.clearAll(); updateSize(); } }); dataFileTableLabel = new Label(cBottomArea, SWT.WRAP); dataFileTableLabel.setAlignment(SWT.RIGHT); gridData = new GridData(SWT.END, SWT.BEGINNING, true, false); dataFileTableLabel.setLayoutData(gridData); diskspaceComp = new Composite(cBottomArea, SWT.NONE); gLayout = new GridLayout(2, false); gLayout.marginHeight = gLayout.marginWidth = 1; gLayout.verticalSpacing = 0; gLayout.horizontalSpacing = 15; diskspaceComp.setLayout(gLayout); gridData = new GridData(SWT.END, SWT.BEGINNING, true, false); diskspaceComp.setLayoutData(gridData); } /** * @param indexes */ protected void changeFileDestination(int[] indexes) { for (int i = 0; i < indexes.length; i++) { TorrentFileInfo fileInfo = (TorrentFileInfo) dataFiles.get(indexes[i]); int style = (fileInfo.parent.iStartID == STARTMODE_SEEDING) ? SWT.OPEN : SWT.SAVE; FileDialog fDialog = new FileDialog(shellForChildren, SWT.SYSTEM_MODAL | style); String sFilterPath = fileInfo.getDestPathName(); String sFileName = fileInfo.orgFileName; File f = new File(sFilterPath); if (!f.isDirectory()) { // Move up the tree until we have an existing path while (sFilterPath != null) { String parentPath = f.getParent(); if (parentPath == null) break; sFilterPath = parentPath; f = new File(sFilterPath); if (f.isDirectory()) break; } } if (sFilterPath != null) fDialog.setFilterPath(sFilterPath); fDialog.setFileName(sFileName); fDialog.setText(MessageText.getString("MainWindow.dialog.choose.savepath") + " (" + fileInfo.orgFullName + ")"); String sNewName = fDialog.open(); if (sNewName == null) return; if (fileInfo.parent.iStartID == STARTMODE_SEEDING) { File file = new File(sNewName); if (file.length() == fileInfo.lSize) fileInfo.setFullDestName(sNewName); else { MessageBoxShell mb = new MessageBoxShell(SWT.OK, "OpenTorrentWindow.mb.badSize", new String[] { file.getName(), fileInfo.orgFullName }); mb.open(null); } } else fileInfo.setFullDestName(sNewName); } // for i checkSeedingMode(); updateDataDirCombo(); diskFreeInfoRefreshPending = true; } /** * Add Torrent(s) to Window using a text list of files/urls/torrents * * @param sClipText Text to parse * @param bVerifyOnly Only check if there's potential torrents in the text, * do not try to add the torrents. * * @return Number of torrents added or found. When bVerifyOnly, this number * may not be exact. */ private int addTorrentsFromTextList(String sClipText, boolean bVerifyOnly) { String[] lines = null; int iNumFound = 0; // # of consecutive non torrent lines int iNoTorrentLines = 0; // no use checking the whole clipboard (which may be megabytes) final int MAX_CONSECUTIVE_NONTORRENT_LINES = 100; final String[] splitters = { "\r\n", "\n", "\r", "\t" }; for (int i = 0; i < splitters.length; i++) if (sClipText.indexOf(splitters[i]) >= 0) { lines = sClipText.split(splitters[i]); break; } if (lines == null) lines = new String[] { sClipText }; // Check if URL, 20 byte hash, Dir, or file for (int i = 0; i < lines.length; i++) { String line = lines[i].trim(); if (line.startsWith("\"") && line.endsWith("\"")) { if (line.length() < 3) { line = ""; } else { line = line.substring(1, line.length() - 2); } } boolean ok; if (line == "") { ok = false; } else if (UrlUtils.isURL(line)) { ok = true; } else { File file = new File(line); if (!file.exists()) { ok = false; } else if (file.isDirectory()) { if (bVerifyOnly) { // XXX Could do a file count here, but the number found is not // expected to be an exact number anyway, since we aren't // event verifying if they are torrents. ok = true; } else { iNumFound += addTorrents(lines[i], null); ok = false; } } else { ok = true; } } if (!ok) { iNoTorrentLines++; lines[i] = null; if (iNoTorrentLines > MAX_CONSECUTIVE_NONTORRENT_LINES) break; } else { iNumFound++; iNoTorrentLines = 0; } } if (bVerifyOnly) { return iNumFound; } return addTorrents(null, lines); } /** * Add Torrent(s) to window * * @param sTorrentFilePath * @param sTorrentFilenames * @return # torrents actually added to list (or downloading) */ private int addTorrents(String sTorrentFilePath, String[] sTorrentFilenames) { sTorrentFilePath = ensureTrailingSeparator(sTorrentFilePath); // Process Directory if (sTorrentFilePath != null && sTorrentFilenames == null) { File dir = new File(sTorrentFilePath); if (!dir.isDirectory()) return 0; final File[] files = dir.listFiles(new FileFilter() { public boolean accept(File arg0) { if (FileUtil.getCanonicalFileName(arg0.getName()).endsWith(".torrent")) return true; if (FileUtil.getCanonicalFileName(arg0.getName()).endsWith(".tor")) return true; return false; } }); if (files.length == 0) return 0; sTorrentFilenames = new String[files.length]; for (int i = 0; i < files.length; i++) sTorrentFilenames[i] = files[i].getName(); } int numAdded = 0; for (int i = 0; i < sTorrentFilenames.length; i++) { if (sTorrentFilenames[i] == null || sTorrentFilenames[i] == "") continue; // Process File String sFileName = ((sTorrentFilePath == null) ? "" : sTorrentFilePath) + sTorrentFilenames[i]; if (!new File(sFileName).exists()) { // Process URL String sURL = UrlUtils.parseTextForURL(sTorrentFilenames[i], true); if (sURL != null) { if (COConfigurationManager.getBooleanParameter("Add URL Silently")) { new FileDownloadWindow(shellForChildren, sURL, null, null, this); } else { new OpenUrlWindow(shellForChildren, sURL, null, this); } numAdded++; continue; } } if (addTorrent(sFileName, sFileName) != null) numAdded++; } if (numAdded > 0 && shell != null && torrentTable != null && !shell.isDisposed()) { int iTotal = torrentList.size(); torrentTable.setItemCount(iTotal); // select the ones we just added torrentTable.select(iTotal - numAdded, iTotal - 1); torrentTable.clearAll(); // select doesn't notify listeners? Do it manually. torrentTable.notifyListeners(SWT.Selection, new Event()); resizeTables(1); checkSeedingMode(); } return numAdded; } private TorrentInfo addTorrent(String sFileName, final String sOriginatingLocation) { TorrentInfo info = null; TOTorrent torrent = null; File torrentFile; boolean bDeleteFileOnCancel = false; // Make a copy if user wants that. We'll delete it when we cancel, if we // actually made a copy. try { if (sFileName.startsWith("file://localhost/")) { sFileName = UrlUtils.decode(sFileName.substring(16)); } final File fOriginal = new File(sFileName); if (!fOriginal.isFile() || !fOriginal.exists()) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (shell == null) new MessageSlideShell(Display.getCurrent(), SWT.ICON_ERROR, "OpenTorrentWindow.mb.openError", fOriginal.toString(), new String[] { UrlUtils.decode(sOriginatingLocation), "Not a File" }, -1 ); else { MessageBoxShell mb = new MessageBoxShell(SWT.OK, "OpenTorrentWindow.mb.openError", new String[] { sOriginatingLocation, "Not a File" }); mb.open(null); } } }); return null; } torrentFile = TorrentUtils.copyTorrentFileToSaveDir(fOriginal, true); bDeleteFileOnCancel = !fOriginal.equals(torrentFile); // TODO if the files are still equal, and it isn't in the save // dir, we should copy it to a temp file in case something // re-writes it. No need to copy a torrent coming from the // downloader though.. } catch (IOException e1) { // Use torrent in wherever it is and hope for the best // XXX Should error instead? torrentFile = new File(sFileName); } // Do a quick check to see if it's a torrent if (!TorrentUtil.isFileTorrent(torrentFile, shellForChildren, torrentFile.getName())) { if (bDeleteFileOnCancel) { torrentFile.delete(); } return null; } // Load up the torrent, see it it's real try { torrent = TorrentUtils.readFromFile(torrentFile, false); } catch (final TOTorrentException e) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (shell == null) new MessageSlideShell(Display.getCurrent(), SWT.ICON_ERROR, "OpenTorrentWindow.mb.openError", Debug.getStackTrace(e), new String[] { sOriginatingLocation, e.getMessage() }, -1 ); else { MessageBoxShell mb = new MessageBoxShell(SWT.OK, "OpenTorrentWindow.mb.openError", new String[] { sOriginatingLocation, e.getMessage() }); mb.open(null); } } }); if (bDeleteFileOnCancel) torrentFile.delete(); return null; } String sExistingName = null; try { HashWrapper hash = torrent.getHashWrapper(); if (hash != null) { for (int i = 0; i < torrentList.size(); i++) { try { TorrentInfo existing = (TorrentInfo) torrentList.get(i); if (existing.torrent.getHashWrapper().equals(hash)) { //sExistingName = existing.sOriginatingLocation; // Exit without warning when it already exists in list if (bDeleteFileOnCancel) torrentFile.delete(); return null; } } catch (Exception e) { } } } } catch (Exception e) { } DownloadManager existingDownload = null; if (sExistingName == null) { // Check if torrent already exists in gm, and add if not existingDownload = (gm == null) ? null : gm.getDownloadManager(torrent); if (existingDownload != null) { sExistingName = existingDownload.getDisplayName(); } } if (sExistingName == null) { info = new TorrentInfo(torrentFile.getAbsolutePath(), torrent, bDeleteFileOnCancel); info.sOriginatingLocation = sOriginatingLocation; torrentList.add(info); } else { final String sfExistingName = sExistingName; final DownloadManager fExistingDownload = existingDownload; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (shell == null) new MessageSlideShell(Display.getCurrent(), SWT.ICON_INFORMATION, MSG_ALREADY_EXISTS, null, new String[] { ":" + sOriginatingLocation, sfExistingName, MessageText.getString(MSG_ALREADY_EXISTS_NAME), }, new Object[] { fExistingDownload }, -1 ); else { MessageBoxShell mb = new MessageBoxShell(SWT.OK, MSG_ALREADY_EXISTS, new String[] { ":" + sOriginatingLocation, sfExistingName, MessageText.getString(MSG_ALREADY_EXISTS_NAME), }); mb.open(null); } } }); if (bDeleteFileOnCancel) torrentFile.delete(); } return info; } /** * Resize the columns of the tables to fit without horizontal scrollbar * * @param which bitwise field of which table to recalc * Bit 0: torrents table * Bit 1: Data Files Table */ private void resizeTables(int which) { try { TableColumn[] tcs; if ((which & 1) > 0 && torrentTable != null && !torrentTable.isDisposed()) { tcs = torrentTable.getColumns(); int newSize = torrentTable.getClientArea().width - 20; int iLength = tcs.length; if (Utils.LAST_TABLECOLUMN_EXPANDS) { iLength--; newSize -= ((Long) tcs[iLength].getData("Width")).intValue(); } final int columnToExpand = 1; for (int i = 0; i < iLength; i++) if (i != columnToExpand) newSize -= tcs[i].getWidth(); if (newSize > 10) tcs[columnToExpand].setWidth(newSize); } // Adjust only first column if ((which & 2) > 0 && dataFileTable != null && !dataFileTable.isDisposed()) { tcs = dataFileTable.getColumns(); int newSize = dataFileTable.getClientArea().width - 20; int iLength = tcs.length; if (Utils.LAST_TABLECOLUMN_EXPANDS) { iLength--; newSize -= ((Long) tcs[iLength].getData("Width")).intValue(); } final int columnToExpand = 0; for (int i = 0; i < iLength; i++) if (i != columnToExpand) newSize -= tcs[i].getWidth(); if (newSize > 10) tcs[columnToExpand].setWidth(newSize); } } catch (Exception e) { // ignore e.printStackTrace(); } } /** * Open the torrents already added based on user choices * * @param sDataDir */ private void openTorrents() { Utils.getOffOfSWTThread(new AERunnable() { public void runSupport() { _openTorrents(); } }); } private void _openTorrents() { ArrayList addedTorrentsTop = new ArrayList(); for (int i = 0; i < torrentList.size(); i++) { final TorrentInfo info = (TorrentInfo) torrentList.get(i); try { if (info.torrent == null) continue; int iStartState = (info.iStartID == STARTMODE_STOPPED) ? DownloadManager.STATE_STOPPED : DownloadManager.STATE_QUEUED; final TorrentFileInfo[] files = info.getFiles(); byte[] hash = null; try { hash = info.torrent.getHash(); } catch (TOTorrentException e1) { } DownloadManager dm = gm.addDownloadManager(info.sFileName, hash, info.sDestDir, info.sDestSubDir, iStartState, true, info.iStartID == STARTMODE_SEEDING, new DownloadManagerInitialisationAdapter() { public void initialised(DownloadManager dm) { DiskManagerFileInfo[] fileInfos = dm.getDiskManagerFileInfo(); try { dm.getDownloadState().suppressStateSave(true); boolean[] toSkip = new boolean[fileInfos.length]; boolean[] toCompact = new boolean[fileInfos.length]; for (int iIndex = 0; iIndex < fileInfos.length; iIndex++) { DiskManagerFileInfo fileInfo = fileInfos[iIndex]; if (iIndex >= 0 && iIndex < files.length && files[iIndex].lSize == fileInfo.getLength()) { // Always pull destination file from fileInfo and not from // TorrentFileInfo because the destination may have changed // by magic code elsewhere File fDest = fileInfo.getFile(true); if (files[iIndex].isLinked()) { fDest = files[iIndex].getDestFileFullName(); // Can't use fileInfo.setLink(fDest) as it renames // the existing file if there is one dm.getDownloadState().setFileLink( fileInfo.getFile(false), fDest); } if (!files[iIndex].bDownload) { toSkip[iIndex] = true; if (!fDest.exists()) toCompact[iIndex] = true; } } } dm.getDiskManagerFileInfoSet().setStorageTypes(toCompact, DiskManagerFileInfo.ST_COMPACT); dm.getDiskManagerFileInfoSet().setSkipped(toSkip, true); } finally { dm.getDownloadState().suppressStateSave(false); } } }); // If dm is null, most likely there was an error printed.. let's hope // the user was notified and skip the error quietly. // We don't have to worry about deleting the file (info.bDelete..) // since gm.addDown.. will handle it. if (dm == null) continue; if (info.iQueueLocation == QUEUELOCATION_TOP) addedTorrentsTop.add(dm); if (info.iStartID == STARTMODE_FORCESTARTED) { dm.setForceStart(true); } } catch (Exception e) { if (shell == null) new MessageSlideShell(Display.getCurrent(), SWT.ICON_ERROR, "OpenTorrentWindow.mb.openError", Debug.getStackTrace(e), new String[] { info.sOriginatingLocation, e.getMessage() }, -1 ); else { MessageBoxShell mb = new MessageBoxShell(SWT.OK, "OpenTorrentWindow.mb.openError", new String[] { info.sOriginatingLocation, e.getMessage() }); mb.open(null); } } } if (addedTorrentsTop.size() > 0) { DownloadManager[] dms = (DownloadManager[]) addedTorrentsTop.toArray(new DownloadManager[0]); gm.moveTop(dms); } torrentList.clear(); } private int getDefaultStartMode() { if (bDefaultForSeeding) return STARTMODE_SEEDING; return (bOverrideStartModeToStopped || COConfigurationManager.getBooleanParameter("Default Start Torrents Stopped")) ? STARTMODE_STOPPED : STARTMODE_QUEUED; } // TorrentDownloaderCallBackInterface public void TorrentDownloaderEvent(int state, final TorrentDownloader inf) { // This method is run even if the window is closed. // The default is to delete file on cancel // We set this flag to false if we detected the file was not a torrent if (!inf.getDeleteFileOnCancel() && (state == TorrentDownloader.STATE_CANCELLED || state == TorrentDownloader.STATE_ERROR || state == TorrentDownloader.STATE_DUPLICATE || state == TorrentDownloader.STATE_FINISHED)) { activeTorrentCount--; enableControl(ok, activeTorrentCount < 1); // PARG - yes, this code sucks, added some sync here to prvent some errors but obviously // it needs a complete rewrite synchronized( downloaders ){ if (!downloaders.contains(inf)) return; downloaders.remove(inf); } File file = inf.getFile(); // we already know it isn't a torrent.. we are just using the call // to popup the message TorrentUtil.isFileTorrent(file, shellForChildren, inf.getURL()); if (file.exists()) { file.delete(); } return; } if (state == TorrentDownloader.STATE_INIT) { activeTorrentCount++; enableControl(ok, activeTorrentCount < 1); synchronized( downloaders ){ downloaders.add(inf); } } else if (state == TorrentDownloader.STATE_FINISHED) { activeTorrentCount--; enableControl(ok, activeTorrentCount < 1); // This can be called more than once for each inf.. synchronized( downloaders ){ if (!downloaders.contains(inf)) return; downloaders.remove(inf); } File file = inf.getFile(); if (addTorrent(file.getAbsolutePath(), inf.getURL()) == null) { // addTorrent may not delete it on error if the downloader saved it // to the place where user wants to store torrents (which is most // likely) if (file.exists()) file.delete(); } else { if (shell != null && !shell.isDisposed()) { Utils.execSWTThread(new AERunnable() { public void runSupport() { torrentTable.setItemCount(torrentList.size()); torrentTable.clearAll(); // select the one we just added torrentTable.select(torrentList.size() - 1); // select doesn't notify listeners? Do it manually. torrentTable.notifyListeners(SWT.Selection, new Event()); resizeTables(1); } }); } else { String saveSilentlyDir = getSaveSilentlyDir(); if (saveSilentlyDir != null) { sDestDir = saveSilentlyDir; for (int i = 0; i < torrentList.size(); i++) { final TorrentInfo info = (TorrentInfo) torrentList.get(i); info.renameDuplicates(); } openTorrents(); } } } checkSeedingMode(); } else if (state == TorrentDownloader.STATE_CANCELLED || state == TorrentDownloader.STATE_ERROR || state == TorrentDownloader.STATE_DUPLICATE) { activeTorrentCount--; enableControl(ok, activeTorrentCount < 1); synchronized( downloaders ){ downloaders.remove(inf); } } else if (state == TorrentDownloader.STATE_DOWNLOADING) { int count = inf.getLastReadCount(); int numRead = inf.getTotalRead(); if (!inf.getDeleteFileOnCancel() && numRead >= 16384) { inf.cancel(); } else if (numRead == count && count > 0) { final byte[] bytes = inf.getLastReadBytes(); if (bytes[0] != 'd') { inf.setDeleteFileOnCancel(false); } } } else { return; } } /** * Class to store one Torrent file's info. Used to populate table and store * user's choices. */ private class TorrentInfo { /** Where the torrent came from. Could be a file, URL, or some other text */ String sOriginatingLocation; /** Filename the .torrent is saved to */ String sFileName; String sDestDir; /** for multifiletorrents and change location */ String sDestSubDir; TOTorrent torrent; int iStartID; int iQueueLocation; boolean isValid; boolean bDeleteFileOnCancel; private TorrentFileInfo[] files = null; /** * Init * * @param sFileName * @param torrent * @param bDeleteFileOnCancel */ public TorrentInfo(String sFileName, TOTorrent torrent, boolean bDeleteFileOnCancel) { this.bDeleteFileOnCancel = bDeleteFileOnCancel; this.sFileName = sFileName; this.sOriginatingLocation = sFileName; this.torrent = torrent; this.sDestDir = OpenTorrentWindow.this.sDestDir; iStartID = getDefaultStartMode(); iQueueLocation = QUEUELOCATION_BOTTOM; isValid = true; // Force a check on the encoding, will prompt user if we dunno try { LocaleTorrentUtil.getTorrentEncoding(TorrentInfo.this.torrent); } catch (Exception e) { e.printStackTrace(); } if (getSaveSilentlyDir() == null && COConfigurationManager.getBooleanParameter("DefaultDir.BestGuess") && !COConfigurationManager.getBooleanParameter(PARAM_MOVEWHENDONE)) { this.sDestDir = getSmartDestDir(); } } public String getParentDir() { return sDestDir; } public void setParentDir(String parentDir) { sDestDir = parentDir; } public String getDataDir() { if (torrent.isSimpleTorrent()) return sDestDir; return new File(sDestDir, sDestSubDir == null ? FileUtil.convertOSSpecificChars(getTorrentName(), true) : sDestSubDir).getPath(); } public String getSmartDestDir() { String sSmartDir = sDestDir; try { String name = getTorrentName(); String torrentFileName = new File(sFileName).getName().replaceFirst( "\\.torrent$", ""); int totalSegmentsLengths = 0; String[][] segments = { name.split("[^a-zA-Z]+"), torrentFileName.split("[^a-zA-Z]+") }; List downloadManagers = gm.getDownloadManagers(); for (int x = 0; x < segments.length; x++) { String[] segmentArray = segments[x]; for (int i = 0; i < segmentArray.length; i++) { int l = segmentArray[i].length(); if (l <= 1) { continue; } segmentArray[i] = segmentArray[i].toLowerCase(); totalSegmentsLengths += l; } } int maxMatches = 0; DownloadManager match = null; for (Iterator iter = downloadManagers.iterator(); iter.hasNext();) { DownloadManager dm = (DownloadManager) iter.next(); if (dm.getState() == DownloadManager.STATE_ERROR) { continue; } int numMatches = 0; String dmName = dm.getDisplayName().toLowerCase(); for (int x = 0; x < segments.length; x++) { String[] segmentArray = segments[x]; for (int i = 0; i < segmentArray.length; i++) { int l = segmentArray[i].length(); if (l <= 1) { continue; } String segment = segmentArray[i]; if (dmName.indexOf(segment) >= 0) { numMatches += l; } } } if (numMatches > maxMatches) { maxMatches = numMatches; match = dm; } } if (match != null) { //System.out.println(match + ": " + (maxMatches * 100 / totalSegmentsLengths) + "%\n"); int iMatchLevel = (maxMatches * 100 / totalSegmentsLengths); if (iMatchLevel >= 30) { File f = match.getSaveLocation(); if (!f.isDirectory() || match.getDiskManagerFileInfo().length > 1) { // don't place data within another torrent's data dir f = f.getParentFile(); } if (f != null && f.isDirectory()) { sSmartDir = f.getAbsolutePath(); } } } } catch (Exception e) { e.printStackTrace(); } return sSmartDir; } public TorrentFileInfo[] getFiles() { if (files == null && torrent != null) { TOTorrentFile[] tfiles = torrent.getFiles(); files = new TorrentFileInfo[tfiles.length]; for (int i = 0; i < files.length; i++) { files[i] = new TorrentFileInfo(this, tfiles[i], i); } } return files; } public String getTorrentName() { if (torrent == null) return ""; try { LocaleUtilDecoder decoder = LocaleTorrentUtil.getTorrentEncodingIfAvailable(torrent); if (decoder != null) return decoder.decodeString(torrent.getName()); } catch (Exception e) { } try { return new String(torrent.getName()); } catch (Exception e) { return "TextDecodingError"; } } public boolean allFilesMoving() { TorrentFileInfo[] files = getFiles(); for (int j = 0; j < files.length; j++) { if (files[j].isLinked()) { return false; } } return true; } public boolean allFilesExist() { // check if all selected files exist TorrentFileInfo[] files = getFiles(); for (int i = 0; i < files.length; i++) { TorrentFileInfo fileInfo = files[i]; if (!fileInfo.bDownload) continue; File file = fileInfo.getDestFileFullName(); if (!file.exists() || file.length() != fileInfo.lSize) { return false; } } return true; } public void renameDuplicates() { if (iStartID == STARTMODE_SEEDING || !COConfigurationManager.getBooleanParameter("DefaultDir.AutoSave.AutoRename") || allFilesExist()) { return; } if (!torrent.isSimpleTorrent()) { if (new File(getDataDir()).isDirectory()) { File f; int idx = 0; do { idx++; f = new File(getDataDir() + "-" + idx); } while (f.isDirectory()); sDestSubDir = f.getName(); } } else { // should only be one file TorrentFileInfo[] fileInfos = getFiles(); for (int i = 0; i < fileInfos.length; i++) { TorrentFileInfo info = fileInfos[i]; File file = info.getDestFileFullName(); int idx = 0; while (file.exists()) { idx++; file = new File(info.getDestPathName(), idx + "-" + info.getDestFileName()); } info.setDestFileName(file.getName()); } } } /* private Boolean has_multiple_small_files = null; private boolean hasMultipleSmallFiles() { TorrentFileInfo[] tfi_files = getFiles(); if (tfi_files.length <= MAX_NODOWNLOAD_COUNT) return false; int small_files_counted = 0; for (int i=0; i MAX_NODOWNLOAD_COUNT) { return true; } } } return false; } */ // Indicates whether all files in this torrent can be deselected // (if not, then it occurs on a per-file basis). public boolean okToDisableAll() { return true; /* if (iStartID == STARTMODE_SEEDING) return true; // Do we have multiple small files? We'll allow all of them to // be disabled if we do. if (has_multiple_small_files == null) { has_multiple_small_files = new Boolean(hasMultipleSmallFiles()); } // You can disable all files if there are lots of small files. return has_multiple_small_files.booleanValue(); */ } } /** * Class to store the file list of a Torrent. Used to populate table and * store user's choices */ private class TorrentFileInfo { /** relative path + full file name as specified by the torrent */ final String orgFullName; final String orgFileName; long lSize; boolean bDownload; private String destFileName; private String destPathName; long iIndex; boolean isValid; final TorrentInfo parent; /** * Init * * @param parent * @param torrentFile * @param iIndex */ public TorrentFileInfo(TorrentInfo parent, TOTorrentFile torrentFile, int iIndex) { this.parent = parent; lSize = torrentFile.getLength(); this.iIndex = iIndex; bDownload = true; isValid = true; orgFullName = torrentFile.getRelativePath(); // translated to locale orgFileName = new File(orgFullName).getName(); } public void setFullDestName(String newFullName) { if(newFullName == null) { setDestPathName(null); setDestFileName(null); return; } File newPath = new File(newFullName); setDestPathName(newPath.getParent()); setDestFileName(newPath.getName()); } public void setDestPathName(String newPath) { if(parent.torrent.isSimpleTorrent()) parent.setParentDir(newPath); else destPathName = newPath; } public void setDestFileName (String newFileName) { if(orgFileName.equals(newFileName)) destFileName = null; else destFileName = newFileName; } public String getDestPathName() { if (destPathName != null) return destPathName; if (parent.torrent.isSimpleTorrent()) return parent.getParentDir(); return new File(parent.getDataDir(), orgFullName).getParent(); } public String getDestFileName() { return destFileName == null ? orgFileName : destFileName; } public File getDestFileFullName() { String path = getDestPathName(); String file = getDestFileName(); return new File(path,file); } public boolean okToDisable() { return /* lSize >= MIN_NODOWNLOAD_SIZE || */parent.okToDisableAll(); } public boolean isLinked() { return destFileName != null || destPathName != null; } } private String ensureTrailingSeparator(String sPath) { if (sPath == null || sPath.length() == 0 || sPath.endsWith(File.separator)) return sPath; return sPath + File.separator; } /** * * @return Null if user doesn't want to save silently, or if no path set */ private static String getSaveSilentlyDir() { boolean bUseDefault = COConfigurationManager.getBooleanParameter("Use default data dir"); if (!bUseDefault) return null; String sDefDir = ""; try { sDefDir = COConfigurationManager.getDirectoryParameter(PARAM_DEFSAVEPATH); } catch (IOException e) { return null; } return (sDefDir == "") ? null : sDefDir; } private final static class Partition { public Partition(File root) { this.root = root; } long bytesToConsume = 0; long freeSpace = 0; final File root; } private final static class FileStatsCacheItem { public FileStatsCacheItem(final File f) { exists = f.exists(); if (exists) freeSpace = FileUtil.getUsableSpace(f); else freeSpace = -1; } boolean exists; long freeSpace; } private long getCachedDirFreeSpace(File directory) { FileStatsCacheItem item = (FileStatsCacheItem) fileStatCache.get(directory); if (item == null) fileStatCache.put(directory, item = new FileStatsCacheItem(directory)); return item.freeSpace; } private boolean getCachedExistsStat(File directory) { FileStatsCacheItem item = (FileStatsCacheItem) fileStatCache.get(directory); if (item == null) fileStatCache.put(directory, item = new FileStatsCacheItem(directory)); return item.exists; } private final Map fileStatCache = new WeakHashMap(20); private final Map parentToRootCache = new WeakHashMap(20); private volatile boolean diskFreeInfoRefreshPending = false; private volatile boolean diskFreeInfoRefreshRunning = false; // @see com.aelitis.azureus.ui.swt.uiupdater.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { return "OpenTorrentWindow"; } // @see com.aelitis.azureus.ui.swt.uiupdater.UIUpdatable#updateUI() public void updateUI() { if (bClosed) { try { UIUpdaterSWT.getInstance().removeUpdater(this); } catch (Exception e) { Debug.out(e); } return; } if (diskFreeInfoRefreshPending && !diskFreeInfoRefreshRunning && FileUtil.getUsableSpaceSupported()) { diskFreeInfoRefreshRunning = true; diskFreeInfoRefreshPending = false; final HashSet FSroots = new HashSet(Arrays.asList(File.listRoots())); final HashMap partitions = new HashMap(); for (int i = 0; i < torrentList.size(); i++) { TorrentInfo tor = (TorrentInfo) torrentList.get(i); TorrentFileInfo[] files = tor.getFiles(); for (int j = 0; j < files.length; j++) { TorrentFileInfo file = files[j]; if (!file.bDownload) continue; // reduce each file to its partition root File root = file.getDestFileFullName().getAbsoluteFile(); Partition part = (Partition) partitions.get((File) parentToRootCache.get(root.getParentFile())); if (part == null) { File next; while (true) { root = root.getParentFile(); next = root.getParentFile(); if (next == null) break; // bubble up until we hit an existing directory if (!getCachedExistsStat(root) || !root.isDirectory()) continue; // check for mount points (different free space) or simple loops in the directory structure if (FSroots.contains(root) || root.equals(next) || getCachedDirFreeSpace(next) != getCachedDirFreeSpace(root)) break; } parentToRootCache.put( file.getDestFileFullName().getAbsoluteFile().getParentFile(), root); part = (Partition) partitions.get(root); if (part == null) { part = new Partition(root); part.freeSpace = getCachedDirFreeSpace(root); partitions.put(root, part); } } part.bytesToConsume += file.lSize; } } // clear child objects Control[] labels = diskspaceComp.getChildren(); for (int i = 0; i < labels.length; i++) labels[i].dispose(); // build labels Iterator it = partitions.values().iterator(); while (it.hasNext()) { Partition part = (Partition) it.next(); boolean filesTooBig = part.bytesToConsume > part.freeSpace; Label l; l = new Label(diskspaceComp, SWT.NONE); l.setForeground(filesTooBig ? Colors.colorError : null); l.setText(part.root.getPath()); l.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false)); l = new Label(diskspaceComp, SWT.NONE); l.setForeground(filesTooBig ? Colors.colorError : null); l.setText(MessageText.getString("OpenTorrentWindow.diskUsage", new String[] { DisplayFormatters.formatByteCountToKiBEtc(part.bytesToConsume), DisplayFormatters.formatByteCountToKiBEtc(part.freeSpace) })); l.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false)); } diskspaceComp.update(); diskspaceComp.getParent().getParent().getParent().layout(true, true); diskFreeInfoRefreshRunning = false; } } private void updateSize() { /* * determine info for selected torrents only */ long totalSize = 0; long checkedSize = 0; for (int i = 0; i < dataFiles.size(); i++) { TorrentFileInfo file = (TorrentFileInfo) dataFiles.get(i); totalSize += file.lSize; if (file.bDownload) { checkedSize += file.lSize; } } // build string and set label if (totalSize == 0) { dataFileTableLabel.setText(""); } else { dataFileTableLabel.setText(MessageText.getString( "OpenTorrentWindow.filesInfo", new String[] { DisplayFormatters.formatByteCountToKiBEtc(checkedSize), DisplayFormatters.formatByteCountToKiBEtc(totalSize) })); } dataFileTableLabel.update(); dataFileTableLabel.getParent().getParent().layout(true, true); diskFreeInfoRefreshPending = true; } /** * Convenience method for setting the enabled state of a control *

This method may be called from any thread

* @param control * @param enabledState */ private void enableControl(final Control control, final boolean enabledState) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (control != null && false == control.isDisposed()) { control.setEnabled(enabledState); } } }); } public static void main(String[] args) { AzureusCore core = AzureusCoreFactory.create(); core.start(); Display display = Display.getDefault(); Colors.getInstance(); invoke(null, core.getGlobalManager()); //OpenTorrentWindow window = new OpenTorrentWindow(null, null, true); while (stOpenTorrentWindow != null && !stOpenTorrentWindow.bClosed) { if (!display.readAndDispatch()) display.sleep(); } core.stop(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/updater/0000755000175000017500000000000011310377446021061 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/updater/snippets/0000755000175000017500000000000011310377636022727 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/updater/snippets/Main.java0000644000175000017500000000425510124624544024457 0ustar adrianadrian/* * File : Main.java * Created : 6 avr. 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.updater.snippets; import java.io.File; import java.net.InetAddress; import java.net.ServerSocket; import org.gudy.azureus2.core3.util.Debug; /** * @author Olivier Chalouhi * */ public class Main { private static String classToStart = "org.gudy.azureus2.ui.swt.updater.snippets.Started"; public static void main(String args[]) { try { ServerSocket server = new ServerSocket(6880, 50, InetAddress.getByName("127.0.0.1")); spawnStarted(); server.close(); } catch(Exception e) { Debug.printStackTrace( e ); } } public static void spawnStarted() throws Exception { String classPath = System.getProperty("java.class.path"); //$NON-NLS-1$ String userPath = System.getProperty("user.dir"); //$NON-NLS-1$ String javaPath = System.getProperty("java.home") + System.getProperty("file.separator") + "bin" + System.getProperty("file.separator"); String exec = "\"" + javaPath + "java\" -classpath \"" + classPath + "\" " + classToStart; Logger.log("Main is about to execute : " + exec); File userDir = new File(userPath); String[] env = {"user.dir=" + userPath}; Runtime.getRuntime().exec(exec); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/updater/snippets/Logger.java0000644000175000017500000000256010034650260025001 0ustar adrianadrian/* * File : Logger.java * Created : 6 avr. 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.updater.snippets; import java.io.File; import java.io.FileOutputStream; /** * @author Olivier Chalouhi * */ public class Logger { public static void log(String value) { FileOutputStream fos = null; try { String userPath = System.getProperty("user.dir") + System.getProperty("file.separator"); File logFile = new File(userPath + "snippet.log"); fos = new FileOutputStream(logFile,true); fos.write((value+"\n").getBytes()); fos.close(); } catch(Exception e) { //Do nothing } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/updater/snippets/Started.java0000644000175000017500000000322610034650260025170 0ustar adrianadrian/* * File : Started.java * Created : 6 avr. 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.updater.snippets; import java.net.InetAddress; import java.net.ServerSocket; /** * @author Olivier Chalouhi * */ public class Started { public static void main(String args[]) { //We wait untill the creating process has ended and released the // socket bind. boolean ok = false; try { while(!ok) { try{ ServerSocket server = new ServerSocket(6880, 50, InetAddress.getByName("127.0.0.1")); ok = true; server.close(); } catch(Exception e) { Logger.log("Exception while trying to bind on port 6880 : " + e); Thread.sleep(1000); } } } catch(Exception e) { Logger.log("Exception while running Started : " +e); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/TrackerChangerWindow.java0000644000175000017500000001054211154452066024333 0ustar adrianadrian/* * Created on 9 sept. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; /** * @author Olivier * */ public class TrackerChangerWindow { public TrackerChangerWindow(final Display display, final DownloadManager[] dms ) { final Shell shell = ShellFactory.createShell(display); shell.setText(MessageText.getString("TrackerChangerWindow.title")); Utils.setShellIcon(shell); GridLayout layout = new GridLayout(); shell.setLayout(layout); Label label = new Label(shell, SWT.NONE); Messages.setLanguageText(label, "TrackerChangerWindow.newtracker"); GridData gridData = new GridData(); gridData.widthHint = 200; label.setLayoutData(gridData); final Text url = new Text(shell, SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.widthHint = 300; url.setLayoutData(gridData); Utils.setTextLinkFromClipboard(shell, url, false); Composite panel = new Composite(shell, SWT.NULL); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); gridData = new GridData(); gridData.horizontalSpan = 2; panel.setLayoutData(gridData); Button ok = new Button(panel, SWT.PUSH); ok.setText(MessageText.getString("Button.ok")); gridData = new GridData(); gridData.widthHint = 70; ok.setLayoutData(gridData); shell.setDefaultButton(ok); ok.addListener(SWT.Selection, new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event event) { try { for ( DownloadManager dm: dms ){ TOTorrent torrent = dm.getTorrent(); if ( torrent != null ){ TorrentUtils.announceGroupsInsertFirst( torrent, url.getText()); TorrentUtils.writeToFile( torrent ); TRTrackerAnnouncer announcer = dm.getTrackerClient(); if ( announcer != null ){ announcer.resetTrackerUrl(false); } } } shell.dispose(); } catch (Exception e) { Debug.printStackTrace( e ); } } }); Button cancel = new Button(panel, SWT.PUSH); cancel.setText(MessageText.getString("Button.cancel")); gridData = new GridData(); gridData.widthHint = 70; cancel.setLayoutData(gridData); cancel.addListener(SWT.Selection, new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event event) { shell.dispose(); } }); shell.pack(); Utils.createURLDropTarget(shell, url); shell.open(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/TrayWindow.java0000644000175000017500000002416411171750562022375 0ustar adrianadrian/* * Created on 8 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerStats; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerListener; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.mainwindow.ListenerNeedingCoreRunning; import org.gudy.azureus2.ui.swt.mainwindow.MainWindow; import org.gudy.azureus2.ui.swt.mainwindow.MenuFactory; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import org.gudy.azureus2.ui.systray.SystemTraySWT; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * Download Basket. For System Tray, see {@link SystemTraySWT} * * @author Olivier * */ public class TrayWindow implements GlobalManagerListener, UIUpdatable { private final static String ID = "DownloadBasket/TrayWindow"; GlobalManager globalManager; List managers; protected AEMonitor managers_mon = new AEMonitor(ID); MainWindow main; Display display; Shell minimized; Label label; private Menu menu; private Rectangle screen; private int xPressed; private int yPressed; private boolean moving; public TrayWindow(MainWindow _main) { this.managers = new ArrayList(); this.main = _main; UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT(); Shell mainShell = uif == null ? Utils.findAnyShell() : uif.getMainShell(); this.display = mainShell.getDisplay(); minimized = ShellFactory.createShell(mainShell, SWT.ON_TOP); minimized.setText("Vuze"); //$NON-NLS-1$ label = new Label(minimized, SWT.NULL); ImageLoader.getInstance().setLabelImage(label, "tray"); final Rectangle bounds = label.getImage().getBounds(); label.setSize(bounds.width, bounds.height); minimized.setSize(bounds.width + 2, bounds.height + 2); screen = display.getClientArea(); //NICO handle macosx and multiple monitors if (!Constants.isOSX) { minimized.setLocation(screen.x + screen.width - bounds.width - 2, screen.y + screen.height - bounds.height - 2); } else { minimized.setLocation(20, 20); } minimized.layout(); minimized.setVisible(false); //minimized.open(); MouseListener mListener = new MouseAdapter() { public void mouseDown(MouseEvent e) { xPressed = e.x; yPressed = e.y; moving = true; //System.out.println("Position : " + xPressed + " , " + yPressed); } public void mouseUp(MouseEvent e) { moving = false; } public void mouseDoubleClick(MouseEvent e) { restore(); } }; MouseMoveListener mMoveListener = new MouseMoveListener() { public void mouseMove(MouseEvent e) { if (moving) { int dX = xPressed - e.x; int dY = yPressed - e.y; Point currentLoc = minimized.getLocation(); int x = currentLoc.x - dX; int y = currentLoc.y - dY; if (x < 10) x = 0; if (x > screen.width - (bounds.width + 12)) x = screen.width - (bounds.width + 2); if (y < 10) y = 0; if (y > screen.height - (bounds.height + 12)) y = screen.height - (bounds.height + 2); minimized.setLocation(x, y); } } }; label.addMouseListener(mListener); label.addMouseMoveListener(mMoveListener); menu = new Menu(minimized, SWT.CASCADE); label.setMenu(menu); MenuItem file_show = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(file_show, "TrayWindow.menu.show"); //$NON-NLS-1$ menu.setDefaultItem(file_show); file_show.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { restore(); } }); new MenuItem(menu, SWT.SEPARATOR); MenuFactory.addCloseDownloadBarsToMenu(menu); new MenuItem(menu, SWT.SEPARATOR); MenuItem file_startalldownloads = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(file_startalldownloads, "TrayWindow.menu.startalldownloads"); //$NON-NLS-1$ file_startalldownloads.addListener(SWT.Selection, new ListenerNeedingCoreRunning() { public void handleEvent(AzureusCore core, Event e) { globalManager.startAllDownloads(); } }); MenuItem file_stopalldownloads = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(file_stopalldownloads, "TrayWindow.menu.stopalldownloads"); //$NON-NLS-1$ file_stopalldownloads.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { ManagerUtils.asyncStopAll(); } }); new MenuItem(menu, SWT.SEPARATOR); MenuItem file_close = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(file_close, "TrayWindow.menu.close"); file_close.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { COConfigurationManager.setParameter("Show Download Basket", false); } }); MenuItem file_exit = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(file_exit, "TrayWindow.menu.exit"); //$NON-NLS-1$ file_exit.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { main.dispose(false,false); } }); Utils.createTorrentDropTarget(minimized, false); try { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { globalManager = core.getGlobalManager(); globalManager.addListener(TrayWindow.this); } }); } catch (Exception e) { Debug.out(e); } } public void setVisible(boolean visible) { if(visible || !COConfigurationManager.getBooleanParameter("Show Download Basket")) { minimized.setVisible(visible); if (!visible) moving = false; } try { if (visible) { UIFunctionsManager.getUIFunctions().getUIUpdater().addUpdater(this); } else { UIFunctionsManager.getUIFunctions().getUIUpdater().removeUpdater(this); } } catch (Exception e) { Debug.out(e); } } public void dispose() { minimized.dispose(); } public void restore() { if(!COConfigurationManager.getBooleanParameter("Show Download Basket")) minimized.setVisible(false); UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (functionsSWT != null) { functionsSWT.bringToFront(); } moving = false; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI() public void updateUI() { if (minimized.isDisposed() || !minimized.isVisible()) return; StringBuffer toolTip = new StringBuffer(); String separator = ""; //$NON-NLS-1$ try{ managers_mon.enter(); for (int i = 0; i < managers.size(); i++) { DownloadManager manager = (DownloadManager) managers.get(i); DownloadManagerStats stats = manager.getStats(); String name = manager.getDisplayName(); String completed = DisplayFormatters.formatPercentFromThousands(stats.getCompleted()); toolTip.append(separator); toolTip.append(name); toolTip.append(" -- C: "); toolTip.append(completed); toolTip.append(", D : "); toolTip.append(DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec( stats.getDataReceiveRate(), stats.getProtocolReceiveRate())); toolTip.append(", U : "); toolTip.append(DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec( stats.getDataSendRate(), stats.getProtocolSendRate())); separator = "\n"; //$NON-NLS-1$ } }finally{ managers_mon.exit(); } //label.setToolTipText(toolTip.toString()); //minimized.moveAbove(null); } public void downloadManagerAdded(DownloadManager created) { try{ managers_mon.enter(); managers.add(created); }finally{ managers_mon.exit(); } } public void downloadManagerRemoved(DownloadManager removed) { try{ managers_mon.enter(); managers.remove(removed); }finally{ managers_mon.exit(); } } // globalmanagerlistener public void destroyed() { } public void destroyInitiated() { } public void seedingStatusChanged( boolean seeding_only_mode, boolean b ){ } public void updateLanguage() { MenuFactory.updateMenuText(menu); } /** * @param moving */ public void setMoving(boolean moving) { this.moving = moving; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { return ID; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/Tab.java0000644000175000017500000006260211120043556020763 0ustar adrianadrian/* * Created on 29 juin 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import java.util.HashMap; import java.util.Iterator; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.mainwindow.MainWindow; import org.gudy.azureus2.ui.swt.plugins.UISWTPluginView; import org.gudy.azureus2.ui.swt.plugins.UISWTView; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl; import org.gudy.azureus2.ui.swt.views.*; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.utils.ColorCache; import org.gudy.azureus2.plugins.PluginView; import org.gudy.azureus2.plugins.ui.UIPluginView; /** * @author Olivier * @author James Yeh Added Add/Remove event listeners */ public class Tab implements ParameterListener, UIUpdatable { private static final LogIDs LOGID = LogIDs.GUI; private static final String ID = "TabSet"; private HashMap tabs; private AEMonitor class_mon = new AEMonitor(ID); private boolean useCustomTab; private Composite folder; private boolean eventCloseAllowed = true; private Item selectedItem = null; private MainWindow mainwindow; private Listener activateListener; /** * */ public Tab(MainWindow _mainWindow) { mainwindow = _mainWindow; tabs = new HashMap(); COConfigurationManager.addParameterListener("GUI_SWT_bFancyTab", this); activateListener = new Listener() { public void handleEvent(Event event) { IView view = null; Composite parent = (Composite) event.widget; IView oldView = getView(selectedItem); if (oldView instanceof IViewExtension) { ((IViewExtension) oldView).viewDeactivated(); } while (parent != null && !parent.isDisposed() && view == null) { if (parent instanceof CTabFolder) { CTabFolder folder = (CTabFolder) parent; selectedItem = folder.getSelection(); view = getView(selectedItem); } else if (parent instanceof TabFolder) { TabFolder folder = (TabFolder) parent; TabItem[] selection = folder.getSelection(); if (selection.length > 0) { selectedItem = selection[0]; view = getView(selectedItem); } } if (view == null) parent = parent.getParent(); } if (view != null) { if (view instanceof IViewExtension) { ((IViewExtension) view).viewActivated(); } view.refresh(); } } }; mainwindow.getUIFunctions().getUIUpdater().addUpdater(this); } public Composite createFolderWidget(Composite parent) { Display display = parent.getDisplay(); if (tabs == null) { tabs = new HashMap(); } if (folder != null && !folder.isDisposed()) { return folder; } useCustomTab = COConfigurationManager.getBooleanParameter("useCustomTab"); if (!useCustomTab) { folder = new TabFolder(parent, SWT.V_SCROLL); } else { folder = new CTabFolder(parent, SWT.CLOSE | SWT.BORDER); float[] hsb = folder.getBackground().getRGB().getHSB(); hsb[2] *= (Constants.isOSX) ? 0.9 : 0.97; folder.setBackground(ColorCache.getColor(parent.getDisplay(), hsb)); hsb = folder.getForeground().getRGB().getHSB(); hsb[2] *= (Constants.isOSX) ? 1.1 : 0.03; folder.setForeground(ColorCache.getColor(parent.getDisplay(), hsb)); //((CTabFolder)folder).setBorderVisible(false); ((CTabFolder) folder).addCTabFolder2Listener(new CTabFolder2Adapter() { public void close(CTabFolderEvent event) { if (!closed((Item) event.item)) { event.doit = false; } } }); // I think this closes the tab on middle click folder.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent arg0) { CTabItem tabItem = ((CTabFolder) folder).getItem(new Point(arg0.x, arg0.y)); if (arg0.button == 2) { if (eventCloseAllowed) { Rectangle rectangle = ((CTabItem) tabItem).getBounds(); if (rectangle.contains(arg0.x, arg0.y)) { eventCloseAllowed = false; selectedItem = null; //folder.removeMouseListener(this); closed(tabItem); } } } else { selectedItem = ((CTabFolder) folder).getSelection(); } } public void mouseUp(MouseEvent arg0) { eventCloseAllowed = true; if (selectedItem != null) { ((CTabFolder) folder).setSelection((CTabItem) selectedItem); ensureVisibilities(); } } }); } folder.getDisplay().addFilter(SWT.KeyDown, new Listener() { public void handleEvent(Event event) { // Another window has control, skip filter Control focus_control = folder.getDisplay().getFocusControl(); if (focus_control != null && focus_control.getShell() != folder.getShell()) { return; } int key = event.character; if ((event.stateMask & SWT.MOD1) != 0 && event.character <= 26 && event.character > 0) key += 'a' - 1; // ESC or CTRL+F4 closes current Tab if (key == SWT.ESC || (event.keyCode == SWT.F4 && event.stateMask == SWT.CTRL)) { closeCurrent(); event.doit = false; } else if (event.keyCode == SWT.F6 || (event.character == SWT.TAB && (event.stateMask & SWT.CTRL) != 0)) { // F6 or Ctrl-Tab selects next Tab // On Windows the tab key will not reach this filter, as it is // processed by the traversal TRAVERSE_TAB_NEXT. It's unknown // what other OSes do, so the code is here in case we get TAB if ((event.stateMask & SWT.SHIFT) == 0) { event.doit = false; selectNextTab(true); // Shift+F6 or Ctrl+Shift+Tab selects previous Tab } else if (event.stateMask == SWT.SHIFT) { selectNextTab(false); event.doit = false; } } } }); SelectionAdapter selectionAdapter = new SelectionAdapter() { public void widgetSelected(final SelectionEvent event) { if (folder == null || folder.isDisposed()) { return; } if (useCustomTab && !folder.isDisposed()) { ensureVisibilities(); } mainwindow.getUIFunctions().refreshIconBar(); mainwindow.getUIFunctions().refreshTorrentMenu(); } }; if (!useCustomTab) { ((TabFolder) folder).addSelectionListener(selectionAdapter); } else { try { ((CTabFolder) folder).setMinimumCharacters(75); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "Can't set MIN_TAB_WIDTH", e)); } //try { /// TabFolder2ListenerAdder.add((CTabFolder)folder); //} catch (NoClassDefFoundError e) { ((CTabFolder) folder).addCTabFolderListener(new CTabFolderAdapter() { public void itemClosed(CTabFolderEvent event) { if (!event.doit) { return; } closed((CTabItem) event.item); event.doit = true; ((CTabItem) event.item).dispose(); } }); //} ((CTabFolder) folder).addSelectionListener(selectionAdapter); try { ((CTabFolder) folder).setSelectionBackground(new Color[] { display.getSystemColor(SWT.COLOR_LIST_BACKGROUND), display.getSystemColor(SWT.COLOR_LIST_BACKGROUND), display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND) }, new int[] { 10, 90 }, true); } catch (NoSuchMethodError e) { /** < SWT 3.0M8 **/ ((CTabFolder) folder).setSelectionBackground(new Color[] { display.getSystemColor(SWT.COLOR_LIST_BACKGROUND) }, new int[0]); } ((CTabFolder) folder).setSelectionForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); try { /* Pre 3.0M8 doesn't have Simple-mode (it's always simple mode) in 3.0M9, it was called setSimpleTab(boolean) in 3.0RC1, it's called setSimple(boolean) Prepare for the future, and use setSimple() */ ((CTabFolder) folder).setSimple(!COConfigurationManager.getBooleanParameter("GUI_SWT_bFancyTab")); } catch (NoSuchMethodError e) { /** < SWT 3.0RC1 **/ } } return folder; } /** * * * @since 4.0.0.5 */ protected void ensureVisibilities() { if (!(folder instanceof CTabFolder)) { return; } CTabItem[] items = ((CTabFolder) folder).getItems(); CTabItem item = ((CTabFolder) folder).getSelection(); for (int i = 0; i < items.length; i++) { CTabItem tabItem = items[i]; if (tabItem == null || tabItem.isDisposed()) { continue; } if (tabItem == item) { try { ((CTabFolder) folder).setSelection(tabItem); Control control = getView(tabItem).getComposite(); if (control != null) { control.setVisible(true); control.setFocus(); } } catch (Throwable e) { Debug.printStackTrace(e); //Do nothing } } else { try { Control control = getView(tabItem).getComposite(); if (control != null) { control.setVisible(false); } } catch (Throwable e) { Debug.printStackTrace(e); //Do nothing } } } } public Item createTabItem(final IView _view, boolean bFocus) { if (folder.isDisposed()) { return null; } Item tabItem; if (folder instanceof CTabFolder) { CTabFolder tabFolder = (CTabFolder) folder; tabItem = new CTabItem(tabFolder, SWT.NULL, (_view instanceof MyTorrentsSuperView) ? 0 : tabFolder.getItemCount()); } else { TabFolder tabFolder = (TabFolder) folder; tabItem = new TabItem(tabFolder, SWT.NULL, (_view instanceof MyTorrentsSuperView) ? 0 : tabFolder.getItemCount()); } tabs.put(tabItem, _view); try { // Always create a composite around the IView, because a lot of them // assume that their parent is of GridLayout layout. final Composite tabArea = new Composite(folder, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; tabArea.setLayout(layout); _view.initialize(tabArea); tabItem.setText(escapeAccelerators(_view.getShortTitle())); Composite viewComposite = _view.getComposite(); if (viewComposite != null && !viewComposite.isDisposed()) { viewComposite.addListener(SWT.Activate, activateListener); // make sure the view's layout data is of GridLayoutData if ((tabArea.getLayout() instanceof GridLayout) && !(viewComposite.getLayoutData() instanceof GridData)) { viewComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); } if (viewComposite != tabArea) { viewComposite.addDisposeListener(new DisposeListener() { boolean alreadyHere = false; public void widgetDisposed(DisposeEvent e) { if (alreadyHere) { return; } alreadyHere = true; Item tab = getTab(_view); if (tab != null) { closed(tab); } } }); } } if (folder instanceof CTabFolder) { ((CTabItem) tabItem).setControl(tabArea); // Disabled for SWT 3.2RC5.. CTabItem tooltip doesn't always disappear // ((CTabItem) tabItem).setToolTipText(view.getFullTitle()); if (bFocus) { ((CTabFolder) folder).setSelection((CTabItem) tabItem); ensureVisibilities(); } } else { ((TabItem) tabItem).setControl(tabArea); ((TabItem) tabItem).setToolTipText(_view.getFullTitle()); TabItem items[] = { (TabItem) tabItem }; if (bFocus) { ((TabFolder) folder).setSelection(items); } } } catch (Exception e) { tabs.remove(tabItem); Debug.printStackTrace(e); } if (bFocus) { UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uif != null) { uif.refreshIconBar(); uif.refreshTorrentMenu(); } selectedItem = tabItem; } return tabItem; } public IView getView(Item item) { return (IView) tabs.get(item); } public Item getTab( IView view ) { try{ class_mon.enter(); Iterator iter = tabs.keySet().iterator(); while( iter.hasNext()){ Item item = (Item) iter.next(); IView this_view = (IView) tabs.get(item); if ( this_view == view ){ return( item ); } } return( null ); }finally{ class_mon.exit(); } } public Item[] getAllTabs() { try { class_mon.enter(); Item[] tabItems = new Item[tabs.size()]; if (tabItems.length > 0) { tabItems = (Item[]) tabs.keySet().toArray(tabItems); } return tabItems; } finally { class_mon.exit(); } } public IView[] getAllViews() { try { class_mon.enter(); IView[] views = new IView[tabs.size()]; if (views.length > 0) { views = (IView[])tabs.values().toArray(views); } return views; } finally { class_mon.exit(); } } public void refresh() { try{ class_mon.enter(); Iterator iter = tabs.keySet().iterator(); while (iter.hasNext()) { //TabItem item = (TabItem) iter.next(); //CTabItem item = (CTabItem) iter.next(); Item item = (Item) iter.next(); IView view = (IView) tabs.get(item); try { if (item.isDisposed()) continue; String lastTitle = item.getText(); String newTitle = view.getShortTitle(); if (lastTitle == null || !lastTitle.equals(newTitle)) { item.setText(escapeAccelerators(newTitle)); } if (item instanceof CTabItem) { // Disabled for SWT 3.2RC5.. CTabItem tooltip doesn't always disappear // String lastToolTip = ((CTabItem) item).getToolTipText(); // String newToolTip = view.getFullTitle(); // if (lastToolTip == null || !lastToolTip.equals(newToolTip)) { // ((CTabItem) item).setToolTipText(newToolTip); // } } else if (item instanceof TabItem) { String lastToolTip = ((TabItem) item).getToolTipText(); String newToolTip = view.getFullTitle(); if (lastToolTip == null || !lastToolTip.equals(newToolTip)) { ((TabItem) item).setToolTipText(newToolTip); } } } catch (Exception e){ Debug.printStackTrace(e); } } }finally{ class_mon.exit(); } } public void updateLanguage() { IView[] views; try{ class_mon.enter(); views = (IView[]) tabs.values().toArray(new IView[tabs.size()]); }finally{ class_mon.exit(); } for (int i = 0; i < views.length; i++) { IView view = views[i]; try { view.updateLanguage(); view.refresh(); } catch (Exception e) { Debug.printStackTrace(e); } } } public void closeAllTabs() { Item[] tab_items; try{ class_mon.enter(); tab_items = (Item[]) tabs.keySet().toArray(new Item[tabs.size()]); }finally{ class_mon.exit(); } for (int i = 0; i < tab_items.length; i++) { closed(tab_items[i], true); } } public boolean hasDetails() { boolean hasDetails = false; try { class_mon.enter(); Iterator iter = tabs.values().iterator(); while (iter.hasNext()) { IView view = (IView) iter.next(); if(view instanceof ManagerView) { hasDetails = true; break; }else if ( view instanceof UIPluginView && ((UIPluginView)view).getViewID().equals( "DMView" )){ hasDetails = true; break; } } } finally { class_mon.exit(); } return hasDetails; } public void closeAllDetails() { Item[] tab_items; try{ class_mon.enter(); tab_items = (Item[]) tabs.keySet().toArray(new Item[tabs.size()]); }finally{ class_mon.exit(); } for (int i = 0; i < tab_items.length; i++) { IView view = (IView) tabs.get(tab_items[i]); if (view instanceof ManagerView) { closed(tab_items[i]); }else if ( view instanceof UIPluginView && ((UIPluginView)view).getViewID().equals( "DMView" )){ closed(tab_items[i]); } } } public void closeCurrent() { if (folder == null || folder.isDisposed()) return; if(folder instanceof TabFolder) { TabItem[] items = ((TabFolder)folder).getSelection(); if(items.length == 1) { closed(items[0]); } } else { closed(((CTabFolder)folder).getSelection()); } } /** * @param selectNext if true, the next tab is selected, else the previous * * @author Rene Leonhardt */ public void selectNextTab(boolean selectNext) { if (folder == null || folder.isDisposed()) return; final int nextOrPrevious = selectNext ? 1 : -1; if(folder instanceof TabFolder) { TabFolder tabFolder = (TabFolder)folder; int index = tabFolder.getSelectionIndex() + nextOrPrevious; if(index == 0 && selectNext || index == -2 || tabFolder.getItemCount() < 2) return; if(index == tabFolder.getItemCount()) index = 0; else if(index < 0) index = tabFolder.getItemCount() - 1; tabFolder.setSelection(index); } else { CTabFolder tabFolder = (CTabFolder)folder; int index = tabFolder.getSelectionIndex() + nextOrPrevious; if(index == 0 && selectNext || index == -2 || tabFolder.getItemCount() < 2) return; if(index == tabFolder.getItemCount()) index = 0; else if(index < 0) index = tabFolder.getItemCount() - 1; tabFolder.setSelection(index); ensureVisibilities(); } } public boolean closed(Item item) { return closed(item, false); } public boolean closed(Item item, boolean bForceClose) { if (item == null) { return true; } IView view = (IView) tabs.get(item); if (!bForceClose && view instanceof UISWTViewImpl) { if (!((UISWTViewImpl)view).requestClose()) { return false; } } try{ class_mon.enter(); view = (IView) tabs.remove(item); }finally{ class_mon.exit(); } if (view != null) { try { if(view instanceof PluginView) { mainwindow.removeActivePluginView(((PluginView)view).getPluginViewName()); } if(view instanceof UISWTPluginView) { mainwindow.removeActivePluginView(((UISWTPluginView)view).getPluginViewName()); } if(view instanceof UISWTView) mainwindow.removeActivePluginView(((UISWTView)view).getViewID()); view.delete(); } catch (Exception e) { Debug.printStackTrace( e ); } if (view instanceof MyTorrentsSuperView) { //TODO : There is a problem here on OSX when using Normal TABS /* org.eclipse.swt.SWTException: Widget is disposed at org.eclipse.swt.SWT.error(SWT.java:2691) at org.eclipse.swt.SWT.error(SWT.java:2616) at org.eclipse.swt.SWT.error(SWT.java:2587) at org.eclipse.swt.widgets.Widget.error(Widget.java:546) at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:296) at org.eclipse.swt.widgets.Control.setVisible(Control.java:2573) at org.eclipse.swt.widgets.TabItem.releaseChild(TabItem.java:180) at org.eclipse.swt.widgets.Widget.dispose(Widget.java:480) at org.gudy.azureus2.ui.swt.Tab.closed(Tab.java:322) */ //Tried to add a if(! item.isDisposed()) but it's not fixing it //Need to investigate... item.dispose(); return true; } if (view instanceof MyTrackerView) { item.dispose(); return true; } if (view instanceof MySharesView) { item.dispose(); return true; } } try { /*Control control; if(item instanceof CTabItem) { control = ((CTabItem)item).getControl(); } else { control = ((TabItem)item).getControl(); } if (control != null && !control.isDisposed()) control.dispose(); */ item.dispose(); } catch (Exception e) { Debug.printStackTrace( e ); } return true; } public void setFocus(Item item) { if (item == null || item.isDisposed()) { return; } if (folder != null && !folder.isDisposed()) { if (useCustomTab) { ((CTabFolder) folder).setSelection((CTabItem) item); ensureVisibilities(); } else { TabItem items[] = { (TabItem) item }; ((TabFolder) folder).setSelection(items); } } } public void dispose(Item tabItem) { IView localView = null; try{ class_mon.enter(); localView = (IView) tabs.get(tabItem); if (localView instanceof UISWTViewImpl) { if (!((UISWTViewImpl) localView).requestClose()) return; } tabs.remove(tabItem); }finally{ class_mon.exit(); } try { if (localView != null) { if(localView instanceof PluginView) { mainwindow.removeActivePluginView(((PluginView)localView).getPluginViewName()); } if(localView instanceof UISWTPluginView) { mainwindow.removeActivePluginView(((UISWTPluginView)localView).getPluginViewName()); } localView.delete(); } tabItem.dispose(); } catch (Exception e) {} } protected String escapeAccelerators( String str ) { if ( str == null ){ return( str ); } return( str.replaceAll( "&", "&&" )); } public void generateDiagnostics(IndentWriter writer) { Object[] views = tabs.values().toArray(); for (int i = 0; i < views.length; i++) { IView view = (IView) views[i]; if (view != null) { writer.println(view.getFullTitle()); try { writer.indent(); view.generateDiagnostics(writer); } catch (Exception e) { } finally { writer.exdent(); } } } } /** * * * @since 3.1.1.1 */ public void update() { if (folder != null) { if (useCustomTab) { ((CTabFolder) folder).update(); } else { ((TabFolder) folder).update(); } } } /** * @param viewID * * @since 3.1.1.1 */ public void closePluginViews(String viewID) { Item[] items; if (folder instanceof CTabFolder) items = ((CTabFolder) folder).getItems(); else if (folder instanceof TabFolder) items = ((TabFolder) folder).getItems(); else return; for (int i = 0; i < items.length; i++) { IView view = getView(items[i]); if (view instanceof UISWTViewImpl) { String sID = ((UISWTViewImpl) view).getViewID(); if (sID != null && sID.equals(viewID)) { try { Item tab = getTab(view); if (tab != null) { closed(tab); } } catch (Exception e) { Debug.printStackTrace(e); } } } } // for } // @see org.gudy.azureus2.core3.config.ParameterListener#parameterChanged(java.lang.String) public void parameterChanged(String parameterName) { if (parameterName.equals("GUI_SWT_bFancyTab") && folder instanceof CTabFolder && folder != null && !folder.isDisposed()) { try { ((CTabFolder) folder).setSimple(!COConfigurationManager.getBooleanParameter("GUI_SWT_bFancyTab")); } catch (NoSuchMethodError e) { /** < SWT 3.0RC1 **/ } } } /** * @return * * @since 3.1.1.1 */ public IView getCurrentView() { try { if (!useCustomTab) { TabItem[] selection = ((TabFolder) folder).getSelection(); if (selection.length > 0) { return getView(selection[0]); } return null; } return getView(((CTabFolder) folder).getSelection()); } catch (Exception e) { return null; } } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { IView currentView = getCurrentView(); if (currentView != null) { return ID + "-" + currentView.getFullTitle(); } return ID; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI() public void updateUI() { if (folder == null || folder.isDisposed()) { return; } IView currentView = getCurrentView(); if (currentView != null) { try { currentView.refresh(); } catch (Exception e) { Debug.out(e); } } refresh(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/UISwitcherListener.java0000644000175000017500000000204310670135014024002 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; /** * @author TuxPaper * @created Sep 6, 2007 * */ public interface UISwitcherListener { public void uiSwitched(String ui); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/0000755000175000017500000000000011310377636021077 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/UISWTParameterContext.java0000644000175000017500000000345611020135364026057 0ustar adrianadrian/* * Created on 25 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.plugins; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.plugins.ui.config.UIParameterContext; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; /** * This is to be used in conjunction with the * {@link BasicPluginConfigModel#addUIParameter2(UIParameterContext, String) addUIParameter2} * method - any plugin that wants to add a SWT object directly to a configuration * section should create a parameter with an object that implements this interface. * * @since 3.0.5.3 */ public interface UISWTParameterContext extends UIParameterContext { /** * This method is invoked when the config section is going to be displayed * in a SWT user interface. * * @param c The parent composite object which will contain the SWT object. */ public void create(Composite c); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/UISWTViewEvent.java0000644000175000017500000000736510475536724024533 0ustar adrianadrian/* * File : UISWTViewEvent.java * Created : Oct 14, 2005 * By : TuxPaper * * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.plugins; /** * A UI SWT View Event triggered by the UISWTViewEventListener * * @see org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener * @see org.gudy.azureus2.ui.swt.plugins.UISWTInstance#addView(String, String, UISWTViewEventListener) * * @author TuxPaper */ public interface UISWTViewEvent { /** * Triggered before view is initialize in order to allow any set up before * initialization *

* This is the only time that setting {@link UISWTView#setControlType(int)} * has any effect. *

* return true from {@link UISWTViewEventListener#eventOccurred(UISWTViewEvent)} * if creation was successfull. If you want only one instance of your view, * or if there's any reason you can't create, return false, and an existing * view will be used, if one is present. * * @since 2.3.0.6 */ public static final int TYPE_CREATE = 0; /** * Triggered when the datasource related to this view change. *

* Usually called after TYPE_CREATE, but before TYPE_INITIALIZE *

* getData() will return an Object[] array, or null * * @since 2.3.0.6 */ public static final int TYPE_DATASOURCE_CHANGED = 1; /** * Initialize your view. *

* getData() will return a SWT Composite or AWT Container for you to place * object in. * * @since 2.3.0.6 */ public static final int TYPE_INITIALIZE = 2; /** * Focus Gained * * @since 2.3.0.6 */ public static final int TYPE_FOCUSGAINED = 3; /** * Focus Lost *

* TYPE_FOCUSLOST may not be called before TYPE_DESTROY * * @since 2.3.0.6 */ public static final int TYPE_FOCUSLOST = 4; /** Triggered on user-specified intervals. Plugins should update any * live information at this time. *

* Caller is the GUI thread * * @since 2.3.0.6 */ public static final int TYPE_REFRESH = 5; /** Language has changed. Plugins should update their text to the new * language. To determine the new language, use Locale.getDefault() * * @since 2.3.0.6 */ public static final int TYPE_LANGUAGEUPDATE = 6; /** * Triggered when the parent view is about to be destroyed *

* TYPE_FOCUSLOST may not be called before TYPE_DESTROY * * @since 2.3.0.6 */ public static final int TYPE_DESTROY = 7; /** * Triggered when the parent view is about to be closed *

* Return false to abort close * * @since 2.5.0.1 */ public static final int TYPE_CLOSE = 8; /** * Get the type. * * @return The TYPE_* constant for this event * * @since 2.3.0.6 */ public int getType(); /** * Get the data * * @return Any data for this event * * @since 2.3.0.6 */ public Object getData(); /** * Get the View * * @return Information and control over the view * * @since 2.3.0.6 */ public UISWTView getView(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/UISWTPluginView.java0000644000175000017500000000256410324160660024665 0ustar adrianadrian/* * File : PluginView.java * Created : 2 nov. 2003 20:58:14 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.plugins; import org.gudy.azureus2.ui.swt.views.AbstractIView; /** * This Class must be extended by Plugin willing to have their own view in Azureus * @author Olivier * * @deprecated Use {@link org.gudy.azureus2.ui.swt.plugins.UISWTInstance#addView(String, String, UISWTViewEventListener)} */ public abstract class UISWTPluginView extends AbstractIView { /** * @return The name of the Plugin, as seen in the View > Plugins menu * * @since 2.0.4.0 */ public abstract String getPluginViewName(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/UISWTGraphic.java0000644000175000017500000000310310373051022024132 0ustar adrianadrian/* * Created on 2004/May/23 * Created by TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.plugins; import org.gudy.azureus2.plugins.ui.Graphic; import org.eclipse.swt.graphics.Image; /** An SWT image to be used in Azureus * * @see UISWTInstance#createGraphic */ public interface UISWTGraphic extends Graphic { /** Retrieve the Image object * * @return image that is stored in this object */ public Image getImage(); /** Sets the image stored in this object to the supplied parameter. * * @param img new image to be stored in this object * @return true - Image Set
* false - Image already set to supplied parameter */ public boolean setImage(Image img); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/UISWTStatusEntry.java0000644000175000017500000000663011021645772025106 0ustar adrianadrian/** * Created on 03-Feb-2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.plugins; import org.gudy.azureus2.plugins.ui.menus.MenuContext; import org.gudy.azureus2.plugins.ui.menus.MenuManager; import org.eclipse.swt.graphics.Image; /** * This interface represents a status entry indicator in the status bar. Examples * of such indicators are the Share Ratio indicator and the DHT Status * indicator. Plugins can create their own indicators via {@link UISWTInstance#createStatusEntry()}. *

* Note: When a status entry is first created, it is set to be invisible, with no status * text or tool tip text and no image to be associated with it. Once you set some content, you * must call setVisible(true) for it to become visible. * * @see UISWTInstance#createStatusEntry() * @author amc1 * @since 3.0.0.8 */ public interface UISWTStatusEntry { public static final int IMAGE_LED_GREY = 0; public static final int IMAGE_LED_RED = 1; public static final int IMAGE_LED_YELLOW = 2; public static final int IMAGE_LED_GREEN = 3; /** * Toggles the visibility of the entry in the status bar. */ public void setVisible(boolean visible); /** * Sets the text to display in the status bar. If you want to prevent any text * being displayed, pass null as a parameter. */ public void setText(String text); /** * Sets the tooltip text to associate with the status bar. If you want to remove * any tooltip text, pass null as a parameter. */ public void setTooltipText(String text); /** * Sets a listener to be informed when the status entry has been clicked on. */ public void setListener(UISWTStatusEntryListener listener); /** * Indicates whether an image should be displayed or not. */ public void setImageEnabled(boolean enabled); /** * Sets the image to display - the value here must be one of the IMAGE_ * values defined above. You must call {@link #setImageEnabled(boolean)} to enable * images to be displayed for this status entry. */ public void setImage(int image_id); /** * Sets the image to display. You must call {@link #setImageEnabled(boolean)} to enable * images to be displayed for this status entry. */ public void setImage(Image image); /** * Destroys the status entry. */ public void destroy(); /** * Returns a menu context object to allow you to add menu items to the status entry. * * @see MenuManager#addMenuItem(MenuContext, String) * @since 3.0.5.3 */ public MenuContext getMenuContext(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/UISWTInputReceiver.java0000644000175000017500000000434611020335274025357 0ustar adrianadrian/* * Created on 11-Nov-2006 * Created by Allan Crooks * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.plugins; import org.gudy.azureus2.plugins.ui.UIInputReceiver; /** * SWT-specific version of {@link UIInputReciever}, providing some additional * methods to customise the appearance of the input receiver. */ public interface UISWTInputReceiver extends UIInputReceiver { /** * Indicates how wide you want the text entry window to be. * @param width */ public void setWidthHint(int width); /** * Indicates how many lines by default to show the user to enter input. * * @param line_count */ public void setLineHeight(int line_count); /** * Indicates whether you want the preentered text to be selected * (highlighted) or not. Default is true. * * @param select */ public void selectPreenteredText(boolean select); /** * Changes the entry box to be a combo box, where the values passed * are selectable. * * @param choices The list of options to be made available. * @param default_choice Index of the option to present by default. * @param allow_edit true if you still want to allow the user to enter * their own text, false if you want to restrict them to the choices * here. * @since 3.0.5.3 */ public void setSelectableItems(String[] choices, int default_choice, boolean allow_edit); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/UISWTAWTPluginView.java0000644000175000017500000000307010373051022025225 0ustar adrianadrian/* * Created on 06-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.plugins; import java.awt.Component; /** * * @deprecated Use {@link org.gudy.azureus2.ui.swt.plugins.UISWTInstance#addView(String, String, UISWTViewEventListener)} */ public interface UISWTAWTPluginView { public String getPluginViewName(); /** * Create an AWT component for this view instance * @return */ public Component create(); /** * The view instance is visible * @param component */ public void open( Component component ); /** * The view instance has been closed * @param component */ public void delete( Component component ); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/UISWTView.java0000644000175000017500000000667010373051022023503 0ustar adrianadrian/* * File : UISWTView.java * Created : Oct 14, 2005 * By : TuxPaper * * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.plugins; import org.gudy.azureus2.plugins.ui.UIPluginView; /** * Commands and Information about a SWT View * * @author TuxPaper * * @see org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent#getView() * @see org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener#eventOccurred(UISWTViewEvent) * @see org.gudy.azureus2.ui.swt.plugins.UISWTInstance#addView(String, String, UISWTViewEventListener) */ public interface UISWTView extends UIPluginView { /** * For {@link #setControlType(int)}; When the event * {@link UISWTViewEvent#TYPE_INITIALIZE} is triggered, getData() will * return a {@link org.eclipse.swt.widgets.Composite} object. * * @since 2.3.0.6 */ public static final int CONTROLTYPE_SWT = 0; /** * For {@link #setControlType(int)}; When the event * {@link UISWTViewEvent#TYPE_INITIALIZE} is triggered, getData() will * return a {@link java.awt.Component} object. * * @since 2.3.0.6 */ public static final int CONTROLTYPE_AWT = 1; /** * Sets the type of control this view uses. Set before view initialization. *

* The default value is {@link #CONTROLTYPE_SWT} * * @param iControlType * * @since 2.3.0.6 */ public void setControlType(int iControlType); /** * Retrieve the data sources related to this view. * * @return Depending on the parent view you added your view to, the Object will be:
* {@link UISWTInstance#VIEW_MAIN}- null
* {@link UISWTInstance#VIEW_MYTORRENTS}- {@link org.gudy.azureus2.plugins.download.Download}
* {@link UISWTInstance#VIEW_TORRENT_PEERS}- {@link org.gudy.azureus2.plugins.peers.Peer}
* If created by {@link UISWTInstance#openMainView(String, UISWTViewEventListener, Object)}, * value will be the value set. *

* May return null if no data source is selected, or while processing the * {@link UISWTViewEvent#TYPE_CREATE} event. * * @since 2.3.0.6 */ // From UIPluginView, declared here only to change JavaDoc public Object getDataSource(); /** * Trigger an event for this view * * @param eventType Event to trigger * @param data data to send with trigger * * @since 2.3.0.6 */ public void triggerEvent(int eventType, Object data); /** * Override the default title with a new one. * * After setting this, you should use the * {@link UISWTViewEvent#TYPE_LANGUAGEUPDATE} to update your title to the * new language. * * @param title new Title * * @since 2.3.0.6 */ public void setTitle(String title); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/UISWTConfigSection.java0000644000175000017500000000341111010504570025311 0ustar adrianadrian/* * Created on 11-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.plugins; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.plugins.ui.config.ConfigSection; /** * * @since 2.3.0.5 */ public interface UISWTConfigSection extends ConfigSection { /** * Create your own configuration panel here. It can be anything that inherits * from SWT's Composite class. * Please be mindful of small screen resolutions * * @param parent The parent of your configuration panel * @return your configuration panel */ public Composite configSectionCreate( Composite parent ); /** * Indicate if additional options are available to display a hint to the users * * @return the highest user mode that reveals additional options (0 = Beginner, 1 = Intermediate, 2 = Advanced) */ public int maxUserMode(); }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/UISWTViewEventListener.java0000644000175000017500000000275510373051022026213 0ustar adrianadrian/* * File : UISWTViewEventListener.java * Created : Oct 14, 2005 * By : TuxPaper * * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.plugins; /** * Listener to be triggered when an event related to a UISWTView takes place * * @see org.gudy.azureus2.ui.swt.plugins.UISWTInstance#addView(String, String, UISWTViewEventListener) * * @author TuxPaper */ public interface UISWTViewEventListener { /** * Triggers when an even listed in UISWTViewEvent occurs * * @param event event that occurred * @return meaning dependent upon event type * * @since 2.3.0.6 */ public boolean eventOccurred(UISWTViewEvent event); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/UISWTStatusEntryListener.java0000644000175000017500000000246110561413602026603 0ustar adrianadrian/** * Created on 03-Feb-2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.plugins; /** * A listener object which is informed when a UISWTStatusEntry has been * clicked on. * * @author amc1 * @since 3.0.0.8 * @see UISWTStatusEntry */ public interface UISWTStatusEntryListener { /** * This method is invoked when a status entry is clicked on. */ public void entryClicked(UISWTStatusEntry entry); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/plugins/UISWTInstance.java0000644000175000017500000002163511267267042024351 0ustar adrianadrian/* * Created on 05-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.plugins; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.UIInstance; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.plugins.ui.model.BasicPluginViewModel; import org.gudy.azureus2.plugins.ui.tables.TableManager; /** * Tools to manage a SWT Instance * * @see org.gudy.azureus2.plugins.ui.UIManagerListener * @see org.gudy.azureus2.plugins.ui.UIManager#addUIListener(UIManagerListener) */ public interface UISWTInstance extends UIInstance { /** ID of main view */ public static final String VIEW_MAIN = "Main"; /** * ID of "My Torrents" view * * @since 2.3.0.7 */ public static final String VIEW_MYTORRENTS = "MyTorrents"; /** * ID of "Peers" view * * @since 2.3.0.7 */ public static final String VIEW_TORRENT_PEERS = TableManager.TABLE_TORRENT_PEERS; /** * ID of "Pieces" view * * @since 2.3.0.7 */ public static final String VIEW_TORRENT_PIECES = TableManager.TABLE_TORRENT_PIECES; /** * ID of "Files" view * * @since 2.3.0.7 */ public static final String VIEW_TORRENT_FILES = TableManager.TABLE_TORRENT_FILES; /** * ID of the top bar of az3ui * * @since 3.0.1.3 */ public static final String VIEW_TOPBAR = "TopBar"; /** Retrieve the SWT Display object that Azureus uses (when in SWT mode). * If you have a thread that does some periodic/asynchronous stuff, Azureus * will crashes with and 'InvalidThreadAccess' exception unless you * embed your calls in a Runnable, and use getDisplay().aSyncExec(Runnable r); * * @return SWT Display object that Azureus uses * * @since 2.3.0.5 */ public Display getDisplay(); public Image loadImage( String resource ); /** Creates an UISWTGraphic object with the supplied SWT Image * * @param img Image to assign to the object * @return a new UISWTGraphic object * * @since 2.3.0.5 */ public UISWTGraphic createGraphic(Image img); /** * Add a detail view to an Azureus parent view. For views added to the Main * window, this adds a menu option. For the other parent views, this adds * a new tab within Azureus' own detail view. * * @param sParentID VIEW_* constant * @param sViewID of your view. Used as part of the resource id.
* "Views.plugins." + ID + ".title" = title of your view * @param l Listener to be triggered when parent view wants to tell you * an event has happened * * @note If you want the window to auto-open, use openMainView when you gain * access to the UISWTInstance * * @since 2.3.0.6 */ public void addView(String sParentID, String sViewID, UISWTViewEventListener l); /** * Open a previously added view * * @param sParentID ParentID of the view to be shown * @param sViewID id of the view to be shown * @param dataSource any data you need to pass the view * @return success level * * @since 2.5.0.1 */ public boolean openView(String sParentID, String sViewID, Object dataSource); /** * Open a previously added view * * @param sParentID ParentID of the view to be shown * @param sViewID id of the view to be shown * @param dataSource any data you need to pass the view * @param setfocus true if you want to display the view immediately, * false if you want to display it in the background. * @return success level * @since 3.0.5.3 */ public boolean openView(String sParentID, String sViewID, Object dataSource, boolean setfocus); /** * Create and open a view in the main window immediately. If you are calling * this from {@link org.gudy.azureus2.plugins.ui.UIManagerListener#UIAttached(UIInstance)}, * the view will not gain focus. *

* Tip: You can add a menu item to a table view, and when triggered, have * it open a new window, passing the datasources that were selected * * @param sViewID ID to give your view * @param l Listener to be triggered when View Events occur * @param dataSource objects to set {@link UISWTView#getDataSource()} with * * @since 2.3.0.6 */ public void openMainView(String sViewID, UISWTViewEventListener l, Object dataSource); /** * Create and open a view in the main window immediately. If you are calling * this from {@link org.gudy.azureus2.plugins.ui.UIManagerListener#UIAttached(UIInstance)}, * the view will not gain focus. *

* Tip: You can add a menu item to a table view, and when triggered, have * it open a new window, passing the datasources that were selected * * @param sViewID ID to give your view * @param l Listener to be triggered when View Events occur * @param dataSource objects to set {@link UISWTView#getDataSource()} with * @param setfocus true if you want to display the view immediately, * false if you want to display it in the background. * * @since 3.0.5.3 */ public void openMainView(String sViewID, UISWTViewEventListener l, Object dataSource, boolean setfocus); /** * Remove all views that belong to a specific parent and of a specific View * ID. If the parent is the main window, the menu item will be removed.
* If you wish to remove (close) just one view, use * {@link UISWTView#closeView()} * * @param sParentID One of VIEW_* constants * @param sViewID View ID to remove * * @since 2.3.0.6 */ public void removeViews(String sParentID, String sViewID); /** * Get a list of views currently open on the specified VIEW_* view * * @param sParentID VIEW_* constant * @return list of views currently open * * @since 2.3.0.6 */ public UISWTView[] getOpenViews(String sParentID); /** * A Plugin might call this method to add a View to Azureus's views * The View will be accessible from View > Plugins > View name * @param view The PluginView to be added * @param autoOpen Whether the plugin should auto-open at startup * * @since 2.3.0.5 * @deprecated Use {@link #addView(String, String, UISWTViewEventListener)} */ public void addView(UISWTPluginView view, boolean autoOpen); /** * Remove a view * @param view * * @since 2.3.0.5 * @deprecated Use {@link #removeViews(String, String)} */ public void removeView(UISWTPluginView view); /** * Add an AWT panel as the plugin view * @param view * @param auto_open * * @since 2.3.0.5 * @deprecated Use {@link #addView(String, String, UISWTViewEventListener)} */ public void addView(UISWTAWTPluginView view, boolean auto_open); /** * Remove a view * @param view * * @since 2.3.0.5 * @deprecated Use {@link #removeViews(String, String)} */ public void removeView(UISWTAWTPluginView view); /** * Shows or hides a download bar for a given download. * * @since 3.0.0.5 * @param download Download to use. * @param display true to show a download bar, false to hide it. */ public void showDownloadBar(Download download, boolean display); /** * Shows or hides the transfers bar. * * @since 3.0.1.3 * @param display true to show the bar, false to hide it. */ public void showTransfersBar(boolean display); /** * Creates an entry in the status bar to display custom status information. * * @since 3.0.0.7 * @see UISWTStatusEntry */ public UISWTStatusEntry createStatusEntry(); /** * Opens the window linked to a given BasicPluginViewModel object. * * @return true if the view was opened successfully. * @since 3.0.5.3 */ public boolean openView(BasicPluginViewModel model); /** * Opens the window linked to a given BasicPluginViewModel object. * * @return true if the view was opened successfully. * @since 3.0.5.3 */ public void openConfig(BasicPluginConfigModel model); /** * Creates a SWT Shell, ensuring Vuze knows about it (ie. Icon, "Window" menu) * * @param style * @return * * @since 4.2.0.9 */ Shell createShell(int style); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/about.properties0000644000175000017500000000073511102507452022641 0ustar adrianadriandevelopers=\ Olivier Chalouhi\n\ Paul Gardner\n\ Alon Rohter\n\ Olivier Goussard\n\ TuxPaper\n\ Joseph Bridgewater\n\ Allan Crooks\n\ Aaron Grunthal\n\ James Yeh\n\ Ren\u00e9 Leonhardt\n\ Chea Chee Keong\n\ Tyler Pitchford translators=Mika Vainikka\n\ Manuel Periago\n\ Aurimas F.\n\ Mele\n\ Pupp Zoltan\n\ Maarten Van Duijvendijk\n\ Palle Raabjerg\n\ Gatak\n\ LeonZhao\n\ Ondrej Zarevucky\n\ Andreas Rudisch\n\ Jeroen Zuiddam\n\ ...And many others\n\ azureus-4.3.0.6/org/gudy/azureus2/ui/swt/Sleak.java0000644000175000017500000002735110736557060021332 0ustar adrianadrian/* * Created on Sep 10, 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; /* * Copyright (c) 2000, 2002 IBM Corp. All rights reserved. * This file is made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html */ import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; /** * Code to detect swt leak * */ public class Sleak { Display display; Shell shell; List list; Canvas canvas; Button start, stop, check; Text text; Text label; Object[] oldObjects = new Object[0]; Error[] oldErrors = new Error[0]; Object[] objects = new Object[0]; Error[] errors = new Error[0]; Map all = new HashMap(); ArrayList oldNonResources = new ArrayList(); public void open() { display = Display.getCurrent(); shell = new Shell(display); shell.setText("S-Leak"); list = new List(shell, SWT.BORDER | SWT.V_SCROLL); list.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { refreshObject(); } }); text = new Text(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); canvas = new Canvas(shell, SWT.BORDER); canvas.addListener(SWT.Paint, new Listener() { public void handleEvent(Event event) { paintCanvas(event); } }); check = new Button(shell, SWT.CHECK); check.setText("Stack"); check.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { toggleStackTrace(); } }); start = new Button(shell, SWT.PUSH); start.setText("Snap"); start.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { refreshAll(); } }); stop = new Button(shell, SWT.PUSH); stop.setText("Diff"); stop.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { refreshDifference(); } }); label = new Text(shell, SWT.BORDER | SWT.READ_ONLY + SWT.MULTI); label.setText("0 object(s)"); shell.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { layout(); } }); check.setSelection(false); text.setVisible(false); Point size = shell.getSize(); shell.setSize(size.x / 2, size.y / 2); shell.open(); } void refreshLabel() { int colors = 0, cursors = 0, fonts = 0, gcs = 0, images = 0, regions = 0, others = 0, composites = 0, labels = 0; for (int i = 0; i < objects.length; i++) { Object object = objects[i]; if (object instanceof Color) { colors++; } else if (object instanceof Cursor) { cursors++; } else if (object instanceof Font) { fonts++; } else if (object instanceof GC) { gcs++; } else if (object instanceof Image) { images++; } else if (object instanceof Region) { regions++; } else if (object instanceof Composite) { composites++; } else if (object instanceof Label) { labels++; } else { others++; } } String string = ""; if (colors != 0) { string += colors + " Color(s)\n"; } if (cursors != 0) { string += cursors + " Cursor(s)\n"; } if (fonts != 0) { string += fonts + " Font(s)\n"; } if (gcs != 0) { string += gcs + " GC(s)\n"; } if (images != 0) { string += images + " Image(s)\n"; } if (composites != 0) { string += composites + " composite(s)\n"; } if (labels != 0) { string += labels + " label(s)\n"; } if (others != 0) { string += others + " Other(s)\n"; } /* Currently regions are not counted. */ // if (regions != 0) string += regions + " Region(s)\n"; if (string.length() != 0) { string = string.substring(0, string.length() - 1); } label.setText(string); } void refreshDifference() { DeviceData info = display.getDeviceData(); if (!info.tracking) { MessageBox dialog = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK); dialog.setText(shell.getText()); dialog.setMessage("Warning: Device is not tracking resource allocation"); dialog.open(); } Object[] newObjects = info.objects; Error[] newErrors = info.errors; Object[] diffObjects = new Object[newObjects.length]; Error[] diffErrors = new Error[newErrors.length]; int countResourceType = 0; for (int i = 0; i < newObjects.length; i++) { int index = 0; while (index < oldObjects.length) { if (newObjects[i] == oldObjects[index]) { break; } index++; } if (index == oldObjects.length) { diffObjects[countResourceType] = newObjects[i]; diffErrors[countResourceType] = newErrors[i]; countResourceType++; } } Shell[] shells = display.getShells(); ArrayList nonResourceList = new ArrayList(); for (int i = 0; i < shells.length; i++) { Shell shell = shells[i]; if (shell != this.shell) { buildObjectList(shell, nonResourceList); } } oldNonResources = nonResourceList; Object[] nonResources = nonResourceList.toArray(); int countNonResources = nonResources.length; int total = countResourceType + countNonResources; objects = new Object[total]; errors = new Error[total]; System.arraycopy(diffObjects, 0, objects, 0, countResourceType); System.arraycopy(diffErrors, 0, errors, 0, countResourceType); System.arraycopy(nonResources, 0, objects, countResourceType, countNonResources); list.removeAll(); text.setText(""); canvas.redraw(); for (int i = 0; i < objects.length; i++) { list.add(objectName(objects[i])); } System.out.println(countResourceType); refreshLabel(); layout(); } /** * @param shell2 * @param list2 */ private void buildObjectList(Control control, ArrayList list) { if (!oldNonResources.contains(control)) { list.add(control); } if (control instanceof Composite) { Composite c = (Composite) control; Control[] children = c.getChildren(); for (int i = 0; i < children.length; i++) { Control control2 = children[i]; buildObjectList(control2, list); } } } String objectName(Object object) { Date timeAdded = (Date)all.get(object); if (timeAdded == null) { timeAdded = new Date(); all.put(object, timeAdded); } String string = timeAdded + "] " + object.toString(); if (object instanceof Resource) { return string; } int index = string.indexOf(" {"); if (index == -1) { return string; } string = string.substring(0, index); if (object instanceof Composite) { Control[] children = ((Composite) object).getChildren(); string += ": " + children.length + " kids"; } return string; } void toggleStackTrace() { refreshObject(); layout(); } void paintCanvas(Event event) { canvas.setCursor(null); int index = list.getSelectionIndex(); if (index == -1) { return; } GC gc = event.gc; Object object = objects[index]; if (object instanceof Color) { if (((Color) object).isDisposed()) { gc.drawString("Color disposed", 0, 0); return; } gc.setBackground((Color) object); gc.fillRectangle(canvas.getClientArea()); return; } if (object instanceof Cursor) { if (((Cursor) object).isDisposed()) { gc.drawString("Cursor disposed", 0, 0); return; } canvas.setCursor((Cursor) object); return; } if (object instanceof Font) { if (((Font) object).isDisposed()) { gc.drawString("Font disposed", 0, 0); return; } gc.setFont((Font) object); FontData[] array = gc.getFont().getFontData(); String string = ""; String lf = text.getLineDelimiter(); for (int i = 0; i < array.length; i++) { FontData data = array[i]; String style = "NORMAL"; int bits = data.getStyle(); if (bits != 0) { if ((bits & SWT.BOLD) != 0) { style = "BOLD "; } if ((bits & SWT.ITALIC) != 0) { style += "ITALIC"; } } string += data.getName() + " " + data.getHeight() + " " + style + lf; } gc.drawString(string, 0, 0); return; } //NOTHING TO DRAW FOR GC // if (object instanceof GC) { // return; // } if (object instanceof Image) { if (((Image) object).isDisposed()) { gc.drawString("Image disposed", 0, 0); return; } gc.drawImage((Image) object, 0, 0); return; } if (object instanceof Region) { if (((Region) object).isDisposed()) { return; } String string = ((Region) object).getBounds().toString(); gc.drawString(string, 0, 0); return; } if (object instanceof Control) { gc.drawString(object.toString(), 0, 0); gc.drawString(((Control) object).getBounds().toString(), 0, 20); if (object instanceof Widget) { Object data = ((Widget)object).getData("sleak"); if (data != null) { gc.drawString(data.toString(), 0, 35); } } return; } } void refreshObject() { int index = list.getSelectionIndex(); if (index == -1) { return; } if (check.getSelection() && index < errors.length && errors[index] == null) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); PrintStream s = new PrintStream(stream); errors[index].printStackTrace(s); text.setText(stream.toString()); text.setVisible(true); canvas.setVisible(false); } else { canvas.setVisible(true); text.setVisible(false); canvas.redraw(); } } void refreshAll() { oldObjects = new Object[0]; oldErrors = new Error[0]; oldNonResources = new ArrayList(); refreshDifference(); oldObjects = objects; oldErrors = errors; } void layout() { Rectangle rect = shell.getClientArea(); int width = 0; String[] items = list.getItems(); GC gc = new GC(list); for (int i = 0; i < objects.length; i++) { width = Math.max(width, gc.stringExtent(items[i]).x); } gc.dispose(); Point size1 = start.computeSize(SWT.DEFAULT, SWT.DEFAULT); Point size2 = stop.computeSize(SWT.DEFAULT, SWT.DEFAULT); Point size3 = check.computeSize(SWT.DEFAULT, SWT.DEFAULT); Point size4 = label.computeSize(SWT.DEFAULT, SWT.DEFAULT); width = Math.max(size1.x, Math.max(size2.x, Math.max(size3.x, width))); width = Math.max(64, Math.max(size4.x, list.computeSize(width, SWT.DEFAULT).x)); start.setBounds(0, 0, width, size1.y); stop.setBounds(0, size1.y, width, size2.y); check.setBounds(0, size1.y + size2.y, width, size3.y); label.setBounds(0, rect.height - size4.y, width, size4.y); int height = size1.y + size2.y + size3.y; list.setBounds(0, height, width, rect.height - height - size4.y); text.setBounds(width, 0, rect.width - width, rect.height); canvas.setBounds(width, 0, rect.width - width, rect.height); } public static void main(String[] args) { DeviceData data = new DeviceData(); data.tracking = true; Display display = new Display (data); Sleak sleak = new Sleak(); Main.main(args); sleak.open(); while (!sleak.shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } try { if (!display.isDisposed()) { display.dispose(); } } catch (Exception e) { // TODO: handle exception } } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/Main.java0000644000175000017500000001645011224477200021143 0ustar adrianadrian/* * Created on 8 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import java.io.File; import com.aelitis.azureus.core.*; import com.aelitis.azureus.launcher.Launcher; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.ui.swt.mainwindow.Initializer; /** * @author Olivier * */ public class Main { private static final LogIDs LOGID = LogIDs.GUI; public static final String PR_MULTI_INSTANCE = "MULTI_INSTANCE"; // values "true" or "false" StartServer startServer; public static long startTime = System.currentTimeMillis(); // This method is called by other Main classes via reflection - must be kept public. public Main(String args[]) { try{ // this should not be necessary, but since it's public let's play safe if(Launcher.checkAndLaunch(Main.class, args)) return; // This *has* to be done first as it sets system properties that are read and cached by Java COConfigurationManager.preInitialise(); String mi_str = System.getProperty( PR_MULTI_INSTANCE ); boolean mi = mi_str != null && mi_str.equalsIgnoreCase("true"); startServer = new StartServer(); boolean debugGUI = Boolean.getBoolean("debug"); if( mi || debugGUI){ // create a MainWindow regardless to the server state AzureusCore core = AzureusCoreFactory.create(); new Initializer(core,startServer,args); return; } if ( processParams(args, startServer) ){ AzureusCore core = AzureusCoreFactory.create(); startServer.pollForConnections(core); new Initializer(core,startServer,args); } }catch( AzureusCoreException e ){ Logger.log(new LogEvent(LOGID, "Start failed", e)); } } /** * @param args * @return whether to init the core */ public static boolean processParams(String[] args, StartServer startServer) { boolean closedown = false; boolean another_instance = startServer.getState() != StartServer.STATE_LISTENING; /* if another instance is running then set the property which is checked during * class instantiation by various stuff to to avoid pulling in too much state * from the already running instance */ if(another_instance) System.setProperty("transitory.startup", "1"); // WATCH OUT FOR LOGGING HERE - we don't want to use Logger if this is a secondary instance as // it initialised TOO MUCH of AZ core for (int i=0;i * Facilitates localization-specific and platform-specific keyboard shortcut handling through the use of keybinding values. *

*

* A keybinding value is a line of String that can be specified in the localization bundle properties file for a particular menu item. To do so, * a localization key/value pair is used, with the key being the same as menu item's key plus ".keybinding". *

*

* For instance, if a keyboard shortcut needs to be specified for "MainWindow.menu.file.open", then a key/value pair with the key of * "MainWindow.menu.file.open.keybinding" is created. The value is what would be used as the keyboard accelerator, with the following special * values:
*

    *
  • Meta (or Cmd) - The "Meta" modifier; this is "Command" on OS X, and "Control" on all other platforms
  • *
  • Ctrl - The "Control" modifier on all platforms. Use this only if you need to enforce the use of Control.
  • *
  • Alt (or Opt) - The "Alt" modifier
  • *
  • Shift - The "Shift" modifier
  • *
  • Ins - Insert
  • *
  • Backspace
  • *
  • Del - Delete
  • *
  • Esc - Escape
  • *
  • PgUp - Page Up
  • *
  • PgDn - Page Down
  • *
  • Left - The left arrow
  • *
  • Up - The up arrow
  • *
  • Right - The right arrow
  • *
  • Down - The down arrow
  • *
  • Home
  • *
  • End
  • *
  • Tab
  • *
  • Fx, where x is an integer from 1 to 15 (inclusive) - The function key (F1-F15)
  • *

* Other valid values can be typed as is or as the Unicode representation. For security reasons, this is initially set with a very conservative scope, * including alphanumerics, \, =, -, (comma), (period), and `. *

*

* As of version 1.2, keybindings are only set if the following conditions are met: *

    *
  1. A function key is set or
  2. *
  3. Meta, Alt, or Ctrl is set (or their variations)
  4. *
*

*

* The keys were chosen to more conveniently address the issue on platforms like Windows where vanilla SWT does not display the shortcuts, as * opposed to higher-level API like JFace or some platforms' native rendering. *

*

* For example, if File / Open / .torrent File is set to be Meta+O (Command+O or Ctrl+O), then in MessageBundle.properties (or the localization- * specific equivalent), MainWindow.menu.file.open.torrent.keybinding=Meta+O will be entered. The label will be adjusted to Ctrl on non-OS X * platforms (OS X will draw the glyph for Cmd). *

*

* As another example, if File / Exit is set to be Alt+F4, then in MessageBundle.properties (or the localization-specific equivalent), * MainWindow.menu.file.exit.keybinding=Alt+F4 will be entered. *

*

* To accommodate for the variety of locales and platforms running on Azureus, platforms and localizations can "override" the default keybinding value. * The order of parsing is as follows:
*

    *
  1. If a localized keybinding value exists for the current locale and platform, it is used
  2. *
  3. If the above is not found, this method looks for a keybinding value for the current locale without platform specificity
  4. *
  5. If the above is not found, this method looks for a keybinding value for the default locale and the currently running platform
  6. *
  7. If the above is not found, this method looks for a keybinding value for the default locale without platform specificity
  8. *
  9. If the above is not found, no accelerator is set for the MenuItem
  10. *
*

*

* For instance, to refer to the above example, if the Mac OS X target for Azureus wants to handle File / Exit as Command+Q, then * MainWindow.menu.file.exit.keybinding.mac=Meta+Q is entered. If it is not entered, the value for the 'default' key MainWindow.menu.file.exit.keybinding * will be used. *

*

* The platform suffix can be attached to the end of the localization key. Valid suffixes are:
*

    *
  • .linux - Linux
  • *
  • .mac - Mac OS X
  • *
  • .windows - Windows
  • *
*

* @author CrazyAlchemist * @version 1.3 Added removeAccelerator */ public final class KeyBindings { private static final Pattern FUNC_EXP = Pattern.compile("([fF]{1})([1-9]{1}[0-5]{0,1})"); private static final Pattern SANCTIONED_EXP = Pattern.compile("([ a-zA-Z\\d/\\\\=\\-,\\.`]{1})"); // modifier key/value pairs must be symmetrical private static final String[] SPECIAL_KEYS = new String[] { "Meta", "Ctrl", "Cmd", "Alt", "Opt", "Shift", "Ins", "Backspace", "Del", "Esc", "PgUp", "PgDn", "Left", "Up", "Right", "Down", "Home", "End", "Tab" }; private static final int[] SPECIAL_VALUES = new int[] { SWT.MOD1, SWT.CTRL, SWT.MOD1, SWT.ALT, SWT.ALT, SWT.SHIFT, SWT.INSERT, '\010', // backspace '\u007f', // del '\033', SWT.PAGE_UP, SWT.PAGE_DOWN, SWT.LEFT, SWT.UP, SWT.RIGHT, SWT.DOWN, SWT.HOME, SWT.END, '\t' }; private static final String DELIM = "+"; private static final String DELIM_EXP = "\\+"; /** *

* Gets the localization key suffix for the running platform for keybinding retrieval *

*

* For now, as is with Azureus' Constants behaviour, supported platforms are Linux, Mac OS X, and Windows only *

* @return The platform key suffix; or an empty string on an unsupported platform */ private static String getPlatformKeySuffix() { if(Constants.isLinux) return ".linux"; else if(Constants.isSolaris) return ".solaris"; else if(Constants.isUnix) return ".unix"; else if(Constants.isFreeBSD) return ".freebsd"; else if(Constants.isOSX) return ".mac"; else if(Constants.isWindows) return ".windows"; return ""; } /** * Parses the keybinding string according to the specifications documented at this class and gets the SWT value equivalent for keyboard accelerator settings. * @param keyBindingValue Keybinding value * @return A KeyBindingInfo object, which consists of the SWT accelerator and its display name */ private static KeyBindingInfo parseKeyBinding(final String keyBindingValue) { if(keyBindingValue.length() < 1) return new KeyBindingInfo(null, SWT.NONE); // initialize with nothing int swtAccelerator = SWT.NONE; final String[] tmpValues = keyBindingValue.split(DELIM_EXP); final boolean[] specVisited = new boolean[SPECIAL_KEYS.length]; // flag for speed optimization boolean funcVisited = false; final StringBuffer displayValue = new StringBuffer(keyBindingValue.length() + 2); // allocate display string displayValue.append('\t'); for (int i = 0; i < tmpValues.length; i++) { final String value = tmpValues[i]; boolean matched = false; // process special keys first for(int j = 0; j < SPECIAL_KEYS.length; j++) { if(!specVisited[j] && SPECIAL_KEYS[j].equalsIgnoreCase(value)) { swtAccelerator = swtAccelerator | SPECIAL_VALUES[j]; // special-case meta; a generalized solution would be warranted if: // a) additional special modifiers persist or // b) other platforms have special labeling requirements or // c) SWT changes its lower-level API so shortcut labels are no longer custom drawn on Win etc. if(SPECIAL_KEYS[j].equalsIgnoreCase("Meta")) displayValue.append(Constants.isOSX ? "Cmd" : "Ctrl").append(DELIM); else displayValue.append(SPECIAL_KEYS[j]).append(DELIM); // mark flags specVisited[j] = true; matched = true; break; } } if(matched) continue; // special treatment for function keys if(!funcVisited) { final Matcher funcMatcher = FUNC_EXP.matcher(value); if(funcMatcher.find() && funcMatcher.start() == 0 && funcMatcher.end() == value.length()) { final int funcVal = Integer.parseInt(funcMatcher.group(2)); // SWT.F1 is (1 << 24) + 10 swtAccelerator = swtAccelerator | ((1 << 24) + (9 + funcVal)); displayValue.append(funcMatcher.group(0)).append(DELIM); funcVisited = true; matched = true; } } if(matched) continue; final Matcher valMatcher = SANCTIONED_EXP.matcher(value); if(valMatcher.find() && valMatcher.start() == 0) { final char c = valMatcher.group().charAt(0); // avoid possible duplicates (\t is index 0) final int subStrIndex = displayValue.indexOf(c + DELIM); if(subStrIndex == 1 || (subStrIndex > 1 && displayValue.substring(subStrIndex - 1, subStrIndex).equals(DELIM))) continue; swtAccelerator = swtAccelerator | c; displayValue.append(c).append(DELIM); } } if(funcVisited || specVisited[0] || specVisited[1] || specVisited[2] || specVisited[3] || specVisited[4]) // special case - be a bit careful for now return new KeyBindingInfo(displayValue.substring(0, displayValue.length() - 1), swtAccelerator); else return new KeyBindingInfo(null, SWT.NONE); } /** *

* Removes the keyboard accelerator for a SWT MenuItem *

* @param menu SWT MenuItem * @param localizationKey The MenuItem's localization key for the localization resource bundle */ public static void removeAccelerator(final MenuItem menu, String localizationKey) { setAccelerator(menu, new KeyBindingInfo("", SWT.NONE)); Messages.setLanguageText(menu, localizationKey); } /** *

* Sets the keyboard accelerator for a SWT MenuItem. *

*

* There is a specific order of accelerator setting in consideration with different platforms and localizations. Specifically:
*

    *
  1. If a localized keybinding value exists for the current locale and platform, it is used
  2. *
  3. If the above is not found, this method looks for a keybinding value for the current locale without platform specificity
  4. *
  5. If the above is not found, this method looks for a keybinding value for the default locale and the currently running platform
  6. *
  7. If the above is not found, this method looks for a keybinding value for the default locale without platform specificity
  8. *
  9. If the above is not found, no accelerator is set for the MenuItem
  10. *
*

* @param menu SWT MenuItem * @param localizationKey The MenuItem's localization key for the localization resource bundle */ public static void setAccelerator(final MenuItem menu, String localizationKey) { localizationKey += ".keybinding"; final String platformSpecificKey = localizationKey + getPlatformKeySuffix(); // first, check for platform-specific, localization-specific binding if(MessageText.keyExists(platformSpecificKey)) { setAccelerator(menu, parseKeyBinding(MessageText.getString(platformSpecificKey))); } else if(MessageText.keyExists(localizationKey)) // platform-independent, localization-specific binding { setAccelerator(menu, parseKeyBinding(MessageText.getString(localizationKey))); } else if(!MessageText.isCurrentLocale(MessageText.LOCALE_DEFAULT)) { // default locale // platform-specific first if(MessageText.keyExistsForDefaultLocale(platformSpecificKey)) { setAccelerator(menu, parseKeyBinding(MessageText.getDefaultLocaleString(platformSpecificKey))); } else if(MessageText.keyExistsForDefaultLocale(localizationKey)) { // default locale, platform-independent setAccelerator(menu, parseKeyBinding(MessageText.getDefaultLocaleString(localizationKey))); } } } /** * Helper method to set a keyboard accelerator for a MenuItem. If kbInfo is SWT.NONE, no accelerator will be set. * @param menu SWT MenuItem * @param kbInfo KeyBindingInfo object, which contains the SWT accelerator value and its display name */ private static void setAccelerator(final MenuItem menu, final KeyBindingInfo kbInfo) { if(kbInfo.accelerator != SWT.NONE) { menu.setAccelerator(kbInfo.accelerator); // SWT on OS X now uses native drawing if(!Constants.isOSX && !menu.getText().endsWith(kbInfo.name)) menu.setText(menu.getText() + kbInfo.name); } } /** * Runs simple tests on KeyBindings keybinding values * @param args Command-line arguments; they are not used */ public static void main(final String[] args) { System.out.println(parseKeyBinding("Ctrl+1").name); // meta+1 System.out.println(parseKeyBinding("Ctrl+F12").name); // meta+f12 System.out.println(parseKeyBinding("Ctrl+F4").name); // meta+f4 System.out.println("Meta+Shift+O"); System.out.println(parseKeyBinding("Ctrl+Shift+O").accelerator); // meta+shift+o System.out.println(parseKeyBinding("Shift+Ctrl+O").accelerator); // meta+shift+o System.out.println(SWT.MOD1 | SWT.SHIFT | 'O'); // meta+shift+o System.out.println("Meta+Shift+o"); System.out.println(SWT.MOD1 | SWT.SHIFT | 'o'); // meta+shift+o } /** *

* A basic bean object containing the SWT accelerator and its display name. This is because on platforms like Windows, vanilla SWT MenuItem must be * provided the textual representation (display name) of the accelerator in order for it to be visible to the users (as opposed to having it handled by a higher- * level API like JFace or native rendering). *

*/ private static class KeyBindingInfo { /** * The display name of the accelerator */ private final String name; /** * The SWT keyboard accelerator value */ private final int accelerator; /** * Constructs a new KeyBindingInfo object with the given accelerator name and accelerator value * @param name Display name * @param accelerator SWT accelerator value */ private KeyBindingInfo(final String name, final int accelerator) { this.name = name; this.accelerator = accelerator; } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/IconBar.java0000644000175000017500000002217311267524616021606 0ustar adrianadrian/* * File : IconBar.java * Created : 7 dc. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.components.BufferedToolItem; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author Olivier * */ public class IconBar { private final boolean OVERRIDE_SHOW_UISWITCHER = System.getProperty( "ui.toolbar.uiswitcher", "0").equals("1"); CoolBar coolBar; Composite parent; Map itemKeyToControl; IconBarEnabler currentEnabler; private Composite cIconBar; private static List listeners = new ArrayList(0); private Listener listenerToolItem; public IconBar(Composite parent) { this.parent = parent; listenerToolItem = new Listener() { public void handleEvent(Event e) { if (e.type == SWT.Selection) { if (currentEnabler != null) { currentEnabler.itemActivated((String) e.widget.getData("key")); } } else if (e.type == SWT.Dispose) { ImageLoader.getInstance().releaseImage( (String) e.widget.getData("ImageID")); } } }; cIconBar = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(2, false); layout.marginHeight = 0; layout.marginWidth = 0; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; cIconBar.setLayout(layout); this.itemKeyToControl = new HashMap(); // 3.1 onwards the default is gradient-fill - the disabled icons' transparency no workies // so disabled buttons look bad on the gradient-filled background this.coolBar = new CoolBar(cIconBar,Constants.isWindows?SWT.FLAT:SWT.NULL); initBar(); this.coolBar.setLocked(true); coolBar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); // We could setup a listener on the parameter and dynamically remove/add // ui switcher button, but it's not worth the effort boolean enableUISwitcher = OVERRIDE_SHOW_UISWITCHER || COConfigurationManager.getBooleanParameter("ui.toolbar.uiswitcher") || COConfigurationManager.getBooleanParameter("ui.asked", false); if (enableUISwitcher) { ToolBar tbSwitch = new ToolBar(cIconBar, SWT.FLAT); GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); tbSwitch.setLayoutData(gridData); ToolItem tiSwitch = new ToolItem(tbSwitch, SWT.PUSH); tiSwitch.setImage(ImageLoader.getInstance().getImage("cb_switch")); Messages.setLanguageText(tiSwitch, "iconBar.switch.tooltip", true); tiSwitch.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { UISwitcherUtil.openSwitcherWindow(); } public void widgetDefaultSelected(SelectionEvent e) { } }); tiSwitch.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { ImageLoader.getInstance().releaseImage("cb_switch"); } }); } } public void setEnabled(String itemKey,boolean enabled) { BufferedToolItem BufferedToolItem = (BufferedToolItem) itemKeyToControl.get(itemKey); if(BufferedToolItem != null) BufferedToolItem.setEnabled(enabled); } public void setSelection(String itemKey,boolean selection) { BufferedToolItem BufferedToolItem = (BufferedToolItem) itemKeyToControl.get(itemKey); if(BufferedToolItem != null) BufferedToolItem.setSelection(selection); } public void setCurrentEnabler(IconBarEnabler enabler) { this.currentEnabler = enabler; refreshEnableItems(); } // dead public IconBarEnabler getCurrentEnabler() { return this.currentEnabler; } private void refreshEnableItems() { Iterator iter = itemKeyToControl.keySet().iterator(); while(iter.hasNext()) { String key = (String) iter.next(); BufferedToolItem BufferedToolItem = (BufferedToolItem) itemKeyToControl.get(key); if(BufferedToolItem == null ) continue; if(currentEnabler != null) { BufferedToolItem.setEnabled(currentEnabler.isEnabled(key)); BufferedToolItem.setSelection(currentEnabler.isSelected(key)); } else { BufferedToolItem.setEnabled(false); BufferedToolItem.setSelection(false); } } } private BufferedToolItem createBufferedToolItem(ToolBar toolBar,int style,String key,final String imageName,String toolTipKey) { final BufferedToolItem bufferedToolItem = new BufferedToolItem(toolBar,style); bufferedToolItem.setData("key",key); bufferedToolItem.setData("ImageID",key); Messages.setLanguageText(bufferedToolItem.getWidget(),toolTipKey,true); bufferedToolItem.setImage(ImageLoader.getInstance().getImage(imageName)); bufferedToolItem.addListener(SWT.Selection, listenerToolItem); bufferedToolItem.addListener(SWT.Dispose, listenerToolItem); itemKeyToControl.put(key,bufferedToolItem); return bufferedToolItem; } public void addItemKeyToControl(String key, BufferedToolItem item) { itemKeyToControl.put(key, item); } private void initBar() { //The File Menu CoolItem coolItem = new CoolItem(coolBar,SWT.NULL); ToolBar toolBar = new ToolBar(coolBar,SWT.FLAT); createBufferedToolItem(toolBar,SWT.PUSH,"open","cb_open_no_default","iconBar.open.tooltip"); // XXX TuxPaper: Remove images (open, open_url, open_folder) from CVS and ImageRepository createBufferedToolItem(toolBar,SWT.PUSH,"new","cb_new","iconBar.new.tooltip"); toolBar.pack(); Point p = toolBar.getSize(); coolItem.setControl(toolBar); coolItem.setSize(coolItem.computeSize (p.x,p.y)); coolItem.setMinimumSize(p.x,p.y); coolItem = new CoolItem(coolBar,SWT.NULL); toolBar = new ToolBar(coolBar,SWT.FLAT); createBufferedToolItem(toolBar,SWT.PUSH,"top","cb_top","iconBar.top.tooltip"); createBufferedToolItem(toolBar,SWT.PUSH,"up","cb_up","iconBar.up.tooltip"); createBufferedToolItem(toolBar,SWT.PUSH,"down","cb_down","iconBar.down.tooltip"); createBufferedToolItem(toolBar,SWT.PUSH,"bottom","cb_bottom","iconBar.bottom.tooltip"); new BufferedToolItem(toolBar,SWT.SEPARATOR); createBufferedToolItem(toolBar,SWT.PUSH,"run","cb_run","iconBar.run.tooltip"); new BufferedToolItem(toolBar,SWT.SEPARATOR); createBufferedToolItem(toolBar,SWT.PUSH,"start","cb_start","iconBar.start.tooltip"); createBufferedToolItem(toolBar,SWT.PUSH,"stop","cb_stop","iconBar.stop.tooltip"); createBufferedToolItem(toolBar,SWT.PUSH,"remove","cb_remove","iconBar.remove.tooltip"); new BufferedToolItem(toolBar,SWT.SEPARATOR); createBufferedToolItem(toolBar,SWT.PUSH,"editcolumns","cb_editcolumns","iconBar.editcolumns.tooltip"); for (Iterator iter = listeners.iterator(); iter.hasNext();) { try { IconBarListener l = (IconBarListener) iter.next(); l.iconBarInitialized(coolBar, this); } catch (Exception e) { Debug.out(e); } } toolBar.pack(); p = toolBar.getSize(); coolItem.setControl(toolBar); if (Constants.isOSX) { p.x += 12; } coolItem.setSize(p.x,p.y); coolItem.setMinimumSize(p.x,p.y); } public void setLayoutData(Object layoutData) { cIconBar.setLayoutData(layoutData); } public static void main(String args[]) { Display display = new Display(); Shell shell = new Shell(display); FormLayout layout = new FormLayout(); layout.marginHeight = 0; layout.marginWidth = 0; shell.setLayout(layout); IconBar ibar = new IconBar(shell); FormData formData = new FormData(); formData.left = new FormAttachment(0,0); formData.right = new FormAttachment(100,0); ibar.setLayoutData(formData); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch ()) display.sleep (); } display.dispose (); } public Composite getComposite() { return cIconBar; } /** * */ public void delete() { Utils.disposeComposite(cIconBar); itemKeyToControl.clear(); currentEnabler = null; } public static void addListener(IconBarListener l) { if (!listeners.contains(l)) { listeners.add(l); } } public static interface IconBarListener { public void iconBarInitialized(CoolBar coolBar, IconBar ib); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/welcome/0000755000175000017500000000000011310377640021044 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/welcome/WelcomeWindow.java0000644000175000017500000002462511273703070024501 0ustar adrianadrian/* * Created on 15 avr. 2005 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.welcome; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Locale; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader.ResourceDownloaderFactoryImpl; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import com.aelitis.azureus.ui.swt.utils.ColorCache; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory; public class WelcomeWindow { private static final String URL_WHATSNEW = "http://www.vuze.com/releasenotes"; private static final String lineSeparator = System.getProperty ("line.separator"); Display display; Shell shell; Color black,white,light,grey,green,blue,fg,bg; String sWhatsNew; Font monospace; private Composite cWhatsNew; private Label labelLoading; public WelcomeWindow(Shell parentShell) { try { init(parentShell); } catch (Throwable t) { } } public void init (Shell parentShell) { shell = ShellFactory.createShell(parentShell, SWT.BORDER | SWT.TITLE | SWT.CLOSE | SWT.RESIZE); Utils.setShellIcon(shell); if(Constants.isOSX) monospace = new Font(shell.getDisplay(),"Courier",12,SWT.NORMAL); else monospace = new Font(shell.getDisplay(),"Courier New",8,SWT.NORMAL); shell.setText(MessageText.getString("window.welcome.title", new String[]{ Constants.AZUREUS_VERSION })); display = shell.getDisplay(); GridLayout layout = new GridLayout(); shell.setLayout(layout); GridData data; cWhatsNew = new Composite(shell, SWT.BORDER); data = new GridData(GridData.FILL_BOTH); cWhatsNew.setLayoutData(data); cWhatsNew.setLayout(new FillLayout()); Button bClose = new Button(shell,SWT.PUSH); bClose.setText(MessageText.getString("Button.close")); data = new GridData(); data.widthHint = 70; data.horizontalAlignment = Constants.isOSX ? SWT.CENTER : SWT.RIGHT; bClose.setLayoutData(data); Listener closeListener = new Listener() { public void handleEvent(Event event) { close(); } }; bClose.addListener(SWT.Selection, closeListener); shell.addListener(SWT.Close,closeListener); shell.setDefaultButton( bClose ); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ close(); } } }); shell.setSize(750,500); Utils.centreWindow(shell); shell.layout(); shell.open(); pullWhatsNew(cWhatsNew); } private void pullWhatsNew(Composite cWhatsNew) { labelLoading = new Label(cWhatsNew, SWT.CENTER); labelLoading.setText(MessageText.getString("installPluginsWizard.details.loading")); shell.layout(true, true); shell.update(); getWhatsNew(1); } public void setWhatsNew() { Utils.execSWTThread(new AERunnable() { public void runSupport() { _setWhatsNew(); } }); } public void _setWhatsNew() { if (sWhatsNew.indexOf("= 0 || sWhatsNew.indexOf("= 0) { Browser browser = Utils.createSafeBrowser(cWhatsNew, SWT.NONE); if (browser != null) { browser.setText(sWhatsNew); } else { try { File tempFile = File.createTempFile("AZU", ".html"); tempFile.deleteOnExit(); FileUtil.writeBytesAsFile(tempFile.getAbsolutePath(), sWhatsNew.getBytes("utf8")); Utils.launch(tempFile.getAbsolutePath()); shell.dispose(); return; } catch (IOException e) { } } } else { StyledText helpPanel = new StyledText(cWhatsNew, SWT.VERTICAL | SWT.HORIZONTAL); helpPanel.setEditable(false); try { helpPanel.setRedraw(false); helpPanel.setWordWrap(false); helpPanel.setFont(monospace); black = ColorCache.getColor(display, 0, 0, 0); white = ColorCache.getColor(display, 255, 255, 255); light = ColorCache.getColor(display, 200, 200, 200); grey = ColorCache.getColor(display, 50, 50, 50); green = ColorCache.getColor(display, 30, 80, 30); blue = ColorCache.getColor(display, 20, 20, 80); int style; boolean setStyle; helpPanel.setForeground(grey); String[] lines = sWhatsNew.split("\\r?\\n"); for (int i = 0; i < lines.length; i++) { String line = lines[i]; setStyle = false; fg = grey; bg = white; style = SWT.NORMAL; char styleChar; String text; if (line.length() < 2) { styleChar = ' '; text = " " + lineSeparator; } else { styleChar = line.charAt(0); text = line.substring(1) + lineSeparator; } switch (styleChar) { case '*': text = " * " + text; fg = green; setStyle = true; break; case '+': text = " " + text; fg = black; bg = light; style = SWT.BOLD; setStyle = true; break; case '!': style = SWT.BOLD; setStyle = true; break; case '@': fg = blue; setStyle = true; break; case '$': bg = blue; fg = white; style = SWT.BOLD; setStyle = true; break; case ' ': text = " " + text; break; default: text = styleChar + text; } helpPanel.append(text); if (setStyle) { int lineCount = helpPanel.getLineCount() - 1; int charCount = helpPanel.getCharCount(); // System.out.println("Got Linecount " + lineCount + ", Charcount " + charCount); int lineOfs = helpPanel.getOffsetAtLine(lineCount - 1); int lineLen = charCount - lineOfs; // System.out.println("Setting Style : " + lineOfs + ", " + lineLen); helpPanel.setStyleRange(new StyleRange(lineOfs, lineLen, fg, bg, style)); helpPanel.setLineBackground(lineCount - 1, 1, bg); } } helpPanel.setRedraw(true); } catch (Exception e) { System.out.println("Unable to load help contents because:" + e); //e.printStackTrace(); } } if (labelLoading != null && !labelLoading.isDisposed()) { labelLoading.dispose(); } shell.layout(true, true); } private void getWhatsNew(final int phase) { String helpFile = null; if (phase == 1) { helpFile = MessageText.getString("window.welcome.file"); if (!helpFile.toLowerCase().startsWith(Constants.SF_WEB_SITE)) { getWhatsNew(2); return; } } else if (phase == 2) { helpFile = URL_WHATSNEW + "?version=" + Constants.AZUREUS_VERSION + "&locale=" + Locale.getDefault().toString() + "&ui=" + COConfigurationManager.getStringParameter("ui"); } else { helpFile = MessageText.getString("window.welcome.file"); InputStream stream; stream = getClass().getResourceAsStream(helpFile); if (stream == null) { String helpFullPath = "/org/gudy/azureus2/internat/whatsnew/" + helpFile; stream = getClass().getResourceAsStream(helpFullPath); } if (stream == null) { stream = getClass().getResourceAsStream("/ChangeLog.txt"); } if (stream == null) { sWhatsNew = "Welcome Window: Error loading resource: " + helpFile; } else { try { sWhatsNew = FileUtil.readInputStreamAsString(stream, 65535, "utf8"); stream.close(); } catch (IOException e) { Debug.out(e); } } setWhatsNew(); return; } final String url = helpFile; new AEThread2("getWhatsNew", true) { public void run() { String s; ResourceDownloaderFactory rdf = ResourceDownloaderFactoryImpl.getSingleton(); try { ResourceDownloader rd = rdf.create(new URL(url)); InputStream is = rd.download(); int length = is.available(); byte data[] = new byte[length]; is.read(data); is.close(); s = new String(data); } catch (ResourceDownloaderException rde) { // We don't need a stack trace - it's arguable that we even need any // errors at all - the below line is better, but suppressed output might // be better. //Debug.outNoStack("Error downloading from " + url + ", " + rde, true); s = ""; } catch (Exception e) { Debug.out(e); s = ""; } sWhatsNew = s; if (sWhatsNew == null || sWhatsNew.length() == 0) { getWhatsNew(phase + 1); return; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (cWhatsNew != null && !cWhatsNew.isDisposed()) { setWhatsNew(); } } }); } }.start(); } private void close() { monospace.dispose(); shell.dispose(); } public static void main(String[] args) { //Locale.setDefault(new Locale("nl", "NL")); //MessageText.changeLocale(new Locale("nl", "NL")); System.out.println(Locale.getDefault().getCountry()); new WelcomeWindow(null); Display display = Display.getDefault(); while (true) { if (!display.readAndDispatch()) { display.sleep(); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/networks/0000755000175000017500000000000011310377636021272 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java0000644000175000017500000001671711275141740026041 0ustar adrianadrian/* * Created on 14-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.networks; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AENetworkClassifier; import org.gudy.azureus2.core3.util.AENetworkClassifierListener; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; /** * @author parg * */ public class SWTNetworkSelection implements AENetworkClassifierListener { public SWTNetworkSelection() { AENetworkClassifier.addListener( this ); } public String[] selectNetworks( final String description, final String[] tracker_networks ) { final Display display = SWTThread.getInstance().getDisplay(); if ( display.isDisposed()){ return( null ); } final AESemaphore sem = new AESemaphore("NetworkClassifier"); final classifierDialog[] dialog = new classifierDialog[1]; try{ Utils.execSWTThread( new AERunnable() { public void runSupport() { dialog[0] = new classifierDialog( sem, display, description, tracker_networks ); } }); }catch( Throwable e ){ Debug.printStackTrace( e ); return( null ); } sem.reserve(); return( dialog[0].getSelection()); } protected class classifierDialog { protected Shell shell; protected AESemaphore sem; protected String[] selection; private Button[] checkboxes; protected classifierDialog( AESemaphore _sem, Display display, String description, String[] tracker_networks ) { sem = _sem; if ( display.isDisposed()){ sem.releaseForever(); return; } shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); Utils.setShellIcon(shell); shell.setText(MessageText.getString("window.networkselection.title")); GridLayout layout = new GridLayout(); layout.numColumns = 3; shell.setLayout (layout); GridData gridData; Label info_label = new Label(shell,SWT.NULL); info_label.setText(MessageText.getString("window.networkselection.info")); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 3; info_label.setLayoutData(gridData); // line Label labelSeparator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; labelSeparator.setLayoutData(gridData); // description Label desc_label = new Label(shell,SWT.NULL); desc_label.setText(MessageText.getString("window.networkselection.description")); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; desc_label.setLayoutData(gridData); Label desc_value = new Label(shell,SWT.NULL); desc_value.setText(description); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; desc_value.setLayoutData(gridData); // networks checkboxes = new Button[AENetworkClassifier.AT_NETWORKS.length]; for (int i=0;i * false = image was the same (doesn't mean image bits were the same) */ public boolean setGraphic(Image img) { boolean bImageSet = (image != img); boolean bDoRedraw = (img == null); if (bImageSet) { // redraw if size changed to wipe area if (!bDoRedraw && image != null && !image.isDisposed() && !img.isDisposed() && !image.getBounds().equals(img.getBounds())) bDoRedraw = true; image = img; } //doPaint(bDoRedraw); return bImageSet; } public boolean needsPainting() { return true; } /** * Clear old image from screen (if needed) and paint image * * @param bForceClear Force clear of area before drawing. Normally, a * non-transparent image will draw overtop of the * area, instead of first clearing it. */ private void doPaint(boolean bForceClear) { if (image == null || image.isDisposed()) return; if (bForceClear || image.getImageData().getTransparencyType() != SWT.TRANSPARENCY_NONE) { // images with transparency need their area cleared first, otherwise we // end up multiplying values (alpha type) or not clearing pixels // (all types) Table table = getTable(); Rectangle bounds = getBoundsForCanvas(); //In case item isn't displayed bounds is null if (bounds == null) return; // This should trigger a doPaint(gc) table.redraw(bounds.x, bounds.y, bounds.width, bounds.height, true); } else { doPaint((GC) null); } } /** Paint the bar without updating it's data. Unless the size changed. */ public void doPaint(GC gc) { if (neverDrawn) { if (gc == null) return; neverDrawn = false; } //Compute bounds ... Rectangle bounds = getBoundsForCanvas(); //In case item isn't displayed bounds is null if (bounds == null || image == null || image.isDisposed()) { //System.out.println(row.getIndex() + " nb"); return; } Table table = getTable(); // System.out.println("doPnt#" + row.getIndex()+": " + // ((gc == null) ? "GC NULL" : String.valueOf(gc.getClipping())) + // "ta="+table.getClientArea()+";bounds="+bounds); Rectangle imageBounds = image.getBounds(); if (imageBounds.width <= 0 || imageBounds.height <= 0 || bounds.width <= 0 || bounds.height <= 0) { //System.out.println(row.getIndex() + " < 0"); return; } Rectangle tableBounds = table.getClientArea(); // Cocoa calls paintitem while row is below tablearea, and painting there // is valid! if (!Utils.isCocoa) { if (bounds.y + bounds.height - tableBounds.y < table.getHeaderHeight() || bounds.y > tableBounds.height) { //System.out.println("doPnt#" + row.getIndex() + ": " // + (bounds.y + bounds.height - tableBounds.y) + "<" + tableBounds.y // + " || " + bounds.y + " > " + tableBounds.height); return; } } boolean fits = (imageBounds.width == bounds.width && imageBounds.height == bounds.height); if (orientation == SWT.FILL || fits) { if (fits) { //System.out.println("doPaint() sizewrong #"+row.getIndex()+ ". Image="+imageBounds +";us="+bounds); /**/ // Enable this for semi-fast visual update with some flicker boolean ourGC = (gc == null); if (ourGC) { gc = new GC(table); } if (gc != null) { gc.drawImage(image, bounds.x, bounds.y); if (ourGC) { gc.dispose(); } } // _OR_ enable refresh() for slower visual update with lots of flicker //refresh(); // OR, disable both and image will be updated on next graphic bar update // TODO: make config option to choose /**/ //invalidate(); return; } } else { if (imageBounds.width < bounds.width) { if (orientation == SWT.CENTER) bounds.x += (bounds.width - imageBounds.width) / 2; else if (orientation == SWT.RIGHT) bounds.x = (bounds.x + bounds.width) - imageBounds.width; } if (imageBounds.height < bounds.height) { bounds.y += (bounds.height - imageBounds.height) / 2; } } Rectangle clipping = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); int iMinY = table.getHeaderHeight() + tableBounds.y; if (clipping.y < iMinY) { clipping.height -= iMinY - clipping.y; clipping.y = iMinY; } int iMaxY = tableBounds.height + tableBounds.y; if (clipping.y + clipping.height > iMaxY) clipping.height = iMaxY - clipping.y + 1; if (clipping.width <= 0 || clipping.height <= 0) { //System.out.println(row.getIndex() + " clipping="+clipping + ";" + iMinY + ";" + iMaxY + ";tca=" + tableBounds); return; } boolean ourGC = (gc == null); if (ourGC) { gc = new GC(table); } try { Point srcStart = new Point(clipping.x - bounds.x, clipping.y - bounds.y); Rectangle dstRect = new Rectangle(clipping.x, clipping.y, imageBounds.width - srcStart.x, imageBounds.height - srcStart.y); Utils.drawImage(gc, image, srcStart, dstRect, clipping, 0, 0, false); } finally { if (ourGC) { gc.dispose(); } } } public void dispose() { super.dispose(); image = null; } /** Calculate the bounds of the receiver should be drawing in * @return what size/position the canvas should be */ public Rectangle getBoundsForCanvas() { Rectangle bounds = getBounds(); if(bounds == null) return null; bounds.y += marginHeight; bounds.height -= (marginHeight * 2); bounds.x += marginWidth; bounds.width -= (marginWidth * 2); return bounds; } public Point getSize() { Rectangle bounds = getBounds(); if(bounds == null) return new Point(0, 0); return new Point(bounds.width - (marginWidth * 2), bounds.height - (marginHeight * 2)); } public void invalidate() { } public int getMarginHeight() { return marginHeight; } public int getMarginWidth() { return marginWidth; } public void setMargin(int width, int height) { if (width >= 0) { marginWidth = width; } if (height >= 0) { marginHeight = height; } } public int getOrientation() { return orientation; } public void setOrientation(int orientation) { this.orientation = orientation; } public Image getBackgroundImage() { Image imageRowBG = row.getBackgroundImage(); if (imageRowBG != null) { Rectangle bounds = getBounds(); int wInside = bounds.width - (marginWidth * 2); int hInside = bounds.height - (marginHeight * 2); Image imageCellBG = new Image(Display.getDefault(), wInside, hInside); GC gc = new GC(imageCellBG); gc.drawImage(imageRowBG, bounds.x + marginWidth, 0 + marginHeight, wInside, hInside, 0, 0, wInside, hInside); gc.dispose(); return imageCellBG; } Table table = row.getTable(); Rectangle bounds = getBounds(); if (bounds.isEmpty()) { return null; } Image image = new Image(Display.getDefault(), bounds.width - (marginWidth * 2), bounds.height - (marginHeight * 2)); GC gc = new GC(image); gc.setForeground(getBackground()); gc.setBackground(getBackground()); gc.fillRectangle(0, 0, bounds.width, bounds.height); gc.dispose(); return image; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/BufferedGraphicTableItem2.java0000644000175000017500000002701011017135252027325 0ustar adrianadrian /* * File : BufferedGraphicTableItem.java * Created : 24 nov. 2003 * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.components; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Canvas; import org.gudy.azureus2.ui.swt.components.BufferedTableRow; /** Draws an image at a column in a row of a table using a Canvas. * In comparison to BufferedGraphicTable, which uses direct paints to table, * Pros: * - Skip the table redrawing and overdrawing bugs in 3.0M8 (or greater?) * * Cons: * - Lag * - A lot more control is needed to do the same thing * * @see BufferedGraphicTable * @author TuxPaper * */ public abstract class BufferedGraphicTableItem2 extends BufferedTableItemImpl implements BufferedGraphicTableItem { private int marginHeight = 1; private int marginWidth = 1; private int orientation = SWT.CENTER; /** Canvas that image is drawn on */ Canvas cBlockView = null; //The Buffered image private Image image; /** Used for !fillCell */ private Color lastBackColor = null; public BufferedGraphicTableItem2(BufferedTableRow row,int position) { super(row, position); } private void createBlockView() { // For !fillCell, we draw the background manually, because some OSes // send a paint listener after setBackground() (causing another doPaint), // and some do not. int iStyle = SWT.NO_FOCUS | SWT.NO_BACKGROUND; if (orientation == SWT.FILL) { iStyle |= SWT.NO_REDRAW_RESIZE; } cBlockView = new Canvas(getTable(), iStyle); cBlockView.setBackground(null); cBlockView.addPaintListener(new PaintListener() { public void paintControl(PaintEvent event) { if (event.width == 0 || event.height == 0) return; doPaint(event.gc.getClipping()); } }); //cBlockView.moveAbove(null); cBlockView.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { Table table = getTable(); Rectangle r = cBlockView.getBounds(); TableItem[] item = { table.getItem(new Point(r.x, r.y)) }; if (item[0] != null) { table.setSelection(item); } table.setFocus(); } public void mouseUp(MouseEvent e) { getTable().setFocus(); } } ); } /** Retrieve the graphic related to this table item. * @return the Image that is draw in the cell, or null if there is none. */ public Image getGraphic() { return image; } /* Sets image to be drawn. * @param img Image to be stored & drawn * @return true - image was changed. false = image was the same */ public boolean setGraphic(Image img) { boolean bImageSet = (image != img); if (bImageSet) { if (cBlockView == null) { createBlockView(); } image = img; } if (img != null) { doPaint((Rectangle)null); } return bImageSet; } public boolean needsPainting() { return true; } public void locationChanged() { if (cBlockView == null || cBlockView.isDisposed()) return; Rectangle bounds = getBoundsForCanvas(); //In case item isn't displayed bounds is null if (bounds == null || image == null || image.isDisposed()) { return; } // moveAbove reduces the # redraws //cBlockView.moveAbove(null); cBlockView.setLocation(bounds.x, bounds.y); } /** Inherited doPaint(GC) call. This is called when the Table needs * repainting. Since we capture the Canvas' paint, most of the Table * repainting can be ignored. Cases where the cell bounds or background * color changed, however, require action. */ public void doPaint(GC gc) { if (cBlockView == null || cBlockView.isDisposed()) return; //Compute bounds ... Rectangle bounds = getBoundsForCanvas(); //In case item isn't displayed bounds is null if (bounds == null || image == null || image.isDisposed()) { return; } Rectangle canvasBounds = cBlockView.getBounds(); if (canvasBounds.x != bounds.x || canvasBounds.y != bounds.y) { //cBlockView.moveAbove(null); cBlockView.setLocation(bounds.x, bounds.y); canvasBounds = cBlockView.getBounds(); //debugOut("doPaint(GC): move cBlockView to " + bounds.x + "x" + bounds.y, false); } Table table = getTable(); Rectangle tableBounds = table.getClientArea(); if (tableBounds.y < table.getHeaderHeight()) { tableBounds.y = table.getHeaderHeight(); } Rectangle rNewCanvas = bounds.intersection(tableBounds); //debugOut("doPaint(gc) rNewCanvas="+rNewCanvas+";canvasBounds="+canvasBounds+";tableBounds="+tableBounds, false); if (rNewCanvas.width <= 0 || rNewCanvas.height <= 0) { return; } if (!rNewCanvas.equals(canvasBounds) || (orientation != SWT.FILL && !getRowBackground(table).equals(lastBackColor))) { rNewCanvas.x -= canvasBounds.x; rNewCanvas.y -= canvasBounds.y; doPaint(rNewCanvas); } } /** Paint the bar without updating it's data. Unless the size changed. */ public void doPaint(Rectangle clipping) { //debugOut("doPaint() clipping="+clipping, false); if (cBlockView == null || cBlockView.isDisposed()) return; Table table = getTable(); //Compute bounds ... Rectangle bounds = getBoundsForCanvas(); //In case item isn't displayed bounds is null if (bounds == null || image == null || image.isDisposed()) { return; } Rectangle canvasBounds = cBlockView.getBounds(); //debugOut("Block:"+canvasBounds+";cell:"+bounds,false); if (canvasBounds.x != bounds.x || canvasBounds.y != bounds.y) { //cBlockView.moveAbove(null); cBlockView.setLocation(bounds.x, bounds.y); canvasBounds = cBlockView.getBounds(); //debugOut("doPaint(clipping): move cBlockView to " + bounds.x + "x" + bounds.y, false); } if (bounds.width != canvasBounds.width || bounds.height != canvasBounds.height) { cBlockView.setSize(bounds.width, bounds.height); canvasBounds = cBlockView.getBounds(); } //debugOut("doPaint()" + ((gc == null) ? "GC NULL" : String.valueOf(gc.getClipping())) + // "ta="+table.getClientArea()+";bounds="+bounds, false); if (orientation == SWT.FILL) { Rectangle imageBounds = image.getBounds(); if (imageBounds.width != bounds.width || imageBounds.height != bounds.height) { // Enable this for semi-fast visual update with some flicker cBlockView.setSize(bounds.width, bounds.height); GC gc = new GC(cBlockView); gc.drawImage(image, 0, 0, imageBounds.width, imageBounds.height, 0, 0, bounds.width, bounds.height); gc.dispose(); /* // _OR_ enable refresh() for slower visual update with lots of flicker //refresh(); // OR, disable both and image will be updated on next graphic bar update // TODO: make config option to choose */ invalidate(); return; } } if (clipping == null) { clipping = new Rectangle(0, 0, bounds.width, bounds.height); } Rectangle tableBounds = table.getClientArea(); if (tableBounds.y < table.getHeaderHeight()) { tableBounds.y = table.getHeaderHeight(); } //debugOut("doPaint() tableBounds="+tableBounds+";canvasBounds="+canvasBounds+";clipping="+clipping, false); tableBounds.x -= canvasBounds.x; tableBounds.y -= canvasBounds.y; clipping = clipping.intersection(tableBounds); //debugOut("doPaint() clipping="+clipping, false); if (clipping.x + clipping.width <= 0 && clipping.y + clipping.height <= 0) { return; } GC gc = new GC(cBlockView); if (orientation == SWT.FILL) { gc.setClipping(clipping); gc.drawImage(image, 0, 0); } else { /* // Grab a pixel beside the cell and draw that as our background // Advantage: paints correct color when hilighted and not in focus // Disadvatage: doesn't always work! GC gc2 = new GC(table); Image i = new Image(table.getDisplay(), 1, 1); gc2.copyArea(i, bounds.x + bounds.width + 1, bounds.y + (bounds.width / 2)); gc2.dispose(); gc.drawImage(i, 0, 0, 1, 1, 0,0, rBlockViewBounds.width, rBlockViewBounds.height); */ lastBackColor = getRowBackground(table); gc.setBackground(lastBackColor); gc.fillRectangle(clipping); /* Rectangle imageBounds = image.getBounds(); Rectangle r = canvasBounds.intersection(tableBounds); int x = (r.width - imageBounds.width) / 2; if (x <= 0) x = 0; clipping.x += x; */ int x = 0; gc.setClipping(clipping); gc.drawImage(image, x, 0); } gc.dispose(); } /** Don't forget to call super.dispose()! */ public void dispose() { super.dispose(); image = null; if (cBlockView != null) { if (!cBlockView.isDisposed()) cBlockView.dispose(); cBlockView = null; } } /** Calculate the bounds of the receiver should be drawing in * @return what size/position the canvas should be */ public Rectangle getBoundsForCanvas() { Rectangle bounds = getBounds(); if(bounds == null) return null; bounds.y += marginHeight; bounds.height -= (marginHeight * 2); bounds.x += marginWidth; bounds.width -= (marginWidth * 2); if (bounds.width <= 0 || bounds.height <= 0) return null; return bounds; } public Point getSize() { Rectangle bounds = getBounds(); if(bounds == null) return new Point(0, 0); return new Point(bounds.width - (marginWidth * 2), bounds.height - (marginHeight * 2)); } private Color getRowBackground(Table table) { if (row.isSelected() && false) { if (table.isFocusControl()) return table.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION); else return table.getDisplay().getSystemColor(SWT.COLOR_GRAY); } else { return getBackground(); } } public void invalidate() { } public int getMarginHeight() { return marginHeight; } public int getMarginWidth() { return marginWidth; } public void setMargin(int width, int height) { if (width >= 0) { marginWidth = width; } if (height >= 0) { marginHeight = height; } } public int getOrientation() { return orientation; } public void setOrientation(int orientation) { this.orientation = orientation; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/BufferedGraphicTableItem.java0000644000175000017500000000312610566764012027257 0ustar adrianadrian/* * Created: 2004/May/26 * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details ( * see the LICENSE file ). * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, 8 Alle Lenotre, La Grille Royale, * 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.components; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Image; public abstract interface BufferedGraphicTableItem { public abstract int getMarginWidth(); public abstract int getMarginHeight(); public abstract void setMargin(int width, int height); /** Orientation of cell. SWT.LEFT, SWT.RIGHT, SWT.CENTER, or SWT.FILL. * When SWT.FILL, update() will be called when the size of the cell has * changed. */ public abstract void setOrientation(int orientation); public abstract int getOrientation(); public abstract Point getSize(); public abstract boolean setGraphic(Image img); public abstract Image getGraphic(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/StringListChooser.java0000644000175000017500000001230011012724464026061 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.components; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; public class StringListChooser { private Display display; private Shell shell; private Label label; private Combo combo; private String result; public StringListChooser(final Shell parentShell) { result = null; display = parentShell.getDisplay(); if(display == null || display.isDisposed()) return; display.syncExec(new Runnable() { public void run() { createShell(parentShell); } }); } private void createShell(Shell parentShell) { shell = ShellFactory.createShell(display,SWT.APPLICATION_MODAL | SWT.BORDER | SWT.TITLE | SWT.CLOSE); Utils.setShellIcon(shell); GridLayout layout = new GridLayout(); layout.numColumns = 2; shell.setLayout(layout); GridData data; label = new Label(shell,SWT.WRAP); combo = new Combo(shell,SWT.READ_ONLY); Button ok = new Button(shell,SWT.PUSH); ok.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { result = combo.getText(); shell.dispose(); } }); ok.setText(MessageText.getString("Button.ok")); Button cancel = new Button(shell,SWT.PUSH); cancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { result = null; shell.dispose(); } }); cancel.setText(MessageText.getString("Button.cancel")); shell.addListener(SWT.Dispose,new Listener() { public void handleEvent(Event arg0) { } }); data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = 2; data.heightHint = 30; label.setLayoutData(data); data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = 2; combo.setLayoutData(data); data = new GridData(); data.widthHint = 80; data.grabExcessHorizontalSpace = true; data.grabExcessVerticalSpace = true; data.verticalAlignment = SWT.END; data.horizontalAlignment = SWT.END; ok.setLayoutData(data); data = new GridData(); data.grabExcessVerticalSpace = true; data.verticalAlignment = SWT.END; data.widthHint = 80; cancel.setLayoutData(data); shell.setSize(300,150); shell.layout(); Utils.centerWindowRelativeTo(shell,parentShell); } public void setTitle(final String title) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if(display == null || display.isDisposed()) return; shell.setText(title); } }); } public void setText(final String text) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if(display == null || display.isDisposed()) return; label.setText(text.replaceAll("&", "&&")); } }); } public void addOption(final String option) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if(display == null || display.isDisposed()) return; combo.add(option); if(combo.getItemCount() == 1) { combo.setText(option); } } }); } public String open() { if(display == null || display.isDisposed()) return null; Utils.execSWTThread(new AERunnable() { public void runSupport() { if(display == null || display.isDisposed()) { return; } try{ shell.open(); while (!shell.isDisposed()) if (!display.readAndDispatch()) display.sleep(); }catch( Throwable e ){ Debug.printStackTrace( e ); } } }); return result; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/ControlUtils.java0000644000175000017500000000423111033177604025102 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.components; /* * Created on 8-Feb-2005 * Created by James Yeh * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.config.COConfigurationManager; /** * General utility methods for SWT controls and components * @version 1.0 * @author James Yeh * @deprecated JFace has higher-level classes and fields to cover this */ public final class ControlUtils { private static boolean smallOSXControl = COConfigurationManager.getBooleanParameter("enable_small_osx_fonts"); /** *

Gets the margin between buttons

*

The margin may vary between platforms, as specified by their guidelines

* @return Margin */ public static int getButtonMargin() { if(Constants.isOSX) return (smallOSXControl) ? 10 : 12; else if(Constants.isWindows) return 6; else return 6; // this is gnome's } /** *

Gets the minimum width of a button in a dialog (usually for alerts)

*

The size may vary between platforms, as specified by their guidelines

* @return Width */ public static int getDialogButtonMinWidth() { if(Constants.isOSX) return 90; else return 70; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/Legend.java0000644000175000017500000001654010731046776023656 0ustar adrianadrian/* * Created on 13-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.components; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowData; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.ColorDialog; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.config.impl.ConfigurationManager; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.swt.utils.ColorCache; /** * * TODO: have a callback when color changes */ public class Legend { /** * Create a legend containing a modifyable color box and description * * @param panel Where to add legend to * @param blockColors array of colors for each legend entry. This * array WILL BE modified if the user changes the color * @param keys array of keys for each legend entry * @return The composite containing the legend */ public static Composite createLegendComposite(Composite panel, Color[] blockColors, String[] keys) { Object layout = panel.getLayout(); Object layoutData = null; if (layout instanceof GridLayout) layoutData = new GridData(GridData.FILL_HORIZONTAL); return createLegendComposite(panel, blockColors, keys, layoutData); } /** * Create a legend containing a modifyable color box and description * * @param panel Where to add legend to * @param blockColors array of colors for each legend entry. This * array WILL BE modified if the user changes the color * @param keys array of keys for each legend entry * @param layoutData How to layout the legend (ie. GridData, LayoutData, etc) * @return The composite containing the legend */ public static Composite createLegendComposite(final Composite panel, final Color[] blockColors, final String[] keys, Object layoutData) { final ConfigurationManager config = ConfigurationManager.getInstance(); if (blockColors.length != keys.length) return null; final Color[] defaultColors = new Color[blockColors.length]; final ParameterListener[] paramListeners = new ParameterListener[keys.length]; System.arraycopy(blockColors, 0, defaultColors, 0, blockColors.length); Composite legend = new Composite(panel, SWT.NONE); if (layoutData != null) legend.setLayoutData(layoutData); RowLayout layout = new RowLayout(SWT.HORIZONTAL); layout.wrap = true; layout.marginBottom = 0; layout.marginTop = 0; layout.marginLeft = 0; layout.marginRight = 0; layout.spacing = 0; legend.setLayout(layout); RowData data; for (int i = 0; i < blockColors.length; i++) { int r = config.getIntParameter(keys[i] + ".red", -1); if (r >= 0) { int g = config.getIntParameter(keys[i] + ".green"); int b = config.getIntParameter(keys[i] + ".blue"); Color color = ColorCache.getColor(panel.getDisplay(), r, g, b); blockColors[i] = color; } Composite colorSet = new Composite(legend, SWT.NONE); colorSet.setLayout(new RowLayout(SWT.HORIZONTAL)); final Canvas cColor = new Canvas(colorSet, SWT.BORDER); cColor.setData("Index", new Integer(i)); // XXX Use paint instead of setBackgrond, because OSX does translucent // crap cColor.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { int i = ((Integer)cColor.getData("Index")).intValue(); e.gc.setBackground(blockColors[i]); e.gc.fillRectangle(e.x, e.y, e.width, e.height); } }); cColor.addMouseListener(new MouseAdapter() { public void mouseUp(MouseEvent e) { Integer iIndex = (Integer)cColor.getData("Index"); if (iIndex == null) return; int index = iIndex.intValue(); if (e.button == 1) { ColorDialog cd = new ColorDialog(panel.getShell()); cd.setRGB(blockColors[index].getRGB()); RGB rgb = cd.open(); if (rgb != null) config.setRGBParameter(keys[index], rgb.red, rgb.green, rgb.blue); } else { config.removeRGBParameter(keys[index]); } } }); Label lblDesc = new Label(colorSet, SWT.NULL); Messages.setLanguageText(lblDesc, keys[i]); data = new RowData(); data.width = 20; data.height = lblDesc.computeSize(SWT.DEFAULT, SWT.DEFAULT).y - 3; cColor.setLayoutData(data); // If color changes, update our legend config.addParameterListener(keys[i],paramListeners[i] = new ParameterListener() { public void parameterChanged(String parameterName) { for (int j = 0; j < keys.length; j++) { if (keys[j].equals(parameterName)) { final int index = j; final int r = config.getIntParameter(keys[j] + ".red", -1); if (r >= 0) { final int g = config.getIntParameter(keys[j] + ".green"); final int b = config.getIntParameter(keys[j] + ".blue"); final RGB rgb = new RGB(r, g, b); if (blockColors[j].isDisposed() || !rgb.equals(blockColors[j].getRGB())) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (panel == null || panel.isDisposed()) return; Color color = ColorCache.getColor(panel.getDisplay(), r, g, b); blockColors[index] = color; cColor.redraw(); } }); } } else { if (blockColors[j].isDisposed() || !blockColors[j].equals(defaultColors[j])) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (panel == null || panel.isDisposed()) return; blockColors[index] = defaultColors[index]; cColor.redraw(); } }); } } } } } }); } legend.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { // We don't want to give them disposed colors // Restore defaults in case blockColors is a static or is used // afterwards, or if the view wants to dispose of the old colors. for (int i = 0; i < blockColors.length; i++) blockColors[i] = defaultColors[i]; for (int i = 0; i < keys.length;i++) config.removeParameterListener(keys[i], paramListeners[i]); } }); return legend; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/BufferedToolItem.java0000644000175000017500000000372310414703230025635 0ustar adrianadrian/* * File : BufferedToolItem.java * Created : 08-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.components; /** * @author parg * */ import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; public class BufferedToolItem extends BufferedWidget { protected ToolItem item; public BufferedToolItem( ToolBar tool_bar, int attributes ) { super( new ToolItem( tool_bar, attributes )); item = (ToolItem)getWidget(); } public void setEnabled( boolean b ) { if ( item.isDisposed() || item.getEnabled() == b ){ return; } item.setEnabled( b ); } public void setSelection( boolean b ) { if ( item.isDisposed() || item.getSelection() == b ){ return; } item.setSelection( b ); } public void setImage( Image i ) { if (i != null) i.setBackground(item.getParent().getBackground()); item.setImage(i); } public Object getData( String key ) { return( item.getData(key)); } public void setData( String key, Object d ) { item.setData(key,d); } public void addListener( int type, Listener l ) { item.addListener( type, l ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/BufferedWidget.java0000644000175000017500000000235707760424710025343 0ustar adrianadrian/* * File : BufferedWidget.java * Created : 24-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.components; /** * @author parg * */ import org.eclipse.swt.widgets.Widget; public class BufferedWidget { protected Widget widget; protected Object data; protected BufferedWidget( Widget _widget ) { widget = _widget; } public Widget getWidget() { return( widget ); } public void setData( Object d ) { data = d; } public Object getData() { return( data ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/graphics/0000755000175000017500000000000011310377636023403 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/graphics/PieUtils.java0000644000175000017500000000425511033177734026011 0ustar adrianadrian/* * Created on 19 nov. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.components.graphics; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.ui.swt.mainwindow.Colors; /** * @author Olivier Chalouhi * */ public class PieUtils { private static Image computePie(Display display,int width,int height,int percent) { Image image = new Image(display,width,height); GC gcImage = new GC(image); gcImage.setForeground(Colors.blue); int angle = (percent * 360) / 100; gcImage.setBackground(Colors.blues[Colors.BLUES_MIDDARK]); gcImage.fillArc(0,0,width,height,90-angle,angle); gcImage.drawOval(0 , 0 , width-1, height-1); gcImage.dispose(); return image; } public static void drawPie(GC gc,int x, int y,int width,int height,int percent) { Color background = gc.getBackground(); gc.setForeground(Colors.blue); int angle = (percent * 360) / 100; if(angle<4) angle = 0; // workaround fillArc rendering bug gc.setBackground(Colors.white); gc.fillArc(x,y,width,height,0,360); gc.setBackground(background); gc.fillArc(x,y,width,height,90,angle*-1); gc.drawOval(x , y , width-1, height-1); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/graphics/Plot3D.java0000644000175000017500000002247710757016336025370 0ustar adrianadrian/* * Created on Jun 26, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.components.graphics; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Canvas; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.HSLColor; public class Plot3D implements Graphic, ParameterListener { private Canvas canvas; private String title = ""; private String[] labels; private ValueFormater[] formatters; private int internalLoop; private int graphicsUpdate; private Point oldSize; protected Image bufferImage; protected AEMonitor this_mon = new AEMonitor( "Plot3D" ); private int[][] values = new int[0][]; private Color[] colours; public Plot3D( String[] _labels, ValueFormater[] _formatters ) { labels = _labels; formatters = _formatters; COConfigurationManager.addAndFireParameterListener( "Graphics Update", this ); parameterChanged("Graphics Update"); } public void initialize( Canvas _canvas ) { canvas = _canvas; Device device = canvas.getDisplay(); colours = new Color[16]; HSLColor hsl = new HSLColor(); hsl.initHSLbyRGB( 130,240,240 ); int step = 128 / colours.length; int hue = colours.length * step; for (int i=0;i 2000 || bounds.height > 2000) return; boolean sizeChanged = (oldSize == null || oldSize.x != bounds.width || oldSize.y != bounds.height); oldSize = new Point(bounds.width,bounds.height); internalLoop++; if(internalLoop > graphicsUpdate){ internalLoop = 0; } if (internalLoop == 0 || sizeChanged ){ drawPlot(); } GC gc = new GC(canvas); gc.drawImage(bufferImage,bounds.x,bounds.y); gc.dispose(); } protected void drawPlot() { final int PAD_TOP = 10; final int PAD_BOTTOM = 10; final int PAD_RIGHT = 10; final int PAD_LEFT = 10; final double ANGLE_RADS = 0.7; final double ANGLE_TAN = Math.tan( ANGLE_RADS ); try{ this_mon.enter(); Rectangle bounds = canvas.getClientArea(); if ( bufferImage != null && ! bufferImage.isDisposed()){ bufferImage.dispose(); } bufferImage = new Image( canvas.getDisplay(), bounds ); GC image = new GC( bufferImage ); int max_x = 0; int max_y = 0; int max_z = 0; for (int i=0;i max_x ){ max_x = entry[0]; } if ( entry[1] > max_y ){ max_y = entry[1]; } if ( entry[2] > max_z ){ max_z = entry[2]; } } int usable_width = bounds.width - PAD_LEFT - PAD_RIGHT; int usable_height = bounds.height - PAD_TOP - PAD_BOTTOM; try { image.setAntialias( SWT.ON ); } catch (Exception e) { // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others } double x_ratio = ((float)usable_width-((usable_height/2)/ANGLE_TAN)) / max_x; double y_ratio = ((float)usable_height/2) / max_y; double z_ratio = ((float)usable_height/2) / max_z; // grid int x_axis_left_x = PAD_LEFT; int x_axis_left_y = usable_height + PAD_TOP; int x_axis_right_x = PAD_LEFT + usable_width; int x_axis_right_y = usable_height + PAD_TOP; int y_axis_left_x = PAD_LEFT; int y_axis_left_y = usable_height + PAD_TOP; int y_axis_right_x = PAD_LEFT + (int)((usable_height/2) / ANGLE_TAN ); int y_axis_right_y = usable_height / 2; int z_axis_bottom_x = PAD_LEFT; int z_axis_bottom_y = usable_height + PAD_TOP; int z_axis_top_x = PAD_LEFT; int z_axis_top_y = PAD_TOP + usable_height / 2; Rectangle old_clip = image.getClipping(); image.setClipping( new Rectangle( PAD_LEFT, PAD_RIGHT, usable_width, usable_height )); image.setForeground( Colors.light_grey ); int x_lines = 10; for (int i=1;i= ENTRIES){ currentPosition = 0; } }finally{ this_mon.exit(); } } public void refresh() { if(drawCanvas == null || drawCanvas.isDisposed()) return; Rectangle bounds = drawCanvas.getClientArea(); if(bounds.height < 30 || bounds.width < 100 || bounds.width > 2000 || bounds.height > 2000) return; boolean sizeChanged = (oldSize == null || oldSize.x != bounds.width || oldSize.y != bounds.height); oldSize = new Point(bounds.width,bounds.height); internalLoop++; if(internalLoop > graphicsUpdate) internalLoop = 0; if(internalLoop == 0 || sizeChanged) { drawChart(sizeChanged); } GC gc = new GC(drawCanvas); gc.drawImage(bufferImage,bounds.x,bounds.y); gc.dispose(); } protected void drawChart(boolean sizeChanged) { try{ this_mon.enter(); drawScale(sizeChanged); Rectangle bounds = drawCanvas.getClientArea(); //If bufferedImage is not null, dispose it if(bufferImage != null && ! bufferImage.isDisposed()) bufferImage.dispose(); bufferImage = new Image(drawCanvas.getDisplay(),bounds); GC gcImage = new GC(bufferImage); gcImage.drawImage(bufferScale,0,0); int oldAverage = 0; int[] oldTargetValues = new int[all_values.length]; int[] maxs = new int[all_values.length]; for(int x = 0 ; x < bounds.width - 71 ; x++) { int position = currentPosition - x -1; if(position < 0) position+= 2000; for (int z=0;z maxs[z]){ maxs[z] = value; } } } int max = 0; for (int i=0;i max) { max = maxs[i]; } } scale.setMax(max); int maxHeight = scale.getScaledValue(max); for(int x = 0 ; x < bounds.width - 71 ; x++) { int position = currentPosition - x -1; if(position < 0) position+= 2000; int xDraw = bounds.width - 71 - x; gcImage.setLineWidth(1); for (int z=0;z 1 ){ int h1 = bounds.height - scale.getScaledValue(targetValue) - 2; int h2 = bounds.height - scale.getScaledValue(oldTargetValue) - 2; gcImage.setForeground( z <= 2 ? colors[z+1] : colors[3]); gcImage.drawLine(xDraw,h1,xDraw+1, h2); } oldTargetValues[z] = all_values[z][position]; } int average = computeAverage(position); if(x > 6) { int h1 = bounds.height - scale.getScaledValue(average) - 2; int h2 = bounds.height - scale.getScaledValue(oldAverage) - 2; gcImage.setForeground(colors[COLOR_AVERAGE]); gcImage.setLineWidth(2); gcImage.drawLine(xDraw,h1,xDraw+1, h2); } oldAverage = average; } if(nbValues > 0) { int height = bounds.height - scale.getScaledValue(computeAverage(currentPosition-6)) - 2; gcImage.setForeground(colors[COLOR_AVERAGE]); gcImage.drawText(formater.format(computeAverage(currentPosition-6)),bounds.width - 65,height - 12,true); } gcImage.dispose(); }finally{ this_mon.exit(); } } protected int computeAverage(int position) { int sum = 0; int nbItems = 0; for(int i = -5 ; i < 6 ; i++) { int pos = position + i; if (pos < 0) pos += 2000; if(pos >= 2000) pos -= 2000; for(int z=0 ; z < all_values.length ; z++) { sum += all_values[z][pos]; nbItems++; } } return (sum / nbItems); } public void parameterChanged(String parameter) { graphicsUpdate = COConfigurationManager.getIntParameter("Graphics Update"); } public void dispose() { super.dispose(); if(bufferImage != null && ! bufferImage.isDisposed()) { bufferImage.dispose(); } COConfigurationManager.removeParameterListener("Graphics Update",this); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/graphics/Graphic.java0000644000175000017500000000203007767512702025624 0ustar adrianadrian/* * File : Graphic.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.components.graphics; import org.eclipse.swt.widgets.Canvas; /** * @author Olivier * */ public interface Graphic { public void initialize(Canvas canvas); public void refresh(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/graphics/SpeedGraphic.java0000644000175000017500000003106211034200774026575 0ustar adrianadrian/* * File : SpeedGraphic.java * Created : 15 d�c. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.components.graphics; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseTrackListener; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; /** * @author Olivier * */ public class SpeedGraphic extends ScaledGraphic implements ParameterListener { private static final int DEFAULT_ENTRIES = 2000; public static final int COLOR_AVERAGE = 0; public static final int COLOR_MAINSPEED = 1; public static final int COLOR_OVERHEAD = 2; public static final int COLOR_LIMIT = 3; public static final int COLOR_OTHERS = 4; public static final int COLOR_TRIMMED = 5; private static final int ALPHA_FOCUS = 200; private static final int ALPHA_NOFOCUS = 150; public Color[] colors = new Color[] { Colors.red, Colors.blues[Colors.BLUES_MIDDARK], Colors.colorInverse, Colors.blue, Colors.grey, Colors.light_grey }; private int internalLoop; private int graphicsUpdate; private Point oldSize; protected Image bufferImage; private int nbValues = 0; private int maxEntries = DEFAULT_ENTRIES; private int[][] all_values = new int[1][maxEntries]; private int currentPosition; private int alpha = 255; private boolean autoAlpha = false; private SpeedGraphic(Scale scale,ValueFormater formater) { super(scale,formater); currentPosition = 0; COConfigurationManager.addParameterListener("Graphics Update",this); parameterChanged("Graphics Update"); } public void initialize(Canvas canvas) { super.initialize(canvas); canvas.addMouseTrackListener(new MouseTrackListener() { public void mouseHover(MouseEvent e) { } public void mouseExit(MouseEvent e) { if (autoAlpha) { setAlpha(ALPHA_NOFOCUS); } } public void mouseEnter(MouseEvent e) { if (autoAlpha) { setAlpha(ALPHA_FOCUS); } } }); drawCanvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { if (bufferImage != null && !bufferImage.isDisposed()) { Rectangle bounds = bufferImage.getBounds(); if (bounds.width >= e.width && bounds.height >= e.height) { if (alpha != 255) { try { e.gc.setAlpha(alpha); } catch (Exception ex) { // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others } } e.gc.drawImage(bufferImage, e.x, e.y, e.width, e.height, e.x, e.y, e.width, e.height); } } } }); drawCanvas.addListener(SWT.Resize, new Listener() { public void handleEvent(Event event) { drawChart(true); } }); } public static SpeedGraphic getInstance() { return new SpeedGraphic(new Scale(),new ValueFormater() { public String format(int value) { return DisplayFormatters.formatByteCountToBase10KBEtcPerSec(value); } }); } public void addIntsValue(int[] new_values) { try{ this_mon.enter(); if ( all_values.length < new_values.length ){ int[][] new_all_values = new int[new_values.length][]; for (int i=0;i 10000 || bounds.height > 10000) return; // inflate # of values only if necessary if(bounds.width > maxEntries) { try { this_mon.enter(); while(maxEntries < bounds.width) maxEntries += 1000; for(int i=0;i graphicsUpdate) internalLoop = 0; if(internalLoop == 0 || sizeChanged) { drawChart(sizeChanged); } drawCanvas.redraw(); drawCanvas.update(); } protected void drawChart(boolean sizeChanged) { if (drawCanvas == null || drawCanvas.isDisposed() || !drawCanvas.isVisible()) { return; } GC gcImage = null; try { this_mon.enter(); drawScale(sizeChanged); if (bufferScale == null || bufferScale.isDisposed()) return; Rectangle bounds = drawCanvas.getClientArea(); if (bounds.isEmpty()) return; //If bufferedImage is not null, dispose it if (bufferImage != null && !bufferImage.isDisposed()) bufferImage.dispose(); bufferImage = new Image(drawCanvas.getDisplay(), bounds); gcImage = new GC(bufferImage); gcImage.drawImage(bufferScale, 0, 0); int oldAverage = 0; int[] oldTargetValues = new int[all_values.length]; int[] maxs = new int[all_values.length]; for (int x = 0; x < bounds.width - 71; x++) { int position = currentPosition - x - 1; if (position < 0) { position += maxEntries; if (position < 0) { position = 0; } } for (int chartIdx = 0; chartIdx < all_values.length; chartIdx++) { int value = all_values[chartIdx][position]; if (value > maxs[chartIdx]) { maxs[chartIdx] = value; } } } int max = maxs[0]; int max_primary = max; for (int i = 1; i < maxs.length; i++) { int m = maxs[i]; if (i == 1) { if (max < m) { max = m; max_primary = max; } } else { // trim secondary indicators so we don't loose the more important info if (max < m) { if (m <= 2 * max_primary) { max = m; } else { max = 2 * max_primary; break; } } } } scale.setMax(max); int maxHeight = scale.getScaledValue(max); Color background = colors[COLOR_MAINSPEED]; // Colors.blues[Colors.BLUES_DARKEST]; Color foreground = colors[COLOR_MAINSPEED]; //Colors.blues[Colors.BLUES_MIDLIGHT]; for (int x = 0; x < bounds.width - 71; x++) { int position = currentPosition - x - 1; if (position < 0) { position += maxEntries; if (position < 0) { position = 0; } } int xDraw = bounds.width - 71 - x; int height = scale.getScaledValue(all_values[0][position]); gcImage.setForeground(background); gcImage.setBackground(foreground); gcImage.setClipping(xDraw, bounds.height - 1 - height, 1, height); gcImage.fillGradientRectangle(xDraw, bounds.height - 1 - maxHeight, 1, maxHeight, true); gcImage.setClipping(0, 0, bounds.width, bounds.height); if(all_values.length > 1) { gcImage.setForeground(colors[COLOR_OVERHEAD]); height = scale.getScaledValue(all_values[1][position]); Utils.drawStriped(gcImage, xDraw, bounds.height - 1 - height, 1, height, 1, currentPosition, false); } for (int chartIdx = 2; chartIdx < all_values.length; chartIdx++) { int targetValue = all_values[chartIdx][position]; int oldTargetValue = oldTargetValues[chartIdx]; if (x > 1 && (chartIdx == 2 && (targetValue > 0 && oldTargetValue > 0) || (chartIdx > 2 && (targetValue > 0 || oldTargetValue > 0)))) { int trimmed = 0; if (targetValue > max) { targetValue = max; trimmed++; } if (oldTargetValue > max) { oldTargetValue = max; trimmed++; } if (trimmed < 2 || trimmed == 2 && position % 3 == 0) { int h1 = bounds.height - scale.getScaledValue(targetValue) - 2; int h2 = bounds.height - scale.getScaledValue(oldTargetValue) - 2; gcImage.setForeground(chartIdx == 2 ? colors[COLOR_LIMIT] : (trimmed > 0 ? colors[COLOR_TRIMMED] : colors[COLOR_OTHERS])); gcImage.drawLine(xDraw, h1, xDraw + 1, h2); } } oldTargetValues[chartIdx] = all_values[chartIdx][position]; } int average = computeAverage(position); if (x > 6) { int h1 = bounds.height - scale.getScaledValue(average) - 2; int h2 = bounds.height - scale.getScaledValue(oldAverage) - 2; gcImage.setForeground(colors[COLOR_AVERAGE]); gcImage.drawLine(xDraw, h1, xDraw + 1, h2); } oldAverage = average; } if (nbValues > 0) { int height = bounds.height - scale.getScaledValue(computeAverage(currentPosition - 6)) - 2; gcImage.setForeground(colors[COLOR_AVERAGE]); gcImage.drawText(formater.format(computeAverage(currentPosition - 6)), bounds.width - 65, height - 12, true); } } catch (Exception e) { Debug.out("Warning", e); } finally { if (gcImage != null) { gcImage.dispose(); } this_mon.exit(); } } protected int computeAverage(int position) { long sum = 0; for(int i = -5 ; i < 6 ; i++) { int pos = position + i; pos %= maxEntries; if (pos < 0) pos += maxEntries; sum += all_values[0][pos]; } return(int)(sum / 11); } public void parameterChanged(String parameter) { graphicsUpdate = COConfigurationManager.getIntParameter("Graphics Update"); } public void dispose() { super.dispose(); if(bufferImage != null && ! bufferImage.isDisposed()) { bufferImage.dispose(); } COConfigurationManager.removeParameterListener("Graphics Update",this); } private int getAlpha() { return alpha; } public void setAlpha(int alpha) { this.alpha = alpha; if (drawCanvas != null && !drawCanvas.isDisposed()) { drawCanvas.redraw(); } } private boolean isAutoAlpha() { return autoAlpha; } private void setAutoAlpha(boolean autoAlpha) { this.autoAlpha = autoAlpha; if (autoAlpha) { setAlpha(drawCanvas.getDisplay().getCursorControl() == drawCanvas ? ALPHA_FOCUS : ALPHA_NOFOCUS); } } public void setLineColors(Color average, Color speed, Color overhead, Color limit, Color others, Color trimmed) { if (average != null) { colors[COLOR_AVERAGE] = average; } if (speed != null) { colors[COLOR_MAINSPEED] = speed; } if (overhead != null) { colors[COLOR_OVERHEAD] = overhead; } if (limit != null) { colors[COLOR_LIMIT] = limit; } if (others != null) { colors[COLOR_OTHERS] = others; } if (trimmed != null) { colors[COLOR_TRIMMED] = trimmed; } if (drawCanvas != null && !drawCanvas.isDisposed()) { drawCanvas.redraw(); } } public void setLineColors(Color[] newChangeableColorSet) { colors = newChangeableColorSet; if (drawCanvas != null && !drawCanvas.isDisposed()) { drawCanvas.redraw(); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/graphics/ScaledGraphic.java0000644000175000017500000000636011033200140026715 0ustar adrianadrian/* * File : ScaledGraphic.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.components.graphics; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.mainwindow.Colors; /** * @author Olivier * */ public class ScaledGraphic extends BackGroundGraphic { protected Scale scale; protected ValueFormater formater; protected Image bufferScale; private int lastMax; private int update_divider_width = 0; public ScaledGraphic(Scale scale,ValueFormater formater) { this.scale = scale; this.formater = formater; } public void setUpdateDividerWidth(int width) { this.update_divider_width = width; } protected void drawScale(boolean sizeChanged) { if(drawCanvas == null || drawCanvas.isDisposed() || !drawCanvas.isVisible()) return; drawBackGround(sizeChanged); if (bufferBackground == null || bufferBackground.isDisposed()) { return; } boolean scaleChanged = lastMax != scale.getMax(); if(sizeChanged || scaleChanged || bufferScale == null) { Rectangle bounds = drawCanvas.getClientArea(); if(bounds.height < 30 || bounds.width < 100) return; if(bufferScale != null && ! bufferScale.isDisposed()) bufferScale.dispose(); bufferScale = new Image(drawCanvas.getDisplay(),bounds); GC gcBuffer = new GC(bufferScale); try { gcBuffer.drawImage(bufferBackground,0,0); gcBuffer.setForeground(Colors.black); //gcImage.setBackground(null); scale.setNbPixels(bounds.height - 16); int[] levels = scale.getScaleValues(); for(int i = 0 ; i < levels.length ; i++) { int height = bounds.height - scale.getScaledValue(levels[i]) - 2; gcBuffer.drawLine(1,height,bounds.width - 70 ,height); gcBuffer.drawText(formater.format(levels[i]),bounds.width - 65,height - 12,true); } if (this.update_divider_width > 0) { for (int i=bounds.width - 70; i > 0; i-=this.update_divider_width) { gcBuffer.setForeground(Colors.grey); gcBuffer.drawLine(i, 0, i, bounds.height); } } } catch (Exception e) { Debug.out(e); } finally { gcBuffer.dispose(); } } } public void dispose() { super.dispose(); if(bufferScale != null && ! bufferScale.isDisposed()) bufferScale.dispose(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/graphics/ValueFormater.java0000644000175000017500000000172607767512702027036 0ustar adrianadrian/* * File : ValueFormater.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.components.graphics; /** * @author Olivier * */ public interface ValueFormater { public String format(int value); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/graphics/Scale.java0000644000175000017500000000464110433660640025275 0ustar adrianadrian/* * File : Scale.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.components.graphics; /** * @author Olivier * */ public class Scale { //The target number of pixels per scale level private int pixelsPerLevel = 50; //The max value private int max = 1; //The displayed number of levels private int nbLevels; //The computed (dislayed max) private int displayedMax; //The number of pixels private int nbPixels = 1; int scaleFactor; int powFactor; public void setMax(int max) { this.max = max; if(max < 1) max = 1; computeValues(); } public int getMax() { return this.max; } public void setNbPixels(int nbPixels) { this.nbPixels = nbPixels; if(nbPixels < 1) nbPixels = 1; computeValues(); } private void computeValues() { int targetNbLevels = nbPixels / pixelsPerLevel; if(targetNbLevels < 1) targetNbLevels = 1; scaleFactor = max / targetNbLevels; powFactor = 1; while(scaleFactor >= 10) { powFactor = 10 * powFactor; scaleFactor = scaleFactor / 10; } if(scaleFactor >= 5) scaleFactor = 5; else if(scaleFactor >= 2) scaleFactor = 2; else scaleFactor = 1; nbLevels = max / (scaleFactor * powFactor) + 1; displayedMax = scaleFactor * powFactor * nbLevels; } public int[] getScaleValues() { int[] result = new int[nbLevels+1]; for(int i = 0 ; i < nbLevels + 1 ; i++) { result[i] = i * scaleFactor * powFactor; } return result; } public int getScaledValue(int value) { return(int)( ((long)value * nbPixels) / displayedMax ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/graphics/BackGroundGraphic.java0000644000175000017500000000653611034200774027564 0ustar adrianadrian/* * File : ScaledGraphic.java * Created : 15 d�c. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.components.graphics; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Canvas; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import com.aelitis.azureus.ui.swt.utils.ColorCache; /** * @author Olivier * */ public class BackGroundGraphic implements Graphic { protected Canvas drawCanvas; protected Image bufferBackground; protected Color lightGrey; protected Color lightGrey2; protected Color colorWhite; protected AEMonitor this_mon = new AEMonitor( "BackGroundGraphic" ); public BackGroundGraphic() { } public void initialize(Canvas canvas) { this.drawCanvas = canvas; lightGrey = ColorCache.getColor(canvas.getDisplay(), 250, 250, 250); lightGrey2 = ColorCache.getColor(canvas.getDisplay(), 233, 233, 233); colorWhite = ColorCache.getColor(canvas.getDisplay(), 255, 255, 255); } public void refresh() { } protected void drawBackGround(boolean sizeChanged) { if(drawCanvas == null || drawCanvas.isDisposed()) return; if(sizeChanged || bufferBackground == null) { Rectangle bounds = drawCanvas.getClientArea(); if(bounds.height < 30 || bounds.width < 100) return; if(bufferBackground != null && ! bufferBackground.isDisposed()) bufferBackground.dispose(); if(bounds.width > 10000 || bounds.height > 10000) return; bufferBackground = new Image(drawCanvas.getDisplay(),bounds); Color colors[] = new Color[4]; colors[0] = colorWhite; colors[1] = lightGrey; colors[2] = lightGrey2; colors[3] = lightGrey; GC gcBuffer = new GC(bufferBackground); for(int i = 0 ; i < bounds.height - 2 ; i++) { gcBuffer.setForeground(colors[i%4]); gcBuffer.drawLine(1,i+1,bounds.width-1,i+1); } gcBuffer.setForeground(Colors.black); gcBuffer.drawLine(bounds.width-70,0,bounds.width-70,bounds.height-1); gcBuffer.drawRectangle(0,0,bounds.width-1,bounds.height-1); gcBuffer.dispose(); } } public void dispose() { if(bufferBackground != null && ! bufferBackground.isDisposed()) bufferBackground.dispose(); } public void setColors(Color color1, Color color2, Color color3) { colorWhite = color1; lightGrey = color2; lightGrey2 = color3; drawCanvas.redraw(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/graphics/Test.java0000644000175000017500000000300510373051046025153 0ustar adrianadrian/* * Created on 11 oct. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.components.graphics; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; /** * @author Olivier Chalouhi * */ public class Test { final static int IMAGES_TO_CREATE = 100; public static void main (String [] args) { Display display = new Display (); Image[] images = new Image[IMAGES_TO_CREATE]; for(int i = 0 ; i < IMAGES_TO_CREATE ; i++) { images[i] = new Image(display,800,600); } for(int i = 0 ; i < IMAGES_TO_CREATE ; i++) { images[i].dispose(); } display.dispose (); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/BufferedTableRow.java0000644000175000017500000004562411237540526025641 0ustar adrianadrian/* * File : BufferedTableItem.java * Created : 24-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.components; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; /** * A buffered Table Row. *

* We buffer certain properties of TableRow to save CPU cycles. For example, * foreground_colors is cached because TableItem.getForegroundColor is expensive * when there is no color set, and setForegroundColor is always expensive. *

* Text is not buffered as SWT does a good job of buffering it already. *

* * @note For Virtual tables, we can not set any visual properties until * SWT.SetData has been called. getData("SD") is set after SetData * call, and the row is invalidated. Thus, there is no need to set * any visual properties until the row #isVisible() * * @author parg
* @author TuxPaper (SWT.Virtual Stuff) */ public class BufferedTableRow { private static final int VALUE_SIZE_INC = 8; private static Color[] alternatingColors = null; // for checkWidget(int) public final static int REQUIRE_TABLEITEM = 0; public final static int REQUIRE_TABLEITEM_INITIALIZED = 1; public final static int REQUIRE_VISIBILITY = 2; protected Table table; protected TableItem item; protected Image[] image_values = new Image[0]; protected Color[] foreground_colors = new Color[0]; protected Color foreground; protected Color ourForeground; private Point ptIconSize = null; private Image imageBG; static { Colors.getInstance().addColorsChangedListener(new ParameterListener() { public void parameterChanged(String parameterName) { alternatingColors = null; } }); } /** * Default constructor * * @param _table */ public BufferedTableRow(Table _table) { table = _table; item = null; } /** * Create a row in the SWT table * */ public void createSWTRow() { item = new TableItem(table, SWT.NULL); setAlternatingBGColor(true); } public void createSWTRow(int index) { new TableItem(table, SWT.NULL); setTableItem(index, false); } public void setAlternatingBGColor(boolean bEvenIfNotVisible) { if (Utils.TABLE_GRIDLINE_IS_ALTERNATING_COLOR) return; if ((table.getStyle() & SWT.VIRTUAL) != 0 && !bEvenIfNotVisible && !isVisible()) { return; } else if (item == null || item.isDisposed()) { return; } int index = table.indexOf(item); if (index == -1) { return; } try { if (alternatingColors == null || alternatingColors[1].isDisposed()) { alternatingColors = new Color[] { table.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND), Colors.colorAltRow }; } Color newColor = alternatingColors[index % alternatingColors.length]; if (!newColor.equals(getBackground())) { item.setBackground(newColor); } } catch (Exception e) { Debug.out(e); } } /** * Disposes of underlying SWT TableItem. If no TableItem has been * assigned to the row yet, an unused TableItem will be disposed of, if * available. *

* Disposing of fonts, colors and other resources are the responsibilty of * the caller. */ public void dispose() { if (table != null && !table.isDisposed() && Utils.isThisThreadSWT()) { if (!checkWidget(REQUIRE_TABLEITEM)) { // No assigned spot yet, or not our spot: // find a row with no TableRow data TableItem[] items = table.getItems(); for (int i = items.length - 1; i >= 0; i--) { TableItem item = items[i]; if (!item.isDisposed()) { Object itemRow = item.getData("TableRow"); if (itemRow == null || itemRow == this) { this.item = item; break; } } } } boolean itemNeedsDisposal = item != null && !item.isDisposed(); if (this.ourForeground != null && !this.ourForeground.isDisposed()) { // Even though we are going to dispose soon, set foreground to null // in case for some reason the OS gets a paint event in between // the color disposal and the item disposal if (itemNeedsDisposal) { item.setForeground(null); } this.ourForeground.dispose(); } if (itemNeedsDisposal) { item.dispose(); } else if (table.getItemCount() > 0) { System.err.println("No table row was found to dispose"); } } else { if (!Utils.isThisThreadSWT()) { System.err.println("Calling BufferedTableRow.dispose on non-SWT thread!"); System.err.println(Debug.getStackTrace(false, false)); } } item = null; } /** * Sets the receiver's image at a column. * * @param index the column index * @param new_image the new image */ public void setImage( int index, Image new_image ) { if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) return; if ( index >= image_values.length ){ int new_size = Math.max( index+1, image_values.length+VALUE_SIZE_INC ); Image[] new_images = new Image[new_size]; System.arraycopy( image_values, 0, new_images, 0, image_values.length ); image_values = new_images; } Image image = image_values[index]; if ( new_image == image ){ return; } image_values[index] = new_image; item.setImage( index, new_image ); } public Image getImage(int index) { if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) return null; return item.getImage(index); } /** * Checks if the widget is valid * * @param checkFlags REQUIRE_* flags (OR'd) * * @return True: Ok; False: Not ok */ public boolean checkWidget(int checkFlags) { boolean bWidgetOk = !table.isDisposed() && item != null && !item.isDisposed() && item.getData("TableRow") == this; final boolean bCheckVisibility = (checkFlags & REQUIRE_VISIBILITY) > 0; final boolean bCheckInitialized = (checkFlags & REQUIRE_TABLEITEM_INITIALIZED) > 0; if (bWidgetOk && bCheckInitialized) { bWidgetOk = (table.getStyle() & SWT.VIRTUAL) == 0 || item.getData("SD") != null; } if (bWidgetOk && bCheckVisibility) { if (_isVisible()) { // Caller assumes that a visible item can be modified, so // make sure we initialize it. if (!bCheckInitialized && (table.getStyle() & SWT.VIRTUAL) != 0 && item.getData("SD") == null) { // This is catch is temporary for SWT 3212, because there are cases where // it says it isn't disposed, when it really almost is try { item.setData("SD", "1"); } catch (NullPointerException badSWT) { } setAlternatingBGColor(true); setIconSize(ptIconSize); invalidate(); } } else { bWidgetOk = false; } } return bWidgetOk; } private boolean _isVisible() { // Least time consuming checks first if (!table.isVisible()) { return false; } int index = table.indexOf(item); if (index == -1) return false; int iTopIndex = table.getTopIndex(); if (index < iTopIndex) return false; int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex); if (index > iBottomIndex) return false; return true; } public Color getForeground() { if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) return null; if (ourForeground == null && table.isSelected(table.indexOf(item))) { return table.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT); } return( item.getForeground()); } private static final boolean DEBUG_SET_FOREGROUND = System.getProperty("debug.setforeground") != null; private static void setForegroundDebug(String method_sig, Color c) { if (DEBUG_SET_FOREGROUND && c != null) { Debug.out("BufferedTableRow " + method_sig + " -> " + c); } } private static void setForegroundDebug(String method_sig, int r, int g, int b) { if (DEBUG_SET_FOREGROUND && (!(r == 0 && g == 0 && b == 0))) { Debug.out("BufferedTableRow " + method_sig + " -> " + r + "," + g + "," + b); } } public void setForeground( Color c ) { setForegroundDebug("setForeground(Color)", c); if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) return; if (foreground == null && c == null) {return;} if (foreground != null && foreground.equals(c)) return; foreground = c; if (this.ourForeground != null) { if (!this.ourForeground.isDisposed()) { this.ourForeground.dispose(); } this.ourForeground = null; } item.setForeground(foreground); } public void setForeground(int red, int green, int blue) { setForegroundDebug("setForeground(r,g,b)", red, green, blue); if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) { return; } if (red == -1 && green == -1 && blue == -1) { this.setForeground(null); return; } RGB newRGB = new RGB(red, green, blue); if (this.foreground != null && this.foreground.getRGB().equals(newRGB)) { return; } // Hopefully it is OK to just assume it is safe to dispose of the colour, // since we're expecting it to match this.foreground. Color newColor = new Color(getTable().getDisplay(), newRGB); item.setForeground(newColor); if (ourForeground != null && !ourForeground.isDisposed()) { ourForeground.dispose(); } this.foreground = newColor; this.ourForeground = newColor; } public boolean setForeground( int index, Color new_color ) { setForegroundDebug("setForeground(int,Color)", new_color); if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) return false; if ( index >= foreground_colors.length ){ int new_size = Math.max( index+1, foreground_colors.length+VALUE_SIZE_INC ); Color[] new_colors = new Color[new_size]; System.arraycopy( foreground_colors, 0, new_colors, 0, foreground_colors.length ); foreground_colors = new_colors; } Color value = foreground_colors[index]; if ( new_color == value ){ return false; } if ( new_color != null && value != null && new_color.equals( value )){ return false; } foreground_colors[index] = new_color; try { item.setForeground(index, new_color); } catch (NoSuchMethodError e) { /* Ignore for Pre 3.0 SWT.. */ } return true; } public Color getForeground(int index) { if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) return null; if (index >= foreground_colors.length) { return getForeground(); } if (foreground_colors[index] == null && isSelected()) { Color systemColor = table.getDisplay().getSystemColor( table.isFocusControl() ? SWT.COLOR_LIST_SELECTION_TEXT : SWT.COLOR_WIDGET_FOREGROUND); return systemColor; } return foreground_colors[index]; } protected String getText( int index ) { if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) return ""; // SWT >= 3041(Win),3014(GTK),3002(Carbon) and returns "" if range check // fails return item.getText(index); } /** * @param index * @param new_value * @return true if the item has been updated */ public boolean setText( int index, String new_value ) { if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) return false; if (index < 0 || index >= table.getColumnCount()) return false; if (new_value == null) new_value = ""; if (item.getText(index).equals(new_value)) return false; item.setText( index, new_value ); return true; } public Rectangle getBounds(int index) { if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) return null; // Some Platforms (OSX) don't handle getBounds properly (3.2M4) when // item doesn't exist in table if (table.indexOf(item) == -1) return null; Rectangle r = item.getBounds(index); if (r == null || r.width == 0 || r.height == 0) return null; return r; } protected Table getTable() { return table; } public Color getBackground() { if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) return null; if (isSelected()) { return table.getDisplay().getSystemColor( table.isFocusControl() ? SWT.COLOR_LIST_SELECTION : SWT.COLOR_WIDGET_BACKGROUND); } return item.getBackground(); } /** * The Index is this item's the position in list. * * @return Item's Position */ public int getIndex() { if (!checkWidget(REQUIRE_TABLEITEM)) return -1; return table.indexOf(item); } private void copyToItem(TableItem newItem) { Table table = getTable(); if (table == null || item == null) return; // newItem.setText(text_values); newItem.setImage(image_values); Color colorFG = item.getForeground(); Color colorBG = item.getBackground(); newItem.setForeground(colorFG); newItem.setBackground(colorBG); int numColumns = table.getColumnCount(); for (int i = 0; i < numColumns; i++) { try { newItem.setText(i, item.getText(i)); Color colorColumnFG = item.getForeground(i); Color colorColumnBG = item.getBackground(i); if (!colorColumnFG.equals(colorFG)) newItem.setForeground(i, colorColumnFG); if (!colorColumnBG.equals(colorBG)) newItem.setBackground(i, colorColumnBG); } catch (NoSuchMethodError e) { /* Ignore for Pre 3.0 SWT.. */ } } if (isSelected()) table.select(table.indexOf(newItem)); else table.deselect(table.indexOf(newItem)); newItem.setData("TableRow", item.getData("TableRow")); } public boolean isSelected() { if (!checkWidget(REQUIRE_TABLEITEM)) return false; // Invalid Indexes are checked/ignored by SWT. return table.isSelected(table.indexOf(item)); } public void setSelected(boolean bSelected) { if (!checkWidget(REQUIRE_TABLEITEM)) return; if (bSelected) table.select(getIndex()); else table.deselect(getIndex()); } /** * Set the TableItem associated with this row to the TableItem at the * specified index. * * @param newIndex Index of TableItem that will be associated with this row * @param bCopyFromOld True: Copy the visuals from the old TableItem to * the new TableItem * @return success level */ public boolean setTableItem(int newIndex, boolean bCopyFromOld) { return setTableItem(newIndex, bCopyFromOld, true); } public boolean setTableItem(int newIndex, boolean bCopyFromOld, boolean isVisible) { TableItem newRow; boolean needsNewAltBG = false; if (alternatingColors != null) { int newAltRowNo = newIndex % alternatingColors.length; int oldAltRowNo = item == null ? -1 : table.indexOf(item) % alternatingColors.length; needsNewAltBG = newAltRowNo != oldAltRowNo; } try { newRow = table.getItem(newIndex); } catch (IllegalArgumentException er) { if (item == null || item.isDisposed()) { return false; } item = null; return true; } catch (Throwable e) { System.out.println("setTableItem(" + newIndex + ", " + bCopyFromOld + ")"); e.printStackTrace(); return false; } if (newRow.isDisposed()) { Debug.out("newRow disposed from " + Debug.getCompressedStackTrace()); return false; } if (newRow == item) { if (newRow.getData("TableRow") == this) { if(isVisible && needsNewAltBG) setAlternatingBGColor(true); return false; } } if (newRow.getParent() != table) return false; if (bCopyFromOld) { copyToItem(newRow); } else if (newRow.getData("SD") != null) { // clear causes too much flicker //table.clear(table.indexOf(newRow)); newRow.setForeground(null); //newRow.setBackground(null); int numColumns = table.getColumnCount(); for (int i = 0; i < numColumns; i++) { try { newRow.setImage(i, null); newRow.setForeground(i, null); } catch (NoSuchMethodError e) { /* Ignore for Pre 3.0 SWT.. */ } } } else { newRow.setData("SD", "1"); setIconSize(ptIconSize); } if(isVisible && needsNewAltBG) setAlternatingBGColor(false); try { newRow.setData("TableRow", this); } catch (Exception e) { e.printStackTrace(); System.out.println("Disposed? " + newRow.isDisposed()); if (!newRow.isDisposed()) { System.out.println("TR? " + newRow.getData("TableRow")); System.out.println("SD? " + newRow.getData("SD")); } } image_values = new Image[0]; foreground_colors = new Color[0]; foreground = null; // unlink old item from tablerow if (item != null && !item.isDisposed() && item.getData("TableRow") == this && newRow != item) { item.setData("TableRow", null); int numColumns = table.getColumnCount(); for (int i = 0; i < numColumns; i++) { try { item.setImage(i, null); item.setForeground(i, null); } catch (NoSuchMethodError e) { /* Ignore for Pre 3.0 SWT.. */ } } } item = newRow; invalidate(); return true; } public boolean setHeight(int iHeight) { return setIconSize(new Point(1, iHeight)); } public boolean setIconSize(Point pt) { ptIconSize = pt; if (pt == null) return false; if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) return false; Image oldImage = item.getImage(0); if (oldImage != null) { Rectangle r = oldImage.getBounds(); if (r.width == pt.x && r.height == pt.y) return false; } // set row height by setting image Image image = new Image(item.getDisplay(), pt.x, pt.y); item.setImage(0, image); item.setImage(0, null); image.dispose(); return true; } /** * Whether the row is currently visible to the user * * @return visibility */ public boolean isVisible() { return checkWidget(REQUIRE_VISIBILITY); } /** * Overridable function that is called when row needs invalidation. * */ public void invalidate() { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED | REQUIRE_VISIBILITY)) return; Rectangle r = item.getBounds(0); table.redraw(0, r.y, table.getClientArea().width, r.height, true); } }); } public void setBackgroundImage(Image image) { if (imageBG != null && !imageBG.isDisposed()) { imageBG.dispose(); } imageBG = image; } public Image getBackgroundImage() { return imageBG; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/LinkArea.java0000644000175000017500000001222610642335710024131 0ustar adrianadrian/* * Created on Jul 2, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.components; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.core3.html.HTMLUtils; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; public class LinkArea { private StyledText styled_text; // list of linkInfo for tracking where the links are // could have just used stDecription.getStyleRanges() since we underline // the links, but I didn't want to risk a chance of any other styles // being in there that I don't know about (plus managing the URL) private ArrayList links = new ArrayList(); private int ofs; private String relative_url_base = ""; public LinkArea( Composite comp ) { styled_text = new StyledText(comp,SWT.BORDER | SWT.READ_ONLY | SWT.H_SCROLL | SWT.V_SCROLL); styled_text.setWordWrap(true); styled_text.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event event) { if (links.size() == 0) { return; } try { int ofs = styled_text.getOffsetAtLocation(new Point(event.x, event.y)); for (int i = 0; i < links.size(); i++) { linkInfo linkInfo = (linkInfo)links.get(i); if (ofs >= linkInfo.ofsStart && ofs <= linkInfo.ofsEnd) { Utils.launch(linkInfo.url); break; } } } catch (Exception e) { } } }); final Cursor handCursor = new Cursor(comp.getDisplay(), SWT.CURSOR_HAND); styled_text.addListener(SWT.MouseMove, new Listener() { Cursor curCursor = null; public void handleEvent(Event event) { if (links.size() == 0) { return; } boolean onLink = false; try { int ofs = styled_text.getOffsetAtLocation(new Point(event.x, event.y)); for (int i = 0; i < links.size(); i++) { linkInfo linkInfo = (linkInfo)links.get(i); if (ofs >= linkInfo.ofsStart && ofs <= linkInfo.ofsEnd) { onLink = true; break; } } } catch (Exception e) { } try { Cursor cursor = onLink ? handCursor : null; if (curCursor != cursor) { styled_text.setCursor(cursor); curCursor = cursor; } } catch (Exception e) { } } }); styled_text.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event event) { styled_text.setCursor(null); handCursor.dispose(); } }); } public Composite getComponent() { return( styled_text ); } public void reset() { if( styled_text.isDisposed()){ return; } ofs = 0; styled_text.setText(""); links.clear(); } public void setRelativeURLBase( String str ) { relative_url_base = str; } public void addLine( String line ) { if( styled_text.isDisposed()){ return; } try{ line = HTMLUtils.expand( line ); Object[] url_details = HTMLUtils.getLinks( line ); String modified_line = (String)url_details[0]; styled_text.append(modified_line + "\n"); List urls = (List)url_details[1]; for (int i=0;i 0 ){ url = relative_url_base + url; } linkInfo info = new linkInfo(ofs + det[0], ofs + det[0] + det[1], url ); links.add(info); StyleRange sr = new StyleRange(); sr.start = info.ofsStart; sr.length = info.ofsEnd - info.ofsStart; sr.underline = true; sr.foreground = Colors.blue; styled_text.setStyleRange(sr); } ofs += modified_line.length() + 1; }catch( Throwable e ){ // just in case something borks Debug.printStackTrace( e ); styled_text.append(line + "\n"); } } public static class linkInfo { int ofsStart; int ofsEnd; String url; linkInfo(int s, int e, String url) { ofsStart = s; ofsEnd = e; this.url = url; } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/BufferedTableItem.java0000644000175000017500000000523410775552626025773 0ustar adrianadrian/* * Created on Jun 12, 2006 11:34:42 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.components; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; /** * @author TuxPaper * @created Jun 12, 2006 * */ public interface BufferedTableItem { public abstract String getText(); public abstract boolean setText(String text); public abstract Image getIcon(); public abstract void setIcon(Image img); public abstract void setRowForeground(Color color); public abstract boolean setForeground(Color color); public abstract boolean setForeground(int red, int green, int blue); public abstract Color getBackground(); public abstract Rectangle getBounds(); public abstract void refresh(); public abstract void dispose(); /** * Is the cell currently shown on the screen? * * @return */ public abstract boolean isShown(); public abstract boolean needsPainting(); /** Paint the image only (no update needed) */ public abstract void doPaint(GC gc); /** Column location (not position) changed. Usually due to a resize of * a column in a position prior to this one. */ public abstract void locationChanged(); public abstract int getPosition(); /** * */ public abstract Image getBackgroundImage(); /** * @return */ public abstract Color getForeground(); /** * */ public abstract void invalidate(); /** * Set to redraw at the next OS paint */ public abstract void redraw(); /** * # of lines item can handle * @return * * @since 3.0.1.1 */ public abstract int getMaxLines(); /** * @param cursorID * * @since 3.0.4.3 */ public abstract void setCursor(int cursorID); /** * * * @since 3.0.5.3 */ public abstract boolean isMouseOver(); }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/shell/0000755000175000017500000000000011310377636022712 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/shell/ShellManager.java0000644000175000017500000001643110461177660026125 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.components.shell; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.ui.swt.Utils; import java.util.*; /* * Created on 17-Mar-2005 * Created by James Yeh * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ /** * ShellManager provides a logical grouping for a set of shells *

Note: This class must be used from the SWT display thread

* @version 1.0 * @author James Yeh * @see org.eclipse.jface.window.WindowManager */ public class ShellManager { private static ShellManager instance; private final Collection shells = new ArrayList(); private final List addHandlers = new LinkedList(); private final List removeHandlers = new LinkedList(); static { instance = new ShellManager(); } /** *

Gets the application's shared shell manager

*

This ShellManager has no bearing on other ShellManager instances

*

Note: This method must be invoked by the SWT display thread

* @return */ public static final ShellManager sharedManager() { return instance; } /** * Adds a shell to the shell manager. If the shell is already managed, it is not added again. *

Note: This method must be invoked by the SWT display thread

* @param shell A SWT Shell */ public final void addWindow(final Shell shell) { //Debug.out("Invoked by thread " + Thread.currentThread().getName()); if(shells.contains(shell)) {return;} shells.add(shell); notifyAddListeners(shell); shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent event) { try { removeWindow(shell); } catch (Exception e) { Logger.log(new LogEvent(LogIDs.GUI, "removeWindow", e)); } } }); shell.addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { Utils.verifyShellRect(shell, false); } }); } /** * Removes a shell from the shell manager *

Note: This method must be invoked by the SWT display thread

* @param shell A SWT Shell */ public final void removeWindow(Shell shell) { shells.remove(shell); notifyRemoveListeners(shell); } /** *

Gets the shells managed by the manager as an Iterator

*

The order in which the shells were added are retained.

*

Note: This method must be invoked by the SWT display thread

* @return The iterator */ public final Iterator getWindows() { return shells.iterator(); } /** * Gets whether the ShellManager manages no shells * @return True if ShellManager is empty */ public final boolean isEmpty() { return shells.isEmpty(); } /** * Gets the number of shells the ShellManager manages * @return The number */ public final int getSize() { return shells.size(); } /** *

Invokes the handleEvent method specified by the SWT listener for each managed shell

*

The event's widget is set to the reference of the shell invoking it

* @param command A command implemented as a SWT Listener */ public final void performForShells(final Listener command) { Iterator iter = shells.iterator(); for(int i = 0; i < shells.size(); i++) { Shell aShell = (Shell)iter.next(); Event evt = new Event(); evt.widget = aShell; evt.data = this; command.handleEvent(evt); } } /** * Gets the set of managed shells * @return The set */ protected final Collection getManagedShellSet() { return shells; } // events /** *

Adds a listener that will be invoked when a shell has been added to the ShellManager

*

The listener and the shell will automatically be removed when the shell is disposed

* @param listener A SWT Listener */ public final void addWindowAddedListener(Listener listener) { addHandlers.add(listener); } /** * Removes a listener that will be invoked when a shell has been added to the ShellManager * @param listener A SWT Listener */ public final void removeWindowAddedListener(Listener listener) { addHandlers.remove(listener); } /** * Adds a listener that will be invoked when a shell has been removed from the ShellManager * @param listener A SWT Listener */ public final void addWindowRemovedListener(Listener listener) { removeHandlers.add(listener); } /** * Removes a listener that will be invoked when a shell has been removed from the ShellManager * @param listener A SWT Listener */ public final void removeWindowRemovedListener(Listener listener) { removeHandlers.remove(listener); } /** * Notifies the WindowAddedListener handlers * @param sender A SWT shell that "sends" the events */ protected final void notifyAddListeners(Shell sender) { Iterator iter = addHandlers.iterator(); for(int i = 0; i < addHandlers.size(); i++) { ((Listener)iter.next()).handleEvent(getSWTEvent(sender)); } } /** * Notifies the WindowRemovedListener handlers * @param sender A SWT shell that "sends" the events */ protected final void notifyRemoveListeners(Shell sender) { Iterator iter = removeHandlers.iterator(); for(int i = 0; i < removeHandlers.size(); i++) { ((Listener)iter.next()).handleEvent(getSWTEvent(sender)); } } /** *

Gets a generated SWT Event based on the shell

*

The widget field of the event should be set to the shell

* @param shell A SWT Shell * @return The event */ protected Event getSWTEvent(Shell shell) { Event e = new Event(); e.widget = shell; e.item = shell; return e; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/shell/ShellFactory.java0000644000175000017500000002130011272502272026141 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.components.shell; /* * Created on 17-Mar-2005 * Created by James Yeh * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; /** * Facilitates the creation of SWT Shells with platform-specific additions. * All shells normal to the user should be created from ShellFactory * @version 1.0 * @author James Yeh */ public final class ShellFactory { public static Shell createMainShell(int styles) { Shell parent = null; UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { parent = uiFunctions.getMainShell(); } if (parent == null) { return createShell(SWTThread.getInstance().getDisplay()); } return (createShell(parent, styles)); } /** *

Creates a shell

*

For platforms that use a unified menu bar, the shell's menu bar is set to the main window's menu bar

* @see org.eclipse.swt.widgets.Shell */ public static Shell createShell(final Display disp, final int styles) { return getRegisteredShell(new AEShell(disp, styles)); } /** *

Creates a shell

*

For platforms that use a unified menu bar, the shell's menu bar is set to the main window's menu bar

* @see org.eclipse.swt.widgets.Shell */ public static Shell createShell(final Display disp) { return getRegisteredShell(new AEShell(disp)); } /** *

Creates a shell

*

For platforms that use a unified menu bar, the shell's menu bar is set to the main window's menu bar

* @see org.eclipse.swt.widgets.Shell */ public static Shell createShell(final Shell parent, final int styles) { if (parent != null && parent.isDisposed()) return null; return getRegisteredShell(new AEShell(parent, styles)); } /** *

Creates a shell

*

For platforms that use a unified menu bar, the shell's menu bar is set to the main window's menu bar

* @see org.eclipse.swt.widgets.Shell */ public static Shell createShell(final Shell parent) { return getRegisteredShell(new AEShell(parent)); } /** *

Creates a shell

*

For platforms that use a unified menu bar, the shell's menu bar is set to the main window's menu bar

* @see org.eclipse.swt.widgets.Shell */ public static Shell createShell(final int styles) { return getRegisteredShell(new AEShell(styles)); } /** *

Gets the registered shell

*

Registration entails setting its menu bar if platform uses a unified menu bar.

* *

On OSX (carbon) the menus for an application is displayed at the top of the screen instead of * on the main window of the application. This menu is shown whenever the application is activated * or any of its pop up dialogs are activated. This behavior is very different than that for * Windows and Linux applications because the menu is shown in the main application window for these OS's.

* *

To provide the same behavior as native OSX application we must ensure that whenever the application * window or any of its pop up dialog is activate we show the same application menus on the OSX global * menubar. In the SWT world this means that the same application menu must be created on each shell * that we pop up.

* *

NOTE: This essentially means that each shell will have its own copy of the main menu so to the users * it would seem like they are looking at the same menu instance. Moreover, this also means that any * shell-related functions activated through the menu may have to distinguish which shell it is working * with... the main application shell? or a pop up dialog shell?

* *

*

Also, the shell is added to the shared ShellManager

* * @param toRegister A SWT Shell * @return The SWT Shell */ private static Shell getRegisteredShell(final Shell toRegister) { if (null == toRegister) return null; if (Constants.isOSX) { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions == null) throw new IllegalStateException("Main window is not initialized yet"); uiFunctions.createMainMenu(toRegister); } ShellManager.sharedManager().addWindow(toRegister); return toRegister; } /** * A shell that provides platform-specific behaviour in some methods in order to better suit the user experience */ private static class AEShell extends Shell { /** * {@inheritDoc} */ private AEShell(int styles) { super(styles); } /** * {@inheritDoc} */ private AEShell(Display display) { super(display); } /** * {@inheritDoc} */ private AEShell(Display display, int styles) { super(display, fixupStyle(styles)); } /** * {@inheritDoc} */ private AEShell(Shell parent) { super(parent); } /** * {@inheritDoc} */ private AEShell(Shell parent, int styles) { super(parent, fixupStyle(styles)); } static private int fixupStyle(int style) { if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL | SWT.PRIMARY_MODAL)) > 0 && Utils.anyShellHaveStyle(SWT.ON_TOP | SWT.TITLE)) { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null && uiFunctions.getMainShell() != null) { style |= SWT.ON_TOP; } } return style; } /** * Does nothing */ protected void checkSubclass() { } /** *

Sets the iconic representation of a SWT window

*

The icon is often located at the top-left corner of the title bar. This is different from Mac OS X's * document proxy icon.

*

For Mac OS X, this method does nothing (because the dock's image would be set instead).

* @param shell The SWT window * @param imgKey ImageRepository key for the image */ public void setImage(final Image image) { if (!Constants.isOSX) super.setImage(image); } /** *

Sets the iconic representation of a SWT window

*

The icon is often located at the top-left corner of the title bar. This is different from Mac OS X's * document proxy icon.

*

For Mac OS X, this method does nothing (because the dock's image would be set instead).

* @param shell The SWT window * @param images Images */ public void setImages(final Image[] images) { if (!Constants.isOSX) super.setImages(images); } public void open() { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { Shell mainShell = uiFunctions.getMainShell(); if (mainShell != null && mainShell.getMinimized()) { uiFunctions.bringToFront(); } } Shell firstShellWithStyle = Utils.findFirstShellWithStyle(SWT.APPLICATION_MODAL); if (firstShellWithStyle != null && firstShellWithStyle != this) { // ok, there's a window with application_modal set, which on OSX will mean // that if we open our window, it will be on top, but users won't be able // to interact with it. So, wait until the modal window goes away.. firstShellWithStyle.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { // wait for dispose to complete, then run open again to check for // any new application modal shells to wait for Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { AEShell.this.open(); } }); } }); firstShellWithStyle.setVisible(true); firstShellWithStyle.forceActive(); } else { super.open(); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/BufferedTableItemImpl.java0000644000175000017500000001464711264273636026620 0ustar adrianadrian/* * File : BufferedTableItem.java * Created : 24 nov. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.components; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Table; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.Utils; /** * @author Olivier * */ public abstract class BufferedTableItemImpl implements BufferedTableItem { protected BufferedTableRow row; private int position; private Color ourFGColor = null; private String text = ""; private Image icon = null; private AERunnable runnableDirtyCell; public BufferedTableItemImpl(BufferedTableRow row, int position) { this.row = row; this.position = position; } public String getText() { return text; } public boolean setText(String text) { if (this.text.equals(text)) { return false; } this.text = (text == null) ? "" : text; dirtyCell(); return true; } private void dirtyCell() { if (runnableDirtyCell == null) { synchronized (this) { if (runnableDirtyCell == null) { runnableDirtyCell = new AERunnable(){ public void runSupport() { Rectangle bounds = getBounds(); if (bounds != null) { Table table = row.getTable(); Rectangle dirty = table.getClientArea().intersection(bounds); //System.out.println("old = " + this.text + ";new=" + text + ";dirty=" + bounds); table.redraw(dirty.x, dirty.y, dirty.width, dirty.height, false); } } }; } } } Utils.execSWTThread(runnableDirtyCell); } public void setIcon(Image img) { if (position != -1) { row.setImage(position, img); icon = img; } } public Image getIcon() { if (position != -1) { Image image = row.getImage(position); return (image != null) ? image : icon; } return null; } public void setRowForeground(Color color) { row.setForeground(color); } public boolean setForeground(Color color) { if (position == -1) return false; boolean ok = row.setForeground(position, color); if (ok && ourFGColor != null) { if (!ourFGColor.isDisposed()) {ourFGColor.dispose();} ourFGColor = null; } return ok; } public Color getForeground() { if (position == -1) return null; return row.getForeground(position); } public boolean setForeground(int red, int green, int blue) { if (position == -1) return false; if (red == -1 && green == -1 && blue == -1) { return setForeground(null); } Color oldColor = row.getForeground(position); RGB newRGB = new RGB(red, green, blue); if (oldColor != null && oldColor.getRGB().equals(newRGB)) { return false; } Color newColor = new Color(row.getTable().getDisplay(), newRGB); boolean ok = row.setForeground(position, newColor); if (ok) { if (ourFGColor != null && !ourFGColor.isDisposed()) ourFGColor.dispose(); ourFGColor = newColor; } else { if (!newColor.isDisposed()) newColor.dispose(); } return ok; } public Color getBackground() { return row.getBackground(); } public Rectangle getBounds() { if (position != -1) return row.getBounds(position); return null; } public Table getTable() { return row.getTable(); } public void dispose() { if (ourFGColor != null && !ourFGColor.isDisposed()) ourFGColor.dispose(); } public boolean isShown() { return true; // XXX Bounds check is almost always slower than any changes we // are going to do to the column // if (position < 0) { // return false; // } // // Rectangle bounds = row.getBounds(position); // if (bounds == null) { // return false; // } // // return row.getTable().getClientArea().intersects(bounds); } public boolean needsPainting() { return false; } public void doPaint(GC gc) { } public void locationChanged() { } public int getPosition() { return position; } public Image getBackgroundImage() { Table table = row.getTable(); Rectangle bounds = getBounds(); if (bounds.isEmpty()) { return null; } Image image = new Image(table.getDisplay(), bounds.width, bounds.height); GC gc = new GC(image); gc.setForeground(getBackground()); gc.setBackground(getBackground()); gc.fillRectangle(0, 0, bounds.width, bounds.height); //gc.copyArea(image, bounds.x, bounds.y); gc.dispose(); return image; } // @see org.gudy.azureus2.ui.swt.components.BufferedTableItem#redraw() public void redraw() { //System.out.println("redraw via " + Debug.getCompressedStackTrace(5)); Utils.execSWTThread(new AERunnable() { public void runSupport() { Rectangle bounds = getBounds(); if (bounds != null) { Table table = row.getTable(); Rectangle dirty = table.getClientArea().intersection(bounds); if (!dirty.isEmpty()) { table.redraw(dirty.x, dirty.y, dirty.width, dirty.height, false); } } } }); } // @see org.gudy.azureus2.ui.swt.components.BufferedTableItem#getMaxLines() public int getMaxLines() { return 1; } // @see org.gudy.azureus2.ui.swt.components.BufferedTableItem#setCursor(int) public void setCursor(final int cursorID) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (row == null) { return; } Table table = row.getTable(); if (table == null || table.isDisposed()) { return; } table.setCursor(table.getDisplay().getSystemCursor(cursorID)); } }); } // @see org.gudy.azureus2.ui.swt.components.BufferedTableItem#isMouseOver() public boolean isMouseOver() { Table table = row.getTable(); if (table == null || table.isDisposed()) { return false; } Point pt = table.getDisplay().getCursorLocation(); pt = table.toControl(pt); Rectangle bounds = getBounds(); return bounds == null ? false : bounds.contains(pt); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/CustomTableTooltipHandler.java0000644000175000017500000001152111077726112027536 0ustar adrianadrian/* * Created on Oct 21, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.ui.swt.components; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; public class CustomTableTooltipHandler implements Listener { Shell toolTipShell = null; Shell mainShell = null; Label toolTipLabel = null; private final Table table; /** * Initialize */ public CustomTableTooltipHandler( Table _table) { table = _table; mainShell = table.getShell(); table.addListener(SWT.Dispose, this); table.addListener(SWT.KeyDown, this); table.addListener(SWT.MouseMove, this); table.addListener(SWT.MouseHover, this); mainShell.addListener(SWT.Deactivate, this); table.addListener(SWT.Deactivate, this); table.setToolTipText( "" ); // disable native tooltip } public void handleEvent(Event event) { switch (event.type) { case SWT.MouseHover: { if (toolTipShell != null && !toolTipShell.isDisposed()) toolTipShell.dispose(); TableItem item = table.getItem( new Point( event.x, event.y )); if (item == null) return; Object oToolTip = item.getData( "tooltip" ); if ( oToolTip == null ){ oToolTip = item.getText(0); } // TODO: support composite, image, etc if (oToolTip == null || !(oToolTip instanceof String)) return; String sToolTip = (String) oToolTip; Display d = table.getDisplay(); if (d == null) return; // We don't get mouse down notifications on trim or borders.. toolTipShell = new Shell(table.getShell(), SWT.ON_TOP); FillLayout f = new FillLayout(); try { f.marginWidth = 3; f.marginHeight = 1; } catch (NoSuchFieldError e) { /* Ignore for Pre 3.0 SWT.. */ } toolTipShell.setLayout(f); toolTipShell.setBackground(d.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); toolTipLabel = new Label(toolTipShell, SWT.WRAP); toolTipLabel.setForeground(d.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); toolTipLabel.setBackground(d.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); //toolTipShell.setData("TableCellSWT", item); toolTipLabel.setText(sToolTip.replaceAll("&", "&&")); // compute size on label instead of shell because label // calculates wrap, while shell doesn't Point size = toolTipLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT); if (size.x > 600) { size = toolTipLabel.computeSize(600, SWT.DEFAULT, true); } size.x += toolTipShell.getBorderWidth() * 2 + 2; size.y += toolTipShell.getBorderWidth() * 2; try { size.x += toolTipShell.getBorderWidth() * 2 + (f.marginWidth * 2); size.y += toolTipShell.getBorderWidth() * 2 + (f.marginHeight * 2); } catch (NoSuchFieldError e) { /* Ignore for Pre 3.0 SWT.. */ } Point pt = table.toDisplay(event.x, event.y); Rectangle displayRect; try { displayRect = table.getMonitor().getClientArea(); } catch (NoSuchMethodError e) { displayRect = table.getDisplay().getClientArea(); } if (pt.x + size.x > displayRect.x + displayRect.width) { pt.x = displayRect.x + displayRect.width - size.x; } if (pt.y + size.y > displayRect.y + displayRect.height) { pt.y -= size.y + 2; } else { pt.y += 21; } if (pt.y < displayRect.y) pt.y = displayRect.y; toolTipShell.setBounds(pt.x, pt.y, size.x, size.y); toolTipShell.setVisible(true); break; } case SWT.Dispose: if (mainShell != null && !mainShell.isDisposed()) mainShell.removeListener(SWT.Deactivate, this); if (table != null && !table.isDisposed()) mainShell.removeListener(SWT.Deactivate, this); // fall through default: if (toolTipShell != null) { toolTipShell.dispose(); toolTipShell = null; toolTipLabel = null; } break; } // switch } // handlEvent() } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/BufferedTruncatedLabel.java0000644000175000017500000000602411247603256027003 0ustar adrianadrian/* * Created on 04-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.components; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.util.DisplayFormatters; /** * @author parg * */ public class BufferedTruncatedLabel extends BufferedWidget { protected Label label; protected int width; protected String value = ""; public BufferedTruncatedLabel( Composite composite, int attrs, int _width) { super( new Label( composite, attrs )); label = (Label)getWidget(); width = _width; } public boolean isDisposed() { return( label.isDisposed()); } public void setLayoutData( GridData gd ) { if (isDisposed()) { return; } label.setLayoutData( gd ); } public void setText( String new_value ) { if ( label.isDisposed()){ return; } if ( new_value == value ){ return; } if ( new_value != null && value != null && new_value.equals( value )){ return; } value = new_value; // '&' chars that occur in the text are treated as accelerators and, for example, // cause the nect character to be underlined on Windows. This is generally NOT // the desired behaviour of a label in Azureus so by default we escape them label.setText( value==null?"":DisplayFormatters.truncateString( value.replaceAll("&", "&&" ), width )); } public String getText() { return value==null?"":value; } public void addMouseListener(MouseListener listener) { label.addMouseListener(listener); } public void setForeground(Color color) { if (isDisposed()) { return; } label.setForeground(color); } public void setCursor(Cursor cursor) { if (isDisposed() || cursor == null || cursor.isDisposed()) { return; } label.setCursor(cursor); } public void setToolTipText(String toolTipText) { if (isDisposed()) { return; } label.setToolTipText(toolTipText); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/components/LinkLabel.java0000644000175000017500000000564711226745146024320 0ustar adrianadrian/* * Created on 11-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.components; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.Cursors; public class LinkLabel { public LinkLabel( Composite composite, String resource, String link ) { this( composite, new GridData(), resource, link ); } public LinkLabel( Composite composite, GridData gridData, String resource, String link ) { Label linkLabel = new Label(composite, SWT.NULL); Messages.setLanguageText(linkLabel,resource); linkLabel.setLayoutData( gridData ); makeLinkedLabel(linkLabel, link); } /** * Alters a given label to make it appear like a launchable * link. This should preferably be done after all other changes * have been performed on the label - especially the setting of * the label's text. */ public static void makeLinkedLabel(Label label, String hyperlink) { label.setData(hyperlink); String tooltip = label.getToolTipText(); // We only set a tooltip if one isn't set already and it isn't // identical to the label text. if (tooltip == null && !hyperlink.equals(label.getText())) { label.setToolTipText(hyperlink); } label.setCursor(Cursors.handCursor); label.setForeground(Colors.blue); label.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } public void mouseUp(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } }); } public static void updateLinkedLabel(Label label, String hyperlink) { label.setData(hyperlink); label.setToolTipText(hyperlink); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/ITwistieConstants.java0000644000175000017500000000041510717253046023715 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt; public interface ITwistieConstants { public static final int NONE = 1 << 1; public static final int SHOW_DESCRIPTION = 1 << 2; public static final int SHOW_SEPARATOR = 1 << 3; public static final int SHOW_EXPANDED = 1 << 4; } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/speedtest/0000755000175000017500000000000011310377636021416 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/speedtest/SpeedTestSetLimitPanel.java0000644000175000017500000005145210654531560026621 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.speedtest; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.Wizard; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.views.stats.TransferStatsView; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.eclipse.swt.widgets.*; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.SWT; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTesterResult; import com.aelitis.azureus.core.speedmanager.SpeedManager; import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate; /** * Created on May 1, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

* This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

* AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class SpeedTestSetLimitPanel extends AbstractWizardPanel { int measuredUploadKbps, measuredDownloadKbps; boolean downloadTestRan,uploadTestRan = true; boolean downloadHitLimit, uploadHitLimit; Label explain; Label downloadLabel; Label uploadLabel; Text uploadText; Button apply; Combo downConfLevelCombo; Combo upConfLevelCombo; SpeedManager speedManager; TransferStatsView.limitToTextHelper helper; public SpeedTestSetLimitPanel(Wizard wizard, IWizardPanel previousPanel, int upload, long maxup, int download, long maxdown) { super(wizard, previousPanel); downloadHitLimit = download > maxdown - 20*1024; uploadHitLimit = upload > maxup - 20*1024; measuredUploadKbps =upload/1024; if(measuredUploadKbps<5){ uploadTestRan = false; } measuredDownloadKbps =download/1024; if(measuredDownloadKbps<5){ downloadTestRan = false; } speedManager = AzureusCoreFactory.getSingleton().getSpeedManager(); helper = new TransferStatsView.limitToTextHelper(); } /** * Panel has text at the top explaining the result. * Then under that it has a label the measured upload value and the recommended value. * Then a button with apply. */ public void show() { wizard.setTitle(MessageText.getString("SpeedTestWizard.set.upload.title")); wizard.setCurrentInfo(MessageText.getString("SpeedTestWizard.set.upload.hint")); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 4; panel.setLayout(layout); Label explain = new Label(panel, SWT.WRAP); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 4; explain.setLayoutData(gridData); Messages.setLanguageText(explain,"SpeedTestWizard.set.upload.panel.explain"); //spacer line Label spacer = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 4; spacer.setLayoutData(gridData); Label spacer1 = new Label(panel, SWT.NULL); gridData = new GridData(); spacer1.setLayoutData(gridData); Label bytesCol = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.widthHint=80; bytesCol.setLayoutData(gridData); Messages.setLanguageText(bytesCol,"SpeedTestWizard.set.upload.bytes.per.sec"); Label bitsCol = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.widthHint=80; bitsCol.setLayoutData(gridData); Messages.setLanguageText(bitsCol,"SpeedTestWizard.set.upload.bits.per.sec"); Label confLevel = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.widthHint=80; confLevel.setLayoutData(gridData); Messages.setLanguageText(confLevel,"SpeedTestWizard.set.limit.conf.level"); //upload limit label. Label ul = new Label(panel, SWT.NULL ); gridData = new GridData(); ul.setLayoutData(gridData); Messages.setLanguageText( ul, "SpeedView.stats.estupcap", new String[] { DisplayFormatters.getRateUnit(DisplayFormatters.UNIT_KB)}); final Text uploadLimitSetting = new Text(panel, SWT.BORDER ); gridData = new GridData(GridData.BEGINNING); gridData.widthHint=80; uploadLimitSetting.setLayoutData(gridData); int uploadCapacity = determineRateSettingEx(measuredUploadKbps,uploadTestRan,true); //don't accept any value less the 20 kb/s if(uploadCapacity<20) uploadCapacity=20; uploadLimitSetting.setText( ""+uploadCapacity ); uploadLimitSetting.addListener(SWT.Verify, new NumberListener(uploadLimitSetting)); //echo final Label echo = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 1; gridData.widthHint = 80; echo.setLayoutData(gridData); echo.setText( DisplayFormatters.formatByteCountToBitsPerSec(uploadCapacity*1024) ); //This space has a change listener the updates in bits/sec. //want a change listener to update the echo label which has the value in bits/sec. uploadLimitSetting.addListener(SWT.Modify, new ByteConversionListener(echo,uploadLimitSetting)); //confidence setting. final String[] confName = helper.getSettableTypes(); final String[] confValue = helper.getSettableTypes(); //upload confidence setting. int uploadDropIndex = setDefaultConfidenceLevelEx(measuredUploadKbps,uploadTestRan,true,confValue); upConfLevelCombo = new Combo(panel, SWT.READ_ONLY ); addDropElements(upConfLevelCombo,confName); upConfLevelCombo.select(uploadDropIndex); //download limit label. Label dl = new Label( panel, SWT.NULL ); gridData = new GridData(); dl.setLayoutData(gridData); Messages.setLanguageText( dl, "SpeedView.stats.estdowncap", new String[] { DisplayFormatters.getRateUnit(DisplayFormatters.UNIT_KB)}); final Text downloadLimitSetting = new Text(panel, SWT.BORDER); gridData = new GridData(GridData.BEGINNING); gridData.widthHint=80; downloadLimitSetting.setLayoutData(gridData); int bestDownloadSetting = determineRateSettingEx(measuredDownloadKbps,downloadTestRan,false); downloadLimitSetting.setText( ""+bestDownloadSetting ); downloadLimitSetting.addListener(SWT.Verify, new NumberListener(downloadLimitSetting) ); //echo final Label downEcho = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 1; gridData.widthHint = 80; downEcho.setLayoutData(gridData); downEcho.setText( DisplayFormatters.formatByteCountToBitsPerSec(bestDownloadSetting*1024) ); //convert bytes to bits on the fly for user. downloadLimitSetting.addListener(SWT.Modify, new ByteConversionListener(downEcho, downloadLimitSetting) ); int downIndex = setDefaultConfidenceLevelEx(measuredDownloadKbps,downloadTestRan,false,confValue); downConfLevelCombo = new Combo(panel, SWT.READ_ONLY ); addDropElements(downConfLevelCombo,confName); downConfLevelCombo.select(downIndex); //spacer col Label c1 = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 1; gridData.widthHint = 80; c1.setLayoutData(gridData); SpeedManager sm = AzureusCoreFactory.getSingleton().getSpeedManager(); if ( uploadTestRan ){ //Since cable modems can over estimate upload need to drop type setting to estimate. sm.setEstimatedUploadCapacityBytesPerSec( measuredUploadKbps*1024, uploadHitLimit? SpeedManagerLimitEstimate.TYPE_ESTIMATED :SpeedManagerLimitEstimate.TYPE_ESTIMATED); } if ( downloadTestRan ){ sm.setEstimatedDownloadCapacityBytesPerSec( measuredDownloadKbps*1024, downloadHitLimit? SpeedManagerLimitEstimate.TYPE_MEASURED_MIN :SpeedManagerLimitEstimate.TYPE_MEASURED); } apply = new Button(panel, SWT.PUSH); Messages.setLanguageText(apply, "SpeedTestWizard.set.upload.button.apply" ); gridData = new GridData(); gridData.widthHint = 70; apply.setLayoutData(gridData); apply.addListener(SWT.Selection, new Listener(){ public void handleEvent(Event event){ //Turn the string into an int and make it kbps. int uploadLimitKBPS = Integer.parseInt( uploadLimitSetting.getText() ); int downlaodLimitKBPS = Integer.parseInt( downloadLimitSetting.getText() ); //No value less then 20 kpbs should be allowed. if(uploadLimitKBPS<20){ uploadLimitKBPS=20; } //download value can never be less then upload. if( downlaodLimitKBPS < uploadLimitKBPS ){ downlaodLimitKBPS = uploadLimitKBPS; } //set upload limits COConfigurationManager.setParameter( "AutoSpeed Max Upload KBs", uploadLimitKBPS ); COConfigurationManager.setParameter( TransferSpeedValidator.UPLOAD_CONFIGKEY, uploadLimitKBPS ); COConfigurationManager.setParameter( TransferSpeedValidator.UPLOAD_SEEDING_CONFIGKEY , uploadLimitKBPS ); // - Do we set these? //COConfigurationManager.setParameter( TransferSpeedValidator.DOWNLOAD_CONFIGKEY, downlaodLimitKBPS ); if(downloadTestRan){ int dIndex = downConfLevelCombo.getSelectionIndex(); float downEstType = helper.textToType( confValue[dIndex] ); speedManager.setEstimatedUploadCapacityBytesPerSec( downlaodLimitKBPS , downEstType ); } if(uploadTestRan){ int uIndex = upConfLevelCombo.getSelectionIndex(); float upEstType = helper.textToType( confValue[uIndex] ); speedManager.setEstimatedUploadCapacityBytesPerSec( uploadLimitKBPS , upEstType ); } wizard.setFinishEnabled(true); wizard.setPreviousEnabled(false); } }); //spacer col Label c3 = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 1; c3.setLayoutData(gridData); //spacer line Label spacer2 = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 3; spacer2.setLayoutData(gridData); //switch column width to 5 columns. Composite resultsPanel = new Composite(rootPanel, SWT.NULL); gridData = new GridData( GridData.VERTICAL_ALIGN_END | GridData.FILL_HORIZONTAL ); resultsPanel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 5; layout.makeColumnsEqualWidth=true; resultsPanel.setLayout(layout); //display last test result NetworkAdminSpeedTesterResult result = SpeedTestData.getInstance().getLastResult(); if( result.hadError() ){ //error String error = result.getLastError(); createResultLabels(resultsPanel,true); createErrorDesc(resultsPanel,error); createTestDesc(resultsPanel); }else{ //no error //print out the last result format. int upload = result.getUploadSpeed(); int download = result.getDownloadSpeed(); createResultLabels(resultsPanel,false); createResultData(resultsPanel, MessageText.getString("GeneralView.label.uploadspeed") ,upload); createResultData(resultsPanel, MessageText.getString("GeneralView.label.downloadspeed"), download); createTestDesc(resultsPanel); } }//show private void addDropElements(Combo combo, String[] elements){ if(elements==null){ return; } int n = elements.length; for(int i=0;i 450 ){ retValType = SpeedManagerLimitEstimate.TYPE_ESTIMATED; }else{ //Otherwise we can rate result as measured. retValType = SpeedManagerLimitEstimate.TYPE_MEASURED; } String cType = helper.typeToText(retValType); //find the index for this string. if(cType==null){ return -1; } for(int i=0; i * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

* AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class SpeedTestFinishPanel extends AbstractWizardPanel { SpeedManager speedManager; TransferStatsView.limitToTextHelper helper; public SpeedTestFinishPanel(Wizard wizard, IWizardPanel previousPanel) { super(wizard, previousPanel); speedManager = AzureusCoreFactory.getSingleton().getSpeedManager(); helper = new TransferStatsView.limitToTextHelper(); } /** * */ public void show() { String title = MessageText.getString("SpeedTestWizard.finish.panel.title"); wizard.setTitle(title); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData( GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL ); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; layout.makeColumnsEqualWidth=true; panel.setLayout(layout); Label label = new Label(panel, SWT.WRAP); gridData = new GridData(); gridData.horizontalSpan = 3; gridData.widthHint = 380; label.setLayoutData(gridData); Messages.setLanguageText(label,"SpeedTestWizard.finish.panel.click.close"); //show the setting for upload speed SpeedManagerLimitEstimate upEst = speedManager.getEstimatedUploadCapacityBytesPerSec(); int maxUploadKbs = upEst.getBytesPerSec()/1024; SpeedManagerLimitEstimate downEst = speedManager.getEstimatedDownloadCapacityBytesPerSec(); int maxDownloadKbs = downEst.getBytesPerSec()/1024; //boolean setting. boolean autoSpeedEnabled = COConfigurationManager.getBooleanParameter( TransferSpeedValidator.AUTO_UPLOAD_ENABLED_CONFIGKEY ); boolean autoSpeedSeedingEnabled = COConfigurationManager.getBooleanParameter( TransferSpeedValidator.AUTO_UPLOAD_SEEDING_ENABLED_CONFIGKEY ); //spacer 2 Label s2 = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 3; s2.setLayoutData(gridData); String autoSpeed = MessageText.getString("SpeedTestWizard.finish.panel.auto.speed"); createStatusLine(panel, autoSpeed, autoSpeedEnabled); String autoSpeedWhileSeeding = MessageText.getString("SpeedTestWizard.finish.panel.auto.speed.seeding"); createStatusLine(panel, autoSpeedWhileSeeding, autoSpeedSeedingEnabled); //spacer 1 Label s1 = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 3; s1.setLayoutData(gridData); //displays a bytes/sec column and a bits/sec column createHeaderLine(panel); String maxUploadLbl = MessageText.getString("SpeedView.stats.estupcap"); createDataLine(panel, maxUploadLbl, maxUploadKbs, upEst); String maxDownloadLbl = MessageText.getString("SpeedView.stats.estdowncap"); createDataLine(panel, maxDownloadLbl, maxDownloadKbs, downEst); }//show //private static final String colSpace = " "; private void createHeaderLine(Composite panel){ GridData gridData; Label c1 = new Label(panel, SWT.NULL);//label gridData = new GridData(); gridData.horizontalSpan = 1; c1.setLayoutData(gridData); c1.setText(" "); Label c2 = new Label(panel,SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 1; gridData.horizontalAlignment = GridData.CENTER; c2.setLayoutData(gridData); c2.setText( MessageText.getString("SpeedTestWizard.set.upload.bytes.per.sec") ); Label c3 = new Label(panel,SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 1; gridData.horizontalAlignment = GridData.BEGINNING; c3.setLayoutData(gridData); c3.setText( MessageText.getString("SpeedTestWizard.set.upload.bits.per.sec") ); } /** * * @param panel - * @param label - label * @param enabled - is enabled */ private void createStatusLine(Composite panel, String label, boolean enabled){ GridData gridData; Label r3c1 = new Label(panel, SWT.NULL);//label gridData = new GridData(); gridData.horizontalSpan = 1; gridData.horizontalAlignment = GridData.END; r3c1.setLayoutData(gridData); r3c1.setText(label); Label c3 = new Label(panel,SWT.NULL);//enabled or disabled gridData = new GridData(); gridData.horizontalSpan = 1; gridData.horizontalAlignment = GridData.CENTER; c3.setLayoutData(gridData); if(enabled){ c3.setText( MessageText.getString("SpeedTestWizard.finish.panel.enabled","enabled") ); }else{ c3.setText( MessageText.getString("SpeedTestWizard.finish.panel.disabled","disabled") ); } Label c2 = new Label(panel,SWT.NULL);//space. gridData = new GridData(); gridData.horizontalSpan = 1; gridData.horizontalAlignment = GridData.BEGINNING; c2.setLayoutData(gridData); String maxUploadBitsSec = " "; c2.setText(maxUploadBitsSec); }//createStatusLine /** * One line of data in the UI * @param panel - * @param label - label * @param maxKbps - bits/sec * @param estimate - */ private void createDataLine(Composite panel, String label, int maxKbps, SpeedManagerLimitEstimate estimate) { GridData gridData; Label c1 = new Label(panel, SWT.NULL);//max upload gridData = new GridData(); gridData.horizontalSpan = 1; gridData.horizontalAlignment = GridData.END; c1.setLayoutData(gridData); c1.setText(label+" "); Label c2 = new Label(panel,SWT.NULL);//kbytes/sec gridData = new GridData(); gridData.horizontalSpan = 1; gridData.horizontalAlignment = GridData.CENTER; c2.setLayoutData(gridData); String estString = helper.getLimitText( estimate ); c2.setText(estString); Label c3 = new Label(panel,SWT.NULL);//kbits/sec gridData = new GridData(); gridData.horizontalSpan = 1; gridData.horizontalAlignment = GridData.BEGINNING; c3.setLayoutData(gridData); String maxBitsPerSec; if(maxKbps==0){ maxBitsPerSec = MessageText.getString("ConfigView.unlimited"); }else{ maxBitsPerSec = DisplayFormatters.formatByteCountToBitsPerSec( maxKbps * 1024 ); } c3.setText(maxBitsPerSec); } public boolean isPreviousEnabled(){ return false; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/speedtest/SpeedTestPanel.java0000644000175000017500000005731411046773330025150 0ustar adrianadrian/* * Created on Apr 30, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.speedtest; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import org.gudy.azureus2.ui.swt.wizard.WizardListener; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Cursors; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTestScheduledTest; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTestScheduledTestListener; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTesterListener; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTestScheduler; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTester; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTesterResult; import com.aelitis.azureus.core.networkmanager.admin.impl.NetworkAdminSpeedTestSchedulerImpl; public class SpeedTestPanel extends AbstractWizardPanel implements NetworkAdminSpeedTestScheduledTestListener, NetworkAdminSpeedTesterListener { private NetworkAdminSpeedTestScheduler nasts; private NetworkAdminSpeedTestScheduledTest scheduled_test; private Combo testCombo; private Button encryptToggle; private Color originalColor; private Button test; private Button abort; private Label testCountDown1; private Label testCountDown2; private Text textMessages; private ProgressBar progress; private Display display; private boolean test_running; private boolean switched_to_close; //measured upload and download results. int uploadTest, downloadTest; long maxUploadTest, maxDownloadTest; WizardListener clListener; private static final String START_VALUES = " - "; public SpeedTestPanel( SpeedTestWizard _wizard, IWizardPanel _previousPanel) { super( _wizard, _previousPanel ); wizard = _wizard; nasts = NetworkAdminSpeedTestSchedulerImpl.getInstance(); } public void show() { display = wizard.getDisplay(); wizard.setTitle(MessageText.getString( SpeedTestWizard.CFG_PREFIX + "run" )); wizard.setCurrentInfo( MessageText.getString("SpeedTestWizard.test.panel.currinfo") ); wizard.setPreviousEnabled(false); wizard.setFinishEnabled(false); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.FILL_BOTH); panel.setLayoutData(gridData); ///////////////////////////////////////// //Add group to link to Azureus Wiki page. ///////////////////////////////////////// Group azWiki = new Group(panel, SWT.WRAP); GridData azwGridData = new GridData(); azwGridData.widthHint = 350; azwGridData.horizontalSpan = 4; azWiki.setLayoutData(azwGridData); GridLayout azwLayout = new GridLayout(); azwLayout.numColumns = 1; //azwLayout.marginHeight = 1; azWiki.setLayout(azwLayout); azWiki.setText(MessageText.getString("Utils.link.visit")); final Label linkLabel = new Label(azWiki, SWT.NULL); linkLabel.setText( Constants.APP_NAME + " Wiki Speed Test" ); linkLabel.setData("http://www.azureuswiki.com/index.php/Speed_Test_FAQ"); linkLabel.setCursor(Cursors.handCursor); linkLabel.setForeground(Colors.blue); azwGridData = new GridData(); azwGridData.horizontalIndent = 10; linkLabel.setLayoutData( azwGridData ); linkLabel.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } public void mouseUp(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } }); //space line Label spacer = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 4; spacer.setLayoutData(gridData); //label explain section. layout = new GridLayout(); layout.numColumns = 4; panel.setLayout(layout); Label explain = new Label(panel, SWT.WRAP); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 4; explain.setLayoutData(gridData); Messages.setLanguageText(explain,"SpeedTestWizard.test.panel.explain"); //space line spacer = new Label(panel, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 4; spacer.setLayoutData(gridData); //label type and button section. Label ul = new Label(panel, SWT.NULL ); gridData = new GridData(); ul.setLayoutData(gridData); Messages.setLanguageText(ul,"SpeedTestWizard.test.panel.label"); testCombo = new Combo(panel, SWT.READ_ONLY); gridData = new GridData(GridData.FILL_HORIZONTAL); testCombo.setLayoutData(gridData); int[] test_types = NetworkAdminSpeedTester.TEST_TYPES; int up_only_index = 0; for (int i=0;i100 ) return 0; return progress; }//getProgressValueFromString protected void switchToClose() { switched_to_close = true; wizard.switchToClose(); } public boolean isFinishEnabled() { return( !( switched_to_close || test_running )); } public boolean isFinishSelectionOK() { return( !( switched_to_close || test_running )); } public IWizardPanel getFinishPanel() { return( this ); } public boolean isNextEnabled(){ //only enable after the test completes correctly. return ( (uploadTest>0 || downloadTest>0) && !test_running); }//isNextEnabled public IWizardPanel getNextPanel() { SpeedTestData persist = SpeedTestData.getInstance(); persist.setLastTestData( textMessages.getText() ); return new SpeedTestSetLimitPanel( wizard, this, uploadTest, maxUploadTest, downloadTest, maxDownloadTest); } /** * An abort button listener */ class AbortButtonListener implements Listener{ public void handleEvent(Event event) { //same action as "cancel" button. cancel(); test.setEnabled(true); abort.setEnabled(false); encryptToggle.setEnabled(true); wizard.setNextEnabled(false); uploadTest=0; downloadTest=0; String testAbortedManually = MessageText.getString("SpeedTestWizard.test.panel.aborted"); wizard.setErrorMessage(testAbortedManually); reportStage("\n"+testAbortedManually); }//handleEvent } /** * A run button listener */ class RunButtonListener implements Listener{ public void handleEvent(Event event) { abort.setEnabled(true); test.setEnabled(false); encryptToggle.setEnabled(false); wizard.setErrorMessage(""); wizard.setNextEnabled(false); textMessages.setText(""); finish(); }//handleEvent } /** * Run test with encryption toggle button listener. */ class EncryptToggleButtonListener implements Listener{ public void handleEvent(Event event){ if(encryptToggle.getSelection()){ Messages.setLanguageText(encryptToggle,"SpeedTestWizard.test.panel.encrypted"); originalColor = encryptToggle.getForeground(); //Color highlightColor = ColorCache.getColor(display,178,78,127); Color highlightColor = display.getSystemColor(SWT.COLOR_DARK_YELLOW); encryptToggle.setBackground(highlightColor); }else{ Messages.setLanguageText(encryptToggle,"SpeedTestWizard.test.panel.standard"); if(originalColor!=null){ encryptToggle.setBackground(originalColor); } } }//handleEvent } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/speedtest/SpeedTestData.java0000644000175000017500000000571010627446106024755 0ustar adrianadrian/** * Created on May 10, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.speedtest; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTesterResult; /** * Use this class to store data that should persist across panels. */ public class SpeedTestData { private static SpeedTestData ourInstance = new SpeedTestData(); private String lastTestData; private NetworkAdminSpeedTesterResult lastResult; private int highestDownloadOnlyResult; private int lastUploadOnlyResult; public static SpeedTestData getInstance() { return ourInstance; } private SpeedTestData() { } public void setLastTestData(String text){ lastTestData = text; } public String getLastTestData(){ return lastTestData; } public void setResult( NetworkAdminSpeedTesterResult result){ lastResult = result; } public NetworkAdminSpeedTesterResult getLastResult(){ return lastResult; } //Results needed for AutoSpeedV2. /** * We are keeping the highest download result, since we want results biased toward * fast downloads. * @param currDownRateInKBytePerSec - result of a "download only" test. */ public void setHighestDownloadResult(int currDownRateInKBytePerSec){ if( highestDownloadOnlyResultButton; using LinkedHashMap since the order the buttons are added is important */ private Map buttons = new LinkedHashMap(); protected SelectionListener defaultButtonListener; /** * A little extra margin so the buttons are a little wider; typically the native buttons * are just a little wider than the text but a slightly wider button looks nicer */ private int buttonExtraMargin = 50; public AbstractWizardPage(MultipageWizard wizard) { this.wizard = wizard; } /** * Returns the main Composite where subclasses can create controls */ public Composite createControls(Composite parent) { pageControl = new Composite(parent, SWT.NONE); pageControl.setBackground(Colors.red); GridLayout gLayout = new GridLayout(); gLayout.marginHeight = 0; gLayout.marginWidth = 0; gLayout.verticalSpacing = 0; pageControl.setLayout(gLayout); contentPanel = new Composite(pageControl, SWT.NONE); contentPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); Label separator2 = new Label(pageControl, SWT.SEPARATOR | SWT.HORIZONTAL); separator2.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); toolbarPanel = new Composite(pageControl, SWT.NONE); toolbarPanel.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false)); GridLayout gLayout2 = new GridLayout(3, false); gLayout2.marginHeight = 16; gLayout2.marginWidth = 16; toolbarPanel.setLayout(gLayout2); defaultButtonListener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { if (true == BUTTON_OK.equals(e.widget.getData("button.id"))) { performOK(); } else if (true == BUTTON_CANCEL.equals(e.widget.getData("button.id"))) { performCancel(); } else if (true == BUTTON_NEXT.equals(e.widget.getData("button.id"))) { performNext(); } else if (true == BUTTON_BACK.equals(e.widget.getData("button.id"))) { performBack(); } } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }; /* * This invisible label is used to ensure the buttons are flushed-right */ Label dummy = new Label(toolbarPanel, SWT.NONE); dummy.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); createButtons(toolbarPanel); return contentPanel; } public void fullScreen(boolean isFullScreen) { toolbarPanel.setVisible(false == isFullScreen); ((GridData) toolbarPanel.getLayoutData()).exclude = isFullScreen; pageControl.layout(true, true); getWizard().fullScreen(isFullScreen); } /** * Default buttons include Cancel, OK, Next, and Back * Subclasses may override to add more buttons or create a custom set of buttons * * @param buttonPanel */ protected void createButtons(Composite buttonPanel) { createButton(BUTTON_CANCEL, MessageText.getString("Button.cancel"), defaultButtonListener); createButton(BUTTON_BACK, MessageText.getString("wizard.previous"), defaultButtonListener); createButton(BUTTON_NEXT, MessageText.getString("wizard.next"), defaultButtonListener); createButton(BUTTON_OK, MessageText.getString("wizard.finish"), defaultButtonListener); } protected Button createButton(String buttonID, String buttonText, SelectionListener listener) { if (null == buttonID) { throw new IllegalArgumentException("A button requires a non-null ID"); } if (true == buttons.containsKey(buttonID)) { Debug.out("AbstractWizardPage:: a button with this same ID already exists ID:" + buttonID); return (Button) buttons.get(buttonID); } Button button = new Button(toolbarPanel, SWT.PUSH); GridData gData = new GridData(SWT.END, SWT.BOTTOM, false, false); gData.widthHint = button.computeSize(SWT.DEFAULT, SWT.DEFAULT).y + buttonExtraMargin; button.setLayoutData(gData); /* * Add listener if given; for default buttons this is used in place of the default listener */ if (null != listener) { button.addSelectionListener(listener); } button.setText(buttonText); button.setData("button.id", buttonID); buttons.put(buttonID, button); adjustToolbar(); return button; } /** * Enable/Disable the button with the given id * @param buttonID * @param value */ protected void enableButton(String buttonID, boolean value) { if (false == buttons.containsKey(buttonID)) { Debug.out("AbstractWizardPage:: a button with this ID is not found ID:" + buttonID); return; } ((Button) buttons.get(buttonID)).setEnabled(value); toolbarPanel.layout(true); } /** * Show or hide the button with the given id * @param buttonID * @param value */ protected void showButton(String buttonID, boolean value) { if (false == buttons.containsKey(buttonID)) { Debug.out("AbstractWizardPage:: a button with this ID is not found ID:" + buttonID); return; } Button button = (Button) buttons.get(buttonID); button.setVisible(value); if (true == value) { GridData gData = ((GridData) button.getLayoutData()); gData.exclude = false; gData.widthHint = button.computeSize(SWT.DEFAULT, SWT.DEFAULT).y + buttonExtraMargin; } else { GridData gData = ((GridData) button.getLayoutData()); gData.exclude = true; gData.widthHint = 0; } toolbarPanel.layout(true); } /** * Return the Button with the given id; returns null if button is not found * @param buttonID * @return */ protected Button getButton(String buttonID) { if (false == buttons.containsKey(buttonID)) { return null; } return (Button) buttons.get(buttonID); } /** * called when the default OK button is pressed */ public void performOK() { //Does nothing } /** * Called when the default Cancel button is pressed */ public void performCancel() { getWizard().performCancel(); } /** * Called when the default Next button is pressed */ public void performNext() { getWizard().performNext(); } /** * Called when the default Back button is pressed */ public void performBack() { getWizard().performBack(); } /** * Adjusting the number of columns to correspond with the number of buttons */ private void adjustToolbar() { /* * NOTE: we're adding 1 to the number of columns because there is always an invisible * label on the far left used for spacing so the buttons are right-aligned properly */ ((GridLayout) toolbarPanel.getLayout()).numColumns = buttons.size() + 1; toolbarPanel.layout(true); } public Control getControl() { return pageControl; } public MultipageWizard getWizard() { return wizard; } public String getDesciption() { return null; } public String getTitle() { return null; } public String getWindowTitle() { return null; } public boolean isComplete() { return false; } public void performDispose() { } public void performFinish() { } public boolean setComplete() { return true; } public void performAboutToBeHidden() { } public void performAboutToBeShown() { /* * If it's the last page then disable the 'Next' button; * if there is no 'Next' button this will do nothing */ if (null != getButton(BUTTON_NEXT)) { enableButton(BUTTON_NEXT, false == getWizard().isLastPage(getPageID())); } /* * If it's the first page then disable the 'Back' button; * if there is no 'Back' button this will do nothing */ if (null != getButton(BUTTON_BACK)) { enableButton(BUTTON_BACK, false == getWizard().isFirstPage(getPageID())); } } public boolean isInitOnStartup(){ return false; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/SpeedScaleShell.java0000644000175000017500000004237111064357126024560 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.shells; import java.util.Iterator; import java.util.LinkedHashMap; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; /** * Cheap ugly slider shell * * @author TuxPaper * @created Jul 5, 2007 * */ public class SpeedScaleShell { private static final boolean MOUSE_ONLY_UP_EXITS = true; private static final int OPTION_HEIGHT = 15; private static final int TEXT_HEIGHT = 32; private static final int SCALER_HEIGHT = 20; private int HEIGHT = TEXT_HEIGHT + SCALER_HEIGHT; private static final int WIDTH = 120; private static final int PADDING_X0 = 10; private static final int PADDING_X1 = 10; private static final int WIDTH_NO_PADDING = WIDTH - PADDING_X0 - PADDING_X1; private static final int TYPED_TEXT_ALPHA = 80; private static final long CLOSE_DELAY = 600; private int value; private boolean cancelled; private int minValue; private int maxValue; private int maxTextValue; private int pageIncrement; private int bigPageIncrement; private Shell shell; private LinkedHashMap mapOptions = new LinkedHashMap(); private String sValue = ""; private Composite composite; private boolean menuChosen; protected boolean lastMoveHadMouseDown; private boolean assumeInitiallyDown; private TimerEventPerformer cursorBlinkPerformer = null; private TimerEvent cursorBlinkEvent = null; public static void main(String[] args) { SpeedScaleShell speedScaleWidget = new SpeedScaleShell() { public String getStringValue() { return getValue() + "b/s"; } }; speedScaleWidget.setMaxValue(10000); speedScaleWidget.setMaxTextValue(15000); speedScaleWidget.addOption("AutoSpeed", -1); speedScaleWidget.addOption("Preset: 10b/s", 10); speedScaleWidget.addOption("Preset: 20b/s", 20); speedScaleWidget.addOption("Preset: 1b/s", 1); speedScaleWidget.addOption("Preset: 1000b/s", 1000); speedScaleWidget.addOption("Preset: A really long preset", 2000); System.out.println("returns " + speedScaleWidget.open(1000, Constants.isWindows) + " w/" + speedScaleWidget.getValue()); } public SpeedScaleShell() { minValue = 0; maxValue = -1; maxTextValue = -1; pageIncrement = 10; bigPageIncrement = 100; cancelled = true; menuChosen = false; } /** * Borks with 0 or -1 maxValue * * @param startValue * @param assumeInitiallyDown * @return * * @since 3.0.1.7 */ public boolean open(final int startValue, boolean _assumeInitiallyDown) { value = startValue; this.assumeInitiallyDown = _assumeInitiallyDown; if (assumeInitiallyDown) { lastMoveHadMouseDown = true; } cancelled = true; shell = new Shell(Utils.findAnyShell(), SWT.DOUBLE_BUFFERED | SWT.ON_TOP); shell.setLayout(new FillLayout()); final Display display = shell.getDisplay(); composite = new Composite(shell, SWT.DOUBLE_BUFFERED); final Point firstMousePos = display.getCursorLocation(); composite.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { setCancelled(true); shell.dispose(); } else if (e.detail == SWT.TRAVERSE_ARROW_NEXT) { setValue(value + 1); } else if (e.detail == SWT.TRAVERSE_ARROW_PREVIOUS) { setValue(value - 1); } else if (e.detail == SWT.TRAVERSE_PAGE_NEXT) { setValue(value + bigPageIncrement); } else if (e.detail == SWT.TRAVERSE_PAGE_PREVIOUS) { setValue(value - bigPageIncrement); } else if (e.detail == SWT.TRAVERSE_RETURN) { setCancelled(false); shell.dispose(); } } }); composite.addKeyListener(new KeyListener() { public void keyReleased(KeyEvent e) { } public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.PAGE_DOWN && e.stateMask == 0) { setValue(value + pageIncrement); } else if (e.keyCode == SWT.PAGE_UP && e.stateMask == 0) { setValue(value - pageIncrement); } else if (e.keyCode == SWT.HOME) { setValue(minValue); } else if (e.keyCode == SWT.END) { if (maxValue != -1) { setValue(maxValue); } } } }); composite.addMouseMoveListener(new MouseMoveListener() { public void mouseMove(MouseEvent e) { lastMoveHadMouseDown = false; boolean hasButtonDown = (e.stateMask & SWT.BUTTON_MASK) > 0 || assumeInitiallyDown; if (hasButtonDown) { if (e.y > HEIGHT - SCALER_HEIGHT) { lastMoveHadMouseDown = true; setValue(getValueFromMousePos(e.x)); } composite.redraw(); } else { composite.redraw(); } } }); composite.addMouseTrackListener(new MouseTrackListener() { boolean mouseIsOut = false; private boolean exitCancelled = false; public void mouseHover(MouseEvent e) { } public void mouseExit(MouseEvent e) { mouseIsOut = true; SimpleTimer.addEvent("close scaler", SystemTime.getOffsetTime(CLOSE_DELAY), new TimerEventPerformer() { public void perform(TimerEvent event) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (!exitCancelled) { shell.dispose(); } else { exitCancelled = false; } } }); } }); } public void mouseEnter(MouseEvent e) { if (mouseIsOut) { exitCancelled = true; } mouseIsOut = false; } }); composite.addMouseListener(new MouseListener() { boolean bMouseDown = false; public void mouseUp(MouseEvent e) { if (assumeInitiallyDown) { //System.out.println("assumed down"); assumeInitiallyDown = false; } if (MOUSE_ONLY_UP_EXITS) { //System.out.println("last move had mouse down: " + lastMoveHadMouseDown); if (lastMoveHadMouseDown) { Point mousePos = display.getCursorLocation(); //System.out.println("first=" + firstMousePos + ";mouse= " + mousePos); if (mousePos.equals(firstMousePos)) { lastMoveHadMouseDown = false; return; } } bMouseDown = true; } if (bMouseDown) { if (e.y > HEIGHT - SCALER_HEIGHT) { setValue(getValueFromMousePos(e.x)); setCancelled(false); if (lastMoveHadMouseDown) { shell.dispose(); } } else if (e.y > TEXT_HEIGHT) { int idx = (e.y - TEXT_HEIGHT) / OPTION_HEIGHT; Iterator iterator = mapOptions.keySet().iterator(); int newValue; do { newValue = ((Integer) iterator.next()).intValue(); idx--; } while (idx >= 0); value = newValue; // ignore min/max setCancelled(false); setMenuChosen(true); shell.dispose(); } } } public void mouseDown(MouseEvent e) { if (e.count > 1) { lastMoveHadMouseDown = true; return; } Point mousePos = display.getCursorLocation(); if (e.y > HEIGHT - SCALER_HEIGHT) { bMouseDown = true; setValue(getValueFromMousePos(e.x)); } } public void mouseDoubleClick(MouseEvent e) { } }); composite.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { int x = WIDTH_NO_PADDING * value / maxValue; if (x < 0) { x = 0; } else if (x > WIDTH_NO_PADDING) { x = WIDTH_NO_PADDING; } int startX = WIDTH_NO_PADDING * startValue / maxValue; if (startX < 0) { startX = 0; } else if (startX > WIDTH_NO_PADDING) { startX = WIDTH_NO_PADDING; } int baseLinePos = getBaselinePos(); try { e.gc.setAdvanced(true); e.gc.setAntialias(SWT.ON); } catch (Exception ex) { // aw } e.gc.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); // left e.gc.drawLine(PADDING_X0, baseLinePos - 6, PADDING_X0, baseLinePos + 6); // right e.gc.drawLine(PADDING_X0 + WIDTH_NO_PADDING, baseLinePos - 6, PADDING_X0 + WIDTH_NO_PADDING, baseLinePos + 6); // baseline e.gc.drawLine(PADDING_X0, baseLinePos, PADDING_X0 + WIDTH_NO_PADDING, baseLinePos); e.gc.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_FOREGROUND)); e.gc.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_FOREGROUND)); // start value marker e.gc.drawLine(PADDING_X0 + startX, baseLinePos - 5, PADDING_X0 + startX, baseLinePos + 5); // current value marker e.gc.fillRoundRectangle(PADDING_X0 + x - 2, baseLinePos - 5, 5, 10, 10, 10); // Current Value Text e.gc.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); e.gc.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); e.gc.fillRectangle(0, 0, WIDTH, TEXT_HEIGHT); GCStringPrinter.printString(e.gc, _getStringValue(), new Rectangle(0, 0, WIDTH, HEIGHT), true, false, SWT.CENTER | SWT.TOP | SWT.WRAP); e.gc.drawLine(0, TEXT_HEIGHT - 1, WIDTH, TEXT_HEIGHT - 1); // options list int y = TEXT_HEIGHT; Point mousePos = composite.toControl(display.getCursorLocation()); for (Iterator iter = mapOptions.keySet().iterator(); iter.hasNext();) { Integer value = (Integer) iter.next(); String text = (String) mapOptions.get(value); Rectangle area = new Rectangle(0, y, WIDTH, OPTION_HEIGHT); Color bg; if (area.contains(mousePos)) { bg = display.getSystemColor(SWT.COLOR_LIST_SELECTION); e.gc.setBackground(bg); e.gc.setForeground(display.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); e.gc.fillRectangle(area); } else { bg = display.getSystemColor(SWT.COLOR_LIST_BACKGROUND); e.gc.setBackground(bg); e.gc.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); } int ovalSize = OPTION_HEIGHT - 6; if (getValue() == value.intValue()) { Color saveColor = e.gc.getBackground(); e.gc.setBackground(e.gc.getForeground()); e.gc.fillOval(4, y + 5, ovalSize - 3, ovalSize - 3); e.gc.setBackground(saveColor); } if (Constants.isLinux) { // Hack: on linux, drawing oval seems to draw a line from last pos // to start of oval.. drawing a point (anywhere) seems to clear the // path Color saveColor = e.gc.getForeground(); e.gc.setForeground(bg); e.gc.drawPoint(2, y + 3); e.gc.setForeground(saveColor); } e.gc.drawOval(2, y + 3, ovalSize, ovalSize); GCStringPrinter.printString(e.gc, text, new Rectangle(OPTION_HEIGHT, y, WIDTH - OPTION_HEIGHT, OPTION_HEIGHT), true, false, SWT.LEFT); y += OPTION_HEIGHT; } // typed value if (sValue.length() > 0) { Point extent = e.gc.textExtent(sValue); if (extent.x > WIDTH - 10) { extent.x = WIDTH - 10; } Rectangle rect = new Rectangle(WIDTH - 8 - extent.x, 14, extent.x + 5, extent.y + 4 + 14 > TEXT_HEIGHT ? TEXT_HEIGHT - 15 : extent.y + 4); e.gc.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); e.gc.fillRectangle(rect); try { e.gc.setAlpha(TYPED_TEXT_ALPHA); } catch (Exception ex) { } e.gc.setBackground(display.getSystemColor(SWT.COLOR_LIST_BACKGROUND)); e.gc.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); //e.gc.drawRectangle(rect); GCStringPrinter.printString(e.gc, sValue, new Rectangle(rect.x + 2, rect.y + 2, WIDTH - 5, OPTION_HEIGHT), true, false, SWT.LEFT | SWT.BOTTOM); } } }); // blinking cursor so people know they can type final AERunnable cursorBlinkRunnable = new AERunnable() { boolean on = false; public void runSupport() { if (composite.isDisposed()) { return; } on = !on; GC gc = new GC(composite); try { gc.setLineWidth(2); if (!on) { gc.setForeground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); } else { try { gc.setAlpha(TYPED_TEXT_ALPHA); } catch (Exception e) { } } int y = 15; gc.drawLine(WIDTH - 5, y + 1, WIDTH - 5, y + OPTION_HEIGHT); } finally { gc.dispose(); } if (cursorBlinkPerformer != null) { cursorBlinkEvent = SimpleTimer.addEvent("BlinkingCursor", SystemTime.getOffsetTime(500), cursorBlinkPerformer); } } }; cursorBlinkPerformer = new TimerEventPerformer() { public void perform(final TimerEvent event) { Utils.execSWTThread(cursorBlinkRunnable); } }; cursorBlinkEvent = SimpleTimer.addEvent("BlinkingCursor", SystemTime.getOffsetTime(500), cursorBlinkPerformer); composite.addKeyListener(new KeyListener() { public void keyReleased(KeyEvent e) { } public void keyPressed(KeyEvent e) { if (Character.isDigit(e.character)) { sValue += e.character; } else if (e.keyCode == SWT.BS && sValue.length() > 0) { sValue = sValue.substring(0, sValue.length() - 1); } else { return; } try { int newValue = Integer.parseInt(sValue); if (maxTextValue == -1) { setValue(newValue); } else { if (minValue > 0 && newValue < minValue) { newValue = minValue; } if (newValue > maxTextValue) { newValue = maxTextValue; } value = newValue; composite.redraw(); } } catch (Exception ex) { setValue(startValue); } } }); Point location = display.getCursorLocation(); location.y -= getBaselinePos(); int x = (int) (WIDTH_NO_PADDING * (value > maxValue ? 1 : (double) value / maxValue)); location.x -= PADDING_X0 + x; Rectangle bounds = new Rectangle(location.x, location.y, WIDTH, HEIGHT); Monitor mouseMonitor = shell.getMonitor(); Monitor[] monitors = display.getMonitors(); for (int i = 0; i < monitors.length; i++) { Monitor monitor = monitors[i]; if (monitor.getBounds().contains(location)) { mouseMonitor = monitor; break; } } Rectangle monitorBounds = mouseMonitor.getBounds(); Rectangle intersection = monitorBounds.intersection(bounds); if (intersection.width != bounds.width) { bounds.x = monitorBounds.x + monitorBounds.width - WIDTH; bounds.width = WIDTH; } if (intersection.height != bounds.height) { bounds.y = monitorBounds.y + monitorBounds.height - HEIGHT; bounds.height = HEIGHT; } shell.setBounds(bounds); if (!bounds.contains(firstMousePos)) { // should never happen, which means it probably will, so handle it badly shell.setLocation(firstMousePos.x - (bounds.width / 2), firstMousePos.y - bounds.height + 2); } shell.open(); // must be after, for OSX composite.setFocus(); try { while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } catch (Throwable t) { Debug.out(t); } if (cursorBlinkEvent != null) { cursorBlinkEvent.cancel(); cursorBlinkEvent = null; } return !cancelled; } /** * @param x * @return * * @since 3.0.1.7 */ protected int getValueFromMousePos(int x) { int x0 = x + 1; if (x < PADDING_X0) { x0 = PADDING_X0; } else if (x > PADDING_X0 + WIDTH_NO_PADDING) { x0 = PADDING_X0 + WIDTH_NO_PADDING; } return (x0 - PADDING_X0) * maxValue / WIDTH_NO_PADDING; } public int getValue() { return value; } public boolean isCancelled() { return cancelled; } public void setCancelled(boolean cancelled) { this.cancelled = cancelled; } public int getMinValue() { return minValue; } public void setMinValue(int minValue) { this.minValue = minValue; } public int getMaxValue() { return maxValue; } public void setMaxValue(int maxValue) { this.maxValue = maxValue; } public void setValue(int value) { //System.out.println("sv " + value + ";" + Debug.getCompressedStackTrace()); if (value > maxValue) { value = maxValue; } else if (value < minValue) { value = minValue; } this.value = value; if (composite != null && !composite.isDisposed()) { composite.redraw(); } } public String _getStringValue() { String name = (String) mapOptions.get(new Integer(value)); return getStringValue(value, name); } public String getStringValue(int value, String sValue) { if (sValue != null) { return sValue; } return "" + value; } private int getBaselinePos() { return HEIGHT - (SCALER_HEIGHT / 2); } public void addOption(String id, int value) { mapOptions.put(new Integer(value), id); HEIGHT += OPTION_HEIGHT; } public int getMaxTextValue() { return maxTextValue; } public void setMaxTextValue(int maxTextValue) { this.maxTextValue = maxTextValue; } public boolean wasMenuChosen() { return menuChosen; } public void setMenuChosen(boolean menuChosen) { this.menuChosen = menuChosen; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/MessageBoxShell.java0000644000175000017500000007055511274266452024616 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.shells; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter.URLInfo; import com.aelitis.azureus.ui.UserPrompterResultListener; import com.aelitis.azureus.ui.UIFunctionsUserPrompter; import com.aelitis.azureus.ui.common.RememberedDecisionsManager; import com.aelitis.azureus.ui.swt.UISkinnableManagerSWT; import com.aelitis.azureus.ui.swt.UISkinnableSWTListener; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.utils.ColorCache; /** * A messagebox that allows you config the button * * @todo When key is pressed, cancel auto close timer */ public class MessageBoxShell implements UIFunctionsUserPrompter { public static final String STATUS_TEXT_CLOSE = "__VUZE__MessageBoxShell__CLOSE"; private final static int MIN_SIZE_X_DEFAULT = 300; private final static int MIN_SIZE_Y_DEFAULT = 120; private final static int MAX_SIZE_X_DEFAULT = 500; private static final int MIN_BUTTON_SIZE = 70; private static int numOpen = 0; private Shell parent; private int min_size_x = MIN_SIZE_X_DEFAULT; private int min_size_y = MIN_SIZE_Y_DEFAULT; private int max_size_x = MAX_SIZE_X_DEFAULT; private final String title; private final String text; private String[] buttons; private Integer[] buttonVals; private int defaultButtonPos; private String rememberID = null; private String rememberText = null; private boolean rememberByDefault = false; private int rememberOnlyIfButtonPos = -1; private int autoCloseInMS = 0; private String html; private String url; private boolean squish; private boolean autoClosed = false; private Object[] relatedObjects; private Image imgLeft; protected Color urlColor; private boolean handleHTML = true; private Image iconImage; private Browser shell_browser; private boolean browser_follow_links; protected boolean isRemembered; private String iconImageID; private UserPrompterResultListener resultListener; private int result; private Listener filterListener; private Shell shell; private boolean opened; public static void open(Shell parent, String title, String text, String[] buttons, int defaultOption, String rememberID, String rememberText, boolean bRememberByDefault, int autoCloseInMS, UserPrompterResultListener l) { MessageBoxShell messageBoxShell = new MessageBoxShell(title, text, buttons, defaultOption); messageBoxShell.setRemember(rememberID, bRememberByDefault, rememberText); messageBoxShell.setAutoCloseInMS(autoCloseInMS); messageBoxShell.setParent(parent); messageBoxShell.open(l); } public static boolean isOpen() { return numOpen > 0; } /** * @param shellForChildren * @param string * @param string2 * @param strings */ public MessageBoxShell(final String title, final String text, final String[] buttons, final int defaultOption) { this.title = title; this.text = text; this.buttons = buttons; this.defaultButtonPos = defaultOption; } /** * ONLY FOR OLD EMP. DO NOT USE */ @Deprecated public MessageBoxShell(Shell parent, final String title, final String text, final String[] buttons, final int defaultOption) { this(title, text, buttons, defaultOption); this.parent = parent; } public MessageBoxShell(String title, String text) { this(title, text, null, 0); } /** Open a messagebox using resource keys for title/text * * @param parent Parent shell for messagebox * @param style SWT styles for messagebox * @param keyPrefix message bundle key prefix used to get title and text. * Title will be keyPrefix + ".title", and text will be set to * keyPrefix + ".text" * @param textParams any parameters for text */ public MessageBoxShell(int style, String keyPrefix, String[] textParams) { if ((style & (0x7f << 5)) == 0) { // need at least one button style |= SWT.OK; } final Object[] buttonInfo = swtButtonStylesToText(style); this.title = MessageText.getString(keyPrefix + ".title"); this.text = MessageText.getString(keyPrefix + ".text", textParams); this.buttons = (String[]) buttonInfo[0]; this.defaultButtonPos = 0; this.rememberID = null; this.rememberText = null; this.rememberByDefault = false; this.autoCloseInMS = -1; this.buttonVals = (Integer[]) buttonInfo[1]; setLeftImage(style & 0x1f); } /** Open a messagebox with actual title and text * * @param parent * @param style * @param title * @param text * @return */ public MessageBoxShell(int style, String title, String text) { if ((style & (0x7f << 5)) == 0) { // need at least one button style |= SWT.OK; } final Object[] buttonInfo = swtButtonStylesToText(style); this.title = title; this.text = text; this.buttons = (String[]) buttonInfo[0]; this.defaultButtonPos = 0; this.rememberID = null; this.rememberText = null; this.rememberByDefault = false; this.autoCloseInMS = -1; this.buttonVals = (Integer[]) buttonInfo[1]; setLeftImage(style & 0x1f); } public void setDefaultButtonUsingStyle(int defaultStyle) { Object[] defaultButtonInfo = swtButtonStylesToText(defaultStyle); int defaultIndex = 0; if (defaultButtonInfo.length > 0) { String name = ((String[]) defaultButtonInfo[0])[0]; for (int i = 0; i < buttons.length; i++) { if (buttons[i].equals(name)) { defaultIndex = i; break; } } } defaultButtonPos = defaultIndex; } /** * ONLY FOR OLD EMP. DO NOT USE. *

* Use {@link #open(UserPrompterResultListener)} * @return */ @Deprecated public int open() { open(false); return waitUntilClosed(); } public void open(UserPrompterResultListener l) { this.resultListener = l; open(false); } private void triggerResultListener(final int returnVal) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { if (resultListener == null) { return; } int realResult = getButtonVal(returnVal); resultListener.prompterClosed(realResult); } }); } private int getButtonVal(int buttonPos) { if (buttonVals == null) { return buttonPos; } if (buttonPos < 0 || buttonPos >= buttonVals.length) { return SWT.CANCEL; } return buttonVals[buttonPos].intValue(); } private int getButtonPos(int buttonVal) { if (buttonVals == null) { return buttonVal; } for (int i = 0; i < buttonVals.length; i++) { if (buttonVals[i] == buttonVal) { return i; } } return -1; } private void open(final boolean useCustomShell) { if (rememberID != null) { int rememberedDecision = RememberedDecisionsManager.getRememberedDecision(rememberID); if (rememberedDecision >= 0 && (rememberOnlyIfButtonPos == -1 || rememberOnlyIfButtonPos == getButtonPos(rememberedDecision))) { result = getButtonPos(rememberedDecision); triggerResultListener(result); return; } } Utils.execSWTThread(new AERunnable() { public void runSupport() { _open(); } }, false); return; } private void _open() { result = -1; boolean ourParent = false; if (parent == null || parent.isDisposed()) { parent = Utils.findAnyShell(); ourParent = true; if (parent == null || parent.isDisposed()) { triggerResultListener(result); return; } } MouseTrackAdapter mouseAdapter = null; final Display display = parent.getDisplay(); shell = ShellFactory.createShell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL); if (title != null) { shell.setText(title); } shell.setBackgroundMode(SWT.INHERIT_DEFAULT); shell.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event event) { if (iconImageID != null) { ImageLoader.getInstance().releaseImage(iconImageID); } triggerResultListener(result); if (display != null && !display.isDisposed() && filterListener != null) { display.removeFilter(SWT.Traverse, filterListener); } numOpen--; } }); GridLayout gridLayout = new GridLayout(); if ( squish ){ gridLayout.verticalSpacing = 0; gridLayout.horizontalSpacing = 0; gridLayout.marginLeft = 0; gridLayout.marginRight = 0; gridLayout.marginTop = 0; gridLayout.marginBottom = 0; gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; } shell.setLayout(gridLayout); Utils.setShellIcon(shell); UISkinnableSWTListener[] listeners = UISkinnableManagerSWT.getInstance().getSkinnableListeners( MessageBoxShell.class.toString()); for (int i = 0; i < listeners.length; i++) { listeners[i].skinBeforeComponents(shell, this, relatedObjects); } FormData formData; GridData gridData; Composite textComposite = shell; if (imgLeft != null) { textComposite = new Composite(shell, SWT.NONE); textComposite.setForeground(shell.getForeground()); GridLayout gl = new GridLayout(2, false); gl.horizontalSpacing = 10; textComposite.setLayout(gl); textComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); Label lblImage = new Label(textComposite, SWT.NONE); lblImage.setImage(imgLeft); lblImage.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); } Control linkControl; if ( text != null && text.length() > 0 ){ linkControl = createLinkLabel(textComposite, text); }else{ linkControl = null; } if ((html != null && html.length() > 0) || (url != null && url.length() > 0)) { try { final Browser browser = shell_browser = Utils.createSafeBrowser(shell, SWT.NONE); if (url != null && url.length() > 0) { browser.setUrl(url); } else { browser.setText(html); } GridData gd = new GridData(GridData.FILL_BOTH); gd.heightHint = 200; browser.setLayoutData(gd); browser.addProgressListener(new ProgressListener() { public void completed(ProgressEvent event) { if (shell == null || shell.isDisposed()) { return; } browser.addLocationListener(new LocationListener() { public void changing(LocationEvent event) { event.doit = browser_follow_links; } public void changed(LocationEvent event) { } }); browser.addOpenWindowListener(new OpenWindowListener() { public void open(WindowEvent event) { event.required = true; } }); } public void changed(ProgressEvent event) { } }); browser.addStatusTextListener(new StatusTextListener() { public void changed(StatusTextEvent event) { if(STATUS_TEXT_CLOSE.equals(event.text)) { //For some reason disposing the shell / browser in the same Thread makes //ieframe.dll crash on windows. Utils.execSWTThreadLater(0, new Runnable() { public void run() { if(!browser.isDisposed() && ! shell.isDisposed()) { shell.close(); } } }); } } }); } catch (Exception e) { Debug.out(e); if (html != null) { Text text = new Text(shell, SWT.BORDER | SWT.READ_ONLY | SWT.WRAP); text.setText(html); GridData gd = new GridData(GridData.FILL_BOTH); gd.heightHint = 200; text.setLayoutData(gd); } } if ( linkControl != null ){ gridData = new GridData(GridData.FILL_HORIZONTAL); linkControl.setLayoutData(gridData); } } else { if ( linkControl != null ){ gridData = new GridData(GridData.FILL_BOTH); linkControl.setLayoutData(gridData); } } if (!squish && (autoCloseInMS > 0 || rememberID != null)) { Label lblPadding = new Label(shell, SWT.NONE ); lblPadding.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); } // Closing in.. if (autoCloseInMS > 0) { final Label lblCloseIn = new Label(shell, SWT.WRAP); lblCloseIn.setForeground(shell.getForeground()); lblCloseIn.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); long endOn = SystemTime.getCurrentTime() + autoCloseInMS; lblCloseIn.setData("CloseOn", new Long(endOn)); SimpleTimer.addPeriodicEvent("autoclose", 500, new TimerEventPerformer() { public void perform(TimerEvent event) { if (shell.isDisposed()) { event.cancel(); return; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (!shell.isDisposed()) { boolean bDelayPaused = lblCloseIn.getData("DelayPaused") != null; if (bDelayPaused) { return; } long endOn = ((Long) lblCloseIn.getData("CloseOn")).longValue(); if (SystemTime.getCurrentTime() > endOn) { result = defaultButtonPos; autoClosed = true; shell.dispose(); } else { String sText = ""; if (lblCloseIn.isDisposed()) return; if (!bDelayPaused) { long delaySecs = (endOn - SystemTime.getCurrentTime()) / 1000; sText = MessageText.getString("popup.closing.in", new String[] { String.valueOf(delaySecs) }); } lblCloseIn.setText(sText); } } }; }); } }); SimpleTimer.addPeriodicEvent("OverPopup", 100, new TimerEventPerformer() { boolean wasOver = true; long lEnterOn = 0; public void perform(final TimerEvent event) { if (shell.isDisposed()) { event.cancel(); return; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (shell.isDisposed()) { event.cancel(); return; } boolean isOver = shell.getBounds().contains( shell.getDisplay().getCursorLocation()); if (isOver != wasOver) { wasOver = isOver; if (isOver) { lblCloseIn.setData("DelayPaused", ""); lEnterOn = SystemTime.getCurrentTime(); lblCloseIn.setText(""); } else { lblCloseIn.setData("DelayPaused", null); if (lEnterOn > 0) { long diff = SystemTime.getCurrentTime() - lEnterOn; long endOn = ((Long) lblCloseIn.getData("CloseOn")).longValue() + diff; lblCloseIn.setData("CloseOn", new Long(endOn)); } } } } }); } }); } // Remember Me Button checkRemember = null; if (rememberID != null) { checkRemember = new Button(shell, SWT.CHECK); checkRemember.setText(rememberText); checkRemember.setSelection(rememberByDefault); isRemembered = rememberByDefault; checkRemember.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { Button checkRemember = (Button) event.widget; isRemembered = checkRemember.getSelection(); } }); checkRemember.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { Button checkRemember = (Button) e.widget; isRemembered = checkRemember != null && checkRemember.getSelection(); if (rememberID != null && isRemembered && (rememberOnlyIfButtonPos == -1 || rememberOnlyIfButtonPos == result)) { RememberedDecisionsManager.setRemembered(rememberID, getButtonVal(result)); } } }); } // Buttons if ( buttons.length > 0 ){ Label labelSeparator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL); labelSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Composite cButtons = new Composite(shell, SWT.NONE); FormLayout layout = new FormLayout(); cButtons.setLayout(layout); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); cButtons.setLayoutData(gridData); Control lastButton = null; Listener buttonListener = new Listener() { public void handleEvent(Event event) { result = ((Integer) event.widget.getData()).intValue(); shell.dispose(); } }; int buttonWidth = 0; Button[] swtButtons = new Button[buttons.length]; for (int i = 0; i < buttons.length; i++) { Button button = new Button(cButtons, SWT.PUSH); swtButtons[i] = button; button.setData(new Integer(i)); button.setText(buttons[i]); button.addListener(SWT.Selection, buttonListener); formData = new FormData(); if (lastButton != null) { formData.left = new FormAttachment(lastButton, 5); } button.setLayoutData(formData); Point size = button.computeSize(SWT.DEFAULT, SWT.DEFAULT); if (size.x > buttonWidth) { buttonWidth = size.x; } if (i == defaultButtonPos) { button.setFocus(); shell.setDefaultButton(button); } lastButton = button; } if (buttonWidth > 0) { if (buttonWidth < MIN_BUTTON_SIZE) { buttonWidth = MIN_BUTTON_SIZE; } for (int i = 0; i < buttons.length; i++) { Point size = swtButtons[i].computeSize(buttonWidth, SWT.DEFAULT); swtButtons[i].setSize(size); formData = (FormData) swtButtons[i].getLayoutData(); formData.width = buttonWidth; } } } shell.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent event) { if (event.detail == SWT.TRAVERSE_ESCAPE) { shell.dispose(); } } }); filterListener = new Listener() { public void handleEvent(Event event) { if (event.detail == SWT.TRAVERSE_ARROW_NEXT) { event.detail = SWT.TRAVERSE_TAB_NEXT; event.doit = true; } else if (event.detail == SWT.TRAVERSE_ARROW_PREVIOUS) { event.detail = SWT.TRAVERSE_TAB_PREVIOUS; event.doit = true; } } }; display.addFilter(SWT.Traverse, filterListener); if (mouseAdapter != null) { addMouseTrackListener(shell, mouseAdapter); } shell.pack(); Point size = shell.getSize(); if (size.x < min_size_x) { size.x = min_size_x; shell.setSize(size); } else if (size.x > max_size_x) { size = shell.computeSize(max_size_x, SWT.DEFAULT); shell.setSize(size); } if (size.y < min_size_y) { size.y = min_size_y; shell.setSize(size); } Shell centerRelativeToShell = parent; if (ourParent) { Control cursorControl = display.getCursorControl(); if (cursorControl != null) { centerRelativeToShell = cursorControl.getShell(); } } Utils.centerWindowRelativeTo(shell, centerRelativeToShell); for (int i = 0; i < listeners.length; i++) { listeners[i].skinAfterComponents(shell, this, relatedObjects); } shell.open(); opened = true; numOpen++; return; } /** * Adds mousetracklistener to composite and all it's children * * @param parent Composite to start at * @param listener Listener to add */ private void addMouseTrackListener(Composite parent, MouseTrackListener listener) { if (parent == null || listener == null || parent.isDisposed()) return; parent.addMouseTrackListener(listener); Control[] children = parent.getChildren(); for (int i = 0; i < children.length; i++) { Control control = children[i]; if (control instanceof Composite) addMouseTrackListener((Composite) control, listener); else control.addMouseTrackListener(listener); } } private Canvas createLinkLabel(final Composite shell, final String text) { final Canvas canvas = new Canvas(shell, SWT.None) { public Point computeSize(int wHint, int hHint, boolean changed) { Rectangle area = new Rectangle(0, 0, wHint < 0 ? max_size_x : wHint, 5000); GC gc = new GC(this); GCStringPrinter sp = new GCStringPrinter(gc, text, area, true, false, SWT.WRAP | SWT.TOP); sp.calculateMetrics(); gc.dispose(); Point size = sp.getCalculatedSize(); return size; } }; Listener l = new Listener() { GCStringPrinter sp; public void handleEvent(Event e) { if (!handleHTML) { if (e.type == SWT.Paint) { Rectangle area = canvas.getClientArea(); e.gc.setForeground(shell.getForeground()); GCStringPrinter.printString(e.gc, text, area, true, false, SWT.WRAP | SWT.TOP); } return; } if (e.type == SWT.Paint) { Rectangle area = canvas.getClientArea(); sp = new GCStringPrinter(e.gc, text, area, true, false, SWT.WRAP | SWT.TOP); sp.setUrlColor(ColorCache.getColor(e.gc.getDevice(), "#0000ff")); if (urlColor != null) { sp.setUrlColor(urlColor); } e.gc.setForeground(shell.getForeground()); sp.printString(); } else if (e.type == SWT.MouseMove) { if (sp != null) { URLInfo hitUrl = sp.getHitUrl(e.x, e.y); if (hitUrl != null) { canvas.setCursor(canvas.getDisplay().getSystemCursor( SWT.CURSOR_HAND)); canvas.setToolTipText(hitUrl.url); } else { canvas.setCursor(canvas.getDisplay().getSystemCursor( SWT.CURSOR_ARROW)); canvas.setToolTipText(null); } } } else if (e.type == SWT.MouseUp) { if (sp != null) { URLInfo hitUrl = sp.getHitUrl(e.x, e.y); if (hitUrl != null && !hitUrl.url.startsWith(":")) { Utils.launch(hitUrl.url); } } } } }; canvas.addListener(SWT.Paint, l); if (handleHTML) { canvas.addListener(SWT.MouseMove, l); canvas.addListener(SWT.MouseUp, l); } ClipboardCopy.addCopyToClipMenu(canvas, new ClipboardCopy.copyToClipProvider() { public String getText() { return (text); } }); return canvas; } public String getHtml() { return html; } public void setHtml(String html) { this.html = html; } public void setUrl(String url) { this.url = url; } public void setSize( int width, int height ) { min_size_x = width; max_size_x = width; min_size_y = height; } /** * @return the rememberID */ public String getRememberID() { return rememberID; } /** * * @param rememberID * @param rememberByDefault * @param rememberText null if you want the default */ public void setRemember(String rememberID, boolean rememberByDefault, String rememberText) { this.rememberID = rememberID; this.rememberByDefault = rememberByDefault; this.rememberText = rememberText; if (this.rememberText == null) { this.rememberText = MessageText.getString("MessageBoxWindow.rememberdecision"); } } /** * @return the rememberText */ public String getRememberText() { return rememberText; } /** * @param rememberText the rememberText to set */ public void setRememberText(String rememberText) { this.rememberText = rememberText; } /** * @return the autoCloseInMS */ public int getAutoCloseInMS() { return autoCloseInMS; } /** * @param autoCloseInMS the autoCloseInMS to set */ public void setAutoCloseInMS(int autoCloseInMS) { this.autoCloseInMS = autoCloseInMS; } public void setSquish( boolean b ){ squish = b; } /** * @return the autoClosed */ public boolean isAutoClosed() { return autoClosed; } // @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#setRelatedObject(java.lang.Object) public void setRelatedObject(Object relatedObject) { this.relatedObjects = new Object[] { relatedObject }; } // @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#setRelatedObjects(java.lang.Object[]) public void setRelatedObjects(Object[] relatedObjects) { this.relatedObjects = relatedObjects; } public Object[] getRelatedObjects() { return relatedObjects; } /** * @return * * @since 4.0.0.1 */ public Object getLeftImage() { return imgLeft == iconImage ? null : imgLeft; } public void setLeftImage(Image imgLeft) { this.imgLeft = imgLeft; } /** * Replaces Image on left with icon * * @param icon SWT.ICON_ERROR, ICON_INFORMATION, ICON_QUESTION, ICON_WARNING, ICON_WORKING * * @since 3.0.1.7 */ public void setLeftImage(final int icon) { Utils.execSWTThread(new AERunnable() { public void runSupport() { setLeftImage(Display.getDefault().getSystemImage(icon)); iconImage = Display.getDefault().getSystemImage(icon); } }); } public void setIconResource(String resource) { iconImageID = null; if (resource.equals("info")) { iconImage = Display.getDefault().getSystemImage(SWT.ICON_INFORMATION); } else if (resource.equals("warning")) { iconImage = Display.getDefault().getSystemImage(SWT.ICON_WARNING); } else if (resource.equals("error")) { iconImage = Display.getDefault().getSystemImage(SWT.ICON_ERROR); } else { iconImage = ImageLoader.getInstance().getImage(resource); iconImageID = resource; } setLeftImage(iconImage); } public static void main(String[] args) { Display display = Display.getDefault(); Shell shell = new Shell(display, SWT.SHELL_TRIM); shell.open(); MessageBoxShell messageBoxShell = new MessageBoxShell( "Title", "Test\n" + "THis is a very long line that tests whether the box gets really wide which is something we don't want.\n" + "A link for you", new String[] { "Okay", "Cancyyyyyy", "Maybe" }, 1); messageBoxShell.setRemember("test2", false, MessageText.getString("MessageBoxWindow.nomoreprompting")); messageBoxShell.setAutoCloseInMS(15000); messageBoxShell.setParent(shell); messageBoxShell.setHtml("Moo goes the cow


"); messageBoxShell.open(new UserPrompterResultListener() { public void prompterClosed(int returnVal) { System.out.println(returnVal); } }); while (!shell.isDisposed()) { if (!display.isDisposed() && !display.readAndDispatch()) { display.sleep(); } } } public int getRememberOnlyIfButton() { return rememberOnlyIfButtonPos; } public void setRememberOnlyIfButton(int rememberOnlyIfButton) { this.rememberOnlyIfButtonPos = rememberOnlyIfButton; } public Color getUrlColor() { return urlColor; } public void setBrowserFollowLinks( boolean follow ) { browser_follow_links = follow; } public void setUrlColor(Color colorURL) { this.urlColor = colorURL; } /** * @param b * * @since 3.0.5.3 */ public void setHandleHTML(boolean handleHTML) { this.handleHTML = handleHTML; } public boolean isRemembered() { return isRemembered; } /** * NOT RECOMMENDED! *

* TODO: Occasionaly inspect list of callers and make them use * {@link UserPrompterResultListener} if possible */ public int waitUntilClosed() { Utils.execSWTThreadWithBool("waitUntilClose", new AERunnableBoolean() { public boolean runSupport() { if (shell == null) { return false; } if (!opened) { shell.open(); } while (shell != null && !shell.isDisposed()) { if (shell.getDisplay() != null && !shell.getDisplay().readAndDispatch()) { shell.getDisplay().sleep(); } } return true; } }); int realResult = getButtonVal(result); return realResult; } public int getResult() { return result; } private static Object[] swtButtonStylesToText(int style) { List buttons = new ArrayList(2); List buttonVal = new ArrayList(2); int buttonCount = 0; if ((style & SWT.OK) > 0) { buttons.add(MessageText.getString("Button.ok")); buttonVal.add(new Integer(SWT.OK)); buttonCount++; } if ((style & SWT.YES) > 0) { buttons.add(MessageText.getString("Button.yes")); buttonVal.add(new Integer(SWT.YES)); buttonCount++; } if ((style & SWT.NO) > 0) { buttons.add(MessageText.getString("Button.no")); buttonVal.add(new Integer(SWT.NO)); buttonCount++; } if ((style & SWT.CANCEL) > 0) { buttons.add(MessageText.getString("Button.cancel")); buttonVal.add(new Integer(SWT.CANCEL)); buttonCount++; } if ((style & SWT.ABORT) > 0) { buttons.add(MessageText.getString("Button.abort")); buttonVal.add(new Integer(SWT.ABORT)); buttonCount++; } if ((style & SWT.RETRY) > 0) { buttons.add(MessageText.getString("Button.retry")); buttonVal.add(new Integer(SWT.RETRY)); buttonCount++; } if ((style & SWT.IGNORE) > 0) { buttons.add(MessageText.getString("Button.ignore")); buttonVal.add(new Integer(SWT.IGNORE)); buttonCount++; } return new Object[] { (String[]) buttons.toArray(new String[buttonCount]), (Integer[]) buttonVal.toArray(new Integer[buttonCount]) }; } public String[] getButtons() { return buttons; } public void setButtons(String[] buttons) { this.buttons = buttons; } public void setButtons(int defaltButtonPos, String[] buttons, Integer[] buttonVals) { this.defaultButtonPos = defaltButtonPos; this.buttons = buttons; this.buttonVals = buttonVals; } public Shell getParent() { return parent; } public void setParent(Shell parent) { this.parent = parent; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/MessageSlideShell.java0000644000175000017500000010633011247070356025111 0ustar adrianadrian/* * Created on Mar 7, 2006 10:42:32 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.shells; import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter.URLInfo; import com.aelitis.azureus.ui.swt.*; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.utils.ColorCache; /** * * +=====================================+ * | +----+ | * | |Icon| Big Bold Title | * | +----+ | * | Wrapping message text | * | with optional URL links | * | +-----+ | * | |BGImg| XX more slideys.. | * | | Icon| Closing in XX secs | * | +-----+ [HideAll] [Details] [Hide] | * +=====================================+ * * @author TuxPaper * @created Mar 7, 2006 * */ public class MessageSlideShell { private static final boolean DEBUG = false; /** Slide until there's this much gap between shell and edge of screen */ private final static int EDGE_GAP = 0; /** Width used when BG image can't be loaded */ private final static int SHELL_DEF_WIDTH = 280; /** Standard height of the shell. Shell may grow depending on text */ private final static int SHELL_MIN_HEIGHT = 150; /** Maximimum height of popup. If text is too long, the full text will be * put into details. */ private final static int SHELL_MAX_HEIGHT = 330; /** Width of the details shell */ private final static int DETAILS_WIDTH = 550; /** Height of the details shell */ private final static int DETAILS_HEIGHT = 180; /** Synchronization for popupList */ private final static AEMonitor monitor = new AEMonitor("slidey_mon"); /** List of all popups ever created */ private static ArrayList historyList = new ArrayList(); /** Current popup being displayed */ private static int currentPopupIndex = -1; /** Index of first message which the user has not seen (index) - set to -1 if we don't care. :) **/ private static int firstUnreadMessage = -1; /** Shell for popup */ private Shell shell; /** Composite in shell */ private Composite cShell; /** popup could and closing in xx seconds label */ private Label lblCloseIn; /** Button that hides all slideys in the popupList. Visible only when there's * more than 1 slidey */ private Button btnHideAll; /** Button to move to next message. Text changes from "Hide" to "Next" * appropriately. */ private Button btnNext; /** paused state of auto-close delay */ private boolean bDelayPaused = false; /** List of SWT objects needing disposal */ private ArrayList disposeList = new ArrayList(); /** Text to put into details popup */ private String sDetails; /** Position this popup is in the history list */ private int idxHistory; private Image imgPopup; protected Color colorURL; private Color colorFG; private int shellWidth; /** Open a popup using resource keys for title/text * * @param display Display to create the shell on * @param iconID SWT.ICON_* constant for icon in top left * @param keyPrefix message bundle key prefix used to get title and text. * Title will be keyPrefix + ".title", and text will be set to * keyPrefix + ".text" * @param details actual text for details (not a key) * @param textParams any parameters for text * * @note Display moved to end to remove conflict in constructors */ public MessageSlideShell(Display display, int iconID, String keyPrefix, String details, String[] textParams, int timeoutSecs ) { this(display, iconID, MessageText.getString(keyPrefix + ".title"), MessageText.getString(keyPrefix + ".text", textParams), details, timeoutSecs); } /** * * @param display * @param iconID * @param keyPrefix * @param details * @param textParams * @param relatedObjects * @param timeoutSecs = -1 -> use default timeout, 0 -> no timeout, other -> timeout in secs */ public MessageSlideShell(Display display, int iconID, String keyPrefix, String details, String[] textParams, Object[] relatedObjects, int timeoutSecs ) { this(display, iconID, MessageText.getString(keyPrefix + ".title"), MessageText.getString(keyPrefix + ".text", textParams), details, relatedObjects, timeoutSecs); } public MessageSlideShell(Display display, int iconID, String title, String text, String details, int timeoutSecs) { this(display, iconID, title, text, details, null, timeoutSecs); } /** * Open Mr Slidey * * @param display Display to create the shell on * @param iconID SWT.ICON_* constant for icon in top left * @param title Text to put in the title * @param text Text to put in the body * @param details Text displayed when the Details button is pressed. Null * for disabled Details button. * @param timeoutSecs = -1 -> use default timeout, 0 -> no timeout, other -> timeout in secs */ public MessageSlideShell(Display display, int iconID, String title, String text, String details, Object[] relatedObjects, int timeoutSecs ) { try { monitor.enter(); PopupParams popupParams = new PopupParams(iconID, title, text, details, relatedObjects, timeoutSecs ); historyList.add(popupParams); if (currentPopupIndex < 0) { create(display, popupParams, true); } } catch (Exception e) { Logger.log(new LogEvent(LogIDs.GUI, "Mr. Slidey Init", e)); disposeShell(shell); Utils.disposeSWTObjects(disposeList); } finally { monitor.exit(); } } private MessageSlideShell(Display display, PopupParams popupParams, boolean bSlide) { create(display, popupParams, bSlide); } public static void displayLastMessage(final Display display, final boolean last_unread) { display.asyncExec(new AERunnable() { public void runSupport() { if (historyList.isEmpty()) { return; } if (currentPopupIndex >= 0) { return; } // Already being displayed. int msg_index = firstUnreadMessage; if (!last_unread || msg_index == -1) { msg_index = historyList.size() - 1; } new MessageSlideShell(display, (PopupParams) historyList.get(msg_index), true); } }); } /** * Adds this message to the slide shell without forcing it to be displayed. * @param relatedTo */ public static void recordMessage(int iconID, String title, String text, String details, Object[] relatedTo, int timeoutSecs ) { try { monitor.enter(); historyList.add(new PopupParams(iconID, title, text, details, relatedTo, timeoutSecs)); if (firstUnreadMessage == -1) { firstUnreadMessage = historyList.size() - 1; } } finally { monitor.exit(); } } private void create(final Display display, final PopupParams popupParams, boolean bSlide) { firstUnreadMessage = -1; // Reset the last read message counter. GridData gridData; int style = SWT.ON_TOP; boolean bDisableSliding = COConfigurationManager.getBooleanParameter("GUI_SWT_DisableAlertSliding"); if (bDisableSliding) { bSlide = false; style = SWT.NONE; } if (DEBUG) System.out.println("create " + (bSlide ? "SlideIn" : "") + ";" + historyList.indexOf(popupParams) + ";"); idxHistory = historyList.indexOf(popupParams); // 2 Assertions if (idxHistory < 0) { System.err.println("Not in popup history list"); return; } if (currentPopupIndex == idxHistory) { System.err.println("Trying to open already opened!! " + idxHistory); return; } try { monitor.enter(); currentPopupIndex = idxHistory; } finally { monitor.exit(); } if (DEBUG) System.out.println("set currIdx = " + idxHistory); sDetails = popupParams.details; // Load Images Image imgIcon = popupParams.iconID <= 0 ? null : display.getSystemImage(popupParams.iconID); /* * If forceTimer is true then we always show the counter for auto-closing the shell; * otherwise proceed to the more fine-grained logic */ // if there's a link, or the info is non-information, // disable timer and mouse watching bDelayPaused = popupParams.iconID != SWT.ICON_INFORMATION || !bSlide; // Pause the auto-close delay when mouse is over slidey // This will be applies to every control final MouseTrackAdapter mouseAdapter = bDelayPaused ? null : new MouseTrackAdapter() { public void mouseEnter(MouseEvent e) { bDelayPaused = true; } public void mouseExit(MouseEvent e) { bDelayPaused = false; } }; // Create shell & widgets if (bDisableSliding) { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { Shell mainShell = uiFunctions.getMainShell(); if (mainShell != null) { shell = new Shell(mainShell, style); } } } if (shell == null) { shell = new Shell(display, style); } try { shell.setBackgroundMode(SWT.INHERIT_DEFAULT); } catch (NoSuchMethodError e) { // Ignore } catch (NoSuchFieldError e2) { // ignore } Utils.setShellIcon(shell); shell.setText(popupParams.title); // Disable BG Image on OSX if (imgPopup == null) { imgPopup = ImageLoader.getInstance().getImage("popup"); shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { ImageLoader.getInstance().releaseImage("popup"); } }); } Rectangle imgPopupBounds; if (imgPopup != null) { shellWidth = imgPopup.getBounds().width; /* * KN: The buttons at the bottom of the shell has an automatic horizontal spacing on OSX; * compensating the shellWidth so that the buttons will not overlap the image at the bottom left * of the shell */ if (true == Constants.isOSX) { shellWidth += 30; } imgPopupBounds = imgPopup.getBounds(); } else { shellWidth = SHELL_DEF_WIDTH; imgPopupBounds = null; } UISkinnableSWTListener[] listeners = UISkinnableManagerSWT.getInstance().getSkinnableListeners( MessageSlideShell.class.toString()); for (int i = 0; i < listeners.length; i++) { try { listeners[i].skinBeforeComponents(shell, this, popupParams.relatedTo); } catch (Exception e) { Debug.out(e); } } if (colorFG == null) { colorFG = display.getSystemColor(SWT.COLOR_BLACK); } FormLayout shellLayout = new FormLayout(); shell.setLayout(shellLayout); cShell = new Composite(shell, SWT.NULL); GridLayout layout = new GridLayout(3, false); cShell.setLayout(layout); FormData formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); cShell.setLayoutData(formData); Label lblIcon = new Label(cShell, SWT.NONE); lblIcon.setImage(imgIcon); lblIcon.setLayoutData(new GridData()); Label lblTitle = new Label(cShell, SWT.getVersion() < 3100 ? SWT.NONE : SWT.WRAP); gridData = new GridData(GridData.FILL_HORIZONTAL); if (SWT.getVersion() < 3100) gridData.widthHint = 140; lblTitle.setLayoutData(gridData); lblTitle.setForeground(colorFG); lblTitle.setText(popupParams.title); FontData[] fontData = lblTitle.getFont().getFontData(); fontData[0].setStyle(SWT.BOLD); fontData[0].setHeight((int) (fontData[0].getHeight() * 1.5)); Font boldFont = new Font(display, fontData); disposeList.add(boldFont); lblTitle.setFont(boldFont); final Button btnDetails = new Button(cShell, SWT.TOGGLE); btnDetails.setForeground(colorFG); Messages.setLanguageText(btnDetails, "popup.error.details"); gridData = new GridData(); btnDetails.setLayoutData(gridData); btnDetails.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event arg0) { try { boolean bShow = btnDetails.getSelection(); if (bShow) { Shell detailsShell = new Shell(display, SWT.BORDER | SWT.ON_TOP); Utils.setShellIcon(detailsShell); detailsShell.setLayout(new FillLayout()); StyledText textDetails = new StyledText(detailsShell, SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER); textDetails.setBackground(display.getSystemColor(SWT.COLOR_LIST_BACKGROUND)); textDetails.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); textDetails.setWordWrap(true); textDetails.setText(sDetails); detailsShell.layout(); Rectangle shellBounds = shell.getBounds(); detailsShell.setBounds(shellBounds.x + shellBounds.width - DETAILS_WIDTH, shellBounds.y - DETAILS_HEIGHT, DETAILS_WIDTH, DETAILS_HEIGHT); detailsShell.open(); shell.setData("detailsShell", detailsShell); shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { Shell detailsShell = (Shell) shell.getData("detailsShell"); if (detailsShell != null && !detailsShell.isDisposed()) { detailsShell.dispose(); } } }); // disable auto-close on opening of details bDelayPaused = true; removeMouseTrackListener(shell, mouseAdapter); } else { Shell detailsShell = (Shell) shell.getData("detailsShell"); if (detailsShell != null && !detailsShell.isDisposed()) { detailsShell.dispose(); } } } catch (Exception e) { Logger.log(new LogEvent(LogIDs.GUI, "Mr. Slidey DetailsButton", e)); } } }); createLinkLabel(cShell, popupParams); lblCloseIn = new Label(cShell, SWT.TRAIL); lblCloseIn.setForeground(colorFG); // Ensure computeSize computes for 2 lined label lblCloseIn.setText("\n"); gridData = new GridData(SWT.FILL, SWT.TOP, true, false); gridData.horizontalSpan = 3; lblCloseIn.setLayoutData(gridData); final Composite cButtons = new Composite(cShell, SWT.NULL); GridLayout gridLayout = new GridLayout(); gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; gridLayout.verticalSpacing = 0; if (Constants.isOSX) gridLayout.horizontalSpacing = 0; gridLayout.numColumns = (idxHistory > 0) ? 3 : 2; cButtons.setLayout(gridLayout); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.VERTICAL_ALIGN_CENTER); gridData.horizontalSpan = 3; cButtons.setLayoutData(gridData); btnHideAll = new Button(cButtons, SWT.PUSH); Messages.setLanguageText(btnHideAll, "popup.error.hideall"); btnHideAll.setVisible(false); btnHideAll.setForeground(display.getSystemColor(SWT.COLOR_BLACK)); // XXX SWT.Selection doesn't work on latest GTK (2.8.17) & SWT3.2 for ON_TOP btnHideAll.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event arg0) { cButtons.setEnabled(false); shell.dispose(); } }); if (idxHistory > 0) { final Button btnPrev = new Button(cButtons, SWT.PUSH); btnPrev.setForeground(display.getSystemColor(SWT.COLOR_BLACK)); btnPrev.setText(MessageText.getString("popup.previous", new String[] { "" + idxHistory })); btnPrev.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event arg0) { disposeShell(shell); int idx = historyList.indexOf(popupParams) - 1; if (idx >= 0) { PopupParams item = (PopupParams) historyList.get(idx); showPopup(display, item, false); disposeShell(shell); } } }); } btnNext = new Button(cButtons, SWT.PUSH); btnNext.setForeground(display.getSystemColor(SWT.COLOR_BLACK)); int numAfter = historyList.size() - idxHistory - 1; setButtonNextText(numAfter); btnNext.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event arg0) { if (DEBUG) System.out.println("Next Pressed"); if (idxHistory + 1 < historyList.size()) { showPopup(display, (PopupParams) historyList.get(idxHistory + 1), false); } disposeShell(shell); } }); // Image has gap for text at the top (with image at bottom left) // trim top to height of shell Point bestSize = cShell.computeSize(shellWidth, SWT.DEFAULT); if (bestSize.y < SHELL_MIN_HEIGHT) bestSize.y = SHELL_MIN_HEIGHT; else if (bestSize.y > SHELL_MAX_HEIGHT) { bestSize.y = SHELL_MAX_HEIGHT; if (sDetails == null) { sDetails = popupParams.text; } else { sDetails = popupParams.text + "\n===============\n" + sDetails; } } if (imgPopup != null) { // no text on the frog in the bottom left int bottomHeight = cButtons.computeSize(SWT.DEFAULT, SWT.DEFAULT).y + lblCloseIn.computeSize(SWT.DEFAULT, SWT.DEFAULT).y; if (bottomHeight < 50) bestSize.y += 50 - bottomHeight; final Image imgBackground = new Image(display, bestSize.x, bestSize.y); disposeList.add(imgBackground); GC gc = new GC(imgBackground); int dstY = imgPopupBounds.height - bestSize.y; if (dstY < 0) dstY = 0; gc.drawImage(imgPopup, 0, dstY, imgPopupBounds.width, imgPopupBounds.height - dstY, 0, 0, bestSize.x, bestSize.y); gc.dispose(); boolean bAlternateDrawing = true; try { shell.setBackgroundImage(imgBackground); bAlternateDrawing = false; } catch (NoSuchMethodError e) { } if (bAlternateDrawing) { // Drawing of BG Image for pre SWT 3.2 cShell.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { e.gc.drawImage(imgBackground, e.x, e.y, e.width, e.height, e.x, e.y, e.width, e.height); } }); Color colorBG = display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); final RGB bgRGB = colorBG.getRGB(); PaintListener paintListener = new PaintListener() { // OSX: copyArea() causes a paint event, resulting in recursion boolean alreadyPainting = false; public void paintControl(PaintEvent e) { if (alreadyPainting || e.width <= 0 || e.height <= 0) { return; } alreadyPainting = true; try { Rectangle bounds = ((Control) e.widget).getBounds(); Image img = new Image(display, e.width, e.height); e.gc.copyArea(img, e.x, e.y); e.gc.drawImage(imgBackground, -bounds.x, -bounds.y); // Set the background color to invisible. img.setBackground // doesn't work, so change transparentPixel directly and roll // a new image ImageData data = img.getImageData(); data.transparentPixel = data.palette.getPixel(bgRGB); Image imgTransparent = new Image(display, data); // This is an alternative way of setting the transparency. // Probably much slower //int bgIndex = data.palette.getPixel(bgRGB); //ImageData transparencyMask = data.getTransparencyMask(); //for (int y = 0; y < data.height; y++) { // for (int x = 0; x < data.width; x++) { // if (bgIndex == data.getPixel(x, y)) // transparencyMask.setPixel(x, y, 0); // } //} // //Image imgTransparent = new Image(display, data, transparencyMask); e.gc.drawImage(imgTransparent, 0, 0, e.width, e.height, e.x, e.y, e.width, e.height); img.dispose(); imgTransparent.dispose(); } finally { alreadyPainting = false; } } }; shell.setBackground(colorBG); cShell.setBackground(colorBG); addPaintListener(cShell, paintListener, colorBG, true); } } Rectangle bounds = null; try { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { Shell mainShell = uiFunctions.getMainShell(); if (mainShell != null) { bounds = mainShell.getMonitor().getClientArea(); } } else { Shell shell = display.getActiveShell(); if (shell != null) { bounds = shell.getMonitor().getClientArea(); } } if (bounds == null) { bounds = shell.getMonitor().getClientArea(); } } catch (Exception e) { } if (bounds == null) { bounds = display.getClientArea(); } Rectangle endBounds; if (bDisableSliding) { endBounds = new Rectangle(((bounds.x + bounds.width) / 2) - (bestSize.x / 2), ((bounds.y + bounds.height) / 2) - (bestSize.y / 2), bestSize.x, bestSize.y); } else { int boundsX2 = bounds.x + bounds.width; int boundsY2 = bounds.y + bounds.height; endBounds = shell.computeTrim(boundsX2 - bestSize.x, boundsY2 - bestSize.y, bestSize.x, bestSize.y); // bottom and right trim will be off the edge, calulate this trim // and adjust it up and left (trim may not be the same size on all sides) int diff = (endBounds.x + endBounds.width) - boundsX2; if (diff >= 0) endBounds.x -= diff + EDGE_GAP; diff = (endBounds.y + endBounds.height) - boundsY2; if (diff >= 0) { endBounds.y -= diff + EDGE_GAP; } //System.out.println("best" + bestSize + ";mon" + bounds + ";end" + endBounds); } FormData data = new FormData(bestSize.x, bestSize.y); cShell.setLayoutData(data); btnDetails.setVisible(sDetails != null); if (sDetails == null) { gridData = new GridData(); gridData.widthHint = 0; btnDetails.setLayoutData(gridData); } shell.layout(); btnNext.setFocus(); shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { Utils.disposeSWTObjects(disposeList); if (currentPopupIndex == idxHistory) { if (DEBUG) System.out.println("Clear #" + currentPopupIndex + "/" + idxHistory); try { monitor.enter(); currentPopupIndex = -1; } finally { monitor.exit(); } } } }); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event event) { if (event.detail == SWT.TRAVERSE_ESCAPE) { disposeShell(shell); event.doit = false; } } }); if (mouseAdapter != null) addMouseTrackListener(shell, mouseAdapter); for (int i = 0; i < listeners.length; i++) { try { listeners[i].skinAfterComponents(shell, this, popupParams.relatedTo); } catch (Exception e) { Debug.out(e); } } int timeoutSecs; if ( popupParams.timeoutSecs < 0 ){ timeoutSecs = COConfigurationManager.getIntParameter("Message Popup Autoclose in Seconds"); }else{ timeoutSecs = popupParams.timeoutSecs; } runPopup(endBounds, idxHistory, bSlide, timeoutSecs ); } /** * @param shell2 * @param b * * @since 3.0.0.9 */ private void createLinkLabel(Composite shell, final PopupParams popupParams) { final Canvas canvas = new Canvas(shell, SWT.None) { public Point computeSize(int wHint, int hHint, boolean changed) { Rectangle area = new Rectangle(0, 0, shellWidth, 5000); GC gc = new GC(this); GCStringPrinter sp = new GCStringPrinter(gc, popupParams.text, area, true, false, SWT.WRAP | SWT.TOP); sp.calculateMetrics(); gc.dispose(); Point size = sp.getCalculatedSize(); return size; } }; Listener l = new Listener() { GCStringPrinter sp; public void handleEvent(Event e) { if (e.type == SWT.Paint) { Rectangle area = canvas.getClientArea(); sp = new GCStringPrinter(e.gc, popupParams.text, area, true, false, SWT.WRAP | SWT.TOP); sp.setUrlColor(ColorCache.getColor(e.gc.getDevice(), "#0000ff")); if (colorURL != null) { sp.setUrlColor(colorURL); } if (colorFG != null) { e.gc.setForeground(colorFG); } sp.printString(); } else if (e.type == SWT.MouseMove) { if (sp != null) { URLInfo hitUrl = sp.getHitUrl(e.x, e.y); if (hitUrl != null) { canvas.setCursor(canvas.getDisplay().getSystemCursor( SWT.CURSOR_HAND)); canvas.setToolTipText(hitUrl.url); } else { canvas.setCursor(canvas.getDisplay().getSystemCursor( SWT.CURSOR_ARROW)); canvas.setToolTipText(null); } } } else if (e.type == SWT.MouseUp) { if (sp != null) { URLInfo hitUrl = sp.getHitUrl(e.x, e.y); if (hitUrl != null && !hitUrl.url.startsWith(":")) { Utils.launch(hitUrl.url); } } } } }; canvas.addListener(SWT.Paint, l); canvas.addListener(SWT.MouseMove, l); canvas.addListener(SWT.MouseUp, l); ClipboardCopy.addCopyToClipMenu(canvas, new ClipboardCopy.copyToClipProvider() { public String getText() { return (popupParams.title + "\n\n" + popupParams.text); } }); GridData gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 3; canvas.setLayoutData(gridData); } /** * @param numAfter */ private void setButtonNextText(int numAfter) { if (numAfter <= 0) Messages.setLanguageText(btnNext, "popup.error.hide"); else Messages.setLanguageText(btnNext, "popup.next", new String[] { "" + numAfter }); cShell.layout(true); } /** * Show the popup with the specified parameters. * * @param display Display to show on * @param item popup to display. Must already exist in historyList * @param bSlide Whether to slide in or show immediately */ private void showPopup(final Display display, final PopupParams item, final boolean bSlide) { Utils.execSWTThread(new AERunnable() { public void runSupport() { new MessageSlideShell(display, item, bSlide); } }); } /** * Adds mousetracklistener to composite and all it's children * * @param parent Composite to start at * @param listener Listener to add */ private void addMouseTrackListener(Composite parent, MouseTrackListener listener) { if (parent == null || listener == null || parent.isDisposed()) return; parent.addMouseTrackListener(listener); Control[] children = parent.getChildren(); for (int i = 0; i < children.length; i++) { Control control = children[i]; if (control instanceof Composite) addMouseTrackListener((Composite) control, listener); else control.addMouseTrackListener(listener); } } private void addPaintListener(Composite parent, PaintListener listener, Color colorBG, boolean childrenOnly) { if (parent == null || listener == null || parent.isDisposed()) return; if (!childrenOnly) { parent.addPaintListener(listener); parent.setBackground(colorBG); } Control[] children = parent.getChildren(); for (int i = 0; i < children.length; i++) { Control control = children[i]; control.addPaintListener(listener); control.setBackground(colorBG); if (control instanceof Composite) addPaintListener((Composite) control, listener, colorBG, true); } } /** * removes mousetracklistener from composite and all it's children * * @param parent Composite to start at * @param listener Listener to remove */ private void removeMouseTrackListener(Composite parent, MouseTrackListener listener) { if (parent == null || listener == null || parent.isDisposed()) return; Control[] children = parent.getChildren(); for (int i = 0; i < children.length; i++) { Control control = children[i]; control.removeMouseTrackListener(listener); if (control instanceof Composite) removeMouseTrackListener((Composite) control, listener); } } /** * Start the slid in, wait specified time while notifying user of impending * auto-close, then slide out. Run on separate thread, so this method * returns immediately * * @param endBounds end location and size wanted * @param idx Index in historyList of popup (Used to calculate # prev, next) * @param bSlide Whether to slide in, or show immediately */ private void runPopup(final Rectangle endBounds, final int idx, final boolean bSlide, final int timeoutSecs ) { if (shell == null || shell.isDisposed()) return; final Display display = shell.getDisplay(); if (DEBUG) System.out.println("runPopup " + idx + ((bSlide) ? " Slide" : " Instant")); AEThread thread = new AEThread("Slidey", true) { private final static int PAUSE = 500; public void runSupport() { if (shell == null || shell.isDisposed()) return; if (bSlide) { new ShellSlider(shell, SWT.UP, endBounds).run(); } else { Utils.execSWTThread(new AERunnable() { public void runSupport() { shell.setBounds(endBounds); shell.open(); } }); } int delayLeft = timeoutSecs * 1000; final boolean autohide = (delayLeft != 0); long lastDelaySecs = 0; int lastNumPopups = -1; while ((!autohide || bDelayPaused || delayLeft > 0) && !shell.isDisposed()) { int delayPausedOfs = (bDelayPaused ? 1 : 0); final long delaySecs = Math.round(delayLeft / 1000.0) + delayPausedOfs; final int numPopups = historyList.size(); if (lastDelaySecs != delaySecs || lastNumPopups != numPopups) { lastDelaySecs = delaySecs; lastNumPopups = numPopups; shell.getDisplay().asyncExec(new AERunnable() { public void runSupport() { String sText = ""; if (lblCloseIn == null || lblCloseIn.isDisposed()) return; lblCloseIn.setRedraw(false); if (!bDelayPaused && autohide) sText += MessageText.getString("popup.closing.in", new String[] { String.valueOf(delaySecs) }); int numPopupsAfterUs = numPopups - idx - 1; boolean bHasMany = numPopupsAfterUs > 0; if (bHasMany) { sText += "\n"; sText += MessageText.getString("popup.more.waiting", new String[] { String.valueOf(numPopupsAfterUs) }); } lblCloseIn.setText(sText); if (btnHideAll.getVisible() != bHasMany) { cShell.setRedraw(false); btnHideAll.setVisible(bHasMany); lblCloseIn.getParent().layout(true); cShell.setRedraw(true); } setButtonNextText(numPopupsAfterUs); // Need to redraw to cause a paint lblCloseIn.setRedraw(true); } }); } if (!bDelayPaused) delayLeft -= PAUSE; try { Thread.sleep(PAUSE); } catch (InterruptedException e) { delayLeft = 0; } } if (this.isInterrupted()) { // App closedown likely, boot out ASAP disposeShell(shell); return; } // Assume that if the shell was disposed during loop, it's on purpose // and that it has handled whether to show the next popup or not if (shell != null && !shell.isDisposed()) { if (idx + 1 < historyList.size()) { showPopup(display, (PopupParams) historyList.get(idx + 1), true); } // slide out current popup if (bSlide) new ShellSlider(shell, SWT.RIGHT).run(); disposeShell(shell); } } }; thread.start(); } private void disposeShell(final Shell shell) { if (shell == null || shell.isDisposed()) return; Utils.execSWTThread(new AERunnable() { public void runSupport() { shell.dispose(); } }); } /** * Waits until all slideys are closed before returning to caller. */ public static void waitUntilClosed() { if (currentPopupIndex < 0) return; Display display = Display.getCurrent(); while (currentPopupIndex >= 0) { if (!display.readAndDispatch()) display.sleep(); } } private static class PopupParams { int iconID; String title; String text; String details; long addedOn; Object[] relatedTo; int timeoutSecs; /** * @param iconID * @param title * @param text * @param details */ public PopupParams(int iconID, String title, String text, String details, int timeoutSecs ) { this.iconID = iconID; this.title = title; this.text = text; this.details = details; this.timeoutSecs = timeoutSecs; addedOn = System.currentTimeMillis(); } /** * @param iconID2 * @param title2 * @param text2 * @param details2 * @param relatedTo */ public PopupParams(int iconID, String title, String text, String details, Object[] relatedTo, int timeoutSecs ) { this(iconID, title, text, details, timeoutSecs ); this.relatedTo = relatedTo; } } /** * Test * * @param args */ public static void main(String[] args) { final Display display = Display.getDefault(); Shell shell = new Shell(display, SWT.DIALOG_TRIM); shell.setLayout(new FillLayout()); Button btn = new Button(shell, SWT.PUSH); btn.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { test(display); } }); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } public static void test(Display display) { String title = "This is the title that never ends, never ends!"; String text = "This is a very long message with lots of information and " + "stuff you really should read. Are you still reading? Good, because " + "reading stimulates the mind and grows " + "hair on your chest.\n\n Unless you are a girl, then it makes you want " + "to read more. It's an endless cycle of reading that will never " + "end. Cursed is the long text that is in this test and may it fill" + "every last line of the shell until there is no more."; // delay before running, to give eclipse time to finish up it's work // Otherwise, Mr Slidey is jumpy try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // MessagePopupShell shell = new MessagePopupShell(display, // MessagePopupShell.ICON_INFO, "Title", text, "Details"); new MessageSlideShell(display, SWT.ICON_INFORMATION, "Simple. . . . . . . . . . . . . . . . . . .", "Simple", (String) null, -1); new MessageSlideShell(display, SWT.ICON_INFORMATION, title + "1", text, "Details: " + text, -1); new MessageSlideShell(display, SWT.ICON_INFORMATION, "ShortTitle2", "ShortText", "Details", -1); MessageSlideShell.waitUntilClosed(); new MessageSlideShell(display, SWT.ICON_INFORMATION, "ShortTitle3", "ShortText", (String) null, -1); for (int x = 0; x < 10; x++) text += "\n\n\n\n\n\n\n\nWow"; new MessageSlideShell(display, SWT.ICON_INFORMATION, title + "4", text, "Details", -1); new MessageSlideShell(display, SWT.ICON_ERROR, title + "5", text, (String) null, -1); MessageSlideShell.waitUntilClosed(); } /** * @return the imgPopup */ public Image getImgPopup() { return imgPopup; } /** * @param imgPopup the imgPopup to set */ public void setImgPopup(Image imgPopup) { this.imgPopup = imgPopup; } public Color getUrlColor() { return colorURL; } public void setUrlColor(Color urlColor) { this.colorURL = urlColor; } public Color getColorFG() { return colorFG; } public void setColorFG(Color colorFG) { this.colorFG = colorFG; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/GCStringPrinter.java0000644000175000017500000011731011275204020024564 0ustar adrianadrian/* * File : GCStringPrinter.java * Created : 16 mars 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.shells; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author Olivier Chalouhi * @author TuxPaper (rewrite) */ public class GCStringPrinter { private static final boolean DEBUG = false; private static final String GOOD_STRING = "(/|,jI~`gy"; public static final int FLAG_SKIPCLIP = 1; public static final int FLAG_FULLLINESONLY = 2; public static final int FLAG_NODRAW = 4; public static final int FLAG_KEEP_URL_INFO = 8; private static final Pattern patHREF = Pattern.compile( "<\\s*?a\\s.*?href\\s*?=\\s*?\"(.+?)\".*?>(.*?)<\\s*?/a\\s*?>", Pattern.CASE_INSENSITIVE); private static final Pattern patAHREF_TITLE = Pattern.compile( "title=\\\"([^\\\"]+)", Pattern.CASE_INSENSITIVE); private static final Pattern patAHREF_TARGET = Pattern.compile( "target=\\\"([^\\\"]+)", Pattern.CASE_INSENSITIVE); //private static final Pattern patOver1000 = Pattern.compile("[^\n]{1010,}"); // Limit word/line length as OSX crashes on stringExtent on very very long words private static final int MAX_LINE_LEN = 4000; // max Word length can be same as line length since words are auto-split // across lines private static final int MAX_WORD_LEN = 4000; private boolean cutoff; private GC gc; private String string; private Rectangle printArea; private int swtFlags; private int printFlags; private Point size; private Color urlColor; private List listUrlInfo; private Image[] images; private float[] imageScales; private int iCurrentHeight; private boolean wrap; public static class URLInfo { public String url; public String text; public Color urlColor; public Color dropShadowColor; int relStartPos; // We could use a region, but that uses a resource that requires disposal public List hitAreas = null; int titleLength; public String fullString; public String title; public String target; public boolean urlUnderline; // @see java.lang.Object#toString() public String toString() { return super.toString() + ": relStart=" + relStartPos + ";url=" + url + ";title=" + text + ";hit=" + (hitAreas == null ? 0 : hitAreas.size()); } } private class LineInfo { public int width; String originalLine; String lineOutputed; int excessPos; public int relStartPos; public int height; public int imageIndexes[]; public LineInfo(String originalLine, int relStartPos) { this.originalLine = originalLine; this.relStartPos = relStartPos; } // @see java.lang.Object#toString() public String toString() { return super.toString() + ": relStart=" + relStartPos + ";xcess=" + excessPos + ";orig=" + originalLine + ";output=" + lineOutputed; } } public static boolean printString(GC gc, String string, Rectangle printArea) { return printString(gc, string, printArea, false, false); } public static boolean printString(GC gc, String string, Rectangle printArea, boolean skipClip, boolean fullLinesOnly) { return printString(gc, string, printArea, skipClip, fullLinesOnly, SWT.WRAP | SWT.TOP); } /** * * @param gc GC to print on * @param string Text to print * @param printArea Area of GC to print text to * @param skipClip Don't set any clipping on the GC. Text may overhang * printArea when this is true * @param fullLinesOnly If bottom of a line will be chopped off, do not display it * @param swtFlags SWT flags. SWT.CENTER, SWT.BOTTOM, SWT.TOP, SWT.WRAP * @return whether it fit */ public static boolean printString(GC gc, String string, Rectangle printArea, boolean skipClip, boolean fullLinesOnly, int swtFlags) { try { GCStringPrinter sp = new GCStringPrinter(gc, string, printArea, skipClip, fullLinesOnly, swtFlags); return sp.printString(); } catch (Exception e) { e.printStackTrace(); } return false; } private boolean _printString() { boolean b = false; try { boolean wasAdvanced = gc.getAdvanced(); Rectangle clipping = null; // With Advanced ontext antialias in SWT.DEFAULT is not the system's default // Turn off Advanced while drawing text so it antialiases based on // system prefs. if (gc.getAdvanced() && gc.getTextAntialias() == SWT.DEFAULT && gc.getAlpha() == 255) { clipping = gc.getClipping(); gc.setAdvanced(false); gc.setClipping(clipping); } b = __printString(); if (wasAdvanced) { gc.setAdvanced(true); gc.setClipping(clipping); } } catch (Throwable t) { Debug.out(t); } if (DEBUG) { System.out.println(""); } return b; } /** * @param gc * @param string * @param printArea * @param printFlags * @param swtFlags * @return * * @since 3.0.4.3 */ private boolean __printString() { size = new Point(0, 0); if (string == null) { return false; } if (printArea == null || printArea.isEmpty()) { return false; } ArrayList lines = new ArrayList(); while (string.indexOf('\t') >= 0) { string = string.replace('\t', ' '); } boolean fullLinesOnly = (printFlags & FLAG_FULLLINESONLY) > 0; boolean skipClip = (printFlags & FLAG_SKIPCLIP) > 0; boolean noDraw = (printFlags & FLAG_NODRAW) > 0; wrap = (swtFlags & SWT.WRAP) > 0; if ((printFlags & FLAG_KEEP_URL_INFO) == 0) { Matcher htmlMatcher = patHREF.matcher(string); boolean hasURL = htmlMatcher.find(); if (hasURL) { listUrlInfo = new ArrayList(1); while (hasURL) { URLInfo urlInfo = new URLInfo(); // Store the full ahref string once, then use substring which doesn't // create real strings :) urlInfo.fullString = htmlMatcher.group(); urlInfo.relStartPos = htmlMatcher.start(0); urlInfo.url = string.substring(htmlMatcher.start(1), htmlMatcher.end(1)); urlInfo.text = string.substring(htmlMatcher.start(2), htmlMatcher.end(2)); urlInfo.titleLength = urlInfo.text.length(); Matcher matcherTitle = patAHREF_TITLE.matcher(urlInfo.fullString); if (matcherTitle.find()) { urlInfo.title = string.substring(urlInfo.relStartPos + matcherTitle.start(1), urlInfo.relStartPos + matcherTitle.end(1)); } Matcher matcherTarget = patAHREF_TARGET.matcher(urlInfo.fullString); if (matcherTarget.find()) { urlInfo.target = string.substring(urlInfo.relStartPos + matcherTarget.start(1), urlInfo.relStartPos + matcherTarget.end(1)); } //System.out.println("URLINFO! " + urlInfo.fullString // + "\ntarget=" // + urlInfo.target + "\ntt=" + urlInfo.title + "\nurl=" // + urlInfo.url + "\ntext=" + urlInfo.text + "\n\n"); string = htmlMatcher.replaceFirst(urlInfo.text.replaceAll("\\$", "\\\\\\$")); listUrlInfo.add(urlInfo); htmlMatcher = patHREF.matcher(string); hasURL = htmlMatcher.find(urlInfo.relStartPos); } } } else { Matcher htmlMatcher = patHREF.matcher(string); string = htmlMatcher.replaceAll("$2"); } Rectangle rectDraw = new Rectangle(printArea.x, printArea.y, printArea.width, printArea.height); Rectangle oldClipping = null; try { if (!skipClip && !noDraw) { oldClipping = gc.getClipping(); // Protect the GC from drawing outside the drawing area gc.setClipping(printArea); } // Process string line by line iCurrentHeight = 0; int currentCharPos = 0; int pos1 = string.indexOf('\n'); int pos2 = string.indexOf('\r'); if (pos2 == -1) { pos2 = pos1; } int posNewLine = Math.min(pos1, pos2); if (posNewLine < 0) { posNewLine = string.length(); } int posLastNewLine = 0; while (posNewLine >= 0 && posLastNewLine < string.length()) { String sLine = string.substring(posLastNewLine, posNewLine); do { LineInfo lineInfo = new LineInfo(sLine, currentCharPos); lineInfo = processLine(gc, lineInfo, printArea, fullLinesOnly, false); String sProcessedLine = (String) lineInfo.lineOutputed; if (sProcessedLine != null && sProcessedLine.length() > 0) { if (lineInfo.width == 0 || lineInfo.height == 0) { Point gcExtent = gc.stringExtent(sProcessedLine); if (lineInfo.width == 0) { lineInfo.width = gcExtent.x; } if (lineInfo.height == 0) { lineInfo.height = gcExtent.y; } } Point extent = new Point(lineInfo.width, lineInfo.height); iCurrentHeight += extent.y; boolean isOverY = iCurrentHeight > printArea.height; if (DEBUG) { System.out.println("Adding Line: [" + sProcessedLine + "]" + sProcessedLine.length() + "; h=" + iCurrentHeight + "(" + printArea.height + "). fullOnly?" + fullLinesOnly + ". Excess: " + lineInfo.excessPos); } if (isOverY && !fullLinesOnly) { //fullLinesOnly = true; // <-- don't know why we needed this lines.add(lineInfo); } else if (isOverY && fullLinesOnly && lines.size() > 0) { String excess = lineInfo.excessPos >= 0 ? sLine.substring(lineInfo.excessPos) : null; if (excess != null) { if (fullLinesOnly) { if (lines.size() > 0) { lineInfo = (LineInfo) lines.remove(lines.size() - 1); sProcessedLine = lineInfo.originalLine.length() > MAX_LINE_LEN ? lineInfo.originalLine.substring(0, MAX_LINE_LEN) : lineInfo.originalLine; //sProcessedLine = ((LineInfo) lines.remove(lines.size() - 1)).originalLine; extent = gc.stringExtent(sProcessedLine); } else { if (DEBUG) { System.out.println("No PREV!?"); } return false; } } else { sProcessedLine = sProcessedLine.length() > MAX_LINE_LEN ? sProcessedLine.substring(0, MAX_LINE_LEN) : sProcessedLine; } if (excess.length() > MAX_LINE_LEN) { excess = excess.substring(0, MAX_LINE_LEN); } StringBuffer outputLine = new StringBuffer(sProcessedLine); lineInfo.width = extent.x; wrap = false; int newExcessPos = processWord(gc, sProcessedLine, " " + excess, printArea, lineInfo, outputLine, new StringBuffer()); if (DEBUG) { System.out.println(" with word [" + excess + "] len is " + lineInfo.width + "(" + printArea.width + ") w/excess " + newExcessPos); } lineInfo.lineOutputed = outputLine.toString(); lines.add(lineInfo); if (DEBUG) { System.out.println("replace prev line with: " + outputLine.toString()); } } else { if (DEBUG) { System.out.println("No Excess"); } } cutoff = true; return false; } else { lines.add(lineInfo); } sLine = lineInfo.excessPos >= 0 && wrap ? sLine.substring(lineInfo.excessPos) : null; } else { if (DEBUG) { System.out.println("Line process resulted in no text: " + sLine); } lines.add(lineInfo); currentCharPos++; break; //return false; } currentCharPos += lineInfo.excessPos >= 0 ? lineInfo.excessPos : lineInfo.lineOutputed.length(); //System.out.println("output: " + lineInfo.lineOutputed.length() + ";" // + lineInfo.lineOutputed + ";xc=" + lineInfo.excessPos + ";ccp=" + currentCharPos); //System.out.println("lineo=" + lineInfo.lineOutputed.length() + ";" + sLine.length() ); } while (sLine != null); if (string.length() > posNewLine && string.charAt(posNewLine) == '\r' && string.charAt(posNewLine + 1) == '\n') { posNewLine++; } posLastNewLine = posNewLine + 1; currentCharPos = posLastNewLine; pos1 = string.indexOf('\n', posLastNewLine); pos2 = string.indexOf('\r', posLastNewLine); if (pos2 == -1) { pos2 = pos1; } posNewLine = Math.min(pos1, pos2); if (posNewLine < 0) { posNewLine = string.length(); } } } finally { if (lines.size() > 0) { // rebuild full text to get the exact y-extent of the output // this may be different (but shouldn't be!) than the height of each // line StringBuffer fullText = new StringBuffer(string.length() + 10); for (Iterator iter = lines.iterator(); iter.hasNext();) { LineInfo lineInfo = (LineInfo) iter.next(); if (fullText.length() > 0) { fullText.append('\n'); } fullText.append(lineInfo.lineOutputed); } //size = gc.textExtent(fullText.toString()); for (Iterator iter = lines.iterator(); iter.hasNext();) { LineInfo lineInfo = (LineInfo) iter.next(); size.x = Math.max(lineInfo.width, size.x); size.y += lineInfo.height; } if ((swtFlags & (SWT.BOTTOM)) != 0) { rectDraw.y = rectDraw.y + rectDraw.height - size.y; } else if ((swtFlags & SWT.TOP) == 0) { // center vert rectDraw.y = rectDraw.y + (rectDraw.height - size.y) / 2; } if (!noDraw || listUrlInfo != null) { for (Iterator iter = lines.iterator(); iter.hasNext();) { LineInfo lineInfo = (LineInfo) iter.next(); try { drawLine(gc, lineInfo, swtFlags, rectDraw, noDraw); } catch (Throwable t) { t.printStackTrace(); } } } } if (!skipClip && !noDraw) { gc.setClipping(oldClipping); } } cutoff |= size.y > printArea.height; return !cutoff; } /** * @param hasMoreElements * @param line * * @since 3.0.0.7 */ private LineInfo processLine(final GC gc, final LineInfo lineInfo, final Rectangle printArea, final boolean fullLinesOnly, boolean hasMoreElements) { if (lineInfo.originalLine.length() == 0) { lineInfo.lineOutputed = ""; lineInfo.height = gc.stringExtent(GOOD_STRING).y; return lineInfo; } StringBuffer outputLine = new StringBuffer(); int excessPos = -1; if (images != null || lineInfo.originalLine.length() > MAX_LINE_LEN || gc.stringExtent(lineInfo.originalLine).x > printArea.width) { if (DEBUG) { System.out.println("Line to process: " + lineInfo.originalLine); } StringBuffer space = new StringBuffer(1); if (!wrap && images == null) { if (DEBUG) { System.out.println("No Wrap.. doing all in one line"); } String sProcessedLine = lineInfo.originalLine.length() > MAX_LINE_LEN ? lineInfo.originalLine.substring(0, MAX_LINE_LEN) : lineInfo.originalLine; // if it weren't for the elipses, we could do: // outputLine.append(sProcessedLine); excessPos = processWord(gc, lineInfo.originalLine, sProcessedLine, printArea, lineInfo, outputLine, space); } else { int posLastWordStart = 0; int posWordStart = lineInfo.originalLine.indexOf(' '); while (posWordStart == 0) { posWordStart = lineInfo.originalLine.indexOf(' ', posWordStart + 1); } if (posWordStart < 0) { posWordStart = lineInfo.originalLine.length(); } // Process line word by word int curPos = 0; while (posWordStart >= 0 && posLastWordStart < lineInfo.originalLine.length()) { String word = lineInfo.originalLine.substring(posLastWordStart, posWordStart); if (word.length() == 0) { excessPos = -1; outputLine.append(' '); } for (int i = 0; i < word.length(); i += MAX_WORD_LEN) { String subWord; int endPos = i + MAX_WORD_LEN; if (endPos > word.length()) { subWord = word.substring(i); } else { subWord = word.substring(i, endPos); } excessPos = processWord(gc, lineInfo.originalLine, subWord, printArea, lineInfo, outputLine, space); if (DEBUG) { System.out.println(" with word [" + subWord + "] len is " + lineInfo.width + "(" + printArea.width + ") w/excess " + excessPos); } if (excessPos >= 0) { excessPos += curPos; break; } if (endPos <= word.length()) { space.setLength(0); } curPos += subWord.length() + 1; } if (excessPos >= 0) { break; } posLastWordStart = posWordStart + 1; posWordStart = lineInfo.originalLine.indexOf(' ', posLastWordStart); if (posWordStart < 0) { posWordStart = lineInfo.originalLine.length(); } } } } else { outputLine.append(lineInfo.originalLine); } if (!wrap && hasMoreElements && excessPos >= 0) { int len = outputLine.length(); if (len > 2) { len -= 2; } outputLine.setLength(len); outputLine.append("\u2026"); cutoff = true; } //drawLine(gc, outputLine, swtFlags, rectDraw); // if (!wrap) { // return hasMoreElements; // } lineInfo.excessPos = excessPos; lineInfo.lineOutputed = outputLine.toString(); return lineInfo; } /** * @param int Position of part of word that didn't fit * * @since 3.0.0.7 */ private int processWord(final GC gc, final String sLine, String word, final Rectangle printArea, final LineInfo lineInfo, StringBuffer outputLine, final StringBuffer space) { if (word.length() == 0) { space.append(' '); return -1; } //System.out.println("PW: " + word); if (images != null && word.length() >= 2 && word.charAt(0) == '%') { int imgIdx = word.charAt(1) - '0'; if (images.length > imgIdx && imgIdx >= 0 && images[imgIdx] != null) { Image img = images[imgIdx]; Rectangle bounds = img.getBounds(); if (imageScales != null && imageScales.length > imgIdx) { bounds.width = (int) (bounds.width * imageScales[imgIdx]); bounds.height = (int) (bounds.height * imageScales[imgIdx]); } Point spaceExtent = gc.stringExtent(space.toString()); int newWidth = lineInfo.width + bounds.width + spaceExtent.x; if (newWidth > printArea.width) { if (bounds.width + spaceExtent.x < printArea.width || lineInfo.width > 0) { //outputLine.append(space); //outputLine.append(word, 0, 2); //System.out.println("w1 = " + lineInfo.width + ";h=" + lineInfo.height); return 0; } } if (lineInfo.imageIndexes == null) { lineInfo.imageIndexes = new int[] { imgIdx }; } int targetWidth = lineInfo.width + newWidth; lineInfo.width = newWidth; lineInfo.height = Math.max(bounds.height, lineInfo.height); Point ptWordSize = gc.stringExtent(word.substring(2) + " "); if (lineInfo.width + ptWordSize.x > printArea.width) { outputLine.append(space); outputLine.append(word.substring(0,2)); //System.out.println("w8 = " + lineInfo.width + ";h=" + lineInfo.height); return 2; } outputLine.append(space); space.setLength(0); outputLine.append(word.substring(0, 2)); word = word.substring(2); //outputLine.append(word); //if (space.length() > 0) { // space.delete(0, space.length()); //} //space.append(' '); //System.out.println("w2 = " + lineInfo.width + ";h=" + lineInfo.height); //return -1; } } Point ptLineAndWordSize = gc.stringExtent(outputLine + word + " "); //System.out.println(ptLineAndWordSize + ";" + outputLine + "::WordComp " + (ptLineAndWordSize.x - lineInfo.width)); if (ptLineAndWordSize.x > printArea.width) { // word is longer than space avail, split Point ptWordSize2 = gc.stringExtent(word + " "); boolean bWordLargerThanWidth = ptWordSize2.x > printArea.width; // This will split put a word that is longer than a full line onto a new // line (when the existing line has text). if (bWordLargerThanWidth && lineInfo.width > 0) { //System.out.println("w3 = " + lineInfo.width + ";h=" + lineInfo.height); return 0; } int endIndex = word.length(); long diff = endIndex; while (ptLineAndWordSize.x != printArea.width) { diff = (diff >> 1) + (diff % 2); if (diff <= 0) { diff = 1; } //System.out.println("diff=" + diff + ";e=" + endIndex + ";tw=" + targetWidth + ";paw= " + printArea.width); if (ptLineAndWordSize.x > printArea.width) { endIndex -= diff; if (endIndex < 1) { endIndex = 1; } } else { endIndex += diff; if (endIndex > word.length()) { endIndex = word.length(); } } ptLineAndWordSize = gc.stringExtent(outputLine + word.substring(0, endIndex) + " "); if (diff <= 1) { break; } } boolean nothingFit = endIndex == 0; if (nothingFit) { endIndex = 1; } if (ptLineAndWordSize.x > printArea.width && endIndex > 1) { endIndex--; ptLineAndWordSize = gc.stringExtent(outputLine + word.substring(0, endIndex) + " "); } if (DEBUG) { System.out.println("excess starts at " + endIndex + " of " + word.length() + ". " + "wrap?" + wrap); } if (wrap && (printFlags & FLAG_FULLLINESONLY) > 0) { int nextLineHeight = gc.stringExtent(GOOD_STRING).y; if (iCurrentHeight + ptLineAndWordSize.y + nextLineHeight > printArea.height) { if (DEBUG) { System.out.println("turn off wrap"); } wrap = false; } } if (endIndex > 0 && outputLine.length() > 0 && !nothingFit) { outputLine.append(space); } int w = ptLineAndWordSize.x - lineInfo.width; if (wrap && !nothingFit && !bWordLargerThanWidth) { // whole word is excess return 0; } outputLine.append(word.substring(0, endIndex)); if (!wrap) { int len = outputLine.length(); if (len == 0) { if (word.length() > 0) { outputLine.append(word.charAt(0)); } else if (sLine.length() > 0) { outputLine.append(sLine.charAt(0)); } } else { if (len > 2) { len -= 2; } outputLine.setLength(len); outputLine.append("\u2026"); cutoff = true; } } //drawLine(gc, outputLine, swtFlags, rectDraw); if (DEBUG) { System.out.println("excess " + word.substring(endIndex)); } //System.out.println("w9 = " + lineInfo.width + ";h=" + lineInfo.height); return endIndex; } lineInfo.width = ptLineAndWordSize.x; if (lineInfo.width > printArea.width) { if (space.length() > 0) { space.delete(0, space.length()); } if (!wrap) { int len = outputLine.length(); if (len == 0) { if (word.length() > 0) { outputLine.append(word.charAt(0)); } else if (sLine.length() > 0) { outputLine.append(sLine.charAt(0)); } } else { if (len > 2) { len -= 2; } outputLine.setLength(len); outputLine.append("\u2026"); cutoff = true; } //System.out.println("w5 = " + lineInfo.width + ";h=" + lineInfo.height); return -1; } else { //System.out.println("w6 = " + lineInfo.width + ";h=" + lineInfo.height); return 0; } //drawLine(gc, outputLine, swtFlags, rectDraw); } if (outputLine.length() > 0) { outputLine.append(space); } outputLine.append(word); if (space.length() > 0) { space.delete(0, space.length()); } space.append(' '); //System.out.println("w4 = " + lineInfo.width + ";h=" + lineInfo.height); return -1; } /** * printArea is updated to the position of the next row * * @param gc * @param outputLine * @param swtFlags * @param printArea * @param noDraw */ private void drawLine(GC gc, LineInfo lineInfo, int swtFlags, Rectangle printArea, boolean noDraw) { String text = lineInfo.lineOutputed; // TODO: ensure width and height have values if (lineInfo.width == 0 || lineInfo.height == 0) { Point gcExtent = gc.stringExtent(text);; if (lineInfo.width == 0) { lineInfo.width = gcExtent.x; } if (lineInfo.height == 0) { lineInfo.height = gcExtent.y; } } Point drawSize = new Point(lineInfo.width, lineInfo.height); int x0; if ((swtFlags & SWT.RIGHT) > 0) { x0 = printArea.x + printArea.width - drawSize.x; } else if ((swtFlags & SWT.CENTER) > 0) { x0 = printArea.x + (printArea.width - drawSize.x) / 2; } else { x0 = printArea.x; } int y0 = printArea.y; int lineInfoRelEndPos = lineInfo.relStartPos + lineInfo.lineOutputed.length(); int relStartPos = lineInfo.relStartPos; int lineStartPos = 0; URLInfo urlInfo = null; boolean drawURL = hasHitUrl(); if (drawURL) { URLInfo[] hitUrlInfo = getHitUrlInfo(); int nextHitUrlInfoPos = 0; while (drawURL) { drawURL = false; for (int i = nextHitUrlInfoPos; i < hitUrlInfo.length; i++) { urlInfo = hitUrlInfo[i]; drawURL = (urlInfo.relStartPos < lineInfoRelEndPos) && (urlInfo.relStartPos + urlInfo.titleLength > relStartPos) && (relStartPos >= lineInfo.relStartPos) && (relStartPos < lineInfoRelEndPos); if (drawURL) { nextHitUrlInfoPos = i + 1; break; } } if (!drawURL) { break; } //int numHitUrlsAlready = urlInfo.hitAreas == null ? 0 : urlInfo.hitAreas.size(); // draw text before url int i = lineStartPos + urlInfo.relStartPos - relStartPos; //System.out.println("numHitUrlsAlready = " + numHitUrlsAlready + ";i=" + i); if (i > 0 && i > lineStartPos && i <= text.length()) { String s = text.substring(lineStartPos, i); //gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_RED)); x0 += drawText(gc, s, x0, y0, lineInfo.height, null, noDraw).x; relStartPos += (i - lineStartPos); lineStartPos += (i - lineStartPos); //System.out.println("|" + s + "|" + textExtent.x); } // draw url text int end = i + urlInfo.titleLength; if (i < 0) { i = 0; } //System.out.println("end=" + end + ";" + text.length() + ";titlelen=" + urlInfo.titleLength); if (end > text.length()) { end = text.length(); } String s = text.substring(i, end); relStartPos += (end - i); lineStartPos += (end - i); Point pt = null; //System.out.println("|" + s + "|"); Color fgColor = null; if (!noDraw) { fgColor = gc.getForeground(); if (urlInfo.dropShadowColor != null) { gc.setForeground(urlInfo.dropShadowColor); drawText(gc, s, x0 + 1, y0 + 1, lineInfo.height, null, noDraw); } if (urlInfo.urlColor != null) { gc.setForeground(urlInfo.urlColor); } else if (urlColor != null) { gc.setForeground(urlColor); } } if (urlInfo.hitAreas == null) { urlInfo.hitAreas = new ArrayList(1); } pt = drawText(gc, s, x0, y0, lineInfo.height, urlInfo.hitAreas, noDraw); if (!noDraw) { if (urlInfo.urlUnderline) { gc.drawLine(x0, y0 + pt.y - 1, x0 + pt.x - 1, y0 + pt.y - 1); } gc.setForeground(fgColor); } if (urlInfo.hitAreas == null) { urlInfo.hitAreas = new ArrayList(1); } //gc.drawRectangle(new Rectangle(x0, y0, pt.x, lineInfo.height)); x0 += pt.x; } } // draw text after url if (lineStartPos < text.length()) { String s = text.substring(lineStartPos); if (!noDraw) { drawText(gc, s, x0, y0, lineInfo.height, null, noDraw); } } printArea.y += drawSize.y; } private Point drawText(GC gc, String s, int x, int y, int height, List hitAreas, boolean nodraw) { Point textExtent; if (images != null) { int pctPos = s.indexOf('%'); int lastPos = 0; int w = 0; int h = 0; while (pctPos >= 0) { if (pctPos >= 0 && s.length() > pctPos + 1) { int imgIdx = s.charAt(pctPos + 1) - '0'; if (imgIdx >= images.length || imgIdx < 0 || images[imgIdx] == null) { String sStart = s.substring(lastPos, pctPos + 1); textExtent = gc.textExtent(sStart); int centerY = y + (height / 2 - textExtent.y / 2); if (hitAreas != null) { hitAreas.add(new Rectangle(x, centerY, textExtent.x, textExtent.y)); } if (!nodraw) { gc.drawText(sStart, x, centerY, true); } x += textExtent.x; w += textExtent.x; h = Math.max(h, textExtent.y); lastPos = pctPos + 1; pctPos = s.indexOf('%', pctPos + 1); continue; } String sStart = s.substring(lastPos, pctPos); textExtent = gc.textExtent(sStart); int centerY = y + (height / 2 - textExtent.y / 2); if (!nodraw) { gc.drawText(sStart, x, centerY, true); } x += textExtent.x; w += textExtent.x; h = Math.max(h, textExtent.y); if (hitAreas != null) { hitAreas.add(new Rectangle(x, centerY, textExtent.x, textExtent.y)); } //System.out.println("drawimage: " + x + "x" + y + ";idx=" + imgIdx); Rectangle imgBounds = images[imgIdx].getBounds(); float scale = 1.0f; if (imageScales != null && imageScales.length > imgIdx) { scale = imageScales[imgIdx]; } int scaleImageWidth = (int) (imgBounds.width * scale); int scaleImageHeight = (int) (imgBounds.height * scale); centerY = y + (height / 2 - scaleImageHeight / 2); if (hitAreas != null) { hitAreas.add(new Rectangle(x, centerY, scaleImageWidth, scaleImageHeight)); } if (!nodraw) { //gc.drawImage(images[imgIdx], x, centerY); gc.drawImage(images[imgIdx], 0, 0, imgBounds.width, imgBounds.height, x, centerY, scaleImageWidth, scaleImageHeight); } x += scaleImageWidth; w += scaleImageWidth; h = Math.max(h, scaleImageHeight); } lastPos = pctPos + 2; pctPos = s.indexOf('%', lastPos); } if (s.length() >= lastPos) { String sEnd = s.substring(lastPos); textExtent = gc.textExtent(sEnd); int centerY = y + (height / 2 - textExtent.y / 2); if (hitAreas != null) { hitAreas.add(new Rectangle(x, centerY, textExtent.x, textExtent.y)); } if (!nodraw) { gc.drawText(sEnd, x, centerY, true); } x += textExtent.x; w += textExtent.x; h = Math.max(h, textExtent.y); } return new Point(w, h); } if (!nodraw) { gc.drawText(s, x, y, true); } textExtent = gc.textExtent(s); if (hitAreas != null) { hitAreas.add(new Rectangle(x, y, textExtent.x, textExtent.y)); } return textExtent; } public static void main(String[] args) { //String s = "this is $1.00"; //String s2 = "$1"; //String s3 = s2.replaceAll("\\$", "\\\\\\$"); //System.out.println(s3); //s.replaceAll("h", s3); //System.out.println(s); //if (true) { // return; //} final Display display = Display.getDefault(); final Shell shell = new Shell(display, SWT.SHELL_TRIM); ImageLoader imageLoader = ImageLoader.getInstance(); final Image[] images = { imageLoader.getImage("azureus32"), imageLoader.getImage("azureus64"), imageLoader.getImage("azureus"), imageLoader.getImage("azureus128"), }; //final String text = "Opil Wrir, Na Poys Iysk, Yann Only. test of the string printer averlongwordthisisyesindeed"; final String text = "Apple Banana, Cow Dug Ergo, Flip Only. test of the string printer averlongwordthisisyesindeed"; //final String text = "Apple, Cow sfjkhsd %1 f, Flip Only. test of %0 the string printer averlongwordthisisyesindeed"; shell.setSize(500, 500); GridLayout gridLayout = new GridLayout(2, false); shell.setLayout(gridLayout); Composite cButtons = new Composite(shell, SWT.NONE); GridData gridData = new GridData(SWT.NONE, SWT.FILL, false, true); cButtons.setLayoutData(gridData); final Canvas cPaint = new Canvas(shell, SWT.DOUBLE_BUFFERED); gridData = new GridData(SWT.FILL, SWT.NONE, true, false); gridData.heightHint = 40; cPaint.setLayoutData(gridData); cButtons.setLayout(new RowLayout(SWT.VERTICAL)); Listener l = new Listener() { public void handleEvent(Event event) { cPaint.redraw(); } }; final Text txtText = new Text(cButtons, SWT.WRAP | SWT.MULTI | SWT.BORDER); txtText.setText(text); txtText.addListener(SWT.Modify, l); txtText.setLayoutData(new RowData(100, 200)); txtText.addKeyListener(new KeyListener() { public void keyReleased(KeyEvent e) { } public void keyPressed(KeyEvent e) { if (e.keyCode == 'a' && e.stateMask == SWT.CONTROL) { txtText.selectAll(); } } }); final Button btnSkipClip = new Button(cButtons, SWT.CHECK); btnSkipClip.setText("Skip Clip"); btnSkipClip.setSelection(true); btnSkipClip.addListener(SWT.Selection, l); final Button btnFullOnly = new Button(cButtons, SWT.CHECK); btnFullOnly.setText("Full Lines Only"); btnFullOnly.setSelection(true); btnFullOnly.addListener(SWT.Selection, l); final Combo cboVAlign = new Combo(cButtons, SWT.READ_ONLY); cboVAlign.add("Top"); cboVAlign.add("Bottom"); cboVAlign.add("None"); cboVAlign.addListener(SWT.Selection, l); cboVAlign.select(0); final Combo cboHAlign = new Combo(cButtons, SWT.READ_ONLY); cboHAlign.add("Left"); cboHAlign.add("Center"); cboHAlign.add("Right"); cboHAlign.add("None"); cboHAlign.addListener(SWT.Selection, l); cboHAlign.select(0); final Button btnWrap = new Button(cButtons, SWT.CHECK); btnWrap.setText("Wrap"); btnWrap.setSelection(true); btnWrap.addListener(SWT.Selection, l); final Label lblInfo = new Label(shell, SWT.WRAP); lblInfo.setText("Welcome"); Listener l2 = new Listener() { URLInfo lastHitInfo = null; public void handleEvent(Event event) { GC gc = event.gc; //System.out.println("HE" + event.type); boolean ourGC = gc == null; if (ourGC) { gc = new GC(cPaint); } try { GCStringPrinter sp = buildSP(gc); Color colorURL = gc.getDevice().getSystemColor(SWT.COLOR_RED); Color colorURL2 = gc.getDevice().getSystemColor( SWT.COLOR_DARK_MAGENTA); if (event.type == SWT.MouseMove) { Point pt = cPaint.toControl(display.getCursorLocation()); URLInfo hitUrl = sp.getHitUrl(pt.x, pt.y); String url1 = hitUrl == null || hitUrl.url == null ? "" : hitUrl.url; String url2 = lastHitInfo == null || lastHitInfo.url == null ? "" : lastHitInfo.url; if (url1.equals(url2)) { return; } cPaint.redraw(); lastHitInfo = hitUrl; return; } Rectangle bounds = cPaint.getClientArea(); Color colorBox = gc.getDevice().getSystemColor(SWT.COLOR_YELLOW); Color colorText = gc.getDevice().getSystemColor(SWT.COLOR_BLACK); gc.setForeground(colorText); Point pt = cPaint.toControl(display.getCursorLocation()); sp.setUrlColor(colorURL); URLInfo hitUrl = sp.getHitUrl(pt.x, pt.y); if (hitUrl != null) { shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_HAND)); hitUrl.urlColor = colorURL2; } else { shell.setCursor(null); } boolean fit = sp.printString(); lblInfo.setText(fit ? "fit" : "no fit"); bounds.width--; bounds.height--; gc.setForeground(colorBox); gc.drawRectangle(bounds); //System.out.println("- " + System.currentTimeMillis()); } catch (Throwable t) { t.printStackTrace(); } finally { if (ourGC) { gc.dispose(); } } } private GCStringPrinter buildSP(GC gc) { //gc.setFont(Utils.getFontWithHeight(shell.getFont(), gc, 15)); //gc.setTextAntialias(SWT.ON); Rectangle bounds = cPaint.getClientArea(); int style = btnWrap.getSelection() ? SWT.WRAP : 0; if (cboVAlign.getSelectionIndex() == 0) { style |= SWT.TOP; } else if (cboVAlign.getSelectionIndex() == 1) { style |= SWT.BOTTOM; } if (cboHAlign.getSelectionIndex() == 0) { style |= SWT.LEFT; } else if (cboHAlign.getSelectionIndex() == 1) { style |= SWT.CENTER; } else if (cboHAlign.getSelectionIndex() == 2) { style |= SWT.RIGHT; } String text = txtText.getText(); text = text.replaceAll("\r\n", "\n"); GCStringPrinter sp = new GCStringPrinter(gc, text, bounds, btnSkipClip.getSelection(), btnFullOnly.getSelection(), style); sp.setImages(images); sp.calculateMetrics(); return sp; } }; cPaint.addListener(SWT.Paint, l2); cPaint.addListener(SWT.MouseMove, l2); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } /** * */ public GCStringPrinter(GC gc, String string, Rectangle printArea, boolean skipClip, boolean fullLinesOnly, int swtFlags) { this.gc = gc; this.string = string; this.printArea = printArea; this.swtFlags = swtFlags; printFlags = 0; if (skipClip) { printFlags |= FLAG_SKIPCLIP; } if (fullLinesOnly) { printFlags |= FLAG_FULLLINESONLY; } } public GCStringPrinter(GC gc, String string, Rectangle printArea, int printFlags, int swtFlags) { this.gc = gc; this.string = string; this.printArea = printArea; this.swtFlags = swtFlags; this.printFlags = printFlags; } public boolean printString() { return _printString(); } public boolean printString(int printFlags) { int oldPrintFlags = this.printFlags; printFlags |= printFlags; boolean b = _printString(); this.printFlags = oldPrintFlags; return b; } public void calculateMetrics() { int oldPrintFlags = printFlags; printFlags |= FLAG_NODRAW; _printString(); printFlags = oldPrintFlags; } /** * @param rectangle * * @since 3.0.4.3 */ public void printString(GC gc, Rectangle rectangle, int swtFlags) { this.gc = gc; int printFlags = this.printFlags; if (printArea.width == rectangle.width) { printFlags |= FLAG_KEEP_URL_INFO; } printArea = rectangle; this.swtFlags = swtFlags; printString(printFlags); } public Point getCalculatedSize() { return size; } public Color getUrlColor() { return urlColor; } public void setUrlColor(Color urlColor) { this.urlColor = urlColor; } public URLInfo getHitUrl(int x, int y) { if (listUrlInfo == null || listUrlInfo.size() == 0) { return null; } for (Iterator iter = listUrlInfo.iterator(); iter.hasNext();) { URLInfo urlInfo = (URLInfo) iter.next(); if (urlInfo.hitAreas != null) { for (Iterator iter2 = urlInfo.hitAreas.iterator(); iter2.hasNext();) { Rectangle r = (Rectangle) iter2.next(); if (r.contains(x, y)) { return urlInfo; } } } } return null; } public URLInfo[] getHitUrlInfo() { if (listUrlInfo == null) { return new URLInfo[0]; } return (URLInfo[]) listUrlInfo.toArray(new URLInfo[0]); } public boolean hasHitUrl() { return listUrlInfo != null && listUrlInfo.size() > 0; } public boolean isCutoff() { return cutoff; } public void setImages(Image[] images) { this.images = images; } public float[] getImageScales() { return imageScales; } public void setImageScales(float[] imageScales) { this.imageScales = imageScales; } /** * @return * * @since 4.0.0.1 */ public String getText() { return string; } /* private Point stringExtent(GC gc, String s) { Matcher m = patOver1000.matcher(s); //if (s.length() > MAX_LINE_LEN) { if (m.find()) { System.out.println(s.length() + "\n" + Debug.getStackTrace(false, false)); System.out.println(s); } return gc.stringExtent(s); } private Point textExtent(GC gc, String s) { Matcher m = patOver1000.matcher(s); //if (s.length() > MAX_LINE_LEN) { if (m.find()) { System.out.println(s.length() + "\n" + Debug.getStackTrace(false, false)); System.out.println(s); } return gc.textExtent(s); } */ } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/Offset.java0000644000175000017500000000033111053727112022766 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.shells; public class Offset { public int xOffset = 0; public int yOffset = 0; public Offset(int xOffset, int yOffset) { this.xOffset = xOffset; this.yOffset = yOffset; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/PopupShell.java0000644000175000017500000000474111127403350023641 0ustar adrianadrian/* * File : PopupShell.java * Created : 14 mars 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.shells; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.ImageRepository; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author Olivier Chalouhi * */ public class PopupShell { protected Shell shell; public static final String IMG_INFORMATION = "information"; /** * Constructs an ON_TOP popup * @param display */ public PopupShell(Display display) { this(display,SWT.ON_TOP); } public PopupShell(Display display,int type) { if ( display.isDisposed()){ return; } shell = new Shell(display,type); shell.setSize(250,150); Utils.setShellIcon(shell); FormLayout layout = new FormLayout(); layout.marginHeight = 0; layout.marginWidth= 0; try { layout.spacing = 0; } catch (NoSuchFieldError e) { /* Ignore for Pre 3.0 SWT.. */ } catch (Throwable e) { Debug.printStackTrace( e ); } shell.setLayout(layout); } protected void layout() { Label label = new Label(shell,SWT.NULL); ImageLoader.getInstance().setLabelImage(label, "popup"); FormData formData = new FormData(); formData.left = new FormAttachment(0,0); formData.top = new FormAttachment(0,0); label.setLayoutData(formData); shell.layout(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/MessagePopupShell.java0000644000175000017500000003143711127403350025150 0ustar adrianadrian/* * File : ErrorPopupShell.java * Created : 15 mars 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.shells; import java.lang.ref.WeakReference; import java.util.Iterator; import java.util.LinkedList; import java.util.Timer; import java.util.TimerTask; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.animations.Animator; import org.gudy.azureus2.ui.swt.animations.shell.AnimableShell; import org.gudy.azureus2.ui.swt.animations.shell.LinearAnimator; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author Olivier Chalouhi * */ public class MessagePopupShell implements AnimableShell { private Shell shell; private Shell detailsShell; Image shellImg; private Display display; public static final String ICON_ERROR = "error"; public static final String ICON_WARNING = "warning"; public static final String ICON_INFO = "info"; private static LinkedList viewStack; private Timer closeTimer; private String icon; static { viewStack = new LinkedList(); } /** Open a popup using resource keys for title/text * * @param keyPrefix message bundle key prefix used to get title and text. * Title will be keyPrefix + ".title", and text will be set to * keyPrefix + ".text" * @param details actual text for details (not a key) * @param textParams any parameters for text * * @note Display moved to end to remove conflict in constructors */ public MessagePopupShell(String icon, String keyPrefix, String details, String[] textParams, Display display) { this(display, icon, MessageText.getString(keyPrefix + ".title"), MessageText.getString(keyPrefix + ".text", textParams), details); } public MessagePopupShell(Display display,String icon,String title,String errorMessage,String details) { closeTimer = new Timer(true); this.display = display; this.icon = icon; detailsShell = new Shell(display,SWT.BORDER | SWT.ON_TOP); Utils.setShellIcon(detailsShell); detailsShell.setLayout(new FillLayout()); StyledText textDetails = new StyledText(detailsShell, SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER); textDetails.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); textDetails.setWordWrap( true ); detailsShell.layout(); detailsShell.setSize(550,300); int popupWidth = 280; int popupHeight = 170; shell = new Shell(display,SWT.ON_TOP); Utils.setShellIcon(shell); FormLayout layout = new FormLayout(); layout.marginHeight = 0; layout.marginWidth = 0; try { layout.spacing = 0; } catch (NoSuchFieldError e) { /* Ignore for Pre 3.0 SWT.. */ } shell.setLayout(layout); ImageLoader imageLoader = ImageLoader.getInstance(); Image popup_image = imageLoader.getImage("popup"); // this code is here to ensure that we can still show error messages even if images // are failing to load (e.g. coz there's a ! in AZ install dir... ) GC gcImage = null; if (ImageLoader.isRealImage(popup_image)) { shellImg = new Image(display, popup_image, SWT.IMAGE_COPY); popupWidth = popup_image.getBounds().width; popupHeight = popup_image.getBounds().height; } else { shellImg = new Image(display, new Rectangle(0, 0, popupWidth, popupHeight)); } imageLoader.releaseImage("popup"); shell.setSize(popupWidth, popupHeight); gcImage = new GC(shellImg); Image imgIcon = imageLoader.getImage(icon); int iconWidth = 0; int iconHeight = 15; if (ImageLoader.isRealImage(imgIcon)) { gcImage.drawImage(imgIcon, 5, 5); iconWidth = imgIcon.getBounds().width; iconHeight = imgIcon.getBounds().height; } imageLoader.releaseImage(icon); Font tempFont = shell.getFont(); FontData[] fontDataMain = tempFont.getFontData(); for (int i = 0; i < fontDataMain.length; i++) { fontDataMain[i].setStyle(SWT.BOLD); fontDataMain[i].setHeight((int) (fontDataMain[i].getHeight() * 1.2)); } Font fontTitle = new Font(display, fontDataMain); gcImage.setFont(fontTitle); Rectangle rect = new Rectangle(iconWidth + 10, 5, popupWidth - iconWidth - 15, iconHeight); GCStringPrinter.printString(gcImage, title, rect); gcImage.setFont(tempFont); fontTitle.dispose(); rect = new Rectangle(5, iconHeight + 5, popupWidth - 10, popupHeight - iconHeight - 60); boolean bItFit = GCStringPrinter.printString(gcImage, errorMessage, rect); gcImage.dispose(); if (!bItFit && details == null) details = errorMessage; if(details != null) textDetails.setText(details); final Button btnDetails = new Button(shell,SWT.TOGGLE); Messages.setLanguageText(btnDetails,"popup.error.details"); btnDetails.setEnabled(details != null); final Button btnHide = new Button(shell,SWT.PUSH); Messages.setLanguageText(btnHide,"popup.error.hide"); Label lblImage = new Label(shell,SWT.NULL); if ( shellImg != null ){ lblImage.setImage(shellImg); } FormData formData; formData = new FormData(); formData.right = new FormAttachment(btnHide,-5); formData.bottom = new FormAttachment(100,-5); btnDetails.setLayoutData(formData); formData = new FormData(); formData.right = new FormAttachment(100,-5); formData.bottom = new FormAttachment(100,-5); btnHide.setLayoutData(formData); formData = new FormData(); formData.left = new FormAttachment(0,0); formData.top = new FormAttachment(0,0); lblImage.setLayoutData(formData); Button btnHideAll = null; if (viewStack.size() > 0) { btnHideAll = new Button(shell, SWT.PUSH); btnHideAll.moveAbove(btnDetails); Messages.setLanguageText(btnHideAll, "popup.error.hideall"); formData = new FormData(); formData.right = new FormAttachment(btnDetails, -5); formData.bottom = new FormAttachment(100,-5); btnHideAll.setLayoutData(formData); btnHideAll.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event event) { btnHide.setEnabled(false); btnDetails.setEnabled(false); for (Iterator iter = viewStack.iterator(); iter.hasNext();) { WeakReference wr = (WeakReference) iter.next(); MessagePopupShell popup = (MessagePopupShell) wr.get(); iter.remove(); if (popup == null) return; popup.shell.dispose(); popup.detailsShell.dispose(); if (popup.shellImg != null) { popup.shellImg.dispose(); } } } }); } shell.layout(); shell.setTabList(new Control[] {btnDetails, btnHide}); btnHide.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event arg0) { btnHide.setEnabled(false); btnDetails.setEnabled(false); hideShell(); } }); btnDetails.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event arg0) { detailsShell.setVisible(btnDetails.getSelection()); } }); Rectangle bounds = null; try { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { Shell mainShell = uiFunctions.getMainShell(); bounds = mainShell.getMonitor().getClientArea(); } } catch (Exception e) { } if (bounds == null) { bounds = display.getClientArea(); } x0 = bounds.x + bounds.width - popupWidth - 5; x1 = bounds.x + bounds.width; y0 = bounds.y + bounds.height; y1 = bounds.y + bounds.height - popupHeight - 5; // currently always animate if ( true ){ shell.setLocation(x0,y0); viewStack.addFirst(new WeakReference(this)); detailsShell.setLocation(x1-detailsShell.getSize().x,y1-detailsShell.getSize().y); currentAnimator = new LinearAnimator(this,new Point(x0,y0),new Point(x0,y1),20,30); currentAnimator.start(); shell.open(); }else{ shell.setLocation(x0,y1); viewStack.addFirst(new WeakReference(this)); detailsShell.setLocation(x1-detailsShell.getSize().x,y1-detailsShell.getSize().y); currentAnimator = new LinearAnimator(this,new Point(x0,y1),new Point(x0,y1),20,30); animationStarted(currentAnimator); shell.open(); animationEnded(currentAnimator); } } private void hideShell() { try { if(currentAnimator == null) { closeTimer.cancel(); detailsShell.setVisible(false); detailsShell.forceActive(); if(!Constants.isOSX){detailsShell.forceFocus();} currentAnimator = new LinearAnimator(this,new Point(x0,y1),new Point(x1,y1),20,30); currentAnimator.start(); closeAfterAnimation = true; } } catch (Exception e) { closeAfterAnimation = true; animationEnded(null); } } private Animator currentAnimator; private boolean closeAfterAnimation; int x0,y0,x1,y1; public void animationEnded(Animator source) { if(source == currentAnimator) { currentAnimator = null; } if(closeAfterAnimation) { if(display == null || display.isDisposed()) return; display.asyncExec(new AERunnable(){ public void runSupport() { viewStack.removeFirst(); shell.dispose(); detailsShell.dispose(); if ( shellImg != null ){ shellImg.dispose(); } } }); } else { scheduleAutocloseTask(); } } private void scheduleAutocloseTask() { final int delay = COConfigurationManager.getIntParameter("Message Popup Autoclose in Seconds") * 1000; if(delay < 1000) return; closeTimer.scheduleAtFixedRate(new TimerTask() { public void run() { display.syncExec(new AERunnable() { public void runSupport() { if(shell.isDisposed()) { closeTimer.cancel(); return; } final boolean notInfoType = MessagePopupShell.this.icon != ICON_INFO; if(notInfoType) { closeTimer.cancel(); return; } final boolean notTopWindow = ((WeakReference)viewStack.getFirst()).get() != MessagePopupShell.this; final boolean animationInProgress = currentAnimator != null; final boolean detailsOpen = (!detailsShell.isDisposed() && detailsShell.isVisible()); final Control cc = display.getCursorControl(); boolean mouseOver = (cc == shell); if(!mouseOver) { final Control[] childControls = shell.getChildren(); for(int i = 0; i < childControls.length; i++) { if(childControls[i] == cc) { mouseOver = true; break; } } } if(notTopWindow || mouseOver || animationInProgress || detailsOpen) return; hideShell(); } }); } }, delay, delay); } public void animationStarted(Animator source) { } public Shell getShell() { return shell; } public void reportPercent(int percent) { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/IWizardPage.java0000644000175000017500000000120611054637130023711 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.shells; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; public interface IWizardPage { public String getPageID(); public boolean isComplete(); public boolean setComplete(); public void performFinish(); public void performDispose(); public String getTitle(); public String getDesciption(); public String getWindowTitle(); public Composite createControls(Composite parent); public Control getControl(); public void performAboutToBeHidden(); public void performAboutToBeShown(); public MultipageWizard getWizard(); public boolean isInitOnStartup(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/ShellSlider.java0000644000175000017500000001040211017135362023752 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.shells; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Monitor; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.util.AERunnable; public class ShellSlider { private final boolean DEBUG = false; private int STEP = 8; private int PAUSE = 30; private Shell shell; private Rectangle shellBounds = null; private Rectangle endBounds; private final int direction; private final boolean slideIn; /** * Slide In * * @param shell * @param direction * @param endBounds */ public ShellSlider(final Shell shell, int direction, final Rectangle endBounds) { this.shell = shell; this.endBounds = endBounds; this.slideIn = true; this.direction = direction; if (shell == null || shell.isDisposed()) return; Display display = shell.getDisplay(); display.syncExec(new Runnable() { public void run() { if (shell.isDisposed()) return; switch (ShellSlider.this.direction) { case SWT.UP: default: shell.setLocation(endBounds.x, endBounds.y); Rectangle displayBounds = null; try { boolean ok = false; Monitor[] monitors = shell.getDisplay().getMonitors(); for (int i = 0; i < monitors.length; i++) { Monitor monitor = monitors[i]; displayBounds = monitor.getBounds(); if (displayBounds.contains(endBounds.x, endBounds.y)) { ok = true; break; } } if (!ok) { displayBounds = shell.getMonitor().getBounds(); } } catch (Throwable t) { displayBounds = shell.getDisplay().getBounds(); } shellBounds = new Rectangle(endBounds.x, displayBounds.y + displayBounds.height, endBounds.width, 0); break; } shell.setBounds(shellBounds); shell.setVisible(true); if (DEBUG) System.out.println("Slide In: " + shell.getText()); } }); } /** * Slide Out * * @param shell * @param direction */ public ShellSlider(final Shell shell, int direction) { this.shell = shell; this.slideIn = false; this.direction = direction; if (DEBUG && canContinue()) shell.getDisplay().syncExec(new Runnable() { public void run() { System.out.println("Slide Out: " + shell.getText()); } }); } private boolean canContinue() { if (shell == null || shell.isDisposed()) return false; if (shellBounds == null) return true; //System.out.println((slideIn ? "In" : "Out") + ";" + direction + ";S:" + shellBounds + ";" + endBounds); if (slideIn) { if (direction == SWT.UP) { return shellBounds.y > endBounds.y; } // TODO: Other directions } else { if (direction == SWT.RIGHT) { // stop early, because some OSes have trim, and won't allow the window // to go smaller than it. return shellBounds.width > 10; } } return false; } public void run() { while (canContinue()) { long lStartedAt = System.currentTimeMillis(); shell.getDisplay().syncExec(new AERunnable() { public void runSupport() { if (shell == null || shell.isDisposed()) { return; } if (shellBounds == null) { shellBounds = shell.getBounds(); } int delta; if (slideIn) { switch (direction) { case SWT.UP: delta = Math.min(endBounds.height - shellBounds.height, STEP); shellBounds.height += delta; delta = Math.min(shellBounds.y - endBounds.y, STEP); shellBounds.y -= delta; break; default: break; } } else { switch (direction) { case SWT.RIGHT: delta = Math.min(shellBounds.width, STEP); shellBounds.width -= delta; shellBounds.x += delta; if (shellBounds.width == 0) { shell.dispose(); return; } break; default: break; } } shell.setBounds(shellBounds); shell.update(); } }); try { long lDrawTime = System.currentTimeMillis() - lStartedAt; long lSleepTime = PAUSE - lDrawTime; if (lSleepTime < 15) { double d = (lDrawTime + 15.0) / PAUSE; PAUSE *= d; STEP *= d; lSleepTime = 15; } Thread.sleep(lSleepTime); } catch (Exception e) { } } } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/AdvRenameWindow.java0000644000175000017500000001544611275141736024617 0ustar adrianadrian/* * Created on Sep 3, 2009 3:12:13 PM * Copyright (C) 2009 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.shells; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import com.aelitis.azureus.ui.common.RememberedDecisionsManager; /** * @author TuxPaper * @created Sep 3, 2009 * */ public class AdvRenameWindow { private DownloadManager dm; private Shell shell; private String newName = null; protected int renameDecisions; private static final int RENAME_DISPLAY = 0x1; private static final int RENAME_SAVEPATH = 0x2; private static final int RENAME_TORRENT = 0x4; public static void main(String[] args) { AdvRenameWindow window = new AdvRenameWindow(); window.open(null); window.waitUntilDone(); } public AdvRenameWindow() { } public void open(DownloadManager dm) { this.dm = dm; Utils.execSWTThread(new AERunnable() { public void runSupport() { openInSWT(); } }); } private void openInSWT() { shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.RESIZE); Utils.setShellIcon(shell); shell.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { shell.dispose(); } } }); Messages.setLanguageText(shell, "AdvRenameWindow.title"); Label lblMessage = new Label(shell, SWT.WRAP); Messages.setLanguageText(lblMessage, "AdvRenameWindow.message"); final Text txtInput = new Text(shell, SWT.BORDER); txtInput.setText(dm == null ? "" : dm.getDisplayName()); final Button btnDisplayName = new Button(shell, SWT.CHECK); Messages.setLanguageText(btnDisplayName, "MyTorrentsView.menu.rename.displayed"); final Button btnSavePath = new Button(shell, SWT.CHECK); Messages.setLanguageText(btnSavePath, "MyTorrentsView.menu.rename.save_path"); final Button btnTorrent = new Button(shell, SWT.CHECK); Messages.setLanguageText(btnTorrent, "AdvRenameWindow.rename.torrent"); Composite cButtons = new Composite(shell, SWT.NONE); RowLayout rowLayout = new RowLayout(SWT.HORIZONTAL); rowLayout.fill = true; rowLayout.spacing = 5; cButtons.setLayout(rowLayout); Button btnOk = new Button(cButtons, SWT.PUSH); Messages.setLanguageText(btnOk, "Button.ok"); shell.setDefaultButton(btnOk); btnOk.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { newName = txtInput.getText(); renameDecisions = 0; if (btnDisplayName.getSelection()) { renameDecisions |= RENAME_DISPLAY; } if (btnSavePath.getSelection()) { renameDecisions |= RENAME_SAVEPATH; } if (btnTorrent.getSelection()) { renameDecisions |= RENAME_TORRENT; } RememberedDecisionsManager.setRemembered("adv.rename", renameDecisions); Utils.getOffOfSWTThread(new AERunnable() { public void runSupport() { doRename(); } }); shell.dispose(); } public void widgetDefaultSelected(SelectionEvent e) { } }); Button btnCancel = new Button(cButtons, SWT.PUSH); Messages.setLanguageText(btnCancel, "Button.cancel"); btnCancel.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { shell.dispose(); } public void widgetDefaultSelected(SelectionEvent e) { } }); shell.setLayout(new FormLayout()); FormData fd; fd = new FormData(); fd.top = new FormAttachment(0, 3); fd.left = new FormAttachment(0, 3); fd.right = new FormAttachment(100, -3); lblMessage.setLayoutData(fd); fd = new FormData(); fd.top = new FormAttachment(lblMessage, 5); fd.left = new FormAttachment(0, 3); fd.right = new FormAttachment(100, -3); fd.width = 300; txtInput.setLayoutData(fd); fd = new FormData(); fd.top = new FormAttachment(txtInput, 5); fd.left = new FormAttachment(0, 8); fd.right = new FormAttachment(100, -3); btnDisplayName.setLayoutData(fd); fd = new FormData(); fd.top = new FormAttachment(btnDisplayName, 2); fd.left = new FormAttachment(0, 8); fd.right = new FormAttachment(100, -3); btnSavePath.setLayoutData(fd); fd = new FormData(); fd.top = new FormAttachment(btnSavePath, 2); fd.left = new FormAttachment(0, 8); fd.right = new FormAttachment(100, -3); btnTorrent.setLayoutData(fd); int renameDecisions = RememberedDecisionsManager.getRememberedDecision("adv.rename"); if ((renameDecisions & RENAME_DISPLAY) > 0) { btnDisplayName.setSelection(true); } if ((renameDecisions & RENAME_SAVEPATH) > 0) { btnSavePath.setSelection(true); } if ((renameDecisions & RENAME_TORRENT) > 0) { btnTorrent.setSelection(true); } fd = new FormData(); fd.top = new FormAttachment(btnTorrent, 5); fd.right = new FormAttachment(100, -3); fd.bottom = new FormAttachment(100, -3); cButtons.setLayoutData(fd); shell.pack(); Utils.centreWindow(shell); shell.open(); } private void waitUntilDone() { while (shell != null && !shell.isDisposed()) { if (!shell.getDisplay().readAndDispatch()) { shell.getDisplay().sleep(); } } } private void doRename() { if (dm == null) { return; } if ((renameDecisions & RENAME_DISPLAY) > 0) { dm.getDownloadState().setDisplayName(newName); } if ((renameDecisions & RENAME_SAVEPATH) > 0) { try { dm.renameDownload(newName); } catch (Exception e) { Logger.log(new LogAlert(dm, LogAlert.REPEATABLE, "Download data rename operation failed", e)); } } if ((renameDecisions & RENAME_TORRENT) > 0) { try { dm.renameTorrentSafe(newName); } catch (Exception e) { Logger.log(new LogAlert(dm, LogAlert.REPEATABLE, "Torrent rename operation failed", e)); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/ShellDocker.java0000644000175000017500000001415411053727112023747 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.shells; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; /** * A utility class that helps in docking a given Shell to a given Control * @author khai * */ public class ShellDocker { private DockPosition anchorControlPosition = new DockPosition(); private boolean isDocked = true; private boolean moveWithShell = true; private boolean resizeWithShell = false; private Listener dockingEnabler = null; private Control anchorControl = null; private Shell dockedShell = null; private Shell mainShell = null; public ShellDocker(Control anchorControl, Shell dockedShell) { if (null == anchorControl || true == anchorControl.isDisposed()) { throw new NullPointerException("anchorControl cannot be null or disposed"); } if (null == dockedShell || true == dockedShell.isDisposed()) { throw new NullPointerException("dockedShell cannot be null or disposed"); } this.anchorControl = anchorControl; this.dockedShell = dockedShell; mainShell = anchorControl.getShell(); } /** * Opens the shell */ public void openShell() { openShell(isDocked(), false); } /** * Opens the shell as docked * @param isDocked */ public void openShell(boolean isDocked) { openShell(isDocked, false); } /** * Opens the shell as docked and animated * @param isDocked * @param isAnimated */ public void openShell(boolean isDocked, boolean isAnimated) { setDocked(isDocked); if (false == isDocked) { /* * Centers the window by default */ UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (null == uiFunctions) { /* * Centers on the active monitor */ Utils.centreWindow(dockedShell); } else { /* * Centers on the main application window */ Utils.centerWindowRelativeTo(dockedShell, uiFunctions.getMainShell()); } } if (false == isAnimated) { dockedShell.open(); } else { //TODO: implement any fancy animation FX here; this is currently just opening the shell normally dockedShell.open(); } } public boolean isDocked() { return isDocked; } public void setDocked(boolean isDocked) { this.isDocked = isDocked; if (true == isDocked) { performDocking(); if (null == dockingEnabler) { dockingEnabler = new Listener() { public void handleEvent(Event event) { if (event.type == SWT.Resize) { if (true == isResizeWithShell()) { System.out.println("resizing");//KN: sysout } else { performDocking(); } } else if (event.type == SWT.Move) { performDocking(); } } }; } if (null != mainShell && false == mainShell.isDisposed()) { if (true == isMoveWithShell()) { mainShell.addListener(SWT.Move, dockingEnabler); } if (true == isResizeWithShell()) { mainShell.addListener(SWT.Resize, dockingEnabler); } anchorControl.addListener(SWT.Move, dockingEnabler); anchorControl.addListener(SWT.Resize, dockingEnabler); } anchorControl.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { setDocked(false); } }); dockedShell.addListener(SWT.Close, new Listener() { public void handleEvent(Event e) { setDocked(false); } }); } else { if (null != mainShell && false == mainShell.isDisposed()) { if (null != dockingEnabler) { mainShell.removeListener(SWT.Move, dockingEnabler); mainShell.removeListener(SWT.Resize, dockingEnabler); } } if (null != anchorControl && false == anchorControl.isDisposed()) { if (null != dockingEnabler) { anchorControl.removeListener(SWT.Move, dockingEnabler); anchorControl.removeListener(SWT.Resize, dockingEnabler); } } } } private void performDocking() { if (true == isAlive()) { switch (anchorControlPosition.getPosition()) { case DockPosition.TOP_LEFT: dockedShell.setLocation(mainShell.toDisplay(anchorControl.getLocation())); break; case DockPosition.TOP_RIGHT: break; case DockPosition.BOTTOM_LEFT: { Point p = mainShell.toDisplay(anchorControl.getLocation()); p.x += anchorControlPosition.getOffset().xOffset; p.y += anchorControlPosition.getOffset().yOffset; p.y += anchorControl.getSize().y; dockedShell.setLocation(p); } break; case DockPosition.BOTTOM_RIGHT: { Point p = mainShell.toDisplay(anchorControl.getLocation()); p.x += anchorControlPosition.getOffset().xOffset; p.y += anchorControlPosition.getOffset().yOffset; p.x += anchorControl.getSize().x; p.y += anchorControl.getSize().y; dockedShell.setLocation(p); } break; default: break; } } } private boolean isAlive() { if (null == mainShell || true == mainShell.isDisposed()) { System.err.println("\tmainshell is disposed?");//KN: sysout return false; } if (null == dockedShell || true == dockedShell.isDisposed()) { System.err.println("\tdockedShell is disposed?");//KN: sysout return false; } if (null == anchorControl || true == anchorControl.isDisposed()) { System.err.println("\tanchorControl is disposed?");//KN: sysout return false; } return true; } public boolean isMoveWithShell() { return moveWithShell; } public void setMoveWithShell(boolean moveWithShell) { this.moveWithShell = moveWithShell; } public boolean isResizeWithShell() { return resizeWithShell; } public void setResizeWithShell(boolean resizeWithShell) { this.resizeWithShell = resizeWithShell; } public DockPosition getAnchorControlPosition() { return anchorControlPosition; } public void setAnchorControlPosition(DockPosition anchorControlPosition) { this.anchorControlPosition = anchorControlPosition; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/MultipageWizard.java0000644000175000017500000001764411275141736024677 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.shells; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; abstract public class MultipageWizard { private Shell shell; private int shellStyle; private Composite topPanel; private Composite contentPanel; private Label titleLabel; private Label descriptionLabel; /** * A map of pageID(String)/IWizardPage; using LinkedHashMap since the order the pages are inserted is important */ private Map pages = new LinkedHashMap(); private StackLayout contentStackLayout; private IWizardPage currentPage; private IWizardPage previousPage; private List initializedPages = new ArrayList(); public abstract void createPages(); private void init() { shell = ShellFactory.createMainShell(shellStyle); createControls(); createPages(); } private void createControls() { GridLayout gLayout = new GridLayout(); gLayout.marginHeight = 0; gLayout.marginWidth = 0; gLayout.verticalSpacing = 0; shell.setLayout(gLayout); Utils.setShellIcon(shell); topPanel = new Composite(shell, SWT.NONE); topPanel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); GridLayout gLayout1 = new GridLayout(); gLayout1.marginBottom = 10; topPanel.setLayout(gLayout1); topPanel.setBackground(shell.getDisplay().getSystemColor( SWT.COLOR_LIST_BACKGROUND)); topPanel.setBackgroundMode(SWT.INHERIT_FORCE); Label separator1 = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL); separator1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); contentPanel = new Composite(shell, SWT.NONE); contentPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); contentStackLayout = new StackLayout(); contentPanel.setLayout(contentStackLayout); titleLabel = new Label(topPanel, SWT.NONE); titleLabel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); Utils.setFontHeight(titleLabel, 16, SWT.NORMAL); descriptionLabel = new Label(topPanel, SWT.WRAP); GridData gData = new GridData(SWT.FILL, SWT.FILL, true, true); gData.horizontalIndent = 10; descriptionLabel.setLayoutData(gData); shell.layout(true, true); } public void fullScreen(boolean isFullScreen) { topPanel.setVisible(false == isFullScreen); ((GridData) topPanel.getLayoutData()).exclude = isFullScreen; shell.layout(true, true); } public boolean addPage(IWizardPage page) { if (null == page) { return false; } if (true == pages.containsKey(page.getPageID())) { Debug.out("MultipageWizard:: a page with this ID already exists ID:" + page.getPageID()); return false; } pages.put(page.getPageID(), page); if (true == page.isInitOnStartup()) { page.createControls(contentPanel); initializedPages.add(page.getPageID()); } return true; } public boolean isFirstPage(String pageID) { if (false == pages.isEmpty()) { return pageID.equals(((IWizardPage) pages.values().iterator().next()).getPageID()); } return false; } public boolean isLastPage(String pageID) { if (false == pages.isEmpty()) { IWizardPage page = null; for (Iterator iterator = pages.values().iterator(); iterator.hasNext();) { page = (IWizardPage) iterator.next(); } if (null != page) { return page.getPageID().equals(pageID); } } return false; } public boolean removePage(IWizardPage page) { if (null == page) { return false; } if (false == pages.containsKey(page.getPageID())) { Debug.out("MultipageWizard:: a page with this ID is not found ID:" + page.getPageID()); return false; } pages.remove(page.getPageID()); page.performDispose(); return true; } public void showPage(String pageID) { if (false == pages.containsKey(pageID)) { Debug.out("MultipageWizard:: a page with this ID is not found ID:" + pageID); return; } IWizardPage page = (IWizardPage) pages.get(pageID); if (null != currentPage) { if (true == currentPage.getPageID().equals(page.getPageID())) { return; } currentPage.performAboutToBeHidden(); } /* * Initializing the page if not done already */ if (false == initializedPages.contains(page.getPageID())) { page.createControls(contentPanel); initializedPages.add(page.getPageID()); } page.performAboutToBeShown(); previousPage = currentPage; currentPage = page; contentStackLayout.topControl = page.getControl(); update(); contentPanel.layout(true); } public void open() { /* * Show the first page */ if (false == pages.isEmpty()) { IWizardPage page = (IWizardPage) pages.values().iterator().next(); showPage(page.getPageID()); } shell.open(); } private void update() { if (null != currentPage) { setText(currentPage.getWindowTitle()); setTitle(currentPage.getTitle()); setDescription(currentPage.getDesciption()); } } public void setTitle(String title) { titleLabel.setText(title + ""); } public void setDescription(String description) { descriptionLabel.setText(description + ""); } /** * Return the IWizardPage with the given id; returns null if page is not found * @param pageID * @return */ public IWizardPage getPage(String pageID) { if (false == pages.containsKey(pageID)) { Debug.out("MultipageWizard:: a Page with this ID is not found ID:" + pageID); return null; } return (IWizardPage) pages.get(pageID); } public void performCancel() { close(); } public void performNext() { if (true == pages.isEmpty()) { return; } if (null == currentPage) { IWizardPage page = (IWizardPage) pages.values().iterator().next(); showPage(page.getPageID()); } else { boolean foundCurrent = false; for (Iterator iterator = pages.values().iterator(); iterator.hasNext();) { IWizardPage page = (IWizardPage) iterator.next(); if (true == foundCurrent) { showPage(page.getPageID()); return; } if (page.getPageID().equals(currentPage.getPageID())) { foundCurrent = true; } } if (false == foundCurrent) { Debug.out("MultipageWizard:: there is no more page to go to"); } } } public void performBack() { if (null != previousPage) { showPage(previousPage.getPageID()); } } /* =========================================== * Below are just some convenience delegations * =========================================== */ public Shell getShell() { return shell; } public void close() { shell.close(); } public Object getData(String key) { return shell.getData(key); } public Point getLocation() { return shell.getLocation(); } public Point getSize() { return shell.getSize(); } public String getText() { return shell.getText(); } public String getToolTipText() { return shell.getToolTipText(); } public void setBounds(int x, int y, int width, int height) { shell.setBounds(x, y, width, height); } public void setData(String key, Object value) { shell.setData(key, value); } public void setLocation(int x, int y) { shell.setLocation(x, y); } public void setSize(int width, int height) { shell.setSize(width, height); } public void setText(String string) { shell.setText(string); } public void setToolTipText(String string) { shell.setToolTipText(string); } public void setVisible(boolean visible) { shell.setVisible(visible); } public Image getImage() { return shell.getImage(); } public void setImage(Image image) { shell.setImage(image); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/SimpleBrowserWindow.java0000644000175000017500000000730611275141736025546 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.shells; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.*; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; /** * @author TuxPaper * @created Jul 18, 2007 * */ public class SimpleBrowserWindow { private Shell shell; private Browser browser; public SimpleBrowserWindow(Shell parent, String url, double wPct, double hPct, boolean allowResize, boolean isModal) { if (parent == null) { init(parent, url, 0, 0, allowResize, isModal); } else { Rectangle clientArea = parent.getClientArea(); init(parent, url, (int) (clientArea.width * wPct), (int) (clientArea.height * hPct), allowResize, isModal); } } public SimpleBrowserWindow(Shell parent, String url, int w, int h, boolean allowResize, boolean isModal) { init(parent, url, w, h, allowResize, isModal); } private void init(Shell parent, String url, int w, int h, boolean allowResize, boolean isModal) { if (parent == null) { parent = Utils.findAnyShell(); } int style = SWT.DIALOG_TRIM; if (allowResize) { style |= SWT.RESIZE; } if (isModal) { style |= SWT.APPLICATION_MODAL; } shell = ShellFactory.createShell(parent, style); shell.setLayout(new FillLayout()); Utils.setShellIcon(shell); browser = Utils.createSafeBrowser(shell, SWT.NONE); if (browser == null) { shell.dispose(); return; } browser.addProgressListener(new ProgressListener() { public void completed(ProgressEvent event) { shell.open(); } public void changed(ProgressEvent event) { } }); browser.addCloseWindowListener(new CloseWindowListener() { public void close(WindowEvent event) { if (shell == null || shell.isDisposed()) { return; } shell.dispose(); } }); browser.addTitleListener(new TitleListener() { public void changed(TitleEvent event) { if (shell == null || shell.isDisposed()) { return; } shell.setText(event.title); } }); if (w > 0 && h > 0) { shell.setSize(w, h); } Utils.centerWindowRelativeTo(shell, parent); browser.setUrl(url); browser.setData("StartURL", url); } public void waitUntilClosed() { Display display = shell.getDisplay(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display, SWT.DIALOG_TRIM); shell.setSize(800, 600); new SimpleBrowserWindow(shell, "http://google.com", 0.8, 0.5, true, false); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/ShellFader.java0000644000175000017500000000010711006302234023542 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.shells; public class ShellFader { } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/BrowserShell.java0000644000175000017500000000253711267524616024200 0ustar adrianadrian/* * Created on Oct 13, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.ui.swt.shells; import org.gudy.azureus2.core3.internat.MessageText; public class BrowserShell { public BrowserShell( String title_resource, String url, int width, int height ) { MessageBoxShell boxShell = new MessageBoxShell( MessageText.getString( title_resource ), "", new String[] { //MessageText.getString("Button.ok") }, 0 ); boxShell.setUrl( url ); boxShell.setBrowserFollowLinks( true ); boxShell.setSquish( true ); boxShell.setSize( width, height ); boxShell.open(null); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/DockPosition.java0000644000175000017500000000210011053727112024141 0ustar adrianadrian/** * */ package org.gudy.azureus2.ui.swt.shells; /** * A simple class to declare a docking position and an offset; currently only used by ShellDocker * @author khai * */ public class DockPosition { public static final int TOP_LEFT = 1; public static final int BOTTOM_LEFT = 2; public static final int TOP_RIGHT = 3; public static final int BOTTOM_RIGHT = 4; private int position = TOP_LEFT; private Offset offset = new Offset(0, 0); public DockPosition() { this(TOP_LEFT, null); } public DockPosition(int position, Offset offset) { if (position == TOP_LEFT || position == TOP_RIGHT || position == BOTTOM_LEFT || position == BOTTOM_RIGHT) { this.position = position; } else { this.position = TOP_LEFT; } if (null != offset) { this.offset = offset; } } public int getPosition() { return position; } public void setPosition(int position) { this.position = position; } public Offset getOffset() { return offset; } public void setOffset(Offset offset) { if (null != offset) { this.offset = offset; } } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/shells/CoreWaiterSWT.java0000644000175000017500000000437111267524616024225 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.shells; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; public class CoreWaiterSWT { private static boolean DEBUG = false; public enum TriggerInThread { SWT_THREAD, ANY_THREAD, NEW_THREAD } private static Shell shell; public static void waitForCoreRunning(final AzureusCoreRunningListener l) { waitForCore(TriggerInThread.SWT_THREAD, l); } public static void waitForCore(final TriggerInThread triggerInThread, final AzureusCoreRunningListener l) { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(final AzureusCore core) { if (triggerInThread == TriggerInThread.ANY_THREAD) { l.azureusCoreRunning(core); } else if (triggerInThread == TriggerInThread.NEW_THREAD) { new AEThread2("CoreWaiterInvoke", true) { public void run() { l.azureusCoreRunning(core); } }.start(); } Utils.execSWTThread(new AERunnable() { public void runSupport() { // TODO: Need to detect cancel (can't rely on shell status since it may never open) if (shell != null && !shell.isDisposed()) { shell.dispose(); shell = null; } if (triggerInThread == TriggerInThread.SWT_THREAD) { l.azureusCoreRunning(core); } } }); } }); if (!AzureusCoreFactory.isCoreRunning()) { if (DEBUG) { System.out.println("NOT AVAIL FOR " + Debug.getCompressedStackTrace()); } Utils.execSWTThread(new AERunnable() { public void runSupport() { showWaitWindow(); } }); } else if (DEBUG) { System.out.println("NO NEED TO WAIT.. CORE AVAIL! " + Debug.getCompressedStackTrace()); } } protected static void showWaitWindow() { if (shell != null && !shell.isDisposed()) { shell.forceActive(); return; } shell = UIFunctionsManagerSWT.getUIFunctionsSWT().showCoreWaitDlg(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/FileDownloadWindow.java0000644000175000017500000002176611214303632024020 0ustar adrianadrian/* * File : FileDownloadWindow.java * Created : 3 nov. 2003 12:51:53 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt; import java.net.URLDecoder; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloader; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderCallBackInterface; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderFactory; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.progress.*; /** * @author Olivier * */ public class FileDownloadWindow implements TorrentDownloaderCallBackInterface, IProgressReportConstants { TorrentDownloader downloader; TorrentDownloaderCallBackInterface listener; IProgressReporter pReporter; Shell parent; String original_url; String decoded_url; String referrer; Map request_properties; String dirName = null; String shortURL = null; /** * Create a file download window. Add torrent when done downloading * * @param _azureus_core * @param parent * @param url * @param referrer */ public FileDownloadWindow(Shell parent, final String url, final String referrer, Map request_properties) { this(parent, url, referrer, request_properties, null); } /** * Create a file download window. If no listener is supplied, torrent will * be added when download is complete. If a listener is supplied, caller * handles it * * @param _azureus_core * @param parent * @param url * @param referrer * @param listener */ public FileDownloadWindow(final Shell parent, final String url, final String referrer, final Map request_properties, final TorrentDownloaderCallBackInterface listener) { this.parent = parent; this.original_url = url; this.referrer = referrer; this.listener = listener; this.request_properties = request_properties; try { decoded_url = URLDecoder.decode(original_url, "UTF8"); } catch (Throwable e) { decoded_url = original_url; } Utils.execSWTThread(new AERunnable() { public void runSupport() { init(); } }); } private void init() { if (COConfigurationManager.getBooleanParameter("Save Torrent Files")) { try { dirName = COConfigurationManager.getDirectoryParameter("General_sDefaultTorrent_Directory"); } catch (Exception egnore) { } } if (dirName == null) { DirectoryDialog dd = new DirectoryDialog(parent, SWT.NULL); dd.setText(MessageText.getString("fileDownloadWindow.saveTorrentIn")); dirName = dd.open(); } if (dirName == null) return; pReporter = ProgressReportingManager.getInstance().addReporter(); setupAndShowDialog(); downloader = TorrentDownloaderFactory.create(this, original_url, referrer, request_properties, dirName); downloader.setIgnoreReponseCode(true); downloader.start(); } /** * Initializes the reporter and show the download dialog if it is not suppressed */ private void setupAndShowDialog() { if (null != pReporter) { pReporter.setName(MessageText.getString("fileDownloadWindow.state_downloading") + ": " + getFileName(decoded_url)); pReporter.appendDetailMessage(MessageText.getString("fileDownloadWindow.downloading") + getShortURL(decoded_url)); pReporter.setTitle(MessageText.getString("fileDownloadWindow.title")); pReporter.setIndeterminate(true); pReporter.setCancelAllowed(true); pReporter.setRetryAllowed(true); /* * Listen to and respond to events from the reporters */ pReporter.addListener(new IProgressReporterListener() { public int report(IProgressReport pReport) { switch (pReport.getReportType()) { case REPORT_TYPE_CANCEL: if (null != downloader) { downloader.cancel(); //KN: correct logger id? Logger.log(new LogEvent(LogIDs.LOGGER, MessageText.getString( "FileDownload.canceled", new String[] { getShortURL(decoded_url) }))); } break; case REPORT_TYPE_DONE: return RETVAL_OK_TO_DISPOSE; case REPORT_TYPE_RETRY: if (true == pReport.isRetryAllowed()) { downloader.cancel(); downloader = TorrentDownloaderFactory.create( FileDownloadWindow.this, original_url, referrer, request_properties, dirName); downloader.setIgnoreReponseCode(true); downloader.start(); } break; default: break; } return RETVAL_OK; } }); ProgressReporterWindow.open(pReporter, ProgressReporterWindow.AUTO_CLOSE); } } public void TorrentDownloaderEvent(int state, TorrentDownloader inf) { if (listener != null) listener.TorrentDownloaderEvent(state, inf); update(); } private void update() { int state = downloader.getDownloadState(); int percentDone = downloader.getPercentDone(); IProgressReport pReport = pReporter.getProgressReport(); switch (state) { case TorrentDownloader.STATE_CANCELLED: if (false == pReport.isCanceled()) { pReporter.cancel(); } return; case TorrentDownloader.STATE_DOWNLOADING: pReporter.setPercentage(percentDone, downloader.getStatus()); break; case TorrentDownloader.STATE_ERROR: /* * If the user has canceled then a call to downloader.cancel() has already been made * so don't bother prompting for the user to retry */ if (true == pReport.isCanceled()) { return; } pReporter.setErrorMessage(MessageText.getString("fileDownloadWindow.state_error") + downloader.getError()); return; case TorrentDownloader.STATE_FINISHED: pReporter.setDone(); /* * If the listener is present then it handle finishing up; otherwise open the torrent that * was just downloaded */ if (listener == null) { TorrentOpener.openTorrent(downloader.getFile().getAbsolutePath()); } return; default: } } /** * Returns a shortened version of the given url * @param url * @return */ private String getShortURL(final String url) { if (null == shortURL) { shortURL = url; // truncate any url parameters for display. This has the benefit of hiding additional uninteresting // parameters added to urls to control the download process (e.g. "&pause_on_error" for magnet downloads") int amp_pos = shortURL.indexOf('&'); if (amp_pos != -1) { shortURL = shortURL.substring(0, amp_pos + 1) + "..."; } shortURL = shortURL.replaceAll("&", "&&"); } return shortURL; } /** * Brute-force extraction of the torrent file name or title from the given URL * @param url * @return */ private String getFileName(String url) { try { String lc_url = url.toLowerCase(MessageText.LOCALE_ENGLISH); /* * First try to retrieve the 'title' field if it has one */ int idx = lc_url.indexOf("&title="); if (idx >= 0) { String title = url.substring(idx + "&title=".length()); idx = title.indexOf('&'); if (idx > 0) { title = title.substring(0, idx); title = title.replace('+', ' '); if (title.length() > 0) { return title; } } } /* * If no 'title' field was found then just get the file name instead * * This is not guaranteed to work in all cases because we are simply searching * for the occurrence of ".torrent" and assuming that it is the extension of the file. * This method will return inaccurate result if any other parameter of the URL also has the ".torrent" * string in it. */ url = getShortURL(url); lc_url = url.toLowerCase(MessageText.LOCALE_ENGLISH); if ( lc_url.startsWith( "magnet:") || lc_url.startsWith( "dht:" )){ return( url ); } String tmp = url.substring(url.lastIndexOf('/') + 1); if (tmp.toLowerCase(MessageText.LOCALE_ENGLISH).lastIndexOf(".torrent") > 0) { tmp = tmp.substring(0, tmp.toLowerCase(MessageText.LOCALE_ENGLISH).lastIndexOf(".torrent")); } return tmp + ".torrent"; } catch (Exception t) { // don't print debug, this code is just parsing lazyness //Debug.out(t); } return url; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/IconBarEnabler.java0000644000175000017500000000204507764770370023102 0ustar adrianadrian/* * File : IconBarEnabler.java * Created : 7 dc. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt; /** * @author Olivier * */ public interface IconBarEnabler { public boolean isEnabled(String itemKey); public boolean isSelected(String itemKey); public void itemActivated(String itemKey); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsimpl/0000755000175000017500000000000011310377636021761 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewImpl.java0000644000175000017500000002033111051462562025206 0ustar adrianadrian/* * File : UISWTViewImpl.java * Created : Oct 14, 2005 * By : TuxPaper * * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.pluginsimpl; import java.awt.Frame; import java.awt.Panel; import org.eclipse.swt.SWT; import org.eclipse.swt.awt.SWT_AWT; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.plugins.UISWTView; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import org.gudy.azureus2.ui.swt.views.AbstractIView; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import org.gudy.azureus2.plugins.ui.UIRuntimeException; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; /** * This class creates an IView that triggers UISWTViewEventListener * appropriately * * @author TuxPaper * */ public class UISWTViewImpl extends AbstractIView implements UISWTView { public static final String CFG_PREFIX = "Views.plugins."; private Object dataSource = null; private boolean useCoreDataSource = false; private final UISWTViewEventListener eventListener; public UISWTViewEventListener getEventListener() { return eventListener; } private Composite composite; private final String sViewID; private int iControlType = UISWTView.CONTROLTYPE_SWT; private boolean bFirstGetCompositeCall = true; private final String sParentID; private String sTitle = null; public UISWTViewImpl(String sParentID, String sViewID, UISWTViewEventListener eventListener) throws Exception { this(sParentID, sViewID, eventListener, null); } /** * * @param sViewID * @param eventListener */ public UISWTViewImpl(String sParentID, String sViewID, UISWTViewEventListener eventListener, Object datasource) throws Exception { this.sParentID = sParentID; this.sViewID = sViewID; this.eventListener = eventListener; this.dataSource = datasource; if (eventListener instanceof UISWTViewCoreEventListener) { useCoreDataSource = true; } if (!eventListener.eventOccurred(new UISWTViewEventImpl(this, UISWTViewEvent.TYPE_CREATE, this))) throw new UISWTViewEventCancelledException(); } // UISWTPluginView implementation // ============================== public Object getDataSource() { return dataSource; } public String getViewID() { return sViewID; } public void closeView() { try { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { uiFunctions.closePluginView(this); } } catch (Exception e) { Debug.out(e); } } public void setControlType(int iControlType) { if (iControlType == UISWTView.CONTROLTYPE_AWT || iControlType == UISWTView.CONTROLTYPE_SWT) this.iControlType = iControlType; } public void triggerEvent(int eventType, Object data) { try { eventListener.eventOccurred(new UISWTViewEventImpl(this, eventType, data)); } catch (Throwable t) { throw (new UIRuntimeException("UISWTView.triggerEvent:: ViewID=" + sViewID + "; EventID=" + eventType + "; data=" + data, t)); } } private boolean triggerEvent2(int eventType, Object data) { try { return eventListener.eventOccurred(new UISWTViewEventImpl(this, eventType, data)); } catch (Throwable t) { throw (new UIRuntimeException("UISWTView.triggerEvent:: ViewID=" + sViewID + "; EventID=" + eventType + "; data=" + data, t)); } } public void setTitle(String title) { sTitle = title; } // AbstractIView Implementation // ============================ public void dataSourceChanged(Object newDataSource) { dataSource = PluginCoreUtils.convert(newDataSource, useCoreDataSource); triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, dataSource); } public void delete() { triggerEvent(UISWTViewEvent.TYPE_DESTROY, null); super.delete(); } public Composite getComposite() { if (bFirstGetCompositeCall) { bFirstGetCompositeCall = false; } return composite; } public String getData() { final String key = CFG_PREFIX + sViewID + ".title"; if (MessageText.keyExists(key)) return key; // For now, to get plugin developers to update their plugins // return key; // For release, change it to this, to make it at least shorter: return sViewID; } public String getFullTitle() { if (sTitle != null) return sTitle; return super.getFullTitle(); } public void initialize(Composite parent) { if (iControlType == UISWTView.CONTROLTYPE_SWT) { GridData gridData; Layout parentLayout = parent.getLayout(); if (parentLayout instanceof FormLayout) { composite = parent; } else { composite = new Composite(parent, SWT.NULL); GridLayout layout = new GridLayout(1, false); layout.marginHeight = 0; layout.marginWidth = 0; composite.setLayout(layout); gridData = new GridData(GridData.FILL_BOTH); composite.setLayoutData(gridData); } triggerEvent(UISWTViewEvent.TYPE_INITIALIZE, composite); if (composite.getLayout() instanceof GridLayout) { // Force children to have GridData layoutdata. Control[] children = composite.getChildren(); for (int i = 0; i < children.length; i++) { Control control = children[i]; Object layoutData = control.getLayoutData(); if (layoutData == null || !(layoutData instanceof GridData)) { if (layoutData != null) Logger.log(new LogEvent(LogIDs.PLUGIN, LogEvent.LT_WARNING, "Plugin View '" + sViewID + "' tried to setLayoutData of " + control + " to a " + layoutData.getClass().getName())); if (children.length == 1) gridData = new GridData(SWT.FILL, SWT.FILL, true, true); else gridData = new GridData(); control.setLayoutData(gridData); } } } } else { composite = new Composite(parent, SWT.EMBEDDED); FillLayout layout = new FillLayout(); layout.marginHeight = 0; layout.marginWidth = 0; composite.setLayout(layout); GridData gridData = new GridData(GridData.FILL_BOTH); composite.setLayoutData(gridData); Frame f = SWT_AWT.new_Frame(composite); Panel pan = new Panel(); f.add(pan); triggerEvent(UISWTViewEvent.TYPE_INITIALIZE, pan); } if (composite != null) { composite.addListener(SWT.Activate, new Listener() { public void handleEvent(Event event) { triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null); } }); composite.addListener(SWT.Deactivate, new Listener() { public void handleEvent(Event event) { triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null); } }); } } public void refresh() { triggerEvent(UISWTViewEvent.TYPE_REFRESH, null); } public void updateLanguage() { super.updateLanguage(); triggerEvent(UISWTViewEvent.TYPE_LANGUAGEUPDATE, null); } // Core Functions public String getParentID() { return sParentID; } public boolean requestClose() { return triggerEvent2(UISWTViewEvent.TYPE_CLOSE, null); } public boolean useCoreDataSource() { return useCoreDataSource; } public void setUseCoreDataSource(boolean useCoreDataSource) { if (this.useCoreDataSource == useCoreDataSource) { return; } this.useCoreDataSource = useCoreDataSource; dataSourceChanged(dataSource); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTInstanceImpl.java0000644000175000017500000006361411275141740026053 0ustar adrianadrian/* * Created on 05-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.pluginsimpl; import java.awt.*; import java.io.File; import java.io.InputStream; import java.lang.ref.WeakReference; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; import org.eclipse.swt.SWT; import org.eclipse.swt.awt.SWT_AWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.*; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AETemporaryFileHandler; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.ui.*; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.plugins.ui.model.BasicPluginViewModel; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener; import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.download.DownloadImpl; import org.gudy.azureus2.pluginsimpl.local.ui.UIManagerImpl; import org.gudy.azureus2.ui.common.util.MenuItemManager; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.mainwindow.*; import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar; import org.gudy.azureus2.ui.swt.minibar.DownloadBar; import org.gudy.azureus2.ui.swt.plugins.*; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import org.gudy.azureus2.ui.swt.views.table.utils.TableContextMenuManager; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.ui.IUIIntializer; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.TableStructureEventDispatcher; import com.aelitis.azureus.ui.common.table.impl.TableColumnImpl; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; public class UISWTInstanceImpl implements UIInstanceFactory, UISWTInstance, UIManagerEventListener { private AzureusCore core; private Map awt_view_map = new WeakHashMap(); private Map config_view_map = new WeakHashMap(); private Map> views = new HashMap>(); private Map plugin_map = new WeakHashMap(); private boolean bUIAttaching; private final UIFunctionsSWT uiFunctions; public UISWTInstanceImpl(AzureusCore _core) { core = _core; // Since this is a UI **SWT** Instance Implementor, it's assumed // that the UI Functions are of UIFunctionsSWT uiFunctions = (UIFunctionsSWT) UIFunctionsManager.getUIFunctions(); } public void init(IUIIntializer init) { UIManager ui_manager = PluginInitializer.getDefaultInterface().getUIManager(); ui_manager.addUIEventListener(this); bUIAttaching = true; ((UIManagerImpl) ui_manager).attachUI(this, init); bUIAttaching = false; } public UIInstance getInstance( PluginInterface plugin_interface ) { UIInstance instance = (UIInstance)plugin_map.get( plugin_interface ); if ( instance == null ){ instance = new instanceWrapper( plugin_interface, this ); plugin_map.put( plugin_interface, instance ); } return( instance ); } public boolean eventOccurred( final UIManagerEvent event ) { boolean done = true; final Object data = event.getData(); switch( event.getType()){ case UIManagerEvent.ET_SHOW_TEXT_MESSAGE: { Utils.execSWTThread( new Runnable() { public void run() { String[] params = (String[])data; new TextViewerWindow( params[0], params[1], params[2] ); } }); break; } case UIManagerEvent.ET_SHOW_MSG_BOX: { final int[] result = { UIManagerEvent.MT_NONE }; Utils.execSWTThread( new Runnable() { public void run() { UIFunctionsManagerSWT.getUIFunctionsSWT().bringToFront(); Object[] params = (Object[])data; long _styles = ((Long)(params[2])).longValue(); int styles = 0; if (( _styles & UIManagerEvent.MT_YES ) != 0 ){ styles |= SWT.YES; } if (( _styles & UIManagerEvent.MT_NO ) != 0 ){ styles |= SWT.NO; } if (( _styles & UIManagerEvent.MT_OK ) != 0 ){ styles |= SWT.OK; } if (( _styles & UIManagerEvent.MT_CANCEL ) != 0 ){ styles |= SWT.CANCEL; } MessageBoxShell mb = new MessageBoxShell(styles, MessageText.getString((String)params[0]), MessageText.getString((String)params[1])); mb.open(null); int _r = mb.waitUntilClosed(); int r = 0; if (( _r & SWT.YES ) != 0 ){ r |= UIManagerEvent.MT_YES; } if (( _r & SWT.NO ) != 0 ){ r |= UIManagerEvent.MT_NO; } if (( _r & SWT.OK ) != 0 ){ r |= UIManagerEvent.MT_OK; } if (( _r & SWT.CANCEL ) != 0 ){ r |= UIManagerEvent.MT_CANCEL; } result[0] = r; } }, false ); event.setResult( new Long( result[0] )); break; } case UIManagerEvent.ET_OPEN_TORRENT_VIA_FILE: { TorrentOpener.openTorrent(((File)data).toString()); break; } case UIManagerEvent.ET_OPEN_TORRENT_VIA_TORRENT: { Torrent t = (Torrent)data; try{ File f = AETemporaryFileHandler.createTempFile(); t.writeToFile( f ); TorrentOpener.openTorrent( f.toString()); }catch( Throwable e ){ Debug.printStackTrace( e ); } break; } case UIManagerEvent.ET_OPEN_TORRENT_VIA_URL: { Display display = SWTThread.getInstance().getDisplay(); display.syncExec(new AERunnable() { public void runSupport() { Object[] params = (Object[]) data; URL target = (URL) params[0]; URL referrer = (URL) params[1]; boolean auto_download = ((Boolean) params[2]).booleanValue(); Map request_properties = (Map)params[3]; // programmatic request to add a torrent, make sure az is visible if (!COConfigurationManager.getBooleanParameter("add_torrents_silently")) { uiFunctions.bringToFront(); } if (auto_download) { Shell shell = uiFunctions.getMainShell(); if (shell != null) { new FileDownloadWindow(shell, target.toString(), referrer == null ? null : referrer.toString(), request_properties ); } } else { // TODO: handle referrer? TorrentOpener.openTorrent(target.toString()); } } }); break; } case UIManagerEvent.ET_PLUGIN_VIEW_MODEL_CREATED: { if ( data instanceof BasicPluginViewModel ){ BasicPluginViewModel model = (BasicPluginViewModel)data; // property bundles can't handle spaces in keys // // If this behaviour changes, change the openView(model) // method lower down. String sViewID = model.getName().replaceAll(" ", "."); BasicPluginViewImpl view = new BasicPluginViewImpl(model); addView(UISWTInstance.VIEW_MAIN, sViewID, view); } break; } case UIManagerEvent.ET_PLUGIN_VIEW_MODEL_DESTROYED: { if ( data instanceof BasicPluginViewModel ){ BasicPluginViewModel model = (BasicPluginViewModel)data; // property bundles can't handle spaces in keys // // If this behaviour changes, change the openView(model) // method lower down. String sViewID = model.getName().replaceAll(" ", "."); removeViews(UISWTInstance.VIEW_MAIN, sViewID); } break; } case UIManagerEvent.ET_PLUGIN_CONFIG_MODEL_CREATED: { if ( data instanceof BasicPluginConfigModel ){ BasicPluginConfigModel model = (BasicPluginConfigModel)data; BasicPluginConfigImpl view = new BasicPluginConfigImpl( new WeakReference( model )); config_view_map.put( model, view ); model.getPluginInterface().addConfigSection( view ); } break; } case UIManagerEvent.ET_PLUGIN_CONFIG_MODEL_DESTROYED: { if ( data instanceof BasicPluginConfigModel ){ BasicPluginConfigModel model = (BasicPluginConfigModel)data; BasicPluginConfigImpl view = (BasicPluginConfigImpl)config_view_map.get( model ); if ( view != null ){ model.getPluginInterface().removeConfigSection( view ); } } break; } case UIManagerEvent.ET_COPY_TO_CLIPBOARD: { ClipboardCopy.copyToClipBoard((String)data); break; } case UIManagerEvent.ET_OPEN_URL: { Utils.launch(((URL)data).toExternalForm()); break; } case UIManagerEvent.ET_CREATE_TABLE_COLUMN:{ if (data instanceof TableColumn) { event.setResult((TableColumn) data); } else { String[] args = (String[]) data; event.setResult(new TableColumnImpl(args[0], args[1])); } break; } case UIManagerEvent.ET_ADD_TABLE_COLUMN:{ TableColumn _col = (TableColumn)data; if ( _col instanceof TableColumnImpl ){ TableColumnManager.getInstance().addColumns(new TableColumnCore[] { (TableColumnCore) _col }); TableStructureEventDispatcher tsed = TableStructureEventDispatcher.getInstance(_col.getTableID()); tsed.tableStructureChanged(true, _col.getForDataSourceType()); }else{ throw(new UIRuntimeException("TableManager.addColumn(..) can only add columns created by createColumn(..)")); } break; } case UIManagerEvent.ET_REGISTER_COLUMN:{ Object[] params = (Object[])data; TableColumnManager tcManager = TableColumnManager.getInstance(); Class dataSource = (Class)params[0]; String columnName = (String)params[1]; tcManager.registerColumn(dataSource, columnName, (TableColumnCreationListener)params[2]); String[] tables = tcManager.getTableIDs(); for ( String tid: tables ){ // we don't know which tables are affected at this point to refresh all. // if this proves to be a performance issue then we would have to use the // datasource to derive affected tables somehow TableStructureEventDispatcher tsed = TableStructureEventDispatcher.getInstance( tid ); tsed.tableStructureChanged(true, dataSource); } break; } case UIManagerEvent.ET_UNREGISTER_COLUMN:{ Object[] params = (Object[])data; TableColumnManager tcManager = TableColumnManager.getInstance(); Class dataSource = (Class)params[0]; String columnName = (String)params[1]; tcManager.unregisterColumn(dataSource, columnName, (TableColumnCreationListener)params[2]); String[] tables = tcManager.getTableIDs(); for ( String tid: tables ){ TableColumnCore col = tcManager.getTableColumnCore( tid, columnName ); if ( col != null ){ col.remove(); } } break; } case UIManagerEvent.ET_ADD_TABLE_CONTEXT_MENU_ITEM:{ TableContextMenuItem item = (TableContextMenuItem)data; TableContextMenuManager.getInstance().addContextMenuItem(item); break; } case UIManagerEvent.ET_ADD_MENU_ITEM: { MenuItem item = (MenuItem)data; MenuItemManager.getInstance().addMenuItem(item); break; } case UIManagerEvent.ET_REMOVE_TABLE_CONTEXT_MENU_ITEM:{ TableContextMenuItem item = (TableContextMenuItem)data; TableContextMenuManager.getInstance().removeContextMenuItem(item); break; } case UIManagerEvent.ET_REMOVE_MENU_ITEM: { MenuItem item = (MenuItem)data; MenuItemManager.getInstance().removeMenuItem(item); break; } case UIManagerEvent.ET_SHOW_CONFIG_SECTION: { event.setResult(new Boolean(false)); if (!(data instanceof String)) break; event.setResult(Boolean.TRUE); uiFunctions.openView(UIFunctions.VIEW_CONFIG, data); break; } case UIManagerEvent.ET_FILE_OPEN: { File file_to_use = (File)data; Utils.launch(file_to_use.getAbsolutePath()); break; } case UIManagerEvent.ET_FILE_SHOW: { File file_to_use = (File)data; final boolean use_open_containing_folder = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled"); ManagerUtils.open(file_to_use, use_open_containing_folder); break; } default: { done = false; break; } } return( done ); } public Display getDisplay() { return SWTThread.getInstance().getDisplay(); } public Image loadImage( String resource ) { throw( new RuntimeException( "plugin specific instance required" )); } protected Image loadImage( PluginInterface pi, String res ) { InputStream is = pi.getPluginClassLoader().getResourceAsStream( res); if ( is != null ){ ImageData imageData = new ImageData(is); return new Image(getDisplay(), imageData); } return null; } public UISWTGraphic createGraphic( Image img) { return new UISWTGraphicImpl(img); } public Shell createShell(int style) { Shell shell = ShellFactory.createMainShell(style); Utils.setShellIcon(shell); return shell; } /** @deprecated */ public void addView(final UISWTPluginView view, boolean bAutoOpen) { // Currently used by firefrog. try { uiFunctions.addPluginView(view); if (bAutoOpen) { uiFunctions.openPluginView(view); } } catch (Throwable e) { // SWT not available prolly } } public void removeView(UISWTPluginView view) { try { uiFunctions.removePluginView(view); } catch (Throwable e) { // SWT not available prolly } } /** @deprecated */ public void addView( UISWTAWTPluginView view, boolean auto_open ) { final WeakReference view_ref = new WeakReference( view ); UISWTPluginView v = new UISWTPluginView() { Composite composite; Component component; boolean first_paint = true; public String getPluginViewName() { return( view_ref.get().getPluginViewName()); } public String getFullTitle() { return( view_ref.get().getPluginViewName()); } public void initialize( Composite _composite ) { first_paint = true; composite = _composite; Composite frame_composite = new Composite(composite, SWT.EMBEDDED); GridData data = new GridData(GridData.FILL_BOTH); frame_composite.setLayoutData(data); Frame f = SWT_AWT.new_Frame(frame_composite); BorderLayout layout = new BorderLayout() { public void layoutContainer(Container parent) { try{ super.layoutContainer( parent ); }finally{ if ( first_paint ){ first_paint = false; view_ref.get().open( component ); } } } }; Panel pan = new Panel( layout ); f.add( pan ); component = view_ref.get().create(); pan.add( component, BorderLayout.CENTER ); } public Composite getComposite() { return( composite ); } public void delete() { super.delete(); view_ref.get().delete( component ); } }; awt_view_map.put( view, v ); addView( v, auto_open ); } public void removeView( UISWTAWTPluginView view ) { UISWTPluginView v = (UISWTPluginView)awt_view_map.remove(view ); if ( v != null ){ removeView( v ); } } public void detach() throws UIException { throw( new UIException( "not supported" )); } public void addView(String sParentID, final String sViewID, final UISWTViewEventListener l) { Map subViews = views.get(sParentID); if (subViews == null) { subViews = new HashMap(); views.put(sParentID, subViews); } subViews.put(sViewID, l); if (sParentID.equals(UISWTInstance.VIEW_MAIN)) { Utils.execSWTThread(new AERunnable() { public void runSupport() { try { uiFunctions.addPluginView(sViewID, l); } catch (Throwable e) { // SWT not available prolly } } }); } } // TODO: Remove views from PeersView, etc public void removeViews(String sParentID, final String sViewID) { Map subViews = views.get(sParentID); if (subViews == null) return; if (sParentID.equals(UISWTInstance.VIEW_MAIN)) { Utils.execSWTThread(new AERunnable() { public void runSupport() { try { if (uiFunctions != null) { uiFunctions.removePluginView(sViewID); } } catch (Throwable e) { // SWT not available prolly } } }); } subViews.remove(sViewID); } public boolean openView(final String sParentID, final String sViewID, final Object dataSource) { return openView(sParentID, sViewID, dataSource, true); } public boolean openView(final String sParentID, final String sViewID, final Object dataSource, final boolean setfocus) { Map subViews = views.get(sParentID); if (subViews == null) { return false; } final UISWTViewEventListener l = subViews.get(sViewID); if (l == null) { return false; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (uiFunctions != null) { uiFunctions.openPluginView(sParentID, sViewID, l, dataSource, setfocus && !bUIAttaching); } } }); return true; } public void openMainView(final String sViewID, final UISWTViewEventListener l, final Object dataSource) { openMainView(sViewID, l, dataSource, true); } public void openMainView(final String sViewID, final UISWTViewEventListener l, final Object dataSource, final boolean setfocus) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (uiFunctions != null) { uiFunctions.openPluginView(UISWTInstance.VIEW_MAIN, sViewID, l, dataSource, setfocus && !bUIAttaching); } } }); } public UISWTView[] getOpenViews(String sParentID) { if (sParentID.equals(UISWTInstance.VIEW_MAIN)) { try { if (uiFunctions != null) { return uiFunctions.getPluginViews(); } } catch (Throwable e) { // SWT not available prolly } } return new UISWTView[0]; } // @see org.gudy.azureus2.plugins.ui.UIInstance#promptUser(java.lang.String, java.lang.String, java.lang.String[], int) public int promptUser(String title, String text, String[] options, int defaultOption) { MessageBoxShell mb = new MessageBoxShell(title, text, options, defaultOption); mb.open(null); // bah, no way to change this to use the UserPrompterResultListener trigger return mb.waitUntilClosed(); } public void showDownloadBar(Download download, final boolean display) { if (!(download instanceof DownloadImpl)) {return;} final DownloadManager dm = ((DownloadImpl)download).getDownload(); if (dm == null) {return;} // Not expecting this, but just in case... Utils.execSWTThread(new AERunnable() { public void runSupport() { if (display) { DownloadBar.open(dm, getDisplay().getActiveShell()); } else { DownloadBar.close(dm); } } }, false); } public void showTransfersBar(final boolean display) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (display) { AllTransfersBar.open(core.getGlobalManager(), getDisplay().getActiveShell()); } else { AllTransfersBar.close(core.getGlobalManager()); } } }, false); } // Core Functions // ============== public Map getViewListeners(String sParentID) { return views.get(sParentID); } /** * @return Map(key=parentid, value=Map(key=id, value=UISWTViewEventListener)) * * @since 3.1.1.1 */ public Map> getAllViews() { return views; } public UIInputReceiver getInputReceiver() { return new SimpleTextEntryWindow(); } public UIMessage createMessage() { return new UIMessageImpl(); } public UISWTStatusEntry createStatusEntry() { final UISWTStatusEntryImpl entry = new UISWTStatusEntryImpl(); UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (functionsSWT == null) { Debug.outNoStack("No UIFunctionsSWT on createStatusEntry"); return null; } MainStatusBar mainStatusBar = functionsSWT.getMainStatusBar(); if (mainStatusBar == null) { Debug.outNoStack("No MainStatusBar on createStatusEntry"); return null; } mainStatusBar.createStatusEntry(entry); return entry; } public boolean openView(BasicPluginViewModel model) { return openView(VIEW_MAIN, model.getName().replaceAll(" ", "."), null); } public void openConfig(final BasicPluginConfigModel model) { Utils.execSWTThread(new Runnable() { public void run() { uiFunctions.openView(UIFunctions.VIEW_CONFIG, model.getSection()); } }); } protected static class instanceWrapper implements UISWTInstance { private WeakReference pi_ref; private UISWTInstanceImpl delegate; protected instanceWrapper( PluginInterface _pi, UISWTInstanceImpl _delegate ) { pi_ref = new WeakReference(_pi ); delegate = _delegate; } public void detach() throws UIException { delegate.detach(); } public Display getDisplay() { return( delegate.getDisplay()); } public Image loadImage( String resource ) { PluginInterface pi = pi_ref.get(); if ( pi == null ){ return( null ); } return( delegate.loadImage( pi, resource )); } public UISWTGraphic createGraphic( Image img ) { return( delegate.createGraphic( img )); } public void addView(String sParentID, String sViewID, UISWTViewEventListener l) { delegate.addView( sParentID, sViewID, l ); } public void openMainView(String sViewID, UISWTViewEventListener l,Object dataSource) { delegate.openMainView( sViewID, l, dataSource ); } public void openMainView(String sViewID, UISWTViewEventListener l,Object dataSource, boolean setfocus) { delegate.openMainView( sViewID, l, dataSource, setfocus ); } public void removeViews(String sParentID, String sViewID) { delegate.removeViews(sParentID, sViewID ); } public UISWTView[] getOpenViews(String sParentID) { return( delegate.getOpenViews(sParentID)); } public void addView(UISWTPluginView view, boolean autoOpen) { delegate.addView( view, autoOpen ); } public void removeView(UISWTPluginView view) { delegate.removeView( view ); } public void addView(UISWTAWTPluginView view, boolean auto_open) { delegate.addView( view, auto_open ); } public void removeView(UISWTAWTPluginView view) { delegate.removeView( view ); } public int promptUser(String title, String text, String[] options, int defaultOption) { return delegate.promptUser(title, text, options, defaultOption); } public boolean openView(String sParentID, String sViewID, Object dataSource) { return delegate.openView(sParentID, sViewID, dataSource); } public boolean openView(String sParentID, String sViewID, Object dataSource, boolean setfocus) { return delegate.openView(sParentID, sViewID, dataSource, setfocus); } public UIInputReceiver getInputReceiver() { return delegate.getInputReceiver(); } public UIMessage createMessage() { return delegate.createMessage(); } public void showDownloadBar(Download download, boolean display) { delegate.showDownloadBar(download, display); } public void showTransfersBar(boolean display) { delegate.showTransfersBar(display); } public UISWTStatusEntry createStatusEntry() { return delegate.createStatusEntry(); } public boolean openView(BasicPluginViewModel model) { return delegate.openView(model); } public void openConfig(BasicPluginConfigModel model) { delegate.openConfig(model); } public Shell createShell(int style) { return delegate.createShell(style); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginViewImpl.java0000644000175000017500000003144611100165200026464 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Olivier Chalouhi * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.pluginsimpl; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.plugins.ui.components.UIPropertyChangeEvent; import org.gudy.azureus2.plugins.ui.components.UIPropertyChangeListener; import org.gudy.azureus2.plugins.ui.model.BasicPluginViewModel; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.components.BufferedLabel; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; /** * */ public class BasicPluginViewImpl implements UISWTViewEventListener, UIPropertyChangeListener { BasicPluginViewModel model; //GUI elements Display display; Composite panel; ProgressBar progress; BufferedLabel status; BufferedLabel task; StyledText log; Pattern inclusionFilter; Pattern exclusionFilter; boolean paused; boolean isCreated; public BasicPluginViewImpl( BasicPluginViewModel model) { this.model = model; isCreated = false; } public boolean eventOccurred(UISWTViewEvent event) { switch (event.getType()) { case UISWTViewEvent.TYPE_CREATE: if (isCreated) return false; isCreated = true; break; case UISWTViewEvent.TYPE_INITIALIZE: initialize((Composite)event.getData()); break; case UISWTViewEvent.TYPE_REFRESH: refresh(); break; case UISWTViewEvent.TYPE_DESTROY: delete(); isCreated = false; break; } return true; } private void initialize(Composite composite) { GridData gridData; GridLayout gridLayout; String sConfigSectionID = model.getConfigSectionID(); this.display = composite.getDisplay(); panel = new Composite(composite,SWT.NULL); gridLayout = new GridLayout(); gridLayout.numColumns = 2; panel.setLayout(gridLayout); gridData = new GridData(GridData.FILL_BOTH); panel.setLayoutData(gridData); /* * Status : [Status Text] * Current Task : [Task Text] * Progress : [||||||||||----------] * Log : * [ * * * ] */ Composite topSection = new Composite(panel, SWT.NONE); gridLayout = new GridLayout(); gridLayout.numColumns = 2; gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; topSection.setLayout(gridLayout); gridData = new GridData(GridData.FILL_HORIZONTAL); if (sConfigSectionID == null){ gridData.horizontalSpan = 2; } topSection.setLayoutData(gridData); if(model.getStatus().getVisible()) { Label statusTitle = new Label(topSection,SWT.NULL); Messages.setLanguageText(statusTitle,"plugins.basicview.status"); status = new BufferedLabel(topSection,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); status.setLayoutData(gridData); } if(model.getActivity().getVisible()) { Label activityTitle = new Label(topSection,SWT.NULL); Messages.setLanguageText(activityTitle,"plugins.basicview.activity"); task = new BufferedLabel(topSection,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); task.setLayoutData(gridData); } if(model.getProgress().getVisible()) { Label progressTitle = new Label(topSection,SWT.NULL); Messages.setLanguageText(progressTitle,"plugins.basicview.progress"); progress = new ProgressBar(topSection,SWT.NULL); progress.setMaximum(100); progress.setMinimum(0); gridData = new GridData(GridData.FILL_HORIZONTAL); progress.setLayoutData(gridData); } if (sConfigSectionID != null) { Composite configSection = new Composite(panel, SWT.NONE); gridLayout = new GridLayout(); gridLayout.numColumns = 1; gridLayout.marginHeight = 0; gridLayout.marginWidth = 2; configSection.setLayout(gridLayout); gridData = new GridData(GridData.END | GridData.VERTICAL_ALIGN_END ); configSection.setLayoutData(gridData); //Label padding = new Label(configSection,SWT.NULL); //gridData = new GridData(GridData.FILL_HORIZONTAL); //padding.setLayoutData(gridData); Button btnConfig = new Button(configSection, SWT.PUSH); Messages.setLanguageText(btnConfig, "plugins.basicview.config"); btnConfig.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_CONFIG, model.getConfigSectionID()); } } }); btnConfig.setLayoutData(new GridData()); } if(model.getLogArea().getVisible()) { Label logTitle = new Label(topSection,SWT.NULL); Messages.setLanguageText(logTitle,"plugins.basicview.log"); // gridData = new GridData(GridData.FILL_HORIZONTAL); // gridData.horizontalSpan = 1; // logTitle.setLayoutData(gridData); Button button = new Button( topSection, SWT.PUSH ); Messages.setLanguageText(button,"plugins.basicview.clear"); button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { model.getLogArea().setText(""); }}); log = new StyledText(panel,SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; log.setLayoutData(gridData); //String text = model.getLogArea().getText().trim(); //log.setText( text); //log.setTopIndex(log.getLineCount()); model.getLogArea().addPropertyChangeListener(this); Composite bottomSection = new Composite(panel, SWT.NONE); gridLayout = new GridLayout(); gridLayout.numColumns = 3; gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; bottomSection.setLayout(gridLayout); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; bottomSection.setLayoutData(gridData); // include Label label = new Label(bottomSection, SWT.NONE); label.setLayoutData(new GridData()); Messages.setLanguageText(label, "LoggerView.includeOnly"); final Text inclText = new Text(bottomSection, SWT.BORDER); gridData = new GridData(); gridData.widthHint = 200; inclText.setLayoutData(gridData); inclText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { String newExpression = inclText.getText(); if (newExpression.length() == 0) inclusionFilter = null; else { try { inclusionFilter = Pattern.compile(newExpression, Pattern.CASE_INSENSITIVE); inclText.setBackground(null); } catch (PatternSyntaxException e1) { inclText.setBackground(Colors.colorErrorBG); } } } }); label = new Label(bottomSection, SWT.NONE); // exclude label = new Label(bottomSection, SWT.NONE); label.setLayoutData(new GridData()); Messages.setLanguageText(label, "LoggerView.excludeAll"); final Text exclText = new Text(bottomSection, SWT.BORDER); gridData = new GridData(); gridData.widthHint = 200; exclText.setLayoutData(gridData); exclText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { String newExpression = exclText.getText(); if (newExpression.length() == 0) exclusionFilter = null; else { try { exclusionFilter = Pattern.compile(newExpression, Pattern.CASE_INSENSITIVE); exclText.setBackground(null); } catch (PatternSyntaxException e1) { exclText.setBackground(Colors.colorErrorBG); } } } }); label = new Label(bottomSection, SWT.NONE); // pause Button buttonPause = new Button(bottomSection, SWT.CHECK); Messages.setLanguageText(buttonPause, "LoggerView.pause"); gridData = new GridData(); buttonPause.setLayoutData(gridData); buttonPause.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (e.widget == null || !(e.widget instanceof Button)) return; Button btn = (Button) e.widget; paused = btn.getSelection(); } }); } composite.addListener( SWT.Hide, new Listener() { public void handleEvent( Event arg0 ) { log.setText(""); } }); composite.addListener( SWT.Show, new Listener() { public void handleEvent( Event arg0 ) { String text = model.getLogArea().getText().trim(); log.setText( text); log.setTopIndex(log.getLineCount()); } }); } private void refresh() { if(status != null) { status.setText(model.getStatus().getText()); } if(task != null) { task.setText(model.getActivity().getText()); } if(progress != null) { progress.setSelection(model.getProgress().getPercentageComplete()); } } public void propertyChanged(final UIPropertyChangeEvent ev) { if(ev.getSource() != model.getLogArea()) return; if(display == null || display.isDisposed() || log == null || paused) return; display.asyncExec(new AERunnable(){ public void runSupport() { if(log.isDisposed()) return; if ( !log.isVisible()){ return; } String old_value = (String)ev.getOldPropertyValue(); String new_value = (String) ev.getNewPropertyValue(); ScrollBar bar = log.getVerticalBar(); boolean max = bar.getSelection() == bar.getMaximum() - bar.getThumb(); int lineOffset = log.getLineCount() - log.getTopIndex(); if ( new_value.startsWith( old_value )){ String toAppend = new_value.substring(old_value.length()); if(toAppend.length() == 0) return; StringBuffer builder = new StringBuffer(toAppend.length()); String[] lines = toAppend.split("\n"); for( int i=0;i= 0 && default_choice < choices.length) { this.preentered_text = choices[default_choice]; } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTStatusEntryImpl.java0000644000175000017500000001427311272502252026605 0ustar adrianadrian/** * */ package org.gudy.azureus2.ui.swt.pluginsimpl; import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.pluginsimpl.local.ui.menus.MenuContextImpl; import org.gudy.azureus2.ui.common.util.MenuItemManager; import org.gudy.azureus2.ui.swt.MenuBuildUtils; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.MainStatusBar; import org.gudy.azureus2.ui.swt.plugins.UISWTStatusEntry; import org.gudy.azureus2.ui.swt.plugins.UISWTStatusEntryListener; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.ui.menus.MenuContext; import org.gudy.azureus2.plugins.ui.menus.MenuItem; /** * @author Allan Crooks * */ public class UISWTStatusEntryImpl implements UISWTStatusEntry, MainStatusBar.CLabelUpdater { private AEMonitor this_mon = new AEMonitor("UISWTStatusEntryImpl@" + Integer.toHexString(this.hashCode())); private UISWTStatusEntryListener listener = null; private MenuContextImpl menu_context = MenuContextImpl.create("status_entry"); // Used by "update". private boolean needs_update = false; private String text = null; private String tooltip = null; private boolean image_enabled = false; private Image image = null; private boolean is_visible = false; private boolean needs_disposing = false; private boolean is_destroyed = false; private Menu menu; private CopyOnWriteArrayList imageIDstoDispose = new CopyOnWriteArrayList(); private String imageID = null; private void checkDestroyed() { if (is_destroyed) {throw new RuntimeException("object is destroyed, cannot be reused");} } public MenuContext getMenuContext() { return this.menu_context; } public void update(CLabel label) { if (needs_disposing && !label.isDisposed()) { if (menu != null && !menu.isDisposed()) { menu.dispose(); menu = null; } label.dispose(); if (imageID != null) { imageIDstoDispose.add(imageID); } releaseOldImages(); return; } if (menu_context.is_dirty) {needs_update = true; menu_context.is_dirty = false;} if (!needs_update) {return;} // This is where we do a big update. try { this_mon.enter(); update0(label); } finally { this_mon.exit(); } } /** * * * @since 4.0.0.5 */ private void releaseOldImages() { if (imageIDstoDispose.size() > 0) { ImageLoader imageLoader = ImageLoader.getInstance(); for (Iterator iter = imageIDstoDispose.iterator(); iter.hasNext();) { String id = (String) iter.next(); imageLoader.releaseImage(id); iter.remove(); } } } private void update0(final CLabel label) { label.setText(text); label.setToolTipText(tooltip); label.setImage(image_enabled ? image : null); label.setVisible(this.is_visible); releaseOldImages(); MenuItem[] items = MenuItemManager.getInstance().getAllAsArray(menu_context.context); if (items.length > 0 & menu == null) { menu = new Menu(label); label.setMenu(menu); MenuBuildUtils.addMaintenanceListenerForMenu(menu, new MenuBuildUtils.MenuBuilder() { public void buildMenu(Menu menu, MenuEvent menuEvent) { MenuItem[] items = MenuItemManager.getInstance().getAllAsArray(menu_context.context); MenuBuildUtils.addPluginMenuItems(label, items, menu, true, true, MenuBuildUtils.BASIC_MENU_ITEM_CONTROLLER); } } ); } else if (menu != null && items.length == 0) { label.setMenu(null); if (!menu.isDisposed()) {menu.dispose();} this.menu = null; } this.needs_update = false; } void onClick() { UISWTStatusEntryListener listener0 = listener; // Avoid race conditions. if (listener0 != null) {listener.entryClicked(this);} } public void destroy() { try { this_mon.enter(); this.is_visible = false; this.listener = null; this.image = null; this.needs_disposing = true; this.is_destroyed = true; // Remove any existing menu items. MenuItemManager.getInstance().removeAllMenuItems(this.menu_context.context); } finally { this_mon.exit(); } } public void setImage(int image_id) { // we can't release the old image here because the label is still using it // Put it into a list until the label is updated with the new image, then // release the old if (imageID != null) { imageIDstoDispose.add(imageID); } switch (image_id) { case IMAGE_LED_GREEN: imageID = "greenled"; break; case IMAGE_LED_RED: imageID = "redled"; break; case IMAGE_LED_YELLOW: imageID = "yellowled"; break; default: imageID = "grayled"; break; } ImageLoader imageLoader = ImageLoader.getInstance(); this.setImage(imageLoader.getImage(imageID)); } public void setImage(Image image) { checkDestroyed(); this_mon.enter(); this.image = image; this.needs_update = true; this_mon.exit(); } public void setImageEnabled(boolean enabled) { checkDestroyed(); this_mon.enter(); this.image_enabled = enabled; this.needs_update = true; this_mon.exit(); } public void setListener(UISWTStatusEntryListener listener) { checkDestroyed(); this.listener = listener; } public void setText(String text) { checkDestroyed(); this_mon.enter(); this.text = text; this.needs_update = true; this_mon.exit(); } public void setTooltipText(String text) { checkDestroyed(); this_mon.enter(); this.tooltip = text; this.needs_update = true; this_mon.exit(); } public void setVisible(boolean visible) { checkDestroyed(); this_mon.enter(); this.is_visible = visible; this.needs_update = true; this_mon.exit(); } public void created(final CLabel label) { final Listener click_listener = new Listener() { public void handleEvent(Event e) { onClick(); } }; Utils.execSWTThread(new AERunnable() { public void runSupport() { label.addListener(SWT.MouseDoubleClick, click_listener); } }, true); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventImpl.java0000644000175000017500000000303410373051022026200 0ustar adrianadrian/* * File : UISWTViewEventImpl.java * Created : Oct 14, 2005 * By : TuxPaper * * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.pluginsimpl; import org.gudy.azureus2.ui.swt.plugins.UISWTView; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent; /** * @author TuxPaper * */ public class UISWTViewEventImpl implements UISWTViewEvent { int eventType; Object data; UISWTView view; public UISWTViewEventImpl(UISWTView view, int eventType, Object data) { this.view = view; this.eventType = eventType; this.data = data; } public int getType() { return eventType; } public Object getData() { return data; } public UISWTView getView() { return view; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventCancelledException.java0000644000175000017500000000313511042245250031034 0ustar adrianadrian/** * Created on Jul 20, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.pluginsimpl; /** * @author TuxPaper * @created Jul 20, 2008 * */ public class UISWTViewEventCancelledException extends Exception { /** * */ private static final long serialVersionUID = -1750725255042799344L; /** * */ public UISWTViewEventCancelledException() { super(); // TODO Auto-generated constructor stub } /** * @param message * @param cause */ public UISWTViewEventCancelledException(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } /** * @param message */ public UISWTViewEventCancelledException(String message) { super(message); // TODO Auto-generated constructor stub } /** * @param cause */ public UISWTViewEventCancelledException(Throwable cause) { super(cause); // TODO Auto-generated constructor stub } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTGraphicImpl.java0000644000175000017500000000351010752764076025665 0ustar adrianadrian/* * Created on 2004/May/23 * Created by TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.pluginsimpl; import org.eclipse.swt.graphics.Image; import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic; import org.gudy.azureus2.plugins.ui.SWT.GraphicSWT; import org.gudy.azureus2.plugins.ui.SWT.SWTManager; /** An SWT image to be used in Azureus * * @see SWTManager.createGraphic */ public class UISWTGraphicImpl implements UISWTGraphic, GraphicSWT // we *have* to implement GraphicsSWT as there are plugins // out there (e.g. ProgressBar) that assume that // Graphics returned to them are instances of GraphicsSWT { Image img; public UISWTGraphicImpl(Image newImage) { img = newImage; } public Image getImage() { if (img == null || img.isDisposed()) { return null; } return img; } public boolean setImage(Image newImage) { if (img == newImage) return false; img = newImage; return true; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginConfigImpl.java0000644000175000017500000004652411271677740027014 0ustar adrianadrian/* * Created on 28-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.pluginsimpl; /** * @author parg * */ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.ui.config.ActionParameter; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.plugins.ui.config.EnablerParameter; import org.gudy.azureus2.plugins.ui.config.ParameterListener; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.pluginsimpl.local.ui.config.*; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.components.LinkLabel; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.ui.swt.plugins.UISWTParameterContext; public class BasicPluginConfigImpl implements UISWTConfigSection { protected WeakReference model_ref; protected String parent_section; protected String section; public BasicPluginConfigImpl( WeakReference _model_ref ) { model_ref = _model_ref; BasicPluginConfigModel model = model_ref.get(); parent_section = model.getParentSection(); section = model.getSection(); } public String configSectionGetParentSection() { if ( parent_section == null || parent_section.length() == 0 ){ return( ConfigSection.SECTION_ROOT ); } return( parent_section ); } public String configSectionGetName() { return( section ); } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { BasicPluginConfigModel model = model_ref.get(); org.gudy.azureus2.plugins.ui.config.Parameter[] parameters = model.getParameters(); int max_mode = 0; for (int i=0;i max_mode ){ max_mode = param.getMinimumRequiredUserMode(); } } return( max_mode ); } public Composite configSectionCreate( final Composite parent ) { int userMode = COConfigurationManager.getIntParameter("User Mode"); // main tab set up Composite main_tab = new Composite(parent, SWT.NULL); GridData main_gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); main_tab.setLayoutData(main_gridData); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; main_tab.setLayout(layout); final Map comp_map = new HashMap(); ParameterGroupImpl current_group = null; Composite current_composite = main_tab; BasicPluginConfigModel model = model_ref.get(); org.gudy.azureus2.plugins.ui.config.Parameter[] parameters = model.getParameters(); for (int i=0;i userMode ){ continue; } ParameterGroupImpl pg = param.getGroup(); if ( pg == null ){ current_composite = main_tab; }else{ if ( pg != current_group ){ current_group = pg; current_composite = new Group(main_tab, SWT.NULL); Messages.setLanguageText(current_composite, current_group.getResourceName()); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan = 2; current_composite.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; current_composite.setLayout(layout); } } Label label = null; String label_key = param.getLabelKey(); String label_text = label_key==null?param.getLabelText():MessageText.getString( label_key ); // we can only use the check-box's label form for boolean params if the text // doesn't include formatting (it doesn't handle it) if ( label_text.indexOf('\n') != -1 || label_text.indexOf('\t') != -1 || !(param instanceof BooleanParameterImpl)) { String hyperlink = null; if (param instanceof HyperlinkParameterImpl) { hyperlink = ((HyperlinkParameterImpl)param).getHyperlink(); } label = new Label(current_composite, (param instanceof LabelParameterImpl) ? SWT.WRAP : SWT.NULL); if ( label_key == null ){ label.setText( param.getLabelText()); }else{ Messages.setLanguageText(label, label_key ); } if (hyperlink != null) { LinkLabel.makeLinkedLabel(label, hyperlink); } if (param instanceof HyperlinkParameterImpl) { final Label f_label = label; param.addListener( new ParameterListener() { public void parameterChanged( org.gudy.azureus2.plugins.ui.config.Parameter p ) { if ( f_label.isDisposed()){ param.removeListener( this ); }else{ final String hyperlink = ((HyperlinkParameterImpl)param).getHyperlink(); if (hyperlink != null) { Utils.execSWTThread( new Runnable() { public void run() { LinkLabel.updateLinkedLabel(f_label, hyperlink); } }); } } } }); } } String key = param.getKey(); //System.out.println( "key = " + key ); final Parameter swt_param; if ( param instanceof BooleanParameterImpl ){ if ( label == null ){ swt_param = new BooleanParameter(current_composite, key, ((BooleanParameterImpl) param).getDefaultValue(), param.getLabelKey()); }else{ swt_param = new BooleanParameter(current_composite, key, ((BooleanParameterImpl)param).getDefaultValue()); } GridData data = new GridData(); data.horizontalSpan = label==null?2:1; swt_param.setLayoutData(data); param.addListener( new ParameterListener() { public void parameterChanged( org.gudy.azureus2.plugins.ui.config.Parameter p ) { if ( swt_param.getControls()[0].isDisposed()){ param.removeListener( this ); }else{ ((BooleanParameter)swt_param).setSelected(((BooleanParameterImpl)param).getValue()); } } }); }else if ( param instanceof IntParameterImpl ){ IntParameterImpl int_param = (IntParameterImpl)param; swt_param = new IntParameter(current_composite, key, int_param.getDefaultValue()); if (int_param.isLimited()) { ((IntParameter)swt_param).setMinimumValue(int_param.getMinValue()); ((IntParameter)swt_param).setMaximumValue(int_param.getMaxValue()); } param.addListener( new ParameterListener() { public void parameterChanged( org.gudy.azureus2.plugins.ui.config.Parameter p ) { if ( swt_param.getControls()[0].isDisposed()){ param.removeListener( this ); }else{ ((IntParameter)swt_param).setValue(((IntParameterImpl)param).getValue()); } } }); GridData gridData = new GridData(); gridData.widthHint = 100; swt_param.setLayoutData( gridData ); }else if ( param instanceof ColorParameterImpl ) { final Composite area = new Composite(current_composite, SWT.NULL); //GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_HORIZONTAL ); GridData gridData = new GridData(); area.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; layout.marginWidth = 0; area.setLayout(layout); final ButtonParameter[] reset_button_holder = new ButtonParameter[1]; final ColorParameterImpl color_param = (ColorParameterImpl)param; swt_param = new org.gudy.azureus2.ui.swt.config.ColorParameter( area, key, color_param.getRedValue(), color_param.getGreenValue(), color_param.getBlueValue()) { public void newColorSet() { color_param.reloadParamDataFromConfig(true); if (reset_button_holder[0] == null) {return;} reset_button_holder[0].getControl().setEnabled(true); } }; // Reuse the same label as defined for Azureus UI reset buttons. reset_button_holder[0] = new ButtonParameter(area, "ConfigView.section.style.colorOverrides.reset"); reset_button_holder[0].getControl().setEnabled(color_param.isOverridden()); reset_button_holder[0].getControl().addListener(SWT.Selection, new Listener(){ public void handleEvent(Event event) { reset_button_holder[0].getControl().setEnabled(false); color_param.resetToDefault(); color_param.reloadParamDataFromConfig(false); } }); gridData = new GridData(); gridData.widthHint = 50; swt_param.setLayoutData( gridData ); }else if ( param instanceof StringParameterImpl ){ GridData gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.widthHint = 150; StringParameterImpl s_param = (StringParameterImpl)param; swt_param = new StringParameter(current_composite, key, s_param.getDefaultValue(), s_param.getGenerateIntermediateEvents()); swt_param.setLayoutData( gridData ); }else if ( param instanceof InfoParameterImpl ){ GridData gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.widthHint = 150; swt_param = new InfoParameter(current_composite, key, "" ); swt_param.setLayoutData( gridData ); }else if ( param instanceof StringListParameterImpl ){ StringListParameterImpl sl_param = (StringListParameterImpl)param; GridData gridData = new GridData(); gridData.widthHint = 150; swt_param = new StringListParameter(current_composite, key, sl_param.getDefaultValue(), sl_param.getLabels(), sl_param.getValues()); swt_param.setLayoutData( gridData ); }else if ( param instanceof PasswordParameterImpl ){ GridData gridData = new GridData(); gridData.widthHint = 150; swt_param = new PasswordParameter(current_composite, key, ((PasswordParameterImpl)param).getEncodingType()); swt_param.setLayoutData( gridData ); }else if ( param instanceof DirectoryParameterImpl || param instanceof org.gudy.azureus2.pluginsimpl.local.ui.config.FileParameter){ Composite area = new Composite(current_composite, SWT.NULL); GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_HORIZONTAL ); area.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; layout.marginWidth = 0; area.setLayout(layout); if (param instanceof DirectoryParameterImpl) { swt_param = new DirectoryParameter(area, key, ((DirectoryParameterImpl)param).getDefaultValue()); } else { org.gudy.azureus2.pluginsimpl.local.ui.config.FileParameter fp = (org.gudy.azureus2.pluginsimpl.local.ui.config.FileParameter)param; swt_param = new org.gudy.azureus2.ui.swt.config.FileParameter(area, key, fp.getDefaultValue(), fp.getFileExtensions()); } }else if ( param instanceof ActionParameterImpl ){ ActionParameterImpl _param = (ActionParameterImpl)param; if ( _param.getStyle() == ActionParameter.STYLE_BUTTON ){ swt_param = new ButtonParameter( current_composite, _param.getActionResource()); }else{ swt_param = new LinkParameter( current_composite, _param.getActionResource()); } swt_param.addChangeListener( new ParameterChangeAdapter() { public void parameterChanged( Parameter p, boolean caused_internally ) { try { param.parameterChanged( "" ); } catch (Throwable t) { Debug.out(t); } } }); } else if ( param instanceof UIParameterImpl) { if (((UIParameterImpl)param).getContext() instanceof UISWTParameterContext) { UISWTParameterContext context = (UISWTParameterContext)((UIParameterImpl)param).getContext(); Composite internal_composite = new Composite(current_composite, SWT.NULL); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); internal_composite.setLayoutData(gridData); boolean initialised_component = true; try {context.create(internal_composite);} catch (Exception e) {Debug.printStackTrace(e); initialised_component = false;} if (initialised_component) { swt_param = new UISWTParameter(internal_composite, param.getKey()); } else { swt_param = null; // We're only expecting this for plugins which screw up their component generation, // so we don't care that this text is not localised. if (label != null) {label.setText("Error while generating UI component.");} } } else { swt_param = null; } }else{ // label GridData gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; // for wrap to work gridData.widthHint = 300; label.setLayoutData( gridData ); swt_param = null; } if ( swt_param == null ){ if ( label == null ){ comp_map.put( param, new Object[]{ null }); }else{ comp_map.put( param, new Object[]{ null, label }); } }else{ Control[] c = swt_param.getControls(); Object[] moo = new Object[c.length+(label==null?1:2)]; int pos = 1; moo[0] = swt_param; if ( label != null){ moo[pos++] = label; } for (int j=0;j 0 ){ IAdditionalActionPerformer ap = new DualChangeSelectionActionPerformer( (Control[]) controlsToEnable.toArray(ce), (Control[]) controlsToDisable.toArray(cd)); BooleanParameter target = (BooleanParameter)((Object[])comp_map.get(param))[0]; target.setAdditionalActionPerformer(ap); } } } return( main_tab ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/SimpleTextEntryWindow.java0000644000175000017500000002306511267524616024602 0ustar adrianadrian/* * Created on 16 July 2006 * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.ui.UIInputValidator; import org.gudy.azureus2.ui.swt.components.ControlUtils; import org.gudy.azureus2.ui.swt.pluginsimpl.AbstractUISWTInputReceiver; /** * @author amc1 * Based on CategoryAdderWindow. */ public class SimpleTextEntryWindow extends AbstractUISWTInputReceiver { private Display display; private Shell shell; public SimpleTextEntryWindow() { } public SimpleTextEntryWindow(String sTitleKey, String sLabelKey) { setTitle(sTitleKey); setMessage(sLabelKey); } public SimpleTextEntryWindow(String sTitleKey, String sLabelKey, boolean bMultiLine) { setTitle(sTitleKey); setMessage(sLabelKey); setMultiLine(bMultiLine); } public void initTexts(String sTitleKey, String[] p0, String sLabelKey, String[] p1) { setLocalisedTitle(MessageText.getString(sTitleKey, p0)); setLocalisedMessage(MessageText.getString(sLabelKey, p1)); } protected void promptForInput() { Utils.execSWTThread(new Runnable() { public void run() { promptForInput0(); if (receiver_listener == null) { while (shell != null && !shell.isDisposed()) if (!display.readAndDispatch()) display.sleep(); } } }, receiver_listener != null); } private void promptForInput0() { //shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(Utils.findAnyShell(), SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); // link to active shell, so that when it closes, the input box closes (good for config windows) Shell parent = Display.getDefault().getActiveShell(); if (parent == null) { parent = Utils.findAnyShell(); } shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(parent, SWT.DIALOG_TRIM); display = shell.getDisplay(); if (this.title != null) { shell.setText(this.title); } Utils.setShellIcon(shell); GridLayout layout = new GridLayout(); shell.setLayout(layout); // Default width hint is 330. int width_hint = (this.width_hint == -1) ? 330 : this.width_hint; // Process any messages. Label label = null; GridData gridData = null; for (int i=0; i 512) { alert_history.remove(0); } } } finally { alert_history_mon.exit(); } if (alert.err == null) { if (alert.entryType == LogAlert.AT_INFORMATION) { showCommentMessageBox(alert.relatedTo, alert.text, alert.timeoutSecs ); } else if (alert.entryType == LogAlert.AT_WARNING) { showWarningMessageBox(alert.relatedTo, alert.text, alert.timeoutSecs ); } else { showErrorMessageBox(alert.relatedTo, alert.text, alert.timeoutSecs ); } } else { showErrorMessageBox(alert.relatedTo, alert.text, alert.err, alert.timeoutSecs ); } } public static void initComplete() { new AEThread2("Init Complete",true) { public void run() { try { alert_queue_mon.enter(); initialisation_complete = true; for (int i = 0; i < alert_queue.size(); i++) { LogAlert alert = (LogAlert) alert_queue.get(i); showAlert(alert); } List close_alerts = COConfigurationManager.getListParameter( "Alerts.raised.at.close", new ArrayList()); if (close_alerts.size() > 0) { COConfigurationManager.setParameter("Alerts.raised.at.close", new ArrayList()); String intro = MessageText.getString("alert.raised.at.close") + "\n"; for (int i = 0; i < close_alerts.size(); i++) { try { Map alert_map = (Map) close_alerts.get(i); byte[] details = (byte[]) alert_map.get("details"); Long l_timeout = (Long)alert_map.get( "timeout" ); int timeout = l_timeout==null?-1:l_timeout.intValue(); showMessageBox( null, ((Long) alert_map.get("type")).intValue(), new String((byte[]) alert_map.get("title")), intro + new String((byte[]) alert_map.get("message")), details == null ? null : new String(details), timeout); } catch (Throwable e) { Debug.printStackTrace(e); } } } alert_queue.clear(); } finally { alert_queue_mon.exit(); } } }.start(); } public static void stopInitiated() { stopping = true; } public static void init() { Logger.addListener(new ILogAlertListener() { /* (non-Javadoc) * @see org.gudy.azureus2.core3.logging.ILogAlertListener#alertRaised(org.gudy.azureus2.core3.logging.LogAlert) */ public void alertRaised(LogAlert alert) { if (!initialisation_complete) { try { alert_queue_mon.enter(); alert_queue.add(alert); } finally { alert_queue_mon.exit(); } return; } showAlert(alert); } }); } public static void addListener(AlertListener l) { listeners .add(l); } public static interface AlertListener { public boolean allowPopup(Object[] relatedObjects, int configID); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/ITwistieListener.java0000644000175000017500000000060510717253046023527 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt; /** * A convenience listener that will be notified whenever the control changes state between being * collapse and being expanded * @author knguyen * */ public interface ITwistieListener { /** * true is the control is in a collapsed state; false otherwise * @param value */ public void isCollapsed(boolean value); }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/UIExitUtilsSWT.java0000644000175000017500000001523211267524616023055 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; /** * @author TuxPaper * @created Nov 6, 2006 * */ public class UIExitUtilsSWT { private static boolean skipCloseCheck = false; private static CopyOnWriteList listeners = new CopyOnWriteList(); public static void addListener( canCloseListener l ) { listeners.add( l ); } public static void setSkipCloseCheck(boolean b) { skipCloseCheck = b; } /** * @return */ public static boolean canClose(GlobalManager globalManager, boolean bForRestart) { if (skipCloseCheck) { return true; } Shell mainShell = UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell(); if (mainShell != null && (!mainShell.isVisible() || mainShell.getMinimized()) && COConfigurationManager.getBooleanParameter("Password enabled")) { if (!PasswordWindow.showPasswordWindow(Display.getCurrent())) { return false; } } if (COConfigurationManager.getBooleanParameter("confirmationOnExit")) { if (!getExitConfirmation(bForRestart)) { return false; } } for ( canCloseListener listener: listeners ){ if ( !listener.canClose()){ return( false ); } } if (globalManager != null) { ArrayList listUnfinished = new ArrayList(); Object[] dms = globalManager.getDownloadManagers().toArray(); for (int i = 0; i < dms.length; i++) { DownloadManager dm = (DownloadManager) dms[i]; if (dm.getState() == DownloadManager.STATE_SEEDING && dm.getDownloadState().isOurContent() && dm.getStats().getAvailability() < 2) { TRTrackerScraperResponse scrape = dm.getTrackerScrapeResponse(); int numSeeds = scrape.getSeeds(); long seedingStartedOn = dm.getStats().getTimeStartedSeeding(); if ((numSeeds > 0) && (seedingStartedOn > 0) && (scrape.getScrapeStartTime() > seedingStartedOn)) numSeeds--; if (numSeeds == 0) { listUnfinished.add(dm); } } } if (listUnfinished.size() > 0) { boolean allowQuit; final List flistUnfinished = listUnfinished; if (listUnfinished.size() == 1) { allowQuit = Utils.execSWTThreadWithBool("quitSeeding", new AERunnableBoolean() { public boolean runSupport() { String title = MessageText.getString("Content.alert.notuploaded.title"); String text = MessageText.getString( "Content.alert.notuploaded.text", new String[] { ((DownloadManager) flistUnfinished.get(0)).getDisplayName(), MessageText.getString("Content.alert.notuploaded.quit") }); MessageBoxShell mb = new MessageBoxShell( title, text, new String[] { MessageText.getString("UpdateWindow.quit"), MessageText.getString("Content.alert.notuploaded.button.abort") }, 1); mb.setRelatedObject(((DownloadManager) flistUnfinished.get(0))); mb.open(null); return mb.waitUntilClosed() == 0; } }, 0); } else { allowQuit = Utils.execSWTThreadWithBool("quitSeeding", new AERunnableBoolean() { public boolean runSupport() { String sList = ""; for (int i = 0; i < flistUnfinished.size() && i < 5; i++) { DownloadManager dm = ((DownloadManager) flistUnfinished.get(i)); if (sList != "") { sList += "\n"; } sList += dm.getDisplayName(); } String title = MessageText.getString("Content.alert.notuploaded.multi.title"); String text = MessageText.getString( "Content.alert.notuploaded.multi.text", new String[] { "" + flistUnfinished.size(), MessageText.getString("Content.alert.notuploaded.quit"), sList }); MessageBoxShell mb = new MessageBoxShell( title, text, new String[] { MessageText.getString("UpdateWindow.quit"), MessageText.getString("Content.alert.notuploaded.button.abort") }, 1); mb.open(null); return mb.waitUntilClosed() == 0; } }, 0); } return allowQuit; } } return true; } /** * @return true, if the user choosed OK in the exit dialog * * @author Rene Leonhardt */ private static boolean getExitConfirmation(boolean for_restart) { MessageBoxShell mb = new MessageBoxShell(SWT.ICON_WARNING | SWT.YES | SWT.NO, for_restart ? "MainWindow.dialog.restartconfirmation" : "MainWindow.dialog.exitconfirmation", (String[]) null); mb.open(null); return mb.waitUntilClosed() == SWT.YES; } public static void uiShutdown() { // problem with closing down web start as AWT threads don't close properly if (SystemProperties.isJavaWebStartInstance()) { Thread close = new AEThread("JWS Force Terminate") { public void runSupport() { try { Thread.sleep(2500); } catch (Throwable e) { Debug.printStackTrace(e); } SESecurityManager.exitVM(1); } }; close.setDaemon(true); close.start(); } } public interface canCloseListener { public boolean canClose(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/donations/0000755000175000017500000000000011310377636021414 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/donations/DonationWindow.java0000644000175000017500000002362411273703072025224 0ustar adrianadrian/** * Created on Feb 9, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.donations; import java.util.Locale; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.stats.transfer.OverallStats; import org.gudy.azureus2.core3.stats.transfer.StatsFactory; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.security.CryptoManagerFactory; /** * @author TuxPaper * @created Feb 9, 2009 * */ public class DonationWindow { public static boolean DEBUG = System.getProperty("donations.debug", "0").equals( "1"); private static int reAskEveryHours = 96; private static int initialAskHours = 48; private static boolean pageLoadedOk = false; private static Shell shell = null; private static Browser browser; public static void checkForDonationPopup() { if (shell != null) { if (DEBUG) { new MessageBoxShell(SWT.OK, "Donations Test", "Already Open").open(null); } return; } //Check if user has already donated first boolean alreadyDonated = COConfigurationManager.getBooleanParameter( "donations.donated", false); if (alreadyDonated) { if (DEBUG) { new MessageBoxShell(SWT.OK, "Donations Test", "Already Donated! I like you.").open(null); } return; } OverallStats stats = StatsFactory.getStats(); if (stats == null) { return; } long upTime = stats.getTotalUpTime(); int hours = (int) (upTime / (60 * 60)); //secs * mins //Ask every DONATIONS_ASK_AFTER hours. int nextAsk = COConfigurationManager.getIntParameter( "donations.nextAskHours", 0); if (nextAsk == 0) { // First Time COConfigurationManager.setParameter("donations.nextAskHours", hours + initialAskHours); COConfigurationManager.save(); if (DEBUG) { new MessageBoxShell(SWT.OK, "Donations Test", "Newbie. You're active for " + hours + ".").open(null); } return; } if (hours < nextAsk) { if (DEBUG) { new MessageBoxShell(SWT.OK, "Donations Test", "Wait " + (nextAsk - hours) + ".").open(null); } return; } long minDate = COConfigurationManager.getLongParameter("donations.minDate", 0); if (minDate > 0 && minDate > SystemTime.getCurrentTime()) { if (DEBUG) { new MessageBoxShell(SWT.OK, "Donation Test", "Wait " + ((SystemTime.getCurrentTime() - minDate) / 1000 / 3600 / 24) + " days").open(null); } return; } COConfigurationManager.setParameter("donations.nextAskHours", hours + reAskEveryHours); COConfigurationManager.save(); Utils.execSWTThread(new AERunnable() { public void runSupport() { open(false, "check"); } }); } public static void open(final boolean showNoLoad, final String sourceRef) { Utils.execSWTThread(new AERunnable() { public void runSupport() { _open(showNoLoad, sourceRef); } }); } public static void _open(final boolean showNoLoad, final String sourceRef) { if (shell != null && !shell.isDisposed()) { return; } final Shell parentShell = Utils.findAnyShell(); shell = ShellFactory.createShell(parentShell, SWT.BORDER | SWT.APPLICATION_MODAL | SWT.TITLE); shell.setLayout(new FillLayout()); if (parentShell != null) { parentShell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); } shell.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { e.doit = false; } } }); shell.addShellListener(new ShellAdapter() { public void shellClosed(ShellEvent e) { e.doit = false; } }); shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (parentShell != null) { parentShell.setCursor(e.display.getSystemCursor(SWT.CURSOR_ARROW)); } shell = null; } }); browser = Utils.createSafeBrowser(shell, SWT.NONE); if (browser == null) { shell.dispose(); return; } browser.addTitleListener(new TitleListener() { public void changed(TitleEvent event) { if (shell == null || shell.isDisposed()) { return; } shell.setText(event.title); } }); browser.addStatusTextListener(new StatusTextListener() { String last = null; public void changed(StatusTextEvent event) { if (shell == null || shell.isDisposed()) { return; } String text = event.text.toLowerCase(); if (last != null && last.equals(text)) { return; } last = text; if (text.contains("page-loaded")) { pageLoadedOk = true; COConfigurationManager.setParameter("donations.count", COConfigurationManager.getLongParameter("donations.count", 1) + 1); Utils.centreWindow(shell); if (parentShell != null) { parentShell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_ARROW)); } shell.open(); } else if (text.contains("reset-ask-time")) { int time = reAskEveryHours; String[] strings = text.split(" "); if (strings.length > 1) { try { time = Integer.parseInt(strings[1]); } catch (Throwable t) { } } resetAskTime(time); } else if (text.contains("never-ask-again")) { neverAskAgain(); } else if (text.contains("close")) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { shell.dispose(); } }); } else if (text.startsWith("open-url")) { String url = event.text.substring(9); Utils.launch(url); } else if (text.startsWith("set-size")) { String[] strings = text.split(" "); if (strings.length > 2) { try { int w = Integer.parseInt(strings[1]); int h = Integer.parseInt(strings[2]); Rectangle computeTrim = shell.computeTrim(0, 0, w, h); shell.setSize(computeTrim.width, computeTrim.height); } catch (Exception e) { } } } } }); browser.addLocationListener(new LocationListener() { public void changing(LocationEvent event) { } public void changed(LocationEvent event) { } }); long upTime = StatsFactory.getStats().getTotalUpTime(); int upHours = (int) (upTime / (60 * 60)); //secs * mins String azid = Base32.encode(CryptoManagerFactory.getSingleton().getSecureID()); final String url = "http://" + System.getProperty("platform_address", "www.vuze.com") + ":" + System.getProperty("platform_port", "80") + "/" + "donate.start?locale=" + Locale.getDefault().toString() + "&azv=" + Constants.AZUREUS_VERSION + "&count=" + COConfigurationManager.getLongParameter("donations.count", 1) + "&uphours=" + upHours + "&azid=" + azid + "&sourceref=" + UrlUtils.encode(sourceRef); SimpleTimer.addEvent("donation.pageload", SystemTime.getOffsetTime(6000), new TimerEventPerformer() { public void perform(TimerEvent event) { if (!pageLoadedOk) { Utils.execSWTThread(new AERunnable() { public void runSupport() { Debug.out("Page Didn't Load:" + url); shell.dispose(); if (showNoLoad) { new MessageBoxShell(SWT.OK, MessageText.getString("DonationWindow.noload.title"), MessageText.getString("DonationWindow.noload.text", new String[] { url })).open(null); } } }); } } }); browser.setUrl(url); } /** * * * @since 4.0.0.5 */ protected static void neverAskAgain() { COConfigurationManager.setParameter("donations.donated", true); COConfigurationManager.save(); } /** * * * @since 4.0.0.5 */ public static void resetAskTime() { resetAskTime(reAskEveryHours); } public static void resetAskTime(int askEveryHours) { long upTime = StatsFactory.getStats().getTotalUpTime(); int hours = (int) (upTime / (60 * 60)); //secs * mins int nextAsk = hours + askEveryHours; COConfigurationManager.setParameter("donations.nextAskHours", nextAsk); COConfigurationManager.setParameter("donations.lastVersion", Constants.AZUREUS_VERSION); COConfigurationManager.save(); } public static void updateMinDate() { COConfigurationManager.setParameter("donations.minDate", SystemTime.getOffsetTime(1000l * 3600 * 24 * 30)); COConfigurationManager.save(); } public static void setMinDate(long timestamp) { COConfigurationManager.setParameter("donations.minDate", timestamp); COConfigurationManager.save(); } public static int getInitialAskHours() { return initialAskHours; } public static void setInitialAskHours(int i) { initialAskHours = i; } public static void main(String[] args) { try { AzureusCoreFactory.create().start(); //checkForDonationPopup(); open(true, "test"); } catch (Exception e) { e.printStackTrace(); } Display d = Display.getDefault(); while (true) { if (!d.readAndDispatch()) { d.sleep(); } } } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/osx/0000755000175000017500000000000011310377636020227 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/osx/CocoaUIEnhancer.java0000644000175000017500000006370211300740364024017 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.osx; import java.lang.reflect.*; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.internal.C; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.wizard.ConfigureWizard; import org.gudy.azureus2.ui.swt.help.AboutWindow; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.nat.NatTestWindow; import org.gudy.azureus2.ui.swt.speedtest.SpeedTestWizard; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; /** * You can exclude this file (or this whole path) for non OSX builds * * Hook some Cocoa specific abilities: * - App->About
* - App->Preferences
* - App->Exit
*
* - OpenDocument (possible limited to only files?)
* * This code was influenced by the * * CocoaUIEnhancer, which was influenced by the * * CarbonUIEnhancer from Agynami. * * Both cocoa implementations are modified from * * org.eclipse.ui.internal.cocoa.CocoaUIEnhancer */ public class CocoaUIEnhancer { private static final boolean DEBUG = false; private static Object /*Callback*/ callBack3; private static long callBack3Addr; private static Object /*Callback*/ callBack4; private static long callBack4Addr; private static CocoaUIEnhancer instance; private static final int kAboutMenuItem = 0; private static final int kPreferencesMenuItem = 2; private static final int kServicesMenuItem = 4; // private static final int kHideApplicationMenuItem = 6; // private static final int kQuitMenuItem = 10; //private static int NSWindowCloseButton = 0; //private static int NSWindowDocumentIconButton = 4; //private static int NSWindowMiniaturizeButton = 1; private static int NSWindowToolbarButton = 3; //private static int NSWindowZoomButton = 2; private static long sel_aboutMenuItemSelected_; private static long sel_application_openFile_; private static long sel_application_openFiles_; private static long sel_preferencesMenuItemSelected_; private static long sel_applicationShouldHandleReopen_; private static long sel_toolbarButtonClicked_; private static long sel_restartMenuSelected_; private static long sel_wizardMenuSelected_; private static long sel_natMenuSelected_; private static long sel_speedMenuSelected_; static final byte[] SWT_OBJECT = { 'S', 'W', 'T', '_', 'O', 'B', 'J', 'E', 'C', 'T', '\0' }; private long delegateIdSWTApplication; private long delegateJniRef; private Object delegate; private static Class osCls = classForName("org.eclipse.swt.internal.cocoa.OS"); private static Class nsmenuCls = classForName("org.eclipse.swt.internal.cocoa.NSMenu"); private static Class nsmenuitemCls = classForName("org.eclipse.swt.internal.cocoa.NSMenuItem"); private static Class nsapplicationCls = classForName("org.eclipse.swt.internal.cocoa.NSApplication"); private static Class nsarrayCls = classForName("org.eclipse.swt.internal.cocoa.NSArray"); private static Class nsstringCls = classForName("org.eclipse.swt.internal.cocoa.NSString"); private static Class swtmenuitemCls = classForName("org.eclipse.swt.internal.cocoa.SWTMenuItem"); private static Class nsidCls = classForName("org.eclipse.swt.internal.cocoa.id"); private static Class nsautoreleasepoolCls = classForName("org.eclipse.swt.internal.cocoa.NSAutoreleasePool"); private static Class nsworkspaceCls = classForName("org.eclipse.swt.internal.cocoa.NSWorkspace"); private static Class nsimageCls = classForName("org.eclipse.swt.internal.cocoa.NSImage"); private static Class nssizeCls = classForName("org.eclipse.swt.internal.cocoa.NSSize"); static { Class clazz = CocoaUIEnhancer.class; Class callbackCls = classForName("org.eclipse.swt.internal.Callback"); try { Method mGetAddress = callbackCls.getMethod("getAddress", new Class[0]); Constructor consCallback = callbackCls.getConstructor(new Class[] { Object.class, String.class, int.class }); //callBack3 = new Callback(clazz, "actionProc", 3); callBack3 = consCallback.newInstance(new Object[] { clazz, "actionProc", 3 }); Object object = mGetAddress.invoke(callBack3, (Object[]) null); callBack3Addr = convertToLong(object); if (callBack3Addr == 0) { SWT.error(SWT.ERROR_NO_MORE_CALLBACKS); } //callBack4 = new Callback(clazz, "actionProc", 4); callBack4 = consCallback.newInstance(new Object[] { clazz, "actionProc", 4 }); object = mGetAddress.invoke(callBack4, (Object[]) null); callBack4Addr = convertToLong(object); if (callBack4Addr == 0) { SWT.error(SWT.ERROR_NO_MORE_CALLBACKS); } } catch (Throwable e) { Debug.out(e); } } static int actionProc(int id, int sel, int arg0) { if (DEBUG) { System.err.println("id=" + id + ";sel=" + sel); } if (sel == sel_aboutMenuItemSelected_) { AboutWindow.show(); } else if (sel == sel_restartMenuSelected_) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.dispose(true, false); } } else if (sel == sel_wizardMenuSelected_) { new ConfigureWizard(false); } else if (sel == sel_natMenuSelected_) { new NatTestWindow(); } else if (sel == sel_speedMenuSelected_) { new SpeedTestWizard(); } else if (sel == sel_toolbarButtonClicked_) { try { Field fldsel_window = osCls.getField("sel_window"); Object windowId = invoke(osCls, "objc_msgSend", new Object[] { wrapPointer(arg0), fldsel_window.get(null) }); final Shell shellAffected = (Shell) invoke(Display.class, Display.getCurrent(), "findWidget", new Object[] { windowId }); Utils.execSWTThread(new AERunnable() { public void runSupport() { int type; Long l = (Long) shellAffected.getData("OSX.ToolBarToggle"); if (l == null || l.longValue() == 0) { type = SWT.Collapse; } else { type = SWT.Expand; } Event event = new Event(); event.type = type; event.display = shellAffected.getDisplay(); event.widget = shellAffected; shellAffected.notifyListeners(type, event); shellAffected.setData("OSX.ToolBarToggle", new Long( type == SWT.Collapse ? 1 : 0)); } }); } catch (Throwable t) { Debug.out(t); } } else if (sel == sel_preferencesMenuItemSelected_) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_CONFIG, null); } } return 0; } static int /*long*/actionProc(int /*long*/id, int /*long*/sel, int /*long*/arg0, int /*long*/arg1) throws Throwable { if (DEBUG) { System.err.println("actionProc 4 " + id + "/" + sel); } Display display = Display.getCurrent(); if (display == null) return 0; if (sel == sel_application_openFile_) { Constructor conNSString = nsstringCls.getConstructor(new Class[] { int.class }); Object file = conNSString.newInstance(arg1); String fileString = (String) invoke(file, "getString"); if (DEBUG) { System.err.println("OMG GOT OpenFile " + fileString); } fileOpen(new String[] { fileString }); } else if (sel == sel_application_openFiles_) { Constructor conNSArray = nsarrayCls.getConstructor(new Class[] { int.class }); Constructor conNSString = nsstringCls.getConstructor(new Class[] { nsidCls }); Object arrayOfFiles = conNSArray.newInstance(arg1); int count = ((Number) invoke(arrayOfFiles, "count")).intValue(); String[] files = new String[count]; for (int i = 0; i < count; i++) { Object fieldId = invoke(nsarrayCls, arrayOfFiles, "objectAtIndex", new Object[] { i }); Object nsstring = conNSString.newInstance(fieldId); files[i] = (String) invoke(nsstring, "getString"); if (DEBUG) { System.err.println("OMG GOT OpenFiles " + files[i]); } } fileOpen(files); } else if (sel == sel_applicationShouldHandleReopen_) { Event event = new Event (); event.detail = 1; if (display != null) { invoke(Display.class, display, "sendEvent", new Class[] { int.class, Event.class }, new Object[] { SWT.Activate, event }); } } return 0; } private static Class classForName(String classname) { try { Class cls = Class.forName(classname); return cls; } catch (ClassNotFoundException e) { throw new IllegalStateException(e); } } private static long convertToLong(Object object) { if (object instanceof Integer) { Integer i = (Integer) object; return i.longValue(); } if (object instanceof Long) { Long l = (Long) object; return l.longValue(); } return 0; } protected static void fileOpen(final String[] files) { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { TorrentOpener.openTorrents(files); } }); } public static CocoaUIEnhancer getInstance() { if (instance == null) { try { instance = new CocoaUIEnhancer(); } catch (Throwable e) { Debug.out(e); } } return instance; } private static Object invoke(Class clazz, Object target, String methodName, Object[] args) { try { Class[] signature = new Class[args.length]; for (int i = 0; i < args.length; i++) { Class thisClass = args[i].getClass(); if (thisClass == Integer.class) signature[i] = int.class; else if (thisClass == Long.class) signature[i] = long.class; else if (thisClass == Byte.class) signature[i] = byte.class; else if (thisClass == Boolean.class) signature[i] = boolean.class; else signature[i] = thisClass; } Method method = clazz.getMethod(methodName, signature); return method.invoke(target, args); } catch (Exception e) { throw new IllegalStateException(e); } } private static Object invoke(Class clazz, Object target, String methodName, Class[] signature, Object[] args) { try { Method method = clazz.getDeclaredMethod(methodName, signature); method.setAccessible(true); return method.invoke(target, args); } catch (Exception e) { throw new IllegalStateException(e); } } private static Object invoke(Class clazz, String methodName, Object[] args) { return invoke(clazz, null, methodName, args); } private static Object invoke(Object obj, String methodName) { return invoke(obj, methodName, (Class[]) null, (Object[]) null); } private static Object invoke(Object obj, String methodName, Class[] paramTypes, Object... arguments) { try { Method m = obj.getClass().getMethod(methodName, paramTypes); return m.invoke(obj, arguments); } catch (Exception e) { throw new IllegalStateException(e); } } private static long registerName(Class osCls, String name) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { Object object = invoke(osCls, "sel_registerName", new Object[] { name }); return convertToLong(object); } //////////////////////////////////////////////////////////// private static Object wrapPointer(long value) { Class PTR_CLASS = C.PTR_SIZEOF == 8 ? long.class : int.class; if (PTR_CLASS == long.class) return new Long(value); else return new Integer((int) value); } private CocoaUIEnhancer() throws Throwable { // Instead of creating a new delegate class in objective-c, // just use the current SWTApplicationDelegate. An instance of this // is a field of the Cocoa Display object and is already the target // for the menuItems. So just get this class and add the new methods // to it. Object delegateObjSWTApplication = invoke(osCls, "objc_lookUpClass", new Object[] { "SWTApplicationDelegate" }); delegateIdSWTApplication = convertToLong(delegateObjSWTApplication); // This doesn't feel right, but it works Class swtapplicationdelegateCls = classForName("org.eclipse.swt.internal.cocoa.SWTApplicationDelegate"); delegate = swtapplicationdelegateCls.newInstance(); Object delegateAlloc = invoke(delegate, "alloc"); invoke(delegateAlloc, "init"); Object delegateIdObj = nsidCls.getField("id").get(delegate); delegateJniRef = ((Number) invoke(osCls, "NewGlobalRef", new Class[] { Object.class }, new Object[] { CocoaUIEnhancer.this })).longValue(); if (delegateJniRef == 0) SWT.error(SWT.ERROR_NO_HANDLES); //OS.object_setInstanceVariable(delegate.id, SWT_OBJECT, delegateJniRef); invoke(osCls, "object_setInstanceVariable", new Object[] { delegateIdObj, SWT_OBJECT, wrapPointer(delegateJniRef) }); } /** * Hook the given Listener to the Mac OS X application Quit menu and the IActions to the About * and Preferences menus. * * @param display * The Display to use. * @param quitListener * The listener to invoke when the Quit menu is invoked. * @param aboutAction * The action to run when the About menu is invoked. * @param preferencesAction * The action to run when the Preferences menu is invoked. */ public void hookApplicationMenu() { Display display = Display.getCurrent(); try { // Initialize the menuItems. initialize(); } catch (Exception e) { throw new IllegalStateException(e); } // Schedule disposal of callback object display.disposeExec(new Runnable() { public void run() { invoke(callBack3, "dispose"); callBack3 = null; invoke(callBack4, "dispose"); callBack4 = null; if (delegateJniRef != 0) { //OS.DeleteGlobalRef(delegateJniRef); invoke(osCls, "DeleteGlobalRef", new Object[] { wrapPointer(delegateJniRef) }); delegateJniRef = 0; } if (delegate != null) { invoke(delegate, "release"); delegate = null; } } }); } public void hookDocumentOpen() throws Throwable { if (sel_application_openFile_ == 0) { sel_application_openFile_ = registerName(osCls, "application:openFile:"); } invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_application_openFile_), wrapPointer(callBack4Addr), "@:@:@" }); if (sel_application_openFiles_ == 0) { sel_application_openFiles_ = registerName(osCls, "application:openFiles:"); } invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_application_openFiles_), wrapPointer(callBack4Addr), "@:@:@" }); } private void initialize() throws Exception { // Register names in objective-c. if (sel_preferencesMenuItemSelected_ == 0) { sel_preferencesMenuItemSelected_ = registerName(osCls, "preferencesMenuItemSelected:"); sel_aboutMenuItemSelected_ = registerName(osCls, "aboutMenuItemSelected:"); sel_restartMenuSelected_ = registerName(osCls, "restartMenuItemSelected:"); sel_natMenuSelected_ = registerName(osCls, "natMenuItemSelected:"); sel_speedMenuSelected_ = registerName(osCls, "speedMenuItemSelected:"); sel_wizardMenuSelected_ = registerName(osCls, "wizardMenuItemSelected:"); sel_applicationShouldHandleReopen_ = registerName(osCls, "applicationShouldHandleReopen:hasVisibleWindows:"); } // Add the action callbacks for Preferences and About menu items. invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_preferencesMenuItemSelected_), wrapPointer(callBack3Addr), "@:@" }); invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_aboutMenuItemSelected_), wrapPointer(callBack3Addr), "@:@" }); invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_restartMenuSelected_), wrapPointer(callBack3Addr), "@:@" }); invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_wizardMenuSelected_), wrapPointer(callBack3Addr), "@:@" }); invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_speedMenuSelected_), wrapPointer(callBack3Addr), "@:@" }); invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_natMenuSelected_), wrapPointer(callBack3Addr), "@:@" }); invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_applicationShouldHandleReopen_), wrapPointer(callBack4Addr), "@:@c" }); // Get the Mac OS X Application menu. Object sharedApplication = invoke(nsapplicationCls, "sharedApplication"); Object mainMenu = invoke(sharedApplication, "mainMenu"); Object mainMenuItem = invoke(nsmenuCls, mainMenu, "itemAtIndex", new Object[] { wrapPointer(0) }); Object appMenu = invoke(mainMenuItem, "submenu"); // Create the About menu command Object aboutMenuItem = invoke(nsmenuCls, appMenu, "itemAtIndex", new Object[] { wrapPointer(kAboutMenuItem) }); // Enable the Preferences menuItem. Object prefMenuItem = invoke(nsmenuCls, appMenu, "itemAtIndex", new Object[] { wrapPointer(kPreferencesMenuItem) }); invoke(nsmenuitemCls, prefMenuItem, "setEnabled", new Object[] { true }); Object servicesMenuItem = invoke(nsmenuCls, appMenu, "itemAtIndex", new Object[] { wrapPointer(kServicesMenuItem) }); invoke(nsmenuitemCls, servicesMenuItem, "setEnabled", new Object[] { false }); // Set the action to execute when the About or Preferences menuItem is invoked. // // We don't need to set the target here as the current target is the SWTApplicationDelegate // and we have registerd the new selectors on it. So just set the new action to invoke the // selector. invoke(nsmenuitemCls, prefMenuItem, "setAction", new Object[] { wrapPointer(sel_preferencesMenuItemSelected_) }); invoke(nsmenuitemCls, aboutMenuItem, "setAction", new Object[] { wrapPointer(sel_aboutMenuItemSelected_) }); // Add other menus Object menuId = appMenu.getClass().getField("id").get(appMenu); boolean isAZ3 = "az3".equalsIgnoreCase(COConfigurationManager.getStringParameter("ui")); if (!isAZ3) { // add Wizard, NAT Test, Speed Test addMenuItem(menuId, 5, (int) sel_wizardMenuSelected_, MessageText.getString("MainWindow.menu.file.configure").replaceAll( "&", "")); addMenuItem(menuId, 6, (int) sel_natMenuSelected_, MessageText.getString( "MainWindow.menu.tools.nattest").replaceAll("&", "")); addMenuItem(menuId, 7, (int) sel_speedMenuSelected_, MessageText.getString("MainWindow.menu.tools.speedtest").replaceAll( "&", "")); } int numOfItems = ((Number) invoke(appMenu, "numberOfItems")).intValue(); Object sep = invoke(osCls, "objc_msgSend", new Object[] { osCls.getField("class_NSMenuItem").get(null), osCls.getField("sel_separatorItem").get(null) }); invoke(osCls, "objc_msgSend", new Object[] { sep, osCls.getField("sel_retain").get(null) }); //OS.objc_msgSend(menuId, OS.sel_insertItem_atIndex_, sep, numOfItems - 1); invoke(osCls, "objc_msgSend", new Object[] { menuId, osCls.getField("sel_insertItem_atIndex_").get(null), sep, numOfItems - 1 }); numOfItems++; addMenuItem(menuId, numOfItems - 1, (int) sel_restartMenuSelected_, MessageText.getString("MainWindow.menu.file.restart").replaceAll("&", "")); } private void addMenuItem(Object menuId, int index, int selector, String title) { try { //NSMenuItem nsItem = (NSMenuItem) new SWTMenuItem().alloc(); Object oSWTMenuItem = swtmenuitemCls.newInstance(); Object nsItem = invoke(oSWTMenuItem, "alloc"); Object nsStrTitle = invoke(nsstringCls, "stringWith", new Object[] { title }); Object nsStrEmpty = invoke(nsstringCls, "stringWith", new Object[] { "" }); invoke(nsmenuitemCls, nsItem, "initWithTitle", new Object[] { nsStrTitle, 0, nsStrEmpty }); invoke(nsItem, "setTarget", new Class[] { nsidCls }, new Object[] { delegate }); invoke(nsmenuitemCls, nsItem, "setAction", new Object[] { wrapPointer(selector) }); //OS.objc_msgSend(menuId, OS.sel_insertItem_atIndex_, nsItem.id, index); invoke(osCls, "objc_msgSend", new Object[] { menuId, osCls.getField("sel_insertItem_atIndex_").get(null), nsmenuitemCls.getField("id").get(nsItem), index }); } catch (Throwable e) { Debug.out(e); } } private Object invoke(Class cls, String methodName) { return invoke(cls, methodName, (Class[]) null, (Object[]) null); } private Object invoke(Class cls, String methodName, Class[] paramTypes, Object... arguments) { try { Method m = cls.getMethod(methodName, paramTypes); return m.invoke(null, arguments); } catch (Exception e) { throw new IllegalStateException(e); } } public void registerToolbarToggle(Shell shell) throws Throwable { if (sel_toolbarButtonClicked_ == 0) { sel_toolbarButtonClicked_ = registerName(osCls, "toolbarButtonClicked:"); } invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_toolbarButtonClicked_), wrapPointer(callBack3Addr), "@:@" }); Class nstoolbarCls = classForName("org.eclipse.swt.internal.cocoa.NSToolbar"); Class nsbuttonCls = classForName("org.eclipse.swt.internal.cocoa.NSButton"); //NSToolbar dummyBar = new NSToolbar(); Object dummyBar = nstoolbarCls.newInstance(); //dummyBar.alloc(); invoke(dummyBar, "alloc"); //dummyBar.initWithIdentifier(NSString.stringWith("SWTToolbar")); Object nsStrDummyToolbar = invoke(nsstringCls, "stringWith", new Object[] { "SWTToolbar" }); invoke(dummyBar, "initWithIdentifier", new Class[] { nsstringCls }, new Object[] { nsStrDummyToolbar }); //dummyBar.setVisible(false); invoke(dummyBar, "setVisible", new Class[] { boolean.class }, new Object[] { Boolean.FALSE }); // reflect me //NSWindow nsWindow = shell.view.window(); Object view = shell.getClass().getField("view").get(shell); Object nsWindow = invoke(view, "window"); //nsWindow.setToolbar(dummyBar); invoke(nsWindow, "setToolbar", new Class[] { nstoolbarCls }, new Object[] { dummyBar }); //nsWindow.setShowsToolbarButton(true); invoke(nsWindow, "setShowsToolbarButton", new Class[] { boolean.class }, new Object[] { Boolean.TRUE }); //NSButton toolbarButton = nsWindow.standardWindowButton(NSWindowToolbarButton); Object toolbarButton = invoke(nsWindow, "standardWindowButton", new Class[] { int.class }, new Object[] { new Integer(NSWindowToolbarButton) }); //toolbarButton.setTarget(delegate); invoke(toolbarButton, "setTarget", new Class[] { nsidCls }, new Object[] { delegate }); //OS.objc_msgSend(this.id, OS.sel_setTarget_, anObject != null ? anObject.id : 0); //invoke(osCls, "objc_msgSend", new Object[] { // toolbarButton.getClass().getField("id").get(toolbarButton), // osCls.getField("sel_setTarget_").get(null), // wrapPointer(delegateIdSWTApplication) //}); //toolbarButton.setAction((int) sel_toolbarButtonClicked_); invoke(nsbuttonCls, toolbarButton, "setAction", new Object[] { wrapPointer(sel_toolbarButtonClicked_) }); } // from Program.getImageData, except returns bigger images public static Image getFileIcon (String path, int imageWidthHeight) { Object pool = null; try { //NSAutoreleasePool pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init(); pool = nsautoreleasepoolCls.newInstance(); Object delegateAlloc = invoke(pool, "alloc"); invoke(delegateAlloc, "init"); //NSWorkspace workspace = NSWorkspace.sharedWorkspace(); Object workspace = invoke(nsworkspaceCls, "sharedWorkspace", new Object[] {}); //NSString fullPath = NSString.stringWith(path); Object fullPath = invoke(nsstringCls, "stringWith", new Object[] { path }); if (fullPath != null) { // SWT also had a : // fullPath = workspace.fullPathForApplication(NSString.stringWith(name)); // which might be handy someday, but for now, full path works //NSImage nsImage = workspace.iconForFile(fullPath); Object nsImage = invoke(workspace, "iconForFile", new Class[] { nsstringCls }, new Object[] { fullPath }); if (nsImage != null) { //NSSize size = new NSSize(); Object size = nssizeCls.newInstance(); //size.width = size.height = imageWidthHeight; nssizeCls.getField("width").set(size, imageWidthHeight); nssizeCls.getField("height").set(size, imageWidthHeight); //nsImage.setSize(size); invoke(nsImage, "setSize", new Class[] { nssizeCls }, new Object[] { size }); //nsImage.retain(); invoke(nsImage, "retain"); //Image image = Image.cocoa_new(Display.getCurrent(), SWT.BITMAP, nsImage); Image image = (Image) invoke(Image.class, null, "cocoa_new", new Class[] { Device.class, int.class, nsimageCls }, new Object[] { Display.getCurrent(), SWT.BITMAP, nsImage }); return image; } } } catch (Throwable t) { Debug.printStackTrace(t); } finally { if (pool != null) { invoke(pool, "release"); } } return null; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/osx/CarbonUIEnhancer.java0000644000175000017500000005023611276722200024176 0ustar adrianadrian/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Aelitis - Adaptation for Azureus *******************************************************************************/ package org.gudy.azureus2.ui.swt.osx; import java.io.IOException; import java.lang.reflect.Method; import org.eclipse.swt.SWT; import org.eclipse.swt.internal.Callback; import org.eclipse.swt.internal.carbon.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.platform.macosx.access.jnilib.OSXAccess; import org.gudy.azureus2.ui.swt.UIExitUtilsSWT; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.wizard.ConfigureWizard; import org.gudy.azureus2.ui.swt.help.AboutWindow; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.nat.NatTestWindow; import org.gudy.azureus2.ui.swt.speedtest.SpeedTestWizard; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.apple.cocoa.application.NSApplication; //import com.apple.eawt.*; //Application and ApplicationAdapter public class CarbonUIEnhancer { private static final int kHICommandPreferences = ('p' << 24) + ('r' << 16) + ('e' << 8) + 'f'; private static final int kHICommandAbout = ('a' << 24) + ('b' << 16) + ('o' << 8) + 'u'; private static final int kHICommandServices = ('s' << 24) + ('e' << 16) + ('r' << 8) + 'v'; private static final int kHICommandWizard = ('a' << 24) + ('z' << 16) + ('c' << 8) + 'n'; private static final int kHICommandNatTest = ('a' << 24) + ('z' << 16) + ('n' << 8) + 't'; private static final int kHICommandSpeedTest = ('a' << 24) + ('z' << 16) + ('s' << 8) + 't'; private static final int kHICommandRestart = ('a' << 24) + ('z' << 16) + ('r' << 8) + 's'; private static final int typeAEList = ('l' << 24) + ('i' << 16) + ('s' << 8) + 't'; private static final int kCoreEventClass = ('a' << 24) + ('e' << 16) + ('v' << 8) + 't'; private static final int kAEOpenDocuments = ('o' << 24) + ('d' << 16) + ('o' << 8) + 'c'; private static final int kAEReopenApplication = ('r' << 24) + ('a' << 16) + ('p' << 8) + 'p'; private static final int kAEOpenContents = ('o' << 24) + ('c' << 16) + ('o' << 8) + 'n'; private static final int kURLEventClass = ('G' << 24) + ('U' << 16) + ('R' << 8) + 'L'; private static final int typeText = ('T' << 24) + ('E' << 16) + ('X' << 8) + 'T'; private static final String RESOURCE_BUNDLE = "org.eclipse.ui.carbon.Messages"; //$NON-NLS-1$ private static String fgAboutActionName; private static String fgWizardActionName; private static String fgNatTestActionName; private static String fgRestartActionName; private static String fgSpeedTestActionName; private static int memmove_type = 0; /** * KN: Some of the menu items have been removed for the Vuze and Vuze Advanced UI's; * the classic UI still retains all its menu items as before. Follow this flag in the code * to see which menu items are effected. */ private boolean isAZ3 = "az3".equalsIgnoreCase(COConfigurationManager.getStringParameter("ui")); public static final int BOUNCE_SINGLE = NSApplication.UserAttentionRequestInformational; public static final int BOUNCE_CONTINUOUS = NSApplication.UserAttentionRequestCritical; public CarbonUIEnhancer() { if (fgAboutActionName == null) { fgAboutActionName = MessageText.getString("MainWindow.menu.help.about").replaceAll( "&", ""); } if (false == isAZ3) { if (fgWizardActionName == null) { fgWizardActionName = MessageText.getString( "MainWindow.menu.file.configure").replaceAll("&", ""); } if (fgNatTestActionName == null) { fgNatTestActionName = MessageText.getString( "MainWindow.menu.tools.nattest").replaceAll("&", ""); } if (fgSpeedTestActionName == null) { fgSpeedTestActionName = MessageText.getString( "MainWindow.menu.tools.speedtest").replaceAll("&", ""); } } if (fgRestartActionName == null) { fgRestartActionName = MessageText.getString( "MainWindow.menu.file.restart").replaceAll("&", ""); } earlyStartup(); registerTorrentFile(); } public static void registerToolbarToggle(Shell shell) { final Callback toolbarToggleCB = new Callback(target, "toolbarToggle", 3); int toolbarToggle = toolbarToggleCB.getAddress(); if (toolbarToggle == 0) { Debug.out("OSX: Could not find callback 'toolbarToggle'"); toolbarToggleCB.dispose(); return; } shell.getDisplay().disposeExec(new Runnable() { public void run() { toolbarToggleCB.dispose(); } }); // add the button to the window trim int windowHandle = OS.GetControlOwner(shell.handle); OS.ChangeWindowAttributes(windowHandle, OS.kWindowToolbarButtonAttribute, 0); int[] mask = new int[] { OS.kEventClassWindow, OS.kEventWindowToolbarSwitchMode }; // register the handler with the OS OS.InstallEventHandler(OS.GetApplicationEventTarget(), toolbarToggle, mask.length / 2, mask, 0, null); } private void registerTorrentFile() { int result; Callback clickDockIconCallback = new Callback(target, "clickDockIcon", 3); int clickDocIcon = clickDockIconCallback.getAddress(); if (clickDocIcon == 0) { clickDockIconCallback.dispose(); } else { result = OS.AEInstallEventHandler(kCoreEventClass, kAEReopenApplication, clickDocIcon, 0, false); if (result != OS.noErr) { Debug.out("OSX: Could Install ReopenApplication Event Handler. Error: " + result); } } Callback openContentsCallback = new Callback(target, "openContents", 3); int openContents = openContentsCallback.getAddress(); if (openContents == 0) { openContentsCallback.dispose(); } else { result = OS.AEInstallEventHandler(kCoreEventClass, kAEOpenContents, openContents, 0, false); if (result != OS.noErr) { Debug.out("OSX: Could Install OpenContents Event Handler. Error: " + result); } } Callback openDocCallback = new Callback(target, "openDocProc", 3); int openDocProc = openDocCallback.getAddress(); if (openDocProc == 0) { Debug.out("OSX: Could not find Callback 'openDocProc'"); openDocCallback.dispose(); return; } result = OS.AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, openDocProc, 0, false); if (result != OS.noErr) { Debug.out("OSX: Could not Install OpenDocs Event Handler. Error: " + result); return; } result = OS.AEInstallEventHandler(kURLEventClass, kURLEventClass, openDocProc, 0, false); if (result != OS.noErr) { Debug.out("OSX: Could not Install URLEventClass Event Handler. Error: " + result); return; } /// Callback quitAppCallback = new Callback(target, "quitAppProc", 3); int quitAppProc = quitAppCallback.getAddress(); if (quitAppProc == 0) { Debug.out("OSX: Could not find Callback 'quitApp'"); quitAppCallback.dispose(); } else { result = OS.AEInstallEventHandler(kCoreEventClass, OS.kAEQuitApplication, quitAppProc, 0, false); if (result != OS.noErr) { Debug.out("OSX: Could not install QuitApplication Event Handler. Error: " + result); } } /// int appTarget = OS.GetApplicationEventTarget(); Callback appleEventCallback = new Callback(this, "appleEventProc", 3); int appleEventProc = appleEventCallback.getAddress(); int[] mask3 = new int[] { OS.kEventClassAppleEvent, OS.kEventAppleEvent, kURLEventClass, kAEReopenApplication, kAEOpenContents, }; result = OS.InstallEventHandler(appTarget, appleEventProc, mask3.length / 2, mask3, 0, null); if (result != OS.noErr) { Debug.out("OSX: Could Install Event Handler. Error: " + result); return; } } /* (non-Javadoc) * @see org.eclipse.ui.IStartup#earlyStartup() */ public void earlyStartup() { final Display display = Display.getDefault(); display.syncExec(new AERunnable() { public void runSupport() { hookApplicationMenu(display); } }); } /** * See Apple Technical Q&A 1079 (http://developer.apple.com/qa/qa2001/qa1079.html)
* Also http://developer.apple.com/documentation/Carbon/Reference/Menu_Manager/menu_mgr_ref/function_group_10.html */ public void hookApplicationMenu(final Display display) { // Callback target Object target = new Object() { int commandProc(int nextHandler, int theEvent, int userData) { if (OS.GetEventKind(theEvent) == OS.kEventProcessCommand) { HICommand command = new HICommand(); OS.GetEventParameter(theEvent, OS.kEventParamDirectObject, OS.typeHICommand, null, HICommand.sizeof, null, command); switch (command.commandID) { case kHICommandPreferences: { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_CONFIG, null); } return OS.noErr; } case kHICommandAbout: AboutWindow.show(); return OS.noErr; case kHICommandRestart: { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.dispose(true, false); } return OS.noErr; } case kHICommandWizard: new ConfigureWizard(false); return OS.noErr; case kHICommandNatTest: new NatTestWindow(); return OS.noErr; case kHICommandSpeedTest: new SpeedTestWizard(); return OS.noErr; case OS.kAEQuitApplication: UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.dispose(false, false); return OS.noErr; } else { UIExitUtilsSWT.setSkipCloseCheck(true); } default: break; } } return OS.eventNotHandledErr; } }; final Callback commandCallback = new Callback(target, "commandProc", 3); //$NON-NLS-1$ int commandProc = commandCallback.getAddress(); if (commandProc == 0) { commandCallback.dispose(); return; // give up } // Install event handler for commands int[] mask = new int[] { OS.kEventClassCommand, OS.kEventProcessCommand }; OS.InstallEventHandler(OS.GetApplicationEventTarget(), commandProc, mask.length / 2, mask, 0, null); // create About menu command int[] outMenu = new int[1]; short[] outIndex = new short[1]; if (OS.GetIndMenuItemWithCommandID(0, kHICommandPreferences, 1, outMenu, outIndex) == OS.noErr && outMenu[0] != 0) { int menu = outMenu[0]; int l = fgAboutActionName.length(); char buffer[] = new char[l]; fgAboutActionName.getChars(0, l, buffer, 0); int str = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, buffer, l); OS.InsertMenuItemTextWithCFString(menu, str, (short) 0, 0, kHICommandAbout); OS.CFRelease(str); // add separator between About & Preferences OS.InsertMenuItemTextWithCFString(menu, 0, (short) 1, OS.kMenuItemAttrSeparator, 0); // enable pref menu OS.EnableMenuCommand(menu, kHICommandPreferences); // disable services menu OS.DisableMenuCommand(menu, kHICommandServices); if (false == isAZ3) { // wizard menu l = fgWizardActionName.length(); buffer = new char[l]; fgWizardActionName.getChars(0, l, buffer, 0); str = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, buffer, l); OS.InsertMenuItemTextWithCFString(menu, str, (short) 3, 0, kHICommandWizard); OS.CFRelease(str); // NAT test menu l = fgNatTestActionName.length(); buffer = new char[l]; fgNatTestActionName.getChars(0, l, buffer, 0); str = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, buffer, l); OS.InsertMenuItemTextWithCFString(menu, str, (short) 4, 0, kHICommandNatTest); OS.CFRelease(str); //SpeedTest l = fgSpeedTestActionName.length(); buffer = new char[l]; fgSpeedTestActionName.getChars(0, l, buffer, 0); str = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, buffer, l); OS.InsertMenuItemTextWithCFString(menu, str, (short) 5, 0, kHICommandSpeedTest); OS.CFRelease(str); } OS.InsertMenuItemTextWithCFString(menu, 0, (short) 6, OS.kMenuItemAttrSeparator, 0); // restart menu l = fgRestartActionName.length(); buffer = new char[l]; fgRestartActionName.getChars(0, l, buffer, 0); str = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, buffer, l); OS.InsertMenuItemTextWithCFString(menu, str, (short) 7, 0, kHICommandRestart); OS.CFRelease(str); OS.InsertMenuItemTextWithCFString(menu, 0, (short) 8, OS.kMenuItemAttrSeparator, 0); } // schedule disposal of callback object display.disposeExec(new AERunnable() { public void runSupport() { commandCallback.dispose(); // stopSidekick(); } }); } private static void stopSidekick() { try { Runtime.getRuntime().exec(new String[] { "osascript", "-e", "tell application \"Azureus\" to quit" }); } catch (IOException e) { Debug.printStackTrace(e); } } int appleEventProc(int nextHandler, int theEvent, int userData) { int eventClass = OS.GetEventClass(theEvent); //int eventKind = OS.GetEventKind(theEvent); //System.out.println("appleEventProc " + OSXtoString(eventClass) + ";" // + OS.GetEventKind(theEvent) + ";" + OSXtoString(theEvent) + ";" // + OSXtoString(userData)); // Process teh odoc event if (eventClass == OS.kEventClassAppleEvent) { int[] aeEventID = new int[1]; if (OS.GetEventParameter(theEvent, OS.kEventParamAEEventID, OS.typeType, null, 4, null, aeEventID) != OS.noErr) { return OS.eventNotHandledErr; } //System.out.println("EventID = " + OSXtoString(aeEventID[0])); if (aeEventID[0] != kAEOpenDocuments && aeEventID[0] != kURLEventClass && aeEventID[0] != kAEReopenApplication && aeEventID[0] != kAEOpenContents && aeEventID[0] != OS.kAEQuitApplication) { return OS.eventNotHandledErr; } // Handle Event EventRecord eventRecord = new EventRecord(); OS.ConvertEventRefToEventRecord(theEvent, eventRecord); OS.AEProcessAppleEvent(eventRecord); // Tell Mac we are handling this event return OS.noErr; } return OS.eventNotHandledErr; } private static String OSXtoString(int i) { char[] c = new char[4]; c[0] = (char) ((i >> 24) & 0xff); c[1] = (char) ((i >> 16) & 0xff); c[2] = (char) ((i >> 8) & 0xff); c[3] = (char) (i & 0xff); return new String(c); } private static void memmove(byte[] dest, int src, int size) { switch (memmove_type) { case 0: try { OSXAccess.memmove(dest, src, size); memmove_type = 0; return; } catch (Throwable e) { } // FALL THROUGH case 1: try { Class cMemMove = Class.forName("org.eclipse.swt.internal.carbon.OS"); Method method = cMemMove.getMethod("memmove", new Class[] { byte[].class, Integer.TYPE, Integer.TYPE }); method.invoke(null, new Object[] { dest, new Integer(src), new Integer(size) }); memmove_type = 1; return; } catch (Throwable e) { } // FALL THROUGH case 2: try { Class cMemMove = Class.forName("org.eclipse.swt.internal.carbon.OS"); Method method = cMemMove.getMethod("memcpy", new Class[] { byte[].class, Integer.TYPE, Integer.TYPE }); method.invoke(null, new Object[] { dest, new Integer(src), new Integer(size) }); memmove_type = 2; return; } catch (Throwable e) { } // FALL THROUGH default: break; } memmove_type = 3; } final static Object target = new Object() { int quitAppProc(int theAppleEvent, int reply, int handlerRefcon) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.dispose(false, false); } else { UIExitUtilsSWT.setSkipCloseCheck(true); Display.getDefault().dispose(); } return OS.noErr; } int openDocProc(int theAppleEvent, int reply, int handlerRefcon) { AEDesc aeDesc = new AEDesc(); EventRecord eventRecord = new EventRecord(); OS.ConvertEventRefToEventRecord(theAppleEvent, eventRecord); try { int result = OSXAccess.AEGetParamDesc(theAppleEvent, OS.kEventParamDirectObject, typeAEList, aeDesc); if (result != OS.noErr) { Debug.out("OSX: Could call AEGetParamDesc. Error: " + result); return OS.noErr; } } catch (java.lang.UnsatisfiedLinkError e) { Debug.out("OSX: AEGetParamDesc not available. Can't open sent file"); return OS.noErr; } int[] count = new int[1]; OS.AECountItems(aeDesc, count); //System.out.println("COUNT: " + count[0]); if (count[0] > 0) { final String[] fileNames = new String[count[0]]; int maximumSize = 80; // size of FSRef int dataPtr = OS.NewPtr(maximumSize); int[] aeKeyword = new int[1]; int[] typeCode = new int[1]; int[] actualSize = new int[1]; for (int i = 0; i < count[0]; i++) { if (OS.AEGetNthPtr(aeDesc, i + 1, OS.typeFSRef, aeKeyword, typeCode, dataPtr, maximumSize, actualSize) == OS.noErr) { byte[] fsRef = new byte[actualSize[0]]; memmove(fsRef, dataPtr, actualSize[0]); int dirUrl = OS.CFURLCreateFromFSRef(OS.kCFAllocatorDefault, fsRef); int dirString = OS.CFURLCopyFileSystemPath(dirUrl, OS.kCFURLPOSIXPathStyle); int length = OS.CFStringGetLength(dirString); char[] buffer = new char[length]; CFRange range = new CFRange(); range.length = length; OS.CFStringGetCharacters(dirString, range, buffer); fileNames[i] = new String(buffer); OS.CFRelease(dirString); OS.CFRelease(dirUrl); } else if (OS.AEGetNthPtr(aeDesc, i + 1, typeText, aeKeyword, typeCode, dataPtr, 2048, actualSize) == OS.noErr) { byte[] urlRef = new byte[actualSize[0]]; memmove(urlRef, dataPtr, actualSize[0]); fileNames[i] = new String(urlRef); } //System.out.println(fileNames[i]); } AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { TorrentOpener.openTorrents(fileNames); } }); } return OS.noErr; } int clickDockIcon(int nextHandler, int theEvent, int userData) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.bringToFront(); return OS.noErr; } return OS.eventNotHandledErr; } int openContents(int nextHandler, int theEvent, int userData) { Debug.out("openDocContents"); return OS.noErr; } int toolbarToggle(int nextHandler, int theEvent, int userData) { int eventKind = OS.GetEventKind(theEvent); if (eventKind != OS.kEventWindowToolbarSwitchMode) { return OS.eventNotHandledErr; } int[] theWindow = new int[1]; OS.GetEventParameter(theEvent, OS.kEventParamDirectObject, OS.typeWindowRef, null, 4, null, theWindow); int[] theRoot = new int[1]; OS.GetRootControl(theWindow[0], theRoot); final Widget widget = Display.getCurrent().findWidget(theRoot[0]); if (!(widget instanceof Shell)) { return OS.eventNotHandledErr; } final Shell shellAffected = (Shell) widget; Utils.execSWTThread(new AERunnable() { public void runSupport() { int type; Long l = (Long) shellAffected.getData("OSX.ToolBarToggle"); if (l == null || l.longValue() == 0) { type = SWT.Collapse; } else { type = SWT.Expand; } Event event = new Event(); event.type = type; event.display = widget.getDisplay(); event.widget = widget; shellAffected.notifyListeners(type, event); shellAffected.setData("OSX.ToolBarToggle", new Long( type == SWT.Collapse ? 1 : 0)); } }); return OS.noErr; } }; }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/osx/Start.java0000644000175000017500000000442310373051054022161 0ustar adrianadrian/* * Created on May 30, 2004 * Created by Olivier Chalouhi * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.osx; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import org.gudy.azureus2.core3.util.Debug; public class Start { public Start(String args[]) { // if(args.length == 0) // return; Socket sck = null; PrintWriter pw = null; try { System.out.println("StartSocket: passing startup args to already-running Azureus java process."); sck = new Socket("127.0.0.1", 6880); pw = new PrintWriter(new OutputStreamWriter(sck.getOutputStream(),"UTF8")); StringBuffer buffer = new StringBuffer("Azureus Start Server Access;args;"); for(int i = 0 ; i < args.length ; i++) { String arg = args[i].replaceAll("&","&&").replaceAll(";","&;"); buffer.append(arg); buffer.append(';'); } pw.println(buffer.toString()); pw.flush(); } catch(Exception e) { Debug.printStackTrace( e ); } finally { try { if (pw != null) pw.close(); } catch (Exception e) { } try { if (sck != null) sck.close(); } catch (Exception e) { } } } public static void main(String args[]) { new Start(args); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/animations/0000755000175000017500000000000011310377636021560 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/animations/shell/0000755000175000017500000000000011310377636022667 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/animations/shell/LinearAnimator.java0000644000175000017500000000543210374433540026437 0ustar adrianadrian/* * File : LinearAnimator.java * Created : 14 mars 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.animations.shell; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.animations.Animator; /** * @author Olivier Chalouhi * */ public class LinearAnimator extends Animator{ private AnimableShell shell; private Display display; private int startX; private int startY; private int endX; private int endY; private int nbSteps; private int period; private boolean interrupted; public LinearAnimator(AnimableShell shell,Point start,Point end,int nbSteps,int period) { super("Linear Shell Animator"); if(period < 20) period = 20; if(nbSteps <= 0) nbSteps = 1; this.shell = shell; this.display = shell.getShell().getDisplay(); this.startX = start.x; this.startY = start.y; this.endX = end.x; this.endY = end.y; this.nbSteps = nbSteps; this.period = period; this.interrupted = false; } public void runSupport() { try { shell.animationStarted(this); int step = 0; while(step <= nbSteps && !interrupted) { setShellAtStep(step); shell.reportPercent(100 * step /nbSteps); step++; try { Thread.sleep(period); } catch(Exception e) { //Stop animating step = nbSteps; } } } finally { shell.animationEnded(this); } } public void interrupt() { this.interrupted = true; } private void setShellAtStep(int step) { if(display == null || display.isDisposed()) return; final int x = startX + ((endX - startX) * step ) / nbSteps; final int y = startY + ((endY - startY) * step ) / nbSteps; display.asyncExec(new AERunnable() { public void runSupport() { if(shell == null || shell.getShell() == null || shell.getShell().isDisposed()) return; shell.getShell().setLocation(x,y); } }); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/animations/shell/TestWindow.java0000644000175000017500000000461710135240324025634 0ustar adrianadrian/* * File : TestWindow.java * Created : 14 mars 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.animations.shell; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.animations.Animator; import org.gudy.azureus2.ui.swt.shells.PopupShell; /** * @author Olivier Chalouhi * */ public class TestWindow extends PopupShell implements AnimableShell { int nbAnimation = 0; int x0,y0,x1,y1; public TestWindow(Display display) { super(display); layout(); Rectangle bounds = display.getClientArea(); x0 = bounds.x + bounds.width - 250; x1 = bounds.x + bounds.width; y0 = bounds.y + bounds.height; y1 = bounds.y + bounds.height - 150; shell.setLocation(x0,y0); shell.open(); new LinearAnimator(this,new Point(x0,y0),new Point(x0,y1),30,30).start(); } public void animationEnded(Animator source) { if(nbAnimation == 0) { nbAnimation++; new LinearAnimator(this,new Point(x0,y1),new Point(x0,y1),1,3000).start(); return; } if(nbAnimation == 1) { nbAnimation++; new LinearAnimator(this,new Point(x0,y1),new Point(x1,y1),50,30).start(); return; } if(nbAnimation == 2) { shell.getDisplay().asyncExec(new AERunnable() { public void runSupport() { shell.dispose(); } }); } } public void animationStarted(Animator source) { } public Shell getShell() { return shell; } public void reportPercent(int percent) { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/animations/shell/AnimableShell.java0000644000175000017500000000230510025250066026217 0ustar adrianadrian/* * File : AnimableShell.java * Created : 14 mars 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.animations.shell; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.ui.swt.animations.Animator; /** * @author Olivier Chalouhi * */ public interface AnimableShell { public Shell getShell(); public void animationStarted(Animator source); public void reportPercent(int percent); public void animationEnded(Animator source); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/animations/Animator.java0000644000175000017500000000211610070061530024156 0ustar adrianadrian/* * File : Animator.java * Created : 14 mars 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.animations; /** * @author Olivier Chalouhi * */ import org.gudy.azureus2.core3.util.AEThread; public abstract class Animator extends AEThread { public abstract void interrupt(); public Animator(String name) { super(name); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/TwistieSection.java0000644000175000017500000001114611023414172023225 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; public class TwistieSection extends Composite implements ITwistieConstants { private TwistieContentPanel content = null; private TwistieLabel label = null; /** * Create a TwistieSection with the given style bit. *

Style bit can be one or more of:

*
    *
  • TwistieLabel.NONE
  • -- The default; does not show description and separator, and is collapsed *
  • TwistieLabel.SHOW_DESCRIPTION
  • -- Show the description below the separator (or title if separator s not shown) *
  • TwistieLabel.SHOW_SEPARATOR
  • -- Show a separator below the title *
  • TwistieLabel.SHOW_EXPANDED
  • -- Show a separator below the title *
*/ public TwistieSection(Composite parent, int style) { super(parent, SWT.NONE); setBackgroundMode(SWT.INHERIT_FORCE); GridLayout gLayout = new GridLayout(); gLayout.marginHeight = 0; gLayout.marginWidth = 0; gLayout.verticalSpacing = 0; setLayout(gLayout); label = new TwistieLabel(this, style); label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); content = new TwistieContentPanel(this, SWT.NONE); final GridData gDataExpanded = new GridData(SWT.FILL, SWT.FILL, true, true); gDataExpanded.horizontalIndent = 10; final GridData gDataCollapsed = new GridData(SWT.FILL, SWT.FILL, true, false); gDataCollapsed.heightHint = 0; content._setLayoutData((true == label.isCollapsed()) ? gDataCollapsed : gDataExpanded); label.addTwistieListener(new ITwistieListener() { public void isCollapsed(boolean value) { content._setLayoutData((true == value) ? gDataCollapsed : gDataExpanded); layout(true, true); } }); } /** * Returns the main body of the section. Callers can add custom controls onto the returned * Composite * @return */ public Composite getContent() { return content; } public void setBackground(Color color) { if (null != label && false == label.isDisposed()) { label.setBackground(color); } if (null != content && false == content.isDisposed()) { content.setBackground(color); } super.setBackground(color); } public void setForeground(Color color) { if (null != label && false == label.isDisposed()) { label.setForeground(color); } if (null != content && false == content.isDisposed()) { content.setForeground(color); } super.setForeground(color); } public void setEnabled(boolean enabled) { if (null != label && false == label.isDisposed()) { label.setEnabled(enabled); } super.setEnabled(enabled); } /** * Delegating to the TwistieLabel * @param listener */ public void addTwistieListener(ITwistieListener listener) { if (null != label && false == label.isDisposed()) { label.addTwistieListener(listener); } } /** * Delegating to the TwistieLabel * @param listener */ public void removeTwistieListener(ITwistieListener listener) { if (null != label && false == label.isDisposed()) { label.removeTwistieListener(listener); } } /** * Delegating to the TwistieLabel * @param string */ public void setDescription(String string) { if (null != label && false == label.isDisposed()) { label.setDescription(string); } } /** * Delegating to the TwistieLabel * @param string */ public void setTitle(String string) { if (null != label && false == label.isDisposed()) { label.setTitle(string); } } /** * Delegating to the TwistieLabel * @param string */ public void setToolTipText(String string) { if (null != label && false == label.isDisposed()) { label.setToolTipText(string); } } /** * Delegating to the TwistieLabel * @param color */ public void setTwistieForeground(Color color) { if (null != label && false == label.isDisposed()) { label.setTwistieForeground(color); } } /** * A simple extension of Composite that disallow modifying its layout data * @author knguyen * */ private class TwistieContentPanel extends Composite { public TwistieContentPanel(Composite parent, int style) { super(parent, style); setBackgroundMode(SWT.INHERIT_FORCE); } private void _setLayoutData(GridData gData) { super.setLayoutData(gData); } public void setLayoutData(Object layoutData) { throw new IllegalArgumentException( "This is a managed class therefore overriding its LayoutData is an illegal operation"); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/Messages.java0000644000175000017500000002425311247070356022034 0ustar adrianadrian/* * Created on 21.07.2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import java.util.regex.Pattern; /** * @author Arbeiten */ public class Messages { private static final Pattern HIG_ELLIP_EXP = Pattern.compile("([\\.]{3})"); // rec. hig style on some platforms /** * */ private Messages() { // TODO Auto-generated constructor stub } public static void updateLanguageForControl(Widget widget) { if (widget == null || widget.isDisposed()) return; updateLanguageFromData(widget,null); // OK, so we loose parameters on language change... updateToolTipFromData(widget); if (widget instanceof CTabFolder) { CTabFolder folder = (CTabFolder) widget; CTabItem[] items = folder.getItems(); for (int i = 0; i < items.length; i++) { updateLanguageForControl(items[i]); updateLanguageForControl(items[i].getControl()); } } else if (widget instanceof TabFolder) { TabFolder folder = (TabFolder) widget; TabItem[] items = folder.getItems(); for (int i = 0; i < items.length; i++) { updateLanguageForControl(items[i]); updateLanguageForControl(items[i].getControl()); } } else if(widget instanceof CoolBar) { CoolItem[] items = ((CoolBar)widget).getItems(); for(int i = 0 ; i < items.length ; i++) { Control control = items[i].getControl(); updateLanguageForControl(control); } } else if(widget instanceof ToolBar) { ToolItem[] items = ((ToolBar)widget).getItems(); for(int i = 0 ; i < items.length ; i++) { updateLanguageForControl(items[i]); } } else if (widget instanceof Composite) { Composite group = (Composite) widget; Control[] controls = group.getChildren(); for (int i = 0; i < controls.length; i++) { updateLanguageForControl(controls[i]); } if (widget instanceof Table) { Table table = (Table) widget; TableColumn[] columns = table.getColumns(); for (int i = 0; i < columns.length; i++) { updateLanguageFromData(columns[i], null); } updateLanguageForControl(table.getMenu()); // XXX We could (should?) send this event for all widget types // XXX Would it better to have a custom event type? Event event = new Event(); event.type = SWT.Settings; event.widget = widget; widget.notifyListeners(SWT.Settings, event); } else if (widget instanceof Tree) { Tree tree = (Tree) widget; TreeItem[] treeitems = tree.getItems(); for (int i = 0; i < treeitems.length; i++) { updateLanguageForControl(treeitems[i]); } } else if (widget instanceof TreeItem) { TreeItem treeItem = (TreeItem) widget; TreeItem[] treeitems = treeItem.getItems(); for (int i = 0; i < treeitems.length; i++) { updateLanguageForControl(treeitems[i]); } } group.layout(); } else if (widget instanceof MenuItem) { MenuItem menuItem = (MenuItem) widget; updateLanguageForControl(menuItem.getMenu()); } else if (widget instanceof Menu) { Menu menu = (Menu) widget; if (menu.getStyle() == SWT.POP_UP) System.out.println("POP_UP"); MenuItem[] items = menu.getItems(); for (int i = 0; i < items.length; i++) { updateLanguageForControl(items[i]); } } else if (widget instanceof TreeItem) { TreeItem treeitem = (TreeItem) widget; TreeItem[] treeitems = treeitem.getItems(); for (int i = 0; i < treeitems.length; i++) { updateLanguageFromData(treeitems[i], null); } } } public static void setLanguageText(Widget widget, String key) { setLanguageText(widget, key, false); } public static void setLanguageText(Widget widget, String key, String[]params) { setLanguageText(widget, key, params, false); } public static void setLanguageText(Widget widget, String key, boolean setTooltipOnly) { setLanguageText( widget, key, null, setTooltipOnly ); } private static void setLanguageText(Widget widget, String key, String[] params, boolean setTooltipOnly) { widget.setData(key); if(!setTooltipOnly) updateLanguageFromData(widget, params); updateToolTipFromData(widget); } private static void updateToolTipFromData(Widget widget) { if(widget instanceof Control) { String key = (String) widget.getData(); if(key != null) { if(!key.endsWith(".tooltip")) key += ".tooltip"; String toolTip = MessageText.getString(key); if(!toolTip.equals('!' + key + '!')) { ((Control)widget).setToolTipText(toolTip); } } } else if(widget instanceof ToolItem) { String key = (String) widget.getData(); if(key != null) { if(!key.endsWith(".tooltip")) key += ".tooltip"; String toolTip = MessageText.getString(key); if(!toolTip.equals('!' + key + '!')) { ((ToolItem) widget).setToolTipText(toolTip.replaceAll("Meta\\+", Constants.isOSX ? "Cmd+" : "Ctrl+")); } } } else if (widget instanceof TableColumn) { String key = (String) widget.getData(); if (key != null) { if (!key.endsWith(".info")) key += ".info"; String toolTip = MessageText.getString(key, (String) null); if (toolTip == null) toolTip = MessageText.getString(key.substring(0, key.length() - 5), (String) null); if (toolTip != null) { try { ((TableColumn) widget).setToolTipText(toolTip); } catch (NoSuchMethodError e) { // Pre SWT 3.2 } } } } } private static void updateLanguageFromData(Widget widget,String[] params) { if (widget == null || widget.isDisposed()) { return; } if (widget.getData() != null) { String key = null; try { key = (String) widget.getData(); } catch(ClassCastException e) { } if(key == null) return; if(key.endsWith(".tooltip")) return; String message; if ( params == null ){ message = MessageText.getString((String) widget.getData()); }else{ message = MessageText.getString((String) widget.getData(), params); } if (widget instanceof MenuItem) { final MenuItem menuItem = ((MenuItem) widget); boolean indent = (menuItem.getData("IndentItem") != null); if(Constants.isOSX) message = HIG_ELLIP_EXP.matcher(message).replaceAll("\u2026"); // hig style - ellipsis menuItem.setText(indent ? " " + message : message); if(menuItem.getAccelerator() != 0) // opt-in only for now; remove this conditional check to allow accelerators for arbitrary MenuItem objects KeyBindings.setAccelerator(menuItem, (String)menuItem.getData()); // update keybinding } else if (widget instanceof TableColumn) { TableColumn tc = ((TableColumn) widget); tc.setText(message); } else if (widget instanceof Label) // Disable Mnemonic when & is before a space. Otherwise, it's most // likely meant to be a Mnemonic ((Label) widget).setText(message.replaceAll("& ", "&& ")); else if (widget instanceof CLabel) ((CLabel) widget).setText(message.replaceAll("& ", "&& ")); else if (widget instanceof Group) ((Group) widget).setText(message); else if (widget instanceof Button) ((Button) widget).setText(message); else if (widget instanceof CTabItem) ((CTabItem) widget).setText(message); else if (widget instanceof TabItem) ((TabItem) widget).setText(message); else if (widget instanceof TreeItem) ((TreeItem) widget).setText(message); else if(widget instanceof Shell) ((Shell) widget).setText(message); else if(widget instanceof ToolItem) ((ToolItem) widget).setText(message); else if(widget instanceof Text) ((Text) widget).setText(message); else{ Debug.out( "No cast for " + widget.getClass().getName()); } } } public static void setLanguageTooltip(Widget widget, String key) { if (widget == null || widget.isDisposed()) { return; } widget.setData(key); updateTooltipLanguageFromData(widget); } public static void updateTooltipLanguageFromData(Widget widget) { if (widget == null || widget.isDisposed()) { return; } if (widget.getData() != null) { String sToolTip = MessageText.getString((String) widget.getData()); if (widget instanceof CLabel) ((CLabel) widget).setToolTipText(sToolTip); else if (widget instanceof Label) ((Label) widget).setToolTipText(sToolTip); else if (widget instanceof Text) ((Text) widget).setToolTipText(sToolTip); else System.out.println("No cast for " + widget.getClass().getName()); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/PasswordWindow.java0000644000175000017500000001536611300665620023256 0ustar adrianadrian/* * Created on 7 sept. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; /** * @author Olivier * */ public class PasswordWindow { private Shell shell; //protected static AEMonitor class_mon = new AEMonitor( "PasswordWindow:class" ); private static boolean bOk; private static long lastSuccess = 0; final private static long REMEMBER_SUCCESS_MS = 3000; protected static AESemaphore class_sem = new AESemaphore("PasswordWindow"); private static PasswordWindow window = null; public static boolean showPasswordWindow(final Display display) { if (lastSuccess + REMEMBER_SUCCESS_MS >= SystemTime.getCurrentTime()) { return true; } final boolean bSWTThread = display.getThread() == Thread.currentThread (); display.syncExec(new AERunnable() { public void runSupport() { if (window == null) { window = new PasswordWindow(display); window.open(); } else { window.shell.setVisible(true); window.shell.forceActive(); } if (bSWTThread) { window.run(); } } }); if (!bSWTThread) { class_sem.reserve(); } lastSuccess = bOk ? SystemTime.getCurrentTime() : 0; return bOk; } protected PasswordWindow(Display display) { } private void open() { bOk = false; shell = ShellFactory.createMainShell(SWT.APPLICATION_MODAL | SWT.TITLE | SWT.CLOSE); shell.setText(MessageText.getString("PasswordWindow.title")); Utils.setShellIcon(shell); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.makeColumnsEqualWidth = true; shell.setLayout(layout); Label label = new Label(shell,SWT.NONE); label.setText(MessageText.getString("PasswordWindow.passwordprotected")); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; label.setLayoutData(gridData); final Text password = new Text(shell,SWT.BORDER); password.setEchoChar('*'); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; password.setLayoutData(gridData); Button ok = new Button(shell,SWT.PUSH); ok.setText(MessageText.getString("Button.ok")); gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); gridData.widthHint = 70; ok.setLayoutData(gridData); shell.setDefaultButton(ok); ok.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { try { SHA1Hasher hasher = new SHA1Hasher(); byte[] passwordText = password.getText().getBytes(); byte[] encoded = hasher.calculateHash(passwordText); byte[] correct = COConfigurationManager.getByteParameter("Password", "".getBytes()); boolean same = true; for (int i = 0; i < correct.length; i++) { if (correct[i] != encoded[i]) same = false; } if (same) { bOk = same; shell.dispose(); } else { close(); } } catch (Exception e) { Debug.printStackTrace(e); } } }); Button cancel = new Button(shell,SWT.PUSH); cancel.setText(MessageText.getString("Button.cancel")); gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); gridData.widthHint = 70; cancel.setLayoutData(gridData); cancel.addListener(SWT.Selection,new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event event) { close(); } }); shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent arg0) { window = null; class_sem.releaseAllWaiters(); } }); shell.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { close(); e.doit = false; } } }); shell.addListener(SWT.Close,new Listener() { public void handleEvent(Event arg0) { close(); } }); shell.pack(); Utils.centreWindow(shell); shell.open(); } protected void run() { while (!shell.isDisposed()) { Display d = shell.getDisplay(); if (!d.readAndDispatch() && !shell.isDisposed()) { d.sleep(); } } } private void close() { shell.dispose(); if(Utils.isCarbon) { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { Shell mainShell = uiFunctions.getMainShell(); if (mainShell != null) { mainShell.setMinimized(true); mainShell.setVisible(true); } } } } public static void main(String[] args) { final Display display = new Display(); new Thread(new Runnable() { public void run() { System.out.println("2: " + showPasswordWindow(display)); } }).start(); new Thread(new Runnable() { public void run() { display.syncExec(new Runnable() { public void run() { System.out.println("3: " + showPasswordWindow(display)); } }); } }).start(); display.asyncExec(new Runnable() { public void run() { System.out.println("4: " + showPasswordWindow(display)); } }); System.out.println("1: " + showPasswordWindow(display)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/0000755000175000017500000000000011310377636020553 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/PeersView.java0000644000175000017500000002613611265777352023347 0ustar adrianadrian/* * Created on 2 juil. 2003 * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerPeerListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.ipfilter.IpFilterManagerFactory; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.peers.Peer; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.views.peer.PeerInfoView; import org.gudy.azureus2.ui.swt.views.peer.RemotePieceDistributionView; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab; import org.gudy.azureus2.ui.swt.views.tableitems.peers.*; import com.aelitis.azureus.ui.common.table.*; /** * @author Olivier * @author TuxPaper * 2004/Apr/20: Use TableRowImpl instead of PeerRow * 2004/Apr/20: Remove need for tableItemToObject * 2004/Apr/21: extends TableView instead of IAbstractView * @author MjrTom * 2005/Oct/08: Add PieceItem */ public class PeersView extends TableViewTab implements DownloadManagerPeerListener, TableDataSourceChangedListener, TableLifeCycleListener, TableViewSWTMenuFillListener { static TableColumnCore[] getBasicColumnItems(String table_id) { return new TableColumnCore[] { new IpItem(table_id), new ClientItem(table_id), new TypeItem(table_id), new MessagingItem(table_id), new EncryptionItem(table_id), new PiecesItem(table_id), new PercentItem(table_id), new DownSpeedItem(table_id), new UpSpeedItem(table_id), new PeerSourceItem(table_id), new HostNameItem(table_id), new PortItem(table_id), new InterestedItem(table_id), new ChokedItem(table_id), new DownItem(table_id), new InterestingItem(table_id), new ChokingItem(table_id), new OptimisticUnchokeItem(table_id), new UpItem(table_id), new UpDownRatioItem(table_id), new GainItem(table_id), new StatUpItem(table_id), new SnubbedItem(table_id), new TotalDownSpeedItem(table_id), new TimeUntilCompleteItem(table_id), new DiscardedItem(table_id), new UniquePieceItem(table_id), new TimeToSendPieceItem(table_id), new DLedFromOthersItem(table_id), new UpRatioItem(table_id), new StateItem(table_id), new ConnectedTimeItem(table_id), new PieceItem(table_id), new IncomingRequestCountItem(table_id), new OutgoingRequestCountItem(table_id), new UpSpeedLimitItem(table_id), new DownSpeedLimitItem(table_id), new LANItem(table_id), new PeerIDItem(table_id), new PeerByteIDItem(table_id), new HandshakeReservedBytesItem(table_id), new ClientIdentificationItem(table_id), new ASItem(table_id), }; } private static final TableColumnCore[] basicItems = getBasicColumnItems(TableManager.TABLE_TORRENT_PEERS); private DownloadManager manager; private TableViewSWT tv; private Shell shell; /** * Initialize * */ public PeersView() { super("PeersView"); } // @see org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab#initYourTableView() public TableViewSWT initYourTableView() { tv = new TableViewSWTImpl(Peer.class, TableManager.TABLE_TORRENT_PEERS, getPropertiesPrefix(), basicItems, "pieces", SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL); tv.setRowDefaultHeight(16); tv.setEnableTabViews(true); tv.setCoreTabViews(new IView[] { new PeerInfoView(), new RemotePieceDistributionView(), new LoggerView(true) }); tv.addTableDataSourceChangedListener(this, true); tv.addLifeCycleListener(this); tv.addMenuFillListener(this); return tv; } public void tableDataSourceChanged(Object newDataSource) { if (manager != null) manager.removePeerListener(this); if (newDataSource == null) manager = null; else if (newDataSource instanceof Object[]) manager = (DownloadManager)((Object[])newDataSource)[0]; else manager = (DownloadManager)newDataSource; if (manager != null && !tv.isDisposed()) { manager.addPeerListener(this, false); addExistingDatasources(); } } // @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewInitialized() public void tableViewInitialized() { shell = tv.getComposite().getShell(); if (manager != null) { manager.removePeerListener(this); manager.addPeerListener(this, false); } addExistingDatasources(); } public void tableViewDestroyed() { if (manager != null) { manager.removePeerListener(this); } } public void fillMenu(String sColumnName, Menu menu) {fillMenu(menu, tv, shell, true);} public static void fillMenu(final Menu menu, final TableView tv, final Shell shell, boolean download_specific) { Object[] peers = tv.getSelectedDataSources().toArray(); boolean hasSelection = (peers.length > 0); boolean downSpeedDisabled = false; boolean downSpeedUnlimited = false; long totalDownSpeed = 0; long downSpeedSetMax = 0; long maxDown = 0; boolean upSpeedDisabled = false; boolean upSpeedUnlimited = false; long totalUpSpeed = 0; long upSpeedSetMax = 0; long maxUp = 0; if (hasSelection){ for (int i = 0; i < peers.length; i++) { PEPeer peer = (PEPeer)peers[i]; try { int maxul = peer.getStats().getUploadRateLimitBytesPerSecond(); maxUp += maxul * 4; if (maxul == 0) { upSpeedUnlimited = true; }else{ if ( maxul > upSpeedSetMax ){ upSpeedSetMax = maxul; } } if (maxul == -1) { maxul = 0; upSpeedDisabled = true; } totalUpSpeed += maxul; int maxdl = peer.getStats().getDownloadRateLimitBytesPerSecond(); maxDown += maxdl * 4; if (maxdl == 0) { downSpeedUnlimited = true; }else{ if ( maxdl > downSpeedSetMax ){ downSpeedSetMax = maxdl; } } if (maxdl == -1) { maxdl = 0; downSpeedDisabled = true; } totalDownSpeed += maxdl; } catch (Exception ex) { Debug.printStackTrace(ex); } } } if (download_specific) { final MenuItem block_item = new MenuItem(menu, SWT.CHECK); PEPeer peer = (PEPeer) tv.getFirstSelectedDataSource(); if ( peer == null || peer.getManager().getDiskManager().getRemainingExcludingDND() > 0 ){ // disallow peer upload blocking when downloading block_item.setSelection(false); block_item.setEnabled(false); } else { block_item.setEnabled(true); block_item.setSelection(peer.isSnubbed()); } Messages.setLanguageText(block_item, "PeersView.menu.blockupload"); block_item.addListener(SWT.Selection, new TableSelectedRowsListener(tv) { public void run(TableRowCore row) { ((PEPeer) row.getDataSource(true)) .setSnubbed(block_item.getSelection()); } }); } final MenuItem ban_item = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(ban_item, "PeersView.menu.kickandban"); ban_item.addListener(SWT.Selection, new TableSelectedRowsListener(tv) { public void run(TableRowCore row) { PEPeer peer = (PEPeer) row.getDataSource(true); String msg = MessageText.getString("PeersView.menu.kickandban.reason"); IpFilterManagerFactory.getSingleton().getIPFilter().ban(peer.getIp(), msg, true ); peer.getManager().removePeer(peer); } }); // === advanced menu === final MenuItem itemAdvanced = new MenuItem(menu, SWT.CASCADE); Messages.setLanguageText(itemAdvanced, "MyTorrentsView.menu.advancedmenu"); //$NON-NLS-1$ itemAdvanced.setEnabled(hasSelection); final Menu menuAdvanced = new Menu(shell, SWT.DROP_DOWN); itemAdvanced.setMenu(menuAdvanced); // advanced > Download Speed Menu // ViewUtils.addSpeedMenu( shell, menuAdvanced, false, hasSelection, downSpeedDisabled, downSpeedUnlimited, totalDownSpeed, downSpeedSetMax, maxDown, upSpeedDisabled, upSpeedUnlimited, totalUpSpeed, upSpeedSetMax, maxUp, peers.length, new ViewUtils.SpeedAdapter() { public void setDownSpeed( int speed ) { setSelectedPeersDownSpeed( speed, tv ); } public void setUpSpeed( int speed ) { setSelectedPeersUpSpeed( speed, tv ); } }); new MenuItem(menu, SWT.SEPARATOR); } public void addThisColumnSubMenu(String columnName, Menu menuThisColumn) { } private static void setSelectedPeersUpSpeed(int speed, TableView tv) { Object[] peers = tv.getSelectedDataSources().toArray(); if(peers.length > 0) { for (int i = 0; i < peers.length; i++) { try { PEPeer peer = (PEPeer)peers[i]; peer.getStats().setUploadRateLimitBytesPerSecond(speed); } catch (Exception e) { Debug.printStackTrace( e ); } } } } private static void setSelectedPeersDownSpeed(int speed, TableView tv) { Object[] peers = tv.getSelectedDataSources().toArray(); if(peers.length > 0) { for (int i = 0; i < peers.length; i++) { try { PEPeer peer = (PEPeer)peers[i]; peer.getStats().setDownloadRateLimitBytesPerSecond(speed); } catch (Exception e) { Debug.printStackTrace( e ); } } } } /* DownloadManagerPeerListener implementation */ public void peerAdded(PEPeer created) { tv.addDataSource(created); } public void peerRemoved(PEPeer removed) { tv.removeDataSource(removed); } public void peerManagerWillBeAdded( PEPeerManager peer_manager ){} public void peerManagerAdded(PEPeerManager manager) { } public void peerManagerRemoved(PEPeerManager manager) { tv.removeAllTableRows(); } /** * Add datasources already in existance before we called addListener. * Faster than allowing addListener to call us one datasource at a time. */ private void addExistingDatasources() { if (manager == null || tv.isDisposed()) { return; } Object[] dataSources = manager.getCurrentPeers(); if (dataSources == null || dataSources.length == 0) { return; } tv.addDataSources(dataSources); tv.processDataSourceQueue(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/IView.java0000644000175000017500000000741410667726560022457 0ustar adrianadrian/* * Created on 29 juin 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.ui.swt.IconBarEnabler; import org.gudy.azureus2.ui.swt.mainwindow.Refreshable; /** * @author Olivier */ // XXX This class is used by plugins. Don't remove any functions from it! public interface IView extends IconBarEnabler, Refreshable { /** * This method is called when the view is instanciated, it should initialize all GUI * components. Must NOT be blocking, or it'll freeze the whole GUI. * Caller is the GUI Thread. * * @param composite the parent composite. Each view should create a child * composite, and then use this child composite to add all elements * to. * * @note It's possible that the view may be created, but never initialize'd. * In these cases, delete will still be called. */ public void initialize(Composite composite); /** * This method is called after initialize so that the Tab is set its control * Caller is the GUI Thread. * @return the Composite that should be set as the control for the Tab item */ public Composite getComposite(); /** * This method is caled when the view is destroyed. * Each color instanciated, images and such things should be disposed. * The caller is the GUI thread. * */ public void delete(); /** * Data 'could' store a key to a language file, in order to support multi-language titles * @return a String which is the key of this view title. */ public String getData(); /** * Called in order to set / update the short title of this view. When the * view is being displayed in a tab, the short title is used for the tab's * text * * @return A short title for the view */ public String getShortTitle(); /** * Called in order to set / update the title of this View. When the view * is being displayed in a tab, the full title is used for the tooltip. * * @return the full title for the view */ public String getFullTitle(); /** * Called when the language needs updating * */ public void updateLanguage(); /** * Called when Azureus generates Diagnostics. * Write any diagnostic information you want to the writer. * * @param writer * @since 2.3.0.4 */ // XXX Introduced IndentWriter to plugins.. public void generateDiagnostics( IndentWriter writer ); /** * Called when the selected dataSource has changed. * If this view is dependent upon a selected datasource, implement this * function and update your view. * * @param newDataSource null if no datasource is selected. May be an array * of Object[] if multiple dataSources are selected * @since 2.3.0.7 */ public void dataSourceChanged(Object newDataSource); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/MyTrackerView.java0000644000175000017500000004472011265777362024172 0ustar adrianadrian/* * File : MyTrackerView.java * Created : 30-Oct-2003 * By : parg * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.URL; import java.util.Arrays; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.category.Category; import org.gudy.azureus2.core3.category.CategoryManager; import org.gudy.azureus2.core3.category.CategoryManagerListener; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.tracker.host.TRHostListener; import org.gudy.azureus2.core3.tracker.host.TRHostTorrent; import org.gudy.azureus2.core3.tracker.host.TRHostTorrentRemovalVetoException; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AsyncController; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.views.table.TableRowSWT; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab; import org.gudy.azureus2.ui.swt.views.tableitems.mytracker.*; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.table.*; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.tracker.TrackerTorrent; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentManagerImpl; /** * @author parg * @author TuxPaper * 2004/Apr/20: Remove need for tableItemToObject * 2004/Apr/21: extends TableView instead of IAbstractView */ public class MyTrackerView extends TableViewTab implements TRHostListener, CategoryManagerListener, TableLifeCycleListener, TableSelectionListener, TableViewSWTMenuFillListener, TableRefreshListener { private static TableColumnCore[] basicItems = null; protected static final TorrentAttribute category_attribute = TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_CATEGORY ); private Menu menuCategory; private TableViewSWT tv; public MyTrackerView() { super("MyTrackerView"); if (basicItems == null) { basicItems = new TableColumnCore[] { new NameItem(), new TrackerItem(), new StatusItem(), new CategoryItem(), new PassiveItem(), new SeedCountItem(), new PeerCountItem(), new BadNATCountItem(), new AnnounceCountItem(), new ScrapeCountItem(), new CompletedCountItem(), new UploadedItem(), new DownloadedItem(), new LeftItem(), new TotalBytesInItem(), new AverageBytesInItem(), new TotalBytesOutItem(), new AverageBytesOutItem(), new DateAddedItem(), }; } tv = new TableViewSWTImpl(TrackerTorrent.class, TableManager.TABLE_MYTRACKER, getPropertiesPrefix(), basicItems, "name", SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL); tv.addLifeCycleListener(this); tv.addSelectionListener(this, false); tv.addMenuFillListener(this); tv.addRefreshListener(this, false); } public TableViewSWT initYourTableView() { return tv; } // @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewInitialized() public void tableViewInitialized() { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { core.getTrackerHost().addListener(MyTrackerView.this); } }); } // @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewDestroyed() public void tableViewDestroyed() { try { AzureusCoreFactory.getSingleton().getTrackerHost().removeListener( this ); } catch (Exception ignore) { } } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#defaultSelected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void defaultSelected(TableRowCore[] rows, int stateMask) { final TRHostTorrent torrent = tv.getFirstSelectedDataSource(); if (torrent == null) return; CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { DownloadManager dm = core.getGlobalManager().getDownloadManager( torrent.getTorrent()); if (dm != null) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_DM_DETAILS, dm); } } } }); } public void fillMenu(String sColumnName, final Menu menu) { menuCategory = new Menu(getComposite().getShell(), SWT.DROP_DOWN); final MenuItem itemCategory = new MenuItem(menu, SWT.CASCADE); Messages.setLanguageText(itemCategory, "MyTorrentsView.menu.setCategory"); //$NON-NLS-1$ //itemCategory.setImage(ImageRepository.getImage("speed")); itemCategory.setMenu(menuCategory); addCategorySubMenu(); new MenuItem(menu, SWT.SEPARATOR); final MenuItem itemStart = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemStart, "MyTorrentsView.menu.start"); //$NON-NLS-1$ Utils.setMenuItemImage(itemStart, "start"); final MenuItem itemStop = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemStop, "MyTorrentsView.menu.stop"); //$NON-NLS-1$ Utils.setMenuItemImage(itemStop, "stop"); final MenuItem itemRemove = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemRemove, "MyTorrentsView.menu.remove"); //$NON-NLS-1$ Utils.setMenuItemImage(itemRemove, "delete"); Object[] hostTorrents = tv.getSelectedDataSources().toArray(); itemStart.setEnabled(false); itemStop.setEnabled(false); itemRemove.setEnabled(false); if (hostTorrents.length > 0) { boolean start_ok = true; boolean stop_ok = true; boolean remove_ok = true; for (int i = 0; i < hostTorrents.length; i++) { TRHostTorrent host_torrent = (TRHostTorrent)hostTorrents[i]; int status = host_torrent.getStatus(); if ( status != TRHostTorrent.TS_STOPPED ){ start_ok = false; } if ( status != TRHostTorrent.TS_STARTED ){ stop_ok = false; } /* try{ host_torrent.canBeRemoved(); }catch( TRHostTorrentRemovalVetoException f ){ remove_ok = false; } */ } itemStart.setEnabled(start_ok); itemStop.setEnabled(stop_ok); itemRemove.setEnabled(remove_ok); } itemStart.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { startSelectedTorrents(); } }); itemStop.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { stopSelectedTorrents(); } }); itemRemove.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { removeSelectedTorrents(); } }); new MenuItem(menu, SWT.SEPARATOR); } // @see org.gudy.azureus2.ui.swt.views.TableViewSWTMenuFillListener#addThisColumnSubMenu(java.lang.String, org.eclipse.swt.widgets.Menu) public void addThisColumnSubMenu(String columnName, Menu menuThisColumn) { } public void torrentAdded( TRHostTorrent host_torrent ) { tv.addDataSource(host_torrent); } public void torrentChanged(TRHostTorrent t) { } public void torrentRemoved( TRHostTorrent host_torrent ) { tv.removeDataSource(host_torrent); } public boolean handleExternalRequest( InetSocketAddress client, String user, String url, URL absolute_url, String header, InputStream is, OutputStream os, AsyncController async ) throws IOException { return( false ); } // @see com.aelitis.azureus.ui.common.table.TableRefreshListener#tableRefresh() public void tableRefresh() { if (getComposite() == null || getComposite().isDisposed()){ return; } computePossibleActions(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } // Store values for columns that are calculate from peer information, so // that we only have to do one loop. (As opposed to each cell doing a loop) // Calculate code copied from TrackerTableItem TableRowCore[] rows = tv.getRows(); for (int x = 0; x < rows.length; x++) { TableRowSWT row = (TableRowSWT)rows[x]; if (row == null){ continue; } TRHostTorrent host_torrent = (TRHostTorrent)rows[x].getDataSource(true); if (host_torrent == null){ continue; } long uploaded = host_torrent.getTotalUploaded(); long downloaded = host_torrent.getTotalDownloaded(); long left = host_torrent.getTotalLeft(); int seed_count = host_torrent.getSeedCount(); host_torrent.setData("GUI_PeerCount", new Long(host_torrent.getLeecherCount())); host_torrent.setData("GUI_SeedCount", new Long(seed_count)); host_torrent.setData("GUI_BadNATCount", new Long(host_torrent.getBadNATCount())); host_torrent.setData("GUI_Uploaded", new Long(uploaded)); host_torrent.setData("GUI_Downloaded", new Long(downloaded)); host_torrent.setData("GUI_Left", new Long(left)); if ( seed_count != 0 ){ Color fg = row.getForeground(); if (fg != null && fg.equals(Colors.blues[Colors.BLUES_MIDDARK])) { row.setForeground(Colors.blues[Colors.BLUES_MIDDARK]); } } } } private boolean start,stop,remove; private void computePossibleActions() { start = stop = remove = false; Object[] hostTorrents = tv.getSelectedDataSources().toArray(); if (hostTorrents.length > 0) { remove = true; for (int i = 0; i < hostTorrents.length; i++) { TRHostTorrent host_torrent = (TRHostTorrent)hostTorrents[i]; int status = host_torrent.getStatus(); if ( status == TRHostTorrent.TS_STOPPED ){ start = true; } if ( status == TRHostTorrent.TS_STARTED ){ stop = true; } /* try{ host_torrent.canBeRemoved(); }catch( TRHostTorrentRemovalVetoException f ){ remove = false; } */ } } } public boolean isEnabled(String itemKey) { if(itemKey.equals("start")) return start; if(itemKey.equals("stop")) return stop; if(itemKey.equals("remove")) return remove; return false; } public void itemActivated(String itemKey) { if(itemKey.equals("start")) { startSelectedTorrents(); return; } if(itemKey.equals("stop")){ stopSelectedTorrents(); return; } if(itemKey.equals("remove")){ removeSelectedTorrents(); return; } } private void stopSelectedTorrents() { tv.runForSelectedRows(new TableGroupRowRunner() { public void run(TableRowCore row) { TRHostTorrent torrent = (TRHostTorrent)row.getDataSource(true); if (torrent.getStatus() == TRHostTorrent.TS_STARTED) torrent.stop(); } }); } private void startSelectedTorrents() { tv.runForSelectedRows(new TableGroupRowRunner() { public void run(TableRowCore row) { TRHostTorrent torrent = (TRHostTorrent)row.getDataSource(true); if (torrent.getStatus() == TRHostTorrent.TS_STOPPED) torrent.start(); } }); } private void removeSelectedTorrents() { tv.runForSelectedRows(new TableGroupRowRunner() { public void run(TableRowCore row) { TRHostTorrent torrent = (TRHostTorrent)row.getDataSource(true); try{ torrent.remove(); }catch( TRHostTorrentRemovalVetoException f ){ Alerts.showErrorMessageBoxUsingResourceString( new Object[] { torrent }, "globalmanager.download.remove.veto", f, 0 ); } } }); } private void addCategorySubMenu() { MenuItem[] items = menuCategory.getItems(); int i; for (i = 0; i < items.length; i++) { items[i].dispose(); } Category[] categories = CategoryManager.getCategories(); Arrays.sort(categories); if (categories.length > 0) { Category catUncat = CategoryManager.getCategory(Category.TYPE_UNCATEGORIZED); if (catUncat != null) { final MenuItem itemCategory = new MenuItem(menuCategory, SWT.PUSH); Messages.setLanguageText(itemCategory, catUncat.getName()); itemCategory.setData("Category", catUncat); itemCategory.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { MenuItem item = (MenuItem)event.widget; assignSelectedToCategory((Category)item.getData("Category")); } }); new MenuItem(menuCategory, SWT.SEPARATOR); } for (i = 0; i < categories.length; i++) { if (categories[i].getType() == Category.TYPE_USER) { final MenuItem itemCategory = new MenuItem(menuCategory, SWT.PUSH); itemCategory.setText(categories[i].getName()); itemCategory.setData("Category", categories[i]); itemCategory.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { MenuItem item = (MenuItem)event.widget; assignSelectedToCategory((Category)item.getData("Category")); } }); } } new MenuItem(menuCategory, SWT.SEPARATOR); } final MenuItem itemAddCategory = new MenuItem(menuCategory, SWT.PUSH); Messages.setLanguageText(itemAddCategory, "MyTorrentsView.menu.setCategory.add"); itemAddCategory.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { addCategory(); } }); } public void categoryAdded(Category category) { Utils.execSWTThread( new AERunnable() { public void runSupport() { addCategorySubMenu(); } }); } public void categoryRemoved( Category category) { Utils.execSWTThread( new AERunnable() { public void runSupport() { addCategorySubMenu(); } }); } private void addCategory() { CategoryAdderWindow adderWindow = new CategoryAdderWindow(SWTThread.getInstance().getDisplay()); Category newCategory = adderWindow.getNewCategory(); if (newCategory != null) assignSelectedToCategory(newCategory); } private void assignSelectedToCategory(final Category category) { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(final AzureusCore core) { assignSelectedToCategory(core, category); } }); } private void assignSelectedToCategory(final AzureusCore core, final Category category) { tv.runForSelectedRows(new TableGroupRowRunner() { public void run(TableRowCore row) { TRHostTorrent tr_torrent = (TRHostTorrent)row.getDataSource(true); final TOTorrent torrent = tr_torrent.getTorrent(); DownloadManager dm = core.getGlobalManager().getDownloadManager( torrent ); if ( dm != null ){ dm.getDownloadState().setCategory( category ); }else{ String cat_str; if ( category == null ){ cat_str = null; }else if ( category == CategoryManager.getCategory(Category.TYPE_UNCATEGORIZED)){ cat_str = null; }else{ cat_str = category.getName(); } // bit of a hack-alert here TorrentUtils.setPluginStringProperty( torrent, "azcoreplugins.category", cat_str ); try{ TorrentUtils.writeToFile( torrent ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } }); } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#deselected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void deselected(TableRowCore[] rows) { computePossibleActions(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#focusChanged(com.aelitis.azureus.ui.common.table.TableRowCore) public void focusChanged(TableRowCore focus) { computePossibleActions(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#selected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void selected(TableRowCore[] rows) { computePossibleActions(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#mouseEnter(com.aelitis.azureus.ui.common.table.TableRowCore) public void mouseEnter(TableRowCore row) { } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#mouseExit(com.aelitis.azureus.ui.common.table.TableRowCore) public void mouseExit(TableRowCore row) { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/FilesView.java0000644000175000017500000006644611275141736023333 0ustar adrianadrian/* * Created on 17 juil. 2003 * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.*; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.download.DownloadManagerStateAttributeListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.views.file.FileInfoView; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab; import org.gudy.azureus2.ui.swt.views.tableitems.files.*; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import com.aelitis.azureus.core.AzureusCoreOperation; import com.aelitis.azureus.core.AzureusCoreOperationTask; import com.aelitis.azureus.ui.common.table.*; /** * @author Olivier * @author TuxPaper * 2004/Apr/23: extends TableView instead of IAbstractView */ public class FilesView extends TableViewTab implements TableDataSourceChangedListener, TableSelectionListener, TableViewSWTMenuFillListener, TableRefreshListener, DownloadManagerStateAttributeListener, TableLifeCycleListener { boolean refreshing = false; private DragSource dragSource = null; private static final TableColumnCore[] basicItems = { new NameItem(), new PathItem(), new SizeItem(), new DoneItem(), new PercentItem(), new FirstPieceItem(), new PieceCountItem(), new RemainingPiecesItem(), new ProgressGraphItem(), new ModeItem(), new PriorityItem(), new StorageTypeItem(), new FileExtensionItem(), }; private DownloadManager manager = null; public static boolean show_full_path; static{ COConfigurationManager.addAndFireParameterListener( "FilesView.show.full.path", new ParameterListener() { public void parameterChanged( String parameterName) { show_full_path = COConfigurationManager.getBooleanParameter( "FilesView.show.full.path" ); } }); } private MenuItem path_item; private TableViewSWT tv; /** * Initialize */ public FilesView() { super("FilesView"); } public TableViewSWT initYourTableView() { tv = new TableViewSWTImpl( org.gudy.azureus2.plugins.disk.DiskManagerFileInfo.class, TableManager.TABLE_TORRENT_FILES, getPropertiesPrefix(), basicItems, "firstpiece", SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL); tv.setRowDefaultIconSize(new Point(16, 16)); tv.setEnableTabViews(true); tv.setCoreTabViews(new IView[] { new FileInfoView() }); tv.addTableDataSourceChangedListener(this, true); tv.addRefreshListener(this, true); tv.addSelectionListener(this, false); tv.addMenuFillListener(this); tv.addLifeCycleListener(this); return tv; } // @see com.aelitis.azureus.ui.common.table.TableDataSourceChangedListener#tableDataSourceChanged(java.lang.Object) public void tableDataSourceChanged(Object newDataSource) { DownloadManager old_manager = manager; if (newDataSource == null) manager = null; else if (newDataSource instanceof Object[]) manager = (DownloadManager)((Object[])newDataSource)[0]; else manager = (DownloadManager)newDataSource; if (old_manager != null) { old_manager.getDownloadState().removeListener(this, DownloadManagerState.AT_FILE_LINKS, DownloadManagerStateAttributeListener.WRITTEN); } if (manager != null) { manager.getDownloadState().addListener(this, DownloadManagerState.AT_FILE_LINKS, DownloadManagerStateAttributeListener.WRITTEN); } tv.removeAllTableRows(); } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#deselected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void deselected(TableRowCore[] rows) { } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#focusChanged(com.aelitis.azureus.ui.common.table.TableRowCore) public void focusChanged(TableRowCore focus) { } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#selected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void selected(TableRowCore[] rows) { } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#defaultSelected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void defaultSelected(TableRowCore[] rows, int stateMask) { DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) tv.getFirstSelectedDataSource(); if (fileInfo != null && fileInfo.getAccessMode() == DiskManagerFileInfo.READ) Utils.launch(fileInfo.getFile(true).toString()); } // @see org.gudy.azureus2.ui.swt.views.TableViewSWTMenuFillListener#fillMenu(org.eclipse.swt.widgets.Menu) public void fillMenu(String sColumnName, final Menu menu) { Shell shell = menu.getShell(); Object[] data_sources = tv.getSelectedDataSources().toArray(); boolean hasSelection = (data_sources.length > 0); final MenuItem itemOpen = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemOpen, "FilesView.menu.open"); Utils.setMenuItemImage(itemOpen, "run"); // Invoke open on enter, double click menu.setDefaultItem(itemOpen); // Explore (Copied from MyTorrentsView) final boolean use_open_containing_folder = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled"); final MenuItem itemExplore = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemExplore, "MyTorrentsView.menu." + (use_open_containing_folder ? "open_parent_folder" : "explore")); itemExplore.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { Object[] dataSources = tv.getSelectedDataSources().toArray(); for (int i = dataSources.length - 1; i >= 0; i--) { DiskManagerFileInfo info = (DiskManagerFileInfo)dataSources[i]; if (info != null) { File this_file = info.getFile(true); File parent_file = (use_open_containing_folder) ? this_file.getParentFile() : null; ManagerUtils.open((parent_file == null) ? this_file : parent_file); } } } }); itemExplore.setEnabled(hasSelection); MenuItem itemRenameOrRetarget = null, itemRename = null, itemRetarget = null; itemRenameOrRetarget = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemRenameOrRetarget, "FilesView.menu.rename"); itemRenameOrRetarget.setData("rename", Boolean.valueOf(true)); itemRenameOrRetarget.setData("retarget", Boolean.valueOf(true)); itemRename = new MenuItem(menu, SWT.PUSH); itemRetarget = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemRename, "FilesView.menu.rename_only"); Messages.setLanguageText(itemRetarget, "FilesView.menu.retarget"); itemRename.setData("rename", Boolean.valueOf(true)); itemRename.setData("retarget", Boolean.valueOf(false)); itemRetarget.setData("rename", Boolean.valueOf(false)); itemRetarget.setData("retarget", Boolean.valueOf(true)); final MenuItem itemPriority = new MenuItem(menu, SWT.CASCADE); Messages.setLanguageText(itemPriority, "FilesView.menu.setpriority"); //$NON-NLS-1$ final Menu menuPriority = new Menu(shell, SWT.DROP_DOWN); itemPriority.setMenu(menuPriority); final MenuItem itemHigh = new MenuItem(menuPriority, SWT.CASCADE); itemHigh.setData("Priority", new Integer(0)); Messages.setLanguageText(itemHigh, "FilesView.menu.setpriority.high"); //$NON-NLS-1$ final MenuItem itemLow = new MenuItem(menuPriority, SWT.CASCADE); itemLow.setData("Priority", new Integer(1)); Messages.setLanguageText(itemLow, "FilesView.menu.setpriority.normal"); //$NON-NLS-1$ final MenuItem itemSkipped = new MenuItem(menuPriority, SWT.CASCADE); itemSkipped.setData("Priority", new Integer(2)); Messages.setLanguageText(itemSkipped, "FilesView.menu.setpriority.skipped"); //$NON-NLS-1$ final MenuItem itemDelete = new MenuItem(menuPriority, SWT.CASCADE); itemDelete.setData("Priority", new Integer(3)); Messages.setLanguageText(itemDelete, "wizard.multitracker.delete"); // lazy but we're near release new MenuItem(menu, SWT.SEPARATOR); if (!hasSelection) { itemOpen.setEnabled(false); itemPriority.setEnabled(false); itemRenameOrRetarget.setEnabled(false); itemRename.setEnabled(false); itemRetarget.setEnabled(false); return; } boolean open = true; boolean all_compact = true; boolean all_skipped = true; boolean all_priority = true; boolean all_not_priority = true; DiskManagerFileInfo[] dmi_array = new DiskManagerFileInfo[data_sources.length]; System.arraycopy(data_sources, 0, dmi_array, 0, data_sources.length); int[] storage_types = manager.getStorageType(dmi_array); for (int i = 0; i < dmi_array.length; i++) { DiskManagerFileInfo file_info = dmi_array[i]; if (open && file_info.getAccessMode() != DiskManagerFileInfo.READ) { open = false; } if (all_compact && storage_types[i] != DiskManagerFileInfo.ST_COMPACT) { all_compact = false; } if (all_skipped || all_priority || all_not_priority) { if ( file_info.isSkipped()){ all_priority = false; all_not_priority = false; }else{ all_skipped = false; // Only do this check if we need to. if (all_not_priority || all_priority) { if (file_info.isPriority()){ all_not_priority = false; }else{ all_priority = false; } } } } } // we can only open files if they are read-only itemOpen.setEnabled(open); // can't rename files for non-persistent downloads (e.g. shares) as these // are managed "externally" itemRenameOrRetarget.setEnabled(manager.isPersistent()); itemRename.setEnabled(manager.isPersistent()); itemRetarget.setEnabled(manager.isPersistent()); itemSkipped.setEnabled( !all_skipped ); itemHigh.setEnabled( !all_priority ); itemLow.setEnabled( !all_not_priority ); itemDelete.setEnabled( !all_compact ); itemOpen.addListener(SWT.Selection, new TableSelectedRowsListener(tv) { public void run(TableRowCore row) { DiskManagerFileInfo fileInfo = (DiskManagerFileInfo)row.getDataSource(true); if (fileInfo.getAccessMode() == DiskManagerFileInfo.READ) { Utils.launch(fileInfo.getFile(true).toString()); } } }); Listener rename_listener = new Listener() { public void handleEvent(Event event) { final boolean rename_it = ((Boolean)event.widget.getData("rename")).booleanValue(); final boolean retarget_it = ((Boolean)event.widget.getData("retarget")).booleanValue(); final TableRowCore[] selectedRows = tv.getSelectedRows(); rename(selectedRows, rename_it, retarget_it); } }; itemRenameOrRetarget.addListener(SWT.Selection, rename_listener); itemRename.addListener(SWT.Selection, rename_listener); itemRetarget.addListener(SWT.Selection, rename_listener); Listener priorityListener = new Listener() { public void handleEvent(Event event) { final int priority = ((Integer) event.widget.getData("Priority")).intValue(); final TableRowCore[] selectedRows = tv.getSelectedRows(); Utils.getOffOfSWTThread(new AERunnable(){ public void runSupport() { changePriority(priority, selectedRows); } }); } }; itemHigh.addListener(SWT.Selection, priorityListener); itemLow.addListener(SWT.Selection, priorityListener); itemSkipped.addListener(SWT.Selection, priorityListener); itemDelete.addListener(SWT.Selection, priorityListener); } private String askForRenameFilename(DiskManagerFileInfo fileInfo) { SimpleTextEntryWindow dialog = new SimpleTextEntryWindow( "FilesView.rename.filename.title", "FilesView.rename.filename.text"); dialog.setPreenteredText(fileInfo.getFile(true).getName(), false); // false -> it's not "suggested", it's a previous value dialog.allowEmptyInput(false); dialog.prompt(); if (!dialog.hasSubmittedInput()) {return null;} return dialog.getSubmittedInput(); } private String askForRetargetedFilename(DiskManagerFileInfo fileInfo) { FileDialog fDialog = new FileDialog(Utils.findAnyShell(), SWT.SYSTEM_MODAL | SWT.SAVE); File existing_file = fileInfo.getFile(true); fDialog.setFilterPath(existing_file.getParent()); fDialog.setFileName(existing_file.getName()); fDialog.setText(MessageText.getString("FilesView.rename.choose.path")); return fDialog.open(); } private String askForSaveDirectory(DiskManagerFileInfo fileInfo) { DirectoryDialog dDialog = new DirectoryDialog(Utils.findAnyShell(), SWT.SYSTEM_MODAL | SWT.SAVE); File current_dir = fileInfo.getFile(true).getParentFile(); dDialog.setFilterPath(current_dir.getPath()); dDialog.setText(MessageText.getString("FilesView.rename.choose.path.dir")); return dDialog.open(); } private boolean askCanOverwrite(File file) { MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.CANCEL, MessageText.getString("FilesView.rename.confirm.delete.title"), MessageText.getString("FilesView.rename.confirm.delete.text", new String[] { file.toString() })); mb.setDefaultButtonUsingStyle(SWT.OK); mb.setRememberOnlyIfButton(0); mb.setRemember("FilesView.messagebox.rename.id", true, null); mb.setLeftImage(SWT.ICON_WARNING); mb.open(null); return mb.waitUntilClosed() == SWT.OK; } // same code is used in tableitems.files.NameItem private void moveFile(final DiskManagerFileInfo fileInfo, final File target) { // this behaviour should be put further down in the core but I'd rather not // do so close to release :( final boolean[] result = { false }; is_changing_links = true; FileUtil.runAsTask(new AzureusCoreOperationTask() { public void run(AzureusCoreOperation operation) { result[0] = fileInfo.setLink(target); } } ); is_changing_links = false; if (!result[0]){ new MessageBoxShell(SWT.ICON_ERROR | SWT.OK, MessageText.getString("FilesView.rename.failed.title"), MessageText.getString("FilesView.rename.failed.text")).open(null); } } protected void rename(TableRowCore[] rows, boolean rename_it, boolean retarget_it) { if (manager == null) {return;} if (rows.length == 0) {return;} String save_dir = null; if (!rename_it && retarget_it) { save_dir = askForSaveDirectory((DiskManagerFileInfo)rows[0].getDataSource(true)); if (save_dir == null) {return;} } boolean paused = false; try { for (int i=0; i 1) { } // This should hopefully reduce the number of "exists" checks. File save_location = manager.getAbsoluteSaveLocation(); boolean root_exists = save_location.isDirectory() || (infos.length <= 1 && save_location.exists()); boolean type_has_been_changed = false; boolean requires_pausing = false; for (int i=0; i 0) ok &= Arrays.equals(setLinear, manager.getDiskManagerFileInfoSet().setStorageTypes(setLinear, DiskManagerFileInfo.ST_LINEAR)); if(compactCount > 0) ok &= Arrays.equals(setCompact, manager.getDiskManagerFileInfoSet().setStorageTypes(setCompact, DiskManagerFileInfo.ST_COMPACT)); } if (ok) { for (int i=0; i datasources = tv.getDataSources(); if(datasources.size() == files.length) { // check if we actually have to replace anything ArrayList toAdd = new ArrayList(Arrays.asList(files)); ArrayList toRemove = new ArrayList(); for(int i = 0;i < datasources.size();i++) { DiskManagerFileInfo info = datasources.get(i); if(files[info.getIndex()] == info) toAdd.set(info.getIndex(), null); else toRemove.add(info); } tv.removeDataSources(toRemove.toArray(new DiskManagerFileInfo[toRemove.size()])); tv.addDataSources(toAdd.toArray(new DiskManagerFileInfo[toAdd.size()])); ((TableViewSWTImpl)tv).tableInvalidate(); } else { tv.removeAllTableRows(); DiskManagerFileInfo filesCopy[] = new DiskManagerFileInfo[files.length]; System.arraycopy(files, 0, filesCopy, 0, files.length); tv.addDataSources(filesCopy); } tv.processDataSourceQueue(); } } finally { refreshing = false; } } /** * @param files * @return * * @since 3.0.0.7 */ private boolean doAllExist(DiskManagerFileInfo[] files) { for (int i = 0; i < files.length; i++) { DiskManagerFileInfo fileinfo = files[i]; // We can't just use tv.dataSourceExists(), since it does a .equals() // comparison, and we want a reference comparison TableRowCore row = tv.getRow(fileinfo); if (row == null) { return false; } // reference comparison if (row.getDataSource(true) != fileinfo) { return false; } } return true; } /* SubMenu for column specific tasks. */ public void addThisColumnSubMenu(String sColumnName, Menu menuThisColumn) { if (sColumnName.equals("path")) { path_item = new MenuItem( menuThisColumn, SWT.CHECK ); path_item.setSelection( show_full_path ); Messages.setLanguageText(path_item, "FilesView.fullpath"); path_item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { show_full_path = path_item.getSelection(); tv.columnInvalidate("path"); tv.refreshTable(false); COConfigurationManager.setParameter( "FilesView.show.full.path", show_full_path ); } }); } } private DiskManagerFileInfo[] getFileInfo() { if (manager == null) return null; return( manager.getDiskManagerFileInfo()); } // Used to notify us of when we need to refresh - normally for external changes to the // file links. private boolean is_changing_links = false; public void attributeEventOccurred(DownloadManager dm, String attribute_name, int event_type) { if (is_changing_links) {return;} this.force_refresh = true; } public void tableViewInitialized() { createDragDrop(); } public void tableViewDestroyed() { Utils.execSWTThread(new AERunnable() { public void runSupport() { try { Utils.disposeSWTObjects(new Object[] { dragSource, }); dragSource = null; } catch (Exception e) { Debug.out(e); } } }); if (manager != null) { manager.getDownloadState().removeListener(this, DownloadManagerState.AT_FILE_LINKS, DownloadManagerStateAttributeListener.WRITTEN); } } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#mouseEnter(com.aelitis.azureus.ui.common.table.TableRowCore) public void mouseEnter(TableRowCore row) { } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#mouseExit(com.aelitis.azureus.ui.common.table.TableRowCore) public void mouseExit(TableRowCore row) { } private void createDragDrop() { try { Transfer[] types = new Transfer[] { TextTransfer.getInstance() }; if (dragSource != null && !dragSource.isDisposed()) { dragSource.dispose(); } dragSource = tv.createDragSource(DND.DROP_MOVE | DND.DROP_COPY); if (dragSource != null) { dragSource.setTransfer(types); dragSource.addDragListener(new DragSourceAdapter() { private String eventData; public void dragStart(DragSourceEvent event) { TableRowCore[] rows = tv.getSelectedRows(); if (rows.length != 0 && manager != null && manager.getTorrent() != null) { event.doit = true; } else { event.doit = false; return; } // Build eventData here because on OSX, selection gets cleared // by the time dragSetData occurs Object[] selectedDownloads = tv.getSelectedDataSources().toArray(); eventData = "DiskManagerFileInfo\n"; TOTorrent torrent = manager.getTorrent(); for (int i = 0; i < selectedDownloads.length; i++) { DiskManagerFileInfo fi = (DiskManagerFileInfo) selectedDownloads[i]; try { eventData += torrent.getHashWrapper().toBase32String() + ";" + fi.getIndex() + "\n"; } catch (Exception e) { } } } public void dragSetData(DragSourceEvent event) { // System.out.println("DragSetData"); event.data = eventData; } }); } } catch (Throwable t) { Logger.log(new LogEvent(LogIDs.GUI, "failed to init drag-n-drop", t)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/ManagerView.java0000644000175000017500000004205011310376010023605 0ustar adrianadrian/* * Created on 2 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views; import java.util.ArrayList; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerListener; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerAdapter; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.pluginsimpl.local.download.DownloadImpl; import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl; import org.gudy.azureus2.ui.swt.IconBarEnabler; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.debug.ObfusticateImage; import org.gudy.azureus2.ui.swt.debug.ObfusticateTab; import org.gudy.azureus2.ui.swt.plugins.*; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import org.gudy.azureus2.plugins.download.DownloadException; /** * Torrent download view, consisting of several information tabs * * @author Olivier * */ public class ManagerView implements DownloadManagerListener, ObfusticateTab, ObfusticateImage, ViewTitleInfo, UISWTViewCoreEventListener, IconBarEnabler, UIUpdatable { private DownloadManager manager; private CTabFolder folder; private ArrayList tabViews = new ArrayList(); int lastCompleted = -1; private UISWTView swtView; private GlobalManagerAdapter gmListener; private Composite parent; protected IView activeView; /** * */ public ManagerView() { // assumed if we are opening a Download Manager View that we // have a DownloadManager and thus an AzureusCore GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); gmListener = new GlobalManagerAdapter() { public void downloadManagerRemoved(DownloadManager dm) { if (dm.equals(manager)) { Utils.execSWTThread(new AERunnable() { public void runSupport() { delete(); } }); } } }; gm.addListener(gmListener, false); UIFunctionsManagerSWT.getUIFunctionsSWT().getUIUpdater().addUpdater(this); } private void dataSourceChanged(Object newDataSource) { if (manager != null) { manager.removeListener(this); } DownloadImpl dataSourcePlugin = null; if (newDataSource instanceof DownloadImpl) { dataSourcePlugin = (DownloadImpl) newDataSource; manager = dataSourcePlugin.getDownload(); } else if (newDataSource instanceof DownloadManager) { manager = (DownloadManager) newDataSource; try { dataSourcePlugin = DownloadManagerImpl.getDownloadStatic(manager); } catch (DownloadException e) { /* Ignore */ } } else { manager = null; } if (manager != null) { manager.addListener(this); } for (int i = 0; i < tabViews.size(); i++) { IView view = (IView) tabViews.get(i); if (view != null) { if (view instanceof UISWTViewImpl) { ((UISWTViewImpl) view).dataSourceChanged(dataSourcePlugin); } else { view.dataSourceChanged(newDataSource); } } } refreshTitle(); ViewTitleInfoManager.refreshTitleInfo(this); } private void delete() { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.removeManagerView(manager); uiFunctions.getUIUpdater().removeUpdater(this); } if (manager != null) { manager.removeListener(this); } try { GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); gm.removeListener(gmListener); } catch (Exception e) { Debug.out(e); } if (folder != null && !folder.isDisposed()){ folder.setSelection(0); } //Don't ask me why, but without this an exception is thrown further // (in folder.dispose() ) //TODO : Investigate to see if it's a platform (OSX-Carbon) BUG, and report to SWT team. if(Utils.isCarbon) { if(folder != null && !folder.isDisposed()) { CTabItem[] items = folder.getItems(); for(int i=0 ; i < items.length ; i++) { if (!items[i].isDisposed()) items[i].dispose(); } } } for (int i = 0; i < tabViews.size(); i++) { IView view = (IView) tabViews.get(i); try { if (view != null) { view.delete(); } } catch (Throwable t) { Debug.out(t); } } tabViews.clear(); Utils.disposeSWTObjects(new Object[] { folder, parent }); } private void initialize(Composite composite) { this.parent = composite; if (folder == null) { folder = new CTabFolder(composite, SWT.LEFT); folder.setBorderVisible(true); } else { System.out.println("ManagerView::initialize : folder isn't null !!!"); } if (composite.getLayout() instanceof FormLayout) { folder.setLayoutData(Utils.getFilledFormData()); } else if (composite.getLayout() instanceof GridLayout) { folder.setLayoutData(new GridData(GridData.FILL_BOTH)); } Label lblClose = new Label(folder, SWT.WRAP); lblClose.setText("x"); lblClose.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event event) { delete(); } }); folder.setTopRight(lblClose); folder.setTabHeight(20); ArrayList iviews_to_use = new ArrayList(); iviews_to_use.add(new GeneralView()); iviews_to_use.add(new PeersView()); iviews_to_use.add(new PeersGraphicView()); iviews_to_use.add(new PiecesView()); iviews_to_use.add(new FilesView()); iviews_to_use.add(new TorrentInfoView()); iviews_to_use.add(new TorrentOptionsView()); if (Logger.isEnabled()) { iviews_to_use.add(new LoggerView(true)); } final IView[] views = (IView[])iviews_to_use.toArray(new IView[iviews_to_use.size()]); for (int i = 0; i < views.length; i++) addSection(views[i], manager); // Call plugin listeners UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { UISWTInstanceImpl pluginUI = uiFunctions.getSWTPluginInstanceImpl(); Map pluginViews = pluginUI == null ? null : pluginUI.getViewListeners(UISWTInstance.VIEW_MYTORRENTS); if (pluginViews != null) { String[] sNames = (String[]) pluginViews.keySet().toArray(new String[0]); for (int i = 0; i < sNames.length; i++) { UISWTViewEventListener l = (UISWTViewEventListener) pluginViews.get(sNames[i]); if (l != null) { try { UISWTViewImpl view = new UISWTViewImpl( UISWTInstance.VIEW_MYTORRENTS, sNames[i], l); addSection(view); } catch (Exception e) { // skip } } } } } // Initialize view when user selects it folder.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { folder.getShell().setCursor(e.display.getSystemCursor(SWT.CURSOR_WAIT)); try { // Send one last refresh to previous tab, just in case it // wants to do something when view goes invisible refresh(); CTabItem item = (CTabItem)e.item; if (item != null) { IView view = (IView)item.getData("IView"); activeView = view; if (item.getControl() == null) { view.initialize(folder); item.setControl(view.getComposite()); } item.getControl().setFocus(); } refresh(); ViewTitleInfoManager.refreshTitleInfo(ManagerView.this); } finally { folder.getShell().setCursor(null); } } }); Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { views[0].initialize(folder); folder.getItem(0).setControl(views[0].getComposite()); views[0].refresh(); views[0].getComposite().layout(true); views[0].getComposite().setFocus(); activeView = views[0]; ViewTitleInfoManager.refreshTitleInfo(ManagerView.this); } }); } private IView getActiveView() { return activeView; } /** * Called when view is visible */ private void refresh() { if (folder == null || folder.isDisposed()) return; try { IView view = getActiveView(); if (view != null) view.refresh(); CTabItem[] items = folder.getItems(); for (int i = 0; i < items.length; i++) { CTabItem item = items[i]; view = (IView) item.getData("IView"); try { if (item.isDisposed()) continue; String lastTitle = item.getText(); String newTitle = view.getShortTitle(); if (lastTitle == null || !lastTitle.equals(newTitle)) { item.setText(escapeAccelerators(newTitle)); } String lastToolTip = item.getToolTipText(); String newToolTip = view.getFullTitle(); if (lastToolTip == null || !lastToolTip.equals(newToolTip)) { item.setToolTipText(newToolTip); } } catch (Exception e){ Debug.printStackTrace(e); } } UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); // For edit columns view } } catch (Exception e) { Debug.printStackTrace(e); } } /** * * * @since 3.1.0.1 */ private void refreshTitle() { if (swtView != null) { int completed = manager == null ? -1 : manager.getStats().getCompleted(); if (lastCompleted != completed) { swtView.setTitle(DisplayFormatters.formatPercentFromThousands(completed) + " : " + manager.getDisplayName()); ViewTitleInfoManager.refreshTitleInfo(this); } } } protected static String escapeAccelerators( String str ) { if ( str == null ){ return( str ); } return( str.replaceAll( "&", "&&" )); } public boolean isEnabled(String itemKey) { if (itemKey.equals("run")) return true; if (itemKey.equals("start")) return ManagerUtils.isStartable(manager); if (itemKey.equals("stop")) return ManagerUtils.isStopable(manager); if (itemKey.equals("remove")) return true; if (itemKey.equals("editcolumns")) { IView active_view = getActiveView(); if (active_view != null) { return active_view.isEnabled(itemKey); } } return false; } public void itemActivated(String itemKey) { if (itemKey.equals("run")) { ManagerUtils.run(manager); return; } if (itemKey.equals("start")) { ManagerUtils.queue(manager, folder.getShell()); return; } if (itemKey.equals("stop")) { ManagerUtils.stop(manager, folder.getShell()); return; } if (itemKey.equals("remove")) { ManagerUtils.remove(manager, null, false, false); return; } if (itemKey.equals("editcolumns")) { IView active_view = getActiveView(); if (active_view != null) { active_view.itemActivated(itemKey); return; } } } public void downloadComplete(DownloadManager manager) { } public void completionChanged(DownloadManager manager, boolean bCompleted) { } public void filePriorityChanged( DownloadManager download, org.gudy.azureus2.core3.disk.DiskManagerFileInfo file ) { } public void stateChanged(DownloadManager manager, int state) { if(folder == null || folder.isDisposed()) return; Display display = folder.getDisplay(); if(display == null || display.isDisposed()) return; Utils.execSWTThread(new AERunnable() { public void runSupport() { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } }); } public void positionChanged(DownloadManager download, int oldPosition, int newPosition) { } public void addSection(UISWTViewImpl view) { Object pluginDataSource = null; try { pluginDataSource = DownloadManagerImpl.getDownloadStatic(manager); } catch (DownloadException e) { /* Ignore */ } addSection(view, pluginDataSource); } private void addSection(IView view, Object dataSource) { if (view == null) return; view.dataSourceChanged(dataSource); CTabItem item = new CTabItem(folder, SWT.NULL); Messages.setLanguageText(item, view.getData()); item.setData("IView", view); tabViews.add(view); } public Image obfusticatedImage(Image image, Point shellOffset) { IView view = getActiveView(); if (view instanceof ObfusticateImage) { try { ((ObfusticateImage)view).obfusticatedImage(image, shellOffset); } catch (Exception e) { Debug.out("Obfusticating " + view, e); } } return image; } public String getObfusticatedHeader() { int completed = manager.getStats().getCompleted(); return DisplayFormatters.formatPercentFromThousands(completed) + " : " + manager; } public DownloadManager getDownload() {return manager;} // @see com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo#getTitleInfoProperty(int) public Object getTitleInfoProperty(int propertyID) { if (propertyID == TITLE_TEXT) { return manager == null ? "" : manager.getDisplayName(); } if (manager == null) { return null; } if (propertyID == TITLE_INDICATOR_TEXT) { int completed = manager.getStats().getCompleted(); if (completed != 1000) { return (completed / 10) + "%"; } } else if (propertyID == TITLE_INDICATOR_TEXT_TOOLTIP) { String s = ""; int completed = manager.getStats().getCompleted(); if (completed != 1000) { s = (completed / 10) + "% Complete\n"; } String eta = DisplayFormatters.formatETA(manager.getStats().getETA()); if (eta.length() > 0) { s += MessageText.getString("TableColumn.header.eta") + ": " + eta + "\n"; } return s; } else if (propertyID == TITLE_LOGID) { String id; if (activeView instanceof UISWTViewImpl) { id = "" + ((UISWTViewImpl)activeView).getViewID(); id = id.substring(id.lastIndexOf(".")+1); } else if (activeView != null) { String simpleName = activeView.getClass().getName(); id = simpleName.substring(simpleName.lastIndexOf(".")+1); } else { id = "??"; } return "DMDetails-" + id; } return null; } public boolean eventOccurred(UISWTViewEvent event) { switch (event.getType()) { case UISWTViewEvent.TYPE_CREATE: swtView = (UISWTView)event.getData(); break; case UISWTViewEvent.TYPE_DESTROY: delete(); break; case UISWTViewEvent.TYPE_INITIALIZE: initialize((Composite)event.getData()); break; case UISWTViewEvent.TYPE_LANGUAGEUPDATE: Messages.updateLanguageForControl(folder); break; case UISWTViewEvent.TYPE_DATASOURCE_CHANGED: dataSourceChanged(event.getData()); break; case UISWTViewEvent.TYPE_REFRESH: refresh(); break; } return true; } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#isSelected(java.lang.String) public boolean isSelected(String itemKey) { return false; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { return "DMDetails"; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI() public void updateUI() { refreshTitle(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/ConfigView.java0000644000175000017500000007501711172266532023466 0ustar adrianadrian/* * Created on 2 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.util.Timer; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.plugins.ui.config.ConfigSectionSWT; import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionRepository; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.ui.swt.views.configsections.*; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author Olivier * */ public class ConfigView extends AbstractIView { private static final LogIDs LOGID = LogIDs.GUI; public static final String sSectionPrefix = "ConfigView.section."; Map sections = new HashMap(); // Only access on SWT Thread java.util.List sectionsCreated = new ArrayList(1); Composite cConfig; Composite cConfigSection; StackLayout layoutConfigSection; Label lHeader; Label usermodeHint; Font headerFont; Font filterFoundFont; Tree tree; ArrayList pluginSections; private Timer filterDelayTimer; private String filterText = ""; private Label lblX; private Listener scResizeListener; private Image imgSmallX; private Image imgSmallXGray; public ConfigView() { } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IView#initialize(org.eclipse.swt.widgets.Composite) */ public void initialize(final Composite composite) { // need to initalize composite now, since getComposite can // be called at any time cConfig = new Composite(composite, SWT.NONE); _initialize(composite); } public void _initialize(Composite composite) { GridData gridData; /* /--cConfig-----------------------------------------------------------\ | ###SashForm#form################################################## | | # /--cLeftSide-\ /--cRightSide---------------------------------\ # | | # |txtFilter X | | ***cHeader********************************* | # | | # | ##tree#### | | * lHeader usermodeHint * | # | | # | # # | | ******************************************* | # | | # | # # | | ###Composite cConfigSection################ | # | | # | # # | | # # | # | | # | # # | | # # | # | | # | # # | | # # | # | | # | # # | | # # | # | | # | ########## | | ########################################### | # | | # \------------/ \---------------------------------------------/ # | | ################################################################## | | [Button] | \--------------------------------------------------------------------/ */ try { Display d = composite.getDisplay(); GridLayout configLayout = new GridLayout(); configLayout.marginHeight = 0; configLayout.marginWidth = 0; cConfig.setLayout(configLayout); gridData = new GridData(GridData.FILL_BOTH); cConfig.setLayoutData(gridData); SashForm form = new SashForm(cConfig,SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_BOTH); form.setLayoutData(gridData); Composite cLeftSide = new Composite(form, SWT.BORDER); gridData = new GridData(GridData.FILL_BOTH); cLeftSide.setLayoutData(gridData); FormLayout layout = new FormLayout(); cLeftSide.setLayout(layout); Composite cFilterArea = new Composite(cLeftSide, SWT.NONE); cFilterArea.setLayout(new FormLayout()); final Text txtFilter = new Text(cFilterArea, SWT.BORDER); final String sFilterText = MessageText.getString("ConfigView.filter"); txtFilter.setText(sFilterText); txtFilter.selectAll(); txtFilter.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { filterTree(txtFilter.getText()); } }); txtFilter.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { if (txtFilter.getText().equals(sFilterText)) { txtFilter.selectAll(); } } }); txtFilter.setFocus(); ImageLoader imageLoader = ImageLoader.getInstance(); imgSmallXGray = imageLoader.getImage("smallx-gray"); imgSmallX = imageLoader.getImage("smallx"); lblX = new Label(cFilterArea, SWT.WRAP); Messages.setLanguageTooltip(lblX, "MyTorrentsView.clearFilter.tooltip"); lblX.setImage(imgSmallXGray); lblX.addMouseListener(new MouseAdapter() { public void mouseUp(MouseEvent e) { txtFilter.setText(""); } }); Label lblSearch = new Label(cFilterArea, SWT.NONE); imageLoader.setLabelImage(lblSearch, "search"); tree = new Tree(cLeftSide, SWT.NONE); FontData[] fontData = tree.getFont().getFontData(); fontData[0].setStyle(SWT.BOLD); filterFoundFont = new Font(d, fontData); FormData formData; formData = new FormData(); formData.bottom = new FormAttachment(100, -5); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); cFilterArea.setLayoutData(formData); formData = new FormData(); formData.top = new FormAttachment(0,5); formData.left = new FormAttachment(0, 5); lblSearch.setLayoutData(formData); formData = new FormData(); formData.top = new FormAttachment(0,5); formData.left = new FormAttachment(lblSearch,5); formData.right = new FormAttachment(lblX, -3); txtFilter.setLayoutData(formData); formData = new FormData(); formData.top = new FormAttachment(0,5); formData.right = new FormAttachment(100,-5); lblX.setLayoutData(formData); formData = new FormData(); formData.top = new FormAttachment(0, 0); formData.left = new FormAttachment(0,0); formData.right = new FormAttachment(100,0); formData.bottom = new FormAttachment(cFilterArea,-1); tree.setLayoutData(formData); Composite cRightSide = new Composite(form, SWT.NULL); configLayout = new GridLayout(); configLayout.marginHeight = 3; configLayout.marginWidth = 0; cRightSide.setLayout(configLayout); // Header Composite cHeader = new Composite(cRightSide, SWT.BORDER); configLayout = new GridLayout(); configLayout.marginHeight = 3; configLayout.marginWidth = 0; configLayout.numColumns = 2; configLayout.marginRight = 5; cHeader.setLayout(configLayout); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER); cHeader.setLayoutData(gridData); cHeader.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION)); cHeader.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); lHeader = new Label(cHeader, SWT.NULL); lHeader.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION)); lHeader.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); fontData = lHeader.getFont().getFontData(); fontData[0].setStyle(SWT.BOLD); int fontHeight = (int)(fontData[0].getHeight() * 1.2); fontData[0].setHeight(fontHeight); headerFont = new Font(d, fontData); lHeader.setFont(headerFont); gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_BEGINNING); lHeader.setLayoutData(gridData); usermodeHint = new Label(cHeader, SWT.NULL); usermodeHint.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION)); usermodeHint.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_END | GridData.GRAB_HORIZONTAL); usermodeHint.setLayoutData(gridData); // Config Section cConfigSection = new Composite(cRightSide, SWT.NULL); layoutConfigSection = new StackLayout(); cConfigSection.setLayout(layoutConfigSection); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalIndent = 2; cConfigSection.setLayoutData(gridData); form.setWeights(new int[] {20,80}); tree.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Tree tree = (Tree)e.getSource(); //Check that at least an item is selected //OSX lets you select nothing in the tree for example when a child is selected //and you close its parent. if(tree.getSelection().length > 0) showSection(tree.getSelection()[0]); } }); // Double click = expand/contract branch tree.addListener(SWT.DefaultSelection, new Listener() { public void handleEvent(Event e) { TreeItem item = (TreeItem)e.item; if (item != null) item.setExpanded(!item.getExpanded()); } }); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "Error initializing ConfigView", e)); } scResizeListener = new Listener() { public void handleEvent(Event event) { setupSC((ScrolledComposite)event.widget); } }; // Add sections /** How to add a new section * 1) Create a new implementation of ConfigSectionSWT in a new file * (Use the ConfigSectionTMP.java as a template if it's still around) * 2) import it into here * 3) add it to the internal sections list */ pluginSections = ConfigSectionRepository.getInstance().getList(); ConfigSection[] internalSections = { new ConfigSectionMode(), new ConfigSectionConnection(), new ConfigSectionConnectionProxy(), new ConfigSectionConnectionAdvanced(), new ConfigSectionConnectionEncryption(), new ConfigSectionTransfer(), new ConfigSectionTransferAutoSpeedSelect(), new ConfigSectionTransferAutoSpeed(), new ConfigSectionTransferAutoSpeedBeta(), new ConfigSectionTransferLAN(), new ConfigSectionFile(), new ConfigSectionFileMove(), new ConfigSectionFileTorrents(), new ConfigSectionFileTorrentsDecoding(), new ConfigSectionFilePerformance(), new ConfigSectionInterface(), new ConfigSectionInterfaceLanguage(), new ConfigSectionInterfaceStart(), new ConfigSectionInterfaceDisplay(), new ConfigSectionInterfaceColor(), new ConfigSectionInterfaceAlerts(), new ConfigSectionInterfacePassword(), new ConfigSectionInterfaceLegacy(), new ConfigSectionIPFilter(), new ConfigSectionPlugins(this), new ConfigSectionStats(), new ConfigSectionTracker(), new ConfigSectionTrackerClient(), new ConfigSectionTrackerServer(), new ConfigSectionSecurity(), new ConfigSectionSharing(), new ConfigSectionLogging() }; pluginSections.addAll(0, Arrays.asList(internalSections)); for (int i = 0; i < pluginSections.size(); i++) { // slip the non-standard "plugins" initialisation inbetween the internal ones // and the plugin ones so plugin ones can be children of it boolean plugin_section = i >= internalSections.length; ConfigSection section = (ConfigSection)pluginSections.get(i); if (section instanceof ConfigSectionSWT || section instanceof UISWTConfigSection ) { String name; try { name = section.configSectionGetName(); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "A ConfigSection plugin caused an " + "error while trying to call its " + "configSectionGetName function", e)); name = "Bad Plugin"; } String section_key = name; if ( plugin_section ){ // if resource exists without prefix then use it as plugins don't // need to start with the prefix if ( !MessageText.keyExists(section_key)){ section_key = sSectionPrefix + name; } }else{ section_key = sSectionPrefix + name; } try { TreeItem treeItem; String location = section.configSectionGetParentSection(); if (location.equalsIgnoreCase(ConfigSection.SECTION_ROOT)) treeItem = new TreeItem(tree, SWT.NULL); else if (location != "") { TreeItem treeItemFound = findTreeItem(tree, location); if (treeItemFound != null){ if (location.equalsIgnoreCase(ConfigSection.SECTION_PLUGINS)) { // Force ordering by name here. int position = findInsertPointFor(MessageText.getString(section_key), treeItemFound); if (position == -1) { treeItem = new TreeItem(treeItemFound, SWT.NULL); } else { treeItem = new TreeItem(treeItemFound, SWT.NULL, position); } } else { treeItem = new TreeItem(treeItemFound, SWT.NULL); } }else{ treeItem = new TreeItem(tree, SWT.NULL); } }else{ treeItem = new TreeItem(tree, SWT.NULL); } ScrolledComposite sc = new ScrolledComposite(cConfigSection, SWT.H_SCROLL | SWT.V_SCROLL); sc.setExpandHorizontal(true); sc.setExpandVertical(true); sc.setLayoutData(new GridData(GridData.FILL_BOTH)); sc.getVerticalBar().setIncrement(16); sc.addListener(SWT.Resize, scResizeListener); if(i == 0) { Composite c; if ( section instanceof ConfigSectionSWT ){ c = ((ConfigSectionSWT)section).configSectionCreate(sc); }else{ c = ((UISWTConfigSection)section).configSectionCreate(sc); } sectionsCreated.add(section); sc.setContent(c); } Messages.setLanguageText(treeItem, section_key); treeItem.setData("Panel", sc); treeItem.setData("ID", name); treeItem.setData("ConfigSectionSWT", section); sections.put(treeItem, section); // ConfigSectionPlugins is special because it has to handle the // PluginConfigModel config pages if (section instanceof ConfigSectionPlugins) ((ConfigSectionPlugins)section).initPluginSubSections(); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "ConfigSection plugin '" + name + "' caused an error", e)); } } } if (composite instanceof Shell) { initApplyCloseButton(); } else { initSaveButton(); } TreeItem[] items = { tree.getItems()[0] }; tree.setSelection(items); // setSelection doesn't trigger a SelectionListener, so.. showSection(items[0]); } public void setupSC(ScrolledComposite sc) { Composite c = (Composite) sc.getContent(); if (c != null) { Point size1 = c.computeSize(sc.getClientArea().width, SWT.DEFAULT); Point size = c.computeSize(SWT.DEFAULT, size1.y); sc.setMinSize(size); } sc.getVerticalBar().setPageIncrement(sc.getSize().y); } /** * @param text */ protected void filterTree(String text) { filterText = text; if (filterDelayTimer != null) { filterDelayTimer.destroy(); } if (lblX != null && !lblX.isDisposed()) { Image img = filterText.length() > 0 ? imgSmallX : imgSmallXGray; lblX.setImage(img); } filterDelayTimer = new Timer("Filter"); filterDelayTimer.addEvent(SystemTime.getCurrentTime() + 300, new TimerEventPerformer() { public void perform(TimerEvent event) { filterDelayTimer.destroy(); filterDelayTimer = null; Utils.execSWTThread(new AERunnable() { public void runSupport() { // TODO Auto-generated method stub ArrayList foundItems = new ArrayList(); TreeItem[] items = tree.getItems(); try { tree.setRedraw(false); for (int i = 0; i < items.length; i++) { items[i].setExpanded(false); } filterTree(items, filterText, foundItems); } finally { tree.setRedraw(true); } } }); } }); } protected void filterTree(TreeItem[] items, String text, ArrayList foundItems) { text = text.toLowerCase(); for (int i = 0; i < items.length; i++) { ensureSectionBuilt(items[i]); ScrolledComposite composite = (ScrolledComposite) items[i].getData("Panel"); if (text.length() > 0 && (items[i].getText().toLowerCase().indexOf(text) >= 0 || compositeHasText( composite, text))) { foundItems.add(items[i]); ensureExpandedTo(items[i]); items[i].setFont(filterFoundFont); } else { items[i].setFont(null); } filterTree(items[i].getItems(), text, foundItems); } } private void ensureExpandedTo(TreeItem item) { TreeItem itemParent = item.getParentItem(); if (itemParent != null) { itemParent.setExpanded(true); ensureExpandedTo(itemParent); } } /** * @param composite * @param text * @return */ private boolean compositeHasText(Composite composite, String text) { Control[] children = composite.getChildren(); for (int i = 0; i < children.length; i++) { Control child = children[i]; if (child instanceof Label) { if (((Label)child).getText().toLowerCase().indexOf(text) >= 0) { return true; } } else if (child instanceof Group) { if (((Group)child).getText().toLowerCase().indexOf(text) >= 0) { return true; } } else if (child instanceof Button) { if (((Button)child).getText().toLowerCase().indexOf(text) >= 0) { return true; } } if (child instanceof Composite) { if (compositeHasText((Composite) child, text)) { return true; } } } return false; } private void showSection(TreeItem section) { ScrolledComposite item = (ScrolledComposite)section.getData("Panel"); if (item != null) { ensureSectionBuilt(section); layoutConfigSection.topControl = item; setupSC(item); cConfigSection.layout(); updateHeader(section); } } private void ensureSectionBuilt(TreeItem treeSection) { ScrolledComposite item = (ScrolledComposite)treeSection.getData("Panel"); if (item != null) { ConfigSection configSection = (ConfigSection)treeSection.getData("ConfigSectionSWT"); if (configSection != null) { Control previous = item.getContent(); if (previous instanceof Composite) { configSection.configSectionDelete(); sectionsCreated.remove(configSection); Utils.disposeComposite((Composite)previous,true); } Composite c; if ( configSection instanceof ConfigSectionSWT ){ c = ((ConfigSectionSWT)configSection).configSectionCreate(item); }else{ c = ((UISWTConfigSection)configSection).configSectionCreate(item); } sectionsCreated.add(configSection); item.setContent(c); } } } private void updateHeader(TreeItem section) { if (section == null) return; int userMode = COConfigurationManager.getIntParameter("User Mode"); int maxUsermode = 0; try { ConfigSection sect = sections.get(section); if (sect instanceof UISWTConfigSection) { maxUsermode = ((UISWTConfigSection) sect).maxUserMode(); } } catch (Error e) { //Debug.printStackTrace(e); } if (userMode < maxUsermode) Messages.setLanguageText(usermodeHint, "ConfigView.higher.mode.available"); else usermodeHint.setText(""); String sHeader = section.getText(); section = section.getParentItem(); while (section != null) { sHeader = section.getText() + " : " + sHeader; section = section.getParentItem(); } lHeader.setText(" " + sHeader.replaceAll("&", "&&")); lHeader.getParent().layout(true, true); } private Composite createConfigSection(String sNameID) { return createConfigSection(null, sNameID, -1, true); } private Composite createConfigSection(String sNameID, int position) { return createConfigSection(null, sNameID, position, true); } public Composite createConfigSection(TreeItem treeItemParent, String sNameID, int position, boolean bPrefix) { ScrolledComposite sc = new ScrolledComposite(cConfigSection, SWT.H_SCROLL | SWT.V_SCROLL); sc.setExpandHorizontal(true); sc.setExpandVertical(true); sc.setLayoutData(new GridData(GridData.FILL_BOTH)); sc.getVerticalBar().setIncrement(16); sc.addListener(SWT.Resize, scResizeListener); Composite cConfigSection = new Composite(sc, SWT.NULL); String section_key = ((bPrefix) ? sSectionPrefix : "") + sNameID; if (position == -2) { // Means "auto-order". position = findInsertPointFor(MessageText.getString(section_key), (treeItemParent == null) ? (Object)tree : (Object)treeItemParent); } TreeItem treeItem; if (treeItemParent == null) { if (position >= 0) treeItem = new TreeItem(tree, SWT.NULL, position); else treeItem = new TreeItem(tree, SWT.NULL); } else { if (position >= 0) treeItem = new TreeItem(treeItemParent, SWT.NULL, position); else treeItem = new TreeItem(treeItemParent, SWT.NULL); } Messages.setLanguageText(treeItem, section_key); treeItem.setData("Panel", sc); treeItem.setData("ID", sNameID); sc.setContent(cConfigSection); return cConfigSection; } private static Comparator insert_point_comparator = new Comparator() { private String asString(Object o) { if (o instanceof String) { return (String)o; } else if (o instanceof TreeItem) { return ((TreeItem)o).getText(); } else { throw new ClassCastException("object is not String or TreeItem: " + o.getClass().getName()); } } public int compare(Object o1, Object o2) { int result = String.CASE_INSENSITIVE_ORDER.compare(asString(o1), asString(o2)); return result; } }; public static int findInsertPointFor(String name, Object structure) { TreeItem[] children = null; if (structure instanceof Tree) { children = ((Tree)structure).getItems(); } else { children = ((TreeItem)structure).getItems(); } if (children.length == 0) {return -1;} int result = Arrays.binarySearch(children, name, insert_point_comparator); if (result > 0) {return result;} result = -(result+1); if (result == children.length) { result = -1; } return result; } public TreeItem findTreeItem(String ID) { return findTreeItem((Tree)null, ID); } private TreeItem findTreeItem(Tree tree, String ID) { if (tree == null) { tree = this.tree; } if (tree == null) { return null; } TreeItem[] items = tree.getItems(); for (int i = 0; i < items.length; i++) { String itemID = (String)items[i].getData("ID"); if (itemID != null && itemID.equalsIgnoreCase(ID)) { return items[i]; } TreeItem itemFound = findTreeItem(items[i], ID); if (itemFound != null) return itemFound; } return null; } private TreeItem findTreeItem(TreeItem item, String ID) { TreeItem[] subItems = item.getItems(); for (int i = 0; i < subItems.length; i++) { String itemID = (String)subItems[i].getData("ID"); if (itemID != null && itemID.equalsIgnoreCase(ID)) { return subItems[i]; } TreeItem itemFound = findTreeItem(subItems[i], ID); if (itemFound != null) return itemFound; } return null; } private void initSaveButton() { GridData gridData; final Button save = new Button(cConfig, SWT.PUSH); Messages.setLanguageText(save, "ConfigView.button.save"); //$NON-NLS-1$ gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gridData.horizontalSpan = 2; gridData.widthHint = 80; save.setLayoutData(gridData); save.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { // force focusout on osx save.setFocus(); save(); } }); } private void initApplyCloseButton() { Composite cButtons = new Composite(cConfig, SWT.NONE); GridLayout gridLayout = new GridLayout(); gridLayout.horizontalSpacing = gridLayout.verticalSpacing = gridLayout.marginHeight = gridLayout.marginWidth = 0; gridLayout.numColumns = 2; cButtons.setLayout(gridLayout); cButtons.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); GridData gridData; final Button apply = new Button(cButtons, SWT.PUSH); Messages.setLanguageText(apply, "Button.apply"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gridData.widthHint = 80; apply.setLayoutData(gridData); apply.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { // force focusout on osx apply.setFocus(); save(); } }); final Button close = new Button(cButtons, SWT.PUSH); Messages.setLanguageText(close, "Button.close"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gridData.widthHint = 80; close.setLayoutData(gridData); close.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { // force focusout on osx apply.setFocus(); save(); apply.getShell().dispose(); } }); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IView#getComposite() */ public Composite getComposite() { return cConfig; } public void updateLanguage() { super.updateLanguage(); updateHeader(tree.getSelection()[0]); // cConfig.setSize(cConfig.computeSize(SWT.DEFAULT, SWT.DEFAULT)); } public void delete() { for (ConfigSection section : sectionsCreated) { try { section.configSectionDelete(); } catch (Exception e) { Debug.out("Error while deleting config section", e); } } sectionsCreated.clear(); pluginSections.clear(); if(! tree.isDisposed()) { TreeItem[] items = tree.getItems(); for (int i = 0; i < items.length; i++) { Composite c = (Composite)items[i].getData("Panel"); Utils.disposeComposite(c); items[i].setData("Panel", null); items[i].setData("ConfigSectionSWT", null); } } Utils.disposeComposite(cConfig); Utils.disposeSWTObjects(new Object[] { headerFont, filterFoundFont }); headerFont = null; filterFoundFont = null; ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage("smallx-gray"); imageLoader.releaseImage("smallx"); } public String getFullTitle() { /* * Using resolveLocalizationKey because there are different version for Classic vs. Vuze */ return MessageText.getString(MessageText.resolveLocalizationKey("ConfigView.title.full")); //$NON-NLS-1$ } public boolean selectSection(String id) { TreeItem ti = findTreeItem(id); if (ti == null) return false; tree.setSelection(new TreeItem[] { ti }); showSection(ti); return true; } public void selectSection( Class config_section_class ) { TreeItem[] items = tree.getItems(); for (int i=0;i 0) { int[] pings = new int[sources.length]; for(int i = 0 ; i < sources.length ; i++) { pings[i] = sources[i].getPingTime(); } pingGraph.addIntsValue(pings); for (int i=0;i 2000 || bounds.height > 2000 ){ return; } boolean size_changed = (old_size == null || old_size.x != bounds.width || old_size.y != bounds.height); old_size = new Point(bounds.width,bounds.height); refresh_count++; if ( refresh_count > graphicsUpdate ){ refresh_count = 0; } if ( refresh_count == 0 || size_changed ){ if ( buffer_image != null && ! buffer_image.isDisposed()){ buffer_image.dispose(); } buffer_image = draw( bounds ); } if ( buffer_image != null ){ GC gc = new GC( canvas ); gc.drawImage( buffer_image, bounds.x, bounds.y ); gc.dispose(); } } private Image draw( Rectangle bounds ) { final int PAD_TOP = 10; final int PAD_BOTTOM = 10; final int PAD_RIGHT = 10; final int PAD_LEFT = 10; int usable_width = bounds.width - PAD_LEFT - PAD_RIGHT; int usable_height = bounds.height - PAD_TOP - PAD_BOTTOM; Image image = new Image( canvas.getDisplay(), bounds ); GC gc = new GC( image ); try { gc.setAntialias( SWT.ON ); } catch (Exception e) { // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others } int font_height = gc.getFontMetrics().getHeight(); int char_width = gc.getFontMetrics().getAverageCharWidth(); Color[] colours = plot_views[0].plotGraph.getColours(); int max_x = 0; int max_y = 0; if ( zones.length > 0 ){ int max_metric = 0; for (int i=0;i 0 ){ max_metric = Math.max( max_metric, metric ); max_x = Math.max( max_x, zone.getUploadEndBytesPerSec()); max_y = Math.max( max_y, zone.getDownloadEndBytesPerSec()); } } if ( max_x > 0 && max_y > 0 ){ double x_ratio = (double)usable_width/max_x; double y_ratio = (double)usable_height/max_y; List texts = new ArrayList(); for (int i=0;i 0 ){ int colour_index = (int)((float)metric*colours.length/max_metric); if ( colour_index >= colours.length ){ colour_index = colours.length-1; } gc.setBackground( colours[colour_index] ); int x = PAD_LEFT + (int)(x1*x_ratio); int y = PAD_TOP + (int)(y1*y_ratio); int width = (int)Math.ceil((x2-x1+1)*x_ratio); int height = (int)Math.ceil((y2-y1+1)*y_ratio ); int y_draw = usable_height + PAD_TOP + PAD_TOP - y - height; gc.fillRectangle( x, y_draw, width, height ); int text_metric = zone.getMetric(); String text = String.valueOf( metric ); int text_width = text.length()*char_width + 4; if ( width >= text_width && height >= font_height ){ Rectangle text_rect = new Rectangle( x + ((width-text_width)/2), y_draw + ((height-font_height)/2), text_width, font_height ); // check for overlap with existing and delete older Iterator it = texts.iterator(); while( it.hasNext()){ Object[] old = (Object[])it.next(); Rectangle old_coords = (Rectangle)old[1]; if ( old_coords.intersects( text_rect )){ it.remove(); } } texts.add( new Object[]{ new Integer( text_metric ), text_rect }); } } } // only do the last 100 texts as things get a little cluttered int text_num = texts.size(); for (int i=(text_num>100?(text_num-100):0);i 0 ){ int max_metric = 0; int max_pos = 0; for (int i=0;i 0 ){ gc.setLineWidth( 3 ); gc.setForeground( Colors.red ); for (int i=0;i 0 ){ int max_metric = 0; int max_pos = 0; for (int i=0;i 0 ){ gc.setForeground( Colors.red ); gc.setLineWidth( 3 ); for (int i=0;i= e.width && bounds.height >= e.height) { if (alpha != 255) { try { e.gc.setAlpha(alpha); } catch (Exception ex) { // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others } } e.gc.drawImage(img, e.x, e.y, e.width, e.height, e.x, e.y, e.width, e.height); } } else { e.gc.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); e.gc.fillRectangle(e.x, e.y, e.width, e.height); e.gc.drawText(MessageText.getString("VivaldiView.notAvailable"), 10, 10, true); } } }); canvas.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent event) { if(event.button == 1) mouseLeftDown = true; if(event.button == 3) mouseRightDown = true; xDown = event.x; yDown = event.y; scale.saveMinX = scale.minX; scale.saveMaxX = scale.maxX; scale.saveMinY = scale.minY; scale.saveMaxY = scale.maxY; scale.saveRotation = scale.rotation; } public void mouseUp(MouseEvent event) { if(event.button == 1) mouseLeftDown = false; if(event.button == 3) mouseRightDown = false; refreshContacts(lastContacts, lastSelf); } }); canvas.addListener(SWT.KeyDown, new Listener() { public void handleEvent(Event event) { } }); canvas.addListener(SWT.MouseWheel, new Listener() { public void handleEvent(Event event) { // System.out.println(event.count); scale.saveMinX = scale.minX; scale.saveMaxX = scale.maxX; scale.saveMinY = scale.minY; scale.saveMaxY = scale.maxY; int deltaY = event.count * 5; // scaleFactor>1 means zoom in, this happens when // deltaY<0 which happens when the mouse is moved up. float scaleFactor = 1 - (float) deltaY / 300; if(scaleFactor <= 0) scaleFactor = 0.01f; // Scalefactor of e.g. 3 makes elements 3 times larger float moveFactor = 1 - 1/scaleFactor; float centerX = (scale.saveMinX + scale.saveMaxX)/2; scale.minX = scale.saveMinX + moveFactor * (centerX - scale.saveMinX); scale.maxX = scale.saveMaxX - moveFactor * (scale.saveMaxX - centerX); float centerY = (scale.saveMinY + scale.saveMaxY)/2; scale.minY = scale.saveMinY + moveFactor * (centerY - scale.saveMinY); scale.maxY = scale.saveMaxY - moveFactor * (scale.saveMaxY - centerY); refreshContacts(lastContacts, lastSelf); } }); canvas.addMouseMoveListener(new MouseMoveListener() { public void mouseMove(MouseEvent event) { if(mouseLeftDown) { int deltaX = event.x - xDown; int deltaY = event.y - yDown; int width = scale.width; int height = scale.height; float ratioX = (float) (scale.saveMaxX - scale.saveMinX) / (float) width; float ratioY = (float) (scale.saveMaxY - scale.saveMinY) / (float) height; float realDeltaX = deltaX * ratioX; float realDeltaY = deltaY * ratioY; scale.minX = scale.saveMinX - realDeltaX; scale.maxX = scale.saveMaxX - realDeltaX; scale.minY = scale.saveMinY - realDeltaY; scale.maxY = scale.saveMaxY - realDeltaY; refreshContacts(lastContacts, lastSelf); } if(mouseRightDown) { int deltaX = event.x - xDown; scale.rotation = scale.saveRotation - (float) deltaX / 100; int deltaY = event.y - yDown; // scaleFactor>1 means zoom in, this happens when // deltaY<0 which happens when the mouse is moved up. float scaleFactor = 1 - (float) deltaY / 300; if(scaleFactor <= 0) scaleFactor = 0.01f; // Scalefactor of e.g. 3 makes elements 3 times larger float moveFactor = 1 - 1/scaleFactor; float centerX = (scale.saveMinX + scale.saveMaxX)/2; scale.minX = scale.saveMinX + moveFactor * (centerX - scale.saveMinX); scale.maxX = scale.saveMaxX - moveFactor * (scale.saveMaxX - centerX); float centerY = (scale.saveMinY + scale.saveMaxY)/2; scale.minY = scale.saveMinY + moveFactor * (centerY - scale.saveMinY); scale.maxY = scale.saveMaxY - moveFactor * (scale.saveMaxY - centerY); refreshContacts(lastContacts, lastSelf); } } }); canvas.addMouseTrackListener(new MouseTrackListener() { public void mouseHover(MouseEvent e) { } public void mouseExit(MouseEvent e) { if (autoAlpha) { setAlpha(ALPHA_NOFOCUS); } } public void mouseEnter(MouseEvent e) { if (autoAlpha) { setAlpha(ALPHA_FOCUS); } } }); } public void setLayoutData(Object data) { canvas.setLayoutData(data); } public void refreshContacts(List contacts,DHTTransportContact self) { if (contacts == null || self == null) { return; } lastContacts = contacts; lastSelf = self; if(canvas.isDisposed()) return; Rectangle size = canvas.getBounds(); if (size.isEmpty()) { return; } scale.width = size.width; scale.height = size.height; Color white = ColorCache.getColor(display,255,255,255); Color blue = ColorCache.getColor(display,66,87,104); if (img != null && !img.isDisposed()) { img.dispose(); } img = new Image(display,size); GC gc = new GC(img); gc.setForeground(white); gc.setBackground(white); gc.fillRectangle(size); if(SWT.getVersion() >= 3138 && antiAliasingAvailable) { try { //gc.setTextAntialias(SWT.ON); //gc.setAntialias(SWT.ON); } catch(Exception e) { antiAliasingAvailable = false; } } gc.setForeground(blue); gc.setBackground(white); DHTNetworkPosition _ownPosition = self.getNetworkPosition(DHTNetworkPosition.POSITION_TYPE_VIVALDI_V1); if ( _ownPosition == null ){ return; } VivaldiPosition ownPosition = (VivaldiPosition)_ownPosition; float ownErrorEstimate = ownPosition.getErrorEstimate(); HeightCoordinatesImpl ownCoords = (HeightCoordinatesImpl) ownPosition.getCoordinates(); gc.drawText("Our error: " + ownErrorEstimate,10,10); Color black = ColorCache.getColor(display, 0, 0, 0); gc.setBackground(black); // Color of the squares // Draw all known positions of other contacts Iterator iter = contacts.iterator(); while(iter.hasNext()) { DHTControlContact contact = (DHTControlContact) iter.next(); DHTNetworkPosition _position = contact.getTransportContact().getNetworkPosition(DHTNetworkPosition.POSITION_TYPE_VIVALDI_V1); if ( _position == null ){ continue; } VivaldiPosition position = (VivaldiPosition)_position; HeightCoordinatesImpl coord = (HeightCoordinatesImpl) position.getCoordinates(); if(coord.isValid()) { draw(gc,coord.getX(),coord.getY(),coord.getH(),contact,(int)ownCoords.distance(coord),position.getErrorEstimate()); } } // Mark our own position Color red = ColorCache.getColor(display, 255, 0, 0); gc.setForeground(red); drawSelf(gc, ownCoords.getX(), ownCoords.getY(), ownCoords.getH(), ownErrorEstimate); gc.dispose(); canvas.redraw(); } public void refresh(List vivaldiPositions) { if(canvas.isDisposed()) return; Rectangle size = canvas.getBounds(); scale.width = size.width; scale.height = size.height; if (img != null && !img.isDisposed()) { img.dispose(); } img = new Image(display,size); GC gc = new GC(img); Color white = ColorCache.getColor(display,255,255,255); gc.setForeground(white); gc.setBackground(white); gc.fillRectangle(size); Color blue = ColorCache.getColor(display,66,87,104); gc.setForeground(blue); gc.setBackground(blue); Iterator iter = vivaldiPositions.iterator(); while(iter.hasNext()) { VivaldiPosition position = (VivaldiPosition)iter.next(); HeightCoordinatesImpl coord = (HeightCoordinatesImpl) position.getCoordinates(); float error = position.getErrorEstimate() - VivaldiPosition.ERROR_MIN; if(error < 0) error = 0; if(error > 1) error = 1; int blueComponent = (int) (255 - error * 255); int redComponent = (int) (255*error); // Don't use ColorCache, as our color creation is temporary and // varying Color drawColor = new Color(display,redComponent,50,blueComponent); gc.setForeground(drawColor); draw(gc,coord.getX(),coord.getY(),coord.getH()); drawColor.dispose(); } gc.dispose(); canvas.redraw(); } private void draw(GC gc,float x,float y,float h) { int x0 = scale.getX(x,y); int y0 = scale.getY(x,y); gc.fillRectangle(x0-1,y0-1,3,3); gc.drawLine(x0,y0,x0,(int)(y0-200*h/(scale.maxY-scale.minY))); } private void draw(GC gc,float x,float y,float h,DHTControlContact contact,int distance,float error) { if(x == 0 && y == 0) return; if(error > 1) error = 1; int errDisplay = (int) (100 * error); int x0 = scale.getX(x,y); int y0 = scale.getY(x,y); gc.fillRectangle(x0-1,y0-1,3,3); //int elevation =(int) ( 200*h/(scale.maxY-scale.minY)); //gc.drawLine(x0,y0,x0,y0-elevation); String text = /*contact.getTransportContact().getAddress().getAddress().getHostAddress() + " (" + */distance + " ms \nerr:"+errDisplay+"%"; int lineReturn = text.indexOf("\n"); int xOffset = gc.getFontMetrics().getAverageCharWidth() * (lineReturn != -1 ? lineReturn:text.length()) / 2; gc.drawText(text,x0-xOffset,y0,true); } // Mark our own position private void drawSelf(GC gc, float x, float y, float h, float errorEstimate){ int x0 = scale.getX(x, y); int y0 = scale.getY(x, y); //gc.drawOval(x0-50, y0-50, 100, 100); gc.drawLine(x0-15, y0, x0+15, y0); // Horizontal gc.drawLine(x0, y0-15, x0, y0+15); // Vertical } public int getAlpha() { return alpha; } public void setAlpha(int alpha) { this.alpha = alpha; if (canvas != null && !canvas.isDisposed()) { canvas.redraw(); } } public void setAutoAlpha(boolean autoAlpha) { this.autoAlpha = autoAlpha; if (autoAlpha) { setAlpha(canvas.getDisplay().getCursorControl() == canvas ? ALPHA_FOCUS : ALPHA_NOFOCUS); } } public void delete() { if(img != null && !img.isDisposed()) { img.dispose(); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/stats/DHTView.java0000644000175000017500000006111611260535120024017 0ustar adrianadrian/* * Created on Sep 13, 2004 * Created by Olivier Chalouhi * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.stats; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.graphics.SpeedGraphic; import org.gudy.azureus2.ui.swt.views.AbstractIView; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.DHTStorageAdapter; import com.aelitis.azureus.core.dht.control.DHTControlActivity; import com.aelitis.azureus.core.dht.control.DHTControlListener; import com.aelitis.azureus.core.dht.control.DHTControlStats; import com.aelitis.azureus.core.dht.db.DHTDBStats; import com.aelitis.azureus.core.dht.nat.DHTNATPuncher; import com.aelitis.azureus.core.dht.router.DHTRouterStats; import com.aelitis.azureus.core.dht.transport.DHTTransport; import com.aelitis.azureus.core.dht.transport.DHTTransportFullStats; import com.aelitis.azureus.core.dht.transport.DHTTransportStats; import com.aelitis.azureus.plugins.dht.DHTPlugin; /** * */ public class DHTView extends AbstractIView { public static final int DHT_TYPE_MAIN = DHT.NW_MAIN; public static final int DHT_TYPE_CVS = DHT.NW_CVS; public static final int DHT_TYPE_MAIN_V6 = DHT.NW_MAIN_V6; DHT dht; Composite panel; String yes_str; String no_str; Label lblUpTime,lblNumberOfUsers; Label lblNodes,lblLeaves; Label lblContacts,lblReplacements,lblLive,lblUnknown,lblDying; Label lblSkew, lblRendezvous, lblReachable; Label lblKeys,lblValues,lblSize; Label lblLocal,lblDirect,lblIndirect; Label lblDivFreq,lblDivSize; Label lblReceivedPackets,lblReceivedBytes; Label lblSentPackets,lblSentBytes; Label lblPings[] = new Label[4]; Label lblFindNodes[] = new Label[4]; Label lblFindValues[] = new Label[4]; Label lblStores[] = new Label[4]; Label lblData[] = new Label[4]; Canvas in,out; SpeedGraphic inGraph,outGraph; boolean activityChanged; DHTControlListener controlListener; Table activityTable; DHTControlActivity[] activities; private final int dht_type; protected AzureusCore core; public DHTView( int dht_type ) { this.dht_type = dht_type; AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { DHTView.this.core = core; init(core); } }); } private void init(AzureusCore core) { try { PluginInterface dht_pi = core.getPluginManager().getPluginInterfaceByClass( DHTPlugin.class ); if ( dht_pi == null ){ return; } DHT[] dhts = ((DHTPlugin)dht_pi.getPlugin()).getDHTs(); for (int i=0;i 0) colDetails.setWidth(remainingWidth); } finally { inUse = false; } } }; activityTable.addListener(SWT.Resize, computeLastRowWidthListener); colStatus.addListener(SWT.Resize,computeLastRowWidthListener); colType.addListener(SWT.Resize,computeLastRowWidthListener); colName.addListener(SWT.Resize,computeLastRowWidthListener); activityTable.addListener(SWT.SetData, new Listener() { public void handleEvent(Event event) { TableItem item = (TableItem) event.item; int index = activityTable.indexOf (item); item.setText (0,MessageText.getString("DHTView.activity.status." + activities[index].isQueued())); item.setText (1,MessageText.getString("DHTView.activity.type." + activities[index].getType())); item.setText (2,ByteFormatter.nicePrint(activities[index].getTarget())); item.setText (3,activities[index].getDescription()); } }); } public void delete() { Utils.disposeComposite(panel); if (dht != null) { dht.getControl().removeListener(controlListener); } outGraph.dispose(); inGraph.dispose(); } public String getFullTitle() { if ( dht_type == DHT_TYPE_MAIN ){ return( "DHTView.title.full" ); }else if ( dht_type == DHT_TYPE_CVS ){ return( "DHTView.title.fullcvs" ); }else{ return( "DHTView.title.full_v6" ); } } public Composite getComposite() { return panel; } public void refresh() { if (dht == null) { if (core != null) { // keep trying until dht is avail init(core); } return; } inGraph.refresh(); outGraph.refresh(); refreshGeneral(); refreshDB(); refreshTransportDetails(); refreshOperationDetails(); refreshActivity(); } private void refreshGeneral() { DHTControlStats controlStats = dht.getControl().getStats(); DHTRouterStats routerStats = dht.getRouter().getStats(); DHTTransport transport = dht.getTransport(); DHTTransportStats transportStats = transport.getStats(); lblUpTime.setText(TimeFormatter.format(controlStats.getRouterUptime() / 1000)); lblNumberOfUsers.setText("" + controlStats.getEstimatedDHTSize()); int percent = transportStats.getRouteablePercentage(); lblReachable.setText((transport.isReachable()?yes_str:no_str) + (percent==-1?"":(" " + percent+"%"))); DHTNATPuncher puncher = dht.getNATPuncher(); String puncher_str; if ( puncher == null ){ puncher_str = ""; }else{ puncher_str = puncher.operational()?yes_str:no_str; } lblRendezvous.setText(transport.isReachable()?"":puncher_str); long[] stats = routerStats.getStats(); lblNodes.setText("" + stats[DHTRouterStats.ST_NODES]); lblLeaves.setText("" + stats[DHTRouterStats.ST_LEAVES]); lblContacts.setText("" + stats[DHTRouterStats.ST_CONTACTS]); lblReplacements.setText("" + stats[DHTRouterStats.ST_REPLACEMENTS]); lblLive.setText("" + stats[DHTRouterStats.ST_CONTACTS_LIVE]); lblUnknown.setText("" + stats[DHTRouterStats.ST_CONTACTS_UNKNOWN]); lblDying.setText("" + stats[DHTRouterStats.ST_CONTACTS_DEAD]); long skew_average = transportStats.getSkewAverage(); lblSkew.setText( skew_average==0?"":(skew_average<0?"-":"") + TimeFormatter.format100ths( Math.abs(skew_average ))); } private int refreshIter = 0; private void refreshDB() { if(refreshIter == 0) { DHTDBStats dbStats = dht.getDataBase().getStats(); lblKeys.setText("" + dbStats.getKeyCount() + " (" + dbStats.getLocalKeyCount() + ")" ); int[] stats = dbStats.getValueDetails(); lblValues.setText("" + stats[DHTDBStats.VD_VALUE_COUNT]); lblSize.setText(DisplayFormatters.formatByteCountToKiBEtc(dbStats.getSize())); lblDirect.setText(DisplayFormatters.formatByteCountToKiBEtc( stats[DHTDBStats.VD_DIRECT_SIZE])); lblIndirect.setText(DisplayFormatters.formatByteCountToKiBEtc( stats[DHTDBStats.VD_INDIRECT_SIZE])); lblLocal.setText(DisplayFormatters.formatByteCountToKiBEtc( stats[DHTDBStats.VD_LOCAL_SIZE])); DHTStorageAdapter sa = dht.getStorageAdapter(); String rem_freq; String rem_size; if ( sa == null ){ rem_freq = "?"; rem_size = "?"; }else{ rem_freq = "" + sa.getRemoteFreqDivCount(); rem_size = "" + sa.getRemoteSizeDivCount(); } lblDivFreq.setText("" + stats[DHTDBStats.VD_DIV_FREQ] + " (" + rem_freq + ")"); lblDivSize.setText("" + stats[DHTDBStats.VD_DIV_SIZE] + " (" + rem_size + ")"); } else { refreshIter++; if(refreshIter == 100) refreshIter = 0; } } private void refreshTransportDetails() { DHTTransportStats transportStats = dht.getTransport().getStats(); lblReceivedBytes.setText(DisplayFormatters.formatByteCountToKiBEtc(transportStats.getBytesReceived())); lblSentBytes.setText(DisplayFormatters.formatByteCountToKiBEtc(transportStats.getBytesSent())); lblReceivedPackets.setText("" + transportStats.getPacketsReceived()); lblSentPackets.setText("" + transportStats.getPacketsSent()); } private void refreshOperationDetails() { DHTTransportStats transportStats = dht.getTransport().getStats(); long[] pings = transportStats.getPings(); for(int i = 0 ; i < 4 ; i++) { lblPings[i].setText("" + pings[i]); } long[] findNodes = transportStats.getFindNodes(); for(int i = 0 ; i < 4 ; i++) { lblFindNodes[i].setText("" + findNodes[i]); } long[] findValues = transportStats.getFindValues(); for(int i = 0 ; i < 4 ; i++) { lblFindValues[i].setText("" + findValues[i]); } long[] stores = transportStats.getStores(); long[] qstores = transportStats.getQueryStores(); for(int i = 0 ; i < 4 ; i++) { lblStores[i].setText("" + stores[i] + " (" + qstores[i] + ")"); } long[] data = transportStats.getData(); for(int i = 0 ; i < 4 ; i++) { lblData[i].setText("" + data[i]); } } private void refreshActivity() { if(activityChanged) { activityChanged = false; activities = dht.getControl().getActivities(); activityTable.setItemCount(activities.length); activityTable.clearAll(); //Dunno if still needed? activityTable.redraw(); } } public void periodicUpdate() { if(dht == null) return; DHTTransportFullStats fullStats = dht.getTransport().getLocalContact().getStats(); inGraph.addIntValue((int)fullStats.getAverageBytesReceived()); outGraph.addIntValue((int)fullStats.getAverageBytesSent()); } public String getData() { return( getFullTitle()); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/stats/ActivityView.java0000644000175000017500000001366511215610220025175 0ustar adrianadrian/* * File : StatsView.java * Created : 15 d�c. 2003} * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.stats; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerStats; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.stats.transfer.OverallStats; import org.gudy.azureus2.core3.stats.transfer.StatsFactory; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.Legend; import org.gudy.azureus2.ui.swt.components.graphics.SpeedGraphic; import org.gudy.azureus2.ui.swt.views.AbstractIView; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; /** * @author Olivier * */ public class ActivityView extends AbstractIView implements ParameterListener { GlobalManager manager = null; GlobalManagerStats stats = null; Composite panel; Canvas downSpeedCanvas; SpeedGraphic downSpeedGraphic; Canvas upSpeedCanvas; SpeedGraphic upSpeedGraphic; public ActivityView() { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { manager = core.getGlobalManager(); stats = manager.getStats(); } }); } public void periodicUpdate() { if (manager == null || stats == null) { return; } int swarms_peer_speed = (int)stats.getTotalSwarmsPeerRate(true,false); downSpeedGraphic.addIntsValue( new int[]{ stats.getDataReceiveRate()+stats.getProtocolReceiveRate(), stats.getProtocolReceiveRate(), COConfigurationManager.getIntParameter("Max Download Speed KBs") * 1024, swarms_peer_speed }); upSpeedGraphic.addIntsValue( new int[]{ stats.getDataSendRate()+stats.getProtocolSendRate(), stats.getProtocolSendRate(), COConfigurationManager.getIntParameter(TransferSpeedValidator.getActiveUploadParameter( manager )) * 1024, swarms_peer_speed }); } public void initialize(Composite composite) { panel = new Composite(composite,SWT.NULL); panel.setLayout(new GridLayout()); GridData gridData; Group gDownSpeed = new Group(panel,SWT.NULL); Messages.setLanguageText(gDownSpeed,"SpeedView.downloadSpeed.title"); gridData = new GridData(GridData.FILL_BOTH); gDownSpeed.setLayoutData(gridData); gDownSpeed.setLayout(new GridLayout()); downSpeedCanvas = new Canvas(gDownSpeed,SWT.NO_BACKGROUND); gridData = new GridData(GridData.FILL_BOTH); downSpeedCanvas.setLayoutData(gridData); downSpeedGraphic = SpeedGraphic.getInstance(); downSpeedGraphic.initialize(downSpeedCanvas); Color[] colors = downSpeedGraphic.colors; Group gUpSpeed = new Group(panel,SWT.NULL); Messages.setLanguageText(gUpSpeed,"SpeedView.uploadSpeed.title"); gridData = new GridData(GridData.FILL_BOTH); gUpSpeed.setLayoutData(gridData); gUpSpeed.setLayout(new GridLayout()); upSpeedCanvas = new Canvas(gUpSpeed,SWT.NO_BACKGROUND); gridData = new GridData(GridData.FILL_BOTH); upSpeedCanvas.setLayoutData(gridData); upSpeedGraphic = SpeedGraphic.getInstance(); upSpeedGraphic.initialize(upSpeedCanvas); COConfigurationManager.addAndFireParameterListener("Stats Graph Dividers", this); upSpeedGraphic.setLineColors(colors); String[] colorConfigs = new String[] { "ActivityView.legend.peeraverage", "ActivityView.legend.achieved", "ActivityView.legend.overhead", "ActivityView.legend.limit", "ActivityView.legend.swarmaverage", "ActivityView.legend.trimmed" }; Legend.createLegendComposite(panel, colors, colorConfigs); } public void delete() { Utils.disposeComposite(panel); downSpeedGraphic.dispose(); upSpeedGraphic.dispose(); COConfigurationManager.removeParameterListener("Stats Graph Dividers", this); } public String getFullTitle() { return MessageText.getString("SpeedView.title.full"); //$NON-NLS-1$ } public Composite getComposite() { return panel; } public void refresh() { downSpeedGraphic.refresh(); upSpeedGraphic.refresh(); } public String getData() { return "SpeedView.title.full"; } public void parameterChanged(String param_name) { boolean update_dividers = COConfigurationManager.getBooleanParameter("Stats Graph Dividers"); int update_divider_width = update_dividers ? 60 : 0; downSpeedGraphic.setUpdateDividerWidth(update_divider_width); upSpeedGraphic.setUpdateDividerWidth(update_divider_width); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/stats/CacheView.java0000644000175000017500000004007110617220604024403 0ustar adrianadrian/* * Created on Sep 13, 2004 * Created by Olivier Chalouhi * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.stats; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.ProgressBar; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.graphics.SpeedGraphic; import org.gudy.azureus2.ui.swt.views.AbstractIView; import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerFactory; import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerStats; /** * */ public class CacheView extends AbstractIView { CacheFileManagerStats stats; Composite panel; Label lblInUse,lblSize,lblPercentUsed; ProgressBar pbInUse; Label lblReadsFromCache,lblNumberReadsFromCache,lblAvgSizeFromCache; Label lblReadsFromFile, lblNumberReadsFromFile,lblAvgSizeFromFile; Label lblPercentReads; ProgressBar pbReads; Label lblWritesToCache,lblNumberWritesToCache,lblAvgSizeToCache; Label lblWritesToFile, lblNumberWritesToFile,lblAvgSizeToFile; Label lblPercentWrites; ProgressBar pbWrites; Canvas readsFromFile,readsFromCache,writesToCache,writesToFile; SpeedGraphic rffGraph,rfcGraph,wtcGraph,wtfGraph; public CacheView() { try { this.stats = CacheFileManagerFactory.getSingleton().getStats(); } catch(Exception e) { Debug.printStackTrace( e ); } } public void initialize(Composite composite) { panel = new Composite(composite,SWT.NULL); panel.setLayout(new GridLayout()); generateGeneralGroup(); generateReadsGroup(); generateWritesGroup(); generateSpeedGroup(); } /** * */ private void generateGeneralGroup() { GridData gridData; Group gCacheGeneral = new Group(panel,SWT.NULL); Messages.setLanguageText(gCacheGeneral,"CacheView.general.title"); gCacheGeneral.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); GridLayout layoutGeneral = new GridLayout(); layoutGeneral.numColumns = 4; gCacheGeneral.setLayout(layoutGeneral); Label lbl; lbl = new Label(gCacheGeneral,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lbl.setLayoutData(gridData); Messages.setLanguageText(lbl,"CacheView.general.inUse"); lblInUse = new Label(gCacheGeneral,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblInUse.setLayoutData(gridData); pbInUse = new ProgressBar(gCacheGeneral,SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.verticalSpan = 2; pbInUse.setLayoutData(gridData); pbInUse.setMinimum(0); pbInUse.setMaximum(1000); lblPercentUsed = new Label(gCacheGeneral,SWT.NULL); gridData = new GridData(); gridData.verticalSpan = 2; gridData.widthHint = 100; lblPercentUsed.setLayoutData(gridData); lbl = new Label(gCacheGeneral,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lbl.setLayoutData(gridData); Messages.setLanguageText(lbl,"CacheView.general.size"); lblSize = new Label(gCacheGeneral,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblSize.setLayoutData(gridData); } private void generateReadsGroup() { GridData gridData; Group gCacheReads = new Group(panel,SWT.NULL); Messages.setLanguageText(gCacheReads,"CacheView.reads.title"); gCacheReads.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); GridLayout layoutGeneral = new GridLayout(); layoutGeneral.numColumns = 6; gCacheReads.setLayout(layoutGeneral); Label lbl; lbl = new Label(gCacheReads,SWT.NULL); lbl = new Label(gCacheReads,SWT.NULL); Messages.setLanguageText(lbl,"CacheView.reads.#"); lbl = new Label(gCacheReads,SWT.NULL); Messages.setLanguageText(lbl,"CacheView.reads.amount"); lbl = new Label(gCacheReads,SWT.NULL); Messages.setLanguageText(lbl,"CacheView.reads.avgsize"); lbl = new Label(gCacheReads,SWT.NULL); lbl = new Label(gCacheReads,SWT.NULL); lbl = new Label(gCacheReads,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lbl.setLayoutData(gridData); Messages.setLanguageText(lbl,"CacheView.reads.fromCache"); lblNumberReadsFromCache = new Label(gCacheReads,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblNumberReadsFromCache.setLayoutData(gridData); lblReadsFromCache = new Label(gCacheReads,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblReadsFromCache.setLayoutData(gridData); lblAvgSizeFromCache = new Label(gCacheReads,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblAvgSizeFromCache.setLayoutData(gridData); pbReads = new ProgressBar(gCacheReads,SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.verticalSpan = 2; pbReads.setLayoutData(gridData); pbReads.setMinimum(0); pbReads.setMaximum(1000); lblPercentReads = new Label(gCacheReads,SWT.NULL); gridData = new GridData(); gridData.verticalSpan = 2; gridData.widthHint = 100; lblPercentReads.setLayoutData(gridData); lbl = new Label(gCacheReads,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lbl.setLayoutData(gridData); Messages.setLanguageText(lbl,"CacheView.reads.fromFile"); lblNumberReadsFromFile = new Label(gCacheReads,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblNumberReadsFromFile.setLayoutData(gridData); lblReadsFromFile = new Label(gCacheReads,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblReadsFromFile.setLayoutData(gridData); lblAvgSizeFromFile = new Label(gCacheReads,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblAvgSizeFromFile.setLayoutData(gridData); } private void generateSpeedGroup() { GridData gridData; Group gCacheSpeeds = new Group(panel,SWT.NULL); Messages.setLanguageText(gCacheSpeeds,"CacheView.speeds.title"); gCacheSpeeds.setLayoutData(new GridData(GridData.FILL_BOTH)); GridLayout layoutGeneral = new GridLayout(); layoutGeneral.numColumns = 3; gCacheSpeeds.setLayout(layoutGeneral); Label lbl; lbl = new Label(gCacheSpeeds,SWT.NULL); lbl = new Label(gCacheSpeeds,SWT.NULL); gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); lbl.setLayoutData(gridData); Messages.setLanguageText(lbl,"CacheView.speeds.reads"); lbl = new Label(gCacheSpeeds,SWT.NULL); gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); lbl.setLayoutData(gridData); Messages.setLanguageText(lbl,"CacheView.speeds.writes"); lbl = new Label(gCacheSpeeds,SWT.NULL); Messages.setLanguageText(lbl,"CacheView.speeds.fromCache"); readsFromCache = new Canvas(gCacheSpeeds,SWT.NO_BACKGROUND); gridData = new GridData(GridData.FILL_BOTH); readsFromCache.setLayoutData(gridData); rfcGraph = SpeedGraphic.getInstance(); rfcGraph.initialize(readsFromCache); writesToCache = new Canvas(gCacheSpeeds,SWT.NO_BACKGROUND); gridData = new GridData(GridData.FILL_BOTH); writesToCache.setLayoutData(gridData); wtcGraph = SpeedGraphic.getInstance(); wtcGraph.initialize(writesToCache); lbl = new Label(gCacheSpeeds,SWT.NULL); Messages.setLanguageText(lbl,"CacheView.speeds.fromFile"); readsFromFile = new Canvas(gCacheSpeeds,SWT.NO_BACKGROUND); gridData = new GridData(GridData.FILL_BOTH); readsFromFile.setLayoutData(gridData); rffGraph = SpeedGraphic.getInstance(); rffGraph.initialize(readsFromFile); writesToFile = new Canvas(gCacheSpeeds,SWT.NO_BACKGROUND); gridData = new GridData(GridData.FILL_BOTH); writesToFile.setLayoutData(gridData); wtfGraph = SpeedGraphic.getInstance(); wtfGraph.initialize(writesToFile); } public void periodicUpdate() { rfcGraph.addIntValue((int)stats.getAverageBytesReadFromCache()); rffGraph.addIntValue((int)stats.getAverageBytesReadFromFile()); wtcGraph.addIntValue((int)stats.getAverageBytesWrittenToCache()); wtfGraph.addIntValue((int)stats.getAverageBytesWrittenToFile()); } private void generateWritesGroup() { GridData gridData; Group gCacheWrites = new Group(panel,SWT.NULL); Messages.setLanguageText(gCacheWrites,"CacheView.writes.title"); gCacheWrites.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); GridLayout layoutGeneral = new GridLayout(); layoutGeneral.numColumns = 6; gCacheWrites.setLayout(layoutGeneral); Label lbl; lbl = new Label(gCacheWrites,SWT.NULL); lbl = new Label(gCacheWrites,SWT.NULL); Messages.setLanguageText(lbl,"CacheView.reads.#"); lbl = new Label(gCacheWrites,SWT.NULL); Messages.setLanguageText(lbl,"CacheView.reads.amount"); lbl = new Label(gCacheWrites,SWT.NULL); Messages.setLanguageText(lbl,"CacheView.reads.avgsize"); lbl = new Label(gCacheWrites,SWT.NULL); lbl = new Label(gCacheWrites,SWT.NULL); lbl = new Label(gCacheWrites,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lbl.setLayoutData(gridData); Messages.setLanguageText(lbl,"CacheView.writes.toCache"); lblNumberWritesToCache = new Label(gCacheWrites,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblNumberWritesToCache.setLayoutData(gridData); lblWritesToCache = new Label(gCacheWrites,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblWritesToCache.setLayoutData(gridData); lblAvgSizeToCache = new Label(gCacheWrites,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblAvgSizeToCache.setLayoutData(gridData); pbWrites = new ProgressBar(gCacheWrites,SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.verticalSpan = 2; pbWrites.setLayoutData(gridData); pbWrites.setMinimum(0); pbWrites.setMaximum(1000); lblPercentWrites = new Label(gCacheWrites,SWT.NULL); gridData = new GridData(); gridData.verticalSpan = 2; gridData.widthHint = 100; lblPercentWrites.setLayoutData(gridData); lbl = new Label(gCacheWrites,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lbl.setLayoutData(gridData); Messages.setLanguageText(lbl,"CacheView.writes.toFile"); lblNumberWritesToFile = new Label(gCacheWrites,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblNumberWritesToFile.setLayoutData(gridData); lblWritesToFile = new Label(gCacheWrites,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblWritesToFile.setLayoutData(gridData); lblAvgSizeToFile = new Label(gCacheWrites,SWT.NULL); gridData = new GridData(); gridData.widthHint = 100; lblAvgSizeToFile.setLayoutData(gridData); } public void delete() { Utils.disposeComposite(panel); rfcGraph.dispose(); rffGraph.dispose(); wtcGraph.dispose(); wtfGraph.dispose(); } public String getFullTitle() { return MessageText.getString("CacheView.title.full"); //$NON-NLS-1$ } public Composite getComposite() { return panel; } public void refresh() { //General Part lblSize.setText(DisplayFormatters.formatByteCountToKiBEtc(stats.getSize())); lblInUse.setText(DisplayFormatters.formatByteCountToKiBEtc(stats.getUsedSize())); int perThousands = (int) ((1000 * stats.getUsedSize()) / stats.getSize()); lblPercentUsed.setText(DisplayFormatters.formatPercentFromThousands(perThousands)); pbInUse.setSelection(perThousands); //Reads refrehReads(); //Writes refreshWrites(); //Graphics rfcGraph.refresh(); rffGraph.refresh(); wtcGraph.refresh(); wtfGraph.refresh(); } /** * */ private void refrehReads() { int perThousands; long readsFromCache = stats.getBytesReadFromCache(); long readsFromFile = stats.getBytesReadFromFile(); long nbReadsFromCache = stats.getCacheReadCount(); long nbReadsFromFile = stats.getFileReadCount(); lblNumberReadsFromCache.setText("" + nbReadsFromCache); lblNumberReadsFromFile.setText("" + nbReadsFromFile); if(nbReadsFromCache != 0) { long avgReadFromCache = readsFromCache / nbReadsFromCache; lblAvgSizeFromCache.setText(DisplayFormatters.formatByteCountToKiBEtc(avgReadFromCache)); } else { lblAvgSizeFromCache.setText("--"); } if(nbReadsFromFile != 0) { long avgReadFromFile = readsFromFile / nbReadsFromFile; lblAvgSizeFromFile.setText(DisplayFormatters.formatByteCountToKiBEtc(avgReadFromFile)); } else { lblAvgSizeFromFile.setText("--"); } lblReadsFromCache.setText(DisplayFormatters.formatByteCountToKiBEtc(readsFromCache)); lblReadsFromFile.setText(DisplayFormatters.formatByteCountToKiBEtc(readsFromFile)); long totalRead = readsFromCache + readsFromFile; if(totalRead > 0) { perThousands = (int) ((1000l * stats.getBytesReadFromCache()) / totalRead); lblPercentReads.setText(DisplayFormatters.formatPercentFromThousands(perThousands) + " " + MessageText.getString("CacheView.reads.hits")); pbReads.setSelection(perThousands); } } private void refreshWrites() { int perThousands; long writesToCache = stats.getBytesWrittenToCache(); long writesToFile = stats.getBytesWrittenToFile(); long nbWritesToCache = stats.getCacheWriteCount(); long nbWritesToFile = stats.getFileWriteCount(); lblNumberWritesToCache.setText("" + nbWritesToCache); lblNumberWritesToFile.setText("" + nbWritesToFile); if(nbWritesToCache != 0) { long avgReadToCache = writesToCache / nbWritesToCache; lblAvgSizeToCache.setText(DisplayFormatters.formatByteCountToKiBEtc(avgReadToCache)); } else { lblAvgSizeToCache.setText("--"); } if(nbWritesToFile != 0) { long avgReadToFile = writesToFile / nbWritesToFile; lblAvgSizeToFile.setText(DisplayFormatters.formatByteCountToKiBEtc(avgReadToFile)); } else { lblAvgSizeToFile.setText("--"); } lblWritesToCache.setText(DisplayFormatters.formatByteCountToKiBEtc(writesToCache)); lblWritesToFile.setText(DisplayFormatters.formatByteCountToKiBEtc(writesToFile)); long totalNbWrites = nbWritesToCache + nbWritesToFile; if(totalNbWrites > 0) { perThousands = (int) ((1000l * nbWritesToCache) / totalNbWrites); lblPercentWrites.setText(DisplayFormatters.formatPercentFromThousands(perThousands) + " " + MessageText.getString("CacheView.writes.hits")); pbWrites.setSelection(perThousands); } } public String getData() { return "CacheView.title.full"; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/stats/TrackerStatsView.java0000644000175000017500000000246411307334262026021 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.stats; import java.util.List; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerFactory; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerFactoryListener; import org.gudy.azureus2.ui.swt.views.AbstractIView; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; public class TrackerStatsView extends AbstractIView { private AzureusCore core; public TrackerStatsView() { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { init(core); } }); } protected void init(AzureusCore core) { this.core = core; TRTrackerAnnouncerFactory.addListener(new TRTrackerAnnouncerFactoryListener() { public void clientDestroyed(TRTrackerAnnouncer client) { System.out.println("ADD " + client.getTrackerURL().toString()); } public void clientCreated(TRTrackerAnnouncer client) { } }); List dms = core.getGlobalManager().getDownloadManagers(); for (Object oDM : dms) { DownloadManager dm = (DownloadManager) oDM; } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/stats/StatsView.java0000644000175000017500000002042311305326642024501 0ustar adrianadrian/* * Created on Sep 13, 2004 * Created by Olivier Chalouhi * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.stats; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.views.AbstractIView; import org.gudy.azureus2.ui.swt.views.IView; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; /** * */ public class StatsView extends AbstractIView { TabFolder folder; TabItem itemActivity; TabItem itemStats; TabItem itemCache; TabItem[] itemDHTs; TabItem[] itemVivaldis; ActivityView viewActivity; TransferStatsView viewStats; CacheView viewCache; DHTView[] viewDHTs; IView[] viewVivaldis; UpdateThread updateThread; public StatsView() { } private class UpdateThread extends Thread { boolean bContinue; public UpdateThread() { super("StatsView Update Thread"); } public void run() { bContinue = true; while(bContinue) { try { viewActivity.periodicUpdate(); viewCache.periodicUpdate(); viewStats.periodicUpdate(); for (int i=0;i copy to clipboard hash.setCursor(Cursors.handCursor); hash.setForeground(Colors.blue); label.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { String hash_str = hash.getText(); if(hash_str != null && hash_str.length() != 0) new Clipboard(display).setContents(new Object[] {hash_str.replaceAll(" ","")}, new Transfer[] {TextTransfer.getInstance()}); } public void mouseDown(MouseEvent arg0) { String hash_str = hash.getText(); if(hash_str != null && hash_str.length() != 0) new Clipboard(display).setContents(new Object[] {hash_str.replaceAll(" ","")}, new Transfer[] {TextTransfer.getInstance()}); } }); hash.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { String hash_str = hash.getText(); if(hash_str != null && hash_str.length() != 0) new Clipboard(display).setContents(new Object[] {hash_str.replaceAll(" ","")}, new Transfer[] {TextTransfer.getInstance()}); } public void mouseDown(MouseEvent arg0) { String hash_str = hash.getText(); if(hash_str != null && hash_str.length() != 0) new Clipboard(display).setContents(new Object[] {hash_str.replaceAll(" ","")}, new Transfer[] {TextTransfer.getInstance()}); } }); label = new Label(gInfo, SWT.LEFT); Messages.setLanguageText(label, "GeneralView.label.trackerurl"); //$NON-NLS-1$ label.setCursor(Cursors.handCursor); label.setForeground(Colors.blue); label.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { String announce = trackerUrlValue.getText(); if(announce != null && announce.length() != 0) new Clipboard(display).setContents(new Object[] {announce}, new Transfer[] {TextTransfer.getInstance()}); } public void mouseDown(MouseEvent arg0) { String announce = trackerUrlValue.getText(); if(announce != null && announce.length() != 0) new Clipboard(display).setContents(new Object[] {announce}, new Transfer[] {TextTransfer.getInstance()}); } }); menuTracker = new Menu(genComposite.getShell(),SWT.POP_UP); itemSelect = new MenuItem(menuTracker,SWT.CASCADE); Messages.setLanguageText(itemSelect, "GeneralView.menu.selectTracker"); MenuItem itemEdit = new MenuItem(menuTracker,SWT.NULL); Messages.setLanguageText(itemEdit, "MyTorrentsView.menu.editTracker"); itemEdit.addListener( SWT.Selection, new Listener() { public void handleEvent(Event e) { final TOTorrent torrent = manager.getTorrent(); if ( torrent == null ){ return; } List group = TorrentUtils.announceGroupsToList( torrent ); new MultiTrackerEditor(null,group, new TrackerEditorListener() { public void trackersChanged( String str, String str2, List _group ) { TorrentUtils.listToAnnounceGroups( _group, torrent ); try{ TorrentUtils.writeToFile( torrent ); }catch( Throwable e2 ){ Debug.printStackTrace( e2 ); } TRTrackerAnnouncer tc = manager.getTrackerClient(); if ( tc != null ){ tc.resetTrackerUrl( true ); } } }, true); } }); final Listener menuListener = new Listener() { public void handleEvent(Event e) { if( e.widget instanceof MenuItem) { String text = ((MenuItem)e.widget).getText(); TOTorrent torrent = manager.getTorrent(); TorrentUtils.announceGroupsSetFirst(torrent,text); try{ TorrentUtils.writeToFile(torrent); }catch( TOTorrentException f){ Debug.printStackTrace( f ); } TRTrackerAnnouncer tc = manager.getTrackerClient(); if ( tc != null ){ tc.resetTrackerUrl( false ); } } } }; menuTracker.addListener(SWT.Show,new Listener() { public void handleEvent(Event e) { Menu menuSelect = itemSelect.getMenu(); if(menuSelect != null && ! menuSelect.isDisposed()) { menuSelect.dispose(); } if(manager == null || genComposite == null || genComposite.isDisposed()) return; List groups = TorrentUtils.announceGroupsToList(manager.getTorrent()); menuSelect = new Menu(genComposite.getShell(),SWT.DROP_DOWN); itemSelect.setMenu(menuSelect); Iterator iterGroups = groups.iterator(); while(iterGroups.hasNext()) { List trackers = (List) iterGroups.next(); MenuItem menuItem = new MenuItem(menuSelect,SWT.CASCADE); Messages.setLanguageText(menuItem,"wizard.multitracker.group"); Menu menu = new Menu(genComposite.getShell(),SWT.DROP_DOWN); menuItem.setMenu(menu); Iterator iterTrackers = trackers.iterator(); while(iterTrackers.hasNext()) { String url = (String) iterTrackers.next(); MenuItem menuItemTracker = new MenuItem(menu,SWT.CASCADE); menuItemTracker.setText(url); menuItemTracker.addListener(SWT.Selection,menuListener); } } } }); trackerUrlValue = new BufferedTruncatedLabel(gInfo, SWT.LEFT,70); trackerUrlValue.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent event) { if (event.button == 3 || (event.button == 1 && event.stateMask == SWT.CONTROL)) { menuTracker.setVisible(true); } else if (event.button == 1) { String url = trackerUrlValue.getText(); if (url.startsWith("http://") || url.startsWith("https://")) { int pos = -1; if ((pos = url.indexOf("/announce")) != -1) { url = url.substring(0, pos + 1); } Utils.launch(url); } } } }); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 1; trackerUrlValue.setLayoutData(gridData); label = new Label(gInfo, SWT.LEFT); Messages.setLanguageText(label, "GeneralView.label.size"); pieceSize = new BufferedLabel(gInfo, SWT.LEFT); gridData = new GridData(GridData.FILL_HORIZONTAL); pieceSize.setLayoutData(gridData); label = new Label(gInfo, SWT.LEFT); Messages.setLanguageText(label, "GeneralView.label.creationdate"); creation_date = new BufferedLabel(gInfo, SWT.LEFT); gridData = new GridData(GridData.FILL_HORIZONTAL); creation_date.setLayoutData(gridData); label = new Label(gInfo, SWT.LEFT); Messages.setLanguageText(label, "GeneralView.label.private"); privateStatus = new BufferedLabel(gInfo, SWT.LEFT); gridData = new GridData(GridData.FILL_HORIZONTAL); privateStatus.setLayoutData(gridData); // empty row label = new Label(gInfo, SWT.LEFT); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 4; label.setLayoutData(gridData); label = new Label(gInfo, SWT.LEFT); Messages.setLanguageText(label, "GeneralView.label.tracker"); tracker_status = new BufferedTruncatedLabel(gInfo, SWT.LEFT,150); gridData = new GridData(GridData.FILL_HORIZONTAL); tracker_status.setLayoutData(gridData); tracker_status.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent event) { if ( event.button == 1 ){ if ( manager.isUnauthorisedOnTracker()){ AZ3Functions.provider az3 = AZ3Functions.getProvider(); if ( az3 != null && az3.canShowCDP( manager )){ az3.showCDP( manager, "tracker.unauth" ); } } } } }); updateButton = new Button(gInfo, SWT.PUSH); Messages.setLanguageText(updateButton, "GeneralView.label.trackerurlupdate"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gridData.verticalSpan = 2; gridData.horizontalSpan = 2; updateButton.setLayoutData(gridData); updateButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { manager.requestTrackerAnnounce(false); } }); label = new Label(gInfo, SWT.LEFT); Messages.setLanguageText(label, "GeneralView.label.updatein"); trackerUpdateIn = new BufferedLabel(gInfo, SWT.LEFT); gridData = new GridData(GridData.FILL_HORIZONTAL); trackerUpdateIn.setLayoutData(gridData); // empty row label = new Label(gInfo, SWT.LEFT); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 4; label.setLayoutData(gridData); label = new Label(gInfo, SWT.LEFT); label.setCursor(Cursors.handCursor); label.setForeground(Colors.blue); Messages.setLanguageText(label, "GeneralView.label.user_comment"); try { user_comment = new Link(gInfo, SWT.LEFT | SWT.WRAP); ((Link)user_comment).addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Utils.launch(e.text); } }); } catch (Throwable e) { user_comment = new Label(gInfo, SWT.LEFT | SWT.WRAP); } gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; user_comment.setLayoutData(gridData); label.addMouseListener(new MouseAdapter() { private void editComment() { TorrentUtil.promptUserForComment(new DownloadManager[] {manager}); } public void mouseDoubleClick(MouseEvent arg0) {editComment();} public void mouseDown(MouseEvent arg0) {editComment();} }); label = new Label(gInfo, SWT.LEFT); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); Messages.setLanguageText(label, "GeneralView.label.comment"); try { lblComment = new Link(gInfo, SWT.LEFT | SWT.WRAP); ((Link)lblComment).addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Utils.launch(e.text); } }); } catch (Throwable e) { lblComment = new Label(gInfo, SWT.LEFT | SWT.WRAP); } gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 3; lblComment.setLayoutData(gridData); piecesImage.addListener(SWT.Paint, new Listener() { public void handleEvent(Event e) { if (e.count == 0 && e.width > 0 && e.height > 0) { updatePiecesInfo(true); } } }); availabilityImage.addListener(SWT.Paint, new Listener() { public void handleEvent(Event e) { if (e.count == 0 && e.width > 0 && e.height > 0) { updateAvailability(); } } }); genComposite.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { menuTracker.dispose(); } }); genComposite.layout(); //Utils.changeBackgroundComposite(genComposite,MainWindow.getWindow().getBackground()); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IView#getComposite() */ public Composite getComposite() { return genComposite; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IView#refresh() */ public void refresh() { if(gFile == null || gFile.isDisposed() || manager == null) return; loopFactor++; if ((loopFactor % graphicsUpdate) == 0) { updateAvailability(); updatePiecesInfo(false); } DiskManager dm = manager.getDiskManager(); String remaining; String eta = DisplayFormatters.formatETA(manager.getStats().getETA()); if ( dm != null ){ long rem = dm.getRemainingExcludingDND(); String data_rem = DisplayFormatters.formatByteCountToKiBEtc( rem ); // append data length unless we have an eta value and none left if ( rem > 0 ){ remaining = eta + (eta.length()==0?"":" ") + data_rem; }else{ // no bytes left, don't show remaining bytes unless no eta if ( eta.length() == 0 ){ remaining = data_rem; }else{ remaining = eta; } } }else{ // only got eta value, just use that remaining = eta; } setTime(manager.getStats().getElapsedTime(), remaining ); TRTrackerScraperResponse hd = manager.getTrackerScrapeResponse(); String seeds_str = manager.getNbSeeds() +" "+ MessageText.getString("GeneralView.label.connected"); String peers_str = manager.getNbPeers() +" "+ MessageText.getString("GeneralView.label.connected"); String completed; if(hd != null && hd.isValid()) { seeds_str += " ( " + hd.getSeeds() +" "+ MessageText.getString("GeneralView.label.in_swarm") + " )"; peers_str += " ( " + hd.getPeers() +" "+ MessageText.getString("GeneralView.label.in_swarm") + " )"; completed = hd.getCompleted() > -1 ? Integer.toString(hd.getCompleted()) : "?"; } else { completed = "?"; } String _shareRatio = ""; int sr = manager.getStats().getShareRatio(); if(sr == -1) _shareRatio = Constants.INFINITY_STRING; if(sr > 0){ String partial = "" + sr%1000; while(partial.length() < 3) partial = "0" + partial; _shareRatio = (sr/1000) + "." + partial; } DownloadManagerStats stats = manager.getStats(); String swarm_speed = DisplayFormatters.formatByteCountToKiBEtcPerSec( stats.getTotalAverage() ) + " ( " +DisplayFormatters.formatByteCountToKiBEtcPerSec( stats.getTotalAveragePerPeer())+ " " +MessageText.getString("GeneralView.label.averagespeed") + " )"; String swarm_completion = ""; String distributedCopies = "0.000"; String piecesDoneAndSum = ""+manager.getNbPieces(); PEPeerManager pm = manager.getPeerManager(); if( pm != null ) { int comp = pm.getAverageCompletionInThousandNotation(); if( comp >= 0 ) { swarm_completion = DisplayFormatters.formatPercentFromThousands( comp ); } piecesDoneAndSum = pm.getPiecePicker().getNbPiecesDone() + "/" + piecesDoneAndSum; distributedCopies = new DecimalFormat("0.000").format(pm.getPiecePicker().getMinAvailability()-pm.getNbSeeds()-(pm.isSeeding()&&stats.getDownloadCompleted(false)==1000?1:0)); } setStats( DisplayFormatters.formatDownloaded(stats), DisplayFormatters.formatByteCountToKiBEtc(stats.getTotalDataBytesSent()), DisplayFormatters.formatByteCountToKiBEtcPerSec(stats.getDataReceiveRate()), DisplayFormatters.formatByteCountToKiBEtcPerSec(stats.getDataSendRate()), swarm_speed, ""+manager.getStats().getDownloadRateLimitBytesPerSecond() /1024, ""+(manager.getStats().getUploadRateLimitBytesPerSecond() /1024), seeds_str, peers_str, completed, DisplayFormatters.formatHashFails(manager), _shareRatio, swarm_completion, distributedCopies ); setTracker(); TOTorrent torrent = manager.getTorrent(); String creation_date = DisplayFormatters.formatDate(manager.getTorrentCreationDate()*1000); byte[] created_by = torrent == null ? null : torrent.getCreatedBy(); if (created_by != null) { try { creation_date = MessageText.getString("GeneralView.torrent_created_on_and_by", new String[] { creation_date, new String(created_by, Constants.DEFAULT_ENCODING) }); } catch (java.io.UnsupportedEncodingException e) {/* forget it */} } setInfos( manager.getDisplayName(), DisplayFormatters.formatByteCountToKiBEtc(manager.getSize()), DisplayFormatters.formatDownloadStatus(manager), manager.getSaveLocation().toString(), TorrentUtils.nicePrintTorrentHash(torrent), piecesDoneAndSum, manager.getPieceLength(), manager.getTorrentComment(), creation_date, manager.getDownloadState().getUserComment(), MessageText.getString("GeneralView."+(torrent != null && torrent.getPrivate()?"yes":"no")) ); //A special layout, for OS X and Linux, on which for some unknown reason //the initial layout fails. if (loopFactor == 2) { getComposite().layout(true); } } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IView#delete() */ public void delete() { if (aImage != null) aImage.dispose(); aImage = null; if (pImage != null) pImage.dispose(); pImage = null; Utils.disposeComposite(genComposite); COConfigurationManager.removeParameterListener("Graphics Update", this); } public String getData() { return "GeneralView.title.short"; //$NON-NLS-1$ } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IView#getFullTitle() */ public String getFullTitle() { return MessageText.getString("GeneralView.title.full"); //$NON-NLS-1$ } private void updateAvailability() { if (manager == null) return; try{ this_mon.enter(); final int[] available; PEPeerManager pm = manager.getPeerManager(); if (manager.getPeerManager() == null) { if (availabilityPercent.getText() != "") availabilityPercent.setText(""); available = new int[manager.getNbPieces()]; }else{ available = pm.getAvailability(); } if (display == null || display.isDisposed()) return; if (availabilityImage == null || availabilityImage.isDisposed()) { return; } Rectangle bounds = availabilityImage.getClientArea(); int xMax = bounds.width - 2; int yMax = bounds.height - 2; if (xMax < 10 || yMax < 5){ return; } if (aImage != null && !aImage.isDisposed()){ aImage.dispose(); } aImage = new Image(display, bounds.width, bounds.height); GC gc = new GC(availabilityImage); GC gcImage = new GC(aImage); try{ gcImage.setForeground(Colors.grey); gcImage.drawRectangle(0, 0, bounds.width-1, bounds.height-1); int allMin = 0; int allMax = 0; int total = 0; String sTotal = "000"; if (available != null) { allMin = available.length==0?0:available[0]; allMax = available.length==0?0:available[0]; int nbPieces = available.length; for (int i = 0; i < nbPieces; i++) { if (available[i] < allMin) allMin = available[i]; if (available[i] > allMax) allMax = available[i]; } int maxAboveMin = allMax - allMin; if (maxAboveMin == 0) { // all the same.. easy paint gcImage.setBackground(Colors.blues[allMin == 0 ? Colors.BLUES_LIGHTEST : Colors.BLUES_DARKEST]); gcImage.fillRectangle(1, 1, xMax, yMax); } else { for (int i = 0; i < nbPieces; i++) { if (available[i] > allMin) total++; } total = (total * 1000) / nbPieces; sTotal = "" + total; if (total < 10) sTotal = "0" + sTotal; if (total < 100) sTotal = "0" + sTotal; for (int i = 0; i < xMax; i++) { int a0 = (i * nbPieces) / xMax; int a1 = ((i + 1) * nbPieces) / xMax; if (a1 == a0) a1++; if (a1 > nbPieces) a1 = nbPieces; int max = 0; int min = available[a0]; int Pi = 1000; for (int j = a0; j < a1; j++) { if (available[j] > max) max = available[j]; if (available[j] < min) min = available[j]; Pi *= available[j]; Pi /= (available[j] + 1); } int pond = Pi; if (max == 0) pond = 0; else { int PiM = 1000; for (int j = a0; j < a1; j++) { PiM *= (max + 1); PiM /= max; } pond *= PiM; pond /= 1000; pond *= (max - min); pond /= 1000; pond += min; } int index; if (pond <= 0 || allMax == 0) { index = 0; } else { // we will always have allMin, so subtract that index = (pond - allMin) * (Colors.BLUES_DARKEST - 1) / maxAboveMin + 1; // just in case? if (index > Colors.BLUES_DARKEST) { index = Colors.BLUES_DARKEST; } } gcImage.setBackground(Colors.blues[index]); gcImage.fillRectangle(i+1, 1, 1, yMax); } } } if (availabilityPercent == null || availabilityPercent.isDisposed()) { return; } availabilityPercent.setText(allMin + "." + sTotal); gc.drawImage(aImage, bounds.x, bounds.y); }finally{ gcImage.dispose(); gc.dispose(); } }finally{ this_mon.exit(); } } private void updatePiecesInfo(boolean bForce) { if (manager == null) return; try{ this_mon.enter(); if (display == null || display.isDisposed()) return; if (piecesImage == null || piecesImage.isDisposed()) return; DiskManager dm = manager.getDiskManager(); boolean valid = !bForce; boolean[] new_pieces = new boolean[manager.getNbPieces()]; if ( dm != null ){ DiskManagerPiece[] dm_pieces = dm.getPieces(); for (int i=0;i nbPieces) a1 = nbPieces; int nbAvailable = 0; for (int j = a0; j < a1; j++) { if (pieces[j]) { nbAvailable++; } int index = (nbAvailable * Colors.BLUES_DARKEST) / (a1 - a0); gcImage.setBackground(Colors.blues[index]); gcImage.fillRectangle(i+1,7,1,yMax); } } } // draw file % bar above int limit = (xMax * total) / 1000; gcImage.setBackground(Colors.colorProgressBar); gcImage.fillRectangle(1,1,limit,5); if (limit < xMax) { gcImage.setBackground(Colors.blues[Colors.BLUES_LIGHTEST]); gcImage.fillRectangle(limit+1,1,xMax-limit,5); } }finally{ gcImage.dispose(); } if (piecesPercent != null && !piecesPercent.isDisposed()) piecesPercent.setText(DisplayFormatters.formatPercentFromThousands(total)); if (pImage == null || pImage.isDisposed()) { return; } GC gc = new GC(piecesImage); gc.drawImage(pImage, bounds.x, bounds.y); gc.dispose(); } }finally{ this_mon.exit(); } } private void setTime(String elapsed, String remaining) { timeElapsed.setText( elapsed ); timeRemaining.setText( remaining); } private void setStats( String dl, String ul, String dls, String uls, String ts, String dl_speed, String ul_speed, String s, String p, String completed, String hash_fails, String share_ratio, String ave_comp, String distr_copies ) { if (display == null || display.isDisposed()) return; download.setText( dl ); downloadSpeed.setText( dls ); upload.setText( ul ); uploadSpeed.setText( uls ); totalSpeed.setText( ts ); ave_completion.setText( ave_comp ); distributedCopies.setText(distr_copies); /* if ( !maxDLSpeed.getText().equals( dl_speed )){ maxDLSpeed.setText( dl_speed ); } if ( !maxULSpeed.getText().equals( ul_speed )){ maxULSpeed.setText( ul_speed ); } */ seeds.setText( s); peers.setText( p); completedLbl.setText(completed); hashFails.setText( hash_fails); shareRatio.setText( share_ratio); } private void setTracker(){ if (display == null || display.isDisposed()) return; String status = manager.getTrackerStatus(); int time = manager.getTrackerTime(); TRTrackerAnnouncer trackerClient = manager.getTrackerClient(); tracker_status.setText( status ); boolean show_cdp_link = false; if ( manager.isUnauthorisedOnTracker()){ AZ3Functions.provider az3 = AZ3Functions.getProvider(); show_cdp_link = az3 != null && az3.canShowCDP( manager ); } if ( show_cdp_link ){ tracker_status.setForeground(Colors.colorError); tracker_status.setCursor(Cursors.handCursor); }else{ tracker_status.setForeground(null); tracker_status.setCursor(null); } if ( time < 0 ){ trackerUpdateIn.setText( MessageText.getString("GeneralView.label.updatein.querying")); }else{ trackerUpdateIn.setText( TimeFormatter.formatColon( time )); } boolean update_state; String trackerURL = null; if ( trackerClient != null ){ URL temp = trackerClient.getTrackerURL(); if ( temp != null ){ trackerURL = temp.toString(); } } if ( trackerURL == null ){ TOTorrent torrent = manager.getTorrent(); if( torrent != null ){ trackerURL = torrent.getAnnounceURL().toString(); } } if ( trackerURL != null ){ trackerUrlValue.setText( trackerURL ); if((trackerURL.startsWith("http://")||trackerURL.startsWith("https://"))) { trackerUrlValue.setForeground(Colors.blue); trackerUrlValue.setCursor(Cursors.handCursor); Messages.setLanguageText(trackerUrlValue.getWidget(), "GeneralView.label.trackerurlopen.tooltip", true); } else { trackerUrlValue.setForeground(null); trackerUrlValue.setCursor(null); Messages.setLanguageText(trackerUrlValue.getWidget(), null); trackerUrlValue.setToolTipText(null); } } if ( trackerClient != null ){ update_state = ((SystemTime.getCurrentTime()/1000 - trackerClient.getLastUpdateTime() >= TRTrackerAnnouncer.REFRESH_MINIMUM_SECS )); }else{ update_state = false; } if ( updateButton.getEnabled() != update_state ){ updateButton.setEnabled( update_state ); } } private void setInfos( final String _fileName, final String _fileSize, final String _torrentStatus, final String _path, final String _hash, final String _pieceData, final String _pieceLength, final String _comment, final String _creation_date, final String _user_comment, final String isPrivate) { if (display == null || display.isDisposed()) return; Utils.execSWTThread(new AERunnable() { public void runSupport() { fileName.setText(_fileName); fileSize.setText(_fileSize); torrentStatus.setText(_torrentStatus); int pos = _torrentStatus.indexOf( "http://" ); if ( pos > 0 ){ torrentStatus.setLink( UrlUtils.getURL( _torrentStatus )); }else{ torrentStatus.setLink( null ); } saveIn.setText(_path); hash.setText(_hash); pieceNumber.setText(_pieceData); //$NON-NLS-1$ pieceSize.setText(_pieceLength); creation_date.setText(_creation_date); privateStatus.setText(isPrivate); boolean do_relayout = false; do_relayout = setCommentAndFormatLinks(lblComment, _comment.length() > 5000 && Constants.isWindowsXP ? _comment.substring(0, 5000) : _comment ) | do_relayout; do_relayout = setCommentAndFormatLinks(user_comment, _user_comment) | do_relayout; if (do_relayout) { gInfo.layout(); } } }); } private static boolean setCommentAndFormatLinks(Control c, String new_comment) { String old_comment = (String)c.getData("comment"); if (new_comment == null) {new_comment = "";} if (new_comment.equals(old_comment)) {return false;} c.setData("comment", new_comment); if (c instanceof Label) { ((Label) c).setText(new_comment); } else if (c instanceof Link) { String sNewComment; sNewComment = new_comment.replaceAll( "([^=\">][\\s]+|^)(http://[\\S]+)", "$1$2"); // need quotes around url sNewComment = sNewComment.replaceAll("(href=)(htt[^\\s>]+)", "$1\"$2\""); // Examples: // http://cowbow.com/fsdjl&sdfkj=34.sk9391 moo // moo // moo // http://moo.com ((Link)c).setText(sNewComment); } return true; } public void parameterChanged(String parameterName) { graphicsUpdate = COConfigurationManager.getIntParameter("Graphics Update"); } public Image obfusticatedImage(Image image, Point shellOffset) { UIDebugGenerator.obfusticateArea(image, (Control) fileName.getWidget(), shellOffset, manager.toString()); UIDebugGenerator.obfusticateArea(image, (Control) saveIn.getWidget(), shellOffset, Debug.secretFileName(saveIn.getText())); return image; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/0000755000175000017500000000000011310377636021642 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/TableViewFilterCheck.java0000644000175000017500000000202011264300532026452 0ustar adrianadrian/** * Created on Oct 4, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.views.table; /** * @author TuxPaper * @created Oct 4, 2009 * */ public interface TableViewFilterCheck { public boolean filterCheck(DATASOURCETYPE ds, String filter, boolean regex); public void filterSet(String filter); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/TableViewSWTPanelCreator.java0000644000175000017500000000035510566514600027264 0ustar adrianadrian/** * */ package org.gudy.azureus2.ui.swt.views.table; import org.eclipse.swt.widgets.Composite; /** * @author TuxPaper * */ public interface TableViewSWTPanelCreator { public Composite createTableViewPanel(Composite parent); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/TableCellSWTPaintListener.java0000644000175000017500000000174611066731146027442 0ustar adrianadrian/** * Created on Sep 19, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.views.table; import org.eclipse.swt.graphics.GC; /** * @author TuxPaper * @created Sep 19, 2008 * */ public interface TableCellSWTPaintListener { public void cellPaint(GC gc, TableCellSWT cell); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/impl/0000755000175000017500000000000011310377636022603 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/impl/TableRowImpl.java0000644000175000017500000003746711153765546026036 0ustar adrianadrian/* * File : TableRowImpl.java * Originally TorrentRow.java, and changed to be more generic by TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.table.impl; import java.util.*; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Table; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.BufferedTableRow; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableRowSWT; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import com.aelitis.azureus.ui.common.table.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; /** Represents an entire row in a table. Stores each cell belonging to the * row and handles refreshing them. * * @see TableCellImpl * * @author TuxPaper * 2005/Oct/07: Moved TableItem.SetData("TableRow", ..) to * BufferedTableRow * 2005/Oct/07: Removed all calls to BufferedTableRoe.getItem() */ public class TableRowImpl extends BufferedTableRow implements TableRowSWT { /** List of cells in this column. They are not stored in display order */ private Map mTableCells; private String sTableID; private Object coreDataSource; private Object pluginDataSource; private boolean bDisposed; private boolean bSetNotUpToDateLastRefresh = false; private TableView tableView; private static AEMonitor this_mon = new AEMonitor( "TableRowImpl" ); private ArrayList mouseListeners; private boolean wasShown = false; private Map dataList; private int lastIndex = -1; private int fontStyle; private int alpha = 255; // XXX add rowVisuallyupdated bool like in ListRow /** * Default constructor * * @param table * @param sTableID * @param columnsSorted * @param dataSource * @param bSkipFirstColumn */ public TableRowImpl(TableView tv, Table table, String sTableID, TableColumnCore[] columnsSorted, Object dataSource, boolean bSkipFirstColumn) { super(table); this.tableView = tv; this.sTableID = sTableID; coreDataSource = dataSource; mTableCells = new LightHashMap(); bDisposed = false; // create all the cells for the column for (int i = 0; i < columnsSorted.length; i++) { if (columnsSorted[i] == null) continue; //System.out.println(dataSource + ": " + tableColumns[i].getName() + ": " + tableColumns[i].getPosition()); TableCellImpl cell = new TableCellImpl(TableRowImpl.this, columnsSorted[i], bSkipFirstColumn ? i+1 : i); mTableCells.put(columnsSorted[i].getName(), cell); //if (i == 10) cell.bDebug = true; } } public boolean isValid() { if (bDisposed) return true; boolean valid = true; Iterator iter = mTableCells.values().iterator(); while (iter.hasNext()) { TableCellSWT cell = (TableCellSWT)iter.next(); if (cell != null) valid &= cell.isValid(); } return valid; } /** TableRow Implementation which returns the * associated plugin object for the row. Core Column Object who wish to get * core data source must re-class TableRow as TableRowCore and use * getDataSource(boolean) * * @see TableRowCore.getDataSource() */ public Object getDataSource() { return getDataSource(false); } public String getTableID() { return sTableID; } public TableCell getTableCell(String field) { if (bDisposed) return null; return (TableCell)mTableCells.get(field); } public void addMouseListener(TableRowMouseListener listener) { try { this_mon.enter(); if (mouseListeners == null) mouseListeners = new ArrayList(1); mouseListeners.add(listener); } finally { this_mon.exit(); } } public void removeMouseListener(TableRowMouseListener listener) { try { this_mon.enter(); if (mouseListeners == null) return; mouseListeners.remove(listener); } finally { this_mon.exit(); } } public void invokeMouseListeners(TableRowMouseEvent event) { ArrayList listeners = mouseListeners; if (listeners == null) return; for (int i = 0; i < listeners.size(); i++) { try { TableRowMouseListener l = (TableRowMouseListener) (listeners.get(i)); l.rowMouseTrigger(event); } catch (Throwable e) { Debug.printStackTrace(e); } } } /* Start Core-Only functions */ /////////////////////////////// public void delete() { this_mon.enter(); try { if (bDisposed) return; if (TableViewSWT.DEBUGADDREMOVE) System.out.println((table.isDisposed() ? "" : table.getData("Name")) + " row delete; index=" + getIndex()); Iterator iter = mTableCells.values().iterator(); while (iter.hasNext()) { TableCellSWT item = (TableCellSWT) iter.next(); item.dispose(); } setForeground((Color) null); bDisposed = true; } finally { this_mon.exit(); } } public List refresh(boolean bDoGraphics) { if (bDisposed) { return Collections.EMPTY_LIST; } boolean bVisible = isVisible(); return refresh(bDoGraphics, bVisible); } public List refresh(boolean bDoGraphics, boolean bVisible) { // If this were called from a plugin, we'd have to refresh the sorted column // even if we weren't visible List list = Collections.EMPTY_LIST; if (bDisposed) { return list; } if (!bVisible) { if (!bSetNotUpToDateLastRefresh) { setUpToDate(false); bSetNotUpToDateLastRefresh = true; } return list; } bSetNotUpToDateLastRefresh = false; //System.out.println(SystemTime.getCurrentTime() + "refresh " + getIndex() + ";vis=" + bVisible); ((TableViewSWTImpl)tableView).invokeRefreshListeners(this); Iterator iter = mTableCells.values().iterator(); while (iter.hasNext()) { TableCellSWT item = (TableCellSWT) iter.next(); TableColumn column = item.getTableColumn(); //System.out.println(column); if (column != tableView.getSortColumn() && !tableView.isColumnVisible(column)) { //System.out.println("skip " + column); continue; } boolean changed = item.refresh(bDoGraphics, bVisible); if (changed) { if(list == Collections.EMPTY_LIST) list = new ArrayList(mTableCells.size()); list.add(item); } } //System.out.println(); return list; } public void setAlternatingBGColor(boolean bEvenIfNotVisible) { super.setAlternatingBGColor(bEvenIfNotVisible); } public void locationChanged(int iStartColumn) { if (bDisposed || !isVisible()) return; Iterator iter = mTableCells.values().iterator(); while(iter.hasNext()) { TableCellSWT item = (TableCellSWT)iter.next(); if (item.getTableColumn().getPosition() > iStartColumn) item.locationChanged(); } } public void doPaint(GC gc) { doPaint(gc, isVisible()); } // @see org.gudy.azureus2.ui.swt.views.table.TableRowSWT#doPaint(org.eclipse.swt.graphics.GC, boolean, boolean) public void doPaint(GC gc, boolean bVisible) { if (bDisposed || !bVisible) return; Iterator iter = mTableCells.values().iterator(); while(iter.hasNext()) { TableCellSWT cell = (TableCellSWT) iter.next(); if (cell == null) { continue; } // if (bOnlyIfChanged && !cell.getVisuallyChangedSinceRefresh()) { // continue; // } if (cell.needsPainting()) { cell.doPaint(gc); } } } public TableCellCore getTableCellCore(String field) { if (bDisposed) return null; return (TableCellCore)mTableCells.get(field); } /** * @param name * @return */ public TableCellSWT getTableCellSWT(String name) { if (bDisposed) return null; return (TableCellSWT)mTableCells.get(name); } public Object getDataSource(boolean bCoreObject) { if (bDisposed) return null; if (bCoreObject) return coreDataSource; if (pluginDataSource != null) return pluginDataSource; pluginDataSource = PluginCoreUtils.convert(coreDataSource, bCoreObject); return pluginDataSource; } public boolean isRowDisposed() { return bDisposed; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#getIndex() */ public int getIndex() { if (bDisposed) return -1; if (lastIndex >= 0) { TableRowCore row = ((TableViewSWTImpl) tableView).getRowQuick(lastIndex); if (row == this) { return lastIndex; } } lastIndex = ((TableViewSWTImpl) tableView).indexOf(this); return lastIndex; //return super.getIndex(); } public int getRealIndex() { return super.getIndex(); } public boolean setTableItem(int newIndex, boolean isVisible) { if (bDisposed) { System.out.println("XXX setTI: bDisposed from " + Debug.getCompressedStackTrace()); return false; } //if (getRealIndex() != newIndex) { // ((TableViewSWTImpl)tableView).debug("sTI " + newIndex + "; via " + Debug.getCompressedStackTrace(4)); //} boolean changed = super.setTableItem(newIndex, false, isVisible); if (lastIndex != newIndex) { lastIndex = newIndex; } setShown(tableView.isRowVisible(this), changed); return changed; } public boolean setTableItem(int newIndex) { return setTableItem(newIndex,true); } private static final boolean DEBUG_SET_FOREGROUND = System.getProperty("debug.setforeground") != null; private static void setForegroundDebug(String method_sig, Color c) { if (DEBUG_SET_FOREGROUND && c != null) { Debug.out("BufferedTableRow " + method_sig + " -> " + c); } } private static void setForegroundDebug(String method_sig, int r, int g, int b) { if (DEBUG_SET_FOREGROUND && (!(r == 0 && g == 0 && b == 0))) { Debug.out("BufferedTableRow " + method_sig + " -> " + r + "," + g + "," + b); } } // @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#setForeground(int, int, int) public void setForeground(int r, int g, int b) { setForegroundDebug("setForeground(r, g, b)", r, g, b); // Don't need to set when not visible if (!isVisible()) { return; } super.setForeground(r, g, b); } // @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#setForeground(org.eclipse.swt.graphics.Color) public void setForeground(final Color c) { setForegroundDebug("setForeground(Color)", c); // Don't need to set when not visible if (!isVisible()) return; Utils.execSWTThread(new AERunnable() { public void runSupport() { TableRowImpl.this.setForegroundInSWTThread(c); } }); } private void setForegroundInSWTThread(Color c) { setForegroundDebug("setForegroundInSWTThread(Color)", c); if (!isVisible()) return; super.setForeground(c); } // @see org.gudy.azureus2.plugins.ui.tables.TableRow#setForeground(int[]) public void setForeground(int[] rgb) { if (rgb == null || rgb.length < 3) { setForeground((Color) null); return; } setForeground(rgb[0], rgb[1], rgb[2]); } public void setForegroundToErrorColor() { this.setForeground(Colors.colorError); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#invalidate() */ public void invalidate() { super.invalidate(); if (bDisposed) return; Iterator iter = mTableCells.values().iterator(); while (iter.hasNext()) { TableCellSWT cell = (TableCellSWT)iter.next(); if (cell != null) cell.invalidate(true); } } public void setUpToDate(boolean upToDate) { if (bDisposed) return; Iterator iter = mTableCells.values().iterator(); while (iter.hasNext()) { TableCellSWT cell = (TableCellSWT)iter.next(); if (cell != null) cell.setUpToDate(upToDate); } } // @see com.aelitis.azureus.ui.common.table.TableRowCore#redraw() public void redraw() { // this will call paintItem which may call refresh Rectangle bounds = getBounds(); table.redraw(bounds.x, bounds.y, bounds.width, bounds.height, false); } public String toString() { String result = "TableRowImpl@" + Integer.toHexString(hashCode()) + "/#" + lastIndex; return result; } // @see com.aelitis.azureus.ui.common.table.TableRowCore#getView() public TableView getView() { return tableView; } /** * @param b * * @since 3.0.4.3 */ public void setShown(boolean b, boolean force) { if (bDisposed) return; if (b == wasShown && !force) { return; } wasShown = b; Iterator iter = mTableCells.values().iterator(); while (iter.hasNext()) { TableCellSWT cell = (TableCellSWT)iter.next(); if (cell != null) { cell.invokeVisibilityListeners(b ? TableCellVisibilityListener.VISIBILITY_SHOWN : TableCellVisibilityListener.VISIBILITY_HIDDEN, true); } } } public boolean isMouseOver() { return tableView.getTableRowWithCursor() == this; } public void setData(String id, Object data) { if (dataList == null) { dataList = new HashMap(1); } if (data == null) { dataList.remove("id"); } else { dataList.put(id, data); } } public Object getData(String id) { return dataList == null ? null : dataList.get(id); } // @see com.aelitis.azureus.ui.common.table.TableRowCore#setDrawableHeight(int) public boolean setDrawableHeight(int height) { return setHeight(height); } // @see org.gudy.azureus2.ui.swt.views.table.TableRowSWT#getBounds() public Rectangle getBounds() { Rectangle bounds = getBounds(1); if (bounds == null) { return new Rectangle(0, 0, 0, 0); } bounds.x = 0; bounds.width = table.getSize().x; return bounds; } // @see org.gudy.azureus2.ui.swt.views.table.TableRowSWT#setFontStyle(int) public boolean setFontStyle(int style) { if (fontStyle == style) { return false; } fontStyle = style; invalidate(); return true; } // @see com.aelitis.azureus.ui.common.table.TableRowCore#setAlpha(int) public boolean setAlpha(int alpha) { if (this.alpha == alpha) { return false; } this.alpha = alpha; invalidate(); return true; } // @see org.gudy.azureus2.ui.swt.views.table.TableRowSWT#getAlpha() public int getAlpha() { return alpha; } // @see org.gudy.azureus2.ui.swt.views.table.TableRowSWT#getFontStyle() public int getFontStyle() { return fontStyle; } // @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#isVisible() public boolean isVisible() { return Utils.execSWTThreadWithBool("isVisible", new AERunnableBoolean() { public boolean runSupport() { return TableRowImpl.super.isVisible(); } }, 1000); } // @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#setSelected(boolean) public void setSelected(boolean selected) { super.setSelected(selected); if (tableView instanceof TableViewSWTImpl) { ((TableViewSWTImpl)tableView).updateSelectedRowIndexes(); } } // @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#isSelected() public boolean isSelected() { return Utils.execSWTThreadWithBool("isSelected", new AERunnableBoolean() { public boolean runSupport() { return TableRowImpl.super.isSelected(); } }, 1000); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/impl/TableViewTab.java0000644000175000017500000000635611272502262025761 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.table.impl; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.ui.swt.views.AbstractIView; import org.gudy.azureus2.ui.swt.views.IViewExtension; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; public abstract class TableViewTab extends AbstractIView implements IViewExtension { private TableViewSWT tv; private Object parentDataSource; private final String propertiesPrefix; private Composite composite; public TableViewTab(String propertiesPrefix) { this.propertiesPrefix = propertiesPrefix; } public TableViewSWT getTableView() { return tv; } public final void initialize(Composite composite) { tv = initYourTableView(); Composite parent = initComposite(composite); tv.initialize(parent); if (parent != composite) { this.composite = composite; } else { this.composite = tv.getComposite(); } tableViewTabInitComplete(); if (parentDataSource != null) { tv.setParentDataSource(parentDataSource); } } public void tableViewTabInitComplete() { } public Composite initComposite(Composite composite) { return composite; } public abstract TableViewSWT initYourTableView(); public final void dataSourceChanged(Object newDataSource) { this.parentDataSource = newDataSource; if (tv != null) { tv.setParentDataSource(newDataSource); } } public void updateLanguage() { super.updateLanguage(); if (tv != null) { tv.updateLanguage(); } } public final void refresh() { if (tv != null) { tv.refreshTable(false); } } // @see org.gudy.azureus2.ui.swt.views.AbstractIView#delete() public final void delete() { if (tv != null) { tv.delete(); } super.delete(); } // @see org.gudy.azureus2.ui.swt.views.AbstractIView#getData() public final String getData() { return getPropertiesPrefix() + ".title.short"; } public final String getFullTitle() { return MessageText.getString(getPropertiesPrefix() + ".title.full"); } // @see org.gudy.azureus2.ui.swt.views.AbstractIView#generateDiagnostics(org.gudy.azureus2.core3.util.IndentWriter) public final void generateDiagnostics(IndentWriter writer) { if (tv != null) { tv.generate(writer); } } // @see org.gudy.azureus2.ui.swt.views.AbstractIView#getComposite() public Composite getComposite() { return composite; } public void itemActivated(String itemKey) { if (itemKey.equals("editcolumns")) { if (tv instanceof TableViewSWTImpl) { ((TableViewSWTImpl)tv).showColumnEditor(); } } } public boolean isEnabled(String itemKey) { if (itemKey.equals("editcolumns")) {return true;} return false; } public String getPropertiesPrefix() { return propertiesPrefix; } public Menu getPrivateMenu() { return null; } public void viewActivated() { // cheap hack.. calling isVisible freshens table's visible status (and // updates subviews) if (tv instanceof TableViewSWTImpl) { ((TableViewSWTImpl)tv).isVisible(); } } public void viewDeactivated() { if (tv instanceof TableViewSWTImpl) { ((TableViewSWTImpl)tv).isVisible(); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWTImpl.java0000644000175000017500000044015611305317246026555 0ustar adrianadrian/* * Created on 2004/Apr/18 * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.table.impl; import java.lang.reflect.Method; import java.util.*; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.*; import org.eclipse.swt.dnd.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.config.impl.ConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.common.util.MenuItemManager; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.debug.ObfusticateImage; import org.gudy.azureus2.ui.swt.debug.UIDebugGenerator; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.views.IView; import org.gudy.azureus2.ui.swt.views.IViewExtension; import org.gudy.azureus2.ui.swt.views.columnsetup.TableColumnSetupWindow; import org.gudy.azureus2.ui.swt.views.table.*; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnSWTUtils; import org.gudy.azureus2.ui.swt.views.table.utils.TableContextMenuManager; import com.aelitis.azureus.ui.common.table.*; import com.aelitis.azureus.ui.common.table.impl.TableViewImpl; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.utils.ColorCache; import org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent; import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem; import org.gudy.azureus2.plugins.ui.tables.TableRowRefreshListener; import org.gudy.azureus2.pluginsimpl.local.ui.tables.TableContextMenuItemImpl; /** * An IView with a sortable table. Handles composite/menu/table creation * and management. * * @author Olivier (Original PeersView/MyTorrentsView/etc code) * @author TuxPaper * 2004/Apr/20: Remove need for tableItemToObject * 2005/Oct/07: Virtual Table * 2005/Nov/16: Moved TableSorter into TableView * * @note From TableSorter.java:
*
  • 2004/Apr/20: Remove need for tableItemToObject (store object in tableItem.setData) *
  • 2004/May/11: Use Comparable instead of SortableItem *
  • 2004/May/14: moved from org.gudy.azureus2.ui.swt.utils *
  • 2005/Oct/10: v2307 : Sort SWT.VIRTUAL Tables, Column Indicator * * @future TableView should be split into two. One for non SWT functions, and * the other extending the first, with extra SWT stuff. * * @future dataSourcesToRemove should be removed after a certain amount of time * has passed. Currently, dataSourcesToRemove is processed every * refresh IF the table is visible, or it is processed when we collect * 20 items to remove. * * @note 4005: We set a text cell's measured width to the columns prefered width * instead of setting it to the actual space needed for the text. * We should really store the last measured width in TableCell and * use that. */ public class TableViewSWTImpl extends TableViewImpl implements ParameterListener, TableViewSWT, TableStructureModificationListener, ObfusticateImage, KeyListener { private final static LogIDs LOGID = LogIDs.GUI; /** Virtual Tables still a work in progress */ // Non-Virtual tables scroll faster with they keyboard // Virtual tables don't flicker when updating a cell (Windows) private final static boolean DISABLEVIRTUAL = SWT.getVersion() < 3138; private static final boolean DEBUG_SORTER = false; // Shorter name for ConfigManager, easier to read code private static final ConfigurationManager configMan = ConfigurationManager.getInstance(); private static final String CFG_SORTDIRECTION = "config.style.table.defaultSortOrder"; private static final long BREAKOFF_ADDTOMAP = 1000; private static final long BREAKOFF_ADDROWSTOSWT = 800; private static final boolean TRIGGER_PAINT_ON_SELECTIONS = false; private static final int ASYOUTYPE_MODE_FIND = 0; private static final int ASYOUTYPE_MODE_FILTER = 1; private static final int ASYOUTYPE_MODE = ASYOUTYPE_MODE_FILTER; private static final int ASYOUTYPE_UPDATEDELAY = 300; private static final Color COLOR_FILTER_REGEX = Colors.fadedYellow; private static final boolean DEBUG_CELL_CHANGES = false; /** TableID (from {@link org.gudy.azureus2.plugins.ui.tables.TableManager}) * of the table this class is * handling. Config settings are stored with the prefix of * "Table.TableID" */ protected String sTableID; /** Prefix for retrieving text from the properties file (MessageText) * Typically TableID + "View" */ protected String sPropertiesPrefix; /** Column name to sort on if user hasn't chosen one yet */ protected String sDefaultSortOn; /** 1st column gap problem (Eclipse Bug 43910). Set to true when table is * using TableItem.setImage */ private boolean bSkipFirstColumn; private Point ptIconSize = null; /** Basic (pre-defined) Column Definitions */ private TableColumnCore[] basicItems; /** All Column Definitions. The array is not necessarily in column order */ private TableColumnCore[] tableColumns; /** Composite for IView implementation */ private Composite mainComposite; /** Composite that stores the table (sometimes the same as mainComposite) */ private Composite tableComposite; /** Table for SortableTable implementation */ private Table table; private TableEditor editor; /** SWT style options for the creation of the Table */ protected int iTableStyle; /** Whether the Table is Virtual */ private boolean bTableVirtual; /** Context Menu */ private Menu menu; /** Link DataSource to their row in the table. * key = DataSource * value = TableRowSWT */ private Map mapDataSourceToRow; private AEMonitor listUnfilteredDatasources_mon = new AEMonitor("TableView:uds"); private Set listUnfilteredDataSources; private AEMonitor dataSourceToRow_mon = new AEMonitor("TableView:OTSI"); private List sortedRows; private AEMonitor sortedRows_mon = new AEMonitor("TableView:sR"); private AEMonitor sortColumn_mon = new AEMonitor("TableView:sC"); /** Sorting functions */ protected TableColumnCore sortColumn; /** TimeStamp of when last sorted all the rows was */ private long lLastSortedOn; /** For updating GUI. * Some UI objects get updating every X cycles (user configurable) */ protected int loopFactor; /** How often graphic cells get updated */ protected int graphicsUpdate = configMan.getIntParameter("Graphics Update"); protected int reOrderDelay = configMan.getIntParameter("ReOrder Delay"); /** * Cache of selected table items to bypass insufficient drawing on Mac OS X */ //private ArrayList oldSelectedItems; /** We need to remember the order of the columns at the time we added them * in case the user drags the columns around. */ private TableColumnCore[] columnsOrdered; private boolean[] columnsVisible; private ColumnMoveListener columnMoveListener = new ColumnMoveListener(); /** Queue added datasources and add them on refresh */ private LightHashSet dataSourcesToAdd = new LightHashSet(4); /** Queue removed datasources and add them on refresh */ private LightHashSet dataSourcesToRemove = new LightHashSet(4); private boolean bReallyAddingDataSources = false; /** TabViews */ public boolean bEnableTabViews = false; /** TabViews */ private CTabFolder tabFolder; /** TabViews */ private ArrayList tabViews = new ArrayList(1); private int lastTopIndex = 0; private int lastBottomIndex = -1; protected IView[] coreTabViews = null; private long lCancelSelectionTriggeredOn = -1; private List listenersMenuFill = new ArrayList( 1); private TableViewSWTPanelCreator mainPanelCreator; private List listenersKey = new ArrayList(1); private boolean columnPaddingAdjusted = false; private boolean columnVisibilitiesChanged = true; // What type of data is stored in this table private final Class classPluginDataSourceType; private AEMonitor listeners_mon = new AEMonitor("tablelisteners"); private ArrayList refreshListeners; private Font fontBold; private Rectangle clientArea; private boolean isVisible; private boolean menuEnabled = true; private boolean headerVisible = true; /** * Up to date list of selected rows, so we can access rows without being on SWT Thread */ private int[] selectedRowIndexes; private List listSelectedCoreDataSources; private Utils.addDataSourceCallback processDataSourceQueueCallback = new Utils.addDataSourceCallback() { public void process() { processDataSourceQueue(); } public void debug(String str) { TableViewSWTImpl.this.debug(str); } }; // private Rectangle firstClientArea; private int lastHorizontalPos; // class used to keep filter stuff in a nice readable parcel class filter { Text widget = null; TimerEvent eventUpdate; String text = ""; long lastFilterTime; boolean regex = false; TableViewFilterCheck checker; String nextText = ""; ModifyListener widgetModifyListener; }; filter filter; /** * Main Initializer * @param _sTableID Which table to handle (see * {@link org.gudy.azureus2.plugins.ui.tables.TableManager}). * Config settings are stored with the prefix of * "Table.TableID" * @param _sPropertiesPrefix Prefix for retrieving text from the properties * file (MessageText). Typically * TableID + "View" * @param _basicItems Column Definitions * @param _sDefaultSortOn Column name to sort on if user hasn't chosen one yet * @param _iTableStyle SWT style constants used when creating the table */ public TableViewSWTImpl(Class pluginDataSourceType, String _sTableID, String _sPropertiesPrefix, TableColumnCore[] _basicItems, String _sDefaultSortOn, int _iTableStyle) { classPluginDataSourceType = pluginDataSourceType; sTableID = _sTableID; basicItems = _basicItems; sPropertiesPrefix = _sPropertiesPrefix; sDefaultSortOn = _sDefaultSortOn; iTableStyle = _iTableStyle | SWT.V_SCROLL; if (DISABLEVIRTUAL) { iTableStyle &= ~(SWT.VIRTUAL); } bTableVirtual = (iTableStyle & SWT.VIRTUAL) != 0; mapDataSourceToRow = new LightHashMap(); sortedRows = new ArrayList(); listUnfilteredDataSources = new HashSet(); } /** * Main Initializer. Table Style will be SWT.SINGLE | SWT.FULL_SELECTION * * @param _sTableID Which table to handle (see * {@link org.gudy.azureus2.plugins.ui.tables.TableManager} * ). Config settings are stored with the prefix of * "Table.TableID" * @param _sPropertiesPrefix Prefix for retrieving text from the properties * file (MessageText). * Typically TableID + "View" * @param _basicItems Column Definitions * @param _sDefaultSortOn Column name to sort on if user hasn't chosen one * yet */ public TableViewSWTImpl(Class pluginDataSourceType, String _sTableID, String _sPropertiesPrefix, TableColumnCore[] _basicItems, String _sDefaultSortOn) { this(pluginDataSourceType, _sTableID, _sPropertiesPrefix, _basicItems, _sDefaultSortOn, SWT.SINGLE | SWT.FULL_SELECTION | SWT.VIRTUAL); } private void initializeColumnDefs() { // XXX Adding Columns only has to be done once per TableID. // Doing it more than once won't harm anything, but it's a waste. TableColumnManager tcManager = TableColumnManager.getInstance(); if (basicItems != null) { if (tcManager.getTableColumnCount(sTableID) != basicItems.length) { tcManager.addColumns(basicItems); } basicItems = null; } tableColumns = tcManager.getAllTableColumnCoreAsArray(classPluginDataSourceType, sTableID); // fixup order tcManager.ensureIntegrety(sTableID); } // @see com.aelitis.azureus.ui.common.table.TableView#setColumnList(com.aelitis.azureus.ui.common.table.TableColumnCore[], java.lang.String) // XXX This isn't right public void setColumnList(TableColumnCore[] columns, String defaultSortColumnID, boolean defaultSortOrder, boolean titleIsMinWidth) { // XXX Adding Columns only has to be done once per TableID. // Doing it more than once won't harm anything, but it's a waste. TableColumnManager tcManager = TableColumnManager.getInstance(); if (tcManager.getTableColumnCount(sTableID) != columns.length) { tcManager.addColumns(basicItems); } tableColumns = tcManager.getAllTableColumnCoreAsArray(classPluginDataSourceType, sTableID); // fixup order tcManager.ensureIntegrety(sTableID); } // AbstractIView::initialize public void initialize(Composite composite) { composite.setRedraw(false); mainComposite = createSashForm(composite); table = createTable(tableComposite); menu = createMenu(table); clientArea = table.getClientArea(); editor = new TableEditor(table); editor.minimumWidth = 80; editor.grabHorizontal = true; initializeTable(table); triggerLifeCycleListener(TableLifeCycleListener.EVENT_INITIALIZED); configMan.addParameterListener("Graphics Update", this); configMan.addParameterListener("ReOrder Delay", this); Colors.getInstance().addColorsChangedListener(this); // So all TableView objects of the same TableID have the same columns, // and column widths, etc TableStructureEventDispatcher.getInstance(sTableID).addListener(this); composite.setRedraw(true); } private Composite createSashForm(final Composite composite) { if (!bEnableTabViews) { tableComposite = createMainPanel(composite); return tableComposite; } int iNumViews = coreTabViews == null ? 0 : coreTabViews.length; UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); Map pluginViews = null; if (uiFunctions != null) { UISWTInstanceImpl pluginUI = uiFunctions.getSWTPluginInstanceImpl(); if (pluginUI != null) { pluginViews = pluginUI.getViewListeners(sTableID); if (pluginViews != null) { iNumViews += pluginViews.size(); } } } if (iNumViews == 0) { tableComposite = createMainPanel(composite); return tableComposite; } FormData formData; final Composite form = new Composite(composite, SWT.NONE); FormLayout flayout = new FormLayout(); flayout.marginHeight = 0; flayout.marginWidth = 0; form.setLayout(flayout); GridData gridData; gridData = new GridData(GridData.FILL_BOTH); form.setLayoutData(gridData); // Create them in reverse order, so we can have the table auto-grow, and // set the tabFolder's height manually final int TABHEIGHT = 20; tabFolder = new CTabFolder(form, SWT.TOP | SWT.BORDER); tabFolder.setMinimizeVisible(true); tabFolder.setTabHeight(TABHEIGHT); final int iFolderHeightAdj = tabFolder.computeSize(SWT.DEFAULT, 0).y; final Sash sash = new Sash(form, SWT.HORIZONTAL); tableComposite = createMainPanel(form); Composite cFixLayout = tableComposite; while (cFixLayout != null && cFixLayout.getParent() != form) { cFixLayout = cFixLayout.getParent(); } if (cFixLayout == null) { cFixLayout = tableComposite; } GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; cFixLayout.setLayout(layout); // FormData for Folder formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.bottom = new FormAttachment(100, 0); int iSplitAt = configMan.getIntParameter(sPropertiesPrefix + ".SplitAt", 3000); // Was stored at whole if (iSplitAt < 100) { iSplitAt *= 100; } double pct = iSplitAt / 10000.0; if (pct < 0.03) { pct = 0.03; } else if (pct > 0.97) { pct = 0.97; } // height will be set on first resize call sash.setData("PCT", new Double(pct)); tabFolder.setLayoutData(formData); final FormData tabFolderData = formData; // FormData for Sash formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.bottom = new FormAttachment(tabFolder); formData.height = 5; sash.setLayoutData(formData); // FormData for table Composite formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.top = new FormAttachment(0, 0); formData.bottom = new FormAttachment(sash); cFixLayout.setLayoutData(formData); // Listeners to size the folder sash.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { final boolean FASTDRAG = true; if (FASTDRAG && e.detail == SWT.DRAG) { return; } if (tabFolder.getMinimized()) { tabFolder.setMinimized(false); refreshSelectedSubView(); configMan.setParameter(sPropertiesPrefix + ".subViews.minimized", false); } Rectangle area = form.getClientArea(); tabFolderData.height = area.height - e.y - e.height - iFolderHeightAdj; form.layout(); Double l = new Double((double) tabFolder.getBounds().height / form.getBounds().height); sash.setData("PCT", l); if (e.detail != SWT.DRAG) { configMan.setParameter(sPropertiesPrefix + ".SplitAt", (int) (l.doubleValue() * 10000)); } } }); final CTabFolder2Adapter folderListener = new CTabFolder2Adapter() { public void minimize(CTabFolderEvent event) { tabFolder.setMinimized(true); tabFolderData.height = iFolderHeightAdj; CTabItem[] items = tabFolder.getItems(); for (int i = 0; i < items.length; i++) { CTabItem tabItem = items[i]; tabItem.getControl().setVisible(false); } form.layout(); configMan.setParameter(sPropertiesPrefix + ".subViews.minimized", true); } public void restore(CTabFolderEvent event) { tabFolder.setMinimized(false); CTabItem selection = tabFolder.getSelection(); if (selection != null) { selection.getControl().setVisible(true); } form.notifyListeners(SWT.Resize, null); refreshSelectedSubView(); configMan.setParameter(sPropertiesPrefix + ".subViews.minimized", false); } }; tabFolder.addCTabFolder2Listener(folderListener); tabFolder.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { // make sure its above try { ((CTabItem) e.item).getControl().setVisible(true); ((CTabItem) e.item).getControl().moveAbove(null); // TODO: Need to viewDeactivated old one IView view = getActiveSubView(); if (view instanceof IViewExtension) { ((IViewExtension)view).viewActivated(); } } catch (Exception t) { } } public void widgetDefaultSelected(SelectionEvent e) { } }); tabFolder.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { if (tabFolder.getMinimized()) { folderListener.restore(null); // If the user clicked down on the restore button, and we restore // before the CTabFolder does, CTabFolder will minimize us again // There's no way that I know of to determine if the mouse is // on that button! // one of these will tell tabFolder to cancel e.button = 0; tabFolder.notifyListeners(SWT.MouseExit, null); } } }); form.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { if (tabFolder.getMinimized()) { return; } Double l = (Double) sash.getData("PCT"); if (l != null) { tabFolderData.height = (int) (form.getBounds().height * l.doubleValue()) - iFolderHeightAdj; form.layout(); } } }); if (coreTabViews != null) { for (int i = 0; i < coreTabViews.length; i++) { addTabView(coreTabViews[i]); } } // Call plugin listeners if (pluginViews != null) { String[] sNames = pluginViews.keySet().toArray(new String[0]); for (int i = 0; i < sNames.length; i++) { UISWTViewEventListener l = pluginViews.get(sNames[i]); if (l != null) { try { UISWTViewImpl view = new UISWTViewImpl(sTableID, sNames[i], l); addTabView(view); } catch (Exception e) { // skip, plugin probably specifically asked to not be added } } } } if (configMan.getBooleanParameter( sPropertiesPrefix + ".subViews.minimized", false)) { tabFolder.setMinimized(true); tabFolderData.height = iFolderHeightAdj; } else { tabFolder.setMinimized(false); } tabFolder.setSelection(0); return form; } /** Creates a composite within the specified composite and sets its layout * to a default FillLayout(). * * @param composite to create your Composite under * @return The newly created composite */ public Composite createMainPanel(Composite composite) { TableViewSWTPanelCreator mainPanelCreator = getMainPanelCreator(); if (mainPanelCreator != null) { return mainPanelCreator.createTableViewPanel(composite); } Composite panel = new Composite(composite, SWT.NO_FOCUS); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; panel.setLayout(layout); panel.setLayoutData(new GridData(GridData.FILL_BOTH)); return panel; } /** Creates the Table. * * @return The created Table. */ public Table createTable(Composite panel) { table = new Table(panel, iTableStyle); table.setLayoutData(new GridData(GridData.FILL_BOTH)); return table; } /** Sets up the sorter, columns, and context menu. * * @param table Table to be initialized */ public void initializeTable(final Table table) { initializeColumnDefs(); iTableStyle = table.getStyle(); bTableVirtual = (iTableStyle & SWT.VIRTUAL) != 0; table.setLinesVisible(Utils.TABLE_GRIDLINE_IS_ALTERNATING_COLOR); table.setMenu(menu); table.setData("Name", sTableID); table.setData("TableView", this); // Setup table // ----------- table.addPaintListener(new PaintListener() { public void paintControl(PaintEvent event) { changeColumnIndicator(); // This fixes the scrollbar not being long enough on Win2k // There may be other methods to get it to refresh right, but // layout(true, true) didn't work. table.setRedraw(false); table.setRedraw(true); table.removePaintListener(this); } }); table.addListener(SWT.PaintItem, new Listener() { public void handleEvent(Event event) { //visibleRowsChanged(); paintItem(event); } }); //table.addListener(SWT.Paint, new Listener() { // public void handleEvent(Event event) { // System.out.println("paint " + event.getBounds() + ";" + table.getColumnCount()); // } //}); ScrollBar horizontalBar = table.getHorizontalBar(); if (horizontalBar != null) { horizontalBar.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { calculateClientArea(); //updateColumnVisibilities(); } public void widgetSelected(SelectionEvent e) { calculateClientArea(); //updateColumnVisibilities(); } }); } table.addListener(SWT.MeasureItem, new Listener() { public void handleEvent(Event event) { int iColumnNo = event.index; if (bSkipFirstColumn) { iColumnNo--; } if (iColumnNo >= 0 && iColumnNo < columnsOrdered.length) { TableColumnCore tc = columnsOrdered[iColumnNo]; int preferredWidth = tc.getPreferredWidth(); event.width = preferredWidth; } int defaultHeight = getRowDefaultHeight(); if (event.height < defaultHeight) { event.height = defaultHeight; } } }); // Deselect rows if user clicks on a blank spot (a spot with no row) table.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent e) { TableColumnCore tc = getTableColumnByOffset(e.x); TableCellSWT cell = getTableCell(e.x, e.y); if (cell != null && tc != null) { TableCellMouseEvent event = createMouseEvent(cell, e, TableCellMouseEvent.EVENT_MOUSEDOUBLECLICK, false); if (event != null) { tc.invokeCellMouseListeners(event); cell.invokeMouseListeners(event); if (event.skipCoreFunctionality) { lCancelSelectionTriggeredOn = System.currentTimeMillis(); } } } } long lastMouseUpEventTime = 0; public void mouseUp(MouseEvent e) { long time = e.time & 0xFFFFFFFFL; long diff = time - lastMouseUpEventTime; if (diff < 10 && diff >= 0) { return; } lastMouseUpEventTime = time; TableColumnCore tc = getTableColumnByOffset(e.x); TableCellSWT cell = getTableCell(e.x, e.y); if (cell != null && tc != null) { TableCellMouseEvent event = createMouseEvent(cell, e, TableCellMouseEvent.EVENT_MOUSEUP, false); if (event != null) { tc.invokeCellMouseListeners(event); cell.invokeMouseListeners(event); if (event.skipCoreFunctionality) { lCancelSelectionTriggeredOn = System.currentTimeMillis(); } } } } TableRowCore lastClickRow; public void mouseDown(MouseEvent e) { // we need to fill the selected row indexes here because the // dragstart event can occur before the SWT.SELECTION event and // our drag code needs to know the selected rows.. updateSelectedRowIndexes(); TableColumnCore tc = getTableColumnByOffset(e.x); TableCellSWT cell = getTableCell(e.x, e.y); editCell(-1, -1); // clear out current cell editor if (cell != null && tc != null) { if (e.button == 2 && e.stateMask == SWT.CONTROL) { ((TableCellImpl) cell).bDebug = !((TableCellImpl) cell).bDebug; System.out.println("Set debug for " + cell + " to " + ((TableCellImpl) cell).bDebug); } TableCellMouseEvent event = createMouseEvent(cell, e, TableCellMouseEvent.EVENT_MOUSEDOWN, false); if (event != null) { tc.invokeCellMouseListeners(event); cell.invokeMouseListeners(event); if (event.skipCoreFunctionality) { lCancelSelectionTriggeredOn = System.currentTimeMillis(); } } if (tc.isInplaceEdit() && e.button == 1 && lastClickRow == cell.getTableRowCore()) { editCell(getColumnNo(e.x), cell.getTableRowCore().getIndex()); } if (e.button == 1) { lastClickRow = cell.getTableRowCore(); } } try { if (table.getItemCount() <= 0) { return; } // skip if outside client area (ie. scrollbars) //System.out.println("Mouse="+iMouseX+"x"+e.y+";TableArea="+clientArea); Point pMousePosition = new Point(e.x, e.y); if (clientArea.contains(pMousePosition)) { int[] columnOrder = table.getColumnOrder(); if (columnOrder.length == 0) { return; } TableItem ti = table.getItem(table.getItemCount() - 1); Rectangle cellBounds = ti.getBounds(columnOrder[columnOrder.length - 1]); // OSX returns 0 size if the cell is not on screen (sometimes? all the time?) if (cellBounds.width <= 0 || cellBounds.height <= 0) { return; } //System.out.println("cellbounds="+cellBounds); if (e.x > cellBounds.x + cellBounds.width || e.y > cellBounds.y + cellBounds.height) { table.deselectAll(); updateSelectedRowIndexes(); } /* // This doesn't work because of OS inconsistencies when table is scrolled // Re-enable once SWT fixes the problem // Bug 103934: Table.getItem(Point) uses incorrect calculation on Motif // Fixed 20050718 SWT 3.2M1 (3201) & SWT 3.1.1 (3139) // TODO: Get Build IDs and use this code (if it works) TableItem ti = table.getItem(pMousePosition); if (ti == null) table.deselectAll(); */ } } catch (Exception ex) { System.out.println("MouseDownError"); Debug.printStackTrace(ex); } } }); table.addMouseMoveListener(new MouseMoveListener() { TableCellSWT lastCell = null; int lastCursorID = 0; public void mouseMove(MouseEvent e) { try { TableCellSWT cell = getTableCell(e.x, e.y); if (lastCell != null && cell != lastCell && !lastCell.isDisposed()) { TableCellMouseEvent event = createMouseEvent(lastCell, e, TableCellMouseEvent.EVENT_MOUSEEXIT, true); if (event != null) { TableColumnCore tc = ((TableColumnCore) lastCell.getTableColumn()); if (tc != null) { tc.invokeCellMouseListeners(event); } lastCell.invokeMouseListeners(event); } } int iCursorID = 0; if (cell == null) { lastCell = null; } else if (cell == lastCell) { iCursorID = lastCursorID; } else { iCursorID = cell.getCursorID(); lastCell = cell; } if (iCursorID < 0) { iCursorID = 0; } if (iCursorID != lastCursorID) { lastCursorID = iCursorID; if (iCursorID >= 0) { table.setCursor(table.getDisplay().getSystemCursor(iCursorID)); } else { table.setCursor(null); } } if (cell != null) { TableCellMouseEvent event = createMouseEvent(cell, e, TableCellMouseEvent.EVENT_MOUSEMOVE, false); if (event != null) { TableColumnCore tc = ((TableColumnCore) cell.getTableColumn()); if (tc.hasCellMouseMoveListener()) { ((TableColumnCore) cell.getTableColumn()).invokeCellMouseListeners(event); } cell.invokeMouseListeners(event); // listener might have changed it lastCursorID = cell.getCursorID(); } } } catch (Exception ex) { Debug.out(ex); } } }); table.addSelectionListener(new SelectionListener() { int[] wasSelected = new int[0]; public void widgetSelected(SelectionEvent event) { updateSelectedRowIndexes(); Arrays.sort(selectedRowIndexes); int x = 0; for (int i = 0; x < wasSelected.length && i < selectedRowIndexes.length; i++) { int index = selectedRowIndexes[i]; if (wasSelected[x] == index) { x++; continue; } else { triggerDeselectionListeners(new TableRowCore[] { getRow(wasSelected[x]) }); } } wasSelected = selectedRowIndexes; //System.out.println(table.getSelection().length); if (selectedRowIndexes.length > 0 && event.item != null) { triggerSelectionListeners(new TableRowCore[] { getRow((TableItem) event.item) }); } triggerTabViewsDataSourceChanged(); } public void widgetDefaultSelected(SelectionEvent e) { if (lCancelSelectionTriggeredOn > 0 && System.currentTimeMillis() - lCancelSelectionTriggeredOn < 200) { e.doit = false; lCancelSelectionTriggeredOn = -1; } else { runDefaultAction(e.stateMask); } } }); // we are sent a SWT.Settings event when the language changes and // when System fonts/colors change. In both cases, invalidate table.addListener(SWT.Settings, new Listener() { public void handleEvent(Event e) { tableInvalidate(); } }); new TableTooltips(this, table); table.addKeyListener(this); table.addDisposeListener(new DisposeListener(){ public void widgetDisposed(DisposeEvent e) { if (filter != null && filter.widget != null && !filter.widget.isDisposed()) { filter.widget.removeKeyListener(TableViewSWTImpl.this); filter.widget.removeModifyListener(filter.widgetModifyListener); } Utils.disposeSWTObjects(new Object[] { slider } ); } }); /* if (Utils.isCocoa) { table.addListener(SWT.MouseVerticalWheel, new Listener() { public void handleEvent(Event event) { calculateClientArea(); visibleRowsChanged(); } }); } */ ScrollBar bar = table.getVerticalBar(); if (bar != null) { bar.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { calculateClientArea(); visibleRowsChanged(); // Bug: Scroll is slow when table is not focus if (!table.isFocusControl()) { table.setFocus(); } } }); } table.setHeaderVisible(getHeaderVisible()); clientArea = table.getClientArea(); //firstClientArea = table.getClientArea(); table.addListener(SWT.Resize, new Listener() { public void handleEvent(Event event) { calculateClientArea(); } }); initializeTableColumns(table); } public void keyPressed(KeyEvent event) { // Note: Both table key presses and txtFilter keypresses go through this // method. Object[] listeners = listenersKey.toArray(); for (int i = 0; i < listeners.length; i++) { KeyListener l = (KeyListener) listeners[i]; l.keyPressed(event); if (!event.doit) { lCancelSelectionTriggeredOn = SystemTime.getCurrentTime(); return; } } if (event.keyCode == SWT.F5) { if ((event.stateMask & SWT.SHIFT) > 0) { runForSelectedRows(new TableGroupRowRunner() { public void run(TableRowCore row) { row.invalidate(); row.refresh(true); } }); } else { sortColumn(true); } event.doit = false; return; } int key = event.character; if (key <= 26 && key > 0) { key += 'a' - 1; } if (event.stateMask == SWT.MOD1) { switch (key) { case 'a': // CTRL+A select all Torrents if (filter == null || event.widget != filter.widget) { if ((table.getStyle() & SWT.MULTI) > 0) { selectAll(); event.doit = false; } } else { filter.widget.selectAll(); event.doit = false; } break; case '+': { if (Constants.isUnix) { TableColumn[] tableColumnsSWT = table.getColumns(); for (int i = 0; i < tableColumnsSWT.length; i++) { TableColumnCore tc = (TableColumnCore) tableColumnsSWT[i].getData("TableColumnCore"); if (tc != null) { int w = tc.getPreferredWidth(); if (w <= 0) { w = tc.getMinWidth(); if (w <= 0) { w = 100; } } tc.setWidth(w); } } event.doit = false; } break; } case 'f': // CTRL+F Find/Filter openFilterDialog(); event.doit = false; break; case 'x': // CTRL+X: RegEx search switch if (filter != null && event.widget == filter.widget) { filter.regex = !filter.regex; filter.widget.setBackground(filter.regex?COLOR_FILTER_REGEX:null); event.doit = false; refilter(); } break; } } if (event.stateMask == 0) { if (filter != null && filter.widget == event.widget) { if (event.keyCode == SWT.ARROW_DOWN) { setFocus(); event.doit = false; } else if (event.character == 13) { refilter(); } } } if (!event.doit) { return; } handleSearchKeyPress(event); } public void keyReleased(KeyEvent event) { calculateClientArea(); visibleRowsChanged(); Object[] listeners = listenersKey.toArray(); for (int i = 0; i < listeners.length; i++) { KeyListener l = (KeyListener) listeners[i]; l.keyReleased(event); if (!event.doit) { return; } } } public boolean getHeaderVisible() { return headerVisible; } public void setHeaderVisible(boolean visible) { headerVisible = visible; if (table != null && !table.isDisposed()) { table.setHeaderVisible(visible); } } protected void calculateClientArea() { Rectangle oldClientArea = clientArea; clientArea = table.getClientArea(); ScrollBar horizontalBar = table.getHorizontalBar(); if (horizontalBar != null) { int pos = horizontalBar.getSelection(); if (pos != lastHorizontalPos) { lastHorizontalPos = pos; columnVisibilitiesChanged = true; } } if (oldClientArea != null && (oldClientArea.x != clientArea.x || oldClientArea.width != clientArea.width)) { columnVisibilitiesChanged = true; } if (columnVisibilitiesChanged) { Utils.execSWTThreadLater(50, new AERunnable() { public void runSupport() { if (columnVisibilitiesChanged) { refreshTable(false); } } }); } } // @see com.aelitis.azureus.ui.common.table.impl.TableViewImpl#triggerSelectionListeners(com.aelitis.azureus.ui.common.table.TableRowCore[]) protected void triggerSelectionListeners(TableRowCore[] rows) { //System.out.println("triggerSelectionLis" + rows[0]); if (TRIGGER_PAINT_ON_SELECTIONS) { for (int i = 0; i < rows.length; i++) { TableRowCore row = rows[i]; row.redraw(); table.update(); } } //System.out.println("e triggerSelectionLis" + rows[0]); super.triggerSelectionListeners(rows); } // @see com.aelitis.azureus.ui.common.table.impl.TableViewImpl#triggerDeselectionListeners(com.aelitis.azureus.ui.common.table.TableRowCore[]) protected void triggerDeselectionListeners(TableRowCore[] rows) { if (TRIGGER_PAINT_ON_SELECTIONS) { for (int i = 0; i < rows.length; i++) { TableRowCore row = rows[i]; row.redraw(); table.update(); } } super.triggerDeselectionListeners(rows); } /** * * * @since 3.1.1.1 */ protected void triggerTabViewsDataSourceChanged() { if (tabViews == null || tabViews.size() == 0) { return; } // Set Data Object for all tabs. Tabs of PluginView are sent the plugin // Peer object, while Tabs of IView are sent the core PEPeer object. // TODO: Send all datasources Object[] dataSourcesCore = getSelectedDataSources(true); Object[] dataSourcesPlugin = null; for (int i = 0; i < tabViews.size(); i++) { IView view = tabViews.get(i); if (view != null) { if (view instanceof UISWTViewImpl) { if (dataSourcesPlugin == null) { dataSourcesPlugin = getSelectedDataSources(false); } ((UISWTViewImpl) view).dataSourceChanged(dataSourcesPlugin.length == 0 ? null : dataSourcesPlugin); } else { view.dataSourceChanged(dataSourcesCore.length == 0 ? null : dataSourcesCore); } } } } private interface SourceReplaceListener { void sourcesChanged(); void cleanup(Text toClean); } private SourceReplaceListener cellEditNotifier; private Scale slider; private void editCell(final int column, final int row) { Text oldInput = (Text) editor.getEditor(); if (column >= table.getColumnCount() || row < 0 || row >= table.getItemCount()) { cellEditNotifier = null; if (oldInput != null && !oldInput.isDisposed()) { editor.getEditor().dispose(); } return; } TableColumn tcColumn = table.getColumn(column); final TableItem item = table.getItem(row); String cellName = (String) tcColumn.getData("Name"); final TableRowSWT rowSWT = (TableRowSWT) getRow(row); final TableCellSWT cell = rowSWT.getTableCellSWT(cellName); // reuse widget if possible, this way we'll keep the focus all the time on jumping through the rows final Text newInput = oldInput == null || oldInput.isDisposed() ? new Text( table, Constants.isOSX ? SWT.NONE : SWT.BORDER) : oldInput; final DATASOURCETYPE datasource = (DATASOURCETYPE) cell.getDataSource(); if (cellEditNotifier != null) { cellEditNotifier.cleanup(newInput); } table.showItem(item); table.showColumn(tcColumn); newInput.setText(cell.getText()); newInput.setSelection(0); newInput.selectAll(); newInput.setFocus(); class QuickEditListener implements ModifyListener, SelectionListener, KeyListener, TraverseListener, SourceReplaceListener, ControlListener { boolean resizing = true; public QuickEditListener(Text toAttach) { toAttach.addModifyListener(this); toAttach.addSelectionListener(this); toAttach.addKeyListener(this); toAttach.addTraverseListener(this); toAttach.addControlListener(this); cellEditNotifier = this; } public void modifyText(ModifyEvent e) { if (item.isDisposed()) { sourcesChanged(); return; } if (((TableColumnCore) cell.getTableColumn()).inplaceValueSet(cell, newInput.getText(), false)) { newInput.setBackground(null); } else { newInput.setBackground(Colors.colorErrorBG); } } public void widgetDefaultSelected(SelectionEvent e) { if (item.isDisposed()) { sourcesChanged(); newInput.traverse(SWT.TRAVERSE_RETURN); return; } ((TableColumnCore) cell.getTableColumn()).inplaceValueSet(cell, newInput.getText(), true); rowSWT.invalidate(); editCell(column, row + 1); } public void widgetSelected(SelectionEvent e) { } public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.ARROW_UP) { e.doit = false; editCell(column, row + (e.keyCode == SWT.ARROW_DOWN ? 1 : -1)); } } public void keyReleased(KeyEvent e) { } public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { e.doit = false; editCell(column, -1); } } public void sourcesChanged() { if (getRow(datasource) == rowSWT || getRow(datasource) == null || newInput.isDisposed()) { return; } String newVal = newInput.getText(); Point sel = newInput.getSelection(); editCell(column, getRow(datasource).getIndex()); if (newInput.isDisposed()) { return; } newInput.setText(newVal); newInput.setSelection(sel); } public void cleanup(Text oldText) { if (!oldText.isDisposed()) { oldText.removeModifyListener(this); oldText.removeSelectionListener(this); oldText.removeKeyListener(this); oldText.removeTraverseListener(this); oldText.removeControlListener(this); } } public void controlMoved(ControlEvent e) { table.showItem(item); if (resizing) { return; } resizing = true; Point sel = newInput.getSelection(); editor.setEditor(newInput, item, column); editor.minimumWidth = newInput.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; Rectangle leftAlignedBounds = item.getBounds(column); leftAlignedBounds.width = editor.minimumWidth = newInput.computeSize( SWT.DEFAULT, SWT.DEFAULT).x; if (leftAlignedBounds.intersection(clientArea).equals(leftAlignedBounds)) { editor.horizontalAlignment = SWT.LEFT; } else { editor.horizontalAlignment = SWT.RIGHT; } editor.layout(); newInput.setSelection(0); newInput.setSelection(sel); resizing = false; } public void controlResized(ControlEvent e) { } } QuickEditListener l = new QuickEditListener(newInput); l.modifyText(null); editor.setEditor(newInput, item, column); table.deselectAll(); table.select(row); updateSelectedRowIndexes(); l.resizing = false; l.controlMoved(null); } private TableCellMouseEvent createMouseEvent(TableCellSWT cell, MouseEvent e, int type, boolean allowOOB) { TableCellMouseEvent event = new TableCellMouseEvent(); event.cell = cell; if (cell != null) { event.row = cell.getTableRow(); } event.eventType = type; event.button = e.button; // TODO: Change to not use SWT masks event.keyboardState = e.stateMask; event.skipCoreFunctionality = false; if (cell != null) { Rectangle r = cell.getBounds(); event.x = e.x - r.x; if (!allowOOB && event.x < 0) { return null; } event.y = e.y - r.y; if (!allowOOB && event.y < 0) { return null; } } return event; } /** * @param event */ protected void paintItem(Event event) { try { if (event.gc.getClipping().isEmpty()) { return; } //System.out.println("paintItem " + event.gc.getClipping()); if (DEBUG_CELL_CHANGES) { Random random = new Random(SystemTime.getCurrentTime() / 500); event.gc.setBackground(ColorCache.getColor(event.gc.getDevice(), 210 + random.nextInt(45), 210 + random.nextInt(45), 210 + random.nextInt(45))); event.gc.fillRectangle(event.gc.getClipping()); } TableItem item = (TableItem) event.item; if (item == null || item.isDisposed()) { return; } int iColumnNo = event.index; //System.out.println(SystemTime.getCurrentTime() + "] paintItem " + table.indexOf(item) + ":" + iColumnNo); if (bSkipFirstColumn) { if (iColumnNo == 0) { return; } iColumnNo--; } if (iColumnNo >= columnsOrdered.length) { System.out.println("Col #" + iColumnNo + " >= " + columnsOrdered.length + " count"); return; } if (!isColumnVisible(columnsOrdered[iColumnNo])) { //System.out.println("col not visible " + iColumnNo); return; } TableRowSWT row = (TableRowSWT) getRow(item); if (row == null) { //System.out.println("no row"); return; } int rowPos = indexOf(row); if (rowPos < lastTopIndex || rowPos > lastBottomIndex) { // this refreshes whole row (perhaps multiple), saving the many // cell.refresh calls later because !cell.isUpToDate() visibleRowsChanged(); } int rowAlpha = row.getAlpha(); int fontStyle = row.getFontStyle(); if (fontStyle == SWT.BOLD) { if (fontBold == null) { FontData[] fontData = event.gc.getFont().getFontData(); for (int i = 0; i < fontData.length; i++) { FontData fd = fontData[i]; fd.setStyle(SWT.BOLD); } fontBold = new Font(event.gc.getDevice(), fontData); } event.gc.setFont(fontBold); } // SWT 3.2 only. Code Ok -- Only called in SWT 3.2 mode Rectangle cellBounds = item.getBounds(event.index); //if (item.getImage(event.index) != null) { // cellBounds.x += 18; // cellBounds.width -= 18; //} if (cellBounds.width <= 0 || cellBounds.height <= 0) { //System.out.println("no bounds"); return; } TableCellSWT cell = row.getTableCellSWT(columnsOrdered[iColumnNo].getName()); if (cell == null) { return; } if (!cell.isUpToDate()) { //System.out.println("R " + table.indexOf(item) + ":" + iColumnNo); cell.refresh(true, true); //return; } String text = cell.getText(); Rectangle clipping = new Rectangle(cellBounds.x, cellBounds.y, cellBounds.width, cellBounds.height); // Cocoa calls paintitem while row is below tablearea, and painting there // is valid! if (!Utils.isCocoa) { int headerHeight = table.getHeaderHeight(); int iMinY = headerHeight + clientArea.y; if (clipping.y < iMinY) { clipping.height -= iMinY - clipping.y; clipping.y = iMinY; } int iMaxY = clientArea.height + clientArea.y; if (clipping.y + clipping.height > iMaxY) { clipping.height = iMaxY - clipping.y + 1; } } if (clipping.width <= 0 || clipping.height <= 0) { //System.out.println(row.getIndex() + " clipping="+clipping + ";" + iMinY + ";" + iMaxY + ";tca=" + tableBounds); return; } event.gc.setClipping(clipping); if (rowAlpha < 255) { event.gc.setAlpha(rowAlpha); } if (cell.needsPainting()) { cell.doPaint(event.gc); } else if (text.length() > 0) { int ofsx = 0; Image image = item.getImage(event.index); if (image != null && !image.isDisposed()) { int ofs = image.getBounds().width; ofsx += ofs; cellBounds.x += ofs; cellBounds.width -= ofs; } //System.out.println("PS " + table.indexOf(item) + ";" + cellBounds + ";" + cell.getText()); int style = TableColumnSWTUtils.convertColumnAlignmentToSWT(columnsOrdered[iColumnNo].getAlignment()); if (cellBounds.height > 20) { style |= SWT.WRAP; } int textOpacity = cell.getTextAlpha(); if (textOpacity < 255) { event.gc.setAlpha(textOpacity); } // put some padding on text ofsx += 6; cellBounds.x += 3; cellBounds.width -= 6; if (!cellBounds.isEmpty()) { GCStringPrinter sp = new GCStringPrinter(event.gc, text, cellBounds, true, cellBounds.height > 20, style); boolean fit = sp.printString(); if (fit) { cell.setDefaultToolTip(null); }else{ cell.setDefaultToolTip(text); } Point size = sp.getCalculatedSize(); size.x += ofsx; if (cell.getTableColumn().getPreferredWidth() < size.x) { cell.getTableColumn().setPreferredWidth(size.x); } }else{ cell.setDefaultToolTip(null); } } } catch (Exception e) { e.printStackTrace(); } } public void runDefaultAction(int stateMask) { // plugin may have cancelled the default action if (lCancelSelectionTriggeredOn > 0 && System.currentTimeMillis() - lCancelSelectionTriggeredOn < 200) { lCancelSelectionTriggeredOn = -1; } else { TableRowCore[] selectedRows = getSelectedRows(); triggerDefaultSelectedListeners(selectedRows, stateMask); } } private void updateColumnVisibilities() { TableColumn[] columns = table.getColumns(); int topIdx = table.getTopIndex(); if (topIdx < 0 || table.getItemCount() < 1) { return; } columnVisibilitiesChanged = false; TableItem topRow = table.getItem(topIdx); for (int i = 0; i < columns.length; i++) { final TableColumnCore tc = (TableColumnCore) columns[i].getData("TableColumnCore"); if (tc == null) { continue; } int position = tc.getPosition(); if (position < 0 || position >= columnsVisible.length) { continue; } Rectangle size = topRow.getBounds(i); //System.out.println("column " + i + ": size=" + size + "; ca=" + clientArea); size.intersect(clientArea); boolean nowVisible = !size.isEmpty(); if (columnsVisible[position] != nowVisible) { columnsVisible[position] = nowVisible; if (nowVisible) { runForVisibleRows(new TableGroupRowRunner() { public void run(TableRowCore row) { TableCellCore cell = row.getTableCellCore(tc.getName()); cell.invalidate(); cell.redraw(); } }); } } } } public boolean isColumnVisible( org.gudy.azureus2.plugins.ui.tables.TableColumn column) { int position = column.getPosition(); if (position < 0 || position >= columnsVisible.length) { return false; } return columnsVisible[position]; } protected void initializeTableColumns(final Table table) { TableColumn[] oldColumns = table.getColumns(); for (int i = 0; i < oldColumns.length; i++) { oldColumns[i].removeListener(SWT.Move, columnMoveListener); } for (int i = oldColumns.length - 1; i >= 0; i--) { oldColumns[i].dispose(); } columnPaddingAdjusted = false; // Pre 3.0RC1 SWT on OSX doesn't call this!! :( ControlListener resizeListener = new ControlAdapter() { // Bug: getClientArea() eventually calls back to controlResized, // creating a loop until a stack overflow private boolean bInFunction = false; public void controlResized(ControlEvent e) { TableColumn column = (TableColumn) e.widget; if (column == null || column.isDisposed() || bInFunction) { return; } try { bInFunction = true; TableColumnCore tc = (TableColumnCore) column.getData("TableColumnCore"); if (tc != null) { Long lPadding = (Long) column.getData("widthOffset"); int padding = (lPadding == null) ? 0 : lPadding.intValue(); tc.setWidth(column.getWidth() - padding); } int columnNumber = table.indexOf(column); locationChanged(columnNumber); } finally { bInFunction = false; } } }; // Add 1 to position because we make a non resizable 0-sized 1st column // to fix the 1st column gap problem (Eclipse Bug 43910) // SWT does not set 0 column width as expected in OS X; see bug 43910 // this will be removed when a SWT-provided solution is available to satisfy all platforms with identation issue bSkipFirstColumn = bSkipFirstColumn && !Constants.isOSX; if (bSkipFirstColumn) { TableColumn tc = new TableColumn(table, SWT.NULL); tc.setWidth(0); tc.setResizable(false); tc.setMoveable(false); } TableColumnCore[] tmpColumnsOrdered = new TableColumnCore[tableColumns.length]; //Create all columns int columnOrderPos = 0; Arrays.sort(tableColumns, TableColumnManager.getTableColumnOrderComparator()); for (int i = 0; i < tableColumns.length; i++) { int position = tableColumns[i].getPosition(); if (position != -1 && tableColumns[i].isVisible()) { new TableColumn(table, SWT.NULL); //System.out.println(i + "] " + tableColumns[i].getName() + ";" + position); tmpColumnsOrdered[columnOrderPos++] = tableColumns[i]; } } int numSWTColumns = table.getColumnCount(); int iNewLength = numSWTColumns - (bSkipFirstColumn ? 1 : 0); columnsOrdered = new TableColumnCore[iNewLength]; System.arraycopy(tmpColumnsOrdered, 0, columnsOrdered, 0, iNewLength); columnsVisible = new boolean[tableColumns.length]; ColumnSelectionListener columnSelectionListener = new ColumnSelectionListener(); //Assign length and titles //We can only do it after ALL columns are created, as position (order) //may not be in the natural order (if the user re-order the columns). int swtColumnPos = (bSkipFirstColumn ? 1 : 0); for (int i = 0; i < tableColumns.length; i++) { int position = tableColumns[i].getPosition(); if (position == -1 || !tableColumns[i].isVisible()) { continue; } columnsVisible[i] = true; String sName = tableColumns[i].getName(); // +1 for Eclipse Bug 43910 (see above) // user has reported a problem here with index-out-of-bounds - not sure why // but putting in a preventative check so that hopefully the view still opens // so they can fix it if (swtColumnPos >= numSWTColumns) { Debug.out("Incorrect table column setup, skipping column '" + sName + "', position=" + swtColumnPos + ";numCols=" + numSWTColumns); continue; } TableColumn column = table.getColumn(swtColumnPos); try { column.setMoveable(true); } catch (NoSuchMethodError e) { // Ignore < SWT 3.1 } column.setAlignment(TableColumnSWTUtils.convertColumnAlignmentToSWT(tableColumns[i].getAlignment())); Messages.setLanguageText(column, tableColumns[i].getTitleLanguageKey()); if (!Constants.isUnix) { column.setWidth(tableColumns[i].getWidth()); } else { column.setData("widthOffset", new Long(1)); column.setWidth(tableColumns[i].getWidth() + 1); } if (tableColumns[i].getMinWidth() == tableColumns[i].getMaxWidth() && tableColumns[i].getMinWidth() > 0) { column.setResizable(false); } column.setData("TableColumnCore", tableColumns[i]); column.setData("configName", "Table." + sTableID + "." + sName); column.setData("Name", sName); column.addControlListener(resizeListener); // At the time of writing this SWT (3.0RC1) on OSX doesn't call the // selection listener for tables column.addListener(SWT.Selection, columnSelectionListener); swtColumnPos++; } // Initialize the sorter after the columns have been added TableColumnManager tcManager = TableColumnManager.getInstance(); String sSortColumn = tcManager.getDefaultSortColumnName(sTableID); if (sSortColumn == null || sSortColumn.length() == 0) { sSortColumn = sDefaultSortOn; } TableColumnCore tc = tcManager.getTableColumnCore(sTableID, sSortColumn); if (tc == null && tableColumns.length > 0) { tc = tableColumns[0]; } sortColumn = tc; fixAlignment(tc, true); changeColumnIndicator(); // Add move listener at the very end, so we don't get a bazillion useless // move triggers TableColumn[] columns = table.getColumns(); for (int i = 0; i < columns.length; i++) { TableColumn column = columns[i]; column.addListener(SWT.Move, columnMoveListener); } columnVisibilitiesChanged = true; } public void fixAlignment(TableColumnCore tc, boolean sorted) { if (Constants.isOSX) { if (table.isDisposed() || tc == null) { return; } int[] columnOrder = table.getColumnOrder(); int i = tc.getPosition() - (bSkipFirstColumn ? 1 : 0); if (i < 0 || i >= columnOrder.length) { return; } TableColumn swtColumn = table.getColumn(columnOrder[i]); if (swtColumn != null) { if (swtColumn.getAlignment() == SWT.RIGHT && sorted) { swtColumn.setText(" " + swtColumn.getText() + " "); } else { swtColumn.setText(swtColumn.getText().trim()); } } } } /** Creates the Context Menu. * @param table * * @return a new Menu object */ private Menu createMenu(final Table table) { if (!isMenuEnabled()) { return null; } final Menu menu = new Menu(tableComposite.getShell(), SWT.POP_UP); table.addListener(SWT.MenuDetect, new Listener() { public void handleEvent(Event event) { Point pt = event.display.map(null, table, new Point(event.x, event.y)); Rectangle clientArea = table.getClientArea(); boolean header = clientArea.y <= pt.y && pt.y < (clientArea.y + table.getHeaderHeight()); // give clicks on blank rows a header menu. header |= table.getItem(pt) == null; menu.setData("isHeader", new Boolean(header)); int columnNo = getColumnNo(pt.x); menu.setData("column", columnNo < 0 || columnNo >= table.getColumnCount() ? null : table.getColumn(columnNo)); } }); MenuBuildUtils.addMaintenanceListenerForMenu(menu, new MenuBuildUtils.MenuBuilder() { public void buildMenu(Menu menu, MenuEvent menuEvent) { Object oIsHeader = menu.getData("isHeader"); boolean isHeader = (oIsHeader instanceof Boolean) ? ((Boolean)oIsHeader).booleanValue() : false; TableColumn tcColumn = (TableColumn) menu.getData("column"); if (!isHeader) { fillMenu(menu, tcColumn); } else { fillColumnMenu(tcColumn); } } }); return menu; } /** Fill the Context Menu with items. Called when menu is about to be shown. * * By default, a "Edit Columns" menu and a Column specific menu is set up. * * @param menu Menu to fill * @param tcColumn */ public void fillMenu(final Menu menu, final TableColumn tcColumn) { String columnName = tcColumn == null ? null : (String) tcColumn.getData("Name"); Object[] listeners = listenersMenuFill.toArray(); for (int i = 0; i < listeners.length; i++) { TableViewSWTMenuFillListener l = (TableViewSWTMenuFillListener) listeners[i]; l.fillMenu(columnName, menu); } // Add Plugin Context menus.. boolean enable_items = table != null && table.getSelection().length > 0; TableContextMenuItem[] items = TableContextMenuManager.getInstance().getAllAsArray( sTableID); // We'll add download-context specific menu items - if the table is download specific. // We need a better way to determine this... org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items = null; if ("MySeeders".equals(sTableID) || "MyTorrents".equals(sTableID)) { menu_items = MenuItemManager.getInstance().getAllAsArray( "download_context"); } else { menu_items = MenuItemManager.getInstance().getAllAsArray((String) null); } MenuItem item = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(item, "MyTorrentsView.menu.thisColumn.toClipboard"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { String sToClipboard = ""; if (tcColumn == null) { return; } String columnName = (String) tcColumn.getData("Name"); if (columnName == null) { return; } TableItem[] tis = table.getSelection(); for (int i = 0; i < tis.length; i++) { if (i != 0) { sToClipboard += "\n"; } TableRowCore row = (TableRowCore) tis[i].getData("TableRow"); TableCellCore cell = row.getTableCellCore(columnName); if (cell != null) { sToClipboard += cell.getText(); } } if (sToClipboard.length() == 0) { return; } new Clipboard(mainComposite.getDisplay()).setContents(new Object[] { sToClipboard }, new Transfer[] { TextTransfer.getInstance() }); } }); if (items.length > 0 || menu_items.length > 0) { new org.eclipse.swt.widgets.MenuItem(menu, SWT.SEPARATOR); // Add download context menu items. if (menu_items != null) { // getSelectedDataSources(false) returns us plugin items. MenuBuildUtils.addPluginMenuItems(getComposite(), menu_items, menu, true, true, new MenuBuildUtils.MenuItemPluginMenuControllerImpl( getSelectedDataSources(false))); } if (items.length > 0) { MenuBuildUtils.addPluginMenuItems(getComposite(), items, menu, true, enable_items, new MenuBuildUtils.PluginMenuController() { public Listener makeSelectionListener( final org.gudy.azureus2.plugins.ui.menus.MenuItem plugin_menu_item) { return new TableSelectedRowsListener(TableViewSWTImpl.this) { public boolean run(TableRowCore[] rows) { if (rows.length != 0) { ((TableContextMenuItemImpl) plugin_menu_item).invokeListenersMulti(rows); } return true; } }; } public void notifyFillListeners( org.gudy.azureus2.plugins.ui.menus.MenuItem menu_item) { ((TableContextMenuItemImpl) menu_item).invokeMenuWillBeShownListeners(getSelectedRows()); } }); } } // Add Plugin Context menus.. if (tcColumn != null) { TableColumnCore tc = (TableColumnCore) tcColumn.getData("TableColumnCore"); TableContextMenuItem[] columnItems = tc.getContextMenuItems(TableColumnCore.MENU_STYLE_COLUMN_DATA); if (columnItems.length > 0) { new MenuItem(menu, SWT.SEPARATOR); MenuBuildUtils.addPluginMenuItems(getComposite(), columnItems, menu, true, true, new MenuBuildUtils.MenuItemPluginMenuControllerImpl( getSelectedDataSources(true))); } } if (filter != null) { final MenuItem itemFilter = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemFilter, "MyTorrentsView.menu.filter"); itemFilter.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { openFilterDialog(); } }); } } void showColumnEditor() { TableRowCore focusedRow = getFocusedRow(); if (focusedRow == null) { focusedRow = getRow(0); } new TableColumnSetupWindow(classPluginDataSourceType, sTableID, focusedRow, TableStructureEventDispatcher.getInstance(sTableID)).open(); } /** * SubMenu for column specific tasks. * * @param iColumn Column # that tasks apply to. */ private void fillColumnMenu(final TableColumn tcColumn) { final MenuItem itemChangeTable = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemChangeTable, "MyTorrentsView.menu.editTableColumns"); Utils.setMenuItemImage(itemChangeTable, "columns"); itemChangeTable.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { showColumnEditor(); } }); if (menu != null) { menu.setData("column", tcColumn); } if (tcColumn == null) { return; } String sColumnName = (String) tcColumn.getData("Name"); if (sColumnName != null) { Object[] listeners = listenersMenuFill.toArray(); for (int i = 0; i < listeners.length; i++) { TableViewSWTMenuFillListener l = (TableViewSWTMenuFillListener) listeners[i]; l.addThisColumnSubMenu(sColumnName, menu); } } if (menu.getItemCount() > 0) { new MenuItem(menu, SWT.SEPARATOR); } MenuItem item = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(item, "MyTorrentsView.menu.thisColumn.sort"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { tcColumn.notifyListeners(SWT.Selection, new Event()); } }); final MenuItem at_item = new MenuItem(menu, SWT.CHECK); Messages.setLanguageText(at_item, "MyTorrentsView.menu.thisColumn.autoTooltip"); at_item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { TableColumn tc = (TableColumn) menu.getData("column"); TableColumnCore tcc = (TableColumnCore) tc.getData("TableColumnCore"); tcc.setAutoTooltip(at_item.getSelection()); tcc.invalidateCells(); } }); at_item.setSelection(((TableColumnCore) tcColumn.getData("TableColumnCore")).doesAutoTooltip()); item = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(item, "MyTorrentsView.menu.thisColumn.remove"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { TableColumn tc = (TableColumn) menu.getData("column"); if (tc == null) { return; } String columnName = (String) tcColumn.getData("Name"); if (columnName == null) { return; } for (int i = 0; i < tableColumns.length; i++) { if (tableColumns[i].getName().equals(columnName)) { tableColumns[i].setVisible(false); } } tableStructureChanged(false, null); } }); // Add Plugin Context menus.. TableColumnCore tc = (TableColumnCore) tcColumn.getData("TableColumnCore"); TableContextMenuItem[] items = tc.getContextMenuItems(TableColumnCore.MENU_STYLE_HEADER); if (items.length > 0) { new MenuItem(menu, SWT.SEPARATOR); MenuBuildUtils.addPluginMenuItems(getComposite(), items, menu, true, true, new MenuBuildUtils.MenuItemPluginMenuControllerImpl( getSelectedDataSources(true))); } } /** IView.getComposite() * @return the composite for this TableView */ public Composite getComposite() { return mainComposite; } public Composite getTableComposite() { return tableComposite; } public IView getActiveSubView() { if (!bEnableTabViews || tabFolder == null || tabFolder.isDisposed() || tabFolder.getMinimized()) { return null; } CTabItem item = tabFolder.getSelection(); if (item != null) { return (IView) item.getData("IView"); } return null; } public void refreshSelectedSubView() { IView view = getActiveSubView(); if (view != null && view.getComposite().isVisible()) { view.refresh(); } } // see common.TableView public void refreshTable(final boolean bForceSort) { Utils.execSWTThread(new AERunnable() { public void runSupport() { _refreshTable(bForceSort); if (bEnableTabViews && tabFolder != null && !tabFolder.isDisposed() && !tabFolder.getMinimized()) { refreshSelectedSubView(); } } }); triggerTableRefreshListeners(); } private void _refreshTable(boolean bForceSort) { // don't refresh while there's no table if (table == null) { return; } // call to trigger invalidation if visibility changes isVisible(); // XXX Try/Finally used to be there for monitor.enter/exit, however // this doesn't stop re-entry from the same thread while already in // process.. need a bAlreadyRefreshing variable instead try { if (getComposite() == null || getComposite().isDisposed()) { return; } if (columnVisibilitiesChanged == true) { updateColumnVisibilities(); } final boolean bDoGraphics = (loopFactor % graphicsUpdate) == 0; final boolean bWillSort = bForceSort || (reOrderDelay != 0) && ((loopFactor % reOrderDelay) == 0); //System.out.println("Refresh.. WillSort? " + bWillSort); if (bWillSort) { if (bForceSort && sortColumn != null) { sortColumn.setLastSortValueChange(SystemTime.getCurrentTime()); } _sortColumn(true, false, false); } long lTimeStart = SystemTime.getMonotonousTime(); //Refresh all visible items in table... runForAllRows(new TableGroupRowVisibilityRunner() { public void run(TableRowCore row, boolean bVisible) { row.refresh(bDoGraphics, bVisible); } }); if (DEBUGADDREMOVE) { long lTimeDiff = (SystemTime.getMonotonousTime() - lTimeStart); if (lTimeDiff > 500) { debug(lTimeDiff + "ms to refresh rows"); } } loopFactor++; } finally { } } private void refreshVisibleRows() { if (getComposite() == null || getComposite().isDisposed()) { return; } runForVisibleRows(new TableGroupRowRunner() { public void run(TableRowCore row) { row.refresh(false, true); } }); } // see common.TableView public void processDataSourceQueue() { Object[] dataSourcesAdd = null; Object[] dataSourcesRemove = null; try { dataSourceToRow_mon.enter(); if (dataSourcesToAdd.size() > 0) { if (dataSourcesToAdd.removeAll(dataSourcesToRemove) && DEBUGADDREMOVE) { debug("Saved time by not adding a row that was removed"); } dataSourcesAdd = dataSourcesToAdd.toArray(); dataSourcesToAdd.clear(); } if (dataSourcesToRemove.size() > 0) { dataSourcesRemove = dataSourcesToRemove.toArray(); if (DEBUGADDREMOVE && dataSourcesRemove.length > 1) { debug("Streamlining removing " + dataSourcesRemove.length + " rows"); } dataSourcesToRemove.clear(); } } finally { dataSourceToRow_mon.exit(); } if (dataSourcesAdd != null && dataSourcesAdd.length > 0) { reallyAddDataSources(dataSourcesAdd); if (DEBUGADDREMOVE && dataSourcesAdd.length > 1) { debug("Streamlined adding " + dataSourcesAdd.length + " rows"); } } if (dataSourcesRemove != null && dataSourcesRemove.length > 0) { reallyRemoveDataSources(dataSourcesRemove); } } private void locationChanged(final int iStartColumn) { if (getComposite() == null || getComposite().isDisposed()) { return; } columnVisibilitiesChanged = true; runForAllRows(new TableGroupRowRunner() { public void run(TableRowCore row) { row.locationChanged(iStartColumn); } }); } private void doPaint(final GC gc, final Rectangle dirtyArea) { if (getComposite() == null || getComposite().isDisposed()) { return; } runForVisibleRows(new TableGroupRowRunner() { public void run(TableRowCore row) { if (!(row instanceof TableRowSWT)) { return; } TableRowSWT rowSWT = (TableRowSWT) row; Rectangle bounds = rowSWT.getBounds(); if (bounds.intersects(dirtyArea)) { if (Constants.isWindowsVistaOrHigher) { Image imgBG = new Image(gc.getDevice(), bounds.width, bounds.height); gc.copyArea(imgBG, bounds.x, bounds.y); rowSWT.setBackgroundImage(imgBG); } //System.out.println("paint " + row); Color oldBG = (Color) row.getData("bgColor"); Color newBG = rowSWT.getBackground(); if (oldBG == null || !oldBG.equals(newBG)) { //System.out.println("redraw " + row + "; " + oldBG + ";" + newBG); row.invalidate(); row.redraw(); row.setData("bgColor", newBG); } else { rowSWT.doPaint(gc, true); } } } }); } /** IView.delete: This method is called when the view is destroyed. * Each color instanciated, images and such things should be disposed. * The caller is the GUI thread. */ public void delete() { triggerLifeCycleListener(TableLifeCycleListener.EVENT_DESTROYED); if (tabViews != null && tabViews.size() > 0) { for (int i = 0; i < tabViews.size(); i++) { IView view = tabViews.get(i); if (view != null) { view.delete(); } } } TableStructureEventDispatcher.getInstance(sTableID).removeListener(this); TableColumnManager tcManager = TableColumnManager.getInstance(); if (tcManager != null) { tcManager.saveTableColumns(classPluginDataSourceType, sTableID); } if (table != null && !table.isDisposed()) { table.dispose(); } removeAllTableRows(); configMan.removeParameterListener("ReOrder Delay", this); configMan.removeParameterListener("Graphics Update", this); Colors.getInstance().removeColorsChangedListener(this); processDataSourceQueueCallback = null; //oldSelectedItems = null; Composite comp = getComposite(); if (comp != null && !comp.isDisposed()) { comp.dispose(); } } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#updateLanguage() */ public void updateLanguage() { if (tabViews != null && tabViews.size() > 0) { for (int i = 0; i < tabViews.size(); i++) { IView view = tabViews.get(i); if (view != null) { view.updateLanguage(); } } } } // see common.TableView public void addDataSource(DATASOURCETYPE dataSource) { addDataSource(dataSource, false); } private void addDataSource(DATASOURCETYPE dataSource, boolean skipFilterCheck) { if (dataSource == null) { return; } listUnfilteredDatasources_mon.enter(); try { listUnfilteredDataSources.add(dataSource); } finally { listUnfilteredDatasources_mon.exit(); } if (!skipFilterCheck && filter != null && !filter.checker.filterCheck(dataSource, filter.text, filter.regex)) { return; } if (Utils.IMMEDIATE_ADDREMOVE_DELAY == 0) { reallyAddDataSources(new Object[] { dataSource }); return; } // In order to save time, we cache entries to be added and process them // in a refresh cycle. This is a huge benefit to tables that have // many rows being added and removed in rapid succession try { dataSourceToRow_mon.enter(); boolean alreadyThere = dataSourcesToAdd.contains(dataSource); if (alreadyThere) { // added twice.. ensure it's not in the remove list dataSourcesToRemove.remove(dataSource); if (DEBUGADDREMOVE) { debug("AddDS: Already There. Total Queued: " + dataSourcesToAdd.size()); } } else { dataSourcesToAdd.add(dataSource); if (DEBUGADDREMOVE) { debug("Queued 1 dataSource to add. Total Queued: " + dataSourcesToAdd.size()); } refreshenProcessDataSourcesTimer(); } } finally { dataSourceToRow_mon.exit(); } } // see common.TableView public void addDataSources(final DATASOURCETYPE dataSources[]) { addDataSources(dataSources, false); } public void addDataSources(final DATASOURCETYPE dataSources[], boolean skipFilterCheck) { if (dataSources == null) { return; } listUnfilteredDatasources_mon.enter(); try { listUnfilteredDataSources.addAll(Arrays.asList(dataSources)); } finally { listUnfilteredDatasources_mon.exit(); } if (Utils.IMMEDIATE_ADDREMOVE_DELAY == 0) { if (!skipFilterCheck && filter!= null) { for (int i = 0; i < dataSources.length; i++) { if (!filter.checker.filterCheck(dataSources[i], filter.text, filter.regex)) { dataSources[i] = null; } } } reallyAddDataSources(dataSources); return; } // In order to save time, we cache entries to be added and process them // in a refresh cycle. This is a huge benefit to tables that have // many rows being added and removed in rapid succession try { dataSourceToRow_mon.enter(); int count = 0; for (int i = 0; i < dataSources.length; i++) { if (dataSources[i] == null) { continue; } if (!skipFilterCheck && filter != null && !filter.checker.filterCheck(dataSources[i], filter.text, filter.regex)) { continue; } boolean alreadyThere = dataSourcesToAdd.contains(dataSources[i]); if (alreadyThere) { // added twice.. ensure it's not in the remove list dataSourcesToRemove.remove(dataSources[i]); } else { count++; dataSourcesToAdd.add(dataSources[i]); } } if (DEBUGADDREMOVE) { debug("Queued " + count + " of " + dataSources.length + " dataSources to add. Total Queued: " + dataSourcesToAdd.size()); } } finally { dataSourceToRow_mon.exit(); } refreshenProcessDataSourcesTimer(); } private void refreshenProcessDataSourcesTimer() { if (bReallyAddingDataSources || processDataSourceQueueCallback == null) { // when processDataSourceQueueCallback is null, we are disposing return; } if (cellEditNotifier != null) { cellEditNotifier.sourcesChanged(); } boolean processQueueImmediately = Utils.addDataSourceAggregated(processDataSourceQueueCallback); if (processQueueImmediately) { processDataSourceQueue(); } } private void reallyAddDataSources(final Object dataSources[]) { // Note: We assume filterCheck has already run, and the list of dataSources // all passed the filter if (mainComposite == null || table == null || mainComposite.isDisposed() || table.isDisposed()) { return; } bReallyAddingDataSources = true; if (DEBUGADDREMOVE) { debug(">>" + " Add " + dataSources.length + " rows;"); } Object[] remainingDataSources = null; Object[] doneDataSources = dataSources; // Create row, and add to map immediately try { dataSourceToRow_mon.enter(); long lStartTime = SystemTime.getCurrentTime(); for (int i = 0; i < dataSources.length; i++) { if (dataSources[i] == null) { continue; } // Break off and add the rows to the UI if we've taken too long to // create them if (SystemTime.getCurrentTime() - lStartTime > BREAKOFF_ADDTOMAP) { int iNewSize = dataSources.length - i; if (DEBUGADDREMOVE) { debug("Breaking off adding datasources to map after " + i + " took " + (SystemTime.getCurrentTime() - lStartTime) + "ms; # remaining: " + iNewSize); } remainingDataSources = new Object[iNewSize]; doneDataSources = new Object[i]; System.arraycopy(dataSources, i, remainingDataSources, 0, iNewSize); System.arraycopy(dataSources, 0, doneDataSources, 0, i); break; } if (mapDataSourceToRow.containsKey(dataSources[i])) { dataSources[i] = null; } else { TableRowImpl row = new TableRowImpl(this, table, sTableID, columnsOrdered, dataSources[i], bSkipFirstColumn); mapDataSourceToRow.put((DATASOURCETYPE) dataSources[i], row); } } } catch (Exception e) { Logger.log(new LogEvent(LOGID, "Error while added row to Table " + sTableID, e)); } finally { dataSourceToRow_mon.exit(); } if (DEBUGADDREMOVE) { debug("--" + " Add " + doneDataSources.length + " rows;"); } if (remainingDataSources == null) { addDataSourcesToSWT(doneDataSources, true); } else { final Object[] fDoneDataSources = doneDataSources; final Object[] fRemainingDataSources = remainingDataSources; // wrap both calls in a SWT thread so that continuation of adding // remaining datasources will be on SWT thread. OSX has horrible handling // of switching to SWT thread. Utils.execSWTThread(new AERunnable() { public void runSupport() { addDataSourcesToSWT(fDoneDataSources, false); reallyAddDataSources(fRemainingDataSources); } }, false); } } private void addDataSourcesToSWT(final Object dataSources[], boolean async) { try { if (isDisposed()) { return; } if (DEBUGADDREMOVE) { debug("--" + " Add " + dataSources.length + " rows to SWT " + (async ? " async " : " NOW")); } if (async) { table.getDisplay().asyncExec(new AERunnable() { public void runSupport() { _addDataSourcesToSWT(dataSources); } }); } else { Utils.execSWTThread(new AERunnable() { public void runSupport() { _addDataSourcesToSWT(dataSources); } }, false); } } catch (Exception e) { bReallyAddingDataSources = false; e.printStackTrace(); } } private void _addDataSourcesToSWT(final Object dataSources[]) { if (table == null || table.isDisposed()) { bReallyAddingDataSources = false; return; } mainComposite.getParent().setCursor( table.getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); TableRowCore[] selectedRows = getSelectedRows(); boolean bBrokeEarly = false; boolean bReplacedVisible = false; boolean bWas0Rows = table.getItemCount() == 0; try { dataSourceToRow_mon.enter(); sortedRows_mon.enter(); if (DEBUGADDREMOVE) { debug("--" + " Add " + dataSources.length + " rows to SWT"); } // purposefully not included in time check table.setItemCount(sortedRows.size() + dataSources.length); long lStartTime = SystemTime.getCurrentTime(); int iTopIndex = table.getTopIndex(); int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex); // add to sortedRows list in best position. // We need to be in the SWT thread because the rowSorter may end up // calling SWT objects. for (int i = 0; i < dataSources.length; i++) { Object dataSource = dataSources[i]; if (dataSource == null) { continue; } // If we've been processing on the SWT thread for too long, // break off and allow SWT a breather to update. if (SystemTime.getCurrentTime() - lStartTime > BREAKOFF_ADDROWSTOSWT) { int iNewSize = dataSources.length - i; if (DEBUGADDREMOVE) { debug("Breaking off adding datasources to SWT after " + i + " took " + (SystemTime.getCurrentTime() - lStartTime) + "ms; # remaining: " + iNewSize); } Object[] remainingDataSources = new Object[iNewSize]; System.arraycopy(dataSources, i, remainingDataSources, 0, iNewSize); addDataSourcesToSWT(remainingDataSources, true); bBrokeEarly = true; break; } TableRowImpl row = (TableRowImpl) mapDataSourceToRow.get(dataSource); if (row == null || row.getIndex() >= 0) { continue; } if (sortColumn != null) { TableCellSWT cell = row.getTableCellSWT(sortColumn.getName()); if (cell != null) { try { cell.invalidate(); cell.refresh(true); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "Minor error adding a row to table " + sTableID, e)); } } } try { int index = 0; if (sortedRows.size() > 0) { // If we are >= to the last item, then just add it to the end // instead of relying on binarySearch, which may return an item // in the middle that also is equal. TableRowSWT lastRow = sortedRows.get(sortedRows.size() - 1); if (sortColumn == null || sortColumn.compare(row, lastRow) >= 0) { index = sortedRows.size(); sortedRows.add(row); if (DEBUGADDREMOVE) { debug("Adding new row to bottom"); } } else { index = Collections.binarySearch(sortedRows, row, sortColumn); if (index < 0) { index = -1 * index - 1; // best guess } if (index > sortedRows.size()) { index = sortedRows.size(); } if (DEBUGADDREMOVE) { debug("Adding new row at position " + index + " of " + (sortedRows.size() - 1)); } sortedRows.add(index, row); } } else { if (DEBUGADDREMOVE) { debug("Adding new row to bottom (1st Entry)"); } index = sortedRows.size(); sortedRows.add(row); } // NOTE: if the listener tries to do something like setSelected, // it will fail because we aren't done adding. // we should trigger after fillRowGaps() triggerListenerRowAdded(row); if (!bReplacedVisible && index >= iTopIndex && index <= iBottomIndex) { bReplacedVisible = true; } // XXX Don't set table item here, it will mess up selected rows // handling (which is handled in fillRowGaps called later on) //row.setTableItem(index); row.setIconSize(ptIconSize); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "Error adding a row to table " + sTableID, e)); try { if (!sortedRows.contains(row)) { sortedRows.add(row); } } catch (Exception e2) { Debug.out(e2); } } } // for dataSources if (DEBUGADDREMOVE) { debug("Adding took " + (SystemTime.getCurrentTime() - lStartTime) + "ms"); } // Sanity Check: Make sure # of rows in table and in array match if (table.getItemCount() > sortedRows.size() && !bBrokeEarly) { // This could happen if one of the datasources was null, or // an error occured table.setItemCount(sortedRows.size()); } } catch (Exception e) { Logger.log(new LogEvent(LOGID, "Error while adding row to Table " + sTableID, e)); } finally { sortedRows_mon.exit(); dataSourceToRow_mon.exit(); if (!bBrokeEarly) { bReallyAddingDataSources = false; refreshenProcessDataSourcesTimer(); } } if (!bBrokeEarly || bReplacedVisible) { fillRowGaps(false); if (bReplacedVisible) { lastTopIndex = 0; lastBottomIndex = -1; visibleRowsChanged(); } } if (!columnPaddingAdjusted && table.getItemCount() > 0 && bWas0Rows) { TableColumn[] tableColumnsSWT = table.getColumns(); TableItem item = table.getItem(0); // on *nix, the last column expands to fill remaining space.. let's just not touch it int len = Constants.isUnix ? tableColumnsSWT.length - 1 : tableColumnsSWT.length; for (int i = 0; i < len; i++) { TableColumnCore tc = (TableColumnCore) tableColumnsSWT[i].getData("TableColumnCore"); if (tc != null) { boolean foundOne = false; Rectangle bounds = item.getBounds(i); int tcWidth = tc.getWidth(); if (tcWidth != 0 && bounds.width != 0) { Object oOldOfs = tableColumnsSWT[i].getData("widthOffset"); int oldOfs = (oOldOfs instanceof Number) ? ((Number)oOldOfs).intValue() : 0; int ofs = tc.getWidth() - bounds.width + oldOfs; if (ofs > 0 && ofs != oldOfs) { foundOne = true; tableColumnsSWT[i].setResizable(true); tableColumnsSWT[i].setData("widthOffset", new Long(ofs + oldOfs)); } } if (foundOne) { tc.triggerColumnSizeChange(); } } } columnPaddingAdjusted = true; } setSelectedRows(selectedRows); if (DEBUGADDREMOVE) { debug("<< " + sortedRows.size()); } mainComposite.getParent().setCursor(null); } // @see com.aelitis.azureus.ui.common.table.TableView#removeDataSource(java.lang.Object) public void removeDataSource(final DATASOURCETYPE dataSource) { if (dataSource == null) { return; } listUnfilteredDatasources_mon.enter(); try { listUnfilteredDataSources.remove(dataSource); } finally { listUnfilteredDatasources_mon.exit(); } if (Utils.IMMEDIATE_ADDREMOVE_DELAY == 0) { reallyRemoveDataSources(new Object[]{dataSource}); return; } try { dataSourceToRow_mon.enter(); dataSourcesToRemove.add(dataSource); if (DEBUGADDREMOVE) { debug("Queued 1 dataSource to remove. Total Queued: " + dataSourcesToRemove.size()); } } finally { dataSourceToRow_mon.exit(); } refreshenProcessDataSourcesTimer(); } /** Remove the specified dataSource from the table. * * @param dataSources data sources to be removed * @param bImmediate Remove immediately, or queue and remove at next refresh */ public void removeDataSources(final DATASOURCETYPE[] dataSources) { if (dataSources == null || dataSources.length == 0) { return; } listUnfilteredDatasources_mon.enter(); try { listUnfilteredDataSources.removeAll(Arrays.asList(dataSources)); } finally { listUnfilteredDatasources_mon.exit(); } if (Utils.IMMEDIATE_ADDREMOVE_DELAY == 0) { reallyRemoveDataSources(dataSources); return; } try { dataSourceToRow_mon.enter(); for (int i = 0; i < dataSources.length; i++) { dataSourcesToRemove.add(dataSources[i]); } if (DEBUGADDREMOVE) { debug("Queued " + dataSources.length + " dataSources to remove. Total Queued: " + dataSourcesToRemove.size()); } } finally { dataSourceToRow_mon.exit(); } refreshenProcessDataSourcesTimer(); } private void reallyRemoveDataSources(final Object[] dataSources) { if (DEBUGADDREMOVE) { debug(">> Remove rows"); } final long lStart = SystemTime.getCurrentTime(); boolean ok = Utils.execSWTThread(new AERunnable() { public void runSupport() { if (table == null || table.isDisposed()) { return; } int numSelected = table.getSelectionCount(); mainComposite.getParent().setCursor( table.getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); StringBuffer sbWillRemove = null; if (DEBUGADDREMOVE) { debug(">>> Remove rows. Start w/" + mapDataSourceToRow.size() + "ds; tc=" + table.getItemCount() + ";" + (SystemTime.getCurrentTime() - lStart) + "ms wait"); sbWillRemove = new StringBuffer("Will soon remove row #"); } ArrayList itemsToRemove = new ArrayList(); ArrayList swtItemsToRemove = new ArrayList(); int iTopIndex = table.getTopIndex(); int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex); boolean bRefresh = false; if (DEBUGADDREMOVE) { debug("--- Remove: vis rows " + iTopIndex + " to " + iBottomIndex); } // pass one: get the SWT indexes of the items we are going to remove // This will re-link them if they lost their link for (int i = 0; i < dataSources.length; i++) { if (dataSources[i] == null) { continue; } TableRowSWT item = (TableRowSWT) mapDataSourceToRow.get(dataSources[i]); if (item != null) { // use sortedRows position instead of item.getIndex(), because // getIndex may have a wrong value (unless we fillRowGaps() which // is more time consuming and we do afterwards anyway) int index = sortedRows.indexOf(item); if (!bRefresh) { bRefresh = index >= iTopIndex && index <= iBottomIndex; } if (DEBUGADDREMOVE) { if (i != 0) { sbWillRemove.append(", "); } sbWillRemove.append(index); } if (index >= 0) { swtItemsToRemove.add(new Long(index)); } } } if (DEBUGADDREMOVE) { debug(sbWillRemove.toString()); debug("#swtItemsToRemove=" + swtItemsToRemove.size()); } boolean hasSelected = false; // pass 2: remove from map and list, add removed to seperate list for (int i = 0; i < dataSources.length; i++) { if (dataSources[i] == null) { continue; } // Must remove from map before deleted from gui TableRowSWT item = (TableRowSWT) mapDataSourceToRow.remove(dataSources[i]); if (item != null) { if (item.isSelected()) { hasSelected = true; } itemsToRemove.add(item); sortedRows.remove(item); triggerListenerRowRemoved(item); } } if (DEBUGADDREMOVE) { debug("-- Removed from map and list"); } // Remove the rows from SWT first. On SWT 3.2, this currently has // zero perf gain, and a small perf gain on Windows. However, in the // future it may be optimized. if (swtItemsToRemove.size() > 0) { // int[] swtRowsToRemove = new int[swtItemsToRemove.size()]; // for (int i = 0; i < swtItemsToRemove.size(); i++) { // swtRowsToRemove[i] = ((Long) swtItemsToRemove.get(i)).intValue(); // } // table.remove(swtRowsToRemove); // refreshVisibleRows should fix up the display table.setItemCount(mapDataSourceToRow.size()); } if (DEBUGADDREMOVE) { debug("-- Removed from SWT"); } // Finally, delete the rows for (Iterator iter = itemsToRemove.iterator(); iter.hasNext();) { TableRowCore row = iter.next(); row.delete(); } if (bRefresh) { fillRowGaps(false); refreshVisibleRows(); if (DEBUGADDREMOVE) { debug("-- Fill row gaps and refresh after remove"); } } if (DEBUGADDREMOVE) { debug("<< Remove " + itemsToRemove.size() + " rows. now " + mapDataSourceToRow.size() + "ds; tc=" + table.getItemCount()); } mainComposite.getParent().setCursor(null); if (numSelected != table.getSelectionCount()) { triggerDeselectionListeners(new TableRowCore[0]); } if (hasSelected) { updateSelectedRowIndexes(); triggerSelectionListeners(getSelectedRows()); } } }); if (!ok) { // execRunnable will only fail if we are closing for (int i = 0; i < dataSources.length; i++) { if (dataSources[i] == null) { continue; } TableRowSWT item = (TableRowSWT) mapDataSourceToRow.get(dataSources[i]); mapDataSourceToRow.remove(dataSources[i]); if (item != null) { sortedRows.remove(item); } } if (DEBUGADDREMOVE) { debug("<< Remove row(s), noswt"); } } } // from common.TableView public void removeAllTableRows() { long lTimeStart = System.currentTimeMillis(); final TableRowCore[] rows = getRows(); try { dataSourceToRow_mon.enter(); sortedRows_mon.enter(); mapDataSourceToRow.clear(); sortedRows.clear(); dataSourcesToAdd.clear(); dataSourcesToRemove.clear(); if (DEBUGADDREMOVE) { debug("removeAll"); } } finally { sortedRows_mon.exit(); dataSourceToRow_mon.exit(); } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (table != null && !table.isDisposed()) { table.removeAll(); } // Image Disposal handled by each cell for (int i = 0; i < rows.length; i++) { rows[i].delete(); } } }); if (DEBUGADDREMOVE) { long lTimeDiff = (System.currentTimeMillis() - lTimeStart); if (lTimeDiff > 10) { debug("RemovaAll took " + lTimeDiff + "ms"); } } } // @see com.aelitis.azureus.ui.common.table.TableView#getTableID() public String getTableID() { return sTableID; } /* ParameterListener Implementation */ public void parameterChanged(String parameterName) { if (parameterName == null || parameterName.equals("Graphics Update")) { graphicsUpdate = configMan.getIntParameter("Graphics Update"); } if (parameterName == null || parameterName.equals("ReOrder Delay")) { reOrderDelay = configMan.getIntParameter("ReOrder Delay"); } if (parameterName == null || parameterName.startsWith("Color")) { tableInvalidate(); } } // ITableStructureModificationListener public void tableStructureChanged(final boolean columnAddedOrRemoved, Class forPluginDataSourceType) { if (forPluginDataSourceType == null || forPluginDataSourceType.equals(classPluginDataSourceType)) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (table.isDisposed()) { return; } _tableStructureChanged(columnAddedOrRemoved); } }); } } private void _tableStructureChanged(boolean columnAddedOrRemoved) { triggerLifeCycleListener(TableLifeCycleListener.EVENT_DESTROYED); removeAllTableRows(); if (columnAddedOrRemoved) { tableColumns = TableColumnManager.getInstance().getAllTableColumnCoreAsArray( classPluginDataSourceType, sTableID); } initializeTableColumns(table); refreshTable(false); triggerLifeCycleListener(TableLifeCycleListener.EVENT_INITIALIZED); } // ITableStructureModificationListener public void columnOrderChanged(int[] positions) { try { table.setColumnOrder(positions); updateColumnVisibilities(); } catch (NoSuchMethodError e) { // Pre SWT 3.1 // This shouldn't really happen, since this function only gets triggered // from SWT >= 3.1 tableStructureChanged(false, null); } } /** * The Columns width changed */ // ITableStructureModificationListener public void columnSizeChanged(TableColumnCore tableColumn) { int newWidth = tableColumn.getWidth(); if (table == null || table.isDisposed()) { return; } TableColumn column = null; TableColumn[] tableColumnsSWT = table.getColumns(); for (int i = 0; i < tableColumnsSWT.length; i++) { if (tableColumnsSWT[i].getData("TableColumnCore") == tableColumn) { column = tableColumnsSWT[i]; break; } } if (column == null) { return; } Long lOfs = (Long) column.getData("widthOffset"); if (lOfs != null) { newWidth += lOfs.intValue(); } if (column.isDisposed() || (column.getWidth() == newWidth)) { return; } if (Constants.isUnix) { final int fNewWidth = newWidth; final TableColumn fTableColumn = column; column.getDisplay().asyncExec(new AERunnable() { public void runSupport() { if (!fTableColumn.isDisposed()) { fTableColumn.setWidth(fNewWidth); } } }); } else { column.setWidth(newWidth); } } // ITableStructureModificationListener // TableView public void columnInvalidate(TableColumnCore tableColumn) { // We are being called from a plugin (probably), so we must refresh columnInvalidate(tableColumn, true); } // @see com.aelitis.azureus.ui.common.table.TableStructureModificationListener#cellInvalidate(com.aelitis.azureus.ui.common.table.TableColumnCore, java.lang.Object) public void cellInvalidate(TableColumnCore tableColumn, DATASOURCETYPE data_source) { cellInvalidate(tableColumn, data_source, true); } public void columnRefresh(TableColumnCore tableColumn) { final String sColumnName = tableColumn.getName(); runForAllRows(new TableGroupRowVisibilityRunner() { public void run(TableRowCore row, boolean bVisible) { TableCellSWT cell = ((TableRowSWT) row).getTableCellSWT(sColumnName); if (cell != null) { cell.refresh(true, bVisible); } } }); } /** * Invalidate and refresh whole table */ public void tableInvalidate() { runForAllRows(new TableGroupRowVisibilityRunner() { public void run(TableRowCore row, boolean bVisible) { row.invalidate(); row.refresh(true, bVisible); } }); } // see common.TableView public void columnInvalidate(final String sColumnName) { TableColumnCore tc = TableColumnManager.getInstance().getTableColumnCore( sTableID, sColumnName); if (tc != null) { columnInvalidate(tc, tc.getType() == TableColumnCore.TYPE_TEXT_ONLY); } } public void columnInvalidate(TableColumnCore tableColumn, final boolean bMustRefresh) { final String sColumnName = tableColumn.getName(); runForAllRows(new TableGroupRowRunner() { public void run(TableRowCore row) { TableCellSWT cell = ((TableRowSWT) row).getTableCellSWT(sColumnName); if (cell != null) { cell.invalidate(bMustRefresh); } } }); } public void cellInvalidate(TableColumnCore tableColumn, final DATASOURCETYPE data_source, final boolean bMustRefresh) { final String sColumnName = tableColumn.getName(); runForAllRows(new TableGroupRowRunner() { public void run(TableRowCore row) { TableCellSWT cell = ((TableRowSWT) row).getTableCellSWT(sColumnName); if (cell != null && cell.getDataSource() != null && cell.getDataSource().equals(data_source)) { cell.invalidate(bMustRefresh); } } }); } // @see com.aelitis.azureus.ui.common.table.TableView#getColumnCells(java.lang.String) public TableCellCore[] getColumnCells(String sColumnName) { TableCellCore[] cells = new TableCellCore[sortedRows.size()]; try { sortedRows_mon.enter(); int i = 0; for (Iterator iter = sortedRows.iterator(); iter.hasNext();) { TableRowCore row = iter.next(); cells[i++] = row.getTableCellCore(sColumnName); } } finally { sortedRows_mon.exit(); } return cells; } public org.gudy.azureus2.plugins.ui.tables.TableColumn getTableColumn( String sColumnName) { for (int i = 0; i < tableColumns.length; i++) { TableColumnCore tc = tableColumns[i]; if (tc.getName().equals(sColumnName)) { return tc; } } return null; } // @see com.aelitis.azureus.ui.common.table.TableView#getRows() public TableRowCore[] getRows() { try { sortedRows_mon.enter(); return sortedRows.toArray(new TableRowCore[0]); } finally { sortedRows_mon.exit(); } } // @see com.aelitis.azureus.ui.common.table.TableView#getRow(java.lang.Object) public TableRowCore getRow(DATASOURCETYPE dataSource) { return mapDataSourceToRow.get(dataSource); } // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getRowSWT(java.lang.Object) public TableRowSWT getRowSWT(DATASOURCETYPE dataSource) { return (TableRowSWT) mapDataSourceToRow.get(dataSource); } // @see com.aelitis.azureus.ui.common.table.TableView#getRow(int) public TableRowCore getRow(int iPos) { try { sortedRows_mon.enter(); if (iPos >= 0 && iPos < sortedRows.size()) { TableRowCore row = sortedRows.get(iPos); if (row.getIndex() != iPos) { row.setTableItem(iPos); } return row; } } finally { sortedRows_mon.exit(); } return null; } protected TableRowCore getRowQuick(int iPos) { try { return sortedRows.get(iPos); } catch (Exception e) { return null; } } public int indexOf(TableRowCore row) { int i = ((TableRowImpl) row).getRealIndex(); if (i == -1) { i = sortedRows.indexOf(row); if (i >= 0) { row.setTableItem(i); } } return i; } private TableRowCore getRow(TableItem item) { try { Object o = item.getData("TableRow"); if (o instanceof TableRowCore) { return (TableRowCore) o; } else { int iPos = table.indexOf(item); //System.out.println(iPos + " has no table row.. associating. " + Debug.getCompressedStackTrace(4)); if (iPos >= 0 && iPos < sortedRows.size()) { TableRowSWT row = sortedRows.get(iPos); //System.out.print(".. associating to " + row); if (row != null) { row.setTableItem(iPos); } //System.out.println(", now " + row); return row; } } } catch (Exception e) { Debug.out(e); } return null; } public int getRowCount() { // don't use sortedRows here, it's not always up to date return mapDataSourceToRow.size(); } // @see com.aelitis.azureus.ui.common.table.TableView#getDataSources() public ArrayList getDataSources() { return new ArrayList(mapDataSourceToRow.keySet()); } /* various selected rows functions */ /***********************************/ public List getSelectedDataSourcesList() { if (listSelectedCoreDataSources != null) { return listSelectedCoreDataSources; } if (table == null || table.isDisposed() || selectedRowIndexes == null || selectedRowIndexes.length == 0) { return Collections.emptyList(); } final ArrayList l = new ArrayList( selectedRowIndexes.length); for (int index : selectedRowIndexes) { TableRowCore row = getRowQuick(index); if (row != null) { Object ds = row.getDataSource(true); if (ds != null) { l.add((DATASOURCETYPE) ds); } } } listSelectedCoreDataSources = l; return l; } /** Returns an array of all selected Data Sources. Null data sources are * ommitted. * * @return an array containing the selected data sources * * @TODO TuxPaper: Virtual row not created when using getSelection? * computePossibleActions isn't being calculated right * because of non-created rows when select user selects all */ public List getSelectedPluginDataSourcesList() { if (table == null || table.isDisposed() || selectedRowIndexes == null || selectedRowIndexes.length == 0) { return Collections.emptyList(); } final ArrayList l = new ArrayList(selectedRowIndexes.length); for (int index : selectedRowIndexes) { TableRowCore row = getRowQuick(index); if (row != null) { Object ds = row.getDataSource(false); if (ds != null) { l.add(ds); } } } return l; } /** Returns an array of all selected Data Sources. Null data sources are * ommitted. * * @return an array containing the selected data sources * **/ // see common.TableView public List getSelectedDataSources() { return new ArrayList(getSelectedDataSourcesList()); } // see common.TableView public Object[] getSelectedDataSources(boolean bCoreDataSource) { if (bCoreDataSource) { return getSelectedDataSourcesList().toArray(); } return getSelectedPluginDataSourcesList().toArray(); } /** @see com.aelitis.azureus.ui.common.table.TableView#getSelectedRows() */ public TableRowCore[] getSelectedRows() { return getSelectedRowsList().toArray(new TableRowCore[0]); } // @see com.aelitis.azureus.ui.common.table.TableView#getSelectedRowsSize() public int getSelectedRowsSize() { return selectedRowIndexes == null ? 0 : selectedRowIndexes.length; } public TableRowSWT[] getSelectedRowsSWT() { return getSelectedRowsList().toArray(new TableRowSWT[0]); } /** Returns an list of all selected TableRowSWT objects. Null data sources are * ommitted. * * @return an list containing the selected TableRowSWT objects */ public List getSelectedRowsList() { List l = new ArrayList(); if (table != null && !table.isDisposed()) { TableItem[] tis = table.getSelection(); for (int i = 0; i < tis.length; i++) { TableRowSWT row = (TableRowSWT) getRow(tis[i]); if (row != null && row.getDataSource(true) != null) { l.add(row); } } } return l; } // @see com.aelitis.azureus.ui.common.table.TableView#getFocusedRow() public TableRowCore getFocusedRow() { TableRowSWT[] selectedRows = getSelectedRowsSWT(); if (selectedRows.length == 0) { return null; } return selectedRows[0]; } // @see com.aelitis.azureus.ui.common.table.TableView#getFirstSelectedDataSource() @SuppressWarnings("unchecked") public DATASOURCETYPE getFirstSelectedDataSource() { return (DATASOURCETYPE) getFirstSelectedDataSource(true); } public TableRowSWT[] getVisibleRows() { if (!isVisible()) { return new TableRowSWT[0]; } int iTopIndex = table.getTopIndex(); if (iTopIndex < 0) { return new TableRowSWT[0]; } int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex); int size = iBottomIndex - iTopIndex + 1; if (size <= 0) { return new TableRowSWT[0]; } TableRowSWT[] rows = new TableRowSWT[size]; int pos = 0; for (int i = iTopIndex; i <= iBottomIndex; i++) { TableItem item = table.getItem(i); if (item != null && !item.isDisposed()) { TableRowSWT row = (TableRowSWT) getRow(item); if (row != null) { rows[pos++] = row; } } } if (pos <= rows.length) { // Some were null, shrink array TableRowSWT[] temp = new TableRowSWT[pos]; System.arraycopy(rows, 0, temp, 0, pos); return temp; } return rows; } /** Returns the first selected data sources. * * @return the first selected data source, or null if no data source is * selected */ public Object getFirstSelectedDataSource(boolean bCoreObject) { if (table == null || table.isDisposed() || table.getSelectionCount() == 0) { return null; } TableRowCore row = getRow(table.getSelection()[0]); if (row == null) { return null; } return row.getDataSource(bCoreObject); } /** For each row source that the user has selected, run the code * provided by the specified parameter. * * @param runner Code to run for each selected row/datasource */ public void runForSelectedRows(TableGroupRowRunner runner) { if (table == null || table.isDisposed()) { return; } TableItem[] tis = table.getSelection(); List rows_to_use = new ArrayList(tis.length); for (int i = 0; i < tis.length; i++) { TableRowCore row = getRow(tis[i]); if (row != null) { if (rows_to_use != null) { rows_to_use.add(row); } } } if (rows_to_use != null) { TableRowCore[] rows = rows_to_use.toArray(new TableRowCore[rows_to_use.size()]); boolean ran = runner.run(rows); if (!ran) { for (int i = 0; i < rows.length; i++) { TableRowCore row = rows[i]; runner.run(row); } } } } /** For each visible row source, run the code provided by the specified * parameter. * * @param runner Code to run for each selected row/datasource */ public void runForVisibleRows(TableGroupRowRunner runner) { TableRowSWT[] rows = getVisibleRows(); if (runner.run(rows)) { return; } for (int i = 0; i < rows.length; i++) { runner.run(rows[i]); } } // see common.tableview public void runForAllRows(TableGroupRowVisibilityRunner runner) { if (table == null || table.isDisposed()) { return; } // put to array instead of synchronised iterator, so that runner can remove TableRowCore[] rows = getRows(); int iTopIndex; int iBottomIndex; if (isVisible()) { iTopIndex = table.getTopIndex(); iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex); } else { iTopIndex = -1; iBottomIndex = -2; } for (int i = 0; i < rows.length; i++) { runner.run(rows[i], i >= iTopIndex && i <= iBottomIndex); } } /** * Runs a specified task for a list of table items that the table contains * @param items A list of TableItems that are part of the table view * @param runner A task */ public void runForTableItems(List items, TableGroupRowRunner runner) { if (table == null || table.isDisposed()) { return; } final Iterator iter = items.iterator(); List rows_to_use = new ArrayList(items.size()); while (iter.hasNext()) { TableItem tableItem = iter.next(); if (tableItem.isDisposed()) { continue; } TableRowSWT row = (TableRowSWT) getRow(tableItem); if (row != null) { rows_to_use.add(row); } } if (rows_to_use.size() > 0) { TableRowCore[] rows = rows_to_use.toArray(new TableRowCore[rows_to_use.size()]); boolean ran = runner.run(rows); if (!ran) { for (int i = 0; i < rows.length; i++) { TableRowCore row = rows[i]; runner.run(row); } } } } // @see com.aelitis.azureus.ui.common.table.TableView#clipboardSelected() public void clipboardSelected() { String sToClipboard = ""; for (int j = 0; j < table.getColumnCount(); j++) { if (j != 0) { sToClipboard += "\t"; } sToClipboard += table.getColumn(j).getText(); } TableItem[] tis = table.getSelection(); for (int i = 0; i < tis.length; i++) { sToClipboard += "\n"; for (int j = 0; j < table.getColumnCount(); j++) { if (j != 0) { sToClipboard += "\t"; } sToClipboard += tis[i].getText(j); } } new Clipboard(getComposite().getDisplay()).setContents(new Object[] { sToClipboard }, new Transfer[] { TextTransfer.getInstance() }); } /** Handle sorting of a column based on clicking the Table Header */ private class ColumnSelectionListener implements Listener { /** Process a Table Header click * @param event event information */ public void handleEvent(final Event event) { TableColumn column = (TableColumn) event.widget; if (column == null) { return; } TableColumnCore tableColumnCore = (TableColumnCore) column.getData("TableColumnCore"); if (tableColumnCore != null) { sortColumnReverse(tableColumnCore); columnVisibilitiesChanged = true; refreshTable(true); } } } /** * Handle movement of a column based on user dragging the Column Header. * SWT >= 3.1 */ private class ColumnMoveListener implements Listener { public void handleEvent(Event event) { TableColumn column = (TableColumn) event.widget; if (column == null) { return; } TableColumnCore tableColumnCore = (TableColumnCore) column.getData("TableColumnCore"); if (tableColumnCore == null) { return; } Table table = column.getParent(); // Get the 'added position' of column // It would have been easier if event (.start, .end) contained the old // and new position.. TableColumn[] tableColumns = table.getColumns(); int iAddedPosition; for (iAddedPosition = 0; iAddedPosition < tableColumns.length; iAddedPosition++) { if (column == tableColumns[iAddedPosition]) { break; } } if (iAddedPosition >= tableColumns.length) { return; } // Find out position in the order list int iColumnOrder[]; try { iColumnOrder = table.getColumnOrder(); } catch (NoSuchMethodError e) { // Ignore < SWT 3.1 return; } for (int i = 0; i < iColumnOrder.length; i++) { if (iColumnOrder[i] == iAddedPosition) { int iNewPosition = i - (bSkipFirstColumn ? 1 : 0); if (tableColumnCore.getPosition() != iNewPosition) { if (iNewPosition == -1) { iColumnOrder[0] = 0; iColumnOrder[1] = iAddedPosition; table.setColumnOrder(iColumnOrder); iNewPosition = 0; } //System.out.println("Moving " + tableColumnCore.getName() + " to Position " + i); tableColumnCore.setPositionNoShift(iNewPosition); tableColumnCore.saveSettings(null); TableStructureEventDispatcher.getInstance(sTableID).columnOrderChanged( iColumnOrder); } break; } } } } private int getColumnNo(int iMouseX) { int iColumn = -1; int itemCount = table.getItemCount(); if (table.getItemCount() > 0) { //Using table.getTopIndex() instead of 0, cause //the first row has no bounds when it's not visible under OS X. int topIndex = table.getTopIndex(); if (topIndex >= itemCount || topIndex < 0) { topIndex = itemCount - 1; } TableItem ti = table.getItem(topIndex); if (ti.isDisposed()) { return -1; } for (int i = bSkipFirstColumn ? 1 : 0; i < table.getColumnCount(); i++) { // M8 Fixes SWT GTK Bug 51777: // "TableItem.getBounds(int) returns the wrong values when table scrolled" Rectangle cellBounds = ti.getBounds(i); //System.out.println("i="+i+";Mouse.x="+iMouseX+";cellbounds="+cellBounds); if (iMouseX >= cellBounds.x && iMouseX < cellBounds.x + cellBounds.width && cellBounds.width > 0) { iColumn = i; break; } } } return iColumn; } public TableRowCore getRow(int x, int y) { int iColumn = getColumnNo(x); if (iColumn < 0) { return null; } TableItem item = table.getItem(new Point(2, y)); if (item == null) { return null; } return getRow(item); } public TableCellSWT getTableCell(int x, int y) { int iColumn = getColumnNo(x); if (iColumn < 0) { return null; } TableItem item = table.getItem(new Point(2, y)); if (item == null) { return null; } TableRowSWT row = (TableRowSWT) getRow(item); if (row == null) { return null; } TableColumn tcColumn = table.getColumn(iColumn); String sCellName = (String) tcColumn.getData("Name"); if (sCellName == null) { return null; } return row.getTableCellSWT(sCellName); } public TableRowSWT getTableRow(int x, int y) { TableItem item = table.getItem(new Point(2, y)); if (item == null) { return null; } return (TableRowSWT) getRow(item); } private TableColumnCore getTableColumnByOffset(int x) { int iColumn = getColumnNo(x); if (iColumn < 0) { return null; } TableColumn column = table.getColumn(iColumn); return (TableColumnCore) column.getData("TableColumnCore"); } // @see org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator#generate(org.gudy.azureus2.core3.util.IndentWriter) public void generate(IndentWriter writer) { writer.println("Diagnostics for " + this + " (" + sTableID + ")"); try { dataSourceToRow_mon.enter(); writer.println("DataSources scheduled to Add/Remove: " + dataSourcesToAdd.size() + "/" + dataSourcesToRemove.size()); writer.println("TableView: " + mapDataSourceToRow.size() + " datasources"); Iterator it = mapDataSourceToRow.keySet().iterator(); while (it.hasNext()) { Object key = it.next(); writer.println(" " + key + " -> " + mapDataSourceToRow.get(key)); } writer.println("# of SubViews: " + tabViews.size()); writer.indent(); try { for (Iterator iter = tabViews.iterator(); iter.hasNext();) { IView view = iter.next(); view.generateDiagnostics(writer); } } finally { writer.exdent(); } writer.println("Columns:"); writer.indent(); try { TableColumn[] tableColumnsSWT = table.getColumns(); for (int i = 0; i < tableColumnsSWT.length; i++) { final TableColumnCore tc = (TableColumnCore) tableColumnsSWT[i].getData("TableColumnCore"); if (tc != null) { writer.println(tc.getName() + ";w=" + tc.getWidth() + ";w-offset=" + tableColumnsSWT[i].getData("widthOffset")); } } } catch (Throwable t) { } finally { writer.exdent(); } } finally { dataSourceToRow_mon.exit(); } } public boolean getSkipFirstColumn() { return bSkipFirstColumn; } // see common.TableView public void setRowDefaultHeight(int iHeight) { if (ptIconSize == null) { ptIconSize = new Point(1, iHeight); } else { ptIconSize.y = iHeight; } if (!Constants.isOSX) { bSkipFirstColumn = true; } } public int getRowDefaultHeight() { if (ptIconSize == null) { return 0; } return ptIconSize.y; } // from common.TableView public void setRowDefaultIconSize(Point size) { ptIconSize = size; if (!Constants.isOSX) { bSkipFirstColumn = true; } } // TabViews Functions public void addTabView(IView view) { if (view == null || tabFolder == null) { return; } CTabItem item = new CTabItem(tabFolder, SWT.NULL); item.setData("IView", view); Messages.setLanguageText(item, view.getData()); view.initialize(tabFolder); item.setControl(view.getComposite()); tabViews.add(view); } private void fillRowGaps(boolean bForceDataRefresh) { _sortColumn(bForceDataRefresh, true, false); } private void sortColumn(boolean bForceDataRefresh) { _sortColumn(bForceDataRefresh, false, false); } private void _sortColumn(boolean bForceDataRefresh, boolean bFillGapsOnly, boolean bFollowSelected) { if (table == null || table.isDisposed()) { return; } try { sortColumn_mon.enter(); long lTimeStart; if (DEBUG_SORTER) { //System.out.println(">>> Sort.. "); lTimeStart = System.currentTimeMillis(); } int iNumMoves = 0; // This actually gets the focus, assuming the focus is selected int iFocusIndex = table.getSelectionIndex(); TableRowCore focusedRow = (iFocusIndex == -1) ? null : getRow(iFocusIndex); int iTopIndex = table.getTopIndex(); int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex); boolean allSelectedRowsVisible = true; int[] selectedRowIndices = table.getSelectionIndices(); TableRowCore[] selectedRows = new TableRowCore[selectedRowIndices.length]; for (int i = 0; i < selectedRowIndices.length; i++) { int index = selectedRowIndices[i]; selectedRows[i] = getRow(table.getItem(index)); if (allSelectedRowsVisible && (index < iTopIndex || index > iBottomIndex)) { allSelectedRowsVisible = false; } //System.out.println("Selected: " + selectedRowIndices[i] + ";" + selectedRows[i].getDataSource(true)); } try { sortedRows_mon.enter(); if (bForceDataRefresh && sortColumn != null) { int i = 0; String sColumnID = sortColumn.getName(); for (Iterator iter = sortedRows.iterator(); iter.hasNext();) { TableRowSWT row = iter.next(); TableCellSWT cell = row.getTableCellSWT(sColumnID); if (cell != null) { cell.refresh(true, i >= iTopIndex && i <= iBottomIndex); } i++; } } if (!bFillGapsOnly) { if (sortColumn != null && sortColumn.getLastSortValueChange() > lLastSortedOn) { lLastSortedOn = SystemTime.getCurrentTime(); Collections.sort(sortedRows, sortColumn); if (DEBUG_SORTER) { long lTimeDiff = (System.currentTimeMillis() - lTimeStart); if (lTimeDiff > 150) { System.out.println("--- Build & Sort took " + lTimeDiff + "ms"); } } } else { if (DEBUG_SORTER) { System.out.println("Skipping sort :)"); } } } int count = sortedRows.size(); if (iBottomIndex >= count) { iBottomIndex = count - 1; } if (bTableVirtual && allSelectedRowsVisible) { for (int i = 0; i < sortedRows.size(); i++) { TableRowSWT row = sortedRows.get(i); boolean visible = i >= iTopIndex && i <= iBottomIndex; if (visible) { if (row.setTableItem(i)) { iNumMoves++; } } else { if (row instanceof TableRowImpl) { ((TableRowImpl) row).setShown(visible, false); } } } // visibleRowsChanged() will setTableItem for the rest } else { for (int i = 0; i < sortedRows.size(); i++) { boolean visible = i >= iTopIndex && i <= iBottomIndex; TableRowSWT row = sortedRows.get(i); if (row.setTableItem(i, visible)) { iNumMoves++; } else { if (row instanceof TableRowImpl) { ((TableRowImpl) row).setShown(visible, false); } } } } } finally { sortedRows_mon.exit(); } // move cursor to selected row /** SWT/Windows Bug: * When we set selection, the first index is the focus row. * This works visually, however, if you press shift-up or shift-down, * it uses an older selection index. * * ie. User selects row #10 * Programmically change selection to Row #15 only * Shift-down * Rows 10 through 26 will be selected * * This is Eclipse bug #77106, and is marked WONTFIX */ if (focusedRow != null) { int pos = selectedRows.length == 1 ? 0 : 1; int numSame = 0; int[] newSelectedRowIndices = new int[selectedRows.length]; Arrays.sort(selectedRowIndices); for (int i = 0; i < selectedRows.length; i++) { if (selectedRows[i] == null) { continue; } int index = selectedRows[i].getIndex(); int iNewPos = (selectedRows[i] == focusedRow) ? 0 : pos++; //System.out.println("new selected, index=" + index + ";row=" + selectedRows[i].getDataSource(true)); newSelectedRowIndices[iNewPos] = index; if (Arrays.binarySearch(selectedRowIndices, index) >= 0) { numSame++; } } if (numSame < selectedRows.length) { if (bFollowSelected) { table.setSelection(newSelectedRowIndices); } else { table.deselectAll(); table.select(newSelectedRowIndices); } setSelectedRowIndexes(table.getSelectionIndices()); } } if (DEBUG_SORTER) { long lTimeDiff = (System.currentTimeMillis() - lTimeStart); if (lTimeDiff >= 500) { System.out.println("<<< Sort & Assign took " + lTimeDiff + "ms with " + iNumMoves + " rows (of " + sortedRows.size() + ") moved. " + focusedRow + ";" + Debug.getCompressedStackTrace()); } } } finally { sortColumn_mon.exit(); } } /** * @param newSelectedRowIndices * * @since 4.1.0.5 */ protected void setSelectedRowIndexes(int[] newSelectedRowIndices) { selectedRowIndexes = newSelectedRowIndices; listSelectedCoreDataSources = null; } protected void updateSelectedRowIndexes() { if (!table.isDisposed()) { setSelectedRowIndexes(table.getSelectionIndices()); } } public void sortColumnReverse(TableColumnCore sorter) { if (sortColumn == null) { return; } boolean bSameColumn = sortColumn.equals(sorter); if (!bSameColumn) { fixAlignment(sortColumn, false); sortColumn = sorter; fixAlignment(sorter, true); int iSortDirection = configMan.getIntParameter(CFG_SORTDIRECTION); if (iSortDirection == 0) { sortColumn.setSortAscending(true); } else if (iSortDirection == 1) { sortColumn.setSortAscending(false); } else { sortColumn.setSortAscending(!sortColumn.isSortAscending()); } TableColumnManager.getInstance().setDefaultSortColumnName(sTableID, sortColumn.getName()); } else { sortColumn.setSortAscending(!sortColumn.isSortAscending()); } changeColumnIndicator(); sortColumn(!bSameColumn); } private void changeColumnIndicator() { if (table == null || table.isDisposed()) { return; } try { // can't use TableColumnCore.getPosition, because user may have moved // columns around, messing up the SWT column indexes. // We can either use search columnsOrdered, or search table.getColumns() TableColumn[] tcs = table.getColumns(); for (int i = 0; i < tcs.length; i++) { String sName = (String) tcs[i].getData("Name"); if (sName != null && sortColumn != null && sName.equals(sortColumn.getName())) { table.setSortDirection(sortColumn.isSortAscending() ? SWT.UP : SWT.DOWN); table.setSortColumn(tcs[i]); return; } } table.setSortColumn(null); } catch (NoSuchMethodError e) { // sWT < 3.2 doesn't have column indicaters } } // @see com.aelitis.azureus.ui.common.table.TableView#isRowVisible(com.aelitis.azureus.ui.common.table.TableRowCore) public boolean isRowVisible(TableRowCore row) { if (!isVisible()) { return false; } int i = row.getIndex(); int iTopIndex = table.getTopIndex(); if (iTopIndex < 0) { return false; } int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex); return i >= iTopIndex && i <= iBottomIndex; } private void visibleRowsChanged() { if (!isVisible()) { lastTopIndex = 0; lastBottomIndex = -1; return; } //debug("VRC " + Debug.getCompressedStackTrace()); boolean bTableUpdate = false; int iTopIndex = table.getTopIndex(); int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex); if (lastTopIndex != iTopIndex) { if (Utils.isCocoa) { calculateClientArea(); } int tmpIndex = lastTopIndex; lastTopIndex = iTopIndex; if (iTopIndex < tmpIndex) { if (tmpIndex > iBottomIndex + 1 && iBottomIndex >= 0) { tmpIndex = iBottomIndex + 1; } //debug("Refresh top rows " + iTopIndex + " to " + (tmpIndex - 1)); try { sortedRows_mon.enter(); for (int i = iTopIndex; i < tmpIndex && i < sortedRows.size(); i++) { TableRowSWT row = (TableRowSWT) getRow(i); if (row != null) { row.setAlternatingBGColor(true); row.refresh(true, true); if (row instanceof TableRowImpl) { ((TableRowImpl) row).setShown(true, false); } if (Constants.isOSX) { bTableUpdate = true; } } } } finally { sortedRows_mon.exit(); } // A refresh might have triggered a row height resize, so // bottom index needs updating iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex); } else { //System.out.println("Made T.Invisible " + (tmpIndex) + " to " + (iTopIndex - 1)); for (int i = tmpIndex; i < iTopIndex; i++) { TableRowSWT row = (TableRowSWT) getRow(i); if (row instanceof TableRowImpl) { ((TableRowImpl) row).setShown(false, false); } } } } if (lastBottomIndex != iBottomIndex) { int tmpIndex = lastBottomIndex; lastBottomIndex = iBottomIndex; if (tmpIndex < iTopIndex - 1) { tmpIndex = iTopIndex - 1; } if (tmpIndex <= iBottomIndex) { //debug("Refresh bottom rows " + (tmpIndex + 1) + " to " + iBottomIndex); try { sortedRows_mon.enter(); for (int i = tmpIndex + 1; i <= iBottomIndex && i < sortedRows.size(); i++) { TableRowSWT row = (TableRowSWT) getRow(i); if (row != null) { row.setAlternatingBGColor(true); row.refresh(true, true); if (row instanceof TableRowImpl) { ((TableRowImpl) row).setShown(true, false); } if (Constants.isOSX) { bTableUpdate = true; } } } } finally { sortedRows_mon.exit(); } } else { //System.out.println("Made B.Invisible " + (tmpIndex) + " to " + (iBottomIndex + 1)); for (int i = tmpIndex; i <= iBottomIndex; i++) { TableRowSWT row = (TableRowSWT) getRow(i); if (row instanceof TableRowImpl) { ((TableRowImpl) row).setShown(false, false); } } } } if (bTableUpdate) { table.update(); } } public Image obfusticatedImage(final Image image, Point shellOffset) { if (table.getItemCount() == 0 || !isVisible()) { return image; } TableColumn[] tableColumnsSWT = table.getColumns(); for (int i = 0; i < tableColumnsSWT.length; i++) { final TableColumnCore tc = (TableColumnCore) tableColumnsSWT[i].getData("TableColumnCore"); if (tc != null && tc.isObfusticated()) { int iTopIndex = table.getTopIndex(); int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex); int size = iBottomIndex - iTopIndex + 1; if (size <= 0 || iTopIndex < 0) { continue; } for (int j = iTopIndex; j <= iBottomIndex; j++) { TableItem rowSWT = table.getItem(j); TableRowSWT row = (TableRowSWT) table.getItem(j).getData("TableRow"); if (row != null) { TableCellSWT cell = row.getTableCellSWT(tc.getName()); final Rectangle columnBounds = rowSWT.getBounds(i); if (columnBounds.y + columnBounds.height > clientArea.y + clientArea.height) { columnBounds.height -= (columnBounds.y + columnBounds.height) - (clientArea.y + clientArea.height); } if (columnBounds.x + columnBounds.width > clientArea.x + clientArea.width) { columnBounds.width -= (columnBounds.x + columnBounds.width) - (clientArea.x + clientArea.width); } final Point offset = table.toDisplay(columnBounds.x, columnBounds.y); columnBounds.x = offset.x - shellOffset.x; columnBounds.y = offset.y - shellOffset.y; String text = cell.getObfusticatedText(); if (text != null) { UIDebugGenerator.obfusticateArea(table.getDisplay(), image, columnBounds, text); } } } //UIDebugGenerator.offusticateArea(image, columnBounds); } } IView view = getActiveSubView(); if (view instanceof ObfusticateImage) { try { ((ObfusticateImage) view).obfusticatedImage(image, shellOffset); } catch (Exception e) { Debug.out("Obfusticating " + view, e); } } return image; } void debug(String s) { AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("table"); diag_logger.log(SystemTime.getCurrentTime() + ":" + sTableID + ": " + s); System.out.println(SystemTime.getCurrentTime() + ": " + sTableID + ": " + s); } // from common.TableView public boolean isEnableTabViews() { return bEnableTabViews; } // from common.TableView public void setEnableTabViews(boolean enableTabViews) { bEnableTabViews = enableTabViews; } // from common.TableView public IView[] getCoreTabViews() { return coreTabViews; } // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#setCoreTabViews(org.gudy.azureus2.ui.swt.views.IView[]) public void setCoreTabViews(IView[] coreTabViews) { this.coreTabViews = coreTabViews; } public void addMenuFillListener(TableViewSWTMenuFillListener l) { listenersMenuFill.add(l); } // @see com.aelitis.azureus.ui.common.table.TableView#isDisposed() public boolean isDisposed() { return mainComposite == null || mainComposite.isDisposed() || table == null || table.isDisposed(); } // @see com.aelitis.azureus.ui.common.table.TableView#size(boolean) public int size(boolean bIncludeQueue) { int size = sortedRows.size(); if (bIncludeQueue) { if (dataSourcesToAdd != null) { size += dataSourcesToAdd.size(); } if (dataSourcesToRemove != null) { size += dataSourcesToRemove.size(); } } return size; } // @see com.aelitis.azureus.ui.common.table.TableView#getPropertiesPrefix() public String getPropertiesPrefix() { return sPropertiesPrefix; } // @see com.aelitis.azureus.ui.common.table.TableView#setFocus() public void setFocus() { if (table != null && !table.isDisposed()) { table.setFocus(); } } // @see org.gudy.azureus2.ui.swt.views.TableViewSWT#addKeyListener(org.eclipse.swt.events.KeyListener) public void addKeyListener(KeyListener listener) { if (listenersKey.contains(listener)) { return; } listenersKey.add(listener); } // @see com.aelitis.azureus.ui.common.table.TableView#removeKeyListener(org.eclipse.swt.events.KeyListener) public void removeKeyListener(KeyListener listener) { listenersKey.remove(listener); } // @see org.gudy.azureus2.ui.swt.views.TableViewSWT#getSortColumn() public TableColumnCore getSortColumn() { return sortColumn; } // @see com.aelitis.azureus.ui.common.table.TableView#selectAll() public void selectAll() { if (table != null && !table.isDisposed()) { ensureAllRowsHaveIndex(); table.selectAll(); updateSelectedRowIndexes(); triggerSelectionListeners(getSelectedRows()); triggerTabViewsDataSourceChanged(); } } /** * * * @since 3.0.0.7 */ private void ensureAllRowsHaveIndex() { for (int i = 0; i < sortedRows.size(); i++) { TableRowSWT row = sortedRows.get(i); row.setTableItem(i); } } // @see com.aelitis.azureus.ui.common.table.TableView#setSelectedRows(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void setSelectedRows(TableRowCore[] rows) { table.deselectAll(); for (int i = 0; i < rows.length; i++) { TableRowCore row = rows[i]; if (row.getIndex() == -1) { int j = sortedRows.indexOf(row); if (j == -1) { System.err.println("BOO"); } else { row.setTableItem(j); } } row.setSelected(true); } updateSelectedRowIndexes(); } // @see com.aelitis.azureus.ui.common.table.TableView#isTableFocus() public boolean isTableFocus() { return table.isFocusControl(); } // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#createDragSource(int) public DragSource createDragSource(int style) { final DragSource dragSource = new DragSource(table, style); table.addDisposeListener(new DisposeListener() { // @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent) public void widgetDisposed(DisposeEvent e) { if (!dragSource.isDisposed()) { dragSource.dispose(); } } }); return dragSource; } // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#createDropTarget(int) public DropTarget createDropTarget(int style) { final DropTarget dropTarget = new DropTarget(table, style); table.addDisposeListener(new DisposeListener() { // @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent) public void widgetDisposed(DisposeEvent e) { if (!dropTarget.isDisposed()) { dropTarget.dispose(); } } }); return dropTarget; } // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#indexOf(org.eclipse.swt.widgets.Widget) public TableRowCore getRow(DropTargetEvent event) { if (event.item instanceof TableItem) { TableItem ti = (TableItem) event.item; return (TableRowCore) ti.getData("TableRow"); } return null; } // @see com.aelitis.azureus.ui.common.table.TableView#dataSourceExists(java.lang.Object) public boolean dataSourceExists(DATASOURCETYPE dataSource) { return mapDataSourceToRow.containsKey(dataSource) || dataSourcesToAdd.contains(dataSource); } // @see com.aelitis.azureus.ui.common.table.TableView#getVisibleColumns() public TableColumnCore[] getVisibleColumns() { return tableColumns; } /** * @return */ protected TableViewSWTPanelCreator getMainPanelCreator() { return mainPanelCreator; } // @see org.gudy.azureus2.ui.swt.views.TableViewSWT#setMainPanelCreator(org.gudy.azureus2.ui.swt.views.TableViewMainPanelCreator) public void setMainPanelCreator(TableViewSWTPanelCreator mainPanelCreator) { this.mainPanelCreator = mainPanelCreator; } public TableCellCore getTableCellWithCursor() { Point pt = table.getDisplay().getCursorLocation(); pt = table.toControl(pt); return getTableCell(pt.x, pt.y); } // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getTableRowWithCursor() public TableRowCore getTableRowWithCursor() { Point pt = table.getDisplay().getCursorLocation(); pt = table.toControl(pt); return getTableRow(pt.x, pt.y); } // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getTableCellMouseOffset() public Point getTableCellMouseOffset(TableCellSWT tableCell) { if (tableCell == null) { return null; } Point pt = table.getDisplay().getCursorLocation(); pt = table.toControl(pt); Rectangle bounds = tableCell.getBounds(); int x = pt.x - bounds.x; if (x < 0 || x > bounds.width) { return null; } int y = pt.y - bounds.y; if (y < 0 || y > bounds.height) { return null; } return new Point(x, y); } // @see com.aelitis.azureus.ui.common.table.TableView#getDataSourceType() public Class getDataSourceType() { return classPluginDataSourceType; } public void addRefreshListener(TableRowRefreshListener listener) { try { listeners_mon.enter(); if (refreshListeners == null) { refreshListeners = new ArrayList(1); } refreshListeners.add(listener); } finally { listeners_mon.exit(); } } public void removeRefreshListener(TableRowRefreshListener listener) { try { listeners_mon.enter(); if (refreshListeners == null) { return; } refreshListeners.remove(listener); } finally { listeners_mon.exit(); } } public void invokeRefreshListeners(TableRowCore row) { Object[] listeners; try { listeners_mon.enter(); if (refreshListeners == null) { return; } listeners = refreshListeners.toArray(); } finally { listeners_mon.exit(); } for (int i = 0; i < listeners.length; i++) { try { TableRowRefreshListener l = (TableRowRefreshListener) listeners[i]; l.rowRefresh(row); } catch (Throwable e) { Debug.printStackTrace(e); } } } public boolean isVisible() { boolean wasVisible = isVisible; isVisible = table != null && !table.isDisposed() && table.isVisible(); if (isVisible != wasVisible) { if (isVisible) { runForVisibleRows(new TableGroupRowRunner() { public void run(TableRowCore row) { row.invalidate(); } }); loopFactor = 0; IView view = getActiveSubView(); if (view instanceof IViewExtension) { ((IViewExtension)view).viewActivated(); } } else { IView view = getActiveSubView(); if (view instanceof IViewExtension) { ((IViewExtension)view).viewDeactivated(); } } } return isVisible; } public void showRow(TableRowCore row) { int index = row.getIndex(); if (index >= 0 && index < table.getItemCount()) { table.showItem(table.getItem(index)); } } public boolean isMenuEnabled() { return menuEnabled; } public void setMenuEnabled(boolean menuEnabled) { this.menuEnabled = menuEnabled; } private void openFilterDialog() { if (filter == null) { return; } SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(); entryWindow.initTexts("MyTorrentsView.dialog.setFilter.title", null, "MyTorrentsView.dialog.setFilter.text", new String[] { MessageText.getString(getTableID() + "View" + ".header") }); entryWindow.setPreenteredText(filter.text, false); entryWindow.prompt(); if (!entryWindow.hasSubmittedInput()) { return; } String message = entryWindow.getSubmittedInput(); if (message == null) { message = ""; } setFilterText(message); } private void handleSearchKeyPress(KeyEvent e) { if (filter == null || e.widget == filter.widget) { return; } String newText = null; // normal character: jump to next item with a name beginning with this character if (ASYOUTYPE_MODE == ASYOUTYPE_MODE_FIND) { if (System.currentTimeMillis() - filter.lastFilterTime > 3000) newText = ""; } if (e.keyCode == SWT.BS) { if (e.stateMask == SWT.CONTROL) { newText = ""; } else if (filter.nextText.length() > 0) { newText = filter.nextText.substring(0, filter.nextText.length() - 1); } } else if ((e.stateMask & ~SWT.SHIFT) == 0 && e.character > 0) { newText = filter.nextText + String.valueOf(e.character); } if (newText == null) { return; } if (ASYOUTYPE_MODE == ASYOUTYPE_MODE_FILTER) { if (filter != null && filter.widget != null && !filter.widget.isDisposed()) { filter.widget.setFocus(); } setFilterText(newText); } else { TableCellCore[] cells = getColumnCells("name"); //System.out.println(sLastSearch); Arrays.sort(cells, TableCellImpl.TEXT_COMPARATOR); int index = Arrays.binarySearch(cells, filter.text, TableCellImpl.TEXT_COMPARATOR); if (index < 0) { int iEarliest = -1; String s = filter.regex ? filter.text : "\\Q" + filter.text + "\\E"; Pattern pattern = Pattern.compile(s, Pattern.CASE_INSENSITIVE); for (int i = 0; i < cells.length; i++) { Matcher m = pattern.matcher(cells[i].getText()); if (m.find() && (m.start() < iEarliest || iEarliest == -1)) { iEarliest = m.start(); index = i; } } if (index < 0) // Insertion Point (best guess) index = -1 * index - 1; } if (index >= 0) { if (index >= cells.length) index = cells.length - 1; TableRowCore row = cells[index].getTableRowCore(); int iTableIndex = row.getIndex(); if (iTableIndex >= 0) { setSelectedRows(new TableRowCore[] { row }); } } filter.lastFilterTime = System.currentTimeMillis(); } e.doit = false; } public void setFilterText(String s) { if (filter == null) { return; } filter.nextText = s; if (filter != null && filter.widget != null && !filter.widget.isDisposed()) { if (!filter.nextText.equals(filter.widget.getText())) { filter.widget.setText(filter.nextText); filter.widget.setSelection(filter.nextText.length()); } if (filter.regex) { try { Pattern.compile(filter.nextText, Pattern.CASE_INSENSITIVE); filter.widget.setBackground(COLOR_FILTER_REGEX); Messages.setLanguageTooltip(filter.widget, "MyTorrentsView.filter.tooltip"); } catch (Exception e) { filter.widget.setBackground(Colors.colorErrorBG); filter.widget.setToolTipText(e.getMessage()); } } else { filter.widget.setBackground(null); Messages.setLanguageTooltip(filter.widget, "MyTorrentsView.filter.tooltip"); } } if (filter.eventUpdate != null) { filter.eventUpdate.cancel(); } filter.eventUpdate = SimpleTimer.addEvent("SearchUpdate", SystemTime.getOffsetTime(ASYOUTYPE_UPDATEDELAY), new TimerEventPerformer() { public void perform(TimerEvent event) { if (filter.eventUpdate.isCancelled()) { filter.eventUpdate = null; return; } filter.eventUpdate = null; if (filter.nextText != null && !filter.nextText.equals(filter.text)) { filter.text = filter.nextText; filter.checker.filterSet(filter.text); refilter(); } } }); } public String getFilterText() { return filter == null ? "" : filter.text; } @SuppressWarnings("unchecked") public void refilter() { if (filter == null) { return; } if (filter.eventUpdate != null) { filter.eventUpdate.cancel(); } filter.eventUpdate = null; listUnfilteredDatasources_mon.enter(); try { DATASOURCETYPE[] unfilteredArray = (DATASOURCETYPE[]) listUnfilteredDataSources.toArray(); boolean all = filter.text.length() == 0; Set existing = new HashSet( getDataSources()); List listRemoves = new ArrayList(); List listAdds = new ArrayList(); for (int i = 0; i < unfilteredArray.length; i++) { boolean bHave = existing.contains(unfilteredArray[i]); boolean isOurs = all ? true : filter.checker.filterCheck( unfilteredArray[i], filter.text, filter.regex); if (!isOurs) { if (bHave) { listRemoves.add(unfilteredArray[i]); } } else { if (!bHave) { listAdds.add(unfilteredArray[i]); } } } removeDataSources((DATASOURCETYPE[]) listRemoves.toArray()); addDataSources((DATASOURCETYPE[]) listAdds.toArray(), true); // add back the ones removeDataSources removed listUnfilteredDataSources.addAll(listRemoves); } finally { listUnfilteredDatasources_mon.exit(); processDataSourceQueue(); } } public void enableFilterCheck(Text txtFilter, TableViewFilterCheck filterCheck) { if (filter != null) { if (filter.widget != null && !filter.widget.isDisposed()) { filter.widget.removeKeyListener(TableViewSWTImpl.this); filter.widget.removeModifyListener(filter.widgetModifyListener); } } else{ filter = new filter(); } filter.widget = txtFilter; if (txtFilter != null) { txtFilter.addKeyListener(this); filter.widgetModifyListener = new ModifyListener() { public void modifyText(ModifyEvent e) { setFilterText(((Text) e.widget).getText()); } }; txtFilter.addModifyListener(filter.widgetModifyListener); if (txtFilter.getText().length() == 0) { txtFilter.setText(filter.text); } else { filter.text = filter.nextText = txtFilter.getText(); } } else { filter.text = filter.nextText = ""; } filter.checker = filterCheck; filter.checker.filterSet(filter.text); refilter(); } public boolean enableSizeSlider(Composite composite, int min, int max) { try { if (slider != null && !slider.isDisposed()) { slider.dispose(); } final Method method = Table.class.getDeclaredMethod("setItemHeight", new Class[] { int.class }); method.setAccessible(true); composite.setLayout(new FormLayout()); slider = new Scale(composite, SWT.HORIZONTAL); slider.setMinimum(min); slider.setMaximum(max); slider.setSelection(getRowDefaultHeight()); try { method.invoke(table, new Object[] { slider.getSelection() } ); } catch (Throwable e1) { } slider.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { setRowDefaultHeight(slider.getSelection()); try { method.invoke(table, new Object[] { slider.getSelection() } ); } catch (Throwable e1) { e1.printStackTrace(); } tableInvalidate(); } public void widgetDefaultSelected(SelectionEvent e) { } }); slider.setLayoutData(Utils.getFilledFormData()); composite.layout(); } catch (Throwable t) { return false; } return true; } public void disableSizeSlider() { Utils.disposeSWTObjects(new Object[] { slider }); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/impl/FakeTableCell.java0000644000175000017500000010574111223221570026060 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.table.impl; import java.util.ArrayList; import java.util.Iterator; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.core3.tracker.host.TRHostTorrent; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.BufferedTableItem; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.TableRowSWT; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnSWTUtils; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.TableRowCore; import com.aelitis.azureus.ui.swt.utils.ColorCache; import org.gudy.azureus2.plugins.download.DownloadException; import org.gudy.azureus2.plugins.ui.Graphic; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import org.gudy.azureus2.pluginsimpl.local.disk.DiskManagerFileInfoImpl; import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl; import org.gudy.azureus2.pluginsimpl.local.peers.PeerManagerImpl; import org.gudy.azureus2.pluginsimpl.local.tracker.TrackerTorrentImpl; /** * @author TuxPaper * @created Aug 29, 2007 * */ public class FakeTableCell implements TableCellSWT, PaintListener, MouseListener, MouseMoveListener, MouseTrackListener { private AEMonitor this_mon = new AEMonitor("FakeTableCell"); private ArrayList refreshListeners; private ArrayList disposeListeners; private ArrayList tooltipListeners; private ArrayList cellMouseListeners; private ArrayList cellMouseMoveListeners; private ArrayList cellVisibilityListeners; private Image image; private Rectangle imageBounds; private int marginHeight; private int orientation; private int marginWidth; private Comparable sortValue; private Object coreDataSource; private Composite composite; private final TableColumnCore tableColumn; private Graphic graphic; private String text; private Object pluginDataSource; private Object tooltip; private Object default_tooltip; private Rectangle cellArea; private boolean hadMore; private ArrayList cellSWTPaintListeners; private boolean valid; private TableRow fakeRow = null; /** * @param columnRateUpDown */ public FakeTableCell(TableColumn column) { valid = false; this.tableColumn = (TableColumnCore) column; setOrientationViaColumn(); } public FakeTableCell(TableColumnCore column) { valid = false; this.tableColumn = column; setOrientationViaColumn(); } public void addRefreshListener(TableCellRefreshListener listener) { try { this_mon.enter(); if (refreshListeners == null) refreshListeners = new ArrayList(1); refreshListeners.add(listener); } finally { this_mon.exit(); } } public void removeRefreshListener(TableCellRefreshListener listener) { try { this_mon.enter(); if (refreshListeners == null) return; refreshListeners.remove(listener); } finally { this_mon.exit(); } } public void addDisposeListener(TableCellDisposeListener listener) { try { this_mon.enter(); if (disposeListeners == null) { disposeListeners = new ArrayList(1); } disposeListeners.add(listener); } finally { this_mon.exit(); } } public void removeDisposeListener(TableCellDisposeListener listener) { try { this_mon.enter(); if (disposeListeners == null) return; disposeListeners.remove(listener); } finally { this_mon.exit(); } } public void addToolTipListener(TableCellToolTipListener listener) { try { this_mon.enter(); if (tooltipListeners == null) { tooltipListeners = new ArrayList(1); } tooltipListeners.add(listener); } finally { this_mon.exit(); } } public void removeToolTipListener(TableCellToolTipListener listener) { try { this_mon.enter(); if (tooltipListeners == null) return; tooltipListeners.remove(listener); } finally { this_mon.exit(); } } public void addMouseListener(TableCellMouseListener listener) { try { this_mon.enter(); if (cellMouseListeners == null) cellMouseListeners = new ArrayList(1); cellMouseListeners.add(listener); } finally { this_mon.exit(); } } public void removeMouseListener(TableCellMouseListener listener) { try { this_mon.enter(); if (cellMouseListeners == null) return; cellMouseListeners.remove(listener); } finally { this_mon.exit(); } } public void addMouseMoveListener(TableCellMouseMoveListener listener) { try { this_mon.enter(); if (cellMouseMoveListeners == null) cellMouseMoveListeners = new ArrayList(1); cellMouseMoveListeners.add(listener); } finally { this_mon.exit(); } } public void removeMouseMoveListener(TableCellMouseMoveListener listener) { try { this_mon.enter(); if (cellMouseMoveListeners == null) return; cellMouseMoveListeners.remove(listener); } finally { this_mon.exit(); } } public void addVisibilityListener(TableCellVisibilityListener listener) { try { this_mon.enter(); if (cellVisibilityListeners == null) cellVisibilityListeners = new ArrayList(1); cellVisibilityListeners.add(listener); } finally { this_mon.exit(); } } public void removeVisibilityListener(TableCellVisibilityListener listener) { try { this_mon.enter(); if (cellVisibilityListeners == null) return; cellVisibilityListeners.remove(listener); } finally { this_mon.exit(); } } /** * @param listenerObject * * @since 4.0.0.1 */ private void addSWTPaintListener(TableCellSWTPaintListener listener) { try { this_mon.enter(); if (cellSWTPaintListeners == null) cellSWTPaintListeners = new ArrayList(1); cellSWTPaintListeners.add(listener); } finally { this_mon.exit(); } } public void invokeSWTPaintListeners(GC gc) { if (getBounds().isEmpty()) { return; } if (tableColumn != null) { Object[] swtPaintListeners = tableColumn.getCellOtherListeners("SWTPaint"); if (swtPaintListeners != null) { for (int i = 0; i < swtPaintListeners.length; i++) { try { TableCellSWTPaintListener l = (TableCellSWTPaintListener) swtPaintListeners[i]; l.cellPaint(gc, this); } catch (Throwable e) { Debug.printStackTrace(e); } } } } if (cellSWTPaintListeners == null) { return; } for (int i = 0; i < cellSWTPaintListeners.size(); i++) { try { TableCellSWTPaintListener l = (TableCellSWTPaintListener) (cellSWTPaintListeners.get(i)); l.cellPaint(gc, this); } catch (Throwable e) { Debug.printStackTrace(e); } } } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#addListeners(java.lang.Object) public void addListeners(Object listenerObject) { if (listenerObject instanceof TableCellDisposeListener) addDisposeListener((TableCellDisposeListener) listenerObject); if (listenerObject instanceof TableCellRefreshListener) addRefreshListener((TableCellRefreshListener) listenerObject); if (listenerObject instanceof TableCellToolTipListener) addToolTipListener((TableCellToolTipListener) listenerObject); if (listenerObject instanceof TableCellMouseMoveListener) { addMouseMoveListener((TableCellMouseMoveListener) listenerObject); } if (listenerObject instanceof TableCellMouseListener) { addMouseListener((TableCellMouseListener) listenerObject); } if (listenerObject instanceof TableCellVisibilityListener) addVisibilityListener((TableCellVisibilityListener) listenerObject); if (listenerObject instanceof TableCellSWTPaintListener) { addSWTPaintListener((TableCellSWTPaintListener) listenerObject); } } public void invokeMouseListeners(TableCellMouseEvent event) { if (event.cell != null && event.row == null) { event.row = event.cell.getTableRow(); } try { tableColumn.invokeCellMouseListeners(event); } catch (Throwable e) { Debug.printStackTrace(e); } ArrayList listeners = event.eventType == TableCellMouseEvent.EVENT_MOUSEMOVE ? cellMouseMoveListeners : cellMouseListeners; if (listeners == null) { return; } for (int i = 0; i < listeners.size(); i++) { try { TableCellMouseListener l = (TableCellMouseListener) (listeners.get(i)); l.cellMouseTrigger(event); } catch (Throwable e) { Debug.printStackTrace(e); } } } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getDataSource() public Object getDataSource() { boolean bCoreObject = ((TableColumnCore) tableColumn).getUseCoreDataSource(); if (bCoreObject) { return coreDataSource; } if (pluginDataSource != null) { return pluginDataSource; } if (coreDataSource instanceof DownloadManager) { DownloadManager dm = (DownloadManager) coreDataSource; if (dm != null) { try { pluginDataSource = DownloadManagerImpl.getDownloadStatic(dm); } catch (DownloadException e) { /* Ignore */ } } } if (coreDataSource instanceof PEPeer) { PEPeer peer = (PEPeer) coreDataSource; if (peer != null) { pluginDataSource = PeerManagerImpl.getPeerForPEPeer(peer); } } if (coreDataSource instanceof PEPiece) { // XXX There is no Piece object for plugins yet PEPiece piece = (PEPiece) coreDataSource; if (piece != null) { pluginDataSource = null; } } if (coreDataSource instanceof DiskManagerFileInfo) { DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) coreDataSource; if (fileInfo != null) { try { pluginDataSource = new DiskManagerFileInfoImpl( DownloadManagerImpl.getDownloadStatic(fileInfo.getDownloadManager()), fileInfo); } catch (DownloadException e) { /* Ignore */ } } } if (coreDataSource instanceof TRHostTorrent) { TRHostTorrent item = (TRHostTorrent) coreDataSource; if (item != null) { pluginDataSource = new TrackerTorrentImpl(item); } } return pluginDataSource; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getForeground() public int[] getForeground() { if (composite == null || composite.isDisposed()) { return null; } Color fg = composite.getForeground(); return new int[] { fg.getRed(), fg.getGreen(), fg.getBlue() }; } public int[] getBackground() { // until we can make sure composite.getBackground is being used // (background image might superceed), return 0 if (true) { return new int[] { 0, 0, 0 }; } if (composite == null || composite.isDisposed()) { return null; } Color bg = composite.getBackground(); return new int[] { bg.getRed(), bg.getGreen(), bg.getBlue() }; } public Graphic getBackgroundGraphic() { // TODO handle cellArea if (composite == null || composite.isDisposed()) { return null; } try { Rectangle bounds = composite.getBounds(); if (bounds.isEmpty()) { return null; } Image imgCap = new Image(composite.getDisplay(), bounds.width, bounds.height); // will walk up tree until it gets an image Control bgControl = Utils.findBackgroundImageControl(composite); Image imgBG = composite.getBackgroundImage(); GC gc = new GC(imgCap); try { if (imgBG == null) { // || imgBG has alpha.. gc.setBackground(composite.getBackground()); gc.fillRectangle(0, 0, bounds.width, bounds.height); } if (imgBG != null) { Point controlPos = new Point(0, 0); if (bgControl instanceof Composite) { Rectangle compArea = ((Composite) bgControl).getClientArea(); controlPos.x = compArea.x; controlPos.y = compArea.y; } Point absControlLoc = bgControl.toDisplay(controlPos.x, controlPos.y); Rectangle shellClientArea = composite.getShell().getClientArea(); Point absShellLoc = composite.getParent().toDisplay( shellClientArea.x, shellClientArea.y); Point ofs = new Point(absControlLoc.x - absShellLoc.x, absControlLoc.y - absShellLoc.y); Rectangle imgBGBounds = imgBG.getBounds(); ofs.x = (ofs.x % imgBGBounds.width); ofs.y = (ofs.y % imgBGBounds.height); gc.drawImage(imgBG, ofs.x, ofs.y); } } finally { gc.dispose(); } return new UISWTGraphicImpl(imgCap); } catch (Exception e) { Debug.out(e); } return null; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getGraphic() public Graphic getGraphic() { return graphic; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getHeight() public int getHeight() { if (composite != null && !composite.isDisposed()) { return composite.getSize().y; } return 0; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getMaxLines() public int getMaxLines() { return -1; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getSortValue() public Comparable getSortValue() { return sortValue; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getTableColumn() public TableColumn getTableColumn() { return tableColumn; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getTableID() public String getTableID() { return tableColumn == null ? null : tableColumn.getTableID(); } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getTableRow() public TableRow getTableRow() { if (fakeRow == null) { fakeRow = new TableRow() { public void setForegroundToErrorColor() { } public void setForeground(int[] rgb) { } public void setForeground(int red, int green, int blue) { } public void removeMouseListener(TableRowMouseListener listener) { } public boolean isValid() { return FakeTableCell.this.isValid(); } public boolean isSelected() { return false; } public String getTableID() { return FakeTableCell.this.getTableID(); } public TableCell getTableCell(String columnName) { return null; } public Object getDataSource() { return FakeTableCell.this.getDataSource(); } public void addMouseListener(TableRowMouseListener listener) { } }; } return fakeRow; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getText() public String getText() { return text; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getToolTip() public Object getToolTip() { if (tooltip == null && hadMore) { return text; } return tooltip; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getWidth() public int getWidth() { if (!isDisposed()) { return composite.getSize().x; } return 0; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#invalidate() public void invalidate() { valid = false; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#isDisposed() public boolean isDisposed() { return composite == null || composite.isDisposed(); } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#isShown() public boolean isShown() { return true; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#isValid() public boolean isValid() { return valid; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setFillCell(boolean) public void setFillCell(boolean fillCell) { // TODO Auto-generated method stub } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setForeground(int, int, int) public boolean setForeground(int red, int green, int blue) { if (isDisposed()) { return false; } if (red < 0 || green < 0 || blue < 0) { composite.setForeground(null); } else { composite.setForeground(ColorCache.getColor(composite.getDisplay(), red, green, blue)); } return true; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setForeground(int[]) public boolean setForeground(int[] rgb) { if (rgb == null || rgb.length < 3) { return setForeground(-1, -1, -1); } return setForeground(rgb[0], rgb[1], rgb[2]); } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setForegroundToErrorColor() public boolean setForegroundToErrorColor() { if (isDisposed()) { return false; } composite.setForeground(Colors.colorError); return true; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setGraphic(org.gudy.azureus2.plugins.ui.Graphic) public boolean setGraphic(Graphic img) { Image imgSWT = null; if (img instanceof UISWTGraphic) { imgSWT = ((UISWTGraphic) img).getImage(); } if (imgSWT != null && imgSWT.isDisposed()) { return false; } if (image == imgSWT) { return false; } //System.out.println("setGraphic " + image); image = imgSWT; if (image != null) { imageBounds = image.getBounds(); } if (composite != null && !composite.isDisposed()) { redraw(); } graphic = img; return true; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setMarginHeight(int) public void setMarginHeight(int height) { // TODO Auto-generated method stub } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setMarginWidth(int) public void setMarginWidth(int width) { // TODO Auto-generated method stub } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setSortValue(java.lang.Comparable) public boolean setSortValue(Comparable valueToSort) { // TODO Auto-generated method stub return false; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setSortValue(float) public boolean setSortValue(float valueToSort) { // TODO Auto-generated method stub return false; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setText(java.lang.String) public boolean setText(String text) { if (text != null && text.equals(this.text)) { return false; } this.text = text; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (!isDisposed()) { composite.redraw(); } } }); return true; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setToolTip(java.lang.Object) public void setToolTip(Object tooltip) { this.tooltip = tooltip; updateTooltip(); } public void setDefaultToolTip( Object o ) { default_tooltip = o; } public Object getDefaultToolTip() { return( default_tooltip ); } private void updateTooltip() { if (!isDisposed()) { Object target = tooltip==null?default_tooltip:tooltip; composite.setToolTipText(target == null ? null : target.toString()); } } private boolean _setSortValue(Comparable valueToSort) { if (sortValue == valueToSort) return false; if ((valueToSort instanceof String) && (sortValue instanceof String) && sortValue.equals(valueToSort)) { return false; } if ((valueToSort instanceof Number) && (sortValue instanceof Number) && sortValue.equals(valueToSort)) { return false; } sortValue = valueToSort; return true; } public boolean setSortValue(long valueToSort) { if ((sortValue instanceof Long) && ((Long) sortValue).longValue() == valueToSort) return false; return _setSortValue(new Long(valueToSort)); } public void doPaint(GC gc, Rectangle bounds) { if (isDisposed()) { return; } // TODO: Cleanup and stop calling me so often! //gc.setBackground(getBackground()); //if (DEBUG_COLORCELL) { // gc.setBackground(Display.getDefault().getSystemColor( // (int) (Math.random() * 16))); //} if (bounds == null) { return; } //gc.fillRectangle(bounds); if (image != null && !image.isDisposed()) { Point size = new Point(bounds.width, bounds.height); int x; int y = marginHeight; y += (size.y - imageBounds.height) / 2; if (orientation == SWT.CENTER) { x = marginWidth; x += (size.x - (marginWidth * 2) - imageBounds.width) / 2; } else if (orientation == SWT.RIGHT) { x = bounds.width - marginWidth - imageBounds.width; } else { x = marginWidth; } int width = Math.min(bounds.width - x - marginWidth, imageBounds.width); int height = Math.min(bounds.height - y - marginHeight, imageBounds.height); if (width >= 0 && height >= 0) { gc.drawImage(image, 0, 0, width, height, bounds.x + x, bounds.y + y, width, height); } } if (text != null && text.length() > 0) { GCStringPrinter sp = new GCStringPrinter(gc, text, bounds, true, false, orientation | SWT.WRAP); sp.printString(); hadMore = sp.isCutoff(); } invokeSWTPaintListeners(gc); } public boolean refresh() { //System.out.println("refresh"); Utils.execSWTThread(new AERunnable() { public void runSupport() { boolean wasValid = valid; try { tableColumn.invokeCellRefreshListeners(FakeTableCell.this, false); } catch (Throwable e) { } if (refreshListeners != null) { for (int i = 0; i < refreshListeners.size(); i++) { ((TableCellRefreshListener) (refreshListeners.get(i))).refresh(FakeTableCell.this); } } if (!wasValid) { valid = true; } } }); return true; } public void setDataSource(Object datasource) { coreDataSource = datasource; if (datasource != null && !isDisposed()) { invokeVisibilityListeners(TableCellVisibilityListener.VISIBILITY_SHOWN, true); } } public void setControl(final Composite composite) { setControl(composite, null); } public void setControl(final Composite composite, Rectangle cellArea) { if (composite == null) { dispose(); this.composite = null; return; } this.composite = composite; this.cellArea = cellArea; composite.addPaintListener(this); composite.addMouseListener(this); composite.addMouseMoveListener(this); composite.addMouseTrackListener(this); setForeground(-1, -1, -1); setText(null); setToolTip(null); composite.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { dispose(); } }); if (coreDataSource != null && !isDisposed()) { invokeVisibilityListeners(TableCellVisibilityListener.VISIBILITY_SHOWN, true); } } public void paintControl(PaintEvent e) { doPaint(e.gc, cellArea == null ? composite.getClientArea() : cellArea); } public void mouseUp(MouseEvent e) { invokeMouseListeners(buildMouseEvent(e, TableCellMouseEvent.EVENT_MOUSEUP)); } public void mouseDown(MouseEvent e) { try{ if ( composite == null || composite.getMenu() != null || ( cellMouseListeners != null && cellMouseListeners.size() > 0 ) || text == null || text.length() == 0 ){ return; } if (!(e.button == 3 || (e.button == 1 && e.stateMask == SWT.CONTROL))){ return; } Menu menu = new Menu(composite.getShell(),SWT.POP_UP); MenuItem item = new MenuItem( menu,SWT.NONE ); item.setText( MessageText.getString( "ConfigView.copy.to.clipboard.tooltip")); item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent arg0) { if ( !composite.isDisposed() && text != null && text.length() > 0 ){ new Clipboard(composite.getDisplay()).setContents(new Object[] {text}, new Transfer[] {TextTransfer.getInstance()}); } } }); composite.setMenu( menu ); menu.addMenuListener( new MenuAdapter() { public void menuHidden( MenuEvent arg0 ) { if ( !composite.isDisposed()){ composite.setMenu( null ); } } }); menu.setVisible( true ); }finally{ invokeMouseListeners(buildMouseEvent(e, TableCellMouseEvent.EVENT_MOUSEDOWN)); } } public void mouseDoubleClick(MouseEvent e) { invokeMouseListeners(buildMouseEvent(e, TableCellMouseEvent.EVENT_MOUSEDOUBLECLICK)); } public void mouseMove(MouseEvent e) { invokeMouseListeners(buildMouseEvent(e, TableCellMouseEvent.EVENT_MOUSEMOVE)); } public void mouseHover(MouseEvent e) { invokeToolTipListeners(TOOLTIPLISTENER_HOVER); } public void mouseExit(MouseEvent e) { invokeMouseListeners(buildMouseEvent(e, TableCellMouseEvent.EVENT_MOUSEEXIT)); } public void mouseEnter(MouseEvent e) { invokeMouseListeners(buildMouseEvent(e, TableCellMouseEvent.EVENT_MOUSEENTER)); } /** * @param e * @return * * @since 3.0.2.1 */ protected TableCellMouseEvent buildMouseEvent(MouseEvent e, int eventType) { if (isDisposed()) { return null; } TableCellMouseEvent event = new TableCellMouseEvent(); event.cell = this; event.button = e.button; event.keyboardState = e.stateMask; event.eventType = eventType; Rectangle r = composite.getBounds(); // int align = tableColumn.getAlignment(); // if (align == TableColumn.ALIGN_CENTER) { // r.x = marginWidth; // r.x += (r.width - (marginWidth * 2) - imageBounds.width) / 2; // } if (cellArea != null) { r = new Rectangle(r.x + cellArea.x, r.y + cellArea.y, cellArea.width, cellArea.height); } event.x = e.x - r.x; event.y = e.y - r.y; return event; } private void setOrientationViaColumn() { orientation = TableColumnSWTUtils.convertColumnAlignmentToSWT(tableColumn.getAlignment()); } // @see com.aelitis.azureus.ui.common.table.TableCellCore#dispose() public void dispose() { if (composite != null && !composite.isDisposed()) { composite.removePaintListener(this); composite.removeMouseListener(this); composite.removeMouseMoveListener(this); composite.removeMouseTrackListener(this); } if (disposeListeners != null) { for (Iterator iter = disposeListeners.iterator(); iter.hasNext();) { TableCellDisposeListener listener = (TableCellDisposeListener) iter.next(); try { listener.dispose(this); } catch (Throwable e) { Debug.out(e); } } disposeListeners = null; } tableColumn.invokeCellDisposeListeners(this); tableColumn.invalidateCells(); } // @see com.aelitis.azureus.ui.common.table.TableCellCore#getCursorID() public int getCursorID() { // TODO Auto-generated method stub return 0; } // @see com.aelitis.azureus.ui.common.table.TableCellCore#getObfusticatedText() public String getObfusticatedText() { return text; } // @see com.aelitis.azureus.ui.common.table.TableCellCore#getTableRowCore() public TableRowCore getTableRowCore() { return null; } // @see com.aelitis.azureus.ui.common.table.TableCellCore#getVisuallyChangedSinceRefresh() public boolean getVisuallyChangedSinceRefresh() { return true; } // @see com.aelitis.azureus.ui.common.table.TableCellCore#invalidate(boolean) public void invalidate(boolean mustRefresh) { valid = false; } // @see com.aelitis.azureus.ui.common.table.TableCellCore#invokeToolTipListeners(int) public void invokeToolTipListeners(int type) { if (tableColumn == null) return; tableColumn.invokeCellToolTipListeners(this, type); if (tooltipListeners == null) return; try { if (type == TOOLTIPLISTENER_HOVER) { for (int i = 0; i < tooltipListeners.size(); i++) ((TableCellToolTipListener) (tooltipListeners.get(i))).cellHover(this); } else { for (int i = 0; i < tooltipListeners.size(); i++) ((TableCellToolTipListener) (tooltipListeners.get(i))).cellHoverComplete(this); } } catch (Throwable e) { Debug.out(e); } } // @see com.aelitis.azureus.ui.common.table.TableCellCore#invokeVisibilityListeners(int, boolean) public void invokeVisibilityListeners(int visibility, boolean invokeColumnListeners) { if (invokeColumnListeners) { tableColumn.invokeCellVisibilityListeners(this, visibility); } if (cellVisibilityListeners == null) return; for (int i = 0; i < cellVisibilityListeners.size(); i++) { try { TableCellVisibilityListener l = (TableCellVisibilityListener) (cellVisibilityListeners.get(i)); l.cellVisibilityChanged(this, visibility); } catch (Throwable e) { Debug.printStackTrace(e); } } } // @see com.aelitis.azureus.ui.common.table.TableCellCore#isMouseOver() public boolean isMouseOver() { if (isDisposed()) { return false; } Rectangle r = composite.getBounds(); if (cellArea != null) { r = new Rectangle(r.x + cellArea.x, r.y + cellArea.y, cellArea.width, cellArea.height); } Point ptStart = composite.toDisplay(r.x, r.y); r.x = ptStart.x; r.y = ptStart.y; Point ptCursor = composite.getDisplay().getCursorLocation(); return r.contains(ptCursor); } // @see com.aelitis.azureus.ui.common.table.TableCellCore#isUpToDate() public boolean isUpToDate() { return false; } // @see com.aelitis.azureus.ui.common.table.TableCellCore#locationChanged() public void locationChanged() { // TODO Auto-generated method stub } // @see com.aelitis.azureus.ui.common.table.TableCellCore#needsPainting() public boolean needsPainting() { return true; } // @see com.aelitis.azureus.ui.common.table.TableCellCore#refresh(boolean) public boolean refresh(boolean doGraphics) { return refresh(); } // @see com.aelitis.azureus.ui.common.table.TableCellCore#refresh(boolean, boolean, boolean) public boolean refresh(boolean doGraphics, boolean rowVisible, boolean cellVisible) { return refresh(); } // @see com.aelitis.azureus.ui.common.table.TableCellCore#refresh(boolean, boolean) public boolean refresh(boolean doGraphics, boolean rowVisible) { return refresh(); } // @see com.aelitis.azureus.ui.common.table.TableCellCore#setCursorID(int) public void setCursorID(int cursorID) { // TODO Auto-generated method stub } // @see com.aelitis.azureus.ui.common.table.TableCellCore#setUpToDate(boolean) public void setUpToDate(boolean upToDate) { // TODO Auto-generated method stub } // @see java.lang.Comparable#compareTo(java.lang.Object) public int compareTo(Object arg0) { // TODO Auto-generated method stub return 0; } public void setOrentation(int o) { orientation = o; } public Rectangle getCellArea() { return cellArea; } public void setCellArea(Rectangle cellArea) { //System.out.println("SCA " + cellArea + ";" + Debug.getCompressedStackTrace()); this.cellArea = cellArea; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getMouseOffset() public int[] getMouseOffset() { if (isDisposed()) { return null; } Rectangle r = composite.getBounds(); if (cellArea != null) { r = new Rectangle(r.x + cellArea.x, r.y + cellArea.y, cellArea.width, cellArea.height); } Point ptStart = composite.toDisplay(r.x, r.y); r.x = ptStart.x; r.y = ptStart.y; Point ptCursor = composite.getDisplay().getCursorLocation(); if (!r.contains(ptCursor)) { return null; } return new int[] { ptCursor.x - r.x, ptCursor.y - r.y }; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getMarginHeight() public int getMarginHeight() { return marginHeight; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getMarginWidth() public int getMarginWidth() { return marginWidth; } // @see com.aelitis.azureus.ui.common.table.TableCellCore#refreshAsync() public void refreshAsync() { refresh(); } // @see com.aelitis.azureus.ui.common.table.TableCellCore#redraw() public void redraw() { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (!isDisposed()) { composite.redraw(); } } }); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#doPaint(org.eclipse.swt.graphics.GC) public void doPaint(GC gc) { doPaint(gc, cellArea == null ? composite.getClientArea() : cellArea); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getBackgroundImage() public Image getBackgroundImage() { // TODO Auto-generated method stub return null; } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getBackgroundSWT() public Color getBackgroundSWT() { // TODO Auto-generated method stub return composite.getBackground(); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getBounds() public Rectangle getBounds() { return cellArea == null ? composite.getClientArea() : new Rectangle( cellArea.x, cellArea.y, cellArea.width, cellArea.height); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getBufferedTableItem() public BufferedTableItem getBufferedTableItem() { // TODO Auto-generated method stub return null; } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getForegroundSWT() public Color getForegroundSWT() { return composite.getForeground(); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getGraphicSWT() public Image getGraphicSWT() { // TODO Auto-generated method stub return null; } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getIcon() public Image getIcon() { // TODO Auto-generated method stub return null; } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getSize() public Point getSize() { Rectangle bounds = getBounds(); if (bounds == null) { return null; } return new Point(bounds.width, bounds.height); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getTableRowSWT() public TableRowSWT getTableRowSWT() { // TODO Auto-generated method stub return null; } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getTextAlpha() public int getTextAlpha() { // TODO Auto-generated method stub return 0; } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#setForeground(org.eclipse.swt.graphics.Color) public boolean setForeground(Color color) { // TODO Auto-generated method stub return false; } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#setGraphic(org.eclipse.swt.graphics.Image) public boolean setGraphic(Image img) { graphic = null; image = img; if (image != null) { imageBounds = image.getBounds(); } if (composite != null && !composite.isDisposed()) { redraw(); } return true; } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#setIcon(org.eclipse.swt.graphics.Image) public boolean setIcon(Image img) { // TODO Auto-generated method stub return false; } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#setTextAlpha(int) public void setTextAlpha(int textOpacity) { // TODO Auto-generated method stub } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/impl/TableCellImpl.java0000644000175000017500000012342711274423712026124 0ustar adrianadrian/* * File : TableCellImpl.java * Created : 24 nov. 2003 * By : Olivier * Originally PluginItem.java, and changed to be more generic. * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.table.impl; import java.text.Collator; import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; import java.util.Locale; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.ui.Graphic; import org.gudy.azureus2.plugins.ui.UIRuntimeException; import org.gudy.azureus2.plugins.ui.SWT.GraphicSWT; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.*; import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.TableRowSWT; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnSWTUtils; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.TableColumnSortObject; import com.aelitis.azureus.ui.common.table.TableRowCore; import com.aelitis.azureus.ui.common.table.TableView; /** TableCellImpl represents one cell in the table. * Table access is provided by BufferedTableItem. * TableCellImpl is stored in and accessed by TableRowCore. * Drawing control gets passed to listeners. * * For plugins, this object is the implementation to TableCell. * * This object is needed to split core code from plugin code. */ public class TableCellImpl implements TableCellSWT { private static final LogIDs LOGID = LogIDs.GUI; private static final byte FLAG_VALID = 1; private static final byte FLAG_SORTVALUEISTEXT = 2; private static final byte FLAG_TOOLTIPISAUTO = 4; /** * For refreshing, this flag manages whether the row is actually up to date. * * We don't update any visuals while the row isn't visible. But, validility * does get set to true so that the cell isn't forced to refresh every * cycle when not visible. (We can't just never call refresh when the row * is not visible, as refresh also sets the sort value) * * When the row does become visible, we have to invalidate the row so * that the row will set its visuals again (this time, actually * updating a viewable object). */ private static final byte FLAG_UPTODATE = 8; private static final byte FLAG_DISPOSED = 16; private static final byte FLAG_MUSTREFRESH = 32; private static final byte FLAG_VISUALLY_CHANGED_SINCE_REFRESH = 64; private byte flags; private TableRowCore tableRow; private Comparable sortValue; private BufferedTableItem bufferedTableItem; private ArrayList refreshListeners; private ArrayList disposeListeners; private ArrayList tooltipListeners; private ArrayList cellMouseListeners; private ArrayList cellMouseMoveListeners; private ArrayList cellVisibilityListeners; private ArrayList cellSWTPaintListeners; private TableColumnCore tableColumn; private byte refreshErrLoopCount; private byte tooltipErrLoopCount; private byte loopFactor; private Object oToolTip; private Object defaultToolTip; private int iCursorID = -1; private Graphic graphic = null; private ArrayList childCells; public boolean bDebug = false; private static AEMonitor this_mon = new AEMonitor( "TableCell" ); private static final String CFG_PAINT = "GUI_SWT_bAlternateTablePainting"; private static boolean bAlternateTablePainting; private static int MAX_REFRESHES = 10; private static int MAX_REFRESHES_WITHIN_MS = 100; private boolean bInRefresh = false; private long lastRefresh; private int numFastRefreshes; private byte restartRefresh = 0; private boolean bInRefreshAsync = false; private int textAlpha = 255; static { COConfigurationManager.addAndFireParameterListener(CFG_PAINT, new ParameterListener() { public void parameterChanged(String parameterName) { bAlternateTablePainting = COConfigurationManager .getBooleanParameter(CFG_PAINT); } }); } public TableCellImpl(TableRowCore _tableRow, TableColumnCore _tableColumn, int position, BufferedTableItem item) { this.tableColumn = _tableColumn; this.tableRow = _tableRow; flags = FLAG_SORTVALUEISTEXT; refreshErrLoopCount = 0; tooltipErrLoopCount = 0; loopFactor = 0; if (item != null) { bufferedTableItem = item; } else { createBufferedTableItem(position); } tableColumn.invokeCellAddedListeners(TableCellImpl.this); //bDebug = (position == 1) && tableColumn.getTableID().equalsIgnoreCase("Peers"); } /** * Initialize * * @param _tableRow * @param _tableColumn * @param position */ public TableCellImpl(TableRowSWT _tableRow, TableColumnCore _tableColumn, int position) { this(_tableRow, _tableColumn, position, null); } private void createBufferedTableItem(int position) { BufferedTableRow bufRow = (BufferedTableRow)tableRow; if (tableColumn.getType() == TableColumnCore.TYPE_GRAPHIC) { if (bAlternateTablePainting) { bufferedTableItem = new BufferedGraphicTableItem2(bufRow, position) { public void refresh() { TableCellImpl.this.refresh(); } public void invalidate() { clearFlag(FLAG_VALID); redraw(); } }; } else { bufferedTableItem = new BufferedGraphicTableItem1(bufRow, position) { public void refresh() { TableCellImpl.this.refresh(); } public void invalidate() { clearFlag(FLAG_VALID); redraw(); } }; } setOrientationViaColumn(); } else { bufferedTableItem = new BufferedTableItemImpl(bufRow, position) { public void refresh() { TableCellImpl.this.refresh(); } public void invalidate() { clearFlag(FLAG_VALID); } }; } } private void pluginError(Throwable e) { String sTitleLanguageKey = tableColumn.getTitleLanguageKey(); String sPosition = (bufferedTableItem == null) ? "null" : "" + bufferedTableItem.getPosition() + " (" + MessageText.getString(sTitleLanguageKey) + ")"; Logger.log(new LogEvent(LOGID, "Table Cell Plugin for Column #" + sPosition + " generated an exception ", e)); } private void pluginError(String s) { String sTitleLanguageKey = tableColumn.getTitleLanguageKey(); String sPosition = "r" + tableRow.getIndex() + (bufferedTableItem == null ? "null" : "c" + bufferedTableItem.getPosition() + " (" + MessageText.getString(sTitleLanguageKey) + ")"); Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "Table Cell Plugin for Column #" + sPosition + ":" + s + "\n " + Debug.getStackTrace(true, true))); } private void checkCellForSetting() { if (isDisposed()) throw new UIRuntimeException("Table Cell is disposed."); } /* Public API */ //////////////// public Object getDataSource() { // if we've been disposed then row/col are null TableRowCore row = tableRow; TableColumnCore col = tableColumn; if ( row == null || col == null){ return( null ); } return row.getDataSource(col.getUseCoreDataSource()); } public TableColumn getTableColumn() { return tableColumn; } public TableRow getTableRow() { return tableRow; } public String getTableID() { return tableRow.getTableID(); } public boolean isValid() { // Called often.. inline faster return (flags & FLAG_VALID) != 0; //return hasFlag(FLAG_VALID); } public Color getForegroundSWT() { checkCellForSetting(); return bufferedTableItem.getForeground(); } public Color getBackgroundSWT() { checkCellForSetting(); return bufferedTableItem.getBackground(); } public int[] getBackground() { if (bufferedTableItem == null) { return null; } Color color = bufferedTableItem.getBackground(); if (color == null) { return null; } return new int[] { color.getRed(), color.getGreen(), color.getBlue() }; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getForeground() public int[] getForeground() { if (bufferedTableItem == null) { return new int[] { 0, 0, 0 }; } Color color = bufferedTableItem.getForeground(); if (color == null) { return new int[3]; } return new int[] { color.getRed(), color.getGreen(), color.getBlue() }; } public boolean setForeground(Color color) { checkCellForSetting(); // Don't need to set when not visible if (isInvisibleAndCanRefresh()) return false; boolean set = bufferedTableItem.setForeground(color); if (set) { setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); } return set; } public boolean setForeground(int red, int green, int blue) { checkCellForSetting(); // Don't need to set when not visible if (isInvisibleAndCanRefresh()) return false; boolean set; if (red < 0 || green < 0 || blue < 0) { set = bufferedTableItem.setForeground(null); } else { set = bufferedTableItem.setForeground(red, green, blue); } if (set) { setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); } return set; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setForeground(int[]) public boolean setForeground(int[] rgb) { if (rgb == null || rgb.length < 3) { return setForeground((Color) null); } return setForeground(rgb[0], rgb[1], rgb[2]); } public boolean setForegroundToErrorColor() { return setForeground(Colors.colorError); } public boolean setText(String text) { checkCellForSetting(); if (text == null) text = ""; boolean bChanged = false; if (hasFlag(FLAG_SORTVALUEISTEXT) && !text.equals(sortValue)) { bChanged = true; sortValue = text; tableColumn.setLastSortValueChange(SystemTime.getCurrentTime()); if (bDebug) debug("Setting SortValue to text;"); } // Slower than setText(..)! // if (isInvisibleAndCanRefresh()) { // if (bDebug) { // debug("setText ignored: invisible"); // } // return false; // } if (bufferedTableItem.setText(text) && !hasFlag(FLAG_SORTVALUEISTEXT)) bChanged = true; if (bDebug) { debug("setText (" + bChanged + ") : " + text); } if (bChanged) { setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); } boolean do_auto = this.tableColumn.doesAutoTooltip(); // If we were using auto tooltips (and we aren't any more), then // clear up previously set tooltips. if (!do_auto) { if (hasFlag(FLAG_TOOLTIPISAUTO)) { this.oToolTip = null; clearFlag(FLAG_TOOLTIPISAUTO); } } else { this.oToolTip = text; setFlag(FLAG_TOOLTIPISAUTO); } return bChanged; } private boolean isInvisibleAndCanRefresh() { return !isShown() && (refreshListeners != null || tableColumn.hasCellRefreshListener()); } public String getText() { if (hasFlag(FLAG_SORTVALUEISTEXT) && sortValue instanceof String) return (String)sortValue; if (bufferedTableItem == null) { return null; } return bufferedTableItem.getText(); } public boolean isShown() { if (bufferedTableItem == null) { return false; } return bufferedTableItem.isShown() && tableRow.getView().isColumnVisible(tableColumn); } public boolean setSortValue(Comparable valueToSort) { if (!tableColumn.isSortValueLive()) { // objects that can't change aren't live if (!(valueToSort instanceof Number) && !(valueToSort instanceof String) && !(valueToSort instanceof TableColumnSortObject)) { tableColumn.setSortValueLive(true); } } return _setSortValue(valueToSort); } private boolean _setSortValue(Comparable valueToSort) { checkCellForSetting(); if (sortValue == valueToSort) return false; if (hasFlag(FLAG_SORTVALUEISTEXT)) { clearFlag(FLAG_SORTVALUEISTEXT); if (sortValue instanceof String) // Make sure text is actually in the cell (it may not have been if // cell wasn't created at the time of setting) setText((String)sortValue); } if ((valueToSort instanceof String) && (sortValue instanceof String) && sortValue.equals(valueToSort)) { return false; } if ((valueToSort instanceof Number) && (sortValue instanceof Number) && sortValue.equals(valueToSort)) { return false; } if (bDebug) debug("Setting SortValue to " + ((valueToSort == null) ? "null" : valueToSort.getClass().getName())); tableColumn.setLastSortValueChange(SystemTime.getCurrentTime()); sortValue = valueToSort; if (cellSWTPaintListeners != null || tableColumn.hasCellOtherListeners("SWTPaint")) { redraw(); } return true; } public boolean setSortValue(long valueToSort) { checkCellForSetting(); if ((sortValue instanceof Long) && ((Long) sortValue).longValue() == valueToSort) return false; return _setSortValue(Long.valueOf(valueToSort)); } public boolean setSortValue( float valueToSort ) { checkCellForSetting(); if (sortValue instanceof Float && ((Float) sortValue).floatValue() == valueToSort) return false; return _setSortValue(new Float(valueToSort)); } public Comparable getSortValue() { if (bDebug) debug("GetSortValue;" + (sortValue == null ? "null" : sortValue.getClass().getName() + ";" + sortValue.toString())); if (sortValue == null) { if (bufferedTableItem != null) return bufferedTableItem.getText(); return ""; } return sortValue; } public void setToolTip(Object tooltip) { oToolTip = tooltip; clearFlag(FLAG_TOOLTIPISAUTO); } public Object getToolTip() { return oToolTip; } public Object getDefaultToolTip() { return defaultToolTip; } public void setDefaultToolTip(Object tt) { defaultToolTip = tt; } public boolean isDisposed() { return hasFlag(FLAG_DISPOSED); } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getMaxLines() public int getMaxLines() { if (bufferedTableItem == null) { // use 1 in case some plugin borks on div by zero return 1; } return bufferedTableItem.getMaxLines(); } /* Start TYPE_GRAPHIC Functions */ public Point getSize() { if (!(bufferedTableItem instanceof BufferedGraphicTableItem)) return null; return ((BufferedGraphicTableItem)bufferedTableItem).getSize(); } public int getWidth() { Point pt = null; if (bufferedTableItem instanceof BufferedGraphicTableItem) { pt = ((BufferedGraphicTableItem)bufferedTableItem).getSize(); } else { Rectangle bounds = bufferedTableItem.getBounds(); if (bounds != null) { pt = new Point(bounds.width, bounds.height); } } if (pt == null) return -1; return pt.x; } public int getHeight() { Point pt = null; if (bufferedTableItem instanceof BufferedGraphicTableItem) { pt = ((BufferedGraphicTableItem)bufferedTableItem).getSize(); } else { Rectangle bounds = bufferedTableItem.getBounds(); if (bounds != null) { pt = new Point(bounds.width, bounds.height); } } if (pt == null) return -1; return pt.y; } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#setGraphic(org.eclipse.swt.graphics.Image) public boolean setGraphic(Image img) { checkCellForSetting(); if (!(bufferedTableItem instanceof BufferedGraphicTableItem)) return false; graphic = null; boolean b = ((BufferedGraphicTableItem)bufferedTableItem).setGraphic(img); if (b) { setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); bufferedTableItem.redraw(); } return b; } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#setGraphic(org.gudy.azureus2.plugins.ui.Graphic) public boolean setGraphic(Graphic img) { if (img != null){ checkCellForSetting(); } if (!(bufferedTableItem instanceof BufferedGraphicTableItem)) return false; if (img == graphic && numFastRefreshes >= MAX_REFRESHES) { pluginError("TableCellImpl::setGraphic to same Graphic object. " + "Forcing refresh."); } graphic = img; if (img == null) { boolean b = ((BufferedGraphicTableItem)bufferedTableItem).setGraphic(null); if (b) { setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); bufferedTableItem.redraw(); } } if (img instanceof GraphicSWT){ Image imgSWT = ((GraphicSWT)img).getImage(); boolean b = ((BufferedGraphicTableItem)bufferedTableItem).setGraphic(imgSWT); if (b) { setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); bufferedTableItem.redraw(); } } else if (img instanceof UISWTGraphic){ Image imgSWT = ((UISWTGraphic)img).getImage(); boolean b = ((BufferedGraphicTableItem)bufferedTableItem).setGraphic(imgSWT); if (b) { setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); bufferedTableItem.redraw(); } } return( false ); } public Graphic getGraphic() { if (graphic != null) { return graphic; } if (!(bufferedTableItem instanceof BufferedGraphicTableItem)) return null; Image img = ((BufferedGraphicTableItem)bufferedTableItem).getGraphic(); return new UISWTGraphicImpl(img); } public Image getGraphicSWT() { if (!(bufferedTableItem instanceof BufferedGraphicTableItem)) return null; return ((BufferedGraphicTableItem)bufferedTableItem).getGraphic(); } public void setFillCell(boolean bFillCell) { checkCellForSetting(); if (!(bufferedTableItem instanceof BufferedGraphicTableItem)) return; if (bFillCell) ((BufferedGraphicTableItem)bufferedTableItem).setOrientation(SWT.FILL); else setOrientationViaColumn(); setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); } public void setMarginHeight(int height) { checkCellForSetting(); if (!(bufferedTableItem instanceof BufferedGraphicTableItem)) return; ((BufferedGraphicTableItem)bufferedTableItem).setMargin(-1, height); setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); } public void setMarginWidth(int width) { checkCellForSetting(); if (!(bufferedTableItem instanceof BufferedGraphicTableItem)) return; ((BufferedGraphicTableItem)bufferedTableItem).setMargin(width, -1); setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); } public int getMarginHeight() { if (!(bufferedTableItem instanceof BufferedGraphicTableItem)) return 0; return ((BufferedGraphicTableItem)bufferedTableItem).getMarginHeight(); } public int getMarginWidth() { if (!(bufferedTableItem instanceof BufferedGraphicTableItem)) return 0; return ((BufferedGraphicTableItem)bufferedTableItem).getMarginWidth(); } /* End TYPE_GRAPHIC Functions */ public void addRefreshListener(TableCellRefreshListener listener) { try{ this_mon.enter(); if (refreshListeners == null) refreshListeners = new ArrayList(1); if (bDebug) { debug("addRefreshListener; count=" + refreshListeners.size()); } refreshListeners.add(listener); }finally{ this_mon.exit(); } } public void removeRefreshListener(TableCellRefreshListener listener) { try{ this_mon.enter(); if (refreshListeners == null) return; refreshListeners.remove(listener); }finally{ this_mon.exit(); } } public void addDisposeListener(TableCellDisposeListener listener) { try{ this_mon.enter(); if (disposeListeners == null) { disposeListeners = new ArrayList(1); } disposeListeners.add(listener); }finally{ this_mon.exit(); } } public void removeDisposeListener(TableCellDisposeListener listener) { try{ this_mon.enter(); if (disposeListeners == null) return; disposeListeners.remove(listener); }finally{ this_mon.exit(); } } public void addToolTipListener(TableCellToolTipListener listener) { try{ this_mon.enter(); if (tooltipListeners == null) { tooltipListeners = new ArrayList(1); } tooltipListeners.add(listener); }finally{ this_mon.exit(); } } public void removeToolTipListener(TableCellToolTipListener listener) { try{ this_mon.enter(); if (tooltipListeners == null) return; tooltipListeners.remove(listener); }finally{ this_mon.exit(); } } public void addMouseListener(TableCellMouseListener listener) { try { this_mon.enter(); if (cellMouseListeners == null) cellMouseListeners = new ArrayList(1); cellMouseListeners.add(listener); } finally { this_mon.exit(); } } public void removeMouseListener(TableCellMouseListener listener) { try { this_mon.enter(); if (cellMouseListeners == null) return; cellMouseListeners.remove(listener); } finally { this_mon.exit(); } } public void addMouseMoveListener(TableCellMouseMoveListener listener) { try { this_mon.enter(); if (cellMouseMoveListeners == null) cellMouseMoveListeners = new ArrayList(1); cellMouseMoveListeners.add(listener); } finally { this_mon.exit(); } } public void removeMouseMoveListener(TableCellMouseMoveListener listener) { try { this_mon.enter(); if (cellMouseMoveListeners == null) return; cellMouseMoveListeners.remove(listener); } finally { this_mon.exit(); } } public void addVisibilityListener(TableCellVisibilityListener listener) { try { this_mon.enter(); if (cellVisibilityListeners == null) cellVisibilityListeners = new ArrayList(1); cellVisibilityListeners.add(listener); } finally { this_mon.exit(); } } public void removeVisibilityListener(TableCellVisibilityListener listener) { try { this_mon.enter(); if (cellVisibilityListeners == null) return; cellVisibilityListeners.remove(listener); } finally { this_mon.exit(); } } /** * @param listenerObject * * @since 3.1.1.1 */ private void addSWTPaintListener(TableCellSWTPaintListener listener) { try { this_mon.enter(); if (cellSWTPaintListeners == null) cellSWTPaintListeners = new ArrayList(1); cellSWTPaintListeners.add(listener); } finally { this_mon.exit(); } } public void invokeSWTPaintListeners(GC gc) { if (tableColumn != null) { Object[] swtPaintListeners = tableColumn.getCellOtherListeners("SWTPaint"); if (swtPaintListeners != null) { for (int i = 0; i < swtPaintListeners.length; i++) { try { TableCellSWTPaintListener l = (TableCellSWTPaintListener) swtPaintListeners[i]; l.cellPaint(gc, this); } catch (Throwable e) { Debug.printStackTrace(e); } } } } if (cellSWTPaintListeners == null) { return; } for (int i = 0; i < cellSWTPaintListeners.size(); i++) { try { TableCellSWTPaintListener l = (TableCellSWTPaintListener) (cellSWTPaintListeners.get(i)); l.cellPaint(gc, this); } catch (Throwable e) { Debug.printStackTrace(e); } } } public void addListeners(Object listenerObject) { if (listenerObject instanceof TableCellDisposeListener) { addDisposeListener((TableCellDisposeListener)listenerObject); } if (listenerObject instanceof TableCellRefreshListener) addRefreshListener((TableCellRefreshListener)listenerObject); if (listenerObject instanceof TableCellToolTipListener) addToolTipListener((TableCellToolTipListener)listenerObject); if (listenerObject instanceof TableCellMouseMoveListener) { addMouseMoveListener((TableCellMouseMoveListener) listenerObject); } if (listenerObject instanceof TableCellMouseListener) { addMouseListener((TableCellMouseListener) listenerObject); } if (listenerObject instanceof TableCellVisibilityListener) addVisibilityListener((TableCellVisibilityListener)listenerObject); if (listenerObject instanceof TableCellSWTPaintListener) addSWTPaintListener((TableCellSWTPaintListener)listenerObject); } /** * If a plugin in trying to invalidate a cell, then clear the sort value * too. */ public void invalidate() { checkCellForSetting(); invalidate(true); } /* Start of Core-Only function */ ////////////////////////////////// public void redraw() { if (bufferedTableItem != null) { bufferedTableItem.redraw(); } } public void invalidate(final boolean bMustRefresh) { if (!hasFlag(FLAG_VALID)) { if (bMustRefresh) { if (hasFlag(FLAG_MUSTREFRESH)) { return; } } else { return; } } clearFlag(FLAG_VALID); setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); if (bDebug) debug("Invalidate Cell;" + bMustRefresh); if (bMustRefresh) { setFlag(FLAG_MUSTREFRESH); if (bufferedTableItem != null) { bufferedTableItem.invalidate(); } } } // @see com.aelitis.azureus.ui.common.table.TableCellCore#refresh() public boolean refresh() { return refresh(true); } // @see com.aelitis.azureus.ui.common.table.TableCellCore#refreshAsync() public void refreshAsync() { if (bInRefreshAsync) { //System.out.println(System.currentTimeMillis() + "] SKIP " + restartRefresh); if (restartRefresh < Byte.MAX_VALUE) { restartRefresh++; } return; } bInRefreshAsync = true; AERunnable runnable = new AERunnable() { public void runSupport() { //System.out.println(System.currentTimeMillis() + "] REFRESH!"); restartRefresh = 0; refresh(true); bInRefreshAsync = false; //System.out.println(System.currentTimeMillis() + "] REFRESH OUT!"); if (restartRefresh > 0) { refreshAsync(); } } }; Utils.execSWTThreadLater(25, runnable); } // @see com.aelitis.azureus.ui.common.table.TableCellCore#refresh(boolean) public boolean refresh(boolean bDoGraphics) { boolean isRowShown; if (tableRow != null) { TableView view = tableRow.getView(); isRowShown = view.isRowVisible(tableRow); } else { isRowShown = true; } boolean isCellShown = isRowShown && isShown(); return refresh(bDoGraphics, isRowShown, isCellShown); } // @see com.aelitis.azureus.ui.common.table.TableCellCore#refresh(boolean, boolean) public boolean refresh(boolean bDoGraphics, boolean bRowVisible) { boolean isCellShown = bRowVisible && isShown(); return refresh(bDoGraphics, bRowVisible, isCellShown); } // @see com.aelitis.azureus.ui.common.table.TableCellCore#refresh(boolean, boolean, boolean) public boolean refresh(boolean bDoGraphics, boolean bRowVisible, boolean bCellVisible) { if (tableColumn == null) { return false; } boolean ret = getVisuallyChangedSinceRefresh(); clearFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); int iErrCount = 0; if (refreshErrLoopCount > 2) { return ret; } iErrCount = tableColumn.getConsecutiveErrCount(); if (iErrCount > 10) { refreshErrLoopCount = 3; return ret; } if (bInRefresh) { // Skip a Refresh call when being called from within refresh. // This could happen on virtual tables where SetData calls us again, or // if we ever introduce plugins to refresh. if (bDebug) debug("Calling Refresh from Refresh :) Skipping."); return ret; } try { bInRefresh = true; if (ret) { long now = SystemTime.getCurrentTime(); if (now - lastRefresh < MAX_REFRESHES_WITHIN_MS) { numFastRefreshes++; if (numFastRefreshes >= MAX_REFRESHES) { if ((numFastRefreshes % MAX_REFRESHES) == 0) { pluginError("this plugin is crazy. tried to refresh " + numFastRefreshes + " times in " + (now - lastRefresh) + "ms"); } return ret; } } else { numFastRefreshes = 0; lastRefresh = now; } } // See bIsUpToDate variable comments if (bCellVisible && !isUpToDate()) { if (bDebug) debug("Setting Invalid because visible & not up to date"); clearFlag(FLAG_VALID); setFlag(FLAG_UPTODATE); } else if (!bCellVisible && isUpToDate()) { if (bDebug) debug("Setting not up to date because cell not visible " + Debug.getCompressedStackTrace()); clearFlag(FLAG_UPTODATE); } if (bDebug) { debug("Cell Valid?" + hasFlag(FLAG_VALID) + "; Visible?" + tableRow.isVisible() + "/" + bufferedTableItem.isShown()); } int iInterval = tableColumn.getRefreshInterval(); if (iInterval == TableColumnCore.INTERVAL_INVALID_ONLY && !hasFlag(FLAG_MUSTREFRESH | FLAG_VALID) && hasFlag(FLAG_SORTVALUEISTEXT) && sortValue != null && tableColumn.getType() == TableColumnCore.TYPE_TEXT_ONLY) { if (bCellVisible) { if (bDebug) debug("fast refresh: setText"); ret = setText((String)sortValue); setFlag(FLAG_VALID); } } else if ((iInterval == TableColumnCore.INTERVAL_LIVE || (iInterval == TableColumnCore.INTERVAL_GRAPHIC && bDoGraphics) || (iInterval > 0 && (loopFactor % iInterval) == 0) || !hasFlag(FLAG_VALID) || hasFlag(FLAG_MUSTREFRESH))) { boolean bWasValid = isValid(); if (hasFlag(FLAG_MUSTREFRESH)) { clearFlag(FLAG_MUSTREFRESH); } if (bDebug) debug("invoke refresh; wasValid? " + bWasValid); long lTimeStart = Constants.isCVSVersion()?SystemTime.getMonotonousTime():0; tableColumn.invokeCellRefreshListeners(this, !bCellVisible); if (refreshListeners != null) { for (int i = 0; i < refreshListeners.size(); i++) { TableCellRefreshListener l = (TableCellRefreshListener)refreshListeners.get(i); if(l instanceof TableCellLightRefreshListener) ((TableCellLightRefreshListener)l).refresh(this,!bCellVisible); else l.refresh(this); } } if ( Constants.isCVSVersion()){ long lTimeEnd = SystemTime.getMonotonousTime(); tableColumn.addRefreshTime(lTimeEnd - lTimeStart); } // Change to valid only if we weren't valid before the listener calls // This is in case the listeners set valid to false when it was true if (!bWasValid && !hasFlag(FLAG_MUSTREFRESH)) { setFlag(FLAG_VALID); } } loopFactor++; refreshErrLoopCount = 0; if (iErrCount > 0) tableColumn.setConsecutiveErrCount(0); ret = getVisuallyChangedSinceRefresh(); if (bDebug) debug("refresh done; visual change? " + ret + ";" + Debug.getCompressedStackTrace()); } catch (Throwable e) { refreshErrLoopCount++; if (tableColumn != null) { tableColumn.setConsecutiveErrCount(++iErrCount); } pluginError(e); if (refreshErrLoopCount > 2) Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "TableCell will not be refreshed anymore this session.")); } finally { bInRefresh = false; } if (childCells != null) { Object[] childCellsArray = childCells.toArray(); for (int i = 0; i < childCellsArray.length; i++) { TableCellImpl childCell = (TableCellImpl) childCellsArray[i]; childCell.refresh(bDoGraphics, bRowVisible, bCellVisible); } } return ret; } public boolean getVisuallyChangedSinceRefresh() { return hasFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); } public void dispose() { setFlag(FLAG_DISPOSED); tableColumn.invokeCellDisposeListeners(this); if (disposeListeners != null) { try { for (Iterator iter = disposeListeners.iterator(); iter.hasNext();) { TableCellDisposeListener listener = (TableCellDisposeListener)iter.next(); listener.dispose(this); } disposeListeners = null; } catch (Throwable e) { pluginError(e); } } if (bufferedTableItem != null) { bufferedTableItem.setForeground(null); bufferedTableItem.dispose(); } refreshListeners = null; bufferedTableItem = null; tableColumn = null; tableRow = null; sortValue = null; } public boolean setIcon(Image img) { if (isInvisibleAndCanRefresh()) return false; bufferedTableItem.setIcon(img); graphic = null; setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH); return true; } public Image getIcon() { if (bufferedTableItem == null) { return null; } return bufferedTableItem.getIcon(); } public boolean needsPainting() { if (cellSWTPaintListeners != null || tableColumn.hasCellOtherListeners("SWTPaint")) { return true; } if (bufferedTableItem == null) { return false; } return bufferedTableItem.needsPainting(); } public void doPaint(GC gc) { //This sometimes causes a infinite loop if the listener invalidates //the drawing area //if ((!hasFlag(FLAG_UPTODATE) || !hasFlag(FLAG_VALID)) && !bInRefresh && !bInRefreshAsync // && (refreshListeners != null || tableColumn.hasCellRefreshListener())) { // if (bDebug) { // debug("doPaint: invoke refresh"); // } // refresh(true); //} if (bDebug) { debug("doPaint up2date:" + hasFlag(FLAG_UPTODATE) + ";v:" + hasFlag(FLAG_VALID) + ";rl=" + refreshListeners); } invokeSWTPaintListeners(gc); bufferedTableItem.doPaint(gc); if (childCells != null) { Object[] childCellsArray = childCells.toArray(); for (int i = 0; i < childCellsArray.length; i++) { TableCellImpl childCell = (TableCellImpl) childCellsArray[i]; childCell.doPaint(gc); } } } public void locationChanged() { if (bufferedTableItem != null) { bufferedTableItem.locationChanged(); } } public TableRowCore getTableRowCore() { return tableRow; } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getTableRowSWT() public TableRowSWT getTableRowSWT() { if (tableRow instanceof TableRowSWT) { return (TableRowSWT)tableRow; } return null; } /* (non-Javadoc) * @see java.lang.Object#toString() */ public String toString() { return "TableCell {" + tableColumn.getName() + "," + (tableRow == null ? "" : "r" + tableRow.getIndex()) + (bufferedTableItem == null ? "c?" : "c" + bufferedTableItem.getPosition()) + "," + getText() + "," + getSortValue() + "}"; } /* Comparable Implementation */ /** Compare our sortValue to the specified object. Assumes the object * is TableCellImp (safe assumption) */ public int compareTo(Object o) { try { Comparable ourSortValue = getSortValue(); Comparable otherSortValue = ((TableCellImpl)o).getSortValue(); if (ourSortValue instanceof String && otherSortValue instanceof String) { // Collator.getInstance cache's Collator object, so this is relatively // fast. However, storing it as static somewhere might give a small // performance boost. If such an approach is take, ensure that the static // variable is updated the user chooses an different language. Collator collator = Collator.getInstance(Locale.getDefault()); return collator.compare(ourSortValue, otherSortValue); } try { return ourSortValue.compareTo(otherSortValue); } catch (ClassCastException e) { // It's possible that a row was created, but not refreshed yet. // In that case, one sortValue will be String, and the other will be // a comparable object that the plugin defined. Those two sortValues // may not be compatable (for good reason!), so just skip it. } } catch (Exception e) { System.out.println("Could not compare cells"); Debug.printStackTrace( e ); } return 0; } public void invokeToolTipListeners(int type) { if (tableColumn == null) return; tableColumn.invokeCellToolTipListeners(this, type); if (tooltipListeners == null || tooltipErrLoopCount > 2) return; int iErrCount = tableColumn.getConsecutiveErrCount(); if (iErrCount > 10) return; try { if (type == TOOLTIPLISTENER_HOVER) { for (int i = 0; i < tooltipListeners.size(); i++) ((TableCellToolTipListener)(tooltipListeners.get(i))).cellHover(this); } else { for (int i = 0; i < tooltipListeners.size(); i++) ((TableCellToolTipListener)(tooltipListeners.get(i))).cellHoverComplete(this); } tooltipErrLoopCount = 0; } catch (Throwable e) { tooltipErrLoopCount++; tableColumn.setConsecutiveErrCount(++iErrCount); pluginError(e); if (tooltipErrLoopCount > 2) Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "TableCell's tooltip will not be refreshed anymore this session.")); } } public void invokeMouseListeners(TableCellMouseEvent event) { ArrayList listeners = event.eventType == TableCellMouseEvent.EVENT_MOUSEMOVE ? cellMouseMoveListeners : cellMouseListeners; if (listeners == null) return; if (event.cell != null && event.row == null) { event.row = event.cell.getTableRow(); } for (int i = 0; i < listeners.size(); i++) { try { TableCellMouseListener l = (TableCellMouseListener) (listeners.get(i)); l.cellMouseTrigger(event); } catch (Throwable e) { Debug.printStackTrace(e); } } } public void invokeVisibilityListeners(int visibility, boolean invokeColumnListeners) { if (invokeColumnListeners) { tableColumn.invokeCellVisibilityListeners(this, visibility); } if (cellVisibilityListeners == null) return; for (int i = 0; i < cellVisibilityListeners.size(); i++) { try { TableCellVisibilityListener l = (TableCellVisibilityListener) (cellVisibilityListeners.get(i)); l.cellVisibilityChanged(this, visibility); } catch (Throwable e) { Debug.printStackTrace(e); } } } public static final Comparator TEXT_COMPARATOR = new TextComparator(); private static class TextComparator implements Comparator { public int compare(Object arg0, Object arg1) { return arg0.toString().compareToIgnoreCase(arg1.toString()); } } public void setUpToDate(boolean upToDate) { if (bDebug) debug("set up to date to " + upToDate); if (upToDate) { setFlag(FLAG_UPTODATE); } else { clearFlag(FLAG_UPTODATE); } } public boolean isUpToDate() { return hasFlag(FLAG_UPTODATE); } public void debug(final String s) { Utils.execSWTThread(new AERunnable() { public void runSupport() { System.out.println(SystemTime.getCurrentTime() + ": r" + tableRow.getIndex() + "c" + tableColumn.getPosition() + "r.v?" + ((tableRow.isVisible() ? "Y" : "N")) + ";" + s); } }, true); } public Rectangle getBounds() { if (isDisposed()) { return new Rectangle(0, 0, 0, 0); } Rectangle bounds = bufferedTableItem.getBounds(); if (bounds == null) { return new Rectangle(0, 0, 0, 0); } return bounds; } private void setOrientationViaColumn() { if (!(bufferedTableItem instanceof BufferedGraphicTableItem)) return; int align = tableColumn.getAlignment(); BufferedGraphicTableItem ti = (BufferedGraphicTableItem) bufferedTableItem; ti.setOrientation(TableColumnSWTUtils.convertColumnAlignmentToSWT(align)); } public String getObfusticatedText() { if (tableColumn.isObfusticated()) { if (tableColumn instanceof ObfusticateCellText) { return ((ObfusticateCellText)tableColumn).getObfusticatedText(this); } return ""; } return null; } public Graphic getBackgroundGraphic() { if (bufferedTableItem == null) { return null; } return new UISWTGraphicImpl(bufferedTableItem.getBackgroundImage()); } public Image getBackgroundImage() { if (bufferedTableItem == null) { return null; } return bufferedTableItem.getBackgroundImage(); } public BufferedTableItem getBufferedTableItem() { return bufferedTableItem; } public int getCursorID() { return iCursorID; } public void setCursorID(int cursorID) { iCursorID = cursorID; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (isMouseOver()) { bufferedTableItem.setCursor(iCursorID); } } }); } public boolean isMouseOver() { if (bufferedTableItem == null) { return false; } return bufferedTableItem.isMouseOver(); } public int[] getMouseOffset() { Point ofs = ((TableViewSWT) tableRow.getView()).getTableCellMouseOffset(this); return ofs == null ? null : new int[] { ofs.x, ofs.y }; } private boolean hasFlag(int flag) { return (flags & flag) != 0; } private void setFlag(int flag) { flags |= flag; } private void clearFlag(int flag) { flags &= ~flag; } /** * @param childCell * * @since 3.0.5.3 */ public void addChildCell(TableCellImpl childCell) { if (childCells == null) { childCells = new ArrayList(1); } //TODO: childCell.setParentCell(this); childCells.add(childCell); } public int getTextAlpha() { return textAlpha; } public void setTextAlpha(int textOpacity) { this.textAlpha = textOpacity; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/impl/TableTooltips.java0000644000175000017500000001303011223221570026214 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.table.impl; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; /** * @author TuxPaper * @created Mar 1, 2007 * */ public class TableTooltips implements Listener { Shell toolTipShell = null; Shell mainShell = null; Label toolTipLabel = null; private final Composite composite; private final TableViewSWT tv; /** * Initialize */ public TableTooltips(TableViewSWT tv, Composite composite) { this.tv = tv; this.composite = composite; mainShell = composite.getShell(); composite.addListener(SWT.Dispose, this); composite.addListener(SWT.KeyDown, this); composite.addListener(SWT.MouseMove, this); composite.addListener(SWT.MouseHover, this); mainShell.addListener(SWT.Deactivate, this); tv.getComposite().addListener(SWT.Deactivate, this); } public void handleEvent(Event event) { switch (event.type) { case SWT.MouseHover: { if (toolTipShell != null && !toolTipShell.isDisposed()) toolTipShell.dispose(); TableCellSWT cell = tv.getTableCell(event.x, event.y); if (cell == null) return; cell.invokeToolTipListeners(TableCellSWT.TOOLTIPLISTENER_HOVER); Object oToolTip = cell.getToolTip(); if ( oToolTip == null ){ oToolTip = cell.getDefaultToolTip(); } // TODO: support composite, image, etc if (oToolTip == null) return; Display d = composite.getDisplay(); if (d == null) return; // We don't get mouse down notifications on trim or borders.. toolTipShell = new Shell(composite.getShell(), SWT.ON_TOP); FillLayout f = new FillLayout(); try { f.marginWidth = 3; f.marginHeight = 1; } catch (NoSuchFieldError e) { /* Ignore for Pre 3.0 SWT.. */ } toolTipShell.setLayout(f); toolTipShell.setBackground(d.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); Point size = new Point(0, 0); if (oToolTip instanceof String) { String sToolTip = (String) oToolTip; toolTipLabel = new Label(toolTipShell, SWT.WRAP); toolTipLabel.setForeground(d.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); toolTipLabel.setBackground(d.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); toolTipShell.setData("TableCellSWT", cell); toolTipLabel.setText(sToolTip.replaceAll("&", "&&")); // compute size on label instead of shell because label // calculates wrap, while shell doesn't size = toolTipLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT); if (size.x > 600) { size = toolTipLabel.computeSize(600, SWT.DEFAULT, true); } } else if (oToolTip instanceof Image) { Image image = (Image) oToolTip; toolTipLabel = new Label(toolTipShell, SWT.CENTER); toolTipLabel.setForeground(d.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); toolTipLabel.setBackground(d.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); toolTipShell.setData("TableCellSWT", cell); toolTipLabel.setImage(image); size = toolTipLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT); } size.x += toolTipShell.getBorderWidth() * 2 + 2; size.y += toolTipShell.getBorderWidth() * 2; try { size.x += toolTipShell.getBorderWidth() * 2 + (f.marginWidth * 2); size.y += toolTipShell.getBorderWidth() * 2 + (f.marginHeight * 2); } catch (NoSuchFieldError e) { /* Ignore for Pre 3.0 SWT.. */ } Point pt = composite.toDisplay(event.x, event.y); Rectangle displayRect; try { displayRect = composite.getMonitor().getClientArea(); } catch (NoSuchMethodError e) { displayRect = composite.getDisplay().getClientArea(); } if (pt.x + size.x > displayRect.x + displayRect.width) { pt.x = displayRect.x + displayRect.width - size.x; } if (pt.y + size.y > displayRect.y + displayRect.height) { pt.y -= size.y + 2; } else { pt.y += 21; } if (pt.y < displayRect.y) pt.y = displayRect.y; toolTipShell.setBounds(pt.x, pt.y, size.x, size.y); toolTipShell.setVisible(true); break; } case SWT.Dispose: if (mainShell != null && !mainShell.isDisposed()) mainShell.removeListener(SWT.Deactivate, this); if (tv.getComposite() != null && !tv.getComposite().isDisposed()) mainShell.removeListener(SWT.Deactivate, this); // fall through default: if (toolTipShell != null) { toolTipShell.dispose(); toolTipShell = null; toolTipLabel = null; } break; } // switch } // handlEvent() } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/TableRowSWT.java0000644000175000017500000000415411072556246024627 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.table; import com.aelitis.azureus.ui.common.table.TableRowCore; import org.eclipse.swt.graphics.*; /** * @author TuxPaper * @created Jan 22, 2007 * */ public interface TableRowSWT extends TableRowCore { /** re-paint an area of the row * * @param gc Area needing repainting, and GC object one can use to repaint it */ public void doPaint(GC gc); public boolean setIconSize(Point pt); /** Retreive the color of the row * * @return color of the row */ public Color getForeground(); /** Set the color of the row * * @param c new color */ public void setForeground(Color c); public Color getBackground(); /** * @param gc * @param b */ public void doPaint(GC gc, boolean bVisible); /** * @param cellName * @return */ public TableCellSWT getTableCellSWT(String cellName); public Rectangle getBounds(); public void setBackgroundImage(Image image); /** * @return * * @since 3.1.1.1 */ public int getFontStyle(); /** * @param bold * * @since 3.1.1.1 */ public boolean setFontStyle(int style); /** * @return * * @since 3.1.1.1 */ public int getAlpha(); /** * @param i * * @since 3.1.1.1 */ public boolean setAlpha(int alpha); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/TableViewSWT.java0000644000175000017500000000730111274223470024761 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.table; import org.eclipse.swt.dnd.DragSource; import org.eclipse.swt.dnd.DropTarget; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.ui.swt.views.IView; import com.aelitis.azureus.ui.common.table.TableRowCore; import com.aelitis.azureus.ui.common.table.TableView; import org.gudy.azureus2.plugins.ui.tables.TableRowRefreshListener; /** * @author TuxPaper * @created Feb 2, 2007 * */ public interface TableViewSWT extends TableView { /** Helpful output when trying to debug add/removal of rows */ public final static boolean DEBUGADDREMOVE = System.getProperty("debug.swt.table.addremove", "0").equals("1"); void addKeyListener(KeyListener listener); public void addMenuFillListener(TableViewSWTMenuFillListener l); DragSource createDragSource(int style); DropTarget createDropTarget(int style); public Composite getComposite(); /** * @return */ IView[] getCoreTabViews(); TableRowCore getRow(DropTargetEvent event); /** * @param dataSource * @return * * @since 3.0.0.7 */ TableRowSWT getRowSWT(DATASOURCETYPE dataSource); Composite getTableComposite(); void initialize(Composite composite); /** * @param image * @param shellOffset * @return */ Image obfusticatedImage(Image image, Point shellOffset); /** * @param listener */ void removeKeyListener(KeyListener listener); /** * @param mainPanelCreator */ void setMainPanelCreator(TableViewSWTPanelCreator mainPanelCreator); /** * @param size */ void setRowDefaultIconSize(Point size); /** * @param coreTabViews */ void setCoreTabViews(IView[] coreTabViews); /** * @param x * @param y * @return * * @since 3.0.0.7 */ TableCellSWT getTableCell(int x, int y); /** * @return Offset potision of the cursor relative to the cell the cursor is in * * @since 3.0.4.3 */ Point getTableCellMouseOffset(TableCellSWT tableCell); /** * @param listener * * @since 3.1.1.1 */ void removeRefreshListener(TableRowRefreshListener listener); /** * @param listener * * @since 3.1.1.1 */ void addRefreshListener(TableRowRefreshListener listener); /** * @return * * @since 4.1.0.9 */ String getFilterText(); /** * @param filterCheck * * @since 4.1.0.9 */ void enableFilterCheck(Text txtFilter, TableViewFilterCheck filterCheck); /** * @param s * * @since 4.1.0.8 */ void setFilterText(String s); /** * @param composite * @param min * @param max * * @since 4.1.0.9 */ boolean enableSizeSlider(Composite composite, int min, int max); void disableSizeSlider(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/TableColumnCoreCreationListener.java0000644000175000017500000000225411135264370030714 0ustar adrianadrian/** * Created on Sep 20, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.views.table; import com.aelitis.azureus.ui.common.table.TableColumnCore; import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener; /** * @author TuxPaper * @created Sep 20, 2008 * */ public interface TableColumnCoreCreationListener extends TableColumnCreationListener { public TableColumnCore createTableColumnCore(Class forDataSourceType, String tableID, String columnID); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/TableCellSWT.java0000644000175000017500000000533211223221564024724 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.table; import org.eclipse.swt.graphics.*; import org.gudy.azureus2.ui.swt.components.BufferedTableItem; /** * SWT specific functions for Table Cells * * SWT cells are split into two logical sections: a BufferedTableItem that * handles the actual drawing, and this class' implementor, which handles * listeners, checking to see if things are right, buffering, etc. * * @author TuxPaper * @created Jan 22, 2007 * */ public interface TableCellSWT extends com.aelitis.azureus.ui.common.table.TableCellCore { /** * @return */ BufferedTableItem getBufferedTableItem(); /** * Change the cell's foreground color. * * NOTE: favor (R, G, B) * * @param color SWT Color object. * @return True - Color changed.
    * False - Color was already set. */ boolean setForeground(Color color); /** * @return */ Image getIcon(); /** * Set the cell's icon * * @param img Cell's new icon * @return true if the icon will be used */ public boolean setIcon(Image img); /** Paint the cell (for graphics) * * @param gc GC object to be used for painting */ public void doPaint(GC gc); public Point getSize(); public Rectangle getBounds(); public boolean setGraphic(Image img); public Image getGraphicSWT(); /** * @return */ public Image getBackgroundImage(); /** * @return */ Color getForegroundSWT(); /** * @return */ TableRowSWT getTableRowSWT(); /** * @return * * @since 3.0.3.4 */ Color getBackgroundSWT(); /** * @return * * @since 3.1.1.1 */ int getTextAlpha(); /** * @param textOpacity * * @since 3.1.1.1 */ void setTextAlpha(int textOpacity); /** * Sets tooltip to be shown in absence of an explicit one * @param str */ public void setDefaultToolTip( Object tt ); public Object getDefaultToolTip(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/utils/0000755000175000017500000000000011310377636023002 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnManager.java0000644000175000017500000004757311300377004027351 0ustar adrianadrian/* * File : TableColumnManager.java * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.table.utils; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.views.table.TableColumnCoreCreationListener; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.impl.TableColumnImpl; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadTypeComplete; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.tables.*; /** Holds a list of column definitions (TableColumnCore) for * all the tables in Azureus. * * Column definitions are added via * PluginInterface.addColumn(TableColumn) * See Use javadoc section for more uses. * * @author Oliver (Original Code) * @author TuxPaper (Modifications to make generic & comments) */ public class TableColumnManager { private static final String CONFIG_FILE = "tables.config"; private static TableColumnManager instance; private static AEMonitor class_mon = new AEMonitor( "TableColumnManager" ); /* Holds all the TableColumnCore objects. * key = TABLE_* type (see TableColumnCore) * value = Map: * key = column name * value = TableColumnCore object */ private Map items; private AEMonitor items_mon = new AEMonitor( "TableColumnManager:items" ); /** * Holds the order in which the columns are auto-hidden * * key = TABLE_* type * value = List of TableColumn, indexed in the order they should be removed */ private Map autoHideOrder = new LightHashMap(); /** * key = table; value = map of columns * * Do not access directly. Use {@link #getTableConfigMap(String)} * or {@link #saveTableConfigs()} */ private Map mapTablesConfig; private long lastTableConfigAccess; private static Comparator orderComparator; private Map mapColumnIDsToListener = new LightHashMap(); private Map mapDataSourceTypeToColumnIDs = new LightHashMap(); /** * key = TableID; value = table column ids */ private Map mapTableDefaultColumns = new LightHashMap(); static { orderComparator = new Comparator() { public int compare(Object arg0, Object arg1) { if ((arg1 instanceof TableColumn) && (arg0 instanceof TableColumn)) { int iPositionA = ((TableColumn) arg0).getPosition(); if (iPositionA < 0) iPositionA = 0xFFFF + iPositionA; int iPositionB = ((TableColumn) arg1).getPosition(); if (iPositionB < 0) iPositionB = 0xFFFF + iPositionB; return iPositionA - iPositionB; } return 0; } }; } private TableColumnManager() { items = new HashMap(); } /** Retrieve the static TableColumnManager instance * @return the static TableColumnManager instance */ public static TableColumnManager getInstance() { try{ class_mon.enter(); if(instance == null) instance = new TableColumnManager(); return instance; }finally{ class_mon.exit(); } } /** Adds a column definition to the list * @param item The column definition object */ public void addColumns(TableColumnCore[] itemsToAdd) { try { items_mon.enter(); for (int i = 0; i < itemsToAdd.length; i++) { TableColumnCore item = itemsToAdd[i]; if ( item.isRemoved()){ continue; } String name = item.getName(); String sTableID = item.getTableID(); Map mTypes = (Map) items.get(sTableID); if (mTypes == null) { // LinkedHashMap to preserve order mTypes = new LinkedHashMap(); items.put(sTableID, mTypes); } if (!mTypes.containsKey(name)) { mTypes.put(name, item); Map mapColumnConfig = getTableConfigMap(sTableID); ((TableColumnCore) item).loadSettings(mapColumnConfig); } if (!item.getColumnAdded()) { item.setColumnAdded(true); } } } catch (Exception e) { System.out.println("Error while adding Table Column Extension"); Debug.printStackTrace(e); } finally { items_mon.exit(); } } /** Adds a column definition to the list * @param item The column definition object */ public void removeColumns(TableColumnCore[] itemsToRemove) { try { items_mon.enter(); for (int i = 0; i < itemsToRemove.length; i++) { TableColumnCore item = itemsToRemove[i]; String name = item.getName(); String sTableID = item.getTableID(); Map mTypes = (Map) items.get(sTableID); if (mTypes != null) { if ( mTypes.remove(name) != null ){ } } } } catch (Exception e) { System.out.println("Error while adding Table Column Extension"); Debug.printStackTrace(e); } finally { items_mon.exit(); } } /** Retrieves TableColumnCore objects of a particular type. * @param sTableID TABLE_* constant. See {@link TableColumn} for list * of constants * @param forDataSourceType * * @return Map of column definition objects matching the supplied criteria. * key = name * value = TableColumnCore object */ public Map getTableColumnsAsMap( Class forDataSourceType, String sTableID) { //System.out.println("getTableColumnsAsMap(" + sTableID + ")"); try{ items_mon.enter(); Map mReturn = new LinkedHashMap(); Map mTypes = getAllTableColumnCore( forDataSourceType, sTableID); if (mTypes != null) { mReturn.putAll(mTypes); } //System.out.println("getTableColumnsAsMap(" + sTableID + ") returnsize: " + mReturn.size()); return mReturn; }finally{ items_mon.exit(); } } public int getTableColumnCount(String sTableID) { Map mTypes = (Map)items.get(sTableID); if (mTypes == null) { return 0; } return mTypes.size(); } public TableColumnCore[] getAllTableColumnCoreAsArray( Class forDataSourceType, String tableID) { Map mTypes = getAllTableColumnCore(forDataSourceType, tableID); return (TableColumnCore[]) mTypes.values().toArray( new TableColumnCore[mTypes.values().size()]); } public String[] getDefaultColumnNames(String tableID) { String[] columnNames = mapTableDefaultColumns.get(tableID); return columnNames; } public void setDefaultColumnNames(String tableID, String[] columnNames) { mapTableDefaultColumns.put(tableID, columnNames); } /* private Map getAllTableColumnCore( Class forDataSourceType, String tableID) { String[] dstColumnIDs = new String[0]; if (forDataSourceType != null) { List listDST = (List) mapDataSourceTypeToColumnIDs.get(forDataSourceType); if (listDST != null) { dstColumnIDs = (String[]) listDST.toArray(new String[0]); } if (forDataSourceType.equals(DownloadTypeComplete.class) || forDataSourceType.equals(DownloadTypeIncomplete.class)) { listDST = (List) mapDataSourceTypeToColumnIDs.get(Download.class); if (listDST != null && listDST.size() > 0) { String[] ids1 = (String[]) listDST.toArray(new String[0]); String[] ids2 = dstColumnIDs; dstColumnIDs = new String[ids2.length + ids1.length]; System.arraycopy(ids2, 0, dstColumnIDs, 0, ids2.length); System.arraycopy(ids1, 0, dstColumnIDs, ids2.length, ids1.length); } } else if (forDataSourceType.equals(Download.class)) { listDST = (List) mapDataSourceTypeToColumnIDs.get(DownloadTypeComplete.class); if (listDST != null && listDST.size() > 0) { String[] ids = (String[]) listDST.toArray(new String[listDST.size()]); dstColumnIDs = appendLists(ids, dstColumnIDs); } listDST = (List) mapDataSourceTypeToColumnIDs.get(DownloadTypeIncomplete.class); if (listDST != null && listDST.size() > 0) { String[] ids = (String[]) listDST.toArray(new String[listDST.size()]); dstColumnIDs = appendLists(ids, dstColumnIDs); } } } try { items_mon.enter(); Map mTypes = (Map) items.get(tableID); if (mTypes == null) { mTypes = new LinkedHashMap(); items.put(tableID, mTypes); } for (int i = 0; i < dstColumnIDs.length; i++) { String columnID = dstColumnIDs[i]; if (!mTypes.containsKey(columnID)) { try { TableColumnCreationListener l = mapColumnIDsToListener.get(forDataSourceType + "." + columnID); TableColumnCore tc = null; if (l instanceof TableColumnCoreCreationListener) { tc = ((TableColumnCoreCreationListener) l).createTableColumnCore( tableID, columnID); } if (tc == null) { tc = new TableColumnImpl(tableID, columnID); } l.tableColumnCreated(tc); addColumns(new TableColumnCore[] { tc }); } catch (Exception e) { Debug.out(e); } } } return mTypes; } finally { items_mon.exit(); } } */ /** * Will create columns for tableID if needed */ private Map getAllTableColumnCore( Class forDataSourceType, String tableID) { Map mTypes = null; try { items_mon.enter(); mTypes = (Map) items.get(tableID); if (mTypes == null) { mTypes = new LinkedHashMap(); items.put(tableID, mTypes); } if (forDataSourceType != null) { List listDST = (List) mapDataSourceTypeToColumnIDs.get(forDataSourceType); if (listDST != null) { doAddCreate(mTypes, forDataSourceType, tableID, listDST); } if (forDataSourceType.equals(DownloadTypeComplete.class) || forDataSourceType.equals(DownloadTypeIncomplete.class)) { listDST = (List) mapDataSourceTypeToColumnIDs.get(Download.class); if (listDST != null && listDST.size() > 0) { doAddCreate(mTypes, Download.class, tableID, listDST); } } else if (Download.class.equals(forDataSourceType)) { listDST = (List) mapDataSourceTypeToColumnIDs.get(DownloadTypeComplete.class); if (listDST != null && listDST.size() > 0) { doAddCreate(mTypes, DownloadTypeComplete.class, tableID, listDST); } listDST = (List) mapDataSourceTypeToColumnIDs.get(DownloadTypeIncomplete.class); if (listDST != null && listDST.size() > 0) { doAddCreate(mTypes, DownloadTypeIncomplete.class, tableID, listDST); } } } } finally { items_mon.exit(); } return mTypes; } /** * Helper for getAllTableColumnCore * @param types * @param listDST * * @since 4.0.0.5 */ private void doAddCreate(Map mTypes, Class forDataSourceType, String tableID, List listDST) { for (Iterator iter = listDST.iterator(); iter.hasNext();) { String columnID = (String) iter.next(); if (!mTypes.containsKey(columnID)) { try { TableColumnCreationListener l = mapColumnIDsToListener.get(forDataSourceType + "." + columnID); TableColumnCore tc = null; if (l instanceof TableColumnCoreCreationListener) { tc = ((TableColumnCoreCreationListener) l).createTableColumnCore( forDataSourceType, tableID, columnID); } if (tc == null) { tc = new TableColumnImpl(forDataSourceType, tableID, columnID); } if (l != null) { l.tableColumnCreated(tc); } addColumns(new TableColumnCore[] { tc }); } catch (Exception e) { Debug.out(e); } } } } public String[] getTableIDs() { try { items_mon.enter(); Set ids = items.keySet(); return( ids.toArray( new String[ids.size()])); } finally { items_mon.exit(); } } public String[] appendLists(String[] list1, String[] list2) { int size = list1.length + list2.length; String[] list = new String[size]; System.arraycopy(list1, 0, list, 0, list1.length); System.arraycopy(list2, 0, list, list1.length, list2.length); return list; } public TableColumnCore getTableColumnCore(String sTableID, String sColumnName) { Map mTypes = (Map)items.get(sTableID); if (mTypes == null) return null; return (TableColumnCore)mTypes.get(sColumnName); } public void ensureIntegrety(String sTableID) { Map mTypes = (Map)items.get(sTableID); if (mTypes == null) return; TableColumnCore[] tableColumns = (TableColumnCore[])mTypes.values().toArray(new TableColumnCore[mTypes.values().size()]); Arrays.sort(tableColumns, getTableColumnOrderComparator()); int iPos = 0; for (int i = 0; i < tableColumns.length; i++) { int iCurPos = tableColumns[i].getPosition(); if (iCurPos == TableColumnCore.POSITION_INVISIBLE) { tableColumns[i].setVisible(false); } else { tableColumns[i].setPositionNoShift(iPos++); } } } public String getDefaultSortColumnName(String tableID) { Map mapTableConfig = getTableConfigMap(tableID); Object object = mapTableConfig.get("SortColumn"); if( object instanceof byte[]) object = new String((byte[])object); if (object instanceof String) { return (String) object; } String s = COConfigurationManager.getStringParameter(tableID + ".sortColumn"); if (s != null) { COConfigurationManager.removeParameter(tableID + ".sortColumn"); COConfigurationManager.removeParameter(tableID + ".sortAsc"); } return s; } public void setDefaultSortColumnName(String tableID, String columnName) { Map mapTableConfig = getTableConfigMap(tableID); mapTableConfig.put("SortColumn", columnName); saveTableConfigs(); } private void saveTableConfigs() { if (mapTablesConfig != null) { FileUtil.writeResilientConfigFile(CONFIG_FILE, mapTablesConfig); } } /** Saves all the user configurable Table Column settings at once, complete * with a COConfigurationManager.save(). * * @param sTableID Table to save settings for */ public void saveTableColumns(Class forDataSourceType, String sTableID) { try { Map mapTableConfig = getTableConfigMap(sTableID); TableColumnCore[] tcs = getAllTableColumnCoreAsArray(forDataSourceType, sTableID); for (int i = 0; i < tcs.length; i++) { if (tcs[i] != null) tcs[i].saveSettings(mapTableConfig); } saveTableConfigs(); } catch (Exception e) { Debug.out(e); } } public boolean loadTableColumnSettings(Class forDataSourceType, String sTableID) { try { Map mapTableConfig = getTableConfigMap(sTableID); int size = mapTableConfig.size(); if (size == 0 || (size == 1 && mapTableConfig.containsKey("SortColumn"))) { return false; } TableColumnCore[] tcs = getAllTableColumnCoreAsArray(forDataSourceType, sTableID); for (int i = 0; i < tcs.length; i++) { if (tcs[i] != null) tcs[i].loadSettings(mapTableConfig); } } catch (Exception e) { Debug.out(e); } return true; } public Map getTableConfigMap(String sTableID) { synchronized (this) { lastTableConfigAccess = SystemTime.getMonotonousTime(); if (mapTablesConfig == null) { mapTablesConfig = FileUtil.readResilientConfigFile(CONFIG_FILE); // Dispose of tableconfigs after XXs.. saves up to 50k SimpleTimer.addEvent( "DisposeTbaleConfigMap", SystemTime.getOffsetTime(30000), new TimerEventPerformer() { public void perform( TimerEvent event ) { synchronized( TableColumnManager.this ){ long now = SystemTime.getMonotonousTime(); if ( now - lastTableConfigAccess > 25000 ){ mapTablesConfig = null; }else{ SimpleTimer.addEvent( "DisposeTbaleConfigMap", SystemTime.getOffsetTime(30000), this ); } } } }); } Map mapTableConfig = (Map) mapTablesConfig.get("Table." + sTableID); if (mapTableConfig == null) { mapTableConfig = new HashMap(); mapTablesConfig.put("Table." + sTableID, mapTableConfig); } return mapTableConfig; } } public void setAutoHideOrder(String sTableID, String[] autoHideOrderColumnIDs) { ArrayList autoHideOrderList = new ArrayList(autoHideOrderColumnIDs.length); for (int i = 0; i < autoHideOrderColumnIDs.length; i++) { String sColumnID = autoHideOrderColumnIDs[i]; TableColumnCore column = getTableColumnCore(sTableID, sColumnID); if (column != null) { autoHideOrderList.add(column); } } autoHideOrder.put(sTableID, autoHideOrderList); } public List getAutoHideOrder(String sTableID) { List list = (List) autoHideOrder.get(sTableID); if (list == null) { return Collections.EMPTY_LIST; } return list; } /** * @param writer */ public void generateDiagnostics(IndentWriter writer) { try{ items_mon.enter(); writer.println("TableColumns"); for (Iterator iter = items.keySet().iterator(); iter.hasNext();) { String sTableID = (String)iter.next(); Map mTypes = (Map)items.get(sTableID); writer.indent(); writer.println(sTableID + ": " + mTypes.size() + " columns:"); writer.indent(); for (Iterator iter2 = mTypes.values().iterator(); iter2.hasNext();) { TableColumnCore tc = (TableColumnCore)iter2.next(); tc.generateDiagnostics(writer); } writer.exdent(); writer.exdent(); } } catch (Exception e) { e.printStackTrace(); } finally { items_mon.exit(); } } public static Comparator getTableColumnOrderComparator() { return orderComparator; } /** * @param forDataSourceType * @param columnID * @param listener * * @since 3.1.1.1 */ public void registerColumn(Class forDataSourceType, String columnID, TableColumnCreationListener listener) { if (listener != null) { mapColumnIDsToListener.put(forDataSourceType + "." + columnID, listener); } try { items_mon.enter(); List list = (List) mapDataSourceTypeToColumnIDs.get(forDataSourceType); if (list == null) { list = new ArrayList(1); mapDataSourceTypeToColumnIDs.put(forDataSourceType, list); } if (!list.contains(columnID)) { list.add(columnID); } } finally { items_mon.exit(); } } public void unregisterColumn(Class forDataSourceType, String columnID, TableColumnCreationListener listener) { try { items_mon.enter(); mapColumnIDsToListener.remove(forDataSourceType + "." + columnID); List list = (List) mapDataSourceTypeToColumnIDs.get(forDataSourceType); if (list != null) { list.remove(columnID); } } finally { items_mon.exit(); } } public TableColumnInfo getColumnInfo(Class forDataSourceType, String forTableID, String columnID) { TableColumnCore column = getTableColumnCore(forTableID, columnID); TableColumnInfoImpl columnInfo = new TableColumnInfoImpl(column); List listeners = column.getColumnExtraInfoListeners(); for (TableColumnExtraInfoListener l : listeners) { l.fillTableColumnInfo(columnInfo); } if (columnInfo.getCategories() == null && !(column instanceof CoreTableColumn)) { columnInfo.addCategories(new String[] { "plugin" }); } return columnInfo; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/utils/CoreTableColumn.java0000644000175000017500000001261711135264370026665 0ustar adrianadrian/* * File : CoreTableColumn.java * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.table.utils; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import com.aelitis.azureus.ui.common.table.impl.TableColumnImpl; import org.gudy.azureus2.plugins.ui.tables.*; /** This class provides constructors for setting most of * the common column attributes and sets the column as a 'core' column.

    * * @author TuxPaper */ public abstract class CoreTableColumn extends TableColumnImpl implements TableColumnExtraInfoListener { /** Construct a new CoreTableColumn * Type will be TYPE_TEXT, Update Interval will be INTERVAL_INVALID_ONLY *

    * TableCell listeners (Added, Refresh, Dispose, ToolTip) are added based on * whether the class is an instance of them. * * @param sName Unique ID for column * @param iAlignment See {@link #getAlignment()} * @param iPosition See {@link TableColumn#setPosition(int)} * @param iWidth See {@link TableColumn#setWidth(int)} * @param sTableID See {@link TableManager}_TABLE* */ public CoreTableColumn(String sName, int iAlignment, int iPosition, int iWidth, String sTableID) { super(sTableID, sName); super.initialize(iAlignment, iPosition, iWidth); setUseCoreDataSource(true); addListeners(this); } public CoreTableColumn(Class forDataSourceType, String sName, int iAlignment, int iWidth, String sTableID) { super(forDataSourceType, sTableID, sName); super.initialize(iAlignment, POSITION_INVISIBLE, iWidth); setUseCoreDataSource(true); addListeners(this); } /** Construct a new CoreTableColumn.

    * Alignment will be ALIGN_LEAD, Type will be TYPE_TEXT, * Update Interval will be INTERVAL_INVALID_ONLY *

    * TableCell listeners (Added, Refresh, Dispose, ToolTip) are added based on * whether the class is an instance of them. * * @param sName Unique ID for column * @param iPosition See {@link TableColumn#setPosition(int)} * @param iWidth See {@link TableColumn#setWidth(int)} * @param sTableID See {@link TableManager}_TABLE* */ public CoreTableColumn(String sName, int iPosition, int iWidth, String sTableID) { super(sTableID, sName); setPosition(iPosition); setWidth(iWidth); setUseCoreDataSource(true); addListeners(this); } /** Construct a new CoreTableColumn.

    * Alignment will be ALIGN_LEAD, Type will be TYPE_TEXT, Position will be * POSITION_INVISIBLE, Update Interval will be INTERVAL_INVALID_ONLY *

    * TableCell listeners (Added, Refresh, Dispose, ToolTip) are added based on * whether the class is an instance of them. * * @param sName Unique ID for column * @param iWidth See {@link TableColumn#setWidth(int)} * @param sTableID See {@link TableManager}_TABLE* */ public CoreTableColumn(String sName, int iWidth, String sTableID) { super(sTableID, sName); setWidth(iWidth); setUseCoreDataSource(true); addListeners(this); } /** Construct a new CoreTableColumn.

    * Alignment will be ALIGN_LEAD, Type will be TYPE_TEXT, Position will be * POSITION_INVISIBLE, Width will be 50, Update Interval will be * INTERVAL_INVALID_ONLY *

    * TableCell listeners (Added, Refresh, Dispose, ToolTip) are added based on * whether the class is an instance of them. * * @param sName Unique ID for column * @param sTableID See {@link TableManager}_TABLE* */ public CoreTableColumn(String sName, String sTableID) { super(sTableID, sName); setUseCoreDataSource(true); addListeners(this); } public void initializeAsGraphic(int iWidth) { setWidth(iWidth); setType(TYPE_GRAPHIC); setRefreshInterval(INTERVAL_GRAPHIC); setAlignment(TableColumn.ALIGN_CENTER); } public void initializeAsGraphic(int iPosition, int iWidth) { setPosition(iPosition); setWidth(iWidth); setType(TYPE_GRAPHIC); setRefreshInterval(INTERVAL_GRAPHIC); setAlignment(TableColumn.ALIGN_CENTER); } // @see com.aelitis.azureus.ui.common.table.impl.TableColumnImpl#addListeners(java.lang.Object) public void addListeners(Object listenerObject) { if (listenerObject instanceof TableCellSWTPaintListener) { super.addCellOtherListener("SWTPaint", listenerObject); } super.addListeners(listenerObject); } // @see org.gudy.azureus2.plugins.ui.tables.TableColumnExtraInfoListener#fillTableColumnInfo(org.gudy.azureus2.plugins.ui.tables.TableColumnInfo) public void fillTableColumnInfo(TableColumnInfo info) { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnSWTUtils.java0000644000175000017500000000366011135264370027471 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.table.utils; import org.eclipse.swt.SWT; import org.gudy.azureus2.plugins.ui.tables.TableColumn; /** * @author TuxPaper * @created Dec 30, 2007 * */ public class TableColumnSWTUtils { public static int convertColumnAlignmentToSWT(int align) { int swt = 0; int hAlign = align & 3; if (hAlign == TableColumn.ALIGN_CENTER) { swt = SWT.CENTER; } else if (hAlign == TableColumn.ALIGN_LEAD) { swt = SWT.LEAD; } else if (hAlign == TableColumn.ALIGN_TRAIL) { swt = SWT.TRAIL; } else { swt = SWT.LEAD; } int vAlign = align & ~3; if (vAlign == TableColumn.ALIGN_TOP) { swt |= SWT.TOP; } else if (vAlign == TableColumn.ALIGN_BOTTOM) { swt |= SWT.BOTTOM; } return swt; } private static int convertSWTAlignmentToColumn(int align) { if ((align & SWT.LEAD) > 0) { return TableColumn.ALIGN_LEAD; } else if ((align & SWT.CENTER) > 0) { return TableColumn.ALIGN_CENTER; } else if ((align & SWT.RIGHT) > 0) { return TableColumn.ALIGN_TRAIL; } return TableColumn.ALIGN_LEAD; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnInfoImpl.java0000644000175000017500000000456311135264370027513 0ustar adrianadrian/** * Created on Jan 5, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.views.table.utils; import com.aelitis.azureus.ui.common.table.TableColumnCore; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * @author TuxPaper * @created Jan 5, 2009 * */ public class TableColumnInfoImpl implements TableColumnInfo { String[] categories; byte proficiency; private final TableColumnCore column; /** * @param column */ public TableColumnInfoImpl(TableColumnCore column) { this.column = column; } public TableColumnCore getColumn() { return column; } // @see org.gudy.azureus2.ui.swt.views.table.utils.TableColumnInfo#getCategories() public String[] getCategories() { return categories; } // @see org.gudy.azureus2.ui.swt.views.table.utils.TableColumnInfo#setCategories(java.lang.String[]) public void addCategories(String[] categories) { if (categories == null || categories.length == 0) { return; } int pos; String[] newCategories; if (this.categories == null) { newCategories = new String[categories.length]; pos = 0; } else { newCategories = new String[categories.length + this.categories.length]; pos = this.categories.length; System.arraycopy(this.categories, 0, newCategories, 0, pos); } System.arraycopy(categories, pos, newCategories, 0, categories.length); this.categories = newCategories; } // @see org.gudy.azureus2.ui.swt.views.table.utils.TableColumnInfo#getProficiency() public byte getProficiency() { return proficiency; } // @see org.gudy.azureus2.ui.swt.views.table.utils.TableColumnInfo#setProficiency(int) public void setProficiency(byte proficiency) { this.proficiency = proficiency; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/utils/TableContextMenuManager.java0000644000175000017500000000715410625407172030365 0ustar adrianadrian/* * File : TableContextMenuManager.java * Created : 2004/May/16 * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.table.utils; import java.util.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.ui.tables.*; /** * * @author TuxPaper * * XXX TODO TUX: This needs to be moved to common, and TableManagerImpl should * add to it instead of UISWTInstanceImpl * */ public class TableContextMenuManager { private static TableContextMenuManager instance; private static AEMonitor class_mon = new AEMonitor( "TableContextMenuManager" ); /* Holds all the TableContextMenu objects. * key = TABLE_* type (see TableColumn) * value = Map: * key = context menu key * value = TableContextMenu object */ private Map items; private AEMonitor items_mon = new AEMonitor( "TableContextMenuManager:items" ); private TableContextMenuManager() { items = new HashMap(); } /** Retrieve the static TableContextMenuManager instance * @return the static TableContextMenuManager instance */ public static TableContextMenuManager getInstance() { try{ class_mon.enter(); if (instance == null) instance = new TableContextMenuManager(); return instance; }finally{ class_mon.exit(); } } public void addContextMenuItem(TableContextMenuItem item) { try { String name = item.getResourceKey(); String sTableID = item.getTableID(); try{ items_mon.enter(); Map mTypes = (Map)items.get(sTableID); if (mTypes == null) { // LinkedHashMap to preserve order mTypes = new LinkedHashMap(); items.put(sTableID, mTypes); } mTypes.put(name, item); }finally{ items_mon.exit(); } } catch (Exception e) { System.out.println("Error while adding Context Table Menu Item"); Debug.printStackTrace( e ); } } public void removeContextMenuItem(TableContextMenuItem item) { Map menu_item_map = (Map)this.items.get(item.getTableID()); if (menu_item_map != null) {menu_item_map.remove(item.getResourceKey());} } public TableContextMenuItem[] getAllAsArray(String sMenuID) { Map local_menu_item_map = (Map)this.items.get(sMenuID); Map global_menu_item_map = (Map)this.items.get(null); if (local_menu_item_map == null && global_menu_item_map == null) { return new TableContextMenuItem[0]; } ArrayList l = new ArrayList(); if (local_menu_item_map != null) {l.addAll(local_menu_item_map.values());} if (global_menu_item_map != null) {l.addAll(global_menu_item_map.values());} return (TableContextMenuItem[]) l.toArray(new TableContextMenuItem[l.size()]); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnCreator.java0000644000175000017500000002633611271456442027403 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.table.utils; import java.lang.reflect.Constructor; import java.util.Iterator; import java.util.Map; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.LightHashMap; import org.gudy.azureus2.plugins.download.DownloadTypeComplete; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import org.gudy.azureus2.ui.swt.views.columnsetup.ColumnTC_ChosenColumn; import org.gudy.azureus2.ui.swt.views.columnsetup.ColumnTC_NameInfo; import org.gudy.azureus2.ui.swt.views.columnsetup.ColumnTC_Sample; import org.gudy.azureus2.ui.swt.views.table.TableColumnCoreCreationListener; import org.gudy.azureus2.ui.swt.views.tableitems.mytorrents.*; import com.aelitis.azureus.ui.common.table.TableColumnCore; /** * @author TuxPaper * @created Dec 19, 2007 * */ public class TableColumnCreator { public static int DATE_COLUMN_WIDTH = 110; public static TableColumnCore[] createIncompleteDM(String tableID) { final String[] defaultVisibleOrder = { HealthItem.COLUMN_ID, RankItem.COLUMN_ID, NameItem.COLUMN_ID, "azsubs.ui.column.subs", "Info", CommentIconItem.COLUMN_ID, SizeItem.COLUMN_ID, DownItem.COLUMN_ID, DoneItem.COLUMN_ID, StatusItem.COLUMN_ID, SeedsItem.COLUMN_ID, PeersItem.COLUMN_ID, DownSpeedItem.COLUMN_ID, UpSpeedItem.COLUMN_ID, ETAItem.COLUMN_ID, ShareRatioItem.COLUMN_ID, TrackerStatusItem.COLUMN_ID, }; TableColumnManager tcManager = TableColumnManager.getInstance(); Map mapTCs = tcManager.getTableColumnsAsMap(DownloadTypeIncomplete.class, tableID); tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder); if (!tcManager.loadTableColumnSettings(DownloadTypeIncomplete.class, tableID) || areNoneVisible(mapTCs)) { setVisibility(mapTCs, defaultVisibleOrder); RankItem tc = (RankItem) mapTCs.get(RankItem.COLUMN_ID); if (tc != null) { tcManager.setDefaultSortColumnName(tableID, RankItem.COLUMN_ID); tc.setSortAscending(true); } } return (TableColumnCore[]) mapTCs.values().toArray(new TableColumnCore[0]); } public static TableColumnCore[] createCompleteDM(String tableID) { final String[] defaultVisibleOrder = { HealthItem.COLUMN_ID, RankItem.COLUMN_ID, "SeedingRank", NameItem.COLUMN_ID, "azsubs.ui.column.subs", "Info", "RateIt", CommentIconItem.COLUMN_ID, SizeItem.COLUMN_ID, StatusItem.COLUMN_ID, SeedsItem.COLUMN_ID, PeersItem.COLUMN_ID, UpSpeedItem.COLUMN_ID, ShareRatioItem.COLUMN_ID, UpItem.COLUMN_ID, TrackerStatusItem.COLUMN_ID, }; TableColumnManager tcManager = TableColumnManager.getInstance(); Map mapTCs = tcManager.getTableColumnsAsMap(DownloadTypeComplete.class, tableID); tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder); if (!tcManager.loadTableColumnSettings(DownloadTypeComplete.class, tableID) || areNoneVisible(mapTCs)) { setVisibility(mapTCs, defaultVisibleOrder); RankItem tc = (RankItem) mapTCs.get(RankItem.COLUMN_ID); if (tc != null) { tcManager.setDefaultSortColumnName(tableID, RankItem.COLUMN_ID); tc.setSortAscending(true); } } return (TableColumnCore[]) mapTCs.values().toArray(new TableColumnCore[0]); } private static boolean areNoneVisible(Map mapTCs) { boolean noneVisible = true; for (Iterator iter = mapTCs.values().iterator(); iter.hasNext();) { TableColumn tc = (TableColumn) iter.next(); if (tc.isVisible()) { noneVisible = false; break; } } return noneVisible; } private static void setVisibility(Map mapTCs, String[] defaultVisibleOrder) { for (Iterator iter = mapTCs.values().iterator(); iter.hasNext();) { TableColumnCore tc = (TableColumnCore) iter.next(); tc.setVisible(false); } for (int i = 0; i < defaultVisibleOrder.length; i++) { String id = defaultVisibleOrder[i]; TableColumnCore tc = (TableColumnCore) mapTCs.get(id); if (tc != null) { tc.setVisible(true); tc.setPositionNoShift(i); } } } /** * * * @since 3.1.1.1 */ public static void initCoreColumns() { // short variable names to reduce wrapping final Map c = new LightHashMap(50); final Class tc = TableColumn.class; c.put(RankItem.COLUMN_ID, new cInfo(RankItem.class, RankItem.DATASOURCE_TYPE)); c.put(NameItem.COLUMN_ID, new cInfo(NameItem.class, NameItem.DATASOURCE_TYPE)); c.put(SizeItem.COLUMN_ID, new cInfo(SizeItem.class, SizeItem.DATASOURCE_TYPE)); c.put(DoneItem.COLUMN_ID, new cInfo(DoneItem.class, DoneItem.DATASOURCE_TYPE)); c.put(StatusItem.COLUMN_ID, new cInfo(StatusItem.class, StatusItem.DATASOURCE_TYPE)); c.put(ETAItem.COLUMN_ID, new cInfo(ETAItem.class, ETAItem.DATASOURCE_TYPE)); c.put(HealthItem.COLUMN_ID, new cInfo(HealthItem.class, HealthItem.DATASOURCE_TYPE)); c.put(CommentIconItem.COLUMN_ID, new cInfo(CommentIconItem.class, CommentIconItem.DATASOURCE_TYPE)); c.put(DownItem.COLUMN_ID, new cInfo(DownItem.class, DownItem.DATASOURCE_TYPE)); c.put(SeedsItem.COLUMN_ID, new cInfo(SeedsItem.class, SeedsItem.DATASOURCE_TYPE)); c.put(PeersItem.COLUMN_ID, new cInfo(PeersItem.class, PeersItem.DATASOURCE_TYPE)); c.put(DownSpeedItem.COLUMN_ID, new cInfo(DownSpeedItem.class, DownSpeedItem.DATASOURCE_TYPE)); c.put(UpSpeedItem.COLUMN_ID, new cInfo(UpSpeedItem.class, UpSpeedItem.DATASOURCE_TYPE)); c.put(UpSpeedLimitItem.COLUMN_ID, new cInfo(UpSpeedLimitItem.class, UpSpeedLimitItem.DATASOURCE_TYPE)); c.put(TrackerStatusItem.COLUMN_ID, new cInfo(TrackerStatusItem.class, TrackerStatusItem.DATASOURCE_TYPE)); c.put(CompletedItem.COLUMN_ID, new cInfo(CompletedItem.class, CompletedItem.DATASOURCE_TYPE)); c.put(ShareRatioItem.COLUMN_ID, new cInfo(ShareRatioItem.class, ShareRatioItem.DATASOURCE_TYPE)); c.put(UpItem.COLUMN_ID, new cInfo(UpItem.class, UpItem.DATASOURCE_TYPE)); c.put(RemainingItem.COLUMN_ID, new cInfo(RemainingItem.class, RemainingItem.DATASOURCE_TYPE)); c.put(PiecesItem.COLUMN_ID, new cInfo(PiecesItem.class, PiecesItem.DATASOURCE_TYPE)); c.put(CompletionItem.COLUMN_ID, new cInfo(CompletionItem.class, CompletionItem.DATASOURCE_TYPE)); c.put(CommentItem.COLUMN_ID, new cInfo(CommentItem.class, CommentItem.DATASOURCE_TYPE)); c.put(MaxUploadsItem.COLUMN_ID, new cInfo(MaxUploadsItem.class, MaxUploadsItem.DATASOURCE_TYPE)); c.put(TotalSpeedItem.COLUMN_ID, new cInfo(TotalSpeedItem.class, TotalSpeedItem.DATASOURCE_TYPE)); c.put(FilesDoneItem.COLUMN_ID, new cInfo(FilesDoneItem.class, FilesDoneItem.DATASOURCE_TYPE)); c.put(SavePathItem.COLUMN_ID, new cInfo(SavePathItem.class, SavePathItem.DATASOURCE_TYPE)); c.put(TorrentPathItem.COLUMN_ID, new cInfo(TorrentPathItem.class, TorrentPathItem.DATASOURCE_TYPE)); c.put(CategoryItem.COLUMN_ID, new cInfo(CategoryItem.class, CategoryItem.DATASOURCE_TYPE)); c.put(NetworksItem.COLUMN_ID, new cInfo(NetworksItem.class, NetworksItem.DATASOURCE_TYPE)); c.put(PeerSourcesItem.COLUMN_ID, new cInfo(PeerSourcesItem.class, PeerSourcesItem.DATASOURCE_TYPE)); c.put(AvailabilityItem.COLUMN_ID, new cInfo(AvailabilityItem.class, AvailabilityItem.DATASOURCE_TYPE)); c.put(AvgAvailItem.COLUMN_ID, new cInfo(AvgAvailItem.class, AvgAvailItem.DATASOURCE_TYPE)); c.put(SecondsSeedingItem.COLUMN_ID, new cInfo(SecondsSeedingItem.class, SecondsSeedingItem.DATASOURCE_TYPE)); c.put(SecondsDownloadingItem.COLUMN_ID, new cInfo(SecondsDownloadingItem.class, SecondsDownloadingItem.DATASOURCE_TYPE)); c.put(TimeSinceDownloadItem.COLUMN_ID, new cInfo(TimeSinceDownloadItem.class, TimeSinceDownloadItem.DATASOURCE_TYPE)); c.put(TimeSinceUploadItem.COLUMN_ID, new cInfo(TimeSinceUploadItem.class, TimeSinceUploadItem.DATASOURCE_TYPE)); c.put(OnlyCDing4Item.COLUMN_ID, new cInfo(OnlyCDing4Item.class, OnlyCDing4Item.DATASOURCE_TYPE)); c.put(TrackerNextAccessItem.COLUMN_ID, new cInfo(TrackerNextAccessItem.class, TrackerNextAccessItem.DATASOURCE_TYPE)); c.put(TrackerNameItem.COLUMN_ID, new cInfo(TrackerNameItem.class, TrackerNameItem.DATASOURCE_TYPE)); c.put(SeedToPeerRatioItem.COLUMN_ID, new cInfo(SeedToPeerRatioItem.class, SeedToPeerRatioItem.DATASOURCE_TYPE)); c.put(DownSpeedLimitItem.COLUMN_ID, new cInfo(DownSpeedLimitItem.class, DownSpeedLimitItem.DATASOURCE_TYPE)); c.put(SwarmAverageSpeed.COLUMN_ID, new cInfo(SwarmAverageSpeed.class, SwarmAverageSpeed.DATASOURCE_TYPE)); c.put(SwarmAverageCompletion.COLUMN_ID, new cInfo(SwarmAverageCompletion.class, SwarmAverageCompletion.DATASOURCE_TYPE)); c.put(BadAvailTimeItem.COLUMN_ID, new cInfo(BadAvailTimeItem.class, BadAvailTimeItem.DATASOURCE_TYPE)); c.put(DateCompletedItem.COLUMN_ID, new cInfo(DateCompletedItem.class, DateCompletedItem.DATASOURCE_TYPE)); c.put(DateAddedItem.COLUMN_ID, new cInfo(DateAddedItem.class, DateAddedItem.DATASOURCE_TYPE)); c.put(ColumnTC_NameInfo.COLUMN_ID, new cInfo(ColumnTC_NameInfo.class, tc)); c.put(ColumnTC_Sample.COLUMN_ID, new cInfo(ColumnTC_Sample.class, tc)); c.put(ColumnTC_ChosenColumn.COLUMN_ID, new cInfo(ColumnTC_ChosenColumn.class, tc)); // Core columns are implementors of TableColumn to save one class creation // Otherwise, we'd have to create a generic TableColumnImpl class, pass it // to another class so that it could manipulate it and act upon changes. TableColumnManager tcManager = TableColumnManager.getInstance(); TableColumnCoreCreationListener tcCreator = new TableColumnCoreCreationListener() { // @see org.gudy.azureus2.ui.swt.views.table.TableColumnCoreCreationListener#createTableColumnCore(java.lang.Class, java.lang.String, java.lang.String) public TableColumnCore createTableColumnCore(Class forDataSourceType, String tableID, String columnID) { cInfo info = (cInfo) c.get(columnID); try { Constructor constructor = info.cla.getDeclaredConstructor(new Class[] { String.class }); TableColumnCore column = (TableColumnCore) constructor.newInstance(new Object[] { tableID }); return column; } catch (Exception e) { Debug.out(e); } return null; } public void tableColumnCreated(TableColumn column) { } }; for (Iterator iter = c.keySet().iterator(); iter.hasNext();) { String id = (String) iter.next(); cInfo info = (cInfo) c.get(id); tcManager.registerColumn(info.forDataSourceType, id, tcCreator); } } private static class cInfo { public Class cla; public Class forDataSourceType; public cInfo(Class cla, Class forDataSourceType) { this.cla = cla; this.forDataSourceType = forDataSourceType; } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/table/TableViewSWTMenuFillListener.java0000644000175000017500000000277511232522032030123 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.table; import org.eclipse.swt.widgets.Menu; /** * @author TuxPaper * @created Feb 2, 2007 * */ public interface TableViewSWTMenuFillListener { public void fillMenu(String sColumnName, Menu menu); /** * Create a SubMenu for column specific tasks. Everytime the user opens * the context menu, the "This Column" submenu is cleared, and this function * is called to refill it. * * @param sColumnName The name of the column the user clicked on * @param menuThisColumn the menu to fill with MenuItems */ public void addThisColumnSubMenu(String sColumnName, Menu menuThisColumn); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/DetailedListView.java0000644000175000017500000002470611074567436024637 0ustar adrianadrian/* * Created on 30 Jun 2008 * Created by Allan Crooks * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.ui.swt.views; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.ui.swt.debug.ObfusticateImage; import org.gudy.azureus2.ui.swt.plugins.UISWTView; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.ui.common.table.*; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; /** * @author MjrTom * 2005/Dec/08: Avg Avail Item */ public class DetailedListView extends AbstractIView implements ObfusticateImage, IViewExtension { private static int SASH_WIDTH = 8; final static TableColumnCore[] tableIncompleteItems = TableColumnCreator.createIncompleteDM(TableManager.TABLE_MYTORRENTS_INCOMPLETE); private AzureusCore azureus_core; private MyTorrentsView torrentview; private UISWTViewImpl managerview; private Composite managerview_parent; private Composite form; private MyTorrentsView lastSelectedView; public DetailedListView(AzureusCore _azureus_core) { azureus_core = _azureus_core; TableColumnManager tcManager = TableColumnManager.getInstance(); tcManager.addColumns(tableIncompleteItems); } public Composite getComposite() { return form; } public void delete() { if (torrentview != null) torrentview.delete(); super.delete(); } public void initialize(Composite parent) { if (form != null) { return; } form = new Composite(parent, SWT.NONE); FormLayout flayout = new FormLayout(); flayout.marginHeight = 0; flayout.marginWidth = 0; form.setLayout(flayout); GridData gridData; gridData = new GridData(GridData.FILL_BOTH); form.setLayoutData(gridData); GridLayout layout; final Composite child1 = new Composite(form,SWT.NULL); layout = new GridLayout(); layout.numColumns = 1; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; child1.setLayout(layout); torrentview = new MyTorrentsView(azureus_core, "DetailedTorrentList", false, tableIncompleteItems); torrentview.initialize(child1); torrentview.getTableView().addSelectionListener(new TableSelectionAdapter() { public void selected(TableRowCore[] rows) { try { DownloadManager[] dms = new DownloadManager[rows.length]; for (int i=0; i 10000) { weight = 10000; } else if (weight < 100) { weight *= 100; } // Min/max of 5%/95% if (weight < 500) { weight = 500; } else if (weight > 9000) { weight = 9000; } // height will be set on first resize call sash.setData("PCT", new Double((float)weight / 10000)); child2.setLayoutData(formData); // Listeners to size the folder sash.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { final boolean FASTDRAG = true; if (FASTDRAG && e.detail == SWT.DRAG) return; child1Data.height = e.y + e.height - SASH_WIDTH; form.layout(); Double l = new Double((double) child1.getBounds().height / form.getBounds().height); sash.setData("PCT", l); if (e.detail != SWT.DRAG) COConfigurationManager.setParameter("DetailedList.SplitAt", (int) (l .doubleValue() * 10000)); } }); form.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { Double l = (Double) sash.getData("PCT"); if (l != null) { child1Data.height = (int) (form.getBounds().height * l .doubleValue()); form.layout(); } } }); } public void refresh() { if (getComposite() == null || getComposite().isDisposed()) return; torrentview.refresh(); } public void updateLanguage() { // no super call, the views will do their own if (getComposite() == null || getComposite().isDisposed()) return; torrentview.updateLanguage(); } public String getFullTitle() { return MessageText.getString("DetailedListView.title"); } // XXX: Is there an easier way to find out what has the focus? private MyTorrentsView getCurrentView() { // wrap in a try, since the controls may be disposed try { if (torrentview.isTableFocus()) lastSelectedView = torrentview; } catch (Exception ignore) {/*ignore*/} return lastSelectedView; } // IconBarEnabler public boolean isEnabled(String itemKey) { IView currentView = getCurrentView(); if (currentView != null) return currentView.isEnabled(itemKey); else return false; } // IconBarEnabler // @see org.gudy.azureus2.ui.swt.views.AbstractIView#itemActivated(java.lang.String) public void itemActivated(String itemKey) { IView currentView = getCurrentView(); if (currentView != null) currentView.itemActivated(itemKey); } public String getIconBarPluginIdentity() {return "torrents";} public Object[] getIconBarPluginContextData() { DownloadManager[] dms = getSelectedDownloads(); if (dms == null) {return null;} Download[] res = new Download[dms.length]; for (int i=0; i= 3138 && antiAliasingAvailable) { try { //gcBuffer.setTextAntialias(SWT.ON); //gcBuffer.setAntialias(SWT.ON); } catch(Exception e) { antiAliasingAvailable = false; } } gcBuffer.setBackground(Colors.blues[Colors.BLUES_MIDLIGHT]); int nbPeers = sortedPeers.length; int iAngle = 0; double currentPerimeter = 0; double angle,r; for(int i = 0 ; i < nbPeers ; i++) { PEPeer peer = sortedPeers[i]; do { angle = angles[iAngle]; r = rs[iAngle]; currentPerimeter += r; if(iAngle + 1 < NB_ANGLES) iAngle++; } while( currentPerimeter < i * perimeter / nbPeers); angle = (4 * i - nbPeers) * Math.PI / (2 * nbPeers) - Math.PI / 2; int[] rectangle = new int[8]; if(! peer.isChokedByMe() || ! peer.isChokingMe()) { gcBuffer.setForeground(Colors.blues[Colors.BLUES_MIDLIGHT]); int x1 = x0 + (int) ( r * deltaYXs[iAngle] ); int y1 = y0 + (int) ( r * deltaYYs[iAngle] ); gcBuffer.drawLine(x0,y0,x1,y1); /* rectangle[0] = x0 + (int) (deltaXXs[iAngle] * 3 + 0.5); rectangle[1] = y0 + (int) (deltaXYs[iAngle] * 3 + 0.5); rectangle[2] = x0 - (int) (deltaXXs[iAngle] * 3 + 0.5); rectangle[3] = y0 - (int) (deltaXYs[iAngle] * 3 + 0.5); rectangle[4] = x0 - (int) (deltaXXs[iAngle] * 3 - r * deltaYXs[iAngle]+ 0.5); rectangle[5] = y0 - (int) (deltaXYs[iAngle] * 3 - r * deltaYYs[iAngle] + 0.5); rectangle[6] = x0 + (int) (deltaXXs[iAngle] * 3 + r * deltaYXs[iAngle] + 0.5); rectangle[7] = y0 + (int) (deltaXYs[iAngle] * 3 + r * deltaYYs[iAngle] + 0.5); gcBuffer.drawPolygon(rectangle); */ } int percentSent = peer.getPercentDoneOfCurrentIncomingRequest(); if(percentSent >= 0) { gcBuffer.setBackground(Colors.blues[Colors.BLUES_MIDDARK]); double r1 = r - r * percentSent / 100; rectangle[0] = (int) (x0 + r1 * deltaYXs[iAngle] + 0.5); rectangle[1] = (int) (y0 + r1 * deltaYYs[iAngle] + 0.5); rectangle[2] = (int) (x0 + deltaXXs[iAngle] * 4 + r1 * deltaYXs[iAngle] + 0.5); rectangle[3] = (int) (y0 + deltaXYs[iAngle] * 4 + r1 * deltaYYs[iAngle] + 0.5); rectangle[4] = (int) (x0 + deltaXXs[iAngle] * 4 + (r1-10) * deltaYXs[iAngle] + 0.5); rectangle[5] = (int) (y0 + deltaXYs[iAngle] * 4 + (r1-10) * deltaYYs[iAngle] + 0.5); rectangle[6] = (int) (x0 + (r1-10) * deltaYXs[iAngle] + 0.5); rectangle[7] = (int) (y0 + (r1-10) * deltaYYs[iAngle] + 0.5); gcBuffer.fillPolygon(rectangle); } percentSent = peer.getPercentDoneOfCurrentOutgoingRequest(); if(percentSent >= 0) { gcBuffer.setBackground(Colors.blues[Colors.BLUES_MIDLIGHT]); double r1 = r * percentSent / 100; rectangle[0] = (int) (x0 + r1 * deltaYXs[iAngle] + 0.5); rectangle[1] = (int) (y0 + r1 * deltaYYs[iAngle] + 0.5); rectangle[2] = (int) (x0 - deltaXXs[iAngle] * 4 + r1 * deltaYXs[iAngle] + 0.5); rectangle[3] = (int) (y0 - deltaXYs[iAngle] * 4 + r1 * deltaYYs[iAngle] + 0.5); rectangle[4] = (int) (x0 - deltaXXs[iAngle] * 4 + (r1-10) * deltaYXs[iAngle] + 0.5); rectangle[5] = (int) (y0 - deltaXYs[iAngle] * 4 + (r1-10) * deltaYYs[iAngle] + 0.5); rectangle[6] = (int) (x0 + (r1-10) * deltaYXs[iAngle] + 0.5); rectangle[7] = (int) (y0 + (r1-10) * deltaYYs[iAngle] + 0.5); gcBuffer.fillPolygon(rectangle); } int x1 = x0 + (int) (r * deltaYXs[iAngle]); int y1 = y0 + (int) (r * deltaYYs[iAngle]); gcBuffer.setBackground(Colors.blues[Colors.BLUES_MIDDARK]); if(peer.isSnubbed()) { gcBuffer.setBackground(Colors.grey); } /*int PS = (int) (PEER_SIZE); if (deltaXY == 0) { PS = (int) (PEER_SIZE * 2); } else { if (deltaYY > 0) { PS = (int) (PEER_SIZE / deltaXY); } }*/ //PieUtils.drawPie(gcBuffer,(x1 - PS / 2),y1 - PS / 2,PS,PS,peer.getPercentDoneInThousandNotation() / 10); PieUtils.drawPie(gcBuffer,x1 - PEER_SIZE / 2,y1 - PEER_SIZE / 2,PEER_SIZE,PEER_SIZE,peer.getPercentDoneInThousandNotation() / 10); //gcBuffer.drawText(peer.getIp() , x1 + 8 , y1 , true); } gcBuffer.setBackground(Colors.blues[Colors.BLUES_MIDDARK]); PieUtils.drawPie(gcBuffer,x0 - OWN_SIZE / 2 ,y0 - OWN_SIZE / 2,OWN_SIZE,OWN_SIZE,manager.getStats().getCompleted() / 10); gcBuffer.dispose(); GC gcPanel = new GC(panel); gcPanel.drawImage(buffer,0,0); gcPanel.dispose(); buffer.dispose(); } public void peerManagerWillBeAdded( PEPeerManager peer_manager ){} public void peerManagerAdded(PEPeerManager manager) {} public void peerManagerRemoved(PEPeerManager manager) {} public void peerAdded(PEPeer peer) { try { peers_mon.enter(); peers.add(peer); } finally { peers_mon.exit(); } } public void peerRemoved(PEPeer peer) { try { peers_mon.enter(); peers.remove(peer); } finally { peers_mon.exit(); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/AbstractIView.java0000644000175000017500000000771410742011064024122 0ustar adrianadrian/* * Created on 29 juin 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.ui.swt.Messages; /** * @author Ren * */ // XXX This class is used by plugins. Don't remove any functions from it! public abstract class AbstractIView implements IView { // XXX AEMonitor introduced to plugin interface.. protected AEMonitor this_mon = new AEMonitor( "AbstractIView" ); private String lastFullTitleKey = null; private String lastFullTitle = ""; public void initialize(Composite composite){ } public Composite getComposite(){ return null; } public void refresh(){} /** * A basic implementation that disposes the composite * Should be called with super.delete() from any extending class. * Images, Colors and such SWT handles must be disposed by the class itself. */ public void delete(){ Composite comp = getComposite(); if (comp != null && !comp.isDisposed()) comp.dispose(); } public String getData(){ return null; } /** * Called in order to set / update the title of this View. When the view * is being displayed in a tab, the full title is used for the tooltip. * * By default, this function will return text from the message bundles which * correspond to the key returned in #getData() * * @return the full title for the view */ public String getFullTitle() { String key = getData(); if (key == null) { return ""; } if ( lastFullTitle.length() > 0 && key.equals(lastFullTitleKey)) { return lastFullTitle; } lastFullTitleKey = key; if (MessageText.keyExists(key)) { lastFullTitle = MessageText.getString(key); } else { lastFullTitle = key.replace('.', ' '); // support old plugins } return lastFullTitle; } /** * Called in order to set / update the short title of this view. When the * view is being displayed in a tab, the short title is used for the tab's * text. * * By default, this function will return the full title. If the full title * is over 30 characters, it will be trimmed and "..." will be added * * @return A short title for the view */ public final String getShortTitle() { String shortTitle = getFullTitle(); if(shortTitle != null && shortTitle.length() > 30) { shortTitle = shortTitle.substring(0,30) + "..."; } return shortTitle; } public void updateLanguage() { lastFullTitle = ""; Messages.updateLanguageForControl(getComposite()); } // IconBarEnabler public boolean isEnabled(String itemKey) { return false; } // IconBarEnabler public boolean isSelected(String itemKey) { return false; } // IconBarEnabler public void itemActivated(String itemKey) { } public void generateDiagnostics( IndentWriter writer ) { writer.println( "Diagnostics for " + this + " (" + getFullTitle()+ ")"); } public void dataSourceChanged(Object newDataSource) { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/clientstats/0000755000175000017500000000000011310377636023110 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_ReceivedPer.java0000644000175000017500000000165611304737530027717 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.clientstats; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumn; public class ColumnCS_ReceivedPer implements TableCellRefreshListener { public static final String COLUMN_ID = "received.per"; public ColumnCS_ReceivedPer(TableColumn column) { column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 80); column.addListeners(this); column.setType(TableColumn.TYPE_TEXT_ONLY); } public void refresh(TableCell cell) { ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource(); if (ds == null) { return; } long val = ds.bytesReceived / ds.count; if (cell.setSortValue(val) || !cell.isValid()) { cell.setText(DisplayFormatters.formatByteCountToKiBEtc(val)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Pct.java0000644000175000017500000000174411273607610026246 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.clientstats; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumn; public class ColumnCS_Pct implements TableCellRefreshListener { public static final String COLUMN_ID = "percent"; public ColumnCS_Pct(TableColumn column) { column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 50); column.addListeners(this); column.setType(TableColumn.TYPE_TEXT_ONLY); column.setRefreshInterval(TableColumn.INTERVAL_LIVE); } public void refresh(TableCell cell) { ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource(); if (ds == null) { return; } float val = ds.count * 1000f / ds.overall.count; if (cell.setSortValue(val) || !cell.isValid()) { cell.setText(DisplayFormatters.formatPercentFromThousands((int) val)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Received.java0000644000175000017500000000163111273607610027241 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.clientstats; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumn; public class ColumnCS_Received implements TableCellRefreshListener { public static final String COLUMN_ID = "received"; public ColumnCS_Received(TableColumn column) { column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 80); column.addListeners(this); column.setType(TableColumn.TYPE_TEXT_ONLY); } public void refresh(TableCell cell) { ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource(); if (ds == null) { return; } long val = ds.bytesReceived; if (cell.setSortValue(val) || !cell.isValid()) { cell.setText(DisplayFormatters.formatByteCountToKiBEtc(val)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Name.java0000644000175000017500000000133311273607610026372 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.clientstats; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumn; public class ColumnCS_Name implements TableCellRefreshListener { public static final String COLUMN_ID = "name"; public ColumnCS_Name(TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 215); column.addListeners(this); column.setType(TableColumn.TYPE_TEXT_ONLY); } public void refresh(TableCell cell) { ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource(); if (ds == null) { return; } cell.setText(ds.client); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsView.java0000644000175000017500000004552511305071650027045 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.clientstats; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.SimpleDateFormat; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.download.*; import org.gudy.azureus2.core3.global.GlobalManagerListener; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerListener; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.core.util.bloom.BloomFilterFactory; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.TableLifeCycleListener; import com.aelitis.azureus.ui.common.table.TableRowCore; import com.aelitis.azureus.util.MapUtils; public class ClientStatsView extends TableViewTab implements TableLifeCycleListener, GlobalManagerListener, DownloadManagerPeerListener { private static final String CONFIG_FILE = "ClientStats.dat"; private static final String CONFIG_FILE_ARCHIVE = "ClientStats_%1.dat"; private static final int BLOOMFILTER_SIZE = 100000; private static final int BLOOMFILTER_PEERID_SIZE = 50000; private static final String TABLEID = "ClientStats"; private AzureusCore core; private TableViewSWTImpl tv; private boolean columnsAdded; private Map mapData; private Composite parent; private BloomFilter bloomFilter; private BloomFilter bloomFilterPeerId; private ClientStatsOverall overall; private long startedListeningOn; private long totalTime; private long lastAdd; private GregorianCalendar calendar = new GregorianCalendar(); private int lastAddMonth; public ClientStatsView() { super("ClientStats"); initAndLoad(); AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { initColumns(core); } }); } public Composite initComposite(Composite composite) { parent = new Composite(composite, SWT.BORDER); parent.setLayout(new FormLayout()); Layout layout = composite.getLayout(); if (layout instanceof GridLayout) { parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); } else if (layout instanceof FormLayout) { parent.setLayoutData(Utils.getFilledFormData()); } return parent; } public void tableViewTabInitComplete() { Composite cTV = (Composite) parent.getChildren()[0]; Composite cBottom = new Composite(parent, SWT.None); FormData fd; fd = Utils.getFilledFormData(); fd.bottom = new FormAttachment(cBottom); cTV.setLayoutData(fd); fd = Utils.getFilledFormData(); fd.top = null; cBottom.setLayoutData(fd); cBottom.setLayout(new FormLayout()); Button btnCopy = new Button(cBottom, SWT.PUSH); btnCopy.setLayoutData(new FormData()); btnCopy.setText("Copy"); btnCopy.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { TableRowCore[] rows = tv.getRows(); StringBuilder sb = new StringBuilder(); sb.append(new SimpleDateFormat("MMM yyyy").format(new Date())); sb.append("\n"); sb.append("Hits,Client,Bytes Sent,Bytes Received,Bad Bytes\n"); for (TableRowCore row : rows) { ClientStatsDataSource stat = (ClientStatsDataSource) row.getDataSource(); if (stat == null) { continue; } sb.append(stat.count); sb.append(","); sb.append(stat.client.replaceAll(",", "")); sb.append(","); sb.append(stat.bytesSent); sb.append(","); sb.append(stat.bytesReceived); sb.append(","); sb.append(stat.bytesDiscarded); sb.append("\n"); } ClipboardCopy.copyToClipBoard(sb.toString()); } }); Button btnCopyShort = new Button(cBottom, SWT.PUSH); btnCopyShort.setLayoutData(new FormData()); btnCopyShort.setText("Copy > 1%"); btnCopyShort.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { StringBuilder sb = new StringBuilder(); sb.append(new SimpleDateFormat("MMM ''yy").format(new Date())); sb.append("] "); sb.append(overall.count); sb.append(": "); ClientStatsDataSource[] stats = mapData.values().toArray( new ClientStatsDataSource[0]); Arrays.sort(stats, new Comparator() { public int compare(ClientStatsDataSource o1, ClientStatsDataSource o2) { if (o1.count == o2.count) { return 0; } return o1.count > o2.count ? -1 : 1; } }); boolean first = true; for (ClientStatsDataSource stat : stats) { int pct = (int) (stat.count * 1000 / overall.count); if (pct < 10) { continue; } if (first) { first = false; } else { sb.append(", "); } sb.append(DisplayFormatters.formatPercentFromThousands(pct)); sb.append(" "); sb.append(stat.client); } Arrays.sort(stats, new Comparator() { public int compare(ClientStatsDataSource o1, ClientStatsDataSource o2) { float v1 = (float) o1.bytesReceived / o1.count; float v2 = (float) o2.bytesReceived / o2.count; if (v1 == v2) { return 0; } return v1 > v2 ? -1 : 1; } }); int top = 5; first = true; sb.append("\nBest Seeders ("); long total = 0; for (ClientStatsDataSource stat : stats) { total += stat.bytesReceived; } sb.append(DisplayFormatters.formatByteCountToKiBEtc(total, false, true, 0)); sb.append(" Downloaded): "); for (ClientStatsDataSource stat : stats) { if (first) { first = false; } else { sb.append(", "); } sb.append(DisplayFormatters.formatByteCountToKiBEtc( stat.bytesReceived / stat.count, false, true, 0)); sb.append(" per "); sb.append(stat.client); sb.append("(x"); sb.append(stat.count); sb.append(")"); if (--top <= 0) { break; } } Arrays.sort(stats, new Comparator() { public int compare(ClientStatsDataSource o1, ClientStatsDataSource o2) { float v1 = (float) o1.bytesDiscarded / o1.count; float v2 = (float) o2.bytesDiscarded / o2.count; if (v1 == v2) { return 0; } return v1 > v2 ? -1 : 1; } }); top = 5; first = true; sb.append("\nMost Discarded ("); total = 0; for (ClientStatsDataSource stat : stats) { total += stat.bytesDiscarded; } sb.append(DisplayFormatters.formatByteCountToKiBEtc(total, false, true, 0)); sb.append(" Discarded): "); for (ClientStatsDataSource stat : stats) { if (first) { first = false; } else { sb.append(", "); } sb.append(DisplayFormatters.formatByteCountToKiBEtc( stat.bytesDiscarded / stat.count, false, true, 0)); sb.append(" per "); sb.append(stat.client); sb.append("(x"); sb.append(stat.count); sb.append(")"); if (--top <= 0) { break; } } Arrays.sort(stats, new Comparator() { public int compare(ClientStatsDataSource o1, ClientStatsDataSource o2) { float v1 = (float) o1.bytesSent / o1.count; float v2 = (float) o2.bytesSent / o2.count; if (v1 == v2) { return 0; } return v1 > v2 ? -1 : 1; } }); top = 5; first = true; sb.append("\nMost Fed ("); total = 0; for (ClientStatsDataSource stat : stats) { total += stat.bytesSent; } sb.append(DisplayFormatters.formatByteCountToKiBEtc(total, false, true, 0)); sb.append(" Sent): "); for (ClientStatsDataSource stat : stats) { if (first) { first = false; } else { sb.append(", "); } sb.append(DisplayFormatters.formatByteCountToKiBEtc( stat.bytesSent / stat.count, false, true, 0)); sb.append(" per "); sb.append(stat.client); sb.append("(x"); sb.append(stat.count); sb.append(")"); if (--top <= 0) { break; } } ClipboardCopy.copyToClipBoard(sb.toString()); } }); fd = new FormData(); fd.left = new FormAttachment(btnCopy, 5); btnCopyShort.setLayoutData(fd); } public TableViewSWT initYourTableView() { tv = new TableViewSWTImpl( ClientStatsDataSource.class, TABLEID, getPropertiesPrefix(), new TableColumnCore[0], ColumnCS_Count.COLUMN_ID, SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL); /* tv.addTableDataSourceChangedListener(this, true); tv.addRefreshListener(this, true); tv.addSelectionListener(this, false); tv.addMenuFillListener(this); */ tv.addLifeCycleListener(this); return tv; } private void initColumns(AzureusCore core) { synchronized (ClientStatsView.class) { if (columnsAdded) { return; } columnsAdded = true; } UIManager uiManager = PluginInitializer.getDefaultInterface().getUIManager(); TableManager tableManager = uiManager.getTableManager(); tableManager.registerColumn(ClientStatsDataSource.class, ColumnCS_Name.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnCS_Name(column); } }); tableManager.registerColumn(ClientStatsDataSource.class, ColumnCS_Count.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnCS_Count(column); } }); tableManager.registerColumn(ClientStatsDataSource.class, ColumnCS_Discarded.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnCS_Discarded(column); } }); tableManager.registerColumn(ClientStatsDataSource.class, ColumnCS_Received.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnCS_Received(column); } }); tableManager.registerColumn(ClientStatsDataSource.class, ColumnCS_ReceivedPer.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnCS_ReceivedPer(column); } }); tableManager.registerColumn(ClientStatsDataSource.class, ColumnCS_Sent.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnCS_Sent(column); } }); tableManager.registerColumn(ClientStatsDataSource.class, ColumnCS_Pct.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnCS_Pct(column); } }); TableColumnManager tcManager = TableColumnManager.getInstance(); tcManager.setDefaultColumnNames(TABLEID, new String[] { ColumnCS_Name.COLUMN_ID, ColumnCS_Pct.COLUMN_ID, ColumnCS_Count.COLUMN_ID, ColumnCS_Received.COLUMN_ID, ColumnCS_Sent.COLUMN_ID, ColumnCS_Discarded.COLUMN_ID, }); } public void tableViewDestroyed() { if (core == null) { // not initialized, skip save return; } core.getGlobalManager().removeListener(this); List downloadManagers = core.getGlobalManager().getDownloadManagers(); for (Object object : downloadManagers) { ((DownloadManager) object).removePeerListener(this); } save(CONFIG_FILE); } private void initAndLoad() { mapData = new HashMap(); synchronized (mapData) { Map map = FileUtil.readResilientConfigFile(CONFIG_FILE); totalTime = MapUtils.getMapLong(map, "time", 0); lastAdd = MapUtils.getMapLong(map, "lastadd", 0); if (lastAdd != 0) { calendar.setTimeInMillis(lastAdd); lastAddMonth = calendar.get(Calendar.MONTH); Map mapBloom = MapUtils.getMapMap(map, "bloomfilter", null); if (mapBloom != null) { bloomFilter = BloomFilterFactory.deserialiseFromMap(mapBloom); } mapBloom = MapUtils.getMapMap(map, "bloomfilterPeerId", null); if (mapBloom != null) { bloomFilterPeerId = BloomFilterFactory.deserialiseFromMap(mapBloom); } } if (bloomFilter == null) { bloomFilter = BloomFilterFactory.createRotating( BloomFilterFactory.createAddOnly(BLOOMFILTER_SIZE), 2); } if (bloomFilterPeerId == null) { bloomFilterPeerId = BloomFilterFactory.createRotating( BloomFilterFactory.createAddOnly(BLOOMFILTER_PEERID_SIZE), 2); } overall = new ClientStatsOverall(); List listSavedData = MapUtils.getMapList(map, "data", null); if (listSavedData != null) { for (Object val : listSavedData) { try { Map mapVal = (Map) val; if (mapVal != null) { ClientStatsDataSource ds = new ClientStatsDataSource(mapVal); ds.overall = overall; if (!mapData.containsKey(ds.client)) { mapData.put(ds.client, ds); overall.count += ds.count; } } } catch (Exception e) { // ignore } } } } } private void save(String filename) { Map map = new HashMap(); synchronized (mapData) { map.put("data", new ArrayList(mapData.values())); map.put("bloomfilter", bloomFilter.serialiseToMap()); map.put("bloomfilterPeerId", bloomFilterPeerId.serialiseToMap()); map.put("lastadd", SystemTime.getCurrentTime()); if (startedListeningOn > 0) { map.put("time", totalTime + (SystemTime.getCurrentTime() - startedListeningOn)); } else { map.put("time", totalTime); } } FileUtil.writeResilientConfigFile(filename, map); } public void tableViewInitialized() { synchronized (mapData) { if (mapData.values().size() > 0) { tv.addDataSources(mapData.values().toArray(new ClientStatsDataSource[0])); } } AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { register(core); } }); } protected void register(AzureusCore core) { this.core = core; core.getGlobalManager().addListener(this); startedListeningOn = SystemTime.getCurrentTime(); } public void destroyInitiated() { } public void destroyed() { } public void downloadManagerAdded(DownloadManager dm) { if (!dm.getDownloadState().getFlag(DownloadManagerState.FLAG_LOW_NOISE)) { dm.addPeerListener(this, true); } } public void downloadManagerRemoved(DownloadManager dm) { dm.removePeerListener(this); } public void seedingStatusChanged(boolean seedingOnlyMode, boolean potentiallySeedingOnlyMode) { } public void peerAdded(PEPeer peer) { peer.addListener(new PEPeerListener() { public void stateChanged(PEPeer peer, int newState) { if (newState == PEPeer.TRANSFERING) { addPeer(peer); } else if (newState == PEPeer.CLOSING || newState == PEPeer.DISCONNECTED) { peer.removeListener(this); } } public void sentBadChunk(PEPeer peer, int pieceNum, int totalBadChunks) { } public void removeAvailability(PEPeer peer, BitFlags peerHavePieces) { } public void addAvailability(PEPeer peer, BitFlags peerHavePieces) { } }); } protected void addPeer(PEPeer peer) { byte[] bloomId; long now = SystemTime.getCurrentTime(); // Bloom Filter is based on the first 8 bytes of peer id + ip address // This captures more duplicates than peer id because most clients // randomize their peer id on restart. IP address, however, changes // less often. byte[] peerId = peer.getId(); InetAddress ip = peer.getAlternativeIPv6(); if (ip == null) { try { ip = InetAddress.getByName(peer.getIp()); } catch (UnknownHostException e) { } } if (ip == null) { bloomId = peerId; } else { byte[] address = ip.getAddress(); bloomId = new byte[8 + address.length]; System.arraycopy(peerId, 0, bloomId, 0, 8); System.arraycopy(address, 0, bloomId, 8, address.length); } synchronized (mapData) { // break on month.. assume user didn't last use this on the same month in a different year calendar.setTimeInMillis(now); int thisMonth = calendar.get(Calendar.MONTH); if (thisMonth != lastAddMonth) { if (lastAddMonth == 0) { lastAddMonth = thisMonth; } else { String s = new SimpleDateFormat("yyyy-MM").format(new Date(lastAdd)); String filename = CONFIG_FILE_ARCHIVE.replace("%1", s); save(filename); lastAddMonth = thisMonth; lastAdd = 0; bloomFilter = BloomFilterFactory.createRotating( BloomFilterFactory.createAddOnly(BLOOMFILTER_SIZE), 2); bloomFilterPeerId = BloomFilterFactory.createRotating( BloomFilterFactory.createAddOnly(BLOOMFILTER_PEERID_SIZE), 2); overall = new ClientStatsOverall(); mapData.clear(); tv.removeAllTableRows(); totalTime = 0; startedListeningOn = 0; } } if (bloomFilter.contains(bloomId) || bloomFilterPeerId.contains(peerId)) { return; } bloomFilter.add(bloomId); bloomFilterPeerId.add(peerId); lastAdd = now; String id = getID(peer); ClientStatsDataSource stat = mapData.get(id); boolean needNew = stat == null; if (needNew) { stat = new ClientStatsDataSource(); stat.overall = overall; mapData.put(id, stat); } overall.count++; stat.client = getID(peer); stat.count++; stat.current++; if (needNew) { tv.addDataSource(stat); } else { TableRowCore row = tv.getRow(stat); if (row != null) { row.invalidate(); } } } } public void peerManagerAdded(PEPeerManager manager) { } public void peerManagerRemoved(PEPeerManager manager) { } public void peerManagerWillBeAdded(PEPeerManager manager) { } public void peerRemoved(PEPeer peer) { synchronized (mapData) { ClientStatsDataSource stat = mapData.get(getID(peer)); if (stat != null) { stat.current--; stat.bytesReceived += peer.getStats().getTotalDataBytesReceived(); stat.bytesSent += peer.getStats().getTotalDataBytesSent(); stat.bytesDiscarded += peer.getStats().getTotalBytesDiscarded(); TableRowCore row = tv.getRow(stat); if (row != null) { row.invalidate(); } } } } private String getID(PEPeer peer) { String s = peer.getClient(); return s.replaceAll(" v?[0-9._]+", ""); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Count.java0000644000175000017500000000126011273607610026601 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.clientstats; import org.gudy.azureus2.plugins.ui.tables.*; public class ColumnCS_Count implements TableCellRefreshListener { public static final String COLUMN_ID = "count"; public ColumnCS_Count(TableColumn column) { column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 50); column.addListeners(this); column.setType(TableColumn.TYPE_TEXT_ONLY); } public void refresh(TableCell cell) { ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource(); if (ds == null) { return; } long val = ds.count; if (cell.setSortValue(val) || !cell.isValid()) { cell.setText(Long.toString(val)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Sent.java0000644000175000017500000000161111273607610026422 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.clientstats; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumn; public class ColumnCS_Sent implements TableCellRefreshListener { public static final String COLUMN_ID = "sent"; public ColumnCS_Sent(TableColumn column) { column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 80); column.addListeners(this); column.setType(TableColumn.TYPE_TEXT_ONLY); } public void refresh(TableCell cell) { ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource(); if (ds == null) { return; } long val = ds.bytesSent; if (cell.setSortValue(val) || !cell.isValid()) { cell.setText(DisplayFormatters.formatByteCountToKiBEtc(val)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Discarded.java0000644000175000017500000000163511273607610027401 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.clientstats; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumn; public class ColumnCS_Discarded implements TableCellRefreshListener { public static final String COLUMN_ID = "discarded"; public ColumnCS_Discarded(TableColumn column) { column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 80); column.addListeners(this); column.setType(TableColumn.TYPE_TEXT_ONLY); } public void refresh(TableCell cell) { ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource(); if (ds == null) { return; } long val = ds.bytesDiscarded; if (cell.setSortValue(val) || !cell.isValid()) { cell.setText(DisplayFormatters.formatByteCountToKiBEtc(val)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsOverall.java0000644000175000017500000000247511273607610027541 0ustar adrianadrian/** * Created on Oct 24, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.views.clientstats; import java.util.HashMap; import java.util.Map; import com.aelitis.azureus.util.MapUtils; /** * @author TuxPaper * @created Oct 24, 2009 * */ public class ClientStatsOverall { long count; public ClientStatsOverall() { } public ClientStatsOverall(Map loadMap) { if (loadMap == null) { return; } count = MapUtils.getMapLong(loadMap, "count", 0); } public Map toMap() { Map map = new HashMap(); map.put("count", Long.valueOf(count)); return map; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsDataSource.java0000644000175000017500000000225411273607610030162 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.clientstats; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.util.BEncodableObject; import com.aelitis.azureus.util.MapUtils; public class ClientStatsDataSource implements BEncodableObject { public String client; public int count; public int current; public long bytesReceived; public long bytesDiscarded; public long bytesSent; public ClientStatsOverall overall; public ClientStatsDataSource() { } public ClientStatsDataSource(Map loadMap) { client = MapUtils.getMapString(loadMap, "client", "?"); count = MapUtils.getMapInt(loadMap, "count", 0); bytesReceived = MapUtils.getMapLong(loadMap, "bytesReceived", 0); bytesDiscarded = MapUtils.getMapLong(loadMap, "bytesDiscarded", 0); bytesSent = MapUtils.getMapLong(loadMap, "bytesSent", 0); } public Object toBencodeObject() { Map map = new HashMap(); map.put("client", client); map.put("count", Long.valueOf(count)); map.put("bytesReceived", Long.valueOf(bytesReceived)); map.put("bytesDiscarded", Long.valueOf(bytesDiscarded)); map.put("bytesSent", Long.valueOf(bytesSent)); return map; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/ConfigShell.java0000644000175000017500000000751111171750562023615 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; /** * A shell containing the ConfigView * This is used to pop-up the configs in a Shell as opposed to hosting it in the application * This class is used to ensure that only one shell is opened at any time. * @author khai * */ public class ConfigShell { private static ConfigShell instance; private Shell shell; private ConfigView configView; public static ConfigShell getInstance() { if (null == instance) { instance = new ConfigShell(); } return instance; } private ConfigShell() { } /** * Opens the ConfigView inside a pop-up Shell. * If the Shell is opened already then just force it active * @param width * @param height */ public void open(String section) { if (null != shell && false == shell.isDisposed()) { configView.selectSection(section); if (true == shell.getMinimized()) { shell.setMinimized(false); } shell.forceActive(); shell.forceFocus(); } else { shell = ShellFactory.createMainShell(SWT.SHELL_TRIM & ~SWT.MIN); shell.setLayout(new GridLayout()); shell.setText(MessageText.getString(MessageText.resolveLocalizationKey("ConfigView.title.full"))); Utils.setShellIcon(shell); configView = new ConfigView(); configView.initialize(shell); configView.selectSection(section); /* * Set default size and centers the shell if it's configuration does not exist yet */ if (null == COConfigurationManager.getStringParameter( "options.rectangle", null)) { Rectangle shellBounds = shell.getMonitor().getBounds(); Point size = new Point(shellBounds.width * 10 / 11, shellBounds.height * 10 / 11); if (size.x > 1400) { size.x = 1400; } if (size.y > 700) { size.y = 700; } shell.setSize(size); Utils.centerWindowRelativeTo(shell, getMainShell()); } Utils.linkShellMetricsToConfig(shell, "options"); /* * Auto-save when the shell closes */ shell.addListener(SWT.Close, new Listener() { public void handleEvent(Event event) { configView.save(); event.doit = true; } }); shell.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { shell.dispose(); } } }); shell.addDisposeListener( new DisposeListener() { public void widgetDisposed( DisposeEvent arg0 ) { close(); } }); shell.open(); } } private void close() { // if (null != shell && false == shell.isDisposed()) { // shell.close(); // } // clear these down as view now dead configView.delete(); shell = null; configView = null; } private Shell getMainShell() { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (null != uiFunctions) { return uiFunctions.getMainShell(); } throw new IllegalStateException( "No instance of UIFunctionsSWT found; the UIFunctionsManager might not have been initialized properly"); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/LoggerView.java0000644000175000017500000005033311063566560023475 0ustar adrianadrian/** * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views; import java.io.PrintStream; import java.text.FieldPosition; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.LinkedList; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.logging.impl.FileLogging; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; /** * @author TuxPaper * * @since 2.3.0.5 */ public class LoggerView extends AbstractIView implements ILogEventListener, ParameterListener { //private final static LogIDs LOGID = LogIDs.GUI; private static final int COLOR_INFO = 0; private static final int COLOR_WARN = 1; private static final int COLOR_ERR = 2; private static Color[] colors = null; private static final int PREFERRED_LINES = 256; private static final int MAX_LINES = 1024 + PREFERRED_LINES; private static final SimpleDateFormat dateFormatter; private static final FieldPosition formatPos; private Display display; private Composite panel; private StyledText consoleText = null; private Button buttonAutoScroll = null; private Object[] filter = null; // LinkedList is better for removing entries when full private LinkedList buffer = new LinkedList(); private boolean bPaused = false; private boolean bRealtime = false; private boolean bEnabled = false; private boolean bAutoScroll = true; private Pattern inclusionFilter; private Pattern exclusionFilter; // List of components we don't log. // Array represents LogTypes (info, warning, error) private ArrayList[] ignoredComponents = new ArrayList[3]; private boolean stopOnNull = false; static { dateFormatter = new SimpleDateFormat("[HH:mm:ss.SSS] "); formatPos = new FieldPosition(0); } public LoggerView() { this(false); setEnabled(true); } public LoggerView(boolean stopOnNull) { for (int i = 0; i < ignoredComponents.length; i++) { ignoredComponents[i] = new ArrayList(); } this.stopOnNull = stopOnNull; } public LoggerView(java.util.List initialList) { this(); if (initialList != null) buffer.addAll(initialList); setEnabled(true); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IView#initialize(org.eclipse.swt.widgets.Composite) */ public void initialize(Composite composite) { display = composite.getDisplay(); Colors.getInstance().addColorsChangedListener(this); parameterChanged("Color"); panel = new Composite(composite, SWT.NULL); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.verticalSpacing = 2; layout.numColumns = 2; panel.setLayout(layout); GridData gd; consoleText = new StyledText(panel, SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL); gd = new GridData(GridData.FILL_BOTH); gd.horizontalSpan = 2; consoleText.setLayoutData(gd); // XXX This doesn't work well, but it's better than nothing consoleText.addListener(SWT.Resize, new Listener() { public void handleEvent(Event event) { GC gc = new GC(consoleText); int charWidth = gc.getFontMetrics().getAverageCharWidth(); gc.dispose(); int areaWidth = consoleText.getBounds().width; consoleText.setTabs(areaWidth / 6 / charWidth); } }); ScrollBar sb = consoleText.getVerticalBar(); sb.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { bAutoScroll = false; if (buttonAutoScroll != null && !buttonAutoScroll.isDisposed()) buttonAutoScroll.setSelection(false); } }); Composite cLeft = new Composite(panel, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.verticalSpacing = 1; cLeft.setLayout(layout); gd = new GridData(SWT.TOP, SWT.LEAD, false, false); cLeft.setLayoutData(gd); Button buttonPause = new Button(cLeft, SWT.CHECK); Messages.setLanguageText(buttonPause, "LoggerView.pause"); gd = new GridData(); buttonPause.setLayoutData(gd); buttonPause.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (e.widget == null || !(e.widget instanceof Button)) return; Button btn = (Button) e.widget; bPaused = btn.getSelection(); if (!bPaused && buffer != null) { refresh(); } } }); Button buttonRealtime = new Button(cLeft, SWT.CHECK); Messages.setLanguageText(buttonRealtime, "LoggerView.realtime"); gd = new GridData(); buttonRealtime.setLayoutData(gd); buttonRealtime.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (e.widget == null || !(e.widget instanceof Button)) return; Button btn = (Button) e.widget; bRealtime = btn.getSelection(); } }); buttonAutoScroll = new Button(cLeft, SWT.CHECK); Messages.setLanguageText(buttonAutoScroll, "LoggerView.autoscroll"); gd = new GridData(); buttonAutoScroll.setLayoutData(gd); buttonAutoScroll.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (e.widget == null || !(e.widget instanceof Button)) return; Button btn = (Button) e.widget; bAutoScroll = btn.getSelection(); } }); buttonAutoScroll.setSelection(true); Button buttonClear = new Button(cLeft, SWT.PUSH); Messages.setLanguageText(buttonClear, "LoggerView.clear"); gd = new GridData(); buttonClear.setLayoutData(gd); buttonClear.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { consoleText.setText(""); } }); /** FileLogging filter, consisting of a List of types (info, warning, error) * and a checkbox Table of component IDs. */ final String sFilterPrefix = "ConfigView.section.logging.filter"; Group gLogIDs = new Group(panel, SWT.NULL); Messages.setLanguageText(gLogIDs, "LoggerView.filter"); layout = new GridLayout(); layout.marginHeight = 0; layout.numColumns = 2; gLogIDs.setLayout(layout); gd = new GridData(); gLogIDs.setLayoutData(gd); Label label = new Label(gLogIDs, SWT.NONE); Messages.setLanguageText(label, "ConfigView.section.logging.level"); label.setLayoutData(new GridData()); final Label labelCatFilter = new Label(gLogIDs, SWT.NONE); labelCatFilter.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); final List listLogTypes = new List(gLogIDs, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL); gd = new GridData(SWT.NULL, SWT.BEGINNING, false, false); listLogTypes.setLayoutData(gd); final int[] logTypes = { LogEvent.LT_INFORMATION, LogEvent.LT_WARNING, LogEvent.LT_ERROR }; for (int i = 0; i < logTypes.length; i++) listLogTypes.add(MessageText.getString("ConfigView.section.logging.log" + i + "type")); listLogTypes.select(0); final LogIDs[] logIDs = FileLogging.configurableLOGIDs; //Arrays.sort(logIDs); Composite cChecksAndButtons = new Composite(gLogIDs, SWT.NULL); layout = new GridLayout(2, false); layout.marginHeight = 0; layout.marginWidth = 0; cChecksAndButtons.setLayout(layout); cChecksAndButtons.setLayoutData(new GridData()); final Composite cChecks = new Composite(cChecksAndButtons, SWT.NULL); RowLayout rowLayout = new RowLayout(SWT.VERTICAL); rowLayout.wrap = true; rowLayout.marginLeft = 0; rowLayout.marginRight = 0; rowLayout.marginTop = 0; rowLayout.marginBottom = 0; cChecks.setLayout(rowLayout); SelectionAdapter buttonClickListener = new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int index = listLogTypes.getSelectionIndex(); if (index < 0 || index >= logTypes.length) return; Button item = (Button) e.widget; if (item.getSelection()) ignoredComponents[index].remove(item.getData("LOGID")); else ignoredComponents[index].add(item.getData("LOGID")); } }; for (int i = 0; i < logIDs.length; i++) { Button btn = new Button(cChecks, SWT.CHECK); btn.setText(MessageText.getString(sFilterPrefix + "." + logIDs[i], logIDs[i].toString())); btn.setData("LOGID", logIDs[i]); btn.addSelectionListener(buttonClickListener); if (i == 0) { gd = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 2); gd.heightHint = (btn.computeSize(SWT.DEFAULT, SWT.DEFAULT).y + 2) * 3; cChecks.setLayoutData(gd); } } // Update table when list selection changes listLogTypes.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int index = listLogTypes.getSelectionIndex(); if (index < 0 || index >= logTypes.length) return; labelCatFilter.setText(MessageText.getString( "ConfigView.section.logging.showLogsFor", listLogTypes .getSelection())); Control[] items = cChecks.getChildren(); for (int i = 0; i < items.length; i++) { if (items[i] instanceof Button) { LogIDs ID = (LogIDs) items[i].getData("LOGID"); if (ID != null) { boolean checked = !ignoredComponents[index].contains(ID); ((Button) items[i]).setSelection(checked); } } } } }); listLogTypes.notifyListeners(SWT.Selection, null); Button btn; btn = new Button(cChecksAndButtons, SWT.PUSH); gd = new GridData(); btn.setLayoutData(gd); Messages.setLanguageText(btn, "LoggerView.filter.checkAll"); btn.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int index = listLogTypes.getSelectionIndex(); Control[] items = cChecks.getChildren(); for (int i = 0; i < items.length; i++) { if (items[i] instanceof Button) { LogIDs ID = (LogIDs) items[i].getData("LOGID"); if (ID != null && ignoredComponents[index].contains(ID)) { ((Button) items[i]).setSelection(true); ignoredComponents[index].remove(ID); } } } } }); btn = new Button(cChecksAndButtons, SWT.PUSH); gd = new GridData(); btn.setLayoutData(gd); Messages.setLanguageText(btn, "LoggerView.filter.uncheckAll"); btn.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int index = listLogTypes.getSelectionIndex(); Control[] items = cChecks.getChildren(); for (int i = 0; i < items.length; i++) { if (items[i] instanceof Button) { LogIDs ID = (LogIDs) items[i].getData("LOGID"); if (ID != null && !ignoredComponents[index].contains(ID)) { ((Button) items[i]).setSelection(false); ignoredComponents[index].add(ID); } } } } }); Composite cBottom = new Composite(panel, SWT.NONE); gd = new GridData(SWT.FILL, SWT.FILL, true, false); gd.horizontalSpan = 2; cBottom.setLayoutData(gd); cBottom.setLayout(new GridLayout(2, false)); label = new Label(cBottom, SWT.NONE); label.setLayoutData(new GridData()); Messages.setLanguageText(label, "LoggerView.includeOnly"); final Text inclText = new Text(cBottom, SWT.BORDER); gd = new GridData(); gd.widthHint = 200; inclText.setLayoutData(gd); inclText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { String newExpression = inclText.getText(); if (newExpression.length() == 0) inclusionFilter = null; else { try { inclusionFilter = Pattern.compile(newExpression, Pattern.CASE_INSENSITIVE); inclText.setBackground(null); } catch (PatternSyntaxException e1) { inclText.setBackground(Colors.colorErrorBG); } } } }); label = new Label(cBottom, SWT.NONE); label.setLayoutData(new GridData()); Messages.setLanguageText(label, "LoggerView.excludeAll"); final Text exclText = new Text(cBottom, SWT.BORDER); gd = new GridData(); gd.widthHint = 200; exclText.setLayoutData(gd); exclText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { String newExpression = exclText.getText(); if (newExpression.length() == 0) exclusionFilter = null; else { try { exclusionFilter = Pattern.compile(newExpression, Pattern.CASE_INSENSITIVE); exclText.setBackground(null); } catch (PatternSyntaxException e1) { exclText.setBackground(Colors.colorErrorBG); } } } }); if (!Logger.isEnabled()) { consoleText.setText(MessageText.getString("LoggerView.loggingDisabled") + "\n"); } } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IView#getComposite() */ public Composite getComposite() { return panel; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IView#refresh() */ public void refresh() { if (bPaused) return; synchronized (buffer) { if (consoleText == null || consoleText.isDisposed()) return; for (int i = 0; i < buffer.size(); i++) { try { LogEvent event = (LogEvent) buffer.get(i); int nbLinesBefore = consoleText.getLineCount(); if (nbLinesBefore > MAX_LINES) { consoleText.replaceTextRange(0, consoleText.getOffsetAtLine(PREFERRED_LINES), ""); nbLinesBefore = consoleText.getLineCount(); } final StringBuffer buf = new StringBuffer(); buf.append('\n'); dateFormatter.format(event.timeStamp, buf, formatPos); buf.append("{").append(event.logID).append("} "); buf.append(event.text); if (event.relatedTo != null) { buf.append("; \t| "); for (int j = 0; j < event.relatedTo.length; j++) { Object obj = event.relatedTo[j]; if (j > 0) buf.append("; "); if (obj instanceof LogRelation) { buf.append(((LogRelation) obj).getRelationText()); } else if (obj != null) { buf.append(obj.getClass().getName()).append(": '").append( obj.toString()).append("'"); } } } String toAppend = buf.toString(); if((inclusionFilter != null && !inclusionFilter.matcher(toAppend).find()) || (exclusionFilter != null && exclusionFilter.matcher(toAppend).find())) continue; consoleText.append(toAppend); int nbLinesNow = consoleText.getLineCount(); int colorIdx = -1; if (event.entryType == LogEvent.LT_INFORMATION) colorIdx = COLOR_INFO; else if (event.entryType == LogEvent.LT_WARNING) colorIdx = COLOR_WARN; else if (event.entryType == LogEvent.LT_ERROR) colorIdx = COLOR_ERR; if (colors != null && colorIdx >= 0) consoleText.setLineBackground(nbLinesBefore, nbLinesNow - nbLinesBefore, colors[colorIdx]); } catch (Exception e) { // don't send it to log, we might be feeding ourselves PrintStream ps = Logger.getOldStdErr(); if (ps != null) { ps.println("Error writing event to console:"); e.printStackTrace(ps); } } } buffer.clear(); if (bAutoScroll) consoleText.setTopIndex(consoleText.getLineCount()); } } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IView#delete() */ public void delete() { Logger.removeListener(this); if (panel != null && !panel.isDisposed()) panel.dispose(); Colors.getInstance().removeColorsChangedListener(this); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.IView#getFullTitle() */ public String getFullTitle() { return MessageText.getString("ConsoleView.title.full"); } public String getData() { return "ConsoleView.title.short"; } // @see org.gudy.azureus2.core3.logging.ILogEventListener#log(org.gudy.azureus2.core3.logging.LogEvent) public synchronized void log(final LogEvent event) { if (display == null || display.isDisposed()) return; if (ignoredComponents[logTypeToIndex(event.entryType)].contains(event.logID)) return; // Always display STDERR messages, as they may relate to the filter boolean bMatch = (event.logID == LogIDs.STDERR || filter == null); if (!bMatch && event.relatedTo != null) { for (int i = 0; !bMatch && i < event.relatedTo.length; i++) { Object obj = event.relatedTo[i]; if (obj == null) continue; for (int j = 0; !bMatch && j < filter.length; j++) { if (obj instanceof LogRelation) { //System.err.println(obj.getClass().getSimpleName() + " is Logrelation"); Object newObj = ((LogRelation) obj).queryForClass(filter[j] .getClass()); if (newObj != null) obj = newObj; } //System.err.println(obj.getClass().getName() + " matches " + filter[j].getClass().getSimpleName() + "?"); if (obj == filter[j]) bMatch = true; } // for filter } // for relatedTo } if (bMatch) { synchronized (buffer) { if (buffer.size() >= 200) buffer.removeFirst(); buffer.add(event); } if (bRealtime && !bPaused) { Utils.execSWTThread(new AERunnable() { public void runSupport() { refresh(); } }); } } } public void setFilter(Object[] _filter) { filter = _filter; clearConsole(); } private void clearConsole() { if (display == null || display.isDisposed()) return; Utils.execSWTThread(new AERunnable() { public void runSupport() { consoleText.setText(""); } }); } public void setEnabled(boolean on) { if (bEnabled == on) return; bEnabled = on; if (on) Logger.addListener(this); else Logger.removeListener(this); } /* (non-Javadoc) * @see org.gudy.azureus2.plugins.PluginView#getPluginViewName() */ public String getPluginViewName() { return "Console"; } // TODO: Support multiple selection public void dataSourceChanged(Object newDataSource) { if (newDataSource == null) { if (stopOnNull) { setEnabled(false); return; } setFilter(null); } else if (newDataSource instanceof Object[]) { setFilter((Object[]) newDataSource); } else { setFilter(new Object[] { newDataSource }); } setEnabled(true); } private int logTypeToIndex(int entryType) { switch (entryType) { case LogEvent.LT_INFORMATION: return 0; case LogEvent.LT_WARNING: return 1; case LogEvent.LT_ERROR: return 2; } return 0; } private int indexToLogType(int index) { switch (index) { case 0: return LogEvent.LT_INFORMATION; case 1: return LogEvent.LT_WARNING; case 2: return LogEvent.LT_ERROR; } return LogEvent.LT_INFORMATION; } public void parameterChanged(String parameterName) { if (parameterName.startsWith("Color")) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (display == null || display.isDisposed()) return; if (colors == null) colors = new Color[3]; final Color[] newColors = { Colors.blues[Colors.BLUES_MIDLIGHT], Colors.colorWarning, Colors.red_ConsoleView }; boolean bColorChanged = false; for (int i = 0; i < newColors.length; i++) { if (colors[i] == null || colors[i].isDisposed()) { colors[i] = newColors[i]; bColorChanged = true; } } if (bColorChanged && consoleText != null) { // remove color String text = consoleText.getText(); consoleText.setText(text); } } }); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/TorrentOptionsView.java0000644000175000017500000004556711256324534025301 0ustar adrianadrian/* * Created on 16-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.download.DownloadManagerStateAttributeListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.ChangeSelectionActionPerformer; import org.gudy.azureus2.ui.swt.config.generic.GenericBooleanParameter; import org.gudy.azureus2.ui.swt.config.generic.GenericIntParameter; import org.gudy.azureus2.ui.swt.config.generic.GenericParameterAdapter; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; public class TorrentOptionsView extends AbstractIView implements DownloadManagerStateAttributeListener { private static final String TEXT_PREFIX = "TorrentOptionsView.param."; // adhoc parameters need explicit code to reset default values below private static final String MAX_UPLOAD = "max.upload"; private static final String MAX_DOWNLOAD = "max.download"; private boolean multi_view; private DownloadManager[] managers; private GenericParameterAdapter ds_param_adapter = new downloadStateParameterAdapter(); private GenericParameterAdapter adhoc_param_adapter = new adhocParameterAdapter(); private Map adhoc_parameters = new HashMap(); private Map ds_parameters = new HashMap(); private Composite panel; private Font headerFont; private Composite parent; public TorrentOptionsView() { } /** * @param managers2 */ public TorrentOptionsView(DownloadManager[] managers2) { dataSourceChanged(managers2); } public void initialize( Composite composite) { this.parent = composite; if (managers == null) { return; } // cheap trick to allow datasource changes. Normally we'd just // refill the components with new info, but I didn't write this and // I don't want to waste my time :) [tux] if (panel != null && !panel.isDisposed()) { panel.dispose(); } panel = new Composite(composite, SWT.NULL); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 1; panel.setLayout(layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); // header Composite cHeader = new Composite(panel, SWT.BORDER); GridLayout configLayout = new GridLayout(); configLayout.marginHeight = 3; configLayout.marginWidth = 0; cHeader.setLayout(configLayout); GridData gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER); cHeader.setLayoutData(gridData); Display d = panel.getDisplay(); cHeader.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION)); cHeader.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); Label lHeader = new Label(cHeader, SWT.NULL); lHeader.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION)); lHeader.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); FontData[] fontData = lHeader.getFont().getFontData(); fontData[0].setStyle(SWT.BOLD); int fontHeight = (int)(fontData[0].getHeight() * 1.2); fontData[0].setHeight(fontHeight); headerFont = new Font(d, fontData); lHeader.setFont(headerFont); if ( managers.length == 1 ){ lHeader.setText( " " + MessageText.getString( "authenticator.torrent" ) + " : " + managers[0].getDisplayName().replaceAll("&", "&&")); }else{ String str = ""; for (int i=0;i 3 ){ str += "..."; } lHeader.setText( " " + managers.length + " " + MessageText.getString( "ConfigView.section.torrents" ) + " : " + str ); } gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER); lHeader.setLayoutData(gridData); Group gTorrentOptions = new Group(panel, SWT.NULL); Messages.setLanguageText(gTorrentOptions, "ConfigView.section.transfer"); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gTorrentOptions.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; gTorrentOptions.setLayout(layout); //Disabled for release. Need to convert from user-specified units to //KB/s before restoring the following line //String k_unit = DisplayFormatters.getRateUnit(DisplayFormatters.UNIT_KB).trim() String k_unit = DisplayFormatters.getRateUnitBase10(DisplayFormatters.UNIT_KB).trim(); // max upload speed Label label = new Label(gTorrentOptions, SWT.NULL); gridData = new GridData(); label.setLayoutData( gridData ); label.setText(k_unit + " " + MessageText.getString( "GeneralView.label.maxuploadspeed.tooltip" )); GenericIntParameter max_upload = new GenericIntParameter( adhoc_param_adapter, gTorrentOptions, MAX_UPLOAD); adhoc_parameters.put( MAX_UPLOAD, max_upload ); gridData = new GridData(); max_upload.setLayoutData(gridData); if ( userMode > 0) { // max upload when busy label = new Label(gTorrentOptions, SWT.NULL); gridData = new GridData(); label.setLayoutData( gridData ); Messages.setLanguageText(label, TEXT_PREFIX + "max.uploads.when.busy"); GenericIntParameter max_upload_when_busy = new GenericIntParameter( ds_param_adapter, gTorrentOptions, DownloadManagerState.PARAM_MAX_UPLOAD_WHEN_BUSY); ds_parameters.put( DownloadManagerState.PARAM_MAX_UPLOAD_WHEN_BUSY, max_upload_when_busy ); gridData = new GridData(); max_upload_when_busy.setLayoutData(gridData); } // max download speed label = new Label(gTorrentOptions, SWT.NULL); gridData = new GridData(); label.setLayoutData( gridData ); label.setText(k_unit + " " + MessageText.getString( "GeneralView.label.maxdownloadspeed.tooltip" )); GenericIntParameter max_download = new GenericIntParameter( adhoc_param_adapter, gTorrentOptions, MAX_DOWNLOAD); adhoc_parameters.put( MAX_DOWNLOAD, max_download ); gridData = new GridData(); max_download.setLayoutData(gridData); // max uploads if (userMode > 0) { label = new Label(gTorrentOptions, SWT.NULL); gridData = new GridData(); label.setLayoutData( gridData ); Messages.setLanguageText(label, TEXT_PREFIX + "max.uploads" ); GenericIntParameter max_uploads = new GenericIntParameter( ds_param_adapter, gTorrentOptions, DownloadManagerState.PARAM_MAX_UPLOADS); ds_parameters.put( DownloadManagerState.PARAM_MAX_UPLOADS, max_uploads ); max_uploads.setMinimumValue(2); gridData = new GridData(); max_uploads.setLayoutData(gridData); // max uploads when seeding enabled final Composite cMaxUploadsOptionsArea = new Composite(gTorrentOptions, SWT.NULL); layout = new GridLayout(); layout.numColumns = 3; layout.marginWidth = 0; layout.marginHeight = 0; cMaxUploadsOptionsArea.setLayout(layout); gridData = new GridData(); gridData.horizontalIndent = 15; gridData.horizontalSpan = 2; cMaxUploadsOptionsArea.setLayoutData(gridData); label = new Label(cMaxUploadsOptionsArea, SWT.NULL); ImageLoader.getInstance().setLabelImage(label, "subitem"); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); gridData = new GridData(); GenericBooleanParameter max_uploads_when_seeding_enabled = new GenericBooleanParameter( ds_param_adapter, cMaxUploadsOptionsArea, DownloadManagerState.PARAM_MAX_UPLOADS_WHEN_SEEDING_ENABLED, false, TEXT_PREFIX + "alternative.value.enable"); ds_parameters.put( DownloadManagerState.PARAM_MAX_UPLOADS_WHEN_SEEDING_ENABLED, max_uploads_when_seeding_enabled ); max_uploads_when_seeding_enabled.setLayoutData( gridData ); GenericIntParameter max_uploads_when_seeding = new GenericIntParameter( ds_param_adapter, cMaxUploadsOptionsArea, DownloadManagerState.PARAM_MAX_UPLOADS_WHEN_SEEDING); ds_parameters.put( DownloadManagerState.PARAM_MAX_UPLOADS_WHEN_SEEDING, max_uploads_when_seeding ); gridData = new GridData(); max_uploads_when_seeding.setMinimumValue(2); max_uploads_when_seeding.setLayoutData(gridData); max_uploads_when_seeding_enabled.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( max_uploads_when_seeding.getControl())); // max peers label = new Label(gTorrentOptions, SWT.NULL); gridData = new GridData(); label.setLayoutData( gridData ); Messages.setLanguageText(label, TEXT_PREFIX + "max.peers"); GenericIntParameter max_peers = new GenericIntParameter(ds_param_adapter, gTorrentOptions, DownloadManagerState.PARAM_MAX_PEERS); ds_parameters.put( DownloadManagerState.PARAM_MAX_PEERS, max_peers ); gridData = new GridData(); max_peers.setLayoutData(gridData); // max peers when seeding final Composite cMaxPeersOptionsArea = new Composite(gTorrentOptions, SWT.NULL); layout = new GridLayout(); layout.numColumns = 3; layout.marginWidth = 0; layout.marginHeight = 0; cMaxPeersOptionsArea.setLayout(layout); gridData = new GridData(); gridData.horizontalIndent = 15; gridData.horizontalSpan = 2; cMaxPeersOptionsArea.setLayoutData(gridData); label = new Label(cMaxPeersOptionsArea, SWT.NULL); ImageLoader.getInstance().setLabelImage(label, "subitem"); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); gridData = new GridData(); GenericBooleanParameter max_peers_when_seeding_enabled = new GenericBooleanParameter( ds_param_adapter, cMaxPeersOptionsArea, DownloadManagerState.PARAM_MAX_PEERS_WHEN_SEEDING_ENABLED, false, TEXT_PREFIX + "alternative.value.enable"); ds_parameters.put( DownloadManagerState.PARAM_MAX_PEERS_WHEN_SEEDING_ENABLED, max_peers_when_seeding_enabled ); max_peers_when_seeding_enabled.setLayoutData( gridData ); GenericIntParameter max_peers_when_seeding = new GenericIntParameter( ds_param_adapter, cMaxPeersOptionsArea, DownloadManagerState.PARAM_MAX_PEERS_WHEN_SEEDING); ds_parameters.put( DownloadManagerState.PARAM_MAX_PEERS_WHEN_SEEDING, max_peers_when_seeding ); gridData = new GridData(); max_peers_when_seeding.setLayoutData(gridData); max_peers_when_seeding_enabled.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( max_peers_when_seeding.getControl())); // max seeds label = new Label(gTorrentOptions, SWT.NULL); gridData = new GridData(); label.setLayoutData( gridData ); Messages.setLanguageText(label, TEXT_PREFIX + "max.seeds" ); GenericIntParameter max_seeds = new GenericIntParameter( ds_param_adapter, gTorrentOptions, DownloadManagerState.PARAM_MAX_SEEDS); ds_parameters.put( DownloadManagerState.PARAM_MAX_SEEDS, max_seeds ); gridData = new GridData(); max_seeds.setLayoutData(gridData); } Label reset_label = new Label(gTorrentOptions, SWT.NULL ); Messages.setLanguageText(reset_label, TEXT_PREFIX + "reset.to.default"); Button reset_button = new Button(gTorrentOptions, SWT.PUSH); Messages.setLanguageText(reset_button, TEXT_PREFIX + "reset.button" ); reset_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { setDefaults(); } }); for (int i=0;i= upperBound) return; // availability and peer lists are OOS, just wait for the next round final int newPeak; if (avlPeak < (newPeak = ++globalPiecesPerAvailability[availabilties[i]])) { avlPeak = newPeak; avlPeakIdx = availabilties[i]; } if ((isMe && dmPieces[i].isDone()) || (!isMe && hasPieces != null && hasPieces[i])) ++datasourcePiecesPerAvailability[availabilties[i]]; if (isMe && pePieces[i] != null) downloading[availabilties[i]] = true; } Image img = new Image(comp.getDisplay(),pieceDistCanvas.getBounds()); GC gc = new GC(img); try { int stepWidthX = (int) Math.floor(rect.width / upperBound); int barGap = 1; int barWidth = stepWidthX - barGap - 1; int barFillingWidth = barWidth - 1; double stepWidthY = 1.0 * (rect.height - 1) / avlPeak; int offsetY = rect.height; gc.setForeground(Colors.green); for (int i = 0; i <= connected; i++) { Color curColor; if (i == 0) curColor = Colors.colorError; else if (i <= seeds) curColor = Colors.green; else curColor = Colors.blues[Colors.BLUES_DARKEST]; gc.setBackground(curColor); gc.setForeground(curColor); if(globalPiecesPerAvailability[i] == 0) { gc.setLineWidth(2); gc.drawLine(stepWidthX * i, offsetY - 1, stepWidthX * (i + 1) - barGap, offsetY - 1); } else { gc.setLineWidth(1); if (downloading[i]) gc.setLineStyle(SWT.LINE_DASH); gc.fillRectangle(stepWidthX * i + 1, offsetY - 1, barFillingWidth, (int) (Math.ceil(stepWidthY * datasourcePiecesPerAvailability[i] - 1) * -1)); gc.drawRectangle(stepWidthX * i, offsetY, barWidth, (int) (Math.ceil(stepWidthY * globalPiecesPerAvailability[i]) + 1) * -1); } if(i==minAvail) { gc.setForeground(Colors.blue); gc.drawRectangle(stepWidthX*i+1, offsetY-1, barWidth-2, (int)(Math.ceil(stepWidthY*globalPiecesPerAvailability[i]-1))*-1); } gc.setLineStyle(SWT.LINE_SOLID); } gc.setLineWidth(1); CoordinateTransform t = new CoordinateTransform(rect); t.shiftExternal(rect.width,0); t.scale(-1.0, 1.0); String[] boxContent = new String[] { MessageText.getString("PiecesView.DistributionView.NoAvl"), MessageText.getString("PiecesView.DistributionView.SeedAvl"), MessageText.getString("PiecesView.DistributionView.PeerAvl"), MessageText.getString("PiecesView.DistributionView.RarestAvl",new String[] {globalPiecesPerAvailability[minAvail]+"",minAvail+""}), MessageText.getString("PiecesView.DistributionView."+ (isMe? "weHave" : "theyHave")), MessageText.getString("PiecesView.DistributionView.weDownload") }; int charWidth = gc.getFontMetrics().getAverageCharWidth(); int charHeight = gc.getFontMetrics().getHeight(); int maxBoxOffsetY = charHeight + 2; int maxBoxWidth = 0; int maxBoxOffsetX = 0; for (int i = 0; i < boxContent.length; i++) maxBoxWidth = Math.max(maxBoxWidth, boxContent[i].length()); maxBoxOffsetX = (maxBoxWidth+5) * charWidth; maxBoxWidth = ++maxBoxWidth * charWidth; int boxNum = 1; gc.setForeground(Colors.colorError); gc.setBackground(Colors.background); gc.drawRectangle(t.x(maxBoxOffsetX),t.y(maxBoxOffsetY*boxNum),maxBoxWidth,charHeight); gc.drawString(boxContent[boxNum-1],t.x(maxBoxOffsetX-5),t.y(maxBoxOffsetY*boxNum),true); boxNum++; gc.setForeground(Colors.green); gc.setBackground(Colors.background); gc.drawRectangle(t.x(maxBoxOffsetX),t.y(maxBoxOffsetY*boxNum),maxBoxWidth,charHeight); gc.drawString(boxContent[boxNum-1],t.x(maxBoxOffsetX-5),t.y(maxBoxOffsetY*boxNum),true); boxNum++; gc.setForeground(Colors.blues[Colors.BLUES_DARKEST]); gc.drawRectangle(t.x(maxBoxOffsetX),t.y(maxBoxOffsetY*boxNum),maxBoxWidth,charHeight); gc.drawString(boxContent[boxNum-1],t.x(maxBoxOffsetX-5),t.y(maxBoxOffsetY*boxNum),true); boxNum++; gc.setForeground(Colors.blue); gc.drawRectangle(t.x(maxBoxOffsetX),t.y(maxBoxOffsetY*boxNum),maxBoxWidth,charHeight); gc.drawString(boxContent[boxNum-1],t.x(maxBoxOffsetX-5),t.y(maxBoxOffsetY*boxNum),true); boxNum++; gc.setForeground(Colors.black); gc.setBackground(Colors.black); gc.drawRectangle(t.x(maxBoxOffsetX),t.y(maxBoxOffsetY*boxNum),maxBoxWidth,charHeight); gc.fillRectangle(t.x(maxBoxOffsetX),t.y(maxBoxOffsetY*boxNum),maxBoxWidth/2,charHeight); gc.setForeground(Colors.grey); gc.setBackground(Colors.background); gc.drawString(boxContent[boxNum-1],t.x(maxBoxOffsetX-5),t.y(maxBoxOffsetY*boxNum),true); if(isMe) { boxNum++; gc.setForeground(Colors.black); gc.setLineStyle(SWT.LINE_DASH); gc.drawRectangle(t.x(maxBoxOffsetX),t.y(maxBoxOffsetY*boxNum),maxBoxWidth,charHeight); gc.drawString(boxContent[boxNum-1],t.x(maxBoxOffsetX-5),t.y(maxBoxOffsetY*boxNum),true); } gc.setLineStyle(SWT.LINE_SOLID); } finally { gc.dispose(); } if (imgToPaint != null) { imgToPaint.dispose(); } imgToPaint = img; pieceDistCanvas.redraw(); } public void refresh() { if (!initialized || pem == null) return; updateDistribution(); super.refresh(); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#getComposite() */ public Composite getComposite() { return comp; } /* * (non-Javadoc) * * @see org.gudy.azureus2.ui.swt.views.AbstractIView#delete() */ public void delete() { if (!initialized) return; initialized = false; Utils.disposeSWTObjects(new Object[] { pieceDistCanvas, comp, imgToPaint }); super.delete(); } public Menu getPrivateMenu() { return null; } public void viewActivated() { updateDistribution(); } public void viewDeactivated() { Utils.disposeSWTObjects(new Object[] { imgToPaint }); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/MyTorrentsView.java0000644000175000017500000017310311274501106024372 0ustar adrianadrian/* * Created on 30 juin 2003 * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views; import java.util.*; import java.util.List; import java.util.regex.Pattern; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.category.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerListener; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.DownloadTypeComplete; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.URLTransfer; import org.gudy.azureus2.ui.swt.help.HealthHelpWindow; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.minibar.DownloadBar; import org.gudy.azureus2.ui.swt.views.ViewUtils.SpeedAdapter; import org.gudy.azureus2.ui.swt.views.table.*; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin; import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddy; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.table.*; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; import com.aelitis.azureus.ui.selectedcontent.SelectedContent; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** Displays a list of torrents in a table view. * * @author Olivier * @author TuxPaper * 2004/Apr/18: Use TableRowImpl instead of PeerRow * 2004/Apr/20: Remove need for tableItemToObject * 2004/Apr/21: extends TableView instead of IAbstractView * 2005/Oct/01: Column moving in SWT >= 3.1 */ public class MyTorrentsView extends TableViewTab implements GlobalManagerListener, ParameterListener, DownloadManagerListener, CategoryManagerListener, CategoryListener, KeyListener, TableLifeCycleListener, TableViewSWTPanelCreator, TableSelectionListener, TableViewSWTMenuFillListener, TableRefreshListener, TableCountChangeListener, TableViewFilterCheck { private static final LogIDs LOGID = LogIDs.GUI; private AzureusCore azureus_core; private GlobalManager globalManager; protected boolean isSeedingView; private Composite cTablePanel; private Font fontButton = null; private Composite cCategories; private ControlAdapter catResizeAdapter; private DragSource dragSource = null; private DropTarget dropTarget = null; private Composite cHeader = null; private Label lblHeader = null; private Text txtFilter = null; private Label lblX = null; private Category currentCategory; // table item index, where the drag has started private int drag_drop_line_start = -1; private TableRowCore[] drag_drop_rows = null; private boolean bDNDalwaysIncomplete; private TableViewSWT tv; private Composite cTableParentPanel; protected boolean viewActive; private boolean forceHeaderVisible = false; private TableSelectionListener defaultSelectedListener; private Composite cFilterArea; protected boolean resizeHeaderEventQueued; private Button btnFilter; private Composite cSizer; public MyTorrentsView() { super("MyTorrentsView"); } /** * Initialize * * @param _azureus_core * @param isSeedingView * @param basicItems */ public MyTorrentsView( AzureusCore _azureus_core, String tableID, boolean isSeedingView, TableColumnCore[] basicItems) { super("MyTorrentsView"); init(_azureus_core, tableID, isSeedingView, basicItems); } // @see org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab#initYourTableView() public TableViewSWT initYourTableView() { return tv; } public void init(AzureusCore _azureus_core, String tableID, boolean isSeedingView, TableColumnCore[] basicItems) { this.isSeedingView = isSeedingView; tv = createTableView(isSeedingView ? DownloadTypeComplete.class : DownloadTypeIncomplete.class, tableID, basicItems); tv.setRowDefaultIconSize(new Point(16, 16)); /* * 'Big' table has taller row height */ if (getRowDefaultHeight() > 0) { tv.setRowDefaultHeight(getRowDefaultHeight()); } azureus_core = _azureus_core; this.globalManager = azureus_core.getGlobalManager(); currentCategory = CategoryManager.getCategory(Category.TYPE_ALL); tv.addLifeCycleListener(this); tv.setMainPanelCreator(this); tv.addSelectionListener(this, false); tv.addMenuFillListener(this); tv.addRefreshListener(this, false); tv.addCountChangeListener(this); forceHeaderVisible = COConfigurationManager.getBooleanParameter("MyTorrentsView.alwaysShowHeader"); //tv.setEnableTabViews(true); //IView views[] = { new GeneralView(), new PeersView(), // new PeersGraphicView(), new PiecesView(), new FilesView(), // new LoggerView() }; //tv.setCoreTabViews(views); } // @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewInitialized() public void tableViewInitialized() { tv.addKeyListener(this); createTabs(); if (txtFilter == null) { tv.enableFilterCheck(null, this); } createDragDrop(); COConfigurationManager.addAndFireParameterListeners(new String[] { "DND Always In Incomplete", "Confirm Data Delete", "MyTorrentsView.alwaysShowHeader", "User Mode" }, this); if (currentCategory != null) { currentCategory.addCategoryListener(this); } CategoryManager.addCategoryManagerListener(this); globalManager.addListener(this, false); Object[] dms = globalManager.getDownloadManagers().toArray(); for (int i = 0; i < dms.length; i++) { DownloadManager dm = (DownloadManager) dms[i]; dm.addListener(this); if (!isOurDownloadManager(dm)) { dms[i] = null; } } tv.addDataSources(dms); tv.processDataSourceQueue(); cTablePanel.layout(); } // @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewDestroyed() public void tableViewDestroyed() { tv.removeKeyListener(this); Utils.execSWTThread(new AERunnable() { public void runSupport() { try { Utils.disposeSWTObjects(new Object[] { dragSource, dropTarget, fontButton }); dragSource = null; dropTarget = null; fontButton = null; } catch (Exception e) { Debug.out(e); } } }); Object[] dms = globalManager.getDownloadManagers().toArray(); for (int i = 0; i < dms.length; i++) { DownloadManager dm = (DownloadManager) dms[i]; dm.removeListener(this); } if (currentCategory != null) { currentCategory.removeCategoryListener(this); } CategoryManager.removeCategoryManagerListener(this); globalManager.removeListener(this); COConfigurationManager.removeParameterListener("DND Always In Incomplete", this); COConfigurationManager.removeParameterListener("Confirm Data Delete", this); COConfigurationManager.removeParameterListener("User Mode", this); } // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWTPanelCreator#createTableViewPanel(org.eclipse.swt.widgets.Composite) public Composite createTableViewPanel(Composite composite) { composite.addListener(SWT.Activate, new Listener() { public void handleEvent(Event event) { viewActive = true; updateSelectedContent(); refreshIconBar(); } }); composite.addListener(SWT.Deactivate, new Listener() { public void handleEvent(Event event) { viewActive = false; // don't updateSelectedContent() because we may have switched // to a button or a text field, and we still want out content to be // selected } }); GridData gridData; cTableParentPanel = new Composite(composite, SWT.NULL); GridLayout layout = new GridLayout(); layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; cTableParentPanel.setLayout(layout); if (composite.getLayout() instanceof GridLayout) { cTableParentPanel.setLayoutData(new GridData(GridData.FILL_BOTH)); } cTablePanel = new Composite(cTableParentPanel, SWT.NULL); cTablePanel.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); cTablePanel.setForeground(composite.getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND)); gridData = new GridData(GridData.FILL_BOTH); cTablePanel.setLayoutData(gridData); layout = new GridLayout(1, false); layout.marginHeight = 0; layout.marginWidth = 0; layout.verticalSpacing = 0; layout.horizontalSpacing = 0; cTablePanel.setLayout(layout); cTablePanel.layout(); return cTablePanel; } public void setForceHeaderVisible(boolean forceHeaderVisible) { this.forceHeaderVisible = forceHeaderVisible; if (cTablePanel != null && !cTablePanel.isDisposed()) { createTabs(); } } private void createTabs() { GridData gridData; Category[] categories = CategoryManager.getCategories(); Arrays.sort(categories); boolean showCat = tv.getFilterText().length() > 0; if (!showCat) { for(int i = 0; i < categories.length; i++) { if(categories[i].getType() == Category.TYPE_USER) { showCat = true; break; } } } boolean show = showCat || forceHeaderVisible; if (!showCat) { if (cCategories != null && !cCategories.isDisposed()) { Control[] controls = cCategories.getChildren(); for (int i = 0; i < controls.length; i++) { controls[i].dispose(); } } } if (show) { if (cCategories == null || cCategories.isDisposed()) { buildHeaderArea(); } else { Control[] controls = cCategories.getChildren(); for (int i = 0; i < controls.length; i++) { controls[i].dispose(); } } if (showCat) { buildCat(categories); } } else { if (cHeader != null && !cHeader.isDisposed()) { cHeader.dispose(); } if (cTableParentPanel != null && !cTableParentPanel.isDisposed()) { cTableParentPanel.layout(); } } } /** * * * @since 4.1.0.5 */ private void buildHeaderArea() { GridData gridData; Composite parent = cTableParentPanel; cHeader = new Composite(parent, SWT.NONE); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalIndent = 5; cHeader.setLayoutData(gridData); cHeader.setLayout(new FormLayout()); FormData fd; lblHeader = new Label(cHeader, SWT.WRAP); updateTableLabel(); Label lblSep = new Label(cHeader, SWT.SEPARATOR | SWT.VERTICAL); gridData = new GridData(GridData.FILL_VERTICAL); gridData.heightHint = 5; lblSep.setLayoutData(gridData); btnFilter = new Button(cHeader, SWT.TOGGLE); Messages.setLanguageText(btnFilter, "MyTorrentsView.filter"); btnFilter.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { boolean enable = btnFilter.getSelection(); cFilterArea.setVisible(enable); if (enable) { tv.setFilterText(txtFilter.getText()); txtFilter.setFocus(); } else { tv.setFilterText(""); tv.setFocus(); } resizeHeader(); } public void widgetDefaultSelected(SelectionEvent e) { } }); boolean hasLastSearch = tv.getFilterText().length() != 0; btnFilter.setSelection(hasLastSearch); cFilterArea = new Composite(cHeader, SWT.NONE); cFilterArea.setVisible(hasLastSearch); GridLayout layout = new GridLayout(); layout.numColumns = 5; cFilterArea.setLayout(layout); cCategories = new Composite(cHeader, SWT.NONE); RowLayout rowLayout = new RowLayout(); rowLayout.marginTop = 0; rowLayout.marginBottom = 0; rowLayout.marginLeft = 3; rowLayout.marginRight = 0; rowLayout.spacing = 0; rowLayout.wrap = true; cCategories.setLayout(rowLayout); cSizer = new Composite(cHeader, SWT.NONE); fd = new FormData(); fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER); lblHeader.setLayoutData(fd); fd = new FormData(); fd.left = new FormAttachment(lblSep, 10); fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER); btnFilter.setLayoutData(fd); fd = new FormData(); fd.left = new FormAttachment(lblHeader, 10); fd.top = new FormAttachment(cFilterArea, 3, SWT.TOP); fd.bottom = new FormAttachment(cFilterArea, -3, SWT.BOTTOM); lblSep.setLayoutData(fd); fd = new FormData(); fd.left = new FormAttachment(btnFilter, 0); fd.right = new FormAttachment(cCategories, -10); cFilterArea.setLayoutData(fd); fd = new FormData(); fd.right = new FormAttachment(cSizer, -2); fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER); fd.bottom = new FormAttachment(cFilterArea, 0, SWT.BOTTOM); cCategories.setLayoutData(fd); int userMode = COConfigurationManager.getIntParameter("User Mode"); boolean enableSizer = userMode >= 2 && Constants.IS_CVS_VERSION; fd = new FormData(); fd.right = new FormAttachment(100, -2); fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER); fd.width = enableSizer ? 100 : 1; fd.height = enableSizer ? 18 : 1; cSizer.setLayoutData(fd); if (enableSizer) { tv.enableSizeSlider(cSizer, 16, 96); } cHeader.addListener(SWT.Resize, new Listener(){ public void handleEvent(Event event) { if (!resizeHeaderEventQueued) { resizeHeaderEventQueued = true; Utils.execSWTThreadLater(0, new AERunnable(){ public void runSupport() { resizeHeader(); resizeHeaderEventQueued = false; } }); } } }); txtFilter = new Text(cFilterArea, SWT.BORDER); Messages.setLanguageTooltip(txtFilter, "MyTorrentsView.filter.tooltip"); gridData = new GridData(GridData.FILL_HORIZONTAL); txtFilter.setLayoutData(gridData); lblX = new Label(cFilterArea, SWT.WRAP); Messages.setLanguageTooltip(lblX, "MyTorrentsView.clearFilter.tooltip"); gridData = new GridData(SWT.TOP); lblX.setLayoutData(gridData); ImageLoader.getInstance().setLabelImage(lblX, "smallx-gray"); lblX.setData("ImageID", "smallx-gray"); lblX.addMouseListener(new MouseAdapter() { public void mouseUp(MouseEvent e) { if (e.y <= 10) { tv.setFilterText(""); txtFilter.setText(""); } } }); lblSep = new Label(cFilterArea, SWT.SEPARATOR | SWT.VERTICAL); gridData = new GridData(GridData.FILL_VERTICAL); gridData.heightHint = 5; lblSep.setLayoutData(gridData); cHeader.moveAbove(null); parent.layout(true); tv.enableFilterCheck(txtFilter, this); } private void hideShowSlider() { if (!Constants.IS_CVS_VERSION) { return; } Utils.execSWTThread(new AERunnable() { public void runSupport() { int userMode = COConfigurationManager.getIntParameter("User Mode"); boolean isAdvanced = userMode >= 2; if (cSizer == null || cSizer.isDisposed()) { return; } FormData fd = (FormData) cSizer.getLayoutData(); if (isAdvanced) { if (fd.width < 100) { fd.width = 100; fd.height = 16; tv.enableSizeSlider(cSizer, 16, 96); cSizer.setVisible(false); cSizer.getParent().layout(true); } } else { if (fd.width == 100) { fd.width = 1; fd.height = 1; tv.disableSizeSlider(); cSizer.setVisible(true); cSizer.getParent().layout(true); } } } }); } /** * * * @since 4.1.0.5 */ protected void showFilterArea() { if (cFilterArea != null && !cFilterArea.isDisposed() && !cFilterArea.isVisible()) { cFilterArea.setVisible(true); } if (btnFilter != null && !btnFilter.isDisposed() && !btnFilter.getSelection()) { btnFilter.setSelection(true); } } /** * * * @since 4.1.0.5 */ protected void resizeHeader() { if (cCategories == null || cCategories.isDisposed()) { return; } Point curCatPos = cCategories.getLocation(); int posEndFilter = cFilterArea.getLocation().x + (cFilterArea.isVisible() ? 170 : 0); boolean onNewLine = ((FormData)cCategories.getLayoutData()).left != null; //System.out.println("posend=" + posEndFilter + ";curcat" + curCatPos); if (onNewLine) { Point prefSizeCat = cCategories.computeSize(SWT.DEFAULT, SWT.DEFAULT); //System.out.println("pref=" + prefSizeCat + ";sz=" + cHeader.getClientArea()); if (prefSizeCat.x + posEndFilter + cSizer.getSize().x < cHeader.getClientArea().width) { //System.out.println("MOVE UP"); FormData fd = new FormData(); fd.right = new FormAttachment(cSizer, -2); fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER); fd.bottom = new FormAttachment(cFilterArea, 0, SWT.BOTTOM); cCategories.setLayoutData(fd); fd = new FormData(); fd.left = new FormAttachment(btnFilter, 0); fd.right = new FormAttachment(cCategories, -10); cFilterArea.setLayoutData(fd); cHeader.getShell().layout(new Control[] { cFilterArea, cCategories }); } // assume on new line } else { if (curCatPos.x < posEndFilter) { //System.out.println("MOVE DOWN"); FormData fd = new FormData(); fd.top = new FormAttachment(cFilterArea, 2); fd.bottom = new FormAttachment(100, -3); fd.left = new FormAttachment(0,0); fd.right = new FormAttachment(100,0); cCategories.setLayoutData(fd); fd = new FormData(); fd.left = new FormAttachment(btnFilter, 0); fd.right = new FormAttachment(cSizer, -10); cFilterArea.setLayoutData(fd); cHeader.getShell().layout(new Control[] { cFilterArea, cCategories }); } } } /** * * * @param categories * @since 3.1.1.1 */ private void buildCat(Category[] categories) { int iFontPixelsHeight = 11; int iFontPointHeight = (iFontPixelsHeight * 72) / cCategories.getDisplay().getDPI().y; for (int i = 0; i < categories.length; i++) { final Category category = categories[i]; final Button catButton = new Button(cCategories, SWT.TOGGLE); catButton.addKeyListener(this); if (i == 0 && fontButton == null) { Font f = catButton.getFont(); FontData fd = f.getFontData()[0]; fd.setHeight(iFontPointHeight); fontButton = new Font(cCategories.getDisplay(), fd); } catButton.setText("|"); catButton.setFont(fontButton); catButton.pack(true); if (catButton.computeSize(100, SWT.DEFAULT).y > 0) { RowData rd = new RowData(); rd.height = catButton.computeSize(100, SWT.DEFAULT).y - 2 + catButton.getBorderWidth() * 2; catButton.setLayoutData(rd); } final String name = category.getName(); if (category.getType() == Category.TYPE_USER) catButton.setText(name); else Messages.setLanguageText(catButton, name); catButton.setData("Category", category); if (category == currentCategory) { catButton.setSelection(true); } catButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Button curButton = (Button) e.widget; boolean isEnabled = curButton.getSelection(); Control[] controls = cCategories.getChildren(); if (!isEnabled) { for (int i = 0; i < controls.length; i++) { if (controls[i] instanceof Button) { curButton = (Button) controls[i]; break; } } } for (int i = 0; i < controls.length; i++) { if (!(controls[i] instanceof Button)) { continue; } Button b = (Button) controls[i]; if (b != curButton && b.getSelection()) b.setSelection(false); else if (b == curButton && !b.getSelection()) b.setSelection(true); } activateCategory((Category) curButton.getData("Category")); } }); catButton.addListener(SWT.MouseHover, new Listener() { public void handleEvent(Event event) { Button curButton = (Button) event.widget; Category curCategory = (Category) curButton.getData("Category"); List dms = curCategory.getDownloadManagers(globalManager.getDownloadManagers()); long ttlActive = 0; long ttlSize = 0; long ttlRSpeed = 0; long ttlSSpeed = 0; int count = 0; for (Iterator iter = dms.iterator(); iter.hasNext();) { DownloadManager dm = (DownloadManager) iter.next(); if (!isInCategory(dm, currentCategory)) continue; count++; if (dm.getState() == DownloadManager.STATE_DOWNLOADING || dm.getState() == DownloadManager.STATE_SEEDING) ttlActive++; ttlSize += dm.getSize(); ttlRSpeed += dm.getStats().getDataReceiveRate(); ttlSSpeed += dm.getStats().getDataSendRate(); } String up_details = ""; String down_details = ""; if (category.getType() != Category.TYPE_ALL) { String up_str = MessageText.getString("GeneralView.label.maxuploadspeed"); String down_str = MessageText.getString("GeneralView.label.maxdownloadspeed"); String unlimited_str = MessageText.getString("MyTorrentsView.menu.setSpeed.unlimited"); int up_speed = category.getUploadSpeed(); int down_speed = category.getDownloadSpeed(); up_details = up_str + ": " + (up_speed == 0 ? unlimited_str : DisplayFormatters.formatByteCountToKiBEtc(up_speed)); down_details = down_str + ": " + (down_speed == 0 ? unlimited_str : DisplayFormatters.formatByteCountToKiBEtc(down_speed)); } if (count == 0) { curButton.setToolTipText(down_details + "\n" + up_details + "\nTotal: 0"); return; } curButton.setToolTipText((up_details.length() == 0 ? "" : (down_details + "\n" + up_details + "\n")) + "Total: " + count + "\n" + "Downloading/Seeding: " + ttlActive + "\n" + "\n" + "Speed: " + DisplayFormatters.formatByteCountToKiBEtcPerSec(ttlRSpeed / count) + "/" + DisplayFormatters.formatByteCountToKiBEtcPerSec(ttlSSpeed / count) + "\n" + "Size: " + DisplayFormatters.formatByteCountToKiBEtc(ttlSize)); } }); final DropTarget tabDropTarget = new DropTarget(catButton, DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK); Transfer[] types = new Transfer[] { TextTransfer.getInstance() }; tabDropTarget.setTransfer(types); tabDropTarget.addDropListener(new DropTargetAdapter() { public void dragOver(DropTargetEvent e) { if (drag_drop_line_start >= 0) e.detail = DND.DROP_MOVE; else e.detail = DND.DROP_NONE; } public void drop(DropTargetEvent e) { e.detail = DND.DROP_NONE; //System.out.println("DragDrop on Button:" + drag_drop_line_start); if (drag_drop_line_start >= 0) { drag_drop_line_start = -1; drag_drop_rows = null; TorrentUtil.assignToCategory(tv.getSelectedDataSources().toArray(), (Category) catButton.getData("Category")); } } }); catButton.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (tabDropTarget != null && !tabDropTarget.isDisposed()) { tabDropTarget.dispose(); } } }); final Menu menu = new Menu(catButton.getShell(), SWT.POP_UP); catButton.setMenu(menu); menu.addMenuListener(new MenuListener() { boolean bShown = false; public void menuHidden(MenuEvent e) { bShown = false; if (Constants.isOSX) return; // Must dispose in an asyncExec, otherwise SWT.Selection doesn't // get fired (async workaround provided by Eclipse Bug #87678) e.widget.getDisplay().asyncExec(new AERunnable() { public void runSupport() { if (bShown || menu.isDisposed()) return; MenuItem[] items = menu.getItems(); for (int i = 0; i < items.length; i++) { items[i].dispose(); } } }); } public void menuShown(MenuEvent e) { MenuItem[] items = menu.getItems(); for (int i = 0; i < items.length; i++) items[i].dispose(); bShown = true; if (category.getType() == Category.TYPE_USER) { final MenuItem itemDelete = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemDelete, "MyTorrentsView.menu.category.delete"); menu.setDefaultItem(itemDelete); itemDelete.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { Category catToDelete = (Category) catButton.getData("Category"); if (catToDelete != null) { java.util.List managers = catToDelete.getDownloadManagers(globalManager.getDownloadManagers()); // move to array,since setcategory removed it from the category, // which would mess up our loop DownloadManager dms[] = (DownloadManager[]) managers.toArray(new DownloadManager[managers.size()]); for (int i = 0; i < dms.length; i++) { dms[i].getDownloadState().setCategory(null); } if (currentCategory == catToDelete) { activateCategory(CategoryManager.getCategory(Category.TYPE_ALL)); } else { // always activate as deletion of this one might have // affected the current view activateCategory(currentCategory); } CategoryManager.removeCategory(catToDelete); } } }); } if (category.getType() != Category.TYPE_ALL) { long maxDownload = COConfigurationManager.getIntParameter( "Max Download Speed KBs", 0) * 1024; long maxUpload = COConfigurationManager.getIntParameter( "Max Upload Speed KBs", 0) * 1024; int down_speed = category.getDownloadSpeed(); int up_speed = category.getUploadSpeed(); ViewUtils.addSpeedMenu(menu.getShell(), menu, true, true, false, down_speed == 0, down_speed, down_speed, maxDownload, false, up_speed == 0, up_speed, up_speed, maxUpload, 1, new SpeedAdapter() { public void setDownSpeed(int val) { category.setDownloadSpeed(val); } public void setUpSpeed(int val) { category.setUploadSpeed(val); } }); } java.util.List managers = category.getDownloadManagers(globalManager.getDownloadManagers()); final DownloadManager dms[] = (DownloadManager[]) managers.toArray(new DownloadManager[managers.size()]); boolean start = false; boolean stop = false; for (int i = 0; i < dms.length; i++) { DownloadManager dm = dms[i]; stop = stop || ManagerUtils.isStopable(dm); start = start || ManagerUtils.isStartable(dm); } // Queue final MenuItem itemQueue = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemQueue, "MyTorrentsView.menu.queue"); Utils.setMenuItemImage(itemQueue, "start"); itemQueue.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { TorrentUtil.queueTorrents(dms, menu.getShell()); } }); itemQueue.setEnabled(start); // Stop final MenuItem itemStop = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemStop, "MyTorrentsView.menu.stop"); Utils.setMenuItemImage(itemStop, "stop"); itemStop.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { TorrentUtil.stopTorrents(dms, menu.getShell()); } }); itemStop.setEnabled(stop); // share with friends PluginInterface bpi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByClass( BuddyPlugin.class ); int cat_type = category.getType(); if ( bpi != null && cat_type != Category.TYPE_UNCATEGORIZED ){ final BuddyPlugin buddy_plugin = (BuddyPlugin)bpi.getPlugin(); if ( buddy_plugin.isEnabled()){ final Menu share_menu = new Menu(menu.getShell(), SWT.DROP_DOWN); final MenuItem share_item = new MenuItem(menu, SWT.CASCADE); Messages.setLanguageText(share_item, "azbuddy.ui.menu.cat.share" ); share_item.setMenu(share_menu); List buddies = buddy_plugin.getBuddies(); if ( buddies.size() == 0 ){ final MenuItem item = new MenuItem(share_menu, SWT.CHECK ); item.setText( MessageText.getString( "general.add.friends" )); item.setEnabled( false ); }else{ final String cname; if ( cat_type == Category.TYPE_ALL ){ cname = "All"; }else{ cname = category.getName(); } final boolean is_public = buddy_plugin.isPublicCategory( cname ); final MenuItem itemPubCat = new MenuItem(share_menu, SWT.CHECK ); Messages.setLanguageText( itemPubCat, "general.all.friends" ); itemPubCat.setSelection( is_public ); itemPubCat.addListener( SWT.Selection, new Listener() { public void handleEvent( Event event) { if ( is_public ){ buddy_plugin.removePublicCategory( cname ); }else{ buddy_plugin.addPublicCategory( cname ); } } }); new MenuItem(share_menu, SWT.SEPARATOR ); for ( final BuddyPluginBuddy buddy: buddies ){ if ( buddy.getNickName() == null ){ continue; } final boolean auth = buddy.isLocalRSSCategoryAuthorised( cname ); final MenuItem itemShare = new MenuItem(share_menu, SWT.CHECK ); itemShare.setText( buddy.getName()); itemShare.setSelection( auth || is_public ); if ( is_public ){ itemShare.setEnabled( false ); } itemShare.addListener( SWT.Selection, new Listener() { public void handleEvent( Event event) { if ( auth ){ buddy.removeLocalAuthorisedRSSCategory( cname ); }else{ buddy.addLocalAuthorisedRSSCategory( cname ); } } }); } } } } // options MenuItem itemOptions = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemOptions, "MainWindow.menu.view.configuration"); itemOptions.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); uiFunctions.openView(UIFunctions.VIEW_DM_MULTI_OPTIONS, dms); } }); if (dms.length == 0) { itemOptions.setEnabled(false); } } }); } cHeader.layout(true, true); Utils.execSWTThreadLater(0, new AERunnable(){ public void runSupport() { resizeHeader(); } }); // layout hack - relayout // if (catResizeAdapter == null) { // catResizeAdapter = new ControlAdapter() { // public void controlResized(ControlEvent event) { // if (getComposite().isDisposed() || cCategories.isDisposed()) // return; // // GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); // // int parentWidth = cCategories.getParent().getClientArea().width; // int catsWidth = cCategories.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; // // give text a 5 pixel right padding // int textWidth = 200; // System.out.println("TW=" + textWidth + ";" + (cHeader.computeSize(20, SWT.DEFAULT).x)); // // Object layoutData = cHeader.getLayoutData(); // if (layoutData instanceof GridData) { // GridData labelGrid = (GridData) layoutData; // textWidth += labelGrid.horizontalIndent; // } // // if (textWidth + catsWidth > parentWidth) { // gridData.widthHint = parentWidth - textWidth; // } // cCategories.setLayoutData(gridData); // cCategories.getParent().layout(true); // // } // }; // // tv.getTableComposite().addControlListener(catResizeAdapter); // } // // catResizeAdapter.controlResized(null); } public boolean isOurDownloadManager(DownloadManager dm) { if (!isInCategory(dm, currentCategory)) { return false; } boolean bCompleted = dm.isDownloadComplete(bDNDalwaysIncomplete); boolean bOurs = (bCompleted && isSeedingView) || (!bCompleted && !isSeedingView); // System.out.println("ourDM? " + sTableID + "; " + dm.getDisplayName() // + "; Complete=" + bCompleted + ";Ours=" + bOurs + ";bc" // + dm.getStats().getDownloadCompleted(false) + ";" // + dm.getStats().getDownloadCompleted(true)); return bOurs; } public boolean filterCheck(Object odm, String sLastSearch, boolean bRegexSearch) { boolean bOurs = true; DownloadManager dm = (DownloadManager) odm; if (sLastSearch.length() > 0) { try { String[][] names = { { "", dm.getDisplayName() }, { "t:", dm.getTorrent().getAnnounceURL().getHost() }, { "st:", "" + dm.getState() } }; String name = names[0][1]; String tmpSearch = sLastSearch; for (int i = 0; i < names.length; i++) { if (tmpSearch.startsWith(names[i][0])) { tmpSearch = tmpSearch.substring(names[i][0].length()); name = names[i][1]; } } String s = bRegexSearch ? tmpSearch : "\\Q" + tmpSearch.replaceAll("[|;]", "\\\\E|\\\\Q") + "\\E"; Pattern pattern = Pattern.compile(s, Pattern.CASE_INSENSITIVE); if (!pattern.matcher(name).find()) bOurs = false; } catch (Exception e) { // Future: report PatternSyntaxException message to user. } } return bOurs; } // @see org.gudy.azureus2.ui.swt.views.table.TableViewFilterCheck#filterSet(java.lang.String) public void filterSet(final String filter) { Utils.execSWTThread(new AERunnable(){ public void runSupport() { if (lblX != null && !lblX.isDisposed()) { String oldID = (String) lblX.getData("ImageID"); String id = filter.length() > 0 ? "smallx" : "smallx-gray"; if (oldID == null || !oldID.equals(id)) { ImageLoader.getInstance().setLabelImage(lblX, id); lblX.setData("ImageID", id); } } if (filter.length() > 0) { if (txtFilter == null) { createTabs(); } else { showFilterArea(); } } } }); } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#selected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void selected(TableRowCore[] rows) { updateSelectedContent(); refreshTorrentMenu(); refreshIconBar(); } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#deselected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void deselected(TableRowCore[] rows) { updateSelectedContent(); refreshTorrentMenu(); refreshIconBar(); } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#focusChanged(com.aelitis.azureus.ui.common.table.TableRowCore) public void focusChanged(TableRowCore focus) { refreshIconBar(); refreshTorrentMenu(); } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#mouseEnter(com.aelitis.azureus.ui.common.table.TableRowCore) public void mouseEnter(TableRowCore row) { } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#mouseExit(com.aelitis.azureus.ui.common.table.TableRowCore) public void mouseExit(TableRowCore row) { } public void updateSelectedContent() { if (cTablePanel == null || cTablePanel.isDisposed() || !cTablePanel.isVisible()) { return; } DownloadManager[] dms = getSelectedDownloads(); ISelectedContent[] sc = new ISelectedContent[dms.length]; int pos = 0; for (int i = 0; i < dms.length; i++) { DownloadManager dm = dms[i]; if (dm != null) { try { sc[pos] = new SelectedContent(dm); pos++; } catch (Exception e) { } } } if (pos != dms.length) { ISelectedContent[] sc_temp = new ISelectedContent[pos]; System.arraycopy(sc, 0, sc_temp, 0, pos); sc = sc_temp; } SelectedContentManager.changeCurrentlySelectedContent(tv.getTableID(), sc, tv); } private void refreshIconBar() { computePossibleActions(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } private void refreshTorrentMenu() { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null && uiFunctions instanceof UIFunctionsSWT) { ((UIFunctionsSWT)uiFunctions).refreshTorrentMenu(); } } public DownloadManager[] getSelectedDownloads() { Object[] data_sources = tv.getSelectedDataSources().toArray(); DownloadManager[] result = new DownloadManager[data_sources.length]; System.arraycopy(data_sources, 0, result, 0, result.length); return result; } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#defaultSelected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void defaultSelected(TableRowCore[] rows, int keyMask) { if (defaultSelectedListener != null) { defaultSelectedListener.defaultSelected(rows, keyMask); return; } showSelectedDetails(); } private void showSelectedDetails() { Object[] dm_sources = tv.getSelectedDataSources().toArray(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); for (int i = 0; i < dm_sources.length; i++) { if (dm_sources[i] == null) { continue; } if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_DM_DETAILS, (DownloadManager) dm_sources[i]); } } } public void overrideDefaultSelected(TableSelectionListener defaultSelectedListener) { this.defaultSelectedListener = defaultSelectedListener; } /* SubMenu for column specific tasks. */ // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener#addThisColumnSubMenu(java.lang.String, org.eclipse.swt.widgets.Menu) public void addThisColumnSubMenu(String sColumnName, Menu menuThisColumn) { if (sColumnName.equals("health")) { MenuItem item = new MenuItem(menuThisColumn, SWT.PUSH); Messages.setLanguageText(item, "MyTorrentsView.menu.health"); Utils.setMenuItemImage(item, "st_explain"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { HealthHelpWindow.show(Display.getDefault()); } }); } } // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener#fillMenu(java.lang.String, org.eclipse.swt.widgets.Menu) public void fillMenu(String sColumnName, final Menu menu) { Object[] dm_items = tv.getSelectedDataSources().toArray(); boolean hasSelection = (dm_items.length > 0); if (hasSelection) { DownloadManager[] dms = new DownloadManager[dm_items.length]; for (int i = 0; i < dm_items.length; i++) { dms[i] = (DownloadManager) dm_items[i]; } TorrentUtil.fillTorrentMenu(menu, dms, azureus_core, cTablePanel, true, (isSeedingView) ? 2 : 1, tv); // --- new MenuItem(menu, SWT.SEPARATOR); } } private void createDragDrop() { try { Transfer[] types = new Transfer[] { TextTransfer.getInstance() }; if (dragSource != null && !dragSource.isDisposed()) { dragSource.dispose(); } if (dropTarget != null && !dropTarget.isDisposed()) { dropTarget.dispose(); } dragSource = tv.createDragSource(DND.DROP_MOVE | DND.DROP_COPY); if (dragSource != null) { dragSource.setTransfer(types); dragSource.addDragListener(new DragSourceAdapter() { private String eventData; public void dragStart(DragSourceEvent event) { TableRowCore[] rows = tv.getSelectedRows(); if (rows.length != 0) { event.doit = true; // System.out.println("DragStart"); drag_drop_line_start = rows[0].getIndex(); drag_drop_rows = rows; } else { event.doit = false; drag_drop_line_start = -1; drag_drop_rows = null; } // Build eventData here because on OSX, selection gets cleared // by the time dragSetData occurs DownloadManager[] selectedDownloads = getSelectedDownloads(); eventData = "DownloadManager\n"; for (int i = 0; i < selectedDownloads.length; i++) { DownloadManager dm = selectedDownloads[i]; TOTorrent torrent = dm.getTorrent(); try { eventData += torrent.getHashWrapper().toBase32String() + "\n"; } catch (Exception e) { } } } public void dragSetData(DragSourceEvent event) { // System.out.println("DragSetData"); event.data = eventData; } }); } dropTarget = tv.createDropTarget(DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_TARGET_MOVE); if (dropTarget != null) { dropTarget.setTransfer(new Transfer[] { HTMLTransfer.getInstance(), URLTransfer.getInstance(), FileTransfer.getInstance(), TextTransfer.getInstance() }); dropTarget.addDropListener(new DropTargetAdapter() { public void dropAccept(DropTargetEvent event) { event.currentDataType = URLTransfer.pickBestType(event.dataTypes, event.currentDataType); } public void dragEnter(DropTargetEvent event) { // no event.data on dragOver, use drag_drop_line_start to determine // if ours if (drag_drop_line_start < 0) { if (event.detail != DND.DROP_COPY) { if ((event.operations & DND.DROP_LINK) > 0) event.detail = DND.DROP_LINK; else if ((event.operations & DND.DROP_COPY) > 0) event.detail = DND.DROP_COPY; } } else if (TextTransfer.getInstance().isSupportedType( event.currentDataType)) { event.detail = event.item == null ? DND.DROP_NONE : DND.DROP_MOVE; event.feedback = DND.FEEDBACK_SCROLL | DND.FEEDBACK_INSERT_BEFORE; } } public void dragOver(DropTargetEvent event) { if (drag_drop_line_start >= 0) { event.detail = event.item == null ? DND.DROP_NONE : DND.DROP_MOVE; event.feedback = DND.FEEDBACK_SCROLL | DND.FEEDBACK_INSERT_BEFORE; } } public void drop(DropTargetEvent event) { if (!(event.data instanceof String) || !((String) event.data).startsWith("DownloadManager\n")) { TorrentOpener.openDroppedTorrents(event, true); return; } event.detail = DND.DROP_NONE; // Torrent file from shell dropped if (drag_drop_line_start >= 0) { // event.data == null event.detail = DND.DROP_NONE; TableRowCore row = tv.getRow(event); if (row == null) return; int drag_drop_line_end = row.getIndex(); if (drag_drop_line_end != drag_drop_line_start) { DownloadManager dm = (DownloadManager) row.getDataSource(true); moveRowsTo(drag_drop_rows, dm.getPosition()); event.detail = DND.DROP_MOVE; } drag_drop_line_start = -1; drag_drop_rows = null; } } }); } } catch (Throwable t) { Logger.log(new LogEvent(LOGID, "failed to init drag-n-drop", t)); } } private void moveRowsTo(TableRowCore[] rows, int iNewPos) { if (rows == null || rows.length == 0) { return; } TableColumnCore sortColumn = tv.getSortColumn(); boolean isSortAscending = sortColumn == null ? true : sortColumn.isSortAscending(); for (int i = 0; i < rows.length; i++) { TableRowCore row = rows[i]; DownloadManager dm = (DownloadManager)row.getDataSource(true); if (dm == null) { continue; } int iOldPos = dm.getPosition(); globalManager.moveTo(dm, iNewPos); if (isSortAscending) { if (iOldPos > iNewPos) iNewPos++; } else { if (iOldPos < iNewPos) iNewPos--; } } boolean bForceSort = sortColumn.getName().equals("#"); tv.columnInvalidate("#"); tv.refreshTable(bForceSort); } // @see com.aelitis.azureus.ui.common.table.TableRefreshListener#tableRefresh() public void tableRefresh() { if (tv.isDisposed()) return; refreshTorrentMenu(); } // @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent) public void keyPressed(KeyEvent e) { int key = e.character; if (key <= 26 && key > 0) key += 'a' - 1; if (e.stateMask == (SWT.CTRL | SWT.SHIFT)) { // CTRL+SHIFT+S stop all Torrents if (key == 's') { ManagerUtils.asyncStopAll(); e.doit = false; return; } // Can't capture Ctrl-PGUP/DOWN for moving up/down in chunks // (because those keys move through tabs), so use shift-ctrl-up/down if (e.keyCode == SWT.ARROW_DOWN) { moveSelectedTorrents(10); e.doit = false; return; } if (e.keyCode == SWT.ARROW_UP) { moveSelectedTorrents(-10); e.doit = false; return; } } if (e.stateMask == SWT.MOD1) { switch (key) { case 'a': // CTRL+A select all Torrents if (e.widget != txtFilter) { tv.selectAll(); e.doit = false; } break; case 'c': // CTRL+C if (e.widget != txtFilter) { tv.clipboardSelected(); e.doit = false; } break; case 'i': // CTRL+I Info/Details showSelectedDetails(); e.doit = false; break; } if (!e.doit) return; } if (e.stateMask == SWT.CTRL) { switch (e.keyCode) { case SWT.ARROW_UP: moveSelectedTorrentsUp(); e.doit = false; break; case SWT.ARROW_DOWN: moveSelectedTorrentsDown(); e.doit = false; break; case SWT.HOME: moveSelectedTorrentsTop(); e.doit = false; break; case SWT.END: moveSelectedTorrentsEnd(); e.doit = false; break; } if (!e.doit) return; switch (key) { case 'r': // CTRL+R resume/start selected Torrents TorrentUtil.resumeTorrents(tv.getSelectedDataSources().toArray()); e.doit = false; break; case 's': // CTRL+S stop selected Torrents TorrentUtil.stopTorrents(tv.getSelectedDataSources().toArray(), cTablePanel.getShell()); e.doit = false; break; } if (!e.doit) return; } // DEL remove selected Torrents if (e.stateMask == 0 && e.keyCode == SWT.DEL && e.widget != txtFilter) { TorrentUtil.removeTorrents(tv.getSelectedDataSources().toArray(), cTablePanel.getShell()); e.doit = false; return; } if (e.keyCode != SWT.BS) { if ((e.stateMask & (~SWT.SHIFT)) != 0 || e.character < 32) return; } } public void keyReleased(KeyEvent e) { // ignore } private void moveSelectedTorrentsDown() { // Don't use runForSelectDataSources to ensure the order we want Object[] dataSources = tv.getSelectedDataSources().toArray(); Arrays.sort(dataSources, new Comparator() { public int compare (Object a, Object b) { return ((DownloadManager)a).getPosition() - ((DownloadManager)b).getPosition(); } }); for (int i = dataSources.length - 1; i >= 0; i--) { DownloadManager dm = (DownloadManager)dataSources[i]; if (dm.getGlobalManager().isMoveableDown(dm)) { dm.getGlobalManager().moveDown(dm); } } boolean bForceSort = tv.getSortColumn().getName().equals("#"); tv.columnInvalidate("#"); tv.refreshTable(bForceSort); } private void moveSelectedTorrentsUp() { // Don't use runForSelectDataSources to ensure the order we want Object[] dataSources = tv.getSelectedDataSources().toArray(); Arrays.sort(dataSources, new Comparator() { public int compare (Object a, Object b) { return ((DownloadManager)a).getPosition() - ((DownloadManager)b).getPosition(); } }); for (int i = 0; i < dataSources.length; i++) { DownloadManager dm = (DownloadManager)dataSources[i]; if (dm.getGlobalManager().isMoveableUp(dm)) { dm.getGlobalManager().moveUp(dm); } } boolean bForceSort = tv.getSortColumn().getName().equals("#"); tv.columnInvalidate("#"); tv.refreshTable(bForceSort); } private void moveSelectedTorrents(int by) { // Don't use runForSelectDataSources to ensure the order we want Object[] dataSources = tv.getSelectedDataSources().toArray(); if (dataSources.length <= 0) return; int[] newPositions = new int[dataSources.length]; if (by < 0) { Arrays.sort(dataSources, new Comparator() { public int compare(Object a, Object b) { return ((DownloadManager) a).getPosition() - ((DownloadManager) b).getPosition(); } }); } else { Arrays.sort(dataSources, new Comparator() { public int compare(Object a, Object b) { return ((DownloadManager) b).getPosition() - ((DownloadManager) a).getPosition(); } }); } int count = globalManager.downloadManagerCount(isSeedingView); for (int i = 0; i < dataSources.length; i++) { DownloadManager dm = (DownloadManager) dataSources[i]; int pos = dm.getPosition() + by; if (pos < i + 1) pos = i + 1; else if (pos > count - i) pos = count - i; newPositions[i] = pos; } for (int i = 0; i < dataSources.length; i++) { DownloadManager dm = (DownloadManager) dataSources[i]; globalManager.moveTo(dm, newPositions[i]); } boolean bForceSort = tv.getSortColumn().getName().equals("#"); tv.columnInvalidate("#"); tv.refreshTable(bForceSort); } private void moveSelectedTorrentsTop() { moveSelectedTorrentsTopOrEnd(true); } private void moveSelectedTorrentsEnd() { moveSelectedTorrentsTopOrEnd(false); } private void moveSelectedTorrentsTopOrEnd(boolean moveToTop) { Object[] datasources = tv.getSelectedDataSources().toArray(); if (datasources.length == 0) return; DownloadManager[] downloadManagers = new DownloadManager[datasources.length]; System.arraycopy(datasources, 0, downloadManagers, 0, datasources.length); if(moveToTop) globalManager.moveTop(downloadManagers); else globalManager.moveEnd(downloadManagers); boolean bForceSort = tv.getSortColumn().getName().equals("#"); if (bForceSort) { tv.columnInvalidate("#"); tv.refreshTable(bForceSort); } } /** * @param parameterName the name of the parameter that has changed * @see org.gudy.azureus2.core3.config.ParameterListener#parameterChanged(java.lang.String) */ public void parameterChanged(String parameterName) { if (parameterName == null || parameterName.equals("DND Always In Incomplete")) { bDNDalwaysIncomplete = COConfigurationManager.getBooleanParameter("DND Always In Incomplete"); } if (parameterName == null || parameterName.equals("MyTorrentsView.alwaysShowHeader")) { setForceHeaderVisible(COConfigurationManager.getBooleanParameter("MyTorrentsView.alwaysShowHeader")); } if (parameterName == null || parameterName.equals("User Mode")) { hideShowSlider(); } } private boolean top,bottom,up,down,run,start,stop,remove; private void computePossibleActions() { Object[] dataSources = tv.getSelectedDataSources().toArray(); // enable up and down so that we can do the "selection rotate trick" up = down = run = remove = (dataSources.length > 0); top = bottom = start = stop = false; for (int i = 0; i < dataSources.length; i++) { DownloadManager dm = (DownloadManager)dataSources[i]; if(!start && ManagerUtils.isStartable(dm)) start = true; if(!stop && ManagerUtils.isStopable(dm)) stop = true; if(!top && dm.getGlobalManager().isMoveableUp(dm)) top = true; if(!bottom && dm.getGlobalManager().isMoveableDown(dm)) bottom = true; } } public boolean isEnabled(String itemKey) { if(itemKey.equals("run")) return run; if(itemKey.equals("start")) return start; if(itemKey.equals("stop")) return stop; if(itemKey.equals("remove")) return remove; if(itemKey.equals("top")) return top; if(itemKey.equals("bottom")) return bottom; if(itemKey.equals("up")) return up; if(itemKey.equals("down")) return down; if(itemKey.equals("share")) return remove; if(itemKey.equals("transcode")) return remove; return super.isEnabled(itemKey); } public void itemActivated(String itemKey) { if(itemKey.equals("top")) { moveSelectedTorrentsTop(); return; } if(itemKey.equals("bottom")){ moveSelectedTorrentsEnd(); return; } if(itemKey.equals("up")) { moveSelectedTorrentsUp(); return; } if(itemKey.equals("down")){ moveSelectedTorrentsDown(); return; } if(itemKey.equals("run")){ TorrentUtil.runTorrents(tv.getSelectedDataSources().toArray()); return; } if(itemKey.equals("start")){ TorrentUtil.queueTorrents(tv.getSelectedDataSources().toArray(), cTablePanel.getShell()); return; } if(itemKey.equals("stop")){ TorrentUtil.stopTorrents(tv.getSelectedDataSources().toArray(), cTablePanel.getShell()); return; } if(itemKey.equals("remove")){ TorrentUtil.removeTorrents(tv.getSelectedDataSources().toArray(), cTablePanel.getShell()); return; } super.itemActivated(itemKey); } // categorymanagerlistener Functions public void downloadManagerAdded(Category category, final DownloadManager manager) { if (isOurDownloadManager(manager)) { tv.addDataSource(manager); } } public void downloadManagerRemoved(Category category, DownloadManager removed) { tv.removeDataSource(removed); } // DownloadManagerListener Functions public void stateChanged(DownloadManager manager, int state) { final TableRowCore row = tv.getRow(manager); if (row != null) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { row.refresh(true); if (row.isSelected()) { refreshIconBar(); } } }); } } // DownloadManagerListener public void positionChanged(DownloadManager download, int oldPosition, int newPosition) { if (isOurDownloadManager(download)) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { refreshIconBar(); } }); } } // DownloadManagerListener public void filePriorityChanged(DownloadManager download, DiskManagerFileInfo file) { } // DownloadManagerListener public void completionChanged(final DownloadManager manager, boolean bCompleted) { // manager has moved lists if (isOurDownloadManager(manager)) { // only make the download visible if it satisfies the category selection if (currentCategory == null || currentCategory.getType() == Category.TYPE_ALL) { tv.addDataSource(manager); } else { int catType = currentCategory.getType(); Category manager_category = manager.getDownloadState().getCategory(); if (manager_category == null) { if (catType == Category.TYPE_UNCATEGORIZED) { tv.addDataSource(manager); } } else { if (currentCategory.getName().equals(manager_category.getName())) tv.addDataSource(manager); } } } else if ((isSeedingView && !bCompleted) || (!isSeedingView && bCompleted)) { tv.removeDataSource(manager); } } // DownloadManagerListener public void downloadComplete(DownloadManager manager) { } /** * Rebuild the table based on the category activated * * @param category */ private void activateCategory(Category category) { if (category != currentCategory) { if (currentCategory != null) currentCategory.removeCategoryListener(this); if (category != null) category.addCategoryListener(this); currentCategory = category; } Object[] managers = globalManager.getDownloadManagers().toArray(); Set existing = new HashSet(tv.getDataSources()); List listRemoves = new ArrayList(); List listAdds = new ArrayList(); for (int i = 0; i < managers.length; i++) { DownloadManager dm = (DownloadManager) managers[i]; boolean bHave = existing.contains(dm); if (!isOurDownloadManager(dm)) { if (bHave) { listRemoves.add(dm); } } else { if (!bHave) { listAdds.add(dm); } } } tv.removeDataSources(listRemoves.toArray()); tv.addDataSources(listAdds.toArray()); tv.processDataSourceQueue(); //tv.refreshTable(false); } public boolean isInCurrentCategory(DownloadManager manager) { return isInCategory(manager, currentCategory); } private boolean isInCategory(DownloadManager manager, Category category) { if (category == null) { return true; } int type = category.getType(); if (type == Category.TYPE_ALL) { return true; } Category dmCategory = manager.getDownloadState().getCategory(); if (dmCategory == null) { return type == Category.TYPE_UNCATEGORIZED; } return category.equals(dmCategory); } // CategoryManagerListener Functions public void categoryAdded(Category category) { Utils.execSWTThread( new AERunnable() { public void runSupport() { createTabs(); } }); } public void categoryRemoved(Category category) { Utils.execSWTThread( new AERunnable() { public void runSupport() { createTabs(); } }); } // globalmanagerlistener Functions public void downloadManagerAdded( DownloadManager dm ) { dm.addListener( this ); downloadManagerAdded(null, dm); } public void downloadManagerRemoved( DownloadManager dm ) { dm.removeListener( this ); DownloadBar.close(dm); downloadManagerRemoved(null, dm); } public void destroyInitiated() { } public void destroyed() { } public void seedingStatusChanged( boolean seeding_only_mode, boolean b ){} // End of globalmanagerlistener Functions // @see com.aelitis.azureus.ui.common.table.TableCountChangeListener#rowAdded(com.aelitis.azureus.ui.common.table.TableRowCore) public void rowAdded(TableRowCore row) { updateTableLabel(); } // @see com.aelitis.azureus.ui.common.table.TableCountChangeListener#rowRemoved(com.aelitis.azureus.ui.common.table.TableRowCore) public void rowRemoved(TableRowCore row) { updateTableLabel(); } public void updateLanguage() { super.updateLanguage(); updateTableLabel(); getComposite().layout(true, true); } /** * */ private boolean refreshingTableLabel = false; private void updateTableLabel() { if (refreshingTableLabel || lblHeader == null || lblHeader.isDisposed()) { return; } refreshingTableLabel = true; lblHeader.getDisplay().asyncExec(new AERunnable() { public void runSupport() { try { if (lblHeader != null && !lblHeader.isDisposed()) { String sText = MessageText.getString(tv.getTableID() + "View" + ".header") + " (" + tv.size(true) + ")"; lblHeader.setText(sText); lblHeader.getParent().layout(); } } finally { refreshingTableLabel = false; } } }); } public boolean isTableFocus() { return viewActive; //return tv.isTableFocus(); } public Image obfusticatedImage(final Image image, Point shellOffset) { return tv.obfusticatedImage(image, shellOffset); } /** * Creates and return an TableViewSWT * Subclasses my override to return a different TableViewSWT if needed * @param basicItems * @return */ protected TableViewSWT createTableView(Class forDataSourceType, String tableID, TableColumnCore[] basicItems) { int tableExtraStyle = COConfigurationManager.getIntParameter("MyTorrentsView.table.style"); return new TableViewSWTImpl(forDataSourceType, tableID, getPropertiesPrefix(), basicItems, "#", tableExtraStyle | SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL) { protected void setSelectedRowIndexes(int[] newSelectedRowIndices) { super.setSelectedRowIndexes(newSelectedRowIndices); updateSelectedContent(); } }; } /** * Returns the default row height for the table * Subclasses my override to return a different height if needed; a height of -1 means use default * @return */ protected int getRowDefaultHeight(){ return -1; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/file/0000755000175000017500000000000011310377636021472 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/file/FileInfoView.java0000644000175000017500000003121411272502252024653 0ustar adrianadrian/* * File : PeerInfoView.java * Created : Oct 2, 2005 * By : TuxPaper * * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.file; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.disk.DiskManagerPiece; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.Legend; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.views.AbstractIView; import org.gudy.azureus2.ui.swt.views.IViewExtension; public class FileInfoView extends AbstractIView implements IViewExtension { private final static int BLOCK_FILLSIZE = 14; private final static int BLOCK_SPACING = 2; private final static int BLOCK_SIZE = BLOCK_FILLSIZE + BLOCK_SPACING; private final static int BLOCKCOLOR_DONE = 0; private final static int BLOCKCOLOR_SKIPPED = 1; private final static int BLOCKCOLOR_ACTIVE = 2; private final static int BLOCKCOLOR_NEEDED = 3; private Composite fileInfoComposite; private ScrolledComposite sc; protected Canvas fileInfoCanvas; private Color[] blockColors; private Label topLabel; // More delay for this view because of high workload private int graphicsUpdate = COConfigurationManager .getIntParameter("Graphics Update") * 2; private int loopFactor = 0; private DiskManagerFileInfo file; private Font font = null; Image img = null; // accessed only in SWT Thread private boolean refreshInfoCanvasQueued; /** * Initialize * */ public FileInfoView() { blockColors = new Color[] { Colors.blues[Colors.BLUES_DARKEST], Colors.white, Colors.red, Colors.green, }; } public void dataSourceChanged(Object newDataSource) { if (newDataSource == null) file = null; else if (newDataSource instanceof Object[]) file = (DiskManagerFileInfo) ((Object[]) newDataSource)[0]; else file = (DiskManagerFileInfo) newDataSource; fillFileInfoSection(); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#getData() */ public String getData() { return "FileView.BlockView.title"; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#initialize(org.eclipse.swt.widgets.Composite) */ public void initialize(Composite composite) { if (fileInfoComposite != null && !fileInfoComposite.isDisposed()) { Logger.log(new LogEvent(LogIDs.GUI, LogEvent.LT_ERROR, "FileInfoView already initialized! Stack: " + Debug.getStackTrace(true, false))); delete(); } createFileInfoPanel(composite); } private Composite createFileInfoPanel(Composite parent) { GridLayout layout; GridData gridData; // Peer Info section contains // - Peer's Block display // - Peer's Datarate fileInfoComposite = new Composite(parent, SWT.NONE); layout = new GridLayout(); layout.numColumns = 2; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; fileInfoComposite.setLayout(layout); gridData = new GridData(GridData.FILL, GridData.FILL, true, true); fileInfoComposite.setLayoutData(gridData); new Label(fileInfoComposite, SWT.NULL).setLayoutData(new GridData()); topLabel = new Label(fileInfoComposite, SWT.NULL); gridData = new GridData(SWT.FILL, SWT.DEFAULT, false, false); topLabel.setLayoutData(gridData); sc = new ScrolledComposite(fileInfoComposite, SWT.V_SCROLL); sc.setExpandHorizontal(true); sc.setExpandVertical(true); layout = new GridLayout(); layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; sc.setLayout(layout); gridData = new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1); sc.setLayoutData(gridData); fileInfoCanvas = new Canvas(sc, SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND); gridData = new GridData(GridData.FILL, SWT.DEFAULT, true, false); fileInfoCanvas.setLayoutData(gridData); fileInfoCanvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { if (e.width <= 0 || e.height <= 0) return; try { Rectangle bounds = (img == null) ? null : img.getBounds(); if (bounds == null) { e.gc.fillRectangle(e.x, e.y, e.width, e.height); } else { if (e.x + e.width > bounds.width) e.gc.fillRectangle(bounds.width, e.y, e.x + e.width - bounds.width + 1, e.height); if (e.y + e.height > bounds.height) e.gc.fillRectangle(e.x, bounds.height, e.width, e.y + e.height - bounds.height + 1); int width = Math.min(e.width, bounds.width - e.x); int height = Math.min(e.height, bounds.height - e.y); e.gc.drawImage(img, e.x, e.y, width, height, e.x, e.y, width, height); } } catch (Exception ex) { } } }); fileInfoCanvas.addMouseTrackListener( new MouseTrackAdapter() { public void mouseHover( MouseEvent event ) { showPieceDetails( event.x, event.y ); } }); Listener doNothingListener = new Listener() { public void handleEvent(Event event) { } }; fileInfoCanvas.addListener(SWT.KeyDown, doNothingListener); fileInfoCanvas.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { if (refreshInfoCanvasQueued) { return; } refreshInfoCanvasQueued = true; // wrap in asyncexec because sc.setMinWidth (called later) doesn't work // too well inside a resize (the canvas won't size isn't always updated) Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { if (img != null) { int iOldColCount = img.getBounds().width / BLOCK_SIZE; int iNewColCount = fileInfoCanvas.getClientArea().width / BLOCK_SIZE; if (iOldColCount != iNewColCount) refreshInfoCanvas(); } } }); } }); sc.setContent(fileInfoCanvas); Legend.createLegendComposite(fileInfoComposite, blockColors, new String[] { "FileView.BlockView.Done", "FileView.BlockView.Skipped", "FileView.BlockView.Active", "FileView.BlockView.Outstanding", }, new GridData(SWT.FILL,SWT.DEFAULT, true, false, 2, 1)); int iFontPixelsHeight = 10; int iFontPointHeight = (iFontPixelsHeight * 72) / fileInfoCanvas.getDisplay().getDPI().y; Font f = fileInfoCanvas.getFont(); FontData[] fontData = f.getFontData(); fontData[0].setHeight(iFontPointHeight); font = new Font(fileInfoCanvas.getDisplay(), fontData); return fileInfoComposite; } public void fillFileInfoSection() { topLabel.setText( "" ); refreshInfoCanvas(); } public void refresh() { super.refresh(); if (loopFactor++ % graphicsUpdate == 0) { refreshInfoCanvas(); } } protected void showPieceDetails( int x, int y ) { Rectangle bounds = fileInfoCanvas.getClientArea(); if (bounds.width <= 0 || bounds.height <= 0){ return; } if ( file == null ){ return; } DownloadManager download_manager = file.getDownloadManager(); if ( download_manager == null ){ return; } DiskManager disk_manager = download_manager.getDiskManager(); PEPeerManager peer_manager = download_manager.getPeerManager(); if (disk_manager == null || peer_manager == null ){ return; } DiskManagerPiece[] dm_pieces = disk_manager.getPieces(); PEPiece[] pe_pieces = peer_manager.getPieces(); int first_piece = file.getFirstPieceNumber(); int num_pieces = file.getNbPieces(); int iNumCols = bounds.width / BLOCK_SIZE; int x_block = x/BLOCK_SIZE; int y_block = y/BLOCK_SIZE; int piece_number = y_block*iNumCols + x_block + first_piece; if ( piece_number >= first_piece && piece_number < first_piece + num_pieces ){ DiskManagerPiece dm_piece = dm_pieces[piece_number]; PEPiece pe_piece = pe_pieces[piece_number]; String text = "Piece " + piece_number + ": " + dm_piece.getString(); if ( pe_piece != null ){ text += ", active: " + pe_piece.getString(); }else{ if ( dm_piece.isNeeded() && !dm_piece.isDone()){ text += ", inactive: " + peer_manager.getPiecePicker().getPieceString( piece_number ); } } topLabel.setText( text ); }else{ topLabel.setText( "" ); } } protected void refreshInfoCanvas() { refreshInfoCanvasQueued = false; Rectangle bounds = fileInfoCanvas.getClientArea(); if (bounds.width <= 0 || bounds.height <= 0) return; if (img != null && !img.isDisposed()) { img.dispose(); img = null; } DownloadManager download_manager = file==null?null:file.getDownloadManager(); DiskManager disk_manager = download_manager==null?null:download_manager.getDiskManager(); PEPeerManager peer_manager = download_manager==null?null:download_manager.getPeerManager(); if ( file == null || disk_manager == null || peer_manager == null ) { GC gc = new GC(fileInfoCanvas); gc.fillRectangle(bounds); gc.dispose(); return; } int first_piece = file.getFirstPieceNumber(); int num_pieces = file.getNbPieces(); int iNumCols = bounds.width / BLOCK_SIZE; int iNeededHeight = (((num_pieces - 1) / iNumCols) + 1) * BLOCK_SIZE; if (sc.getMinHeight() != iNeededHeight) { sc.setMinHeight(iNeededHeight); sc.layout(true, true); bounds = fileInfoCanvas.getClientArea(); } img = new Image(fileInfoCanvas.getDisplay(), bounds.width, iNeededHeight); GC gcImg = new GC(img); try { gcImg.setBackground(fileInfoCanvas.getBackground()); gcImg.fillRectangle(0, 0, bounds.width, bounds.height); DiskManagerPiece[] dm_pieces = disk_manager.getPieces(); PEPiece[] pe_pieces = peer_manager.getPieces(); int iRow = 0; int iCol = 0; for (int i = first_piece; i < first_piece+num_pieces; i++) { DiskManagerPiece dm_piece = dm_pieces[i]; PEPiece pe_piece = pe_pieces[i]; int colorIndex; int iXPos = iCol * BLOCK_SIZE; int iYPos = iRow * BLOCK_SIZE; if ( dm_piece.isDone()){ colorIndex = BLOCKCOLOR_DONE; }else if ( !dm_piece.isNeeded()){ colorIndex = BLOCKCOLOR_SKIPPED; }else if ( pe_piece != null ){ colorIndex = BLOCKCOLOR_ACTIVE; }else{ colorIndex = BLOCKCOLOR_NEEDED; } gcImg.setBackground(blockColors[colorIndex]); gcImg.fillRectangle(iXPos, iYPos, BLOCK_FILLSIZE, BLOCK_FILLSIZE); iCol++; if (iCol >= iNumCols) { iCol = 0; iRow++; } } } catch (Exception e) { Logger.log(new LogEvent(LogIDs.GUI, "drawing piece map", e)); } finally { gcImg.dispose(); } fileInfoCanvas.redraw(); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#getComposite() */ public Composite getComposite() { return fileInfoComposite; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#delete() */ public void delete() { if (img != null && !img.isDisposed()) { img.dispose(); img = null; } if (font != null && !font.isDisposed()) { font.dispose(); font = null; } super.delete(); } public Menu getPrivateMenu() { return null; } public void viewActivated() { refreshInfoCanvas(); } public void viewDeactivated() { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/MyTorrentsSuperView.java0000644000175000017500000003007211171750562025416 0ustar adrianadrian/* * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.debug.ObfusticateImage; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import org.gudy.azureus2.plugins.ui.tables.TableManager; /** * @author MjrTom * 2005/Dec/08: Avg Avail Item */ public class MyTorrentsSuperView extends AbstractIView implements ObfusticateImage, IViewExtension { private static int SASH_WIDTH = 5; private MyTorrentsView torrentview; private MyTorrentsView seedingview; private Composite form; private MyTorrentsView lastSelectedView; private Composite child1; private Composite child2; public MyTorrentsSuperView() { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { Utils.execSWTThread(new AERunnable() { public void runSupport() { TableColumnManager tcManager = TableColumnManager.getInstance(); tcManager.addColumns(getCompleteColumns()); tcManager.addColumns(getIncompleteColumns()); } }); } }); } public Composite getComposite() { return form; } public void delete() { if (torrentview != null) torrentview.delete(); if (seedingview != null) seedingview.delete(); super.delete(); } public void initialize(final Composite parent) { if (form != null) { return; } form = new Composite(parent, SWT.NONE); FormLayout flayout = new FormLayout(); flayout.marginHeight = 0; flayout.marginWidth = 0; form.setLayout(flayout); GridData gridData; gridData = new GridData(GridData.FILL_BOTH); form.setLayoutData(gridData); GridLayout layout; child1 = new Composite(form,SWT.NULL); layout = new GridLayout(); layout.numColumns = 1; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; child1.setLayout(layout); final Sash sash = new Sash(form, SWT.HORIZONTAL); child2 = new Composite(form,SWT.NULL); layout = new GridLayout(); layout.numColumns = 1; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; child2.setLayout(layout); FormData formData; // FormData for table child1 formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.top = new FormAttachment(0, 0); child1.setLayoutData(formData); final FormData child1Data = formData; // sash formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.top = new FormAttachment(child1); formData.height = SASH_WIDTH; sash.setLayoutData(formData); // child2 formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.bottom = new FormAttachment(100, 0); formData.top = new FormAttachment(sash); // More precision, times by 100 int weight = (int) (COConfigurationManager.getFloatParameter("MyTorrents.SplitAt")); if (weight > 10000) { weight = 10000; } else if (weight < 100) { weight *= 100; } // Min/max of 5%/95% if (weight < 500) { weight = 500; } else if (weight > 9000) { weight = 9000; } // height will be set on first resize call sash.setData("PCT", new Double((float)weight / 10000)); child2.setLayoutData(formData); // Listeners to size the folder sash.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { final boolean FASTDRAG = true; if (FASTDRAG && e.detail == SWT.DRAG) return; child1Data.height = e.y + e.height - SASH_WIDTH; form.layout(); Double l = new Double((double) child1.getBounds().height / form.getBounds().height); sash.setData("PCT", l); if (e.detail != SWT.DRAG) { int i = (int) (l.doubleValue() * 10000); COConfigurationManager.setParameter("MyTorrents.SplitAt", i); } } }); form.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { Double l = (Double) sash.getData("PCT"); if (l != null) { child1Data.height = (int) (form.getBounds().height * l .doubleValue()); form.layout(); } } }); try { Double l = (Double) sash.getData("PCT"); if (l != null) { child1Data.height = (int) (form.getBounds().height * l .doubleValue()); } } catch (Exception e) { } AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(final AzureusCore core) { Utils.execSWTThread(new AERunnable() { public void runSupport() { initializeWithCore(core, parent); } }); } }); } private void initializeWithCore(AzureusCore core, Composite parent) { torrentview = createTorrentView(core, TableManager.TABLE_MYTORRENTS_INCOMPLETE, false, getIncompleteColumns(), child1); seedingview = createTorrentView(core, TableManager.TABLE_MYTORRENTS_COMPLETE, true, getCompleteColumns(), child2); initializeDone(); } public void initializeDone() { } public void refresh() { if (getComposite() == null || getComposite().isDisposed()) return; if (seedingview != null) { seedingview.refresh(); } if (torrentview != null) { torrentview.refresh(); } } public void updateLanguage() { // no super call, the views will do their own if (getComposite() == null || getComposite().isDisposed()) return; if (seedingview != null) { seedingview.updateLanguage(); } if (torrentview != null) { torrentview.updateLanguage(); } } public String getFullTitle() { return MessageText.getString("MyTorrentsView.mytorrents"); } // XXX: Is there an easier way to find out what has the focus? private MyTorrentsView getCurrentView() { // wrap in a try, since the controls may be disposed try { if (torrentview != null && torrentview.isTableFocus()) lastSelectedView = torrentview; else if (seedingview != null && seedingview.isTableFocus()) lastSelectedView = seedingview; } catch (Exception ignore) {/*ignore*/} return lastSelectedView; } // IconBarEnabler public boolean isEnabled(String itemKey) { IView currentView = getCurrentView(); if (currentView != null) return currentView.isEnabled(itemKey); else return false; } // IconBarEnabler // @see org.gudy.azureus2.ui.swt.views.AbstractIView#itemActivated(java.lang.String) public void itemActivated(String itemKey) { IView currentView = getCurrentView(); if (currentView != null) currentView.itemActivated(itemKey); } public DownloadManager[] getSelectedDownloads() { MyTorrentsView currentView = getCurrentView(); if (currentView == null) {return null;} return currentView.getSelectedDownloads(); } public void generateDiagnostics( IndentWriter writer ) { super.generateDiagnostics( writer ); try{ writer.indent(); writer.println( "Downloading" ); writer.indent(); torrentview.generateDiagnostics( writer ); }finally{ writer.exdent(); writer.exdent(); } try{ writer.indent(); writer.println( "Seeding" ); writer.indent(); seedingview.generateDiagnostics( writer ); }finally{ writer.exdent(); writer.exdent(); } } public Image obfusticatedImage(Image image, Point shellOffset) { if (torrentview != null) { torrentview.obfusticatedImage(image, shellOffset); } if (seedingview != null) { seedingview.obfusticatedImage(image, shellOffset); } return image; } public Menu getPrivateMenu() { return null; } public void viewActivated() { SelectedContentManager.clearCurrentlySelectedContent(); IView currentView = getCurrentView(); if (currentView instanceof IViewExtension) { ((IViewExtension)currentView).viewActivated(); } if (currentView instanceof MyTorrentsView) { ((MyTorrentsView)currentView).updateSelectedContent(); } } public void viewDeactivated() { IView currentView = getCurrentView(); if (currentView == null) {return;} if (currentView instanceof IViewExtension) { ((IViewExtension)currentView).viewDeactivated(); } /* String ID = currentView.getShortTitle(); if (currentView instanceof MyTorrentsView) { ID = ((MyTorrentsView)currentView).getTableView().getTableID(); } TableView tv = null; if (currentView instanceof MyTorrentsView) { tv = ((MyTorrentsView) currentView).getTableView(); } //SelectedContentManager.clearCurrentlySelectedContent(); SelectedContentManager.changeCurrentlySelectedContent(ID, null, tv); */ } /** * Returns the set of columns for the incomplete torrents view * Subclasses my override to return a different set of columns * @return */ protected TableColumnCore[] getIncompleteColumns(){ return TableColumnCreator.createIncompleteDM(TableManager.TABLE_MYTORRENTS_INCOMPLETE); } /** * Returns the set of columns for the completed torrents view * Subclasses my override to return a different set of columns * @return */ protected TableColumnCore[] getCompleteColumns(){ return TableColumnCreator.createCompleteDM(TableManager.TABLE_MYTORRENTS_COMPLETE); } /** * Returns an instance of MyTorrentsView * Subclasses my override to return a different instance of MyTorrentsView * @param _azureus_core * @param isSeedingView * @param columns * @param child1 * @return */ protected MyTorrentsView createTorrentView(AzureusCore _azureus_core, String tableID, boolean isSeedingView, TableColumnCore[] columns, Composite c) { MyTorrentsView view = new MyTorrentsView(_azureus_core, tableID, isSeedingView, columns); view.initialize(c); c.addListener(SWT.Activate, new Listener() { public void handleEvent(Event event) { viewActivated(); } }); c.addListener(SWT.Deactivate, new Listener() { public void handleEvent(Event event) { viewDeactivated(); } }); return view; } public MyTorrentsView getTorrentview() { return torrentview; } public MyTorrentsView getSeedingview() { return seedingview; } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/MySharesView.java0000644000175000017500000004432211275142106024001 0ustar adrianadrian/* * File : MySharesView.java * Created : 18-Jan-2004 * By : parg * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.category.Category; import org.gudy.azureus2.core3.category.CategoryManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.sharing.*; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.tracker.Tracker; import org.gudy.azureus2.plugins.tracker.TrackerTorrent; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentManagerImpl; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab; import org.gudy.azureus2.ui.swt.views.tableitems.myshares.CategoryItem; import org.gudy.azureus2.ui.swt.views.tableitems.myshares.NameItem; import org.gudy.azureus2.ui.swt.views.tableitems.myshares.TypeItem; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.table.*; /** * @author parg * @author TuxPaper * 2004/Apr/20: Remove need for tableItemToObject * 2004/Apr/21: extends TableView instead of IAbstractView */ public class MySharesView extends TableViewTab implements ShareManagerListener, TableLifeCycleListener, TableViewSWTMenuFillListener, TableRefreshListener, TableSelectionListener { private static final TableColumnCore[] basicItems = { new NameItem(), new TypeItem(), new CategoryItem(), }; protected static final TorrentAttribute category_attribute = TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_CATEGORY ); private Menu menuCategory; private TableViewSWTImpl tv; public MySharesView() { super("MySharesView"); tv = new TableViewSWTImpl(ShareResource.class, TableManager.TABLE_MYSHARES, getPropertiesPrefix(), basicItems, "name", SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL); tv.addSelectionListener(new TableSelectionAdapter() { public void defaultSelected(TableRowCore[] rows, int stateMask) { MySharesView.this.defaultSelected(rows); } }, false); tv.addLifeCycleListener(this); tv.addMenuFillListener(this); tv.addRefreshListener(this, false); tv.addSelectionListener(this, false); } public TableViewSWT initYourTableView() { return tv; } private void defaultSelected(TableRowCore[] rows) { ShareResource share = tv.getFirstSelectedDataSource(); if (share == null) { return; } // if a row was selected that means it was added, which // required a core, so we assume there's a core here List dms = AzureusCoreFactory.getSingleton().getGlobalManager().getDownloadManagers(); for (int i = 0; i < dms.size(); i++) { DownloadManager dm = (DownloadManager) dms.get(i); try { byte[] share_hash = null; if (share.getType() == ShareResource.ST_DIR) { share_hash = ((ShareResourceDir) share).getItem().getTorrent().getHash(); } else if (share.getType() == ShareResource.ST_FILE) { share_hash = ((ShareResourceFile) share).getItem().getTorrent().getHash(); } if (Arrays.equals(share_hash, dm.getTorrent().getHash())) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_DM_DETAILS, dm); } break; } } catch (Throwable e) { Debug.printStackTrace(e); } } } public void tableViewInitialized() { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { createRows(core); } }); } public void tableViewDestroyed() { try { PluginInitializer.getDefaultInterface().getShareManager().removeListener( this); } catch (ShareException e) { Debug.printStackTrace(e); } catch (Throwable ignore) { } } private void createRows(AzureusCore core) { try{ ShareManager sm = core.getPluginManager().getDefaultPluginInterface().getShareManager(); ShareResource[] shares = sm.getShares(); for (int i=0;i 0); itemRemove.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { removeSelectedShares(); } }); new MenuItem(menu, SWT.SEPARATOR); } public void resourceAdded(ShareResource resource) { tv.addDataSource(resource); } public void resourceModified(ShareResource old_resource,ShareResource new_resource) { tv.removeDataSource( old_resource ); tv.addDataSource( new_resource ); } public void resourceDeleted(ShareResource resource) { tv.removeDataSource(resource); } public void reportProgress(final int percent_complete) { } public void reportCurrentTask(final String task_description) { } public void tableRefresh() { computePossibleActions(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } private void addCategorySubMenu() { MenuItem[] items = menuCategory.getItems(); int i; for (i = 0; i < items.length; i++) { items[i].dispose(); } Category[] categories = CategoryManager.getCategories(); Arrays.sort(categories); if (categories.length > 0) { Category catUncat = CategoryManager.getCategory(Category.TYPE_UNCATEGORIZED); if (catUncat != null) { final MenuItem itemCategory = new MenuItem(menuCategory, SWT.PUSH); Messages.setLanguageText(itemCategory, catUncat.getName()); itemCategory.setData("Category", catUncat); itemCategory.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { MenuItem item = (MenuItem)event.widget; assignSelectedToCategory((Category)item.getData("Category")); } }); new MenuItem(menuCategory, SWT.SEPARATOR); } for (i = 0; i < categories.length; i++) { if (categories[i].getType() == Category.TYPE_USER) { final MenuItem itemCategory = new MenuItem(menuCategory, SWT.PUSH); itemCategory.setText(categories[i].getName()); itemCategory.setData("Category", categories[i]); itemCategory.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { MenuItem item = (MenuItem)event.widget; assignSelectedToCategory((Category)item.getData("Category")); } }); } } new MenuItem(menuCategory, SWT.SEPARATOR); } final MenuItem itemAddCategory = new MenuItem(menuCategory, SWT.PUSH); Messages.setLanguageText(itemAddCategory, "MyTorrentsView.menu.setCategory.add"); itemAddCategory.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { addCategory(); } }); } private void addCategory() { CategoryAdderWindow adderWindow = new CategoryAdderWindow(Display.getDefault()); Category newCategory = adderWindow.getNewCategory(); if (newCategory != null) assignSelectedToCategory(newCategory); } private void assignSelectedToCategory(final Category category) { tv.runForSelectedRows(new TableGroupRowRunner() { public void run(TableRowCore row) { String value; if ( category == null ){ value = null; }else if ( category == CategoryManager.getCategory(Category.TYPE_UNCATEGORIZED)){ value = null; }else{ value = category.getName(); } ((ShareResource)row.getDataSource(true)).setAttribute( category_attribute, value ); } }); } private boolean start,stop,remove; private void computePossibleActions() { start = stop = remove = false; if (!AzureusCoreFactory.isCoreRunning()) { return; } List items = getSelectedItems(); if (items.size() > 0) { PluginInterface pi = PluginInitializer.getDefaultInterface(); org.gudy.azureus2.plugins.download.DownloadManager dm = pi.getDownloadManager(); remove = true; for (int i=0; i < items.size(); i++){ ShareItem item = (ShareItem)items.get(i); try{ Torrent t = item.getTorrent(); Download download = dm.getDownload( t ); if ( download == null ){ continue; } int dl_state = download.getState(); if ( dl_state == Download.ST_ERROR ){ }else if ( dl_state != Download.ST_STOPPED ){ stop = true; }else{ start = true; } }catch( Throwable e ){ Debug.printStackTrace(e); } } } } public boolean isEnabled(String itemKey) { if(itemKey.equals("start")) return start; if(itemKey.equals("stop")) return stop; if(itemKey.equals("remove")) return remove; return super.isEnabled(itemKey); } public void itemActivated(String itemKey) { if(itemKey.equals("remove")){ removeSelectedShares(); return; }else if ( itemKey.equals( "stop" )){ stopSelectedShares(); return; }else if ( itemKey.equals( "start" )){ startSelectedShares(); return; } super.itemActivated(itemKey); } private List getSelectedItems() { Object[] shares = tv.getSelectedDataSources().toArray(); List items = new ArrayList(); if ( shares.length > 0 ){ for (int i=0; i < shares.length; i++){ ShareResource share = (ShareResource)shares[i]; int type = share.getType(); if ( type == ShareResource.ST_DIR ){ ShareResourceDir sr = (ShareResourceDir)share; items.add( sr.getItem()); }else if ( type == ShareResource.ST_FILE ){ ShareResourceFile sr = (ShareResourceFile)share; items.add( sr.getItem()); }else{ ShareResourceDirContents cont = (ShareResourceDirContents)share; List entries = new ArrayList(); getEntries( entries, cont ); for (int j=0;j Download Speed Menu // final MenuItem itemDownSpeed = new MenuItem(menuAdvanced, SWT.CASCADE); Messages.setLanguageText(itemDownSpeed, "MyTorrentsView.menu.setDownSpeed"); //$NON-NLS-1$ Utils.setMenuItemImage(itemDownSpeed, "speed"); final Menu menuDownSpeed = new Menu(shell, SWT.DROP_DOWN); itemDownSpeed.setMenu(menuDownSpeed); final MenuItem itemCurrentDownSpeed = new MenuItem(menuDownSpeed, SWT.PUSH); itemCurrentDownSpeed.setEnabled(false); StringBuffer speedText = new StringBuffer(); String separator = ""; //itemDownSpeed. if (downSpeedDisabled) { speedText.append(MessageText .getString("MyTorrentsView.menu.setSpeed.disabled")); separator = " / "; } if (downSpeedUnlimited) { speedText.append(separator); speedText.append(MessageText .getString("MyTorrentsView.menu.setSpeed.unlimited")); separator = " / "; } if (totalDownSpeed > 0) { speedText.append(separator); speedText.append(DisplayFormatters .formatByteCountToKiBEtcPerSec(totalDownSpeed)); } itemCurrentDownSpeed.setText(speedText.toString()); new MenuItem(menuDownSpeed, SWT.SEPARATOR); final MenuItem itemsDownSpeed[] = new MenuItem[12]; Listener itemsDownSpeedListener = new Listener() { public void handleEvent(Event e) { if (e.widget != null && e.widget instanceof MenuItem) { MenuItem item = (MenuItem) e.widget; int speed = item.getData("maxdl") == null ? 0 : ((Integer) item .getData("maxdl")).intValue(); adapter.setDownSpeed(speed); } } }; itemsDownSpeed[1] = new MenuItem(menuDownSpeed, SWT.PUSH); Messages.setLanguageText(itemsDownSpeed[1], "MyTorrentsView.menu.setSpeed.unlimit"); itemsDownSpeed[1].setData("maxdl", new Integer(0)); itemsDownSpeed[1].addListener(SWT.Selection, itemsDownSpeedListener); if (hasSelection) { //using 200KiB/s as the default limit when no limit set. if (maxDownload == 0){ if ( downSpeedSetMax == 0 ){ maxDownload = 200 * 1024; }else{ maxDownload = 4 * ( downSpeedSetMax/1024 ) * 1024; } } for (int i = 2; i < 12; i++) { itemsDownSpeed[i] = new MenuItem(menuDownSpeed, SWT.PUSH); itemsDownSpeed[i].addListener(SWT.Selection, itemsDownSpeedListener); // dms.length has to be > 0 when hasSelection int limit = (int)(maxDownload / (10 * num_entries) * (12 - i)); StringBuffer speed = new StringBuffer(); speed.append(DisplayFormatters.formatByteCountToKiBEtcPerSec(limit * num_entries)); if (num_entries > 1) { speed.append(" "); speed.append(MessageText .getString("MyTorrentsView.menu.setSpeed.in")); speed.append(" "); speed.append(num_entries); speed.append(" "); speed.append(MessageText .getString("MyTorrentsView.menu.setSpeed.slots")); speed.append(" "); speed .append(DisplayFormatters.formatByteCountToKiBEtcPerSec(limit)); } itemsDownSpeed[i].setText(speed.toString()); itemsDownSpeed[i].setData("maxdl", new Integer(limit)); } } // --- new MenuItem(menuDownSpeed, SWT.SEPARATOR); String menu_key = "MyTorrentsView.menu.manual"; if (num_entries > 1) {menu_key += (isTorrentContext?".per_torrent":".per_peer" );} final MenuItem itemDownSpeedManualSingle = new MenuItem(menuDownSpeed, SWT.PUSH); Messages.setLanguageText(itemDownSpeedManualSingle, menu_key); itemDownSpeedManualSingle.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int speed_value = getManualSpeedValue(shell, true); if (speed_value > 0) {adapter.setDownSpeed(speed_value);} } }); if (num_entries > 1) { final MenuItem itemDownSpeedManualShared = new MenuItem(menuDownSpeed, SWT.PUSH); Messages.setLanguageText(itemDownSpeedManualShared, isTorrentContext?"MyTorrentsView.menu.manual.shared_torrents":"MyTorrentsView.menu.manual.shared_peers"); itemDownSpeedManualShared.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int speed_value = getManualSharedSpeedValue(shell, true, num_entries); if (speed_value > 0) {adapter.setDownSpeed(speed_value);} } }); } // advanced >Upload Speed Menu // final MenuItem itemUpSpeed = new MenuItem(menuAdvanced, SWT.CASCADE); Messages.setLanguageText(itemUpSpeed, "MyTorrentsView.menu.setUpSpeed"); //$NON-NLS-1$ Utils.setMenuItemImage(itemUpSpeed, "speed"); final Menu menuUpSpeed = new Menu(shell, SWT.DROP_DOWN); itemUpSpeed.setMenu(menuUpSpeed); final MenuItem itemCurrentUpSpeed = new MenuItem(menuUpSpeed, SWT.PUSH); itemCurrentUpSpeed.setEnabled(false); separator = ""; speedText = new StringBuffer(); //itemUpSpeed. if (upSpeedDisabled) { speedText.append(MessageText .getString("MyTorrentsView.menu.setSpeed.disabled")); separator = " / "; } if (upSpeedUnlimited) { speedText.append(separator); speedText.append(MessageText .getString("MyTorrentsView.menu.setSpeed.unlimited")); separator = " / "; } if (totalUpSpeed > 0) { speedText.append(separator); speedText.append(DisplayFormatters .formatByteCountToKiBEtcPerSec(totalUpSpeed)); } itemCurrentUpSpeed.setText(speedText.toString()); // --- new MenuItem(menuUpSpeed, SWT.SEPARATOR); final MenuItem itemsUpSpeed[] = new MenuItem[12]; Listener itemsUpSpeedListener = new Listener() { public void handleEvent(Event e) { if (e.widget != null && e.widget instanceof MenuItem) { MenuItem item = (MenuItem) e.widget; int speed = item.getData("maxul") == null ? 0 : ((Integer) item .getData("maxul")).intValue(); adapter.setUpSpeed(speed); } } }; itemsUpSpeed[1] = new MenuItem(menuUpSpeed, SWT.PUSH); Messages.setLanguageText(itemsUpSpeed[1], "MyTorrentsView.menu.setSpeed.unlimit"); itemsUpSpeed[1].setData("maxul", new Integer(0)); itemsUpSpeed[1].addListener(SWT.Selection, itemsUpSpeedListener); if (hasSelection) { //using 75KiB/s as the default limit when no limit set. if (maxUpload == 0){ maxUpload = 75 * 1024; }else{ if ( upSpeedSetMax == 0 ){ maxUpload = 200 * 1024; }else{ maxUpload = 4 * ( upSpeedSetMax/1024 ) * 1024; } } for (int i = 2; i < 12; i++) { itemsUpSpeed[i] = new MenuItem(menuUpSpeed, SWT.PUSH); itemsUpSpeed[i].addListener(SWT.Selection, itemsUpSpeedListener); int limit = (int)( maxUpload / (10 * num_entries) * (12 - i)); StringBuffer speed = new StringBuffer(); speed.append(DisplayFormatters.formatByteCountToKiBEtcPerSec(limit * num_entries)); if (num_entries > 1) { speed.append(" "); speed.append(MessageText .getString("MyTorrentsView.menu.setSpeed.in")); speed.append(" "); speed.append(num_entries); speed.append(" "); speed.append(MessageText .getString("MyTorrentsView.menu.setSpeed.slots")); speed.append(" "); speed .append(DisplayFormatters.formatByteCountToKiBEtcPerSec(limit)); } itemsUpSpeed[i].setText(speed.toString()); itemsUpSpeed[i].setData("maxul", new Integer(limit)); } } new MenuItem(menuUpSpeed, SWT.SEPARATOR); final MenuItem itemUpSpeedManualSingle = new MenuItem(menuUpSpeed, SWT.PUSH); Messages.setLanguageText(itemUpSpeedManualSingle, menu_key); itemUpSpeedManualSingle.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int speed_value = getManualSpeedValue(shell, false); if (speed_value > 0) {adapter.setUpSpeed(speed_value);} } }); if (num_entries > 1) { final MenuItem itemUpSpeedManualShared = new MenuItem(menuUpSpeed, SWT.PUSH); Messages.setLanguageText(itemUpSpeedManualShared, isTorrentContext?"MyTorrentsView.menu.manual.shared_torrents":"MyTorrentsView.menu.manual.shared_peers" ); itemUpSpeedManualShared.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int speed_value = getManualSharedSpeedValue(shell, false, num_entries); if (speed_value > 0) {adapter.setUpSpeed(speed_value);} } }); } } public static int getManualSpeedValue(Shell shell, boolean for_download) { String kbps_str = MessageText.getString("MyTorrentsView.dialog.setNumber.inKbps", new String[]{ DisplayFormatters.getRateUnit(DisplayFormatters.UNIT_KB ) }); String set_num_str = MessageText.getString("MyTorrentsView.dialog.setNumber." + ((for_download) ? "download" : "upload")); SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(); entryWindow.initTexts( "MyTorrentsView.dialog.setSpeed.title", new String[] {set_num_str}, "MyTorrentsView.dialog.setNumber.text", new String[] { kbps_str, set_num_str }); entryWindow.prompt(); if (!entryWindow.hasSubmittedInput()) { return -1; } String sReturn = entryWindow.getSubmittedInput(); if (sReturn == null) return -1; try { int result = (int) (Double.valueOf(sReturn).doubleValue() * 1024); if ( DisplayFormatters.isRateUsingBits()){ result /= 8; } if (result <= 0) {throw new NumberFormatException("non-positive number entered");} return result; } catch (NumberFormatException er) { MessageBox mb = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK); mb.setText(MessageText .getString("MyTorrentsView.dialog.NumberError.title")); mb.setMessage(MessageText .getString("MyTorrentsView.dialog.NumberError.text")); mb.open(); return -1; } } public static int getManualSharedSpeedValue(Shell shell, boolean for_download, int num_entries) { int result = getManualSpeedValue(shell, for_download); if (result == -1) {return -1;} result = result / num_entries; if (result == 0) {result = 1;} return result; } public interface SpeedAdapter { public void setUpSpeed( int val ); public void setDownSpeed( int val ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/columnsetup/0000755000175000017500000000000011310377636023131 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/columnsetup/TableColumnSetupWindow.java0000644000175000017500000011076711273750770030430 0ustar adrianadrian/** * Created on Jan 3, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.views.columnsetup; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.views.table.TableRowSWT; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import com.aelitis.azureus.ui.common.table.*; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; import org.gudy.azureus2.plugins.ui.tables.TableRow; /** * @author TuxPaper * @created Jan 3, 2009 * */ public class TableColumnSetupWindow implements UIUpdatable { private static final String TABLEID_AVAIL = "ColumnSetupAvail"; private static final String TABLEID_CHOSEN = "ColumnSetupChosen"; private static final boolean CAT_BUTTONS = true; private Shell shell; private TableViewColumnSetup tvAvail; private final String forTableID; private final Class forDataSourceType; private Composite cTableAvail; private Composite cCategories; private TableViewColumnSetup tvChosen; private Composite cTableChosen; private TableColumnCore[] columnsChosen; private final TableRow sampleRow; private DragSourceListener dragSourceListener; private final TableStructureModificationListener listener; private TableColumnCore[] columnsOriginalOrder; protected boolean apply = false; private Button[] radProficiency = new Button[3]; private Map mapNewVisibility = new HashMap(); private ArrayList listColumnsNoCat; private ArrayList listCats; private Combo comboFilter; private Group cPickArea; protected boolean doReset; public TableColumnSetupWindow(final Class forDataSourceType, String _tableID, TableRow sampleRow, TableStructureModificationListener _listener) { this.sampleRow = sampleRow; this.listener = _listener; FormData fd; this.forDataSourceType = forDataSourceType; forTableID = _tableID; dragSourceListener = new DragSourceListener() { private TableColumnCore tableColumn; public void dragStart(DragSourceEvent event) { event.doit = true; Table table = (Table) ((DragSource) event.widget).getControl(); TableView tv = (TableView) table.getData("TableView"); // drag start happens a bit after the mouse moves, so the // cursor location isn't accurate //Point cursorLocation = event.display.getCursorLocation(); //cursorLocation = tv.getTableComposite().toControl(cursorLocation); //TableRowCore row = tv.getRow(cursorLocation.x, cursorLocation.y); //System.out.println("" + event.x + ";" + event.y + "/" + cursorLocation); // event.x and y doesn't always return correct values! //TableRowCore row = tv.getRow(event.x, event.y); TableRowCore row = tv.getFocusedRow(); if (row == null) { event.doit = false; return; } tableColumn = (TableColumnCore) row.getDataSource(); if (event.image != null && !Constants.isLinux) { try { GC gc = new GC(event.image); try { Rectangle bounds = event.image.getBounds(); gc.fillRectangle(bounds); String title = MessageText.getString( tableColumn.getTitleLanguageKey(), tableColumn.getName()); String s = title + " Column will be placed at the location you drop it, shifting other columns down"; GCStringPrinter sp = new GCStringPrinter(gc, s, bounds, false, false, SWT.CENTER | SWT.WRAP); sp.calculateMetrics(); if (sp.isCutoff()) { GCStringPrinter.printString(gc, title, bounds, false, false, SWT.CENTER | SWT.WRAP); } else { sp.printString(); } } finally { gc.dispose(); } } catch (Throwable t) { //ignore } } } public void dragSetData(DragSourceEvent event) { Table table = (Table) ((DragSource) event.widget).getControl(); TableView tv = (TableView) table.getData("TableView"); event.data = "" + (tv == tvChosen ? "c" : "a"); } public void dragFinished(DragSourceEvent event) { } }; String tableName = MessageText.getString(_tableID + "View.header", (String) null); if (tableName == null) { tableName = MessageText.getString(_tableID + "View.title.full", (String) null); if (tableName == null) { tableName = _tableID; } } shell = ShellFactory.createShell(Utils.findAnyShell(), SWT.SHELL_TRIM); Utils.setShellIcon(shell); FormLayout formLayout = new FormLayout(); shell.setText(MessageText.getString("ColumnSetup.title", new String[] { tableName })); shell.setLayout(formLayout); shell.setSize(780, 550); shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { close(); } }); Label topInfo = new Label(shell, SWT.WRAP); Messages.setLanguageText(topInfo, "ColumnSetup.explain"); fd = Utils.getFilledFormData(); fd.left.offset = 5; fd.top.offset = 5; fd.bottom = null; topInfo.setLayoutData(fd); Button btnOk = new Button(shell, SWT.PUSH); Messages.setLanguageText(btnOk, "Button.ok"); btnOk.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { apply = true; shell.dispose(); } }); cPickArea = new Group(shell, SWT.NONE); cPickArea.setLayout(new FormLayout()); final ExpandBar expandFilters = new ExpandBar(cPickArea, SWT.NONE); expandFilters.setSpacing(1); final Composite cFilterArea = new Composite(expandFilters, SWT.NONE); cFilterArea.setLayout(new FormLayout()); final TableColumnManager tcm = TableColumnManager.getInstance(); Group cResultArea = new Group(shell, SWT.NONE); Messages.setLanguageText(cResultArea, "ColumnSetup.chosencolumns"); cResultArea.setLayout(new FormLayout()); Composite cResultButtonArea = new Composite(cResultArea, SWT.NONE); cResultButtonArea.setLayout(new FormLayout()); tvAvail = createTVAvail(); cTableAvail = new Composite(cPickArea, SWT.NO_FOCUS); GridLayout gridLayout = new GridLayout(); gridLayout.marginWidth = gridLayout.marginHeight = 0; cTableAvail.setLayout(gridLayout); tvAvail.initialize(cTableAvail); TableColumnCore[] datasources = tcm.getAllTableColumnCoreAsArray( forDataSourceType, forTableID); listColumnsNoCat = new ArrayList( Arrays.asList(datasources)); listCats = new ArrayList(); for (int i = 0; i < datasources.length; i++) { TableColumnCore column = datasources[i]; TableColumnInfo info = tcm.getColumnInfo(forDataSourceType, forTableID, column.getName()); if (info != null) { String[] categories = info.getCategories(); if (categories != null && categories.length > 0) { for (int j = 0; j < categories.length; j++) { String cat = categories[j]; if (!listCats.contains(cat)) { listCats.add(cat); } } listColumnsNoCat.remove(column); } } } Listener radListener = new Listener() { public void handleEvent(Event event) { fillAvail(); } }; Composite cProficiency = new Composite(cFilterArea, SWT.NONE); cProficiency.setBackgroundMode(SWT.INHERIT_FORCE); cProficiency.setLayout(new FormLayout()); Label lblProficiency = new Label(cProficiency, SWT.NONE); Messages.setLanguageText(lblProficiency, "ColumnSetup.proficiency"); radProficiency[0] = new Button(cProficiency, SWT.RADIO); Messages.setLanguageText(radProficiency[0], "ConfigView.section.mode.beginner"); fd = new FormData(); fd.left = new FormAttachment(lblProficiency, 5); radProficiency[0].setLayoutData(fd); radProficiency[0].addListener(SWT.Selection, radListener); radProficiency[1] = new Button(cProficiency, SWT.RADIO); Messages.setLanguageText(radProficiency[1], "ConfigView.section.mode.intermediate"); fd = new FormData(); fd.left = new FormAttachment(radProficiency[0], 5); radProficiency[1].setLayoutData(fd); radProficiency[1].addListener(SWT.Selection, radListener); radProficiency[2] = new Button(cProficiency, SWT.RADIO); Messages.setLanguageText(radProficiency[2], "ConfigView.section.mode.advanced"); fd = new FormData(); fd.left = new FormAttachment(radProficiency[1], 5); radProficiency[2].setLayoutData(fd); radProficiency[2].addListener(SWT.Selection, radListener); int userMode = COConfigurationManager.getIntParameter("User Mode"); if (userMode < 0) { userMode = 0; } else if (userMode >= radProficiency.length) { userMode = radProficiency.length - 1; } radProficiency[userMode].setSelection(true); // >>>>>>>> Buttons Listener buttonListener = new Listener() { public void handleEvent(Event event) { Control[] children = cCategories.getChildren(); for (int i = 0; i < children.length; i++) { Control child = children[i]; if (child != event.widget && (child instanceof Button)) { Button btn = (Button) child; btn.setSelection(false); } } fillAvail(); } }; Label lblCat = new Label(cFilterArea, SWT.NONE); Messages.setLanguageText(lblCat, "ColumnSetup.categories"); if (CAT_BUTTONS) { cCategories = new Composite(cFilterArea, SWT.NONE); cCategories.setLayout(new RowLayout()); Button button = new Button(cCategories, SWT.TOGGLE); Messages.setLanguageText(button, "Categories.all"); button.addListener(SWT.Selection, buttonListener); button.setSelection(true); for (String cat : listCats) { button = new Button(cCategories, SWT.TOGGLE); button.setData("cat", cat); if (MessageText.keyExists("ColumnCategory." + cat)) { button.setText(MessageText.getString("ColumnCategory." + cat)); } else { button.setText(cat); } button.addListener(SWT.Selection, buttonListener); } if (listColumnsNoCat.size() > 0) { button = new Button(cCategories, SWT.TOGGLE); if (MessageText.keyExists("ColumnCategory.uncat")) { button.setText(MessageText.getString("ColumnCategory.uncat")); } else { button.setText("?"); } button.setText("?"); button.setData("cat", "uncat"); button.addListener(SWT.Selection, buttonListener); } } else { comboFilter = new Combo(cFilterArea, SWT.DROP_DOWN | SWT.READ_ONLY); comboFilter.addListener(SWT.Selection, radListener); listCats.add(0, "all"); for (String cat : listCats) { comboFilter.add(cat); } comboFilter.select(0); } final ExpandItem expandItemFilters = new ExpandItem(expandFilters, SWT.NONE); expandItemFilters.setText(MessageText.getString("ColumnSetup.filters")); expandItemFilters.setControl(cFilterArea); expandFilters.addListener(SWT.Resize, new Listener() { public void handleEvent(Event event) { expandItemFilters.setHeight(cFilterArea.computeSize( expandFilters.getSize().x, SWT.DEFAULT).y + 3); } }); expandFilters.addListener(SWT.Expand, new Listener() { public void handleEvent(Event event) { Utils.execSWTThreadLater(Constants.isLinux ? 250 : 0, new AERunnable() { public void runSupport() { shell.layout(true, true); } }); } }); expandFilters.addListener(SWT.Collapse, new Listener() { public void handleEvent(Event event) { Utils.execSWTThreadLater(Constants.isLinux ? 250 : 0, new AERunnable() { public void runSupport() { shell.layout(true, true); } }); } }); // <<<<<<< Buttons // >>>>>>> Chosen ImageLoader imageLoader = ImageLoader.getInstance(); Button btnUp = new Button(cResultButtonArea, SWT.PUSH); imageLoader.setButtonImage(btnUp, "up"); btnUp.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { moveChosenUp(); } public void widgetDefaultSelected(SelectionEvent e) { } }); Button btnDown = new Button(cResultButtonArea, SWT.PUSH); imageLoader.setButtonImage(btnDown, "down"); btnDown.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { moveChosenDown(); } public void widgetDefaultSelected(SelectionEvent e) { } }); Button btnDel = new Button(cResultButtonArea, SWT.PUSH); imageLoader.setButtonImage(btnDel, "delete"); btnDel.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { removeSelectedChosen(); } public void widgetDefaultSelected(SelectionEvent e) { } }); tvChosen = createTVChosen(); cTableChosen = new Composite(cResultArea, SWT.NONE); gridLayout = new GridLayout(); gridLayout.marginWidth = gridLayout.marginHeight = 0; cTableChosen.setLayout(gridLayout); tvChosen.initialize(cTableChosen); columnsChosen = tcm.getAllTableColumnCoreAsArray(forDataSourceType, forTableID); Arrays.sort(columnsChosen, TableColumnManager.getTableColumnOrderComparator()); columnsOriginalOrder = new TableColumnCore[columnsChosen.length]; System.arraycopy(columnsChosen, 0, columnsOriginalOrder, 0, columnsChosen.length); int pos = 0; for (int i = 0; i < columnsChosen.length; i++) { boolean visible = columnsChosen[i].isVisible(); mapNewVisibility.put(columnsChosen[i], new Boolean(visible)); if (visible) { columnsChosen[i].setPositionNoShift(pos++); tvChosen.addDataSource(columnsChosen[i]); } } tvChosen.processDataSourceQueue(); Button btnReset = null; String[] defaultColumnNames = tcm.getDefaultColumnNames(forTableID); if (defaultColumnNames != null) { btnReset = new Button(cResultButtonArea, SWT.PUSH); Messages.setLanguageText(btnReset, "Button.reset"); btnReset.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { String[] defaultColumnNames = tcm.getDefaultColumnNames(forTableID); if (defaultColumnNames != null) { List defaultColumns = new ArrayList(); for (String name : defaultColumnNames) { TableColumnCore column = tcm.getTableColumnCore(forTableID, name); if (column != null) { defaultColumns.add(column); } } if (defaultColumns.size() > 0) { for (TableColumnCore tc : mapNewVisibility.keySet()) { mapNewVisibility.put(tc, Boolean.FALSE); } tvChosen.removeAllTableRows(); columnsChosen = defaultColumns.toArray(new TableColumnCore[0]); for (int i = 0; i < columnsChosen.length; i++) { mapNewVisibility.put(columnsChosen[i], Boolean.TRUE); columnsChosen[i].setPositionNoShift(i); tvChosen.addDataSource(columnsChosen[i]); } doReset = true; } } } }); } Button btnCancel = new Button(shell, SWT.PUSH); Messages.setLanguageText(btnCancel, "Button.cancel"); btnCancel.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { shell.dispose(); } }); Button btnApply = new Button(cResultButtonArea, SWT.PUSH); Messages.setLanguageText(btnApply, "Button.apply"); btnApply.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { apply(); } }); fd = new FormData(); fd.left = new FormAttachment(0, 5); fd.right = new FormAttachment(100, -5); //fd.bottom = new FormAttachment(100, -5); //lblChosenHeader.setLayoutData(fd); fd = new FormData(); fd.top = new FormAttachment(topInfo, 5); fd.right = new FormAttachment(100, -3); fd.bottom = new FormAttachment(btnOk, -5); fd.width = 200; cResultArea.setLayoutData(fd); fd = new FormData(); fd.bottom = new FormAttachment(100, 0); fd.left = new FormAttachment(cTableChosen, 0, SWT.CENTER); //fd.right = new FormAttachment(100, 0); cResultButtonArea.setLayoutData(fd); fd = new FormData(); fd.right = new FormAttachment(btnDown, -5); fd.bottom = new FormAttachment(btnApply, -3); btnUp.setLayoutData(fd); fd = new FormData(); fd.right = new FormAttachment(btnDel, -5); fd.top = new FormAttachment(btnUp, 0, SWT.TOP); fd.bottom = new FormAttachment(btnUp, 0, SWT.BOTTOM); btnDown.setLayoutData(fd); fd = new FormData(); fd.right = new FormAttachment(100, -5); fd.top = new FormAttachment(btnUp, 0, SWT.TOP); fd.bottom = new FormAttachment(btnUp, 0, SWT.BOTTOM); btnDel.setLayoutData(fd); fd = new FormData(); fd.top = new FormAttachment(0, 3); fd.left = new FormAttachment(0, 0); fd.right = new FormAttachment(100, 0); //fd.bottom = new FormAttachment(100, 0); fd.bottom = new FormAttachment(cResultButtonArea, -3, SWT.TOP); cTableChosen.setLayoutData(fd); if (btnReset != null) { fd = new FormData(); fd.right = new FormAttachment(btnApply, -3); fd.bottom = new FormAttachment(btnApply, 0, SWT.BOTTOM); btnReset.setLayoutData(fd); } fd = new FormData(); fd.right = new FormAttachment(100, -5); fd.bottom = new FormAttachment(100, -3); //fd.width = 64; btnApply.setLayoutData(fd); fd = new FormData(); fd.right = new FormAttachment(100, -8); fd.bottom = new FormAttachment(100, -3); //fd.width = 65; btnCancel.setLayoutData(fd); fd = new FormData(); fd.right = new FormAttachment(btnCancel, -3); fd.bottom = new FormAttachment(btnCancel, 0, SWT.BOTTOM); //fd.width = 64; btnOk.setLayoutData(fd); // <<<<<<<<< Chosen fd = new FormData(); fd.top = new FormAttachment(topInfo, 5); fd.left = new FormAttachment(0, 3); fd.right = new FormAttachment(cResultArea, -3); fd.bottom = new FormAttachment(100, -3); cPickArea.setLayoutData(fd); fd = new FormData(); fd.bottom = new FormAttachment(100, 0); fd.left = new FormAttachment(0, 0); fd.right = new FormAttachment(100, 0); expandFilters.setLayoutData(fd); if (CAT_BUTTONS) { fd = new FormData(); fd.bottom = new FormAttachment(cCategories, 0, SWT.CENTER); fd.left = new FormAttachment(0, 5); lblCat.setLayoutData(fd); fd = new FormData(); //fd.top = new FormAttachment(0, 0); fd.bottom = new FormAttachment(radProficiency[0], 0, SWT.CENTER); fd.left = new FormAttachment(0, 0); lblProficiency.setLayoutData(fd); fd = new FormData(); fd.top = new FormAttachment(cProficiency, 5); fd.left = new FormAttachment(lblCat, 5); fd.right = new FormAttachment(100, 0); cCategories.setLayoutData(fd); } else { fd = new FormData(); fd.top = new FormAttachment(comboFilter, -5); fd.right = new FormAttachment(comboFilter, 0, SWT.CENTER); lblCat.setLayoutData(fd); fd = new FormData(); fd.top = new FormAttachment(cProficiency, 0, SWT.CENTER); fd.right = new FormAttachment(100, 0); comboFilter.setLayoutData(fd); } fd = new FormData(); fd.top = new FormAttachment(0, 5); fd.left = new FormAttachment(0, 5); cProficiency.setLayoutData(fd); fd = new FormData(); fd.top = new FormAttachment(0, 3); fd.left = new FormAttachment(0, 0); fd.right = new FormAttachment(100, 0); fd.bottom = new FormAttachment(expandFilters, -3); cTableAvail.setLayoutData(fd); //cTableAvail.setFocus(); //tvAvail.getTableComposite().setFocus(); shell.setTabList(new Control[] { cPickArea, cResultArea, btnOk, btnCancel, }); cPickArea.setTabList(new Control[] { cTableAvail }); fillAvail(); UIUpdaterSWT.getInstance().addUpdater(this); } /** * * * @since 4.0.0.5 */ protected void fillAvail() { String selectedCat = null; if (CAT_BUTTONS) { Control[] children = cCategories.getChildren(); for (int i = 0; i < children.length; i++) { Control child = children[i]; if (child instanceof Button) { Button btn = (Button) child; if (btn.getSelection()) { selectedCat = (String) btn.getData("cat"); break; } } } } else { selectedCat = comboFilter.getItem(comboFilter.getSelectionIndex()); } if (selectedCat != null && selectedCat.equals("all")) { selectedCat = null; } byte selectedProf = 0; for (byte i = 0; i < radProficiency.length; i++) { Button btn = radProficiency[i]; if (btn.getSelection()) { selectedProf = i; break; } } String s; //= "Available " + radProficiency[selectedProf].getText() + " Columns"; if (selectedCat != null) { s = MessageText.getString("ColumnSetup.availcolumns.filteredby", new String[] { radProficiency[selectedProf].getText(), selectedCat }); } else { s = MessageText.getString("ColumnSetup.availcolumns", new String[] { radProficiency[selectedProf].getText(), }); } cPickArea.setText(s); tvAvail.removeAllTableRows(); final TableColumnManager tcm = TableColumnManager.getInstance(); TableColumnCore[] datasources = tcm.getAllTableColumnCoreAsArray( forDataSourceType, forTableID); if (selectedCat == "uncat") { datasources = (TableColumnCore[]) listColumnsNoCat.toArray( new TableColumnCore[listColumnsNoCat.size()]); } for (int i = 0; i < datasources.length; i++) { TableColumnCore column = datasources[i]; TableColumnInfo info = tcm.getColumnInfo(forDataSourceType, forTableID, column.getName()); String[] cats = info == null ? null : info.getCategories(); if (cats == null) { if (selectedCat == null || selectedCat.equals("uncat")) { tvAvail.addDataSource(column); } } else { for (int j = 0; j < cats.length; j++) { String cat = cats[j]; if ((selectedCat == null || selectedCat.equalsIgnoreCase(cat)) && info.getProficiency() <= selectedProf) { tvAvail.addDataSource(column); break; } } } } tvAvail.processDataSourceQueue(); } /** * * * @since 4.0.0.5 */ protected void removeSelectedChosen() { Object[] datasources = tvChosen.getSelectedDataSources().toArray(); for (int i = 0; i < datasources.length; i++) { TableColumnCore column = (TableColumnCore) datasources[i]; mapNewVisibility.put(column, Boolean.FALSE); } tvChosen.removeDataSources(datasources); tvChosen.processDataSourceQueue(); for (int i = 0; i < datasources.length; i++) { TableRowSWT row = (TableRowSWT) tvAvail.getRow(datasources[i]); if (row != null) { row.redraw(); } } } /** * * * @since 4.0.0.5 */ protected void moveChosenDown() { TableRowCore[] selectedRows = tvChosen.getSelectedRows(); TableRowCore[] rows = tvChosen.getRows(); for (int i = selectedRows.length - 1; i >= 0; i--) { TableRowCore row = selectedRows[i]; TableColumnCore column = (TableColumnCore) row.getDataSource(); if (column != null) { int oldColumnPos = column.getPosition(); int oldRowPos = row.getIndex(); if (oldRowPos < rows.length - 1) { TableRowCore displacedRow = rows[oldRowPos + 1]; ((TableColumnCore) displacedRow.getDataSource()).setPositionNoShift(oldColumnPos); rows[oldRowPos + 1] = rows[oldRowPos]; rows[oldRowPos] = displacedRow; column.setPositionNoShift(oldColumnPos + 1); } } } tvChosen.tableInvalidate(); tvChosen.refreshTable(true); } /** * * * @since 4.0.0.5 */ protected void moveChosenUp() { TableRowCore[] selectedRows = tvChosen.getSelectedRows(); TableRowCore[] rows = tvChosen.getRows(); for (int i = 0; i < selectedRows.length; i++) { TableRowCore row = selectedRows[i]; TableColumnCore column = (TableColumnCore) row.getDataSource(); if (column != null) { int oldColumnPos = column.getPosition(); int oldRowPos = row.getIndex(); if (oldRowPos > 0) { TableRowCore displacedRow = rows[oldRowPos - 1]; ((TableColumnCore) displacedRow.getDataSource()).setPositionNoShift(oldColumnPos); rows[oldRowPos - 1] = rows[oldRowPos]; rows[oldRowPos] = displacedRow; column.setPositionNoShift(oldColumnPos - 1); } } } tvChosen.tableInvalidate(); tvChosen.refreshTable(true); } /** * * * @since 4.0.0.5 */ protected void apply() { for (TableColumnCore tc : mapNewVisibility.keySet()) { boolean visible = mapNewVisibility.get(tc).booleanValue(); tc.setVisible(visible); if (doReset) { tc.reset(); } } TableColumnManager.getInstance().saveTableColumns(forDataSourceType, forTableID); listener.tableStructureChanged(true, forDataSourceType); } /** * @return * * @since 4.0.0.5 */ private TableViewColumnSetup createTVChosen() { final TableColumnManager tcm = TableColumnManager.getInstance(); TableColumnCore[] columnTVChosen = tcm.getAllTableColumnCoreAsArray( TableColumn.class, TABLEID_CHOSEN); for (int i = 0; i < columnTVChosen.length; i++) { TableColumnCore column = columnTVChosen[i]; if (column.getName().equals(ColumnTC_ChosenColumn.COLUMN_ID)) { column.setVisible(true); column.setWidth(175); column.setSortAscending(true); } else { column.setVisible(false); } } final TableViewColumnSetup tvChosen = new TableViewColumnSetup( this, TableColumn.class, TABLEID_CHOSEN, columnTVChosen, ColumnTC_ChosenColumn.COLUMN_ID, true); tvChosen.setMenuEnabled(false); tvChosen.setSampleRow(sampleRow); tvChosen.setHeaderVisible(false); //tvChosen.setRowDefaultHeight(16); tvChosen.addLifeCycleListener(new TableLifeCycleListener() { private DragSource dragSource; private DropTarget dropTarget; public void tableViewInitialized() { dragSource = tvChosen.createDragSource(DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK); dragSource.setTransfer(new Transfer[] { TextTransfer.getInstance() }); dragSource.addDragListener(dragSourceListener); dropTarget = tvChosen.createDropTarget(DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_TARGET_MOVE); dropTarget.setTransfer(new Transfer[] { TextTransfer.getInstance() }); dropTarget.addDropListener(new DropTargetListener() { public void dropAccept(DropTargetEvent event) { // TODO Auto-generated method stub } public void drop(DropTargetEvent event) { String id = (String) event.data; TableRowCore destRow = tvChosen.getRow(event); TableView tv = id.equals("c") ? tvChosen : tvAvail; Object[] dataSources = tv.getSelectedDataSources().toArray(); for (int i = 0; i < dataSources.length; i++) { TableColumnCore column = (TableColumnCore) dataSources[i]; if (column != null) { chooseColumn(column, destRow, true); TableRowCore row = tvAvail.getRow(column); if (row != null) { row.redraw(); } } } } public void dragOver(DropTargetEvent event) { // TODO Auto-generated method stub } public void dragOperationChanged(DropTargetEvent event) { // TODO Auto-generated method stub } public void dragLeave(DropTargetEvent event) { // TODO Auto-generated method stub } public void dragEnter(DropTargetEvent event) { // TODO Auto-generated method stub } }); } public void tableViewDestroyed() { if (dragSource != null && !dragSource.isDisposed()) { dragSource.dispose(); } if (dropTarget != null && !dropTarget.isDisposed()) { dropTarget.dispose(); } } }); tvChosen.addKeyListener(new KeyListener() { public void keyReleased(KeyEvent e) { } public void keyPressed(KeyEvent e) { if (e.stateMask == 0 && (e.keyCode == SWT.ARROW_LEFT || e.keyCode == SWT.DEL)) { removeSelectedChosen(); e.doit = false; } if (e.stateMask == SWT.CONTROL) { if (e.keyCode == SWT.ARROW_UP) { moveChosenUp(); e.doit = false; } else if (e.keyCode == SWT.ARROW_DOWN) { moveChosenDown(); e.doit = false; } } } }); return tvChosen; } /** * @return * * @since 4.0.0.5 */ private TableViewColumnSetup createTVAvail() { final TableColumnManager tcm = TableColumnManager.getInstance(); Map mapColumns = tcm.getTableColumnsAsMap(TableColumn.class, TABLEID_AVAIL); TableColumnCore[] columns; int[] widths = { 405, 120 }; if (sampleRow == null) { columns = new TableColumnCore[] { (TableColumnCore) mapColumns.get(ColumnTC_NameInfo.COLUMN_ID), }; widths = new int[] { 525 }; } else { columns = new TableColumnCore[] { (TableColumnCore) mapColumns.get(ColumnTC_NameInfo.COLUMN_ID), (TableColumnCore) mapColumns.get(ColumnTC_Sample.COLUMN_ID), }; } for (int i = 0; i < columns.length; i++) { TableColumnCore column = columns[i]; if (column != null) { column.setVisible(true); column.setPositionNoShift(i); column.setWidth(widths[i]); } } final TableViewColumnSetup tvAvail = new TableViewColumnSetup(this, TableColumn.class, TABLEID_AVAIL, columns, ColumnTC_ChosenColumn.COLUMN_ID, false); tvAvail.setMenuEnabled(false); tvAvail.setSampleRow(sampleRow); tvAvail.setRowDefaultHeight(65); tvAvail.addLifeCycleListener(new TableLifeCycleListener() { private DragSource dragSource; private DropTarget dropTarget; public void tableViewInitialized() { dragSource = tvAvail.createDragSource(DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK); dragSource.setTransfer(new Transfer[] { TextTransfer.getInstance() }); dragSource.addDragListener(dragSourceListener); dropTarget = tvAvail.createDropTarget(DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_TARGET_MOVE); dropTarget.setTransfer(new Transfer[] { TextTransfer.getInstance() }); dropTarget.addDropListener(new DropTargetAdapter() { public void drop(DropTargetEvent event) { String id = (String) event.data; if (!id.equals("c")) { return; } removeSelectedChosen(); } }); } public void tableViewDestroyed() { if (dragSource != null && !dragSource.isDisposed()) { dragSource.dispose(); } if (dropTarget != null && !dropTarget.isDisposed()) { dropTarget.dispose(); } } }); tvAvail.addSelectionListener(new TableSelectionAdapter() { public void defaultSelected(TableRowCore[] rows, int stateMask) { for (int i = 0; i < rows.length; i++) { TableRowCore row = rows[i]; TableColumnCore column = (TableColumnCore) row.getDataSource(); chooseColumn(column, null, false); } } }, false); tvAvail.addKeyListener(new KeyListener() { public void keyReleased(KeyEvent e) { } public void keyPressed(KeyEvent e) { if (e.stateMask == 0) { if (e.keyCode == SWT.ARROW_RIGHT) { TableRowCore[] selectedRows = tvAvail.getSelectedRows(); for (int i = 0; i < selectedRows.length; i++) { TableRowCore row = selectedRows[i]; TableColumnCore column = (TableColumnCore) row.getDataSource(); chooseColumn(column, null, false); tvChosen.processDataSourceQueue(); row.redraw(); } e.doit = false; } else if (e.keyCode == SWT.ARROW_LEFT) { TableRowCore[] selectedRows = tvAvail.getSelectedRows(); for (int i = 0; i < selectedRows.length; i++) { TableRowCore row = selectedRows[i]; TableColumnCore column = (TableColumnCore) row.getDataSource(); mapNewVisibility.put(column, Boolean.FALSE); tvChosen.removeDataSource(column); tvChosen.processDataSourceQueue(); row.redraw(); } e.doit = false; } } } }); return tvAvail; } public void open() { shell.open(); } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { // TODO Auto-generated method stub return null; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI() public void updateUI() { if (shell.isDisposed()) { UIUpdaterSWT.getInstance().removeUpdater(this); return; } if (tvAvail != null && !tvAvail.isDisposed()) { tvAvail.refreshTable(false); } if (tvChosen != null && !tvChosen.isDisposed()) { tvChosen.refreshTable(false); } } public class TableViewColumnSetup extends TableViewSWTImpl { private TableRow sampleRow = null; private final TableColumnSetupWindow setupWindow; public TableViewColumnSetup(TableColumnSetupWindow setupWindow, Class forPluginDataSourceType, String tableID, TableColumnCore[] items, String defaultSortOn, boolean multi) { super(forPluginDataSourceType, tableID, tableID, items, defaultSortOn, SWT.FULL_SELECTION | SWT.VIRTUAL | (multi ? SWT.MULTI : SWT.SINGLE)); this.setupWindow = setupWindow; } public TableRow getSampleRow() { return sampleRow; } public void setSampleRow(TableRow sampleRow) { this.sampleRow = sampleRow; } public void chooseColumn(TableColumnCore column) { setupWindow.chooseColumn(column, null, false); TableRowCore row = tvAvail.getRow(column); if (row != null) { row.redraw(); } } public boolean isColumnAdded(TableColumnCore column) { TableRowCore row = tvChosen.getRow(column); return row != null; } } /** * @param column * * @since 4.0.0.5 */ public void chooseColumn(final TableColumnCore column, TableRowCore placeAboveRow, boolean ignoreExisting) { TableRowCore row = tvChosen.getRow(column); if (row == null || ignoreExisting) { int newPosition = 0; row = placeAboveRow == null && !ignoreExisting ? tvChosen.getFocusedRow() : placeAboveRow; if (row == null) { if (columnsChosen.length > 0) { newPosition = columnsChosen.length; } } else { newPosition = ((TableColumn) row.getDataSource()).getPosition(); } int oldPosition = column.getPosition(); final boolean shiftDir = oldPosition > newPosition || !mapNewVisibility.get(column).booleanValue(); column.setPositionNoShift(newPosition); mapNewVisibility.put(column, Boolean.TRUE); Arrays.sort(columnsChosen, new Comparator() { public int compare(Object arg0, Object arg1) { if ((arg1 instanceof TableColumn) && (arg0 instanceof TableColumn)) { int iPositionA = ((TableColumn) arg0).getPosition(); if (iPositionA < 0) iPositionA = 0xFFFF + iPositionA; int iPositionB = ((TableColumn) arg1).getPosition(); if (iPositionB < 0) iPositionB = 0xFFFF + iPositionB; int i = iPositionA - iPositionB; if (i == 0) { if (column == arg0) { return shiftDir ? -1 : 1; } else { return shiftDir ? 1 : -1; } } return i; } return 0; } }); int pos = 0; for (int i = 0; i < columnsChosen.length; i++) { if (mapNewVisibility.get(columnsChosen[i]).booleanValue()) { columnsChosen[i].setPositionNoShift(pos++); } } TableRowCore existingRow = tvChosen.getRow(column); if (existingRow == null) { tvChosen.addDataSource(column); tvChosen.processDataSourceQueue(); tvChosen.addCountChangeListener(new TableCountChangeListener() { public void rowRemoved(TableRowCore row) { } public void rowAdded(final TableRowCore row) { Utils.execSWTThreadLater(500, new AERunnable() { public void runSupport() { tvChosen.setSelectedRows(new TableRowCore[] { row }); tvChosen.showRow(row); } }); tvChosen.removeCountChangeListener(this); } }); } tvChosen.tableInvalidate(); tvChosen.refreshTable(true); Arrays.sort(columnsChosen, TableColumnManager.getTableColumnOrderComparator()); } else { row.setSelected(true); } } private void close() { if (apply) { apply(); } else { for (int i = 0; i < columnsOriginalOrder.length; i++) { TableColumnCore column = columnsOriginalOrder[i]; if (column != null) { column.setPositionNoShift(i); } } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_ChosenColumn.java0000644000175000017500000000432611135267676030151 0ustar adrianadrian/** * Created on Jan 3, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.views.columnsetup; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.ui.common.table.TableCellCore; import com.aelitis.azureus.ui.common.table.TableColumnCore; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; /** * @author TuxPaper * @created Jan 3, 2009 * */ public class ColumnTC_ChosenColumn extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "TableColumnChosenColumn"; /** * @param name * @param tableID */ public ColumnTC_ChosenColumn(String tableID) { super(COLUMN_ID, tableID); initialize(ALIGN_LEAD | ALIGN_TOP, POSITION_INVISIBLE, 175, INTERVAL_INVALID_ONLY); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { TableColumnCore column = (TableColumnCore) cell.getDataSource(); String key = column.getTitleLanguageKey(); if (!cell.setSortValue(column.getPosition()) && cell.isValid()) { return; } String s = ""; try { s = (((TableCellCore) cell).getTableRowCore().getIndex() + 1) + ". "; } catch (Throwable e) { } s += MessageText.getString(key, column.getName()); //s = column.getPosition() + "] " + s; cell.setText(s); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_NameInfo.java0000644000175000017500000001711711137504002027225 0ustar adrianadrian/** * Created on Jan 3, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.views.columnsetup; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.views.columnsetup.TableColumnSetupWindow.TableViewColumnSetup; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import com.aelitis.azureus.ui.common.table.TableCellCore; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.swt.utils.ColorCache; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Jan 3, 2009 * */ public class ColumnTC_NameInfo extends CoreTableColumn implements TableCellRefreshListener, TableCellSWTPaintListener, TableCellMouseMoveListener, TableCellToolTipListener { public static final String COLUMN_ID = "TableColumnNameInfo"; public static Font fontHeader = null; private static String[] profText = { "beginner", "intermediate", "advanced" }; /** * @param name * @param tableID */ public ColumnTC_NameInfo(String tableID) { super(COLUMN_ID, tableID); initialize(ALIGN_LEAD | ALIGN_TOP, POSITION_INVISIBLE, 415, INTERVAL_INVALID_ONLY); setType(TYPE_GRAPHIC); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { TableColumnCore column = (TableColumnCore) cell.getDataSource(); String key = column.getTitleLanguageKey(); cell.setSortValue(MessageText.getString(key, column.getName())); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT) public void cellPaint(GC gc, TableCellSWT cell) { TableColumnCore column = (TableColumnCore) cell.getDataSource(); String key = column.getTitleLanguageKey(); Rectangle bounds = cell.getBounds(); if (bounds == null || bounds.isEmpty()) { return; } Font fontDefault = gc.getFont(); if (fontHeader == null) { FontData[] fontData = gc.getFont().getFontData(); fontData[0].setStyle(SWT.BOLD); fontData[0].setHeight(fontData[0].getHeight() + 1); fontHeader = new Font(gc.getDevice(), fontData); } gc.setFont(fontHeader); bounds.y += 3; bounds.x += 7; bounds.width -= 14; String name = MessageText.getString(key, column.getName()); GCStringPrinter sp = new GCStringPrinter(gc, name, bounds, GCStringPrinter.FLAG_SKIPCLIP, SWT.TOP); sp.printString(); Point titleSize = sp.getCalculatedSize(); gc.setFont(fontDefault); String info = MessageText.getString(key + ".info", ""); Rectangle infoBounds = new Rectangle(bounds.x + 10, bounds.y + titleSize.y + 5, bounds.width - 15, bounds.height - 20); GCStringPrinter.printString(gc, info, infoBounds, true, false); TableColumnInfo columnInfo = (TableColumnInfo) cell.getTableRowCore().getData( "columninfo"); if (columnInfo == null) { final TableColumnManager tcm = TableColumnManager.getInstance(); columnInfo = tcm.getColumnInfo(column.getForDataSourceType(), column.getTableID(), column.getName()); cell.getTableRowCore().setData("columninfo", columnInfo); } Rectangle profBounds = new Rectangle(bounds.width - 100, bounds.y - 2, 100, 20); byte proficiency = columnInfo.getProficiency(); if (proficiency > 0 && proficiency < profText.length) { Color oldColor = gc.getForeground(); gc.setForeground(Colors.grey); GCStringPrinter.printString(gc, MessageText.getString("ConfigView.section.mode." + profText[proficiency]), profBounds, true, false, SWT.RIGHT | SWT.TOP); gc.setForeground(oldColor); } Rectangle hitArea; TableViewColumnSetup tv = (TableViewColumnSetup) ((TableCellCore) cell).getTableRowCore().getView(); if (tv.isColumnAdded(column)) { hitArea = Utils.EMPTY_RECT; } else { int x = bounds.x + titleSize.x + 15; int y = bounds.y - 1; int h = 15; String textAdd = MessageText.getString("Button.add"); GCStringPrinter sp2 = new GCStringPrinter(gc, textAdd, new Rectangle(x, y, 500, h), true, false, SWT.CENTER); sp2.calculateMetrics(); int w = sp2.getCalculatedSize().x + 12; gc.setAdvanced(true); gc.setAntialias(SWT.ON); gc.setBackground(ColorCache.getColor(gc.getDevice(), 255, 255, 255)); gc.fillRoundRectangle(x, y, w, h, 15, h); gc.setBackground(ColorCache.getColor(gc.getDevice(), 215, 215, 215)); gc.fillRoundRectangle(x + 2, y + 2, w, h, 15, h); gc.setForeground(ColorCache.getColor(gc.getDevice(), 145, 145, 145)); gc.drawRoundRectangle(x, y, w, h, 15, h); gc.setForeground(ColorCache.getColor(gc.getDevice(), 50, 50, 50)); hitArea = new Rectangle(x, y, w + 2, h); sp2.printString(gc, hitArea, SWT.CENTER); bounds = cell.getBounds(); hitArea.x -= bounds.x; hitArea.y -= bounds.y; } cell.getTableRowCore().setData("AddHitArea", hitArea); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellMouseListener#cellMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent) public void cellMouseTrigger(TableCellMouseEvent event) { if (event.button == 1 && event.eventType == TableRowMouseEvent.EVENT_MOUSEUP && (event.cell instanceof TableCellCore)) { Object data = ((TableCellCore) event.cell).getTableRowCore().getData( "AddHitArea"); if (data instanceof Rectangle) { Rectangle hitArea = (Rectangle) data; if (hitArea.contains(event.x, event.y)) { TableViewColumnSetup tv = (TableViewColumnSetup) ((TableCellCore) event.cell).getTableRowCore().getView(); Object dataSource = event.cell.getDataSource(); if (dataSource instanceof TableColumnCore) { TableColumnCore column = (TableColumnCore) dataSource; tv.chooseColumn(column); } } } } else if (event.eventType == TableRowMouseEvent.EVENT_MOUSEMOVE) { Object data = ((TableCellCore) event.cell).getTableRowCore().getData( "AddHitArea"); if (data instanceof Rectangle) { Rectangle hitArea = (Rectangle) data; if (hitArea.contains(event.x, event.y)) { ((TableCellSWT)event.cell).setCursorID(SWT.CURSOR_HAND); return; } } ((TableCellSWT)event.cell).setCursorID(SWT.CURSOR_ARROW); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHover(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellHover(TableCell cell) { } // @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHoverComplete(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellHoverComplete(TableCell cell) { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_Sample.java0000644000175000017500000001066111135264370026760 0ustar adrianadrian/** * Created on Jan 3, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.views.columnsetup; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Rectangle; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.views.columnsetup.TableColumnSetupWindow.TableViewColumnSetup; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.impl.FakeTableCell; import org.gudy.azureus2.ui.swt.views.table.impl.TableCellImpl; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.ui.common.table.TableCellCore; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.TableRowCore; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Jan 3, 2009 * */ public class ColumnTC_Sample extends CoreTableColumn implements TableCellAddedListener { public static final String COLUMN_ID = "TableColumnSample"; public ColumnTC_Sample(String tableID) { super(COLUMN_ID, tableID); setPosition(POSITION_INVISIBLE); setRefreshInterval(INTERVAL_LIVE); setWidth(120); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellAdded(final TableCell cell) { Utils.execSWTThread(new AERunnable() { public void runSupport() { TableColumnCore column = (TableColumnCore) cell.getDataSource(); TableViewColumnSetup tv = (TableViewColumnSetup) ((TableCellCore) cell).getTableRowCore().getView(); TableRowCore sampleRow = (TableRowCore) tv.getSampleRow(); cell.addListeners(new Cell(cell, column, tv, sampleRow)); } }); } public class Cell implements TableCellRefreshListener, TableCellSWTPaintListener, TableCellVisibilityListener { private final TableColumnCore column; private FakeTableCell sampleCell; public Cell(TableCell parentCell, TableColumnCore column, TableViewColumnSetup tv, TableRowCore sampleRow) { this.column = column; if (sampleRow == null) { return; } sampleCell = new FakeTableCell(column); sampleCell.setControl(tv.getTableComposite()); Rectangle bounds = ((TableCellImpl)parentCell).getBounds(); sampleCell.setCellArea(bounds); if (sampleRow != null) { sampleCell.setDataSource(((TableRowCore)sampleRow).getDataSource(true)); } } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT) public void cellPaint(GC gc, TableCellSWT cell) { if (sampleCell == null) { return; } Rectangle bounds = ((TableCellImpl)cell).getBounds(); sampleCell.setCellArea(bounds); try { sampleCell.doPaint(gc); } catch (Throwable e) { Debug.out(e); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellVisibilityListener#cellVisibilityChanged(org.gudy.azureus2.plugins.ui.tables.TableCell, int) public void cellVisibilityChanged(TableCell cell, int visibility) { if (sampleCell == null) { return; } try { column.invokeCellVisibilityListeners((TableCellCore) sampleCell, visibility); } catch (Throwable e) { Debug.out(e); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { if (sampleCell == null) { return; } if (!cell.isShown()) { return; } sampleCell.refresh(true, true, true); cell.setSortValue(sampleCell.getSortValue()); //cell.setText(sampleCell.getText()); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_Info.java0000644000175000017500000000361511135264370026433 0ustar adrianadrian/** * Created on Jan 3, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.views.columnsetup; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.ui.common.table.TableColumnCore; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; /** * @author TuxPaper * @created Jan 3, 2009 * */ public class ColumnTC_Info extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "TableColumnInfo"; /** * @param name * @param tableID */ public ColumnTC_Info(String tableID) { super(COLUMN_ID, tableID); initialize(ALIGN_LEAD | ALIGN_TOP, POSITION_INVISIBLE, 150, INTERVAL_INVALID_ONLY); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { TableColumnCore column = (TableColumnCore) cell.getDataSource(); String key = column.getTitleLanguageKey(); if (!cell.setSortValue(key) && cell.isValid()) { return; } cell.setText(MessageText.getString(key + ".info", "")); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/peer/0000755000175000017500000000000011310377636021506 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/peer/RemotePieceDistributionView.java0000644000175000017500000000435711012724354030006 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.peer; import java.util.Arrays; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.impl.transport.PEPeerTransportProtocol; import org.gudy.azureus2.ui.swt.views.PieceDistributionView; import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags; /** * @author Aaron Grunthal * @create 02.10.2007 */ public class RemotePieceDistributionView extends PieceDistributionView { private PEPeer peer = null; /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.PieceDistributionView#dataSourceChanged(java.lang.Object) */ public void dataSourceChanged(Object newDataSource) { if (newDataSource instanceof Object[]) newDataSource = ((Object[]) newDataSource)[0]; if (newDataSource instanceof PEPeer) { peer = (PEPeer) newDataSource; pem = peer.getManager(); } else { peer = null; pem = null; } refresh(); } public void refresh() { if (pem == null) return; if (peer instanceof PEPeerTransportProtocol) { PEPeerTransportProtocol pet = (PEPeerTransportProtocol) peer; BitFlags avl = pet.getAvailable(); if (avl == null) hasPieces = null; else hasPieces = avl.flags; } else { if (peer.isSeed()) { hasPieces = new boolean[pem.getPieces().length]; Arrays.fill(hasPieces, true); } else hasPieces = null; } super.refresh(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/peer/PeerInfoView.java0000644000175000017500000004455411273743310024721 0ustar adrianadrian/* * File : PeerInfoView.java * Created : Oct 2, 2005 * By : TuxPaper * * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.peer; import java.io.InputStream; import java.util.Arrays; import java.util.Locale; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.disk.DiskManagerPiece; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.Plugin; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.Legend; import org.gudy.azureus2.ui.swt.debug.ObfusticateImage; import org.gudy.azureus2.ui.swt.debug.UIDebugGenerator; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.views.AbstractIView; import org.gudy.azureus2.ui.swt.views.IViewExtension; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags; /** * Piece Map subview for Peers View. * Testing bed for SubView stuff. * * @author TuxPaper * @created 2005/10/02 * * @todo on paint, paint cached image instead of recalc */ public class PeerInfoView extends AbstractIView implements ObfusticateImage, IViewExtension { private final static int BLOCK_FILLSIZE = 14; private final static int BLOCK_SPACING = 2; private final static int BLOCK_SIZE = BLOCK_FILLSIZE + BLOCK_SPACING; private final static int BLOCKCOLOR_AVAIL_HAVE = 0; private final static int BLOCKCOLOR_AVAIL_NOHAVE = 1; private final static int BLOCKCOLOR_NOAVAIL_HAVE = 2; private final static int BLOCKCOLOR_NOAVAIL_NOHAVE = 3; private final static int BLOCKCOLOR_TRANSFER = 4; private final static int BLOCKCOLOR_NEXT = 5; private final static int BLOCKCOLOR_AVAILCOUNT = 6; private Composite peerInfoComposite; private ScrolledComposite sc; protected Canvas peerInfoCanvas; private Color[] blockColors; private Label topLabel; private Label imageLabel; // More delay for this view because of high workload private int graphicsUpdate = COConfigurationManager .getIntParameter("Graphics Update") * 2; private int loopFactor = 0; private PEPeer peer; private Plugin countryLocator = null; private String sCountryImagesDir; private Font font = null; Image img = null; protected boolean refreshInfoCanvasQueued; /** * Initialize * */ public PeerInfoView() { blockColors = new Color[] { Colors.blues[Colors.BLUES_DARKEST], Colors.blues[Colors.BLUES_MIDLIGHT], Colors.fadedGreen, Colors.white, Colors.red, Colors.fadedRed, Colors.black }; AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { initCountryPlugin(); } }); } private void initCountryPlugin() { // Pull in Country Information if the plugin exists /** * If this view was a real plugin view, we could attach the CountryLocator.jar * to our project, cast countryLocator as CountryLocator (instead of Plugin), * and then directly call the functions. * * Since we are in core, and we don't want to add a dependency on the * CountryLocator.jar, we invoke the methods via the Class object. */ try { PluginInterface pi = PluginInitializer.getDefaultInterface() .getPluginManager().getPluginInterfaceByID("CountryLocator"); if (pi != null) { countryLocator = pi.getPlugin(); if (!pi.getPluginState().isOperational() || pi.getUtilities().compareVersions(pi.getPluginVersion(), "1.6") < 0) countryLocator = null; if (countryLocator != null) { sCountryImagesDir = (String) countryLocator.getClass().getMethod( "getImageLocation", new Class[] { Integer.TYPE }).invoke( countryLocator, new Object[] { new Integer(0) }); } } } catch (Throwable t) { } } public void dataSourceChanged(Object newDataSource) { if (newDataSource == null) peer = null; else if (newDataSource instanceof Object[]) peer = (PEPeer) ((Object[]) newDataSource)[0]; else peer = (PEPeer) newDataSource; fillPeerInfoSection(); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#getData() */ public String getData() { return "PeersView.BlockView.title"; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#initialize(org.eclipse.swt.widgets.Composite) */ public void initialize(Composite composite) { if (peerInfoComposite != null && !peerInfoComposite.isDisposed()) { Logger.log(new LogEvent(LogIDs.GUI, LogEvent.LT_ERROR, "PeerInfoView already initialized! Stack: " + Debug.getStackTrace(true, false))); delete(); } createPeerInfoPanel(composite); } private Composite createPeerInfoPanel(Composite parent) { GridLayout layout; GridData gridData; // Peer Info section contains // - Peer's Block display // - Peer's Datarate peerInfoComposite = new Composite(parent, SWT.NONE); layout = new GridLayout(); layout.numColumns = 2; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; peerInfoComposite.setLayout(layout); gridData = new GridData(GridData.FILL, GridData.FILL, true, true); peerInfoComposite.setLayoutData(gridData); imageLabel = new Label(peerInfoComposite, SWT.NULL); gridData = new GridData(); if (countryLocator != null) gridData.widthHint = 28; imageLabel.setLayoutData(gridData); topLabel = new Label(peerInfoComposite, SWT.NULL); gridData = new GridData(SWT.FILL, SWT.DEFAULT, false, false); topLabel.setLayoutData(gridData); sc = new ScrolledComposite(peerInfoComposite, SWT.V_SCROLL); sc.setExpandHorizontal(true); sc.setExpandVertical(true); layout = new GridLayout(); layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; sc.setLayout(layout); gridData = new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1); sc.setLayoutData(gridData); sc.getVerticalBar().setIncrement(BLOCK_SIZE); peerInfoCanvas = new Canvas(sc, SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND); gridData = new GridData(GridData.FILL, SWT.DEFAULT, true, false); peerInfoCanvas.setLayoutData(gridData); peerInfoCanvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { if (e.width <= 0 || e.height <= 0) return; try { Rectangle bounds = (img == null) ? null : img.getBounds(); if (bounds == null) { e.gc.fillRectangle(e.x, e.y, e.width, e.height); } else { if (e.x + e.width > bounds.width) e.gc.fillRectangle(bounds.width, e.y, e.x + e.width - bounds.width + 1, e.height); if (e.y + e.height > bounds.height) e.gc.fillRectangle(e.x, bounds.height, e.width, e.y + e.height - bounds.height + 1); int width = Math.min(e.width, bounds.width - e.x); int height = Math.min(e.height, bounds.height - e.y); e.gc.drawImage(img, e.x, e.y, width, height, e.x, e.y, width, height); } } catch (Exception ex) { } } }); Listener doNothingListener = new Listener() { public void handleEvent(Event event) { } }; peerInfoCanvas.addListener(SWT.KeyDown, doNothingListener); peerInfoCanvas.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { if (refreshInfoCanvasQueued || !peerInfoCanvas.isVisible()) { return; } // wrap in asyncexec because sc.setMinWidth (called later) doesn't work // too well inside a resize (the canvas won't size isn't always updated) Utils.execSWTThreadLater(100, new AERunnable() { public void runSupport() { if (refreshInfoCanvasQueued) { return; } refreshInfoCanvasQueued = true; if (img != null) { int iOldColCount = img.getBounds().width / BLOCK_SIZE; int iNewColCount = peerInfoCanvas.getClientArea().width / BLOCK_SIZE; if (iOldColCount != iNewColCount) refreshInfoCanvas(); } } }); } }); sc.setContent(peerInfoCanvas); Legend.createLegendComposite(peerInfoComposite, blockColors, new String[] { "PeersView.BlockView.Avail.Have", "PeersView.BlockView.Avail.NoHave", "PeersView.BlockView.NoAvail.Have", "PeersView.BlockView.NoAvail.NoHave", "PeersView.BlockView.Transfer", "PeersView.BlockView.NextRequest", "PeersView.BlockView.AvailCount" }, new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1)); int iFontPixelsHeight = 10; int iFontPointHeight = (iFontPixelsHeight * 72) / peerInfoCanvas.getDisplay().getDPI().y; Font f = peerInfoCanvas.getFont(); FontData[] fontData = f.getFontData(); fontData[0].setHeight(iFontPointHeight); font = new Font(peerInfoCanvas.getDisplay(), fontData); return peerInfoComposite; } public void fillPeerInfoSection() { if (imageLabel.getImage() != null) { Image image = imageLabel.getImage(); imageLabel.setImage(null); image.dispose(); } if (peer == null) { topLabel.setText(""); } else { String s = peer.getClient(); if (s == null) s = ""; if (s != "") s += "; "; s += peer.getIp() + "; " + DisplayFormatters.formatPercentFromThousands(peer .getPercentDoneInThousandNotation()); topLabel.setText(s); if (countryLocator != null) { try { String sCountry = (String) countryLocator.getClass().getMethod( "getIPCountry", new Class[] { String.class, Locale.class }) .invoke(countryLocator, new Object[] { peer.getIp(), Locale.getDefault() }); String sCode = (String) countryLocator.getClass().getMethod( "getIPISO3166", new Class[] { String.class }).invoke( countryLocator, new Object[] { peer.getIp() }); imageLabel.setToolTipText(sCode + "- " + sCountry); InputStream is = countryLocator.getClass().getClassLoader() .getResourceAsStream( sCountryImagesDir + "/" + sCode.toLowerCase() + ".png"); if (is != null) { Image img = new Image(imageLabel.getDisplay(), is); img.setBackground(imageLabel.getBackground()); imageLabel.setImage(img); } } catch (Exception e) { // ignore } } } refreshInfoCanvas(); } public void refresh() { super.refresh(); if (loopFactor++ % graphicsUpdate == 0) { refreshInfoCanvas(); } } private void refreshInfoCanvas() { refreshInfoCanvasQueued = false; peerInfoCanvas.layout(true); Rectangle bounds = peerInfoCanvas.getClientArea(); if (bounds.width <= 0 || bounds.height <= 0) return; if (img != null && !img.isDisposed()) { img.dispose(); img = null; } if (peer == null || peer.getPeerState() != PEPeer.TRANSFERING) { GC gc = new GC(peerInfoCanvas); gc.fillRectangle(bounds); gc.dispose(); return; } BitFlags peerHavePieces = peer.getAvailable(); if (peerHavePieces == null) { GC gc = new GC(peerInfoCanvas); gc.fillRectangle(bounds); gc.dispose(); return; } DiskManagerPiece[] dm_pieces = null; PEPeerManager pm = peer.getManager(); DiskManager dm = pm.getDiskManager(); dm_pieces = dm.getPieces(); int iNumCols = bounds.width / BLOCK_SIZE; int iNeededHeight = (((dm.getNbPieces() - 1) / iNumCols) + 1) * BLOCK_SIZE; if (sc.getMinHeight() != iNeededHeight) { sc.setMinHeight(iNeededHeight); sc.layout(true, true); bounds = peerInfoCanvas.getClientArea(); } img = new Image(peerInfoCanvas.getDisplay(), bounds.width, iNeededHeight); GC gcImg = new GC(img); try { // use advanced capabilities for faster drawText gcImg.setAdvanced(true); gcImg.setBackground(peerInfoCanvas.getBackground()); gcImg.fillRectangle(0, 0, bounds.width, iNeededHeight); int[] availability = pm.getAvailability(); int iNextDLPieceID = -1; int iDLPieceID = -1; int[] ourRequestedPieces = peer.getOutgoingRequestedPieceNumbers(); if (ourRequestedPieces != null) { if (!peer.isChokingMe()) { // !choking == downloading if (ourRequestedPieces.length > 0) { iDLPieceID = ourRequestedPieces[0]; if (ourRequestedPieces.length > 1) iNextDLPieceID = ourRequestedPieces[1]; } } else { if (ourRequestedPieces.length > 0) iNextDLPieceID = ourRequestedPieces[0]; } // if (iNextDLPieceID == -1) { // iNextDLPieceID = peer.getNextPieceNumberGuess(); // } } int[] peerRequestedPieces = peer.getIncomingRequestedPieceNumbers(); if (peerRequestedPieces == null) peerRequestedPieces = new int[0]; int peerNextRequestedPiece = -1; if (peerRequestedPieces.length > 0) peerNextRequestedPiece = peerRequestedPieces[0]; Arrays.sort(peerRequestedPieces); int iRow = 0; int iCol = 0; for (int i = 0; i < peerHavePieces.flags.length; i++) { int colorIndex; boolean done = (dm_pieces == null) ? false : dm_pieces[i].isDone(); int iXPos = iCol * BLOCK_SIZE; int iYPos = iRow * BLOCK_SIZE; if (done) { if (peerHavePieces.flags[i]) colorIndex = BLOCKCOLOR_AVAIL_HAVE; else colorIndex = BLOCKCOLOR_NOAVAIL_HAVE; gcImg.setBackground(blockColors[colorIndex]); gcImg.fillRectangle(iXPos, iYPos, BLOCK_FILLSIZE, BLOCK_FILLSIZE); } else { // !done boolean partiallyDone = (dm_pieces == null) ? false : dm_pieces[i] .getNbWritten() > 0; int x = iXPos; int width = BLOCK_FILLSIZE; if (partiallyDone) { if (peerHavePieces.flags[i]) colorIndex = BLOCKCOLOR_AVAIL_HAVE; else colorIndex = BLOCKCOLOR_NOAVAIL_HAVE; gcImg.setBackground(blockColors[colorIndex]); int iNewWidth = (int) (((float) dm_pieces[i].getNbWritten() / dm_pieces[i] .getNbBlocks()) * width); if (iNewWidth >= width) iNewWidth = width - 1; else if (iNewWidth <= 0) iNewWidth = 1; gcImg.fillRectangle(x, iYPos, iNewWidth, BLOCK_FILLSIZE); width -= iNewWidth; x += iNewWidth; } if (peerHavePieces.flags[i]) colorIndex = BLOCKCOLOR_AVAIL_NOHAVE; else colorIndex = BLOCKCOLOR_NOAVAIL_NOHAVE; gcImg.setBackground(blockColors[colorIndex]); gcImg.fillRectangle(x, iYPos, width, BLOCK_FILLSIZE); } // Down Arrow inside box for "dowloading" piece if (i == iDLPieceID) { gcImg.setBackground(blockColors[BLOCKCOLOR_TRANSFER]); gcImg.fillPolygon(new int[] { iXPos, iYPos, iXPos + BLOCK_FILLSIZE, iYPos, iXPos + (BLOCK_FILLSIZE / 2), iYPos + BLOCK_FILLSIZE }); } // Small Down Arrow inside box for next download piece if (i == iNextDLPieceID) { gcImg.setBackground(blockColors[BLOCKCOLOR_NEXT]); gcImg.fillPolygon(new int[] { iXPos + 2, iYPos + 2, iXPos + BLOCK_FILLSIZE - 1, iYPos + 2, iXPos + (BLOCK_FILLSIZE / 2), iYPos + BLOCK_FILLSIZE - 1 }); } // Up Arrow in uploading piece if (i == peerNextRequestedPiece) { gcImg.setBackground(blockColors[BLOCKCOLOR_TRANSFER]); gcImg.fillPolygon(new int[] { iXPos, iYPos + BLOCK_FILLSIZE, iXPos + BLOCK_FILLSIZE, iYPos + BLOCK_FILLSIZE, iXPos + (BLOCK_FILLSIZE / 2), iYPos }); } else if (Arrays.binarySearch(peerRequestedPieces, i) >= 0) { // Small Up Arrow each upload request gcImg.setBackground(blockColors[BLOCKCOLOR_NEXT]); gcImg.fillPolygon(new int[] { iXPos + 1, iYPos + BLOCK_FILLSIZE - 2, iXPos + BLOCK_FILLSIZE - 2, iYPos + BLOCK_FILLSIZE - 2, iXPos + (BLOCK_FILLSIZE / 2), iYPos + 2 }); } if (availability != null) { gcImg.setFont(font); String sNumber = String.valueOf(availability[i]); Point size = gcImg.stringExtent(sNumber); if (availability[i] < 100) { int x = iXPos + (BLOCK_FILLSIZE / 2) - (size.x / 2); int y = iYPos + (BLOCK_FILLSIZE / 2) - (size.y / 2); gcImg.setForeground(blockColors[BLOCKCOLOR_AVAILCOUNT]); gcImg.drawText(sNumber, x, y, true); } } iCol++; if (iCol >= iNumCols) { iCol = 0; iRow++; } } } catch (Exception e) { Logger.log(new LogEvent(LogIDs.GUI, "drawing piece map", e)); } finally { gcImg.dispose(); } peerInfoCanvas.redraw(); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#getComposite() */ public Composite getComposite() { return peerInfoComposite; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#delete() */ public void delete() { if (!imageLabel.isDisposed() && imageLabel.getImage() != null) { Image image = imageLabel.getImage(); imageLabel.setImage(null); image.dispose(); } if (img != null && !img.isDisposed()) { img.dispose(); img = null; } if (font != null && !font.isDisposed()) { font.dispose(); font = null; } super.delete(); } public Image obfusticatedImage(Image image, Point shellOffset) { UIDebugGenerator.obfusticateArea(image, topLabel, shellOffset, ""); return image; } public Menu getPrivateMenu() { return null; } public void viewActivated() { refreshInfoCanvas(); } public void viewDeactivated() { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/0000755000175000017500000000000011310377632022700 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/0000755000175000017500000000000011310377640025125 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/BadAvailTimeItem.java0000644000175000017500000000646611135264366031112 0ustar adrianadrian/* * Created on 05-May-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import java.util.Locale; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; public class BadAvailTimeItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "bad_avail_time"; private static String now_string; static{ MessageText.addAndFireListener( new MessageText.MessageTextListener() { public void localeChanged( Locale old_locale, Locale new_locale ) { now_string = MessageText.getString( "SpeedView.stats.now" ); } }); } public BadAvailTimeItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, 120, sTableID); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SWARM, CAT_TIME, }); info.setProficiency(TableColumnInfo.PROFICIENCY_ADVANCED); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); long value = dm==null?-1:dm.getStats().getAvailWentBadTime(); if ( value == 0 ){ // zero means no recorded last bad availability time (bad=transition from >=1 -> < 1) PEPeerManager pm = dm.getPeerManager(); if ( pm == null || pm.getMinAvailability() < 1.0 ){ long stopped = dm.getDownloadState().getLongAttribute( DownloadManagerState.AT_TIME_STOPPED ); if ( stopped > 0 ){ value = stopped; }else{ value = -1; } }else{ value = -2; } } String text; if ( value == -1 ){ text = ""; }else if ( value == -2 ){ text = now_string; }else{ text = DisplayFormatters.formatDate(value); } if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(text); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TorrentPathItem.java0000644000175000017500000000457711135264366031103 0ustar adrianadrian/* * Created on 19-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; /** * @author parg * */ import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; public class TorrentPathItem extends CoreTableColumn implements TableCellRefreshListener, ObfusticateCellText { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "torrentpath"; /** Default Constructor */ public TorrentPathItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 150, sTableID); setObfustication(true); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, }); info.setProficiency(TableColumnInfo.PROFICIENCY_ADVANCED); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); cell.setText((dm == null) ? "" : dm.getTorrentFileName()); } public String getObfusticatedText(TableCell cell) { return Debug.secretFileName(cell.getText()); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AbstractTrackerCell.java0000644000175000017500000000664511135264366031667 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import java.net.URL; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerTrackerListener; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.plugins.ui.tables.*; /** * Base cell class for cells listening to the tracker listener */ abstract class AbstractTrackerCell implements TableCellRefreshListener, TableCellToolTipListener, TableCellDisposeListener, DownloadManagerTrackerListener { TableCell cell; DownloadManager dm; /** * Initialize * * @param cell */ public AbstractTrackerCell(TableCell cell) { this.cell = cell; cell.addListeners(this); dm = (DownloadManager) cell.getDataSource(); if (dm == null) return; dm.addTrackerListener(this); } public void announceResult(TRTrackerAnnouncerResponse response) { // Don't care about announce } public boolean checkScrapeResult(final TRTrackerScraperResponse response) { if (response != null) { TableCell cell_ref = cell; if ( cell_ref == null ){ return( false ); } // Exit if this scrape result is not from the tracker currently being used. DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm == null || dm != this.dm) return false; TOTorrent torrent = dm.getTorrent(); if ( torrent == null ){ return( false ); } URL announceURL = torrent.getAnnounceURL(); URL responseURL = response.getURL(); if (announceURL != responseURL && announceURL != null && responseURL != null && !announceURL.toString().equals(responseURL.toString())) return false; cell_ref.invalidate(); return response.isValid(); } return false; } public void refresh(TableCell cell) { DownloadManager oldDM = dm; dm = (DownloadManager) cell.getDataSource(); // datasource changed, change listener if (dm != oldDM) { if (oldDM != null) oldDM.removeTrackerListener(this); if (dm != null) dm.addTrackerListener(this); } } public void cellHover(TableCell cell) { } public void cellHoverComplete(TableCell cell) { cell.setToolTip(null); } public void dispose(TableCell cell) { if (dm != null) dm.removeTrackerListener(this); DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm != null && dm != this.dm) dm.removeTrackerListener(this); dm = null; cell = null; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateAddedItem.java0000644000175000017500000000660211135264366030417 0ustar adrianadrian/* * Created on 05-May-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import java.io.File; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator; import org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer; import com.aelitis.azureus.ui.common.table.TableRowCore; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.menus.MenuItemListener; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem; public class DateAddedItem extends ColumnDateSizer { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "date_added"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_TIME, CAT_CONTENT }); } public DateAddedItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, TableColumnCreator.DATE_COLUMN_WIDTH, sTableID); setMultiline(false); TableContextMenuItem menuReset = addContextMenuItem("TableColumn.menu.date_added.reset"); menuReset.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof TableRowCore) { TableRowCore row = (TableRowCore) target; Object dataSource = row.getDataSource(true); if (dataSource instanceof DownloadManager) { DownloadManager dm = (DownloadManager) dataSource; DownloadManagerState state = dm.getDownloadState(); try { long add_time = new File(dm.getTorrentFileName()).lastModified(); if (add_time >= 0) { state.setLongParameter( DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME, add_time); } } catch (Throwable e) { } } row.getTableCell("date_added").invalidate(); } } }); } /** * @param tableID * @param b */ public DateAddedItem(String tableID, boolean v) { this(tableID); setVisible(v); } public void refresh(TableCell cell, long timestamp) { DownloadManager dm = (DownloadManager) cell.getDataSource(); timestamp = (dm == null) ? 0 : dm.getDownloadState().getLongParameter( DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME); super.refresh(cell, timestamp); //cell.setText(DisplayFormatters.formatDate(timestamp)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerNameItem.java0000644000175000017500000000607611135264366031021 0ustar adrianadrian/* * File : TrackerStatusItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.StringInterner; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author Olivier * */ public class TrackerNameItem extends CoreTableColumn implements TableCellRefreshListener, TableCellToolTipListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "trackername"; public TrackerNameItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 120, sTableID); setRefreshInterval(5); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_TRACKER, }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); String name = ""; if( dm != null && dm.getTorrent() != null ) { String host = dm.getTorrent().getAnnounceURL().getHost(); String[] parts = host.split( "\\." ); int used = 0; for( int i = parts.length-1; i >= 0; i-- ) { if( used > 4 ) break; //don't use more than 4 segments String chunk = parts[ i ]; if( used < 2 || chunk.length() < 11 ) { //use first end two always, but trim out >10 chars (passkeys) if( used == 0 ) name = chunk; else name = chunk + "." + name; used++; } else break; } if(name.equals(host)) name = host; else name = StringInterner.intern(name); } if (cell.setText(name) || !cell.isValid()) { TrackerCellUtils.updateColor(cell, dm, false); } } public void cellHover(TableCell cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); cell.setToolTip(TrackerCellUtils.getTooltipText(cell, dm, false)); } public void cellHoverComplete(TableCell cell) { cell.setToolTip(null); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/FilesDoneItem.java0000644000175000017500000000572511135264366030475 0ustar adrianadrian/* * File : SavePathItem.java * Created : 01 febv. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.StringInterner; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; public class FilesDoneItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "filesdone"; public FilesDoneItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, 50, sTableID); setRefreshInterval(5); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, CAT_PROGRESS }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); String text = ""; if ( dm != null ){ int complete = 0; int skipped = 0; int skipped_complete = 0; DiskManagerFileInfo[] files = dm.getDiskManagerFileInfo(); int total = files.length; for (int i=0;i 60) ? (value % 60) : 1) * 1000); map.put(dm, new Long(lNextUpdate)); if (!cell.setSortValue(value) && cell.isValid()) return; String sText = TimeFormatter.formatColon(value); if (value > 60) sText = "< " + sText; TrackerCellUtils.updateColor(cell, dm, false); cell.setText(sText); } public void cellHover(TableCell cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); cell.setToolTip(TrackerCellUtils.getTooltipText(cell, dm, false)); } public void cellHoverComplete(TableCell cell) { cell.setToolTip(null); } public void dispose(TableCell cell) { map.remove(cell.getDataSource()); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ETAItem.java0000644000175000017500000000447411135264370027231 0ustar adrianadrian/* * File : ETAItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class ETAItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = DownloadTypeIncomplete.class; public static final String COLUMN_ID = "eta"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_ESSENTIAL }); } /** Default Constructor */ public ETAItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 60, sTableID); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); long value = (dm == null) ? 0 : dm.getStats().getETA(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatETA(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/OnlyCDing4Item.java0000644000175000017500000000456211135264366030535 0ustar adrianadrian/* * File : SecondsSeedingItem.java * Created : 01 feb. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author TuxPaper * @since 2.0.8.5 */ public class OnlyCDing4Item extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "OnlyCDing4"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SHARING }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } /** Default Constructor */ public OnlyCDing4Item(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); long value = (dm == null) ? 0 : dm.getStats().getSecondsOnlySeeding(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(TimeFormatter.format(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SwarmAverageCompletion.java0000644000175000017500000000515011135264366032414 0ustar adrianadrian/* * Created : 11 nov. 2004 * By : Alon Rohter * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; public class SwarmAverageCompletion extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "swarm_average_completion"; public SwarmAverageCompletion(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setRefreshInterval(INTERVAL_GRAPHIC); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SWARM, CAT_PROGRESS }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } public void refresh(TableCell cell) { int average = -1; DownloadManager dm = (DownloadManager)cell.getDataSource(); if( dm != null ) { PEPeerManager pm = dm.getPeerManager(); if( pm != null ) { average = pm.getAverageCompletionInThousandNotation(); } } if( !cell.setSortValue( average ) && cell.isValid() ) { return; } if( average < 0 ) { cell.setText( "" ); } else { cell.setText( DisplayFormatters.formatPercentFromThousands( average ) ); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NameItem.java0000644000175000017500000001333611267524616027505 0ustar adrianadrian/* * File : NameItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.eclipse.swt.graphics.Image; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.UIInputReceiver; import org.gudy.azureus2.plugins.ui.UIInputReceiverListener; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.menus.MenuItemListener; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.ImageRepository; import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow; import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** Torrent name cell for My Torrents. * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class NameItem extends CoreTableColumn implements TableCellLightRefreshListener, ObfusticateCellText, TableCellDisposeListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "name"; private boolean showIcon; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_ESSENTIAL, CAT_CONTENT }); } /** * * @param sTableID */ public NameItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 250, sTableID); setObfustication(true); setRefreshInterval(INTERVAL_LIVE); setType(TableColumn.TYPE_TEXT); setMinWidth(100); TableContextMenuItem menuItem = addContextMenuItem("MyTorrentsView.menu.rename.displayed"); menuItem.addMultiListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target == null) { return; } Object[] o = (Object[]) target; for (Object object : o) { if (object instanceof DownloadManager) { final DownloadManager dm = (DownloadManager) object; String msg_key_prefix = "MyTorrentsView.menu.rename.displayed.enter."; SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow( msg_key_prefix + "title", msg_key_prefix + "message"); entryWindow.setPreenteredText(dm.getDisplayName(), false); entryWindow.prompt(new UIInputReceiverListener() { public void UIInputReceiverClosed(UIInputReceiver entryWindow) { if (!entryWindow.hasSubmittedInput()) { return; } String value = entryWindow.getSubmittedInput(); if (value != null && value.length() > 0) { dm.getDownloadState().setDisplayName(value); } } }); } } } }); COConfigurationManager.addAndFireParameterListener( "NameColumn.showProgramIcon", new ParameterListener() { public void parameterChanged(String parameterName) { setShowIcon(COConfigurationManager.getBooleanParameter("NameColumn.showProgramIcon")); } }); } public void refresh(TableCell cell) { refresh(cell, false); } public void refresh(TableCell cell, boolean sortOnlyRefresh) { String name = null; DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm != null) name = dm.getDisplayName(); if (name == null) name = ""; //setText returns true only if the text is updated if ((cell.setText(name) || !cell.isValid())) { if (dm != null && isShowIcon() && !sortOnlyRefresh && (cell instanceof TableCellSWT)) { String path = dm.getDownloadState().getPrimaryFile(); if (path != null) { // Don't ever dispose of PathIcon, it's cached and may be used elsewhere TOTorrent torrent = dm.getTorrent(); Image icon = ImageRepository.getPathIcon(path, false, torrent != null && !torrent.isSimpleTorrent()); ((TableCellSWT) cell).setIcon(icon); } } } } public String getObfusticatedText(TableCell cell) { String name = null; DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm != null) { name = dm.toString(); int i = name.indexOf('#'); if (i > 0) { name = name.substring(i + 1); } } if (name == null) name = ""; return name; } public void dispose(TableCell cell) { } private void disposeCellIcon(TableCell cell) { if (!(cell instanceof TableCellSWT)) { return; } final Image img = ((TableCellSWT) cell).getIcon(); if (img != null) { ((TableCellSWT) cell).setIcon(null); if (!img.isDisposed()) { img.dispose(); } } } /** * @param showIcon the showIcon to set */ public void setShowIcon(boolean showIcon) { this.showIcon = showIcon; } /** * @return the showIcon */ public boolean isShowIcon() { return showIcon; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PiecesItem.java0000644000175000017500000002125011135264366030024 0ustar adrianadrian/* * File : PiecesItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.disk.DiskManagerPiece; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.Graphic; import org.gudy.azureus2.plugins.ui.tables.*; /** * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class PiecesItem extends CoreTableColumn implements TableCellAddedListener, TableCellRefreshListener, TableCellDisposeListener { public static final Class DATASOURCE_TYPE = DownloadTypeIncomplete.class; private final static int INDEX_COLOR_NONEAVAIL = Colors.BLUES_DARKEST + 1; // only supports 0 or 1 border size private final static int borderHorizontalSize = 1; private final static int borderVerticalSize = 1; private final static int borderSplit = 1; // height of little completion bar above piece bar. private final static int completionHeight = 2; public static final String COLUMN_ID = "pieces"; private int marginHeight = -1; /** Default Constructor */ public PiecesItem(String sTableID) { this(sTableID,-1); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, CAT_PROGRESS }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } /** * * @param sTableID * @param marginHeight -- Margin height above and below the pieces graphic; used in cases where the row is very tall */ public PiecesItem(String sTableID, int marginHeight) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 100, sTableID); this.marginHeight = marginHeight; initializeAsGraphic(POSITION_INVISIBLE, 100); setMinWidth(100); } public void cellAdded(TableCell cell) { if (marginHeight != -1) { cell.setMarginHeight(marginHeight); } cell.setFillCell(true); } public void dispose(TableCell cell) { // Named infoObj so code can be copied easily to the other PiecesItem DownloadManager infoObj = (DownloadManager) cell.getDataSource(); if (infoObj == null) return; Image img = (Image) infoObj.getUserData("PiecesImage"); if (img != null && !img.isDisposed()) img.dispose(); infoObj.setUserData("PiecesImageBuffer", null); infoObj.setUserData("PiecesImage", null); } public void refresh(TableCell cell) { /* Notes: * We store our image and imageBufer in DownloadManager using * setData & getData. */ // Named infoObj so code can be copied easily to the other PiecesItem DownloadManager infoObj = (DownloadManager) cell.getDataSource(); long lCompleted = (infoObj == null) ? 0 : infoObj.getStats().getCompleted(); boolean bForce = infoObj != null && infoObj.getUserData("PiecesImage") == null; if (!cell.setSortValue(lCompleted) && cell.isValid() && !bForce) { return; } if (infoObj == null) return; //Compute bounds ... int newWidth = cell.getWidth(); if (newWidth <= 0) return; int newHeight = cell.getHeight(); int x0 = borderVerticalSize; int x1 = newWidth - 1 - borderVerticalSize; int y0 = completionHeight + borderHorizontalSize + borderSplit; int y1 = newHeight - 1 - borderHorizontalSize; int drawWidth = x1 - x0 + 1; if (drawWidth < 10 || y1 < 3) return; boolean bImageBufferValid = true; int[] imageBuffer = (int[]) infoObj.getUserData("PiecesImageBuffer"); if (imageBuffer == null || imageBuffer.length != drawWidth) { imageBuffer = new int[drawWidth]; bImageBufferValid = false; } Image image = (Image) infoObj.getUserData("PiecesImage"); GC gcImage; boolean bImageChanged; Rectangle imageBounds; if (image == null || image.isDisposed()) { bImageChanged = true; } else { imageBounds = image.getBounds(); bImageChanged = imageBounds.width != newWidth || imageBounds.height != newHeight; } if (bImageChanged) { if (image != null && !image.isDisposed()) { image.dispose(); } image = new Image(SWTThread.getInstance().getDisplay(), newWidth, newHeight); imageBounds = image.getBounds(); bImageBufferValid = false; // draw border gcImage = new GC(image); gcImage.setForeground(Colors.grey); if (borderHorizontalSize > 0) { if (borderVerticalSize > 0) { gcImage.drawRectangle(0, 0, newWidth - 1, newHeight - 1); } else { gcImage.drawLine(0, 0, newWidth - 1, 0); gcImage.drawLine(0, newHeight - 1, newWidth - 1, newHeight - 1); } } else if (borderVerticalSize > 0) { gcImage.drawLine(0, 0, 0, newHeight - 1); gcImage.drawLine(newWidth - 1, 0, newWidth - 1, newHeight - 1); } if (borderSplit > 0) { gcImage.setForeground(Colors.white); gcImage.drawLine(x0, completionHeight + borderHorizontalSize, x1, completionHeight + borderHorizontalSize); } } else { gcImage = new GC(image); } DiskManager disk_manager = infoObj.getDiskManager(); DiskManagerPiece[] pieces = disk_manager == null ? null : disk_manager.getPieces(); int nbPieces = infoObj.getNbPieces(); try { int nbComplete = 0; int a0; int a1 = 0; for (int i = 0; i < drawWidth; i++) { if (i == 0) { // always start out with one piece a0 = 0; a1 = nbPieces / drawWidth; if (a1 == 0) a1 = 1; } else { // the last iteration, a1 will be nbPieces a0 = a1; a1 = ((i + 1) * nbPieces) / (drawWidth); } int index; if (a1 <= a0) { index = imageBuffer[i - 1]; } else { int nbAvailable = 0; for (int j = a0; j < a1; j++) if (pieces != null && pieces[j].isDone()) nbAvailable++; nbComplete += nbAvailable; index = (nbAvailable * Colors.BLUES_DARKEST) / (a1 - a0); //System.out.println("i="+i+";nbAvailable="+nbAvailable+";nbComplete="+nbComplete+";nbPieces="+nbPieces+";a0="+a0+";a1="+a1); } if (!bImageBufferValid || imageBuffer[i] != index) { imageBuffer[i] = index; bImageChanged = true; gcImage.setForeground(index == INDEX_COLOR_NONEAVAIL ? Colors.red : Colors.blues[index]); gcImage.drawLine(i + x0, y0, i + x0, y1); } } // pieces can sometimes be 0 due to timing or bad torrent (well, there's a bug with a /0 error // so it can happen somehow :) int limit = nbPieces == 0 ? 0 : ((drawWidth * nbComplete) / nbPieces); if (limit < drawWidth) { gcImage.setBackground(Colors.blues[Colors.BLUES_LIGHTEST]); gcImage.fillRectangle(limit + x0, borderHorizontalSize, x1 - limit, completionHeight); } gcImage.setBackground(Colors.colorProgressBar); gcImage.fillRectangle(x0, borderHorizontalSize, limit, completionHeight); } catch (Exception e) { System.out.println("Error Drawing PiecesItem"); Debug.printStackTrace(e); } gcImage.dispose(); Image oldImage = null; Graphic graphic = cell.getGraphic(); if (graphic instanceof UISWTGraphic) { oldImage = ((UISWTGraphic) graphic).getImage(); } if (bImageChanged || image != oldImage || !cell.isValid()) { if (cell instanceof TableCellSWT) { ((TableCellSWT) cell).setGraphic(image); } else { cell.setGraphic(new UISWTGraphicImpl(image)); } if (bImageChanged) { cell.invalidate(); } infoObj.setUserData("PiecesImage", image); infoObj.setUserData("PiecesImageBuffer", imageBuffer); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpSpeedItem.java0000644000175000017500000001003611135264366030161 0ustar adrianadrian/* * File : UpSpeedItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.eclipse.swt.graphics.Color; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.util.StringInterner; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.plugins.startstoprules.defaultplugin.DefaultRankCalculator; import com.aelitis.azureus.plugins.startstoprules.defaultplugin.StartStopRulesDefaultPlugin; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadTypeComplete; import org.gudy.azureus2.plugins.ui.tables.*; /** Upload Speed column * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class UpSpeedItem extends CoreTableColumn implements TableCellAddedListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "upspeed"; /* * Default Constructor * * @param sTableID The ID of the table the cell belongs to */ public UpSpeedItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setType(TableColumn.TYPE_TEXT); setRefreshInterval(INTERVAL_LIVE); setUseCoreDataSource(false); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SHARING, CAT_BYTES }); Class dsType = info.getColumn().getForDataSourceType(); if (DownloadTypeComplete.class == dsType) { info.addCategories(new String[] { CAT_ESSENTIAL }); } } public void cellAdded(TableCell cell) { cell.addRefreshListener(new RefreshListener()); } public class RefreshListener implements TableCellRefreshListener { private int iLastState; private int loop = 0; public void refresh(TableCell cell) { Download dm = (Download)cell.getDataSource(); long value; int iState; if (dm == null) { iState = -1; value = 0; } else { iState = dm.getState(); value = dm.getStats().getUploadAverage(); } boolean bChangeColor = (++loop % 10) == 0; if (cell.setSortValue(value) || !cell.isValid() || (iState != iLastState)) { cell.setText(StringInterner.intern(DisplayFormatters.formatByteCountToKiBEtcPerSec(value))); bChangeColor = true; } if (bChangeColor) { changeColor(cell, dm, iState); loop = 0; } } private void changeColor(TableCell cell, Download dl, int iState) { try { DefaultRankCalculator calc = StartStopRulesDefaultPlugin.getRankCalculator(dl); Color newFG = null; if (calc != null && dl.getState() == Download.ST_SEEDING && !calc.getActivelySeeding()) newFG = Colors.colorWarning; cell.setForeground(Utils.colorToIntArray(newFG)); iLastState = iState; } catch (Exception e) { Debug.printStackTrace( e ); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AvgAvailItem.java0000644000175000017500000000605411135264366030313 0ustar adrianadrian/* * File : AvailabilityItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** Avg Avail/"Seeing Copies/peer" Column * * @author MjrTom * @since 2.3.0.7 */ public class AvgAvailItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; // If you want more decimals, just add a zero private static final String zeros = "0000"; // # decimal places == numZeros - 1 private static final int numZeros = zeros.length(); public static final String COLUMN_ID = "AvgAvail"; private int iTimesBy; /** Default Constructor */ public AvgAvailItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 50, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); iTimesBy = 1; for (int i = 1; i < numZeros; i++) iTimesBy *= 10; } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SWARM }); } public void refresh(TableCell cell) { String sText = ""; DownloadManager dm = (DownloadManager)cell.getDataSource(); if (dm == null) return; PEPeerManager pm = dm.getPeerManager(); if (pm != null) { float f =pm.getAvgAvail(); if (!cell.setSortValue((long)(f * 1000)) && cell.isValid()) return; sText = String.valueOf((int)(f * iTimesBy)); if (numZeros - sText.length() > 0) sText = zeros.substring(0, numZeros - sText.length()) + sText; sText = sText.substring(0, sText.length() - numZeros + 1) + "." + sText.substring(sText.length() - numZeros + 1); } else { cell.setSortValue(0); } cell.setText(sText); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TimeSinceDownloadItem.java0000644000175000017500000000510211135264366032162 0ustar adrianadrian/* * File : SecondsDownloadingItem.java * Created : 01 febv. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author TuxPaper * @since 2.0.8.5 */ public class TimeSinceDownloadItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = DownloadTypeIncomplete.class; public static final String COLUMN_ID = "timesincedownload"; /** Default Constructor */ public TimeSinceDownloadItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_TIME }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); int value = (dm == null) ? -2 : dm.getStats().getTimeSinceLastDataReceivedInSeconds(); if (!cell.setSortValue(value==-1?Integer.MAX_VALUE:value) && cell.isValid()) return; cell.setText(value==-2?"":(value==-1?Constants.INFINITY_STRING:TimeFormatter.format(value)));; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/RankItem.java0000644000175000017500000001204011171750562027502 0ustar adrianadrian/* * File : RankItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerListener; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerListener; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * Torrent Position column. * * One object for all rows to save memory * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class RankItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "#"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT }); } private boolean bInvalidByTrigger = false; private boolean showCompleteIncomplete = false; /** Default Constructor */ public RankItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 50, sTableID); setRefreshInterval(INTERVAL_INVALID_ONLY); AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { core.getGlobalManager().addListener(new GMListener()); } }); setMaxWidthAuto(true); setMinWidthAuto(true); } public RankItem(String sTableID, boolean showCompleteIncomplete) { this(sTableID); this.showCompleteIncomplete = showCompleteIncomplete; } public void refresh(TableCell cell) { bInvalidByTrigger = false; DownloadManager dm = (DownloadManager)cell.getDataSource(); long value = (dm == null) ? 0 : dm.getPosition(); String text; if (showCompleteIncomplete) { boolean complete = dm == null ? false : dm.getAssumedComplete(); text = (complete ? "Done\n#" : "Partial\n#") + value; if (complete) { value += 0x10000; } } else { text = "" + value; } cell.setSortValue(value); cell.setText(text); } private class GMListener implements GlobalManagerListener { DownloadManagerListener listener; public GMListener() { listener = new DownloadManagerListener() { public void completionChanged(DownloadManager manager, boolean bCompleted) { } public void downloadComplete(DownloadManager manager) { } public void positionChanged(DownloadManager download, int oldPosition, int newPosition) { /** We will be getting multiple position changes, but we only need * to invalidate cells once. */ if (bInvalidByTrigger) return; RankItem.this.invalidateCells(); bInvalidByTrigger = true; } public void stateChanged(DownloadManager manager, int state) { } public void filePriorityChanged( DownloadManager download, org.gudy.azureus2.core3.disk.DiskManagerFileInfo file ) { } }; } public void destroyed() { } public void destroyInitiated() { try { GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); gm.removeListener(this); } catch (Exception e) { Debug.out(e); } } public void downloadManagerAdded(DownloadManager dm) { dm.addListener(listener); } public void downloadManagerRemoved(DownloadManager dm) { dm.removeListener(listener); } public void seedingStatusChanged(boolean seeding_only_mode, boolean b) { } } public boolean isShowCompleteIncomplete() { return showCompleteIncomplete; } public void setShowCompleteIncomplete(boolean showCompleteIncomplete) { this.showCompleteIncomplete = showCompleteIncomplete; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DoneItem.java0000644000175000017500000000457311135264370027505 0ustar adrianadrian/* * File : DoneItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.*; /** % Done column in My Torrents * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class DoneItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "done"; /** Default Constructor */ public DoneItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 55, sTableID); setRefreshInterval(INTERVAL_LIVE); if (sTableID.equals(TableManager.TABLE_MYTORRENTS_INCOMPLETE)) setPosition(POSITION_LAST); else setPosition(POSITION_INVISIBLE); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROGRESS }); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); int value = (dm == null) ? 0 : dm.getStats().getCompleted(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatPercentFromThousands(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/HealthItem.java0000644000175000017500000001247311171750562030026 0ustar adrianadrian/* * File : HealthItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.tracker.host.TRHost; import org.gudy.azureus2.core3.tracker.host.TRHostTorrent; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.*; /** * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class HealthItem extends CoreTableColumn implements TableCellAddedListener, TableCellRefreshListener, TableCellSWTPaintListener { public static final Class DATASOURCE_TYPE = Download.class; static final int COLUMN_WIDTH = 16; public static final String COLUMN_ID = "health"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_ESSENTIAL }); } static TRHost tracker_host = null; /** Default Constructor */ public HealthItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, COLUMN_WIDTH, sTableID); initializeAsGraphic(POSITION_LAST, COLUMN_WIDTH); setMinWidth(COLUMN_WIDTH); } public void cellAdded(TableCell cell) { cell.setMarginWidth(0); cell.setMarginHeight(0); } public void refresh(TableCell cell) { if (tracker_host == null) { try { tracker_host = AzureusCoreFactory.getSingleton().getTrackerHost(); } catch (Throwable t) { } if (tracker_host == null) { return; } } DownloadManager dm = (DownloadManager) cell.getDataSource(); int health; TRHostTorrent ht; if (dm == null) { health = 0; ht = null; } else { health = dm.getHealthStatus(); ht = tracker_host.getHostTorrent(dm.getTorrent()); } if (!cell.setSortValue(health + (ht == null ? 0 : 256)) && cell.isValid()) return; String sHelpID = null; if (health == DownloadManager.WEALTH_KO) { sHelpID = "health.explain.red"; } else if (health == DownloadManager.WEALTH_OK) { sHelpID = "health.explain.green"; } else if (health == DownloadManager.WEALTH_NO_TRACKER) { sHelpID = "health.explain.blue"; } else if (health == DownloadManager.WEALTH_NO_REMOTE) { sHelpID = "health.explain.yellow"; } else if (health == DownloadManager.WEALTH_ERROR) { } else { sHelpID = "health.explain.grey"; } String sToolTip = (health == DownloadManager.WEALTH_ERROR && dm != null) ? dm.getErrorDetails() : MessageText.getString(sHelpID); if (ht != null) sToolTip += "\n" + MessageText.getString("health.explain.share"); cell.setToolTip(sToolTip); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT) public void cellPaint(GC gc, TableCellSWT cell) { Comparable sortValue = cell.getSortValue(); if (!(sortValue instanceof Long)) { return; } boolean isShare = false; long health = ((Long) sortValue).longValue(); if (health >= 256) { health -= 256; isShare = true; } String image_name; if (health == DownloadManager.WEALTH_KO) { image_name = "st_ko"; } else if (health == DownloadManager.WEALTH_OK) { image_name = "st_ok"; } else if (health == DownloadManager.WEALTH_NO_TRACKER) { image_name = "st_no_tracker"; } else if (health == DownloadManager.WEALTH_NO_REMOTE) { image_name = "st_no_remote"; } else if (health == DownloadManager.WEALTH_ERROR) { image_name = "st_error"; } else { image_name = "st_stopped"; } if (isShare) { image_name += "_shared"; } ImageLoader imageLoader = ImageLoader.getInstance(); Image img = imageLoader.getImage(image_name); try { Rectangle cellBounds = cell.getBounds(); if (img != null && !img.isDisposed()) { Rectangle imgBounds = img.getBounds(); gc.drawImage(img, cellBounds.x + ((cellBounds.width - imgBounds.width) / 2), cellBounds.y + ((cellBounds.height - imgBounds.height) / 2)); } } finally { imageLoader.releaseImage(image_name); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SecondsDownloadingItem.java0000644000175000017500000000462111135264370032376 0ustar adrianadrian/* * File : SecondsDownloadingItem.java * Created : 01 febv. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author TuxPaper * @since 2.0.8.5 */ public class SecondsDownloadingItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "secondsdownloading"; /** Default Constructor */ public SecondsDownloadingItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_TIME }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); long value = (dm == null) ? 0 : dm.getStats().getSecondsDownloading(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(TimeFormatter.format(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownItem.java0000644000175000017500000000467011135264366027532 0ustar adrianadrian/* * File : DownItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** bytes downloaded column * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class DownItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = DownloadTypeIncomplete.class; public static final String COLUMN_ID = "down"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, CAT_PROGRESS, CAT_BYTES }); } /** Default Constructor */ public DownItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); long value = (dm == null) ? 0 : dm.getStats().getTotalGoodDataBytesReceived(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatByteCountToKiBEtc(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeersItem.java0000644000175000017500000001132011135264366027667 0ustar adrianadrian/* * File : PeersItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** # of Peers * * A new object is created for each cell, so that we can listen to the * scrapes and update individually (and only when needed). * * Total connected peers are left to update on INTERVAL_LIVE, as they aren't * very expensive. It would probably be more expensive to hook the * peer listener and only refresh on peer added/removed, because that happens * frequently. * * @author Olivier * @author TuxPaper * 2004/Apr/17: modified to TableCellAdapter * 2005/Oct/13: Use listener to update total from scrape */ public class PeersItem extends CoreTableColumn implements TableCellAddedListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "peers"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SWARM }); } /** Default Constructor */ public PeersItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, 60, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void cellAdded(TableCell cell) { new Cell(cell); } private class Cell extends AbstractTrackerCell { long lTotalPeers = -1; /** * Initialize * * @param cell */ public Cell(TableCell cell) { super(cell); } public void scrapeResult(TRTrackerScraperResponse response) { if (checkScrapeResult(response)) { lTotalPeers = response.getPeers(); } } public void refresh(TableCell cell) { super.refresh(cell); long lConnectedPeers = 0; if (dm != null) { lConnectedPeers = dm.getNbPeers(); if (lTotalPeers == -1) { TRTrackerScraperResponse response = dm.getTrackerScrapeResponse(); if (response != null && response.isValid()) { lTotalPeers = response.getPeers(); } } } long totalPeers = lTotalPeers; if (totalPeers <= 0) { DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm != null) { totalPeers = dm.getActivationCount(); } } long value = lConnectedPeers * 10000000; if (totalPeers > 0) value = value + totalPeers; if (!cell.setSortValue(value) && cell.isValid()) return; String tmp = String.valueOf(lConnectedPeers); if (totalPeers != -1) tmp += " (" + totalPeers + ")"; cell.setText(tmp); } public void cellHover(TableCell cell) { super.cellHover(cell); long lConnectedPeers = 0; DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm != null) { lConnectedPeers = dm.getNbPeers(); } String sToolTip = lConnectedPeers + " " + MessageText.getString("GeneralView.label.connected") + "\n"; if (lTotalPeers != -1) { sToolTip += lTotalPeers + " " + MessageText.getString("GeneralView.label.in_swarm"); } else { TRTrackerScraperResponse response = dm.getTrackerScrapeResponse(); sToolTip += "?? " + MessageText.getString("GeneralView.label.in_swarm"); if (response != null) sToolTip += "(" + response.getStatusString() + ")"; } int activationCount = dm==null?0:dm.getActivationCount(); if (activationCount > 0) { sToolTip += "\n" + MessageText.getString("PeerColumn.activationCount", new String[] { "" + activationCount }); } cell.setToolTip(sToolTip); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SeedToPeerRatioItem.java0000644000175000017500000000654311135264366031622 0ustar adrianadrian/* * Created : 11 nov. 2004 * By : Alon Rohter * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; public class SeedToPeerRatioItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "seed_to_peer_ratio"; public SeedToPeerRatioItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SWARM, }); info.setProficiency(TableColumnInfo.PROFICIENCY_ADVANCED); } public void refresh(TableCell cell) { float ratio = -1; DownloadManager dm = (DownloadManager)cell.getDataSource(); if( dm != null ) { TRTrackerScraperResponse response = dm.getTrackerScrapeResponse(); int seeds; int peers; if( response != null && response.isValid() ) { seeds = Math.max( dm.getNbSeeds(), response.getSeeds() ); int trackerPeerCount = response.getPeers(); peers = dm.getNbPeers(); if (peers == 0 || trackerPeerCount > peers) { if (trackerPeerCount <= 0) { peers = dm.getActivationCount(); } else { peers = trackerPeerCount; } } } else { seeds = dm.getNbSeeds(); peers = dm.getNbPeers(); } if (peers < 0 || seeds < 0) { ratio = 0; } else { if (peers == 0) { if (seeds == 0) ratio = 0; else ratio = Float.POSITIVE_INFINITY; } else { ratio = (float)seeds / peers; } } } if( !cell.setSortValue( ratio ) && cell.isValid() ) { return; } if (ratio == -1) { cell.setText(""); } else if (ratio == 0) { cell.setText("??"); } else { cell.setText(DisplayFormatters.formatDecimal(ratio, 3)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerCellUtils.java0000644000175000017500000000565411135264366031223 0ustar adrianadrian/* * File : TrackerCellUtils.java * Created : Nov 24, 2005 * By : TuxPaper * * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.eclipse.swt.graphics.Color; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.core3.tracker.client.impl.bt.TRTrackerBTScraperResponseImpl; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; /** * @author TuxPaper * */ public class TrackerCellUtils { public static final Class DATASOURCE_TYPE = Download.class; public static void updateColor(TableCell cell, DownloadManager dm, boolean show_errors ) { if (dm == null || cell == null) return; if ( show_errors ){ if ( dm.isTrackerError()){ cell.setForegroundToErrorColor(); return; } } TRTrackerScraperResponse response = dm.getTrackerScrapeResponse(); if (response instanceof TRTrackerBTScraperResponseImpl) { boolean bMultiHashScrapes = ((TRTrackerBTScraperResponseImpl) response).getTrackerStatus().getSupportsMultipeHashScrapes(); Color color = (bMultiHashScrapes) ? null : Colors.grey; cell.setForeground(Utils.colorToIntArray(color)); }else{ cell.setForeground(Utils.colorToIntArray(null)); } } public static String getTooltipText(TableCell cell, DownloadManager dm, boolean show_errors ) { if (dm == null || cell == null) return null; if ( show_errors ){ if ( dm.isTrackerError()){ return( null ); } } String sToolTip = null; TRTrackerScraperResponse response = dm.getTrackerScrapeResponse(); if (response instanceof TRTrackerBTScraperResponseImpl) { String sPrefix = ((TRTrackerBTScraperResponseImpl) response).getTrackerStatus().getSupportsMultipeHashScrapes() ? "" : "No"; sToolTip = MessageText.getString("Tracker.tooltip." + sPrefix + "MultiSupport"); } return sToolTip; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/StatusItem.java0000644000175000017500000001173111214107656030076 0ustar adrianadrian/* * File : StatusItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.*; /** * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class StatusItem extends CoreTableColumn implements TableCellRefreshListener, TableCellMouseListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "status"; private final static Object CLICK_KEY = new Object(); private static final int[] BLUE = Utils.colorToIntArray( Colors.blue ); private boolean changeRowFG; private boolean changeCellFG = true; private boolean showTrackerErrors; public StatusItem(String sTableID, boolean changeRowFG) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 80, sTableID); this.changeRowFG = changeRowFG; setRefreshInterval(INTERVAL_LIVE); } public StatusItem(String sTableID) { this(sTableID, true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_ESSENTIAL, }); } public void refresh( TableCell cell ) { DownloadManager dm = (DownloadManager) cell.getDataSource(); if ( dm == null ){ return; } int state = dm.getState(); String text; if ( showTrackerErrors && dm.isUnauthorisedOnTracker() && state != DownloadManager.STATE_ERROR ){ text = dm.getTrackerStatus(); }else{ text = DisplayFormatters.formatDownloadStatus(dm); } if ( cell.setText( text ) || !cell.isValid()) { boolean clickable = false; if ( cell instanceof TableCellSWT ){ int cursor_id; if ( text.indexOf( "http://" ) == -1 ){ dm.setUserData( CLICK_KEY, null ); cursor_id = SWT.CURSOR_ARROW; }else{ dm.setUserData( CLICK_KEY, text ); cursor_id = SWT.CURSOR_HAND; clickable = true; } ((TableCellSWT)cell).setCursorID( cursor_id ); } if (!changeCellFG && !changeRowFG){ // clickable, make it blue whatever cell.setForeground( clickable?BLUE:null); return; } TableRow row = cell.getTableRow(); if (row != null ) { Color color = null; if (state == DownloadManager.STATE_SEEDING) { color = Colors.blues[Colors.BLUES_MIDDARK]; } else if (state == DownloadManager.STATE_ERROR) { color = Colors.colorError; } else { color = null; } if (changeRowFG) { row.setForeground(Utils.colorToIntArray(color)); } else if (changeCellFG) { cell.setForeground(Utils.colorToIntArray(color)); } if ( clickable ){ cell.setForeground( Utils.colorToIntArray( Colors.blue )); } } } } public boolean isChangeRowFG() { return changeRowFG; } public void setChangeRowFG(boolean changeRowFG) { this.changeRowFG = changeRowFG; } public boolean isChangeCellFG() { return changeCellFG; } public void setChangeCellFG(boolean changeCellFG) { this.changeCellFG = changeCellFG; } public void setShowTrackerErrors( boolean s ) { showTrackerErrors = s; } public void cellMouseTrigger( TableCellMouseEvent event ) { DownloadManager dm = (DownloadManager) event.cell.getDataSource(); if (dm == null) {return;} String clickable = (String)dm.getUserData( CLICK_KEY ); if ( clickable == null ){ return; } event.skipCoreFunctionality = true; if ( event.eventType == TableCellMouseEvent.EVENT_MOUSEUP ){ String url = UrlUtils.getURL( clickable ); if ( url != null ){ Utils.launch( url ); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CompletedItem.java0000644000175000017500000000443111135264366030532 0ustar adrianadrian/** * Copyright (C) 2008 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros 8 Allee Lenotre, La Grille Royale, * 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * @author Aaron Grunthal * @create 11.02.2008 */ public class CompletedItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "completed"; /** Default Constructor */ public CompletedItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 50, sTableID); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROGRESS, }); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm == null) return; TRTrackerScraperResponse resp = dm.getTrackerScrapeResponse(); if (resp == null) return; int completed = resp.getCompleted(); if(cell.setSortValue(completed) || !cell.isValid()) cell.setText(completed == -1 ? "?" : Integer.toString(completed)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SavePathItem.java0000644000175000017500000000457211135264366030337 0ustar adrianadrian/* * File : SavePathItem.java * Created : 01 febv. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; public class SavePathItem extends CoreTableColumn implements TableCellRefreshListener, ObfusticateCellText { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "savepath"; /** Default Constructor */ public SavePathItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 150, sTableID); setObfustication(true); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); cell.setText((dm == null) ? "" : dm.getSaveLocation().toString()); } public String getObfusticatedText(TableCell cell) { return Debug.secretFileName(cell.getText()); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TimeSinceUploadItem.java0000644000175000017500000000507311135264366031646 0ustar adrianadrian/* * File : SecondsDownloadingItem.java * Created : 01 febv. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author TuxPaper * @since 2.0.8.5 */ public class TimeSinceUploadItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "timesinceupload"; /** Default Constructor */ public TimeSinceUploadItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_TIME }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); int value = (dm == null) ? -2 : dm.getStats().getTimeSinceLastDataSentInSeconds(); if (!cell.setSortValue(value==-1?Integer.MAX_VALUE:value) && cell.isValid()) return; cell.setText(value==-2?"":(value==-1?Constants.INFINITY_STRING:TimeFormatter.format(value))); //cell.setText("" + value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/RemainingItem.java0000644000175000017500000000533411135264370030525 0ustar adrianadrian/* * File : NameItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class RemainingItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = DownloadTypeIncomplete.class; public static final String COLUMN_ID = "remaining"; /** Default Constructor */ public RemainingItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, CAT_PROGRESS }); } private boolean bLastValueEstimate = false; public void refresh(TableCell cell) { long lRemaining = getRemaining(cell); if( !cell.setSortValue( lRemaining ) && cell.isValid() ) { return; } if (bLastValueEstimate) { cell.setText("~ " + DisplayFormatters.formatByteCountToKiBEtc(lRemaining)); } else { cell.setText(DisplayFormatters.formatByteCountToKiBEtc(lRemaining)); } } private long getRemaining(TableCell cell) { DownloadManager manager = (DownloadManager)cell.getDataSource(); if (manager == null) return 0; return( manager.getStats().getRemaining()); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentItem.java0000644000175000017500000000556011135264370030217 0ustar adrianadrian/* * File : CommentItem.java * Created : 26 Oct 2006 * By : Allan Crooks * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.ui.swt.TorrentUtil; import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.*; /** * User-editable comment for a download. * * @author amc1 */ public class CommentItem extends CoreTableColumn implements TableCellRefreshListener, TableCellMouseListener, ObfusticateCellText { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "comment"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT }); } /** Default Constructor */ public CommentItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 300, sTableID); setRefreshInterval(INTERVAL_LIVE); setType(TableColumn.TYPE_TEXT); setObfustication(true); setMinWidth(50); } public void refresh(TableCell cell) { String comment = null; DownloadManager dm = (DownloadManager)cell.getDataSource(); comment = dm.getDownloadState().getUserComment(); if (comment != null) { comment = comment.replace('\r', ' ').replace('\n', ' '); } cell.setText((comment == null) ? "" : comment); } public void cellMouseTrigger(TableCellMouseEvent event) { DownloadManager dm = (DownloadManager) event.cell.getDataSource(); if (dm == null) {return;} event.skipCoreFunctionality = true; if (event.eventType != TableCellMouseEvent.EVENT_MOUSEDOUBLECLICK) {return;} TorrentUtil.promptUserForComment(new DownloadManager[] {dm}); } public String getObfusticatedText(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); return Integer.toHexString(dm.hashCode()); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerStatusItem.java0000644000175000017500000001034311135264366031414 0ustar adrianadrian/* * File : TrackerStatusItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.eclipse.swt.SWT; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.util.AZ3Functions; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author Olivier * */ public class TrackerStatusItem extends CoreTableColumn implements TableCellAddedListener, TableCellToolTipListener, TableCellMouseMoveListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "tracker"; public TrackerStatusItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 90, sTableID); setRefreshInterval(15); // Slow update while no responses from tracker } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_TRACKER, }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } public void cellAdded(TableCell cell) { new Cell(cell); } public void cellMouseTrigger( TableCellMouseEvent event ) { Object ds = event.cell.getDataSource(); if ( !( ds instanceof DownloadManager )){ return; } DownloadManager dm = (DownloadManager)ds; AZ3Functions.provider az3 = AZ3Functions.getProvider(); if ( az3 == null || !az3.canShowCDP( dm )){ return; } if ( !(event.cell instanceof TableCellSWT )){ return; } TableCellSWT cell = (TableCellSWT)event.cell; boolean invalidateAndRefresh = false; int newCursor = dm.isUnauthorisedOnTracker()?SWT.CURSOR_HAND:SWT.CURSOR_ARROW; int oldCursor = cell.getCursorID(); if ( oldCursor != newCursor ){ invalidateAndRefresh = true; cell.setCursorID(newCursor); } if ( event.eventType == TableCellMouseEvent.EVENT_MOUSEUP ){ if ( newCursor == SWT.CURSOR_HAND ){ az3.showCDP( dm, "tracker.unauth" ); } } if ( invalidateAndRefresh ){ cell.invalidate(); cell.redraw(); } } private class Cell extends AbstractTrackerCell { public Cell(TableCell cell) { super(cell); } public void refresh(TableCell cell) { super.refresh(cell); String status = dm == null ? "" : dm.getTrackerStatus(); // status sometimes contains multiline text (e.g. HTML) on failure // - trim to end of first line break if present (see bug 1337563) int nl_pos = status.indexOf('\n'); if (nl_pos >= 0) status = status.substring(0, nl_pos); if (cell.setText(status) || !cell.isValid()) { TrackerCellUtils.updateColor(cell, dm, true); } } public void scrapeResult(TRTrackerScraperResponse response) { checkScrapeResult(response); } public void announceResult(TRTrackerAnnouncerResponse response) { cell.invalidate(); } } public void cellHover(TableCell cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); cell.setToolTip(TrackerCellUtils.getTooltipText(cell, dm, true)); } public void cellHoverComplete(TableCell cell) { cell.setToolTip(null); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AvailabilityItem.java0000644000175000017500000000616011135264366031231 0ustar adrianadrian/* * File : AvailabilityItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** Availability/"Seeing Copies" Column * * @author TuxPaper */ public class AvailabilityItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; // If you want more decimals, just add a zero private static final String zeros = "0000"; // # decimal places == numZeros - 1 private static final int numZeros = zeros.length(); public static final String COLUMN_ID = "availability"; private int iTimesBy; /** Default Constructor */ public AvailabilityItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 50, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); iTimesBy = 1; for (int i = 1; i < numZeros; i++) iTimesBy *= 10; } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SWARM, }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } public void refresh(TableCell cell) { String sText = ""; DownloadManager dm = (DownloadManager)cell.getDataSource(); if (dm == null) return; PEPeerManager pm = dm.getPeerManager(); if (pm != null) { float f = pm.getMinAvailability(); if (!cell.setSortValue((long)(f * 1000)) && cell.isValid()) return; sText = String.valueOf((int)(f * iTimesBy)); if (numZeros - sText.length() > 0) sText = zeros.substring(0, numZeros - sText.length()) + sText; sText = sText.substring(0, sText.length() - numZeros + 1) + "." + sText.substring(sText.length() - numZeros + 1); } else { cell.setSortValue(0); } cell.setText(sText); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TotalSpeedItem.java0000644000175000017500000000476211135264366030671 0ustar adrianadrian/* * File : TotalSpeedItem.java * Created : 1 feb. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** Total Speed of all peers cell for My Torrents * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class TotalSpeedItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "totalspeed"; /** Default Constructor */ public TotalSpeedItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SWARM, CAT_BYTES }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); long value = (dm == null) ? 0 : dm.getStats().getTotalAverage(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatByteCountToKiBEtcPerSec(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownSpeedLimitItem.java0000644000175000017500000000525711135264366031514 0ustar adrianadrian/* * Created on 17-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * @author parg * */ public class DownSpeedLimitItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = DownloadTypeIncomplete.class; public static final String COLUMN_ID = "maxdownspeed"; /** Default Constructor */ public DownSpeedLimitItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 35, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SETTINGS, }); info.setProficiency(TableColumnInfo.PROFICIENCY_ADVANCED); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); long value = (dm == null) ? 0 : dm.getStats().getDownloadRateLimitBytesPerSecond(); if (!cell.setSortValue(value) && cell.isValid()) return; if(value == -1) { cell.setText(MessageText.getString("MyTorrents.items.DownSpeedLimit.disabled")); } else if(value == 0) { cell.setText(Constants.INFINITY_STRING); } else { cell.setText(DisplayFormatters.formatByteCountToKiBEtcPerSec(value)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateCompletedItem.java0000644000175000017500000000672411135264366031337 0ustar adrianadrian/* * Created on 05-May-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator; import org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer; import org.gudy.azureus2.plugins.download.DownloadTypeComplete; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; public class DateCompletedItem extends ColumnDateSizer { public static final Class DATASOURCE_TYPE = DownloadTypeComplete.class; public static final String COLUMN_ID = "DateCompleted"; private static final long SHOW_ETA_AFTER_MS = 30000; public DateCompletedItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, TableColumnCreator.DATE_COLUMN_WIDTH, sTableID); setMultiline(false); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_TIME, CAT_CONTENT, }); } /** * @param tableID * @param b */ public DateCompletedItem(String tableID, boolean v) { this(tableID); setVisible(v); } public void refresh(TableCell cell, long timestamp) { DownloadManager dm = (DownloadManager) cell.getDataSource(); long value = 0; if (dm == null) { return; } if (dm.isDownloadComplete(false)) { long completedTime = dm.getDownloadState().getLongParameter( DownloadManagerState.PARAM_DOWNLOAD_COMPLETED_TIME); if (completedTime <= 0) { value = dm.getDownloadState().getLongParameter( DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME); } else { value = completedTime; } } else { long diff = SystemTime.getCurrentTime() - dm.getStats().getTimeStarted(); if (diff > SHOW_ETA_AFTER_MS) { long eta = dm.getStats().getETA(); if (eta > 0) { String sETA = TimeFormatter.format(eta); value = eta << 42; if (value < 0) { value = Long.MAX_VALUE; } cell.setText(MessageText.getString( "MyTorrents.column.ColumnProgressETA.2ndLine", new String[] { sETA })); } else { cell.setText(""); // make above value = SystemTime.getCurrentTime() / 1000 * 1001; } } else { cell.setText(""); value = SystemTime.getCurrentTime() / 1000 * 1002; } cell.invalidate(); cell.setSortValue(value); return; } super.refresh(cell, value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SeedsItem.java0000644000175000017500000001402411135264366027660 0ustar adrianadrian/* * File : SeedsItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier
    * @author TuxPaper 2004/Apr/17: modified to TableCellAdapter
    * @author TuxPaper 2005/Oct/13: Full Copy text & Scrape listener */ public class SeedsItem extends CoreTableColumn implements TableCellAddedListener, ParameterListener { public static final Class DATASOURCE_TYPE = Download.class; private static final String CFG_FC_SEEDSTART = "StartStopManager_iFakeFullCopySeedStart"; private static final String CFG_FC_NUMPEERS = "StartStopManager_iNumPeersAsFullCopy"; public static final String COLUMN_ID = "seeds"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SWARM }); } // don't count x peers as a full copy if seeds below private int iFC_MinSeeds; // count x peers as a full copy, but.. private int iFC_NumPeers; /** Default Constructor */ public SeedsItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, 60, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); iFC_MinSeeds = COConfigurationManager.getIntParameter(CFG_FC_SEEDSTART); iFC_NumPeers = COConfigurationManager.getIntParameter(CFG_FC_NUMPEERS); COConfigurationManager.addParameterListener(CFG_FC_SEEDSTART, this); COConfigurationManager.addParameterListener(CFG_FC_NUMPEERS, this); } protected void finalize() throws Throwable { super.finalize(); COConfigurationManager.removeParameterListener(CFG_FC_SEEDSTART, this); COConfigurationManager.removeParameterListener(CFG_FC_NUMPEERS, this); } public void cellAdded(TableCell cell) { new Cell(cell); } public void parameterChanged(String parameterName) { iFC_MinSeeds = COConfigurationManager.getIntParameter(CFG_FC_SEEDSTART); iFC_NumPeers = COConfigurationManager.getIntParameter(CFG_FC_NUMPEERS); } private class Cell extends AbstractTrackerCell { private long lTotalPeers = 0; private long lTotalSeeds = -1; /** * Initialize * * @param cell */ public Cell(TableCell cell) { super(cell); } public void scrapeResult(final TRTrackerScraperResponse response) { if (checkScrapeResult(response)) { lTotalSeeds = response.getSeeds(); lTotalPeers = response.getPeers(); } } public void refresh(TableCell cell) { super.refresh(cell); long lConnectedSeeds = 0; if (dm != null) { lConnectedSeeds = dm.getNbSeeds(); if (lTotalSeeds == -1) { TRTrackerScraperResponse response = dm.getTrackerScrapeResponse(); if (response != null && response.isValid()) { lTotalSeeds = response.getSeeds(); lTotalPeers = response.getPeers(); } } } // Allows for 2097151 of each type (connected seeds, seeds, peers) long value = (lConnectedSeeds << 42); if (lTotalSeeds > 0) value += (lTotalSeeds << 21); if (lTotalPeers > 0) value += lTotalPeers; if (!cell.setSortValue(value) && cell.isValid()) return; boolean bCompleteTorrent = dm == null ? false : dm.getAssumedComplete(); String tmp = String.valueOf(lConnectedSeeds); if (lTotalSeeds != -1) { tmp += " (" + lTotalSeeds; if (bCompleteTorrent && iFC_NumPeers > 0 && lTotalSeeds >= iFC_MinSeeds && lTotalPeers > 0) { long lSeedsToAdd = lTotalPeers / iFC_NumPeers; if (lSeedsToAdd > 0) tmp += "+" + lSeedsToAdd; } tmp += ")"; } cell.setText(tmp); } public void cellHover(TableCell cell) { super.cellHover(cell); long lConnectedSeeds = 0; DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm != null) { lConnectedSeeds = dm.getNbSeeds(); } String sToolTip = lConnectedSeeds + " " + MessageText.getString("GeneralView.label.connected") + "\n"; if (lTotalSeeds != -1) { sToolTip += lTotalSeeds + " " + MessageText.getString("GeneralView.label.in_swarm"); } else { TRTrackerScraperResponse response = dm.getTrackerScrapeResponse(); sToolTip += "?? " + MessageText.getString("GeneralView.label.in_swarm"); if (response != null) sToolTip += "(" + response.getStatusString() + ")"; } boolean bCompleteTorrent = dm == null ? false : dm.getAssumedComplete(); if (bCompleteTorrent && iFC_NumPeers > 0 && lTotalSeeds >= iFC_MinSeeds && lTotalPeers > 0) { long lSeedsToAdd = lTotalPeers / iFC_NumPeers; sToolTip += "\n" + MessageText.getString("MyTorrentsView.seeds.fullcopycalc", new String[] { "" + lTotalPeers, "" + lSeedsToAdd }); } cell.setToolTip(sToolTip); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SecondsSeedingItem.java0000644000175000017500000000473411135264366031521 0ustar adrianadrian/* * File : SecondsSeedingItem.java * Created : 01 feb. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author TuxPaper * @since 2.0.8.5 */ public class SecondsSeedingItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "secondsseeding"; /** Default Constructor */ public SecondsSeedingItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SHARING, CAT_TIME, }); info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); long value = (dm == null) ? 0 : dm.getStats().getSecondsDownloading() + dm.getStats().getSecondsOnlySeeding(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(TimeFormatter.format(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ShareRatioItem.java0000644000175000017500000000744111222067160030651 0ustar adrianadrian/* * File : ShareRatioItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.eclipse.swt.graphics.Color; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.*; /** * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class ShareRatioItem extends CoreTableColumn implements TableCellRefreshListener, ParameterListener { public static final Class DATASOURCE_TYPE = Download.class; private final static String CONFIG_ID = "StartStopManager_iFirstPriority_ShareRatio"; public static final String COLUMN_ID = "shareRatio"; private int iMinShareRatio; private boolean changeFG = true; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SHARING, CAT_SWARM }); } /** Default Constructor */ public ShareRatioItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setType(TableColumn.TYPE_TEXT); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); setPosition(POSITION_LAST); iMinShareRatio = COConfigurationManager.getIntParameter(CONFIG_ID); COConfigurationManager.addParameterListener(CONFIG_ID, this); } protected void finalize() throws Throwable { super.finalize(); COConfigurationManager.removeParameterListener(CONFIG_ID, this); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager)cell.getDataSource(); int sr = (dm == null) ? 0 : dm.getStats().getShareRatio(); if ( sr == Integer.MAX_VALUE ){ sr = Integer.MAX_VALUE-1; } if ( sr == -1 ){ sr = Integer.MAX_VALUE; } if (!cell.setSortValue(sr) && cell.isValid()) return; String shareRatio = ""; if (sr == Integer.MAX_VALUE ) { shareRatio = Constants.INFINITY_STRING; } else { shareRatio = DisplayFormatters.formatDecimal((double) sr / 1000, 3); } if( cell.setText(shareRatio) && changeFG ) { Color color = sr < iMinShareRatio ? Colors.colorWarning : null; cell.setForeground(Utils.colorToIntArray(color)); } } public void parameterChanged(String parameterName) { iMinShareRatio = COConfigurationManager.getIntParameter(CONFIG_ID); invalidateCells(); } public boolean isChangeFG() { return changeFG; } public void setChangeFG(boolean changeFG) { this.changeFG = changeFG; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SizeItem.java0000644000175000017500000000660211135264366027532 0ustar adrianadrian/* * File : SizeItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** Size of Torrent cell * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class SizeItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "size"; private static boolean DO_MULTILINE = true; /** Default Constructor */ public SizeItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID); setRefreshInterval(INTERVAL_GRAPHIC); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_ESSENTIAL, CAT_CONTENT, CAT_BYTES }); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); sizeitemsort value = (dm == null) ? new sizeitemsort(0, 0) : new sizeitemsort(dm.getSize(), dm.getStats().getRemaining()); // cell.setSortValue(value) always returns true and if I change it, // I'm afraid something will break.. so use compareTo if (value.compareTo(cell.getSortValue()) == 0 && cell.isValid()) return; cell.setSortValue(value); String s = DisplayFormatters.formatByteCountToKiBEtc(value.size); if (DO_MULTILINE && cell.getMaxLines() > 1 && value.remaining > 0) { s += "\n" + DisplayFormatters.formatByteCountToKiBEtc(value.remaining, false, false, 0) + " to go"; } cell.setText(s); } private class sizeitemsort implements Comparable { private final long size; private final long remaining; public sizeitemsort(long size, long remaining) { this.size = size; this.remaining = remaining; } public int compareTo(Object arg0) { if (!(arg0 instanceof sizeitemsort)) { return 1; } sizeitemsort otherObj = (sizeitemsort) arg0; if (size == otherObj.size) { return remaining == otherObj.remaining ? 0 : remaining > otherObj.remaining ? 1 : -1; } return size > otherObj.size ? 1 : -1; } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CategoryItem.java0000644000175000017500000000447711135264370030400 0ustar adrianadrian/* * File : CategoryItem.java * Created : 01 feb. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.category.Category; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** Display Category torrent belongs to. * * @author TuxPaper */ public class CategoryItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "category"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT }); } /** Default Constructor */ public CategoryItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 70, sTableID); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { String sCategory = null; DownloadManager dm = (DownloadManager)cell.getDataSource(); if (dm != null) { Category cat = dm.getDownloadState().getCategory(); if (cat != null) sCategory = cat.getName(); } cell.setText((sCategory == null) ? "" : sCategory); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownSpeedItem.java0000644000175000017500000000740711135264366030514 0ustar adrianadrian/* * File : DownSpeedItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.eclipse.swt.graphics.Color; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.plugins.startstoprules.defaultplugin.DefaultRankCalculator; import com.aelitis.azureus.plugins.startstoprules.defaultplugin.StartStopRulesDefaultPlugin; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.tables.*; /** Download Speed column * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class DownSpeedItem extends CoreTableColumn implements TableCellAddedListener { public static final Class DATASOURCE_TYPE = DownloadTypeIncomplete.class; public static final String COLUMN_ID = "downspeed"; /** Default Constructor */ public DownSpeedItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 60, sTableID); setType(TableColumn.TYPE_TEXT); setRefreshInterval(INTERVAL_LIVE); setUseCoreDataSource(false); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_ESSENTIAL, CAT_BYTES, }); } public void cellAdded(TableCell cell) { cell.addRefreshListener(new RefreshListener()); } public class RefreshListener implements TableCellRefreshListener { private int iLastState; private int loop = 0; public void refresh(TableCell cell) { Download dm = (Download)cell.getDataSource(); long value; int iState; if (dm == null) { iState = -1; value = 0; } else { iState = dm.getState(); value = dm.getStats().getDownloadAverage(); } boolean bChangeColor = (++loop % 10) == 0; if (cell.setSortValue(value) || !cell.isValid() || (iState != iLastState)) { cell.setText(DisplayFormatters.formatByteCountToKiBEtcPerSec(value)); bChangeColor = true; } if (bChangeColor) { changeColor(cell, dm, iState); loop = 0; } } private void changeColor(TableCell cell, Download dl, int iState) { try { DefaultRankCalculator calc = StartStopRulesDefaultPlugin.getRankCalculator(dl); Color newFG = null; if (calc != null && dl.getState() == Download.ST_DOWNLOADING && !calc.getActivelyDownloading()) newFG = Colors.colorWarning; cell.setForeground(Utils.colorToIntArray(newFG)); iLastState = iState; } catch (Exception e) { Debug.printStackTrace( e ); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CompletionItem.java0000644000175000017500000001575711135264370030737 0ustar adrianadrian/* * File : CompletionItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.utils.ColorCache; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.Graphic; import org.gudy.azureus2.plugins.ui.tables.*; /** Torrent Completion Level Graphic Cell for My Torrents. * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class CompletionItem extends CoreTableColumn implements TableCellAddedListener, TableCellRefreshListener, TableCellDisposeListener, TableCellSWTPaintListener { public static final Class DATASOURCE_TYPE = DownloadTypeIncomplete.class; private static final int borderWidth = 1; public static final String COLUMN_ID = "completion"; private static Font fontText; private Map mapCellLastPercentDone = new HashMap(); private int marginHeight = -1; Color textColor; /** Default Constructor */ public CompletionItem(String sTableID) { this(sTableID, -1); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROGRESS, }); } /** * * @param sTableID * @param marginHeight -- Margin height above and below the progress bar; used in cases where the row is very tall */ public CompletionItem(String sTableID, int marginHeight) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 150, sTableID); this.marginHeight = marginHeight; initializeAsGraphic(POSITION_INVISIBLE, 150); setMinWidth(100); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellAdded(TableCell cell) { if (marginHeight != -1) { cell.setMarginHeight(marginHeight); } else { cell.setMarginHeight(2); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellDisposeListener#dispose(org.gudy.azureus2.plugins.ui.tables.TableCell) public void dispose(TableCell cell) { mapCellLastPercentDone.remove(cell); Graphic graphic = cell.getGraphic(); if (graphic instanceof UISWTGraphic) { Image img = ((UISWTGraphic) graphic).getImage(); if (img != null && !img.isDisposed()) { img.dispose(); } } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { int percentDone = getPercentDone(cell); Integer intObj = (Integer) mapCellLastPercentDone.get(cell); int lastPercentDone = intObj == null ? 0 : intObj.intValue(); if (!cell.setSortValue(percentDone) && cell.isValid() && lastPercentDone == percentDone) { return; } } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT) public void cellPaint(GC gcImage, TableCellSWT cell) { int percentDone = getPercentDone(cell); Rectangle bounds = cell.getBounds(); int yOfs = (bounds.height - 13) / 2 ; int x1 = bounds.width - borderWidth - 2; int y1 = bounds.height - 3 - yOfs; if (x1 < 10 || y1 < 3) { return; } int textYofs = 0; if (y1 >= 28) { yOfs = 2; y1 = 16; //textYofs = yOfs; } mapCellLastPercentDone.put(cell, new Integer(percentDone)); ImageLoader imageLoader = ImageLoader.getInstance(); Image imgEnd = imageLoader.getImage("dl_bar_end"); Image img0 = imageLoader.getImage("dl_bar_0"); Image img1 = imageLoader.getImage("dl_bar_1"); //draw begining and end if (!imgEnd.isDisposed()) { gcImage.drawImage(imgEnd, bounds.x , bounds.y + yOfs); gcImage.drawImage(imgEnd, bounds.x + x1 + 1, bounds.y + yOfs); } // draw border // Color fg = gcImage.getForeground(); // gcImage.setForeground(Colors.grey); // gcImage.drawRectangle(bounds.x, bounds.y + yOfs, x1 + 1, y1 + 1); // gcImage.setForeground(fg); int limit = (x1 * percentDone) / 1000; if (!img1.isDisposed() && limit > 0) { Rectangle imgBounds = img1.getBounds(); gcImage.drawImage(img1, 0, 0, imgBounds.width, imgBounds.height, bounds.x + 1, bounds.y + yOfs, limit, imgBounds.height); } if (percentDone < 1000 && !img0.isDisposed()) { Rectangle imgBounds = img0.getBounds(); gcImage.drawImage(img0, 0, 0, imgBounds.width, imgBounds.height, bounds.x + limit + 1, bounds.y + yOfs, x1 - limit, imgBounds.height); } imageLoader.releaseImage("dl_bar_end"); imageLoader.releaseImage("dl_bar_0"); imageLoader.releaseImage("dl_bar_1"); // gcImage.setBackground(Colors.blues[Colors.BLUES_DARKEST]); // gcImage.fillRectangle(bounds.x + 1, bounds.y + 1 + yOfs, limit, y1); // if (limit < x1) { // gcImage.setBackground(Colors.blues[Colors.BLUES_LIGHTEST]); // gcImage.fillRectangle(bounds.x + limit + 1, bounds.y + 1 + yOfs, x1 // - limit, y1); // } if(textColor == null) { textColor = ColorCache.getColor(gcImage.getDevice(), "#005ACF" ); } // if (textYofs == 0) { // if (fontText == null) { // fontText = Utils.getFontWithHeight(gcImage.getFont(), gcImage, y1); // } // gcImage.setFont(fontText); gcImage.setForeground(textColor); // } String sPercent = DisplayFormatters.formatPercentFromThousands(percentDone); GCStringPrinter.printString(gcImage, sPercent, new Rectangle(bounds.x + 4, bounds.y + yOfs, bounds.width - 4,13), true, false, SWT.CENTER); } private int getPercentDone(TableCell cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm == null) { return 0; } return dm.getStats().getDownloadCompleted(true); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeerSourcesItem.java0000644000175000017500000000455211135264370031054 0ustar adrianadrian/* * File : CategoryItem.java * Created : 01 feb. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** Display Category torrent belongs to. * * @author TuxPaper */ public class PeerSourcesItem extends CoreTableColumn implements TableCellRefreshListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "peersources"; /** Default Constructor */ public PeerSourcesItem(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 70, sTableID); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SWARM, }); info.setProficiency(TableColumnInfo.PROFICIENCY_ADVANCED); } public void refresh(TableCell cell) { String ps = ""; DownloadManager dm = (DownloadManager)cell.getDataSource(); if (dm != null) { String[] nets = dm.getDownloadState().getPeerSources(); for (int i=0;i nbPieces && nbPieces != 0) a1 = nbPieces; int nbAvailable = 0; boolean written = false; boolean partially_written = false; if (firstPiece >= 0) for (int j = a0; j < a1; j++) { final int this_index = j + firstPiece; final DiskManagerPiece dm_piece = dm_pieces[this_index]; if (dm_piece.isDone()) nbAvailable++; if (written) continue; if (pe_pieces != null) { PEPiece pe_piece = pe_pieces[this_index]; if (pe_piece != null) written = written || (pe_piece.getLastDownloadTime(now) + 500) > last_draw_time; } if ((!written) && (!partially_written)) { final boolean[] blocks = dm_piece.getWritten(); if (blocks != null) for (int k = 0; k < blocks.length; k++) if (blocks[k]) { partially_written = true; break; } } } // for j else nbAvailable = 1; gcImage.setBackground(written ? Colors.red : partially_written ? Colors.grey : Colors.blues[(nbAvailable * Colors.BLUES_DARKEST) / (a1 - a0)]); gcImage.fillRectangle(i, 1, 1, newHeight - 2); if (written) bNoRed = false; } gcImage.setForeground(Colors.grey); } } else gcImage.setForeground(Colors.grey); if (manager != null) gcImage.drawRectangle(0, 0, newWidth - 1, newHeight - 1); gcImage.dispose(); last_draw_time = now; if (cell instanceof TableCellSWT) ((TableCellSWT) cell).setGraphic(piecesImage); else cell.setGraphic(new UISWTGraphicImpl(piecesImage)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/files/PieceCountItem.java0000644000175000017500000000361611135264370027527 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.files; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class PieceCountItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PieceCountItem() { super("numberofpieces", ALIGN_TRAIL, POSITION_LAST, 75, TableManager.TABLE_TORRENT_FILES); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, }); } public void refresh(TableCell cell) { DiskManagerFileInfo fileInfo = (DiskManagerFileInfo)cell.getDataSource(); long value = (fileInfo == null) ? 0 : fileInfo.getNbPieces(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } // < 0 -> unknown skeleton value cell.setText( value<0?"":(""+value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/files/DoneItem.java0000644000175000017500000000403611135264370026353 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.files; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** bytes done * * @author TuxPaper * @since 2.0.8.5 */ public class DoneItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public DoneItem() { super("done", ALIGN_TRAIL, POSITION_LAST, 70, TableManager.TABLE_TORRENT_FILES); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, CAT_PROGRESS, }); } public void refresh(TableCell cell) { DiskManagerFileInfo fileInfo = (DiskManagerFileInfo)cell.getDataSource(); long value = (fileInfo == null) ? 0 : fileInfo.getDownloaded(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } // value < 0 -> unknown skeleton value cell.setText(value<0?"":DisplayFormatters.formatByteCountToKiBEtc(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/files/FirstPieceItem.java0000644000175000017500000000420611270776772027540 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.files; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** File's First Piece # * * @author TuxPaper * @since 2.0.8.5 */ public class FirstPieceItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public FirstPieceItem() { super("firstpiece", ALIGN_TRAIL, POSITION_LAST, 75, TableManager.TABLE_TORRENT_FILES); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROTOCOL, }); } public void refresh(TableCell cell) { DiskManagerFileInfo fileInfo = (DiskManagerFileInfo)cell.getDataSource(); long sort_value; if ( fileInfo == null ){ sort_value = 0; }else{ sort_value = fileInfo.getFirstPieceNumber(); if ( sort_value >= 0 ){ sort_value = (sort_value << 32) + fileInfo.getIndex(); } } if( !cell.setSortValue( sort_value ) && cell.isValid() ) { return; } // < 0 -> unknown skeleton value cell.setText( sort_value<0?"":(""+fileInfo.getFirstPieceNumber())); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/files/PercentItem.java0000644000175000017500000000444111264271716027073 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.files; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class PercentItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PercentItem() { super("%", ALIGN_TRAIL, POSITION_LAST, 60, TableManager.TABLE_TORRENT_FILES); setRefreshInterval(INTERVAL_LIVE); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROGRESS, }); } public void refresh(TableCell cell) { DiskManagerFileInfo fileInfo = (DiskManagerFileInfo)cell.getDataSource(); long percent = 0; if (fileInfo != null ){ long bytesDownloaded = fileInfo.getDownloaded(); if ( bytesDownloaded < 0 ){ percent = -1; // unknown skeleton value }else if ( fileInfo.getLength() != 0 ){ percent = (1000 * bytesDownloaded) / fileInfo.getLength(); } }else{ percent = -1; // unknown skeleton value } if( !cell.setSortValue( percent ) && cell.isValid() ) { return; } cell.setText( percent < 0?"":DisplayFormatters.formatPercentFromThousands((int)percent)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/files/FileExtensionItem.java0000644000175000017500000000370311135264370030242 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.files; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; public class FileExtensionItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public FileExtensionItem() { super("fileext", ALIGN_LEAD, POSITION_INVISIBLE, 50, TableManager.TABLE_TORRENT_FILES); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, }); } public void refresh(TableCell cell) { DiskManagerFileInfo fileInfo = (DiskManagerFileInfo)cell.getDataSource(); cell.setText(determineFileExt(fileInfo)); } private static String determineFileExt(DiskManagerFileInfo fileInfo) { String name = (fileInfo == null) ? "" : fileInfo.getFile(true).getName(); int dot_position = name.lastIndexOf("."); if (dot_position == -1) {return "";} return name.substring(dot_position+1); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/files/SizeItem.java0000644000175000017500000000364111135264370026401 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.files; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class SizeItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public SizeItem() { super("size", ALIGN_TRAIL, POSITION_LAST, 70, TableManager.TABLE_TORRENT_FILES); setMinWidthAuto(true); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, }); } public void refresh(TableCell cell) { DiskManagerFileInfo fileInfo = (DiskManagerFileInfo)cell.getDataSource(); long value = (fileInfo == null) ? 0 : fileInfo.getLength(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(DisplayFormatters.formatByteCountToKiBEtc(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/files/PathItem.java0000644000175000017500000000724111135264370026363 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.files; import java.io.File; import java.io.IOException; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.ui.swt.views.FilesView; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; public class PathItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PathItem() { super("path", ALIGN_LEAD, POSITION_LAST, 200, TableManager.TABLE_TORRENT_FILES); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, }); } public void refresh(TableCell cell) { DiskManagerFileInfo fileInfo = (DiskManagerFileInfo)cell.getDataSource(); cell.setText(determinePath(fileInfo)); } private static String determinePath(DiskManagerFileInfo fileInfo) { if( fileInfo == null ) { return ""; } boolean has_link = fileInfo.getLink() != null; boolean show_full_path = FilesView.show_full_path; DownloadManager dm = fileInfo.getDownloadManager(); File dl_save_path_file = dm.getAbsoluteSaveLocation(); TOTorrent torrent = dm.getTorrent(); if ( torrent != null && torrent.isSimpleTorrent()){ dl_save_path_file = dl_save_path_file.getParentFile(); } String dl_save_path = dl_save_path_file.getPath(); if (!dl_save_path.endsWith(File.separator)) { dl_save_path += File.separator; } File file = fileInfo.getFile(true); /** * Figure out whether we should show the full path anyway. * We'll do this if the path is relative to he current * download save path. */ // if (has_link && !show_full_path) { show_full_path = !file.getAbsolutePath().startsWith(dl_save_path); } String path = ""; if (show_full_path) { try { path = file.getParentFile().getCanonicalPath(); } catch( IOException e ) { path = file.getParentFile().getAbsolutePath(); } if ( !path.endsWith( File.separator )){ path += File.separator; } }else{ path = file.getAbsolutePath().substring(dl_save_path.length()); if (path.length() == 0) { path = File.separator; } else { if (path.charAt(0) == File.separatorChar) { path = path.substring(1); } int pos = path.lastIndexOf(File.separator); if (pos > 0 ) { path = File.separator + path.substring( 0, pos ); } else { path = File.separator; } } } return path; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/myshares/0000755000175000017500000000000011310377636024537 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/myshares/NameItem.java0000644000175000017500000000306110373051050027064 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.myshares; import org.gudy.azureus2.plugins.sharing.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class NameItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public NameItem() { super("name", POSITION_LAST, 400, TableManager.TABLE_MYSHARES); } public void refresh(TableCell cell) { ShareResource item = (ShareResource)cell.getDataSource(); if (item == null) cell.setText(""); else cell.setText(item.getName()); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/myshares/CategoryItem.java0000644000175000017500000000420010373051050027755 0ustar adrianadrian/* * Created on 10-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.myshares; import org.gudy.azureus2.plugins.sharing.ShareResource; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentManagerImpl; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * @author parg * */ public class CategoryItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ protected static final TorrentAttribute category_attribute = TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_CATEGORY ); public CategoryItem() { super("category", POSITION_LAST, 400, TableManager.TABLE_MYSHARES); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { ShareResource item = (ShareResource)cell.getDataSource(); if (item == null){ cell.setText(""); }else{ String value = item.getAttribute(category_attribute); cell.setText( value==null?"":value); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/myshares/TypeItem.java0000644000175000017500000000442210373051050027127 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.myshares; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.plugins.sharing.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class TypeItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public TypeItem() { super("type", POSITION_LAST, 100, TableManager.TABLE_MYSHARES); } public void refresh(TableCell cell) { ShareResource item = (ShareResource)cell.getDataSource(); String text = ""; if( item != null ) { int type = item.getType(); if( !cell.setSortValue( type ) && cell.isValid() ) { return; } if (type == ShareResource.ST_DIR) text = MessageText.getString( "MySharesView.type.dir" ); else if (type == ShareResource.ST_FILE) text = MessageText.getString( "MySharesView.type.file" ); else if (type == ShareResource.ST_DIR_CONTENTS) { ShareResourceDirContents s = (ShareResourceDirContents)item; if (s.isRecursive()) text = MessageText.getString( "MySharesView.type.dircontentsrecursive" ); else text = MessageText.getString( "MySharesView.type.dircontents" ); } } cell.setText( text ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/ColumnDateSizer.java0000644000175000017500000001632711276126554026632 0ustar adrianadrian/** * Created on Oct 5, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.views.tableitems; import java.text.SimpleDateFormat; import java.util.Date; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.menus.MenuItemListener; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem; /** * @author TuxPaper * @created Oct 5, 2008 * */ public abstract class ColumnDateSizer extends CoreTableColumn implements TableCellRefreshListener { private static int PADDING = 10; int curFormat = 0; int[] maxWidthUsed = new int[TimeFormatter.DATEFORMATS_DESC.length]; Date[] maxWidthDate = new Date[TimeFormatter.DATEFORMATS_DESC.length]; private boolean showTime = true; private boolean multiline = true; private static Font fontBold; /** * @param name * @param tableID */ public ColumnDateSizer(Class forDataSrouceType, String columnID, int width, String tableID) { super(forDataSrouceType, columnID, ALIGN_TRAIL, width, tableID); TableContextMenuItem menuShowTime = addContextMenuItem("TableColumn.menu.date_added.time"); menuShowTime.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { showTime = !showTime; setUserData("showTime", new Long(showTime ? 1 : 0)); maxWidthUsed = new int[TimeFormatter.DATEFORMATS_DESC.length]; maxWidthDate = new Date[TimeFormatter.DATEFORMATS_DESC.length]; curFormat = -1; recalcWidth(new Date()); if (curFormat < 0) { curFormat = TimeFormatter.DATEFORMATS_DESC.length - 1; } } }); } // @see com.aelitis.azureus.ui.common.table.impl.TableColumnImpl#postConfigLoad() public void postConfigLoad() { Object oShowTime = getUserData("showTime"); if (oShowTime instanceof Number) { Number nShowTime = (Number) oShowTime; showTime = nShowTime.byteValue() == 1; } else { int userMode = COConfigurationManager.getIntParameter("User Mode"); showTime = userMode > 1; } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public final void refresh(TableCell cell) { refresh(cell, 0); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell, long timestamp) { if (!cell.setSortValue(timestamp) && cell.isValid()) { return; } if (timestamp <= 0) { return; } Date date = new Date(timestamp); if (curFormat >= 0) { if (multiline && cell.getHeight() < 20) { multiline = false; } String suffix = showTime && !multiline ? " hh:mm a" : ""; int newWidth = calcWidth(date, TimeFormatter.DATEFORMATS_DESC[curFormat] + suffix); //SimpleDateFormat temp2 = new SimpleDateFormat(TimeFormatter.DATEFORMATS_DESC[curFormat] + suffix + (showTime && multiline ? "\nh:mm a" : "")); //System.out.println(curFormat + ":newWidth=" + newWidth + ":max=" + maxWidthUsed[curFormat] + ":cell=" + cell.getWidth() + "::" + temp2.format(date)); if (newWidth > cell.getWidth() - PADDING) { if (newWidth > maxWidthUsed[curFormat]) { maxWidthUsed[curFormat] = newWidth; maxWidthDate[curFormat] = date; } recalcWidth(date); } String s = TimeFormatter.DATEFORMATS_DESC[curFormat] + suffix; SimpleDateFormat temp = new SimpleDateFormat(s + (showTime && multiline ? "\nh:mm a" : "")); cell.setText(temp.format(date)); } } // @see com.aelitis.azureus.ui.common.table.impl.TableColumnImpl#setWidth(int) public void setWidth(int width) { int oldWidth = this.getWidth(); super.setWidth(width); if (oldWidth == width) { return; } if (maxWidthDate != null) { if (maxWidthDate[curFormat] == null) { maxWidthDate[curFormat] = new Date(); } recalcWidth(maxWidthDate[curFormat]); } } private void recalcWidth(Date date) { String suffix = showTime && !multiline ? " hh:mm a" : ""; int width = getWidth(); if (maxWidthDate == null) { maxWidthUsed = new int[TimeFormatter.DATEFORMATS_DESC.length]; maxWidthDate = new Date[TimeFormatter.DATEFORMATS_DESC.length]; } int idxFormat = TimeFormatter.DATEFORMATS_DESC.length - 1; GC gc = new GC(Display.getDefault()); if (fontBold == null) { FontData[] fontData = gc.getFont().getFontData(); for (int i = 0; i < fontData.length; i++) { FontData fd = fontData[i]; fd.setStyle(SWT.BOLD); } fontBold = new Font(gc.getDevice(), fontData); } gc.setFont(fontBold); try { Point minSize = new Point(99999, 0); for (int i = 0; i < TimeFormatter.DATEFORMATS_DESC.length; i++) { if (maxWidthUsed[i] > width - PADDING) { continue; } SimpleDateFormat temp = new SimpleDateFormat( TimeFormatter.DATEFORMATS_DESC[i] + suffix); Point newSize = gc.stringExtent(temp.format(date)); if (newSize.x < width - PADDING) { idxFormat = i; if (maxWidthUsed[i] < newSize.x) { maxWidthUsed[i] = newSize.x; maxWidthDate[i] = date; } break; } if (newSize.x < minSize.x) { minSize = newSize; idxFormat = i; } } } catch (Throwable t) { return; } finally { gc.dispose(); } if (curFormat != idxFormat) { //System.out.println("switch fmt to " + idxFormat + ", max=" + maxWidthUsed[idxFormat]); curFormat = idxFormat; invalidateCells(); } } private int calcWidth(Date date, String format) { GC gc = new GC(Display.getDefault()); if (fontBold == null) { FontData[] fontData = gc.getFont().getFontData(); for (int i = 0; i < fontData.length; i++) { FontData fd = fontData[i]; fd.setStyle(SWT.BOLD); } fontBold = new Font(gc.getDevice(), fontData); } gc.setFont(fontBold); SimpleDateFormat temp = new SimpleDateFormat(format); Point newSize = gc.stringExtent(temp.format(date)); gc.dispose(); return newSize.x; } public boolean getShowTime() { return showTime; } public void setShowTime(boolean showTime) { this.showTime = showTime; } /** * @return the multiline */ public boolean isMultiline() { return multiline; } /** * @param multiline the multiline to set */ public void setMultiline(boolean multiline) { this.multiline = multiline; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/0000755000175000017500000000000011310377640024147 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/WritersItem.java0000644000175000017500000000567711135264370027307 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.pieces; import java.util.*; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class WritersItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public WritersItem() { super("writers", ALIGN_LEAD, POSITION_INVISIBLE, 80, TableManager.TABLE_TORRENT_PIECES); setObfustication(true); setRefreshInterval(4); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SWARM, }); } public void refresh(TableCell cell) { PEPiece piece = (PEPiece)cell.getDataSource(); String[] core_writers = piece.getWriters(); String[] my_writers = new String[core_writers.length]; int writer_count = 0; Map map = new HashMap(); for(int i = 0 ; ; ) { String this_writer = null; int start; for (start = i ; start < core_writers.length ; start++ ) { this_writer = core_writers[start]; if (this_writer != null) break; } if (this_writer == null) break; int end; for (end = start + 1; end < core_writers.length; end++) { if (! this_writer.equals(core_writers[end])) break; } StringBuffer pieces = (StringBuffer) map.get(this_writer); if (pieces == null) { pieces = new StringBuffer(); map.put(this_writer, pieces); my_writers[writer_count++] = this_writer; } else { pieces.append(','); } pieces.append(start); if (end-1 > start) pieces.append('-').append(end-1); i=end; } StringBuffer sb = new StringBuffer(); for (int i = 0 ; i < writer_count ; i++) { String writer = my_writers[i]; StringBuffer pieces = (StringBuffer) map.get(writer); if (i > 0) sb.append(';'); sb.append(writer).append('[').append(pieces).append(']'); } String value = sb.toString(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(value); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/PriorityItem.java0000644000175000017500000000345511135264370027461 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.pieces; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author MjrTom * @since 2.3.0.7 */ public class PriorityItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PriorityItem() { super("priority", ALIGN_TRAIL, POSITION_LAST, 80, TableManager.TABLE_TORRENT_PIECES); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SETTINGS, }); } public void refresh(TableCell cell) { int value =0; final PEPiece piece = (PEPiece)cell.getDataSource(); if (piece !=null) { value =piece.getResumePriority(); if(!cell.setSortValue(value) &&cell.isValid()) { return; } } cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/PieceNumberItem.java0000644000175000017500000000322610373051022030021 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.pieces; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class PieceNumberItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PieceNumberItem() { super("#", ALIGN_TRAIL, POSITION_LAST, 50, TableManager.TABLE_TORRENT_PIECES); } public void refresh(TableCell cell) { PEPiece piece = (PEPiece)cell.getDataSource(); long value = (piece == null) ? 0 : piece.getPieceNumber(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/SpeedItem.java0000644000175000017500000000343011135264370026671 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.pieces; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author MjrTom * @since 2.3.0.7 */ public class SpeedItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public SpeedItem() { super("speed", ALIGN_TRAIL, POSITION_LAST, 80, TableManager.TABLE_TORRENT_PIECES); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, }); } public void refresh(TableCell cell) { PEPiece piece = (PEPiece)cell.getDataSource(); int value =0; if (null !=piece) { value =piece.getSpeed(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } } cell.setText("" +value); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/CompletedItem.java0000644000175000017500000000347011135264370027551 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.pieces; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class CompletedItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public CompletedItem() { super("completed", ALIGN_TRAIL, POSITION_LAST, 80, TableManager.TABLE_TORRENT_PIECES); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROGRESS, }); } public void refresh(TableCell cell) { PEPiece piece = (PEPiece)cell.getDataSource(); long value = (piece == null) ? 0 : piece.getNbWritten(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/RequestedItem.java0000644000175000017500000000401511135264370027572 0ustar adrianadrian/* * Created by Joseph Bridgewater * Created on Feb 05, 2006 * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.pieces; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * @author MjrTom * Shows if more requests can be made on the piece or not */ public class RequestedItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public RequestedItem() { super("Requested", ALIGN_CENTER, POSITION_INVISIBLE, 20, TableManager.TABLE_TORRENT_PIECES); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SWARM, }); } public void refresh(TableCell cell) { boolean value =false; final PEPiece pePiece =(PEPiece) cell.getDataSource(); if (pePiece !=null) { value = pePiece.isRequested(); } if (!cell.setSortValue(value ?1 :0) &&cell.isValid()) return; cell.setText(value?"*" :""); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/AvailabilityItem.java0000644000175000017500000000350111135264370030242 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.pieces; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class AvailabilityItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public AvailabilityItem() { super("availability", ALIGN_TRAIL, POSITION_LAST, 80, TableManager.TABLE_TORRENT_PIECES); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SWARM, }); } public void refresh(TableCell cell) { PEPiece piece = (PEPiece)cell.getDataSource(); long value = (piece == null) ? 0 : piece.getAvailability(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/BlocksItem.java0000644000175000017500000001525611135264370027057 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.pieces; import java.util.Arrays; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerFactory; import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerStats; import org.gudy.azureus2.plugins.ui.Graphic; import org.gudy.azureus2.plugins.ui.tables.*; /** * * @author TuxPaper * @since 2.0.8.5 */ public class BlocksItem extends CoreTableColumn implements TableCellAddedListener, TableCellRefreshListener, TableCellDisposeListener { private final int COLOR_REQUESTED = 0; private final int COLOR_WRITTEN = 1; private final int COLOR_DOWNLOADED = 2; private final int COLOR_INCACHE = 3; public static Color[] colors = new Color[] { Colors.blues[Colors.BLUES_MIDLIGHT], Colors.blues[Colors.BLUES_DARKEST], Colors.red, Colors.grey }; private static CacheFileManagerStats cacheStats = null; /** Default Constructor */ public BlocksItem() { super("blocks", TableManager.TABLE_TORRENT_PIECES); initializeAsGraphic(POSITION_LAST, 200); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROGRESS, }); } public void cellAdded(TableCell cell) { if (cacheStats == null) { try { cacheStats = CacheFileManagerFactory.getSingleton().getStats(); } catch (Exception e) { e.printStackTrace(); } } cell.setFillCell(true); } public void dispose(TableCell cell) { Image img = ((TableCellSWT) cell).getGraphicSWT(); if (img != null && !img.isDisposed()) img.dispose(); } public void refresh(TableCell cell) { PEPiece pePiece = (PEPiece) cell.getDataSource(); if (pePiece == null) { cell.setSortValue(0); dispose(cell); cell.setGraphic(null); return; } cell.setSortValue(pePiece.getNbWritten()); long lNumBlocks = pePiece.getNbBlocks(); int newWidth = cell.getWidth(); if (newWidth <= 0) { dispose(cell); cell.setGraphic(null); return; } int newHeight = cell.getHeight(); int x1 = newWidth - 2; int y1 = newHeight - 3; if (x1 < 10 || y1 < 3) { dispose(cell); cell.setGraphic(null); return; } Image image = new Image(SWTThread.getInstance().getDisplay(), newWidth, newHeight); Color color; GC gcImage = new GC(image); gcImage.setForeground(Colors.grey); gcImage.drawRectangle(0, 0, x1 + 1, y1 + 1); int blocksPerPixel = 0; int iPixelsPerBlock = 0; int pxRes = 0; long pxBlockStep = 0; int factor = 4; while (iPixelsPerBlock <= 0) { blocksPerPixel++; iPixelsPerBlock = (int) ((x1 + 1) / (lNumBlocks / blocksPerPixel)); } pxRes = (int) (x1 - ((lNumBlocks / blocksPerPixel) * iPixelsPerBlock)); // kolik mi zbyde if (pxRes <= 0) pxRes = 1; pxBlockStep = (lNumBlocks * factor) / pxRes; // kolikaty blok na +1 k sirce long addBlocks = (lNumBlocks * factor) / pxBlockStep; if ((addBlocks * iPixelsPerBlock) > pxRes) pxBlockStep += 1; /* String msg = "iPixelsPerBlock = "+iPixelsPerBlock + ", blocksPerPixel = " + blocksPerPixel; msg += ", pxRes = " + pxRes + ", pxBlockStep = " + pxBlockStep + ", addBlocks = " + addBlocks + ", x1 = " + x1; Debug.out(msg);*/ TOTorrent torrent = pePiece.getManager().getDiskManager().getTorrent(); boolean[] written = pePiece.getDMPiece().getWritten(); boolean piece_written = pePiece.isWritten(); int drawnWidth = 0; int blockStep = 0; int pieceNumber = pePiece.getPieceNumber(); long[] offsets = new long[(int) lNumBlocks]; long[] lengths = (long[]) offsets.clone(); Arrays.fill(offsets, (long) pePiece.getManager().getDiskManager().getPieceLength() * (long) pieceNumber); for (int i = 0; i < lNumBlocks; lengths[i] = pePiece.getBlockSize(i), offsets[i] += DiskManager.BLOCK_SIZE * i, i++) ; boolean[] isCached = cacheStats == null ? null : cacheStats.getBytesInCache(torrent, offsets, lengths); for (int i = 0; i < lNumBlocks; i += blocksPerPixel) { int nextWidth = iPixelsPerBlock; blockStep += blocksPerPixel * factor; if (blockStep >= pxBlockStep) { // pokud jsem prelezl dany pocet bloku, zvys tomuhle sirku nextWidth += (int) (blockStep / pxBlockStep); blockStep -= pxBlockStep; } if (i >= lNumBlocks - blocksPerPixel) { // pokud je posledni, at zasahuje az na konec nextWidth = x1 - drawnWidth; } color = Colors.white; if ((written == null && piece_written) || (written != null && written[i])) { color = colors[COLOR_WRITTEN]; } else if (pePiece.isDownloaded(i)) { color = colors[COLOR_DOWNLOADED]; } else if (pePiece.isRequested(i)) { color = colors[COLOR_REQUESTED]; } gcImage.setBackground(color); gcImage.fillRectangle(drawnWidth + 1, 1, nextWidth, y1); if (isCached[i]) { gcImage.setBackground(colors[COLOR_INCACHE]); gcImage.fillRectangle(drawnWidth + 1, 1, nextWidth, 3); } drawnWidth += nextWidth; } gcImage.dispose(); Image oldImage = null; Graphic graphic = cell.getGraphic(); if (graphic instanceof UISWTGraphic) { oldImage = ((UISWTGraphic)graphic).getImage(); } if (cell instanceof TableCellSWT) { ((TableCellSWT) cell).setGraphic(image); } else { cell.setGraphic(new UISWTGraphicImpl(image)); } if (oldImage != null && !oldImage.isDisposed()) oldImage.dispose(); gcImage.dispose(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/SizeItem.java0000644000175000017500000000355111135264370026547 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.pieces; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** Piece Size * * @author TuxPaper * @since 2.0.8.5 */ public class SizeItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Initialization */ public SizeItem() { super("size", ALIGN_TRAIL, POSITION_LAST, 60, TableManager.TABLE_TORRENT_PIECES); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, }); } public void refresh(TableCell cell) { PEPiece piece = (PEPiece)cell.getDataSource(); long value = (piece == null) ? 0 : piece.getLength(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(DisplayFormatters.formatByteCountToKiBEtc(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/BlockCountItem.java0000644000175000017500000000323610373051022027667 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.pieces; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class BlockCountItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public BlockCountItem() { super("numberofblocks", ALIGN_TRAIL, POSITION_LAST, 65, TableManager.TABLE_TORRENT_PIECES); } public void refresh(TableCell cell) { PEPiece piece = (PEPiece)cell.getDataSource(); long value = (piece == null) ? 0 : piece.getNbBlocks(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/TypeItem.java0000644000175000017500000000356310373051022026550 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.pieces; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 * @author MjrTom * 2005/Oct/08: fast/slow changed to graduated, so >2 = fast now */ public class TypeItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public TypeItem() { super("type", ALIGN_TRAIL, POSITION_LAST, 80, TableManager.TABLE_TORRENT_PIECES); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPiece piece = (PEPiece)cell.getDataSource(); long value = (piece == null) ? 0 : piece.getSpeed() >2 ? 1 : 0; if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(MessageText.getString("PiecesView.typeItem." + value)); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/pieces/ReservedByItem.java0000644000175000017500000000341510373051022027675 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.pieces; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class ReservedByItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public ReservedByItem() { super("reservedby", ALIGN_TRAIL, POSITION_INVISIBLE, 80, TableManager.TABLE_TORRENT_PIECES); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPiece piece = (PEPiece)cell.getDataSource(); String reservedBy = (piece == null) ? null : piece.getReservedBy(); String value = reservedBy == null ? "---" : reservedBy; if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(value); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/0000755000175000017500000000000011310377640024700 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/CompletedCountItem.java0000644000175000017500000000333010373051012031274 0ustar adrianadrian /* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class CompletedCountItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public CompletedCountItem() { super("completed", ALIGN_TRAIL, POSITION_LAST, 70, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = (item == null) ? 0 : item.getCompletedCount(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/UploadedItem.java0000644000175000017500000000363610373051012030115 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class UploadedItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public UploadedItem() { super("uploaded", ALIGN_TRAIL, POSITION_LAST, 70, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = 0; if (item != null) { Long longObject = (Long)item.getData("GUI_Uploaded"); if (longObject != null) value = longObject.longValue(); } if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(DisplayFormatters.formatByteCountToKiBEtc(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/DateAddedItem.java0000644000175000017500000000340010551565060030157 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class DateAddedItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public DateAddedItem() { super("date_added", ALIGN_TRAIL, POSITION_LAST, 60, TableManager.TABLE_MYTRACKER); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); String date_text = ""; if( item != null ) { long date = item.getDateAdded(); date_text = DisplayFormatters.formatDate( date ); } cell.setText( date_text ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/PeerCountItem.java0000644000175000017500000000347710373051012030267 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class PeerCountItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PeerCountItem() { super("peers", ALIGN_TRAIL, POSITION_LAST, 60, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = 0; if (item != null) { Long longObject = (Long)item.getData("GUI_PeerCount"); if (longObject != null) value = longObject.longValue(); } if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/NameItem.java0000644000175000017500000000706411127403350027243 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.tracker.host.TRHostTorrent; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.ui.swt.ImageRepository; import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.*; /** * * @author TuxPaper * @since 2.0.8.5 */ public class NameItem extends CoreTableColumn implements TableCellRefreshListener, ObfusticateCellText { private static boolean bShowIcon; static { COConfigurationManager.addAndFireParameterListener( "NameColumn.showProgramIcon", new ParameterListener() { public void parameterChanged(String parameterName) { bShowIcon = COConfigurationManager.getBooleanParameter("NameColumn.showProgramIcon"); } }); } /** Default Constructor */ public NameItem() { super("name", POSITION_LAST, 250, TableManager.TABLE_MYTRACKER); setType(TableColumn.TYPE_TEXT); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent) cell.getDataSource(); String name = (item == null) ? "" : TorrentUtils.getLocalisedName(item.getTorrent()); //setText returns true only if the text is updated if (cell.setText(name) || !cell.isValid()) { if (item != null && item.getTorrent() != null && bShowIcon && (cell instanceof TableCellSWT)) { try { TOTorrent torrent = item.getTorrent(); String path = torrent.getFiles()[0].getRelativePath(); if (path != null) { // Don't ever dispose of PathIcon, it's cached and may be used elsewhere Image icon = ImageRepository.getPathIcon(path, false, torrent != null && !torrent.isSimpleTorrent()); ((TableCellSWT) cell).setIcon(icon); } } catch (Exception e) { } } } } public String getObfusticatedText(TableCell cell) { TRHostTorrent item = (TRHostTorrent) cell.getDataSource(); String name = null; try { name = ByteFormatter.nicePrint(item.getTorrent().getHash(), true); } catch (TOTorrentException e) { } if (name == null) name = ""; return name; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/ScrapeCountItem.java0000644000175000017500000000331410373051012030577 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class ScrapeCountItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public ScrapeCountItem() { super("scrapes", ALIGN_TRAIL, POSITION_LAST, 60, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = (item == null) ? 0 : item.getScrapeCount(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/BadNATCountItem.java0000644000175000017500000000374110373051012030417 0ustar adrianadrian/* * Created on 30-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.tracker.host.TRHostTorrent; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * @author parg * */ public class BadNATCountItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public BadNATCountItem() { super("badnat", ALIGN_TRAIL, POSITION_LAST, 60, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = 0; if (item != null) { Long longObject = (Long)item.getData("GUI_BadNATCount"); if (longObject != null) value = longObject.longValue(); } if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TrackerItem.java0000644000175000017500000000326110373051012027745 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class TrackerItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public TrackerItem() { super("tracker", POSITION_LAST, 250, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { String sText; TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); if (item == null) { sText = ""; } else { sText = item.getTorrent().getAnnounceURL().toString(); } cell.setText(sText); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/LeftItem.java0000644000175000017500000000361610373051012027250 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class LeftItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public LeftItem() { super("left", ALIGN_TRAIL, POSITION_LAST, 50, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = 0; if (item != null) { Long longObject = (Long)item.getData("GUI_Left"); if (longObject != null) value = longObject.longValue(); } if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(DisplayFormatters.formatByteCountToKiBEtc(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TotalBytesInItem.java0000644000175000017500000000345610373051012030741 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class TotalBytesInItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public TotalBytesInItem() { super("bytesin", ALIGN_TRAIL, POSITION_LAST, 50, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = (item == null) ? 0 : item.getTotalBytesIn(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(DisplayFormatters.formatByteCountToKiBEtc(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AverageBytesOutItem.java0000644000175000017500000000350110373051012031420 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class AverageBytesOutItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public AverageBytesOutItem() { super("bytesoutave", ALIGN_TRAIL, POSITION_LAST, 50, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = (item == null) ? 0 : item.getAverageBytesOut(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(DisplayFormatters.formatByteCountToKiBEtcPerSec(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/StatusItem.java0000644000175000017500000000453210373051012027637 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class StatusItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public StatusItem() { super("status", POSITION_LAST, 60, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); String status_text = ""; if( item != null ) { int status = item.getStatus(); if( !cell.setSortValue( status ) && cell.isValid() ) { return; } if (status == TRHostTorrent.TS_STARTED) { status_text = MessageText.getString( "MyTrackerView.status.started" ); } else if (status == TRHostTorrent.TS_STOPPED) { status_text = MessageText.getString( "MyTrackerView.status.stopped" ); } else if (status == TRHostTorrent.TS_FAILED) { status_text = MessageText.getString( "MyTrackerView.status.failed" ); } else if (status == TRHostTorrent.TS_PUBLISHED) { status_text = MessageText.getString( "MyTrackerView.status.published" ); } } cell.setText( status_text ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AnnounceCountItem.java0000644000175000017500000000332410373051012031131 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class AnnounceCountItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public AnnounceCountItem() { super("announces", ALIGN_TRAIL, POSITION_LAST, 70, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = (item == null) ? 0 : item.getAnnounceCount(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/PassiveItem.java0000644000175000017500000000375710660036704030010 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class PassiveItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PassiveItem() { super("passive", ALIGN_TRAIL, POSITION_LAST, 60, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); String status_text = ""; if( item != null ) { if( !cell.setSortValue( item.isPassive()?1:0 ) && cell.isValid() ) { return; } if ( item.isPassive() ){ status_text = MessageText.getString( "Button.yes" ).replaceAll("&", ""); }else{ status_text = MessageText.getString( "Button.no" ).replaceAll("&", ""); } } cell.setText( status_text ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/DownloadedItem.java0000644000175000017500000000364610373051012030441 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class DownloadedItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public DownloadedItem() { super("downloaded", ALIGN_TRAIL, POSITION_LAST, 70, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = 0; if (item != null) { Long longObject = (Long)item.getData("GUI_Downloaded"); if (longObject != null) value = longObject.longValue(); } if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(DisplayFormatters.formatByteCountToKiBEtc(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TotalBytesOutItem.java0000644000175000017500000000346210373051012031137 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class TotalBytesOutItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public TotalBytesOutItem() { super("bytesout", ALIGN_TRAIL, POSITION_LAST, 50, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = (item == null) ? 0 : item.getTotalBytesOut(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(DisplayFormatters.formatByteCountToKiBEtc(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/CategoryItem.java0000644000175000017500000000546111171750564030152 0ustar adrianadrian/* * Created on 10-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.category.Category; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.tracker.host.TRHostTorrent; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.AzureusCoreFactory; /** * @author parg * */ public class CategoryItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ protected static GlobalManager gm; public CategoryItem() { super("category", CoreTableColumn.POSITION_INVISIBLE, 400, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent tr_torrent = (TRHostTorrent)cell.getDataSource(); if ( tr_torrent == null ){ cell.setText(""); }else{ TOTorrent torrent = tr_torrent.getTorrent(); if (gm == null) { if (AzureusCoreFactory.isCoreRunning()) { return; } gm = AzureusCoreFactory.getSingleton().getGlobalManager(); } DownloadManager dm = gm.getDownloadManager( torrent ); String cat_str = null; if ( dm != null ){ Category cat = dm.getDownloadState().getCategory(); if (cat != null){ cat_str = cat.getName(); } }else{ // pick up specific torrent category, bit 'o' a hack tis cat_str = TorrentUtils.getPluginStringProperty( torrent, "azcoreplugins.category" ); } cell.setText( cat_str==null?"":cat_str); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AverageBytesInItem.java0000644000175000017500000000347510373051012031231 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class AverageBytesInItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public AverageBytesInItem() { super("bytesinave", ALIGN_TRAIL, POSITION_LAST, 50, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = (item == null) ? 0 : item.getAverageBytesIn(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(DisplayFormatters.formatByteCountToKiBEtcPerSec(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/SeedCountItem.java0000644000175000017500000000347710373051012030254 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.mytracker; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @since 2.0.8.5 */ public class SeedCountItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public SeedCountItem() { super("seeds", ALIGN_TRAIL, POSITION_LAST, 60, TableManager.TABLE_MYTRACKER); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { TRHostTorrent item = (TRHostTorrent)cell.getDataSource(); long value = 0; if (item != null) { Long longObject = (Long)item.getData("GUI_SeedCount"); if (longObject != null) value = longObject.longValue(); } if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/0000755000175000017500000000000011310377640024015 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/StateItem.java0000644000175000017500000000516511135264370026566 0ustar adrianadrian/* * File : ClientItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.impl.PEPeerTransport; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; public class StateItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public StateItem(String table_id) { super("state", POSITION_LAST, 65, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROTOCOL, CAT_CONNECTION, }); } public void refresh(TableCell cell) { PEPeerTransport peer = (PEPeerTransport)cell.getDataSource(); //TODO fix this "naughty" cast String state_text = ""; if( peer != null ) { int state = peer.getConnectionState(); if( !cell.setSortValue( state ) && cell.isValid() ) { return; } switch( state ) { case PEPeerTransport.CONNECTION_PENDING : state_text = MessageText.getString( "PeersView.state.pending" ); break; case PEPeerTransport.CONNECTION_CONNECTING : state_text = MessageText.getString( "PeersView.state.connecting" ); break; case PEPeerTransport.CONNECTION_WAITING_FOR_HANDSHAKE : state_text = MessageText.getString( "PeersView.state.handshake" ); break; case PEPeerTransport.CONNECTION_FULLY_ESTABLISHED : state_text = MessageText.getString( "PeersView.state.established" ); break; } } cell.setText( state_text ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpDownRatioItem.java0000644000175000017500000000524111222070734027710 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper * @author MjrTom Jan/14/2006 subtract discarded bytes */ public class UpDownRatioItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public UpDownRatioItem(String table_id) { super("UpDownRatio", ALIGN_TRAIL, POSITION_INVISIBLE, 70, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SHARING, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); float value = 0; long lDivisor = 0; long lDivident = 0; if (peer != null) { lDivisor = peer.getStats().getTotalDataBytesReceived() -peer.getStats().getTotalBytesDiscarded(); lDivident = peer.getStats().getTotalDataBytesSent(); // skip if divisor is small (most likely handshake) or 0 (DivisionByZero) if (lDivisor > 1024) { value = lDivident / (float)lDivisor; if (value == 0) value = -1; } else if (lDivident > 0) value = Float.MAX_VALUE; } if (!cell.setSortValue((long)(value * 1000.0d )) && cell.isValid()) return; String s; if (lDivisor <= 0) s = ""; else if (value == Float.MAX_VALUE ) s = Constants.INFINITY_STRING + ":1"; else if (value == -1) s = "1:" + Constants.INFINITY_STRING; else s = DisplayFormatters.formatDecimal(value, 2) + ":1"; cell.setText(s); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/InterestedItem.java0000644000175000017500000000416011135264370027606 0ustar adrianadrian/* * File : InterestedItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class InterestedItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "I1"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROTOCOL, }); } /** Default Constructor */ public InterestedItem(String table_id) { super(COLUMN_ID, ALIGN_CENTER, POSITION_INVISIBLE, 20, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : (peer.isInteresting() ? 1 : 0); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText((value == 1) ? "*" : ""); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/ConnectedTimeItem.java0000644000175000017500000000411411135264370030220 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.impl.PEPeerTransport; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; public class ConnectedTimeItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "connected_time"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_TIME, }); } /** Default Constructor */ public ConnectedTimeItem(String table_id) { super(COLUMN_ID, ALIGN_TRAIL, POSITION_INVISIBLE, 70, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeerTransport peer = (PEPeerTransport)cell.getDataSource(); long value = (peer == null) ? 0 : peer.getTimeSinceConnectionEstablished(); if( !cell.setSortValue( value ) && cell.isValid() ) { return; } cell.setText( TimeFormatter.format( value / 1000 ) ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerIDItem.java0000644000175000017500000000443611135264370026616 0ustar adrianadrian/* * Created on 2 Mar 2007 Created by Allan Crooks Copyright (C) 2007 Aelitis, All * Rights Reserved. This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. This program is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, write * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. AELITIS, SAS au capital de 46,603.30 euros 8 Allee * Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * @author Allan Crooks */ public class PeerIDItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PeerIDItem(String table_id) { // Uses same values for subclass constructor as ClientItem does. super("peer_id", POSITION_INVISIBLE, 100, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PEER_IDENTIFICATION, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer) cell.getDataSource(); if (peer == null) {cell.setText(""); return;} byte[] peer_id = peer.getId(); if (peer_id == null) {cell.setText(""); return;} try { String text = new String(peer_id, 0, peer_id.length, Constants.BYTE_ENCODING); text = text.replace((char)12, (char)32); // Replace newlines. text = text.replace((char)10, (char)32); cell.setText(text); } catch (java.io.UnsupportedEncodingException uee) { cell.setText(""); } } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/PiecesItem.java0000644000175000017500000002671011142146224026710 0ustar adrianadrian/* * File : PiecesItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.impl.PEPeerTransport; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags; import org.gudy.azureus2.plugins.ui.Graphic; import org.gudy.azureus2.plugins.ui.tables.*; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class PiecesItem extends CoreTableColumn implements TableCellAddedListener, TableCellRefreshListener, TableCellDisposeListener, DiskManagerListener { private final static int INDEX_COLOR_FADEDSTARTS = Colors.BLUES_DARKEST + 1; // only supports 0 or 1 border width private final static int borderHorizontalSize = 1; private final static int borderVerticalSize = 1; private final static int borderSplit = 1; private final static int completionHeight = 2; private int row_count; /** Default Constructor */ public PiecesItem(String table_id) { super("pieces", table_id); initializeAsGraphic(POSITION_LAST, 200); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, }); } public void cellAdded(TableCell cell) { synchronized( this ){ row_count++; } cell.setFillCell(true); Object ds = cell.getDataSource(); if (ds instanceof PEPeer) { PEPeer peer = (PEPeer) ds; DiskManager diskmanager = peer.getManager().getDiskManager(); if ( diskmanager.getRemaining() > 0 ){ if ( !diskmanager.hasListener( this )){ diskmanager.addListener( this ); } } } } public void dispose(TableCell cell) { synchronized( this ){ row_count--; } // Named infoObj so code can be copied easily to the other PiecesItem PEPeer infoObj = (PEPeer)cell.getDataSource(); if (infoObj == null) return; Image img = (Image)infoObj.getData("PiecesImage"); if (img != null && !img.isDisposed()) img.dispose(); infoObj.setData("PiecesImageBuffer", null); infoObj.setData("PiecesImage", null); } public void refresh(TableCell cell) { /* Notes: * We store our image and imageBufer in PEPeer using * setData & getData. */ // Named infoObj so code can be copied easily to the other PiecesItem PEPeer infoObj = (PEPeer)cell.getDataSource(); long lCompleted = (infoObj == null) ? 0 : infoObj.getPercentDoneInThousandNotation(); if( !cell.setSortValue( lCompleted ) && cell.isValid() ) { return; } if (infoObj == null) return; //Compute bounds ... int newWidth = cell.getWidth(); if (newWidth <= 0) return; int newHeight = cell.getHeight(); int x0 = borderVerticalSize; int x1 = newWidth - 1 - borderVerticalSize; int y0 = completionHeight + borderHorizontalSize + borderSplit; int y1 = newHeight - 1 - borderHorizontalSize; int drawWidth = x1 - x0 + 1; if (drawWidth < 10 || y1 < 3) return; int[] imageBuffer = (int [])infoObj.getData("PiecesImageBuffer"); boolean bImageBufferValid = imageBuffer != null && imageBuffer.length == drawWidth; Image image = (Image)infoObj.getData("PiecesImage"); GC gcImage; boolean bImageChanged; Rectangle imageBounds; if (image == null || image.isDisposed()) { bImageChanged = true; } else { imageBounds = image.getBounds(); bImageChanged = imageBounds.width != newWidth || imageBounds.height != newHeight; } if (bImageChanged) { if (image != null && !image.isDisposed()) { image.dispose(); } image = new Image(SWTThread.getInstance().getDisplay(), newWidth, newHeight); imageBounds = image.getBounds(); bImageBufferValid = false; // draw border gcImage = new GC(image); gcImage.setForeground(Colors.grey); if (borderHorizontalSize > 0) { if (borderVerticalSize > 0) { gcImage.drawRectangle(0, 0, newWidth - 1, newHeight - 1); } else { gcImage.drawLine(0, 0, newWidth - 1, 0); gcImage.drawLine(0, newHeight -1, newWidth - 1, newHeight - 1); } } else if (borderVerticalSize > 0) { gcImage.drawLine(0, 0, 0, newHeight - 1); gcImage.drawLine(newWidth - 1, 0, newWidth - 1, newHeight - 1); } if (borderSplit > 0) { gcImage.setForeground(Colors.white); gcImage.drawLine(x0, completionHeight + borderHorizontalSize, x1, completionHeight + borderHorizontalSize); } } else { gcImage = new GC(image); } final BitFlags peerHave = infoObj.getAvailable(); boolean established = ((PEPeerTransport)infoObj).getConnectionState() == PEPeerTransport.CONNECTION_FULLY_ESTABLISHED; if (established && peerHave != null && peerHave.flags.length > 0) { if (imageBuffer == null || imageBuffer.length != drawWidth) { imageBuffer = new int[drawWidth]; } final boolean available[] =peerHave.flags; try { int nbComplete = 0; int nbPieces = available.length; DiskManager disk_manager = infoObj.getManager().getDiskManager(); DiskManagerPiece[] pieces = disk_manager==null?null:disk_manager.getPieces(); int a0; int a1 = 0; for (int i = 0; i < drawWidth; i++) { if (i == 0) { // always start out with one piece a0 = 0; a1 = nbPieces / drawWidth; if (a1 == 0) a1 = 1; } else { // the last iteration, a1 will be nbPieces a0 = a1; a1 = ((i + 1) * nbPieces) / (drawWidth); } int index; int nbNeeded = 0; if (a1 <= a0) { index = imageBuffer[i - 1]; } else { int nbAvailable = 0; for (int j = a0; j < a1; j++) { if (available[j]) { if (pieces==null || !pieces[j].isDone()) { nbNeeded++; } nbAvailable++; } } nbComplete += nbAvailable; index = (nbAvailable * Colors.BLUES_DARKEST) / (a1 - a0); if (nbNeeded <= nbAvailable / 2) index += INDEX_COLOR_FADEDSTARTS; } if (imageBuffer[i] != index) { imageBuffer[i] = index; if (bImageBufferValid) { bImageChanged = true; if (imageBuffer[i] >= INDEX_COLOR_FADEDSTARTS) gcImage.setForeground(Colors.faded[index - INDEX_COLOR_FADEDSTARTS]); else gcImage.setForeground(Colors.blues[index]); gcImage.drawLine(i + x0, y0, i + x0, y1); } } } if (!bImageBufferValid) { if(established) { int iLastIndex = imageBuffer[0]; int iWidth = 1; for (int i = 1; i < drawWidth; i++) { if (iLastIndex == imageBuffer[i]) { iWidth++; } else { if (iLastIndex >= INDEX_COLOR_FADEDSTARTS) { gcImage.setBackground(Colors.faded[iLastIndex - INDEX_COLOR_FADEDSTARTS]); } else gcImage.setBackground(Colors.blues[iLastIndex]); gcImage.fillRectangle(i - iWidth + x0, y0, iWidth, y1 - y0 + 1); iWidth = 1; iLastIndex = imageBuffer[i]; } } if (iLastIndex >= INDEX_COLOR_FADEDSTARTS) gcImage.setBackground(Colors.faded[iLastIndex - INDEX_COLOR_FADEDSTARTS]); else gcImage.setBackground(Colors.blues[iLastIndex]); gcImage.fillRectangle(x1 - iWidth + 1, y0, iWidth, y1 - y0 + 1); bImageChanged = true; } } int limit = (drawWidth * nbComplete) / nbPieces; if (limit < drawWidth) { gcImage.setBackground(Colors.blues[Colors.BLUES_LIGHTEST]); gcImage.fillRectangle(limit+x0, borderHorizontalSize, x1-limit, completionHeight); } gcImage.setBackground(Colors.colorProgressBar); gcImage.fillRectangle(x0, borderHorizontalSize, limit, completionHeight); } catch (Exception e) { System.out.println("Error Drawing PiecesItem"); Debug.printStackTrace( e ); } } else { gcImage.setForeground(Colors.grey); gcImage.setBackground(Colors.grey); gcImage.fillRectangle(x0,y0,newWidth,y1); } gcImage.dispose(); Image oldImage = null; Graphic graphic = cell.getGraphic(); if (graphic instanceof UISWTGraphic) { oldImage = ((UISWTGraphic) graphic).getImage(); } if (bImageChanged || image != oldImage || !cell.isValid()) { if (cell instanceof TableCellSWT) { ((TableCellSWT) cell).setGraphic(image); } else { cell.setGraphic(new UISWTGraphicImpl(image)); } if (bImageChanged || image != oldImage) { cell.invalidate(); } infoObj.setData("PiecesImage", image); infoObj.setData("PiecesImageBuffer", imageBuffer); } } // @see org.gudy.azureus2.core3.disk.DiskManagerListener#fileAccessModeChanged(org.gudy.azureus2.core3.disk.DiskManagerFileInfo, int, int) public void fileAccessModeChanged(DiskManagerFileInfo file, int old_mode, int new_mode) { } // @see org.gudy.azureus2.core3.disk.DiskManagerListener#filePriorityChanged(org.gudy.azureus2.core3.disk.DiskManagerFileInfo) public void filePriorityChanged(DiskManagerFileInfo file) { } // @see org.gudy.azureus2.core3.disk.DiskManagerListener#pieceDoneChanged(org.gudy.azureus2.core3.disk.DiskManagerPiece) public void pieceDoneChanged(DiskManagerPiece piece) { DiskManager diskmanager = piece.getManager(); boolean remove_listener; synchronized( this ){ remove_listener = row_count==0; } if ( remove_listener ){ diskmanager.removeListener( this ); }else{ invalidateCells(); if ( diskmanager.getRemaining() == 0 ){ diskmanager.removeListener(this); } } } // @see org.gudy.azureus2.core3.disk.DiskManagerListener#stateChanged(int, int) public void stateChanged(int oldState, int newState) { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/ClientItem.java0000644000175000017500000000374511135264370026726 0ustar adrianadrian/* * File : ClientItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class ClientItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "client"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PEER_IDENTIFICATION, }); } /** Default Constructor */ public ClientItem(String table_id) { super(COLUMN_ID, POSITION_LAST, 100, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); cell.setText( peer == null ? "" : peer.getClient() ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/UniquePieceItem.java0000644000175000017500000000410511135264370027713 0ustar adrianadrian/* * File : UniquePieceItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class UniquePieceItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public UniquePieceItem(String table_id) { super("uniquepiece", ALIGN_TRAIL, POSITION_INVISIBLE, 60, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : peer.getUniqueAnnounce(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText((value == -1) ? MessageText.getString("PeersView.uniquepiece.none") : "" + value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/LANItem.java0000644000175000017500000000416111135264370026113 0ustar adrianadrian/* * File : SnubbedItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.*; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class LANItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "lan"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONNECTION, }); } public LANItem(String table_id) { super(COLUMN_ID, ALIGN_CENTER, POSITION_INVISIBLE, 20, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer) cell.getDataSource(); boolean lan = (peer == null) ? false : peer.isLANLocal(); if (!cell.setSortValue(lan ? 1 : 0) && cell.isValid()) return; cell.setText(lan ? "*" : ""); TableRow row = cell.getTableRow(); if (row != null) { row.setForeground(Utils.colorToIntArray(lan ? Colors.blue : null)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpSpeedItem.java0000644000175000017500000000433211135264370027046 0ustar adrianadrian/* * File : UpSpeedItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class UpSpeedItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public UpSpeedItem(String table_id) { super("uploadspeed", ALIGN_TRAIL, POSITION_LAST, 65, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long data_value = 0; long prot_value = 0; if ( peer != null ){ data_value = peer.getStats().getDataSendRate(); prot_value = peer.getStats().getProtocolSendRate(); } long sort_value = ( data_value<<32 ) + prot_value; if (!cell.setSortValue(sort_value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec(data_value,prot_value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/ASItem.java0000644000175000017500000000534111135264370026005 0ustar adrianadrian/* * File : ASItem.java * Created : 24 dec 2008 * By : Parg * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import java.net.InetAddress; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.networkmanager.admin.*; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * */ public class ASItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "as"; public ASItem(String table_id) { super(COLUMN_ID, ALIGN_LEAD, POSITION_INVISIBLE, 100, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PEER_IDENTIFICATION, }); } public void refresh(TableCell cell) { final PEPeer peer = (PEPeer)cell.getDataSource(); String text = ""; if ( peer != null ){ text = (String)peer.getUserData( ASItem.class ); if ( text == null ){ text = ""; peer.setUserData( ASItem.class, text ); try{ NetworkAdmin.getSingleton().lookupASN( InetAddress.getByName( peer.getIp()), new NetworkAdminASNListener() { public void success( NetworkAdminASN asn ) { peer.setUserData( ASItem.class, asn.getAS() + " - " + asn.getASName()); } public void failed( NetworkAdminException error ) { } }); }catch( Throwable e ){ } } } if (!cell.setSortValue(text) && cell.isValid()){ return; } cell.setText( text ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownloadNameItem.java0000644000175000017500000000424611135264370030055 0ustar adrianadrian/* * Created on 14 Sep 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author Allan Crooks * */ public class DownloadNameItem extends CoreTableColumn implements TableCellRefreshListener /*, ObfusticateCellText */ { public static final String COLUMN_ID = "name"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, }); } /** Default Constructor */ public DownloadNameItem(String table_id) { super(COLUMN_ID, 250, table_id); this.setPosition(0); //setObfustication(true); setRefreshInterval(INTERVAL_LIVE); setType(TableColumn.TYPE_TEXT); setMinWidth(100); } /* (non-Javadoc) * @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) */ public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); if (peer == null) {cell.setText(""); return;} PEPeerManager manager = peer.getManager(); if (manager == null) {cell.setText(""); return;} cell.setText(manager.getDisplayName()); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpRatioItem.java0000644000175000017500000000514111222070734027057 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author TuxPaper */ public class UpRatioItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public UpRatioItem(String table_id) { super("UpRatio", ALIGN_TRAIL, POSITION_INVISIBLE, 70, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SHARING, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); float value = 0; long lDivisor = 0; long lDivident = 0; if (peer != null) { lDivisor = peer.getStats().getTotalBytesDownloadedByPeer() - peer.getStats().getTotalDataBytesSent(); lDivident = peer.getStats().getTotalDataBytesSent(); // skip if divisor is small (most likely handshake) or 0 (DivisionByZero) if (lDivisor > 1024) { value = lDivident / (float)lDivisor; if (value == 0) value = -1; } else if (lDivident > 0) value = Float.MAX_VALUE; } if (!cell.setSortValue((long)(value * 1000.0d)) && cell.isValid()) return; String s; if (lDivisor <= 0) s = ""; else if (value == Float.MAX_VALUE ) s = Constants.INFINITY_STRING + ":1"; else if (value == -1) s = "1:" + Constants.INFINITY_STRING; else s = DisplayFormatters.formatDecimal(value, 2) + ":1"; cell.setText(s); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/EncryptionItem.java0000644000175000017500000000366411135264370027642 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * */ public class EncryptionItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "Encryption"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONNECTION, }); } /** Default Constructor */ public EncryptionItem(String table_id) { super(COLUMN_ID, ALIGN_CENTER, POSITION_INVISIBLE, 20, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); String value = peer == null ? "" : peer.getEncryption(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/PortItem.java0000644000175000017500000000353511135264370026431 0ustar adrianadrian/* * File : PortItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class PortItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PortItem(String table_id) { super("port", ALIGN_TRAIL, POSITION_INVISIBLE, 40, table_id); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONNECTION, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); int value = (peer == null) ? 0 : peer.getPort(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/ClientIdentificationItem.java0000644000175000017500000000505011135264370031567 0ustar adrianadrian/* * Created on 5 Sep 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * @author Allan Crooks * */ public class ClientIdentificationItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "client_identification"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PEER_IDENTIFICATION, }); } public ClientIdentificationItem(String table_id) { super(COLUMN_ID, POSITION_INVISIBLE, 200, table_id); setRefreshInterval(INTERVAL_LIVE); } /* (non-Javadoc) * @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) */ public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); if (peer == null) {cell.setText(""); return;} String peer_id_name = peer.getClientNameFromPeerID(); String peer_handshake_name = peer.getClientNameFromExtensionHandshake(); if (peer_id_name == null) {peer_id_name = "";} if (peer_handshake_name == null) {peer_handshake_name = "";} if (peer_id_name.equals("") && peer_handshake_name.equals("")) { cell.setText(""); return; } String result = peer_id_name; if (!peer_handshake_name.equals("")) {result += " / " + peer_handshake_name;} cell.setText(result); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/GainItem.java0000644000175000017500000000423311135264370026357 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * @author The8472 * @created Jun 28, 2007 */ public class GainItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "gain"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, CAT_SHARING, }); } /** Default Constructor */ public GainItem(String table_id) { super(COLUMN_ID, ALIGN_TRAIL, POSITION_INVISIBLE, 70, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : peer.getStats().getTotalDataBytesReceived()-peer.getStats().getTotalDataBytesSent(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText((value >= 0 ? "" : "-") + DisplayFormatters.formatByteCountToKiBEtc(Math.abs(value))); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownItem.java0000644000175000017500000000625111135264370026412 0ustar adrianadrian/* * File : DownItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class DownItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "download"; protected static boolean separate_prot_data_stats; protected static boolean data_stats_only; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, }); } static { COConfigurationManager.addAndFireParameterListeners(new String[] { "config.style.dataStatsOnly", "config.style.separateProtDataStats" }, new ParameterListener() { public void parameterChanged(String x) { separate_prot_data_stats = COConfigurationManager.getBooleanParameter("config.style.separateProtDataStats"); data_stats_only = COConfigurationManager.getBooleanParameter("config.style.dataStatsOnly"); } }); } /** Default Constructor */ public DownItem(String table_id) { super(COLUMN_ID, ALIGN_TRAIL, POSITION_INVISIBLE, 70, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer) cell.getDataSource(); long data_value = 0; long prot_value = 0; if (peer != null) { data_value = peer.getStats().getTotalDataBytesReceived(); prot_value = peer.getStats().getTotalProtocolBytesReceived(); } long sort_value; if (separate_prot_data_stats) { sort_value = (data_value << 24) + prot_value; } else if (data_stats_only) { sort_value = data_value; } else { sort_value = data_value + prot_value; } if (!cell.setSortValue(sort_value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatDataProtByteCountToKiBEtc(data_value, prot_value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/ChokingItem.java0000644000175000017500000000414611135264370027066 0ustar adrianadrian/* * File : ChokingItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class ChokingItem extends CoreTableColumn implements TableCellRefreshListener { private static final String COLUMN_ID = "C2"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROTOCOL, }); } /** Default Constructor */ public ChokingItem(String table_id) { super(COLUMN_ID, ALIGN_CENTER, POSITION_INVISIBLE, 20, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : (peer.isChokedByMe() ? 1 : 0); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText((value == 1) ? "*" : ""); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/HostNameItem.java0000644000175000017500000000425711135264370027225 0ustar adrianadrian/* * Created on 27-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * @author parg * */ public class HostNameItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "host"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PEER_IDENTIFICATION, }); } /** Default Constructor */ public HostNameItem(String table_id) { super(COLUMN_ID, POSITION_INVISIBLE, 100, table_id); setRefreshInterval(INTERVAL_LIVE); setObfustication(true); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer) cell.getDataSource(); String addr = peer == null ? "" : peer.getIPHostName(); if (cell.setText(addr) && !addr.equals(peer.getIp())) { String[] l = addr.split("\\."); StringBuffer buf = new StringBuffer(); for (int i = l.length-1; i >= 0 ; i--) { buf.append(l[i]); buf.append('.'); } cell.setSortValue(buf.toString()); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/TimeToSendPieceItem.java0000644000175000017500000000442511135264370030465 0ustar adrianadrian/* * File : TimeToSendPieceItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class TimeToSendPieceItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public TimeToSendPieceItem(String table_id) { super("timetosend", ALIGN_TRAIL, POSITION_INVISIBLE, 70, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_TIME, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : peer.getUploadHint(); Comparable sortValue = cell.getSortValue(); long oldValue = 0; if (sortValue instanceof Number) { oldValue = ((Number)sortValue).longValue(); } if (!cell.setSortValue(value) && cell.isValid()) return; String text = TimeFormatter.format(value / 1000); if (oldValue > 0) { text += ", " + TimeFormatter.format(oldValue / 1000); } cell.setText(text); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/TimeUntilCompleteItem.java0000644000175000017500000000421411135264370031103 0ustar adrianadrian/* * File : TotalDownSpeedItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class TimeUntilCompleteItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public TimeUntilCompleteItem(String table_id) { super("timetocomplete", ALIGN_TRAIL, POSITION_INVISIBLE, 65, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_TIME, CAT_CONTENT, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? Long.MAX_VALUE : peer.getStats().getEstimatedSecondsToCompletion(); if (!cell.setSortValue(value) && cell.isValid()) return; if ( value > 7*24*60*60 ){ value = Long.MAX_VALUE; } cell.setText(DisplayFormatters.formatETA(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerSourceItem.java0000644000175000017500000000357611135264370027566 0ustar adrianadrian/* * File : PortItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class PeerSourceItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PeerSourceItem(String table_id) { super("source", ALIGN_TRAIL, POSITION_INVISIBLE, 40, table_id); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PEER_IDENTIFICATION, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); String value = (peer == null) ? "" : peer.getPeerSource(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/PercentItem.java0000644000175000017500000000377711135264370027115 0ustar adrianadrian/* * File : PercentItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class PercentItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PercentItem(String table_id) { super("%", ALIGN_TRAIL, POSITION_LAST, 55, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROGRESS, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); int value = (peer == null) ? 0 : peer.getPercentDoneInThousandNotation(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatPercentFromThousands(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/StatUpItem.java0000644000175000017500000000401611135264370026720 0ustar adrianadrian/* * File : StatUpItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class StatUpItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public StatUpItem(String table_id) { super("statup", ALIGN_TRAIL, POSITION_INVISIBLE, 65, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : peer.getStats().getEstimatedUploadRateOfPeer(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatByteCountToKiBEtcPerSec(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/IncomingRequestCountItem.java0000644000175000017500000000420511135264370031625 0ustar adrianadrian/* * File : UniquePieceItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class IncomingRequestCountItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "incomingreqcount"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROTOCOL, }); } /** Default Constructor */ public IncomingRequestCountItem(String table_id) { super(COLUMN_ID, ALIGN_TRAIL, POSITION_INVISIBLE, 60, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : peer.getIncomingRequestCount(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText("" + value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownSpeedLimitItem.java0000644000175000017500000000467411135264370030401 0ustar adrianadrian/* * Created on 17-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * @author parg * */ public class DownSpeedLimitItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "maxdownspeed"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, CAT_SETTINGS, }); } /** Default Constructor */ public DownSpeedLimitItem(String table_id) { super(COLUMN_ID, ALIGN_TRAIL, POSITION_INVISIBLE, 35, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : peer.getStats().getDownloadRateLimitBytesPerSecond(); if (!cell.setSortValue(value) && cell.isValid()) return; if(value == -1) { cell.setText(MessageText.getString("MyTorrents.items.DownSpeedLimit.disabled")); } else if(value == 0) { cell.setText(Constants.INFINITY_STRING); } else { cell.setText(DisplayFormatters.formatByteCountToKiBEtcPerSec(value)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/DLedFromOthersItem.java0000644000175000017500000000546011135264370030325 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** Downloaded from others WHILE connected to you * * @author TuxPaper * @since 2.1.0.1 */ public class DLedFromOthersItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "DLedFromOthers"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, }); } /** Default Constructor */ public DLedFromOthersItem(String table_id) { super(COLUMN_ID, ALIGN_TRAIL, POSITION_INVISIBLE, 70, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : peer.getStats().getTotalBytesDownloadedByPeer() - peer.getStats().getTotalDataBytesSent(); // Just because we sent data doesn't mean the peer has told us the piece is done yet if (value < 0) value = 0; if ( peer != null ){ Long prev_value = (Long)peer.getData( "DLedFromOther_prev" ); if( prev_value != null ) { if( value < prev_value.longValue() ) { //dont show decrement while we're actively uploading value = prev_value.longValue(); } else if( value > prev_value.longValue() ) { peer.setData( "DLedFromOther_prev", new Long( value ) ); } } else { peer.setData( "DLedFromOther_prev", new Long( value ) ); } } if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatByteCountToKiBEtc(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/OptimisticUnchokeItem.java0000644000175000017500000000422211135264370031140 0ustar adrianadrian/* * File : OptimisticUnchokeItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class OptimisticUnchokeItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "optunchoke"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROTOCOL, }); } /** Default Constructor */ public OptimisticUnchokeItem(String table_id) { super(COLUMN_ID, ALIGN_CENTER, POSITION_INVISIBLE, 20, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : (peer.isOptimisticUnchoke() ? 1 : 0); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText((value == 1) ? "*" : ""); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/SnubbedItem.java0000644000175000017500000000412411135264370027062 0ustar adrianadrian/* * File : SnubbedItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.*; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class SnubbedItem extends CoreTableColumn implements TableCellRefreshListener { public SnubbedItem(String table_id) { super("S", ALIGN_CENTER, POSITION_INVISIBLE, 20, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROTOCOL, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer) cell.getDataSource(); boolean bSnubbed = (peer == null) ? false : peer.isSnubbed(); if (!cell.setSortValue(bSnubbed ? 1 : 0) && cell.isValid()) return; cell.setText(bSnubbed ? "*" : ""); TableRow row = cell.getTableRow(); if (row != null) { row.setForeground(Utils.colorToIntArray(bSnubbed ? Colors.grey : null)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/ChokedItem.java0000644000175000017500000000414211135264370026675 0ustar adrianadrian/* * File : ChokedItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class ChokedItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "C1"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROTOCOL, }); } /** Default Constructor */ public ChokedItem(String table_id) { super(COLUMN_ID, ALIGN_CENTER, POSITION_INVISIBLE, 20, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : (peer.isChokingMe() ? 1 : 0); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText((value == 1) ? "*" : ""); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/DiscardedItem.java0000644000175000017500000000431211135264370027361 0ustar adrianadrian/* * File : DiscardedItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class DiscardedItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "discarded"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, }); } /** Default Constructor */ public DiscardedItem(String table_id) { super(COLUMN_ID, ALIGN_TRAIL, POSITION_INVISIBLE, 60, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : peer.getStats().getTotalBytesDiscarded(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatByteCountToKiBEtc(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/PieceItem.java0000644000175000017500000000353311135264370026530 0ustar adrianadrian/* * File : PortItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author MjrTom * @since 2.3.0.7 */ public class PieceItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PieceItem(String table_id) { super("piece", ALIGN_TRAIL, POSITION_INVISIBLE, 40, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); int value = (peer == null) ? 0 : peer.getLastPiece(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(""+value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownSpeedItem.java0000644000175000017500000000464411135264370027377 0ustar adrianadrian/* * File : DownSpeedItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class DownSpeedItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "downloadspeed"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, }); } /** Default Constructor */ public DownSpeedItem(String table_id) { super(COLUMN_ID, ALIGN_TRAIL, POSITION_LAST, 65, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long data_value = 0; long prot_value = 0; if ( peer != null ){ data_value = peer.getStats().getDataReceiveRate(); prot_value = peer.getStats().getProtocolReceiveRate(); } long sort_value = ( data_value<<32 ) + prot_value; if (!cell.setSortValue(sort_value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec(data_value,prot_value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/MessagingItem.java0000644000175000017500000000435411135264370027422 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * */ public class MessagingItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "Messaging"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROTOCOL, }); } /** Default Constructor */ public MessagingItem(String table_id) { super(COLUMN_ID, ALIGN_CENTER, POSITION_INVISIBLE, 40, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); int value = (peer == null) ? -1 : peer.getMessagingMode(); if (!cell.setSortValue(value) && cell.isValid()) return; String text; switch (value) { case PEPeer.MESSAGING_BT_ONLY: text = ""; break; case PEPeer.MESSAGING_LTEP: text = "LT"; break; case PEPeer.MESSAGING_AZMP: text = "AZ"; break; case PEPeer.MESSAGING_EXTERN: text = "Plugin"; break; default: text = ""; break; } cell.setText(text); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/TotalDownSpeedItem.java0000644000175000017500000000406611135264370030401 0ustar adrianadrian/* * File : TotalDownSpeedItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class TotalDownSpeedItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public TotalDownSpeedItem(String table_id) { super("downloadspeedoverall", ALIGN_TRAIL, POSITION_INVISIBLE, 65, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : peer.getStats().getEstimatedDownloadRateOfPeer(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatByteCountToKiBEtcPerSec(value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerByteIDItem.java0000644000175000017500000000407111135264370027435 0ustar adrianadrian/* * Created on 2 Mar 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. This program is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, write * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. AELITIS, SAS au capital de 46,603.30 euros 8 Allee * Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * @author Allan Crooks */ public class PeerByteIDItem extends CoreTableColumn implements TableCellRefreshListener { /** Default Constructor */ public PeerByteIDItem(String table_id) { // Uses same values for subclass constructor as ClientItem does. super("peer_byte_id", POSITION_INVISIBLE, 100, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PEER_IDENTIFICATION, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer) cell.getDataSource(); if (peer == null) {cell.setText(""); return;} byte[] peer_id = peer.getId(); if (peer_id == null) {cell.setText(""); return;} cell.setText(ByteFormatter.nicePrint(peer_id)); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/IpItem.java0000644000175000017500000000514611135264370026055 0ustar adrianadrian/* * File : IpItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class IpItem extends CoreTableColumn implements TableCellRefreshListener, ObfusticateCellText { public static final String COLUMN_ID = "ip"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PEER_IDENTIFICATION, CAT_CONNECTION }); } /** Default Constructor */ public IpItem(String table_id) { super(COLUMN_ID, POSITION_LAST, 100, table_id); setObfustication(true); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); String sText = (peer == null) ? "" : peer.getIp(); if (cell.setText(sText) || !cell.isValid()) { String[] sBlocks = sText.split("\\."); if (sBlocks.length == 4) { try { long l = (Long.parseLong(sBlocks[0]) << 24) + (Long.parseLong(sBlocks[1]) << 16) + (Long.parseLong(sBlocks[2]) << 8) + Long.parseLong(sBlocks[3]); cell.setSortValue(l); } catch (Exception e) { e.printStackTrace(); /* ignore */ } } } } public String getObfusticatedText(TableCell cell) { return cell.getText().substring(0, 3); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/TypeItem.java0000644000175000017500000000441711135264370026426 0ustar adrianadrian/* * File : TypeItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class TypeItem extends CoreTableColumn implements TableCellRefreshListener, TableCellToolTipListener { /** Default Constructor */ public TypeItem(String table_id) { super("T", ALIGN_CENTER, POSITION_LAST, 20, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONNECTION, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : (peer.isIncoming() ? 1 : 0); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText((value == 1) ? "R" : "L"); } public void cellHover(TableCell cell) { String ID = "PeersView.T." + cell.getText() + ".tooltip"; String sTooltip = MessageText.getString(ID, ""); if (sTooltip.length() > 0) cell.setToolTip(sTooltip); } public void cellHoverComplete(TableCell cell) { cell.setToolTip(null); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/HandshakeReservedBytesItem.java0000644000175000017500000000421311135264370032074 0ustar adrianadrian/* * Created on 29 Aug 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * @author Allan Crooks * */ public class HandshakeReservedBytesItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "handshake_reserved"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROTOCOL, }); } public HandshakeReservedBytesItem(String table_id) { super(COLUMN_ID, POSITION_INVISIBLE, 80, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); byte[] handshake_reserved = null; if (peer != null) {handshake_reserved = peer.getHandshakeReservedBytes();} if (handshake_reserved == null) { cell.setText(""); return; } cell.setText(ByteFormatter.nicePrint(handshake_reserved, false)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpSpeedLimitItem.java0000644000175000017500000000464411135264370030053 0ustar adrianadrian/* * Created on 8 oct. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * @author Olivier Chalouhi * */ public class UpSpeedLimitItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "maxupspeed"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_SETTINGS, }); } /** Default Constructor */ public UpSpeedLimitItem(String table_id) { super(COLUMN_ID, ALIGN_TRAIL, POSITION_INVISIBLE, 35, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : peer.getUploadRateLimitBytesPerSecond(); if (!cell.setSortValue(value) && cell.isValid()) return; if(value == -1) { cell.setText(MessageText.getString("MyTorrents.items.UpSpeedLimit.disabled")); } else if(value == 0) { cell.setText(Constants.INFINITY_STRING); } else { cell.setText(DisplayFormatters.formatByteCountToKiBEtcPerSec(value)); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/OutgoingRequestCountItem.java0000644000175000017500000000421611135264370031657 0ustar adrianadrian/* * File : UniquePieceItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class OutgoingRequestCountItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "outgoingreqcount"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROTOCOL, }); } /** Default Constructor */ public OutgoingRequestCountItem(String table_id) { super("outgoingreqcount", ALIGN_TRAIL, POSITION_INVISIBLE, 60, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : peer.getOutgoingRequestCount(); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText("" + value); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/InterestingItem.java0000644000175000017500000000416011135264370027773 0ustar adrianadrian/* * File : InterestingItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class InterestingItem extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "I2"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_PROTOCOL, }); } /** Default Constructor */ public InterestingItem(String table_id) { super(COLUMN_ID, ALIGN_CENTER, POSITION_INVISIBLE, 20, table_id); setRefreshInterval(INTERVAL_LIVE); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer)cell.getDataSource(); long value = (peer == null) ? 0 : (peer.isInterested() ? 1 : 0); if (!cell.setSortValue(value) && cell.isValid()) return; cell.setText((value == 1) ? "*" : ""); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpItem.java0000644000175000017500000000573311135264370026073 0ustar adrianadrian/* * File : UpItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.tableitems.peers; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; /** * * @author Olivier * @author TuxPaper (2004/Apr/19: modified to TableCellAdapter) */ public class UpItem extends CoreTableColumn implements TableCellRefreshListener { protected static boolean separate_prot_data_stats; protected static boolean data_stats_only; static { COConfigurationManager.addAndFireParameterListeners(new String[] { "config.style.dataStatsOnly", "config.style.separateProtDataStats" }, new ParameterListener() { public void parameterChanged(String x) { separate_prot_data_stats = COConfigurationManager.getBooleanParameter("config.style.separateProtDataStats"); data_stats_only = COConfigurationManager.getBooleanParameter("config.style.dataStatsOnly"); } }); } /** Default Constructor */ public UpItem(String table_id) { super("upload", ALIGN_TRAIL, POSITION_INVISIBLE, 70, table_id); setRefreshInterval(INTERVAL_LIVE); } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_BYTES, }); } public void refresh(TableCell cell) { PEPeer peer = (PEPeer) cell.getDataSource(); long data_value = 0; long prot_value = 0; if (peer != null) { data_value = peer.getStats().getTotalDataBytesSent(); prot_value = peer.getStats().getTotalProtocolBytesSent(); } long sort_value; if (separate_prot_data_stats) { sort_value = (data_value << 24) + prot_value; } else if (data_stats_only) { sort_value = data_value; } else { sort_value = data_value + prot_value; } if (!cell.setSortValue(sort_value) && cell.isValid()) return; cell.setText(DisplayFormatters.formatDataProtByteCountToKiBEtc(data_value, prot_value)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/utils/0000755000175000017500000000000011310377640021706 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/utils/ManagerUtils.java0000644000175000017500000003330111267754526025161 0ustar adrianadrian/* * File : ManagerUtils.java * Created : 7 d�c. 2003} * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.utils; import java.io.File; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.global.GlobalManagerDownloadRemovalVetoException; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.core3.tracker.host.TRHostException; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AERunnableBoolean; import org.gudy.azureus2.core3.util.AsyncDispatcher; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.plugins.platform.PlatformManagerException; import org.gudy.azureus2.ui.swt.Alerts; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT.TriggerInThread; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; /** * @author Olivier * */ public class ManagerUtils { private static RunDownloadManager run; public static interface RunDownloadManager { public void run(DownloadManager dm); } public static void setRunRunnable(RunDownloadManager run) { ManagerUtils.run = run; } public static void run(DownloadManager dm) { if(dm != null) { if (run != null) { run.run(dm); } else { Utils.launch(dm.getSaveLocation().toString()); } } } /** * Opens the parent folder of dm's path * @param dm DownloadManager instance */ public static void open(DownloadManager dm) {open(dm, false);} public static void open(DownloadManager dm, boolean open_containing_folder_mode) { if (dm != null) {open(dm.getSaveLocation(), open_containing_folder_mode);} } public static void open(File f, boolean open_containing_folder_mode) { if (open_containing_folder_mode) { Utils.launch(f.getParent()); } else { open(f); } } public static void open(File f) { while (f != null && !f.exists()) f = f.getParentFile(); if (f == null) return; PlatformManager mgr = PlatformManagerFactory.getPlatformManager(); if (mgr.hasCapability(PlatformManagerCapabilities.ShowFileInBrowser)) { try { PlatformManagerFactory.getPlatformManager().showFile(f.toString()); return; } catch (PlatformManagerException e) { Debug.printStackTrace(e); } } if (f.isDirectory()) { Utils.launch(f.toString()); // default launcher } else { Utils.launch(f.getParent().toString()); } } public static boolean isStartable(DownloadManager dm) { if(dm == null) return false; int state = dm.getState(); if (state != DownloadManager.STATE_STOPPED) { return false; } return true; } public static boolean isStopable(DownloadManager dm) { if(dm == null) return false; int state = dm.getState(); if ( state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_STOPPING ) { return false; } return true; } public static boolean isStopped(DownloadManager dm) { if(dm == null) return false; int state = dm.getState(); if ( state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_ERROR ) { return true; } return false; } public static boolean isForceStartable( DownloadManager dm ) { if(dm == null){ return false; } int state = dm.getState(); if ( state != DownloadManager.STATE_STOPPED && state != DownloadManager.STATE_QUEUED && state != DownloadManager.STATE_SEEDING && state != DownloadManager.STATE_DOWNLOADING){ return( false ); } return( true ); } public static void host( AzureusCore azureus_core, DownloadManager dm, Composite panel) { if(dm == null) return; TOTorrent torrent = dm.getTorrent(); if (torrent != null) { try { azureus_core.getTrackerHost().hostTorrent(torrent, true, false ); } catch (TRHostException e) { MessageBox mb = new MessageBox(panel.getShell(), SWT.ICON_ERROR | SWT.OK); mb.setText(MessageText.getString("MyTorrentsView.menu.host.error.title")); mb.setMessage(MessageText.getString("MyTorrentsView.menu.host.error.message").concat("\n").concat(e.toString())); mb.open(); } } } public static void publish( AzureusCore azureus_core, DownloadManager dm, Composite panel) { if(dm == null) return; TOTorrent torrent = dm.getTorrent(); if (torrent != null) { try { azureus_core.getTrackerHost().publishTorrent(torrent); } catch (TRHostException e) { MessageBox mb = new MessageBox(panel.getShell(), SWT.ICON_ERROR | SWT.OK); mb.setText(MessageText.getString("MyTorrentsView.menu.host.error.title")); mb.setMessage(MessageText.getString("MyTorrentsView.menu.host.error.message").concat("\n").concat(e.toString())); mb.open(); } } } public static void start( DownloadManager dm) { if (dm != null && dm.getState() == DownloadManager.STATE_STOPPED) { dm.setStateWaiting(); } } public static void queue( DownloadManager dm, Composite panel) { if (dm != null) { if (dm.getState() == DownloadManager.STATE_STOPPED){ dm.setStateQueued(); /* parg - removed this - why would we want to effectively stop + restart * torrents that are running? This is what happens if the code is left in. * e.g. select two torrents, one stopped and one downloading, then hit "queue" }else if ( dm.getState() == DownloadManager.STATE_DOWNLOADING || dm.getState() == DownloadManager.STATE_SEEDING) { stop(dm,panel,DownloadManager.STATE_QUEUED); */ } } } public static void stop(DownloadManager dm, Shell shell) { stop(dm, shell, DownloadManager.STATE_STOPPED); } public static void stop( final DownloadManager dm, Shell shell, int stateAfterStopped ) { if (dm == null) { return; } int state = dm.getState(); if (state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_STOPPING || state == stateAfterStopped) { return; } boolean stopme = true; if (state == DownloadManager.STATE_SEEDING) { if (dm.getStats().getShareRatio() >= 0 && dm.getStats().getShareRatio() < 1000 && COConfigurationManager.getBooleanParameter("Alert on close", false)) { if (shell == null) { shell = Utils.findAnyShell(); } MessageBox mb = new MessageBox(shell, SWT.ICON_WARNING | SWT.YES | SWT.NO); mb.setText(MessageText.getString("seedmore.title")); mb.setMessage(MessageText.getString("seedmore.shareratio") + (dm.getStats().getShareRatio() / 10) + "%.\n" + MessageText.getString("seedmore.uploadmore")); int action = mb.open(); stopme = action == SWT.YES; } else if (dm.getDownloadState().isOurContent() && dm.getStats().getAvailability() < 2) { TRTrackerScraperResponse scrape = dm.getTrackerScrapeResponse(); int numSeeds = scrape.getSeeds(); long seedingStartedOn = dm.getStats().getTimeStartedSeeding(); if ((numSeeds > 0) && (seedingStartedOn > 0) && (scrape.getScrapeStartTime() > seedingStartedOn)) numSeeds--; if (numSeeds == 0) { String title = MessageText.getString("Content.alert.notuploaded.title"); String text = MessageText.getString("Content.alert.notuploaded.text", new String[] { dm.getDisplayName(), MessageText.getString("Content.alert.notuploaded.stop") }); MessageBoxShell mb = new MessageBoxShell( title, text, new String[] { MessageText.getString("Content.alert.notuploaded.button.stop"), MessageText.getString("Content.alert.notuploaded.button.continue") }, 1); mb.setRelatedObject(dm); mb.open(null); stopme = mb.waitUntilClosed() == 0; } } } if (stopme) { asyncStop(dm, stateAfterStopped); } } public static void remove(final DownloadManager dm, Shell shell, final boolean bDeleteTorrent, final boolean bDeleteData) { remove(dm, shell, bDeleteTorrent, bDeleteData, null); } public static void remove(final DownloadManager dm, Shell shell, final boolean bDeleteTorrent, final boolean bDeleteData, final AERunnable deleteFailed) { if (!dm.getDownloadState().getFlag(DownloadManagerState.FLAG_LOW_NOISE)) { if (COConfigurationManager.getBooleanParameter("confirm_torrent_removal")) { String title = MessageText.getString("deletedata.title"); String text = MessageText.getString("deletetorrent.message1") + dm.getDisplayName() + " :\n" + dm.getTorrentFileName() + MessageText.getString("deletetorrent.message2"); MessageBoxShell mb = new MessageBoxShell(SWT.YES | SWT.NO, title, text); mb.setDefaultButtonUsingStyle(SWT.NO); mb.setRelatedObject(dm); mb.setLeftImage(SWT.ICON_WARNING); mb.open(null); int result = mb.waitUntilClosed(); if (result != SWT.YES) { if (deleteFailed != null) { deleteFailed.runSupport(); } return; } } boolean confirmDataDelete = COConfigurationManager.getBooleanParameter( "Confirm Data Delete"); if (confirmDataDelete && bDeleteData) { String path = dm.getSaveLocation().toString(); String title = MessageText.getString("deletedata.title"); String text = MessageText.getString("deletedata.message1", new String[] { dm.getDisplayName() }); MessageBoxShell mb = new MessageBoxShell(SWT.YES | SWT.NO, title, text); mb.setDefaultButtonUsingStyle(SWT.NO); mb.setRemember("deletedata.noconfirm.key2", false, MessageText.getString("deletedata.noprompt")); mb.setRememberOnlyIfButton(0); mb.setRelatedObject(dm); mb.setLeftImage(SWT.ICON_WARNING); mb.open(null); int result = mb.waitUntilClosed(); if (result != SWT.YES) { if (deleteFailed != null) { deleteFailed.runSupport(); } return; } } } asyncStopDelete(dm, DownloadManager.STATE_STOPPED, bDeleteTorrent, bDeleteData, deleteFailed); } private static AsyncDispatcher async = new AsyncDispatcher(2000); public static void asyncStopDelete(final DownloadManager dm, final int stateAfterStopped, final boolean bDeleteTorrent, final boolean bDeleteData, final AERunnable deleteFailed) { async.dispatch(new AERunnable() { public void runSupport() { try { dm.getGlobalManager().removeDownloadManager(dm, bDeleteTorrent, bDeleteData); } catch (GlobalManagerDownloadRemovalVetoException f) { if (!f.isSilent()) { Alerts.showErrorMessageBoxUsingResourceString(new Object[] { dm }, "globalmanager.download.remove.veto", f, 0 ); } if (deleteFailed != null) { deleteFailed.runSupport(); } } catch (Exception ex) { Debug.printStackTrace(ex); if (deleteFailed != null) { deleteFailed.runSupport(); } } } }); } public static void asyncStop( final DownloadManager dm, final int stateAfterStopped ) { async.dispatch(new AERunnable() { public void runSupport() { dm.stopIt( stateAfterStopped, false, false ); } }); } public static void asyncStartAll() { CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD, new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { core.getGlobalManager().startAllDownloads(); } }); } public static void asyncStopAll() { CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD, new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { core.getGlobalManager().stopAllDownloads(); } }); } public static void asyncPause() { CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD, new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { core.getGlobalManager().pauseDownloads(); } }); } public static void asyncResume() { CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD, new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { core.getGlobalManager().resumeDownloads(); } }); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/utils/CoordinateTransform.java0000644000175000017500000000300711033057534026533 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.utils; import org.eclipse.swt.graphics.Rectangle; public class CoordinateTransform { public CoordinateTransform(Rectangle exteriorBounds) { extWidth = exteriorBounds.width; extHeight = exteriorBounds.height; } final int extWidth; final int extHeight; int offsetX = 0; int offsetY = 0; double scaleX = 1.0; double scaleY = 1.0; public int x(int x) { return (int)(Math.round(offsetX+x*scaleX)); } public int y(int y) { return (int)(Math.round(offsetY+y*scaleY)); } private int w(int w) { return (int)Math.round(w*scaleX); } private int h(int h) { return (int)Math.ceil(h*scaleY); } public void scale(double x, double y) { scaleX *= x; scaleY *= y; } public void shiftExternal(int x, int y) { offsetX += x; offsetY += y; } public void shiftInternal(int x, int y) { offsetX += x*scaleX; offsetY += y*scaleY; } private void calcFromDimensions(int internalWidth, int internalHeight, int marginLeft, int marginRight, int marginTop, int marginBottom, boolean leftToRight, boolean topDown) { shiftExternal(leftToRight ? 0 : extWidth,topDown ? 0 : extHeight); scale(leftToRight ? 1.0 : -1.0, topDown ? 1.0 : -1.0); shiftInternal(leftToRight ? marginLeft : marginRight, topDown ? marginTop : marginBottom); scale(Math.round((extWidth-marginLeft-marginRight)/(1.0*internalWidth)),Math.round((extHeight-marginTop-marginBottom)/(1.0*internalHeight))); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/0000755000175000017500000000000011310377636023570 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceColor.java0000644000175000017500000001156110747145306032011 0ustar adrianadrian/* * File : ConfigPanel*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.config.ColorParameter; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; public class ConfigSectionInterfaceColor implements UISWTConfigSection { private static final String[] sColorsToOverride = { "progressBar", "error", "warning", "altRow" }; private Color[] colorsToOverride = { Colors.colorProgressBar, Colors.colorError, Colors.colorWarning, Colors.colorAltRow }; private Button[] btnColorReset = new Button[sColorsToOverride.length]; public String configSectionGetParentSection() { return ConfigSection.SECTION_INTERFACE; } public String configSectionGetName() { return "color"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 0; } public Composite configSectionCreate(final Composite parent) { Label label; GridLayout layout; GridData gridData; Composite cSection = new Composite(parent, SWT.NULL); cSection.setLayoutData(new GridData(GridData.FILL_BOTH)); layout = new GridLayout(); layout.numColumns = 1; cSection.setLayout(layout); Composite cArea = new Composite(cSection, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 2; cArea.setLayout(layout); cArea.setLayoutData(new GridData()); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, "ConfigView.section.color"); ColorParameter colorScheme = new ColorParameter(cArea, "Color Scheme", 0, 128, 255); gridData = new GridData(); gridData.widthHint = 50; colorScheme.setLayoutData(gridData); Group cColorOverride = new Group(cArea, SWT.NULL); Messages.setLanguageText(cColorOverride, "ConfigView.section.style.colorOverrides"); layout = new GridLayout(); layout.numColumns = 3; cColorOverride.setLayout(layout); gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan = 2; cColorOverride.setLayoutData(gridData); for (int i = 0; i < sColorsToOverride.length; i++) { String sConfigID = "Colors." + sColorsToOverride[i]; label = new Label(cColorOverride, SWT.NULL); Messages.setLanguageText(label, "ConfigView.section.style.colorOverride." + sColorsToOverride[i]); ColorParameter colorParm = new ColorParameter(cColorOverride, sConfigID, colorsToOverride[i].getRed(), colorsToOverride[i].getGreen(), colorsToOverride[i].getBlue()) { public void newColorChosen() { COConfigurationManager.setParameter(sParamName + ".override", true); for (int i = 0; i < sColorsToOverride.length; i++) { if (sParamName.equals("Colors." + sColorsToOverride[i])) { btnColorReset[i].setEnabled(true); break; } } } }; gridData = new GridData(); gridData.widthHint = 50; colorParm.setLayoutData(gridData); btnColorReset[i] = new Button(cColorOverride, SWT.PUSH); Messages.setLanguageText(btnColorReset[i], "ConfigView.section.style.colorOverrides.reset"); btnColorReset[i].setEnabled(COConfigurationManager.getBooleanParameter( sConfigID + ".override", false)); btnColorReset[i].setData("ColorName", sConfigID); btnColorReset[i].addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { Button btn = (Button) event.widget; String sName = (String) btn.getData("ColorName"); if (sName != null) { COConfigurationManager.setParameter(sName + ".override", false); btn.setEnabled(false); } } }); } return cSection; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionStats.java0000644000175000017500000002114211127403350030171 0ustar adrianadrian/* * File : ConfigPanel*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.ImageRepository; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.Cursors; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.core3.stats.StatsWriterPeriodic; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; public class ConfigSectionStats implements UISWTConfigSection { private static final int defaultStatsPeriod = 30; private static final int statsPeriods[] = { 1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 40, 50, 60, 120, 180, 240, 300, 360, 420, 480, 540, 600, 900, 1200, 1800, 2400, 3000, 3600, 7200, 10800, 14400, 21600, 43200, 86400, }; public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } public String configSectionGetName() { return "stats"; } public void configSectionSave() { } public void configSectionDelete() { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage("openFolderButton"); } public int maxUserMode() { return 0; } public Composite configSectionCreate(final Composite parent) { ImageLoader imageLoader = ImageLoader.getInstance(); Image imgOpenFolder = imageLoader.getImage("openFolderButton"); GridData gridData; GridLayout layout; Composite gStats = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gStats.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; gStats.setLayout(layout); // row gridData = new GridData(); gridData.horizontalSpan = 3; BooleanParameter enableStats = new BooleanParameter(gStats, "Stats Enable", "ConfigView.section.stats.enable"); enableStats.setLayoutData(gridData); Control[] controls = new Control[14]; // row Label lStatsPath = new Label(gStats, SWT.NULL); Messages.setLanguageText(lStatsPath, "ConfigView.section.stats.defaultsavepath"); //$NON-NLS-1$ gridData = new GridData(); gridData.widthHint = 150; final StringParameter pathParameter = new StringParameter(gStats, "Stats Dir", ""); //$NON-NLS-1$ //$NON-NLS-2$ pathParameter.setLayoutData(gridData); controls[0] = lStatsPath; controls[1] = pathParameter.getControl(); Button browse = new Button(gStats, SWT.PUSH); browse.setImage(imgOpenFolder); imgOpenFolder.setBackground(browse.getBackground()); browse.setToolTipText(MessageText.getString("ConfigView.button.browse")); controls[2] = browse; browse.addListener(SWT.Selection, new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event event) { DirectoryDialog dialog = new DirectoryDialog(parent.getShell(), SWT.APPLICATION_MODAL); dialog.setFilterPath(pathParameter.getValue()); dialog.setText(MessageText.getString("ConfigView.section.stats.choosedefaultsavepath")); //$NON-NLS-1$ String path = dialog.open(); if (path != null) { pathParameter.setValue(path); } } }); // row Label lSaveFile = new Label(gStats, SWT.NULL); Messages.setLanguageText(lSaveFile, "ConfigView.section.stats.savefile"); //$NON-NLS-1$ controls[3] = lSaveFile; gridData = new GridData(); gridData.widthHint = 150; final StringParameter fileParameter = new StringParameter(gStats, "Stats File", StatsWriterPeriodic.DEFAULT_STATS_FILE_NAME ); fileParameter.setLayoutData(gridData); controls[4] = fileParameter.getControl(); new Label(gStats, SWT.NULL); // row Label lxslFile = new Label(gStats, SWT.NULL); Messages.setLanguageText(lxslFile, "ConfigView.section.stats.xslfile"); //$NON-NLS-1$ controls[5] = lxslFile; gridData = new GridData(); gridData.widthHint = 150; final StringParameter xslParameter = new StringParameter(gStats, "Stats XSL File", "" ); xslParameter.setLayoutData(gridData); controls[6] = xslParameter.getControl(); Label lxslDetails = new Label(gStats, SWT.NULL); Messages.setLanguageText(lxslDetails, "ConfigView.section.stats.xslfiledetails"); //$NON-NLS-1$ final String linkFAQ = "http://azureus.sourceforge.net/faq.php#20"; lxslDetails.setCursor(Cursors.handCursor); lxslDetails.setForeground(Colors.blue); lxslDetails.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { Utils.launch(linkFAQ); } public void mouseDown(MouseEvent arg0) { Utils.launch(linkFAQ); } }); controls[7] = lxslDetails; // row Label lSaveFreq = new Label(gStats, SWT.NULL); Messages.setLanguageText(lSaveFreq, "ConfigView.section.stats.savefreq"); controls[8] = lSaveFreq; final String spLabels[] = new String[statsPeriods.length]; final int spValues[] = new int[statsPeriods.length]; for (int i = 0; i < statsPeriods.length; i++) { int num = statsPeriods[i]; if ( num%3600 == 0 ) spLabels[i] = " " + (statsPeriods[i]/3600) + " " + MessageText.getString("ConfigView.section.stats.hours"); else if ( num%60 == 0 ) spLabels[i] = " " + (statsPeriods[i]/60) + " " + MessageText.getString("ConfigView.section.stats.minutes"); else spLabels[i] = " " + statsPeriods[i] + " " + MessageText.getString("ConfigView.section.stats.seconds"); spValues[i] = statsPeriods[i]; } controls[9] = lSaveFreq; controls[10] = new IntListParameter(gStats, "Stats Period", defaultStatsPeriod, spLabels, spValues).getControl(); new Label(gStats, SWT.NULL); // ROW gridData = new GridData(); gridData.horizontalSpan = 3; BooleanParameter exportPeers = new BooleanParameter(gStats, "Stats Export Peer Details", "ConfigView.section.stats.exportpeers"); exportPeers.setLayoutData(gridData); controls[11] = exportPeers.getControl(); // ROW gridData = new GridData(); gridData.horizontalSpan = 3; BooleanParameter exportFiles = new BooleanParameter(gStats, "Stats Export File Details", "ConfigView.section.stats.exportfiles"); exportFiles.setLayoutData(gridData); controls[12] = exportFiles.getControl(); // ROW gridData = new GridData(); gridData.horizontalSpan = 3; BooleanParameter graph_dividers = new BooleanParameter(gStats, "Stats Graph Dividers", "ConfigView.section.stats.graph_update_dividers"); graph_dividers.setLayoutData(gridData); controls[13] = graph_dividers.getControl(); // control stuff enableStats.setAdditionalActionPerformer(new ChangeSelectionActionPerformer(controls)); return gStats; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTMP.java0000644000175000017500000000622410747145304027550 0ustar adrianadrian/* * File : ConfigSection*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; public class ConfigSectionTMP implements UISWTConfigSection { private final int REQUIRED_MODE = 0; public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } /* Name of section will be pulled from * ConfigView.section.configSectionGetName() */ public String configSectionGetName() { return "newsectionname"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 0; } public Composite configSectionCreate(final Composite parent) { GridData gridData; GridLayout layout; Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; cSection.setLayout(layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); if (userMode < REQUIRED_MODE) { Label label = new Label(cSection, SWT.WRAP); gridData = new GridData(); label.setLayoutData(gridData); final String[] modeKeys = { "ConfigView.section.mode.beginner", "ConfigView.section.mode.intermediate", "ConfigView.section.mode.advanced" }; String param1, param2; if (REQUIRED_MODE < modeKeys.length) param1 = MessageText.getString(modeKeys[REQUIRED_MODE]); else param1 = String.valueOf(REQUIRED_MODE); if (userMode < modeKeys.length) param2 = MessageText.getString(modeKeys[userMode]); else param2 = String.valueOf(userMode); label.setText(MessageText.getString("ConfigView.notAvailableForMode", new String[] { param1, param2 })); return cSection; } // Place SWT config items here return cSection; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferLAN.java0000644000175000017500000001033711256315674031234 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; public class ConfigSectionTransferLAN implements UISWTConfigSection { private final String CFG_PREFIX = "ConfigView.section.transfer.lan."; private final int REQUIRED_MODE = 2; public int maxUserMode() { return REQUIRED_MODE; } public String configSectionGetParentSection() { return ConfigSection.SECTION_TRANSFER; } public String configSectionGetName() { return "transfer.lan"; } public void configSectionSave() { } public void configSectionDelete() { } public Composite configSectionCreate(final Composite parent) { GridData gridData; Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); GridLayout advanced_layout = new GridLayout(); advanced_layout.numColumns = 2; cSection.setLayout(advanced_layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); if (userMode < REQUIRED_MODE) { Label label = new Label(cSection, SWT.WRAP); gridData = new GridData(); gridData.horizontalSpan = 2; label.setLayoutData(gridData); final String[] modeKeys = { "ConfigView.section.mode.beginner", "ConfigView.section.mode.intermediate", "ConfigView.section.mode.advanced" }; String param1, param2; if (REQUIRED_MODE < modeKeys.length) param1 = MessageText.getString(modeKeys[REQUIRED_MODE]); else param1 = String.valueOf(REQUIRED_MODE); if (userMode < modeKeys.length) param2 = MessageText.getString(modeKeys[userMode]); else param2 = String.valueOf(userMode); label.setText(MessageText.getString("ConfigView.notAvailableForMode", new String[] { param1, param2 } )); return cSection; } BooleanParameter enable_lan = new BooleanParameter( cSection, "LAN Speed Enabled", CFG_PREFIX + "enable" ); gridData = new GridData(); gridData.horizontalSpan = 2; enable_lan.setLayoutData(gridData); IntParameter lan_max_upload = new IntParameter( cSection, "Max LAN Upload Speed KBs" ); gridData = new GridData(); lan_max_upload.setLayoutData(gridData); Label llmux = new Label(cSection, SWT.NULL); Messages.setLanguageText( llmux, CFG_PREFIX + "uploadrate" ); IntParameter lan_max_download = new IntParameter( cSection, "Max LAN Download Speed KBs" ); gridData = new GridData(); lan_max_download.setLayoutData(gridData); Label llmdx = new Label(cSection, SWT.NULL); Messages.setLanguageText( llmdx, CFG_PREFIX + "downloadrate" ); enable_lan.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( new Parameter[]{ lan_max_upload, lan_max_download } )); enable_lan.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( new Control[]{ llmux, llmdx })); return cSection; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceDisplay.java0000644000175000017500000002437011263301326032330 0ustar adrianadrian/* * File : ConfigPanel*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import java.io.File; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.plugins.ui.config.ConfigSection; public class ConfigSectionInterfaceDisplay implements UISWTConfigSection { private final static String MSG_PREFIX = "ConfigView.section.style."; private final static String LBLKEY_PREFIX = "ConfigView.label."; public String configSectionGetParentSection() { return ConfigSection.SECTION_INTERFACE; } public String configSectionGetName() { return "display"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 2; } public Composite configSectionCreate(final Composite parent) { int userMode = COConfigurationManager.getIntParameter("User Mode"); boolean isAZ3 = COConfigurationManager.getStringParameter("ui").equals("az3"); // "Display" Sub-Section: // ---------------------- // Any Look & Feel settings that don't really change the way the user // normally interacts Label label; GridLayout layout; GridData gridData; Composite cLook = new Composite(parent, SWT.NULL); cLook.setLayoutData(new GridData(GridData.FILL_BOTH)); layout = new GridLayout(); layout.numColumns = 1; cLook.setLayout(layout); new BooleanParameter(cLook, "Show Download Basket", MSG_PREFIX + "showdownloadbasket"); if (!isAZ3) { new BooleanParameter(cLook, "IconBar.enabled", MSG_PREFIX + "showiconbar"); } Composite cStatusBar = new Composite(cLook, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 5; cStatusBar.setLayout(layout); cStatusBar.setLayoutData(new GridData()); label = new Label(cStatusBar, SWT.NULL); Messages.setLanguageText(label, MSG_PREFIX + "status"); new BooleanParameter(cStatusBar, "Status Area Show SR", MSG_PREFIX + "status.show_sr"); new BooleanParameter(cStatusBar, "Status Area Show NAT", MSG_PREFIX + "status.show_nat"); new BooleanParameter(cStatusBar, "Status Area Show DDB", MSG_PREFIX + "status.show_ddb"); new BooleanParameter(cStatusBar, "Status Area Show IPF", MSG_PREFIX + "status.show_ipf"); new BooleanParameter(cLook, "Add URL Silently", MSG_PREFIX + "addurlsilently"); new BooleanParameter(cLook, "add_torrents_silently", "ConfigView.section.interface.display.add_torrents_silently"); new BooleanParameter(cLook, "suppress_file_download_dialog", "ConfigView.section.interface.display.suppress.file.download.dialog"); new BooleanParameter(cLook, "show_torrents_menu", "Menu.show.torrent.menu"); if (Constants.isWindowsXP) { final Button enableXPStyle = new Button(cLook, SWT.CHECK); Messages.setLanguageText(enableXPStyle, MSG_PREFIX + "enableXPStyle"); boolean enabled = false; boolean valid = false; try { File f = new File(System.getProperty("java.home") + "\\bin\\javaw.exe.manifest"); if (f.exists()) { enabled = true; } f = FileUtil.getApplicationFile("javaw.exe.manifest"); if (f.exists()) { valid = true; } } catch (Exception e) { Debug.printStackTrace(e); valid = false; } enableXPStyle.setEnabled(valid); enableXPStyle.setSelection(enabled); enableXPStyle.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { //In case we enable the XP Style if (enableXPStyle.getSelection()) { try { File fDest = new File(System.getProperty("java.home") + "\\bin\\javaw.exe.manifest"); File fOrigin = new File("javaw.exe.manifest"); if (!fDest.exists() && fOrigin.exists()) { FileUtil.copyFile(fOrigin, fDest); } } catch (Exception e) { Debug.printStackTrace(e); } } else { try { File fDest = new File(System.getProperty("java.home") + "\\bin\\javaw.exe.manifest"); fDest.delete(); } catch (Exception e) { Debug.printStackTrace(e); } } } }); } if (Constants.isOSX) { new BooleanParameter(cLook, "enable_small_osx_fonts", MSG_PREFIX + "osx_small_fonts"); } if (userMode > 1) { new BooleanParameter(cLook, "GUI_SWT_bAlternateTablePainting", MSG_PREFIX + "alternateTablePainting"); } if (userMode > 0) { new BooleanParameter(cLook, "config.style.useSIUnits", MSG_PREFIX + "useSIUnits"); new BooleanParameter(cLook, "config.style.forceSIValues", MSG_PREFIX + "forceSIValues"); new BooleanParameter(cLook, "config.style.useUnitsRateBits", MSG_PREFIX + "useUnitsRateBits"); new BooleanParameter(cLook, "config.style.doNotUseGB", MSG_PREFIX + "doNotUseGB"); new BooleanParameter(cLook, "config.style.dataStatsOnly", MSG_PREFIX + "dataStatsOnly"); new BooleanParameter(cLook, "config.style.separateProtDataStats", MSG_PREFIX + "separateProtDataStats"); } if( userMode > 1 ) { final BooleanParameter fMoz = new BooleanParameter(cLook, "swt.forceMozilla",MSG_PREFIX + "forceMozilla"); Composite pArea = new Composite(cLook,SWT.NULL); pArea.setLayout(new GridLayout(3,false)); pArea.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Messages.setLanguageText(new Label(pArea,SWT.NONE), MSG_PREFIX+"xulRunnerPath"); final Parameter xulDir = new DirectoryParameter(pArea, "swt.xulRunner.path",""); fMoz.setAdditionalActionPerformer(new ChangeSelectionActionPerformer(xulDir.getControls(), false)); } Composite cArea = new Composite(cLook, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 2; cArea.setLayout(layout); cArea.setLayoutData(new GridData()); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, MSG_PREFIX + "guiUpdate"); int[] values = { 100, 250, 500, 1000, 2000, 5000, 10000, 15000 }; String[] labels = { "100 ms", "250 ms", "500 ms", "1 s", "2 s", "5 s", "10 s", "15 s" }; new IntListParameter(cArea, "GUI Refresh", 1000, labels, values); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, MSG_PREFIX + "inactiveUpdate"); gridData = new GridData(); IntParameter inactiveUpdate = new IntParameter(cArea, "Refresh When Inactive", 1, -1); inactiveUpdate.setLayoutData(gridData); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, MSG_PREFIX + "graphicsUpdate"); gridData = new GridData(); IntParameter graphicUpdate = new IntParameter(cArea, "Graphics Update", 1, -1); graphicUpdate.setLayoutData(gridData); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, MSG_PREFIX + "reOrderDelay"); gridData = new GridData(); IntParameter reorderDelay = new IntParameter(cArea, "ReOrder Delay"); reorderDelay.setLayoutData(gridData); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, MSG_PREFIX + "defaultSortOrder"); int[] sortOrderValues = { 0, 1, 2 }; String[] sortOrderLabels = { MessageText.getString(MSG_PREFIX + "defaultSortOrder.asc"), MessageText.getString(MSG_PREFIX + "defaultSortOrder.desc"), MessageText.getString(MSG_PREFIX + "defaultSortOrder.flip") }; new IntListParameter(cArea, "config.style.table.defaultSortOrder", sortOrderLabels, sortOrderValues); new BooleanParameter(cLook, "NameColumn.showProgramIcon", MSG_PREFIX + "showProgramIcon"); new BooleanParameter(cLook, "DND Always In Incomplete", MSG_PREFIX + "DNDalwaysInIncomplete"); new BooleanParameter(cLook, "MyTorrentsView.alwaysShowHeader", "ConfigView.label.alwaysShowLibraryHeader"); // Reuse the labels of the other menu actions. if (PlatformManagerFactory.getPlatformManager().hasCapability(PlatformManagerCapabilities.ShowFileInBrowser)) { BooleanParameter bp = new BooleanParameter(cLook, "MyTorrentsView.menu.show_parent_folder_enabled", MSG_PREFIX + "use_show_parent_folder"); Messages.setLanguageText(bp.getControl(), "ConfigView.section.style.use_show_parent_folder", new String[] { MessageText.getString("MyTorrentsView.menu.open_parent_folder"), MessageText.getString("MyTorrentsView.menu.explore"), }); if (Constants.isOSX) { new BooleanParameter(cLook, "FileBrowse.usePathFinder", MSG_PREFIX + "usePathFinder"); } } if ( Constants.isOSX_10_5_OrHigher ){ Composite cSWT = new Composite(cLook, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 2; cSWT.setLayout(layout); cSWT.setLayoutData(new GridData()); label = new Label(cSWT, SWT.NULL); label.setText( "SWT Library" ); String[] swtLibraries = { "carbon", "cocoa" }; new StringListParameter(cSWT, MSG_PREFIX + "swt.library.selection", swtLibraries, swtLibraries); } return cLook; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionProxy.java0000644000175000017500000002347310747145302032254 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; public class ConfigSectionConnectionProxy implements UISWTConfigSection { private final static String CFG_PREFIX = "ConfigView.section.proxy."; private final int REQUIRED_MODE = 2; public int maxUserMode() { return REQUIRED_MODE; } public String configSectionGetParentSection() { return ConfigSection.SECTION_CONNECTION; } public String configSectionGetName() { return "proxy"; } public void configSectionSave() { } public void configSectionDelete() { } public Composite configSectionCreate(final Composite parent) { GridData gridData; GridLayout layout; Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; cSection.setLayout(layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); if (userMode < REQUIRED_MODE) { Label label = new Label(cSection, SWT.WRAP); gridData = new GridData(); gridData.horizontalSpan = 2; label.setLayoutData(gridData); final String[] modeKeys = { "ConfigView.section.mode.beginner", "ConfigView.section.mode.intermediate", "ConfigView.section.mode.advanced" }; String param1, param2; if (REQUIRED_MODE < modeKeys.length) param1 = MessageText.getString(modeKeys[REQUIRED_MODE]); else param1 = String.valueOf(REQUIRED_MODE); if (userMode < modeKeys.length) param2 = MessageText.getString(modeKeys[userMode]); else param2 = String.valueOf(userMode); label.setText(MessageText.getString("ConfigView.notAvailableForMode", new String[] { param1, param2 } )); return cSection; } ////////////////////// PROXY GROUP ///////////////// Group gProxyTracker = new Group(cSection, SWT.NULL); Messages.setLanguageText(gProxyTracker, CFG_PREFIX + "group.tracker"); gridData = new GridData(); gridData.horizontalSpan = 2; gProxyTracker.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; gProxyTracker.setLayout(layout); final BooleanParameter enableProxy = new BooleanParameter(gProxyTracker, "Enable.Proxy", CFG_PREFIX + "enable_proxy"); gridData = new GridData(); gridData.horizontalSpan = 2; enableProxy.setLayoutData(gridData); final BooleanParameter enableSocks = new BooleanParameter(gProxyTracker, "Enable.SOCKS", CFG_PREFIX + "enable_socks"); gridData = new GridData(); gridData.horizontalSpan = 2; enableSocks.setLayoutData(gridData); Label lHost = new Label(gProxyTracker, SWT.NULL); Messages.setLanguageText(lHost, CFG_PREFIX + "host"); StringParameter pHost = new StringParameter(gProxyTracker, "Proxy.Host", ""); gridData = new GridData(); gridData.widthHint = 105; pHost.setLayoutData(gridData); Label lPort = new Label(gProxyTracker, SWT.NULL); Messages.setLanguageText(lPort, CFG_PREFIX + "port"); StringParameter pPort = new StringParameter(gProxyTracker, "Proxy.Port", ""); gridData = new GridData(); gridData.widthHint = 40; pPort.setLayoutData(gridData); Label lUser = new Label(gProxyTracker, SWT.NULL); Messages.setLanguageText(lUser, CFG_PREFIX + "username"); StringParameter pUser = new StringParameter(gProxyTracker, "Proxy.Username" ); gridData = new GridData(); gridData.widthHint = 105; pUser.setLayoutData(gridData); Label lPass = new Label(gProxyTracker, SWT.NULL); Messages.setLanguageText(lPass, CFG_PREFIX + "password"); StringParameter pPass = new StringParameter(gProxyTracker, "Proxy.Password", ""); gridData = new GridData(); gridData.widthHint = 105; pPass.setLayoutData(gridData); //////////////////////////////////////////////// Group gProxyPeer = new Group(cSection, SWT.NULL); Messages.setLanguageText(gProxyPeer, CFG_PREFIX + "group.peer"); gridData = new GridData(); gridData.horizontalSpan = 2; gProxyPeer.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; gProxyPeer.setLayout(layout); final BooleanParameter enableSocksPeer = new BooleanParameter(gProxyPeer, "Proxy.Data.Enable", CFG_PREFIX + "enable_socks.peer"); gridData = new GridData(); gridData.horizontalSpan = 2; enableSocksPeer.setLayoutData(gridData); final BooleanParameter socksPeerInform = new BooleanParameter(gProxyPeer, "Proxy.Data.SOCKS.inform", CFG_PREFIX + "peer.informtracker"); gridData = new GridData(); gridData.horizontalSpan = 2; socksPeerInform.setLayoutData(gridData); Label lSocksVersion = new Label(gProxyPeer, SWT.NULL); Messages.setLanguageText(lSocksVersion, CFG_PREFIX + "socks.version"); String[] socks_types = { "V4", "V4a", "V5" }; String dropLabels[] = new String[socks_types.length]; String dropValues[] = new String[socks_types.length]; for (int i = 0; i < socks_types.length; i++) { dropLabels[i] = socks_types[i]; dropValues[i] = socks_types[i]; } final StringListParameter socksType = new StringListParameter(gProxyPeer, "Proxy.Data.SOCKS.version", "V4", dropLabels, dropValues); final BooleanParameter sameConfig = new BooleanParameter(gProxyPeer, "Proxy.Data.Same", CFG_PREFIX + "peer.same"); gridData = new GridData(); gridData.horizontalSpan = 2; sameConfig.setLayoutData(gridData); Label lDataHost = new Label(gProxyPeer, SWT.NULL); Messages.setLanguageText(lDataHost, CFG_PREFIX + "host"); StringParameter pDataHost = new StringParameter(gProxyPeer, "Proxy.Data.Host", ""); gridData = new GridData(); gridData.widthHint = 105; pDataHost.setLayoutData(gridData); Label lDataPort = new Label(gProxyPeer, SWT.NULL); Messages.setLanguageText(lDataPort, CFG_PREFIX + "port"); StringParameter pDataPort = new StringParameter(gProxyPeer, "Proxy.Data.Port", ""); gridData = new GridData(); gridData.widthHint = 40; pDataPort.setLayoutData(gridData); Label lDataUser = new Label(gProxyPeer, SWT.NULL); Messages.setLanguageText(lDataUser, CFG_PREFIX + "username"); StringParameter pDataUser = new StringParameter(gProxyPeer, "Proxy.Data.Username"); gridData = new GridData(); gridData.widthHint = 105; pDataUser.setLayoutData(gridData); Label lDataPass = new Label(gProxyPeer, SWT.NULL); Messages.setLanguageText(lDataPass, CFG_PREFIX + "password"); StringParameter pDataPass = new StringParameter(gProxyPeer, "Proxy.Data.Password", ""); gridData = new GridData(); gridData.widthHint = 105; pDataPass.setLayoutData(gridData); final Control[] proxy_controls = new Control[] { enableSocks.getControl(), lHost, pHost.getControl(), lPort, pPort.getControl(), lUser, pUser.getControl(), lPass, pPass.getControl(), }; IAdditionalActionPerformer proxy_enabler = new GenericActionPerformer( new Control[] {}) { public void performAction() { for (int i = 0; i < proxy_controls.length; i++) { proxy_controls[i].setEnabled(enableProxy.isSelected()); } } }; final Control[] proxy_peer_controls = new Control[] { lDataHost, pDataHost.getControl(), lDataPort, pDataPort.getControl(), lDataUser, pDataUser.getControl(), lDataPass, pDataPass.getControl() }; final Control[] proxy_peer_details = new Control[] { sameConfig.getControl(), socksPeerInform.getControl(), socksType.getControl(), lSocksVersion }; IAdditionalActionPerformer proxy_peer_enabler = new GenericActionPerformer( new Control[] {}) { public void performAction() { for (int i = 0; i < proxy_peer_controls.length; i++) { proxy_peer_controls[i].setEnabled(enableSocksPeer.isSelected() && !sameConfig.isSelected()); } for (int i = 0; i < proxy_peer_details.length; i++) { proxy_peer_details[i].setEnabled(enableSocksPeer.isSelected()); } } }; enableSocks.setAdditionalActionPerformer(proxy_enabler); enableProxy.setAdditionalActionPerformer(proxy_enabler); enableSocksPeer.setAdditionalActionPerformer(proxy_peer_enabler); sameConfig.setAdditionalActionPerformer(proxy_peer_enabler); final BooleanParameter checkOnStart = new BooleanParameter(cSection, "Proxy.Check.On.Start", CFG_PREFIX + "check.on.start"); gridData = new GridData(); gridData.horizontalSpan = 2; checkOnStart.setLayoutData(gridData); Label label = new Label(cSection, SWT.WRAP); gridData = new GridData(); gridData.horizontalSpan = 2; label.setLayoutData(gridData); label.setText(MessageText.getString(CFG_PREFIX+"username.info" )); return cSection; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionLogging.java0000644000175000017500000003277111127403350030473 0ustar adrianadrian/* * File : ConfigPanel*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import java.io.PrintWriter; import java.io.StringWriter; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.logging.impl.FileLogging; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.stats.AzureusCoreStats; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.ui.config.ConfigSection; public class ConfigSectionLogging implements UISWTConfigSection { private static final LogIDs LOGID = LogIDs.GUI; private static final String CFG_PREFIX = "ConfigView.section.logging."; private static final int logFileSizes[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40, 50, 75, 100, 200, 300, 500 }; public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } public String configSectionGetName() { return "logging"; } public void configSectionSave() { } public void configSectionDelete() { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage("openFolderButton"); } public int maxUserMode() { return 2; } public Composite configSectionCreate(final Composite parent) { ImageLoader imageLoader = ImageLoader.getInstance(); Image imgOpenFolder = imageLoader.getImage("openFolderButton"); GridData gridData; GridLayout layout; Composite gLogging = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gLogging.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; gLogging.setLayout(layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); BooleanParameter enable_logger = new BooleanParameter(gLogging, "Logger.Enabled", CFG_PREFIX + "loggerenable"); gridData = new GridData(); gridData.horizontalSpan = 2; enable_logger.setLayoutData(gridData); // row final BooleanParameter enableLogging = new BooleanParameter(gLogging, "Logging Enable", CFG_PREFIX + "enable"); gridData = new GridData(); gridData.horizontalSpan = 2; enableLogging.setLayoutData(gridData); Composite cArea = new Composite(gLogging, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 3; cArea.setLayout(layout); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; cArea.setLayoutData(gridData); // row Label lStatsPath = new Label(cArea, SWT.NULL); Messages.setLanguageText(lStatsPath, CFG_PREFIX + "logdir"); //$NON-NLS-1$ gridData = new GridData(); gridData.widthHint = 150; final StringParameter pathParameter = new StringParameter(cArea, "Logging Dir"); //$NON-NLS-1$ //$NON-NLS-2$ pathParameter.setLayoutData(gridData); Button browse = new Button(cArea, SWT.PUSH); browse.setImage(imgOpenFolder); imgOpenFolder.setBackground(browse.getBackground()); browse.setToolTipText(MessageText.getString("ConfigView.button.browse")); browse.addListener(SWT.Selection, new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event event) { DirectoryDialog dialog = new DirectoryDialog(parent.getShell(), SWT.APPLICATION_MODAL); dialog.setFilterPath(pathParameter.getValue()); dialog.setText(MessageText.getString(CFG_PREFIX + "choosedefaultsavepath")); //$NON-NLS-1$ String path = dialog.open(); if (path != null) { pathParameter.setValue(path); } } }); Label lMaxLog = new Label(cArea, SWT.NULL); Messages.setLanguageText(lMaxLog, CFG_PREFIX + "maxsize"); final String lmLabels[] = new String[logFileSizes.length]; final int lmValues[] = new int[logFileSizes.length]; for (int i = 0; i < logFileSizes.length; i++) { int num = logFileSizes[i]; lmLabels[i] = " " + num + " MB"; lmValues[i] = num; } IntListParameter paramMaxSize = new IntListParameter(cArea, "Logging Max Size", lmLabels, lmValues); gridData = new GridData(); gridData.horizontalSpan = 2; paramMaxSize.setLayoutData(gridData); if(userMode > 1) { Label timeStampLbl = new Label(cArea, SWT.NULL); Messages.setLanguageText(timeStampLbl, CFG_PREFIX+"timestamp"); timeStampLbl.setLayoutData(new GridData()); StringParameter timeStamp = new StringParameter(cArea,"Logging Timestamp"); gridData = new GridData(); gridData.horizontalSpan = 2; gridData.widthHint = 150; timeStamp.setLayoutData(gridData); } /** FileLogging filter, consisting of a List of types (info, warning, error) * and a checkbox Table of component IDs. */ final String sFilterPrefix = CFG_PREFIX + "filter"; Group gLogIDs = new Group(gLogging, SWT.NULL); Messages.setLanguageText(gLogIDs, sFilterPrefix); layout = new GridLayout(); layout.numColumns = 2; gLogIDs.setLayout(layout); gridData = new GridData(SWT.BEGINNING, SWT.BEGINNING, true, true); gridData.horizontalSpan = 2; gLogIDs.setLayoutData(gridData); final List listLogTypes = new List(gLogIDs, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL); gridData = new GridData(SWT.NULL, SWT.BEGINNING, false, false); listLogTypes.setLayoutData(gridData); final int[] logTypes = { LogEvent.LT_INFORMATION, LogEvent.LT_WARNING, LogEvent.LT_ERROR }; for (int i = 0; i < logTypes.length; i++) listLogTypes.add(MessageText.getString(CFG_PREFIX + "log" + i + "type")); listLogTypes.select(0); final LogIDs[] logIDs = FileLogging.configurableLOGIDs; //Arrays.sort(logIDs); final Table tableLogIDs = new Table(gLogIDs, SWT.CHECK | SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION); gridData = new GridData(GridData.FILL_BOTH); tableLogIDs.setLayoutData(gridData); tableLogIDs.setLinesVisible (false); tableLogIDs.setHeaderVisible(false); TableColumn column = new TableColumn(tableLogIDs, SWT.NONE); for (int i = 0; i < logIDs.length; i++) { TableItem item = new TableItem(tableLogIDs, SWT.NULL); item.setText(0, MessageText.getString(sFilterPrefix + "." + logIDs[i], logIDs[i].toString())); item.setData(logIDs[i]); boolean checked = COConfigurationManager.getBooleanParameter("bLog." + logTypes[0] + "." + logIDs[i], true); item.setChecked(checked); } column.pack(); // Update table when list selection changes listLogTypes.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int index = listLogTypes.getSelectionIndex(); if (index < 0 || index >= logTypes.length) return; TableItem[] items = tableLogIDs.getItems(); for (int i = 0; i < items.length; i++) { boolean checked = COConfigurationManager.getBooleanParameter( "bLog." + logTypes[index] + "." + items[i].getData(), true); items[i].setChecked(checked); } } }); // Save config when checkbox is clicked tableLogIDs.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (e.detail != SWT.CHECK) return; int index = listLogTypes.getSelectionIndex(); if (index < 0 || index >= logTypes.length) return; TableItem item = (TableItem) e.item; COConfigurationManager.setParameter("bLog." + logTypes[index] + "." + item.getData(), item.getChecked()); } }); final Control[] controls_main = { cArea, gLogIDs }; final ChangeSelectionActionPerformer perf2 = new ChangeSelectionActionPerformer( controls_main ); enableLogging.setAdditionalActionPerformer( perf2 ); enable_logger.setAdditionalActionPerformer( new IAdditionalActionPerformer() { ChangeSelectionActionPerformer p1 = new ChangeSelectionActionPerformer(new Control[] {enableLogging.getControl() } ); public void performAction() { p1.performAction(); } public void setSelected(boolean selected) { p1.setSelected( selected ); if( !selected && enableLogging.isSelected() ) enableLogging.setSelected( false ); } public void setIntValue(int value) { /*nothing*/ } public void setStringValue(String value) { /*nothing*/ } } ); /* BooleanParameter udp_transport = new BooleanParameter(gLogging, "Logging Enable UDP Transport", CFG_PREFIX + "udptransport"); gridData = new GridData(); gridData.horizontalSpan = 2; udp_transport.setLayoutData(gridData); */ // network diagnostics Label generate_net_info = new Label(gLogging, SWT.NULL); Messages.setLanguageText(generate_net_info, CFG_PREFIX + "netinfo"); Button generate_net_button = new Button(gLogging, SWT.PUSH); Messages.setLanguageText(generate_net_button, CFG_PREFIX + "generatediagnostics"); generate_net_button.addListener( SWT.Selection, new Listener() { public void handleEvent(Event event) { new AEThread2("GenerateNetDiag", true) { public void run() { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter( sw ); IndentWriter iw = new IndentWriter( pw ); NetworkAdmin admin = NetworkAdmin.getSingleton(); admin.generateDiagnostics( iw ); pw.close(); final String info = sw.toString(); Logger.log( new LogEvent(LOGID, "Network Info:\n" + info)); Utils.execSWTThread( new Runnable() { public void run() { ClipboardCopy.copyToClipBoard( info ); } }); } }.start(); } }); // stats Label generate_stats_info = new Label(gLogging, SWT.NULL); Messages.setLanguageText(generate_stats_info, CFG_PREFIX + "statsinfo"); Button generate_stats_button = new Button(gLogging, SWT.PUSH); Messages.setLanguageText(generate_stats_button, CFG_PREFIX + "generatediagnostics"); generate_stats_button.addListener( SWT.Selection, new Listener() { public void handleEvent(Event event) { java.util.Set types = new HashSet(); types.add( AzureusCoreStats.ST_ALL ); Map reply = AzureusCoreStats.getStats( types ); Iterator it = reply.entrySet().iterator(); StringBuffer buffer = new StringBuffer(16000); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); buffer.append( entry.getKey() + " -> " + entry.getValue() + "\r\n" ); } String str = buffer.toString(); ClipboardCopy.copyToClipBoard( str ); Logger.log( new LogEvent(LOGID, "Stats Info:\n" + str)); } }); // diagnostics Label generate_info = new Label(gLogging, SWT.NULL); Messages.setLanguageText(generate_info, CFG_PREFIX + "generatediagnostics.info"); Button generate_button = new Button(gLogging, SWT.PUSH); Messages.setLanguageText(generate_button, CFG_PREFIX + "generatediagnostics"); generate_button.addListener( SWT.Selection, new Listener() { public void handleEvent(Event event) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter( sw ); AEDiagnostics.generateEvidence( pw ); pw.close(); String evidence = sw.toString(); ClipboardCopy.copyToClipBoard( evidence ); Logger.log( new LogEvent(LOGID, "Evidence Generation:\n" + evidence)); } }); return gLogging; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java0000644000175000017500000003237711256315674031224 0ustar adrianadrian/* * File : ConfigPanelServer.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.PEPeerSource; import org.gudy.azureus2.core3.util.AENetworkClassifier; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.components.LinkLabel; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.Cursors; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; public class ConfigSectionConnection implements UISWTConfigSection { private static final String CFG_PREFIX = "ConfigView.section.connection."; public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } public String configSectionGetName() { return ConfigSection.SECTION_CONNECTION; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 2; } public Composite configSectionCreate(final Composite parent) { Label label; GridData gridData; GridLayout layout; Composite cMiniArea; int userMode = COConfigurationManager.getIntParameter("User Mode"); Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); layout = new GridLayout(); cSection.setLayout(layout); /////////////////////// cMiniArea = new Composite(cSection, SWT.NULL); layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; layout.marginWidth = 0; cMiniArea.setLayout(layout); gridData = new GridData(GridData.FILL_HORIZONTAL); cMiniArea.setLayoutData(gridData); final boolean separate_ports = userMode > 1 || COConfigurationManager.getIntParameter( "TCP.Listen.Port" ) != COConfigurationManager.getIntParameter( "UDP.Listen.Port" ); label = new Label(cMiniArea, SWT.NULL); Messages.setLanguageText(label, separate_ports?"ConfigView.label.tcplistenport":"ConfigView.label.serverport"); gridData = new GridData(); label.setLayoutData(gridData); final IntParameter tcplisten = new IntParameter(cMiniArea, "TCP.Listen.Port", 1, 65535); gridData = new GridData(); tcplisten.setLayoutData(gridData); tcplisten.addChangeListener(new ParameterChangeAdapter() { public void intParameterChanging(Parameter p, int toValue) { if (toValue == 6880) { toValue = 6881; tcplisten.setValue(toValue); } if (!separate_ports) { COConfigurationManager.setParameter("UDP.Listen.Port", toValue); COConfigurationManager.setParameter("UDP.NonData.Listen.Port", toValue); } } }); if ( separate_ports ){ label = new Label(cMiniArea, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.udplistenport"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); label.setLayoutData(gridData); final IntParameter udp_listen = new IntParameter(cMiniArea, "UDP.Listen.Port", 1, 65535); gridData = new GridData(); udp_listen.setLayoutData(gridData); final boolean MULTI_UDP = COConfigurationManager.ENABLE_MULTIPLE_UDP_PORTS && userMode > 1; udp_listen.addChangeListener(new ParameterChangeAdapter() { public void intParameterChanging(Parameter p, int toValue) { if (toValue == 6880) { toValue = 6881; udp_listen.setValue(toValue); } if (!MULTI_UDP) { COConfigurationManager.setParameter("UDP.NonData.Listen.Port", toValue); } } }); if ( MULTI_UDP ){ Composite cNonDataUDPArea = new Composite(cSection, SWT.NULL); layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; layout.marginWidth = 0; cNonDataUDPArea.setLayout(layout); gridData = new GridData(GridData.FILL_HORIZONTAL); cNonDataUDPArea.setLayoutData(gridData); final BooleanParameter commonUDP = new BooleanParameter(cNonDataUDPArea, "UDP.NonData.Listen.Port.Same", CFG_PREFIX + "nondata.udp.same"); gridData = new GridData(); gridData.horizontalIndent = 16; commonUDP.setLayoutData( gridData ); final IntParameter non_data_udp_listen = new IntParameter( cNonDataUDPArea, "UDP.NonData.Listen.Port"); non_data_udp_listen.addChangeListener( new ParameterChangeAdapter() { public void intParameterChanging(Parameter p, int toValue) { if (toValue == 6880) { toValue = 6881; non_data_udp_listen.setValue(toValue); } } }); udp_listen.addChangeListener( new ParameterChangeAdapter() { public void parameterChanged(Parameter p, boolean caused_internally) { if ( commonUDP.isSelected()){ int udp_listen_port = udp_listen.getValue(); if ( udp_listen_port != 6880 ){ COConfigurationManager.setParameter( "UDP.NonData.Listen.Port", udp_listen_port ); non_data_udp_listen.setValue( udp_listen_port ); } } } }); gridData = new GridData(); non_data_udp_listen.setLayoutData( gridData ); commonUDP.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( non_data_udp_listen.getControls(), true )); commonUDP.addChangeListener( new ParameterChangeAdapter() { public void parameterChanged( Parameter p, boolean caused_internally) { if ( commonUDP.isSelected()){ int udp_listen_port = COConfigurationManager.getIntParameter("UDP.Listen.Port"); if ( COConfigurationManager.getIntParameter("UDP.NonData.Listen.Port") != udp_listen_port ){ COConfigurationManager.setParameter( "UDP.NonData.Listen.Port", udp_listen_port ); non_data_udp_listen.setValue( udp_listen_port ); } } } }); final BooleanParameter enable_tcp = new BooleanParameter(cNonDataUDPArea, "TCP.Listen.Port.Enable", CFG_PREFIX + "tcp.enable"); gridData = new GridData(); enable_tcp.setLayoutData( gridData ); label = new Label(cNonDataUDPArea, SWT.NULL); final BooleanParameter enable_udp = new BooleanParameter(cNonDataUDPArea, "UDP.Listen.Port.Enable", CFG_PREFIX + "udp.enable"); gridData = new GridData(); enable_udp.setLayoutData( gridData ); label = new Label(cNonDataUDPArea, SWT.NULL); enable_tcp.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( tcplisten )); enable_udp.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( udp_listen )); } } if ( userMode > 1 ){ final BooleanParameter prefer_udp = new BooleanParameter(cMiniArea, "peercontrol.prefer.udp", CFG_PREFIX + "prefer.udp"); gridData = new GridData(); prefer_udp.setLayoutData( gridData ); label = new Label(cMiniArea, SWT.NULL); } if (userMode < 2) { // wiki link label = new Label(cSection, SWT.NULL); gridData = new GridData(); label.setLayoutData(gridData); label.setText(MessageText.getString("Utils.link.visit") + ":"); final Label linkLabel = new Label(cSection, SWT.NULL); linkLabel.setText(MessageText .getString(CFG_PREFIX + "serverport.wiki")); linkLabel .setData("http://www.azureuswiki.com/index.php?title=Why_ports_like_6881_are_no_good_choice"); linkLabel.setCursor(Cursors.handCursor); linkLabel.setForeground(Colors.blue); gridData = new GridData(); linkLabel.setLayoutData(gridData); linkLabel.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } public void mouseDown(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } }); } if (userMode > 0) { /////////////////////// HTTP /////////////////// Group http_group = new Group(cSection, SWT.NULL); Messages.setLanguageText(http_group,CFG_PREFIX + "group.http"); GridLayout http_layout = new GridLayout(); http_layout.numColumns = 2; http_group.setLayout(http_layout); gridData = new GridData(GridData.FILL_HORIZONTAL); http_group.setLayoutData(gridData); label = new Label(http_group, SWT.WRAP); Messages.setLanguageText(label, CFG_PREFIX + "group.http.info"); new LinkLabel( http_group, "ConfigView.label.please.visit.here", "http://www.azureuswiki.com/index.php?title=HTTP_Seeding"); final BooleanParameter enable_http = new BooleanParameter(http_group, "HTTP.Data.Listen.Port.Enable", CFG_PREFIX + "http.enable"); gridData = new GridData(); gridData.horizontalSpan = 2; enable_http.setLayoutData( gridData ); label = new Label(http_group, SWT.NULL); Messages.setLanguageText(label, CFG_PREFIX + "http.port" ); IntParameter http_port = new IntParameter(http_group, "HTTP.Data.Listen.Port"); gridData = new GridData(); http_port.setLayoutData( gridData ); label = new Label(http_group, SWT.NULL); Messages.setLanguageText(label, CFG_PREFIX + "http.portoverride" ); IntParameter http_port_override = new IntParameter(http_group, "HTTP.Data.Listen.Port.Override"); gridData = new GridData(); http_port_override.setLayoutData( gridData ); enable_http.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( http_port )); enable_http.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( http_port_override )); } if (userMode > 0) { /////////////////////// PEER SOURCES GROUP /////////////////// Group peer_sources_group = new Group(cSection, SWT.NULL); Messages.setLanguageText(peer_sources_group, CFG_PREFIX + "group.peersources"); GridLayout peer_sources_layout = new GridLayout(); peer_sources_group.setLayout(peer_sources_layout); gridData = new GridData(GridData.FILL_HORIZONTAL); peer_sources_group.setLayoutData(gridData); label = new Label(peer_sources_group, SWT.WRAP); Messages.setLanguageText(label, CFG_PREFIX + "group.peersources.info"); gridData = new GridData(); label.setLayoutData(gridData); for (int i = 0; i < PEPeerSource.PS_SOURCES.length; i++) { String p = PEPeerSource.PS_SOURCES[i]; String config_name = "Peer Source Selection Default." + p; String msg_text = CFG_PREFIX + "peersource." + p; BooleanParameter peer_source = new BooleanParameter(peer_sources_group, config_name, msg_text); gridData = new GridData(); peer_source.setLayoutData(gridData); } ////////////////////// if (userMode > 1) { /////////////////////// NETWORKS GROUP /////////////////// Group networks_group = new Group(cSection, SWT.NULL); Messages.setLanguageText(networks_group, CFG_PREFIX + "group.networks"); GridLayout networks_layout = new GridLayout(); networks_group.setLayout(networks_layout); gridData = new GridData(GridData.FILL_HORIZONTAL); networks_group.setLayoutData(gridData); label = new Label(networks_group, SWT.NULL); Messages.setLanguageText(label, CFG_PREFIX + "group.networks.info"); gridData = new GridData(); label.setLayoutData(gridData); for (int i = 0; i < AENetworkClassifier.AT_NETWORKS.length; i++) { String nn = AENetworkClassifier.AT_NETWORKS[i]; String config_name = "Network Selection Default." + nn; String msg_text = CFG_PREFIX + "networks." + nn; BooleanParameter network = new BooleanParameter(networks_group, config_name, msg_text); gridData = new GridData(); network.setLayoutData(gridData); } label = new Label(networks_group, SWT.NULL); gridData = new GridData(); label.setLayoutData(gridData); BooleanParameter network_prompt = new BooleanParameter(networks_group, "Network Selection Prompt", CFG_PREFIX + "networks.prompt"); gridData = new GridData(); network_prompt.setLayoutData(gridData); } // end userMode>1 } // end userMode>0 /////////////////////// return cSection; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFilePerformance.java0000644000175000017500000002546311256315674032164 0ustar adrianadrian/* * File : ConfigSection*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; public class ConfigSectionFilePerformance implements UISWTConfigSection { public String configSectionGetParentSection() { return ConfigSection.SECTION_FILES; } /* Name of section will be pulled from * ConfigView.section.configSectionGetName() */ public String configSectionGetName() { return "file.perf"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 2; } public Composite configSectionCreate(final Composite parent) { GridData gridData; GridLayout layout; Label label; int userMode = COConfigurationManager.getIntParameter("User Mode"); Composite cSection = new Composite(parent, SWT.NULL); layout = new GridLayout(); layout.numColumns = 3; cSection.setLayout(layout); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan = 2; cSection.setLayoutData(gridData); label = new Label(cSection, SWT.WRAP); Messages.setLanguageText(label, "ConfigView.section.file.perf.explain"); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; label.setLayoutData( gridData ); // diskmanager.friendly.hashchecking final BooleanParameter friendly_hashchecking = new BooleanParameter(cSection, "diskmanager.friendly.hashchecking", "ConfigView.section.file.friendly.hashchecking"); gridData = new GridData(); gridData.horizontalSpan = 3; friendly_hashchecking.setLayoutData(gridData); // diskmanager.friendly.hashchecking final BooleanParameter check_smallest = new BooleanParameter(cSection, "diskmanager.hashchecking.smallestfirst", "ConfigView.section.file.hashchecking.smallestfirst"); gridData = new GridData(); gridData.horizontalSpan = 3; check_smallest.setLayoutData(gridData); // diskmanager.perf.cache.enable final BooleanParameter disk_cache = new BooleanParameter(cSection, "diskmanager.perf.cache.enable", "ConfigView.section.file.perf.cache.enable"); gridData = new GridData(); gridData.horizontalSpan = 3; disk_cache.setLayoutData(gridData); // diskmanager.perf.cache.size long max_mem_bytes = Runtime.getRuntime().maxMemory(); long mb_1 = 1*1024*1024; long mb_32 = 32*mb_1; Label cache_size_label = new Label(cSection, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); cache_size_label.setLayoutData(gridData); // XXX Changed "DisplayFormatters.getUnit(DisplayFormatters.UNIT_MB)" // to getUnitBase10 for the release, since the # is in MB. Messages.setLanguageText(cache_size_label, "ConfigView.section.file.perf.cache.size", new String[] { DisplayFormatters.getUnitBase10(DisplayFormatters.UNIT_MB) }); IntParameter cache_size = new IntParameter(cSection, "diskmanager.perf.cache.size", 1, COConfigurationManager.CONFIG_CACHE_SIZE_MAX_MB); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); cache_size.setLayoutData( gridData ); Label cache_explain_label = new Label(cSection, SWT.WRAP); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); gridData.widthHint = 300; cache_explain_label.setLayoutData(gridData); Messages.setLanguageText( cache_explain_label, "ConfigView.section.file.perf.cache.size.explain", new String[]{ DisplayFormatters.formatByteCountToKiBEtc(mb_32), DisplayFormatters.formatByteCountToKiBEtc(max_mem_bytes), Constants.AZUREUS_WIKI }); if(userMode > 0) { // don't cache smaller than Label cnst_label = new Label(cSection, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); cnst_label.setLayoutData(gridData); // XXX Changed "DisplayFormatters.getUnit(DisplayFormatters.UNIT_KB)" to // getUnitBase10 for the release, since the # is stored in KB. Messages.setLanguageText(cnst_label, "ConfigView.section.file.perf.cache.notsmallerthan", new String[] { DisplayFormatters.getUnitBase10(DisplayFormatters.UNIT_KB) }); IntParameter cache_not_smaller_than= new IntParameter(cSection, "diskmanager.perf.cache.notsmallerthan" ); cache_not_smaller_than.setMinimumValue(0); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); cache_not_smaller_than.setLayoutData( gridData ); // diskmanager.perf.cache.enable.read final BooleanParameter disk_cache_read = new BooleanParameter(cSection, "diskmanager.perf.cache.enable.read", "ConfigView.section.file.perf.cache.enable.read"); gridData = new GridData(); gridData.horizontalSpan = 3; disk_cache_read.setLayoutData(gridData); // diskmanager.perf.cache.enable.write final BooleanParameter disk_cache_write = new BooleanParameter(cSection, "diskmanager.perf.cache.enable.write", "ConfigView.section.file.perf.cache.enable.write"); gridData = new GridData(); gridData.horizontalSpan = 3; disk_cache_write.setLayoutData(gridData); // diskmanager.perf.cache.flushpieces final BooleanParameter disk_cache_flush = new BooleanParameter(cSection, "diskmanager.perf.cache.flushpieces", "ConfigView.section.file.perf.cache.flushpieces"); gridData = new GridData(); gridData.horizontalSpan = 3; disk_cache_flush.setLayoutData(gridData); // diskmanager.perf.cache.trace final BooleanParameter disk_cache_trace = new BooleanParameter(cSection, "diskmanager.perf.cache.trace", "ConfigView.section.file.perf.cache.trace"); gridData = new GridData(); gridData.horizontalSpan = 3; disk_cache_trace.setLayoutData(gridData); disk_cache.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( new Control[]{ cnst_label })); disk_cache.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( cache_not_smaller_than.getControls() )); disk_cache.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( disk_cache_trace.getControls() )); disk_cache.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( disk_cache_read.getControls() )); disk_cache.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( disk_cache_write.getControls() )); disk_cache.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( disk_cache_flush.getControls() )); disk_cache.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( disk_cache_trace.getControls() )); if(userMode > 1) { // Max Open Files label = new Label(cSection, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.section.file.max_open_files"); IntParameter file_max_open = new IntParameter(cSection, "File Max Open"); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); file_max_open.setLayoutData( gridData ); label = new Label(cSection, SWT.WRAP); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); gridData.widthHint = 300; label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.section.file.max_open_files.explain"); // write mb limit label = new Label(cSection, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); String label_text = MessageText.getString( "ConfigView.section.file.writemblimit", new String[] { DisplayFormatters.getUnitBase10(DisplayFormatters.UNIT_MB) }); label.setText(label_text); IntParameter write_block_limit = new IntParameter(cSection, "diskmanager.perf.write.maxmb" ); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); write_block_limit.setLayoutData( gridData ); label = new Label(cSection, SWT.WRAP); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); gridData.widthHint = 300; label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.section.file.writemblimit.explain"); // read mb limit label = new Label(cSection, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); label_text = MessageText.getString( "ConfigView.section.file.readmblimit", new String[] { DisplayFormatters.getUnitBase10(DisplayFormatters.UNIT_MB) }); label.setText(label_text); IntParameter check_piece_limit = new IntParameter(cSection, "diskmanager.perf.read.maxmb" ); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); check_piece_limit.setLayoutData( gridData ); label = new Label(cSection, SWT.WRAP); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); gridData.widthHint = 300; label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.section.file.readmblimit.explain"); } } disk_cache.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( cache_size.getControls() )); disk_cache.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( new Control[]{ cache_size_label, cache_explain_label })); return cSection; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTracker.java0000644000175000017500000000424511172266532030504 0ustar adrianadrian/* * File : ConfigPanel*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import com.aelitis.azureus.core.*; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; public class ConfigSectionTracker implements UISWTConfigSection { public ConfigSectionTracker() { } public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } public String configSectionGetName() { return "tracker"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 0; } public Composite configSectionCreate(final Composite parent) { GridData gridData; GridLayout layout; // main tab set up Composite gMainTab = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gMainTab.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; gMainTab.setLayout(layout); // MAIN TAB DATA return gMainTab; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java0000644000175000017500000002520711300652044032625 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.impl.ConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.plugins.platform.PlatformManagerException; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.components.LinkLabel; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; public class ConfigSectionConnectionAdvanced implements UISWTConfigSection { private final String CFG_PREFIX = "ConfigView.section.connection.advanced."; private final int REQUIRED_MODE = 2; public int maxUserMode() { return REQUIRED_MODE; } public String configSectionGetParentSection() { return ConfigSection.SECTION_CONNECTION; } public String configSectionGetName() { return "connection.advanced"; } public void configSectionSave() { } public void configSectionDelete() { } public Composite configSectionCreate(final Composite parent) { GridData gridData; Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL + GridData.VERTICAL_ALIGN_FILL); cSection.setLayoutData(gridData); GridLayout advanced_layout = new GridLayout(); cSection.setLayout(advanced_layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); if (userMode < REQUIRED_MODE) { Label label = new Label(cSection, SWT.WRAP); gridData = new GridData(); label.setLayoutData(gridData); final String[] modeKeys = { "ConfigView.section.mode.beginner", "ConfigView.section.mode.intermediate", "ConfigView.section.mode.advanced" }; String param1, param2; if (REQUIRED_MODE < modeKeys.length) param1 = MessageText.getString(modeKeys[REQUIRED_MODE]); else param1 = String.valueOf(REQUIRED_MODE); if (userMode < modeKeys.length) param2 = MessageText.getString(modeKeys[userMode]); else param2 = String.valueOf(userMode); label.setText(MessageText.getString("ConfigView.notAvailableForMode", new String[] { param1, param2 } )); return cSection; } new LinkLabel(cSection, gridData, CFG_PREFIX + "info.link", MessageText.getString(CFG_PREFIX + "url")); /////////////////////// ADVANCED SOCKET SETTINGS GROUP ////////// Group gSocket = new Group(cSection, SWT.NULL); Messages.setLanguageText(gSocket, CFG_PREFIX + "socket.group"); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.FILL_HORIZONTAL); gSocket.setLayoutData(gridData); GridLayout glayout = new GridLayout(); glayout.numColumns = 2; gSocket.setLayout(glayout); // max simultaneous Label lmaxout = new Label(gSocket, SWT.NULL); Messages.setLanguageText(lmaxout, "ConfigView.section.connection.network.max.simultaneous.connect.attempts"); gridData = new GridData(); lmaxout.setLayoutData( gridData ); IntParameter max_connects = new IntParameter(gSocket, "network.max.simultaneous.connect.attempts", 1, 100); gridData = new GridData(); max_connects.setLayoutData(gridData); // // max pending Label lmaxpout = new Label(gSocket, SWT.NULL); Messages.setLanguageText(lmaxpout, "ConfigView.section.connection.network.max.outstanding.connect.attempts"); gridData = new GridData(); lmaxpout.setLayoutData( gridData ); IntParameter max_pending_connects = new IntParameter(gSocket, "network.tcp.max.connections.outstanding", 1, 65536 ); gridData = new GridData(); max_pending_connects.setLayoutData(gridData); // bind ip Label lbind = new Label(gSocket, SWT.NULL); Messages.setLanguageText(lbind, "ConfigView.label.bindip" ); lbind.setLayoutData(new GridData()); StringParameter bindip = new StringParameter(gSocket, "Bind IP", "", false); gridData = new GridData(); gridData.widthHint = 100; bindip.setLayoutData(gridData); Text lbind2 = new Text(gSocket, SWT.READ_ONLY | SWT.MULTI); lbind2.setTabs(8); Messages.setLanguageText( lbind2, "ConfigView.label.bindip.details", new String[] {NetworkAdmin.getSingleton().getNetworkInterfacesAsString() }); gridData = new GridData(); gridData.horizontalSpan = 2; lbind2.setLayoutData(gridData); Label lpbind = new Label(gSocket, SWT.NULL); Messages.setLanguageText(lpbind, CFG_PREFIX + "bind_port"); final IntParameter port_bind = new IntParameter(gSocket, "network.bind.local.port", 0, 65535); gridData = new GridData(); port_bind.setLayoutData(gridData); Label lmtu = new Label(gSocket, SWT.NULL); Messages.setLanguageText(lmtu, CFG_PREFIX + "mtu"); final IntParameter mtu_size = new IntParameter(gSocket,"network.tcp.mtu.size"); mtu_size.setMaximumValue(512 * 1024); gridData = new GridData(); mtu_size.setLayoutData(gridData); Label lsend = new Label(gSocket, SWT.NULL); Messages.setLanguageText(lsend, CFG_PREFIX + "SO_SNDBUF"); final IntParameter SO_SNDBUF = new IntParameter(gSocket, "network.tcp.socket.SO_SNDBUF"); gridData = new GridData(); SO_SNDBUF.setLayoutData(gridData); Label lreceiv = new Label(gSocket, SWT.NULL); Messages.setLanguageText(lreceiv, CFG_PREFIX + "SO_RCVBUF"); final IntParameter SO_RCVBUF = new IntParameter(gSocket, "network.tcp.socket.SO_RCVBUF"); gridData = new GridData(); SO_RCVBUF.setLayoutData(gridData); Label ltos = new Label(gSocket, SWT.NULL); Messages.setLanguageText(ltos, CFG_PREFIX + "IPDiffServ"); final StringParameter IPDiffServ = new StringParameter(gSocket, "network.tcp.socket.IPDiffServ"); gridData = new GridData(); gridData.widthHint = 100; IPDiffServ.setLayoutData(gridData); //do simple input verification, and registry key setting for TOS field IPDiffServ.addChangeListener(new ParameterChangeAdapter() { final Color obg = IPDiffServ.getControl().getBackground(); final Color ofg = IPDiffServ.getControl().getForeground(); public void parameterChanged(Parameter p, boolean caused_internally) { String raw = IPDiffServ.getValue(); int value = -1; try { value = Integer.decode(raw).intValue(); } catch (Throwable t) { } if (value < 0 || value > 255) { //invalid or no value entered ConfigurationManager.getInstance().removeParameter( "network.tcp.socket.IPDiffServ"); if (raw != null && raw.length() > 0) { //error state IPDiffServ.getControl().setBackground(Colors.red); IPDiffServ.getControl().setForeground(Colors.white); } else { //no value state IPDiffServ.getControl().setBackground(obg); IPDiffServ.getControl().setForeground(ofg); } enableTOSRegistrySetting(false); //disable registry setting if necessary } else { //passes test IPDiffServ.getControl().setBackground(obg); IPDiffServ.getControl().setForeground(ofg); enableTOSRegistrySetting(true); //enable registry setting if necessary } } }); // read select Label lreadsel = new Label(gSocket, SWT.NULL); Messages.setLanguageText(lreadsel, CFG_PREFIX + "read_select", new String[]{ String.valueOf( COConfigurationManager.getDefault("network.tcp.read.select.time"))}); final IntParameter read_select = new IntParameter(gSocket, "network.tcp.read.select.time", 10, 250); gridData = new GridData(); read_select.setLayoutData(gridData); Label lreadselmin = new Label(gSocket, SWT.NULL); Messages.setLanguageText(lreadselmin, CFG_PREFIX + "read_select_min", new String[]{ String.valueOf( COConfigurationManager.getDefault("network.tcp.read.select.min.time"))}); final IntParameter read_select_min = new IntParameter(gSocket, "network.tcp.read.select.min.time", 0, 100 ); gridData = new GridData(); read_select_min.setLayoutData(gridData); // write select Label lwritesel = new Label(gSocket, SWT.NULL); Messages.setLanguageText(lwritesel, CFG_PREFIX + "write_select", new String[]{ String.valueOf( COConfigurationManager.getDefault("network.tcp.write.select.time"))}); final IntParameter write_select = new IntParameter(gSocket, "network.tcp.write.select.time", 10, 250); gridData = new GridData(); write_select.setLayoutData(gridData); Label lwriteselmin = new Label(gSocket, SWT.NULL); Messages.setLanguageText(lwriteselmin, CFG_PREFIX + "write_select_min", new String[]{ String.valueOf( COConfigurationManager.getDefault("network.tcp.write.select.min.time"))}); final IntParameter write_select_min = new IntParameter(gSocket, "network.tcp.write.select.min.time", 0, 100 ); gridData = new GridData(); write_select_min.setLayoutData(gridData); new BooleanParameter( cSection, "IPV6 Enable Support", "network.ipv6.enable.support" ); new BooleanParameter( cSection, "IPV6 Prefer Addresses", "network.ipv6.prefer.addresses" ); new BooleanParameter(cSection, "Enforce Bind IP","network.enforce.ipbinding"); ////////////////////////////////////////////////////////////////////////// return cSection; } private void enableTOSRegistrySetting(boolean enable) { PlatformManager mgr = PlatformManagerFactory.getPlatformManager(); if (mgr.hasCapability(PlatformManagerCapabilities.SetTCPTOSEnabled)) { //see http://www.azureuswiki.com/index.php/AdvancedNetworkSettings try { mgr.setTCPTOSEnabled(enable); } catch (PlatformManagerException pe) { Debug.printStackTrace(pe); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFile.java0000644000175000017500000004710111256315674027773 0ustar adrianadrian/* * File : ConfigPanelFile.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.components.LinkLabel; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.ui.config.ConfigSection; public class ConfigSectionFile implements UISWTConfigSection { public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } public String configSectionGetName() { return ConfigSection.SECTION_FILES; } public void configSectionSave() { } public int maxUserMode() { return 2; } public void configSectionDelete() { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage("openFolderButton"); } public Composite configSectionCreate(final Composite parent) { ImageLoader imageLoader = ImageLoader.getInstance(); Image imgOpenFolder = imageLoader.getImage("openFolderButton"); GridData gridData; Label label; String sCurConfigID; final ArrayList allConfigIDs = new ArrayList(); Composite gFile = new Composite(parent, SWT.NULL); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; gFile.setLayout(layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); // Default Dir Sction Group gDefaultDir = new Group(gFile, SWT.NONE); Messages.setLanguageText(gDefaultDir, "ConfigView.section.file.defaultdir.section"); layout = new GridLayout(); layout.numColumns = 3; layout.marginHeight = 0; gDefaultDir.setLayout(layout); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; gDefaultDir.setLayoutData(gridData); // Save Path sCurConfigID = "Default save path"; allConfigIDs.add(sCurConfigID); Label lblDefaultDir = new Label(gDefaultDir, SWT.NONE); Messages.setLanguageText(lblDefaultDir, "ConfigView.section.file.defaultdir.ask"); lblDefaultDir.setLayoutData(new GridData()); gridData = new GridData(GridData.FILL_HORIZONTAL); final StringParameter pathParameter = new StringParameter(gDefaultDir, sCurConfigID); pathParameter.setLayoutData(gridData); Button browse = new Button(gDefaultDir, SWT.PUSH); browse.setImage(imgOpenFolder); imgOpenFolder.setBackground(browse.getBackground()); browse.setToolTipText(MessageText.getString("ConfigView.button.browse")); browse.addListener(SWT.Selection, new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event event) { DirectoryDialog dialog = new DirectoryDialog(parent.getShell(), SWT.APPLICATION_MODAL); dialog.setFilterPath(pathParameter.getValue()); dialog.setMessage(MessageText.getString("ConfigView.dialog.choosedefaultsavepath")); dialog.setText(MessageText.getString("ConfigView.section.file.defaultdir.ask")); String path = dialog.open(); if (path != null) { pathParameter.setValue(path); } } }); // def dir: autoSave sCurConfigID = "Use default data dir"; allConfigIDs.add(sCurConfigID); BooleanParameter autoSaveToDir = new BooleanParameter(gDefaultDir, sCurConfigID, "ConfigView.section.file.defaultdir.auto"); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; autoSaveToDir.setLayoutData(gridData); // def dir: autoSave -> auto-rename sCurConfigID = "DefaultDir.AutoSave.AutoRename"; allConfigIDs.add(sCurConfigID); BooleanParameter autoSaveAutoRename = new BooleanParameter(gDefaultDir, sCurConfigID, "ConfigView.section.file.defaultdir.autorename"); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; gridData.horizontalIndent = 20; autoSaveAutoRename.setLayoutData(gridData); IAdditionalActionPerformer aapDefaultDirStuff3 = new ChangeSelectionActionPerformer( autoSaveAutoRename.getControls(), false); autoSaveToDir.setAdditionalActionPerformer(aapDefaultDirStuff3); // def dir: best guess sCurConfigID = "DefaultDir.BestGuess"; allConfigIDs.add(sCurConfigID); BooleanParameter bestGuess = new BooleanParameter(gDefaultDir, sCurConfigID, "ConfigView.section.file.defaultdir.bestguess"); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; bestGuess.setLayoutData(gridData); IAdditionalActionPerformer aapDefaultDirStuff = new ChangeSelectionActionPerformer( bestGuess.getControls(), true); autoSaveToDir.setAdditionalActionPerformer(aapDefaultDirStuff); // def dir: auto update sCurConfigID = "DefaultDir.AutoUpdate"; allConfigIDs.add(sCurConfigID); BooleanParameter autoUpdateSaveDir = new BooleanParameter(gDefaultDir, sCurConfigID, "ConfigView.section.file.defaultdir.lastused"); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; autoUpdateSaveDir.setLayoutData(gridData); IAdditionalActionPerformer aapDefaultDirStuff2 = new ChangeSelectionActionPerformer( autoUpdateSaveDir.getControls(), true); autoSaveToDir.setAdditionalActionPerformer(aapDefaultDirStuff2); //////////////////// sCurConfigID = "XFS Allocation"; allConfigIDs.add(sCurConfigID); if( userMode > 0 && !Constants.isWindows ) { BooleanParameter xfsAllocation = new BooleanParameter(gFile, sCurConfigID, "ConfigView.label.xfs.allocation"); gridData = new GridData(); gridData.horizontalSpan = 2; xfsAllocation.setLayoutData(gridData); } BooleanParameter zeroNew = null; sCurConfigID = "Zero New"; allConfigIDs.add(sCurConfigID); if( userMode > 0 ) { // zero new files zeroNew = new BooleanParameter(gFile, sCurConfigID, "ConfigView.label.zeronewfiles"); gridData = new GridData(); gridData.horizontalSpan = 2; zeroNew.setLayoutData(gridData); } sCurConfigID = "File.truncate.if.too.large"; allConfigIDs.add(sCurConfigID); if( userMode > 0 ) { // truncate too large BooleanParameter truncateLarge = new BooleanParameter(gFile, sCurConfigID, "ConfigView.section.file.truncate.too.large"); gridData = new GridData(); gridData.horizontalSpan = 2; truncateLarge.setLayoutData(gridData); } sCurConfigID = "Enable incremental file creation"; allConfigIDs.add(sCurConfigID); if( userMode > 0 ) { // incremental file creation BooleanParameter incremental = new BooleanParameter(gFile, sCurConfigID, "ConfigView.label.incrementalfile"); gridData = new GridData(); gridData.horizontalSpan = 2; incremental.setLayoutData(gridData); //Make the incremental checkbox (button) deselect when zero new is used Button[] btnIncremental = {(Button)incremental.getControl()}; zeroNew.setAdditionalActionPerformer(new ExclusiveSelectionActionPerformer(btnIncremental)); //Make the zero new checkbox(button) deselct when incremental is used Button[] btnZeroNew = {(Button)zeroNew.getControl()}; incremental.setAdditionalActionPerformer(new ExclusiveSelectionActionPerformer(btnZeroNew)); } sCurConfigID = "Check Pieces on Completion"; allConfigIDs.add(sCurConfigID); if( userMode > 0 ) { // check on complete BooleanParameter checkOnComp = new BooleanParameter(gFile, sCurConfigID, "ConfigView.label.checkOncompletion"); gridData = new GridData(); gridData.horizontalSpan = 2; checkOnComp.setLayoutData(gridData); } sCurConfigID = "Seeding Piece Check Recheck Enable"; allConfigIDs.add(sCurConfigID); if( userMode > 0 ) { // check on complete BooleanParameter checkOnSeeding = new BooleanParameter(gFile, sCurConfigID, "ConfigView.label.checkOnSeeding"); gridData = new GridData(); gridData.horizontalSpan = 2; checkOnSeeding.setLayoutData(gridData); } sCurConfigID = "File.strict.locking"; allConfigIDs.add(sCurConfigID); if( userMode > 1 ) { BooleanParameter strictLocking = new BooleanParameter(gFile, sCurConfigID, "ConfigView.label.strictfilelocking"); gridData = new GridData(); gridData.horizontalSpan = 2; strictLocking.setLayoutData(gridData); } if( userMode == 0 ) { allConfigIDs.add("Use Resume"); sCurConfigID = "Save Resume Interval"; allConfigIDs.add(sCurConfigID); sCurConfigID = "On Resume Recheck All"; allConfigIDs.add(sCurConfigID); sCurConfigID = "File.save.peers.enable"; allConfigIDs.add(sCurConfigID); sCurConfigID = "File.save.peers.max"; allConfigIDs.add(sCurConfigID); } else { sCurConfigID = "Use Resume"; allConfigIDs.add(sCurConfigID); // resume data final BooleanParameter bpUseResume = new BooleanParameter(gFile, sCurConfigID, "ConfigView.label.usefastresume"); bpUseResume.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); Composite cResumeGroup = new Composite(gFile, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 4; layout.numColumns = 3; cResumeGroup.setLayout(layout); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalIndent = 25; gridData.horizontalSpan = 2; cResumeGroup.setLayoutData(gridData); sCurConfigID = "Save Resume Interval"; allConfigIDs.add(sCurConfigID); Label lblSaveResumeInterval = new Label(cResumeGroup, SWT.NULL); Messages.setLanguageText(lblSaveResumeInterval, "ConfigView.label.saveresumeinterval"); IntParameter paramSaveInterval = new IntParameter(cResumeGroup, sCurConfigID); gridData = new GridData(); paramSaveInterval.setLayoutData(gridData); Label lblMinutes = new Label(cResumeGroup, SWT.NULL); Messages.setLanguageText(lblMinutes, "ConfigView.text.minutes"); // save peers sCurConfigID = "On Resume Recheck All"; allConfigIDs.add(sCurConfigID); final BooleanParameter recheck_all = new BooleanParameter(cResumeGroup, sCurConfigID, "ConfigView.section.file.resume.recheck.all"); gridData = new GridData(); gridData.horizontalSpan = 3; recheck_all.setLayoutData(gridData); // save peers sCurConfigID = "File.save.peers.enable"; allConfigIDs.add(sCurConfigID); final BooleanParameter save_peers = new BooleanParameter(cResumeGroup, sCurConfigID, "ConfigView.section.file.save.peers.enable"); gridData = new GridData(); gridData.horizontalSpan = 3; save_peers.setLayoutData(gridData); // save peers max sCurConfigID = "File.save.peers.max"; allConfigIDs.add(sCurConfigID); final Label lblSavePeersMax = new Label(cResumeGroup, SWT.NULL); Messages.setLanguageText(lblSavePeersMax, "ConfigView.section.file.save.peers.max"); final IntParameter savePeersMax = new IntParameter(cResumeGroup, sCurConfigID); gridData = new GridData(); savePeersMax.setLayoutData(gridData); final Label lblPerTorrent = new Label(cResumeGroup, SWT.NULL); Messages.setLanguageText(lblPerTorrent, "ConfigView.section.file.save.peers.pertorrent"); final Control[] controls = { cResumeGroup }; /* IAdditionalActionPerformer performer = new ChangeSelectionActionPerformer(controls); bpUseResume.setAdditionalActionPerformer(performer); */ IAdditionalActionPerformer f_enabler = new GenericActionPerformer(controls) { public void performAction() { controlsSetEnabled(controls, bpUseResume.isSelected()); if ( bpUseResume.isSelected()){ lblSavePeersMax.setEnabled( save_peers.isSelected()); savePeersMax.getControl().setEnabled( save_peers.isSelected()); lblPerTorrent.setEnabled( save_peers.isSelected()); } } }; bpUseResume.setAdditionalActionPerformer(f_enabler); save_peers.setAdditionalActionPerformer(f_enabler); } //end usermode>0 if( userMode > 0 ) { sCurConfigID = "priorityExtensions"; allConfigIDs.add(sCurConfigID); // Auto-Prioritize label = new Label(gFile, SWT.WRAP); gridData = new GridData(); gridData.widthHint = 180; label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.label.priorityExtensions"); Composite cExtensions = new Composite(gFile, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); cExtensions.setLayoutData(gridData); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 3; cExtensions.setLayout(layout); gridData = new GridData(GridData.FILL_HORIZONTAL); new StringParameter(cExtensions, sCurConfigID).setLayoutData(gridData); sCurConfigID = "priorityExtensionsIgnoreCase"; allConfigIDs.add(sCurConfigID); new BooleanParameter(cExtensions, sCurConfigID, "ConfigView.label.ignoreCase"); } else { sCurConfigID = "priorityExtensions"; allConfigIDs.add(sCurConfigID); sCurConfigID = "priorityExtensionsIgnoreCase"; allConfigIDs.add(sCurConfigID); } // rename incomplete sCurConfigID = "Rename Incomplete Files"; allConfigIDs.add(sCurConfigID); gridData = new GridData(); gridData.horizontalSpan = 1; BooleanParameter rename_incomplete = new BooleanParameter(gFile, sCurConfigID, "ConfigView.section.file.rename.incomplete"); rename_incomplete.setLayoutData(gridData); sCurConfigID = "Rename Incomplete Files Extension"; allConfigIDs.add(sCurConfigID); gridData = new GridData(GridData.FILL_HORIZONTAL); StringParameter rename_incomplete_ext = new StringParameter(gFile, sCurConfigID); rename_incomplete_ext.setLayoutData(gridData); IAdditionalActionPerformer incompFileAP = new ChangeSelectionActionPerformer( rename_incomplete_ext.getControls(), false); rename_incomplete.setAdditionalActionPerformer(incompFileAP); // Confirm Delete sCurConfigID = "Confirm Data Delete"; allConfigIDs.add(sCurConfigID); gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(gFile, sCurConfigID, "ConfigView.section.file.confirm_data_delete").setLayoutData(gridData); sCurConfigID = "File.delete.include_files_outside_save_dir"; allConfigIDs.add(sCurConfigID); gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(gFile, sCurConfigID, "ConfigView.section.file.delete.include_files_outside_save_dir").setLayoutData(gridData); if ( userMode > 0 ){ Label lIgnoreFiles = new Label(gFile, SWT.NULL); Messages.setLanguageText(lIgnoreFiles, "ConfigView.section.file.torrent.ignorefiles"); gridData = new GridData(GridData.FILL_HORIZONTAL); new StringParameter(gFile, "File.Torrent.IgnoreFiles", TOTorrent.DEFAULT_IGNORE_FILES).setLayoutData(gridData); } try{ final PlatformManager platform = PlatformManagerFactory.getPlatformManager(); if (platform.hasCapability(PlatformManagerCapabilities.RecoverableFileDelete)){ sCurConfigID = "Move Deleted Data To Recycle Bin"; allConfigIDs.add(sCurConfigID); gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(gFile, sCurConfigID, "ConfigView.section.file.nativedelete").setLayoutData(gridData); } }catch( Throwable e ){ } if( userMode > 0 ) { Group gConfigSettings = new Group(gFile, SWT.NONE); Messages.setLanguageText(gConfigSettings, "ConfigView.section.file.config.section"); layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 5; gConfigSettings.setLayout(layout); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; gConfigSettings.setLayoutData(gridData); // Configuration directory information. Label config_label = new Label(gConfigSettings, SWT.NULL); Messages.setLanguageText(config_label, "ConfigView.section.file.config.currentdir"); config_label.setLayoutData(new GridData()); Label config_link = new Label(gConfigSettings, SWT.NULL); config_link.setText(SystemProperties.getUserPath()); config_link.setLayoutData(new GridData()); LinkLabel.makeLinkedLabel(config_link, SystemProperties.getUserPath()); sCurConfigID = "Use Config File Backups"; allConfigIDs.add(sCurConfigID); // check on complete BooleanParameter backupConfig = new BooleanParameter(gConfigSettings, sCurConfigID, "ConfigView.label.backupconfigfiles"); gridData = new GridData(); gridData.horizontalSpan = 2; backupConfig.setLayoutData(gridData); } /* Button buttonReset = new Button(gFile, SWT.PUSH); Messages.setLanguageText(buttonReset, "Button.reset"); gridData = new GridData(GridData.FILL_VERTICAL | GridData.VERTICAL_ALIGN_END); gridData.horizontalSpan = 2; buttonReset.setLayoutData(gridData); buttonReset.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { for (Iterator iter = allConfigIDs.iterator(); iter.hasNext();) { String sConfigID = (String) iter.next(); COConfigurationManager.removeParameter(sConfigID); } } }); */ return gFile; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java0000644000175000017500000002167311256315674031654 0ustar adrianadrian/* * File : ConfigPanel*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; public class ConfigSectionTrackerClient implements UISWTConfigSection { public String configSectionGetParentSection() { return ConfigSection.SECTION_TRACKER; } public String configSectionGetName() { return "tracker.client"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 2; } public Composite configSectionCreate(final Composite parent) { GridData gridData; GridLayout layout; Label label; int userMode = COConfigurationManager.getIntParameter("User Mode"); // extensions tab set up Composite gMainTab = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gMainTab.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; gMainTab.setLayout(layout); //////////////////////SCRAPE GROUP /////////////////// Group scrapeGroup = new Group(gMainTab,SWT.NULL); Messages.setLanguageText(scrapeGroup,"ConfigView.group.scrape"); GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 1; scrapeGroup.setLayout(gridLayout); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; scrapeGroup.setLayoutData( gridData ); label = new Label(scrapeGroup, SWT.WRAP); label.setLayoutData(Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL)); Messages.setLanguageText(label, "ConfigView.section.tracker.client.scrapeinfo"); BooleanParameter scrape = new BooleanParameter(scrapeGroup, "Tracker Client Scrape Enable", "ConfigView.section.tracker.client.scrapeenable"); BooleanParameter scrape_stopped = new BooleanParameter(scrapeGroup, "Tracker Client Scrape Stopped Enable", "ConfigView.section.tracker.client.scrapestoppedenable"); scrape.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( scrape_stopped.getControls())); new BooleanParameter(scrapeGroup, "Tracker Client Scrape Single Only", "ConfigView.section.tracker.client.scrapesingleonly"); ///////////////////////// // row gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(gMainTab, "Tracker Client Send OS and Java Version", "ConfigView.section.tracker.sendjavaversionandos").setLayoutData(gridData); label = new Label(gMainTab, SWT.NULL); ////////////////////// BooleanParameter enableUDP = new BooleanParameter(gMainTab, "Server Enable UDP", "ConfigView.section.server.enableudp"); gridData = new GridData(); gridData.horizontalSpan = 2; enableUDP.setLayoutData(gridData); label = new Label(gMainTab, SWT.NULL); ////////////////////// BooleanParameter showWarnings = new BooleanParameter(gMainTab, "Tracker Client Show Warnings", "ConfigView.section.tracker.client.showwarnings" ); gridData = new GridData(); gridData.horizontalSpan = 2; showWarnings.setLayoutData(gridData); label = new Label(gMainTab, SWT.NULL); if (userMode > 0) { //////////////////////OVERRIDE GROUP /////////////////// Group overrideGroup = new Group(gMainTab,SWT.NULL); Messages.setLanguageText(overrideGroup,"ConfigView.group.override"); gridLayout = new GridLayout(); gridLayout.numColumns = 2; overrideGroup.setLayout(gridLayout); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; overrideGroup.setLayoutData( gridData ); label = new Label(overrideGroup, SWT.WRAP); label.setLayoutData(Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL)); Messages.setLanguageText(label, "ConfigView.label.overrideip"); StringParameter overrideip = new StringParameter(overrideGroup, "Override Ip", ""); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.widthHint = 100; overrideip.setLayoutData(data); label = new Label(overrideGroup, SWT.WRAP); label.setLayoutData(Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL)); Messages.setLanguageText(label, "ConfigView.label.announceport"); StringParameter tcpOverride = new StringParameter(overrideGroup, "TCP.Listen.Port.Override"); data = new GridData(); data.widthHint = 50; tcpOverride.setLayoutData(data); tcpOverride.addChangeListener(new ParameterChangeAdapter() { public void stringParameterChanging(Parameter p, String toValue) { if(toValue == "") return; try { int portVal = Integer.parseInt(toValue); if(portVal >= 0 && portVal <= 65535) return; } catch (NumberFormatException e) {} p.setValue(""); } }); label = new Label(overrideGroup, SWT.WRAP); label.setLayoutData(Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL)); Messages.setLanguageText(label, "ConfigView.label.noportannounce"); BooleanParameter noPortAnnounce = new BooleanParameter(overrideGroup,"Tracker Client No Port Announce"); data = new GridData(); noPortAnnounce.setLayoutData(data); label = new Label(overrideGroup, SWT.WRAP); label.setLayoutData(Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL)); Messages.setLanguageText(label, "ConfigView.label.maxnumwant"); IntParameter numwant = new IntParameter(overrideGroup, "Tracker Client Numwant Limit",0,100); data = new GridData(); numwant.setLayoutData(data); label = new Label(overrideGroup, SWT.WRAP); label.setLayoutData(Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL)); Messages.setLanguageText(label, "ConfigView.label.minannounce"); IntParameter minmininterval = new IntParameter(overrideGroup, "Tracker Client Min Announce Interval"); data = new GridData(); minmininterval.setLayoutData(data); ////////////////////////// if(userMode>1) { // row label = new Label(gMainTab, SWT.NULL); Messages.setLanguageText(label, "ConfigView.section.tracker.client.connecttimeout"); gridData = new GridData(); IntParameter connect_timeout = new IntParameter(gMainTab, "Tracker Client Connect Timeout" ); connect_timeout.setLayoutData(gridData); label = new Label(gMainTab, SWT.NULL); // row label = new Label(gMainTab, SWT.NULL); Messages.setLanguageText(label, "ConfigView.section.tracker.client.readtimeout"); gridData = new GridData(); IntParameter read_timeout = new IntParameter(gMainTab, "Tracker Client Read Timeout" ); read_timeout.setLayoutData(gridData); label = new Label(gMainTab, SWT.NULL); ////// main tab // row gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(gMainTab, "Tracker Key Enable Client", "ConfigView.section.tracker.enablekey").setLayoutData(gridData); label = new Label(gMainTab, SWT.NULL); // row gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(gMainTab, "Tracker Separate Peer IDs", "ConfigView.section.tracker.separatepeerids").setLayoutData(gridData); label = new Label(gMainTab, SWT.WRAP); label.setLayoutData(Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL)); Messages.setLanguageText(label, "ConfigView.section.tracker.separatepeerids.info"); } } return gMainTab; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionIPFilter.java0000644000175000017500000005000511256315674030567 0ustar adrianadrian/* * File : ConfigPanel*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import java.io.File; import java.util.Arrays; import java.util.Comparator; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.ipfilter.*; import org.gudy.azureus2.core3.ipfilter.impl.IpFilterAutoLoaderImpl; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.ui.config.ConfigSection; public class ConfigSectionIPFilter implements UISWTConfigSection { IpFilter filter; Table table; boolean noChange; FilterComparator comparator; private boolean bIsCachingDescriptions = false; class FilterComparator implements Comparator { boolean ascending = true; static final int FIELD_NAME = 0; static final int FIELD_START_IP = 1; static final int FIELD_END_IP = 2; int field = FIELD_START_IP; public int compare(Object arg0,Object arg1) { IpRange range0 = (IpRange) arg0; IpRange range1 = (IpRange) arg1; if(field == FIELD_NAME) { return (ascending ? 1 : -1) * ( range0.compareDescription( range1 )); } if(field == FIELD_START_IP) { return (ascending ? 1 : -1) * ( range0.compareStartIpTo( range1 )); } if(field == FIELD_END_IP) { return (ascending ? 1 : -1) * ( range0.compareEndIpTo( range1 )); } return 0; } public void setField(int newField) { if(field == newField) ascending = ! ascending; field = newField; } } IpRange ipRanges[]; Label percentage_blocked; private IPFilterListener filterListener; public ConfigSectionIPFilter() { comparator = new FilterComparator(); } public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } public String configSectionGetName() { return "ipfilter"; } public void configSectionSave() { try{ if (filter != null) filter.save(); }catch( Exception e ){ Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "Save of filter file fails", e)); } } public int maxUserMode() { return 1; } public void configSectionDelete() { if (bIsCachingDescriptions) { IpFilterManager ipFilterManager = AzureusCoreFactory.getSingleton().getIpFilterManager(); ipFilterManager.clearDescriptionCache(); bIsCachingDescriptions = false; } if (filter != null) { filter.removeListener(filterListener); } ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage("openFolderButton"); imageLoader.releaseImage("subitem"); } public Composite configSectionCreate(final Composite parent) { if (!AzureusCoreFactory.isCoreRunning()) { Composite cSection = new Composite(parent, SWT.NULL); cSection.setLayout(new FillLayout()); Label lblNotAvail = new Label(cSection, SWT.WRAP); Messages.setLanguageText(lblNotAvail, "core.not.available"); return cSection; } ImageLoader imageLoader = ImageLoader.getInstance(); Image imgOpenFolder = imageLoader.getImage("openFolderButton"); String sCurConfigID; GridData gridData; int userMode = COConfigurationManager.getIntParameter("User Mode"); final IpFilterManager ipFilterManager = AzureusCoreFactory.getSingleton().getIpFilterManager(); filter = ipFilterManager.getIPFilter(); Composite gFilter = new Composite(parent, SWT.NULL); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; gFilter.setLayout(layout); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gFilter.setLayoutData(gridData); // start controls // row: enable filter + allow/deny gridData = new GridData(); BooleanParameter enabled = new BooleanParameter(gFilter, "Ip Filter Enabled"); enabled.setLayoutData( gridData ); Messages.setLanguageText(enabled.getControl(), "ConfigView.section.ipfilter.enable"); gridData = new GridData(); BooleanParameter deny = new BooleanParameter(gFilter, "Ip Filter Allow"); deny.setLayoutData( gridData ); Messages.setLanguageText(deny.getControl(), "ConfigView.section.ipfilter.allow"); deny.addChangeListener( new ParameterChangeAdapter() { public void parameterChanged( Parameter p, boolean caused_internally ) { setPercentageBlocked(); } }); // row persist banning gridData = new GridData(); BooleanParameter persist_bad_data_banning = new BooleanParameter(gFilter, "Ip Filter Banning Persistent"); persist_bad_data_banning.setLayoutData( gridData ); Messages.setLanguageText(persist_bad_data_banning.getControl(), "ConfigView.section.ipfilter.persistblocking"); Group gBlockBanning = new Group(gFilter, SWT.NULL); Messages.setLanguageText(gBlockBanning, "ConfigView.section.ipfilter.peerblocking.group"); layout = new GridLayout(); layout.numColumns = 2; gBlockBanning.setLayout(layout); // row block bad + group ban BooleanParameter enable_bad_data_banning = new BooleanParameter( gBlockBanning, "Ip Filter Enable Banning", "ConfigView.section.ipfilter.enablebanning"); gridData = new GridData(); gridData.horizontalSpan = 2; enable_bad_data_banning.setLayoutData(gridData); Label discard_label = new Label(gBlockBanning, SWT.NULL); Messages.setLanguageText(discard_label, "ConfigView.section.ipfilter.discardbanning"); FloatParameter discard_ratio = new FloatParameter(gBlockBanning, "Ip Filter Ban Discard Ratio"); gridData = new GridData(); discard_ratio.setLayoutData(gridData); Composite cIndent = new Composite(gBlockBanning, SWT.NONE); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; gridData.horizontalIndent = 15; cIndent.setLayoutData(gridData); layout = new GridLayout(3, false); layout.marginHeight = 0; layout.marginWidth = 0; cIndent.setLayout(layout); Image img = imageLoader.getImage("subitem"); Label label = new Label(cIndent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); label.setImage(img); Label discard_min_label = new Label(cIndent, SWT.NULL); Messages.setLanguageText(discard_min_label, "ConfigView.section.ipfilter.discardminkb", new String[]{ DisplayFormatters.getUnit( DisplayFormatters.UNIT_KB)}); IntParameter discard_min = new IntParameter(cIndent, "Ip Filter Ban Discard Min KB"); gridData = new GridData(); discard_min.setLayoutData(gridData); // block banning Label block_label = new Label(gBlockBanning, SWT.NULL); Messages.setLanguageText(block_label, "ConfigView.section.ipfilter.blockbanning"); IntParameter block_banning = new IntParameter(gBlockBanning, "Ip Filter Ban Block Limit", 0, 256); gridData = new GridData(); block_banning.setLayoutData(gridData); // triggers enable_bad_data_banning.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( new Control[] { block_banning.getControl(), block_label, discard_ratio.getControl(), discard_label, discard_min.getControl(), discard_min_label })); Group gAutoLoad = new Group(gFilter, SWT.NONE); Messages.setLanguageText(gAutoLoad, "ConfigView.section.ipfilter.autoload.group"); layout = new GridLayout(); layout.numColumns = 4; gAutoLoad.setLayout(layout); gAutoLoad.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); // Load from file sCurConfigID = "Ip Filter Autoload File"; //allConfigIDs.add(sCurConfigID); Label lblDefaultDir = new Label(gAutoLoad, SWT.NONE); Messages.setLanguageText(lblDefaultDir, "ConfigView.section.ipfilter.autoload.file"); lblDefaultDir.setLayoutData(new GridData()); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.minimumWidth = 50; final StringParameter pathParameter = new StringParameter(gAutoLoad, sCurConfigID); pathParameter.setLayoutData(gridData); Button browse = new Button(gAutoLoad, SWT.PUSH); browse.setImage(imgOpenFolder); imgOpenFolder.setBackground(browse.getBackground()); browse.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { FileDialog dialog = new FileDialog(parent.getShell(), SWT.APPLICATION_MODAL); dialog.setFilterPath(pathParameter.getValue()); dialog.setText(MessageText.getString("ConfigView.section.ipfilter.autoload.file")); dialog.setFilterExtensions(new String[] { "*.dat" + File.pathSeparator + "*.p2p" + File.pathSeparator + "*.p2b" + File.pathSeparator + "*.txt", "*.*" }); dialog.setFileName("ipfilter.dat"); String file = dialog.open(); if (file != null) { pathParameter.setValue(file); } } }); browse.setLayoutData(new GridData()); final Button btnLoadNow = new Button(gAutoLoad, SWT.PUSH); Messages.setLanguageText(btnLoadNow, "ConfigView.section.ipfilter.autoload.loadnow"); btnLoadNow.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { try { btnLoadNow.getShell().setCursor(btnLoadNow.getDisplay().getSystemCursor( SWT.CURSOR_WAIT)); COConfigurationManager.setParameter(IpFilterAutoLoaderImpl.CFG_AUTOLOAD_LAST, 0); filter.reload(); btnLoadNow.getShell().setCursor(btnLoadNow.getDisplay().getSystemCursor( SWT.CURSOR_ARROW)); } catch (Exception e) { e.printStackTrace(); } } }); btnLoadNow.setLayoutData(new GridData()); Label lblAutoLoadInfo = new Label(gAutoLoad, SWT.WRAP); Messages.setLanguageText(lblAutoLoadInfo, "ConfigView.section.ipfilter.autoload.info"); lblAutoLoadInfo.setLayoutData(Utils.getWrappableLabelGridData(4, 0)); // description scratch file if (userMode > 0) { gridData = new GridData(); BooleanParameter enableDesc = new BooleanParameter(gFilter, "Ip Filter Enable Description Cache"); enableDesc.setLayoutData(gridData); Messages.setLanguageText(enableDesc.getControl(), "ConfigView.section.ipfilter.enable.descriptionCache"); } // table table = new Table(gFilter, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL); String[] headers = { "ConfigView.section.ipfilter.description", "ConfigView.section.ipfilter.start", "ConfigView.section.ipfilter.end" }; int[] sizes = { 110, 110, 110 }; int[] aligns = { SWT.LEFT, SWT.CENTER, SWT.CENTER }; for (int i = 0; i < headers.length; i++) { TableColumn tc = new TableColumn(table, aligns[i]); tc.setText(headers[i]); tc.setWidth(sizes[i]); Messages.setLanguageText(tc, headers[i]); //$NON-NLS-1$ } TableColumn[] columns = table.getColumns(); columns[0].setData(new Integer(FilterComparator.FIELD_NAME)); columns[1].setData(new Integer(FilterComparator.FIELD_START_IP)); columns[2].setData(new Integer(FilterComparator.FIELD_END_IP)); Listener listener = new Listener() { public void handleEvent(Event e) { TableColumn tc = (TableColumn) e.widget; int field = ((Integer) tc.getData()).intValue(); comparator.setField(field); if (field == FilterComparator.FIELD_NAME && !bIsCachingDescriptions) { ipFilterManager.cacheAllDescriptions(); bIsCachingDescriptions = true; } ipRanges = getSortedRanges(filter.getRanges()); table.setItemCount(ipRanges.length); table.clearAll(); // bug 69398 on Windows table.redraw(); } }; columns[0].addListener(SWT.Selection,listener); columns[1].addListener(SWT.Selection,listener); columns[2].addListener(SWT.Selection,listener); table.setHeaderVisible(true); gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = table.getHeaderHeight() * 3; gridData.widthHint = 200; table.setLayoutData(gridData); Composite cArea = new Composite(gFilter, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 4; cArea.setLayout(layout); gridData = new GridData(GridData.FILL_HORIZONTAL); cArea.setLayoutData(gridData); Button add = new Button(cArea, SWT.PUSH); gridData = new GridData(GridData.CENTER); gridData.widthHint = 100; add.setLayoutData(gridData); Messages.setLanguageText(add, "ConfigView.section.ipfilter.add"); add.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { addRange(); } }); Button remove = new Button(cArea, SWT.PUSH); gridData = new GridData(GridData.CENTER); gridData.widthHint = 100; remove.setLayoutData(gridData); Messages.setLanguageText(remove, "ConfigView.section.ipfilter.remove"); remove.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { TableItem[] selection = table.getSelection(); if (selection.length == 0) return; removeRange((IpRange) selection[0].getData()); ipRanges = getSortedRanges(filter.getRanges()); table.setItemCount(ipRanges.length); table.clearAll(); table.redraw(); } }); Button edit = new Button(cArea, SWT.PUSH); gridData = new GridData(GridData.CENTER); gridData.widthHint = 100; edit.setLayoutData(gridData); Messages.setLanguageText(edit, "ConfigView.section.ipfilter.edit"); edit.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { TableItem[] selection = table.getSelection(); if (selection.length == 0) return; editRange((IpRange) selection[0].getData()); } }); percentage_blocked = new Label(cArea, SWT.WRAP | SWT.RIGHT); percentage_blocked.setLayoutData(Utils.getWrappableLabelGridData(1, 0)); setPercentageBlocked(); table.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { TableItem[] selection = table.getSelection(); if (selection.length == 0) return; editRange((IpRange) selection[0].getData()); } }); Control[] controls = new Control[3]; controls[0] = add; controls[1] = remove; controls[2] = edit; IAdditionalActionPerformer enabler = new ChangeSelectionActionPerformer(controls); enabled.setAdditionalActionPerformer(enabler); ipRanges = getSortedRanges(filter.getRanges()); table.addListener(SWT.SetData, new Listener() { public void handleEvent(Event event) { TableItem item = (TableItem) event.item; int index = table.indexOf(item); // seems we can get -1 here (see bug 1219314 ) if (index < 0 || index >= ipRanges.length) { return; } IpRange range = ipRanges[index]; item.setText(0, range.getDescription()); item.setText(1, range.getStartIp()); item.setText(2, range.getEndIp()); item.setData(range); } }); table.setItemCount(ipRanges.length); table.clearAll(); // bug 69398 on Windows table.redraw(); table.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { resizeTable(); } }); gFilter.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { resizeTable(); } }); filterListener = new IPFilterListener() { public boolean canIPBeBanned(String ip) { return true; } public void IPBanned(BannedIp ip) { } public void IPBlockedListChanged(final IpFilter filter) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (table.isDisposed()) { filter.removeListener(filterListener); return; } ipRanges = getSortedRanges(filter.getRanges()); table.setItemCount(ipRanges.length); table.clearAll(); table.redraw(); } }); } public boolean canIPBeBlocked( String ip, byte[] torrent_hash ) { return true; } }; filter.addListener(filterListener); return gFilter; } private void resizeTable() { int iNewWidth = table.getClientArea().width - table.getColumn(1).getWidth() - table.getColumn(2).getWidth() - 20; if (iNewWidth > 50) table.getColumn(0).setWidth(iNewWidth); } public void removeRange(IpRange range) { filter.removeRange( range ); //noChange = false; //refresh(); } public void editRange(IpRange range) { new IpFilterEditor(AzureusCoreFactory.getSingleton(),table.getShell(), range); noChange = false; //refresh(); } public void addRange() { new IpFilterEditor(AzureusCoreFactory.getSingleton(),table.getShell(), null); //noChange = false; //refresh(); } public void refresh() { if (table == null || table.isDisposed() || noChange) return; noChange = true; TableItem[] items = table.getItems(); for (int i = 0; i < items.length; i++) { if (items[i] == null || items[i].isDisposed()) continue; String tmp = items[i].getText(0); IpRange range = (IpRange) items[i].getData(); String desc = range.getDescription(); if (desc != null && !desc.equals(tmp)) items[i].setText(0, desc); tmp = items[i].getText(1); if (range.getStartIp() != null && !range.getStartIp().equals(tmp)) items[i].setText(1, range.getStartIp()); tmp = items[i].getText(2); if (range.getEndIp() != null && !range.getEndIp().equals(tmp)) items[i].setText(2, range.getEndIp()); } } protected IpRange[] getSortedRanges( IpRange[] ranges ) { Arrays.sort( ranges, comparator); return( ranges ); } protected void setPercentageBlocked() { long nbIPsBlocked = filter.getTotalAddressesInRange(); if ( COConfigurationManager.getBooleanParameter( "Ip Filter Allow" )){ nbIPsBlocked = 0x100000000L - nbIPsBlocked; } int percentIPsBlocked = (int) (nbIPsBlocked * 1000L / (256L * 256L * 256L * 256L)); String nbIps = "" + nbIPsBlocked; String percentIps = DisplayFormatters.formatPercentFromThousands(percentIPsBlocked); Messages.setLanguageText(percentage_blocked,"ConfigView.section.ipfilter.totalIPs",new String[]{nbIps,percentIps}); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionPlugins.java0000644000175000017500000005401611267524616030540 0ustar adrianadrian/* * File : ConfigSectionPlguins.java * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import java.io.File; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.DualChangeSelectionActionPerformer; import org.gudy.azureus2.ui.swt.config.IAdditionalActionPerformer; import org.gudy.azureus2.ui.swt.config.plugins.PluginParameter; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.Cursors; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.ui.swt.views.ConfigView; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.platform.PlatformManagerException; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.plugins.ui.config.Parameter; import org.gudy.azureus2.pluginsimpl.local.PluginInterfaceImpl; import org.gudy.azureus2.pluginsimpl.local.ui.config.BooleanParameterImpl; import org.gudy.azureus2.pluginsimpl.local.ui.config.ParameterRepository; /** * Configuration Section that lists all the plugins and sets up * subsections for plugins that used the PluginConfigModel object. * * Moved from ConfigView * * @author TuxPaper * */ public class ConfigSectionPlugins implements UISWTConfigSection, ParameterListener { private final static String HEADER_PREFIX = "ConfigView.pluginlist.column."; private final static String[] COLUMN_HEADERS = { "loadAtStartup", "type", "name", "version", "directory", "unloadable" }; private final static int[] COLUMN_SIZES = { 110, 50, 150, 75, 100, 50 }; private final static int[] COLUMN_ALIGNS = { SWT.CENTER, SWT.LEFT, SWT.LEFT, SWT.RIGHT, SWT.LEFT, SWT.CENTER}; private ConfigView configView; FilterComparator comparator; List pluginIFs; private Table table; private Image imgRedLed; private Image imgGreenLed; class FilterComparator implements Comparator { boolean ascending = true; static final int FIELD_LOAD = 0; static final int FIELD_TYPE = 1; static final int FIELD_NAME = 2; static final int FIELD_VERSION = 3; static final int FIELD_DIRECTORY = 4; static final int FIELD_UNLOADABLE = 5; int field = FIELD_NAME; String sUserPluginDir; String sAppPluginDir; public FilterComparator() { String sep = System.getProperty("file.separator"); sUserPluginDir = FileUtil.getUserFile("plugins").toString(); if (!sUserPluginDir.endsWith(sep)) sUserPluginDir += sep; sAppPluginDir = FileUtil.getApplicationFile("plugins").toString(); if (!sAppPluginDir.endsWith(sep)) sAppPluginDir += sep; } public int compare(Object arg0, Object arg1) { PluginInterface if0 = (PluginInterface) arg0; PluginInterfaceImpl if1 = (PluginInterfaceImpl) arg1; int result = 0; switch (field) { case FIELD_LOAD: { boolean b0 = if0.getPluginState().isLoadedAtStartup(); boolean b1 = if1.getPluginState().isLoadedAtStartup(); result = (b0 == b1 ? 0 : (b0 ? -1 : 1)); // Use the plugin ID name to sort by instead. if (result == 0) { result = if0.getPluginID().compareToIgnoreCase( if1.getPluginID()); } break; } case FIELD_TYPE: case FIELD_DIRECTORY: { result = getFieldValue(field, if0).compareToIgnoreCase( getFieldValue(field, if1)); break; } case FIELD_VERSION: { // XXX Not really right.. String s0 = if0.getPluginVersion(); String s1 = if1.getPluginVersion(); if (s0 == null) s0 = ""; if (s1 == null) s1 = ""; result = s0.compareToIgnoreCase(s1); break; } case FIELD_UNLOADABLE: { boolean b0 = if0.getPluginState().isUnloadable(); boolean b1 = if1.getPluginState().isUnloadable(); result = (b0 == b1 ? 0 : (b0 ? -1 : 1)); break; } } if (result == 0) result = if0.getPluginName().compareToIgnoreCase(if1.getPluginName()); if (!ascending) result *= -1; return result; } public boolean setField(int newField) { if (field == newField) ascending = !ascending; else ascending = true; field = newField; return ascending; } public String getFieldValue(int iField, PluginInterface pluginIF) { switch (iField) { case FIELD_LOAD: { return pluginIF.getPluginID(); } case FIELD_DIRECTORY: { String sDirName = pluginIF.getPluginDirectoryName(); if (sDirName.length() > sUserPluginDir.length() && sDirName.substring(0, sUserPluginDir.length()).equals( sUserPluginDir)) { return sDirName.substring(sUserPluginDir.length()); } else if (sDirName.length() > sAppPluginDir.length() && sDirName.substring(0, sAppPluginDir.length()).equals( sAppPluginDir)) { return sDirName.substring(sAppPluginDir.length()); } return sDirName; } case FIELD_NAME: { return pluginIF.getPluginName(); } case FIELD_TYPE: { String sDirName = pluginIF.getPluginDirectoryName(); String sKey; if (sDirName.length() > sUserPluginDir.length() && sDirName.substring(0, sUserPluginDir.length()).equals( sUserPluginDir)) { sKey = "perUser"; } else if (sDirName.length() > sAppPluginDir.length() && sDirName.substring(0, sAppPluginDir.length()).equals( sAppPluginDir)) { sKey = "shared"; } else { sKey = "builtIn"; } return MessageText.getString(HEADER_PREFIX + "type." + sKey); } case FIELD_VERSION: { return pluginIF.getPluginVersion(); } case FIELD_UNLOADABLE: { return MessageText.getString("Button." + (pluginIF.getPluginState().isUnloadable() ? "yes" : "no")).replaceAll("&", ""); } } // switch return ""; } } /** * Initialize * @param _configView */ public ConfigSectionPlugins(ConfigView _configView) { configView = _configView; comparator = new FilterComparator(); } public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } /* Name of section will be pulled from * ConfigView.section.configSectionGetName() */ public String configSectionGetName() { return ConfigSection.SECTION_PLUGINS; } public void configSectionSave() { } public int maxUserMode() { return 0; } public void configSectionDelete() { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage("redled"); imageLoader.releaseImage("greenled"); } public Composite configSectionCreate(final Composite parent) { if (!AzureusCoreFactory.isCoreRunning()) { Composite cSection = new Composite(parent, SWT.NULL); cSection.setLayout(new FillLayout()); Label lblNotAvail = new Label(cSection, SWT.WRAP); Messages.setLanguageText(lblNotAvail, "core.not.available"); return cSection; } GridLayout layout; GridData gridData; Label label; ImageLoader imageLoader = ImageLoader.getInstance(); imgRedLed = imageLoader.getImage("redled"); imgGreenLed = imageLoader.getImage("greenled"); Composite infoGroup = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); infoGroup.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 1; layout.marginWidth = 0; layout.marginHeight = 0; infoGroup.setLayout(layout); infoGroup.setLayout(new GridLayout()); String sep = System.getProperty("file.separator"); File fUserPluginDir = FileUtil.getUserFile("plugins"); String sUserPluginDir; try{ sUserPluginDir = fUserPluginDir.getCanonicalPath(); }catch( Throwable e ){ sUserPluginDir = fUserPluginDir.toString(); } if (!sUserPluginDir.endsWith(sep)) { sUserPluginDir += sep; } File fAppPluginDir = FileUtil.getApplicationFile("plugins"); String sAppPluginDir; try{ sAppPluginDir = fAppPluginDir.getCanonicalPath(); }catch( Throwable e ){ sAppPluginDir = fAppPluginDir.toString(); } if (!sAppPluginDir.endsWith(sep)) { sAppPluginDir += sep; } label = new Label(infoGroup, SWT.WRAP); label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Messages.setLanguageText(label, "ConfigView.pluginlist.whereToPut"); label = new Label(infoGroup, SWT.WRAP); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalIndent = 10; label.setLayoutData(gridData); label.setText(sUserPluginDir.replaceAll("&", "&&")); label.setForeground(Colors.blue); label.setCursor(Cursors.handCursor); final String _sUserPluginDir = sUserPluginDir; label.addMouseListener(new MouseAdapter() { public void mouseUp(MouseEvent arg0) { if (_sUserPluginDir.endsWith("/plugins/") || _sUserPluginDir.endsWith("\\plugins\\")) { File f = new File(_sUserPluginDir); String dir = _sUserPluginDir; if (!(f.exists() && f.isDirectory())) { dir = _sUserPluginDir.substring(0, _sUserPluginDir .length() - 9); } Utils.launch(dir); } } }); label = new Label(infoGroup, SWT.WRAP); label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Messages.setLanguageText(label, "ConfigView.pluginlist.whereToPutOr"); label = new Label(infoGroup, SWT.WRAP); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalIndent = 10; label.setLayoutData(gridData); label.setText(sAppPluginDir.replaceAll("&", "&&")); label.setForeground(Colors.blue); label.setCursor(Cursors.handCursor); final String _sAppPluginDir = sAppPluginDir; //TODO : Fix it for windows label.addMouseListener(new MouseAdapter() { public void mouseUp(MouseEvent arg0) { if (_sAppPluginDir.endsWith("/plugins/") || _sAppPluginDir.endsWith("\\plugins\\")) { File f = new File(_sAppPluginDir); if (f.exists() && f.isDirectory()) { Utils.launch(_sAppPluginDir); } else { String azureusDir = _sAppPluginDir.substring(0, _sAppPluginDir .length() - 9); System.out.println(azureusDir); Utils.launch(azureusDir); } } } }); pluginIFs = rebuildPluginIFs(); Collections.sort(pluginIFs, new Comparator() { public int compare(Object o1, Object o2) { return (((PluginInterface) o1).getPluginName() .compareToIgnoreCase(((PluginInterface) o2).getPluginName())); } }); Label labelInfo = new Label(infoGroup, SWT.WRAP); labelInfo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Messages.setLanguageText(labelInfo, "ConfigView.pluginlist.info"); table = new Table(infoGroup, SWT.BORDER | SWT.SINGLE | SWT.CHECK | SWT.VIRTUAL | SWT.FULL_SELECTION); gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 200; gridData.widthHint = 200; table.setLayoutData(gridData); for (int i = 0; i < COLUMN_HEADERS.length; i++) { final TableColumn tc = new TableColumn(table, COLUMN_ALIGNS[i]); tc.setWidth(COLUMN_SIZES[i]); tc.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { boolean ascending = comparator.setField(table.indexOf(tc)); try { table.setSortColumn(tc); table.setSortDirection(ascending ? SWT.UP : SWT.DOWN); } catch (NoSuchMethodError ignore) { // Ignore Pre 3.0 } Collections.sort(pluginIFs, comparator); table.clearAll(); } }); Messages.setLanguageText(tc, HEADER_PREFIX + COLUMN_HEADERS[i]); } table.setHeaderVisible(true); Composite cButtons = new Composite(infoGroup, SWT.NONE); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 3; cButtons.setLayout(layout); cButtons.setLayoutData(new GridData()); final Button btnUnload = new Button(cButtons, SWT.PUSH); btnUnload.setLayoutData(new GridData()); Messages.setLanguageText(btnUnload, "ConfigView.pluginlist.unloadSelected"); btnUnload.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int[] items = table.getSelectionIndices(); for (int i = 0; i < items.length; i++) { int index = items[i]; if (index >= 0 && index < pluginIFs.size()) { PluginInterface pluginIF = (PluginInterface) pluginIFs.get(index); if (pluginIF.getPluginState().isOperational()) { if (pluginIF.getPluginState().isUnloadable()) { try { pluginIF.getPluginState().unload(); } catch (PluginException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } pluginIFs = rebuildPluginIFs(); table.setItemCount(pluginIFs.size()); Collections.sort(pluginIFs, comparator); table.clearAll(); } } } }); btnUnload.setEnabled( false ); final Button btnLoad = new Button(cButtons, SWT.PUSH); btnUnload.setLayoutData(new GridData()); Messages.setLanguageText(btnLoad, "ConfigView.pluginlist.loadSelected"); btnLoad.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int[] items = table.getSelectionIndices(); for (int i = 0; i < items.length; i++) { int index = items[i]; if (index >= 0 && index < pluginIFs.size()) { PluginInterface pluginIF = (PluginInterface) pluginIFs.get(index); if (pluginIF.getPluginState().isOperational()) {continue;} // Already loaded. // Re-enable disabled plugins, as long as they haven't failed on // initialise. if (pluginIF.getPluginState().isDisabled()) { if (pluginIF.getPluginState().hasFailed()) {continue;} pluginIF.getPluginState().setDisabled(false); } try { pluginIF.getPluginState().reload(); } catch (PluginException e1) { // TODO Auto-generated catch block Debug.printStackTrace(e1); } pluginIFs = rebuildPluginIFs(); table.setItemCount(pluginIFs.size()); Collections.sort(pluginIFs, comparator); table.clearAll(); } } } }); btnLoad.setEnabled( false ); final Button btnScan = new Button(cButtons, SWT.PUSH); btnScan.setLayoutData(new GridData()); Messages.setLanguageText(btnScan, "ConfigView.pluginlist.scan"); btnScan.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { AzureusCoreFactory.getSingleton().getPluginManager().refreshPluginList(false); pluginIFs = rebuildPluginIFs(); table.setItemCount(pluginIFs.size()); Collections.sort(pluginIFs, comparator); table.clearAll(); } }); table.addListener(SWT.SetData, new Listener() { public void handleEvent(Event event) { TableItem item = (TableItem) event.item; int index = table.indexOf(item); PluginInterface pluginIF = (PluginInterface) pluginIFs.get(index); for (int i = 0; i < COLUMN_HEADERS.length; i++) { if (i == FilterComparator.FIELD_NAME) item.setImage(i, pluginIF.getPluginState().isOperational() ? imgGreenLed : imgRedLed); String sText = comparator.getFieldValue(i, pluginIF); if (sText == null) sText = ""; item.setText(i, sText); } item.setGrayed(pluginIF.getPluginState().isMandatory()); boolean bEnabled = pluginIF.getPluginState().isLoadedAtStartup(); Utils.setCheckedInSetData(item, bEnabled); item.setData("PluginID", pluginIF.getPluginID()); Utils.alternateRowBackground(item); } }); table.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { TableItem item = (TableItem) e.item; int index = table.indexOf(item); PluginInterface pluginIF = (PluginInterface) pluginIFs.get(index); if (e.detail == SWT.CHECK){ if (item.getGrayed()) { if (!item.getChecked()) item.setChecked(true); return; } pluginIF.getPluginState().setDisabled(!item.getChecked()); pluginIF.getPluginState().setLoadedAtStartup(item.getChecked()); } btnUnload.setEnabled(pluginIF.getPluginState().isOperational() && pluginIF.getPluginState().isUnloadable()); btnLoad.setEnabled(!pluginIF.getPluginState().isOperational() && !pluginIF.getPluginState().hasFailed()); } }); table.setItemCount(pluginIFs.size()); return infoGroup; } /** * @return * * @since 3.0.5.3 */ private List rebuildPluginIFs() { List pluginIFs = Arrays.asList(AzureusCoreFactory.getSingleton().getPluginManager().getPlugins()); for (Iterator iter = pluginIFs.iterator(); iter.hasNext();) { PluginInterface pi = (PluginInterface) iter.next(); // COConfigurationManager will not add the same listener twice COConfigurationManager.addParameterListener("PluginInfo." + pi.getPluginID() + ".enabled", this); } return pluginIFs; } // @see org.gudy.azureus2.core3.config.ParameterListener#parameterChanged(java.lang.String) public void parameterChanged(String parameterName) { if (table != null) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (table != null && !table.isDisposed()) { table.clearAll(); } } }); } } public void initPluginSubSections() { // Create subsections for plugins that used the PluginConfigModel object // ===================================================================== TreeItem treePlugins = configView .findTreeItem(ConfigSection.SECTION_PLUGINS); ParameterRepository repository = ParameterRepository.getInstance(); String[] names = repository.getNames(); Arrays.sort(names); for (int i = 0; i < names.length; i++) { String pluginName = names[i]; Parameter[] parameters = repository.getParameterBlock(pluginName); // Note: 2070's plugin documentation for PluginInterface.addConfigUIParameters // said to pass <"ConfigView.plugins." + displayName>. This was // never implemented in 2070. 2070 read the key without // the prefix. // // 2071+ uses // and falls back to . Since // <"ConfigView.plugins." + displayName> was never implemented in the // first place, a check for it has not been created boolean bUsePrefix = MessageText.keyExists(ConfigView.sSectionPrefix + "plugins." + pluginName); Composite pluginGroup = configView.createConfigSection(treePlugins, pluginName, -2, bUsePrefix); GridLayout pluginLayout = new GridLayout(); pluginLayout.numColumns = 3; pluginGroup.setLayout(pluginLayout); Map parameterToPluginParameter = new HashMap(); //Add all parameters for (int j = 0; j < parameters.length; j++) { Parameter parameter = parameters[j]; parameterToPluginParameter.put(parameter, new PluginParameter( pluginGroup, parameter)); } //Check for dependencies for (int j = 0; j < parameters.length; j++) { Parameter parameter = parameters[j]; if (parameter instanceof BooleanParameterImpl) { List parametersToEnable = ((BooleanParameterImpl) parameter) .getEnabledOnSelectionParameters(); List controlsToEnable = new ArrayList(); Iterator iter = parametersToEnable.iterator(); while (iter.hasNext()) { Parameter parameterToEnable = (Parameter) iter.next(); PluginParameter pp = (PluginParameter) parameterToPluginParameter .get(parameterToEnable); Control[] controls = pp.getControls(); for (int k = 0; k < controls.length; k++) { controlsToEnable.add(controls[k]); } } List parametersToDisable = ((BooleanParameterImpl) parameter) .getDisabledOnSelectionParameters(); List controlsToDisable = new ArrayList(); iter = parametersToDisable.iterator(); while (iter.hasNext()) { Parameter parameterToDisable = (Parameter) iter.next(); PluginParameter pp = (PluginParameter) parameterToPluginParameter .get(parameterToDisable); Control[] controls = pp.getControls(); for (int k = 0; k < controls.length; k++) { controlsToDisable.add(controls[k]); } } Control[] ce = new Control[controlsToEnable.size()]; Control[] cd = new Control[controlsToDisable.size()]; if (ce.length + cd.length > 0) { IAdditionalActionPerformer ap = new DualChangeSelectionActionPerformer( (Control[]) controlsToEnable.toArray(ce), (Control[]) controlsToDisable.toArray(cd)); PluginParameter pp = (PluginParameter) parameterToPluginParameter .get(parameter); pp.setAdditionalActionPerfomer(ap); } } } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeed.java0000644000175000017500000001476311134026454032510 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.components.LinkLabel; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; public class ConfigSectionTransferAutoSpeed implements UISWTConfigSection { private final String CFG_PREFIX = "ConfigView.section.transfer.autospeed."; public String configSectionGetParentSection() { return "transfer.select"; } public String configSectionGetName() { return "transfer.autospeed"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 2; } public Composite configSectionCreate(final Composite parent) { GridData gridData; Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); GridLayout advanced_layout = new GridLayout(); advanced_layout.numColumns = 2; cSection.setLayout(advanced_layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); Label linfo = new Label(cSection, SWT.WRAP); Messages.setLanguageText( linfo, CFG_PREFIX + "info" ); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; linfo.setLayoutData(gridData); gridData = new GridData(); gridData.horizontalSpan = 2; new LinkLabel(cSection, gridData, "ConfigView.label.please.visit.here", "http://www.azureuswiki.com/index.php/Auto_Speed"); String[] units = { DisplayFormatters.getRateUnit( DisplayFormatters.UNIT_KB )}; // min up Label llmux = new Label(cSection, SWT.NULL); Messages.setLanguageText( llmux, CFG_PREFIX + "minupload", units ); IntParameter min_upload = new IntParameter(cSection, "AutoSpeed Min Upload KBs"); gridData = new GridData(); min_upload.setLayoutData(gridData); // max up Label llmdx = new Label(cSection, SWT.NULL); Messages.setLanguageText( llmdx, CFG_PREFIX + "maxupload", units ); IntParameter max_upload = new IntParameter(cSection, "AutoSpeed Max Upload KBs"); gridData = new GridData(); max_upload.setLayoutData(gridData); if ( userMode > 0 ){ BooleanParameter enable_down_adj = new BooleanParameter( cSection, "AutoSpeed Download Adj Enable", CFG_PREFIX + "enabledownadj" ); gridData = new GridData(); gridData.horizontalSpan = 2; enable_down_adj.setLayoutData(gridData); Label label = new Label(cSection, SWT.NULL); Messages.setLanguageText( label, CFG_PREFIX + "downadjratio" ); FloatParameter down_adj = new FloatParameter( cSection, "AutoSpeed Download Adj Ratio", 0, Float.MAX_VALUE, false, 2 ); gridData = new GridData(); down_adj.setLayoutData(gridData); enable_down_adj.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( new Control[]{ down_adj.getControl()})); } if ( userMode > 1 ){ // max inc Label label = new Label(cSection, SWT.NULL); Messages.setLanguageText( label, CFG_PREFIX + "maxinc", units ); final IntParameter max_increase = new IntParameter(cSection, "AutoSpeed Max Increment KBs"); gridData = new GridData(); max_increase.setLayoutData(gridData); // max dec label = new Label(cSection, SWT.NULL); Messages.setLanguageText( label, CFG_PREFIX + "maxdec", units ); final IntParameter max_decrease = new IntParameter(cSection, "AutoSpeed Max Decrement KBs"); gridData = new GridData(); max_decrease.setLayoutData(gridData); // choking ping label = new Label(cSection, SWT.NULL); Messages.setLanguageText( label, CFG_PREFIX + "chokeping" ); final IntParameter choke_ping = new IntParameter(cSection, "AutoSpeed Choking Ping Millis"); gridData = new GridData(); choke_ping.setLayoutData(gridData); // forced min label = new Label(cSection, SWT.NULL); Messages.setLanguageText( label, CFG_PREFIX + "forcemin", units ); final IntParameter forced_min = new IntParameter(cSection, "AutoSpeed Forced Min KBs"); gridData = new GridData(); forced_min.setLayoutData(gridData); // latency label = new Label(cSection, SWT.NULL); Messages.setLanguageText( label, CFG_PREFIX + "latencyfactor" ); final IntParameter latency_factor = new IntParameter(cSection, "AutoSpeed Latency Factor", 1, Integer.MAX_VALUE); gridData = new GridData(); latency_factor.setLayoutData(gridData); Label reset_label = new Label(cSection, SWT.NULL ); Messages.setLanguageText(reset_label, CFG_PREFIX + "reset"); Button reset_button = new Button(cSection, SWT.PUSH); Messages.setLanguageText(reset_button, CFG_PREFIX + "reset.button" ); reset_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { max_increase.resetToDefault(); max_decrease.resetToDefault(); choke_ping.resetToDefault(); latency_factor.resetToDefault(); forced_min.resetToDefault(); } }); } return cSection; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionMode.java0000644000175000017500000001766511046773326030013 0ustar adrianadrian /* * File : ConfigPanel*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.Cursors; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; public class ConfigSectionMode implements UISWTConfigSection { public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } public String configSectionGetName() { return "mode"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 0; } public Composite configSectionCreate(final Composite parent) { GridData gridData; GridLayout layout; String initsMode = ""; final String[] text = {""}; final String[] messTexts = {"ConfigView.section.mode.beginner.wiki.definitions", "ConfigView.section.mode.intermediate.wiki.host", "ConfigView.section.mode.advanced.wiki.main", "ConfigView.section.mode.intermediate.wiki.publish" }; final String[] links = {"http://www.azureuswiki.com/index.php/This_funny_word", "http://www.azureuswiki.com/index.php/HostingFiles", "http://www.azureuswiki.com/index.php/Main_Page", "http://www.azureuswiki.com/index.php/PublishingFiles" }; int userMode = COConfigurationManager.getIntParameter("User Mode"); final Composite cMode = new Composite(parent, SWT.WRAP); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cMode.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 4; layout.marginHeight = 0; cMode.setLayout(layout); gridData = new GridData(); gridData.horizontalSpan = 4; final Group gRadio = new Group(cMode, SWT.WRAP); Messages.setLanguageText(gRadio, "ConfigView.section.mode.title"); gRadio.setLayoutData(gridData); gRadio.setLayout(new RowLayout(SWT.HORIZONTAL)); Button button0 = new Button (gRadio, SWT.RADIO); Messages.setLanguageText(button0, "ConfigView.section.mode.beginner"); button0.setData("iMode", "0"); button0.setData("sMode", "beginner.text"); Button button1 = new Button (gRadio, SWT.RADIO); Messages.setLanguageText(button1, "ConfigView.section.mode.intermediate"); button1.setData("iMode", "1"); button1.setData("sMode", "intermediate.text"); Button button2 = new Button (gRadio, SWT.RADIO); Messages.setLanguageText(button2, "ConfigView.section.mode.advanced"); button2.setData("iMode", "2"); button2.setData("sMode", "advanced.text"); if ( userMode == 0) { initsMode = "beginner.text"; button0.setSelection(true); } else if ( userMode == 1) { initsMode = "intermediate.text"; button1.setSelection(true); } else { initsMode = "advanced.text"; button2.setSelection(true); } gridData = new GridData(GridData.FILL_HORIZONTAL); final Label label = new Label(cMode, SWT.WRAP); gridData.horizontalSpan = 4; label.setLayoutData(gridData); text[0] = MessageText.getString("ConfigView.section.mode." + initsMode); label.setText(text[0]); label.addListener (SWT.Selection, new Listener () { public void handleEvent(Event event) { Utils.launch(event.text); } }); Group gWiki = new Group(cMode, SWT.WRAP); gridData = new GridData(); gridData.widthHint = 350; gWiki.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 1; layout.marginHeight = 1; gWiki.setLayout(layout); gWiki.setText(MessageText.getString("Utils.link.visit")); final Label linkLabel = new Label(gWiki, SWT.NULL); linkLabel.setText( MessageText.getString( messTexts[userMode] ) ); linkLabel.setData( links[userMode] ); linkLabel.setCursor(Cursors.handCursor); linkLabel.setForeground(Colors.blue); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalIndent = 10; linkLabel.setLayoutData( gridData ); linkLabel.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } public void mouseUp(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } }); final Label linkLabel1 = new Label(gWiki, SWT.NULL); linkLabel1.setText( (userMode == 1)?MessageText.getString(messTexts[3]):""); linkLabel1.setData( links[3] ); linkLabel1.setCursor(Cursors.handCursor); linkLabel1.setForeground(Colors.blue); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalIndent = 10; linkLabel1.setLayoutData( gridData ); linkLabel1.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } public void mouseUp(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } }); Listener radioGroup = new Listener () { public void handleEvent (Event event) { Control [] children = gRadio.getChildren (); for (int j=0; j 0; clear_label.setEnabled(enabled); clear_decisions.setEnabled(enabled); } } }; decisions_parameter_listener.parameterChanged(null); COConfigurationManager.addParameterListener("MessageBoxWindow.decisions", decisions_parameter_listener); // drag-drop label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, "ConfigView.section.style.dropdiraction"); String[] drop_options = { "ConfigView.section.style.dropdiraction.opentorrents", "ConfigView.section.style.dropdiraction.sharefolder", "ConfigView.section.style.dropdiraction.sharefoldercontents", "ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive", }; String dropLabels[] = new String[drop_options.length]; String dropValues[] = new String[drop_options.length]; for (int i = 0; i < drop_options.length; i++) { dropLabels[i] = MessageText.getString(drop_options[i]); dropValues[i] = "" + i; } new StringListParameter(cArea, "config.style.dropdiraction", dropLabels, dropValues); // double-click if (COConfigurationManager.getStringParameter("ui").equals("az3")) { label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, LBLKEY_PREFIX + "dm.dblclick"); String[] dblclickOptions = { "ConfigView.option.dm.dblclick.play", "ConfigView.option.dm.dblclick.details", "ConfigView.option.dm.dblclick.show", }; String dblclickLabels[] = new String[dblclickOptions.length]; String dblclickValues[] = new String[dblclickOptions.length]; for (int i = 0; i < dblclickOptions.length; i++) { dblclickLabels[i] = MessageText.getString(dblclickOptions[i]); dblclickValues[i] = "" + i; } new StringListParameter(cArea, "list.dm.dblclick", dblclickLabels, dblclickValues); } // reset associations final PlatformManager platform = PlatformManagerFactory .getPlatformManager(); if (platform .hasCapability(PlatformManagerCapabilities.RegisterFileAssociations)) { Composite cResetAssoc = new Composite(cArea, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 2; cResetAssoc.setLayout(layout); cResetAssoc.setLayoutData(new GridData()); label = new Label(cResetAssoc, SWT.NULL); Messages.setLanguageText(label, KEY_PREFIX + "resetassoc"); Button reset = new Button(cResetAssoc, SWT.PUSH); Messages.setLanguageText(reset, KEY_PREFIX + "resetassocbutton"); //$NON-NLS-1$ reset.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { try { platform.registerApplication(); } catch (PlatformManagerException e) { Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "Failed to register application", e)); } } }); new BooleanParameter(cArea, "config.interface.checkassoc", KEY_PREFIX + "checkassoc"); } return cDisplay; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceStart.java0000644000175000017500000001065711276126554032037 0ustar adrianadrian/* * File : ConfigPanel*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.UISwitcherUtil; import org.gudy.azureus2.ui.swt.config.BooleanParameter; import org.gudy.azureus2.ui.swt.config.ChangeSelectionActionPerformer; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; public class ConfigSectionInterfaceStart implements UISWTConfigSection { public String configSectionGetParentSection() { return ConfigSection.SECTION_INTERFACE; } public String configSectionGetName() { return "start"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 0; } public Composite configSectionCreate(final Composite parent) { // "Start" Sub-Section // ------------------- GridLayout layout; Composite cStart = new Composite(parent, SWT.NULL); cStart.setLayoutData(new GridData(GridData.FILL_BOTH)); layout = new GridLayout(); layout.numColumns = 1; cStart.setLayout(layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); boolean isAZ3 = COConfigurationManager.getStringParameter("ui").equals("az3"); if (userMode >= 2) { new BooleanParameter(cStart, "ui.startfirst", "ConfigView.label.StartUIBeforeCore"); } new BooleanParameter(cStart, "Show Splash", "ConfigView.label.showsplash"); new BooleanParameter(cStart, "update.start", "ConfigView.label.checkonstart"); new BooleanParameter(cStart, "update.periodic", "ConfigView.label.periodiccheck"); BooleanParameter autoDownload = new BooleanParameter(cStart, "update.autodownload", "ConfigView.section.update.autodownload"); BooleanParameter openDialog = new BooleanParameter(cStart, "update.opendialog", "ConfigView.label.opendialog"); autoDownload.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( new Control[] { openDialog.getControl() }, true )); new Label(cStart,SWT.NULL); if (!isAZ3) { new BooleanParameter(cStart, "Open MyTorrents", "ConfigView.label.openmytorrents"); new BooleanParameter(cStart, "Open Console", "ConfigView.label.openconsole"); new BooleanParameter(cStart, "Open Stats On Start", "ConfigView.label.openstatsonstart"); new BooleanParameter(cStart, "Open Config", "ConfigView.label.openconfig"); } new BooleanParameter(cStart, "Open Transfer Bar On Start", "ConfigView.label.open_transfer_bar_on_start"); new BooleanParameter(cStart, "Start Minimized", "ConfigView.label.startminimized"); // UI switcher window. Composite cUISwitcher = new Composite(cStart, SWT.NONE); layout = new GridLayout(2, false); layout.marginHeight = 0; layout.marginWidth = 0; cUISwitcher.setLayout(layout); final Label ui_switcher_label = new Label(cUISwitcher, SWT.NULL); Messages.setLanguageText(ui_switcher_label, "ConfigView.label.ui_switcher"); final Button ui_switcher_button = new Button(cUISwitcher, SWT.PUSH); Messages.setLanguageText(ui_switcher_button, "ConfigView.label.ui_switcher_button"); ui_switcher_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { UISwitcherUtil.openSwitcherWindow(); } }); return cStart; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileTorrents.java0000644000175000017500000002075611156364756031547 0ustar adrianadrian/* * File : ConfigPanelFileTorrents.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.ui.config.ConfigSection; public class ConfigSectionFileTorrents implements UISWTConfigSection { public String configSectionGetParentSection() { return ConfigSection.SECTION_FILES; } public String configSectionGetName() { return "torrents"; } public void configSectionSave() { } public void configSectionDelete() { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage("openFolderButton"); } public int maxUserMode() { return 0; } public Composite configSectionCreate(final Composite parent) { ImageLoader imageLoader = ImageLoader.getInstance(); Image imgOpenFolder = imageLoader.getImage("openFolderButton"); GridData gridData; GridLayout layout; // Sub-Section: File -> Torrent // ---------------------------- Composite cTorrent = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cTorrent.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; cTorrent.setLayout(layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); // Save .Torrent files to.. BooleanParameter saveTorrents = new BooleanParameter(cTorrent, "Save Torrent Files", "ConfigView.label.savetorrents"); Composite gSaveTorrents = new Composite(cTorrent, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalIndent = 25; gridData.horizontalSpan = 2; gSaveTorrents.setLayoutData(gridData); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 3; gSaveTorrents.setLayout(layout); Label lSaveDir = new Label(gSaveTorrents, SWT.NULL); Messages.setLanguageText(lSaveDir, "ConfigView.label.savedirectory"); gridData = new GridData(GridData.FILL_HORIZONTAL); final StringParameter torrentPathParameter = new StringParameter(gSaveTorrents, "General_sDefaultTorrent_Directory"); torrentPathParameter.setLayoutData(gridData); Button browse2 = new Button(gSaveTorrents, SWT.PUSH); browse2.setImage(imgOpenFolder); imgOpenFolder.setBackground(browse2.getBackground()); browse2.setToolTipText(MessageText.getString("ConfigView.button.browse")); browse2.addListener(SWT.Selection, new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event event) { DirectoryDialog dialog = new DirectoryDialog(parent.getShell(), SWT.APPLICATION_MODAL); dialog.setFilterPath(torrentPathParameter.getValue()); dialog.setText(MessageText.getString("ConfigView.dialog.choosedefaulttorrentpath")); String path = dialog.open(); if (path != null) { torrentPathParameter.setValue(path); } } }); browse2.setLayoutData(new GridData()); gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(gSaveTorrents, "Save Torrent Backup", "ConfigView.label.savetorrentbackup").setLayoutData(gridData); Control[] controls = new Control[]{ gSaveTorrents }; IAdditionalActionPerformer grayPathAndButton1 = new ChangeSelectionActionPerformer(controls); saveTorrents.setAdditionalActionPerformer(grayPathAndButton1); gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter( cTorrent, "Default Start Torrents Stopped", "ConfigView.label.defaultstarttorrentsstopped").setLayoutData(gridData); // Watch Folder BooleanParameter watchFolder = new BooleanParameter(cTorrent, "Watch Torrent Folder", "ConfigView.label.watchtorrentfolder"); Composite gWatchFolder = new Composite(cTorrent, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalIndent = 25; gridData.horizontalSpan = 2; gWatchFolder.setLayoutData(gridData); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 3; gWatchFolder.setLayout(layout); Label lImportDir = new Label(gWatchFolder, SWT.NULL); Messages.setLanguageText(lImportDir, "ConfigView.label.importdirectory"); gridData = new GridData(GridData.FILL_HORIZONTAL); final StringParameter watchFolderPathParameter = new StringParameter(gWatchFolder, "Watch Torrent Folder Path", ""); watchFolderPathParameter.setLayoutData(gridData); Button browse4 = new Button(gWatchFolder, SWT.PUSH); browse4.setImage(imgOpenFolder); imgOpenFolder.setBackground(browse4.getBackground()); browse4.setToolTipText(MessageText.getString("ConfigView.button.browse")); browse4.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { DirectoryDialog dialog = new DirectoryDialog(parent.getShell(), SWT.APPLICATION_MODAL); dialog.setFilterPath(watchFolderPathParameter.getValue()); dialog.setText(MessageText.getString("ConfigView.dialog.choosewatchtorrentfolderpath")); String path = dialog.open(); if (path != null) { watchFolderPathParameter.setValue(path); } } }); Label lWatchTorrentFolderInterval = new Label(gWatchFolder, SWT.NULL); Messages.setLanguageText(lWatchTorrentFolderInterval, "ConfigView.label.watchtorrentfolderinterval"); String min = " " + MessageText.getString("ConfigView.section.stats.minutes"); String hr = " " + MessageText.getString("ConfigView.section.stats.hours"); int [] watchTorrentFolderIntervalValues = { 1, 2, 3, 4, 5, 10, 15, 30, 60, 2*60, 4*60, 6*60, 8*60, 12*60, 16*60, 20*60, 24*60 }; final String watchTorrentFolderIntervalLabels[] = new String[watchTorrentFolderIntervalValues.length]; for (int i = 0; i < watchTorrentFolderIntervalValues.length; i++) { int mins = watchTorrentFolderIntervalValues[i]; int hrs = mins/60; watchTorrentFolderIntervalLabels[i] = " " + (hrs==0?(mins + min):(hrs + hr )); } gridData = new GridData(); gridData.horizontalSpan = 2; new IntListParameter(gWatchFolder, "Watch Torrent Folder Interval", 1, watchTorrentFolderIntervalLabels, watchTorrentFolderIntervalValues).setLayoutData(gridData); gridData = new GridData(); gridData.horizontalSpan = 3; new BooleanParameter(gWatchFolder, "Start Watched Torrents Stopped", "ConfigView.label.startwatchedtorrentsstopped").setLayoutData(gridData); controls = new Control[]{ gWatchFolder }; watchFolder.setAdditionalActionPerformer(new ChangeSelectionActionPerformer(controls)); return cTorrent; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSecurity.java0000644000175000017500000005001011272146154030705 0ustar adrianadrian/* * Created on 12-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.configsections; import java.io.*; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.auth.CertificateCreatorWindow; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.Cursors; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import com.aelitis.azureus.core.security.*; import com.aelitis.azureus.ui.UserPrompterResultListener; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.ui.config.ConfigSection; /** * @author parg * */ public class ConfigSectionSecurity implements UISWTConfigSection { public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } public String configSectionGetName() { return( "security" ); } public void configSectionSave() { } public void configSectionDelete() { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage("openFolderButton"); } public int maxUserMode() { return 2; } public Composite configSectionCreate( final Composite parent) { int userMode = COConfigurationManager.getIntParameter("User Mode"); GridData gridData; Composite gSecurity = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gSecurity.setLayoutData(gridData); GridLayout layout = new GridLayout(); layout.numColumns = 3; gSecurity.setLayout(layout); // row Label cert_label = new Label(gSecurity, SWT.NULL ); Messages.setLanguageText(cert_label, "ConfigView.section.tracker.createcert"); Button cert_button = new Button(gSecurity, SWT.PUSH); Messages.setLanguageText(cert_button, "ConfigView.section.tracker.createbutton"); cert_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { new CertificateCreatorWindow(); } }); new Label(gSecurity, SWT.NULL ); // row Label info_label = new Label( gSecurity, SWT.WRAP ); Messages.setLanguageText( info_label, "ConfigView.section.security.toolsinfo" ); info_label.setLayoutData(Utils.getWrappableLabelGridData(3, 0)); // row Label lStatsPath = new Label(gSecurity, SWT.NULL); Messages.setLanguageText(lStatsPath, "ConfigView.section.security.toolsdir"); //$NON-NLS-1$ ImageLoader imageLoader = ImageLoader.getInstance(); Image imgOpenFolder = imageLoader.getImage("openFolderButton"); gridData = new GridData(); gridData.widthHint = 150; final StringParameter pathParameter = new StringParameter(gSecurity, "Security.JAR.tools.dir", ""); //$NON-NLS-1$ //$NON-NLS-2$ pathParameter.setLayoutData(gridData); Button browse = new Button(gSecurity, SWT.PUSH); browse.setImage(imgOpenFolder); imgOpenFolder.setBackground(browse.getBackground()); browse.setToolTipText(MessageText.getString("ConfigView.button.browse")); browse.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { DirectoryDialog dialog = new DirectoryDialog(parent.getShell(), SWT.APPLICATION_MODAL); dialog.setFilterPath(pathParameter.getValue()); dialog.setText(MessageText.getString("ConfigView.section.security.choosetoolssavedir")); //$NON-NLS-1$ String path = dialog.open(); if (path != null) { pathParameter.setValue(path); } } }); // row Label pw_label = new Label(gSecurity, SWT.NULL ); Messages.setLanguageText(pw_label, "ConfigView.section.security.clearpasswords"); Button pw_button = new Button(gSecurity, SWT.PUSH); Messages.setLanguageText(pw_button, "ConfigView.section.security.clearpasswords.button"); pw_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { SESecurityManager.clearPasswords(); CryptoManagerFactory.getSingleton().clearPasswords(); } }); new Label(gSecurity, SWT.NULL ); if ( userMode >= 2 ){ final CryptoManager crypt_man = CryptoManagerFactory.getSingleton(); final Group crypto_group = new Group(gSecurity, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; crypto_group.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; crypto_group.setLayout(layout); Messages.setLanguageText(crypto_group,"ConfigView.section.security.group.crypto"); // wiki link final Label linkLabel = new Label(crypto_group, SWT.NULL); linkLabel.setText(MessageText.getString("ConfigView.label.please.visit.here")); linkLabel.setData("http://www.azureuswiki.com/index.php?title=Public_Private_Keys"); linkLabel.setCursor(Cursors.handCursor); linkLabel.setForeground(Colors.blue); gridData = new GridData(); gridData.horizontalSpan = 3; linkLabel.setLayoutData(gridData); linkLabel.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } public void mouseDown(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } }); // publick key display byte[] public_key = crypt_man.getECCHandler().peekPublicKey(); Label public_key_label = new Label(crypto_group, SWT.NULL ); Messages.setLanguageText(public_key_label, "ConfigView.section.security.publickey"); final Label public_key_value = new Label(crypto_group, SWT.NULL ); if ( public_key == null ){ Messages.setLanguageText(public_key_value, "ConfigView.section.security.publickey.undef"); }else{ public_key_value.setText( Base32.encode( public_key )); } Messages.setLanguageText(public_key_value, "ConfigView.copy.to.clipboard.tooltip", true); public_key_value.setCursor(Cursors.handCursor); public_key_value.setForeground(Colors.blue); public_key_value.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { copyToClipboard(); } public void mouseDown(MouseEvent arg0) { copyToClipboard(); } protected void copyToClipboard() { new Clipboard(parent.getDisplay()).setContents(new Object[] {public_key_value.getText()}, new Transfer[] {TextTransfer.getInstance()}); } }); crypt_man.addKeyListener( new CryptoManagerKeyListener() { public void keyChanged( final CryptoHandler handler ) { final CryptoManagerKeyListener me = this; Utils.execSWTThread( new Runnable() { public void run() { if ( public_key_value.isDisposed()){ crypt_man.removeKeyListener( me ); }else{ if ( handler.getType() == CryptoManager.HANDLER_ECC ){ byte[] public_key = handler.peekPublicKey(); if ( public_key == null ){ Messages.setLanguageText(public_key_value, "ConfigView.section.security.publickey.undef"); }else{ public_key_value.setText( Base32.encode( public_key )); } crypto_group.layout(); } } } }); } public void keyLockStatusChanged( CryptoHandler handler ) { } }); new Label(crypto_group, SWT.NULL ); // manage keys /* gridData = new GridData(); gridData.horizontalSpan = 3; final BooleanParameter manage_keys = new BooleanParameter( crypto_group, "crypto.keys.system.managed.temp", "ConfigView.section.security.system.managed"); manage_keys.setLayoutData( gridData ); final CryptoManager crypto_man = CryptoManagerFactory.getSingleton(); final CryptoHandler ecc_handler = crypto_man.getECCHandler(); manage_keys.setSelected( ecc_handler.getDefaultPasswordHandlerType() == CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM ); manage_keys.addChangeListener( new ParameterChangeAdapter () { public void parameterChanged( Parameter p, boolean caused_internally ) { boolean existing_value = ecc_handler.getDefaultPasswordHandlerType() == CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM; if ( existing_value == manage_keys.isSelected()){ return; } String error = null; int new_type = manage_keys.isSelected()?CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM:CryptoManagerPasswordHandler.HANDLER_TYPE_USER; try{ ecc_handler.setDefaultPasswordHandlerType( new_type ); error = null; }catch( CryptoManagerPasswordException e ){ if ( e.wasIncorrect()){ error = MessageText.getString( "ConfigView.section.security.unlockkey.error" ); }else{ if ( existing_value || !ecc_handler.isUnlocked()){ error = MessageText.getString( "Torrent.create.progress.cancelled" ); }else{ error = MessageText.getString( "ConfigView.section.security.vuze.login" ); } } }catch( Throwable e ){ error = Debug.getNestedExceptionMessage( e ); } if ( error != null ){ MessageBoxShell mb = new MessageBoxShell( SWT.ICON_ERROR | SWT.OK, MessageText.getString("ConfigView.section.security.op.error.title"), MessageText.getString("ConfigView.section.security.op.error", new String[] { error })); mb.setParent(parent.getShell()); mb.open(null); } boolean new_value = ecc_handler.getDefaultPasswordHandlerType() == CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM; if ( new_value != manage_keys.isSelected()){ manage_keys.setSelected( new_value ); } } }); */ // reset keys Label reset_key_label = new Label(crypto_group, SWT.NULL ); Messages.setLanguageText(reset_key_label, "ConfigView.section.security.resetkey"); Button reset_key_button = new Button(crypto_group, SWT.PUSH); Messages.setLanguageText(reset_key_button, "ConfigView.section.security.clearpasswords.button"); reset_key_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { MessageBoxShell mb = new MessageBoxShell( SWT.ICON_WARNING | SWT.OK | SWT.CANCEL, MessageText.getString("ConfigView.section.security.resetkey.warning.title"), MessageText.getString("ConfigView.section.security.resetkey.warning")); mb.setDefaultButtonUsingStyle(SWT.CANCEL); mb.setParent(parent.getShell()); mb.open(new UserPrompterResultListener() { public void prompterClosed(int returnVal) { if (returnVal != SWT.OK) { return; } try{ crypt_man.getECCHandler().resetKeys( "Manual key reset" ); }catch( Throwable e ){ MessageBoxShell mb = new MessageBoxShell( SWT.ICON_ERROR | SWT.OK, MessageText.getString( "ConfigView.section.security.resetkey.error.title"), getError( e )); mb.setParent(parent.getShell()); mb.open(null); } } }); } }); new Label(crypto_group, SWT.NULL ); // unlock Label priv_key_label = new Label(crypto_group, SWT.NULL ); Messages.setLanguageText(priv_key_label, "ConfigView.section.security.unlockkey"); Button priv_key_button = new Button(crypto_group, SWT.PUSH); Messages.setLanguageText(priv_key_button, "ConfigView.section.security.unlockkey.button"); priv_key_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { try{ crypt_man.getECCHandler().getEncryptedPrivateKey( "Manual unlock" ); }catch( Throwable e ){ MessageBoxShell mb = new MessageBoxShell( SWT.ICON_ERROR | SWT.OK, MessageText.getString( "ConfigView.section.security.resetkey.error.title" ), getError( e )); mb.setParent(parent.getShell()); mb.open(null); }; } }); new Label(crypto_group, SWT.NULL ); // backup Label backup_keys_label = new Label(crypto_group, SWT.NULL ); Messages.setLanguageText(backup_keys_label, "ConfigView.section.security.backupkeys"); final Button backup_keys_button = new Button(crypto_group, SWT.PUSH); Messages.setLanguageText(backup_keys_button, "ConfigView.section.security.backupkeys.button"); backup_keys_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { FileDialog dialog = new FileDialog( backup_keys_button.getShell(), SWT.APPLICATION_MODAL ); String target = dialog.open(); if ( target != null ){ try{ String keys = crypt_man.getECCHandler().exportKeys(); PrintWriter pw = new PrintWriter(new FileWriter( target )); pw.println( keys ); pw.close(); }catch( Throwable e ){ MessageBoxShell mb = new MessageBoxShell( SWT.ICON_ERROR | SWT.OK, MessageText.getString( "ConfigView.section.security.op.error.title" ), MessageText.getString( "ConfigView.section.security.op.error", new String[]{ getError(e) })); mb.setParent(parent.getShell()); mb.open(null); } } } }); new Label(crypto_group, SWT.NULL ); // restore Label restore_keys_label = new Label(crypto_group, SWT.NULL ); Messages.setLanguageText(restore_keys_label, "ConfigView.section.security.restorekeys"); final Button restore_keys_button = new Button(crypto_group, SWT.PUSH); Messages.setLanguageText(restore_keys_button, "ConfigView.section.security.restorekeys.button"); restore_keys_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { FileDialog dialog = new FileDialog( backup_keys_button.getShell(), SWT.APPLICATION_MODAL ); String target = dialog.open(); if ( target != null ){ try{ LineNumberReader reader = new LineNumberReader( new FileReader( target )); String str = ""; while( true ){ String line = reader.readLine(); if ( line == null ){ break; } str += line + "\r\n"; } boolean restart = crypt_man.getECCHandler().importKeys(str); if ( restart ){ MessageBoxShell mb = new MessageBoxShell( SWT.ICON_INFORMATION | SWT.OK, MessageText.getString( "ConfigView.section.security.restart.title" ), MessageText.getString( "ConfigView.section.security.restart.msg" )); mb.setParent(parent.getShell()); mb.open(null); UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if ( uiFunctions != null ){ uiFunctions.dispose(true, false); } } }catch( Throwable e ){ MessageBoxShell mb = new MessageBoxShell( SWT.ICON_ERROR | SWT.OK, MessageText.getString( "ConfigView.section.security.op.error.title" ), MessageText.getString( "ConfigView.section.security.op.error", new String[]{ getError( e )})); mb.setParent(parent.getShell()); mb.open(null); } } } }); new Label(crypto_group, SWT.NULL ); } return gSecurity; } protected String getError( Throwable e ) { String error; if ( e instanceof CryptoManagerPasswordException ){ if (((CryptoManagerPasswordException)e).wasIncorrect()){ error = MessageText.getString( "ConfigView.section.security.unlockkey.error"); }else{ final CryptoManager crypto_man = CryptoManagerFactory.getSingleton(); final CryptoHandler ecc_handler = crypto_man.getECCHandler(); //if ( ecc_handler.getDefaultPasswordHandlerType() == CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM ){ // // error = MessageText.getString( "ConfigView.section.security.nopw_v" ); // //}else{ error = MessageText.getString( "ConfigView.section.security.nopw" ); //} } }else{ error = MessageText.getString( "ConfigView.section.security.resetkey.error" ) + ": " + Debug.getNestedExceptionMessage(e); } return( error ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceLegacy.java0000644000175000017500000001050511131053126032116 0ustar adrianadrian/** * Created on Jan 6, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.config.BooleanParameter; import org.gudy.azureus2.ui.swt.config.ChangeSelectionActionPerformer; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.plugins.ui.config.ConfigSection; /** * @author TuxPaper * @created Jan 6, 2009 * */ public class ConfigSectionInterfaceLegacy implements UISWTConfigSection { private final static String LBLKEY_PREFIX = "ConfigView.label."; private final int REQUIRED_MODE = 2; // @see org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection#configSectionCreate(org.eclipse.swt.widgets.Composite) public Composite configSectionCreate(Composite parent) { GridData gridData; GridLayout layout; Label label; Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 1; layout.marginWidth = 0; layout.marginHeight = 0; cSection.setLayout(layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); if (userMode < REQUIRED_MODE) { label = new Label(cSection, SWT.WRAP); gridData = new GridData(); gridData.horizontalSpan = 2; label.setLayoutData(gridData); final String[] modeKeys = { "ConfigView.section.mode.beginner", "ConfigView.section.mode.intermediate", "ConfigView.section.mode.advanced" }; String param1, param2; if (REQUIRED_MODE < modeKeys.length) param1 = MessageText.getString(modeKeys[REQUIRED_MODE]); else param1 = String.valueOf(REQUIRED_MODE); if (userMode < modeKeys.length) param2 = MessageText.getString(modeKeys[userMode]); else param2 = String.valueOf(userMode); label.setText(MessageText.getString("ConfigView.notAvailableForMode", new String[] { param1, param2 } )); return cSection; } /** * Old-style speed menus. */ new BooleanParameter(cSection, "GUI_SWT_bOldSpeedMenu", LBLKEY_PREFIX + "use_old_speed_menus"); BooleanParameter bpCustomTab = new BooleanParameter(cSection, "useCustomTab", "ConfigView.section.style.useCustomTabs"); Control cFancyTab = new BooleanParameter(cSection, "GUI_SWT_bFancyTab", "ConfigView.section.style.useFancyTabs").getControl(); Control[] controls = { cFancyTab }; bpCustomTab.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( controls)); return cSection; } // @see org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection#maxUserMode() public int maxUserMode() { return REQUIRED_MODE; } // @see org.gudy.azureus2.plugins.ui.config.ConfigSection#configSectionDelete() public void configSectionDelete() { // TODO Auto-generated method stub } // @see org.gudy.azureus2.plugins.ui.config.ConfigSection#configSectionGetName() public String configSectionGetName() { return "interface.legacy"; } // @see org.gudy.azureus2.plugins.ui.config.ConfigSection#configSectionGetParentSection() public String configSectionGetParentSection() { return ConfigSection.SECTION_INTERFACE; } // @see org.gudy.azureus2.plugins.ui.config.ConfigSection#configSectionSave() public void configSectionSave() { // TODO Auto-generated method stub } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceAlerts.java0000644000175000017500000003364011256315674032172 0ustar adrianadrian/* * File : ConfigSectionInterfaceAlerts.java * Created : Dec 4, 2006 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import java.applet.Applet; import java.io.File; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.ImageRepository; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.ui.swt.shells.MessageSlideShell; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; public class ConfigSectionInterfaceAlerts implements UISWTConfigSection { private final static String INTERFACE_PREFIX = "ConfigView.section.interface."; private final static String LBLKEY_PREFIX = "ConfigView.label."; private final static String STYLE_PREFIX = "ConfigView.section.style."; private final int REQUIRED_MODE = 0; public String configSectionGetParentSection() { return ConfigSection.SECTION_INTERFACE; } /* Name of section will be pulled from * ConfigView.section.configSectionGetName() */ public String configSectionGetName() { return "interface.alerts"; } public void configSectionSave() { } public void configSectionDelete() { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage("openFolderButton"); } public int maxUserMode() { return REQUIRED_MODE; } public Composite configSectionCreate(final Composite parent) { Image imgOpenFolder = null; if (!Constants.isOSX) { ImageLoader imageLoader = ImageLoader.getInstance(); imgOpenFolder = imageLoader.getImage("openFolderButton"); } GridData gridData; GridLayout layout; Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); layout = new GridLayout(); layout.marginWidth = 0; //layout.numColumns = 2; cSection.setLayout(layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); if (userMode < REQUIRED_MODE) { Label label = new Label(cSection, SWT.WRAP); gridData = new GridData(); label.setLayoutData(gridData); final String[] modeKeys = { "ConfigView.section.mode.beginner", "ConfigView.section.mode.intermediate", "ConfigView.section.mode.advanced" }; String param1, param2; if (REQUIRED_MODE < modeKeys.length) param1 = MessageText.getString(modeKeys[REQUIRED_MODE]); else param1 = String.valueOf(REQUIRED_MODE); if (userMode < modeKeys.length) param2 = MessageText.getString(modeKeys[userMode]); else param2 = String.valueOf(userMode); label.setText(MessageText.getString("ConfigView.notAvailableForMode", new String[] { param1, param2 })); return cSection; } Composite cArea = new Composite(cSection, SWT.NONE); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 4; cArea.setLayout(layout); cArea.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); BooleanParameter d_play_sound = new BooleanParameter(cArea, "Play Download Finished", LBLKEY_PREFIX + "playdownloadfinished"); // OS X counterpart for alerts (see below for what is disabled) if (Constants.isOSX) { // download info gridData = new GridData(); gridData.horizontalSpan = 3; gridData.widthHint = 0; gridData.heightHint = 0; Composite d_filler = new Composite(cArea, SWT.NONE); d_filler.setSize(0, 0); d_filler.setLayoutData(gridData); final BooleanParameter d_speechEnabledParameter = new BooleanParameter( cArea, "Play Download Finished Announcement", LBLKEY_PREFIX + "playdownloadspeech"); final StringParameter d_speechParameter = new StringParameter(cArea, "Play Download Finished Announcement Text"); gridData = new GridData(); gridData.horizontalSpan = 3; gridData.widthHint = 150; d_speechParameter.setLayoutData(gridData); ((Text) d_speechParameter.getControl()).setTextLimit(40); d_speechEnabledParameter.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( d_speechParameter.getControls())); final Label d_speechInfo = new Label(cArea, SWT.NONE); gridData = new GridData(); gridData.horizontalSpan = 4; gridData.horizontalIndent = 24; d_speechInfo.setLayoutData(gridData); Messages.setLanguageText(d_speechInfo, LBLKEY_PREFIX + "playdownloadspeech.info"); } //Option disabled on OS X, as impossible to make it work correctly if (!Constants.isOSX) { // download info gridData = new GridData(GridData.FILL_HORIZONTAL); final StringParameter d_pathParameter = new StringParameter(cArea, "Play Download Finished File", ""); if (d_pathParameter.getValue().length() == 0) { d_pathParameter.setValue(""); } d_pathParameter.setLayoutData(gridData); Button d_browse = new Button(cArea, SWT.PUSH); d_browse.setImage(imgOpenFolder); imgOpenFolder.setBackground(d_browse.getBackground()); d_browse.setToolTipText(MessageText.getString("ConfigView.button.browse")); d_browse.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { FileDialog dialog = new FileDialog(parent.getShell(), SWT.APPLICATION_MODAL); dialog.setFilterExtensions(new String[] { "*.wav" }); dialog.setFilterNames(new String[] { "*.wav" }); dialog.setText(MessageText.getString(INTERFACE_PREFIX + "wavlocation")); final String path = dialog.open(); if (path != null) { d_pathParameter.setValue(path); new AEThread("SoundTest") { public void runSupport() { try { Applet.newAudioClip(new File(path).toURL()).play(); Thread.sleep(2500); } catch (Throwable e) { } } }.start(); } } }); Label d_sound_info = new Label(cArea, SWT.WRAP); Messages.setLanguageText(d_sound_info, INTERFACE_PREFIX + "wavlocation.info"); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.widthHint = 100; d_sound_info.setLayoutData(gridData); d_play_sound.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( d_pathParameter.getControls())); d_play_sound.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( new Control[] { d_browse, d_sound_info })); // } BooleanParameter f_play_sound = new BooleanParameter(cArea, "Play File Finished", LBLKEY_PREFIX + "playfilefinished"); // OS X counterpart for alerts (see below for what is disabled) if (Constants.isOSX) { // per-file info gridData = new GridData(); gridData.horizontalSpan = 3; gridData.widthHint = 0; gridData.heightHint = 0; Composite f_filler = new Composite(cArea, SWT.NONE); f_filler.setSize(0, 0); f_filler.setLayoutData(gridData); final BooleanParameter f_speechEnabledParameter = new BooleanParameter( cArea, "Play File Finished Announcement", LBLKEY_PREFIX + "playfilespeech"); final StringParameter f_speechParameter = new StringParameter(cArea, "Play File Finished Announcement Text"); gridData = new GridData(); gridData.horizontalSpan = 3; gridData.widthHint = 150; f_speechParameter.setLayoutData(gridData); ((Text) f_speechParameter.getControl()).setTextLimit(40); f_speechEnabledParameter.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( f_speechParameter.getControls())); final Label speechInfo = new Label(cArea, SWT.NONE); gridData = new GridData(); gridData.horizontalSpan = 4; gridData.horizontalIndent = 24; speechInfo.setLayoutData(gridData); Messages.setLanguageText(speechInfo, LBLKEY_PREFIX + "playfilespeech.info"); } //Option disabled on OS X, as impossible to make it work correctly if (!Constants.isOSX) { // file info gridData = new GridData(GridData.FILL_HORIZONTAL); final StringParameter f_pathParameter = new StringParameter(cArea, "Play File Finished File", ""); if (f_pathParameter.getValue().length() == 0) { f_pathParameter.setValue(""); } f_pathParameter.setLayoutData(gridData); Button f_browse = new Button(cArea, SWT.PUSH); f_browse.setImage(imgOpenFolder); imgOpenFolder.setBackground(f_browse.getBackground()); f_browse.setToolTipText(MessageText.getString("ConfigView.button.browse")); f_browse.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { FileDialog dialog = new FileDialog(parent.getShell(), SWT.APPLICATION_MODAL); dialog.setFilterExtensions(new String[] { "*.wav" }); dialog.setFilterNames(new String[] { "*.wav" }); dialog.setText(MessageText.getString(INTERFACE_PREFIX + "wavlocation")); final String path = dialog.open(); if (path != null) { f_pathParameter.setValue(path); new AEThread("SoundTest") { public void runSupport() { try { Applet.newAudioClip(new File(path).toURL()).play(); Thread.sleep(2500); } catch (Throwable e) { } } }.start(); } } }); Label f_sound_info = new Label(cArea, SWT.WRAP); Messages.setLanguageText(f_sound_info, INTERFACE_PREFIX + "wavlocation.info"); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.widthHint = 100; f_sound_info.setLayoutData(gridData); f_play_sound.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( f_pathParameter.getControls())); f_play_sound.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( new Control[] { f_browse, f_sound_info })); } cArea = new Composite(cSection, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 2; cArea.setLayout(layout); cArea.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); BooleanParameter popup_dl_added = new BooleanParameter(cArea, "Popup Download Added", LBLKEY_PREFIX + "popupdownloadadded"); gridData = new GridData(); gridData.horizontalSpan = 2; popup_dl_added.setLayoutData(gridData); BooleanParameter popup_dl_completed = new BooleanParameter(cArea, "Popup Download Finished", LBLKEY_PREFIX + "popupdownloadfinished"); gridData = new GridData(); gridData.horizontalSpan = 2; popup_dl_completed.setLayoutData(gridData); BooleanParameter popup_file_completed = new BooleanParameter(cArea, "Popup File Finished", LBLKEY_PREFIX + "popupfilefinished"); gridData = new GridData(); gridData.horizontalSpan = 2; popup_file_completed.setLayoutData(gridData); BooleanParameter disable_sliding = new BooleanParameter(cArea, "GUI_SWT_DisableAlertSliding", STYLE_PREFIX + "disableAlertSliding"); gridData = new GridData(); gridData.horizontalSpan = 2; disable_sliding.setLayoutData(gridData); // Timestamps for popup alerts. BooleanParameter show_alert_timestamps = new BooleanParameter(cArea, "Show Timestamp For Alerts", LBLKEY_PREFIX + "popup.timestamp"); gridData = new GridData(); gridData.horizontalSpan = 2; show_alert_timestamps.setLayoutData(gridData); // Auto-hide popup setting. Label label = new Label(cArea, SWT.WRAP); Messages.setLanguageText(label, LBLKEY_PREFIX + "popup.autohide"); label.setLayoutData(Utils.getWrappableLabelGridData(1, 0)); IntParameter auto_hide_alert = new IntParameter(cArea, "Message Popup Autoclose in Seconds", 0, 86400); gridData = new GridData(); gridData.horizontalSpan = 1; auto_hide_alert.setLayoutData(gridData); // Use popup boxes rather than Mr Slidey. BooleanParameter use_popup_boxes = new BooleanParameter(cArea, "Use Message Box For Popups", LBLKEY_PREFIX + "popup.use_message_boxes"); gridData = new GridData(); gridData.horizontalSpan = 2; use_popup_boxes.setLayoutData(gridData); // Suppress alerts. BooleanParameter suppress_alerts = new BooleanParameter(cArea, "Suppress Alerts", LBLKEY_PREFIX + "popup.suppress_alerts"); gridData = new GridData(); gridData.horizontalSpan = 2; suppress_alerts.setLayoutData(gridData); // Show alerts. label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, LBLKEY_PREFIX + "popup.show"); ButtonParameter show_alerts = new ButtonParameter(cArea, LBLKEY_PREFIX + "popup.show.button"); show_alerts.addChangeListener(new ParameterChangeAdapter() { public void parameterChanged(Parameter p, boolean b) { Display display = parent.getDisplay(); if (display.isDisposed()) {return;} MessageSlideShell.displayLastMessage(display, true); } }); gridData = new GridData(); gridData.horizontalSpan = 1; gridData.widthHint = 60; show_alerts.setLayoutData(gridData); return cSection; } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileTorrentsDecoding.javaazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileTorrentsDecoding.java0000644000175000017500000001117510747145304033166 0ustar adrianadrian/* * File : ConfigSection*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.LocaleUtil; import org.gudy.azureus2.core3.internat.LocaleUtilDecoder; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.config.BooleanParameter; import org.gudy.azureus2.ui.swt.config.StringListParameter; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; public class ConfigSectionFileTorrentsDecoding implements UISWTConfigSection { private final int REQUIRED_MODE = 2; public String configSectionGetParentSection() { return "torrents"; } public int maxUserMode() { return REQUIRED_MODE; } /* Name of section will be pulled from * ConfigView.section.configSectionGetName() */ public String configSectionGetName() { return "torrent.decoding"; } public void configSectionSave() { } public void configSectionDelete() { } public Composite configSectionCreate(final Composite parent) { GridData gridData; GridLayout layout; Label label; Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; cSection.setLayout(layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); if (userMode < REQUIRED_MODE) { label = new Label(cSection, SWT.WRAP); gridData = new GridData(); label.setLayoutData(gridData); final String[] modeKeys = { "ConfigView.section.mode.beginner", "ConfigView.section.mode.intermediate", "ConfigView.section.mode.advanced" }; String param1, param2; if (REQUIRED_MODE < modeKeys.length) param1 = MessageText.getString(modeKeys[REQUIRED_MODE]); else param1 = String.valueOf(REQUIRED_MODE); if (userMode < modeKeys.length) param2 = MessageText.getString(modeKeys[userMode]); else param2 = String.valueOf(userMode); label.setText(MessageText.getString("ConfigView.notAvailableForMode", new String[] { param1, param2 })); return cSection; } // locale decoder label = new Label(cSection, SWT.NULL); Messages.setLanguageText(label, "ConfigView.section.file.decoder.label"); LocaleUtilDecoder[] decoders = LocaleUtil.getSingleton().getDecoders(); String decoderLabels[] = new String[decoders.length + 1]; String decoderValues[] = new String[decoders.length + 1]; decoderLabels[0] = MessageText.getString("ConfigView.section.file.decoder.nodecoder"); decoderValues[0] = ""; for (int i = 1; i <= decoders.length; i++) { decoderLabels[i] = decoderValues[i] = decoders[i - 1].getName(); } new StringListParameter(cSection, "File.Decoder.Default", "", decoderLabels, decoderValues); // locale always prompt gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(cSection, "File.Decoder.Prompt", "ConfigView.section.file.decoder.prompt").setLayoutData(gridData); // show lax decodings gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(cSection, "File.Decoder.ShowLax", "ConfigView.section.file.decoder.showlax").setLayoutData(gridData); // show all decoders gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(cSection, "File.Decoder.ShowAll", "ConfigView.section.file.decoder.showall").setLayoutData(gridData); return cSection; } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionEncryption.javaazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionEncryption.java0000644000175000017500000001610011046773326033260 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.components.LinkLabel; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; public class ConfigSectionConnectionEncryption implements UISWTConfigSection { private final String CFG_PREFIX = "ConfigView.section.connection.encryption."; private final int REQUIRED_MODE = 1; public int maxUserMode() { return REQUIRED_MODE; } public String configSectionGetParentSection() { return ConfigSection.SECTION_CONNECTION; } public String configSectionGetName() { return "connection.encryption"; } public void configSectionSave() { } public void configSectionDelete() { } public Composite configSectionCreate(final Composite parent) { GridData gridData; Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL + GridData.VERTICAL_ALIGN_FILL); cSection.setLayoutData(gridData); GridLayout advanced_layout = new GridLayout(); cSection.setLayout(advanced_layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); if (userMode < REQUIRED_MODE) { Label label = new Label(cSection, SWT.WRAP); gridData = new GridData(); label.setLayoutData(gridData); final String[] modeKeys = { "ConfigView.section.mode.beginner", "ConfigView.section.mode.intermediate", "ConfigView.section.mode.advanced" }; String param1, param2; if (REQUIRED_MODE < modeKeys.length) param1 = MessageText.getString(modeKeys[REQUIRED_MODE]); else param1 = String.valueOf(REQUIRED_MODE); if (userMode < modeKeys.length) param2 = MessageText.getString(modeKeys[userMode]); else param2 = String.valueOf(userMode); label.setText(MessageText.getString("ConfigView.notAvailableForMode", new String[] { param1, param2 } )); return cSection; } Group gCrypto = new Group(cSection, SWT.NULL); Messages.setLanguageText(gCrypto, CFG_PREFIX + "encrypt.group"); gridData = new GridData(GridData.FILL_HORIZONTAL); gCrypto.setLayoutData(gridData); GridLayout layout = new GridLayout(); layout.numColumns = 2; gCrypto.setLayout(layout); Label lcrypto = new Label(gCrypto, SWT.WRAP); Messages.setLanguageText(lcrypto, CFG_PREFIX + "encrypt.info"); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; gridData.widthHint = 200; // needed for wrap lcrypto.setLayoutData(gridData); gridData = new GridData(); gridData.horizontalSpan = 2; new LinkLabel(gCrypto, gridData, CFG_PREFIX + "encrypt.info.link", "http://www.azureuswiki.com/index.php/Avoid_traffic_shaping"); final BooleanParameter require = new BooleanParameter(gCrypto, "network.transport.encrypted.require", CFG_PREFIX + "require_encrypted_transport"); gridData = new GridData(); gridData.horizontalSpan = 2; require.setLayoutData(gridData); String[] encryption_types = { "Plain", "RC4" }; String dropLabels[] = new String[encryption_types.length]; String dropValues[] = new String[encryption_types.length]; for (int i = 0; i < encryption_types.length; i++) { dropLabels[i] = encryption_types[i]; dropValues[i] = encryption_types[i]; } Composite cEncryptLevel = new Composite(gCrypto, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan = 2; cEncryptLevel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; layout.marginWidth = 0; layout.marginHeight = 0; cEncryptLevel.setLayout(layout); Label lmin = new Label(cEncryptLevel, SWT.NULL); Messages.setLanguageText(lmin, CFG_PREFIX + "min_encryption_level"); final StringListParameter min_level = new StringListParameter(cEncryptLevel, "network.transport.encrypted.min_level", encryption_types[1], dropLabels, dropValues); Label lcryptofb = new Label(gCrypto, SWT.WRAP); Messages.setLanguageText(lcryptofb, CFG_PREFIX + "encrypt.fallback_info"); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; gridData.widthHint = 200; // needed for wrap lcryptofb.setLayoutData(gridData); BooleanParameter fallback_outgoing = new BooleanParameter(gCrypto, "network.transport.encrypted.fallback.outgoing", CFG_PREFIX + "encrypt.fallback_outgoing"); gridData = new GridData(); gridData.horizontalSpan = 2; fallback_outgoing.setLayoutData(gridData); final BooleanParameter fallback_incoming = new BooleanParameter(gCrypto, "network.transport.encrypted.fallback.incoming", CFG_PREFIX + "encrypt.fallback_incoming"); gridData = new GridData(); gridData.horizontalSpan = 2; fallback_incoming.setLayoutData(gridData); final BooleanParameter use_crypto_port = new BooleanParameter(gCrypto, "network.transport.encrypted.use.crypto.port", CFG_PREFIX + "use_crypto_port"); gridData = new GridData(); gridData.horizontalSpan = 2; use_crypto_port.setLayoutData(gridData); final Control[] ap_controls = { min_level.getControl(), lmin, lcryptofb, fallback_outgoing.getControl(), fallback_incoming.getControl()}; IAdditionalActionPerformer iap = new GenericActionPerformer(new Control[] {}) { public void performAction() { boolean required = require.isSelected(); boolean ucp_enabled = !fallback_incoming.isSelected() && required; use_crypto_port.getControl().setEnabled( ucp_enabled ); for (int i=0;i * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class ConfigSectionTransferAutoSpeedSelect implements UISWTConfigSection { private final String CFG_PREFIX = "ConfigView.section.transfer.autospeed."; StringListParameter versionList; BooleanParameter enableAutoSpeed; BooleanParameter enableAutoSpeedWhileSeeding; /** * Returns section you want your configuration panel to be under. * See SECTION_* constants. To add a subsection to your own ConfigSection, * return the configSectionGetName result of your parent.
    */ public String configSectionGetParentSection() { return ConfigSection.SECTION_TRANSFER; } /** * In order for the plugin to display its section correctly, a key in the * Plugin language file will need to contain * ConfigView.section.<configSectionGetName() result>=The Section name.
    * * @return The name of the configuration section */ public String configSectionGetName() { return "transfer.select"; } /** * User selected Save. * All saving of non-plugin tabs have been completed, as well as * saving of plugins that implement org.gudy.azureus2.plugins.ui.config * parameters. */ public void configSectionSave() { } /** * Config view is closing */ public void configSectionDelete() { } public int maxUserMode() { return 0; } /** * Create your own configuration panel here. It can be anything that inherits * from SWT's Composite class. * Please be mindfull of small screen resolutions * * @param parent The parent of your configuration panel * @return your configuration panel */ public Composite configSectionCreate(final Composite parent) { GridData gridData; Composite cSection = new Composite(parent, SWT.NULL); if (!AzureusCoreFactory.isCoreRunning()) { cSection.setLayout(new FillLayout()); Label lblNotAvail = new Label(cSection, SWT.WRAP); Messages.setLanguageText(lblNotAvail, "core.not.available"); return cSection; } gridData = new GridData(GridData.VERTICAL_ALIGN_FILL|GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); GridLayout subPanel = new GridLayout(); subPanel.numColumns = 3; cSection.setLayout(subPanel); //V1, V2 ... drop down. //enable auto-speed beta /////////////////////////////////// // AutoSpeed Beta mode group /////////////////////////////////// //Beta-mode grouping. Group modeGroup = new Group(cSection, SWT.NULL); Messages.setLanguageText(modeGroup,"ConfigTransferAutoSpeed.algorithm.selector"); GridLayout modeLayout = new GridLayout(); modeLayout.numColumns = 3; modeGroup.setLayout(modeLayout); gridData = new GridData(GridData.FILL_HORIZONTAL); modeGroup.setLayoutData(gridData); //Need a drop down to select which method will be used. Label label = new Label(modeGroup, SWT.NULL); Messages.setLanguageText(label,"ConfigTransferAutoSpeed.algorithm"); gridData = new GridData(); label.setLayoutData(gridData); String AutoSpeedClassic = MessageText.getString("ConfigTransferAutoSpeed.auto.speed.classic"); String AutoSpeedBeta = MessageText.getString("ConfigTransferAutoSpeed.auto.speed.beta"); String AutoSpeedNeural = MessageText.getString("ConfigTransferAutoSpeed.auto.speed.neural"); String[] modeNames = { AutoSpeedClassic, AutoSpeedBeta, AutoSpeedNeural, }; String[] modes = { "1", "2", "3", }; //versionList = new StringListParameter(modeGroup, // SpeedManagerImpl.CONFIG_VERSION_STR, // "1", // modeNames,modes,true); versionList = new StringListParameter(modeGroup,SpeedManagerImpl.CONFIG_VERSION_STR, modeNames, modes); long verNum = COConfigurationManager.getLongParameter( SpeedManagerImpl.CONFIG_VERSION ); if( verNum==1 ){ //SpeedManagerAlgorithmProviderV1 versionList.setValue(modes[0]); }else if( verNum==2 ){ //SpeedManagerAlgorithmProviderV2 versionList.setValue(modes[1]); }else if( verNum==3 ){ //SpeedManagerAlgorithmProviderV2 versionList.setValue(modes[2]); }else{ //Default is currently version ...V1. versionList.setValue(modes[0]); //ToDo: log this condition. } versionList.addChangeListener( new ConvertToLongChangeListener() ); //spacer Label spacer = new Label(modeGroup, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan=3; spacer.setLayoutData(gridData); //To enable the beta. gridData = new GridData(); gridData.horizontalIndent = 20; gridData.horizontalSpan = 2; enableAutoSpeed = new BooleanParameter(modeGroup, TransferSpeedValidator.AUTO_UPLOAD_ENABLED_CONFIGKEY,CFG_PREFIX+"enableauto"); enableAutoSpeed.setLayoutData(gridData); //enableAutoSpeed.addChangeListener( new GroupModeChangeListener() ); spacer = new Label(modeGroup, SWT.NULL); //AutoSpeed while seeding enabled. enableAutoSpeedWhileSeeding = new BooleanParameter(modeGroup, "Auto Upload Speed Seeding Enabled",CFG_PREFIX+"enableautoseeding"); gridData = new GridData(); gridData.horizontalIndent = 20; gridData.horizontalSpan = 2; enableAutoSpeedWhileSeeding.setLayoutData(gridData); enableAutoSpeed.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( enableAutoSpeedWhileSeeding.getControls(), true )); spacer = new Label(modeGroup, SWT.NULL); spacer = new Label(cSection, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan=3; spacer.setLayoutData(gridData); // NETWORK GROUP Group networkGroup = new Group(cSection, SWT.NULL); //networkGroup.addControlListener(new Utils.LabelWrapControlListener()); Messages.setLanguageText(networkGroup,CFG_PREFIX+"networks"); GridLayout networksLayout = new GridLayout(); networksLayout.numColumns = 5; networkGroup.setLayout(networksLayout); gridData = new GridData(GridData.FILL_HORIZONTAL); networkGroup.setLayoutData(gridData); // asn label = new Label(networkGroup, SWT.NULL); Messages.setLanguageText(label,"SpeedView.stats.asn"); final Label asn_label = new Label(networkGroup, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 4; gridData.grabExcessHorizontalSpace = true; asn_label.setLayoutData(gridData); // up cap label = new Label(networkGroup, SWT.NULL); Messages.setLanguageText(label,"SpeedView.stats.estupcap"); gridData = new GridData(); gridData.horizontalIndent = 20; label.setLayoutData(gridData); final Label up_cap = new Label(networkGroup, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 4; up_cap.setLayoutData(gridData); // down cap label = new Label(networkGroup, SWT.NULL); Messages.setLanguageText(label,"SpeedView.stats.estdowncap"); gridData = new GridData(); gridData.horizontalIndent = 20; label.setLayoutData(gridData); final Label down_cap = new Label(networkGroup, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 4; down_cap.setLayoutData(gridData); // Core avail: We check at top final SpeedManager sm = AzureusCoreFactory.getSingleton().getSpeedManager(); final TransferStatsView.limitToTextHelper limit_to_text = new TransferStatsView.limitToTextHelper(); asn_label.setText( sm.getASN()); up_cap.setText( limit_to_text.getLimitText( sm.getEstimatedUploadCapacityBytesPerSec())); down_cap.setText( limit_to_text.getLimitText( sm.getEstimatedDownloadCapacityBytesPerSec())); // space spacer = new Label(networkGroup, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan=5; spacer.setLayoutData(gridData); // info Label info_label = new Label(networkGroup, SWT.WRAP ); Messages.setLanguageText( info_label, CFG_PREFIX + "network.info", new String[]{ DisplayFormatters.getRateUnit( DisplayFormatters.UNIT_KB )}); info_label.setLayoutData(Utils.getWrappableLabelGridData(5, 0)); // up set label = new Label(networkGroup, SWT.NULL); Messages.setLanguageText(label,"SpeedView.stats.estupcap"); gridData = new GridData(); gridData.horizontalIndent = 20; label.setLayoutData(gridData); String co_up = "AutoSpeed Network Upload Speed (temp)"; String co_up_type = "AutoSpeed Network Upload Speed Type (temp)"; SpeedManagerLimitEstimate up_lim = sm.getEstimatedUploadCapacityBytesPerSec(); COConfigurationManager.setParameter( co_up, up_lim.getBytesPerSec()/1024 ); COConfigurationManager.setParameter( co_up_type, limit_to_text.getSettableType( up_lim )); final IntParameter max_upload = new IntParameter(networkGroup, co_up ); final Label upload_bits = new Label(networkGroup, SWT.NULL); gridData = new GridData(); upload_bits.setLayoutData(gridData); upload_bits.setText(getMBitLimit(limit_to_text,(up_lim.getBytesPerSec()/1024)*1024)); final StringListParameter max_upload_type = new StringListParameter(networkGroup, co_up_type, limit_to_text.getSettableTypes(),limit_to_text.getSettableTypes() ); max_upload_type.addChangeListener( new ParameterChangeAdapter() { public void parameterChanged( Parameter p, boolean caused_internally ) { if ( max_upload_type.isDisposed()){ return; } float type = limit_to_text.textToType( max_upload_type.getValue()); SpeedManagerLimitEstimate existing = sm.getEstimatedUploadCapacityBytesPerSec(); if ( existing.getEstimateType() != type ){ sm.setEstimatedUploadCapacityBytesPerSec( existing.getBytesPerSec(), type ); } } }); max_upload.addChangeListener( new ParameterChangeAdapter() { public void parameterChanged( Parameter p, boolean caused_internally ) { if ( max_upload.isDisposed()){ return; } int value = max_upload.getValue() * 1024; SpeedManagerLimitEstimate existing = sm.getEstimatedUploadCapacityBytesPerSec(); if ( existing.getBytesPerSec() != value ){ sm.setEstimatedUploadCapacityBytesPerSec( value, existing.getEstimateType()); } } }); label = new Label(networkGroup, SWT.NULL); // down set label = new Label(networkGroup, SWT.NULL); Messages.setLanguageText(label,"SpeedView.stats.estdowncap"); gridData = new GridData(); gridData.horizontalIndent = 20; label.setLayoutData(gridData); SpeedManagerLimitEstimate down_lim = sm.getEstimatedDownloadCapacityBytesPerSec(); String co_down = "AutoSpeed Network Download Speed (temp)"; String co_down_type = "AutoSpeed Network Download Speed Type (temp)"; COConfigurationManager.setParameter( co_down, down_lim.getBytesPerSec()/1024 ); COConfigurationManager.setParameter( co_down_type, limit_to_text.getSettableType( down_lim )); final IntParameter max_download = new IntParameter(networkGroup, co_down ); final Label download_bits = new Label(networkGroup, SWT.NULL); gridData = new GridData(); download_bits.setLayoutData(gridData); download_bits.setText(getMBitLimit(limit_to_text,(down_lim.getBytesPerSec()/1024)*1024)); final StringListParameter max_download_type = new StringListParameter(networkGroup, co_down_type, limit_to_text.getSettableTypes(),limit_to_text.getSettableTypes() ); max_download_type.addChangeListener( new ParameterChangeAdapter() { public void parameterChanged( Parameter p, boolean caused_internally ) { if ( max_download_type.isDisposed()){ return; } float type = limit_to_text.textToType( max_download_type.getValue()); SpeedManagerLimitEstimate existing = sm.getEstimatedDownloadCapacityBytesPerSec(); if ( existing.getEstimateType() != type ){ sm.setEstimatedDownloadCapacityBytesPerSec( existing.getBytesPerSec(), type ); } } }); max_download.addChangeListener( new ParameterChangeAdapter() { public void parameterChanged( Parameter p, boolean caused_internally ) { if ( max_download.isDisposed()){ return; } int value = max_download.getValue() * 1024; SpeedManagerLimitEstimate existing = sm.getEstimatedDownloadCapacityBytesPerSec(); if ( existing.getBytesPerSec() != value ){ sm.setEstimatedDownloadCapacityBytesPerSec( value, existing.getEstimateType()); } } }); label = new Label(networkGroup, SWT.NULL); // reset Label reset_label = new Label(networkGroup, SWT.NULL ); Messages.setLanguageText(reset_label, CFG_PREFIX + "resetnetwork"); Button reset_button = new Button(networkGroup, SWT.PUSH); Messages.setLanguageText(reset_button, CFG_PREFIX + "reset.button" ); reset_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { sm.reset(); } }); sm.addListener( new SpeedManagerListener() { private final SpeedManagerListener listener = this; public void propertyChanged( final int property ) { Utils.execSWTThread( new Runnable() { public void run() { if ( asn_label.isDisposed()){ sm.removeListener( listener ); }else{ if ( property == SpeedManagerListener.PR_ASN ){ asn_label.setText( sm.getASN()); }else if ( property == SpeedManagerListener.PR_UP_CAPACITY ){ SpeedManagerLimitEstimate limit = sm.getEstimatedUploadCapacityBytesPerSec(); up_cap.setText( limit_to_text.getLimitText( limit )); upload_bits.setText(getMBitLimit(limit_to_text, limit.getBytesPerSec())); max_upload.setValue( limit.getBytesPerSec()/1024 ); max_upload_type.setValue( limit_to_text.getSettableType( limit )); }else if ( property == SpeedManagerListener.PR_DOWN_CAPACITY ){ SpeedManagerLimitEstimate limit = sm.getEstimatedDownloadCapacityBytesPerSec(); down_cap.setText( limit_to_text.getLimitText( limit )); download_bits.setText(getMBitLimit(limit_to_text, limit.getBytesPerSec())); max_download.setValue( limit.getBytesPerSec()/1024 ); max_download_type.setValue( limit_to_text.getSettableType( limit )); } } } }); } }); //Add listeners to disable setting when needed. //spacer spacer = new Label(cSection, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan=3; spacer.setLayoutData(gridData); BooleanParameter debug_au = new BooleanParameter( cSection, "Auto Upload Speed Debug Enabled", CFG_PREFIX + "enabledebug" ); gridData = new GridData(); gridData.horizontalSpan = 3; debug_au.setLayoutData(gridData); //spacer spacer = new Label(cSection, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan=3; spacer.setLayoutData(gridData); ///////////////////////////////////////// //Add group to link to Azureus Wiki page. ///////////////////////////////////////// Group azWiki = new Group(cSection, SWT.WRAP); gridData = new GridData(); azWiki.setLayoutData(gridData); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.marginHeight = 1; layout.marginWidth = 20; azWiki.setLayout(layout); azWiki.setText(MessageText.getString("Utils.link.visit")); final Label linkLabel = new Label(azWiki, SWT.NULL); linkLabel.setText( Constants.APP_NAME + " Wiki AutoSpeed (beta)" ); linkLabel.setData("http://www.azureuswiki.com/index.php/Auto_Speed"); linkLabel.setCursor(Cursors.handCursor); linkLabel.setForeground(Colors.blue); gridData = new GridData(); linkLabel.setLayoutData( gridData ); linkLabel.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } public void mouseUp(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getData()); } }); return cSection; }//configSectionCreate class ConvertToLongChangeListener implements ParameterChangeListener{ public void parameterChanged(Parameter p, boolean caused_internally) { try{ //StringList doesn't work with Long parameters, so need to convert here. String str = COConfigurationManager.getStringParameter(SpeedManagerImpl.CONFIG_VERSION_STR); long asLong = Long.parseLong( str ); COConfigurationManager.setParameter(SpeedManagerImpl.CONFIG_VERSION, asLong ); }catch(Throwable t){ //ToDo: log an error. COConfigurationManager.setParameter(SpeedManagerImpl.CONFIG_VERSION, 1); } } /** * An int parameter is about to change. *

    * Not called when parameter set via COConfigurationManager.setParameter * * @param p - * @param toValue - */ public void intParameterChanging(Parameter p, int toValue) { } /** * A boolean parameter is about to change. *

    * Not called when parameter set via COConfigurationManager.setParameter * * @param p - * @param toValue - */ public void booleanParameterChanging(Parameter p, boolean toValue) { } /** * A String parameter is about to change. *

    * Not called when parameter set via COConfigurationManager.setParameter * * @param p - * @param toValue - */ public void stringParameterChanging(Parameter p, String toValue) { } /** * A double/float parameter is about to change. *

    * Not called when parameter set via COConfigurationManager.setParameter * * @param owner - * @param toValue - */ public void floatParameterChanging(Parameter owner, double toValue) { } } protected String getMBitLimit( TransferStatsView.limitToTextHelper helper, long value ) { return("("+(value==0?helper.getUnlimited():DisplayFormatters.formatByteCountToBitsPerSec( value ))+")" ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerServer.java0000644000175000017500000006234511256315674031705 0ustar adrianadrian/* * File : ConfigPanel*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AENetworkClassifier; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.auth.CertificateCreatorWindow; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.ipchecker.IpCheckerWizard; import org.gudy.azureus2.ui.swt.ipchecker.IpSetterCallBack; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.Cursors; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; public class ConfigSectionTrackerServer implements UISWTConfigSection { private static final String CFG_PREFIX = "ConfigView.section."; private final int REQUIRED_MODE = 1; public int maxUserMode() { return 2; } public ConfigSectionTrackerServer() { } public String configSectionGetParentSection() { return ConfigSection.SECTION_TRACKER; } public String configSectionGetName() { return "tracker.server"; } public void configSectionSave() { } public void configSectionDelete() { } public Composite configSectionCreate(final Composite parent) { GridData gridData; GridLayout layout; Label label; // main tab set up Composite gMainTab = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gMainTab.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 4; gMainTab.setLayout(layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); if (userMode < REQUIRED_MODE) { label = new Label(gMainTab, SWT.WRAP); gridData = new GridData(); label.setLayoutData(gridData); final String[] modeKeys = { CFG_PREFIX + "mode.beginner", CFG_PREFIX + "mode.intermediate", CFG_PREFIX + "mode.advanced" }; String param1, param2; if (REQUIRED_MODE < modeKeys.length) param1 = MessageText.getString(modeKeys[REQUIRED_MODE]); else param1 = String.valueOf(REQUIRED_MODE); if (userMode < modeKeys.length) param2 = MessageText.getString(modeKeys[userMode]); else param2 = String.valueOf(userMode); label.setText(MessageText.getString("ConfigView.notAvailableForMode", new String[] { param1, param2 } )); return gMainTab; } // MAIN TAB DATA // row if(userMode>0) { // XXX label = new Label(gMainTab, SWT.NULL); Messages.setLanguageText(label, CFG_PREFIX + "tracker.ip"); final StringParameter tracker_ip = new StringParameter(gMainTab, "Tracker IP", "" ); gridData = new GridData(); gridData.widthHint = 120; tracker_ip.setLayoutData( gridData ); Button check_button = new Button(gMainTab, SWT.PUSH); gridData = new GridData(); gridData.horizontalSpan = 2; check_button.setLayoutData(gridData); Messages.setLanguageText(check_button, CFG_PREFIX + "tracker.checkip"); //$NON-NLS-1$ final Display display = gMainTab.getDisplay(); check_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { IpCheckerWizard wizard = new IpCheckerWizard(); wizard.setIpSetterCallBack(new IpSetterCallBack() { public void setIp(final String ip) { if(display == null || display.isDisposed()) return; display.asyncExec(new AERunnable(){ public void runSupport() { if(tracker_ip != null) tracker_ip.setValue(ip); } }); } }); // setIPSetterCallback } }); // row final BooleanParameter nonsslEnable = new BooleanParameter(gMainTab, "Tracker Port Enable", CFG_PREFIX + "tracker.port"); IntParameter tracker_port = new IntParameter(gMainTab, "Tracker Port", 0, 65535); gridData = new GridData(); tracker_port.setLayoutData( gridData ); final StringParameter tracker_port_backup = new StringParameter(gMainTab, "Tracker Port Backups", "" ); gridData = new GridData(); gridData.widthHint = 100; tracker_port_backup.setLayoutData( gridData ); Label tracker_port_backup_label = new Label(gMainTab, SWT.NULL ); Messages.setLanguageText(tracker_port_backup_label, CFG_PREFIX + "tracker.portbackup"); Control[] non_ssl_controls = new Control[3]; non_ssl_controls[0] = tracker_port.getControl(); non_ssl_controls[1] = tracker_port_backup.getControl(); non_ssl_controls[2] = tracker_port_backup_label; nonsslEnable.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( non_ssl_controls )); // row final BooleanParameter sslEnable = new BooleanParameter(gMainTab, "Tracker Port SSL Enable", CFG_PREFIX + "tracker.sslport"); IntParameter tracker_port_ssl = new IntParameter(gMainTab, "Tracker Port SSL", 0, 65535); gridData = new GridData(); tracker_port_ssl.setLayoutData( gridData ); final StringParameter tracker_port_ssl_backup = new StringParameter(gMainTab, "Tracker Port SSL Backups", "" ); gridData = new GridData(); gridData.widthHint = 100; tracker_port_ssl_backup.setLayoutData( gridData ); Label tracker_port_ssl_backup_label = new Label(gMainTab, SWT.NULL ); Messages.setLanguageText(tracker_port_ssl_backup_label, CFG_PREFIX + "tracker.portbackup"); // create cert row Label cert_label = new Label(gMainTab, SWT.NULL ); Messages.setLanguageText(cert_label, CFG_PREFIX + "tracker.createcert"); Button cert_button = new Button(gMainTab, SWT.PUSH); Messages.setLanguageText(cert_button, CFG_PREFIX + "tracker.createbutton"); cert_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { new CertificateCreatorWindow(); } }); Label ssl_faq_label = new Label(gMainTab, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 2; ssl_faq_label.setLayoutData(gridData); Messages.setLanguageText(ssl_faq_label, CFG_PREFIX + "tracker.sslport.info"); final String linkFAQ = "http://azureus.sourceforge.net/faq.php#19"; ssl_faq_label.setCursor(Cursors.handCursor); ssl_faq_label.setForeground(Colors.blue); ssl_faq_label.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { Utils.launch(linkFAQ); } public void mouseDown(MouseEvent arg0) { Utils.launch(linkFAQ); } }); Control[] ssl_controls = { tracker_port_ssl.getControl(), tracker_port_ssl_backup.getControl(), tracker_port_ssl_backup_label, ssl_faq_label, cert_label, cert_button }; sslEnable.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( ssl_controls )); // row gridData = new GridData(); gridData.horizontalSpan = 1; new BooleanParameter(gMainTab, "Tracker Public Enable", CFG_PREFIX + "tracker.publicenable").setLayoutData( gridData ); label = new Label(gMainTab, SWT.NULL); Messages.setLanguageText(label, CFG_PREFIX + "tracker.publicenable.info"); gridData = new GridData(); gridData.horizontalSpan = 3; label.setLayoutData(gridData); // row BooleanParameter forcePortDetails = new BooleanParameter(gMainTab, "Tracker Port Force External", CFG_PREFIX + "tracker.forceport"); label = new Label(gMainTab, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 3; label.setLayoutData(gridData); Control[] f_controls = new Control[1]; f_controls[0] = forcePortDetails.getControl(); IAdditionalActionPerformer f_enabler = new GenericActionPerformer(f_controls) { public void performAction() { boolean selected = nonsslEnable.isSelected() || sslEnable.isSelected(); controls[0].setEnabled( selected ); } }; nonsslEnable.setAdditionalActionPerformer(f_enabler); sslEnable.setAdditionalActionPerformer(f_enabler); // row // add announce urls to hosted torrents BooleanParameter hostAddURLs = new BooleanParameter(gMainTab, "Tracker Host Add Our Announce URLs", CFG_PREFIX + "tracker.host.addurls"); gridData = new GridData(); gridData.horizontalSpan = 2; hostAddURLs.setLayoutData( gridData ); label = new Label(gMainTab, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 2; label.setLayoutData(gridData); // row gridData = new GridData(); gridData.horizontalSpan = 1; final BooleanParameter passwordEnableWeb = new BooleanParameter(gMainTab, "Tracker Password Enable Web", CFG_PREFIX + "tracker.passwordenableweb"); passwordEnableWeb.setLayoutData( gridData ); gridData = new GridData(); gridData.horizontalSpan = 3; final BooleanParameter passwordWebHTTPSOnly = new BooleanParameter(gMainTab, "Tracker Password Web HTTPS Only", CFG_PREFIX + "tracker.passwordwebhttpsonly"); passwordWebHTTPSOnly.setLayoutData( gridData ); IAdditionalActionPerformer web_https_enabler = new GenericActionPerformer(passwordWebHTTPSOnly.getControls()) { public void performAction() { boolean selected = passwordEnableWeb.isSelected() && sslEnable.isSelected(); for (int i=0;i1) { // XXX // row gridData = new GridData(); gridData.horizontalSpan = 4; new BooleanParameter(gMainTab, "Tracker Key Enable Server", CFG_PREFIX + "tracker.enablekey").setLayoutData(gridData); // Networks Group // Group networks_group = new Group( gMainTab, SWT.NULL ); Messages.setLanguageText( networks_group, CFG_PREFIX + "tracker.server.group.networks" ); GridData networks_layout = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); networks_layout.horizontalSpan = 4; networks_group.setLayoutData( networks_layout ); layout = new GridLayout(); layout.numColumns = 2; networks_group.setLayout(layout); label = new Label(networks_group, SWT.NULL); Messages.setLanguageText(label, CFG_PREFIX + "tracker.server.group.networks.info"); GridData grid_data = new GridData(); grid_data.horizontalSpan = 2; label.setLayoutData( grid_data ); for (int i=0;i= 0) ((List)locale_param.getControl()).select(iUsingLocale); locale_param.addChangeListener( new ParameterChangeAdapter() { public void parameterChanged( Parameter p, boolean caused_internally ) { MessageText.loadBundle(); DisplayFormatters.setUnits(); DisplayFormatters.loadMessages(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshLanguage(); } } }); return cMain; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileMove.java0000644000175000017500000001471211127403350030606 0ustar adrianadrian/* * File : ConfigPanelFile.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.ui.config.ConfigSection; public class ConfigSectionFileMove implements UISWTConfigSection { private Image imgOpenFolder; public String configSectionGetParentSection() { return ConfigSection.SECTION_FILES; } public String configSectionGetName() { return ConfigSection.SECTION_FILES + ".move"; } public void configSectionSave() { } public void configSectionDelete() { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage("openFolderButton"); } public int maxUserMode() { return 1; } public Composite configSectionCreate(final Composite parent) { GridData gridData; int userMode = COConfigurationManager.getIntParameter("User Mode"); Composite gFile = new Composite(parent, SWT.NULL); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; gFile.setLayout(layout); ImageLoader imageLoader = ImageLoader.getInstance(); imgOpenFolder = imageLoader.getImage("openFolderButton"); // Move on complete / deletion. createMoveOnEventGrouping(gFile, "ConfigView.label.movecompleted", "Move Completed When Done", "Completed Files Directory", "Move Torrent When Done", "Move Only When In Default Save Dir", null); createMoveOnEventGrouping(gFile, "ConfigView.label.moveremoved", "File.move.download.removed.enabled", "File.move.download.removed.path", "File.move.download.removed.move_torrent", "File.move.download.removed.only_in_default", "File.move.download.removed.move_partial"); if (userMode > 0) { // copy rather than move BooleanParameter copyDontMove = new BooleanParameter(gFile, "Copy And Delete Data Rather Than Move", "ConfigView.label.copyanddeleteratherthanmove"); gridData = new GridData(); gridData.horizontalSpan = 2; copyDontMove.setLayoutData(gridData); } BooleanParameter subdirIsDefault = new BooleanParameter(gFile, "File.move.subdir_is_default", "ConfigView.label.subdir_is_in_default"); gridData = new GridData(); gridData.horizontalSpan = 2; subdirIsDefault.setLayoutData(gridData); return gFile; } private void createMoveOnEventGrouping(final Composite gFile, String enable_section_label, String move_when_done_setting, String move_path_setting, String move_torrent_setting, String move_when_in_save_dir_setting, String move_partial_downloads_setting) { BooleanParameter moveCompleted = new BooleanParameter(gFile, move_when_done_setting, enable_section_label); GridData gridData = new GridData(); GridLayout layout = null; gridData.horizontalSpan = 2; moveCompleted.setLayoutData(gridData); Composite gMoveCompleted = new Composite(gFile, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalIndent = 25; gridData.horizontalSpan = 2; gMoveCompleted.setLayoutData(gridData); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 4; layout.numColumns = 3; gMoveCompleted.setLayout(layout); Label lDir = new Label(gMoveCompleted, SWT.NULL); Messages.setLanguageText(lDir, "ConfigView.label.directory"); gridData = new GridData(GridData.FILL_HORIZONTAL); final StringParameter movePath = new StringParameter(gMoveCompleted, move_path_setting); movePath.setLayoutData(gridData); Button browse3 = new Button(gMoveCompleted, SWT.PUSH); browse3.setImage(imgOpenFolder); imgOpenFolder.setBackground(browse3.getBackground()); browse3.setToolTipText(MessageText.getString("ConfigView.button.browse")); browse3.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { DirectoryDialog dialog = new DirectoryDialog(gFile.getShell(), SWT.APPLICATION_MODAL); dialog.setFilterPath(movePath.getValue()); dialog.setText(MessageText.getString("ConfigView.dialog.choosemovepath")); String path = dialog.open(); if (path != null) { movePath.setValue(path); } } }); // move when done BooleanParameter moveTorrent = new BooleanParameter(gMoveCompleted, move_torrent_setting, "ConfigView.label.movetorrent"); gridData = new GridData(); gridData.horizontalSpan = 2; moveTorrent.setLayoutData(gridData); // only in default BooleanParameter moveOnly = new BooleanParameter(gMoveCompleted, move_when_in_save_dir_setting, "ConfigView.label.moveonlyusingdefaultsave"); gridData = new GridData(); gridData.horizontalSpan = 2; moveOnly.setLayoutData(gridData); // move if partially finished. if (move_partial_downloads_setting != null) { BooleanParameter movePartial = new BooleanParameter(gMoveCompleted, move_partial_downloads_setting, "ConfigView.label.movepartialdownloads"); gridData = new GridData(); gridData.horizontalSpan = 2; movePartial.setLayoutData(gridData); } Control[] controls3 = new Control[] { gMoveCompleted }; IAdditionalActionPerformer grayPathAndButton2 = new ChangeSelectionActionPerformer( controls3); moveCompleted.setAdditionalActionPerformer(grayPathAndButton2); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfacePassword.java0000644000175000017500000001164411157634462032541 0ustar adrianadrian/* * File : ConfigSectionInterfaceAlerts.java * Created : Dec 4, 2006 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.config.PasswordParameter; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.plugins.ui.config.ConfigSection; public class ConfigSectionInterfacePassword implements UISWTConfigSection { private final static String LBLKEY_PREFIX = "ConfigView.label."; private final int REQUIRED_MODE = 0; Label passwordMatch; public String configSectionGetParentSection() { return ConfigSection.SECTION_INTERFACE; } /* Name of section will be pulled from * ConfigView.section.configSectionGetName() */ public String configSectionGetName() { return "interface.password"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return REQUIRED_MODE; } public Composite configSectionCreate(final Composite parent) { GridData gridData; GridLayout layout; Label label; Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); layout = new GridLayout(); layout.marginWidth = 0; layout.numColumns = 2; cSection.setLayout(layout); // password label = new Label(cSection, SWT.NULL); Messages.setLanguageText(label, LBLKEY_PREFIX + "password"); gridData = new GridData(); gridData.widthHint = 150; PasswordParameter pw1 = new PasswordParameter(cSection, "Password"); pw1.setLayoutData(gridData); Text t1 = (Text) pw1.getControl(); //password confirm label = new Label(cSection, SWT.NULL); Messages.setLanguageText(label, LBLKEY_PREFIX + "passwordconfirm"); gridData = new GridData(); gridData.widthHint = 150; PasswordParameter pw2 = new PasswordParameter(cSection, "Password Confirm"); pw2.setLayoutData(gridData); Text t2 = (Text) pw2.getControl(); // password activated label = new Label(cSection, SWT.NULL); Messages.setLanguageText(label, LBLKEY_PREFIX + "passwordmatch"); passwordMatch = new Label(cSection, SWT.NULL); gridData = new GridData(); gridData.widthHint = 150; passwordMatch.setLayoutData(gridData); refreshPWLabel(); t1.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { refreshPWLabel(); } }); t2.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { refreshPWLabel(); } }); return cSection; } private void refreshPWLabel() { if (passwordMatch == null || passwordMatch.isDisposed()) return; byte[] password = COConfigurationManager.getByteParameter("Password", "" .getBytes()); COConfigurationManager.setParameter("Password enabled", false); if (password.length == 0) { passwordMatch.setText(MessageText.getString(LBLKEY_PREFIX + "passwordmatchnone")); } else { byte[] confirm = COConfigurationManager.getByteParameter( "Password Confirm", "".getBytes()); if (confirm.length == 0) { passwordMatch.setText(MessageText.getString(LBLKEY_PREFIX + "passwordmatchno")); } else { boolean same = true; for (int i = 0; i < password.length; i++) { if (password[i] != confirm[i]) same = false; } if (same) { passwordMatch.setText(MessageText.getString(LBLKEY_PREFIX + "passwordmatchyes")); COConfigurationManager.setParameter("Password enabled", true); } else { passwordMatch.setText(MessageText.getString(LBLKEY_PREFIX + "passwordmatchno")); } } } } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeedBeta.javaazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeedBeta.jav0000644000175000017500000003760511134026632033141 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.views.configsections; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEDiagnosticsLogger; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator; import org.gudy.azureus2.core3.config.impl.ConfigurationDefaults; import org.gudy.azureus2.core3.config.impl.ConfigurationParameterNotFoundException; import org.eclipse.swt.widgets.*; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.SWT; import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerImpl; import com.aelitis.azureus.core.speedmanager.impl.v2.SpeedLimitMonitor; import com.aelitis.azureus.core.speedmanager.impl.v2.SpeedManagerAlgorithmProviderV2; /** * Created on May 15, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class ConfigSectionTransferAutoSpeedBeta implements UISWTConfigSection { //upload/download limits IntParameter downMaxLim; IntParameter uploadMaxLim; StringListParameter confDownload; StringListParameter confUpload; //add a comment to the auto-speed debug logs. Group commentGroup; Group uploadCapGroup; //DHT ping set-points Group dhtGroup; IntParameter dGood; IntParameter dGoodTol; IntParameter dBad; IntParameter dBadTol; //general ping set-points. IntParameter adjustmentInterval; BooleanParameter skipAfterAdjustment; Button reset; IntListParameter downloadModeUsedCap; IntListParameter seedModeUsedCap; /** * Create your own configuration panel here. It can be anything that inherits * from SWT's Composite class. * Please be mindfull of small screen resolutions * * @param parent The parent of your configuration panel * @return your configuration panel */ /** * Returns section you want your configuration panel to be under. * See SECTION_* constants. To add a subsection to your own ConfigSection, * return the configSectionGetName result of your parent.
    */ public String configSectionGetParentSection() { return "transfer.select"; } /** * In order for the plugin to display its section correctly, a key in the * Plugin language file will need to contain * ConfigView.section.<configSectionGetName() result>=The Section name.
    * * @return The name of the configuration section */ public String configSectionGetName() { return "transfer.select.v2"; } /** * User selected Save. * All saving of non-plugin tabs have been completed, as well as * saving of plugins that implement org.gudy.azureus2.plugins.ui.config * parameters. */ public void configSectionSave() { } /** * Config view is closing */ public void configSectionDelete() { } public int maxUserMode() { return 0; } public Composite configSectionCreate(final Composite parent) { GridData gridData; Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL|GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); GridLayout subPanel = new GridLayout(); subPanel.numColumns = 3; cSection.setLayout(subPanel); //add a comment to the debug log. /////////////////////////////////// // Comment group /////////////////////////////////// //comment grouping. commentGroup = new Group(cSection, SWT.NULL); Messages.setLanguageText(commentGroup,"ConfigTransferAutoSpeed.add.comment.to.log.group"); GridLayout commentLayout = new GridLayout(); commentLayout.numColumns = 3; commentGroup.setLayout(commentLayout); gridData = new GridData(GridData.FILL_HORIZONTAL); commentGroup.setLayoutData(gridData); //Label Label commentLabel = new Label(commentGroup,SWT.NULL); Messages.setLanguageText(commentLabel,"ConfigTransferAutoSpeed.add.comment.to.log"); gridData = new GridData(); gridData.horizontalSpan=1; commentLabel.setLayoutData(gridData); //Text-Box final Text commentBox = new Text(commentGroup, SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan=1; commentBox.setText(""); commentBox.setLayoutData(gridData); //button Button commentButton = new Button( commentGroup, SWT.PUSH); //Messages. gridData = new GridData(); gridData.horizontalSpan=1; commentButton.setLayoutData(gridData); Messages.setLanguageText(commentButton,"ConfigTransferAutoSpeed.log.button"); commentButton.addListener(SWT.Selection, new Listener(){ public void handleEvent(Event event){ //Add a file to the log. AEDiagnosticsLogger dLog = AEDiagnostics.getLogger("AutoSpeed"); String comment = commentBox.getText(); if(comment!=null){ if( comment.length()>0){ dLog.log( "user-comment:"+comment ); commentBox.setText(""); } } } }); //spacer Label commentSpacer = new Label(cSection, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan=3; commentSpacer.setLayoutData(gridData); /////////////////////////// // Upload Capacity used settings. /////////////////////////// uploadCapGroup = new Group(cSection, SWT.NULL); Messages.setLanguageText(uploadCapGroup,"ConfigTransferAutoSpeed.upload.capacity.usage"); GridLayout uCapLayout = new GridLayout(); uCapLayout.numColumns = 2; uploadCapGroup.setLayout(uCapLayout); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; uploadCapGroup.setLayoutData(gridData); //Label column Label upCapModeLbl = new Label(uploadCapGroup, SWT.NULL); gridData = new GridData(); upCapModeLbl.setLayoutData(gridData); Messages.setLanguageText(upCapModeLbl,"ConfigTransferAutoSpeed.mode"); Label ucSetLbl = new Label(uploadCapGroup, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan = 2; Messages.setLanguageText(ucSetLbl,"ConfigTransferAutoSpeed.capacity.used"); Label dlModeLbl = new Label(uploadCapGroup, SWT.NULL); gridData = new GridData(); Messages.setLanguageText(dlModeLbl,"ConfigTransferAutoSpeed.while.downloading"); //add a drop down. String[] downloadModeNames = { " 80%", " 70%", " 60%", " 50%" }; int[] downloadModeValues = { 80, 70, 60, 50 }; downloadModeUsedCap = new IntListParameter(uploadCapGroup, SpeedLimitMonitor.USED_UPLOAD_CAPACITY_DOWNLOAD_MODE, downloadModeNames, downloadModeValues); //spacer Label cSpacer = new Label(cSection, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan=4; cSpacer.setLayoutData(gridData); ////////////////////////// // DHT Ping Group ////////////////////////// dhtGroup = new Group(cSection, SWT.NULL); Messages.setLanguageText(dhtGroup,"ConfigTransferAutoSpeed.data.update.frequency"); dhtGroup.setLayout(subPanel); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; dhtGroup.setLayoutData(gridData); // //label column for Vivaldi limits // Label dhtSetting = new Label(dhtGroup, SWT.NULL); // gridData = new GridData(); // //dhtSetting.setText("DHT Ping Settings: "); // Messages.setLanguageText(dhtSetting,"ConfigTransferAutoSpeed.set.dht.ping"); // // Label dSet = new Label(dhtGroup,SWT.NULL); // gridData = new GridData(); // dSet.setLayoutData(gridData); // //dSet.setText("set point (ms)"); // Messages.setLanguageText(dSet,"ConfigTransferAutoSpeed.set.point"); // // Label dTol = new Label(dhtGroup, SWT.NULL); // gridData = new GridData(); // dTol.setLayoutData(gridData); // //dTol.setText("tolerance (ms)"); // Messages.setLanguageText(dTol,"ConfigTransferAutoSpeed.set.tolerance"); // // //good // Label dGoodLbl = new Label(dhtGroup, SWT.NULL); // gridData = new GridData(); // dGoodLbl.setLayoutData(gridData); // //dGoodLbl.setText("Good: "); // Messages.setLanguageText(dGoodLbl,"ConfigTransferAutoSpeed.ping.time.good"); // // // gridData = new GridData(); // dGood = new IntParameter(dhtGroup, SpeedManagerAlgorithmProviderV2.SETTING_DHT_GOOD_SET_POINT); // dGood.setLayoutData( gridData ); // // gridData = new GridData(); // dGoodTol = new IntParameter(dhtGroup, SpeedManagerAlgorithmProviderV2.SETTING_DHT_GOOD_TOLERANCE); // dGoodTol.setLayoutData( gridData ); // // //bad // Label dBadLbl = new Label(dhtGroup, SWT.NULL); // gridData = new GridData(); // dBadLbl.setLayoutData(gridData); // //dBadLbl.setText("Bad: "); // Messages.setLanguageText(dBadLbl,"ConfigTransferAutoSpeed.ping.time.bad"); // // // gridData = new GridData(); // dBad = new IntParameter(dhtGroup, SpeedManagerAlgorithmProviderV2.SETTING_DHT_BAD_SET_POINT); // dBad.setLayoutData( gridData ); // // // gridData = new GridData(); // dBadTol = new IntParameter(dhtGroup, SpeedManagerAlgorithmProviderV2.SETTING_DHT_BAD_TOLERANCE); // dBadTol.setLayoutData( gridData ); // // //spacer // cSpacer = new Label(cSection, SWT.NULL); // gridData = new GridData(); // gridData.horizontalSpan=1; // cSpacer.setLayoutData(gridData); //how much data to accumulate before making an adjustment. Label iCount = new Label(dhtGroup, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan=2; gridData.horizontalAlignment=GridData.BEGINNING; iCount.setLayoutData(gridData); //iCount.setText("Adjustment interval: "); Messages.setLanguageText(iCount,"ConfigTransferAutoSpeed.adjustment.interval"); adjustmentInterval = new IntParameter(dhtGroup, SpeedManagerAlgorithmProviderV2.SETTING_INTERVALS_BETWEEN_ADJUST); gridData = new GridData(); adjustmentInterval.setLayoutData(gridData); //spacer cSpacer = new Label(cSection, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan=1; cSpacer.setLayoutData(gridData); //how much data to accumulate before making an adjustment. Label skip = new Label(dhtGroup, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan=2; gridData.horizontalAlignment=GridData.BEGINNING; skip.setLayoutData(gridData); //skip.setText("Skip after adjustment: "); Messages.setLanguageText(skip,"ConfigTransferAutoSpeed.skip.after.adjust"); skipAfterAdjustment = new BooleanParameter(dhtGroup, SpeedManagerAlgorithmProviderV2.SETTING_WAIT_AFTER_ADJUST); gridData = new GridData(); skipAfterAdjustment.setLayoutData(gridData); //spacer cSpacer = new Label(cSection, SWT.NULL); gridData = new GridData(); gridData.horizontalSpan=3; cSpacer.setLayoutData(gridData); return cSection; } void enableGroups(String strategyListValue){ if(strategyListValue==null){ return; } //only enable the comment section if the beta is enabled. boolean isBothEnabled = COConfigurationManager.getBooleanParameter( TransferSpeedValidator.AUTO_UPLOAD_ENABLED_CONFIGKEY ); boolean isSeedingEnabled = COConfigurationManager.getBooleanParameter( TransferSpeedValidator.AUTO_UPLOAD_SEEDING_ENABLED_CONFIGKEY ); long version = COConfigurationManager.getLongParameter( SpeedManagerImpl.CONFIG_VERSION ); boolean isV2Enabled = false; if( (isBothEnabled || isSeedingEnabled) && version==2 ){ isV2Enabled = true; } if( commentGroup!=null){ if( isV2Enabled ){ //make this section visible. commentGroup.setEnabled(true); commentGroup.setVisible(true); }else{ //make it invisible. commentGroup.setEnabled(false); commentGroup.setVisible(false); } } }//enableGroups /** * Listen for changes in the drop down, then enable/disable the appropriate * group mode. */ class GroupModeChangeListener implements ParameterChangeListener { /** * Enable/Disable approriate group. * @param p - * @param caused_internally - */ public void parameterChanged(Parameter p, boolean caused_internally) { } public void intParameterChanging(Parameter p, int toValue) { //nothing to do here. } public void booleanParameterChanging(Parameter p, boolean toValue) { //nothing to do here. } public void stringParameterChanging(Parameter p, String toValue) { //nothing to do here. } public void floatParameterChanging(Parameter owner, double toValue) { //nothing to do here. } }//class GroupModeChangeListener class RestoreDefaultsListener implements Listener { public void handleEvent(Event event) { ConfigurationDefaults configDefs = ConfigurationDefaults.getInstance(); try{ long downMax = configDefs.getLongParameter( SpeedManagerAlgorithmProviderV2.SETTING_DOWNLOAD_MAX_LIMIT); String downConf = configDefs.getStringParameter( SpeedLimitMonitor.DOWNLOAD_CONF_LIMIT_SETTING ); long upMax = configDefs.getLongParameter( SpeedManagerAlgorithmProviderV2.SETTING_UPLOAD_MAX_LIMIT ); String upConf = configDefs.getStringParameter( SpeedLimitMonitor.UPLOAD_CONF_LIMIT_SETTING ); COConfigurationManager.setParameter(SpeedManagerAlgorithmProviderV2.SETTING_DOWNLOAD_MAX_LIMIT,downMax); COConfigurationManager.setParameter(SpeedLimitMonitor.DOWNLOAD_CONF_LIMIT_SETTING,downConf); COConfigurationManager.setParameter(SpeedManagerAlgorithmProviderV2.SETTING_UPLOAD_MAX_LIMIT,upMax); COConfigurationManager.setParameter(SpeedLimitMonitor.UPLOAD_CONF_LIMIT_SETTING,upConf); }catch(ConfigurationParameterNotFoundException cpnfe){ //ToDo: log this. } }//handleEvent }//class } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransfer.java0000644000175000017500000004073511256315674030706 0ustar adrianadrian/* * File : ConfigPanel*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.components.LinkLabel; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.ImageRepository; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator; import org.gudy.azureus2.core3.internat.MessageText; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; public class ConfigSectionTransfer implements UISWTConfigSection { public ConfigSectionTransfer() { } public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } public String configSectionGetName() { return ConfigSection.SECTION_TRANSFER; } public void configSectionSave() { } public void configSectionDelete() { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage("subitem"); } public int maxUserMode() { return 2; } public Composite configSectionCreate(final Composite parent) { GridData gridData; GridLayout layout; Label label; Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; cSection.setLayout(layout); int userMode = COConfigurationManager.getIntParameter("User Mode"); // store the initial d/l speed so we can do something sensible later final int[] manual_max_download_speed = { COConfigurationManager .getIntParameter("Max Download Speed KBs") }; // max upload speed gridData = new GridData(); label = new Label(cSection, SWT.NULL); label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.label.maxuploadspeed"); gridData = new GridData(); final IntParameter paramMaxUploadSpeed = new IntParameter(cSection, "Max Upload Speed KBs", 0, -1); paramMaxUploadSpeed.setLayoutData(gridData); // max upload speed when seeding final Composite cMaxUploadSpeedOptionsArea = new Composite(cSection, SWT.NULL); layout = new GridLayout(); layout.numColumns = 3; layout.marginWidth = 0; layout.marginHeight = 0; cMaxUploadSpeedOptionsArea.setLayout(layout); gridData = new GridData(); gridData.horizontalIndent = 15; gridData.horizontalSpan = 2; cMaxUploadSpeedOptionsArea.setLayoutData(gridData); ImageLoader imageLoader = ImageLoader.getInstance(); Image img = imageLoader.getImage("subitem"); label = new Label(cMaxUploadSpeedOptionsArea, SWT.NULL); img.setBackground(label.getBackground()); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); label.setImage(img); gridData = new GridData(); final BooleanParameter enable_seeding_rate = new BooleanParameter( cMaxUploadSpeedOptionsArea, "enable.seedingonly.upload.rate", "ConfigView.label.maxuploadspeedseeding"); enable_seeding_rate.setLayoutData(gridData); gridData = new GridData(); final IntParameter paramMaxUploadSpeedSeeding = new IntParameter( cMaxUploadSpeedOptionsArea, "Max Upload Speed Seeding KBs", 0, -1); paramMaxUploadSpeedSeeding.setLayoutData(gridData); enable_seeding_rate .setAdditionalActionPerformer(new ChangeSelectionActionPerformer( paramMaxUploadSpeedSeeding.getControl())); if (userMode < 2) { // wiki link Composite cWiki = new Composite(cSection, SWT.COLOR_GRAY); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan = 2; cWiki.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 4; layout.marginHeight = 0; cWiki.setLayout(layout); gridData = new GridData(); gridData.horizontalIndent = 6; gridData.horizontalSpan = 2; label = new Label(cWiki, SWT.NULL); label.setLayoutData(gridData); label.setText(MessageText.getString("Utils.link.visit") + ":"); gridData = new GridData(); gridData.horizontalIndent = 10; gridData.horizontalSpan = 2; new LinkLabel(cWiki, gridData, "ConfigView.section.transfer.speeds.wiki", "http://www.azureuswiki.com/index.php/Good_settings"); } if ( userMode > 1 ){ gridData = new GridData(); label = new Label(cSection, SWT.NULL); label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.label.maxuploadswhenbusymin" ); gridData = new GridData(); new IntParameter(cSection, "max.uploads.when.busy.inc.min.secs", 0, -1).setLayoutData(gridData); } // max download speed gridData = new GridData(); label = new Label(cSection, SWT.NULL); label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.label.maxdownloadspeed"); gridData = new GridData(); final IntParameter paramMaxDownSpeed = new IntParameter(cSection, "Max Download Speed KBs", 0, -1); paramMaxDownSpeed.setLayoutData(gridData); // max upload/download limit dependencies Listener l = new Listener() { public void handleEvent(Event event) { boolean disableAuto = false; boolean disableAutoSeeding = false; if(enable_seeding_rate.isSelected()) { disableAutoSeeding = event.widget == paramMaxUploadSpeedSeeding.getControl(); disableAuto = event.widget == paramMaxDownSpeed.getControl() || event.widget == paramMaxUploadSpeed.getControl(); } else { disableAuto = true; disableAutoSeeding = true; } if(disableAuto) COConfigurationManager.setParameter(TransferSpeedValidator.AUTO_UPLOAD_ENABLED_CONFIGKEY, false); if(disableAutoSeeding) COConfigurationManager.setParameter(TransferSpeedValidator.AUTO_UPLOAD_SEEDING_ENABLED_CONFIGKEY, false); } }; paramMaxDownSpeed.getControl().addListener(SWT.Selection, l); paramMaxUploadSpeed.getControl().addListener(SWT.Selection, l); paramMaxUploadSpeedSeeding.getControl().addListener(SWT.Selection, l); paramMaxUploadSpeed.addChangeListener(new ParameterChangeAdapter() { ParameterChangeAdapter me = this; public void parameterChanged(Parameter p, boolean internal) { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { if (paramMaxUploadSpeed.isDisposed()) { paramMaxUploadSpeed.removeChangeListener(me); return; } // we don't want to police these limits when auto-speed is running as // they screw things up bigtime if (TransferSpeedValidator.isAutoSpeedActive(core.getGlobalManager())) { return; } int up_val = paramMaxUploadSpeed.getValue(); int down_val = paramMaxDownSpeed.getValue(); if (up_val != 0 && up_val < COConfigurationManager.CONFIG_DEFAULT_MIN_MAX_UPLOAD_SPEED) { if ((down_val == 0) || down_val > (up_val * 2)) { paramMaxDownSpeed.setValue(up_val * 2); } } else { if (down_val != manual_max_download_speed[0]) { paramMaxDownSpeed.setValue(manual_max_download_speed[0]); } } } }); }; }); paramMaxDownSpeed.addChangeListener(new ParameterChangeAdapter() { ParameterChangeAdapter me = this; public void parameterChanged(Parameter p, boolean internal) { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { if (paramMaxDownSpeed.isDisposed()) { paramMaxDownSpeed.removeChangeListener(me); return; } // we don't want to police these limits when auto-speed is running as // they screw things up bigtime if (TransferSpeedValidator.isAutoSpeedActive(core.getGlobalManager())) { return; } int up_val = paramMaxUploadSpeed.getValue(); int down_val = paramMaxDownSpeed.getValue(); manual_max_download_speed[0] = down_val; if (up_val < COConfigurationManager.CONFIG_DEFAULT_MIN_MAX_UPLOAD_SPEED) { if (up_val != 0 && up_val < (down_val * 2)) { paramMaxUploadSpeed.setValue((down_val + 1) / 2); } else if (down_val == 0) { paramMaxUploadSpeed.setValue(0); } } } }); } }); if (userMode > 0) { // max uploads gridData = new GridData(); label = new Label(cSection, SWT.NULL); label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.label.maxuploads"); gridData = new GridData(); IntParameter paramMaxUploads = new IntParameter(cSection, "Max Uploads", 2, -1); paramMaxUploads.setLayoutData(gridData); // max uploads when seeding final Composite cMaxUploadsOptionsArea = new Composite(cSection, SWT.NULL); layout = new GridLayout(); layout.numColumns = 3; layout.marginWidth = 0; layout.marginHeight = 0; cMaxUploadsOptionsArea.setLayout(layout); gridData = new GridData(); gridData.horizontalIndent = 15; gridData.horizontalSpan = 2; cMaxUploadsOptionsArea.setLayoutData(gridData); label = new Label(cMaxUploadsOptionsArea, SWT.NULL); img.setBackground(label.getBackground()); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); label.setImage(img); gridData = new GridData(); BooleanParameter enable_seeding_uploads = new BooleanParameter( cMaxUploadsOptionsArea, "enable.seedingonly.maxuploads", "ConfigView.label.maxuploadsseeding"); enable_seeding_uploads.setLayoutData(gridData); gridData = new GridData(); IntParameter paramMaxUploadsSeeding = new IntParameter( cMaxUploadsOptionsArea, "Max Uploads Seeding", 2, -1); paramMaxUploadsSeeding.setLayoutData(gridData); enable_seeding_uploads .setAdditionalActionPerformer(new ChangeSelectionActionPerformer( paramMaxUploadsSeeding.getControl())); //// gridData = new GridData(); label = new Label(cSection, SWT.NULL); label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.label.max_peers_per_torrent"); gridData = new GridData(); IntParameter paramMaxClients = new IntParameter(cSection, "Max.Peer.Connections.Per.Torrent"); paramMaxClients.setLayoutData(gridData); ///// // max peers when seeding final Composite cMaxPeersOptionsArea = new Composite(cSection, SWT.NULL); layout = new GridLayout(); layout.numColumns = 3; layout.marginWidth = 0; layout.marginHeight = 0; cMaxPeersOptionsArea.setLayout(layout); gridData = new GridData(); gridData.horizontalIndent = 15; gridData.horizontalSpan = 2; cMaxPeersOptionsArea.setLayoutData(gridData); label = new Label(cMaxPeersOptionsArea, SWT.NULL); img.setBackground(label.getBackground()); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); label.setImage(img); gridData = new GridData(); BooleanParameter enable_max_peers_seeding = new BooleanParameter( cMaxPeersOptionsArea, "Max.Peer.Connections.Per.Torrent.When.Seeding.Enable", "ConfigView.label.maxuploadsseeding"); enable_max_peers_seeding.setLayoutData(gridData); gridData = new GridData(); IntParameter paramMaxPeersSeeding = new IntParameter( cMaxPeersOptionsArea, "Max.Peer.Connections.Per.Torrent.When.Seeding", 0, -1); paramMaxPeersSeeding.setLayoutData(gridData); enable_max_peers_seeding .setAdditionalActionPerformer(new ChangeSelectionActionPerformer( paramMaxPeersSeeding.getControl())); ///// gridData = new GridData(); label = new Label(cSection, SWT.NULL); label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.label.max_peers_total"); gridData = new GridData(); IntParameter paramMaxClientsTotal = new IntParameter(cSection, "Max.Peer.Connections.Total"); paramMaxClientsTotal.setLayoutData(gridData); gridData = new GridData(); label = new Label(cSection, SWT.NULL); label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.label.maxseedspertorrent"); gridData = new GridData(); new IntParameter(cSection,"Max Seeds Per Torrent").setLayoutData(gridData); gridData = new GridData(); gridData.horizontalSpan = 2; BooleanParameter useReqLimiting = new BooleanParameter(cSection, "Use Request Limiting", "ConfigView.label.userequestlimiting"); useReqLimiting.setLayoutData(gridData); gridData = new GridData(); gridData.horizontalSpan = 2; BooleanParameter useReqLimitingPrios = new BooleanParameter(cSection, "Use Request Limiting Priorities", "ConfigView.label.userequestlimitingpriorities"); useReqLimitingPrios.setLayoutData(gridData); useReqLimiting .setAdditionalActionPerformer(new ChangeSelectionActionPerformer( useReqLimitingPrios.getControl())); gridData = new GridData(); gridData.horizontalSpan = 2; BooleanParameter allowSameIP = new BooleanParameter(cSection, "Allow Same IP Peers", "ConfigView.label.allowsameip"); allowSameIP.setLayoutData(gridData); // lazy bit field gridData = new GridData(); gridData.horizontalSpan = 2; BooleanParameter lazybf = new BooleanParameter(cSection, "Use Lazy Bitfield", "ConfigView.label.lazybitfield"); lazybf.setLayoutData(gridData); // prioritise first/last pieces gridData = new GridData(); gridData.horizontalSpan = 2; BooleanParameter firstPiece = new BooleanParameter(cSection, "Prioritize First Piece", "ConfigView.label.prioritizefirstpiece"); firstPiece.setLayoutData(gridData); // Further prioritize High priority files according to % complete and size of file gridData = new GridData(); gridData.horizontalSpan = 2; BooleanParameter mostCompletedFiles = new BooleanParameter(cSection, "Prioritize Most Completed Files", "ConfigView.label.prioritizemostcompletedfiles"); mostCompletedFiles.setLayoutData(gridData); // ignore ports Composite cMiniArea = new Composite(cSection, SWT.NULL); layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; layout.marginWidth = 0; cMiniArea.setLayout(layout); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; cMiniArea.setLayoutData(gridData); gridData = new GridData(); label = new Label(cMiniArea, SWT.NULL); label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.label.transfer.ignorepeerports"); gridData = new GridData(); gridData.widthHint = 125; StringParameter ignore_ports = new StringParameter(cMiniArea, "Ignore.peer.ports", "0"); ignore_ports.setLayoutData(gridData); gridData = new GridData(); gridData.horizontalSpan = 2; BooleanParameter pauseOnExit = new BooleanParameter(cSection, "Pause Downloads On Exit", "ConfigView.label.pause.downloads.on.exit"); pauseOnExit.setLayoutData(gridData); gridData = new GridData(); gridData.horizontalSpan = 2; BooleanParameter resumeOnStart = new BooleanParameter(cSection, "Resume Downloads On Start", "ConfigView.label.resume.downloads.on.start"); resumeOnStart.setLayoutData(gridData); } return cSection; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSharing.java0000644000175000017500000001222411256315674030505 0ustar adrianadrian/* * File : ConfigPanel*.java * Created : 11 mar. 2004 * By : TuxPaper * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views.configsections; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; public class ConfigSectionSharing implements UISWTConfigSection { public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } public String configSectionGetName() { return "sharing"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 0; } public Composite configSectionCreate(final Composite parent) { GridData gridData; GridLayout layout; Composite gSharing = new Composite(parent, SWT.WRAP); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gSharing.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; gSharing.setLayout(layout); // row gridData = new GridData(); Label protocol_lab = new Label(gSharing, SWT.NULL); Messages.setLanguageText(protocol_lab, "ConfigView.section.sharing.protocol"); protocol_lab.setLayoutData( gridData ); String[] protocols = {"HTTP","HTTPS","UDP","DHT" }; String[] descs = {"HTTP","HTTPS (SSL)", "UDP", "Decentralised" }; new StringListParameter(gSharing, "Sharing Protocol", "DHT", descs, protocols ); // row GridData grid_data = new GridData(); grid_data.horizontalSpan = 2; final BooleanParameter private_torrent = new BooleanParameter(gSharing, "Sharing Torrent Private", "ConfigView.section.sharing.privatetorrent"); private_torrent.setLayoutData(grid_data); // row gridData = new GridData(); gridData.horizontalSpan = 2; final BooleanParameter permit_dht = new BooleanParameter(gSharing, "Sharing Permit DHT", "ConfigView.section.sharing.permitdht"); permit_dht.setLayoutData( gridData ); private_torrent.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( permit_dht.getControls(), true )); private_torrent.addChangeListener( new ParameterChangeAdapter() { public void parameterChanged( Parameter p, boolean caused_internally ) { if ( private_torrent.isSelected() ){ permit_dht.setSelected( false ); } } }); // row gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(gSharing, "Sharing Add Hashes", "wizard.createtorrent.extrahashes").setLayoutData( gridData ); // row gridData = new GridData(); gridData.horizontalSpan = 2; BooleanParameter rescan_enable = new BooleanParameter(gSharing, "Sharing Rescan Enable", "ConfigView.section.sharing.rescanenable"); rescan_enable.setLayoutData( gridData ); //row gridData = new GridData(); gridData.horizontalIndent = 25; Label period_label = new Label(gSharing, SWT.NULL ); Messages.setLanguageText(period_label, "ConfigView.section.sharing.rescanperiod"); period_label.setLayoutData( gridData ); gridData = new GridData(); IntParameter rescan_period = new IntParameter(gSharing, "Sharing Rescan Period"); rescan_period.setMinimumValue(1); rescan_period.setLayoutData( gridData ); rescan_enable.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( rescan_period.getControls() )); rescan_enable.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( new Control[]{period_label} )); // comment Label comment_label = new Label(gSharing, SWT.NULL ); Messages.setLanguageText(comment_label, "ConfigView.section.sharing.torrentcomment"); new Label(gSharing, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalIndent = 25; gridData.horizontalSpan = 2; StringParameter torrent_comment = new StringParameter(gSharing, "Sharing Torrent Comment", "" ); torrent_comment.setLayoutData(gridData); return gSharing; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/PeerSuperView.java0000644000175000017500000001460011272701446024161 0ustar adrianadrian/* * Created on 2 juil. 2003 * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerPeerListener; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerListener; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.plugins.peers.Peer; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.ui.swt.views.peer.PeerInfoView; import org.gudy.azureus2.ui.swt.views.peer.RemotePieceDistributionView; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab; import org.gudy.azureus2.ui.swt.views.tableitems.peers.DownloadNameItem; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.TableLifeCycleListener; /** * @author Olivier * @author TuxPaper * 2004/Apr/20: Use TableRowImpl instead of PeerRow * 2004/Apr/20: Remove need for tableItemToObject * 2004/Apr/21: extends TableView instead of IAbstractView * @author MjrTom * 2005/Oct/08: Add PieceItem */ public class PeerSuperView extends TableViewTab implements GlobalManagerListener, DownloadManagerPeerListener, TableLifeCycleListener, TableViewSWTMenuFillListener { private TableViewSWT tv; private Shell shell; private boolean active_listener = true; /** * Initialize * */ public PeerSuperView() { super("AllPeersView"); TableColumnCore[] items = PeersView.getBasicColumnItems(TableManager.TABLE_ALL_PEERS); TableColumnCore[] basicItems = new TableColumnCore[items.length + 1]; System.arraycopy(items, 0, basicItems, 0, items.length); basicItems[items.length] = new DownloadNameItem(TableManager.TABLE_ALL_PEERS); tv = new TableViewSWTImpl(Peer.class, TableManager.TABLE_ALL_PEERS, getPropertiesPrefix(), basicItems, "connected_time", SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL); tv.setRowDefaultHeight(16); tv.setEnableTabViews(true); tv.setCoreTabViews(new IView[] { new PeerInfoView(), new RemotePieceDistributionView(), new LoggerView(true) }); tv.addLifeCycleListener(this); tv.addMenuFillListener(this); } public TableViewSWT initYourTableView() { return tv; } // @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewInitialized() public void tableViewInitialized() { shell = tv.getComposite().getShell(); AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { registerGlobalManagerListener(core); } }); } public void tableViewDestroyed() { unregisterListeners(); } public void fillMenu(String sColumnName, final Menu menu) { PeersView.fillMenu(menu, tv, shell, false); } /* DownloadManagerPeerListener implementation */ public void peerAdded(PEPeer created) { tv.addDataSource(created); } public void peerRemoved(PEPeer removed) { tv.removeDataSource(removed); } /** * Add datasources already in existance before we called addListener. * Faster than allowing addListener to call us one datasource at a time. * @param core */ private void addExistingDatasources(AzureusCore core) { if (tv.isDisposed()) { return; } ArrayList sources = new ArrayList(); Iterator itr = core.getGlobalManager().getDownloadManagers().iterator(); while (itr.hasNext()) { PEPeer[] peers = ((DownloadManager)itr.next()).getCurrentPeers(); if (peers != null) { sources.addAll(Arrays.asList(peers)); } } if (sources.isEmpty()) { return; } tv.addDataSources(sources.toArray(new PEPeer[sources.size()])); tv.processDataSourceQueue(); } private void registerGlobalManagerListener(AzureusCore core) { this.active_listener = false; try { core.getGlobalManager().addListener(this); } finally { this.active_listener = true; } addExistingDatasources(core); } private void unregisterListeners() { try { GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); gm.removeListener(this); Iterator itr = gm.getDownloadManagers().iterator(); while(itr.hasNext()) { DownloadManager dm = (DownloadManager)itr.next(); downloadManagerRemoved(dm); } } catch (Exception e) { } } public void downloadManagerAdded(DownloadManager dm) { dm.addPeerListener(this, !this.active_listener); } public void downloadManagerRemoved(DownloadManager dm) { dm.removePeerListener(this); } // Methods I have to implement but have no need for... public void destroyInitiated() {} public void destroyed() {} public void seedingStatusChanged(boolean seeding_only_mode, boolean b) {} public void addThisColumnSubMenu(String columnName, Menu menuThisColumn) {} public void peerManagerAdded(PEPeerManager manager){} public void peerManagerRemoved(PEPeerManager manager) {} public void peerManagerWillBeAdded(PEPeerManager manager) {} } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/PiecesView.java0000644000175000017500000001475411265777354023506 0ustar adrianadrian/* * Created on 2 juil. 2003 * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerPeerListener; import org.gudy.azureus2.core3.download.DownloadManagerPieceListener; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.ui.swt.components.Legend; import org.gudy.azureus2.ui.swt.views.piece.MyPieceDistributionView; import org.gudy.azureus2.ui.swt.views.piece.PieceInfoView; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab; import org.gudy.azureus2.ui.swt.views.tableitems.pieces.*; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.TableDataSourceChangedListener; import com.aelitis.azureus.ui.common.table.TableLifeCycleListener; import org.gudy.azureus2.plugins.ui.tables.TableManager; /** * @author Olivier * @author TuxPaper * 2004/Apr/20: Remove need for tableItemToObject * 2004/Apr/21: extends TableView instead of IAbstractView * @author MjrTom * 2005/Oct/08: Add PriorityItem, SpeedItem */ public class PiecesView extends TableViewTab implements DownloadManagerPeerListener, DownloadManagerPieceListener, TableDataSourceChangedListener, TableLifeCycleListener { private final static TableColumnCore[] basicItems = { new PieceNumberItem(), new SizeItem(), new BlockCountItem(), new BlocksItem(), new CompletedItem(), new AvailabilityItem(), new TypeItem(), new ReservedByItem(), new WritersItem(), new PriorityItem(), new SpeedItem(), new RequestedItem() }; DownloadManager manager; private TableViewSWTImpl tv; private Composite legendComposite; private PieceInfoView pieceInfoView; private MyPieceDistributionView pieceDistView; /** * Initialize * */ public PiecesView() { super("PiecesView"); } // @see org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab#initYourTableView() public TableViewSWT initYourTableView() { tv = new TableViewSWTImpl(PEPiece.class, TableManager.TABLE_TORRENT_PIECES, getPropertiesPrefix(), basicItems, basicItems[0].getName(), SWT.SINGLE | SWT.FULL_SELECTION | SWT.VIRTUAL); tv.setEnableTabViews(true); pieceInfoView = new PieceInfoView(); pieceDistView = new MyPieceDistributionView(); tv.setCoreTabViews(new IView[] { pieceInfoView,pieceDistView }); tv.addTableDataSourceChangedListener(this, true); tv.addLifeCycleListener(this); return tv; } // @see com.aelitis.azureus.ui.common.table.TableDataSourceChangedListener#tableDataSourceChanged(java.lang.Object) public void tableDataSourceChanged(Object newDataSource) { if (manager != null){ manager.removePeerListener(this); manager.removePieceListener(this); } if (newDataSource == null) manager = null; else if (newDataSource instanceof Object[]) manager = (DownloadManager)((Object[])newDataSource)[0]; else manager = (DownloadManager)newDataSource; if (manager != null) { manager.addPeerListener(this, false); manager.addPieceListener(this, false); addExistingDatasources(); } if (pieceInfoView != null) { pieceInfoView.dataSourceChanged(manager); } if (pieceDistView != null) { pieceDistView.dataSourceChanged(manager); } } // @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewInitialized() public void tableViewInitialized() { if (legendComposite != null && (tv instanceof TableViewSWT)) { Composite composite = ((TableViewSWT) tv).getTableComposite(); legendComposite = Legend.createLegendComposite(composite, BlocksItem.colors, new String[] { "PiecesView.legend.requested", "PiecesView.legend.written", "PiecesView.legend.downloaded", "PiecesView.legend.incache" }); } if (manager != null) { manager.removePeerListener(this); manager.removePieceListener(this); manager.addPeerListener(this, false); manager.addPieceListener(this, false); addExistingDatasources(); } } // @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewDestroyed() public void tableViewDestroyed() { if (legendComposite != null && legendComposite.isDisposed()) { legendComposite.dispose(); } if (manager != null) { manager.removePeerListener(this); manager.removePieceListener(this); } } /* DownloadManagerPeerListener implementation */ public void pieceAdded(PEPiece created) { tv.addDataSource(created); } public void pieceRemoved(PEPiece removed) { tv.removeDataSource(removed); } public void peerAdded(PEPeer peer) { } public void peerRemoved(PEPeer peer) { } public void peerManagerWillBeAdded( PEPeerManager peer_manager ){} public void peerManagerAdded(PEPeerManager manager) { } public void peerManagerRemoved(PEPeerManager manager) { tv.removeAllTableRows(); } /** * Add datasources already in existance before we called addListener. * Faster than allowing addListener to call us one datasource at a time. */ private void addExistingDatasources() { if (manager == null || tv.isDisposed()) { return; } PEPiece[] dataSources = manager.getCurrentPieces(); if (dataSources == null || dataSources.length == 0) return; tv.addDataSources(dataSources); tv.processDataSourceQueue(); } /** * @return the manager */ public DownloadManager getManager() { return manager; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/piece/0000755000175000017500000000000011310377636021640 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/piece/MyPieceDistributionView.java0000644000175000017500000000327510704550426027274 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.piece; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.ui.swt.views.PieceDistributionView; /** * @author The8472 * @created Jun 28, 2007 * */ public class MyPieceDistributionView extends PieceDistributionView { public MyPieceDistributionView() { isMe = true; } public void dataSourceChanged(Object newDataSource) { if (newDataSource instanceof DownloadManager) { pem = ((DownloadManager)newDataSource).getPeerManager(); refresh(); } else if(newDataSource instanceof Object[]) { newDataSource = ((Object[])newDataSource)[0]; if(newDataSource instanceof PEPiece) { PEPiece piece = (PEPiece)newDataSource; pem = piece.getManager(); } } else pem = null; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/piece/PieceInfoView.java0000644000175000017500000004460011262747454025210 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views.piece; import java.util.Iterator; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.disk.DiskManagerPiece; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerPieceListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.Legend; import org.gudy.azureus2.ui.swt.debug.ObfusticateImage; import org.gudy.azureus2.ui.swt.debug.UIDebugGenerator; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.views.AbstractIView; /** * @author TuxPaper * @created Feb 26, 2007 * */ public class PieceInfoView extends AbstractIView implements ObfusticateImage, DownloadManagerPieceListener { private final static int BLOCK_FILLSIZE = 14; private final static int BLOCK_SPACING = 3; private final static int BLOCK_SIZE = BLOCK_FILLSIZE + BLOCK_SPACING; private final static int BLOCKCOLOR_HAVE = 0; private final static int BLOCKCOLORL_NOHAVE = 1; private final static int BLOCKCOLOR_TRANSFER = 2; private final static int BLOCKCOLOR_NEXT = 3; private final static int BLOCKCOLOR_AVAILCOUNT = 4; private Composite pieceInfoComposite; private ScrolledComposite sc; protected Canvas pieceInfoCanvas; private Color[] blockColors; private Label topLabel; private Label imageLabel; // More delay for this view because of high workload private int graphicsUpdate = COConfigurationManager.getIntParameter("Graphics Update") * 2; private int loopFactor = 0; private Font font = null; Image img = null; private DownloadManager dlm; BlockInfo[] oldBlockInfo; /** * Initialize * */ public PieceInfoView() { blockColors = new Color[] { Colors.blues[Colors.BLUES_DARKEST], Colors.white, Colors.red, Colors.fadedRed, Colors.black }; } public void dataSourceChanged(Object newDataSource) { if (newDataSource instanceof DownloadManager) { oldBlockInfo = null; if (dlm != null) { dlm.removePieceListener(this); } dlm = (DownloadManager)newDataSource; dlm.addPieceListener(this, false); fillPieceInfoSection(); } } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#getData() */ public String getData() { return "PeersView.BlockView.title"; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#initialize(org.eclipse.swt.widgets.Composite) */ public void initialize(Composite composite) { if (pieceInfoComposite != null && !pieceInfoComposite.isDisposed()) { Logger.log(new LogEvent(LogIDs.GUI, LogEvent.LT_ERROR, "PeerInfoView already initialized! Stack: " + Debug.getStackTrace(true, false))); delete(); } createPeerInfoPanel(composite); fillPieceInfoSection(); } private Composite createPeerInfoPanel(Composite parent) { GridLayout layout; GridData gridData; // Peer Info section contains // - Peer's Block display // - Peer's Datarate pieceInfoComposite = new Composite(parent, SWT.NONE); layout = new GridLayout(); layout.numColumns = 2; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; pieceInfoComposite.setLayout(layout); gridData = new GridData(GridData.FILL, GridData.FILL, true, true); pieceInfoComposite.setLayoutData(gridData); imageLabel = new Label(pieceInfoComposite, SWT.NULL); gridData = new GridData(); imageLabel.setLayoutData(gridData); topLabel = new Label(pieceInfoComposite, SWT.NULL); gridData = new GridData(SWT.FILL, SWT.DEFAULT, false, false); topLabel.setLayoutData(gridData); sc = new ScrolledComposite(pieceInfoComposite, SWT.V_SCROLL); sc.setExpandHorizontal(true); sc.setExpandVertical(true); layout = new GridLayout(); layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; sc.setLayout(layout); gridData = new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1); sc.setLayoutData(gridData); sc.getVerticalBar().setIncrement(BLOCK_SIZE); pieceInfoCanvas = new Canvas(sc, SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND); gridData = new GridData(GridData.FILL, SWT.DEFAULT, true, false); pieceInfoCanvas.setLayoutData(gridData); pieceInfoCanvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { if (e.width <= 0 || e.height <= 0) return; try { Rectangle bounds = (img == null) ? null : img.getBounds(); if (bounds == null) { e.gc.fillRectangle(e.x, e.y, e.width, e.height); } else { if (e.x + e.width > bounds.width) e.gc.fillRectangle(bounds.width, e.y, e.x + e.width - bounds.width + 1, e.height); if (e.y + e.height > bounds.height) e.gc.fillRectangle(e.x, bounds.height, e.width, e.y + e.height - bounds.height + 1); int width = Math.min(e.width, bounds.width - e.x); int height = Math.min(e.height, bounds.height - e.y); e.gc.drawImage(img, e.x, e.y, width, height, e.x, e.y, width, height); } } catch (Exception ex) { } } }); Listener doNothingListener = new Listener() { public void handleEvent(Event event) { } }; pieceInfoCanvas.addListener(SWT.KeyDown, doNothingListener); pieceInfoCanvas.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { // wrap in asyncexec because sc.setMinWidth (called later) doesn't work // too well inside a resize (the canvas won't size isn't always updated) e.widget.getDisplay().asyncExec(new AERunnable() { public void runSupport() { if (img != null) { int iOldColCount = img.getBounds().width / BLOCK_SIZE; int iNewColCount = pieceInfoCanvas.getClientArea().width / BLOCK_SIZE; if (iOldColCount != iNewColCount) refreshInfoCanvas(); } } }); } }); sc.setContent(pieceInfoCanvas); Legend.createLegendComposite(pieceInfoComposite, blockColors, new String[] { "PiecesView.BlockView.Have", "PiecesView.BlockView.NoHave", "PeersView.BlockView.Transfer", "PeersView.BlockView.NextRequest", "PeersView.BlockView.AvailCount" }, new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1)); int iFontPixelsHeight = 10; int iFontPointHeight = (iFontPixelsHeight * 72) / pieceInfoCanvas.getDisplay().getDPI().y; Font f = pieceInfoCanvas.getFont(); FontData[] fontData = f.getFontData(); fontData[0].setHeight(iFontPointHeight); font = new Font(pieceInfoCanvas.getDisplay(), fontData); return pieceInfoComposite; } private boolean alreadyFilling = false; public void fillPieceInfoSection() { if (alreadyFilling) { return; } alreadyFilling = true; Utils.execSWTThreadLater(100, new AERunnable() { public void runSupport() { if (!alreadyFilling) { return; } try { if (imageLabel == null || imageLabel.isDisposed()) { return; } if (imageLabel.getImage() != null) { Image image = imageLabel.getImage(); imageLabel.setImage(null); image.dispose(); } refreshInfoCanvas(); } finally { alreadyFilling = false; } } }); } public void refresh() { super.refresh(); if (loopFactor++ % graphicsUpdate == 0) { refreshInfoCanvas(); } } protected void refreshInfoCanvas() { alreadyFilling = false; if (!pieceInfoCanvas.isVisible()) { return; } pieceInfoCanvas.layout(true); Rectangle bounds = pieceInfoCanvas.getClientArea(); if (bounds.width <= 0 || bounds.height <= 0) { topLabel.setText(""); return; } if (dlm == null) { GC gc = new GC(pieceInfoCanvas); gc.fillRectangle(bounds); gc.dispose(); topLabel.setText(""); return; } PEPeerManager pm = dlm.getPeerManager(); DiskManager dm = dlm.getDiskManager(); if (pm == null || dm == null) { GC gc = new GC(pieceInfoCanvas); gc.fillRectangle(bounds); gc.dispose(); topLabel.setText(""); return; } int iNumCols = bounds.width / BLOCK_SIZE; int iNeededHeight = (((dm.getNbPieces() - 1) / iNumCols) + 1) * BLOCK_SIZE; if (img != null && !img.isDisposed()) { Rectangle imgBounds = img.getBounds(); if (imgBounds.width != bounds.width || imgBounds.height != iNeededHeight) { oldBlockInfo = null; img.dispose(); img = null; } } DiskManagerPiece[] dm_pieces = dm.getPieces(); PEPiece[] currentDLPieces = pm.getPieces(); byte[] uploadingPieces = new byte[dm_pieces.length]; // find upload pieces Iterator peer_it = pm.getPeers().iterator(); while( peer_it.hasNext()){ PEPeer peer = peer_it.next(); int[] peerRequestedPieces = peer.getIncomingRequestedPieceNumbers(); if (peerRequestedPieces != null && peerRequestedPieces.length > 0) { int pieceNum = peerRequestedPieces[0]; if(uploadingPieces[pieceNum] < 2) uploadingPieces[pieceNum] = 2; for (int j = 1; j < peerRequestedPieces.length; j++) { pieceNum = peerRequestedPieces[j]; if(uploadingPieces[pieceNum] < 1) uploadingPieces[pieceNum] = 1; } } } if (sc.getMinHeight() != iNeededHeight) { sc.setMinHeight(iNeededHeight); sc.layout(true, true); bounds = pieceInfoCanvas.getClientArea(); } int[] availability = pm.getAvailability(); int minAvailability = Integer.MAX_VALUE; int minAvailability2 = Integer.MAX_VALUE; if (availability != null && availability.length > 0) { for (int i = 0; i < availability.length; i++) { if (availability[i] != 0 && availability[i] < minAvailability) { minAvailability2 = minAvailability; minAvailability = availability[i]; if (minAvailability == 1) { break; } } } } if (img == null) { img = new Image(pieceInfoCanvas.getDisplay(), bounds.width, iNeededHeight); } GC gcImg = new GC(img); BlockInfo[] newBlockInfo = new BlockInfo[dm_pieces.length]; int iRow = 0; try { // use advanced capabilities for faster drawText gcImg.setAdvanced(true); if (oldBlockInfo == null) { gcImg.setBackground(pieceInfoCanvas.getBackground()); gcImg.fillRectangle(0, 0, bounds.width, iNeededHeight); } gcImg.setFont(font); int iCol = 0; for (int i = 0; i < dm_pieces.length; i++) { if (iCol >= iNumCols) { iCol = 0; iRow++; } newBlockInfo[i] = new BlockInfo(); int colorIndex; boolean done = dm_pieces[i].isDone(); int iXPos = iCol * BLOCK_SIZE + 1; int iYPos = iRow * BLOCK_SIZE + 1; if (done) { colorIndex = BLOCKCOLOR_HAVE; newBlockInfo[i].haveWidth = BLOCK_FILLSIZE; } else { // !done boolean partiallyDone = dm_pieces[i].getNbWritten() > 0; int width = BLOCK_FILLSIZE; if (partiallyDone) { int iNewWidth = (int) (((float) dm_pieces[i].getNbWritten() / dm_pieces[i].getNbBlocks()) * width); if (iNewWidth >= width) iNewWidth = width - 1; else if (iNewWidth <= 0) iNewWidth = 1; newBlockInfo[i].haveWidth = iNewWidth; } } if (currentDLPieces[i] != null && currentDLPieces[i].hasUndownloadedBlock()) { newBlockInfo[i].downloadingIndicator = true; } newBlockInfo[i].uploadingIndicator = uploadingPieces[i] > 0; if (newBlockInfo[i].uploadingIndicator) { newBlockInfo[i].uploadingIndicatorSmall = uploadingPieces[i] < 2; } if (availability != null) { newBlockInfo[i].availNum = availability[i]; if (minAvailability2 == availability[i]) { newBlockInfo[i].availDotted = true; } } else { newBlockInfo[i].availNum = -1; } if (oldBlockInfo != null && i < oldBlockInfo.length && oldBlockInfo[i].sameAs(newBlockInfo[i])) { iCol++; continue; } gcImg.setBackground(pieceInfoCanvas.getBackground()); gcImg.fillRectangle(iCol * BLOCK_SIZE, iRow * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); colorIndex = BLOCKCOLOR_HAVE; gcImg.setBackground(blockColors[colorIndex]); gcImg.fillRectangle(iXPos, iYPos, newBlockInfo[i].haveWidth, BLOCK_FILLSIZE); colorIndex = BLOCKCOLORL_NOHAVE; gcImg.setBackground(blockColors[colorIndex]); gcImg.fillRectangle(iXPos + newBlockInfo[i].haveWidth, iYPos, BLOCK_FILLSIZE - newBlockInfo[i].haveWidth, BLOCK_FILLSIZE); if (newBlockInfo[i].downloadingIndicator) { drawDownloadIndicator(gcImg, iXPos, iYPos, false); } if (newBlockInfo[i].uploadingIndicator) { drawUploadIndicator(gcImg, iXPos, iYPos, newBlockInfo[i].uploadingIndicatorSmall); } if (newBlockInfo[i].availNum != -1) { if (minAvailability == newBlockInfo[i].availNum) { gcImg.setForeground(blockColors[BLOCKCOLOR_AVAILCOUNT]); gcImg.drawRectangle(iXPos - 1, iYPos - 1, BLOCK_FILLSIZE + 1, BLOCK_FILLSIZE + 1); } if (minAvailability2 == newBlockInfo[i].availNum) { gcImg.setLineStyle(SWT.LINE_DOT); gcImg.setForeground(blockColors[BLOCKCOLOR_AVAILCOUNT]); gcImg.drawRectangle(iXPos - 1, iYPos - 1, BLOCK_FILLSIZE + 1, BLOCK_FILLSIZE + 1); gcImg.setLineStyle(SWT.LINE_SOLID); } String sNumber = String.valueOf(newBlockInfo[i].availNum); Point size = gcImg.stringExtent(sNumber); if (newBlockInfo[i].availNum < 100) { int x = iXPos + (BLOCK_FILLSIZE / 2) - (size.x / 2); int y = iYPos + (BLOCK_FILLSIZE / 2) - (size.y / 2); gcImg.setForeground(blockColors[BLOCKCOLOR_AVAILCOUNT]); gcImg.drawText(sNumber, x, y, true); } } iCol++; } oldBlockInfo = newBlockInfo; } catch (Exception e) { Logger.log(new LogEvent(LogIDs.GUI, "drawing piece map", e)); } finally { gcImg.dispose(); } topLabel.setText(MessageText.getString("PiecesView.BlockView.Header", new String[] { "" + iNumCols, "" + (iRow + 1), "" + dm_pieces.length })); pieceInfoCanvas.redraw(); } private void drawDownloadIndicator(GC gcImg, int iXPos, int iYPos, boolean small) { if (small) { gcImg.setBackground(blockColors[BLOCKCOLOR_NEXT]); gcImg.fillPolygon(new int[] { iXPos + 2, iYPos + 2, iXPos + BLOCK_FILLSIZE - 1, iYPos + 2, iXPos + (BLOCK_FILLSIZE / 2), iYPos + BLOCK_FILLSIZE - 1 }); } else { gcImg.setBackground(blockColors[BLOCKCOLOR_TRANSFER]); gcImg.fillPolygon(new int[] { iXPos, iYPos, iXPos + BLOCK_FILLSIZE, iYPos, iXPos + (BLOCK_FILLSIZE / 2), iYPos + BLOCK_FILLSIZE }); } } private void drawUploadIndicator(GC gcImg, int iXPos, int iYPos, boolean small) { if (!small) { gcImg.setBackground(blockColors[BLOCKCOLOR_TRANSFER]); gcImg.fillPolygon(new int[] { iXPos, iYPos + BLOCK_FILLSIZE, iXPos + BLOCK_FILLSIZE, iYPos + BLOCK_FILLSIZE, iXPos + (BLOCK_FILLSIZE / 2), iYPos }); } else { // Small Up Arrow each upload request gcImg.setBackground(blockColors[BLOCKCOLOR_NEXT]); gcImg.fillPolygon(new int[] { iXPos + 1, iYPos + BLOCK_FILLSIZE - 2, iXPos + BLOCK_FILLSIZE - 2, iYPos + BLOCK_FILLSIZE - 2, iXPos + (BLOCK_FILLSIZE / 2), iYPos + 2 }); } } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#getComposite() */ public Composite getComposite() { return pieceInfoComposite; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.views.AbstractIView#delete() */ public void delete() { if (imageLabel != null && !imageLabel.isDisposed() && imageLabel.getImage() != null) { Image image = imageLabel.getImage(); imageLabel.setImage(null); image.dispose(); } if (img != null && !img.isDisposed()) { img.dispose(); img = null; } if (font != null && !font.isDisposed()) { font.dispose(); font = null; } if(dlm != null) dlm.removePieceListener(this); super.delete(); } public Image obfusticatedImage(Image image, Point shellOffset) { UIDebugGenerator.obfusticateArea(image, topLabel, shellOffset, ""); return image; } // @see org.gudy.azureus2.core3.download.DownloadManagerPeerListener#pieceAdded(org.gudy.azureus2.core3.peer.PEPiece) public void pieceAdded(PEPiece piece) { fillPieceInfoSection(); } // @see org.gudy.azureus2.core3.download.DownloadManagerPeerListener#pieceRemoved(org.gudy.azureus2.core3.peer.PEPiece) public void pieceRemoved(PEPiece piece) { fillPieceInfoSection(); } private static class BlockInfo { public int haveWidth; int availNum; boolean availDotted; boolean uploadingIndicator; boolean uploadingIndicatorSmall; boolean downloadingIndicator; /** * */ public BlockInfo() { haveWidth = -1; } public boolean sameAs(BlockInfo otherBlockInfo) { return haveWidth == otherBlockInfo.haveWidth && availNum == otherBlockInfo.availNum && availDotted == otherBlockInfo.availDotted && uploadingIndicator == otherBlockInfo.uploadingIndicator && uploadingIndicatorSmall == otherBlockInfo.uploadingIndicatorSmall && downloadingIndicator == otherBlockInfo.downloadingIndicator; } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/IViewExtension.java0000644000175000017500000000240710457421366024342 0ustar adrianadrian/* * Created on Jul 19, 2006 3:46:25 AM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views; import org.eclipse.swt.widgets.Menu; /** * IView extensions (not added to IView because that's used in the Plugin * Interface * * @author TuxPaper * @created Jul 19, 2006 * */ public interface IViewExtension { public Menu getPrivateMenu(); public void viewActivated(); public void viewDeactivated(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/views/TorrentInfoView.java0000644000175000017500000002735511307334262024530 0ustar adrianadrian/* * Created on 16-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.views; import java.net.URL; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.LocaleTorrentUtil; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLGroup; import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.components.BufferedLabel; import org.gudy.azureus2.ui.swt.views.table.impl.FakeTableCell; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import com.aelitis.azureus.ui.common.table.TableCellCore; import com.aelitis.azureus.ui.common.table.TableColumnCore; import org.gudy.azureus2.plugins.download.*; import org.gudy.azureus2.plugins.ui.tables.TableManager; public class TorrentInfoView extends AbstractIView { private static final String TEXT_PREFIX = "TorrentInfoView."; private DownloadManager download_manager; private Composite outer_panel; private Font headerFont; private FakeTableCell[] cells; private ScrolledComposite sc; private Composite parent; protected TorrentInfoView( ) { } public void initialize( Composite composite) { this.parent = composite; if (download_manager == null) { return; } // cheap trick to allow datasource changes. Normally we'd just // refill the components with new info, but I didn't write this and // I don't want to waste my time :) [tux] if (sc != null && !sc.isDisposed()) { sc.dispose(); } sc = new ScrolledComposite(composite, SWT.V_SCROLL | SWT.H_SCROLL ); sc.setExpandHorizontal(true); sc.setExpandVertical(true); GridData gridData = new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1); sc.setLayoutData(gridData); outer_panel = sc; Composite panel = new Composite(sc, SWT.NULL); sc.setContent( panel ); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 1; panel.setLayout(layout); //int userMode = COConfigurationManager.getIntParameter("User Mode"); // header Composite cHeader = new Composite(panel, SWT.BORDER); GridLayout configLayout = new GridLayout(); configLayout.marginHeight = 3; configLayout.marginWidth = 0; cHeader.setLayout(configLayout); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER); cHeader.setLayoutData(gridData); Display d = panel.getDisplay(); cHeader.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION)); cHeader.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); Label lHeader = new Label(cHeader, SWT.NULL); lHeader.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION)); lHeader.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); FontData[] fontData = lHeader.getFont().getFontData(); fontData[0].setStyle(SWT.BOLD); int fontHeight = (int)(fontData[0].getHeight() * 1.2); fontData[0].setHeight(fontHeight); headerFont = new Font(d, fontData); lHeader.setFont(headerFont); lHeader.setText( " " + MessageText.getString( "authenticator.torrent" ) + " : " + download_manager.getDisplayName().replaceAll("&", "&&")); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER); lHeader.setLayoutData(gridData); Composite gTorrentInfo = new Composite(panel, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gTorrentInfo.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; gTorrentInfo.setLayout(layout); // torrent encoding Label label = new Label(gTorrentInfo, SWT.NULL); gridData = new GridData(); label.setLayoutData( gridData ); label.setText( MessageText.getString( TEXT_PREFIX + "torrent.encoding" ) + ": " ); TOTorrent torrent = download_manager.getTorrent(); BufferedLabel blabel = new BufferedLabel(gTorrentInfo, SWT.NULL); gridData = new GridData(); blabel.setLayoutData( gridData ); blabel.setText(torrent==null?"":LocaleTorrentUtil.getCurrentTorrentEncoding( torrent )); // trackers label = new Label(gTorrentInfo, SWT.NULL); gridData = new GridData(); label.setLayoutData( gridData ); label.setText( MessageText.getString( "MyTrackerView.tracker" ) + ": " ); String trackers = ""; if ( torrent != null ){ TOTorrentAnnounceURLGroup group = torrent.getAnnounceURLGroup(); TOTorrentAnnounceURLSet[] sets = group.getAnnounceURLSets(); List tracker_list = new ArrayList(); URL url = torrent.getAnnounceURL(); tracker_list.add( url.getHost() + (url.getPort()==-1?"":(":"+url.getPort()))); for (int i=0;i 0 ){ trackers += " ("; for (int i=0;i 1) { if (DEBUG) { for (int i = 0; i < buffer.length; i++) { if (buffer[i] >= 32) System.out.print(((char) buffer[i])); else System.out.print("#"); } System.out.println(); } boolean bFirst0 = buffer[0] == 0; boolean bSecond0 = buffer[1] == 0; if (bFirst0 && bSecond0) // This is probably UTF-32 Big Endian. // Let's hope default constructor can handle it (It can't) data = new String(buffer); else if (bFirst0) data = new String(buffer, "UTF-16BE"); else if (bSecond0) data = new String(buffer, "UTF-16LE"); else if (buffer[0] == (byte) 0xEF && buffer[1] == (byte) 0xBB && buffer.length > 3 && buffer[2] == (byte) 0xBF) data = new String(buffer, 3, buffer.length - 3, "UTF-8"); else if (buffer[0] == (byte) 0xFF || buffer[0] == (byte) 0xFE) data = new String(buffer, "UTF-16"); else { data = new String(buffer); } } else { // Older Code: // Remove 0 values from byte array, messing up any Unicode strings byte[] text = new byte[buffer.length]; int j = 0; for (int i = 0; i < buffer.length; i++) { if (buffer[i] != 0) text[j++] = buffer[i]; } data = new String(text, 0, j); } int iPos = data.indexOf("\nURL="); if (iPos > 0) { int iEndPos = data.indexOf("\r", iPos); if (iEndPos < 0) { iEndPos = data.length(); } myData = new URLType(); myData.linkURL = data.substring(iPos + 5, iEndPos); myData.linkText = ""; } else { String[] split = data.split("[\r\n]+", 2); myData = new URLType(); myData.linkURL = (split.length > 0) ? split[0] : ""; myData.linkText = (split.length > 1) ? split[1] : ""; } } catch (Exception ex) { ex.printStackTrace(); } return myData; } protected String[] getTypeNames() { return supportedTypes; } protected int[] getTypeIds() { return supportedTypeIds; } /** * @param transferData * @see org.eclipse.swt.dnd.Transfer#isSupportedType(org.eclipse.swt.dnd.TransferData) * @return */ public boolean isSupportedType(TransferData transferData) { if (bCheckingString) return true; if (transferData == null) return false; // TODO: Check if it's a string list of URLs // String -- Check if URL, skip to next if not URLType url = null; if (DEBUG) System.out.println("Checking if type #" + transferData.type + " is URL"); bCheckingString = true; try { byte[] buffer = (byte[]) super.nativeToJava(transferData); url = bytebufferToJava(buffer); } catch (Exception e) { Debug.out(e); } finally { bCheckingString = false; } if (url == null) { if (DEBUG) System.out.println("no, Null URL for type #" + transferData.type); return false; } if (UrlUtils.isURL(url.linkURL, false)) { if (DEBUG) System.out.println("Yes, " + url.linkURL + " of type #" + transferData.type); return true; } if (DEBUG) System.out.println("no, " + url.linkURL + " not URL for type #" + transferData.type); return false; } /** * Sometimes, CF_Text will be in currentDataType even though CF_UNICODETEXT * is present. This is a workaround until its fixed properly. *

    * Place it in dropAccept * *

    	 *if (event.data instanceof URLTransfer.URLType)
    	 *	event.currentDataType = URLTransfer.pickBestType(event.dataTypes, event.currentDataType);
    	 * 
    * * @param dataTypes * @param def * @return */ public static TransferData pickBestType(TransferData[] dataTypes, TransferData def) { for (int i = 0; i < supportedTypeIds.length; i++) { int supportedTypeID = supportedTypeIds[i]; for (int j = 0; j < dataTypes.length; j++) { try { TransferData data = dataTypes[j]; if (supportedTypeID == data.type) return data; } catch (Throwable t) { Debug.out("Picking Best Type", t); } } } return def; } public class URLType { public String linkURL; public String linkText; public String toString() { return linkURL + "\n" + linkText; } } /** * Test for varioud UTF Strings * BOM information from http://www.unicode.org/faq/utf_bom.html * @param args */ public static void main(String[] args) { Map map = new LinkedHashMap(); map.put("UTF-8", new byte[] { (byte) 0xEF, (byte) 0xbb, (byte) 0xbf, 'H', 'i' }); map.put("UTF-32 BE BOM", new byte[] { 0, 0, (byte) 0xFE, (byte) 0xFF, 'H', 0, 0, 0, 'i', 0, 0, 0 }); map.put("UTF-16 LE BOM", new byte[] { (byte) 0xFF, (byte) 0xFE, 'H', 0, 'i', 0 }); map.put("UTF-16 BE BOM", new byte[] { (byte) 0xFE, (byte) 0xFF, 0, 'H', 0, 'i' }); map.put("UTF-16 LE", new byte[] { 'H', 0, 'i', 0 }); map.put("UTF-16 BE", new byte[] { 0, 'H', 0, 'i' }); for (Iterator iterator = map.keySet().iterator(); iterator.hasNext();) { String element = (String) iterator.next(); System.out.println(element + ":"); byte[] buffer = (byte[]) map.get(element); boolean bFirst0 = buffer[0] == 0; boolean bSecond0 = buffer[1] == 0; String data = ""; try { if (bFirst0 && bSecond0) // This is probably UTF-32 Big Endian. // Let's hope default constructor can handle it (It can't) data = new String(buffer); else if (bFirst0) data = new String(buffer, "UTF-16BE"); else if (bSecond0) data = new String(buffer, "UTF-16LE"); else if (buffer[0] == (byte) 0xEF && buffer[1] == (byte) 0xBB && buffer.length > 3 && buffer[2] == (byte) 0xBF) data = new String(buffer, 3, buffer.length - 3, "UTF-8"); else if (buffer[0] == (byte) 0xFF || buffer[0] == (byte) 0xFE) data = new String(buffer, "UTF-16"); else { data = new String(buffer); } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(data); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/help/0000755000175000017500000000000011310377636020346 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/help/AboutWindow.java0000644000175000017500000002601411251621204023441 0ustar adrianadrian/* * File : AboutWindow.java * Created : 18 d�c. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.help; import java.util.Properties; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.mainwindow.*; import org.gudy.azureus2.update.CorePatchLevel; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author Olivier * */ public class AboutWindow { private final static String IMG_SPLASH = "azureus_splash"; static Image image; static AEMonitor class_mon = new AEMonitor( "AboutWindow" ); private static Shell instance; private static Image imgSrc; private static int paintColorTo = 0; public static void show() { Utils.execSWTThread(new AERunnable() { public void runSupport() { _show(); } }); } private static void _show() { if(instance != null) { instance.open(); return; } paintColorTo = 0; Properties properties = new Properties(); try { properties.load(AboutWindow.class.getClassLoader().getResourceAsStream("org/gudy/azureus2/ui/swt/about.properties")); } catch (Exception e1) { Debug.printStackTrace( e1 ); return; } final Shell window = ShellFactory.createMainShell((Constants.isOSX) ? SWT.DIALOG_TRIM : (SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL)); Utils.setShellIcon(window); final Display display = window.getDisplay(); window.setText(MessageText.getString("MainWindow.about.title") + " " + Constants.AZUREUS_VERSION); //$NON-NLS-1$ GridData gridData; window.setLayout(new GridLayout(3, false)); ImageLoader imageLoader = ImageLoader.getInstance(); image = imageLoader.getImage(IMG_SPLASH); if (image != null) { int w = image.getBounds().width; int ow = w; if (w > 350) { w = 350; } int h = image.getBounds().height; h = 220; imgSrc = new Image(display, w, h); GC gc = new GC(imgSrc); gc.drawImage(image, (w - ow) / 2, 0); gc.dispose(); Image imgGray = new Image(display, imageLoader.getImage(IMG_SPLASH), SWT.IMAGE_GRAY); imageLoader.releaseImage(IMG_SPLASH); gc = new GC(imgGray); if (Constants.isOSX) { gc.drawImage(imgGray, (w - ow) / 2, 0); } else { gc.copyArea(0, 0, ow, h, (w - ow) / 2, 0); } gc.dispose(); Image image2 = new Image(display, w, h); gc = new GC(image2); gc.setBackground(Colors.black); gc.fillRectangle(image2.getBounds()); gc.dispose(); image = Utils.renderTransparency(display, image2, imgGray, new Point(0, 0), 180); image2.dispose(); imgGray.dispose(); } imageLoader.releaseImage(IMG_SPLASH); Group gDevelopers = new Group(window, SWT.NULL); gDevelopers.setLayout(new GridLayout()); Messages.setLanguageText(gDevelopers, "MainWindow.about.section.developers"); //$NON-NLS-1$ gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gDevelopers.setLayoutData(gridData); Label label = new Label(gDevelopers, SWT.LEFT); label.setText(properties.getProperty("developers")); //$NON-NLS-1$ //$NON-NLS-2$ label.setLayoutData(gridData = new GridData()); final Canvas labelImage = new Canvas(window, SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND); //labelImage.setImage(image); gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); Rectangle imgBounds = image.getBounds(); gridData.widthHint = imgBounds.width; gridData.heightHint = imgBounds.height; labelImage.setLayoutData(gridData); labelImage.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { Rectangle boundsColor = imgSrc.getBounds(); if (paintColorTo > 0) { e.gc.drawImage(imgSrc, 0, 0, paintColorTo, boundsColor.height, 0, 0, paintColorTo, boundsColor.height); } Rectangle imgBounds = image.getBounds(); if (imgBounds.width - paintColorTo - 1 > 0) { e.gc.drawImage(image, paintColorTo + 1, 0, imgBounds.width - paintColorTo - 1, imgBounds.height, paintColorTo + 1, 0, imgBounds.width - paintColorTo - 1, imgBounds.height); } } }); Group gTranslators = new Group(window, SWT.NULL); GridLayout gl = new GridLayout(); gl.marginHeight = 2; gl.marginWidth = 0; gTranslators.setLayout(gl); Messages.setLanguageText(gTranslators, "MainWindow.about.section.translators"); //$NON-NLS-1$ gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gTranslators.setLayoutData(gridData); Text txtTrans = new Text(gTranslators, SWT.READ_ONLY | SWT.MULTI | SWT.WRAP | SWT.NO_FOCUS); txtTrans.setText(properties.getProperty("translators")); //$NON-NLS-1$ //$NON-NLS-2$ gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = txtTrans.computeSize(SWT.DEFAULT, SWT.DEFAULT).y + 10; txtTrans.setLayoutData(gridData); txtTrans.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); Group gInternet = new Group(window, SWT.NULL); GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 2; gridLayout.makeColumnsEqualWidth = true; gInternet.setLayout(gridLayout); Messages.setLanguageText(gInternet, "MainWindow.about.section.internet"); //$NON-NLS-1$ gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan = 2; gInternet.setLayoutData(gridData); Group gSys = new Group(window, SWT.NULL); gSys.setLayout(new GridLayout()); Messages.setLanguageText(gSys, "MainWindow.about.section.system"); //$NON-NLS-1$ gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gridData.verticalSpan = 1; gSys.setLayoutData(gridData); Text txtSysInfo = new Text(gSys, SWT.READ_ONLY | SWT.MULTI | SWT.WRAP); txtSysInfo.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); txtSysInfo.setText("Java " + System.getProperty("java.version") + "\n " + System.getProperty("java.vendor") + "\n" + "SWT v" + SWT.getVersion() + ", " + SWT.getPlatform() + "\n" + System.getProperty("os.name") + " v" + System.getProperty("os.version") + ", " + System.getProperty("os.arch") + "\n" + Constants.APP_NAME.charAt(0) + Constants.AZUREUS_VERSION + "/" + CorePatchLevel.getCurrentPatchLevel() + " " + COConfigurationManager.getStringParameter("ui")); txtSysInfo.setLayoutData(gridData = new GridData(GridData.FILL_BOTH)); if (window.getCaret() != null) window.getCaret().setVisible(false); final String[][] link = { { "homepage", "sourceforge", "sourceforgedownloads", "bugreports", "forumdiscussion", "wiki" }, { "http://www.vuze.com", "http://azureus.sourceforge.net", "http://sourceforge.net/project/showfiles.php?group_id=84122", "http://forum.vuze.com/category.jspa?categoryID=3", "http://forum.vuze.com", Constants.AZUREUS_WIKI } }; for (int i = 0; i < link[0].length; i++) { final CLabel linkLabel = new CLabel(gInternet, SWT.NULL); linkLabel.setText(MessageText.getString("MainWindow.about.internet." + link[0][i])); linkLabel.setData(link[1][i]); linkLabel.setCursor(Cursors.handCursor); linkLabel.setForeground(Colors.blue); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 1; linkLabel.setLayoutData(gridData); linkLabel.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { Utils.launch((String) ((CLabel) arg0.widget).getData()); } public void mouseDown(MouseEvent arg0) { Utils.launch((String) ((CLabel) arg0.widget).getData()); } }); } Listener keyListener = new Listener() { public void handleEvent(Event e) { if(e.character == SWT.ESC) { window.dispose(); } } }; window.addListener(SWT.KeyUp,keyListener); window.pack(); txtSysInfo.setFocus(); Utils.centreWindow(window); window.open(); instance = window; window.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent event) { instance = null; disposeImage(); } }); AEThread2 updater = new AEThread2("Splash Screen Updater", true) { public void run() { if(image == null || image.isDisposed()) return; final int maxX = image.getBounds().width; final int maxY = image.getBounds().height; while(paintColorTo < maxX) { if(image == null || image.isDisposed()) { paintColorTo = maxX; break; } if(display.isDisposed()) { paintColorTo = maxX; break; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if(labelImage.isDisposed()) return; paintColorTo++; labelImage.redraw(paintColorTo - 1, 0, 2, maxY, true); } }); try { Thread.sleep(30); }catch(Exception e) { Debug.printStackTrace( e ); } } }}; updater.start(); } public static void disposeImage() { try{ class_mon.enter(); if(image != null && ! image.isDisposed()) image.dispose(); image = null; if(imgSrc != null && ! imgSrc.isDisposed()) imgSrc.dispose(); imgSrc = null; }finally{ class_mon.exit(); } } public static void main(String[] args) { try { new Display(); Colors.getInstance(); SWTThread.createInstance(null); show(); } catch (SWTThreadAlreadyInstanciatedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/help/HealthHelpWindow.java0000644000175000017500000000660311127403350024411 0ustar adrianadrian/* * File : HealthHelpWindow.java * Created : 18 déc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.help; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author Olivier * */ public class HealthHelpWindow { public static void show(Display display) { final ArrayList imagesToRelease = new ArrayList(); final Shell window = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell( display, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); Utils.setShellIcon(window); window.setText(MessageText.getString("MyTorrentsView.menu.health")); Map mapIDs = new LinkedHashMap(); mapIDs.put("grey", "st_stopped"); mapIDs.put("red", "st_ko"); mapIDs.put("blue", "st_no_tracker"); mapIDs.put("yellow", "st_no_remote"); mapIDs.put("green", "st_ok"); mapIDs.put("error", "st_error"); mapIDs.put("share", "st_shared"); GridLayout layout = new GridLayout(); layout.marginHeight = 3; layout.marginWidth = 3; try { layout.verticalSpacing = 3; } catch (NoSuchFieldError e) { /* Ignore for Pre 3.0 SWT.. */ } window.setLayout(layout); ImageLoader imageLoader = ImageLoader.getInstance(); for (Iterator iter = mapIDs.keySet().iterator(); iter.hasNext();) { String key = (String) iter.next(); String value = (String) mapIDs.get(key); Image img = imageLoader.getImage(value); imagesToRelease.add(value); CLabel lbl = new CLabel(window, SWT.NONE); lbl.setImage(img); lbl.setText(MessageText.getString("health.explain." + key)); } // buttons Button btnOk = new Button(window, SWT.PUSH); btnOk.setText(MessageText.getString("Button.ok")); GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); gridData.widthHint = 70; btnOk.setLayoutData(gridData); btnOk.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { window.dispose(); } }); window.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { window.dispose(); } } }); window.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent arg0) { ImageLoader imageLoader = ImageLoader.getInstance(); for (String id : imagesToRelease) { imageLoader.releaseImage(id); } } }); window.pack(); window.open(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/0000755000175000017500000000000011310377636021262 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/IProgressReporterListener.java0000644000175000017500000000723410715213334027271 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.progress; /** * A simple listener interface used to pass a ProgressReport to a listener from a ProgressReporter * @author knguyen * */ public interface IProgressReporterListener extends IProgressReportConstants { /** * When an event is detected this callback method will be called so listeners can take appropriate action such as updating a UI element *

    * Currently there are 2 return types recognized: *

      *
    • RETVAL_OK - Indicates the given ProgressReport has been consumed successfully
    • *
    • RETVAL_OK_TO_DISPOSE - Indicates that this listener is no longer interested in any subsequent reports
    • *
    *

    * * The return value of RETVAL_OK_TO_DISPOSE is a hint to the caller that it is now * safe to remove this listener from the caller's list of listeners. This pattern allows the caller * to perform clean up operations associated with this listener, and allows the listener to initiate * its own removal from within an event loop. * *

    A typical life cycle of an event listener is create listener, register listener, then remove listener. * To accomplish all three steps we would need a reference to the listeners at all time as can be seen in this sample:

    * * *
    	 * ProgressReporter reporter = new ProgressReporter("I'm a reporter");
    	 * 
    	 * // Create a concrete listener since we need to remove it later for clean up
    	 * IProgressReporterListener listener = new IProgressReporterListener() {
    	 * 	public int report(ProgressReport progressReport) {
    	 * 		// Do some work here
    	 * 		return RETVAL_OK;
    	 * 	}
    	 * };
    	 * 
    	 * // Add the listener
    	 * reporter.addListener(listener);
    	 * 
    	 * // Do some more work
    	 * 
    	 * // Then for clean up remove the listener
    	 * if ([some condition] == true) {
    	 * 	reporter.removeListener(listener);
    	 * }
    	 * 
    	 * 
    * * * Sometime it is more convenient to remove a listener from within the call to .report() but a direct * attempt at removal of this listener may result in modification conflict since most likely this method is being * called from within an iterator loop which does not allow concurrent modifications. * * To address this limitation we make use of the RETVAL_OK_TO_DISPOSE as a return code which will * allow the caller to perform the clean up as in this modification of the example above: * *
    	 * ...
    	 * 
    	 * final IProgressReporterListener listener = new IProgressReporterListener() {
    	 * 	public int report(ProgressReport progressReport) {
    	 * 
    	 * 		// Do some work here
    	 * 
    	 * 		// This would throw a ConcurrentModificationException
    	 *		reporter.removeListener(listener); 
    	 * 
    	 * 		// This would work
    	 * 		if ([some condition] == true) {
    	 * 			return RETVAL_OK_TO_DISPOSE;
    	 * 		}
    	 * 
    	 * 		return RETVAL_OK;
    	 * 	}
    	 * };
    	 * 
    * *

    If the decision to remove a listener is based on the information contained in the given ProgressReport * we can implement a much simpler listener as an inner class like so:

    *
    	 * 
    	 * ProgressReporter reporter = new ProgressReporter("I'm a reporter");
    	 * 
    	 * // Creates an anonymous inner class using RETVAL_OK_TO_DISPOSE to initiate clean up  
    	 * reporter.addListener(new IProgressReporterListener() {
    	 * 	public int report(ProgressReport progressReport) {
    	 * 
    	 * 		// Do some work
    	 * 
    	 * 		if ([some condition] == true) {
    	 * 			return RETVAL_OK_TO_DISPOSE;
    	 * 		}
    	 * 		return RETVAL_OK;
    	 * 
    	 * 	}}
    	 * );
    	 * 
    	 * 
    	 * 
    * * @param progressReport * @return */ public int report(IProgressReport progressReport); }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/IProgressReportConstants.java0000644000175000017500000001036010726415556027137 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.progress; /** * These are all the constants used by the ProgressReporter and related classes *

    * These constants are in this separate interface so that classes that need to reference these * constants can simply implement this interface and reference them directly like REPORT_TYPE_CANCEL == [some test] * instead of having to fully reference them like IProgressReportConstants.REPORT_TYPE_CANCEL == [some test]

    * @author knguyen * */ public interface IProgressReportConstants { /** * Unless specified by the user for a particular reporter all reporters have this default type */ public static final String REPORTER_TYPE_DEFAULT = "default.reporter.type"; /** * The default visibility for a ProgressReporter; this is the most generous * visibility level in that any interested processes can see this reporter and receive it's ProgressReporter.ProgressReport * This is used for when it makes sense to show the full information about a reporter to the user; this reporter will * be seen in the progress history */ public static final int REPORTER_VISIBILITY_USER = 1; /** * A hint to the ProgressReportingManager and any interested parties that the * reporter and its reports are not intended to be shown (in full) to the user. UI components * displaying progress reporters and reports can use this hint to show a minimum set of values and additionally * skip soliciting the user for any loopback events. */ public static final int REPORTER_VISIBILITY_SYSTEM = 2; //======= report types ============= /** * Default event type indicating no event */ public static final int REPORT_TYPE_INIT = 0; /** * When {@link ProgressReporter#cancel()} is detected */ public static final int REPORT_TYPE_CANCEL = 1; /** * When {@link ProgressReporter#setDone()} is detected */ public static final int REPORT_TYPE_DONE = 2; /** * When {@link ProgressReporter#setIndeterminate(boolean)} is detected */ public static final int REPORT_TYPE_MODE_CHANGE = 3; /** * When {@link ProgressReporter#setErrorMessage(String)} is detected */ public static final int REPORT_TYPE_ERROR = 4; /** * When {@link ProgressReporter#retry()} is detected */ public static final int REPORT_TYPE_RETRY = 5; /** * When any other property is modified */ public static final int REPORT_TYPE_PROPERTY_CHANGED = 6; /** * When {@link ProgressReporter#dispose()} is called */ public static final int REPORT_TYPE_DISPOSED = 7; //========== return values for report listeners ====== /** * Default return value from a listener indicating the event has been received and processed successfully */ public static final int RETVAL_OK = 0; /** * A return value from a listener indicating that the listener is done and is no longer interested * in any subsequent event; this is a hint to the notifier so that the notifier can perform clean up * operation relating to that particular listener */ public static final int RETVAL_OK_TO_DISPOSE = 1; //============ events from the ProgressReportingManager ==== /** * When a reporter is added to the history list */ public static final int MANAGER_EVENT_ADDED = 1; /** * When a reporter is removed from the history list */ public static final int MANAGER_EVENT_REMOVED = 2; /** * When a reporter that is already in the history list report an event */ public static final int MANAGER_EVENT_UPDATED = 3; //======== style bits for UI components================= /** * Default style bit for no styles */ public static final int NONE = 0; /** * Automatically closes the window when the reporter is finished; * this only takes effect when there is only 1 reporter in the window */ public static final int AUTO_CLOSE = 1 << 1; /** * Open the window as MODAL */ public static final int MODAL = 1 << 2; /** * The reporter is the only one in a window */ public static final int STANDALONE = 1 << 3; public static final int BORDER = 1 << 4; public static final int SHOW_TOOLBAR = 1 << 5; //========== report message types ================= public static final int MSG_TYPE_INFO = 1 << 1; public static final int MSG_TYPE_ERROR = 1 << 2; public static final int MSG_TYPE_LOG = 1 << 3; }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/ProgressReportingManager.java0000644000175000017500000002073210726415556027126 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.progress; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.mainwindow.MainStatusBar; import com.aelitis.azureus.core.util.CopyOnWriteList; /** * A manager that aggregates and forward progress information for long running operations *

    This is a non-intrusive implementation, such that, it does not directly manage any of the process; it simply receives and forwards information

    *

    The primary user of this class is the {@link MainStatusBar} where it is used to display progress information

    * @author knguyen * */ public class ProgressReportingManager implements IProgressReportConstants { private static ProgressReportingManager INSTANCE = null; /** * A custom stack to keep track of ProgressReporter */ private ProgressReporterStack progressReporters = new ProgressReporterStack(); /** * Keeps count of all ProgressReporter created since this session started; * is used as unique ID and hashCode for each instance of ProgressReporter * */ private int reporterCounter = Integer.MIN_VALUE; public static final int COUNT_ALL = 0; public static final int COUNT_ACTIVE = 1; public static final int COUNT_ERROR = 2; /** * A CopyOnWriteList of IProgressReportingListener */ private CopyOnWriteList listeners = new CopyOnWriteList(); /** * Convenience variable tied to the parameter "auto_remove_inactive_items" */ private boolean isAutoRemove = false; /** * Private constructor */ private ProgressReportingManager() { /* * Set up isAutoRemove flag */ isAutoRemove = COConfigurationManager.getBooleanParameter("auto_remove_inactive_items"); COConfigurationManager.addParameterListener("auto_remove_inactive_items", new ParameterListener() { public void parameterChanged(String parameterName) { isAutoRemove = COConfigurationManager.getBooleanParameter("auto_remove_inactive_items"); } }); } public static final synchronized ProgressReportingManager getInstance() { if (null == INSTANCE) { INSTANCE = new ProgressReportingManager(); } return INSTANCE; } public IProgressReporter addReporter() { return( new ProgressReporter( this )); } public IProgressReporter addReporter( String name ) { return( new ProgressReporter( this, name )); } /** * Returns the number of reporters that have sent any event to this manager and have not been removed *
      *
    • COUNT_ERROR - count all reporters in error state
    • *
    • COUNT_ACTIVE - count all reporters that are still active
    • *
    • COUNT_ALL - count all reporters
    • *
    * @param whatToCount one of the above constants; will default to COUNT_ALL if the parameter is unrecognized * @return */ public int getReporterCount(int whatToCount) { if (whatToCount == COUNT_ERROR) { return progressReporters.getErrorCount(); } if (whatToCount == COUNT_ACTIVE) { return progressReporters.getActiveCount(); } return progressReporters.size(); } /** * A convenience method for quickly determining whether more than one reporter is still active. * This method can be much quicker than calling {@link #getReporterCount()} and inspecting the returned value * if the number of reporters is high since we may not have to go through the entire list before getting the result * * @return true if there are at least 2 active reporters; false otherwise */ public boolean hasMultipleActive() { return progressReporters.hasMultipleActive(); } /** * Returns the next active reporter * @return the next reporter that is still active; null if none are active or no reporters are found */ public IProgressReporter getNextActiveReporter() { return progressReporters.getNextActiveReporter(); } /** * Returns the current reporter, in other word, the last reporter to have reported anything * @return the last reporter; null if none are found */ public IProgressReporter getCurrentReporter() { return progressReporters.peek(); } /** * Returns a modifiable list of ProgressReporters; manipulating this list has no * effect on the internal list of reporters maintained by this manager * * @param onlyActive true to filter the list to only include those reporters that are still active * @return a sorted List of ProgressReporter where the oldest reporter would be at position 0 */ public List getReporters(boolean onlyActive) { List reporters = progressReporters.getReporters(onlyActive); Collections.sort(reporters); return reporters; } /** * * Returns a modifiable array of ProgressReporters; manipulating this array has no * effect on the internal list of reporters maintained by this manager * @param onlyActive true to filter the array to only include those reporters that are still active * @return a sorted array of ProgressReporter where the oldest reporter would be at position 0 */ public IProgressReporter[] getReportersArray(boolean onlyActive) { List rpList = progressReporters.getReporters(onlyActive); IProgressReporter[] array = (IProgressReporter[]) rpList.toArray(new IProgressReporter[rpList.size()]); Arrays.sort(array); return array; } /** * Removes the given ProgressReporter from this manager. This has the effect that * any subsequent event reported by the same reporter will not be captured nor forwarded by this manager * @param reporter * @return */ public boolean remove(IProgressReporter reporter) { boolean value = progressReporters.remove(reporter); notifyListeners(MANAGER_EVENT_REMOVED, reporter); return value; } /** * * @param listener */ public void addListener(IProgressReportingListener listener) { if (null != listener && false == listeners.contains(listener)) { listeners.add(listener); } } /** * * @param listener */ public void removeListener(IProgressReportingListener listener) { if (null != listener && true == listeners.contains(listener)) { listeners.remove(listener); } } /** * Notifies listeners that the given ProgressReporter has been modified * @param eventType * @param reporter */ private void notifyListeners(int eventType, IProgressReporter reporter) { for (Iterator iterator = listeners.iterator(); iterator.hasNext();) { IProgressReportingListener listener = (IProgressReportingListener) iterator.next(); if (null != listener) { try { listener.reporting(eventType, reporter); } catch (Throwable e) { Debug.out(e); } } } } /** * Push this reporter on top of the stack, and notifies any listeners that a state change has occurred * @param reporter */ protected void notifyManager(IProgressReporter reporter) { /* * Update the history stack and notify listeners */ IProgressReport pReport = reporter.getProgressReport(); if ((true == isAutoRemove && false == pReport.isActive()) || true == pReport.isDisposed()) { progressReporters.remove(reporter); notifyListeners(MANAGER_EVENT_REMOVED, reporter); } else if (true == progressReporters.contains(reporter)) { progressReporters.push(reporter); notifyListeners(MANAGER_EVENT_UPDATED, reporter); } else { progressReporters.push(reporter); notifyListeners(MANAGER_EVENT_ADDED, reporter); } } /** * Returns the next available ID that can be assigned to a {@link ProgressReporter} * @return int the next available ID */ protected synchronized final int getNextAvailableID() { /* * This is a simple brute forced way to generate unique ID's which can also be use as a unique hashcode * without having to directly track all previously created/disposed ProgressReporters * * This is synchronized to ensure that the incrementing of reporterCounter is consistent * so that each ProgressReporter is guaranteed to have a unique ID (which is also used as its hashCode) * * WARNING: This method is mainly intended to be used by the constructors of ProgressReporter and should not be called * from anywhere else (unless you really know what you're doing); unintended repeated call to this method can exhaust * the limit of the integer. This counter starts from Integer.MIN_VALUE */ return reporterCounter++; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/IProgressReportingListener.java0000644000175000017500000000103410714736016027436 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.progress; /** * A simple listener that can be registered with the ProgressReportingManager to receive notification * when any ProgressReporter has a status change * @author knguyen * */ public interface IProgressReportingListener extends IProgressReportConstants { /** * Notify that some event has happened * @param eventType * @param reporter The ProgressReporter that reported the change; * @return */ public int reporting(int eventType, IProgressReporter reporter); }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/ProgressReportMessage.java0000644000175000017500000000227411023414172026423 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.progress; /** * A simple class for a message * @author knguyen * */ public class ProgressReportMessage implements IMessage, IProgressReportConstants { private String value = ""; private int type; /** * Create a message for the given value and type; message type can by any one of: *
      *
    • IProgressReportConstants.MSG_TYPE_ERROR -- an error message
    • *
    • IProgressReportConstants.MSG_TYPE_INFO -- a general informational message
    • *
    • IProgressReportConstants.MSG_TYPE_LOG -- a log message; for messages that are more detailed and verbose
    • *
    * @param value * @param type */ public ProgressReportMessage(String value, int type) { this.value = value; switch (type) { case MSG_TYPE_ERROR: case MSG_TYPE_INFO: this.type = type; break; default: this.type = MSG_TYPE_LOG; } } public String getValue() { return value; } public int getType() { return type; } public boolean isError() { return type == MSG_TYPE_ERROR; } public boolean isInfo() { return type == MSG_TYPE_INFO; } public boolean isLog() { return type == MSG_TYPE_LOG; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/IProgressReport.java0000644000175000017500000000553510717253314025242 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.progress; import org.eclipse.swt.graphics.Image; /** * The interface for a progress report; a progress report is a read only object containing * all the properties of an IProgressReporter at a moment in time * @author knguyen * */ public interface IProgressReport { /** * Returns the reporter type of the reporter that created this report * @return */ public String getReporterType(); /** * Returns the id of the reporter that created this report * @return */ public int getReporterID(); /** * Returns the minimum amount of work to be done * @return */ public int getMinimum(); /** * Returns the maximum amount of work to be done * @return */ public int getMaximum(); /** * Returns the amount of work done so far * @return */ public int getSelection(); /** * Returns the percentage of work done so far * @return */ public int getPercentage(); /** * Returns whether the reporter is still in active state * @return */ public boolean isActive(); /** * Returns whether the amount of work done so far can not be calculated accurately * @return */ public boolean isIndeterminate(); /** * Returns whether the reporter is done with all its work * @return */ public boolean isDone(); /** * Returns whether the amount of work done is in percentage form * @return */ public boolean isPercentageInUse(); /** * Returns whether the process owning the reporter allows a cancel request * @return */ public boolean isCancelAllowed(); /** * Returns whether the reporter has been canceled * @return */ public boolean isCanceled(); /** * Returns whether the process owning the reporter allows a retry request * @return */ public boolean isRetryAllowed(); /** * Returns whether the reporter has reported an error * @return */ public boolean isInErrorState(); /** * Returns whether the reporter has been marked for disposal * @return */ public boolean isDisposed(); /** * Returns the title of the reporter; this is mainly used as a window title if the reporter is shown by itself in a window * @return */ public String getTitle(); /** * Returns the message for this particular report * @return */ public String getMessage(); /** * Returns the detail message for this particular report * @return */ public String getDetailMessage(); /** * Returns the error message (if any) for this report * @return */ public String getErrorMessage(); /** * Returns the name of the reporter * @return */ public String getName(); /** * Returns the image of the reporter * @return */ public Image getImage(); /** * Returns the object associated with this report * @return */ public Object getObjectData(); /** * Returns the type of report this is * @return */ public int getReportType(); }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/ProgressWindow.java0000644000175000017500000001770211127403352025117 0ustar adrianadrian/* * Created on 27 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.progress; import java.io.InputStream; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DelayedEvent; import org.gudy.azureus2.ui.swt.ImageRepository; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreOperation; import com.aelitis.azureus.core.AzureusCoreOperationListener; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; public class ProgressWindow { public static void register( AzureusCore core ) { core.addOperationListener( new AzureusCoreOperationListener() { public boolean operationCreated( AzureusCoreOperation operation ) { if ( ( operation.getOperationType() == AzureusCoreOperation.OP_FILE_MOVE || operation.getOperationType() == AzureusCoreOperation.OP_PROGRESS )&& Utils.isThisThreadSWT()){ if ( operation.getTask() != null ){ new ProgressWindow( operation ); return( true ); } } return( false ); } }); } private volatile Shell shell; private volatile boolean task_complete; private final String resource; private Image[] spinImages; protected int curSpinIndex = 0; protected ProgressWindow( final AzureusCoreOperation operation ) { final RuntimeException[] error = {null}; resource = operation.getOperationType()==AzureusCoreOperation.OP_FILE_MOVE?"progress.window.msg.filemove":"progress.window.msg.progress"; new DelayedEvent( "ProgWin", operation.getOperationType()==AzureusCoreOperation.OP_FILE_MOVE?1000:10, new AERunnable() { public void runSupport() { if ( !task_complete ){ Utils.execSWTThread( new Runnable() { public void run() { synchronized( ProgressWindow.this ){ if ( !task_complete ){ Shell shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createMainShell( ( SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL )); showDialog( shell ); } } } }, false ); } } }); new AEThread2( "ProgressWindow", true ) { public void run() { try{ // Thread.sleep(10000); operation.getTask().run( operation ); }catch( RuntimeException e ){ error[0] = e; }catch( Throwable e ){ error[0] = new RuntimeException( e ); }finally{ Utils.execSWTThread( new Runnable() { public void run() { destroy(); } }); } } }.start(); try{ final Display display = SWTThread.getInstance().getDisplay(); while( !( task_complete || display.isDisposed())){ if (!display.readAndDispatch()) display.sleep(); } }finally{ // bit of boiler plate in case something fails in the dispatch loop synchronized( ProgressWindow.this ){ task_complete = true; } try{ if ( shell != null && !shell.isDisposed()){ shell.dispose(); } }catch( Throwable e ){ Debug.printStackTrace(e); } } if ( error[0] != null ){ throw( error[0] ); } } public ProgressWindow( Shell _parent, String _resource, int _style, int _delay_millis ) { resource = _resource; final Shell shell = new Shell( _parent, _style ); if ( _delay_millis <= 0 ){ showDialog( shell ); }else{ new DelayedEvent( "ProgWin", _delay_millis, new AERunnable() { public void runSupport() { if ( !task_complete ){ Utils.execSWTThread( new Runnable() { public void run() { synchronized( ProgressWindow.this ){ if ( !task_complete ){ showDialog( shell ); } } } }, false ); } } }); } } protected void showDialog( Shell _shell ) { shell = _shell; shell.setText( MessageText.getString( "progress.window.title" )); Utils.setShellIcon(shell); shell.addListener( SWT.Close, new Listener() { public void handleEvent( org.eclipse.swt.widgets.Event event) { event.doit = false; } }); GridLayout layout = new GridLayout(); layout.numColumns = 2; shell.setLayout(layout); spinImages = ImageLoader.getInstance().getImages("working"); if ( spinImages.length == 0 || spinImages == null ){ new Label( shell, SWT.NULL ); }else{ final Rectangle spinBounds = spinImages[0].getBounds(); final Canvas canvas = new Canvas( shell, SWT.NULL ) { public Point computeSize(int wHint, int hHint,boolean changed ) { return( new Point(spinBounds.width, spinBounds.height)); } }; canvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { e.gc.drawImage(spinImages[curSpinIndex ], 0, 0); } }); Utils.execSWTThreadLater(100, new AERunnable() { public void runSupport() { if (canvas == null || canvas.isDisposed()) { return; } canvas.redraw(); canvas.update(); if (curSpinIndex == spinImages.length - 1) { curSpinIndex = 0; } else { curSpinIndex++; } Utils.execSWTThreadLater(100, this); } }); } Label label = new Label(shell, SWT.NONE); label.setText(MessageText.getString( resource )); GridData gridData = new GridData(); label.setLayoutData(gridData); shell.pack(); Composite parent = shell.getParent(); if ( parent != null ){ Utils.centerWindowRelativeTo( shell, parent ); }else{ Utils.centreWindow( shell ); } shell.open(); } public void destroy() { synchronized( ProgressWindow.this ){ task_complete = true; } try{ if ( shell != null && !shell.isDisposed()){ shell.dispose(); } }catch( Throwable e ){ Debug.printStackTrace(e); } if (spinImages != null) { ImageLoader.getInstance().releaseImage("working"); spinImages = null; } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/ProgressReporterStack.java0000644000175000017500000001342110723714476026447 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.progress; import java.util.*; /** * A convenience Stack for tracking ProgressReporters *

    When a reporter is pushed onto the stack we remove any other occurrences of the same reporter so * that there is at most one instance of a particular reporter in the stack at any time

    * * @author knguyen * */ class ProgressReporterStack { private Stack reporterStack = new Stack(); /** * A dummy object used purely for implementing synchronized blocks */ private Object lockObject = new Object(); /** * Pushes the given reporter on top of the stack; additionally remove any other occurrence of the reporter. * @param reporter */ public void push(IProgressReporter reporter) { if (null == reporter) { return; } synchronized (lockObject) { /* * Remove the reporter from the stack if it's in there already */ if (true == reporterStack.contains(reporter)) { reporterStack.remove(reporter); } reporterStack.push(reporter); } } /** * Returns the reporter at the top of the stack * @return */ public IProgressReporter peek() { synchronized (lockObject) { if (false == reporterStack.isEmpty()) { return (IProgressReporter) reporterStack.peek(); } return null; } } /** * Remove the given ProgressReporter; * @return true if the given reporter is found; otherwise false */ public boolean remove(IProgressReporter reporter) { synchronized (lockObject) { if (null != reporter && true == reporterStack.contains(reporter)) { return reporterStack.remove(reporter); } return false; } } /** * Returns whether or not the given IProgressReporter is already in the stack * @param reporter * @return */ public boolean contains(IProgressReporter reporter) { synchronized (lockObject) { return reporterStack.contains(reporter); } } /** * Remove and return the reporter at the top of the stack * @return */ public IProgressReporter pop() { synchronized (lockObject) { if (false == reporterStack.isEmpty()) { return (IProgressReporter) reporterStack.pop(); } return null; } } /** * Trim the list by removing all inactive reporters */ public void trim() { synchronized (lockObject) { for (Iterator iterator = reporterStack.iterator(); iterator.hasNext();) { IProgressReporter reporter = ((IProgressReporter) iterator.next()); if (false == reporter.getProgressReport().isActive()) { iterator.remove(); } } } } /** * Returns a list of reporters; this list can safely be manipulated because it is not directly referencing the internal list * @param onlyActive true to return only reporters that are still active, false to return all reporters * @return List */ public List getReporters(boolean onlyActive) { synchronized (lockObject) { List reporters = new ArrayList(); for (Iterator iterator = reporterStack.iterator(); iterator.hasNext();) { IProgressReporter reporter = ((IProgressReporter) iterator.next()); if (true == onlyActive) { if (true == reporter.getProgressReport().isActive()) { reporters.add(reporter); } } else { reporters.add(reporter); } } return reporters; } } public int size() { synchronized (lockObject) { return reporterStack.size(); } } /** * Returns the number of reporters in the stack that are still active * @return */ public int getActiveCount() { synchronized (lockObject) { int activeReporters = 0; for (Iterator iterator = reporterStack.iterator(); iterator.hasNext();) { IProgressReporter reporter = ((IProgressReporter) iterator.next()); if (true == reporter.getProgressReport().isActive()) { activeReporters++; } } return activeReporters; } } /** * Returns the number of reporters in the stack that are in error state * @return */ public int getErrorCount() { synchronized (lockObject) { int reportersInErrorState = 0; for (Iterator iterator = reporterStack.iterator(); iterator.hasNext();) { IProgressReporter reporter = ((IProgressReporter) iterator.next()); if (true == reporter.getProgressReport().isInErrorState()) { reportersInErrorState++; } } return reportersInErrorState; } } /** * A convenience method for quickly determining whether more than one reporter is still active. * This method can be much quicker than calling {@link #getActiveCount()} and inspecting the returned value * if the number of reporters is high since we may not have to go through the entire list before getting the result * @return true if there are at least 2 active reporters; false otherwise */ public boolean hasMultipleActive() { synchronized (lockObject) { int activeReporters = 0; for (Iterator iterator = reporterStack.iterator(); iterator.hasNext();) { IProgressReporter reporter = (IProgressReporter) iterator.next(); if (true == reporter.getProgressReport().isActive()) { activeReporters++; } if (activeReporters > 1) { return true; } } } return false; } /** * Get the next active reporter. *

    NOTE: this is different from calling {@link #peek()} since the next active reporter may not be at the top of the stack

    * @return ProgressReporter the next reporter on the stack that is still active; null if none are active or none are found */ public IProgressReporter getNextActiveReporter() { synchronized (lockObject) { for (Iterator iterator = reporterStack.iterator(); iterator.hasNext();) { IProgressReporter reporter = (IProgressReporter) iterator.next(); if (true == reporter.getProgressReport().isActive()) { return reporter; } } } return null; } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/IMessage.java0000644000175000017500000000017710717253112023617 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.progress; public interface IMessage { public String getValue(); public int getType(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/ProgressReporterWindow.java0000644000175000017500000004336310777057274026666 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.progress; import java.util.ArrayList; import java.util.Arrays; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.ITwistieListener; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; public class ProgressReporterWindow implements IProgressReportConstants, ITwistieListener, DisposeListener { private Shell shell; private ScrolledComposite scrollable; private Composite scrollChild; private IProgressReporter[] pReporters; /** * A registry to keep track of all reporters that are being displayed in all instances * of this window. * @see #isOpened(IProgressReporter) */ private static final ArrayList reportersRegistry = new ArrayList(); /** * A special boolean to track whether this window is opened and is showing the empty panel; * mainly used to prevent opening more than one of these window when there are no reporters to work with */ private static boolean isShowingEmpty = false; /** * The default width for the shell upon first opening */ private int defaultShellWidth = 500; /** * The maximum number of panels to show when the window first open */ private int initialMaxNumberOfPanels = 3; /** * The style bits to use for this panel */ private int style; /** * Convenience variable tied to the parameter "auto_remove_inactive_items" */ private boolean isAutoRemove = false; /** * Construct a ProgressReporterWindow for a single ProgressReporter * @param pReporter */ private ProgressReporterWindow(IProgressReporter pReporter, int style) { this.style = style; if (null != pReporter) { pReporters = new IProgressReporter[] { pReporter }; } else { pReporters = new IProgressReporter[0]; } createControls(); } /** * Construct a single ProgressReporterWindow showing all ProgressReporter's in the given array * @param pReporters */ private ProgressReporterWindow(IProgressReporter[] pReporters, int style) { this.style = style; if (null != pReporters) { this.pReporters = pReporters; } else { pReporters = new IProgressReporter[0]; } createControls(); } /** * Opens the window and display the given IProgressReporter * style could be one or more of these: *
      *
    • IProgressReportConstants.NONE -- the default
    • *
    • IProgressReportConstants.AUTO_CLOSE -- automatically disposes this panel when the given reporter is done
    • *
    • IProgressReportConstants.MODAL -- this window will be application modal
    • *
    • IProgressReportConstants.SHOW_TOOLBAR -- shows the toolbar for removing inactive reporters
    • *
    * @param pReporter * @param style */ public static void open(IProgressReporter pReporter, int style) { new ProgressReporterWindow(pReporter, style).openWindow(); } /** * Opens the window and display the given array of IProgressReporter's * style could be one or more of these: *
      *
    • IProgressReportConstants.NONE -- the default
    • *
    • IProgressReportConstants.AUTO_CLOSE -- automatically disposes this panel when the given reporter is done
    • *
    • IProgressReportConstants.MODAL -- this window will be application modal
    • *
    • IProgressReportConstants.SHOW_TOOLBAR -- shows the toolbar for removing inactive reporters
    • *
    * @param pReporters * @param style */ public static void open(IProgressReporter[] pReporters, int style) { new ProgressReporterWindow(pReporters, style).openWindow(); } /** * Returns whether this window is already opened and is showing the empty panel * @return */ public static boolean isShowingEmpty() { return isShowingEmpty; } /** * Returns whether the given IProgressReporter is opened in any instance of this window; * processes can query this method before opening another window to prevent opening multiple * windows for the same reporter. This is implemented explicitly instead of having the window automatically * recycle instances because there are times when it is desirable to open a reporter in more than one * instances of this window. * @param pReporter * @return */ public static boolean isOpened(IProgressReporter pReporter) { return reportersRegistry.contains(pReporter); } private void createControls() { /* * Sets up the shell */ int shellStyle = SWT.DIALOG_TRIM | SWT.RESIZE; if ((style & MODAL) != 0) { shellStyle |= SWT.APPLICATION_MODAL; } shell = ShellFactory.createMainShell(shellStyle); shell.setText(MessageText.getString("progress.window.title")); Utils.setShellIcon(shell); GridLayout gLayout = new GridLayout(); gLayout.marginHeight = 0; gLayout.marginWidth = 0; shell.setLayout(gLayout); /* * Using ScrolledComposite with only vertical scroll */ scrollable = new ScrolledComposite(shell, SWT.V_SCROLL); scrollable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); /* * Main content composite where panels will be created */ scrollChild = new Composite(scrollable, SWT.NONE); GridLayout gLayoutChild = new GridLayout(); gLayoutChild.marginHeight = 0; gLayoutChild.marginWidth = 0; gLayoutChild.verticalSpacing = 0; scrollChild.setLayout(gLayoutChild); scrollable.setContent(scrollChild); scrollable.setExpandVertical(true); scrollable.setExpandHorizontal(true); /* * Re-adjust scrollbar setting when the window resizes */ scrollable.addControlListener(new ControlAdapter() { public void controlResized(ControlEvent e) { Rectangle r = scrollable.getClientArea(); scrollable.setMinSize(scrollChild.computeSize(r.width, SWT.DEFAULT)); } }); /* * On closing remove all reporters that was handled by this instance of the window from the registry */ shell.addListener(SWT.Close, new Listener() { public void handleEvent(Event event) { /* * Remove this class as a listener to the disposal event for the panels or else * as the shell is closing the panels would be disposed one-by-one and each one would * force a re-layouting of the shell. */ Control[] controls = scrollChild.getChildren(); for (int i = 0; i < controls.length; i++) { if (controls[i] instanceof ProgressReporterPanel) { ((ProgressReporterPanel) controls[i]).removeDisposeListener(ProgressReporterWindow.this); } } /* * Removes all the reporters that is still handled by this window */ for (int i = 0; i < pReporters.length; i++) { reportersRegistry.remove(pReporters[i]); } isShowingEmpty = false; } }); if (pReporters.length == 0) { createEmptyPanel(); } else { createPanels(); } /* * Shows the toolbar if specified */ if ((style & SHOW_TOOLBAR) != 0) { createToolbar(); } isAutoRemove = COConfigurationManager.getBooleanParameter("auto_remove_inactive_items"); } /** * Creates a the toolbar at the bottom of the window */ private void createToolbar() { Composite toolbarPanel = new Composite(shell, SWT.NONE); toolbarPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); GridLayout gLayout = new GridLayout(3, false); gLayout.marginWidth = 25; gLayout.marginTop = 0; gLayout.marginBottom = 0; toolbarPanel.setLayout(gLayout); final Button autoClearButton = new Button(toolbarPanel, SWT.CHECK); autoClearButton.setText(MessageText.getString("Progress.reporting.window.remove.auto")); autoClearButton.setToolTipText(MessageText.getString("Progress.reporting.window.remove.auto.tooltip")); autoClearButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); autoClearButton.setSelection(COConfigurationManager.getBooleanParameter("auto_remove_inactive_items")); Label dummy = new Label(toolbarPanel, SWT.NONE); dummy.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); final Button clearInActiveButton = new Button(toolbarPanel, SWT.NONE); clearInActiveButton.setText(MessageText.getString("Progress.reporting.window.remove.now")); clearInActiveButton.setToolTipText(MessageText.getString("Progress.reporting.window.remove.now.tooltip")); clearInActiveButton.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false)); clearInActiveButton.setEnabled(!COConfigurationManager.getBooleanParameter("auto_remove_inactive_items")); /* * Toggles the checked state of auto remove */ autoClearButton.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { COConfigurationManager.setParameter("auto_remove_inactive_items", autoClearButton.getSelection()); /* * Disable clearInActiveButton if auto remove is checked */ clearInActiveButton.setEnabled(!autoClearButton.getSelection()); isAutoRemove = autoClearButton.getSelection(); /* * Removes any inactive panels that may already be in the window if this option is set to true */ if (true == isAutoRemove) { removeInActivePanels(); } } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); /* * Remove inactive when clicked */ clearInActiveButton.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { removeInActivePanels(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); } /** * Removes all panels whose reporter is no longer active */ private void removeInActivePanels() { Control[] controls = scrollChild.getChildren(); for (int i = 0; i < controls.length; i++) { if (null == controls[i] || true == controls[i].isDisposed()) { continue; } if (controls[i] instanceof ProgressReporterPanel) { IProgressReporter pReporter = ((ProgressReporterPanel) controls[i]).getProgressReporter(); if (false == pReporter.getProgressReport().isActive()) { ProgressReportingManager.getInstance().remove(pReporter); controls[i].dispose(); } } } } /** * Creates just an empty panel with a message indicating there are no reports to display */ private void createEmptyPanel() { Composite emptyPanel = new Composite(scrollChild, SWT.BORDER); GridData gData = new GridData(SWT.FILL, SWT.FILL, true, true); gData.heightHint = 100; emptyPanel.setLayoutData(gData); emptyPanel.setLayout(new GridLayout()); Label nothingToDisplay = new Label(emptyPanel, SWT.NONE); nothingToDisplay.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); nothingToDisplay.setText(MessageText.getString("Progress.reporting.no.reports.to.display")); /* * Mark this as being opened and is showing the empty panel */ isShowingEmpty = true; } /** * Set initial size and layout for the window then open it */ private void openWindow() { /* * Using initialMaxNumberOfPanels as a lower limit we exclude all other panels from the layout, * compute the window size, then finally we include all panels back into the layout * * This ensures that the window will fit exactly the desired number of panels */ Control[] controls = scrollChild.getChildren(); for (int i = (initialMaxNumberOfPanels); i < controls.length; i++) { ((GridData) controls[i].getLayoutData()).exclude = true; } Point p = shell.computeSize(defaultShellWidth, SWT.DEFAULT); for (int i = 0; i < controls.length; i++) { ((GridData) controls[i].getLayoutData()).exclude = false; } formatLastPanel(null); scrollChild.layout(); /* * Set the shell size if it's different that the computed size */ if (false == shell.getSize().equals(p)) { shell.setSize(p); shell.layout(false); } /* * Centers the window */ UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (null == uiFunctions) { /* * Centers on the active monitor */ Utils.centreWindow(shell); } else { /* * Centers on the main application window */ Utils.centerWindowRelativeTo(shell, uiFunctions.getMainShell()); } shell.open(); } private void createPanels() { int size = pReporters.length; /* * Add the style bit for standalone if there is zero or 1 reporters */ if (size < 2) { style |= STANDALONE; } for (int i = 0; i < size; i++) { if (null != pReporters[i]) { /* * Add this reporter to the registry */ reportersRegistry.add(pReporters[i]); /* * Create the reporter panel; adding the style bit for BORDER */ final ProgressReporterPanel panel = new ProgressReporterPanel( scrollChild, pReporters[i], style | BORDER); panel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); panel.addTwistieListener(this); panel.addDisposeListener(this); pReporters[i].addListener(new AutoRemoveListener(panel)); } } formatLastPanel(null); } /** * Formats the last ProgressReporterPanel in the window to extend to the bottom of the window. * This method will iterate from the last panel backward to the first, skipping over the given panel. * @param panelToIgnore */ private void formatLastPanel(ProgressReporterPanel panelToIgnore) { Control[] controls = scrollChild.getChildren(); for (int i = controls.length - 1; i >= 0; i--) { if (true != controls[i].equals(panelToIgnore)) { ((GridData) controls[i].getLayoutData()).grabExcessVerticalSpace = true; break; } } } /** * Remove the given IProgressReporter from the pReporters array; resize the array if required * @param reporter */ private void removeReporter(IProgressReporter reporter) { /* * Removes it from the registry */ reportersRegistry.remove(reporter); /* * The array is typically small so this is good enough for now */ int IDX = Arrays.binarySearch(pReporters, reporter); if (IDX >= 0) { IProgressReporter[] rps = new IProgressReporter[pReporters.length - 1]; for (int i = 0; i < rps.length; i++) { rps[i] = pReporters[(i >= IDX ? i + 1 : i)]; } pReporters = rps; } } /** * When any ProgressReporterPanel in this window is expanded or collapsed * re-layout the controls and window appropriately */ public void isCollapsed(boolean value) { if (null != shell && false == shell.isDisposed()) { scrollable.setRedraw(false); Rectangle r = scrollable.getClientArea(); scrollable.setMinSize(scrollChild.computeSize(r.width, SWT.DEFAULT)); /* * Resizing to fit the panel if there is only one */ if (pReporters.length == 1) { Point p = shell.computeSize(defaultShellWidth, SWT.DEFAULT); if (shell.getSize().y != p.y) { p.x = shell.getSize().x; shell.setSize(p); } } scrollable.layout(); scrollable.setRedraw(true); } } /** * When any ProgressReporterPanel in this window is disposed * re-layout the controls and window appropriately */ public void widgetDisposed(DisposeEvent e) { if (e.widget instanceof ProgressReporterPanel) { ProgressReporterPanel panel = (ProgressReporterPanel) e.widget; removeReporter(panel.pReporter); panel.removeTwistieListener(this); /* * Must let the GridLayout manager know that this control should be ignored */ ((GridData) panel.getLayoutData()).exclude = true; panel.setVisible(false); /* * If it's the last reporter then close the shell itself since it will be just empty */ if (pReporters.length == 0) { if ((style & AUTO_CLOSE) != 0) { if (null != shell && false == shell.isDisposed()) { shell.close(); } } else { createEmptyPanel(); } } else { /* * Formats the last panel; specifying this panel as the panelToIgnore * because at this point in the code this panel has not been removed * from the window yet */ formatLastPanel(panel); } if (null != shell && false == shell.isDisposed()) { shell.layout(true, true); } } } /** * Listener to reporters so we can remove the corresponding ProgressReporterPanel is the option * isAutoRemove = true * @author knguyen * */ private class AutoRemoveListener implements IProgressReporterListener { private ProgressReporterPanel panel = null; private AutoRemoveListener(ProgressReporterPanel panel) { this.panel = panel; } public int report(IProgressReport progressReport) { if (true == isAutoRemove && false == progressReport.isActive()) { if (null != panel && false == panel.isDisposed()) { ProgressReportingManager.getInstance().remove( panel.getProgressReporter()); Utils.execSWTThread(new AERunnable() { public void runSupport() { panel.dispose(); } }); } return RETVAL_OK_TO_DISPOSE; } return RETVAL_OK; } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/ProgressReporterPanel.java0000644000175000017500000005065711301715724026443 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.progress; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * * @author knguyen * */ public class ProgressReporterPanel extends Composite implements IProgressReportConstants, IProgressReporterListener { private Color normalColor = null; private Color errorColor = null; public IProgressReporter pReporter = null; private Label imageLabel = null; private Label nameLabel = null; private Label statusLabel = null; private StyledText detailListWidget = null; private GridData detailSectionData = null; private AZProgressBar pBar = null; private Composite progressPanel = null; private TwistieSection detailSection = null; private int style; private Label actionLabel_cancel = null; private Label actionLabel_remove = null; private Label actionLabel_retry = null; /** * The height of the detail panel when the window first appears. * This only takes effect when there is some detail messages to display and when that * list of messages is too long; this value limits the height of the panel so that the window * does not grow to take up too much of the screen in such instances. */ private int maxPreferredDetailPanelHeight = 200; /** * The preferred maximum height for the detail section on initialization */ private int maxPreferredDetailPanelHeight_Standalone = 600; /** * The preferred maximum width for the panel. When the longest line of the detail messages * of the width of the title is too wide we use this limit to prevent the panel from taking * up too much width; the user is still free to manually make the panel wider of narrower as desired */ private int maxPreferredWidth = 900; /** * we persist the last error to avoid it being overwritten by subsequent non-error messages */ private String lastStatusError = null; /** * Create a panel for the given reporter. * style could be one or more of these: *
      *
    • IProgressReportConstants.NONE -- the default
    • *
    • IProgressReportConstants.AUTO_CLOSE -- automatically disposes this panel when the given reporter is done
    • *
    • IProgressReportConstants.STANDALONE -- this panel will be hosted by itself in a window; the detail section of this panel will be given more height
    • *
    • IProgressReportConstants.BORDER -- this panel will be hosted by itself in a window; the detail section of this panel will be given more height
    • *
    * @param parent the Composite hosting the panel * @param reporter the IProgressReporter to host * @param style one of the style bits listed above */ public ProgressReporterPanel(Composite parent, IProgressReporter reporter, int style) { super(parent, ((style & BORDER) != 0 ? SWT.BORDER : SWT.NONE)); if (null == reporter) { throw new NullPointerException("IProgressReporter can not be null");//KN: should use resource? } this.pReporter = reporter; this.style = style; normalColor = Colors.blue; errorColor = Colors.colorError; /* * Give this Composite some margin and spacing */ setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); GridLayout gLayout = new GridLayout(2, false); gLayout.marginWidth = 25; gLayout.marginTop =15; gLayout.marginBottom=10; setLayout(gLayout); /* * Creates the rest of the controls */ createControls(pReporter.getProgressReport()); /* * Resize content when this panel changes size */ addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { resizeContent(); } }); /* * Update the UI when ever the reporter send a report */ pReporter.addListener(this); } /** * Call-back method from IProgressReporterListener; this method is called when ever the reporter * dispatches an event */ public int report(IProgressReport pReport) { return handleEvents(pReport); } /** * Creates all the controls for the panel * @param pReport */ private void createControls(IProgressReport pReport) { imageLabel = new Label(this, SWT.NONE); imageLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.TOP, false, false,1,3)); /* * Creates the main panel */ progressPanel = new Composite(this, SWT.NONE); progressPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); GridLayout rightLayout = new GridLayout(4, false); rightLayout.marginHeight = 0; rightLayout.marginWidth = 0; progressPanel.setLayout(rightLayout); /* * Creates all the controls */ nameLabel = new Label(progressPanel, SWT.WRAP); nameLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1)); pBar = new AZProgressBar(progressPanel, pReport.isIndeterminate()); pBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); actionLabel_cancel = new Label(progressPanel, SWT.NONE); actionLabel_cancel.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false)); actionLabel_remove = new Label(progressPanel, SWT.NONE); actionLabel_remove.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false)); actionLabel_retry = new Label(progressPanel, SWT.NONE); actionLabel_retry.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false)); statusLabel = new Label(progressPanel, SWT.NONE); statusLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false, 2, 1)); /* * Creates the detail section */ createDetailSection(pReport); /* * Initialize controls from information in the given report */ initControls(pReport); /* * Listener to 'cancel' label */ actionLabel_cancel.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { pReporter.cancel(); } }); /* * Listener to 'retry' label */ actionLabel_retry.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { pReporter.retry(); } }); /* * Listener to 'remove' label */ actionLabel_remove.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { /* * Removes the current reporter from the history stack of the reporting manager */ ProgressReportingManager.getInstance().remove(pReporter); /* * Then perform general clean-ups */ dispose(); } }); } /** * Initialize the controls with information from the given IProgressReport * @param pReport */ private void initControls(IProgressReport pReport) { /* * Image */ if (null != pReport.getImage()) { imageLabel.setImage(pReport.getImage()); } else { imageLabel.setImage(getDisplay().getSystemImage(SWT.ICON_INFORMATION)); } /* * Name label */ nameLabel.setText(formatForDisplay(pReport.getName())); /* * Action labels */ ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.setLabelImage(actionLabel_cancel, "progress_cancel"); imageLoader.setLabelImage(actionLabel_remove, "progress_remove"); imageLoader.setLabelImage(actionLabel_retry, "progress_retry"); actionLabel_cancel.setToolTipText(MessageText.getString("Progress.reporting.action.label.cancel.tooltip")); actionLabel_remove.setToolTipText(MessageText.getString("Progress.reporting.action.label.remove.tooltip")); actionLabel_retry.setToolTipText(MessageText.getString("Progress.reporting.action.label.retry.tooltip")); /* ======================================== * Catch up on any messages we might have missed */ { if (true == pReport.isInErrorState()) { updateStatusLabel( MessageText.getString("Progress.reporting.default.error"), true); }else if (true == pReport.isDone()) { updateStatusLabel( MessageText.getString("Progress.reporting.status.finished"), false); } else if (true == pReport.isCanceled()) { updateStatusLabel( MessageText.getString("Progress.reporting.status.canceled"), false); } else if (true == pReport.isIndeterminate()) { updateStatusLabel(Constants.INFINITY_STRING, false); } else { updateStatusLabel(pReport.getPercentage() + "%", false); } } /* * Synch the progress bar */ synchProgressBar(pReport); /* * Synch the action label according to existing properties of the ProgressReport */ synchActionLabels(pReport); } /** * Below the panel, taking up the entire width of the window, is the detail section */ private void createDetailSection(IProgressReport pReport) { Label separator = new Label(this, SWT.SEPARATOR | SWT.HORIZONTAL); separator.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); detailSection = new TwistieSection(this, TwistieLabel.NONE); detailSection.setTitle(MessageText.getString("Progress.reporting.action.label.detail")); Composite sectionContent = detailSection.getContent(); detailSectionData = new GridData(SWT.FILL, SWT.FILL, true, true); detailSection.setLayoutData(detailSectionData); GridLayout sectionLayout = new GridLayout(); sectionLayout.marginHeight = 0; sectionLayout.marginWidth = 0; sectionContent.setLayout(sectionLayout); detailSection.setEnabled(false); detailListWidget = new StyledText(sectionContent, SWT.BORDER | SWT.V_SCROLL | SWT.WRAP); detailListWidget.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); /* * Add a default message instead of an empty box if there is no history; * remove this later when a real detail message arrive */ IMessage[] messages = pReporter.getMessageHistory(); /* * Show error messages in red; otherwise use default color */ for (int i = 0; i < messages.length; i++) { if (messages[i].getType() == MSG_TYPE_ERROR) { appendToDetail(formatForDisplay(messages[i].getValue()), true); } else { appendToDetail(formatForDisplay(messages[i].getValue()), false); } } resizeDetailSection(); /* * Force a layout when ever the section is collapsed or expanded */ detailSection.addTwistieListener(new ITwistieListener() { public void isCollapsed(boolean value) { resizeDetailSection(); layout(true, true); } }); } /** * Ensure that the detail does not take up too much vertical space */ private void resizeDetailSection() { /* * Since detail panel automatically grows to show the entire list of detail messages * we want to at least place a limit on its height just in case the list is too long. * A vertical scrollbar will appear so the user can scroll through the rest of the list */ Point computedSize = detailSection.computeSize(SWT.DEFAULT, SWT.DEFAULT); detailSectionData.heightHint = computedSize.y; if ((STANDALONE & style) != 0) { if (computedSize.y > maxPreferredDetailPanelHeight_Standalone) { detailSectionData.heightHint = maxPreferredDetailPanelHeight_Standalone; } } else if (computedSize.y > maxPreferredDetailPanelHeight) { detailSectionData.heightHint = maxPreferredDetailPanelHeight; } if (computedSize.x > maxPreferredWidth) { detailSectionData.widthHint = maxPreferredWidth; } } public Point computeSize(int hint, int hint2, boolean changed) { Point newSize = super.computeSize(hint, hint2, changed); if (newSize.x > maxPreferredWidth) { newSize.x = maxPreferredWidth; } return newSize; } /** * Process the event from the given ProgressReport * * @param pReport */ private int handleEvents(final IProgressReport pReport) { if (null == pReport || true == isDisposed() || null == getDisplay()) { return RETVAL_OK; } /* Note each 'case' statement of the 'switch' block performs its UI update encapsulated in an .asyncExec() * so that the UI does not freeze or flicker. It may be tempting to encapsulate the whole 'switch' block * within one .asyncExec() but then a separate loop would be required to wait for the Runnable to finish * before attaining the correct return code. The alternative would be to encapsulate the 'switch' block * in a .syncExec() but that would cause freezing and flickering */ switch (pReport.getReportType()) { case REPORT_TYPE_PROPERTY_CHANGED: getDisplay().asyncExec(new Runnable() { public void run() { if (null != nameLabel && false == nameLabel.isDisposed()) { nameLabel.setText(pReport.getName()); } if (true == pReport.isIndeterminate()) { updateStatusLabel(Constants.INFINITY_STRING, false); } else { updateStatusLabel(pReport.getPercentage() + "%", false); } appendToDetail(pReport.getMessage(), false); appendToDetail(pReport.getDetailMessage(), false); synchProgressBar(pReport); synchActionLabels(pReport); resizeContent(); } }); break; case REPORT_TYPE_CANCEL: getDisplay().asyncExec(new Runnable() { public void run() { synchProgressBar(pReport); updateStatusLabel( MessageText.getString("Progress.reporting.status.canceled"), false); appendToDetail(pReport.getMessage(), false); synchActionLabels(pReport); resizeContent(); } }); break; case REPORT_TYPE_DONE: getDisplay().asyncExec(new Runnable() { public void run() { if (((style & AUTO_CLOSE) != 0)) { dispose(); } else { synchProgressBar(pReport); updateStatusLabel( MessageText.getString("Progress.reporting.status.finished"), false); appendToDetail( MessageText.getString("Progress.reporting.status.finished"), false); synchActionLabels(pReport); resizeContent(); } } }); /* * Since the reporter is done we don't need this listener anymore */ return RETVAL_OK_TO_DISPOSE; case REPORT_TYPE_MODE_CHANGE: getDisplay().asyncExec(new Runnable() { public void run() { if (null != pBar && false == pBar.isDisposed()) { pBar.setIndeterminate(pReport.isIndeterminate()); } } }); break; case REPORT_TYPE_ERROR: getDisplay().asyncExec(new Runnable() { public void run() { updateStatusLabel( MessageText.getString("Progress.reporting.default.error"), true); appendToDetail(pReport.getErrorMessage(), true); synchActionLabels(pReport); synchProgressBar(pReport); resizeContent(); } }); break; case REPORT_TYPE_RETRY: getDisplay().asyncExec(new Runnable() { public void run() { lastStatusError = null; updateStatusLabel(pReport.getMessage(), false); appendToDetail( MessageText.getString("Progress.reporting.status.retrying"), false); synchActionLabels(pReport); synchProgressBar(pReport); resizeContent(); } }); break; default: break; } return RETVAL_OK; } /** * Synchronize the progress bar with the given IProgressReport * @param pReport */ private void synchProgressBar(IProgressReport pReport) { if (null == pBar || pBar.isDisposed() || null == pReport) { return; } if (true == pReport.isInErrorState()) { pBar.setIndeterminate(false); pBar.setSelection(pReport.getMinimum()); } else { pBar.setIndeterminate(pReport.isIndeterminate()); if (false == pReport.isIndeterminate()) { pBar.setMinimum(pReport.getMinimum()); pBar.setMaximum(pReport.getMaximum()); } pBar.setSelection(pReport.getSelection()); } } /** * Sets the defined color to the given label * @param label * @param text * @param showAsError true to show as error; false otherwise */ private void updateStatusLabel(String text, boolean showAsError) { if (null == statusLabel || statusLabel.isDisposed()) { return; } // we persist any error reports as these need to be sticky and not // overritten by subsequent messages if ( showAsError ){ lastStatusError = text; } if ( lastStatusError != null ){ showAsError = true; text = lastStatusError; } statusLabel.setText(formatForDisplay(text)); if (false == showAsError) { statusLabel.setForeground(normalColor); } else { statusLabel.setForeground(errorColor); } statusLabel.update(); } /** * Display the appropriate text for the action labels * based on what action can be taken */ private void synchActionLabels(IProgressReport pReport) { if (null == actionLabel_remove || null == actionLabel_cancel || null == actionLabel_retry || true == actionLabel_remove.isDisposed() || true == actionLabel_cancel.isDisposed() || true == actionLabel_retry.isDisposed()) { return; } /* * There are 3 labels that can be clicked on; base on the state of the reporter itself. * The basic rules are these: * * If it's done * then show just "remove" * * else if it's in error * and retry is allowed * then show "retry" and "remove" * else just show "remove" * * else if it's been canceled * and retry is allowed * then show "retry" and "remove" * else just show "remove" * * else if it's none of the above * then show just the "cancel" label * enable the label if cancel is allowed * else disable the label * */ showActionLabel(actionLabel_cancel, false); showActionLabel(actionLabel_remove, false); showActionLabel(actionLabel_retry, false); if (true == pReport.isDone()) { showActionLabel(actionLabel_remove, true); } else if (true == pReport.isInErrorState()) { if (true == pReport.isRetryAllowed()) { showActionLabel(actionLabel_retry, true); showActionLabel(actionLabel_remove, true); } else { showActionLabel(actionLabel_remove, true); } } else if (true == pReport.isCanceled()) { if (true == pReport.isRetryAllowed()) { showActionLabel(actionLabel_retry, true); showActionLabel(actionLabel_remove, true); } else { showActionLabel(actionLabel_remove, true); } } else { showActionLabel(actionLabel_cancel, true); actionLabel_cancel.setEnabled(pReport.isCancelAllowed()); } } /** * Convenience method for showing or hiding a label by setting its GridData.widthHint * @param label * @param showIt */ private void showActionLabel(Label label, boolean showIt) { ((GridData) label.getLayoutData()).widthHint = (true == showIt) ? 16 : 0; } /** * Resizes the content of this panel to fit within the shell and to layout children control appropriately */ public void resizeContent() { if (false == isDisposed()) { layout(true, true); } } /** * Formats the string so it displays properly in an SWT text control * @param string * @return */ private String formatForDisplay(String string) { /* * SWT text controls do not allow a null argument as a value and will throw an exception if a null is encountered

    */ string = null == string ? "" : string; /* * Escaping the '&' character so it won't be shown as an underscore */ return string.replaceAll("&", "&&"); } public void addTwistieListener(ITwistieListener listener) { detailSection.addTwistieListener(listener); } public void removeTwistieListener(ITwistieListener listener) { detailSection.removeTwistieListener(listener); } /** * Appends the given message to the detail panel; render the message in error color if specified * @param value * @param isError if true then render the message in the system error color; otherwise render in default color */ private void appendToDetail(String value, boolean isError) { if (null == value || value.length() < 1) { return; } if (null == detailListWidget || detailListWidget.isDisposed()) { return; } int charCount = detailListWidget.getCharCount(); detailListWidget.append(value + "\n"); if (true == isError) { StyleRange style2 = new StyleRange(); style2.start = charCount; style2.length = value.length(); style2.foreground = errorColor; detailListWidget.setStyleRange(style2); } detailSection.setEnabled(true); } /** * Returns the attached reporter * @return */ public IProgressReporter getProgressReporter(){ return pReporter; } public int getStyle(){ return style; } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/IProgressReporter.java0000644000175000017500000001623510717253314025570 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.progress; import org.eclipse.swt.graphics.Image; /** * The interface for a progress reporter * @author knguyen * */ public interface IProgressReporter extends Comparable { /** * Sets the type of a reporter. This is a user defined property and no duplication check is ensured. * This optional property can be used to identify particular types of reports so that report consumers * have a way to ignore uninteresting report types * @param reporterType */ public void setReporterType(String reporterType); /** * Disposes any resources or listeners that this reporter has references to or otherwise is responsible for *

    Also removes it from the global ProgressReportingManager so that any subsequent event * from this reporter is no longer forwarded

    */ public void dispose(); /** * Returns an IProgressReport which is a snapshot of this reporter *

    * * NOTE: Each call to this method creates a new snapshot therefore the correct * usage pattern is:

    *
    	 * 
    	 * 	IProgressReport report = getProgressReport();
    	 * 	if( report.isDone() == false ){ 
    	 * 		// Do something
    	 * 	{
    	 * 	else if( report.isCanceled() == false ){ 
    	 * 		// Do something else
    	 * 	{
    	 * 	...
    	 * 
    	 * 
    * It may be tempting to use the less verbose pattern by repeatedly calling this * method directly such as: *
    	 * 
    	 * 	if( getProgressReport().isDone == false ){ 
    	 * 		// Do something
    	 * 	{
    	 * 	else if( getProgressReport().isCanceled == false ){ 
    	 * 		// Do something else
    	 * 	{
    	 * 
    	 * 
    * * BUT this can produce inconsistent results since each successive call to getProgressReport() * is returning a different snapshot. * * * @return */ public IProgressReport getProgressReport(); /** * Sets the selection to the progress reporter; this is used when a traditional min, max, selection is specified. *

    NOTE: this selection value also synchronize the percentage value of this reporter

    * @param selection * @param message */ public void setSelection(int selection, String message); /** * Sets the percentage value to the progress reporter; this is used when a simple percentage is specified as opposed to setting min, max, and selection. *

    NOTE: this percentage value also synchronize the selection value of this reporter

    * @param percentage an integer from 0-100 * @param message a textual message to display; null to leave the previous message untouched, empty String to clear any previous message */ public void setPercentage(int percentage, String message); /** * Set this reporter into indeterminate mode; use this when an accurate ratio of amount of work done vs. total amount of work can not be calculated * @param isIndeterminate */ public void setIndeterminate(boolean isIndeterminate); /** * Indicates that the associated process is done */ public void setDone(); /** * @param min the min to set */ public void setMinimum(int min); /** * @param max the max to set */ public void setMaximum(int max); /** * Marks this reporter as canceled and notify any listeners about it *

    NOTE: This is only a hint back to the processes listening to this reporter; * it is up to that process to determine the correct course of action in response to this flag */ public void cancel(); /** * Notifies listener that a retry is requested */ public void retry(); /** * Sets whether the process associated with this reporter is allowed to be canceled by the user. This serves as a hint * to the progress manager handling this reporter. If set to true the manager may * enable a UI component allowing the user to cancel the associated process if appropriate. *

    The holder of this reporter can register a listener to receive the cancel event

    * @see #addListener(IProgressReporterListener) * @see #removeListener(IProgressReporterListener) * * @param cancelAllowed true to indicate that this process may solicit a REPORT_TYPE_CANCEL input from the user; * default is false */ public void setCancelAllowed(boolean cancelAllowed); /** * * @param listener */ public void addListener(IProgressReporterListener listener); /** * * @param listener */ public void removeListener(IProgressReporterListener listener); /** * @param name a textual name to identify the process this reporter represents; need not be unique (should not be used as a lookup key), and may be null. */ public void setName(String name); /** * Sets the title that may be used by a UI component. * A typical usage would be for the title of a progress dialog * @param title the title to set */ public void setTitle(String title); /** * Sets the image corresponding to this reporter; this image may be used by the UI to decorate this reporter *

    NOTE: Though not strictly required (nor enforced) the image should be 32X32 pixels with transparency. * If not then cropping or enlargement may be applied as required by the particular UI

    * @param image the image; may be null */ public void setImage(Image image); /** * Sets an error message to this reporter; subsequently isInErrorState will be set to true * @see #reInit() * @param errorMessage */ public void setErrorMessage(String errorMessage); /** * Sets the current status message for this reporter; this is typically used to display a message at each incremental update * @param message a textual message */ public void setMessage(String message); /** * Appends the detail message to this reporter. This is typically a more verbose message that is optionally displayed by the UI. * This is an optional property so UI components displaying this can decide to show nothing for it (if it's null)or show the regular message in its place * *

    Additionally this is an appending message so that reporters can send smaller units of the message rather than * having to store and send the entire (and ever increasing) messages for each update

    * @param detailMessage */ public void appendDetailMessage(String detailMessage); /** * This is a hint to any UI components displaying this reporter * to determine if the user should be prompted to retry on error * @param isRetryAllowed true if the user should be prompted to retry when an error has occurred; false otherwise. Default is false */ public void setRetryAllowed(boolean retryOnError); /** * An arbitrary object reference that can be used to further identify the reporter. * This object is also accessible to listeners of the reporter through {@link ProgressReporter.ProgressReport#objectData} * so that it can be used to pass information to and from the listeners. * @param objectData the objectData to set */ public void setObjectData(Object objectData); /** * Returns an array of IMessage's that has been generated since the reporter was created * @return */ public IMessage[] getMessageHistory(); }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/progress/ProgressReporter.java0000644000175000017500000006532711301677064025467 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.progress; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.swt.graphics.Image; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.util.CopyOnWriteList; /** * A implementation of IProgressReporter *

    Any process wishing to participate in providing global progress indication can instantiate * this class and simply use the available methods so set values or issue a command * *

    * When ever any state changes in this reporter a notification will be sent to the global * reporting manager {@link ProgressReportingManager} followed by a notification to all * registered listeners of this reporter

    * * The listeners will be passed an immutable progress report {@link ProgressReporter.ProgressReport} which * represents a snapshot of all the public properties contained in this reporter; inspecting the * ProgressReport is the only way a listener can query the properties of this reporter. This pattern * allows the ProgressReporter to continue and process requests by not having to thread lock all public * methods. Additionally, the listeners are guaranteed a consistent snapshot of the reporter. * *

    * This reporter also has the capability to receive loop back commands from a listener for actions such like * {@link #cancel()} and {@link #retry()}. These commands are enabled by calling * {@link ProgressReporter#setCancelAllowed(boolean)} * or {@link ProgressReporter#setRetryAllowed(boolean)}. * * The listener only initiates these actions by sending a notification back to the owner of the reporter; * it is up the to owner to perform the actual act of canceling or retrying. *

    * * A typical life cycle of the ProgresReporter as seen from an owner is as follows * (an owner is defined as the process that created the reporter): *

      *
    • Create ProgressReporter
    • *
    • Set initial properties
    • *
    • Register a listener to the reporter to respond to loopback notifications (optional)
    • *
    • Update the reporter
    • *
        *
      • Set selection or percentage [{@link ProgressReporter#setSelection(int, String)}, {@link ProgressReporter#setPercentage(int, String)}]
      • *
      • Set message [{@link ProgressReporter#setMessage(String)}]
      • *
      • ...
      • *
      • Repeat until done
      • *
      • Set done [{@link ProgressReporter#setDone()}]
      • *
      * *
    • Then optionally Dispose of the reporter [{@link ProgressReporter#dispose(Object)}]
    • .

      * In addition to internal clean-ups, calling dispose(Object) will effectively remove the reporter from the history stack of the * reporting manager and no more messages from this reporter will be processed.

      *

    * * Once a reporter is created and any property in the reporter is set the global reporting manager is * notified; at which point any listener listening to the manager is forwarded this reporter. * The manager listener may decide to display this reporter in a UI element, may register specific * listeners to this reporter, may query its properties and take action, or can simply monitor it * for such functions as logging.

    * * This implementation is non-intrusive to the owner process and so provides existing processes the * ability to participate in global progress indication without significant modification to the underlying * processes. * * * * @author knguyen * */ public class ProgressReporter implements IProgressReporter, IProgressReportConstants { private ProgressReportingManager manager = null; /** * An instance id for this reporter that is guaranteed to be unique within this same session * It is declared as transient to help ensure no accidental reliance on the persistence of this ID * between sessionS (just in case this class is declared serializable in a future modification) */ private transient int ID; private int minimum, maximum, selection, percentage; private int latestReportType = REPORT_TYPE_INIT; private boolean isIndeterminate, isDone, isPercentageInUse, isCancelAllowed, isCanceled, isRetryAllowed, isInErrorState, isDisposed; private String title = ""; private String message = ""; /** * Accumulates the detail messages in a List *

    This is for when a listener starts listening to this reporter after it has started running; * upon initialization the listener may query this list to get all messages sent up to that point.

    * */ private CopyOnWriteList messageHistory = new CopyOnWriteList(); private String detailMessage = ""; private String errorMessage = ""; private String name = ""; private Image image = null; private String reporterType = REPORTER_TYPE_DEFAULT; private IProgressReport latestProgressReport = null; private CopyOnWriteList reporterListeners = null; //KN: Lazy init since not all reporters will have direct listeners /** * An arbitrary object reference that can be used by the owner of the ProgressReporter and its * listeners to share additional information should the current implementation be insufficient */ private Object objectData = null; private int messageHistoryLimit = 1000; /** * If any of the following states have been reached then the reporter is considered inactive: *
      *
    • isDisposed == true
    • *
    • isDone == true
    • *
    • isInErrorState == true
    • *
    • isCanceled == true
    • *
    */ private boolean isActive = true; /** * Construct a ProgressReporter; the returned instance is initialized with the proper ID */ protected ProgressReporter(ProgressReportingManager manager) { this(manager,null); } /** * Construct a ProgressReporter with the given name; the returned * instance would have been initialized with the proper ID * @param name */ protected ProgressReporter(ProgressReportingManager _manager, String name) { manager = _manager; this.name = name; this.ID = manager.getNextAvailableID(); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setReporterType(String) */ public void setReporterType(String reporterType) { this.reporterType = reporterType; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#dispose() */ public void dispose() { synchronized (this) { /* * Disposed already so no need to do it again */ if (true == isDisposed) { return; } isDisposed = true; isActive = false; } latestReportType = REPORT_TYPE_DISPOSED; /* * Notifies listeners */ notifyListeners( getProgressReport()); /* * Then dispose all listeners to let GC do it's magic. * This is just to do final clearing since at this point most listeners should have been disposed * already. */ if (null != reporterListeners) { reporterListeners.clear(); } /* * Finally notifies the manager */ manager.notifyManager(this); } /** * Resets this reporter to its initial states such that values are reset to default *

    An appropriate use for this is when a process is restarting or retrying; this allows an owning process * to keep on using the same instance of this reporter without having to create and dispatch a new one

    */ private void reInit() { isActive = true; isCanceled = false; isDone = false; isInErrorState = false; errorMessage = ""; message = ""; detailMessage = ""; messageHistory.clear(); } /** * Notifies registered listener that an event has occurred. * Subsequently a listener may be removed if it returns the value of RETVAL_OK_TO_DISPOSE; * this optimization is designed to prevent dangling/orphaned listeners, and also reduces the * number of listeners to notify upon the next event */ private void notifyListeners( IProgressReport report) { if (null == reporterListeners || reporterListeners.size() < 1) { return; } List removalList = new ArrayList(); for (Iterator iterator = reporterListeners.iterator(); iterator.hasNext();) { IProgressReporterListener listener = ((IProgressReporterListener) iterator.next()); try { /* * If the listener returned RETVAL_OK_TO_DISPOSE then it has indicated that it is no longer needed so we release it */ if (RETVAL_OK_TO_DISPOSE == listener.report( report )) { removalList.add(listener); } } catch (Throwable e) { Debug.out(e); } } /* * Removes any listeners marked ok to disposed */ for (Iterator iterator = removalList.iterator(); iterator.hasNext();) { reporterListeners.remove(iterator.next()); } } /** * Updates and notifies listeners * @param REPORT_TYPE */ private void updateAndNotify(int eventType) { latestReportType = eventType; /* * Take a snap shot of the reporter */ latestProgressReport = new ProgressReport(); /* * We directly bubble up this event to the manager for efficiency; * as opposed to having the manager register as a listener to each and every ProgressReporter. * Effectively this allows the manager to receive all events from all reporters */ manager.notifyManager(this); /* * If a property has changed but the reporter has been canceled then don't notify the listener * since they are no longer expecting a REPORT_TYPE_PROPERTY_CHANGED event */ if (eventType == REPORT_TYPE_PROPERTY_CHANGED && true == isCanceled) { return; } /* * Now we can notify listeners for this specific reporter */ notifyListeners( latestProgressReport ); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setSelection(int, java.lang.String) */ public void setSelection(int selection, String message) { if (true == shouldIgnore()) { return; } this.message = message; if (selection >= maximum) { setDone(); return; } if (selection < minimum) { percentage = 0; selection = minimum; isIndeterminate = true; return; } this.selection = selection; percentage = (selection * 100) / (maximum - minimum); isDone = false; isPercentageInUse = false; isIndeterminate = false; if (null != message && message.length() > 0) { addToMessageHistory(message, MSG_TYPE_INFO); } updateAndNotify(REPORT_TYPE_PROPERTY_CHANGED); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setPercentage(int, java.lang.String) */ public void setPercentage(int percentage, String message) { if (true == shouldIgnore()) { return; } this.message = message; if (percentage >= 100) { setDone(); return; } if (percentage < 0) { percentage = 0; selection = minimum; isIndeterminate = true; return; } minimum = 0; maximum = 100; this.percentage = percentage; this.selection = percentage; isDone = false; isPercentageInUse = true; isIndeterminate = false; if (null != message && message.length() > 0) { addToMessageHistory(message, MSG_TYPE_INFO); } updateAndNotify(REPORT_TYPE_PROPERTY_CHANGED); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setIndeterminate(boolean) */ public void setIndeterminate(boolean isIndeterminate) { if (true == shouldIgnore()) { return; } this.isIndeterminate = isIndeterminate; if (true == isIndeterminate) { minimum = 0; maximum = 0; } updateAndNotify(REPORT_TYPE_MODE_CHANGE); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setDone() */ public void setDone() { synchronized (this) { if (true == shouldIgnore()) { return; } isDone = true; isActive = false; } selection = maximum; percentage = 100; isIndeterminate = false; message = MessageText.getString("Progress.reporting.status.finished"); addToMessageHistory(message, MSG_TYPE_LOG); updateAndNotify(REPORT_TYPE_DONE); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setMessage(java.lang.String) */ public void setMessage(String message) { if (true == shouldIgnore()) { return; } this.message = message; addToMessageHistory(message, MSG_TYPE_INFO); updateAndNotify(REPORT_TYPE_PROPERTY_CHANGED); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setDetailMessage(java.lang.String) */ public void appendDetailMessage(String detailMessage) { if (true == shouldIgnore()) { return; } this.detailMessage = detailMessage; addToMessageHistory(detailMessage, MSG_TYPE_LOG); updateAndNotify(REPORT_TYPE_PROPERTY_CHANGED); /* * The detail message operates in append mode so after we have notified all the listeners * we reset it. It is up to the listeners to accumulate the messages. * * Lazy implementor can also simply query the messageHistory */ this.detailMessage = ""; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setMinimum(int) */ public void setMinimum(int min) { if (true == shouldIgnore()) { return; } this.minimum = min; updateAndNotify(REPORT_TYPE_PROPERTY_CHANGED); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setMaximum(int) */ public void setMaximum(int max) { if (true == shouldIgnore()) { return; } this.maximum = max; updateAndNotify(REPORT_TYPE_PROPERTY_CHANGED); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#cancel() */ public void cancel() { synchronized (this) { if (true == isCanceled || true == shouldIgnore()) { return; } isCanceled = true; isActive = false; } message = MessageText.getString("Progress.reporting.status.canceled"); addToMessageHistory(message, MSG_TYPE_LOG); updateAndNotify(REPORT_TYPE_CANCEL); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#retry() */ public void retry() { synchronized (this) { if (true == shouldIgnore()) { return; } reInit(); } message = MessageText.getString("Progress.reporting.status.retrying"); addToMessageHistory(message, MSG_TYPE_LOG); updateAndNotify(REPORT_TYPE_RETRY); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setCancelAllowed(boolean) */ public void setCancelAllowed(boolean cancelAllowed) { if (true == shouldIgnore()) { return; } this.isCancelAllowed = cancelAllowed; updateAndNotify(REPORT_TYPE_PROPERTY_CHANGED); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setName(java.lang.String) */ public void setName(String name) { if (true == shouldIgnore()) { return; } this.name = name + ""; //KN: Just a quick way to ensure the name is not null updateAndNotify(REPORT_TYPE_PROPERTY_CHANGED); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setTitle(java.lang.String) */ public void setTitle(String title) { if (true == shouldIgnore()) { return; } this.title = title; updateAndNotify(REPORT_TYPE_PROPERTY_CHANGED); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setImage(org.eclipse.swt.graphics.Image) */ public void setImage(Image image) { if (true == shouldIgnore()) { return; } this.image = image; updateAndNotify(REPORT_TYPE_PROPERTY_CHANGED); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setErrorMessage(java.lang.String) */ public void setErrorMessage(String errorMessage) { if (true == shouldIgnore()) { return; } /* * Ignores duplicate error messages * NOTE: TorrentDownloaderImpl#runSupport() has a loop that currently sends the same error message * multiple times; there may be other processes doing the same thing so this code is meant to prevent * forwarding any error message from the same reporter more than once. */ if (null != this.errorMessage && true == this.errorMessage.equals(errorMessage)) { return; } if (null == errorMessage || errorMessage.length() < 1) { this.errorMessage = MessageText.getString("Progress.reporting.default.error"); } else { this.errorMessage = errorMessage; } isInErrorState = true; isActive = false; addToMessageHistory(this.errorMessage, MSG_TYPE_ERROR); updateAndNotify(REPORT_TYPE_ERROR); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setRetryAllowed(boolean) */ public void setRetryAllowed(boolean retryOnError) { if (true == shouldIgnore()) { return; } this.isRetryAllowed = retryOnError; } /** * A convenience method to return whether this reporter should ignore subsequent calls to its accessor methods. * When a reporter has reached this state listeners usually make the assumption that there will be no * more changes to any properties in this reporter. The use of this method is intended to provide a more consistent * state for the reporter; without this check a listener may have reference to a reporter that is marked as done * but then a subsequent message says it's at 50% completion. By cutting of the notification here we prevent such * ambiguity from occurring for the listeners. *

    * If any of the following states have been reached then the reporter can ignore subsequent calls to its accessor methods: *

      *
    • isDisposed == true
    • *
    • isDone == true
    • *
    *

    * @return */ private boolean shouldIgnore() { return (true == isDisposed || true == isDone); } /** * Create and add an IMessage to the message history * @param value * @param type */ private void addToMessageHistory(String value, int type) { /* * Limiting the history list to prevent runaway processes from taking up too much resources */ if (messageHistory.size() >= messageHistoryLimit) { return; } if (messageHistory.size() < messageHistoryLimit) { messageHistory.add(new ProgressReportMessage(value, type)); } if (messageHistory.size() == messageHistoryLimit) { Debug.out(MessageText.getString( "Progress.reporting.detail.history.limit", new String[] { messageHistoryLimit + "" })); } } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#setObjectData(java.lang.Object) */ public void setObjectData(Object objectData) { if (true == shouldIgnore()) { return; } this.objectData = objectData; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#getMessageHistory() */ public IMessage[] getMessageHistory() { /* * Converting to array so the original list is insulated from modification */ List tmp = messageHistory.getList(); return (IMessage[]) tmp.toArray(new IMessage[tmp.size()]); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#addListener(org.gudy.azureus2.ui.swt.mainwindow.IProgressReporterListener) */ public void addListener(IProgressReporterListener listener) { if (true == shouldIgnore()) { return; } if (null != listener) { if (null == reporterListeners) { reporterListeners = new CopyOnWriteList(); reporterListeners.add(listener); } else if (false == reporterListeners.contains(listener)) { reporterListeners.add(listener); } } } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#removeListener(org.gudy.azureus2.ui.swt.mainwindow.IProgressReporterListener) */ public void removeListener(IProgressReporterListener listener) { if (null == reporterListeners) { return; } reporterListeners.remove(listener); } /** * Numerically compare by reporter ID's */ public int compareTo(Object obj) { if (obj instanceof IProgressReporter) { //KN: Will this always work as expected as opposed to using ((IProgressReporter)obj).getID()? return (ID < obj.hashCode() ? -1 : (ID == obj.hashCode() ? 0 : 1)); } return 0; } /** * Reporters are equal iif they have the same ID */ public boolean equals(Object obj) { if (obj instanceof IProgressReporter) { //KN: Will this always work as expected as opposed to using ((IProgressReporter)obj).getID()? return ID == obj.hashCode(); } return false; } /** * Hashcode and ID are the same */ public int hashCode() { return ID; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.mainwindow.IProgressReporter#getProgressReport() */ public IProgressReport getProgressReport() { if (null == latestProgressReport) { latestProgressReport = new ProgressReport(); } return latestProgressReport; } /** * An immutable object containing all interesting values in a ProgressReporter. *

    This represents a snapshot of all values at a single moment so instantiation of this class * should be guarded against multi-threaded modification of the source ProgressReporter

    * *

    This class is the only way an observer can query the properties of a ProgressReporter; * though they do not have to be, all variables are declared final to help remind the user of this class * that modification to any of its properties would have no effect on the reporter itself. *

    * An exception to this insulation is the objectData variable; both the reporter * and the ProgressReport consumer have full access to it. This is to facilitate advanced * 2-way communication between the 2 parties.

    * * * @author knguyen * @see ProgressReporter#getProgressReport() */ public class ProgressReport implements IProgressReport { private final String reporterType = ProgressReporter.this.reporterType; private final int reporterID = ProgressReporter.this.ID; private final int minimum = ProgressReporter.this.minimum; private final int maximum = ProgressReporter.this.maximum; private final int selection = ProgressReporter.this.selection; private final int percentage = ProgressReporter.this.percentage; private final boolean isActive = ProgressReporter.this.isActive; private final boolean isIndeterminate = ProgressReporter.this.isIndeterminate; private final boolean isDone = ProgressReporter.this.isDone; private final boolean isPercentageInUse = ProgressReporter.this.isPercentageInUse; private final boolean isCancelAllowed = ProgressReporter.this.isCancelAllowed; public final boolean isCanceled = ProgressReporter.this.isCanceled; private final boolean isRetryAllowed = ProgressReporter.this.isRetryAllowed; private final boolean isInErrorState = ProgressReporter.this.isInErrorState; private final boolean isDisposed = ProgressReporter.this.isDisposed; private final String title = ProgressReporter.this.title; private final String message = ProgressReporter.this.message; private final String detailMessage = ProgressReporter.this.detailMessage; private final String errorMessage = ProgressReporter.this.errorMessage; private final String name = ProgressReporter.this.name; private final Image image = ProgressReporter.this.image; private final Object objectData = ProgressReporter.this.objectData; private final int REPORT_TYPE = ProgressReporter.this.latestReportType; /** * Construct a ProgressReport */ private ProgressReport() { } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getReporterType() */ public String getReporterType() { return reporterType; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getReporterID() */ public int getReporterID() { return reporterID; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getMinimum() */ public int getMinimum() { return minimum; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getMaximum() */ public int getMaximum() { return maximum; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getSelection() */ public int getSelection() { return selection; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getPercentage() */ public int getPercentage() { return percentage; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#isActive() */ public boolean isActive() { return isActive; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#isIndeterminate() */ public boolean isIndeterminate() { return isIndeterminate; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#isDone() */ public boolean isDone() { return isDone; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#isPercentageInUse() */ public boolean isPercentageInUse() { return isPercentageInUse; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#isCancelAllowed() */ public boolean isCancelAllowed() { return isCancelAllowed; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#isCanceled() */ public boolean isCanceled() { return isCanceled; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#isRetryAllowed() */ public boolean isRetryAllowed() { return isRetryAllowed; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#isInErrorState() */ public boolean isInErrorState() { return isInErrorState; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#isDisposed() */ public boolean isDisposed() { return isDisposed; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getTitle() */ public String getTitle() { return title; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getMessage() */ public String getMessage() { return message; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getDetailMessage() */ public String getDetailMessage() { return detailMessage; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getErrorMessage() */ public String getErrorMessage() { return errorMessage; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getName() */ public String getName() { return name; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getImage() */ public Image getImage() { return image; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getObjectData() */ public Object getObjectData() { return objectData; } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getREPORT_TYPE() */ public int getReportType() { return REPORT_TYPE; } } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/updater2/0000755000175000017500000000000011310377636021144 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/updater2/SWTUpdateChecker.java0000644000175000017500000002740211171750562025117 0ustar adrianadrian/* * Created on 20 mai 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.updater2; import java.io.File; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.eclipse.swt.SWT; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.update.UpdatableComponent; import org.gudy.azureus2.plugins.update.Update; import org.gudy.azureus2.plugins.update.UpdateChecker; import org.gudy.azureus2.plugins.update.UpdateInstaller; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderAdapter; import org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader.ResourceDownloaderFactoryImpl; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; /** * @author Olivier Chalouhi * */ public class SWTUpdateChecker implements UpdatableComponent { private static final LogIDs LOGID = LogIDs.GUI; private static final String OSX_APP = "/" + SystemProperties.getApplicationName() + ".app"; public static void initialize() { PluginInitializer.getDefaultInterface().getUpdateManager().registerUpdatableComponent(new SWTUpdateChecker(),true); } public SWTUpdateChecker() { } public void checkForUpdate(final UpdateChecker checker) { try{ SWTVersionGetter versionGetter = new SWTVersionGetter( checker ); boolean update_required = System.getProperty("azureus.skipSWTcheck") == null && versionGetter.needsUpdate(); if ( update_required ){ int update_prevented_version = COConfigurationManager.getIntParameter( "swt.update.prevented.version", -1 ); try{ URL swt_url = SWT.class.getClassLoader().getResource("org/eclipse/swt/SWT.class"); if ( swt_url != null ){ String url_str = swt_url.toExternalForm(); if ( url_str.startsWith("jar:file:")){ File jar_file = FileUtil.getJarFileFromURL(url_str); String expected_location; if ( Constants.isOSX ){ expected_location = checker.getCheckInstance().getManager().getInstallDir() + OSX_APP + "/Contents/Resources/Java"; }else{ expected_location = checker.getCheckInstance().getManager().getInstallDir(); } File expected_dir = new File( expected_location ); File jar_file_dir = jar_file.getParentFile(); // sanity check if ( expected_dir.exists() && jar_file_dir.exists() ){ expected_dir = expected_dir.getCanonicalFile(); jar_file_dir = jar_file_dir.getCanonicalFile(); if ( expected_dir.equals( jar_file_dir )){ // everything looks ok if ( update_prevented_version != -1 ){ update_prevented_version = -1; COConfigurationManager.setParameter( "swt.update.prevented.version", update_prevented_version ); } }else{ // we need to periodically remind the user there's a problem as they need to realise that // it is causing ALL updates (core/plugin) to fail String alert = MessageText.getString( "swt.alert.cant.update", new String[]{ String.valueOf( versionGetter.getCurrentVersion()), String.valueOf( versionGetter.getLatestVersion()), jar_file_dir.toString(), expected_dir.toString()}); checker.reportProgress( alert ); long last_prompt = COConfigurationManager.getLongParameter( "swt.update.prevented.version.time", 0 ); long now = SystemTime.getCurrentTime(); boolean force = now < last_prompt || now - last_prompt > 7*24*60*60*1000; if ( !checker.getCheckInstance().isAutomatic()){ force = true; } if ( force || update_prevented_version != versionGetter.getCurrentVersion()){ Logger.log( new LogAlert(LogAlert.REPEATABLE, LogEvent.LT_ERROR, alert )); update_prevented_version = versionGetter.getCurrentVersion(); COConfigurationManager.setParameter( "swt.update.prevented.version", update_prevented_version ); COConfigurationManager.setParameter( "swt.update.prevented.version.time", now ); } } } } } }catch( Throwable e ){ Debug.printStackTrace(e); } if ( update_prevented_version == versionGetter.getCurrentVersion()){ Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "SWT update aborted due to previously reported issues regarding its install location" )); checker.failed(); checker.getCheckInstance().cancel(); return; } String[] mirrors = versionGetter.getMirrors(); ResourceDownloader swtDownloader = null; ResourceDownloaderFactory factory = ResourceDownloaderFactoryImpl.getSingleton(); List downloaders = new ArrayList(); for(int i = 0 ; i < mirrors.length ; i++) { try { downloaders.add(factory.getSuffixBasedDownloader(factory.create(new URL(mirrors[i])))); } catch(MalformedURLException e) { //Do nothing if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Cannot use URL " + mirrors[i] + " (not valid)")); } } ResourceDownloader[] resourceDownloaders = (ResourceDownloader[]) downloaders.toArray(new ResourceDownloader[downloaders.size()]); swtDownloader = factory.getRandomDownloader(resourceDownloaders); // get the size so its cached up try{ swtDownloader.getSize(); }catch( ResourceDownloaderException e ){ Debug.printStackTrace( e ); } final Update update = checker.addUpdate("SWT Library for " + versionGetter.getPlatform(), new String[] {"SWT is the graphical library used by " + Constants.APP_NAME}, "" + versionGetter.getLatestVersion(), swtDownloader, Update.RESTART_REQUIRED_YES ); update.setDescriptionURL(versionGetter.getInfoURL()); swtDownloader.addListener(new ResourceDownloaderAdapter() { public boolean completed(ResourceDownloader downloader, InputStream data) { //On completion, process the InputStream to store temp files return processData(checker,update,downloader,data); } }); } }catch( Throwable e ){ Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "SWT Version check failed", e)); checker.failed(); }finally{ checker.completed(); } } private boolean processData( UpdateChecker checker, Update update, ResourceDownloader rd, InputStream data ) { ZipInputStream zip = null; try { data = update.verifyData( data, true ); rd.reportActivity( "Data verified successfully" ); UpdateInstaller installer = checker.createInstaller(); zip = new ZipInputStream(data); ZipEntry entry = null; while((entry = zip.getNextEntry()) != null) { String name = entry.getName(); // all jars if ( name.endsWith( ".jar" )){ installer.addResource(name,zip,false); if ( Constants.isOSX ){ installer.addMoveAction(name,installer.getInstallDir() + OSX_APP + "/Contents/Resources/Java/" + name); }else{ installer.addMoveAction(name,installer.getInstallDir() + File.separator + name); } }else if ( name.endsWith(".jnilib") && Constants.isOSX ){ //on OS X, any .jnilib installer.addResource(name,zip,false); installer.addMoveAction(name,installer.getInstallDir() + OSX_APP + "/Contents/Resources/Java/dll/" + name); }else if ( name.equals("java_swt")){ //on OS X, java_swt (the launcher to start SWT applications) installer.addResource(name,zip,false); installer.addMoveAction(name,installer.getInstallDir() + OSX_APP + "/Contents/MacOS/" + name); installer.addChangeRightsAction("755",installer.getInstallDir() + OSX_APP + "/Contents/MacOS/" + name); }else if( name.endsWith( ".dll" ) || name.endsWith( ".so" ) || name.indexOf( ".so." ) != -1 ) { // native stuff for windows and linux installer.addResource(name,zip,false); installer.addMoveAction(name,installer.getInstallDir() + File.separator + name); }else if ( name.equals("javaw.exe.manifest") || name.equals( "azureus.sig" )){ // silently ignore this one }else{ Debug.outNoStack( "SWTUpdate: ignoring zip entry '" + name + "'" ); } } } catch(Exception e) { Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "SWT Update failed", e)); return false; }finally{ if ( zip != null ){ try{ zip.close(); }catch( Throwable e ){ } } } return true; } public String getName() { return( "SWT library" ); } public int getMaximumCheckTime() { return( 30 ); // !!!! TODO: fix this } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/updater2/SWTVersionGetter.java0000644000175000017500000001332611250036232025175 0ustar adrianadrian/* * Created on 20 mai 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.updater2; import java.util.Map; import org.eclipse.swt.SWT; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.AEVerifier; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; import org.gudy.azureus2.plugins.update.UpdateChecker; /** * @author Olivier Chalouhi * */ public class SWTVersionGetter { private static final LogIDs LOGID = LogIDs.GUI; private String platform; private int currentVersion; private int latestVersion; private UpdateChecker checker; private String[] mirrors; private String infoURL; public SWTVersionGetter( UpdateChecker _checker ) { this.platform = SWT.getPlatform(); this.currentVersion = SWT.getVersion(); this.latestVersion = 0; checker = _checker; } public boolean needsUpdate() { try { downloadLatestVersion(); String msg = "SWT: current version = " + currentVersion + ", latest version = " + latestVersion; checker.reportProgress( msg ); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, msg)); return latestVersion > currentVersion; } catch(Exception e) { e.printStackTrace(); return false; } } private void downloadLatestVersion() { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Requesting latest SWT version " + "and url from version check client.")); Map reply = VersionCheckClient.getSingleton().getVersionCheckInfo(VersionCheckClient.REASON_CHECK_SWT); String msg = "SWT version check received:"; boolean done = false; if ( Constants.isOSX_10_5_OrHigher ){ String target_lib = COConfigurationManager.getStringParameter( "ConfigView.section.style.swt.library.selection" ); String current_lib = SWT.getPlatform(); if ( target_lib.equalsIgnoreCase( current_lib )){ byte[] version_bytes = (byte[])reply.get( "swt_version_" + target_lib ); if ( version_bytes != null ){ latestVersion = Integer.parseInt( new String( version_bytes ) ); msg += " version=" + latestVersion; byte[] url_bytes = (byte[])reply.get( "swt_url_" + target_lib ); if ( url_bytes != null ){ mirrors = new String[] { new String( url_bytes ) }; msg += " url=" + mirrors[0]; } done = true; } }else{ byte[] url_bytes = (byte[])reply.get( "swt_url_" + target_lib ); if ( url_bytes != null ){ msg += " (platform switch from " + current_lib + " to " + target_lib + ")"; mirrors = new String[] { new String( url_bytes ) }; msg += " url=" + mirrors[0]; latestVersion = Integer.MAX_VALUE; done = true; } } } if ( !done ){ byte[] version_bytes = (byte[])reply.get( "swt_version" ); if( version_bytes != null ) { latestVersion = Integer.parseInt( new String( version_bytes ) ); msg += " version=" + latestVersion; } byte[] url_bytes = (byte[])reply.get( "swt_url" ); if( url_bytes != null ) { mirrors = new String[] { new String( url_bytes ) }; msg += " url=" + mirrors[0]; } } byte[] info_bytes = (byte[])reply.get( "swt_info_url" ); if ( info_bytes != null ){ byte[] sig = (byte[])reply.get( "swt_info_sig" ); if ( sig == null ){ Logger.log( new LogEvent( LogIDs.LOGGER, "swt info signature check failed - missing signature" )); }else{ try{ infoURL = new String( info_bytes ); try{ AEVerifier.verifyData( infoURL, sig ); }catch( Throwable e ){ Logger.log( new LogEvent( LogIDs.LOGGER, "swt info signature check failed", e )); infoURL = null; } }catch ( Exception e ){ Logger.log(new LogEvent(LOGID, "swt info_url", e)); } } } if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, msg)); } /** * @return Returns the latestVersion. */ public int getLatestVersion() { return latestVersion; } public int getCurrentVersion() { return currentVersion; } /** * @return Returns the platform. */ public String getPlatform() { return platform; } /** * @return Returns the mirrors. */ public String[] getMirrors() { return mirrors; } public String getInfoURL() { return infoURL; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/updater2/PreUpdateChecker.java0000644000175000017500000000304511066631516025165 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.updater2; import org.gudy.azureus2.update.UpdaterUtils; import com.aelitis.azureus.core.AzureusCore; /** * @created Sep 6, 2007 * */ public class PreUpdateChecker { /** * @param ui * * @since 3.0.2.3 */ public static void initialize( AzureusCore core, String ui ) { if ( ui.equals( "az3") && !"0".equals(System.getProperty("azureus.loadplugins"))) { if ( UpdaterUtils.ensurePluginPresent( "azemp", "com.azureus.plugins.azemp.EmbeddedMediaPlayerPlugin", "Embedded Media Player" )){ // rescan if we've done anything core.getPluginManager().refreshPluginList(); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/updater2/swt_version.php0000644000175000017500000000723410064611770024240 0ustar adrianadrian http://download2.eclipse.org/downloads/drops/S-3.0RC2-200406111814/eclipse-SDK-3.0RC2-win32.zip http://download2.eclipse.org/downloads/drops/S-3.0RC2-200406111814/eclipse-SDK-3.0RC2-linux-motif.zip http://download2.eclipse.org/downloads/drops/S-3.0RC2-200406111814/eclipse-SDK-3.0RC2-linux-gtk.zip http://download2.eclipse.org/downloads/drops/S-3.0RC2-200406111814/swt-3.0RC2-macosx-carbon.zip http://mirror.tiscali.dk/eclipse/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-win32.zip http://download2.eclipse.org/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-win32.zip http://mirror.tiscali.dk/eclipse/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-linux-motif.zip http://download2.eclipse.org/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-linux-motif.zip http://mirror.tiscali.dk/eclipse/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-linux-gtk.zip http://download2.eclipse.org/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-linux-motif.zip http://mirror.tiscali.dk/eclipse/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-macosx-carbon.zip http://download2.eclipse.org/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-macosx-carbon.zip http://download2.eclipse.org/downloads/drops/S-3.0RC2-200406111814/swt-3.0RC2-win32.zip http://download2.eclipse.org/downloads/drops/S-3.0RC2-200406111814/swt-3.0RC2-linux-motif.zip http://download2.eclipse.org/downloads/drops/S-3.0RC2-200406111814/swt-3.0RC2-linux-gtk.zip http://download2.eclipse.org/downloads/drops/S-3.0RC2-200406111814/swt-3.0RC2-macosx-carbon.zip http://mirror.tiscali.dk/eclipse/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-win32.zip http://download2.eclipse.org/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-win32.zip http://mirror.tiscali.dk/eclipse/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-linux-motif.zip http://download2.eclipse.org/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-linux-motif.zip http://mirror.tiscali.dk/eclipse/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-linux-gtk.zip http://download2.eclipse.org/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-linux-motif.zip http://mirror.tiscali.dk/eclipse/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-macosx-carbon.zip http://download2.eclipse.org/downloads/drops/S-3.0M9-200405211200/swt-3.0M9-macosx-carbon.zip azureus-4.3.0.6/org/gudy/azureus2/ui/swt/MenuBuildUtils.java0000644000175000017500000002331311232522032023151 0ustar adrianadrian/* * Created on 25-Jan-2007 * Created by Allan Crooks * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.events.MenuListener; import org.eclipse.swt.widgets.Menu; import org.gudy.azureus2.plugins.ui.Graphic; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.pluginsimpl.local.ui.menus.MenuItemImpl; import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem; import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Constants; /** * A class which helps generate build SWT menus. * * It provides two main functions. The first provides the ability to create * regenerateable menus (it will dispose old items when not displayed and * invoke a callback method to regenerate it). * * The second provides the ability to create SWT menus based on the plugin * API for menu creation - this allows internal code that generates menus * to include plugins to append to their own internal menus. * * @author Allan Crooks */ public class MenuBuildUtils { /** * An interface to be used for addMaintenanceListenerForMenu. */ public static interface MenuBuilder { public void buildMenu(Menu root_menu, MenuEvent menuEvent); } /** * Creates and adds a listener object to implement regeneratable menus. * * The first piece of functionality it offers is the ability to call a * callback method to generate the menu when it is about to be displayed * (the callback method is done by passing an object implementing the * MenuBuilder interface). * * This means that the caller of this method only needs to provide the * logic to construct the menu's contents. This is helpful if you want * to update an existing menu. * * The second piece of functionality is that it automatically does what * is required to dispose of existing menu items when the menu is hidden. */ public static void addMaintenanceListenerForMenu(final Menu menu, final MenuBuilder builder) { // Was taken from TableView.java menu.addMenuListener(new MenuListener() { boolean bShown = false; public void menuHidden(MenuEvent e) { bShown = false; if (Constants.isOSX) return; // Must dispose in an asyncExec, otherwise SWT.Selection doesn't // get fired (async workaround provided by Eclipse Bug #87678) e.widget.getDisplay().asyncExec(new AERunnable() { public void runSupport() { if (bShown || menu.isDisposed()) return; org.eclipse.swt.widgets.MenuItem[] items = menu .getItems(); for (int i = 0; i < items.length; i++) { items[i].dispose(); } } }); }; public void menuShown(MenuEvent e) { org.eclipse.swt.widgets.MenuItem[] items = menu.getItems(); for (int i = 0; i < items.length; i++) items[i].dispose(); bShown = true; builder.buildMenu(menu, e); } }); } /** * This is an interface used by addPluginMenuItems. */ public static interface PluginMenuController { /** * This method should create a listener object which should be invoked * when the given menu item is selected. */ public Listener makeSelectionListener(MenuItem plugin_menu_item); /** * This method will be invoked just before the given menu item is * displayed in a menu. */ public void notifyFillListeners(MenuItem menu_item); } /** * This is an implementation of the PluginMenuController interface for use with * MenuItemImpl classes - note that this is not intended for use by subclasses of * MenuItemImpl (like TableContextMenuItemImpl). * * The object passed at construction time is the object to be passed when selection * listeners and fill listeners are notified. */ public static class MenuItemPluginMenuControllerImpl implements PluginMenuController { private Object[] objects; public MenuItemPluginMenuControllerImpl(Object[] o) { this.objects = o; } public Listener makeSelectionListener(MenuItem menu_item) { final MenuItemImpl mii = (MenuItemImpl) menu_item; return new Listener() { public void handleEvent(Event e) { mii.invokeListenersMulti(objects); } }; } public void notifyFillListeners(MenuItem menu_item) { ((MenuItemImpl) menu_item).invokeMenuWillBeShownListeners(objects); } } /** * An instance of MenuItemPluginMenuControllerImpl with a default value of * null - this will be the value passed when notifying selection and fill * listeners. */ public static final PluginMenuController BASIC_MENU_ITEM_CONTROLLER = new MenuItemPluginMenuControllerImpl(null); /** * Creates menu items inside the given menu based on the plugin API MenuItem * instances provided. This method is provided mainly as a utility method to * make it easier for menus to incorporate menu components specified by * plugins. * * Usually, the list of array items will be extracted from a class like * MenuItemManager or TableContextMenuManager, where plugins will usually * register menu items they have created. * * @param composite Some composite to get a shell from. * @param items The list of plugin MenuItem to add * @param parent The SWT Menu to add to. * @param prev_was_separator Indicates if the previous item in the menu is * a separator or not * @param enable_items Indicates whether you want generated items to be * enabled or not. If false, all items will be disabled. If true, * then the items *may* be enabled, depending on how each MenuItem * is configured. * @param controller The callback object used by this method when creating the * SWT menus (used for invoking fill and selection listeners). */ public static void addPluginMenuItems(Composite composite, MenuItem[] items, Menu parent, boolean prev_was_separator, boolean enable_items, PluginMenuController controller) { for (int i = 0; i < items.length; i++) { final MenuItemImpl az_menuitem = (MenuItemImpl) items[i]; controller.notifyFillListeners(az_menuitem); if (!az_menuitem.isVisible()) {continue;} final int style = az_menuitem.getStyle(); final int swt_style; boolean this_is_separator = false; // Do we have any children? If so, we override any manually defined // style. boolean is_container = false; if (style == TableContextMenuItem.STYLE_MENU) { swt_style = SWT.CASCADE; is_container = true; } else if (style == TableContextMenuItem.STYLE_PUSH) { swt_style = SWT.PUSH; } else if (style == TableContextMenuItem.STYLE_CHECK) { swt_style = SWT.CHECK; } else if (style == TableContextMenuItem.STYLE_RADIO) { swt_style = SWT.RADIO; } else if (style == TableContextMenuItem.STYLE_SEPARATOR) { this_is_separator = true; swt_style = SWT.SEPARATOR; } else { swt_style = SWT.PUSH; } final org.eclipse.swt.widgets.MenuItem menuItem = new org.eclipse.swt.widgets.MenuItem( parent, swt_style); if (swt_style == SWT.SEPARATOR) {continue;} if (prev_was_separator && this_is_separator) {continue;} // Skip contiguous separators if (this_is_separator && i == items.length - 1) {continue;} // Skip trailing separator prev_was_separator = this_is_separator; if (enable_items) { if (style == TableContextMenuItem.STYLE_CHECK || style == TableContextMenuItem.STYLE_RADIO) { Boolean selection_value = (Boolean) az_menuitem.getData(); if (selection_value == null) { throw new RuntimeException( "MenuItem with resource name \"" + az_menuitem.getResourceKey() + "\" needs to have a boolean value entered via setData before being used!"); } menuItem.setSelection(selection_value.booleanValue()); } } final Listener main_listener = controller.makeSelectionListener(az_menuitem); menuItem.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { if (az_menuitem.getStyle() == MenuItem.STYLE_CHECK || az_menuitem.getStyle() == MenuItem.STYLE_RADIO) { if (!menuItem.isDisposed()) { az_menuitem.setData(new Boolean(menuItem.getSelection())); } } main_listener.handleEvent(e); } }); if (is_container) { Menu this_menu = new Menu(composite.getShell(), SWT.DROP_DOWN); menuItem.setMenu(this_menu); addPluginMenuItems(composite, az_menuitem.getItems(), this_menu, false, enable_items, controller); } String custom_title = az_menuitem.getText(); menuItem.setText(custom_title); Graphic g = az_menuitem.getGraphic(); if (g instanceof UISWTGraphic) { Utils.setMenuItemImage(menuItem, ((UISWTGraphic) g).getImage()); } menuItem.setEnabled(enable_items && az_menuitem.isEnabled()); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/exporttorrent/0000755000175000017500000000000011310377444022352 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/exporttorrent/wizard/0000755000175000017500000000000011310377636023655 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardFinishPanel.java0000644000175000017500000000453007745251402032662 0ustar adrianadrian/* * File : ExportTorrentFinishPanel.java * Created : 13-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.exporttorrent.wizard; /** * @author parg * */ import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; public class ExportTorrentWizardFinishPanel extends AbstractWizardPanel { public ExportTorrentWizardFinishPanel( ExportTorrentWizard wizard, IWizardPanel previous) { super(wizard, previous); } public void show() { wizard.setTitle(MessageText.getString("exportTorrentWizard.finish.title")); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); Label label = new Label(panel, SWT.WRAP); gridData = new GridData(); gridData.horizontalSpan = 3; gridData.widthHint = 380; label.setLayoutData(gridData); Messages.setLanguageText(label, "exportTorrentWizard.finish.message"); } public boolean isPreviousEnabled() { return( false ); } public void finish() { wizard.switchToClose(); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizard.java0000644000175000017500000001063011171750564030540 0ustar adrianadrian/* * File : ConfigureWizard.java * Created : 13-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.exporttorrent.wizard; /** * @author parg * */ import java.io.File; import java.io.IOException; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.MessageBox; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.ui.swt.wizard.Wizard; public class ExportTorrentWizard extends Wizard { String torrent_file = ""; String export_file = ""; public ExportTorrentWizard() { super("exportTorrentWizard.title"); ExportTorrentWizardInputPanel input_panel = new ExportTorrentWizardInputPanel(this,null); setFirstPanel(input_panel); } public ExportTorrentWizard( Display display, DownloadManager dm ) { super("exportTorrentWizard.title"); setTorrentFile( dm.getTorrentFileName()); ExportTorrentWizardOutputPanel output_panel = new ExportTorrentWizardOutputPanel(this,null); setFirstPanel(output_panel); } public void onClose() { // Call the parent class to clean up resources super.onClose(); } protected void setTorrentFile( String str ) { torrent_file = str; export_file = str + ".xml"; } protected String getTorrentFile() { return( torrent_file ); } protected void setExportFile( String str ) { export_file = str; } protected String getExportFile() { return( export_file ); } protected boolean performExport() { File input_file; try{ input_file = new File( getTorrentFile()).getCanonicalFile(); }catch( IOException e ){ MessageBox mb = new MessageBox(getWizardWindow(),SWT.ICON_ERROR | SWT.OK ); mb.setText(MessageText.getString("exportTorrentWizard.process.inputfilebad.title")); mb.setMessage( MessageText.getString("exportTorrentWizard.process.inputfilebad.message")+"\n" + e.toString()); mb.open(); return( false ); } File output_file = new File( export_file ); if ( output_file.exists()){ MessageBox mb = new MessageBox(this.getWizardWindow(),SWT.ICON_QUESTION | SWT.YES | SWT.NO); mb.setText(MessageText.getString("exportTorrentWizard.process.outputfileexists.title")); mb.setMessage(MessageText.getString("exportTorrentWizard.process.outputfileexists.message")); int result = mb.open(); if( result == SWT.NO ){ return( false ); } } String error_title; String error_detail; try{ TOTorrent torrent; try{ torrent = TOTorrentFactory.deserialiseFromBEncodedFile( input_file ); try{ torrent.serialiseToXMLFile( output_file ); return( true ); }catch( TOTorrentException e ){ error_title = MessageText.getString("exportTorrentWizard.process.exportfail.title"); error_detail = TorrentUtils.exceptionToText( e ); } }catch( TOTorrentException e ){ error_title = MessageText.getString("exportTorrentWizard.process.torrentfail.title"); error_detail = TorrentUtils.exceptionToText( e ); } }catch( Throwable e ){ error_title = MessageText.getString("exportTorrentWizard.process.unknownfail.title"); error_detail = e.toString(); } MessageBox mb = new MessageBox(this.getWizardWindow(),SWT.ICON_ERROR | SWT.OK ); mb.setText(error_title); mb.setMessage(error_detail); mb.open(); return( false ); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardInputPanel.java0000644000175000017500000001044610357107106032536 0ustar adrianadrian/* * File : ExportTorrentWizardFilePanel.java * Created : 13-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.exporttorrent.wizard; /** * @author parg * */ import java.io.File; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.*; public class ExportTorrentWizardInputPanel extends AbstractWizardPanel { protected boolean file_valid = false; public ExportTorrentWizardInputPanel( Wizard wizard, IWizardPanel previous ) { super(wizard, previous); } public void show() { wizard.setTitle(MessageText.getString("exportTorrentWizard.torrentfile.title")); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); Label label = new Label(panel, SWT.WRAP); gridData = new GridData(); gridData.horizontalSpan = 3; gridData.widthHint = 380; label.setLayoutData(gridData); Messages.setLanguageText(label, "exportTorrentWizard.torrentfile.message"); label = new Label(panel,SWT.NULL); Messages.setLanguageText(label, "exportTorrentWizard.torrentfile.path"); final Text textPath = new Text(panel,SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); textPath.setLayoutData(gridData); textPath.setText(""); Button browse = new Button(panel,SWT.PUSH); Messages.setLanguageText(browse, "exportTorrentWizard.torrentfile.browse"); browse.addListener(SWT.Selection,new Listener() { public void handleEvent(Event arg0) { FileDialog fd = new FileDialog(wizard.getWizardWindow()); fd.setFileName(textPath.getText()); fd.setFilterExtensions(new String[]{"*.torrent", "*.tor", Constants.FILE_WILDCARD}); String path = fd.open(); if(path != null) { textPath.setText(path); } } }); textPath.addListener(SWT.Modify, new Listener(){ public void handleEvent(Event event) { String path = textPath.getText(); ((ExportTorrentWizard)wizard).setTorrentFile( path ); file_valid = false; try{ File f = new File(path); if( f.exists()){ if (f.isFile()){ file_valid = true; wizard.setErrorMessage(""); }else{ wizard.setErrorMessage(MessageText.getString("exportTorrentWizard.torrentfile.invalidPath")); } } }catch(Exception e){ wizard.setErrorMessage(MessageText.getString("exportTorrentWizard.torrentfile.invalidPath")); } wizard.setNextEnabled( file_valid ); } }); textPath.setText(((ExportTorrentWizard)wizard).getTorrentFile()); textPath.setFocus(); } public IWizardPanel getNextPanel() { return( new ExportTorrentWizardOutputPanel(wizard,this)); } public boolean isNextEnabled() { return( file_valid ); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardOutputPanel.java0000644000175000017500000001104710357107106032735 0ustar adrianadrian/* * File : ExportTorrentWizardFilePanel.java * Created : 13-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.exporttorrent.wizard; /** * @author parg * */ import java.io.File; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.*; public class ExportTorrentWizardOutputPanel extends AbstractWizardPanel { protected boolean file_valid = false; public ExportTorrentWizardOutputPanel( Wizard wizard, IWizardPanel previous ) { super(wizard, previous); } public void show() { wizard.setTitle(MessageText.getString("exportTorrentWizard.exportfile.title")); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); Label label = new Label(panel, SWT.WRAP); gridData = new GridData(); gridData.horizontalSpan = 3; gridData.widthHint = 380; label.setLayoutData(gridData); Messages.setLanguageText(label, "exportTorrentWizard.exportfile.message"); label = new Label(panel,SWT.NULL); Messages.setLanguageText(label, "exportTorrentWizard.exportfile.path"); final Text textPath = new Text(panel,SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); textPath.setLayoutData(gridData); textPath.setText(((ExportTorrentWizard)wizard).getExportFile()); Button browse = new Button(panel,SWT.PUSH); Messages.setLanguageText(browse, "exportTorrentWizard.exportfile.browse"); browse.addListener(SWT.Selection,new Listener() { public void handleEvent(Event arg0){ FileDialog fd = new FileDialog(wizard.getWizardWindow(), SWT.SAVE ); fd.setFileName(textPath.getText()); fd.setFilterExtensions(new String[]{"*.xml", Constants.FILE_WILDCARD}); String path = fd.open(); if(path != null) { textPath.setText(path); } } }); textPath.addListener(SWT.Modify, new Listener(){ public void handleEvent(Event event) { String path = textPath.getText(); pathSet( path ); } }); textPath.setText(((ExportTorrentWizard)wizard).getExportFile()); textPath.setFocus(); } protected void pathSet( String path ) { ((ExportTorrentWizard)wizard).setExportFile( path ); file_valid = false; try { File f = new File(path); if(f.exists()){ if (f.isFile()){ wizard.setErrorMessage(""); file_valid = true; }else{ wizard.setErrorMessage(MessageText.getString("exportTorrentWizard.exportfile.invalidPath")); } }else{ wizard.setErrorMessage(""); file_valid = true; } } catch(Exception e){ wizard.setErrorMessage(MessageText.getString("exportTorrentWizard.exportfile.invalidPath")); } wizard.setFinishEnabled(file_valid); } public boolean isFinishEnabled() { return( file_valid ); } public boolean isFinishSelectionOK() { return( ((ExportTorrentWizard)wizard).performExport() ); } public IWizardPanel getFinishPanel(){ return new ExportTorrentWizardFinishPanel(((ExportTorrentWizard)wizard),this); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/associations/0000755000175000017500000000000011310377636022115 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/associations/AssociationChecker.java0000644000175000017500000001354411275141740026523 0ustar adrianadrian/* * Created on 23-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.associations; /** * @author parg * */ import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import org.gudy.azureus2.plugins.platform.PlatformManagerException; public class AssociationChecker { public static void checkAssociations() { try{ PlatformManager platform = PlatformManagerFactory.getPlatformManager(); if ( platform.hasCapability(PlatformManagerCapabilities.RegisterFileAssociations) ){ if ( COConfigurationManager.getBooleanParameter( "config.interface.checkassoc")){ if ( !platform.isApplicationRegistered()){ new AssociationChecker( platform ); } } } }catch( Throwable e ){ // Debug.printStackTrace( e ); } } protected PlatformManager platform; protected Display display; protected Shell shell; protected AssociationChecker( final PlatformManager _platform ) { platform = _platform; display = SWTThread.getInstance().getDisplay(); if ( display.isDisposed()){ return; } Utils.execSWTThread( new AERunnable() { public void runSupport() { check(); } }); } protected void check() { if (display.isDisposed()) return; shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); Utils.setShellIcon(shell); shell.setText(MessageText.getString("dialog.associations.title")); GridLayout layout = new GridLayout(); layout.numColumns = 3; shell.setLayout (layout); GridData gridData; // text Label user_label = new Label(shell,SWT.NULL); Messages.setLanguageText(user_label, "dialog.associations.prompt"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 3; user_label.setLayoutData(gridData); final Button checkBox = new Button(shell, SWT.CHECK); checkBox.setSelection(true); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 3; checkBox.setLayoutData(gridData); Messages.setLanguageText(checkBox, "dialog.associations.askagain"); // line Label labelSeparator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; labelSeparator.setLayoutData(gridData); // buttons new Label(shell,SWT.NULL); Button bYes = new Button(shell,SWT.PUSH); bYes.setText(MessageText.getString("Button.yes")); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.HORIZONTAL_ALIGN_FILL); gridData.grabExcessHorizontalSpace = true; gridData.widthHint = 70; bYes.setLayoutData(gridData); bYes.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { close(true, checkBox.getSelection()); } }); Button bNo = new Button(shell,SWT.PUSH); bNo.setText(MessageText.getString("Button.no")); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); gridData.grabExcessHorizontalSpace = false; gridData.widthHint = 70; bNo.setLayoutData(gridData); bNo.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { close(false, checkBox.getSelection()); } }); bYes.setFocus(); shell.setDefaultButton( bYes ); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ close( false, true ); } } }); shell.pack (); Utils.centreWindow( shell ); shell.open (); /* * parg - removed this as causing UI hang when assoc checker and key-unlock dialogs * open together while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } */ } protected void close( boolean ok, boolean check_on_startup ) { if ( check_on_startup != COConfigurationManager.getBooleanParameter( "config.interface.checkassoc" )){ COConfigurationManager.setParameter( "config.interface.checkassoc",check_on_startup ); COConfigurationManager.save(); } if ( ok ){ try{ platform.registerApplication(); }catch( PlatformManagerException e ){ Debug.printStackTrace( e ); } } shell.dispose(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/BlockedIpsWindow.java0000644000175000017500000002267110735653622023502 0ustar adrianadrian/* * File : BlockedIpsWindow.java * Created : 17 d�c. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import com.aelitis.azureus.core.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.ipfilter.*; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.DisplayFormatters; /** * @author Olivier * */ public class BlockedIpsWindow { static AzureusCore azureus_core; static Shell instance; private BlockedIpsWindow(){} public static void show( AzureusCore _azureus_core, Display display, String ipsBlocked, String ipsBanned) { if(instance == null || instance.isDisposed()) { instance = create(_azureus_core, display, ipsBlocked, ipsBanned); instance.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent event) { instance = null; } }); } else { instance.open(); } } private static Shell create( AzureusCore _azureus_core, Display display, String ipsBlocked, String ipsBanned) { azureus_core = _azureus_core; final int styles; if(Constants.isOSX) { styles = SWT.SHELL_TRIM; } else { styles = SWT.DIALOG_TRIM | SWT.MAX | SWT.RESIZE | SWT.APPLICATION_MODAL; } final Shell window = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(display,styles); Messages.setLanguageText(window,"ConfigView.section.ipfilter.list.title"); Utils.setShellIcon(window); FormLayout layout = new FormLayout(); try { layout.spacing = 5; } catch (NoSuchFieldError e) { /* Ignore for Pre 3.0 SWT.. */ } layout.marginHeight = 5; layout.marginWidth = 5; window.setLayout(layout); FormData formData; // text blocked area final StyledText textBlocked = new StyledText(window,SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); Button btnClear = new Button(window,SWT.PUSH); textBlocked.setEditable(false); final StyledText textBanned = new StyledText(window,SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); Button btnOk = new Button(window,SWT.PUSH); Button btnReset = new Button(window,SWT.PUSH); textBanned.setEditable(false); formData = new FormData(); formData.left = new FormAttachment(0,0); formData.right = new FormAttachment(100,0); formData.top = new FormAttachment(0,0); formData.bottom = new FormAttachment(40,0); textBlocked.setLayoutData(formData); textBlocked.setText(ipsBlocked); // label blocked area Label blockedInfo = new Label(window, SWT.NULL); Messages.setLanguageText(blockedInfo,"ConfigView.section.ipfilter.blockedinfo"); formData = new FormData(); formData.top = new FormAttachment(textBlocked); formData.right = new FormAttachment(btnClear); formData.left = new FormAttachment(0,0); blockedInfo.setLayoutData( formData ); // clear button Messages.setLanguageText(btnClear,"Button.clear"); formData = new FormData(); formData.top = new FormAttachment(textBlocked); formData.right = new FormAttachment(95,0 ); //formData.bottom = new FormAttachment(textBanned); formData.width = 70; btnClear.setLayoutData(formData); btnClear.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { azureus_core.getIpFilterManager().getIPFilter().clearBlockedIPs(); textBlocked.setText( "" ); } }); // text banned area formData = new FormData(); formData.left = new FormAttachment(0,0); formData.right = new FormAttachment(100,0); formData.top = new FormAttachment(btnClear); formData.bottom = new FormAttachment(btnOk); textBanned.setLayoutData(formData); textBanned.setText(ipsBanned); // label banned area Label bannedInfo = new Label(window, SWT.NULL); Messages.setLanguageText(bannedInfo,"ConfigView.section.ipfilter.bannedinfo"); formData = new FormData(); formData.right = new FormAttachment(btnReset); formData.left = new FormAttachment(0,0); formData.bottom = new FormAttachment(100,0); bannedInfo.setLayoutData( formData ); // reset button Messages.setLanguageText(btnReset,"Button.reset"); formData = new FormData(); formData.right = new FormAttachment(btnOk); formData.bottom = new FormAttachment(100,0); formData.width = 70; btnReset.setLayoutData(formData); btnReset.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { azureus_core.getIpFilterManager().getIPFilter().clearBannedIps(); azureus_core.getIpFilterManager().getBadIps().clearBadIps(); textBanned.setText( "" ); } }); // ok button Messages.setLanguageText(btnOk,"Button.ok"); formData = new FormData(); formData.right = new FormAttachment(95,0); formData.bottom = new FormAttachment(100,0); formData.width = 70; btnOk.setLayoutData(formData); btnOk.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { window.dispose(); } }); window.setDefaultButton( btnOk ); window.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ window.dispose(); } } }); if (!Utils.linkShellMetricsToConfig(window, "BlockedIpsWindow")) { window.setSize(620, 450); if (!Constants.isOSX) Utils.centreWindow(window); } window.layout(); window.open(); return window; } public static void showBlockedIps( AzureusCore azureus_core, Shell mainWindow) { StringBuffer sbBlocked = new StringBuffer(); StringBuffer sbBanned = new StringBuffer(); BlockedIp[] blocked = azureus_core.getIpFilterManager().getIPFilter().getBlockedIps(); String inRange = MessageText.getString("ConfigView.section.ipfilter.list.inrange"); String notInRange = MessageText.getString("ConfigView.section.ipfilter.list.notinrange"); String bannedMessage = MessageText.getString( "ConfigView.section.ipfilter.list.banned" ); String badDataMessage = MessageText.getString( "ConfigView.section.ipfilter.list.baddata" ); for(int i=0;i 0 ){ for (int i = 0; i < candidates.length; i++) { if(candidates[i].getValue() != null && candidates[i].getDecoder().getName().equals( default_name )) { return( candidates[i] ); } } } } ArrayList choosableCandidates = new ArrayList(); // Always stick the default candidate in position 0 if valid if ( defaultString != null ){ choosableCandidates.add( default_candidate ); } LocaleUtilDecoder[] general_decoders = locale_util.getGeneralDecoders(); // add all general candidates with names not already in the list for (int j = 0; j < general_decoders.length; j++) { for (int i = 0; i < candidates.length; i++) { if (candidates[i].getValue()==null || candidates[i].getDecoder()==null) continue; if( general_decoders[j] != null && general_decoders[j].getName().equals(candidates[i].getDecoder().getName())){ if (!choosableCandidates.contains(candidates[i])) { choosableCandidates.add(candidates[i]); break; } } } } // add the remaining possible locales for (int i = 0; i < candidates.length; i++){ if (candidates[i].getValue()==null || candidates[i].getDecoder()==null) continue; if (!choosableCandidates.contains(candidates[i])){ choosableCandidates.add(candidates[i]); } } final LocaleUtilDecoderCandidate[] candidatesToChoose = (LocaleUtilDecoderCandidate[]) choosableCandidates.toArray(new LocaleUtilDecoderCandidate[choosableCandidates.size()]); final LocaleUtilDecoderCandidate[] selected_candidate = {null}; // Run Synchronously, since we want the results Utils.execSWTThread(new AERunnable() { public void runSupport() { try{ showChoosableEncodingWindow(Utils.findAnyShell(), candidatesToChoose,selected_candidate); }catch( Throwable e ){ Debug.printStackTrace( e ); } } }, false); if ( selected_candidate[0] == null ){ throw( new LocaleUtilEncodingException( true )); }else{ return ( selected_candidate[0] ); } } private void showChoosableEncodingWindow( final Shell shell, final LocaleUtilDecoderCandidate[] candidates, final LocaleUtilDecoderCandidate[] selected_candidate ) { final Shell s = org.gudy.azureus2.ui.swt.components.shell.ShellFactory .createShell(shell, SWT.RESIZE | SWT.DIALOG_TRIM | SWT.PRIMARY_MODAL); Utils.setShellIcon(s); s.setText(MessageText.getString("LocaleUtil.title")); //$NON-NLS-1$ GridData gridData; s.setLayout(new GridLayout(1, true)); Label label = new Label(s, SWT.LEFT); Messages.setLanguageText(label, "LocaleUtil.label.chooseencoding"); //$NON-NLS-1$ final Table table = new Table(s, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL); gridData = new GridData( GridData.FILL_BOTH ); table.setLayoutData(gridData); table.setLinesVisible(true); table.setHeaderVisible(true); String[] titlesPieces = { "encoding", "text" }; for (int i = 0; i < titlesPieces.length; i++) { TableColumn column = new TableColumn(table, SWT.LEFT); Messages.setLanguageText(column, "LocaleUtil.column." + titlesPieces[i]); } // add candidates to table for (int i = 0; i < candidates.length; i++) { TableItem item = new TableItem(table, SWT.NULL); String name = candidates[i].getDecoder().getName(); item.setText(0, name); item.setText(1, candidates[i].getValue()); } int lastSelectedIndex = 0; for (int i = 1; i < candidates.length; i++) { if(candidates[i].getValue() != null && candidates[i].getDecoder() == rememberedDecoder ) { lastSelectedIndex = i; break; } } table.select(lastSelectedIndex); // resize all columns to fit the widest entry table.getColumn(0).pack(); table.getColumn(1).pack(); label = new Label(s, SWT.LEFT); Messages.setLanguageText(label, "LocaleUtil.label.hint.doubleclick"); //$NON-NLS-1$ Composite composite = new Composite(s,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); composite.setLayoutData(gridData); GridLayout subLayout = new GridLayout(); subLayout.numColumns = 2; composite.setLayout(subLayout); final Button checkBox = new Button(composite, SWT.CHECK); checkBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); checkBox.setSelection(rememberEncodingDecision); Messages.setLanguageText(checkBox, "LocaleUtil.label.checkbox.rememberdecision"); //$NON-NLS-1$, "LocaleUtil.label.checkbox.rememberdecision"); //$NON-NLS-1$ final Button ok = new Button(composite, SWT.PUSH); ok.setText(" ".concat(MessageText.getString("Button.next")).concat(" ")); //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$ gridData = new GridData(GridData.END); gridData.widthHint = 100; ok.setLayoutData(gridData); s.setSize(500,500); s.layout(); Utils.centreWindow(s); ok.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { //abandonSelection(s); setSelectedIndex(s, table, checkBox, candidates,selected_candidate); s.dispose(); } }); table.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent mEvent) { setSelectedIndex(s, table, checkBox, candidates,selected_candidate); s.dispose(); } }); s.open(); while (!s.isDisposed()) { if (!s.getDisplay().readAndDispatch()) { s.getDisplay().sleep(); } } } private void setSelectedIndex( final Shell s, final Table table, final Button checkBox, LocaleUtilDecoderCandidate[] candidates, LocaleUtilDecoderCandidate[] selected_candidate ) { int selectedIndex = table.getSelectionIndex(); if(-1 == selectedIndex) return; rememberEncodingDecision = checkBox.getSelection(); selected_candidate[0] = candidates[selectedIndex]; if ( rememberEncodingDecision ){ rememberedDecoder = selected_candidate[0].getDecoder(); }else{ rememberedDecoder = null; } s.dispose(); } private void abandonSelection( final Shell s) { s.dispose(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/TextViewerWindow.java0000644000175000017500000000637111012724262023554 0ustar adrianadrian/* * Created on 2 feb. 2004 * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; public class TextViewerWindow { public TextViewerWindow(String sTitleID, String sMessageID, String sText) { final Display display = SWTThread.getInstance().getDisplay(); final Shell shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(display, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); if (sTitleID != null) shell.setText(MessageText.keyExists(sTitleID)?MessageText.getString(sTitleID):sTitleID); Utils.setShellIcon(shell); GridLayout layout = new GridLayout(); shell.setLayout(layout); Label label = new Label(shell, SWT.NONE); if (sMessageID != null) label.setText(MessageText.keyExists(sMessageID)?MessageText.getString(sMessageID):sMessageID); GridData gridData = new GridData(); gridData.widthHint = 200; label.setLayoutData(gridData); final Text txtInfo = new Text(shell, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL); gridData = new GridData(); gridData.widthHint = 300; txtInfo.setLayoutData(gridData); txtInfo.setText(sText); Button ok = new Button(shell, SWT.PUSH); ok.setText(MessageText.getString("Button.ok")); gridData = new GridData(); gridData.widthHint = 70; ok.setLayoutData(gridData); shell.setDefaultButton(ok); ok.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { try { shell.dispose(); } catch (Exception e) { Debug.printStackTrace( e ); } } }); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ shell.dispose(); } } }); shell.pack(); Utils.centreWindow( shell ); shell.open(); while (!shell.isDisposed()) if (!display.readAndDispatch()) display.sleep(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/Utils.java0000644000175000017500000017074711300671560021371 0ustar adrianadrian/* * File : Utils.java * Created : 25 sept. 2003 16:15:07 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt; import java.io.File; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.dnd.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.program.Program; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.util.Timer; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.plugins.platform.PlatformManagerException; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author Olivier * */ public class Utils { public static final String GOOD_STRING = "(/|,jI~`gy"; public static final boolean isGTK = SWT.getPlatform().equals("gtk"); public static final boolean isCarbon = SWT.getPlatform().equals("carbon"); public static final boolean isCocoa = SWT.getPlatform().equals("cocoa"); /** Some platforms expand the last column to fit the remaining width of * the table. */ public static final boolean LAST_TABLECOLUMN_EXPANDS = isGTK; /** GTK already handles alternating background for tables */ public static final boolean TABLE_GRIDLINE_IS_ALTERNATING_COLOR = isGTK; /** * Debug/Diagnose SWT exec calls. Provides usefull information like how * many we are queuing up, and how long each call takes. Good to turn on * occassionally to see if we coded something stupid. */ private static final boolean DEBUG_SWTEXEC = System.getProperty( "debug.swtexec", "0").equals("1"); private static ArrayList queue; private static AEDiagnosticsLogger diag_logger; private static Image[] shellIcons = null; private static Image icon128; private final static String[] shellIconNames = { "azureus", "azureus32", "azureus64", "azureus128" }; public static final Rectangle EMPTY_RECT = new Rectangle(0, 0, 0, 0); static { if (DEBUG_SWTEXEC) { queue = new ArrayList(); diag_logger = AEDiagnostics.getLogger("swt"); diag_logger.log("\n\nSWT Logging Starts"); AEDiagnostics.addEvidenceGenerator(new AEDiagnosticsEvidenceGenerator(){ public void generate(IndentWriter writer) { writer.println("SWT Queue:"); writer.indent(); for (Runnable r : queue) { writer.println(r.toString()); } writer.exdent(); } }); } else { queue = null; diag_logger = null; } } public static boolean isAZ2UI() { String ui_type = COConfigurationManager.getStringParameter("ui"); return (ui_type.equals("az2")); } public static void disposeComposite(Composite composite, boolean disposeSelf) { if (composite == null || composite.isDisposed()) return; Control[] controls = composite.getChildren(); for (int i = 0; i < controls.length; i++) { Control control = controls[i]; if (control != null && !control.isDisposed()) { if (control instanceof Composite) { disposeComposite((Composite) control, true); } try { control.dispose(); } catch (SWTException e) { Debug.printStackTrace(e); } } } // It's possible that the composite was destroyed by the child if (!composite.isDisposed() && disposeSelf) try { composite.dispose(); } catch (SWTException e) { Debug.printStackTrace(e); } } public static void disposeComposite(Composite composite) { disposeComposite(composite, true); } /** * Dispose of a list of SWT objects * * @param disposeList */ public static void disposeSWTObjects(List disposeList) { disposeSWTObjects(disposeList.toArray()); disposeList.clear(); } public static void disposeSWTObjects(Object[] disposeList) { if (disposeList == null) { return; } for (int i = 0; i < disposeList.length; i++) { Object o = disposeList[i]; if (o instanceof Widget && !((Widget) o).isDisposed()) ((Widget) o).dispose(); else if ((o instanceof Resource) && !((Resource) o).isDisposed()) { ((Resource) o).dispose(); } } } /** * Initializes the URL dialog with http:// * If a valid link is found in the clipboard, it will be inserted * and the size (and location) of the dialog is adjusted. * @param shell to set the dialog location if needed * @param url the URL text control * @param accept_magnets * * @author Rene Leonhardt */ public static void setTextLinkFromClipboard(final Shell shell, final Text url, boolean accept_magnets) { String link = getLinkFromClipboard(shell.getDisplay(), accept_magnets); if (link != null) url.setText(link); } /** *

    Gets an URL from the clipboard if a valid URL for downloading has been copied.

    *

    The supported protocols currently are http, https, and magnet.

    * @param display * @param accept_magnets * @return first valid link from clipboard, else "http://" */ public static String getLinkFromClipboard(Display display, boolean accept_magnets) { final Clipboard cb = new Clipboard(display); final TextTransfer transfer = TextTransfer.getInstance(); String data = (String) cb.getContents(transfer); String text = UrlUtils.parseTextForURL(data, accept_magnets); if (text == null) { return "http://"; } return text; } public static void centreWindow(Shell shell) { Rectangle displayArea; // area to center in if (shell.getParent() != null) { displayArea = shell.getParent().getBounds(); } else { try { displayArea = shell.getMonitor().getClientArea(); } catch (NoSuchMethodError e) { displayArea = shell.getDisplay().getClientArea(); } } Rectangle shellRect = shell.getBounds(); if (shellRect.height > displayArea.height) { shellRect.height = displayArea.height; } if (shellRect.width > displayArea.width - 50) { shellRect.width = displayArea.width; } shellRect.x = displayArea.x + (displayArea.width - shellRect.width) / 2; shellRect.y = displayArea.y + (displayArea.height - shellRect.height) / 2; shell.setBounds(shellRect); } /** * Centers a window relative to a control. That is to say, the window will be located at the center of the control. * @param window * @param control */ public static void centerWindowRelativeTo(final Shell window, final Control control) { final Rectangle bounds = control.getBounds(); final Point shellSize = window.getSize(); window.setLocation(bounds.x + (bounds.width / 2) - shellSize.x / 2, bounds.y + (bounds.height / 2) - shellSize.y / 2); } public static void createTorrentDropTarget(Composite composite, boolean bAllowShareAdd) { try { createDropTarget(composite, bAllowShareAdd, null); } catch (Exception e) { Debug.out(e); } } /** * @param control the control (usually a Shell) to add the DropTarget * @param url the Text control where to set the link text * * @author Rene Leonhardt */ public static void createURLDropTarget(Composite composite, Text url) { try { createDropTarget(composite, false, url); } catch (Exception e) { Debug.out(e); } } private static void createDropTarget(Composite composite, final boolean bAllowShareAdd, final Text url, DropTargetListener dropTargetListener) { Transfer[] transferList = new Transfer[] { HTMLTransfer.getInstance(), URLTransfer.getInstance(), FileTransfer.getInstance(), TextTransfer.getInstance() }; final DropTarget dropTarget = new DropTarget(composite, DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_TARGET_MOVE); dropTarget.setTransfer(transferList); dropTarget.addDropListener(dropTargetListener); // Note: DropTarget will dipose when the parent it's on diposes // On Windows, dropping on children moves up to parent // On OSX, each child needs it's own drop. if (Constants.isWindows) return; Control[] children = composite.getChildren(); for (int i = 0; i < children.length; i++) { Control control = children[i]; if (!control.isDisposed()) { if (control instanceof Composite) { createDropTarget((Composite) control, bAllowShareAdd, url, dropTargetListener); } else { final DropTarget dropTarget2 = new DropTarget(control, DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_TARGET_MOVE); dropTarget2.setTransfer(transferList); dropTarget2.addDropListener(dropTargetListener); } } } } private static void createDropTarget(Composite composite, boolean bAllowShareAdd, Text url) { URLDropTarget target = new URLDropTarget(url, bAllowShareAdd); createDropTarget(composite, bAllowShareAdd, url, target); } private static class URLDropTarget extends DropTargetAdapter { private final Text url; private final boolean bAllowShareAdd; public URLDropTarget(Text url, boolean bAllowShareAdd) { this.url = url; this.bAllowShareAdd = bAllowShareAdd; } public void dropAccept(DropTargetEvent event) { event.currentDataType = URLTransfer.pickBestType(event.dataTypes, event.currentDataType); } public void dragOver(DropTargetEvent event) { // skip setting detail if user is forcing a drop type (ex. via the // ctrl key), providing that the operation is valid if (event.detail != DND.DROP_DEFAULT && ((event.operations & event.detail) > 0)) return; if ((event.operations & DND.DROP_LINK) > 0) event.detail = DND.DROP_LINK; else if ((event.operations & DND.DROP_DEFAULT) > 0) event.detail = DND.DROP_DEFAULT; else if ((event.operations & DND.DROP_COPY) > 0) event.detail = DND.DROP_COPY; } public void drop(DropTargetEvent event) { if (url == null || url.isDisposed()) { TorrentOpener.openDroppedTorrents(event, bAllowShareAdd); } else { if (event.data instanceof URLTransfer.URLType) { if (((URLTransfer.URLType) event.data).linkURL != null) url.setText(((URLTransfer.URLType) event.data).linkURL); } else if (event.data instanceof String) { String sURL = UrlUtils.parseTextForURL((String) event.data, true); if (sURL != null) { url.setText(sURL); } } } } } public static void alternateRowBackground(TableItem item) { if (Utils.TABLE_GRIDLINE_IS_ALTERNATING_COLOR) { if (!item.getParent().getLinesVisible()) item.getParent().setLinesVisible(true); return; } if (item == null || item.isDisposed()) return; Color[] colors = { item.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND), Colors.colorAltRow }; Color newColor = colors[item.getParent().indexOf(item) % colors.length]; if (!item.getBackground().equals(newColor)) { item.setBackground(newColor); } } // Yes, this is actually used by the RSSFeed plugin... // so don't make private until this is fixed public static void alternateTableBackground(Table table) { if (table == null || table.isDisposed()) return; if (Utils.TABLE_GRIDLINE_IS_ALTERNATING_COLOR) { if (!table.getLinesVisible()) table.setLinesVisible(true); return; } int iTopIndex = table.getTopIndex(); if (iTopIndex < 0) { return; } int iBottomIndex = getTableBottomIndex(table, iTopIndex); Color[] colors = { table.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND), Colors.colorAltRow }; int iFixedIndex = iTopIndex; for (int i = iTopIndex; i <= iBottomIndex; i++) { TableItem row = table.getItem(i); // Rows can be disposed! if (!row.isDisposed()) { Color newColor = colors[iFixedIndex % colors.length]; iFixedIndex++; if (!row.getBackground().equals(newColor)) { // System.out.println("setting "+rows[i].getBackground() +" to " + newColor); row.setBackground(newColor); } } } } /** *

    * Set a MenuItem's image with the given ImageRepository key. In compliance with platform * human interface guidelines, the images are not set under Mac OS X. *

    * @param item SWT MenuItem * @param repoKey ImageRepository image key * @see Apple HIG */ public static void setMenuItemImage(final MenuItem item, final String repoKey) { if (Constants.isOSX || repoKey == null) { return; } ImageLoader imageLoader = ImageLoader.getInstance(); item.setImage(imageLoader.getImage(repoKey)); item.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage(repoKey); } }); } public static void setMenuItemImage(final MenuItem item, final Image image) { if (!Constants.isOSX) item.setImage(image); } /** * Sets the shell's Icon(s) to the default Azureus icon. OSX doesn't require * an icon, so they are skipped * * @param shell */ public static void setShellIcon(Shell shell) { if (Constants.isOSX) { if (true) { return; } if (icon128 == null) { ImageLoader imageLoader = ImageLoader.getInstance(); icon128 = imageLoader.getImage("azureus128"); if (Constants.isCVSVersion()) { final int border = 9; Image image = Utils.createAlphaImage(shell.getDisplay(), 128 + (border * 2), 128 + (border * 2)); image = blitImage(shell.getDisplay(), icon128, null, image, new Point(border, border + 1)); imageLoader.releaseImage("azureus128"); icon128 = image; // GC gc = new GC(icon128); // gc.setTextAntialias(SWT.ON); // gc.setForeground(shell.getDisplay().getSystemColor(SWT.COLOR_YELLOW)); // Font font = getFontWithHeight(gc.getFont(), gc, 20, SWT.BOLD); // gc.setFont(font); // GCStringPrinter.printString(gc, Constants.AZUREUS_VERSION, // new Rectangle(0, 0, 128, 128), false, false, SWT.CENTER // | SWT.BOTTOM); // gc.dispose(); // font.dispose(); } } shell.setImage(icon128); return; } try { if (shellIcons == null) { ArrayList listShellIcons = new ArrayList( shellIconNames.length); ImageLoader imageLoader = ImageLoader.getInstance(); for (int i = 0; i < shellIconNames.length; i++) { // never release images since they are always used and stored // in an array Image image = imageLoader.getImage(shellIconNames[i]); if (ImageLoader.isRealImage(image)) { listShellIcons.add(image); } } shellIcons = (Image[]) listShellIcons.toArray(new Image[listShellIcons.size()]); } shell.setImages(shellIcons); } catch (NoSuchMethodError e) { // SWT < 3.0 } } public static Display getDisplay() { SWTThread swt = SWTThread.getInstance(); Display display; if (swt == null) { display = Display.getDefault(); if (display == null) { System.err.println("SWT Thread not started yet!"); return null; } } else { if (swt.isTerminated()) { return null; } display = swt.getDisplay(); } if (display == null || display.isDisposed()) { return null; } return display; } /** * Execute code in the Runnable object using SWT's thread. If current * thread it already SWT's thread, the code will run immediately. If the * current thread is not SWT's, code will be run either synchronously or * asynchronously on SWT's thread at the next reasonable opportunity. * * This method does not catch any exceptions. * * @param code code to run * @param async true if SWT asyncExec, false if SWT syncExec * @return success */ public static boolean execSWTThread(final Runnable code, boolean async) { return execSWTThread(code, async ? -1 : -2); } /** * Schedule execution of the code in the Runnable object using SWT's thread. * Even if the current thread is the SWT Thread, the code will be scheduled. *

    * Much like Display.asyncExec, except getting the display is handled for you, * and provides the ability to diagnose and monitor scheduled code run. * * @param msLater time to wait before running code on SWT thread. 0 does not * mean immediate, but as soon as possible. * @param code Code to run * @return sucess * * @since 3.0.4.3 */ public static boolean execSWTThreadLater(int msLater, final Runnable code) { return execSWTThread(code, msLater); } /** * * @param code * @param msLater -2: sync
    * -1: sync if on SWT thread, async otherwise
    * 0: async
    * >0: timerExec * @return * * @since 3.0.4.3 */ private static boolean execSWTThread(final Runnable code, final int msLater) { final Display display = getDisplay(); if (display == null || code == null) { return false; } boolean isSWTThread = display.getThread() == Thread.currentThread(); if (msLater < 0 && isSWTThread) { if (queue == null) { code.run(); } else { long lStartTimeRun = SystemTime.getCurrentTime(); code.run(); long wait = SystemTime.getCurrentTime() - lStartTimeRun; if (wait > 700) { diag_logger.log(SystemTime.getCurrentTime() + "] took " + wait + "ms to run " + Debug.getCompressedStackTrace()); } } } else if (msLater >= -1) { try { if (queue == null) { if (msLater <= 0) { display.asyncExec(code); } else { if(isSWTThread) { display.timerExec(msLater, code); } else { SimpleTimer.addEvent("execSWTThreadLater", SystemTime.getOffsetTime(msLater), new TimerEventPerformer() { public void perform(TimerEvent event) { if (!display.isDisposed()) { display.asyncExec(code); } } }); } } } else { queue.add(code); diag_logger.log(SystemTime.getCurrentTime() + "] + Q. size= " + queue.size() + "; add " + code + " via " + Debug.getCompressedStackTrace()); final long lStart = SystemTime.getCurrentTime(); final Display fDisplay = display; AERunnable runnableWrapper = new AERunnable() { public void runSupport() { long wait = SystemTime.getCurrentTime() - lStart - msLater; if (wait > 700) { diag_logger.log(SystemTime.getCurrentTime() + "] took " + wait + "ms before SWT ran async code " + code); } long lStartTimeRun = SystemTime.getCurrentTime(); try { if (fDisplay.isDisposed()) { Debug.out("Display disposed while trying to execSWTThread " + code); // run anayway, except trap SWT error try { code.run(); } catch (SWTException e) { Debug.out("Error while execSWTThread w/disposed Display", e); } } else { code.run(); } } finally { long runTIme = SystemTime.getCurrentTime() - lStartTimeRun; if (runTIme > 500) { diag_logger.log(SystemTime.getCurrentTime() + "] took " + runTIme + "ms to run " + code); } queue.remove(code); if (runTIme > 10) { diag_logger.log(SystemTime.getCurrentTime() + "] - Q. size=" + queue.size() + ";wait:" + wait + "ms;run:" + runTIme + "ms " + code); } else { diag_logger.log(SystemTime.getCurrentTime() + "] - Q. size=" + queue.size() + ";wait:" + wait + "ms;run:" + runTIme + "ms"); } } } }; if (msLater <= 0) { display.asyncExec(runnableWrapper); } else { if(isSWTThread) { display.timerExec(msLater, code); } else { SimpleTimer.addEvent("execSWTThreadLater", SystemTime.getOffsetTime(msLater), new TimerEventPerformer() { public void perform(TimerEvent event) { if (!display.isDisposed()) { display.asyncExec(code); } } }); } } } } catch (NullPointerException e) { // If the display is being disposed of, asyncExec may give a null // pointer error return false; } } else { display.syncExec(code); } return true; } /** * Execute code in the Runnable object using SWT's thread. If current * thread it already SWT's thread, the code will run immediately. If the * current thread is not SWT's, code will be run asynchronously on SWT's * thread at the next reasonable opportunity. * * This method does not catch any exceptions. * * @param code code to run * @return success */ public static boolean execSWTThread(Runnable code) { return execSWTThread(code, -1); } public static boolean isThisThreadSWT() { SWTThread swt = SWTThread.getInstance(); if (swt == null) { System.err.println("WARNING: SWT Thread not started yet"); } Display display = (swt == null) ? Display.getCurrent() : swt.getDisplay(); if (display == null) { return false; } // This will throw if we are disposed or on the wrong thread // Much better that display.getThread() as that one locks Device.class // and may end up causing sync lock when disposing try { display.getWarnings(); } catch (SWTException e) { return false; } return (display.getThread() == Thread.currentThread()); } /** * Bottom Index may be negative. Returns bottom index even if invisible. */ public static int getTableBottomIndex(Table table, int iTopIndex) { // on Linux, getItemHeight is slow AND WRONG. so is getItem(x).getBounds().y // getItem(Point) is slow on OSX // On Windows, in rare cases, getItem(Point(2,y)) doesn't return the item // (such as within a paint event) int itemCount = table.getItemCount(); if (iTopIndex >= itemCount || iTopIndex < 0) return -1; if (Constants.isOSX || Constants.isWindows) { try { TableItem item = table.getItem(iTopIndex); Rectangle bounds = item.getBounds(); Rectangle clientArea = table.getClientArea(); int itemHeight = table.getItemHeight(); int iBottomIndex = Math.min(iTopIndex + (clientArea.height + clientArea.y - bounds.y - 1) / itemHeight, itemCount - 1); // System.out.println(bounds + ";" + clientArea + ";" + itemHeight + ";bi=" // + iBottomIndex + ";ti=" + iTopIndex + ";" // + (clientArea.height + clientArea.y - bounds.y - 1)); return iBottomIndex; } catch (NoSuchMethodError e) { // item.getBounds is 3.2 return Math.min( iTopIndex + ((table.getClientArea().height - table.getHeaderHeight() - 1) / table.getItemHeight()) + 1, table.getItemCount() - 1); } } // getItem will return null if clientArea's height is smaller than // header height. int areaHeight = table.getClientArea().height; if (areaHeight <= table.getHeaderHeight()) return -1; // 2 offset to be on the safe side TableItem bottomItem = table.getItem(new Point(2, table.getClientArea().height - 1)); int iBottomIndex = (bottomItem != null) ? table.indexOf(bottomItem) : itemCount - 1; return iBottomIndex; } public static void launch(String sFile) { if (sFile == null || sFile.trim().length() == 0) { return; } if (!Constants.isWindows && new File(sFile).isDirectory()) { PlatformManager mgr = PlatformManagerFactory.getPlatformManager(); if (mgr.hasCapability(PlatformManagerCapabilities.ShowFileInBrowser)) { try { PlatformManagerFactory.getPlatformManager().showFile(sFile); return; } catch (PlatformManagerException e) { } } } boolean launched = Program.launch(sFile); if (!launched && Constants.isUnix) { if (!Program.launch("xdg-open " + sFile)) { Program.launch("htmlview " + sFile); } } } /** * Sets the checkbox in a Virtual Table while inside a SWT.SetData listener * trigger. SWT 3.1 has an OSX bug that needs working around. * * @param item * @param checked */ public static void setCheckedInSetData(final TableItem item, final boolean checked) { item.setChecked(checked); if (Constants.isWindowsXP || isGTK) { Rectangle r = item.getBounds(0); Table table = item.getParent(); Rectangle rTable = table.getClientArea(); table.redraw(0, r.y, rTable.width, r.height, true); } } public static boolean linkShellMetricsToConfig(final Shell shell, final String sConfigPrefix) { boolean isMaximized = COConfigurationManager.getBooleanParameter(sConfigPrefix + ".maximized"); if (!isMaximized) { shell.setMaximized(false); } String windowRectangle = COConfigurationManager.getStringParameter( sConfigPrefix + ".rectangle", null); boolean bDidResize = false; if (null != windowRectangle) { int i = 0; int[] values = new int[4]; StringTokenizer st = new StringTokenizer(windowRectangle, ","); try { while (st.hasMoreTokens() && i < 4) { values[i++] = Integer.valueOf(st.nextToken()).intValue(); } if (i == 4) { Rectangle shellBounds = new Rectangle(values[0], values[1], values[2], values[3]); shell.setBounds(shellBounds); verifyShellRect(shell, true); bDidResize = true; } } catch (Exception e) { } } if (isMaximized) { shell.setMaximized(isMaximized); } new ShellMetricsResizeListener(shell, sConfigPrefix); return bDidResize; } private static class ShellMetricsResizeListener implements Listener { private int state = -1; private String sConfigPrefix; private Rectangle bounds = null; ShellMetricsResizeListener(Shell shell, String sConfigPrefix) { this.sConfigPrefix = sConfigPrefix; state = calcState(shell); if (state == SWT.NONE) bounds = shell.getBounds(); shell.addListener(SWT.Resize, this); shell.addListener(SWT.Move, this); shell.addListener(SWT.Dispose, this); } private int calcState(Shell shell) { return shell.getMinimized() ? SWT.MIN : shell.getMaximized() && !isCarbon ? SWT.MAX : SWT.NONE; } private void saveMetrics() { COConfigurationManager.setParameter(sConfigPrefix + ".maximized", state == SWT.MAX); if (bounds == null) return; COConfigurationManager.setParameter(sConfigPrefix + ".rectangle", bounds.x + "," + bounds.y + "," + bounds.width + "," + bounds.height); COConfigurationManager.save(); } public void handleEvent(Event event) { Shell shell = (Shell) event.widget; state = calcState(shell); if (event.type != SWT.Dispose && state == SWT.NONE) bounds = shell.getBounds(); if (event.type == SWT.Dispose) saveMetrics(); } } public static GridData setGridData(Composite composite, int gridStyle, Control ctrlBestSize, int maxHeight) { GridData gridData = new GridData(gridStyle); gridData.heightHint = ctrlBestSize.computeSize(SWT.DEFAULT, SWT.DEFAULT).y; if (gridData.heightHint > maxHeight && maxHeight > 0) gridData.heightHint = maxHeight; composite.setLayoutData(gridData); return gridData; } public static FormData getFilledFormData() { FormData formData = new FormData(); formData.top = new FormAttachment(0, 0); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.bottom = new FormAttachment(100, 0); return formData; } public static int pixelsToPoint(int pixels, int dpi) { int ret = (int) Math.round((pixels * 72.0) / dpi); return ret; } private static int pixelsToPoint(double pixels, int dpi) { int ret = (int) Math.round((pixels * 72.0) / dpi); return ret; } private static boolean drawImage(GC gc, Image image, Rectangle dstRect, Rectangle clipping, int hOffset, int vOffset, boolean clearArea) { return drawImage(gc, image, new Point(0, 0), dstRect, clipping, hOffset, vOffset, clearArea); } private static boolean drawImage(GC gc, Image image, Rectangle dstRect, Rectangle clipping, int hOffset, int vOffset) { return drawImage(gc, image, new Point(0, 0), dstRect, clipping, hOffset, vOffset, false); } public static boolean drawImage(GC gc, Image image, Point srcStart, Rectangle dstRect, Rectangle clipping, int hOffset, int vOffset, boolean clearArea) { Rectangle srcRect; Point dstAdj; if (clipping == null) { dstAdj = new Point(0, 0); srcRect = new Rectangle(srcStart.x, srcStart.y, dstRect.width, dstRect.height); } else { if (!dstRect.intersects(clipping)) { return false; } dstAdj = new Point(Math.max(0, clipping.x - dstRect.x), Math.max(0, clipping.y - dstRect.y)); srcRect = new Rectangle(0, 0, 0, 0); srcRect.x = srcStart.x + dstAdj.x; srcRect.y = srcStart.y + dstAdj.y; srcRect.width = Math.min(dstRect.width - dstAdj.x, clipping.x + clipping.width - dstRect.x); srcRect.height = Math.min(dstRect.height - dstAdj.y, clipping.y + clipping.height - dstRect.y); } if (!srcRect.isEmpty()) { try { if (clearArea) { gc.fillRectangle(dstRect.x + dstAdj.x + hOffset, dstRect.y + dstAdj.y + vOffset, srcRect.width, srcRect.height); } gc.drawImage(image, srcRect.x, srcRect.y, srcRect.width, srcRect.height, dstRect.x + dstAdj.x + hOffset, dstRect.y + dstAdj.y + vOffset, srcRect.width, srcRect.height); } catch (Exception e) { System.out.println("drawImage: " + e.getMessage() + ": " + image + ", " + srcRect + ", " + (dstRect.x + dstAdj.y + hOffset) + "," + (dstRect.y + dstAdj.y + vOffset) + "," + srcRect.width + "," + srcRect.height + "; imageBounds = " + image.getBounds()); } } return true; } /** * @param area * @param event id * @param listener */ public static void addListenerAndChildren(Composite area, int event, Listener listener) { area.addListener(event, listener); Control[] children = area.getChildren(); for (int i = 0; i < children.length; i++) { Control child = children[i]; if (child instanceof Composite) { addListenerAndChildren((Composite) child, event, listener); } else { child.addListener(event, listener); } } } public static Shell findAnyShell() { // Pick the main shell if we can UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { Shell shell = uiFunctions.getMainShell(); if (shell != null && !shell.isDisposed()) { return shell; } } // Get active shell from current display if we can Display current = Display.getCurrent(); if (current == null) { return null; } Shell shell = current.getActiveShell(); if (shell != null && !shell.isDisposed()) { return shell; } // Get first shell of current display if we can Shell[] shells = current.getShells(); if (shells.length == 0) { return null; } if (shells[0] != null && !shells[0].isDisposed()) { return shells[0]; } return null; } /** * @param listener */ public static boolean verifyShellRect(Shell shell, boolean bAdjustIfInvalid) { boolean bMetricsOk; try { bMetricsOk = false; Point ptTopLeft = shell.getLocation(); Monitor[] monitors = shell.getDisplay().getMonitors(); for (int j = 0; j < monitors.length && !bMetricsOk; j++) { Rectangle bounds = monitors[j].getBounds(); bMetricsOk = bounds.contains(ptTopLeft); } } catch (NoSuchMethodError e) { Rectangle bounds = shell.getDisplay().getBounds(); bMetricsOk = shell.getBounds().intersects(bounds); } if (!bMetricsOk && bAdjustIfInvalid) { centreWindow(shell); } return bMetricsOk; } /** * Relayout all composites up from control until there's enough room for the * control to fit * * @param control Control that had it's sized changed and needs more room */ public static void relayout(Control control) { relayout(control, false); } /** * Relayout all composites up from control until there's enough room for the * control to fit * * @param control Control that had it's sized changed and needs more room */ public static void relayout(Control control, boolean expandOnly) { if (control == null || control.isDisposed() || !control.isVisible()) { return; } Composite parent = control.getParent(); Point targetSize = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); Point size = control.getSize(); if (size.y == targetSize.y && size.x == targetSize.x) { return; } int fixedWidth = -1; int fixedHeight = -1; Object layoutData = control.getLayoutData(); if (layoutData instanceof FormData) { FormData fd = (FormData) layoutData; fixedHeight = fd.height; fixedWidth = fd.width; if (fd.width != SWT.DEFAULT && fd.height != SWT.DEFAULT) { parent.layout(); return; } } if (expandOnly && size.y >= targetSize.y && size.x >= targetSize.x) { parent.layout(); return; } while (parent != null) { parent.layout(true, true); parent = parent.getParent(); Point newSize = control.getSize(); //System.out.println("new=" + newSize + ";target=" + targetSize); if ((fixedHeight > -1 || (newSize.y >= targetSize.y)) && (fixedWidth > -1 || (newSize.x >= targetSize.x))) { break; } } if (parent != null) { parent.layout(); } } /** * */ public static void beep() { execSWTThread(new AERunnable() { public void runSupport() { Display display = Display.getDefault(); if (display != null) { display.beep(); } } }); } /** * * @param baseFont * @param gc Can be null * @param heightInPixels * @return * * @since 3.0.0.7 */ public static int getFontHeightFromPX(Font baseFont, GC gc, int heightInPixels) { Font font = null; Device device = baseFont.getDevice(); // hack.. heightInPixels++; // This isn't accurate, but gets us close int size = Utils.pixelsToPoint(heightInPixels, device.getDPI().y) + 1; if (size <= 0) { return 0; } boolean bOurGC = gc == null || gc.isDisposed(); try { if (bOurGC) { gc = new GC(device); } FontData[] fontData = baseFont.getFontData(); do { if (font != null) { size--; font.dispose(); } fontData[0].setHeight(size); font = new Font(device, fontData); gc.setFont(font); } while (gc.textExtent(GOOD_STRING).y > heightInPixels && size > 1); } finally { if (bOurGC) { gc.dispose(); } if (font != null && !font.isDisposed()) { font.dispose(); } } return size; } public static int getFontHeightFromPX(Device device, FontData[] fontData, GC gc, int heightInPixels) { Font font = null; // hack.. heightInPixels++; // This isn't accurate, but gets us close int size = Utils.pixelsToPoint(heightInPixels, device.getDPI().y) + 1; if (size <= 0) { return 0; } boolean bOurGC = gc == null || gc.isDisposed(); try { if (bOurGC) { gc = new GC(device); } do { if (font != null) { size--; font.dispose(); } fontData[0].setHeight(size); font = new Font(device, fontData); gc.setFont(font); } while (font != null && gc.textExtent(GOOD_STRING).y > heightInPixels && size > 1); } finally { if (bOurGC) { gc.dispose(); } if (font != null && !font.isDisposed()) { font.dispose(); } } return size; } public static Font getFontWithHeight(Font baseFont, GC gc, int heightInPixels) { return getFontWithHeight(baseFont, gc, heightInPixels, SWT.DEFAULT); } public static Font getFontWithHeight(Font baseFont, GC gc, int heightInPixels, int style) { Font font = null; Device device = baseFont.getDevice(); // hack.. heightInPixels++; // This isn't accurate, but gets us close int size = Utils.pixelsToPoint(heightInPixels, device.getDPI().y) + 1; if (size <= 0) { size = 2; } boolean bOurGC = gc == null || gc.isDisposed(); try { if (bOurGC) { gc = new GC(device); } FontData[] fontData = baseFont.getFontData(); do { if (font != null) { size--; font.dispose(); } fontData[0].setHeight(size); if (style != SWT.DEFAULT) { fontData[0].setStyle(style); } font = new Font(device, fontData); gc.setFont(font); } while (font != null && gc.textExtent(GOOD_STRING).y > heightInPixels && size > 1); } finally { if (bOurGC) { gc.dispose(); } } return font; } /** * @deprecated Use {@link #execSWTThread(AERunnableWithCallback)} to avoid * thread locking issues */ public static boolean execSWTThreadWithBool(String ID, AERunnableBoolean code) { return execSWTThreadWithBool(ID, code, 0); } /** * Runs code within the SWT thread, waits for code to complete executing, * (using a semaphore), and then returns a value. * * @note USE WITH CAUTION. If the calling function synchronizes, and the * runnable code ends up synchronizing on the same object, an indefinite * thread lock or an unexpected timeout may occur (if one of the threads * is the SWT thread).

    * ex - Thread1 calls c.foo(), which synchronized(this). * - Thread2 is the SWT Thread. Thread2 calls c.foo(), which waits on * Thread1 to complete. * - c.foo() from Thread1 calls execSWTThreadWithBoolean(.., swtcode, ..), * which waits for the SWT Thread to return run the swtcode. * - Deadlock, or Timoeout which returns a false (and no code ran) * * @param ID id for debug * @param code code to run * @param millis ms to timeout in * @return */ public static boolean execSWTThreadWithBool(String ID, AERunnableBoolean code, long millis) { if (code == null) { return false; } boolean[] returnValueObject = { false }; Display display = getDisplay(); AESemaphore sem = null; if (display == null || display.getThread() != Thread.currentThread()) { sem = new AESemaphore(ID); } try { code.setupReturn(ID, returnValueObject, sem); if (!execSWTThread(code)) { // code never got run // XXX: throw instead? return false; } } catch (Throwable e) { if (sem != null) { sem.release(); } Debug.out(ID, e); } if (sem != null) { sem.reserve(millis); } return returnValueObject[0]; } /** * @deprecated Use {@link #execSWTThread(AERunnableWithCallback)} to avoid * thread locking issues */ public static Object execSWTThreadWithObject(String ID, AERunnableObject code) { return execSWTThreadWithObject(ID, code, 0); } /** * Runs code within the SWT thread, waits for code to complete executing, * (using a semaphore), and then returns a value. * * @note USE WITH CAUTION. If the calling function synchronizes, and the * runnable code ends up synchronizing on the same object, an indefinite * thread lock or an unexpected timeout may occur (if one of the threads * is the SWT thread).

    * ex - Thread1 calls c.foo(), which synchronized(this). * - Thread2 is the SWT Thread. Thread2 calls c.foo(), which waits on * Thread1 to complete. * - c.foo() from Thread1 calls execSWTThreadWithObject(.., swtcode, ..), * which waits for the SWT Thread to return run the swtcode. * - Deadlock, or Timoeout which returns a null (and no code ran) * * @param ID id for debug * @param code code to run * @param millis ms to timeout in * @return */ public static Object execSWTThreadWithObject(String ID, AERunnableObject code, long millis) { if (code == null) { return null; } Object[] returnValueObject = { null }; Display display = getDisplay(); AESemaphore sem = null; if (display == null || display.getThread() != Thread.currentThread()) { sem = new AESemaphore(ID); } try { code.setupReturn(ID, returnValueObject, sem); if (!execSWTThread(code)) { // XXX: throw instead? return null; } } catch (Throwable e) { if (sem != null) { sem.release(); } Debug.out(ID, e); } if (sem != null) { sem.reserve(millis); } return returnValueObject[0]; } /** * Waits until modal dialogs are disposed. Assumes we are on SWT thread * * @since 3.0.1.3 */ public static void waitForModals() { SWTThread swt = SWTThread.getInstance(); Display display; if (swt == null) { display = Display.getDefault(); if (display == null) { System.err.println("SWT Thread not started yet!"); return; } } else { if (swt.isTerminated()) { return; } display = swt.getDisplay(); } if (display == null || display.isDisposed()) { return; } Shell[] shells = display.getShells(); Shell modalShell = null; for (int i = 0; i < shells.length; i++) { Shell shell = shells[i]; if ((shell.getStyle() & SWT.APPLICATION_MODAL) > 0) { modalShell = shell; break; } } if (modalShell != null) { while (!modalShell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } } public static GridData getWrappableLabelGridData(int hspan, int styles) { GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | styles); gridData.horizontalSpan = hspan; gridData.widthHint = 0; return gridData; } private static Image createAlphaImage(Device device, int width, int height) { return createAlphaImage(device, width, height, (byte) 0); } public static Image createAlphaImage(Device device, int width, int height, byte defaultAlpha) { byte[] alphaData = new byte[width * height]; Arrays.fill(alphaData, 0, alphaData.length, (byte) defaultAlpha); ImageData imageData = new ImageData(width, height, 24, new PaletteData( 0xFF, 0xFF00, 0xFF0000)); Arrays.fill(imageData.data, 0, imageData.data.length, (byte) 0); imageData.alphaData = alphaData; Image image = new Image(device, imageData); return image; } public static Image blitImage(Device device, Image srcImage, Rectangle srcArea, Image dstImage, Point dstPos) { if (srcArea == null) { srcArea = srcImage.getBounds(); } Rectangle dstBounds = dstImage.getBounds(); if (dstPos == null) { dstPos = new Point(dstBounds.x, dstBounds.y); } else { dstBounds.x = dstPos.x; dstBounds.y = dstPos.y; } ImageData dstImageData = dstImage.getImageData(); ImageData srcImageData = srcImage.getImageData(); int yPos = dstPos.y; int[] pixels = new int[srcArea.width]; byte[] alphas = new byte[srcArea.width]; for (int y = 0; y < srcArea.height; y++) { srcImageData.getPixels(srcArea.x, y + srcArea.y, srcArea.width, pixels, 0); dstImageData.setPixels(dstPos.x, yPos, srcArea.width, pixels, 0); srcImageData.getAlphas(srcArea.x, y + srcArea.y, srcArea.width, alphas, 0); dstImageData.setAlphas(dstPos.x, yPos, srcArea.width, alphas, 0); yPos++; } return new Image(device, dstImageData); } /** * Draws diagonal stripes onto the specified area of a GC * @param lineDist spacing between the individual lines * @param leftshift moves the stripes to the left, useful to shift with the background * @param fallingLines true for top left to bottom-right lines, false otherwise */ public static void drawStriped(GC gcImg, int x, int y, int width, int height, int lineDist, int leftshift, boolean fallingLines) { lineDist += 2; final int xm = x + width; final int ym = y + height; for (int i = x; i < xm; i++) { for (int j = y; j < ym; j++) { if ((i + leftshift + (fallingLines ? -j : j)) % lineDist == 0) gcImg.drawPoint(i, j); } } } /** * * @param display * @param background * @param foreground * @param foregroundOffsetOnBg * @param modifyForegroundAlpha 0 (fully transparent) to 255 (retain current alpha) * @return */ public static Image renderTransparency(Display display, Image background, Image foreground, Point foregroundOffsetOnBg, int modifyForegroundAlpha) { //Checks if (display == null || display.isDisposed() || background == null || background.isDisposed() || foreground == null || foreground.isDisposed()) return null; Rectangle backgroundArea = background.getBounds(); Rectangle foregroundDrawArea = foreground.getBounds(); foregroundDrawArea.x += foregroundOffsetOnBg.x; foregroundDrawArea.y += foregroundOffsetOnBg.y; foregroundDrawArea.intersect(backgroundArea); if (foregroundDrawArea.isEmpty()) return null; Image image = new Image(display, backgroundArea); ImageData backData = background.getImageData(); ImageData foreData = foreground.getImageData(); ImageData imgData = image.getImageData(); PaletteData backPalette = backData.palette; ImageData backMask = backData.getTransparencyType() != SWT.TRANSPARENCY_ALPHA ? backData.getTransparencyMask() : null; PaletteData forePalette = foreData.palette; ImageData foreMask = foreData.getTransparencyType() != SWT.TRANSPARENCY_ALPHA ? foreData.getTransparencyMask() : null; PaletteData imgPalette = imgData.palette; image.dispose(); for (int x = 0; x < backgroundArea.width; x++) { for (int y = 0; y < backgroundArea.height; y++) { RGB cBack = backPalette.getRGB(backData.getPixel(x, y)); int aBack = backData.getAlpha(x, y); if (backMask != null && backMask.getPixel(x, y) == 0) aBack = 0; // special treatment for icons with transparency masks int aFore = 0; if (foregroundDrawArea.contains(x, y)) { final int fx = x - foregroundDrawArea.x; final int fy = y - foregroundDrawArea.y; RGB cFore = forePalette.getRGB(foreData.getPixel(fx, fy)); aFore = foreData.getAlpha(fx, fy); if (foreMask != null && foreMask.getPixel(fx, fy) == 0) aFore = 0; // special treatment for icons with transparency masks aFore = aFore * modifyForegroundAlpha / 255; cBack.red *= aBack * (255 - aFore); cBack.red /= 255; cBack.red += aFore * cFore.red; cBack.red /= 255; cBack.green *= aBack * (255 - aFore); cBack.green /= 255; cBack.green += aFore * cFore.green; cBack.green /= 255; cBack.blue *= aBack * (255 - aFore); cBack.blue /= 255; cBack.blue += aFore * cFore.blue; cBack.blue /= 255; } imgData.setAlpha(x, y, aFore + aBack * (255 - aFore) / 255); imgData.setPixel(x, y, imgPalette.getPixel(cBack)); } } return new Image(display, imgData); } public static Control findBackgroundImageControl(Control control) { Image image = control.getBackgroundImage(); if (image == null) { return control; } Composite parent = control.getParent(); Composite lastParent = parent; while (parent != null) { Image parentImage = parent.getBackgroundImage(); if (!image.equals(parentImage)) { return lastParent; } lastParent = parent; parent = parent.getParent(); } return control; } /** * @return * * @since 3.0.3.5 */ public static boolean anyShellHaveStyle(int styles) { Display display = Display.getCurrent(); if (display != null) { Shell[] shells = display.getShells(); for (int i = 0; i < shells.length; i++) { Shell shell = shells[i]; int style = shell.getStyle(); if ((style & styles) == styles) { return true; } } } return false; } public static Shell findFirstShellWithStyle(int styles) { Display display = Display.getCurrent(); if (display != null) { Shell[] shells = display.getShells(); for (int i = 0; i < shells.length; i++) { Shell shell = shells[i]; int style = shell.getStyle(); if ((style & styles) == styles && !shell.isDisposed()) { return shell; } } } return null; } public static int[] colorToIntArray(Color color) { if (color == null || color.isDisposed()) { return null; } return new int[] { color.getRed(), color.getGreen(), color.getBlue() }; } /** * Centers the target Rectangle relative to the reference Rectangle * @param target * @param reference */ public static void centerRelativeTo(Rectangle target, Rectangle reference) { target.x = reference.x + (reference.width / 2) - target.width / 2; target.y = reference.y + (reference.height / 2) - target.height / 2; } /** * Ensure that the given Rectangle is fully visible on the monitor that the cursor * is currently in. This method does not resize the given Rectangle; it merely reposition it * if appropriate. If the given Rectangle is taller or wider than the current monitor then * it may not fit 'fully' in the monitor. *

    * We use a best-effort approach with an emphasis to have at least the top-left of the Rectangle * be visible. If the given Rectangle does not fit entirely in the monitor then portion * of the right and/or left may be off-screen. * *

    * This method does honor global screen elements when possible. Screen elements include the TaskBar on Windows * and the Application menu on OSX, and possibly others. The re-positioned Rectangle returned will fit on the * screen without overlapping (or sliding under) these screen elements. * @param rect * @return */ public static void makeVisibleOnCursor(Rectangle rect) { if (null == rect) { return; } Display display = Display.getCurrent(); if (null == display) { Debug.out("No current display detected. This method [Utils.makeVisibleOnCursor()] must be called from a display thread."); return; } try { /* * Get cursor location */ Point cursorLocation = display.getCursorLocation(); /* * Make visible on the monitor that the mouse cursor resides in */ makeVisibleOnMonitor(rect, getMonitor(cursorLocation)); } catch (Throwable t) { //Do nothing } } /** * Ensure that the given Rectangle is fully visible on the given Monitor. * This method does not resize the given Rectangle; it merely reposition it if appropriate. * If the given Rectangle is taller or wider than the current monitor then it may not fit 'fully' in the monitor. *

    * We use a best-effort approach with an emphasis to have at least the top-left of the Rectangle * be visible. If the given Rectangle does not fit entirely in the monitor then portion * of the right and/or left may be off-screen. * *

    * This method does honor global screen elements when possible. Screen elements include the TaskBar on Windows * and the Application menu on OSX, and possibly others. The re-positioned Rectangle returned will fit on the * screen without overlapping (or sliding under) these screen elements. * @param rect * @param monitor */ public static void makeVisibleOnMonitor(Rectangle rect, Monitor monitor) { if (null == rect || null == monitor) { return; } try { Rectangle monitorBounds = monitor.getClientArea(); /* * Make sure the bottom is fully visible on the monitor */ int bottomDiff = (monitorBounds.y + monitorBounds.height) - (rect.y + rect.height); if (bottomDiff < 0) { rect.y += bottomDiff; } /* * Make sure the right is fully visible on the monitor */ int rightDiff = (monitorBounds.x + monitorBounds.width) - (rect.x + rect.width); if (rightDiff < 0) { rect.x += rightDiff; } /* * Make sure the left is fully visible on the monitor */ if (rect.x < monitorBounds.x) { rect.x = monitorBounds.x; } /* * Make sure the top is fully visible on the monitor */ if (rect.y < monitorBounds.y) { rect.y = monitorBounds.y; } } catch (Throwable t) { //Do nothing } } /** * Returns the Monitor that the given x,y coordinates resides in * @param x * @param y * @return the monitor if found; otherwise returns null */ private static Monitor getMonitor(int x, int y) { return getMonitor(new Point(x, y)); } /** * Returns the Monitor that the given Point resides in * @param location * @return the monitor if found; otherwise returns null */ public static Monitor getMonitor(Point location) { Display display = Display.getCurrent(); if (null == display) { Debug.out("No current display detected. This method [Utils.makeVisibleOnCursor()] must be called from a display thread."); return null; } try { /* * Find the monitor that this location resides in */ Monitor[] monitors = display.getMonitors(); Rectangle monitorBounds = null; for (int i = 0; i < monitors.length; i++) { monitorBounds = monitors[i].getClientArea(); if (true == monitorBounds.contains(location)) { return monitors[i]; } } } catch (Throwable t) { //Do nothing } return null; } private static boolean gotBrowserStyle = false; private static int browserStyle = SWT.NONE; /** * Consistently applies the browser style obtained during the first invocation * @param style the style you wish to apply * @return the style, possibly ORed with SWT.MOZILLA */ public static int getInitialBrowserStyle(int style) { if (!gotBrowserStyle) { browserStyle = COConfigurationManager.getBooleanParameter("swt.forceMozilla") ? SWT.MOZILLA : SWT.NONE; gotBrowserStyle = true; } return style | browserStyle; } /** * Change the height of the installed Font and takes care of disposing * the new font when the control is disposed * @param control * @param height * @param style one or both of SWT.BOLD, SWT.ITALIC, or SWT.NORMAL */ public static void setFontHeight(Control control, int height, int style) { FontData[] fDatas = control.getFont().getFontData(); for (int i = 0; i < fDatas.length; i++) { fDatas[i].height = height; fDatas[i].setStyle(style); } final Font newFont = new Font(control.getDisplay(), fDatas); control.setFont(newFont); control.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (null != newFont && false == newFont.isDisposed()) { newFont.dispose(); } } }); } public static final long IMMEDIATE_ADDREMOVE_DELAY = 150; private static final long IMMEDIATE_ADDREMOVE_MAXDELAY = 2000; private static Timer timerProcessDataSources = new Timer("Process Data Sources"); private static TimerEvent timerEventProcessDS; private static List processDataSourcesOutstanding = new ArrayList(); public static boolean addDataSourceAggregated( addDataSourceCallback callback ) { if ( callback == null ){ return( true ); } boolean processQueueImmediately = false; List to_do_now = null; synchronized( timerProcessDataSources ){ if ( timerEventProcessDS != null && !timerEventProcessDS.hasRun()){ // Push timer forward, unless we've pushed it forward for over x seconds long now = SystemTime.getCurrentTime(); if (now - timerEventProcessDS.getCreatedTime() < IMMEDIATE_ADDREMOVE_MAXDELAY) { long lNextTime = now + IMMEDIATE_ADDREMOVE_DELAY; timerProcessDataSources.adjustAllBy( lNextTime - timerEventProcessDS.getWhen()); if ( !processDataSourcesOutstanding.contains( callback )){ processDataSourcesOutstanding.add( callback ); } }else{ timerEventProcessDS.cancel(); timerEventProcessDS = null; processQueueImmediately = true; to_do_now = processDataSourcesOutstanding; processDataSourcesOutstanding = new ArrayList(); } }else{ if ( !processDataSourcesOutstanding.contains( callback )){ processDataSourcesOutstanding.add( callback ); } timerEventProcessDS = timerProcessDataSources.addEvent( SystemTime.getCurrentTime() + IMMEDIATE_ADDREMOVE_DELAY, new TimerEventPerformer() { public void perform( TimerEvent event ) { List to_do; synchronized( timerProcessDataSources ){ timerEventProcessDS = null; to_do = processDataSourcesOutstanding; processDataSourcesOutstanding = new ArrayList(); } for (int i=0;i maxWidth) { //Remove characters until they fit into the maximum width sb.deleteCharAt(sb.length()-1); needsAppend = true; if(sb.length() == 1) { break; } } if(needsAppend) { while(gc.textExtent(sb.toString()).x + appendWidth > maxWidth) { //Remove characters until they fit into the maximum width sb.deleteCharAt(sb.length()-1); needsAppend = true; if(sb.length() == 1) { break; } } sb.append(append); } if(cache) { TruncatedTextResult ttR = new TruncatedTextResult(); ttR.text = sb.toString(); ttR.maxWidth = maxWidth; truncatedTextCache.put(text, ttR); } return sb.toString(); } /** * @param bg * @return * * @since 3.1.1.1 */ public static String toColorHexString(Color bg) { StringBuffer sb = new StringBuffer(); twoHex(sb, bg.getRed()); twoHex(sb, bg.getGreen()); twoHex(sb, bg.getBlue()); return sb.toString(); } private static void twoHex(StringBuffer sb, int h) { if (h <= 15) { sb.append('0'); } sb.append(Integer.toHexString(h)); } public static String getWidgetBGColorURLParam() { Color bg = findAnyShell().getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); byte[] color = new byte[3]; color[0] = (byte) bg.getRed(); color[1] = (byte) bg.getGreen(); color[2] = (byte) bg.getBlue(); return( "bg_color=" + ByteFormatter.nicePrint(color)); } public static void reportError( Throwable e ) { MessageBoxShell mb = new MessageBoxShell( MessageText.getString("ConfigView.section.security.op.error.title"), MessageText.getString("ConfigView.section.security.op.error", new String[] { Debug.getNestedExceptionMessage(e) }), new String[] { MessageText.getString("Button.ok"), }, 0 ); mb.open(null); } public static void getOffOfSWTThread(AERunnable runnable) { tp.run(runnable); } public static Browser createSafeBrowser(Composite parent, int style) { try { Browser browser = new Browser(parent, Utils.getInitialBrowserStyle(style)); browser.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { ((Browser)e.widget).setUrl("about:blank"); ((Browser)e.widget).setVisible(false); while (!e.display.isDisposed() && e.display.readAndDispatch()); } }); return browser; } catch (Throwable e) { } return null; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/auth/0000755000175000017500000000000011310377636020357 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/auth/AuthenticatorWindow.java0000644000175000017500000003746111275141736025237 0ustar adrianadrian/* * File : AuthenticatorWindow.java * Created : 25-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.auth; /** * @author parg * */ import java.net.*; import java.util.*; import org.eclipse.swt.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.security.*; import org.bouncycastle.util.encoders.Base64; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.ui.common.RememberedDecisionsManager; public class AuthenticatorWindow implements SEPasswordListener { private static final String CONFIG_PARAM = "swt.auth.persistent.cache"; protected Map auth_cache = new HashMap(); protected AEMonitor this_mon = new AEMonitor( "AuthWind" ); public AuthenticatorWindow() { SESecurityManager.addPasswordListener( this ); // System.out.println( "AuthenticatorWindow"); Map cache = COConfigurationManager.getMapParameter( CONFIG_PARAM, new HashMap()); try{ Iterator it = cache.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); String key = (String)entry.getKey(); Map value = (Map)entry.getValue(); String user = new String((byte[])value.get( "user" ), "UTF-8" ); char[] pw = new String((byte[])value.get( "pw" ), "UTF-8" ).toCharArray(); auth_cache.put( key, new authCache( key, new PasswordAuthentication( user, pw ), true )); } }catch( Throwable e ){ COConfigurationManager.setParameter( CONFIG_PARAM, new HashMap()); Debug.printStackTrace(e); } } protected void saveAuthCache() { try{ this_mon.enter(); HashMap map = new HashMap(); Iterator it = auth_cache.values().iterator(); while( it.hasNext()){ authCache value = (authCache)it.next(); if ( value.isPersistent()){ try{ HashMap entry_map = new HashMap(); entry_map.put( "user", value.getAuth().getUserName().getBytes( "UTF-8" )); entry_map.put( "pw", new String(value.getAuth().getPassword()).getBytes( "UTF-8" )); map.put( value.getKey(), entry_map ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } COConfigurationManager.setParameter( CONFIG_PARAM, map ); }finally{ this_mon.exit(); } } public void clearPasswords() { try{ this_mon.enter(); auth_cache = new HashMap(); saveAuthCache(); }finally{ this_mon.exit(); } } public PasswordAuthentication getAuthentication( String realm, URL tracker ) { try{ this_mon.enter(); return( getAuthentication( realm, tracker.getProtocol(), tracker.getHost(), tracker.getPort())); }finally{ this_mon.exit(); } } public void setAuthenticationOutcome( String realm, URL tracker, boolean success ) { try{ this_mon.enter(); setAuthenticationOutcome( realm, tracker.getProtocol(), tracker.getHost(), tracker.getPort(), success ); }finally{ this_mon.exit(); } } public void setAuthenticationOutcome( String realm, String protocol, String host, int port, boolean success ) { try{ this_mon.enter(); String tracker = protocol + "://" + host + ":" + port + "/"; String auth_key = realm+":"+tracker; authCache cache = (authCache)auth_cache.get( auth_key ); if ( cache != null ){ cache.setOutcome( success ); } }finally{ this_mon.exit(); } } public PasswordAuthentication getAuthentication( String realm, String protocol, String host, int port ) { try{ this_mon.enter(); String tracker = protocol + "://" + host + ":" + port + "/"; InetAddress bind_ip = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress(); String self_addr; // System.out.println( "auth req for " + realm + " - " + tracker ); if ( bind_ip == null || bind_ip.isAnyLocalAddress()){ self_addr = "127.0.0.1"; }else{ self_addr = bind_ip.getHostAddress(); } // when the tracker is connected to internally we don't want to prompt // for the password. Here we return a special user and the password hash // which is picked up in the tracker auth code - search for ""! // also include the tracker IP as well as for scrapes these can occur on // a raw torrent which hasn't been modified to point to localhost if ( host.equals(self_addr) || host.equals(COConfigurationManager.getStringParameter("Tracker IP", ""))){ try{ byte[] pw = COConfigurationManager.getByteParameter("Tracker Password", new byte[0]); String str_pw = new String( Base64.encode(pw)); return( new PasswordAuthentication( "", str_pw.toCharArray())); }catch( Throwable e ){ Debug.printStackTrace( e ); } } String auth_key = realm+":"+tracker; authCache cache = (authCache)auth_cache.get( auth_key ); if ( cache != null ){ PasswordAuthentication auth = cache.getAuth(); if ( auth != null ){ return( auth ); } } String[] res = getAuthenticationDialog( realm, tracker ); if ( res == null ){ return( null ); }else{ PasswordAuthentication auth = new PasswordAuthentication( res[0], res[1].toCharArray()); boolean save_pw = res[2].equals("true"); boolean old_entry_existed = auth_cache.put( auth_key, new authCache( auth_key, auth, save_pw )) != null; if ( save_pw || old_entry_existed ){ saveAuthCache(); } return( auth ); } }finally{ this_mon.exit(); } } protected String[] getAuthenticationDialog( final String realm, final String location ) { final Display display = SWTThread.getInstance().getDisplay(); if ( display.isDisposed()){ return( null ); } final AESemaphore sem = new AESemaphore("SWTAuth"); final authDialog[] dialog = new authDialog[1]; TOTorrent torrent = TorrentUtils.getTLSTorrent(); final boolean is_tracker; final String details; if ( torrent == null ){ is_tracker = false; details = TorrentUtils.getTLSDescription(); }else{ details = TorrentUtils.getLocalisedName( torrent ); is_tracker = true; } try{ display.asyncExec( new AERunnable() { public void runSupport() { dialog[0] = new authDialog( sem, display, realm, is_tracker, location, details ); } }); }catch( Throwable e ){ Debug.printStackTrace( e ); return( null ); } sem.reserve(); String user = dialog[0].getUsername(); String pw = dialog[0].getPassword(); String persist = dialog[0].savePassword()?"true":"false"; if ( user == null ){ return( null ); } return( new String[]{ user, pw == null?"":pw, persist }); } protected class authDialog { private Shell shell; private AESemaphore sem; private String username; private String password; private boolean persist; protected authDialog( AESemaphore _sem, Display display, String realm, boolean is_tracker, String target, String details ) { sem = _sem; if ( display.isDisposed()){ sem.release(); return; } final String ignore_key = "IgnoreAuth:" + realm + ":" + target + ":" + details; if ( RememberedDecisionsManager.getRememberedDecision( ignore_key ) == 1 ){ Debug.out( "Authentication for " + realm + "/" + target + "/" + details + " ignored as told not to ask again" ); sem.release(); return; } shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); Utils.setShellIcon(shell); Messages.setLanguageText(shell, "authenticator.title"); GridLayout layout = new GridLayout(); layout.numColumns = 3; shell.setLayout (layout); GridData gridData; // realm Label realm_label = new Label(shell,SWT.NULL); Messages.setLanguageText(realm_label, "authenticator.realm"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; realm_label.setLayoutData(gridData); Label realm_value = new Label(shell,SWT.NULL); realm_value.setText(realm.replaceAll("&", "&&")); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; realm_value.setLayoutData(gridData); // target Label target_label = new Label(shell,SWT.NULL); Messages.setLanguageText(target_label, is_tracker?"authenticator.tracker":"authenticator.location"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; target_label.setLayoutData(gridData); Label target_value = new Label(shell,SWT.NULL); target_value.setText(target.replaceAll("&", "&&")); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; target_value.setLayoutData(gridData); if ( details != null ){ Label details_label = new Label(shell,SWT.NULL); Messages.setLanguageText(details_label, is_tracker?"authenticator.torrent":"authenticator.details"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; details_label.setLayoutData(gridData); Label details_value = new Label(shell,SWT.NULL); details_value.setText(details.replaceAll("&", "&&")); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; details_value.setLayoutData(gridData); } // user Label user_label = new Label(shell,SWT.NULL); Messages.setLanguageText(user_label, "authenticator.user"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; user_label.setLayoutData(gridData); final Text user_value = new Text(shell,SWT.BORDER); user_value.setText(""); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; user_value.setLayoutData(gridData); user_value.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { username = user_value.getText(); }}); // password Label password_label = new Label(shell,SWT.NULL); Messages.setLanguageText(password_label, "authenticator.password"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; password_label.setLayoutData(gridData); final Text password_value = new Text(shell,SWT.BORDER); password_value.setEchoChar('*'); password_value.setText(""); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; password_value.setLayoutData(gridData); password_value.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { password = password_value.getText(); }}); // persist Label blank_label = new Label(shell,SWT.NULL); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; blank_label.setLayoutData(gridData); final Button checkBox = new Button(shell, SWT.CHECK); checkBox.setText(MessageText.getString( "authenticator.savepassword" )); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; checkBox.setLayoutData(gridData); checkBox.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { persist = checkBox.getSelection(); } }); final Button dontAsk = new Button(shell, SWT.CHECK); dontAsk.setText(MessageText.getString( "general.dont.ask.again" )); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; dontAsk.setLayoutData(gridData); dontAsk.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { RememberedDecisionsManager.setRemembered( ignore_key, dontAsk.getSelection()?1:0 ); } }); // line Label labelSeparator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; labelSeparator.setLayoutData(gridData); // buttons new Label(shell,SWT.NULL); Button bOk = new Button(shell,SWT.PUSH); Messages.setLanguageText(bOk, "Button.ok"); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.HORIZONTAL_ALIGN_FILL); gridData.grabExcessHorizontalSpace = true; gridData.widthHint = 70; bOk.setLayoutData(gridData); bOk.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { close(true); } }); Button bCancel = new Button(shell,SWT.PUSH); Messages.setLanguageText(bCancel, "Button.cancel"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); gridData.grabExcessHorizontalSpace = false; gridData.widthHint = 70; bCancel.setLayoutData(gridData); bCancel.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { close(false); } }); shell.setDefaultButton( bOk ); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ close( false ); } } }); shell.pack (); Utils.centreWindow( shell ); shell.open (); } protected void close( boolean ok ) { if ( ok ){ if ( username == null ){ username = ""; } if ( password == null ){ password = ""; } }else{ username = null; password = null; } shell.dispose(); sem.release(); } protected String getUsername() { return( username ); } protected String getPassword() { return( password ); } protected boolean savePassword() { return( persist ); } } protected class authCache { private String key; private PasswordAuthentication auth; private boolean persist; private int life = 5; private boolean succeeded; protected authCache( String _key, PasswordAuthentication _auth, boolean _persist ) { key = _key; auth = _auth; persist = _persist; } protected String getKey() { return( key ); } protected boolean isPersistent() { return( persist ); } protected void setOutcome( boolean success) { if ( success ){ succeeded = true; }else{ if ( persist ){ persist = false; saveAuthCache(); } if ( !succeeded ){ auth = null; } } } protected PasswordAuthentication getAuth() { if ( succeeded ){ return( auth ); } life--; if ( life >= 0 ){ return( auth ); } if ( persist ){ persist = false; saveAuthCache(); } return( null ); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/auth/CertificateTrustWindow.java0000644000175000017500000001650311275141740025676 0ustar adrianadrian/* * File : CertificateTrustWindow.java * Created : 29-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.auth; /** * @author parg * */ import java.security.cert.X509Certificate; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.security.SECertificateListener; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; public class CertificateTrustWindow implements SECertificateListener { public CertificateTrustWindow() { SESecurityManager.addCertificateListener( this ); } public boolean trustCertificate( final String resource, final X509Certificate cert ) { final Display display = SWTThread.getInstance().getDisplay(); if ( display.isDisposed()){ return( false ); } final trustDialog[] dialog = new trustDialog[1]; try{ Utils.execSWTThread(new AERunnable() { public void runSupport() { dialog[0] = new trustDialog( display, resource, cert ); } }, false); }catch( Throwable e ){ Debug.printStackTrace( e ); return( false ); } return(dialog[0].getTrusted()); } protected class trustDialog { protected Shell shell; protected boolean trusted; protected trustDialog( Display display, String resource, X509Certificate cert ) { if ( display.isDisposed()){ return; } shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); Utils.setShellIcon(shell); shell.setText(MessageText.getString("security.certtruster.title")); GridLayout layout = new GridLayout(); layout.numColumns = 3; shell.setLayout (layout); GridData gridData; // info Label info_label = new Label(shell,SWT.NULL); Messages.setLanguageText(info_label, "security.certtruster.intro"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 3; info_label.setLayoutData(gridData); // resource Label resource_label = new Label(shell,SWT.NULL); Messages.setLanguageText(resource_label, "security.certtruster.resource"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; resource_label.setLayoutData(gridData); Label resource_value = new Label(shell,SWT.NULL); resource_value.setText(resource.replaceAll("&", "&&")); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; resource_value.setLayoutData(gridData); // issued by Label issued_by_label = new Label(shell,SWT.NULL); Messages.setLanguageText(issued_by_label, "security.certtruster.issuedby"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; issued_by_label.setLayoutData(gridData); Label issued_by_value = new Label(shell,SWT.NULL); issued_by_value.setText(extractCN(cert.getIssuerDN().getName()).replaceAll("&", "&&")); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; issued_by_value.setLayoutData(gridData); // issued to Label issued_to_label = new Label(shell,SWT.NULL); Messages.setLanguageText(issued_to_label, "security.certtruster.issuedto"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; issued_to_label.setLayoutData(gridData); Label issued_to_value = new Label(shell,SWT.NULL); issued_to_value.setText(extractCN(cert.getSubjectDN().getName()).replaceAll("&", "&&")); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; issued_to_value.setLayoutData(gridData); // prompt Label prompt_label = new Label(shell,SWT.NULL); Messages.setLanguageText(prompt_label, "security.certtruster.prompt"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 3; prompt_label.setLayoutData(gridData); // line Label labelSeparator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; labelSeparator.setLayoutData(gridData); // buttons new Label(shell,SWT.NULL); Composite comp = new Composite(shell,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.HORIZONTAL_ALIGN_FILL); gridData.grabExcessHorizontalSpace = true; gridData.horizontalSpan = 2; comp.setLayoutData(gridData); GridLayout layoutButtons = new GridLayout(); layoutButtons.numColumns = 2; comp.setLayout(layoutButtons); Button bYes = new Button(comp,SWT.PUSH); bYes.setText(MessageText.getString("security.certtruster.yes")); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.HORIZONTAL_ALIGN_FILL); gridData.grabExcessHorizontalSpace = true; gridData.widthHint = 70; bYes.setLayoutData(gridData); bYes.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { close(true); } }); Button bNo = new Button(comp,SWT.PUSH); bNo.setText(MessageText.getString("security.certtruster.no")); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); gridData.grabExcessHorizontalSpace = false; gridData.widthHint = 70; bNo.setLayoutData(gridData); bNo.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { close(false); } }); shell.setDefaultButton( bYes ); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ close( false ); } } }); shell.pack (); Utils.centreWindow( shell ); shell.open (); while (!shell.isDisposed()) { if (!shell.getDisplay().readAndDispatch()) { shell.getDisplay().sleep(); } } } protected void close( boolean ok ) { trusted = ok; shell.dispose(); } protected String extractCN( String dn ) { int p1 = dn.indexOf( "CN="); if ( p1 == -1 ){ return( dn ); } int p2 = dn.indexOf(",", p1 ); if ( p2 == -1 ){ return( dn.substring(p1+3).trim()); } return( dn.substring(p1+3,p2).trim()); } public boolean getTrusted() { return( trusted ); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/auth/CertificateCreatorWindow.java0000644000175000017500000001732511275141736026164 0ustar adrianadrian/* * Created on 08-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.auth; /** * @author parg * */ import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; public class CertificateCreatorWindow { public CertificateCreatorWindow() { createCertificate(); } public void createCertificate() { final Display display = SWTThread.getInstance().getDisplay(); if ( display.isDisposed()){ return; } try{ display.asyncExec( new AERunnable() { public void runSupport() { new createDialog( display ); } }); }catch( Throwable e ){ Debug.printStackTrace( e ); } } protected class createDialog { protected Shell shell; protected createDialog( Display display ) { if ( display.isDisposed()){ return; } shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); Utils.setShellIcon(shell); Messages.setLanguageText(shell, "security.certcreate.title"); GridLayout layout = new GridLayout(); layout.numColumns = 3; shell.setLayout (layout); GridData gridData; // info Label info_label = new Label(shell,SWT.NULL); Messages.setLanguageText(info_label, "security.certcreate.intro"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 3; info_label.setLayoutData(gridData); // alias Label alias_label = new Label(shell,SWT.NULL); Messages.setLanguageText(alias_label, "security.certcreate.alias"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; alias_label.setLayoutData(gridData); final Text alias_field =new Text(shell,SWT.BORDER); alias_field.setText( SESecurityManager.DEFAULT_ALIAS ); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; alias_field.setLayoutData(gridData); // strength Label strength_label = new Label(shell,SWT.NULL); Messages.setLanguageText(strength_label, "security.certcreate.strength"); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 1; strength_label.setLayoutData(gridData); final Combo strength_combo = new Combo(shell, SWT.SINGLE | SWT.READ_ONLY); final int[] strengths = { 512, 1024, 1536, 2048 }; for (int i=0;i 0 ){ referrer_combo.setText( referrer ); }else if ( last_referrer != null ){ referrer_combo.setText( last_referrer ); } Label referrer_info = new Label(shell, SWT.NULL); referrer_info.setText(MessageText.getString("openUrl.referrer.info")); // line Label labelSeparator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_END); gridData.horizontalSpan = 3; labelSeparator.setLayoutData(gridData); // buttons Composite panel = new Composite(shell, SWT.NULL); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.VERTICAL_ALIGN_END); gridData.horizontalSpan = 3; gridData.grabExcessHorizontalSpace = true; panel.setLayoutData(gridData); new Label(panel, SWT.NULL); Button ok = new Button(panel,SWT.PUSH); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.VERTICAL_ALIGN_END); gridData.widthHint = 70; gridData.grabExcessHorizontalSpace = true; ok.setLayoutData(gridData); ok.setText(MessageText.getString("Button.ok")); ok.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { last_referrer = referrer_combo.getText().trim(); if(! referrers.contains(last_referrer)) { referrers.add(last_referrer); COConfigurationManager.setParameter("url_open_referrers",referrers); COConfigurationManager.save(); } COConfigurationManager.setParameter( CONFIG_REFERRER_DEFAULT, last_referrer ); COConfigurationManager.save(); String url_str = url.getText(); url_str = UrlUtils.parseHTMLforURL( url_str ); if ( url_str == null ){ url_str = url.getText(); } new FileDownloadWindow(parent,url_str, last_referrer, null, listener ); shell.dispose(); } }); shell.setDefaultButton (ok); Button cancel = new Button(panel,SWT.PUSH); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); gridData.grabExcessHorizontalSpace = false; gridData.widthHint = 70; cancel.setLayoutData(gridData); cancel.setText(MessageText.getString("Button.cancel")); cancel.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { shell.dispose(); } }); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ shell.dispose(); } } }); Point p = shell.computeSize( SWT.DEFAULT, SWT.DEFAULT ); if ( p.x > 800 ){ p.x = 800; } shell.setSize( p ); Utils.createURLDropTarget(shell, url); Utils.centreWindow( shell ); shell.open(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/0000755000175000017500000000000011310377636021572 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/IMainWindow.java0000644000175000017500000000132011076212222024602 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.mainwindow; import org.eclipse.swt.graphics.Rectangle; public interface IMainWindow { public static final int WINDOW_ELEMENT_MENU = 1; public static final int WINDOW_ELEMENT_TOOLBAR = 2; public static final int WINDOW_ELEMENT_STATUSBAR = 3; public static final int WINDOW_ELEMENT_TOPBAR = 4; // 3.2 TODO: rename to searchbar or profilebar or something public static final int WINDOW_ELEMENT_TABBAR = 5; public static final int WINDOW_CLIENT_AREA = 6; public static final int WINDOW_CONTENT_DISPLAY_AREA = 7; public boolean isVisible(int windowElement); public void setVisible(int windowElement, boolean value); public Rectangle getMetrics(int windowElement); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/MainWindow.java0000644000175000017500000013572311273607612024522 0ustar adrianadrian/* * Created on Jun 25, 2003 * Modified Apr 13, 2004 by Alon Rohter * Modified Apr 17, 2004 by Olivier Chalouhi (OSX system menu) * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.mainwindow; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTError; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerAdapter; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.sharing.ShareException; import org.gudy.azureus2.plugins.sharing.ShareManager; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.associations.AssociationChecker; import org.gudy.azureus2.ui.swt.components.shell.ShellManager; import org.gudy.azureus2.ui.swt.config.wizard.ConfigureWizard; import org.gudy.azureus2.ui.swt.debug.ObfusticateImage; import org.gudy.azureus2.ui.swt.debug.ObfusticateShell; import org.gudy.azureus2.ui.swt.debug.ObfusticateTab; import org.gudy.azureus2.ui.swt.donations.DonationWindow; import org.gudy.azureus2.ui.swt.maketorrent.NewTorrentWizard; import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar; import org.gudy.azureus2.ui.swt.minibar.MiniBarManager; import org.gudy.azureus2.ui.swt.plugins.UISWTView; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl; import org.gudy.azureus2.ui.swt.sharing.progress.ProgressWindow; import org.gudy.azureus2.ui.swt.views.*; import org.gudy.azureus2.ui.swt.views.clientstats.ClientStatsView; import org.gudy.azureus2.ui.swt.views.stats.StatsView; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import org.gudy.azureus2.ui.swt.welcome.WelcomeWindow; import org.gudy.azureus2.ui.systray.SystemTraySWT; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreException; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.UIStatusTextClickListener; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.util.MapUtils; /** * @author Olivier * Runnable : so that GUI initialization is done via asyncExec(this) * STProgressListener : To make it visible once initialization is done */ public class MainWindow extends AERunnable implements ParameterListener, IconBarEnabler, AEDiagnosticsEvidenceGenerator, ObfusticateShell, IMainWindow { private static final LogIDs LOGID = LogIDs.GUI; private static MainWindow window; private Initializer initializer; private AzureusCore azureus_core; private GlobalManager globalManager; //NICO handle swt on macosx public static boolean isAlreadyDead = false; public static boolean isDisposeFromListener = false; private Display display; private Composite parent; private Shell shell; private IMainMenu mainMenu; private IconBar iconBar; private Composite folder; /** * Handles initializing and refreshing the status bar (w/help of GUIUpdater) */ private MainStatusBar mainStatusBar; private TrayWindow downloadBasket; private SystemTraySWT systemTraySWT; private HashMap downloadViews; private AEMonitor downloadViews_mon = new AEMonitor("MainWindow:dlviews"); private Item mytorrents; private Item detailed_list; private Item all_peers; private Item my_tracker_tab; private Item my_shares_tab; private Item stats_tab; private Item console; private Item multi_options_tab; private Item config; private Item viewClientStats; private ConfigView config_view; protected AEMonitor this_mon = new AEMonitor("MainWindow"); private UISWTInstanceImpl uiSWTInstanceImpl = null; private ArrayList events; private UIFunctionsSWT uiFunctions; private boolean bIconBarEnabled = false; private boolean bShowMainWindow; private boolean bSettingVisibility = false; private Tab mainTabSet; public MainWindow(AzureusCore _azureus_core, Initializer _initializer, ArrayList events) { bShowMainWindow = true; try { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "MainWindow start")); AEDiagnostics.addEvidenceGenerator(this); azureus_core = _azureus_core; globalManager = azureus_core.getGlobalManager(); initializer = _initializer; display = SWTThread.getInstance().getDisplay(); window = this; this.events = events; display.asyncExec(this); } catch (AzureusCoreException e) { Debug.printStackTrace(e); } } /** * runSupport() MUST BE CALLED TO FINISH INITIALIZATION * @param _azureus_core * @param _initializer * @param shell * @param parent */ public MainWindow(AzureusCore _azureus_core, Initializer _initializer, Shell shell, Composite parent, UISWTInstanceImpl swtinstance) { this.shell = shell; this.parent = parent; bShowMainWindow = true; try { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "MainWindow start")); AEDiagnostics.addEvidenceGenerator(this); azureus_core = _azureus_core; globalManager = azureus_core.getGlobalManager(); initializer = _initializer; display = SWTThread.getInstance().getDisplay(); window = this; uiSWTInstanceImpl = swtinstance; } catch (AzureusCoreException e) { Debug.printStackTrace(e); } } public MainWindow() { bShowMainWindow = true; try { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "MainWindow start")); AEDiagnostics.addEvidenceGenerator(this); azureus_core = AzureusCoreFactory.getSingleton(); globalManager = azureus_core.getGlobalManager(); display = SWTThread.getInstance().getDisplay(); window = this; } catch (AzureusCoreException e) { Debug.printStackTrace(e); } } public void init(Composite parent, UISWTInstanceImpl swtInstance) { this.parent = parent; this.shell = parent.getShell(); uiSWTInstanceImpl = swtInstance; } public void setShowMainWindow(boolean b) { bShowMainWindow = b; } // @see org.gudy.azureus2.core3.util.AERunnable#runSupport() public void runSupport() { FormData formData; try { uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions == null) { uiFunctions = new UIFunctionsImpl(this); UIFunctionsManager.setUIFunctions(uiFunctions); } else { uiFunctions = new UIFunctionsImpl(this); } globalManager.loadExistingTorrentsNow(true); COConfigurationManager.addParameterListener("config.style.useSIUnits", this); COConfigurationManager.addParameterListener("config.style.forceSIValues", this); mytorrents = null; my_tracker_tab = null; console = null; config = null; config_view = null; downloadViews = new HashMap(); Control attachToTopOf = null; Control controlAboveFolder = null; Control controlBelowFolder = null; //The Main Window if (shell == null) { shell = new Shell(display, SWT.RESIZE | SWT.BORDER | SWT.CLOSE | SWT.MAX | SWT.MIN); shell.setData("class", this); shell.setText(Constants.APP_NAME); //$NON-NLS-1$ Utils.setShellIcon(shell); if (parent == null) { parent = shell; } // register window ShellManager.sharedManager().addWindow(shell); mainMenu = new MainMenu(shell); FormLayout mainLayout = new FormLayout(); mainLayout.marginHeight = 0; mainLayout.marginWidth = 0; try { mainLayout.spacing = 0; } catch (NoSuchFieldError e) { /* Pre SWT 3.0 */ } shell.setLayout(mainLayout); Utils.linkShellMetricsToConfig(shell, "window"); //NICO catch the dispose event from file/quit on osx shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent event) { if (!isAlreadyDead) { isDisposeFromListener = true; if (shell != null) { shell.removeDisposeListener(this); dispose(false, false); } isAlreadyDead = true; } } }); shell.addShellListener(new ShellAdapter() { public void shellClosed(ShellEvent event) { if (bSettingVisibility) { return; } if (systemTraySWT != null && COConfigurationManager.getBooleanParameter("Enable System Tray") && COConfigurationManager.getBooleanParameter("Close To Tray")) { minimizeToTray(event); } else { event.doit = dispose(false, false); } } public void shellIconified(ShellEvent event) { if (bSettingVisibility) { return; } if (systemTraySWT != null && COConfigurationManager.getBooleanParameter("Enable System Tray") && COConfigurationManager.getBooleanParameter("Minimize To Tray")) { minimizeToTray(event); } } public void shellDeiconified(ShellEvent e) { if (Constants.isOSX && COConfigurationManager.getBooleanParameter("Password enabled")) { shell.setVisible(false); if (PasswordWindow.showPasswordWindow(display)) { shell.setVisible(true); } } } }); // Separator between menu and icon bar Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); formData = new FormData(); formData.top = new FormAttachment(0, 0); // 2 params for Pre SWT 3.0 formData.left = new FormAttachment(0, 0); // 2 params for Pre SWT 3.0 formData.right = new FormAttachment(100, 0); // 2 params for Pre SWT 3.0 separator.setLayoutData(formData); attachToTopOf = separator; mainStatusBar = new MainStatusBar(); Composite statusBar = mainStatusBar.initStatusBar(shell); controlAboveFolder = attachToTopOf; controlBelowFolder = statusBar; } try { Utils.createTorrentDropTarget(parent, true); } catch (SWTError e) { // "Cannot initialize Drop".. don't spew stack trace Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Drag and Drop not available: " + e.getMessage())); } catch (Throwable e) { Logger.log(new LogEvent(LOGID, "Drag and Drop not available", e)); } mainTabSet = new Tab(this); folder = mainTabSet.createFolderWidget(parent); formData = new FormData(); if (controlAboveFolder == null) { formData.top = new FormAttachment(0, 0); } else { formData.top = new FormAttachment(controlAboveFolder); } if (controlBelowFolder == null) { formData.bottom = new FormAttachment(100, 0); } else { formData.bottom = new FormAttachment(controlBelowFolder); } formData.left = new FormAttachment(0, 0); // 2 params for Pre SWT 3.0 formData.right = new FormAttachment(100, 0); // 2 params for Pre SWT 3.0 folder.setLayoutData(formData); display.addFilter(SWT.KeyDown, new Listener() { public void handleEvent(Event event) { // Another window has control, skip filter Control focus_control = display.getFocusControl(); if (focus_control != null && focus_control.getShell() != shell) return; int key = event.character; if ((event.stateMask & SWT.MOD1) != 0 && event.character <= 26 && event.character > 0) key += 'a' - 1; if (key == 'l' && (event.stateMask & SWT.MOD1) != 0) { // Ctrl-L: Open URL OpenTorrentWindow.invokeURLPopup(shell, globalManager); event.doit = false; } } }); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Initializing GUI complete")); globalManager.addListener(new GlobalManagerAdapter() { public void downloadManagerAdded(DownloadManager dm) { MainWindow.this.downloadManagerAdded(dm); } public void downloadManagerRemoved(DownloadManager dm) { MainWindow.this.downloadManagerRemoved(dm); } }); PluginManager plugin_manager = azureus_core.getPluginManager(); plugin_manager.firePluginEvent(PluginEvent.PEV_CONFIGURATION_WIZARD_STARTS); if (!COConfigurationManager.getBooleanParameter("Wizard Completed")) { // returns after the wizard is done new ConfigureWizard(true); } plugin_manager.firePluginEvent(PluginEvent.PEV_CONFIGURATION_WIZARD_COMPLETES); // attach the UI to plugins // Must be done before initializing views, since plugins may register // table columns and other objects if (uiSWTInstanceImpl == null) { TableColumnCreator.initCoreColumns(); uiSWTInstanceImpl = new UISWTInstanceImpl(azureus_core); uiSWTInstanceImpl.init(initializer); // check if any plugins shut us down if (isAlreadyDead) { return; } postPluginSetup(0, 50); } } catch (Throwable e) { Debug.printStackTrace(e); } showMainWindow(); } /** * * * @since 3.0.4.3 */ public void postPluginSetup(int delay, final int delayInc) { if (initializer != null) { initializer.reportCurrentTask(MessageText.getString("splash.openViews")); initializer.nextTask(); } if (!Constants.isSafeMode && azureus_core.getTrackerHost().getTorrents().length > 0) { Utils.execSWTThreadLater(delay += delayInc, new Runnable() { public void run() { showMyTracker(); } }); } // share manager init is async so we need to deal with this PluginInterface default_pi = PluginInitializer.getDefaultInterface(); try { final ShareManager share_manager = default_pi.getShareManager(); default_pi.addListener(new PluginListener() { public void initializationComplete() { } public void closedownInitiated() { int share_count = share_manager.getShares().length; if (share_count != COConfigurationManager.getIntParameter("GUI_SWT_share_count_at_close")) { COConfigurationManager.setParameter("GUI_SWT_share_count_at_close", share_count); } } public void closedownComplete() { } }); if (share_manager.getShares().length > 0 || COConfigurationManager.getIntParameter("GUI_SWT_share_count_at_close") > 0) { Utils.execSWTThreadLater(delay += delayInc, new Runnable() { public void run() { showMyShares(); } }); } } catch (ShareException e) { Debug.out(e); } if (!Constants.isSafeMode && COConfigurationManager.getBooleanParameter("Open MyTorrents")) { Utils.execSWTThreadLater(delay += delayInc, new Runnable() { public void run() { showMyTorrents(); } }); } // share progress window new ProgressWindow(); if (!Constants.isSafeMode && COConfigurationManager.getBooleanParameter("Open Console")) { Utils.execSWTThreadLater(delay += delayInc, new Runnable() { public void run() { showConsole(); } }); } events = null; if (Constants.isSafeMode || COConfigurationManager.getBooleanParameter("Open Config")) { Utils.execSWTThreadLater(delay += delayInc, new Runnable() { public void run() { showConfig(); } }); } if (!Constants.isSafeMode && COConfigurationManager.getBooleanParameter("Open Stats On Start")) { Utils.execSWTThreadLater(delay += delayInc, new Runnable() { public void run() { showStats(); } }); } if (!Constants.isSafeMode && COConfigurationManager.getBooleanParameter("Open Transfer Bar On Start")) { Utils.execSWTThreadLater(delay += delayInc, new Runnable() { public void run() { uiFunctions.showGlobalTransferBar(); } }); } if (!Constants.isSafeMode && COConfigurationManager.getBooleanParameter("Open Client Stats")) { Utils.execSWTThreadLater(delay += delayInc, new Runnable() { public void run() { showClientStatsView(); } }); } COConfigurationManager.addAndFireParameterListener("IconBar.enabled", new ParameterListener() { public void parameterChanged(String parameterName) { setIconBarEnabled(COConfigurationManager.getBooleanParameter(parameterName)); } }); // init done if (initializer != null) initializer.abortProgress(); } protected boolean getIconBarEnabled() { return bIconBarEnabled; } protected void setIconBarEnabled(boolean enabled) { if (enabled == bIconBarEnabled || shell.isDisposed()) { return; } bIconBarEnabled = enabled; COConfigurationManager.setParameter("IconBar.enabled", bIconBarEnabled); if (bIconBarEnabled) { try { iconBar = new IconBar(parent); iconBar.setCurrentEnabler(this); Composite cIconBar = iconBar.getComposite(); FormData folderLayoutData = (FormData) folder.getLayoutData(); FormData formData = new FormData(); if (folderLayoutData.top != null && folderLayoutData.top.control != null) { formData.top = new FormAttachment(folderLayoutData.top.control); } else { formData.top = new FormAttachment(0, 0); } folderLayoutData.top = new FormAttachment(cIconBar); formData.left = new FormAttachment(0, 0); // 2 params for Pre SWT 3.0 formData.right = new FormAttachment(100, 0); // 2 params for Pre SWT 3.0 this.iconBar.setLayoutData(formData); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "Creating Icon Bar", e)); } } else if (iconBar != null) { try { FormData folderLayoutData = (FormData) folder.getLayoutData(); FormData iconBarLayoutData = (FormData) iconBar.getComposite().getLayoutData(); if (iconBarLayoutData.top != null && iconBarLayoutData.top.control != null) { folderLayoutData.top = new FormAttachment( iconBarLayoutData.top.control); } else { folderLayoutData.top = new FormAttachment(0, 0); } iconBar.delete(); iconBar = null; } catch (Exception e) { Logger.log(new LogEvent(LOGID, "Removing Icon Bar", e)); } } shell.layout(true, true); } private void showMainWindow() { COConfigurationManager.addAndFireParameterListener("Show Download Basket",this); if (!bShowMainWindow) { return; } boolean bEnableTray = COConfigurationManager.getBooleanParameter("Enable System Tray"); boolean bPassworded = COConfigurationManager.getBooleanParameter("Password enabled"); boolean bStartMinimize = bEnableTray && (bPassworded || COConfigurationManager.getBooleanParameter("Start Minimized")); if (!bStartMinimize) { shell.layout(); shell.open(); if (!Constants.isOSX) { shell.forceActive(); } } else if (Constants.isOSX) { shell.setMinimized(true); shell.setVisible(true); } if (bEnableTray) { try { systemTraySWT = new SystemTraySWT(); } catch (Throwable e) { Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "Upgrade to SWT3.0M8 or later for system tray support.")); } if (bStartMinimize) { minimizeToTray(null); } //Only show the password if not started minimized //Correct bug #878227 else { if (bPassworded) { minimizeToTray(null); setVisible(true, true); // invokes password } } } // do this before other checks as these are blocking dialogs to force order if ( initializer != null ){ initializer.initializationComplete(); } checkForWhatsNewWindow(); // check file associations AssociationChecker.checkAssociations(); // Donation stuff Map map = VersionCheckClient.getSingleton().getMostRecentVersionCheckData(); DonationWindow.setInitialAskHours(MapUtils.getMapInt(map, "donations.askhrs", DonationWindow.getInitialAskHours())); azureus_core.triggerLifeCycleComponentCreated(uiFunctions); } protected void showMyTracker() { if (my_tracker_tab == null) { my_tracker_tab = mainTabSet.createTabItem(new MyTrackerView(), true); mainTabSet.getView(my_tracker_tab).getComposite().addDisposeListener( new DisposeListener() { public void widgetDisposed(DisposeEvent e) { my_tracker_tab = null; } }); } else { mainTabSet.setFocus(my_tracker_tab); refreshIconBar(); refreshTorrentMenu(); } } protected void showMyShares() { if (my_shares_tab == null) { my_shares_tab = mainTabSet.createTabItem(new MySharesView(), true); mainTabSet.getView(my_shares_tab).getComposite().addDisposeListener( new DisposeListener() { public void widgetDisposed(DisposeEvent e) { my_shares_tab = null; } }); } else { mainTabSet.setFocus(my_shares_tab); refreshIconBar(); refreshTorrentMenu(); } } protected void showMyTorrents() { if (mytorrents == null) { MyTorrentsSuperView view = new MyTorrentsSuperView(); mytorrents = mainTabSet.createTabItem(view, true); mainTabSet.getView(mytorrents).getComposite().addDisposeListener( new DisposeListener() { public void widgetDisposed(DisposeEvent e) { mytorrents = null; } }); } else { mainTabSet.setFocus(mytorrents); } refreshIconBar(); refreshTorrentMenu(); } protected void showDetailedListView() { if (detailed_list == null) { DetailedListView view = new DetailedListView(azureus_core); detailed_list = mainTabSet.createTabItem(view, true); mainTabSet.getView(detailed_list).getComposite().addDisposeListener( new DisposeListener() { public void widgetDisposed(DisposeEvent e) { detailed_list = null; } }); } else { mainTabSet.setFocus(detailed_list); } refreshIconBar(); refreshTorrentMenu(); } protected void showAllPeersView() { if (all_peers == null) { PeerSuperView view = new PeerSuperView(); all_peers = mainTabSet.createTabItem(view, true); mainTabSet.getView(all_peers).getComposite().addDisposeListener( new DisposeListener() { public void widgetDisposed(DisposeEvent e) { all_peers = null; } }); } else { mainTabSet.setFocus(all_peers); } refreshIconBar(); refreshTorrentMenu(); } protected void showClientStatsView() { if (viewClientStats == null) { ClientStatsView view = new ClientStatsView(); viewClientStats = mainTabSet.createTabItem(view, true); mainTabSet.getView(viewClientStats).getComposite().addDisposeListener( new DisposeListener() { public void widgetDisposed(DisposeEvent e) { viewClientStats = null; } }); } else { mainTabSet.setFocus(viewClientStats); } refreshIconBar(); refreshTorrentMenu(); } protected void showMultiOptionsView(DownloadManager[] managers) { if (multi_options_tab != null) { multi_options_tab.dispose(); } TorrentOptionsView view = new TorrentOptionsView(managers); multi_options_tab = mainTabSet.createTabItem(view, true); view.getComposite().addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { multi_options_tab = null; } }); refreshIconBar(); refreshTorrentMenu(); } private void minimizeToTray(ShellEvent event) { //Added this test so that we can call this method with null parameter. if (event != null) event.doit = false; // XXX hack for release.. should not access param outside Utils.linkShellMetrics COConfigurationManager.setParameter("window.maximized", shell.getMaximized()); shell.setVisible(false); if (downloadBasket != null) downloadBasket.setVisible(true); MiniBarManager.getManager().setAllVisible(true); } private void updateComponents() { if (mainStatusBar != null) mainStatusBar.refreshStatusText(); if (mainTabSet != null) { mainTabSet.update(); } } private void downloadManagerAdded(DownloadManager created) { // only do donation check if swt instance is initialized, which means // initial download managers are loaded and this main window is really // the main window if (uiSWTInstanceImpl != null && !created.getDownloadState().getFlag(DownloadManagerState.FLAG_LOW_NOISE)) { DonationWindow.checkForDonationPopup(); } } protected void openManagerView(DownloadManager downloadManager) { try { downloadViews_mon.enter(); if (downloadViews.containsKey(downloadManager)) { mainTabSet.setFocus((Item) downloadViews.get(downloadManager)); refreshIconBar(); refreshTorrentMenu(); } else { Item tab = openPluginView(null, "DMView", new ManagerView(), downloadManager, true, true); // Item tab = mainTabSet.createTabItem(new ManagerView(azureus_core, // downloadManager), true); downloadViews.put(downloadManager, tab); } } finally { downloadViews_mon.exit(); } } protected void removeManagerView(DownloadManager downloadManager) { try { downloadViews_mon.enter(); downloadViews.remove(downloadManager); } finally { downloadViews_mon.exit(); } } private void downloadManagerRemoved(DownloadManager removed) { try { downloadViews_mon.enter(); if (downloadViews.containsKey(removed)) { final Item tab = (Item) downloadViews.get(removed); Utils.execSWTThread(new AERunnable() { public void runSupport() { if (display == null || display.isDisposed()) return; mainTabSet.dispose(tab); } }); } } finally { downloadViews_mon.exit(); } } protected Display getDisplay() { return this.display; } protected Shell getShell() { return shell; } public void setVisible(final boolean visible, final boolean tryTricks) { Utils.execSWTThread(new AERunnable() { public void runSupport() { bSettingVisibility = true; try { boolean currentlyVisible = shell.getVisible() && !shell.getMinimized(); if (visible && !currentlyVisible) { if (COConfigurationManager.getBooleanParameter("Password enabled", false)) { if (!PasswordWindow.showPasswordWindow(display)) { shell.setVisible(false); return; } } } ArrayList wasVisibleList = null; boolean bHideAndShow = false; // temp disabled //tryTricks && visible && Constants.isWindows && display.getActiveShell() != shell; if (bHideAndShow) { wasVisibleList = new ArrayList(); // We don't want the window to just flash and not open, so: // -Minimize main shell // -Set all shells invisible try { shell.setMinimized(true); Shell[] shells = shell.getDisplay().getShells(); for (int i = 0; i < shells.length; i++) { if (shells[i].isVisible()) { wasVisibleList.add(shells[i]); shells[i].setVisible(false); } } } catch (Exception e) { } } if (visible) { if (shell.getMinimized()) { shell.setMinimized(false); } if (!currentlyVisible && COConfigurationManager.getBooleanParameter("window.maximized")) { shell.setMaximized(true); } } else { // XXX hack for release.. should not access param outside Utils.linkShellMetrics COConfigurationManager.setParameter("window.maximized", shell.getMaximized()); } shell.setVisible(visible); if (visible) { if (downloadBasket != null) { downloadBasket.setVisible(false); downloadBasket.setMoving(false); } /* if (trayIcon != null) trayIcon.showIcon(); */ shell.forceActive(); if (bHideAndShow) { try { Shell[] shells = shell.getDisplay().getShells(); for (int i = 0; i < shells.length; i++) { if (shells[i] != shell) { if (wasVisibleList.contains(shells[i])) { shells[i].setVisible(visible); } shells[i].setFocus(); } } } catch (Exception e) { } } } } finally { bSettingVisibility = false; } } }); } protected boolean isVisible() { return shell.isVisible(); } public boolean dispose(final boolean for_restart, final boolean close_already_in_progress) { return Utils.execSWTThreadWithBool("MainWindow.dispose", new AERunnableBoolean() { public boolean runSupport() { return _dispose(for_restart, close_already_in_progress); } }); } private boolean _dispose(boolean for_restart, boolean close_already_in_progress) { if (isAlreadyDead) { return true; } if (!UIExitUtilsSWT.canClose(globalManager, for_restart)) { return false; } if (systemTraySWT != null) { systemTraySWT.dispose(); } /** * Explicitly force the transfer bar location to be saved (if appropriate and open). * * We can't rely that the normal mechanism for doing this won't fail (which it usually does) * when the GUI is being disposed of. */ try { AllTransfersBar transfer_bar = AllTransfersBar.getBarIfOpen(AzureusCoreFactory.getSingleton().getGlobalManager()); if (transfer_bar != null) { transfer_bar.forceSaveLocation(); } } catch (Exception e) { // ignore } // close all tabs mainTabSet.closeAllTabs(); isAlreadyDead = true; //NICO try to never die twice... /* if (this.trayIcon != null) SysTrayMenu.dispose(); */ if (initializer != null) { initializer.stopIt(for_restart, close_already_in_progress); } //NICO swt disposes the mainWindow all by itself (thanks... ;-( ) on macosx if (!shell.isDisposed() && !isDisposeFromListener) { shell.dispose(); } COConfigurationManager.removeParameterListener("config.style.useSIUnits", this); COConfigurationManager.removeParameterListener("config.style.forceSIValues", this); COConfigurationManager.removeParameterListener("Show Download Basket", this); UIExitUtilsSWT.uiShutdown(); return true; } protected GlobalManager getGlobalManager() { return globalManager; } /** * @return */ protected static MainWindow getWindow() { return window; } /** * @return */ protected TrayWindow getTray() { return downloadBasket; } Map pluginTabs = new HashMap(); protected Item openPluginView(String sParentID, String sViewID, UISWTViewEventListener l, Object dataSource, boolean bSetFocus, boolean useCoreDS) { UISWTViewImpl view = null; try { view = new UISWTViewImpl(sParentID, sViewID, l); } catch (Exception e) { Item tab = (Item) pluginTabs.get(sViewID); if (tab != null) { mainTabSet.setFocus(tab); } return tab; } view.setUseCoreDataSource(useCoreDS); view.dataSourceChanged(dataSource); Item tab = mainTabSet.createTabItem(view, bSetFocus); pluginTabs.put(sViewID, tab); return tab; } /** * Close all plugin views with the specified ID * * @param sViewID */ protected void closePluginViews(String sViewID) { if (mainTabSet != null) { mainTabSet.closePluginViews(sViewID); } } /** * Get all open Plugin Views * * @return open plugin views */ protected UISWTView[] getPluginViews() { IView[] allViews = mainTabSet.getAllViews(); ArrayList views = new ArrayList(); for (int i = 0; i < allViews.length; i++) { IView view = allViews[i]; if (view instanceof UISWTViewImpl) { views.add(view); } } return (UISWTView[]) views.toArray(new UISWTView[0]); } protected void openPluginView(final AbstractIView view, final String name) { Utils.execSWTThread(new AERunnable() { public void runSupport() { Item tab = (Item) pluginTabs.get(name); if (tab != null) { mainTabSet.setFocus(tab); } else { tab = mainTabSet.createTabItem(view, true); pluginTabs.put(name, tab); } } }); } protected void closePluginView(IView view) { Item tab = mainTabSet.getTab(view); if (tab != null) { mainTabSet.closed(tab); } } public void removeActivePluginView(String view_name) { pluginTabs.remove(view_name); } // @see org.gudy.azureus2.core3.config.ParameterListener#parameterChanged(java.lang.String) public void parameterChanged(String parameterName) { if (parameterName.equals("Show Download Basket")) { if (COConfigurationManager.getBooleanParameter("Show Download Basket")) { if (downloadBasket == null) { downloadBasket = new TrayWindow(this); downloadBasket.setVisible(true); } } else if (downloadBasket != null) { downloadBasket.setVisible(false); downloadBasket = null; } } if (parameterName.equals("config.style.useSIUnits") || parameterName.equals("config.style.forceSIValues")) { updateComponents(); } } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#isEnabled(java.lang.String) public boolean isEnabled(String itemKey) { if (itemKey.equals("open")) return true; if (itemKey.equals("new")) return true; IView currentView = getCurrentView(); if (currentView instanceof UISWTViewImpl) { UISWTViewEventListener eventListener = ((UISWTViewImpl) currentView).getEventListener(); if (eventListener instanceof IconBarEnabler) { return ((IconBarEnabler)eventListener).isEnabled(itemKey); } } if (currentView != null) return currentView.isEnabled(itemKey); return false; } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#isSelected(java.lang.String) public boolean isSelected(String itemKey) { return false; } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#itemActivated(java.lang.String) public void itemActivated(String itemKey) { if (itemKey.equals("open")) { TorrentOpener.openTorrentWindow(); return; } if (itemKey.equals("new")) { new NewTorrentWizard(display); return; } IView currentView = getCurrentView(); if (currentView instanceof UISWTViewImpl) { UISWTViewEventListener eventListener = ((UISWTViewImpl) currentView).getEventListener(); if (eventListener instanceof IconBarEnabler) { ((IconBarEnabler)eventListener).itemActivated(itemKey); return; } } if (currentView != null) currentView.itemActivated(itemKey); } IView getCurrentView() { if (mainTabSet != null) { return mainTabSet.getCurrentView(); } return null; } protected void refreshIconBar() { if (iconBar != null) { iconBar.setCurrentEnabler(this); } } protected void refreshTorrentMenu() { if (this.mainMenu == null) { return; } DownloadManager[] dm; boolean detailed_view; TableViewSWT tv = null; IView currentView = getCurrentView(); if (currentView instanceof ManagerView) { dm = new DownloadManager[] { ((ManagerView) currentView).getDownload(), }; detailed_view = true; } else if (currentView instanceof UISWTView) { UISWTView current_swt_view = (UISWTView)currentView; Object core_object = PluginCoreUtils.convert(current_swt_view.getDataSource(), true); if (core_object instanceof DownloadManager) { dm = new DownloadManager[] {(DownloadManager)core_object}; // We should be using a constant somewhere! detailed_view = "DMView".equals(current_swt_view.getViewID()); } else { dm = null; detailed_view = false; } } else if (currentView instanceof MyTorrentsSuperView) { dm = ((MyTorrentsSuperView) this.getCurrentView()).getSelectedDownloads(); detailed_view = false; } else { dm = null; detailed_view = false; } if (currentView instanceof TableViewTab) { tv = ((TableViewTab) currentView).getTableView(); } /* * KN: Reflectively find the Torrents menu item and update its data */ final MenuItem torrentItem = MenuFactory.findMenuItem( mainMenu.getMenu(IMenuConstants.MENU_ID_MENU_BAR), MenuFactory.MENU_ID_TORRENT); if (null != torrentItem) { final DownloadManager[] dm_final = dm; final TableViewSWT tv_final = tv; final boolean detailed_view_final = detailed_view; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (null == dm_final) { torrentItem.setEnabled(false); } else { torrentItem.setData("downloads", dm_final); torrentItem.setData("TableView", tv_final); torrentItem.setData("is_detailed_view", Boolean.valueOf(detailed_view_final)); torrentItem.setEnabled(true); } } }, true); // async } } protected void close() { getShell().close(); } protected void closeViewOrWindow() { if (getCurrentView() != null) mainTabSet.closeCurrent(); else close(); } protected ConfigView showConfig() { if (config == null) { config_view = new ConfigView(); config = mainTabSet.createTabItem(config_view, true); config_view.getComposite().addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { config = null; config_view = null; } }); } else { mainTabSet.setFocus(config); refreshIconBar(); refreshTorrentMenu(); } return config_view; } protected boolean showConfig(String id) { boolean has_rebuilt = config_view == null; showConfig(); if (config_view == null) { return false; } if (id == null) { return true; } boolean result = config_view.selectSection(id); if (!result && !has_rebuilt) { config.dispose(); if (config_view != null) {throw new RuntimeException("something has gone wrong");} return showConfig(id); } return result; } protected void showConsole() { if (console == null) { console = mainTabSet.createTabItem(new LoggerView(events), true); mainTabSet.getView(console).getComposite().addDisposeListener( new DisposeListener() { public void widgetDisposed(DisposeEvent e) { console = null; } }); } else { mainTabSet.setFocus(console); refreshIconBar(); refreshTorrentMenu(); } } protected void showStats() { if (stats_tab == null) { stats_tab = mainTabSet.createTabItem(new StatsView(), true); mainTabSet.getView(stats_tab).getComposite().addDisposeListener( new DisposeListener() { public void widgetDisposed(DisposeEvent e) { stats_tab = null; } }); } else { mainTabSet.setFocus(stats_tab); refreshIconBar(); refreshTorrentMenu(); } } protected void showStatsDHT() { showStats(); if (stats_tab == null) { return; } IView view = mainTabSet.getView(stats_tab); if (view instanceof StatsView) { ((StatsView) view).showDHT(); } } protected void showStatsTransfers() { showStats(); if (stats_tab == null) { return; } IView view = mainTabSet.getView(stats_tab); if (view instanceof StatsView) { ((StatsView) view).showTransfers(); } } protected void setSelectedLanguageItem() { try { this_mon.enter(); Messages.updateLanguageForControl(shell); if (systemTraySWT != null) { systemTraySWT.updateLanguage(); } if (mainStatusBar != null) { mainStatusBar.refreshStatusText(); } if (folder != null) { folder.update(); } if (downloadBasket != null) { downloadBasket.updateLanguage(); } mainTabSet.updateLanguage(); if (mainStatusBar != null) { mainStatusBar.updateStatusText(); } if (mainMenu != null) { MenuFactory.updateMenuText(mainMenu.getMenu(IMenuConstants.MENU_ID_MENU_BAR)); } } finally { this_mon.exit(); } } /** * @deprecated Use {@link #getMainMenu()} instead * @return */ public MainMenu getMenu() { return (MainMenu) mainMenu; } /** * @deprecated Use {@link #setMainMenu(IMainMenu)} instead * @param menu */ public void setMenu(MainMenu menu) { mainMenu = menu; } public IMainMenu getMainMenu() { return mainMenu; } public void setMainMenu(IMainMenu menu) { mainMenu = menu; } protected AzureusCore getAzureusCore() { return (azureus_core); } // @see org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator#generate(org.gudy.azureus2.core3.util.IndentWriter) public void generate(IndentWriter writer) { writer.println("SWT UI"); try { writer.indent(); mainTabSet.generateDiagnostics(writer); TableColumnManager.getInstance().generateDiagnostics(writer); } finally { writer.exdent(); } } private void checkForWhatsNewWindow() { final String CONFIG_LASTSHOWN = "welcome.version.lastshown"; // Config used to store int, such as 2500. Now, it stores a string // getIntParameter will return default value if parameter is string (user // downgraded) // getStringParameter will bork if parameter isn't really a string try { String lastShown = ""; boolean bIsStringParam = true; try { lastShown = COConfigurationManager.getStringParameter(CONFIG_LASTSHOWN, ""); } catch (Exception e) { bIsStringParam = false; } if (lastShown.length() == 0) { // check if we have an old style version int latestDisplayed = COConfigurationManager.getIntParameter( CONFIG_LASTSHOWN, 0); if (latestDisplayed > 0) { bIsStringParam = false; String s = "" + latestDisplayed; for (int i = 0; i < s.length(); i++) { if (i != 0) { lastShown += "."; } lastShown += s.charAt(i); } } } if (Constants.compareVersions(lastShown, Constants.getBaseVersion()) < 0) { new WelcomeWindow(shell); if (!bIsStringParam) { // setting parameter to a different value type makes az unhappy COConfigurationManager.removeParameter(CONFIG_LASTSHOWN); } COConfigurationManager.setParameter(CONFIG_LASTSHOWN, Constants.getBaseVersion()); COConfigurationManager.save(); } } catch (Exception e) { Debug.out(e); } } protected UISWTInstanceImpl getUISWTInstanceImpl() { return uiSWTInstanceImpl; } /** * @param string */ protected void setStatusText(String string) { // TODO Auto-generated method stub if (mainStatusBar != null) mainStatusBar.setStatusText(string); } /** * @param statustype * @param string * @param l */ protected void setStatusText(int statustype, String string, UIStatusTextClickListener l) { if (mainStatusBar != null) { mainStatusBar.setStatusText(statustype, string, l); } } protected SystemTraySWT getSystemTraySWT() { return systemTraySWT; } protected MainStatusBar getMainStatusBar() { return mainStatusBar; } // @see org.gudy.azureus2.ui.swt.debug.ObfusticateShell#generateObfusticatedImage() public Image generateObfusticatedImage() { Image image; IView[] allViews = mainTabSet.getAllViews(); for (int i = 0; i < allViews.length; i++) { IView view = allViews[i]; if (view instanceof ObfusticateTab) { Item tab = mainTabSet.getTab(view); tab.setText(((ObfusticateTab) view).getObfusticatedHeader()); folder.update(); } } Rectangle clientArea = shell.getClientArea(); image = new Image(display, clientArea.width, clientArea.height); GC gc = new GC(shell); try { gc.copyArea(image, clientArea.x, clientArea.y); } finally { gc.dispose(); } IView currentView = getCurrentView(); if (currentView instanceof ObfusticateImage) { Point ofs = shell.toDisplay(clientArea.x, clientArea.y); try { ((ObfusticateImage) currentView).obfusticatedImage(image, ofs); } catch (Exception e) { Debug.out("Obfusticating " + currentView, e); } } for (int i = 0; i < allViews.length; i++) { IView view = allViews[i]; if (view instanceof ObfusticateTab) { view.refresh(); } } return image; } private static Point getStoredWindowSize() { Point size = null; boolean isMaximized = COConfigurationManager.getBooleanParameter( "window.maximized", false); if (isMaximized) { Monitor monitor = SWTThread.getInstance().getPrimaryMonitor(); if (Utils.isThisThreadSWT()) { if (window != null && window.getShell() != null && !window.getShell().isDisposed()) { monitor = window.getShell().getMonitor(); } } if (monitor != null) { Rectangle clientArea = monitor.getClientArea(); size = new Point(clientArea.width, clientArea.height); return size; } } String windowRectangle = COConfigurationManager.getStringParameter( "window.rectangle", null); if (windowRectangle != null) { String[] values = windowRectangle.split(","); if (values.length == 4) { try { size = new Point(Integer.parseInt(values[2]), Integer.parseInt(values[3])); } catch (Exception e) { } } } return size; } public static void addToVersionCheckMessage(final Map map) { try { Point size = getStoredWindowSize(); if (size == null) { return; } map.put("mainwindow.w", new Long(size.x)); map.put("mainwindow.h", new Long(size.y)); } catch (Throwable e) { e.printStackTrace(); } } public UIFunctionsSWT getUIFunctions() { return uiFunctions; } public boolean isVisible(int windowElement) { if (windowElement == IMainWindow.WINDOW_ELEMENT_TOOLBAR) { return bIconBarEnabled; } else if (windowElement == IMainWindow.WINDOW_ELEMENT_STATUSBAR) { //TODO: } else if (windowElement == IMainWindow.WINDOW_ELEMENT_MENU) { //TODO: } return true; } public void setVisible(int windowElement, boolean value) { if (windowElement == IMainWindow.WINDOW_ELEMENT_TOOLBAR) { setIconBarEnabled(value); } else if (windowElement == IMainWindow.WINDOW_ELEMENT_STATUSBAR) { //TODO: } else if (windowElement == IMainWindow.WINDOW_ELEMENT_MENU) { //TODO: } } public Rectangle getMetrics(int windowElement) { if (windowElement == IMainWindow.WINDOW_ELEMENT_TOOLBAR) { if (null != iconBar && null != iconBar.getComposite()) { return iconBar.getComposite().getBounds(); } } else if (windowElement == IMainWindow.WINDOW_ELEMENT_STATUSBAR) { return mainStatusBar.getBounds(); } else if (windowElement == IMainWindow.WINDOW_ELEMENT_TOPBAR) { //KN: No search bar in classic UI } else if (windowElement == IMainWindow.WINDOW_ELEMENT_TABBAR) { //KN: No tab bar in classic UI } else if (windowElement == IMainWindow.WINDOW_CLIENT_AREA) { return shell.getClientArea(); } else if (windowElement == IMainWindow.WINDOW_CONTENT_DISPLAY_AREA) { Rectangle r = shell.getClientArea(); r.x += iconBar.getComposite().getBounds().x; r.height -= iconBar.getComposite().getBounds().height; r.height -= mainStatusBar.getBounds().height; return r; } return new Rectangle(0, 0, 0, 0); } /** * * * @since 3.1.1.1 */ public void closeAllDetails() { if (mainTabSet != null) { mainTabSet.closeAllDetails(); } } /** * @return * * @since 3.1.1.1 */ public boolean hasDetailViews() { if (mainTabSet != null) { return( mainTabSet.hasDetails()); } return false; } public Tab getMainTabSet() { return mainTabSet; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/DebugMenuHelper.java0000644000175000017500000001214011237542240025437 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.mainwindow; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.DisplayFormatters; import com.aelitis.azureus.plugins.startstoprules.defaultplugin.StartStopRulesDefaultPlugin; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; /** * A convenience class for creating the Debug menu *

    * This has been extracted out into its own class since it does not really belong to production code * @author knguyen * */ public class DebugMenuHelper { /** * Creates the Debug menu and its children * NOTE: This is a development only menu and so it's not modularized into separate menu items * because this menu is always rendered in its entirety * @param menu * @param mainWindow * @return */ public static Menu createDebugMenuItem(final Menu menu) { MenuItem item; final UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (null == uiFunctions) { throw new IllegalStateException( "UIFunctionsManagerSWT.getUIFunctionsSWT() is returning null"); } item = new MenuItem(menu, SWT.CASCADE); item.setText("&Debug"); Menu menuDebug = new Menu(menu.getParent(), SWT.DROP_DOWN); item.setMenu(menuDebug); item = new MenuItem(menuDebug, SWT.CASCADE); item.setText("ScreenSize"); Menu menuSS = new Menu(menu.getParent(), SWT.DROP_DOWN); item.setMenu(menuSS); item = new MenuItem(menuSS, SWT.NONE); item.setText("640x400"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { uiFunctions.getMainShell().setSize(640, 400); } }); item = new MenuItem(menuSS, SWT.NONE); item.setText("800x560"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { uiFunctions.getMainShell().setSize(850, 560); } }); item = new MenuItem(menuSS, SWT.NONE); item.setText("1024x700"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { uiFunctions.getMainShell().setSize(1024, 700); } }); item = new MenuItem(menuSS, SWT.NONE); item.setText("1024x768"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { uiFunctions.getMainShell().setSize(1024, 768); } }); item = new MenuItem(menuSS, SWT.NONE); item.setText("1152x784"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { uiFunctions.getMainShell().setSize(1152, 784); } }); item = new MenuItem(menuSS, SWT.NONE); item.setText("1280x720"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { uiFunctions.getMainShell().setSize(1280, 720); } }); item = new MenuItem(menuSS, SWT.NONE); item.setText("1280x1024"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { uiFunctions.getMainShell().setSize(1280, 1024); } }); item = new MenuItem(menuSS, SWT.NONE); item.setText("1440x820"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { uiFunctions.getMainShell().setSize(1440, 820); } }); item = new MenuItem(menuSS, SWT.NONE); item.setText("1600x970"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { uiFunctions.getMainShell().setSize(1600, 970); } }); item = new MenuItem(menuSS, SWT.NONE); item.setText("1920x1200"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { uiFunctions.getMainShell().setSize(1920, 1200); } }); item = new MenuItem(menuSS, SWT.NONE); item.setText("2560x1520"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { uiFunctions.getMainShell().setSize(2560, 1520); } }); item = new MenuItem(menuDebug, SWT.NONE); item.setText("Reload messagebundle"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { MessageText.loadBundle(true); DisplayFormatters.setUnits(); DisplayFormatters.loadMessages(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshLanguage(); } } }); item = new MenuItem(menuDebug, SWT.CHECK); item.setText("SR ChangeFlagChecker Paused"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { StartStopRulesDefaultPlugin.pauseChangeFlagChecker = !StartStopRulesDefaultPlugin.pauseChangeFlagChecker; ((MenuItem)e.widget).setSelection(StartStopRulesDefaultPlugin.pauseChangeFlagChecker); } }); return menuDebug; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/MenuFactory.java0000644000175000017500000012553711306350314024673 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.mainwindow; import java.util.Iterator; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.ui.menus.MenuManager; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.plugins.update.UpdateCheckInstance; import org.gudy.azureus2.plugins.update.UpdateCheckInstanceListener; import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl; import org.gudy.azureus2.ui.common.util.MenuItemManager; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.components.shell.ShellManager; import org.gudy.azureus2.ui.swt.config.wizard.ConfigureWizard; import org.gudy.azureus2.ui.swt.debug.UIDebugGenerator; import org.gudy.azureus2.ui.swt.donations.DonationWindow; import org.gudy.azureus2.ui.swt.exporttorrent.wizard.ExportTorrentWizard; import org.gudy.azureus2.ui.swt.help.AboutWindow; import org.gudy.azureus2.ui.swt.help.HealthHelpWindow; import org.gudy.azureus2.ui.swt.importtorrent.wizard.ImportTorrentWizard; import org.gudy.azureus2.ui.swt.maketorrent.NewTorrentWizard; import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar; import org.gudy.azureus2.ui.swt.minibar.MiniBarManager; import org.gudy.azureus2.ui.swt.nat.NatTestWindow; import org.gudy.azureus2.ui.swt.pluginsinstaller.InstallPluginWizard; import org.gudy.azureus2.ui.swt.pluginsuninstaller.UnInstallPluginWizard; import org.gudy.azureus2.ui.swt.sharing.ShareUtils; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.speedtest.SpeedTestWizard; import org.gudy.azureus2.ui.swt.update.UpdateMonitor; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.utils.TableContextMenuManager; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import org.gudy.azureus2.ui.swt.welcome.WelcomeWindow; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.vuzefile.VuzeFileComponent; import com.aelitis.azureus.core.vuzefile.VuzeFileHandler; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; public class MenuFactory implements IMenuConstants { private static boolean isAZ3 = "az3".equalsIgnoreCase(COConfigurationManager.getStringParameter("ui")); public static MenuItem createFileMenuItem(Menu menuParent) { return createTopLevelMenuItem(menuParent, MENU_ID_FILE); } public static MenuItem createTransfersMenuItem(Menu menuParent) { MenuItem transferMenuItem = createTopLevelMenuItem(menuParent, MENU_ID_TRANSFERS); Menu transferMenu = transferMenuItem.getMenu(); MenuFactory.addStartAllMenuItem(transferMenu); MenuFactory.addStopAllMenuItem(transferMenu); final MenuItem itemPause = MenuFactory.addPauseMenuItem(transferMenu); final MenuItem itemResume = MenuFactory.addResumeMenuItem(transferMenu); // if (notMainWindow) { // MenuFactory.performOneTimeDisable(itemPause, true); // MenuFactory.performOneTimeDisable(itemResume, true); // } transferMenu.addMenuListener(new MenuListener() { public void menuShown(MenuEvent menu) { if (!AzureusCoreFactory.isCoreRunning()) { itemPause.setEnabled(false); itemResume.setEnabled(false); } else { AzureusCore core = AzureusCoreFactory.getSingleton(); itemPause.setEnabled(core.getGlobalManager().canPauseDownloads()); itemResume.setEnabled(core.getGlobalManager().canResumeDownloads()); } } public void menuHidden(MenuEvent menu) { } }); return transferMenuItem; } public static MenuItem createViewMenuItem(Menu menuParent) { return createTopLevelMenuItem(menuParent, MENU_ID_VIEW); } public static MenuItem createAdvancedMenuItem(Menu menuParent) { return createTopLevelMenuItem(menuParent, MENU_ID_ADVANCED); } public static MenuItem createTorrentMenuItem(final Menu menuParent) { final MenuItem torrentItem = createTopLevelMenuItem(menuParent, MENU_ID_TORRENT); /* * The Torrents menu is context-sensitive to which torrent is selected in the UI. * For this reason we need to dynamically build the menu when ever it is about to be displayed * so that the states of the menu items accurately reflect what was selected in the UI. */ MenuBuildUtils.addMaintenanceListenerForMenu(torrentItem.getMenu(), new MenuBuildUtils.MenuBuilder() { public void buildMenu(Menu menu, MenuEvent menuEvent) { DownloadManager[] current_dls = (DownloadManager[]) torrentItem.getData("downloads"); if (current_dls == null) { return; } if (AzureusCoreFactory.isCoreRunning()) { boolean is_detailed_view = ((Boolean) torrentItem.getData("is_detailed_view")).booleanValue(); TableViewSWT tv = (TableViewSWT) torrentItem.getData("TableView"); AzureusCore core = AzureusCoreFactory.getSingleton(); TorrentUtil.fillTorrentMenu(menu, current_dls, core, menuParent.getShell(), !is_detailed_view, 0, tv); } org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items; menu_items = MenuItemManager.getInstance().getAllAsArray( new String[] { MenuManager.MENU_TORRENT_MENU, MenuManager.MENU_DOWNLOAD_CONTEXT }); final Object[] plugin_dls = DownloadManagerImpl.getDownloadStatic(current_dls); if (menu_items.length > 0) { addSeparatorMenuItem(menu); MenuBuildUtils.addPluginMenuItems(menuParent.getShell(), menu_items, menu, true, true, new MenuBuildUtils.MenuItemPluginMenuControllerImpl( plugin_dls)); } menu_items = null; /** * OK, "hack" time - we'll allow plugins which add menu items against * a table to appear in this menu. We'll have to fake the table row * object though. All downloads need to share a common table. */ String table_to_use = null; for (int i = 0; i < current_dls.length; i++) { String table_name = (current_dls[i].isDownloadComplete(false) ? TableManager.TABLE_MYTORRENTS_COMPLETE : TableManager.TABLE_MYTORRENTS_INCOMPLETE); if (table_to_use == null || table_to_use.equals(table_name)) { table_to_use = table_name; } else { table_to_use = null; break; } } if (table_to_use != null) { menu_items = TableContextMenuManager.getInstance().getAllAsArray( table_to_use); } if (menu_items != null) { addSeparatorMenuItem(menu); TableRow[] dls_as_rows = null; dls_as_rows = new TableRow[plugin_dls.length]; for (int i = 0; i < plugin_dls.length; i++) { dls_as_rows[i] = wrapAsRow(plugin_dls[i], table_to_use); } MenuBuildUtils.addPluginMenuItems(menuParent.getShell(), menu_items, menu, true, true, new MenuBuildUtils.MenuItemPluginMenuControllerImpl( dls_as_rows)); } } }); return torrentItem; } public static MenuItem createToolsMenuItem(Menu menuParent) { return createTopLevelMenuItem(menuParent, MENU_ID_TOOLS); } /** * Creates the Plugins menu item and all it's children * @param menuParent * @param includeGetPluginsMenu if true then also include a menu item for getting new plugins * @return */ public static MenuItem createPluginsMenuItem(final Menu menuParent, final boolean includeGetPluginsMenu) { MenuItem pluginsMenuItem = createTopLevelMenuItem(menuParent, MENU_ID_PLUGINS); MenuBuildUtils.addMaintenanceListenerForMenu(pluginsMenuItem.getMenu(), new MenuBuildUtils.MenuBuilder() { public void buildMenu(Menu menu, MenuEvent menuEvent) { PluginsMenuHelper.getInstance().buildPluginMenu(menu, menuParent.getShell(), includeGetPluginsMenu); } }); return pluginsMenuItem; } public static MenuItem createWindowMenuItem(Menu menuParent) { return createTopLevelMenuItem(menuParent, MENU_ID_WINDOW); } public static MenuItem createHelpMenuItem(Menu menuParent) { return createTopLevelMenuItem(menuParent, MENU_ID_HELP); } public static MenuItem addCreateMenuItem(Menu menuParent) { MenuItem file_create = addMenuItem(menuParent, MENU_ID_CREATE, new Listener() { public void handleEvent(Event e) { new NewTorrentWizard(e.display); } }); return file_create; } public static MenuItem createOpenMenuItem(Menu menuParent) { return createTopLevelMenuItem(menuParent, MENU_ID_OPEN); } public static MenuItem addLogsViewMenuItem(Menu menuParent) { return createTopLevelMenuItem(menuParent, MENU_ID_LOG_VIEWS); } public static MenuItem addOpenTorrentMenuItem(Menu menuParent) { return addMenuItem(menuParent, MENU_ID_OPEN_TORRENT, new Listener() { public void handleEvent(Event e) { TorrentOpener.openTorrentWindow(); } }); } public static MenuItem addOpenTorrentForTrackingMenuItem(Menu menuParent) { MenuItem file_new_torrent_for_tracking = addMenuItem(menuParent, MENU_ID_OPEN_TORRENT_FOR_TRACKING, new Listener() { public void handleEvent(Event e) { TorrentOpener.openTorrentTrackingOnly(); } }); return file_new_torrent_for_tracking; } public static MenuItem addOpenVuzeFileMenuItem(final Menu menuParent) { return addMenuItem(menuParent, MENU_ID_OPEN_VUZE_FILE, new Listener() { public void handleEvent(Event e) { Display display = menuParent.getDisplay(); display.asyncExec(new AERunnable() { public void runSupport() { FileDialog dialog = new FileDialog(menuParent.getShell(), SWT.SYSTEM_MODAL | SWT.OPEN); dialog.setFilterPath(TorrentOpener.getFilterPathData()); dialog.setText(MessageText.getString("MainWindow.dialog.select.vuze.file")); dialog.setFilterExtensions(new String[] { "*.vuze", "*.vuz", Constants.FILE_WILDCARD }); dialog.setFilterNames(new String[] { "*.vuze", "*.vuz", Constants.FILE_WILDCARD }); String path = TorrentOpener.setFilterPathData(dialog.open()); if (path != null) { VuzeFileHandler vfh = VuzeFileHandler.getSingleton(); if (vfh.loadAndHandleVuzeFile(path, VuzeFileComponent.COMP_TYPE_NONE) == null) { TorrentOpener.openTorrent(path); } } } }); } }); } public static MenuItem createShareMenuItem(Menu menuParent) { MenuItem file_share = createTopLevelMenuItem(menuParent, MENU_ID_SHARE); return file_share; } public static MenuItem addShareFileMenuItem(final Menu menuParent) { MenuItem file_share_file = addMenuItem(menuParent, MENU_ID_SHARE_FILE, new Listener() { public void handleEvent(Event e) { ShareUtils.shareFile(menuParent.getShell()); } }); return file_share_file; } public static MenuItem addShareFolderMenuItem(final Menu menuParent) { MenuItem file_share_dir = addMenuItem(menuParent, MENU_ID_SHARE_DIR, new Listener() { public void handleEvent(Event e) { ShareUtils.shareDir(menuParent.getShell()); } }); return file_share_dir; } public static MenuItem addShareFolderContentMenuItem(final Menu menuParent) { MenuItem file_share_dircontents = addMenuItem(menuParent, MENU_ID_SHARE_DIR_CONTENT, new Listener() { public void handleEvent(Event e) { ShareUtils.shareDirContents(menuParent.getShell(), false); } }); return file_share_dircontents; } public static MenuItem addShareFolderContentRecursiveMenuItem( final Menu menuParent) { MenuItem file_share_dircontents_rec = addMenuItem(menuParent, MENU_ID_SHARE_DIR_CONTENT_RECURSE, new Listener() { public void handleEvent(Event e) { ShareUtils.shareDirContents(menuParent.getShell(), true); } }); return file_share_dircontents_rec; } public static MenuItem addImportMenuItem(Menu menuParent) { MenuItem file_import = addMenuItem(menuParent, MENU_ID_IMPORT, new Listener() { public void handleEvent(Event e) { new ImportTorrentWizard(); } }); return file_import; } public static MenuItem addExportMenuItem(Menu menuParent) { MenuItem file_export = addMenuItem(menuParent, MENU_ID_EXPORT, new Listener() { public void handleEvent(Event e) { new ExportTorrentWizard(); } }); return file_export; } public static MenuItem addCloseWindowMenuItem(final Menu menuParent) { MenuItem closeWindow = addMenuItem(menuParent, MENU_ID_WINDOW_CLOSE, new Listener() { public void handleEvent(Event event) { Shell shell = menuParent.getShell(); if (shell != null && !shell.isDisposed()) { menuParent.getShell().close(); } } }); return closeWindow; } public static MenuItem addCloseTabMenuItem(Menu menu, final MainWindow mainWindow) { return addMenuItem(menu, MENU_ID_CLOSE_TAB, new Listener() { public void handleEvent(Event event) { if (MainWindow.isAlreadyDead) { return; } mainWindow.closeViewOrWindow(); } }); } public static MenuItem addCloseDetailsMenuItem(Menu menu) { final MenuItem item = addMenuItem(menu, MENU_ID_CLOSE_ALL_DETAIL, new Listener() { public void handleEvent(Event e) { UIFunctionsManagerSWT.getUIFunctionsSWT().closeAllDetails(); } }); Listener enableHandler = new Listener() { public void handleEvent(Event event) { if (true == MenuFactory.isEnabledForCurrentMode(item)) { if (false == item.isDisposed() && false == event.widget.isDisposed()) { boolean hasDetails = UIFunctionsManagerSWT.getUIFunctionsSWT().hasDetailViews(); item.setEnabled(hasDetails); } } } }; menu.addListener(SWT.Show, enableHandler); return item; } public static MenuItem addCloseDownloadBarsToMenu(Menu menu) { final MenuItem item = addMenuItem(menu, MENU_ID_CLOSE_ALL_DL_BARS, new Listener() { public void handleEvent(Event e) { MiniBarManager.getManager().closeAll(); } }); Listener enableHandler = new Listener() { public void handleEvent(Event event) { if (false == item.isDisposed()) { item.setEnabled(false == MiniBarManager.getManager().getShellManager().isEmpty()); } } }; menu.addListener(SWT.Show, enableHandler); // shell.addListener(SWT.FocusIn, enableHandler); return item; } public static MenuItem addRestartMenuItem(Menu menuParent) { MenuItem file_restart = new MenuItem(menuParent, SWT.NULL); Messages.setLanguageText(file_restart, MENU_ID_RESTART); //$NON-NLS-1$ file_restart.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { UIFunctionsManagerSWT.getUIFunctionsSWT().dispose(true, false); } }); return file_restart; } public static MenuItem addExitMenuItem(Menu menuParent) { final MenuItem file_exit = new MenuItem(menuParent, SWT.NULL); if (!COConfigurationManager.getBooleanParameter("Enable System Tray") || !COConfigurationManager.getBooleanParameter("Close To Tray")) { KeyBindings.setAccelerator(file_exit, MENU_ID_EXIT); } Messages.setLanguageText(file_exit, MENU_ID_EXIT); //$NON-NLS-1$ file_exit.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { UIFunctionsManagerSWT.getUIFunctionsSWT().dispose(false, false); } }); // let platform decide ParameterListener paramListener = new ParameterListener() { public void parameterChanged(String parameterName) { if (COConfigurationManager.getBooleanParameter("Enable System Tray") && COConfigurationManager.getBooleanParameter("Close To Tray")) { KeyBindings.removeAccelerator(file_exit, MENU_ID_EXIT); } else { KeyBindings.setAccelerator(file_exit, MENU_ID_EXIT); } } }; COConfigurationManager.addParameterListener("Enable System Tray", paramListener); COConfigurationManager.addParameterListener("Close To Tray", paramListener); return file_exit; } public static MenuItem addStartAllMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_START_ALL_TRANSFERS, new ListenerNeedingCoreRunning() { public void handleEvent(AzureusCore core, Event e) { core.getGlobalManager().startAllDownloads(); /* * KN: Not sure why we can not use the call below as opposed to the line above * which was the exiting code */ // ManagerUtils.asyncStartAll(); } }); } public static MenuItem addStopAllMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_STOP_ALL_TRANSFERS, new Listener() { public void handleEvent(Event event) { ManagerUtils.asyncStopAll(); } }); } public static MenuItem addPauseMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_PAUSE_TRANSFERS, new Listener() { public void handleEvent(Event event) { ManagerUtils.asyncPause(); } }); } public static MenuItem addResumeMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_RESUME_TRANSFERS, new Listener() { public void handleEvent(Event event) { ManagerUtils.asyncResume(); } }); } public static MenuItem addMyTorrentsMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_MY_TORRENTS, new Listener() { public void handleEvent(Event e) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_MYTORRENTS, null); } } }); } public static MenuItem addDetailedListMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_DETAILED_LIST, new Listener() { public void handleEvent(Event e) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_DETAILED_LISTVIEW, null); } } }); } public static MenuItem addAllPeersMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_ALL_PEERS, new Listener() { public void handleEvent(Event e) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_ALLPEERS, null); } } }); } public static MenuItem addClientStatsMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_CLIENT_STATS, new Listener() { public void handleEvent(Event e) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_PEERS_STATS, null); } } }); } public static MenuItem addMyTrackerMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_MY_TRACKERS, new Listener() { public void handleEvent(Event e) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_MYTRACKER, null); } } }); } public static MenuItem addMySharesMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_MY_SHARES, new Listener() { public void handleEvent(Event e) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_MYSHARES, null); } } }); } public static MenuItem addViewToolbarMenuItem(Menu menu) { final MenuItem item = addMenuItem(menu, SWT.CHECK, MENU_ID_TOOLBAR, new Listener() { public void handleEvent(Event e) { UIFunctionsSWT uiFunctions = getUIFunctionSWT(); if (null != uiFunctions) { IMainWindow mainWindow = uiFunctions.getMainWindow(); boolean isToolbarVisible = mainWindow.isVisible(IMainWindow.WINDOW_ELEMENT_TOOLBAR); mainWindow.setVisible(IMainWindow.WINDOW_ELEMENT_TOOLBAR, !isToolbarVisible); } } }); final ParameterListener listener = new ParameterListener() { public void parameterChanged(String parameterName) { item.setSelection(COConfigurationManager.getBooleanParameter(parameterName)); } }; COConfigurationManager.addAndFireParameterListener("IconBar.enabled", listener); item.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { COConfigurationManager.removeParameterListener("IconBar.enabled", listener); } }); return item; } public static MenuItem addTransferBarToMenu(final Menu menu) { final MenuItem item = addMenuItem(menu, SWT.CHECK, MENU_ID_TRANSFER_BAR, new ListenerNeedingCoreRunning() { public void handleEvent(AzureusCore core, Event e) { if (AllTransfersBar.getManager().isOpen( core.getGlobalManager())) { AllTransfersBar.close(core.getGlobalManager()); } else { AllTransfersBar.open(core.getGlobalManager(), menu.getShell()); } } }); menu.addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { item.setSelection(!MiniBarManager.getManager().getShellManager().isEmpty()); } }); return item; } public static MenuItem addBlockedIPsMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_IP_FILTER, new ListenerNeedingCoreRunning() { public void handleEvent(AzureusCore core, Event e) { BlockedIpsWindow.showBlockedIps(core, getUIFunctionSWT().getMainShell()); } }); } public static MenuItem addConsoleMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_CONSOLE, new Listener() { public void handleEvent(Event e) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_CONSOLE, null); } } }); } public static MenuItem addStatisticsMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_STATS, new Listener() { public void handleEvent(Event e) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_STATS, null); } } }); } public static MenuItem addNatTestMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_NAT_TEST, new Listener() { public void handleEvent(Event e) { new NatTestWindow(); } }); } public static MenuItem addSpeedTestMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_SPEED_TEST, new Listener() { public void handleEvent(Event e) { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { new SpeedTestWizard(); } }); } }); } public static MenuItem addConfigWizardMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_CONFIGURE, new Listener() { public void handleEvent(Event e) { new ConfigureWizard(false); } }); } public static MenuItem addOptionsMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_OPTIONS, new Listener() { public void handleEvent(Event e) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_CONFIG, null); } } }); } public static MenuItem addMinimizeWindowMenuItem(Menu menu) { final Shell shell = menu.getShell(); final MenuItem item = addMenuItem(menu, MENU_ID_WINDOW_MINIMIZE, new Listener() { public void handleEvent(Event event) { if (null == shell || shell.isDisposed()) { event.doit = false; return; } shell.setMinimized(true); } }); Listener enableHandler = new Listener() { public void handleEvent(Event event) { if (null == shell || true == shell.isDisposed() || true == item.isDisposed()) { event.doit = false; return; } if (((shell.getStyle() & SWT.MIN) != 0)) { item.setEnabled(false == shell.getMinimized()); } else { item.setEnabled(false); } } }; menu.addListener(SWT.Show, enableHandler); shell.addListener(SWT.FocusIn, enableHandler); shell.addListener(SWT.Iconify, enableHandler); shell.addListener(SWT.Deiconify, enableHandler); return item; } public static MenuItem addBringAllToFrontMenuItem(Menu menu) { final MenuItem item = addMenuItem(menu, MENU_ID_WINDOW_ALL_TO_FRONT, new Listener() { public void handleEvent(Event event) { Iterator iter = ShellManager.sharedManager().getWindows(); while (iter.hasNext()) { Shell shell = (Shell) iter.next(); if (!shell.isDisposed() && !shell.getMinimized()) shell.open(); } } }); final Listener enableHandler = new Listener() { public void handleEvent(Event event) { if (item.isDisposed()) { return; } Iterator iter = ShellManager.sharedManager().getWindows(); boolean hasNonMaximizedShell = false; while (iter.hasNext()) { Shell shell = (Shell) iter.next(); if (false == shell.isDisposed() && false == shell.getMinimized()) { hasNonMaximizedShell = true; break; } } item.setEnabled(hasNonMaximizedShell); } }; menu.addListener(SWT.Show, enableHandler); menu.getShell().addListener(SWT.FocusIn, enableHandler); ShellManager.sharedManager().addWindowAddedListener(enableHandler); ShellManager.sharedManager().addWindowRemovedListener(enableHandler); item.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent event) { ShellManager.sharedManager().removeWindowAddedListener(enableHandler); ShellManager.sharedManager().removeWindowRemovedListener(enableHandler); } }); return item; } /** * Appends the list of opened interactive windows to the bottom of the specified shell menu * @param menuParent The shell menu * @param shell */ public static void appendWindowMenuItems(final Menu menuParent) { final Shell shell = menuParent.getShell(); final int numTopItems = menuParent.getItemCount(); Listener rebuild = new Listener() { public void handleEvent(Event event) { try { if (menuParent.isDisposed() || shell.isDisposed()) return; final int size = ShellManager.sharedManager().getSize(); if (size == menuParent.getItemCount() - numTopItems) { for (int i = numTopItems; i < menuParent.getItemCount(); i++) { final MenuItem item = menuParent.getItem(i); item.setSelection(item.getData() == shell); } return; } for (int i = numTopItems; i < menuParent.getItemCount();) menuParent.getItem(i).dispose(); Iterator iter = ShellManager.sharedManager().getWindows(); for (int i = 0; i < size; i++) { final Shell sh = (Shell) iter.next(); if (sh.isDisposed() || sh.getText().length() == 0) continue; final MenuItem item = new MenuItem(menuParent, SWT.CHECK); item.setText(sh.getText()); item.setSelection(shell == sh); item.setData(sh); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { if (event.widget.isDisposed() || sh.isDisposed()) return; if (sh.getMinimized()) sh.setMinimized(false); sh.open(); } }); } } catch (Exception e) { Logger.log(new LogEvent(LogIDs.GUI, "rebuild menu error", e)); } } }; ShellManager.sharedManager().addWindowAddedListener(rebuild); ShellManager.sharedManager().addWindowRemovedListener(rebuild); shell.addListener(SWT.FocusIn, rebuild); menuParent.addListener(SWT.Show, rebuild); } public static MenuItem addZoomWindowMenuItem(Menu menuParent) { final Shell shell = menuParent.getShell(); final MenuItem item = addMenuItem(menuParent, MENU_ID_WINDOW_ZOOM, new Listener() { public void handleEvent(Event event) { if (shell.isDisposed()) { event.doit = false; return; } shell.setMaximized(!shell.getMaximized()); } }); Listener enableHandler = new Listener() { public void handleEvent(Event event) { if ( !shell.isDisposed() && !item.isDisposed()) { if (false == Constants.isOSX) { if (true == shell.getMaximized()) { Messages.setLanguageText( item, MessageText.resolveLocalizationKey(MENU_ID_WINDOW_ZOOM_RESTORE)); } else { Messages.setLanguageText( item, MessageText.resolveLocalizationKey(MENU_ID_WINDOW_ZOOM_MAXIMIZE)); } } if (((shell.getStyle() & SWT.MAX) != 0)) { item.setEnabled(false == shell.getMinimized()); } else { item.setEnabled(false); } } } }; menuParent.addListener(SWT.Show, enableHandler); shell.addListener(SWT.FocusIn, enableHandler); shell.addListener(SWT.Iconify, enableHandler); shell.addListener(SWT.Deiconify, enableHandler); return item; } public static MenuItem addAboutMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_ABOUT, new Listener() { public void handleEvent(Event e) { AboutWindow.show(); } }); } public static MenuItem addHealthMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_HEALTH, new Listener() { public void handleEvent(Event e) { HealthHelpWindow.show(getDisplay()); } }); } public static MenuItem addWhatsNewMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_WHATS_NEW, new Listener() { public void handleEvent(Event e) { Utils.launch("http://azureus.sourceforge.net/changelog.php?version=" + Constants.AZUREUS_VERSION); } }); } public static MenuItem addWikiMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_COMMUNITY_WIKI, new Listener() { public void handleEvent(Event e) { Utils.launch(Constants.AZUREUS_WIKI); } }); } public static MenuItem addReleaseNotesMenuItem(final Menu menu) { return addMenuItem(menu, MENU_ID_RELEASE_NOTES, new Listener() { public void handleEvent(Event e) { new WelcomeWindow(menu.getShell()); } }); } public static MenuItem addHelpSupportMenuItem(Menu menu, final String support_url ) { return addMenuItem(menu, MENU_ID_HELP_SUPPORT, new Listener() { public void handleEvent(Event e) { Utils.launch( support_url ); } }); } public static MenuItem addDonationMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_DONATE, new Listener() { public void handleEvent(Event e) { DonationWindow.open(true, "menu"); } }); } public static MenuItem addGetPluginsMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_PLUGINS_HELP, new Listener() { public void handleEvent(Event e) { Utils.launch("http://azureus.sourceforge.net/plugin_list.php"); } }); } public static MenuItem addDebugHelpMenuItem(Menu menu) { return addMenuItem(menu, MENU_ID_DEBUG_HELP, new Listener() { public void handleEvent(Event e) { UIDebugGenerator.generate(); } }); } public static MenuItem addCheckUpdateMenuItem(final Menu menu) { return addMenuItem(menu, MENU_ID_UPDATE_CHECK, new ListenerNeedingCoreRunning() { public void handleEvent(AzureusCore core, Event e) { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { uiFunctions.bringToFront(); } UpdateMonitor.getSingleton(core).performCheck(true, false, false, new UpdateCheckInstanceListener() { public void cancelled(UpdateCheckInstance instance) { } public void complete(UpdateCheckInstance instance) { if (instance.getUpdates().length == 0) { MessageBoxShell mb = new MessageBoxShell( SWT.ICON_INFORMATION | SWT.OK, "window.update.noupdates", (String[]) null); mb.open(null); } } }); } }); } public static MenuItem addPluginInstallMenuItem(Menu menuParent) { return addMenuItem(menuParent, MENU_ID_PLUGINS_INSTALL, new Listener() { public void handleEvent(Event e) { new InstallPluginWizard(); } }); } public static MenuItem addPluginUnInstallMenuItem(Menu menuParent) { return addMenuItem(menuParent, MENU_ID_PLUGINS_UNINSTALL, new Listener() { public void handleEvent(Event e) { new UnInstallPluginWizard(getDisplay()); } }); } /** * Creates a menu item that is simply a label; it does nothing is selected * @param menu * @param localizationKey * @return */ public static final MenuItem addLabelMenuItem(Menu menu, String localizationKey) { MenuItem item = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(item, localizationKey); item.setEnabled(false); return item; } //========================== public static MenuItem addSeparatorMenuItem(Menu menuParent) { return new MenuItem(menuParent, SWT.SEPARATOR); } public static MenuItem createTopLevelMenuItem(Menu menuParent, String localizationKey) { Menu menu = new Menu(menuParent.getShell(), SWT.DROP_DOWN); MenuItem menuItem = new MenuItem(menuParent, SWT.CASCADE); Messages.setLanguageText(menuItem, localizationKey); menuItem.setMenu(menu); /* * A top level menu and its menu item has the same ID; this is used to locate them at runtime */ menu.setData(KEY_MENU_ID, localizationKey); menuItem.setData(KEY_MENU_ID, localizationKey); return menuItem; } public static final MenuItem addMenuItem(Menu menu, String localizationKey, Listener selListener) { return addMenuItem(menu, localizationKey, selListener, SWT.NONE); } public static final MenuItem addMenuItem(Menu menu, String localizationKey, Listener selListener, int style) { MenuItem menuItem = new MenuItem(menu, style); Messages.setLanguageText(menuItem, MessageText.resolveLocalizationKey(localizationKey)); KeyBindings.setAccelerator(menuItem, MessageText.resolveAcceleratorKey(localizationKey)); if (null != selListener) { menuItem.addListener(SWT.Selection, selListener); } /* * Using the localizationKey as the id for the menu item; this can be used to locate it at runtime * using .KN: missing method pointers */ menuItem.setData(KEY_MENU_ID, localizationKey); return menuItem; } public static final MenuItem addMenuItem(Menu menu, int style, String localizationKey, Listener selListener) { return addMenuItem(menu, style, -1, localizationKey, selListener); } public static final MenuItem addMenuItem(Menu menu, int style, int index, String localizationKey, Listener selListener) { if (index < 0 || index > menu.getItemCount()) { index = menu.getItemCount(); } MenuItem menuItem = new MenuItem(menu, style, index); Messages.setLanguageText(menuItem, localizationKey); KeyBindings.setAccelerator(menuItem, localizationKey); menuItem.addListener(SWT.Selection, selListener); /* * Using the localizationKey as the id for the menu item; this can be used to locate it at runtime * using .KN: missing method pointers */ menuItem.setData(KEY_MENU_ID, localizationKey); return menuItem; } private static UIFunctionsSWT getUIFunctionSWT() { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (null != uiFunctions) { return uiFunctions; } throw new IllegalStateException( "No instance of UIFunctionsSWT found; the UIFunctionsManager might not have been initialized properly"); } private static Display getDisplay() { return SWTThread.getInstance().getDisplay(); } public static void updateMenuText(Object menu) { if (menu == null) return; if (menu instanceof Menu) { MenuItem[] menus = ((Menu) menu).getItems(); for (int i = 0; i < menus.length; i++) { updateMenuText(menus[i]); } } else if (menu instanceof MenuItem) { MenuItem item = (MenuItem) menu; if (item.getData(KEY_MENU_ID) instanceof String) { String localizationKey = (String) item.getData(KEY_MENU_ID); item.setText(MessageText.getString(localizationKey)); KeyBindings.setAccelerator(item, MessageText.resolveAcceleratorKey(localizationKey)); updateMenuText(item.getMenu()); } else { Messages.updateLanguageForControl(item); } } } public static void performOneTimeDisable(MenuItem item, boolean affectsChildMenuItems) { item.setEnabled(false); if (affectsChildMenuItems) { Menu childMenu = item.getMenu(); if (childMenu == null) return; for (int i = 0; i < childMenu.getItemCount(); i++) { childMenu.getItem(i).setEnabled(false); } } } /** * Find and return the menu with the given id starting from the given menu * * @param menuToStartWith * @param idToMatch any of the menu keys listed in {@link org.gudy.azureus2.ui.swt.mainwindow.IMenuConstants} * @return may return null if not found */ public static Menu findMenu(Menu menuToStartWith, String idToMatch) { /* * This is a recursive method; it will start at the given menuToStartWith * and recursively traverse to all its sub menus until a matching * menu is found or until it has touched all sub menus */ if (null == menuToStartWith || true == menuToStartWith.isDisposed() || null == idToMatch || idToMatch.length() < 1) { return null; } /* * The given menuToStartWith may be the one we're looking for */ if (true == idToMatch.equals(getID(menuToStartWith))) { return menuToStartWith; } MenuItem[] items = menuToStartWith.getItems(); /* * Go deeper into each child to try and find it */ for (int i = 0; i < items.length; i++) { MenuItem item = items[i]; Menu menuToFind = findMenu(item.getMenu(), idToMatch); if (null != menuToFind) { return menuToFind; } } return null; } /** * Find and return the menu item with the given id starting from the given menu * * @param menuToStartWith * @param idToMatch any of the menu keys listed in {@link org.gudy.azureus2.ui.swt.mainwindow.IMenuConstants} * @return may return null if not found */ public static MenuItem findMenuItem(Menu menuToStartWith, String idToMatch) { return findMenuItem(menuToStartWith, idToMatch, true); } public static MenuItem findMenuItem(Menu menuToStartWith, String idToMatch, boolean deep) { /* * This is a recursive method; it will start at the given menuToStartWith * and recursively traverse to all its sub menus until a matching * menu item is found or until it has touched all existing menu items */ if (null == menuToStartWith || true == menuToStartWith.isDisposed() || null == idToMatch || idToMatch.length() < 1) { return null; } MenuItem[] items = menuToStartWith.getItems(); for (int i = 0; i < items.length; i++) { MenuItem item = items[i]; if (true == idToMatch.equals(getID(item))) { return item; } if (deep) { /* * Go deeper into each child to try and find it */ MenuItem menuItemToFind = findMenuItem(item.getMenu(), idToMatch); if (null != menuItemToFind) { return menuItemToFind; } } } return null; } private static String getID(Widget widget) { if (null != widget && false == widget.isDisposed()) { Object id = widget.getData(KEY_MENU_ID); if (null != id) { return id.toString(); } } return ""; } public static void setEnablementKeys(Widget widget, int keys) { if (null != widget && false == widget.isDisposed()) { widget.setData(KEY_ENABLEMENT, new Integer(keys)); } } public static int getEnablementKeys(Widget widget) { if (null != widget && false == widget.isDisposed()) { Object keys = widget.getData(KEY_ENABLEMENT); if (keys instanceof Integer) { return ((Integer) keys).intValue(); } } return -1; } /** * Updates the enabled state of the given menu and all its applicable children *

    NOTE: This method currently iterates through the menu hierarchy to * set the enablement which may be inefficient since most menus do not have this flag set; * it may be desirable to employ a map of only the effected menus for efficient direct * access to them

    * @param menuToStartWith */ public static void updateEnabledStates(Menu menuToStartWith) { /* * This is a recursive method; it will start at the given menuToStartWith * and recursively traverse to all its sub menus until a matching * menu item is found or until it has touched all existing menu items */ if (null == menuToStartWith || true == menuToStartWith.isDisposed()) { return; } /* * If the given menu itself is disabled then just return since * its menu items can not be seen anyway */ if (false == setEnablement(menuToStartWith)) { return; } MenuItem[] items = menuToStartWith.getItems(); for (int i = 0; i < items.length; i++) { MenuItem item = items[i]; /* * If the current menu item is disabled then just return since * its children items can not be seen anyway */ if (false == setEnablement(item)) { continue; } /* * Go deeper into the children items and set their enablement */ updateEnabledStates(item.getMenu()); } } /** * Sets whether the given widget is enabled or not based on the value of the * KEY_ENABLEMENT object data set into the given widget. * @param widget * @return */ public static boolean setEnablement(Widget widget) { if (null != widget && false == widget.isDisposed()) { boolean isEnabled = isEnabledForCurrentMode(widget); if (widget instanceof MenuItem) { ((MenuItem) widget).setEnabled(isEnabled); } else if (widget instanceof Menu) { ((Menu) widget).setEnabled(isEnabled); } return isEnabled; } return false; } /** * Returns whether the given widget should be enabled for the current mode; * current mode can be az2, az3, or az3 advanced. * @param widget * @return */ public static boolean isEnabledForCurrentMode(Widget widget) { int keys = getEnablementKeys(widget); if (keys <= 0) { return true; } else if (true == isAZ3) { return ((keys & FOR_AZ3) != 0); } else { return ((keys & FOR_AZ2) != 0); } } private static final boolean DEBUG_SET_FOREGROUND = System.getProperty("debug.setforeground") != null; private static TableRow wrapAsRow(final Object o, final String table_name) { return new TableRow() { public Object getDataSource() {return o;} public String getTableID() {return table_name;} private void notSupported() { throw new RuntimeException("method is not supported - table row is a \"virtual\" one, only getDataSource and getTableID are supported."); } private void setForegroundDebug() { if (DEBUG_SET_FOREGROUND) { Debug.out("setForeground on fake TableRow"); } } // Everything below is unsupported. public void setForeground(int red, int green, int blue) {setForegroundDebug(); notSupported();} public void setForeground(int[] rgb) {setForegroundDebug(); notSupported();} public void setForegroundToErrorColor() {setForegroundDebug(); notSupported();} public boolean isValid() {notSupported(); return false;} public TableCell getTableCell(String sColumnName) {notSupported(); return null;} public boolean isSelected() {notSupported(); return false;} public void addMouseListener(TableRowMouseListener listener) {notSupported();} public void removeMouseListener(TableRowMouseListener listener) {notSupported();} }; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/PluginsMenuHelper.java0000644000175000017500000001561011045736520026042 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.mainwindow; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.common.util.MenuItemManager; import org.gudy.azureus2.ui.swt.MenuBuildUtils; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.plugins.UISWTInstance; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import org.gudy.azureus2.ui.swt.pluginsimpl.BasicPluginViewImpl; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl; import org.gudy.azureus2.ui.swt.views.AbstractIView; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; public class PluginsMenuHelper { private static PluginsMenuHelper INSTANCE = null; private AEMonitor plugin_helper_mon = new AEMonitor("plugin_helper_mon"); private Map plugin_view_info_map = new TreeMap(); private Map plugin_logs_view_info_map = new TreeMap(); private List pluginAddedViewListener = new ArrayList(); private PluginsMenuHelper() { //Making this private } public static PluginsMenuHelper getInstance() { if (null == INSTANCE) { INSTANCE = new PluginsMenuHelper(); } return INSTANCE; } public void buildPluginMenu(Menu pluginMenu, Shell parent, boolean includeGetPluginsMenu) { try { plugin_helper_mon.enter(); createIViewInfoMenuItems(pluginMenu, plugin_view_info_map); MenuItem menu_plugin_logViews = MenuFactory.addLogsViewMenuItem(pluginMenu); createIViewInfoMenuItems(menu_plugin_logViews.getMenu(), plugin_logs_view_info_map); } finally { plugin_helper_mon.exit(); } MenuFactory.addSeparatorMenuItem(pluginMenu); org.gudy.azureus2.plugins.ui.menus.MenuItem[] plugin_items; plugin_items = MenuItemManager.getInstance().getAllAsArray("mainmenu"); if (plugin_items.length > 0) { MenuBuildUtils.addPluginMenuItems(parent, plugin_items, pluginMenu, true, true, MenuBuildUtils.BASIC_MENU_ITEM_CONTROLLER); MenuFactory.addSeparatorMenuItem(pluginMenu); } MenuFactory.addPluginInstallMenuItem(pluginMenu); MenuFactory.addPluginUnInstallMenuItem(pluginMenu); if (true == includeGetPluginsMenu) { MenuFactory.addGetPluginsMenuItem(pluginMenu); } } public void addPluginView(String sViewID, UISWTViewEventListener l) { IViewInfo view_info = new IViewInfo(); view_info.viewID = sViewID; view_info.event_listener = l; String sResourceID = UISWTViewImpl.CFG_PREFIX + sViewID + ".title"; boolean bResourceExists = MessageText.keyExists(sResourceID); String name; if (bResourceExists) { name = MessageText.getString(sResourceID); } else { // try plain resource sResourceID = sViewID; bResourceExists = MessageText.keyExists(sResourceID); if (bResourceExists) { name = MessageText.getString(sResourceID); } else { name = sViewID.replace('.', ' '); // support old plugins } } view_info.name = name; Map map_to_use = (l instanceof BasicPluginViewImpl) ? this.plugin_logs_view_info_map : this.plugin_view_info_map; try { plugin_helper_mon.enter(); map_to_use.put(name, view_info); } finally { plugin_helper_mon.exit(); } triggerPluginAddedViewListeners(view_info); } private void removePluginViewsWithID(String sViewID, Map map) { if (sViewID == null) { return; } Iterator itr = map.values().iterator(); IViewInfo view_info = null; while (itr.hasNext()) { view_info = (IViewInfo) itr.next(); if (sViewID.equals(view_info.viewID)) { itr.remove(); } } } public void removePluginViews(final String sViewID) { try { plugin_helper_mon.enter(); removePluginViewsWithID(sViewID, plugin_view_info_map); removePluginViewsWithID(sViewID, plugin_logs_view_info_map); } finally { plugin_helper_mon.exit(); } Utils.execSWTThread(new AERunnable() { public void runSupport() { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { uiFunctions.closePluginViews(sViewID); } } }); } public void addPluginView(final AbstractIView view, final String name) { IViewInfo view_info = new IViewInfo(); view_info.name = name; view_info.view = view; try { plugin_helper_mon.enter(); plugin_view_info_map.put(name, view_info); } finally { plugin_helper_mon.exit(); } triggerPluginAddedViewListeners(view_info); } public void removePluginView(final AbstractIView view, final String name) { IViewInfo view_info = null; try { plugin_helper_mon.enter(); view_info = (IViewInfo) this.plugin_view_info_map.remove(name); } finally { plugin_helper_mon.exit(); } if (view_info != null) { Utils.execSWTThread(new AERunnable() { public void runSupport() { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { uiFunctions.closePluginView(view); } } }); } } /** * Populates Azureus' menu bar * @param locales * @param parent */ private void createIViewInfoMenuItem(Menu parent, final IViewInfo info) { MenuItem item = new MenuItem(parent, SWT.NULL); item.setText(info.name); if (info.viewID != null) { item.setData("ViewID", info.viewID); } item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { info.openView(uiFunctions); } } }); } private void createIViewInfoMenuItems(Menu parent, Map menu_data) { Iterator itr = menu_data.values().iterator(); while (itr.hasNext()) { createIViewInfoMenuItem(parent, (IViewInfo) itr.next()); } } public IViewInfo[] getPluginViewsInfo() { return (IViewInfo[])plugin_view_info_map.values().toArray(new IViewInfo[0]); } public IViewInfo[] getPluginLogViewsInfo() { return (IViewInfo[])plugin_logs_view_info_map.values().toArray(new IViewInfo[0]); } public static class IViewInfo { public AbstractIView view; public String name; public String viewID; public UISWTViewEventListener event_listener; public void openView(UIFunctionsSWT uiFunctions) { if (event_listener != null) { uiFunctions.openPluginView(UISWTInstance.VIEW_MAIN, viewID, event_listener, null, true); } else { uiFunctions.openPluginView(view, name); } } } public void addPluginAddedViewListener(PluginAddedViewListener l) { pluginAddedViewListener.add(l); } public void triggerPluginAddedViewListeners(IViewInfo viewInfo) { Object[] listeners = pluginAddedViewListener.toArray(); for (int i = 0; i < listeners.length; i++) { PluginAddedViewListener l = (PluginAddedViewListener) listeners[i]; l.pluginViewAdded(viewInfo); } } public static interface PluginAddedViewListener { public void pluginViewAdded(IViewInfo viewInfo); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/UIFunctionsImpl.java0000644000175000017500000003534011273607612025470 0ustar adrianadrian/* * Created on Jul 12, 2006 2:56:52 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.mainwindow; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginView; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar; import org.gudy.azureus2.ui.swt.minibar.MiniBarManager; import org.gudy.azureus2.ui.swt.plugins.*; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.shells.SimpleBrowserWindow; import org.gudy.azureus2.ui.swt.update.FullUpdateWindow; import org.gudy.azureus2.ui.swt.views.AbstractIView; import org.gudy.azureus2.ui.swt.views.IView; import com.aelitis.azureus.ui.UIFunctionsUserPrompter; import com.aelitis.azureus.ui.UIStatusTextClickListener; import com.aelitis.azureus.ui.UserPrompterResultListener; import com.aelitis.azureus.ui.common.updater.UIUpdater; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT; /** * @author TuxPaper * @created Jul 12, 2006 * */ public class UIFunctionsImpl implements UIFunctionsSWT { private final MainWindow mainwindow; /** * @param window */ public UIFunctionsImpl(MainWindow mainwindow) { this.mainwindow = mainwindow; } // UIFunctions public void bringToFront() { bringToFront(true); } public void bringToFront(final boolean tryTricks) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.setVisible(true, tryTricks); } }); } // UIFunctions public void addPluginView(final PluginView view) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { PluginsMenuHelper.getInstance().addPluginView(view, view.getPluginViewName()); } }); } public void openPluginView(final PluginView view) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.openPluginView(view, view.getPluginViewName()); } }); } public void removePluginView(final PluginView view) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { PluginsMenuHelper.getInstance().removePluginView(view, view.getPluginViewName()); } }); } private void showStats() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.showStats(); } }); } private void showStatsDHT() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.showStatsDHT(); } }); } private void showStatsTransfers() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.showStatsTransfers(); } }); } public Shell getMainShell() { return mainwindow.getShell(); } public void addPluginView(final UISWTPluginView view) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { PluginsMenuHelper.getInstance().addPluginView(view, view.getPluginViewName()); } }); } public void openPluginView(final UISWTPluginView view) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.openPluginView(view, view.getPluginViewName()); } }); } public void removePluginView(final UISWTPluginView view) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { PluginsMenuHelper.getInstance().removePluginView(view, view.getPluginViewName()); } }); } public boolean showConfig(String string) { return mainwindow.showConfig(string); } public void addPluginView(final String viewID, final UISWTViewEventListener l) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { PluginsMenuHelper.getInstance().addPluginView(viewID, l); } }); } public void refreshLanguage() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.setSelectedLanguageItem(); } }); } public void closeDownloadBars() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { MiniBarManager.getManager().closeAll(); } }); } public boolean isGlobalTransferBarShown() { return AllTransfersBar.getManager().isOpen(mainwindow.getGlobalManager()); } public void showGlobalTransferBar() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { AllTransfersBar.open(mainwindow.getGlobalManager(), mainwindow.getShell()); } }); } public void closeGlobalTransferBar() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { AllTransfersBar.close(mainwindow.getGlobalManager()); } }); } public UISWTInstanceImpl getSWTPluginInstanceImpl() { return mainwindow.getUISWTInstanceImpl(); } public void openManagerView(final DownloadManager dm) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.openManagerView(dm); } }); } public void refreshIconBar() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.refreshIconBar(); } }); } public void removeManagerView(final DownloadManager dm) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.removeManagerView(dm); } }); } private void showMyTracker() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.showMyTracker(); } }); } public void closePluginView(final IView view) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.closePluginView(view); } }); } public UISWTView[] getPluginViews() { return mainwindow.getPluginViews(); } public void openPluginView(final String sParentID, final String sViewID, final UISWTViewEventListener l, final Object dataSource, final boolean bSetFocus) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.openPluginView(sParentID, sViewID, l, dataSource, bSetFocus, false); } }); } public void removePluginView(final String viewID) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { PluginsMenuHelper.getInstance().removePluginViews(viewID); } }); } public void setStatusText(final String string) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.setStatusText(string); } }); } public void setStatusText(final int statustype, final String string, final UIStatusTextClickListener l) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.setStatusText(statustype, string, l); } }); } public boolean dispose(boolean for_restart, boolean close_already_in_progress) { return mainwindow.dispose(for_restart, close_already_in_progress); } public Menu getMenu(int id) { if (mainwindow.getMenu() != null) { return mainwindow.getMenu().getMenu(id); } return null; } public void closePluginViews(final String sViewID) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.closePluginViews(sViewID); } }); } public void openPluginView(final AbstractIView view, final String name) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.openPluginView(view, name); } }); } private void showMyShares() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.showMyShares(); } }); } private void showMyTorrents() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.showMyTorrents(); } }); } private void showDetailedListView() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.showDetailedListView(); } }); } private void showAllPeersView() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.showAllPeersView(); } }); } private void showClientStatsView() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.showClientStatsView(); } }); } private void showMultiOptionsView(final DownloadManager[] dms) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.showMultiOptionsView(dms); } }); } private void showConsole() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { mainwindow.showConsole(); } }); } public UISWTInstance getUISWTInstance() { return mainwindow.getUISWTInstanceImpl(); } // @see com.aelitis.azureus.ui.UIFunctions#viewURL(java.lang.String, java.lang.String, java.lang.String) public void viewURL(String url, String target, String sourceRef) { viewURL(url, target, 0.9, 0.9, true, false); } // @see com.aelitis.azureus.ui.UIFunctions#viewURL(java.lang.String, java.lang.String, int, int, boolean, boolean) public boolean viewURL(final String url, final String target, final int w, final int h, final boolean allowResize, final boolean isModal) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { SimpleBrowserWindow window = new SimpleBrowserWindow( mainwindow.getShell(), url, w, h, allowResize, isModal); window.waitUntilClosed(); } }); return true; } // @see com.aelitis.azureus.ui.UIFunctions#viewURL(java.lang.String, java.lang.String, double, double, boolean, boolean) public boolean viewURL(final String url, final String target, final double w, final double h, final boolean allowResize, final boolean isModal) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { SimpleBrowserWindow window = new SimpleBrowserWindow( mainwindow.getShell(), url, w, h, allowResize, isModal); window.waitUntilClosed(); } }); return true; } // @see com.aelitis.azureus.ui.UIFunctions#promptUser(java.lang.String, java.lang.String, java.lang.String[], int, java.lang.String, java.lang.String, boolean, int) public void promptUser(String title, String text, String[] buttons, int defaultOption, String rememberID, String rememberText, boolean rememberByDefault, int autoCloseInMS, UserPrompterResultListener l) { MessageBoxShell.open(getMainShell(), title, text, buttons, defaultOption, rememberID, rememberText, rememberByDefault, autoCloseInMS, l); } // @see com.aelitis.azureus.ui.UIFunctions#getUserPrompter(java.lang.String, java.lang.String, java.lang.String[], int) public UIFunctionsUserPrompter getUserPrompter(String title, String text, String[] buttons, int defaultOption) { MessageBoxShell mb = new MessageBoxShell(title, text, buttons, defaultOption); return mb; } public void refreshTorrentMenu() { mainwindow.refreshTorrentMenu(); } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#getMainStatusBar() public MainStatusBar getMainStatusBar() { return mainwindow.getMainStatusBar(); } public IMainMenu createMainMenu(Shell shell) { return new MainMenu(shell); } public IMainWindow getMainWindow() { return mainwindow; } // @see com.aelitis.azureus.ui.UIFunctions#getUIUpdater() public UIUpdater getUIUpdater() { return UIUpdaterSWT.getInstance(); } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#closeAllDetails() public void closeAllDetails() { mainwindow.closeAllDetails(); } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#hasDetailViews() public boolean hasDetailViews() { return mainwindow.hasDetailViews(); } // @see com.aelitis.azureus.ui.UIFunctions#openView(int, java.lang.Object) public void openView(int viewID, Object datasource) { switch (viewID) { case VIEW_CONSOLE: showConsole(); break; case VIEW_ALLPEERS: showAllPeersView(); break; case VIEW_PEERS_STATS: showClientStatsView(); break; case VIEW_CONFIG: showConfig((datasource instanceof String) ? (String) datasource : null); break; case VIEW_DM_DETAILS: if (datasource instanceof DownloadManager) { openManagerView((DownloadManager) datasource); } break; case VIEW_DM_MULTI_OPTIONS: if (datasource instanceof DownloadManager[]) { DownloadManager[] dms = (DownloadManager[]) datasource; showMultiOptionsView(dms); } break; case VIEW_MYSHARES: showMyShares(); break; case VIEW_MYTORRENTS: showMyTorrents(); break; case VIEW_MYTRACKER: showMyTracker(); break; case VIEW_STATS: if ("dht".equals(datasource)) { showStatsDHT(); } else if ("transfers".equals(datasource)) { showStatsTransfers(); } else { showStats(); } break; case VIEW_DETAILED_LISTVIEW: showDetailedListView(); break; default: break; } } public void performAction( int action_id, Object args, actionListener listener ) { if ( action_id == ACTION_FULL_UPDATE ){ FullUpdateWindow.handleUpdate((String)args, listener ); }else{ Debug.out( "Unknown action " + action_id ); } } public Shell showCoreWaitDlg() { Shell activeShell = Display.getDefault().getActiveShell(); if (activeShell == null) { activeShell = Utils.findAnyShell(); } Shell shell = new Shell(activeShell, SWT.TITLE | SWT.BORDER | SWT.APPLICATION_MODAL); shell.setText("Please Wait"); FillLayout fillLayout = new FillLayout(); fillLayout.marginHeight = 5; fillLayout.marginWidth = 5; shell.setLayout(fillLayout); Label label = new Label(shell, SWT.NONE); label.setText("Your operation will run momentarily"); shell.pack(); //shell.setSize(300,50); Utils.centreWindow(shell); shell.open(); return shell; } // @see com.aelitis.azureus.ui.UIFunctions#doSearch(java.lang.String) public void doSearch(String searchText) { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/ClipboardCopy.java0000644000175000017500000000650011005472122025153 0ustar adrianadrian/* * Created on 3 mai 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Alle Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.mainwindow; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.MenuAdapter; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.gudy.azureus2.core3.internat.MessageText; /** * @author Olivier Chalouhi * */ public class ClipboardCopy { public static void copyToClipBoard( String data ) { new Clipboard(SWTThread.getInstance().getDisplay()).setContents( new Object[] {data }, new Transfer[] {TextTransfer.getInstance()}); } public static void addCopyToClipMenu( final Control control, final copyToClipProvider provider ) { control.addMouseListener( new MouseAdapter() { public void mouseDown( MouseEvent e ) { if ( control.isDisposed()){ return; } final String text = provider.getText(); if ( control.getMenu() != null || text == null || text.length() == 0 ){ return; } if (!(e.button == 3 || (e.button == 1 && e.stateMask == SWT.CONTROL))){ return; } final Menu menu = new Menu(control.getShell(),SWT.POP_UP); MenuItem item = new MenuItem( menu,SWT.NONE ); item.setText( MessageText.getString( "ConfigView.copy.to.clipboard.tooltip")); item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent arg0) { new Clipboard(control.getDisplay()).setContents(new Object[] {text}, new Transfer[] {TextTransfer.getInstance()}); } }); control.setMenu( menu ); menu.addMenuListener( new MenuAdapter() { public void menuHidden( MenuEvent arg0 ) { if ( control.getMenu() == menu ){ control.setMenu( null ); } } }); menu.setVisible( true ); } }); } public interface copyToClipProvider { public String getText(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/SWTThread.java0000644000175000017500000002303311300740526024232 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Olivier Chalouhi * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.mainwindow; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.ui.swt.UISwitcherListener; import org.gudy.azureus2.ui.swt.UISwitcherUtil; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import com.aelitis.azureus.ui.*; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; /** * The main SWT Thread, the only one that should run any GUI code. */ public class SWTThread { private static SWTThread instance; public static SWTThread getInstance() { return instance; } public static void createInstance(IUIIntializer initializer) throws SWTThreadAlreadyInstanciatedException { if(instance != null) { throw new SWTThreadAlreadyInstanciatedException(); } //Will only return on termination new SWTThread(initializer); } Display display; private boolean sleak; private boolean terminated; private Thread runner; private final IUIIntializer initializer; private Monitor primaryMonitor; private SWTThread( final IUIIntializer app ) { this.initializer = app; instance = this; Display.setAppName(Constants.APP_NAME); try { display = Display.getCurrent(); if ( display == null ){ display = new Display(); sleak = false; }else{ sleak = true; } } catch(Exception e) { display = new Display(); sleak = false; } catch (UnsatisfiedLinkError ue) { String sMin = "3.4"; try { sMin = "" + (((int)(SWT.getVersion() / 100)) / 10.0); } catch (Throwable t) { } try{ String tempDir = System.getProperty ("swt.library.path"); if (tempDir == null) { tempDir = System.getProperty ("java.io.tmpdir"); } Debug.out("Loading SWT Libraries failed. " + "Typical causes:\n\n" + "(1) swt.jar is not for your os architecture (" + System.getProperty("os.arch") + "). " + "You can get a new swt.jar (Min Version: " + sMin + ") " + "from http://eclipse.org/swt" + "\n\n" + "(2) No write access to '" + tempDir + "'. SWT will extract libraries contained in the swt.jar to this dir.\n", ue); if (!terminated) { app.stopIt(false, false); terminated = true; } PlatformManagerFactory.getPlatformManager().dispose(); } catch (Throwable t) { } return; } primaryMonitor = display.getPrimaryMonitor(); AEDiagnostics.addEvidenceGenerator(new AEDiagnosticsEvidenceGenerator() { public void generate(IndentWriter writer) { writer.println("SWT"); try { writer.indent(); writer.println("SWT Version:" + SWT.getVersion() + "/" + SWT.getPlatform()); writer.println("org.eclipse.swt.browser.XULRunnerPath: " + System.getProperty("org.eclipse.swt.browser.XULRunnerPath", "")); writer.println("MOZILLA_FIVE_HOME: " + SystemProperties.getEnvironmentalVariable("MOZILLA_FIVE_HOME")); } finally { writer.exdent(); } } }); UISwitcherUtil.addListener(new UISwitcherListener() { public void uiSwitched(String ui) { MessageBoxShell mb = new MessageBoxShell( MessageText.getString("dialog.uiswitcher.restart.title"), MessageText.getString("dialog.uiswitcher.restart.text"), new String[] { MessageText.getString("UpdateWindow.restart"), MessageText.getString("UpdateWindow.restartLater"), }, 0); mb.open(new UserPrompterResultListener() { public void prompterClosed(int result) { if (result != 0) { return; } UIFunctions uif = UIFunctionsManager.getUIFunctions(); if (uif != null) { uif.dispose(true, false); } } }); } }); display.addListener(SWT.Activate, new Listener() { public void handleEvent(Event event) { if (event.detail != 1) { return; } UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uif != null) { uif.bringToFront(false); } } }); if (Constants.isOSX) { // On Cocoa, we get a Close trigger on display. Need to check if all // platforms send this. display.addListener(SWT.Close, new Listener() { public void handleEvent(Event event) { event.doit = UIFunctionsManager.getUIFunctions().dispose(false, false); } }); String platform = SWT.getPlatform(); // use reflection here so we decouple generic SWT from OSX specific stuff to an extent if (platform.equals("carbon")) { try { Class ehancerClass = Class.forName("org.gudy.azureus2.ui.swt.osx.CarbonUIEnhancer"); Constructor constructor = ehancerClass.getConstructor(new Class[] {}); constructor.newInstance(new Object[] {}); } catch (Throwable e) { Debug.printStackTrace(e); } } else if (platform.equals("cocoa")) { try { Class ehancerClass = Class.forName("org.gudy.azureus2.ui.swt.osx.CocoaUIEnhancer"); Method mGetInstance = ehancerClass.getMethod("getInstance", new Class[0]); Object claObj = mGetInstance.invoke(null, new Object[0] ); Method mHookAppMenu = claObj.getClass().getMethod("hookApplicationMenu", new Class[] {}); if (mHookAppMenu != null) { mHookAppMenu.invoke(claObj, new Object[0]); } Method mHookDocOpen = claObj.getClass().getMethod("hookDocumentOpen", new Class[] {}); if (mHookDocOpen != null) { mHookDocOpen.invoke(claObj, new Object[0]); } } catch (Throwable e) { Debug.printStackTrace(e); } } } if (app != null) { app.runInSWTThread(); runner = new Thread(new AERunnable() { public void runSupport() { app.run(); } }, "Main Thread"); runner.start(); } if(!sleak) { while(!display.isDisposed() && !terminated) { try { if (!display.readAndDispatch()) display.sleep(); } catch (Throwable e) { if (terminated) { Logger.log(new LogEvent(LogIDs.GUI, "Weird non-critical error after terminated in readAndDispatch: " + e.toString())); } else { String stackTrace = Debug.getStackTrace(e); if (Constants.isOSX && stackTrace.indexOf("Device.dispose") > 0 && stackTrace.indexOf("DropTarget") > 0) { Logger.log(new LogEvent(LogIDs.GUI, "Weird non-critical display disposal in readAndDispatch")); } else { // Must use printStackTrace() (no params) in order to get // "cause of"'s stack trace in SWT < 3119 if (SWT.getVersion() < 3119) e.printStackTrace(); if (Constants.isCVSVersion()) { Logger.log(new LogAlert(LogAlert.UNREPEATABLE,MessageText.getString("SWT.alert.erroringuithread"),e)); } } } } } if(!terminated) { // if we've falled out of the loop without being explicitly terminated then // this appears to have been caused by a non-specific exit/restart request (as the // specific ones should terminate us before disposing of the window...) if (app != null) { app.stopIt( false, false ); } terminated = true; } try { if (!display.isDisposed()) display.dispose(); } catch (Throwable t) { // Must use printStackTrace() (no params) in order to get // "cause of"'s stack trace in SWT < 3119 if (SWT.getVersion() < 3119) t.printStackTrace(); else Debug.printStackTrace(t); } // dispose platform manager here PlatformManagerFactory.getPlatformManager().dispose(); } } public void terminate() { terminated = true; // must dispose here in case another window has take over the // readAndDispatch/sleep loop if (!display.isDisposed()) { try { Shell[] shells = display.getShells(); for (int i = 0; i < shells.length; i++) { try { Shell shell = shells[i]; shell.dispose(); } catch (Throwable t) { Debug.out(t); } } } catch (Throwable t) { Debug.out(t); } display.dispose(); } } public Display getDisplay() { return display; } public boolean isTerminated() { return terminated; } public IUIIntializer getInitializer() { return initializer; } public Monitor getPrimaryMonitor() { return primaryMonitor; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/IMenuConstants.java0000644000175000017500000001617311276126552025357 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.mainwindow; /** * Constants for working with menus * * NOTE: Each menu id is storing the textual value equivalent to its localization key * so care must be taken to keep these menu id's in synch with the localization keys found * in MessagesBundle.properties * * NOTE: These menu id's are used to retrieve the localized text to display for the menu, the tooltip, * the shortcut key bindings, and as the id's for the menus. * @author knguyen * */ public interface IMenuConstants { /** * The key used to store the enablement bit mask for a menu item */ public static final String KEY_ENABLEMENT = "key.enablement"; /** * Bit mask for az2 */ public static int FOR_AZ2 = 1 << 0; /** * Bit mask for az3 */ public static int FOR_AZ3 = 1 << 1; /** * A key used to store key/value pairs for menu ids; * currently used for setting the menu id for menus and menu items. *

    NOTE: This is not a localization key * @see MenuFactory#createTopLevelMenuItem() * @see MenuFactory#addMenuItem() */ public static final String KEY_MENU_ID = "key.menu.id"; /** * A special id for the menu bar itself *

    NOTE: This is not a localization key */ public static final String MENU_ID_MENU_BAR = "menu.bar"; public static final String MENU_ID_FILE = "MainWindow.menu.file"; public static final String MENU_ID_TRANSFERS = "MainWindow.menu.transfers"; public static final String MENU_ID_VIEW = "MainWindow.menu.view"; public static final String MENU_ID_TORRENT = "MainWindow.menu.torrent"; public static final String MENU_ID_TOOLS = "MainWindow.menu.tools"; public static final String MENU_ID_PLUGINS = "MainWindow.menu.view.plugins"; public static final String MENU_ID_WINDOW = "MainWindow.menu.window"; public static final String MENU_ID_HELP = "MainWindow.menu.help"; public static final String MENU_ID_CREATE = "MainWindow.menu.file.create"; public static final String MENU_ID_OPEN = "MainWindow.menu.file.open"; public static final String MENU_ID_LOG_VIEWS = "MainWindow.menu.view.plugins.logViews"; public static final String MENU_ID_OPEN_TORRENT = "MainWindow.menu.file.open.torrent"; public static final String MENU_ID_OPEN_TORRENT_FOR_TRACKING = "MainWindow.menu.file.open.torrentfortracking"; public static final String MENU_ID_OPEN_VUZE_FILE = "MainWindow.menu.file.open.vuze"; public static final String MENU_ID_SHARE = "MainWindow.menu.file.share"; public static final String MENU_ID_SHARE_FILE = "MainWindow.menu.file.share.file"; public static final String MENU_ID_SHARE_DIR = "MainWindow.menu.file.share.dir"; public static final String MENU_ID_SHARE_DIR_CONTENT = "MainWindow.menu.file.share.dircontents"; public static final String MENU_ID_SHARE_DIR_CONTENT_RECURSE = "MainWindow.menu.file.share.dircontentsrecursive"; public static final String MENU_ID_IMPORT = "MainWindow.menu.file.import"; public static final String MENU_ID_EXPORT = "MainWindow.menu.file.export"; public static final String MENU_ID_WINDOW_CLOSE = "MainWindow.menu.file.closewindow"; public static final String MENU_ID_CLOSE_TAB = "MainWindow.menu.file.closetab"; public static final String MENU_ID_CLOSE_ALL_DETAIL = "MainWindow.menu.closealldetails"; public static final String MENU_ID_CLOSE_ALL_DL_BARS = "MainWindow.menu.closealldownloadbars"; public static final String MENU_ID_RESTART = "MainWindow.menu.file.restart"; public static final String MENU_ID_EXIT = "MainWindow.menu.file.exit"; public static final String MENU_ID_START_ALL_TRANSFERS = "MainWindow.menu.transfers.startalltransfers"; public static final String MENU_ID_STOP_ALL_TRANSFERS = "MainWindow.menu.transfers.stopalltransfers"; public static final String MENU_ID_PAUSE_TRANSFERS = "MainWindow.menu.transfers.pausetransfers"; public static final String MENU_ID_RESUME_TRANSFERS = "MainWindow.menu.transfers.resumetransfers"; public static final String MENU_ID_MY_TORRENTS = "MainWindow.menu.view.mytorrents"; public static final String MENU_ID_DETAILED_LIST = "MainWindow.menu.view.detailedlist"; public static final String MENU_ID_ALL_PEERS = "MainWindow.menu.view.allpeers"; public static final String MENU_ID_CLIENT_STATS = "MainWindow.menu.view.clientstats"; public static final String MENU_ID_MY_TRACKERS = "MainWindow.menu.view.mytracker"; public static final String MENU_ID_MY_SHARES = "MainWindow.menu.view.myshares"; public static final String MENU_ID_TOOLBAR = "MainWindow.menu.view.iconbar"; public static final String MENU_ID_TRANSFER_BAR = "MainWindow.menu.view.open_global_transfer_bar"; public static final String MENU_ID_IP_FILTER = "MainWindow.menu.view.ipFilter"; public static final String MENU_ID_CONSOLE = "MainWindow.menu.view.console"; public static final String MENU_ID_STATS = "MainWindow.menu.view.stats"; public static final String MENU_ID_NAT_TEST = "MainWindow.menu.tools.nattest"; public static final String MENU_ID_SPEED_TEST = "MainWindow.menu.tools.speedtest"; public static final String MENU_ID_CONFIGURE = "MainWindow.menu.file.configure"; public static final String MENU_ID_OPTIONS = "MainWindow.menu.view.configuration"; public static final String MENU_ID_WINDOW_MINIMIZE = "MainWindow.menu.window.minimize"; public static final String MENU_ID_WINDOW_ALL_TO_FRONT = "MainWindow.menu.window.alltofront"; public static final String MENU_ID_WINDOW_ZOOM = "MainWindow.menu.window.zoom"; public static final String MENU_ID_WINDOW_ZOOM_MAXIMIZE = "MainWindow.menu.window.zoom.maximize"; public static final String MENU_ID_WINDOW_ZOOM_RESTORE = "MainWindow.menu.window.zoom.restore"; public static final String MENU_ID_ABOUT = "MainWindow.menu.help.about"; public static final String MENU_ID_HEALTH = "MyTorrentsView.menu.health"; public static final String MENU_ID_WHATS_NEW = "MainWindow.menu.help.whatsnew"; public static final String MENU_ID_FAQ = "MainWindow.menu.help.faq"; public static final String MENU_ID_RELEASE_NOTES = "MainWindow.menu.help.releasenotes"; public static final String MENU_ID_PLUGINS_HELP = "MainWindow.menu.help.plugins"; public static final String MENU_ID_DEBUG_HELP = "MainWindow.menu.help.debug"; public static final String MENU_ID_UPDATE_CHECK = "MainWindow.menu.help.checkupdate"; public static final String MENU_ID_PLUGINS_INSTALL = "MainWindow.menu.plugins.installPlugins"; public static final String MENU_ID_PLUGINS_UNINSTALL = "MainWindow.menu.plugins.uninstallPlugins"; public static final String MENU_ID_ADVANCED = "v3.MainWindow.tab.advanced"; public static final String MENU_ID_SEARCH_BAR = "v3.MainWindow.menu.view.searchbar"; // dead public static final String MENU_ID_TAB_BAR = "v3.MainWindow.menu.view.tabbar"; // dead public static final String MENU_ID_COMMUNITY = "MainWindow.menu.community"; public static final String MENU_ID_COMMUNITY_BLOG = "MainWindow.menu.community.blog"; public static final String MENU_ID_COMMUNITY_FORUMS = "MainWindow.menu.community.forums"; public static final String MENU_ID_COMMUNITY_WIKI = "MainWindow.menu.community.wiki"; public static final String MENU_ID_HELP_SUPPORT = "MainWindow.menu.help.support"; public static final String MENU_ID_DONATE = "MainWindow.menu.help.donate"; } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/SplashWindow.java0000644000175000017500000002347411127403346025063 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Olivier Chalouhi * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.mainwindow; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.ImageRepository; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.IUIIntializer; import com.aelitis.azureus.ui.InitializerListener; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.utils.ColorCache; /** * The initial Splash Screen shown while azureus loads */ public class SplashWindow implements InitializerListener { private static final String IMG_SPLASH = "azureus_splash"; // config 1 : PB_HEIGHT = 3, PB_INVERTED = false // config 2 : PB_HEIGHT = 3, PB_INVERTED = true, PB_INVERTED_BG_HEIGHT = 3 // config 3 : PB_HEIGHT = 2, PB_INVERTED = true, PB_INVERTED_BG_HEIGHT = 2 // config 4 : PB_HEIGHT = 3, PB_INVERTED = true, PB_INVERTED_BG_HEIGHT = 1, PB_INVERTED_X_OFFSET = 4 protected static final int OFFSET_LEFT = 10; protected static final int OFFSET_RIGHT = 139; protected static final int OFFSET_BOTTOM = 12; protected static final int PB_HEIGHT = 2; protected static final boolean PB_INVERTED = true; protected static final int PB_INVERTED_BG_HEIGHT = 2; protected static final int PB_INVERTED_X_OFFSET = 0; protected static final boolean DISPLAY_BORDER = true; Display display; IUIIntializer initializer; Shell splash; //Label currentTask; //ProgressBar percentDone; Canvas canvas; Image background; int width; int height; Image current; Color progressBarColor; Color textColor; Color fadedGreyColor; Font textFont; private String task; private int percent; private boolean updating; int pbX, pbY, pbWidth; public SplashWindow(Display display) { this(display, null); } public static void main(String args[]) { Display display = new Display(); final SplashWindow splash = new SplashWindow(display); Thread t = new Thread() { public void run() { try { int percent = 0; while (percent <= 100) { splash.reportPercent(percent++); splash.reportCurrentTask(percent + "% Loading dbnvsudn vjksfdh fgshdu fbhsduh bvsfd fbsd fbvsdb fsuid opnum supnum boopergood haha text doot subliminal.".substring( 0, (int) (1 + Math.random() * 110))); Thread.sleep(100); } } catch (Exception e) { // TODO: handle exception } splash.closeSplash(); } }; t.start(); while (!splash.splash.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); } public SplashWindow(Display _display, IUIIntializer initializer) { this.display = _display; this.initializer = initializer; splash = new Shell(display, SWT.NO_TRIM); splash.setText(Constants.APP_NAME); Utils.setShellIcon(splash); splash.setLayout(new FillLayout()); canvas = new Canvas(splash, SWT.DOUBLE_BUFFERED); ImageLoader imageLoader = ImageLoader.getInstance(); background = imageLoader.getImage(IMG_SPLASH); if (ImageLoader.isRealImage(background)) { width = background.getBounds().width; height = background.getBounds().height; } else { width = 400; height = 80; background = new Image(display, width, height); GC gc = new GC(background); try { gc.setBackground(ColorCache.getColor(display, 255, 255, 255)); gc.fillRectangle(0, 0, width, height); gc.drawRectangle(0, 0, width - 1, height - 1); gc.drawText(Constants.APP_NAME, 5, 5, true); } finally { gc.dispose(); } } current = new Image(display, background, SWT.IMAGE_COPY); progressBarColor = new Color(display, 21, 92, 198); textColor = new Color(display, 90, 90, 90); fadedGreyColor = new Color(display, 170, 170, 170); pbX = OFFSET_LEFT; pbY = height - OFFSET_BOTTOM; pbWidth = width - OFFSET_LEFT - OFFSET_RIGHT; canvas.setSize(width, height); Font font = canvas.getFont(); FontData[] fdata = font.getFontData(); fdata[0].setHeight(Constants.isOSX ? 9 : 7); textFont = new Font(display, fdata); canvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent event) { if (current == null) { return; } event.gc.drawImage(current, 0, 0); } }); //splash.pack(); splash.setSize(width, height); //splash.layout(); Utils.centreWindow(splash); splash.open(); if (initializer != null) { initializer.addListener(this); } } public static void create(final Display display, final Initializer initializer) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (display == null || display.isDisposed()) return; new SplashWindow(display, initializer); } }); } /* * Should be called by the GUI thread */ public void closeSplash() { Utils.execSWTThread(new AERunnable() { public void runSupport() { try { if (initializer != null) initializer.removeListener(SplashWindow.this); if (splash != null && !splash.isDisposed()) splash.dispose(); if (current != null && !current.isDisposed()) { current.dispose(); } if (progressBarColor != null && !progressBarColor.isDisposed()) { progressBarColor.dispose(); } if (fadedGreyColor != null && !fadedGreyColor.isDisposed()) { fadedGreyColor.dispose(); } if (textColor != null && !textColor.isDisposed()) { textColor.dispose(); } if (textFont != null && !textFont.isDisposed()) { textFont.dispose(); } ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage(IMG_SPLASH); imageLoader.collectGarbage(); } catch (Exception e) { //ignore } } }); } /* * STProgressListener implementation */ // AzureusCoreListener public void reportCurrentTask(final String task) { //Ensure that display is set and not disposed if (display == null || display.isDisposed()) return; if (this.task == null || this.task.compareTo(task) != 0) { this.task = task; update(); } } /** * * * @since 3.0.0.7 */ private void update() { if (updating && !Utils.isThisThreadSWT()) { return; } updating = true; //Post runnable to SWTThread Utils.execSWTThread(new AERunnable() { public void runSupport() { updating = false; if (splash == null || splash.isDisposed()) { return; } Image newCurrent = new Image(display, background, SWT.IMAGE_COPY); GC gc = new GC(newCurrent); try { gc.setAntialias(SWT.ON); gc.setTextAntialias(SWT.ON); } catch (Exception e) { } int y = pbY; if (task != null) { gc.setFont(textFont); gc.setForeground(textColor); Point extent = gc.textExtent(task); y = pbY - extent.y - 5; gc.setClipping(OFFSET_LEFT, y, width - (OFFSET_LEFT * 2), extent.y); gc.drawText(task, OFFSET_LEFT, y, true); gc.setClipping((Rectangle) null); } if(PB_INVERTED){ gc.setForeground(fadedGreyColor); gc.setBackground(fadedGreyColor); gc.fillRectangle(pbX-PB_INVERTED_X_OFFSET, pbY + Math.abs(PB_HEIGHT - PB_INVERTED_BG_HEIGHT) / 2, pbWidth+2*PB_INVERTED_X_OFFSET, PB_INVERTED_BG_HEIGHT); gc.setForeground(progressBarColor); gc.setBackground(progressBarColor); gc.fillRectangle(pbX, pbY, percent * pbWidth / 100, PB_HEIGHT); } else { gc.setForeground(progressBarColor); gc.setBackground(progressBarColor); if(DISPLAY_BORDER){ gc.fillRectangle(pbX + 1, pbY, percent * (pbWidth - 2) / 100, PB_HEIGHT); gc.setForeground(fadedGreyColor); gc.setBackground(fadedGreyColor); gc.fillRectangle(pbX, pbY - 1, pbWidth, 1); gc.fillRectangle(pbX + pbWidth - 1, pbY, 1, PB_HEIGHT); gc.fillRectangle(pbX, pbY + PB_HEIGHT, pbWidth, 1); gc.fillRectangle(pbX, pbY, 1, PB_HEIGHT); } else { gc.fillRectangle(pbX, pbY, percent * pbWidth / 100, PB_HEIGHT); } } Image old = current; current = newCurrent; if (old != null && !old.isDisposed()) { old.dispose(); } gc.dispose(); canvas.redraw(0, y, width, height - y, true); canvas.update(); } }); } public int getPercent() { return percent; } // AzureusCoreListener public void reportPercent(final int percent) { //System.out.println("splash: " + percent + " via " + Debug.getCompressedStackTrace()); //Ensure that display is set and not disposed if (display == null || display.isDisposed()) return; //OK Tricky way to close the splash window BUT ... sending a percent > 100 means closing if (percent > 100) { closeSplash(); return; } if (this.percent != percent) { this.percent = percent; update(); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/Cursors.java0000644000175000017500000000371710624713324024100 0ustar adrianadrian/* * Created on 2 mai 2004 Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details ( * see the LICENSE file ). * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, 8 Alle Lenotre, La Grille Royale, * 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.mainwindow; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; /** * @author Olivier Chalouhi * */ public class Cursors { public static Cursor handCursor = null; public static void init() { try { Utils.execSWTThread(new AERunnable() { public void runSupport() { Display display = SWTThread.getInstance().getDisplay(); if (display != null && !display.isDisposed()) { handCursor = new Cursor(display, SWT.CURSOR_HAND); } } }); } catch (Exception e) { Debug.out("Cursor Init", e); } } public static void dispose() { try { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (handCursor != null && !handCursor.isDisposed()) { handCursor.dispose(); } } }); } catch (Exception e) { Debug.out("Cursor Destroy", e); } } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/TorrentOpener.java0000644000175000017500000003120311171750562025240 0ustar adrianadrian/* * Created on 3 mai 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Alle Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.mainwindow; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.OpenTorrentWindow; import org.gudy.azureus2.ui.swt.URLTransfer; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.sharing.ShareUtils; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import com.aelitis.azureus.core.*; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.core.vuzefile.VuzeFileComponent; import com.aelitis.azureus.core.vuzefile.VuzeFileHandler; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; /** * @author Olivier Chalouhi * @author TuxPaper (openTorrentWindow) */ public class TorrentOpener { /** * Open a torrent. Possibly display a window if the user config says so * * @param torrentFile Torrent to open (file, url, etc) */ public static void openTorrent(String torrentFile) { openTorrentWindow(null, new String[] { torrentFile }, false); } public static void openTorrents(String[] torrentFiles) { openTorrentWindow(null, torrentFiles, false); } /** * Open the torrent window * */ public static void openTorrentWindow() { openTorrentWindow(null, null, false); } protected static void openTorrentsForTracking( final String path, final String fileNames[] ) { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(final AzureusCore core) { final Display display = SWTThread.getInstance().getDisplay(); if (display == null || display.isDisposed() || core == null) return; new AEThread("TorrentOpener") { public void runSupport() { for (int i = 0; i < fileNames.length; i++) { try { TOTorrent t = TorrentUtils.readFromFile(new File(path, fileNames[i]), true); core.getTrackerHost().hostTorrent(t, true, true); } catch (Throwable e) { Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "Torrent open fails for '" + path + File.separator + fileNames[i] + "'", e)); } } } }.start(); } }); } public static void openTorrentTrackingOnly() { Utils.execSWTThread(new AERunnable() { public void runSupport() { final Shell shell = Utils.findAnyShell(); if (shell == null) return; FileDialog fDialog = new FileDialog(shell, SWT.OPEN | SWT.MULTI); fDialog.setFilterPath(getFilterPathTorrent()); fDialog .setFilterExtensions(new String[] { "*.torrent", "*.tor", Constants.FILE_WILDCARD }); fDialog.setFilterNames(new String[] { "*.torrent", "*.tor", Constants.FILE_WILDCARD }); fDialog.setText(MessageText.getString("MainWindow.dialog.choose.file")); String path = setFilterPathTorrent(fDialog.open()); if (path == null) return; TorrentOpener.openTorrentsForTracking(path, fDialog.getFileNames()); } }); } public static void openTorrentSimple() { Utils.execSWTThread(new AERunnable() { public void runSupport() { final Shell shell = Utils.findAnyShell(); if (shell == null) return; FileDialog fDialog = new FileDialog(shell, SWT.OPEN | SWT.MULTI); fDialog.setFilterPath(getFilterPathTorrent()); fDialog.setFilterExtensions(new String[] { "*.torrent", "*.tor", Constants.FILE_WILDCARD }); fDialog.setFilterNames(new String[] { "*.torrent", "*.tor", Constants.FILE_WILDCARD }); fDialog.setText(MessageText.getString("MainWindow.dialog.choose.file")); String path = setFilterPathTorrent(fDialog.open()); if (path == null) return; openTorrentWindow(path, fDialog.getFileNames(), false); } }); } public static void openDroppedTorrents(DropTargetEvent event, final boolean bAllowShareAdd) { if (event.data == null) return; final boolean bOverrideToStopped = event.detail == DND.DROP_COPY; if (event.data instanceof String[] || event.data instanceof String) { final String[] sourceNames = (event.data instanceof String[]) ? (String[]) event.data : new String[] { (String) event.data }; if (sourceNames == null) event.detail = DND.DROP_NONE; if (event.detail == DND.DROP_NONE) return; for (int i = 0; (i < sourceNames.length); i++) { final File source = new File(sourceNames[i]); String sURL = UrlUtils.parseTextForURL(sourceNames[i], true); if (sURL != null && !source.exists()) { openTorrentWindow(null, new String[] { sURL }, bOverrideToStopped); } else if (source.isFile()) { // go async as vuze file handling can require UI access which then blocks // if this is happening during init new AEThread2( "asyncOpen", true ) { public void run() { String filename = source.getAbsolutePath(); VuzeFileHandler vfh = VuzeFileHandler.getSingleton(); if ( vfh.loadAndHandleVuzeFile( filename, VuzeFileComponent.COMP_TYPE_NONE ) != null ){ return; } try { if (!TorrentUtils.isTorrentFile(filename) && bAllowShareAdd) { Logger.log(new LogEvent(LogIDs.GUI, "openDroppedTorrents: file not a torrent file, sharing")); ShareUtils.shareFile(filename); } else { openTorrentWindow(null, new String[] { filename }, bOverrideToStopped); } } catch (Exception e) { Logger.log(new LogAlert(LogAlert.REPEATABLE, "Torrent open fails for '" + filename + "'", e)); } } }.start(); } else if (source.isDirectory()) { String dir_name = source.getAbsolutePath(); if (!bAllowShareAdd) { openTorrentWindow(dir_name, null, bOverrideToStopped); } else { String drop_action = COConfigurationManager.getStringParameter( "config.style.dropdiraction" ); if (drop_action.equals("1")) { ShareUtils.shareDir(dir_name); } else if (drop_action.equals("2")) { ShareUtils.shareDirContents(dir_name, false); } else if (drop_action.equals("3")) { ShareUtils.shareDirContents(dir_name, true); } else { openTorrentWindow(dir_name, null, bOverrideToStopped); } } } } } else if (event.data instanceof URLTransfer.URLType) { openTorrentWindow(null, new String[] { ((URLTransfer.URLType) event.data).linkURL }, bOverrideToStopped); } } public static String getFilterPathData() { String before = COConfigurationManager.getStringParameter("previous.filter.dir.data"); if( before != null && before.length() > 0 ) { return before; } String def; try { def = COConfigurationManager.getDirectoryParameter("Default save path"); return def; } catch (IOException e) { return ""; } } public static String getFilterPathTorrent() { String before = COConfigurationManager.getStringParameter("previous.filter.dir.torrent"); if( before != null && before.length() > 0 ) { return before; } return COConfigurationManager.getStringParameter("General_sDefaultTorrent_Directory"); } public static String setFilterPathData( String path ) { if( path != null && path.length() > 0 ) { File test = new File( path ); if( !test.isDirectory() ) test = test.getParentFile(); String now = ""; if( test != null ) now = test.getAbsolutePath(); String before = COConfigurationManager.getStringParameter("previous.filter.dir.data"); if( before == null || before.length() == 0 || !before.equals( now ) ) { COConfigurationManager.setParameter( "previous.filter.dir.data", now ); COConfigurationManager.save(); } } return path; } public static String setFilterPathTorrent( String path ) { if( path != null && path.length() > 0 ) { File test = new File( path ); if( !test.isDirectory() ) test = test.getParentFile(); String now = ""; if( test != null ) now = test.getAbsolutePath(); String before = COConfigurationManager.getStringParameter("previous.filter.dir.torrent"); if( before == null || before.length() == 0 || !before.equals( now ) ) { COConfigurationManager.setParameter( "previous.filter.dir.torrent", now ); COConfigurationManager.save(); } return now; } return path; } private static void openTorrentWindow(final String path, final String[] torrents, final boolean bOverrideStartModeToStopped) { // loadVuzeFile takes a long time if it's fetching a URL, so prevent it // from blocking the calling thread (like the SWT Thread) new AEThread2("openTorrentWindow", true) { public void run() { _openTorrentWindow(path, torrents, bOverrideStartModeToStopped); } }.start(); } private static void _openTorrentWindow(final String path, String[] torrents, final boolean bOverrideStartModeToStopped) { // this is a good place to trim out any .vuze files if ( torrents != null && torrents.length > 0 ){ VuzeFileHandler vfh = VuzeFileHandler.getSingleton(); List non_vuze_files = new ArrayList(); List vuze_files = new ArrayList(); for (int i=0;i 0 ){ VuzeFile[] vfs = new VuzeFile[vuze_files.size()]; vuze_files.toArray( vfs ); vfh.handleFiles( vfs, VuzeFileComponent.COMP_TYPE_NONE ); } if ( non_vuze_files.size() == 0 && vuze_files.size() > 0 ){ return; } String[] t = new String[non_vuze_files.size()]; non_vuze_files.toArray( t ); torrents = t; } final String[] f_torrents = torrents; Utils.execSWTThread(new AERunnable() { public void runSupport() { Shell shell = Utils.findAnyShell(); if (!AzureusCoreFactory.isCoreRunning()) { // not running, wait until running, then either // wait for UIFunctionsManager to be initialized, // or open immediately AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { if (UIFunctionsManager.getUIFunctions() == null) { core.addLifecycleListener(new AzureusCoreLifecycleAdapter() { public void componentCreated(AzureusCore core, AzureusCoreComponent component) { if (component instanceof UIFunctionsSWT) { openTorrentWindow(path, f_torrents, bOverrideStartModeToStopped); } } }); } else { openTorrentWindow(path, f_torrents, bOverrideStartModeToStopped); } } }); } if (shell == null) { Debug.out("openTorrentWindow().. no shell"); return; } OpenTorrentWindow.invoke(shell, AzureusCoreFactory.getSingleton().getGlobalManager(), path, f_torrents, bOverrideStartModeToStopped, false, false); } }); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/MainMenu.java0000644000175000017500000002423211273607612024147 0ustar adrianadrian/* * Created on 4 mai 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Alle Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.mainwindow; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.ui.swt.Utils; /** * @author Olivier Chalouhi */ public class MainMenu implements IMainMenu { /** * @deprecated */ public static int MENU_BAR = 0; /** * @deprecated */ public static int MENU_TRANSFER = 1; /** * @deprecated */ public static int MENU_VIEW = 2; private MainWindow mainWindow; private Menu menuBar; /** *

    Creates the main menu bar and attaches it to the given shell

    * @param shell A shell */ public MainMenu(Shell shell) { mainWindow = MainWindow.getWindow(); createMenus(shell); } public void setMainWindow(MainWindow mainWindow) { this.mainWindow = mainWindow; } public void linkMenuBar(Shell parent) { parent.setMenuBar(menuBar); } private void createMenus(final Shell parent) { //The Main Menu menuBar = new Menu(parent, SWT.BAR); parent.setMenuBar(menuBar); addFileMenu(parent); /* ======= View, Transfers, Torrent, Tools menus ===== * hig compliance for OSX dictates that more granular actions are positioned farther * on the right of the menu and more general actions are closer to the left * NOTE: we keep the original menu order (for non-OSX) in-tact so as to not disturb existing non-OSX users */ if (Constants.isOSX) { addViewMenu(parent); addTransferMenu(parent); addTorrentMenu(parent); } else { addTransferMenu(parent); addTorrentMenu(parent); addViewMenu(parent); /* * The Tools menu is only present on non-OSX systems */ addToolsMenu(parent); } addPluginsMenu(parent); // ========== Windows menu (OSX only)================ if (true == Constants.isOSX) { addWindowMenu(parent); } // =========== Debug menu (development only)========= if (Constants.isCVSVersion()) { DebugMenuHelper.createDebugMenuItem(menuBar); } addV2HelpMenu(parent); /* * Enabled/disable menus based on what ui mode we're in * NOTE: This is largely superfluous here since all menu items in the classic UI * are available at all time; this method is left here for completeness should we * add dynamic behavior to the menu in the future. */ MenuFactory.updateEnabledStates(menuBar); } /** * Creates the Window menu and all its children * @param parent */ private void addWindowMenu(final Shell parent) { MenuItem menu_window = MenuFactory.createWindowMenuItem(menuBar); Menu windowMenu = menu_window.getMenu(); MenuFactory.addMinimizeWindowMenuItem(windowMenu); MenuFactory.addZoomWindowMenuItem(windowMenu); MenuFactory.addSeparatorMenuItem(windowMenu); MenuFactory.addBlockedIPsMenuItem(windowMenu); MenuFactory.addSeparatorMenuItem(windowMenu); MenuFactory.addBringAllToFrontMenuItem(windowMenu); MenuFactory.addSeparatorMenuItem(windowMenu); MenuFactory.appendWindowMenuItems(windowMenu); } /** * Creates the File menu and all its children * @param parent */ private void addFileMenu(final Shell parent) { MenuItem fileItem = MenuFactory.createFileMenuItem(menuBar); Menu fileMenu = fileItem.getMenu(); MenuFactory.addCreateMenuItem(fileMenu); MenuItem openMenuItem = MenuFactory.createOpenMenuItem(fileMenu); Menu openSubMenu = openMenuItem.getMenu(); MenuFactory.addOpenTorrentMenuItem(openSubMenu); MenuFactory.addOpenTorrentForTrackingMenuItem(openSubMenu); MenuFactory.addOpenVuzeFileMenuItem(openSubMenu); MenuItem shareMenuItem = MenuFactory.createShareMenuItem(fileMenu); Menu shareSubMenu = shareMenuItem.getMenu(); MenuFactory.addShareFileMenuItem(shareSubMenu); MenuFactory.addShareFolderMenuItem(shareSubMenu); MenuFactory.addShareFolderContentMenuItem(shareSubMenu); MenuFactory.addShareFolderContentRecursiveMenuItem(shareSubMenu); MenuFactory.addSeparatorMenuItem(fileMenu); MenuFactory.addImportMenuItem(fileMenu); MenuFactory.addExportMenuItem(fileMenu); MenuFactory.addSeparatorMenuItem(fileMenu); MenuFactory.addCloseWindowMenuItem(fileMenu); MenuFactory.addCloseTabMenuItem(fileMenu, mainWindow); MenuFactory.addCloseDetailsMenuItem(fileMenu); MenuFactory.addCloseDownloadBarsToMenu(fileMenu); /* * No need for restart and exit on OSX in the File menu since it is moved to the gobla application * menu instead see org.gudy.azureus2.ui.swt.osx.CarbonUIEnhancer for detail about that menu */ if (!Utils.isCarbon) { MenuFactory.addSeparatorMenuItem(fileMenu); MenuFactory.addRestartMenuItem(fileMenu); } if (!Constants.isOSX) { MenuFactory.addExitMenuItem(fileMenu); } } /** * Creates the Transfer menu and all its children * @param parent */ private void addTransferMenu(final Shell parent) { MenuFactory.createTransfersMenuItem(menuBar); } /** * Creates the View menu and all its children * @param parent */ private void addViewMenu(final Shell parent) { try { MenuItem viewItem = MenuFactory.createViewMenuItem(menuBar); Menu viewMenu = viewItem.getMenu(); MenuFactory.addLabelMenuItem(viewMenu, "MainWindow.menu.view.show"); indent(MenuFactory.addMyTorrentsMenuItem(viewMenu)); indent(MenuFactory.addMyTrackerMenuItem(viewMenu)); indent(MenuFactory.addMySharesMenuItem(viewMenu)); indent(MenuFactory.addViewToolbarMenuItem(viewMenu)); indent(MenuFactory.addTransferBarToMenu(viewMenu)); indent(MenuFactory.addAllPeersMenuItem(viewMenu)); indent(MenuFactory.addClientStatsMenuItem(viewMenu)); if (Constants.isCVSVersion()) { indent(MenuFactory.addDetailedListMenuItem(viewMenu)); } /* * These 2 menus resides on the Tools menu on non-OSX platforms; * since the Tools menu is not present in the OSX version these menus are added here to the View menu */ if (Constants.isOSX) { indent(MenuFactory.addConsoleMenuItem(viewMenu)); indent(MenuFactory.addStatisticsMenuItem(viewMenu)); } } catch (Exception e) { Debug.out("Error creating View Menu", e); } } /** * Creates the Torrent menu and all its children * @param parent */ private void addTorrentMenu(final Shell parent) { /* * The Torrents menu is now a user-configured option */ if (true == COConfigurationManager.getBooleanParameter("show_torrents_menu")) { MenuFactory.createTorrentMenuItem(menuBar); } } /** * Creates the Tools menu and all its children * @param parent */ private void addToolsMenu(final Shell parent) { MenuItem item = MenuFactory.createToolsMenuItem(menuBar); Menu toolsMenu = item.getMenu(); MenuFactory.addBlockedIPsMenuItem(toolsMenu); MenuFactory.addConsoleMenuItem(toolsMenu); MenuFactory.addStatisticsMenuItem(toolsMenu); MenuFactory.addNatTestMenuItem(toolsMenu); MenuFactory.addSpeedTestMenuItem(toolsMenu); MenuFactory.addSeparatorMenuItem(toolsMenu); MenuFactory.addConfigWizardMenuItem(toolsMenu); MenuFactory.addOptionsMenuItem(toolsMenu); } /** * Creates the Plugins menu and all its children * @param parent */ private void addPluginsMenu(final Shell parent) { /* * NOTE: We are specifying that the Plugins menu be created WITHOUT the 'get plugins' menu item * since that item is an addition only for the new Vuze menu */ MenuFactory.createPluginsMenuItem(menuBar, false); } /** * Creates the Help menu and all its children * @param parent */ private void addV2HelpMenu(final Shell parent) { MenuItem helpItem = MenuFactory.createHelpMenuItem(menuBar); Menu helpMenu = helpItem.getMenu(); if (false == Constants.isOSX) { MenuFactory.addAboutMenuItem(helpMenu); MenuFactory.addSeparatorMenuItem(helpMenu); } MenuFactory.addHealthMenuItem(helpMenu); MenuFactory.addReleaseNotesMenuItem(helpMenu); MenuFactory.addWhatsNewMenuItem(helpMenu); MenuFactory.addWikiMenuItem(helpMenu); MenuFactory.addGetPluginsMenuItem(helpMenu); MenuFactory.addSeparatorMenuItem(helpMenu); if (false == SystemProperties.isJavaWebStartInstance()) { MenuFactory.addCheckUpdateMenuItem(helpMenu); } MenuFactory.addDonationMenuItem(helpMenu); MenuFactory.addSeparatorMenuItem(helpMenu); MenuFactory.addDebugHelpMenuItem(helpMenu); } private static final void indent(MenuItem item) { item.setData("IndentItem", "YES"); item.setText(" " + item.getText()); } /** * @deprecated This method has been replaced with {@link #getMenu(String)}; * use {@link #getMenu(IMenuConstants.MENU_ID_MENU_BAR)} , * {@link #getMenu(IMenuConstants.MENU_ID_TRANSFERS)}, or * {@link #getMenu(IMenuConstants.MENU_ID_VIEW)} instead * @param id * @return */ public Menu getMenu(int id) { /* * KN: Retrofitted to use the new getMenu(String) method */ if (id == MENU_BAR) { return getMenu(IMenuConstants.MENU_ID_MENU_BAR); } if (id == MENU_TRANSFER) { return getMenu(IMenuConstants.MENU_ID_TRANSFERS); } if (id == MENU_VIEW) { return getMenu(IMenuConstants.MENU_ID_VIEW); } return null; } public Menu getMenu(String id) { if (true == IMenuConstants.MENU_ID_MENU_BAR.equals(id)) { return menuBar; } return MenuFactory.findMenu(menuBar, id); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/Colors.java0000644000175000017500000003325011267676662023715 0ustar adrianadrian/* * Created on 2 mai 2004 Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details ( * see the LICENSE file ). * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, 8 Alle Lenotre, La Grille Royale, * 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.mainwindow; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.swt.utils.ColorCache; /** * @author Olivier Chalouhi * @author MjrTom * 2005/Dec/08: green * */ public class Colors implements ParameterListener { private static final LogIDs LOGID = LogIDs.GUI; private static Colors instance = null; public static final int BLUES_LIGHTEST = 0; public static final int BLUES_DARKEST = 9; public static final int BLUES_MIDLIGHT = (BLUES_DARKEST + 1) / 4; public static final int BLUES_MIDDARK = ((BLUES_DARKEST + 1) / 2) + BLUES_MIDLIGHT; public static final int FADED_LIGHTEST = 0; public static final int FADED_DARKEST = 9; public static Color[] blues = new Color[BLUES_DARKEST + 1]; public static Color[] faded = new Color[FADED_DARKEST + 1]; public static Color colorProgressBar; public static Color colorInverse; public static Color colorShiftLeft; public static Color colorShiftRight; public static Color colorError; public static Color colorErrorBG; public static Color colorAltRow; public static Color colorWarning; public static Color black; public static Color light_grey; public static Color blue; public static Color green; public static Color fadedGreen; public static Color grey; public static Color red; public static Color fadedRed; public static Color yellow; public static Color fadedYellow; public static Color white; public static Color background; public static Color red_ConsoleView; private static AEMonitor class_mon = new AEMonitor( "Colors" ); private void allocateBlues() { int r = 0; int g = 128; int b = 255; try { r = COConfigurationManager.getIntParameter("Color Scheme.red", r); g = COConfigurationManager.getIntParameter("Color Scheme.green", g); b = COConfigurationManager.getIntParameter("Color Scheme.blue", b); boolean bGrayScale = (r == b) && (b == g); HSLColor hslColor = new HSLColor(); Color colorTables = display.getSystemColor(SWT.COLOR_LIST_BACKGROUND); int tR = colorTables.getRed(); int tG = colorTables.getGreen(); int tB = colorTables.getBlue(); // 0 == window background (white) // [blues.length-1] == rgb // in between == blend for (int i = 0; i < blues.length; i++) { hslColor.initHSLbyRGB(r, g, b); float blendBy = (i == 0) ? 1 : (float) 1.0 - ((float) i / (float) (blues.length - 1)); hslColor.blend(tR, tG, tB, blendBy); blues[i] = ColorCache.getColor(display, hslColor.getRed(), hslColor.getGreen(), hslColor.getBlue()); int iSat = hslColor.getSaturation(); int luminence = hslColor.getLuminence(); if (luminence < 20) { if (iSat > 10) { hslColor.setSaturation(iSat / 2); hslColor.brighten(1.25f); } else if (bGrayScale) { // gray hslColor.brighten(1.2f); } } else { if (iSat > 10) { hslColor.setSaturation(iSat / 2); hslColor.brighten(0.75f); } else if (bGrayScale) { // gray hslColor.brighten(0.8f); } } faded[i] = ColorCache.getColor(display, hslColor.getRed(), hslColor.getGreen(), hslColor.getBlue()); } if (bGrayScale) { if (b > 200) b -= 20; else b += 20; } hslColor.initHSLbyRGB(r, g, b); hslColor.reverseColor(); colorInverse = ColorCache.getColor(display, hslColor.getRed(), hslColor.getGreen(), hslColor.getBlue()); hslColor.initHSLbyRGB(r, g, b); hslColor.setHue(hslColor.getHue() + 25); colorShiftRight = ColorCache.getColor(display, hslColor.getRed(), hslColor.getGreen(), hslColor.getBlue()); hslColor.initHSLbyRGB(r, g, b); hslColor.setHue(hslColor.getHue() - 25); colorShiftLeft = ColorCache.getColor(display, hslColor.getRed(), hslColor.getGreen(), hslColor.getBlue()); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "Error allocating colors", e)); } } private void allocateColorProgressBar() { if (display == null || display.isDisposed()) return; colorProgressBar = new AllocateColor("progressBar", colorShiftRight, colorProgressBar).getColor(); } private void allocateColorErrorBG() { if (display == null || display.isDisposed()) return; Utils.execSWTThread(new AERunnable() { public void runSupport() { Color colorTables = display.getSystemColor(SWT.COLOR_LIST_BACKGROUND); HSLColor hslColor = new HSLColor(); hslColor.initHSLbyRGB(colorTables.getRed(), colorTables.getGreen(), colorTables.getBlue()); int lum = hslColor.getLuminence(); int sat = hslColor.getSaturation(); lum = (int)((lum > 127) ? lum * 0.8 : lum * 1.3); if (sat == 0) { sat = 80; } hslColor.initRGBbyHSL(0, sat, lum); colorErrorBG = new AllocateColor("errorBG", new RGB(hslColor.getRed(), hslColor.getGreen(), hslColor.getBlue()), colorErrorBG).getColor(); } }, false); } private void allocateColorError() { if (display == null || display.isDisposed()) return; colorError = new AllocateColor("error", new RGB(255, 68, 68), colorError) .getColor(); } private void allocateColorWarning() { if (display == null || display.isDisposed()) return; Utils.execSWTThread(new AERunnable() { public void runSupport() { Color colorTables = display.getSystemColor(SWT.COLOR_LIST_BACKGROUND); HSLColor hslBG = new HSLColor(); hslBG.initHSLbyRGB(colorTables.getRed(), colorTables.getGreen(), colorTables.getBlue()); int lum = hslBG.getLuminence(); HSLColor hslColor = new HSLColor(); hslColor.initRGBbyHSL(25, 200, 128 + (lum < 160 ? 10 : -10)); colorWarning = new AllocateColor("warning", new RGB(hslColor.getRed(), hslColor.getGreen(), hslColor.getBlue()), colorWarning).getColor(); } }, false); } private void allocateColorAltRow() { if (display == null || display.isDisposed()) return; Utils.execSWTThread(new AERunnable() { public void runSupport() { Color colorTables = display.getSystemColor(SWT.COLOR_LIST_BACKGROUND); HSLColor hslColor = new HSLColor(); hslColor.initHSLbyRGB(colorTables.getRed(), colorTables.getGreen(), colorTables.getBlue()); int lum = hslColor.getLuminence(); if (lum > 127) lum -= 16; else lum += 30; // it's usually harder to see difference in darkness hslColor.setLuminence(lum); //HSLColor blueHSL = new HSLColor(); //RGB rgb = blues[BLUES_DARKEST].getRGB(); //blueHSL.initHSLbyRGB(rgb.red, rgb.green, rgb.blue); //int blueHue = blueHSL.getHue(); //int altHue = hslColor.getHue(); //if (blueHue > altHue) { // altHue += 11; //} else { // altHue -= 11; //} //hslColor.setHue(blueHue); colorAltRow = new AllocateColor("altRow", new RGB(hslColor.getRed(), hslColor.getGreen(), hslColor.getBlue()), colorAltRow).getColor(); } }, false); } /** Allocates a color */ private class AllocateColor extends AERunnable { private String sName; private RGB rgbDefault; private Color newColor; public AllocateColor(String sName, RGB rgbDefault, Color colorOld) { this.sName = sName; this.rgbDefault = rgbDefault; } public AllocateColor(String sName, final Color colorDefault, Color colorOld) { this.sName = sName; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (!colorDefault.isDisposed()) AllocateColor.this.rgbDefault = colorDefault.getRGB(); else AllocateColor.this.rgbDefault = new RGB(0, 0, 0); } }, false); } public Color getColor() { Utils.execSWTThread(this, false); return newColor; } public void runSupport() { if (COConfigurationManager.getBooleanParameter("Colors." + sName + ".override")) { newColor = ColorCache.getColor(display, COConfigurationManager.getIntParameter("Colors." + sName + ".red", rgbDefault.red), COConfigurationManager.getIntParameter("Colors." + sName + ".green", rgbDefault.green), COConfigurationManager.getIntParameter("Colors." + sName + ".blue", rgbDefault.blue)); } else { newColor = ColorCache.getColor(display, rgbDefault.red, rgbDefault.green, rgbDefault.blue); // Since the color is not longer overriden, reset back to default // so that the user sees the correct color in Config. COConfigurationManager.setRGBParameter("Colors." + sName, rgbDefault.red, rgbDefault.green, rgbDefault.blue); } } } private void allocateDynamicColors() { if(display == null || display.isDisposed()) return; Utils.execSWTThread(new AERunnable(){ public void runSupport() { allocateBlues(); allocateColorProgressBar(); allocateColorErrorBG(); } }, false); } private void allocateNonDynamicColors() { allocateColorWarning(); allocateColorError(); allocateColorAltRow(); black = ColorCache.getColor(display, 0, 0, 0); light_grey = ColorCache.getColor(display, 192, 192, 192); blue = ColorCache.getColor(display, 0, 0, 170); green = ColorCache.getColor(display, 0, 170, 0); fadedGreen = ColorCache.getColor(display, 96, 160, 96); grey = ColorCache.getColor(display, 170, 170, 170); red = ColorCache.getColor(display, 255, 0, 0); fadedRed = ColorCache.getColor(display, 160, 96, 96); yellow = ColorCache.getColor(display, 255, 255, 0); fadedYellow = ColorCache.getColor(display, 255, 255, 221); white = ColorCache.getColor(display, 255, 255, 255); background = ColorCache.getColor(display, 248, 248, 248); red_ConsoleView = ColorCache.getColor(display, 255, 192, 192); } private Display display; private Colors() { instance = this; try { display = SWTThread.getInstance().getDisplay(); } catch (Exception e) { display = Display.getDefault(); } allocateDynamicColors(); allocateNonDynamicColors(); addColorsChangedListener(this); } public static Colors getInstance() { try{ class_mon.enter(); if (instance == null) instance = new Colors(); return instance; }finally{ class_mon.exit(); } } public void addColorsChangedListener(ParameterListener l) { COConfigurationManager.addParameterListener("Color Scheme", l); COConfigurationManager.addParameterListener("Colors.progressBar.override", l); COConfigurationManager.addParameterListener("Colors.progressBar", l); COConfigurationManager.addParameterListener("Colors.error.override", l); COConfigurationManager.addParameterListener("Colors.error", l); COConfigurationManager.addParameterListener("Colors.warning.override", l); COConfigurationManager.addParameterListener("Colors.warning", l); COConfigurationManager.addParameterListener("Colors.altRow.override", l); COConfigurationManager.addParameterListener("Colors.altRow", l); } public void removeColorsChangedListener(ParameterListener l) { COConfigurationManager.removeParameterListener("Color Scheme", l); COConfigurationManager.removeParameterListener("Colors.progressBar.override", l); COConfigurationManager.removeParameterListener("Colors.progressBar", l); COConfigurationManager.removeParameterListener("Colors.error.override", l); COConfigurationManager.removeParameterListener("Colors.error", l); COConfigurationManager.removeParameterListener("Colors.warning.override", l); COConfigurationManager.removeParameterListener("Colors.warning", l); COConfigurationManager.removeParameterListener("Colors.altRow.override", l); COConfigurationManager.removeParameterListener("Colors.altRow", l); } public void parameterChanged(String parameterName) { if (parameterName.equals("Color Scheme")) { allocateDynamicColors(); } if(parameterName.startsWith("Colors.progressBar")) { allocateColorProgressBar(); } if(parameterName.startsWith("Colors.error")) { allocateColorError(); } if(parameterName.startsWith("Colors.warning")) { allocateColorWarning(); } if(parameterName.startsWith("Colors.altRow")) { allocateColorAltRow(); } } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/Refreshable.java0000644000175000017500000000055510667726560024674 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.mainwindow; public interface Refreshable { /** * This method is called on each refresh. * The view should not instanciate a Thread to refresh itself, unless this is for async purposes. In which case, don't forget to call the display.asyncexec method. * Called by the GUI Thread */ public void refresh(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/SWTThreadAlreadyInstanciatedException.java0000644000175000017500000000227011012742402031735 0ustar adrianadrian/* * Created on May 1, 2004 * Created by Olivier Chalouhi * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.mainwindow; /** * */ public class SWTThreadAlreadyInstanciatedException extends Exception { public SWTThreadAlreadyInstanciatedException() { super("The SWT Thread has already been instanciated"); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/ListenerNeedingCoreRunning.java0000644000175000017500000000132711171750562027667 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.mainwindow; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; /** * SWT Listener that, when fired, waits for AzureusCore to be available */ public abstract class ListenerNeedingCoreRunning implements Listener { public final void handleEvent(final Event event) { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { handleEvent(core, event); } }); } public abstract void handleEvent(AzureusCore core, Event event); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/IMainMenu.java0000644000175000017500000000022410747771526024266 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.mainwindow; import org.eclipse.swt.widgets.Menu; public interface IMainMenu { public Menu getMenu(String id); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/Initializer.java0000644000175000017500000003362611267524616024735 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Olivier Chalouhi * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.mainwindow; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Iterator; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.ipfilter.IpFilterManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginEvent; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; import org.gudy.azureus2.ui.common.util.UserAlerts; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.auth.AuthenticatorWindow; import org.gudy.azureus2.ui.swt.auth.CertificateTrustWindow; import org.gudy.azureus2.ui.swt.auth.CryptoWindow; import org.gudy.azureus2.ui.swt.networks.SWTNetworkSelection; import org.gudy.azureus2.ui.swt.pluginsinstaller.InstallPluginWizard; import org.gudy.azureus2.ui.swt.progress.ProgressWindow; import org.gudy.azureus2.ui.swt.update.UpdateMonitor; import org.gudy.azureus2.ui.swt.updater2.PreUpdateChecker; import org.gudy.azureus2.ui.swt.updater2.SWTUpdateChecker; import com.aelitis.azureus.core.*; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.launcher.Launcher; import com.aelitis.azureus.ui.IUIIntializer; import com.aelitis.azureus.ui.InitializerListener; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.utils.UIMagnetHandler; /** * this class initiatize all GUI and Core components which are : * 1. The SWT Thread * 2. Images * 3. The Splash Screen if needed * 4. The GlobalManager * 5. The Main Window in correct state or the Password window if needed. */ public class Initializer implements AzureusCoreListener, IUIIntializer { private static final LogIDs LOGID = LogIDs.GUI; private AzureusCore azureus_core; private GlobalManager gm; private StartServer startServer; private CopyOnWriteList listeners = new CopyOnWriteList(); private AEMonitor listeners_mon = new AEMonitor( "Initializer:l" ); private String[] args; private AESemaphore semFilterLoader = new AESemaphore("filter loader"); private AESemaphore init_task = new AESemaphore("delayed init"); public Initializer( final AzureusCore _azureus_core, StartServer _server, String[] _args ) { azureus_core = _azureus_core; startServer = _server; args = _args; Thread filterLoaderThread = new AEThread("filter loader", true) { public void runSupport() { try { azureus_core.getIpFilterManager().getIPFilter(); } finally { semFilterLoader.releaseForever(); } } }; filterLoaderThread.setPriority(Thread.MIN_PRIORITY); filterLoaderThread.start(); try { SWTThread.createInstance(this); } catch(SWTThreadAlreadyInstanciatedException e) { Debug.printStackTrace( e ); } } public static boolean handleStopRestart( final boolean restart ) { UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (functionsSWT != null) { return functionsSWT.dispose(restart, true); } return false; } public void run() { try{ if (initializer != null) { try { initializer.run(); } catch (Throwable t) { // use print stack trace because we don't want to introduce logger t.printStackTrace(); // Ignore and use AZ2 } return; } // else AZ2UI DelayedTask delayed_task = UtilitiesImpl.addDelayedTask("SWT Initialisation", new Runnable() { public void run() { init_task.reserve(); } }); delayed_task.queue(); // initialise the SWT locale util new LocaleUtilSWT( azureus_core ); Display display = SWTThread.getInstance().getDisplay(); new UIMagnetHandler(azureus_core); UIConfigDefaultsSWT.initialize(); //Splash Window is not always shown if (COConfigurationManager.getBooleanParameter("Show Splash")) { SplashWindow.create(display,this); } setNbTasks(6); nextTask(); reportCurrentTaskByKey("splash.firstMessageNoI18N"); Alerts.init(); final ArrayList logEvents = new ArrayList(); ILogEventListener logListener = null; if (COConfigurationManager.getBooleanParameter("Open Console", false)) { logListener = new ILogEventListener() { public void log(LogEvent event) { logEvents.add(event); } }; Logger.addListener(logListener); } final ILogEventListener finalLogListener = logListener; ProgressWindow.register( azureus_core ); new SWTNetworkSelection(); new AuthenticatorWindow(); new CryptoWindow(); new CertificateTrustWindow(); InstallPluginWizard.register( azureus_core, display ); nextTask(); reportCurrentTaskByKey("splash.initializeGM"); azureus_core.addListener( this ); azureus_core.addLifecycleListener(new AzureusCoreLifecycleAdapter() { public void componentCreated(AzureusCore core, AzureusCoreComponent comp) { if (comp instanceof GlobalManager) { gm = (GlobalManager) comp; nextTask(); reportCurrentTask(MessageText.getString("splash.initializePlugins")); } } public void started( final AzureusCore core) { boolean main_window_will_report_complete = false; try{ if (gm == null) return; new UserAlerts(gm); nextTask(); IpFilterManager ipFilterManager = azureus_core.getIpFilterManager(); if (ipFilterManager != null) { String s = MessageText.getString("splash.loadIpFilters"); do { reportCurrentTask(s); s += "."; } while (!semFilterLoader.reserve(3000)); } nextTask(); reportCurrentTaskByKey("splash.initializeGui"); Colors.getInstance(); Cursors.init(); main_window_will_report_complete = true; // main window controls further progress now new MainWindow(core, Initializer.this, logEvents); if (finalLogListener != null) Logger.removeListener(finalLogListener); SWTUpdateChecker.initialize(); PreUpdateChecker.initialize( core, COConfigurationManager.getStringParameter("ui")); UpdateMonitor.getSingleton(core); // setup the update monitor //Tell listeners that all is initialized : Alerts.initComplete(); //Finally, open torrents if any. for (int i = 0; i < args.length; i++) { try { TorrentOpener.openTorrent(args[i]); } catch (Throwable e) { Debug.printStackTrace(e); } } }finally{ if ( !main_window_will_report_complete ){ init_task.release(); } } } public void stopping(AzureusCore core) { Alerts.stopInitiated(); } public void stopped(AzureusCore core) { } public boolean syncInvokeRequired() { return (true); } public boolean requiresPluginInitCompleteBeforeStartedEvent() { return( false ); } public boolean stopRequested(AzureusCore _core) throws AzureusCoreException { return (handleStopRestart(false)); } public boolean restartRequested(final AzureusCore core) { return (handleStopRestart(true)); } }); azureus_core.start(); }catch( Throwable e ){ Logger.log(new LogEvent(LOGID, "Initialization fails:", e)); init_task.release(); } } public void addListener(InitializerListener listener){ try{ listeners_mon.enter(); listeners.add(listener); }finally{ listeners_mon.exit(); } } public void removeListener(InitializerListener listener) { try{ listeners_mon.enter(); listeners.remove(listener); }finally{ listeners_mon.exit(); } } public void reportCurrentTask( AzureusCoreOperation operation, String currentTask ) { if ( operation.getOperationType() == AzureusCoreOperation.OP_INITIALISATION ){ reportCurrentTask( currentTask ); } } public void reportPercent( AzureusCoreOperation operation, int percent ) { if ( operation.getOperationType() == AzureusCoreOperation.OP_INITIALISATION ){ reportPercent( percent ); } } public void reportCurrentTask(String currentTaskString) { try{ listeners_mon.enter(); Iterator iter = listeners.iterator(); while(iter.hasNext()) { try{ InitializerListener listener = (InitializerListener) iter.next(); listener.reportCurrentTask(currentTaskString); }catch( Throwable e ){ Debug.printStackTrace( e ); } } }finally{ listeners_mon.exit(); } } public void initializationComplete() { azureus_core.getPluginManager().firePluginEvent( PluginEvent.PEV_INITIALISATION_UI_COMPLETES ); new DelayedEvent( "SWTInitComplete:delay", 8500, new AERunnable() { public void runSupport() { init_task.release(); } }); } // AzureusCoreListener public void reportPercent(int percent) { int overallPercent = overallPercent(percent); try{ listeners_mon.enter(); Iterator iter = listeners.iterator(); while(iter.hasNext()) { try{ InitializerListener listener = (InitializerListener) iter.next(); listener.reportPercent(overallPercent); }catch( Throwable e ){ Debug.printStackTrace( e ); } } if (overallPercent > 100) { listeners.clear(); } }finally{ listeners_mon.exit(); } } public void stopIt( boolean for_restart, boolean close_already_in_progress ) throws AzureusCoreException { if ( azureus_core != null && !close_already_in_progress ){ if ( for_restart ){ azureus_core.checkRestartSupported(); } } try{ Cursors.dispose(); SWTThread.getInstance().terminate(); }finally{ try{ if ( azureus_core != null && !close_already_in_progress ){ try{ if ( for_restart ){ azureus_core.restart(); }else{ azureus_core.stop(); } }catch( Throwable e ){ // don't let any failure here cause the stop operation to fail Debug.out( e ); } } }finally{ // do this after closing core to minimise window when the we aren't // listening and therefore another Azureus start can potentially get // in and screw things up if ( startServer != null ){ startServer.stopIt(); } } } } private int nbTasks = 1; private int currentTask = 0; private int currentPercent = 0; private int lastTaskPercent = 0; private IUIIntializer initializer; private void setNbTasks(int _nbTasks) { currentTask = 0; nbTasks = _nbTasks; } public void nextTask() { currentTask++; currentPercent = 100 * currentTask / (nbTasks) ; //0% done of current task reportPercent(0); } private int overallPercent(int taskPercent) { lastTaskPercent = taskPercent; //System.out.println("ST percent " + currentPercent + " / " + taskPercent + " : " + (currentPercent + (taskPercent / nbTasks))); return currentPercent + taskPercent / nbTasks; } private void reportCurrentTaskByKey(String key) { reportCurrentTask(MessageText.getString(key)); } // @see com.aelitis.azureus.ui.IUIIntializer#increaseProgresss() public void increaseProgress() { if (lastTaskPercent < 100) { reportPercent(lastTaskPercent + 1); } } public void abortProgress() { currentTask = nbTasks; nextTask(); reportPercent(101); } public static void main(String args[]) { if(Launcher.checkAndLaunch(Initializer.class, args)) return; System.err.println("Shouldn't you be starting with org.gudy.azureus2.ui.swt.Main?"); AzureusCore core = AzureusCoreFactory.create(); new Initializer( core, null,args); } public void runInSWTThread() { String uiMode = UISwitcherUtil.calcUIMode(); if (uiMode.equals("az3")) { try { final Class az3Class = Class.forName("com.aelitis.azureus.ui.swt.Initializer"); final Constructor constructor = az3Class.getConstructor(new Class[] { AzureusCore.class, Boolean.TYPE, String[].class }); initializer = (IUIIntializer) constructor.newInstance(new Object[] { azureus_core, new Boolean(false), args }); initializer.runInSWTThread(); return; } catch (Throwable t) { // use print stack trace because we don't want to introduce logger t.printStackTrace(); // Ignore and use AZ2 } } // else AZ2UI } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/HSLColor.java0000644000175000017500000001430711033057536024063 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.mainwindow; public class HSLColor { private final static int HSLMAX = 255; private final static int RGBMAX = 255; private final static int UNDEFINED = 170; private int pHue; private int pSat; private int pLum; private int pRed; private int pGreen; private int pBlue; public void initHSLbyRGB(int R, int G, int B) { // sets Hue, Sat, Lum int cMax; int cMin; int RDelta; int GDelta; int BDelta; int cMinus; int cPlus; pRed = R; pGreen = G; pBlue = B; //Set Max & MinColor Values cMax = iMax(iMax(R, G), B); cMin = iMin(iMin(R, G), B); cMinus = cMax - cMin; cPlus = cMax + cMin; // Calculate luminescence (lightness) pLum = ((cPlus * HSLMAX) + RGBMAX) / (2 * RGBMAX); if (cMax == cMin) { // greyscale pSat = 0; pHue = UNDEFINED; } else { // Calculate color saturation if (pLum <= (HSLMAX / 2)) { pSat = (int)(((cMinus * HSLMAX) + 0.5) / cPlus); } else { pSat = (int)(((cMinus * HSLMAX) + 0.5) / (2 * RGBMAX - cPlus)); } //Calculate hue RDelta = (int)((((cMax - R) * (HSLMAX / 6)) + 0.5) / cMinus); GDelta = (int)((((cMax - G) * (HSLMAX / 6)) + 0.5) / cMinus); BDelta = (int)((((cMax - B) * (HSLMAX / 6)) + 0.5) / cMinus); if (cMax == R) { pHue = BDelta - GDelta; } else if (cMax == G) { pHue = (HSLMAX / 3) + RDelta - BDelta; } else if (cMax == B) { pHue = ((2 * HSLMAX) / 3) + GDelta - RDelta; } if (pHue < 0) { pHue = pHue + HSLMAX; } } } public void initRGBbyHSL(int H, int S, int L) { int Magic1; int Magic2; pHue = H; pLum = L; pSat = S; if (S == 0) { //Greyscale pRed = (L * RGBMAX) / HSLMAX; //luminescence: set to range pGreen = pRed; pBlue = pRed; } else { if (L <= HSLMAX / 2) { Magic2 = (L * (HSLMAX + S) + (HSLMAX / 2)) / (HSLMAX); } else { Magic2 = L + S - ((L * S) + (HSLMAX / 2)) / HSLMAX; } Magic1 = 2 * L - Magic2; //get R, G, B; change units from HSLMAX range to RGBMAX range pRed = (hueToRGB(Magic1, Magic2, H + (HSLMAX / 3)) * RGBMAX + (HSLMAX / 2)) / HSLMAX; if (pRed > RGBMAX) { pRed = RGBMAX; } pGreen = (hueToRGB(Magic1, Magic2, H) * RGBMAX + (HSLMAX / 2)) / HSLMAX; if (pGreen > RGBMAX) { pGreen = RGBMAX; } pBlue = (hueToRGB(Magic1, Magic2, H - (HSLMAX / 3)) * RGBMAX + (HSLMAX / 2)) / HSLMAX; if (pBlue > RGBMAX) { pBlue = RGBMAX; } } } private int hueToRGB(int mag1, int mag2, int Hue) { // check the range if (Hue < 0) { Hue = Hue + HSLMAX; } else if (Hue > HSLMAX) { Hue = Hue - HSLMAX; } if (Hue < (HSLMAX / 6)) return (mag1 + (((mag2 - mag1) * Hue + (HSLMAX / 12)) / (HSLMAX / 6))); if (Hue < (HSLMAX / 2)) return mag2; if (Hue < (HSLMAX * 2 / 3)) return (mag1 + (((mag2 - mag1) * ((HSLMAX * 2 / 3) - Hue) + (HSLMAX / 12)) / (HSLMAX / 6))); return mag1; } private int iMax(int a, int b) { if (a > b) return a; else return b; } private int iMin(int a, int b) { if (a < b) return a; else return b; } private void greyscale() { initRGBbyHSL(UNDEFINED, 0, pLum); } // -- public int getHue() { return pHue; } public void setHue(int iToValue) { while (iToValue < 0) { iToValue = HSLMAX + iToValue; } while (iToValue > HSLMAX) { iToValue = iToValue - HSLMAX; } initRGBbyHSL(iToValue, pSat, pLum); } // -- public int getSaturation() { return pSat; } public void setSaturation(int iToValue) { if (iToValue < 0) { iToValue = 0; } else if (iToValue > HSLMAX) { iToValue = HSLMAX; } initRGBbyHSL(pHue, iToValue, pLum); } // -- public int getLuminence() { return pLum; } public void setLuminence(int iToValue) { if (iToValue < 0) { iToValue = 0; } else if (iToValue > HSLMAX) { iToValue = HSLMAX; } initRGBbyHSL(pHue, pSat, iToValue); } // -- public int getRed() { return pRed; } private void setRed(int iNewValue) { initHSLbyRGB(iNewValue, pGreen, pBlue); } // -- public int getGreen() { return pGreen; } private void setGreen(int iNewValue) { initHSLbyRGB(pRed, iNewValue, pBlue); } // -- public int getBlue() { return pBlue; } private void setBlue(int iNewValue) { initHSLbyRGB(pRed, pGreen, iNewValue); } // -- public void reverseColor() { setHue(pHue + (HSLMAX / 2)); } // -- private void reverseLight() { setLuminence(HSLMAX - pLum); } // -- public void brighten(float fPercent) { int L; if (fPercent == 0) { return; } L = (int)(pLum * fPercent); if (L < 0) L = 0; if (L > HSLMAX) L = HSLMAX; setLuminence(L); } // -- // -- public void blend(int R, int G, int B, float fPercent) { if (fPercent >= 1) { initHSLbyRGB(R, G, B); return; } if (fPercent <= 0) return; int newR = (int)((R * fPercent) + (pRed * (1.0 - fPercent))); int newG = (int)((G * fPercent) + (pGreen * (1.0 - fPercent))); int newB = (int)((B * fPercent) + (pBlue * (1.0 - fPercent))); initHSLbyRGB(newR, newG, newB); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/SelectableSpeedMenu.java0000644000175000017500000003535411306360220026302 0ustar adrianadrian/** * Created on 04-Jun-2006 * Created by Allan Crooks * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.mainwindow; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerStats; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.UIInputReceiver; import org.gudy.azureus2.plugins.ui.UIInputReceiverListener; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow; import org.gudy.azureus2.ui.swt.shells.SpeedScaleShell; import com.aelitis.azureus.core.AzureusCore; public class SelectableSpeedMenu { private final static int[] increases = { 1, 1, 3, 5, // totals 10 10, 40, // totals 50 50, // 100 50, 50, 100 }; public static void generateMenuItems(final Menu parent, final AzureusCore core, final GlobalManager globalManager, final boolean up_menu) { final MenuItem[] oldItems = parent.getItems(); for(int i = 0; i < oldItems.length; i++) { oldItems[i].dispose(); } final String configKey = up_menu? TransferSpeedValidator.getActiveUploadParameter(globalManager): "Max Download Speed KBs"; final int speedPartitions = 12; int maxBandwidth = COConfigurationManager.getIntParameter(configKey); final boolean unlim = (maxBandwidth == 0); maxBandwidth = adjustMaxBandWidth(maxBandwidth, globalManager, up_menu); boolean auto = false; if ( up_menu ){ final String configAutoKey = TransferSpeedValidator.getActiveAutoUploadParameter(globalManager); auto = TransferSpeedValidator.isAutoSpeedActive(globalManager); // auto final MenuItem auto_item = new MenuItem(parent,SWT.CHECK); auto_item.setText(MessageText.getString("ConfigView.auto")); auto_item.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { COConfigurationManager.setParameter(configAutoKey,auto_item.getSelection()); COConfigurationManager.save(); } }); if(auto)auto_item.setSelection(true); auto_item.setEnabled(TransferSpeedValidator.isAutoUploadAvailable(core)); new MenuItem(parent,SWT.SEPARATOR); } MenuItem item = new MenuItem(parent, SWT.RADIO); item.setText(MessageText.getString("MyTorrentsView.menu.setSpeed.unlimited")); item.setData("maxkb", new Integer(0)); item.setSelection(unlim && !auto); item.addListener(SWT.Selection, getLimitMenuItemListener(up_menu, parent, globalManager, configKey)); Integer[] speed_limits = null; final String config_prefix = "config.ui.speed.partitions.manual." + ((up_menu) ? "upload": "download") + "."; if (COConfigurationManager.getBooleanParameter(config_prefix + "enabled", false)) { speed_limits = parseSpeedPartitionString(COConfigurationManager.getStringParameter(config_prefix + "values", "")); } if (speed_limits == null) { speed_limits = getGenericSpeedList(speedPartitions, maxBandwidth); } for (int i=0; i= 1024) { maxBandwidth = dataReceive / 1024; } } SpeedScaleShell speedScale = new SpeedScaleShell() { public String getStringValue(int value, String sValue) { if (sValue != null) { return prefix + ": " + sValue; } if (value == 0) { return MessageText.getString("MyTorrentsView.menu.setSpeed.unlimited"); } if (value == -1) { return MessageText.getString("ConfigView.auto"); } return prefix + ": " + (value == 0 ? MessageText.getString("ConfigView.unlimited") : DisplayFormatters.formatByteCountToKiBEtcPerSec( getValue() * 1024, true)); } }; int max = unlim ? (isUpSpeed ? 100 : 800) : maxBandwidth * 5; if (max < 50) { max = 50; } speedScale.setMaxValue(max); speedScale.setMaxTextValue(9999999); final String config_prefix = "config.ui.speed.partitions.manual." + (isUpSpeed ? "upload" : "download") + "."; int lastValue = COConfigurationManager.getIntParameter(config_prefix + "last", -10); Integer[] speed_limits; if (COConfigurationManager.getBooleanParameter(config_prefix + "enabled", false)) { speed_limits = parseSpeedPartitionString(COConfigurationManager.getStringParameter( config_prefix + "values", "")); } else { speed_limits = getGenericSpeedList(6, maxBandwidth); } if (speed_limits != null) { for (int i = 0; i < speed_limits.length; i++) { int value = speed_limits[i].intValue(); if (value > 0) { speedScale.addOption(DisplayFormatters.formatByteCountToKiBEtcPerSec( value * 1024, true), value); if (value == lastValue) { lastValue = -10; } } } } speedScale.addOption( MessageText.getString("MyTorrentsView.menu.setSpeed.unlimited"), 0); speedScale.addOption(MessageText.getString("ConfigView.auto"), -1); if (lastValue > 0) { speedScale.addOption(DisplayFormatters.formatByteCountToKiBEtcPerSec( lastValue * 1024, true), lastValue); } // SWT BUG: on windows/linux, if mouse is down on shell open, all mouse events // will not reflect this if (speedScale.open(auto ? -1 : maxBandwidth, Constants.isWindows || Constants.isLinux)) { int value = speedScale.getValue(); if (!speedScale.wasMenuChosen() || lastValue == value) { COConfigurationManager.setParameter(config_prefix + "last", maxBandwidth); } if (value >= 0) { if (auto) { COConfigurationManager.setParameter(configAutoKey, false); } COConfigurationManager.setParameter(configKey, value); COConfigurationManager.save(); } else { // autospeed COConfigurationManager.setParameter(configAutoKey, true); COConfigurationManager.save(); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/mainwindow/MainStatusBar.java0000644000175000017500000012415211307206206025145 0ustar adrianadrian/* * Created on Mar 20, 2006 6:40:14 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.mainwindow; import java.text.NumberFormat; import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerStats; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.ipfilter.IpFilter; import org.gudy.azureus2.core3.stats.transfer.OverallStats; import org.gudy.azureus2.core3.stats.transfer.StatsFactory; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.PluginManager; import org.gudy.azureus2.plugins.network.ConnectionManager; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.progress.*; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.update.UpdateWindow; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.networkmanager.NetworkManager; import com.aelitis.azureus.plugins.dht.DHTPlugin; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.UIStatusTextClickListener; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * Moved from MainWindow and GUIUpdater */ public class MainStatusBar implements UIUpdatable { /** * Warning status icon identifier */ private static final String STATUS_ICON_WARN = "sb_warning"; private static final String ID = "MainStatusBar"; private AEMonitor this_mon = new AEMonitor(ID); private UpdateWindow updateWindow; private Composite statusBar; private CLabel statusText; private String statusTextKey = ""; private String statusImageKey = null; private Image statusImage = null; private AZProgressBar progressBar; private CLabel ipBlocked; private CLabel srStatus; private CLabel natStatus; private CLabel dhtStatus; private CLabel statusDown; private CLabel statusUp; private Composite plugin_label_composite; private ArrayList listRunAfterInit = new ArrayList(); private Display display; // For Refresh.. private long last_sr_ratio = -1; private int last_sr_status = -1; private int lastNATstatus = -1; private String lastNATimageID = null; private int lastDHTstatus = -1; private long lastDHTcount = -1; private NumberFormat numberFormat; private OverallStats overall_stats; private ConnectionManager connection_manager; private DHTPlugin dhtPlugin; private UIFunctions uiFunctions; private UIStatusTextClickListener clickListener; // final int borderFlag = (Constants.isOSX) ? SWT.SHADOW_NONE : SWT.SHADOW_IN; private static final int borderFlag = SWT.SHADOW_NONE; /** * Just a flag to differentiate az3 from other versions; default status bar text is handled differently between versions. * Specifically speaking the Vuze UI status text is just empty whereas the Classic UI status text has an icon * and the application version number. */ private boolean isAZ3 = false; /** * Just a reference to the static ProgressReportingManager to make the code look cleaner instead of * using ProgressReportingManager.getInstance().xxx() everywhere. */ private ProgressReportingManager PRManager = ProgressReportingManager.getInstance(); /** * A GridData for the progress bar; used to dynamically provide .widthHint to the layout manager */ private GridData progressGridData = new GridData(SWT.RIGHT, SWT.CENTER, false, false); /** * A clickable image label that brings up the Progress viewer */ private CLabelPadding progressViewerImageLabel; private String lastProgressImageID = null; private boolean updateProgressBarDisplayQueued = false; protected IProgressReport latestReport = null; protected AEMonitor latestReport_mon = new AEMonitor("latestReport"); private String lastSRimageID = null; private int last_dl_limit; private long last_rec_data = - 1; private long last_rec_prot; /** * */ public MainStatusBar() { numberFormat = NumberFormat.getInstance(); // Proably need to wait for core to be running to make sure dht plugin is fully avail AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { PluginManager pm = core.getPluginManager(); connection_manager = PluginInitializer.getDefaultInterface().getConnectionManager(); PluginInterface dht_pi = pm.getPluginInterfaceByClass(DHTPlugin.class); if (dht_pi != null) { dhtPlugin = (DHTPlugin) dht_pi.getPlugin(); } } }); } /** * * @return composite holding the statusbar */ public Composite initStatusBar(final Composite parent) { this.display = parent.getDisplay(); this.uiFunctions = UIFunctionsManager.getUIFunctions(); ImageLoader imageLoader = ImageLoader.getInstance(); FormData formData; Color fgColor = parent.getForeground(); statusBar = new Composite(parent, SWT.NONE); statusBar.setForeground(fgColor); isAZ3 = "az3".equalsIgnoreCase(COConfigurationManager.getStringParameter("ui")); GridLayout layout_status = new GridLayout(); layout_status.numColumns = 20; layout_status.horizontalSpacing = 0; layout_status.verticalSpacing = 0; layout_status.marginHeight = 0; if (Constants.isOSX) { // OSX has a resize widget on the bottom right. It's about 15px wide. try { layout_status.marginRight = 15; } catch (NoSuchFieldError e) { // Pre SWT 3.1 layout_status.marginWidth = 15; } } else { layout_status.marginWidth = 0; } statusBar.setLayout(layout_status); //Either the Status Text statusText = new CLabel(statusBar, borderFlag); statusText.setForeground(fgColor); statusText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL)); addStatusBarMenu(statusText); GC gc = new GC(statusText); // add 6, because CLabel forces a 3 pixel indent int height = Math.max(16, gc.getFontMetrics().getHeight()) + 6; gc.dispose(); formData = new FormData(); formData.height = height; formData.bottom = new FormAttachment(100, 0); // 2 params for Pre SWT 3.0 formData.left = new FormAttachment(0, 0); // 2 params for Pre SWT 3.0 formData.right = new FormAttachment(100, 0); // 2 params for Pre SWT 3.0 statusBar.setLayoutData(formData); Listener listener = new Listener() { public void handleEvent(Event e) { if (clickListener == null) { if (updateWindow != null) { updateWindow.show(); } } else { clickListener.UIStatusTextClicked(); } } }; statusText.addListener(SWT.MouseUp, listener); statusText.addListener(SWT.MouseDoubleClick, listener); // final int progressFlag = (Constants.isOSX) ? SWT.INDETERMINATE : SWT.HORIZONTAL; // KN: Don't know why OSX is treated differently but this check was already here from the previous code if (true == Constants.isOSX) { progressBar = new AZProgressBar(statusBar, true); } else { progressBar = new AZProgressBar(statusBar, false); } progressBar.setVisible(false); progressGridData = new GridData(SWT.CENTER, SWT.CENTER, false, false); progressGridData.widthHint = 5; progressBar.setLayoutData(progressGridData); if ( isAZ3 ){ try{ addFeedBack(); }catch( Throwable e ){ Debug.printStackTrace(e); } } /* * Progress reporting window image label */ progressViewerImageLabel = new CLabelPadding(statusBar, SWT.NONE); // image set below after adding listener progressViewerImageLabel.setToolTipText(MessageText.getString("Progress.reporting.statusbar.button.tooltip")); progressViewerImageLabel.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { /* * Opens the progress viewer if any of the reporters in the array is NOT already opened * KN: TODO -- This is only a partial solution to minimize the occurrence of the main progress window * opening more than once. The one remaining case where multiple windows will still open is * when you have one opened already... then run another process such as a torrent file download... * at this point this new process is not in the already opened window so the check would * allow the second window to open. */ IProgressReporter[] reporters = PRManager.getReportersArray(false); if (reporters.length == 0) { /* * If there's nothing to see then open the window; the default widow will say there's nothing to see * KN: calling isShowingEmpty return true is there is already a window opened showing the empty panel */ if (false == ProgressReporterWindow.isShowingEmpty()) { ProgressReporterWindow.open(reporters, ProgressReporterWindow.SHOW_TOOLBAR); } } else { for (int i = 0; i < reporters.length; i++) { if (false == ProgressReporterWindow.isOpened(reporters[i])) { ProgressReporterWindow.open(reporters, ProgressReporterWindow.SHOW_TOOLBAR); break; } } } } }); progressViewerImageLabel.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage("progress_error"); imageLoader.releaseImage("progress_info"); imageLoader.releaseImage("progress_viewer"); } }); this.plugin_label_composite = new Composite(statusBar, SWT.NONE); this.plugin_label_composite.setForeground(fgColor); GridLayout gridLayout = new GridLayout(); gridLayout.horizontalSpacing = 0; gridLayout.verticalSpacing = 0; gridLayout.marginHeight = 0; gridLayout.marginBottom = 0; gridLayout.marginTop = 0; gridLayout.marginLeft = 0; gridLayout.marginRight = 0; gridLayout.numColumns = 20; // Something nice and big. :) GridData gridData = new GridData(GridData.FILL_VERTICAL); gridData.heightHint = height; gridData.minimumHeight = height; plugin_label_composite.setLayout(gridLayout); plugin_label_composite.setLayoutData(gridData); srStatus = new CLabelPadding(statusBar, borderFlag); srStatus.setText(MessageText.getString("SpeedView.stats.ratio")); COConfigurationManager.addAndFireParameterListener("Status Area Show SR", new ParameterListener() { public void parameterChanged(String parameterName) { srStatus.setVisible(COConfigurationManager.getBooleanParameter(parameterName)); statusBar.layout(); } }); natStatus = new CLabelPadding(statusBar, borderFlag); natStatus.setText(""); COConfigurationManager.addAndFireParameterListener("Status Area Show NAT", new ParameterListener() { public void parameterChanged(String parameterName) { natStatus.setVisible(COConfigurationManager.getBooleanParameter(parameterName)); statusBar.layout(); } }); dhtStatus = new CLabelPadding(statusBar, borderFlag); dhtStatus.setText(""); dhtStatus.setToolTipText(MessageText.getString("MainWindow.dht.status.tooltip")); COConfigurationManager.addAndFireParameterListener("Status Area Show DDB", new ParameterListener() { public void parameterChanged(String parameterName) { dhtStatus.setVisible(COConfigurationManager.getBooleanParameter(parameterName)); statusBar.layout(); } }); ipBlocked = new CLabelPadding(statusBar, borderFlag); ipBlocked.setText("{} IPs:"); //$NON-NLS-1$ Messages.setLanguageText(ipBlocked, "MainWindow.IPs.tooltip"); ipBlocked.addListener(SWT.MouseDoubleClick, new ListenerNeedingCoreRunning() { public void handleEvent(AzureusCore core, Event event) { BlockedIpsWindow.showBlockedIps(core, parent.getShell()); } }); COConfigurationManager.addAndFireParameterListener("Status Area Show IPF", new ParameterListener() { public void parameterChanged(String parameterName) { ipBlocked.setVisible(COConfigurationManager.getBooleanParameter(parameterName)); statusBar.layout(); } }); statusDown = new CLabelPadding(statusBar, borderFlag); statusDown.setImage(imageLoader.getImage("down")); //statusDown.setText(/*MessageText.getString("ConfigView.download.abbreviated") +*/"n/a"); Messages.setLanguageText(statusDown, "MainWindow.status.updowndetails.tooltip"); Listener lStats = new Listener() { public void handleEvent(Event e) { uiFunctions.openView(UIFunctions.VIEW_STATS, null); } }; statusUp = new CLabelPadding(statusBar, borderFlag); statusUp.setImage(imageLoader.getImage("up")); //statusUp.setText(/*MessageText.getString("ConfigView.upload.abbreviated") +*/"n/a"); Messages.setLanguageText(statusUp, "MainWindow.status.updowndetails.tooltip"); statusDown.addListener(SWT.MouseDoubleClick, lStats); statusUp.addListener(SWT.MouseDoubleClick, lStats); Listener lDHT = new Listener() { public void handleEvent(Event e) { uiFunctions.openView(UIFunctions.VIEW_STATS, "dht"); } }; dhtStatus.addListener(SWT.MouseDoubleClick, lDHT); Listener lSR = new Listener() { public void handleEvent(Event e) { uiFunctions.openView(UIFunctions.VIEW_STATS, "transfers"); OverallStats stats = StatsFactory.getStats(); if (stats == null) { return; } long ratio = (1000 * stats.getUploadedBytes() / (stats.getDownloadedBytes() + 1)); if (ratio < 900) { Utils.launch(Constants.AZUREUS_WIKI + "Share_Ratio"); } } }; srStatus.addListener(SWT.MouseDoubleClick, lSR); Listener lNAT = new ListenerNeedingCoreRunning() { public void handleEvent(AzureusCore core, Event e) { uiFunctions.openView(UIFunctions.VIEW_CONFIG, ConfigSection.SECTION_CONNECTION); if (PluginInitializer.getDefaultInterface().getConnectionManager().getNATStatus() != ConnectionManager.NAT_OK) { Utils.launch(Constants.AZUREUS_WIKI + "NAT_problem"); } } }; natStatus.addListener(SWT.MouseDoubleClick, lNAT); boolean bSpeedMenu = COConfigurationManager.getBooleanParameter("GUI_SWT_bOldSpeedMenu"); if (bSpeedMenu) { // Status Bar Menu construction final Menu menuUpSpeed = new Menu(statusBar.getShell(), SWT.POP_UP); menuUpSpeed.addListener(SWT.Show, new Listener() { public void handleEvent(Event e) { if (!AzureusCoreFactory.isCoreRunning()) { return; } AzureusCore core = AzureusCoreFactory.getSingleton(); GlobalManager globalManager = core.getGlobalManager(); SelectableSpeedMenu.generateMenuItems(menuUpSpeed, core, globalManager, true); } }); statusUp.setMenu(menuUpSpeed); } else { statusUp.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { if (!(e.button == 3 || (e.button == 1 && e.stateMask == SWT.CONTROL))) { return; } Event event = new Event(); event.type = SWT.MouseUp; event.widget = e.widget; event.stateMask = e.stateMask; event.button = e.button; e.widget.getDisplay().post(event); CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { SelectableSpeedMenu.invokeSlider(core, true); } }); } }); } if (bSpeedMenu) { final Menu menuDownSpeed = new Menu(statusBar.getShell(), SWT.POP_UP); menuDownSpeed.addListener(SWT.Show, new Listener() { public void handleEvent(Event e) { if (!AzureusCoreFactory.isCoreRunning()) { return; } AzureusCore core = AzureusCoreFactory.getSingleton(); GlobalManager globalManager = core.getGlobalManager(); SelectableSpeedMenu.generateMenuItems(menuDownSpeed, core, globalManager, false); } }); statusDown.setMenu(menuDownSpeed); } else { statusDown.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { if (!(e.button == 3 || (e.button == 1 && e.stateMask == SWT.CONTROL))) { return; } Event event = new Event(); event.type = SWT.MouseUp; event.widget = e.widget; event.stateMask = e.stateMask; event.button = e.button; e.widget.getDisplay().post(event); CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { SelectableSpeedMenu.invokeSlider(core, false); } }); } }); } PRManager.addListener(new ProgressListener()); setProgressImage(); uiFunctions.getUIUpdater().addUpdater(this); ArrayList list; this_mon.enter(); try { list = listRunAfterInit; listRunAfterInit = null; } finally { this_mon.exit(); } for (Runnable runnable : list) { try { runnable.run(); } catch (Exception e) { Debug.out(e); } } statusBar.layout(true); return statusBar; } private void addFeedBack() { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { Utils.execSWTThread(new AERunnable() { public void runSupport() { _addFeedBack(); } }); } }); } private void _addFeedBack() { /* * Feedback * */ // only show after restart after 15 mins uptime OverallStats stats = StatsFactory.getStats(); long secs_uptime = stats.getTotalUpTime(); long last_uptime = COConfigurationManager.getLongParameter( "statusbar.feedback.uptime", 0); if (last_uptime == 0) { COConfigurationManager.setParameter("statusbar.feedback.uptime", secs_uptime); } else if (secs_uptime - last_uptime > 15 * 60) { createStatusEntry(new CLabelUpdater() { public void update(CLabel label) { } public void created(CLabel feedback) { feedback.setText(MessageText.getString("statusbar.feedback")); Listener feedback_listener = new Listener() { public void handleEvent(Event e) { String url = "feedback.start?" + Utils.getWidgetBGColorURLParam() + "&fromWeb=false&os.name=" + UrlUtils.encode(Constants.OSName) + "&os.version=" + UrlUtils.encode(System.getProperty("os.version")) + "&java.version=" + UrlUtils.encode(Constants.JAVA_VERSION); // Utils.launch( url ); UIFunctionsManagerSWT.getUIFunctionsSWT().viewURL(url, null, 600, 520, true, false); } }; feedback.setToolTipText(MessageText.getString("statusbar.feedback.tooltip")); feedback.setCursor(Cursors.handCursor); feedback.setForeground(Colors.blue); feedback.addListener(SWT.MouseUp, feedback_listener); feedback.addListener(SWT.MouseDoubleClick, feedback_listener); feedback.setVisible(true); } }); } } /** * @param statusBar2 * * @since 4.0.0.1 */ private void addStatusBarMenu(Composite cSB) { if (!Constants.isCVSVersion()) { return; } Menu menu = new Menu(cSB); cSB.setMenu(menu); MenuItem itemShow = new MenuItem(menu, SWT.CASCADE); itemShow.setText("Show"); Menu menuShow = new Menu(itemShow); itemShow.setMenu(menuShow); final String[] statusAreaLangs = { "ConfigView.section.style.status.show_sr", "ConfigView.section.style.status.show_nat", "ConfigView.section.style.status.show_ddb", "ConfigView.section.style.status.show_ipf", }; final String[] statusAreaConfig = { "Status Area Show SR", "Status Area Show NAT", "Status Area Show DDB", "Status Area Show IPF", }; for (int i = 0; i < statusAreaConfig.length; i++) { final String configID = statusAreaConfig[i]; String langID = statusAreaLangs[i]; final MenuItem item = new MenuItem(menuShow, SWT.CHECK); Messages.setLanguageText(item, langID); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { COConfigurationManager.setParameter(configID, !COConfigurationManager.getBooleanParameter(configID)); } }); menuShow.addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { item.setSelection(COConfigurationManager.getBooleanParameter(configID)); } }); } } /** * * @param keyedSentence */ public void setStatusText(String keyedSentence) { this.statusTextKey = keyedSentence == null ? "" : keyedSentence; setStatusImageKey(null); this.clickListener = null; if (statusTextKey.length() == 0) { // reset resetStatus(); } updateStatusText(); } private void setStatusImageKey(String newStatusImageKey) { if (("" + statusImageKey).equals("" + newStatusImageKey)) { return; } ImageLoader imageLoader = ImageLoader.getInstance(); if (statusImageKey != null) { imageLoader.releaseImage(statusImageKey); } statusImageKey = newStatusImageKey; if (statusImageKey != null) { statusImage = imageLoader.getImage(statusImageKey); } else { statusImage = null; } } private void resetStatus() { if (Constants.isCVSVersion()) { statusTextKey = "MainWindow.status.unofficialversion (" + Constants.AZUREUS_VERSION + ")"; setStatusImageKey(STATUS_ICON_WARN); } else if (!Constants.isOSX) { //don't show official version numbers for OSX L&F statusTextKey = Constants.APP_NAME + " " + Constants.AZUREUS_VERSION; setStatusImageKey(null); } } /** * @param statustype * @param string * @param l */ public void setStatusText(int statustype, String string, UIStatusTextClickListener l) { this.statusTextKey = string == null ? "" : string; if (statusTextKey.length() == 0) { // reset resetStatus(); } this.clickListener = l; if (statustype == UIFunctions.STATUSICON_WARNING) { setStatusImageKey(STATUS_ICON_WARN); } if (statustype == UIFunctions.STATUSICON_WARNING) { setStatusImageKey(STATUS_ICON_WARN); } else { setStatusImageKey(null); } updateStatusText(); } /** * * */ public void updateStatusText() { if (display == null || display.isDisposed()) return; final String text; if (updateWindow != null) { text = "MainWindow.updateavail"; } else { text = this.statusTextKey; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (statusText != null && !statusText.isDisposed()) { statusText.setText(MessageText.getStringForSentence(text)); statusText.setImage(statusImage); } } }); } /** * * */ public void refreshStatusText() { if (statusText != null && !statusText.isDisposed()) statusText.update(); } /** * * @param updateWindow */ public void setUpdateNeeded(UpdateWindow updateWindow) { this.updateWindow = updateWindow; if (updateWindow != null) { statusText.setCursor(Cursors.handCursor); statusText.setForeground(Colors.colorWarning); updateStatusText(); } else { statusText.setCursor(null); statusText.setForeground(null); updateStatusText(); } } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI() public void updateUI() { if (statusBar.isDisposed()) { uiFunctions.getUIUpdater().removeUpdater(this); return; } // Plugins. Control[] plugin_elements = this.plugin_label_composite.getChildren(); for (int i = 0; i < plugin_elements.length; i++) { if (plugin_elements[i] instanceof UpdateableCLabel) { ((UpdateableCLabel) plugin_elements[i]).checkForRefresh(); } } if (ipBlocked.isVisible()) { updateIPBlocked(); } if (srStatus.isVisible()) { updateShareRatioStatus(); } if (natStatus.isVisible()) { updateNatStatus(); } if (dhtStatus.isVisible()) { updateDHTStatus(); } // UL/DL Status Sections if (AzureusCoreFactory.isCoreRunning()) { AzureusCore core = AzureusCoreFactory.getSingleton(); GlobalManager gm = core.getGlobalManager(); GlobalManagerStats stats = gm.getStats(); int dl_limit = NetworkManager.getMaxDownloadRateBPS() / 1024; long rec_data = stats.getDataReceiveRate(); long rec_prot = stats.getProtocolReceiveRate(); if (last_dl_limit != dl_limit || last_rec_data != rec_data || last_rec_prot != rec_prot) { last_dl_limit = dl_limit; last_rec_data = rec_data; last_rec_prot = rec_prot; statusDown.setText((dl_limit == 0 ? "" : "[" + dl_limit + "K] ") + DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec(rec_data, rec_prot)); } boolean auto_up = TransferSpeedValidator.isAutoSpeedActive(gm) && TransferSpeedValidator.isAutoUploadAvailable(core); int ul_limit_norm = NetworkManager.getMaxUploadRateBPSNormal() / 1024; String seeding_only; if (NetworkManager.isSeedingOnlyUploadRate()) { int ul_limit_seed = NetworkManager.getMaxUploadRateBPSSeedingOnly() / 1024; if (ul_limit_seed == 0) { seeding_only = "+" + Constants.INFINITY_STRING + "K"; } else { int diff = ul_limit_seed - ul_limit_norm; seeding_only = (diff >= 0 ? "+" : "") + diff + "K"; } } else { seeding_only = ""; } statusUp.setText((ul_limit_norm == 0 ? "" : "[" + ul_limit_norm + "K" + seeding_only + "]") + (auto_up ? "* " : " ") + DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec( stats.getDataSendRate(), stats.getProtocolSendRate())); } } /** * * * @since 3.1.1.1 */ private void updateDHTStatus() { if (dhtPlugin == null) { return; } // DHT Status Section int dht_status = dhtPlugin.getStatus(); long dht_count = -1; //boolean reachable = false; if (dht_status == DHTPlugin.STATUS_RUNNING) { DHT[] dhts = dhtPlugin.getDHTs(); //reachable = dhts.length > 0 && dhts[0].getTransport().isReachable(); //if ( reachable ){ dht_count = dhts[0].getControl().getStats().getEstimatedDHTSize(); //} } if (lastDHTstatus != dht_status || lastDHTcount != dht_count) { boolean hasImage = dhtStatus.getImage() != null; boolean needImage = true; switch (dht_status) { case DHTPlugin.STATUS_RUNNING: dhtStatus.setToolTipText(MessageText.getString("MainWindow.dht.status.tooltip")); dhtStatus.setText(MessageText.getString("MainWindow.dht.status.users").replaceAll( "%1", numberFormat.format(dht_count))); /* if ( reachable ){ dhtStatus.setImage(ImageRepository.getImage("greenled")); dhtStatus.setToolTipText(MessageText .getString("MainWindow.dht.status.tooltip")); dhtStatus.setText(MessageText.getString("MainWindow.dht.status.users").replaceAll("%1", numberFormat.format(dht_count))); } else { dhtStatus.setImage(ImageRepository.getImage("yellowled")); dhtStatus.setToolTipText(MessageText .getString("MainWindow.dht.status.unreachabletooltip")); dhtStatus.setText(MessageText .getString("MainWindow.dht.status.unreachable")); } */ break; case DHTPlugin.STATUS_DISABLED: //dhtStatus.setImage(ImageRepository.getImage("grayled")); dhtStatus.setText(MessageText.getString("MainWindow.dht.status.disabled")); break; case DHTPlugin.STATUS_INITALISING: //dhtStatus.setImage(ImageRepository.getImage("yellowled")); dhtStatus.setText(MessageText.getString("MainWindow.dht.status.initializing")); break; case DHTPlugin.STATUS_FAILED: //dhtStatus.setImage(ImageRepository.getImage("redled")); dhtStatus.setText(MessageText.getString("MainWindow.dht.status.failed")); break; default: needImage = false; break; } if (hasImage != needImage) { ImageLoader imageLoader = ImageLoader.getInstance(); if (needImage) { Image img = imageLoader.getImage("sb_count"); dhtStatus.setImage(img); } else { imageLoader.releaseImage("sb_count"); dhtStatus.setImage(null); } } lastDHTstatus = dht_status; lastDHTcount = dht_count; } } /** * * * @since 3.1.1.1 */ private void updateNatStatus() { // NAT status Section if (connection_manager == null) { return; } int nat_status = connection_manager.getNATStatus(); if (lastNATstatus != nat_status) { String imgID; String tooltipID; String statusID; switch (nat_status) { case ConnectionManager.NAT_UNKNOWN: imgID = "grayled"; tooltipID = "MainWindow.nat.status.tooltip.unknown"; statusID = "MainWindow.nat.status.unknown"; break; case ConnectionManager.NAT_OK: imgID = "greenled"; tooltipID = "MainWindow.nat.status.tooltip.ok"; statusID = "MainWindow.nat.status.ok"; break; case ConnectionManager.NAT_PROBABLY_OK: imgID = "yellowled"; tooltipID = "MainWindow.nat.status.tooltip.probok"; statusID = "MainWindow.nat.status.probok"; break; default: imgID = "redled"; tooltipID = "MainWindow.nat.status.tooltip.bad"; statusID = "MainWindow.nat.status.bad"; break; } if (!imgID.equals(lastNATimageID)) { ImageLoader imageLoader = ImageLoader.getInstance(); natStatus.setImage(imageLoader.getImage(imgID)); if (lastNATimageID != null) { imageLoader.releaseImage(lastNATimageID); } lastNATimageID = imgID; } natStatus.setToolTipText(MessageText.getString(tooltipID)); natStatus.setText(MessageText.getString(statusID)); lastNATstatus = nat_status; } } /** * * * @since 3.1.1.1 */ private void updateShareRatioStatus() { // SR status section if (overall_stats == null) { overall_stats = StatsFactory.getStats(); if (overall_stats == null) { return; } } long ratio = (1000 * overall_stats.getUploadedBytes() / (overall_stats.getDownloadedBytes() + 1)); int sr_status; if (ratio < 500) { sr_status = 0; } else if (ratio < 900) { sr_status = 1; } else { sr_status = 2; } if (sr_status != last_sr_status) { String imgID; switch (sr_status) { case 2: imgID = "greenled"; break; case 1: imgID = "yellowled"; break; default: imgID = "redled"; break; } if (!imgID.equals(lastSRimageID)) { ImageLoader imageLoader = ImageLoader.getInstance(); srStatus.setImage(imageLoader.getImage(imgID)); if (lastSRimageID != null) { imageLoader.releaseImage(lastSRimageID); } lastSRimageID = imgID; } last_sr_status = sr_status; } if (ratio != last_sr_ratio) { String tooltipID; switch (sr_status) { case 2: tooltipID = "MainWindow.sr.status.tooltip.ok"; break; case 1: tooltipID = "MainWindow.sr.status.tooltip.poor"; break; default: tooltipID = "MainWindow.sr.status.tooltip.bad"; break; } String ratio_str = ""; String partial = "" + ratio % 1000; while (partial.length() < 3) { partial = "0" + partial; } ratio_str = (ratio / 1000) + "." + partial; srStatus.setToolTipText(MessageText.getString(tooltipID, new String[] { ratio_str })); last_sr_ratio = ratio; } } /** * * * @since 3.1.1.1 */ private void updateIPBlocked() { if (!AzureusCoreFactory.isCoreRunning()) { return; } AzureusCore azureusCore = AzureusCoreFactory.getSingleton(); // IP Filter Status Section IpFilter ip_filter = azureusCore.getIpFilterManager().getIPFilter(); ipBlocked.setText("IPs: " + numberFormat.format(ip_filter.getNbRanges()) + " - " + numberFormat.format(ip_filter.getNbIpsBlockedAndLoggable()) + "/" + numberFormat.format(ip_filter.getNbBannedIps()) + "/" + numberFormat.format(azureusCore.getIpFilterManager().getBadIps().getNbBadIps())); ipBlocked.setToolTipText(MessageText.getString("MainWindow.IPs.tooltip", new String[] { DisplayFormatters.formatDateShort(ip_filter.getLastUpdateTime()) })); } /** * @param string */ public void setDebugInfo(String string) { if (statusText != null && !statusText.isDisposed()) statusText.setToolTipText(string); } public boolean isMouseOver() { if (statusText == null || statusText.isDisposed()) { return false; } return statusText.getDisplay().getCursorControl() == statusText; } public static interface CLabelUpdater { public void created(CLabel label); public void update(CLabel label); } /** * CLabel that shrinks to fit text after a specific period of time. * Makes textual changes less jumpy * * @author TuxPaper * @created Mar 21, 2006 * */ private class CLabelPadding extends CLabel { private int lastWidth = 0; private long widthSetOn = 0; private static final int KEEPWIDTHFOR_MS = 30 * 1000; /** * Default Constructor * * @param parent * @param style */ public CLabelPadding(Composite parent, int style) { super(parent, style | SWT.CENTER); GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.VERTICAL_ALIGN_FILL); setLayoutData(gridData); setForeground(parent.getForeground()); } public void setText(String text) { if (text == null) { text = ""; } if (text.equals(getText())) { return; } super.setText(text); int oldWidth = lastWidth; Point pt = super.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); pt.x += 4; if (pt.x > oldWidth && text.length() > 0) { statusBar.layout(); } else if (pt.x < oldWidth) { Utils.execSWTThreadLater(KEEPWIDTHFOR_MS, new AERunnable() { public void runSupport() { statusBar.layout(); } }); } } /* (non-Javadoc) * @see org.eclipse.swt.custom.CLabel#computeSize(int, int, boolean) */ public Point computeSize(int wHint, int hHint, boolean changed) { if (!isVisible()) { return (new Point(0, 0)); } try { Point pt = super.computeSize(wHint, hHint, changed); pt.x += 4; long now = System.currentTimeMillis(); if (lastWidth > pt.x && now - widthSetOn < KEEPWIDTHFOR_MS) { pt.x = lastWidth; } else { if (lastWidth != pt.x) lastWidth = pt.x; widthSetOn = now; } return pt; } catch (Throwable t) { Debug.out("Error while computing size for CLabel with text:" + getText()); return new Point(0, 0); } } } private class UpdateableCLabel extends CLabelPadding { private CLabelUpdater updater; public UpdateableCLabel(Composite parent, int style, CLabelUpdater updater) { super(parent, style); this.updater = updater; } private void checkForRefresh() { updater.update(this); } } public void createStatusEntry(final CLabelUpdater updater) { AERunnable r = new AERunnable() { public void runSupport() { UpdateableCLabel result = new UpdateableCLabel(plugin_label_composite, borderFlag, updater); result.setLayoutData(new GridData(GridData.FILL_BOTH)); updater.created(result); } }; this_mon.enter(); try { if (listRunAfterInit != null) { listRunAfterInit.add(r); return; } } finally { this_mon.exit(); } Utils.execSWTThread(r); } // ============================================================= // Below code are ProgressBar/Status text specific // ============================================================= /** * Show or hide the Progress Bar * @param state */ private void showProgressBar(boolean state) { /* * We show/hide the progress bar simply by setting the .widthHint and letting the statusBar handle the layout */ if (true == state && false == progressBar.isVisible()) { progressGridData.widthHint = 100; progressBar.setVisible(true); statusBar.layout(); } else if (false == state && true == progressBar.isVisible()) { progressBar.setVisible(false); progressGridData.widthHint = 0; statusBar.layout(); } } /** * Updates the display of the ProgressBar and/or the status text * @param pReport the ProgressReport containing the information * to display; can be null in which case the status text and progress bar will be reset to default states */ private void updateProgressBarDisplay(IProgressReport pReport) { latestReport_mon.enter(); try { latestReport = pReport; } finally { latestReport_mon.exit(); } if (null == progressBar || progressBar.isDisposed() || updateProgressBarDisplayQueued) { return; } updateProgressBarDisplayQueued = true; Utils.execSWTThread(new AERunnable() { public void runSupport() { latestReport_mon.enter(); try { updateProgressBarDisplayQueued = false; if ((null == progressBar || true == progressBar.isDisposed())) { return; } if (null != latestReport) { /* * Pass the values through to the progressbar */ progressBar.setMinimum(latestReport.getMinimum()); progressBar.setMaximum(latestReport.getMaximum()); progressBar.setIndeterminate(latestReport.isIndeterminate()); progressBar.setPercentage(latestReport.getPercentage()); showProgressBar(true); /* * Update status text */ if (true == isAZ3) { statusText.setText(latestReport.getName()); } else { setStatusText(latestReport.getName()); } } else { /* * Since the pReport is null then reset progress display appropriately */ showProgressBar(false); if (true == isAZ3) { statusText.setText(""); } else { setStatusText(null); } } } finally { latestReport_mon.exit(); } } }, true); } private void setProgressImage() { String imageID; if (PRManager.getReporterCount(ProgressReportingManager.COUNT_ERROR) > 0) { imageID = "progress_error"; } else if (PRManager.getReporterCount(ProgressReportingManager.COUNT_ALL) > 0) { imageID = "progress_info"; } else { imageID = "progress_viewer"; } if (!imageID.equals(lastProgressImageID)) { final String fImageID = imageID; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (progressViewerImageLabel.isDisposed()) { return; } ImageLoader imageLoader = ImageLoader.getInstance(); progressViewerImageLabel.setImage(imageLoader.getImage(fImageID)); if (lastProgressImageID != null) { imageLoader.releaseImage(lastProgressImageID); } lastProgressImageID = fImageID; } }); } } /** * A listener that listens to any changes notified from the ProgressReportingManager and * accordingly update the progress bar and/or the status text area. * @author knguyen * */ private class ProgressListener implements IProgressReportingListener, IProgressReportConstants { public int reporting(int eventType, IProgressReporter reporter) { /* * Show the appropriate image based on the content of the reporting manager */ setProgressImage(); if (null == reporter) { return RETVAL_OK; } if (MANAGER_EVENT_REMOVED == eventType) { updateFromPrevious(); } else if (MANAGER_EVENT_ADDED == eventType || MANAGER_EVENT_UPDATED == eventType) { /* * Get a ProgressReport to ensure all data is consistent */ IProgressReport pReport = reporter.getProgressReport(); /* * Pops up the ProgressReportingWindow to show this report if it is an error report; * this is to help catch the users attention */ if (true == pReport.isInErrorState()) { if(true == "reporterType_updater".equals(pReport.getReporterType())){ /* * Suppressing the pop-up for update-related errors */ return RETVAL_OK; } final IProgressReporter final_reporter = reporter; /* * The new window is opened only if there is not one already showing the same reporter */ if (false == ProgressReporterWindow.isOpened(final_reporter)) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if ( !ProgressReporterWindow.isOpened(final_reporter)){ ProgressReporterWindow.open(final_reporter, ProgressReporterWindow.NONE); } } }, true); } } /* * If this reporter is not active then get the previous reporter that is still active and display info from that */ if (false == pReport.isActive()) { updateFromPrevious(); } else { update(pReport); } } return RETVAL_OK; } private void update(final IProgressReport pReport) { if (null == pReport) { updateProgressBarDisplay(null); return; } /* * If there is at least 2 reporters still active then show the progress bar as indeterminate * and display the text from the current reporter */ if (true == PRManager.hasMultipleActive()) { Utils.execSWTThread(new AERunnable() { public void runSupport() { setStatusText(pReport.getName()); progressBar.setIndeterminate(true); showProgressBar(true); } }, true); } else { updateProgressBarDisplay(pReport); } } private void updateFromPrevious() { /* * Get the previous reporter that is still active */ IProgressReporter previousReporter = PRManager.getNextActiveReporter(); /* * If null then we reset the status text and the progress bar */ if (null != previousReporter) { update(previousReporter.getProgressReport()); } else { update(null); } } } public Rectangle getBounds() { if (null != statusBar) { return statusBar.getBounds(); } return null; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { return ID; } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/sharing/0000755000175000017500000000000011310377636021051 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/sharing/ShareUtils.java0000644000175000017500000001113411171750564023777 0ustar adrianadrian/* * File : ShareUtils.java * Created : 08-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.sharing; /** * @author parg * */ import java.io.File; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; import com.aelitis.azureus.core.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; public class ShareUtils { public static void shareFile( final Shell shell ) { new AEThread("shareFile") { public void runSupport() { Display display = shell.getDisplay(); final String[] path = { null }; final AESemaphore sem = new AESemaphore("ShareUtils:file"); display.asyncExec(new AERunnable() { public void runSupport() { try{ FileDialog dialog = new FileDialog(shell, SWT.SYSTEM_MODAL | SWT.OPEN); dialog.setFilterPath( TorrentOpener.getFilterPathData() ); dialog.setText(MessageText.getString("MainWindow.dialog.share.sharefile")); path[0] = TorrentOpener.setFilterPathData( dialog.open() ); }finally{ sem.release(); } } }); sem.reserve(); if ( path[0] != null ){ shareFile( path[0] ); } } }.start(); } public static void shareDir( Shell shell ) { shareDirSupport( shell, false, false ); } public static void shareDirContents( Shell shell, boolean recursive ) { shareDirSupport( shell, true, recursive ); } protected static void shareDirSupport( final Shell shell, final boolean contents, final boolean recursive ) { new AEThread("shareDirSupport") { public void runSupport() { Display display = shell.getDisplay(); final String[] path = { null }; final AESemaphore sem = new AESemaphore("ShareUtils:dir"); display.asyncExec(new AERunnable() { public void runSupport() { try{ DirectoryDialog dialog = new DirectoryDialog(shell, SWT.SYSTEM_MODAL); dialog.setFilterPath( TorrentOpener.getFilterPathData() ); dialog.setText( contents? MessageText.getString("MainWindow.dialog.share.sharedircontents") + (recursive?"("+MessageText.getString("MainWindow.dialog.share.sharedircontents.recursive")+")":""): MessageText.getString("MainWindow.dialog.share.sharedir")); path[0] = TorrentOpener.setFilterPathData( dialog.open() ); }finally{ sem.release(); } } }); sem.reserve(); if ( path[0] != null ){ if ( contents ){ shareDirContents( path[0], recursive ); }else{ shareDir( path[0] ); } } } }.start(); } public static void shareFile( final String file_name ) { new AEThread("shareFile") { public void runSupport() { try{ PluginInitializer.getDefaultInterface().getShareManager().addFile(new File(file_name)); }catch( Throwable e ){ Debug.printStackTrace( e ); } } }.start(); } public static void shareDir( final String file_name ) { new AEThread("shareDir") { public void runSupport() { try{ PluginInitializer.getDefaultInterface().getShareManager().addDir(new File(file_name)); }catch( Throwable e ){ Debug.printStackTrace( e ); } } }.start(); } public static void shareDirContents( final String file_name, final boolean recursive ) { new AEThread("shareDirCntents") { public void runSupport() { try{ PluginInitializer.getDefaultInterface().getShareManager().addDirContents(new File(file_name), recursive); }catch( Throwable e ){ Debug.printStackTrace( e ); } } }.start(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/sharing/progress/0000755000175000017500000000000011310377636022715 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/sharing/progress/ProgressWindow.java0000644000175000017500000002124411275142106026547 0ustar adrianadrian/* * File : ProgressWindow.java * Created : 15-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.sharing.progress; /** * @author parg * */ import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.animations.Animator; import org.gudy.azureus2.ui.swt.animations.shell.AnimableShell; import org.gudy.azureus2.ui.swt.animations.shell.LinearAnimator; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import org.gudy.azureus2.ui.swt.shells.PopupShell; import org.gudy.azureus2.plugins.sharing.ShareException; import org.gudy.azureus2.plugins.sharing.ShareManager; import org.gudy.azureus2.plugins.sharing.ShareManagerListener; import org.gudy.azureus2.plugins.sharing.ShareResource; public class ProgressWindow implements ShareManagerListener { private ShareManager share_manager; private progressDialog dialog = null; private Display display; private StyledText tasks; private ProgressBar progress; private Button cancel_button; private boolean shell_opened; private boolean manually_hidden; public ProgressWindow() { try{ share_manager = PluginInitializer.getDefaultInterface().getShareManager(); display = SWTThread.getInstance().getDisplay(); if ( display.isDisposed()){ return; } share_manager.addListener(this); }catch( ShareException e ){ Debug.printStackTrace( e ); } } private class progressDialog extends PopupShell implements AnimableShell { protected progressDialog( Display dialog_display ) { super(dialog_display); if ( dialog_display.isDisposed()){ return; } shell.setText(MessageText.getString("sharing.progress.title")); tasks = new StyledText(shell, SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER); tasks.setBackground(dialog_display.getSystemColor(SWT.COLOR_WHITE)); progress = new ProgressBar(shell, SWT.NULL); progress.setMinimum(0); progress.setMaximum(100); Button hide_button = new Button(shell,SWT.PUSH); hide_button.setText(MessageText.getString("sharing.progress.hide")); cancel_button = new Button(shell,SWT.PUSH); cancel_button.setText(MessageText.getString("sharing.progress.cancel")); cancel_button.setEnabled( false ); //Layout : //Progress Bar on bottom, with Hide button next to it. FormData formData; formData = new FormData(); formData.right = new FormAttachment(100,-5); formData.bottom = new FormAttachment(100,-10); hide_button.setLayoutData(formData); formData = new FormData(); formData.right = new FormAttachment(hide_button,-5); formData.bottom = new FormAttachment(100,-10); cancel_button.setLayoutData(formData); formData = new FormData(); formData.right = new FormAttachment(cancel_button,-5); formData.left = new FormAttachment(0,50); formData.bottom = new FormAttachment(100,-10); progress.setLayoutData(formData); formData = new FormData(); formData.right = new FormAttachment(100,-5); formData.bottom = new FormAttachment(100,-50); formData.top = new FormAttachment(0,5); formData.left = new FormAttachment(0,5); tasks.setLayoutData(formData); layout(); cancel_button.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { cancel_button.setEnabled( false ); share_manager.cancelOperation(); } }); hide_button.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { hidePanel(); } }); shell.setDefaultButton( hide_button ); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ hidePanel(); } } }); Rectangle bounds = dialog_display.getClientArea(); x0 = bounds.x + bounds.width - 255; x1 = bounds.x + bounds.width; y0 = bounds.y + bounds.height; y1 = bounds.y + bounds.height - 155; shell.setLocation(x0,y0); } protected void hidePanel() { manually_hidden = true; currentAnimator = new LinearAnimator(this,new Point(x0,y1),new Point(x1,y1),15,30); currentAnimator.start(); hideAfter = true; } protected void showPanel() { manually_hidden = false; boolean animate = false ; if ( !shell_opened ){ shell_opened = true; shell.open(); animate = true ; } Shell otherShell = Utils.findAnyShell(); if (otherShell != null) { shell.moveAbove(otherShell); } if ( !shell.isVisible()){ shell.setVisible(true); animate = true ; } if(animate && currentAnimator == null) { currentAnimator = new LinearAnimator(this,new Point(x0,y0),new Point(x0,y1),15,30); currentAnimator.start(); } } protected boolean isShown() { return( shell.isVisible()); } //Animation properties Animator currentAnimator; int x0,y0,x1,y1; boolean isAnimated; boolean hideAfter; public void animationEnded(Animator source) { if(source != currentAnimator) return; isAnimated = false; currentAnimator = null; if(hideAfter) { hideAfter = false; if(display == null || display.isDisposed()) return; display.asyncExec(new AERunnable() { public void runSupport() { shell.setVisible(false); } }); } } public void animationStarted(Animator source) { } public Shell getShell() { return shell; } public void reportPercent(int percent) { } } public void resourceAdded( ShareResource resource ) { // we don't want to pick these additions up if ( !share_manager.isInitialising()){ reportCurrentTask( "Resource added: " + resource.getName()); } } public void resourceModified( ShareResource old_resource, ShareResource new_resource ) { reportCurrentTask( "Resource modified: " + old_resource.getName()); } public void resourceDeleted( ShareResource resource ) { reportCurrentTask( "Resource deleted: " + resource.getName()); } public void reportProgress( final int percent_complete ) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (progress != null && !progress.isDisposed()) { if (dialog == null) { dialog = new progressDialog(display); if (dialog == null) { return; } } // only allow percentage updates to make the window visible // if it hasn't been manually hidden if (!dialog.isShown() && !manually_hidden) { dialog.showPanel(); } cancel_button.setEnabled(percent_complete < 100); progress.setSelection(percent_complete); } } }); } public void reportCurrentTask( final String task_description ) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (dialog == null) { dialog = new progressDialog(display); if (dialog == null) { return; } } if (tasks != null && !tasks.isDisposed()) { dialog.showPanel(); tasks.append(task_description + Text.DELIMITER); int lines = tasks.getLineCount(); // tasks(nbLines - 2, 1, colors[_color]); tasks.setTopIndex(lines - 1); } } }); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/ipchecker/0000755000175000017500000000000011310377636021353 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/ipchecker/ProgressPanel.java0000644000175000017500000000725410124635162025003 0ustar adrianadrian/* * File : ProgressPanel.java * Created : 7 oct. 2003 13:01:42 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.ipchecker; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.ipchecker.extipchecker.ExternalIPCheckerService; import org.gudy.azureus2.core3.ipchecker.extipchecker.ExternalIPCheckerServiceListener; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.wizard.*; /** * @author Olivier * */ public class ProgressPanel extends AbstractWizardPanel implements ExternalIPCheckerServiceListener { Text tasks; Display display; public ProgressPanel(IpCheckerWizard wizard, IWizardPanel previousPanel) { super(wizard, previousPanel); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#show() */ public void show() { display = wizard.getDisplay(); wizard.setTitle(MessageText.getString("ipCheckerWizard.progresstitle")); wizard.setCurrentInfo(""); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 1; panel.setLayout(layout); tasks = new Text(panel, SWT.BORDER | SWT.MULTI | SWT.READ_ONLY); tasks.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 120; tasks.setLayoutData(gridData); } public void finish() { ((IpCheckerWizard)wizard).selectedService.addListener(this); ((IpCheckerWizard)wizard).selectedService.initiateCheck(10000); } public void checkComplete(ExternalIPCheckerService service, String ip) { reportProgress(service,MessageText.getString("ipCheckerWizard.checkComplete") + ip); IpSetterCallBack callBack = ((IpCheckerWizard)wizard).callBack; if(callBack != null) { callBack.setIp(ip); } wizard.switchToClose(); } public void checkFailed(ExternalIPCheckerService service, String reason) { reportProgress(service,MessageText.getString("ipCheckerWizard.checkFailed") + reason); wizard.switchToClose(); } public void reportProgress( final ExternalIPCheckerService service, final String message) { if(display == null || display.isDisposed()) return; display.asyncExec(new AERunnable() { public void runSupport() { if (tasks != null && !tasks.isDisposed()) { tasks.append(service.getName() + " : " + message + Text.DELIMITER); } } }); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/ipchecker/IpSetterCallBack.java0000644000175000017500000000172007754000102025316 0ustar adrianadrian/* * File : IpSetterCallBack.java * Created : 10 nov. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.ipchecker; /** * @author Olivier * */ public interface IpSetterCallBack { public void setIp(String ip); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/ipchecker/IpCheckerWizard.java0000644000175000017500000000266611171750564025246 0ustar adrianadrian/* * File : IpCheckerWizard.java Created : 10 nov. 2003 By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.ipchecker; import org.gudy.azureus2.core3.ipchecker.extipchecker.ExternalIPCheckerService; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import org.gudy.azureus2.ui.swt.wizard.Wizard; /** * @author Olivier * */ public class IpCheckerWizard extends Wizard { IpSetterCallBack callBack; ExternalIPCheckerService selectedService; public IpCheckerWizard() { super("ipCheckerWizard.title"); IWizardPanel panel = new ChooseServicePanel(this,null); this.setFirstPanel(panel); } public void setIpSetterCallBack(IpSetterCallBack callBack) { this.callBack = callBack; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/ipchecker/ChooseServicePanel.java0000644000175000017500000001172310551540656025743 0ustar adrianadrian/* * File : ChooseServicePanel.java * Created : 10 nov. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.ipchecker; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.ipchecker.extipchecker.ExternalIPCheckerFactory; import org.gudy.azureus2.core3.ipchecker.extipchecker.ExternalIPCheckerService; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; /** * @author Olivier * */ public class ChooseServicePanel extends AbstractWizardPanel { private Combo servicesList; private ExternalIPCheckerService[] services; Label serviceDescription; Label serviceUrl; public ChooseServicePanel(IpCheckerWizard wizard,IWizardPanel previousPanel) { super(wizard,previousPanel); } public void show() { wizard.setTitle(MessageText.getString("ipCheckerWizard.service")); wizard.setCurrentInfo(MessageText.getString("ipCheckerWizard.chooseService")); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 2; rootPanel.setLayout(layout); Label label = new Label(rootPanel,SWT.WRAP); GridData gridData = new GridData(); gridData.widthHint = 380; gridData.horizontalSpan = 2; label.setLayoutData(gridData); label.setText(MessageText.getString("ipCheckerWizard.explanations")); this.servicesList = new Combo(rootPanel,SWT.READ_ONLY); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; servicesList.setLayoutData(gridData); this.services = ExternalIPCheckerFactory.create().getServices(); for(int i = 0 ; i < services.length ; i++) { servicesList.add(services[i].getName()); } label = new Label(rootPanel,SWT.NULL); label.setText(MessageText.getString("ipCheckerWizard.service.url")); Cursor handCursor = new Cursor(rootPanel.getDisplay(), SWT.CURSOR_HAND); this.serviceUrl = new Label(rootPanel,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); serviceUrl.setLayoutData(gridData); serviceUrl.setForeground(Colors.blue); serviceUrl.setCursor(handCursor); serviceUrl.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getText()); } public void mouseDown(MouseEvent arg0) { Utils.launch((String) ((Label) arg0.widget).getText()); } }); servicesList.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { updateInfos(); } }); servicesList.select(0); label = new Label(rootPanel,SWT.NULL); gridData = new GridData(); gridData.heightHint = 50; gridData.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; label.setLayoutData(gridData); label.setText(MessageText.getString("ipCheckerWizard.service.description")); this.serviceDescription = new Label(rootPanel,SWT.WRAP); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.heightHint = 50; gridData.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; serviceDescription.setLayoutData(gridData); updateInfos(); } private void updateInfos() { int selection = servicesList.getSelectionIndex(); serviceDescription.setText(services[selection].getDescription()); serviceUrl.setText(services[selection].getURL()); ((IpCheckerWizard)wizard).selectedService = services[selection]; ((IpCheckerWizard)wizard).setFinishEnabled( services[selection].supportsCheck()); } public boolean isFinishEnabled() { return true; } public IWizardPanel getFinishPanel() { return new ProgressPanel((IpCheckerWizard)wizard,this); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/UIConfigDefaultsSWT.java0000644000175000017500000001136411256533624024017 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.impl.ConfigurationDefaults; import org.gudy.azureus2.core3.util.Constants; /** * @author TuxPaper * @created Nov 3, 2006 * */ public class UIConfigDefaultsSWT { /** * */ public static void initialize() { ConfigurationDefaults def = ConfigurationDefaults.getInstance(); def.addParameter("useCustomTab", true); def.addParameter("GUI Refresh", 500); def.addParameter("Graphics Update", 4); def.addParameter("ReOrder Delay", 4); def.addParameter("Refresh When Inactive", 2); def.addParameter("Send Version Info", true); def.addParameter("Show Download Basket", false); def.addParameter("config.style.refreshMT", 0); def.addParameter("Open Details", false); def.addParameter("Open Seeding Details", false); def.addParameter("IconBar.enabled", true); def.addParameter("DefaultDir.BestGuess", true); def.addParameter("DefaultDir.AutoUpdate", true); def.addParameter("DefaultDir.AutoSave.AutoRename", true); def.addParameter("GUI_SWT_bFancyTab", true); def.addParameter("GUI_SWT_bAlternateTablePainting", false); def.addParameter("Colors.progressBar.override", false); def.addParameter("GUI_SWT_DisableAlertSliding", false); def.addParameter("NameColumn.showProgramIcon", !Constants.isWindowsVista); def.addParameter("Open MyTorrents", true); def.addParameter("DND Always In Incomplete", false); def.addParameter("Message Popup Autoclose in Seconds", 15); def.addParameter("Add URL Silently", false); def.addParameter("config.style.dropdiraction", "0"); def.addParameter("MyTorrents.SplitAt", 30); def.addParameter("Wizard Completed", false); def.addParameter("Color Scheme.red", 0); def.addParameter("Color Scheme.green", 128); def.addParameter("Color Scheme.blue", 255); def.addParameter("Show Splash", true); def.addParameter("window.maximized", true); def.addParameter("window.rectangle", ""); def.addParameter("Open Console", false); def.addParameter("Open Config", false); def.addParameter("Open Stats On Start", false); def.addParameter("Start Minimized", false); def.addParameter("Open Transfer Bar On Start", false); def.addParameter("Stats Graph Dividers", false); def.addParameter("Open Bar Incomplete", false); def.addParameter("Open Bar Complete", false); def.addParameter("Close To Tray", true); def.addParameter("Minimize To Tray", false); def.addParameter("Status Area Show SR", true); def.addParameter("Status Area Show NAT", true); def.addParameter("Status Area Show DDB", true); def.addParameter("Status Area Show IPF", true); def.addParameter("GUI_SWT_share_count_at_close", 0 ); def.addParameter("GUI_SWT_bOldSpeedMenu", false); def.addParameter("ui.toolbar.uiswitcher", false); def.addParameter("ui.systray.tooltip.enable", false); def.addParameter("ui", "az2"); def.addParameter("Remember transfer bar location", true); if ( COConfigurationManager.getBooleanParameter( "Open Bar" )){ COConfigurationManager.setParameter( "Open Bar Incomplete", true ); COConfigurationManager.setParameter( "Open Bar Complete", true ); COConfigurationManager.setParameter( "Open Bar", false ); } def.addParameter("suppress_file_download_dialog", false); def.addParameter("auto_remove_inactive_items", false); def.addParameter("show_torrents_menu", true); def.addParameter("swt.forceMozilla",false); def.addParameter("swt.xulRunner.path",""); String xulPath = COConfigurationManager.getStringParameter("swt.xulRunner.path"); if(!xulPath.equals("")) System.setProperty("org.eclipse.swt.browser.XULRunnerPath", xulPath); def.addParameter("MyTorrentsView.table.style", 0); def.addParameter("MyTorrentsView.alwaysShowHeader", true); def.addParameter("ConfigView.section.style.swt.library.selection", "cocoa"); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/test/0000755000175000017500000000000011310377636020375 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/test/PrintTransferTypes.java0000644000175000017500000001060607766434640025102 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.test; import org.eclipse.swt.*; import org.eclipse.swt.dnd.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; /** * Application to identify supported URL drag and drop IDs from different * browsers. * * @see org.gudy.azureus2.ui.swt.URLTransfer * @author Rene Leonhardt */ public class PrintTransferTypes extends ByteArrayTransfer { private static PrintTransferTypes _instance = new PrintTransferTypes(); private int[] ids; private String[] names; public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setLayout(new FillLayout()); Canvas canvas = new Canvas(shell, SWT.NONE); DropTarget target = new DropTarget(canvas, DND.DROP_DEFAULT | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_TARGET_MOVE | DND.DROP_NONE); target.setTransfer(new Transfer[] { PrintTransferTypes.getInstance(), TextTransfer.getInstance(), FileTransfer.getInstance()}); target.addDropListener(new DropTargetAdapter() { public void dragEnter(DropTargetEvent event) { // if(event.detail == DND.DROP_NONE) event.detail = DND.DROP_LINK; String ops = ""; if ((event.operations & DND.DROP_COPY) != 0) ops += "Copy;"; if ((event.operations & DND.DROP_MOVE) != 0) ops += "Move;"; if ((event.operations & DND.DROP_LINK) != 0) ops += "Link;"; System.out.println("Allowed Operations are " + ops); TransferData[] data = event.dataTypes; for (int i = 0; i < data.length; i++) { int id = data[i].type; String name = getNameFromId(id); System.out.println("Data type is " + id + " " + name); } } public void dragOver(DropTargetEvent event) { event.detail = DND.DROP_LINK; } public void drop(DropTargetEvent event) { System.out.println("URL dropped: " + event.data); System.out.println("Data type is " + event.currentDataType.type + " " + getNameFromId(event.currentDataType.type)); } }); shell.setSize(400, 400); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } public static PrintTransferTypes getInstance() { return _instance; } PrintTransferTypes() { ids = new int[50000]; names = new String[50000]; for (int i = 0; i < ids.length; i++) { ids[i] = i; names[i] = getNameFromId(i); } } public void javaToNative(Object object, TransferData transferData) {} public Object nativeToJava(TransferData transferData) { byte[] buffer = (byte[]) super.nativeToJava(transferData); if (buffer == null) return null; int size = buffer.length; byte[] text = new byte[size]; int j = 0; for (int i = 0; i < buffer.length; i++) { if (buffer[i] != 0) text[j++] = buffer[i]; } String data = new String(text, 0, j); int end = data.indexOf("\n"); return end >= 0 ? data.substring(0, end) : data; } protected String[] getTypeNames() { return names; } protected int[] getTypeIds() { return ids; } static String getNameFromId(int id) { switch (id) { case 1 : return "CF_TEXT"; case 8 : return "CF_DIB"; case 13 : return "CF_UNICODETEXT"; case 15 : return "CF_HDROP"; case 49158 : return "FileName"; case 49159 : return "FileNameW"; case 49267 : return "Shell IDList Array"; case 49350 : return "FileContents"; case 49351 : return "FileGroupDescriptor"; case 49352 : return "FileGroupDescriptorW"; case 49356 : return "HTML Format"; case 49357 : return "Preferred DropEffect"; case 49361 : return "UniformResourceLocator"; case 49362 : return "UniformResourceLocator"; // or InShellDragLoop case 49368 : return "UniformResourceLocator"; case 49429 : return "UniformResourceLocatorW"; case 49458 : return "UniformResourceLocatorW"; case 49569 : return "text/html"; case 49570 : return "text/_moz_htmlcontext"; case 49571 : return "text/_moz_htmlinfo"; case 49624 : return "application/x-moz-nativeimage"; } return "*UNKNOWN_TYPE*"; } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/test/Main.java0000644000175000017500000001430510634360542022123 0ustar adrianadrian/* * Copyright (c) 2000, 2003 IBM Corp. All rights reserved. * This file is made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html */ /* * Table example snippet: place arbitrary controls in a table * * For a list of all SWT example snippets see * http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-swt-home/dev.html#snippets */ package org.gudy.azureus2.ui.swt.test; import org.eclipse.swt.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.eclipse.swt.custom.*; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseMoveListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; public class Main { private Color blue; private Table table; private boolean mousePressed; private TableItem selectedItem; Rectangle oldBounds; Image oldImage; public Main() { final Display display = new Display (); blue = new Color(display,0,0,128); final Shell shell = new Shell (display); GridLayout layout = new GridLayout(); layout.numColumns = 3; GridData gridData; shell.setLayout (layout); table = new Table (shell, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 3; table.setLayoutData(gridData); table.setLinesVisible (true); Font f = table.getFont(); FontData fd = f.getFontData()[0]; fd.setHeight(9); Font font = new Font(display, fd); table.setFont(font); Button bOk = new Button(shell,SWT.PUSH); bOk.setText("Ok"); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.HORIZONTAL_ALIGN_FILL); gridData.grabExcessHorizontalSpace = true; gridData.widthHint = 70; bOk.setLayoutData(gridData); Button bCancel = new Button(shell,SWT.PUSH); bCancel.setText("Cancel"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); gridData.grabExcessHorizontalSpace = false; gridData.widthHint = 70; bCancel.setLayoutData(gridData); Button bApply = new Button(shell,SWT.PUSH); bApply.setText("Apply"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); gridData.grabExcessHorizontalSpace = false; gridData.widthHint = 70; bApply.setLayoutData(gridData); for (int i=0; i<2; i++) { new TableColumn(table, SWT.NONE); } for (int i=0; i<12; i++) { createTableRow(-1,"Toto" + i , false); } TableItem item = new TableItem(table,SWT.NULL); item.setText(1,"---"); //Hack to get a correct width table.getColumn(0).setWidth(20); table.getColumn(1).setWidth(200); table.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent arg0) { mousePressed = true; selectedItem = table.getItem(new Point(arg0.x,arg0.y)); if(selectedItem.getText(1).equals("---")) { selectedItem = null; } } public void mouseUp(MouseEvent e) { mousePressed = false; //1. Restore old image if(oldBounds != null && oldImage != null) { GC gc = new GC(table); gc.drawImage(oldImage,oldBounds.x,oldBounds.y); oldImage.dispose(); oldImage = null; oldBounds = null; } Point p = new Point(e.x,e.y); TableItem item = table.getItem(p); if(item != null && selectedItem != null) { int index = table.indexOf(item); int oldIndex = table.indexOf(selectedItem); if(index == oldIndex) return; String name = (String) selectedItem.getData("name"); Button oldBtn = (Button)selectedItem.getData("button"); boolean selected = oldBtn.getSelection(); oldBtn.dispose(); createTableRow(index,name,selected); selectedItem.dispose(); Point size = shell.getSize(); shell.setSize(size.x+1,size.y+1); shell.setSize(size); } } }); table.addMouseMoveListener(new MouseMoveListener(){ public void mouseMove(MouseEvent e) { if(mousePressed && selectedItem != null) { Point p = new Point(e.x,e.y); TableItem item = table.getItem(p); if(item != null) { GC gc = new GC(table); Rectangle bounds = item.getBounds(1); //1. Restore old image if(oldBounds != null && oldImage != null) { gc.drawImage(oldImage,oldBounds.x,oldBounds.y); oldImage.dispose(); oldImage = null; oldBounds = null; } //2. Store the image oldImage = new Image(display,bounds.width,2); gc.copyArea(oldImage,bounds.x,bounds.y); oldBounds = bounds; //3. Draw a thick line gc.setBackground(blue); gc.fillRectangle(bounds.x,bounds.y,bounds.width,2); } } } }); shell.pack (); shell.open (); while (!shell.isDisposed ()) { if (!display.readAndDispatch ()) display.sleep (); } display.dispose (); if (font != null && !font.isDisposed()) { font.dispose(); } } private void createTableRow(int index,String name,boolean selected) { TableItem item; if(index == -1) item = new TableItem (table, SWT.NONE); else item = new TableItem (table, SWT.NONE,index); item.setText(1,name); item.setData("name",name); TableEditor editor = new TableEditor (table); Button button = new Button (table, SWT.CHECK); button.setSelection(selected); button.pack (); editor.minimumWidth = button.getSize ().x; editor.horizontalAlignment = SWT.CENTER; editor.setEditor (button, item, 0); item.setData("button",button); } public static void main(String[] args) { new Main(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/test/SashFormTest.java0000644000175000017500000000327210534155666023632 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt.test; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; /** * @author TuxPaper * @created Dec 1, 2006 * */ public class SashFormTest { public static void main(String[] args) { Display display = Display.getDefault(); Shell shell = new Shell(display, SWT.SHELL_TRIM); shell.setLayout(new FillLayout()); SashForm sf = new SashForm(shell, SWT.VERTICAL); sf.SASH_WIDTH = 10; sf.setLayout(new FillLayout()); new Composite(sf, SWT.BORDER); new Composite(sf, SWT.BORDER); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/test/TableTest.java0000644000175000017500000001072010457154734023132 0ustar adrianadrian/* * Created on Jul 18, 2006 11:13:05 AM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.test; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; /** * @author TuxPaper * @created Jul 18, 2006 * */ public class TableTest { static Table tableNormal; private static Table tableVirtual; static Display display; public static void main(String[] args) { display = Display.getDefault(); Shell shell = new Shell(display, SWT.SHELL_TRIM); shell.setLayout(new FillLayout()); tableNormal = new Table(shell, SWT.BORDER); tableVirtual = new Table(shell, SWT.BORDER | SWT.VIRTUAL); Button btnStart = new Button(shell, SWT.PUSH); btnStart.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { runtest(); } }); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } /** * */ protected static void runtest() { tableNormal.clearAll(); waitForComplete(); runtest1(); tableNormal.clearAll(); waitForComplete(); runtest2(); tableNormal.clearAll(); waitForComplete(); runtest3(); tableNormal.clearAll(); waitForComplete(); runtest4(); tableNormal.clearAll(); waitForComplete(); runtest5(); tableNormal.clearAll(); waitForComplete(); runtest6(); tableNormal.clearAll(); waitForComplete(); runtest7(); } static void runtest1() { long lStartTime = System.currentTimeMillis(); for (int i = 0; i < 500; i++) { new TableItem(tableNormal, SWT.None); } waitForComplete(); long lEndTime = System.currentTimeMillis(); System.out.println("NVI: " + (lEndTime - lStartTime)); } static void runtest2() { long lStartTime = System.currentTimeMillis(); tableNormal.setItemCount(500); waitForComplete(); long lEndTime = System.currentTimeMillis(); System.out.println("NVS: " + (lEndTime - lStartTime)); } static void runtest3() { long lStartTime = System.currentTimeMillis(); for (int i = 0; i < 500; i++) { new TableItem(tableVirtual, SWT.None); } waitForComplete(); long lEndTime = System.currentTimeMillis(); System.out.println("VI:" + (lEndTime - lStartTime)); } static void runtest4() { long lStartTime = System.currentTimeMillis(); tableVirtual.setItemCount(500); waitForComplete(); long lEndTime = System.currentTimeMillis(); System.out.println("Vs:" + (lEndTime - lStartTime)); } static void waitForComplete() { while (display.readAndDispatch()) {} } static void runtest5() { tableNormal.setItemCount(1000); waitForComplete(); long lStartTime = System.currentTimeMillis(); tableNormal.setItemCount(500); long lEndTime = System.currentTimeMillis(); System.out.println("NVD1: " + (lEndTime - lStartTime)); } static void runtest6() { tableNormal.setItemCount(1000); waitForComplete(); long lStartTime = System.currentTimeMillis(); for (int i = 0; i < 500; i++) { tableNormal.getItem(2).dispose(); } long lEndTime = System.currentTimeMillis(); System.out.println("NVD2: " + (lEndTime - lStartTime)); } static void runtest7() { tableNormal.setItemCount(1000); waitForComplete(); int indexes[] = new int[500]; for (int i = 0; i < 200; i++) { indexes[i] = i * 2; } int x = 400; for (int i = 200; i < 500; i++) { indexes[i] = x++; } long lStartTime = System.currentTimeMillis(); tableNormal.remove(indexes); long lEndTime = System.currentTimeMillis(); System.out.println("NVD3: " + (lEndTime - lStartTime)); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/test/Win32TransferTypes.java0000644000175000017500000001151407766434640024707 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt.test; import org.eclipse.swt.*; import org.eclipse.swt.dnd.*; import org.eclipse.swt.internal.ole.win32.*; import org.eclipse.swt.internal.win32.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; /** * Application to identify supported URL drag and drop IDs from different browsers on Windows. * * @see org.gudy.azureus2.ui.swt.URLTransfer * @author Rene Leonhardt */ public class Win32TransferTypes extends ByteArrayTransfer { private static Win32TransferTypes _instance = new Win32TransferTypes(); private int[] ids; private String[] names; public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setLayout(new FillLayout()); Canvas canvas = new Canvas(shell, SWT.NONE); DropTarget target = new DropTarget(canvas, DND.DROP_DEFAULT | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_TARGET_MOVE | DND.DROP_NONE); target.setTransfer(new Transfer[] { Win32TransferTypes.getInstance(), TextTransfer.getInstance(), FileTransfer.getInstance()}); target.addDropListener(new DropTargetAdapter() { public void dragEnter(DropTargetEvent event) { // if(event.detail == DND.DROP_NONE) event.detail = DND.DROP_LINK; String ops = ""; if ((event.operations & DND.DROP_COPY) != 0) ops += "Copy;"; if ((event.operations & DND.DROP_MOVE) != 0) ops += "Move;"; if ((event.operations & DND.DROP_LINK) != 0) ops += "Link;"; System.out.println("Allowed Operations are " + ops); TransferData[] data = event.dataTypes; for (int i = 0; i < data.length; i++) { int id = data[i].type; String name = getNameFromId(id); System.out.println("Data type is " + id + " " + name); } } public void dragOver(DropTargetEvent event) { event.detail = DND.DROP_LINK; } public void drop(DropTargetEvent event) { System.out.println("URL dropped: " + event.data); System.out.println("Data type is " + event.currentDataType.type + " " + getNameFromId(event.currentDataType.type)); } }); shell.setSize(400, 400); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } public static Win32TransferTypes getInstance() { return _instance; } Win32TransferTypes() { ids = new int[50000]; names = new String[50000]; for (int i = 0; i < ids.length; i++) { ids[i] = i; names[i] = getNameFromId(i); } } public void javaToNative(Object object, TransferData transferData) {} public Object nativeToJava(TransferData transferData) { byte[] buffer = (byte[]) super.nativeToJava(transferData); if (buffer == null) return null; int size = buffer.length; byte[] text = new byte[size]; int j = 0; for (int i = 0; i < buffer.length; i++) { if (buffer[i] != 0) text[j++] = buffer[i]; } String data = new String(text, 0, j); int end = data.indexOf("\n"); return end >= 0 ? data.substring(0, end) : data; } protected String[] getTypeNames() { return names; } protected int[] getTypeIds() { return ids; } static String getNameFromId(int id) { String name = null; int maxSize = 128; TCHAR buffer = new TCHAR(0, maxSize); int size = COM.GetClipboardFormatName(id, buffer, maxSize); if (size != 0) { name = buffer.toString(0, size); } else { switch (id) { case COM.CF_HDROP : name = "CF_HDROP"; break; case COM.CF_TEXT : name = "CF_TEXT"; break; case COM.CF_BITMAP : name = "CF_BITMAP"; break; case COM.CF_METAFILEPICT : name = "CF_METAFILEPICT"; break; case COM.CF_SYLK : name = "CF_SYLK"; break; case COM.CF_DIF : name = "CF_DIF"; break; case COM.CF_TIFF : name = "CF_TIFF"; break; case COM.CF_OEMTEXT : name = "CF_OEMTEXT"; break; case COM.CF_DIB : name = "CF_DIB"; break; case COM.CF_PALETTE : name = "CF_PALETTE"; break; case COM.CF_PENDATA : name = "CF_PENDATA"; break; case COM.CF_RIFF : name = "CF_RIFF"; break; case COM.CF_WAVE : name = "CF_WAVE"; break; case COM.CF_UNICODETEXT : name = "CF_UNICODETEXT"; break; case COM.CF_ENHMETAFILE : name = "CF_ENHMETAFILE"; break; case COM.CF_LOCALE : name = "CF_LOCALE"; break; case COM.CF_MAX : name = "CF_MAX"; break; } } return name; } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/maketorrent/0000755000175000017500000000000011310377636021751 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/maketorrent/MultiTrackerPanel.java0000644000175000017500000002226410672622606026210 0ustar adrianadrian/* * File : ModePanel.java Created : 30 sept. 2003 01:51:05 By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.maketorrent; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.TrackersUtil; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; /** * @author Olivier * */ public class MultiTrackerPanel extends AbstractWizardPanel implements TrackerEditorListener{ private Combo configList; private Tree configDetails; private Button btnNew; private Button btnEdit; private Button btnDelete; public MultiTrackerPanel(NewTorrentWizard wizard, AbstractWizardPanel previous) { super(wizard, previous); } /* * (non-Javadoc) * * @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#show() */ public void show() { wizard.setTitle(MessageText.getString("wizard.multitracker.title")); wizard.setCurrentInfo(""); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); //Line : // Multi-Tracker Configuration final Label labelTitle = new Label(panel,SWT.NULL); Messages.setLanguageText(labelTitle, "wizard.multitracker.configuration"); gridData = new GridData(); gridData.horizontalSpan = 3; labelTitle.setLayoutData(gridData); configList = new Combo(panel,SWT.READ_ONLY); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; configList.setLayoutData(gridData); configList.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { updateTrackers(); refreshDetails(); } }); btnNew = new Button(panel, SWT.PUSH); Messages.setLanguageText(btnNew, "wizard.multitracker.new"); gridData = new GridData(); gridData.widthHint = 100; btnNew.setLayoutData(gridData); btnNew.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { List group = new ArrayList(); List tracker = new ArrayList(); tracker.add(((NewTorrentWizard)wizard).trackerURL); group.add(tracker); new MultiTrackerEditor(null,group,MultiTrackerPanel.this); } }); btnEdit = new Button(panel, SWT.PUSH); Messages.setLanguageText(btnEdit, "wizard.multitracker.edit"); gridData = new GridData(); gridData.widthHint = 100; btnEdit.setLayoutData(gridData); btnEdit.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { int selection = configList.getSelectionIndex(); String selected = configList.getItem(selection); Map multiTrackers = TrackersUtil.getInstance().getMultiTrackers(); new MultiTrackerEditor(selected,(List)multiTrackers.get(selected),MultiTrackerPanel.this); } }); btnDelete = new Button(panel, SWT.PUSH); Messages.setLanguageText(btnDelete, "wizard.multitracker.delete"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); gridData.widthHint = 100; btnDelete.setLayoutData(gridData); btnDelete.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { int selection = configList.getSelectionIndex(); String selected = configList.getItem(selection); TrackersUtil.getInstance().removeMultiTracker(selected); refreshList(""); refreshDetails(); setEditDeleteEnable(); } }); final Label labelSeparator = new Label(panel,SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; labelSeparator.setLayoutData(gridData); configDetails = new Tree(panel,SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.heightHint = 150; gridData.horizontalSpan = 3; configDetails.setLayoutData(gridData); refreshList(((NewTorrentWizard)wizard).multiTrackerConfig); refreshDetails(); setEditDeleteEnable(); } /* * (non-Javadoc) * * @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#getNextPanel() */ public IWizardPanel getNextPanel() { if(((NewTorrentWizard) wizard).useWebSeed) return new WebSeedPanel((NewTorrentWizard) wizard, this); if (((NewTorrentWizard) wizard).create_from_dir) { return new DirectoryPanel(((NewTorrentWizard) wizard), this); } else { return new SingleFilePanel(((NewTorrentWizard) wizard), this); } } public boolean isNextEnabled() { return true; } void refreshDetails() { configDetails.removeAll(); List trackers = ((NewTorrentWizard) wizard).trackers; Iterator iter = trackers.iterator(); while(iter.hasNext()) { List trackerGroup = (List) iter.next(); TreeItem itemRoot = new TreeItem(configDetails,SWT.NULL); Messages.setLanguageText(itemRoot, "wizard.multitracker.group"); Iterator iter2 = trackerGroup.iterator(); while(iter2.hasNext()) { String url = (String) iter2.next(); new TreeItem(itemRoot,SWT.NULL).setText(url); } itemRoot.setExpanded(true); } } void setEditDeleteEnable() { if(configList.getItemCount() > 0) { btnEdit.setEnabled(true); btnDelete.setEnabled(true); } else { btnEdit.setEnabled(false); btnDelete.setEnabled(false); } } public void trackersChanged(String oldName, String newName, List trackers) { TrackersUtil util = TrackersUtil.getInstance(); if(oldName != null && !oldName.equals(newName)) util.removeMultiTracker(oldName); util.addMultiTracker(newName,trackers); refreshList(newName); refreshDetails(); setEditDeleteEnable(); } private void refreshList(String toBeSelected) { Map multiTrackers = TrackersUtil.getInstance().getMultiTrackers(); configList.removeAll(); Iterator iter = multiTrackers.keySet().iterator(); while(iter.hasNext()) { configList.add((String)iter.next()); } int selection = configList.indexOf(toBeSelected); if(selection != -1) { configList.select(selection); } else if(configList.getItemCount() > 0) { configList.select(0); } updateTrackers(); } private void updateTrackers() { int selection = configList.getSelectionIndex(); if(selection == -1) { List group = new ArrayList(); List tracker = new ArrayList(); tracker.add(((NewTorrentWizard)wizard).trackerURL); group.add(tracker); ((NewTorrentWizard)wizard).trackers = group; ((NewTorrentWizard)wizard).multiTrackerConfig = ""; setNext(); return; } String selected = configList.getItem(selection); ((NewTorrentWizard)wizard).multiTrackerConfig = selected; Map multiTrackers = TrackersUtil.getInstance().getMultiTrackers(); ((NewTorrentWizard)wizard).trackers = (List) multiTrackers.get(selected); setNext(); } private void setNext() { String trackerUrl = ((NewTorrentWizard)wizard).trackerURL; List groups = ((NewTorrentWizard)wizard).trackers; Iterator iterGroups = groups.iterator(); while(iterGroups.hasNext()) { List trackers = (List) iterGroups.next(); Iterator iterTrackers = trackers.iterator(); while(iterTrackers.hasNext()) { String tracker = (String) iterTrackers.next(); if(trackerUrl.equals(tracker)) { wizard.setNextEnabled(true); wizard.setErrorMessage(""); return; } } } wizard.setNextEnabled(false); wizard.setErrorMessage(MessageText.getString("wizard.multitracker.noannounce")); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/maketorrent/DirectoryPanel.java0000644000175000017500000001247610143004470025534 0ustar adrianadrian/* * File : SingleFilePanel.java Created : 30 sept. 2003 02:50:19 By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.maketorrent; import java.io.File; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; /** * @author Olivier * */ public class DirectoryPanel extends AbstractWizardPanel { private Text file; public DirectoryPanel(NewTorrentWizard wizard, IWizardPanel previous) { super(wizard, previous); } /* * (non-Javadoc) * * @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#show() */ public void show() { wizard.setTitle(MessageText.getString("wizard.directory")); wizard.setCurrentInfo(MessageText.getString("wizard.choosedirectory")); Composite panel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); Label label = new Label(panel, SWT.NULL); Messages.setLanguageText(label, "wizard.directory"); file = new Text(panel, SWT.BORDER); file.addModifyListener(new ModifyListener() { /* * (non-Javadoc) * * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent) */ public void modifyText(ModifyEvent arg0) { String fName = file.getText(); ((NewTorrentWizard) wizard).directoryPath = fName; String error = ""; if (!fName.equals("")) { File f = new File(file.getText()); if (!f.exists() || !f.isDirectory()) { error = MessageText.getString("wizard.invaliddirectory"); }else{ String parent = f.getParent(); if ( parent != null ){ ((NewTorrentWizard) wizard).setDefaultOpenDir( parent ); } } } wizard.setErrorMessage(error); wizard.setNextEnabled(!((NewTorrentWizard) wizard).directoryPath.equals("") && error.equals("")); } }); file.setText(((NewTorrentWizard) wizard).directoryPath); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); file.setLayoutData(gridData); Button browse = new Button(panel, SWT.PUSH); browse.addListener(SWT.Selection, new Listener() { /* * (non-Javadoc) * * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event arg0) { DirectoryDialog fd = new DirectoryDialog(wizard.getWizardWindow()); if (wizard.getErrorMessage().equals("") && !((NewTorrentWizard) wizard).directoryPath.equals("")) { fd.setFilterPath(((NewTorrentWizard) wizard).directoryPath); }else{ String def = ((NewTorrentWizard) wizard).getDefaultOpenDir(); if ( def.length() > 0 ){ fd.setFilterPath( def ); } } String f = fd.open(); if (f != null){ file.setText(f); File ff = new File(f); String parent = ff.getParent(); if ( parent != null ){ ((NewTorrentWizard) wizard).setDefaultOpenDir( parent ); } } } }); Messages.setLanguageText(browse, "wizard.browse"); label = new Label(panel, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; label.setLayoutData(gridData); label.setText("\n"); label = new Label(panel, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; label.setLayoutData(gridData); label.setForeground(Colors.blue); Messages.setLanguageText(label, "wizard.hint.directory"); } /* * (non-Javadoc) * * @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#getNextPanel() */ public IWizardPanel getNextPanel() { // TODO Auto-generated method stub return new SavePathPanel(((NewTorrentWizard) wizard), this); } public void setFilename(String filename) { file.setText(filename); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/maketorrent/SavePathPanel.java0000644000175000017500000002613110656726504025316 0ustar adrianadrian/* * File : SavePathPanel.java * Created : 30 sept. 2003 17:06:45 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.maketorrent; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import java.io.File; /** * @author Olivier * */ public class SavePathPanel extends AbstractWizardPanel { protected long file_size; protected long piece_size; protected long piece_count; public SavePathPanel(NewTorrentWizard _wizard,AbstractWizardPanel _previousPanel) { super(_wizard,_previousPanel); } /* (non-Javadoc) * @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#show() */ public void show() { final NewTorrentWizard _wizard = (NewTorrentWizard)wizard; try{ file_size = TOTorrentFactory.getTorrentDataSizeFromFileOrDir(new File(_wizard.create_from_dir?_wizard.directoryPath:_wizard.singlePath)); piece_size = TOTorrentFactory.getComputedPieceSize( file_size ); piece_count = TOTorrentFactory.getPieceCount( file_size, piece_size ); }catch( Throwable e ){ Debug.printStackTrace( e ); } wizard.setTitle(MessageText.getString("wizard.torrentFile")); wizard.setCurrentInfo(MessageText.getString("wizard.choosetorrent")); Composite panel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); Label label;/* = new Label(panel,SWT.NULL); Messages.setLanguageText(label,"wizard.file");*/ final Text file = new Text(panel,SWT.BORDER); file.addModifyListener(new ModifyListener() { /* (non-Javadoc) * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent) */ public void modifyText(ModifyEvent arg0) { String fName = file.getText(); ((NewTorrentWizard)wizard).savePath = fName; String error = ""; if(! fName.equals("")) { File f = new File(file.getText()); if(f.exists() || f.isDirectory()) { error = MessageText.getString("wizard.invalidfile"); }else{ String parent = f.getParent(); if ( parent != null ){ ((NewTorrentWizard) wizard).setDefaultSaveDir( parent ); } } } wizard.setErrorMessage(error); wizard.setFinishEnabled(!((NewTorrentWizard)wizard).savePath.equals("") && error.equals("")); } }); // if we have a default save dir then use this as the basis for save location String target_file; if(((NewTorrentWizard)wizard).create_from_dir) { target_file = ((NewTorrentWizard)wizard).directoryPath + ".torrent"; } else { target_file = ((NewTorrentWizard)wizard).singlePath + ".torrent"; } String default_save = ((NewTorrentWizard)wizard).getDefaultSaveDir(); if (default_save.length() > 0 ){ File temp = new File( target_file ); String existing_parent = temp.getParent(); if ( existing_parent != null ){ target_file = new File( default_save, temp.getName()).toString(); } } ((NewTorrentWizard)wizard).savePath = target_file; file.setText(((NewTorrentWizard)wizard).savePath); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; file.setLayoutData(gridData); Button browse = new Button(panel,SWT.PUSH); browse.addListener(SWT.Selection,new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event arg0) { FileDialog fd = new FileDialog(wizard.getWizardWindow(),SWT.SAVE); final String path = ((NewTorrentWizard)wizard).savePath; if(wizard.getErrorMessage().equals("") && !path.equals("")) { File fsPath = new File(path); if(!path.endsWith(File.separator)) { fd.setFilterPath(fsPath.getParent()); fd.setFileName(fsPath.getName()); } else { fd.setFileName(path); } } String f = fd.open(); if (f != null){ file.setText(f); File ff = new File(f); String parent = ff.getParent(); if ( parent != null ) ((NewTorrentWizard) wizard).setDefaultSaveDir( parent ); } } }); Messages.setLanguageText(browse,"wizard.browse"); // ---------------------- label = new Label(panel, SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; label.setLayoutData(gridData); Composite gFileStuff = new Composite(panel, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan = 3; gFileStuff.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 4; gFileStuff.setLayout(layout); // file size label = new Label(gFileStuff, SWT.NULL); Messages.setLanguageText(label, "wizard.maketorrent.filesize"); Label file_size_label = new Label(gFileStuff, SWT.NULL); file_size_label.setText( DisplayFormatters.formatByteCountToKiBEtc(file_size)); label = new Label(gFileStuff, SWT.NULL); label = new Label(gFileStuff, SWT.NULL); // piece count label = new Label(gFileStuff, SWT.NULL); Messages.setLanguageText(label, "wizard.maketorrent.piececount"); final Label piece_count_label = new Label(gFileStuff, SWT.NULL); piece_count_label.setText( ""+piece_count ); label = new Label(gFileStuff, SWT.NULL); label = new Label(gFileStuff, SWT.NULL); // piece size label = new Label(gFileStuff, SWT.NULL); Messages.setLanguageText(label, "wizard.maketorrent.piecesize"); final Label piece_size_label = new Label(gFileStuff, SWT.NULL); gridData = new GridData(); gridData.widthHint = 75; piece_size_label.setLayoutData(gridData); piece_size_label.setText( DisplayFormatters.formatByteCountToKiBEtc( piece_size )); final Combo manual = new Combo(gFileStuff, SWT.SINGLE | SWT.READ_ONLY); final long[] sizes = TOTorrentFactory.STANDARD_PIECE_SIZES; manual.add( MessageText.getString( "wizard.maketorrent.auto")); for (int i=0;i 0 ){ this.reportCurrentTask(MessageText.getString("wizard.webseed.adding")); Map ws = _wizard.webseeds; List getright = (List)ws.get( "getright" ); if ( getright.size() > 0 ){ for (int i=0;i 0 ){ for (int i=0;i final String localTrackerHost = COConfigurationManager.getStringParameter("Tracker IP", ""); final int localTrackerPort = COConfigurationManager.getIntParameter("Tracker Port", TRHost.DEFAULT_PORT ); final int localTrackerPortSSL = COConfigurationManager.getIntParameter("Tracker Port SSL", TRHost.DEFAULT_PORT_SSL ); final boolean SSLEnabled = COConfigurationManager.getBooleanParameter("Tracker Port SSL Enable", false ); final String[] localTrackerUrl = new String[1]; // there's a potential oversize issue with the howToLocal string, and attemtping to force wrap has no effect - // therefore, provide more room and remove extraneous labeling final boolean showLocal = TRTrackerUtils.isTrackerEnabled(); final Label labelLocalAnnounce = (showLocal) ? new Label(panel, SWT.NULL) : null; final Label localTrackerValue = new Label(panel, SWT.NULL); if ( showLocal ){ Messages.setLanguageText(labelLocalAnnounce, "wizard.announceUrl"); localTrackerUrl[0] = "http://" + UrlUtils.convertIPV6Host(localTrackerHost) + ":" + localTrackerPort + "/announce"; localTrackerValue.setText(localTrackerUrl[0]); btnSSL.setEnabled( SSLEnabled ); gridData = new GridData(); gridData.horizontalSpan = 3; } else { localTrackerUrl[0] = ""; Messages.setLanguageText(localTrackerValue, "wizard.tracker.howToLocal"); btnLocalTracker.setSelection(false); btnSSL.setEnabled(false); btnLocalTracker.setEnabled(false); localTrackerValue.setEnabled(true); if ( wizard.getTrackerType() == NewTorrentWizard.TT_LOCAL ){ wizard.setTrackerType( NewTorrentWizard.TT_EXTERNAL ); } gridData = new GridData(); gridData.horizontalSpan = 4; } localTrackerValue.setLayoutData(gridData); int tracker_type = wizard.getTrackerType(); if (tracker_type == NewTorrentWizard.TT_LOCAL) { setTrackerUrl(localTrackerUrl[0]); }else if ( tracker_type == NewTorrentWizard.TT_EXTERNAL ){ setTrackerUrl( NewTorrentWizard.TT_EXTERNAL_DEFAULT ); }else{ setTrackerUrl( NewTorrentWizard.TT_DECENTRAL_DEFAULT ); } //Line: // O use external Tracker final Button btnExternalTracker = new Button(panel, SWT.RADIO); Messages.setLanguageText(btnExternalTracker, "wizard.tracker.external"); gridData = new GridData(); gridData.horizontalSpan = 4; btnExternalTracker.setLayoutData(gridData); //Line: // [External Tracker Url ]V final Label labelExternalAnnounce = new Label(panel, SWT.NULL); Messages.setLanguageText(labelExternalAnnounce, "wizard.announceUrl"); btnLocalTracker.setSelection(tracker_type==NewTorrentWizard.TT_LOCAL); if(showLocal) localTrackerValue.setEnabled(tracker_type==NewTorrentWizard.TT_LOCAL); btnSSL.setEnabled(SSLEnabled&&tracker_type==NewTorrentWizard.TT_LOCAL); btnExternalTracker.setSelection(tracker_type==NewTorrentWizard.TT_EXTERNAL); labelExternalAnnounce.setEnabled(tracker_type==NewTorrentWizard.TT_EXTERNAL); tracker = new Combo(panel, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; tracker.setLayoutData(gridData); List trackers = TrackersUtil.getInstance().getTrackersList(); Iterator iter = trackers.iterator(); while (iter.hasNext()) { tracker.add((String) iter.next()); } tracker.addModifyListener(new ModifyListener() { /* * (non-Javadoc) * * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent) */ public void modifyText(ModifyEvent arg0) { String text = tracker.getText(); setTrackerUrl(text); boolean valid = true; String errorMessage = ""; try { new URL(text); } catch (MalformedURLException e) { valid = false; errorMessage = MessageText.getString("wizard.invalidurl"); } wizard.setErrorMessage(errorMessage); wizard.setNextEnabled(valid); } }); tracker.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { String text = tracker.getText(); setTrackerUrl(text); boolean valid = true; String errorMessage = ""; try { new URL(text); } catch (MalformedURLException ex) { valid = false; errorMessage = MessageText.getString("wizard.invalidurl"); } wizard.setErrorMessage(errorMessage); wizard.setNextEnabled(valid); } }); updateTrackerURL(); tracker.setEnabled( tracker_type == NewTorrentWizard.TT_EXTERNAL ); new Label(panel,SWT.NULL); // O decentral tracking // has to be on same no-radio-group panel otherwise weird things happen regarding selection of // "external tracker" button *even if* we set it up so that "dht tracker" should be selected.... final Button btnDHTTracker = new Button(panel, SWT.RADIO); Messages.setLanguageText(btnDHTTracker, "wizard.tracker.dht"); gridData = new GridData(); gridData.horizontalSpan = 4; btnDHTTracker.setLayoutData(gridData); btnDHTTracker.setSelection(tracker_type==NewTorrentWizard.TT_DECENTRAL); // add another panel due to control oversize issues panel = new Composite(rootPanel, SWT.NO_RADIO_GROUP); gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 4; panel.setLayout(layout); //Line: // ------------------------------ Label label = new Label(panel, SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 4; label.setLayoutData(gridData); //Line: // [] add Multi-tracker information [] webseed final Button btnMultiTracker = new Button(panel,SWT.CHECK); Messages.setLanguageText(btnMultiTracker, "wizard.multitracker"); gridData = new GridData(); gridData.horizontalSpan = 2; btnMultiTracker.setLayoutData(gridData); btnMultiTracker.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { ((NewTorrentWizard) wizard).useMultiTracker = btnMultiTracker.getSelection(); } }); btnMultiTracker.setSelection(((NewTorrentWizard) wizard).useMultiTracker); btnMultiTracker.setEnabled( tracker_type != NewTorrentWizard.TT_DECENTRAL); final Button btnWebSeed = new Button(panel,SWT.CHECK); Messages.setLanguageText(btnWebSeed, "wizard.webseed"); gridData = new GridData(); gridData.horizontalSpan = 2; btnWebSeed.setLayoutData(gridData); btnWebSeed.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { ((NewTorrentWizard) wizard).useWebSeed = btnWebSeed.getSelection(); } }); btnWebSeed.setSelection(((NewTorrentWizard) wizard).useWebSeed); //Line: // include hashes for other networks ( final Button btnExtraHashes = new Button(panel,SWT.CHECK); Messages.setLanguageText(btnExtraHashes, "wizard.createtorrent.extrahashes"); gridData = new GridData(); gridData.horizontalSpan = 4; btnExtraHashes.setLayoutData(gridData); btnExtraHashes.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { ((NewTorrentWizard) wizard).setAddOtherHashes( btnExtraHashes.getSelection()); } }); btnExtraHashes.setSelection(((NewTorrentWizard) wizard).getAddOtherHashes()); // add another panel due to control oversize issues // the "hack" is staying until a more satisfactory solution can be found panel = new Composite(rootPanel, SWT.NONE); gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 4; panel.setLayout(layout); //Line: // ------------------------------ Label label1 = new Label(panel, SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 4; label1.setLayoutData(gridData); //Line: // O single file O Directory mode bSingle = new Button(panel, SWT.RADIO); bSingle.setSelection(!((NewTorrentWizard) wizard).create_from_dir); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; bSingle.setLayoutData(gridData); Messages.setLanguageText(bSingle, "wizard.singlefile"); bSingle.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { activateMode(true); } }); bDirectory = new Button(panel, SWT.RADIO); bDirectory.setSelection(((NewTorrentWizard) wizard).create_from_dir); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; bDirectory.setLayoutData(gridData); Messages.setLanguageText(bDirectory, "wizard.directory"); bDirectory.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { activateMode(false); } }); btnSSL.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { String url; if ( btnSSL.getSelection()){ url = "https://" + UrlUtils.convertIPV6Host(localTrackerHost) + ":" + localTrackerPortSSL + "/announce"; }else{ url = "http://" + UrlUtils.convertIPV6Host(localTrackerHost) + ":" + localTrackerPort + "/announce"; } localTrackerValue.setText(url); localTrackerUrl[0] = url; setTrackerUrl(url); } }); btnLocalTracker.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { wizard.setTrackerType( NewTorrentWizard.TT_LOCAL ); setTrackerUrl(localTrackerUrl[0]); updateTrackerURL(); btnExternalTracker.setSelection(false); btnLocalTracker.setSelection(true); btnDHTTracker.setSelection(false); tracker.setEnabled(false); btnSSL.setEnabled(SSLEnabled); if(labelLocalAnnounce != null) {labelLocalAnnounce.setEnabled(true);} localTrackerValue.setEnabled(true); labelExternalAnnounce.setEnabled(false); btnMultiTracker.setEnabled(true); } }); btnExternalTracker.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { wizard.setTrackerType( NewTorrentWizard.TT_EXTERNAL ); setTrackerUrl( NewTorrentWizard.TT_EXTERNAL_DEFAULT ); updateTrackerURL(); btnLocalTracker.setSelection(false); btnExternalTracker.setSelection(true); btnDHTTracker.setSelection(false); tracker.setEnabled(true); btnSSL.setEnabled(false); if(labelLocalAnnounce != null) {labelLocalAnnounce.setEnabled(false);} localTrackerValue.setEnabled(false); labelExternalAnnounce.setEnabled(true); btnMultiTracker.setEnabled(true); } }); btnDHTTracker.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { wizard.setTrackerType( NewTorrentWizard.TT_DECENTRAL ); setTrackerUrl( NewTorrentWizard.TT_DECENTRAL_DEFAULT ); updateTrackerURL(); btnLocalTracker.setSelection(false); btnExternalTracker.setSelection(false); btnDHTTracker.setSelection(true); tracker.setEnabled(false); btnSSL.setEnabled(false); if(labelLocalAnnounce != null) {labelLocalAnnounce.setEnabled(false);} localTrackerValue.setEnabled(false); labelExternalAnnounce.setEnabled(false); btnMultiTracker.setEnabled(false); } }); //Line: // ------------------------------ label = new Label(panel, SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 4; label.setLayoutData(gridData); //Line: //Comment: [ ] label = new Label(panel, SWT.NULL); Messages.setLanguageText(label, "wizard.comment"); final Text comment = new Text(panel, SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; comment.setLayoutData(gridData); comment.setText(((NewTorrentWizard) wizard).getComment()); comment.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { ((NewTorrentWizard) wizard).setComment(comment.getText()); } }); label = new Label(panel, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 4; label.setLayoutData(gridData); label.setText("\n"); label = new Label(panel, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 4; label.setLayoutData(gridData); label.setForeground(Colors.blue); Messages.setLanguageText(label, "wizard.hint.mode"); } /* * (non-Javadoc) * * @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#getNextPanel() */ public IWizardPanel getNextPanel() { //OSX work-arround to Fix SWT BUG #43396 : //Combo doesn't fire Selection Event if(Constants.isOSX) { //In case we're not using the localTracker, refresh the //Tracker URL from the Combo text if( ((NewTorrentWizard) wizard).getTrackerType() == NewTorrentWizard.TT_EXTERNAL ){ setTrackerUrl(tracker.getText()); } } if(((NewTorrentWizard) wizard).useMultiTracker) return new MultiTrackerPanel((NewTorrentWizard) wizard, this); if(((NewTorrentWizard) wizard).useWebSeed) return new WebSeedPanel((NewTorrentWizard) wizard, this); if (((NewTorrentWizard) wizard).create_from_dir) { return new DirectoryPanel(((NewTorrentWizard) wizard), this); } else { return new SingleFilePanel(((NewTorrentWizard) wizard), this); } } /* * (non-Javadoc) * * @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#isNextEnabled() */ public boolean isNextEnabled() { return true; } void activateMode(boolean singleFile) { wizard.setCurrentInfo(MessageText.getString(singleFile ? "wizard.singlefile.help" : "wizard.directory.help")); ((NewTorrentWizard) wizard).create_from_dir = !singleFile; bDirectory.setSelection(!singleFile); bSingle.setSelection(singleFile); } void updateTrackerURL() { tracker.setText(((NewTorrentWizard) wizard).trackerURL); } void setTrackerUrl(String url) { ((NewTorrentWizard) wizard).trackerURL = url; String config = ((NewTorrentWizard) wizard).multiTrackerConfig; if(config.equals("")) { List list = (List) ((NewTorrentWizard) wizard).trackers.get(0); if(list.size() > 0) list.remove(0); list.add(url); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/maketorrent/SingleFilePanel.java0000644000175000017500000001252710636371006025617 0ustar adrianadrian/* * File : SingleFilePanel.java Created : 30 sept. 2003 02:50:19 By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.maketorrent; import java.io.File; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; /** * @author Olivier * */ public class SingleFilePanel extends AbstractWizardPanel { private Text file; public SingleFilePanel(NewTorrentWizard wizard, AbstractWizardPanel previous) { super(wizard, previous); } /* * (non-Javadoc) * * @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#show() */ public void show() { wizard.setTitle(MessageText.getString("wizard.singlefile")); wizard.setCurrentInfo(MessageText.getString("wizard.choosefile")); Composite panel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); Label label = new Label(panel, SWT.NULL); Messages.setLanguageText(label, "wizard.file"); file = new Text(panel, SWT.BORDER); file.addModifyListener(new ModifyListener() { /* * (non-Javadoc) * * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent) */ public void modifyText(ModifyEvent arg0) { String fName = file.getText(); ((NewTorrentWizard) wizard).singlePath = fName; String error = ""; if (!fName.equals("")) { File f = new File(file.getText()); if (!f.exists() || f.isDirectory()) { error = MessageText.getString("wizard.invalidfile"); }else{ String parent = f.getParent(); if ( parent != null ){ ((NewTorrentWizard) wizard).setDefaultOpenDir( parent ); } } } wizard.setErrorMessage(error); wizard.setNextEnabled(!((NewTorrentWizard) wizard).singlePath.equals("") && error.equals("")); } }); file.setText(((NewTorrentWizard) wizard).singlePath); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); file.setLayoutData(gridData); Button browse = new Button(panel, SWT.PUSH); browse.addListener(SWT.Selection, new Listener() { /* * (non-Javadoc) * * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event arg0) { FileDialog fd = new FileDialog(wizard.getWizardWindow()); if (wizard.getErrorMessage().equals("") && !((NewTorrentWizard) wizard).singlePath.equals("")) { fd.setFileName(((NewTorrentWizard) wizard).singlePath); }else{ String def = ((NewTorrentWizard) wizard).getDefaultOpenDir(); if ( def.length() > 0 & new File(def).isDirectory() ){ fd.setFilterPath( def ); } } String f = fd.open(); if (f != null){ file.setText(f); File ff = new File(f); String parent = ff.getParent(); if ( parent != null ){ ((NewTorrentWizard) wizard).setDefaultOpenDir( parent ); } } } }); Messages.setLanguageText(browse, "wizard.browse"); label = new Label(panel, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; label.setLayoutData(gridData); label.setText("\n"); label = new Label(panel, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; label.setLayoutData(gridData); label.setForeground(Colors.blue); Messages.setLanguageText(label, "wizard.hint.file"); } /* * (non-Javadoc) * * @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#getNextPanel() */ public IWizardPanel getNextPanel() { // TODO Auto-generated method stub return new SavePathPanel(((NewTorrentWizard) wizard), this); } public void setFilename(String filename) { file.setText(filename); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/maketorrent/MultiTrackerEditor.java0000644000175000017500000003413211307316614026367 0ustar adrianadrian/* * File : MultiTrackerEditor.java * Created : 3 déc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.maketorrent; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TreeEditor; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * @author Olivier * */ public class MultiTrackerEditor { TrackerEditorListener listener; String oldName; String currentName; boolean anonymous; List trackers; Display display; Shell shell; Text textName; Tree treeGroups; TreeEditor editor; TreeItem itemEdited; Button btnSave; Button btnCancel; Menu menu; public MultiTrackerEditor(String name,List trackers,TrackerEditorListener listener) { this( name, trackers, listener, false ); } public MultiTrackerEditor( String name, List trackers, TrackerEditorListener listener, boolean _anonymous ) { this.oldName = name; if(name != null) this.currentName = name; else this.currentName = ""; this.listener = listener; anonymous = _anonymous; this.trackers = new ArrayList(trackers); createWindow(); } private void createWindow() { this.display = Display.getCurrent(); this.shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL | SWT.RESIZE); Messages.setLanguageText(this.shell,"wizard.multitracker.edit.title"); Utils.setShellIcon(shell); GridLayout layout = new GridLayout(); layout.numColumns = 3; shell.setLayout(layout); GridData gridData; if ( !anonymous ){ Label labelName = new Label(shell,SWT.NULL); Messages.setLanguageText(labelName,"wizard.multitracker.edit.name"); textName = new Text(shell,SWT.BORDER); textName.setText(currentName); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; textName.setLayoutData(gridData); textName.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent arg0) { currentName = textName.getText(); computeSaveEnable(); } }); } treeGroups = new Tree(shell,SWT.BORDER); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 3; gridData.heightHint = 150; treeGroups.setLayoutData(gridData); treeGroups.addMouseListener( new MouseAdapter() { public void mouseDoubleClick( MouseEvent arg0 ) { if(treeGroups.getSelectionCount() == 1) { TreeItem treeItem = treeGroups.getSelection()[0]; String type = (String) treeItem.getData("type"); if(type.equals("tracker")) { editTreeItem(treeItem); } } } }); Label labelSeparator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; labelSeparator.setLayoutData(gridData); // button row Composite cButtons = new Composite(shell, SWT.NONE); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; cButtons.setLayoutData(gridData); GridLayout layoutButtons = new GridLayout(); layoutButtons.numColumns = 3; cButtons.setLayout(layoutButtons); Label label = new Label(cButtons,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL ); label.setLayoutData(gridData); btnSave = new Button(cButtons,SWT.PUSH); gridData = new GridData(); gridData.widthHint = 70; gridData.horizontalAlignment = GridData.END; btnSave.setLayoutData(gridData); Messages.setLanguageText(btnSave,"wizard.multitracker.edit.save"); btnSave.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { update(); shell.dispose(); } }); btnCancel = new Button(cButtons,SWT.PUSH); gridData = new GridData(); gridData.horizontalAlignment = GridData.END; gridData.widthHint = 70; btnCancel.setLayoutData(gridData); Messages.setLanguageText(btnCancel,"Button.cancel"); btnCancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { shell.dispose(); } }); shell.setDefaultButton( btnSave ); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ shell.dispose(); } } }); computeSaveEnable(); refresh(); constructMenu(); editor = new TreeEditor (treeGroups); treeGroups.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent arg0) { if(itemEdited != null && !editor.getEditor().isDisposed()) itemEdited.setText(((Text)editor.getEditor()).getText()); removeEditor(); } }); Point size = shell.computeSize(400,SWT.DEFAULT); shell.setSize(size); Utils.centreWindow( shell ); shell.open(); } private void update() { trackers = new ArrayList(); TreeItem[] groupItems = treeGroups.getItems(); for(int i = 0 ; i < groupItems.length ; i++) { TreeItem group = groupItems[i]; TreeItem[] trackerItems = group.getItems(); List groupList = new ArrayList(group.getItemCount()); for(int j = 0 ; j < trackerItems.length ; j++) { groupList.add(trackerItems[j].getText()); } trackers.add(groupList); } listener.trackersChanged(oldName,currentName,trackers); oldName = currentName; } private void computeSaveEnable() { boolean enabled = anonymous || !("".equals(currentName)); if ( enabled ){ TreeItem[] groupItems = treeGroups.getItems(); outer: for(int i = 0 ; i < groupItems.length ; i++) { TreeItem group = groupItems[i]; TreeItem[] trackerItems = group.getItems(); for(int j = 0 ; j < trackerItems.length ; j++) { if ( ! validURL(trackerItems[j].getText())){ enabled = false; break outer; } } } } if ( enabled != btnSave.getEnabled()){ btnSave.setEnabled( enabled ); } } private void refresh() { treeGroups.removeAll(); Iterator iter = trackers.iterator(); while(iter.hasNext()) { List trackerGroup = (List) iter.next(); TreeItem itemRoot = newGroup(); Iterator iter2 = trackerGroup.iterator(); while(iter2.hasNext()) { String url = (String) iter2.next(); newTracker(itemRoot,url); } } } private void constructMenu() { menu = new Menu(shell,SWT.NULL); menu.addListener(SWT.Show, new Listener() { public void handleEvent(Event e) { //1. Empty the menu MenuItem[] items = menu.getItems(); for(int i = 0 ; i < items.length ; i++) { items[i].dispose(); } //2. Test for the number of element selected // should be 1 if(treeGroups.getSelectionCount() != 1) { MenuItem item = new MenuItem(menu,SWT.NULL); Messages.setLanguageText(item,"wizard.multitracker.edit.newgroup"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { TreeItem group = newGroup(); TreeItem itemTracker = newTracker(group,"http://"); editTreeItem(itemTracker); } }); return; } //3. Grab the element final TreeItem treeItem = treeGroups.getSelection()[0]; String type = (String) treeItem.getData("type"); if(type.equals("tracker")) { //The Tracker menu MenuItem item = new MenuItem(menu,SWT.NULL); Messages.setLanguageText(item,"wizard.multitracker.edit.deletetracker"); item.addListener(SWT.Selection,new Listener(){ public void handleEvent(Event arg0) { treeItem.dispose(); } }); item = new MenuItem(menu,SWT.NULL); Messages.setLanguageText(item,"wizard.multitracker.edit.edit"); item.addListener(SWT.Selection,new Listener(){ public void handleEvent(Event arg0) { editTreeItem(treeItem); } }); } else if(type.equals("group")) { //The Group menu MenuItem item = new MenuItem(menu,SWT.NULL); Messages.setLanguageText(item,"wizard.multitracker.edit.newgroup"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { TreeItem group = newGroup(); TreeItem itemTracker = newTracker(group,"http://"); editTreeItem(itemTracker); } }); item = new MenuItem(menu,SWT.NULL); Messages.setLanguageText(item,"wizard.multitracker.edit.deletegroup"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { TreeItem[] subItems = treeItem.getItems(); for(int i = 0 ; i < subItems.length ; i++) { subItems[i].dispose(); } treeItem.dispose(); } }); new MenuItem(menu,SWT.SEPARATOR); item = new MenuItem(menu,SWT.NULL); Messages.setLanguageText(item,"wizard.multitracker.edit.newtracker"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { TreeItem itemTracker = newTracker(treeItem,"http://"); editTreeItem(itemTracker); } }); /* new MenuItem(menu,SWT.SEPARATOR); item = new MenuItem(menu,SWT.NULL); Messages.setLanguageText(item,"wizard.multitracker.edit.tracker.moveUp"); item = new MenuItem(menu,SWT.NULL); Messages.setLanguageText(item,"wizard.multitracker.edit.tracker.moveDown"); */ } } }); treeGroups.setMenu(menu); } private void editTreeItem(final TreeItem item) { // Clean up any previous editor control Control oldEditor = editor.getEditor(); if (oldEditor != null) oldEditor.dispose(); itemEdited = item; // The control that will be the editor must be a child of the Tree final Text text = new Text(treeGroups, SWT.BORDER); text.setText(item.getText()); text.setForeground(item.getForeground()); text.setSelection(item.getText().length()); text.addListener (SWT.DefaultSelection, new Listener () { public void handleEvent (Event e) { String url = text.getText(); if ( validURL(url)){ text.setForeground( null ); item.setForeground( null ); }else{ text.setForeground( Colors.colorError ); item.setForeground( Colors.colorError ); } item.setText(url); computeSaveEnable(); removeEditor(); } }); text.addListener(SWT.Modify, new Listener() { public void handleEvent (Event e) { String url = text.getText(); if ( validURL(url)){ text.setForeground( null ); item.setForeground( null ); }else{ text.setForeground( Colors.colorError ); item.setForeground( Colors.colorError ); } item.setText(url); computeSaveEnable(); } }); text.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent keyEvent) { if(keyEvent.character == SWT.ESC) { removeEditor(); } } }); //The text editor must have the same size as the cell and must //not be any smaller than 50 pixels. editor.horizontalAlignment = SWT.LEFT; editor.grabHorizontal = true; editor.minimumWidth = 50; Rectangle r = text.computeTrim(0, 0, 100, text.getLineHeight()); editor.minimumHeight = r.height; // Open the text editor on the selected row. editor.setEditor (text, item); // Assign focus to the text control text.setFocus (); } private boolean validURL( String str ) { try{ URL url = new URL(str); String prot = url.getProtocol().toLowerCase(); if ( prot.equals( "http") || prot.equals( "https" ) || prot.equals( "udp") || prot.equals( "dht")){ return( true ); } return( false ); }catch( Throwable e ){ return( false ); } } private void removeEditor() { Control oldEditor = editor.getEditor(); if (oldEditor != null) oldEditor.dispose(); } private TreeItem newGroup() { TreeItem item = new TreeItem(treeGroups,SWT.NULL); item.setData("type","group"); Messages.setLanguageText(item, "wizard.multitracker.group"); return item; } private TreeItem newTracker(TreeItem root,String url) { TreeItem item = new TreeItem(root,SWT.NULL); item.setText(url); item.setData("type","tracker"); root.setExpanded(true); return item; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/maketorrent/NewTorrentWizard.java0000644000175000017500000001615411171750562026111 0ustar adrianadrian/* * File : Wizard.java Created : 12 oct. 2003 14:30:57 By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.maketorrent; import java.io.File; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.torrent.TOTorrentCreator; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.ui.swt.URLTransfer; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.wizard.Wizard; /** * @author Olivier * */ public class NewTorrentWizard extends Wizard { static final int TT_LOCAL = 1; static final int TT_EXTERNAL = 2; static final int TT_DECENTRAL = 3; static final String TT_EXTERNAL_DEFAULT = "http://"; static final String TT_DECENTRAL_DEFAULT = TorrentUtils.getDecentralisedEmptyURL().toString(); private static String default_open_dir = COConfigurationManager.getStringParameter( "CreateTorrent.default.open", "" ); private static String default_save_dir = COConfigurationManager.getStringParameter( "CreateTorrent.default.save", "" ); private static String comment = COConfigurationManager.getStringParameter( "CreateTorrent.default.comment", "" ); private static int tracker_type = COConfigurationManager.getIntParameter( "CreateTorrent.default.trackertype", TT_LOCAL ); static{ // default the default to the "save torrents to" location if ( default_save_dir.length() == 0 ){ default_save_dir = COConfigurationManager.getStringParameter( "General_sDefaultTorrent_Directory", "" ); } } //false : singleMode, true: directory boolean create_from_dir; String singlePath = ""; String directoryPath = ""; String savePath = ""; String trackerURL = TT_EXTERNAL_DEFAULT; boolean computed_piece_size = true; long manual_piece_size; boolean useMultiTracker = false; boolean useWebSeed = false; private boolean addOtherHashes = COConfigurationManager.getBooleanParameter( "CreateTorrent.default.addhashes", false ); String multiTrackerConfig = ""; List trackers = new ArrayList(); String webSeedConfig = ""; Map webseeds = new HashMap(); boolean autoOpen = false; boolean autoHost = false; boolean permitDHT = true; boolean privateTorrent = false; TOTorrentCreator creator = null; public NewTorrentWizard( Display display) { super("wizard.title"); cancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { if(creator != null) creator.cancel(); } }); trackers.add(new ArrayList()); trackerURL = Utils.getLinkFromClipboard(display,false); ModePanel panel = new ModePanel(this, null); createDropTarget(getWizardWindow()); this.setFirstPanel(panel); } protected int getTrackerType() { return( tracker_type ); } protected void setTrackerType( int type ) { tracker_type = type; COConfigurationManager.setParameter( "CreateTorrent.default.trackertype", tracker_type ); } protected String getDefaultOpenDir() { return( default_open_dir ); } protected void setDefaultOpenDir( String d ) { default_open_dir = d; COConfigurationManager.setParameter( "CreateTorrent.default.open", default_open_dir ); } protected String getDefaultSaveDir() { return( default_save_dir ); } protected void setDefaultSaveDir( String d ) { default_save_dir = d; COConfigurationManager.setParameter( "CreateTorrent.default.save", default_save_dir ); } void setComment(String s) { comment = s; COConfigurationManager.setParameter("CreateTorrent.default.comment",comment); } String getComment() { return (comment); } private void createDropTarget(final Control control) { DropTarget dropTarget = new DropTarget(control, DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK); dropTarget.setTransfer(new Transfer[] { URLTransfer.getInstance(), FileTransfer.getInstance()}); dropTarget.addDropListener(new DropTargetAdapter() { public void dragOver(DropTargetEvent event) { if(URLTransfer.getInstance().isSupportedType(event.currentDataType)) { event.detail = getCurrentPanel() instanceof ModePanel ? DND.DROP_LINK : DND.DROP_NONE; } } public void drop(DropTargetEvent event) { if (event.data instanceof String[]) { String[] sourceNames = (String[]) event.data; if (sourceNames == null || sourceNames.length != 1) event.detail = DND.DROP_NONE; if (event.detail == DND.DROP_NONE) return; File droppedFile = new File(sourceNames[0]); if (getCurrentPanel() instanceof ModePanel) { if (droppedFile.isFile()) { singlePath = droppedFile.getAbsolutePath(); ((ModePanel) getCurrentPanel()).activateMode(true); } else if (droppedFile.isDirectory()) { directoryPath = droppedFile.getAbsolutePath(); ((ModePanel) getCurrentPanel()).activateMode(false); } } else if (getCurrentPanel() instanceof DirectoryPanel) { if (droppedFile.isDirectory()) ((DirectoryPanel) getCurrentPanel()).setFilename(droppedFile.getAbsolutePath()); } else if (getCurrentPanel() instanceof SingleFilePanel) { if (droppedFile.isFile()) ((SingleFilePanel) getCurrentPanel()).setFilename(droppedFile.getAbsolutePath()); } } else if (getCurrentPanel() instanceof ModePanel) { trackerURL = ((URLTransfer.URLType)event.data).linkURL; ((ModePanel) getCurrentPanel()).updateTrackerURL(); } } }); } protected void setPieceSizeComputed() { computed_piece_size = true; } public boolean getPieceSizeComputed() { return( computed_piece_size ); } protected void setPieceSizeManual( long _value ) { computed_piece_size = false; manual_piece_size = _value; } protected long getPieceSizeManual() { return( manual_piece_size ); } protected void setAddOtherHashes( boolean o ) { addOtherHashes = o; COConfigurationManager.setParameter( "CreateTorrent.default.addhashes", addOtherHashes ); } protected boolean getAddOtherHashes() { return( addOtherHashes ); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/maketorrent/WebSeedPanel.java0000644000175000017500000002026710672622606025121 0ustar adrianadrian/* * File : ModePanel.java Created : 30 sept. 2003 01:51:05 By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.maketorrent; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.TrackersUtil; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; /** * @author Olivier * */ public class WebSeedPanel extends AbstractWizardPanel implements WebSeedsEditorListener{ private Combo configList; private Tree configDetails; private Button btnNew; private Button btnEdit; private Button btnDelete; public WebSeedPanel(NewTorrentWizard wizard, AbstractWizardPanel previous) { super(wizard, previous); } /* * (non-Javadoc) * * @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#show() */ public void show() { wizard.setTitle(MessageText.getString("wizard.webseed.title")); wizard.setCurrentInfo(""); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); //Line : // Web Seed Configuration final Label labelTitle = new Label(panel,SWT.NULL); Messages.setLanguageText(labelTitle, "wizard.webseed.configuration"); gridData = new GridData(); gridData.horizontalSpan = 3; labelTitle.setLayoutData(gridData); configList = new Combo(panel,SWT.READ_ONLY); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; configList.setLayoutData(gridData); configList.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { updateWebSeeds(); refreshDetails(); } }); btnNew = new Button(panel, SWT.PUSH); Messages.setLanguageText(btnNew, "wizard.multitracker.new"); gridData = new GridData(); gridData.widthHint = 100; btnNew.setLayoutData(gridData); btnNew.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { Map webseeds = new HashMap(); webseeds.put( "getright", new ArrayList()); webseeds.put( "webseed", new ArrayList()); new WebSeedsEditor(null,webseeds,WebSeedPanel.this); } }); btnEdit = new Button(panel, SWT.PUSH); Messages.setLanguageText(btnEdit, "wizard.multitracker.edit"); gridData = new GridData(); gridData.widthHint = 100; btnEdit.setLayoutData(gridData); btnEdit.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { int selection = configList.getSelectionIndex(); String selected = configList.getItem(selection); Map webseeds = TrackersUtil.getInstance().getWebSeeds(); new WebSeedsEditor(selected,(Map)webseeds.get(selected),WebSeedPanel.this); } }); btnDelete = new Button(panel, SWT.PUSH); Messages.setLanguageText(btnDelete, "wizard.multitracker.delete"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); gridData.widthHint = 100; btnDelete.setLayoutData(gridData); btnDelete.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { int selection = configList.getSelectionIndex(); String selected = configList.getItem(selection); TrackersUtil.getInstance().removeWebSeed(selected); refreshList(""); refreshDetails(); setEditDeleteEnable(); } }); final Label labelSeparator = new Label(panel,SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; labelSeparator.setLayoutData(gridData); configDetails = new Tree(panel,SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.heightHint = 150; gridData.horizontalSpan = 3; configDetails.setLayoutData(gridData); refreshList(((NewTorrentWizard)wizard).webSeedConfig); refreshDetails(); setEditDeleteEnable(); } /* * (non-Javadoc) * * @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#getNextPanel() */ public IWizardPanel getNextPanel() { if (((NewTorrentWizard) wizard).create_from_dir) { return new DirectoryPanel(((NewTorrentWizard) wizard), this); } else { return new SingleFilePanel(((NewTorrentWizard) wizard), this); } } public boolean isNextEnabled() { return true; } void refreshDetails() { configDetails.removeAll(); Map webseeds = ((NewTorrentWizard) wizard).webseeds; Iterator iter = webseeds.entrySet().iterator(); while(iter.hasNext()) { Map.Entry entry = (Map.Entry)iter.next(); TreeItem itemRoot = new TreeItem(configDetails,SWT.NULL); itemRoot.setText((String)entry.getKey()); Iterator iter2 = ((List)entry.getValue()).iterator(); while(iter2.hasNext()) { String url = (String) iter2.next(); new TreeItem(itemRoot,SWT.NULL).setText(url); } itemRoot.setExpanded(true); } } void setEditDeleteEnable() { if(configList.getItemCount() > 0) { btnEdit.setEnabled(true); btnDelete.setEnabled(true); } else { btnEdit.setEnabled(false); btnDelete.setEnabled(false); } } public void webSeedsChanged(String oldName, String newName, Map ws) { TrackersUtil util = TrackersUtil.getInstance(); if(oldName != null && !oldName.equals(newName)) util.removeWebSeed(oldName); util.addWebSeed(newName,ws); refreshList(newName); refreshDetails(); setEditDeleteEnable(); } private void refreshList(String toBeSelected) { Map webseeds = TrackersUtil.getInstance().getWebSeeds(); configList.removeAll(); Iterator iter = webseeds.keySet().iterator(); while(iter.hasNext()) { configList.add((String)iter.next()); } int selection = configList.indexOf(toBeSelected); if(selection != -1) { configList.select(selection); } else if(configList.getItemCount() > 0) { configList.select(0); } updateWebSeeds(); } private void updateWebSeeds() { int selection = configList.getSelectionIndex(); if(selection == -1) { ((NewTorrentWizard)wizard).webSeedConfig = ""; ((NewTorrentWizard)wizard).webseeds = new HashMap(); setNext(); return; } String selected = configList.getItem(selection); ((NewTorrentWizard)wizard).webSeedConfig = selected; Map webseeds = TrackersUtil.getInstance().getWebSeeds(); ((NewTorrentWizard)wizard).webseeds = (Map) webseeds.get(selected); setNext(); } private void setNext() { wizard.setNextEnabled(true); wizard.setErrorMessage(""); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/maketorrent/TrackerEditorListener.java0000644000175000017500000000205711147747214027071 0ustar adrianadrian/* * File : TrackerEditorListener.java * Created : 3 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.maketorrent; import java.util.List; /** * @author Olivier * */ public interface TrackerEditorListener { public void trackersChanged(String oldName,String newName,List> trackers); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditorListener.java0000644000175000017500000000204010672622606027166 0ustar adrianadrian/* * File : TrackerEditorListener.java * Created : 3 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.maketorrent; import java.util.Map; /** * @author Olivier * */ public interface WebSeedsEditorListener { public void webSeedsChanged(String oldName,String newName,Map webseeds); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditor.java0000644000175000017500000003064511272724632025473 0ustar adrianadrian/* * File : MultiTrackerEditor.java * Created : 3 déc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.maketorrent; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TreeEditor; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import java.net.URL; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.ArrayList; /** * @author Olivier * */ public class WebSeedsEditor { WebSeedsEditorListener listener; String oldName; String currentName; boolean anonymous; Map webseeds; Display display; Shell shell; Text textName; Tree treeGroups; TreeEditor editor; TreeItem itemEdited; Button btnSave; Button btnCancel; Menu menu; public WebSeedsEditor(String name,Map webseeds,WebSeedsEditorListener listener) { this( name, webseeds, listener, false ); } public WebSeedsEditor( String name, Map webseeds, WebSeedsEditorListener listener, boolean _anonymous ) { this.oldName = name; if(name != null) this.currentName = name; else this.currentName = ""; this.listener = listener; anonymous = _anonymous; this.webseeds = new HashMap(webseeds); createWindow(); } private void createWindow() { this.display = Display.getCurrent(); this.shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); Messages.setLanguageText(this.shell,"wizard.webseedseditor.edit.title"); Utils.setShellIcon(shell); GridLayout layout = new GridLayout(); layout.numColumns = 3; shell.setLayout(layout); GridData gridData; if ( !anonymous ){ Label labelName = new Label(shell,SWT.NULL); Messages.setLanguageText(labelName,"wizard.multitracker.edit.name"); textName = new Text(shell,SWT.BORDER); textName.setText(currentName); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; textName.setLayoutData(gridData); textName.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent arg0) { currentName = textName.getText(); computeSaveEnable(); } }); } treeGroups = new Tree(shell,SWT.BORDER); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 3; gridData.heightHint = 150; treeGroups.setLayoutData(gridData); treeGroups.addMouseListener( new MouseAdapter() { public void mouseDoubleClick( MouseEvent arg0 ) { if(treeGroups.getSelectionCount() == 1) { TreeItem treeItem = treeGroups.getSelection()[0]; String type = (String) treeItem.getData("type"); if(type.equals("tracker")) { editTreeItem(treeItem); } } } }); Label labelSeparator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; labelSeparator.setLayoutData(gridData); // button row Label label = new Label(shell,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL ); label.setLayoutData(gridData); Composite cButtons = new Composite(shell, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; cButtons.setLayoutData(gridData); GridLayout layoutButtons = new GridLayout(); layoutButtons.numColumns = 3; cButtons.setLayout(layoutButtons); label = new Label(cButtons,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL ); label.setLayoutData(gridData); btnSave = new Button(cButtons,SWT.PUSH); gridData = new GridData(); gridData.widthHint = 70; gridData.horizontalAlignment = GridData.END; btnSave.setLayoutData(gridData); Messages.setLanguageText(btnSave,"wizard.multitracker.edit.save"); btnSave.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { update(); shell.dispose(); } }); btnCancel = new Button(cButtons,SWT.PUSH); gridData = new GridData(); gridData.horizontalAlignment = GridData.END; gridData.widthHint = 70; btnCancel.setLayoutData(gridData); Messages.setLanguageText(btnCancel,"Button.cancel"); btnCancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { shell.dispose(); } }); shell.setDefaultButton( btnSave ); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ shell.dispose(); } } }); computeSaveEnable(); refresh(); constructMenu(); editor = new TreeEditor (treeGroups); treeGroups.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent arg0) { if(itemEdited != null && !editor.getEditor().isDisposed()) itemEdited.setText(((Text)editor.getEditor()).getText()); removeEditor(); } }); shell.pack(); Point size = shell.computeSize(400,SWT.DEFAULT); shell.setSize(size); Utils.centreWindow( shell ); shell.open(); } private void update() { webseeds = new HashMap(); TreeItem[] groupItems = treeGroups.getItems(); for(int i = 0 ; i < groupItems.length ; i++) { TreeItem group = groupItems[i]; TreeItem[] trackerItems = group.getItems(); List groupList = new ArrayList(group.getItemCount()); for(int j = 0 ; j < trackerItems.length ; j++) { groupList.add(trackerItems[j].getText()); } webseeds.put(group.getText(),groupList); } listener.webSeedsChanged(oldName,currentName,webseeds); oldName = currentName; } private void computeSaveEnable() { boolean enabled = anonymous || !("".equals(currentName)); if ( enabled ){ TreeItem[] groupItems = treeGroups.getItems(); outer: for(int i = 0 ; i < groupItems.length ; i++) { TreeItem group = groupItems[i]; TreeItem[] trackerItems = group.getItems(); for(int j = 0 ; j < trackerItems.length ; j++) { if ( ! validURL(trackerItems[j].getText())){ enabled = false; break outer; } } } } if ( enabled != btnSave.getEnabled()){ btnSave.setEnabled( enabled ); } } private void refresh() { treeGroups.removeAll(); Iterator iter = webseeds.entrySet().iterator(); while(iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); TreeItem itemRoot = newGroup((String)entry.getKey()); Iterator iter2 = ((List)entry.getValue()).iterator(); while(iter2.hasNext()) { String url = (String) iter2.next(); newTracker(itemRoot,url); } } } private void constructMenu() { menu = new Menu(shell,SWT.NULL); menu.addListener(SWT.Show, new Listener() { public void handleEvent(Event e) { //1. Empty the menu MenuItem[] items = menu.getItems(); for(int i = 0 ; i < items.length ; i++) { items[i].dispose(); } //3. Grab the element final TreeItem treeItem = treeGroups.getSelection()[0]; String type = (String) treeItem.getData("type"); if(type.equals("tracker")) { //The Tracker menu MenuItem item = new MenuItem(menu,SWT.NULL); Messages.setLanguageText(item,"wizard.multitracker.edit.deletetracker"); item.addListener(SWT.Selection,new Listener(){ public void handleEvent(Event arg0) { treeItem.dispose(); } }); item = new MenuItem(menu,SWT.NULL); Messages.setLanguageText(item,"wizard.multitracker.edit.edit"); item.addListener(SWT.Selection,new Listener(){ public void handleEvent(Event arg0) { editTreeItem(treeItem); } }); } else if(type.equals("group")) { //The Group menu MenuItem item = new MenuItem(menu,SWT.NULL); Messages.setLanguageText(item,"wizard.webseedseditor.edit.newseed"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { TreeItem itemTracker = newTracker(treeItem,"http://"); editTreeItem(itemTracker); } }); } } }); treeGroups.setMenu(menu); } private void editTreeItem(final TreeItem item) { // Clean up any previous editor control Control oldEditor = editor.getEditor(); if (oldEditor != null) oldEditor.dispose(); itemEdited = item; // The control that will be the editor must be a child of the Tree final Text text = new Text(treeGroups, SWT.BORDER); text.setText(item.getText()); text.setForeground(item.getForeground()); text.setSelection(item.getText().length()); text.addListener (SWT.DefaultSelection, new Listener () { public void handleEvent (Event e) { String url = text.getText(); if ( validURL(url)){ text.setForeground( null ); item.setForeground( null ); }else{ text.setForeground( Colors.colorError ); item.setForeground( Colors.colorError ); } item.setText(url); computeSaveEnable(); removeEditor(); } }); text.addListener(SWT.Modify, new Listener() { public void handleEvent (Event e) { String url = text.getText(); if ( validURL(url)){ text.setForeground( null ); item.setForeground( null ); }else{ text.setForeground( Colors.colorError ); item.setForeground( Colors.colorError ); } item.setText(url); computeSaveEnable(); } }); text.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent keyEvent) { if(keyEvent.character == SWT.ESC) { removeEditor(); } } }); //The text editor must have the same size as the cell and must //not be any smaller than 50 pixels. editor.horizontalAlignment = SWT.LEFT; editor.grabHorizontal = true; editor.minimumWidth = 50; Rectangle r = text.computeTrim(0, 0, 100, text.getLineHeight()); editor.minimumHeight = r.height; // Open the text editor on the selected row. editor.setEditor (text, item); // Assign focus to the text control text.setFocus (); } private boolean validURL( String str ) { try{ URL url = new URL(str); String prot = url.getProtocol().toLowerCase(); // don't support https in Az if ( prot.equals( "http" )){ return( true ); } return( false ); }catch( Throwable e ){ return( false ); } } private void removeEditor() { Control oldEditor = editor.getEditor(); if (oldEditor != null) oldEditor.dispose(); } private TreeItem newGroup(String name) { TreeItem item = new TreeItem(treeGroups,SWT.NULL); item.setData("type","group"); item.setText(name); return item; } private TreeItem newTracker(TreeItem root,String url) { TreeItem item = new TreeItem(root,SWT.NULL); item.setText(url); item.setData("type","tracker"); root.setExpanded(true); return item; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/AZProgressBar.java0000644000175000017500000000546110714236064022747 0ustar adrianadrianpackage org.gudy.azureus2.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.ProgressBar; /** * A ProgressBar implementation that allows the on-the-fly switching between determinate and indeterminate modes. * @author knguyen * */ public class AZProgressBar extends Composite { private ProgressBar incrementalProgressBar = null; private ProgressBar indeterminateProgressBar = null; private boolean isIndeterminate = false; private StackLayout stack = null; /** * Construct a progress bar initialized as incremental and no input button * @param parent */ public AZProgressBar(Composite parent) { this(parent, false); } /** * * @param parent * @param isIndeterminate * @param useInputButton determines whether the inputButton is available or not * @param image an Image to display; may be null */ public AZProgressBar(Composite parent, boolean isIndeterminate) { super(parent, SWT.NULL); incrementalProgressBar = new ProgressBar(this, SWT.HORIZONTAL); indeterminateProgressBar = new ProgressBar(this, SWT.HORIZONTAL | SWT.INDETERMINATE); stack = new StackLayout(); setLayout(stack); pack(); setIndeterminate(isIndeterminate); } public void setIndeterminate(boolean isIndeterminate) { if (this.isIndeterminate != isIndeterminate || null == stack.topControl) { this.isIndeterminate = isIndeterminate; if (true == isIndeterminate) { stack.topControl = indeterminateProgressBar; } else { incrementalProgressBar.setMinimum(0); incrementalProgressBar.setMaximum(100); incrementalProgressBar.setSelection(0); stack.topControl = incrementalProgressBar; } layout(); } } public void done() { incrementalProgressBar.setSelection(incrementalProgressBar.getMaximum()); stack.topControl = null; layout(); } public void setSelection(int value) { if (incrementalProgressBar.getMaximum() < value) { done(); } else { incrementalProgressBar.setSelection(value); } } public void setPercentage(final int percentage) { if (percentage > 0 && percentage < 101) { int range = incrementalProgressBar.getMaximum() - incrementalProgressBar.getMinimum(); setSelection(incrementalProgressBar.getMinimum() + (range * percentage / 100)); } } public int getMaximum() { return incrementalProgressBar.getMaximum(); } public int getMinimum() { return incrementalProgressBar.getMinimum(); } public int getSelection() { return incrementalProgressBar.getSelection(); } public void setMaximum(int value) { incrementalProgressBar.setMaximum(value); } public void setMinimum(int value) { incrementalProgressBar.setMinimum(value); } public boolean isIndeterminate() { return isIndeterminate; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/update/0000755000175000017500000000000011310377636020700 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/update/SimpleInstallUI.java0000644000175000017500000001422411156365354024566 0ustar adrianadrian/* * Created on Mar 6, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.ui.swt.update; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ProgressBar; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.update.Update; import org.gudy.azureus2.plugins.update.UpdateCheckInstance; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderAdapter; import org.gudy.azureus2.ui.swt.Utils; public class SimpleInstallUI { private UpdateMonitor monitor; private UpdateCheckInstance instance; private boolean cancelled; private ResourceDownloader current_downloader; protected SimpleInstallUI( UpdateMonitor _monitor, UpdateCheckInstance _instance ) { monitor = _monitor; instance = _instance; try{ monitor.addDecisionHandler(_instance ); Utils.execSWTThread( new Runnable() { public void run() { try{ build(); }catch( Throwable e ){ Debug.out( e ); instance.cancel(); } } }); }catch( Throwable e ){ Debug.out( e ); instance.cancel(); } } protected void build() { Composite parent = (Composite)instance.getProperty( UpdateCheckInstance.PT_UI_PARENT_SWT_COMPOSITE ); if ( parent != null ){ build( parent ); }else{ throw( new RuntimeException( "borkeroo" )); } } protected void build( Composite parent ) { parent.setLayout(new FormLayout()); Button cancel_button = new Button( parent, SWT.NULL ); cancel_button.setText( "Cancel" ); cancel_button.addListener( SWT.Selection, new Listener() { public void handleEvent( Event arg0 ) { synchronized( SimpleInstallUI.this ){ cancelled = true; if ( current_downloader != null ){ current_downloader.cancel(); } } instance.cancel(); } }); FormData data = new FormData(); data.right = new FormAttachment(100,0); data.top = new FormAttachment(0,0); data.bottom = new FormAttachment(100,0); cancel_button.setLayoutData( data ); final Label label = new Label(parent, SWT.NULL ); label.setText( "blah blah " ); data = new FormData(); data.left = new FormAttachment(0,0); data.top = new FormAttachment(cancel_button,0, SWT.CENTER); label.setLayoutData( data ); final ProgressBar progress = new ProgressBar(parent, SWT.NULL ); progress.setMinimum( 0 ); progress.setMaximum( 100 ); progress.setSelection( 0 ); data = new FormData(); data.left = new FormAttachment(label,4); data.top = new FormAttachment(cancel_button, 0, SWT.CENTER); data.right = new FormAttachment(cancel_button,-4); progress.setLayoutData( data ); parent.layout( true, true ); new AEThread2( "SimpleInstallerUI", true ) { public void run() { try{ Update[] updates = instance.getUpdates(); for ( Update update: updates ){ String name = update.getName(); int pos = name.indexOf('/'); if ( pos >= 0 ){ name = name.substring( pos+1 ); } setLabel( name ); ResourceDownloader[] downloaders = update.getDownloaders(); for ( ResourceDownloader downloader: downloaders ){ synchronized( SimpleInstallUI.this ){ if ( cancelled ){ return; } current_downloader = downloader; } setProgress( 0 ); downloader.addListener( new ResourceDownloaderAdapter() { public void reportPercentComplete( ResourceDownloader downloader, int percentage ) { setProgress( percentage ); } public void reportAmountComplete( ResourceDownloader downloader, long amount ) { } }); downloader.download(); } } boolean restart_required = false; for (int i=0;i 0){ if (update.getRestartRequired() != Update.RESTART_REQUIRED_NO) { bRequiresRestart = true; } if ( update.isMandatory()){ bHadMandatoryUpdates = true; } } } completionCallback.allUpdatesComplete(bRequiresRestart,bHadMandatoryUpdates); } // @see org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderListener#completed(org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader, java.io.InputStream) public boolean completed(ResourceDownloader downloader, InputStream data) { downloader.removeListener(this); if (!nextUpdate()) { // fire in another thread so completed function can exit AEThread thread = new AEThread("AllDownloadsComplete", true) { public void runSupport() { allDownloadsComplete(); } }; thread.start(); } return true; } // @see org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderListener#failed(org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader, org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException) public void failed(ResourceDownloader downloader, ResourceDownloaderException e) { downloader.removeListener(this); iterDownloaders.remove(); nextUpdate(); } // @see org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderListener#reportActivity(org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader, java.lang.String) public void reportActivity(ResourceDownloader downloader, String activity) { } // @see org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderListener#reportAmountComplete(org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader, long) public void reportAmountComplete(ResourceDownloader downloader, long amount) { } // @see org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderListener#reportPercentComplete(org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader, int) public void reportPercentComplete(ResourceDownloader downloader, int percentage) { } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/update/FullUpdateWindow.java0000644000175000017500000001416011273703064024776 0ustar adrianadrian/** * Created on June 29th, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.update; import java.util.Locale; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.*; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import com.aelitis.azureus.ui.UIFunctions; public class FullUpdateWindow { private static Shell current_shell = null; private static Browser browser; public static void handleUpdate( final String url, final UIFunctions.actionListener listener ) { try{ Utils.execSWTThread(new AERunnable() { public void runSupport() { open( url, listener ); } }); }catch( Throwable e ){ Debug.out( e ); listener.actionComplete( false ); } } public static void open( final String url, final UIFunctions.actionListener listener ) { boolean ok = false; final boolean[] listener_informed = { false }; try{ if ( current_shell != null && !current_shell.isDisposed()){ return; } final Shell parentShell = Utils.findAnyShell(); final Shell shell = current_shell = ShellFactory.createShell(parentShell, SWT.BORDER | SWT.APPLICATION_MODAL | SWT.TITLE | SWT.DIALOG_TRIM ); shell.setLayout(new FillLayout()); if (parentShell != null) { parentShell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); } shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { try{ if (parentShell != null) { parentShell.setCursor(e.display.getSystemCursor(SWT.CURSOR_ARROW)); } current_shell = null; }finally{ if ( !listener_informed[0] ){ try{ listener.actionComplete( false ); }catch( Throwable f ){ Debug.out( f ); } } } } }); browser = Utils.createSafeBrowser(shell, SWT.NONE); if (browser == null) { shell.dispose(); return; } browser.addTitleListener(new TitleListener() { public void changed(TitleEvent event) { if (shell == null || shell.isDisposed()) { return; } shell.setText(event.title); } }); browser.addStatusTextListener(new StatusTextListener() { String last = null; public void changed(StatusTextEvent event) { if (shell == null || shell.isDisposed()) { return; } String text = event.text.toLowerCase(); if (last != null && last.equals(text)) { return; } last = text; if ( text.contains("page-loaded")) { Utils.centreWindow(shell); if (parentShell != null) { parentShell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_ARROW)); } shell.open(); } else if (text.startsWith("set-size")){ String[] strings = text.split(" "); if (strings.length > 2){ try { int w = Integer.parseInt(strings[1]); int h = Integer.parseInt(strings[2]); Rectangle computeTrim = shell.computeTrim(0, 0, w, h); shell.setSize(computeTrim.width, computeTrim.height); } catch (Exception e) { } } }else if ( text.contains( "decline" ) || text.contains( "close" )){ Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { shell.dispose(); } }); }else if ( text.contains("accept")){ Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport(){ listener_informed[0] = true; try{ listener.actionComplete( true ); }catch( Throwable e ){ Debug.out( e ); } shell.dispose(); } }); } } }); browser.addLocationListener(new LocationListener() { public void changing(LocationEvent event) { } public void changed(LocationEvent event) { } }); String final_url = url + ( url.indexOf('?')==-1?"?":"&") + "locale=" + Locale.getDefault().toString() + "&azv=" + Constants.AZUREUS_VERSION; SimpleTimer.addEvent( "fullupdate.pageload", SystemTime.getOffsetTime(5000), new TimerEventPerformer() { public void perform(TimerEvent event) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if ( !shell.isDisposed()){ shell.open(); } } }); } }); browser.setUrl(final_url); ok = true; }finally{ if ( !ok ){ try{ listener.actionComplete( false ); }catch( Throwable f ){ Debug.out( f ); } } } } public static void main(String[] args) { try { open( "http://192.168.0.88:8080/client/Update.html", new UIFunctions.actionListener() { public void actionComplete(Object result) { System.out.println( "result=" + result ); //System.exit(1); } }); } catch (Exception e) { e.printStackTrace(); } Display d = Display.getDefault(); while (true) { if (!d.readAndDispatch()) { d.sleep(); } } } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/update/UpdateMonitor.java0000644000175000017500000005050411267524616024344 0ustar adrianadrian/* * Created on 7 mai 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.update; import java.io.File; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.StringListChooser; import org.gudy.azureus2.ui.swt.progress.IProgressReport; import org.gudy.azureus2.ui.swt.progress.IProgressReportConstants; import org.gudy.azureus2.ui.swt.progress.IProgressReporter; import org.gudy.azureus2.ui.swt.progress.IProgressReporterListener; import org.gudy.azureus2.ui.swt.progress.ProgressReportingManager; import org.gudy.azureus2.update.CoreUpdateChecker; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.ui.*; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.update.*; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; /** * @author Olivier Chalouhi * */ public class UpdateMonitor implements UpdateCheckInstanceListener { private static final LogIDs LOGID = LogIDs.GUI; public static final long AUTO_UPDATE_CHECK_PERIOD = 23 * 60 * 60 * 1000; // 23 hours private static final String MSG_PREFIX = "UpdateMonitor.messagebox."; private static UpdateMonitor singleton; private static AEMonitor class_mon = new AEMonitor("UpdateMonitor:class"); public static UpdateMonitor getSingleton(AzureusCore core) { try { class_mon.enter(); if (singleton == null) { singleton = new UpdateMonitor(core); } return (singleton); } finally { class_mon.exit(); } } private AzureusCore azCore; private UpdateWindow current_update_window; private UpdateCheckInstance current_update_instance; private long last_recheck_time; protected UpdateMonitor(AzureusCore _azureus_core) { azCore = _azureus_core; PluginInterface defPI = PluginInitializer.getDefaultInterface(); UpdateManager um = defPI.getUpdateManager(); um.addListener(new UpdateManagerListener() { public void checkInstanceCreated(UpdateCheckInstance instance) { instance.addListener(UpdateMonitor.this); if ( !instance.isLowNoise()){ new updateStatusChanger(instance); } } }); um.addVerificationListener(new UpdateManagerVerificationListener() { public boolean acceptUnVerifiedUpdate(final Update update) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { String title = MessageText.getString(MSG_PREFIX + "accept.unverified.title"); String text = MessageText.getString(MSG_PREFIX + "accept.unverified.text", new String[] { update.getName() }); UIFunctionsUserPrompter prompter = uiFunctions.getUserPrompter(title, text, new String[] { MessageText.getString("Button.yes"), MessageText.getString("Button.no") }, 1); prompter.setRemember(MSG_PREFIX + "accept.unverified", false, MessageText.getString("MessageBoxWindow.nomoreprompting")); prompter.setAutoCloseInMS(0); prompter.open(null); return prompter.waitUntilClosed() == 0; } return false; } public void verificationFailed(final Update update, final Throwable cause) { final String cause_str = Debug.getNestedExceptionMessage(cause); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { String title = MessageText.getString(MSG_PREFIX + "verification.failed.title"); String text = MessageText.getString(MSG_PREFIX + "verification.failed.text", new String[] { update.getName(), cause_str }); uiFunctions.promptUser(title, text, new String[] { MessageText.getString("Button.ok") }, 0, null, null, false, 0, null); } } }); SimpleTimer.addPeriodicEvent("UpdateMon:autocheck", AUTO_UPDATE_CHECK_PERIOD, new TimerEventPerformer() { public void perform(TimerEvent ev) { performAutoCheck(false); } }); DelayedTask delayed_task = UtilitiesImpl.addDelayedTask( "Update Check", new Runnable() { public void run() { // check for non-writeable app dir on non-vista platforms (vista we've got a chance of // elevating perms when updating) and warn user. Particularly useful on OSX when // users haven't installed properly if ( !( Constants.isWindowsVistaOrHigher || SystemProperties.isJavaWebStartInstance())){ String app_str = SystemProperties.getApplicationPath(); if ( !new File(app_str).canWrite()){ final UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if ( uiFunctions != null ){ if ( app_str.endsWith( File.separator )){ app_str = app_str.substring(0, app_str.length()-1); } final String f_app_str = app_str; Utils.execSWTThread( new Runnable() { public void run() { UIFunctionsUserPrompter prompt = uiFunctions.getUserPrompter( MessageText.getString("updater.cant.write.to.app.title"), MessageText.getString("updater.cant.write.to.app.details", new String[]{f_app_str}), new String[]{ MessageText.getString( "Button.ok" )}, 0 ); //prompt.setHtml( "http://a.b.c/" ); prompt.setIconResource( "warning" ); prompt.setRemember( "UpdateMonitor.can.not.write.to.app.dir.2", false, MessageText.getString( "MessageBoxWindow.nomoreprompting" )); prompt.open(null); } }, true ); } } } performAutoCheck(true); } }); delayed_task.queue(); } protected class updateStatusChanger implements IProgressReportConstants { UpdateCheckInstance instance; int check_num = 0; /* * Creates a ProgressReporter for the update process */ IProgressReporter updateReporter = ProgressReportingManager.getInstance().addReporter( MessageText.getString("UpdateWindow.title")); protected updateStatusChanger(UpdateCheckInstance _instance) { instance = _instance; /* * Init reporter and allow cancel */ updateReporter.setReporterType("reporterType_updater"); updateReporter.setCancelAllowed(true); updateReporter.setTitle(MessageText.getString("updater.progress.window.title")); updateReporter.appendDetailMessage(format(instance, "added")); String name = instance.getName(); if (MessageText.keyExists(name)) { updateReporter.setMessage(MessageText.getString(name)); } else { updateReporter.setMessage(name); } updateReporter.setMinimum(0); updateReporter.setMaximum(instance.getCheckers().length); updateReporter.setSelection(check_num, null); /* * Add a listener to the reporter for a cancel event and cancel the update * check instance if the event is detected */ updateReporter.addListener(new IProgressReporterListener() { public int report(IProgressReport progressReport) { if (progressReport.getReportType() == REPORT_TYPE_DONE || progressReport.getReportType() == REPORT_TYPE_ERROR) { return RETVAL_OK_TO_DISPOSE; } if (progressReport.getReportType() == REPORT_TYPE_CANCEL) { if (null != instance) { instance.cancel(); } return RETVAL_OK_TO_DISPOSE; } return RETVAL_OK; } }); /* * Add listener to the running state of the update check instance and forward * to the reporter when they arrive */ instance.addListener(new UpdateCheckInstanceListener() { public void cancelled(UpdateCheckInstance instance) { updateReporter.appendDetailMessage(format(instance, MessageText.getString("Progress.reporting.status.canceled"))); updateReporter.cancel(); } public void complete(UpdateCheckInstance instance) { updateReporter.appendDetailMessage(format(instance, MessageText.getString("Progress.reporting.status.finished"))); updateReporter.setDone(); } }); UpdateChecker[] checkers = instance.getCheckers(); for (int i = 0; i < checkers.length; i++) { final UpdateChecker checker = checkers[i]; /* * Add update check listener to get running state */ checker.addListener(new UpdateCheckerListener() { public void cancelled(UpdateChecker checker) { // we don't count a cancellation as progress step updateReporter.appendDetailMessage(format(checker, MessageText.getString("Progress.reporting.status.canceled"))); } public void completed(UpdateChecker checker) { updateReporter.appendDetailMessage(format(checker, MessageText.getString("Progress.reporting.status.finished"))); updateReporter.setSelection(++check_num, null); } public void failed(UpdateChecker checker) { updateReporter.appendDetailMessage(format(checker, MessageText.getString("Progress.reporting.default.error"))); updateReporter.setSelection(++check_num, null); // notify user of a failed update, use default error message updateReporter.setErrorMessage(null); } }); /* * Add a listener to get the detail messages */ checker.addProgressListener(new UpdateProgressListener() { public void reportProgress(String str) { updateReporter.appendDetailMessage(format(checker, " " + str)); } }); } } } // ============================================================ // Convenience methods for formatting the detail messages for // the update process // ============================================================ private String format(UpdateCheckInstance instance, String str) { String name = instance.getName(); if (MessageText.keyExists(name)) { name = MessageText.getString(name); } return name + " - " + str; } private String format(UpdateChecker checker, String str) { return " " + checker.getComponent().getName() + " - " + str; } protected void requestRecheck() { if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "UpdateMonitor: recheck requested" )); } performCheck( false, true, true, null ); } protected void performAutoCheck(final boolean start_of_day) { boolean check_at_start = false; boolean check_periodic = false; boolean bOldSWT = SWT.getVersion() < 3139; // no update checks for java web start if (!SystemProperties.isJavaWebStartInstance()) { // force check when SWT is really old check_at_start = COConfigurationManager.getBooleanParameter("update.start") || bOldSWT; check_periodic = COConfigurationManager.getBooleanParameter("update.periodic"); } // periodic -> check at start as well check_at_start = check_at_start || check_periodic; if ((check_at_start && start_of_day) || (check_periodic && !start_of_day)) { performCheck(bOldSWT, true, false, null ); // this will implicitly do usage stats } else { new DelayedEvent("UpdateMon:wait2", 5000, new AERunnable() { public void runSupport() { if (start_of_day) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.setStatusText(""); } } CoreUpdateChecker.doUsageStats(); } }); } } public void performCheck( final boolean bForce, final boolean automatic, final boolean isRecheck, final UpdateCheckInstanceListener l ) { long now = SystemTime.getCurrentTime(); if ( isRecheck ){ if ( last_recheck_time > now || now - last_recheck_time < 23*60*60*1000 ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "skipping recheck as consecutive recheck too soon")); return; } last_recheck_time = now; }else{ last_recheck_time = 0; } if (SystemProperties.isJavaWebStartInstance()) { // just in case we get here somehome! if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "skipping update check as java web start")); return; } // kill any existing update window if (current_update_window != null && !current_update_window.isDisposed()) { current_update_window.dispose(); } if (current_update_instance != null) { current_update_instance.cancel(); } UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { // XXX What kind of format is this!? uiFunctions.setStatusText("MainWindow.status.checking ..."); } // take this off this GUI thread in case it blocks for a while AEThread2 t = new AEThread2("UpdateMonitor:kickoff", true) { public void run() { UpdateManager um = PluginInitializer.getDefaultInterface().getUpdateManager(); current_update_instance = um.createUpdateCheckInstance(bForce ? UpdateCheckInstance.UCI_INSTALL : UpdateCheckInstance.UCI_UPDATE, "update.instance.update"); if (!automatic) { current_update_instance.setAutomatic(false); } if (l != null) { current_update_instance.addListener(l); } current_update_instance.start(); } }; t.start(); } public void complete( final UpdateCheckInstance instance) { if ( instance.isLowNoise()){ handleLowNoise( instance ); return; } boolean hasDownloads = false; Update[] us = instance.getUpdates(); // updates with zero-length downloaders exist for admin purposes // and shoudn't cause the window to be shown if only they exist for (int i = 0; i < us.length; i++) { if (us[i].getDownloaders().length > 0) { hasDownloads = true; break; } } try{ int ui = (Integer)instance.getProperty( UpdateCheckInstance.PT_UI_STYLE ); if ( ui == UpdateCheckInstance.PT_UI_STYLE_SIMPLE ){ new SimpleInstallUI( this, instance ); return; } }catch( Throwable e ){ Debug.printStackTrace(e); } // we can get here for either update actions (triggered above) or for plugin // install actions (triggered by the plugin installer) boolean update_action = instance.getType() == UpdateCheckInstance.UCI_UPDATE; UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.setStatusText(""); } // this controls whether or not the update window is displayed // note that we just don't show the window if this is set, we still do the // update check (as amongst other things we want ot know the latest // version of the core anyway if (hasDownloads) { // don't show another update if one's already there! UpdateWindow this_window = null; boolean autoDownload = COConfigurationManager.getBooleanParameter("update.autodownload"); if (update_action) { if (!autoDownload && (current_update_window == null || current_update_window.isDisposed())) { this_window = current_update_window = new UpdateWindow( this, azCore,instance); } } else { // always show an installer window this_window = new UpdateWindow( this, azCore, instance); } if (this_window != null) { for (int i = 0; i < us.length; i++) { if (us[i].getDownloaders().length > 0) { this_window.addUpdate(us[i]); } } this_window.updateAdditionComplete(); } else { if (autoDownload) { new UpdateAutoDownloader(us, new UpdateAutoDownloader.cbCompletion() { public void allUpdatesComplete( boolean requiresRestart, boolean bHadMandatoryUpdates) { Boolean b = (Boolean)instance.getProperty( UpdateCheckInstance.PT_CLOSE_OR_RESTART_ALREADY_IN_PROGRESS ); if ( b != null && b ){ return; } if (requiresRestart) { handleRestart(); }else if ( bHadMandatoryUpdates ){ // no restart and mandatory -> rescan for optional updates now requestRecheck(); } } }); } else { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "UpdateMonitor: user dialog already " + "in progress, updates skipped")); } } } else { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "UpdateMonitor: check instance " + "resulted in no user-actionable updates")); } } public void cancelled(UpdateCheckInstance instance) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.setStatusText(""); } } protected void handleRestart() { final UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { String title = MessageText.getString(MSG_PREFIX + "restart.title"); String text = MessageText.getString(MSG_PREFIX + "restart.text"); uiFunctions.bringToFront(); int timeout = 180000; if (azCore != null && !azCore.getPluginManager().isSilentRestartEnabled()) { timeout = -1; } uiFunctions.promptUser(title, text, new String[] { MessageText.getString("UpdateWindow.restart"), MessageText.getString("UpdateWindow.restartLater") }, 0, null, null, false, timeout, new UserPrompterResultListener() { public void prompterClosed(int result) { if (result == 0) { uiFunctions.dispose(true, false); } } }); } } protected void addDecisionHandler( UpdateCheckInstance instance ) { instance.addDecisionListener( new UpdateManagerDecisionListener() { public Object decide( Update update, int decision_type, String decision_name, String decision_description, Object decision_data ) { if ( decision_type == UpdateManagerDecisionListener.DT_STRING_ARRAY_TO_STRING ){ String[] options = (String[])decision_data; Shell shell = UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell(); if ( shell == null ){ Debug.out( "Shell doesn't exist" ); return( null ); } StringListChooser chooser = new StringListChooser( shell ); chooser.setTitle( decision_name ); chooser.setText( decision_description ); for (int i=0;i 0 (determine that automatically), +1 (downloading), +2 (seeding), +3 (mixed - not used by anything yet) public static void fillTorrentMenu(final Menu menu, final DownloadManager[] dms, final AzureusCore azureus_core, final Composite composite, boolean include_show_details, int selected_dl_types, final TableView tv) { final boolean isSeedingView; switch (selected_dl_types) { case 1: isSeedingView = false; break; case 2: isSeedingView = true; break; case 0: { if (dms.length == 1) { isSeedingView = dms[0].isDownloadComplete(false); break; } } default: // I was going to raise an error, but let's not be too hasty. :) isSeedingView = false; } boolean hasSelection = (dms.length > 0); boolean isTrackerOn = TRTrackerUtils.isTrackerEnabled(); int userMode = COConfigurationManager.getIntParameter("User Mode"); // Enable/Disable Logic boolean bChangeDir = hasSelection; boolean start, stop, changeUrl, barsOpened, forceStart; boolean forceStartEnabled, recheck, manualUpdate, fileMove, fileRescan; changeUrl = barsOpened = manualUpdate = fileMove = fileRescan = true; forceStart = forceStartEnabled = recheck = start = stop = false; boolean canSetSuperSeed = false; boolean superSeedAllYes = true; boolean superSeedAllNo = true; boolean upSpeedDisabled = false; long totalUpSpeed = 0; boolean upSpeedUnlimited = false; long upSpeedSetMax = 0; boolean downSpeedDisabled = false; long totalDownSpeed = 0; boolean downSpeedUnlimited = false; long downSpeedSetMax = 0; boolean allScanSelected = true; boolean allScanNotSelected = true; boolean allStopped = true; if (hasSelection) { for (int i = 0; i < dms.length; i++) { DownloadManager dm = (DownloadManager) dms[i]; try { int maxul = dm.getStats().getUploadRateLimitBytesPerSecond(); if (maxul == 0) { upSpeedUnlimited = true; } else { if (maxul > upSpeedSetMax) { upSpeedSetMax = maxul; } } if (maxul == -1) { maxul = 0; upSpeedDisabled = true; } totalUpSpeed += maxul; int maxdl = dm.getStats().getDownloadRateLimitBytesPerSecond(); if (maxdl == 0) { downSpeedUnlimited = true; } else { if (maxdl > downSpeedSetMax) { downSpeedSetMax = maxdl; } } if (maxdl == -1) { maxdl = 0; downSpeedDisabled = true; } totalDownSpeed += maxdl; } catch (Exception ex) { Debug.printStackTrace(ex); } if (barsOpened && !DownloadBar.getManager().isOpen(dm)) { barsOpened = false; } stop = stop || ManagerUtils.isStopable(dm); start = start || ManagerUtils.isStartable(dm); recheck = recheck || dm.canForceRecheck(); forceStartEnabled = forceStartEnabled || ManagerUtils.isForceStartable(dm); forceStart = forceStart || dm.isForceStart(); boolean stopped = ManagerUtils.isStopped(dm); allStopped &= stopped; fileMove = fileMove && dm.canMoveDataFiles(); if (userMode < 2) { TRTrackerAnnouncer trackerClient = dm.getTrackerClient(); if (trackerClient != null) { boolean update_state = ((SystemTime.getCurrentTime() / 1000 - trackerClient.getLastUpdateTime() >= TRTrackerAnnouncer.REFRESH_MINIMUM_SECS)); manualUpdate = manualUpdate & update_state; } } int state = dm.getState(); bChangeDir &= (state == DownloadManager.STATE_ERROR || state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_QUEUED);; /** * Only perform a test on disk if: * 1) We are currently set to allow the "Change Data Directory" option, and * 2) We've only got one item selected - otherwise, we may potentially end up checking massive * amounts of files across multiple torrents before we generate a menu. */ if (bChangeDir && dms.length == 1) { bChangeDir = dm.isDataAlreadyAllocated() && !dm.filesExist( true ); } boolean scan = dm.getDownloadState().getFlag(DownloadManagerState.FLAG_SCAN_INCOMPLETE_PIECES); // include DND files in incomplete stat, since a recheck may // find those files have been completed boolean incomplete = !dm.isDownloadComplete(true); allScanSelected = incomplete && allScanSelected && scan; allScanNotSelected = incomplete && allScanNotSelected && !scan; PEPeerManager pm = dm.getPeerManager(); if (pm != null) { if (pm.canToggleSuperSeedMode()) { canSetSuperSeed = true; } if (pm.isSuperSeedMode()) { superSeedAllYes = false; } else { superSeedAllNo = false; } } else { superSeedAllYes = false; superSeedAllNo = false; } } fileRescan = allScanSelected || allScanNotSelected; } else { // empty right-click barsOpened = false; forceStart = false; forceStartEnabled = false; start = false; stop = false; fileMove = false; fileRescan = false; upSpeedDisabled = true; downSpeedDisabled = true; changeUrl = false; recheck = false; manualUpdate = false; } // === Root Menu === if (bChangeDir) { MenuItem menuItemChangeDir = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(menuItemChangeDir, "MyTorrentsView.menu.changeDirectory"); menuItemChangeDir.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { changeDirSelectedTorrents(dms, composite.getShell()); } }); } // Open Details if (include_show_details) { final MenuItem itemDetails = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemDetails, "MyTorrentsView.menu.showdetails"); menu.setDefaultItem(itemDetails); Utils.setMenuItemImage(itemDetails, "details"); itemDetails.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_DM_DETAILS, dm); } } }); itemDetails.setEnabled(hasSelection); } // Open Bar final MenuItem itemBar = new MenuItem(menu, SWT.CHECK); Messages.setLanguageText(itemBar, "MyTorrentsView.menu.showdownloadbar"); Utils.setMenuItemImage(itemBar, "downloadBar"); itemBar.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { if (DownloadBar.getManager().isOpen(dm)) { DownloadBar.close(dm); } else { DownloadBar.open(dm, menu.getShell()); } } // run }); itemBar.setEnabled(hasSelection); itemBar.setSelection(barsOpened); // --- new MenuItem(menu, SWT.SEPARATOR); // Run Data File final MenuItem itemOpen = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemOpen, "MyTorrentsView.menu.open"); Utils.setMenuItemImage(itemOpen, "run"); itemOpen.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager[] dms) { runTorrents(dms); } }); itemOpen.setEnabled(hasSelection); // Explore (or open containing folder) final boolean use_open_containing_folder = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled"); final MenuItem itemExplore = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemExplore, "MyTorrentsView.menu." + (use_open_containing_folder ? "open_parent_folder" : "explore")); itemExplore.addListener(SWT.Selection, new DMTask(dms, false) { public void run(DownloadManager dm) { ManagerUtils.open(dm, use_open_containing_folder); } }); itemExplore.setEnabled(hasSelection); // === advanced menu === final MenuItem itemAdvanced = new MenuItem(menu, SWT.CASCADE); Messages.setLanguageText(itemAdvanced, "MyTorrentsView.menu.advancedmenu"); //$NON-NLS-1$ itemAdvanced.setEnabled(hasSelection); final Menu menuAdvanced = new Menu(menu.getShell(), SWT.DROP_DOWN); itemAdvanced.setMenu(menuAdvanced); // advanced > Download Speed Menu // long maxDownload = COConfigurationManager.getIntParameter("Max Download Speed KBs", 0) * 1024; long maxUpload = COConfigurationManager.getIntParameter("Max Upload Speed KBs", 0) * 1024; ViewUtils.addSpeedMenu(menu.getShell(), menuAdvanced, true, hasSelection, downSpeedDisabled, downSpeedUnlimited, totalDownSpeed, downSpeedSetMax, maxDownload, upSpeedDisabled, upSpeedUnlimited, totalUpSpeed, upSpeedSetMax, maxUpload, dms.length, new ViewUtils.SpeedAdapter() { public void setDownSpeed(final int speed) { DMTask task = new DMTask(dms) { public void run(DownloadManager dm) { dm.getStats().setDownloadRateLimitBytesPerSecond(speed); } }; task.go(); } public void setUpSpeed(final int speed) { DMTask task = new DMTask(dms) { public void run(DownloadManager dm) { dm.getStats().setUploadRateLimitBytesPerSecond(speed); } }; task.go(); } }); // advanced > Tracker Menu // final Menu menuTracker = new Menu(menu.getShell(), SWT.DROP_DOWN); final MenuItem itemTracker = new MenuItem(menuAdvanced, SWT.CASCADE); Messages.setLanguageText(itemTracker, "MyTorrentsView.menu.tracker"); itemTracker.setMenu(menuTracker); final MenuItem itemChangeTracker = new MenuItem(menuTracker, SWT.PUSH); Messages.setLanguageText(itemChangeTracker, "MyTorrentsView.menu.changeTracker"); //$NON-NLS-1$ Utils.setMenuItemImage(itemChangeTracker, "add_tracker"); itemChangeTracker.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager[] dms) { if ( dms.length > 0 ){ new TrackerChangerWindow(composite.getDisplay(), dms); } } }); itemChangeTracker.setEnabled(changeUrl); final MenuItem itemEditTracker = new MenuItem(menuTracker, SWT.PUSH); Messages.setLanguageText(itemEditTracker, "MyTorrentsView.menu.editTracker"); Utils.setMenuItemImage(itemEditTracker, "edit_trackers"); itemEditTracker.addListener(SWT.Selection, new DMTask(dms) { public void run( final DownloadManager[] dms ) { Map> same_map = new HashMap>(); for ( DownloadManager dm: dms ){ TOTorrent torrent = dm.getTorrent(); if ( torrent == null ){ continue; } List> group = TorrentUtils.announceGroupsToList(torrent); String str = ""; for ( List l: group ){ str += "[["; for ( String s:l ){ str += s + ", "; } } List dl = same_map.get( str ); if ( dl == null ){ dl = new ArrayList(); same_map.put( str, dl ); } dl.add(dm ); } for ( final List set: same_map.values()){ TOTorrent torrent = set.get(0).getTorrent(); List> group = TorrentUtils.announceGroupsToList(torrent); new MultiTrackerEditor( null, group, new TrackerEditorListener() { public void trackersChanged( String str, String str2, List> group ) { for ( DownloadManager dm: set ){ TOTorrent torrent = dm.getTorrent(); TorrentUtils.listToAnnounceGroups(group, torrent); try{ TorrentUtils.writeToFile(torrent); }catch (Throwable e){ Debug.printStackTrace(e); } if ( dm.getTrackerClient() != null){ dm.getTrackerClient().resetTrackerUrl(true); } } } }, true); } } }); itemEditTracker.setEnabled(hasSelection); // edit webseeds final MenuItem itemEditWebSeeds = new MenuItem(menuTracker, SWT.PUSH); Messages.setLanguageText(itemEditWebSeeds, "MyTorrentsView.menu.editWebSeeds"); itemEditWebSeeds.addListener(SWT.Selection, new DMTask(dms) { public void run( final DownloadManager[] dms ) { final TOTorrent torrent = dms[0].getTorrent(); if ( torrent == null ){ return; } List getright = getURLList( torrent, "url-list" ); List webseeds = getURLList( torrent, "httpseeds" ); Map ws = new HashMap(); ws.put( "getright", getright ); ws.put( "webseeds", webseeds ); ws = BDecoder.decodeStrings( ws ); new WebSeedsEditor( null, ws, new WebSeedsEditorListener() { public void webSeedsChanged( String oldName, String newName, Map ws ) { try{ // String -> byte[] ws = BDecoder.decode( BEncoder.encode( ws )); List getright = (List)ws.get( "getright" ); if ( getright == null || getright.size() == 0 ){ torrent.removeAdditionalProperty( "url-list" ); }else{ torrent.setAdditionalListProperty( "url-list", getright ); } List webseeds = (List)ws.get( "webseeds" ); if ( webseeds == null || webseeds.size() == 0 ){ torrent.removeAdditionalProperty( "httpseeds" ); }else{ torrent.setAdditionalListProperty( "httpseeds", webseeds ); } PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass(ExternalSeedPlugin.class); if ( pi != null ){ ExternalSeedPlugin ext_seed_plugin = (ExternalSeedPlugin)pi.getPlugin(); ext_seed_plugin.downloadChanged( PluginCoreUtils.wrap( dms[0] )); } }catch (Throwable e){ Debug.printStackTrace( e ); } } }, true ); } protected List getURLList( TOTorrent torrent, String key ) { Object obj = torrent.getAdditionalProperty( key ); if ( obj instanceof byte[] ){ List l = new ArrayList(); l.add(obj); return( l ); }else if ( obj instanceof List ){ return((List)obj); }else{ return( new ArrayList()); } } }); itemEditWebSeeds.setEnabled(dms.length==1); // manual update final MenuItem itemManualUpdate = new MenuItem(menuTracker, SWT.PUSH); Messages.setLanguageText(itemManualUpdate, "GeneralView.label.trackerurlupdate"); //$NON-NLS-1$ //itemManualUpdate.setImage(ImageRepository.getImage("edit_trackers")); itemManualUpdate.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { dm.requestTrackerAnnounce(false); } }); itemManualUpdate.setEnabled(manualUpdate); boolean scrape_enabled = COConfigurationManager.getBooleanParameter("Tracker Client Scrape Enable"); boolean scrape_stopped = COConfigurationManager.getBooleanParameter("Tracker Client Scrape Stopped Enable"); boolean manualScrape = (!scrape_enabled) || ((!scrape_stopped) && allStopped); final MenuItem itemManualScrape = new MenuItem(menuTracker, SWT.PUSH); Messages.setLanguageText(itemManualScrape, "GeneralView.label.trackerscrapeupdate"); //itemManualUpdate.setImage(ImageRepository.getImage("edit_trackers")); itemManualScrape.addListener(SWT.Selection, new DMTask(dms, true, true ) { public void run(DownloadManager dm) { dm.requestTrackerScrape(true); } }); itemManualScrape.setEnabled(manualScrape); // advanced > files final MenuItem itemFiles = new MenuItem(menuAdvanced, SWT.CASCADE); Messages.setLanguageText(itemFiles, "ConfigView.section.files"); final Menu menuFiles = new Menu(composite.getShell(), SWT.DROP_DOWN); itemFiles.setMenu(menuFiles); final MenuItem itemFileMoveData = new MenuItem(menuFiles, SWT.PUSH); Messages.setLanguageText(itemFileMoveData, "MyTorrentsView.menu.movedata"); itemFileMoveData.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager[] dms) { if (dms != null && dms.length > 0) { DirectoryDialog dd = new DirectoryDialog(composite.getShell()); dd.setFilterPath(TorrentOpener.getFilterPathData()); dd.setText(MessageText.getString("MyTorrentsView.menu.movedata.dialog")); String path = dd.open(); if (path != null) { TorrentOpener.setFilterPathData(path); File target = new File(path); for (int i = 0; i < dms.length; i++) { try { dms[i].moveDataFiles(target); } catch (Throwable e) { Logger.log(new LogAlert(dms[i], LogAlert.REPEATABLE, "Download data move operation failed", e)); } } } } } }); itemFileMoveData.setEnabled(fileMove); final MenuItem itemFileMoveTorrent = new MenuItem(menuFiles, SWT.PUSH); Messages.setLanguageText(itemFileMoveTorrent, "MyTorrentsView.menu.movetorrent"); itemFileMoveTorrent.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager[] dms) { if (dms != null && dms.length > 0) { DirectoryDialog dd = new DirectoryDialog(composite.getShell()); String filter_path = TorrentOpener.getFilterPathTorrent(); // If we don't have a decent path, default to the path of the first // torrent. if (filter_path == null || filter_path.trim().length() == 0) { filter_path = new File(dms[0].getTorrentFileName()).getParent(); } dd.setFilterPath(filter_path); dd.setText(MessageText.getString("MyTorrentsView.menu.movedata.dialog")); String path = dd.open(); if (path != null) { File target = new File(path); TorrentOpener.setFilterPathTorrent(target.toString()); for (int i = 0; i < dms.length; i++) { try { dms[i].moveTorrentFile(target); } catch (Throwable e) { Logger.log(new LogAlert(dms[i], LogAlert.REPEATABLE, "Download torrent move operation failed", e)); } } } } } }); itemFileMoveTorrent.setEnabled(fileMove); final MenuItem itemCheckFilesExist = new MenuItem(menuFiles, SWT.PUSH); Messages.setLanguageText(itemCheckFilesExist, "MyTorrentsView.menu.checkfilesexist"); itemCheckFilesExist.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { dm.filesExist( true ); } }); final MenuItem itemFileRescan = new MenuItem(menuFiles, SWT.CHECK); Messages.setLanguageText(itemFileRescan, "MyTorrentsView.menu.rescanfile"); itemFileRescan.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { dm.getDownloadState().setFlag(DownloadManagerState.FLAG_SCAN_INCOMPLETE_PIECES, itemFileRescan.getSelection()); } }); itemFileRescan.setSelection(allScanSelected); itemFileRescan.setEnabled(fileRescan); // clear allocation MenuItem itemFileClearAlloc = new MenuItem(menuFiles, SWT.PUSH); Messages.setLanguageText(itemFileClearAlloc, "MyTorrentsView.menu.clear_alloc_data"); itemFileClearAlloc.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { dm.setDataAlreadyAllocated( false ); } }); itemFileClearAlloc.setEnabled(allStopped); // clear resume MenuItem itemFileClearResume = new MenuItem(menuFiles, SWT.PUSH); Messages.setLanguageText(itemFileClearResume, "MyTorrentsView.menu.clear_resume_data"); itemFileClearResume.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { dm.getDownloadState().clearResumeData(); } }); itemFileClearResume.setEnabled(allStopped); // Advanced - > Rename final MenuItem itemRename = new MenuItem(menuAdvanced, SWT.DROP_DOWN); Messages.setLanguageText(itemRename, "MyTorrentsView.menu.rename"); itemRename.setEnabled(hasSelection && dms.length == 1); itemRename.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { AdvRenameWindow window = new AdvRenameWindow(); window.open(dms[0]); } }); // === advanced > export === // ========================= if (userMode > 0) { final MenuItem itemExport = new MenuItem(menuAdvanced, SWT.CASCADE); Messages.setLanguageText(itemExport, "MyTorrentsView.menu.exportmenu"); //$NON-NLS-1$ Utils.setMenuItemImage(itemExport, "export"); itemExport.setEnabled(hasSelection); final Menu menuExport = new Menu(composite.getShell(), SWT.DROP_DOWN); itemExport.setMenu(menuExport); // Advanced > Export > Export XML final MenuItem itemExportXML = new MenuItem(menuExport, SWT.PUSH); Messages.setLanguageText(itemExportXML, "MyTorrentsView.menu.export"); itemExportXML.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager[] dms) { DownloadManager dm = dms[0]; // First only. if (dm != null) new ExportTorrentWizard(itemExportXML.getDisplay(), dm); } }); // Advanced > Export > Export Torrent final MenuItem itemExportTorrent = new MenuItem(menuExport, SWT.PUSH); Messages.setLanguageText(itemExportTorrent, "MyTorrentsView.menu.exporttorrent"); itemExportTorrent.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager[] dms) { // FileDialog for single download // DirectoryDialog for multiple. File[] destinations = new File[dms.length]; if (dms.length == 1) { FileDialog fd = new FileDialog(composite.getShell(), SWT.SAVE); fd.setFileName(dms[0].getTorrentFileName()); String path = fd.open(); if (path == null) {return;} destinations[0] = new File(path); } else { DirectoryDialog dd = new DirectoryDialog(composite.getShell(), SWT.SAVE); String path = dd.open(); if (path == null) {return;} for (int i=0; i Export > WebSeed URL final MenuItem itemWebSeed = new MenuItem(menuExport, SWT.PUSH); Messages.setLanguageText(itemWebSeed, "MyTorrentsView.menu.exporthttpseeds"); itemWebSeed.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager[] dms) { final String NL = "\r\n"; String data = ""; boolean http_enable = COConfigurationManager.getBooleanParameter( "HTTP.Data.Listen.Port.Enable" ); String port; if ( http_enable ){ int p = COConfigurationManager.getIntParameter( "HTTP.Data.Listen.Port" ); int o = COConfigurationManager.getIntParameter( "HTTP.Data.Listen.Port.Override" ); if ( o == 0 ){ port = String.valueOf( p ); }else{ port = String.valueOf( o ); } }else{ data = "You need to enable the HTTP port or modify the URL(s) appropriately" + NL + NL; port = ""; } String ip = COConfigurationManager.getStringParameter( "Tracker IP", "" ); if ( ip.length() == 0 ){ data += "You might need to modify the host address in the URL(s)" + NL + NL; try{ InetAddress ia = AzureusCoreFactory.getSingleton().getInstanceManager().getMyInstance().getExternalAddress(); if ( ia != null ){ ip = IPToHostNameResolver.syncResolve( ia.getHostAddress(), 10000 ); } }catch( Throwable e ){ } if ( ip.length() == 0 ){ ip = ""; } } String base = "http://" + UrlUtils.convertIPV6Host(ip) + ":" + port + "/"; for (int i=0;i 0){ ClipboardCopy.copyToClipBoard( data ); } } }); } // export menu // === advanced > options === // =========================== if (userMode > 0) { final MenuItem itemExportXML = new MenuItem(menuAdvanced, SWT.PUSH); Messages.setLanguageText(itemExportXML, "MainWindow.menu.view.configuration"); itemExportXML.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager[] dms) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); uiFunctions.openView(UIFunctions.VIEW_DM_MULTI_OPTIONS, dms); } }); } // === advanced > peer sources === // =============================== if (userMode > 0) { final MenuItem itemPeerSource = new MenuItem(menuAdvanced, SWT.CASCADE); Messages.setLanguageText(itemPeerSource, "MyTorrentsView.menu.peersource"); //$NON-NLS-1$ final Menu menuPeerSource = new Menu(composite.getShell(), SWT.DROP_DOWN); itemPeerSource.setMenu(menuPeerSource); for (int i = 0; i < PEPeerSource.PS_SOURCES.length; i++) { final String p = PEPeerSource.PS_SOURCES[i]; String msg_text = "ConfigView.section.connection.peersource." + p; final MenuItem itemPS = new MenuItem(menuPeerSource, SWT.CHECK); itemPS.setData("peerSource", p); Messages.setLanguageText(itemPS, msg_text); //$NON-NLS-1$ itemPS.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { dm.getDownloadState().setPeerSourceEnabled(p, itemPS.getSelection()); } }); itemPS.setSelection(true); boolean bChecked = hasSelection; boolean bEnabled = !hasSelection; if (bChecked) { bEnabled = true; // turn on check if just one dm is not enabled for (int j = 0; j < dms.length; j++) { DownloadManager dm = (DownloadManager) dms[j]; if (!dm.getDownloadState().isPeerSourceEnabled(p)) { bChecked = false; } if (!dm.getDownloadState().isPeerSourcePermitted(p)) { bEnabled = false; } } } itemPS.setSelection(bChecked); itemPS.setEnabled(bEnabled); } } // === advanced > networks === // =========================== if (userMode > 1) { final MenuItem itemNetworks = new MenuItem(menuAdvanced, SWT.CASCADE); Messages.setLanguageText(itemNetworks, "MyTorrentsView.menu.networks"); //$NON-NLS-1$ final Menu menuNetworks = new Menu(composite.getShell(), SWT.DROP_DOWN); itemNetworks.setMenu(menuNetworks); for (int i = 0; i < AENetworkClassifier.AT_NETWORKS.length; i++) { final String nn = AENetworkClassifier.AT_NETWORKS[i]; String msg_text = "ConfigView.section.connection.networks." + nn; final MenuItem itemNetwork = new MenuItem(menuNetworks, SWT.CHECK); itemNetwork.setData("network", nn); Messages.setLanguageText(itemNetwork, msg_text); //$NON-NLS-1$ itemNetwork.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { dm.getDownloadState().setNetworkEnabled(nn, itemNetwork.getSelection()); } }); boolean bChecked = hasSelection; if (bChecked) { // turn on check if just one dm is not enabled for (int j = 0; j < dms.length; j++) { DownloadManager dm = (DownloadManager) dms[j]; if (!dm.getDownloadState().isNetworkEnabled(nn)) { bChecked = false; break; } } } itemNetwork.setSelection(bChecked); } } // superseed if (userMode > 1 && isSeedingView) { final MenuItem itemSuperSeed = new MenuItem(menuAdvanced, SWT.CHECK); Messages.setLanguageText(itemSuperSeed, "ManagerItem.superseeding"); boolean enabled = canSetSuperSeed && (superSeedAllNo || superSeedAllYes); itemSuperSeed.setEnabled(enabled); final boolean selected = superSeedAllNo; if (enabled) { itemSuperSeed.setSelection(selected); itemSuperSeed.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { PEPeerManager pm = dm.getPeerManager(); if (pm != null) { if (pm.isSuperSeedMode() == selected && pm.canToggleSuperSeedMode()) { pm.setSuperSeedMode(!selected); } } } }); } } final MenuItem itemPositionManual = new MenuItem(menuAdvanced, SWT.PUSH); Messages.setLanguageText(itemPositionManual, "MyTorrentsView.menu.reposition.manual"); itemPositionManual.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow( "MyTorrentsView.dialog.setPosition.title", "MyTorrentsView.dialog.setPosition.text"); entryWindow.prompt(new UIInputReceiverListener() { public void UIInputReceiverClosed(UIInputReceiver entryWindow) { if (!entryWindow.hasSubmittedInput()) { return; } String sReturn = entryWindow.getSubmittedInput(); if (sReturn == null) return; int newPosition = -1; try { newPosition = Integer.valueOf(sReturn).intValue(); } catch (NumberFormatException er) { // Ignore } int size = azureus_core.getGlobalManager().downloadManagerCount( isSeedingView); if (newPosition > size) newPosition = size; if (newPosition <= 0) { MessageBox mb = new MessageBox(composite.getShell(), SWT.ICON_ERROR | SWT.OK); mb.setText(MessageText.getString("MyTorrentsView.dialog.NumberError.title")); mb.setMessage(MessageText.getString("MyTorrentsView.dialog.NumberError.text")); mb.open(); return; } moveSelectedTorrentsTo(tv, dms, newPosition); } }); } }); // back to main menu if (userMode > 0 && isTrackerOn) { // Host final MenuItem itemHost = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemHost, "MyTorrentsView.menu.host"); Utils.setMenuItemImage(itemHost, "host"); itemHost.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { hostTorrents(dms, azureus_core, composite); } }); // Publish final MenuItem itemPublish = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemPublish, "MyTorrentsView.menu.publish"); Utils.setMenuItemImage(itemPublish, "publish"); itemPublish.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { publishTorrents(dms, azureus_core, composite); } }); itemHost.setEnabled(hasSelection); itemPublish.setEnabled(hasSelection); } /* Do we really need the Move submenu? There's shortcut keys and toolbar * buttons.. new MenuItem(menu, SWT.SEPARATOR); final MenuItem itemMove = new MenuItem(menu, SWT.CASCADE); Messages.setLanguageText(itemMove, "MyTorrentsView.menu.move"); Utils.setMenuItemImage(itemMove, "move"); itemMove.setEnabled(hasSelection); final Menu menuMove = new Menu(composite.getShell(), SWT.DROP_DOWN); itemMove.setMenu(menuMove); final MenuItem itemMoveTop = new MenuItem(menuMove, SWT.PUSH); Messages.setLanguageText(itemMoveTop, "MyTorrentsView.menu.moveTop"); Utils.setMenuItemImage(itemMoveTop, "top"); itemMoveTop.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { moveSelectedTorrentsTop(); } }); itemMoveTop.setEnabled(moveUp); final MenuItem itemMoveUp = new MenuItem(menuMove, SWT.PUSH); Messages.setLanguageText(itemMoveUp, "MyTorrentsView.menu.moveUp"); Utils.setMenuItemImage(itemMoveUp, "up"); itemMoveUp.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { moveSelectedTorrentsUp(); } }); final MenuItem itemMoveDown = new MenuItem(menuMove, SWT.PUSH); Messages.setLanguageText(itemMoveDown, "MyTorrentsView.menu.moveDown"); Utils.setMenuItemImage(itemMoveDown, "down"); itemMoveDown.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { moveSelectedTorrentsDown(); } }); final MenuItem itemMoveEnd = new MenuItem(menuMove, SWT.PUSH); Messages.setLanguageText(itemMoveEnd, "MyTorrentsView.menu.moveEnd"); Utils.setMenuItemImage(itemMoveEnd, "bottom"); itemMoveEnd.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { moveSelectedTorrentsEnd(); } }); itemMoveEnd.setEnabled(moveDown); */ /* //TODO ensure that all limits combined don't go under the min 5kbs ? //Disable at the end of the list, thus the first item of the array is instanciated last. itemsSpeed[0] = new MenuItem(menuSpeed,SWT.PUSH); Messages.setLanguageText(itemsSpeed[0],"MyTorrentsView.menu.setSpeed.disable"); itemsSpeed[0].setData("maxul", new Integer(-1)); itemsSpeed[0].addListener(SWT.Selection,itemsSpeedListener); */ // Category Menu menuCategory = new Menu(composite.getShell(), SWT.DROP_DOWN); final MenuItem itemCategory = new MenuItem(menu, SWT.CASCADE); Messages.setLanguageText(itemCategory, "MyTorrentsView.menu.setCategory"); //$NON-NLS-1$ //itemCategory.setImage(ImageRepository.getImage("speed")); itemCategory.setMenu(menuCategory); itemCategory.setEnabled(hasSelection); addCategorySubMenu(dms, menuCategory, composite); // --- new MenuItem(menu, SWT.SEPARATOR); // Queue final MenuItem itemQueue = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemQueue, "MyTorrentsView.menu.queue"); //$NON-NLS-1$ Utils.setMenuItemImage(itemQueue, "start"); itemQueue.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager[] dms) { queueTorrents(dms, menu.getShell()); } }); itemQueue.setEnabled(start); // Force Start if (userMode > 0) { final MenuItem itemForceStart = new MenuItem(menu, SWT.CHECK); Messages.setLanguageText(itemForceStart, "MyTorrentsView.menu.forceStart"); Utils.setMenuItemImage(itemForceStart, "forcestart"); itemForceStart.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { if (ManagerUtils.isForceStartable(dm)) { dm.setForceStart(itemForceStart.getSelection()); } } }); itemForceStart.setSelection(forceStart); itemForceStart.setEnabled(forceStartEnabled); } // Stop final MenuItem itemStop = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemStop, "MyTorrentsView.menu.stop"); //$NON-NLS-1$ Utils.setMenuItemImage(itemStop, "stop"); itemStop.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager[] dms) { stopTorrents(dms, menu.getShell()); } }); itemStop.setEnabled(stop); // Force Recheck final MenuItem itemRecheck = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemRecheck, "MyTorrentsView.menu.recheck"); Utils.setMenuItemImage(itemRecheck, "recheck"); itemRecheck.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { if (dm.canForceRecheck()) { dm.forceRecheck(); } } }); itemRecheck.setEnabled(recheck); // Remove final MenuItem itemRemove = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemRemove, "MyTorrentsView.menu.remove"); //$NON-NLS-1$ Utils.setMenuItemImage(itemRemove, "delete"); itemRemove.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { removeTorrent(dm, false, false, menu.getShell()); } }); itemRemove.setEnabled(hasSelection); // === Remove And === // ================== final MenuItem itemRemoveAnd = new MenuItem(menu, SWT.CASCADE); Messages.setLanguageText(itemRemoveAnd, "MyTorrentsView.menu.removeand"); //$NON-NLS-1$ Utils.setMenuItemImage(itemRemoveAnd, "delete"); itemRemoveAnd.setEnabled(hasSelection); final Menu menuRemove = new Menu(composite.getShell(), SWT.DROP_DOWN); itemRemoveAnd.setMenu(menuRemove); // Remove And > Delete Torrent final MenuItem itemDeleteTorrent = new MenuItem(menuRemove, SWT.PUSH); Messages.setLanguageText(itemDeleteTorrent, "MyTorrentsView.menu.removeand.deletetorrent"); //$NON-NLS-1$ itemDeleteTorrent.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { removeTorrent(dm, true, false, menu.getShell()); } }); // Remove And > Delete Data final MenuItem itemDeleteData = new MenuItem(menuRemove, SWT.PUSH); Messages.setLanguageText(itemDeleteData, "MyTorrentsView.menu.removeand.deletedata"); itemDeleteData.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { removeTorrent(dm, false, true, menu.getShell()); } }); // Remove And > Delete Both final MenuItem itemDeleteBoth = new MenuItem(menuRemove, SWT.PUSH); Messages.setLanguageText(itemDeleteBoth, "MyTorrentsView.menu.removeand.deleteboth"); itemDeleteBoth.addListener(SWT.Selection, new DMTask(dms) { public void run(DownloadManager dm) { removeTorrent(dm, true, true, menu.getShell()); } }); } private static void addCategorySubMenu(final DownloadManager[] dms, Menu menuCategory, final Composite composite) { MenuItem[] items = menuCategory.getItems(); int i; for (i = 0; i < items.length; i++) { items[i].dispose(); } Category[] categories = CategoryManager.getCategories(); Arrays.sort(categories); // Ensure that there is at least one user category available. boolean allow_category_selection = categories.length > 0; if (allow_category_selection) { boolean user_category_found = false; for (i=0; i iNewPos) iNewPos++; } else { if (iOldPos < iNewPos) iNewPos--; } } if (tv != null) { boolean bForceSort = sortColumn.getName().equals("#"); tv.columnInvalidate("#"); tv.refreshTable(bForceSort); } } private static void changeDirSelectedTorrents(DownloadManager[] dms, Shell shell) { if (dms.length <= 0) return; String sDefPath = COConfigurationManager.getBooleanParameter("Use default data dir") ? COConfigurationManager .getStringParameter("Default save path") : ""; if (sDefPath.length() > 0) { File f = new File(sDefPath); if (!f.exists()) { FileUtil.mkdirs(f); } } DirectoryDialog dDialog = new DirectoryDialog(shell, SWT.SYSTEM_MODAL); dDialog.setFilterPath(sDefPath); dDialog.setMessage(MessageText.getString("MainWindow.dialog.choose.savepath")); String sSavePath = dDialog.open(); if (sSavePath != null) { File fSavePath = new File(sSavePath); for (int i = 0; i < dms.length; i++) { DownloadManager dm = dms[i]; if (dm.getState() == DownloadManager.STATE_ERROR) { dm.setTorrentSaveDir(sSavePath); boolean found = dm.filesExist(true); if (!found && dm.getTorrent() != null && !dm.getTorrent().isSimpleTorrent()) { String parentPath = fSavePath.getParent(); if (parentPath != null) { dm.setTorrentSaveDir(parentPath); found = dm.filesExist(true); if (!found) { dm.setTorrentSaveDir(sSavePath); } } } if (found) { dm.stopIt(DownloadManager.STATE_STOPPED, false, false); ManagerUtils.queue(dm, shell); } } } } } public static void runTorrents(Object[] download_managers) { for (int i = download_managers.length - 1; i >= 0; i--) { DownloadManager dm = (DownloadManager) download_managers[i]; if (dm != null) { ManagerUtils.run(dm); } } } public static void hostTorrents(final Object[] download_managers, final AzureusCore azureus_core, final Composite composite) { DMTask task = new DMTask(toDMS(download_managers)) { public void run(DownloadManager dm) { ManagerUtils.host(azureus_core, dm, composite); } }; task.go(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_MYTRACKER, null); } } public static void publishTorrents(final Object[] download_managers, final AzureusCore azureus_core, final Composite composite) { DMTask task = new DMTask(toDMS(download_managers)) { public void run(DownloadManager dm) { ManagerUtils.publish(azureus_core, dm, composite); } }; task.go(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_MYTRACKER, null); } } public static void removeTorrent(final DownloadManager dm, final boolean bDeleteTorrent, final boolean bDeleteData, Shell shell) { ManagerUtils.remove(dm, shell, bDeleteTorrent, bDeleteData); } public static void removeTorrents(Object[] download_managers, final Shell shell) { DMTask task = new DMTask(toDMS(download_managers)) { public void run(DownloadManager dm) { removeTorrent(dm, false, false, shell); } }; task.go(); } public static void stopTorrents(Object[] download_managers, final Shell shell) { DMTask task = new DMTask(toDMS(download_managers)) { public void run(DownloadManager dm) { ManagerUtils.stop(dm, shell); } }; task.go(); } public static void queueTorrents(Object[] download_managers, final Shell shell) { DMTask task = new DMTask(toDMS(download_managers)) { public void run(DownloadManager dm) { ManagerUtils.queue(dm, shell); } }; task.go(); } public static void resumeTorrents(Object[] download_managers) { DMTask task = new DMTask(toDMS(download_managers)) { public void run(DownloadManager dm) { ManagerUtils.start(dm); } }; task.go(); } // Category Stuff public static void assignToCategory(Object[] download_managers, final Category category) { DMTask task = new DMTask(toDMS(download_managers)) { public void run(DownloadManager dm) { dm.getDownloadState().setCategory(category); } }; task.go(); } public static void promptUserForComment(final DownloadManager[] dms) { if (dms.length == 0) {return;} DownloadManager dm = dms[0]; // Create dialog box. String suggested = dm.getDownloadState().getUserComment(); String msg_key_prefix = "MyTorrentsView.menu.edit_comment.enter."; SimpleTextEntryWindow text_entry = new SimpleTextEntryWindow(); text_entry.setTitle(msg_key_prefix + "title"); text_entry.setMessage(msg_key_prefix + "message"); text_entry.setPreenteredText(suggested, false); text_entry.setMultiLine(true); text_entry.prompt(new UIInputReceiverListener() { public void UIInputReceiverClosed(UIInputReceiver text_entry) { if (text_entry.hasSubmittedInput()) { String value = text_entry.getSubmittedInput(); final String value_to_set = (value.length() == 0) ? null : value; DMTask task = new DMTask(dms) { public void run(DownloadManager dm) { dm.getDownloadState().setUserComment(value_to_set); } }; task.go(); } } }); } private static DownloadManager[] toDMS(Object[] objects) { if (objects instanceof DownloadManager[]) { return (DownloadManager[]) objects; } DownloadManager[] result = new DownloadManager[objects.length]; System.arraycopy(objects, 0, result, 0, result.length); return result; } private abstract static class DMTask implements Listener { private DownloadManager[] dms; private boolean ascending; private boolean async; public DMTask(DownloadManager[] dms) { this(dms, true); } public DMTask(DownloadManager[] dms, boolean ascending) { this.dms = dms; this.ascending = ascending; } public DMTask(DownloadManager[] dms, boolean ascending, boolean async ) { this.dms = dms; this.ascending = ascending; this.async = async; } // One of the following methods should be overridden. public void run(DownloadManager dm) { } public void run(DownloadManager[] dm) { } public void handleEvent(Event event) { if ( async ){ new AEThread2( "DMTask:async", true ) { public void run() { go(); } }.start(); }else{ go(); } } public void go() { try { DownloadManager dm = null; for (int i = 0; i < dms.length; i++) { dm = dms[ascending ? i : (dms.length - 1) - i]; if (dm == null) { continue; } this.run(dm); } this.run(dms); } catch (Exception e) { Debug.printStackTrace(e); } } } /** * quick check to see if a file might be a torrent * @param torrentFile * @param deleteFileOnCancel * @param parentShell non-null: display a window if it's not a torrent * @return * * @since 3.0.2.3 */ public static boolean isFileTorrent(File torrentFile, Shell parentShell, String torrentName) { String sFirstChunk = null; try { sFirstChunk = FileUtil.readFileAsString(torrentFile, 16384).toLowerCase(); } catch (IOException e) { Debug.out("warning", e); } if (sFirstChunk == null) { sFirstChunk = ""; } if (!sFirstChunk.startsWith("d")) { if (parentShell != null) { boolean isHTML = sFirstChunk.indexOf("= 0; MessageBoxShell boxShell = new MessageBoxShell( MessageText.getString("OpenTorrentWindow.mb.notTorrent.title"), MessageText.getString("OpenTorrentWindow.mb.notTorrent.text", new String[] { torrentName, isHTML ? "" : MessageText.getString("OpenTorrentWindow.mb.notTorrent.cannot.display") }), new String[] { MessageText.getString("Button.ok") }, 0); if (isHTML) { boxShell.setHtml(sFirstChunk); } boxShell.open(null); } return false; } return true; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/debug/0000755000175000017500000000000011310377636020504 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/debug/UIDebugGenerator.java0000644000175000017500000002444311267524620024507 0ustar adrianadrian/* * Created on May 28, 2006 4:31:42 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.debug; import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.logging.impl.FileLogging; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT.TriggerInThread; import com.aelitis.azureus.core.*; import com.aelitis.azureus.ui.UserPrompterResultListener; /** * @author TuxPaper * @created May 28, 2006 * */ public class UIDebugGenerator { public static void generate() { Display display = Display.getCurrent(); if (display == null) { return; } // make sure display is up to date while (display.readAndDispatch()) { } Shell[] shells = display.getShells(); if (shells == null || shells.length == 0) { return; } final File path = new File(SystemProperties.getUserPath(), "debug"); if (!path.isDirectory()) { path.mkdir(); } else { try { File[] files = path.listFiles(); for (int i = 0; i < files.length; i++) { files[i].delete(); } } catch (Exception e) { } } for (int i = 0; i < shells.length; i++) { try { Shell shell = shells[i]; Image image = null; if (shell.getData("class") instanceof ObfusticateShell) { ObfusticateShell shellClass = (ObfusticateShell) shell.getData("class"); try { image = shellClass.generateObfusticatedImage(); } catch (Exception e) { Debug.out("Obfusticating shell " + shell, e); } } else { Rectangle clientArea = shell.getClientArea(); image = new Image(display, clientArea.width, clientArea.height); GC gc = new GC(shell); try { gc.copyArea(image, clientArea.x, clientArea.y); } finally { gc.dispose(); } } if (image != null) { File file = new File(path, "image-" + i + ".jpg"); String sFileName = file.getAbsolutePath(); ImageLoader imageLoader = new ImageLoader(); imageLoader.data = new ImageData[] { image.getImageData() }; imageLoader.save(sFileName, SWT.IMAGE_JPEG); } } catch (Exception e) { Logger.log(new LogEvent(LogIDs.GUI, "Creating Obfusticated Image", e)); } } SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow( "UIDebugGenerator.messageask.title", "UIDebugGenerator.messageask.text", true); entryWindow.prompt(); if (!entryWindow.hasSubmittedInput()) { return; } String message = entryWindow.getSubmittedInput(); if (message == null || message.length() == 0) { new MessageBoxShell(SWT.OK, "UIDebugGenerator.message.cancel", (String[]) null).open(null); return; } try { File fUserMessage = new File(path, "usermessage.txt"); FileWriter fw; fw = new FileWriter(fUserMessage); fw.write(message); fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } CoreWaiterSWT.waitForCore(TriggerInThread.ANY_THREAD, new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { core.createOperation(AzureusCoreOperation.OP_PROGRESS, new AzureusCoreOperationTask() { public void run(AzureusCoreOperation operation) { try { File fEvidence = new File(path, "evidence.log"); FileWriter fw; fw = new FileWriter(fEvidence); PrintWriter pw = new PrintWriter(fw); AEDiagnostics.generateEvidence(pw); fw.close(); } catch (IOException e) { Debug.printStackTrace(e); } } }); } }); try { final File outFile = new File(SystemProperties.getUserPath(), "debug.zip"); if (outFile.exists()) { outFile.delete(); } ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outFile)); // %USERDIR%\logs File logPath = new File(SystemProperties.getUserPath(), "logs"); File[] files = logPath.listFiles(new FileFilter() { public boolean accept(File pathname) { return pathname.getName().endsWith(".log"); } }); addFilesToZip(out, files); // %USERDIR% File userPath = new File(SystemProperties.getUserPath()); files = userPath.listFiles(new FileFilter() { public boolean accept(File pathname) { return pathname.getName().endsWith(".log"); } }); addFilesToZip(out, files); // %USERDIR%\debug files = path.listFiles(); addFilesToZip(out, files); // recent errors from exe dir final long ago = SystemTime.getCurrentTime() - 1000L * 60 * 60 * 24 * 90; File azureusPath = new File(SystemProperties.getApplicationPath()); files = azureusPath.listFiles(new FileFilter() { public boolean accept(File pathname) { return (pathname.getName().startsWith("hs_err") && pathname.lastModified() > ago); } }); addFilesToZip(out, files); // recent errors from OSX java log dir File javaLogPath = new File(System.getProperty("user.home"), "Library" + File.separator + "Logs" + File.separator + "Java"); if (javaLogPath.isDirectory()) { files = javaLogPath.listFiles(new FileFilter() { public boolean accept(File pathname) { return (pathname.getName().endsWith("log") && pathname.lastModified() > ago); } }); addFilesToZip(out, files); } boolean bLogToFile = COConfigurationManager.getBooleanParameter("Logging Enable"); String sLogDir = COConfigurationManager.getStringParameter("Logging Dir", ""); if (bLogToFile && sLogDir != null) { File loggingFile = new File(sLogDir, FileLogging.LOG_FILE_NAME); if (loggingFile.isFile()) { addFilesToZip(out, new File[] { loggingFile }); } } out.close(); if (outFile.exists()) { MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.CANCEL | SWT.ICON_INFORMATION | SWT.APPLICATION_MODAL, "UIDebugGenerator.complete", new String[] { outFile.toString() }); mb.open(new UserPrompterResultListener() { public void prompterClosed(int result) { if (result == SWT.OK) { try { PlatformManagerFactory.getPlatformManager().showFile( outFile.getAbsolutePath()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static void addFilesToZip(ZipOutputStream out, File[] files) { byte[] buf = new byte[1024]; if (files == null) { return; } for (int j = 0; j < files.length; j++) { File file = files[j]; FileInputStream in; try { in = new FileInputStream(file); } catch (FileNotFoundException e) { continue; } try { ZipEntry entry = new ZipEntry(file.getName()); entry.setTime(file.lastModified()); out.putNextEntry(entry); // Transfer bytes from the file to the ZIP file int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } // Complete the entry out.closeEntry(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { in.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * @param image * @param bounds */ // XXX After we swith to 3.2, display param can be removed, and // image.getDevice() can be used public static void obfusticateArea(Display display, Image image, Rectangle bounds) { GC gc = new GC(image); try { gc.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); gc.setForeground(display.getSystemColor(SWT.COLOR_RED)); gc.fillRectangle(bounds); gc.drawRectangle(bounds); int x2 = bounds.x + bounds.width; int y2 = bounds.y + bounds.height; gc.drawLine(bounds.x, bounds.y, x2, y2); gc.drawLine(x2, bounds.y, bounds.x, y2); } finally { gc.dispose(); } } /** * @param image * @param bounds * @param text */ public static void obfusticateArea(Display display, Image image, Rectangle bounds, String text) { if (bounds.isEmpty()) return; if (text == "") { obfusticateArea(display, image, bounds); return; } GC gc = new GC(image); try { gc.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); gc.setForeground(display.getSystemColor(SWT.COLOR_RED)); gc.fillRectangle(bounds); gc.drawRectangle(bounds); gc.setClipping(bounds); gc.drawText(text, bounds.x + 2, bounds.y + 1); } finally { gc.dispose(); } } /** * @param image * @param control * @param shellOffset * @param text */ public static void obfusticateArea(Image image, Control control, Point shellOffset, String text) { Rectangle bounds = control.getBounds(); Point offset = control.getParent().toDisplay(bounds.x, bounds.y); bounds.x = offset.x - shellOffset.x; bounds.y = offset.y - shellOffset.y; obfusticateArea(control.getDisplay(), image, bounds, text); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/debug/ObfusticateCellText.java0000644000175000017500000000222510437300144025252 0ustar adrianadrian/* * Created on May 28, 2006 8:20:02 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.debug; import org.gudy.azureus2.plugins.ui.tables.TableCell; /** * @author TuxPaper * @created May 28, 2006 * */ public interface ObfusticateCellText { public String getObfusticatedText(TableCell cell); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/debug/ObfusticateShell.java0000644000175000017500000000221310437300144024572 0ustar adrianadrian/* * Created on May 28, 2006 4:51:20 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.debug; import org.eclipse.swt.graphics.Image; /** * @author TuxPaper * @created May 28, 2006 * */ public interface ObfusticateShell { /** * @return */ Image generateObfusticatedImage(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/debug/ObfusticateImage.java0000644000175000017500000000225710437147356024573 0ustar adrianadrian/* * Created on May 28, 2006 5:03:50 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.debug; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; /** * @author TuxPaper * @created May 28, 2006 * */ public interface ObfusticateImage { Image obfusticatedImage(Image image, Point shellOffset); }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/debug/ObfusticateTab.java0000644000175000017500000000210710551540654024244 0ustar adrianadrian/* * Created on May 28, 2006 10:45:31 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.debug; /** * @author TuxPaper * @created May 28, 2006 * */ public interface ObfusticateTab { String getObfusticatedHeader(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsuninstaller/0000755000175000017500000000000011310377636023360 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsuninstaller/UIPWFinishPanel.java0000644000175000017500000000501410373051010027107 0ustar adrianadrian/* * Created on 29 nov. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.pluginsuninstaller; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import org.gudy.azureus2.ui.swt.wizard.Wizard; /** * @author Olivier Chalouhi * */ public class UIPWFinishPanel extends AbstractWizardPanel { public UIPWFinishPanel( Wizard wizard, IWizardPanel previous) { super(wizard, previous); } public void show() { wizard.setTitle(MessageText.getString("uninstallPluginsWizard.finish.title")); wizard.setErrorMessage(""); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 1; panel.setLayout(layout); Label lblExplanation = new Label(panel,SWT.WRAP); GridData data = new GridData(GridData.FILL_BOTH); lblExplanation.setLayoutData(data); Messages.setLanguageText(lblExplanation,"uninstallPluginsWizard.finish.explanation"); } public void finish() { ((UnInstallPluginWizard)wizard).performUnInstall(); wizard.switchToClose(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsuninstaller/UIPWListPanel.java0000644000175000017500000001563111171750562026627 0ustar adrianadrian/* * Created on 29 nov. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.pluginsuninstaller; import java.util.List; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.Map; import java.util.HashMap; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import org.gudy.azureus2.ui.swt.wizard.Wizard; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; /** * @author Olivier Chalouhi * */ public class UIPWListPanel extends AbstractWizardPanel { Table pluginList; public UIPWListPanel( Wizard wizard, IWizardPanel previous ) { super(wizard, previous); } public void show() { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { _show(core); } }); } private void _show(AzureusCore core) { wizard.setTitle(MessageText.getString("uninstallPluginsWizard.list.title")); wizard.setErrorMessage(""); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 1; panel.setLayout(layout); final Label lblStatus = new Label(panel,SWT.NULL); Messages.setLanguageText(lblStatus,"uninstallPluginsWizard.list.loaded"); pluginList = new Table(panel,SWT.BORDER | SWT.V_SCROLL | SWT.CHECK | SWT.FULL_SELECTION | SWT.SINGLE); pluginList.setHeaderVisible(true); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.heightHint = 200; pluginList.setLayoutData(data); TableColumn tcName = new TableColumn(pluginList,SWT.LEFT); Messages.setLanguageText(tcName,"installPluginsWizard.list.name"); tcName.setWidth(200); TableColumn tcVersion = new TableColumn(pluginList,SWT.LEFT); Messages.setLanguageText(tcVersion,"installPluginsWizard.list.version"); tcVersion.setWidth(150); PluginInterface plugins[] = new PluginInterface[0]; try { plugins = core.getPluginManager().getPluginInterfaces(); Arrays.sort( plugins, new Comparator() { public int compare( Object o1, Object o2) { return(((PluginInterface)o1).getPluginName().compareTo(((PluginInterface)o2).getPluginName())); } }); } catch(final Exception e) { Debug.printStackTrace(e); } // one "plugin" can have multiple interfaces. We need to group by their id Map pid_map = new HashMap(); for(int i = 0 ; i < plugins.length ; i++){ PluginInterface plugin = plugins[i]; String pid = plugin.getPluginID(); ArrayList pis = (ArrayList)pid_map.get( pid ); if ( pis == null ){ pis = new ArrayList(); pid_map.put( pid, pis ); } pis.add( plugin ); } ArrayList[] pid_list = new ArrayList[pid_map.size()]; pid_map.values().toArray( pid_list ); Arrays.sort( pid_list, new Comparator() { public int compare( Object o1, Object o2) { ArrayList l1 = (ArrayList)o1; ArrayList l2 = (ArrayList)o2; return(((PluginInterface)l1.get(0)).getPluginName().compareToIgnoreCase(((PluginInterface)l2.get(0)).getPluginName())); } }); for(int i = 0 ; i < pid_list.length ; i++){ ArrayList pis = pid_list[i]; boolean skip = false; String display_name = ""; for (int j=0;j 0 ); } public IWizardPanel getFinishPanel() { return new UIPWFinishPanel(wizard,this); } public void updateList() { ArrayList list = new ArrayList(); TableItem[] items = pluginList.getItems(); for(int i = 0 ; i < items.length ; i++) { if(items[i].getChecked()) list.add(items[i].getData()); } ((UnInstallPluginWizard)wizard).setPluginList(list); ((UnInstallPluginWizard)wizard).setFinishEnabled( isFinishEnabled() ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsuninstaller/UnInstallPluginWizard.java0000644000175000017500000000456111171750562030500 0ustar adrianadrian/* * Created on 29 nov. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.pluginsuninstaller; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.ui.swt.wizard.Wizard; /** * @author Olivier Chalouhi * */ public class UnInstallPluginWizard extends Wizard { List plugins = new ArrayList(); public UnInstallPluginWizard( Display display ) { super("uninstallPluginsWizard.title"); UIPWListPanel list_panel = new UIPWListPanel(this,null); setFirstPanel(list_panel); } public void onClose() { // Call the parent class to clean up resources super.onClose(); } public void setPluginList(List _plugins) { plugins = _plugins; } public List getPluginList() { return( plugins ); } public void performUnInstall() { PluginInterface[] ps = new PluginInterface[ plugins.size()]; plugins.toArray( ps ); if ( ps.length > 0 ){ try{ ps[0].getPluginManager().getPluginInstaller().uninstall( ps ); }catch(Exception e){ Debug.printStackTrace(e); Logger.log(new LogAlert(LogAlert.REPEATABLE, "Failed to initialise installer", e)); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/UISwitcherUtil.java0000644000175000017500000001373411276126554023157 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Map; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.ui.UIInputReceiver; import org.gudy.azureus2.plugins.ui.UIInputReceiverListener; import org.gudy.azureus2.ui.swt.views.tableitems.files.FirstPieceItem; /** * @author TuxPaper * @created Mar 21, 2007 * */ public class UISwitcherUtil { private static final long UPTIME_NEWUSER = 60 * 60 * 1; // 1 hour private static ArrayList listeners = new ArrayList(); private static String switchedToUI = null; public static void addListener(UISwitcherListener l) { listeners.add(l); if (switchedToUI != null) { triggerListeners(switchedToUI); } } public static void removeListener(UISwitcherListener l) { listeners.remove(l); } public static void openSwitcherWindow() { _openSwitcherWindow(); } public static void triggerListeners(String ui) { Object[] array = listeners.toArray(); for (int i = 0; i < array.length; i++) { UISwitcherListener l = (UISwitcherListener) array[i]; l.uiSwitched(ui); } } public static String calcUIMode() { if (!isAZ3Avail()) { return "az2"; } // Can't use Constants.isSafeMode - it's not set by the time we // get here. if ("1".equals(System.getProperty("azureus.safemode"))) { // If we are in safe-mode, prefer the classic UI - less likely to cause problems. return "az2"; } String lastUI = COConfigurationManager.getStringParameter("ui", "az2"); COConfigurationManager.setParameter("lastUI", lastUI); String forceUI = System.getProperty("force.ui"); if (forceUI != null) { COConfigurationManager.setParameter("ui", forceUI); return forceUI; } // Flip people who install this client over top of an existing az // to az3ui. The installer will write a file to the program dir, // while an upgrade won't boolean installLogExists = FileUtil.getApplicationFile("installer.log").exists(); boolean alreadySwitched = COConfigurationManager.getBooleanParameter( "installer.ui.alreadySwitched", false); if (!alreadySwitched && installLogExists) { COConfigurationManager.setParameter("installer.ui.alreadySwitched", true); COConfigurationManager.setParameter("ui", "az3"); COConfigurationManager.setParameter("az3.virgin.switch", true); return "az3"; } boolean asked = COConfigurationManager.getBooleanParameter("ui.asked", false); if (asked || COConfigurationManager.hasParameter("ui", true)) { return COConfigurationManager.getStringParameter("ui", "az3"); } // Never auto-ask people who never have had 2.x, because they'd be scared // and cry at the advanced coolness of the az2 ui String sFirstVersion = COConfigurationManager.getStringParameter("First Recorded Version"); if (Constants.compareVersions(sFirstVersion, "3.0.0.0") >= 0) { COConfigurationManager.setParameter("ui", "az3"); return "az3"; } // For new users who install pre v3 Azureus, and then immediately upgrade // to v3: // Give them v3 by default since they've (in theory) never used az2ui // Note: Users with any existing 3.x.x.x version will not get because // they have the "ui" parameter set and there's logic above to // exit early. try { Map map = FileUtil.readResilientConfigFile("azureus.statistics"); if (map != null) { Map overallMap = (Map) map.get("all"); if (overallMap != null) { long uptime = 0; Object uptimeObject = overallMap.get("uptime"); if (uptimeObject instanceof Number) { uptime = ((Number) uptimeObject).longValue(); } // during a previous azureus, we may have screwed up uptime // and it might be zero.. so check for that.. if (uptime < UPTIME_NEWUSER && uptime >= 0) { COConfigurationManager.setParameter("ui", "az3"); COConfigurationManager.setParameter("az3.virgin.switch", true); COConfigurationManager.setParameter("az3.switch.immediate", true); return "az3"; } } } } catch (Exception e) { Debug.out(e); // ignore } // Short Circuit: We don't want to ask az2 users yet COConfigurationManager.setParameter("ui", "az2"); return "az2"; } public static void _openSwitcherWindow() { Class uiswClass = null; try { uiswClass = Class.forName("com.aelitis.azureus.ui.swt.shells.uiswitcher.UISwitcherWindow"); } catch (ClassNotFoundException e1) { } if (uiswClass == null) { return; } // either !asked or forceAsked at this point try { final Constructor constructor = uiswClass.getConstructor(new Class[] {}); Object object = constructor.newInstance(new Object[] {}); Method method = uiswClass.getMethod("open", new Class[] {}); method.invoke(object, new Object[] {}); } catch (Exception e) { Debug.printStackTrace(e); } return; } public static boolean isAZ3Avail() { Class uiswClass = null; try { uiswClass = Class.forName("com.aelitis.azureus.ui.swt.shells.uiswitcher.UISwitcherWindow"); return true; } catch (ClassNotFoundException e1) { } return false; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/minibar/0000755000175000017500000000000011310377636021037 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/minibar/AllTransfersBar.java0000644000175000017500000001314211232522032024711 0ustar adrianadrian/* * Created on 12 May 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.minibar; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerStats; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; /** * @author Allan Crooks * */ public class AllTransfersBar extends MiniBar { private static MiniBarManager manager; static { manager = new MiniBarManager("AllTransfersBar"); } public static MiniBarManager getManager() { return manager; } public static AllTransfersBar getBarIfOpen(GlobalManager g_manager) { return (AllTransfersBar)manager.getMiniBarForObject(g_manager); } public static AllTransfersBar open(GlobalManager g_manager, Shell main) { AllTransfersBar result = getBarIfOpen(g_manager); if (result == null) { result = new AllTransfersBar(g_manager, main); } return result; } public static void close(GlobalManager g_manager) { AllTransfersBar result = getBarIfOpen(g_manager); if (result != null) {result.close();} } private GlobalManager g_manager; private Label down_speed; private Label up_speed; private AllTransfersBar(GlobalManager gmanager, Shell main) { super(manager); this.g_manager = gmanager; this.construct(main); } public Object getContextObject() {return this.g_manager;} public void beginConstruction() { this.createFixedTextLabel("MinimizedWindow.all_transfers", false, true); this.createGap(40); // Download speed. this.createFixedTextLabel("ConfigView.download.abbreviated", false, false); this.down_speed = this.createSpeedLabel(); // Upload speed. this.createFixedTextLabel("ConfigView.upload.abbreviated", false, false); this.up_speed = this.createSpeedLabel(); } public void buildMenu(Menu menu, MenuEvent menuEvent) { // Start All MenuItem start_all = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(start_all, "MainWindow.menu.transfers.startalltransfers"); Utils.setMenuItemImage(start_all, "start"); start_all.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { ManagerUtils.asyncStartAll(); } }); start_all.setEnabled(true); // Stop All MenuItem stop_all = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(stop_all, "MainWindow.menu.transfers.stopalltransfers"); Utils.setMenuItemImage(stop_all, "stop"); stop_all.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { ManagerUtils.asyncStopAll(); } }); stop_all.setEnabled(true); // Pause All MenuItem pause_all = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(pause_all, "MainWindow.menu.transfers.pausetransfers"); Utils.setMenuItemImage(pause_all, "pause"); pause_all.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { ManagerUtils.asyncPause(); } }); pause_all.setEnabled(g_manager.canPauseDownloads()); // Resume All MenuItem resume_all = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(resume_all, "MainWindow.menu.transfers.resumetransfers"); Utils.setMenuItemImage(resume_all, "resume"); resume_all.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { ManagerUtils.asyncResume(); } }); resume_all.setEnabled(g_manager.canResumeDownloads()); new MenuItem(menu, SWT.SEPARATOR); super.buildMenu(menu); } protected void refresh0() { GlobalManagerStats stats = g_manager.getStats(); this.updateSpeedLabel(down_speed, stats.getDataReceiveRate(),stats.getProtocolReceiveRate()); this.updateSpeedLabel(up_speed, stats.getDataSendRate(),stats.getProtocolSendRate()); } public String getPluginMenuIdentifier(Object context) { return "transfersbar"; } protected void storeLastLocation(Point location) { COConfigurationManager.setParameter("transferbar.x", location.x); COConfigurationManager.setParameter("transferbar.y", location.y); } protected Point getInitialLocation() { if (!COConfigurationManager.getBooleanParameter("Remember transfer bar location")) { return null; } if (!COConfigurationManager.hasParameter("transferbar.x", false)) { return null; } int x = COConfigurationManager.getIntParameter("transferbar.x"); int y = COConfigurationManager.getIntParameter("transferbar.y"); return new Point(x, y); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/minibar/MiniBarManager.java0000644000175000017500000001147311036613130024507 0ustar adrianadrian/* * Created on 12 May 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.minibar; import java.util.Iterator; import java.util.ListIterator; import java.util.ArrayList; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.components.shell.ShellManager; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.updater.UIUpdatable; /** * @author Allan Crooks * */ public class MiniBarManager implements UIUpdatable { private boolean global; private String type; private ArrayList minibars = new ArrayList(); private static final AEMonitor minibars_mon = new AEMonitor("MiniBarManager"); private final ShellManager shellManager = new ShellManager(); private static MiniBarManager global_instance; static { global_instance = new MiniBarManager(); } public static MiniBarManager getManager() { return global_instance; } // Intentionally package-private. MiniBarManager(String type) { this.global = false; this.type = type; } private MiniBarManager() { this.global = true; this.type = null; } public void register(MiniBar bar) { shellManager.addWindow(bar.getShell()); try { minibars_mon.enter(); minibars.add(bar); if (!global) {global_instance.register(bar);} } finally { minibars_mon.exit(); } if (minibars.size() == 1) { try { UIFunctionsManager.getUIFunctions().getUIUpdater().addUpdater(this); } catch (Exception e) { Debug.out(e); } } } public void unregister(MiniBar bar) { try { minibars_mon.enter(); minibars.remove(bar); if (!global) {global_instance.unregister(bar);} } finally { minibars_mon.exit(); } if (minibars.isEmpty()) { try { UIFunctionsManager.getUIFunctions().getUIUpdater().removeUpdater(this); } catch (Exception e) { Debug.out(e); } } } public ShellManager getShellManager() { return shellManager; } public AEMonitor getMiniBarMonitor() { return minibars_mon; } public ListIterator getMiniBarIterator() { return this.minibars.listIterator(); } public int countMiniBars() { return this.minibars.size(); } public void setAllVisible(boolean visible) { try { minibars_mon.enter(); for (Iterator iter = minibars.iterator(); iter.hasNext();) { MiniBar bar = (MiniBar) iter.next(); bar.setVisible(visible); } } finally { minibars_mon.exit(); } } public void close(MiniBar mini_bar) { if (mini_bar != null) { mini_bar.close(); } } public MiniBar getMiniBarForObject(Object context) { try { minibars_mon.enter(); for (Iterator iter = minibars.iterator(); iter.hasNext();) { MiniBar bar = (MiniBar) iter.next(); if (bar.hasContext(context)) {return bar;} } return null; } finally { minibars_mon.exit(); } } public void close(Object context) { MiniBar bar = this.getMiniBarForObject(context); if (bar != null) {bar.close();} } public void closeAll() { try { minibars_mon.enter(); for (Iterator iter = new ArrayList(minibars).iterator(); iter.hasNext();) { MiniBar bar = (MiniBar) iter.next(); bar.close(); } } finally { minibars_mon.exit(); } } public boolean isOpen(Object context) { return this.getMiniBarForObject(context) != null; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { return "MiniBar-" + type; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI() public void updateUI() { try { minibars_mon.enter(); for (Iterator iter = minibars.iterator(); iter.hasNext();) { MiniBar bar = (MiniBar) iter.next(); try { bar.refresh(); } catch (Exception e) { Debug.out(e); } } } finally { minibars_mon.exit(); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/minibar/DownloadBar.java0000644000175000017500000001233211232522032024060 0ustar adrianadrian/* * Created on 12 May 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.minibar; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerStats; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.download.DownloadException; import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.ProgressBar; import org.eclipse.swt.widgets.Shell; /** * @author Allan Crooks * */ public class DownloadBar extends MiniBar { private static MiniBarManager manager; static { manager = new MiniBarManager("AllTransfersBar"); } public static MiniBarManager getManager() { return manager; } public static DownloadBar open(DownloadManager download, Shell main) { DownloadBar result = (DownloadBar)manager.getMiniBarForObject(download); if (result == null) { result = new DownloadBar(download, main); } return result; } public static void close(DownloadManager download) { DownloadBar result = (DownloadBar)manager.getMiniBarForObject(download); if (result != null) {result.close();} } private DownloadManager download; private Label download_name; private ProgressBar progress_bar; private Label down_speed; private Label up_speed; private Label eta; private DownloadBar(DownloadManager download, Shell main) { super(manager); this.download = download; this.construct(main); } public Object getContextObject() {return this.download;} public void beginConstruction() { // Download name. this.createFixedTextLabel("MinimizedWindow.name", false, false); this.download_name = this.createDataLabel(200); // Download progress. this.progress_bar = this.createPercentProgressBar(100); // Download speed. this.createFixedTextLabel("ConfigView.download.abbreviated", false, false); this.down_speed = this.createSpeedLabel(); // Upload speed. this.createFixedTextLabel("ConfigView.upload.abbreviated", false, false); this.up_speed = this.createSpeedLabel(); // ETA. this.createFixedTextLabel("TableColumn.header.eta", true, false); this.eta = this.createDataLabel(65); } public void buildMenu(Menu menu, MenuEvent menuEvent) { // Queue final MenuItem itemQueue = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemQueue, "MyTorrentsView.menu.queue"); Utils.setMenuItemImage(itemQueue, "start"); itemQueue.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { ManagerUtils.queue(download, splash); } }); itemQueue.setEnabled(ManagerUtils.isStartable(download)); // Stop final MenuItem itemStop = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(itemStop, "MyTorrentsView.menu.stop"); Utils.setMenuItemImage(itemStop, "stop"); itemStop.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { ManagerUtils.stop(download, splash); } }); itemStop.setEnabled(ManagerUtils.isStopable(download)); new MenuItem(menu, SWT.SEPARATOR); super.buildMenu(menu); } protected void refresh0() { DownloadManagerStats stats = download.getStats(); download_name.setText(download.getDisplayName()); int percent = stats.getCompleted(); this.updateSpeedLabel(down_speed, stats.getDataReceiveRate(), stats.getProtocolReceiveRate()); this.updateSpeedLabel(up_speed, stats.getDataSendRate(), stats.getProtocolSendRate()); eta.setText(DisplayFormatters.formatETA(stats.getETA())); if (progress_bar.getSelection() != percent) { progress_bar.setSelection(percent); progress_bar.redraw(); } } public String[] getPluginMenuIdentifiers(Object context) { if (context == null) {return null;} return new String[] {"downloadbar", "download_context"}; } public Object getPluginMenuContextObject() { try {return DownloadManagerImpl.getDownloadStatic(this.download);} catch (DownloadException de) {return null;} } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/minibar/MiniBar.java0000644000175000017500000004024111127403350023211 0ustar adrianadrian/* * Created on 12 May 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.minibar; import java.util.Iterator; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.common.util.MenuItemManager; import org.gudy.azureus2.ui.swt.MenuBuildUtils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author Allan Crooks * */ public abstract class MiniBar implements MenuBuildUtils.MenuBuilder { // // These are components which are related to the bar itself. // protected Label lDrag; protected MiniBar stucked; protected Monitor[] screens; protected int xPressed, yPressed; protected boolean moving; protected int hSize; protected Shell splash; protected MiniBarManager manager; private Font bold_font = null; // // These are components used during the construction of the bar. // private boolean constructing = false; private boolean constructed = false; private Menu menu; private MouseMoveListener mMoveListener; private MouseListener mListener; private int xSize; private boolean separateDataProt; protected MiniBar(MiniBarManager manager) { this.manager = manager; setPrebuildValues(); this.separateDataProt = DisplayFormatters.isDataProtSeparate(); } private void setPrebuildValues() { this.constructing = false; this.constructed = false; this.xSize = 0; this.hSize = -1; } // // These methods provide a construction API for subclasses. // private void assertConstructing() { if (!this.constructing) throw new RuntimeException("not constructing!"); } private Font createBoldFont(Font original) { FontData[] font_data = original.getFontData(); for (int i=0; i hSizeImage ? hSizeText : hSizeImage; } this.xSize += result.getSize().x + 3; } protected final Label createDataLabel(int width, boolean centered) { assertConstructing(); Label result = new Label(splash, (centered ? SWT.CENTER : SWT.NULL)); result.setBackground(Colors.blues[Colors.BLUES_LIGHTEST]); result.setText(""); result.addMouseListener(this.mListener); result.addMouseMoveListener(this.mMoveListener); if (this.hSize == -1) { throw new RuntimeException("must add fixed text label first!"); } result.setSize(width, hSize); result.setLocation(this.xSize, 0); result.setMenu(this.menu); this.xSize += width + 3; return result; } protected final Label createDataLabel(int width) { return createDataLabel(width, false); } protected final Label createSpeedLabel() { return createDataLabel(separateDataProt ? 110 : 65, separateDataProt); } protected void updateSpeedLabel(Label label, long data_rate, long protocol_rate) { if (separateDataProt) { label.setText(DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec(data_rate, protocol_rate)); } else { label.setText(DisplayFormatters.formatByteCountToKiBEtcPerSec(data_rate)); } } protected final ProgressBar createProgressBar(int min, int max, int width, final ProgressBarText pbt) { final ProgressBar result = new ProgressBar(splash, SWT.SMOOTH); result.setBackground(Colors.blues[Colors.BLUES_LIGHTEST]); result.setForeground(Colors.blues[Colors.BLUES_MIDLIGHT]); result.setMinimum(min); result.setMaximum(max); result.addMouseListener(this.mListener); result.addMouseMoveListener(this.mMoveListener); if (this.hSize == -1) { throw new RuntimeException("must add fixed text label first!"); } result.setSize(width, hSize); result.setLocation(this.xSize, 0); result.setMenu(this.menu); this.xSize += width + 3; // Add a listener to display text on the progress bar. if (pbt != null) { result.addListener(SWT.Paint, new Listener() { public void handleEvent(Event event) { Color old = event.gc.getForeground(); event.gc.setForeground(Colors.black); int char_width = event.gc.getFontMetrics().getAverageCharWidth(); String pb_text = pbt.convert(result.getSelection()); event.gc.drawText(pb_text, (result.getSize().x - pb_text.length() * char_width )/2, -1, true); event.gc.setForeground(old); } }); } return result; } protected final ProgressBar createPercentProgressBar(int width) { return createProgressBar(0, 1000, width, new ProgressBarText() { public String convert(int value) { return DisplayFormatters.formatPercentFromThousands(value); } }); } protected static interface ProgressBarText { public String convert(int value); } // // These methods define the main MiniBar behaviour. // public final void construct(final Shell main) { if (this.constructed) { throw new RuntimeException("already constructed!"); } this.constructing = true; this.stucked = null; this.splash = org.gudy.azureus2.ui.swt.components.shell.ShellFactory .createShell(SWT.ON_TOP); manager.register(this); final DisposeListener mainDisposeListener; main.addDisposeListener(mainDisposeListener = new DisposeListener() { public void widgetDisposed(DisposeEvent event) { close(); } }); // cleanup dangling references splash.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (main.isDisposed()) return; main.removeDisposeListener(mainDisposeListener); } }); screens = main.getDisplay().getMonitors(); build(); } private void build() { lDrag = new Label(splash, SWT.NULL); if(!Constants.isOSX) { lDrag.setImage(ImageLoader.getInstance().getImage("dragger")); lDrag.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { ImageLoader.getInstance().releaseImage("dragger"); } }); } lDrag.pack(); this.xSize = lDrag.getSize().x + 3; lDrag.setLocation(0, 0); this.mListener = new MouseAdapter() { public void mouseDown(MouseEvent e) { xPressed = e.x; yPressed = e.y; moving = true; //System.out.println("Position : " + xPressed + " , " + yPressed); } public void mouseUp(MouseEvent e) { moving = false; } }; this.mMoveListener = new MouseMoveListener() { public void mouseMove(MouseEvent e) { if (moving) { int dX = xPressed - e.x; int dY = yPressed - e.y; //System.out.println("dX,dY : " + dX + " , " + dY); Point currentLoc = splash.getLocation(); currentLoc.x -= dX; currentLoc.y -= dY; setSnapLocation(currentLoc); //System.out.println("Position : " + xPressed + " , " + yPressed); } } }; splash.setBackground(Colors.blues[Colors.BLUES_LIGHTEST]); splash.setForeground(Colors.blues[Colors.BLUES_DARKEST]); splash.addMouseListener(mListener); splash.addMouseMoveListener(mMoveListener); lDrag.addMouseListener(mListener); lDrag.addMouseMoveListener(mMoveListener); this.menu = new Menu(splash, SWT.POP_UP); MenuBuildUtils.addMaintenanceListenerForMenu(menu, this); this.beginConstruction(); splash.addListener(SWT.Deiconify, new Listener() { public void handleEvent(Event e) { splash.setVisible(true); splash.setActive(); } }); splash.setSize(xSize + 3, hSize + 2); // Tidy up construction variables. this.mListener = null; this.mMoveListener = null; this.menu = null; // Avoid doing a refresh on construction. this.refresh(); this.constructing = false; this.constructed = true; // Allow subclasses to determine the initial position of the splash object. Point point = this.getInitialLocation(); if (point != null) {splash.setLocation(point);} splash.setVisible(true); } public void buildMenu(Menu menu) { org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items; Object plugin_context_obj = this.getPluginMenuContextObject(); Object[] plugin_context_obj_arg = null; if (plugin_context_obj != null) { plugin_context_obj_arg = new Object[]{plugin_context_obj}; } String[] plugin_menu_ids = this.getPluginMenuIdentifiers(plugin_context_obj); if (plugin_menu_ids != null) { menu_items = MenuItemManager.getInstance().getAllAsArray(plugin_menu_ids); if (menu_items.length > 0) { MenuBuildUtils.addPluginMenuItems(splash, menu_items, menu, true, true, // This will retrieve the plugin download object for associated menus. new MenuBuildUtils.MenuItemPluginMenuControllerImpl(plugin_context_obj_arg) ); new MenuItem(menu, SWT.SEPARATOR); } } MenuItem itemClose = new MenuItem(menu,SWT.NULL); itemClose.setText(MessageText.getString("wizard.close")); itemClose.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { close(); } }); } protected final void setSnapLocation(Point currentLoc) { Rectangle dim = new Rectangle(currentLoc.x,currentLoc.y,splash.getBounds().width,splash.getBounds().height); // find the screen we mostly reside in int topIntersectArea = 0; int bestScreen = 0; for(int i=0;i topIntersectArea) { bestScreen = i; topIntersectArea = area; } } Rectangle screen = screens[bestScreen].getClientArea(); if (currentLoc.x-screen.x < 10) currentLoc.x = screen.x; else if (currentLoc.x-screen.x > screen.width - dim.width - 10) currentLoc.x = screen.x + screen.width - dim.width; if (currentLoc.y-screen.y < 10) currentLoc.y = screen.y; MiniBar mw = this; int height = 0; while (mw != null) { Shell s = mw.getShell(); if (s.isDisposed()) mw = null; else { height += s.getBounds().height - 1; mw = mw.getStucked(); if (mw == this) mw = null; } } if (currentLoc.y-screen.y > screen.height - height - 10) currentLoc.y = screen.y + screen.height - height; MiniBarManager g_manager = MiniBarManager.getManager(); try { g_manager.getMiniBarMonitor().enter(); if (g_manager.countMiniBars() > 1) { Iterator itr = g_manager.getMiniBarIterator(); while (itr.hasNext()) { MiniBar downloadBar = (MiniBar) itr.next(); Point location = downloadBar.getShell().getLocation(); // isn't the height always 10? // Gudy : No it depends on your system font. location.y += downloadBar.getShell().getBounds().height; //Stucking to someone else if (downloadBar != this && downloadBar.getStucked() == null || downloadBar.getStucked() == this) { if (Math.abs(location.x - currentLoc.x) < 10 && location.y - currentLoc.y < 10 && location.y - currentLoc.y > 0) { downloadBar.setStucked(this); currentLoc.x = location.x; currentLoc.y = location.y - 1; } } //Un-stucking from someone if (downloadBar != this && downloadBar.getStucked() == this) { if (Math.abs(location.x - currentLoc.x) > 10 || Math.abs(location.y - currentLoc.y) > 10) downloadBar.setStucked(null); } } } } finally { g_manager.getMiniBarMonitor().exit(); } splash.setLocation(currentLoc); MiniBar mwCurrent = this; while (mwCurrent != null) { currentLoc.y += mwCurrent.getShell().getBounds().height - 1; MiniBar mwChild = mwCurrent.getStucked(); if (mwChild != null && mwChild != this) { Shell s = mwChild.getShell(); if (s.isDisposed()) { mwCurrent.setStucked(null); mwCurrent = null; } else { mwCurrent = mwChild; mwCurrent.getShell().setLocation(currentLoc); } } else mwCurrent = null; } } // // These methods define the management of MiniBars. // public Shell getShell() { return this.splash; } public void setVisible(boolean visible) { splash.setVisible(visible); } public final boolean hasSameContext(MiniBar m) { return this.hasContext(m.getContextObject()); } public final boolean hasContext(Object context) { Object my_context = this.getContextObject(); if (my_context == null) { return context == null; } else { return my_context.equals(context); } } public MiniBar getStucked() { return this.stucked; } public void setStucked(MiniBar mw) { this.stucked = mw; } // Have to be in the SWT thread to do this. public final void forceSaveLocation() { if (!splash.isDisposed()) { this.storeLastLocation(splash.getLocation()); } } public final void close() { if (!splash.isDisposed()) { Display display = splash.getDisplay(); if (display != null && !display.isDisposed()) { display.asyncExec(new AERunnable() { public void runSupport() {dispose();} }); } } manager.unregister(this); } public void dispose() { if (!splash.isDisposed()) { this.forceSaveLocation(); splash.dispose(); } if (bold_font != null && !bold_font.isDisposed()) {bold_font.dispose();} } public final void refresh() { if (splash.isDisposed()) {return;} refresh0(); } // // Subclass methods. // protected abstract void refresh0(); protected abstract void beginConstruction(); protected abstract Object getContextObject(); public String[] getPluginMenuIdentifiers(Object context) { return null; } public Object getPluginMenuContextObject() { return null; } protected Point getInitialLocation() { return null; } protected void storeLastLocation(Point point) { // Do nothing. } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/ImageRepository.java0000644000175000017500000002432611273740250023404 0ustar adrianadrian/* * Created on 29 juin 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.lang.reflect.Method; import javax.imageio.ImageIO; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.program.Program; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import com.aelitis.azureus.ui.skin.SkinProperties; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author Olivier * */ public class ImageRepository { private static final String[] noCacheExtList = new String[] { ".exe" }; private static final boolean forceNoAWT = Constants.isOSX || Constants.isWindows; /**public*/ static void addPath(String path, String id) { SkinProperties[] skinProperties = ImageLoader.getInstance().getSkinProperties(); if (skinProperties != null && skinProperties.length > 0) { skinProperties[0].addProperty(id, path); } } /** * @deprecated Use {@link ImageLoader#getImage(String)} */ public static Image getImage(String name) { return ImageLoader.getInstance().getImage(name); } /** * Gets an image for a file associated with a given program * * @param program the Program */ public static Image getIconFromExtension(File file, String ext, boolean bBig, boolean minifolder) { Image image = null; try { String key = "osicon" + ext; if (bBig) key += "-big"; if (minifolder) key += "-fold"; image = ImageLoader.getInstance().getImage(key); if (ImageLoader.isRealImage(image)) { return image; } ImageLoader.getInstance().releaseImage(key); image = null; ImageData imageData = null; if (Constants.isWindows) { try { //Image icon = Win32UIEnhancer.getFileIcon(new File(path), big); Class enhancerClass = Class.forName("org.gudy.azureus2.ui.swt.win32.Win32UIEnhancer"); Method method = enhancerClass.getMethod("getFileIcon", new Class[] { File.class, boolean.class }); image = (Image) method.invoke(null, new Object[] { file, bBig }); if (image != null) { if (!bBig) image = force16height(image); if (minifolder) image = minifolderize(file.getParent(), image, bBig); ImageLoader.getInstance().addImageNoDipose(key, image); return image; } } catch (Exception e) { Debug.printStackTrace(e); } } else if (Utils.isCocoa) { try { Class enhancerClass = Class.forName("org.gudy.azureus2.ui.swt.osx.CocoaUIEnhancer"); Method method = enhancerClass.getMethod("getFileIcon", new Class[] { String.class, int.class }); image = (Image) method.invoke(null, new Object[] { file.getAbsolutePath(), (int) (bBig ? 128 : 16) }); if (image != null) { if (!bBig) image = force16height(image); if (minifolder) image = minifolderize(file.getParent(), image, bBig); ImageLoader.getInstance().addImageNoDipose(key, image); return image; } } catch (Throwable t) { Debug.printStackTrace(t); } } if (imageData == null) { Program program = Program.findProgram(ext); if (program != null) { imageData = program.getImageData(); } } if (imageData != null) { image = new Image(Display.getDefault(), imageData); if (!bBig) image = force16height(image); if (minifolder) image = minifolderize(file.getParent(), image, bBig); ImageLoader.getInstance().addImageNoDipose(key, image); } } catch (Throwable e) { // seen exceptions thrown here, due to images.get failing in Program.hashCode // ignore and use default icon } if (image == null) { return getImage(minifolder ? "folder" : "transparent"); } return image; } private static Image minifolderize(String path, Image img, boolean big) { Image imgFolder = getImage(big ? "folder" : "foldersmall"); Rectangle folderBounds = imgFolder.getBounds(); Rectangle dstBounds = img.getBounds(); Image tempImg = Utils.renderTransparency(Display.getCurrent(), img, imgFolder, new Point(dstBounds.width - folderBounds.width, dstBounds.height - folderBounds.height), 204); if (tempImg != null) { img.dispose(); img = tempImg; } return img; } private static Image force16height(Image image) { if (image == null) { return image; } Rectangle bounds = image.getBounds(); if (bounds.height != 16) { Image newImage = new Image(image.getDevice(), 16, 16); GC gc = new GC(newImage); try { if (!Constants.isUnix) { // drawImage doesn't work on GTK when advanced is on gc.setAdvanced(true); } gc.drawImage(image, 0, 0, bounds.width, bounds.height, 0, 0, 16, 16); } finally { gc.dispose(); } image.dispose(); image = newImage; } return image; } /** *

    Gets an iconic representation of the file or directory at the path

    *

    For most platforms, the icon is a 16x16 image; weak-referencing caching is used to avoid abundant reallocation.

    * @param path Absolute path to the file or directory * @return The image */ public static Image getPathIcon(final String path, boolean bBig, boolean minifolder) { if (path == null) return null; File file = null; boolean bDeleteFile = false; boolean noAWT = forceNoAWT || !bBig; try { file = new File(path); // workaround for unsupported platforms // notes: // Mac OS X - Do not mix AWT with SWT (possible workaround: use IPC/Cocoa) String key; if (file.isDirectory()) { if (noAWT) { if (Constants.isWindows || Utils.isCocoa) { return getIconFromExtension(file, "-folder", bBig, false); } return getImage("folder"); } key = file.getPath(); } else { final int idxDot = file.getName().lastIndexOf("."); if (idxDot == -1) { if (noAWT) { return getImage("folder"); } key = "?!blank"; } else { final String ext = file.getName().substring(idxDot); key = ext; if (noAWT) return getIconFromExtension(file, ext, bBig, minifolder); // case-insensitive file systems for (int i = 0; i < noCacheExtList.length; i++) { if (noCacheExtList[i].equalsIgnoreCase(ext)) { key = file.getPath(); break; } } } } if (bBig) key += "-big"; if (minifolder) key += "-fold"; key = "osicon" + key; // this method mostly deals with incoming torrent files, so there's less concern for // custom icons (unless user sets a custom icon in a later session) // other platforms - try sun.awt Image image = ImageLoader.getInstance().getImage(key); if (ImageLoader.isRealImage(image)) { return image; } ImageLoader.getInstance().releaseImage(key); image = null; bDeleteFile = !file.exists(); if (bDeleteFile) { file = File.createTempFile("AZ_", FileUtil.getExtension(path)); } java.awt.Image awtImage = null; final Class sfClass = Class.forName("sun.awt.shell.ShellFolder"); if (sfClass != null && file != null) { Method method = sfClass.getMethod("getShellFolder", new Class[] { File.class }); if (method != null) { Object sfInstance = method.invoke(null, new Object[] { file }); if (sfInstance != null) { method = sfClass.getMethod("getIcon", new Class[] { Boolean.TYPE }); if (method != null) { awtImage = (java.awt.Image) method.invoke(sfInstance, new Object[] { new Boolean(bBig) }); } } } } if (awtImage != null) { final ByteArrayOutputStream outStream = new ByteArrayOutputStream(); ImageIO.write((BufferedImage) awtImage, "png", outStream); final ByteArrayInputStream inStream = new ByteArrayInputStream( outStream.toByteArray()); image = new Image(Display.getDefault(), inStream); if (!bBig) { image = force16height(image); } if (minifolder) image = minifolderize(file.getParent(), image, bBig); ImageLoader.getInstance().addImageNoDipose(key, image); if (bDeleteFile && file != null && file.exists()) { file.delete(); } return image; } } catch (Exception e) { //Debug.printStackTrace(e); } if (bDeleteFile && file != null && file.exists()) { file.delete(); } // Possible scenario: Method call before file creation String ext = FileUtil.getExtension(path); if (ext.length() == 0) { return getImage("folder"); } return getIconFromExtension(file, ext, bBig, minifolder); } public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display, SWT.SHELL_TRIM); shell.setLayout(new FillLayout(SWT.VERTICAL)); final Label label = new Label(shell, SWT.BORDER); final Text text = new Text(shell, SWT.BORDER); text.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { Image pathIcon = getPathIcon(text.getText(), false, false); label.setImage(pathIcon); } }); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/PropertiesWindow.java0000644000175000017500000001341711275141740023606 0ustar adrianadrian/* * Created on 02-Oct-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.components.BufferedLabel; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; public class PropertiesWindow { private final Shell shell; public PropertiesWindow( String object_name, String[] keys, String[] values ) { shell = ShellFactory.createMainShell(SWT.APPLICATION_MODAL | SWT.TITLE | SWT.CLOSE |SWT.RESIZE ); shell.setText( MessageText.getString( "props.window.title", new String[]{ object_name })); Utils.setShellIcon(shell); GridLayout layout = new GridLayout(); layout.numColumns = 3; shell.setLayout(layout); final ScrolledComposite scrollable = new ScrolledComposite(shell, SWT.V_SCROLL | SWT.H_SCROLL ); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); gridData.horizontalSpan = 3; scrollable.setLayoutData( gridData ); /* * Main content composite where panels will be created */ final Composite main = new Composite(scrollable, SWT.NONE); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; //layout.verticalSpacing = 0; layout.numColumns = 2; main.setLayout(layout); scrollable.setContent(main); scrollable.setExpandVertical(true); scrollable.setExpandHorizontal(true); /* * Re-adjust scrollbar setting when the window resizes */ scrollable.addControlListener(new ControlAdapter() { public void controlResized(ControlEvent e) { Rectangle r = scrollable.getClientArea(); scrollable.setMinSize(main.computeSize(r.width, SWT.DEFAULT )); } }); gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 3; main.setLayoutData(gridData); for (int i=0;i" )){ msg_label.setText( msg ); value = ""; }else{ msg_label.setText( msg + ":" ); } gridData = new GridData(); gridData.verticalAlignment = GridData.VERTICAL_ALIGN_FILL; msg_label.setLayoutData(gridData); BufferedLabel val_label = new BufferedLabel(main,SWT.WRAP); val_label.setText( value ); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalIndent = 6; val_label.setLayoutData(gridData); } // separator Label labelSeparator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; labelSeparator.setLayoutData(gridData); // buttons new Label(shell,SWT.NULL); Button bOk = new Button(shell,SWT.PUSH); Messages.setLanguageText(bOk, "Button.ok"); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.HORIZONTAL_ALIGN_FILL); gridData.grabExcessHorizontalSpace = true; gridData.widthHint = 70; bOk.setLayoutData(gridData); bOk.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { close(); } }); Button bCancel = new Button(shell,SWT.PUSH); Messages.setLanguageText(bCancel, "Button.cancel"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); gridData.grabExcessHorizontalSpace = false; gridData.widthHint = 70; bCancel.setLayoutData(gridData); bCancel.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { close(); } }); shell.setDefaultButton( bOk ); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ close(); } } }); int shell_width = 400; int main_height = main.computeSize(shell_width, SWT.DEFAULT).y; main_height = Math.max( main_height, 250 ); main_height = Math.min( main_height, 500 ); int shell_height = main_height + 50; shell.setSize( shell_width, shell_height ); Utils.centreWindow( shell ); shell.open(); } protected void close() { if ( !shell.isDisposed()){ shell.dispose(); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/importtorrent/0000755000175000017500000000000011310377444022343 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/importtorrent/wizard/0000755000175000017500000000000011310377636023646 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizard.java0000644000175000017500000001025211171750564030522 0ustar adrianadrian/* * File : ImportTorrentWizard.java * Created : 13-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.importtorrent.wizard; /** * @author parg * */ import java.io.File; import java.io.IOException; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.MessageBox; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.ui.swt.wizard.Wizard; public class ImportTorrentWizard extends Wizard { String torrent_file = ""; String import_file = ""; public ImportTorrentWizard() { super("importTorrentWizard.title"); ImportTorrentWizardInputPanel input_panel = new ImportTorrentWizardInputPanel(this,null); this.setFirstPanel(input_panel); } public void onClose() { // Call the parent class to clean up resources super.onClose(); } protected void setTorrentFile( String str ) { torrent_file = str; } protected String getTorrentFile() { return( torrent_file ); } protected void setImportFile( String str ) { import_file = str; torrent_file = str + ".torrent"; } protected String getImportFile() { return( import_file ); } protected boolean performImport() { File input_file; try{ input_file = new File( getImportFile()).getCanonicalFile(); }catch( IOException e ){ MessageBox mb = new MessageBox(getWizardWindow(),SWT.ICON_ERROR | SWT.OK ); mb.setText(MessageText.getString("importTorrentWizard.process.inputfilebad.title")); mb.setMessage( MessageText.getString("importTorrentWizard.process.inputfilebad.message")+"\n" + e.toString()); mb.open(); return( false ); } File output_file = new File( getTorrentFile() ); if ( output_file.exists()){ MessageBox mb = new MessageBox(this.getWizardWindow(),SWT.ICON_QUESTION | SWT.YES | SWT.NO); mb.setText(MessageText.getString("importTorrentWizard.process.outputfileexists.title")); mb.setMessage(MessageText.getString("importTorrentWizard.process.outputfileexists.message")); int result = mb.open(); if(result == SWT.NO) { return( false ); } } String error_title; String error_detail; try{ TOTorrent torrent; try{ torrent = TOTorrentFactory.deserialiseFromXMLFile( input_file ); try{ torrent.serialiseToBEncodedFile( output_file ); return( true ); }catch( TOTorrentException e ){ //e.printStackTrace(); error_title = MessageText.getString("importTorrentWizard.process.torrentfail.title"); error_detail = TorrentUtils.exceptionToText( e ); } }catch( TOTorrentException e ){ // e.printStackTrace(); error_title = MessageText.getString("importTorrentWizard.process.importfail.title"); error_detail = TorrentUtils.exceptionToText( e ); } }catch( Throwable e ){ error_title = MessageText.getString("importTorrentWizard.process.unknownfail.title"); Debug.printStackTrace( e ); error_detail = e.toString(); } MessageBox mb = new MessageBox(this.getWizardWindow(),SWT.ICON_ERROR | SWT.OK ); mb.setText(error_title); mb.setMessage(error_detail); mb.open(); return( false ); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardOutputPanel.java0000644000175000017500000001107010357107106032713 0ustar adrianadrian/* * File : ImportTorrentWizardOutputPanel.java * Created : 14-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.importtorrent.wizard; /** * @author parg * */ import java.io.File; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.*; public class ImportTorrentWizardOutputPanel extends AbstractWizardPanel { protected boolean file_valid = false; public ImportTorrentWizardOutputPanel( Wizard wizard, IWizardPanel previous ) { super(wizard, previous); } public void show() { wizard.setTitle(MessageText.getString("importTorrentWizard.torrentfile.title")); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); Label label = new Label(panel, SWT.WRAP); gridData = new GridData(); gridData.horizontalSpan = 3; gridData.widthHint = 380; label.setLayoutData(gridData); Messages.setLanguageText(label, "importTorrentWizard.torrentfile.message"); label = new Label(panel,SWT.NULL); Messages.setLanguageText(label, "importTorrentWizard.torrentfile.path"); final Text textPath = new Text(panel,SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); textPath.setLayoutData(gridData); textPath.setText(((ImportTorrentWizard)wizard).getTorrentFile()); Button browse = new Button(panel,SWT.PUSH); Messages.setLanguageText(browse, "importTorrentWizard.torrentfile.browse"); browse.addListener(SWT.Selection,new Listener() { public void handleEvent(Event arg0){ FileDialog fd = new FileDialog(wizard.getWizardWindow(), SWT.SAVE); fd.setFileName(textPath.getText()); fd.setFilterExtensions(new String[]{"*.torrent", "*.tor", Constants.FILE_WILDCARD}); String path = fd.open(); if(path != null) { textPath.setText(path); } } }); textPath.addListener(SWT.Modify, new Listener(){ public void handleEvent(Event event) { String path = textPath.getText(); pathSet( path ); } }); textPath.setText(((ImportTorrentWizard)wizard).getTorrentFile()); textPath.setFocus(); } protected void pathSet( String path ) { ((ImportTorrentWizard)wizard).setTorrentFile( path ); file_valid = false; try { File f = new File(path); if(f.exists()){ if (f.isFile()){ wizard.setErrorMessage(""); file_valid = true; }else{ wizard.setErrorMessage(MessageText.getString("importTorrentWizard.torrentfile.invalidPath")); } }else{ wizard.setErrorMessage(""); file_valid = true; } } catch(Exception e){ wizard.setErrorMessage(MessageText.getString("importTorrentWizard.torrentfile.invalidPath")); } wizard.setFinishEnabled(file_valid); } public boolean isFinishEnabled() { return( file_valid ); } public boolean isFinishSelectionOK() { return( ((ImportTorrentWizard)wizard).performImport() ); } public IWizardPanel getFinishPanel(){ return new ImportTorrentWizardFinishPanel(((ImportTorrentWizard)wizard),this); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardInputPanel.java0000644000175000017500000001042010357107106032510 0ustar adrianadrian/* * File : ImportTorrentWizardInputPanel.java * Created : 14-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.importtorrent.wizard; /** * @author parg * */ import java.io.File; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.*; public class ImportTorrentWizardInputPanel extends AbstractWizardPanel { protected boolean file_valid = false; public ImportTorrentWizardInputPanel( Wizard wizard, IWizardPanel previous ) { super(wizard, previous); } public void show() { wizard.setTitle(MessageText.getString("importTorrentWizard.importfile.title")); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); Label label = new Label(panel, SWT.WRAP); gridData = new GridData(); gridData.horizontalSpan = 3; gridData.widthHint = 380; label.setLayoutData(gridData); Messages.setLanguageText(label, "importTorrentWizard.importfile.message"); label = new Label(panel,SWT.NULL); Messages.setLanguageText(label, "importTorrentWizard.importfile.path"); final Text textPath = new Text(panel,SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); textPath.setLayoutData(gridData); textPath.setText(""); Button browse = new Button(panel,SWT.PUSH); Messages.setLanguageText(browse, "importTorrentWizard.importfile.browse"); browse.addListener(SWT.Selection,new Listener() { public void handleEvent(Event arg0) { FileDialog fd = new FileDialog(wizard.getWizardWindow()); fd.setFileName(textPath.getText()); fd.setFilterExtensions(new String[]{"*.xml", Constants.FILE_WILDCARD}); String path = fd.open(); if(path != null) { textPath.setText(path); } } }); textPath.addListener(SWT.Modify, new Listener(){ public void handleEvent(Event event) { String path = textPath.getText(); ((ImportTorrentWizard)wizard).setImportFile( path ); file_valid = false; try{ File f = new File(path); if( f.exists()){ if (f.isFile()){ file_valid = true; wizard.setErrorMessage(""); }else{ wizard.setErrorMessage(MessageText.getString("importTorrentWizard.importfile.invalidPath")); } } }catch(Exception e){ wizard.setErrorMessage(MessageText.getString("importTorrentWizard.importfile.invalidPath")); } wizard.setNextEnabled( file_valid ); } }); textPath.setText(((ImportTorrentWizard)wizard).getImportFile()); textPath.setFocus(); } public IWizardPanel getNextPanel() { return( new ImportTorrentWizardOutputPanel(wizard,this)); } public boolean isNextEnabled() { return( file_valid ); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardFinishPanel.java0000644000175000017500000000441607745251402032647 0ustar adrianadrian/* * File : ImportTorrentWizardFinishPanel.java * Created : 13-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.importtorrent.wizard; /** * @author parg * */ import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.*; public class ImportTorrentWizardFinishPanel extends AbstractWizardPanel { public ImportTorrentWizardFinishPanel( Wizard wizard, IWizardPanel previous) { super(wizard, previous); } public void show() { wizard.setTitle(MessageText.getString("importTorrentWizard.finish.title")); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); Label label = new Label(panel, SWT.WRAP); gridData = new GridData(); gridData.horizontalSpan = 3; gridData.widthHint = 380; label.setLayoutData(gridData); Messages.setLanguageText(label, "importTorrentWizard.finish.message"); } public boolean isPreviousEnabled() { return( false ); } public void finish() { wizard.switchToClose(); } }azureus-4.3.0.6/org/gudy/azureus2/ui/swt/nat/0000755000175000017500000000000011310377636020200 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/nat/NatTestWindow.java0000644000175000017500000002131211275141740023607 0ustar adrianadrian/* * Created on 14 avr. 2005 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.nat; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.ipchecker.natchecker.NatChecker; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT.TriggerInThread; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; public class NatTestWindow { Display display; Button bTest,bApply,bCancel; StyledText textResults; Checker checker; int serverTCPListenPort; public class Checker extends AEThread { //private int lowPort; //private int highPort; private int TCPListenPort; public Checker(int tcp_listen_port) { super("NAT Checker"); this.TCPListenPort = tcp_listen_port; } public void runSupport() { printMessage(MessageText.getString("configureWizard.nat.testing") + " " + TCPListenPort + " ... "); NatChecker checker = new NatChecker(AzureusCoreFactory.getSingleton(), NetworkAdmin.getSingleton().getMultiHomedServiceBindAddresses(true)[0], TCPListenPort, false); switch (checker.getResult()) { case NatChecker.NAT_OK : printMessage(MessageText.getString("configureWizard.nat.ok") + "\n" + checker.getAdditionalInfo()); break; case NatChecker.NAT_KO : printMessage( "\n" + MessageText.getString("configureWizard.nat.ko") + " - " + checker.getAdditionalInfo()+".\n"); break; default : printMessage( "\n" + MessageText.getString("configureWizard.nat.unable") + ". \n(" + checker.getAdditionalInfo()+").\n"); break; } if (display.isDisposed()) {return;} display.asyncExec(new AERunnable() { public void runSupport() { if(bTest != null && ! bTest.isDisposed()) bTest.setEnabled(true); } }); } } public NatTestWindow() { serverTCPListenPort = COConfigurationManager.getIntParameter( "TCP.Listen.Port" ); final Shell shell = ShellFactory.createMainShell(SWT.BORDER | SWT.TITLE | SWT.CLOSE); shell.setText(MessageText.getString("configureWizard.nat.title")); Utils.setShellIcon(shell); display = shell.getDisplay(); GridLayout layout = new GridLayout(); layout.numColumns = 1; shell.setLayout(layout); Composite panel = new Composite(shell, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); Label label = new Label(panel, SWT.WRAP); gridData = new GridData(); gridData.horizontalSpan = 3; gridData.widthHint = 400; label.setLayoutData(gridData); Messages.setLanguageText(label, "configureWizard.nat.message"); label = new Label(panel, SWT.NULL); label = new Label(panel, SWT.NULL); label = new Label(panel, SWT.NULL); label = new Label(panel, SWT.NULL); Messages.setLanguageText(label, "configureWizard.nat.server.tcp_listen_port"); final Text textServerTCPListen = new Text(panel, SWT.BORDER); gridData = new GridData(); gridData.grabExcessHorizontalSpace = true; gridData.horizontalAlignment = SWT.FILL; textServerTCPListen.setLayoutData(gridData); textServerTCPListen.setText("" + serverTCPListenPort); textServerTCPListen.addListener(SWT.Verify, new Listener() { public void handleEvent(Event e) { String text = e.text; char[] chars = new char[text.length()]; text.getChars(0, chars.length, chars, 0); for (int i = 0; i < chars.length; i++) { if (!('0' <= chars[i] && chars[i] <= '9')) { e.doit = false; return; } } } }); textServerTCPListen.addListener(SWT.Modify, new Listener() { public void handleEvent(Event e) { final int TCPListenPort = Integer.parseInt(textServerTCPListen.getText()); serverTCPListenPort = TCPListenPort; } }); bTest = new Button(panel, SWT.PUSH); Messages.setLanguageText(bTest, "configureWizard.nat.test"); gridData = new GridData(); gridData.widthHint = 70; bTest.setLayoutData(gridData); textResults = new StyledText(panel, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.WRAP ); gridData = new GridData(); gridData.widthHint = 400; gridData.heightHint = 100; gridData.grabExcessVerticalSpace = true; gridData.verticalAlignment = SWT.FILL; gridData.horizontalSpan = 3; textResults.setLayoutData(gridData); textResults.setBackground(panel.getDisplay().getSystemColor(SWT.COLOR_WHITE)); bTest.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { bTest.setEnabled(false); textResults.setText(""); CoreWaiterSWT.waitForCore(TriggerInThread.ANY_THREAD, new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { checker = new Checker(serverTCPListenPort); checker.start(); } }); } }); bApply = new Button(panel,SWT.PUSH); bApply.setText(MessageText.getString("Button.apply")); gridData = new GridData(); gridData.widthHint = 70; gridData.grabExcessHorizontalSpace = true; gridData.horizontalAlignment = SWT.RIGHT; gridData.horizontalSpan = 2; bApply.setLayoutData(gridData); bApply.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { int old_tcp = COConfigurationManager.getIntParameter( "TCP.Listen.Port" ); int old_udp = COConfigurationManager.getIntParameter( "UDP.Listen.Port" ); int old_udp2 = COConfigurationManager.getIntParameter( "UDP.NonData.Listen.Port" ); COConfigurationManager.setParameter("TCP.Listen.Port",serverTCPListenPort); if ( old_tcp == old_udp ){ COConfigurationManager.setParameter("UDP.Listen.Port",serverTCPListenPort); } if ( old_tcp == old_udp2 ){ COConfigurationManager.setParameter("UDP.NonData.Listen.Port",serverTCPListenPort); } COConfigurationManager.save(); shell.close(); } }); bCancel = new Button(panel,SWT.PUSH); bCancel.setText(MessageText.getString("Button.cancel")); gridData = new GridData(); gridData.widthHint = 70; bCancel.setLayoutData(gridData); bCancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { shell.close(); } }); shell.setDefaultButton( bApply ); shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ shell.close(); } } }); shell.pack(); Utils.centreWindow(shell); shell.open(); } public void printMessage(final String message) { if (display == null || display.isDisposed()) return; display.asyncExec(new AERunnable() { public void runSupport() { if (textResults == null || textResults.isDisposed()) return; textResults.append(message); } }); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/wizard/0000755000175000017500000000000011310377636020716 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/wizard/WizardListener.java0000644000175000017500000000167410010753202024516 0ustar adrianadrian/* * File : WizardListener.java * Created : 06-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.wizard; /** * @author parg * */ public interface WizardListener { public void closed(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/wizard/Wizard.java0000644000175000017500000002710511267524620023024 0ustar adrianadrian/* * File : Wizard.java * Created : 30 sept. 2003 00:06:56 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.wizard; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; /** * @author Olivier * */ public class Wizard { private final static int DEFAULT_WIDTH = 500; List listeners = new ArrayList(1); Display display; Shell wizardWindow; Label title; Label currentInfo; Label errorMessage; IWizardPanel currentPanel; Composite panel; Font titleFont; protected Button previous, next, finish, cancel; Listener closeCatcher; int wizardHeight; public Wizard( String keyTitle, boolean modal) { this(modal); setTitleKey(keyTitle); } public Wizard(String keyTitle) { this(keyTitle, false); } public Wizard( boolean modal) { int style = SWT.DIALOG_TRIM | SWT.RESIZE; if (modal) { style |= SWT.APPLICATION_MODAL; } wizardWindow = ShellFactory.createMainShell(style); this.display = wizardWindow.getDisplay(); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; wizardWindow.setLayout(layout); Utils.setShellIcon(wizardWindow); Composite cTitle = new Composite(wizardWindow, SWT.NULL); Color white = display.getSystemColor(SWT.COLOR_WHITE); cTitle.setBackground(white); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); cTitle.setLayoutData(gridData); GridLayout titleLayout = new GridLayout(); titleLayout.numColumns = 1; cTitle.setLayout(titleLayout); title = new Label(cTitle, SWT.NULL); title.setBackground(white); gridData = new GridData(GridData.FILL_HORIZONTAL); title.setLayoutData(gridData); Font font = title.getFont(); FontData[] data = font.getFontData(); for(int i = 0 ; i < data.length ; i++) { data[i].setStyle(SWT.BOLD); } titleFont=new Font(display,data); title.setFont(titleFont); currentInfo = new Label(cTitle, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); currentInfo.setLayoutData(gridData); currentInfo.setBackground(white); errorMessage = new Label(cTitle, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); errorMessage.setLayoutData(gridData); errorMessage.setBackground(white); Color red = display.getSystemColor(SWT.COLOR_RED); errorMessage.setForeground(red); gridData = new GridData(GridData.FILL_HORIZONTAL); new Label(wizardWindow, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(gridData); panel = new Composite(wizardWindow, SWT.NULL); gridData = new GridData(GridData.FILL_BOTH); panel.setLayoutData(gridData); gridData = new GridData(GridData.FILL_HORIZONTAL); new Label(wizardWindow, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(gridData); Composite cButtons = new Composite(wizardWindow, SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); cButtons.setLayoutData(gridData); GridLayout layoutButtons = new GridLayout(); layoutButtons.numColumns = 5; cButtons.setLayout(layoutButtons); gridData = new GridData(GridData.FILL_HORIZONTAL); new Label(cButtons, SWT.NULL).setLayoutData(gridData); cancel = new Button(cButtons, SWT.PUSH); gridData = new GridData(); gridData.widthHint = 90; gridData.horizontalAlignment = GridData.CENTER; cancel.setLayoutData(gridData); Messages.setLanguageText(cancel, "Button.cancel"); previous = new Button(cButtons, SWT.PUSH); gridData = new GridData(); gridData.widthHint = 90; gridData.horizontalAlignment = GridData.END; previous.setLayoutData(gridData); Messages.setLanguageText(previous, "wizard.previous"); next = new Button(cButtons, SWT.PUSH); gridData = new GridData(); gridData.widthHint = 90; gridData.horizontalAlignment = GridData.BEGINNING; next.setLayoutData(gridData); Messages.setLanguageText(next, "wizard.next"); finish = new Button(cButtons, SWT.PUSH); gridData = new GridData(); gridData.widthHint = 90; gridData.horizontalAlignment = GridData.CENTER; finish.setLayoutData(gridData); Messages.setLanguageText(finish, "wizard.finish"); previous.addListener(SWT.Selection, new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event arg0) { clearPanel(); currentPanel = currentPanel.getPreviousPanel(); refresh(); } }); next.addListener(SWT.Selection, new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event arg0) { IWizardPanel nextPanel = currentPanel.getNextPanel(); clearPanel(); currentPanel = nextPanel; refresh(); } }); closeCatcher = new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event event) { event.doit = false; } }; finish.addListener(SWT.Selection, new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event arg0){ finishSelected(); } }); cancel.addListener(SWT.Selection, new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event arg0) { wizardWindow.dispose(); } }); wizardWindow.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent de) { onClose(); } }); wizardWindow.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event e) { if ( e.character == SWT.ESC){ if ( cancel.isEnabled()){ wizardWindow.dispose(); } } } }); wizardHeight = wizardWindow.computeSize(DEFAULT_WIDTH,SWT.DEFAULT).y - 50; wizardWindow.setSize(DEFAULT_WIDTH,400); } private void finishSelected() { if ( currentPanel.isFinishSelectionOK()){ wizardWindow.addListener(SWT.Close, closeCatcher); clearPanel(); currentPanel = currentPanel.getFinishPanel(); refresh(); currentPanel.finish(); } } private void clearPanel() { Control[] controls = panel.getChildren(); for (int i = 0; i < controls.length; i++) { if (controls[i] != null && !controls[i].isDisposed()) controls[i].dispose(); } setTitle(""); setCurrentInfo(""); } private void refresh(){ if (currentPanel == null){ setDefaultButton(); return; } previous.setEnabled(currentPanel.isPreviousEnabled()); next.setEnabled(currentPanel.isNextEnabled()); finish.setEnabled(currentPanel.isFinishEnabled()); setDefaultButton(); currentPanel.show(); panel.layout(); panel.redraw(); insureSize(); } private void setDefaultButton() { if (!wizardWindow.isDisposed()){ display.asyncExec(new AERunnable() { public void runSupport() { if (!wizardWindow.isDisposed()){ Button default_button = null; if ( next.isEnabled()){ default_button = next; }else if ( finish.isEnabled()){ default_button = finish; }else if ( previous.isEnabled()){ default_button = previous; }else if ( cancel.isEnabled()){ default_button = cancel; } if ( default_button != null ){ wizardWindow.setDefaultButton( default_button ); } } } }); } } public Composite getPanel() { return panel; } public void setTitle(String title) { this.title.setText(title); } public void setTitleAsResourceID(String id) { Messages.setLanguageText(title, id); } public void setCurrentInfo(String currentInfo) { this.currentInfo.setText("\t" + currentInfo); } public void setErrorMessage(String errorMessage) { this.errorMessage.setText(errorMessage); } public void setTitleKey(String key) { Messages.setLanguageText(wizardWindow, key); } public void setNextEnabled(boolean enabled) { this.next.setEnabled(enabled); setDefaultButton(); } public void setPreviousEnabled(boolean enabled) { this.previous.setEnabled(enabled); setDefaultButton(); } public void setFinishEnabled(boolean enabled) { this.finish.setEnabled(enabled); setDefaultButton(); } public void setFirstPanel(IWizardPanel panel) { this.currentPanel = panel; refresh(); insureSize(); Utils.centreWindow( wizardWindow ); wizardWindow.open(); } public Shell getWizardWindow() { return wizardWindow; } public String getErrorMessage() { return errorMessage.getText(); } public Display getDisplay() { return display; } public void switchToClose() { if (!wizardWindow.isDisposed()) { display.asyncExec(new AERunnable() { public void runSupport() { if (closeCatcher != null && wizardWindow != null && !wizardWindow.isDisposed()) { wizardWindow.removeListener(SWT.Close, closeCatcher); cancel.setText(MessageText.getString("wizard.close")); cancel.setEnabled(true); setDefaultButton(); } } }); } } public void onClose() { if (titleFont != null && !titleFont.isDisposed()) { titleFont.dispose(); titleFont=null; } for (int i=0;i wizardWindow.getSize().y) wizardWindow.setSize(p.x,height); } public void addListener( WizardListener l ) { if (wizardWindow.isDisposed() && closeCatcher != null) { l.closed(); } listeners.add(l); } public void removeListener( WizardListener l ) { listeners.remove(l); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/wizard/AbstractWizardPanel.java0000644000175000017500000000324207742625304025470 0ustar adrianadrian/* * File : AbstractWizardPanel.java * Created : 30 sept. 2003 00:12:11 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.wizard; /** * @author Olivier * */ public abstract class AbstractWizardPanel implements IWizardPanel { protected IWizardPanel previousPanel; protected Wizard wizard; public AbstractWizardPanel(Wizard wizard, IWizardPanel previousPanel) { this.previousPanel = previousPanel; this.wizard = wizard; } public boolean isPreviousEnabled() { return !(this.previousPanel == null); } public boolean isNextEnabled() { return false; } public boolean isFinishEnabled() { return false; } public IWizardPanel getPreviousPanel() { return previousPanel; } public IWizardPanel getNextPanel() { return null; } public IWizardPanel getFinishPanel() { return null; } public boolean isFinishSelectionOK() { return( true ); } public void finish() {} } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/wizard/IWizardPanel.java0000644000175000017500000000300707742625304024114 0ustar adrianadrian/* * File : IWizardPanel.java * Created : 30 sept. 2003 00:20:26 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swt.wizard; /** * @author Olivier * */ public interface IWizardPanel { public void show(); public IWizardPanel getNextPanel(); public IWizardPanel getPreviousPanel(); public IWizardPanel getFinishPanel(); public boolean isPreviousEnabled(); public boolean isNextEnabled(); public boolean isFinishEnabled(); /** * This method is called when the "finish" button is pressed. It allows operations to be * carried out before the "finish" panel is shown. * @return true - carry on and show the finish panel; false - operation failed, * leave on current panel */ public boolean isFinishSelectionOK(); public void finish(); } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsinstaller/0000755000175000017500000000000011310377636023015 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWListPanel.java0000644000175000017500000001767011171750562026144 0ustar adrianadrian/* * Created on 29 nov. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.pluginsinstaller; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.html.HTMLUtils; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.installer.StandardPlugin; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.components.LinkArea; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT.TriggerInThread; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import org.gudy.azureus2.ui.swt.wizard.Wizard; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; /** * @author Olivier Chalouhi * */ public class IPWListPanel extends AbstractWizardPanel { Table pluginList; LinkArea link_area; public IPWListPanel( Wizard wizard, IWizardPanel previous ) { super(wizard, previous); } public void show() { wizard.setTitle(MessageText.getString("installPluginsWizard.list.title")); wizard.setErrorMessage(""); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 1; panel.setLayout(layout); final Label lblStatus = new Label(panel,SWT.NULL); GridData data = new GridData(GridData.FILL_HORIZONTAL); lblStatus.setLayoutData(data); Messages.setLanguageText(lblStatus,"installPluginsWizard.list.loading"); pluginList = new Table(panel,SWT.BORDER | SWT.V_SCROLL | SWT.CHECK | SWT.FULL_SELECTION | SWT.SINGLE); pluginList.setHeaderVisible(true); data = new GridData(GridData.FILL_HORIZONTAL); data.heightHint = 120; pluginList.setLayoutData(data); TableColumn tcName = new TableColumn(pluginList,SWT.LEFT); Messages.setLanguageText(tcName,"installPluginsWizard.list.name"); tcName.setWidth(200); TableColumn tcVersion = new TableColumn(pluginList,SWT.LEFT); Messages.setLanguageText(tcVersion,"installPluginsWizard.list.version"); tcVersion.setWidth(150); Label lblDescription = new Label(panel,SWT.NULL); Messages.setLanguageText(lblDescription,"installPluginsWizard.list.description"); link_area = new LinkArea( panel ); data = new GridData(GridData.FILL_HORIZONTAL); data.heightHint = 100; link_area.getComponent().setLayoutData(data); CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD, new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { final StandardPlugin plugins[]; try { plugins = ((InstallPluginWizard)wizard).getStandardPlugins(core); Arrays.sort( plugins, new Comparator() { public int compare( Object o1, Object o2) { return(((StandardPlugin)o1).getName().compareToIgnoreCase(((StandardPlugin)o2).getName())); } }); } catch(final Exception e) { Debug.printStackTrace(e); wizard.getDisplay().asyncExec(new AERunnable() { public void runSupport() { link_area.addLine( Debug.getNestedExceptionMessage(e)); } }); return; } wizard.getDisplay().asyncExec(new AERunnable() { public void runSupport() { lblStatus.setText( ((InstallPluginWizard)wizard).getListTitleText()); List selected_plugins = ((InstallPluginWizard)wizard).getPluginList(); for(int i = 0 ; i < plugins.length ; i++) { StandardPlugin plugin = plugins[i]; if(plugin.getAlreadyInstalledPlugin() == null) { if(pluginList == null || pluginList.isDisposed()) return; TableItem item = new TableItem(pluginList,SWT.NULL); item.setData(plugin); item.setText(0,plugin.getName()); boolean selected = false; for (int j=0;j 0 ){ pluginList.select(0); loadPluginDetails( pluginList.getItem(0)); } } }); } }); pluginList.addListener(SWT.Selection,new Listener() { public void handleEvent(Event e) { if(pluginList.getSelectionCount() > 0) { loadPluginDetails( pluginList.getSelection()[0]); } updateList(); } }); } protected void loadPluginDetails( final TableItem selected_item ) { link_area.reset(); link_area.addLine( MessageText.getString( "installPluginsWizard.details.loading")); final StandardPlugin plugin = (StandardPlugin) selected_item.getData(); AEThread detailsLoader = new AEThread("Detail Loader") { public void runSupport() { final String description = HTMLUtils.convertListToString(HTMLUtils.convertHTMLToText(plugin.getDescription(),"")); wizard.getDisplay().asyncExec(new AERunnable() { public void runSupport() { if(pluginList == null || pluginList.isDisposed() || pluginList.getSelectionCount() ==0) return; if(pluginList.getSelection()[0] != selected_item) return; link_area.reset(); link_area.setRelativeURLBase( plugin.getRelativeURLBase()); link_area.addLine(description); } }); } }; detailsLoader.setDaemon(true); detailsLoader.start(); } public boolean isNextEnabled() { return(((InstallPluginWizard)wizard).getPluginList().size() > 0 ); } public IWizardPanel getNextPanel() { return new IPWInstallModePanel(wizard,this); } public void updateList() { ArrayList list = new ArrayList(); TableItem[] items = pluginList.getItems(); for(int i = 0 ; i < items.length ; i++) { if(items[i].getChecked()){ list.add(items[i].getData()); } } ((InstallPluginWizard)wizard).setPluginList(list); ((InstallPluginWizard)wizard).setNextEnabled( isNextEnabled() ); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWModePanel.java0000644000175000017500000001100610652265226026101 0ustar adrianadrian/* * Created on 29 nov. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.pluginsinstaller; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import org.gudy.azureus2.ui.swt.wizard.Wizard; /** * @author Olivier Chalouhi * */ public class IPWModePanel extends AbstractWizardPanel { private static final int MODE_FROM_LIST = 0; private static final int MODE_FROM_FILE = 1; //private static final int MODE_FROM_URL = 2; private int mode = MODE_FROM_LIST; public IPWModePanel( Wizard wizard, IWizardPanel previous ) { super(wizard, previous); } public void show() { int userMode = COConfigurationManager.getIntParameter("User Mode"); wizard.setTitle(MessageText.getString("installPluginsWizard.mode.title")); wizard.setErrorMessage(""); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 1; panel.setLayout(layout); Button bListMode = new Button(panel,SWT.RADIO); Messages.setLanguageText(bListMode,"installPluginsWizard.mode.list"); bListMode.setData("mode",new Integer(MODE_FROM_LIST)); if(((InstallPluginWizard)wizard).mode == MODE_FROM_LIST) bListMode.setSelection(true); Button bFileMode = new Button(panel,SWT.RADIO); Messages.setLanguageText(bFileMode,"installPluginsWizard.mode.file"); bFileMode.setData("mode",new Integer(MODE_FROM_FILE)); if(((InstallPluginWizard)wizard).mode == MODE_FROM_FILE) bFileMode.setSelection(true); Listener modeListener = new Listener() { public void handleEvent(Event e) { mode = ((Integer) e.widget.getData("mode")).intValue(); ((InstallPluginWizard)wizard).mode = mode; } }; bListMode.addListener(SWT.Selection,modeListener); bFileMode.addListener(SWT.Selection,modeListener); if(userMode < 2){ Group cWiki = new Group(panel, SWT.WRAP); cWiki.setText(MessageText.getString("installPluginsWizard.installMode.info.title")); gridData = new GridData( GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); gridData.verticalIndent = 15; cWiki.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 4; layout.marginHeight = 0; cWiki.setLayout(layout); gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); gridData.horizontalIndent = 10; gridData.horizontalSpan = 4; Label label = new Label(cWiki, SWT.WRAP); label.setLayoutData( gridData ); label.setText(MessageText.getString("installPluginsWizard.installMode.info.text")); } } public IWizardPanel getNextPanel() { switch(mode) { case MODE_FROM_LIST : return new IPWListPanel(wizard,this); case MODE_FROM_FILE : return new IPWFilePanel(wizard,this); } return null; } public boolean isNextEnabled() { return true; } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsinstaller/InstallPluginWizard.java0000644000175000017500000001032211171750562027622 0ustar adrianadrian/* * Created on 29 nov. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.pluginsinstaller; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.wizard.Wizard; import com.aelitis.azureus.core.AzureusCore; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.installer.InstallablePlugin; import org.gudy.azureus2.plugins.installer.PluginInstallerListener; import org.gudy.azureus2.plugins.installer.StandardPlugin; /** * @author Olivier Chalouhi * */ public class InstallPluginWizard extends Wizard { int mode; StandardPlugin[] standard_plugins; List plugins = new ArrayList(); boolean shared = false; String list_title_text; public static void register( final AzureusCore core, final Display display ) { core.getPluginManager().getPluginInstaller().addListener( new PluginInstallerListener() { public boolean installRequest( final String reason, final InstallablePlugin plugin ) throws PluginException { if ( plugin instanceof StandardPlugin ){ display.asyncExec( new Runnable() { public void run() { new InstallPluginWizard( reason, (StandardPlugin)plugin ); } }); return( true ); }else{ return( false ); } } }); } public InstallPluginWizard() { super("installPluginsWizard.title"); IPWModePanel mode_panel = new IPWModePanel(this,null); setFirstPanel(mode_panel); } public InstallPluginWizard( String reason, StandardPlugin plugin ) { super("installPluginsWizard.title"); standard_plugins = new StandardPlugin[]{ plugin }; list_title_text = reason; plugins = new ArrayList(); plugins.add( plugin ); IPWListPanel list_panel = new IPWListPanel(this,null); setFirstPanel(list_panel); } protected StandardPlugin[] getStandardPlugins(AzureusCore core) throws PluginException { if ( standard_plugins == null ){ standard_plugins = core.getPluginManager().getPluginInstaller().getStandardPlugins(); } return( standard_plugins ); } protected String getListTitleText() { if ( list_title_text == null ){ list_title_text = MessageText.getString( "installPluginsWizard.list.loaded" ); } return( list_title_text ); } public void onClose() { // Call the parent class to clean up resources super.onClose(); } public void setPluginList(List _plugins) { plugins = _plugins; } public List getPluginList() { return( plugins ); } public void performInstall() { InstallablePlugin[] ps = new InstallablePlugin[ plugins.size()]; plugins.toArray( ps ); if ( ps.length > 0 ){ try{ ps[0].getInstaller().install(ps,shared); }catch(Exception e){ Debug.printStackTrace(e); Logger.log(new LogAlert(LogAlert.REPEATABLE, "Failed to initialise installer", e)); } } } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWFilePanel.java0000644000175000017500000001131711171750562026100 0ustar adrianadrian/* * Created on 30 nov. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.pluginsinstaller; import java.io.File; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.installer.InstallablePlugin; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.mainwindow.ListenerNeedingCoreRunning; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import org.gudy.azureus2.ui.swt.wizard.Wizard; import com.aelitis.azureus.core.AzureusCore; /** * @author Olivier Chalouhi * */ public class IPWFilePanel extends AbstractWizardPanel { Text txtFile; boolean valid = false; public IPWFilePanel( Wizard wizard, IWizardPanel previous) { super(wizard,previous); } public void show() { wizard.setTitle(MessageText.getString("installPluginsWizard.file.title")); wizard.setErrorMessage(""); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); Label label = new Label(panel,SWT.NULL); Messages.setLanguageText(label,"installPluginsWizard.file.file"); txtFile = new Text(panel,SWT.BORDER); GridData data = new GridData(GridData.FILL_HORIZONTAL); txtFile.setLayoutData(data); txtFile.addListener(SWT.Modify,new ListenerNeedingCoreRunning() { public void handleEvent(AzureusCore core, Event event) { checkValidFile(core); } } ); Button btnBrowse = new Button(panel,SWT.PUSH); Messages.setLanguageText(btnBrowse,"installPluginsWizard.file.browse"); btnBrowse.addListener(SWT.Selection,new Listener() { public void handleEvent(Event event) { FileDialog fd = new FileDialog(wizard.getWizardWindow()); fd.setFilterExtensions(new String[] {"*.zip;*.jar"}); fd.setFilterNames(new String[] {"Azureus Plugins"}); String fileName = fd.open(); if(fileName != null) txtFile.setText(fileName); } }); } private void checkValidFile(AzureusCore core) { String fileName = txtFile.getText(); String error_message = null; try { File f = new File(fileName); if (f.isFile() && (f.getName().endsWith(".jar") || f.getName().endsWith(".zip"))) { wizard.setErrorMessage(""); wizard.setNextEnabled(true); List list = new ArrayList(); InstallablePlugin plugin = core.getPluginManager().getPluginInstaller().installFromFile( f); list.add(plugin); ((InstallPluginWizard) wizard).plugins = list; valid = true; return; } } catch (org.gudy.azureus2.plugins.PluginException e) { error_message = e.getMessage(); Debug.printStackTrace(e); } catch (Exception e) { error_message = null; Debug.printStackTrace(e); } valid = false; if (!fileName.equals("")) { String error_message_full; if (new File(fileName).isFile()) { error_message_full = MessageText.getString("installPluginsWizard.file.invalidfile"); } else { error_message_full = MessageText.getString("installPluginsWizard.file.no_such_file"); } if (error_message != null) { error_message_full += " (" + error_message + ")"; } wizard.setErrorMessage(error_message_full); wizard.setNextEnabled(false); } } public boolean isNextEnabled() { return valid; } public IWizardPanel getNextPanel() { return new IPWInstallModePanel(wizard,this); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWInstallModePanel.java0000644000175000017500000000705710373051016027431 0ustar adrianadrian/* * Created on 29 nov. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.pluginsinstaller; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import org.gudy.azureus2.ui.swt.wizard.Wizard; /** * @author Olivier Chalouhi * */ public class IPWInstallModePanel extends AbstractWizardPanel { private static final int MODE_USER = 0; private static final int MODE_SHARED = 1; public IPWInstallModePanel( Wizard wizard, IWizardPanel previous ) { super(wizard, previous); } public void show() { wizard.setTitle(MessageText.getString("installPluginsWizard.installMode.title")); wizard.setErrorMessage(""); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 1; panel.setLayout(layout); // default is shared installation ((InstallPluginWizard) wizard).shared = true; Button bSharedMode = new Button(panel,SWT.RADIO); Messages.setLanguageText(bSharedMode,"installPluginsWizard.installMode.shared"); bSharedMode.setData("mode",new Integer(MODE_SHARED)); bSharedMode.setSelection(true); GridData data = new GridData(GridData.FILL_VERTICAL); data.verticalAlignment = GridData.VERTICAL_ALIGN_END; bSharedMode.setLayoutData(data); Button bUserMode = new Button(panel,SWT.RADIO); Messages.setLanguageText(bUserMode,"installPluginsWizard.installMode.user"); bUserMode.setData("mode",new Integer(MODE_USER)); data = new GridData(GridData.FILL_VERTICAL); data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; bUserMode.setLayoutData(data); Listener modeListener = new Listener() { public void handleEvent(Event e) { ((InstallPluginWizard) wizard).shared = ((Integer) e.widget.getData("mode")).intValue() == MODE_SHARED; } }; bUserMode.addListener(SWT.Selection,modeListener); bSharedMode.addListener(SWT.Selection,modeListener); } public boolean isFinishEnabled() { return( true ); } public IWizardPanel getFinishPanel() { return new IPWFinishPanel(wizard,this); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWFinishPanel.java0000644000175000017500000000500010373051016026420 0ustar adrianadrian/* * Created on 29 nov. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.pluginsinstaller; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel; import org.gudy.azureus2.ui.swt.wizard.IWizardPanel; import org.gudy.azureus2.ui.swt.wizard.Wizard; /** * @author Olivier Chalouhi * */ public class IPWFinishPanel extends AbstractWizardPanel { public IPWFinishPanel( Wizard wizard, IWizardPanel previous) { super(wizard, previous); } public void show() { wizard.setTitle(MessageText.getString("installPluginsWizard.finish.title")); wizard.setErrorMessage(""); Composite rootPanel = wizard.getPanel(); GridLayout layout = new GridLayout(); layout.numColumns = 1; rootPanel.setLayout(layout); Composite panel = new Composite(rootPanel, SWT.NULL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL); panel.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 1; panel.setLayout(layout); Label lblExplanation = new Label(panel,SWT.WRAP); GridData data = new GridData(GridData.FILL_BOTH); lblExplanation.setLayoutData(data); Messages.setLanguageText(lblExplanation,"installPluginsWizard.finish.explanation"); } public void finish() { ((InstallPluginWizard)wizard).performInstall(); wizard.switchToClose(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/swing/0000755000175000017500000000000011310377636017730 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/swing/UISwingImageRepository.java0000644000175000017500000000377411023343700025160 0ustar adrianadrian/* * File : UISwingImageRepository.java * Created : 31-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.swing; /** * This class is used by the remote applet UI. * * @author parg * */ import java.io.*; import java.awt.*; import javax.swing.*; import javax.imageio.*; import org.gudy.azureus2.ui.common.*; public class UISwingImageRepository { public static Image getImage( String name ) { try{ return(ImageIO.read(UIImageRepository.getImageAsStream(name))); }catch( Throwable e ){ // some versions of Opera don't have the imageio stuff available it seems // so catch all errors and return null e.printStackTrace(); return( null ); } } public static InputStream getImageAsStream( String name ) { return( UIImageRepository.getImageAsStream(name)); } public static Image getImage( InputStream is ) { try{ return(ImageIO.read(is)); }catch( Throwable e ){ e.printStackTrace(); return( null ); } } public static Icon getIcon( String name ) { Image image = getImage( name ); return( image==null?null:new ImageIcon( image )); } public static Icon getIcon( InputStream is ) { Image image = getImage( is ); return( image==null?null:new ImageIcon( image )); } } azureus-4.3.0.6/org/gudy/azureus2/ui/icons/0000755000175000017500000000000011310377466017715 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/icons/yellowled.gif0000644000175000017500000000106010233531024022362 0ustar adrianadrianGIF89a00@``@@@uǁ ᾏr{ LJ@Dž@Sn+w9ljP̤ϭ!Z,ZWUSSUXYTV7>RTYTN (ITXV&,1PZU0 #6:HUS.38GS !%+S -2Dsb y6*B`\#BgVM2  _ UufkS"! =$Ы?#l˲W>h1w:X)Ç/#YM$Cn<:k$Pߨ/_놕J8&"QI>}:~ٌ 0!"~آs1[ݰQTlёFp8LkOZAJA/U}<96;ȐOQg޹z{fP Ug{2V&@hQ߻{GSTI#6~!զ7nޙn<"u*̷ f@rdg]1 BJnW^;%bG>U]Q]?T4LqQSRsϳ&é<~RawɫZ4in(tۀoêD7<*mSW;24lu8T~R])[kRjp:hK{%gլZyt_Դ IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/top.gif0000644000175000017500000000167607770226420021216 0ustar adrianadrianGIF89a 4 6?8 ?NRY0E;E?F#E#F%I&M(Q)U*Y,],]>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~!, H@Vڴ946@SkmcW[ib8;tYX%cg6jϒ+uH`zy&1aw.6kЖKiLbQsӗfU"4fGy%9Pmՠ)+ȁ!ɂg%\֠a;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/btn_rss_green_bud.png0000644000175000017500000000113011225745000024066 0ustar adrianadrianPNG  IHDR􃯪tIME sTw pHYs B4gAMA aIDATx]ka|3ξ2QX!QVie*+ Ak2 (S ADQP&MVLp>grs+Nئ."A B2;`\QhEF'H9pJ֝Eƕ ."!s[5yv=c9V4O3>GѿM=@(Lq| qKotw j%Av# l־re w`H,=zپ n3hDAgAdDں\ L*,ٹ(Fvr|c:jJF} À_ɥRj~ I}OP OT32)BG #I* !9ʭtM*ut,J_]l~*tb~);EN#0԰P3튗--PB(Ua컵'Zr۫ilEl/_.Ah } HXCIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/host.gif0000644000175000017500000000172107765157204021367 0ustar adrianadrianGIF89a {{ ~'-0049<<=<6?GKQV[>N)J!X"\JVgwxyz*\#f9p/|1|FVCWB_J_DdJsKvO{R~ !()8;;5(FHQUQZSTTbipuuw!,  B&\b7|hPb! gQS'Oe!&M2ACC0Y#/[x(DI5x1@"wH0 @ 8M!F6pfA\:dH0C !l$1ÆOF 4n`! =A4 `@@;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/btn_rss_subscribe_orange_30x14.png0000644000175000017500000000204211105222574026315 0ustar adrianadrianPNG  IHDR89sBIT|d pHYs B4tEXtCreation Time11/6/08OĝtEXtSoftwareAdobe Fireworks CS3F{IDAT8]h\Es?Id؈v-Z,F*F5?腈`URoLX)FJcI%H6%.v잜/db377;Zg@#BLq L̙ +נ4 n%62L;:44@~{JP0ڸc l|EO̧"jpמV^pmh] G+W 7KA(W#*X]IHmC`M}lc| j=^.oM_<WbFl!SoaӜILT4(M8bR\$E)=5uXRqL'7$Y6Zv4i(OCLV-``@i5s`>`~UOq Ŀ?"X#?v^+^E,;IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/info.gif0000644000175000017500000000040010040064644021317 0ustar adrianadrianGIF89a !, 0Iø'@( X]`RCΣ@섬&ǣH0+1[ sEե1wLcD^ܪܶK}uFwdU+z9YFg]aN63[c%`W7V72/0!"õǻ˵;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/toolbar/0000755000175000017500000000000011310377436021354 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/icons/toolbar/top.gif0000644000175000017500000000213407770226420022646 0ustar adrianadrianGIF89arsux { { w      ! # $( * .0$,0==?5;BCGBEFFGJNHNTY"C#J!W#[#]*T"a%`6fdefhjklmko nrstsvwux wyz}~s}"a"b'j4p"w/~P\YbFhGnAqRaTeUiWnRuU}Xsdlbyxxy{z~  &!'$%((-88<___jGHLVYhou!,Y 8L f*\(0̎7nb|aHю>V)G=zx0p2yR!B/I  {rϞ\&d8#6H٬Y իg3@RٲUY[〆=^T8⤮]'L˗$Dd #I≮#hLeRƌϠCb8Tƒ $@P` Ȼ;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/toolbar/run.gif0000644000175000017500000000220307770104624022646 0ustar adrianadrianGIF89a3>FEW _NRWSUc'R-\.]<_"a*b=`]^_ah c am dtvw q{|t qfhmhayll}u!i'p*r,u)w+y5u8p0{Hg@eBiCkOtHsTpQv     19:*%4= %<7035 ]oistt{|}AJSUBFIBKWfvwcs{tydcK^TX\_b{y된䠭ͫŵ“ғރ!, - >;QO<%<ꙫ&(_ͥJAJ(b mD 2nHPS8$ :H "hhX`sgO*+;PSi:JU DM)nbEgKa܌0r fI\Mv ZC V(3&,zbҀHSKAmʀq$\s14lVN@ _L"]9է3``1Đ`)DIOH.j̷ɀ Y$TH!H ^lЀ0r{ D&(Yt 8 x;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/toolbar/editcolumns.gif0000644000175000017500000000205511033205612024357 0ustar adrianadrianGIF89a䬪zLNL̶\^\Ծ̴Ħdfd̶Ծ̮쬮\Z\̺dbdԴĪ$"$ljlĢ`mEAB|~~ hH| ` @YA~Pnp&FH~ _ |0*AYA~ W`YD~|`A~|JYA|~@xPFn hl ̩Y4+|h||p|`|m7|J7+||X+|n4d<L|W|wOmnd|-`4-dAO~|t 6hO d 4dd||Yp&FHG!,耠\p p  `p (1!@$Rl`Ã(`QPr@U!"6\0gSMG 1`@Jn5Rhłhe".!⅍3BSe_ P"A t}wᎣ#K>Xː+<"BXaƌnS[|9CGՂ`4 9{1B^d?gAd[H~65 !<;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/toolbar/new.gif0000644000175000017500000000205507770104624022640 0ustar adrianadrianGIF89atx!4,i,h@  3"FD:|(qb #lq# g` JrL c3V4# **`cO2^!M9CJ ,,P@̎1^`B6}ӋGײ79ߗ&6JDʪJI|`e͒Lq0A%\M6tv5Nv|:b&t ~e#q4sBsuF HI 3ˬ s,[4 ׎Ed,h4DqMj.vXͻ}S.guar+FM #C5ZdX60?o<6-h`͢pB!C'b]Q&0::h5^k36u5[~}&ʥ9|T&8BF RKBSVXZ]ACR[ak"O$J#F-@%S(W,[ W"X0M0K4O9]=Y"`%b'`'e/`)f-j2c4e4g6i7k0l3n6p9s:w]n۞1KflRhy̑ٲcc()"vG:hӌ2CJ(|@ ?Ѓ. dA C ;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/toolbar/stop.gif0000644000175000017500000000210407770104624023027 0ustar adrianadrianGIF89aadfgiklnprsux|m'',,--..// !!!!!!""""##$$%%66&&((**++//22447799;;>>@@CCGGJJLLMMOOQQVVYY__``bbddeeiinnppqqssuuvvꄄ뇇쐐!e,HZf`D "@hȀB  B.^BI Vΐ˗0aFAAcrs[4Cѣb4BJPJ #Nhʵ+' Pٳh(I đ.pʅ% $?$Ad߿ApGQ¸1#6 K 0!3 RCd?AΞ k6^˞L9rͻwNYμs#Aj{ؓ 0L!O^ ! (@`@P;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/toolbar/bottom.gif0000644000175000017500000000213207770226420023346 0ustar adrianadrianGIF89artw{ {}|   !%!%*,.!!')-123569:23::;<=>$$0025<<B@AEIIMPQV/S U"Y#]$^-`/f/gZ\efghxgjlopqqrstqwsvvy } |{ { }x| pHHKPMUOZTTP^CbRbTgchatk|z}z} %&(.4408KBGEFMOT\bgv|!,Ey䇏9pبѢS*r^t C`SY^4c˞z씍 ڋpVd)[J7w9qaD|Z0P`.(R)^׹$ #'\tYhútF9s݄@mD5F>F>D>@7B9G@XTojnmnnqopjvnzn~orrrr{q~r ".//6800?*8! &)63=#B-C,C.D.L:A+B$I(N)S-X*].Z/P1P2W8X9Z;[ʡK.PD$# K4aZ󣂞HtrbT $89-QM0[R q?ĴacS)% a(0f<aʠ☋&hGͦ,eI9|9ɒ6fl`p%P 00P(Ǒ\@ 1^iР!'0`/\PqaEbd `B A@BPPgQ -ЁvM0^5pA A |M'U呡@;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/toolbar/down.gif0000644000175000017500000000177307770104624023024 0ustar adrianadrianGIF89ar{ y||~    !&$ * .+05:3 4<?$$(.+6.=0013DDKHMLRT0E!W"Y#\$]4L6S9[8mmozx}~zyTTFi /#&(*00235;fAACGGUafgo~!t,H*\P-V0QbĆ *P0#c,(S\E .̙IMU(Gϟ@ʉC#NYʴ)2_!$õ+W0L~!'xY,DCA"DJ ro=B!X`*2B v~d%Hd^A+W4ͰC.[n"@ sͻ;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/toolbar/open_no_default.gif0000644000175000017500000000225407770104624025211 0ustar adrianadrianGIF89a%(%1 2;=3"%(( )9;3;= 4,.4=9"5BF$Awh &[mk֨q 80] GO} @PP“9-Cr+ `G1%#+T'Bn\QRP dBp;뜓5v^n@xByCzE{G}H~JfLOQSTVXY_bdv螟묜!`,s% A*\0$58`Hq` _`"Ft# CRˑ P $MI*x F,@AfV*BpTJu* <^ѤW7 8hƒK(AdEd ;D>T8ᅍk`"#pE … ,ȓ=>=" x X }D 9Cn 60!1ONx@;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/export.gif0000644000175000017500000000173407765157204021737 0ustar adrianadrianGIF89a !%,.5 2 ?JFFHL!S(c:w I M$#O$$W$,U,7a 1s2;d?5c;=p>Gpy<-KN})IGZKUWYce{{qt}y~w{Ę_CcQjU~~p(8%ɒgڗjߩOոGN13:LM[~\zšƏŐŘʚΧǭ̱ƿ̲ԼѴܹؿ޹՟լ!, + (+Àe*V| !ͣ@QC Y*4J~̈I*4+,$$QE!ッ%JRs BRthp:$5 R$DT !琣>D0Xi!r ' ?mT0%2c2RP $D@AT ;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/error.gif0000644000175000017500000000310210040064626021517 0ustar adrianadrianGIF89a )!!)))))11!!1119999BBBJJ99RRRZcc11kkRRkccssccsss{{Zc{{kkRRss99kkssƥ֭!!11ZZƵ99!!JJ11JJZZssƥƽ!!BBJJΔ99BBRR{11JJ甔祥絵!!ccs{{!!))99RRRZZZZc!!))1199BBJJRRZZcckkss{{!, Hp<&IdH3#J$gPJ2etҤHHRJ4qԉ&L(Itg ɈzIB%K:ʄ˕<ڙrӗ/YD#)CHq%L;*IҤ"A(HֈsADRC5b#H Az$G yTv!)R;F4rT؍8ҠDg5~\x_7\1 P{u>c7[p <9"'-ApOȰ] eW,}c ptRdl|wرXx8y[ha@]H`mT|!!"7FPhE2!b FY(yQh@ FaKf"E`BaĘ?pcFacE%V &;pfHMB pj?g +?z$PDyBPƙ;, 7\d "橧1@C4h'T +4@aį; & ! Q8B68cfKC_g 0 T] 11\ !$<;1л I(qn=$!4` B!l 0E&.1O)L/+s10PBB~NA805RPA o `.P}Dd"@patEXtSoftwareAdobe ImageReadyqe<$IDATx] Ue_pS8x\_Jz HxrEo] k K`Ih2 sixqev_}M3@߅+EYyJOwo=1IK>TS"5[bT:A-f5@ͩ1igX pVfDoKBnʛT&$~3aBE{Zf Õ5&0%"5 ?3feb*o{H.`+}I[g`)TfK=V9Vc3 m- 98Ŀ/vIE!Srp+=Ggw7b淖^#.齢;p5iC:7ӹ]YY1b,I:Je J im1|.( m5Vc}ϊsW]ͽf-rtdW-p?1̀;Bb]rz~s>KWFm9LD~~G4z,psD97*KGpxS# u$bK9 ; :"I>?um'̽x}fݢ 2)K f 5`G(\dQl[NsI/+`!f~f̑pDm@_`Ɨ^b1 <@Ydch9T*]`VxaI,BrTbQ~ W6b3g ]?y(~$GU>,MHzcG3M:G9Q)? @/SaWnK8zD[ryRV571+6DF:R[=y1D#̆}u8s0[MG5Ru_LBNt1ijkIH@!zT<@AZ5p:\4qH! f?GN`h@Rƭ w?ɪ" I% ㇵ'ڑ-D,Ztm pc={hW(+TcKK Gu6jFcU"G1@jy (O9%QDEGʑMTf Rܩ[I)C=+L  @Gt 3' @6Ѩ@B^8wTut"dWgsz* x(eUrǹS@mLyA[0TzXE'1}WE *]_+eU7ChRajQSS E .K;H/#*eb?޺lɊkG~l)!0%vjИWӊWtWd?Z2eAI|'m_!Q@<ߟxvd!YQG f"ׯܿ YZlwş|?1n)VN `s&ItBW4j5?OVf^Ay,%6V55}X fGo$'yzWY|i]O` d =oM"kdGVxDzY(䴔I^~i(0e5CQ@p4Ec / -jt!'83)p[\:srmǔ|\5 5I9#Ork $%t|]վoߖۚ_o^Dz o38^bs L7#5!ZTpN-=LrĿ?v'%wi VukOn'Fĭ]=&3G@RWv^kddZ_ҕ-y;)vYDKq.!'\ɚ6p52(J]sF=jHKKȁ[^nW)%)bdz1?,݂̄']Z_RݹQg;L<i5|zQ@J%"/uY$mkfZE(o*]~{*~N뒖*5.)EC #bJWv:@_[* &;ߏ 0]uݜ5J!icw6툡:?!09Tm#lNɫmGpu 7\ v6A `PSC!t55M ,禫:%(='Z`P )Z5j};5g3$*_NN t_ K0>^\%%j,_q,&tcfλVفRm ~(Đ87i[n^! 1n`=wu~AᖱvTd4sAR* 3':k{XHi]cGG^V쳲Ni!!/U\,Rk ֘%}"&۵cpm𑛟z.=[ G_:N6@`@UϚΈFQIVpMO}Z? ȷAˇN#ߝ%;ۖw=..#1t |=Bgya_Bt4A LvťyӺ?zög[_O WP"0Q<Ӧ'^ D(慹$y9s1) 9|Rt= ξAEKc%O|~E WES!j~E  ĭt|q~ϳޱ:8X,:\#K] A]#Ѡ ~ц2=z˶Nn.]Ǐ]c%7zܩ9.{z#fPAHkkLAJu˸#gt5[@kxYK}c~./_:PHE)4VG79f蛲"ǮS߸:"o8B=͋NK~ kJU~,8\i1+6^l17xm7?yݑ7XL:{,6g\rܵxz^ly:Xi`AR0r 4~Ο8L%yB &8 aX' 7^1#?eki|p}Eq \0p~ ͤqu#\(.Oqpew=2<6y's'GKt~ӎ>& !eB4)E]={,]Y|&͡ nkcЧ6^f?v3Ai8Qu.ȧC3ջ w]686M[C + lڔMF K@zO2px]>q~xAr/HN>4se:ǝ_>1"pXH]H^c7#6kOn /r3+~ km]23\\Uy.IAo>vsǏN^oBផ@ת= !1/sK[klyO0hI'>Sڧ_'?JGG!/kܽYI;%/;g+gU> c~`;:z9dw/E^vڑ#y!r'~q/F6 l7p pYb@cg"IZ[ ~?;GOX.zBMsQ7HR+gfUdq׊I8Gl| ح_3ؖs<⋺I^VwT}`BfP1(0:Nn`Wcޔ&PV.;b*>n 몀Qyr3/?APA|kvN+ p^\0#]\S:GROČON;},o.EFr6WXd.r@As} ײK%r.mA9o;z׾{cy`ؐZh2". yF`4@d+9\˔;eR÷xOk~̈p8zXRML#h~~u]7f|OKЉk557 -qKpjCwsъLp-QփH7DL&bPfB4"&/+}TJܺ8z}XLJ|?)F}c3;gLY^"Z=@bq.F*'e~QXߵ,$ܞC}?7{@9SIhe؄3dI{AC! &8+rVF+#J8Q~~WŘ@6Sw 9?(JHY@B z$* I&>#+QŌKᴹ"8퓛P/9%6IQѓD14sq39#\m._ ?DF*/'2ᤖc9ͷ>d33C.Jl ,,)Ai! >9 IsFs#pea]Lb _~8"CyI9)*W ^ FT ;([yN3*0gK?c᫗O3:ZJ^L+yx0oe-7:z# XnGl8(烸7 a7,pTe[\S{V<խǷӉ@q<>slbP[JD[4&G[ZN.;{K%cI/2t/I:e}g!PtxMiiG5ץ,qG-6\^m?rk(nH>x%EPTu=@L܇7npca|b}uH:9.*&7 [Rtql.~99Ubw@'nGD3-JMRJ0C\ul_ qӈ~6\Ҋ]!% $A'~ B3ͪd c%J97COԏCI7 C,:O_4~(?)0 ׯOt !x]pc;$$q[F{e b F'3JI!ɱ/Z0΋n8_K>arXJJ8'q ja@.>IczB<*H!V?7.]a' [mUT5*T"yP1z(( icǒKˑ0XNLM=V^`I2[I?ǁ0+"x܆-~ev9Q+A։O⠣1ݿWb ^VHyϽl^C=TSS}Vq(!F\y =u(]# 5kb( Gi {? Rɤ ^f 9,G֭GFRWȤ5T:T<p0RǠ Xʺ=W۲S[whIwߧN5bI!q$^<4Nd -5 d< 6eR4ZwŲRvG24zJ3@*yxTQQ*> @EKP %w)첃ҳ$c'MU\G&V!~%AhK#/0Zfژ-*T٧KVBUVv'{fJ~2?xs{|wܴMkU ~n%((\DŞ7%z s"9Ap$<ަTSL _Pɠ8BJ6)W5&tw\gkgj ӬJTUU|&s 1Z_ץP > mٜj dCϴ XU50H9fz'~Aw|LMj2oY-F%k5]TJ<Vz-gx),챢 U4ʎ*0d %󯏈uQ4? uUcfkܹĿ#{ibuhv:{H|{MΊfz["?:=:IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/run.gif0000644000175000017500000000167007765157204021221 0ustar adrianadrianGIF89a Ak+W>\;c_Sdqr|hhw{lqsy*x q$t'{3m<{Vu   '00<F[upzzY@@kEJsѪèĴͽ!|, e_0 qA>QrC J ,G . E`>bHHL4䅝W$1 7"d@0 RRO).hCF #L8E.|t,H@ 0pK/pDq$@,ѐC>b< ;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/folder.gif0000644000175000017500000000024007705635174021661 0ustar adrianadrianGIF89a?__?߿?_?߿_ߟ___! ,MI8fK2i S (F^R@DP bXh>%Ij/8fpx 贚3;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/rss.png0000644000175000017500000000120111044004736021213 0ustar adrianadrianPNG  IHDRH- pHYs  3IDAT(uKkaLnhM֒b]tحRWB] FEM UтҒFiJLwq z/*pf4 V$f L]ӆ̞DD" G>סƆChb߿}0KoGă%tG:Aeac= :!h>2NafNaE&ZaHML9K{AB}:}B$F6D,=1 $[ D$$"TqZ+yO\EhP-gp ͎c8CػhYP(Ё@O*9{M vqC^g -:n@hMc]屺ӛ< O3lӅRl%׏(/, MD^6 wt:ܿ ('qͫf!% s[ՍǗ %-09 ~QYEIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/az3_osx_tray.png0000644000175000017500000000053510524747646023062 0ustar adrianadrianPNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxڌS @ l |#8N@VpK60lɻ\44^__{.1NYjbN4oJ0H.Ԩ$MAW؉BpR@ve2pX+" 48\?o0 o x{tV>FN1]eL0IkbLpD3K=󦱲@TF[ 0EcIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/dragger.gif0000644000175000017500000000154407703225170022016 0ustar adrianadrianGIF89a z!, AHHP!Á 8Qb1"ШG .HE7 eȇIX1eK;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/rcm.png0000644000175000017500000000104011271263330021165 0ustar adrianadrianPNG  IHDR7tIME %q pHYs  ~gAMA aIDATx]KAǿf'AShZ"HXDc<ړ'& Ń ]HjblvvM}1*y0xy捄5#O| {@1*=:T=u7~Ꟶ|/zG12@'4m{#w4[P&8+@68];bxMɸq!z QfČ\Ny L@AKH-XPuiQ oark,oiW(gbOb] n#Cv!- &+%޶ّtQD"1 0,F!U Ob4Tz9:h0Z\iPR{zps?naoq:# Vdk߯`t:yճg z`gߜkP[[u!IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/dl_bar_0.png0000644000175000017500000000032311074245116022054 0ustar adrianadrianPNG  IHDR hsBIT|d pHYs  ~tEXtCreation Time10/10/08F|tEXtSoftwareAdobe Fireworks CS3F+IDATeɱ 0l3=5GFIdГ kO@IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/btn_all_rss.png0000644000175000017500000000226711100221412022704 0ustar adrianadrianPNG  IHDR89sBIT|d pHYs B4tEXtCreation Time10/8/08dG9>tEXtSoftwareAdobe Fireworks CS3FIDAT8ŕ[oUEf6Vx% rЂB$1CH/5xacB$ J Q}\3ˋv7ht/߼|3Xq4kSoZeY+(DJ<8ƶZs. ]'{q?ض…A֮]pH&N|uRZ[uDQPb=TJ[9!QrRUTRtӹitRP[AkCU\a5{s m`TWRzqâ}_B)E6;MW#!n\|"pBq1p(n!v:]Ͳ6r|d444.q\םkW|m/?'f#k4Zgpg~.JPGS}Ԥ_s=Np]5A199,ö,ɐ(TSSs/ϩGRxJK@:h(qim4g6mfմo@?Դ+jc@ǫ,rٗF1f}1FIaG-(p*IwGre=+"Ӡ  x"|UbGԄYRjh0l\i 57e{3~)s >P[ Vi eɃ)|ee/^陀Mk@2V0srG@!- rb&@_=ֻ˂s<~"Ed֊he$UGܜ.gAxF,ڀh7gZ~Tbe"V:ҝ0qnÉl)Ν&L(:*EzcdoB}=m7w&@uJEy*p8Hw5}Oc׶ ~%}>jtNI$W6M1L\_'x̃bҿ7,Fz٫.4 ˱* LdS*N WOh^CO-:)Ԙc- >1 Nܳ E7/Pr,c;D807n _/azWm"f2J|ãѸ.w;` 4bh1-7o`ݙNwL p@n?dFۃ=XP}А>Z%;Ξ_#k:KNttky[rKz DAx*_y{Zn<\B?)g6t8q;"ٖ7k>zY߅C9 N~>~P KD:iKW+qǬv#T~p6Ϙ9/(Z1KpQ,Jwh^ameplih x_y🛒~`D Xc^LK|Cv@2IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/a64.png0000644000175000017500000000625511074014470021013 0ustar adrianadrianPNG  IHDR@@iqtEXtSoftwareAdobe ImageReadyqe< OIDATxڼ[ l~cpM9jsIlsB)vG46Ti B4*BEEJ!jZHR$IH U9crPP;;#=g{{3@Zg>0[<G5<S<uA 0 7 u/l ga<` 5O4OOlsm;\;73l!:nFhgH z3{$Et7Sn]q8|VxyXjVBaM2ո/%8`!ja=|,Uҥ&s 0vhBhl o\s{A'^r?9LxTD79n^> m{CiՆt@)ovTqFP$'13>&E$4^8!:0|Xp$<򻴇^P6;. ? .AUm0YA(t1 %ŨID }V)33' AݬV /}6~T A* 5mҁKh߹=,y  $ڳP,#tCR;R?2&Fl@TT^?#s-/iaI<$Tq%U+* dW0*? `$=r;aճ-i{3-bO<%R=v=&#ASԢf(>^ ;pf/>WW~ZCBEkTq#xJWb+ Y-7}Hsl`ɫ/~vT <)#L'WSubc= }J~6W aﮰ'Һk&cVBmBd`̒62 F"w(Ao]?d][vOzc}=uw+Cf}@5kwn+p,m( [3 W _?ҡ=aAPǏJ%*"zAX/~Oa幵]dwR -?q*=<]CR4h->=E+v{[ &A;pзD uR wS$@rz=Mͨo;ǠbXaۂFM|LNKF딼 *,yHJnerR 3C`R̂hL3E\[g"BPbVWdb7/>A}y~ nIZ+>*QUꪌ[?f1G`ck!Հ$kX(e$^k +=DȕcQ}B[Znǁɔ^gK3*r<"w'bF܅&/ ]f6e]wu?<Š:F x'*}Uʚ2q{Ji8¼-^yI6r5F5nZﳸfx>'jehKb7GRSdBbìg.[>ތZ1Nm1gآkeGYppҞhqE5W/ 8;~o@k`"?%7iy~c,4-|4!4K2jճn]qSoՈYu7q,׳Nc B@%tرA SX b!" r>$ e Y@4^ 0;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/dl_bar_1.png0000644000175000017500000000033211074245116022055 0ustar adrianadrianPNG  IHDR hsBIT|d pHYs  ~tEXtCreation Time10/10/08F|tEXtSoftwareAdobe Fireworks CS3F2IDATmǫ D-Ψ4m nQ8$%Lmf JPbkQIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/btn_rss_orange_bud.png0000644000175000017500000000114411225745000024246 0ustar adrianadrianPNG  IHDR􃯪tIME :76 pHYs B4gAMA aIDATxu1hA]%.A9SHlbq"lb]"eH)+bP)"&!1r!l΁7 oÌ1 Z[o'1- ?qɥ+u1,G9L'5hL\I#`tcSNɴp"SO.&(ұp; d 6 G͚{G̼;В/l4QݍǽX wenkn"{7|o+v0Dk ݞcHE@w12̅qtu 2Tjď_)y2o!(+uW`PjdX$Z!">L̑y[Z(b59Nd=uT"hVЩ~AH^GRjS]֝ty-%jZ3u8mԞ4觀j;ރv>EbIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/icons.properties0000644000175000017500000001314311274131344023140 0ustar adrianadrianforcestart=org/gudy/azureus2/ui/icons/forcestart.gif progress_cancel=org/gudy/azureus2/ui/icons/progress_cancel.png cb_editcolumns=org/gudy/azureus2/ui/icons/toolbar/editcolumns.gif cb_run=org/gudy/azureus2/ui/icons/toolbar/run.gif st_no_remote=org/gudy/azureus2/ui/icons/status/no_remote.gif columns=org/gudy/azureus2/ui/icons/columns.gif info=org/gudy/azureus2/ui/icons/info.gif progress_info=org/gudy/azureus2/ui/icons/progress_viewer_has_info.png search=org/gudy/azureus2/ui/icons/search.png cb_start=org/gudy/azureus2/ui/icons/toolbar/start.gif st_shared=org/gudy/azureus2/ui/icons/status/shared.gif progress_viewer=org/gudy/azureus2/ui/icons/progress_viewer.png st_ok_shared=org/gudy/azureus2/ui/icons/status/ok_shared.gif working=multi,16,org/gudy/azureus2/ui/icons/working.png move=org/gudy/azureus2/ui/icons/move.gif edit_trackers=org/gudy/azureus2/ui/icons/edit_trackers.gif host=org/gudy/azureus2/ui/icons/host.gif st_ko=org/gudy/azureus2/ui/icons/status/ko.gif cb_remove=org/gudy/azureus2/ui/icons/toolbar/remove.gif start=org/gudy/azureus2/ui/icons/start.gif cb_switch=org/gudy/azureus2/ui/icons/toolbar/switchui.png redled=org/gudy/azureus2/ui/icons/redled.gif add_to_share=com/aelitis/azureus/ui/images/buddy_add_to_share.png spinner_big=multi,32,org/gudy/azureus2/ui/icons/spinning_indicator_big_white.png bottom=org/gudy/azureus2/ui/icons/bottom.gif cb_new=org/gudy/azureus2/ui/icons/toolbar/new.gif comment=org/gudy/azureus2/ui/icons/comment.png greenled=org/gudy/azureus2/ui/icons/greenled.gif cb_stop=org/gudy/azureus2/ui/icons/toolbar/stop.gif run=org/gudy/azureus2/ui/icons/run.gif st_ko_shared=org/gudy/azureus2/ui/icons/status/ko_shared.gif sb_warning=org/gudy/azureus2/ui/icons/statusbar/status_warning.gif cb_top=org/gudy/azureus2/ui/icons/toolbar/top.gif popup=org/gudy/azureus2/ui/icons/popup.png delete=org/gudy/azureus2/ui/icons/delete.gif cb_bottom=org/gudy/azureus2/ui/icons/toolbar/bottom.gif cb_open_folder=org/gudy/azureus2/ui/icons/toolbar/open_folder.gif cb_open_no_default=org/gudy/azureus2/ui/icons/toolbar/open_no_default.gif st_ok=org/gudy/azureus2/ui/icons/status/ok.gif publish=org/gudy/azureus2/ui/icons/publish.gif st_stopped=org/gudy/azureus2/ui/icons/status/stopped.gif subitem=org/gudy/azureus2/ui/icons/subitem.gif bbb_out=org/gudy/azureus2/ui/icons/statusbar/bbb_boosting.png add_tracker=org/gudy/azureus2/ui/icons/add_tracker.gif cb_up=org/gudy/azureus2/ui/icons/toolbar/up.gif st_no_tracker=org/gudy/azureus2/ui/icons/status/no_tracker.gif azureus_splash=org/gudy/azureus2/ui/splash/splash_frog.jpg smallx=org/gudy/azureus2/ui/icons/smallx.png up=org/gudy/azureus2/ui/icons/up.png folder=org/gudy/azureus2/ui/icons/folder.gif yellowled=org/gudy/azureus2/ui/icons/yellowled.gif down=org/gudy/azureus2/ui/icons/down.png warning=org/gudy/azureus2/ui/icons/warning.gif dragger=org/gudy/azureus2/ui/icons/dragger.gif progress_remove=org/gudy/azureus2/ui/icons/progress_remove.png st_error_shared=org/gudy/azureus2/ui/icons/status/error_shared.gif no_comment=org/gudy/azureus2/ui/icons/comment_blank.png st_no_remote_shared=org/gudy/azureus2/ui/icons/status/no_remote_shared.gif downloadBar=org/gudy/azureus2/ui/icons/bar.gif sb_count=org/gudy/azureus2/ui/icons/statusbar/user_count.png st_stopped_shared=org/gudy/azureus2/ui/icons/status/stopped_shared.gif progress_retry=org/gudy/azureus2/ui/icons/progress_retry.png openFolderButton=org/gudy/azureus2/ui/icons/openFolder16x12.gif azureus32=org/gudy/azureus2/ui/icons/a32.png st_explain=org/gudy/azureus2/ui/icons/status/explain.gif progress_error=org/gudy/azureus2/ui/icons/progress_viewer_has_error.png smallx-gray=org/gudy/azureus2/ui/icons/smallx-gray.png cb_open=org/gudy/azureus2/ui/icons/toolbar/open.gif tray=org/gudy/azureus2/ui/icons/Azureus_big.png foldersmall=org/gudy/azureus2/ui/icons/foldersmall.png stop=org/gudy/azureus2/ui/icons/stop.gif cb_open_url=org/gudy/azureus2/ui/icons/toolbar/open_url.gif azureus64=org/gudy/azureus2/ui/icons/a64.png bbb_idle=org/gudy/azureus2/ui/icons/statusbar/bbb_idle.png recheck=org/gudy/azureus2/ui/icons/recheck.gif bbb_nli=org/gudy/azureus2/ui/icons/statusbar/bbb_notloggedin.png add_to_share_selected=com/aelitis/azureus/ui/images/buddy_add_to_share_selected.png details=org/gudy/azureus2/ui/icons/details.gif cb_down=org/gudy/azureus2/ui/icons/toolbar/down.gif grayled=org/gudy/azureus2/ui/icons/grayled.gif top=org/gudy/azureus2/ui/icons/top.gif export=org/gudy/azureus2/ui/icons/export.gif error=org/gudy/azureus2/ui/icons/error.gif speed=org/gudy/azureus2/ui/icons/speed.gif st_error=org/gudy/azureus2/ui/icons/status/error.gif lock=org/gudy/azureus2/ui/icons/lock.gif bbb_in=org/gudy/azureus2/ui/icons/statusbar/bbb_boosted.png azureus128=org/gudy/azureus2/ui/icons/a128.png azureus=org/gudy/azureus2/ui/icons/a16.png st_no_tracker_shared=org/gudy/azureus2/ui/icons/status/no_tracker_shared.gif pause=org/gudy/azureus2/ui/icons/pause.gif resume=org/gudy/azureus2/ui/icons/resume.gif azureus_white=org/gudy/azureus2/ui/icons/az3_osx_tray_white.png azureus_grey=org/gudy/azureus2/ui/icons/az3_osx_tray.png transparent=org/gudy/azureus2/ui/icons/transparent16x16.png dl_bar_end=org/gudy/azureus2/ui/icons/dl_bar_end.png dl_bar_0=org/gudy/azureus2/ui/icons/dl_bar_0.png dl_bar_1=org/gudy/azureus2/ui/icons/dl_bar_1.png rss_buddy_orange=org/gudy/azureus2/ui/icons/btn_rss_orange_bud.png rss_buddy_gray=org/gudy/azureus2/ui/icons/btn_rss_gray_bud.png rss_buddy_green=org/gudy/azureus2/ui/icons/btn_rss_green_bud.png # if ( Utils.isAZ2UI()){ # addPath("org/gudy/azureus2/ui/icons/recheck.gif", "progress_retry"); # addPath("org/gudy/azureus2/ui/icons/stop.gif", "progress_cancel"); # addPath("org/gudy/azureus2/ui/icons/delete.gif", "progress_remove"); # }else{ azureus-4.3.0.6/org/gudy/azureus2/ui/icons/columns.gif0000644000175000017500000000171007770246346022072 0ustar adrianadrianGIF89a /q&*-:&>*K4P8^\Zj/n-kBbdmemFqOtTr #)62S\]`jlvu[ܫߦ!n, H` ?xȁㆍ4 Ab$ "(@`"2`XAaA@K6(DQSfL B\HAch%m֌ qd  @\:L Pe |ᰡ  =\1q 4A; 1,djΐ劕)O(ǎ;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/downloadFinished.wav0000644000175000017500000001402007761746072023722 0ustar adrianadrianRIFFWAVEfmt @>data; I/ 5E 9+,Ⱦw0OE('1yE;Ke4N0VtSpݦ̫@Eq/Od\4UD?&v.D,2#864?O7K2rnȾi6/)@:O&:| -05 e{ؗui}Ր}i';;O$O3?eXػb4J7E 2&*.h+ލ>P%lw#  ,3770}" yiCTΎV:4?I@<==j6ؠޫJVfP#(>6%j#\ y xC,-}1^>OKUJ51/8m’j6 "1x05$&u:6Lnq:ftk_Nw]c$6#G.F{06I"׾Ocֱg /@l>D.=$#U!2XDjU^S q+3}0" z~ ҰE/=>83T3-Y'hsӧעGcB( t<Z HB  N #֧(rH(D/3:@$=(/U[WޑحؾL&(;"6 ; ) -]?^ju#&a3>i &V!!u}w;/?I 3(3 g!}G"ARbZlʻ9M\`[Z_F)[ eL'-02YqxqcL\+g m ;սY +,@DC?7(/OMӗBLiz!!b/ H6؍6Y ,0.+*'x ih(1{Oͻ=UI;%#>}PZYP>%9 !EYON!#79B;D@,6% vw0,d7/7.&$$hx ]u0HTVO?k' G0&pt-J]bN_UB'(bBĨaϝ+0;BgA90QtyBQˑV =Q\0^0W[F-Z,Tǵ3'!#:|HMKAn06qtҼhIJ9) O]*/-`%yӗ:JW  1?:<8!/lPrLG ]5:DJJJ,DR7# JK۵lvMC[% -8E>=7|*; aӐq/%y'%!^{V #7\0~9//()5;A:2#j|Fdˣ:7SL;WYYSD->h^٨* 8 6FLILC2RZ%ẻw$j$'&U2a< !.!/٢؇q$*031O*V  Ł.#a1 :S<89^1$I B{'ƹόuB'1771l%"v/؝mb"$!v D'=;$O-51/'Kxki£@*s=HLGI==(m(dfְG)~-R0" ͻ\a < "K h I+.E   qH;/7{, x!) d Vz}H%2R9 2:/r <]ͩ\ݽ $)_)${ !n  Y K4 bB .A+4u!!htՃٳ #+//)'o؅z܍)6 ')-']  Dߪ7a_gv ;|)QPEx DVޒ$f. !%'F%SS aAu<" N E  hU!WTg 7Qp `D-hdD N  Dfy" ;- *J_ݓm'G(,,'`Үm9 '*(\"v0 FY1 V_; T"M|& n t ] J&7;    ~@@ 8sz @{ihtxU @ F E( ޸< ## B7Y|(& ; 3c a% ;m=W1t ?& H\ Eu Sx6xH x e OM 3opDAHD5AuHD68qHDcBIDATA:O'5O'-O'!yoO'.PA M-U.PAM-U.PAM-U.PAM-U.PAM*.PA&*-.PA$x'.PAN#Q*? -U$9L-U##L-UQoL-UM4#WGAM4#WGAM4#WGAM4#WGAM4#WGAM4#WM/kg]`zpWX7GAQKe VGA2/L="VGA------D]-S4X6i/KV/x`Q-(((((( (dpzD(??????J4<-4'#o??YxIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/status/0000755000175000017500000000000011310377436021235 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/icons/status/shared.gif0000644000175000017500000000161710060105612023161 0ustar adrianadrianGIF89a!!!11111119999991999999BBBBBB9BBB9B9JJJJBJBJBJJRRZRRRJRRRJZZZZZZZZRZRccccZcZcZcccZkkkkckkssskss{s{{{s{քތ֌֔ޔޜ祭筵筵絽!G,lH*\ȰÇ "<xIBhPBI\PA!Ug08sA5@Ƭ fXʴRG 0z" @`@;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/status/stopped.gif0000644000175000017500000000170110061404500023362 0ustar adrianadrianGIF89accckkksss{{{!,#HA($pp  8hC;1]JF93&# !3,gHA0`XqбcG+|pG5V́ChԨÂ4l0Ё@S,8!(. >,1LP…W%:X,}HA(T` n +"c 1* ;j< @:vp" 56jhXР1Ŋ348HAb+dP&zh%ȁBd} @] bL1Q qA8T ]  !"B1 4Xˠ Bp`u7Z%ȞM[vV 0 ;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/status/error_shared.gif0000644000175000017500000000200310351015666024374 0ustar adrianadrianGIF89a # &13;>!!!111999ADFSVX]bkrs v w z!}!~"BBBJJJRRZZZZccckkk#"#$$%%&&''(**-.0!<,yHA)b P@aHcG `,}HA8p`@`qcƇСc:\8(9j@hԘ9L4$ 0" J`q!ň )RX `1"D  H*VZ ʚ!B[ xmx dC=.0 00'd[V d} b(@2<>!0@dcˆOA! ;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/status/stopped_shared.gif0000644000175000017500000000175210060105612024717 0ustar adrianadrianGIF89a!!!111999BBBJJJRRZZZZccckkksss{{{!,7HA (lpp`,\@C "`@C $1\pa< 8%,0e @n(E$x @HmL"P"G tm : ǧګߪҴ%ŐDƙBŝGʒPoeeiW}be!h, ;\h$H._l1B!1g̔!hB #*PbJ(\h %"h*9ƒ+0aɁ 4\p@b.j `'J# #t*.nR &H :tH!@ď@XȰaĀ0 B2 ;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/bar.gif0000644000175000017500000000166207765157204021162 0ustar adrianadrianGIF89a ///GHHKLLQQQTTTUUUWWWXXXXYY[[[\]\^_^`a`aaababcccgfghhhqqpuuuvvvyyzyy{zyz|||}}}!W, HA+^(\0ƕV%JB# NaŽWf,AP@$,a# $(@ 5gL48q + 4)a!p\a&IJPEVHB% )Uxﶀq`@;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/comment_blank.png0000644000175000017500000000227211037236410023224 0ustar adrianadrianPNG  IHDR pPLTE////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////ItRNSXfiIDATxc`30?33cJ@&bp09Rp4#dkk(dGOK]UQ^5sĹA9 a!Av _IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/downloadBar.png0000644000175000017500000000075207753631250022663 0ustar adrianadrianPNG  IHDR 22$tIME $8Ll pHYsnu>gAMA aPLTE㚪srvvtpg`^djmic^c^ۏg݋~c܅\|zbwmݾ]ؖYnܓ뎳YބYu_y`{\w[vtRNS@fyIDATx}`EL LlEGN8~=.@@C$|?ܪb >vZ~[66pT':_n`8O3-b\p.G_/ ;UIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/delete.gif0000644000175000017500000000165407765157204021661 0ustar adrianadrianGIF89a ..//=<=<""##1#6/5.?.?/<$=% ''=>&'"?5 5 F%})z{hj2, RiQ'3wzssak_ko{ *T^=)5h$ֶ*Œ `IG^+|ƺ9x܁k\f֓'gz9w3`9G?"8k#(mi-V|~=Ghc$9TzhUTHmrd{(_f ҤƧhcAij[Rd]Ag$@{ wA>Y~e"7#B_'kPFKndj|Źl䆛}4e +fm%%3/lj6{2E81Zn]@*#p|AӴnXaIMi’.s7JER1rsN{|[r UK>lzj m&!~HGd)(oX3KeX ft {wJ?Y\m,h\f$n\4By*n1kTh]I 6B M+Wt~}@8{KT,J {Ur`*@8ʿ Jse\,D͠IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/up.png0000644000175000017500000000063611042245244021042 0ustar adrianadrianPNG  IHDRaeIDATxՓM+DQ;^gl5|[; ДPBd!% Sc$ faҸHYy6ᴻ-&GlZ3h$\;mfrVž)/ Ke"vKH Q*f%6NjeW;aQ% HS|3oAiPJNNŗCnQDJzCpJ⋁LD LP%LpFܬ*/B h@5SQIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/warning.gif0000644000175000017500000000037610040064644022045 0ustar adrianadrianGIF89a !, 0I'5- B@y*g8rEw@T aĖh\BAshl lO"@P R2Y` ' $AE$;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/resume.gif0000644000175000017500000000165410334141642021700 0ustar adrianadrianGIF89a 19BJRZcks{{!!!!!!)))))1B!J)R9cBcBkJkRsck!%, K4XPA "D >\ЁJP"@(<J 2h@A@3k*pA7y J=xX!$ $T52d0Z7 yPܑ;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/popup.png0000644000175000017500000006746410671734060021603 0ustar adrianadrianPNG  IHDR,e9sRGBbKGD pHYs  tIME ,*dG IDATxkmY9Vw-h Bml!qRU~RI$SJN*r9)8.H%UI" @=Rn9{{9Oe΢h{ُ5 `@@,+&`Oa@@y?G%#쓐`{sOWޕ | .Ծ+h_Ͻ\=\([/__:|.]ër@/X?V~ ;>'^VA,__kJ+S|Jʋ#5[s<$b>>X#kXcpkc5}F5>X#>X#kXcpkc5}F5>X#kX#kXcpkc5}F5>X#kXcpkXcpkc5}F5>X#kXcpkcpkc5}F5>X#kXcpkc5}F5}F5>X#kXcpkc5}F5F5>X#kXcpkc5}F5>>X#kXcpkc5}F5>X#>X#kXcpkc5}F5>X#kX#%kXcpkc5}F5>X#kXcpkcpkc5}F5>X#kXcpkc5}c5}F5>X#kXcpkc5}F5}F5>X#kXcpkc5}F5F5>X wD@ " $ ό@?. Dd򗇷#X~b9bk.? lX_J僡?V >bDD"8|NfW-1+\)},$XC\Rb_mzn^wW`zmF4B2!w,7\õܶר:b$D0˷X"%8,|^e*Vڲ>cײI KؾEQEh.,u F=kܬ`賏[n>##`vO(ۧA~́v >yFcrO~(ies_n!L'agbuFAP@rO2?݊u;\{PuQ@9K-th1%j1b޾CB9e53A=tS< g;@PI6[Ƭܶa74ƹd;Rjuyrt[V[-Xc{ߒ۔|u,4_ Qv5N Ik ~)i`{)<4#n&<ǏX복j€̮UW*@!&QeT7J/dQmZJ֋CݺJ W6<,m\}0ureGY=JFd>D!712@K/gb@;h5G;!GtvPMm{[jZcYa_] Ix݀V܌]6n7fJA8e9dڳ [5^j{@5Ҳ-8rh)/Ӄ[@XG[ vf3gZj>?6\Bu鸠5OR\z\.yAS2vi唰 ֚ ^Z5&w8q[4aU\~JӎÎLJ< x O+Z6OM֩`5Cc%M\j&j͡Zu*[tOgd%s/Mi T[;.Ve@AnZXYY"#ǖRqU Pn@ @,Q o+8H20), Ko֠='h3}Pz+ eNk-4&hGKiְ#Njtx(0m(LGF!RLqi7W94B>c G11gKR9`HkK y<"`:u[`s,HVBŠ& B*ڴQ+6 h ca:|$ džn4x_K:lEKy`mqh1V% `Պ7~x:(`*q& IYjn9]˔`|ZkGEI>i[!iݩ*G] _б[04Dck1BiQmkΑ[g$^}C<1Ղw| 6 ҥ@ -(i&h4ЉQv큆OwENKåc]WNay $.=ޔMDDV !S`_ u_Fa[֝$5ц|\hAsE~h|Kiz(л[) 2ʬy4hTR2椐)-KHSv h`הHpZ 7@dC"D!R& (FtJJqr^`M$(Qӎsi]N@A5ʡ6lv' | .^NRK 0{CNV#%)Zק46L;0Ux&2e\1kiGݫpƥE? &$mIir4tk5[˞UR2ԯKxH%lm(I屡^ UWJ\)uRre4(E?1H9hz+RJiE4 !2f:'q5\ $l,e:D* -.2]g0HT Z<%cƁcr׈qA @@(3ẗP8o'B7UH{ o~".d Ԡ]`iIS0=@iC:[&SAmpuuP|rγ \1EjV'0*@> V JלL" DK|x(Ql#PC %+hg5 G>tu  Z3}6"! p n(@bCxmsvee oHR)/c JCSzLw#g@&"s V0àb޵]4)yf jAr\cj2ccv +H#Cd!oH5%0Q$ڇjOrh0/iV8:c>u+!I;ՓD>HñW .ntFi sN+0(Pb]< S^: &]J_*ZcBGk0~PD66*&B3 =\4z5Zc[vL[kHf:vNvgvGzaQ11caaw/beP#5 _*KIX+Q7mK4/@PI(dQ2FGlDC33H!OmInv_8c=ˢhk]!\NZ*OJ[7z̔X+FoQR Waޟ kְI&kS;7&2eIBs0}!ІICc 3I.h-LF*Y#c}n e{2DkX< 5Ō.33YRO_hw鴧>3aOX` #ޒ4 FKb槂aTOZGvZҦk@x)Obgݠk?X#(Htd!BI`7Tg\&B:FzM$LA84" -I Ak2fY-whEQk2 Ȕk a%5"a/S:ER[bk. ں205CƊ$QV&DPMַdҭg7HgEmuXêȲ6-V>wŸ́WkQV319uS$ۭ}Bk+ hv– !4@UlR (EȐn;e֭3>V3Fͩԓ eCA^C鍲õA(YH6VLا\k+{€ DsXuBeG2͞$j Fy#,ÑoّB  Uö?Bp yPt*ZAmmi/E,xo A҄%}{CZ0R,`5He[ksɨ6tж?1TBn#]ȏޤuF:l )Y"u)XɒkbPVfɸ$9 8] O0UOJ.Uj1?6)҈-x ik1f oțB@Yxs^zxfNn,ۡøK #3ž8b;!-uI2cGQD4.DGSth%9uR2۷t Ѹ5Iwmk!nP~H3(Sϧ$t\~=Mњ2^ё!zs:KuԈRBi']Jήa` 欀FMaC6WkFODac*#x꫆&aEY ;ZlQ?قQedlDtg *&GaiVK=:G5t]} Q uk NN {X0+r9CRy )yPYdeg_nP@&Ҙ4t$kxEF1홥ɀCDD$~` :5ASE l%2k+=V3|j!+}jã/ձL XGk ݽ1)עK^U6F3rXmc6,H-V62+j{qw1)Ȁ1ΑgLM@4[hR^z=p7V0UTgt4P@z\i8nY`"(4Lx"ʚ, rT`zMnSv!eFR&^Wޚa; Tp,yU6m'(vtnqA;TN AisDݹx\?kw,GUX9.fJtJ@ QJ$5(*nU[8Q+ JMJB8L+;rPY1z25lW ;8pPʕ;FjC'3r+k@`k={`U5Ihh%ţ]\4M`-(t̰Zw9&E+%C`;F)6}8*'cj"LDv^827Z70IbW=t Ty JՄ]Lmi|,pJ(jpηLRPʯ:%OQ
      2 *HEܲ}B㕈! ,XXZ+Dv4C3qg>>.6,zoT X9v,h rYm 5@HWHz`ZɬO4\ q%I뿛kA"U]po,C%pjQ7bd426 Ʀg&+]BN-+!,mr4)G A #CUtamV5J7} %ɥ ,'Ƚ},0FvaDv,s) TIك*z Q̲a4=VǾ6PI,)Ivj1O@H?J4p֤eHc~D!3epP+@c.gp Ojn`'Q!4534gCsնzb2nRN(~"Ks.dRGA{:cxYD^U {YILWH"'4 b{;\MZvrW+J^LF5e+Yڏ% 8luT5.{3yok5yQp(1ˀa2 ؚ 9 ̙d4u»Z "ѳBW)թM kU$^ Һc J}eH;.}ֆҿ"~Z]O@ XW?hFu91@T덩ӟdϪ*C O]7 Ƈ/fakς7 wӖJHP^% ϭ zZ.P9_V0 *\[Ub&eFKŖsTF|*&0hu|lP¨u&0WE V VfGs^dLv!kE\Atx޾BvޙhRWt*^͔cju7j;a0&6T߶ZuΨ$QTgIEI*þ AבdoD j)H'-, Q7 %We -)_k*@P0S+E$q ĞtE". :'33` krjbBlK# Al4 "2FdO"ơz帳ztN4$bK?N'L}Z(Gm2-ƣȮb?vk\/|c~ْ:HR=@i4#mK00RNZ4S1e|T|mlP<v|aѴ$GX'xp MnT%.*=58-ch |ESr aXБwr4R ?*rU:(9T(?MרnF(" wQY"и"JVѪpM%û"59 D(rVgȀZQ(,JYa(Nb Ěv)afauA&ޱsy8}5ٚFWίў$j%hBIץ-wX8㣥B-"\kT;VQAf'LfAGNS˚k2Kb$}iSXSJMA@gn(hUT:m&b%',9 # WBG:C=@{gzMNI@1!"뙡-áN̵)>Wf/5I@n)gQh?F!Z3V):f4*{G~a&W)l#B_Ԧ˴D2k{~p%ɰY\XbŚ⇊A=cj29^k^m0s4)QWUyif"׌,+s3ʁvѹd%39EujݺMj2i  R}34kdW0\w}3ʼn%?z/S3ف/*Tq,!%xĈtJHI5uw:_AyWjjمciM} ? ZE{ys1Yt@GFGCLY`@72ehH%}5xӑDM:@Nբ6iVRLR6T!Zz D_L+Q{j#{ήwt&YB&فըGHHmD'؜)5C嵭i$d(-}u3uhGydt|NiHNePIV|R!D߰sgy_5} K SMG'ւ7:,QfnIdYIS'iPPɠ vUU?numc"a+Y;|"thod!3ɺV`YsWݩ}|p1TmwkZJt1?/*B -mZO(j0nU1"k㟙Tj]J,]4Wەg.$(D ո"ډdZR1=vMiͺyhZmB\[T5/fFU Oi@ E 'V F)![x(șq:_f4[Di}DOS]5;&@6hIkۓf4t-Lu%Beq [1˲v(*2!U%QKT +I(\AV4Ƈ0S0)fW" u{~DJ0B41.Wy\Wm@8êEuRjZ%pB R1d!B _[+zP, [uBL?{Au$0clEi%Ul3Mwi"Q1-lgRU r{T;Z"ϤȬJ]7JdZ(|$S hgS%VlE"XaH8&٪ w: ۡnhxmr~zӘ]lS Q[^5bMo-eN-P%hsN@dl˶r:E'HTZOYn蜄!ɝ¬a`9p ?] 6"j%YAeCm[ߟI`pOs$#&gW**Ur3MMwcFdU$_UO$kKtl@caaQ` ?b]U횢I*qh!Yݮ;s`mFǍ4jhY»1N+-%sAe QL2TeЙ 2S^Q#3wIȼdree (%O2F6F+JΝf*'c5gvFr;iZ1b\T`# J/k3hFRPp]}ڋkBo'5HpeTQG.{Hf辂qd;a- ;1!fkMmv(UH' 4wi 4h=}!;=Ԓ\7t֫z{ᓪ0\\Cc\r2R0mDHtU5B B hK;XOn0lk ѫx6QrBgiC2m)BԪ*G@g0-f'n/qa3&myu"m0BkMR(PiFTNe$v۠(UDFr/gS"tIvb`MR%գ )B|!Q+E)Hjv Ec ӬxE,hSD&tNPR9h U)7!tAF='g1g5M=J1gqu'0!`? Z6a$G9o$Y 2 ժy=:e/@apf`զtoJ*K Lx:=*fsGu.`j4(Ҏnr3`C-B4*l6" P DtHPԎ~QJ2iCA6HjO'$"kJcE65nL-8M TƸ{E>yV1iL0u@w#vVMK$"R35O͚ mUVFwF]Bpz6`PB]< Mß"ٌ._4;ah׫[D7ArL\@EIܪv&RsU&}OE;O&QȕM%W>ڦKT_Z6ʤ dcx?i&4.x~5j!zF}%LEo0BMU]A!=W':^' CR /431(󂛑4'-iAjr]k}sK浧pbLQH*yKVBIP֜zgnagjZΞ)Vv~5az*06X N$E6612wD~XK, e:ɾub $jEL5yQ;+QC"&z2)!Z[hiȲmd|@rĩV:vڇJVnb* (JkYȞ@{Sd`cy^-;E *)Q+m6$*`<41&q_5-SI0UmC 2z$^kSFqdUqPHUJ&aZNd~}7_ӌ`>>|01LETTQg,>Bh! LMejAjgå(5#*n29$d #:wOlMjȥelp^J2,Dt0+?ZQDIV (.0lҨhB,i*,IlYG;jRS$e,fGJ)EET*ĪA$l*m^%sC2I<P$SߌkE ~"ɥ4[qZ .Uɒ ᘍ\K^&ބU}:3d'3j+th ;jyd(,-$ ө *$i@mem/ډ,G۽rܝAsԉΤ> >k%]+^m1z])?dw]J*ʳ d_k$R"&ŕG*Z57O$.SY0,Z q\N\'P|Ӥ0SͤM)Ǧ;D95ĭt+M bʡ ="OPds͕hM]Xn_U٦Y W_\RATMEjK:veP+ Q FPkI}+`q' jj8"nonHj\dNCsnZ0H8\C8;& ?Vܼ]Ӟ2T%k SEWX 8-u+wXc/7, Df\4" 4i}&XU{õf;-#j5ɣ*sb^pt,iZ%&dHAڡ d.YX{ GG͋$Y\&g - $NOkNj&EWA3Bm5AP?/nl *Dqt)}"a=M[MqeT#sW(v[ְQTn={w< t;Н㺣 %.4R \GIjQ?gUP$k}^nT:LWB mR)IRAAiVf*g-ڋCBL`yHgXyFTy7qu$#j-ޏL(lc[Z%ї$TvVQߧ S?zX9yu3;2*t1+@/3¦nfqr'ɔ; iE4t蠢07ХIB"A7.56aywB h:hT)6|3AH{p J/M, )YR5jJ5Lr+QF8 X=~v) к Dȭjfc6:[7_>[+g3w=[!u"?.Ϧp蠲[rp‰r^#6bAXQf\0y8xa ^PAu%|F#U9%E]-ahj>#C7_x0J)CKdk7l0f3bk'\d[%+| _Hr`F!aBk+kpyG/_~?s 33QqV ؁wV,Si٢r"'4h$ kר)pHLSp;eA3@Sc l_j5I{0Rjݶٲ XչGQܓ$_'y9Ofٞ8~7n~^7x||,ӢFr1UPBw w݉B  z^.xDb+v2ǐ:ErFIFC(ȍB1{;tDD > IDATk]6+{bpc0%`ZB) Yᮛ|8% NdfYGy<ϿM?#y}MܿKG3~9nDD<:(ξ36JiCg=2kjJ6.`Ԇʣr4n0ccĦ¬dP=:Q™3-az'q&g_|Mo00牢 o^:$=% )K6 $'Bӳqb^2p 9؝ 86mç!F3d()T$ki99e i脑NJˆmX2sèJ@(g>ɇo8nr5ƅMM13?9?{['^~H`4JWny͡г= "`:#5qdEStnlҊb8$M&°)Ө6F+DC1G4-,SFz-IM}hFvn"; E>ۚ]Y~É 'ݘ7Y%GL\&Бᄄ5I9v?_^N\pć.q80=p_]'>ryRN[13Ȋj#!qEGM8j#+ NI&E8];t 2FY0dVb!@}jYjJx0CXs^JP܁YeP.+˶AB4J~iİp*"ήF>_z`:;#~27bi7sqvwb=t{֬WDX@F00Cz бP0:ZR QGW PQ9֊`vMS1hm?w$$:Q*xi; P-K+l tU{d6T=5ct4l￰g#.+?ؿo|⼟19v8;v0"8/_p%(|H2AVGo'̛.\HF 38J/ +ISos0hIL >k$hUʫT?{|! \UWTkeY .iQ6gy(U%^ G>7bw1E<_|~|<89zvoM No{(%hbVCYd1HoQ ֊LЯɦ:.ydmHP(f*k9MS+bk7~3Plӓx1{ =o>ɗ0y{ȟ ?3ox~n]3LL r ek$aܤ g:q 7(:\k~ 4U ȞwF(:jP%*LǶ+M4{?W3ԭ$HI[؄NFw!z4fR~*6*ŏ@36 ̜Gla{^Mo1so:y~k?>˻}yi!YvIlnPP.r^es&FKA7dm) &4fxBVLlcThj<ޠvFr ]41awHBi6zSy"׵l:+0 f΍EN>OqB\;ᅘ{7w=_m7>=|rzHvnĴ!8m&y&Et" BgҒ"d8̩odx*"Qru* \@Yv$ȧڒdmIwPlN#+]/%]$i>iɥL/; B¼TN *JW|g\Cl4ݸy~'oQKGo>Ź?fמѽx>{ƹy>ޛ~{2yVkg enΟ4?`;X7EƼJMtqN0".Z]6E*!G˘Jr #撇pe)o e9T9OqN!|d&xHրWpZ!A3<爘9m7OO?0mL%ƬijJF(*He8V"u;P`J+zTV}!,3iRe'CC CKxpTt9v31t??G}ǿ'{~=pݘؓq_no6&`0bAȸZ;.[I8ʂvBC<{QEqNTI((EA-4[DX;n~KO+; cf~u_+~y7=q]l n7}{ufsrr &,lsl0A΁ S0j}xlmp}5$mTA(872P%lL@eHbaTfKM=`幪&ٷ':>^A|':J~9/y>|7Mlc>WsWoѹ7<6?~??ϼpfG.2tY31cWo{lIi "L8suǙ1 @ƶh7 i/z!s&7󪓩}]{@WE6ZMz|$I*ӃBnMNWBx+J^Aj.'2dKn&*Ȳy4m{_ԯ/~6#'ҹ?s|e/{O\㈗7O{_pcW7''7o<9>>lʹmv@ &LGLA`y0\ZG֩4 m VlEЩ^Z6T MEUAi?v@.Z.2FG$,:Dz`{dD(P} (_2Ppz_üSzﭫ_ Ӭsm 13L 8/isO>n\%>yo_x ? G7/rƝ{ݻwbB1a:HLC>y5o\xgMW߆;~?_N'Goc6/]y{޺}sn#64m6ifpXdl7!X.xdԭ] +#T'Mg9̎9ZaCuBG1ٝPMj' -S_Wn [{6Ӽyynvnܼ?ߺw+8^/o#7{Eb_b="bw6+Ͻp}wvvzzzzzvzzvgn;n>grgjĕ#̖l][=ZX4[GDtPL*o 0pw=!hG eAmm0yjm0BALCBq@,Zw(ձ%<7WO_]=׮]w}̍ޞ\O<_E;^0]A|>^~v{ޝ}ocevn4MKJSFEa0m8PwheCQ7wDW5MFӎoJvN/t>ǩGt qk?DG㶞Bz$RV 37--%sQ;څC#a0nw˟y=KOwŸ2o?n~&Z8޸|qz7nոd{Kw.<~oq-Ͻp}v}bBLvnw~y;~k- 1p'M,CU¡auw:0US%bEOe';O<9Uhs36x'ze rWhf2]+'] ȫӔ>|i漟lw3?Oĵ?1]w~wݻ󯋸/7=v֝8;WnŹ#867\y/?~>?;nwv_x'~>}뇬Y $9 Q5t> LU._K~K)NBBdPIQz,MmUA1,D|9_,?JW*J ~]PxuZmB(,gwH>Rg G?ny?۟r~==~'ǽw嘯޺yw/<ϟ0yKO-y9 y[9ɧIpĪ,FCR W,1 ,*.i* .6^9KxF݈Ůjod] eJ; WYU5T5 ^„p7<([#/5TbDpvlwvv۝O}^ܻ?"7OI޻{s"gԧ\_zܺ/>ǯ^/7ģ8t\{0_{/|흟&gw>?u3lwyϙlKF?=ecvxY6^LuOeh m2Zk" T>.MpɝPY\ =s@K0}2Nx242bgan*TT>%Yp#Oߌz8.]-~Hw$?߼qk؝i&[Obw!ߝz|4ф|W\6q(^xx镸y+NKnw Mox/+xϻ/gvh&fi()ID< !lʝZy}vX0(VT 1{5.@U&^exfOʰ0/l&K7Nᕮ@hDDlݼ?g;8pn<|18tlo).Nܺ7ǽG6GGfnmo;<}t/+=0Mn6w'|iY7 C%t&+>a1'Ƒ'}jBRovi5㪐ol"a6 D*8 $|* $>jJ] [Kb WTh|kH Z-930=ӿs<ϻy34/\۳׹ݝ@&^|q o;>Yiމ13ˏfs='n_ݻʛӧqW]zcO~i8W't48| LսPB"MI`0PR ,j =]h6OfN4z@n~|؞r:sg?|"ɘoE~˶s?YlO%oN`z7~?7mvs4ϼq^׾ux%|ÛCG^HDlۣ㣣v[:4[]sԓI"*x*&5) g䈠7fLԍnzb)=k{X:`1t@@adQ 7SU5s`)~t^\R"Z_o|y\ܝ/ͽ%֘Ey~K"N9ƴ[Ϸ'Lf´lis|r|rr#o8#¥]oniZJii3MX Π`{9$}fM2M)Llr@ɂI3- %)38~0a"6ho^+mF ;@@!ML~ 8=VgVLTR9ծpʽWO[`„ f]=+|f?O\8Wˋl.p{Ob<ߌ ]`́f޷> l1MfnGGG'''GGGG/7i6fLvlf6f3͞TL*=&@@2&7>RѸ~:#7zc-D$!x1?)8O@zP1ɉ:Ie,Kfa&MRHM j6+2 3\ZXNNνݿ_|qNw7?Z_t3\Ko}s^'S:}nX7ǢqP)dm|jJ kyKڼ1\%:Vq bŇ/yC1)Q" _6~s A͚M*+{%8t`?b(-M$ܦ.24z +~ᓪdesVsDc; ܐډ 4n u'Xȕv `DQ$_^>[7oxsw7^={ųѫz~a@)R>I&7&^yDˍ{K*XZځvf眽Z@$ ̴3}J1#Mo/^Y=,v 1616r@*d黺H+]-b%ՀW/V*cP K11/0Q:?n}ux_>=xSc1F1OU31AHx,Ǝ@2Em&[՜/"|.{z=(R7/<qb5s#2C@FʶG]~e4XBpO,YaK >$i(S 2Qh<|fYQ3$)%I]mry\U{ttxG7޿s $SOԧBbꃤ(IĄ>43[/\H_rw/_X[}*Ph X*y8Q]͍JusDLF!-km59g19-;5 -eI4't9ZdZ@e+bLiQA;T;И  B ăokWO9OSѴfӆc$Os'7wNnoo]rycs#@c"@".2^Yo'4s+iLθ"F2mvL;>QC,!\I,R -̀_Giif_ُlL ,Ŧ|[@BmL%X6J67 H}ܳFaCzPc\ .s?M|")-[15i.Nk/=qԉͭ"Ҷ1Gvzq I=(@]S;chRݤWW#ix;M)N/0Q1[?q3l )`)ˈ[kor7& $ |RɾBQ'QN=+) (QJ9p\ӧg޺~hW덬5܄萿nOngO\ݍq1 c!KvaδsCìnYpBDgy00't3ٓgZ:߈L0Q%LA/}JM]'Z^f@u9奼OSoMlC[+HP/Dm2Y1￿WR!D߮F+k׎UۮV G o<8xt[?~?|Y416͢Y&41y " M҄;& })>f~rhm951Og\I,jQ⑑eTTg~<> If7V09pϢr%;S^ T}\94m꺾mWmu]7CJ|MD! ?_?/~Wq!AbCۧOd':T<oq^A;f $`Θj,3+>C*5OBD,\ݺbx޳/sheN"UU\5~LnD eA\؟@q%J cLnFʿ$$00;vdzfr$umǽ2NC508~GM.?cLIY0wR^!P7ʛe]Tw垗1NEj6Q2A9d*L&r@$rE9~ƌ"L̡EI(ܫwWAF17?f`1N=b 9Xxs> D06BDV0O!SϽ$I("V.JT?{ݻ{q-U)wYG''/{{_x*N.ܾyUu1^!B--;8yygw޼i-^m}P"7JccKR40:z3g>ν|ԀXhkX-u=S|[Mg@5*tW.]>dפ\jĪYRU,Nl;v77G߿F5g/>XŒF@)>Y]bY ~mIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/search.png0000644000175000017500000000106210667655712021676 0ustar adrianadrianPNG  IHDRaIDATxڥkaǿ$F?P*BEpԭ 8TwݺM;TE!"AVD 1 &oysV$yg>jص֖9b C cxfz ̶3a Bhw#2IdST".N:0 ZcݓTOtE|CC>)qWDk6'w.zkJpQ0 toIO^> o?u(gOĵM?2gV\g6W'ghz"Qh}+FDjދ%7.mIs33\r(~J7IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/btn_rss_subscribe_green_30x14.png0000644000175000017500000000210411105222574026141 0ustar adrianadrianPNG  IHDR89sBIT|d pHYs B4tEXtCreation Time11/6/08OĝtEXtSoftwareAdobe Fireworks CS3FIDAT8[h\UϜI2qMR[uc4 VXKZJQQD ⃷B b1>hhDLbRknM&̜gɘR>Xs}fŒu$ؼS[EDE-}~%+O}`EO wTz[)VǹjQ##g~8l|BkupiѱwFKu*5C2_Q/ n`w6t"9ܖCRNDDM$X! iҫ![G:wVeMbJG{)Zm^}CLU&1QT^P,tpsl|W&ζS5Rsǽ{ tϾm|$<))]MqN G}f5dƎ胗잆`Tz!cbcn>24gɵ389@}Թ7&u7庞o=N%Ns!}c]~MM/r\=8b\>8ZއudX}g-)J,u)VD̬eG9=q$kgyz b-, ~/X%5t)9t­QDZx :[?͖]$d>LrMk3-<*0q"tZ0Ɩ"z>/N~ ;)k<9=?^:̆?9JzG^`72$}ڕ{]wbKĈʹ# nz XJl1c/MIff&J'V6~jv_n\:|`QpDpܛT_ifcxxqu 諵3dl"7R6_ eu͑5xhtv7?MۍM?ޱ eIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/spinning_indicator_big_white.png0000644000175000017500000014032011127403350026311 0ustar adrianadrianPNG  IHDR sRGBbKGD IDATx{dkd|hH8B%?'''''''||%czd``zH,,dH#?A%''8%''%''%''%''%''%''%H28H2%8   d H 8 8 8 8 8d8.XDXd2UH8.H.%.%.....M98H'A|2%`U#'''''2H'%gzUz'df IDAT'A'8'%'%'%'%'%%z#d%Af%c%9%,%#%#%#%#%#z#f%%HHc%HH9`zd#`zH#.dH#Az`%# %H.# %H.# %H.# %H.# %H.% %H.H8`.' %U`` Xdq' ..9|d|. }H2. BH`. #%U. .' . .' . .' . .' H .' Hc2X.' dc88A9%8%#`829%#.8p8X%#.%X%#.J%#.%#.%#.%#.z.zf8}HH2H8h888z8H8Hԭg IDAT8H8H2qH8}H!Q+ 0@S>`2z!2 a3 ^dc%A9%%#}%#z%#z%#H%#%%#%%#%%#%z%zf%`.        %U`HHHzHHHHH8,'''''''|''B''''J|'J|'.`9J > IDAT'B'''''''','''' '9'''k|k|`%%%%zzzH%%%%%%#H%%%#H%%%#H%%%#H%%zz%dfz%HMd%82`A%%#.%z%#.%z%#.%H%#.%%6/%6/%6/%6/%6@d%63W%62E%6^=z)/z3/d'/AM/'8'8'8'mAz IDAT8'829'%8X'%X'JHH Ag9%U <8%68%68%68%68%62 8z3  8d!8H+ r X8^h t%6Sn%6d6%6%H%# %H%# %H%# %H%# %H%#@%Hh/  %Hzq2%8zf2zYxk%H: zOu%%# dAm%# A(;%# .8HH.8HH.8HH.8HH.8HH.8Hk.8h.2X d89`Hz.HdH.%U8H.#'#'#'#'#'|fd2rc`H89U:H #'% #' #''%'%'%'%'%'z'z|Kj IDATdA`%U%'%%#%#%#%#%#%h%fzcz9d#A#%#fMc9%%%%%9zXzXdA%%%       kh2# KxL@!i0IDATk8)IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/speed.gif0000644000175000017500000000165607770246346021523 0ustar adrianadrianGIF89a 3~B_IfJhXoXuYw`va~ddnyhno}|}xY}v춦$նEܺEζj:4PişŠ©̭͸ǑҴӹԹֺջտм׿Ͼǃ!m, C*h4dXP"(1刓% P$3I XN8 aF|Q &>Vt! (fPB $00` &"n B)$"0 PB ;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/details.gif0000644000175000017500000000164407765157204022043 0ustar adrianadrianGIF89a n>pN4b_uVo`qjp`ri~}uz}cW{x~yuwuhZ 1䵓3fʁ!`ٲPKwa.2X.?L)}vM( $(BۺLxE(+80}rjpi ,' TUT2fן ~c=zp>gXF\!܈eI!R jh an8qy= 3$, T$!Ʌ;$0;+޾~F= 1F[Nv7.pƵ9W h6LOOcT۽#g@Ra CVVײ/ \ζj?Fz?Y~fwIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/down.png0000644000175000017500000000070711042245244021364 0ustar adrianadrianPNG  IHDRaIDATxՒK[Qɽ B"-%C] R]\Q+(]\POt,B,Xt0~oz?9{Kv^x<_t_ޭhbV,8=߷V75nZoÍ<Ƃ?Wl;@Aaп5ڀ2 h#hDg?v Ŕ mzX[*D}7כ@ DI9>?˸QUϧIiO Z+w{M 1*$nj SctP%(|؜ͷ;%%xB'z΋_ݡw/:z0@utYkt),L.dN"tyi^lQB&IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/openFolder16x12.gif0000644000175000017500000000175710007763130023202 0ustar adrianadrianGIF89a %*5734"61Q9XHDARANZ)C)H2J3W0T$[3_!`?z+i;k5y=zC_@`EgLn@|G~Ui]qTvR\uZ}`u:KMGEUQUX[^UX`gefr{haeecfmn`pniks|pquty}x놬玹焴䞮垯擼蛼敹Դڶؼ޲!, C`ER* iP =`Xh%̞> Ǐq H獛4"+/`x.v$"hP&)V-V3P=E[y<$Dr  $HD W-s_} ~F"]]R+ٲf)p-H{J*@Vt^XpL@gf*@ vF">`Q) ;8, MNnQR,G>_@;)-u}ś2kS妦Vg2eFF0 (}"'oMB52(J *͜Xnw4E !**>J}v 4Lv5?R0Hss[W46X( HjP# ŋuE뒄$"a=vΞsf)呸׻hPR"OBA(%=;;W@/}j c$~beC IHo~( ͖ "O9c1>ے\2i)M!5࠶9]Q[$$ @rXbJg,6 !گx>-Lp1Km!b4 S>{wb_:RSܜmAPIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/add_to_share.png0000644000175000017500000000175111042245244023031 0ustar adrianadrianPNG  IHDR(-SPLTE\k]kkz[l\mZmYl[l]mo\mrXlwh:4tRNS@fIDATxڝ0aF7FnmZAɜ+g{|EPOcM`yB XU=B$PP#iB sCK]LЊ~ZsE+Ke)-2y{?{GyI{UA{XDtvy{zz?LAIKJLNOQPPWjw%}]awxË=Ĉ9    7459:8 $+))+)*AQAůȺȻ!x, ˘/[*:r(e (YaE;R&xsE!9pSE!5̆ȏ!Ax$JY¤бc7X8H 5hPDpx" J.V b&T ! ;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/progress_viewer_has_info.png0000644000175000017500000000132411042245244025504 0ustar adrianadrianPNG  IHDRaIDATxuKhI?WF"!.$0 (Jʍ;q `\](DEEaL<ԌNv:]{gU CUqoSaqڠZe4@VcAA%#ݲuS.ZAfUMѤ{t>}B|3&WW Xpost*c$Ĩw_纱9R`>Q(^yh]evfTw]gQ\"Z-r<&Wx|`gg~ٻH:dP /Ɵ&Ix][S%A ~5G_W 5u*kk3B%ޣ ^ 9֝v2G>jh(P+)z5%փu+QRyZE|ω-UhHfԧvTxPAU^.>xSo` ^kdHjjC%|~e~q`SR h(}JeU oW^ &*LfEU>]#h6|Vr2XM2ualoIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/lock.png0000644000175000017500000000120707753631250021353 0ustar adrianadrianPNG  IHDR 22$tIME $% pHYsnu>gAMA aMPLTE×}֕n՚v՚u֛w֜y֜x֕oŒuuM܍Zpߛoruttۏ\tFgDk5xBw@yD{FzD{Dm6a9cAc-n4l2m3o4n3n4d.]7dBe0q8o5r9uzDv?w?h2^8eBc-m3k2o7r;o8p7d._8bAݦ|ϩˤ̧ͩͧЫݧ~Z6M-tä¡£äxM.M,þЇR3dFkNxjC̹nIsμ}_pKoJ~_̸tRNS@fIDATxYWQE(BI"DB (%DgA jM@BYi1x:um]pD~_EC6 PlM'Zjo)iHfsB$$zzv_$mmw<^޾4lZ1ZȇIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/btn_add_rss.png0000644000175000017500000000204211075272370022677 0ustar adrianadrianPNG  IHDR89sBIT|d pHYs B4tEXtCreation Time10/8/08dG9>tEXtSoftwareAdobe Fireworks CS3F{IDAT8]h\Es?Id؈v-Z,F*F5?腈`URoLX)FJcI%H6%.v잜/db377;Zg@#BLq L̙ +נ4 n%62L;:44@~{JP0ڸc l|EO̧"jpמV^pmh] G+W 7KA(W#*X]IHmC`M}lc| j=^.oM_<WbFl!SoaӜILT4(M8bR\$E)=5uXRqL'7$Y6Zv4i(OCLV-``@i5s`>`~UOq Ŀ?"X#?v^+^E,;IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/stop.gif0000644000175000017500000000170407765157204021400 0ustar adrianadrianGIF89a twwy}y88z::<< !!???? ####""$$%%&&&&''''((@@FFFF&&(())**,,--//7799;;<<>>FFHHOOPPTTUUWWZZ__aaiimmpprrttwwzz灁興鉉ꎎ뗗흝裏﫫!Y,  a4`@!PPRb(0"X+ \҄A&S\E0QB'Itr"FazǏT0Aƒ  H` K@;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/pause.gif0000644000175000017500000000166710334141642021521 0ustar adrianadrianGIF89a twwy}y88z::<< !!???? ####""$$%%&&&&''''((@@FFFF&&(())**,,--//7799;;<<>>FFHHOOPPTTUUWWZZ__aaiimmpprrttwwzz灁興鉉ꎎ뗗흝裏﫫!Y,  B fA 6|,X0bMHy H$? a$ɂ,*YдsC'N P 1h.P@TObEv 2nb5|Q \tTA|;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/statusbar/0000755000175000017500000000000011310377436021722 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/icons/statusbar/user_count.png0000644000175000017500000000115511042245250024606 0ustar adrianadrianPNG  IHDRa4IDATxœ1ha|wsMBm(DE `)(.\$cw'' PGԭBCh$5\rrw.: "zxbTyy->xۏw KXK^?|:՚߾i0LF~#q1997 }/{M Ymb6uT*Ջb=ɼNRQxաa17X(0J_e<}?brG;6f.DCӁmېeXlD 3^DCBQip]T*'O +j_mmwa4jYue1 DaBvaʘMFTx$IJeMB,{Fc*r~a|tsq`&(u]r^eY_]&1?n ˲rNwWVV> J)4Mi['romllkZ3H C,{|6kkEm(ؠy$ T # r]M]lBBӲ3 qup 6\aM,Oea#S6,_?@g*4MkMFFz$ pGٗQu0)i|%g JQ9-/J`D"M]~ͽą=Z"$1c;tڥ'(hmDY-}m_H~8Či<&:;ͩEr01B1Q*XLv.#$#'ipy=C4EYHV 9L3n@TcR<}؋$Z]fKěRco1N7wa:do \ljݍϖ빸eî0GꡂFӴ@Gp߹ot;,IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/statusbar/bbb_idle.png0000644000175000017500000000050011042245246024140 0ustar adrianadrianPNG  IHDRaIDATx͒?KA/$S?`i!O`e[XYY l +tR66!!Q 7hxY !6>ca4ή]Q\ܺlc /p'& XR ͐&Sh^ 'T7%kC!75evQ2wBmߚ_KFrxkVb lA,` I*|WX*+`xYuKq:灁'47`̆'VrO\~rh  :HIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/statusbar/bbb_boosting.png0000644000175000017500000000115711042245250025053 0ustar adrianadrianPNG  IHDRa6IDATxڭMHTa;qFǙ&iF3^A#E(juiDMAѮpF"( Z$bIRT㐤#8]&;?-.,:;/|1>bv~>(H?|)46ZXdZ.X[`qZWT_VS&Ua OIM0BT"yB>~ZӴB~.>̇W3Ti"n-Fu={OѤ'HLDO#;a &]`G6LTRN%"~.B-mopHuW`(sh.LhHI)P*@>ވb/ݑPHj-`S@ !@4 񯐪v^QL"9T9K!c'ڊb[KBTҔ4:Ui+4gaB] bT=Qr {;}k.=2_ƢڹGyi)!ĈW}LmÙƷkk*fO<o:^SIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/bottom.gif0000644000175000017500000000167407770226420021716 0ustar adrianadrianGIF89a *+/:<"7#7,:DCNWVX=N!H)L!N,S,W:Z3bgjptvzvswxyz{|}+s4f6j7m9r:v;y9|=~CMCUBWDWOpIxOxQoxyz|~~  ()-7=>;,h"ʣܺ ܓ3s~|眏/!D C r6gzk S \Z ®L5v ɐBu{̩)  ^ ɡ]͢'ŷFo.B:w<m_6xC'ћk4rqtuZ)_(P@ jX=.{{qq Xت' X)'Muk$v'BwIQn\V J cJWo>.W]" 6R.Arp9p=pB&Հvwg\0 <9!pa/VI":ўbE_+3L0;iƦou 1yA~R_F0 05v = =1 V${y^(=B ?n`;&SNc4;Pbk[l:bJy5ѫ #ib/olr%eôӴYt-6K%Bq u+LVW!x6ٝef T}෥`g66hc4 q ^[v]eO/4My-VVNN 7+Wh6 MoDѥ-Ghi ̘Xl x{!!@x8&- YX#`d:t(4NK~ ^Zl @d$ <<gg…!pr r Ԯ7`f̛88..]@@;w^o$`z9EC`Dy#G"91] -s++9[9wwttٳzfɑ,oӧKh01AðaHxMf~>u)Sd?D#z`RaTjX`p`@##`(Ihx07ƏG;  -T(shmsz5 #/_Q< ӈeP4!!A5~kKt ? ƌN{~6Z3eRM*ICM4>%$ $- ?b,o*}!"<S3rDR8biJ@o'6%Ed=Gdcr)6^~5x+ t- AO˄P S4u@1K hN˄犐kh5rFSqo_2V #ᲀ.ߠdxD*XB4`TVv 3CxF=kk)B{^q!b^z-t7ʡ*"G/Q]ǁTOS/점ӬC$C¶m޾eehde! 5@M&*`.:GxjRKP[Gr6xq"B4tFz@I922ݑ\U2sT@KICtE PZ)EźWnݐOC4zEF,9=pB*Dn.`)!:LK?Q@a7$s*:ۗ"gi)א$mshPAnĒ(ޟ'@T|zD: R",d't= (g"d,#E89Hx( g}C6vΈe%"|l '/ IxUZ_p"R$ј0~$G>"F~PesD34@TM4J//,turrVXRnXrXd;Xnʹ]8NsTU T0NIc!Ă<+o1J#@aeއp: gHR756"'P~?@hԗ{Ď[MN, NXI1 )ʕKZQD A\wv{b8Eߞ!W]WW7t81R 09"7z4[s;g"B ;:Ix/DIl^1|P>SSGI}$[H¼-E~ x&8.J;Q1}ɷ#LKPrO8*|Yʥ %CbbȆ%d\ofϞ3Sz\i,f#o~V+9 T"!QR C1YҀooP0X^~? ;z(ymCc/Ű+qlo751ns)R9WnQT\FuGt:d5X3Qy'BjD|i۶[5dgg:iRoc}xʓʔԇ F[tMCiHwΤ*u.qlj9xԻF|2[(&Ep%rʄZfiSG*i!L+Ssy{LNeuGn; 7/XעV;q4 U K $T}. *!E} = >:#=iA]$F `Wxƈ(G $Y\rRjFZ@m+CrXi2Y'xbqVey|zxusqnm~hvjzr~cqSaDT.@z\m tRNS@f [IDATxڥ}XSSunuf 4h$T$8hHs@ Hf-DCP8R!`4 Z:7{= .羟ysFǼ|1G}F-OH=zx{>z1'<?_b_z;&fQk4jZQkZlZˬewYYnYEYnEEEnEnYno?֭(k%Xb =Vgٶ{zdx|||dd srK𧧓 aL?2v4!1Z R߿i> #W)Z@+ea }P@&YL)`R9486Q"Y@OT(>`tQx/ZT&n0"Y Qt'wQj34}fP#X @-X#z;&{<7NɤzV80j1# ~szPH dFzp#:|Wkn5pp v rUJcgYF<cjPUӃ&3}H_YTg"a +{Su@FW?GuOlQ*@ G-ЃWm> pr:&gHI&"Lr6GCA0p&#ShQ{'S L zɉLY`X?wb`00ٗU(F(`Ίb7qfPU.flmjU@o8]"8 :>~&h8FMu0 ,OɆL4N[ drPgQ6"R*L ! ~U&Uk͐k1,Qh4 e.'gw—wPf"|ɪU+#uwn(F'kϵK(Ԣ}^a=dvpڵkׯܰST%rўʽ`(> @D5]iy&ELR6d>(l鮹SY[ oH/F0[<7%p(z~Wgt&PE(aˁxOQtBU FOo?c 2;r `8AhT @mXn_(IijpXt>I-q8RY"WkjLRR*w{y][(^<Ҷ^rn0 ]K-E;*.^BԑATxb b<#Aehoj* ޢ=.VW{8(20yvAZdU+nu }>HiQFV{{ÚҀ !2DvH@chz>HF oW-]\\AdMn^ P=vطE@Nr 2Շ[UstG m>G*![J_E?% :JX6ZktWq8RL+a:>um0)`V~N| `dO <@p=.Pf7t8A*-li-R,fmH:E= o- = S"VjA:#n/OOeѰTAUUu:=]n Cyilt=Tg=yrI;'>n3_")jRP豟$xtûN൳LU,+LJPRV֑#fle)$HVAϏ̦3'uCjRÛF)JyyYi"LL `I>U{F(;n\H AqA0,LLH>{d{ À+LHH%H Aq?qdF]ii(o+;`OH\-VTR1r`mԴ32f`կ%,K\ōF^[\0sˎȽq++WZIؕ0$a׮KJ^>yCƄMpw]}eIҥ˖|/K^ZE7r‹_ٗ~PD^oOIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/favicon.ico0000644000175000017500000000146610147434144022037 0ustar adrianadrianBM66(ι͸ιιιιιιιιι͸͸ιʵs~p~ιҾ~pf/nt r.nbλι̜q3r ͸Ҵd?(i/q) `'!ιķzA1*P D 1` ]C0˽;˼ι3-is l[+e* {n˘uq,zmbιɐcYe+iUP.tlhxGDfaι岦b6#}5$o %w\?2ojιڲQ%w6\2̸ܘzy) ߑ!uj{͸y|9x-&'mJ>͸ y:ȆQX6t@@ιy|e g5}ĽιVPpkJJιazureus-4.3.0.6/org/gudy/azureus2/ui/icons/transparent16x16.png0000644000175000017500000000013010524224242023451 0ustar adrianadrianPNG  IHDRaIDATx̡ 0z# 0100 ŭGIENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/recheck.gif0000644000175000017500000000165607765157204022025 0ustar adrianadrianGIF89a ^Y_Z ^[c^c^c^#kdto~wkg!id)qm(|v(|w/sp2~y2roPyvN|yP{ (4!4/))#NNZflnl~xxNZf~nĸŹʾɾú1  #(KBT\!o, |3Ȓ 5*4M6J2lQ4l@*옠P7 .(5Á@.((D Qz(bL49S  BM #0AJ-f)@ !4}B;azureus-4.3.0.6/org/gudy/azureus2/ui/icons/redled.gif0000644000175000017500000000053610233531022021626 0ustar adrianadrianGIF89aK}<~nB$mD-X܉~,\Կp XZ#]H5$N64静$x&~:j4u/4H\)1!B7IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/az3_osx_tray_white.png0000644000175000017500000000046610524747646024265 0ustar adrianadrianPNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxb`_C{ N` +I1`>Sb;Iǡ=!@?n`@x4ǧ)$ @HyhiWe9H  @A }d'B5ObP@nddd\<@J5$O@&ePQKCW yd;@N<( M-@AU0~IENDB`azureus-4.3.0.6/org/gudy/azureus2/ui/icons/btn_rss_subscribed_gray_30x14.png0000644000175000017500000000232111105222574026150 0ustar adrianadrianPNG  IHDR89sBIT|d pHYs B4tEXtCreation Time11/6/08OĝtEXtSoftwareAdobe Fireworks CS3F*IDAT8KlUE3gιm }@)5PJ P,!!]1qqҕqVFC4n"ʣ -(- ȣ>Μǜk)&I&%1~Μ;jG@yRB)]8FJ)/~kǻi\\. ܾuK~g.M20P(%Ʋ,yۛox@`=%o0d1PȻ 1 ) { String checker = (String) argsList.remove(0); if (checker.equals(AzureusCoreSingleInstanceClient.ACCESS_STRING)) { if (argsList.get(0).equals("args")) { argsList.remove(0); String newargs[] = new String[argsList.size()]; argsList.toArray(newargs); Main.processArgs(newargs, null, null); } else { Logger.getLogger("azureus2").error("Something strange was sent to the StartServer: " + line); } } else { Logger.getLogger("azureus2").error("StartServer: Wrong access token."); } } } } sck.close(); } catch (Exception e) { if (!(e instanceof SocketException)) e.printStackTrace(); bContinue = false; } finally { try { if (br != null) br.close(); } catch (Exception e) { } } } } public void stopIt() { bContinue = false; try { socket.close(); } catch (Exception e) { } } /** * @return */ public int getServerState() { return state; } } azureus-4.3.0.6/org/gudy/azureus2/ui/common/Main.java0000644000175000017500000002756411053706520021626 0ustar adrianadrian/* * UserInterfaceMain.java * * Created on 9. Oktober 2003, 19:50 */ package org.gudy.azureus2.ui.common; import java.io.FileReader; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.PrintWriter; import java.io.Reader; import java.io.StringReader; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.StringTokenizer; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import org.apache.log4j.Appender; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.varia.DenyAllFilter; import com.aelitis.azureus.core.*; import com.aelitis.azureus.core.impl.AzureusCoreSingleInstanceClient; import com.aelitis.azureus.launcher.Launcher; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.ui.common.IUserInterface; import org.gudy.azureus2.ui.common.UserInterfaceFactory; /** * * @author Tobias Minich */ public class Main { public static String DEFAULT_UI = "swt"; public static StartServer start = null; protected static AzureusCore core; private static CommandLine parseCommands(String[] args, boolean constart) { if (args==null) return null; CommandLineParser parser = new PosixParser(); Options options = new Options(); options.addOption("h", "help", false, "Show this help."); OptionBuilder.withLongOpt("exec"); OptionBuilder.hasArg(); OptionBuilder.withArgName("file"); OptionBuilder.withDescription("Execute script file. The file should end with 'logout', otherwise the parser thread doesn't stop."); options.addOption( OptionBuilder.create('e')); OptionBuilder.withLongOpt("command"); OptionBuilder.hasArg(); OptionBuilder.withArgName("command"); OptionBuilder.withDescription("Execute single script command. Try '-c help' for help on commands."); options.addOption(OptionBuilder.create('c')); OptionBuilder.withLongOpt("ui"); OptionBuilder.withDescription("Run . ',' separated list of user interfaces to run. The first one given will respond to requests without determinable source UI (e.g. further torrents added via command line)."); OptionBuilder.withArgName("uis"); OptionBuilder.hasArg(); options.addOption(OptionBuilder.create('u')); CommandLine commands = null; try { commands = parser.parse(options, args, true); } catch( ParseException exp ) { Logger.getLogger("azureus2").error("Parsing failed. Reason: " + exp.getMessage(), exp); if (constart) System.exit(2); } if (commands.hasOption('h')) { if (constart) { HelpFormatter hf = new HelpFormatter(); hf.printHelp("java org.gudy.azureus2.ui.common.Main", "Optionally you can put torrent files to add to the end of the command line.\r\n", options, "Available User Interfaces: swt (default), web, console\r\nThe default interface is not started if you give either the '-e' or '-c' option (But you can start it by hand with '-u').", true); System.exit(0); } } return commands; } public static void initRootLogger() { if (Logger.getRootLogger().getAppender("ConsoleAppender")==null) { Appender app; app = new ConsoleAppender(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN)); app.setName("ConsoleAppender"); app.addFilter( new DenyAllFilter() ); //'log off' by default Logger.getRootLogger().addAppender(app); } } public static void main(String[] args) { if(Launcher.checkAndLaunch(Main.class, args)) return; // This *has* to be done first as it sets system properties that are read and cached by Java COConfigurationManager.preInitialise(); String mi_str = System.getProperty( "MULTI_INSTANCE" ); boolean mi = mi_str != null && mi_str.equalsIgnoreCase("true"); initRootLogger(); try{ CommandLine commands = parseCommands(args, true); if ( commands != null && directLaunch( args, commands )){ return; } // don't create core until we know we really need it if( mi ){ System.out.println( "MULTI_INSTANCE enabled" ); core = AzureusCoreFactory.create(); processArgs(args, core, commands); return; } start = new StartServer(); if ((start == null) || (start.getServerState()==StartServer.STATE_FAULTY)) { new StartSocket( args ); }else{ core = AzureusCoreFactory.create(); start.start(); processArgs(args, core, commands); } }catch( AzureusCoreException e ){ System.out.println( "Start fails:" ); e.printStackTrace(); } } public static void shutdown() { if (start!=null){ start.stopIt(); } if ( core != null ){ try{ core.stop(); }catch( AzureusCoreException e ){ System.out.println( "Stop fails:" ); e.printStackTrace(); } } SimpleDateFormat temp = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss"); Logger.getLogger("azureus2").fatal("Azureus stopped at "+temp.format(new Date())); //System.exit(0); - we don't want to force quit, wait until other threads have completed // so that resume data etc is saved.... } public static boolean directLaunch( String[] args, CommandLine commands) { // frig to support launch of SWT ui via this means pending a proper rewrite // of this stuff if ( commands.hasOption('u')) { String uinames = commands.getOptionValue('u'); if ( uinames.indexOf(',') != -1 ){ return( false ); } if ( !uinames.equalsIgnoreCase( DEFAULT_UI )){ return( false ); } } try{ String uiclass = "org.gudy.azureus2.ui." + DEFAULT_UI + ".Main"; Class main_class = Class.forName( uiclass ); Method main_method = main_class.getMethod( "main", new Class[]{ String[].class }); main_method.invoke( null, new Object[]{ commands.getArgs()}); return( true ); }catch( Throwable e ){ e.printStackTrace(); return( false ); } } public static void processArgs( String[] args, AzureusCore new_core, CommandLine commands) { if (commands==null) { commands = parseCommands(args, false); } if (((commands!=null) && (args.length>0)) || (new_core != null)) { if (UIConst.UIS == null) { UIConst.UIS = new HashMap(); } if (commands.hasOption('u')) { String uinames = commands.getOptionValue('u'); if (uinames.indexOf(',')==-1) { if (!UIConst.UIS.containsKey(uinames)) UIConst.UIS.put(uinames,UserInterfaceFactory.getUI(uinames)); } else { StringTokenizer stok = new StringTokenizer(uinames, ","); while (stok.hasMoreTokens()) { String uin = stok.nextToken(); if (!UIConst.UIS.containsKey(uin)) UIConst.UIS.put(uin,UserInterfaceFactory.getUI(uin)); } } } else { if (UIConst.UIS.isEmpty() && !commands.hasOption('c') && !commands.hasOption('e')) UIConst.UIS.put(DEFAULT_UI, UserInterfaceFactory.getUI(DEFAULT_UI)); } Iterator uis = UIConst.UIS.values().iterator(); boolean isFirst = true; String [] theRest = commands.getArgs(); while (uis.hasNext()) { IUserInterface ui = (IUserInterface) uis.next(); ui.init(isFirst, (UIConst.UIS.size()>1)); theRest = ui.processArgs(theRest); isFirst = false; } if ( new_core != null ){ SimpleDateFormat temp = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss"); UIConst.startTime = new Date(); Logger.getLogger("azureus2").fatal("Azureus started at "+temp.format(UIConst.startTime)); UIConst.setAzureusCore( new_core ); } uis = UIConst.UIS.values().iterator(); while (uis.hasNext()) ((IUserInterface) uis.next()).startUI(); Class clConsoleInput; Constructor conConsoleInput =null; try { clConsoleInput = Class.forName("org.gudy.azureus2.ui.console.ConsoleInput"); // change this and you'll need to change the parameters below.... Class params[] = {String.class, AzureusCore.class, Reader.class, PrintStream.class, Boolean.class}; conConsoleInput=clConsoleInput.getConstructor(params); } catch (Exception e) { e.printStackTrace(); } if (commands.hasOption('e')) { if (conConsoleInput != null) { try { Object params[] = {commands.getOptionValue('e'), new_core, new FileReader(commands.getOptionValue('e')), System.out, Boolean.FALSE}; conConsoleInput.newInstance(params); } catch (java.io.FileNotFoundException e) { Logger.getLogger("azureus2").error("Script file not found: "+e.toString()); } catch (Exception e) { Logger.getLogger("azureus2").error("Error invocating the script processor: "+e.toString()); } } else Logger.getLogger("azureus2").error("ConsoleInput class not found. You need the console ui package to use '-e'"); } if (commands.hasOption('c')) { if (conConsoleInput != null) { String comm = commands.getOptionValue('c'); comm+="\nlogout\n"; Object params[] = {commands.getOptionValue('c'), UIConst.getAzureusCore(), new StringReader(comm), System.out, Boolean.FALSE}; try { conConsoleInput.newInstance(params); } catch (Exception e) { Logger.getLogger("azureus2").error("Error invocating the script processor: "+e.toString()); } } else Logger.getLogger("azureus2").error("ConsoleInput class not found. You need the console ui package to use '-e'"); } openTorrents(theRest); } else { Logger.getLogger("azureus2").error("No commands to process"); } } public static void openTorrents(String[] torrents) { if ((UIConst.UIS!=null) && (!UIConst.UIS.isEmpty()) && (torrents.length>0)) { for(int l=0; lPreferences>Java>Code Generation>Code and Comments */ package org.gudy.azureus2.ui.common; import org.gudy.azureus2.ui.common.IUserInterface; import org.gudy.azureus2.ui.common.UITemplate; import org.gudy.azureus2.ui.common.util.LGLogger2Log4j; /** * @author tobi * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public abstract class UITemplateHeadless extends UITemplate implements IUserInterface { /* (non-Javadoc) * @see org.gudy.azureus2.ui.common.IUserInterface#init(boolean, boolean) */ public void init(boolean first, boolean others) { super.init(first, others); if (first) LGLogger2Log4j.set(); } } azureus-4.3.0.6/org/gudy/azureus2/ui/common/UIConst.java0000644000175000017500000000336311053706520022255 0ustar adrianadrian/* * Created on 10.11.2003 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package org.gudy.azureus2.ui.common; import java.util.Date; import java.util.HashMap; import com.aelitis.azureus.core.*; import org.apache.log4j.Logger; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.ui.common.IUserInterface; import org.gudy.azureus2.ui.common.UserInterfaceFactory; /** * @author tobi * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public class UIConst { public static Date startTime; public static HashMap UIS; private static AzureusCore azureus_core; private static boolean must_init_core; public static void setAzureusCore( AzureusCore _azureus_core ) { azureus_core = _azureus_core; must_init_core = !azureus_core.isStarted(); } public static synchronized AzureusCore getAzureusCore() { if (must_init_core) { try {azureus_core.start();} catch( AzureusCoreException e ) { Logger.getLogger("azureus2").error("Start fails", e); } must_init_core = false; } return( azureus_core ); } public static GlobalManager getGlobalManager() { return( azureus_core.getGlobalManager()); } public static void shutdown() { Main.shutdown(); } public static synchronized boolean startUI(String ui, String[] args) { if (UIS.containsKey(ui)) return false; IUserInterface uif = UserInterfaceFactory.getUI(ui); uif.init(false, true); if (args!=null) uif.processArgs(args); uif.startUI(); UIS.put(ui, uif); return true; } } azureus-4.3.0.6/org/gudy/azureus2/ui/common/UIImageRepository.java0000644000175000017500000000216410032625340024303 0ustar adrianadrian/* * File : UIImageRepository.java * Created : 08-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.common; /** * @author parg * */ import java.io.InputStream; public class UIImageRepository { public static InputStream getImageAsStream( String name ) { return(UIImageRepository.class.getClassLoader().getResourceAsStream("org/gudy/azureus2/ui/icons/" + name)); } }azureus-4.3.0.6/org/gudy/azureus2/ui/common/ExternalUIConst.java0000644000175000017500000001711710671620666023775 0ustar adrianadrian/* * Created on 13.03.2004 * * To change the template for this generated file go to * Window - Preferences - Java - Code Generation - Code and Comments */ package org.gudy.azureus2.ui.common; import java.util.HashMap; import java.util.Hashtable; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.ui.common.util.LegacyHashtable; /** * @author Tobias Minich * * To change the template for this generated type comment go to * Window - Preferences - Java - Code Generation - Code and Comments */ public class ExternalUIConst { public static Hashtable parameterlegacy = null; private static boolean defaultsNotRegistered = true; static { parameterlegacy = new LegacyHashtable(); parameterlegacy.put("General_sDefaultSave_Directory", "Default save path"); parameterlegacy.put("Core_sOverrideIP", "Override Ip"); //parameterlegacy.put("Core_bAllocateNew", "Zero New"); parameterlegacy.put("Core_iTCPListenPort", "TCP.Listen.Port"); //parameterlegacy.put("Core_iLowPort", "TCP.Listen.Port"); //parameterlegacy.put("Core_iHighPort", "High Port"); parameterlegacy.put("Core_iMaxActiveTorrents", "max active torrents"); parameterlegacy.put("Core_iMaxDownloads", "max downloads"); //parameterlegacy.put("Core_iMaxClients", "Max Clients"); parameterlegacy.put("Core_iMaxUploads", "Max Uploads"); parameterlegacy.put("Core_iMaxUploadSpeed", "Max Upload Speed KBs"); parameterlegacy.put("Core_bUseResume", "Use Resume"); parameterlegacy.put("Core_iSaveResumeInterval", "Save Resume Interval"); parameterlegacy.put("Core_bIncrementalAllocate", "Enable incremental file creation"); parameterlegacy.put("Core_bCheckPiecesOnCompletion", "Check Pieces on Completion"); parameterlegacy.put("Core_fSeedingShareStop", "Stop Ratio"); parameterlegacy.put("StartStopManager_bIgnoreRatioPeers", "Stop Peers Ratio"); parameterlegacy.put("Core_iSeedingRatioStart", "Start Peers Ratio"); parameterlegacy.put("Core_bDisconnectSeed", "Disconnect Seed"); parameterlegacy.put("Core_bSwitchPriority", "Switch Priority"); parameterlegacy.put("Core_bSlowConnect", "Slow Connect"); parameterlegacy.put("Core_sPriorityExtensions", "priorityExtensions"); parameterlegacy.put("Core_bPriorityExtensionsIgnoreCase", "priorityExtensionsIgnoreCase"); parameterlegacy.put("Core_bIpFilterEnabled", "Ip Filter Enabled"); parameterlegacy.put("Core_bIpFilterAllow", "Ip Filter Allow"); parameterlegacy.put("Core_bAllowSameIPPeers", "Allow Same IP Peers"); parameterlegacy.put("Core_bUseSuperSeeding", "Use Super Seeding"); parameterlegacy.put("Core_iMaxPeerConnectionsPerTorrent", "Max.Peer.Connections.Per.Torrent"); parameterlegacy.put("Core_iMaxPeerConnectionsTotal", "Max.Peer.Connections.Total"); parameterlegacy.put("SWT_bUseCustomTab", "useCustomTab"); parameterlegacy.put("SWT_iGUIRefresh", "GUI Refresh"); parameterlegacy.put("SWT_iGraphicsUpdate", "Graphics Update"); parameterlegacy.put("SWT_iReOrderDelay", "ReOrder Delay"); parameterlegacy.put("SWT_bSendVersionInfo", "Send Version Info"); parameterlegacy.put("SWT_bShowDownloadBasket", "Show Download Basket"); parameterlegacy.put("SWT_bAlwaysRefreshMyTorrents", "config.style.refreshMT"); parameterlegacy.put("SWT_bOpenDetails", "Open Details"); parameterlegacy.put("SWT_bProgressBarColorOverride", "Colors.progressBar.override"); parameterlegacy.put("Plugin_sConfig_Directory", "Plugin.config.directory"); parameterlegacy.put("Plugin_bConfigEnable", "Plugin.config.enable"); parameterlegacy.put("Plugin_iConfigIntlist", "Plugin.config.intlist"); parameterlegacy.put("Plugin_sConfigLogfile", "Plugin.config.logfile"); parameterlegacy.put("Plugin_sConfigNick", "Plugin.config.nick"); parameterlegacy.put("Plugin_iConfigPortBlue", "Plugin.config.port.blue"); parameterlegacy.put("Plugin_iConfigPortGreen", "Plugin.config.port.green"); parameterlegacy.put("Plugin_iConfigPortRed", "Plugin.config.port.red"); parameterlegacy.put("Plugin_iConfigPort", "Plugin.config.port"); parameterlegacy.put("Plugin_sConfigStringlist", "Plugin.config.stringlist"); parameterlegacy.put("Logger_bEnable","Logging Enable"); parameterlegacy.put("Logger_sDir_Directory", "Logging Dir"); parameterlegacy.put("Logger_iMaxSize", "Logging Max Size"); parameterlegacy.put("Tracker_Password_Enable","Tracker Password Enable Web"); parameterlegacy.put("Tracker_UserName","Tracker Username"); parameterlegacy.put("Tracker_Password","Tracker Password"); int[] logComponents = { 0, 1, 2, 4 }; for (int i = 0; i < logComponents.length; i++) for (int j = 0; j <= 3; j++) parameterlegacy.put("Logger_bLog" + logComponents[i] + "-" + j,"bLog" + logComponents[i] + "-" + j); } public static void registerDefaults() { HashMap def =new HashMap(); if (defaultsNotRegistered) { defaultsNotRegistered = false; /** Headless Server settings **/ // Server Name def.put("Server_sName", "Azureus2 WebInterface"); // IP to bind to def.put("Server_sBindIP", ""); // Port the server runs on def.put("Server_iPort", new Long(8088)); // Connection Timeout in seconds. def.put("Server_iTimeout", new Long(10)); // Path to the html templates. def.put("Server_sTemplate_Directory", SystemProperties.getUserPath()+"template"); // Maximal simultaneous connections def.put("Server_iMaxHTTPConnections", new Long(5)); // Auto-refresh torrents every (seconds, 0 = off); def.put("Server_iRefresh", new Long(20)); // Allowed static ips (space separated list) def.put("Server_sAllowStatic", "127.0.0.1"); // Allowed dynamic hosts (space separated list) def.put("Server_sAllowDynamic", ""); // Recheck dynamic hosts every (minutes) def.put("Server_iRecheckDynamic", new Long(30)); // Be not JavaScript-dependant def.put("Server_bNoJavaScript", new Long(0)); // Relevant for the proxy part // Fake hostname to access the webinterface when used in proxy mode def.put("Server_sAccessHost", "torrent"); // Enable Cookies def.put("Server_bProxyEnableCookies", new Long(1)); // Block certain URLs def.put("Server_bProxyBlockURLs", new Long(0)); // Filter HTTP Headers (Referer and User Agent) def.put("Server_bProxyFilterHTTP", new Long(0)); // User agent for outgoing connections def.put("Server_sProxyUserAgent", "Mozilla/4.0 (compatible; MSIE 4.0; WindowsNT 5.0)"); // Use a downstream proxy def.put("Server_bUseDownstreamProxy", new Long(0)); // Server Host Name def.put("Server_sDownstreamProxyHost", "127.0.0.1"); // Port of a downstream proxy def.put("Server_iDownstreamProxyPort", new Long(0)); // Grab Torrents in Proxy mode def.put("Server_bProxyGrabTorrents", new Long(1)); // Page to redirect to if torrent download was successful def.put("Server_sProxySuccessRedirect", "torrents"); // Logging relevant Stuff // Log levels: // 50000 Fatal // 40000 Error // 30000 Warn // 20000 Info // 12000 HTTP (SLevel) // 11101 Torrent Received (SLevel) // 11100 Torrent Sent (SLevel) // 11000 Core info (SLevel) // 10001 Thread (SLevel) // 10000 Debug // Log to file def.put("Server_bLogFile", new Long(0)); // Logfile def.put("Server_sLogFile", SystemProperties.getUserPath()+"webinterface.log"); // Log Level for web interface def.put("Server_iLogLevelWebinterface", new Long(20000)); // Log Level for core def.put("Server_iLogLevelCore", new Long(20000)); // Number of remembered log entries def.put("Server_iLogCount", new Long(200)); COConfigurationManager.registerExternalDefaults(def); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/common/util/0000755000175000017500000000000011310377634021044 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/common/util/MenuItemManager.java0000644000175000017500000000753111021656154024727 0ustar adrianadrian/* * Created on 6 Feb 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.common.util; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.ui.menus.MenuItem; /** * Similar to TableContextMenuManager - this keeps references to created menu * items by plugins to be used by external code. * * @author amc1 */ public class MenuItemManager { private static MenuItemManager instance; private static AEMonitor class_mon = new AEMonitor("MenuManager"); /* * Holds all the MenuItem objects. * key = MENU_* type (see MenuManager in the plugin API) * value = Map: key = menu key value = MenuItem object */ private Map items; private AEMonitor items_mon = new AEMonitor("MenuManager:items"); private MenuItemManager() { this.items = new HashMap(); } /** * Return the static MenuManager instance */ public static MenuItemManager getInstance() { try { class_mon.enter(); if (instance == null) instance = new MenuItemManager(); return instance; } finally { class_mon.exit(); } } public void addMenuItem(MenuItem item) { try { String name = item.getResourceKey(); String sMenuID = item.getMenuID(); try { this.items_mon.enter(); Map mTypes = (Map) this.items.get(sMenuID); if (mTypes == null) { // LinkedHashMap to preserve order mTypes = new LinkedHashMap(); this.items.put(sMenuID, mTypes); } mTypes.put(name, item); } finally { this.items_mon.exit(); } } catch (Exception e) { System.out.println("Error while adding Menu Item"); Debug.printStackTrace(e); } } public void removeAllMenuItems(String sMenuID) { this.items.remove(sMenuID); } public void removeMenuItem(MenuItem item) { Map menu_item_map = (Map)this.items.get(item.getMenuID()); if (menu_item_map != null) {menu_item_map.remove(item.getResourceKey());} } public MenuItem[] getAllAsArray(String sMenuID) { Map local_menu_item_map = (Map)this.items.get(sMenuID); Map global_menu_item_map = (Map)this.items.get(null); if (local_menu_item_map == null && global_menu_item_map == null) { return new MenuItem[0]; } if (sMenuID == null) {local_menu_item_map = null;} ArrayList l = new ArrayList(); if (local_menu_item_map != null) {l.addAll(local_menu_item_map.values());} if (global_menu_item_map != null) {l.addAll(global_menu_item_map.values());} return (MenuItem[]) l.toArray(new MenuItem[l.size()]); } public MenuItem[] getAllAsArray(String[] menu_ids) { ArrayList l = new ArrayList(); for (int i=0; i " + new_mode ); */ } }; final DownloadManagerDiskListener dm_disk_listener = new DownloadManagerDiskListener() { public void diskManagerAdded( DiskManager dm ) { dm.addListener( disk_listener ); } public void diskManagerRemoved( DiskManager dm ) { dm.removeListener( disk_listener ); } }; global_manager.addListener( new GlobalManagerAdapter() { public void downloadManagerAdded(DownloadManager manager) { // don't pop up for non-persistent as these get added late in the day every time // so we'll notify for each download every startup if (!startup && manager.isPersistent()) { boolean bPopup = COConfigurationManager.getBooleanParameter("Popup Download Added"); if (bPopup) { if( !manager.getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE )){ String popup_text = MessageText.getString("popup.download.added", new String[] { manager.getDisplayName() }); Logger.log(new LogAlert(manager, true, LogAlert.AT_INFORMATION, popup_text)); } } } manager.addListener(download_manager_listener); manager.addDiskListener(dm_disk_listener); } public void downloadManagerRemoved(DownloadManager manager) { manager.removeListener(download_manager_listener); manager.removeDiskListener( dm_disk_listener ); } public void destroyed() { tidyUp(); } }); startup = false; } protected void activityFinished(boolean download, String item_name, Object relatedObject) { final String sound_enabler; final String sound_file; final String default_sound = "org/gudy/azureus2/ui/icons/downloadFinished.wav"; final String speech_enabler; final String speech_text; final String popup_enabler; final String popup_def_text; if ( download ){ sound_enabler = "Play Download Finished"; sound_file = "Play Download Finished File"; speech_enabler = "Play Download Finished Announcement"; speech_text = "Play Download Finished Announcement Text"; popup_enabler = "Popup Download Finished"; popup_def_text = "popup.download.finished"; }else{ sound_enabler = "Play File Finished"; sound_file = "Play File Finished File"; speech_enabler = "Play File Finished Announcement"; speech_text = "Play File Finished Announcement Text"; popup_enabler = "Popup File Finished"; popup_def_text = "popup.file.finished"; } try{ this_mon.enter(); if (COConfigurationManager.getBooleanParameter(popup_enabler)) { String popup_text = MessageText.getString(popup_def_text, new String[]{item_name}); Logger.log(new LogAlert(relatedObject, true, LogAlert.AT_INFORMATION, popup_text)); } if(Constants.isOSX) { // OS X cannot concurrently use SWT and AWT new AEThread("DownloadSound") { public void runSupport() { try { if(COConfigurationManager.getBooleanParameter( speech_enabler )) Runtime.getRuntime().exec(new String[]{"say", COConfigurationManager.getStringParameter( speech_text )}); // Speech Synthesis services if(COConfigurationManager.getBooleanParameter( sound_enabler )) Runtime.getRuntime().exec(new String[]{"osascript", "-e" ,"beep"}); // Beep alert type is in accordance with System Preferences Thread.sleep(2500); } catch(Throwable e) {} } }.start(); } else if( COConfigurationManager.getBooleanParameter( sound_enabler, false)){ String file = COConfigurationManager.getStringParameter( sound_file ); file = file.trim(); // turn "" into blank if ( file.startsWith( "<" )){ file = ""; } if ( audio_clip == null || !file.equals( audio_resource )){ audio_clip = null; // try explicit file if ( file.length() != 0 ){ File f = new File( file ); try{ if ( f.exists()){ URL file_url = f.toURL(); audio_clip = Applet.newAudioClip( file_url ); } }catch( Throwable e ){ Debug.printStackTrace(e); }finally{ if ( audio_clip == null ){ Logger.log(new LogAlert(relatedObject, LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Failed to load audio file '" + file + "'")); } } } // either non-explicit or explicit missing if ( audio_clip == null ){ audio_clip = Applet.newAudioClip(UserAlerts.class.getClassLoader().getResource( default_sound )); } audio_resource = file; } if ( audio_clip != null ){ new AEThread("DownloadSound") { public void runSupport() { try{ audio_clip.play(); Thread.sleep(2500); }catch( Throwable e ){ } } }.start(); } } }catch( Throwable e ){ Debug.printStackTrace( e ); }finally{ this_mon.exit(); } } protected void tidyUp() { /* The Java audio system keeps some threads running even after playback is finished. One of them, named "Java Sound event dispatcher", is *not* a daemon thread and keeps the VM alive. We have to locate and interrupt it explicitely. */ try{ ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); Thread[] threadList = new Thread[threadGroup.activeCount()]; threadGroup.enumerate(threadList); for (int i = 0; i < threadList.length; i++){ if(threadList[i] != null && "Java Sound event dispatcher".equals(threadList[i].getName())){ threadList[i].interrupt(); } } }catch( Throwable e ){ Debug.printStackTrace( e ); } } /** * Grab the user's attention in a platform dependent way * @param type one of PlatformManager.USER_REQUEST_INFO, * PlatformManager.USER_REQUEST_WARNING, OR * PlatformManager.USER_REQUEST_QUESTION * @param data user-defined data object; * see the platform-specific PlatformManager for what may be supported */ public static void requestUserAttention(int type, Object data) { PlatformManager pm = PlatformManagerFactory.getPlatformManager(); if (true == pm.hasCapability(PlatformManagerCapabilities.RequestUserAttention)) { try { pm.requestUserAttention(type, data); } catch (PlatformManagerException e) { Debug.printStackTrace(e); } } } }azureus-4.3.0.6/org/gudy/azureus2/ui/common/util/LGLogger2Log4j.java0000644000175000017500000000233010344250554024326 0ustar adrianadrian/* * Created on 10.11.2003 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package org.gudy.azureus2.ui.common.util; import org.apache.log4j.Logger; import org.gudy.azureus2.core3.logging.ILogAlertListener; import org.gudy.azureus2.core3.logging.ILogEventListener; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.LogEvent; /** * @author tobi * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public class LGLogger2Log4j implements ILogEventListener { public static Logger core = Logger.getLogger("azureus2.core"); private static LGLogger2Log4j inst = null; public static LGLogger2Log4j getInstance() { if (inst == null) inst = new LGLogger2Log4j(); return inst; } public static void set() { org.gudy.azureus2.core3.logging.Logger.addListener(getInstance()); } public void log(LogEvent event) { if (event.entryType == LogEvent.LT_ERROR) core.error(event.text); else if (event.entryType == LogEvent.LT_WARNING) core.log(SLevel.CORE_WARNING, event.text); else core.log(SLevel.CORE_INFO, event.text); } } azureus-4.3.0.6/org/gudy/azureus2/ui/common/util/SLevel.java0000644000175000017500000000307410344250554023102 0ustar adrianadrian/* Written and copyright 2001-2003 Tobias Minich. * Distributed under the GNU General Public License; see the README file. * This code comes with NO WARRANTY. * * * SLevel.java * * Created on 16. August 2003, 23:16 */ package org.gudy.azureus2.ui.common.util; import org.apache.log4j.Level; /** * * @author Tobias Minich */ public class SLevel extends Level { public final static int INT_CORE_WARNING = 11100; public final static int INT_CORE_INFO = 11000; public final static int INT_THREAD = 10001; public final static int INT_HTTP = 12000; public final static int INT_ACCESS_VIOLATION = 35000; public static final Level CORE_WARNING = new SLevel(INT_CORE_WARNING, "CORE WARNING", 6); public static final Level CORE_INFO = new SLevel(INT_CORE_INFO, "CORE INFO", 6); public static final Level THREAD = new SLevel(INT_THREAD, "THREAD", 6); public static final Level HTTP = new SLevel(INT_HTTP, "HTTP", 6); public static final Level ACCESS_VIOLATION = new SLevel(INT_ACCESS_VIOLATION, "ACCESS VIOLATION", 6); SLevel(int c, String a, int b) {super(c,a,b);} public static Level toLevel(int val) { return toLevel(val, Level.DEBUG); } public static Level toLevel(int val, Level defaultLevel) { switch (val) { case INT_CORE_WARNING: return SLevel.CORE_WARNING; case INT_CORE_INFO: return SLevel.CORE_INFO; case INT_THREAD: return SLevel.THREAD; case INT_HTTP: return SLevel.HTTP; case INT_ACCESS_VIOLATION: return SLevel.ACCESS_VIOLATION; default: return Level.toLevel(val, defaultLevel); } } } azureus-4.3.0.6/org/gudy/azureus2/ui/common/util/LegacyHashtable.java0000644000175000017500000000256411012742400024720 0ustar adrianadrian/* Written and copyright 2001-2003 Tobias Minich. * * LegacyHashtable.java * * Created on 31. August 2003, 18:16 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.common.util; import java.util.Hashtable; /** * * @author tobi */ public class LegacyHashtable extends Hashtable { /** Creates a new instance of LegacyHashtable */ public LegacyHashtable() { super(); } public Object get(Object key) { if (containsKey(key)) return super.get(key); else return ""; } } azureus-4.3.0.6/org/gudy/azureus2/ui/telnet/0000755000175000017500000000000011310377640020067 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/telnet/UI.java0000644000175000017500000001343311053677034021257 0ustar adrianadrian/* * Created on 23-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.telnet; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.util.HashSet; import java.util.Set; import java.util.StringTokenizer; import org.apache.log4j.Logger; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderFactory; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.ui.common.IUserInterface; import org.gudy.azureus2.ui.common.UIConst; import org.gudy.azureus2.ui.console.ConsoleInput; import org.gudy.azureus2.ui.console.UserProfile; import org.gudy.azureus2.ui.console.multiuser.MultiUserConsoleInput; import org.gudy.azureus2.ui.console.multiuser.UserManager; import org.gudy.azureus2.ui.console.multiuser.commands.UserCommand; import com.aelitis.azureus.core.AzureusCore; /** * this is a telnet UI that starts up a server socket that listens for new connections * on a (configurable) port. when an incoming connection is recieved, we check the host * against our list of allowed hosts and if this host is permitted, we start a new * command line interface for that connection. * @author fatal */ public class UI extends org.gudy.azureus2.ui.common.UITemplateHeadless implements IUserInterface { public String[] processArgs(String[] args) { return args; } private UserManager userManager; /** * start up a server socket thread on an appropriate port as obtained from the configuration manager. */ public void startUI() { if( ! isStarted() ) { try { int telnetPort = COConfigurationManager.getIntParameter("Telnet_iPort", 57006); String allowedHostsStr = COConfigurationManager.getStringParameter("Telnet_sAllowedHosts", "127.0.0.1,titan"); StringTokenizer st = new StringTokenizer(allowedHostsStr, ","); Set allowedHosts = new HashSet(); while( st.hasMoreTokens() ) allowedHosts.add(st.nextToken().toLowerCase()); int maxLoginAttempts = COConfigurationManager.getIntParameter("Telnet_iMaxLoginAttempts", 3); userManager = initUserManager(); Thread thread = new Thread(new SocketServer(this, telnetPort, allowedHosts, userManager, maxLoginAttempts), "Telnet Socket Server Thread"); thread.setDaemon(true); thread.start(); } catch (IOException e) { e.printStackTrace(); } } super.startUI(); } /** * @return user manager instance if multi user is enabled, otherwise null */ private UserManager initUserManager() { if( System.getProperty("azureus.console.multiuser") != null ) return UserManager.getInstance(UIConst.getAzureusCore().getPluginManager().getDefaultPluginInterface()); else return null; } /** * shamelessly copied from the console ui. could this be extracted into a static utility method? */ public void openTorrent(String fileName) { if( fileName.toUpperCase().startsWith( "HTTP://" ) ) { System.out.println( "Downloading torrent from url: " + fileName ); TorrentDownloaderFactory.downloadManaged( fileName ); return; } try { if (!TorrentUtils.isTorrentFile(fileName)) {//$NON-NLS-1$ Logger.getLogger("azureus2.ui.telnet").error(fileName+" doesn't seem to be a torrent file. Not added."); return; } } catch (Exception e) { Logger.getLogger("azureus2.ui.telnet").error("Something is wrong with "+fileName+". Not added. (Reason: "+e.getMessage()+")"); return; } if (UIConst.getGlobalManager()!=null) { try { UIConst.getGlobalManager().addDownloadManager(fileName, COConfigurationManager.getDirectoryParameter("Default save path")); } catch (Exception e) { Logger.getLogger("azureus2.ui.telnet").error("The torrent "+fileName+" could not be added.", e); } } } /** * creates a new console input using the specified input/output streams. * we create the new input in non-controlling mode because we don't want the 'quit' * command to shut down the whole interface - simply this clients connection. * @param consoleName * @param inputStream * @param outputStream * @param profile */ public void createNewConsoleInput(String consoleName, InputStream inputStream, PrintStream outputStream, UserProfile profile) { ConsoleInput console; if( userManager != null ) { MultiUserConsoleInput muc = new MultiUserConsoleInput(consoleName, UIConst.getAzureusCore(), new InputStreamReader(inputStream), outputStream, Boolean.FALSE, profile); muc.registerCommand( new UserCommand(userManager) ); console = muc; } else { console = new ConsoleInput(consoleName, UIConst.getAzureusCore(), new InputStreamReader(inputStream), outputStream, Boolean.FALSE, profile); System.out.println( "TelnetUI: console input instantiated" ); } console.printwelcome(); console.printconsolehelp(); } }azureus-4.3.0.6/org/gudy/azureus2/ui/telnet/SocketServer.java0000644000175000017500000001406411164772320023357 0ustar adrianadrian/* * Created on 26/01/2005 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.telnet; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.Iterator; import java.util.Set; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.ui.common.UIConst; import org.gudy.azureus2.ui.console.UserProfile; import org.gudy.azureus2.ui.console.multiuser.UserManager; /** * this class is used to receive incoming connections for the telnet UI and * then authenticate and create a console session for the connection * @author pauld */ final class SocketServer implements Runnable { private final ServerSocket serverSocket; private final Set allowedHosts; private final int maxLoginAttempts; private final UserManager userManager; private final UI ui; public SocketServer(UI ui, int port, Set allowedHosts, UserManager userManager, int maxLoginAttempts) throws IOException { this.ui = ui; this.allowedHosts = allowedHosts; this.userManager = userManager; serverSocket = new ServerSocket(port); this.maxLoginAttempts = maxLoginAttempts; } /** * start up the server socket and when a new connection is received, check that * the source address is in our permitted list and if so, start a new console input * on that socket. */ public void run() { int threadNum = 1; System.out.println("Telnet server started. Listening on port: " + serverSocket.getLocalPort()); new AEThread2( "AZCoreStartup", true ) { public void run() { UIConst.getAzureusCore(); } }.start(); while( true ) { try { Socket socket = serverSocket.accept(); InetSocketAddress addr = (InetSocketAddress) socket.getRemoteSocketAddress(); if( addr.isUnresolved() || ! isAllowed(addr) ) { System.out.println("TelnetUI: rejecting connection from: " + addr + " as address is not allowed"); socket.close(); } else { System.out.println("TelnetUI: accepting connection from: " + addr); int loginAttempts = 0; while( true ) { // TODO: might want to put this in another thread so the port doesnt block while the user logs in //System.out.println("TelnetUI: starting login" ); UserProfile profile = login( socket.getInputStream(), socket.getOutputStream() ); //System.out.println("TelnetUI: login profile obtained" ); if( profile != null ) { //System.out.println("TelnetUI: creating console input" ); ui.createNewConsoleInput("Telnet Console " + threadNum++, socket.getInputStream(), new PrintStream(socket.getOutputStream()), profile); break; } //System.out.println("TelnetUI: failed to obtain login profile" ); loginAttempts++; if( loginAttempts >= maxLoginAttempts ) { System.out.println("TelnetUI: rejecting connection from: " + addr + " as number of failed connections > max login attempts (" + maxLoginAttempts + ")"); socket.close(); break; } } } } catch (Throwable t) { t.printStackTrace(); break; } } } /** * if usermanager is null (ie: multi user is not enabled), returns the default user profile * otherwise, requests username and password and authenticates user before returning * the user profile for this user * @param in input stream to read from * @param out stream to write messages to * @return username if login was successful, null otherwise * @throws IOException */ private UserProfile login(InputStream in, OutputStream out) throws IOException { if( userManager == null ) return UserProfile.DEFAULT_USER_PROFILE; PrintStream ps = new PrintStream(out); BufferedReader br = new BufferedReader(new InputStreamReader(in)); ps.print("Username: "); String username = br.readLine(); ps.print("Password: "); String password = br.readLine(); UserProfile userProfile = userManager.authenticate(username, password); if( userProfile != null ) { ps.println("Login successful"); return userProfile; } ps.println("Login failed"); return null; } /** * check that the specified host/ip is allowed * @param addr * @return */ private boolean isAllowed(InetSocketAddress addr) { InetAddress address = addr.getAddress(); if( checkHost(address.getHostAddress()) ) return true; else if( checkHost(address.getHostName())) return true; else return false; } /** * compare the specified host (might be a hostname or an IP - dont really care) * and see if it is a match against one of the allowed hosts * @param hostName * @return true if this hostname matches one in our allowed hosts */ private boolean checkHost(String hostName) { if( hostName == null ) return false; hostName = hostName.toLowerCase(); // System.out.println("checking host: " + hostName); for (Iterator iter = allowedHosts.iterator(); iter.hasNext();) { String allowedHost = (String) iter.next(); if( hostName.equals(allowedHost) ) return true; } return false; } }azureus-4.3.0.6/org/gudy/azureus2/ui/web/0000755000175000017500000000000011310377516017353 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web/template/0000755000175000017500000000000011310377516021166 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web/template/old/0000755000175000017500000000000011310377516021744 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web/template/new/0000755000175000017500000000000011310377516021757 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/web/template/img/0000755000175000017500000000000011310377516021742 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/systray/0000755000175000017500000000000011310377640020312 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/ui/systray/Main.java0000644000175000017500000000466410033373222022044 0ustar adrianadrian/* * File : Main.java * Created : 2 avr. 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.systray; import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; public class Main { public static void main(String[] args) { Display display = new Display (); Shell shell = new Shell (display); Image image = new Image (display, 16, 16); final Tray tray = display.getSystemTray (); final TrayItem item = new TrayItem (tray, SWT.NONE); item.setToolTipText("SWT TrayItem"); item.addListener (SWT.Show, new Listener () { public void handleEvent (Event event) { System.out.println("show"); } }); item.addListener (SWT.Hide, new Listener () { public void handleEvent (Event event) { System.out.println("hide"); } }); item.addListener (SWT.Selection, new Listener () { public void handleEvent (Event event) { System.out.println("selection"); } }); item.addListener (SWT.DefaultSelection, new Listener () { public void handleEvent (Event event) { System.out.println("default selection"); } }); final Menu menu = new Menu (shell, SWT.POP_UP); for (int i = 0; i < 8; i++) { MenuItem mi = new MenuItem (menu, SWT.PUSH); mi.setText ("Item" + i); } item.addListener (SWT.MenuDetect, new Listener () { public void handleEvent (Event event) { menu.setVisible (true); } }); item.setImage (image); shell.setBounds(50, 50, 300, 200); shell.open (); while (!shell.isDisposed ()) { if (!display.readAndDispatch ()) display.sleep (); } image.dispose (); display.dispose (); } } azureus-4.3.0.6/org/gudy/azureus2/ui/systray/SystemTraySWT.java0000644000175000017500000003216711256533624023715 0ustar adrianadrian/* * File : SystemTraySWT.java * Created : 2 avr. 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.ui.systray; import java.util.List; import java.util.Locale; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.events.MenuListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerStats; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.internat.MessageText.MessageTextListener; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.common.util.MenuItemManager; import org.gudy.azureus2.ui.swt.MenuBuildUtils; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import org.gudy.azureus2.ui.swt.mainwindow.SelectableSpeedMenu; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.ui.common.updater.UIUpdatableAlways; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author Olivier Chalouhi * */ public class SystemTraySWT implements UIUpdatableAlways, MessageTextListener { protected static AzureusCore core = null; Display display; UIFunctionsSWT uiFunctions; Tray tray; TrayItem trayItem; Menu menu; Image imgAzureus; Image imgAzureusGray; Image imgAzureusWhite; protected GlobalManager gm = null; private String seedingKeyVal; private String downloadingKeyVal; private String dlAbbrKeyVal; protected String ulAbbrKeyVal; long interval = 0; protected boolean enableTooltip; public SystemTraySWT() { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { SystemTraySWT.core = core; gm = core.getGlobalManager(); } }); COConfigurationManager.addAndFireParameterListener( "ui.systray.tooltip.enable", new ParameterListener() { public void parameterChanged(String parameterName) { enableTooltip = COConfigurationManager.getBooleanParameter(parameterName); if (enableTooltip) { MessageText.addAndFireListener(SystemTraySWT.this); } else { MessageText.removeListener(SystemTraySWT.this); if (trayItem != null && !trayItem.isDisposed()) { trayItem.setToolTipText(null); } } } }); uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); display = SWTThread.getInstance().getDisplay(); tray = display.getSystemTray(); trayItem = new TrayItem(tray, SWT.NULL); ImageLoader imageLoader = ImageLoader.getInstance(); if (Constants.isOSX) { imgAzureusGray = imageLoader.getImage("azureus_grey"); imgAzureusWhite = imageLoader.getImage("azureus_white"); trayItem.setImage(imgAzureusGray); } else { imgAzureus = imageLoader.getImage("azureus"); trayItem.setImage(imgAzureus); } trayItem.setVisible(true); menu = new Menu(uiFunctions.getMainShell(), SWT.POP_UP); menu.addMenuListener(new MenuListener() { public void menuShown(MenuEvent _menu) {} public void menuHidden(MenuEvent _menu) { if(Constants.isOSX) { trayItem.setImage(imgAzureusGray); } } }); MenuBuildUtils.addMaintenanceListenerForMenu(menu, new MenuBuildUtils.MenuBuilder() { public void buildMenu(Menu menu, MenuEvent menuEvent) { fillMenu(menu); } }); trayItem.addListener(SWT.DefaultSelection, new Listener() { public void handleEvent(Event arg0) { showMainWindow(); } }); trayItem.addListener(SWT.Selection, new Listener() { long lastTime = 0; public void handleEvent(Event arg0) { // Bug in Windows (seems to have started around SWT 3.3 Release // Candidates) where double click isn't interpreted as DefaultSelection // Since we "know" SWT.Selection is actually a mouse down, check // if two mouse downs happen in a short timespan and fake a // DefaultSelection if (Constants.isWindows) { long now = SystemTime.getCurrentTime(); if (now - lastTime < 200) { showMainWindow(); } else { lastTime = now; } } else if (Constants.isOSX) { trayItem.setImage(imgAzureusWhite); menu.setVisible(true); } } }); trayItem.addListener(SWT.MenuDetect, new Listener() { public void handleEvent(Event arg0) { menu.setVisible(true); } }); uiFunctions.getUIUpdater().addUpdater(this); } public void fillMenu(final Menu menu) { final MenuItem itemShow = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(itemShow, "SystemTray.menu.show"); new MenuItem(menu, SWT.SEPARATOR); final MenuItem itemCloseAll = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(itemCloseAll, "SystemTray.menu.closealldownloadbars"); final MenuItem itemShowGlobalTransferBar = new MenuItem(menu, SWT.CHECK); Messages.setLanguageText(itemShowGlobalTransferBar, "SystemTray.menu.open_global_transfer_bar"); new MenuItem(menu, SWT.SEPARATOR); org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items; menu_items = MenuItemManager.getInstance().getAllAsArray("systray"); if (menu_items.length > 0) { MenuBuildUtils.addPluginMenuItems(uiFunctions.getMainShell(), menu_items, menu, true, true, MenuBuildUtils.BASIC_MENU_ITEM_CONTROLLER); new MenuItem(menu, SWT.SEPARATOR); } createUploadLimitMenu(menu); createDownloadLimitMenu(menu); new MenuItem(menu, SWT.SEPARATOR); final MenuItem itemStartAll = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(itemStartAll, "SystemTray.menu.startalltransfers"); final MenuItem itemStopAll = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(itemStopAll, "SystemTray.menu.stopalltransfers"); final MenuItem itemPause = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(itemPause, "SystemTray.menu.pausetransfers"); final MenuItem itemResume = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(itemResume, "SystemTray.menu.resumetransfers"); new MenuItem(menu, SWT.SEPARATOR); final MenuItem itemExit = new MenuItem(menu, SWT.NULL); Messages.setLanguageText(itemExit, "SystemTray.menu.exit"); itemShow.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { showMainWindow(); } }); itemStartAll.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { if (gm == null) { return; } gm.startAllDownloads(); } }); itemStopAll.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { ManagerUtils.asyncStopAll(); } }); itemPause.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { ManagerUtils.asyncPause(); } }); itemResume.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { if (gm == null) { return; } gm.resumeDownloads(); } }); itemPause.setEnabled(gm != null && gm.canPauseDownloads()); itemResume.setEnabled(gm != null && gm.canResumeDownloads()); itemCloseAll.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { uiFunctions.closeDownloadBars(); } }); itemShowGlobalTransferBar.setSelection(uiFunctions.isGlobalTransferBarShown()); itemShowGlobalTransferBar.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { if (uiFunctions.isGlobalTransferBarShown()) { uiFunctions.closeGlobalTransferBar(); } else { uiFunctions.showGlobalTransferBar(); } } }); itemExit.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { uiFunctions.dispose(false, false); } }); } /** * Creates the global upload limit context menu item * @param parent The system tray contextual menu */ private final void createUploadLimitMenu(final Menu parent) { if (core == null) { return; } final MenuItem uploadSpeedItem = new MenuItem(parent, SWT.CASCADE); uploadSpeedItem.setText(MessageText.getString("GeneralView.label.maxuploadspeed")); final Menu uploadSpeedMenu = new Menu(uiFunctions.getMainShell(), SWT.DROP_DOWN); uploadSpeedMenu.addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { SelectableSpeedMenu.generateMenuItems(uploadSpeedMenu, core, gm, true); } }); uploadSpeedItem.setMenu(uploadSpeedMenu); } /** * Creates the global download limit context menu item * @param parent The system tray contextual menu */ private final void createDownloadLimitMenu(final Menu parent) { final MenuItem downloadSpeedItem = new MenuItem(parent, SWT.CASCADE); downloadSpeedItem.setText(MessageText.getString("GeneralView.label.maxdownloadspeed")); final Menu downloadSpeedMenu = new Menu(uiFunctions.getMainShell(), SWT.DROP_DOWN); downloadSpeedMenu.addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { SelectableSpeedMenu.generateMenuItems(downloadSpeedMenu, core, gm, false); } }); downloadSpeedItem.setMenu(downloadSpeedMenu); } public void dispose() { uiFunctions.getUIUpdater().removeUpdater(this); Utils.execSWTThread(new AERunnable() { public void runSupport() { if (trayItem != null && !trayItem.isDisposed()) { trayItem.dispose(); } ImageLoader imageLoader = ImageLoader.getInstance(); if (Constants.isOSX) { imageLoader.releaseImage("azureus_grey"); imageLoader.releaseImage("azureus_white"); } else { imageLoader.releaseImage("azureus"); } } }); } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI() public void updateUI() { if (interval++ % 10 > 0) { return; } if (trayItem.isDisposed()) { uiFunctions.getUIUpdater().removeUpdater(this); return; } if (core == null || !core.isStarted()) { return; } if (enableTooltip) { GlobalManagerStats stats = gm.getStats(); List managers = gm.getDownloadManagers(); StringBuffer toolTip = new StringBuffer(); int seeding = 0; int downloading = 0; // OMG this must be slow on 10k lists for (int i = 0; i < managers.size(); i++) { DownloadManager manager = (DownloadManager) managers.get(i); int state = manager.getState(); if (state == DownloadManager.STATE_DOWNLOADING) downloading++; if (state == DownloadManager.STATE_SEEDING) seeding++; } String seeding_text = seedingKeyVal.replaceAll("%1", "" + seeding); String downloading_text = downloadingKeyVal.replaceAll("%1", "" + downloading); toolTip.append(seeding_text).append(downloading_text).append("\n"); toolTip.append(dlAbbrKeyVal).append( " "); toolTip.append(DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec( stats.getDataReceiveRate(), stats.getProtocolReceiveRate())); toolTip.append(", ").append(ulAbbrKeyVal).append(" "); toolTip.append(DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec( stats.getDataSendRate(), stats.getProtocolSendRate())); trayItem.setToolTipText(toolTip.toString()); } //Why should we refresh the image? it never changes ... //and is a memory bottleneck for some non-obvious reasons. //trayItem.setImage(ImageRepository.getImage("azureus")); trayItem.setVisible(true); } private void showMainWindow() { uiFunctions.bringToFront(false); } public void updateLanguage() { if (menu != null) { Messages.updateLanguageForControl(menu); } updateUI(); } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { return "SystemTraySWT"; } public void localeChanged(Locale oldLocale, Locale newLocale) { seedingKeyVal = MessageText.getString("SystemTray.tooltip.seeding"); downloadingKeyVal = MessageText.getString("SystemTray.tooltip.downloading"); if (!downloadingKeyVal.startsWith(" ")) { downloadingKeyVal = " " + downloadingKeyVal; } dlAbbrKeyVal = MessageText.getString("ConfigView.download.abbreviated"); ulAbbrKeyVal = MessageText.getString("ConfigView.upload.abbreviated"); } } azureus-4.3.0.6/org/gudy/azureus2/core3/0000755000175000017500000000000011310377466017200 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/config/0000755000175000017500000000000011310377632020440 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/config/ParameterListener.java0000644000175000017500000000262410373051016024726 0ustar adrianadrian/* * Created on 24.11.2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.config; /** * A ParameterListener is called when a configuration parameter changes. * @author Rene Leonhardt */ public interface ParameterListener { /** * Called, when a parameter has changed. * The listener could only react if the parameter name is relevant. * Or the listener can just read all parameters again. * @param parameterName the name of the parameter that has changed */ public void parameterChanged(String parameterName); } azureus-4.3.0.6/org/gudy/azureus2/core3/config/COConfigurationManager.java0000644000175000017500000003445111300347336025633 0ustar adrianadrian/* * File : COConfigurationManager.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.config; import java.util.List; import java.util.Map; import java.util.Set; import java.io.IOException; import java.net.URL; import org.gudy.azureus2.core3.config.impl.*; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.core3.util.protocol.AzURLStreamHandlerFactory; public class COConfigurationManager { public static final int CONFIG_DEFAULT_MIN_MAX_UPLOAD_SPEED = 5; public static final int CONFIG_DEFAULT_MAX_DOWNLOAD_SPEED = 0; public static final int CONFIG_DEFAULT_MAX_CONNECTIONS_PER_TORRENT = 50; public static final int CONFIG_DEFAULT_MAX_CONNECTIONS_GLOBAL = 250; public static final int CONFIG_CACHE_SIZE_MAX_MB; static{ long max_mem_bytes = Runtime.getRuntime().maxMemory(); long mb_1 = 1*1024*1024; long mb_32 = 32*mb_1; int size = (int)(( max_mem_bytes - mb_32 )/mb_1); if( size > 1024 ) size = 1024; //safety check if( size < 1 ) size = 1; CONFIG_CACHE_SIZE_MAX_MB = size; } public static final boolean ENABLE_MULTIPLE_UDP_PORTS = false; private static boolean pre_initialised; public static synchronized void preInitialise() { if ( !pre_initialised ){ pre_initialised = true; try{ /* String handlers = System.getProperty( "java.protocol.handler.pkgs" ); if ( handlers == null ){ handlers = "org.gudy.azureus2.core3.util.protocol"; }else{ handlers += "|org.gudy.azureus2.core3.util.protocol"; } System.setProperty( "java.protocol.handler.pkgs", handlers ); */ URL.setURLStreamHandlerFactory(new AzURLStreamHandlerFactory()); // DNS cache timeouts System.setProperty("sun.net.inetaddr.ttl", "60"); System.setProperty("networkaddress.cache.ttl", "60"); // flick AWT into headless mode, which is supposed to make it more lightweight // don't do this as it borks (for example) swing based plugins, java webstart installer, // swing webui plugin, .... // System.setProperty("java.awt.headless", "true"); // defaults, overridden later if needed System.setProperty( "sun.net.client.defaultConnectTimeout", "120000" ); System.setProperty( "sun.net.client.defaultReadTimeout", "60000" ); //see http://developer.apple.com/releasenotes/Java/Java142RN/ResolvedIssues/chapter_3_section_7.html //fixes the osx kernel panic bug caused by Apple's faulty kqueue implementation (as of 10.3.6) if( Constants.isOSX ) { // things seem good in 10.6 //if ( !Constants.isOSX_10_6_OrHigher ){ System.setProperty( "java.nio.preferSelect", "true" ); //} } SystemProperties.determineApplicationName(); }catch( Throwable e ){ // can happen in applet e.printStackTrace(); } } } public static ConfigurationManager initialise() { preInitialise(); return ConfigurationManager.getInstance(); } public static ConfigurationManager initialiseFromMap( Map data ) { preInitialise(); return ConfigurationManager.getInstance(data); } public static final boolean isNewInstall() { return( ConfigurationManager.getInstance().isNewInstall()); } public static String getStringParameter( String _name ) { return( ConfigurationManager.getInstance().getStringParameter( _name )); } public static String getStringParameter( String _name, String _default ) { return( ConfigurationManager.getInstance().getStringParameter( _name, _default )); } public static boolean setParameter(String parameter, String value) { return ConfigurationManager.getInstance().setParameter( parameter, value ); } public static boolean verifyParameter(String parameter, String value) { return ConfigurationManager.getInstance().verifyParameter( parameter, value ); } public static boolean getBooleanParameter( String _name ) { return( ConfigurationManager.getInstance().getBooleanParameter( _name )); } /** * @deprecated You should set ConfigurationDefaults, and use {@link #getBooleanParameter(String)} */ public static boolean getBooleanParameter( String _name, boolean _default ) { return( ConfigurationManager.getInstance().getBooleanParameter( _name, _default )); } public static boolean setParameter(String parameter, boolean value) { return ConfigurationManager.getInstance().setParameter( parameter, value ); } public static int getIntParameter( String _name ) { return( ConfigurationManager.getInstance().getIntParameter( _name )); } /** * Only use this for internal values, NOT for ones that the user can sensibly change. In this * case add the key to the configuration defaults and use the above method * @param _name * @param _def * @return */ public static int getIntParameter( String _name, int _default ) { return( ConfigurationManager.getInstance().getIntParameter( _name, _default )); } public static boolean setParameter(String parameter, int value) { return ConfigurationManager.getInstance().setParameter( parameter, value ); } public static boolean setParameter(String parameter, long value) { return ConfigurationManager.getInstance().setParameter( parameter, value ); } public static long getLongParameter( String _name ) { return( ConfigurationManager.getInstance().getLongParameter( _name )); } /** * Only use this for internal values, NOT for ones that the user can sensibly change. In this * case add the key to the configuration defaults and use the above method * @param _name * @param _def * @return */ public static long getLongParameter( String _name, long _def ) { return( ConfigurationManager.getInstance().getLongParameter( _name, _def )); } public static byte[] getByteParameter(String _name) { return( ConfigurationManager.getInstance().getByteParameter(_name)); } public static byte[] getByteParameter( String _name, byte[] _default ) { return( ConfigurationManager.getInstance().getByteParameter( _name, _default )); } public static boolean setParameter(String parameter, byte[] value) { return ConfigurationManager.getInstance().setParameter( parameter, value ); } public static String getDirectoryParameter( String _name ) throws IOException { return( ConfigurationManager.getInstance().getDirectoryParameter( _name )); } /* public static boolean setParameter(String parameter, Color value) { return ConfigurationManager.getInstance().setParameter( parameter, value ); } public static boolean setParameter(String parameter, RGB value) { return ConfigurationManager.getInstance().setParameter( parameter, value ); } */ public static boolean setRGBParameter(String parameter, int red, int green, int blue) { return ConfigurationManager.getInstance().setRGBParameter( parameter, red, green, blue); } public static boolean setRGBParameter(String parameter, int[] rgb, boolean override) { return ConfigurationManager.getInstance().setRGBParameter(parameter, rgb, override); } public static float getFloatParameter( String _name) { return( ConfigurationManager.getInstance().getFloatParameter( _name )); } public static float getFloatParameter( String _name, float _def ) { return( ConfigurationManager.getInstance().getFloatParameter( _name, _def )); } public static boolean setParameter(String parameter, float value) { return ConfigurationManager.getInstance().setParameter( parameter, value ); } public static boolean setParameter(String parameter,StringList value) { return ConfigurationManager.getInstance().setParameter( parameter, value ); } public static StringList getStringListParameter(String parameter) { return( ConfigurationManager.getInstance().getStringListParameter( parameter )); } public static boolean setParameter(String parameter,List value) { return ConfigurationManager.getInstance().setParameter( parameter, value ); } public static List getListParameter(String parameter, List def) { return( ConfigurationManager.getInstance().getListParameter( parameter, def )); } public static boolean setParameter(String parameter,Map value) { return ConfigurationManager.getInstance().setParameter( parameter, value ); } public static Map getMapParameter(String parameter, Map def) { return( ConfigurationManager.getInstance().getMapParameter( parameter, def )); } /** * Returns true if a parameter with the given name exists. * @param key The name of the parameter to check. * @param explicit If true, we only check for a value which is * definitely stored explicitly, false means that we'll also * check against configuration defaults too. */ public static boolean hasParameter(String parameter, boolean explicit) { return ConfigurationManager.getInstance().hasParameter(parameter, explicit); } public static void save() { ConfigurationManager.getInstance().save(); } /** * Mark as needing a save but not immediately - use when potentially needing a large number of saves that aren't * absolutely required to be immediately persisted */ public static void setDirty() { ConfigurationManager.getInstance().setDirty(); } public static void addListener( COConfigurationListener listener ) { ConfigurationManager.getInstance().addListener( listener ); } public static void addParameterListener(String parameter, ParameterListener listener) { ConfigurationManager.getInstance().addParameterListener(parameter, listener); } /** * @param strings * @param parameterListener * * @since 3.0.1.5 */ public static void addParameterListener(String[] ids, ParameterListener listener) { ConfigurationManager instance = ConfigurationManager.getInstance(); for (int i = 0; i < ids.length; i++) { instance.addParameterListener(ids[i], listener); } } public static void addAndFireParameterListener(String parameter, ParameterListener listener) { ConfigurationManager.getInstance().addParameterListener(parameter, listener); listener.parameterChanged( parameter ); } public static void addAndFireParameterListeners(String[] parameters, ParameterListener listener) { for (int i=0;i newValue*2) ) { newValue = (downValue + 1)/2; //COConfigurationManager.setParameter(DOWNLOAD_CONFIGKEY, newValue * 2); } } else if(configKey == DOWNLOAD_CONFIGKEY) { final int upValue = COConfigurationManager.getIntParameter(UPLOAD_CONFIGKEY); if( upValue != 0 && upValue < COConfigurationManager.CONFIG_DEFAULT_MIN_MAX_UPLOAD_SPEED ) { if(newValue > upValue*2) { newValue = upValue*2; //COConfigurationManager.setParameter(UPLOAD_CONFIGKEY, (newValue+1)/2); } else if(newValue == 0) { newValue = upValue*2; //COConfigurationManager.setParameter(UPLOAD_CONFIGKEY, 0); } } }else if ( configKey == UPLOAD_SEEDING_CONFIGKEY ){ // nothing to do as this is active only when were not downloading // so we don't really care }else { throw new IllegalArgumentException("Invalid Configuation Key; use key for max upload and max download"); } return new Integer(newValue); //return value; } /** * Validates the given configuration key/value pair and returns the validated value * @return Modified configuration value that conforms to validation as an Integer */ public Object getValue() { return validate(configKey, configValue); } public static String getActiveUploadParameter( GlobalManager gm ) { if ( seeding_upload_enabled && gm.isSeedingOnly()){ return( TransferSpeedValidator.UPLOAD_SEEDING_CONFIGKEY ); }else{ return( TransferSpeedValidator.UPLOAD_CONFIGKEY ); } } public static String getDownloadParameter() { return( DOWNLOAD_CONFIGKEY ); } public static int getGlobalDownloadRateLimitBytesPerSecond() { return( COConfigurationManager.getIntParameter( getDownloadParameter()) * 1024 ); } public static void setGlobalDownloadRateLimitBytesPerSecond( int bytes_per_second ) { COConfigurationManager.setParameter( getDownloadParameter(), (bytes_per_second+1023)/1024 ); } public static boolean isAutoUploadAvailable( AzureusCore core ) { SpeedManager speedManager = core.getSpeedManager(); return speedManager == null ? false : speedManager.isAvailable(); } public static boolean isAutoSpeedActive( GlobalManager gm ) { // if downloading+seeding is set then we always use this regardless of // only seeding status if (auto_upload_enabled) { return auto_upload_enabled; } if ( gm.isSeedingOnly()){ return auto_upload_seeding_enabled; }else{ return auto_upload_enabled; } } public static String getActiveAutoUploadParameter( GlobalManager gm) { if (!auto_upload_enabled && gm.isSeedingOnly()) { return AUTO_UPLOAD_SEEDING_ENABLED_CONFIGKEY; } return AUTO_UPLOAD_ENABLED_CONFIGKEY; } } azureus-4.3.0.6/org/gudy/azureus2/core3/config/impl/ConfigurationManager.java0000644000175000017500000006306511236440472026360 0ustar adrianadrian/* * Created on Jun 20, 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.config.impl; import java.io.*; import java.util.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.config.COConfigurationManager.ParameterVerifier; import com.aelitis.azureus.core.security.CryptoManager; /** * A singleton used to store configuration into a bencoded file. * * @author TdC_VgA * */ public class ConfigurationManager implements AEDiagnosticsEvidenceGenerator { private static ConfigurationManager config_temp = null; private static ConfigurationManager config = null; private static AEMonitor class_mon = new AEMonitor( "ConfigMan:class" ); private Map propertiesMap; // leave this NULL - it picks up errors caused by initialisation sequence errors private List transient_properties = new ArrayList(); private List listeners = new ArrayList(); private Hashtable parameterListeners = new Hashtable(); private AEMonitor this_mon = new AEMonitor( "ConfigMan"); private static FrequencyLimitedDispatcher dirty_dispatcher = new FrequencyLimitedDispatcher( new AERunnable() { public void runSupport() { COConfigurationManager.save(); } }, 30*1000 ); public static ConfigurationManager getInstance() { try{ class_mon.enter(); if ( config == null){ // this is nasty but I can't see an easy way around it. Unfortunately while reading the config // we hit other code (logging for example) that needs access to the config data. Things are // cunningly (?) arranged so that a recursive call here *won't* result in a further (looping) // recursive call if we attempt to load the config again. Hence this disgusting code that // goes for a second load attempt if ( config_temp == null ){ config_temp = new ConfigurationManager(); config_temp.load(); config_temp.initialise(); config = config_temp; }else{ if ( config_temp.propertiesMap == null ){ config_temp.load(); } return( config_temp ); } } return config; }finally{ class_mon.exit(); } } public static ConfigurationManager getInstance(Map data) { try{ class_mon.enter(); if (config == null){ config = new ConfigurationManager(data); } return config; }finally{ class_mon.exit(); } } private ConfigurationManager() { } private ConfigurationManager( Map data ) { // default state of play for config initialised from map is debug log files off unless already // specified if ( data.get("Logger.DebugFiles.Enabled") == null ){ data.put( "Logger.DebugFiles.Enabled", new Long(0)); } propertiesMap = data; } protected void initialise() { //ConfigurationChecker.migrateConfig(); //removed 2201 ConfigurationChecker.checkConfiguration(); ConfigurationChecker.setSystemProperties(); AEDiagnostics.addEvidenceGenerator( this ); } public void load(String filename) { Map data = FileUtil.readResilientConfigFile( filename, false ); // horrendous recursive loading going on here due to logger + config depedencies. If already loaded // then use the existing data as it might have already been written to... if ( propertiesMap == null ){ propertiesMap = data; } /* * Can't do this yet. Sometimes, there's a default set to x, but the code * calls get..Parameter(..., y). y != x. When the user sets the the parameter * to x, we remove it from the list. Later, the get..Parameter(.., y) returns * y because there is no entry. * * The solution is to not allow get..Parameter(.., y) when there's a default * value. Another reason to not allow it is that having two defaults confuses * coders. * // Remove entries that are default. Saves memory, reduces // file size when saved again ConfigurationDefaults def = ConfigurationDefaults.getInstance(); Iterator it = new TreeSet(propertiesMap.keySet()).iterator(); while (it.hasNext()) { String key = (String)it.next(); Object defValue = def.getDefaultValueAsObject(key); if (defValue == null) continue; if (defValue instanceof Long) { int iDefValue = ((Long)defValue).intValue(); int iValue = getIntParameter(key, iDefValue); if (iValue == iDefValue) propertiesMap.remove(key); } if (defValue instanceof String) { String sDefValue = defValue.toString(); String sValue = getStringParameter(key, sDefValue); if (sValue.compareTo(sDefValue) == 0) propertiesMap.remove(key); } } */ } public void load() { load("azureus.config"); } public void save(String filename) { if ( propertiesMap == null ){ // nothing to save, initialisation not complete return; } /** * Note - propertiesMap isn't synchronised! We'll clone the map * now, because we need to modify it. The BEncoding code will * create a new map object (TreeMap) because it needs to be * sorted, so we might as well do it here too. */ TreeMap properties_clone = new TreeMap(propertiesMap); // Remove any transient parameters. if (!this.transient_properties.isEmpty()) { properties_clone.keySet().removeAll(this.transient_properties); } FileUtil.writeResilientConfigFile( filename, properties_clone ); List listeners_copy; try{ this_mon.enter(); listeners_copy = new ArrayList( listeners ); }finally{ this_mon.exit(); } for (int i=0;i 0 ) { File temp = new File(dir); if (!temp.exists()) { FileUtil.mkdirs(temp); } if (!temp.isDirectory()) { throw new IOException("Configuration error. This is not a directory: " + dir); } } return dir; } public float getFloatParameter(String parameter) { return( getFloatParameter( parameter, ConfigurationDefaults.def_float )); } public float getFloatParameter(String parameter, float def_val) { ConfigurationDefaults def = ConfigurationDefaults.getInstance(); try { Object o = propertiesMap.get(parameter); if (o instanceof Number) { return ((Number)o).floatValue(); } String s = getStringParameter(parameter); if (!s.equals(ConfigurationDefaults.def_String)) return Float.parseFloat(s); } catch (Exception e) { Debug.out( "Parameter '" + parameter + "' has incorrect type", e ); } try { return def.getFloatParameter(parameter); } catch (Exception e2) { return def_val; } } public boolean setParameter(String parameter, float defaultValue) { String newValue = String.valueOf(defaultValue); return setParameter(parameter, stringToBytes(newValue)); } public boolean setParameter(String parameter, int defaultValue) { Long newValue = new Long(defaultValue); try { Long oldValue = (Long) propertiesMap.put(parameter, newValue); return notifyParameterListenersIfChanged(parameter, newValue, oldValue); } catch (ClassCastException e) { // Issuing a warning here would be nice, but both logging and config stuff // at startup create potential deadlocks or stack overflows notifyParameterListeners(parameter); return true; } } public boolean setParameter(String parameter, long defaultValue) { Long newValue = new Long(defaultValue); try { Long oldValue = (Long) propertiesMap.put(parameter, newValue); return notifyParameterListenersIfChanged(parameter, newValue, oldValue); } catch (ClassCastException e) { // Issuing a warning here would be nice, but both logging and config stuff // at startup create potential deadlocks or stack overflows notifyParameterListeners(parameter); return true; } } public boolean setParameter(String parameter, byte[] defaultValue) { try { byte[] oldValue = (byte[]) propertiesMap.put(parameter, defaultValue); return notifyParameterListenersIfChanged(parameter, defaultValue, oldValue); } catch (ClassCastException e) { // Issuing a warning here would be nice, but both logging and config stuff // at startup create potential deadlocks or stack overflows notifyParameterListeners(parameter); return true; } } public boolean setParameter(String parameter, String defaultValue) { return setParameter(parameter, stringToBytes(defaultValue)); } /** * Returns true if a parameter with the given name exists. * @param key The name of the parameter to check. * @param explicit If true, we only check for a value which is * definitely stored explicitly, false means that we'll also * check against configuration defaults too. */ public boolean hasParameter(String key, boolean explicit) { // We have an explicit value set. if (propertiesMap.containsKey(key)) {return true;} // We have a default value set. if ((!explicit) && ConfigurationDefaults.getInstance().hasParameter(key)) { return true; } return false; } public boolean verifyParameter( String parameter, String value ) { List verifiers = ConfigurationDefaults.getInstance().getVerifiers(parameter); if ( verifiers != null ){ try{ for (int i=0;i env = System.getenv(); if ( env == null ){ writer.println( "Not supported" ); }else{ Iterator it = new TreeSet( env.keySet()).iterator(); while(it.hasNext()){ String key = (String)it.next(); writer.println( key + "=" + env.get( key )); } } }finally{ writer.exdent(); } writer.println( "Azureus Config" ); try{ writer.indent(); Iterator it = new TreeSet(propertiesMap.keySet()).iterator(); while( it.hasNext()){ String key = (String)it.next(); // don't dump crypto stuff if ( key.startsWith( CryptoManager.CRYPTO_CONFIG_PREFIX )){ continue; } Object value = propertiesMap.get(key); boolean bParamExists = ConfigurationDefaults.getInstance().doesParameterDefaultExist(key.toString()); if (!bParamExists){ key = "[NoDef] " + key; } if ( value instanceof Long ){ writer.println( key + "=" + value ); }else if ( value instanceof List ){ writer.println( key + "=" + value + "[list]" ); }else if ( value instanceof Map ){ writer.println( key + "=" + value + "[map]" ); }else if ( value instanceof byte[] ){ byte[] b = (byte[])value; boolean hex = false; for (int i=0;i/?'".indexOf(c) != -1 )){ hex = true; break; } } writer.println( key + "=" + (hex?ByteFormatter.nicePrint(b):bytesToString((byte[])value))); }else{ writer.println( key + "=" + value + "[unknown]" ); } } }finally{ writer.exdent(); } }finally{ writer.exdent(); } } protected static String bytesToString( byte[] bytes ) { try{ return( new String( bytes, Constants.DEFAULT_ENCODING )); }catch( Throwable e ){ return( new String(bytes)); } } protected static byte[] stringToBytes( String str ) { try{ return( str.getBytes( Constants.DEFAULT_ENCODING )); }catch( Throwable e ){ return( str.getBytes()); } } }azureus-4.3.0.6/org/gudy/azureus2/core3/config/impl/ConfigurationDefaults.java0000644000175000017500000007520611300652044026545 0ustar adrianadrian/* Written and copyright 2001-2003 Tobias Minich. * * ConfigurationDefaults.java * * Created on 31. Juli 2003, 21:31 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.config.impl; import java.io.File; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.stats.StatsWriterPeriodic; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.host.TRHost; import org.gudy.azureus2.core3.tracker.server.TRTrackerServer; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerImpl; import com.aelitis.azureus.core.speedmanager.impl.v2.SpeedLimitConfidence; import com.aelitis.azureus.core.speedmanager.impl.v2.SpeedLimitMonitor; import com.aelitis.azureus.core.speedmanager.impl.v2.SpeedManagerAlgorithmProviderV2; import com.aelitis.azureus.core.speedmanager.impl.v2.SMConst; /** * * @author Tobias Minich */ /** * Some (proposed) option naming conventions: * - Starts with a general identifier * General_ for, well, general things =) * Server_ for webinterface specific things * GUI_ (eventually) for GUI specific things * Core_ (eventually) for core specific things * - Second is some identifing term. It starts with a small letter denoting * the variable type. * b Boolean * i Integer * s String * - Directory options should end with _Directory. This activates some * special validity checks in the webinterface option parsing code. * (Namely they are created if they don't exist and the option isn't changed * with a logged error if a normal file of the same name exists) */ public class ConfigurationDefaults { private static final Long ZERO = new Long(0); private static final Long ONE = new Long(1); private static final Long FALSE = ZERO; private static final Long TRUE = ONE; private static ConfigurationDefaults configdefaults; private static AEMonitor class_mon = new AEMonitor( "ConfigDef"); private Map def = null; public static final int def_int = 0; public static final long def_long = 0; public static final float def_float = 0; public static final int def_boolean = 0; public static final String def_String = ""; public static final byte[] def_bytes = null; private Hashtable parameter_verifiers = new Hashtable(); public static ConfigurationDefaults getInstance() { try{ class_mon.enter(); if(configdefaults == null){ try{ configdefaults = new ConfigurationDefaults(); }catch( Throwable e ){ // this is here for when we are just using a few of the Azureus classes and // we can live with no defaults (e.g. swing webui). If we initialise // the normal config-defaults fully this pulls in all sorts of unwanted // classes (platform manager for example). Also, don't using Debug/Logging // to record this fact! System.out.println( "Falling back to default defaults as environment is restricted" ); configdefaults = new ConfigurationDefaults( new HashMap()); } } return configdefaults; }finally{ class_mon.exit(); } } /** Creates a new instance of Defaults */ protected ConfigurationDefaults() { def = new HashMap(); /** Core settings **/ def.put("Override Ip", ""); def.put("Enable incremental file creation", FALSE); def.put("TCP.Listen.Port", new Long( 6881 )); def.put("TCP.Listen.Port.Enable", TRUE ); def.put("TCP.Listen.Port.Override", ""); def.put("UDP.Listen.Port", new Long( 6881 )); def.put("UDP.Listen.Port.Enable", TRUE ); def.put("UDP.NonData.Listen.Port", new Long( 6881 )); // two effective enablers for this, dht + tracker udp client def.put("UDP.NonData.Listen.Port.Same", TRUE ); // control over whether non-data and data udp port are the same def.put("HTTP.Data.Listen.Port", new Long( Constants.isWindows?80:8080 )); def.put("HTTP.Data.Listen.Port.Override", ZERO); def.put("HTTP.Data.Listen.Port.Enable", FALSE ); def.put("IPV6 Enable Support", Constants.isOSX?FALSE:TRUE ); def.put("IPV6 Prefer Addresses",FALSE); def.put("max active torrents", new Long(4)); def.put("max downloads", new Long(4)); def.put("min downloads", ONE); def.put("Newly Seeding Torrents Get First Priority", TRUE); def.put("Max.Peer.Connections.Per.Torrent", new Long(COConfigurationManager.CONFIG_DEFAULT_MAX_CONNECTIONS_PER_TORRENT)); def.put("Max.Peer.Connections.Per.Torrent.When.Seeding", new Long(COConfigurationManager.CONFIG_DEFAULT_MAX_CONNECTIONS_PER_TORRENT)); def.put("Max.Peer.Connections.Per.Torrent.When.Seeding.Enable", FALSE ); def.put("Max.Peer.Connections.Total", new Long(COConfigurationManager.CONFIG_DEFAULT_MAX_CONNECTIONS_GLOBAL)); def.put( "Peer.Fast.Initial.Unchoke.Enabled", FALSE ); def.put( "File Max Open", new Long(50)); def.put( "Use Config File Backups", TRUE); def.put( "Max Uploads", new Long(4) ); def.put( "Max Uploads Seeding", new Long(4)); def.put( "enable.seedingonly.maxuploads", FALSE ); def.put( "max.uploads.when.busy.inc.min.secs", new Long( 30 )); def.put( "Max Download Speed KBs", ZERO ); def.put( "Use Request Limiting", TRUE ); def.put( "Use Request Limiting Priorities", TRUE ); def.put( "Max Upload Speed KBs", ZERO); def.put( "Max Upload Speed Seeding KBs", ZERO ); def.put( "enable.seedingonly.upload.rate", FALSE ); def.put( "Max Seeds Per Torrent", ZERO); //def.put( "Auto Upload Speed Enabled", FALSE ); def.put( TransferSpeedValidator.AUTO_UPLOAD_ENABLED_CONFIGKEY, FALSE ); //"Auto Upload Speed Enabled" def.put( "Auto Upload Speed Seeding Enabled", FALSE ); def.put( "AutoSpeed Available", FALSE ); // informative read-only parameter def.put( "AutoSpeed Min Upload KBs", ZERO ); def.put( "AutoSpeed Max Upload KBs", ZERO ); def.put( "AutoSpeed Max Increment KBs", ONE); def.put( "AutoSpeed Max Decrement KBs", new Long(4)); def.put( "AutoSpeed Choking Ping Millis", new Long(200) ); def.put( "AutoSpeed Download Adj Enable", FALSE ); def.put( "AutoSpeed Download Adj Ratio", "1.0" ); def.put( "AutoSpeed Latency Factor", new Long(50)); def.put( "AutoSpeed Forced Min KBs", new Long(4)); def.put( "Auto Upload Speed Debug Enabled", FALSE ); def.put( "ASN Autocheck Performed Time", ZERO ); def.put( "LAN Speed Enabled", TRUE ); def.put( "Max LAN Download Speed KBs", ZERO ); def.put( "Max LAN Upload Speed KBs", ZERO ); def.put("Use Resume", TRUE); def.put("On Resume Recheck All", FALSE); def.put("Save Resume Interval", new Long(5)); def.put("Check Pieces on Completion", TRUE); def.put("Stop Ratio", new Float(0)); def.put("Stop Peers Ratio", ZERO); def.put("Disconnect Seed", TRUE); def.put("Seeding Piece Check Recheck Enable", TRUE ); def.put("priorityExtensions", ""); def.put("priorityExtensionsIgnoreCase", FALSE); def.put("Rename Incomplete Files", FALSE ); def.put("Rename Incomplete Files Extension", ".az!" ); def.put("Ip Filter Enabled", TRUE); def.put("Ip Filter Allow",FALSE); def.put("Ip Filter Enable Banning", TRUE); def.put("Ip Filter Ban Block Limit", new Long(4)); def.put("Ip Filter Ban Discard Ratio", "5.0" ); def.put("Ip Filter Ban Discard Min KB", new Long(128)); def.put("Ip Filter Banning Persistent", TRUE); def.put("Ip Filter Enable Description Cache", TRUE); def.put("Ip Filter Autoload File", ""); def.put("Allow Same IP Peers",FALSE); def.put("Use Super Seeding",FALSE); def.put("Pause Downloads On Exit", FALSE ); def.put("Resume Downloads On Start", FALSE ); // SWT GUI Settings def.put("User Mode", ZERO); //default data location options def.put("Use default data dir", FALSE); String docPath = SystemProperties.getDocPath(); File f = new File(docPath, "Azureus Downloads"); def.put("Default save path", f.getAbsolutePath()); def.put("update.start",TRUE); def.put("update.periodic",TRUE); def.put("update.opendialog",TRUE); def.put("update.autodownload", FALSE); def.put("Send Version Info", TRUE); // Logging def.put("Logger.Enabled", FALSE); //logging in general def.put("Logging Enable", FALSE); //file logging def.put("Logging Dir", ""); def.put("Logging Timestamp", "HH:mm:ss.SSS"); def.put("Logging Max Size", new Long(5)); int[] logComponents = { 0, 1, 2, 4 }; for (int i = 0; i < logComponents.length; i++) for (int j = 0; j <= 3; j++) def.put("bLog" + logComponents[i] + "-" + j, TRUE); def.put("Logger.DebugFiles.Enabled", TRUE); def.put("Logger.DebugFiles.Enabled.Force", FALSE ); def.put("Logging Enable UDP Transport", FALSE); //tracker proxy defaults def.put( "Enable.Proxy", FALSE ); def.put( "Enable.SOCKS", FALSE ); def.put( "Proxy.Host", "" ); def.put( "Proxy.Port", "" ); def.put( "Proxy.Username", "" ); // default is explicit "none", as opposed to "not defined" def.put( "Proxy.Password", "" ); def.put( "Proxy.Check.On.Start", TRUE ); // data proxy defaults def.put( "Proxy.Data.Enable", FALSE); def.put( "Proxy.Data.SOCKS.version", "V4" ); def.put( "Proxy.Data.SOCKS.inform", TRUE); def.put( "Proxy.Data.Same", TRUE); def.put( "Proxy.Data.Host", "" ); def.put( "Proxy.Data.Port", "" ); def.put( "Proxy.Data.Username", "" ); def.put( "Proxy.Data.Password", "" ); //old def.put( "Start Num Peers", new Long(-1) ); def.put( "Max Upload Speed", new Long(-1) ); def.put( "Max Clients", new Long(-1) ); def.put( "Server.shared.port", TRUE ); def.put( "Low Port", new Long(6881) ); def.put( "Already_Migrated", FALSE ); //misc def.put( "ID", "" ); def.put( "Play Download Finished", FALSE ); def.put( "Play Download Finished File", "" ); def.put( "Watch Torrent Folder", FALSE ); def.put( "Watch Torrent Folder Interval", ONE ); def.put( "Start Watched Torrents Stopped", FALSE ); def.put( "Watch Torrent Folder Path", "" ); def.put( "Prioritize First Piece", FALSE ); def.put( "Prioritize Most Completed Files", FALSE ); def.put( "Piece Picker Request Hint Enabled", TRUE ); def.put( "Use Lazy Bitfield", FALSE ); def.put( "Zero New", FALSE ); def.put( "XFS Allocation", FALSE ); def.put( "Copy And Delete Data Rather Than Move", FALSE); def.put( "File.save.peers.enable", TRUE ); def.put( "File.strict.locking", TRUE ); def.put( "Move Deleted Data To Recycle Bin", TRUE); def.put( "Popup Download Finished", FALSE); def.put( "Popup File Finished", FALSE); def.put( "Popup Download Added", FALSE); def.put( "Show Timestamp For Alerts", FALSE); def.put( "Use Message Box For Popups", FALSE); def.put( "Suppress Alerts", FALSE); //default torrent directory option def.put( "Save Torrent Files", TRUE ); def.put("General_sDefaultTorrent_Directory", SystemProperties.getUserPath()+"torrents"); def.put( "Bind IP", "" ); def.put( "Enforce Bind IP", FALSE); def.put( "Stats Export Peer Details", FALSE ); def.put( "Stats Export File Details", FALSE ); def.put( "Stats XSL File", "" ); def.put( "Stats Enable", FALSE ); def.put( "Stats Period", new Long(StatsWriterPeriodic.DEFAULT_SLEEP_PERIOD) ); def.put( "Stats Dir", "" ); def.put( "Stats File", StatsWriterPeriodic.DEFAULT_STATS_FILE_NAME ); def.put( "File.Torrent.IgnoreFiles", TOTorrent.DEFAULT_IGNORE_FILES ); def.put( "File.save.peers.max", new Long( TRTrackerAnnouncer.DEFAULT_PEERS_TO_CACHE ) ); // tracker def.put( "Tracker Compact Enable", TRUE ); def.put( "Tracker Key Enable Client", TRUE ); def.put( "Tracker Key Enable Server", TRUE ); def.put( "Tracker Separate Peer IDs", FALSE); def.put( "Tracker Client Connect Timeout", new Long(120)); def.put( "Tracker Client Read Timeout", new Long(60)); def.put( "Tracker Client Send OS and Java Version", TRUE); def.put( "Tracker Client Show Warnings", TRUE); def.put( "Tracker Client Min Announce Interval", ZERO); def.put( "Tracker Client Numwant Limit", new Long(100)); def.put( "Tracker Client No Port Announce", FALSE); def.put( "Tracker Public Enable", FALSE ); def.put( "Tracker Log Enable", FALSE ); def.put( "Tracker Port Enable", FALSE ); def.put( "Tracker Port", new Long( TRHost.DEFAULT_PORT ) ); def.put( "Tracker Port Backups", "" ); def.put( "Tracker Port SSL Enable", FALSE ); def.put( "Tracker Port SSL", new Long( TRHost.DEFAULT_PORT_SSL ) ); def.put( "Tracker Port SSL Backups", "" ); def.put( "Tracker Port Force External", FALSE ); def.put( "Tracker Host Add Our Announce URLs", TRUE ); def_put( "Tracker IP", "", new IPVerifier()); def.put( "Tracker Port UDP Enable", FALSE ); def.put( "Tracker Port UDP Version", new Long(2) ); def.put( "Tracker Send Peer IDs", TRUE ); def.put( "Tracker Max Peers Returned", new Long(100) ); def.put( "Tracker Scrape Cache", new Long( TRTrackerServer.DEFAULT_SCRAPE_CACHE_PERIOD ) ); def.put( "Tracker Announce Cache", new Long( TRTrackerServer.DEFAULT_ANNOUNCE_CACHE_PERIOD ) ); def.put( "Tracker Announce Cache Min Peers", new Long( TRTrackerServer.DEFAULT_ANNOUNCE_CACHE_PEER_THRESHOLD ) ); def.put( "Tracker Poll Interval Min", new Long( TRTrackerServer.DEFAULT_MIN_RETRY_DELAY) ); def.put( "Tracker Poll Interval Max", new Long( TRTrackerServer.DEFAULT_MAX_RETRY_DELAY) ); def.put( "Tracker Poll Seed Interval Mult", new Long(1)); def.put( "Tracker Scrape Retry Percentage", new Long( TRTrackerServer.DEFAULT_SCRAPE_RETRY_PERCENTAGE ) ); def.put( "Tracker Password Enable Web", FALSE ); def.put( "Tracker Password Web HTTPS Only", FALSE); def.put( "Tracker Password Enable Torrent", FALSE ); def.put( "Tracker Username", "" ); def.put( "Tracker Password", null ); def.put( "Tracker Poll Inc By", new Long( TRTrackerServer.DEFAULT_INC_BY ) ); def.put( "Tracker Poll Inc Per", new Long( TRTrackerServer.DEFAULT_INC_PER ) ); def.put( "Tracker NAT Check Enable", TRUE); def.put( "Tracker NAT Check Timeout", new Long(TRTrackerServer.DEFAULT_NAT_CHECK_SECS)); def.put( "Tracker Max Seeds Retained", ZERO ); def.put( "Tracker Max Seeds", ZERO ); def.put( "Tracker Max GET Time", new Long(20)); def.put( "Tracker Max POST Time Multiplier", ONE); def.put( "Tracker Max Threads", new Long( 48 )); def.put( "Tracker TCP NonBlocking", FALSE); def.put( "Tracker TCP NonBlocking Restrict Request Types", TRUE); def.put( "Tracker TCP NonBlocking Conc Max", new Long(2048)); def.put( "Tracker TCP NonBlocking Immediate Close", FALSE ); def.put( "Tracker Client Scrape Enable", TRUE); def.put( "Tracker Client Scrape Total Disable", FALSE ); def.put( "Tracker Client Scrape Stopped Enable", TRUE); def.put( "Tracker Client Scrape Single Only", FALSE); def.put( "Tracker Server Full Scrape Enable", TRUE ); def.put( "Tracker Server Not Found Redirect", "" ); def.put( "Tracker Server Support Experimental Extensions", FALSE ); def.put( "Network Selection Prompt", FALSE ); def.put( "Network Selection Default.Public", TRUE ); def.put( "Network Selection Default.I2P", FALSE ); def.put( "Network Selection Default.Tor", FALSE ); def.put( "Tracker Network Selection Default.Public", TRUE); def.put( "Tracker Network Selection Default.I2P", TRUE); def.put( "Tracker Network Selection Default.Tor", TRUE); def.put( "Peer Source Selection Default.Tracker", TRUE); def.put( "Peer Source Selection Default.DHT", TRUE); def.put( "Peer Source Selection Default.PeerExchange", TRUE); def.put( "Peer Source Selection Default.Plugin", TRUE); def.put( "Peer Source Selection Default.Incoming", TRUE); def.put( "config.style.useSIUnits", FALSE ); def.put( "config.style.forceSIValues", Constants.isOSX_10_6_OrHigher?FALSE:TRUE ); def.put( "config.style.useUnitsRateBits", FALSE ); def.put( "config.style.separateProtDataStats", FALSE ); def.put( "config.style.dataStatsOnly", FALSE ); def.put( "config.style.doNotUseGB", FALSE ); def.put( "Save Torrent Backup", FALSE ); def.put( "Sharing Protocol", "DHT" ); def.put( "Sharing Add Hashes", FALSE ); def.put( "Sharing Rescan Enable", FALSE); def.put( "Sharing Rescan Period", new Long(60)); def.put( "Sharing Torrent Comment", "" ); def.put( "Sharing Permit DHT", TRUE); def.put( "Sharing Torrent Private", FALSE); def.put( "File.Decoder.Prompt", FALSE ); def.put( "File.Decoder.Default", "" ); def.put( "File.Decoder.ShowLax", FALSE); def.put( "File.Decoder.ShowAll", FALSE); def.put( "Password enabled", FALSE ); def.put( "Password", null ); def.put( "config.interface.checkassoc", TRUE ); def.put( "confirmationOnExit", FALSE ); def.put( "locale", Locale.getDefault().toString() ); def.put( "locale.set.complete.count", ZERO); def.put( "Confirm Data Delete", TRUE ); def.put( "Password Confirm", null ); def.put( "Auto Update", TRUE ); def.put( "Alert on close", FALSE ); def.put( "diskmanager.friendly.hashchecking", FALSE ); def.put( "diskmanager.hashchecking.smallestfirst", TRUE ); def.put( "Default Start Torrents Stopped", FALSE); def.put( "Server Enable UDP", TRUE); // this actually means the UDP tracker client def.put( "diskmanager.perf.cache.enable", TRUE); def.put( "diskmanager.perf.cache.enable.read", FALSE); def.put( "diskmanager.perf.cache.enable.write", TRUE); def.put( "diskmanager.perf.cache.size", new Long(4)); // 4 MB def.put( "diskmanager.perf.cache.notsmallerthan", new Long(1024)); // 1024 K def.put( "diskmanager.perf.read.maxthreads", new Long(32)); def.put( "diskmanager.perf.read.maxmb", new Long(5)); def.put( "diskmanager.perf.write.maxthreads", new Long(32)); def.put( "diskmanager.perf.write.maxmb", new Long(5)); def.put( "diskmanager.perf.cache.trace", FALSE); def.put( "diskmanager.perf.cache.flushpieces", TRUE); def.put( "diskmanager.perf.read.aggregate.enable", FALSE ); def.put( "diskmanager.perf.read.aggregate.request.limit", ZERO ); def.put( "diskmanager.perf.read.aggregate.byte.limit", ZERO ); def.put( "diskmanager.perf.write.aggregate.enable", FALSE ); def.put( "diskmanager.perf.write.aggregate.request.limit", ZERO ); def.put( "diskmanager.perf.write.aggregate.byte.limit", ZERO ); def.put( "diskmanager.perf.checking.read.priority", FALSE ); def.put( "diskmanager.perf.checking.fully.async", FALSE ); def.put( "diskmanager.perf.queue.torrent.bias", TRUE ); // Peer control def.put( "peercontrol.udp.fallback.connect.fail", TRUE ); def.put( "peercontrol.udp.fallback.connect.drop", TRUE ); def.put( "peercontrol.udp.probe.enable", FALSE ); def.put( "peercontrol.hide.piece", FALSE ); def.put( "peercontrol.scheduler.use.priorities", TRUE ); def.put( "peercontrol.prefer.udp", FALSE ); def.put( "File.truncate.if.too.large", FALSE); def.put( "Enable System Tray", TRUE); def.put( "config.style.table.defaultSortOrder", ZERO); def.put( "Ignore.peer.ports", "0" ); def.put( "Security.JAR.tools.dir", "" ); def.put( "network.max.simultaneous.connect.attempts", new Long( Constants.isWindows?8:24 )); def.put( "network.tcp.max.connections.outstanding", new Long( 2048 )); def.put( "network.tcp.mtu.size", new Long(1500) ); def.put( "network.udp.mtu.size", new Long(1500) ); def.put( "network.tcp.socket.SO_SNDBUF", ZERO ); def.put( "network.tcp.socket.SO_RCVBUF", ZERO ); def.put( "network.tcp.socket.IPDiffServ", "" ); def.put( "network.tcp.read.select.time", new Long(25)); def.put( "network.tcp.read.select.min.time", new Long(0)); def.put( "network.tcp.write.select.time", new Long(25)); def.put( "network.tcp.write.select.min.time", new Long(0)); def.put( "network.control.write.idle.time", new Long(50)); def.put( "network.control.write.aggressive", FALSE ); def.put( "network.control.read.idle.time", new Long(50)); def.put( "network.control.read.aggressive", FALSE ); def.put( "network.control.read.processor.count", new Long(1)); def.put( "network.control.write.processor.count", new Long(1)); def.put( "peermanager.schedule.time", new Long(100)); def.put( "confirm_torrent_removal", FALSE ); def.put( "add_torrents_silently", FALSE ); def.put( "enable_small_osx_fonts", TRUE ); def.put( "Play Download Finished Announcement", FALSE); def.put( "Play Download Finished Announcement Text", "Download Complete"); def.put( "Play File Finished", FALSE ); def.put( "Play File Finished File", "" ); def.put( "Play File Finished Announcement", FALSE); def.put( "Play File Finished Announcement Text", "File Complete"); def.put( "filechannel.rt.buffer.millis", new Long( 60*1000 )); def.put( "filechannel.rt.buffer.pieces", new Long( 5 )); def.put( "BT Request Max Block Size", new Long(65536)); def.put( "network.tcp.enable_safe_selector_mode", FALSE ); def.put( "network.tcp.safe_selector_mode.chunk_size", new Long( 60 )); def.put( "network.transport.encrypted.require", FALSE ); def.put( "network.transport.encrypted.min_level", "RC4" ); def.put( "network.transport.encrypted.fallback.outgoing", FALSE ); def.put( "network.transport.encrypted.fallback.incoming", FALSE ); def.put( "network.transport.encrypted.use.crypto.port", FALSE ); def.put( "network.transport.encrypted.allow.incoming", TRUE ); // should always be TRUE, here for testing only def.put( "network.bind.local.port", ZERO ); def.put( "crypto.keys.system.managed", FALSE ); def.put( "peer.nat.traversal.request.conc.max", new Long(3)); // Memory settings def.put( "memory.slice.limit.multiplier", new Long(1)); // Move on completion settings. def.put( "Move Completed When Done", FALSE ); def.put( "Completed Files Directory", "" ); def.put( "Move Only When In Default Save Dir", TRUE ); def.put( "Move Torrent When Done", TRUE ); def.put( "File.move.subdir_is_default", TRUE ); // This gets permanently set by GlobalManagerImpl to false once Azureus has initialised. // This is intended to be used once as part of an upgrade. def.put( "Set Completion Flag For Completed Downloads On Start", TRUE ); // Move on removal settings. def.put( "File.move.download.removed.enabled", FALSE ); def.put( "File.move.download.removed.path", "" ); def.put( "File.move.download.removed.only_in_default", TRUE ); def.put( "File.move.download.removed.move_torrent", TRUE ); def.put( "File.move.download.removed.move_partial", FALSE ); def.put( "File.delete.include_files_outside_save_dir", FALSE); def.put("FilesView.show.full.path", FALSE ); def.put("MyTorrentsView.menu.show_parent_folder_enabled", FALSE); def.put("FileBrowse.usePathFinder", FALSE); //temp section for SpeedManagerAlgorithmProviderV2 try{ def.put(SpeedManagerAlgorithmProviderV2.SETTING_DOWNLOAD_MAX_LIMIT, new Long(SMConst.START_DOWNLOAD_RATE_MAX) ); def.put(SpeedManagerAlgorithmProviderV2.SETTING_UPLOAD_MAX_LIMIT, new Long(SMConst.START_UPLOAD_RATE_MAX) ); def.put(SpeedManagerAlgorithmProviderV2.SETTING_DHT_GOOD_SET_POINT, new Long(50) ); def.put(SpeedManagerAlgorithmProviderV2.SETTING_DHT_GOOD_TOLERANCE, new Long(100) ); def.put(SpeedManagerAlgorithmProviderV2.SETTING_DHT_BAD_SET_POINT, new Long(900) ); def.put(SpeedManagerAlgorithmProviderV2.SETTING_DHT_BAD_TOLERANCE, new Long(500) ); //**** NOTE! This default can be overridden in ConfigurationChecker def.put(SpeedManagerImpl.CONFIG_VERSION, new Long(2) ); // 1 == classic, 2 == beta def.put( SpeedLimitMonitor.DOWNLOAD_CONF_LIMIT_SETTING, SpeedLimitConfidence.NONE.getString() ); def.put( SpeedLimitMonitor.UPLOAD_CONF_LIMIT_SETTING, SpeedLimitConfidence.NONE.getString() ); def.put( SpeedLimitMonitor.UPLOAD_CHOKE_PING_COUNT, new Long(1) ); //default V2 algorithm seeding and download mode usage, stored as an Int def.put( SpeedLimitMonitor.USED_UPLOAD_CAPACITY_SEEDING_MODE, new Long(90) ); def.put( SpeedLimitMonitor.USED_UPLOAD_CAPACITY_DOWNLOAD_MODE, new Long(60) ); def.put( SpeedManagerAlgorithmProviderV2.SETTING_WAIT_AFTER_ADJUST, TRUE ); def.put( SpeedManagerAlgorithmProviderV2.SETTING_INTERVALS_BETWEEN_ADJUST, new Long(2) ); }catch( Throwable e ){ } // subscriptions def.put( "subscriptions.max.non.deleted.results", new Long( 512 )); def.put( "subscriptions.auto.start.downloads", TRUE ); def.put( "subscriptions.auto.start.min.mb", ZERO ); def.put( "subscriptions.auto.start.max.mb", ZERO ); } protected ConfigurationDefaults( Map _def ) { def = _def; } protected void def_put( String key, String key_def, COConfigurationManager.ParameterVerifier verifier ) { def.put( key, key_def ); List l = (List)parameter_verifiers.get( key ); if ( l == null ){ l = new ArrayList(1); parameter_verifiers.put( key, l ); } l.add( verifier ); } private void checkParameterExists(String p) throws ConfigurationParameterNotFoundException { if (!def.containsKey(p)) { ConfigurationParameterNotFoundException cpnfe = new ConfigurationParameterNotFoundException(p); //cpnfe.fillInStackTrace(); //Debug.out(cpnfe); throw cpnfe; } } public String getStringParameter(String p) throws ConfigurationParameterNotFoundException { checkParameterExists(p); Object o = def.get(p); if (o instanceof Number) return ((Number)o).toString(); return (String)o; } public int getIntParameter(String p) throws ConfigurationParameterNotFoundException { checkParameterExists(p); return ((Long) def.get(p)).intValue(); } public long getLongParameter(String p) throws ConfigurationParameterNotFoundException { checkParameterExists(p); return ((Long) def.get(p)).longValue(); } public float getFloatParameter(String p) throws ConfigurationParameterNotFoundException { checkParameterExists(p); return ((Float) def.get(p)).floatValue(); } public byte[] getByteParameter(String p) throws ConfigurationParameterNotFoundException { checkParameterExists(p); return (byte[])def.get(p); } public boolean getBooleanParameter(String p) throws ConfigurationParameterNotFoundException { checkParameterExists(p); return ((Long)def.get(p)).equals(TRUE); } public boolean hasParameter(String p) { return def.containsKey(p); } /** * Returns the default value as an object (String, Long, Float, Boolean) * * @param key * @return default value */ public Object getDefaultValueAsObject(String key) { return def.get(key); } public Set getAllowedParameters() { return def.keySet(); } public void addParameter(String sKey, String sParameter) { def.put(sKey, sParameter); } public void addParameter(String sKey, int iParameter) { def.put(sKey, new Long(iParameter)); } public void addParameter(String sKey, byte[] bParameter) { def.put(sKey, bParameter); } public void addParameter(String sKey, boolean bParameter) { Long lParameter = new Long(bParameter ? 1 : 0); def.put(sKey, lParameter); } public void addParameter(String sKey, long lParameter) { def.put(sKey, new Long(lParameter)); } public void addParameter(String sKey, float fParameter) { def.put(sKey, new Float(fParameter)); } public void registerExternalDefaults(Map addmap) { def.putAll(addmap); } public boolean doesParameterDefaultExist(String p) { return def.containsKey(p); } public Object getParameter( String key ) { return( def.get( key )); } public List getVerifiers( String key ) { return((List)parameter_verifiers.get( key )); } protected void runVerifiers() { Iterator it = parameter_verifiers.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry =(Map.Entry)it.next(); String key = (String)entry.getKey(); List verifiers = (List)entry.getValue(); for (int i=0;i")){ user = ""; } if ( COConfigurationManager.getBooleanParameter("Enable.SOCKS") ) { System.setProperty("socksProxyHost", host); System.setProperty("socksProxyPort", port); if (user.length() > 0) { System.setProperty("java.net.socks.username", user); System.setProperty("java.net.socks.password", pass); } } else { System.setProperty("http.proxyHost", host); System.setProperty("http.proxyPort", port); System.setProperty("https.proxyHost", host); System.setProperty("https.proxyPort", port); if (user.length() > 0) { System.setProperty("http.proxyUser", user); System.setProperty("http.proxyPassword", pass); } } } } SESecurityManager.initialise(); }finally{ class_mon.exit(); } } protected static void loadProperties( String dir ) { try{ File prop_file = new File( dir, "azureus.properties" ); if ( prop_file.exists()){ Logger.log(new LogEvent(LOGID, "Loading properties file from " + prop_file.getAbsolutePath())); Properties props = new Properties(); InputStream is = new FileInputStream( prop_file ); try{ props.load( is ); Iterator it = props.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); String key = (String)entry.getKey(); String value = (String)entry.getValue(); Logger.log(new LogEvent(LOGID, " " + key + "=" + value )); System.setProperty( key, value ); } }finally{ is.close(); } } }catch( Throwable e ){ } } public static void checkConfiguration() { try{ class_mon.enter(); if(checked) return; checked = true; boolean changed = false; String last_version = COConfigurationManager.getStringParameter( "azureus.version", "" ); String this_version = Constants.AZUREUS_VERSION; if ( !last_version.equals( this_version )){ if (!Constants.getBaseVersion(last_version).equals( Constants.getBaseVersion())) { COConfigurationManager.setParameter("Last Version", last_version); new_version = true; } if (!COConfigurationManager.hasParameter("First Recorded Version", true)) { COConfigurationManager.setParameter("First Recorded Version", last_version.length() == 0 ? this_version : last_version); } else { String sFirstVersion = COConfigurationManager.getStringParameter("First Recorded Version"); String sMinVersion = Constants.compareVersions(sFirstVersion, this_version) > 0 ? this_version : sFirstVersion; if (last_version.length() > 0) { sMinVersion = Constants.compareVersions(sMinVersion, last_version) > 0 ? last_version : sMinVersion; } COConfigurationManager.setParameter("First Recorded Version", sMinVersion); } COConfigurationManager.setParameter( "azureus.version", this_version ); changed = true; } // migration from default-save-dir enable = true to false // if the user hadn't explicitly set a value then we want to stick with true if ( last_version.length() == 0 ){ //this is a virgin installation, i.e. first time running, called only once ever new_install = true; // "last version" introduced at same time as the default save dir problem // which was the release after 2.2.0.0 // only do this on an already existing configuration. Easiest way to test // for this is the "diagnostics.tidy_close" flag if ( COConfigurationManager.doesParameterNonDefaultExist( "diagnostics.tidy_close" )){ if ( !COConfigurationManager.doesParameterNonDefaultExist( "Use default data dir" )){ COConfigurationManager.setParameter( "Use default data dir", true ); changed = true; } if ( !COConfigurationManager.doesParameterNonDefaultExist( "Tracker Port Enable" )){ COConfigurationManager.setParameter( "Tracker Port Enable", true ); changed = true; } } // also, if we now have a default data dir enabled (either explicitly or by // above migration fix), and there's no value defined for the dir, then // set it to what it would have been before the default was changed to blank if ( COConfigurationManager.getBooleanParameter( "Use default data dir" ) && !COConfigurationManager.doesParameterNonDefaultExist( "Default save path" )){ COConfigurationManager.setParameter( "Default save path", SystemProperties.getUserPath()+"downloads" ); changed = true; } //enable Beginner user mode for first time if( !COConfigurationManager.doesParameterNonDefaultExist( "User Mode" ) ) { COConfigurationManager.setParameter( "User Mode", 0 ); changed = true; } //make sure we set and save a random listen port if( !COConfigurationManager.doesParameterNonDefaultExist( "TCP.Listen.Port" ) ) { int rand_port = RandomUtils.generateRandomNetworkListenPort(); COConfigurationManager.setParameter( "TCP.Listen.Port", rand_port ); COConfigurationManager.setParameter( "UDP.Listen.Port", rand_port ); COConfigurationManager.setParameter( "UDP.NonData.Listen.Port", rand_port ); changed = true; } }else { //this is a pre-existing installation, called every time after first if // disable safe selector mode enabled at some point in the past if we're on java 6 or higher and/or not on windows ( COConfigurationManager.getBooleanParameter("network.tcp.enable_safe_selector_mode") && !(Constants.isWindows && (Constants.JAVA_VERSION.startsWith("1.4") || Constants.JAVA_VERSION.startsWith("1.5")) ) ) { COConfigurationManager.removeParameter("network.tcp.enable_safe_selector_mode"); changed = true; } // transition from tracker-only port override to global port override if(COConfigurationManager.doesParameterNonDefaultExist("TCP.Announce.Port")) { COConfigurationManager.setParameter("TCP.Listen.Port.Override", COConfigurationManager.getStringParameter("TCP.Announce.Port", "")); COConfigurationManager.removeParameter("TCP.Announce.Port"); changed = true; } //enable Advanced user mode for existing users by default, to ease 2304-->2306 migrations if( !COConfigurationManager.doesParameterNonDefaultExist( "User Mode" ) ) { COConfigurationManager.setParameter( "User Mode", 2 ); changed = true; } } // initial UDP port is same as TCP if( !COConfigurationManager.doesParameterNonDefaultExist( "UDP.Listen.Port" ) ){ COConfigurationManager.setParameter( "UDP.Listen.Port", COConfigurationManager.getIntParameter( "TCP.Listen.Port" )); changed = true; } // remove separate DHT udp port config and migrate to main UDP port above if ( !COConfigurationManager.getBooleanParameter( "Plugin.DHT.dht.portdefault", true )){ COConfigurationManager.removeParameter( "Plugin.DHT.dht.portdefault" ); int tcp_port = COConfigurationManager.getIntParameter( "TCP.Listen.Port" ); int udp_port = COConfigurationManager.getIntParameter( "UDP.Listen.Port" ); int dht_port = COConfigurationManager.getIntParameter( "Plugin.DHT.dht.port", udp_port ); if ( dht_port != udp_port ){ // if tcp + udp are currently different then we leave them as is and migrate // dht to the udp one. Otherwise we change the core udp to be that of the dht if ( tcp_port == udp_port ){ COConfigurationManager.setParameter( "UDP.Listen.Port", dht_port ); } } changed = true; } // reintroduce separate non-data UDP port yto separtate data from dht/UDP tracker if( !COConfigurationManager.doesParameterNonDefaultExist( "UDP.NonData.Listen.Port" ) ){ COConfigurationManager.setParameter( "UDP.NonData.Listen.Port", COConfigurationManager.getIntParameter( "UDP.Listen.Port" )); changed = true; } // fix up broken config when multi-udp not enabled but values differ if ( !COConfigurationManager.ENABLE_MULTIPLE_UDP_PORTS ){ int udp1 = COConfigurationManager.getIntParameter( "UDP.Listen.Port" ); int udp2 = COConfigurationManager.getIntParameter( "UDP.NonData.Listen.Port" ); if ( udp1 != udp2 ){ COConfigurationManager.setParameter( "UDP.NonData.Listen.Port", udp1 ); changed = true; } } int tcp_port = COConfigurationManager.getIntParameter( "TCP.Listen.Port" ); // reset invalid ports - single-instance socket port and (small) magnet uri listener port range if ( tcp_port == 6880 || ( tcp_port >= 45100 && tcp_port <= 45103 )){ int new_tcp_port = RandomUtils.generateRandomNetworkListenPort(); COConfigurationManager.setParameter( "TCP.Listen.Port", new_tcp_port ); if ( COConfigurationManager.getIntParameter( "UDP.Listen.Port" ) == tcp_port ){ COConfigurationManager.setParameter( "UDP.Listen.Port", new_tcp_port ); } if ( COConfigurationManager.getIntParameter( "UDP.NonData.Listen.Port" ) == tcp_port ){ COConfigurationManager.setParameter( "UDP.NonData.Listen.Port", new_tcp_port ); } changed = true; } // migrate to split tracker client/server key config if ( !COConfigurationManager.doesParameterDefaultExist( "Tracker Key Enable Client")){ boolean old_value = COConfigurationManager.getBooleanParameter("Tracker Key Enable"); COConfigurationManager.setParameter("Tracker Key Enable Client", old_value); COConfigurationManager.setParameter("Tracker Key Enable Server", old_value); changed = true; } int maxUpSpeed = COConfigurationManager.getIntParameter("Max Upload Speed KBs",0); int maxDownSpeed = COConfigurationManager.getIntParameter("Max Download Speed KBs",0); if( maxUpSpeed > 0 && maxUpSpeed < COConfigurationManager.CONFIG_DEFAULT_MIN_MAX_UPLOAD_SPEED && ( maxDownSpeed == 0 || maxDownSpeed > (2*maxUpSpeed ))){ changed = true; COConfigurationManager.setParameter("Max Upload Speed KBs", COConfigurationManager.CONFIG_DEFAULT_MIN_MAX_UPLOAD_SPEED); } int peersRatio = COConfigurationManager.getIntParameter("Stop Peers Ratio",0); if(peersRatio > 14) { COConfigurationManager.setParameter("Stop Peers Ratio", 14); changed = true; } int minQueueingShareRatio = COConfigurationManager.getIntParameter("StartStopManager_iFirstPriority_ShareRatio"); if (minQueueingShareRatio < 500) { COConfigurationManager.setParameter("StartStopManager_iFirstPriority_ShareRatio", 500); changed = true; } int iSeedingMin = COConfigurationManager.getIntParameter("StartStopManager_iFirstPriority_SeedingMinutes"); if (iSeedingMin < 90 && iSeedingMin != 0) { COConfigurationManager.setParameter("StartStopManager_iFirstPriority_SeedingMinutes", 90); changed = true; } int iDLMin = COConfigurationManager.getIntParameter("StartStopManager_iFirstPriority_DLMinutes"); if (iDLMin < 60*3 && iDLMin != 0) { COConfigurationManager.setParameter("StartStopManager_iFirstPriority_DLMinutes", 60*3); changed = true; } int iIgnoreSPRatio = COConfigurationManager.getIntParameter("StartStopManager_iFirstPriority_ignoreSPRatio"); if (iIgnoreSPRatio < 10 && iIgnoreSPRatio != 0) { COConfigurationManager.setParameter("StartStopManager_iFirstPriority_ignoreSPRatio", 10); changed = true; } String uniqueId = COConfigurationManager.getStringParameter("ID",null); if(uniqueId == null || uniqueId.length() != 20) { uniqueId = RandomUtils.generateRandomAlphanumerics( 20 ); COConfigurationManager.setParameter("ID", uniqueId); changed = true; } int cache_max = COConfigurationManager.getIntParameter("diskmanager.perf.cache.size"); if (cache_max > COConfigurationManager.CONFIG_CACHE_SIZE_MAX_MB ) { COConfigurationManager.setParameter("diskmanager.perf.cache.size", COConfigurationManager.CONFIG_CACHE_SIZE_MAX_MB ); changed = true; } if( cache_max < 1 ) { //oops COConfigurationManager.setParameter("diskmanager.perf.cache.size", 4 ); changed = true; } /** * Special Patch for OSX users */ if (Constants.isOSX) { boolean sound = COConfigurationManager.getBooleanParameter("Play Download Finished",true); // Command + Q destroys the window, then notifies SWT, making it // hard to do a confirmation exit. boolean confirmExit = COConfigurationManager.getBooleanParameter("confirmationOnExit"); if ( sound || confirmExit ) { COConfigurationManager.setParameter("Play Download Finished",false); COConfigurationManager.setParameter("confirmationOnExit",false); changed = true; } } if( Constants.isOSX ) { if( COConfigurationManager.getBooleanParameter( "enable_small_osx_fonts" ) ) { System.setProperty( "org.eclipse.swt.internal.carbon.smallFonts", "1" ); } else { System.getProperties().remove( "org.eclipse.swt.internal.carbon.smallFonts" ); } System.setProperty( "org.eclipse.swt.internal.carbon.noFocusRing", "1" ); } //remove a trailing slash, due to user manually entering the path in config String[] path_params = { "Default save path", "General_sDefaultTorrent_Directory", "Watch Torrent Folder Path", "Completed Files Directory" }; for( int i=0; i < path_params.length; i++ ) { if( path_params[i].endsWith( SystemProperties.SEP ) ) { String new_path = path_params[i].substring( 0, path_params[i].length() - 1 ); COConfigurationManager.setParameter( path_params[i], new_path ); changed = true; } } //2105 removed the language file web-update functionality, //but old left-over MessagesBundle.properties files in the user dir //cause display text problems, so let's delete them. if( ConfigurationManager.getInstance().doesParameterNonDefaultExist( "General_bEnableLanguageUpdate" ) ) { File user_dir = new File( SystemProperties.getUserPath() ); File[] files = user_dir.listFiles( new FilenameFilter() { public boolean accept(File dir, String name) { if( name.startsWith( "MessagesBundle" ) && name.endsWith( ".properties" ) ) { return true; } return false; } }); for( int i=0; i < files.length; i++ ) { File file = files[ i ]; if( file.exists() ) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "ConfigurationChecker:: removing old language file: " + file.getAbsolutePath())); file.renameTo( new File( file.getParentFile(), "delme" + file.getName() ) ); } } ConfigurationManager.getInstance().removeParameter( "General_bEnableLanguageUpdate" ); changed = true; } if ( FeatureAvailability.isAutoSpeedDefaultClassic()){ ConfigurationDefaults.getInstance().addParameter( SpeedManagerImpl.CONFIG_VERSION, 1 ); // 1 == classic, 2 == beta } if(changed) { COConfigurationManager.save(); } }finally{ class_mon.exit(); } ConfigurationDefaults.getInstance().runVerifiers(); } public static final boolean isNewInstall() { return( new_install ); } public static final boolean isNewVersion() { return( new_version ); } public static void main(String args[]) { Integer obj = new Integer(1); HashMap test = new HashMap(); int collisions = 0; for(int i = 0 ; i < 1000000 ; i++) { String id = RandomUtils.generateRandomAlphanumerics( 20 ); if(test.containsKey(id)) { collisions++; } else { test.put(id,obj); } if(i%1000 == 0) { System.out.println(i + " : " + id + " : " + collisions); } } System.out.println("\n" + collisions); } } azureus-4.3.0.6/org/gudy/azureus2/core3/config/impl/StringIteratorImpl.java0000644000175000017500000000267010373051016026044 0ustar adrianadrian/* * Created on 24 sept. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.config.impl; import java.util.Iterator; import org.gudy.azureus2.core3.config.StringIterator; /** * @author Olivier Chalouhi * */ public class StringIteratorImpl implements StringIterator { Iterator iterator; public StringIteratorImpl(Iterator _iterator) { iterator = _iterator; } public boolean hasNext() { return iterator.hasNext(); } public String next() { return (String) iterator.next(); } public void remove() { iterator.remove(); } } azureus-4.3.0.6/org/gudy/azureus2/core3/config/StringList.java0000644000175000017500000000253111021161614023374 0ustar adrianadrian/* * Created on 24 sept. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.config; /** * @author Olivier Chalouhi * */ public interface StringList { public int size(); public String get(int i); public void add(String str); public void add(int index,String str); public StringIterator iterator(); public int indexOf(String str); public boolean contains(String str); public String remove(int index); public String[] toArray(); } azureus-4.3.0.6/org/gudy/azureus2/core3/config/COConfigurationListener.java0000644000175000017500000000215107745771062026055 0ustar adrianadrian/* * File : COConfigurationListener.java * Created : 23-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.config; /** * @author gardnerpar * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public interface COConfigurationListener { public void configurationSaved(); } azureus-4.3.0.6/org/gudy/azureus2/core3/config/StringIterator.java0000644000175000017500000000217710373051016024263 0ustar adrianadrian/* * Created on 24 sept. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.config; /** * @author Olivier Chalouhi * */ public interface StringIterator { public boolean hasNext(); public String next(); public void remove(); } azureus-4.3.0.6/org/gudy/azureus2/core3/torrentdownloader/0000755000175000017500000000000011310377634022751 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderFactory.java0000644000175000017500000001227211024374164030621 0ustar adrianadrian/* * TorrentDownloaderFactory.java * * Created on 2. November 2003, 03:52 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.torrentdownloader; import java.util.Map; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.torrentdownloader.impl.TorrentDownloaderImpl; import org.gudy.azureus2.core3.torrentdownloader.impl.TorrentDownloaderManager; import org.gudy.azureus2.core3.util.Debug; /** * * @author Tobias Minich */ public class TorrentDownloaderFactory { private static TorrentDownloaderImpl getClass(boolean logged) { try { return (TorrentDownloaderImpl) Class.forName("org.gudy.azureus2.core3.torrentdownloader.impl.TorrentDownloader"+(logged?"Logged":"")+"Impl").newInstance(); } catch (Exception e) { Debug.printStackTrace( e ); return null; } } /** * creates and initializes a TorrentDownloader object with the specified parameters. * NOTE: this does not actually start the TorrentDownloader object * @param callback object to notify about torrent download status * @param url url of torrent file to download * @param referrer url of referrer to set as HTTP_REFERER header when requesting torrent * @param fileordir path to a file or directory that the actual * torrent file should be saved to. if a default save directory is not specified, this will be used instead. * even if a default save directory is specified, if this parameter path refers to a file, the filename will * be used when saving the torrent * @param whether or not logging is enabled for the torrent download. this is performed through the TorrentDownloaderLoggedImpl class which is only available in the uis project * @return */ public static TorrentDownloader create( TorrentDownloaderCallBackInterface callback, String url, String referrer, String fileordir, boolean logged) { TorrentDownloaderImpl dl = getClass(logged); if (dl!=null) dl.init(callback, url, referrer, null, fileordir); return dl; } public static TorrentDownloader create( TorrentDownloaderCallBackInterface callback, String url, String referrer, String fileordir) { return create(callback, url, referrer, fileordir, false); } public static TorrentDownloader create( TorrentDownloaderCallBackInterface callback, String url, String referrer, Map request_properties, String fileordir) { TorrentDownloaderImpl dl = getClass(false); if (dl!=null) dl.init(callback, url, referrer, request_properties, fileordir); return dl; } public static TorrentDownloader create(TorrentDownloaderCallBackInterface callback, String url, boolean logged) { return create(callback, url, null, null, logged); } public static TorrentDownloader create(TorrentDownloaderCallBackInterface callback, String url) { return create(callback, url, null, null, false); } public static TorrentDownloader create(String url, String fileordir, boolean logged) { return create(null, url, null, fileordir, logged); } public static TorrentDownloader create(String url, String fileordir) { return create(null, url, null, fileordir, false); } public static TorrentDownloader create(String url, boolean logged) { return create(null, url, null, null, logged); } public static TorrentDownloader create(String url) { return create(null, url, null, null, false); } public static void initManager(GlobalManager gm, boolean logged, boolean autostart, String downloaddir) { TorrentDownloaderManager.getInstance().init(gm, logged, autostart, downloaddir); } public static TorrentDownloader downloadManaged(String url, String fileordir, boolean logged) { return TorrentDownloaderManager.getInstance().download(url, fileordir, logged); } public static TorrentDownloader downloadManaged(String url, String fileordir) { return TorrentDownloaderManager.getInstance().download(url, fileordir); } public static TorrentDownloader downloadManaged(String url, boolean logged) { return TorrentDownloaderManager.getInstance().download(url, logged); } public static TorrentDownloader downloadManaged(String url) { return TorrentDownloaderManager.getInstance().download(url); } } azureus-4.3.0.6/org/gudy/azureus2/core3/torrentdownloader/impl/0000755000175000017500000000000011310377634023712 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderImpl.java0000644000175000017500000005203711310130440031040 0ustar adrianadrian/* * Written and copyright 2001-2003 Tobias Minich. * * HTTPDownloader.java * * Created on 17. August 2003, 22:22 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.torrentdownloader.impl; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLDecoder; import java.util.Iterator; import java.util.Map; import java.util.zip.GZIPInputStream; import java.util.zip.InflaterInputStream; import javax.net.ssl.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderCallBackInterface; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloader; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.util.protocol.magnet.MagnetConnection; import org.gudy.azureus2.core3.util.protocol.magnet.MagnetConnection2; import org.gudy.azureus2.core3.torrent.*; /** * @author Tobias Minich */ public class TorrentDownloaderImpl extends AEThread implements TorrentDownloader { private String original_url; private String url_str; private String referrer; private Map request_properties; private String file_str; private URL url; private HttpURLConnection con; private String error = "Ok"; private String status = ""; private TorrentDownloaderCallBackInterface iface; private int state = STATE_NON_INIT; private int percentDone = 0; private int readTotal = 0; private boolean cancel = false; private String filename, directoryname; private File file = null; private byte[] buf = new byte[1020]; private int bufBytes = 0; private boolean deleteFileOnCancel = true; private boolean ignoreReponseCode = false; private AEMonitor this_mon = new AEMonitor( "TorrentDownloader" ); private int errCode; public TorrentDownloaderImpl() { super("Torrent Downloader"); setDaemon(true); } public void init( TorrentDownloaderCallBackInterface _iface, String _url, String _referrer, Map _request_properties, String _file ) { this.iface = _iface; original_url = _url; //clean up accidental left-facing slashes _url = _url.replace( (char)92, (char)47 ); // it's possible that the URL hasn't been encoded (see Bug 878990) _url = _url.replaceAll( " ", "%20" ); setName("TorrentDownloader: " + _url); url_str = _url; referrer = _referrer; request_properties = _request_properties; file_str = _file; } public void notifyListener() { if (this.iface != null) this.iface.TorrentDownloaderEvent(this.state, this); else if (this.state == STATE_ERROR) System.err.println(this.error); } private void cleanUpFile() { if ((this.file != null) && this.file.exists()) this.file.delete(); } private void error(int errCode, String err) { try{ this_mon.enter(); // what's the point of this? this.state = STATE_ERROR; this.setError(errCode, err); this.cleanUpFile(); this.notifyListener(); }finally{ this_mon.exit(); closeConnection(); } } public void runSupport() { try{ new URL( url_str ); //determine if this is already a proper URL } catch( Throwable t ) { //it's not //check if the string is just a base32/hex-encoded torrent infohash String magnet_uri = UrlUtils.normaliseMagnetURI( url_str ); if ( magnet_uri != null ){ url_str = magnet_uri; } } try { url = AddressUtils.adjustURL( new URL(url_str)); String protocol = url.getProtocol().toLowerCase(); // hack here - the magnet download process requires an additional paramter to cause it to // stall on error so the error can be reported if ( protocol.equals( "magnet" ) || protocol.equals( "dht" )){ url = AddressUtils.adjustURL( new URL(url_str+"&pause_on_error=true")); } for (int i=0;i<2;i++){ try{ if ( protocol.equals("https")){ // see ConfigurationChecker for SSL client defaults HttpsURLConnection ssl_con = (HttpsURLConnection)url.openConnection(); // allow for certs that contain IP addresses rather than dns names ssl_con.setHostnameVerifier( new HostnameVerifier() { public boolean verify( String host, SSLSession session ) { return( true ); } }); con = ssl_con; }else{ con = (HttpURLConnection) url.openConnection(); } con.setRequestProperty("User-Agent", Constants.AZUREUS_NAME + " " + Constants.AZUREUS_VERSION); if ( referrer != null && referrer.length() > 0 ){ con.setRequestProperty( "Referer", referrer ); } if ( request_properties != null ){ Iterator it = request_properties.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); String key = (String)entry.getKey(); String value = (String)entry.getValue(); // currently this code doesn't support gzip/deflate... if ( !key.equalsIgnoreCase( "Accept-Encoding" )){ con.setRequestProperty( key, value ); } } } this.con.connect(); break; }catch( SSLException e ){ if ( i == 0 ){ if ( SESecurityManager.installServerCertificates( url ) != null ){ // certificate has been installed continue; // retry with new certificate } } throw( e ); }catch( IOException e ){ if ( i == 0 ){ URL retry_url = UrlUtils.getIPV4Fallback( url ); if ( retry_url != null ){ url = retry_url; }else{ throw( e ); } } } } int response = this.con.getResponseCode(); if (!ignoreReponseCode) { if ((response != HttpURLConnection.HTTP_ACCEPTED) && (response != HttpURLConnection.HTTP_OK)) { this.error(response, Integer.toString(response) + ": " + this.con.getResponseMessage()); return; } } /* Map headerFields = this.con.getHeaderFields(); System.out.println("Header of download of " + url_str); for (Iterator iter = headerFields.keySet().iterator(); iter.hasNext();) { String s = (String) iter.next(); System.out.println(s + ":" + headerFields.get(s)); } */ filename = this.con.getHeaderField("Content-Disposition"); if ((filename!=null) && filename.toLowerCase().matches(".*attachment.*")) // Some code to handle b0rked servers. while (filename.toLowerCase().charAt(0)!='a') filename = filename.substring(1); if ((filename == null) || !filename.toLowerCase().startsWith("attachment") || (filename.indexOf('=') == -1)) { String tmp = this.url.getFile(); if (tmp.length() == 0 || tmp.equals("/")) { filename = url.getHost(); } else if ( tmp.startsWith("?")){ // probably a magnet URI - use the hash // magnet:?xt=urn:sha1:VGC53ZWCUXUWVGX7LQPVZIYF4L6RXSU6 String query = tmp.toUpperCase(); int pos = query.indexOf( "XT=URN:SHA1:"); if ( pos == -1 ){ pos = query.indexOf( "XT=URN:BTIH:"); } if ( pos != -1 ){ pos += 12; int p2 = query.indexOf( "&", pos ); if ( p2 == -1 ){ filename = query.substring(pos); }else{ filename = query.substring(pos,p2); } }else{ filename = "Torrent" + (long)(Math.random()*Long.MAX_VALUE); } filename += ".tmp"; }else{ // might be /sdsdssd/ffgfgffgfg/ so remove trailing / while( tmp.endsWith( "/" )){ tmp = tmp.substring(0,tmp.length()-1); } if (tmp.lastIndexOf('/') != -1){ tmp = tmp.substring(tmp.lastIndexOf('/') + 1); } // remove any params in the url int param_pos = tmp.indexOf('?'); if ( param_pos != -1 ){ tmp = tmp.substring(0,param_pos); } filename = URLDecoder.decode(tmp, Constants.DEFAULT_ENCODING ); if ( filename.length() == 0 ){ filename = "Torrent" + (long)(Math.random()*Long.MAX_VALUE); } } } else { filename = filename.substring(filename.indexOf('=') + 1); if (filename.startsWith("\"") && filename.endsWith("\"")) filename = filename.substring(1, filename.lastIndexOf('\"')); filename = URLDecoder.decode(filename, Constants.DEFAULT_ENCODING ); // not sure of this piece of logic here but I'm not changing it at the moment File temp = new File(filename); filename = temp.getName(); } filename = FileUtil.convertOSSpecificChars( filename, false ); directoryname = COConfigurationManager.getDirectoryParameter("General_sDefaultTorrent_Directory"); boolean useTorrentSave = COConfigurationManager.getBooleanParameter("Save Torrent Files"); if (file_str != null) { // not completely sure about the whole logic in this block File temp = new File(file_str); //if we're not using a default torrent save dir if (!useTorrentSave || directoryname.length() == 0) { //if it's already a dir if (temp.isDirectory()) { //use it directoryname = temp.getCanonicalPath(); } //it's a file else { //so use its parent dir directoryname = temp.getCanonicalFile().getParent(); } } //if it's a file if (!temp.isDirectory()) { //set the file name filename = temp.getName(); } } // what would happen here if directoryname == null and file_str == null?? this.state = STATE_INIT; this.notifyListener(); } catch (java.net.MalformedURLException e) { this.error(0, "Exception while parsing URL '" + url + "':" + e.getMessage()); } catch (java.net.UnknownHostException e) { this.error(0, "Exception while initializing download of '" + url + "': Unknown Host '" + e.getMessage() + "'"); } catch (java.io.IOException ioe) { this.error(0, "I/O Exception while initializing download of '" + url + "':" + ioe.toString()); } catch( Throwable e ){ this.error(0, "Exception while initializing download of '" + url + "':" + e.toString()); } if ( this.state == STATE_ERROR ){ return; } try{ final boolean status_reader_run[] = { true }; this.state = STATE_START; notifyListener(); this.state = STATE_DOWNLOADING; notifyListener(); Thread status_reader = new AEThread( "TorrentDownloader:statusreader" ) { public void runSupport() { boolean changed_status = false; String last_status = ""; boolean sleep = false; while( true ){ try{ if ( sleep ){ Thread.sleep(50); sleep = false; } try{ this_mon.enter(); if ( !status_reader_run[0] ){ break; } }finally{ this_mon.exit(); } String s = con.getResponseMessage(); if ( s.equals( last_status )){ sleep = true; }else{ last_status = s; if ( !s.toLowerCase().startsWith("error:")){ if ( s.toLowerCase().indexOf( "alive" ) != -1 ){ if ( percentDone < 10 ){ percentDone++; } } int pos = s.indexOf( '%' ); if ( pos != -1 ){ int i; for ( i=pos-1;i>=0;i--){ char c = s.charAt(i); if ( !Character.isDigit( c ) && c != ' ' ){ i++; break; } } try{ percentDone = Integer.parseInt( s.substring( i, pos ).trim()); }catch( Throwable e ){ } } setStatus(s); }else{ error(con.getResponseCode(), s.substring(6)); } changed_status = true; } }catch( Throwable e ){ break; } } if ( changed_status ){ setStatus( "" ); } } }; status_reader.setDaemon( true ); status_reader.start(); InputStream in; try{ in = this.con.getInputStream(); } catch (FileNotFoundException e) { if (ignoreReponseCode) { in = this.con.getErrorStream(); } else { throw e; } }finally{ try{ this_mon.enter(); status_reader_run[0] = false; }finally{ this_mon.exit(); } } // handle some servers that return gzip'd torrents even though we don't request it! String encoding = con.getHeaderField( "content-encoding"); if ( encoding != null ){ if ( encoding.equalsIgnoreCase( "gzip" )){ in = new GZIPInputStream( in ); }else if ( encoding.equalsIgnoreCase( "deflate" )){ in = new InflaterInputStream( in ); } } if ( this.state != STATE_ERROR ){ this.file = new File(this.directoryname, filename); boolean useTempFile = false; try { this.file.createNewFile(); useTempFile = !this.file.exists(); } catch (Throwable t) { useTempFile = true; } if (useTempFile) { this.file = File.createTempFile("AZU", ".torrent", new File( this.directoryname)); this.file.createNewFile(); } FileOutputStream fileout = new FileOutputStream(this.file, false); bufBytes = 0; int size = (int) UrlUtils.getContentLength(con); this.percentDone = -1; do { if (this.cancel){ break; } try { bufBytes = in.read(buf); this.readTotal += bufBytes; if (size > 0){ this.percentDone = (100 * this.readTotal) / size; } notifyListener(); } catch (IOException e) { } if (bufBytes > 0){ fileout.write(buf, 0, bufBytes); } } while (bufBytes > 0); in.close(); fileout.flush(); fileout.close(); if (this.cancel) { this.state = STATE_CANCELLED; if (deleteFileOnCancel) { this.cleanUpFile(); } } else { if (this.readTotal <= 0) { this.error(0, "No data contained in '" + this.url.toString() + "'"); return; } // if the file has come down with a not-so-useful name then we try to rename // it to something more useful try{ if ( !filename.toLowerCase().endsWith(".torrent" )){ TOTorrent torrent = TorrentUtils.readFromFile( file, false ); String name = TorrentUtils.getLocalisedName( torrent ) + ".torrent"; File new_file = new File( directoryname, name ); if ( file.renameTo( new_file )){ filename = name; file = new_file; } } }catch( Throwable e ){ Debug.printStackTrace( e ); } TorrentUtils.setObtainedFrom( file, original_url ); this.state = STATE_FINISHED; } this.notifyListener(); } } catch (Exception e) { if ( !cancel ){ Debug.out("'" + this.directoryname + "' '" + filename + "'", e); } this.error(0, "Exception while downloading '" + this.url.toString() + "':" + e.getMessage()); } } public boolean equals(Object obj) { if (this == obj){ return true; } if ( obj instanceof TorrentDownloaderImpl ){ TorrentDownloaderImpl other = (TorrentDownloaderImpl) obj; if (other.getURL().equals(this.url.toString())){ File other_file = other.getFile(); File this_file = file; if ( other_file == this_file ){ return( true ); } if ( other_file == null || this_file == null ){ return( false ); } return( other_file.getAbsolutePath().equals(this_file.getAbsolutePath())); }else{ return false; } }else{ return false; } } public int hashCode() { return this.url.hashCode(); } public String getError() { return this.error; } public void setError(int errCode, String err) { this.error = err; this.errCode = errCode; } public int getErrorCode() { return errCode; } protected void setStatus( String str ) { status = str; notifyListener(); } public String getStatus() { return( status ); } public java.io.File getFile() { if ((!this.isAlive()) || (this.file == null)) this.file = new File(this.directoryname, filename); return this.file; } public int getPercentDone() { return this.percentDone; } public int getDownloadState() { return this.state; } public void setDownloadState(int state) { this.state = state; } public String getURL() { return this.url.toString(); } public void cancel() { this.cancel = true; closeConnection(); } protected void closeConnection() { if ( con instanceof MagnetConnection || con instanceof MagnetConnection2 ){ con.disconnect(); } } public void setDownloadPath(String path, String file) { if (!this.isAlive()) { if (path != null) this.directoryname = path; if (file != null) filename = file; } } /* (non-Javadoc) * @see org.gudy.azureus2.core3.torrentdownloader.TorrentDownloader#getTotalRead() */ public int getTotalRead() { return this.readTotal; } public byte[] getLastReadBytes() { if (bufBytes <= 0) { return new byte[0]; } byte[] bytes = new byte[bufBytes]; System.arraycopy(buf, 0, bytes, 0, bufBytes); return bytes; } public int getLastReadCount() { return bufBytes; } public void setDeleteFileOnCancel(boolean deleteFileOnCancel) { this.deleteFileOnCancel = deleteFileOnCancel; } public boolean getDeleteFileOnCancel() { return deleteFileOnCancel; } public boolean isIgnoreReponseCode() { return ignoreReponseCode; } public void setIgnoreReponseCode(boolean ignoreReponseCode) { this.ignoreReponseCode = ignoreReponseCode; } } azureus-4.3.0.6/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderManager.java0000644000175000017500000001144210373051046031520 0ustar adrianadrian/* * TorrentDownloaderManagerImpl.java * * Created on 2. November 2003, 04:29 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.torrentdownloader.impl; import java.util.ArrayList; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloader; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderCallBackInterface; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderFactory; /** * * @author Tobias Minich */ public class TorrentDownloaderManager implements TorrentDownloaderCallBackInterface { private static TorrentDownloaderManager man = null; private boolean logged = false; private boolean autostart = false; private GlobalManager gm = null; private String downloaddir; //private String error; private ArrayList running = new ArrayList(); private ArrayList queued = new ArrayList(); private ArrayList errors = new ArrayList(); public TorrentDownloaderManager() { try { downloaddir = COConfigurationManager.getDirectoryParameter("Default save path"); } catch (Exception e) { //this.error = e.getMessage(); downloaddir = null; } } public static TorrentDownloaderManager getInstance() { if (man==null) man = new TorrentDownloaderManager(); return man; } public void init(GlobalManager _gm, boolean _logged, boolean _autostart, String _downloaddir) { this.gm = _gm; this.logged = _logged; this.autostart = _autostart; if (_downloaddir != null) this.downloaddir = _downloaddir; } public TorrentDownloader add(TorrentDownloader dl) { if (dl.getDownloadState()==TorrentDownloader.STATE_ERROR) this.errors.add(dl); else if (this.running.contains(dl) || this.queued.contains(dl)) { ((TorrentDownloaderImpl) dl).setDownloadState(TorrentDownloader.STATE_DUPLICATE); ((TorrentDownloaderImpl) dl).notifyListener(); this.errors.add(dl); } else if (this.autostart) { dl.start(); } else this.queued.add(dl); return dl; } public TorrentDownloader download(String url, String fileordir, boolean logged) { return add(TorrentDownloaderFactory.create(this, url, null, fileordir, logged)); } public TorrentDownloader download(String url, boolean logged) { return add(TorrentDownloaderFactory.create(this, url, null, null, logged)); } public TorrentDownloader download(String url, String fileordir) { return add(TorrentDownloaderFactory.create(this, url, null, fileordir, this.logged)); } public TorrentDownloader download(String url) { return add(TorrentDownloaderFactory.create(this, url, this.logged)); } public void TorrentDownloaderEvent(int state, org.gudy.azureus2.core3.torrentdownloader.TorrentDownloader inf) { switch(state) { case TorrentDownloader.STATE_START: if (this.queued.contains(inf)) this.queued.remove(inf); if (!this.running.contains(inf)) this.running.add(inf); break; case TorrentDownloader.STATE_FINISHED: remove(inf); if ((gm != null) && (downloaddir != null)) { gm.addDownloadManager(inf.getFile().getAbsolutePath(), downloaddir); } break; case TorrentDownloader.STATE_ERROR: remove(inf); this.errors.add(inf); break; } } /** * @param inf */ public void remove(TorrentDownloader inf) { if (this.running.contains(inf)) this.running.remove(inf); if (this.queued.contains(inf)) this.queued.remove(inf); } } azureus-4.3.0.6/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderLoggedImpl.java0000644000175000017500000000241110067633642032175 0ustar adrianadrian/* * TorrentDownloaderLoggedImpl.java * * Created on 2. November 2003, 03:26 */ package org.gudy.azureus2.core3.torrentdownloader.impl; /** * * @author Tobias Minich */ public class TorrentDownloaderLoggedImpl extends TorrentDownloaderImpl { public void notifyListener() { super.notifyListener(); switch(this.getDownloadState()) { case STATE_INIT: org.apache.log4j.Logger.getLogger("azureus2.torrentdownloader").info("Download of '"+this.getFile().getName()+"' queued."); break; case STATE_START: org.apache.log4j.Logger.getLogger("azureus2.torrentdownloader").info("Download of '"+this.getFile().getName()+"' started."); break; case STATE_FINISHED: org.apache.log4j.Logger.getLogger("azureus2.torrentdownloader").info("Download of '"+this.getFile().getName()+"' finished."); break; case STATE_ERROR: org.apache.log4j.Logger.getLogger("azureus2.torrentdownloader").error(this.getError()); break; case STATE_DUPLICATE: org.apache.log4j.Logger.getLogger("azureus2.torrentdownloader").error("Download of '"+this.getFile().getName()+"' cancelled. File is already queued or downloading."); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderException.java0000644000175000017500000000203411012742270031135 0ustar adrianadrian/* * File : TorrentDownloaderException.java * Created : 27-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.torrentdownloader; /** * @author parg * */ public class TorrentDownloaderException extends Exception { public TorrentDownloaderException( String str ) { super(str); } } azureus-4.3.0.6/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderCallBackInterface.java0000644000175000017500000000227410373051016032462 0ustar adrianadrian/* * TorrentDownloaderCallBackInterface.java * * Created on 2. November 2003, 01:32 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.torrentdownloader; /** * * @author Tobias Minich */ public interface TorrentDownloaderCallBackInterface { public void TorrentDownloaderEvent(int state, TorrentDownloader inf); } azureus-4.3.0.6/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloader.java0000644000175000017500000000663111131317606027270 0ustar adrianadrian/* * TorrentDownloaderInfo.java * * Created on 2. November 2003, 01:48 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.torrentdownloader; /** * * @author Tobias Minich */ public interface TorrentDownloader { public static final int STATE_NON_INIT = -1; public static final int STATE_INIT = 0; public static final int STATE_START = 1; public static final int STATE_DOWNLOADING = 2; public static final int STATE_FINISHED = 3; public static final int STATE_ERROR = 4; public static final int STATE_DUPLICATE = 5; public static final int STATE_CANCELLED = 6; //public void init(TorrentDownloaderCallBackInterface _iface, String _url, String _file); /** * Starts the download. */ public void start(); /** * Cancels the download. */ public void cancel(); /** * Changes the path and filename to download to. * You can give null for either to leave it as is. * (These are initialized to either the path/filename given via * TorrentDownloaderFactory.download(Managed) or to * the default torrent save directory (path) and the filename the * server proposes (file). * This function does nothing after the download has been started. * * @param path The path for download. * @param file The file name for download. */ public void setDownloadPath(String path, String file); /** * Gets the state of the TorrentDownloader. */ public int getDownloadState(); /** * Returns the File the TorrentDownloader downloads to. */ public java.io.File getFile(); /** * Returns the amount downloaded in per cent. Gives -1 if total size is not available. */ public int getPercentDone(); /** * Returns the amount downloaded in bytes. */ public int getTotalRead(); /** * Returns the error string if one occured, "Ok" otherwise. */ public String getError(); public String getStatus(); /** * Returns the URL downloaded from. */ public String getURL(); /** * @return */ int getLastReadCount(); /** * @return */ byte[] getLastReadBytes(); /** * @return */ boolean getDeleteFileOnCancel(); /** * @param deleteFileOnCancel */ void setDeleteFileOnCancel(boolean deleteFileOnCancel); /** * @return * * @since 4.0.0.5 */ boolean isIgnoreReponseCode(); /** * @param ignoreReponseCode * * @since 4.0.0.5 */ void setIgnoreReponseCode(boolean ignoreReponseCode); } azureus-4.3.0.6/org/gudy/azureus2/core3/security/0000755000175000017500000000000011310377634021044 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/security/impl/0000755000175000017500000000000011310377634022005 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/security/impl/SESecurityManagerImpl.java0000644000175000017500000006523411147377516027045 0ustar adrianadrian/* * File : SECertificateHandlerImpl.java * Created : 29-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.security.impl; /** * @author parg * */ import java.io.*; import java.net.Authenticator; import java.net.MalformedURLException; import java.net.PasswordAuthentication; import java.net.URL; import java.security.Key; import java.security.KeyStore; import java.security.Permission; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.*; import javax.net.ssl.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.security.SECertificateListener; import org.gudy.azureus2.core3.security.SEKeyDetails; import org.gudy.azureus2.core3.security.SEPasswordListener; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.RandomUtils; import com.aelitis.azureus.core.util.CopyOnWriteList; public class SESecurityManagerImpl { private static final LogIDs LOGID = LogIDs.NET; protected static SESecurityManagerImpl singleton = new SESecurityManagerImpl(); protected static String KEYSTORE_TYPE; static{ String[] types = { "JKS", "GKR" }; for (int i=0;i" as some servers seem to cause // a password prompt when no auth defined and java doesn't cache a successful blank response // thus causing repetitive prompts if ( protocol.toLowerCase().startsWith( "socks" )){ String socks_user = COConfigurationManager.getStringParameter( "Proxy.Username" ).trim(); String socks_pw = COConfigurationManager.getStringParameter( "Proxy.Password" ).trim(); if ( socks_user.equalsIgnoreCase( "" )){ return( new PasswordAuthentication( "", "".toCharArray())); } // actually getting all sorts of problems with Java not caching socks passwords // properly so I've abandoned prompting for them and always use the defined // password if ( socks_user.length() == 0 ){ Logger.log( new LogAlert(false, LogAlert.AT_WARNING, "Socks server is requesting authentication, please setup user and password in config" )); } return( new PasswordAuthentication( socks_user, socks_pw.toCharArray())); } try{ URL tracker_url = new URL( protocol + "://" + host + ":" + port + "/" ); return( getPasswordAuthentication( realm, tracker_url )); }catch( MalformedURLException e ){ Debug.printStackTrace( e ); return( null ); } } protected boolean checkKeyStoreHasEntry() { File f = new File(keystore_name); if ( !f.exists()){ Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Security.keystore.empty"), new String[] { keystore_name }); return( false ); } try{ KeyStore key_store = loadKeyStore(); Enumeration enumx = key_store.aliases(); if ( !enumx.hasMoreElements()){ Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Security.keystore.empty"), new String[] { keystore_name }); return( false ); } }catch( Throwable e ){ Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Security.keystore.corrupt"), new String[] { keystore_name }); return( false ); } return( true ); } protected boolean ensureStoreExists( String name ) { try{ this_mon.enter(); KeyStore keystore = KeyStore.getInstance( KEYSTORE_TYPE ); if ( !new File(name).exists()){ keystore.load(null,null); FileOutputStream out = null; try{ out = new FileOutputStream(name); keystore.store(out, SESecurityManager.SSL_PASSWORD.toCharArray()); }finally{ if ( out != null ){ out.close(); } } return( true ); }else{ return( false ); } }catch( Throwable e ){ Debug.printStackTrace(e); return( false ); }finally{ this_mon.exit(); } } public KeyStore getKeyStore() throws Exception { return( loadKeyStore()); } public KeyStore getTrustStore() throws Exception { KeyStore keystore = KeyStore.getInstance( KEYSTORE_TYPE ); if ( !new File(truststore_name).exists()){ keystore.load(null,null); }else{ FileInputStream in = null; try{ in = new FileInputStream(truststore_name); keystore.load(in, SESecurityManager.SSL_PASSWORD.toCharArray()); }finally{ if ( in != null ){ in.close(); } } } return( keystore ); } protected KeyStore loadKeyStore() throws Exception { KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); return( loadKeyStore( keyManagerFactory )); } protected KeyStore loadKeyStore( KeyManagerFactory keyManagerFactory ) throws Exception { KeyStore key_store = KeyStore.getInstance( KEYSTORE_TYPE ); if ( !new File(keystore_name).exists()){ key_store.load(null,null); }else{ InputStream kis = null; try{ kis = new FileInputStream(keystore_name); key_store.load(kis, SESecurityManager.SSL_PASSWORD.toCharArray()); }finally{ if ( kis != null ){ kis.close(); } } } keyManagerFactory.init(key_store, SESecurityManager.SSL_PASSWORD.toCharArray()); return( key_store ); } public SSLServerSocketFactory getSSLServerSocketFactory() throws Exception { if ( !checkKeyStoreHasEntry()){ return( null ); } SSLContext context = SSLContext.getInstance( "SSL" ); // Create the key manager factory used to extract the server key KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); loadKeyStore(keyManagerFactory); // Initialize the context with the key managers context.init( keyManagerFactory.getKeyManagers(), null, RandomUtils.SECURE_RANDOM); SSLServerSocketFactory factory = context.getServerSocketFactory(); return( factory ); } public SEKeyDetails getKeyDetails( String alias ) throws Exception { // Create the key manager factory used to extract the server key KeyStore key_store = loadKeyStore(); final Key key = key_store.getKey( alias, SESecurityManager.SSL_PASSWORD.toCharArray()); if ( key == null ){ return( null ); } java.security.cert.Certificate[] chain = key_store.getCertificateChain( alias ); final X509Certificate[] res = new X509Certificate[chain.length]; for (int i=0;i listeners = new ArrayList(); protected static List clients = new ArrayList(); protected static AEMonitor class_mon = new AEMonitor( "TRTrackerClientFactory" ); public static TRTrackerAnnouncer create( TOTorrent torrent, String[] networks, boolean manual ) throws TRTrackerAnnouncerException { TRTrackerAnnouncerImpl client = new TRTrackerAnnouncerMuxer( torrent, networks, manual ); if ( !manual ){ List listeners_copy = new ArrayList(); try{ class_mon.enter(); clients.add( client ); listeners_copy = new ArrayList( listeners ); }finally{ class_mon.exit(); } for (int i=0;i scrapeInterval) scrapeInterval = iRecIntervalSecs; // randomize scrape interval by 3 minutes to scrapeInterval += scrapeFuzzAdd; if (scrapeInterval > MAX) scrapeInterval = MAX; return scrapeInterval; } public String getString() { return( getURL() + ": " + ByteFormatter.encodeString(hash.getBytes()) +",seeds=" + seeds + ",peers=" + peers +",state="+status+ "/"+sStatus+",last="+last_status+"/"+sLastStatus+",start="+scrapeStartTime+",next="+nextScrapeStartTime); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerImpl.java0000644000175000017500000003415211307334262030247 0ustar adrianadrian/* * Created on 14-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.client.impl; import java.io.UnsupportedEncodingException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.peer.PEPeerSource; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerListener; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponsePeer; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.LightHashMap; import org.gudy.azureus2.core3.util.ListenerManager; import org.gudy.azureus2.core3.util.ListenerManagerDispatcher; import org.gudy.azureus2.plugins.download.DownloadAnnounceResultPeer; /** * @author parg * */ public abstract class TRTrackerAnnouncerImpl implements TRTrackerAnnouncer { // Used to be componentID 2 public final static LogIDs LOGID = LogIDs.TRACKER; // listener protected static final int LDT_TRACKER_RESPONSE = 1; protected static final int LDT_URL_CHANGED = 2; protected static final int LDT_URL_REFRESH = 3; protected ListenerManager listeners = ListenerManager.createManager( "TrackerClient:ListenDispatcher", new ListenerManagerDispatcher() { public void dispatch( TRTrackerAnnouncerListener listener, int type, Object value ) { if ( type == LDT_TRACKER_RESPONSE ){ listener.receivedTrackerResponse((TRTrackerAnnouncerResponse)value); }else if ( type == LDT_URL_CHANGED ){ Object[] x = (Object[])value; URL old_url = (URL)x[0]; URL new_url = (URL)x[1]; boolean explicit = ((Boolean)x[2]).booleanValue(); listener.urlChanged( TRTrackerAnnouncerImpl.this, old_url, new_url, explicit ); }else{ listener.urlRefresh(); } } }); private Map tracker_peer_cache = new LinkedHashMap(); // insertion order - most recent at end private AEMonitor tracker_peer_cache_mon = new AEMonitor( "TRTrackerClientClassic:PC" ); private TOTorrent torrent; protected TRTrackerAnnouncerImpl( TOTorrent _torrent ) { torrent = _torrent; } public Helper getHelper() { return( new Helper() { public void addToTrackerCache( TRTrackerAnnouncerResponsePeerImpl[] peers ) { TRTrackerAnnouncerImpl.this.addToTrackerCache( peers ); } public TRTrackerAnnouncerResponsePeer[] getPeersFromCache( int num_want ) { return( TRTrackerAnnouncerImpl.this.getPeersFromCache(num_want)); } public void setTrackerResponseCache( Map map ) { TRTrackerAnnouncerImpl.this.setTrackerResponseCache( map ); } public void removeFromTrackerResponseCache( String ip, int tcpPort ) { TRTrackerAnnouncerImpl.this.removeFromTrackerResponseCache( ip,tcpPort ); } public Map getTrackerResponseCache() { return( TRTrackerAnnouncerImpl.this.getTrackerResponseCache()); } public void informResponse( TRTrackerAnnouncerResponse response ) { listeners.dispatch( LDT_TRACKER_RESPONSE, response ); } public void informURLChange( URL old_url, URL new_url, boolean explicit ) { listeners.dispatch( LDT_URL_CHANGED, new Object[]{old_url, new_url, new Boolean(explicit)}); } public void informURLRefresh() { listeners.dispatch( LDT_URL_REFRESH, null ); } public void addListener( TRTrackerAnnouncerListener l ) { TRTrackerAnnouncerImpl.this.addListener( l ); } public void removeListener( TRTrackerAnnouncerListener l ) { TRTrackerAnnouncerImpl.this.removeListener( l ); } }); } public static byte[] getAnonymousPeerId( String my_ip, int my_port ) { byte[] anon_peer_id = new byte[20]; // unique initial two bytes to identify this as fake anon_peer_id[0] = (byte)'['; anon_peer_id[1] = (byte)']'; try{ byte[] ip_bytes = my_ip.getBytes( Constants.DEFAULT_ENCODING ); int ip_len = ip_bytes.length; if ( ip_len > 18 ){ ip_len = 18; } System.arraycopy( ip_bytes, 0, anon_peer_id, 2, ip_len ); int port_copy = my_port; for (int j=2+ip_len;j<20;j++){ anon_peer_id[j] = (byte)(port_copy&0xff); port_copy >>= 8; } }catch( UnsupportedEncodingException e ){ Debug.printStackTrace( e ); } return( anon_peer_id ); } // NOTE: tracker_cache is cleared out in DownloadManager when opening a torrent for the // first time as a DOS prevention measure public Map getTrackerResponseCache() { return( exportTrackerCache()); } public void setTrackerResponseCache( Map map ) { int num = importTrackerCache( map ); if (Logger.isEnabled()) Logger.log(new LogEvent(getTorrent(), LOGID, "TRTrackerClient: imported " + num + " cached peers")); } protected Map exportTrackerCache() { Map res = new LightHashMap(1); List peers = new ArrayList(); res.put( "tracker_peers", peers ); try{ tracker_peer_cache_mon.enter(); Iterator it = tracker_peer_cache.values().iterator(); while( it.hasNext()){ TRTrackerAnnouncerResponsePeer peer = (TRTrackerAnnouncerResponsePeer)it.next(); LightHashMap entry = new LightHashMap(); entry.put( "ip", peer.getAddress().getBytes()); entry.put( "src", peer.getSource().getBytes()); entry.put( "port", new Long(peer.getPort())); int udp_port = peer.getUDPPort(); if ( udp_port != 0 ){ entry.put( "udpport", new Long( udp_port)); } int http_port = peer.getHTTPPort(); if ( http_port != 0 ){ entry.put( "httpport", new Long( http_port)); } entry.put( "prot", new Long(peer.getProtocol())); byte az_ver = peer.getAZVersion(); if ( az_ver != TRTrackerAnnouncer.AZ_TRACKER_VERSION_1 ){ entry.put( "azver", new Long( az_ver )); } entry.compactify(0.9f); peers.add( entry ); } if (Logger.isEnabled()) Logger.log(new LogEvent(getTorrent(), LOGID, "TRTrackerClient: exported " + tracker_peer_cache.size() + " cached peers")); }finally{ tracker_peer_cache_mon.exit(); } return( res ); } protected int importTrackerCache( Map map ) { if ( !COConfigurationManager.getBooleanParameter("File.save.peers.enable")){ return( 0 ); } try{ if ( map == null ){ return( 0 ); } List peers = (List)map.get( "tracker_peers" ); if ( peers == null ){ return( 0 ); } try{ tracker_peer_cache_mon.enter(); for (int i=0;i 0 ){ str += " - " + failure_reason; } return( str ); } public void setFailurReason(String reason) { failure_reason = reason; } public long getTimeToWait() { return( time_to_wait ); } public String getAdditionalInfo() { return( failure_reason ); } public void setPeers( TRTrackerAnnouncerResponsePeer[] _peers ) { peers = _peers; } public TRTrackerAnnouncerResponsePeer[] getPeers() { return( peers ); } public void setExtensions( Map _extensions ) { extensions = _extensions; } public Map getExtensions() { return( extensions ); } public URL getURL() { return( url ); } public int getScrapeCompleteCount() { return( scrape_complete ); } public int getScrapeIncompleteCount() { return( scrape_incomplete ); } public void setScrapeResult( int _complete, int _incomplete ) { scrape_complete = _complete; scrape_incomplete = _incomplete; } public void print() { System.out.println( "TRTrackerResponse::print"); System.out.println( "\tstatus = " + getStatus()); System.out.println( "\tfail msg = " + getAdditionalInfo()); System.out.println( "\tpeers:" ); if ( peers != null ){ for (int i=0;i0?min_interval_override:TRTrackerAnnouncer.REFRESH_MINIMUM_SECS; if ( manual_control || force || ( now - last_update_time_secs >= effective_min )){ requestUpdate(); } } public void complete( boolean already_reported ) { complete_reported = (complete_reported || already_reported ); completed = true; requestUpdate(); } public void stop( boolean for_queue ) { stopped = true; stopped_for_queue = for_queue; requestUpdate(); } protected void requestUpdate() { try{ this_mon.enter(); if ( current_timer_event != null ){ current_timer_event.cancel(); } rd_last_override = SystemTime.getCurrentTime(); //"pause" overrides for 10s if ( !destroyed ){ if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, "Forcing tracker announce now via " + Debug.getStackTrace(true, false, 0, 3))); current_timer_event = tracker_timer.addEvent( SystemTime.getCurrentTime(), timer_event_action ); } }finally{ this_mon.exit(); } } protected long requestUpdateSupport() { boolean clear_progress = true; try{ try{ this_mon.enter(); // can't continue if the data provider hasn't been set yet... if ( update_in_progress || announce_data_provider == null ){ clear_progress = false; return( getErrorRetryInterval() ); } update_in_progress = true; }finally{ this_mon.exit(); } last_update_time_secs = SystemTime.getCurrentTime()/1000; tracker_status_str = MessageText.getString("PeerManager.status.checking") + "..."; //$NON-NLS-1$ //$NON-NLS-2$ TRTrackerAnnouncerResponseImpl response = null; if ( stopped ){ // if manual control then we assume that a stop request is required, even if we // are in an init state. needed for explicit stop based on URL if ( tracker_state == TRTrackerAnnouncer.TS_INITIALISED && !manual_control ){ // never started tracker_state = TRTrackerAnnouncer.TS_STOPPED; }else if ( tracker_state != TRTrackerAnnouncer.TS_STOPPED ){ response = stopSupport(); if ( response.getStatus() == TRTrackerAnnouncerResponse.ST_ONLINE ){ tracker_state = TRTrackerAnnouncer.TS_STOPPED; }else{ // just have one go at sending a stop event as we don't want to sit here // forever trying to send stop to a stuffed tracker tracker_state = TRTrackerAnnouncer.TS_STOPPED; } } }else if ( tracker_state == TRTrackerAnnouncer.TS_INITIALISED ){ // always go through the "start" phase, even if we're already complete // as some trackers insist on the initial "start" response = startSupport(); if ( response.getStatus() == TRTrackerAnnouncerResponse.ST_ONLINE ){ tracker_state = TRTrackerAnnouncer.TS_DOWNLOADING; } }else if ( completed ){ if ( !complete_reported ){ response = completeSupport(); // treat the "complete" as processed if the tracker replies either OK or an explicit // error. In particular, if the tracker has returned an error to control seed limits // we don't want to treat this as an error and report completed again next time around // as this causes the tracker to double count stats if ( response.getStatus() != TRTrackerAnnouncerResponse.ST_OFFLINE ){ complete_reported = true; tracker_state = TRTrackerAnnouncer.TS_COMPLETED; } }else{ tracker_state = TRTrackerAnnouncer.TS_COMPLETED; response = updateSupport(); } }else{ response = updateSupport(); } if ( response != null ){ int rs = response.getStatus(); if ( rs == TRTrackerAnnouncerResponse.ST_OFFLINE ){ tracker_status_str = MessageText.getString("PeerManager.status.offline"); }else if ( rs == TRTrackerAnnouncerResponse.ST_REPORTED_ERROR ){ tracker_status_str = MessageText.getString("PeerManager.status.error"); // move state back to initialised to next time around a "started" // event it resent. Required for trackers like 123torrents.com that // will fail peers that don't start with a "started" event after a // tracker restart tracker_state = TRTrackerAnnouncer.TS_INITIALISED; }else{ if ( announce_data_provider.isPeerSourceEnabled( PEPeerSource.PS_BT_TRACKER )){ tracker_status_str = MessageText.getString("PeerManager.status.ok"); }else{ tracker_status_str = MessageText.getString("PeerManager.status.ps_disabled"); response.setPeers(new TRTrackerAnnouncerResponsePeerImpl[0]); } } String reason = response.getAdditionalInfo(); if ( reason != null ){ tracker_status_str += " (" + reason + ")"; } last_response = response; helper.informResponse( response ); return( response.getTimeToWait()); } tracker_status_str = ""; return( getErrorRetryInterval() ); }catch( Throwable e ){ Debug.printStackTrace( e ); return( getErrorRetryInterval() ); }finally{ try{ this_mon.enter(); if ( clear_progress ){ update_in_progress = false; } }finally{ this_mon.exit(); } } } protected TRTrackerAnnouncerResponseImpl startSupport() { if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, "Tracker Announcer is sending " + "a start Request")); return (update("started")); } protected TRTrackerAnnouncerResponseImpl completeSupport() { if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, "Tracker Announcer is sending " + "a completed Request")); return (update("completed")); } protected TRTrackerAnnouncerResponseImpl stopSupport() { if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, "Tracker Announcer is sending " + "a stopped Request")); return (update("stopped")); } protected TRTrackerAnnouncerResponseImpl updateSupport() { if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, "Tracker Announcer is sending " + "an update Request")); return update(""); } private TRTrackerAnnouncerResponseImpl update( String evt ) { // this method filters out any responses incompatible with the network selection TRTrackerAnnouncerResponseImpl resp = update2( evt ); TRTrackerAnnouncerResponsePeer[] peers = resp.getPeers(); if ( peers != null ){ List p = new ArrayList(); for (int i=0;i":request_url.toString()) + "'" ); }catch( Throwable e ){ announceFailCount++; last_failure_resp = new TRTrackerAnnouncerResponseImpl( original_url, torrent_hash, TRTrackerAnnouncerResponse.ST_OFFLINE, getErrorRetryInterval(), e.getMessage()==null?e.toString():e.getMessage()); } if ( destroyed ){ break outer; } } } // things no good here if ( last_failure_resp == null ){ last_failure_resp = new TRTrackerAnnouncerResponseImpl( null, torrent_hash, TRTrackerAnnouncerResponse.ST_OFFLINE, getErrorRetryInterval(), "Reason Unknown" ); } // use 4* the num_want as no doubt a fair few connections will fail and // we want to get a decent reconnect rate int num_want = calculateNumWant() * 4; TRTrackerAnnouncerResponsePeer[] cached_peers = helper.getPeersFromCache(num_want); if ( cached_peers.length > 0 ){ // System.out.println( "cached peers used:" + cached_peers.length ); last_failure_resp.setPeers( cached_peers ); } return( last_failure_resp ); } private byte[] updateOld( URL[] tracker_url, URL reqUrl ) throws Exception { // set context in case authentication dialog is required boolean errorLevel = true; try{ TorrentUtils.setTLSTorrentHash( torrent_hash ); // loop to possibly retry update on SSL certificate install for (int i=0;i<2;i++){ String failure_reason = null; String protocol = reqUrl.getProtocol(); try{ if (Logger.isEnabled()){ Logger.log(new LogEvent(torrent, LOGID, "Tracker Announcer is Requesting: " + reqUrl)); } ByteArrayOutputStream message = new ByteArrayOutputStream(); URL udpAnnounceURL = null; boolean udp_probe = false; // if we have multiple tracker URLs then do something sensible about if ( protocol.equalsIgnoreCase("udp") && udpAnnounceEnabled ){ udpAnnounceURL = reqUrl; }else if ( protocol.equalsIgnoreCase("http") && !az_tracker && announceCount % autoUDPprobeEvery == 0 && udpAnnounceEnabled ){ // if we don't know this tracker supports UDP then don't probe on // first announce as we don't want a large delay on torrent startup // also if we are stopping we don't want to initiate a probe as // we want the stop instruction to get to tracker if possible if ( ( stopped || announceCount == 0 || ( announceCount < trackerUrlLists.size() && announceFailCount == announceCount )) && !TRTrackerUtils.isUDPProbeOK(reqUrl)){ // skip probe }else{ udpAnnounceURL = new URL(reqUrl.toString().replaceFirst("^http", "udp")); udp_probe = true; } } if ( udpAnnounceURL != null ){ failure_reason = announceUDP( reqUrl, message, udp_probe ); if ((failure_reason != null || message.size() == 0) && udp_probe){ // automatic UDP probe failed, use HTTP again udpAnnounceURL = null; if ( autoUDPprobeEvery < 16 ){ autoUDPprobeEvery <<= 1; }else{ // unregister in case the tracker somehow changed its capabilities TRTrackerUtils.setUDPProbeResult(reqUrl, false); } if (Logger.isEnabled()){ Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_INFORMATION, "redirection of http announce [" + tracker_url[0] + "] to udp failed, will retry in " + autoUDPprobeEvery + " announces")); } }else if (failure_reason == null && udp_probe){ TRTrackerUtils.setUDPProbeResult(reqUrl, true); if (Logger.isEnabled()){ Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_INFORMATION, "redirection of http announce [" + tracker_url[0] + "] to udp successful")); } autoUDPprobeEvery = 1; } } announceCount++; if ( udpAnnounceURL == null){ failure_reason = announceHTTP( tracker_url, reqUrl, message ); } // if we've got some kind of response then return it if ( message.size() > 0 ){ return( message.toByteArray()); } if ( failure_reason == null ){ failure_reason = "No data received from tracker"; } }catch( SSLException e ){ // e.printStackTrace(); // try and install certificate regardless of error (as this changed in JDK1.5 // and broke this...) if ( i == 0 ){//&& e.getMessage().indexOf("No trusted certificate found") != -1 ){ if ( SESecurityManager.installServerCertificates( reqUrl ) != null ){ // certificate has been installed continue; // retry with new certificate } failure_reason = exceptionToString( e ); }else{ failure_reason = exceptionToString( e ); } }catch( IOException e ){ if(e instanceof UnknownHostException) errorLevel = false; if ( i == 0 && protocol.toLowerCase().startsWith( "http" )){ URL retry_url = UrlUtils.getIPV4Fallback( reqUrl ); if ( retry_url != null ){ reqUrl = retry_url; continue; } } failure_reason = exceptionToString( e ); }catch (Exception e){ // e.printStackTrace(); failure_reason = exceptionToString( e ); } if ( failure_reason != null && failure_reason.indexOf("401" ) != -1 ){ failure_reason = "Tracker authentication failed"; errorLevel = false; } if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, errorLevel ? LogEvent.LT_ERROR : LogEvent.LT_WARNING, "Exception while processing the Tracker Request for " + reqUrl + ": " + failure_reason)); throw( new Exception( failure_reason)); } // should never get here as second iteration of loop will always cause an exit throw( new Exception( "Internal Error: should never get here" )); }finally{ TorrentUtils.setTLSTorrentHash( null ); } } protected String announceHTTP( URL[] tracker_url, // overwritten if redirected URL original_reqUrl, ByteArrayOutputStream message ) throws IOException { TRTrackerUtils.checkForBlacklistedURLs( original_reqUrl ); URL reqUrl = TRTrackerUtils.adjustURLForHosting( original_reqUrl ); reqUrl = AddressUtils.adjustURL( reqUrl ); if ( reqUrl != original_reqUrl ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(torrent, LOGID, " HTTP: url adjusted to " + reqUrl )); } } String failure_reason = null; HttpURLConnection con; Properties http_properties = new Properties(); http_properties.put( ClientIDGenerator.PR_URL, reqUrl ); try{ ClientIDManagerImpl.getSingleton().generateHTTPProperties( http_properties ); }catch( ClientIDException e ){ throw( new IOException( e.getMessage())); } reqUrl = (URL)http_properties.get( ClientIDGenerator.PR_URL ); if ( reqUrl.getProtocol().equalsIgnoreCase("https")){ // see ConfigurationChecker for SSL client defaults HttpsURLConnection ssl_con = (HttpsURLConnection)reqUrl.openConnection(); // allow for certs that contain IP addresses rather than dns names ssl_con.setHostnameVerifier( new HostnameVerifier() { public boolean verify( String host, SSLSession session ) { return( true ); } }); con = ssl_con; }else{ con = (HttpURLConnection) reqUrl.openConnection(); } String user_agent = (String)http_properties.get( ClientIDGenerator.PR_USER_AGENT ); if ( user_agent != null ){ con.setRequestProperty("User-Agent", user_agent ); } con.setRequestProperty("Connection", "close" ); // some trackers support gzip encoding of replies con.addRequestProperty("Accept-Encoding","gzip"); try{ con.connect(); InputStream is = null; try{ is = con.getInputStream(); String resulting_url_str = con.getURL().toString(); if ( !reqUrl.toString().equals( resulting_url_str )){ // some kind of redirect has occurred. Unfortunately we can't get at the underlying // redirection reason (temp, perm etc) so we support the use of an explicit indicator // in the resulting url String marker = "permredirect=1"; int pos = resulting_url_str.indexOf( marker ); if ( pos != -1 ){ pos = pos-1; // include the '&' or '?' try{ URL redirect_url = new URL( resulting_url_str.substring(0,pos)); tracker_url[0] = redirect_url; }catch( Throwable e ){ Debug.printStackTrace(e); } } } String encoding = con.getHeaderField( "content-encoding"); boolean gzip = encoding != null && encoding.equalsIgnoreCase("gzip"); // System.out.println( "encoding = " + encoding ); if ( gzip ){ is = new GZIPInputStream( is ); } // there are some trackers out there that don't set content length correctly // so we can't reliably use it :( int content_length = -1; //con.getContentLength(); // System.out.println(length); byte[] data = new byte[1024]; int num_read = 0; // some trackers don't return content-length while ( content_length <= 0 || num_read < content_length ){ try{ int len = is.read(data); if ( len > 0 ){ message.write(data, 0, len); num_read += len; if ( num_read > 128*1024 ){ // someone's sending us junk, bail out message.reset(); throw( new Exception( "Tracker response invalid (too large)" )); } }else if ( len == 0 ){ Thread.sleep(20); }else{ break; } }catch (Exception e){ if (Logger.isEnabled()) { Logger.log(new LogEvent(torrent, LOGID, "Exception while Requesting Tracker", e)); Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_ERROR, "Message Received was : " + message)); } failure_reason = exceptionToString( e ); break; } } if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, "Tracker Announcer [" + lastUsedUrl + "] has received : " + message)); }catch (Exception e){ // e.printStackTrace(); failure_reason = exceptionToString( e ); }finally{ if (is != null) { try { is.close(); }catch (Exception e) { } is = null; } } }finally{ con.disconnect(); } return( failure_reason ); } protected String announceUDP( URL original_reqUrl, ByteArrayOutputStream message, boolean is_probe ) throws IOException { long timeout = is_probe?10000:PRUDPPacket.DEFAULT_UDP_TIMEOUT; URL reqUrl = TRTrackerUtils.adjustURLForHosting( original_reqUrl ); if ( reqUrl != original_reqUrl ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(torrent, LOGID, " UDP: url adjusted to " + reqUrl )); } } String failure_reason = null; PasswordAuthentication auth = null; try{ if ( (!is_probe) && UrlUtils.queryHasParameter(reqUrl.getQuery(), "auth", false)) { auth = SESecurityManager.getPasswordAuthentication( UDP_REALM, reqUrl ); } PRUDPPacketHandler handler = PRUDPPacketHandlerFactory.getHandler( UDPNetworkManager.getSingleton().getUDPNonDataListeningPortNumber()); InetSocketAddress destination = new InetSocketAddress(reqUrl.getHost(),reqUrl.getPort()==-1?80:reqUrl.getPort()); for (int retry_loop=0;retry_loop 0 ){ // gotta select an appropriate override based on network type StringTokenizer tok = new StringTokenizer( explicit_ips, ";" ); while( tok.hasMoreTokens()){ String this_address = tok.nextToken().trim(); if ( this_address.length() > 0 ){ String cat = AENetworkClassifier.categoriseAddress( this_address ); if ( cat == AENetworkClassifier.AT_PUBLIC ){ normal_explicit = this_address; } if ( tracker_network == cat ){ ip = this_address; break; } } } } if ( ip == null ){ // if we have a normal explicit override and this is enabled then use it if ( normal_network_ok && normal_explicit != null ){ ip = normal_explicit; }else{ if ( ip_override != null ){ ip = ip_override; } } } if ( ip != null ){ if ( tracker_network == AENetworkClassifier.AT_PUBLIC ){ try{ ip = PRHelpers.DNSToIPAddress( ip ); }catch( UnknownHostException e){ if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_ERROR, "IP Override host resolution of '" + ip + "' fails, using unresolved address")); } } request.append("&ip=").append(ip); } if ( COConfigurationManager.getBooleanParameter("Tracker Key Enable Client", true )){ request.append( "&key=").append(key_id); } String ext = announce_data_provider.getExtensions(); if ( ext != null ){ // sanitise it while ( ext.startsWith("&")){ ext = ext.substring( 1 ); } request.append( "&" ); request.append( ext ); } request.append( "&azver=" + TRTrackerAnnouncer.AZ_TRACKER_VERSION_CURRENT ); if ( az_tracker && !stopped ){ int up = announce_data_provider.getUploadSpeedKBSec( evt.equals( "started" )); if ( up > 0 ){ request.append( "&azup=" + up ); } String as = NetworkAdmin.getSingleton().getCurrentASN().getAS(); if ( as.length() > 0 ){ request.append( "&azas=" + URLEncoder.encode( as, "UTF8" )); } DHTNetworkPosition best_position = DHTNetworkPositionManager.getBestLocalPosition(); if ( best_position != null ){ try{ byte[] bytes = DHTNetworkPositionManager.serialisePosition( best_position ); request.append( "&aznp=" + Base32.encode( bytes )); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } return new URL( request.toString()); } protected int calculateNumWant() { if ( !announce_data_provider.isPeerSourceEnabled( PEPeerSource.PS_BT_TRACKER )){ return( 0 ); } int MAX_PEERS = 100; int maxAllowed = announce_data_provider.getMaxNewConnectionsAllowed(); if ( maxAllowed < 0 || maxAllowed > MAX_PEERS ) { maxAllowed = MAX_PEERS; } return maxAllowed; } public byte[] getPeerId() { return( data_peer_id ); } public void setAnnounceDataProvider( TRTrackerAnnouncerDataProvider _provider) { try{ this_mon.enter(); announce_data_provider = _provider; }finally{ this_mon.exit(); } } public TOTorrent getTorrent() { return( torrent ); } public URL getTrackerURL() { return( lastUsedUrl ); } public void setTrackerURL( URL new_url ) { try{ new_url = new URL( new_url.toString().replaceAll(" ", "")); List list = new ArrayList(1); list.add( new_url ); trackerUrlLists.clear(); trackerUrlLists.add( list ); informURLChange( lastUsedUrl, new_url, true ); }catch( Throwable e ){ Debug.printStackTrace(e); } } public void setTrackerURLs( TOTorrentAnnounceURLSet[] _set ) { announce_urls = _set; } public void resetTrackerUrl( boolean shuffle ) { String old_list = trackerURLListToString(); constructTrackerUrlLists(shuffle); if ( trackerUrlLists.size() == 0 ){ return; } if ( !old_list.equals(trackerURLListToString())){ URL first_url = (URL)((List)trackerUrlLists.get(0)).get(0); informURLChange( lastUsedUrl, first_url, true ); } } public void refreshListeners() { informURLRefresh(); } public void setIPOverride( String override ) { ip_override = override; } public void clearIPOverride() { ip_override = null; } private void constructTrackerUrlLists( boolean shuffle ) { try{ trackerUrlLists = new ArrayList(1); //This entry is present on multi-tracker torrents if ( announce_urls.length == 0 ){ //If not present, we use the default specification URL url = torrent.getAnnounceURL(); //We then contruct a list of one element, containing this url, and put this list //into the list of lists of urls. List list = new ArrayList(); list.add(url); trackerUrlLists.add(list); }else{ //Ok we have a multi-tracker torrent for(int i = 0 ; i < announce_urls.length ; i++){ //Each list contains a list of urls URL[] urls = announce_urls[i].getAnnounceURLs(); List random_urls = new ArrayList(); for(int j = 0 ; j < urls.length; j++){ //System.out.println(urls.get(j).getClass()); URL url = urls[j]; //Shuffle int pos = shuffle?(int)(Math.random() * (random_urls.size()+1)):j; random_urls.add(pos,url); } //Add this list to the list trackerUrlLists.add(random_urls); } } }catch(Exception e){ Debug.printStackTrace( e ); } } protected String trackerURLListToString() { String trackerUrlListString = "["; for (int i=0;i time_to_wait) { if (Logger.isEnabled()) { Logger.log(new LogEvent( torrent, LOGID, LogEvent.LT_INFORMATION, "Tracker being silly and " + "returning a 'min interval' (" + min_interval + ") greater than recommended announce 'interval'" + " (" + time_to_wait + ")")); } min_interval = 0; } } else { // tracker owners complain we announce too much but then never // implement "min interval". So take it into our own hands // and enforce a min_interval of interval when there is no // "min interval" min_interval = time_to_wait > 30 ? time_to_wait - 10 : time_to_wait; } if(userMinInterval != 0) { time_to_wait = Math.max(userMinInterval, time_to_wait); min_interval = Math.max(min_interval, userMinInterval); if (Logger.isEnabled()) { Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_INFORMATION, "Overriding with user settings: 'interval' = " + time_to_wait + "; 'min interval' = " + min_interval)); } } // roll back 10 seconds to make sure we announce before the tracker // times us out. This is done after min_interval in order not to // mess up the "ignore useless values" if (time_to_wait > 30) time_to_wait -= 10; } catch (Exception e) { byte[] failure_reason_bytes = (byte[]) metaData.get("failure reason"); if ( failure_reason_bytes == null ){ if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_WARNING, "Problems with Tracker, will retry in " + getErrorRetryInterval() + "ms")); return( new TRTrackerAnnouncerResponseImpl( url, torrent_hash, TRTrackerAnnouncerResponse.ST_OFFLINE, getErrorRetryInterval(), "Unknown cause" )); } // explicit failure from the tracker failure_reason = new String( failure_reason_bytes, Constants.DEFAULT_ENCODING); return( new TRTrackerAnnouncerResponseImpl( url, torrent_hash, TRTrackerAnnouncerResponse.ST_REPORTED_ERROR, getErrorRetryInterval(), failure_reason )); } //System.out.println("Response from Announce: " + new String(data)); Long incomplete_l = (Long)metaData.get("incomplete"); Long complete_l = (Long)metaData.get("complete"); if ( incomplete_l != null || complete_l != null ){ if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, "ANNOUNCE SCRAPE1: seeds=" + complete_l + " peers=" + incomplete_l)); } //TrackerID extension, used by phpbt trackers. //We reply with '&trackerid=1234' when we receive //'10:tracker id4:1234e' on announce reply. //NOTE: we receive as 'tracker id' but reply as 'trackerid' byte[] trackerid = (byte[])metaData.get( "tracker id" ); if( trackerid != null ) { tracker_id = new String( trackerid ); } byte[] crypto_flags = (byte[])metaData.get( "crypto_flags" ); //build the list of peers List valid_meta_peers = new ArrayList(); Object meta_peers_peek = metaData.get( "peers" ); Long az_compact_l = (Long)metaData.get( "azcompact" ); long az_compact = az_compact_l==null?0:az_compact_l.longValue(); boolean this_is_az_tracker = az_compact == 2; if ( az_tracker != this_is_az_tracker || lastUsedUrl != lastAZTrackerCheckedURL ){ lastAZTrackerCheckedURL = lastUsedUrl; az_tracker = this_is_az_tracker; TRTrackerUtils.setAZTracker( url, az_tracker ); } if ( az_compact == 2 ){ // latest return to dictionary based data List meta_peers = (List)meta_peers_peek; int peers_length = meta_peers.size(); if (Logger.isEnabled()) { Logger.log(new LogEvent(torrent, LOGID, "ANNOUNCE CompactPeers2: num=" + peers_length)); } if ( peers_length > 1 ){ // calculate average rtt to use for those with no rtt long total_rtt = 0; int rtt_count = 0; for ( int i = 0; i < peers_length; i++ ){ Map peer = (Map) meta_peers.get(i); Long l_rtt = (Long)peer.get( "r" ); if ( l_rtt != null ){ long rtt = l_rtt.longValue(); if ( rtt <= 0 ){ // invalid, remove peer.remove( "r" ); }else{ total_rtt += rtt; } rtt_count++; } } final int average_rtt = (int)( rtt_count==0?0:(total_rtt/rtt_count)); // sort into smallest rtt order with biased at front Collections.sort( meta_peers, new Comparator() { public int compare( Object o1, Object o2 ) { Map map1 = (Map)o1; Map map2 = (Map)o2; Long l_rtt1 = (Long)map1.get( "r" ); Long l_rtt2 = (Long)map2.get( "r" ); boolean biased_1 = map1.containsKey( "b" ); boolean biased_2 = map2.containsKey( "b" ); if ( biased_1 == biased_2 ){ int rtt1 = l_rtt1==null?average_rtt:l_rtt1.intValue(); int rtt2 = l_rtt2==null?average_rtt:l_rtt2.intValue(); return( rtt1 - rtt2 ); }else if ( biased_1 ){ return( -1 ); }else{ return( +1 ); } } }); // interleave non-biased peers with good rtt int biased_pos = peers_length; int non_biased_pos = peers_length; for ( int i = 0; i < peers_length; i++ ){ Map peer = (Map) meta_peers.get(i); if ( peer.containsKey( "b" )){ if ( i == 0 ){ biased_pos = i; } }else{ non_biased_pos = i; break; } } List new_peers = new ArrayList(peers_length); int non_biased_start = non_biased_pos; boolean last_biased = true; while( biased_pos < non_biased_start || non_biased_pos < peers_length ){ if ( biased_pos < non_biased_start ){ if ( non_biased_pos < peers_length ){ Map biased = (Map) meta_peers.get(biased_pos); Map non_biased = (Map) meta_peers.get(non_biased_pos); boolean use_biased; if ( !last_biased ){ use_biased = true; }else{ Long l_rtt_biased = (Long)biased.get( "r" ); Long l_rtt_non_biased = (Long)non_biased.get( "r" ); int biased_rtt = l_rtt_biased==null?average_rtt:l_rtt_biased.intValue(); int non_biased_rtt = l_rtt_non_biased==null?average_rtt:l_rtt_non_biased.intValue(); use_biased = non_biased_rtt >= biased_rtt; } if ( use_biased ){ new_peers.add( biased ); biased_pos++; }else{ new_peers.add( non_biased ); non_biased_pos++; } last_biased = use_biased; }else{ new_peers.add( meta_peers.get( biased_pos++ )); } }else{ new_peers.add( meta_peers.get( non_biased_pos++ )); } } meta_peers = new_peers; } for ( int i = 0; i < peers_length; i++ ){ Map peer = (Map) meta_peers.get(i); try{ byte[] ip_bytes = (byte[])peer.get("i"); String ip; if ( ip_bytes.length == 4 ){ int ip1 = 0xff & ip_bytes[0]; int ip2 = 0xff & ip_bytes[1]; int ip3 = 0xff & ip_bytes[2]; int ip4 = 0xff & ip_bytes[3]; ip = ip1 + "." + ip2 + "." + ip3 + "." + ip4; }else{ StringBuffer sb = new StringBuffer(39); for ( int j=0; j<16; j+=2 ){ sb.append( Integer.toHexString(((ip_bytes[j]<<8) & 0xff00) | (ip_bytes[j+1]&0x00ff))); if (j < 14 ){ sb.append( ":" ); } } ip = sb.toString(); } byte[] tcp_bytes = (byte[])peer.get("t"); int tcp_port = ((tcp_bytes[0]&0xff) << 8 ) + (tcp_bytes[1]&0xff ); byte[] peer_peer_id = TRTrackerAnnouncerImpl.getAnonymousPeerId( ip, tcp_port ); int udp_port = 0; byte[] udp_bytes = (byte[])peer.get("u"); if ( udp_bytes != null ){ if ( udp_bytes.length == 0 ){ udp_port = tcp_port; }else{ udp_port = ((udp_bytes[0]&0xff) << 8 ) + (udp_bytes[1]&0xff ); } } int http_port = 0; byte[] http_bytes = (byte[])peer.get("h"); if ( http_bytes != null ){ http_port = ((http_bytes[0]&0xff) << 8 ) + (http_bytes[1]&0xff ); } short protocol = DownloadAnnounceResultPeer.PROTOCOL_NORMAL; byte[] protocol_bytes = (byte[])peer.get("c"); if ( protocol_bytes != null ){ protocol = (protocol_bytes[0]&0x01)==0?DownloadAnnounceResultPeer.PROTOCOL_NORMAL:DownloadAnnounceResultPeer.PROTOCOL_CRYPT; } Long l_azver = (Long)peer.get("v" ); byte az_ver = l_azver==null?TRTrackerAnnouncer.AZ_TRACKER_VERSION_1:l_azver.byteValue(); Long l_up_speed = (Long)peer.get( "s" ); boolean biased = peer.containsKey("b"); if ( biased ){ PeerClassifier.setAzureusIP( ip ); } TRTrackerAnnouncerResponsePeerImpl new_peer = new TRTrackerAnnouncerResponsePeerImpl( PEPeerSource.PS_BT_TRACKER, peer_peer_id, ip, tcp_port, udp_port, http_port, protocol, az_ver, l_up_speed==null?0:l_up_speed.shortValue()); if (Logger.isEnabled()){ String extra = ""; Long l_rtt = (Long)peer.get( "r" ); if ( l_rtt != null ){ extra = ",rtt=" + l_rtt; } if ( biased ){ extra += ",biased"; } Logger.log(new LogEvent(torrent, LOGID, "AZ2-COMPACT PEER: " + new_peer.getString() + extra)); } valid_meta_peers.add( new_peer ); }catch( Throwable e ){ if (Logger.isEnabled()) Logger.log( new LogEvent( torrent, LOGID, LogEvent.LT_ERROR, "Invalid az2 peer received: " + peer )); } } }else if ( meta_peers_peek instanceof List ){ // old style non-compact List meta_peers = (List)meta_peers_peek; //for every peer int peers_length = meta_peers.size(); if (Logger.isEnabled()) { Logger.log(new LogEvent(torrent, LOGID, "ANNOUNCE old style non-compact: num=" + peers_length)); } if ( crypto_flags != null && peers_length != crypto_flags.length ){ crypto_flags = null; if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_ERROR, "Invalid crypto_flags returned: length mismatch" )); } for (int i = 0; i < peers_length; i++) { Map peer = (Map) meta_peers.get(i); Object s_peerid = peer.get("peer id"); Object s_ip = peer.get("ip"); Object s_port = peer.get("port"); // Assert that all ip and port are available if ( s_ip != null && s_port != null ){ //get the peer ip address String ip = new String((byte[]) s_ip, Constants.DEFAULT_ENCODING); //get the peer port number int peer_port = ((Long) s_port).intValue(); // try to repair invalid peer ports; worst that can happen is we // still can't make outgoing connections that we already can't make if (peer_port >65535) peer_port -=65536; if (peer_port <0) peer_port +=65536; if (peer_port < 0 || peer_port > 65535) { if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_ERROR, "Invalid peer port given: " + ip + ": " + peer_port)); continue; } byte[] peer_peer_id; // extension - if peer id is missing then the tracker isn't sending // peer ids to save on bandwidth. However, we need something "unique" to // work on internally so make an ID up from the ip and port if ( s_peerid == null ){ // Debug.out(ip + ": tracker did not give peerID in reply"); peer_peer_id = TRTrackerAnnouncerImpl.getAnonymousPeerId( ip, peer_port ); // System.out.println("generated peer id" + new String(peerId) + "/" + ByteFormatter.nicePrint( peerId, true )); }else{ peer_peer_id = (byte[])s_peerid ; } short protocol; if ( crypto_flags == null ){ protocol = DownloadAnnounceResultPeer.PROTOCOL_NORMAL; }else{ protocol = crypto_flags[i]==0?DownloadAnnounceResultPeer.PROTOCOL_NORMAL:DownloadAnnounceResultPeer.PROTOCOL_CRYPT; } int udp_port = 0; int http_port = 0; TRTrackerAnnouncerResponsePeerImpl new_peer = new TRTrackerAnnouncerResponsePeerImpl( PEPeerSource.PS_BT_TRACKER, peer_peer_id, ip, peer_port, udp_port, http_port, protocol, TRTrackerAnnouncer.AZ_TRACKER_VERSION_1, (short)0 ); if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, "NON-COMPACT PEER: " + new_peer.getString())); valid_meta_peers.add( new_peer ); } } }else if ( meta_peers_peek instanceof byte[] ){ // byte[] for compact returns byte[] meta_peers = (byte[])meta_peers_peek; int entry_size = az_compact==1?9:6; if ( crypto_flags != null && meta_peers.length/entry_size != crypto_flags.length ){ crypto_flags = null; if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_ERROR, "Invalid crypto_flags returned: length mismatch" )); } int peer_number = 0; if (Logger.isEnabled()) { Logger.log(new LogEvent(torrent, LOGID, "ANNOUNCE CompactPeers: num=" + (meta_peers.length/entry_size))); } for (int i=0;i 65535) { if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_ERROR, "Invalid compact peer port given: " + ip + ": " + tcp_port)); continue; } byte[] peer_peer_id = TRTrackerAnnouncerImpl.getAnonymousPeerId( ip, tcp_port ); short protocol; int udp_port; if ( az_compact == 1 ){ int upo1 = 0xFF & meta_peers[i+6]; int upo2 = 0xFF & meta_peers[i+7]; udp_port = upo1*256+upo2; byte flags = meta_peers[i+8]; protocol = (flags&0x01)==0?DownloadAnnounceResultPeer.PROTOCOL_NORMAL:DownloadAnnounceResultPeer.PROTOCOL_CRYPT; }else{ if ( crypto_flags == null ){ protocol = DownloadAnnounceResultPeer.PROTOCOL_NORMAL; }else{ protocol = crypto_flags[peer_number-1]==0?DownloadAnnounceResultPeer.PROTOCOL_NORMAL:DownloadAnnounceResultPeer.PROTOCOL_CRYPT; } udp_port = 0; } int http_port = 0; TRTrackerAnnouncerResponsePeerImpl peer = new TRTrackerAnnouncerResponsePeerImpl( PEPeerSource.PS_BT_TRACKER, peer_peer_id, ip, tcp_port, udp_port, http_port, protocol, TRTrackerAnnouncer.AZ_TRACKER_VERSION_1, (short)0 ); if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, "COMPACT PEER: " + peer.getString())); valid_meta_peers.add( peer ); } }else if ( meta_peers_peek instanceof Map ){ // some trackers incorrectly return an empty Map when no peers available if (((Map)meta_peers_peek).size() != 0 ){ throw( new IOException( "peers missing from response" )); } }else if (!metaData.containsKey("peers6")){ // we got nothing useful under peers and no peers6 either throw( new IOException( "peers missing from response" )); } final byte[] v6peers = (byte[])metaData.get("peers6"); if ( v6peers != null ){ // 16 bytes for v6 + 2 bytes for port final int entry_size = 18; final byte[] rawAddr = new byte[16]; for (int i=0; i 65535){ if (Logger.isEnabled()){ Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_ERROR, "Invalid compactv6 peer port given: " + ip + ": " + tcp_port)); } continue; } byte[] peer_peer_id = TRTrackerAnnouncerImpl.getAnonymousPeerId( ip, tcp_port ); short protocol = DownloadAnnounceResultPeer.PROTOCOL_NORMAL; TRTrackerAnnouncerResponsePeerImpl peer = new TRTrackerAnnouncerResponsePeerImpl(PEPeerSource.PS_BT_TRACKER, peer_peer_id, ip, tcp_port, 0, 0, protocol, TRTrackerAnnouncer.AZ_TRACKER_VERSION_1, (short) 0); if (Logger.isEnabled()){ Logger.log(new LogEvent(torrent, LOGID, "COMPACTv6 PEER: " + peer.getString())); } valid_meta_peers.add(peer); } } TRTrackerAnnouncerResponsePeerImpl[] peers=new TRTrackerAnnouncerResponsePeerImpl[valid_meta_peers.size()]; valid_meta_peers.toArray(peers); helper.addToTrackerCache( peers); TRTrackerAnnouncerResponseImpl resp = new TRTrackerAnnouncerResponseImpl( url, torrent_hash, TRTrackerAnnouncerResponse.ST_ONLINE, time_to_wait, peers ); //reset failure retry interval on successful connect failure_added_time = 0; Map extensions = (Map)metaData.get( "extensions" ); resp.setExtensions(extensions); if ( extensions != null ){ if ( complete_l == null) { complete_l = (Long)extensions.get("complete"); } if ( incomplete_l == null) { incomplete_l = (Long)extensions.get("incomplete"); } if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, "ANNOUNCE SCRAPE2: seeds=" + complete_l + " peers=" + incomplete_l)); Object override = extensions.get( "min interval override" ); if ( override != null && override instanceof Long ){ // this is to allow specific torrents to be refreshed more quickly // if the tracker permits. Parg min_interval_override = ((Long)override).longValue(); } } if (complete_l != null || incomplete_l != null) { int complete = complete_l == null ? 0 : complete_l.intValue(); int incomplete = incomplete_l == null ? 0 : incomplete_l.intValue(); if (complete < 0 || incomplete < 0) { resp.setFailurReason(MessageText.getString( "Tracker.announce.ignorePeerSeed", new String[] { (complete < 0 ? MessageText.getString("MyTorrentsView.seeds") + " == " + complete + ". " : "") + (incomplete < 0 ? MessageText.getString("MyTorrentsView.peers") + " == " + incomplete + ". " : "") })); } else { resp.setScrapeResult( complete, incomplete ); TRTrackerScraper scraper = TRTrackerScraperFactory.getSingleton(); if (scraper != null) { TRTrackerScraperResponse scrapeResponse = scraper.scrape( torrent, getTrackerURL()); if (scrapeResponse != null) { long lNextScrapeTime = scrapeResponse.getNextScrapeStartTime(); long lNewNextScrapeTime = TRTrackerScraperResponseImpl.calcScrapeIntervalSecs( 0, complete) * 1000; // make it look as if the scrape has just run. Important // as seeding rules may make calculations on when the // scrape value were set scrapeResponse.setScrapeStartTime(SystemTime.getCurrentTime()); if (lNextScrapeTime < lNewNextScrapeTime) scrapeResponse.setNextScrapeStartTime(lNewNextScrapeTime); scrapeResponse.setSeedsPeers(complete, incomplete); } } } } return (resp); }catch( IOException e ){ // decode could fail if the tracker's returned, say, an HTTP response // indicating server overload String trace_data; if ( data.length <= 150 ){ trace_data = new String(data); }else{ trace_data = new String(data,0,150) + "..."; } if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_ERROR, "TRTrackerAnnouncer::invalid reply: " + trace_data)); failure_reason = "invalid reply: " + trace_data; } }catch( Throwable e ){ Debug.printStackTrace( e ); failure_reason = "error: " + e.getMessage(); } } return( new TRTrackerAnnouncerResponseImpl( url, torrent_hash, TRTrackerAnnouncerResponse.ST_OFFLINE, getErrorRetryInterval(), failure_reason )); } protected void informURLChange( URL old_url, URL new_url, boolean explicit ) { helper.informURLChange( old_url, new_url, explicit ); } protected void informURLRefresh() { helper.informURLRefresh(); } public TRTrackerAnnouncerResponse getLastResponse() { if( last_response == null ){ return new TRTrackerAnnouncerResponseImpl( null, torrent_hash, TRTrackerAnnouncerResponse.ST_OFFLINE, TRTrackerAnnouncer.REFRESH_MINIMUM_SECS, "Initialising" ); } return( last_response ); } public boolean isManual() { return( manual_control ); } public void destroy() { destroyed = true; try{ this_mon.enter(); if ( current_timer_event != null ){ // cancel any events that are a way off being triggered. note that // we don't want to cancel all events as the "stopped" event that // is scheduled on stop of a download may still be lurking if ( current_timer_event.getWhen() - SystemTime.getCurrentTime() > 10*1000 ){ if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, "Canceling announce trigger")); current_timer_event.cancel(); } } }finally{ this_mon.exit(); } } /** * Retrieve the retry interval to use on announce errors. */ protected int getErrorRetryInterval() { long currentTime = SystemTime.getCurrentTime() /1000; long diff = currentTime - failure_time_last_updated; //use previously calculated interval if it's not time to update if( diff < failure_added_time && !(diff < 0) ) { return failure_added_time; } //update previous change time failure_time_last_updated = currentTime; if( failure_added_time == 0 ) { //start failure_added_time = 10; } else if( failure_added_time < 30 ) { //three 10-sec retries failure_added_time += 10; } else if( failure_added_time < 60 ) { //two 15-sec retries failure_added_time += 15; } else if( failure_added_time < 120 ) { //two 30-sec retries failure_added_time += 30; } else if( failure_added_time < 600 ) { //eight 60-sec retries failure_added_time += 60; } else { //2-3min random retry failure_added_time += 120 + new Random().nextInt( 60 ); } boolean is_seed = (announce_data_provider == null) ? false : announce_data_provider.getRemaining() == 0; if( is_seed ) failure_added_time = failure_added_time * 2; //no need to retry as often //make sure we're not waiting longer than 30min if( !is_seed && failure_added_time > 1800) { failure_added_time = 1800; } else if ( is_seed && failure_added_time > 3600) { //or 60min if seed failure_added_time = 3600; } return failure_added_time; } public void setAnnounceResult( DownloadAnnounceResult result ) { // this is how the results from "external" announces get into the system // really should refactor so that "normal" and "external" mechanisms are // just instances of the same generic approach TRTrackerAnnouncerResponseImpl response; String status; if ( result.getResponseType() == DownloadAnnounceResult.RT_ERROR ){ status = MessageText.getString("PeerManager.status.error"); String reason = result.getError(); if ( reason != null ){ status += " (" + reason + ")"; } response = new TRTrackerAnnouncerResponseImpl( result.getURL(), torrent_hash, TRTrackerAnnouncerResponse.ST_OFFLINE, result.getTimeToWait(), reason ); }else{ DownloadAnnounceResultPeer[] ext_peers = result.getPeers(); List l_peers = new ArrayList(ext_peers.length); boolean ps_enabled = announce_data_provider != null && announce_data_provider.isPeerSourceEnabled( PEPeerSource.PS_BT_TRACKER ); for (int i=0;i 0 || ext_peers.length == 0 ){ status = MessageText.getString("PeerManager.status.ok"); }else{ status = MessageText.getString("PeerManager.status.ps_disabled"); peers = new TRTrackerAnnouncerResponsePeerImpl[0]; } response = new TRTrackerAnnouncerResponseImpl( result.getURL(), torrent_hash, TRTrackerAnnouncerResponse.ST_ONLINE, result.getTimeToWait(), peers ); } // only make the user aware of the status if the underlying announce is // failing if ( last_response == null || last_response.getStatus() != TRTrackerAnnouncerResponse.ST_ONLINE ){ tracker_status_str = status + " (" + result.getURL() + ")"; } helper.informResponse( response ); } public void addListener( TRTrackerAnnouncerListener l ) { helper.addListener( l ); } public void removeListener( TRTrackerAnnouncerListener l ) { helper.removeListener( l ); } public void setTrackerResponseCache( Map map ) { helper.setTrackerResponseCache( map ); } public void removeFromTrackerResponseCache( String ip, int tcpPort) { helper.removeFromTrackerResponseCache( ip, tcpPort ); } public Map getTrackerResponseCache() { return( helper.getTrackerResponseCache()); } public void generateEvidence( IndentWriter writer ) { writer.println( "BT announce:" ); try{ writer.indent(); writer.println( "state: " + tracker_state + ", in_progress=" + update_in_progress ); writer.println( "current: " + (lastUsedUrl==null?"null":lastUsedUrl.toString())); writer.println( "last: " + (last_response==null?"null":last_response.getString())); writer.println( "last_update_secs: " + last_update_time_secs ); writer.println( "secs_to_wait: " + current_time_to_wait_secs + (manual_control?" - manual":"")); writer.println( "min_interval: " + min_interval ); writer.println( "min_interval_override: " + min_interval_override ); writer.println( "rd: last_override=" + rd_last_override + ",percentage=" + rd_override_percentage ); writer.println( "event: " + ( current_timer_event==null?"null":current_timer_event.getString())); writer.println( "stopped: " + stopped + ", for_q=" + stopped_for_queue ); writer.println( "complete: " + completed + ", reported=" + complete_reported ); }finally{ writer.exdent(); } } }azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerChecker.java0000644000175000017500000003513611307334262027203 0ustar adrianadrian/* * Created on 22 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.client.impl.bt; import java.net.URL; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerScraperResponseImpl; import org.gudy.azureus2.core3.util.*; /** * @author Olivier * */ public class TrackerChecker implements AEDiagnosticsEvidenceGenerator, SystemTime.ChangeListener, TimerEventPerformer { private final static LogIDs LOGID = LogIDs.TRACKER; /** List of Trackers. * key = Tracker URL string * value = TrackerStatus object */ private HashMap trackers; private AEMonitor trackers_mon = new AEMonitor( "TrackerChecker:trackers" ); /** TRTrackerScraperImpl object associated with this object. */ private TRTrackerBTScraperImpl scraper; private long nextScrapeCheckOn; /** Initialize TrackerChecker. * * @note Since there is only one TRTrackerScraperImpl, there will only be one * TrackerChecker instance. * */ protected TrackerChecker(TRTrackerBTScraperImpl _scraper) { scraper = _scraper; trackers = new HashMap(); if ( !COConfigurationManager.getBooleanParameter("Tracker Client Scrape Total Disable")){ runScrapes(); } AEDiagnostics.addEvidenceGenerator( this ); SystemTime.registerClockChangeListener( this ); } /** Retrieves the last cached Scraper Response based on a TRTrackerClient's * current URL (announce-list entry or announce) and its torrent's hash. * * @return The cached scrape response. Can be null. */ protected TRTrackerScraperResponseImpl getHashData( TRTrackerAnnouncer tracker_client) { try { return getHashData(tracker_client.getTrackerURL(), tracker_client.getTorrent().getHashWrapper()); } catch (TOTorrentException e) { Debug.printStackTrace( e ); return null; } } /** Retrieves the last cached Scraper Response based on a TOTorrent's * Announce URL (not announce-list) and hash. * * @return The cached scrape response. Can be null. */ protected TRTrackerScraperResponseImpl getHashData( TOTorrent torrent, URL target_url ) { try { return getHashData(target_url==null?torrent.getAnnounceURL():target_url, torrent.getHashWrapper()); } catch(TOTorrentException e) { Debug.printStackTrace( e ); return null; } } /** Retrieves the last cached Scraper Response for the supplied tracker URL * and hash. If no cache has exists for the hash, one is created. * * @return The cached scrape response. Can be null. */ protected TRTrackerScraperResponseImpl getHashData( URL trackerUrl, final HashWrapper hash) { // can be null when first called and url not yet set up... if ( trackerUrl == null ){ return( null ); } TRTrackerScraperResponseImpl data = null; // DON'T USE URL as a key in the trackers map, use the string version. If you // use a URL then the "containsKey" method does a URL.equals test. This does not // simply check on str equivalence, it tries to resolve the host name. this can // result in significant hangs (several seconds....) String url_str = trackerUrl.toString(); TrackerStatus ts = null; try{ trackers_mon.enter(); ts = (TrackerStatus) trackers.get(url_str); if ( ts != null ){ data = ts.getHashData( hash ); }else{ //System.out.println( "adding hash for " + trackerUrl + " : " + ByteFormatter.nicePrint(hashBytes, true)); ts = new TrackerStatus(this, scraper.getScraper(),trackerUrl); trackers.put(url_str, ts); if( !ts.isTrackerScrapeUrlValid() ) { if (Logger.isEnabled()){ Logger.log(new LogEvent(TorrentUtils.getDownloadManager(hash), LOGID, LogEvent.LT_ERROR, "Can't scrape using url '" + trackerUrl + "' as it doesn't end in " + "'/announce', skipping.")); } } } }finally{ trackers_mon.exit(); } // do outside monitor to avoid deadlock situation as ts.addHash invokes // listeners.... if ( data == null ){ data = ts.addHash(hash); } return data; } /** Removes the scrape task and data associated with the TOTorrent's * Announce URL, announce-list data and hash. */ protected void removeHash(TOTorrent torrent) { try{ removeHash(torrent.getAnnounceURL().toString(), torrent.getHashWrapper()); TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets(); for (int i=0;i= 0 && trackerUrl.length() >= position+9 && trackerUrl.substring(position+1,position+9).equals("announce")) { this.scrapeURL = trackerUrl.substring(0,position+1) + "scrape" + trackerUrl.substring(position+9); // System.out.println( "url = " + trackerUrl + ", scrape =" + scrapeURL ); }else if ( trackerUrl.toLowerCase().startsWith("udp:")){ // UDP scrapes aren't based on URL rewriting, just carry on scrapeURL = trackerUrl; }else if ( position >= 0 && trackerUrl.lastIndexOf('.') < position ){ // some trackers support /scrape appended but don't have an /announce // don't do this though it the URL ends with .php (or infact .) scrapeURL = trackerUrl + (trackerUrl.endsWith("/")?"":"/") + "scrape"; } else { if (!logged_invalid_urls.contains(trackerUrl)) { logged_invalid_urls.add(trackerUrl); // Error logging is done by the caller, since it has the hash/torrent info } } } catch (Throwable e) { Debug.printStackTrace( e ); } } protected boolean isTrackerScrapeUrlValid() { return scrapeURL != null; } protected TRTrackerScraperResponseImpl getHashData(HashWrapper hash) { try{ hashes_mon.enter(); return (TRTrackerScraperResponseImpl) hashes.get(hash); }finally{ hashes_mon.exit(); } } protected void updateSingleHash( HashWrapper hash, boolean force) { updateSingleHash(hash, force, true); } protected void updateSingleHash( HashWrapper hash, boolean force, boolean async ) { //LGLogger.log( "updateSingleHash():: force=" + force + ", async=" +async+ ", url=" +scrapeURL+ ", hash=" +ByteFormatter.nicePrint(hash, true) ); if ( scrapeURL == null ){ if (Logger.isEnabled()) { Logger.log(new LogEvent(TorrentUtils.getDownloadManager(hash), LOGID, "TrackerStatus: scrape cancelled.. url null")); } return; } try { ArrayList responsesToUpdate = new ArrayList(); TRTrackerScraperResponseImpl response; try{ hashes_mon.enter(); response = (TRTrackerScraperResponseImpl)hashes.get( hash ); }finally{ hashes_mon.exit(); } if ( response == null ){ response = addHash(hash); } long lMainNextScrapeStartTime = response.getNextScrapeStartTime(); if( !force && lMainNextScrapeStartTime > SystemTime.getCurrentTime() ) { if (Logger.isEnabled()) { Logger.log(new LogEvent(TorrentUtils.getDownloadManager(hash), LOGID, "TrackerStatus: scrape cancelled.. not forced and still " + (lMainNextScrapeStartTime - SystemTime.getCurrentTime()) + "ms")); } return; } // Set status id to SCRAPING, but leave status string until we actually // do the scrape response.setStatus(TRTrackerScraperResponse.ST_SCRAPING, MessageText.getString(SS + "scraping.queued")); if (Logger.isEnabled()) { Logger.log(new LogEvent(TorrentUtils.getDownloadManager(hash), LOGID, "TrackerStatus: setting to scraping")); } responsesToUpdate.add(response); // Go through hashes and pick out other scrapes that are "close to" wanting a new scrape. if (!bSingleHashScrapes){ try{ hashes_mon.enter(); Iterator iterHashes = hashes.values().iterator(); // if we hit trackers with excessive scrapes they respond in varying fashions - from no reply // to returning 414 to whatever. Rather than hit trackers with large payloads that they then // reject we limit to MULTI_SCRAPE_LIMIT in one go while( iterHashes.hasNext() && responsesToUpdate.size() < GROUP_SCRAPES_LIMIT ){ TRTrackerScraperResponseImpl r = (TRTrackerScraperResponseImpl)iterHashes.next(); if ( !r.getHash().equals( hash )) { long lTimeDiff = Math.abs(lMainNextScrapeStartTime - r.getNextScrapeStartTime()); if (lTimeDiff <= GROUP_SCRAPES_MS && r.getStatus() != TRTrackerScraperResponse.ST_SCRAPING) { r.setStatus(TRTrackerScraperResponse.ST_SCRAPING, MessageText.getString(SS + "scraping.queued")); if (Logger.isEnabled()) { Logger.log(new LogEvent(TorrentUtils.getDownloadManager(r.getHash()), LOGID, "TrackerStatus: setting to scraping via group scrape")); } responsesToUpdate.add(r); } } } }finally{ hashes_mon.exit(); } } runScrapes(responsesToUpdate, force, async); }catch( Throwable t ) { Debug.out( "updateSingleHash() exception", t ); } } protected void runScrapes( final ArrayList responses, final boolean force, boolean async) { numActiveScrapes++; if ( async ){ thread_pool.run( new AERunnable() { public void runSupport() { runScrapesSupport( responses, force ); } }); if (Logger.isEnabled()) { Logger.log(new LogEvent(LOGID, "TrackerStatus: queuing '" + scrapeURL + "', for " + responses.size() + " of " + hashes.size() + " hashes" + ", single_hash_scrapes: " + (bSingleHashScrapes ? "Y" : "N") + ", queue size=" + thread_pool.getQueueSize())); } }else{ runScrapesSupport( responses, force ); } } protected void runScrapesSupport( ArrayList responses, boolean force ) { try { if (Logger.isEnabled()) { Logger.log(new LogEvent(LOGID, "TrackerStatus: scraping '" + scrapeURL + "', for " + responses.size() + " of " + hashes.size() + " hashes" + ", single_hash_scrapes: " + (bSingleHashScrapes ? "Y" : "N"))); } boolean original_bSingleHashScrapes = bSingleHashScrapes; boolean disable_all_scrapes = !COConfigurationManager .getBooleanParameter("Tracker Client Scrape Enable"); boolean disable_stopped_scrapes = !COConfigurationManager .getBooleanParameter("Tracker Client Scrape Stopped Enable"); byte[] scrape_reply = null; try { // if URL already includes a query component then just append our // params HashWrapper one_of_the_hashes = null; TRTrackerScraperResponseImpl one_of_the_responses = null; char first_separator = scrapeURL.indexOf('?') == -1 ? '?' : '&'; String info_hash = ""; String flags = ""; List hashesForUDP = new ArrayList(); for (int i = 0; i < responses.size(); i++) { TRTrackerScraperResponseImpl response = (TRTrackerScraperResponseImpl) responses.get(i); HashWrapper hash = response.getHash(); if (Logger.isEnabled()) Logger.log(new LogEvent(TorrentUtils.getDownloadManager(hash), LOGID, "TrackerStatus: scraping, single_hash_scrapes = " + bSingleHashScrapes)); if (!scraper.isNetworkEnabled(hash, tracker_url)) { response.setNextScrapeStartTime(SystemTime.getCurrentTime() + FAULTY_SCRAPE_RETRY_INTERVAL); response.setStatus(TRTrackerScraperResponse.ST_ERROR, MessageText .getString(SS + "networkdisabled")); scraper.scrapeReceived(response); } else if ( !force && ( disable_all_scrapes || (disable_stopped_scrapes && !scraper.isTorrentRunning(hash)))){ response.setNextScrapeStartTime(SystemTime.getCurrentTime() + FAULTY_SCRAPE_RETRY_INTERVAL); response.setStatus(TRTrackerScraperResponse.ST_ERROR, MessageText .getString(SS + "disabled")); scraper.scrapeReceived(response); } else { response.setStatus(TRTrackerScraperResponse.ST_SCRAPING, MessageText.getString(SS + "scraping")); // technically haven't recieved a scrape yet, but we need // to notify listeners (the ones that display status) scraper.scrapeReceived(response); // the client-id stuff RELIES on info_hash being the FIRST // parameter added by // us to the URL, so don't change it! info_hash += ((one_of_the_hashes != null) ? '&' : first_separator) + "info_hash="; info_hash += URLEncoder.encode( new String(hash.getBytes(), Constants.BYTE_ENCODING), Constants.BYTE_ENCODING).replaceAll("\\+", "%20"); Object[] extensions = scraper.getExtensions(hash); if ( extensions != null ){ if ( extensions[0] != null ){ info_hash += (String)extensions[0]; } flags += (Character)extensions[1]; }else{ flags += TRTrackerScraperClientResolver.FL_NONE; } one_of_the_responses = response; one_of_the_hashes = hash; // 28 + 16 + 70*20 -> IPv4/udp packet size of 1444 , that should go through most lines unfragmented if(hashesForUDP.size() < 70) hashesForUDP.add(hash); } } // for responses if (one_of_the_hashes == null) return; String request = scrapeURL + info_hash; if ( az_tracker ){ String port_details = TRTrackerUtils.getPortsForURL(); request += port_details; request += "&azsf=" + flags + "&azver=" + TRTrackerAnnouncer.AZ_TRACKER_VERSION_CURRENT; } URL reqUrl = new URL( request ); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Accessing scrape interface using url : " + reqUrl)); ByteArrayOutputStream message = new ByteArrayOutputStream(); long scrapeStartTime = SystemTime.getCurrentTime(); URL redirect_url = null; String protocol = reqUrl.getProtocol(); URL udpScrapeURL = null; boolean auto_probe = false; if(protocol.equalsIgnoreCase("udp") && udpScrapeEnabled) udpScrapeURL = reqUrl; else if(protocol.equalsIgnoreCase("http") && !az_tracker && scrapeCount % autoUDPscrapeEvery == 0 && udpScrapeEnabled) { udpScrapeURL = new URL(reqUrl.toString().replaceFirst("^http", "udp")); auto_probe = true; } try{ // set context in case authentication dialog is required TorrentUtils.setTLSTorrentHash(one_of_the_hashes); if ( udpScrapeURL != null){ boolean success = scrapeUDP( reqUrl, message, hashesForUDP, !auto_probe ); if((!success || message.size() == 0) && !protocol.equalsIgnoreCase("udp")) { // automatic UDP probe failed, use HTTP again udpScrapeURL = null; message.reset(); if(autoUDPscrapeEvery < 16) autoUDPscrapeEvery <<= 1; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_INFORMATION, "redirection of http scrape ["+scrapeURL+"] to udp failed, will retry in "+autoUDPscrapeEvery+" scrapes")); } else if(success && !protocol.equalsIgnoreCase("udp")) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_INFORMATION, "redirection of http scrape ["+scrapeURL+"] to udp successful")); autoUDPscrapeEvery = 1; TRTrackerUtils.setUDPProbeResult( reqUrl, true ); } } scrapeCount++; if(udpScrapeURL == null) redirect_url = scrapeHTTP(reqUrl, message); }finally{ TorrentUtils.setTLSTorrentHash( null ); } scrape_reply = message.toByteArray(); Map map = BDecoder.decode( scrape_reply ); boolean this_is_az_tracker = map.get( "aztracker" ) != null; if ( az_tracker != this_is_az_tracker ){ az_tracker = this_is_az_tracker; TRTrackerUtils.setAZTracker( tracker_url, az_tracker ); } Map mapFiles = (Map) map.get("files"); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Response from scrape interface " + scrapeURL + ": " + ((mapFiles == null) ? "null" : "" + mapFiles.size()) + " returned")); int iMinRequestInterval = 0; if (map != null) { /* "The spec": * files * infohash * complete * incomplete * downloaded * name * flags * min_request_interval * failure reason */ /* * files infohash complete incomplete downloaded name flags * min_request_interval */ Map mapFlags = (Map) map.get("flags"); if (mapFlags != null) { Long longScrapeValue = (Long) mapFlags .get("min_request_interval"); if (longScrapeValue != null) iMinRequestInterval = longScrapeValue.intValue(); // Tracker owners want this log entry if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Received min_request_interval of " + iMinRequestInterval)); } } if (mapFiles == null || mapFiles.size() == 0) { // azureus extension here to handle "failure reason" returned for // scrapes byte[] failure_reason_bytes = map == null ? null : (byte[]) map .get("failure reason"); if (failure_reason_bytes != null) { long nextScrapeTime = SystemTime.getCurrentTime() + ((iMinRequestInterval == 0) ? FAULTY_SCRAPE_RETRY_INTERVAL : iMinRequestInterval * 1000); for (int i = 0; i < responses.size(); i++) { TRTrackerScraperResponseImpl response = (TRTrackerScraperResponseImpl) responses .get(i); response.setNextScrapeStartTime(nextScrapeTime); response.setStatus(TRTrackerScraperResponse.ST_ERROR, MessageText.getString(SS + "error") + new String(failure_reason_bytes, Constants.DEFAULT_ENCODING)); // notifiy listeners scraper.scrapeReceived(response); } } else { if (responses.size() > 1) { // multi were requested, 0 returned. Therefore, multi not // supported bSingleHashScrapes = true; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, scrapeURL + " doesn't properly support " + "multi-hash scrapes")); for (int i = 0; i < responses.size(); i++) { TRTrackerScraperResponseImpl response = (TRTrackerScraperResponseImpl) responses .get(i); response.setStatus(TRTrackerScraperResponse.ST_ERROR, MessageText.getString(SS + "error") + MessageText.getString(SSErr + "invalid")); // notifiy listeners scraper.scrapeReceived(response); } } else { long nextScrapeTime = SystemTime.getCurrentTime() + ((iMinRequestInterval == 0) ? NOHASH_RETRY_INTERVAL : iMinRequestInterval * 1000); // 1 was requested, 0 returned. Therefore, hash not found. TRTrackerScraperResponseImpl response = (TRTrackerScraperResponseImpl) responses .get(0); response.setNextScrapeStartTime(nextScrapeTime); response.setStatus(TRTrackerScraperResponse.ST_ERROR, MessageText.getString(SS + "error") + MessageText.getString(SSErr + "nohash")); // notifiy listeners scraper.scrapeReceived(response); } } return; } /* * If we requested mutliple hashes, but only one was returned, revert * to Single Hash Scrapes, but continue on to process the one has that * was returned (it may be a random one from the list) */ if (!bSingleHashScrapes && responses.size() > 1 && mapFiles.size() == 1) { bSingleHashScrapes = true; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, scrapeURL + " only returned " + mapFiles.size() + " hash scrape(s), but we asked for " + responses.size())); } for (int i = 0; i < responses.size(); i++) { TRTrackerScraperResponseImpl response = (TRTrackerScraperResponseImpl) responses .get(i); // LGLogger.log( "decoding response #" +i+ ": " + // ByteFormatter.nicePrint( response.getHash(), true ) ); // retrieve the scrape data for the relevent infohash Map scrapeMap = (Map) mapFiles.get(new String(response.getHash().getBytes(), Constants.BYTE_ENCODING)); if (scrapeMap == null) { // some trackers that return only 1 hash return a random one! if (responses.size() == 1 || mapFiles.size() != 1) { response.setNextScrapeStartTime(SystemTime.getCurrentTime() + NOHASH_RETRY_INTERVAL); response.setStatus(TRTrackerScraperResponse.ST_ERROR, MessageText.getString(SS + "error") + MessageText.getString(SSErr + "nohash")); // notifiy listeners scraper.scrapeReceived(response); } else { // This tracker doesn't support multiple hash requests. // revert status to what it was response.revertStatus(); if (response.getStatus() == TRTrackerScraperResponse.ST_SCRAPING) { // System.out.println("Hash " + // ByteFormatter.nicePrint(response.getHash(), true) + " // mysteriously reverted to ST_SCRAPING!"); // response.setStatus(TRTrackerScraperResponse.ST_ONLINE, ""); response.setNextScrapeStartTime(SystemTime.getCurrentTime() + FAULTY_SCRAPE_RETRY_INTERVAL); response.setStatus(TRTrackerScraperResponse.ST_ERROR, MessageText.getString(SS + "error") + MessageText.getString(SSErr + "invalid")); } else { // force single-hash scrapes here bSingleHashScrapes = true; // only leave the next retry time if this is the first single // hash fail if (original_bSingleHashScrapes) { response.setNextScrapeStartTime(SystemTime.getCurrentTime() + FAULTY_SCRAPE_RETRY_INTERVAL); } } // notifiy listeners scraper.scrapeReceived(response); // if this was the first scrape request in the list, // TrackerChecker // will attempt to scrape again because we didn't reset the // nextscrapestarttime. But the next time, bSingleHashScrapes // will be true, and only 1 has will be requested, so there // will not be infinite looping } // System.out.println("scrape: hash missing from reply"); } else { // retrieve values int seeds = ((Long) scrapeMap.get("complete")).intValue(); int peers = ((Long) scrapeMap.get("incomplete")).intValue(); Long comp = (Long) scrapeMap.get("downloaded"); int completed = comp == null ? -1 : comp.intValue(); // make sure we dont use invalid replies if (seeds < 0 || peers < 0 || completed < -1) { if (Logger.isEnabled()) { HashWrapper hash = response.getHash(); Logger.log(new LogEvent(TorrentUtils.getDownloadManager(hash), LOGID, "Invalid scrape response from '" + reqUrl + "': map = " + scrapeMap)); } // We requested multiple hashes, but tracker didn't support // multiple hashes and returned 1 hash. However, that hash is // invalid because seeds or peers was < 0. So, exit. Scrape // manager will run scrapes for each individual hash. if (responses.size() > 1 && bSingleHashScrapes) { response.setStatus(TRTrackerScraperResponse.ST_ERROR, MessageText.getString(SS + "error") + MessageText.getString(SSErr + "invalid")); scraper.scrapeReceived(response); continue; } response.setNextScrapeStartTime(SystemTime.getCurrentTime() + FAULTY_SCRAPE_RETRY_INTERVAL); response.setStatus(TRTrackerScraperResponse.ST_ERROR, MessageText.getString(SS + "error") + MessageText.getString(SSErr + "invalid") + " " + (seeds < 0 ? MessageText .getString("MyTorrentsView.seeds") + " == " + seeds + ". " : "") + (peers < 0 ? MessageText .getString("MyTorrentsView.peers") + " == " + peers + ". " : "") + (completed < 0 ? MessageText .getString("MyTorrentsView.completed") + " == " + completed + ". " : "")); scraper.scrapeReceived(response); continue; } int scrapeInterval = TRTrackerScraperResponseImpl .calcScrapeIntervalSecs(iMinRequestInterval, seeds); long nextScrapeTime = SystemTime.getCurrentTime() + (scrapeInterval * 1000); response.setNextScrapeStartTime(nextScrapeTime); // create the response response.setScrapeStartTime(scrapeStartTime); response.setSeeds(seeds); response.setPeers(peers); response.setCompleted(completed); response.setStatus(TRTrackerScraperResponse.ST_ONLINE, MessageText.getString(SS + "ok")); // notifiy listeners scraper.scrapeReceived(response); try{ if ( responses.size() == 1 && redirect_url != null ){ // we only deal with redirects for single urls - if the tracker wants to // redirect one of a group is has to force single-hash scrapes anyway String redirect_str = redirect_url.toString(); int s_pos = redirect_str.indexOf( "/scrape" ); if ( s_pos != -1 ){ URL new_url = new URL( redirect_str.substring(0,s_pos) + "/announce" + redirect_str.substring(s_pos+7)); if ( scraper.redirectTrackerUrl( response.getHash(), tracker_url, new_url )){ removeHash( response.getHash()); } } } }catch( Throwable e ){ Debug.printStackTrace(e); } } } // for responses } catch (NoClassDefFoundError ignoreSSL) { // javax/net/ssl/SSLSocket for (int i = 0; i < responses.size(); i++) { TRTrackerScraperResponseImpl response = (TRTrackerScraperResponseImpl) responses .get(i); response.setNextScrapeStartTime(SystemTime.getCurrentTime() + FAULTY_SCRAPE_RETRY_INTERVAL); response.setStatus(TRTrackerScraperResponse.ST_ERROR, MessageText .getString(SS + "error") + ignoreSSL.getMessage()); // notifiy listeners scraper.scrapeReceived(response); } } catch (FileNotFoundException e) { for (int i = 0; i < responses.size(); i++) { TRTrackerScraperResponseImpl response = (TRTrackerScraperResponseImpl) responses .get(i); response.setNextScrapeStartTime(SystemTime.getCurrentTime() + FAULTY_SCRAPE_RETRY_INTERVAL); response.setStatus(TRTrackerScraperResponse.ST_ERROR, MessageText .getString(SS + "error") + MessageText.getString("DownloadManager.error.filenotfound")); // notifiy listeners scraper.scrapeReceived(response); } } catch (SocketException e) { setAllError(e); } catch (SocketTimeoutException e) { setAllError(e); } catch (UnknownHostException e) { setAllError(e); } catch (PRUDPPacketHandlerException e) { setAllError(e); } catch (BEncodingException e) { setAllError(e); } catch (Exception e) { // for apache we can get error 414 - URL too long. simplest solution // for this // is to fall back to single scraping String error_message = e.getMessage(); if (error_message != null) { if (error_message.indexOf(" 500 ") >= 0 || error_message.indexOf(" 400 ") >= 0 || error_message.indexOf(" 403 ") >= 0 || error_message.indexOf(" 404 ") >= 0 || error_message.indexOf(" 501 ") >= 0) { // various errors that have a 99% chance of happening on // any other scrape request setAllError(e); return; } if (error_message.indexOf("414") != -1 && !bSingleHashScrapes) { bSingleHashScrapes = true; // Skip the setuing up the response. We want to scrape again return; } } String msg = Debug.getNestedExceptionMessage(e); if ( scrape_reply != null ){ String trace_data; if ( scrape_reply.length <= 150 ){ trace_data = new String(scrape_reply); }else{ trace_data = new String(scrape_reply,0,150) + "..."; } msg += " [" + trace_data + "]"; } for (int i = 0; i < responses.size(); i++) { TRTrackerScraperResponseImpl response = (TRTrackerScraperResponseImpl) responses .get(i); if (Logger.isEnabled()) { HashWrapper hash = response.getHash(); Logger.log(new LogEvent(TorrentUtils.getDownloadManager(hash), LOGID, LogEvent.LT_ERROR, "Error from scrape interface " + scrapeURL + " : " + msg + " (" + e.getClass() + ")")); } response.setNextScrapeStartTime(SystemTime.getCurrentTime() + FAULTY_SCRAPE_RETRY_INTERVAL); response.setStatus(TRTrackerScraperResponse.ST_ERROR, MessageText .getString(SS + "error") + msg); // notifiy listeners scraper.scrapeReceived(response); } } } catch (Throwable t) { Debug.out("runScrapesSupport failed", t); } finally { numActiveScrapes--; } } /** * @param e */ private void setAllError(Exception e) { // Error will apply to ALL hashes, so set all Object[] values; try { hashes_mon.enter(); values = hashes.values().toArray(); } finally { hashes_mon.exit(); } String msg = e.getLocalizedMessage(); if(e instanceof BEncodingException) if(msg.indexOf("html") != -1) msg = "could not decode response, appears to be a website instead of tracker scrape: "+msg.replace('\n', ' '); else msg = "bencoded response malformed:"+msg; for (int i = 0; i < values.length; i++) { TRTrackerScraperResponseImpl response = (TRTrackerScraperResponseImpl) values[i]; if (Logger.isEnabled()) { HashWrapper hash = response.getHash(); Logger.log(new LogEvent(TorrentUtils.getDownloadManager(hash), LOGID, LogEvent.LT_WARNING, "Error from scrape interface " + scrapeURL + " : " + msg)); //e.printStackTrace(); } response.setNextScrapeStartTime(SystemTime.getCurrentTime() + FAULTY_SCRAPE_RETRY_INTERVAL); response.setStatus(TRTrackerScraperResponse.ST_ERROR,StringInterner.intern( MessageText.getString(SS + "error") + msg + " (IO)")); // notifiy listeners scraper.scrapeReceived(response); } } protected URL scrapeHTTP( URL reqUrl, ByteArrayOutputStream message ) throws IOException { URL redirect_url = null; TRTrackerUtils.checkForBlacklistedURLs( reqUrl ); reqUrl = TRTrackerUtils.adjustURLForHosting( reqUrl ); reqUrl = AddressUtils.adjustURL( reqUrl ); // System.out.println( "scraping " + reqUrl.toString()); Properties http_properties = new Properties(); http_properties.put( ClientIDGenerator.PR_URL, reqUrl ); try{ ClientIDManagerImpl.getSingleton().generateHTTPProperties( http_properties ); }catch( ClientIDException e ){ throw( new IOException( e.getMessage())); } reqUrl = (URL)http_properties.get( ClientIDGenerator.PR_URL ); InputStream is = null; try{ HttpURLConnection con = null; if ( reqUrl.getProtocol().equalsIgnoreCase("https")){ // see ConfigurationChecker for SSL client defaults HttpsURLConnection ssl_con = (HttpsURLConnection)reqUrl.openConnection(); // allow for certs that contain IP addresses rather than dns names ssl_con.setHostnameVerifier( new HostnameVerifier() { public boolean verify(String host, SSLSession session) { return( true ); } }); con = ssl_con; } else { con = (HttpURLConnection) reqUrl.openConnection(); } String user_agent = (String)http_properties.get( ClientIDGenerator.PR_USER_AGENT ); if ( user_agent != null ){ con.setRequestProperty("User-Agent", user_agent ); } // some trackers support gzip encoding of replies con.addRequestProperty("Accept-Encoding","gzip"); con.setRequestProperty("Connection", "close" ); con.connect(); is = con.getInputStream(); String resulting_url_str = con.getURL().toString(); if ( !reqUrl.toString().equals( resulting_url_str )){ // some kind of redirect has occurred. Unfortunately we can't get at the underlying // redirection reason (temp, perm etc) so we support the use of an explicit indicator // in the resulting url String marker = "permredirect=1"; int pos = resulting_url_str.indexOf( marker ); if ( pos != -1 ){ pos = pos-1; // include the '&' or '?' try{ redirect_url = new URL( resulting_url_str.substring(0,pos)); }catch( Throwable e ){ Debug.printStackTrace(e); } } } String encoding = con.getHeaderField( "content-encoding"); boolean gzip = encoding != null && encoding.equalsIgnoreCase("gzip"); // System.out.println( "encoding = " + encoding ); if ( gzip ){ is = new GZIPInputStream( is ); } byte[] data = new byte[1024]; int num_read = 0; while( true ){ try { int len = is.read(data); if ( len > 0 ){ message.write(data, 0, len); num_read += len; if ( num_read > 128*1024 ){ // someone's sending us junk, bail out message.reset(); throw( new Exception( "Tracker response invalid (too large)" )); } }else if ( len == 0 ){ Thread.sleep(20); }else{ break; } } catch (Exception e) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "Error from scrape interface " + scrapeURL + " : " + Debug.getNestedExceptionMessage(e))); return( null ); } } } finally { if (is != null) { try { is.close(); } catch (IOException e1) { } } } return( redirect_url ); } protected boolean scrapeUDP(URL reqUrl, ByteArrayOutputStream message, List hashes, boolean do_auth_test) throws Exception { Map rootMap = new HashMap(); Map files = new ByteEncodedKeyHashMap(); rootMap.put("files", files); /* * reduce network traffic by only scraping UDP when the torrent isn't * running as UDP version 2 contains scrape data in the announce * response */ /* removed implementation for the time being for (Iterator it = hashes.iterator(); it.hasNext();) { HashWrapper hash = (HashWrapper) it.next(); if (PRUDPPacketTracker.VERSION == 2 && scraper.isTorrentDownloading(hash)) { if (Logger.isEnabled()) Logger.log(new LogEvent(TorrentUtils.getDownloadManager(hash), LOGID, LogEvent.LT_WARNING, "Scrape of " + reqUrl + " skipped as torrent running and " + "therefore scrape data available in " + "announce replies")); // easiest approach here is to brew up a response that looks like the current one Map file = new HashMap(); byte[] resp_hash = hash.getBytes(); // System.out.println("got hash:" + ByteFormatter.nicePrint( resp_hash, true )); files.put(new String(resp_hash, Constants.BYTE_ENCODING), file); file.put("complete", new Long(current_response.getSeeds())); file.put("downloaded", new Long(-1)); // unknown file.put("incomplete", new Long(current_response.getPeers())); byte[] data = BEncoder.encode(rootMap); message.write(data); return true; } } */ reqUrl = TRTrackerUtils.adjustURLForHosting( reqUrl ); PasswordAuthentication auth = null; boolean auth_ok = false; try{ if (do_auth_test && UrlUtils.queryHasParameter(reqUrl.getQuery(), "auth", false)) { auth = SESecurityManager.getPasswordAuthentication( "UDP Tracker", reqUrl ); } int port = UDPNetworkManager.getSingleton().getUDPNonDataListeningPortNumber(); PRUDPPacketHandler handler = PRUDPPacketHandlerFactory.getHandler( port ); InetSocketAddress destination = new InetSocketAddress(reqUrl.getHost(),reqUrl.getPort()==-1?80:reqUrl.getPort()); String failure_reason = null; for (int retry_loop=0;retry_loop 0) { result[pos++] = (byte) (iter % 255); iter = iter / 255; } return result; } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTScraperImpl.java0000644000175000017500000000763110373051032030544 0ustar adrianadrian/* * Created on 14-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.client.impl.bt; import java.net.URL; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.core3.tracker.client.impl.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.plugins.download.DownloadScrapeResult; /** * @author parg * */ public class TRTrackerBTScraperImpl { protected static TRTrackerBTScraperImpl singleton; protected static AEMonitor class_mon = new AEMonitor( "TRTrackerBTScraper" ); private TRTrackerScraperImpl scraper; private TrackerChecker tracker_checker; public static TRTrackerBTScraperImpl create( TRTrackerScraperImpl _scraper ) { try{ class_mon.enter(); if ( singleton == null ){ singleton = new TRTrackerBTScraperImpl( _scraper ); } return( singleton ); }finally{ class_mon.exit(); } } protected TRTrackerBTScraperImpl( TRTrackerScraperImpl _scraper ) { scraper = _scraper; tracker_checker = new TrackerChecker( this ); } protected TRTrackerScraperImpl getScraper() { return( scraper ); } public void setScrape( TOTorrent torrent, URL url, DownloadScrapeResult result ) { if ( torrent != null && result != null ){ TRTrackerScraperResponseImpl resp = tracker_checker.getHashData( torrent, url ); // only override details if underlying scrape is failing if ( resp != null && resp.getStatus() == TRTrackerScraperResponse.ST_ERROR ){ resp.setSeedsPeers( result.getSeedCount(), result.getNonSeedCount()); resp.setScrapeStartTime( result.getScrapeStartTime()); // leave nextScrapeStartTime alone as we still want the existing // scraping mechanism to kick in and check the torrent's tracker resp.setStatus( result.getResponseType()==DownloadScrapeResult.RT_SUCCESS? TRTrackerScraperResponse.ST_ONLINE: TRTrackerScraperResponse.ST_ERROR, result.getStatus() + " (" + result.getURL() + ")"); scraper.scrapeReceived( resp ); } } } public TRTrackerScraperResponse scrape( TOTorrent torrent, URL target_url, boolean force ) { if (torrent == null){ return null; } if ( force ){ tracker_checker.syncUpdate( torrent, target_url ); } TRTrackerScraperResponse res = tracker_checker.getHashData( torrent, target_url ); // System.out.println( "scrape: " + torrent + " -> " + (res==null?"null":""+res.getSeeds())); return( res ); } public TRTrackerScraperResponse scrape( TRTrackerAnnouncer tracker_client ) { TRTrackerScraperResponse res = tracker_checker.getHashData( tracker_client ); // System.out.println( "scrape: " + tracker_client + " -> " + (res==null?"null":""+res.getSeeds())); return( res ); } public void remove( TOTorrent torrent ) { tracker_checker.removeHash( torrent ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperImpl.java0000644000175000017500000001313611273742420027716 0ustar adrianadrian/* * File : TRTrackerScraperImpl.java * Created : 09-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.client.impl; /** * @author parg * */ import java.net.URL; import org.gudy.azureus2.core3.tracker.client.*; import org.gudy.azureus2.core3.tracker.client.impl.bt.TRTrackerBTScraperImpl; import org.gudy.azureus2.core3.tracker.client.impl.dht.TRTrackerDHTScraperImpl; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.download.DownloadScrapeResult; public class TRTrackerScraperImpl implements TRTrackerScraper { private static TRTrackerScraperImpl singleton; private static AEMonitor class_mon = new AEMonitor( "TRTrackerScraper" ); private TRTrackerBTScraperImpl bt_scraper; private TRTrackerDHTScraperImpl dht_scraper; private TRTrackerScraperClientResolver client_resolver; // DiskManager listeners private static final int LDT_SCRAPE_RECEIVED = 1; private ListenerManager listeners = ListenerManager.createManager( "TrackerScraper:ListenDispatcher", new ListenerManagerDispatcher() { public void dispatch( Object _listener, int type, Object value ) { TRTrackerScraperListener listener = (TRTrackerScraperListener)_listener; listener.scrapeReceived((TRTrackerScraperResponse)value); } }); public static TRTrackerScraperImpl create() { try{ class_mon.enter(); if ( singleton == null ){ singleton = new TRTrackerScraperImpl(); } return( singleton ); }finally{ class_mon.exit(); } } protected TRTrackerScraperImpl() { bt_scraper = TRTrackerBTScraperImpl.create( this ); dht_scraper = TRTrackerDHTScraperImpl.create( this ); } public TRTrackerScraperResponse scrape( TOTorrent torrent ) { return( scrape( torrent, false )); } public TRTrackerScraperResponse scrape( TOTorrent torrent, URL target_url ) { return( scrape( torrent, target_url, false )); } public TRTrackerScraperResponse scrape( TOTorrent torrent, boolean force ) { return( scrape( torrent, null, force )); } public void setScrape( TOTorrent torrent, URL url, DownloadScrapeResult result ) { if ( torrent != null ){ if ( TorrentUtils.isDecentralised( torrent )){ dht_scraper.setScrape( torrent, url, result ); }else{ bt_scraper.setScrape( torrent, url, result ); } } } public TRTrackerScraperResponse scrape( TOTorrent torrent, URL target_url, boolean force ) { if (torrent == null ){ return null; } if ( TorrentUtils.isDecentralised( torrent )){ return( dht_scraper.scrape( torrent, target_url, force )); }else{ return( bt_scraper.scrape( torrent, target_url, force )); } } public TRTrackerScraperResponse scrape( TRTrackerAnnouncer tracker_client ) { TOTorrent torrent = tracker_client.getTorrent(); if ( TorrentUtils.isDecentralised( torrent )){ return( dht_scraper.scrape( tracker_client )); }else{ return( bt_scraper.scrape( tracker_client )); } } public void remove( TOTorrent torrent ) { if ( TorrentUtils.isDecentralised( torrent )){ dht_scraper.remove( torrent ); }else{ bt_scraper.remove( torrent ); } } public void scrapeReceived( TRTrackerScraperResponse response ) { listeners.dispatch( LDT_SCRAPE_RECEIVED, response ); } public void setClientResolver( TRTrackerScraperClientResolver resolver ) { client_resolver = resolver; } public TRTrackerScraperClientResolver getClientResolver() { return( client_resolver ); } public boolean isTorrentDownloading( HashWrapper hash ) { if ( client_resolver == null ){ return( false ); } int state = client_resolver.getStatus( hash ); return( state == TRTrackerScraperClientResolver.ST_RUNNING ); } public boolean isTorrentRunning( HashWrapper hash ) { if ( client_resolver == null ){ return( false ); } int state = client_resolver.getStatus( hash ); return( state == TRTrackerScraperClientResolver.ST_RUNNING || state == TRTrackerScraperClientResolver.ST_QUEUED ); } public boolean isNetworkEnabled( HashWrapper hash, URL url ) { if ( client_resolver == null ){ return( false ); } return( client_resolver.isNetworkEnabled( hash, url )); } public Object[] getExtensions( HashWrapper hash ) { if ( client_resolver == null ){ return( null ); } return( client_resolver.getExtensions( hash )); } public boolean redirectTrackerUrl( HashWrapper hash, URL old_url, URL new_url ) { return( client_resolver.redirectTrackerUrl( hash, old_url, new_url )); } public void addListener( TRTrackerScraperListener l ) { listeners.addListener(l); } public void removeListener( TRTrackerScraperListener l ) { listeners.removeListener(l); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerMuxer.java0000644000175000017500000001143511307334262030445 0ustar adrianadrian/* * Created on Dec 4, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.core3.tracker.client.impl; import java.net.URL; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerDataProvider; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerException; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse; import org.gudy.azureus2.core3.tracker.client.impl.bt.TRTrackerBTAnnouncerImpl; import org.gudy.azureus2.core3.tracker.client.impl.dht.TRTrackerDHTAnnouncerImpl; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.plugins.download.DownloadAnnounceResult; public class TRTrackerAnnouncerMuxer extends TRTrackerAnnouncerImpl { private TRTrackerAnnouncer main_announcer; protected TRTrackerAnnouncerMuxer( TOTorrent torrent, String[] networks, boolean manual ) throws TRTrackerAnnouncerException { super( torrent ); TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets(); if ( TorrentUtils.isDecentralised( torrent )){ main_announcer = new TRTrackerDHTAnnouncerImpl( torrent, networks, manual, getHelper()); }else{ main_announcer = new TRTrackerBTAnnouncerImpl( torrent, sets, networks, manual, getHelper()); } } public void setAnnounceDataProvider( TRTrackerAnnouncerDataProvider provider ) { main_announcer.setAnnounceDataProvider( provider ); //System.out.println( "announcer set" ); } public TOTorrent getTorrent() { return( main_announcer.getTorrent()); } public URL getTrackerURL() { return( main_announcer.getTrackerURL()); } public void setTrackerURL( URL url ) { main_announcer.setTrackerURL( url ); } public void setTrackerURLs( TOTorrentAnnounceURLSet[] sets ) { Debug.out( "Not implemented" ); } public void resetTrackerUrl( boolean shuffle ) { main_announcer.setTrackerURLs( getTorrent().getAnnounceURLGroup().getAnnounceURLSets()); main_announcer.resetTrackerUrl( shuffle ); } public void setIPOverride( String override ) { main_announcer.setIPOverride( override ); } public void cloneFrom( TRTrackerAnnouncer other ) { main_announcer.cloneFrom( other ); } public void clearIPOverride() { main_announcer.clearIPOverride(); } public byte[] getPeerId() { return( main_announcer.getPeerId()); } public void setRefreshDelayOverrides( int percentage ) { main_announcer.setRefreshDelayOverrides( percentage ); } public int getTimeUntilNextUpdate() { return( main_announcer.getTimeUntilNextUpdate()); } public int getLastUpdateTime() { return( main_announcer.getLastUpdateTime()); } public void update( boolean force ) { main_announcer.update(force); //System.out.println( "update" ); } public void complete( boolean already_reported ) { main_announcer.complete(already_reported); //System.out.println( "complete" ); } public void stop( boolean for_queue ) { main_announcer.stop( for_queue ); //System.out.println( "stop" ); } public void destroy() { TRTrackerAnnouncerFactoryImpl.destroy( this ); main_announcer.destroy(); //System.out.println( "destroy" ); } public int getStatus() { return( main_announcer.getStatus()); } public boolean isManual() { return( main_announcer.isManual()); } public String getStatusString() { return( main_announcer.getStatusString()); } public TRTrackerAnnouncerResponse getLastResponse() { return( main_announcer.getLastResponse()); } public void refreshListeners() { main_announcer.refreshListeners(); } public void setAnnounceResult( DownloadAnnounceResult result ) { main_announcer.setAnnounceResult(result); } public void generateEvidence( IndentWriter writer ) { main_announcer.generateEvidence(writer); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/impl/dht/0000755000175000017500000000000011310377634023626 5ustar adrianadrian././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperResponseImpl.javaazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperResponseImpl.java0000644000175000017500000000304010456465312032551 0ustar adrianadrian/* * Created on 14-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.client.impl.dht; import java.net.URL; import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerScraperResponseImpl; import org.gudy.azureus2.core3.util.HashWrapper; /** * @author parg * */ public class TRTrackerDHTScraperResponseImpl extends TRTrackerScraperResponseImpl { private URL url; protected TRTrackerDHTScraperResponseImpl( HashWrapper hash, URL _url ) { super(hash ); url = _url; } public void setSeedsPeers( int s, int p ) { setSeeds( s ); setPeers( p ); } public URL getURL() { return( url ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTAnnouncerImpl.java0000644000175000017500000002057611307334262031373 0ustar adrianadrian/* * Created on 14-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.client.impl.dht; import java.net.URL; import java.util.Map; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerDataProvider; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerException; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerListener; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponsePeer; import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerAnnouncerImpl; import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerAnnouncerResponseImpl; import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerAnnouncerResponsePeerImpl; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.HashWrapper; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.clientid.ClientIDException; import org.gudy.azureus2.plugins.download.DownloadAnnounceResult; import org.gudy.azureus2.plugins.download.DownloadAnnounceResultPeer; import org.gudy.azureus2.pluginsimpl.local.clientid.ClientIDManagerImpl; /** * @author parg * */ public class TRTrackerDHTAnnouncerImpl implements TRTrackerAnnouncer { public final static LogIDs LOGID = LogIDs.TRACKER; private TOTorrent torrent; private HashWrapper torrent_hash; private TRTrackerAnnouncerImpl.Helper helper; private byte[] data_peer_id; private String tracker_status_str; private long last_update_time; private int state = TS_INITIALISED; private TRTrackerAnnouncerResponseImpl last_response; private boolean manual; public TRTrackerDHTAnnouncerImpl( TOTorrent _torrent, String[] _networks, boolean _manual, TRTrackerAnnouncerImpl.Helper _helper ) throws TRTrackerAnnouncerException { torrent = _torrent; manual = _manual; helper = _helper; try{ torrent_hash = torrent.getHashWrapper(); }catch( TOTorrentException e ){ Debug.printStackTrace(e); } try{ data_peer_id = ClientIDManagerImpl.getSingleton().generatePeerID( torrent, false ); }catch( ClientIDException e ){ throw( new TRTrackerAnnouncerException( "TRTrackerAnnouncer: Peer ID generation fails", e )); } last_response = new TRTrackerAnnouncerResponseImpl( torrent.getAnnounceURL(), torrent_hash, TRTrackerAnnouncerResponse.ST_OFFLINE, 0, "Initialising" ); tracker_status_str = MessageText.getString("PeerManager.status.checking") + "..."; } public void setAnnounceDataProvider( TRTrackerAnnouncerDataProvider provider ) { } public boolean isManual() { return( manual ); } public TOTorrent getTorrent() { return( torrent ); } public URL getTrackerURL() { return( torrent.getAnnounceURL()); } public void setTrackerURL( URL url ) { Debug.out( "Not implemented" ); } public void setTrackerURLs( TOTorrentAnnounceURLSet[] sets ) { Debug.out( "Not implemented" ); } public void resetTrackerUrl( boolean shuffle ) { } public void cloneFrom( TRTrackerAnnouncer other ) { data_peer_id = other.getPeerId(); } public void setIPOverride( String override ) { } public void clearIPOverride() { } public int getPort() { return(0); } public byte[] getPeerId() { return( data_peer_id ); } public void setRefreshDelayOverrides( int percentage ) { } public int getTimeUntilNextUpdate() { long elapsed = (SystemTime.getCurrentTime() - last_update_time)/1000; return( (int)(last_response.getTimeToWait()-elapsed)); } public int getLastUpdateTime() { return( (int)(last_update_time/1000)); } public void update( boolean force ) { state = TS_DOWNLOADING; checkCache(); } public void complete( boolean already_reported ) { state = TS_COMPLETED; } public void stop( boolean for_queue ) { state = TS_STOPPED; } public void destroy() { } public int getStatus() { return( state ); } public String getStatusString() { return( tracker_status_str ); } public TRTrackerAnnouncerResponse getLastResponse() { return( last_response ); } public void refreshListeners() { } public void setAnnounceResult( DownloadAnnounceResult result ) { last_update_time = SystemTime.getCurrentTime(); TRTrackerAnnouncerResponseImpl response; if ( result.getResponseType() == DownloadAnnounceResult.RT_ERROR ){ tracker_status_str = MessageText.getString("PeerManager.status.error"); String reason = result.getError(); if ( reason != null ){ tracker_status_str += " (" + reason + ")"; } response = new TRTrackerAnnouncerResponseImpl( result.getURL(), torrent_hash, TRTrackerAnnouncerResponse.ST_OFFLINE, result.getTimeToWait(), reason ); }else{ DownloadAnnounceResultPeer[] ext_peers = result.getPeers(); TRTrackerAnnouncerResponsePeerImpl[] peers = new TRTrackerAnnouncerResponsePeerImpl[ext_peers.length]; for (int i=0;i 0 ){ last_response.setPeers( cached_peers ); helper.informResponse( last_response ); } } } public void addListener( TRTrackerAnnouncerListener l ) { helper.addListener( l ); } public void removeListener( TRTrackerAnnouncerListener l ) { helper.removeListener( l ); } public void setTrackerResponseCache( Map map ) { helper.setTrackerResponseCache( map ); } public void removeFromTrackerResponseCache( String ip, int tcpPort) { helper.removeFromTrackerResponseCache( ip, tcpPort ); } public Map getTrackerResponseCache() { return( helper.getTrackerResponseCache()); } public void generateEvidence( IndentWriter writer ) { writer.println( "DHT announce: " + (last_response==null?"null":last_response.getString())); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperImpl.java0000644000175000017500000001167611273742420031044 0ustar adrianadrian/* * Created on 14-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.client.impl.dht; import java.util.*; import java.net.URL; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperClientResolver; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerScraperImpl; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.HashWrapper; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.download.DownloadScrapeResult; /** * @author parg * */ public class TRTrackerDHTScraperImpl { protected static TRTrackerDHTScraperImpl singleton; protected static AEMonitor class_mon = new AEMonitor( "TRTrackerDHTScraper" ); private TRTrackerScraperImpl scraper; private Map responses = new HashMap(); public static TRTrackerDHTScraperImpl create( TRTrackerScraperImpl _scraper ) { try{ class_mon.enter(); if ( singleton == null ){ singleton = new TRTrackerDHTScraperImpl( _scraper ); } return( singleton ); }finally{ class_mon.exit(); } } protected TRTrackerDHTScraperImpl( TRTrackerScraperImpl _scraper ) { scraper = _scraper; } public void setScrape( TOTorrent torrent, URL url, DownloadScrapeResult result ) { if ( torrent != null && result != null){ try{ TRTrackerDHTScraperResponseImpl resp = new TRTrackerDHTScraperResponseImpl( torrent.getHashWrapper(), result.getURL()); resp.setSeedsPeers( result.getSeedCount(), result.getNonSeedCount()); resp.setScrapeStartTime( result.getScrapeStartTime()); resp.setNextScrapeStartTime( result.getNextScrapeStartTime()); resp.setStatus( result.getResponseType()==DownloadScrapeResult.RT_SUCCESS? TRTrackerScraperResponse.ST_ONLINE: TRTrackerScraperResponse.ST_ERROR, result.getStatus()); responses.put( torrent.getHashWrapper(), resp ); scraper.scrapeReceived( resp ); }catch( TOTorrentException e ){ Debug.printStackTrace(e); } } } public TRTrackerScraperResponse scrape( TOTorrent torrent, URL unused_target_url, boolean unused_force ) { if ( torrent != null ){ try{ HashWrapper hw = torrent.getHashWrapper(); TRTrackerDHTScraperResponseImpl response = responses.get( hw ); if ( response == null ){ TRTrackerScraperClientResolver resolver = scraper.getClientResolver(); if ( resolver != null ){ int[] cache = resolver.getCachedScrape( hw ); if ( cache != null ){ response = new TRTrackerDHTScraperResponseImpl( hw, torrent.getAnnounceURL()); response.setSeedsPeers( cache[0], cache[1] ); long now = SystemTime.getCurrentTime(); response.setScrapeStartTime( now ); response.setNextScrapeStartTime( now + 5*60*1000 ); response.setStatus( TRTrackerScraperResponse.ST_ONLINE, MessageText.getString( "Scrape.status.cached" )); responses.put( torrent.getHashWrapper(), response ); scraper.scrapeReceived( response ); } } } return( response ); }catch( TOTorrentException e ){ Debug.printStackTrace(e); } } return( null ); } public TRTrackerScraperResponse scrape( TRTrackerAnnouncer tracker_client ) { return( scrape( tracker_client.getTorrent(), null, false )); } public void remove( TOTorrent torrent ) { try{ responses.remove( torrent.getHashWrapper()); }catch( TOTorrentException e ){ Debug.printStackTrace(e); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerListener.java0000644000175000017500000000274710555114120030170 0ustar adrianadrian/* * File : TRTrackerClientListener.java * Created : 03-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.client; import java.net.URL; /** * @author parg * */ public interface TRTrackerAnnouncerListener { public void receivedTrackerResponse( TRTrackerAnnouncerResponse response ); /** * This callback indicates if the tracker client has change URL. If "explicit" is true then * this was via a call to the "setTrackerURL" method on TRTrackerClient. If false then the selected * URL has changed because it is a multi-tracker torrent * * @param explicit as above */ public void urlChanged( TRTrackerAnnouncer announcer, URL old_url, URL new_url, boolean explicit ); public void urlRefresh(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerResponsePeer.java0000644000175000017500000000215710545331612031016 0ustar adrianadrian/* * File : TRTrackerResponsePeer.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.client; import org.gudy.azureus2.plugins.download.DownloadAnnounceResultPeer; public interface TRTrackerAnnouncerResponsePeer extends DownloadAnnounceResultPeer { public int getHTTPPort(); public byte getAZVersion(); public int getUploadSpeed(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperListener.java0000644000175000017500000000200710001264136027623 0ustar adrianadrian/* * File : TRTrackerScraperListener.java * Created : 14-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.client; /** * @author parg * */ public interface TRTrackerScraperListener { public void scrapeReceived( TRTrackerScraperResponse response ); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperResponse.java0000644000175000017500000000361710754212224027652 0ustar adrianadrian/* * File : TRTrackerScraperResponse.java * Created : 09-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.client; import java.net.URL; import org.gudy.azureus2.core3.util.HashWrapper; /** * @author parg * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public interface TRTrackerScraperResponse { public static final int ST_INITIALIZING = 0; public static final int ST_ERROR = 1; public static final int ST_ONLINE = 2; public static final int ST_SCRAPING = 3; public HashWrapper getHash(); public int getCompleted(); public void setCompleted(int completed); public int getSeeds(); public int getPeers(); public void setSeedsPeers(int iSeeds, int iPeers); public int getStatus(); public long getScrapeStartTime(); public void setScrapeStartTime( long time ); public long getNextScrapeStartTime(); public void setNextScrapeStartTime( long nextScrapeStartTime ); public String getStatusString(); public boolean isValid(); public URL getURL(); public String getString(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerException.java0000644000175000017500000000215311012742270030332 0ustar adrianadrian/* * File : TRTrackerClientException.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.client; public class TRTrackerAnnouncerException extends Exception { public TRTrackerAnnouncerException( String str ) { super( str ); } public TRTrackerAnnouncerException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerResponse.java0000644000175000017500000000414310710557102030175 0ustar adrianadrian/* * File : TRTrackerResponse.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.client; import java.net.URL; import java.util.Map; import org.gudy.azureus2.core3.util.HashWrapper; public interface TRTrackerAnnouncerResponse { public static final int ST_OFFLINE = 0; public static final int ST_REPORTED_ERROR = 1; public static final int ST_ONLINE = 2; /** * Returns the current status of the tracker * @return see above ST_ set */ public int getStatus(); public String getStatusString(); public HashWrapper getHash(); /** * This value is always available * @return time to wait before requerying tracker */ public long getTimeToWait(); /** * Returns any additional textual information associated with reponse. * If the status is ST_REPORTED_ERROR, this will return the error description * (possibly directly from the tracker). * * @return Additional information */ public String getAdditionalInfo(); /** * * @return peers reported by tracker. this will include the local peer as well */ public TRTrackerAnnouncerResponsePeer[] getPeers(); public void setPeers( TRTrackerAnnouncerResponsePeer[] peers ); public Map getExtensions(); public URL getURL(); public int getScrapeCompleteCount(); public int getScrapeIncompleteCount(); public void print(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperClientResolver.java0000644000175000017500000000522011273742420031007 0ustar adrianadrian/* * Created on 27-Aug-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.client; import java.net.URL; import org.gudy.azureus2.core3.util.HashWrapper; /** * @author parg * */ public interface TRTrackerScraperClientResolver { public static final int ST_NOT_FOUND = 1; public static final int ST_RUNNING = 2; // downloading, seeding public static final int ST_QUEUED = 3; public static final int ST_OTHER = 4; public static final Character FL_NONE = new Character( 'n' ); public static final Character FL_INCOMPLETE_STOPPED = new Character( 's' ); public static final Character FL_INCOMPLETE_QUEUED = new Character( 'q' ); public static final Character FL_INCOMPLETE_RUNNING = new Character( 'r' ); public static final Character FL_COMPLETE_STOPPED = new Character( 'S' ); public static final Character FL_COMPLETE_QUEUED = new Character( 'Q' ); public static final Character FL_COMPLETE_RUNNING = new Character( 'R' ); /** * Gives access to a restricted set of states for this torrent from ST_ set * @param torrent_hash * @return */ public int getStatus( HashWrapper torrent_hash ); /** * * @param hash * @return */ public int[] getCachedScrape( HashWrapper hash ); public boolean isNetworkEnabled( HashWrapper hash, URL url ); /** * Two kinds of extensions: entry [0] = String (or null) that gets passed with the scrape verbotem after infohash * entry [1] = Character - status of download, aggregated into a single String passed with scrape * status flags are above FL_ values * @param hash * @return */ public Object[] getExtensions( HashWrapper hash ); public boolean redirectTrackerUrl( HashWrapper hash, URL old_url, URL new_url ); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerFactory.java0000644000175000017500000000354410435147724030023 0ustar adrianadrian/* * File : TRTrackerClientFactory.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.client; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerAnnouncerFactoryImpl; public class TRTrackerAnnouncerFactory { public static TRTrackerAnnouncer create( TOTorrent torrent ) throws TRTrackerAnnouncerException { return( create( torrent, null )); } public static TRTrackerAnnouncer create( TOTorrent torrent, boolean manual ) throws TRTrackerAnnouncerException { return( TRTrackerAnnouncerFactoryImpl.create( torrent, null, manual )); } public static TRTrackerAnnouncer create( TOTorrent torrent, String[] networks ) throws TRTrackerAnnouncerException { return( TRTrackerAnnouncerFactoryImpl.create( torrent, networks, false )); } public static void addListener( TRTrackerAnnouncerFactoryListener l ) { TRTrackerAnnouncerFactoryImpl.addListener(l); } public static void removeListener( TRTrackerAnnouncerFactoryListener l ) { TRTrackerAnnouncerFactoryImpl.removeListener(l); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/TRTrackerScraper.java0000644000175000017500000000345010207131716026125 0ustar adrianadrian/* * File : TRTrackerScraper.java * Created : 09-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.client; /** * @author parg * */ import java.net.URL; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.plugins.download.DownloadScrapeResult; public interface TRTrackerScraper { public TRTrackerScraperResponse scrape( TOTorrent torrent ); // scrape an explicit URL from the (multi-tracker) torrent's set of URLs public TRTrackerScraperResponse scrape( TOTorrent torrent, URL target_url ); public TRTrackerScraperResponse scrape( TOTorrent torrent, boolean force ); public TRTrackerScraperResponse scrape( TRTrackerAnnouncer tracker_client ); public void setScrape( TOTorrent torrent, URL url, DownloadScrapeResult result ); public void remove( TOTorrent torrent ); public void setClientResolver( TRTrackerScraperClientResolver resolver ); public void addListener( TRTrackerScraperListener l ); public void removeListener( TRTrackerScraperListener l ); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncer.java0000644000175000017500000000720211307334262026460 0ustar adrianadrian/* * File : TRTrackerClient.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.client; import java.util.Map; import java.net.URL; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.plugins.download.DownloadAnnounceResult; public interface TRTrackerAnnouncer { public final static byte AZ_TRACKER_VERSION_1 = 1; // anything before 2 ;) public final static byte AZ_TRACKER_VERSION_2 = 2; // supports azcompact public final static byte AZ_TRACKER_VERSION_3 = 3; // supports experimental alternative secret for crypto public final static byte AZ_TRACKER_VERSION_CURRENT = AZ_TRACKER_VERSION_3; public static final int REFRESH_MINIMUM_SECS = 60; public static final int DEFAULT_PEERS_TO_CACHE = 512; public static final int TS_INITIALISED = 1; public static final int TS_DOWNLOADING = 2; public static final int TS_COMPLETED = 3; public static final int TS_STOPPED = 4; public void setAnnounceDataProvider( TRTrackerAnnouncerDataProvider provider ); public TOTorrent getTorrent(); public URL getTrackerURL(); public void setTrackerURL( URL url ); public void setTrackerURLs( TOTorrentAnnounceURLSet[] sets ); public void resetTrackerUrl( boolean shuffle ); public void setIPOverride( String override ); public void cloneFrom( TRTrackerAnnouncer other ); public void clearIPOverride(); public byte[] getPeerId(); public void setRefreshDelayOverrides( int percentage ); public int getTimeUntilNextUpdate(); public int getLastUpdateTime(); public void update( boolean force ); public void complete( boolean already_reported ); public void stop( boolean for_queue ); public void destroy(); public int getStatus(); public boolean isManual(); public String getStatusString(); public TRTrackerAnnouncerResponse getLastResponse(); /** * returns a Map containing "bencoded" entries representing a cache of tracker * responses. * @return */ public Map getTrackerResponseCache(); /** * sets the response cache. This may be used by the tracker client to return peer * details when the tracker is offline * @param map */ public void setTrackerResponseCache( Map map ); /** * remove a specific entry from the cache if present * @param ip * @param tcp_port */ public void removeFromTrackerResponseCache( String ip, int tcp_port ); /** * This method forces all listeners to get an explicit "urlChanged" event to get them * to re-examine the tracker */ public void refreshListeners(); public void setAnnounceResult( DownloadAnnounceResult result ); public void addListener( TRTrackerAnnouncerListener l ); public void removeListener( TRTrackerAnnouncerListener l ); public void generateEvidence( IndentWriter writer ); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerFactoryListener.java0000644000175000017500000000211410204241606031505 0ustar adrianadrian/* * File : TRTrackerClientFactoryListener.java * Created : 04-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.client; /** * @author parg * */ public interface TRTrackerAnnouncerFactoryListener { public void clientCreated( TRTrackerAnnouncer client ); public void clientDestroyed( TRTrackerAnnouncer client ); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/util/0000755000175000017500000000000011310377634021605 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/util/TRTrackerUtilsListener.java0000644000175000017500000000207010457041776027045 0ustar adrianadrian/* * Created on 17 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.util; public interface TRTrackerUtilsListener { public void announceDetailsChanged(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/util/TRTrackerUtils.java0000644000175000017500000004222111307334262025327 0ustar adrianadrian/* * File : TRTrackerClientUtils.java * Created : 29-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.util; /** * @author parg * */ import java.util.*; import java.net.*; import java.io.*; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerAnnouncerImpl; import org.gudy.azureus2.core3.tracker.client.impl.bt.TRTrackerBTAnnouncerImpl; import org.gudy.azureus2.core3.tracker.host.TRHost; import org.gudy.azureus2.core3.util.AENetworkClassifier; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.UrlUtils; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminPropertyChangeListener; import com.aelitis.azureus.core.util.CopyOnWriteList; public class TRTrackerUtils { // author of MakeTorrent has requested we blacklist his site // as people keep embedding it as a tracker in torrents private static String[] BLACKLISTED_HOSTS = { "krypt.dyndns.org" }; private static int[] BLACKLISTED_PORTS = { 81 }; private static String tracker_ip; private static Set tracker_ip_aliases; private static Map override_map; private static String bind_ip; private static String ports_for_url; private static String ports_for_url_with_crypto; private static CopyOnWriteList listeners = new CopyOnWriteList(); private static AEThread2 listener_thread; static{ COConfigurationManager.addAndFireParameterListeners( new String[] { "Proxy.Data.Enable", "Proxy.Data.SOCKS.inform", "TCP.Listen.Port.Override", "Tracker Client No Port Announce", "network.transport.encrypted.use.crypto.port", "network.transport.encrypted.require", "network.transport.encrypted.fallback.incoming", "TCP.Listen.Port", "UDP.Listen.Port", "HTTP.Data.Listen.Port", "HTTP.Data.Listen.Port.Override", "HTTP.Data.Listen.Port.Enable", "Tracker Client Min Announce Interval" }, new ParameterListener() { public void parameterChanged( String parameterName ) { String port = computePortsForURL( false, true ); String port_with_crypto = computePortsForURL( true, false ); if ( ports_for_url != null && ( !ports_for_url.equals( port ))){ synchronized( listeners ){ // back off for a bit to prevent multiple config changes from causing // multiple firings if ( listener_thread == null ){ listener_thread = new AEThread2( "TRTrackerUtils:listener", true ) { public void run() { try{ Thread.sleep(30000); }catch( Throwable e ){ } synchronized( listeners ){ listener_thread = null; } for (Iterator it=listeners.iterator();it.hasNext();){ try{ ((TRTrackerUtilsListener)it.next()).announceDetailsChanged(); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } }; listener_thread.start(); } } } ports_for_url = port; ports_for_url_with_crypto = port_with_crypto; } }); } private static String computePortsForURL( boolean force_crypto, boolean allow_incoming ) { boolean socks_peer_inform = COConfigurationManager.getBooleanParameter("Proxy.Data.Enable")&& COConfigurationManager.getBooleanParameter("Proxy.Data.SOCKS.inform"); // we currently don't support incoming connections when SOCKs proxying allow_incoming &= !COConfigurationManager.getBooleanParameter("Tracker Client No Port Announce"); int tcp_port_num; int udp_port_num; if ( allow_incoming ){ if ( socks_peer_inform ){ tcp_port_num = 0; udp_port_num = 0; }else{ tcp_port_num = COConfigurationManager.getIntParameter( "TCP.Listen.Port" ); udp_port_num = COConfigurationManager.getIntParameter( "UDP.Listen.Port" ); } String portOverride = COConfigurationManager.getStringParameter("TCP.Listen.Port.Override"); if(! portOverride.equals("")) { try{ tcp_port_num = Integer.parseInt( portOverride ); }catch( Throwable e ){ Debug.printStackTrace(e); } } }else{ tcp_port_num = 0; udp_port_num = 0; } String port = ""; if ( force_crypto ){ port += "&requirecrypto=1"; port += "&port=0&cryptoport=" + tcp_port_num; }else{ boolean require_crypto = COConfigurationManager.getBooleanParameter( "network.transport.encrypted.require"); if ( require_crypto ){ port += "&requirecrypto=1"; }else{ port += "&supportcrypto=1"; } if ( require_crypto && (!COConfigurationManager.getBooleanParameter( "network.transport.encrypted.fallback.incoming") ) && COConfigurationManager.getBooleanParameter( "network.transport.encrypted.use.crypto.port" )){ port += "&port=0&cryptoport=" + tcp_port_num; }else{ port += "&port=" + tcp_port_num; } port += "&azudp=" + udp_port_num; // BitComet extension for no incoming connections if ( tcp_port_num == 0 ){ port += "&hide=1"; } if ( COConfigurationManager.getBooleanParameter( "HTTP.Data.Listen.Port.Enable" )){ int http_port = COConfigurationManager.getIntParameter( "HTTP.Data.Listen.Port.Override" ); if ( http_port == 0 ){ http_port = COConfigurationManager.getIntParameter( "HTTP.Data.Listen.Port" ); } port += "&azhttp=" + http_port; } } return( port ); } public static String getPublicIPOverride() { String explicit_ips = COConfigurationManager.getStringParameter( "Override Ip", "" ); if ( explicit_ips.length() > 0 ){ StringTokenizer tok = new StringTokenizer( explicit_ips, ";" ); while( tok.hasMoreTokens()){ String this_address = tok.nextToken().trim(); if ( this_address.length() > 0 ){ String cat = AENetworkClassifier.categoriseAddress( this_address ); if ( cat == AENetworkClassifier.AT_PUBLIC ){ return( this_address ); } } } } return( null ); } private static Map az_trackers = COConfigurationManager.getMapParameter( "Tracker Client AZ Instances", new HashMap()); private static Map udp_probe_results = COConfigurationManager.getMapParameter( "Tracker Client UDP Probe Results", new HashMap()); static{ COConfigurationManager.addListener( new COConfigurationListener() { public void configurationSaved() { readConfig(); } }); NetworkAdmin.getSingleton().addPropertyChangeListener( new NetworkAdminPropertyChangeListener() { public void propertyChanged( String property ) { if ( property == NetworkAdmin.PR_DEFAULT_BIND_ADDRESS ){ readConfig(); } } }); readConfig(); } static void readConfig() { tracker_ip = COConfigurationManager.getStringParameter("Tracker IP", ""); tracker_ip = UrlUtils.expandIPV6Host( tracker_ip ); String aliases = COConfigurationManager.getStringParameter("Tracker IP Aliases", ""); if ( aliases.length() > 0 ){ tracker_ip_aliases = new HashSet(); String[] bits = aliases.split(","); for (String b: bits ){ b = b.trim(); if ( b.length() > 0 ){ tracker_ip_aliases.add( b ); } } }else{ tracker_ip_aliases = null; } String override_ips = COConfigurationManager.getStringParameter("Override Ip", ""); StringTokenizer tok = new StringTokenizer( override_ips, ";" ); Map new_override_map = new HashMap(); while( tok.hasMoreTokens()){ String ip = tok.nextToken().trim(); if ( ip.length() > 0 ){ new_override_map.put( AENetworkClassifier.categoriseAddress( ip ), ip ); } } override_map = new_override_map; InetAddress bad = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress(); if ( bad == null || bad.isAnyLocalAddress()){ bind_ip = ""; }else{ bind_ip = bad.getHostAddress(); } } public static boolean isHosting( URL url_in ) { if ( tracker_ip.length() > 0 ){ String host = UrlUtils.expandIPV6Host(url_in.getHost()); boolean result = host.equalsIgnoreCase( tracker_ip ); if ( !result && tracker_ip_aliases != null ){ result = tracker_ip_aliases.contains( host ); } return( result ); }else{ return( false ); } } public static String getTrackerIP() { return( tracker_ip ); } public static boolean isTrackerEnabled() { return( getAnnounceURLs().length > 0 ); } public static URL[][] getAnnounceURLs() { String tracker_host = COConfigurationManager.getStringParameter( "Tracker IP", "" ); List urls = new ArrayList(); if ( tracker_host.length() > 0 ){ if ( COConfigurationManager.getBooleanParameter( "Tracker Port Enable")){ int port = COConfigurationManager.getIntParameter("Tracker Port", TRHost.DEFAULT_PORT ); try{ List l = new ArrayList(); l.add( new URL( "http://" + UrlUtils.convertIPV6Host( tracker_host ) + ":" + port + "/announce" )); List ports = stringToPorts( COConfigurationManager.getStringParameter("Tracker Port Backups" )); for (int i=0;i 0 ){ String address_type = AENetworkClassifier.categoriseAddress( host_in ); String target_ip = (String)override_map.get( address_type ); if ( target_ip == null ){ target_ip = tracker_ip; } if ( isLoopback( host_in )){ return( target_ip ); } } return( host_in ); } public static boolean isLoopback( String host ) { return( host.equals( "127.0.0.1" ) || host.equals( "0:0:0:0:0:0:0:1" ) || host.equals( "::1" ) || host.equals( bind_ip )); } public static void checkForBlacklistedURLs( URL url ) throws IOException { for (int i=0;i 512 ){ udp_probe_results.clear(); } udp_probe_results.put( key, new Long( SystemTime.getCurrentTime())); changed = true; } }else{ if ( !probe_ok ){ if ( udp_probe_results.remove( key ) != null ){ changed = true; } } } if ( changed ){ COConfigurationManager.setParameter( "Tracker Client UDP Probe Results", udp_probe_results ); } } } public static void addListener( TRTrackerUtilsListener l ) { listeners.add( l ); } public static void removeListener( TRTrackerUtilsListener l ) { listeners.remove( l ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/0000755000175000017500000000000011310377634021605 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHost.java0000644000175000017500000000555011223045274023633 0ustar adrianadrian/* * File : TRHost.java * Created : 24-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host; /** * @author parg */ import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.tracker.server.*; public interface TRHost { public static final int DEFAULT_MIN_RETRY_DELAY = TRTrackerServer.DEFAULT_MIN_RETRY_DELAY; public static final int DEFAULT_MAX_RETRY_DELAY = TRTrackerServer.DEFAULT_MAX_RETRY_DELAY; public static final int DEFAULT_INC_BY = TRTrackerServer.DEFAULT_INC_BY; public static final int DEFAULT_INC_PER = TRTrackerServer.DEFAULT_INC_PER; public static final int DEFAULT_SCRAPE_RETRY_PERCENTAGE = TRTrackerServer.DEFAULT_SCRAPE_RETRY_PERCENTAGE; public static final int DEFAULT_SCRAPE_CACHE_PERIOD = TRTrackerServer.DEFAULT_SCRAPE_CACHE_PERIOD; public static final int DEFAULT_ANNOUNCE_CACHE_PERIOD = TRTrackerServer.DEFAULT_ANNOUNCE_CACHE_PERIOD; public static final int DEFAULT_ANNOUNCE_CACHE_PEER_THRESHOLD = TRTrackerServer.DEFAULT_ANNOUNCE_CACHE_PEER_THRESHOLD; public static final int DEFAULT_PORT = TRTrackerServer.DEFAULT_TRACKER_PORT; public static final int DEFAULT_PORT_SSL = TRTrackerServer.DEFAULT_TRACKER_PORT_SSL; public void initialise( TRHostTorrentFinder finder ); public String getName(); public TRHostTorrent hostTorrent( TOTorrent torrent, boolean persistent, boolean passive ) throws TRHostException; public TRHostTorrent publishTorrent( TOTorrent torrent ) throws TRHostException; public TRHostTorrent[] getTorrents(); /** * returns the host torrent for the torrent if it exists, null otherwise * @param torrent * @return */ public TRHostTorrent getHostTorrent( TOTorrent torrent ); public void addListener( TRHostListener l ); public void removeListener( TRHostListener l ); public void addListener2( TRHostListener2 l ); public void removeListener2( TRHostListener2 l ); public void addAuthenticationListener( TRHostAuthenticationListener l ); public void removeAuthenticationListener( TRHostAuthenticationListener l ); public void close(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHostTorrent.java0000644000175000017500000000600511070576746025222 0ustar adrianadrian/* * File : TRHostTorrent.java * Created : 26-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host; /** * @author parg * */ import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.tracker.server.TRTrackerServerTorrent; public interface TRHostTorrent { public static final int TS_FAILED = 0; public static final int TS_STOPPED = 1; public static final int TS_STARTED = 2; public static final int TS_PUBLISHED = 3; public void start(); public void stop(); public void remove() throws TRHostTorrentRemovalVetoException; /** * doesn't guarantee that removal will be successful as conditions may change * @return true if OK, exception thrown otherwise * @throws TRHostTorrentRemovalVetoException */ public boolean canBeRemoved() throws TRHostTorrentRemovalVetoException; public int getStatus(); public boolean isPersistent(); public boolean isPassive(); public void setPassive( boolean passive ); public long getDateAdded(); public TOTorrent getTorrent(); public TRTrackerServerTorrent getTrackerTorrent(); public int getPort(); public TRHostPeer[] getPeers(); public int getSeedCount(); public int getLeecherCount(); public int getBadNATCount(); public long getAnnounceCount(); public long getAverageAnnounceCount(); public long getScrapeCount(); public long getAverageScrapeCount(); public long getCompletedCount(); public long getTotalUploaded(); public long getTotalDownloaded(); public long getTotalLeft(); public long getAverageUploaded(); public long getAverageDownloaded(); public long getTotalBytesIn(); public long getAverageBytesIn(); public long getTotalBytesOut(); public long getAverageBytesOut(); public void disableReplyCaching(); public void addListener( TRHostTorrentListener l ); public void removeListener( TRHostTorrentListener l ); public void addRemovalListener( TRHostTorrentWillBeRemovedListener l ); public void removeRemovalListener( TRHostTorrentWillBeRemovedListener l ); /** To retreive arbitrary objects against this object. */ public Object getData (String key); /** To store arbitrary objects against this object. */ public void setData (String key, Object value); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHostTorrentWillBeRemovedListener.java0000644000175000017500000000207510004100472031323 0ustar adrianadrian/* * File : TRHostTorrentWillBeRemovedListener.java * Created : 22-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host; /** * @author parg * */ public interface TRHostTorrentWillBeRemovedListener { public void torrentWillBeRemoved( TRHostTorrent torrent ) throws TRHostTorrentRemovalVetoException; } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHostFactory.java0000644000175000017500000000204310060105574025153 0ustar adrianadrian/* * File : TRHostFactory.java * Created : 24-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host; /** * @author parg */ import org.gudy.azureus2.core3.tracker.host.impl.*; public class TRHostFactory { public static TRHost getSingleton() { return( TRHostImpl.create()); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHostTorrentRemovalVetoException.java0000644000175000017500000000206011012742266031246 0ustar adrianadrian/* * File : TRHostTorrentRemovalVetoException.java * Created : 22-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host; /** * @author parg * */ public class TRHostTorrentRemovalVetoException extends Exception { public TRHostTorrentRemovalVetoException( String str ) { super( str ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHostException.java0000644000175000017500000000211711012742266025507 0ustar adrianadrian/* * File : TRHostException.java * Created : 05-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host; /** * @author parg * */ public class TRHostException extends Exception { public TRHostException( String str ) { super( str ); } public TRHostException( String str, Throwable e ) { super( str, e ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/impl/0000755000175000017500000000000011310377634022546 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentHostImpl.java0000644000175000017500000003444411070576746027653 0ustar adrianadrian/* * File : TRHostTorrentImpl.java * Created : 26-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host.impl; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.core3.tracker.server.*; import org.gudy.azureus2.core3.torrent.*; public class TRHostTorrentHostImpl implements TRHostTorrent { private TRHostImpl host; private TRTrackerServer server; private TRTrackerServerTorrent server_torrent; private TOTorrent torrent; private long date_added; private int port; private List listeners_cow = new ArrayList(); private List removal_listeners = new ArrayList(); private int status = TS_STOPPED; private boolean persistent; private boolean passive; private long sos_uploaded; private long sos_downloaded; private long sos_bytes_in; private long sos_bytes_out; private long sos_announce; private long sos_scrape; private long sos_complete; private long last_uploaded; private long last_downloaded; private long last_bytes_in; private long last_bytes_out; private long last_announce; private long last_scrape; //average over 10 periods, update every period. private Average average_uploaded = Average.getInstance(TRHostImpl.STATS_PERIOD_SECS*1000,TRHostImpl.STATS_PERIOD_SECS*10); private Average average_downloaded = Average.getInstance(TRHostImpl.STATS_PERIOD_SECS*1000,TRHostImpl.STATS_PERIOD_SECS*10); private Average average_bytes_in = Average.getInstance(TRHostImpl.STATS_PERIOD_SECS*1000,TRHostImpl.STATS_PERIOD_SECS*10); private Average average_bytes_out = Average.getInstance(TRHostImpl.STATS_PERIOD_SECS*1000,TRHostImpl.STATS_PERIOD_SECS*10); private Average average_announce = Average.getInstance(TRHostImpl.STATS_PERIOD_SECS*1000,TRHostImpl.STATS_PERIOD_SECS*10); private Average average_scrape = Average.getInstance(TRHostImpl.STATS_PERIOD_SECS*1000,TRHostImpl.STATS_PERIOD_SECS*10); private boolean disable_reply_caching; private HashMap data; protected AEMonitor this_mon = new AEMonitor( "TRHostTorrentHost" ); protected TRHostTorrentHostImpl( TRHostImpl _host, TRTrackerServer _server, TOTorrent _torrent, int _port, long _date_added ) { host = _host; server = _server; torrent = _torrent; port = _port; date_added = _date_added; } public int getPort() { return( port ); } public void start() { // there's a potential deadlock situation if we call the server while holding // the torrent lock, as the server then calls back to the host and we get // a torrent -> host monitor chain. We already have a host->torrent chain. // easiest solution is to delegate call to the host, which will grab the host // monitor and then call back out to startSupport. Hence the chain is in the // right direction host.startTorrent( this ); } protected void startSupport() { try{ this_mon.enter(); // System.out.println( "TRHostTorrentHostImpl::start"); status = TS_STARTED; server_torrent = server.permit( "", torrent.getHash(), true); if ( disable_reply_caching ){ server_torrent.disableCaching(); } }catch( Throwable e ){ Debug.printStackTrace( e ); }finally{ this_mon.exit(); } host.hostTorrentStateChange( this ); } public void stop() { host.stopTorrent( this ); } protected void stopSupport() { try{ this_mon.enter(); // System.out.println( "TRHostTorrentHostImpl::stop"); status = TS_STOPPED; server.deny( torrent.getHash(), true); TRTrackerServerTorrent st = server_torrent; TRTrackerServerTorrentStats torrent_stats = st==null?null:st.getStats(); if ( torrent_stats != null ){ sos_uploaded = sos_uploaded + torrent_stats.getUploaded(); sos_downloaded = sos_downloaded + torrent_stats.getDownloaded(); sos_bytes_in = sos_bytes_in + torrent_stats.getBytesIn(); sos_bytes_out = sos_bytes_out + torrent_stats.getBytesOut(); sos_announce = sos_announce + torrent_stats.getAnnounceCount(); sos_scrape = sos_scrape + torrent_stats.getScrapeCount(); sos_complete = sos_complete + torrent_stats.getCompletedCount(); torrent_stats = null; } last_uploaded = 0; last_downloaded = 0; last_bytes_in = 0; last_bytes_out = 0; last_announce = 0; last_scrape = 0; }catch( Throwable e ){ Debug.printStackTrace( e ); }finally{ this_mon.exit(); } host.hostTorrentStateChange( this ); } public void remove() throws TRHostTorrentRemovalVetoException { canBeRemoved(); stop(); host.remove( this ); } public boolean canBeRemoved() throws TRHostTorrentRemovalVetoException { ArrayList listeners_copy; try{ this_mon.enter(); listeners_copy = new ArrayList( removal_listeners ); }finally{ this_mon.exit(); } for (int i=0;i 0 ){ synchronized( saved_stats_to_delete ){ Map saved_stats_copy = new HashMap( saved_stats ); for (int i=0;i 0 ){ try{ String timeStamp = "["+new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss").format(new Date())+"] "; PrintWriter pw = null; File file_name = new File( log_dir.concat(File.separator).concat(LOG_FILE_NAME) ); try{ pw = new PrintWriter(new FileWriter( file_name, true )); for (int i=0;i listeners = ListenerManager.createAsyncManager( "TRHost:ListenDispatcher", new ListenerManagerDispatcher() { public void dispatch( TRHostListener _listener, int type, Object value ) { TRHostListener target = (TRHostListener)_listener; if ( type == LDT_TORRENT_ADDED ){ target.torrentAdded((TRHostTorrent)value); }else if ( type == LDT_TORRENT_REMOVED ){ target.torrentRemoved((TRHostTorrent)value); }else if ( type == LDT_TORRENT_CHANGED ){ target.torrentChanged((TRHostTorrent)value); } } }); private CopyOnWriteList listeners2 = new CopyOnWriteList(); private static boolean host_add_announce_urls; static{ COConfigurationManager.addAndFireParameterListener( "Tracker Host Add Our Announce URLs", new ParameterListener() { public void parameterChanged( String name ) { host_add_announce_urls = COConfigurationManager.getBooleanParameter( name ); } }); } private List auth_listeners = new ArrayList(); private boolean server_factory_listener_added; protected AEMonitor this_mon = new AEMonitor( "TRHost" ); private volatile boolean closed; public static TRHost create() { try{ class_mon.enter(); if ( singleton == null ){ singleton = new TRHostImpl(); } return( singleton ); }finally{ class_mon.exit(); } } protected TRHostImpl() { // we need to synchronize this so that the async (possible) establishment of // a server within the stats loop (to deal with public trackers with no locally // hosted torrents) doesn't get ahead of the reading of persisted torrents // If we allow the server to start early then it can potentially receive an // announce/scrape and result in the creation of an "external" torrent when // it should really be using an existing torrent try{ this_mon.enter(); config = new TRHostConfigImpl(this); TRTrackerAnnouncerFactory.addListener( this ); Thread t = new AEThread("TRHost::stats.loop") { private int tick_count = 0; private Set failed_ports = new HashSet(); public void runSupport() { while(true){ try{ URL[][] url_sets = TRTrackerUtils.getAnnounceURLs(); for (int i=0;i 0 && !announce_url.getHost().equalsIgnoreCase( tracker_ip )){ if ( ssl ){ port = COConfigurationManager.getIntParameter("Tracker Port SSL", TRHost.DEFAULT_PORT_SSL ); }else{ port = COConfigurationManager.getIntParameter("Tracker Port", TRHost.DEFAULT_PORT ); } } } if ( port == -1 ){ port = ssl?URL_DEFAULT_PORT_SSL:URL_DEFAULT_PORT; } } TRTrackerServer server = startServer( protocol, port, ssl ); TRHostTorrent host_torrent; if ( state == TRHostTorrent.TS_PUBLISHED ){ TRHostTorrentPublishImpl new_torrent = new TRHostTorrentPublishImpl( this, torrent, date_added ); new_torrent.setPersistent( persistent ); host_torrent = new_torrent; }else{ TRHostTorrentHostImpl new_torrent = new TRHostTorrentHostImpl( this, server, torrent, port, date_added ); new_torrent.setPersistent( persistent ); new_torrent.setPassive( passive ); host_torrent = new_torrent; } host_torrents.add( host_torrent ); try{ host_torrent_hash_map.put( new HashWrapper( torrent.getHash()), host_torrent ); }catch( TOTorrentException e ){ Debug.printStackTrace( e ); } host_torrent_map.put( torrent, host_torrent ); if ( state != TRHostTorrent.TS_PUBLISHED ){ startHosting((TRHostTorrentHostImpl)host_torrent ); if ( state == TRHostTorrent.TS_STARTED ){ host_torrent.start(); } // if not persistent, see if we can recover the stats if ( !persistent ){ config.recoverStats( (TRHostTorrentHostImpl)host_torrent ); } } listeners.dispatch( LDT_TORRENT_ADDED, host_torrent ); config.saveRequired(); return( host_torrent ); }finally{ this_mon.exit(); } } protected TRTrackerServer startServer( int protocol, int port, boolean ssl ) throws TRHostException { try{ this_mon.enter(); String key = ""+protocol+ ":" + port; TRTrackerServer server = (TRTrackerServer)server_map.get( key ); if ( server == null ){ try{ if ( ssl ){ server = TRTrackerServerFactory.createSSL( "tracker", protocol, port, true, true ); }else{ server = TRTrackerServerFactory.create( "tracker", protocol, port, true, true ); } server_map.put( key, server ); if ( auth_listeners.size() > 0 ){ server.addAuthenticationListener( this ); } server.addListener( this ); server.addListener2( this ); }catch( TRTrackerServerException e ){ throw( new TRHostException( "startServer failed", e )); } } return( server ); }finally{ this_mon.exit(); } } protected TRHostTorrent lookupHostTorrent( TOTorrent torrent ) { if (torrent == null) return null; try{ return((TRHostTorrent)host_torrent_hash_map.get( torrent.getHashWrapper())); }catch( TOTorrentException e ){ Debug.printStackTrace( e ); } return( null ); } protected void startHosting( TRHostTorrentHostImpl host_torrent ) { TOTorrent torrent = host_torrent.getTorrent(); TRTrackerAnnouncer tc = (TRTrackerAnnouncer)tracker_client_map.get( torrent ); if ( tc != null ){ startHosting( host_torrent, tc ); } } protected void startHosting( TRTrackerAnnouncer tracker_client ) { TRHostTorrent host_torrent = (TRHostTorrent)host_torrent_map.get( tracker_client.getTorrent()); if ( host_torrent instanceof TRHostTorrentHostImpl ){ startHosting( (TRHostTorrentHostImpl)host_torrent, tracker_client ); } } protected void startHosting( TRHostTorrentHostImpl host_torrent, final TRTrackerAnnouncer tracker_client ) { final TOTorrent torrent = host_torrent.getTorrent(); // set the ip override so that we announce ourselves to other peers via the // real external address, not the local one used to connect to the tracker URL announce = torrent.getAnnounceURL(); if ( host_add_announce_urls ){ tracker_client.setIPOverride( announce.getHost()); }else{ // prolly a backup tracker, we only want to override the IP if we're hosting it if ( TRTrackerUtils.isHosting( announce )){ tracker_client.setIPOverride( announce.getHost()); } } // hook into the client so that when the announce succeeds after the refresh below // we can force a rescrape to pick up the new status TRTrackerAnnouncerListener listener = new TRTrackerAnnouncerListener() { public void receivedTrackerResponse( TRTrackerAnnouncerResponse response ) { try{ TRTrackerScraperFactory.getSingleton().scrape( torrent, true ); }finally{ tracker_client.removeListener( this ); } } public void urlChanged( TRTrackerAnnouncer announcer, URL old_url, URL new_url, boolean explicit ) { } public void urlRefresh() { } }; tracker_client.addListener(listener); tracker_client.refreshListeners(); } protected void remove( TRHostTorrent host_torrent ) { try{ this_mon.enter(); if ( !host_torrents.contains( host_torrent )){ return; } host_torrents.remove( host_torrent ); TOTorrent torrent = host_torrent.getTorrent(); try{ host_torrent_hash_map.remove(new HashWrapper(torrent.getHash())); }catch( TOTorrentException e ){ Debug.printStackTrace( e ); } host_torrent_map.remove( torrent ); if ( host_torrent instanceof TRHostTorrentHostImpl ){ stopHosting((TRHostTorrentHostImpl)host_torrent ); } listeners.dispatch( LDT_TORRENT_REMOVED, host_torrent ); // this'll get saved sometime soon anyway - performance problems // here when removing multiple torrents from a large set (e.g. 1000) // config.saveConfig(); }finally{ this_mon.exit(); } } protected void stopHosting( TRHostTorrentHostImpl host_torrent ) { TOTorrent torrent = host_torrent.getTorrent(); TRTrackerAnnouncer tc = (TRTrackerAnnouncer)tracker_client_map.get( torrent ); if ( tc != null ){ stopHosting( host_torrent, tc ); } } protected void stopHosting( TRTrackerAnnouncer tracker_client ) { TRHostTorrent host_torrent = (TRHostTorrent)host_torrent_map.get( tracker_client.getTorrent()); if ( host_torrent instanceof TRHostTorrentHostImpl ){ // we only "connect" the announcer and the hosted torrent if it isn't passive. This allows // us to make a torrent passive without losing the tracker stats by // 1) making it passive // 2) removing the Download //if ( !host_torrent.isPassive()){ stopHosting( (TRHostTorrentHostImpl)host_torrent, tracker_client ); //} } } protected void stopHosting( final TRHostTorrentHostImpl host_torrent, final TRTrackerAnnouncer tracker_client ) { // unfortunately a lot of the "stop" operations that occur when a tracker client // connection is closed happen async. In particular the "stopped" message to the // tracker. Hence, if we switch the URL back here the "stopped" doesn't get // through. // for the moment stick a delay in to allow any async stuff to complete Thread thread = new AEThread("StopHosting") { public void runSupport() { try{ Thread.sleep(2500); }catch( InterruptedException e ){ } try{ this_mon.enter(); // got to look up the host torrent again as may have been // removed and re-added TRHostTorrent ht = lookupHostTorrent( host_torrent.getTorrent()); // check it's still in stopped state and hasn't been restarted if ( ht == null || ( ht == host_torrent && ht.getStatus() == TRHostTorrent.TS_STOPPED )){ tracker_client.clearIPOverride(); } }finally{ this_mon.exit(); } } }; thread.setDaemon(true); thread.start(); } protected TRTrackerAnnouncer getTrackerClient( TRHostTorrent host_torrent ) { try{ this_mon.enter(); return((TRTrackerAnnouncer)tracker_client_map.get( host_torrent.getTorrent())); }finally{ this_mon.exit(); } } protected void hostTorrentStateChange( TRHostTorrent host_torrent ) { try{ this_mon.enter(); TOTorrent torrent = host_torrent.getTorrent(); TRTrackerAnnouncer tc = (TRTrackerAnnouncer)tracker_client_map.get( torrent ); if ( tc != null ){ tc.refreshListeners(); } // config will get saved soon anyway (periodic or on closedown) - perf issues // here with multiple torrent removal if we save each time // config.saveConfig(); }finally{ this_mon.exit(); } } public TRHostTorrent[] getTorrents() { try{ this_mon.enter(); TRHostTorrent[] res = new TRHostTorrent[host_torrents.size()]; host_torrents.toArray( res ); return( res ); }finally{ this_mon.exit(); } } public void clientCreated( TRTrackerAnnouncer client ) { try{ this_mon.enter(); tracker_client_map.put( client.getTorrent(), client ); startHosting( client ); }finally{ this_mon.exit(); } } public void clientDestroyed( TRTrackerAnnouncer client ) { try{ this_mon.enter(); tracker_client_map.remove( client.getTorrent()); stopHosting( client ); }finally{ this_mon.exit(); } } protected TRHostTorrent lookupHostTorrentViaHash( byte[] hash ) { return((TRHostTorrent)host_torrent_hash_map.get(new HashWrapper(hash))); } // reports from TRTrackerServer regarding state of hashes // if we get a "permitted" event for a torrent we know nothing about // the the server is allowing public hosting and this is a new hash // create an 'external' entry for it public boolean permitted( String originator, byte[] hash, boolean explicit ) { try{ this_mon.enter(); TRHostTorrent ht = lookupHostTorrentViaHash( hash ); if ( ht != null ){ if ( !explicit ){ if ( ht.getStatus() != TRHostTorrent.TS_STARTED ){ return( false ); } } return( true ); } addExternalTorrent( hash, TRHostTorrent.TS_STARTED, SystemTime.getCurrentTime()); return( true ); }finally{ this_mon.exit(); } } protected void addExternalTorrent( byte[] hash, int state, long date_added ) { try{ this_mon.enter(); if ( lookupHostTorrentViaHash( hash ) != null ){ return; } String tracker_ip = COConfigurationManager.getStringParameter("Tracker IP", "127.0.0.1"); // external torrents don't care whether ssl or not so just assume non-ssl for simplicity int port = COConfigurationManager.getIntParameter("Tracker Port", TRHost.DEFAULT_PORT ); try{ TOTorrent external_torrent = new TRHostExternalTorrent(hash, new URL( "http://" + UrlUtils.convertIPV6Host(tracker_ip) + ":" + port + "/announce")); addTorrent( external_torrent, state, true, false, date_added ); }catch( Throwable e ){ Debug.printStackTrace( e ); } }finally{ this_mon.exit(); } } public boolean denied( byte[] hash, boolean permitted ) { return( true ); } public boolean handleExternalRequest( InetSocketAddress client_address, String user, String url, URL absolute_url, String header, InputStream is, OutputStream os, AsyncController async ) throws IOException { List listeners_copy = listeners.getListenersCopy(); for (int i=0;i it = listeners2.iterator(); while( it.hasNext()){ try{ if ( it.next().handleExternalRequest(request)){ return( true ); } }catch( Throwable e ){ Debug.out( e ); } } return( false ); } public TRHostTorrent getHostTorrent( TOTorrent torrent ) { return( lookupHostTorrent( torrent )); } public void addListener( TRHostListener l ) { try{ this_mon.enter(); listeners.addListener( l ); for (int i=0;i=0;i--){ String url_str = primary_urls[i].toString(); if ( TorrentUtils.announceGroupsContainsURL( torrent, url_str )){ TorrentUtils.announceGroupsSetFirst( torrent, url_str ); }else{ TorrentUtils.announceGroupsInsertFirst( torrent, url_str ); } } } } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/impl/TRHostPeerHostImpl.java0000644000175000017500000000325310542072476027075 0ustar adrianadrian/* * File : TRHostPeerImpl.java * Created : 31-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host.impl; /** * @author parg */ import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.core3.tracker.server.*; public class TRHostPeerHostImpl implements TRHostPeer { protected TRTrackerServerPeer peer; protected TRHostPeerHostImpl( TRTrackerServerPeer _peer ) { peer = _peer; } public boolean isSeed() { return( getAmountLeft() == 0 ); } public long getUploaded() { return( peer.getUploaded()); } public long getDownloaded() { return( peer.getDownloaded()); } public long getAmountLeft() { return( peer.getAmountLeft()); } public String getIP() { return( peer.getIP()); } public String getIPRaw() { return( peer.getIPRaw()); } public int getPort() { return( peer.getTCPPort()); } public byte[] getPeerID() { return( peer.getPeerID()); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/impl/TRHostExternalTorrent.java0000644000175000017500000001617411270516754027671 0ustar adrianadrian/* * File : TRHostExternalTorrent.java * Created : 19-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host.impl; /** * @author parg * */ import java.util.*; import java.net.*; import java.io.*; import org.gudy.azureus2.core3.internat.*; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.util.*; public class TRHostExternalTorrent implements TOTorrent { private byte[] name; private byte[] hash; private HashWrapper hash_wrapper; private URL announce_url; protected Map additional_properties = new HashMap(); protected AEMonitor this_mon = new AEMonitor( "TRHostExternalTorrent" ); protected TRHostExternalTorrent( byte[] _hash, URL _announce_url ) { hash = _hash; hash_wrapper = new HashWrapper( hash ); announce_url = _announce_url; name = ByteFormatter.nicePrint( hash, true ).getBytes(); try{ LocaleTorrentUtil.setDefaultTorrentEncoding( this ); }catch( LocaleUtilEncodingException e ){ Debug.printStackTrace( e ); } } public byte[] getName() { return( name ); } public boolean isSimpleTorrent() { return( true ); } public byte[] getComment() { return( null ); } public void setComment( String comment ) { } public long getCreationDate() { return(0); } public void setCreationDate( long date ) { } public byte[] getCreatedBy() { return( null ); } public void setCreatedBy( byte[] cb ) { } public boolean isCreated() { return( false ); } public URL getAnnounceURL() { return( announce_url ); } public boolean setAnnounceURL( URL url ) { return false; } public TOTorrentAnnounceURLGroup getAnnounceURLGroup() { return( new TOTorrentAnnounceURLGroup() { public TOTorrentAnnounceURLSet[] getAnnounceURLSets() { return( new TOTorrentAnnounceURLSet[0] ); } public void setAnnounceURLSets( TOTorrentAnnounceURLSet[] sets ) { } public TOTorrentAnnounceURLSet createAnnounceURLSet( URL[] urls ) { return( new TOTorrentAnnounceURLSet() { public URL[] getAnnounceURLs() { return( new URL[0]); } public void setAnnounceURLs( URL[] urls ) { } }); } }); } public void addTorrentAnnounceURLSet( URL[] urls ) { } public byte[][] getPieces() { return( new byte[0][] ); } public void setPieces( byte[][] b ) { } public int getNumberOfPieces() { return( 0); } public long getPieceLength() { return( -1 ); } public long getSize() { return( -1 ); } public TOTorrentFile[] getFiles() { return( new TOTorrentFile[0]); } public byte[] getHash() throws TOTorrentException { return( hash ); } public HashWrapper getHashWrapper() throws TOTorrentException { return( hash_wrapper ); } public void setHashOverride( byte[] hash ) throws TOTorrentException { throw( new TOTorrentException( "Not supported", TOTorrentException.RT_HASH_FAILS )); } public boolean getPrivate() { return( false ); } public void setPrivate( boolean _private ) throws TOTorrentException { } public boolean hasSameHashAs( TOTorrent other ) { try{ byte[] other_hash = other.getHash(); return( Arrays.equals( hash, other_hash )); }catch( TOTorrentException e ){ Debug.printStackTrace( e ); return( false ); } } public void setAdditionalStringProperty( String name, String value ) { try{ additional_properties.put(name,value.getBytes(Constants.DEFAULT_ENCODING)); }catch( Throwable e ){ Debug.printStackTrace( e ); } } public String getAdditionalStringProperty( String name ) { try{ Object obj = additional_properties.get(name); if ( obj == null ){ return( null ); } if ( !( obj instanceof byte[] )){ Debug.out( "property '" + name + "' is not a byte[]: " + obj ); return( null ); } return( new String((byte[])obj,Constants.DEFAULT_ENCODING)); }catch( Throwable e ){ Debug.printStackTrace( e ); return( null ); } } public void setAdditionalByteArrayProperty( String name, byte[] value ) { additional_properties.put(name,value); } public byte[] getAdditionalByteArrayProperty( String name ) { return( (byte[])additional_properties.get(name)); } public void setAdditionalLongProperty( String name, Long value ) { additional_properties.put(name,value); } public void setAdditionalProperty( String name, Object value ) { if ( value instanceof String ){ setAdditionalStringProperty(name,(String)value); }else{ additional_properties.put( name, value ); } } public Long getAdditionalLongProperty( String name ) { return((Long)additional_properties.get(name)); } public void setAdditionalListProperty( String name, List value ) { additional_properties.put(name,value); } public List getAdditionalListProperty( String name ) { return((List)additional_properties.get(name)); } public void setAdditionalMapProperty( String name, Map value ) { additional_properties.put(name,value); } public Map getAdditionalMapProperty( String name ) { return( (Map)additional_properties.get(name)); } public Object getAdditionalProperty( String name ) { return( additional_properties.get(name)); } public void removeAdditionalProperty( String name ) { additional_properties.remove( name ); } public void removeAdditionalProperties() { additional_properties.clear(); } public void serialiseToBEncodedFile( File file ) throws TOTorrentException { throw( new TOTorrentException("External Torrent", TOTorrentException.RT_WRITE_FAILS )); } public Map serialiseToMap() throws TOTorrentException { throw( new TOTorrentException("External Torrent", TOTorrentException.RT_WRITE_FAILS )); } public void serialiseToXMLFile( File file ) throws TOTorrentException { throw( new TOTorrentException("External Torrent", TOTorrentException.RT_WRITE_FAILS )); } public AEMonitor getMonitor() { return( this_mon ); } public void print() { } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentRequestImpl.java0000644000175000017500000000365010221672464030350 0ustar adrianadrian/* * File : TRHostTorrentRequestImpl.java * Created : 13-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host.impl; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.core3.tracker.server.*; public class TRHostTorrentRequestImpl implements TRHostTorrentRequest { protected TRHostTorrent torrent; protected TRHostPeer peer; protected TRTrackerServerRequest request; protected TRHostTorrentRequestImpl( TRHostTorrent _torrent, TRHostPeer _peer, TRTrackerServerRequest _request ) { torrent = _torrent; peer = _peer; request = _request; } public TRHostPeer getPeer() { return( peer ); } public TRHostTorrent getTorrent() { return( torrent ); } public int getRequestType() { if ( request.getType() == TRTrackerServerRequest.RT_ANNOUNCE ){ return( RT_ANNOUNCE ); }else if ( request.getType() == TRTrackerServerRequest.RT_SCRAPE ){ return( RT_SCRAPE ); }else{ return( RT_FULL_SCRAPE ); } } public String getRequest() { return( request.getRequest()); } public Map getResponse() { return( request.getResponse()); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/impl/TRHostPeerPublishImpl.java0000644000175000017500000000306210433237714027561 0ustar adrianadrian/* * File : TRHostPeerPublishImpl.java * Created : 12-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host.impl; /** * @author parg * */ import org.gudy.azureus2.core3.tracker.host.*; public class TRHostPeerPublishImpl implements TRHostPeer { protected boolean seed; protected TRHostPeerPublishImpl( boolean _seed ) { seed =_seed; } public boolean isSeed() { return( seed ); } public long getUploaded() { return( 0 ); } public long getDownloaded() { return( 0 ); } public long getAmountLeft() { return( 0 ); } public int getNumberOfPeers() { return( 0 ); } public String getIP() { return(""); } public String getIPRaw() { return(""); } public int getPort() { return( 0 ); } public byte[] getPeerID() { return( null ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHostTorrentFinder.java0000644000175000017500000000202307752623220026336 0ustar adrianadrian/* * File : TRHostTorrentFinder.java * Created : 06-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host; /** * @author parg * */ import org.gudy.azureus2.core3.torrent.*; public interface TRHostTorrentFinder { public TOTorrent lookupTorrent( byte[] hash ); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHostListener2.java0000644000175000017500000000211111223045274025411 0ustar adrianadrian/* * Created on Jul 1, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.core3.tracker.host; import java.io.IOException; import org.gudy.azureus2.core3.tracker.server.TRTrackerServerListener2; public interface TRHostListener2 { public boolean handleExternalRequest( TRTrackerServerListener2.ExternalRequest request ) throws IOException; } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHostTorrentRequest.java0000644000175000017500000000236610221672464026570 0ustar adrianadrian/* * File : TRHostServerRequest.java * Created : 13-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host; /** * @author parg * */ import java.util.Map; public interface TRHostTorrentRequest { public static final int RT_ANNOUNCE = 1; public static final int RT_SCRAPE = 2; public static final int RT_FULL_SCRAPE = 3; public TRHostPeer getPeer(); public TRHostTorrent getTorrent(); public int getRequestType(); public String getRequest(); public Map getResponse(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHostTorrentListener.java0000644000175000017500000000214710221666410026714 0ustar adrianadrian/* * File : TRHostTorrentListener.java * Created : 13-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host; /** * @author parg * */ public interface TRHostTorrentListener { public void preProcess( TRHostTorrentRequest request ) throws TRHostException; public void postProcess( TRHostTorrentRequest request ) throws TRHostException; }azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHostAuthenticationListener.java0000644000175000017500000000236010373051024030230 0ustar adrianadrian/* * Created on 10-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.host; /** * @author parg * */ import java.net.URL; public interface TRHostAuthenticationListener { public boolean authenticate( URL resource, String user, String password ); public byte[] authenticate( URL resource, String user ); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHostListener.java0000644000175000017500000000270411062635752025346 0ustar adrianadrian/* * File : TRHostListener.java * Created : 30-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host; /** * @author parg * */ import java.io.*; import java.net.InetSocketAddress; import java.net.URL; import org.gudy.azureus2.core3.util.AsyncController; public interface TRHostListener { public void torrentAdded( TRHostTorrent t ); public void torrentChanged( TRHostTorrent t ); public void torrentRemoved( TRHostTorrent t ); public boolean handleExternalRequest( InetSocketAddress client_address, String user, String url, URL absolute_url, String header, InputStream is, OutputStream os, AsyncController async ) throws IOException; } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/host/TRHostPeer.java0000644000175000017500000000222010433237722024441 0ustar adrianadrian/* * File : TRHostPeer.java * Created : 26-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.host; /** * @author parg * */ public interface TRHostPeer { public boolean isSeed(); public long getUploaded(); public long getDownloaded(); public long getAmountLeft(); public String getIP(); public String getIPRaw(); public int getPort(); public byte[] getPeerID(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/protocol/0000755000175000017500000000000011310377634022471 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/protocol/udp/0000755000175000017500000000000011310377634023261 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestScrape.java0000644000175000017500000000475010750462632030663 0ustar adrianadrian/* * File : PRUDPPacketRequestScrape.java * Created : 21-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.protocol.udp; /** * @author parg * */ import java.io.*; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.gudy.azureus2.core3.util.*; import com.aelitis.net.udp.uc.PRUDPPacketRequest; public class PRUDPPacketRequestScrape extends PRUDPPacketRequest { protected List hashes; public PRUDPPacketRequestScrape( long con_id, byte[] _hash) { super( PRUDPPacketTracker.ACT_REQUEST_SCRAPE, con_id ); hashes = new ArrayList(); hashes.add(_hash); } public PRUDPPacketRequestScrape( long con_id, List hashwrappers) { super( PRUDPPacketTracker.ACT_REQUEST_SCRAPE, con_id ); hashes = new ArrayList(); for(Iterator it = hashwrappers.iterator();it.hasNext();) hashes.add(((HashWrapper)it.next()).getBytes()); } protected PRUDPPacketRequestScrape( DataInputStream is, long con_id, int trans_id ) throws IOException { super( PRUDPPacketTracker.ACT_REQUEST_SCRAPE, con_id, trans_id ); byte[] hash; while(is.read(hash = new byte[20]) == 20) hashes.add(hash); } public List getHashes() { return hashes; } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); for(Iterator it = hashes.iterator();it.hasNext();) os.write((byte[])it.next()); } public String getString() { StringBuffer buf = new StringBuffer(); buf.append(super.getString()); buf.append("["); for(Iterator it = hashes.iterator();it.hasNext();) { buf.append(ByteFormatter.nicePrint( (byte[])it.next(), true )); if(it.hasNext()) buf.append(";"); } buf.append("]"); return buf.toString(); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyAnnounce2.java0000644000175000017500000000561610357264316030745 0ustar adrianadrian/* * File : PRUDPPacketReplyAnnounce.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.protocol.udp; /** * @author parg * */ import java.io.*; import com.aelitis.net.udp.uc.PRUDPPacketReply; public class PRUDPPacketReplyAnnounce2 extends PRUDPPacketReply { protected int interval; protected int leechers; protected int seeders; protected static final int BYTES_PER_ENTRY = 6; protected int[] addresses; protected short[] ports; public PRUDPPacketReplyAnnounce2( int trans_id ) { super( PRUDPPacketTracker.ACT_REPLY_ANNOUNCE, trans_id ); } protected PRUDPPacketReplyAnnounce2( DataInputStream is, int trans_id ) throws IOException { super( PRUDPPacketTracker.ACT_REPLY_ANNOUNCE, trans_id ); interval = is.readInt(); leechers = is.readInt(); seeders = is.readInt(); addresses = new int[is.available()/BYTES_PER_ENTRY]; ports = new short[addresses.length]; for (int i=0;i __int64 m_downloaded; __int64 m_left; __int64 m_uploaded; int m_event; int m_ipa; INT KEY // V2 int m_num_want; short m_port; */ /* enum t_event { e_none, e_completed, e_started, e_stopped, }; heh 0, 1, 2, 3 */ public static final int EV_STARTED = 2; public static final int EV_STOPPED = 3; public static final int EV_COMPLETED = 1; public static final int EV_UPDATE = 0; protected byte[] hash; protected byte[] peer_id; protected long downloaded; protected int event; protected int key; protected int num_want; protected long left; protected short port; protected long uploaded; protected int ip_address; public PRUDPPacketRequestAnnounce2( long con_id ) { super( PRUDPPacketTracker.ACT_REQUEST_ANNOUNCE, con_id ); } protected PRUDPPacketRequestAnnounce2( DataInputStream is, long con_id, int trans_id ) throws IOException { super( PRUDPPacketTracker.ACT_REQUEST_ANNOUNCE, con_id, trans_id ); hash = new byte[20]; peer_id = new byte[20]; is.read( hash ); is.read( peer_id ); downloaded = is.readLong(); left = is.readLong(); uploaded = is.readLong(); event = is.readInt(); ip_address = is.readInt(); key = is.readInt(); num_want = is.readInt(); port = is.readShort(); } public byte[] getHash() { return( hash ); } public byte[] getPeerId() { return( peer_id ); } public long getDownloaded() { return( downloaded ); } public int getEvent() { return( event ); } public int getNumWant() { return( num_want ); } public long getLeft() { return( left ); } public short getPort() { return( port ); } public long getUploaded() { return( uploaded ); } public int getIPAddress() { return( ip_address ); } public int getKey() { return( key ); } public void setDetails( byte[] _hash, byte[] _peer_id, long _downloaded, int _event, int _ip_address, int _key, int _num_want, long _left, short _port, long _uploaded ) { hash = _hash; peer_id = _peer_id; downloaded = _downloaded; event = _event; ip_address = _ip_address; key = _key; num_want = _num_want; left = _left; port = _port; uploaded = _uploaded; } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); os.write( hash ); os.write( peer_id ); os.writeLong( downloaded ); os.writeLong( left ); os.writeLong( uploaded ); os.writeInt( event ); os.writeInt( ip_address ); os.writeInt( key ); os.writeInt( num_want ); os.writeShort( port ); } public String getString() { return( super.getString()).concat("[").concat( "hash="+ByteFormatter.nicePrint( hash, true )+ "peer="+ByteFormatter.nicePrint( peer_id, true )+ "dl="+downloaded+ "ev="+event+ "ip="+ip_address+ "key="+key+ "nw="+num_want+ "left="+left+ "port="+port+ "ul="+uploaded+"]"); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyScrape2.java0000644000175000017500000000555010357264316030411 0ustar adrianadrian/* * File : PRUDPPacketReplyScrape.java * Created : 21-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.protocol.udp; /** * @author parg * */ import java.io.*; import com.aelitis.net.udp.uc.PRUDPPacketReply; public class PRUDPPacketReplyScrape2 extends PRUDPPacketReply { // protected int interval; protected static final int BYTES_PER_ENTRY = 12; protected int[] complete; protected int[] incomplete; protected int[] downloaded; public PRUDPPacketReplyScrape2( int trans_id ) { super( PRUDPPacketTracker.ACT_REPLY_SCRAPE, trans_id ); } protected PRUDPPacketReplyScrape2( DataInputStream is, int trans_id ) throws IOException { super( PRUDPPacketTracker.ACT_REPLY_SCRAPE, trans_id ); // interval = is.readInt(); complete = new int[is.available()/BYTES_PER_ENTRY]; incomplete = new int[complete.length]; downloaded = new int[complete.length]; for (int i=0;i __int64 m_downloaded; __int64 m_left; __int64 m_uploaded; int m_event; int m_ipa; int m_num_want; short m_port; */ /* enum t_event { e_none, e_completed, e_started, e_stopped, }; heh 0, 1, 2, 3 */ public static final int EV_STARTED = 2; public static final int EV_STOPPED = 3; public static final int EV_COMPLETED = 1; public static final int EV_UPDATE = 0; protected byte[] hash; protected byte[] peer_id; protected long downloaded; protected int event; protected int num_want; protected long left; protected short port; protected long uploaded; protected int ip_address; public PRUDPPacketRequestAnnounce( long con_id ) { super( PRUDPPacketTracker.ACT_REQUEST_ANNOUNCE, con_id ); } protected PRUDPPacketRequestAnnounce( DataInputStream is, long con_id, int trans_id ) throws IOException { super( PRUDPPacketTracker.ACT_REQUEST_ANNOUNCE, con_id, trans_id ); hash = new byte[20]; peer_id = new byte[20]; is.read( hash ); is.read( peer_id ); downloaded = is.readLong(); left = is.readLong(); uploaded = is.readLong(); event = is.readInt(); ip_address = is.readInt(); num_want = is.readInt(); port = is.readShort(); } public byte[] getHash() { return( hash ); } public byte[] getPeerId() { return( peer_id ); } public long getDownloaded() { return( downloaded ); } public int getEvent() { return( event ); } public int getNumWant() { return( num_want ); } public long getLeft() { return( left ); } public short getPort() { return( port ); } public long getUploaded() { return( uploaded ); } public int getIPAddress() { return( ip_address ); } public void setDetails( byte[] _hash, byte[] _peer_id, long _downloaded, int _event, int _ip_address, int _num_want, long _left, short _port, long _uploaded ) { hash = _hash; peer_id = _peer_id; downloaded = _downloaded; event = _event; ip_address = _ip_address; num_want = _num_want; left = _left; port = _port; uploaded = _uploaded; } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); os.write( hash ); os.write( peer_id ); os.writeLong( downloaded ); os.writeLong( left ); os.writeLong( uploaded ); os.writeInt( event ); os.writeInt( ip_address ); os.writeInt( num_want ); os.writeShort( port ); } public String getString() { return( super.getString()).concat("[").concat( "hash=").concat(ByteFormatter.nicePrint( hash, true )).concat( "peer=").concat(ByteFormatter.nicePrint( peer_id, true )).concat( "dl=").concat(String.valueOf(downloaded)).concat( "ev=").concat(String.valueOf(event)).concat( "ip=").concat(String.valueOf(ip_address)).concat( "nw=").concat(String.valueOf(num_want)).concat( "left=").concat(String.valueOf(left)).concat( "port=").concat(String.valueOf(port)).concat( "ul=").concat(String.valueOf(uploaded)).concat("]"); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyAnnounce.java0000644000175000017500000000501410357264316030653 0ustar adrianadrian/* * File : PRUDPPacketReplyAnnounce.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.protocol.udp; /** * @author parg * */ import java.io.*; import com.aelitis.net.udp.uc.PRUDPPacketReply; public class PRUDPPacketReplyAnnounce extends PRUDPPacketReply { protected int interval; protected static final int BYTES_PER_ENTRY = 6; protected int[] addresses; protected short[] ports; public PRUDPPacketReplyAnnounce( int trans_id ) { super( PRUDPPacketTracker.ACT_REPLY_ANNOUNCE, trans_id ); } protected PRUDPPacketReplyAnnounce( DataInputStream is, int trans_id ) throws IOException { super( PRUDPPacketTracker.ACT_REPLY_ANNOUNCE, trans_id ); interval = is.readInt(); addresses = new int[is.available()/BYTES_PER_ENTRY]; ports = new short[addresses.length]; for (int i=0;i " + Integer.toHexString(resp)); return( resp ); } public static int addressToInt( InetAddress i_address ) { byte[] bytes = i_address.getAddress(); int resp = (bytes[0]<<24)&0xff000000 | (bytes[1] << 16)&0x00ff0000 | (bytes[2] << 8)&0x0000ff00 | bytes[3]&0x000000ff; // System.out.println( "addressToInt: " + address + " -> " + Integer.toHexString(resp)); return( resp ); } public static long addressToLong( InetAddress i_address ) { return(((long)addressToInt( i_address ))&0xffffffffL); } public static String intToAddress( int value ) { byte[] bytes = { (byte)(value>>24), (byte)(value>>16),(byte)(value>>8),(byte)value }; try{ String res = InetAddress.getByAddress(bytes).getHostAddress(); // System.out.println( "intToAddress: " + Integer.toHexString(value) + " -> " + res ); return( res ); }catch( UnknownHostException e ){ // should never get here as always valid byte array (4 long) Debug.printStackTrace(e); return( null ); } } public static void addressTo4ByteArray( String address, byte[] buffer, int offset ) throws UnknownHostException { InetAddress i_address = HostNameToIPResolver.syncResolve(address); byte[] bytes = i_address.getAddress(); System.arraycopy( bytes, 0, buffer, offset, 4 ); } public static String DNSToIPAddress( String dns_name ) throws UnknownHostException { return( HostNameToIPResolver.syncResolve(dns_name).getHostAddress()); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/0000755000175000017500000000000011310377634022136 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerException.java0000644000175000017500000000371611012742266027713 0ustar adrianadrian/* * File : TRTrackerServerException.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server; import java.util.Map; public class TRTrackerServerException extends Exception { private int response_code = -1; private String response_text; private Map response_headers; private boolean user_message; private Map error_map; public TRTrackerServerException( int _response_code, String _response_text, Map _response_headers ) { response_code = _response_code; response_text = _response_text; response_headers = _response_headers; } public TRTrackerServerException( String str ) { super(str); } public TRTrackerServerException( String str, Throwable e ) { super(str,e); } public int getResponseCode() { return( response_code ); } public String getResponseText() { return( response_text ); } public Map getResponseHeaders() { return( response_headers ); } public void setUserMessage( boolean b ) { user_message = b; } public boolean isUserMessage() { return( user_message ); } public void setErrorEntries( Map map ) { error_map = map; } public Map getErrorEntries() { return( error_map ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentStats.java0000644000175000017500000000266410631371610030427 0ustar adrianadrian/* * File : TRTrackerServerStats.java * Created : 31-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server; /** * @author parg */ public interface TRTrackerServerTorrentStats { public int getSeedCount(); public int getLeecherCount(); public int getQueuedCount(); public long getScrapeCount(); public long getAnnounceCount(); public long getCompletedCount(); public long getUploaded(); public long getDownloaded(); public long getBiasedUploaded(); public long getBiasedDownloaded(); public long getAmountLeft(); public long getBytesIn(); public long getBytesOut(); public int getBadNATPeerCount(); public String getString(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/0000755000175000017500000000000011310377634023077 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerSimplePeer.java0000644000175000017500000000260211147643640030761 0ustar adrianadrian/* * Created on Feb 20, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.core3.tracker.server.impl; import org.gudy.azureus2.core3.util.HashWrapper; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition; public interface TRTrackerServerSimplePeer { public byte[] getIPAsRead(); public byte[] getIPAddressBytes(); public HashWrapper getPeerId(); public int getTCPPort(); public int getUDPPort(); public int getHTTPPort(); public boolean isSeed(); public boolean isBiased(); public byte getCryptoLevel(); public byte getAZVer(); public int getUpSpeed(); public DHTNetworkPosition getNetworkPosition(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerNATChecker.java0000644000175000017500000001351410373051016030615 0ustar adrianadrian/* * Created on 29-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.server.impl; /** * @author parg * */ import java.util.*; import java.net.*; import org.gudy.azureus2.core3.tracker.server.*; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.logging.*; import com.aelitis.azureus.core.proxy.AEProxyFactory; public class TRTrackerServerNATChecker { private static final LogIDs LOGID = LogIDs.TRACKER; protected static TRTrackerServerNATChecker singleton = new TRTrackerServerNATChecker(); protected static final int THREAD_POOL_SIZE = 32; protected static final int CHECK_QUEUE_LIMIT = 2048; protected static int check_timeout = TRTrackerServer.DEFAULT_NAT_CHECK_SECS*1000; protected static TRTrackerServerNATChecker getSingleton() { return( singleton ); } protected boolean enabled; protected ThreadPool thread_pool; protected List check_queue = new ArrayList(); protected AESemaphore check_queue_sem = new AESemaphore("TracerServerNATChecker"); protected AEMonitor check_queue_mon = new AEMonitor( "TRTrackerServerNATChecker:Q" ); protected AEMonitor this_mon = new AEMonitor( "TRTrackerServerNATChecker" ); protected TRTrackerServerNATChecker() { final String enable_param = "Tracker NAT Check Enable"; final String timeout_param = "Tracker NAT Check Timeout"; final String[] params = { enable_param, timeout_param }; for (int i=0;i CHECK_QUEUE_LIMIT ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "NAT Check queue size too large, check for '" + host + ":" + port + "' skipped")); //Debug.out( "NAT Check queue size too large, check skipped" ); listener.NATCheckComplete( true ); }else{ check_queue.add( new ThreadPoolTask() { protected Socket socket; public void runSupport() { boolean ok = false; try{ InetSocketAddress address = new InetSocketAddress( AEProxyFactory.getAddressMapper().internalise(host), port ); socket = new Socket(); socket.connect( address, check_timeout ); ok = true; socket.close(); socket = null; }catch( Throwable e ){ }finally{ listener.NATCheckComplete( ok ); if ( socket != null ){ try{ socket.close(); }catch( Throwable e ){ } } } } public void interruptTask() { if ( socket != null ){ try{ socket.close(); }catch( Throwable e ){ } } } }); check_queue_sem.release(); } }finally{ check_queue_mon.exit(); } return( true ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerNatCheckerListener.java0000644000175000017500000000217410373051016032423 0ustar adrianadrian/* * Created on 29-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.server.impl; /** * @author parg * */ public interface TRTrackerServerNatCheckerListener { public void NATCheckComplete( boolean ok ); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerImpl.java0000644000175000017500000005765211223045276027630 0ustar adrianadrian/* * File : TRTrackerServerImpl.java * Created : 19-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server.impl; /** * @author parg * */ import java.util.*; import java.net.URL; import java.net.URLDecoder; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.ipfilter.*; import org.gudy.azureus2.core3.tracker.server.*; import com.aelitis.azureus.core.util.CopyOnWriteList; public abstract class TRTrackerServerImpl implements TRTrackerServer { public static final int RETRY_MINIMUM_SECS = 60; public static final int RETRY_MINIMUM_MILLIS = RETRY_MINIMUM_SECS*1000; public static final int CLIENT_TIMEOUT_MULTIPLIER = 3; public static final int TIMEOUT_CHECK = RETRY_MINIMUM_MILLIS*CLIENT_TIMEOUT_MULTIPLIER; public static int max_peers_to_send = 0; public static boolean send_peer_ids = true; public static int announce_cache_period = TRTrackerServer.DEFAULT_ANNOUNCE_CACHE_PERIOD; public static int scrape_cache_period = TRTrackerServer.DEFAULT_SCRAPE_CACHE_PERIOD; public static int announce_cache_threshold = TRTrackerServer.DEFAULT_ANNOUNCE_CACHE_PEER_THRESHOLD; public static int max_seed_retention = 0; public static int seed_limit = 0; public static boolean full_scrape_enable = true; public static boolean restrict_non_blocking_requests = true; public static boolean all_networks_permitted = true; public static String[] permitted_networks = {}; public static boolean support_experimental_extensions; public static String redirect_on_not_found = ""; // torrent map is static across all protocol servers private static Map torrent_map = new HashMap(); private static Map link_map = new HashMap(); protected AEMonitor class_mon = new AEMonitor( "TRTrackerServer:class" ); static{ COConfigurationManager.addListener( new COConfigurationListener() { public void configurationSaved() { readConfig(); } }); readConfig(); } protected static void readConfig() { send_peer_ids = COConfigurationManager.getBooleanParameter( "Tracker Send Peer IDs" ); max_peers_to_send = COConfigurationManager.getIntParameter( "Tracker Max Peers Returned" ); scrape_cache_period = COConfigurationManager.getIntParameter( "Tracker Scrape Cache", TRTrackerServer.DEFAULT_SCRAPE_CACHE_PERIOD ); announce_cache_period = COConfigurationManager.getIntParameter( "Tracker Announce Cache", TRTrackerServer.DEFAULT_ANNOUNCE_CACHE_PERIOD ); announce_cache_threshold = COConfigurationManager.getIntParameter( "Tracker Announce Cache Min Peers", TRTrackerServer.DEFAULT_ANNOUNCE_CACHE_PEER_THRESHOLD ); max_seed_retention = COConfigurationManager.getIntParameter( "Tracker Max Seeds Retained", 0 ); seed_limit = COConfigurationManager.getIntParameter( "Tracker Max Seeds", 0 ); List nets = new ArrayList(); for (int i=0;i listeners = new CopyOnWriteList(); protected CopyOnWriteList listeners2 = new CopyOnWriteList(); private List auth_listeners = new ArrayList(); private Vector request_listeners = new Vector(); protected AEMonitor this_mon = new AEMonitor( "TRTrackerServer" ); private COConfigurationListener config_listener; private boolean destroyed; private Set biased_peers; private boolean is_ready; public TRTrackerServerImpl( String _name, boolean _start_up_ready ) { name = _name==null?DEFAULT_NAME:_name; is_ready = _start_up_ready; config_listener = new COConfigurationListener() { public void configurationSaved() { readConfigSettings(); } }; COConfigurationManager.addListener( config_listener ); readConfigSettings(); current_min_poll_interval = COConfigurationManager.getIntParameter("Tracker Poll Interval Min", DEFAULT_MIN_RETRY_DELAY ); if ( current_min_poll_interval < RETRY_MINIMUM_SECS ){ current_min_poll_interval = RETRY_MINIMUM_SECS; } current_min_seed_announce_mult = COConfigurationManager.getIntParameter( "Tracker Poll Seed Interval Mult" ); current_announce_retry_interval = current_min_poll_interval; int scrape_percentage = COConfigurationManager.getIntParameter("Tracker Scrape Retry Percentage", DEFAULT_SCRAPE_RETRY_PERCENTAGE ); current_scrape_retry_interval = (current_announce_retry_interval*scrape_percentage)/100; Thread timer_thread = new AEThread("TrackerServer:timer.loop") { public void runSupport( ) { timerLoop(); } }; timer_thread.setDaemon( true ); timer_thread.start(); } protected void readConfigSettings() { web_password_enabled = COConfigurationManager.getBooleanParameter("Tracker Password Enable Web"); tracker_password_enabled = COConfigurationManager.getBooleanParameter("Tracker Password Enable Torrent"); web_password_https_only = COConfigurationManager.getBooleanParameter("Tracker Password Web HTTPS Only"); if ( web_password_enabled || tracker_password_enabled ){ password_user = COConfigurationManager.getStringParameter("Tracker Username", ""); password_pw = COConfigurationManager.getByteParameter("Tracker Password", new byte[0]); } compact_enabled = COConfigurationManager.getBooleanParameter("Tracker Compact Enable" ); key_enabled = COConfigurationManager.getBooleanParameter("Tracker Key Enable Server"); } public void setReady() { is_ready = true; } public final boolean isReady() { return( is_ready ); } public void setEnabled( boolean e ) { enabled = e; } public boolean isEnabled() { return( enabled ); } public void setEnableKeepAlive( boolean enable ) { keep_alive_enabled = enabled; } public boolean isKeepAliveEnabled() { return( keep_alive_enabled ); } public TRTrackerServerTorrent addLink( String link, TRTrackerServerTorrent target ) { try{ class_mon.enter(); return((TRTrackerServerTorrent)link_map.put( link, target )); }finally{ class_mon.exit(); } } public void removeLink( String link, TRTrackerServerTorrent target ) { try{ class_mon.enter(); link_map.remove( link ); }finally{ class_mon.exit(); } } public void setBiasedPeers( Set peers ) { if ( biased_peers != null && peers.equals( biased_peers )){ return; } String str = ""; Iterator it = peers.iterator(); while( it.hasNext()){ str += " " + it.next(); } System.out.println( "biased peers: " + str ); try{ class_mon.enter(); biased_peers = new HashSet( peers ); Iterator tit = torrent_map.values().iterator(); while(tit.hasNext()){ TRTrackerServerTorrentImpl this_torrent = (TRTrackerServerTorrentImpl)tit.next(); this_torrent.updateBiasedPeers( biased_peers ); } }finally{ class_mon.exit(); } } protected Set getBiasedPeers() { return( biased_peers ); } public boolean isWebPasswordEnabled() { return( web_password_enabled || auth_listeners.size() > 0 ); } public boolean isTrackerPasswordEnabled() { return( tracker_password_enabled || auth_listeners.size() > 0 ); } public boolean isWebPasswordHTTPSOnly() { return( web_password_https_only ); } public boolean hasExternalAuthorisation() { return( auth_listeners.size() > 0 ); } public boolean hasInternalAuthorisation() { return( web_password_enabled || tracker_password_enabled ); } public boolean performExternalAuthorisation( URL resource, String user, String password ) { for (int i=0;i 0 ){ // full scrape or error - spread the reported bytes across the torrents int ave_in = bytes_in/num; int ave_out = bytes_out/num; int rem_in = bytes_in-(ave_in*num); int rem_out = bytes_out-(ave_out*num); Iterator it = torrent_map.values().iterator(); while(it.hasNext()){ TRTrackerServerTorrentImpl this_torrent = (TRTrackerServerTorrentImpl)it.next(); if ( it.hasNext()){ this_torrent.updateXferStats( ave_in, ave_out ); }else{ this_torrent.updateXferStats( ave_in+rem_in, ave_out+rem_out ); } } } }finally{ class_mon.exit(); } } } } protected void updateTime( int request_type, long time ) { stats.updateTime( request_type, time ); } protected void timerLoop() { long time_to_go = TIMEOUT_CHECK; while( !destroyed ){ try{ Thread.sleep( RETRY_MINIMUM_MILLIS ); time_to_go -= RETRY_MINIMUM_MILLIS; // recalc tracker interval every minute current_min_poll_interval = COConfigurationManager.getIntParameter("Tracker Poll Interval Min", DEFAULT_MIN_RETRY_DELAY ); if ( current_min_poll_interval < RETRY_MINIMUM_SECS ){ current_min_poll_interval = RETRY_MINIMUM_SECS; } int min = current_min_poll_interval; int max = COConfigurationManager.getIntParameter("Tracker Poll Interval Max", DEFAULT_MAX_RETRY_DELAY ); int inc_by = COConfigurationManager.getIntParameter("Tracker Poll Inc By", DEFAULT_INC_BY ); int inc_per = COConfigurationManager.getIntParameter("Tracker Poll Inc Per", DEFAULT_INC_PER ); int scrape_percentage = COConfigurationManager.getIntParameter("Tracker Scrape Retry Percentage", DEFAULT_SCRAPE_RETRY_PERCENTAGE ); int retry = min; int clients = 0; try{ class_mon.enter(); Iterator it = torrent_map.values().iterator(); while(it.hasNext()){ TRTrackerServerTorrentImpl t = (TRTrackerServerTorrentImpl)it.next(); clients += t.getPeerCount(); } }finally{ class_mon.exit(); } if ( inc_by > 0 && inc_per > 0 ){ retry += inc_by * (clients/inc_per); } if ( max > 0 && retry > max ){ retry = max; } if ( retry < RETRY_MINIMUM_SECS ){ retry = RETRY_MINIMUM_SECS; } current_announce_retry_interval = retry; current_scrape_retry_interval = (current_announce_retry_interval*scrape_percentage)/100; current_total_clients = clients; // timeout dead clients if ( time_to_go <= 0 ){ time_to_go = TIMEOUT_CHECK; try{ class_mon.enter(); Iterator it = torrent_map.values().iterator(); while(it.hasNext()){ TRTrackerServerTorrentImpl t = (TRTrackerServerTorrentImpl)it.next(); t.checkTimeouts(); } }finally{ class_mon.exit(); } } }catch( InterruptedException e ){ Debug.printStackTrace( e ); } } } public TRTrackerServerTorrent permit( String _originator, byte[] _hash, boolean _explicit ) throws TRTrackerServerException { return( permit( _originator, _hash, _explicit, true )); } public TRTrackerServerTorrent permit( String _originator, byte[] _hash, boolean _explicit, boolean _enabled ) throws TRTrackerServerException { // System.out.println( "TRTrackerServerImpl::permit( " + _explicit + ")"); HashWrapper hash = new HashWrapper( _hash ); // don't invoke listeners when synched, deadlock possible TRTrackerServerTorrentImpl entry; try{ class_mon.enter(); entry = (TRTrackerServerTorrentImpl)torrent_map.get( hash ); }finally{ class_mon.exit(); } if ( entry == null ){ Iterator it = listeners.iterator(); while( it.hasNext()){ if ( !it.next().permitted( _originator, _hash, _explicit )){ throw( new TRTrackerServerException( "operation denied")); } } try{ class_mon.enter(); // double check in-case added in parallel entry = (TRTrackerServerTorrentImpl)torrent_map.get( hash ); if ( entry == null ){ entry = new TRTrackerServerTorrentImpl( this, hash, _enabled ); torrent_map.put( hash, entry ); } }finally{ class_mon.exit(); } } return( entry ); } public void deny( byte[] _hash, boolean _explicit ) throws TRTrackerServerException { // System.out.println( "TRTrackerServerImpl::deny( " + _explicit + ")"); HashWrapper hash = new HashWrapper( _hash ); Iterator it = listeners.iterator(); while( it.hasNext()){ if ( !it.next().denied( _hash, _explicit )){ throw( new TRTrackerServerException( "operation denied")); } } try{ class_mon.enter(); TRTrackerServerTorrentImpl entry = (TRTrackerServerTorrentImpl)torrent_map.get( hash ); if ( entry != null ){ entry.delete(); } torrent_map.remove( hash ); }finally{ class_mon.exit(); } } public TRTrackerServerTorrentImpl getTorrent( byte[] hash ) { try{ class_mon.enter(); return((TRTrackerServerTorrentImpl)torrent_map.get(new HashWrapper(hash))); }finally{ class_mon.exit(); } } public TRTrackerServerTorrentImpl getTorrent( String link ) { try{ class_mon.enter(); return((TRTrackerServerTorrentImpl)link_map.get( link )); }finally{ class_mon.exit(); } } public TRTrackerServerTorrentImpl[] getTorrents() { try{ class_mon.enter(); TRTrackerServerTorrentImpl[] res = new TRTrackerServerTorrentImpl[torrent_map.size()]; torrent_map.values().toArray( res ); return( res ); }finally{ class_mon.exit(); } } public int getTorrentCount() { return( torrent_map.size()); } public TRTrackerServerTorrentStats getStats( byte[] hash ) { TRTrackerServerTorrentImpl torrent = getTorrent( hash ); if ( torrent == null ){ return( null ); } return( torrent.getStats()); } public TRTrackerServerPeer[] getPeers( byte[] hash ) { TRTrackerServerTorrentImpl torrent = getTorrent( hash ); if ( torrent == null ){ return( null ); } return( torrent.getPeers()); } public void addListener( TRTrackerServerListener l ) { listeners.add( l ); } public void removeListener( TRTrackerServerListener l ) { listeners.remove(l); } public void addListener2( TRTrackerServerListener2 l ) { listeners2.add( l ); } public void removeListener2( TRTrackerServerListener2 l ) { listeners2.remove(l); } public void addAuthenticationListener( TRTrackerServerAuthenticationListener l ) { auth_listeners.add( l ); } public void removeAuthenticationListener( TRTrackerServerAuthenticationListener l ) { auth_listeners.remove(l); } public void preProcess( TRTrackerServerPeer peer, TRTrackerServerTorrent torrent, int type, String request, Map response ) throws TRTrackerServerException { if ( request_listeners.size() > 0 ){ // if this is a scrape then we need to patch up stuff as it may be multi-scrape if ( type == TRTrackerServerRequest.RT_SCRAPE ){ try{ int request_pos = 10; while( true ){ int p = request.indexOf( "info_hash=", request_pos ); String bit; if ( p == -1 ){ if ( request_pos == 10 ){ break; // only one entry, nothing to do } bit = request.substring( request_pos ); }else{ bit = request.substring( request_pos, p ); } int pos = bit.indexOf('&'); String hash_str = pos==-1?bit:bit.substring(0,pos); hash_str = URLDecoder.decode( hash_str, Constants.BYTE_ENCODING ); byte[] hash = hash_str.getBytes(Constants.BYTE_ENCODING); if ( Arrays.equals( hash, torrent.getHash().getBytes())){ request = "info_hash=" + bit; if ( request.endsWith("&")){ request = request.substring(0,request.length()-1); } break; } if ( p == -1 ){ break; } request_pos = p + 10; } }catch( Throwable e ){ Debug.printStackTrace(e); } } TRTrackerServerRequestImpl req = new TRTrackerServerRequestImpl( this, peer, torrent, type, request, response ); for (int i=0;i 0 ){ TRTrackerServerRequestImpl req = new TRTrackerServerRequestImpl( this, peer, torrent, type, request, response ); for (int i=0;iShort.MAX_VALUE?Short.MAX_VALUE:(short)_up_speed; network_position = _network_position; resolveAndCheckNAT(); } /** * Import constructor */ protected TRTrackerServerPeerImpl( HashWrapper _peer_id, int _key_hash_code, byte[] _ip, boolean _ip_override, short _tcp_port, short _udp_port, short _http_port, byte _crypto_level, byte _az_ver, String _ip_str, byte[] _ip_bytes, byte _NAT_status, long _timeout, long _uploaded, long _downloaded, long _amount_left, long _last_contact_time, boolean _download_completed, boolean _biased, short _up_speed ) { peer_id = _peer_id; key_hash_code = _key_hash_code; ip = _ip; ip_override = _ip_override; tcp_port = _tcp_port; udp_port = _udp_port; http_port = _http_port; crypto_level = _crypto_level; az_ver = _az_ver; ip_str = _ip_str; ip_bytes = _ip_bytes; NAT_status = _NAT_status; timeout = _timeout; uploaded = _uploaded; downloaded = _downloaded; amount_left = _amount_left; last_contact_time = _last_contact_time; download_completed = _download_completed; biased = _biased; up_speed = _up_speed; } protected boolean update( byte[] _ip, int _port, int _udp_port, int _http_port, byte _crypto_level, byte _az_ver, int _up_speed, DHTNetworkPosition _network_position ) { udp_port = (short)_udp_port; http_port = (short)_http_port; crypto_level = _crypto_level; az_ver = _az_ver; up_speed = _up_speed>Short.MAX_VALUE?Short.MAX_VALUE:(short)_up_speed; network_position = _network_position; boolean res = false; if ( _port != getTCPPort() ){ tcp_port = (short)_port; res = true; } if ( !Arrays.equals( _ip, ip )){ ip = _ip; res = true; } if ( res ){ resolveAndCheckNAT(); } return( res ); } public void NATCheckComplete( boolean ok ) { if ( ok ){ NAT_status = NAT_CHECK_OK; }else{ NAT_status = NAT_CHECK_FAILED; } } protected void setNATStatus( byte status ) { NAT_status = status; } public byte getNATStatus() { return( NAT_status ); } protected boolean isNATStatusBad() { return( NAT_status == NAT_CHECK_FAILED || NAT_status == NAT_CHECK_FAILED_AND_REPORTED ); } protected void resolveAndCheckNAT() { // default values pending resolution ip_str = new String( ip ); ip_bytes = null; HostNameToIPResolver.addResolverRequest( ip_str, this ); // a port of 0 is taken to mean that the client can't/won't receive incoming // connections - tr if ( tcp_port == 0 ){ NAT_status = NAT_CHECK_FAILED_AND_REPORTED; }else{ // only recheck if we haven't already ascertained the state if ( NAT_status == NAT_CHECK_UNKNOWN ){ NAT_status = NAT_CHECK_INITIATED; if ( !TRTrackerServerNATChecker.getSingleton().addNATCheckRequest( ip_str, getTCPPort(), this )){ NAT_status = NAT_CHECK_DISABLED; } } } } public void hostNameResolutionComplete( InetAddress address ) { if ( address != null ){ ip_str = address.getHostAddress(); ip_bytes = address.getAddress(); } } protected long getLastContactTime() { return( last_contact_time ); } protected boolean getDownloadCompleted() { return( download_completed ); } protected void setDownloadCompleted() { download_completed = true; } public boolean isBiased() { return( biased ); } public void setBiased( boolean _biased ) { biased = _biased; } public HashWrapper getPeerId() { return( peer_id ); } public byte[] getPeerID() { return( peer_id.getBytes()); } protected int getKeyHashCode() { return( key_hash_code ); } public byte[] getIPAsRead() { return( ip ); } public String getIPRaw() { return( new String(ip)); } /** * If asynchronous resolution of the address is required, this will return * the non-resolved address until the async process completes */ public String getIP() { return( ip_str ); } protected boolean isIPOverride() { return( ip_override ); } /** * This will return in resolution of the address is not complete or fails * @return */ public byte[] getIPAddressBytes() { return( ip_bytes ); } public int getTCPPort() { return( tcp_port&0xffff ); } public int getUDPPort() { return( udp_port&0xffff ); } public int getHTTPPort() { return( http_port&0xffff ); } public byte getCryptoLevel() { return( crypto_level ); } public byte getAZVer() { return( az_ver ); } public int getUpSpeed() { return( up_speed&0xffff ); } public DHTNetworkPosition getNetworkPosition() { return( network_position ); } protected void setTimeout( long _now, long _timeout ) { last_contact_time = _now; timeout = _timeout; } protected long getTimeout() { return( timeout ); } public int getSecsToLive() { return((int)(( timeout - SystemTime.getCurrentTime())/1000 )); } protected void setStats( long _uploaded, long _downloaded, long _amount_left ) { uploaded = _uploaded; downloaded = _downloaded; amount_left = _amount_left; } public long getUploaded() { return( uploaded ); } public long getDownloaded() { return( downloaded ); } public long getAmountLeft() { return( amount_left ); } public boolean isSeed() { return( amount_left == 0 ); } public void setUserData( Object key, Object data ) { if ( user_data == null ){ user_data = new Object[]{ key, data }; }else if ( user_data instanceof Object[]){ Object[] x = (Object[])user_data; if ( x[0] == key ){ x[1] = data; }else{ HashMap map = new HashMap(); user_data = map; map.put( x[0], x[1] ); map.put( key, data ); } }else{ ((Map)user_data).put( key, data ); } } public Object getUserData( Object key ) { if ( user_data == null ){ return( null ); }else if( user_data instanceof Object[]){ Object[] x = (Object[])user_data; if ( x[0] == key ){ return( x[1] ); }else{ return( null ); } }else{ return(((Map)user_data).get(key)); } } public Map export() { Map map = new HashMap(); map.put( "peer_id", peer_id.getBytes()); map.put( "key_hash_code", new Long( key_hash_code )); map.put( "ip", ip ); map.put( "ip_override", new Long( ip_override?1:0 )); map.put( "tcp_port", new Long( tcp_port )); map.put( "udp_port", new Long( udp_port )); map.put( "http_port", new Long( http_port )); map.put( "crypto_level", new Long( crypto_level )); map.put( "az_ver", new Long( az_ver )); map.put( "ip_str", ip_str ); if ( ip_bytes != null ){ map.put( "ip_bytes", ip_bytes ); } map.put( "NAT_status", new Long( NAT_status )); map.put( "timeout", new Long( timeout )); map.put( "uploaded", new Long( uploaded )); map.put( "downloaded", new Long( downloaded )); map.put( "amount_left", new Long( amount_left )); map.put( "last_contact_time", new Long( last_contact_time )); map.put( "download_completed", new Long( download_completed?1:0 )); map.put( "biased", new Long( biased?1:0 )); map.put( "up_speed", new Long( up_speed )); return( map ); } public static TRTrackerServerPeerImpl importPeer( Map map ) { try{ HashWrapper peer_id = new HashWrapper((byte[])map.get( "peer_id" )); int key_hash_code = ((Long)map.get( "key_hash_code" )).intValue(); byte[] ip = (byte[])map.get( "ip" ); boolean ip_override = ((Long)map.get( "ip_override" )).intValue()==1; short tcp_port = ((Long)map.get( "tcp_port" )).shortValue(); short udp_port = ((Long)map.get( "udp_port" )).shortValue(); short http_port = ((Long)map.get( "http_port" )).shortValue(); byte crypto_level = ((Long)map.get( "crypto_level" )).byteValue(); byte az_ver = ((Long)map.get( "az_ver" )).byteValue(); String ip_str = new String( (byte[])map.get( "ip_str" )); byte[] ip_bytes = (byte[])map.get( "ip_bytes" ); byte NAT_status = ((Long)map.get( "NAT_status" )).byteValue(); long timeout = ((Long)map.get( "timeout" )).longValue(); long uploaded = ((Long)map.get( "uploaded" )).longValue(); long downloaded = ((Long)map.get( "downloaded" )).longValue(); long amount_left = ((Long)map.get( "amount_left" )).longValue(); long last_contact_time = ((Long)map.get( "last_contact_time" )).longValue(); boolean download_completed = ((Long)map.get( "download_completed" )).intValue() == 1; boolean biased = ((Long)map.get( "biased" )).intValue() == 1; short up_speed = ((Long)map.get( "up_speed" )).shortValue(); return( new TRTrackerServerPeerImpl( peer_id, key_hash_code, ip, ip_override, tcp_port, udp_port, http_port, crypto_level, az_ver, ip_str, ip_bytes, NAT_status, timeout, uploaded, downloaded, amount_left, last_contact_time, download_completed, biased, up_speed )); }catch( Throwable e ){ return( null ); } } protected String getString() { return( new String(ip) + ":" + getTCPPort() + "(" + new String(peer_id.getHash()) + ")" ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/udp/0000755000175000017500000000000011310377634023667 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/udp/TRTrackerServerUDP.java0000644000175000017500000001103410702575546030140 0ustar adrianadrian/* * File : TRTrackerServerUDP.java * Created : 19-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server.impl.udp; /** * @author parg * */ import java.net.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.tracker.server.*; import org.gudy.azureus2.core3.tracker.server.impl.*; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.net.udp.uc.PRUDPPacket; public class TRTrackerServerUDP extends TRTrackerServerImpl { private static final LogIDs LOGID = LogIDs.TRACKER; private static final int THREAD_POOL_SIZE = 10; private ThreadPool thread_pool; private int port; private DatagramSocket dg_socket; private volatile boolean closed; public TRTrackerServerUDP( String _name, int _port, boolean _start_up_ready ) { super( _name, _start_up_ready ); port = _port; thread_pool = new ThreadPool( "TrackerServer:UDP:"+port, THREAD_POOL_SIZE ); try{ InetAddress bind_ip = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress(); InetSocketAddress address; DatagramSocket socket; if ( bind_ip == null ){ address = new InetSocketAddress(InetAddress.getByName("127.0.0.1"),port); socket = new DatagramSocket( port ); }else{ address = new InetSocketAddress( bind_ip, port); socket = new DatagramSocket(address); } socket.setReuseAddress(true); dg_socket = socket; final InetSocketAddress f_address = address; Thread recv_thread = new AEThread("TRTrackerServerUDP:recv.loop") { public void runSupport() { recvLoop( dg_socket, f_address ); } }; recv_thread.setDaemon( true ); recv_thread.start(); Logger.log(new LogEvent(LOGID, "TRTrackerServerUDP: recv established on port " + port)); }catch( Throwable e ){ Logger.log(new LogEvent(LOGID, "TRTrackerServerUDP: " + "DatagramSocket bind failed on port " + port, e)); } } protected void recvLoop( DatagramSocket socket, InetSocketAddress address ) { long successful_accepts = 0; long failed_accepts = 0; while( !closed ){ try{ byte[] buf = new byte[PRUDPPacket.MAX_PACKET_SIZE]; DatagramPacket packet = new DatagramPacket( buf, buf.length, address ); socket.receive( packet ); successful_accepts++; failed_accepts = 0; String ip = packet.getAddress().getHostAddress(); if ( !ip_filter.isInRange( ip, "Tracker", null )){ thread_pool.run( new TRTrackerServerProcessorUDP( this, socket, packet )); } }catch( Throwable e ){ if ( !closed ){ failed_accepts++; Logger.log(new LogEvent(LOGID, "TRTrackerServer: receive failed on port " + port, e)); if (( failed_accepts > 100 && successful_accepts == 0 ) || failed_accepts > 1000 ){ // looks like its not going to work... // some kind of socket problem Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Network.alert.acceptfail"), new String[] { "" + port, "UDP" }); break; } } } } } public int getPort() { return( port ); } public String getHost() { return( COConfigurationManager.getStringParameter( "Tracker IP", "" )); } public boolean isSSL() { return( false ); } public void addRequestListener( TRTrackerServerRequestListener l ) { } public void removeRequestListener( TRTrackerServerRequestListener l ) { } protected void closeSupport() { closed = true; try{ dg_socket.close(); }catch( Throwable e ){ } destroySupport(); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/udp/TRTrackerServerProcessorUDP.java0000644000175000017500000004317611147377516032055 0ustar adrianadrian/* * File : TRTrackerServerProcessorUDP.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server.impl.udp; /** * @author parg * */ import java.net.*; import java.io.*; import java.security.SecureRandom; import java.util.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.tracker.server.*; import org.gudy.azureus2.core3.tracker.server.impl.*; import org.gudy.azureus2.core3.tracker.protocol.*; import org.gudy.azureus2.core3.tracker.protocol.udp.*; import com.aelitis.net.udp.uc.PRUDPPacket; import com.aelitis.net.udp.uc.PRUDPPacketRequest; public class TRTrackerServerProcessorUDP extends TRTrackerServerProcessor { private static final LogIDs LOGID = LogIDs.TRACKER; // client may connect + then retry announce up to 4 times -> * 6 public static final long CONNECTION_ID_LIFETIME = PRUDPPacket.DEFAULT_UDP_TIMEOUT*6; private TRTrackerServerUDP server; private DatagramSocket socket; private DatagramPacket request_dg; private static Map connection_id_map = new LinkedHashMap(); private static SecureRandom random = RandomUtils.SECURE_RANDOM; private static AEMonitor random_mon = new AEMonitor( "TRTrackerServerUDP:rand" ); static{ PRUDPTrackerCodecs.registerCodecs(); } protected TRTrackerServerProcessorUDP( TRTrackerServerUDP _server, DatagramSocket _socket, DatagramPacket _packet ) { server = _server; socket = _socket; request_dg = _packet; } public void runSupport() { byte[] input_buffer = new byte[request_dg.getLength()]; System.arraycopy( request_dg.getData(), 0, input_buffer, 0, input_buffer.length ); int packet_data_length = input_buffer.length; String auth_user = null; byte[] auth_user_bytes = null; byte[] auth_hash = null; if ( server.isTrackerPasswordEnabled()){ // auth detail should be attached to the packet. Auth details are 16 // bytes if ( input_buffer.length < 17 ){ Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "TRTrackerServerProcessorUDP: " + "packet received but authorisation missing")); return; } packet_data_length -= 16; auth_user_bytes = new byte[8]; auth_hash = new byte[8]; System.arraycopy( input_buffer, packet_data_length, auth_user_bytes, 0, 8 ); int user_len = 0; while( user_len < 8 && auth_user_bytes[user_len] != 0 ){ user_len++; } auth_user = new String( auth_user_bytes, 0, user_len ); System.arraycopy( input_buffer, packet_data_length+8, auth_hash, 0, 8 ); } DataInputStream is = new DataInputStream(new ByteArrayInputStream(input_buffer, 0, packet_data_length )); try{ String client_ip_address = request_dg.getAddress().getHostAddress(); PRUDPPacketRequest request = PRUDPPacketRequest.deserialiseRequest( null, is ); Logger.log(new LogEvent(LOGID, "TRTrackerServerProcessorUDP: packet received: " + request.getString())); PRUDPPacket reply = null; TRTrackerServerTorrentImpl torrent = null; if ( auth_user_bytes != null ){ // user name is irrelevant as we only have one at the moment // so = + + // where = first 8 bytes of sha1( + + sha1(pass)) // Yes byte[] sha1_pw = null; if ( server.hasExternalAuthorisation()){ try{ URL resource = new URL( "udp://" + server.getHost() + ":" + server.getPort() + "/" ); sha1_pw = server.performExternalAuthorisation( resource, auth_user ); }catch( MalformedURLException e ){ Debug.printStackTrace( e ); } if ( sha1_pw == null ){ Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "TRTrackerServerProcessorUDP: auth fails for user '" + auth_user + "'")); reply = new PRUDPPacketReplyError( request.getTransactionId(), "Access Denied" ); } }else{ sha1_pw = server.getPassword(); } // if we haven't already failed then check the PW if ( reply == null ){ SHA1Hasher hasher = new SHA1Hasher(); hasher.update( input_buffer, 0, packet_data_length); hasher.update( auth_user_bytes ); hasher.update( sha1_pw ); byte[] digest = hasher.getDigest(); for (int i=0;i CONNECTION_ID_LIFETIME ){ // System.out.println( "TRTrackerServerProcessorUDP: conection id timeout" ); it.remove(); }else{ // insertion order into map is time based - LinkedHashMap returns keys in same order break; } } connection_id_map.put( new_key, new_data ); // System.out.println( "TRTrackerServerProcessorUDP: allocated:" + id + ", conection id map size = " + connection_id_map.size()); return( id ); }finally{ random_mon.exit(); } } protected boolean checkConnectionId( String client_address, long id ) { try{ random_mon.enter(); Long key = new Long(id); connectionData data = (connectionData)connection_id_map.get( key ); if ( data == null ){ // System.out.println( "TRTrackerServerProcessorUDP: rejected:" + id + ", data not found" ); return( false ); }else{ // single shot id, can't be reused connection_id_map.remove( key ); } boolean ok = data.getAddress().equals( client_address ); // System.out.println( "TRTrackerServerProcessorUDP: tested:" + id + "/" + client_address + " -> " + ok ); return( ok ); }finally{ random_mon.exit(); } } protected PRUDPPacket handleConnect( String client_ip_address, PRUDPPacketRequest request ) { long conn_id = allocateConnectionId( client_ip_address ); PRUDPPacket reply = new PRUDPPacketReplyConnect(request.getTransactionId(), conn_id ); return( reply ); } // returns reply packet and associated torrent if exists protected Object[] handleAnnounceAndScrape( String client_ip_address, PRUDPPacketRequest request, int request_type ) throws Exception { if ( !checkConnectionId( client_ip_address, request.getConnectionId())){ return( null ); } List hashbytes = new ArrayList(); HashWrapper peer_id = null; int port = 0; String event = null; long uploaded = 0; long downloaded = 0; long left = 0; int num_want = -1; String key = null; if ( request_type == TRTrackerServerRequest.RT_ANNOUNCE ){ if ( PRUDPPacketTracker.VERSION == 1 ){ PRUDPPacketRequestAnnounce announce = (PRUDPPacketRequestAnnounce)request; hashbytes.add(announce.getHash()); peer_id = new HashWrapper( announce.getPeerId()); port = announce.getPort(); int i_event = announce.getEvent(); switch( i_event ){ case PRUDPPacketRequestAnnounce.EV_STARTED: { event = "started"; break; } case PRUDPPacketRequestAnnounce.EV_STOPPED: { event = "stopped"; break; } case PRUDPPacketRequestAnnounce.EV_COMPLETED: { event = "completed"; break; } } uploaded = announce.getUploaded(); downloaded = announce.getDownloaded(); left = announce.getLeft(); num_want = announce.getNumWant(); int i_ip = announce.getIPAddress(); if ( i_ip != 0 ){ client_ip_address = PRHelpers.intToAddress( i_ip ); } }else{ PRUDPPacketRequestAnnounce2 announce = (PRUDPPacketRequestAnnounce2)request; hashbytes.add(announce.getHash()); peer_id = new HashWrapper( announce.getPeerId()); port = announce.getPort(); int i_event = announce.getEvent(); switch( i_event ){ case PRUDPPacketRequestAnnounce.EV_STARTED: { event = "started"; break; } case PRUDPPacketRequestAnnounce.EV_STOPPED: { event = "stopped"; break; } case PRUDPPacketRequestAnnounce.EV_COMPLETED: { event = "completed"; break; } } uploaded = announce.getUploaded(); downloaded = announce.getDownloaded(); left = announce.getLeft(); num_want = announce.getNumWant(); int i_ip = announce.getIPAddress(); if ( i_ip != 0 ){ client_ip_address = PRHelpers.intToAddress( i_ip ); } key = "" + announce.getKey(); } }else{ PRUDPPacketRequestScrape scrape = (PRUDPPacketRequestScrape)request; hashbytes.addAll(scrape.getHashes()); } Map[] root_out = new Map[1]; TRTrackerServerPeerImpl[] peer_out = new TRTrackerServerPeerImpl[1]; TRTrackerServerTorrentImpl torrent = processTrackerRequest( server, "", root_out, peer_out, request_type, (byte[][])hashbytes.toArray(new byte[0][0]), null, null, peer_id, false, TRTrackerServerTorrentImpl.COMPACT_MODE_NONE, key, // currently no "no_peer_id" / "compact" in the packet and anyway they aren't returned / key event, false, port, 0, 0, client_ip_address, client_ip_address, downloaded, uploaded, left, num_want, TRTrackerServerPeer.CRYPTO_NONE, (byte)1, 0, null ); Map root = root_out[0]; if ( request_type == TRTrackerServerRequest.RT_ANNOUNCE ){ if ( PRUDPPacketTracker.VERSION == 1 ){ PRUDPPacketReplyAnnounce reply = new PRUDPPacketReplyAnnounce(request.getTransactionId()); reply.setInterval(((Long)root.get("interval")).intValue()); List peers = (List)root.get("peers"); int[] addresses = new int[peers.size()]; short[] ports = new short[addresses.length]; for (int i=0;i peer_map = new HashMap(); private Map peer_reuse_map = new HashMap(); private List peer_list = new ArrayList(); private int peer_list_hole_count; private boolean peer_list_compaction_suspended; private List biased_peers = null; private int min_biased_peers = 0; private Map lightweight_seed_map = new HashMap(); private int seed_count; private int removed_count; private int ip_override_count; private int bad_NAT_count; // calculated periodically private Random random = new Random( SystemTime.getCurrentTime()); private long last_scrape_calc_time; private Map last_scrape; private LinkedHashMap announce_cache = new LinkedHashMap(); private TRTrackerServerTorrentStatsImpl stats; private List listeners = new ArrayList(); private List peer_listeners; private boolean deleted; private boolean enabled; private boolean map_size_diff_reported; private boolean ip_override_limit_exceeded_reported; private byte duplicate_peer_checker_index = 0; private byte[] duplicate_peer_checker = new byte[0]; private URL[] redirects; private boolean caching_enabled = true; private LinkedList queued_peers; protected AEMonitor this_mon = new AEMonitor( "TRTrackerServerTorrent" ); private List explicit_manual_biased_peers; private int explicit_next_peer; public TRTrackerServerTorrentImpl( TRTrackerServerImpl _server, HashWrapper _hash, boolean _enabled ) { server = _server; hash = _hash; enabled = _enabled; stats = new TRTrackerServerTorrentStatsImpl( this ); } public void setEnabled( boolean _enabled ) { enabled = _enabled; } public boolean isEnabled() { return( enabled ); } public void setMinBiasedPeers( int num ) { min_biased_peers = num; } public void importPeers( List peers ) { try{ this_mon.enter(); // only currently support import when torrent "empty" if ( peer_map.size() > 0 ){ System.out.println( "TRTrackerServerTorrent: ignoring peer import as torrent already active" ); return; } for (int i=0;i= MAX_IP_OVERRIDE_PEERS && !( loopback || biased )){ // bail out - the peer will still get an announce response but we don't // want too many override peers on a torrent as these can be spoofed // to cause trouble if ( !ip_override_limit_exceeded_reported ){ ip_override_limit_exceeded_reported = true; Debug.out( "Too many ip-override peers for " + ByteFormatter.encodeString( hash.getBytes())); } return( null ); } peer = new TRTrackerServerPeerImpl( peer_id, tracker_key_hash_code, ip_address_bytes, ip_override, tcp_port, udp_port, http_port, crypto_level, az_ver, last_contact_time, already_completed, last_NAT_status, up_speed, network_position ); if ( ip_override ){ // never allow an ip-override to take on the guise of a biased peer if ( biased ){ // UNLESS the originating IP is biased too if ( !biased_peer_set.contains( original_address )){ throw( new TRTrackerServerException( "IP Override denied (you are " + original_address + ")" )); } } ip_override_count++; } peer_map.put( peer_id, peer ); peer_list.add( peer ); peer_reuse_map.put( reuse_key, peer ); if ( biased ){ peer.setBiased( true ); if ( biased_peers == null ){ biased_peers = new ArrayList(); } biased_peers.add( peer ); } if ( queued_peers != null ){ if ( peer_map.size() > QUEUED_PEERS_MAX_SWARM_SIZE ){ queued_peers = null; }else{ // peer has become active, remove the queued peer info Iterator it = queued_peers.iterator(); while( it.hasNext()){ QueuedPeer qp = (QueuedPeer)it.next(); if ( qp.sameAs( peer )){ it.remove(); break; } } } } } }else{ int existing_tracker_key_hash_code = peer.getKeyHashCode(); // System.out.println( "tracker_key:" + existing_tracker_key + "/" + tracker_key ); if ( existing_tracker_key_hash_code != tracker_key_hash_code ){ throw( new TRTrackerServerException( "Unauthorised: key mismatch ")); } if ( ip_override ){ // biased peers are never ip-override if ( peer.isBiased()){ // UNLESS the originating IP is biased too Set biased_peer_set = server.getBiasedPeers(); if ( biased_peer_set == null || !biased_peer_set.contains( original_address )){ throw( new TRTrackerServerException( "IP Override denied (you are " + original_address + ")")); } } // prevent an ip_override peer from affecting a non-override entry if ( !peer.isIPOverride()){ throw( new TRTrackerServerException( "IP Override denied (existing entry not override)" )); } } already_completed = peer.getDownloadCompleted(); last_contact_time = peer.getLastContactTime(); if ( event_type == TRTrackerServerTorrentPeerListener.ET_STOPPED ){ removePeer( peer, event_type, url_parameters ); peer_already_removed = true; }else{ // IP may have changed - update if required // it is possible for two az clients to have the same peer id. Unlikely but possible // or indeed some hacked versions could do it on purpose. If this is the case then all we // will see here is address/port changes as each peer announces byte[] old_ip = peer.getIPAsRead(); int old_port = peer.getTCPPort(); if ( peer.update( ip_address_bytes, tcp_port, udp_port, http_port, crypto_level, az_ver, up_speed, network_position )){ // same peer id so same port String old_key = new String( old_ip, Constants.BYTE_ENCODING ) + ":" + old_port; String new_key = new String( ip_address_bytes, Constants.BYTE_ENCODING ) + ":" + tcp_port; // it is possible, on address change, that the target address already exists and is // (was) being used by another peer. Given that this peer has taken over its address // the assumption is that the other peer has also had an address change and has yet // to report it. The only action here is to delete the other peer TRTrackerServerPeerImpl old_peer = (TRTrackerServerPeerImpl)peer_reuse_map.get( new_key ); if ( old_peer != null ){ removePeer( old_peer, TRTrackerServerTorrentPeerListener.ET_REPLACED, null ); } // now swap the keys if ( peer_reuse_map.remove( old_key ) == null ){ Debug.out( "TRTrackerServerTorrent: IP address change: '" + old_key + "' -> '" + new_key + "': old key not found" ); } peer_reuse_map.put( new_key, peer ); } } } // a null peer here signifies a new peer whose first state was "stopped" long new_timeout = now + ( interval_requested * 1000 * TRTrackerServerImpl.CLIENT_TIMEOUT_MULTIPLIER ); if ( peer != null ){ peer.setTimeout( now, new_timeout ); // if this is the first time we've heard from this peer then we don't want to // use existing ul/dl value diffs as they will have been reported previously // (either the client's changed peer id by stop/start (in which case the values // should be 0 anyway as its a per-session total), or the tracker's been // stopped and started). if ( !new_peer ){ ul_diff = uploaded - peer.getUploaded(); dl_diff = downloaded - peer.getDownloaded(); } // simple rate control long elapsed_time = now - last_contact_time; if ( elapsed_time == 0 ){ elapsed_time = SystemTime.TIME_GRANULARITY_MILLIS; } long ul_rate = (ul_diff*1000)/elapsed_time; // bytes per second long dl_rate = (dl_diff*1000)/elapsed_time; if ( ul_rate > MAX_UPLOAD_BYTES_PER_SEC ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "TRTrackerPeer: peer " + peer.getIPRaw() + "/" + new String(peer.getPeerId().getHash()) + " reported an upload rate of " + ul_rate / 1024 + " KiB/s per second")); ul_diff = 0; } if ( dl_rate > MAX_DOWNLOAD_BYTES_PER_SEC ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "TRTrackerPeer: peer " + peer.getIPRaw() + "/" + new String(peer.getPeerId().getHash()) + " reported a download rate of " + dl_rate / 1024 + " KiB/s per second")); dl_diff = 0; } // when the peer is removed its "left" amount will dealt with le_diff = (event_type==TRTrackerServerTorrentPeerListener.ET_STOPPED)?0:(left - peer.getAmountLeft()); boolean was_seed = new_peer?false:peer.isSeed(); peer.setStats( uploaded, downloaded, left ); boolean is_seed = peer.isSeed(); if (!(event_type == TRTrackerServerTorrentPeerListener.ET_STOPPED || was_seed || !is_seed )){ seed_count++; } // report event *after* updating totals above so listeners get a valid initial // view of the peer (e.g. is it a seed) // if the peer has already been removed above then it will have reported the // event already if ( !peer_already_removed ){ try{ peerEvent( peer, event_type, url_parameters ); }catch( TRTrackerServerException e ){ deferred_failure = e; } } } stats.addAnnounce( ul_diff, dl_diff, le_diff, peer != null && peer.isBiased()); if ( event_type==TRTrackerServerTorrentPeerListener.ET_COMPLETE && !already_completed ){ peer.setDownloadCompleted(); stats.addCompleted(); } if ( peer != null && peer.isSeed()){ int seed_limit = TRTrackerServerImpl.getSeedLimit(); if ( seed_limit != 0 && seed_count > seed_limit && !loopback ){ if ( !peer_already_removed ){ removePeer( peer, TRTrackerServerTorrentPeerListener.ET_TOO_MANY_PEERS, null ); } // this is picked up by AZ client removal rules and causes the torrent to // be removed throw( new TRTrackerServerException( "too many seeds" )); } int seed_retention = TRTrackerServerImpl.getMaxSeedRetention(); if ( seed_retention != 0 && seed_count > seed_retention ){ // remove 5% of the seeds int to_remove = (seed_retention/20)+1; try{ peer_list_compaction_suspended = true; // remove bad NAT ones in preference to others for (int bad_nat_loop=TRTrackerServerNATChecker.getSingleton().isEnabled()?0:1;bad_nat_loop<2;bad_nat_loop++){ for (int i=0;i= QUEUED_PEERS_MAX_SWARM_SIZE || tcp_port == 0 ){ return; } try{ this_mon.enter(); Set biased_peer_set = server.getBiasedPeers(); boolean biased = biased_peer_set != null && biased_peer_set.contains( ip ); QueuedPeer new_qp = new QueuedPeer( ip, tcp_port, udp_port, http_port, crypto_level, az_ver, (int)timeout_secs, seed, biased ); String reuse_key = new_qp.getIP() + ":" + tcp_port; // if still active then drop it if ( peer_reuse_map.containsKey( reuse_key )){ return; } boolean add = true; if ( queued_peers != null ){ Iterator it = queued_peers.iterator(); while( it.hasNext()){ QueuedPeer qp = (QueuedPeer)it.next(); if ( qp.sameAs( new_qp )){ it.remove(); queued_peers.add( new_qp ); return; } } if ( queued_peers.size() >= QUEUED_PEERS_MAX ){ QueuedPeer oldest = null; it = queued_peers.iterator(); while( it.hasNext()){ QueuedPeer qp = (QueuedPeer)it.next(); // never drop biased peers if ( qp.isBiased()){ continue; } if ( oldest == null ){ oldest = qp; }else{ if ( qp.getCreateTime() < oldest.getCreateTime()){ oldest = qp; } } } if ( oldest == null ){ add = false; }else{ queued_peers.remove( oldest ); } } }else{ queued_peers = new LinkedList(); } if ( add ){ queued_peers.addFirst( new_qp ); } }finally{ this_mon.exit(); } } public void remove( TRTrackerServerPeerBase peer ) { try{ this_mon.enter(); if ( peer instanceof TRTrackerServerPeerImpl ){ TRTrackerServerPeerImpl pi = (TRTrackerServerPeerImpl)peer; if ( peer_map.containsKey( pi.getPeerId())){ int index = peer_list.indexOf( pi ); if ( index != -1 ){ removePeer( pi, index, TRTrackerServerTorrentPeerListener.ET_FAILED, null ); } } }else{ if ( queued_peers != null ){ queued_peers.remove( peer ); if ( queued_peers.size() == 0 ){ queued_peers = null; } } } }finally{ this_mon.exit(); } } protected void removePeer( TRTrackerServerPeerImpl peer, int reason, String url_parameters ) { removePeer( peer, -1, reason, url_parameters ); } protected void removePeer( TRTrackerServerPeerImpl peer, int peer_list_index, int reason, String url_parameters ) // -1 if not known { try{ this_mon.enter(); if ( peer.isIPOverride()){ ip_override_count--; } stats.removeLeft( peer.getAmountLeft()); if ( peer_map.size() != peer_reuse_map.size()){ if ( !map_size_diff_reported ){ map_size_diff_reported = true; Debug.out( "TRTrackerServerTorrent::removePeer: maps size different ( " + peer_map.size() + "/" + peer_reuse_map.size() +")"); } } { Object o = peer_map.remove( peer.getPeerId()); if ( o == null ){ Debug.out(" TRTrackerServerTorrent::removePeer: peer_map doesn't contain peer"); }else{ try{ peerEvent( peer, reason, url_parameters ); }catch( TRTrackerServerException e ){ // ignore during peer removal } } } if ( peer_list_index == -1 ){ int peer_index = peer_list.indexOf( peer ); if ( peer_index == -1){ Debug.out(" TRTrackerServerTorrent::removePeer: peer_list doesn't contain peer"); }else{ peer_list.set( peer_index, null ); } }else{ if ( peer_list.get( peer_list_index ) == peer ){ peer_list.set( peer_list_index, null ); }else{ Debug.out(" TRTrackerServerTorrent::removePeer: peer_list doesn't contain peer at index"); } } peer_list_hole_count++; checkForPeerListCompaction( false ); try{ Object o = peer_reuse_map.remove( new String( peer.getIPAsRead(), Constants.BYTE_ENCODING ) + ":" + peer.getTCPPort()); if ( o == null ){ Debug.out(" TRTrackerServerTorrent::removePeer: peer_reuse_map doesn't contain peer"); } }catch( UnsupportedEncodingException e ){ } if ( biased_peers != null ){ biased_peers.remove( peer ); } if ( peer.isSeed()){ seed_count--; } removed_count++; }finally{ this_mon.exit(); } } protected void updateBiasedPeers( Set biased_peers_set ) { try{ this_mon.enter(); Iterator it = peer_list.iterator(); if ( it.hasNext() && biased_peers == null ){ biased_peers = new ArrayList(); } while( it.hasNext()){ TRTrackerServerPeerImpl this_peer = (TRTrackerServerPeerImpl)it.next(); if ( this_peer != null ){ boolean biased = biased_peers_set.contains( this_peer.getIPRaw()); this_peer.setBiased( biased ); if ( biased ){ if ( !biased_peers.contains( this_peer )){ biased_peers.add( this_peer ); } }else{ biased_peers.remove( this_peer ); } } } if ( queued_peers != null ){ it = queued_peers.iterator(); while( it.hasNext()){ QueuedPeer peer = (QueuedPeer)it.next(); peer.setBiased( biased_peers_set.contains( peer.getIP())); } } }finally{ this_mon.exit(); } } public TRTrackerServerTorrent addLink( String link ) { return( server.addLink( link, this )); } public void removeLink( String link ) { server.removeLink( link, this ); } public Map exportAnnounceToMap( String ip_address, HashMap preprocess_map, TRTrackerServerPeerImpl requesting_peer, // maybe null for an initial announce from a stopped peer boolean include_seeds, int num_want, long interval, long min_interval, boolean no_peer_id, byte compact_mode, byte crypto_level, DHTNetworkPosition network_position ) { try{ this_mon.enter(); long now = SystemTime.getCurrentTime(); // we have to force non-caching for nat_warnings responses as they include // peer-specific data boolean nat_warning = requesting_peer != null && requesting_peer.getNATStatus() == TRTrackerServerPeerImpl.NAT_CHECK_FAILED; int total_peers = peer_map.size(); int cache_millis = TRTrackerServerImpl.getAnnounceCachePeriod(); boolean send_peer_ids = TRTrackerServerImpl.getSendPeerIds(); // override if client has explicitly not requested them if ( no_peer_id || compact_mode != COMPACT_MODE_NONE ){ send_peer_ids = false; } boolean add_to_cache = false; int max_peers = TRTrackerServerImpl.getMaxPeersToSend(); // num_want < 0 -> not supplied so give them max if ( num_want < 0 ){ num_want = total_peers; } // trim back to max_peers if specified if ( max_peers > 0 && num_want > max_peers ){ num_want = max_peers; } // if set this list contains the only peers that are to be returned. It allows a manual // external peer selection algorithm List explicit_limited_peers = null; List explicit_biased_peers = null; Set remove_ips = null; if ( requesting_peer != null ){ if ( peer_listeners != null ){ for (int i=0;i(); } for (int j=0;j(); } for (int j=0;j 0 && num_want >= MIN_CACHE_ENTRY_SIZE && total_peers >= TRTrackerServerImpl.getAnnounceCachePeerThreshold() && crypto_level != TRTrackerServerPeer.CRYPTO_REQUIRED ){ // no cache for crypto required peers // too busy to bother with network position stuff network_position = null; // note that we've got to select a cache entry that is somewhat // relevant to the num_want param (but NOT greater than it) // remove stuff that's too old Iterator it = announce_cache.keySet().iterator(); while( it.hasNext() ){ Integer key = (Integer)it.next(); announceCacheEntry entry = (announceCacheEntry)announce_cache.get( key ); if ( now - entry.getTime() > cache_millis ){ it.remove(); } } // look for an entry with a reasonable num_want // e.g. for 100 look between 50 and 100 for (int i=num_want/10;i>num_want/20;i--){ announceCacheEntry entry = (announceCacheEntry)announce_cache.get(new Integer(i)); if( entry != null ){ if ( now - entry.getTime() > cache_millis ){ announce_cache.remove( new Integer(i)); }else{ // make sure this is compatible if ( entry.getSendPeerIds() == send_peer_ids && entry.getCompactMode() == compact_mode ){ return( entry.getData()); } } } } add_to_cache = true; } LinkedList rep_peers = new LinkedList(); // System.out.println( "exportPeersToMap: num_want = " + num_want + ", max = " + max_peers ); // if they want them all simply give them the set if ( num_want > 0 && explicit_limited_peers == null ){ if ( num_want >= total_peers){ // if they want them all simply give them the set for (int i=0;i peer.getTimeout()){ // System.out.println( "removing timed out client '" + peer.getString()); removePeer( peer, i, TRTrackerServerTorrentPeerListener.ET_TIMEOUT, null ); }else if ( peer.getTCPPort() == 0 ){ // a port of 0 means that the peer definitely can't accept incoming connections }else if ( crypto_level == TRTrackerServerPeer.CRYPTO_NONE && peer.getCryptoLevel() == TRTrackerServerPeer.CRYPTO_REQUIRED ){ // don't return "crypto required" peers to those that can't correctly connect to them /* change this to make the explicit ones additional, not replacing }else if ( explicit_biased_peers != null && peer.isBiased()){ */ // if we have an explicit biased peer list and this peer is biased // skip here as we add them later }else if ( remove_ips != null && remove_ips.contains( new String( peer.getIP()))){ // skippy skippy }else if ( include_seeds || !peer.isSeed()){ Map rep_peer = new HashMap(3); if ( send_peer_ids ){ rep_peer.put( "peer id", peer.getPeerId().getHash()); } if ( compact_mode != COMPACT_MODE_NONE ){ byte[] peer_bytes = peer.getIPAddressBytes(); if ( peer_bytes == null ){ continue; } rep_peer.put( "ip", peer_bytes ); if ( compact_mode >= COMPACT_MODE_AZ ){ rep_peer.put( "azver", new Long( peer.getAZVer())); rep_peer.put( "azudp", new Long( peer.getUDPPort())); if ( peer.isSeed()){ rep_peer.put( "azhttp", new Long( peer.getHTTPPort())); } if ( compact_mode >= COMPACT_MODE_XML ){ rep_peer.put( "ip", peer.getIPAsRead() ); }else{ rep_peer.put( "azup", new Long( peer.getUpSpeed())); if ( peer.isBiased()){ rep_peer.put( "azbiased", "" ); } if ( network_position != null ){ DHTNetworkPosition peer_pos = peer.getNetworkPosition(); if ( peer_pos != null && network_position.getPositionType() == peer_pos.getPositionType()){ rep_peer.put( "azrtt", new Long( (long)peer_pos.estimateRTT(network_position ))); } } } } }else{ rep_peer.put( "ip", peer.getIPAsRead() ); } rep_peer.put( "port", new Long( peer.getTCPPort())); if ( crypto_level != TRTrackerServerPeer.CRYPTO_NONE ){ rep_peer.put( "crypto_flag", new Long( peer.getCryptoLevel() == TRTrackerServerPeer.CRYPTO_REQUIRED?1:0)); } if ( peer.isBiased()){ rep_peers.addFirst( rep_peer ); }else{ rep_peers.addLast( rep_peer ); } } } }else{ int peer_list_size = peer_list.size(); // to avoid returning duplicates when doing the two-loop check // for nat selection we maintain an array of markers if ( duplicate_peer_checker.length < peer_list_size ){ duplicate_peer_checker = new byte[peer_list_size*2]; duplicate_peer_checker_index = 1; }else if ( duplicate_peer_checker.length > (peer_list_size*2)){ duplicate_peer_checker = new byte[(3*peer_list_size)/2]; duplicate_peer_checker_index = 1; }else{ duplicate_peer_checker_index++; if ( duplicate_peer_checker_index == 0 ){ Arrays.fill( duplicate_peer_checker, (byte)0); duplicate_peer_checker_index = 1; } } boolean peer_removed = false; try{ // got to suspend peer list compaction as we rely on the // list staying the same size during processing below peer_list_compaction_suspended = true; // too costly to randomise as below. use more efficient but slightly less accurate // approach // two pass process if bad nat detection enabled int added = 0; //int bad_nat_added = 0; for (int bad_nat_loop=TRTrackerServerNATChecker.getSingleton().isEnabled()?0:1;bad_nat_loop<2;bad_nat_loop++){ int limit = num_want*2; // some entries we find might not be usable // so in the limit search for more if ( num_want*3 > total_peers ){ limit++; } int biased_peers_count = 0; if ( biased_peers != null ){ // explicit are additional && explicit_biased_peers == null ){ if ( biased_peers.size() > 1 ){ // juggle things a bit Object x = biased_peers.remove(0); biased_peers.add( random.nextInt( biased_peers.size() + 1 ), x); } biased_peers_count = Math.min( min_biased_peers, biased_peers.size()); } for (int i=0;i peer.getTimeout()){ removePeer( peer, TRTrackerServerTorrentPeerListener.ET_TIMEOUT, null ); peer_removed = true; }else if ( requesting_peer == peer || peer.getTCPPort() == 0 ){ // a port of 0 means that the peer definitely can't accept incoming connections }else if ( crypto_level == TRTrackerServerPeer.CRYPTO_NONE && peer.getCryptoLevel() == TRTrackerServerPeer.CRYPTO_REQUIRED ){ // don't return "crypto required" peers to those that can't correctly connect to them }else if ( remove_ips != null && remove_ips.contains( new String( peer.getIP()))){ // skippy skippy }else if ( include_seeds || !peer.isSeed()){ boolean bad_nat = peer.isNATStatusBad(); if ( ( bad_nat_loop == 0 && !bad_nat ) || ( bad_nat_loop == 1 )){ if ( peer_index == -1 || duplicate_peer_checker[peer_index] != duplicate_peer_checker_index ){ if ( peer_index != -1 ){ duplicate_peer_checker[peer_index] = duplicate_peer_checker_index; } //if ( bad_nat ){ // // bad_nat_added++; //} added++; Map rep_peer = new HashMap(3); if ( send_peer_ids ){ rep_peer.put( "peer id", peer.getPeerId().getHash()); } if ( compact_mode != COMPACT_MODE_NONE ){ byte[] peer_bytes = peer.getIPAddressBytes(); if ( peer_bytes == null ){ continue; } rep_peer.put( "ip", peer_bytes ); if ( compact_mode >= COMPACT_MODE_AZ ){ rep_peer.put( "azver", new Long( peer.getAZVer())); rep_peer.put( "azudp", new Long( peer.getUDPPort())); if ( peer.isSeed()){ rep_peer.put( "azhttp", new Long( peer.getHTTPPort())); } if ( compact_mode >= COMPACT_MODE_XML ){ rep_peer.put( "ip", peer.getIPAsRead() ); }else{ rep_peer.put( "azup", new Long( peer.getUpSpeed())); if ( peer.isBiased()){ rep_peer.put( "azbiased", "" ); } if ( network_position != null ){ DHTNetworkPosition peer_pos = peer.getNetworkPosition(); if ( peer_pos != null && network_position.getPositionType() == peer_pos.getPositionType()){ rep_peer.put( "azrtt", new Long( (long)peer_pos.estimateRTT(network_position ))); } } } } }else{ rep_peer.put( "ip", peer.getIPAsRead() ); } rep_peer.put( "port", new Long( peer.getTCPPort())); if ( crypto_level != TRTrackerServerPeer.CRYPTO_NONE ){ rep_peer.put( "crypto_flag", new Long( peer.getCryptoLevel() == TRTrackerServerPeer.CRYPTO_REQUIRED?1:0)); } if ( peer.isBiased()){ rep_peers.addFirst( rep_peer ); }else{ rep_peers.addLast( rep_peer ); } } } } } } // System.out.println( "num_want = " + num_want + ", added = " + added + ", bad_nat = " + bad_nat_added ); }finally{ peer_list_compaction_suspended = false; if ( peer_removed ){ checkForPeerListCompaction( false ); } } /* }else{ // given up on this approach for the moment as too costly // randomly select the peers to return LinkedList peers = new LinkedList( peer_map.keySet()); int added = 0; while( added < num_want && peers.size() > 0 ){ String key = (String)peers.remove(random.nextInt(peers.size())); TRTrackerServerPeerImpl peer = (TRTrackerServerPeerImpl)peer_map.get(key); if ( now > peer.getTimeout()){ removePeer( peer, TRTrackerServerTorrentPeerListener.ET_TIMEOUT, null ); }else if ( peer.getTCPPort() == 0 ){ // a port of 0 means that the peer definitely can't accept incoming connections }else if ( crypto_level == TRTrackerServerPeer.CRYPTO_NONE && peer.getCryptoLevel() == TRTrackerServerPeer.CRYPTO_REQUIRED ){ // don't return "crypto required" peers to those that can't correctly connect to them }else if ( include_seeds || !peer.isSeed()){ added++; Map rep_peer = new HashMap(3); // don't use TreeMap as default is "compact" // so we never actually encode anyway if ( send_peer_ids ){ rep_peer.put( "peer id", peer.getPeerId().getHash()); } if ( compact_mode != COMPACT_MODE_NONE ){ byte[] peer_bytes = peer.getIPBytes(); if ( peer_bytes == null ){ continue; } rep_peer.put( "ip", peer_bytes ); if ( compact_mode >= COMPACT_MODE_AZ ){ rep_peer.put( "azver", new Long( peer.getAZVer())); rep_peer.put( "azudp", new Long( peer.getUDPPort())); if ( peer.isSeed()){ rep_peer.put( "azhttp", new Long( peer.getHTTPPort())); } } }else{ rep_peer.put( "ip", peer.getIPAsRead() ); } rep_peer.put( "port", new Long( peer.getTCPPort())); if ( crypto_level != TRTrackerServerPeer.CRYPTO_NONE ){ rep_peer.put( "crypto_flag", new Long( peer.getCryptoLevel() == TRTrackerServerPeer.CRYPTO_REQUIRED?1:0)); } rep_peers.add( rep_peer ); } }*/ } } if ( include_seeds && explicit_limited_peers == null && !send_peer_ids && seed_count < 3 && queued_peers != null ){ Iterator it = queued_peers.iterator(); List added = new ArrayList( QUEUED_PEERS_ADD_MAX ); while( it.hasNext() && num_want > rep_peers.size() && added.size() < QUEUED_PEERS_ADD_MAX ){ QueuedPeer peer = (QueuedPeer)it.next(); if ( peer.isTimedOut( now )){ it.remove(); }else if ( crypto_level == TRTrackerServerPeer.CRYPTO_NONE && peer.getCryptoLevel() == TRTrackerServerPeer.CRYPTO_REQUIRED ){ // don't return "crypto required" peers to those that can't correctly connect to them }else if ( remove_ips != null && remove_ips.contains( peer.getIP())){ // skippy skippy }else{ Map rep_peer = new HashMap(3); if ( compact_mode != COMPACT_MODE_NONE ){ byte[] peer_bytes = peer.getIPAddressBytes(); if ( peer_bytes == null ){ continue; } rep_peer.put( "ip", peer_bytes ); if ( compact_mode >= COMPACT_MODE_AZ ){ rep_peer.put( "azver", new Long( peer.getAZVer())); rep_peer.put( "azudp", new Long( peer.getUDPPort())); if ( peer.isSeed()){ rep_peer.put( "azhttp", new Long( peer.getHTTPPort())); } if ( compact_mode >= COMPACT_MODE_XML ){ rep_peer.put( "ip", peer.getIPAsRead()); } } }else{ rep_peer.put( "ip", peer.getIPAsRead()); } rep_peer.put( "port", new Long( peer.getTCPPort())); if ( crypto_level != TRTrackerServerPeer.CRYPTO_NONE ){ rep_peer.put( "crypto_flag", new Long( peer.getCryptoLevel() == TRTrackerServerPeer.CRYPTO_REQUIRED?1:0)); } // System.out.println( "added queued peer " + peer.getString()); rep_peers.addLast( rep_peer ); added.add( peer ); // it'll be added back in below, don't worry! it.remove(); } } for (int i=0;i 0 ){ root.putAll( preprocess_map ); } if ( explicit_limited_peers != null ){ for (int i=0;i= COMPACT_MODE_AZ ){ rep_peer.put( "azver", new Long( 0 )); // non-az rep_peer.put( "azudp", new Long( 0 )); rep_peer.put( "azup", new Long( 0 )); rep_peer.put( "azbiased", "" ); } }else{ rep_peer.put( "ip", ((String)explicit_peer[0]).getBytes()); } rep_peer.put( "port", new Long( ((Integer)explicit_peer[2]).intValue())); if ( crypto_level != TRTrackerServerPeer.CRYPTO_NONE ){ rep_peer.put( "crypto_flag", new Long( 0 )); } rep_peers.addFirst( rep_peer ); } } int num_peers_returned = rep_peers.size(); Iterator it = rep_peers.iterator(); if ( compact_mode == COMPACT_MODE_AZ ){ byte[] compact_peers = new byte[num_peers_returned*9]; int index = 0; while( it.hasNext()){ Map rep_peer = (Map)it.next(); byte[] ip = (byte[])rep_peer.get( "ip" ); int tcp_port = ((Long)rep_peer.get( "port" )).intValue(); int udp_port = ((Long)rep_peer.get( "azudp" )).intValue(); Long crypto_flag_l = (Long)rep_peer.get( "crypto_flag" ); byte crypto_flag = crypto_flag_l==null?0:crypto_flag_l.byteValue(); int pos = index*9; System.arraycopy( ip, 0, compact_peers, pos, 4 ); pos += 4; compact_peers[pos++] = (byte)(tcp_port>>8); compact_peers[pos++] = (byte)(tcp_port&0xff); compact_peers[pos++] = (byte)(udp_port>>8); compact_peers[pos++] = (byte)(udp_port&0xff); compact_peers[pos++] = crypto_flag; index++; } root.put( "peers", compact_peers ); root.put( "azcompact", new Long(1)); }else if ( compact_mode == COMPACT_MODE_AZ_2 ){ List compact_peers = new ArrayList( num_peers_returned ); while( it.hasNext()){ Map rep_peer = (Map)it.next(); Map peer = new HashMap(); compact_peers.add( peer ); byte[] ip = (byte[])rep_peer.get( "ip" ); peer.put( "i", ip ); int tcp_port = ((Long)rep_peer.get( "port" )).intValue(); peer.put( "t", new byte[]{ (byte)(tcp_port>>8), (byte)(tcp_port&0xff) }); int udp_port = ((Long)rep_peer.get( "azudp" )).intValue(); if ( udp_port != 0 ){ if ( udp_port == tcp_port ){ peer.put( "u", new byte[0] ); }else{ peer.put( "u", new byte[]{ (byte)(udp_port>>8), (byte)(udp_port&0xff) }); } } Long http_port_l = (Long)rep_peer.get( "azhttp" ); if ( http_port_l != null ){ int http_port = http_port_l.intValue(); if ( http_port != 0 ){ peer.put( "h", new byte[]{ (byte)(http_port>>8), (byte)(http_port&0xff) }); } } Long crypto_flag_l = (Long)rep_peer.get( "crypto_flag" ); byte crypto_flag = crypto_flag_l==null?0:crypto_flag_l.byteValue(); if ( crypto_flag != 0 ){ peer.put( "c", new byte[]{ crypto_flag } ); } Long az_ver_l = (Long)rep_peer.get( "azver" ); byte az_ver = az_ver_l==null?0:az_ver_l.byteValue(); if ( az_ver != 0 ){ peer.put( "v", new Long(az_ver)); } Long up_speed = (Long)rep_peer.get( "azup" ); if ( up_speed != null && up_speed.longValue() != 0 ){ peer.put( "s", up_speed ); } Long rtt = (Long)rep_peer.get( "azrtt" ); if ( rtt != null ){ peer.put( "r", rtt ); } if ( rep_peer.containsKey("azbiased")){ peer.put( "b", new Long(1)); } } root.put( "peers", compact_peers ); root.put( "azcompact", new Long(2)); }else if ( compact_mode == COMPACT_MODE_XML ){ List xml_peers = new ArrayList( num_peers_returned ); while( it.hasNext()){ Map rep_peer = (Map)it.next(); Map peer = new HashMap(); xml_peers.add( peer ); peer.put( "ip", rep_peer.get( "ip" ) ); peer.put( "tcp", rep_peer.get( "port" )); int udp_port = ((Long)rep_peer.get( "azudp" )).intValue(); if ( udp_port != 0 ){ peer.put( "udp", new Long( udp_port )); } Long http_port_l = (Long)rep_peer.get( "azhttp" ); if ( http_port_l != null ){ int http_port = http_port_l.intValue(); if ( http_port != 0 ){ peer.put( "http", new Long( http_port )); } } } root.put( "peers", xml_peers ); }else{ byte[] crypto_flags = null; if ( crypto_level != TRTrackerServerPeer.CRYPTO_NONE ){ crypto_flags = new byte[num_peers_returned]; } if ( compact_mode == COMPACT_MODE_NORMAL ){ byte[] compact_peers = new byte[num_peers_returned*6]; int index = 0; int num_ipv4 = 0; int num_ipv6 = 0; while( it.hasNext()){ Map rep_peer = (Map)it.next(); byte[] ip = (byte[])rep_peer.get( "ip" ); if ( ip.length > 4 ){ num_ipv6++; // continue and fill in crypto return }else{ num_ipv4++; if ( num_ipv6 == 0 ){ int port = ((Long)rep_peer.get( "port" )).intValue(); int pos = index*6; System.arraycopy( ip, 0, compact_peers, pos, 4 ); pos += 4; compact_peers[pos++] = (byte)(port>>8); compact_peers[pos++] = (byte)(port&0xff); } } if ( crypto_flags != null ){ Long crypto_flag = (Long)rep_peer.remove( "crypto_flag" ); crypto_flags[index] = crypto_flag.byteValue(); } index++; } // inefficient hack to support ipv6 compact for the moment if ( num_ipv6 > 0 ){ byte[] compact_peers_v4 = new byte[num_ipv4*6]; byte[] compact_peers_v6 = new byte[num_ipv6*18]; it = rep_peers.iterator(); int v4_index = 0; int v6_index = 0; while( it.hasNext()){ Map rep_peer = (Map)it.next(); byte[] ip = (byte[])rep_peer.get( "ip" ); int port = ((Long)rep_peer.get( "port" )).intValue(); if ( ip.length > 4 ){ int pos = v6_index*18; System.arraycopy( ip, 0, compact_peers_v6, pos, 16 ); pos += 16; compact_peers_v6[pos++] = (byte)(port>>8); compact_peers_v6[pos++] = (byte)(port&0xff); v6_index++; }else{ int pos = v4_index*6; System.arraycopy( ip, 0, compact_peers_v4, pos, 4 ); pos += 4; compact_peers_v4[pos++] = (byte)(port>>8); compact_peers_v4[pos++] = (byte)(port&0xff); v4_index++; } } if ( compact_peers_v4.length > 0 ){ root.put( "peers", compact_peers_v4 ); } if ( compact_peers_v6.length > 0 ){ root.put( "peers6", compact_peers_v6 ); } }else{ root.put( "peers", compact_peers ); } }else{ int index = 0; while( it.hasNext()){ Map rep_peer = (Map)it.next(); if ( crypto_flags != null ){ Long crypto_flag = (Long)rep_peer.remove( "crypto_flag" ); crypto_flags[index] = crypto_flag.byteValue(); } index++; } root.put( "peers", rep_peers ); } if ( crypto_flags != null ){ root.put( "crypto_flags", crypto_flags ); } } root.put( "interval", new Long( interval )); root.put( "min interval", new Long( min_interval )); if ( nat_warning ){ requesting_peer.setNATStatus( TRTrackerServerPeerImpl.NAT_CHECK_FAILED_AND_REPORTED ); root.put( "warning message", ("Unable to connect to your incoming data port (" + requesting_peer.getIP() + ":" + requesting_peer.getTCPPort() +"). " + "This will result in slow downloads. Please check your firewall/router settings").getBytes()); } // also include scrape details root.put( "complete", new Long( getSeedCountForScrape( requester_is_biased ))); root.put( "incomplete", new Long( getLeecherCount() )); root.put( "downloaded", new Long(stats.getCompletedCount())); if ( add_to_cache ){ announce_cache.put( new Integer((num_peers_returned+9)/10), new announceCacheEntry( root, send_peer_ids, compact_mode )); } return( root ); }finally{ this_mon.exit(); } } private void exportPeer( LinkedList rep_peers, TRTrackerServerSimplePeer peer, boolean send_peer_ids, byte compact_mode, byte crypto_level, DHTNetworkPosition network_position ) { Map rep_peer = new HashMap(3); if ( send_peer_ids ){ rep_peer.put( "peer id", peer.getPeerId().getHash()); } if ( compact_mode != COMPACT_MODE_NONE ){ byte[] peer_bytes = peer.getIPAddressBytes(); if ( peer_bytes == null ){ return; } rep_peer.put( "ip", peer_bytes ); if ( compact_mode >= COMPACT_MODE_AZ ){ rep_peer.put( "azver", new Long( peer.getAZVer())); rep_peer.put( "azudp", new Long( peer.getUDPPort())); if ( peer.isSeed()){ rep_peer.put( "azhttp", new Long( peer.getHTTPPort())); } if ( compact_mode >= COMPACT_MODE_XML ){ rep_peer.put( "ip", peer.getIPAsRead() ); }else{ rep_peer.put( "azup", new Long( peer.getUpSpeed())); if ( peer.isBiased()){ rep_peer.put( "azbiased", "" ); } if ( network_position != null ){ DHTNetworkPosition peer_pos = peer.getNetworkPosition(); if ( peer_pos != null && network_position.getPositionType() == peer_pos.getPositionType()){ rep_peer.put( "azrtt", new Long( (long)peer_pos.estimateRTT(network_position ))); } } } } }else{ rep_peer.put( "ip", peer.getIPAsRead() ); } rep_peer.put( "port", new Long( peer.getTCPPort())); if ( crypto_level != TRTrackerServerPeer.CRYPTO_NONE ){ rep_peer.put( "crypto_flag", new Long( peer.getCryptoLevel() == TRTrackerServerPeer.CRYPTO_REQUIRED?1:0)); } if ( peer.isBiased()){ rep_peers.addFirst( rep_peer ); }else{ rep_peers.addLast( rep_peer ); } } public Map exportScrapeToMap( String url_parameters, String ip_address, boolean allow_cache ) throws TRTrackerServerException { try{ this_mon.enter(); handleRedirects( url_parameters, ip_address, true ); stats.addScrape(); long now = SystemTime.getCurrentTime(); long diff = now - last_scrape_calc_time; if( allow_cache && last_scrape != null && diff < TRTrackerServerImpl.getScrapeCachePeriod() && !(diff < 0) ){ return( last_scrape ); } last_scrape = new TreeMap(); last_scrape_calc_time = now; boolean requester_is_biased; Set bp = server.getBiasedPeers(); if ( bp == null ){ requester_is_biased = false; }else{ requester_is_biased = bp.contains( ip_address ); } last_scrape.put( "complete", new Long( getSeedCountForScrape( requester_is_biased ))); last_scrape.put( "incomplete", new Long( getLeecherCount())); last_scrape.put( "downloaded", new Long(stats.getCompletedCount())); return( last_scrape ); }finally{ this_mon.exit(); } } protected void checkTimeouts() { try{ this_mon.enter(); long now = SystemTime.getCurrentTime(); int new_bad_NAT_count = 0; // recalc seed count as this drifts for some reason (maybe seeds switching back to leechers // on recheck fail, not sure) int new_seed_count = 0; try{ peer_list_compaction_suspended = true; for (int i=0;i peer.getTimeout()){ removePeer( peer, i, TRTrackerServerTorrentPeerListener.ET_TIMEOUT, null ); }else{ if ( peer.isSeed()){ new_seed_count++; } if ( peer.isNATStatusBad()){ new_bad_NAT_count++; } } } }finally{ peer_list_compaction_suspended = false; } bad_NAT_count = new_bad_NAT_count; seed_count = new_seed_count; if ( removed_count > 1000 ){ removed_count = 0; checkForPeerListCompaction( true ); // rehash HashMap new_peer_map = new HashMap(peer_map); HashMap new_peer_reuse_map = new HashMap(peer_reuse_map); peer_map = new_peer_map; peer_reuse_map = new_peer_reuse_map; }else{ checkForPeerListCompaction( false ); } Iterator it = lightweight_seed_map.values().iterator(); while( it.hasNext()){ lightweightSeed lws = (lightweightSeed)it.next(); if ( now > lws.getTimeout()){ it.remove(); } } }finally{ this_mon.exit(); } } protected void checkForPeerListCompaction( boolean force ) { if ( peer_list_hole_count > 0 && !peer_list_compaction_suspended ){ if ( force || peer_list_hole_count > peer_map.size()/10 ){ ArrayList new_peer_list = new ArrayList( peer_list.size() - (peer_list_hole_count/2)); int holes_found = 0; for (int i=0;i 0 ){ seeds++; } } // if we have any queued then lets add at least one in to indicate potential int queued = getQueuedCount(); if ( queued > 0 ){ seeds++; } return( seeds ); } protected int getLeecherCount() { // this isn't synchronised so could possible end up negative int res = peer_map.size() - seed_count; return( res<0?0:res ); } public TRTrackerServerPeer[] getPeers() { try{ this_mon.enter(); TRTrackerServerPeer[] res = new TRTrackerServerPeer[peer_map.size()]; peer_map.values().toArray( res ); return( res ); }finally{ this_mon.exit(); } } protected int getQueuedCount() { List l = queued_peers; if ( l == null ){ return( 0 ); } return( l.size()); } public TRTrackerServerPeerBase[] getQueuedPeers() { try{ this_mon.enter(); if ( queued_peers == null ){ return( new TRTrackerServerPeerBase[0] ); } TRTrackerServerPeerBase[] res = new TRTrackerServerPeerBase[queued_peers.size()]; queued_peers.toArray( res ); return( res ); }finally{ this_mon.exit(); } } public HashWrapper getHash() { return( hash ); } public void addExplicitBiasedPeer( String ip, int port ) { byte[] bytes = HostNameToIPResolver.hostAddressToBytes( ip ); if ( bytes != null ){ try{ this_mon.enter(); if ( explicit_manual_biased_peers == null ){ explicit_manual_biased_peers = new ArrayList(); } explicit_manual_biased_peers.add( new Object[]{ ip, bytes, new Integer( port )}); }finally{ this_mon.exit(); } } } public void setRedirects( URL[] urls ) { try{ this_mon.enter(); redirects = urls; }finally{ this_mon.exit(); } } public URL[] getRedirects() { return( redirects ); } protected void handleRedirects( String url_parameters, String real_ip_address, boolean scrape ) throws TRTrackerServerException { if ( redirects != null ){ if ( url_parameters.indexOf("permredirect") != -1 ){ Debug.out( "redirect recursion" ); throw( new TRTrackerServerException( "redirection recursion not supported" )); } URL redirect = redirects[real_ip_address.hashCode()%redirects.length]; Map headers = new HashMap(); String redirect_str = redirect.toString(); if ( scrape ){ int pos = redirect_str.indexOf( "/announce" ); if ( pos == -1 ){ return; } redirect_str = redirect_str.substring( 0, pos ) + "/scrape" + redirect_str.substring( pos + 9 ); } if ( redirect_str.indexOf('?' ) == -1 ){ redirect_str += "?"; }else{ redirect_str += "&"; } redirect_str += "permredirect=1"; if ( url_parameters.length() > 0 ){ redirect_str += "&" + url_parameters; } System.out.println( "redirect -> " + redirect_str ); headers.put( "Location", redirect_str); throw( new TRTrackerServerException(301, "Moved Permanently", headers )); } } public void addListener( TRTrackerServerTorrentListener l ) { listeners.add(l); if ( deleted ){ l.deleted(this); } } public void removeListener( TRTrackerServerTorrentListener l ) { listeners.remove(l); } protected void peerEvent( TRTrackerServerPeer peer, int event, String url_parameters ) throws TRTrackerServerException { if ( peer_listeners != null ){ for (int i=0;i 0 ){ os.write( ("HTTP/1.1 301 Moved Permanently" + NL + "Location: " + redirect + NL + NL).getBytes() ); }else{ os.write( ("HTTP/1.1 404 Not Found" + NL + NL + "Page not found." + NL).getBytes() ); } os.flush(); return( false ); // throw( new Exception( "Unsupported Request Type")); } // OK, here its an announce, scrape or full scrape // check tracker authentication if ( doAuthentication( url_path, input_header, os, true ) == null ){ return ( false ); } int enc_pos = lowercase_input_header.indexOf( "accept-encoding:"); if ( enc_pos != -1 ){ int e_pos = input_header.indexOf( NL, enc_pos ); if ( e_pos != -1 ){ // check we've not found X-Accept-Encoding (for example) if ( enc_pos > 0 ){ char c = lowercase_input_header.charAt(enc_pos-1); if ( c != FF && c != ' ' ){ enc_pos = -1; } } if ( enc_pos != -1 ){ String accept_encoding = lowercase_input_header.substring(enc_pos+16,e_pos); gzip_reply = HTTPUtils.canGZIP( accept_encoding ); } } } setTaskState( "decoding announce/scrape" ); int pos = 0; byte[] hash = null; List hash_list = null; String link = null; HashWrapper peer_id = null; int tcp_port = 0; String event = null; long uploaded = 0; long downloaded = 0; long left = 0; int num_want = -1; boolean no_peer_id = false; byte compact_mode = TRTrackerServerTorrentImpl.COMPACT_MODE_NONE; String key = null; byte crypto_level = TRTrackerServerPeer.CRYPTO_NONE; int crypto_port = 0; int udp_port = 0; int http_port = 0; int az_ver = 0; boolean stop_to_queue = false; String scrape_flags = null; int up_speed = 0; boolean hide = false; DHTNetworkPosition network_position = null; String real_ip_address = remote_address.getAddress().getHostAddress(); String client_ip_address = real_ip_address; while(pos < str.length()){ int p1 = str.indexOf( '&', pos ); String token; if ( p1 == -1 ){ token = str.substring( pos ); }else{ token = str.substring( pos, p1 ); pos = p1+1; } int p2 = token.indexOf('='); if ( p2 == -1 ){ throw( new Exception( "format invalid" )); } String lhs = token.substring( 0, p2 ).toLowerCase(); String rhs = URLDecoder.decode(token.substring( p2+1 ), Constants.BYTE_ENCODING ); // System.out.println( "param:" + lhs + " = " + rhs ); if ( lhs.equals( "info_hash" )){ byte[] b = rhs.getBytes(Constants.BYTE_ENCODING); if ( hash == null ){ hash = b; }else{ if ( hash_list == null ){ hash_list = new ArrayList(); hash_list.add( hash ); } hash_list.add( b ); } }else if ( lhs.equals( "peer_id" )){ peer_id = new HashWrapper(rhs.getBytes(Constants.BYTE_ENCODING)); }else if ( lhs.equals( "no_peer_id" )){ no_peer_id = rhs.equals("1"); }else if ( lhs.equals( "compact" )){ if ( server.isCompactEnabled()){ if ( rhs.equals("1") && compact_mode == TRTrackerServerTorrentImpl.COMPACT_MODE_NONE ){ compact_mode = TRTrackerServerTorrentImpl.COMPACT_MODE_NORMAL; } } }else if ( lhs.equals( "key" )){ if ( server.isKeyEnabled()){ key = rhs; } }else if ( lhs.equals( "port" )){ tcp_port = Integer.parseInt( rhs ); }else if ( lhs.equals( "event" )){ event = rhs; }else if ( lhs.equals( "ip" )){ // System.out.println( "override: " + real_ip_address + " -> " + rhs + " [" + input_header + "]" ); if ( !HostNameToIPResolver.isNonDNSName( rhs )){ for (int i=0;i= so that if this tracker is "old" and sees a version 3+ it replies with the // best it can - version 2 if ( xml_output ){ compact_mode = TRTrackerServerTorrentImpl.COMPACT_MODE_XML; }else if ( az_ver >= 2 ){ compact_mode = TRTrackerServerTorrentImpl.COMPACT_MODE_AZ_2; } Map[] root_out = new Map[1]; TRTrackerServerPeerImpl[] peer_out = new TRTrackerServerPeerImpl[1]; specific_torrent = processTrackerRequest( server, str, root_out, peer_out, request_type, hashes, link, scrape_flags, peer_id, no_peer_id, compact_mode, key, event, stop_to_queue, tcp_port&0xffff, udp_port&0xffff, http_port&0xffff, real_ip_address, client_ip_address, downloaded, uploaded, left, num_want, crypto_level, (byte)az_ver, up_speed, network_position ); root = root_out[0]; if ( request_type == TRTrackerServerRequest.RT_SCRAPE ){ // add in tracker type for az clients so they know this is an AZ tracker if ( lowercase_input_header.indexOf( lc_azureus_name ) != -1 ){ root.put( "aztracker", new Long(1)); } } // only post-process if this isn't a cached entry if ( root.get( "_data" ) == null ){ TRTrackerServerPeer post_process_peer = peer_out[0]; if ( post_process_peer == null ){ post_process_peer = new lightweightPeer( client_ip_address, tcp_port, peer_id ); } server.postProcess( post_process_peer, specific_torrent, request_type, str, root ); } }catch( Exception e ){ String warning_message = null; Map error_entries = null; if ( e instanceof TRTrackerServerException ){ TRTrackerServerException tr_excep = (TRTrackerServerException)e; int reason = tr_excep.getResponseCode(); error_entries = tr_excep.getErrorEntries(); if ( reason != -1 ){ String resp = "HTTP/1.1 " + reason + " " + tr_excep.getResponseText() + NL; Map headers = tr_excep.getResponseHeaders(); Iterator it = headers.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); String key = (String)entry.getKey(); String value = (String)entry.getValue(); resp += key + ": " + value + NL; } byte[] payload = null; if ( error_entries != null ){ payload = BEncoder.encode( error_entries ); resp += "Content-Length: " + payload.length + NL; } resp += NL; os.write( resp.getBytes()); if ( payload != null ){ os.write( payload ); } os.flush(); return( false ); } if ( tr_excep.isUserMessage()){ warning_message = tr_excep.getMessage(); } }else if ( e instanceof NullPointerException ){ e.printStackTrace(); } String message = e.getMessage(); // e.printStackTrace(); if ( message == null || message.length() == 0 ){ // e.printStackTrace(); message = e.toString(); } root = new HashMap(); root.put( "failure reason", message ); if ( warning_message != null ){ root.put( "warning message", warning_message ); } if ( error_entries != null ){ root.putAll( error_entries ); } } setTaskState( "writing response" ); byte[] data; byte[] header_start; if ( xml_output ){ StringBuffer xml = new StringBuffer( "" ); xml.append( "" ); if ( specific_torrent != null ){ xml.append( "" ); xml.append( ByteFormatter.encodeString( specific_torrent.getHash().getBytes())); xml.append( "" ); xml.append( BEncoder.encodeToXML( root, true )); } xml.append( "" ); data = xml.toString().getBytes("UTF-8" ); header_start = HTTP_RESPONSE_XML_START; }else{ // cache both plain and gzip encoded data for possible reuse data = (byte[])root.get( "_data" ); if ( data == null ){ data = BEncoder.encode( root ); if ( data.length > 1000000 ){ File dump = new File( "bdecoder.dump" ); synchronized( TRTrackerServerProcessorTCP.class ){ try{ Debug.out( "Output is too large, saving diagnostics to " + dump.toString()); PrintWriter pw = new PrintWriter( new FileWriter( dump )); BDecoder.print( pw, root ); pw.close(); }catch( Throwable e ){ } } } root.put( "_data", data ); } header_start = HTTP_RESPONSE_START; } if ( gzip_reply ){ byte[] gzip_data = (byte[])root.get( "_gzipdata"); if ( gzip_data == null ){ ByteArrayOutputStream tos = new ByteArrayOutputStream(data.length); GZIPOutputStream gos = new GZIPOutputStream( tos ); gos.write( data ); gos.close(); gzip_data = tos.toByteArray(); root.put( "_gzipdata", gzip_data ); } data = gzip_data; } // System.out.println( "TRTrackerServerProcessor::reply: sending " + new String(data)); // write the response setTaskState( "writing header" ); os.write( header_start ); byte[] length_bytes = String.valueOf(data.length).getBytes(); os.write( length_bytes ); int header_len = header_start.length + length_bytes.length; setTaskState( "writing content" ); if ( gzip_reply ){ os.write( HTTP_RESPONSE_END_GZIP ); header_len += HTTP_RESPONSE_END_GZIP.length; }else{ os.write( HTTP_RESPONSE_END_NOGZIP ); header_len += HTTP_RESPONSE_END_NOGZIP.length; } os.write( data ); server.updateStats( request_type, specific_torrent, input_header.length(), header_len+data.length ); }finally{ setTaskState( "final os flush" ); os.flush(); } return( false ); } protected String doAuthentication( String url_path, String header, OutputStream os, boolean tracker ) throws IOException { // System.out.println( "doAuth: " + server.isTrackerPasswordEnabled() + "/" + server.isWebPasswordEnabled()); boolean apply_web_password = (!tracker) && server.isWebPasswordEnabled(); boolean apply_torrent_password = tracker && server.isTrackerPasswordEnabled(); if ( apply_web_password && server.isWebPasswordHTTPSOnly() && !server.isSSL()){ os.write( ("HTTP/1.1 403 BAD\r\n\r\nAccess Denied\r\n").getBytes() ); os.flush(); return( null ); }else if ( apply_torrent_password || apply_web_password ){ int x = header.indexOf( "Authorization:" ); if ( x == -1 ){ // auth missing. however, if we have external auth defined // and external auth is happy with junk then allow it through if ( server.hasExternalAuthorisation()){ try{ String resource_str = ( server.isSSL()?"https":"http" ) + "://" + UrlUtils.convertIPV6Host(server.getHost()) + ":" + server.getPort() + url_path; URL resource = new URL( resource_str ); if ( server.performExternalAuthorisation( resource, "", "" )){ return( "" ); } }catch( MalformedURLException e ){ Debug.printStackTrace( e ); } } }else{ // Authorization: Basic dG9tY2F0OnRvbWNhdA== int p1 = header.indexOf(' ', x ); int p2 = header.indexOf(' ', p1+1 ); String body = header.substring( p2, header.indexOf( '\r', p2 )).trim(); String decoded=new String( Base64.decode(body)); // username:password int cp = decoded.indexOf(':'); String user = decoded.substring(0,cp); String pw = decoded.substring(cp+1); boolean auth_failed = false; if ( server.hasExternalAuthorisation()){ try{ String resource_str = ( server.isSSL()?"https":"http" ) + "://" + UrlUtils.convertIPV6Host(server.getHost()) + ":" + server.getPort() + url_path; URL resource = new URL( resource_str ); if ( server.performExternalAuthorisation( resource, user, pw )){ return( user ); } }catch( MalformedURLException e ){ Debug.printStackTrace( e ); } auth_failed = true; } if ( server.hasInternalAuthorisation() && !auth_failed ){ try{ SHA1Hasher hasher = new SHA1Hasher(); byte[] password = pw.getBytes(); byte[] encoded; if( password.length > 0){ encoded = hasher.calculateHash(password); }else{ encoded = new byte[0]; } if ( user.equals( "")){ byte[] internal_pw = Base64.decode(pw); if ( Arrays.equals( internal_pw, server.getPassword())){ return( user ); } }else if ( user.equalsIgnoreCase(server.getUsername()) && Arrays.equals(encoded, server.getPassword())){ return( user ); } }catch( Exception e ){ Debug.printStackTrace( e ); } } } os.write( ("HTTP/1.1 401 BAD\r\nWWW-Authenticate: Basic realm=\"" + server.getName() + "\"\r\n\r\nAccess Denied\r\n").getBytes() ); os.flush(); return( null ); }else{ return( "" ); } } protected boolean handleExternalRequest( InetSocketAddress local_address, InetSocketAddress remote_address, String user, String url, String header, InputStream is, OutputStream os, AsyncController async, boolean[] keep_alive ) throws IOException { URL absolute_url = new URL( server_url + (url.startsWith("/")?url:("/"+url))); return( server.handleExternalRequest( local_address, remote_address, user,url,absolute_url,header, is, os, async, keep_alive )); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/0000755000175000017500000000000011310377634026170 5ustar adrianadrian././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServer.javaazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServer.java0000644000175000017500000003637211277161200032676 0ustar adrianadrian/* * Created on 02-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.server.impl.tcp.nonblocking; import java.util.*; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.tracker.server.TRTrackerServerException; import org.gudy.azureus2.core3.tracker.server.impl.tcp.TRTrackerServerTCP; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector; import com.aelitis.azureus.core.networkmanager.VirtualServerChannelSelector; import com.aelitis.azureus.core.networkmanager.VirtualServerChannelSelectorFactory; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; /** * @author parg * */ public class TRNonBlockingServer extends TRTrackerServerTCP implements VirtualServerChannelSelector.SelectListener { private static final LogIDs LOGID = LogIDs.TRACKER; private static final int TIMEOUT_CHECK_INTERVAL = 10*1000; //10sec private static final int CLOSE_DELAY = 5*1000; private TRNonBlockingServerProcessorFactory processor_factory; private final VirtualChannelSelector read_selector; private final VirtualChannelSelector write_selector; private List connections_to_close = new ArrayList(); private List processors = new ArrayList(); /* private long last_stats_time; private long last_timeouts; private long last_connections; */ private long total_timeouts; private long total_connections; public static final int MAX_CONCURRENT_CONNECTIONS = COConfigurationManager.getIntParameter( "Tracker TCP NonBlocking Conc Max" ); private final AEMonitor this_mon = new AEMonitor( "TRNonBlockingServer" ); private VirtualServerChannelSelector accept_server; private boolean immediate_close = COConfigurationManager.getBooleanParameter( "Tracker TCP NonBlocking Immediate Close" ); private volatile boolean closed; public TRNonBlockingServer( String _name, int _port, InetAddress _bind_ip, boolean _apply_ip_filter, TRNonBlockingServerProcessorFactory _processor_factory ) throws TRTrackerServerException { this( _name, _port, _bind_ip, _apply_ip_filter, true, _processor_factory ); } public TRNonBlockingServer( String _name, int _port, InetAddress _bind_ip, boolean _apply_ip_filter, boolean _start_up_ready, TRNonBlockingServerProcessorFactory _processor_factory ) throws TRTrackerServerException { super( _name, _port, false, _apply_ip_filter, _start_up_ready ); processor_factory = _processor_factory; read_selector = new VirtualChannelSelector( _name + ":" + _port, VirtualChannelSelector.OP_READ, false ); write_selector = new VirtualChannelSelector( _name + ":" + _port, VirtualChannelSelector.OP_WRITE, true ); boolean ok = false; if ( _port == 0 ){ throw( new TRTrackerServerException( "port of 0 not currently supported")); } try{ InetSocketAddress address; if ( _bind_ip == null ){ _bind_ip = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress(); if ( _bind_ip == null ){ address = new InetSocketAddress( _port ); }else{ address = new InetSocketAddress( _bind_ip, _port ); } }else{ address = new InetSocketAddress( _bind_ip, _port ); } accept_server = VirtualServerChannelSelectorFactory.createBlocking( address, 0, this ); accept_server.start(); AEThread read_thread = new AEThread( "TRTrackerServer:readSelector") { public void runSupport() { selectLoop( read_selector ); } }; read_thread.setDaemon(true); read_thread.start(); AEThread write_thread = new AEThread( "TRTrackerServer:writeSelector") { public void runSupport() { selectLoop( write_selector ); } }; write_thread.setDaemon(true); write_thread.start(); AEThread close_thread = new AEThread( "TRTrackerServer:closeScheduler") { public void runSupport() { closeLoop(); } }; close_thread.setDaemon(true); close_thread.start(); Logger.log(new LogEvent(LOGID, "TRTrackerServer: Non-blocking listener established on port " + getPort())); ok = true; }catch( Throwable e){ Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Tracker.alert.listenfail"), new String[] { "" + getPort() }); throw( new TRTrackerServerException( "TRTrackerServer: accept fails", e )); }finally{ if ( !ok ){ destroySupport(); } } } public void setImmediateClose( boolean immediate ) { immediate_close = immediate; } protected void selectLoop( VirtualChannelSelector selector ) { long last_time = 0; while( !closed ){ try{ selector.select( 100 ); // only use one selector to trigger the timeouts! if ( selector == read_selector ){ long now = SystemTime.getCurrentTime(); if ( now < last_time ){ last_time = now; }else if ( now - last_time >= TIMEOUT_CHECK_INTERVAL ){ last_time = now; checkTimeouts(now); } } }catch( Throwable e ){ Debug.printStackTrace(e); } } } public void newConnectionAccepted( ServerSocketChannel server, SocketChannel channel ) { final TRNonBlockingServerProcessor processor = processor_factory.create( this, channel ); int num_processors; try{ this_mon.enter(); total_connections++; processors.add( processor ); num_processors = processors.size(); }finally{ this_mon.exit(); } if ( MAX_CONCURRENT_CONNECTIONS != 0 && num_processors > MAX_CONCURRENT_CONNECTIONS ){ removeAndCloseConnection( processor ); }else if ( isIPFilterEnabled() && ip_filter.isInRange( channel.socket().getInetAddress().getHostAddress(), "Tracker", null )){ removeAndCloseConnection( processor ); }else{ VirtualChannelSelector.VirtualSelectorListener read_listener = new VirtualChannelSelector.VirtualSelectorListener() { private boolean selector_registered; public boolean selectSuccess( VirtualChannelSelector selector, SocketChannel sc, Object attachment ) { try{ int read_result = processor.processRead(); if ( read_result == 0 ) { //read processing is complete if ( selector_registered ){ read_selector.pauseSelects( sc ); } }else if ( read_result < 0 ) { //a read error occured removeAndCloseConnection( processor ); }else{ if ( !selector_registered ){ selector_registered = true; read_selector.register( sc, this, null ); } } return( read_result != 2 ); }catch( Throwable e ){ Debug.printStackTrace(e); removeAndCloseConnection( processor ); return( false ); } } public void selectFailure( VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg ) { removeAndCloseConnection( processor ); } }; read_listener.selectSuccess( read_selector, channel, null ); } } protected void readyToWrite( final TRNonBlockingServerProcessor processor ) { final VirtualChannelSelector.VirtualSelectorListener write_listener = new VirtualChannelSelector.VirtualSelectorListener() { private boolean selector_registered; public boolean selectSuccess( VirtualChannelSelector selector, SocketChannel sc, Object attachment ) { try{ int write_result = processor.processWrite(); if( write_result > 0 ) { //more writing is needed if ( selector_registered ){ write_selector.resumeSelects( sc ); //resume for more writing }else{ selector_registered = true; write_selector.register( sc, this, null ); } }else if( write_result == 0 ) { //write processing is complete removeAndCloseConnection( processor ); }else if( write_result < 0 ) { //a write error occured processor.failed(); removeAndCloseConnection( processor ); } return( write_result != 2 ); }catch( Throwable e ){ Debug.printStackTrace(e); removeAndCloseConnection( processor ); return( false ); } } public void selectFailure( VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg ) { removeAndCloseConnection( processor ); } }; write_listener.selectSuccess( write_selector, processor.getSocketChannel(), null ); } protected void removeAndCloseConnection( TRNonBlockingServerProcessor processor ) { processor.completed(); try{ this_mon.enter(); if ( processors.remove( processor )){ read_selector.cancel( processor.getSocketChannel() ); write_selector.cancel( processor.getSocketChannel() ); if ( immediate_close ){ try{ processor.closed(); processor.getSocketChannel().close(); }catch( Throwable e ){ } }else{ connections_to_close.add( processor ); } } }finally{ this_mon.exit(); } } public void checkTimeouts( long now ) { // we don't particularly care about timeouts if nothing's going on, hence we only // trigger the check on the arrival of a new connection /* String con_rate = ""; String tim_rate = ""; if ( last_stats_time > 0 ){ long time_diff = (now - last_stats_time)/1000; long conn_diff = total_connections - last_connections; long tim_diff = total_timeouts - last_timeouts; con_rate = "" + (conn_diff/time_diff); tim_rate = "" + (tim_diff/time_diff); } System.out.println( "Tracker: con/sec = " + con_rate + ", timeout/sec = " + tim_rate + ", tot_con = " + total_connections+ ", total timeouts = " + total_timeouts + ", current connections = " + processors.size() + ", closing = " + connections_to_close.size()); last_stats_time = now; last_connections = total_connections; last_timeouts = total_timeouts; */ try{ this_mon.enter(); List new_processors = new ArrayList(processors.size()); for (int i=0;i PROCESSING_GET_LIMIT ){ read_selector.cancel( processor.getSocketChannel() ); write_selector.cancel( processor.getSocketChannel() ); connections_to_close.add( processor ); total_timeouts++; }else{ new_processors.add( processor ); } } processors = new_processors; }finally{ this_mon.exit(); } } public void closeLoop() { // socket channel close ops can block, hence we move it off the main processing loops // to ensure that a rogue connection doesn't stall us List pending_list = new ArrayList(); long default_delay = CLOSE_DELAY*2/3; long delay = default_delay; while( !closed ){ // wait a small amount of time to allow the client to close the connection rather // than us. This prevents a buildup of TIME_WAIT state sockets if ( delay > 0 ){ try{ Thread.sleep( delay ); }catch( Throwable e ){ Debug.printStackTrace(e); } } // System.out.println( "close delay = " + delay + ", pending =" + pending_list.size()); long start = SystemTime.getCurrentTime(); for (int i=0;i complete // 1 -> more to do // 2 -> no progress // -1 -> error protected int processRead() { if ( read_buffer.remaining() == 0 ){ int capacity = read_buffer.capacity(); if ( capacity == READ_BUFFER_LIMIT ){ return( -1 ); }else{ read_buffer.position(0); byte[] data = new byte[capacity]; read_buffer.get( data ); read_buffer = ByteBuffer.allocate( capacity + READ_BUFFER_INCREMENT ); read_buffer.put( data ); } } try{ int len = socket_channel.read( read_buffer ); // System.out.println( "read op[" + len + "]: " + System.currentTimeMillis()); if ( len < 0 ){ return( -1 ); }else if ( len == 0 ){ return( 2 ); // no progress } byte[] data = read_buffer.array(); for (int i=read_buffer.position()-4;i>=0;i--){ if ( data[i] == CR && data[i+1] == FF && data[i+2] == CR && data[i+3] == FF ){ request_header = new String(data,0,read_buffer.position()); // System.out.println( "read done: " + System.currentTimeMillis()); getServer().runProcessor( this ); return( 0 ); } } return( 1 ); }catch( IOException e ){ return( -1 ); } } // 0 -> complete // 1 -> more to do // 2 -> no progress made // -1 -> error protected int processWrite() { if ( write_buffer == null ){ return( -1 ); } if ( !write_buffer.hasRemaining()){ return( 0 ); } try{ int written = socket_channel.write( write_buffer ); if ( written == 0 ){ return( 2 ); } if ( write_buffer.hasRemaining()){ return( 1 ); } return( 0 ); }catch( IOException e ){ return( -1 ); } } public void runSupport() { boolean async = false; try{ String url = request_header.substring(4).trim(); int pos = url.indexOf( " " ); url = url.substring(0,pos); final AESemaphore[] went_async = { null }; final ByteArrayOutputStream[] async_stream = { null }; AsyncController async_control = new AsyncController() { public void setAsyncStart() { went_async[0] = new AESemaphore( "async" ); } public void setAsyncComplete() { went_async[0].reserve(); asyncProcessComplete( async_stream[0] ); } }; try{ ByteArrayOutputStream response = process( request_header, request_header.toLowerCase(), url, (InetSocketAddress)socket_channel.socket().getRemoteSocketAddress(), TRTrackerServerImpl.restrict_non_blocking_requests, new ByteArrayInputStream(new byte[0]), async_control ); // two ways of going async // 1) return is null and something else will call asyncProcessComplete later // 2) return is 'not-yet-filled' os and async controller is managing things if ( response == null ){ async = true; }else if ( went_async[0] != null ){ async_stream[0] = response; async = true; }else{ write_buffer = ByteBuffer.wrap( response.toByteArray()); } }finally{ if ( went_async[0] != null ){ went_async[0].release(); } } }catch( Throwable e ){ }finally{ if ( !async ){ ((TRNonBlockingServer)getServer()).readyToWrite( this ); } } } protected abstract ByteArrayOutputStream process( String input_header, String lowercase_input_header, String url_path, InetSocketAddress client_address, boolean announce_and_scrape_only, InputStream is, AsyncController async ) throws IOException; protected void asyncProcessComplete( ByteArrayOutputStream response ) { write_buffer = ByteBuffer.wrap( response.toByteArray()); ((TRNonBlockingServer)getServer()).readyToWrite( this ); } protected SocketChannel getSocketChannel() { return( socket_channel ); } protected long getStartTime() { return( start_time ); } public void interruptTask() { } // overridden if subclass is interested in failures, so don't remove! protected void failed() { } protected void completed() { // System.out.println( "complete: " + System.currentTimeMillis()); } protected void closed() { // System.out.println( "close: " + System.currentTimeMillis()); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/tcp/blocking/0000755000175000017500000000000011310377634025455 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/tcp/blocking/TRBlockingServer.java0000644000175000017500000001575310702575536031525 0ustar adrianadrian/* * Created on 02-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.server.impl.tcp.blocking; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.tracker.server.TRTrackerServerException; import org.gudy.azureus2.core3.tracker.server.impl.tcp.TRTrackerServerTCP; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; /** * @author parg * */ public class TRBlockingServer extends TRTrackerServerTCP { private static final LogIDs LOGID = LogIDs.TRACKER; private ServerSocket server_socket; private volatile boolean closed; public TRBlockingServer( String _name, int _port, InetAddress _bind_ip, boolean _ssl, boolean _apply_ip_filter, boolean _start_up_ready ) throws TRTrackerServerException { super( _name, _port, _ssl, _apply_ip_filter, _start_up_ready ); boolean ok = false; try{ InetAddress bind_ip = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress(); String tr_bind_ip = COConfigurationManager.getStringParameter("Bind IP for Tracker", ""); if ( tr_bind_ip.length() >= 7 ){ try{ bind_ip = InetAddress.getByName(tr_bind_ip); }catch( Throwable e ){ Debug.printStackTrace(e); } } if ( _ssl ){ if ( _port == 0 ){ throw( new TRTrackerServerException( "port of 0 not currently supported for SSL")); } try { SSLServerSocketFactory factory = SESecurityManager.getSSLServerSocketFactory(); if ( factory == null ){ throw( new TRTrackerServerException( "TRTrackerServer: failed to get SSL factory" )); }else{ SSLServerSocket ssl_server_socket; if ( bind_ip == null ){ ssl_server_socket = (SSLServerSocket)factory.createServerSocket( getPort(), 128 ); }else{ ssl_server_socket = (SSLServerSocket)factory.createServerSocket( getPort(), 128, bind_ip ); } String cipherSuites[] = ssl_server_socket.getSupportedCipherSuites(); ssl_server_socket.setEnabledCipherSuites(cipherSuites); ssl_server_socket.setNeedClientAuth(false); ssl_server_socket.setReuseAddress(true); server_socket = ssl_server_socket; Thread accept_thread = new AEThread("TRTrackerServer:accept.loop(ssl)") { public void runSupport() { acceptLoop( server_socket ); } }; accept_thread.setDaemon( true ); accept_thread.start(); Logger.log(new LogEvent(LOGID, "TRTrackerServer: SSL listener established on port " + getPort())); ok = true; } }catch( Throwable e){ Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Tracker.alert.listenfail"), new String[] { "" + getPort() }); Logger.log(new LogEvent(LOGID, "TRTrackerServer: SSL listener failed on port " + getPort(), e)); if ( e instanceof TRTrackerServerException ){ throw((TRTrackerServerException)e); }else{ throw( new TRTrackerServerException( "TRTrackerServer: accept fails: " + e.toString())); } } }else{ try{ ServerSocket ss; int port = getPort(); if ( _bind_ip != null ){ ss = new ServerSocket( port, 1024, _bind_ip ); }else if ( bind_ip == null ){ ss = new ServerSocket( port, 1024 ); }else{ ss = new ServerSocket( port, 1024, bind_ip ); } if ( port == 0 ){ setPort( ss.getLocalPort()); } ss.setReuseAddress(true); server_socket = ss; Thread accept_thread = new AEThread("TRTrackerServer:accept.loop") { public void runSupport() { acceptLoop( server_socket ); } }; accept_thread.setDaemon( true ); accept_thread.start(); Logger.log(new LogEvent(LOGID, "TRTrackerServer: " + "listener established on port " + getPort())); ok = true; }catch( Throwable e){ Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Tracker.alert.listenfail"), new String[] { "" + getPort() }); throw( new TRTrackerServerException( "TRTrackerServer: accept fails", e )); } } }finally{ if ( !ok ){ destroySupport(); } } } protected void acceptLoop( ServerSocket ss ) { long successfull_accepts = 0; long failed_accepts = 0; while( !closed ){ try{ Socket socket = ss.accept(); successfull_accepts++; String ip = socket.getInetAddress().getHostAddress(); if ( (!isIPFilterEnabled()) || (!ip_filter.isInRange( ip, "Tracker", null ))){ runProcessor( new TRBlockingServerProcessor( this, socket )); }else{ socket.close(); } }catch( Throwable e ){ if ( !closed ){ failed_accepts++; Logger.log(new LogEvent(LOGID, "TRTrackerServer: listener failed on port " + getPort(), e)); if ( failed_accepts > 100 && successfull_accepts == 0 ){ // looks like its not going to work... // some kind of socket problem Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Network.alert.acceptfail"), new String[] { "" + getPort(), "TCP" }); break; } } } } } protected void closeSupport() { closed = true; try{ server_socket.close(); }catch( Throwable e ){ } destroySupport(); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/tcp/blocking/TRBlockingServerProcessor.javaazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/tcp/blocking/TRBlockingServerProcessor.j0000644000175000017500000002520711233522512032712 0ustar adrianadrian/* * Created on 02-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.server.impl.tcp.blocking; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; import java.net.SocketTimeoutException; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.tracker.server.TRTrackerServerException; import org.gudy.azureus2.core3.tracker.server.impl.tcp.TRTrackerServerProcessorTCP; import org.gudy.azureus2.core3.tracker.server.impl.tcp.TRTrackerServerTCP; import org.gudy.azureus2.core3.util.AETemporaryFileHandler; import org.gudy.azureus2.core3.util.Constants; /** * @author parg * */ public class TRBlockingServerProcessor extends TRTrackerServerProcessorTCP { protected static final int KEEP_ALIVE_SOCKET_TIMEOUT = 30*1000; private static final LogIDs LOGID = LogIDs.TRACKER; protected Socket socket; protected int timeout_ticks = 1; protected String current_request; protected TRBlockingServerProcessor( TRTrackerServerTCP _server, Socket _socket ) { super( _server ); socket = _socket; } public void runSupport() { // System.out.println( "Processor starts: " + socket.getRemoteSocketAddress()); boolean keep_alive = getServer().isKeepAliveEnabled(); try{ InputStream is = new BufferedInputStream( socket.getInputStream()); while( true ){ setTaskState( "entry" ); try{ socket.setSoTimeout( SOCKET_TIMEOUT ); }catch ( Throwable e ){ // e.printStackTrace(); } setTaskState( "reading header" ); try{ byte[] buffer = new byte[16*1024]; int header_pos = 0; while( header_pos < buffer.length ){ int len = is.read( buffer, header_pos, 1); if ( len != 1 ){ throw( new Exception( "Premature end of stream reading header" )); } header_pos++; if ( header_pos >= 4 && buffer[header_pos-4] == CR && buffer[header_pos-3] == FF && buffer[header_pos-2] == CR && buffer[header_pos-1] == FF ){ break; } } String header = new String( buffer, 0, header_pos, Constants.BYTE_ENCODING ); if ( Logger.isEnabled()){ String log_str = header; int pos = log_str.indexOf( NL ); if ( pos != -1 ){ log_str = log_str.substring(0,pos); } Logger.log(new LogEvent(LOGID, "Tracker Server: received header '" + log_str + "' from " + socket.getRemoteSocketAddress())); } // System.out.println( "got header:" + header ); InputStream post_is = null; File post_file = null; String lowercase_header; boolean head = false; int url_start; if ( header.startsWith( "GET " )){ timeout_ticks = 1; lowercase_header = header.toLowerCase(); url_start = 4; }else if ( header.startsWith( "HEAD " )){ timeout_ticks = 1; lowercase_header = header.toLowerCase(); url_start = 5; head = true; }else if ( header.startsWith( "POST ")){ timeout_ticks = TRTrackerServerTCP.PROCESSING_POST_MULTIPLIER; if ( timeout_ticks == 0 ){ setTimeoutsDisabled( true ); } setTaskState( "reading content" ); lowercase_header = header.toLowerCase(); url_start = 5; String cl_str = getHeaderField( header, lowercase_header, "content-length:" ); if ( cl_str == null ){ throw( new Exception( "Content-Length missing" )); } int content_length = Integer.parseInt( cl_str ); ByteArrayOutputStream baos = null; FileOutputStream fos = null; OutputStream data_os; if ( content_length <= 256*1024 ){ baos = new ByteArrayOutputStream(); data_os = baos; }else{ post_file = AETemporaryFileHandler.createTempFile(); post_file.deleteOnExit(); fos = new FileOutputStream( post_file ); data_os = fos; } while( content_length > 0 ){ int len = is.read( buffer, 0, Math.min( content_length, buffer.length )); if ( len < 0 ){ throw( new TRTrackerServerException( "premature end of input stream" )); } data_os.write( buffer, 0, len ); content_length -= len; } if ( baos != null ){ post_is = new ByteArrayInputStream(baos.toByteArray()); }else{ fos.close(); post_is = new BufferedInputStream( new FileInputStream( post_file ), 256*1024 ); } // System.out.println( "TRTrackerServerProcessorTCP: request data = " + baos.size()); }else{ int pos = header.indexOf(' '); if ( pos == -1 ){ throw( new TRTrackerServerException( "header doesn't have space in right place" )); } timeout_ticks = 1; lowercase_header = header.toLowerCase(); url_start = pos+1; } setTaskState( "processing request" ); current_request = header; try{ if ( post_is == null ){ // set up a default input stream post_is = new ByteArrayInputStream(new byte[0]); } int url_end = header.indexOf( " ", url_start ); if ( url_end == -1 ){ throw( new TRTrackerServerException( "header doesn't have space in right place" )); } String url = header.substring( url_start, url_end ).trim(); int nl_pos = header.indexOf( NL, url_end ); if ( nl_pos == -1 ){ throw( new TRTrackerServerException( "header doesn't have nl in right place" )); } String http_ver = header.substring( url_end, nl_pos ).trim(); String con_str = getHeaderField( header, lowercase_header, "connection:" ); if ( con_str == null ){ if ( http_ver.equalsIgnoreCase( "HTTP/1.0" )){ keep_alive = false; } }else if ( con_str.equalsIgnoreCase( "close" )){ keep_alive = false; } if ( head ){ ByteArrayOutputStream head_response = new ByteArrayOutputStream(4096); if ( !processRequest( header, lowercase_header, url, (InetSocketAddress)socket.getLocalSocketAddress(), (InetSocketAddress)socket.getRemoteSocketAddress(), false, keep_alive, post_is, head_response, null )){ keep_alive = false; } byte[] head_data = head_response.toByteArray(); int header_length = head_data.length; for (int i=3;i 0 ){ thread_pool.setExecutionLimit( PROCESSING_GET_LIMIT ); } } public void runProcessor( TRTrackerServerProcessorTCP processor ) { thread_pool.run( processor ); } protected boolean isIPFilterEnabled() { return( apply_ip_filter ); } static boolean LOG_DOS_TO_FILE = false; static{ LOG_DOS_TO_FILE = System.getProperty("azureus.log.dos") != null; } protected static File dos_log_file; protected static AEMonitor class_mon = new AEMonitor( "TRTrackerServerTCP:class" ); Map DOS_map = new LinkedHashMap( 1000, (float)0.75, true ) { protected boolean removeEldestEntry( Map.Entry eldest) { return( checkDOSRemove( eldest )); } }; List dos_list = new ArrayList(128); long last_dos_check = 0; long MAX_DOS_ENTRIES = 10000; long MAX_DOS_RETENTION = 10000; int DOS_CHECK_DEAD_WOOD_COUNT = 512; int DOS_MIN_INTERVAL = 1000; int dos_check_count = 0; protected boolean checkDOS( String ip ) throws UnknownHostException { InetAddress inet_address = InetAddress.getByName(ip); if ( inet_address.isLoopbackAddress() || InetAddress.getLocalHost().equals( inet_address )){ return( false); } boolean res; last_dos_check = SystemTime.getCurrentTime(); DOSEntry entry = (DOSEntry)DOS_map.get(ip); if ( entry == null ){ entry = new DOSEntry(ip); DOS_map.put( ip, entry ); res = false; }else{ res = last_dos_check - entry.last_time < DOS_MIN_INTERVAL; if ( res && LOG_DOS_TO_FILE ){ dos_list.add( entry ); } entry.last_time = last_dos_check; } // remove dead wood dos_check_count++; if ( dos_check_count == DOS_CHECK_DEAD_WOOD_COUNT ){ dos_check_count = 0; Iterator it = DOS_map.values().iterator(); while( it.hasNext()){ DOSEntry this_entry = (DOSEntry)it.next(); if ( last_dos_check - this_entry.last_time > MAX_DOS_RETENTION ){ it.remove(); }else{ break; } } if ( dos_list.size() > 0 ){ try{ class_mon.enter(); if ( dos_log_file == null ){ dos_log_file = new File( System.getProperty("user.dir" ) + File.separator + "dos.log" ); } PrintWriter pw = null; try{ pw = new PrintWriter( new FileWriter( dos_log_file, true )); for (int i=0;i MAX_DOS_ENTRIES || last_dos_check - ((DOSEntry)eldest.getValue()).last_time > MAX_DOS_RETENTION; return( res ); } protected class DOSEntry { String ip; long last_time; protected DOSEntry( String _ip ) { ip = _ip; last_time = last_dos_check; } } public int getPort() { return( port ); } protected void setPort( int _port ) { port = _port; } public String getHost() { return( COConfigurationManager.getStringParameter( "Tracker IP", "" )); } public boolean isSSL() { return( ssl ); } protected boolean handleExternalRequest( final InetSocketAddress local_address, final InetSocketAddress client_address, final String user, final String url, final URL absolute_url, final String header, final InputStream is, final OutputStream os, final AsyncController async, final boolean[] keep_alive ) throws IOException { final boolean original_ka = keep_alive[0]; keep_alive[0] = false; for ( TRTrackerServerListener listener: listeners ){ if ( listener.handleExternalRequest( client_address, user, url, absolute_url, header, is, os, async )){ return( true ); } } for ( TRTrackerServerListener2 listener: listeners2 ){ TRTrackerServerListener2.ExternalRequest request = new TRTrackerServerListener2.ExternalRequest() { public InetSocketAddress getClientAddress() { return( client_address ); } public InetSocketAddress getLocalAddress() { return( local_address ); } public String getUser() { return( user ); } public String getURL() { return( url ); } public URL getAbsoluteURL() { return( absolute_url ); } public String getHeader() { return( header ); } public InputStream getInputStream() { return( is ); } public OutputStream getOutputStream() { return( os ); } public AsyncController getAsyncController() { return( async ); } public boolean canKeepAlive() { return( original_ka ); } public void setKeepAlive( boolean ka ) { keep_alive[0] = original_ka && ka; } }; if ( listener.handleExternalRequest( request )){ return( true ); } } return( false ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerProcessor.java0000644000175000017500000003577311223230212030670 0ustar adrianadrian/* * File : TRTrackerServerProcessor.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server.impl; /** * @author parg * */ import java.io.UnsupportedEncodingException; import java.util.*; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.tracker.server.*; import org.gudy.azureus2.core3.tracker.util.TRTrackerUtils; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition; public abstract class TRTrackerServerProcessor extends ThreadPoolTask { private static final boolean QUEUE_TEST = false; static{ if ( QUEUE_TEST ){ System.out.println( "**** TRTrackerServerProcessor::QUEUE_TEST ****" ); } } private TRTrackerServerImpl server; private long start; private int request_type; protected TRTrackerServerTorrentImpl processTrackerRequest( TRTrackerServerImpl _server, String request, Map[] root_out, // output TRTrackerServerPeerImpl[] peer_out, // output int _request_type, byte[][] hashes, String link, String scrape_flags, HashWrapper peer_id, boolean no_peer_id, byte compact_mode, String key, String event, boolean stop_to_queue, int port, int udp_port, int http_port, String real_ip_address, String original_client_ip_address, long downloaded, long uploaded, long left, int num_want, byte crypto_level, byte az_ver, int up_speed, DHTNetworkPosition network_position ) throws TRTrackerServerException { server = _server; request_type = _request_type; if ( !server.isReady()){ throw( new TRTrackerServerException( "Tracker initialising, please wait" )); } start = SystemTime.getHighPrecisionCounter(); boolean ip_override = real_ip_address != original_client_ip_address; boolean loopback = TRTrackerUtils.isLoopback( real_ip_address ); if ( loopback ){ // any override is purely for routing purposes for loopback connections and we don't // want to apply the ip-override precedence rules against us ip_override = false; } // translate any 127.0.0.1 local addresses back to the tracker address. Note this // fixes up .i2p and onion addresses back to their real values when needed String client_ip_address = TRTrackerUtils.adjustHostFromHosting( original_client_ip_address ); if ( client_ip_address != original_client_ip_address ){ if ( Logger.isEnabled()){ Logger.log( new LogEvent(LogIDs.TRACKER, " address adjusted: original=" + original_client_ip_address + ", real=" + real_ip_address + ", adjusted=" + client_ip_address + ", loopback=" + loopback )); } } if ( !TRTrackerServerImpl.getAllNetworksSupported()){ String network = AENetworkClassifier.categoriseAddress( client_ip_address ); String[] permitted_networks = TRTrackerServerImpl.getPermittedNetworks(); boolean ok = false; for (int i=0;i 0, stopped?0:num_want, interval, min_interval, no_peer_id, compact_mode, crypto_level, network_position ); peer_out[0] = peer; }else if ( request_type == TRTrackerServerRequest.RT_QUERY ){ if ( link == null ){ if ( hashes == null || hashes.length == 0 ){ throw( new TRTrackerServerException( "Hash missing from request ")); } if ( hashes.length != 1 ){ throw( new TRTrackerServerException( "Too many hashes for query")); } byte[] hash = hashes[0]; torrent = server.getTorrent( hash ); }else{ torrent = server.getTorrent( link ); } if ( torrent == null ){ throw( new TRTrackerServerException( "Torrent unauthorised" )); } long interval = server.getAnnounceRetryInterval( torrent ); root_out[0] = torrent.exportAnnounceToMap( client_ip_address, new HashMap(), null, true, num_want, interval, server.getMinAnnounceRetryInterval(), true, compact_mode, crypto_level, network_position ); }else{ if ( hashes == null || hashes.length == 0 ){ throw( new TRTrackerServerException( "Hash missing from request ")); } boolean local_scrape = client_ip_address.equals( "127.0.0.1" ); long max_interval = server.getMinScrapeRetryInterval(); Map root = new HashMap(); root_out[0] = root; Map files = new ByteEncodedKeyHashMap(); root.put( "files", files ); char[] scrape_chars = scrape_flags==null?null:scrape_flags.toCharArray(); if ( scrape_chars != null && scrape_chars.length != hashes.length ){ scrape_chars = null; } for (int i=0;i 0 && files.get( str_hash ) != null ){ continue; } }catch( UnsupportedEncodingException e ){ continue; } torrent = server.getTorrent( hash ); if ( torrent == null ){ if ( !COConfigurationManager.getBooleanParameter( "Tracker Public Enable")){ continue; }else{ try{ torrent = (TRTrackerServerTorrentImpl)server.permit( real_ip_address, hash, false ); }catch( Throwable e ){ continue; } } } long interval = server.getScrapeRetryInterval( torrent ); if ( interval > max_interval ){ max_interval = interval; } if ( scrape_chars != null && ( QUEUE_TEST || !( loopback || ip_override ))){ // note, 'Q' is complete+queued so we set seed true below if ( scrape_chars[i] == 'Q' ){ torrent.peerQueued( client_ip_address, port, udp_port, http_port, crypto_level, az_ver, (int)interval, true ); } } if ( torrent.getRedirects() != null ){ if ( hashes.length > 1 ){ // just drop this from the set. this will cause the client to revert // to single-hash scrapes and subsequently pick up the redirect continue; } } server.preProcess( new lightweightPeer(client_ip_address,port,peer_id), torrent, request_type, request, null ); // we don't cache local scrapes as if we do this causes the hosting of // torrents to retrieve old values initially. Not a fatal error but not // the best behaviour as the (local) seed isn't initially visible. Map hash_entry = torrent.exportScrapeToMap( request, client_ip_address, !local_scrape ); // System.out.println( "tracker - encoding: " + ByteFormatter.nicePrint(torrent_hash) + " -> " + ByteFormatter.nicePrint( str_hash.getBytes( Constants.BYTE_ENCODING ))); files.put( str_hash, hash_entry ); } if ( hashes.length > 1 ){ torrent = null; // no specific torrent } // System.out.println( "scrape: hashes = " + hashes.length + ", files = " + files.size() + ", tim = " + max_interval ); addScrapeInterval( max_interval, root ); } }else{ if ( !TRTrackerServerImpl.isFullScrapeEnabled()){ throw( new TRTrackerServerException( "Full scrape disabled" )); } Map files = new ByteEncodedKeyHashMap(); TRTrackerServerTorrentImpl[] torrents = server.getTorrents(); for (int i=0;i " + ByteFormatter.nicePrint( str_hash.getBytes( Constants.BYTE_ENCODING ))); Map hash_entry = this_torrent.exportScrapeToMap( request, client_ip_address, true ); files.put( str_hash, hash_entry ); }catch( UnsupportedEncodingException e ){ throw( new TRTrackerServerException( "Encoding error", e )); } } Map root = new HashMap(); root_out[0] = root; addScrapeInterval( null, root ); root.put( "files", files ); } return( torrent ); } protected void addScrapeInterval( TRTrackerServerTorrentImpl torrent, Map root ) { long interval = server.getScrapeRetryInterval( torrent ); addScrapeInterval( interval, root ); } protected void addScrapeInterval( long interval, Map root ) { if ( interval > 0 ){ Map flags = new HashMap(); flags.put("min_request_interval", new Long(interval)); root.put( "flags", flags ); } } public void taskCompleted() { if ( start > 0 ){ long time = SystemTime.getHighPrecisionCounter() - start; server.updateTime( request_type, time ); } } protected static class lightweightPeer implements TRTrackerServerPeer { private String ip; private int port; private byte[] peer_id; public lightweightPeer( String _ip, int _port, HashWrapper _peer_id ) { ip = _ip; port = _port; peer_id = _peer_id==null?null:_peer_id.getBytes(); } public long getUploaded() { return( -1 ); } public long getDownloaded() { return( -1 ); } public long getAmountLeft() { return( -1 ); } public String getIP() { return( ip ); } public String getIPRaw() { return( ip ); } public byte getNATStatus() { return( NAT_CHECK_UNKNOWN ); } public int getTCPPort() { return( port ); } public int getHTTPPort() { return( 0 ); } public int getUDPPort() { return( 0 ); } public byte[] getPeerID() { return( peer_id ); } public boolean isBiased() { return( false ); } public void setBiased( boolean biased ) { } public void setUserData( Object key, Object data ) { } public Object getUserData( Object key ) { return( null ); } public int getSecsToLive() { return( -1 ); } public Map export() { return( null ); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/dht/0000755000175000017500000000000011310377634023656 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/impl/dht/TRTrackerServerDHT.java0000644000175000017500000000333110670221666030112 0ustar adrianadrian/* * Created on 13-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.server.impl.dht; import org.gudy.azureus2.core3.tracker.server.TRTrackerServerRequestListener; import org.gudy.azureus2.core3.tracker.server.impl.TRTrackerServerImpl; /** * @author parg * */ public class TRTrackerServerDHT extends TRTrackerServerImpl { public TRTrackerServerDHT( String _name, boolean _start_up_ready ) { super( _name, _start_up_ready ); } public String getHost() { return( "dht"); } public int getPort() { return( -1 ); } public boolean isSSL() { return( false ); } public void addRequestListener( TRTrackerServerRequestListener l ) { } public void removeRequestListener( TRTrackerServerRequestListener l ) { } protected void closeSupport() { destroySupport(); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerFactory.java0000644000175000017500000000751410617007270027363 0ustar adrianadrian/* * File : TRTrackerServerFactory.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server; import java.net.InetAddress; import org.gudy.azureus2.core3.tracker.server.impl.*; public class TRTrackerServerFactory { public static final int PR_TCP = 1; public static final int PR_UDP = 2; public static final int PR_DHT = 3; public static TRTrackerServer create( int protocol, int port, boolean apply_ip_filter, boolean main_tracker ) throws TRTrackerServerException { return( TRTrackerServerFactoryImpl.create( "", protocol, port, null, false, apply_ip_filter, main_tracker, true )); } public static TRTrackerServer createSSL( int protocol, int port, boolean apply_ip_filter, boolean main_tracker ) throws TRTrackerServerException { return( TRTrackerServerFactoryImpl.create( "", protocol, port, null, true, apply_ip_filter, main_tracker, true )); } public static TRTrackerServer create( String name, int protocol, int port, boolean apply_ip_filter, boolean main_tracker ) throws TRTrackerServerException { return( TRTrackerServerFactoryImpl.create( name, protocol, port, null, false, apply_ip_filter, main_tracker, true )); } public static TRTrackerServer create( String name, int protocol, int port, boolean apply_ip_filter, boolean main_tracker, boolean start_up_ready ) throws TRTrackerServerException { return( TRTrackerServerFactoryImpl.create( name, protocol, port, null, false, apply_ip_filter, main_tracker, start_up_ready )); } public static TRTrackerServer createSSL( String name, int protocol, int port, boolean apply_ip_filter, boolean main_tracker ) throws TRTrackerServerException { return( TRTrackerServerFactoryImpl.create( name, protocol, port, null, true, apply_ip_filter, main_tracker, true )); } public static TRTrackerServer createSSL( String name, int protocol, int port, boolean apply_ip_filter, boolean main_tracker, boolean startup_ready ) throws TRTrackerServerException { return( TRTrackerServerFactoryImpl.create( name, protocol, port, null, true, apply_ip_filter, main_tracker, startup_ready )); } public static TRTrackerServer create( String name, int protocol, int port, InetAddress bind_ip, boolean apply_ip_filter, boolean main_tracker ) throws TRTrackerServerException { return( TRTrackerServerFactoryImpl.create( name, protocol, port, bind_ip, false, apply_ip_filter, main_tracker, true )); } public static TRTrackerServer createSSL( String name, int protocol, int port, InetAddress bind_ip, boolean apply_ip_filter, boolean main_tracker ) throws TRTrackerServerException { return( TRTrackerServerFactoryImpl.create( name, protocol, port, bind_ip, true, apply_ip_filter, main_tracker, true )); } public static void addListener( TRTrackerServerFactoryListener l ) { TRTrackerServerFactoryImpl.addListener( l ); } public static void removeListener( TRTrackerServerFactoryListener l ) { TRTrackerServerFactoryImpl.removeListener( l ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerAuthenticationListener.java0000644000175000017500000000300210373051046032424 0ustar adrianadrian/* * Created on 10-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.server; /** * @author parg * */ import java.net.URL; public interface TRTrackerServerAuthenticationListener { /** * checks the password against user and returns true if OK * @param resource * @param user * @param password * @return */ public boolean authenticate( URL resource, String user, String password ); /** * returns SHA1 hash of pw for user if available * @param resource * @param user * @return */ public byte[] authenticate( URL resource, String user ); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerRequest.java0000644000175000017500000000253610666167424027417 0ustar adrianadrian/* * File : TRTrackerServerRequest.java * Created : 13-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server; /** * @author parg * */ import java.util.Map; public interface TRTrackerServerRequest { public static final int RT_UNKNOWN = -1; public static final int RT_ANNOUNCE = 1; public static final int RT_SCRAPE = 2; public static final int RT_FULL_SCRAPE = 3; public static final int RT_QUERY = 4; public int getType(); public TRTrackerServerPeer getPeer(); public TRTrackerServerTorrent getTorrent(); public String getRequest(); public Map getResponse(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServer.java0000644000175000017500000000616111223045276026032 0ustar adrianadrian/* * File : TRTrackerServer.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server; import java.util.Set; import org.gudy.azureus2.core3.util.Constants; public interface TRTrackerServer { public static final String DEFAULT_NAME = Constants.AZUREUS_NAME; public static final int DEFAULT_MIN_RETRY_DELAY = 120; public static final int DEFAULT_MAX_RETRY_DELAY = 3600; public static final int DEFAULT_INC_BY = 60; public static final int DEFAULT_INC_PER = 10; public static final int DEFAULT_SCRAPE_RETRY_PERCENTAGE = 200; public static final int DEFAULT_SCRAPE_CACHE_PERIOD = 5000; public static final int DEFAULT_ANNOUNCE_CACHE_PERIOD = 500; public static final int DEFAULT_ANNOUNCE_CACHE_PEER_THRESHOLD = 500; public static final int DEFAULT_TRACKER_PORT = 6969; public static final int DEFAULT_TRACKER_PORT_SSL = 7000; public static final int DEFAULT_NAT_CHECK_SECS = 15; public String getName(); public int getPort(); public String getHost(); public void setReady(); public void setEnabled( boolean enabled ); public boolean isSSL(); public void setEnableKeepAlive( boolean enable ); public TRTrackerServerTorrent permit( String originator, byte[] hash, boolean explicit ) throws TRTrackerServerException; public TRTrackerServerTorrent permit( String originator, byte[] hash, boolean explicit, boolean enabled ) throws TRTrackerServerException; public void deny( byte[] hash, boolean explicit ) throws TRTrackerServerException; public TRTrackerServerTorrentStats getStats( byte[] hash ); public TRTrackerServerPeer[] getPeers( byte[] hash ); public TRTrackerServerStats getStats(); public void setBiasedPeers( Set ips ); public void addListener( TRTrackerServerListener l ); public void removeListener( TRTrackerServerListener l ); public void addListener2( TRTrackerServerListener2 l ); public void removeListener2( TRTrackerServerListener2 l ); public void addRequestListener( TRTrackerServerRequestListener l ); public void removeRequestListener( TRTrackerServerRequestListener l ); public void addAuthenticationListener( TRTrackerServerAuthenticationListener l ); public void removeAuthenticationListener( TRTrackerServerAuthenticationListener l ); public void close(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerListener2.java0000644000175000017500000000322411233522512027611 0ustar adrianadrian/* * Created on Jul 1, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.core3.tracker.server; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.URL; import org.gudy.azureus2.core3.util.AsyncController; public interface TRTrackerServerListener2 { public boolean handleExternalRequest( ExternalRequest request ) throws IOException; public interface ExternalRequest { public InetSocketAddress getClientAddress(); public InetSocketAddress getLocalAddress(); public String getUser(); public String getURL(); public URL getAbsoluteURL(); public String getHeader(); public InputStream getInputStream(); public OutputStream getOutputStream(); public AsyncController getAsyncController(); public boolean canKeepAlive(); public void setKeepAlive( boolean ka ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrent.java0000644000175000017500000000402411070576746027417 0ustar adrianadrian/* * File : TRTrackerServerTorrent.java * Created : 13-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server; /** * @author parg * */ import java.net.URL; import java.util.List; import org.gudy.azureus2.core3.util.*; public interface TRTrackerServerTorrent { public HashWrapper getHash(); public TRTrackerServerPeer[] getPeers(); public TRTrackerServerPeerBase[] getQueuedPeers(); public TRTrackerServerTorrentStats getStats(); public void disableCaching(); public void setMinBiasedPeers( int num ); public void setEnabled( boolean enabled ); public boolean isEnabled(); public void setRedirects( URL[] urls ); public URL[] getRedirects(); public TRTrackerServerTorrent addLink( String link ); public void removeLink( String link ); public void addExplicitBiasedPeer( String ip, int port ); public void remove( TRTrackerServerPeerBase peer ); public void addListener( TRTrackerServerTorrentListener l ); public void removeListener( TRTrackerServerTorrentListener l ); public void addPeerListener( TRTrackerServerTorrentPeerListener l ); public void removePeerListener( TRTrackerServerTorrentPeerListener l ); public void importPeers( List peers ); public String getString(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerRequestListener.java0000644000175000017500000000222410221666410031101 0ustar adrianadrian/* * File : TRTrackerServerExtensionListener.java * Created : 13-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server; /** * @author parg * */ public interface TRTrackerServerRequestListener { public void preProcess( TRTrackerServerRequest request ) throws TRTrackerServerException; public void postProcess( TRTrackerServerRequest request ) throws TRTrackerServerException; }azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentListener.java0000644000175000017500000000217510373051046031114 0ustar adrianadrian/* * Created on 01-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.server; /** * @author parg * */ public interface TRTrackerServerTorrentListener { public void deleted( TRTrackerServerTorrent torrent ); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerPeer.java0000644000175000017500000000363310734547356026663 0ustar adrianadrian/* * File : TRTrackerServerPeer.java * Created : 31-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server; import java.util.Map; /** * @author parg */ public interface TRTrackerServerPeer extends TRTrackerServerPeerBase { public static final byte NAT_CHECK_UNKNOWN = 0; public static final byte NAT_CHECK_DISABLED = 1; public static final byte NAT_CHECK_INITIATED = 2; public static final byte NAT_CHECK_OK = 3; public static final byte NAT_CHECK_FAILED = 4; public static final byte NAT_CHECK_FAILED_AND_REPORTED = 5; public static final byte CRYPTO_NONE = 0; public static final byte CRYPTO_SUPPORTED = 1; public static final byte CRYPTO_REQUIRED = 2; public long getUploaded(); public long getDownloaded(); public long getAmountLeft(); public String getIPRaw(); public byte[] getPeerID(); /** * returns the current NAT status of the peer * @return */ public byte getNATStatus(); public boolean isBiased(); public void setBiased( boolean bias ); public void setUserData( Object key, Object data ); public Object getUserData( Object key ); public Map export(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerStats.java0000644000175000017500000000223710722746732027061 0ustar adrianadrian/* * File : TRTrackerServerStats.java * Created : 09-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server; /** * @author parg * */ public interface TRTrackerServerStats { public int getTorrentCount(); public long getBytesIn(); public long getBytesOut(); public long getAnnounceCount(); public long getScrapeCount(); public long getAnnounceTime(); public long getScrapeTime(); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentPeerListener.java0000644000175000017500000000377510605645054031745 0ustar adrianadrian/* * Created on 18 May 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.server; import java.util.Map; public interface TRTrackerServerTorrentPeerListener { public static final int ET_STARTED = 1; public static final int ET_UPDATED = 2; public static final int ET_COMPLETE = 3; // all the following result in the peer being removed from the tracker's tables public static final int ET_STOPPED = 4; // peer removed due to stop public static final int ET_TIMEOUT = 5; // peer has timed out and been removed public static final int ET_REPLACED = 5; // peer's address has changed and someone else already has it - old one is removed public static final int ET_TOO_MANY_PEERS = 6; // peer removed due to too many peers public static final int ET_FAILED = 7; // eventOccurred method threw exception public static final int ET_ANNOUNCE = 8; // announce event - reply can contain List of explicit peers to return public Map eventOccurred( TRTrackerServerTorrent torrent, TRTrackerServerPeer peer, int event, String url_parameters ) throws TRTrackerServerException; } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerFactoryListener.java0000644000175000017500000000210210670221664031061 0ustar adrianadrian/* * File : TRTrackerServerFactoryListener.java * Created : 13-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server; /** * @author parg * */ public interface TRTrackerServerFactoryListener { public void serverCreated( TRTrackerServer server ); public void serverDestroyed( TRTrackerServer server ); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerListener.java0000644000175000017500000000272511062635756027553 0ustar adrianadrian/* * File : TRTrackerServerListener.java * Created : 05-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.tracker.server; /** * @author parg * */ import java.io.*; import java.net.InetSocketAddress; import java.net.URL; import org.gudy.azureus2.core3.util.AsyncController; public interface TRTrackerServerListener { public boolean handleExternalRequest( InetSocketAddress client_address, String user, String url, URL absolute_url, String header, InputStream is, OutputStream os, AsyncController async ) throws IOException; public boolean permitted( String originator, byte[] hash, boolean explicit ); public boolean denied( byte[] hash, boolean explicit ); } azureus-4.3.0.6/org/gudy/azureus2/core3/tracker/server/TRTrackerServerPeerBase.java0000644000175000017500000000221111173776722027444 0ustar adrianadrian/* * Created on Jun 5, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.tracker.server; public interface TRTrackerServerPeerBase { public String getIP(); public int getTCPPort(); public int getHTTPPort(); public int getSecsToLive(); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/0000755000175000017500000000000011310377634021004 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerStateFactory.java0000644000175000017500000000320210540166164027235 0ustar adrianadrian/* * Created on 15-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.download; import org.gudy.azureus2.core3.download.impl.*; import org.gudy.azureus2.core3.torrent.*; /** * @author parg * */ public class DownloadManagerStateFactory { public static DownloadManagerState getDownloadState( TOTorrent torrent ) throws TOTorrentException { return( DownloadManagerStateImpl.getDownloadState( torrent )); } public static void loadGlobalStateCache() { DownloadManagerStateImpl.loadGlobalStateCache(); } public static void saveGlobalStateCache() { DownloadManagerStateImpl.saveGlobalStateCache(); } public static void discardGlobalStateCache() { DownloadManagerStateImpl.discardGlobalStateCache(); } } azureus-4.3.0.6/org/gudy/azureus2/core3/download/impl/0000755000175000017500000000000011310377634021745 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/download/impl/DownloadManagerController.java0000644000175000017500000017200211264071660027716 0ustar adrianadrian/* * Created on 29-Jul-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.download.impl; import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerDiskListener; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.download.ForceRecheckListener; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerStats; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.LogRelation; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.peer.*; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerDataProvider; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.network.ConnectionManager; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.networkmanager.LimitedRateGroup; import com.aelitis.azureus.core.networkmanager.NetworkConnection; import com.aelitis.azureus.core.peermanager.PeerManager; import com.aelitis.azureus.core.peermanager.PeerManagerRegistration; import com.aelitis.azureus.core.peermanager.PeerManagerRegistrationAdapter; import com.aelitis.azureus.core.peermanager.peerdb.PeerItemFactory; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.core.util.bloom.BloomFilterFactory; import com.aelitis.azureus.plugins.extseed.ExternalSeedPlugin; public class DownloadManagerController extends LogRelation implements PEPeerManagerAdapter, PeerManagerRegistrationAdapter { private static long STATE_FLAG_HASDND = 0x01; private static long STATE_FLAG_COMPLETE_NO_DND = 0x02; private static long skeleton_builds; private static ExternalSeedPlugin ext_seed_plugin; private static boolean ext_seed_plugin_tried; private static ExternalSeedPlugin getExternalSeedPlugin() { if ( !ext_seed_plugin_tried ){ ext_seed_plugin_tried = true; try { org.gudy.azureus2.plugins.PluginInterface ext_pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass(ExternalSeedPlugin.class); if (ext_pi != null) { ext_seed_plugin = (ExternalSeedPlugin)ext_pi.getPlugin(); } }catch (Throwable e){ Debug.printStackTrace( e ); } } return( ext_seed_plugin ); } // DISK listeners private static final int LDT_DL_ADDED = 1; private static final int LDT_DL_REMOVED = 2; private static ListenerManager disk_listeners_agregator = ListenerManager.createAsyncManager( "DMC:DiskListenAgregatorDispatcher", new ListenerManagerDispatcher() { public void dispatch( Object _listener, int type, Object value ) { DownloadManagerDiskListener listener = (DownloadManagerDiskListener)_listener; if ( type == LDT_DL_ADDED ){ listener.diskManagerAdded((DiskManager)value); }else if ( type == LDT_DL_REMOVED ){ listener.diskManagerRemoved((DiskManager)value); } } }); private ListenerManager disk_listeners = ListenerManager.createManager( "DMC:DiskListenDispatcher", new ListenerManagerDispatcher() { public void dispatch( Object listener, int type, Object value ) { disk_listeners_agregator.dispatch( listener, type, value ); } }); private AEMonitor disk_listeners_mon = new AEMonitor( "DownloadManagerController:DL" ); protected AEMonitor this_mon = new AEMonitor( "DownloadManagerController" ); protected AEMonitor state_mon = new AEMonitor( "DownloadManagerController:State" ); private DownloadManagerImpl download_manager; private DownloadManagerStatsImpl stats; // these are volatile as we want to ensure that if a state is read it is always the // most up to date value available (as we don't synchronize state read - see below // for comments) private volatile int state_set_by_method = DownloadManager.STATE_START_OF_DAY; private volatile int substate; private volatile boolean force_start; // to try and ensure people don't start using disk_manager without properly considering its // access implications we've given it a silly name private volatile DiskManager disk_manager_use_accessors; private DiskManagerListener disk_manager_listener_use_accessors; private FileInfoFacadeSet fileFacadeSet = new FileInfoFacadeSet(); private boolean files_facade_destroyed; private boolean cached_complete_excluding_dnd; private boolean cached_has_dnd_files; private boolean cached_values_set; private PeerManagerRegistration peer_manager_registration; private PEPeerManager peer_manager; private List external_rate_limiters_cow; private String errorDetail; private GlobalManagerStats global_stats; private boolean bInitialized = false; private long data_send_rate_at_close; private static final int ACTIVATION_REBUILD_TIME = 10*60*1000; private static final int BLOOM_SIZE = 64; private volatile BloomFilter activation_bloom; private volatile long activation_bloom_create_time = SystemTime.getCurrentTime(); private volatile int activation_count; private volatile long activation_count_time; private boolean piece_checking_enabled = true; private long priority_connection_count; protected DownloadManagerController( DownloadManagerImpl _download_manager ) { download_manager = _download_manager; GlobalManager gm = download_manager.getGlobalManager(); global_stats = gm.getStats(); stats = (DownloadManagerStatsImpl)download_manager.getStats(); cached_values_set = false; } protected void setInitialState( int initial_state ) { // only take note if there's been no errors bInitialized = true; if ( getState() == DownloadManager.STATE_START_OF_DAY ){ setState( initial_state, true ); } TOTorrent torrent = download_manager.getTorrent(); if (torrent != null) { try{ peer_manager_registration = PeerManager.getSingleton().registerLegacyManager( torrent.getHashWrapper(), this ); }catch( TOTorrentException e ){ Debug.printStackTrace(e); } } DownloadManagerState state = download_manager.getDownloadState(); if (state.parameterExists(DownloadManagerState.PARAM_DND_FLAGS)) { long flags = state.getLongParameter(DownloadManagerState.PARAM_DND_FLAGS); cached_complete_excluding_dnd = (flags & STATE_FLAG_COMPLETE_NO_DND) != 0; cached_has_dnd_files = (flags & STATE_FLAG_HASDND) != 0; cached_values_set = true; } } public void startDownload( TRTrackerAnnouncer tracker_client ) { DiskManager dm; try{ this_mon.enter(); if ( getState() != DownloadManager.STATE_READY ){ Debug.out( "DownloadManagerController::startDownload state must be ready, " + getState()); setFailed( "Inconsistent download state: startDownload, state = " + getState()); return; } if ( tracker_client == null ){ Debug.out( "DownloadManagerController:startDownload: tracker_client is null" ); // one day we should really do a proper state machine for this. In the meantime... // probably caused by a "stop" during initialisation, I've reproduced it once or twice // in my life... Tidy things up so we don't sit here in a READ state that can't // be started. stopIt( DownloadManager.STATE_STOPPED, false, false ); return; } if ( peer_manager != null ){ Debug.out( "DownloadManagerController::startDownload: peer manager not null" ); // try and continue.... peer_manager.stopAll(); peer_manager = null; } dm = getDiskManager(); if ( dm == null ){ Debug.out( "DownloadManagerController::startDownload: disk manager is null" ); return; } setState( DownloadManager.STATE_DOWNLOADING, false ); }finally{ this_mon.exit(); } // make sure it is started before making it "visible" final PEPeerManager temp = PEPeerManagerFactory.create( tracker_client.getPeerId(), this, dm ); download_manager.informWillBeStarted( temp ); temp.start(); //The connection to the tracker tracker_client.setAnnounceDataProvider( new TRTrackerAnnouncerDataProvider() { private long last_reported_total_received; private long last_reported_total_received_data; private long last_reported_total_received_discard; private long last_reported_total_received_failed; public String getName() { return( getDisplayName()); } public long getTotalSent() { return(temp.getStats().getTotalDataBytesSentNoLan()); } public long getTotalReceived() { long received = temp.getStats().getTotalDataBytesReceivedNoLan(); long discarded = temp.getStats().getTotalDiscarded(); long failed = temp.getStats().getTotalHashFailBytes(); long verified = received - ( discarded + failed ); verified -= temp.getHiddenBytes(); // ensure we don't go backwards. due to lack of atomicity of updates and possible // miscounting somewhere we have seen this occur if ( verified < last_reported_total_received ){ verified = last_reported_total_received; // use -1 as indicator that we've reported this event if ( last_reported_total_received_data != -1 ){ /* Debug.out( getDisplayName() + ": decrease in overall downloaded - " + "data=" + received + "/" + last_reported_total_received_data + ",discard=" + discarded + "/" + last_reported_total_received_discard + ",fail=" + failed + "/" + last_reported_total_received_failed ); */ last_reported_total_received_data = -1; } }else{ last_reported_total_received = verified; last_reported_total_received_data = received; last_reported_total_received_discard = discarded; last_reported_total_received_failed = failed; } return( verified < 0?0:verified ); } public long getRemaining() { return( Math.max( temp.getRemaining(), temp.getHiddenBytes())); } public long getFailedHashCheck() { return( temp.getStats().getTotalHashFailBytes()); } public String getExtensions() { return( getTrackerClientExtensions()); } public int getMaxNewConnectionsAllowed() { return( temp.getMaxNewConnectionsAllowed()); } public int getUploadSpeedKBSec( boolean estimate ) { long current_local = stats.getDataSendRate(); if ( estimate ){ // see if we have an old value from previous stop/start current_local = data_send_rate_at_close; if ( current_local == 0 ){ int current_global = global_stats.getDataSendRate(); int old_global = global_stats.getDataSendRateAtClose(); if ( current_global < old_global ){ current_global = old_global; } List managers = download_manager.getGlobalManager().getDownloadManagers(); int num_dls = 0; // be optimistic and share out the bytes between non-seeds for (int i=0;i allowed = new HashSet(); allowed.addAll( Arrays.asList( allowed_sources )); Iterator it = pm.getPeers().iterator(); while( it.hasNext()){ PEPeer peer = it.next(); if ( !allowed.contains( peer.getPeerSource())){ pm.removePeer( peer, "Peer source not permitted" ); } } } } public boolean isPeerSourceEnabled( String peer_source ) { return( DownloadManagerController.this.isPeerSourceEnabled( peer_source )); } }); List limiters; try{ this_mon.enter(); peer_manager = temp; limiters = external_rate_limiters_cow; }finally{ this_mon.exit(); } if ( limiters != null ){ for (int i=0;i 0 ){ stats.setSavedDownloadedUploaded( download_manager.getSize()*dl_copies, stats.getTotalDataBytesSent()); } download_manager.getDownloadState().setFlag( DownloadManagerState.FLAG_ONLY_EVER_SEEDED, true ); } } /* all initialization should be done here (Disk- and DownloadManager). * assume this download is complete and won't recieve any modifications until it is stopped again * or the user fiddles on the knobs * discard fluff once tentatively, will save memory for many active, seeding torrent-cases */ if(completed == 1000) download_manager.getDownloadState().discardFluff(); } }finally{ download_manager.informStateChanged(); } } public void filePriorityChanged( DiskManagerFileInfo file ) { download_manager.informPriorityChange( file ); } public void pieceDoneChanged( DiskManagerPiece piece ) { } public void fileAccessModeChanged( DiskManagerFileInfo file, int old_mode, int new_mode ) { } }); } protected void initializeDiskManagerSupport( int initialising_state, DiskManagerListener listener ) { try{ this_mon.enter(); int entry_state = getState(); if ( entry_state != DownloadManager.STATE_WAITING && entry_state != DownloadManager.STATE_STOPPED && entry_state != DownloadManager.STATE_QUEUED && entry_state != DownloadManager.STATE_ERROR ){ Debug.out( "DownloadManagerController::initializeDiskManager: Illegal initialize state, " + entry_state ); setFailed( "Inconsistent download state: initSupport, state = " + entry_state ); return; } DiskManager old_dm = getDiskManager(); if ( old_dm != null ){ Debug.out( "DownloadManagerController::initializeDiskManager: disk manager is not null" ); // we shouldn't get here but try to recover the situation old_dm.stop( false ); setDiskManager( null, null ); } errorDetail = ""; setState( initialising_state, false ); DiskManager dm = DiskManagerFactory.create( download_manager.getTorrent(), download_manager); setDiskManager( dm, listener ); }finally{ this_mon.exit(); download_manager.informStateChanged(); } } public boolean canForceRecheck() { int state = getState(); // gotta check error + disk manager state as error can be generated by both // an overall error or a running disk manager in faulty state return( (state == DownloadManager.STATE_STOPPED ) || (state == DownloadManager.STATE_QUEUED ) || (state == DownloadManager.STATE_ERROR && getDiskManager() == null)); } public void forceRecheck(final ForceRecheckListener l) { try{ this_mon.enter(); if ( getDiskManager() != null || !canForceRecheck() ){ Debug.out( "DownloadManagerController::forceRecheck: illegal entry state" ); return; } final int start_state = DownloadManagerController.this.getState(); // remove resume data download_manager.getDownloadState().clearResumeData(); // For extra protection from a plugin stopping a checking torrent, // fake a forced start. final boolean wasForceStarted = force_start; force_start = true; // if a file has been deleted we want this recheck to recreate the file and mark // it as 0%, not fail the recheck. Otherwise the only way of recovering is to remove and // re-add the torrent download_manager.setDataAlreadyAllocated( false ); initializeDiskManagerSupport( DownloadManager.STATE_CHECKING, new forceRecheckDiskManagerListener(wasForceStarted, start_state, l)); }finally{ this_mon.exit(); } } public void setPieceCheckingEnabled( boolean enabled ) { piece_checking_enabled = enabled; DiskManager dm = getDiskManager(); if ( dm != null ){ dm.setPieceCheckingEnabled( enabled ); } } public void stopIt( int _stateAfterStopping, final boolean remove_torrent, final boolean remove_data ) { long current_up = stats.getDataSendRate(); if ( current_up != 0 ){ data_send_rate_at_close = current_up; } boolean closing = _stateAfterStopping == DownloadManager.STATE_CLOSED; if ( closing ){ _stateAfterStopping = DownloadManager.STATE_STOPPED; } final int stateAfterStopping = _stateAfterStopping; try{ this_mon.enter(); int state = getState(); if ( state == DownloadManager.STATE_STOPPED || ( state == DownloadManager.STATE_ERROR && getDiskManager() == null )) { //already in stopped state, just do removals if necessary if( remove_data ){ download_manager.deleteDataFiles(); } if( remove_torrent ){ download_manager.deleteTorrentFile(); } setState( _stateAfterStopping, false ); return; } if ( state == DownloadManager.STATE_STOPPING){ return; } setSubState( _stateAfterStopping ); setState( DownloadManager.STATE_STOPPING, false ); // this will run synchronously but on a non-daemon thread so that it will under // normal circumstances complete, even if we're closing final AESemaphore nd_sem = new AESemaphore( "DM:DownloadManager.NDTR" ); NonDaemonTaskRunner.runAsync( new NonDaemonTask() { public Object run() { nd_sem.reserve(); return( null ); } public String getName() { return( "Stopping '" + getDisplayName() + "'" ); } }); try{ try{ if ( peer_manager != null ){ peer_manager.stopAll(); stats.saveSessionTotals(); } // do this even if null as it also triggers tracker actions download_manager.informStopped( peer_manager, stateAfterStopping==DownloadManager.STATE_QUEUED ); peer_manager = null; DiskManager dm = getDiskManager(); if ( dm != null ){ dm.stop( closing ); stats.setCompleted(stats.getCompleted()); stats.setDownloadCompleted(stats.getDownloadCompleted(true)); // we don't want to update the torrent if we're seeding if ( !download_manager.getAssumedComplete()){ download_manager.getDownloadState().save(); } setDiskManager( null, null ); } }finally{ force_start = false; if( remove_data ){ download_manager.deleteDataFiles(); } if( remove_torrent ){ download_manager.deleteTorrentFile(); } // only update the state if things haven't gone wrong if ( getState() == DownloadManager.STATE_STOPPING ){ setState( stateAfterStopping, true ); } } }finally{ nd_sem.release(); } }catch( Throwable e ){ Debug.printStackTrace( e ); }finally{ this_mon.exit(); download_manager.informStateChanged(); } } protected void setStateWaiting() { setState(DownloadManager.STATE_WAITING, true ); } public void setStateFinishing() { setState(DownloadManager.STATE_FINISHING, true); } public void setStateDownloading() { if (getState() == DownloadManager.STATE_SEEDING) { setState(DownloadManager.STATE_DOWNLOADING, true); } else if (getState() != DownloadManager.STATE_DOWNLOADING) { Logger.log(new LogEvent(this, LogIDs.CORE, LogEvent.LT_WARNING, "Trying to set state to downloading when state is not seeding")); } } public void setStateSeeding( boolean never_downloaded ) { // should already be finishing, but make sure (if it already is, there // won't be a trigger) setStateFinishing(); download_manager.downloadEnded(never_downloaded); setState(DownloadManager.STATE_SEEDING, true); } public boolean isStateSeeding() { return( getState() == DownloadManager.STATE_SEEDING ); } protected void setStateQueued() { setState(DownloadManager.STATE_QUEUED, true); } public int getState() { if ( state_set_by_method != DownloadManager.STATE_INITIALIZED ){ return( state_set_by_method ); } // we don't want to synchronize here as there are potential deadlock problems // regarding the DownloadManager::addListener call invoking this method while // holding the listeners monitor. // DiskManager dm = getDiskManager(); if ( dm == null){ return DownloadManager.STATE_INITIALIZED; } int diskManagerState = dm.getState(); if (diskManagerState == DiskManager.INITIALIZING){ return DownloadManager.STATE_INITIALIZED; }else if (diskManagerState == DiskManager.ALLOCATING){ return DownloadManager.STATE_ALLOCATING; }else if (diskManagerState == DiskManager.CHECKING){ return DownloadManager.STATE_CHECKING; }else if (diskManagerState == DiskManager.READY){ return DownloadManager.STATE_READY; }else if (diskManagerState == DiskManager.FAULTY){ return DownloadManager.STATE_ERROR; } return DownloadManager.STATE_ERROR; } protected int getSubState() { if ( state_set_by_method == DownloadManager.STATE_STOPPING ){ return( substate ); }else{ return( getState()); } } private void setSubState( int ss ) { substate = ss; } /** * @param _state * @param _inform_changed trigger informStateChange (which may not trigger * listeners if state hasn't changed since last trigger) */ private void setState( int _state, boolean _inform_changed ) { // we bring this call out of the monitor block to prevent a potential deadlock whereby we chain // state_mon -> this_mon (there exist numerous dependencies this_mon -> state_mon... boolean call_filesExist = false; try{ state_mon.enter(); int old_state = state_set_by_method; // note: there is a DIFFERENCE between the state held on the DownloadManager and // that reported via getState as getState incorporated DiskManager states when // the DownloadManager is INITIALIZED //System.out.println( "DM:setState - " + _state ); if ( old_state != _state ){ state_set_by_method = _state; if ( state_set_by_method != DownloadManager.STATE_QUEUED ){ // only maintain this while queued activation_bloom = null; if ( state_set_by_method == DownloadManager.STATE_STOPPED ){ activation_count = 0; } } if (state_set_by_method == DownloadManager.STATE_QUEUED ){ // don't pick up errors regarding missing data while queued. // We'll do that when the torrent starts. Saves time at startup // pick up any errors regarding missing data for queued SEEDING torrents // if ( download_manager.getAssumedComplete()){ // // call_filesExist = true; // } }else if ( state_set_by_method == DownloadManager.STATE_ERROR ){ // the process of attempting to start the torrent may have left some empty // directories created, some users take exception to this. // the most straight forward way of remedying this is to delete such empty // folders here TOTorrent torrent = download_manager.getTorrent(); if ( torrent != null && !torrent.isSimpleTorrent()){ File save_dir_file = download_manager.getAbsoluteSaveLocation(); if ( save_dir_file != null && save_dir_file.exists() && save_dir_file.isDirectory()){ TorrentUtils.recursiveEmptyDirDelete( save_dir_file, false ); } } } } }finally{ state_mon.exit(); } if ( call_filesExist ){ filesExist( true ); } if ( _inform_changed ){ download_manager.informStateChanged(); } } /** * Stops the current download, then restarts it again. */ public void restartDownload(boolean forceRecheck) { boolean was_force_start = isForceStart(); stopIt( DownloadManager.STATE_STOPPED, false, false ); if (forceRecheck) { download_manager.getDownloadState().clearResumeData(); } download_manager.initialize(); if ( was_force_start ){ setForceStart(true); } } protected void destroy() { if ( peer_manager_registration != null ){ peer_manager_registration.unregister(); peer_manager_registration = null; } fileFacadeSet.destroyFileInfo(); } public boolean isPeerSourceEnabled( String peer_source ) { return( download_manager.getDownloadState().isPeerSourceEnabled( peer_source )); } // secrets for inbound connections, support all public byte[][] getSecrets() { TOTorrent torrent = download_manager.getTorrent(); try{ byte[] secret1 = torrent.getHash(); try{ byte[] secret2 = getSecret2( torrent ); return( new byte[][]{ secret1, secret2 }); }catch( Throwable e ){ Debug.printStackTrace( e ); return( new byte[][]{ secret1 } ); } }catch( Throwable e ){ Debug.printStackTrace( e ); return( new byte[0][] ); } } // secrets for outbound connections, based on level of target public byte[][] getSecrets( int crypto_level ) { TOTorrent torrent = download_manager.getTorrent(); try{ byte[] secret; if ( crypto_level == PeerItemFactory.CRYPTO_LEVEL_1 ){ secret = torrent.getHash(); }else{ secret = getSecret2( torrent ); } return( new byte[][]{ secret }); }catch( Throwable e ){ Debug.printStackTrace( e ); return( new byte[0][] ); } } protected byte[] getSecret2( TOTorrent torrent ) throws TOTorrentException { Map secrets_map = download_manager.getDownloadState().getMapAttribute( DownloadManagerState.AT_SECRETS ); if ( secrets_map == null ){ secrets_map = new HashMap(); }else{ // clone as we can't just update the returned values secrets_map = new LightHashMap(secrets_map); } if ( secrets_map.size() == 0 ){ secrets_map.put( "p1", torrent.getPieces()[0] ); download_manager.getDownloadState().setMapAttribute( DownloadManagerState.AT_SECRETS, secrets_map ); } return((byte[])secrets_map.get( "p1" )); } public boolean manualRoute( NetworkConnection connection ) { return false; } public long getRandomSeed() { return( download_manager.getDownloadState().getLongParameter( DownloadManagerState.PARAM_RANDOM_SEED )); } public void addRateLimiter( LimitedRateGroup group, boolean upload ) { PEPeerManager pm; try{ this_mon.enter(); ArrayList new_limiters = new ArrayList( external_rate_limiters_cow==null?1:external_rate_limiters_cow.size()+1); if ( external_rate_limiters_cow != null ){ new_limiters.addAll( external_rate_limiters_cow ); } new_limiters.add( new Object[]{ group, new Boolean( upload )}); external_rate_limiters_cow = new_limiters; pm = peer_manager; }finally{ this_mon.exit(); } if ( pm != null ){ pm.addRateLimiter(group, upload); } } public void removeRateLimiter( LimitedRateGroup group, boolean upload ) { PEPeerManager pm; try{ this_mon.enter(); if ( external_rate_limiters_cow != null ){ ArrayList new_limiters = new ArrayList( external_rate_limiters_cow.size()-1); for (int i=0;i 5 ){ Logger.log( new LogEvent( this, LogIDs.CORE, LogEvent.LT_WARNING, "Activate request for " + getDisplayName() + " from " + address + " denied as too many recently received" )); return( false ); } Logger.log(new LogEvent(this, LogIDs.CORE, "Activate request for " + getDisplayName() + " from " + address )); long now = SystemTime.getCurrentTime(); // we don't really care about the bloom filter filling up and giving false positives // as activation events should be fairly rare if ( now < activation_bloom_create_time || now - activation_bloom_create_time > ACTIVATION_REBUILD_TIME ){ activation_bloom = BloomFilterFactory.createAddRemove4Bit( BLOOM_SIZE ); activation_bloom_create_time = now; } activation_count = bloom.getEntryCount(); activation_count_time = now; return( download_manager.activateRequest( activation_count )); } return( false ); } public void deactivateRequest( InetSocketAddress address ) { BloomFilter bloom = activation_bloom; if ( bloom != null ){ byte[] address_bytes = address.getAddress().getAddress(); int count = bloom.count( address_bytes); for (int i=0;i ACTIVATION_REBUILD_TIME ){ activation_count = 0; } return( activation_count ); } public PeerManagerRegistration getPeerManagerRegistration() { return( peer_manager_registration ); } public boolean isForceStart() { return( force_start ); } public void setForceStart( boolean _force_start) { try{ state_mon.enter(); if ( force_start != _force_start ){ force_start = _force_start; int state = getState(); if ( force_start && ( state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_QUEUED )) { // Start it! (Which will cause a stateChanged to trigger) setState(DownloadManager.STATE_WAITING, false ); } } }finally{ state_mon.exit(); } // "state" includes the force-start setting download_manager.informStateChanged(); } protected void setFailed( String reason ) { if ( reason != null ){ errorDetail = reason; } stopIt( DownloadManager.STATE_ERROR, false, false ); } public boolean filesExist( boolean expected_to_be_allocated ) { if ( !expected_to_be_allocated ){ if ( !download_manager.isDataAlreadyAllocated()){ return( false ); } } DiskManager dm = getDiskManager(); if (dm != null) { return dm.filesExist(); } fileFacadeSet.makeSureFilesFacadeFilled(false); DiskManagerFileInfo[] files = fileFacadeSet.getFiles(); for (int i = 0; i < files.length; i++) { DiskManagerFileInfo fileInfo = files[i]; if (!fileInfo.isSkipped()) { File file = fileInfo.getFile(true); try { if (!file.exists()) { // For multi-file torrents, complain if the save directory is missing. if (!this.download_manager.getTorrent().isSimpleTorrent()) { File save_path = this.download_manager.getAbsoluteSaveLocation(); if (FileUtil.isAncestorOf(save_path, file) && !save_path.exists()) { file = save_path; // We're going to abort very soon, so it's OK to overwrite this. } } setFailed(MessageText.getString("DownloadManager.error.datamissing") + " " + file); return false; } else if (fileInfo.getLength() < file.length()) { // file may be incremental creation - don't complain if too small // don't bitch if the user is happy with this if ( !COConfigurationManager.getBooleanParameter("File.truncate.if.too.large")){ setFailed(MessageText.getString("DownloadManager.error.badsize") + " " + file + "(" + fileInfo.getLength() + "/" + file.length() + ")"); return false; } } } catch (Exception e) { setFailed(e.getMessage()); return false; } } } return true; } public DiskManagerFileInfoSet getDiskManagerFileInfoSet() { fileFacadeSet.makeSureFilesFacadeFilled(false); return fileFacadeSet; } /** * @deprecated use getDiskManagerFileInfoSet() instead */ public DiskManagerFileInfo[] getDiskManagerFileInfo() { fileFacadeSet.makeSureFilesFacadeFilled(false); return( fileFacadeSet.getFiles() ); } protected void fileInfoChanged() { fileFacadeSet.makeSureFilesFacadeFilled(true); } protected void filePrioritiesChanged(List files) { if (!cached_values_set) { fileFacadeSet.makeSureFilesFacadeFilled(false); } // no need to calculate completeness if there are no DND files and the // file being changed is not DND if (!cached_has_dnd_files && files.size() == 1 && !((DiskManagerFileInfo)files.get(0)).isSkipped()){ return; } // if it's more than one file just do the scan anyway fileFacadeSet.makeSureFilesFacadeFilled(false); calculateCompleteness( fileFacadeSet.facadeFiles ); } protected void calculateCompleteness( DiskManagerFileInfo[] active ) { boolean complete_excluding_dnd = true; boolean has_dnd_files = false; for (int i = 0; i < active.length; i++) { DiskManagerFileInfo file = active[i]; if ( file.isSkipped()){ has_dnd_files = true; }else if (file.getDownloaded() != file.getLength()) { complete_excluding_dnd = false; } if(has_dnd_files && !complete_excluding_dnd) break; // we can bail out early } cached_complete_excluding_dnd = complete_excluding_dnd; cached_has_dnd_files = has_dnd_files; cached_values_set = true; DownloadManagerState state = download_manager.getDownloadState(); long flags = (cached_complete_excluding_dnd ? STATE_FLAG_COMPLETE_NO_DND : 0) | (cached_has_dnd_files ? STATE_FLAG_HASDND : 0); state.setLongParameter(DownloadManagerState.PARAM_DND_FLAGS, flags); } /** * Determine if the download is complete, excluding DND files. This * function is mostly cached when there is a DiskManager. * * @return completion state */ protected boolean isDownloadComplete(boolean bIncludeDND) { if (!cached_values_set) { fileFacadeSet.makeSureFilesFacadeFilled(false); } // The calculate from stats doesn't take into consideration DND // So, if we have no DND files, use calculation from stats, which // remembers things like whether the file was once complete if (!cached_has_dnd_files) { return stats.getDownloadCompleted(false) == 1000; } // We have DND files. If we have an existing diskmanager, then it // will have better information than the stats object. DiskManager dm = getDiskManager(); //System.out.println(dm + ":" + (dm == null ? "null" : dm.getState() + ";" + dm.getRemainingExcludingDND())); if (dm != null) { int dm_state = dm.getState(); if (dm_state == DiskManager.READY) { long remaining = bIncludeDND ? dm.getRemaining() : dm.getRemainingExcludingDND(); return remaining == 0; } } // No DiskManager or it's in a bad state for us. // Assumed: We have DND files if (bIncludeDND) { // Want to include DND files in calculation, which there some, which // means completion MUST be false return false; } // Have DND files, bad DiskManager, and we don't want to include DND files return cached_complete_excluding_dnd; } protected PEPeerManager getPeerManager() { return( peer_manager ); } protected DiskManager getDiskManager() { return( disk_manager_use_accessors ); } protected String getErrorDetail() { return( errorDetail ); } protected void setDiskManager( DiskManager new_disk_manager, DiskManagerListener new_disk_manager_listener ) { if ( new_disk_manager != null ){ new_disk_manager.setPieceCheckingEnabled( piece_checking_enabled ); } try{ disk_listeners_mon.enter(); DiskManager old_disk_manager = disk_manager_use_accessors; // remove any old listeners in case the diskmanager is still running async if ( old_disk_manager != null && disk_manager_listener_use_accessors != null ){ old_disk_manager.removeListener( disk_manager_listener_use_accessors ); } disk_manager_use_accessors = new_disk_manager; disk_manager_listener_use_accessors = new_disk_manager_listener; if ( new_disk_manager != null ){ new_disk_manager.addListener( new_disk_manager_listener ); } // whether going from none->active or the other way, indicate that the file info // has changed fileInfoChanged(); if ( new_disk_manager == null && old_disk_manager != null ){ disk_listeners.dispatch( LDT_DL_REMOVED, old_disk_manager ); }else if ( new_disk_manager != null && old_disk_manager == null ){ disk_listeners.dispatch( LDT_DL_ADDED, new_disk_manager ); }else{ Debug.out( "inconsistent DiskManager state - " + new_disk_manager + "/" + old_disk_manager ); } }finally{ disk_listeners_mon.exit(); } } public void addDiskListener( DownloadManagerDiskListener listener ) { try{ disk_listeners_mon.enter(); disk_listeners.addListener( listener ); DiskManager dm = getDiskManager(); if ( dm != null ){ disk_listeners.dispatch( listener, LDT_DL_ADDED, dm ); } }finally{ disk_listeners_mon.exit(); } } public void removeDiskListener( DownloadManagerDiskListener listener ) { try{ disk_listeners_mon.enter(); disk_listeners.removeListener( listener ); }finally{ disk_listeners_mon.exit(); } } public long getDiskListenerCount() { return disk_listeners.size(); } public String getDisplayName() { return( download_manager.getDisplayName()); } public int getUploadRateLimitBytesPerSecond() { return( download_manager.getEffectiveUploadRateLimitBytesPerSecond()); } public int getDownloadRateLimitBytesPerSecond() { return( stats.getDownloadRateLimitBytesPerSecond()); } public int getMaxUploads() { return( download_manager.getEffectiveMaxUploads()); } public int getMaxConnections() { int result; if ( download_manager.isMaxConnectionsWhenSeedingEnabled() && isStateSeeding()){ result = download_manager.getMaxConnectionsWhenSeeding(); }else{ result = download_manager.getMaxConnections(); } return( result ); } public int getMaxSeedConnections() { return( download_manager.getMaxSeedConnections()); } public boolean isExtendedMessagingEnabled() { return( download_manager.isExtendedMessagingEnabled()); } public boolean isPeerExchangeEnabled() { return( download_manager.getDownloadState().isPeerSourceEnabled( PEPeerSource.PS_OTHER_PEER )); } public int getCryptoLevel() { return( download_manager.getCryptoLevel()); } public boolean isPeriodicRescanEnabled() { return( download_manager.getDownloadState().getFlag( DownloadManagerState.FLAG_SCAN_INCOMPLETE_PIECES )); } public TRTrackerScraperResponse getTrackerScrapeResponse() { return( download_manager.getTrackerScrapeResponse()); } public String getTrackerClientExtensions() { return( download_manager.getDownloadState().getTrackerClientExtensions()); } public void setTrackerRefreshDelayOverrides( int percent ) { download_manager.setTrackerRefreshDelayOverrides( percent ); } public boolean isNATHealthy() { return( download_manager.getNATStatus() == ConnectionManager.NAT_OK ); } public void addPeer( PEPeer peer ) { download_manager.addPeer( peer ); } public void removePeer( PEPeer peer ) { download_manager.removePeer( peer ); } public void addPiece( PEPiece piece ) { download_manager.addPiece( piece ); } public void removePiece( PEPiece piece ) { download_manager.removePiece( piece ); } public void discarded( PEPeer peer, int bytes ) { if ( global_stats != null ){ global_stats.discarded( bytes ); } } public void protocolBytesReceived( PEPeer peer, int bytes ) { if ( global_stats != null ){ global_stats.protocolBytesReceived( bytes, peer.isLANLocal()); } } public void dataBytesReceived( PEPeer peer, int bytes ) { if ( global_stats != null ){ global_stats.dataBytesReceived( bytes, peer.isLANLocal()); } } public void protocolBytesSent( PEPeer peer, int bytes ) { if ( global_stats != null ){ global_stats.protocolBytesSent( bytes, peer.isLANLocal()); } } public void dataBytesSent( PEPeer peer, int bytes ) { if ( global_stats != null ){ global_stats.dataBytesSent( bytes, peer.isLANLocal()); } } public int getPosition() { return download_manager.getPosition(); } public void addHTTPSeed( String address, int port ) { ExternalSeedPlugin plugin = getExternalSeedPlugin(); try{ if ( plugin != null ){ Map config = new HashMap(); List urls = new ArrayList(); String seed_url = "http://" + UrlUtils.convertIPV6Host(address) + ":" + port + "/webseed"; urls.add( seed_url.getBytes()); config.put("httpseeds", urls); Map params = new HashMap(); params.put( "supports_503", new Long(0)); params.put( "transient", new Long(1)); config.put("httpseeds-params", params); plugin.addSeed( org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl.getDownloadStatic( download_manager ), config); } }catch( Throwable e ){ Debug.printStackTrace(e); } } public void priorityConnectionChanged( boolean added ) { synchronized( this ){ if ( added ){ priority_connection_count++; }else{ priority_connection_count--; } } } public boolean hasPriorityConnection() { synchronized( this ){ return( priority_connection_count > 0 ); } } public String getDescription() { return( download_manager.getDisplayName()); } public LogRelation getLogRelation() { return( this ); } public String getRelationText() { return( download_manager.getRelationText()); } public Object[] getQueryableInterfaces() { List interfaces = new ArrayList(); Object[] intf = download_manager.getQueryableInterfaces(); for (int i=0;i * Only a forced-recheck should clear this flag. *

      * Current Implementation:
      * - implies that the user completed the download at one point
      * - Checks if there's Data Missing when torrent is done (or torrent load) */ private boolean assumedComplete; /** * forceStarted torrents can't/shouldn't be automatically stopped */ private int last_informed_state = STATE_START_OF_DAY; private boolean latest_informed_force_start; private GlobalManager globalManager; private String torrentFileName; private boolean open_for_seeding; private String display_name = ""; private String internal_name = ""; // for simple torrents this refers to the torrent file itself. For non-simple it refers to the // folder containing the torrent's files private File torrent_save_location; // Position in Queue private int position = -1; private Object[] read_torrent_state; private DownloadManagerState download_manager_state; private TOTorrent torrent; private String torrent_comment; private String torrent_created_by; private TRTrackerAnnouncer tracker_client; private TRTrackerAnnouncerListener tracker_client_listener = new TRTrackerAnnouncerListener() { public void receivedTrackerResponse( TRTrackerAnnouncerResponse response) { PEPeerManager pm = controller.getPeerManager(); if ( pm != null ) { pm.processTrackerResponse( response ); } tracker_listeners.dispatch( LDT_TL_ANNOUNCERESULT, response ); } public void urlChanged( final TRTrackerAnnouncer announcer, final URL old_url, URL new_url, boolean explicit ) { if ( explicit ){ // flush connected peers on explicit url change if ( torrent.getPrivate()){ final List peers; try{ peer_listeners_mon.enter(); peers = new ArrayList( current_peers ); }finally{ peer_listeners_mon.exit(); } new AEThread( "DM:torrentChangeFlusher", true ) { public void runSupport() { for (int i=0;i 5000 ){ last_upload_when_busy_update = now; // might need to impose the limit String key = TransferSpeedValidator.getActiveUploadParameter( globalManager ); int global_limit_bps = COConfigurationManager.getIntParameter( key )*1024; if ( global_limit_bps > 0 && max_upload_when_busy_bps < global_limit_bps ){ // we have a global limit and a valid busy limit local_max_bps = local_max_bps==0?global_limit_bps:local_max_bps; GlobalManagerStats gm_stats = globalManager.getStats(); int actual = gm_stats.getDataSendRateNoLAN() + gm_stats.getProtocolSendRateNoLAN(); int move_by = ( local_max_bps - max_upload_when_busy_bps ) / 10; if ( move_by < 1024 ){ move_by = 1024; } if ( global_limit_bps - actual <= 2*1024 ){ // close enough to impose the busy limit downwards if ( current_upload_when_busy_bps == 0 ){ current_upload_when_busy_bps = local_max_bps; } int prev_upload_when_busy_bps = current_upload_when_busy_bps; current_upload_when_busy_bps -= move_by; if ( current_upload_when_busy_bps < max_upload_when_busy_bps ){ current_upload_when_busy_bps = max_upload_when_busy_bps; } if ( current_upload_when_busy_bps < prev_upload_when_busy_bps ){ last_upload_when_busy_dec_time = now; } }else{ // not hitting limit, increase if ( current_upload_when_busy_bps != 0 ){ // only try increment if sufficient time passed if ( upload_when_busy_min_secs == 0 || now < last_upload_when_busy_dec_time || now - last_upload_when_busy_dec_time >= upload_when_busy_min_secs*1000 ){ current_upload_when_busy_bps += move_by; if ( current_upload_when_busy_bps >= local_max_bps ){ current_upload_when_busy_bps = 0; } } } } if ( current_upload_when_busy_bps > 0 ){ rate = current_upload_when_busy_bps; } }else{ current_upload_when_busy_bps = 0; } }else{ if ( current_upload_when_busy_bps > 0 ){ rate = current_upload_when_busy_bps; } } } return( rate ); } protected void setFileLinks() { // invalidate the cache info in case its now wrong cached_save_location = null; DiskManagerFactory.setFileLinks( this, download_manager_state.getFileLinks()); controller.fileInfoChanged(); } protected void clearFileLinks() { download_manager_state.clearFileLinks(); } protected void updateFileLinks(File old_save_path, File new_save_path) { try {old_save_path = old_save_path.getCanonicalFile();} catch (IOException ioe) {old_save_path = old_save_path.getAbsoluteFile();} try {new_save_path = new_save_path.getCanonicalFile();} catch (IOException ioe) {new_save_path = new_save_path.getAbsoluteFile();} String old_path = old_save_path.getPath(); String new_path = new_save_path.getPath(); CaseSensitiveFileMap links = download_manager_state.getFileLinks(); Iterator it = links.keySetIterator(); while(it.hasNext()){ File from = (File)it.next(); File to = (File)links.get(from); String from_s = (from == null) ? null : from.getAbsolutePath(); String to_s = (to == null) ? null : to.getAbsolutePath(); try { updateFileLink(old_path, new_path, from_s, to_s); } catch (Exception e) { Debug.printStackTrace(e); } } } // old_path -> Full location of old torrent (inclusive of save name) // from_loc -> Old unmodified location of file within torrent. // to_loc -> Old modified location of file (where the link points to). // // We have to update from_loc and to_loc. // We should always be modifying from_loc. Only modify to_loc if it sits within // the old path. protected void updateFileLink(String old_path, String new_path, String from_loc, String to_loc) { if (to_loc == null) return; if (this.torrent.isSimpleTorrent()) { if (!old_path.equals(from_loc)) {throw new RuntimeException("assert failure: old_path=" + old_path + ", from_loc=" + from_loc);} download_manager_state.setFileLink(new File(old_path), null ); download_manager_state.setFileLink(new File(new_path), new File(new_path)); // Or should the second bit be null? return; } String from_loc_to_use = FileUtil.translateMoveFilePath(old_path, new_path, from_loc); if (from_loc_to_use == null) return; String to_loc_to_use = FileUtil.translateMoveFilePath(old_path, new_path, to_loc); if (to_loc_to_use == null) {to_loc_to_use = to_loc;} download_manager_state.setFileLink(new File(from_loc), null); download_manager_state.setFileLink(new File(from_loc_to_use), new File(to_loc_to_use)); } // Superceded by updateFileLinks(String, String). /* protected void updateFileLinks( String _old_dir, String _new_dir, File _old_save_dir ) { try{ String old_dir = new File( _old_dir ).getCanonicalPath(); String new_dir = new File( _new_dir ).getCanonicalPath(); String old_save_dir = _old_save_dir.getCanonicalPath(); CaseSensitiveFileMap links = download_manager_state.getFileLinks(); Iterator it = links.keySetIterator(); while( it.hasNext()){ File from = (File)it.next(); File to = (File)links.get(from); if ( to == null ){ continue; } String from_str = from.getCanonicalPath(); if ( from_str.startsWith( old_save_dir )){ String new_from_str; String from_suffix = from_str.substring( old_dir.length()); if ( from_suffix.startsWith( File.separator )){ new_from_str = new_dir + from_suffix; }else{ new_from_str = new_dir + File.separator + from_suffix; } String to_str = to.getCanonicalPath(); if ( to_str.startsWith( old_save_dir )){ String new_to_str; String to_suffix = to_str.substring( old_dir.length()); if ( to_suffix.startsWith( File.separator )){ new_to_str = new_dir + to_suffix; }else{ new_to_str = new_dir + File.separator + to_suffix; } to = new File( new_to_str ); } // System.out.println( "Updating file link:" + from + "->" + to + ":" + new_from_str ); download_manager_state.setFileLink( from, null ); download_manager_state.setFileLink( new File( new_from_str), to ); } } }catch( Throwable e ){ Debug.printStackTrace(e); } } */ /** * @deprecated */ public boolean filesExist() { return( filesExist( true )); } public boolean filesExist( boolean expected_to_be_allocated ) { return( controller.filesExist( expected_to_be_allocated )); } public boolean isPersistent() { return( persistent ); } public String getDisplayName() { DownloadManagerState dms = this.getDownloadState(); if (dms != null) { String result = dms.getDisplayName(); if (result != null) {return result;} } return( display_name ); } public String getInternalName() { return( internal_name ); } public String getErrorDetails() { return( controller.getErrorDetail()); } public long getSize() { if( torrent != null){ return torrent.getSize(); } return 0; } protected void setFailed() { setFailed((String)null ); } protected void setFailed( Throwable e ) { setFailed( Debug.getNestedExceptionMessage(e)); } protected void setFailed( String str ) { controller.setFailed( str ); } protected void setTorrentInvalid( String str ) { setFailed( str ); torrent = null; } public void saveResumeData() { if ( getState() == STATE_DOWNLOADING) { try{ getDiskManager().saveResumeData( true ); }catch( Exception e ){ setFailed( "Resume data save fails: " + Debug.getNestedExceptionMessage(e)); } } // we don't want to update the torrent if we're seeding if ( !assumedComplete ){ download_manager_state.save(); } } public void saveDownload() { DiskManager disk_manager = controller.getDiskManager(); if ( disk_manager != null ){ disk_manager.saveState(); } download_manager_state.save(); } public void initialize() { // entry: valid if waiting, stopped or queued // exit: error, ready or on the way to error if ( torrent == null ) { // have a go at re-reading the torrent in case its been recovered readTorrent(); } if ( torrent == null ) { setFailed(); return; } // If a torrent that is assumed complete, verify that it actually has the // files, before we create the diskManager, which will try to allocate // disk space. if (assumedComplete && !filesExist( true )) { // filesExist() has set state to error for us // If the user wants to re-download the missing files, they must // do a re-check, which will reset the flag. return; } download_manager_state.setActive( true ); try{ try{ this_mon.enter(); if ( tracker_client != null ){ Debug.out( "DownloadManager: initialize called with tracker client still available" ); tracker_client.destroy(); } tracker_client = TRTrackerAnnouncerFactory.create( torrent, download_manager_state.getNetworks()); tracker_client.setTrackerResponseCache( download_manager_state.getTrackerResponseCache()); tracker_client.addListener( tracker_client_listener ); }finally{ this_mon.exit(); } // we need to set the state to "initialized" before kicking off the disk manager // initialisation as it should only report its status while in the "initialized" // state (see getState for how this works...) try{ controller.initializeDiskManager( open_for_seeding ); }finally{ // only supply this the very first time the torrent starts so the controller can check // that things are ok. Subsequent restarts are under user control open_for_seeding = false; } }catch( TRTrackerAnnouncerException e ){ setFailed( e ); } } public void setStateWaiting() { controller.setStateWaiting(); } public void setStateFinishing() { controller.setStateFinishing(); } public void setStateQueued() { controller.setStateQueued(); } public int getState() { return( controller.getState()); } public int getSubState() { return( controller.getSubState()); } public boolean canForceRecheck() { if ( getTorrent() == null ){ // broken torrent, can't force recheck return( false ); } return( controller.canForceRecheck()); } public void forceRecheck() { controller.forceRecheck(null); } public void forceRecheck(final ForceRecheckListener l) { controller.forceRecheck(l); } public void setPieceCheckingEnabled( boolean enabled ) { controller.setPieceCheckingEnabled( enabled ); } public void resetFile( DiskManagerFileInfo file ) { int state = getState(); if ( state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_ERROR ){ DiskManagerFactory.clearResumeData( this, file ); }else{ Debug.out( "Download not stopped" ); } } public void recheckFile( DiskManagerFileInfo file ) { int state = getState(); if ( state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_ERROR ){ DiskManagerFactory.recheckFile( this, file ); }else{ Debug.out( "Download not stopped" ); } } public void startDownload() { controller.startDownload( getTrackerClient() ); } public void stopIt( int state_after_stopping, boolean remove_torrent, boolean remove_data ) { try{ download_manager_state.setLongAttribute( DownloadManagerState.AT_TIME_STOPPED, SystemTime.getCurrentTime()); controller.stopIt( state_after_stopping, remove_torrent, remove_data ); }finally{ download_manager_state.setActive( false ); } } public boolean pause() { return( globalManager.pauseDownload( this )); } public boolean isPaused() { return( globalManager.isPaused( this )); } public void resume() { globalManager.resumeDownload( this ); } public boolean getAssumedComplete() { return assumedComplete; } public boolean requestAssumedCompleteMode() { boolean bCompleteNoDND = controller.isDownloadComplete(false); setAssumedComplete(bCompleteNoDND); return bCompleteNoDND; } // Protected: Use requestAssumedCompleteMode outside of scope protected void setAssumedComplete(boolean _assumedComplete) { if (_assumedComplete) { long completedOn = download_manager_state.getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_COMPLETED_TIME); if (completedOn <= 0) { download_manager_state.setLongParameter( DownloadManagerState.PARAM_DOWNLOAD_COMPLETED_TIME, SystemTime.getCurrentTime()); } } if (assumedComplete == _assumedComplete) { return; } //Logger.log(new LogEvent(this, LogIDs.CORE, "setAssumedComplete(" // + _assumedComplete + ") was " + assumedComplete)); assumedComplete = _assumedComplete; if (!assumedComplete) { controller.setStateDownloading(); } // NOTE: We don't set "stats.setDownloadCompleted(1000)" anymore because // we can be in seeding mode with an unfinished torrent if (position != -1) { // we are in a new list, move to the top of the list so that we continue // seeding. // -1 position means it hasn't been added to the global list. We // shouldn't touch it, since it'll get a position once it's adding is // complete DownloadManager[] dms = { DownloadManagerImpl.this }; // pretend we are at the bottom of the new list // so that move top will shift everything down one position = globalManager.getDownloadManagers().size() + 1; if (COConfigurationManager.getBooleanParameter(CFG_MOVE_COMPLETED_TOP)) { globalManager.moveTop(dms); } else { globalManager.moveEnd(dms); } // we left a gap in incomplete list, fixup globalManager.fixUpDownloadManagerPositions(); } listeners.dispatch(LDT_COMPLETIONCHANGED, new Object[] { this, new Boolean(_assumedComplete) }); } public int getNbSeeds() { PEPeerManager peerManager = controller.getPeerManager(); if (peerManager != null){ return peerManager.getNbSeeds(); } return 0; } public int getNbPeers() { PEPeerManager peerManager = controller.getPeerManager(); if (peerManager != null){ return peerManager.getNbPeers(); } return 0; } public String getTrackerStatus() { TRTrackerAnnouncer tc = getTrackerClient(); if (tc != null){ return tc.getStatusString(); } // no tracker, return scrape if (torrent != null ) { TRTrackerScraperResponse response = getTrackerScrapeResponse(); if (response != null) { return response.getStatusString(); } } return ""; } public TRTrackerAnnouncer getTrackerClient() { return( tracker_client ); } public void setAnnounceResult( DownloadAnnounceResult result ) { TRTrackerAnnouncer cl = getTrackerClient(); if ( cl == null ){ // this can happen due to timing issues - not work debug spew for // Debug.out( "setAnnounceResult called when download not running" ); return; } cl.setAnnounceResult( result ); } public void setScrapeResult( DownloadScrapeResult result ) { if ( torrent != null && result != null ){ TRTrackerScraper scraper = globalManager.getTrackerScraper(); TRTrackerScraperResponse current_resp = getTrackerScrapeResponse(); URL target_url; if ( current_resp != null ){ target_url = current_resp.getURL(); }else{ target_url = torrent.getAnnounceURL(); } scraper.setScrape( torrent, target_url, result ); } } public int getNbPieces() { if ( torrent == null ){ return(0); } return( torrent.getNumberOfPieces()); } public int getTrackerTime() { TRTrackerAnnouncer tc = getTrackerClient(); if ( tc != null){ return( tc.getTimeUntilNextUpdate()); } // no tracker, return scrape if ( torrent != null ) { TRTrackerScraperResponse response = getTrackerScrapeResponse(); if (response != null) { if (response.getStatus() == TRTrackerScraperResponse.ST_SCRAPING){ return( -1 ); } return (int)((response.getNextScrapeStartTime() - SystemTime.getCurrentTime()) / 1000); } } return( TRTrackerAnnouncer.REFRESH_MINIMUM_SECS ); } public TOTorrent getTorrent() { return( torrent ); } private File cached_save_location; private File cached_save_location_result; public File getSaveLocation() { // this can be called quite often - cache results for perf reasons File save_location = torrent_save_location; if ( save_location == cached_save_location ){ return( cached_save_location_result ); } File res = download_manager_state.getFileLink( save_location ); if ( res == null || res.equals(save_location) ){ res = save_location; }else{ try{ res = res.getCanonicalFile(); }catch( Throwable e ){ res = res.getAbsoluteFile(); } } cached_save_location = save_location; cached_save_location_result = res; return( res ); } public File getAbsoluteSaveLocation() { return( torrent_save_location ); } public void setTorrentSaveDir(String new_dir) { setTorrentSaveDir(new_dir, this.getAbsoluteSaveLocation().getName()); } public void setTorrentSaveDir(String new_dir, String dl_name) { File old_location = torrent_save_location; File new_location = new File(new_dir, dl_name); if (new_location.equals(old_location)){ return; } // assumption here is that the caller really knows what they are doing. You can't // just change this willy nilly, it must be synchronised with reality. For example, // the disk-manager calls it after moving files on completing // The UI can call it as long as the torrent is stopped. // Calling it while a download is active will in general result in unpredictable behaviour! updateFileLinks( old_location, new_location); torrent_save_location = new_location; try{ torrent_save_location = torrent_save_location.getCanonicalFile(); }catch( Throwable e ){ torrent_save_location = torrent_save_location.getAbsoluteFile(); } Logger.log(new LogEvent(this, LogIDs.CORE, "Torrent save directory changing from \"" + old_location.getPath() + "\" to \"" + new_location.getPath())); // Trying to fix a problem where downloads are being moved into the program // directory on my machine, and I don't know why... //Debug.out("Torrent save directory changing from \"" + old_location.getPath() + "\" to \"" + new_location.getPath()); controller.fileInfoChanged(); } public String getPieceLength() { if ( torrent != null ){ return( DisplayFormatters.formatByteCountToKiBEtc(torrent.getPieceLength())); } return( "" ); } public String getTorrentFileName() { return torrentFileName; } public void setTorrentFileName( String string) { torrentFileName = string; } // this is called asynchronously when a response is received public void setTrackerScrapeResponse( TRTrackerScraperResponse response ) { // this is a reasonable place to pick up the change in active url caused by this scrape // response and update the torrent's url accordingly Object[] res = getActiveScrapeResponse(); URL active_url = (URL)res[1]; if ( active_url != null && torrent != null ){ torrent.setAnnounceURL( active_url ); } if (response != null) { int state = getState(); if (state == STATE_ERROR || state == STATE_STOPPED) { long minNextScrape; if (response.getStatus() == TRTrackerScraperResponse.ST_INITIALIZING) { minNextScrape = SystemTime.getCurrentTime() + (state == STATE_ERROR ? SCRAPE_INITDELAY_ERROR_TORRENTS : SCRAPE_INITDELAY_STOPPED_TORRENTS); } else { minNextScrape = SystemTime.getCurrentTime() + (state == STATE_ERROR ? SCRAPE_DELAY_ERROR_TORRENTS : SCRAPE_DELAY_STOPPED_TORRENTS); } if (response.getNextScrapeStartTime() < minNextScrape) { response.setNextScrapeStartTime(minNextScrape); } } else if (!response.isValid() && response.getStatus() == TRTrackerScraperResponse.ST_INITIALIZING) { long minNextScrape; // Spread the scrapes out a bit. This is extremely helpfull on large // torrent lists, and trackers that do not support multi-scrapes. // For trackers that do support multi-scrapes, it will really delay // the scrape for all torrent in the tracker to the one that has // the lowest share ratio. int sr = getStats().getShareRatio(); minNextScrape = SystemTime.getCurrentTime() + ((sr > 10000 ? 10000 : sr + 1000) * 60); if (response.getNextScrapeStartTime() < minNextScrape) { response.setNextScrapeStartTime(minNextScrape); } } // Need to notify listeners, even if scrape result is not valid, in // case they parse invalid scrapes if ( response.isValid() && response.getStatus() == TRTrackerScraperResponse.ST_ONLINE ){ long cache = ((((long)response.getSeeds())&0x00ffffffL)<<32)|(((long)response.getPeers())&0x00ffffffL); download_manager_state.setLongAttribute( DownloadManagerState.AT_SCRAPE_CACHE, cache ); } tracker_listeners.dispatch(LDT_TL_SCRAPERESULT, response); } } public TRTrackerScraperResponse getTrackerScrapeResponse() { Object[] res = getActiveScrapeResponse(); return((TRTrackerScraperResponse)res[0]); } /** * Returns the "first" online scrape response found, and its active URL, otherwise one of the failing * scrapes * @return */ protected Object[] getActiveScrapeResponse() { TRTrackerScraperResponse response = null; URL active_url = null; TRTrackerScraper scraper = globalManager.getTrackerScraper(); TRTrackerAnnouncer tc = getTrackerClient(); if ( tc != null ){ response = scraper.scrape( tc ); } if ( response == null && torrent != null){ // torrent not running. For multi-tracker torrents we need to behave sensibly // here TRTrackerScraperResponse non_null_response = null; TOTorrentAnnounceURLSet[] sets; try { sets = torrent.getAnnounceURLGroup().getAnnounceURLSets(); } catch (Exception e) { return( new Object[]{ scraper.scrape(torrent), active_url } ); } if ( sets.length == 0 ){ response = scraper.scrape(torrent); }else{ // we use a fixed seed so that subsequent scrapes will randomise // in the same order, as required by the spec. Note that if the // torrent's announce sets are edited this all works fine (if we // cached the randomised URL set this wouldn't work) Random scrape_random = new Random(scrape_random_seed); for (int i=0;response==null && i can destroy retained stuff now tracker_client.getLastResponse().setPeers(new TRTrackerAnnouncerResponsePeer[0]); // currently only report this for complete downloads... tracker_client.stop( for_queue && isDownloadComplete( false )); tracker_client.destroy(); tracker_client = null; } }finally{ this_mon.exit(); } } public DownloadManagerStats getStats() { return( stats ); } public boolean isForceStart() { return( controller.isForceStart()); } public void setForceStart( boolean forceStart) { controller.setForceStart( forceStart ); } /** * Is called when a download is finished. * Activates alerts for the user. * * @param never_downloaded true indicates that we never actually downloaded * anything in this session, but we determined that * the download is complete (usually via * startDownload()) * * @author Rene Leonhardt */ protected void downloadEnded( boolean never_downloaded ) { if ( !never_downloaded ){ if (isForceStart()){ setForceStart(false); } setAssumedComplete(true); informDownloadEnded(); } TRTrackerAnnouncer tc = tracker_client; if ( tc != null ){ DiskManager dm = getDiskManager(); // only report "complete" if we really are complete, not a dnd completion event if ( dm != null && dm.getRemaining() == 0 ){ tc.complete( never_downloaded ); } } } public void addDiskListener( DownloadManagerDiskListener listener ) { controller.addDiskListener( listener ); } public void removeDiskListener( DownloadManagerDiskListener listener ) { controller.removeDiskListener( listener ); } public void addActivationListener( DownloadManagerActivationListener listener ) { activation_listeners.add( listener ); } public void removeActivationListener( DownloadManagerActivationListener listener ) { activation_listeners.remove( listener ); } public int getHealthStatus() { int state = getState(); PEPeerManager peerManager = controller.getPeerManager(); TRTrackerAnnouncer tc = getTrackerClient(); if( tc != null && peerManager != null && (state == STATE_DOWNLOADING || state == STATE_SEEDING)) { int nbSeeds = getNbSeeds(); int nbPeers = getNbPeers(); int nbRemotes = peerManager.getNbRemoteConnectionsExcludingUDP(); TRTrackerAnnouncerResponse announce_response = tc.getLastResponse(); int trackerStatus = announce_response.getStatus(); boolean isSeed = (state == STATE_SEEDING); if( (nbSeeds + nbPeers) == 0) { if( isSeed ){ return WEALTH_NO_TRACKER; // not connected to any peer and seeding } return WEALTH_KO; // not connected to any peer and downloading } // read the spec for this!!!! // no_tracker = // 1) if downloading -> no tracker // 2) if seeding -> no connections (dealt with above) if ( !isSeed ){ if( trackerStatus == TRTrackerAnnouncerResponse.ST_OFFLINE || trackerStatus == TRTrackerAnnouncerResponse.ST_REPORTED_ERROR){ return WEALTH_NO_TRACKER; } } if( nbRemotes == 0 ){ TRTrackerScraperResponse scrape_response = getTrackerScrapeResponse(); if ( scrape_response != null && scrape_response.isValid()){ // if we're connected to everyone then report OK as we can't get // any incoming connections! if ( nbSeeds == scrape_response.getSeeds() && nbPeers == scrape_response.getPeers()){ return WEALTH_OK; } } return WEALTH_NO_REMOTE; } return WEALTH_OK; } else if (state == STATE_ERROR) { return WEALTH_ERROR; }else{ return WEALTH_STOPPED; } } public int getNATStatus() { int state = getState(); PEPeerManager peerManager = controller.getPeerManager(); TRTrackerAnnouncer tc = getTrackerClient(); if ( tc != null && peerManager != null && (state == STATE_DOWNLOADING || state == STATE_SEEDING)) { if ( peerManager.getNbRemoteConnectionsExcludingUDP() > 0 ){ return( ConnectionManager.NAT_OK ); } long last_good_time = peerManager.getLastRemoteConnectionTime(); if ( last_good_time > 0 ){ // half an hour's grace if ( SystemTime.getCurrentTime() - last_good_time < 30*60*1000 ){ return( ConnectionManager.NAT_OK ); }else{ return( ConnectionManager.NAT_PROBABLY_OK ); } } TRTrackerAnnouncerResponse announce_response = tc.getLastResponse(); int trackerStatus = announce_response.getStatus(); if( trackerStatus == TRTrackerAnnouncerResponse.ST_OFFLINE || trackerStatus == TRTrackerAnnouncerResponse.ST_REPORTED_ERROR){ return ConnectionManager.NAT_UNKNOWN; } // tracker's ok but no remotes - give it some time if ( SystemTime.getCurrentTime() - peerManager.getTimeStarted() < 3*60*1000 ){ return ConnectionManager.NAT_UNKNOWN; } TRTrackerScraperResponse scrape_response = getTrackerScrapeResponse(); if ( scrape_response != null && scrape_response.isValid()){ // if we're connected to everyone then report OK as we can't get // any incoming connections! if ( peerManager.getNbSeeds() == scrape_response.getSeeds() && peerManager.getNbPeers() == scrape_response.getPeers()){ return ConnectionManager.NAT_UNKNOWN; } } return ConnectionManager.NAT_BAD; }else{ return ConnectionManager.NAT_UNKNOWN; } } public int getPosition() { return position; } public void setPosition( int new_position ) { informPositionChanged( new_position ); } public void addTrackerListener( DownloadManagerTrackerListener listener ) { tracker_listeners.addListener( listener ); } public void removeTrackerListener( DownloadManagerTrackerListener listener ) { tracker_listeners.removeListener( listener ); } protected void deleteDataFiles() { DiskManagerFactory.deleteDataFiles( torrent, torrent_save_location.getParent(), torrent_save_location.getName(), getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE )); // Attempted fix for bug 1572356 - apparently sometimes when we perform removal of a download's data files, // it still somehow gets processed by the move-on-removal rules. I'm making the assumption that this method // is only called when a download is about to be removed. this.getDownloadState().setFlag(DownloadManagerState.FLAG_DISABLE_AUTO_FILE_MOVE, true); } protected void deleteTorrentFile() { if ( torrentFileName != null ){ TorrentUtils.delete( new File(torrentFileName),getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE )); } } public DownloadManagerState getDownloadState() { return( download_manager_state ); } public Object getData (String key){ return( getUserData( key ));} public void setData (String key, Object value){ setUserData( key, value ); } /** To retreive arbitrary objects against a download. */ public Object getUserData (Object key) { if (data == null) return null; return data.get(key); } /** To store arbitrary objects against a download. */ public void setUserData (Object key, Object value) { try{ peer_listeners_mon.enter(); if (data == null) { data = new LightHashMap(); } if (value == null) { if (data.containsKey(key)) data.remove(key); } else { data.put(key, value); } }finally{ peer_listeners_mon.exit(); } } public boolean isDataAlreadyAllocated() { return data_already_allocated; } public void setDataAlreadyAllocated( boolean already_allocated ) { data_already_allocated = already_allocated; } public void setSeedingRank(int rank) { iSeedingRank = rank; } public int getSeedingRank() { return iSeedingRank; } public long getCreationTime() { return( creation_time ); } public void setCreationTime( long t ) { creation_time = t; } public boolean isExtendedMessagingEnabled() { return az_messaging_enabled; } public void setAZMessagingEnabled( boolean enable ) { az_messaging_enabled = enable; } public void setCryptoLevel( int level ) { crypto_level = level; } public int getCryptoLevel() { return( crypto_level ); } public void moveDataFiles( File new_parent_dir ) throws DownloadManagerException { this.moveDataFiles(new_parent_dir, null); } public void renameDownload(String new_name) throws DownloadManagerException { this.moveDataFiles(null, new_name); } public void moveDataFiles( final File destination, final String new_name) throws DownloadManagerException { if (destination == null && new_name == null) { throw new NullPointerException("destination and new name are both null"); } if (!canMoveDataFiles()) { throw new DownloadManagerException("canMoveDataFiles is false!"); } /** * Test to see if the download is to be moved somewhere where it already * exists. Perhaps you might think it is slightly unnecessary to check this, * but I would prefer this test left in - we want to prevent pausing * unnecessarily pausing a running torrent (it fires off listeners, which * might try to move the download). * * This helps us avoid a situation with AzCatDest... */ SaveLocationChange slc = new SaveLocationChange(); slc.download_location = destination; slc.download_name = new_name; File current_location = getSaveLocation(); if (slc.normaliseDownloadLocation(current_location).equals(current_location)) { return; } try{ FileUtil.runAsTask( new AzureusCoreOperationTask() { public void run( AzureusCoreOperation operation) { try{ moveDataFilesSupport( destination, new_name ); }catch( DownloadManagerException e ){ throw( new RuntimeException( e )); } } }); }catch( RuntimeException e ){ Throwable cause = e.getCause(); if ( cause instanceof DownloadManagerException ){ throw((DownloadManagerException)cause); } throw( e ); } } private void moveDataFilesSupport( File new_parent_dir, String new_filename) throws DownloadManagerException { boolean is_paused = this.pause(); try {moveDataFilesSupport0(new_parent_dir, new_filename);} finally {if (is_paused) {this.resume();}} } private void moveDataFilesSupport0( File new_parent_dir, String new_filename) throws DownloadManagerException { if (!canMoveDataFiles()){ throw new DownloadManagerException("canMoveDataFiles is false!"); } if (new_filename != null) {new_filename = FileUtil.convertOSSpecificChars(new_filename,false);} // old file will be a "file" for simple torrents, a dir for non-simple File old_file = getSaveLocation(); try{ old_file = old_file.getCanonicalFile(); if (new_parent_dir != null) {new_parent_dir = new_parent_dir.getCanonicalFile();} }catch( Throwable e ){ Debug.printStackTrace(e); throw( new DownloadManagerException( "Failed to get canonical paths", e )); } File current_save_location = old_file; File new_save_location = new File( (new_parent_dir == null) ? old_file.getParentFile() : new_parent_dir, (new_filename == null) ? old_file.getName() : new_filename ); if (current_save_location.equals(new_save_location)) { // null operation return; } DiskManager dm = getDiskManager(); if ( dm == null || dm.getFiles() == null){ if ( !old_file.exists()){ // files not created yet FileUtil.mkdirs(new_save_location.getParentFile()); setTorrentSaveDir(new_save_location.getParent().toString(), new_save_location.getName()); return; } try{ new_save_location = new_save_location.getCanonicalFile(); }catch( Throwable e ){ Debug.printStackTrace(e); } if ( old_file.equals( new_save_location )){ // nothing to do } else if (torrent.isSimpleTorrent()) { // Have to keep the file name in sync if we're renaming. if (controller.getDiskManagerFileInfo()[0].setLinkAtomic(new_save_location)) { setTorrentSaveDir( new_save_location.getParentFile().toString(), new_save_location.getName()); } else {throw new DownloadManagerException( "rename operation failed");} }else{ if (FileUtil.isAncestorOf(old_file, new_save_location)) { Logger.logTextResource(new LogAlert(this, LogAlert.REPEATABLE, LogAlert.AT_ERROR, "DiskManager.alert.movefilefails"), new String[] {old_file.toString(), "Target is sub-directory of files" }); throw( new DownloadManagerException( "rename operation failed" )); } // The files we move must be limited to those mentioned in the torrent. final HashSet files_to_move = new HashSet(); // Required for the adding of parent directories logic. files_to_move.add(null); DiskManagerFileInfo[] info_files = controller.getDiskManagerFileInfo(); for (int i=0; i 10) { status = status.substring(0, 10); } return "DownloadManagerImpl#" + getPosition() + (getAssumedComplete() ? "s" : "d") + "@" + Integer.toHexString(hashCode()) + "/" + status + "/" + hash; } protected static class NoStackException extends Exception { protected NoStackException( String str ) { super( str ); } } public void generateEvidence( IndentWriter writer ) { writer.println(toString()); PEPeerManager pm = getPeerManager(); try { writer.indent(); writer.println("Save Dir: " + Debug.secretFileName(getSaveLocation().toString())); if (current_peers.size() > 0) { writer.println("# Peers: " + current_peers.size()); } if (current_pieces.size() > 0) { writer.println("# Pieces: " + current_pieces.size()); } writer.println("Listeners: DownloadManager=" + listeners.size() + "; Disk=" + controller.getDiskListenerCount() + "; Peer=" + peer_listeners.size() + "; Tracker=" + tracker_listeners.size()); writer.println("SR: " + iSeedingRank); String sFlags = ""; if (open_for_seeding) { sFlags += "Opened for Seeding; "; } if (data_already_allocated) { sFlags += "Data Already Allocated; "; } if (assumedComplete) { sFlags += "onlySeeding; "; } if (persistent) { sFlags += "persistent; "; } if (sFlags.length() > 0) { writer.println("Flags: " + sFlags); } stats.generateEvidence( writer ); download_manager_state.generateEvidence( writer ); if (pm != null) { pm.generateEvidence(writer); } // note, PeerManager generates DiskManager evidence controller.generateEvidence(writer); TRTrackerAnnouncer announcer = tracker_client; if ( announcer != null ){ announcer.generateEvidence( writer ); } TRTrackerScraperResponse scrape = getTrackerScrapeResponse(); if ( scrape == null ){ writer.println( "Scrape: null" ); }else{ writer.println( "Scrape: " + scrape.getString()); } } finally { writer.exdent(); } } public void destroy( boolean is_duplicate ) { destroyed = true; if ( is_duplicate ){ // minimal tear-down controller.destroy(); }else{ try{ // Data files don't exist, so we just don't do anything. if (!getSaveLocation().exists()) {return;} DiskManager dm = this.getDiskManager(); if (dm != null) { dm.downloadRemoved(); return; } SaveLocationChange move_details; move_details = DownloadManagerMoveHandler.onRemoval(this); if (move_details == null) { return; } boolean can_move_torrent = move_details.hasTorrentChange(); try { if (move_details.hasDownloadChange()) { this.moveDataFiles(move_details.download_location, move_details.download_name); } } catch (Exception e) { can_move_torrent = false; Logger.log(new LogAlert(this, true, "Problem moving files to removed download directory", e)); } // This code will silently fail if the torrent file doesn't exist. if (can_move_torrent) { try { this.moveTorrentFile(move_details.torrent_location, move_details.torrent_name); } catch (Exception e) { Logger.log(new LogAlert(this, true, "Problem moving torrent to removed download directory", e)); } } }finally{ clearFileLinks(); controller.destroy(); } } } public boolean isDestroyed() { return( destroyed ); } public int[] getStorageType(DiskManagerFileInfo[] info) { String[] types = DiskManagerImpl.getStorageTypes(this); int[] result = new int[info.length]; boolean is_linear; for (int i=0; i 0) { logInfo("Consider relative save path: " + relative_path, dm); // Doesn't matter if File.separator is required or not, it seems to // remove duplicate file separators. target = new File(target.getPath() + File.separator + relative_path); } return target; } } private static class TransferSpecification extends ParameterHelper { public SaveLocationChange getTransferDetails(DownloadManager dm, ContextDescriptor cd, File target_path) { if (target_path == null) {throw new NullPointerException();} SaveLocationChange result = new SaveLocationChange(); result.download_location = target_path; if (this.getBoolean("torrent")) { result.torrent_location = target_path; } return result; } } public static File getCompletionDirectory(DownloadManager dm) { return COMPLETION_DETAILS.target.getTarget(dm, null); } static String describe(DownloadManager dm, ContextDescriptor cs) { if (cs == null) {return describe(dm);} if (dm == null) { return "\"" + cs.getContext() + "\""; } return "\"" + dm.getDisplayName() + "\" with regard to \"" + cs.getContext() + "\""; } }azureus-4.3.0.6/org/gudy/azureus2/core3/download/impl/DownloadManagerAdapter.java0000644000175000017500000000273510416502244027153 0ustar adrianadrian/* * File : DownloadManagerAdapter.java * Created : 2004/May/21 * By : tuxpaper * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.download.impl; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.*; /** Adapter for DownloadManagerListener */ public class DownloadManagerAdapter implements DownloadManagerListener { public void stateChanged(DownloadManager manager, int state) {} public void downloadComplete(DownloadManager manager) {} public void completionChanged(DownloadManager manager, boolean bCompleted) {} public void positionChanged(DownloadManager download, int oldPosition, int newPosition) {} public void filePriorityChanged( DownloadManager download, DiskManagerFileInfo file ){} } azureus-4.3.0.6/org/gudy/azureus2/core3/download/impl/DownloadManagerStateImpl.java0000644000175000017500000022576411273603246027514 0ustar adrianadrian/* * Created on 15-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.download.impl; import java.io.*; import java.net.URL; import java.util.*; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import org.gudy.azureus2.core3.category.Category; import org.gudy.azureus2.core3.category.CategoryManager; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.disk.DiskManagerFactory; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.*; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.LogRelation; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.peer.PEPeerSource; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.util.CaseSensitiveFileMap; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.util.CopyOnWriteMap; /** * @author parg * Overall aim of this is to stop updating the torrent file itself and update something * Azureus owns. To this end a file based on torrent hash is created in user-dir/active * It is actually just a copy of the torrent file */ public class DownloadManagerStateImpl implements DownloadManagerState, ParameterListener { private static final int VER_INCOMING_PEER_SOURCE = 1; private static final int VER_CURRENT = VER_INCOMING_PEER_SOURCE; private static final LogIDs LOGID = LogIDs.DISK; private static final String RESUME_KEY = "resume"; private static final String TRACKER_CACHE_KEY = "tracker_cache"; private static final String ATTRIBUTE_KEY = "attributes"; private static final String AZUREUS_PROPERTIES_KEY = "azureus_properties"; private static final File ACTIVE_DIR; public static boolean SUPPRESS_FIXUP_ERRORS = false; static{ ACTIVE_DIR = FileUtil.getUserFile( "active" ); if ( !ACTIVE_DIR.exists()){ FileUtil.mkdirs(ACTIVE_DIR); } } private static Random random = RandomUtils.SECURE_RANDOM; private static final Map default_parameters; private static final Map default_attributes; static{ default_parameters = new HashMap(); for (int i=0;i 32; // System.out.println( "getDownloadState: hash = " + (torrent_hash==null?"null":ByteFormatter.encodeString(torrent_hash) + ", file = " + torrent_file )); TOTorrent original_torrent = null; TorrentUtils.ExtendedTorrent saved_state = null; // first, if we already have the hash then see if we can load the saved state if ( torrent_hash != null ){ File saved_file = getStateFile( torrent_hash ); if ( saved_file.exists()){ try{ Map cached_state = (Map)global_state_cache.remove( new HashWrapper( torrent_hash )); if ( cached_state != null ){ CachedStateWrapper wrapper = new CachedStateWrapper( download_manager, torrent_file, torrent_hash, cached_state, inactive ); global_state_cache_wrappers.add( wrapper ); saved_state = wrapper; }else{ saved_state = TorrentUtils.readDelegateFromFile( saved_file, discard_pieces ); } }catch( Throwable e ){ Debug.out( "Failed to load download state for " + saved_file ); } } } // if saved state not found then recreate from original torrent if required if ( saved_state == null ){ original_torrent = TorrentUtils.readDelegateFromFile( new File(torrent_file), discard_pieces ); torrent_hash = original_torrent.getHash(); File saved_file = getStateFile( torrent_hash ); if ( saved_file.exists()){ try{ saved_state = TorrentUtils.readDelegateFromFile( saved_file, discard_pieces ); }catch( Throwable e ){ Debug.out( "Failed to load download state for " + saved_file ); } } if ( saved_state == null ){ // we must copy the torrent as we want one independent from the // original (someone might still have references to the original // and do stuff like write it somewhere else which would screw us // up) TorrentUtils.copyToFile( original_torrent, saved_file ); saved_state = TorrentUtils.readDelegateFromFile( saved_file, discard_pieces ); } } DownloadManagerState res = getDownloadState( download_manager, original_torrent, saved_state ); if ( inactive ){ res.setActive( false ); } return( res ); } protected static File getStateFile( byte[] torrent_hash ) { return( new File( ACTIVE_DIR, ByteFormatter.encodeString( torrent_hash ) + ".dat" )); } protected static File getGlobalStateFile() { return( new File( ACTIVE_DIR, "cache.dat" )); } public static void loadGlobalStateCache() { File file = getGlobalStateFile(); if ( !file.canRead()){ return; } try{ BufferedInputStream is = new BufferedInputStream( new GZIPInputStream( new FileInputStream( file ))); try{ Map map = BDecoder.decode( is ); List cache = (List)map.get( "state" ); if ( cache != null ){ for (int i=0;i 0 ){ if ( PEPeerSource.isPeerSourceEnabledByDefault( PEPeerSource.PS_INCOMING )){ setPeerSourceEnabled( PEPeerSource.PS_INCOMING, true ); } }else{ // set default for newly added torrent setPeerSources( PEPeerSource.getDefaultEnabledPeerSources()); } } if ( version < VER_CURRENT ){ setIntAttribute( AT_VERSION, VER_CURRENT ); } addListeners(); } public void parameterChanged( String parameterName) { // get any listeners to pick up new values as their defaults are based on core params informWritten( AT_PARAMETERS ); } protected void addListeners() { COConfigurationManager.addParameterListener( "Max.Peer.Connections.Per.Torrent.When.Seeding", this ); COConfigurationManager.addParameterListener( "Max.Peer.Connections.Per.Torrent.When.Seeding.Enable", this ); COConfigurationManager.addParameterListener( "Max.Peer.Connections.Per.Torrent", this ); COConfigurationManager.addParameterListener( "Max Uploads", this ); COConfigurationManager.addParameterListener( "Max Uploads Seeding", this ); COConfigurationManager.addParameterListener( "Max Seeds Per Torrent", this ); COConfigurationManager.addParameterListener( "enable.seedingonly.maxuploads", this ); } protected void removeListeners() { COConfigurationManager.removeParameterListener( "Max.Peer.Connections.Per.Torrent.When.Seeding", this ); COConfigurationManager.removeParameterListener( "Max.Peer.Connections.Per.Torrent.When.Seeding.Enable", this ); COConfigurationManager.removeParameterListener( "Max.Peer.Connections.Per.Torrent", this ); COConfigurationManager.removeParameterListener( "Max Uploads", this ); COConfigurationManager.removeParameterListener( "Max Uploads Seeding", this ); COConfigurationManager.removeParameterListener( "Max Seeds Per Torrent", this ); COConfigurationManager.removeParameterListener( "enable.seedingonly.maxuploads", this ); } public DownloadManager getDownloadManager() { return( download_manager ); } protected void setDownloadManager( DownloadManagerImpl dm ) { download_manager = dm; } public File getStateFile( ) { try{ File parent = new File( ACTIVE_DIR, ByteFormatter.encodeString( torrent.getHash()) + File.separatorChar); return( StringInterner.internFile(parent)); }catch( Throwable e ){ Debug.printStackTrace(e); return( null ); } } public void clearTrackerResponseCache() { setTrackerResponseCache( new HashMap()); } public Map getTrackerResponseCache() { Map tracker_response_cache = null; tracker_response_cache = torrent.getAdditionalMapProperty(TRACKER_CACHE_KEY); if (tracker_response_cache == null) tracker_response_cache = new HashMap(); return (tracker_response_cache); } public void setTrackerResponseCache( Map value ) { try{ this_mon.enter(); // System.out.println( "setting download state/tracker cache for '" + new String(torrent.getName())); boolean changed = !BEncoder.mapsAreIdentical( value, getTrackerResponseCache() ); if ( changed ){ write_required = true; torrent.setAdditionalMapProperty( TRACKER_CACHE_KEY, value ); } }finally{ this_mon.exit(); } } public Map getResumeData() { try{ this_mon.enter(); return( torrent.getAdditionalMapProperty(RESUME_KEY)); }finally{ this_mon.exit(); } } public void clearResumeData() { setResumeData( null ); } public void setResumeData( Map data ) { try{ this_mon.enter(); // System.out.println( "setting download state/resume data for '" + new String(torrent.getName())); if ( data == null ){ setLongAttribute( AT_RESUME_STATE, 1 ); torrent.removeAdditionalProperty( RESUME_KEY ); }else{ torrent.setAdditionalMapProperty( RESUME_KEY, data ); boolean complete = DiskManagerFactory.isTorrentResumeDataComplete( this ); setLongAttribute( AT_RESUME_STATE, complete?2:1 ); } write_required = true; }finally{ this_mon.exit(); } // we need to ensure this is persisted now as it has implications regarding crash restarts etc save(); } public boolean isResumeDataComplete() { // this is a cache of resume state to speed up startup long state = getLongAttribute( AT_RESUME_STATE ); if ( state == 0 ){ // don't know boolean complete = DiskManagerFactory.isTorrentResumeDataComplete( this ); setLongAttribute( AT_RESUME_STATE, complete?2:1 ); return( complete ); }else{ return( state == 2 ); } } public TOTorrent getTorrent() { return( torrent ); } public void setActive( boolean active ) { torrent.setDiscardFluff( !active ); } public void discardFluff() { torrent.setDiscardFluff(true); } public void suppressStateSave(boolean suppress) { if(suppress) supressWrites++; else if(supressWrites > 0) supressWrites--; } public void save() { if(supressWrites > 0) return; boolean do_write; try { this_mon.enter(); do_write = write_required; if(write_required != false) write_required = false; } finally { this_mon.exit(); } if ( do_write ){ try { // System.out.println( "writing download state for '" + new String(torrent.getName())); if (Logger.isEnabled()) Logger.log(new LogEvent(torrent, LOGID, "Saving state for download '" + TorrentUtils.getLocalisedName(torrent) + "'")); torrent.setAdditionalMapProperty( ATTRIBUTE_KEY, attributes ); TorrentUtils.writeToFile(torrent, true); } catch (Throwable e) { Logger.log(new LogEvent(torrent, LOGID, "Saving state", e)); } } else { // System.out.println( "not writing download state for '" + new String(torrent.getName())); } } public void delete() { try{ class_mon.enter(); HashWrapper wrapper = torrent.getHashWrapper(); state_map.remove( wrapper ); TorrentUtils.delete( torrent ); File dir = new File( ACTIVE_DIR, ByteFormatter.encodeString( wrapper.getBytes())); if ( dir.exists() && dir.isDirectory()){ FileUtil.recursiveDelete( dir ); } removeListeners(); }catch( Throwable e ){ Debug.printStackTrace( e ); }finally{ class_mon.exit(); } } protected void mergeTorrentDetails( TOTorrent other_torrent ) { try{ boolean write = TorrentUtils.mergeAnnounceURLs( other_torrent, torrent ); // System.out.println( "DownloadManagerState:mergeTorrentDetails -> " + write ); if ( write ){ save(); if ( download_manager != null ){ TRTrackerAnnouncer client = download_manager.getTrackerClient(); if ( client != null ){ // pick up any URL changes client.resetTrackerUrl( false ); } } } }catch( Throwable e ){ Debug.printStackTrace( e ); } } public void setFlag( long flag, boolean set ) { long old_value = getLongAttribute( AT_FLAGS ); long new_value; if ( set ){ new_value = old_value | flag; }else{ new_value = old_value & ~flag; } if ( old_value != new_value ){ setLongAttribute( AT_FLAGS, new_value ); } } public boolean getFlag( long flag ) { long value = getLongAttribute( AT_FLAGS ); return(( value & flag ) != 0 ); } public long getFlags() { return( getLongAttribute( AT_FLAGS )); } public boolean parameterExists(String name) { return parameters.containsKey(name); } public void setParameterDefault( String name ) { try{ this_mon.enter(); Object value = parameters.get( name ); if ( value == null ){ return; } // gotta clone here otherwise we update the underlying map and the setMapAttribute code // doesn't think it has changed parameters = new LightHashMap(parameters); parameters.remove( name ); }finally{ this_mon.exit(); } setMapAttribute( AT_PARAMETERS, parameters ); } public long getLongParameter( String name ) { try{ this_mon.enter(); Object value = parameters.get( name ); if ( value == null ){ value = default_parameters.get( name ); if ( value == null ){ Debug.out( "Unknown parameter '" + name + "' - must be defined in DownloadManagerState" ); return( 0 ); }else{ // default overrides // **** note - if you add to these make sure you extend the parameter listeners // registered as well (see addParameterListeners) if ( name == PARAM_MAX_UPLOADS_WHEN_SEEDING_ENABLED ){ if ( COConfigurationManager.getBooleanParameter( "enable.seedingonly.maxuploads" )){ value = new Boolean( true ); } }else if ( name == PARAM_MAX_UPLOADS_WHEN_SEEDING ){ int def = COConfigurationManager.getIntParameter( "Max Uploads Seeding" ); value = new Integer( def ); }else if ( name == PARAM_MAX_UPLOADS ){ int def = COConfigurationManager.getIntParameter("Max Uploads" ); value = new Integer( def ); }else if ( name == PARAM_MAX_PEERS ){ int def = COConfigurationManager.getIntParameter( "Max.Peer.Connections.Per.Torrent" ); value = new Integer( def ); }else if ( name == PARAM_MAX_PEERS_WHEN_SEEDING_ENABLED ){ if ( COConfigurationManager.getBooleanParameter( "Max.Peer.Connections.Per.Torrent.When.Seeding.Enable" )){ value = new Boolean( true ); } }else if ( name == PARAM_MAX_PEERS_WHEN_SEEDING ){ int def = COConfigurationManager.getIntParameter( "Max.Peer.Connections.Per.Torrent.When.Seeding" ); value = new Integer( def ); }else if ( name == PARAM_MAX_SEEDS ){ value = new Integer(COConfigurationManager.getIntParameter( "Max Seeds Per Torrent" )); }else if ( name == PARAM_RANDOM_SEED ){ long rand = random.nextLong(); setLongParameter( name, rand ); value = new Long( rand ); } } } if ( value instanceof Boolean ){ return(((Boolean)value).booleanValue()?1:0); }else if ( value instanceof Integer ){ return( ((Integer)value).longValue()); }else if ( value instanceof Long ){ return( ((Long)value).longValue()); } Debug.out( "Invalid parameter value for '" + name + "' - " + value ); return( 0 ); }finally{ this_mon.exit(); } } public void setLongParameter( String name, long value ) { Object default_value = default_parameters.get( name ); if ( default_value == null ){ Debug.out( "Unknown parameter '" + name + "' - must be defined in DownloadManagerState" ); } try{ this_mon.enter(); // gotta clone here otherwise we update the underlying map and the setMapAttribute code // doesn't think it has changed parameters = new LightHashMap(parameters); parameters.put( name, new Long(value)); setMapAttribute( AT_PARAMETERS, parameters ); }finally{ this_mon.exit(); } } public int getIntParameter( String name ) { return( (int)getLongParameter( name )); } public void setIntParameter( String name, int value ) { setLongParameter( name, value ); } public boolean getBooleanParameter( String name ) { return( getLongParameter( name ) != 0 ); } public void setBooleanParameter( String name, boolean value ) { setLongParameter( name, value?1:0 ); } public void setAttribute( String name, String value ) { if ( name.equals( AT_CATEGORY )){ if ( value == null ){ setCategory( null ); }else{ Category cat = CategoryManager.getCategory( value ); if ( cat == null ){ cat = CategoryManager.createCategory( value ); } setCategory( cat ); } return; } if (name.equals(AT_RELATIVE_SAVE_PATH)) { if (value.length() > 0) { File relative_path_file = new File(value); relative_path_file = DownloadManagerDefaultPaths.normaliseRelativePath(relative_path_file); value = (relative_path_file == null) ? "" : relative_path_file.getPath(); } } setStringAttribute( name, value ); } public String getAttribute( String name ) { if ( name.equals( AT_CATEGORY )){ Category cat = getCategory(); if ( cat == null ){ return( null ); } if ( cat == CategoryManager.getCategory( Category.TYPE_UNCATEGORIZED )){ return( null ); } return( cat.getName()); }else{ return( getStringAttribute( name )); } } public Category getCategory() { return category; } public void setCategory( Category cat ) { if ( cat == CategoryManager.getCategory(Category.TYPE_UNCATEGORIZED)){ cat = null; } if ( cat == category ){ return; } if (cat != null && cat.getType() != Category.TYPE_USER){ cat = null; } Category oldCategory = (category == null)?CategoryManager.getCategory(Category.TYPE_UNCATEGORIZED):category; category = cat; if (oldCategory != null ){ oldCategory.removeManager( this ); } if (category != null ){ category.addManager( this ); } if ( category != null && category.getType() == Category.TYPE_USER ){ setStringAttribute( AT_CATEGORY, category.getName()); }else{ setStringAttribute( AT_CATEGORY, null ); } } public String getTrackerClientExtensions() { return( getStringAttribute( AT_TRACKER_CLIENT_EXTENSIONS )); } public void setTrackerClientExtensions( String value ) { setStringAttribute( AT_TRACKER_CLIENT_EXTENSIONS, value ); } public String getDisplayName() { return this.getStringAttribute(AT_DISPLAY_NAME); } public void setDisplayName(String value) { this.setStringAttribute(AT_DISPLAY_NAME, value); } public String getUserComment() { return this.getStringAttribute(AT_USER_COMMENT); } public void setUserComment(String value) { this.setStringAttribute(AT_USER_COMMENT, value); } public String getRelativeSavePath() { return this.getStringAttribute(AT_RELATIVE_SAVE_PATH); } public String getPrimaryFile() { String sPrimary = this.getStringAttribute(AT_PRIMARY_FILE); // Only recheck when file doesn't exists if this is the first check // of the session, because the file may never exist and we don't want // to continuously go through the fileinfos if (sPrimary == null || sPrimary.length() == 0 || (firstPrimaryFileRead && !new File(sPrimary).exists() && download_manager.getStats().getDownloadCompleted(true) != 0)) { DiskManagerFileInfo[] fileInfo = download_manager.getDiskManagerFileInfo(); if (fileInfo.length > 0) { int idxBiggest = -1; long lBiggest = -1; int numChecked = 0; for (int i = 0; i < fileInfo.length && numChecked < 10; i++) { if (!fileInfo[i].isSkipped()) { numChecked++; if (fileInfo[i].getLength() > lBiggest) { lBiggest = fileInfo[i].getLength(); idxBiggest = i; } } } if (idxBiggest >= 0) { sPrimary = fileInfo[idxBiggest].getFile(true).getPath(); } } // System.out.println("calc getPrimaryFile " + sPrimary + ": " + download_manager.getDisplayName()); } if (sPrimary == null) { sPrimary = ""; } if (firstPrimaryFileRead) { firstPrimaryFileRead = false; } setPrimaryFile(sPrimary); return sPrimary; } /** * @param primary */ public void setPrimaryFile(String fileFullPath) { this.setStringAttribute(AT_PRIMARY_FILE, fileFullPath); } public String[] getNetworks() { List values = getListAttributeSupport( AT_NETWORKS ); List res = new ArrayList(); // map back to the constants to allow == comparisons for (int i=0;i= values.size() || idx < 0) return null; Object o = values.get(idx); if (o instanceof byte[]) { byte[] bytes = (byte[]) o; String s = null; try { s = StringInterner.intern(new String(bytes, Constants.DEFAULT_ENCODING)); } catch (UnsupportedEncodingException e) { Debug.printStackTrace(e); } if (s != null) values.set(idx, s); return s; } else if (o instanceof String) { return (String) o; } } finally { this_mon.exit(); } return null; } public String[] getListAttribute( String attribute_name ) { if ( attribute_name == AT_NETWORKS ){ return( getNetworks()); }else if ( attribute_name == AT_PEER_SOURCES ){ return( getPeerSources()); }else{ List l = getListAttributeSupport( attribute_name ); if ( l == null ){ return( null ); } String[] res = new String[l.size()]; try { res = (String[])l.toArray(res); } catch (ArrayStoreException e) { Debug.out( "getListAttribute( " + attribute_name + ") - object isnt String - " + e ); return( null ); } return( res ); } } protected List getListAttributeSupport( String attribute_name ) { informWillRead( attribute_name ); try{ this_mon.enter(); List values = (List)attributes.get( attribute_name ); List res = new ArrayList(values != null ? values.size() : 0); if ( values != null ){ for (int i=0;i 0 ){ List s = new ArrayList( urls.length ); for (int j=0;j 0 ){ return( size ); } if ( fixup()){ size = delegate.getSize(); return( size ); } return( 0 ); } public TOTorrentFile[] getFiles() { if ( fixup()){ return( delegate.getFiles()); } return( new TOTorrentFile[0] ); } public byte[] getHash() throws TOTorrentException { // optimise this return( torrent_hash_wrapper.getBytes()); } public HashWrapper getHashWrapper() throws TOTorrentException { return( torrent_hash_wrapper ); } public void setHashOverride( byte[] hash ) throws TOTorrentException { throw( new TOTorrentException( "Not supported", TOTorrentException.RT_HASH_FAILS )); } public boolean hasSameHashAs( TOTorrent other ) { try{ byte[] other_hash = other.getHash(); return( Arrays.equals( getHash(), other_hash )); }catch( TOTorrentException e ){ Debug.printStackTrace( e ); return( false ); } } public boolean getPrivate() { if ( fixup()){ return( delegate.getPrivate()); } return( false ); } public void setPrivate( boolean _private ) throws TOTorrentException { if ( fixup()){ delegate.setPrivate( _private ); } } public void setAdditionalStringProperty( String name, String value ) { if ( fixup()){ delegate.setAdditionalStringProperty( name, value ); } } public String getAdditionalStringProperty( String name ) { Map c = cache; if ( c != null && ( name.equals( "encoding") || name.equals( "torrent filename" ))){ byte[] res = (byte[])c.get( name ); if ( res == null ){ return( null ); } try{ return( new String( res, "UTF8" )); }catch( Throwable e ){ Debug.printStackTrace( e ); return( null ); } } if ( fixup()){ return( delegate.getAdditionalStringProperty( name )); } return( null ); } public void setAdditionalByteArrayProperty( String name, byte[] value ) { if ( fixup()){ delegate.setAdditionalByteArrayProperty( name, value ); } } public byte[] getAdditionalByteArrayProperty( String name ) { if ( fixup()){ return( delegate.getAdditionalByteArrayProperty( name )); } return( null ); } public void setAdditionalLongProperty( String name, Long value ) { if ( fixup()){ delegate.setAdditionalLongProperty( name, value ); } } public Long getAdditionalLongProperty( String name ) { if ( fixup()){ return( delegate.getAdditionalLongProperty( name )); } return( null ); } public void setAdditionalListProperty( String name, List value ) { if ( fixup()){ delegate.setAdditionalListProperty( name, value ); } } public List getAdditionalListProperty( String name ) { if ( fixup()){ return( delegate.getAdditionalListProperty( name )); } return( null ); } public void setAdditionalMapProperty( String name, Map value ) { if ( fixup()){ delegate.setAdditionalMapProperty( name, value ); } } public Map getAdditionalMapProperty( String name ) { Map c = cache_attributes; if ( c != null && name.equals( "attributes" )){ return( c ); } c = cache_azp; if ( c != null && name.equals( "azureus_properties" )){ return( c ); } if ( fixup()){ return( delegate.getAdditionalMapProperty( name )); } return( null ); } public Object getAdditionalProperty( String name ) { if ( fixup()){ return( delegate.getAdditionalProperty( name )); } return( null ); } public void setAdditionalProperty( String name, Object value ) { if ( fixup()){ delegate.setAdditionalProperty( name, value ); } } public void removeAdditionalProperty( String name ) { if ( fixup()){ delegate.removeAdditionalProperty( name ); } } public void removeAdditionalProperties() { if ( fixup()){ delegate.removeAdditionalProperties(); } } public void serialiseToBEncodedFile( File file ) throws TOTorrentException { if ( fixup()){ delegate.serialiseToBEncodedFile( file ); return; } throw( fixup_failure ); } public Map serialiseToMap() throws TOTorrentException { if ( fixup()){ return( delegate.serialiseToMap()); } throw( fixup_failure ); } public void serialiseToXMLFile( File file ) throws TOTorrentException { if ( fixup()){ delegate.serialiseToXMLFile( file ); return; } throw( fixup_failure ); } public AEMonitor getMonitor() { if ( fixup()){ return( delegate.getMonitor()); } return( null ); } public void print() { if ( fixup()){ delegate.print(); } } /* (non-Javadoc) * @see org.gudy.azureus2.core3.logging.LogRelation#getLogRelationText() */ public String getRelationText() { return "Torrent: '" + new String(getName()) + "'"; } /* (non-Javadoc) * @see org.gudy.azureus2.core3.logging.LogRelation#queryForClass(java.lang.Class) */ public Object[] getQueryableInterfaces() { // yuck try { return new Object[] { AzureusCoreFactory.getSingleton() .getGlobalManager().getDownloadManager(this) }; } catch (Exception e) { } return null; } } }azureus-4.3.0.6/org/gudy/azureus2/core3/download/impl/DownloadManagerStatsImpl.java0000644000175000017500000003474510660561414027526 0ustar adrianadrian/* * File : DownloadManagerStatsImpl.java * Created : 24-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.download.impl; /** * @author parg */ import org.gudy.azureus2.core3.download.*; import org.gudy.azureus2.core3.peer.*; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.disk.*; public class DownloadManagerStatsImpl implements DownloadManagerStats { private DownloadManagerImpl download_manager; //Completed (used for auto-starting purposes) private int completed; private int downloadCompleted; // saved downloaded and uploaded private long saved_data_bytes_downloaded; private long saved_protocol_bytes_downloaded; private long saved_data_bytes_uploaded; private long saved_protocol_bytes_uploaded; private long saved_discarded = 0; private long saved_hashfails = 0; private long saved_SecondsDownloading = 0; private long saved_SecondsOnlySeeding = 0; private int saved_SecondsSinceDownload = 0; private int saved_SecondsSinceUpload = 0; private int max_upload_rate_bps = 0; //0 for unlimited private int max_download_rate_bps = 0; //0 for unlimited protected DownloadManagerStatsImpl( DownloadManagerImpl dm ) { download_manager = dm; } public long getDataReceiveRate() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null){ return pm.getStats().getDataReceiveRate(); } return 0; } public long getProtocolReceiveRate() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null){ return pm.getStats().getProtocolReceiveRate(); } return 0; } public long getDataSendRate() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null){ return pm.getStats().getDataSendRate(); } return 0; } public long getProtocolSendRate() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null){ return pm.getStats().getProtocolSendRate(); } return 0; } public long getETA() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null){ return pm.getETA(); } return -1; //return exactly -1 if ETA is unknown } public int getCompleted() { DiskManager dm = download_manager.getDiskManager(); if (dm == null) { int state = download_manager.getState(); if (state == DownloadManager.STATE_ALLOCATING || state == DownloadManager.STATE_CHECKING || state == DownloadManager.STATE_INITIALIZING) return completed; else return downloadCompleted; } if (dm.getState() == DiskManager.ALLOCATING || dm.getState() == DiskManager.CHECKING || dm.getState() == DiskManager.INITIALIZING) return dm.getPercentDone(); else { long total = dm.getTotalLength(); return total == 0 ? 0 : (int) ((1000 * (total - dm.getRemaining())) / total); } } public void setCompleted(int _completed) { completed = _completed; } public int getDownloadCompleted( boolean bLive ) { DiskManager dm = download_manager.getDiskManager(); // no disk manager -> not running -> use stored value if ( dm == null ){ return downloadCompleted; } int state = dm.getState(); boolean transient_state = state == DiskManager.INITIALIZING || state == DiskManager.ALLOCATING || state == DiskManager.CHECKING; long total = dm.getTotalLength(); int computed_completion = (total == 0) ? 0 : (int) ((1000 * (total - dm.getRemaining())) / total); // use non-transient values to update the record of download completion if ( !transient_state ){ downloadCompleted = computed_completion; } if ( bLive ){ // return the transient completion level return computed_completion; }else{ // return the non-transient one return( downloadCompleted ); } } public void setDownloadCompleted(int _completed) { downloadCompleted = _completed; } public String getElapsedTime() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null){ return pm.getElapsedTime(); } return ""; } public long getTimeStarted() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null){ return pm.getTimeStarted(); } return -1; } public long getTimeStartedSeeding() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null){ return pm.getTimeStartedSeeding(); } return -1; } public long getTotalDataBytesReceived() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null) { return saved_data_bytes_downloaded + pm.getStats().getTotalDataBytesReceived(); } return(saved_data_bytes_downloaded); } public long getTotalGoodDataBytesReceived() { long downloaded = getTotalDataBytesReceived(); downloaded -= ( getHashFailBytes() + getDiscarded()); if ( downloaded < 0 ){ downloaded = 0; } return( downloaded ); } public long getTotalProtocolBytesReceived() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null) { return saved_protocol_bytes_downloaded + pm.getStats().getTotalProtocolBytesReceived(); } return(saved_protocol_bytes_downloaded); } public long getTotalDataBytesSent() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null) { return saved_data_bytes_uploaded + pm.getStats().getTotalDataBytesSent(); } return( saved_data_bytes_uploaded ); } public long getTotalProtocolBytesSent() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null) { return saved_protocol_bytes_uploaded + pm.getStats().getTotalProtocolBytesSent(); } return( saved_protocol_bytes_uploaded ); } public long getRemaining() { DiskManager disk_manager = download_manager.getDiskManager(); if ( disk_manager == null ){ return download_manager.getSize() - ((long)getCompleted() * download_manager.getSize() / 1000L); }else{ return disk_manager.getRemainingExcludingDND(); } } public long getDiscarded() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null){ return saved_discarded + pm.getStats().getTotalDiscarded(); } return( saved_discarded ); } public long getHashFailCount() { TOTorrent t = download_manager.getTorrent(); if ( t == null ){ return(0); } long total = getHashFailBytes(); long res = total / t.getPieceLength(); if ( res == 0 && total > 0 ){ res = 1; } return( res ); } public long getHashFailBytes() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null){ return saved_hashfails + pm.getStats().getTotalHashFailBytes(); } return( saved_hashfails ); } public long getTotalAverage() { PEPeerManager pm = download_manager.getPeerManager(); if (pm != null){ return pm.getStats().getTotalAverage(); } return( 0 ); } public long getTotalAveragePerPeer() { int div = download_manager.getNbPeers() + (download_manager.isDownloadComplete(false) ? 0 : 1); //since total speed includes our own speed when downloading long average = div < 1 ? 0 : getTotalAverage() / div; return( average ); } public int getShareRatio() { long downloaded = getTotalGoodDataBytesReceived(); long uploaded = getTotalDataBytesSent(); if ( downloaded <= 0 ){ return( -1 ); } return (int) ((1000 * uploaded) / downloaded); } public long getSecondsDownloading() { long lTimeStartedDL = getTimeStarted(); if (lTimeStartedDL >= 0) { long lTimeEndedDL = getTimeStartedSeeding(); if (lTimeEndedDL == -1) { lTimeEndedDL = SystemTime.getCurrentTime(); } if (lTimeEndedDL > lTimeStartedDL) { return saved_SecondsDownloading + ((lTimeEndedDL - lTimeStartedDL) / 1000); } } return saved_SecondsDownloading; } public long getSecondsOnlySeeding() { long lTimeStarted = getTimeStartedSeeding(); if (lTimeStarted >= 0) { return saved_SecondsOnlySeeding + ((SystemTime.getCurrentTime() - lTimeStarted) / 1000); } return saved_SecondsOnlySeeding; } public float getAvailability() { PEPeerManager pm = download_manager.getPeerManager(); if ( pm == null ){ return( -1 ); } return( pm.getMinAvailability()); } public int getUploadRateLimitBytesPerSecond() { return max_upload_rate_bps; } public void setUploadRateLimitBytesPerSecond( int max_rate_bps ) { max_upload_rate_bps = max_rate_bps; } public int getDownloadRateLimitBytesPerSecond() { return max_download_rate_bps; } public void setDownloadRateLimitBytesPerSecond( int max_rate_bps ) { max_download_rate_bps = max_rate_bps; } public int getTimeSinceLastDataReceivedInSeconds() { PEPeerManager pm = download_manager.getPeerManager(); int res = saved_SecondsSinceDownload; if ( pm != null ){ int current = pm.getStats().getTimeSinceLastDataReceivedInSeconds(); if ( current >= 0 ){ // activity this session, use this value res = current; }else{ // no activity this session. If ever has been activity add in session // time if ( res >= 0 ){ long now = SystemTime.getCurrentTime(); long elapsed = now - pm.getTimeStarted(); if ( elapsed < 0 ){ elapsed = 0; } res += elapsed/1000; } } } return( res ); } public int getTimeSinceLastDataSentInSeconds() { PEPeerManager pm = download_manager.getPeerManager(); int res = saved_SecondsSinceUpload; if ( pm != null ){ int current = pm.getStats().getTimeSinceLastDataSentInSeconds(); if ( current >= 0 ){ // activity this session, use this value res = current; }else{ // no activity this session. If ever has been activity add in session // time if ( res >= 0 ){ long now = SystemTime.getCurrentTime(); long elapsed = now - pm.getTimeStarted(); if ( elapsed < 0 ){ elapsed = 0; } res += elapsed/1000; } } } return( res ); } public long getAvailWentBadTime() { PEPeerManager pm = download_manager.getPeerManager(); if ( pm != null ){ long bad_time = pm.getAvailWentBadTime(); if ( bad_time > 0 ){ // valid last bad time return( bad_time ); } if ( pm.getMinAvailability() >= 1.0 ){ // we can believe the fact that it isn't bad (we want to ignore 0 results from // downloads that never get to a 1.0 availbility) return( 0 ); } } DownloadManagerState state = download_manager.getDownloadState(); return( state.getLongAttribute( DownloadManagerState.AT_AVAIL_BAD_TIME )); } protected void saveSessionTotals() { // re-base the totals from current totals and session totals saved_data_bytes_downloaded = getTotalDataBytesReceived(); saved_data_bytes_uploaded = getTotalDataBytesSent(); saved_discarded = getDiscarded(); saved_hashfails = getHashFailBytes(); saved_SecondsDownloading = getSecondsDownloading(); saved_SecondsOnlySeeding = getSecondsOnlySeeding(); saved_SecondsSinceDownload = getTimeSinceLastDataReceivedInSeconds(); saved_SecondsSinceUpload = getTimeSinceLastDataSentInSeconds(); DownloadManagerState state = download_manager.getDownloadState(); state.setIntAttribute( DownloadManagerState.AT_TIME_SINCE_DOWNLOAD, saved_SecondsSinceDownload ); state.setIntAttribute( DownloadManagerState.AT_TIME_SINCE_UPLOAD, saved_SecondsSinceUpload ); state.setLongAttribute( DownloadManagerState.AT_AVAIL_BAD_TIME, getAvailWentBadTime()); } protected void setSavedDownloadedUploaded( long d, long u ) { saved_data_bytes_downloaded = d; saved_data_bytes_uploaded = u; } public void restoreSessionTotals( long _saved_data_bytes_downloaded, long _saved_data_bytes_uploaded, long _saved_discarded, long _saved_hashfails, long _saved_SecondsDownloading, long _saved_SecondsOnlySeeding ) { saved_data_bytes_downloaded = _saved_data_bytes_downloaded; saved_data_bytes_uploaded = _saved_data_bytes_uploaded; saved_discarded = _saved_discarded; saved_hashfails = _saved_hashfails; saved_SecondsDownloading = _saved_SecondsDownloading; saved_SecondsOnlySeeding = _saved_SecondsOnlySeeding; DownloadManagerState state = download_manager.getDownloadState(); saved_SecondsSinceDownload = state.getIntAttribute( DownloadManagerState.AT_TIME_SINCE_DOWNLOAD ); saved_SecondsSinceUpload = state.getIntAttribute( DownloadManagerState.AT_TIME_SINCE_UPLOAD ); } protected void generateEvidence( IndentWriter writer) { writer.println( "DownloadManagerStats" ); try{ writer.indent(); writer.println( "recv_d=" + getTotalDataBytesReceived() + ",recv_p=" + getTotalProtocolBytesReceived() + ",recv_g=" + getTotalGoodDataBytesReceived() + ",sent_d=" + getTotalDataBytesSent() + ",sent_p=" + getTotalProtocolBytesSent() + ",discard=" + getDiscarded() + ",hash_fails=" + getHashFailCount() + "/" + getHashFailBytes() + ",comp=" + getCompleted() + "[live:" + getDownloadCompleted(true) + "/" + getDownloadCompleted( false) + "],dl_comp=" + downloadCompleted + ",remaining=" + getRemaining()); }finally{ writer.exdent(); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerStats.java0000644000175000017500000001223511004133210025707 0ustar adrianadrian/* * File : DownloadManagerStats.java * Created : 22-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.download; /** * @author parg * */ public interface DownloadManagerStats { /** Find out percentage done of current state * Use getDownloadCompleted() if you wish to find out a torrents download completion level * * @return 0 to 1000, 0% to 100% respectively * When state is Allocating, Checking, or Initializing, this * returns the % done of that task * Any other state MAY return getDownloadCompleted() */ public int getCompleted(); /** Retrieve the level of download completion. * * To understand the bLive parameter, you must know a bit about the * Torrent activation process: * 1) Torrent goes into ST_WAITING * 2) Torrent moves to ST_PREPARING * 3) Torrent moves to ST_DOWNLOADING or ST_SEEDING * * While in ST_PREPARING, Completion Level is rebuilt (either via Fast Resume * or via piece checking). Quite often, the download completion level before * ST_PREPARING and after ST_PREPARING are identical. * * Before going into ST_PREPARING, we store the download completion level. * If you wish to retrieve this value instead of the live "building" one, * pass false for the parameter. * * @param bLive true - Always returns the known completion level of the torrent * false - In the case of ST_PREPARING, return completion level * before of the torrent ST_PREPARING started. * Otherwise, same as true. * @return 0 - 1000 */ public int getDownloadCompleted(boolean bLive); public void setDownloadCompleted(int completed); /** * Get the total number of bytes ever downloaded. * @return total bytes downloaded */ public long getTotalDataBytesReceived(); /** * data bytes received minus discards and hashfails * @return */ public long getTotalGoodDataBytesReceived(); public long getTotalProtocolBytesReceived(); /** * Get the total number of bytes ever uploaded. * @return total bytes uploaded */ public long getTotalDataBytesSent(); public long getTotalProtocolBytesSent(); public long getRemaining(); public long getDiscarded(); public long getHashFailBytes(); public long getHashFailCount(); /** * Gives the share ratio of the torrent in 1000ths (i.e. 1000 = share ratio of 1) */ public int getShareRatio(); public long getDataReceiveRate(); public long getProtocolReceiveRate(); public long getDataSendRate(); public long getProtocolSendRate(); /** * Swarm speed * @return */ public long getTotalAverage(); /** * Average for a peer in the swarm * @return */ public long getTotalAveragePerPeer(); public String getElapsedTime(); // in ms public long getTimeStarted(); /* -1 if not seeding */ public long getTimeStartedSeeding(); public long getETA(); public float getAvailability(); public long getSecondsDownloading(); public long getSecondsOnlySeeding(); public void setCompleted( int c ); /** * Get the max upload rate allowed for this download. * @return upload rate in bytes per second, 0 for unlimited, -1 for upload disabled */ public int getUploadRateLimitBytesPerSecond(); /** * Set the max upload rate allowed for this download. * @param max_rate_bps limit in bytes per second, 0 for unlimited, -1 for upload disabled */ public void setUploadRateLimitBytesPerSecond( int max_rate_bps ); /** * Get the max download rate allowed for this download. * @return download rate in bytes per second, 0 for unlimited, -1 for download disabled */ public int getDownloadRateLimitBytesPerSecond(); /** * Set the max download rate allowed for this download. * @param max_rate_bps limit in bytes per second, 0 for unlimited, -1 for download disabled */ public void setDownloadRateLimitBytesPerSecond( int max_rate_bps ); public int getTimeSinceLastDataReceivedInSeconds(); public int getTimeSinceLastDataSentInSeconds(); public long getAvailWentBadTime(); /* public long getEstimatedDownloaded(); public long getEstimatedUploaded(); */ public void restoreSessionTotals( long _saved_data_bytes_downloaded, long _saved_data_bytes_uploaded, long _saved_discarded, long _saved_hashfails, long _saved_SecondsDownloading, long _saved_SecondsOnlySeeding ); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/ForceRecheckListener.java0000644000175000017500000000210010573142234025665 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.download; /** * @author TuxPaper * @created Mar 5, 2007 * */ public interface ForceRecheckListener { public void forceRecheckComplete(DownloadManager dm); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerStateAttributeListener.java0000644000175000017500000000256611012444100031273 0ustar adrianadrian/* * Created on 12 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.download; import org.gudy.azureus2.plugins.download.DownloadAttributeListener; /** * @author Allan Crooks * */ public interface DownloadManagerStateAttributeListener { public static final int WRITTEN = DownloadAttributeListener.WRITTEN; public static final int WILL_BE_READ = DownloadAttributeListener.WILL_BE_READ; public void attributeEventOccurred(DownloadManager download, String attribute, int event_type); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerPieceListener.java0000644000175000017500000000210710746511204027360 0ustar adrianadrian/* * File : DownloadManagerListener.java * Created : 19-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.download; /** * @author parg * */ import org.gudy.azureus2.core3.peer.*; public interface DownloadManagerPieceListener { public void pieceAdded( PEPiece piece ); public void pieceRemoved( PEPiece piece ); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerState.java0000644000175000017500000002450611270516754025724 0ustar adrianadrian/* * Created on 15-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.download; import java.io.File; import java.util.Map; import org.gudy.azureus2.core3.category.Category; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.plugins.download.Download; import com.aelitis.azureus.core.util.CaseSensitiveFileMap; /** * @author parg */ public interface DownloadManagerState { public static final String AT_VERSION = "version"; public static final String AT_CATEGORY = "category"; public static final String AT_NETWORKS = "networks"; public static final String AT_USER = "user"; public static final String AT_PEER_SOURCES = "peersources"; public static final String AT_PEER_SOURCES_DENIED = "peersourcesdenied"; public static final String AT_TRACKER_CLIENT_EXTENSIONS = "trackerclientextensions"; public static final String AT_FILE_LINKS = "filelinks"; public static final String AT_FILE_STORE_TYPES = "storetypes"; public static final String AT_FILE_DOWNLOADED = "filedownloaded"; public static final String AT_FLAGS = "flags"; public static final String AT_PARAMETERS = "parameters"; public static final String AT_DISPLAY_NAME = "displayname"; public static final String AT_USER_COMMENT = "comment"; public static final String AT_RELATIVE_SAVE_PATH = "relativepath"; public static final String AT_SECRETS = "secrets"; public static final String AT_RESUME_STATE = "resumecomplete"; public static final String AT_PRIMARY_FILE = "primaryfile"; public static final String AT_TIME_SINCE_DOWNLOAD = "timesincedl"; public static final String AT_TIME_SINCE_UPLOAD = "timesinceul"; public static final String AT_AVAIL_BAD_TIME = "badavail"; public static final String AT_TIME_STOPPED = "timestopped"; public static final String AT_INCOMP_FILE_SUFFIX = "incompfilesuffix"; public static final String AT_SCRAPE_CACHE = "scrapecache"; // long value, seeds in upper word, leechers in lower public static Object[][] ATTRIBUTE_DEFAULTS = { { AT_VERSION, new Integer( -1 )}, { AT_TIME_SINCE_DOWNLOAD, new Integer( -1 )}, { AT_TIME_SINCE_UPLOAD, new Integer( -1 )}, { AT_AVAIL_BAD_TIME, new Long( -1 )}, { AT_SCRAPE_CACHE, new Long( -1 )}, }; public static final long FLAG_ONLY_EVER_SEEDED = Download.FLAG_ONLY_EVER_SEEDED; public static final long FLAG_SCAN_INCOMPLETE_PIECES = Download.FLAG_SCAN_INCOMPLETE_PIECES; public static final long FLAG_DISABLE_AUTO_FILE_MOVE = Download.FLAG_DISABLE_AUTO_FILE_MOVE; public static final long FLAG_MOVE_ON_COMPLETION_DONE = Download.FLAG_MOVE_ON_COMPLETION_DONE; public static final long FLAG_LOW_NOISE = Download.FLAG_LOW_NOISE; public static final long FLAG_ALLOW_PERMITTED_PEER_SOURCE_CHANGES = Download.FLAG_ALLOW_PERMITTED_PEER_SOURCE_CHANGES; public static final long FLAG_DO_NOT_DELETE_DATA_ON_REMOVE = Download.FLAG_DO_NOT_DELETE_DATA_ON_REMOVE; public static final String PARAM_MAX_PEERS = "max.peers"; public static final String PARAM_MAX_PEERS_WHEN_SEEDING = "max.peers.when.seeding"; public static final String PARAM_MAX_PEERS_WHEN_SEEDING_ENABLED = "max.peers.when.seeding.enabled"; public static final String PARAM_MAX_SEEDS = "max.seeds"; public static final String PARAM_MAX_UPLOADS = "max.uploads"; public static final String PARAM_MAX_UPLOADS_WHEN_SEEDING = "max.uploads.when.seeding"; public static final String PARAM_MAX_UPLOADS_WHEN_SEEDING_ENABLED = "max.uploads.when.seeding.enabled"; public static final String PARAM_STATS_COUNTED = "stats.counted"; public static final String PARAM_DOWNLOAD_ADDED_TIME = "stats.download.added.time"; public static final String PARAM_DOWNLOAD_COMPLETED_TIME = "stats.download.completed.time"; public static final String PARAM_MAX_UPLOAD_WHEN_BUSY = "max.upload.when.busy"; public static final String PARAM_DND_FLAGS = "dndflags"; public static final String PARAM_RANDOM_SEED = "rand"; public static final int DEFAULT_MAX_UPLOADS = 4; public static final int MIN_MAX_UPLOADS = 2; public static Object[][] PARAMETERS = { { PARAM_MAX_PEERS, new Integer( 0 ) }, { PARAM_MAX_PEERS_WHEN_SEEDING, new Integer( 0 ) }, { PARAM_MAX_PEERS_WHEN_SEEDING_ENABLED, new Boolean( false ) }, { PARAM_MAX_SEEDS, new Integer( 0 ) }, { PARAM_MAX_UPLOADS, new Long( DEFAULT_MAX_UPLOADS ) }, { PARAM_MAX_UPLOADS_WHEN_SEEDING, new Integer( DEFAULT_MAX_UPLOADS ) }, { PARAM_MAX_UPLOADS_WHEN_SEEDING_ENABLED, new Boolean( false ) }, { PARAM_STATS_COUNTED, new Boolean( false ) }, { PARAM_DOWNLOAD_ADDED_TIME, new Long( 0 ) }, { PARAM_DOWNLOAD_COMPLETED_TIME, new Long( 0 ) }, { PARAM_MAX_UPLOAD_WHEN_BUSY, new Long( 0 ) }, { PARAM_DND_FLAGS, new Long( 0 ) }, { PARAM_RANDOM_SEED, new Long( 0 ) }, }; public TOTorrent getTorrent(); public DownloadManager getDownloadManager(); public File getStateFile( ); public void setFlag( long flag, boolean set ); public boolean getFlag( long flag ); public long getFlags(); /** * Reset to default value * @param name */ public void setParameterDefault( String name ); public int getIntParameter( String name ); public void setIntParameter( String name, int value ); public long getLongParameter( String name ); public void setLongParameter( String name, long value ); public boolean getBooleanParameter( String name ); public void setBooleanParameter( String name, boolean value ); public void clearResumeData(); public Map getResumeData(); public void setResumeData( Map data ); public boolean isResumeDataComplete(); public void clearTrackerResponseCache(); public Map getTrackerResponseCache(); public void setTrackerResponseCache( Map value ); public Category getCategory(); public void setCategory( Category cat ); public String getDisplayName(); public void setDisplayName(String name); public String getUserComment(); public void setUserComment(String name); public String getRelativeSavePath(); public void setPrimaryFile(String fileFullPath); public String getPrimaryFile(); public String getTrackerClientExtensions(); public void setTrackerClientExtensions( String value ); public String[] // from AENetworkClassifier constants getNetworks(); public boolean isNetworkEnabled( String network); //from AENetworkClassifier constants public void setNetworks( String[] networks ); // from AENetworkClassifier constants public void setNetworkEnabled( String network, // from AENetworkClassifier constants boolean enabled); public String[] // from PEPeerSource constants getPeerSources(); public boolean isPeerSourcePermitted( String peerSource ); public void setPeerSourcePermitted( String peerSource, boolean permitted ); public boolean isPeerSourceEnabled( String peerSource); // from PEPeerSource constants public void setPeerSources( String[] sources ); // from PEPeerSource constants public void setPeerSourceEnabled( String source, // from PEPeerSource constants boolean enabled); // file links public void setFileLink( File link_source, File link_destination ); public void clearFileLinks(); public File getFileLink( File link_source ); /** * returns a File -> File map of the defined links (empty if no links) * @return */ public CaseSensitiveFileMap getFileLinks(); /** * @return */ boolean isOurContent(); // General access - make sure you use an AT_ value defined above when calling // these methods. public void setAttribute(String name, String value); public String getAttribute(String name); public void setMapAttribute(String name, Map value); public Map getMapAttribute(String name); public void setListAttribute(String name, String[] values); public String[] getListAttribute(String name); public String getListAttribute(String name, int idx); public void setIntAttribute(String name, int value); public int getIntAttribute(String name); public void setLongAttribute(String name, long value); public long getLongAttribute(String name); public void setBooleanAttribute(String name, boolean value); public boolean getBooleanAttribute(String name); public boolean hasAttribute(String name); public void setActive( boolean active ); public void discardFluff(); public void save(); /** * deletes the saved state */ public void delete(); public void addListener( DownloadManagerStateListener l ); public void removeListener( DownloadManagerStateListener l ); /** * @param name * @return */ boolean parameterExists(String name); public void generateEvidence(IndentWriter writer); /** * This method should only be invoked in matching try-finally pairs. If it is invoked with true * multiple times it must be invoked with false the equal amount of times to reallow state * writes * * @param suppress * when set to true prevents flushing of the state/increments the internal nesting * counter, decrements/allows flush otherwise */ public void suppressStateSave(boolean suppress); public void addListener(DownloadManagerStateAttributeListener l, String attribute, int event_type); public void removeListener(DownloadManagerStateAttributeListener l, String attribute, int event_type); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerListener.java0000644000175000017500000000367210416502244026420 0ustar adrianadrian/* * File : DownloadManagerListener.java * Created : 29-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.download; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; /** * @author parg * * [Paper 2004/01/12] * Added DownloadManager parameter to calls. This allows for one listener object * to listen to many DownloadManagers */ public interface DownloadManagerListener { public void stateChanged( DownloadManager manager, int state ); /** Notification that we were downloading and the download has completed */ public void downloadComplete(DownloadManager manager); /** Notification that the completion state has changed. * Tells you when we switched from Completed to Incompleted (or visa versa) * Does not get called when diskManager goes into CHECKING, but does * when it goes out of CHECKING, to avoid torrents jumping momentarily from * Completed to Incompleted to Completed again. */ public void completionChanged(DownloadManager manager, boolean bCompleted); public void positionChanged(DownloadManager download, int oldPosition, int newPosition); public void filePriorityChanged( DownloadManager download, DiskManagerFileInfo file ); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerStateEvent.java0000644000175000017500000000244710373051034026712 0ustar adrianadrian/* * Created on 10-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.download; /** * @author parg * */ public interface DownloadManagerStateEvent { public static final int ET_ATTRIBUTE_WRITTEN = 1; // data will be string attribute name public static final int ET_ATTRIBUTE_WILL_BE_READ = 2; // data will be string attribute name public int getType(); public Object getData(); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManager.java0000644000175000017500000004255011250135724024712 0ustar adrianadrian/* * File : DownloadManager.java * Created : 19-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.download; import java.io.File; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.disk.DiskManagerFileInfoSet; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.plugins.download.DownloadAnnounceResult; import org.gudy.azureus2.plugins.download.DownloadScrapeResult; import com.aelitis.azureus.core.networkmanager.LimitedRateGroup; public interface DownloadManager { public static final int STATE_START_OF_DAY = -1; // should never actually see this one public static final int STATE_WAITING = 0; public static final int STATE_INITIALIZING = 5; public static final int STATE_INITIALIZED = 10; public static final int STATE_ALLOCATING = 20; public static final int STATE_CHECKING = 30; // Ready: Resources allocated public static final int STATE_READY = 40; public static final int STATE_DOWNLOADING = 50; public static final int STATE_FINISHING = 55; public static final int STATE_SEEDING = 60; public static final int STATE_STOPPING = 65; // Stopped: can't be automatically started public static final int STATE_STOPPED = 70; public static final int STATE_CLOSED = 71; // download never *has* this state, just used to inform // when stopping for az closedown // Queued: Same as stopped, except can be automatically started public static final int STATE_QUEUED = 75; public static final int STATE_ERROR = 100; public static final int WEALTH_STOPPED = 1; public static final int WEALTH_NO_TRACKER = 2; public static final int WEALTH_NO_REMOTE = 3; public static final int WEALTH_OK = 4; public static final int WEALTH_KO = 5; public static final int WEALTH_ERROR = 6; public void initialize(); public int getState(); /** * For stopping this returns the target state after stopping (stopped/queued) * @return */ public int getSubState(); public void setStateWaiting(); public void setStateQueued(); public void startDownload(); public boolean canForceRecheck(); public void forceRecheck(); /** * @param l * * @since 3.0.0.7 */ void forceRecheck(ForceRecheckListener l); /** * Reset the file download state to totally undownloaded. Download must be stopped * @param file */ public void resetFile( DiskManagerFileInfo file ); /** * Recheck a particular file. Download must be stopped * @param file */ public void recheckFile( DiskManagerFileInfo file ); /** * Use with care - introduced to support speed tests whereby we want to avoid checking the * virtual torrent used for the test * @param enabled */ public void setPieceCheckingEnabled( boolean enabled ); /** * Stop the download manager, and do any file/torrent removals. * @param _stateAfterStopping * @param remove_torrent remove the .torrent file after stopping * @param remove_data remove the data file after stopping */ public void stopIt( int stateAfterStopping, boolean remove_torrent, boolean remove_data ); public boolean pause(); public boolean isPaused(); public void resume(); public GlobalManager getGlobalManager(); public DiskManager getDiskManager(); public DiskManagerFileInfo[] getDiskManagerFileInfo(); public DiskManagerFileInfoSet getDiskManagerFileInfoSet(); public PEPeerManager getPeerManager(); public DownloadManagerState getDownloadState(); public TOTorrent getTorrent(); public TRTrackerAnnouncer getTrackerClient(); public void requestTrackerAnnounce( boolean immediate ); public void requestTrackerScrape( boolean immediate ); public TRTrackerScraperResponse getTrackerScrapeResponse(); public void setTrackerScrapeResponse( TRTrackerScraperResponse response ); public String getDisplayName(); /** * returns a name based on the torrent hash or an empty string if torrent invalid * @return */ public String getInternalName(); public long getSize(); /** * This includes the full path to the torrent file. * @return */ public String getTorrentFileName(); public void setTorrentFileName(String string); /** * Returns the file location where we save the torrent, this includes the parent * directory and the actual file name. */ public File getAbsoluteSaveLocation(); public File getSaveLocation(); /** * changes the save directory. Only call this if you know what you are doing!!!! * @param sPath */ public void setTorrentSaveDir( String sPath ); /** * changes the save directory. Only call this if you know what you are doing!!!! * @param sPath */ public void setTorrentSaveDir(String parent_dir, String dl_name); public boolean isForceStart(); public void setForceStart(boolean forceStart); public boolean isPersistent(); /** * Retrieves whether the download is complete * * @param bIncludingDND true- include files marked as Do Not Download.
      * false- don't include files marked DND.

      * If there are DND files and you choose to include * DND in the calculation, false will always be * returned. * @return whether download is complete */ public boolean isDownloadComplete(boolean bIncludingDND); public String getTrackerStatus(); public int getTrackerTime(); public String getTorrentComment(); public String getTorrentCreatedBy(); public long getTorrentCreationDate(); public int getNbPieces(); public String getPieceLength(); public int getNbSeeds(); public int getNbPeers(); /** * Same as filesExist( true ); * @deprecated Use {@link #filesExist(boolean)} - to be removed when EMP dependency removed * @return */ public boolean filesExist(); /** * Checks if all the files the user wants to download from this torrent * actually exist on their filesystem. *

      * If a file does not exist, the download will be set to error state. * @param expected_to_be_allocated if this is false and allocation hasn't been attempted then the method will return with false without marking the download as in an error state * @return Whether all the non-skipped (non-DND) files exist */ public boolean filesExist( boolean expected_to_be_allocated ); public String getErrorDetails(); public DownloadManagerStats getStats(); public int getPosition(); public void setPosition( int newPosition ); /** * Retrieve whether this download is assumed complete. *

      * Assumed complete status is kept while the torrent is in a non-running * state, even if it has no data. *

      * When the torrent starts up, the real complete * level will be checked, and if the torrent * actually does have missing data, the download will be thrown * into error state. *

      * Only a forced-recheck should clear this flag. * * @see {@link #requestAssumedCompleteMode()} */ public boolean getAssumedComplete(); /** * Will set this download to be "assumed complete" for if the download * is already complete (excluding DND) * * @return true- success; false- failure, download not complete */ public boolean requestAssumedCompleteMode(); /** * @return the wealthy status of this download */ public int getHealthStatus(); /** * See plugin ConnectionManager.NAT_ constants for return values * @return */ public int getNATStatus(); /** * persist resume data * */ public void saveResumeData(); /** * persist any general download related information, excluding resume data which is * managed separately by saveResumeData */ public void saveDownload(); /** * To retreive arbitrary objects against this object. * @deprecated Use getUserData */ public Object getData (String key); /** To store arbitrary objects against this object. * @deprecated @deprecated Use setUserData * */ public void setData (String key, Object value); public Object getUserData (Object key); /** To store arbitrary objects against this object. */ public void setUserData (Object key, Object value); /** * Determine whether disk allocation has already been done. * Used for checking if data is missing on a previously-loaded torrent. * @return true if data files have already been allocated */ public boolean isDataAlreadyAllocated(); /** * Set whether data allocation has already been done, so we know * when to allocate and when to throw a missing-data error message. * @param already_allocated */ public void setDataAlreadyAllocated( boolean already_allocated ); public void setSeedingRank(int rank); public int getSeedingRank(); public void setMaxUploads( int max_slots ); public int getMaxUploads(); /** * Returns the max uploads depending on whether the download is seeding and it has a separate * rate for this * @return */ public int getEffectiveMaxUploads(); /** * returns the currently in force upload speed limit which may vary from the stats. value * as this gives the fixed per-torrent limit * @return */ public int getEffectiveUploadRateLimitBytesPerSecond(); public void setCryptoLevel( int level ); public int getCryptoLevel(); /** * Move data files to new location. Torrent must be in stopped/error state * @param new_parent_dir * @return */ public void moveDataFiles( File new_parent_dir ) throws DownloadManagerException; /** * Rename the download - this means the name of the file being downloaded (for single * file torrents), or the name of the directory holding the files (in a multi-file torrent). * * This does not alter the displayed name of the download. * * @param new_name * @throws DownloadManagerException */ public void renameDownload(String new_name) throws DownloadManagerException; /** * Move the files and rename a download in one go. * * For convenience - either argument can be null, but not both. * * @see #moveDataFiles(File) * @see #renameDownload(String) */ public void moveDataFiles(File new_parent_dir, String new_name) throws DownloadManagerException; /** * Move torrent file to new location. Download must be stopped/error * @param new_parent_dir * @return */ public void moveTorrentFile( File new_parent_dir ) throws DownloadManagerException; /** * Returns true if the download is being saved to one of the default * save directories. * * @since 2.5.0.2 */ public boolean isInDefaultSaveDir(); /** * gives the time this download was created (not the torrent but the download itself) * @return */ public long getCreationTime(); public void setCreationTime( long t ); public void setAnnounceResult( DownloadAnnounceResult result ); public void setScrapeResult( DownloadScrapeResult result ); public boolean isUnauthorisedOnTracker(); public boolean isTrackerError(); /** * Is extended messaging enabled for this download (meaning AzMP and LTEP support). * @return true if enabled, false if disabled */ public boolean isExtendedMessagingEnabled(); /** * Enable or disable extended messaging messaging for this download. * @param enable true to enabled, false to disabled * * @deprecated Want to get rid of this if possible. */ public void setAZMessagingEnabled( boolean enable ); /** * Indicates that the download manager is no longer needed * @param is_duplicate indicates whether this dm is being destroyed because it is a duplicate */ public void destroy( boolean is_duplicate ); public boolean isDestroyed(); public PEPiece[] getCurrentPieces(); public PEPeer[] getCurrentPeers(); /** * Gives the download an opportunity to schedule seeding mode piece rechecks if desired * @return true if a piece has been rechecked */ public boolean seedPieceRecheck(); public void addRateLimiter( LimitedRateGroup group, boolean upload ); public void removeRateLimiter( LimitedRateGroup group, boolean upload ); /** * @param listener * @param triggerStateChange * * @since 3.1.1.1 */ public void addListener( DownloadManagerListener listener, boolean triggerStateChange ); public void addListener( DownloadManagerListener listener ); public void removeListener( DownloadManagerListener listener ); // tracker listeners public void addTrackerListener( DownloadManagerTrackerListener listener ); public void removeTrackerListener( DownloadManagerTrackerListener listener ); // peer listeners public void addPeerListener( DownloadManagerPeerListener listener ); public void addPeerListener( DownloadManagerPeerListener listener, boolean bDispatchForExisting ); public void removePeerListener( DownloadManagerPeerListener listener ); // piece listeners public void addPieceListener( DownloadManagerPieceListener listener ); public void addPieceListener( DownloadManagerPieceListener listener, boolean bDispatchForExisting ); public void removePieceListener( DownloadManagerPieceListener listener ); // disk listeners public void addDiskListener( DownloadManagerDiskListener listener ); public void removeDiskListener( DownloadManagerDiskListener listener ); public int getActivationCount(); public void addActivationListener( DownloadManagerActivationListener listener ); public void removeActivationListener( DownloadManagerActivationListener listener ); public void generateEvidence( IndentWriter writer ); public int[] getStorageType(DiskManagerFileInfo[] infos); /** * @since 3.0.5.1 */ public boolean canMoveDataFiles(); /** * Renames the save file, torrent file and the displayed name. */ public void rename(String new_name) throws DownloadManagerException; /** * @since 3.0.5.1 */ public void renameTorrent(String new_name) throws DownloadManagerException; /** * Same as renameTorrent, but appends numbers if torrent already exists * @since 4.2.0.9 */ public void renameTorrentSafe(String name) throws DownloadManagerException; /** * @since 3.0.5.1 */ public void moveTorrentFile(File parent_dir, String new_name) throws DownloadManagerException; /** * Sets the torrent file name (will perform a move of the torrent file) - * this shouldn't be used unless you know what you are doing (it requires * the download to be stopped!) - it is safer to use moveTorrentFile instead. * * @since 3.0.5.3 */ public void setTorrentFile(File new_parent_dir, String new_name) throws DownloadManagerException; }azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerTrackerListener.java0000644000175000017500000000220610204241602027715 0ustar adrianadrian/* * File : DownloadManagerTrackerListener.java * Created : 11-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.download; /** * @author parg * */ import org.gudy.azureus2.core3.tracker.client.*; public interface DownloadManagerTrackerListener { public void scrapeResult( TRTrackerScraperResponse response ); public void announceResult( TRTrackerAnnouncerResponse response ); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerDiskListener.java0000644000175000017500000000226610373051034027227 0ustar adrianadrian/* * Created on 02-Jul-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.download; import org.gudy.azureus2.core3.disk.DiskManager; public interface DownloadManagerDiskListener { public void diskManagerAdded( DiskManager dm ); public void diskManagerRemoved( DiskManager dm ); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerInitialisationAdapter.java0000644000175000017500000000212410410066602031100 0ustar adrianadrian/* * Created on 27-Feb-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.download; public interface DownloadManagerInitialisationAdapter { public void initialised( DownloadManager manager ); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerStateListener.java0000644000175000017500000000236511012444344027416 0ustar adrianadrian/* * Created on 10-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.download; /** * @author parg * * @deprecated Don't use this class, use DownloadManagerStateAttributeListener instead. */ public interface DownloadManagerStateListener { public void stateChanged( DownloadManagerState state, DownloadManagerStateEvent event ); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerFactory.java0000644000175000017500000000417410712572662026252 0ustar adrianadrian/* * File : DownloadManagerFactory.java * Created : 19-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.download; /** * @author parg * */ import java.util.List; import org.gudy.azureus2.core3.download.impl.*; import org.gudy.azureus2.core3.global.*; public class DownloadManagerFactory { // new downloads public static DownloadManager create( GlobalManager gm, byte[] torrent_hash, String torrentFileName, String savePath, String saveFile, int initialState, boolean persistent, boolean for_seeding, List file_priorities, DownloadManagerInitialisationAdapter adapter ) { return( new DownloadManagerImpl( gm, torrent_hash, torrentFileName, savePath, saveFile, initialState, persistent, false, for_seeding, false, file_priorities, adapter )); } // recovery method public static DownloadManager create( GlobalManager gm, byte[] torrent_hash, String torrentFileName, String torrent_save_dir, String torrent_save_file, int initialState, boolean persistent, boolean recovered, boolean has_ever_been_started, List file_priorities ) { return( new DownloadManagerImpl( gm, torrent_hash, torrentFileName, torrent_save_dir, torrent_save_file, initialState, persistent, recovered, false, has_ever_been_started, file_priorities, null )); } } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerPeerListener.java0000644000175000017500000000253610746511204027234 0ustar adrianadrian/* * File : DownloadManagerListener.java * Created : 19-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.download; /** * @author parg * */ import org.gudy.azureus2.core3.peer.*; public interface DownloadManagerPeerListener { /** * Called when a peer manager is created but not yet started * @param manager */ public void peerManagerWillBeAdded( PEPeerManager manager ); public void peerManagerAdded( PEPeerManager manager ); public void peerManagerRemoved( PEPeerManager manager ); public void peerAdded( PEPeer peer ); public void peerRemoved( PEPeer peer ); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerActivationListener.java0000644000175000017500000000211210455463374030443 0ustar adrianadrian/* * Created on 13 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.download; public interface DownloadManagerActivationListener { public boolean activateRequest( int count ); } azureus-4.3.0.6/org/gudy/azureus2/core3/download/DownloadManagerException.java0000644000175000017500000000232111012742300026547 0ustar adrianadrian/* * Created on 14-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.download; public class DownloadManagerException extends Exception { public DownloadManagerException( String str ) { super( str ); } public DownloadManagerException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/stats/0000755000175000017500000000000011310377634020333 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/stats/transfer/0000755000175000017500000000000011310377634022157 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/stats/transfer/impl/0000755000175000017500000000000011310377634023120 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/stats/transfer/impl/OverallStatsImpl.java0000644000175000017500000002400111275166326027231 0ustar adrianadrian/* * File : OverallStatsImpl.java * Created : 2 mars 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.stats.transfer.impl; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.gudy.azureus2.core3.global.*; import org.gudy.azureus2.core3.stats.transfer.OverallStats; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreComponent; import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter; import com.aelitis.azureus.core.stats.AzureusCoreStats; import com.aelitis.azureus.core.stats.AzureusCoreStatsProvider; /** * @author Olivier * */ public class OverallStatsImpl extends GlobalManagerAdapter implements OverallStats { // sizes in MB private static final long TEN_YEARS = 60*60*24*365*10L; private static final int STATS_PERIOD = 60*1000; // 1 min private static final int SAVE_PERIOD = 10*60*1000; // 10 min private static final int SAVE_TICKS = SAVE_PERIOD / STATS_PERIOD; private AzureusCore core; private long totalDownloaded; private long totalUploaded; private long totalUptime; private long lastDownloaded; private long lastUploaded; private long lastUptime; // separate stats private long totalProtocolUploaded; private long totalDataUploaded; private long totalProtocolDownloaded; private long totalDataDownloaded; private long lastProtocolUploaded; private long lastDataUploaded; private long lastProtocolDownloaded; private long lastDataDownloaded; private long session_start_time = SystemTime.getCurrentTime(); protected AEMonitor this_mon = new AEMonitor( "OverallStats" ); private int tick_count; private Map load(String filename) { return( FileUtil.readResilientConfigFile( filename )); } private Map load() { return( load("azureus.statistics")); } private void save(String filename, Map map ) { try{ this_mon.enter(); FileUtil.writeResilientConfigFile( filename, map ); }finally{ this_mon.exit(); } } private void save( Map map ) { save("azureus.statistics", map); } private void validateAndLoadValues( Map statisticsMap ) { lastUptime = SystemTime.getCurrentTime() / 1000; Map overallMap = (Map) statisticsMap.get("all"); totalDownloaded = getLong( overallMap, "downloaded" ); totalUploaded = getLong( overallMap, "uploaded" ); totalUptime = getLong( overallMap, "uptime" ); totalProtocolUploaded = getLong( overallMap, "p_uploaded" ); totalDataUploaded = getLong( overallMap, "d_uploaded" ); totalProtocolDownloaded = getLong( overallMap, "p_downloaded" ); totalDataDownloaded = getLong( overallMap, "d_downloaded" ); } protected long getLong( Map map, String name ) { if ( map == null ){ return( 0 ); } Object obj = map.get(name); if (!(obj instanceof Long )){ return(0); } return(((Long)obj).longValue()); } public OverallStatsImpl( AzureusCore _core) { core = _core; Map stats = load(); validateAndLoadValues(stats); Set types = new HashSet(); types.add( AzureusCoreStats.ST_XFER_UPLOADED_PROTOCOL_BYTES ); types.add( AzureusCoreStats.ST_XFER_UPLOADED_DATA_BYTES ); types.add( AzureusCoreStats.ST_XFER_DOWNLOADED_PROTOCOL_BYTES ); types.add( AzureusCoreStats.ST_XFER_DOWNLOADED_DATA_BYTES ); AzureusCoreStats.registerProvider( types, new AzureusCoreStatsProvider() { public void updateStats( Set types, Map values ) { try{ this_mon.enter(); if ( core.isStarted()){ GlobalManagerStats stats = core.getGlobalManager().getStats(); if ( types.contains( AzureusCoreStats.ST_XFER_UPLOADED_PROTOCOL_BYTES )){ values.put( AzureusCoreStats.ST_XFER_UPLOADED_PROTOCOL_BYTES, new Long( totalProtocolUploaded + ( stats.getTotalProtocolBytesSent() - lastProtocolUploaded ))); } if ( types.contains( AzureusCoreStats.ST_XFER_UPLOADED_DATA_BYTES )){ values.put( AzureusCoreStats.ST_XFER_UPLOADED_DATA_BYTES, new Long( totalDataUploaded + ( stats.getTotalDataBytesSent() - lastDataUploaded ))); } if ( types.contains( AzureusCoreStats.ST_XFER_DOWNLOADED_PROTOCOL_BYTES )){ values.put( AzureusCoreStats.ST_XFER_DOWNLOADED_PROTOCOL_BYTES, new Long( totalProtocolDownloaded + ( stats.getTotalProtocolBytesReceived() - lastProtocolDownloaded ))); } if ( types.contains( AzureusCoreStats.ST_XFER_DOWNLOADED_DATA_BYTES )){ values.put( AzureusCoreStats.ST_XFER_DOWNLOADED_DATA_BYTES, new Long( totalDataDownloaded + ( stats.getTotalDataBytesReceived() - lastDataDownloaded ))); } } }finally{ this_mon.exit(); } } }); core.addLifecycleListener( new AzureusCoreLifecycleAdapter() { public void componentCreated( AzureusCore core, AzureusCoreComponent component ) { if ( component instanceof GlobalManager ){ GlobalManager gm = (GlobalManager)component; gm.addListener( OverallStatsImpl.this, false ); SimpleTimer.addPeriodicEvent( "OverallStats", STATS_PERIOD, new TimerEventPerformer() { public void perform(TimerEvent event) { updateStats( false ); } }); } } }); } public int getAverageDownloadSpeed() { if(totalUptime > 1) { return (int)(totalDownloaded / totalUptime); } return 0; } public int getAverageUploadSpeed() { if(totalUptime > 1) { return (int)(totalUploaded / totalUptime); } return 0; } public long getDownloadedBytes() { return totalDownloaded; } public long getUploadedBytes() { return totalUploaded; } public long getTotalUpTime() { return totalUptime; } public long getSessionUpTime() { return (SystemTime.getCurrentTime() - session_start_time) / 1000; } public void destroyInitiated() { updateStats( true ); } private void updateStats( boolean force ) { try{ this_mon.enter(); long current_time = SystemTime.getCurrentTime() / 1000; if ( current_time < lastUptime ) { //time went backwards lastUptime = current_time; return; } GlobalManagerStats stats = core.getGlobalManager().getStats(); long current_total_d_received = stats.getTotalDataBytesReceived(); long current_total_p_received = stats.getTotalProtocolBytesReceived(); long current_total_d_sent = stats.getTotalDataBytesSent(); long current_total_p_sent = stats.getTotalProtocolBytesSent(); long current_total_received = current_total_d_received + current_total_p_received; long current_total_sent = current_total_d_sent + current_total_p_sent; // overall totals totalDownloaded += current_total_received - lastDownloaded; lastDownloaded = current_total_received; if( totalDownloaded < 0 ) totalDownloaded = 0; totalUploaded += current_total_sent - lastUploaded; lastUploaded = current_total_sent; if( totalUploaded < 0 ) totalUploaded = 0; // split totals totalDataDownloaded += current_total_d_received - lastDataDownloaded; lastDataDownloaded = current_total_d_received; if( totalDataDownloaded < 0 ) totalDataDownloaded = 0; totalProtocolDownloaded += current_total_p_received - lastProtocolDownloaded; lastProtocolDownloaded = current_total_p_received; if( totalProtocolDownloaded < 0 ) totalProtocolDownloaded = 0; totalDataUploaded += current_total_d_sent - lastDataUploaded; lastDataUploaded = current_total_d_sent; if( totalDataUploaded < 0 ) totalDataUploaded = 0; totalProtocolUploaded += current_total_p_sent - lastProtocolUploaded; lastProtocolUploaded = current_total_p_sent; if( totalProtocolUploaded < 0 ) totalProtocolUploaded = 0; // TIME long delta = current_time - lastUptime; if( delta > 100 || delta < 0 ) { //make sure the time diff isn't borked lastUptime = current_time; return; } if( totalUptime > TEN_YEARS ) { //total uptime > 10years is an error, reset totalUptime = 0; } if( totalUptime < 0 ) totalUptime = 0; totalUptime += delta; lastUptime = current_time; HashMap overallMap = new HashMap(); overallMap.put("downloaded",new Long(totalDownloaded)); overallMap.put("uploaded",new Long(totalUploaded)); overallMap.put("uptime",new Long(totalUptime)); overallMap.put("p_uploaded",new Long(totalProtocolUploaded)); overallMap.put("d_uploaded",new Long(totalDataUploaded)); overallMap.put("p_downloaded",new Long(totalProtocolDownloaded)); overallMap.put("d_downloaded",new Long(totalDataDownloaded)); Map map = new HashMap(); map.put( "all", overallMap ); tick_count++; if ( force || tick_count % SAVE_TICKS == 0 ){ save( map ); } }finally{ this_mon.exit(); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/stats/transfer/GeneralStats.java0000644000175000017500000000301110654212752025410 0ustar adrianadrian/* * File : GeneralStats.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.stats.transfer; /** * @author Olivier * */ public interface GeneralStats { /** * @return the number of downloaded bytes */ public long getDownloadedBytes(); /** * @return the number of uploaded bytes */ public long getUploadedBytes(); /** * @return the total lifetime 'up time' in seconds */ public long getTotalUpTime(); /** * @return this session uptime in seconds */ public long getSessionUpTime(); /** * @return the average download speed in bytes per second */ public int getAverageDownloadSpeed(); /** * @return the average upload speed in bytes per second */ public int getAverageUploadSpeed(); } azureus-4.3.0.6/org/gudy/azureus2/core3/stats/transfer/OverallStats.java0000644000175000017500000000170010400454652025436 0ustar adrianadrian/* * File : OverallStats.java * Created : 15 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.stats.transfer; /** * @author Olivier * */ public interface OverallStats extends GeneralStats { } azureus-4.3.0.6/org/gudy/azureus2/core3/stats/transfer/StatsFactory.java0000644000175000017500000000233710541725414025453 0ustar adrianadrian/* * File : Factory.java * Created : 2 mars 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.stats.transfer; import org.gudy.azureus2.core3.stats.transfer.impl.OverallStatsImpl; import com.aelitis.azureus.core.AzureusCore; /** * @author Olivier * */ public class StatsFactory { public static OverallStats stats; public static OverallStats getStats() { return stats; } public static void initialize(AzureusCore core ) { stats = new OverallStatsImpl(core); } } azureus-4.3.0.6/org/gudy/azureus2/core3/stats/impl/0000755000175000017500000000000011310377634021274 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/stats/impl/StatsWriterStreamerImpl.java0000644000175000017500000000247110541725414026761 0ustar adrianadrian/* * File : StatsWriterStreamerImpl.java * Created : 30-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.stats.impl; /** * @author parg * */ import java.io.*; import org.gudy.azureus2.core3.stats.*; import com.aelitis.azureus.core.AzureusCore; public class StatsWriterStreamerImpl implements StatsWriterStreamer { protected AzureusCore core; public StatsWriterStreamerImpl( AzureusCore _core ) { core = _core; } public void write( OutputStream output_stream ) throws IOException { new StatsWriterImpl( core ).write( output_stream ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/stats/impl/StatsWriterPeriodicImpl.java0000644000175000017500000001115411264673734026745 0ustar adrianadrian/* * File : StatsWriterPeriodicImpl.java * Created : 23-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.stats.impl; import java.io.File; import org.gudy.azureus2.core3.config.COConfigurationListener; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.stats.StatsWriterPeriodic; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.AzureusCore; /** * @author parg */ public class StatsWriterPeriodicImpl implements StatsWriterPeriodic, COConfigurationListener, TimerEventPerformer { private static final LogIDs LOGID = LogIDs.CORE; private static StatsWriterPeriodicImpl singleton; private boolean started; private long last_write_time = 0; private AzureusCore core; private TimerEventPeriodic event; private boolean config_enabled; private int config_period; private String config_dir; private String config_file; public static synchronized StatsWriterPeriodic create(AzureusCore _core) { synchronized (StatsWriterPeriodicImpl.class) { if (singleton == null) { singleton = new StatsWriterPeriodicImpl(_core); } return (singleton); } } protected StatsWriterPeriodicImpl( AzureusCore _core ) { core = _core; } public void perform(TimerEvent event) { update(); } protected void update() { try { writeStats(); } catch (Throwable e) { Debug.printStackTrace(e); } } protected synchronized void readConfigValues() { config_enabled = COConfigurationManager.getBooleanParameter( "Stats Enable" ); config_period = COConfigurationManager.getIntParameter( "Stats Period" ); config_dir = COConfigurationManager.getStringParameter( "Stats Dir" ); config_file = COConfigurationManager.getStringParameter( "Stats File" ); if(config_enabled) { long targetFrequency = 1000 * (config_period < DEFAULT_SLEEP_PERIOD ? config_period : DEFAULT_SLEEP_PERIOD); if(event != null && event.getFrequency() != targetFrequency) { event.cancel(); event = null; } if(event == null) event = SimpleTimer.addPeriodicEvent("StatsWriter", targetFrequency, this); } else if(event != null) { event.cancel(); event = null; } } protected void writeStats() { if ( !config_enabled ){ return; } int period = config_period; long now = SystemTime.getMonotonousTime() /1000; // if we have a 1 second period then now-last-write_time will often be 0 (due to the // rounding of SystemTime) and the stats won't be written - hence the check against // (period-1). Its only if ( now - last_write_time < ( period - 1 ) ){ return; } last_write_time = now; try{ String dir = config_dir; dir = dir.trim(); if ( dir.length() == 0 ){ dir = File.separator; } String file_name = dir; if ( !file_name.endsWith( File.separator )){ file_name = file_name + File.separator; } String file = config_file; if ( file.trim().length() == 0 ){ file = DEFAULT_STATS_FILE_NAME; } file_name += file; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Stats Logged to '" + file_name + "'")); new StatsWriterImpl( core ).write( file_name ); }catch( Throwable e ){ Logger.log(new LogEvent(LOGID, "Stats Logging fails", e)); } } public void configurationSaved() { // only pick up configuration changes when saved readConfigValues(); writeStats(); } public void start() { if(started) return; started = true; COConfigurationManager.addListener( this ); configurationSaved(); } public void stop() { COConfigurationManager.removeListener( this ); if(event != null) event.cancel(); } } azureus-4.3.0.6/org/gudy/azureus2/core3/stats/impl/StatsWriterImpl.java0000644000175000017500000002404710741771462025267 0ustar adrianadrian/* * File : StatsWriterImpl.java * Created : 30-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.stats.impl; /** * @author parg * */ import java.util.*; import java.io.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.xml.util.*; import org.gudy.azureus2.core3.global.*; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.*; import org.gudy.azureus2.core3.peer.*; import org.gudy.azureus2.core3.torrent.*; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.peermanager.utils.PeerClassifier; public class StatsWriterImpl extends XUXmlWriter { AzureusCore core; protected StatsWriterImpl( AzureusCore _core ) { core = _core; } protected void write( String file_name ) throws IOException { try{ setOutputStream( new FileOutputStream( file_name )); writeSupport(); }finally{ closeOutputStream(); } } protected void write( OutputStream os ) throws IOException { try{ setOutputStream( os ); writeSupport(); }finally{ flushOutputStream(); } } protected void writeSupport() { writeLineRaw( "" ); boolean export_peer_stats = COConfigurationManager.getBooleanParameter("Stats Export Peer Details"); boolean export_file_stats = COConfigurationManager.getBooleanParameter("Stats Export File Details"); String xsl = COConfigurationManager.getStringParameter( "Stats XSL File" ); if ( xsl.length() > 0 ){ writeLineRaw( "" ); } writeLineRaw( ""); GlobalManager global = core.getGlobalManager(); try{ indent(); writeTag( "AZUREUS_VERSION", Constants.AZUREUS_VERSION ); writeLineRaw( "" ); try{ indent(); GlobalManagerStats gm_stats = global.getStats(); writeRawCookedAverageTag( "DOWNLOAD_SPEED", gm_stats.getDataReceiveRate() + gm_stats.getProtocolReceiveRate() ); writeRawCookedAverageTag( "UPLOAD_SPEED", gm_stats.getDataSendRate() + gm_stats.getProtocolSendRate() ); }finally{ exdent(); } writeLineRaw( "" ); writeLineRaw( ""); try{ indent(); List _dms = global.getDownloadManagers(); DownloadManager[] dms = new DownloadManager[_dms.size()]; // sort by position, downloads then seeders _dms.toArray( dms ); Arrays.sort( dms, new Comparator() { public int compare( Object o1, Object o2) { DownloadManager d1 = (DownloadManager)o1; DownloadManager d2 = (DownloadManager)o2; int d1_index = d1.getPosition(); int d2_index = d2.getPosition(); if ( d1.isDownloadComplete(false) ){ d1_index += 1000000; } if ( d2.isDownloadComplete(false) ){ d2_index += 1000000; } return( d1_index - d2_index ); } }); for (int i=0;i"); try{ indent(); writeLineRaw( "" ); // torrent can be null if broken torrent! TOTorrent torrent = dm.getTorrent(); try{ indent(); writeTag( "NAME", dm.getDisplayName()); writeTag( "TORRENT_FILE", dm.getTorrentFileName()); if ( torrent != null ){ writeTag( "HASH", TorrentUtils.nicePrintTorrentHash(torrent, true)); writeRawCookedTag( "SIZE", torrent.getSize()); writeTag( "PIECE_LENGTH", torrent.getPieceLength()); writeTag( "PIECE_COUNT", torrent.getNumberOfPieces()); writeTag( "FILE_COUNT", torrent.getFiles().length ); writeTag( "COMMENT", dm.getTorrentComment()); writeTag( "CREATED_BY", dm.getTorrentCreatedBy()); writeTag( "CREATION_DATE", torrent.getCreationDate()); } }finally{ exdent(); } writeLineRaw( ""); writeTag( "DOWNLOAD_STATUS", DisplayFormatters.formatDownloadStatusDefaultLocale( dm)); writeTag( "DOWNLOAD_DIR", dm.getSaveLocation().toString()); if ( torrent != null ){ if ( torrent.isSimpleTorrent()){ writeTag( "TARGET_FILE", dm.getSaveLocation().toString()); }else{ writeTag( "TARGET_DIR", dm.getSaveLocation().toString()); } } writeTag( "TRACKER_STATUS", dm.getTrackerStatus()); writeTag( "COMPLETED", dm_stats.getCompleted()); writeTag( "NON_DND_COMPLETED", dm.isDownloadComplete(false)); writeRawCookedTag( "DOWNLOADED", dm_stats.getTotalDataBytesReceived()); writeRawCookedTag( "UPLOADED", dm_stats.getTotalDataBytesSent()); writeRawCookedTag( "DISCARDED", dm_stats.getDiscarded()); writeRawCookedAverageTag( "DOWNLOAD_SPEED", dm_stats.getDataReceiveRate()); writeRawCookedAverageTag( "UPLOAD_SPEED", dm_stats.getDataSendRate()); writeRawCookedAverageTag( "TOTAL_SPEED", dm_stats.getTotalAverage()); writeTag( "ELAPSED", dm_stats.getElapsedTime()); writeTag( "ETA", DisplayFormatters.formatETA(dm_stats.getETA())); writeTag( "HASH_FAILS", dm_stats.getHashFailCount()); writeTag( "SHARE_RATIO", dm_stats.getShareRatio()); writeTag( "TOTAL_SEEDS", dm.getNbSeeds()); writeTag( "TOTAL_LEECHERS", dm.getNbPeers()); if ( export_file_stats ){ try{ writeLineRaw( ""); indent(); DiskManagerFileInfo[] files = dm.getDiskManagerFileInfo(); for (int j=0;j"); indent(); writeTag( "NAME", file.getTorrentFile().getRelativePath()); writeTag( "DND", file.isSkipped()); writeRawCookedTag( "SIZE", file.getLength()); writeRawCookedTag( "DOWNLOADED", file.getDownloaded()); }finally{ exdent(); writeLineRaw( ""); } } }finally{ exdent(); writeLineRaw( ""); } } if ( export_peer_stats ){ try{ writeLineRaw( ""); indent(); PEPeerManager pm = dm.getPeerManager(); if ( pm != null ){ List peers = pm.getPeers(); for (int j=0;j"); indent(); writeTag( "IP", peer.getIp()); writeTag( "IS_SEED", peer.isSeed()); writeRawCookedTag( "DOWNLOADED", peer_stats.getTotalDataBytesReceived()); writeRawCookedTag( "UPLOADED", peer_stats.getTotalDataBytesSent()); writeRawCookedAverageTag( "DOWNLOAD_SPEED", peer_stats.getDataReceiveRate()); writeRawCookedAverageTag( "UPLOAD_SPEED", peer_stats.getDataSendRate()); }catch( Throwable e ){ Debug.printStackTrace( e ); }finally{ exdent(); writeLineRaw( ""); } } } }finally{ exdent(); writeLineRaw( ""); } } }finally{ exdent(); } writeLineRaw( ""); } }finally{ exdent(); } writeLineRaw( "" ); }finally{ exdent(); } writeLineRaw( ""); } protected void writeRawCookedTag( String tag, long raw ) { writeLineRaw( "<" + tag + ">"); try{ indent(); writeTag( "TEXT", DisplayFormatters.formatByteCountToKiBEtc( raw )); writeTag( "RAW", raw); }finally{ exdent(); } writeLineRaw( ""); } protected void writeRawCookedAverageTag( String tag, long raw ) { writeLineRaw( "<" + tag + ">"); try{ indent(); writeTag( "TEXT", DisplayFormatters.formatByteCountToKiBEtcPerSec( raw )); writeTag( "RAW", raw); }finally{ exdent(); } writeLineRaw( ""); } } azureus-4.3.0.6/org/gudy/azureus2/core3/stats/StatsWriterStreamer.java0000644000175000017500000000201507750305276025200 0ustar adrianadrian/* * File : StatsWriterStreamer.java * Created : 30-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.stats; /** * @author parg * */ import java.io.*; public interface StatsWriterStreamer { public void write( OutputStream output_stream ) throws IOException; } azureus-4.3.0.6/org/gudy/azureus2/core3/stats/StatsWriterFactory.java0000644000175000017500000000241610541725414025022 0ustar adrianadrian/* * File : StatsWriterFactory.java * Created : 23-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.stats; /** * @author parg * */ import org.gudy.azureus2.core3.stats.impl.*; import com.aelitis.azureus.core.AzureusCore; public class StatsWriterFactory { public static StatsWriterPeriodic createPeriodicDumper( AzureusCore core ) { return(StatsWriterPeriodicImpl.create( core )); } public static StatsWriterStreamer createStreamer( AzureusCore core ) { return( new StatsWriterStreamerImpl( core )); } } azureus-4.3.0.6/org/gudy/azureus2/core3/stats/StatsWriterPeriodic.java0000644000175000017500000000225310057000340025132 0ustar adrianadrian/* * File : StatsWriterPeriodic.java * Created : 23-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.stats; /** * @author parg * */ import org.gudy.azureus2.core3.util.Constants; public interface StatsWriterPeriodic { public static final int DEFAULT_SLEEP_PERIOD = 30*1000; public static final String DEFAULT_STATS_FILE_NAME = Constants.AZUREUS_NAME + "_Stats.xml"; public void start(); public void stop(); } azureus-4.3.0.6/org/gudy/azureus2/core3/internat/0000755000175000017500000000000011310377634021021 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/internat/IntegratedResourceBundle.java0000644000175000017500000002637611231711074026622 0ustar adrianadrian/* * Created on 29.11.2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.internat; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.util.*; import org.gudy.azureus2.core3.util.AETemporaryFileHandler; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.LightHashMap; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.core3.util.TimerEventPeriodic; /** * @author Rene Leonhardt */ public class IntegratedResourceBundle extends ResourceBundle { private static final boolean DEBUG = false; private static final Object NULL_OBJECT = new Object(); private static final Map bundle_map = new WeakHashMap(); private static TimerEventPeriodic compact_timer; protected static void resetCompactTimer() { synchronized( bundle_map ){ if ( compact_timer == null && System.getProperty("transitory.startup", "0").equals("0")){ compact_timer = SimpleTimer.addPeriodicEvent( "IRB:compactor", 60*1000, new TimerEventPerformer() { public void perform( TimerEvent event ) { synchronized( bundle_map ){ Iterator it = bundle_map.keySet().iterator(); boolean did_something = false; while( it.hasNext()){ IntegratedResourceBundle rb = (IntegratedResourceBundle)it.next(); if (DEBUG) { System.out.println("Compact RB " + rb.getString()); } if ( rb.compact()){ did_something = true; } if (DEBUG) { System.out.println(" to " + rb.getString()); } } if ( !did_something ){ compact_timer.cancel(); compact_timer = null; } } } }); } } } private Locale locale; private Map messages; private Map used_messages; private List null_values; private int clean_count = 0; private boolean one_off_discard_done; private File scratch_file_name; private InputStream scratch_file_is; private final int initCapacity; public IntegratedResourceBundle( ResourceBundle main, Map localizationPaths) { this( main, localizationPaths, null, 10 ); } public IntegratedResourceBundle( ResourceBundle main, Map localizationPaths, int initCapacity) { this( main, localizationPaths, null, initCapacity ); } public IntegratedResourceBundle( ResourceBundle main, Map localizationPaths, Collection resource_bundles, int initCapacity) { this.initCapacity = initCapacity; messages = new LightHashMap(initCapacity); locale = main.getLocale(); // use a somewhat decent initial capacity, proper calculation would require java 1.6 addResourceMessages( main ); synchronized (localizationPaths) { for (Iterator iter = localizationPaths.keySet().iterator(); iter.hasNext();){ String localizationPath = (String) iter.next(); ClassLoader classLoader = (ClassLoader) localizationPaths.get(localizationPath); addPluginBundle(localizationPath, classLoader); } } if (resource_bundles != null) { synchronized (resource_bundles) { for (Iterator itr = resource_bundles.iterator(); itr.hasNext();) { addResourceMessages((ResourceBundle)itr.next()); } } } used_messages = new LightHashMap( messages.size()); synchronized( bundle_map ){ bundle_map.put( this, NULL_OBJECT ); resetCompactTimer(); } //System.out.println("IRB Size = " + messages.size() + "/cap=" + initCapacity + ";" + Debug.getCompressedStackTrace()); } public Locale getLocale() { return locale; } private Map getMessages() { return( loadMessages()); } public Enumeration getKeys() { new Exception("Don't call me, call getKeysLight").printStackTrace(); Map m = loadMessages(); return( new Vector( m.keySet()).elements()); } protected Iterator getKeysLight() { Map m = new LightHashMap(loadMessages()); return( m.keySet().iterator()); } /** * Gets a string, using default if key doesn't exist. Skips * throwing MissingResourceException when key doesn't exist, which saves * some CPU cycles * * @param key * @param def * @return * * @since 3.1.1.1 */ public String getString(String key, String def) { String s = (String) handleGetObject(key); if (s == null) { if (parent != null) { s = parent.getString(key); } if (s == null) { return def; } } return s; } protected Object handleGetObject( String key ) { Object res; synchronized( bundle_map ){ res = used_messages.get( key ); } Integer keyHash = null; if (null_values != null) { keyHash = new Integer(key.hashCode()); int index = Collections.binarySearch(null_values, keyHash); if (index >= 0) { return null; } } if ( res == NULL_OBJECT ){ return( null ); } if ( res == null ){ synchronized( bundle_map ){ loadMessages(); if ( messages != null ){ res = messages.get( key ); } if (res == null && null_values != null) { int index = Collections.binarySearch(null_values, keyHash); if (index < 0) { index = -1 * index - 1; // best guess } if (index > null_values.size()) { index = null_values.size(); } null_values.add(index, keyHash); } else { used_messages.put( key, res==null?NULL_OBJECT:res ); } clean_count = 0; resetCompactTimer(); } } return( res ); } public void addPluginBundle(String localizationPath, ClassLoader classLoader) { ResourceBundle newResourceBundle = null; try { if(classLoader != null) newResourceBundle = ResourceBundle.getBundle(localizationPath, locale ,classLoader); else newResourceBundle = ResourceBundle.getBundle(localizationPath, locale,IntegratedResourceBundle.class.getClassLoader()); } catch (Exception e) { // System.out.println(localizationPath+": no resource bundle for " + // main.getLocale()); try { if(classLoader != null) newResourceBundle = ResourceBundle.getBundle(localizationPath, MessageText.LOCALE_DEFAULT,classLoader); else newResourceBundle = ResourceBundle.getBundle(localizationPath, MessageText.LOCALE_DEFAULT,IntegratedResourceBundle.class.getClassLoader()); } catch (Exception e2) { System.out.println(localizationPath + ": no default resource bundle"); return; } } addResourceMessages(newResourceBundle); } public void addResourceMessages( ResourceBundle bundle ) { synchronized (bundle_map) { loadMessages(); if ( bundle != null ){ if ( bundle instanceof IntegratedResourceBundle ){ messages.putAll(((IntegratedResourceBundle)bundle).getMessages()); }else{ for (Enumeration enumeration = bundle.getKeys(); enumeration.hasMoreElements();) { String key = (String) enumeration.nextElement(); messages.put(key, bundle.getObject(key)); } } } } // System.out.println("after addrb; IRB Size = " + messages.size() + "/cap=" + initCapacity + ";" + Debug.getCompressedStackTrace()); } protected boolean compact() { // System.out.println("compact " + getString() + ": cc=" + clean_count ); clean_count++; if ( clean_count == 1 ){ return( true ); } if ( scratch_file_is == null ){ File temp_file = null; FileOutputStream fos = null; try{ Properties props = new Properties(); props.putAll( messages ); temp_file = AETemporaryFileHandler.createTempFile(); fos = new FileOutputStream( temp_file ); props.store( fos, "message cache" ); fos.close(); fos = null; scratch_file_name = temp_file; scratch_file_is = new FileInputStream( temp_file ); }catch( Throwable e ){ if ( fos != null ){ try{ fos.close(); }catch( Throwable f ){ } } if ( temp_file != null ){ temp_file.delete(); } } } if ( scratch_file_is != null ){ if ( clean_count >= 2 ){ // throw away full message map after 2 ticks messages = null; } if ( clean_count == 5 && !one_off_discard_done){ one_off_discard_done = true; // one off discard of used_messages to clear out any that were // accessed once and never again used_messages.clear(); } } if ( clean_count > 5 ){ Map compact_um = new LightHashMap( used_messages.size() + 16 ); compact_um.putAll( used_messages ); used_messages = compact_um; return( false ); }else{ return( true ); } } protected Map loadMessages() { synchronized( bundle_map ){ if ( messages != null ){ return( messages ); } if ( scratch_file_is == null ){ return( new LightHashMap()); } Properties p = new Properties(); InputStream fis = scratch_file_is; try{ p.load( fis ); fis.close(); scratch_file_is = new FileInputStream( scratch_file_name ); messages = new LightHashMap(); messages.putAll( p ); return( messages ); }catch( Throwable e ){ if ( fis != null ){ try{ fis.close(); }catch( Throwable f ){ } } Debug.out( "Failed to load message bundle scratch file", e ); scratch_file_name.delete(); scratch_file_is = null; return( new LightHashMap()); } } } protected String getString() { return( locale + ": use=" + used_messages.size() + ",map=" + (messages==null?"":String.valueOf(messages.size())) + (null_values == null ? "" : ",null=" + null_values.size())); } public void addString(String key, String value) { messages.put(key, value); } public boolean getUseNullList() { return null_values != null; } public void setUseNullList(boolean useNullList) { if (useNullList && null_values == null) { null_values = new ArrayList(0); } else if (!useNullList && null_values != null) { null_values = null; } } public void clearUsedMessagesMap(int initialCapacity) { used_messages = new LightHashMap(initialCapacity); if (null_values != null) { null_values = new ArrayList(0); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/internat/LocaleTorrentUtil.java0000644000175000017500000002403611255104206025273 0ustar adrianadrian/* * Created on May 30, 2006 7:32:56 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.internat; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.util.*; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.TorrentUtils; /** * Locale functions specific to Torrents. * @note Moved from LocaleUtil to keep (cyclical) dependencies down. */ public class LocaleTorrentUtil { private static List listeners = new ArrayList(); /** * Retrieves the encoding of the torrent if it can be determined. *
      * Does not prompt the user with choices. * * @param torrent Torrent to get encoding of * @return Locale torrent is in * * @throws TOTorrentException * @throws UnsupportedEncodingException */ static public LocaleUtilDecoder getTorrentEncodingIfAvailable( TOTorrent torrent) throws TOTorrentException, UnsupportedEncodingException { String encoding = torrent.getAdditionalStringProperty("encoding"); if (encoding == null) { return null; } if (TOTorrent.ENCODING_ACTUALLY_UTF8_KEYS.equals(encoding)) { encoding = "utf8"; } // get canonical name String canonical_name; try { canonical_name = Charset.forName(encoding).name(); } catch (Throwable e) { canonical_name = encoding; } LocaleUtilDecoder chosenDecoder = null; LocaleUtilDecoder[] all_decoders = LocaleUtil.getSingleton().getDecoders(); for (int i = 0; i < all_decoders.length; i++) { if (all_decoders[i].getName().equals(canonical_name)) { chosenDecoder = all_decoders[i]; break; } } return chosenDecoder; } /** * Get the torrent's encoding, prompting the user to choose from a list * if needed. * * @param torrent Torrent to get encoding of * @return LocaleUtilDecoder that the torrent is in * * @throws TOTorrentException * @throws UnsupportedEncodingException * */ // TODO: Use getTorrentEncodingIfAvailable instead of almost-similar code // (merge anything cool from this function's dup code into // getTorrentEncodingIfAvailable) static public LocaleUtilDecoder getTorrentEncoding(TOTorrent torrent) throws TOTorrentException, UnsupportedEncodingException { String encoding = torrent.getAdditionalStringProperty("encoding"); if (TOTorrent.ENCODING_ACTUALLY_UTF8_KEYS.equals(encoding)) { encoding = "utf8"; } // we can only persist the torrent if it has a filename defined for it boolean bSaveToFile; try { TorrentUtils.getTorrentFileName(torrent); bSaveToFile = true; } catch (Throwable e) { bSaveToFile = false; } if (encoding != null) { // get canonical name try { LocaleUtilDecoder[] all_decoders = LocaleUtil.getSingleton().getDecoders(); LocaleUtilDecoder fallback_decoder = LocaleUtil.getSingleton().getFallBackDecoder(); String canonical_name = encoding.equals(fallback_decoder.getName()) ? encoding : Charset.forName(encoding).name(); for (int i = 0; i < all_decoders.length; i++) { if (all_decoders[i].getName().equals(canonical_name)) { return (all_decoders[i]); } } } catch (Throwable e) { Debug.printStackTrace(e); } } // get the decoders valid for various localisable parts of torrent content // not in any particular order LocaleUtilDecoderCandidate[] candidates = getTorrentCandidates(torrent); boolean system_decoder_is_valid = false; LocaleUtil localeUtil = LocaleUtil.getSingleton(); LocaleUtilDecoder system_decoder = localeUtil.getSystemDecoder(); for (int i = 0; i < candidates.length; i++) { if (candidates[i].getDecoder() == system_decoder) { system_decoder_is_valid = true; break; } } LocaleUtilDecoder selected_decoder = null; for (int i = 0; i < listeners.size(); i++) { LocaleUtilDecoderCandidate candidate = null; try { candidate = ((LocaleUtilListener) listeners.get(i)).selectDecoder( localeUtil, torrent, candidates); } catch (LocaleUtilEncodingException e) { } if (candidate != null) { selected_decoder = candidate.getDecoder(); break; } bSaveToFile = false; } if (selected_decoder == null) { // go for system decoder, if valid, fallback if not if (system_decoder_is_valid) { selected_decoder = localeUtil.getSystemDecoder(); } else { selected_decoder = localeUtil.getFallBackDecoder(); } } torrent.setAdditionalStringProperty("encoding", selected_decoder.getName()); if (bSaveToFile) { TorrentUtils.writeToFile(torrent); } return (selected_decoder); } /** * Checks the Torrent's text fields (path, comment, etc) against a list * of locals, returning only those that can handle all the fields. * * @param torrent * @return * @throws TOTorrentException * @throws UnsupportedEncodingException */ static protected LocaleUtilDecoderCandidate[] getTorrentCandidates( TOTorrent torrent) throws TOTorrentException, UnsupportedEncodingException { long lMinCandidates; byte[] minCandidatesArray; Set cand_set = new HashSet(); LocaleUtil localeUtil = LocaleUtil.getSingleton(); List candidateDecoders = localeUtil.getCandidateDecoders(torrent.getName()); lMinCandidates = candidateDecoders.size(); minCandidatesArray = torrent.getName(); cand_set.addAll(candidateDecoders); TOTorrentFile[] files = torrent.getFiles(); for (int i = 0; i < files.length; i++) { TOTorrentFile file = files[i]; byte[][] comps = file.getPathComponents(); for (int j = 0; j < comps.length; j++) { candidateDecoders = localeUtil.getCandidateDecoders(comps[j]); if (candidateDecoders.size() < lMinCandidates) { lMinCandidates = candidateDecoders.size(); minCandidatesArray = comps[j]; } cand_set.retainAll(candidateDecoders); } } byte[] comment = torrent.getComment(); if (comment != null) { candidateDecoders = localeUtil.getCandidateDecoders(comment); if (candidateDecoders.size() < lMinCandidates) { lMinCandidates = candidateDecoders.size(); minCandidatesArray = comment; } cand_set.retainAll(candidateDecoders); } byte[] created = torrent.getCreatedBy(); if (created != null) { candidateDecoders = localeUtil.getCandidateDecoders(created); if (candidateDecoders.size() < lMinCandidates) { lMinCandidates = candidateDecoders.size(); minCandidatesArray = created; } cand_set.retainAll(candidateDecoders); } List candidatesList = localeUtil.getCandidatesAsList(minCandidatesArray); LocaleUtilDecoderCandidate[] candidates; candidates = new LocaleUtilDecoderCandidate[candidatesList.size()]; candidatesList.toArray(candidates); Arrays.sort(candidates, new Comparator() { public int compare(Object o1, Object o2) { LocaleUtilDecoderCandidate luc1 = (LocaleUtilDecoderCandidate) o1; LocaleUtilDecoderCandidate luc2 = (LocaleUtilDecoderCandidate) o2; return (luc1.getDecoder().getIndex() - luc2.getDecoder().getIndex()); } }); return candidates; } static public void setTorrentEncoding(TOTorrent torrent, String encoding) throws LocaleUtilEncodingException { try { LocaleUtil localeUtil = LocaleUtil.getSingleton(); LocaleUtilDecoderCandidate[] candidates = getTorrentCandidates(torrent); String canonical_requested_name; // "System" means use the system encoding if (encoding.equalsIgnoreCase("system")) { canonical_requested_name = localeUtil.getSystemEncoding(); } else if (encoding.equalsIgnoreCase(LocaleUtilDecoderFallback.NAME)) { canonical_requested_name = LocaleUtilDecoderFallback.NAME; } else { CharsetDecoder requested_decoder = Charset.forName(encoding).newDecoder(); canonical_requested_name = requested_decoder.charset().name(); } boolean ok = false; for (int i = 0; i < candidates.length; i++) { if (candidates[i].getDecoder().getName().equals( canonical_requested_name)) { ok = true; break; } } if (!ok) { String[] charsets = new String[candidates.length]; String[] names = new String[candidates.length]; for (int i = 0; i < candidates.length; i++) { LocaleUtilDecoder decoder = candidates[i].getDecoder(); charsets[i] = decoder.getName(); names[i] = decoder.decodeString(torrent.getName()); } throw (new LocaleUtilEncodingException(charsets, names)); } torrent.setAdditionalStringProperty("encoding", canonical_requested_name); } catch (Throwable e) { if (e instanceof LocaleUtilEncodingException) { throw ((LocaleUtilEncodingException) e); } throw (new LocaleUtilEncodingException(e)); } } static public void setDefaultTorrentEncoding(TOTorrent torrent) throws LocaleUtilEncodingException { setTorrentEncoding(torrent, Constants.DEFAULT_ENCODING); } static public String getCurrentTorrentEncoding(TOTorrent torrent) { return (torrent.getAdditionalStringProperty("encoding")); } public static void addListener(LocaleUtilListener l) { listeners.add(l); } public static void removeListener(LocaleUtilListener l) { listeners.remove(l); } } azureus-4.3.0.6/org/gudy/azureus2/core3/internat/MessageText.java0000644000175000017500000006405011250054754024120 0ustar adrianadrian/* * Created on 24.07.2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.internat; import java.io.File; import java.io.FilenameFilter; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.SystemProperties; /** * @author Arbeiten * * @author CrazyAlchemist Added keyExistsForDefaultLocale */ @SuppressWarnings("restriction") public class MessageText { public static final Locale LOCALE_ENGLISH = Constants.LOCALE_ENGLISH; public static final Locale LOCALE_DEFAULT = new Locale("", ""); // == english private static Locale LOCALE_CURRENT = LOCALE_DEFAULT; private static final String BUNDLE_NAME = "org.gudy.azureus2.internat.MessagesBundle"; //$NON-NLS-1$ private static Map pluginLocalizationPaths = new HashMap(); private static Collection pluginResourceBundles = new ArrayList(); private static IntegratedResourceBundle RESOURCE_BUNDLE; private static Set platform_specific_keys = new HashSet(); private static final Pattern PAT_PARAM_ALPHA = Pattern.compile("\\{([^0-9].+?)\\}"); private static int bundle_fail_count = 0; private static List listeners = new ArrayList(); // preload default language w/o plugins static{ setResourceBundle( new IntegratedResourceBundle( getResourceBundle( BUNDLE_NAME, LOCALE_DEFAULT, MessageText.class.getClassLoader()), pluginLocalizationPaths, 4000 )); } // grab a reference to the default bundle private static IntegratedResourceBundle DEFAULT_BUNDLE = RESOURCE_BUNDLE; public static void loadBundle() { loadBundle(false); } public static void loadBundle(boolean forceReload) { Locale old_locale = getCurrentLocale(); String savedLocaleString = COConfigurationManager.getStringParameter("locale"); Locale savedLocale; String[] savedLocaleStrings = savedLocaleString.split("_", 3); if (savedLocaleStrings.length > 0 && savedLocaleStrings[0].length() == 2) { if (savedLocaleStrings.length == 3) { savedLocale = new Locale(savedLocaleStrings[0], savedLocaleStrings[1], savedLocaleStrings[2]); } else if (savedLocaleStrings.length == 2 && savedLocaleStrings[1].length() == 2) { savedLocale = new Locale(savedLocaleStrings[0], savedLocaleStrings[1]); } else { savedLocale = new Locale(savedLocaleStrings[0]); } } else { if (savedLocaleStrings.length == 3 && savedLocaleStrings[0].length() == 0 && savedLocaleStrings[2].length() > 0) { savedLocale = new Locale(savedLocaleStrings[0], savedLocaleStrings[1], savedLocaleStrings[2]); } else { savedLocale = Locale.getDefault(); } } MessageText.changeLocale(savedLocale,forceReload); COConfigurationManager .setParameter("locale.set.complete.count", COConfigurationManager .getIntParameter("locale.set.complete.count") + 1); Locale new_locale = getCurrentLocale(); if ( !old_locale.equals( new_locale ) || forceReload){ for (int i=0;i 0) { Matcher matcher = PAT_PARAM_ALPHA.matcher(value); while (matcher.find()) { key = matcher.group(1); try { String text = getResourceBundleString(key); if (text != null) { value = value.replaceAll("\\Q{" + key + "}\\E", text); } } catch (MissingResourceException e) { // ignore error } } } return value; } /** * Gets the localization key suffix for the running platform * @return The suffix * @see Constants */ private static String getPlatformSuffix() { if(Constants.isOSX) return "._mac"; else if(Constants.isLinux) return "._linux"; else if(Constants.isUnix) return "._unix"; else if(Constants.isFreeBSD) return "._freebsd"; else if(Constants.isSolaris) return "._solaris"; else if(Constants.isWindows) return "._windows"; else return "._unknown"; } /** * Process a sequence of words, and translate the ones containing at least one '.', unless it's an ending dot. * @param sentence * @return the formated String in the current Locale */ public static String getStringForSentence(String sentence) { StringTokenizer st = new StringTokenizer(sentence , " "); StringBuffer result = new StringBuffer(sentence.length()); String separator = ""; while(st.hasMoreTokens()) { result.append(separator); separator = " "; String word = st.nextToken(); int length = word.length(); int position = word.lastIndexOf("."); if(position == -1 || (position+1) == length) { result.append(word); } else { //We have a key : String translated = getString(word); if(translated.equals("!" + word + "!")) { result.append(word); } else { result.append(translated); } } } return result.toString(); } /** * Expands a message text and replaces occurrences of %1 with first param, %2 with second... * @param key * @param params * @return */ public static String getString( String key, String[] params ) { String res = getString(key); if (params == null) { return res; } for(int i=0;i 0 && sLocalesSplit[0].length() == 2) { if (sLocalesSplit.length == 3) { foundLocalesList.add( new Locale(sLocalesSplit[0], sLocalesSplit[1], sLocalesSplit[2])); } else if (sLocalesSplit.length == 2 && sLocalesSplit[1].length() == 2) { foundLocalesList.add( new Locale(sLocalesSplit[0], sLocalesSplit[1])); } else { foundLocalesList.add( new Locale(sLocalesSplit[0])); } } else { if (sLocalesSplit.length == 3 && sLocalesSplit[0].length() == 0 && sLocalesSplit[2].length() > 0) { foundLocalesList.add( new Locale(sLocalesSplit[0], sLocalesSplit[1], sLocalesSplit[2])); } } } } Locale[] foundLocales = new Locale[foundLocalesList.size()]; foundLocalesList.toArray( foundLocales ); if (sort) { try{ Arrays.sort(foundLocales, new Comparator() { public final int compare (Object a, Object b) { return ((Locale)a).getDisplayName((Locale)a).compareToIgnoreCase(((Locale)b).getDisplayName((Locale)b)); } }); }catch( Throwable e ){ // user has a problem whereby a null-pointer exception occurs when sorting the // list - I've done some fixes to the locale list construction but am // putting this in here just in case Debug.printStackTrace( e ); } } return foundLocales; } public static boolean changeLocale(Locale newLocale) { return changeLocale(newLocale, false); } private static boolean changeLocale(Locale newLocale, boolean force) { // set locale for startup (will override immediately it on locale change anyway) Locale.setDefault(newLocale); if (!isCurrentLocale(newLocale) || force) { Locale.setDefault(LOCALE_DEFAULT); ResourceBundle newResourceBundle = null; String bundleFolder = BUNDLE_NAME.replace('.', '/'); final String prefix = BUNDLE_NAME.substring(BUNDLE_NAME.lastIndexOf('.') + 1); final String extension = ".properties"; if(newLocale.equals(LOCALE_ENGLISH)) newLocale = LOCALE_DEFAULT; try { File userBundleFile = new File(SystemProperties.getUserPath()); File appBundleFile = new File(SystemProperties.getApplicationPath()); // Get the jarURL // XXX Is there a better way to get the JAR name? ClassLoader cl = MessageText.class.getClassLoader(); String sJar = cl.getResource(bundleFolder + extension).toString(); sJar = sJar.substring(0, sJar.length() - prefix.length() - extension.length()); URL jarURL = new URL(sJar); // User dir overrides app dir which overrides jar file bundles URL[] urls = {userBundleFile.toURL(), appBundleFile.toURL(), jarURL}; /* This is debugging code, use it when things go wrong :) The line number * is approximate as the input stream is buffered by the reader... { LineNumberInputStream lnis = null; try{ ClassLoader fff = new URLClassLoader(urls); java.io.InputStream stream = fff.getResourceAsStream("MessagesBundle_th_TH.properties"); lnis = new LineNumberInputStream( stream ); new java.util.PropertyResourceBundle(lnis); }catch( Throwable e ){ System.out.println( lnis.getLineNumber()); e.printStackTrace(); } } */ newResourceBundle = getResourceBundle("MessagesBundle", newLocale, new URLClassLoader(urls)); // do more searches if getBundle failed, or if the language is not the // same and the user wanted a specific country if ((!newResourceBundle.getLocale().getLanguage().equals(newLocale.getLanguage()) && !newLocale.getCountry().equals(""))) { Locale foundLocale = newResourceBundle.getLocale(); System.out.println("changeLocale: "+ (foundLocale.toString().equals("") ? "*Default Language*" : foundLocale.getDisplayLanguage()) + " != "+newLocale.getDisplayName()+". Searching without country.."); // try it without the country Locale localeJustLang = new Locale(newLocale.getLanguage()); newResourceBundle = getResourceBundle("MessagesBundle", localeJustLang, new URLClassLoader(urls)); if (newResourceBundle == null || !newResourceBundle.getLocale().getLanguage().equals(localeJustLang.getLanguage())) { // find first language we have in our list System.out.println("changeLocale: Searching for language " + newLocale.getDisplayLanguage() + " in *any* country.."); Locale[] locales = getLocales(false); for (int i = 0; i < locales.length; i++) { if (locales[i].getLanguage() == newLocale.getLanguage()) { newResourceBundle = getResourceBundle("MessagesBundle", locales[i], new URLClassLoader(urls)); break; } } } } } catch (MissingResourceException e) { System.out.println("changeLocale: no resource bundle for " + newLocale); Debug.printStackTrace( e ); return false; } catch (Exception e) { Debug.printStackTrace( e ); } if (newResourceBundle != null) { if (!newLocale.equals(LOCALE_DEFAULT) && !newResourceBundle.getLocale().equals(newLocale)) { String sNewLanguage = newResourceBundle.getLocale().getDisplayName(); if (sNewLanguage == null || sNewLanguage.trim().equals("")) sNewLanguage = "English (default)"; System.out.println("changeLocale: no message properties for Locale '" + newLocale.getDisplayName() + "' (" + newLocale + "), using '" + sNewLanguage + "'"); if (newResourceBundle.getLocale().equals(RESOURCE_BUNDLE.getLocale())) { return false; } } newLocale = newResourceBundle.getLocale(); Locale.setDefault(newLocale.equals(LOCALE_DEFAULT) ? LOCALE_ENGLISH : newLocale); LOCALE_CURRENT = newLocale; setResourceBundle(new IntegratedResourceBundle(newResourceBundle, pluginLocalizationPaths, 3200)); if(newLocale.equals(LOCALE_DEFAULT)) DEFAULT_BUNDLE = RESOURCE_BUNDLE; return true; } else return false; } return false; } // TODO: This is slow. For every call, IntegratedResourceBundle creates // a hashtables and fills it with the old resourceBundle, then adds // the new one, and then puts it all back into a ListResourceBundle. // As we get more plugins, the time to add a new plugin's language file // increases dramatically (even if the language file only has 1 entry!) // Fix this by: // - Create only one IntegratedResourceBundle // - extending ResourceBundle // - override handleGetObject, store in hashtable // - function to add another ResourceBundle, adds to hashtable public static boolean integratePluginMessages(String localizationPath, ClassLoader classLoader) { boolean integratedSuccessfully = false; if (null != localizationPath && localizationPath.length() != 0 && !pluginLocalizationPaths.containsKey(localizationPath)) { synchronized (pluginLocalizationPaths) { pluginLocalizationPaths.put(localizationPath, classLoader); } RESOURCE_BUNDLE.addPluginBundle(localizationPath, classLoader); setResourceBundle(RESOURCE_BUNDLE); integratedSuccessfully = true; } return integratedSuccessfully; } public static boolean integratePluginMessages(ResourceBundle bundle) { synchronized (pluginResourceBundles) { pluginResourceBundles.add(bundle); } RESOURCE_BUNDLE.addResourceMessages(bundle); setResourceBundle(RESOURCE_BUNDLE); return true; } /** * Reverts Locale back to default, and removes the config settin. * Notifications of change should be done by the caller. */ /* @SuppressWarnings("restriction") public static void revertToDefaultLocale() { // Aside from the last 2 lines, this is Sun's code that is run // at startup to determine the locale. Too bad they didn't provide // a way to call this code explicitly.. String language, region, country, variant; language = System.getProperty("user.language", "en"); // for compatibility, check for old user.region property region = System.getProperty("user.region"); if (region != null) { // region can be of form country, country_variant, or _variant int i = region.indexOf('_'); if (i >= 0) { country = region.substring(0, i); variant = region.substring(i + 1); } else { country = region; variant = ""; } } else { country = System.getProperty("user.country", ""); variant = System.getProperty("user.variant", ""); } changeLocale(new Locale(language, country, variant)); COConfigurationManager.removeParameter("locale"); } */ public static interface MessageTextListener { public void localeChanged( Locale old_locale, Locale new_locale ); } /** * Sometime a localization key has 2 different returned values: one for Classic UI and another for the Vuze UI * This method will attempt to locate the given key (with the prefix v3. ) if applicable, if found * then it will return the key with the prepended prefix. Otherwise it will return the key as given * @param localizationKey * @return */ public static String resolveLocalizationKey(String localizationKey) { if (null == localizationKey) { return null; } if (true == "az3".equalsIgnoreCase(COConfigurationManager.getStringParameter("ui"))) { String v3Key = null; if (false == localizationKey.startsWith("v3.")) { v3Key = "v3." + localizationKey; } else { v3Key = localizationKey; } if (true == MessageText.keyExists(v3Key)) { return v3Key; } } return localizationKey; } /** * Sometime a accelerator key has 2 different returned values: one for Classic UI and another for the Vuze UI * This method will attempt to locate the given key (with the prefix v3. ) if applicable, if found * then it will return the key with the prepended prefix. Otherwise it will return the key as given * @param acceleratorKey * @return */ public static String resolveAcceleratorKey(String acceleratorKey) { if (null == acceleratorKey) { return null; } if (true == "az3".equalsIgnoreCase(COConfigurationManager.getStringParameter("ui"))) { String v3Key = null; if (false == acceleratorKey.startsWith("v3.")) { v3Key = "v3." + acceleratorKey; } else { v3Key = acceleratorKey; } if (true == MessageText.keyExists(v3Key + ".keybinding")) { return v3Key; } } return acceleratorKey; } } azureus-4.3.0.6/org/gudy/azureus2/core3/internat/LocaleUtilDecoderCandidate.java0000644000175000017500000000506510373051006027000 0ustar adrianadrian/* * Created on 25-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.internat; public class LocaleUtilDecoderCandidate implements Comparable { private int index; private String value; private LocaleUtilDecoder decoder; protected LocaleUtilDecoderCandidate( int _index ) { index = _index; } public String getValue() { return value; } public LocaleUtilDecoder getDecoder() { return decoder; } public void setDetails( LocaleUtilDecoder _decoder, String _value ) { decoder = _decoder; value = _value; } public int compareTo(Object o) { LocaleUtilDecoderCandidate candidate = (LocaleUtilDecoderCandidate)o; int res; if( value == null && candidate.value == null){ res = 0; }else if ( value == null ){ res = 1; }else if ( candidate.value == null ){ res = -1; }else{ res = value.length() - candidate.value.length(); if ( res == 0 ){ res = index - candidate.index; } } if ( decoder != null && candidate.getDecoder() != null ){ // System.out.println( "comp:" + decoder.getName() + "/" + candidate.getDecoder().getName() + " -> " + res ); } return( res ); } /* removed as this removed valid decoders that happen to decode to the same thing for the current public boolean equals(Object obj) { LocaleUtilDecoderCandidate other = (LocaleUtilDecoderCandidate) obj; if ( value == null && other.value == null ){ return( true ); }else if ( value == null || other.value == null ){ return( false ); }else{ return( value.equals( other.value )); } } */ }azureus-4.3.0.6/org/gudy/azureus2/core3/internat/LocaleUtil.java0000644000175000017500000001522110437303614023716 0ustar adrianadrian/** * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.internat; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.*; public class LocaleUtil { private static final String systemEncoding = System.getProperty("file.encoding"); private static final String[] manual_charset = { systemEncoding, // must be first entry due to code below that gets the system decoder "Big5","EUC-JP","EUC-KR","GB18030","GB2312","GBK","ISO-2022-JP","ISO-2022-KR", "Shift_JIS","KOI8-R", "TIS-620", // added for bug #1008848 Constants.DEFAULT_ENCODING,"windows-1251",Constants.BYTE_ENCODING }; // the general ones *must* also be members of the above manual ones protected static final String[] generalCharsets = { Constants.BYTE_ENCODING, Constants.DEFAULT_ENCODING, systemEncoding }; private static LocaleUtil singleton = new LocaleUtil(); public static LocaleUtil getSingleton() { return( singleton ); } private LocaleUtilDecoder[] all_decoders; private LocaleUtilDecoder[] general_decoders; private LocaleUtilDecoder system_decoder; private LocaleUtilDecoder fallback_decoder; private LocaleUtil() { List decoders = new ArrayList(); List decoder_names = new ArrayList(); for (int i = 0; i < manual_charset.length; i++) { try { String name = manual_charset[i]; CharsetDecoder decoder = Charset.forName(name).newDecoder(); if ( decoder != null ){ LocaleUtilDecoder lu_decoder = new LocaleUtilDecoderReal(decoders.size(),decoder); decoder_names.add( lu_decoder.getName()); if ( i == 0 ){ system_decoder = lu_decoder; } decoders.add( lu_decoder ); }else if ( i == 0 ){ Debug.out( "System decoder failed to be found!!!!" ); } }catch (Exception ignore) { } } general_decoders = new LocaleUtilDecoder[generalCharsets.length]; for (int i=0;i max_ok_name_length ){ // could be a file system out there that supports arbitarily long names, so // we can't pre-calculate the max if ( ( !max_ok_name_length_determined )&& fileLengthOK( len )){ // this length is ok, bump up the known limit max_ok_name_length = len; }else{ // won't fit if ( !max_ok_name_length_determined ){ for (int i=max_ok_name_length+16;i 4 ){ extension = null; } } // replace the end of the string with a hash value to ensure uniqueness byte[] hash = new SHA1Hasher().calculateHash( data ); String hash_str = ByteFormatter.nicePrint( hash, true ); res = new StringBuffer(res.substring( 0, max_ok_name_length - hash_str.length() - (extension == null?0:extension.length()))); res.append( hash_str ); if ( extension != null ){ res.append( extension ); } } } return( res.toString()); } protected boolean fileLengthOK( int len ) { StringBuffer n = new StringBuffer( len ); for (int i=0;i This XML Schema document represents a BitTorrent torrent file's contents azureus-4.3.0.6/org/gudy/azureus2/core3/xml/schemas/classxmlserialisationinfo.xsd0000644000175000017500000000474307771437152027451 0ustar adrianadrian This XML Schema document represents information to (de)serialize a Azureus class to xml. azureus-4.3.0.6/org/gudy/azureus2/core3/xml/simpleparser/0000755000175000017500000000000011310377634022503 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/xml/simpleparser/SimpleXMLParserDocumentFactory.java0000644000175000017500000000331010100507270031344 0ustar adrianadrian/* * File : SimpleXMLParserDocumentFactory.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.xml.simpleparser; import java.io.*; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentException; import org.gudy.azureus2.pluginsimpl.local.utils.xml.simpleparser.SimpleXMLParserDocumentImpl; public class SimpleXMLParserDocumentFactory { public static SimpleXMLParserDocument create( File file ) throws SimpleXMLParserDocumentException { return( new SimpleXMLParserDocumentImpl( file )); } public static SimpleXMLParserDocument create( InputStream is ) throws SimpleXMLParserDocumentException { return( new SimpleXMLParserDocumentImpl( is )); } public static SimpleXMLParserDocument create( String data ) throws SimpleXMLParserDocumentException { return( new SimpleXMLParserDocumentImpl( data )); } } azureus-4.3.0.6/org/gudy/azureus2/core3/xml/util/0000755000175000017500000000000011310377634020752 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/xml/util/XMLElement.java0000644000175000017500000002264210551551710023570 0ustar adrianadrian/** * Created on 10-Jan-2006 * Created by Allan Crooks * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.xml.util; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Map; import java.util.Iterator; import java.util.TreeMap; import java.util.TreeSet; public class XMLElement { protected Object single_content; protected Map attributes; protected Collection contents; protected String tag_name; protected boolean auto_order; public XMLElement(String tag_name) { this(tag_name, false); } public XMLElement(String tag_name, boolean auto_order) { this.single_content = null; this.attributes = null; this.contents = null; this.tag_name = tag_name; this.auto_order = auto_order; } public String getTag() { return tag_name; } public String getAttribute(String key) { if (this.attributes == null) {return null;} return (String)this.attributes.get(key); } public void addAttribute(String key, String value) { if (attributes == null) { this.attributes = new TreeMap(ATTRIBUTE_COMPARATOR); } this.attributes.put(key, value); } public void addAttribute(String key, int value) { this.addAttribute(key, String.valueOf(value)); } public void addAttribute(String key, boolean value) { this.addAttribute(key, (value) ? "yes" : "no"); } public void addContent(String s) {addContent((Object)s);} public void addContent(XMLElement e) {addContent((Object)e);} protected void addContent(Object o) { if (o == null) throw new NullPointerException(); if (this.contents == null) { if (this.single_content != null) { if (!this.auto_order) { this.contents = new ArrayList(); } else { this.contents = new TreeSet(CONTENT_COMPARATOR); } this.contents.add(this.single_content); this.single_content = null; } } if (this.contents == null) { this.single_content = o; } else { this.contents.add(o); } } public void printTo(PrintWriter pw) { printTo(pw, 0, false); } public void printTo(PrintWriter pw, boolean spaced_out) { printTo(pw, 0, spaced_out); } public void printTo(PrintWriter pw, int indent) { printTo(pw, indent, false); } public void printTo(PrintWriter pw, int indent, boolean spaced_out) { for (int i=0; i"); } return; } pw.print("<"); pw.print(this.tag_name); Iterator itr = null; if (this.attributes != null) { itr = this.attributes.entrySet().iterator(); while (itr.hasNext()) { Map.Entry entry = (Map.Entry)itr.next(); pw.print(" "); pw.print(entry.getKey()); pw.print("=\""); pw.print(quote((String)entry.getValue())); pw.print("\""); } } boolean needs_indented_close = (this.contents != null || this.single_content instanceof XMLElement); boolean needs_close_tag = needs_indented_close || this.single_content != null; needs_indented_close = needs_indented_close || spaced_out; needs_close_tag = needs_close_tag || spaced_out; if (needs_indented_close) {pw.println(">");} else if (needs_close_tag) {pw.print(">");} else {pw.print(" />");} itr = null; if (this.contents != null) { itr = this.contents.iterator(); } else if (this.single_content != null) { itr = Collections.singletonList(this.single_content).iterator(); } else { itr = Collections.singletonList("").iterator(); } Object content_element = null; if (itr != null) { while (itr.hasNext()) { content_element = itr.next(); if (content_element instanceof XMLElement) { ((XMLElement)content_element).printTo(pw, indent+2, spaced_out); } else if (spaced_out) { for (int i=0; i"); } } private String quote(String text) { text = text.replaceAll( "&", "&" ); text = text.replaceAll( ">", ">" ); text = text.replaceAll( "<", "<" ); text = text.replaceAll( "\"", """ ); text = text.replaceAll( "--", "--" ); return text; } public XMLElement makeContent(String tag_name) { return this.makeContent(tag_name, false); } public XMLElement makeContent(String tag_name, boolean auto_order) { XMLElement content = new XMLElement(tag_name, auto_order); this.addContent(content); return content; } public void clear() { this.single_content = null; this.attributes = null; this.contents = null; } public void setAutoOrdering(boolean mode) { if (mode == this.auto_order) return; this.auto_order = mode; if (this.contents == null) return; Collection previous_contents = contents; if (this.auto_order) { this.contents = new TreeSet(CONTENT_COMPARATOR); this.contents.addAll(previous_contents); } else { this.contents = new ArrayList(previous_contents); } } public String toString() { return "XMLElement[" + this.tag_name + "]@" + Integer.toHexString(System.identityHashCode(this)); } private static Comparator ATTRIBUTE_COMPARATOR = String.CASE_INSENSITIVE_ORDER; private static class ContentComparator implements java.util.Comparator { public int compare(Object o1, Object o2) { if (o1 instanceof XMLElement) { if (o2 instanceof XMLElement) { XMLElement xe1 = (XMLElement)o1; XMLElement xe2 = (XMLElement)o2; int result = String.CASE_INSENSITIVE_ORDER.compare(xe1.getTag(), xe2.getTag()); if (result == 0) { int xe1_index = 0, xe2_index = 0; try { xe1_index = Integer.parseInt(xe1.getAttribute("index")); xe2_index = Integer.parseInt(xe2.getAttribute("index")); } catch (NullPointerException ne) { xe1_index = xe2_index = 0; } catch (NumberFormatException ne) { xe1_index = xe2_index = 0; } if (xe1_index != xe2_index) { return xe1_index - xe2_index; } throw new RuntimeException("Shouldn't be using sorting for contents if you have tags with same name and no index attribute! (e.g. " + o1 + ")"); } return result; } else { return -1; // XMLElements before strings. } } else { if (o2 instanceof XMLElement) { return 1; // XMLElements before strings. } else { // Can't allow the returning of 0. int result = String.CASE_INSENSITIVE_ORDER.compare((String)o1, (String)o2); if (result == 0) {return -1;} return result; } } } } private static Comparator CONTENT_COMPARATOR = new ContentComparator(); } azureus-4.3.0.6/org/gudy/azureus2/core3/xml/util/XUXmlWriter.java0000644000175000017500000002107411222640230024016 0ustar adrianadrian/* * File : XUXmlWriter.java * Created : 23-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.xml.util; /** * @author parg */ import java.io.*; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import org.gudy.azureus2.core3.util.*; public class XUXmlWriter { private static final int INDENT_AMOUNT = 4; private String current_indent_string; private PrintWriter writer; private boolean generic_simple; protected XUXmlWriter() { resetIndent(); } protected XUXmlWriter( OutputStream _output_stream ) { setOutputStream( _output_stream ); resetIndent(); } protected void setOutputStream( OutputStream _output_stream ) { try{ writer = new PrintWriter( new OutputStreamWriter(_output_stream , Constants.DEFAULT_ENCODING )); }catch( UnsupportedEncodingException e ){ Debug.printStackTrace( e ); writer = new PrintWriter( _output_stream ); } } protected void setOutputWriter( Writer _writer ) { if ( _writer instanceof PrintWriter ){ writer = (PrintWriter)_writer; }else{ writer = new PrintWriter( _writer ); } } protected void setGenericSimple( boolean simple ) { generic_simple = simple; } protected void writeTag( String tag, String content ) { writeLineRaw( "<" + tag + ">" + escapeXML( content ) + "" ); } protected void writeTag( String tag, long content ) { writeLineRaw( "<" + tag + ">" + content + "" ); } protected void writeTag( String tag, boolean content ) { writeLineRaw( "<" + tag + ">" + (content?"YES":"NO") + "" ); } protected void writeLineRaw( String str ) { writer.println( current_indent_string + str ); } protected void writeLineEscaped( String str ) { writer.println( current_indent_string + escapeXML(str)); } protected void resetIndent() { current_indent_string = ""; } protected void indent() { for (int i=0;i= INDENT_AMOUNT ){ current_indent_string = current_indent_string.substring(0,current_indent_string.length()-INDENT_AMOUNT); }else{ current_indent_string = ""; } } public static String escapeXML( String str ) { if ( str == null ){ return( "" ); } str = str.replaceAll( "&", "&" ); str = str.replaceAll( ">", ">" ); str = str.replaceAll( "<", "<" ); str = str.replaceAll( "\"", """ ); str = str.replaceAll( "'", "'" ); str = str.replaceAll( "--", "--" ); char[] chars = str.toCharArray(); // eliminate chars not supported by XML for ( int i=0;i= 127 && c <= 159 ) || !Character.isDefined( c )){ chars[i] = '?'; } } return( new String( chars )); } public static String unescapeXML( String str ) { if ( str == null ){ return( "" ); } str = str.replaceAll( ">", ">" ); str = str.replaceAll( "<", "<" ); str = str.replaceAll( """, "\"" ); str = str.replaceAll( "'", "'" ); str = str.replaceAll( "--", "--" ); str = str.replaceAll( "&", "&" ); return( str ); } public static String[] splitWithEscape( String str, char delim ) { List res = new ArrayList(); String current = ""; char[] chars = str.toCharArray(); for (int i=0;i 0 ){ res.add( current ); current = ""; } }else{ current += c; } } if ( current.length() > 0 ){ res.add( current ); } return( res.toArray( new String[ res.size() ])); } protected void flushOutputStream() { if ( writer != null ){ writer.flush(); } } protected void closeOutputStream() { if ( writer != null ){ writer.flush(); writer.close(); writer = null; } } // generic Map encoder protected void writeGenericMapEntry( String name, Object value ) { if ( generic_simple ){ name = name.replace(' ', '_' ).toUpperCase(); writeLineRaw( "<" + name + ">" ); try{ indent(); writeGeneric( value ); }finally{ exdent(); } writeLineRaw( "" ); }else{ writeLineRaw( ""); try{ indent(); writeGeneric( value ); }finally{ exdent(); } writeLineRaw( ""); } } protected void writeGeneric( Object obj ) { if ( obj instanceof Map ){ writeGeneric((Map)obj); }else if( obj instanceof List ){ writeGeneric((List)obj); }else if ( obj instanceof String ){ writeGeneric((String)obj ); }else if ( obj instanceof byte[] ){ writeGeneric((byte[])obj); }else{ writeGeneric((Long)obj); } } protected void writeGeneric( Map map ) { writeLineRaw( "" ); try{ indent(); Iterator it = map.keySet().iterator(); while(it.hasNext()){ String key = (String)it.next(); writeGenericMapEntry( key, map.get( key )); } }finally{ exdent(); } writeLineRaw( "" ); } protected void writeGeneric( List list ) { writeLineRaw( "" ); try{ indent(); for (int i=0;i" ); } protected void writeGeneric( byte[] bytes ) { if ( generic_simple ){ try{ writeLineRaw( escapeXML( new String(bytes, "UTF-8" ))); }catch( Throwable e ){ e.printStackTrace(); } }else{ writeTag( "BYTES", encodeBytes( bytes )); } } protected void writeGeneric( String str ) { if ( generic_simple ){ try{ writeLineRaw( escapeXML( str )); }catch( Throwable e ){ e.printStackTrace(); } }else{ writeTag( "STRING", str ); } } protected void writeGeneric( Long l ) { if ( generic_simple ){ writeLineRaw( l.toString()); }else{ writeTag( "LONG", ""+l ); } } protected void writeTag( String tag, byte[] content ) { writeLineRaw( "<" + tag + ">" + encodeBytes( content ) + "" ); } protected void writeLocalisableTag( String tag, byte[] content ) { boolean use_bytes = true; String utf_string = null; try{ utf_string = new String(content,Constants.DEFAULT_ENCODING); if ( Arrays.equals( content, utf_string.getBytes( Constants.DEFAULT_ENCODING))){ use_bytes = false; } }catch( UnsupportedEncodingException e ){ } writeLineRaw( "<" + tag + " encoding=\""+(use_bytes?"bytes":"utf8") + "\">" + (use_bytes?encodeBytes( content ):escapeXML(utf_string)) + "" ); } protected String encodeBytes( byte[] bytes ) { String data = ByteFormatter.nicePrint( bytes, true ); return( data ); /* try{ return( URLEncoder.encode(new String( bytes, Constants.DEFAULT_ENCODING ), Constants.DEFAULT_ENCODING)); }catch( UnsupportedEncodingException e ){ throw( new TOTorrentException( "TOTorrentXMLSerialiser: unsupported encoding for '" + new String(bytes) + "'", TOTorrentException.RT_UNSUPPORTED_ENCODING)); } */ } protected String getUTF( byte[] bytes ) { try{ return( new String(bytes,Constants.DEFAULT_ENCODING)); }catch( UnsupportedEncodingException e ){ Debug.printStackTrace( e ); return( "" ); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/html/0000755000175000017500000000000011310377634020141 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/html/HTMLTableRow.java0000644000175000017500000000213610373051016023201 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.html; /** * @author parg * */ public interface HTMLTableRow extends HTMLChunk { public HTMLTableCell[] getCells(); } azureus-4.3.0.6/org/gudy/azureus2/core3/html/HTMLException.java0000644000175000017500000000221611012742270023417 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.html; /** * @author parg * */ public class HTMLException extends Exception { public HTMLException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/html/impl/0000755000175000017500000000000011310377634021102 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/html/impl/HTMLTableCellImpl.java0000644000175000017500000000252410373051040025072 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.html.impl; /** * @author parg * */ import org.gudy.azureus2.core3.html.*; public class HTMLTableCellImpl extends HTMLChunkImpl implements HTMLTableCell { String raw_content; protected HTMLTableCellImpl( String str ) { raw_content = str; int pos = str.indexOf(">"); String content = str.substring( pos+1 ); setContent( content ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/html/impl/HTMLChunkImpl.java0000644000175000017500000001174111166774656024346 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.html.impl; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.core3.html.*; import org.gudy.azureus2.core3.internat.MessageText; public class HTMLChunkImpl { String content; protected HTMLChunkImpl() { } protected HTMLChunkImpl( String _content ) { content = _content; } protected void setContent( String str ) { content = str; } public String[] getLinks() { int pos = 0; List res = new ArrayList(); while(true){ int p1 = content.indexOf( "<", pos ); if ( p1 == -1 ){ break; } p1++; int p2 = content.indexOf( ">", p1 ); if ( p2 == -1 ){ break; } pos = p2; String tag = content.substring( p1, p2 ).trim(); String lc_tag = tag.toLowerCase( MessageText.LOCALE_ENGLISH ); if ( lc_tag.startsWith("a " )){ int hr_start = lc_tag.indexOf( "href"); if ( hr_start == -1 ){ continue; } hr_start = lc_tag.indexOf("=", hr_start); if ( hr_start == -1 ){ continue; } hr_start += 1; while( hr_start < lc_tag.length() && Character.isWhitespace(lc_tag.charAt(hr_start))){ hr_start++; } int hr_end = hr_start; while( hr_end < lc_tag.length() && !Character.isWhitespace(lc_tag.charAt(hr_end))){ hr_end++; } String href = tag.substring(hr_start, hr_end ).trim(); if ( href.startsWith("\"")){ href = href.substring(1,href.length()-1); } res.add( href ); } } String[] res_array = new String[res.size()]; res.toArray( res_array ); return( res_array ); } public HTMLTable[] getTables() { String[] tables = getTagPairContent( "table" ); HTMLTable[] res = new HTMLTable[tables.length]; for (int i=0;i", p1 ); if ( p2 == -1 ){ break; } res.add( content.substring( p1+1, p2 )); pos = p2+1; } String[] x = new String[res.size()]; res.toArray( x ); return( x ); } public String[] getTagPairContent( String tag_name ) { tag_name = tag_name.toLowerCase( MessageText.LOCALE_ENGLISH ); String lc_content = content.toLowerCase( MessageText.LOCALE_ENGLISH ); int pos = 0; List res = new ArrayList(); int level = 0; int start_pos = -1; while(true){ int start_tag_start = lc_content.indexOf( "<" + tag_name, pos ); int end_tag_start = lc_content.indexOf( ""; String[] tags = getTags( "META" ); for (int i=0;i", url_start ); if ( e1 != -1 ){ e2 = e1; try{ return( new URL(tag.substring(url_start, e2).trim())); }catch( MalformedURLException e ){ Debug.printStackTrace( e ); } } } } return( null ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/html/HTMLPage.java0000644000175000017500000000215510373051016022337 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.html; /** * @author parg * */ import java.net.URL; public interface HTMLPage extends HTMLChunk { public URL getMetaRefreshURL(); } azureus-4.3.0.6/org/gudy/azureus2/core3/html/HTMLTable.java0000644000175000017500000000213210373051016022505 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.html; /** * @author parg * */ public interface HTMLTable extends HTMLChunk { public HTMLTableRow[] getRows(); } azureus-4.3.0.6/org/gudy/azureus2/core3/html/HTMLPageFactory.java0000644000175000017500000000331211106717752023676 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.html; /** * @author parg * */ import java.io.*; import org.gudy.azureus2.core3.html.impl.*; public class HTMLPageFactory { public static HTMLPage loadPage( InputStream is ) throws HTMLException { return( loadPage( is, true )); } public static HTMLPage loadPage( InputStream is, String charset ) throws HTMLException { return( loadPage( is, charset, true )); } public static HTMLPage loadPage( InputStream is, boolean close_file ) throws HTMLException { return(loadPage( is, null, close_file )); } public static HTMLPage loadPage( InputStream is, String charset, boolean close_file ) throws HTMLException { return( new HTMLPageImpl( is, charset, close_file )); } } azureus-4.3.0.6/org/gudy/azureus2/core3/html/HTMLChunk.java0000644000175000017500000000220510373051016022527 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.html; /** * @author parg * */ public interface HTMLChunk { public String getContent(); public HTMLTable[] getTables(); public String[] getLinks(); } azureus-4.3.0.6/org/gudy/azureus2/core3/html/HTMLTableCell.java0000644000175000017500000000213010373051016023303 0ustar adrianadrian/* * Created on 27-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.html; /** * @author parg * */ public interface HTMLTableCell extends HTMLChunk { public String getContent(); } azureus-4.3.0.6/org/gudy/azureus2/core3/html/HTMLUtils.java0000644000175000017500000002074711166774660022614 0ustar adrianadrian/* * Created on 30-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.html; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.xml.util.XUXmlWriter; /** * @author parg * */ public class HTMLUtils { /** * returns a list of strings for each line in a basic text representation * @param indent * @param text * @return */ public static List convertHTMLToText( String indent, String text ) { int pos = 0; text = text.replaceAll("

        ",""); text = text.replaceAll("
      ",""); text = text.replaceAll("
        ",""); text = text.replaceAll("
      ",""); text = text.replaceAll("",""); text = text.replaceAll("
    1. ","\n\t*"); String lc_text = text.toLowerCase( MessageText.LOCALE_ENGLISH ); List lines = new ArrayList(); while( true ){ String line; String[] tokens = new String[]{ "
      ", "

      " }; String token = null; int p1 = -1; for (int i=0;i", p1 ); if ( p2 == -1 ){ res += content.substring(pos); break; } String tag = content.substring(p1+1,p2).toLowerCase( MessageText.LOCALE_ENGLISH ); res += content.substring(pos,p1); if ( tag.equals("p") || tag.equals("br")){ if ( res.length() > 0 && res.charAt(res.length()-1) != '\n' ){ res += "\n"; } } pos = p2+1; } res = res.replaceAll( "[ \\t\\x0B\\f\\r]+", " " ); res = res.replaceAll( "[ \\t\\x0B\\f\\r]+\\n", "\n" ); res = res.replaceAll( "\\n[ \\t\\x0B\\f\\r]+", "\n" ); if ( res.length() > 0 && Character.isWhitespace(res.charAt(0))){ res = res.substring(1); } return( res ); } public static String splitWithLineLength( String str, int length ) { String res = ""; StringTokenizer tok = new StringTokenizer(str, "\n"); while( tok.hasMoreTokens()){ String line = tok.nextToken(); while( line.length() > length ){ if ( res.length() > 0 ){ res += "\n"; } boolean done = false; for (int i=length-1;i>=0;i--){ if ( Character.isWhitespace( line.charAt(i))){ done = true; res += line.substring(0,i); line = line.substring(i+1); break; } } if ( !done ){ res += line.substring(0,length); line = line.substring( length ); } } if ( res.length() > 0 && line.length() > 0 ){ res += "\n"; res += line; } } return( res ); } public static String removeTagPairs( String content, String tag_name ) { tag_name = tag_name.toLowerCase( MessageText.LOCALE_ENGLISH ); String lc_content = content.toLowerCase( MessageText.LOCALE_ENGLISH ); int pos = 0; String res = ""; int level = 0; int start_pos = -1; while(true){ int start_tag_start = lc_content.indexOf( "<" + tag_name, pos ); int end_tag_start = lc_content.indexOf( "', end_tag_start ); if( end_end == -1 ){ break; } pos = end_end + 1; }else{ if ( start_tag_start == -1 ){ res += content.substring(pos); break; } level++; pos = start_tag_start+1; } } } return( res ); } public static Object[] getLinks( String content_in ) { int pos = 0; List urls = new ArrayList(); String content_out = ""; String current_url = null; int current_url_start = -1; while(true){ int p1 = content_in.indexOf( "<", pos ); if ( p1 == -1 ){ break; } p1++; int p2 = content_in.indexOf( ">", p1 ); if ( p2 == -1 ){ break; } if ( p1 > pos ){ content_out += content_in.substring( pos, p1-1 ); } pos = p2+1; String tag = content_in.substring( p1, p2 ).trim(); String lc_tag = tag.toLowerCase( MessageText.LOCALE_ENGLISH ); if ( lc_tag.startsWith("a " )){ int hr_start = lc_tag.indexOf( "href"); if ( hr_start == -1 ){ continue; } hr_start = lc_tag.indexOf("=", hr_start); if ( hr_start == -1 ){ continue; } hr_start += 1; while( hr_start < lc_tag.length() && Character.isWhitespace(lc_tag.charAt(hr_start))){ hr_start++; } int hr_end = lc_tag.length()-1; while( hr_end >= lc_tag.length() && Character.isWhitespace(lc_tag.charAt(hr_end))){ hr_end--; } String href = tag.substring(hr_start, hr_end+1 ).trim(); if ( href.startsWith("\"")){ href = href.substring(1,href.length()-1); } current_url = href; current_url_start = content_out.length(); }else if ( lc_tag.startsWith( "/" ) && lc_tag.substring(1).trim().equals( "a" )){ if ( current_url != null ){ int len = content_out.length() - current_url_start; urls.add( new Object[]{ current_url, new int[]{ current_url_start, len }}); } current_url = null; } } if ( pos < content_in.length()){ content_out += content_in.substring( pos ); } return( new Object[]{ content_out, urls }); } public static String expand( String str ) { str = XUXmlWriter.unescapeXML( str ); str = str.replaceAll( " ", " " ); return( str ); } public static void main( String[] args ) { Object[] obj = getLinks( "aaaaaaa link< / a > prute klink" ); System.out.println( obj[0] ); List urls = (List)obj[1]; for (int i=0;i managers_cow = new ArrayList(); private AEMonitor managers_mon = new AEMonitor( "GM:Managers" ); private Map manager_map = new HashMap(); private GlobalMangerProgressListener progress_listener; private Checker checker; private GlobalManagerStatsImpl stats; private long last_swarm_stats_calc_time = 0; private long last_swarm_stats = 0; // Set this flag to disable interaction with downloads.config. // Do *NOT* change this - only the constructor should set it once. private boolean cripple_downloads_config; private TRTrackerScraper trackerScraper; private GlobalManagerStatsWriter stats_writer; private GlobalManagerHostSupport host_support; private Map saved_download_manager_state = new HashMap(); private int next_seed_piece_recheck_index; private TorrentFolderWatcher torrent_folder_watcher; private ArrayList paused_list = new ArrayList(); private final AEMonitor paused_list_mon = new AEMonitor( "GlobalManager:PL" ); /* Whether the GlobalManager is active (false) or stopped (true) */ private volatile boolean isStopping; private volatile boolean destroyed; private volatile boolean needsSaving = false; private boolean seeding_only_mode = false; private boolean potentially_seeding_only_mode = false; private FrequencyLimitedDispatcher check_seeding_only_state_dispatcher = new FrequencyLimitedDispatcher( new AERunnable(){ public void runSupport(){ checkSeedingOnlyStateSupport(); }}, 5000 ); private boolean force_start_non_seed_exists; private int nat_status = ConnectionManager.NAT_UNKNOWN; private boolean nat_status_probably_ok; private CopyOnWriteList dm_adapters = new CopyOnWriteList(); /** delay loading of torrents */ DelayedEvent loadTorrentsDelay = null; /** Whether loading of existing torrents is done */ boolean loadingComplete = false; /** Monitor to block adding torrents while loading existing torrent list */ AESemaphore loadingSem = new AESemaphore("Loading Torrents"); AEMonitor addingDM_monitor = new AEMonitor("addingDM"); /** List of torrents being added, but not added to the GM list yet */ List addingDMs = new ArrayList(); private MainlineDHTProvider provider = null; public class Checker extends AEThread { int loopFactor; private static final int waitTime = 10*1000; // 5 minutes save resume data interval (default) private int saveResumeLoopCount = 5*60*1000 / waitTime; private int initSaveResumeLoopCount = 60*1000 / waitTime; private int natCheckLoopCount = 30*1000 / waitTime; private int seedPieceCheckCount = 30*1000 / waitTime; private AESemaphore run_sem = new AESemaphore( "GM:Checker:run"); public Checker() { super("Global Status Checker"); loopFactor = 0; setPriority(Thread.MIN_PRIORITY); //determineSaveResumeDataInterval(); } private void determineSaveResumeDataInterval() { int saveResumeInterval = COConfigurationManager.getIntParameter("Save Resume Interval", 5); if (saveResumeInterval >= 1 && saveResumeInterval <= 90) saveResumeLoopCount = saveResumeInterval * 60000 / waitTime; } public void runSupport() { while ( true ){ try{ loopFactor++; determineSaveResumeDataInterval(); if ( ( loopFactor % saveResumeLoopCount == 0 ) || ( needsSaving && loadingComplete && loopFactor > initSaveResumeLoopCount )) { saveDownloads( true ); } if ((loopFactor % natCheckLoopCount == 0)) { computeNATStatus(); // we need this periodic check to pick up on DND file state changes (someone changes // a file from DND to normal and consequentially changes to a non-seeding mode). // Doing this via listeners is too much effort checkSeedingOnlyState(); // double check consistency checkForceStart( false ); } if ((loopFactor % seedPieceCheckCount == 0)) { seedPieceRecheck(); } for (Iterator it=managers_cow.iterator();it.hasNext();) { DownloadManager manager = (DownloadManager)it.next(); if ( loopFactor % saveResumeLoopCount == 0 ) { manager.saveResumeData(); } /* * seeding rules have been moved to StartStopRulesDefaultPlugin */ } }catch( Throwable e ){ Debug.printStackTrace( e ); } try { run_sem.reserve(waitTime); if ( run_sem.isReleasedForever()){ break; } } catch (Exception e) { Debug.printStackTrace( e ); } } } public void stopIt() { run_sem.releaseForever(); } } public GlobalManagerImpl( AzureusCore core, GlobalMangerProgressListener listener, long existingTorrentLoadDelay) { //Debug.dumpThreadsLoop("Active threads"); progress_listener = listener; this.cripple_downloads_config = "1".equals(System.getProperty("azureus.disabledownloads")); AEDiagnostics.addEvidenceGenerator( this ); stats = new GlobalManagerStatsImpl( this ); try{ stats_writer = new GlobalManagerStatsWriter( core ); }catch( Throwable e ){ Logger.log(new LogEvent(LOGID, "Stats unavailable", e )); } // Wait at least a few seconds before loading existing torrents. // typically the UI will call loadExistingTorrents before this runs // This is here in case the UI is stupid or forgets if (existingTorrentLoadDelay > 0) { loadTorrentsDelay = new DelayedEvent("GM:tld", existingTorrentLoadDelay, new AERunnable() { public void runSupport() { loadExistingTorrentsNow(false); // already async } }); } else { // run sync loadDownloads(); } if (progress_listener != null){ progress_listener.reportCurrentTask(MessageText.getString("splash.initializeGM")); } // Initialize scraper after loadDownloads so that we can merge scrapes // into one request per tracker trackerScraper = TRTrackerScraperFactory.getSingleton(); trackerScraper.setClientResolver( new TRTrackerScraperClientResolver() { public int getStatus( HashWrapper torrent_hash ) { DownloadManager dm = getDownloadManager(torrent_hash); if ( dm == null ){ return( TRTrackerScraperClientResolver.ST_NOT_FOUND ); } int dm_state = dm.getState(); if ( dm_state == DownloadManager.STATE_QUEUED ){ return( TRTrackerScraperClientResolver.ST_QUEUED ); }else if ( dm_state == DownloadManager.STATE_DOWNLOADING || dm_state == DownloadManager.STATE_SEEDING ){ return( TRTrackerScraperClientResolver.ST_RUNNING ); } return( TRTrackerScraperClientResolver.ST_OTHER ); } public boolean isNetworkEnabled( HashWrapper hash, URL url ) { DownloadManager dm = getDownloadManager(hash); if ( dm == null ){ return( false ); } String nw = AENetworkClassifier.categoriseAddress( url.getHost()); String[] networks = dm.getDownloadState().getNetworks(); for (int i=0;i>32)&0x00ffffff); int leechers = (int)(cache&0x00ffffff); return( new int[]{ seeds, leechers }); } } public Object[] getExtensions( HashWrapper hash ) { DownloadManager dm = getDownloadManager(hash); Character state; String ext; if ( dm == null ){ ext = ""; state = TRTrackerScraperClientResolver.FL_NONE; }else{ ext = dm.getDownloadState().getTrackerClientExtensions(); if ( ext == null ){ ext = ""; } boolean comp = dm.isDownloadComplete( false ); int dm_state = dm.getState(); // treat anything not stopped or running as queued as we need to be "optimistic" // for torrents at the start-of-day if ( dm_state == DownloadManager.STATE_ERROR || dm_state == DownloadManager.STATE_STOPPED || ( dm_state == DownloadManager.STATE_STOPPING && dm.getSubState() != DownloadManager.STATE_QUEUED )){ state = comp?TRTrackerScraperClientResolver.FL_COMPLETE_STOPPED:TRTrackerScraperClientResolver.FL_INCOMPLETE_STOPPED; }else if ( dm_state == DownloadManager.STATE_DOWNLOADING || dm_state == DownloadManager.STATE_SEEDING ){ state = comp?TRTrackerScraperClientResolver.FL_COMPLETE_RUNNING:TRTrackerScraperClientResolver.FL_INCOMPLETE_RUNNING; }else{ state = comp?TRTrackerScraperClientResolver.FL_COMPLETE_QUEUED:TRTrackerScraperClientResolver.FL_INCOMPLETE_QUEUED; } } return( new Object[]{ ext, state }); } public boolean redirectTrackerUrl( HashWrapper hash, URL old_url, URL new_url ) { DownloadManager dm = getDownloadManager(hash); if ( dm == null || dm.getTorrent() == null ){ return( false ); } return( TorrentUtils.replaceAnnounceURL( dm.getTorrent(), old_url, new_url )); } }); trackerScraper.addListener( new TRTrackerScraperListener() { public void scrapeReceived(TRTrackerScraperResponse response) { HashWrapper hash = response.getHash(); DownloadManager manager = (DownloadManager)manager_map.get( hash ); if ( manager != null ) { manager.setTrackerScrapeResponse( response ); } } }); try{ host_support = new GlobalManagerHostSupport( this ); }catch( Throwable e ){ Logger.log(new LogEvent(LOGID, "Hosting unavailable", e)); } checker = new Checker(); checker.start(); torrent_folder_watcher = new TorrentFolderWatcher( this ); TRTrackerUtils.addListener( new TRTrackerUtilsListener() { public void announceDetailsChanged() { Logger.log( new LogEvent(LOGID, "Announce details have changed, updating trackers" )); List managers = managers_cow; for (int i=0;i managers = sortForStop(); int nbDownloads = managers.size(); for ( int i=0;i 100) { lastListenerUpdate = now; int currentDownload = i+1; progress_listener.reportPercent(100 * currentDownload / nbDownloads); progress_listener.reportCurrentTask(MessageText.getString("splash.unloadingTorrent") + " " + currentDownload + " " + MessageText.getString("splash.of") + " " + nbDownloads + " : " + manager.getTorrentFileName()); } int state = manager.getState(); if( state != DownloadManager.STATE_STOPPED && state != DownloadManager.STATE_STOPPING ) { manager.stopIt( for_close?DownloadManager.STATE_CLOSED:DownloadManager.STATE_STOPPED, false, false ); } } } /** * Starts all downloads */ public void startAllDownloads() { for (Iterator iter = managers_cow.iterator(); iter.hasNext();) { DownloadManager manager = (DownloadManager) iter.next(); if ( manager.getState() == DownloadManager.STATE_STOPPED ){ manager.stopIt( DownloadManager.STATE_QUEUED, false, false ); } } } public boolean pauseDownload( DownloadManager manager ) { if ( manager.getTorrent() == null ) { return( false ); } int state = manager.getState(); if ( state != DownloadManager.STATE_STOPPED && state != DownloadManager.STATE_ERROR && state != DownloadManager.STATE_STOPPING ) { try{ HashWrapper wrapper = manager.getTorrent().getHashWrapper(); boolean forced = manager.isForceStart(); // add first so anyone picking up the ->stopped transition see it is paused try{ paused_list_mon.enter(); paused_list.add( new Object[]{wrapper, new Boolean(forced)}); }finally{ paused_list_mon.exit(); } manager.stopIt( DownloadManager.STATE_STOPPED, false, false ); return( true ); }catch( TOTorrentException e ){ Debug.printStackTrace( e ); } } return( false ); } public void pauseDownloads() { pauseDownloads( false ); } protected void pauseDownloads( boolean tag_only ) { List managers = sortForStop(); for( DownloadManager manager: managers ){ if ( manager.getTorrent() == null ) { continue; } int state = manager.getState(); if( state != DownloadManager.STATE_STOPPED && state != DownloadManager.STATE_ERROR && state != DownloadManager.STATE_STOPPING ) { try { boolean forced = manager.isForceStart(); // add before stopping so anyone picking up the ->stopped transition sees that it is // paused try { paused_list_mon.enter(); paused_list.add( new Object[]{ manager.getTorrent().getHashWrapper(), new Boolean(forced)}); }finally{ paused_list_mon.exit(); } if ( !tag_only ){ manager.stopIt( DownloadManager.STATE_STOPPED, false, false ); } }catch( TOTorrentException e ) { Debug.printStackTrace( e ); } } } } public boolean canPauseDownload( DownloadManager manager ) { if( manager.getTorrent() == null ) { return( false ); } int state = manager.getState(); if( state != DownloadManager.STATE_STOPPED && state != DownloadManager.STATE_ERROR && state != DownloadManager.STATE_STOPPING ) { return( true ); } return false; } public boolean isPaused( DownloadManager manager ) { if ( paused_list.size() == 0 ){ return( false ); } try { paused_list_mon.enter(); for( int i=0; i < paused_list.size(); i++ ) { Object[] data = (Object[])paused_list.get(i); HashWrapper hash = (HashWrapper)data[0]; DownloadManager this_manager = getDownloadManager( hash ); if ( this_manager == manager ){ return( true ); } } return( false ); }finally{ paused_list_mon.exit(); } } public boolean canPauseDownloads() { for( Iterator i = managers_cow.iterator(); i.hasNext(); ) { DownloadManager manager = (DownloadManager)i.next(); if ( canPauseDownload( manager )){ return( true ); } } return false; } public void resumeDownload( DownloadManager manager ) { boolean resume_ok = false; boolean force = false; try { paused_list_mon.enter(); for( int i=0; i < paused_list.size(); i++ ) { Object[] data = (Object[])paused_list.get(i); HashWrapper hash = (HashWrapper)data[0]; force = ((Boolean)data[1]).booleanValue(); DownloadManager this_manager = getDownloadManager( hash ); if ( this_manager == manager ){ resume_ok = true; paused_list.remove(i); break; } } }finally{ paused_list_mon.exit(); } if ( resume_ok ){ if ( manager.getState() == DownloadManager.STATE_STOPPED ) { if ( force ){ manager.setForceStart(true); }else{ manager.stopIt( DownloadManager.STATE_QUEUED, false, false ); } } } } public void resumeDownloads() { try { paused_list_mon.enter(); for( int i=0; i < paused_list.size(); i++ ) { Object[] data = (Object[])paused_list.get(i); HashWrapper hash = (HashWrapper)data[0]; boolean force = ((Boolean)data[1]).booleanValue(); DownloadManager manager = getDownloadManager( hash ); if( manager != null && manager.getState() == DownloadManager.STATE_STOPPED ) { if ( force ){ manager.setForceStart(true); }else{ manager.stopIt( DownloadManager.STATE_QUEUED, false, false ); } } } paused_list.clear(); } finally { paused_list_mon.exit(); } } public boolean canResumeDownloads() { try { paused_list_mon.enter(); for( int i=0; i < paused_list.size(); i++ ) { Object[] data = (Object[])paused_list.get(i); HashWrapper hash = (HashWrapper)data[0]; DownloadManager manager = getDownloadManager( hash ); if( manager != null && manager.getState() == DownloadManager.STATE_STOPPED ) { return true; } } } finally { paused_list_mon.exit(); } return false; } private List sortForStop() { List managers = new ArrayList( managers_cow ); Collections.sort( managers, new Comparator() { public int compare( DownloadManager o1, DownloadManager o2) { int s1 = o1.getState(); int s2 = o2.getState(); if ( s2 == DownloadManager.STATE_QUEUED ){ return( 1 ); }else if ( s1 == DownloadManager.STATE_QUEUED ){ return( -1 ); } return( 0 ); } }); return( managers ); } private void loadDownloads() { if (this.cripple_downloads_config) { loadingComplete = true; loadingSem.releaseForever(); return; } try{ DownloadManagerStateFactory.loadGlobalStateCache(); int triggerOnCount = 2; ArrayList downloadsAdded = new ArrayList(); long lastListenerUpdate = 0; try{ if (progress_listener != null){ progress_listener.reportCurrentTask(MessageText.getString("splash.loadingTorrents")); } Map map = FileUtil.readResilientConfigFile("downloads.config"); boolean debug = Boolean.getBoolean("debug"); Iterator iter = null; //v2.0.3.0+ vs older mode List downloads = (List) map.get("downloads"); int nbDownloads; if (downloads == null) { //No downloads entry, then use the old way iter = map.values().iterator(); nbDownloads = map.size(); } else { //New way, downloads stored in a list iter = downloads.iterator(); nbDownloads = downloads.size(); } int currentDownload = 0; while (iter.hasNext()) { currentDownload++; Map mDownload = (Map) iter.next(); try { byte[] torrent_hash = (byte[])mDownload.get( "torrent_hash" ); Long lPersistent = (Long)mDownload.get( "persistent" ); boolean persistent = lPersistent==null || lPersistent.longValue()==1; String fileName = new String((byte[]) mDownload.get("torrent"), Constants.DEFAULT_ENCODING); if(progress_listener != null && SystemTime.getCurrentTime() - lastListenerUpdate > 100) { lastListenerUpdate = SystemTime.getCurrentTime(); String shortFileName = fileName; try { File f = new File(fileName); shortFileName = f.getName(); } catch (Exception e) { // TODO: handle exception } progress_listener.reportPercent(100 * currentDownload / nbDownloads); progress_listener.reportCurrentTask(MessageText.getString("splash.loadingTorrent") + " " + currentDownload + " " + MessageText.getString("splash.of") + " " + nbDownloads + " : " + shortFileName ); } //migration from using a single savePath to a separate dir and file entry String torrent_save_dir; String torrent_save_file; byte[] torrent_save_dir_bytes = (byte[]) mDownload.get("save_dir"); if ( torrent_save_dir_bytes != null ){ byte[] torrent_save_file_bytes = (byte[]) mDownload.get("save_file"); torrent_save_dir = new String(torrent_save_dir_bytes, Constants.DEFAULT_ENCODING); if ( torrent_save_file_bytes != null ){ torrent_save_file = new String(torrent_save_file_bytes, Constants.DEFAULT_ENCODING); }else{ torrent_save_file = null; } }else{ byte[] savePathBytes = (byte[]) mDownload.get("path"); torrent_save_dir = new String(savePathBytes, Constants.DEFAULT_ENCODING); torrent_save_file = null; } int state = DownloadManager.STATE_WAITING; if (debug){ state = DownloadManager.STATE_STOPPED; }else { if (mDownload.containsKey("state")) { state = ((Long) mDownload.get("state")).intValue(); if (state != DownloadManager.STATE_STOPPED && state != DownloadManager.STATE_QUEUED && state != DownloadManager.STATE_WAITING) state = DownloadManager.STATE_QUEUED; }else{ int stopped = ((Long) mDownload.get("stopped")).intValue(); if (stopped == 1){ state = DownloadManager.STATE_STOPPED; } } } Long seconds_downloading = (Long)mDownload.get("secondsDownloading"); boolean has_ever_been_started = seconds_downloading != null && seconds_downloading.longValue() > 0; if (torrent_hash != null) { saved_download_manager_state.put(new HashWrapper(torrent_hash), mDownload); } // for non-persistent downloads the state will be picked up if the download is re-added // it won't get saved unless it is picked up, hence dead data is dropped as required if ( persistent ){ List file_priorities = (List) mDownload.get("file_priorities"); final DownloadManager dm = DownloadManagerFactory.create( this, torrent_hash, fileName, torrent_save_dir, torrent_save_file, state, true, true, has_ever_been_started, file_priorities ); if (addDownloadManager(dm, false, false) == dm) { downloadsAdded.add(dm); if (downloadsAdded.size() >= triggerOnCount) { triggerOnCount *= 2; triggerAddListener(downloadsAdded); downloadsAdded.clear(); } } } } catch (UnsupportedEncodingException e1) { //Do nothing and process next. } catch (Throwable e) { Logger.log(new LogEvent(LOGID, "Error while loading downloads. " + "One download may not have been added to the list.", e)); } } // This is set to true by default, but once the downloads have been loaded, we have no reason to ever // to do this check again - we only want to do it once to upgrade the state of existing downloads // created before this code was around. COConfigurationManager.setParameter("Set Completion Flag For Completed Downloads On Start", false); //load pause/resume state ArrayList pause_data = (ArrayList)map.get( "pause_data" ); if( pause_data != null ) { try { paused_list_mon.enter(); for( int i=0; i < pause_data.size(); i++ ) { Object pd = pause_data.get(i); byte[] key; boolean force; if ( pd instanceof byte[]){ // old style, migration purposes key = (byte[])pause_data.get( i ); force = false; }else{ Map m = (Map)pd; key = (byte[])m.get("hash"); force = ((Long)m.get("force")).intValue() == 1; } paused_list.add( new Object[]{ new HashWrapper( key ), new Boolean( force )} ); } } finally { paused_list_mon.exit(); } } // Someone could have mucked with the config file and set weird positions, // so fix them up. fixUpDownloadManagerPositions(); Logger.log(new LogEvent(LOGID, "Loaded " + managers_cow.size() + " torrents")); }catch( Throwable e ){ // there's been problems with corrupted download files stopping AZ from starting // added this to try and prevent such foolishness Debug.printStackTrace( e ); } finally { loadingComplete = true; triggerAddListener(downloadsAdded); loadingSem.releaseForever(); } }finally{ DownloadManagerStateFactory.discardGlobalStateCache(); } } private void triggerAddListener(List downloadsToAdd) { try { managers_mon.enter(); List listenersCopy = listeners.getListenersCopy(); for (int j = 0; j < listenersCopy.size(); j++) { GlobalManagerListener gmListener = (GlobalManagerListener) listenersCopy.get(j); for (int i = 0; i < downloadsToAdd.size(); i++) { DownloadManager dm = (DownloadManager) downloadsToAdd.get(i); gmListener.downloadManagerAdded(dm); } } } finally { managers_mon.exit(); } } protected void saveDownloads( boolean immediate ) { if ( !immediate ){ needsSaving = true; return; } if (!loadingComplete) { needsSaving = true; return; } // if(Boolean.getBoolean("debug")) return; needsSaving = false; if (this.cripple_downloads_config) { return; } try{ managers_mon.enter(); Collections.sort(managers_cow, new Comparator () { public final int compare (Object a, Object b) { return ((DownloadManager) a).getPosition() - ((DownloadManager) b).getPosition(); } }); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Saving Download List (" + managers_cow.size() + " items)")); Map map = new HashMap(); List list = new ArrayList(managers_cow.size()); for (int i = 0; i < managers_cow.size(); i++) { DownloadManager dm = (DownloadManager) managers_cow.get(i); DownloadManagerStats dm_stats = dm.getStats(); Map dmMap = new HashMap(); TOTorrent torrent = dm.getTorrent(); if ( torrent != null ){ try{ dmMap.put( "torrent_hash", torrent.getHash()); }catch( TOTorrentException e ){ Debug.printStackTrace(e); } } File save_loc = dm.getAbsoluteSaveLocation(); dmMap.put("persistent", new Long(dm.isPersistent()?1:0)); dmMap.put("torrent", dm.getTorrentFileName()); dmMap.put("save_dir", save_loc.getParent()); dmMap.put("save_file", save_loc.getName()); dmMap.put("maxdl", new Long( dm_stats.getDownloadRateLimitBytesPerSecond() )); dmMap.put("maxul", new Long( dm_stats.getUploadRateLimitBytesPerSecond() )); int state = dm.getState(); if (state == DownloadManager.STATE_ERROR ){ // torrents in error state always come back stopped state = DownloadManager.STATE_STOPPED; }else if ( dm.getAssumedComplete() && !dm.isForceStart() && state != DownloadManager.STATE_STOPPED) { state = DownloadManager.STATE_QUEUED; }else if ( state != DownloadManager.STATE_STOPPED && state != DownloadManager.STATE_QUEUED && state != DownloadManager.STATE_WAITING){ state = DownloadManager.STATE_WAITING; } dmMap.put("state", new Long(state)); dmMap.put("position", new Long(dm.getPosition())); dmMap.put("downloaded", new Long(dm_stats.getTotalDataBytesReceived())); dmMap.put("uploaded", new Long(dm_stats.getTotalDataBytesSent())); dmMap.put("completed", new Long(dm_stats.getDownloadCompleted(true))); dmMap.put("discarded", new Long(dm_stats.getDiscarded())); dmMap.put("hashfailbytes", new Long(dm_stats.getHashFailBytes())); dmMap.put("forceStart", new Long(dm.isForceStart() && (dm.getState() != DownloadManager.STATE_CHECKING) ? 1 : 0)); dmMap.put("secondsDownloading", new Long(dm_stats.getSecondsDownloading())); dmMap.put("secondsOnlySeeding", new Long(dm_stats.getSecondsOnlySeeding())); // although this has been migrated, keep storing it to allow regression for a while dmMap.put("uploads", new Long(dm.getMaxUploads())); dmMap.put("creationTime", new Long( dm.getCreationTime())); //save file priorities dm.saveDownload(); List file_priorities = (List)dm.getData( "file_priorities" ); if ( file_priorities != null ) dmMap.put( "file_priorities" , file_priorities ); dmMap.put( "allocated", new Long( dm.isDataAlreadyAllocated() == true ? 1 : 0 ) ); list.add(dmMap); } map.put("downloads", list); //save pause/resume state try { paused_list_mon.enter(); if( !paused_list.isEmpty() ) { ArrayList pause_data = new ArrayList(); for( int i=0; i < paused_list.size(); i++ ) { Object[] data = (Object[])paused_list.get(i); HashWrapper hash = (HashWrapper)data[0]; Boolean force = (Boolean)data[1]; Map m = new HashMap(); m.put( "hash", hash.getHash()); m.put( "force", new Long(force.booleanValue()?1:0)); pause_data.add( m ); } map.put( "pause_data", pause_data ); } } finally { paused_list_mon.exit(); } FileUtil.writeResilientConfigFile("downloads.config", map ); }finally{ managers_mon.exit(); } } /** * @return */ public TRTrackerScraper getTrackerScraper() { return trackerScraper; } public GlobalManagerStats getStats() { return( stats ); } public boolean contains(DownloadManager manager) { if (managers_cow != null && manager != null) { return managers_cow.contains(manager); } return false; } public int getIndexOf(DownloadManager manager) { if (managers_cow != null && manager != null) return managers_cow.indexOf(manager); return -1; } public boolean isMoveableUp(DownloadManager manager) { if ((manager.isDownloadComplete(false)) && (COConfigurationManager.getIntParameter("StartStopManager_iRankType") != 0) && (COConfigurationManager.getBooleanParameter("StartStopManager_bAutoReposition"))) return false; return manager.getPosition() > 1; } public int downloadManagerCount(boolean bCompleted) { int numInGroup = 0; for (Iterator it = managers_cow.iterator();it.hasNext();) { DownloadManager dm = (DownloadManager)it.next(); if (dm.isDownloadComplete(false) == bCompleted) numInGroup++; } return numInGroup; } public boolean isMoveableDown(DownloadManager manager) { boolean isCompleted = manager.isDownloadComplete(false); if (isCompleted && (COConfigurationManager.getIntParameter("StartStopManager_iRankType") != 0) && (COConfigurationManager.getBooleanParameter("StartStopManager_bAutoReposition"))) return false; return manager.getPosition() < downloadManagerCount(isCompleted); } public void moveUp(DownloadManager manager) { moveTo(manager, manager.getPosition() - 1); } public void moveDown(DownloadManager manager) { moveTo(manager, manager.getPosition() + 1); } public void moveTop(DownloadManager[] manager) { try{ managers_mon.enter(); int newPosition = 1; for (int i = 0; i < manager.length; i++) moveTo(manager[i], newPosition++); }finally{ managers_mon.exit(); } } public void moveEnd(DownloadManager[] manager) { try{ managers_mon.enter(); int endPosComplete = 0; int endPosIncomplete = 0; for (int j = 0; j < managers_cow.size(); j++) { DownloadManager dm = (DownloadManager) managers_cow.get(j); if (dm.isDownloadComplete(false)) endPosComplete++; else endPosIncomplete++; } for (int i = manager.length - 1; i >= 0; i--) { if (manager[i].isDownloadComplete(false) && endPosComplete > 0) { moveTo(manager[i], endPosComplete--); } else if (endPosIncomplete > 0) { moveTo(manager[i], endPosIncomplete--); } } }finally{ managers_mon.exit(); } } public void moveTo(DownloadManager manager, int newPosition) { boolean curCompleted = manager.isDownloadComplete(false); if (newPosition < 1 || newPosition > downloadManagerCount(curCompleted)) return; try{ managers_mon.enter(); int curPosition = manager.getPosition(); if (newPosition > curPosition) { // move [manager] down // move everything between [curPosition+1] and [newPosition] up(-) 1 int numToMove = newPosition - curPosition; for (int i = 0; i < managers_cow.size(); i++) { DownloadManager dm = (DownloadManager) managers_cow.get(i); boolean dmCompleted = (dm.isDownloadComplete(false)); if (dmCompleted == curCompleted) { int dmPosition = dm.getPosition(); if ((dmPosition > curPosition) && (dmPosition <= newPosition)) { dm.setPosition(dmPosition - 1); numToMove--; if (numToMove <= 0) break; } } } manager.setPosition(newPosition); } else if (newPosition < curPosition && curPosition > 1) { // move [manager] up // move everything between [newPosition] and [curPosition-1] down(+) 1 int numToMove = curPosition - newPosition; for (int i = 0; i < managers_cow.size(); i++) { DownloadManager dm = (DownloadManager) managers_cow.get(i); boolean dmCompleted = (dm.isDownloadComplete(false)); int dmPosition = dm.getPosition(); if ((dmCompleted == curCompleted) && (dmPosition >= newPosition) && (dmPosition < curPosition) ) { dm.setPosition(dmPosition + 1); numToMove--; if (numToMove <= 0) break; } } manager.setPosition(newPosition); } }finally{ managers_mon.exit(); } } public void fixUpDownloadManagerPositions() { try{ managers_mon.enter(); int posComplete = 1; int posIncomplete = 1; Collections.sort(managers_cow, new Comparator () { public final int compare (Object a, Object b) { int i = ((DownloadManager)a).getPosition() - ((DownloadManager)b).getPosition(); if (i != 0) { return i; } // non persistent before persistent if (((DownloadManager)a).isPersistent()) { return 1; } else if (((DownloadManager)b).isPersistent()) { return -1; } return 0; } } ); for (int i = 0; i < managers_cow.size(); i++) { DownloadManager dm = (DownloadManager) managers_cow.get(i); if (dm.isDownloadComplete(false)) dm.setPosition(posComplete++); else dm.setPosition(posIncomplete++); } }finally{ managers_mon.exit(); } } protected void informDestroyed() { if ( destroyed ) { return; } destroyed = true; /* Thread t = new Thread("Azureus: destroy checker") { public void run() { long start = SystemTime.getCurrentTime(); while(true){ try{ Thread.sleep(2500); }catch( Throwable e ){ e.printStackTrace(); } if ( SystemTime.getCurrentTime() - start > 10000 ){ // java web start problem here... // Debug.dumpThreads("Azureus: slow stop - thread dump"); // Debug.killAWTThreads(); doesn't work } } } }; t.setDaemon(true); t.start(); */ listeners.dispatch( LDT_DESTROYED, null, true ); } public void informDestroyInitiated() { listeners.dispatch( LDT_DESTROY_INITIATED, null, true ); } public void addListener( GlobalManagerListener listener ) { addListener(listener, true); } public void addListener( GlobalManagerListener listener, boolean trigger ) { if ( isStopping ){ listener.destroyed(); }else{ listeners.addListener(listener); if (!trigger) { return; } // Don't use Dispatch.. async is bad (esp for plugin initialization) try{ managers_mon.enter(); List managers = managers_cow; for (int i=0;i" + force_start_non_seed_exists ); PeerControlSchedulerFactory.overrideWeightedPriorities( force_start_non_seed_exists ); } } protected void checkSeedingOnlyState() { check_seeding_only_state_dispatcher.dispatch(); } protected void checkSeedingOnlyStateSupport() { boolean seeding = false; boolean seeding_set = false; boolean potentially_seeding = false; List managers = managers_cow; for( int i=0; i < managers.size(); i++ ) { DownloadManager dm = (DownloadManager)managers.get( i ); PEPeerManager pm = dm.getPeerManager(); int state = dm.getState(); if ( dm.getDiskManager() == null || pm == null ){ // download not running if ( state == DownloadManager.STATE_QUEUED ){ if ( dm.isDownloadComplete( false )){ potentially_seeding = true; } else { // Queued and Incomplete means we aren't "only seeding". This // download WILL start, it just hasn't yet for various reasons // (1st Priority, etc) seeding = false; // can't break out, because we still need to calculate // potentially_seeding. Set a flag so we don't set "seeding" // back to true seeding_set = true; } } continue; } if ( state == DownloadManager.STATE_DOWNLOADING ){ if (!pm.hasDownloadablePiece()){ // complete DND file if (!seeding_set) { seeding = true; } }else{ seeding = false; potentially_seeding = false; break; } }else if ( state == DownloadManager.STATE_SEEDING ){ if (!seeding_set) { seeding = true; } } } if ( seeding ){ potentially_seeding = true; } setSeedingOnlyState( seeding, potentially_seeding ); } protected void setSeedingOnlyState( boolean seeding, boolean potentially_seeding ) { synchronized( this ){ if ( seeding != seeding_only_mode || potentially_seeding != potentially_seeding_only_mode ){ seeding_only_mode = seeding; potentially_seeding_only_mode = potentially_seeding; // System.out.println( "dispatching " + seeding_only_mode + "/" + potentially_seeding_only_mode ); listeners.dispatch( LDT_SEEDING_ONLY, new boolean[]{ seeding_only_mode, potentially_seeding_only_mode }); } } } public boolean isSeedingOnly() { return( seeding_only_mode ); } public boolean isPotentiallySeedingOnly() { return( potentially_seeding_only_mode ); } public long getTotalSwarmsPeerRate( boolean downloading, boolean seeding ) { long now = SystemTime.getCurrentTime(); if ( now < last_swarm_stats_calc_time || now - last_swarm_stats_calc_time >= 1000 ){ long total = 0; List managers = managers_cow; for (int i=0;i 0 ){ nat_status = ConnectionManager.NAT_OK; }else if ( num_probably_ok > 0 || nat_status_probably_ok ){ nat_status = ConnectionManager.NAT_PROBABLY_OK; nat_status_probably_ok = true; }else if ( num_bad > 0 ){ nat_status = ConnectionManager.NAT_BAD; }else{ nat_status = ConnectionManager.NAT_UNKNOWN; } } public int getNATStatus() { return( nat_status ); } protected void seedPieceRecheck() { List managers = managers_cow; if ( next_seed_piece_recheck_index >= managers.size()){ next_seed_piece_recheck_index = 0; } for (int i=next_seed_piece_recheck_index;i= managers.size()){ next_seed_piece_recheck_index = 0; } return; } } for (int i=0;i= managers.size()){ next_seed_piece_recheck_index = 0; } return; } } } protected boolean seedPieceRecheck( DownloadManager manager ) { if ( manager.getState() != DownloadManager.STATE_SEEDING ){ return( false ); } return( manager.seedPieceRecheck()); } protected DownloadManagerInitialisationAdapter getDMAdapter( DownloadManagerInitialisationAdapter adapter ) { List adapters = dm_adapters.getList(); if ( adapters.size() == 0 ){ return( adapter ); } if ( adapter != null ){ // musn't update the copy-on-write list adapters = new ArrayList( adapters ); adapters.add( adapter ); } if ( adapters.size() == 1 ){ return((DownloadManagerInitialisationAdapter)adapters.get(0)); } final List f_adapters = adapters; return( new DownloadManagerInitialisationAdapter() { public void initialised( DownloadManager manager ) { for (int i=0;i 0 && existing_ext == null ){ ext = FileUtil.convertOSSpecificChars( ext, false ); DiskManagerFileInfo[] fileInfos = manager.getDiskManagerFileInfo(); try{ state.suppressStateSave(true); for ( int i=0; i * May return an existing DownloadManager if torrent was already * in GlobalManager. */ public DownloadManager addDownloadManager(String file_name, String save_path); /** * Create and add a Download Manager to the global list * * @param fileName location and name of torrent file * @param savePath path to write the data to * @param initialState Initial state of download. See DownloadManager.STATE_* * @param persistent Whether the download should be treated as persistent download * * @return The Downloadmanger based on the supplied information.
      * May return an existing DownloadManager if torrent was already * in GlobalManager. */ public DownloadManager addDownloadManager(String fileName, byte[] optionalHash, String savePath, int initialState, boolean persistent); /** * Create and add a Download Manager to the global list * * @param fileName location and name of torrent file * @param savePath path to write the data to * @param safeFile subdirectory or filename to write the data to * @param initialState Initial state of download. See DownloadManager.STATE_* * @param persistent Whether the download should be treated as persistent download * @param for_seeding Whether the manager should assume the torrent is * already complete and ready for seeding. * * @return The Downloadmanger based on the supplied information.
      * May return an existing DownloadManager if torrent was already * in GlobalManager. */ public DownloadManager addDownloadManager(String fileName, byte[] optionalHash, String savePath, String saveFile, int initialState, boolean persistent, boolean for_seeding, DownloadManagerInitialisationAdapter adapter ); /** * Create and add a Download Manager to the global list * * @param fileName location and name of torrent file * @param savePath path to write the data to * @param initialState Initial state of download. See DownloadManager.STATE_* * @param persistent Whether the download should be treated as persistent download * @param for_seeding Whether the manager should assume the torrent is * already complete and ready for seeding. * * @return The Downloadmanger based on the supplied information.
      * May return an existing DownloadManager if torrent was already * in GlobalManager. */ public DownloadManager addDownloadManager(String fileName, byte[] optionalHash, String savePath, int initialState, boolean persistent, boolean for_seeding, DownloadManagerInitialisationAdapter adapter ); /** * Removes a DownloadManager from the global list, providing it can be * removed (see {@link #canDownloadManagerBeRemoved(DownloadManager)}) *

      * The DownloadManager will not be stopped if it is running. Scraping, * however, will be turned off. * * @param dm DownloadManager to remove * * @throws GlobalManagerDownloadRemovalVetoException */ public void removeDownloadManager(DownloadManager dm) throws GlobalManagerDownloadRemovalVetoException; /** * Determines whether a DownloadManager can be removed * * @param dm DownloadManager to check * @throws GlobalManagerDownloadRemovalVetoException */ public void canDownloadManagerBeRemoved(DownloadManager dm, boolean remove_torrent, boolean remove_data) throws GlobalManagerDownloadRemovalVetoException; /** * Retrieve a list of {@link DownloadManager}s that GlobalManager is handling * @return a list of {@link DownloadManager}s */ public List getDownloadManagers(); /** * Retrieve the DownloadManager associated with a TOTorrent object * * @param torrent Torrent to search for * @return The DownloadManager associted with the TOTOrrent, or null if * none found */ public DownloadManager getDownloadManager(TOTorrent torrent); /** * Retrieve the DownloadManager associated with a hash * * @param hash Hash to search for * @return The DownloadManager associted with the hash, or null if * none found */ public DownloadManager getDownloadManager(HashWrapper hash); /** * Retrieve the Tracker Scraper management class * * @return Tracker Scraper management class */ public TRTrackerScraper getTrackerScraper(); /** * Retrieve the Global Manager Statistics class * * @return the Global Manager Statistics class */ public GlobalManagerStats getStats(); /** * Puts GlobalManager in a stopped state.
      * Used when closing down Azureus. */ public void stopGlobalManager(); /** * Stops all downloads without removing them * * @author Rene Leonhardt */ public void stopAllDownloads(); /** * Starts all downloads */ public void startAllDownloads(); /** * Pauses (stops) all running downloads/seedings. */ public void pauseDownloads(); /** * Indicates whether or not there are any downloads that can be paused. * @return true if there is at least one download to pause, false if none */ public boolean canPauseDownloads(); /** * Resumes (starts) all downloads paused by the previous pauseDownloads call. */ public void resumeDownloads(); /** * Indicates whether or not there are any paused downloads to resume. * @return true if there is at least one download to resume, false if none. */ public boolean canResumeDownloads(); /** * Pause one DownloadManager * @param dm DownloadManager to pause * @return False if DownloadManager was invalid, stopped, or pause failed */ public boolean pauseDownload(DownloadManager dm); /** * Resume a previously paused DownloadManager * @param dm DownloadManager to resume */ public void resumeDownload(DownloadManager dm); /** * Retrieve whether a DownloadManager is in a paused state * * @param dm DownloadManager to query * @return the pause state */ public boolean isPaused(DownloadManager dm); /** * Determines whether we are only seeding, and not currently downloading * anything. * * @return Seeding Only State */ public boolean isSeedingOnly(); /** * As for isSeedingOnly but includes queued seeds * @return */ public boolean isPotentiallySeedingOnly(); /** * Retrieve the index of a DownloadManager within the GlobalManager * list retrieved via {@link #getDownloadManagers()}. *

      * This is NOT the DownloadManager's position * * @param dm DownloadManger to find the index of * @return index, -1 if not in list * * @deprecated Should not be used, as indexes may be different than * when getDownloadManagers() was called. */ public int getIndexOf(DownloadManager dm); /** * Retrieve the number of download managers the global manager is managing. * * @param bCompleted True: Return count of completed downloads
      * False: Return count of incomplete downloads * @return count */ public int downloadManagerCount(boolean bCompleted); /** * Retrieve whether a DownloadManager can move down in the GlobalManager list * @param dm DownloadManager to check * @return True - Can move down */ public boolean isMoveableDown(DownloadManager dm); /** * Retrieve whether a DownloadManager can move up in the GlobalManager list * @param dm DownloadManager to check * @return True - Can move up */ public boolean isMoveableUp(DownloadManager dm); /** * Move a list of DownloadManagers to the top of the GlobalManager list * * @param dm array list of DownloadManager objects to move */ public void moveTop(DownloadManager[] dm); /** * Move one DownloadManager up in the GlobalManager's list * @param dm DownloadManager to move up */ public void moveUp(DownloadManager dm); /** * Move one DownloadManager down in the GlobalManager's list * @param dm DownloadManager to move down */ public void moveDown(DownloadManager dm); /** * Move a list of DownloadManagers to the end of the GlobalManager list * * @param dm array list of DownloadManager objects to move */ public void moveEnd(DownloadManager[] dm); /** * Move a Downloadmanager to a new position. * * @param manager DownloadManager to move * @param newPosition position to place */ public void moveTo(DownloadManager manager, int newPosition); /** * Verifies the positions of the DownloadManagers, * filling in gaps and shifting duplicate IDs down if necessary. *

      * This does not need to be called after MoveXXX, addDownloadManager, or * removeDownloadManager functions. */ public void fixUpDownloadManagerPositions(); /** * Add a Global Manager listener * @param l Listener to add */ public void addListener(GlobalManagerListener l); /** * Removes a Global Manager listener * @param l Listener to remove */ public void removeListener(GlobalManagerListener l); /** * Add a listener triggered when Download is about to be removed * @param l Listener to add */ public void addDownloadWillBeRemovedListener( GlobalManagerDownloadWillBeRemovedListener l); /** * Remove a listener triggered when Download is about to be removed * @param l Listener to remove */ public void removeDownloadWillBeRemovedListener( GlobalManagerDownloadWillBeRemovedListener l); /** * See plugin ConnectionManager.NAT_ constants for return values * @return ConnectionManager.NAT_* */ public int getNATStatus(); /** * Any adapters added will get a chance to see/set the initial state of downloads as they are * added * @param adapter */ public void addDownloadManagerInitialisationAdapter( DownloadManagerInitialisationAdapter adapter ); public void removeDownloadManagerInitialisationAdapter( DownloadManagerInitialisationAdapter adapter ); /** * @param listener */ public void loadExistingTorrentsNow(boolean async); /** * @param listener * @param trigger */ void addListener(GlobalManagerListener listener, boolean trigger); /** * @param manager * @param remove_torrent * @param remove_data * @throws GlobalManagerDownloadRemovalVetoException * * @since 3.0.1.7 */ void removeDownloadManager(DownloadManager manager, boolean remove_torrent, boolean remove_data) throws GlobalManagerDownloadRemovalVetoException; /** * Calling this method doesn't prepare Azureus to be DHT-ready, it is * only used to store, or remove, a DHT provider - so that it can be globally * accessible. See the DHT manager classes in the plugin API for a better way * to register a provider. * * @since 3.0.4.3 */ void setMainlineDHTProvider(MainlineDHTProvider provider); /** * @since 3.0.4.3 */ MainlineDHTProvider getMainlineDHTProvider(); /** * @param manager * @return * * @since 4.0.0.5 */ boolean contains(DownloadManager manager); }azureus-4.3.0.6/org/gudy/azureus2/core3/global/GlobalManagerDownloadRemovalVetoException.java0000644000175000017500000000242511012742270031520 0ustar adrianadrian/* * File : DownloadManagerRemovalVetoException.java * Created : 10-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.global; /** * @author parg * */ public class GlobalManagerDownloadRemovalVetoException extends Exception { private boolean silent; public GlobalManagerDownloadRemovalVetoException( String str, boolean silent) { super( str ); this.silent = silent; } public GlobalManagerDownloadRemovalVetoException( String str ) { this( str, false ); } public boolean isSilent() { return silent; } } azureus-4.3.0.6/org/gudy/azureus2/core3/global/GlobalManagerFactory.java0000644000175000017500000000331710541725414025325 0ustar adrianadrian/* * File : GlobalManagerFactory.java * Created : 21-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.global; /** * @author parg * */ import org.gudy.azureus2.core3.global.impl.*; import com.aelitis.azureus.core.AzureusCore; public class GlobalManagerFactory { /* public static GlobalManager create( AzureusCore core, GlobalMangerProgressListener operation ) { return( new GlobalManagerImpl( operation, 0 )); } public static GlobalManager create( AzureusCore core ) { return( new GlobalManagerImpl( null, 0 )); } */ public static GlobalManager create( AzureusCore core, GlobalMangerProgressListener operation, long existingTorrentLoadDelay) { return( new GlobalManagerImpl( core, operation, existingTorrentLoadDelay )); } /* public static GlobalManager create( AzureusCore core, long existingTorrentLoadDelay) { return( new GlobalManagerImpl( null, existingTorrentLoadDelay )); } */ } azureus-4.3.0.6/org/gudy/azureus2/core3/torrent/0000755000175000017500000000000011310377634020672 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/torrent/TOTorrentException.java0000644000175000017500000000324111012742276025311 0ustar adrianadrian/* * File : TOTorrentException.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.torrent; public class TOTorrentException extends Exception { public static final int RT_FILE_NOT_FOUND = 1; public static final int RT_ZERO_LENGTH = 2; public static final int RT_TOO_BIG = 3; public static final int RT_READ_FAILS = 4; public static final int RT_WRITE_FAILS = 5; public static final int RT_DECODE_FAILS = 6; public static final int RT_UNSUPPORTED_ENCODING = 7; public static final int RT_HASH_FAILS = 8; public static final int RT_CANCELLED = 9; protected int reason; public TOTorrentException( String _str, int _reason ) { super( _str ); reason = _reason; } public TOTorrentException( String _str, int _reason, Throwable cause ) { this(_str, _reason); initCause(cause); } public int getReason() { return( reason ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/torrent/TOTorrentAnnounceURLGroup.java0000644000175000017500000000316507740675524026544 0ustar adrianadrian/* * File : TOTorrentAnnounceURLGroup.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.torrent; import java.net.*; public interface TOTorrentAnnounceURLGroup { /** * Gets the current sets defined for this group, 0 length if none defined * @return */ public TOTorrentAnnounceURLSet[] getAnnounceURLSets(); /** * Sets the group's URL sets to the supplied values. * @param sets */ public void setAnnounceURLSets( TOTorrentAnnounceURLSet[] sets ); /** * This method will create a new set. It is not added into the current set, this * must be done by the caller inserting the newly created set into an array as * required and calling the above "set" method. * * @param urls the URLs for the new set * @return the newly created set */ public TOTorrentAnnounceURLSet createAnnounceURLSet( URL[] urls ); } azureus-4.3.0.6/org/gudy/azureus2/core3/torrent/TOTorrentAnnounceURLSet.java0000644000175000017500000000200407740432652026163 0ustar adrianadrian/* * File : TOTorrentAnnounceURLSet.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.torrent; import java.net.*; public interface TOTorrentAnnounceURLSet { public URL[] getAnnounceURLs(); public void setAnnounceURLs( URL[] urls ); } azureus-4.3.0.6/org/gudy/azureus2/core3/torrent/impl/0000755000175000017500000000000011310377634021633 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/torrent/impl/TOTorrentAnnounceURLSetImpl.java0000644000175000017500000000302510776254672027761 0ustar adrianadrian/* * File : TOTorrentAnnounceURLSetImpl.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.torrent.impl; import java.net.URL; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.util.StringInterner; public class TOTorrentAnnounceURLSetImpl implements TOTorrentAnnounceURLSet { private TOTorrentImpl torrent; private URL[] urls; protected TOTorrentAnnounceURLSetImpl( TOTorrentImpl _torrent, URL[] _urls ) { torrent = _torrent; setAnnounceURLs( _urls ); } public URL[] getAnnounceURLs() { return( urls ); } public void setAnnounceURLs( URL[] _urls ) { urls = new URL[_urls.length]; for (int i=0;i 0 ){ file_name = root + File.separator + file_name ; } processDir( hasher, file, encoded, file_name ); }else{ if ( !ignoreFile( file_name )){ if ( root.length() > 0 ){ file_name = root + File.separator + file_name; } long length = hasher.add( file ); TOTorrentFileImpl tf = new TOTorrentFileImpl( this, offset, length, file_name); offset += length; if ( add_other_hashes ){ byte[] ed2k_digest = hasher.getPerFileED2KDigest(); byte[] sha1_digest = hasher.getPerFileSHA1Digest(); //System.out.println( "file:ed2k = " + ByteFormatter.nicePrint( ed2k_digest, true )); //System.out.println( "file:sha1 = " + ByteFormatter.nicePrint( sha1_digest, true )); tf.setAdditionalProperty( "sha1", sha1_digest ); tf.setAdditionalProperty( "ed2k", ed2k_digest ); } encoded.addElement( tf ); } } } } } public void pieceHashed( int piece_number ) { for (int i=0;i 0 ){ report( resource_key, DisplayFormatters.formatByteCountToKiBEtc( bytes )); } } protected void report( String resource_key, String additional_text ) { if ( progress_listeners.size() > 0 ){ String prefix = MessageText.getString(resource_key); for (int i=0;i 1L ) { output_file.delete(); // Will fail silently if it doesn't exist. temp.renameTo( output_file ); } }catch( TOTorrentException e ){ throw( e ); }catch( Throwable e){ throw( new TOTorrentException( "Failed to serialise torrent: " + Debug.getNestedExceptionMessage(e), TOTorrentException.RT_WRITE_FAILS )); }finally{ if ( bos != null ){ try{ bos.close(); }catch( IOException e ){ Debug.printStackTrace( e ); } } } } protected byte[] serialiseToByteArray() throws TOTorrentException { if ( created ){ TorrentUtils.addCreatedTorrent( this ); } Map root = serialiseToMap(); try{ return( BEncoder.encode( root )); }catch( IOException e ){ throw( new TOTorrentException( "Failed to serialise torrent: " + Debug.getNestedExceptionMessage(e), TOTorrentException.RT_WRITE_FAILS )); } } public Map serialiseToMap() throws TOTorrentException { // protect against recursion when getting the hash if ( created && !serialising ){ try{ serialising = true; // not thread safe but we can live without the hassle of using TLS or whatever TorrentUtils.addCreatedTorrent( this ); }finally{ serialising = false; } } Map root = new HashMap(); writeStringToMetaData( root, TK_ANNOUNCE, announce_url.toString()); TOTorrentAnnounceURLSet[] sets = announce_group.getAnnounceURLSets(); if (sets.length > 0 ){ List announce_list = new ArrayList(); for (int i=0;i 0 ){ root.put( TK_ANNOUNCE_LIST, announce_list ); } } if ( comment != null ){ root.put( TK_COMMENT, comment ); } if ( creation_date != 0 ){ root.put( TK_CREATION_DATE, new Long( creation_date )); } if ( created_by != null ){ root.put( TK_CREATED_BY, created_by ); } Map info = new HashMap(); root.put( TK_INFO, info ); info.put( TK_PIECE_LENGTH, new Long( piece_length )); if ( pieces == null ){ throw( new TOTorrentException( "Pieces is null", TOTorrentException.RT_WRITE_FAILS )); } byte[] flat_pieces = new byte[pieces.length*20]; for (int i=0;i= '0' && iFirstByte <= '9')){ // often people download an HTML file by accident - if it looks like HTML // then produce a more informative error try{ metaInfo.write(iFirstByte); int nbRead; while ((nbRead = is.read(buf)) > 0 && metaInfo.size() < 32000 ){ metaInfo.write(buf, 0, nbRead); } String char_data = new String( metaInfo.toByteArray()); if ( char_data.toLowerCase().indexOf( "html") != -1 ){ char_data = HTMLUtils.convertHTMLToText2( char_data ); char_data = HTMLUtils.splitWithLineLength( char_data, 80 ); if ( char_data.length() > 400 ){ char_data = char_data.substring(0,400) + "..."; } throw( new TOTorrentException( "Contents maybe HTML:\n" + char_data, TOTorrentException.RT_DECODE_FAILS )); } }catch( Throwable e ){ if ( e instanceof TOTorrentException ){ throw((TOTorrentException)e); } // ignore this } throw( new TOTorrentException( "Contents invalid - bad header", TOTorrentException.RT_DECODE_FAILS )); } metaInfo.write(iFirstByte); int nbRead; while ((nbRead = is.read(buf)) > 0){ metaInfo.write(buf, 0, nbRead); } }catch( Throwable e ){ throw( new TOTorrentException( "Error reading torrent: " + Debug.getNestedExceptionMessage(e), TOTorrentException.RT_READ_FAILS )); } construct( metaInfo.toByteArray()); } protected void construct( byte[] bytes ) throws TOTorrentException { try{ Map meta_data = BDecoder.decode(bytes); // print( "", "", meta_data ); construct( meta_data ); }catch( IOException e ){ throw( new TOTorrentException( "Error reading torrent: " + Debug.getNestedExceptionMessage(e), TOTorrentException.RT_DECODE_FAILS, e )); } } protected void construct( Map meta_data ) throws TOTorrentException { try{ String announce_url = null; boolean got_announce = false; boolean got_announce_list = false; boolean bad_announce = false; // decode the stuff Iterator root_it = meta_data.keySet().iterator(); while( root_it.hasNext()){ String key = (String)root_it.next(); if ( key.equalsIgnoreCase( TK_ANNOUNCE )){ got_announce = true; announce_url = readStringFromMetaData( meta_data, TK_ANNOUNCE ); if ( announce_url == null ){ bad_announce = true; }else{ announce_url = announce_url.replaceAll( " ", "" ); try{ setAnnounceURL( new URL(announce_url)); }catch( MalformedURLException e ){ if ( announce_url.indexOf( "://" ) == -1 ){ announce_url = "http:/" + (announce_url.startsWith("/")?"":"/") + announce_url; } try{ setAnnounceURL(new URL(announce_url)); }catch( MalformedURLException f ){ bad_announce = true; } } } }else if ( key.equalsIgnoreCase( TK_ANNOUNCE_LIST )){ got_announce_list = true; List announce_list = null; Object ann_list = meta_data.get( TK_ANNOUNCE_LIST ); if ( ann_list instanceof List ){ //some malformed torrents have this key as a zero-sized string instead of a zero-sized list announce_list = (List)ann_list; } if ( announce_list != null && announce_list.size() > 0 ){ announce_url = readStringFromMetaData( meta_data, TK_ANNOUNCE ); if ( announce_url != null ){ announce_url = announce_url.replaceAll( " ", "" ); } boolean announce_url_found = false; for (int i=0;i 0 ){ URL[] url_array = new URL[urls.size()]; urls.copyInto( url_array ); addTorrentAnnounceURLSet( url_array ); } }else{ Debug.out( "Torrent has invalid url-list entry (" + temp + ") - ignoring" ); } } //if the original announce url isn't found, add it to the list // watch out for those invalid torrents with announce url missing if ( !announce_url_found && announce_url != null && announce_url.length() > 0) { try { Vector urls = new Vector(); urls.add( new URL( StringInterner.intern(announce_url) )); URL[] url_array = new URL[ urls.size() ]; urls.copyInto( url_array ); addTorrentAnnounceURLSet( url_array ); } catch (Exception e) { Debug.printStackTrace( e ); } } } }else if ( key.equalsIgnoreCase( TK_COMMENT )){ setComment((byte[])meta_data.get( TK_COMMENT )); }else if ( key.equalsIgnoreCase( TK_CREATED_BY )){ setCreatedBy((byte[])meta_data.get( TK_CREATED_BY )); }else if ( key.equalsIgnoreCase( TK_CREATION_DATE )){ // non standard, don't fail if format wrong try{ Long creation_date = (Long)meta_data.get( TK_CREATION_DATE ); if ( creation_date != null ){ setCreationDate( creation_date.longValue()); } }catch( Exception e ){ System.out.println( "creation_date extraction fails, ignoring"); } }else if ( key.equalsIgnoreCase( TK_INFO )){ // processed later }else{ Object prop = meta_data.get( key ); if ( prop instanceof byte[] ){ setAdditionalByteArrayProperty( key, (byte[])prop ); }else if ( prop instanceof Long ){ setAdditionalLongProperty( key, (Long)prop ); }else if ( prop instanceof List ){ setAdditionalListProperty( key, (List)prop ); }else{ setAdditionalMapProperty( key, (Map)prop ); } } } if ( bad_announce ){ if ( got_announce_list ){ TOTorrentAnnounceURLSet[] sets = getAnnounceURLGroup().getAnnounceURLSets(); if ( sets.length > 0 ){ setAnnounceURL( sets[0].getAnnounceURLs()[0]); }else{ throw( new TOTorrentException( "ANNOUNCE_URL malformed ('" + announce_url + "' and no usable announce list)", TOTorrentException.RT_DECODE_FAILS )); } }else{ throw( new TOTorrentException( "ANNOUNCE_URL malformed ('" + announce_url + "'", TOTorrentException.RT_DECODE_FAILS )); } } if ( ! ( got_announce_list || got_announce )){ setAnnounceURL( TorrentUtils.getDecentralisedEmptyURL()); } Map info = (Map)meta_data.get( TK_INFO ); if ( info == null ){ throw( new TOTorrentException( "Decode fails, 'info' element not found'", TOTorrentException.RT_DECODE_FAILS )); } boolean hasUTF8Keys = info.containsKey(TK_NAME_UTF8); setName((byte[])info.get( TK_NAME )); long piece_length = ((Long)info.get( TK_PIECE_LENGTH )).longValue(); if ( piece_length <= 0 ){ throw( new TOTorrentException( "Decode fails, piece-length is invalid", TOTorrentException.RT_DECODE_FAILS )); } setPieceLength( piece_length ); setHashFromInfo( info ); Long simple_file_length = (Long)info.get( TK_LENGTH ); long total_length = 0; String encoding = getAdditionalStringProperty("encoding"); hasUTF8Keys &= encoding == null || encoding.equals(ENCODING_ACTUALLY_UTF8_KEYS); if ( simple_file_length != null ){ setSimpleTorrent( true ); total_length = simple_file_length.longValue(); if (hasUTF8Keys) { setNameUTF8((byte[])info.get( TK_NAME_UTF8 )); setAdditionalStringProperty("encoding", ENCODING_ACTUALLY_UTF8_KEYS); } setFiles( new TOTorrentFileImpl[]{ new TOTorrentFileImpl( this, 0, total_length, new byte[][]{getName()})}); }else{ setSimpleTorrent( false ); List meta_files = (List)info.get( TK_FILES ); TOTorrentFileImpl[] files = new TOTorrentFileImpl[ meta_files.size()]; if (hasUTF8Keys) { for (int i=0;i pieces_required ){ Debug.out( "Torrent '" + new String( getName()) + "' has too many pieces (required=" + pieces_required + ",supplied=" + pieces_supplied + ") - ignoring excess" ); } byte[][]pieces = new byte[pieces_supplied][20]; for (int i=0;i 0 ){ if ( do_other_per_file_hash ){ sha1_hash.update( buffer, buffer_pos, len ); ed2k_hash.update( buffer, buffer_pos, len ); } file_length += len; buffer_pos += len; if ( buffer_pos == piece_length ){ // hash this piece byte[] hash = new SHA1Hasher().calculateHash(buffer); if ( overall_sha1_hash != null ){ overall_sha1_hash.update( buffer ); overall_ed2k_hash.update( buffer ); } pieces.add( hash ); if ( listener != null ){ listener.pieceHashed( pieces.size() ); } buffer_pos = 0; } }else{ break; } } if ( do_other_per_file_hash ){ per_file_sha1_digest = sha1_hash.getDigest(); per_file_ed2k_digest = ed2k_hash.getDigest(); } }catch( TOTorrentException e ){ throw( e ); }catch( Throwable e ){ throw( new TOTorrentException( "TOTorrentFileHasher: file read fails '" + e.toString() + "'", TOTorrentException.RT_READ_FAILS )); }finally { if (is != null) { try { is.close(); } catch (Exception e) { } } } return( file_length ); } protected byte[] getPerFileSHA1Digest() { return( per_file_sha1_digest ); } protected byte[] getPerFileED2KDigest() { return( per_file_ed2k_digest ); } protected byte[][] getPieces() throws TOTorrentException { try{ if ( buffer_pos > 0 ){ byte[] rem = new byte[buffer_pos]; System.arraycopy( buffer, 0, rem, 0, buffer_pos ); pieces.addElement(new SHA1Hasher().calculateHash(rem)); if ( overall_sha1_hash != null ){ overall_sha1_hash.update( rem ); overall_ed2k_hash.update( rem ); } if ( listener != null ){ listener.pieceHashed( pieces.size() ); } buffer_pos = 0; } if ( overall_sha1_hash != null && sha1_digest == null ){ sha1_digest = overall_sha1_hash.getDigest(); ed2k_digest = overall_ed2k_hash.getDigest(); } byte[][] res = new byte[pieces.size()][]; pieces.copyInto( res ); return( res ); }catch( Throwable e ){ throw( new TOTorrentException( "TOTorrentFileHasher: file read fails '" + e.toString() + "'", TOTorrentException.RT_READ_FAILS )); } } protected byte[] getED2KDigest() throws TOTorrentException { if ( ed2k_digest == null ){ getPieces(); } return( ed2k_digest ); } protected byte[] getSHA1Digest() throws TOTorrentException { if ( sha1_digest == null ){ getPieces(); } return( sha1_digest ); } protected void cancel() { cancelled = true; } } azureus-4.3.0.6/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java0000644000175000017500000001647711255104206026026 0ustar adrianadrian/* * File : TOTorrentFileImpl.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.torrent.impl; import java.io.*; import java.util.*; import org.gudy.azureus2.core3.internat.*; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.util.*; public class TOTorrentFileImpl implements TOTorrentFile { private final TOTorrent torrent; private final long file_length; private final byte[][] path_components; private final byte[][] path_components_utf8; private final int first_piece_number; private final int last_piece_number; private final Map additional_properties = new LightHashMap(1); private final boolean is_utf8; protected TOTorrentFileImpl( TOTorrent _torrent, long _torrent_offset, long _len, String _path ) throws TOTorrentException { torrent = _torrent; file_length = _len; first_piece_number = (int)( _torrent_offset / torrent.getPieceLength()); last_piece_number = (int)(( _torrent_offset + file_length - 1 ) / torrent.getPieceLength()); is_utf8 = true; try{ Vector temp = new Vector(); int pos = 0; while(true){ int p1 = _path.indexOf( File.separator, pos ); if ( p1 == -1 ){ temp.add( _path.substring( pos ).getBytes( Constants.DEFAULT_ENCODING )); break; } temp.add( _path.substring( pos, p1 ).getBytes( Constants.DEFAULT_ENCODING )); pos = p1+1; } path_components = new byte[temp.size()][]; temp.copyInto( path_components ); path_components_utf8 = new byte[temp.size()][]; temp.copyInto( path_components_utf8 ); checkComponents(); }catch( UnsupportedEncodingException e ){ throw( new TOTorrentException( "Unsupported encoding for '" + _path + "'", TOTorrentException.RT_UNSUPPORTED_ENCODING)); } } protected TOTorrentFileImpl( TOTorrent _torrent, long _torrent_offset, long _len, byte[][] _path_components ) throws TOTorrentException { torrent = _torrent; file_length = _len; path_components = _path_components; path_components_utf8 = null; first_piece_number = (int)( _torrent_offset / torrent.getPieceLength()); last_piece_number = (int)(( _torrent_offset + file_length - 1 ) / torrent.getPieceLength()); is_utf8 = false; checkComponents(); } protected TOTorrentFileImpl( TOTorrent _torrent, long _torrent_offset, long _len, byte[][] _path_components, byte[][] _path_components_utf8 ) throws TOTorrentException { torrent = _torrent; file_length = _len; path_components = _path_components; path_components_utf8 = _path_components_utf8; first_piece_number = (int)( _torrent_offset / torrent.getPieceLength()); last_piece_number = (int)(( _torrent_offset + file_length - 1 ) / torrent.getPieceLength()); is_utf8 = false; checkComponents(); } protected void checkComponents() throws TOTorrentException { for (int i=0;i" ); writeLineRaw( "" ); try{ indent(); writeTag( "ANNOUNCE_URL", torrent.getAnnounceURL().toString()); TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets(); if (sets.length > 0 ){ writeLineRaw( ""); try{ indent(); for (int i=0;i"); try{ indent(); for (int j=0;j"); } }finally{ exdent(); } writeLineRaw( ""); } byte[] comment = torrent.getComment(); if ( comment != null ){ writeLocalisableTag( "COMMENT", comment ); } long creation_date = torrent.getCreationDate(); if ( creation_date != 0 ){ writeTag( "CREATION_DATE", creation_date ); } byte[] created_by = torrent.getCreatedBy(); if ( created_by != null ){ writeLocalisableTag( "CREATED_BY", created_by ); } writeTag( "TORRENT_HASH", torrent.getHash()); byte[] hash_override = torrent.getHashOverride(); if ( hash_override != null ){ writeTag( "TORRENT_HASH_OVERRIDE", hash_override ); } writeInfo(); Map additional_properties = torrent.getAdditionalProperties(); Iterator it = additional_properties.keySet().iterator(); while( it.hasNext()){ String key = (String)it.next(); writeGenericMapEntry( key, additional_properties.get( key )); } }finally{ exdent(); } writeLineRaw( ""); } protected void writeInfo() throws TOTorrentException { writeLineRaw( "" ); try{ indent(); writeLocalisableTag( "NAME", torrent.getName()); writeTag( "PIECE_LENGTH", torrent.getPieceLength()); TOTorrentFileImpl[] files = (TOTorrentFileImpl[])torrent.getFiles(); if ( torrent.isSimpleTorrent()){ writeTag( "LENGTH", files[0].getLength()); }else{ writeLineRaw( ""); try{ indent(); for (int i=0;i"); try{ indent(); TOTorrentFileImpl file = files[i]; writeTag( "LENGTH", file.getLength()); writeLineRaw( ""); try{ indent(); byte[][] path_comps = file.getPathComponents(); for (int j=0;j"); Map additional_properties = file.getAdditionalProperties(); Iterator prop_it = additional_properties.keySet().iterator(); while( prop_it.hasNext()){ String key = (String)prop_it.next(); writeGenericMapEntry( key, additional_properties.get( key )); } }finally{ exdent(); } writeLineRaw( ""); } }finally{ exdent(); } writeLineRaw( ""); } writeLineRaw( ""); try{ indent(); byte[][] pieces = torrent.getPieces(); for (int i=0;i"); Map additional_properties = torrent.getAdditionalInfoProperties(); Iterator it = additional_properties.keySet().iterator(); while( it.hasNext()){ String key = (String)it.next(); writeGenericMapEntry( key, additional_properties.get( key )); } }finally{ exdent(); } writeLineRaw( ""); } } azureus-4.3.0.6/org/gudy/azureus2/core3/torrent/TOTorrentProgressListener.java0000644000175000017500000000203307740432652026672 0ustar adrianadrian/* * File : TOTorrentProgressListener.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.torrent; public interface TOTorrentProgressListener { public void reportProgress( int percent_complete ); public void reportCurrentTask( String task_description ); } azureus-4.3.0.6/org/gudy/azureus2/core3/torrent/TOTorrentCreator.java0000644000175000017500000000242010373051054024744 0ustar adrianadrian/* * Created on 07-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.torrent; /** * @author parg * */ public interface TOTorrentCreator { public TOTorrent create() throws TOTorrentException; public void cancel(); public void addListener( TOTorrentProgressListener listener ); public void removeListener( TOTorrentProgressListener listener ); } azureus-4.3.0.6/org/gudy/azureus2/core3/torrent/TOTorrentFactory.java0000644000175000017500000001425310547027164024773 0ustar adrianadrian/* * File : TOTorrentFactory.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.torrent; import java.util.*; import java.io.*; import java.net.*; import org.gudy.azureus2.core3.torrent.impl.*; public class TOTorrentFactory { public static final long TO_DEFAULT_FIXED_PIECE_SIZE = 256*1024; public static final long TO_DEFAULT_VARIABLE_PIECE_SIZE_MIN = 32*1024; public static final long TO_DEFAULT_VARIABLE_PIECE_SIZE_MAX = 2*1024*1024; public static final long TO_DEFAULT_VARIABLE_PIECE_NUM_LOWER = 1024; public static final long TO_DEFAULT_VARIABLE_PIECE_NUM_UPPER = 2048; public static final long[] STANDARD_PIECE_SIZES = { 32*1024, 48*1024, 64*1024, 96*1024, 128*1024, 192*1024, 256*1024, 384*1024, 512*1024, 768*1024, 1024*1024, 1536*1024, 2*1024*1024, 3*1024*1024, 4*1024*1024 }; // deserialisation methods public static TOTorrent deserialiseFromBEncodedFile( File file ) throws TOTorrentException { return( new TOTorrentDeserialiseImpl( file )); } /** * WARNING - take care if you use this that the data you're creating the torrent from doesn't contain * unwanted attributes in it (e.g. "torrent filename"). You should almost definitely be using * TorrentUtils.deserialiseFromBEncodedInputStream * @param is * @return * @throws TOTorrentException */ public static TOTorrent deserialiseFromBEncodedInputStream( InputStream is ) throws TOTorrentException { return( new TOTorrentDeserialiseImpl( is )); } public static TOTorrent deserialiseFromBEncodedByteArray( byte[] bytes ) throws TOTorrentException { return( new TOTorrentDeserialiseImpl( bytes )); } public static TOTorrent deserialiseFromMap( Map data ) throws TOTorrentException { return( new TOTorrentDeserialiseImpl( data )); } public static TOTorrent deserialiseFromXMLFile( File file ) throws TOTorrentException { return( new TOTorrentXMLDeserialiser().deserialise( file )); } // construction methods: fixed piece size public static TOTorrentCreator createFromFileOrDirWithFixedPieceLength( File file, URL announce_url ) throws TOTorrentException { return( createFromFileOrDirWithFixedPieceLength( file, announce_url, false, TO_DEFAULT_FIXED_PIECE_SIZE )); } public static TOTorrentCreator createFromFileOrDirWithFixedPieceLength( File file, URL announce_url, boolean add_hashes ) throws TOTorrentException { return( createFromFileOrDirWithFixedPieceLength( file, announce_url, add_hashes, TO_DEFAULT_FIXED_PIECE_SIZE )); } public static TOTorrentCreator createFromFileOrDirWithFixedPieceLength( File file, URL announce_url, long piece_length ) throws TOTorrentException { return( createFromFileOrDirWithFixedPieceLength( file, announce_url, false, piece_length )); } public static TOTorrentCreator createFromFileOrDirWithFixedPieceLength( File file, URL announce_url, boolean add_hashes, long piece_length ) throws TOTorrentException { return( TOTorrentCreateImpl.create( file, announce_url, add_hashes, piece_length )); } // construction methods: variable piece size public static TOTorrentCreator createFromFileOrDirWithComputedPieceLength( File file, URL announce_url ) throws TOTorrentException { return( createFromFileOrDirWithComputedPieceLength( file, announce_url, false )); } public static TOTorrentCreator createFromFileOrDirWithComputedPieceLength( File file, URL announce_url, boolean add_hashes ) throws TOTorrentException { return( createFromFileOrDirWithComputedPieceLength( file, announce_url, add_hashes, TO_DEFAULT_VARIABLE_PIECE_SIZE_MIN, TO_DEFAULT_VARIABLE_PIECE_SIZE_MAX, TO_DEFAULT_VARIABLE_PIECE_NUM_LOWER, TO_DEFAULT_VARIABLE_PIECE_NUM_UPPER )); } public static TOTorrentCreator createFromFileOrDirWithComputedPieceLength( File file, URL announce_url, long piece_min_size, long piece_max_size, long piece_num_lower, long piece_num_upper ) throws TOTorrentException { return( createFromFileOrDirWithComputedPieceLength( file, announce_url, false, piece_min_size, piece_max_size, piece_num_lower, piece_num_upper )); } public static TOTorrentCreator createFromFileOrDirWithComputedPieceLength( File file, URL announce_url, boolean add_hashes, long piece_min_size, long piece_max_size, long piece_num_lower, long piece_num_upper ) throws TOTorrentException { return( TOTorrentCreateImpl.create( file, announce_url, add_hashes, piece_min_size, piece_max_size, piece_num_lower, piece_num_upper )); } public static long getTorrentDataSizeFromFileOrDir( File file_or_dir ) { return( TOTorrentCreateImpl.getTorrentDataSizeFromFileOrDir( file_or_dir )); } public static long getComputedPieceSize( long data_size ) { return( TOTorrentCreateImpl.getComputedPieceSize( data_size, TO_DEFAULT_VARIABLE_PIECE_SIZE_MIN, TO_DEFAULT_VARIABLE_PIECE_SIZE_MAX, TO_DEFAULT_VARIABLE_PIECE_NUM_LOWER, TO_DEFAULT_VARIABLE_PIECE_NUM_UPPER )); } public static long getPieceCount( long total_size, long piece_size ) { return( TOTorrentCreateImpl.getPieceCount( total_size, piece_size )); } } azureus-4.3.0.6/org/gudy/azureus2/core3/torrent/test/0000755000175000017500000000000011310377634021651 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/torrent/test/Main.java0000644000175000017500000001104710634631646023407 0ustar adrianadrian/* * File : Main.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.torrent.test; import java.io.*; import java.net.*; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.util.Debug; public class Main { static int TT_ENCODE = 1; static int TT_DECODE = 2; static int TT_CREATE = 3; static void usage() { System.err.println( "Usage: encode|decode|create" ); SESecurityManager.exitVM(1); } public static void main( String[] args ) { int test_type= 0; if ( args.length != 1 ){ usage(); } if ( args[0].equalsIgnoreCase( "encode" )){ test_type = TT_ENCODE; }else if ( args[0].equalsIgnoreCase( "decode" )){ test_type = TT_DECODE; }else if ( args[0].equalsIgnoreCase( "create" )){ test_type = TT_CREATE; }else{ usage(); } try{ if ( test_type == TT_ENCODE ){ /* File f = new File("D:\\az2060-broken.torrent"); TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedFile( f ); TOTorrentAnnounceURLSet set = torrent.getAnnounceURLGroup().createAnnounceURLSet(new URL[]{ new URL("http://localhost:6970/announce"), new URL("http://localhost:6969/announce")}); torrent.getAnnounceURLGroup().setAnnounceURLSets( new TOTorrentAnnounceURLSet[]{ set }); torrent.setAdditionalStringProperty( "Wibble", "wobble" ); torrent.print(); torrent.serialiseToBEncodedFile( new File("c:\\temp\\test2.torrent")); */ }else if ( test_type == TT_DECODE ){ File f = new File("c:\\temp\\az3008-broken.torrent" ); TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedFile( f ); // System.out.println( "\turl group sets = " + torrent.getAnnounceURLGroup().getAnnounceURLSets().length); torrent.print(); }else if ( test_type == TT_CREATE ){ TOTorrentProgressListener list = new TOTorrentProgressListener() { public void reportProgress( int p ) { System.out.println( "" + p ); } public void reportCurrentTask( String task_description ) { System.out.println( "task = " + task_description ); } }; boolean do_file = false; boolean do_fixed = false; TOTorrent t; if ( do_fixed ){ if ( do_file ){ TOTorrentCreator c = TOTorrentFactory.createFromFileOrDirWithFixedPieceLength( new File("c:\\temp\\test.wmf"), new URL( "http://127.0.0.1:6969/announce" ), 1024*10 ); c.addListener( list ); t = c.create(); }else{ TOTorrentCreator c = TOTorrentFactory.createFromFileOrDirWithFixedPieceLength( new File("c:\\temp\\scans"), new URL("http://127.0.0.1:6969/announce" ), 1024*256 ); c.addListener( list ); t = c.create(); } }else{ if ( do_file ){ TOTorrentCreator c = TOTorrentFactory.createFromFileOrDirWithComputedPieceLength( new File("c:\\temp\\test.wmf"), new URL( "http://127.0.0.1:6969/announce" )); c.addListener( list ); t = c.create(); }else{ TOTorrentCreator c = TOTorrentFactory.createFromFileOrDirWithComputedPieceLength( new File("c:\\temp\\qqq"), new URL("http://127.0.0.1:6969/announce" )); c.addListener( list ); t = c.create(); t.setCreationDate( 12345L ); t.setComment( "poo pee plop mcjock"); } } t.print(); t.serialiseToBEncodedFile( new File("c:\\temp\\test.torrent" )); } }catch( Throwable e ){ Debug.printStackTrace( e ); } } }azureus-4.3.0.6/org/gudy/azureus2/core3/torrent/TOTorrentFile.java0000644000175000017500000000220410551433514024227 0ustar adrianadrian/* * File : TOTorrentFile.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.torrent; public interface TOTorrentFile { public TOTorrent getTorrent(); public long getLength(); public byte[][] getPathComponents(); public String getRelativePath(); public int getFirstPieceNumber(); public int getLastPieceNumber(); public int getNumberOfPieces(); } azureus-4.3.0.6/org/gudy/azureus2/core3/torrent/TOTorrent.java0000644000175000017500000001551411270516754023446 0ustar adrianadrian/* * File : TOTorrent.java * Created : 5 Oct. 2003 * By : Parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.torrent; import java.io.*; import java.net.*; import java.util.*; import org.gudy.azureus2.core3.util.*; public interface TOTorrent { public static final String DEFAULT_IGNORE_FILES = ".DS_Store;Thumbs.db;desktop.ini"; /** * A Map additional property defined for holding AZ specific properties that are * deemed to be exportable to the world */ public static final String AZUREUS_PROPERTIES = "azureus_properties"; /** * These ones are *not* exportable to the world */ public static final String AZUREUS_PRIVATE_PROPERTIES = "azureus_private_properties"; public static final String ENCODING_ACTUALLY_UTF8_KEYS = "utf8 keys"; /** * Get the name of the torrent * @return */ public byte[] getName(); /** * A "simple torrent" is one that consists of a single file on its own (i.e. not in a * nested directory). * @return */ public boolean isSimpleTorrent(); /** * Comment is an optional torrent property * @return */ public byte[] getComment(); public void setComment( String comment ); /** * Gets the creation date of the torrent. Optional property, 0 returned if not set * @return */ public long getCreationDate(); public void setCreationDate( long date ); public byte[] getCreatedBy(); public void setCreatedBy( byte[] cb ); public boolean isCreated(); /** * A torrent must have a URL that identifies the tracker. This method returns it. However * an extension to this exists to allow multiple trackers, and their backups, to be defined. * See below * @return */ public URL getAnnounceURL(); /** * * @param url * @return true-changed; false-not changed */ public boolean setAnnounceURL( URL url ); /** * When a group of sets of trackers is defined their URLs are accessed via this method * @return the group, always present, which may have 0 members */ public TOTorrentAnnounceURLGroup getAnnounceURLGroup(); /** * This method provides access to the SHA1 hash values (20 bytes each) that correspond * to the pieces of the torrent. * @return * @exception can fail if re-reading of piece hashes for space spacing fails */ public byte[][] getPieces() throws TOTorrentException; /** * This method exists to support the temporary discarding of piece hashes to conserver * memory. It should only be used with care! * @param pieces */ public void setPieces( byte[][] pieces ) throws TOTorrentException; /** * Returns the piece length used for the torrent * @return */ public long getPieceLength(); public int getNumberOfPieces(); public long getSize(); /** * A torrent consists of one or more files. These are accessed via this method. * @return */ public TOTorrentFile[] getFiles(); /** * A torrent has a unique SHA1 (20 byte) hash that is computed from some of its contents. * It is used, for example, when contacting a tracker to identify the torrent. * @return * @throws TOTorrentException */ public byte[] getHash() throws TOTorrentException; /** * convenience method to get a wrapped hash for performance purposes * @return * @throws TOTorrentException */ public HashWrapper getHashWrapper() throws TOTorrentException; /** * Only supported for decentralised torrents, allows an alternative hash to be used * for them in the DHT * @param hash * @throws TOTorrentException */ public void setHashOverride( byte[] hash ) throws TOTorrentException; /** * compares two torrents by hash * @param other * @return */ public boolean hasSameHashAs( TOTorrent other ); public boolean getPrivate(); /** * Note - changing the private attribute CHANGES THE TORRENT HASH * @param _private */ public void setPrivate( boolean _private ) throws TOTorrentException; /** * The additional properties are used for holding non-core data for Azureus' own user * @param name name of the property (e.g. "encoding") * @param value value. This will be encoded with default encoding */ public void setAdditionalStringProperty( String name, String value ); public String getAdditionalStringProperty( String name ); public void setAdditionalByteArrayProperty( String name, byte[] value ); public byte[] getAdditionalByteArrayProperty( String name ); public void setAdditionalLongProperty( String name, Long value ); public Long getAdditionalLongProperty( String name ); public void setAdditionalListProperty( String name, List value ); public List getAdditionalListProperty( String name ); public void setAdditionalMapProperty( String name, Map value ); public Map getAdditionalMapProperty( String name ); public Object getAdditionalProperty( String name ); /** * set an arbitrary property. Make sure its compatible with bencoding! */ public void setAdditionalProperty( String name, Object value ); public void removeAdditionalProperty( String name ); /** * remove all additional properties to clear out the torrent */ public void removeAdditionalProperties(); /** * This method will serialise a torrent using the standard "b-encoding" mechanism into a file * @param file * @throws TOTorrentException */ public void serialiseToBEncodedFile( File file ) throws TOTorrentException; /** * This method will serialise a torrent into a Map consistent with that used by the * "b-encoding" routines defined elsewhere * @return * @throws TOTorrentException */ public Map serialiseToMap() throws TOTorrentException; /** * This method will serialise a torrent using an XML encoding to a file * @param file * @throws TOTorrentException */ public void serialiseToXMLFile( File file ) throws TOTorrentException; public AEMonitor getMonitor(); /** * A diagnostic method for dumping the tracker contents to "stdout" * */ public void print(); } azureus-4.3.0.6/org/gudy/azureus2/core3/category/0000755000175000017500000000000011310377634021012 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/category/CategoryManager.java0000644000175000017500000000572510014452532024725 0ustar adrianadrian/* * File : CategoryManager.java * Created : 09 feb. 2004 * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.category; import org.gudy.azureus2.core3.category.Category; import org.gudy.azureus2.core3.category.CategoryManagerListener; import org.gudy.azureus2.core3.category.impl.CategoryManagerImpl; /** A singleton to manage Categories of Torrents (DownloadManagers). * @author TuxPaper */ public class CategoryManager { /** Add a CategoryManager Listener * @param l Listener to Add */ public static void addCategoryManagerListener(CategoryManagerListener l) { CategoryManagerImpl.getInstance().addCategoryManagerListener(l); } /** Removes a CategoryManager Listener * @param l Listener to remove * @see CategoryManagerListener */ public static void removeCategoryManagerListener(CategoryManagerListener l) { CategoryManagerImpl.getInstance().removeCategoryManagerListener(l); } /** Creates a new Category object and adds it to the list * @return If successful, returns the newly created Category. Otherwise, returns null. * @param name Name of Category to add */ public static Category createCategory(String name) { return CategoryManagerImpl.getInstance().createCategory(name); } /** Removes a Category from the list * @param category Category to remove */ public static void removeCategory(Category category) { CategoryManagerImpl.getInstance().removeCategory(category); } /** Retrieves the list of Categories * To sort the categories by name (TYPE_USER last): * * Arrays.sort(categories); * * * @return List of Categories */ public static Category[] getCategories() { return CategoryManagerImpl.getInstance().getCategories(); } /** Retrieve a Category * @param name Name of Category * @return Category you asked for */ public static Category getCategory(String name) { return CategoryManagerImpl.getInstance().getCategory(name); } /** Retrieve a non-user Category * @param type any type except TYPE_USER * @return The Category, or null if not found. * @see Category * USER_ constants */ public static Category getCategory(int type) { return CategoryManagerImpl.getInstance().getCategory(type); } } azureus-4.3.0.6/org/gudy/azureus2/core3/category/impl/0000755000175000017500000000000011310377634021753 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/category/impl/CategoryManagerImpl.java0000644000175000017500000001772710734644204026525 0ustar adrianadrian/* * File : CategoryManagerImpl.java * Created : 09 feb. 2004 * By : TuxPaper * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.category.impl; import java.util.Map; import java.util.Iterator; import java.util.HashMap; import java.util.ArrayList; import java.util.List; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.UnsupportedEncodingException; import org.gudy.azureus2.core3.category.*; import org.gudy.azureus2.core3.util.*; public class CategoryManagerImpl { private static final String UNCAT_NAME = "__uncategorised__"; private static CategoryManagerImpl catMan; private static Category catAll = null; private static Category catUncategorized = null; private static boolean doneLoading = false; private static AEMonitor class_mon = new AEMonitor( "CategoryManager:class" ); private Map categories = new HashMap(); private AEMonitor categories_mon = new AEMonitor( "Categories" ); private static final int LDT_CATEGORY_ADDED = 1; private static final int LDT_CATEGORY_REMOVED = 2; private ListenerManager category_listeners = ListenerManager.createManager( "CatListenDispatcher", new ListenerManagerDispatcher() { public void dispatch(Object _listener, int type, Object value ) { CategoryManagerListener target = (CategoryManagerListener)_listener; if ( type == LDT_CATEGORY_ADDED ) target.categoryAdded((Category)value); else if ( type == LDT_CATEGORY_REMOVED ) target.categoryRemoved((Category)value); } }); protected CategoryManagerImpl() { loadCategories(); } public void addCategoryManagerListener(CategoryManagerListener l) { category_listeners.addListener( l ); } public void removeCategoryManagerListener(CategoryManagerListener l) { category_listeners.removeListener( l ); } public static CategoryManagerImpl getInstance() { try{ class_mon.enter(); if (catMan == null) catMan = new CategoryManagerImpl(); return catMan; }finally{ class_mon.exit(); } } protected void loadCategories() { if (doneLoading) return; doneLoading = true; FileInputStream fin = null; BufferedInputStream bin = null; makeSpecialCategories(); try { //open the file File configFile = FileUtil.getUserFile("categories.config"); fin = new FileInputStream(configFile); bin = new BufferedInputStream(fin, 8192); Map map = BDecoder.decode(bin); List catList = (List) map.get("categories"); for (int i = 0; i < catList.size(); i++) { Map mCategory = (Map) catList.get(i); try { String catName = new String((byte[]) mCategory.get("name"), Constants.DEFAULT_ENCODING); Long l_maxup = (Long)mCategory.get( "maxup" ); Long l_maxdown = (Long)mCategory.get( "maxdown" ); if ( catName.equals( UNCAT_NAME )){ catUncategorized.setUploadSpeed(l_maxup==null?0:l_maxup.intValue()); catUncategorized.setDownloadSpeed(l_maxdown==null?0:l_maxdown.intValue()); }else{ categories.put( catName, new CategoryImpl( catName, l_maxup==null?0:l_maxup.intValue(), l_maxdown==null?0:l_maxdown.intValue())); } } catch (UnsupportedEncodingException e1) { //Do nothing and process next. } } } catch (FileNotFoundException e) { //Do nothing } catch (Exception e) { Debug.printStackTrace( e ); } finally { try { if (bin != null) bin.close(); } catch (Exception e) {} try { if (fin != null) fin.close(); } catch (Exception e) {} } } public void saveCategories() { try{ categories_mon.enter(); Map map = new HashMap(); List list = new ArrayList(categories.size()); Iterator iter = categories.values().iterator(); while (iter.hasNext()) { Category cat = (Category) iter.next(); if (cat.getType() == Category.TYPE_USER) { Map catMap = new HashMap(); catMap.put( "name", cat.getName()); catMap.put( "maxup", new Long(cat.getUploadSpeed())); catMap.put( "maxdown", new Long(cat.getDownloadSpeed())); list.add(catMap); } } Map uncat = new HashMap(); uncat.put( "name", UNCAT_NAME ); uncat.put( "maxup", new Long(catUncategorized.getUploadSpeed())); uncat.put( "maxdown", new Long(catUncategorized.getDownloadSpeed())); list.add( uncat ); map.put("categories", list); FileOutputStream fos = null; try { //encode the data byte[] torrentData = BEncoder.encode(map); File oldFile = FileUtil.getUserFile("categories.config"); File newFile = FileUtil.getUserFile("categories.config.new"); //write the data out fos = new FileOutputStream(newFile); fos.write(torrentData); fos.flush(); fos.getFD().sync(); //close the output stream fos.close(); fos = null; //delete the old file if ( !oldFile.exists() || oldFile.delete() ) { //rename the new one newFile.renameTo(oldFile); } } catch (Exception e) { Debug.printStackTrace( e ); } finally { try { if (fos != null) fos.close(); } catch (Exception e) {} } }finally{ categories_mon.exit(); } } public Category createCategory(String name) { makeSpecialCategories(); Category newCategory = getCategory(name); if (newCategory == null) { newCategory = new CategoryImpl(name, 0, 0); categories.put(name, newCategory); saveCategories(); category_listeners.dispatch( LDT_CATEGORY_ADDED, newCategory ); return (Category)categories.get(name); } return newCategory; } public void removeCategory(Category category) { if (categories.containsKey(category.getName())) { categories.remove(category.getName()); saveCategories(); category_listeners.dispatch( LDT_CATEGORY_REMOVED, category ); } } public Category[] getCategories() { if (categories.size() > 0) return (Category[])categories.values().toArray(new Category[categories.size()]); return (new Category[0]); } public Category getCategory(String name) { return (Category)categories.get(name); } public Category getCategory(int type) { if (type == Category.TYPE_ALL) return catAll; if (type == Category.TYPE_UNCATEGORIZED) return catUncategorized; return null; } private void makeSpecialCategories() { if (catAll == null) { catAll = new CategoryImpl("Categories.all", Category.TYPE_ALL); categories.put("Categories.all", catAll); } if (catUncategorized == null) { catUncategorized = new CategoryImpl("Categories.uncategorized", Category.TYPE_UNCATEGORIZED); categories.put("Categories.uncategorized", catUncategorized); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/category/impl/CategoryImpl.java0000644000175000017500000001365111137476006025223 0ustar adrianadrian/* * File : CategoryImpl.java * Created : 09 feb. 2004 * By : TuxPaper * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.category.impl; import java.util.List; import java.util.ArrayList; import org.gudy.azureus2.core3.category.Category; import org.gudy.azureus2.core3.category.CategoryListener; import org.gudy.azureus2.core3.download.*; import org.gudy.azureus2.core3.util.ListenerManager; import org.gudy.azureus2.core3.util.ListenerManagerDispatcher; import com.aelitis.azureus.core.networkmanager.LimitedRateGroup; public class CategoryImpl implements Category, Comparable { private String sName; private int type; private List managers = new ArrayList(); private int upload_speed; private int download_speed; private LimitedRateGroup upload_limiter = new LimitedRateGroup() { public String getName() { return( "cat_up: " + sName); } public int getRateLimitBytesPerSecond() { return( upload_speed ); } }; private LimitedRateGroup download_limiter = new LimitedRateGroup() { public String getName() { return( "cat_down: " + sName); } public int getRateLimitBytesPerSecond() { return( download_speed ); } }; private static final int LDT_CATEGORY_DMADDED = 1; private static final int LDT_CATEGORY_DMREMOVED = 2; private ListenerManager category_listeners = ListenerManager.createManager( "CatListenDispatcher", new ListenerManagerDispatcher() { public void dispatch(Object _listener, int type, Object value ) { CategoryListener target = (CategoryListener)_listener; if ( type == LDT_CATEGORY_DMADDED ) target.downloadManagerAdded((Category) CategoryImpl.this, (DownloadManager)value); else if ( type == LDT_CATEGORY_DMREMOVED ) target.downloadManagerRemoved(CategoryImpl.this, (DownloadManager)value); } }); public CategoryImpl(String sName, int maxup, int maxdown ) { this.sName = sName; this.type = Category.TYPE_USER; upload_speed = maxup; download_speed = maxdown; } public CategoryImpl(String sName, int type) { this.sName = sName; this.type = type; } public void addCategoryListener(CategoryListener l) { category_listeners.addListener( l ); } public void removeCategoryListener(CategoryListener l) { category_listeners.removeListener( l ); } public String getName() { return sName; } public int getType() { return type; } public List getDownloadManagers(List all_dms) { if ( type == Category.TYPE_USER ){ return managers; }else if ( type == Category.TYPE_ALL ){ return all_dms; }else{ List result = new ArrayList(); for (int i=0;i 0) { return false; } long start_address = ipStart; long end_address = ipEnd; if (start_address < 0) { start_address += 0x100000000L; } if (end_address < 0) { end_address += 0x100000000L; } return (end_address >= start_address); } public boolean isInRange(String ipAddress) { if (!isValid()) { return false; } try { long int_address = PRHelpers.addressToInt(ipAddress); if (int_address < 0) { int_address += 0x100000000L; } long start_address = ipStart; long end_address = ipEnd; if (start_address < 0) { start_address += 0x100000000L; } if (end_address < 0) { end_address += 0x100000000L; } return (int_address >= start_address && int_address <= end_address); } catch (UnknownHostException e) { return (false); } } public String getDescription() { return new String(IpFilterManagerFactory.getSingleton().getDescription( descRef)); } public void setDescription(String str) { descRef = IpFilterManagerFactory.getSingleton().addDescription(this, str.getBytes()); } public String getStartIp() { return (flags & FLAG_INVALID_START) > 0 ? "" : PRHelpers.intToAddress(ipStart); } public long getStartIpLong() { if ((flags & FLAG_INVALID_START) > 0) { return -1; } long val = ipStart; if (val < 0) { val += 0x100000000L; } return (val); } public void setStartIp(String str) { if (str == null) { throw (new RuntimeException("Invalid start value - null not supported")); } if (str.equals(getStartIp())) { return; } flags &= ~FLAG_INVALID_START; try { ipStart = PRHelpers.addressToInt(str); } catch (UnknownHostException e) { flags |= FLAG_INVALID_START; } if ((flags & FLAG_INVALID) == 0) { checkValid(); } } public String getEndIp() { return (flags & FLAG_INVALID_END) > 0 ? "" : PRHelpers.intToAddress(ipEnd); } public long getEndIpLong() { if ((flags & FLAG_INVALID_END) > 0) { return -1; } long val = ipEnd; if (val < 0) { val += 0x100000000L; } return (val); } public void setEndIp(String str) { if (str == null) { throw (new RuntimeException("Invalid end value - null not supported")); } if (str.equals(getEndIp())) { return; } flags &= ~FLAG_INVALID_END; try { ipEnd = PRHelpers.addressToInt(str); } catch (UnknownHostException e) { flags |= FLAG_INVALID_END; } if ((flags & FLAG_INVALID) == 0) { checkValid(); } } public String toString() { return getDescription() + " : " + getStartIp() + " - " + getEndIp(); } public boolean isSessionOnly() { return (flags & FLAG_SESSION_ONLY) != 0; } public void setSessionOnly(boolean _sessionOnly) { if (_sessionOnly) { flags |= FLAG_SESSION_ONLY; } else { flags &= ~FLAG_SESSION_ONLY; } } public int compareStartIpTo(IpRange other) { long l = getStartIpLong() - ((IpRangeImpl) other).getStartIpLong(); if (l < 0) { return (-1); } else if (l > 0) { return (1); } else { return (0); } } public int compareEndIpTo(IpRange other) { long l = getEndIpLong() - ((IpRangeImpl) other).getEndIpLong(); if (l < 0) { return (-1); } else if (l > 0) { return (1); } return (0); } protected void setAddedToRangeList(boolean b) { if (b) { flags |= FLAG_ADDED_TO_RANGE_LIST; } else { flags &= ~FLAG_ADDED_TO_RANGE_LIST; } } public boolean getAddedToRangeList() { return (flags & FLAG_ADDED_TO_RANGE_LIST) != 0; } public int compareDescription(IpRange other) { return getDescription().compareTo(other.getDescription()); } protected Object getDescRef() { return descRef; } protected void setDescRef(Object descRef) { this.descRef = descRef; } public long getMergedEndLong() { return (merged_end < 0 ? (merged_end + 0x100000000L) : merged_end); } public IpRange[] getMergedEntries() { return (my_merged_entries); } public void resetMergeInfo() { flags &= ~FLAG_MERGED; if ((flags & FLAG_INVALID_END) == 0) { merged_end = ipEnd; } } public boolean getMerged() { return (flags & FLAG_MERGED) != 0; } public void setMerged() { flags |= FLAG_MERGED; } public void setMergedEnd(long endIpLong) { merged_end = (int) (endIpLong >= 0x100000000L ? endIpLong - 0x100000000L : endIpLong); } public void addMergedEntry(IpRange e2) { if (my_merged_entries == null) { my_merged_entries = new IpRange[] { e2 }; } else { IpRange[] x = new IpRange[my_merged_entries.length + 1]; System.arraycopy(my_merged_entries, 0, x, 0, my_merged_entries.length); x[x.length - 1] = e2; my_merged_entries = x; } } } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/impl/BadIpsImpl.java0000644000175000017500000000553410123166234024603 0ustar adrianadrian/* * File : BadIpsImpl.java * Created : 10 nov. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.ipfilter.impl; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.ipfilter.BadIp; import org.gudy.azureus2.core3.ipfilter.BadIps; import org.gudy.azureus2.core3.util.*; /** * @author Olivier * */ public class BadIpsImpl implements BadIps { private static BadIps instance; private static AEMonitor class_mon = new AEMonitor( "BadIps:class" ); private Map bad_ip_map; private AEMonitor bad_ip_map_mon = new AEMonitor( "BadIps:Map"); public static BadIps getInstance() { try{ class_mon.enter(); if( instance == null ){ instance = new BadIpsImpl(); } return( instance ); }finally{ class_mon.exit(); } } public BadIpsImpl() { bad_ip_map = new HashMap(); } public int addWarningForIp( String ip ) { try{ bad_ip_map_mon.enter(); BadIpImpl bad_ip = (BadIpImpl)bad_ip_map.get( ip ); if ( bad_ip == null ){ bad_ip = new BadIpImpl(ip); bad_ip_map.put( ip, bad_ip ); } return( bad_ip.incrementWarnings()); }finally{ bad_ip_map_mon.exit(); } } public int getNbWarningForIp( String ip) { try{ bad_ip_map_mon.enter(); BadIpImpl bad_ip = (BadIpImpl) bad_ip_map.get(ip); if(bad_ip == null) { return 0; }else{ return bad_ip.getNumberOfWarnings(); } }finally{ bad_ip_map_mon.exit(); } } public BadIp[] getBadIps() { try{ bad_ip_map_mon.enter(); BadIp[] res = new BadIp[bad_ip_map.size()]; bad_ip_map.values().toArray( res ); return( res ); }finally{ bad_ip_map_mon.exit(); } } public void clearBadIps() { try{ bad_ip_map_mon.enter(); bad_ip_map.clear(); }finally{ bad_ip_map_mon.exit(); } } public int getNbBadIps() { return( bad_ip_map.size()); } } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/impl/IpFilterImpl.java0000644000175000017500000006222211163305126025154 0ustar adrianadrian/* * File : IpFilterImpl.java * Created : 16-Oct-2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.ipfilter.impl; /** * @author Olivier * */ import java.io.*; import java.net.Inet6Address; import java.net.InetAddress; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.ipfilter.*; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.tracker.protocol.PRHelpers; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.util.CopyOnWriteList; public class IpFilterImpl implements IpFilter { private static final LogIDs LOGID = LogIDs.CORE; private final static long BAN_IP_PERSIST_TIME = 7*24*60*60*1000L; private final static int MAX_BLOCKS_TO_REMEMBER = 500; private static IpFilterImpl ipFilter; private static AEMonitor2 class_mon = new AEMonitor2( "IpFilter:class" ); private IPAddressRangeManager range_manager = new IPAddressRangeManager(); private Map bannedIps; //Map ip blocked -> matching range private LinkedList ipsBlocked; private int num_ips_blocked = 0; private int num_ips_blocked_loggable = 0; private long last_update_time; private List listeners = new ArrayList(); private CopyOnWriteList external_handlers = new CopyOnWriteList(); FrequencyLimitedDispatcher blockedListChangedDispatcher; private IpFilterAutoLoaderImpl ipFilterAutoLoader; private boolean ip_filter_enabled; private boolean ip_filter_allow; { COConfigurationManager.addAndFireParameterListeners( new String[] { "Ip Filter Allow", "Ip Filter Enabled" }, new ParameterListener() { public void parameterChanged( String parameterName ) { ip_filter_enabled = COConfigurationManager.getBooleanParameter( "Ip Filter Enabled" ); ip_filter_allow = COConfigurationManager.getBooleanParameter( "Ip Filter Allow" ); } }); } private IpFilterImpl() { ipFilter = this; bannedIps = new HashMap(); ipsBlocked = new LinkedList(); blockedListChangedDispatcher = new FrequencyLimitedDispatcher( new AERunnable() { public void runSupport() { Object[] listenersArray = listeners.toArray(); for (int i = 0; i < listenersArray.length; i++) { try { IPFilterListener l = (IPFilterListener) listenersArray[i]; l.IPBlockedListChanged(IpFilterImpl.this); } catch (Exception e) { Debug.out(e); } } } }, 10000); ipFilterAutoLoader = new IpFilterAutoLoaderImpl(this); try{ loadBannedIPs(); }catch( Throwable e ){ Debug.printStackTrace(e); } try{ loadFilters(true, true); }catch( Exception e ){ Debug.printStackTrace( e ); } COConfigurationManager.addParameterListener(new String[] { "Ip Filter Allow", "Ip Filter Enabled" }, new ParameterListener() { public void parameterChanged(String parameterName) { markAsUpToDate(); } }); } public static IpFilter getInstance() { try{ class_mon.enter(); if(ipFilter == null) { ipFilter = new IpFilterImpl(); } return ipFilter; }finally{ class_mon.exit(); } } public File getFile() { return( FileUtil.getUserFile("filters.config")); } public void reload() throws Exception { reload(true); } public void reload(boolean allowAsyncDownloading) throws Exception { range_manager.clearAllEntries(); markAsUpToDate(); loadFilters(allowAsyncDownloading, false); } public void save() throws Exception { try{ class_mon.enter(); Map map = new HashMap(); List filters = new ArrayList(); map.put("ranges",filters); List entries = range_manager.getEntries(); Iterator iter = entries.iterator(); while(iter.hasNext()) { IpRange range = (IpRange) iter.next(); if(range.isValid() && ! range.isSessionOnly()) { String description = range.getDescription(); String startIp = range.getStartIp(); String endIp = range.getEndIp(); Map mapRange = new HashMap(); mapRange.put("description",description.getBytes( "UTF-8" )); mapRange.put("start",startIp); mapRange.put("end",endIp); filters.add(mapRange); } } FileOutputStream fos = null; try { // Open the file File filtersFile = FileUtil.getUserFile("filters.config"); fos = new FileOutputStream(filtersFile); fos.write(BEncoder.encode(map)); }finally{ if ( fos != null ){ fos.close(); } } }finally{ class_mon.exit(); } } private void loadFilters(boolean allowAsyncDownloading, boolean loadOldWhileAsyncDownloading) throws Exception { long startTime = System.currentTimeMillis(); ipFilterAutoLoader.loadOtherFilters(allowAsyncDownloading, loadOldWhileAsyncDownloading); if (getNbRanges() > 0) { Logger.log(new LogEvent(LOGID, (System.currentTimeMillis() - startTime) + "ms for " + getNbRanges() + ". now loading norm")); } try{ class_mon.enter(); List new_ipRanges = new ArrayList(1024); FileInputStream fin = null; BufferedInputStream bin = null; try { //open the file File filtersFile = FileUtil.getUserFile("filters.config"); if (filtersFile.exists()) { fin = new FileInputStream(filtersFile); bin = new BufferedInputStream(fin, 16384); Map map = BDecoder.decode(bin); List list = (List) map.get("ranges"); Iterator iter = list.listIterator(); while(iter.hasNext()) { Map range = (Map) iter.next(); String description = new String((byte[])range.get("description"), "UTF-8"); String startIp = new String((byte[])range.get("start")); String endIp = new String((byte[])range.get("end")); IpRangeImpl ipRange = new IpRangeImpl(description,startIp,endIp,false); ipRange.setAddedToRangeList(true); new_ipRanges.add( ipRange ); } } }finally{ if ( bin != null ){ try{ bin.close(); }catch( Throwable e ){ } } if ( fin != null ){ try{ fin.close(); }catch( Throwable e ){ } } Iterator it = new_ipRanges.iterator(); while( it.hasNext()){ ((IpRange)it.next()).checkValid(); } markAsUpToDate(); } }finally{ class_mon.exit(); } Logger.log(new LogEvent(LOGID, (System.currentTimeMillis() - startTime) + "ms to load all IP Filters")); } protected void loadBannedIPs() { if ( !COConfigurationManager.getBooleanParameter("Ip Filter Banning Persistent" )){ return; } try{ class_mon.enter(); Map map = FileUtil.readResilientConfigFile( "banips.config" ); List ips = (List)map.get( "ips" ); if ( ips != null ){ long now = SystemTime.getCurrentTime(); for (int i=0;i now ){ time = now; }else if ( now - time >= BAN_IP_PERSIST_TIME ){ drop = true; if (Logger.isEnabled()){ Logger.log( new LogEvent( LOGID, LogEvent.LT_INFORMATION, "Persistent ban dropped as too old : " + ip + ", " + desc)); } } if ( !drop ){ int int_ip = range_manager.addressToInt( ip ); bannedIps.put( new Integer( int_ip ), new BannedIpImpl(ip, desc, time )); } } } }catch( Throwable e ){ Debug.printStackTrace(e); }finally{ class_mon.exit(); } } protected void saveBannedIPs() { if ( !COConfigurationManager.getBooleanParameter("Ip Filter Banning Persistent" )){ return; } try{ class_mon.enter(); Map map = new HashMap(); List ips = new ArrayList(); Iterator it = bannedIps.values().iterator(); while( it.hasNext()){ BannedIpImpl bip = (BannedIpImpl)it.next(); Map entry = new HashMap(); entry.put( "ip", bip.getIp()); entry.put( "desc", bip.getTorrentName().getBytes( "UTF-8" )); entry.put( "time", new Long( bip.getBanningTime())); ips.add( entry ); } map.put( "ips", ips ); FileUtil.writeResilientConfigFile( "banips.config", map ); }catch( Throwable e ){ Debug.printStackTrace(e); }finally{ class_mon.exit(); } } public boolean isInRange( String ipAddress) { return isInRange( ipAddress, "", null ); } public boolean isInRange( String ipAddress, String torrent_name, byte[] torrent_hash ) { return( isInRange( ipAddress, torrent_name, torrent_hash, true )); } public boolean isInRange( String ipAddress, String torrent_name, byte[] torrent_hash, boolean loggable ) { //In all cases, block banned ip addresses if(isBanned(ipAddress)){ return true; } if ( !isEnabled()){ return( false ); } // never bounce the local machine (peer guardian has a range that includes it!) if ( ipAddress.equals("127.0.0.1")){ return( false ); } // don't currently support IPv6 if ( ipAddress.indexOf( ":" ) != -1 ){ return( false ); } //never block lan local addresses if( AddressUtils.isLANLocalAddress( ipAddress ) != AddressUtils.LAN_LOCAL_NO ) { return false; } boolean allow = ip_filter_allow; IpRange match = (IpRange)range_manager.isInRange( ipAddress ); if ( match == null || allow ){ IpRange explict_deny = checkExternalHandlers( torrent_hash, ipAddress ); if ( explict_deny != null ){ match = explict_deny; allow = false; } } if(match != null) { if(!allow) { // don't bounce non-public addresses (we can ban them but not filter them as they have no sensible // real filter address if ( AENetworkClassifier.categoriseAddress( ipAddress ) != AENetworkClassifier.AT_PUBLIC ){ return( false ); } if ( addBlockedIP( new BlockedIpImpl( ipAddress, match, torrent_name, loggable), torrent_hash, loggable )){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocked : " + ipAddress + ", in range : " + match)); return true; }else{ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocking Denied : " + ipAddress + ", in range : " + match)); return false; } } return false; } if( allow ){ if ( AENetworkClassifier.categoriseAddress( ipAddress ) != AENetworkClassifier.AT_PUBLIC ){ return( false ); } if ( addBlockedIP( new BlockedIpImpl(ipAddress,null, torrent_name, loggable), torrent_hash, loggable )){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocked : " + ipAddress + ", not in any range")); return true; }else{ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocking Denied : " + ipAddress + ", not in any range")); return false; } } return false; } public boolean isInRange( InetAddress ipAddress, String torrent_name, byte[] torrent_hash, boolean loggable ) { //In all cases, block banned ip addresses if(isBanned(ipAddress)){ return true; } if ( !isEnabled()){ return( false ); } // never bounce the local machine (peer guardian has a range that includes it!) if ( ipAddress.isLoopbackAddress() || ipAddress.isLinkLocalAddress() || ipAddress.isSiteLocalAddress()){ return( false ); } // don't currently support IPv6 if ( ipAddress instanceof Inet6Address ){ return( false ); } //never block lan local addresses if( AddressUtils.isLANLocalAddress( ipAddress ) != AddressUtils.LAN_LOCAL_NO ) { return false; } boolean allow = ip_filter_allow; IpRange match = (IpRange)range_manager.isInRange( ipAddress ); if ( match == null || allow ){ // get here if // match -> deny and we didn't match // match -> allow and we did match IpRange explicit_deny = checkExternalHandlers( torrent_hash, ipAddress ); if ( explicit_deny != null ){ // turn this into a denial match = explicit_deny; allow = false; } } if ( match != null ){ if(!allow) { if ( addBlockedIP( new BlockedIpImpl(ipAddress.getHostAddress(),match, torrent_name, loggable), torrent_hash, loggable )){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocked : " + ipAddress + ", in range : " + match)); return true; }else{ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocking Denied: " + ipAddress + ", in range : " + match)); return false; } } return false; } if( allow ){ if ( addBlockedIP( new BlockedIpImpl(ipAddress.getHostAddress(),null, torrent_name, loggable), torrent_hash, loggable )){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocked : " + ipAddress + ", not in any range")); return true; }else{ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Ip Blocking Denied : " + ipAddress + ", not in any range")); return false; } } return false; } protected IpRange checkExternalHandlers( byte[] torrent_hash, String address ) { if ( external_handlers.size() > 0 ){ Iterator it = external_handlers.iterator(); while( it.hasNext()){ if (((IpFilterExternalHandler)it.next()).isBlocked( torrent_hash, address )){ return( new IpRangeImpl( "External handler", address, address, true )); } } } return( null ); } protected IpRange checkExternalHandlers( byte[] torrent_hash, InetAddress address ) { if ( external_handlers.size() > 0 ){ Iterator it = external_handlers.iterator(); while( it.hasNext()){ if (((IpFilterExternalHandler)it.next()).isBlocked( torrent_hash, address )){ String ip = address.getHostAddress(); return( new IpRangeImpl( "External handler", ip, ip, true )); } } } return( null ); } private boolean addBlockedIP( BlockedIp ip, byte[] torrent_hash, boolean loggable ) { if ( torrent_hash != null ){ List listeners_ref = listeners; for (int j=0;j MAX_BLOCKS_TO_REMEMBER ) { //only "remember" the last few blocks occurrences ipsBlocked.removeFirst(); } }finally{ class_mon.exit(); } return( true ); } private boolean isBanned( InetAddress ipAddress) { try{ class_mon.enter(); int address = range_manager.addressToInt( ipAddress ); Integer i_address = new Integer( address ); return( bannedIps.get(i_address) != null ); }finally{ class_mon.exit(); } } private boolean isBanned( String ipAddress) { try{ class_mon.enter(); int address = range_manager.addressToInt( ipAddress ); Integer i_address = new Integer( address ); return( bannedIps.get(i_address) != null ); }finally{ class_mon.exit(); } } public boolean getInRangeAddressesAreAllowed() { return( ip_filter_allow ); } public void setInRangeAddressesAreAllowed( boolean b ) { COConfigurationManager.setParameter("Ip Filter Allow", b ); } /** * @return * @deprecated */ public List getIpRanges() { try{ class_mon.enter(); return new ArrayList( range_manager.getEntries() ); }finally{ class_mon.exit(); } } public IpRange[] getRanges() { try{ class_mon.enter(); List entries = range_manager.getEntries(); IpRange[] res = new IpRange[entries.size()]; entries.toArray( res ); return( res ); }finally{ class_mon.exit(); } } public IpRange createRange(boolean sessionOnly) { return ( new IpRangeImpl("","","",sessionOnly)); } public void addRange( IpRange range ) { try{ class_mon.enter(); ((IpRangeImpl)range).setAddedToRangeList(true); // we only allow the validity check to take effect once its added to // the list of all ip ranges (coz safepeer creates lots of dummy entries // during refresh and then never adds them... range.checkValid(); }finally{ class_mon.exit(); } markAsUpToDate(); } public void removeRange( IpRange range ) { try{ class_mon.enter(); ((IpRangeImpl)range).setAddedToRangeList( false ); range_manager.removeRange( range ); }finally{ class_mon.exit(); } markAsUpToDate(); } public int getNbRanges() { List entries = range_manager.getEntries(); return entries.size(); } protected void setValidOrNot( IpRange range, boolean valid ) { try{ class_mon.enter(); // this is an optimisation to deal with the way safepeer validates stuff // before adding it in if ( !range.getAddedToRangeList()){ return; } }finally{ class_mon.exit(); } if ( valid ){ range_manager.addRange( range ); }else{ range_manager.removeRange( range ); } } public int getNbIpsBlocked() { return num_ips_blocked; } public int getNbIpsBlockedAndLoggable() { return num_ips_blocked_loggable; } public boolean ban( String ipAddress, String torrent_name, boolean manual ) { // always allow manual bans through if ( !manual ){ List listeners_ref = listeners; for (int j=0;j= hit_limit ){ block_ban = true; for (long i=start;i " + res ); return( res ); }finally{ this_mon.exit(); } } public Object isInRange( InetAddress ip ) { // optimise for pretty normal case where there are no ranges if ( entries.size() == 0 ){ return( null ); } try{ this_mon.enter(); long address_long = addressToInt( ip ); if ( address_long < 0 ){ address_long += 0x100000000L; } Object res = isInRange( address_long ); // LGLogger.log( "IPAddressRangeManager: checking '" + ip + "' against " + entries.size() + "/" + merged_entries.length + " -> " + res ); return( res ); }finally{ this_mon.exit(); } } protected Object isInRange( long address_long ) { try{ this_mon.enter(); checkRebuild(); if ( mergedRanges.length == 0 ){ return( null ); } // assisted binary chop int bottom = 0; int top = mergedRanges.length-1; int current = -1; while( top >= 0 && bottom < mergedRanges.length && bottom <= top){ current = (bottom+top)/2; IpRange e = mergedRanges[current]; long this_start = e.getStartIpLong(); long this_end = e.getMergedEndLong(); if ( address_long == this_start ){ break; }else if ( address_long > this_start ){ if ( address_long <= this_end ){ break; } // lies to the right of this entry bottom = current + 1; }else if ( address_long == this_end ){ break; }else{ // < this_end if ( address_long >= this_start ){ break; } top = current - 1; } } if ( top >= 0 && bottom < mergedRanges.length && bottom <= top ){ IpRange e = mergedRanges[current]; if ( address_long <= e.getEndIpLong()){ return( e ); } IpRange[] merged = e.getMergedEntries(); if ( merged == null ){ Debug.out( "IPAddressRangeManager: inconsistent merged details - no entries" ); return( null ); } for (int i=0;i= address_long ){ return( me ); } } Debug.out( "IPAddressRangeManager: inconsistent merged details - entry not found" ); } return( null ); }finally{ this_mon.exit(); } } protected int addressToInt( String address ) { try{ return( PRHelpers.addressToInt( address )); }catch( UnknownHostException e ){ return( UnresolvableHostManager.getPseudoAddress( address )); } } protected int addressToInt( InetAddress address ) { return( PRHelpers.addressToInt( address )); } protected void checkRebuild() { try{ this_mon.enter(); if ( rebuild_required ){ // with substantial numbers of filters (e.g. 80,000) rebuilding // is a slow process. Therefore prevent frequent rebuilds at the // cost of delaying the effect of the change long now = SystemTime.getCurrentTime(); long secs_since_last_build = (now - last_rebuild_time)/1000; // allow one second per 2000 entries if ( secs_since_last_build > entries.size()/2000 ){ last_rebuild_time = now; rebuild_required = false; rebuild(); } } }finally{ this_mon.exit(); } } protected void rebuild() { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "IPAddressRangeManager: rebuilding " + entries.size() + " entries starts")); IpRange[] ents = new IpRange[entries.size()]; entries.toArray(ents); for (int i=0;i= e2.getStartIpLong()){ e2.setMerged(); if ( e2.getEndIpLong() > end_pos ){ entry.setMergedEnd( e2.getEndIpLong() ); entry.addMergedEntry( e2 ); } }else{ break; } } } } /* for (int i=0;i 0) { return 1; } if (diff < 0) { return -1; } return 0; } protected long getTotalSpan() { checkRebuild(); return( total_span ); } public static void main( String[] args ) { IPAddressRangeManager manager = new IPAddressRangeManager(); /* Object[] testBlockIPs1 = { new String[] { "1", "3.1.1.1", "3.1.1.2" }, new String[] { "2", "3.1.1.1", "3.1.1.3" }, new String[] { "3", "1.1.1.1", "2.2.2.2", "2" }, new String[] { "4", "0.1.1.1", "2.2.2.2", "3" }, new String[] { "5", "1.1.1.1", "1.2.2.2" }, new String[] { "6", "7.7.7.7", "7.7.8.7" }, new String[] { "7", "8.8.8.8", "8.8.8.8" }, //new String[] {"8","0.0.0.0", "255.255.255.255"}, new String[] { "9", "5.5.5.5", "6.6.6.9" }, new String[] { "10", "6.6.6.6", "7.7.0.0" }, new String[] { "11", "254.6.6.6", "254.7.0.0" } }; Object[] testBlockIPs2 = { new String[] { "1", "0.0.0.1", "60.0.0.0" }, new String[] { "2", "60.0.0.2", "119.255.255.255" }, new String[] { "2a", "60.0.0.2", "119.255.255.255" }, new String[] { "3", "120.0.0.1", "180.0.0.0" }, new String[] { "4", "180.0.0.0", "255.255.255.255" } }; Object[] testBlockIPs = testBlockIPs2; for (int i = 0; i < testBlockIPs.length; i++) { String[] ip = (String[]) testBlockIPs[i]; if (ip == null) continue; manager.addRange(new IpRangeImpl(ip[0], ip[1], ip[2], true)); } System.out.println( "inRange -> " + manager.isInRange( "254.6.6.8" )); String [] testIPs = { "60.0.0.0", "60.0.0.1", "60.0.0.2", "60.0.0.3", "119.255.255.254", "119.255.255.255", "120.0.0.0", "120.0.0.1", "120.0.0.2", "179.255.255.255", "180.0.0.0", "180.0.0.1" }; for (int i = 0; i < testIPs.length; i++) { String string = testIPs[i]; System.out.println(string + " InRange? " + manager.isInRange(string)); } System.out.println( "Total span = " + manager.getTotalSpan()); */ Random r = new Random(); for (int i=0;i<1000000;i++){ int ip1 = r.nextInt( 0x0fffffff ); int ip2 = ip1 + r.nextInt( 255 ); String start = PRHelpers.intToAddress( ip1 ); String end = PRHelpers.intToAddress( ip2 ); manager.addRange( new IpRangeImpl("test_" + i, start, end, true )); } /* for (int i=0;i<100000;i++){ int start = (int)(Math.random() * 0xfffff000); int end = start + (int)(Math.random()*5000); manager.addRange( start, end, new Object()); } */ int num = 0; int hits = 0; while(true){ if ( num % 1000 == 0 ){ System.out.println( num + "/" + hits ); } num++; int ip = r.nextInt(); Object res = manager.isInRange( ip ); if ( res != null ){ hits++; } } } public ArrayList getEntries() { return entries; } public void clearAllEntries() { try{ this_mon.enter(); entries.clear(); IpFilterManagerFactory.getSingleton().deleteAllDescriptions(); rebuild_required = true; }finally{ this_mon.exit(); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/impl/IpFilterAutoLoaderImpl.java0000644000175000017500000004057410631270746027152 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.ipfilter.impl; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.ipfilter.IpRange; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderAdapter; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException; import org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader.ResourceDownloaderFactoryImpl; /** * @author TuxPaper * @created Jun 5, 2007 * */ public class IpFilterAutoLoaderImpl { private static final LogIDs LOGID = LogIDs.CORE; public static final String CFG_AUTOLOAD_LAST = "Ip Filter Autoload Last Date"; public static final String CFG_AUTOLOAD_FILE = "Ip Filter Autoload File"; private static AEMonitor class_mon = new AEMonitor( "IpFilterAutoLoaderImpl:class"); private Object timerEventFilterReload; private final IpFilterImpl ipFilter; public IpFilterAutoLoaderImpl(IpFilterImpl ipFilter) { this.ipFilter = ipFilter; COConfigurationManager.setLongDefault(CFG_AUTOLOAD_LAST, 0); COConfigurationManager.setStringDefault(CFG_AUTOLOAD_FILE, ""); } /** * Load dat filter as specified at http://wiki.phoenixlabs.org/wiki/DAT_Format * @param fin * @throws Exception * * @since 3.0.1.5 */ private void loadDATFilters(InputStream fin) { try { class_mon.enter(); List new_ipRanges = new ArrayList(1024); InputStreamReader streamReader = null; BufferedReader reader = null; try { Pattern pattern = Pattern.compile("^(.*):([0-9\\.]+)[^0-9]+([0-9\\.]+).*"); int parseMode = -1; //open the file // TODO: test charset fallback (should fallback to ascii) streamReader = new InputStreamReader(fin, "utf8"); reader = new BufferedReader(streamReader); int numConsecutiveUnknowns = 0; while (numConsecutiveUnknowns < 1000) { String line = reader.readLine(); //System.out.println("line=" + line); if (line == null) { break; } line = line.trim(); if (line.startsWith("#") || line.length() == 0) { continue; } String description = ""; String startIp = null; String endIp = null; int level = 0; if (parseMode <= 0 || parseMode == 1) { Matcher matcher = pattern.matcher(line); if (matcher.find()) { if (parseMode != 1) { parseMode = 1; } description = matcher.group(1); startIp = matcher.group(2); endIp = matcher.group(3); } else { Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "unrecognized line while reading ip filter: " + line)); } } if (parseMode != 1) { if (parseMode != 2) { parseMode = 2; } // spec says: // 1.1.1.1, 1.1.1.2, 100, moo // but I've seen dash format, such as // 1.1.1.1 - 1.1.1.2, 100, moo // so for both String[] sections = line.split(" *[-,] *", 4); if (sections.length >= 2) { if (sections[0].indexOf('.') < 0 || sections[1].indexOf('.') < 0 || sections[0].length() > 15 || sections[1].length() > 15 || sections[0].length() < 7 || sections[1].length() < 7) { numConsecutiveUnknowns++; continue; } } if (sections.length >= 4) { // simple format: // startip, endip, level, desc startIp = sections[0]; endIp = sections[1]; description = sections[3]; try { level = Integer.parseInt(sections[2]); } catch (NumberFormatException e) { description = sections[2] + " " + description; } for (int i = 4; i < sections.length; i++) { description += " " + sections[i]; } numConsecutiveUnknowns = 0; } else if (sections.length == 3) { startIp = sections[0]; endIp = sections[1]; description = sections[2]; numConsecutiveUnknowns = 0; } else if (sections.length == 2) { startIp = sections[0]; endIp = sections[1]; numConsecutiveUnknowns = 0; } else { numConsecutiveUnknowns++; continue; } if (level >= 128) { continue; } } if (startIp == null || endIp == null) { continue; } IpRangeImpl ipRange = new IpRangeImpl(description, startIp, endIp, true); //System.out.println(parseMode + ":" + description + ";" + ipRange.getStartIp()); ipRange.setAddedToRangeList(true); new_ipRanges.add(ipRange); } } catch (IOException e) { Debug.out(e); } finally { if (reader != null) { try { reader.close(); } catch (Throwable e) { } } if (streamReader != null) { try { streamReader.close(); } catch (Throwable e) { } } Iterator it = new_ipRanges.iterator(); while (it.hasNext()) { ((IpRange) it.next()).checkValid(); } ipFilter.markAsUpToDate(); } } finally { class_mon.exit(); } } private int getP2BFileVersion(InputStream is) { try { // first 4 are 255 for (int i = 0; i < 4; i++) { int byteRead = is.read(); if (byteRead != 255) { return -1; } } // next 'P2B' byte[] MAGIC = new byte[] { 'P', '2', 'B' }; for (int i = 0; i < MAGIC.length; i++) { byte b = MAGIC[i]; if (b != is.read()) { return -1; } } // next: version no int p2bVersion = is.read(); Logger.log(new LogEvent(LOGID, "Log Filter: loading p2b version " + p2bVersion)); return p2bVersion; } catch (IOException e) { Debug.out(e); } return -1; } protected void loadOtherFilters(boolean allowAsyncDownloading, boolean loadOldWhileAsyncDownloading) { int p2bVersion = -1; try { class_mon.enter(); List new_ipRanges = new ArrayList(1024); InputStream fin = null; BufferedInputStream bin = null; boolean isURL = false; try { //open the file String file = COConfigurationManager.getStringParameter(CFG_AUTOLOAD_FILE); Logger.log(new LogEvent(LOGID, "IP Filter file: " + file)); File filtersFile = new File(file); if (filtersFile.exists()) { isURL = false; } else { if (!UrlUtils.isURL(file)) { return; } isURL = true; filtersFile = FileUtil.getUserFile("ipfilter.dl"); if (filtersFile.exists()) { if (allowAsyncDownloading) { Logger.log(new LogEvent(LOGID, "Downloading " + file + " async")); downloadFiltersAsync(new URL(file)); if (!loadOldWhileAsyncDownloading) { return; } } } else { // no old dl, download sync now Logger.log(new LogEvent(LOGID, "sync Downloading " + file)); try { ResourceDownloader rd = ResourceDownloaderFactoryImpl.getSingleton().create( new URL(file)); fin = rd.download(); FileUtil.copyFile(fin, filtersFile); setNextAutoDownload(true); } catch (ResourceDownloaderException e) { return; } } } fin = new FileInputStream(filtersFile); bin = new BufferedInputStream(fin, 16384); // extract (g)zip'd file and open that byte[] headerBytes = new byte[2]; bin.mark(3); bin.read(headerBytes, 0, 2); bin.reset(); if (headerBytes[1] == (byte) 0x8b && headerBytes[0] == 0x1f) { GZIPInputStream gzip = new GZIPInputStream(bin); filtersFile = FileUtil.getUserFile("ipfilter.ext"); FileUtil.copyFile(gzip, filtersFile); fin = new FileInputStream(filtersFile); bin = new BufferedInputStream(fin, 16384); } else if (headerBytes[0] == 0x50 && headerBytes[1] == 0x4b) { ZipInputStream zip = new ZipInputStream(bin); ZipEntry zipEntry = zip.getNextEntry(); // Skip small files while (zipEntry != null && zipEntry.getSize() < 1024 * 1024) { zipEntry = zip.getNextEntry(); } if (zipEntry == null) { return; } filtersFile = FileUtil.getUserFile("ipfilter.ext"); FileUtil.copyFile(zip, filtersFile); fin = new FileInputStream(filtersFile); bin = new BufferedInputStream(fin, 16384); } bin.mark(8); p2bVersion = getP2BFileVersion(bin); if (p2bVersion < 1 || p2bVersion > 3) { bin.reset(); loadDATFilters(bin); return; } byte[] descBytes = new byte[255]; byte[] ipBytes = new byte[4]; String encoding = p2bVersion == 1 ? "ISO-8859-1" : "UTF-8"; if (p2bVersion == 1 || p2bVersion == 2) { while (true) { String description = readString(bin, descBytes, encoding); int read = bin.read(ipBytes); if (read < 4) { break; } int startIp = ByteFormatter.byteArrayToInt(ipBytes); read = bin.read(ipBytes); if (read < 4) { break; } int endIp = ByteFormatter.byteArrayToInt(ipBytes); IpRangeImpl ipRange = new IpRangeImpl(description, startIp, endIp, true); ipRange.setAddedToRangeList(true); new_ipRanges.add(ipRange); } } else { // version 3 int read = bin.read(ipBytes); if (read < 4) { return; } int numDescs = ByteFormatter.byteArrayToInt(ipBytes); String[] descs = new String[numDescs]; for (int i = 0; i < numDescs; i++) { descs[i] = readString(bin, descBytes, encoding); } read = bin.read(ipBytes); if (read < 4) { return; } int numRanges = ByteFormatter.byteArrayToInt(ipBytes); for (int i = 0; i < numRanges; i++) { read = bin.read(ipBytes); if (read < 4) { return; } int descIdx = ByteFormatter.byteArrayToInt(ipBytes); read = bin.read(ipBytes); if (read < 4) { return; } int startIp = ByteFormatter.byteArrayToInt(ipBytes); read = bin.read(ipBytes); if (read < 4) { return; } int endIp = ByteFormatter.byteArrayToInt(ipBytes); String description = descIdx < descs.length && descIdx >= 0 ? descs[descIdx] : ""; IpRangeImpl ipRange = new IpRangeImpl(description, startIp, endIp, true); ipRange.setAddedToRangeList(true); new_ipRanges.add(ipRange); } } } catch (IOException e) { Debug.out(e); } finally { if (bin != null) { try { bin.close(); } catch (Throwable e) { } } if (fin != null) { try { fin.close(); } catch (Throwable e) { } } Iterator it = new_ipRanges.iterator(); while (it.hasNext()) { ((IpRange) it.next()).checkValid(); } ipFilter.markAsUpToDate(); if (!isURL) { setFileReloadTimer(); } } } finally { class_mon.exit(); } } /** * * * @since 3.0.1.5 */ private void setFileReloadTimer() { if (timerEventFilterReload instanceof TimerEvent) { ((TimerEvent) timerEventFilterReload).cancel(); } else if (timerEventFilterReload instanceof TimerEventPeriodic) { ((TimerEventPeriodic) timerEventFilterReload).cancel(); } timerEventFilterReload = SimpleTimer.addPeriodicEvent("IP Filter download", 60000, new TimerEventPerformer() { long lastFileModified; public void perform(TimerEvent event) { event.cancel(); String file = COConfigurationManager.getStringParameter(CFG_AUTOLOAD_FILE); File filtersFile = new File(file); if (!filtersFile.exists()) { return; } long fileModified = filtersFile.lastModified(); if (lastFileModified == 0) { lastFileModified = fileModified; } else if (lastFileModified != fileModified) { try { // reload will create a new periodic time ipFilter.reload(); } catch (Exception e) { } } } }); } /** * @param url * * @since 3.0.1.5 */ private void downloadFiltersAsync(URL url) { ResourceDownloader rd = ResourceDownloaderFactoryImpl.getSingleton().create( url); // old dl exists, load old one while new one downloads async rd.addListener(new ResourceDownloaderAdapter() { // @see org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderAdapter#reportPercentComplete(org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader, int) public void reportPercentComplete(ResourceDownloader downloader, int percentage) { } public boolean completed(ResourceDownloader downloader, InputStream data) { try { setNextAutoDownload(true); Logger.log(new LogEvent(LOGID, "downloaded..waiting")); // since this is a different thread, we can use class_mon as // a cheap semaphore to wait until previous load completes class_mon.enter(); Logger.log(new LogEvent(LOGID, "downloaded.. copying")); try { FileUtil.copyFile(data, FileUtil.getUserFile("ipfilter.dl")); AEThread thread = new AEThread("reload ipfilters", true) { public void runSupport() { try { UIFunctions uif = UIFunctionsManager.getUIFunctions(); if (uif != null) { uif.setStatusText("Reloading Filters.."); } ipFilter.reload(false); if (uif != null) { uif.setStatusText(null); } } catch (Exception e) { Debug.out(e); } } }; thread.setPriority(Thread.NORM_PRIORITY - 1); thread.start(); } catch (Exception e) { Debug.out(e); } } finally { class_mon.exit(); } return true; } }); rd.asyncDownload(); } public void setNextAutoDownload(boolean updateLastDownloadedDate) { long now = SystemTime.getCurrentTime(); long lastDL; if (updateLastDownloadedDate) { COConfigurationManager.setParameter(CFG_AUTOLOAD_LAST, now); lastDL = now; } else { lastDL = COConfigurationManager.getLongParameter(CFG_AUTOLOAD_LAST); if (lastDL > now) { lastDL = now; COConfigurationManager.setParameter(CFG_AUTOLOAD_LAST, now); } } long nextDL = lastDL + (86400000L * 7); if (timerEventFilterReload instanceof TimerEvent) { ((TimerEvent) timerEventFilterReload).cancel(); } else if (timerEventFilterReload instanceof TimerEventPeriodic) { ((TimerEventPeriodic) timerEventFilterReload).cancel(); } timerEventFilterReload = SimpleTimer.addEvent("IP Filter download", nextDL, new TimerEventPerformer() { public void perform(TimerEvent event) { String file = COConfigurationManager.getStringParameter(CFG_AUTOLOAD_FILE); try { downloadFiltersAsync(new URL(file)); } catch (MalformedURLException e) { } } }); } /** * @param bin * @param descBytes * @param encoding * @return * * @since 3.0.1.5 */ private String readString(BufferedInputStream bin, byte[] descBytes, String encoding) { int pos = 0; try { while (true) { int byteRead = bin.read(); if (byteRead < 0) { break; } if (pos < descBytes.length) { descBytes[pos] = (byte) byteRead; pos++; } if (byteRead == 0) { break; } } } catch (IOException e) { } if (pos > 1) { try { return new String(descBytes, 0, pos - 1, encoding); } catch (UnsupportedEncodingException e) { } } return ""; } } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/impl/BlockedIpImpl.java0000644000175000017500000000337710276131172025302 0ustar adrianadrian/* * File : BlockedIpImpl.java * Created : 12 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.ipfilter.impl; import org.gudy.azureus2.core3.ipfilter.BlockedIp; import org.gudy.azureus2.core3.ipfilter.IpRange; import org.gudy.azureus2.core3.util.SystemTime; /** * @author Olivier * */ public class BlockedIpImpl implements BlockedIp { private String ip; private long time; private IpRange range; private String torrentname; private boolean loggable; public BlockedIpImpl(String ip,IpRange range, String torrent_name,boolean _loggable) { this.ip = ip; this.range = range; this.time = SystemTime.getCurrentTime(); this.torrentname = torrent_name; loggable = _loggable; } public String getBlockedIp() { return this.ip; } public IpRange getBlockingRange() { return this.range; } public long getBlockedTime() { return time; } public String getTorrentName() { return torrentname; } public boolean isLoggable() { return( loggable ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/impl/IpFilterManagerImpl.java0000644000175000017500000001316510734653610026460 0ustar adrianadrian/* * Created on 19-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.ipfilter.impl; /** * @author parg * */ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.ipfilter.BadIps; import org.gudy.azureus2.core3.ipfilter.IpFilter; import org.gudy.azureus2.core3.ipfilter.IpFilterManager; import org.gudy.azureus2.core3.ipfilter.IpRange; import org.gudy.azureus2.core3.util.FileUtil; public class IpFilterManagerImpl implements IpFilterManager, ParameterListener { protected static IpFilterManagerImpl singleton = new IpFilterManagerImpl(); private RandomAccessFile rafDescriptions = null; /** * */ public IpFilterManagerImpl() { COConfigurationManager.addAndFireParameterListener( "Ip Filter Enable Description Cache", this); } public Object addDescription(IpRange range, byte[] description) { //if (true) return; if (rafDescriptions == null) { return null; } try { if (description == null || description.length == 0) return null; int start; int end; start = (int)rafDescriptions.getFilePointer(); int len = (int)rafDescriptions.length(); //System.out.println(len - 0x1FFFFFF); if (len + 61 >= 0x1FFFFFF) { // we could try to fit a desc < 61, but why bother.. at this point // we have at least 550,072 ranges return null; } if (start != len) { rafDescriptions.seek(len); start = (int)rafDescriptions.getFilePointer(); } // last 25: position // 26 - 31 (6, 61 chars max): len if (description.length <= 61) { rafDescriptions.write(description); } else { rafDescriptions.write(description, 0, 61); } end = (int)rafDescriptions.getFilePointer(); //System.out.println("add " + new String(description, 0, (end - start)) + "; " + start + " - " + end); int info = start + ((end - start) << 25); return new Integer(info); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public byte[] getDescription(Object info) { // if cached, info is an object array, with the first index being the descr if (info instanceof Object[]) { return (byte[])(((Object[])info)[0]); } if (rafDescriptions == null || !(info instanceof Integer)) { return "".getBytes(); } try { int posInfo = ((Integer)info).intValue(); int pos = posInfo & 0x1FFFFFF; int len = posInfo >> 25; if (len < 0) { throw new IllegalArgumentException(getClass().getName() + ": invalid posInfo [" + posInfo +"], pos [" + pos + "], len [" + len + "]"); } if (rafDescriptions.getFilePointer() != pos) { rafDescriptions.seek(pos); } byte[] bytes = new byte[len]; rafDescriptions.read(bytes); return bytes; } catch (IOException e) { return "".getBytes(); } } public void cacheAllDescriptions() { IpRange[] ranges = getIPFilter().getRanges(); for (int i = 0; i < ranges.length; i++) { Object info = ((IpRangeImpl)ranges[i]).getDescRef(); if (info instanceof Integer) { byte[] desc = getDescription(info); Object[] data = { desc, info }; ((IpRangeImpl)ranges[i]).setDescRef(data); } } } public void clearDescriptionCache() { IpRange[] ranges = getIPFilter().getRanges(); for (int i = 0; i < ranges.length; i++) { Object info = ((IpRangeImpl)ranges[i]).getDescRef(); if (info instanceof Object[]) { Integer data = (Integer)((Object[])info)[1]; ((IpRangeImpl)ranges[i]).setDescRef(data); } } } public void deleteAllDescriptions() { if (rafDescriptions != null) { try { rafDescriptions.close(); } catch (IOException e) { } rafDescriptions = null; } parameterChanged(null); } public static IpFilterManager getSingleton() { return( singleton ); } public IpFilter getIPFilter() { return( IpFilterImpl.getInstance()); } public BadIps getBadIps() { return (BadIpsImpl.getInstance()); } public void parameterChanged(String parameterName) { boolean enable = COConfigurationManager.getBooleanParameter("Ip Filter Enable Description Cache"); if (enable && rafDescriptions == null) { File fDescriptions = FileUtil.getUserFile("ipfilter.cache"); try { if (fDescriptions.exists()) { fDescriptions.delete(); } rafDescriptions = new RandomAccessFile(fDescriptions, "rw"); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else if (!enable && rafDescriptions != null) { try { rafDescriptions.close(); } catch (IOException e) { } rafDescriptions = null; } } } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/impl/tests/0000755000175000017500000000000011310377634023116 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/impl/tests/FakeTrackerResponseGenerator.java0000644000175000017500000000325210373051024031521 0ustar adrianadrian/* * Created on 30 sept. 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.ipfilter.impl.tests; /** * @author Olivier Chalouhi * */ public class FakeTrackerResponseGenerator { //This will generate a fake announce with loads of bad IPs in it. public static void main(String args[]) { String baseRange = "195.68.236."; String basePeerId = "-AZ2104-0VR73lDzLejd"; System.out.print("d8:intervali10e5:peersl"); for(int i = 100 ; i < 200 ; i++) { String iStr = "" + i; int iStrLength = iStr.length(); String ip = baseRange + iStr; String peerId = basePeerId.substring(0,20-iStrLength) + iStr; System.out.print("d2:ip" + ip.length() + ":" + ip); System.out.print("7:peer id20:" + peerId); System.out.print("4:porti3003ee"); } System.out.print("ee"); } } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/BadIp.java0000644000175000017500000000220210373051034022620 0ustar adrianadrian/* * Created on 05-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.ipfilter; /** * @author parg * */ public interface BadIp { public String getIp(); public int getNumberOfWarnings(); public long getLastTime(); } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/IpRange.java0000644000175000017500000000410110631270742023174 0ustar adrianadrian/* * File : IpRange.java * Created : 8 oct. 2003 13:02:23 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.ipfilter; /** * @author Olivier * */ public interface IpRange { public String getDescription(); public void setDescription( String str ); public boolean isValid(); public boolean isSessionOnly(); public String getStartIp(); public void setStartIp( String str ); public String getEndIp(); public void setEndIp( String str ); public void setSessionOnly( boolean sessionOnly ); public boolean isInRange(String ipAddress); public void checkValid(); public int compareStartIpTo( IpRange other ); public int compareEndIpTo( IpRange other ); public int compareDescription( IpRange other ); /** * @return */ long getEndIpLong(); /** * @return */ long getStartIpLong(); /** * @return */ public long getMergedEndLong(); /** * @return */ public IpRange[] getMergedEntries(); /** * */ public void resetMergeInfo(); /** * @return */ public boolean getMerged(); /** * */ public void setMerged(); /** * @param endIpLong */ public void setMergedEnd(long endIpLong); /** * @param e2 */ public void addMergedEntry(IpRange e2); /** * @return * * @since 3.0.1.5 */ public boolean getAddedToRangeList(); } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/BannedIp.java0000644000175000017500000000221010373051034023320 0ustar adrianadrian/* * Created on 05-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.ipfilter; /** * @author parg * */ public interface BannedIp { public String getIp(); public long getBanningTime(); public String getTorrentName(); } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/IPFilterListener.java0000644000175000017500000000236510633727370025053 0ustar adrianadrian/* * Created on 09-Aug-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.ipfilter; public interface IPFilterListener { public boolean canIPBeBanned( String ip ); public void IPBanned( BannedIp ip ); public void IPBlockedListChanged( IpFilter filter ); public boolean canIPBeBlocked( String ip, byte[] torrent_hash ); } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/IpFilter.java0000644000175000017500000000563110723262104023371 0ustar adrianadrian/* * File : IpFilter.java * Created : 1 oct. 2003 12:27:26 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.ipfilter; /** * @author Olivier * */ import java.util.List; import java.io.File; import java.net.InetAddress; public interface IpFilter { public File getFile(); public void save() throws Exception; public void reload() throws Exception; /** * deprecated and to be removed after 2.0.8.0. Left in to support old SafePeer plugin * version that uses this stuff directly... * @deprecated * @return */ public List getIpRanges(); public IpRange[] getRanges(); public boolean isInRange( String ipAddress); public boolean isInRange( String ipAddress, String torrent_name, byte[] torrent_hash ); public boolean isInRange( String ipAddress, String torrent_name, byte[] torrent_hash, boolean loggable ); public boolean isInRange( InetAddress ipAddress, String torrent_name, byte[] torrent_hash, boolean loggable ); public IpRange createRange( boolean sessionOnly); public void addRange( IpRange range ); public void removeRange( IpRange range ); public int getNbRanges(); public int getNbIpsBlocked(); public int getNbIpsBlockedAndLoggable(); public BlockedIp[] getBlockedIps(); public void clearBlockedIPs(); public boolean ban( String ipAddress, String torrent_name, boolean manual ); public void unban(String ipAddress); public void unban(String ipAddress, boolean block); public int getNbBannedIps(); public BannedIp[] getBannedIps(); public void clearBannedIps(); public boolean isEnabled(); public void setEnabled( boolean enabled ); public boolean getInRangeAddressesAreAllowed(); public void setInRangeAddressesAreAllowed( boolean b ); public void markAsUpToDate(); public long getLastUpdateTime(); public long getTotalAddressesInRange(); public void addListener( IPFilterListener l ); public void removeListener( IPFilterListener l ); public void addExternalHandler( IpFilterExternalHandler handler ); public void removeExternalHandler( IpFilterExternalHandler handler ); } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/BlockedIp.java0000644000175000017500000000211010276131172023477 0ustar adrianadrian/* * File : BlockedIp.java * Created : 12 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.ipfilter; /** * @author Olivier * */ public interface BlockedIp { public String getBlockedIp(); public long getBlockedTime(); public IpRange getBlockingRange(); public String getTorrentName(); public boolean isLoggable(); } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/BadIps.java0000644000175000017500000000221410076752256023024 0ustar adrianadrian/* * File : BadIps.java * Created : 10 nov. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.ipfilter; /** * @author Olivier * */ public interface BadIps { public abstract int addWarningForIp(String ip); public abstract int getNbWarningForIp(String ip); public abstract int getNbBadIps(); public abstract BadIp[] getBadIps(); public abstract void clearBadIps(); } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/IpFilterManagerFactory.java0000644000175000017500000000230610373051034026207 0ustar adrianadrian/* * Created on 19-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.ipfilter; /** * @author parg * */ import org.gudy.azureus2.core3.ipfilter.impl.*; public class IpFilterManagerFactory { public static IpFilterManager getSingleton() { return( IpFilterManagerImpl.getSingleton()); } } azureus-4.3.0.6/org/gudy/azureus2/core3/ipfilter/IpFilterExternalHandler.java0000644000175000017500000000041210723262104026362 0ustar adrianadrianpackage org.gudy.azureus2.core3.ipfilter; import java.net.InetAddress; public interface IpFilterExternalHandler { public boolean isBlocked( byte[] torrent_hash, String ip ); public boolean isBlocked( byte[] torrent_hash, InetAddress ip ); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/0000755000175000017500000000000011310377634020152 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/util/DebugWeakList.java0000644000175000017500000001077610537446112023520 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.lang.ref.WeakReference; import java.util.*; public class DebugWeakList { final static boolean DEBUG = Constants.isCVSVersion(); private String name; private List list; public DebugWeakList( String _name ) { name = _name; list = new ArrayList(); } public DebugWeakList( String _name, DebugWeakList l ) { name = _name; list = new ArrayList( l.list ); } public void add( Object obj ) { if ( DEBUG ){ list.add( new Object[]{ obj.getClass(), new WeakReference( obj )}); }else{ list.add( obj ); } } public void remove( Object obj ) { if ( DEBUG ){ Iterator it = list.iterator(); while( it.hasNext()){ Object[] entry = (Object[])it.next(); WeakReference wr = (WeakReference)entry[1]; Object target = wr.get(); if ( target == null ){ it.remove(); logRemoved((Class)entry[0]); }else if ( target == obj ){ it.remove(); return; } } }else{ list.remove( obj ); } } public boolean contains( Object obj ) { if ( DEBUG ){ Iterator it = list.iterator(); while( it.hasNext()){ Object[] entry = (Object[])it.next(); WeakReference wr = (WeakReference)entry[1]; Object target = wr.get(); if ( target == null ){ it.remove(); logRemoved((Class)entry[0]); }else if ( target == obj ){ return( true ); } } return( false ); }else{ return( list.contains( obj )); } } protected void logRemoved( Class cla ) { Debug.out( "Object '" + cla + "' was not removed correctly from " + name ); } public Iterator iterator() { if ( DEBUG ){ return( new WeakListIterator()); }else{ return( list.iterator()); } } public int estimatedSize() { return( list.size()); } protected class WeakListIterator implements Iterator { private Iterator it = list.iterator(); private Object pending_result; private Object last_result; public boolean hasNext() { if ( pending_result != null ){ return( true ); } while( it.hasNext()){ Object[] entry = (Object[])it.next(); WeakReference wr = (WeakReference)entry[1]; Object target = wr.get(); if ( target == null ){ it.remove(); logRemoved((Class)entry[0]); }else{ pending_result = target; return( true ); } } return( false ); } public Object next() throws NoSuchElementException { if ( pending_result == null ){ hasNext(); } if ( pending_result == null ){ throw( new NoSuchElementException()); } last_result = pending_result; pending_result = null; return( last_result ); } public void remove() { Object lr = last_result; if ( lr == null ){ throw( new NoSuchElementException()); } last_result = null; if ( pending_result == null ){ it.remove(); }else{ // has next has skipped on beyond last result, need to manually fix up... Iterator temp_it = list.iterator(); while( temp_it.hasNext()){ Object[] entry = (Object[])temp_it.next(); WeakReference wr = (WeakReference)entry[1]; Object target = wr.get(); if ( target == lr ){ it = temp_it; it.remove(); return; } } // not found (Garbage collected), nothing to do } } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/ReferenceCountedDirectByteBuffer.java0000644000175000017500000000571610560054340027347 0ustar adrianadrian/* * Created on Jan 26, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.nio.ByteBuffer; public class ReferenceCountedDirectByteBuffer extends DirectByteBuffer { private DirectByteBuffer basis; private int ref_count = 1; protected ReferenceCountedDirectByteBuffer( DirectByteBuffer _basis ) { this( _basis.getBufferInternal()); basis = _basis; } protected ReferenceCountedDirectByteBuffer( ByteBuffer _buffer ) { super( _buffer ); } public ReferenceCountedDirectByteBuffer duplicate( int offset, int length ) { ByteBuffer duplicate = getBufferInternal().duplicate(); duplicate.position( duplicate.position() + offset ); duplicate.limit( duplicate.position() + length ); ReferenceCountedDirectByteBuffer res = new ReferenceCountedDirectByteBufferDuplicate( duplicate ); return( res ); } public void incrementReferenceCount() { synchronized( this ){ ref_count++; // System.out.println( "" + this + ": rc=" + ref_count ); } } public void decrementReferenceCount() { synchronized( this ){ ref_count--; // System.out.println( "" + this + ": rc=" + ref_count ); if ( ref_count == 0 ){ basis.returnToPool(); } } } public int getReferenceCount() { return( ref_count ); } public void returnToPool() { decrementReferenceCount(); } protected class ReferenceCountedDirectByteBufferDuplicate extends ReferenceCountedDirectByteBuffer { protected ReferenceCountedDirectByteBufferDuplicate( ByteBuffer owner ) { super( owner ); incrementReferenceCount(); } public ReferenceCountedDirectByteBuffer duplicate( int offset, int length ) { Debug.out( "dup dup" ); return( null ); } public void returnToPool() { decrementReferenceCount(); } public void incrementReferenceCount() { ReferenceCountedDirectByteBuffer.this.incrementReferenceCount(); } public void decrementReferenceCount() { ReferenceCountedDirectByteBuffer.this.decrementReferenceCount(); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/BEncodingException.java0000644000175000017500000000255311012742274024524 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.io.IOException; /** * @author Aaron Grunthal * @create 09.08.2007 * * This is thrown when the BEncoder/BDecoder stumbles upon any internal error, such as malformed input * @IOException will be used if the encountered problem is of external nature (mostly IOExceptiosn themselves) */ public class BEncodingException extends IOException { public BEncodingException(){} public BEncodingException(String message) { super(message); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/LightHashSet.java0000644000175000017500000003570411157341626023356 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.util.*; /** * A lighter (on memory) hash set
      * * Advantages over HashSet: *

        *
      • Lower memory footprint *
      • Everything is stored in a single array, this might improve cache performance (not verified) *
      • Read-only operations on iterators should be concurrency-safe but they might return null values unexpectedly under concurrent modification (not verified) *
      * * Disadvantages: *
        *
      • removal is implemented with thombstone-keys, this can significantly increase the lookup time if many values are removed. Use compactify() for scrubbing *
      • entry set iterators and thus transfers to other maps are slower than compareable implementations *
      • the map does not store hashcodes and relies on either the key-objects themselves caching them (such as strings) or a fast computation of hashcodes *
      * * @author Aaron Grunthal * @create 28.11.2007 */ public class LightHashSet extends AbstractSet implements Cloneable { private static final Object THOMBSTONE = new Object(); private static final Object NULLKEY = new Object(); private static final float DEFAULT_LOAD_FACTOR = 0.75f; private static final int DEFAULT_CAPACITY = 8; public LightHashSet() { this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR); } public LightHashSet(final int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } public LightHashSet(final Collection c) { this(0); if(c instanceof LightHashSet) { final LightHashSet lightMap = (LightHashSet)c; this.size = lightMap.size; this.data = (Object[])lightMap.data.clone(); } else addAll(c); } public Object clone() { try { final LightHashMap newMap = (LightHashMap) super.clone(); newMap.data = (Object[])data.clone(); return newMap; } catch (CloneNotSupportedException e) { // should not ever happen e.printStackTrace(); throw new RuntimeException(e); } } public LightHashSet(int initialCapacity, final float loadFactor) { if (loadFactor > 1) throw new IllegalArgumentException("Load factor must not be > 1"); this.loadFactor = loadFactor; int capacity = 1; while (capacity < initialCapacity) capacity <<= 1; data = new Object[capacity]; } final float loadFactor; int size; Object[] data; public Iterator iterator() { return new HashIterator(); } private class HashIterator implements Iterator { private int nextIdx = -1; private int currentIdx = -1; private Object[] itData = data; public HashIterator() { findNext(); } private void findNext() { do nextIdx++; while (nextIdx < itData.length && (itData[nextIdx] == null || itData[nextIdx] == THOMBSTONE)); } public void remove() { if (currentIdx == -1) throw new IllegalStateException("No entry to delete, use next() first"); if (itData != data) throw new ConcurrentModificationException("removal opperation not supported as concurrent structural modification occured"); LightHashSet.this.removeForIndex(currentIdx); currentIdx = -1; } public boolean hasNext() { return nextIdx < itData.length; } public Object next() { if (!hasNext()) throw new IllegalStateException("No more entries"); currentIdx = nextIdx; findNext(); final Object key = itData[currentIdx]; return key != NULLKEY ? key : null; } } public boolean add(final Object key) { checkCapacity(1); return addInternal(key, false); } public int size() { return size; } public boolean addAll(final Collection c) { checkCapacity(c.size()); boolean changed = false; for (final Iterator it = c.iterator(); it.hasNext();) { changed |= addInternal(it.next(), true); } // compactify in case we overestimated the new size due to redundant entries //compactify(0.f); return changed; } public int capacity() { return data.length; } /** * Fetches an element which does equal() the provided object but is not necessarily the same object * @param Object to retrieve * @return an object fulfilling the equals contract or null if no such object was found in this set */ public Object get(Object key) { if(key == null) key = NULLKEY; final int idx = nonModifyingFindIndex(key); if(keysEqual(data[idx], key)) return data[idx]; return null; } private boolean addInternal(Object key, final boolean bulkAdd) { if(key == null) key = NULLKEY; final int idx = bulkAdd ? nonModifyingFindIndex(key) : findIndex(key); if (data[idx] == null || data[idx] == THOMBSTONE) { data[idx] = key; size++; return true; } return false; } public boolean remove(Object key) { if(size == 0) return false; if(key == null) key = NULLKEY; final int idx = findIndex(key); if (keysEqual(key, data[idx])) { removeForIndex(idx); return true; } return false; } private void removeForIndex(final int idx) { data[idx] = THOMBSTONE; size--; } public void clear() { size = 0; int capacity = 1; while (capacity < DEFAULT_CAPACITY) capacity <<= 1; data = new Object[capacity]; } public boolean contains(Object key) { if(size == 0) return false; if(key == null) key = NULLKEY; return keysEqual(key, data[nonModifyingFindIndex(key)]); } private final boolean keysEqual(final Object o1, final Object o2) { return o1 == o2 || (o1 != null && o2 != null && o1.hashCode() == o2.hashCode() && o1.equals(o2)); } private int findIndex(final Object keyToFind) { final int hash = keyToFind.hashCode(); /* hash ^= (hash >>> 20) ^ (hash >>> 12); * hash ^= (hash >>> 7) ^ (hash >>> 4); */ int probe = 1; int newIndex = hash & (data.length - 1); int thombStoneIndex = -1; int thombStoneCount = 0; final int thombStoneThreshold = Math.min(data.length-size, 100); // search until we find a free entry or an entry matching the key to insert while (data[newIndex] != null && !keysEqual(data[newIndex], keyToFind)) { if (data[newIndex] == THOMBSTONE) { if(thombStoneIndex == -1) thombStoneIndex = newIndex; thombStoneCount++; if(thombStoneCount * 2 > thombStoneThreshold) { compactify(0.f); thombStoneIndex = -1; probe = 0; thombStoneCount = 0; // not really necessary } } newIndex = (hash + ((probe + probe * probe) >> 1)) & (data.length - 1); probe++; } // if we didn't find an exact match then the first thombstone will do too for insert if (thombStoneIndex != -1 && !keysEqual(data[newIndex], keyToFind)) return thombStoneIndex; return newIndex; } private int nonModifyingFindIndex(final Object keyToFind) { final int hash = keyToFind.hashCode(); /* hash ^= (hash >>> 20) ^ (hash >>> 12); * hash ^= (hash >>> 7) ^ (hash >>> 4); */ int probe = 1; int newIndex = hash & (data.length - 1); int thombStoneIndex = -1; // search until we find a free entry or an entry matching the key to insert while (data[newIndex] != null && !keysEqual(data[newIndex], keyToFind) && probe < data.length) { if(data[newIndex] == THOMBSTONE && thombStoneIndex == -1) thombStoneIndex = newIndex; newIndex = (hash + ((probe + probe * probe) >> 1)) & (data.length - 1); probe++; } if (thombStoneIndex != -1 && !keysEqual(data[newIndex], keyToFind)) return thombStoneIndex; return newIndex; } private void checkCapacity(final int n) { final int currentCapacity = data.length; if ((size + n) < currentCapacity * loadFactor) return; int newCapacity = currentCapacity; do newCapacity <<= 1; while (newCapacity * loadFactor < (size + n)); adjustCapacity(newCapacity); } /** * will shrink the internal storage size to the least possible amount, * should be used after removing many entries for example * * @param compactingLoadFactor * load factor for the compacting operation. Use 0f to compact * with the load factor specified during instantiation. Use * negative values of the desired load factors to compact only * when it would reduce the storage size. */ public void compactify(float compactingLoadFactor) { int newCapacity = 1; float adjustedLoadFactor = Math.abs(compactingLoadFactor); if (adjustedLoadFactor <= 0.f || adjustedLoadFactor >= 1.f) adjustedLoadFactor = loadFactor; while (newCapacity * adjustedLoadFactor < (size+1)) newCapacity <<= 1; if(newCapacity < data.length || compactingLoadFactor >= 0.f ) adjustCapacity(newCapacity); } private void adjustCapacity(final int newSize) { final Object[] oldData = data; data = new Object[newSize]; size = 0; for (int i = 0; i < oldData.length; i++) { if (oldData[i] == null || oldData[i] == THOMBSTONE) continue; addInternal(oldData[i], true); } } static void test() { final Random rnd = new Random(); final byte[] buffer = new byte[5]; final String[] fillData = new String[(int)((1<<20) * 0.93f)]; for (int i = 0; i < fillData.length; i++) { rnd.nextBytes(buffer); fillData[i] = new String(buffer); fillData[i].hashCode(); } long time; final Set s1 = new HashSet(); final Set s2 = new LightHashSet(); System.out.println("fill:"); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) s1.add(fillData[i]); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) s2.add(fillData[i]); System.out.println(System.currentTimeMillis() - time); System.out.println("replace-fill:"); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) s1.add(fillData[i]); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) s2.add(fillData[i]); System.out.println(System.currentTimeMillis() - time); System.out.println("get:"); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) s1.contains(fillData[i]); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) s2.contains(fillData[i]); System.out.println(System.currentTimeMillis() - time); System.out.println("compactify light map"); time = System.currentTimeMillis(); ((LightHashSet) s2).compactify(0.95f); System.out.println(System.currentTimeMillis() - time); System.out.println("transfer to hashmap"); time = System.currentTimeMillis(); new HashSet(s1); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); new HashSet(s2); System.out.println(System.currentTimeMillis() - time); System.out.println("transfer to lighthashmap"); time = System.currentTimeMillis(); new LightHashSet(s1); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); new LightHashSet(s2); System.out.println(System.currentTimeMillis() - time); System.out.println("remove entry by entry"); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) s1.remove(fillData[i]); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) s2.remove(fillData[i]); System.out.println(System.currentTimeMillis() - time); } public static void main(final String[] args) { System.out.println("Call with -Xmx300m -Xcomp -server"); Thread.currentThread().setPriority(Thread.MAX_PRIORITY); // some quadratic probing math test: /* boolean[] testArr = new boolean[1<<13]; int hash = 0xc8d3 << 1; int position = hash & (testArr.length -1); int probe = 0; do { position = (hash + probe + probe * probe) & (testArr.length - 1); probe++; testArr[position] = true; } while (probe < (testArr.length>>1)); for(int i = 0;i" and // "Tracker Network Selection Default. public static final String AT_PUBLIC = "Public"; public static final String AT_I2P = "I2P"; public static final String AT_TOR = "Tor"; public static final String[] AT_NETWORKS = { AT_PUBLIC, AT_I2P, AT_TOR }; private static List listeners = new ArrayList(); public static String categoriseAddress( String str ) { int last_dot = str.lastIndexOf('.'); if ( last_dot == -1 ){ return( AT_PUBLIC ); // no idea really, treat as normal } String dom = str.substring(last_dot+1).toLowerCase(); if ( dom.equals( "i2p" )){ return( AT_I2P ); }else if ( dom.equals( "onion" )){ return( AT_TOR ); } return( AT_PUBLIC ); } public static String[] getNetworks( TOTorrent torrent, String display_name ) { // go through all the announce URL and find all networks List urls = new ArrayList(); urls.add( torrent.getAnnounceURL()); TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets(); for (int i=0;i 0 ){ String[] t_nets = new String[available_networks.size()]; available_networks.toArray( t_nets ); for (int i=0;i requests = new LinkedList(); protected List hashers = new ArrayList(); protected AESemaphore request_sem = new AESemaphore("ConcHashReqQ"); protected AESemaphore scheduler_sem = new AESemaphore("ConcHashSched"); protected AEMonitor requests_mon = new AEMonitor( "ConcurrentHasher:R" ); private static boolean friendly_hashing; static{ friendly_hashing = COConfigurationManager.getBooleanParameter( "diskmanager.friendly.hashchecking" ); COConfigurationManager.addParameterListener( "diskmanager.friendly.hashchecking", new ParameterListener() { public void parameterChanged( String str ) { friendly_hashing = COConfigurationManager.getBooleanParameter( "diskmanager.friendly.hashchecking" ); } }); } public static ConcurrentHasher getSingleton() { return( singleton ); } public static boolean concurrentHashingAvailable() { return( getSingleton().processor_num > 1 ); } protected ConcurrentHasher() { // TODO: number of processors can apparently change.... // so periodically grab num + reserve/release as necessary processor_num = Runtime.getRuntime().availableProcessors(); // just in case :P if ( processor_num <= 0 ){ processor_num = 1; } // one more that proc num seems to improve performance ;) for (int i=0;i 500 // 1MB -> 125 size = Math.min( size, max ); size = Math.max( size, min ); Thread.sleep( size ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } scheduler_sem.release(); } } }); } } }.start(); } /** * add a synchronous request - on return it will have run (or been cancelled) */ public ConcurrentHasherRequest addRequest( ByteBuffer buffer ) { return( addRequest( buffer, null, false )); } /** * Add an asynchronous request if listener supplied, sync otherwise * @param buffer * @param priority * @param listener * @param low_priorty low priority checks will cause the "friendly hashing" setting to be * taken into account * @return */ public ConcurrentHasherRequest addRequest( ByteBuffer buffer, ConcurrentHasherRequestListener listener, boolean low_priorty ) { final ConcurrentHasherRequest req = new ConcurrentHasherRequest( this, buffer, listener, low_priorty ); // get permission to run a request // test code to force synchronous checking //SHA1Hasher hasher = new SHA1Hasher(); //req.run( hasher ); scheduler_sem.reserve(); try{ requests_mon.enter(); requests.add( req ); }finally{ requests_mon.exit(); } request_sem.release(); return( req ); } public static void main( String[] args ) { /* final ConcurrentHasher hasher = ConcurrentHasher.getSingleton(); int threads = 1; final long buffer_size = 128*1024; final long loop = 1024; for (int i=0;i":last_waiter.getName()) + "] " + ms.name + " - " + ms.last_trace_key ); } } if ( busy_monitors.size() > 0 ){ diag_logger.log( " busy monitors" ); for (int i=0;i":owner.getName()) + "] " + ms.name + " - " + ms.last_trace_key ); } } if ( waiting_semaphores.size() > 0 ){ diag_logger.log( " waiting semaphores" ); for (int i=0;i":last_waiter.getName()) + "] " + ms.name + " - " + ms.last_trace_key ); } } for (int i=0;iB and somewhere else B->A // or // A(inst1) -> A(inst2) Stack stack = (Stack)tls.get(); if ( stack.size() > 64 ){ StringBuffer sb = new StringBuffer(1024); for (int i=0;i 0 ){ Debug.outNoStack( recursion_trace + "\r\n " + trace_key ); } last_trace_key = trace_key; if ( !is_monitor ){ // only add semaphores to the stack if they aren't already present. // This is because we can reserve a semaphore on one thread and // release it on another. This will grow the stack indefinitely boolean match = false; for (int i=0;i b -> c -> g // x -> y -> b -> z // stop at b because beyond this things are "protected" int earliest_common = stack.size(); int common_count = 0; for (int i=0;i= 2 ){ for (int i=0;i p2 ){ String reciprocal_log = trace_key + " / " + old_key; if ( !debug_reciprocals.contains( reciprocal_log )){ debug_reciprocals.add( reciprocal_log ); Debug.outNoStack( "AEMonSem: Reciprocal usage:\r\n" + " " + trace_key + "\r\n" + " [" + thread_name + "] " + stack_trace + "\r\n" + " " + old_key + "\r\n" + " [" + old_thread_name + "] " + old_trace ); } } } } } } } debug_traces.put( trace_key, new String[]{ thread_name, stack_trace }); // look through all the traces for an A->B and B->A } } }else{ last_trace_key = "$" + name + "$"; stack.push( this ); } }catch( Throwable e ){ try{ Debug.printStackTrace(e); }catch( Throwable f ){ } } } protected void debugExit() { try{ Stack stack = (Stack)tls.get(); if ( is_monitor ){ // skip over any sem reserves within a sync block while( stack.peek() != this ){ stack.pop(); } stack.pop(); }else{ // for semaphores we can release stuff without a matching reserve if // the semaphore has an initial value or if we have one thread releasing // a semaphore and another reserving it if ( !stack.isEmpty()){ if ( stack.peek() == this ){ stack.pop(); } } } }catch( Throwable e ){ try{ Debug.printStackTrace(e); }catch( Throwable f ){ } } } /* protected boolean trace; protected static Map trace_map = new HashMap(); public void trace( boolean _on ) { trace = _on; } protected void traceEntry() { String str = Debug.getCompressedStackTrace(); synchronized( trace_map ){ Map map = (Map)trace_map.get( name ); if ( map == null ){ map = new HashMap(); trace_map.put( name, map ); } Long l = (Long)map.get(str); if ( l == null ){ l = new Long(1); }else{ l = new Long(l.longValue()+1); } map.put(str,l); } } protected static void dumpTrace() { synchronized( trace_map ){ Iterator it = trace_map.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); System.out.println( entry.getKey()); Map map = (Map)entry.getValue(); Iterator it2 = map.entrySet().iterator(); while( it2.hasNext()){ Map.Entry entry2 = (Map.Entry)it2.next(); System.out.println( " " + entry2.getValue() + " -> " + entry2.getKey()); } } trace_map.clear(); } } */ public String getName() { return( name ); } protected static class monSemData { protected String class_name; protected int line_number; protected monSemData( String _class_name, int _line_number ) { class_name = _class_name; line_number = _line_number; } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AERunnable.java0000644000175000017500000000233710373051004022762 0ustar adrianadrian/* * Created on 23-Sep-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author parg * */ public abstract class AERunnable implements Runnable { public void run() { try{ runSupport(); }catch( Throwable e ){ DebugLight.printStackTrace(e); } } public abstract void runSupport(); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/StringInterner.java0000644000175000017500000004446411264071660024004 0ustar adrianadrian/* * Created on Jun 8, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.io.File; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.net.URL; import java.util.*; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import com.aelitis.azureus.core.util.HashCodeUtils; public class StringInterner { private static final int SCHEDULED_CLEANUP_INTERVAL = 60*1000; private static final boolean TRACE_CLEANUP = false; private static final boolean TRACE_MULTIHITS = false; private static final int IMMEDIATE_CLEANUP_TRIGGER = 2000; private static final int IMMEDIATE_CLEANUP_GOAL = 1500; private static final int SCHEDULED_CLEANUP_TRIGGER = 1500; private static final int SCHEDULED_CLEANUP_GOAL = 1000; private static final int SCHEDULED_AGING_THRESHOLD = 750; private static LightHashSet managedInterningSet = new LightHashSet(800); private static LightHashSet unmanagedInterningSet = new LightHashSet(); private static ReadWriteLock managedSetLock = new ReentrantReadWriteLock(); private final static ReferenceQueue managedRefQueue = new ReferenceQueue(); private final static ReferenceQueue unmanagedRefQueue = new ReferenceQueue(); private static final String[] COMMON_KEYS = { "src","port","prot","ip","udpport","azver","httpport","downloaded", "Content","Refresh On","path.utf-8","uploaded","completed","persistent","attributes","encoding", "azureus_properties","stats.download.added.time","networks","p1","resume data","dndflags","blocks","resume", "primaryfile","resumecomplete","data","peersources","name.utf-8","valid","torrent filename","parameters", "secrets","timesincedl","tracker_cache","filedownloaded","timesinceul","tracker_peers","trackerclientextensions","GlobalRating", "comment.utf-8","Count","String","stats.counted","Thumbnail","Plugin..DDBaseTTTorrent::sha1","type","Title", "displayname","Publisher","Creation Date","Revision Date","Content Hash","flags","stats.download.completed.time","Description", "Progressive","Content Type","QOS Class","DRM","hash","ver","id", "body","seed","eip","rid","iip","dp2","tp","orig", "dp","Quality","private","dht_backup_enable","max.uploads","filelinks","Speed Bps","cdn_properties", "sha1","ed2k","DRM Key","Plugin.aeseedingengine.attributes","initial_seed","dht_backup_requested","ta","size", "DIRECTOR PUBLISH","Plugin.azdirector.ContentMap","dateadded","bytesin","announces","status","bytesout","scrapes", "passive", }; private static final ByteArrayHashMap byte_map = new ByteArrayHashMap( COMMON_KEYS.length ); static{ try{ for (int i=0;i " + res ); return( res ); } /** * A generic interning facilty for heavyweight or frequently duplicated * Objects that have a reasonable equals() implementation.
      *
      * Important: The objects should have a limited lifespan, the interning set * used by this method is unmanaged, i.e. does not clean out old entries! * Entries without strong references are still removed. * */ public static Object internObject(Object toIntern) { if(toIntern == null) return null; Object internedItem; WeakEntry checkEntry = new WeakEntry(toIntern,unmanagedRefQueue); synchronized( unmanagedInterningSet ){ WeakEntry internedEntry = (WeakEntry) unmanagedInterningSet.get(checkEntry); if (internedEntry == null || (internedItem = (internedEntry.get())) == null) { internedItem = toIntern; if(!unmanagedInterningSet.add(checkEntry)) System.out.println("unexpected modification"); // should not happen } sanitizeLight(); } // should not happen if(!toIntern.equals(internedItem)) System.err.println("mismatch"); return internedItem; } public static String intern(String toIntern) { if(toIntern == null) return null; String internedString; WeakStringEntry checkEntry = new WeakStringEntry(toIntern); WeakStringEntry internedEntry = null; boolean hit = false; managedSetLock.readLock().lock(); try { internedEntry = (WeakStringEntry) managedInterningSet.get(checkEntry); if (internedEntry != null && (internedString = internedEntry.getString()) != null) hit = true; else { managedSetLock.readLock().unlock(); managedSetLock.writeLock().lock(); sanitize(false); // get again, weakrefs might have expired and been added by another thread concurrently internedEntry = (WeakStringEntry) managedInterningSet.get(checkEntry); if (internedEntry != null && (internedString = internedEntry.getString()) != null) hit = true; else { managedInterningSet.add(checkEntry); internedString = toIntern; } managedSetLock.readLock().lock(); managedSetLock.writeLock().unlock(); } } finally { managedSetLock.readLock().unlock(); } if(hit) { internedEntry.incHits(); checkEntry.destroy(); if(TRACE_MULTIHITS && internedEntry.hits % 10 == 0) System.out.println("multihit "+internedEntry); } return internedString; } public static byte[] internBytes(byte[] toIntern) { if(toIntern == null) return null; byte[] internedArray; WeakByteArrayEntry checkEntry = new WeakByteArrayEntry(toIntern); WeakByteArrayEntry internedEntry = null; boolean hit = false; managedSetLock.readLock().lock(); try { internedEntry = (WeakByteArrayEntry) managedInterningSet.get(checkEntry); if (internedEntry != null && (internedArray = internedEntry.getArray()) != null) hit = true; else { managedSetLock.readLock().unlock(); managedSetLock.writeLock().lock(); sanitize(false); // get again, weakrefs might have expired and been added by another thread concurrently internedEntry = (WeakByteArrayEntry) managedInterningSet.get(checkEntry); if (internedEntry != null && (internedArray = internedEntry.getArray()) != null) hit = true; else { managedInterningSet.add(checkEntry); internedArray = toIntern; } managedSetLock.readLock().lock(); managedSetLock.writeLock().unlock(); } } finally { managedSetLock.readLock().unlock(); } if (hit) { internedEntry.incHits(); checkEntry.destroy(); if (TRACE_MULTIHITS && internedEntry.hits % 10 == 0) System.out.println("multihit " + internedEntry); } // should not happen if(!Arrays.equals(toIntern, internedArray)) System.err.println("mismatch"); return internedArray; } /** * This is based on File.hashCode() and File.equals(), which can return different values for different representations of the same paths. * Thus internFile should be used with canonized Files exclusively */ public static File internFile(File toIntern) { if(toIntern == null) return null; File internedFile; WeakFileEntry checkEntry = new WeakFileEntry(toIntern); WeakFileEntry internedEntry = null; boolean hit = false; managedSetLock.readLock().lock(); try { internedEntry = (WeakFileEntry) managedInterningSet.get(checkEntry); if (internedEntry != null && (internedFile = internedEntry.getFile()) != null) hit = true; else { managedSetLock.readLock().unlock(); managedSetLock.writeLock().lock(); sanitize(false); // get again, weakrefs might have expired and been added by another thread concurrently internedEntry = (WeakFileEntry) managedInterningSet.get(checkEntry); if (internedEntry != null && (internedFile = internedEntry.getFile()) != null) hit = true; else { managedInterningSet.add(checkEntry); internedFile = toIntern; } managedSetLock.readLock().lock(); managedSetLock.writeLock().unlock(); } } finally { managedSetLock.readLock().unlock(); } if (hit) { internedEntry.incHits(); checkEntry.destroy(); if (TRACE_MULTIHITS && internedEntry.hits % 10 == 0) System.out.println("multihit " + internedEntry); } // should not happen if(!toIntern.equals(internedFile)) System.err.println("mismatch"); return internedFile; } public static URL internURL(URL toIntern) { if(toIntern == null) return null; URL internedURL; WeakURLEntry checkEntry = new WeakURLEntry(toIntern); WeakURLEntry internedEntry = null; boolean hit = false; managedSetLock.readLock().lock(); try { internedEntry = (WeakURLEntry) managedInterningSet.get(checkEntry); if (internedEntry != null && (internedURL = internedEntry.getURL()) != null) hit = true; else { managedSetLock.readLock().unlock(); managedSetLock.writeLock().lock(); sanitize(false); // get again, weakrefs might have expired and been added by another thread concurrently internedEntry = (WeakURLEntry) managedInterningSet.get(checkEntry); if (internedEntry != null && (internedURL = internedEntry.getURL()) != null) hit = true; else { managedInterningSet.add(checkEntry); internedURL = toIntern; } managedSetLock.readLock().lock(); managedSetLock.writeLock().unlock(); } } finally { managedSetLock.readLock().unlock(); } if (hit) { internedEntry.incHits(); checkEntry.destroy(); if (TRACE_MULTIHITS && internedEntry.hits % 10 == 0) System.out.println("multihit " + internedEntry); } // should not happen if(!toIntern.toExternalForm().equals(internedURL.toExternalForm())) System.err.println("mismatch"); return internedURL; } private final static Comparator savingsComp = new Comparator() { public int compare(Object o1, Object o2) { WeakWeightedEntry w1 = (WeakWeightedEntry) o1; WeakWeightedEntry w2 = (WeakWeightedEntry) o2; return w1.hits * w1.size - w2.hits * w2.size; } }; private static void sanitizeLight() { synchronized (unmanagedInterningSet) { WeakEntry ref; while((ref = (WeakEntry)(unmanagedRefQueue.poll())) != null) unmanagedInterningSet.remove(ref); unmanagedInterningSet.compactify(-1f); } } private static void sanitize(boolean scheduled) { WeakWeightedEntry ref; while ((ref = (WeakWeightedEntry) (managedRefQueue.poll())) != null) { if (!ref.isDestroyed()) { managedInterningSet.remove(ref); if (TRACE_CLEANUP && ref.hits > 30) System.out.println("queue remove:" + ref); } else {// should not happen System.err.println("double removal " + ref); } } int currentSetSize = managedInterningSet.size(); aging: { cleanup: { // unscheduled cleanup/aging only in case of emergency if (currentSetSize < IMMEDIATE_CLEANUP_TRIGGER && !scheduled) break aging; if (TRACE_CLEANUP) System.out.println("Doing cleanup " + currentSetSize); ArrayList remaining = new ArrayList(); // remove objects that aren't shared by multiple holders first (interning is useless) for (Iterator it = managedInterningSet.iterator(); it.hasNext();) { if (managedInterningSet.size() < IMMEDIATE_CLEANUP_GOAL && !scheduled) break aging; WeakWeightedEntry entry = (WeakWeightedEntry) it.next(); if (entry.hits == 0) { if (TRACE_CLEANUP) System.out.println("0-remove: " + entry); it.remove(); } else remaining.add(entry); } currentSetSize = managedInterningSet.size(); if (currentSetSize < SCHEDULED_CLEANUP_TRIGGER && scheduled) break cleanup; if (currentSetSize < IMMEDIATE_CLEANUP_GOAL && !scheduled) break aging; Collections.sort(remaining, savingsComp); // remove those objects that saved the least amount first weightedRemove: for (int i = 0; i < remaining.size(); i++) { currentSetSize = managedInterningSet.size(); if (currentSetSize < SCHEDULED_CLEANUP_GOAL && scheduled) break weightedRemove; if (currentSetSize < IMMEDIATE_CLEANUP_GOAL && !scheduled) break aging; WeakWeightedEntry entry = (WeakWeightedEntry) remaining.get(i); if (TRACE_CLEANUP) System.out.println("weighted remove: " + entry); managedInterningSet.remove(entry); } } currentSetSize = managedInterningSet.size(); if (currentSetSize < SCHEDULED_AGING_THRESHOLD && scheduled) break aging; if (currentSetSize < IMMEDIATE_CLEANUP_GOAL && !scheduled) break aging; for (Iterator it = managedInterningSet.iterator(); it.hasNext();) ((WeakWeightedEntry) it.next()).decHits(); } if (TRACE_CLEANUP && scheduled) { List weightTraceSorted = new ArrayList(managedInterningSet); Collections.sort(weightTraceSorted, savingsComp); System.out.println("Remaining elements after cleanup:"); for (Iterator it = weightTraceSorted.iterator(); it.hasNext();) System.out.println("\t" + it.next()); } if (scheduled) managedInterningSet.compactify(-1f); } private static class WeakEntry extends WeakReference { private final int hash; protected WeakEntry(Object o, ReferenceQueue q, int hash) { super(o, q); this.hash = hash; } public WeakEntry(Object o, ReferenceQueue q) { super(o, q); this.hash = o.hashCode(); } public boolean equals(Object obj) { if (this == obj) return true; if (obj instanceof WeakEntry) { Object myObj = get(); Object otherObj = ((WeakEntry) obj).get(); return myObj == null ? false : myObj.equals(otherObj); } return false; } public final int hashCode() { return hash; } } private static abstract class WeakWeightedEntry extends WeakEntry { final short size; short hits; public WeakWeightedEntry(Object o, int hash, int size) { super(o, managedRefQueue,hash); this.size = (short) (size & 0x7FFF); } public void incHits() { if (hits < Short.MAX_VALUE) hits++; } public void decHits() { if (hits > 0) hits--; } public String toString() { return this.getClass().getName().replaceAll("^.*\\..\\w+$", "") + " h=" + (int) hits + ";s=" + (int) size; } public void destroy() { hits = -1; } public boolean isDestroyed() { return hits == -1; } } private static class WeakByteArrayEntry extends WeakWeightedEntry { public WeakByteArrayEntry(byte[] array) { // byte-array object super(array, HashCodeUtils.hashCode(array), array.length + 8); } /** * override equals since byte arrays need Arrays.equals */ public boolean equals(Object obj) { if (this == obj) return true; if (obj instanceof WeakByteArrayEntry) { byte[] myArray = getArray(); byte[] otherArray = ((WeakByteArrayEntry) obj).getArray(); return myArray == null ? false : Arrays.equals(myArray, otherArray); } return false; } public byte[] getArray() { return (byte[]) get(); } public String toString() { return super.toString() + " " + (getArray() == null ? "null" : new String(getArray())); } } private static class WeakStringEntry extends WeakWeightedEntry { public WeakStringEntry(String entry) { // string object with 2 fields, char-array object super(entry, entry.hashCode(), 16 + 8 + entry.length() * 2); } public String getString() { return (String) get(); } public String toString() { return super.toString() + " " + getString(); } } private static class WeakFileEntry extends WeakWeightedEntry { public WeakFileEntry(File entry) { // file object with 2 fields, string object with 2 fields, char-array object super(entry, entry.hashCode(), 16 + 16 + 8 + entry.getPath().length() * 2); } public File getFile() { return (File) get(); } public String toString() { return super.toString() + " " + getFile(); } } private static class WeakURLEntry extends WeakWeightedEntry { public WeakURLEntry(URL entry) { // url object with 12 fields, ~4 string objects with 2 fields, 1 shared char-array object // use URL.toExternalForm().hashCode since URL.hashCode tries to resolve hostnames :( super(entry, entry.toExternalForm().hashCode(), 13 * 8 + 4 * 16 + 8 + entry.toString().length() * 2); } public URL getURL() { return (URL) get(); } /** * override equals since byte arrays need Arrays.equals */ public boolean equals(Object obj) { if (this == obj) return true; if (obj instanceof WeakURLEntry) { URL my = getURL(); URL other = ((WeakURLEntry) obj).getURL(); // use string compare as URL.equals tries to resolve hostnames return my == null ? false : my.toExternalForm().equals(other.toExternalForm()); } return false; } public String toString() { return super.toString() + " " + getURL(); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/SHA1.java0000644000175000017500000004676410666155502021533 0ustar adrianadrian/* * Created on Apr 12, 2004 * Created by Olivier Chalouhi * Modified Apr 13, 2004 by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.nio.ByteBuffer; /** * SHA-1 message digest class. */ public final class SHA1 { private int h0,h1,h2,h3,h4; private ByteBuffer finalBuffer; private ByteBuffer saveBuffer; private int s0,s1,s2,s3,s4; private long length; private long saveLength; /** * Create a new SHA-1 message digest hasher. */ public SHA1() { finalBuffer = ByteBuffer.allocate(64); finalBuffer.position(0); finalBuffer.limit(64); saveBuffer = ByteBuffer.allocate(64); saveBuffer.position(0); saveBuffer.limit(64); reset(); } final private void transform(final byte[] ar, int offset) { int w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; int a,b,c,d,e; /* * we're using direct array access instead of buffer.getInt() since it is significantly faster * combined with the chunk-fetching on direct byte buffers this is 30(direct) to 100%(heap) faster * than the previous implementation */ w0 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w1 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w2 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w3 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w4 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w5 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w6 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w7 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w8 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w9 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w10 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w11 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w12 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w13 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w14 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset++]&0xff); w15 = (ar[offset++]&0xff) << 24 | (ar[offset++]&0xff) << 16 | (ar[offset++]&0xff) << 8 | (ar[offset]&0xff); a = h0 ; b = h1 ; c = h2 ; d = h3 ; e = h4; e += ((a << 5) | ( a >>> 27)) + w0 + ((b & c) | ((~b ) & d)) + 0x5A827999 ; b = (b << 30) | (b >>> 2) ; d += ((e << 5) | ( e >>> 27)) + w1 + ((a & b) | ((~a ) & c)) + 0x5A827999 ; a = (a << 30) | (a >>> 2) ; c += ((d << 5) | ( d >>> 27)) + w2 + ((e & a) | ((~e ) & b)) + 0x5A827999 ; e = (e << 30) | (e >>> 2) ; b += ((c << 5) | ( c >>> 27)) + w3 + ((d & e) | ((~d ) & a)) + 0x5A827999 ; d = (d << 30) | (d >>> 2) ; a += ((b << 5) | ( b >>> 27)) + w4 + ((c & d) | ((~c ) & e)) + 0x5A827999 ; c = (c << 30) | (c >>> 2) ; e += ((a << 5) | ( a >>> 27)) + w5 + ((b & c) | ((~b ) & d)) + 0x5A827999 ; b = (b << 30) | (b >>> 2) ; d += ((e << 5) | ( e >>> 27)) + w6 + ((a & b) | ((~a ) & c)) + 0x5A827999 ; a = (a << 30) | (a >>> 2) ; c += ((d << 5) | ( d >>> 27)) + w7 + ((e & a) | ((~e ) & b)) + 0x5A827999 ; e = (e << 30) | (e >>> 2) ; b += ((c << 5) | ( c >>> 27)) + w8 + ((d & e) | ((~d ) & a)) + 0x5A827999 ; d = (d << 30) | (d >>> 2) ; a += ((b << 5) | ( b >>> 27)) + w9 + ((c & d) | ((~c ) & e)) + 0x5A827999 ; c = (c << 30) | (c >>> 2) ; e += ((a << 5) | ( a >>> 27)) + w10 + ((b & c) | ((~b ) & d)) + 0x5A827999 ; b = (b << 30) | (b >>> 2) ; d += ((e << 5) | ( e >>> 27)) + w11 + ((a & b) | ((~a ) & c)) + 0x5A827999 ; a = (a << 30) | (a >>> 2) ; c += ((d << 5) | ( d >>> 27)) + w12 + ((e & a) | ((~e ) & b)) + 0x5A827999 ; e = (e << 30) | (e >>> 2) ; b += ((c << 5) | ( c >>> 27)) + w13 + ((d & e) | ((~d ) & a)) + 0x5A827999 ; d = (d << 30) | (d >>> 2) ; a += ((b << 5) | ( b >>> 27)) + w14 + ((c & d) | ((~c ) & e)) + 0x5A827999 ; c = (c << 30) | (c >>> 2) ; e += ((a << 5) | ( a >>> 27)) + w15 + ((b & c) | ((~b ) & d)) + 0x5A827999 ; b = (b << 30) | (b >>> 2) ; w0 = w13 ^ w8 ^ w2 ^ w0; w0 = (w0 << 1) | (w0 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w0 + ((a & b) | ((~a ) & c)) + 0x5A827999 ; a = (a << 30) | (a >>> 2) ; w1 = w14 ^ w9 ^ w3 ^ w1; w1 = (w1 << 1) | (w1 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w1 + ((e & a) | ((~e ) & b)) + 0x5A827999 ; e = (e << 30) | (e >>> 2) ; w2 = w15 ^ w10 ^ w4 ^ w2; w2 = (w2 << 1) | (w2 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w2 + ((d & e) | ((~d ) & a)) + 0x5A827999 ; d = (d << 30) | (d >>> 2) ; w3 = w0 ^ w11 ^ w5 ^ w3; w3 = (w3 << 1) | (w3 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w3 + ((c & d) | ((~c ) & e)) + 0x5A827999 ; c = (c << 30) | (c >>> 2) ; w4 = w1 ^ w12 ^ w6 ^ w4; w4 = (w4 << 1) | (w4 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w4 + (b ^ c ^ d) + 0x6ED9EBA1 ; b = (b << 30) | (b >>> 2) ; w5 = w2 ^ w13 ^ w7 ^ w5; w5 = (w5 << 1) | (w5 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w5 + (a ^ b ^ c) + 0x6ED9EBA1 ; a = (a << 30) | (a >>> 2) ; w6 = w3 ^ w14 ^ w8 ^ w6; w6 = (w6 << 1) | (w6 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w6 + (e ^ a ^ b) + 0x6ED9EBA1 ; e = (e << 30) | (e >>> 2) ; w7 = w4 ^ w15 ^ w9 ^ w7; w7 = (w7 << 1) | (w7 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w7 + (d ^ e ^ a) + 0x6ED9EBA1 ; d = (d << 30) | (d >>> 2) ; w8 = w5 ^ w0 ^ w10 ^ w8; w8 = (w8 << 1) | (w8 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w8 + (c ^ d ^ e) + 0x6ED9EBA1 ; c = (c << 30) | (c >>> 2) ; w9 = w6 ^ w1 ^ w11 ^ w9; w9 = (w9 << 1) | (w9 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w9 + (b ^ c ^ d) + 0x6ED9EBA1 ; b = (b << 30) | (b >>> 2) ; w10 = w7 ^ w2 ^ w12 ^ w10; w10 = (w10 << 1) | (w10 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w10 + (a ^ b ^ c) + 0x6ED9EBA1 ; a = (a << 30) | (a >>> 2) ; w11 = w8 ^ w3 ^ w13 ^ w11; w11 = (w11 << 1) | (w11 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w11 + (e ^ a ^ b) + 0x6ED9EBA1 ; e = (e << 30) | (e >>> 2) ; w12 = w9 ^ w4 ^ w14 ^ w12; w12 = (w12 << 1) | (w12 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w12 + (d ^ e ^ a) + 0x6ED9EBA1 ; d = (d << 30) | (d >>> 2) ; w13 = w10 ^ w5 ^ w15 ^ w13; w13 = (w13 << 1) | (w13 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w13 + (c ^ d ^ e) + 0x6ED9EBA1 ; c = (c << 30) | (c >>> 2) ; w14 = w11 ^ w6 ^ w0 ^ w14; w14 = (w14 << 1) | (w14 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w14 + (b ^ c ^ d) + 0x6ED9EBA1 ; b = (b << 30) | (b >>> 2) ; w15 = w12 ^ w7 ^ w1 ^ w15; w15 = (w15 << 1) | (w15 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w15 + (a ^ b ^ c) + 0x6ED9EBA1 ; a = (a << 30) | (a >>> 2) ; w0 = w13 ^ w8 ^ w2 ^ w0; w0 = (w0 << 1) | (w0 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w0 + (e ^ a ^ b) + 0x6ED9EBA1 ; e = (e << 30) | (e >>> 2) ; w1 = w14 ^ w9 ^ w3 ^ w1; w1 = (w1 << 1) | (w1 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w1 + (d ^ e ^ a) + 0x6ED9EBA1 ; d = (d << 30) | (d >>> 2) ; w2 = w15 ^ w10 ^ w4 ^ w2; w2 = (w2 << 1) | (w2 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w2 + (c ^ d ^ e) + 0x6ED9EBA1 ; c = (c << 30) | (c >>> 2) ; w3 = w0 ^ w11 ^ w5 ^ w3; w3 = (w3 << 1) | (w3 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w3 + (b ^ c ^ d) + 0x6ED9EBA1 ; b = (b << 30) | (b >>> 2) ; w4 = w1 ^ w12 ^ w6 ^ w4; w4 = (w4 << 1) | (w4 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w4 + (a ^ b ^ c) + 0x6ED9EBA1 ; a = (a << 30) | (a >>> 2) ; w5 = w2 ^ w13 ^ w7 ^ w5; w5 = (w5 << 1) | (w5 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w5 + (e ^ a ^ b) + 0x6ED9EBA1 ; e = (e << 30) | (e >>> 2) ; w6 = w3 ^ w14 ^ w8 ^ w6; w6 = (w6 << 1) | (w6 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w6 + (d ^ e ^ a) + 0x6ED9EBA1 ; d = (d << 30) | (d >>> 2) ; w7 = w4 ^ w15 ^ w9 ^ w7; w7 = (w7 << 1) | (w7 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w7 + (c ^ d ^ e) + 0x6ED9EBA1 ; c = (c << 30) | (c >>> 2) ; w8 = w5 ^ w0 ^ w10 ^ w8; w8 = (w8 << 1) | (w8 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w8 + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ; b = (b << 30) | (b >>> 2) ; w9 = w6 ^ w1 ^ w11 ^ w9; w9 = (w9 << 1) | (w9 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w9 + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC ; a = (a << 30) | (a >>> 2) ; w10 = w7 ^ w2 ^ w12 ^ w10; w10 = (w10 << 1) | (w10 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w10 + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC ; e = (e << 30) | (e >>> 2) ; w11 = w8 ^ w3 ^ w13 ^ w11; w11 = (w11 << 1) | (w11 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w11 + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC ; d = (d << 30) | (d >>> 2) ; w12 = w9 ^ w4 ^ w14 ^ w12; w12 = (w12 << 1) | (w12 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w12 + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC ; c = (c << 30) | (c >>> 2) ; w13 = w10 ^ w5 ^ w15 ^ w13; w13 = (w13 << 1) | (w13 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w13 + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ; b = (b << 30) | (b >>> 2) ; w14 = w11 ^ w6 ^ w0 ^ w14; w14 = (w14 << 1) | (w14 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w14 + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC ; a = (a << 30) | (a >>> 2) ; w15 = w12 ^ w7 ^ w1 ^ w15; w15 = (w15 << 1) | (w15 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w15 + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC ; e = (e << 30) | (e >>> 2) ; w0 = w13 ^ w8 ^ w2 ^ w0; w0 = (w0 << 1) | (w0 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w0 + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC ; d = (d << 30) | (d >>> 2) ; w1 = w14 ^ w9 ^ w3 ^ w1; w1 = (w1 << 1) | (w1 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w1 + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC ; c = (c << 30) | (c >>> 2) ; w2 = w15 ^ w10 ^ w4 ^ w2; w2 = (w2 << 1) | (w2 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w2 + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ; b = (b << 30) | (b >>> 2) ; w3 = w0 ^ w11 ^ w5 ^ w3; w3 = (w3 << 1) | (w3 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w3 + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC ; a = (a << 30) | (a >>> 2) ; w4 = w1 ^ w12 ^ w6 ^ w4; w4 = (w4 << 1) | (w4 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w4 + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC ; e = (e << 30) | (e >>> 2) ; w5 = w2 ^ w13 ^ w7 ^ w5; w5 = (w5 << 1) | (w5 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w5 + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC ; d = (d << 30) | (d >>> 2) ; w6 = w3 ^ w14 ^ w8 ^ w6; w6 = (w6 << 1) | (w6 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w6 + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC ; c = (c << 30) | (c >>> 2) ; w7 = w4 ^ w15 ^ w9 ^ w7; w7 = (w7 << 1) | (w7 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w7 + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ; b = (b << 30) | (b >>> 2) ; w8 = w5 ^ w0 ^ w10 ^ w8; w8 = (w8 << 1) | (w8 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w8 + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC ; a = (a << 30) | (a >>> 2) ; w9 = w6 ^ w1 ^ w11 ^ w9; w9 = (w9 << 1) | (w9 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w9 + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC ; e = (e << 30) | (e >>> 2) ; w10 = w7 ^ w2 ^ w12 ^ w10; w10 = (w10 << 1) | (w10 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w10 + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC ; d = (d << 30) | (d >>> 2) ; w11 = w8 ^ w3 ^ w13 ^ w11; w11 = (w11 << 1) | (w11 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w11 + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC ; c = (c << 30) | (c >>> 2) ; w12 = w9 ^ w4 ^ w14 ^ w12; w12 = (w12 << 1) | (w12 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w12 + (b ^ c ^ d) + 0xCA62C1D6 ; b = (b << 30) | (b >>> 2) ; w13 = w10 ^ w5 ^ w15 ^ w13; w13 = (w13 << 1) | (w13 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w13 + (a ^ b ^ c) + 0xCA62C1D6 ; a = (a << 30) | (a >>> 2) ; w14 = w11 ^ w6 ^ w0 ^ w14; w14 = (w14 << 1) | (w14 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w14 + (e ^ a ^ b) + 0xCA62C1D6 ; e = (e << 30) | (e >>> 2) ; w15 = w12 ^ w7 ^ w1 ^ w15; w15 = (w15 << 1) | (w15 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w15 + (d ^ e ^ a) + 0xCA62C1D6 ; d = (d << 30) | (d >>> 2) ; w0 = w13 ^ w8 ^ w2 ^ w0; w0 = (w0 << 1) | (w0 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w0 + (c ^ d ^ e) + 0xCA62C1D6 ; c = (c << 30) | (c >>> 2) ; w1 = w14 ^ w9 ^ w3 ^ w1; w1 = (w1 << 1) | (w1 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w1 + (b ^ c ^ d) + 0xCA62C1D6 ; b = (b << 30) | (b >>> 2) ; w2 = w15 ^ w10 ^ w4 ^ w2; w2 = (w2 << 1) | (w2 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w2 + (a ^ b ^ c) + 0xCA62C1D6 ; a = (a << 30) | (a >>> 2) ; w3 = w0 ^ w11 ^ w5 ^ w3; w3 = (w3 << 1) | (w3 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w3 + (e ^ a ^ b) + 0xCA62C1D6 ; e = (e << 30) | (e >>> 2) ; w4 = w1 ^ w12 ^ w6 ^ w4; w4 = (w4 << 1) | (w4 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w4 + (d ^ e ^ a) + 0xCA62C1D6 ; d = (d << 30) | (d >>> 2) ; w5 = w2 ^ w13 ^ w7 ^ w5; w5 = (w5 << 1) | (w5 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w5 + (c ^ d ^ e) + 0xCA62C1D6 ; c = (c << 30) | (c >>> 2) ; w6 = w3 ^ w14 ^ w8 ^ w6; w6 = (w6 << 1) | (w6 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w6 + (b ^ c ^ d) + 0xCA62C1D6 ; b = (b << 30) | (b >>> 2) ; w7 = w4 ^ w15 ^ w9 ^ w7; w7 = (w7 << 1) | (w7 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w7 + (a ^ b ^ c) + 0xCA62C1D6 ; a = (a << 30) | (a >>> 2) ; w8 = w5 ^ w0 ^ w10 ^ w8; w8 = (w8 << 1) | (w8 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w8 + (e ^ a ^ b) + 0xCA62C1D6 ; e = (e << 30) | (e >>> 2) ; w9 = w6 ^ w1 ^ w11 ^ w9; w9 = (w9 << 1) | (w9 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w9 + (d ^ e ^ a) + 0xCA62C1D6 ; d = (d << 30) | (d >>> 2) ; w10 = w7 ^ w2 ^ w12 ^ w10; w10 = (w10 << 1) | (w10 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w10 + (c ^ d ^ e) + 0xCA62C1D6 ; c = (c << 30) | (c >>> 2) ; w11 = w8 ^ w3 ^ w13 ^ w11; w11 = (w11 << 1) | (w11 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w11 + (b ^ c ^ d) + 0xCA62C1D6 ; b = (b << 30) | (b >>> 2) ; w12 = w9 ^ w4 ^ w14 ^ w12; w12 = (w12 << 1) | (w12 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w12 + (a ^ b ^ c) + 0xCA62C1D6 ; a = (a << 30) | (a >>> 2) ; w13 = w10 ^ w5 ^ w15 ^ w13; w13 = (w13 << 1) | (w13 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w13 + (e ^ a ^ b) + 0xCA62C1D6 ; e = (e << 30) | (e >>> 2) ; w14 = w11 ^ w6 ^ w0 ^ w14; w14 = (w14 << 1) | (w14 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w14 + (d ^ e ^ a) + 0xCA62C1D6 ; d = (d << 30) | (d >>> 2) ; w15 = w12 ^ w7 ^ w1 ^ w15; w15 = (w15 << 1) | (w15 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w15 + (c ^ d ^ e) + 0xCA62C1D6 ; c = (c << 30) | (c >>> 2) ; h0 += a; h1 += b; h2 += c; h3 += d; h4 += e; } private void completeFinalBuffer(ByteBuffer buffer) { if(finalBuffer.position() == 0) return; while(buffer.remaining() > 0 && finalBuffer.remaining() > 0) { finalBuffer.put(buffer.get()); } if(finalBuffer.remaining() == 0) { transform(finalBuffer.array(),0); finalBuffer.rewind(); } } /** * Resets the SHA-1 to initial state for a new message digest calculation. * Must be called before starting a new hash calculation. */ public void reset() { h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; h4 = 0xC3D2E1F0; length = 0; finalBuffer.clear(); } // must be a multiple of 64 private static final int cacheSize = 4*1024; // cache block to reduce expensive native access for direct byte buffers private byte[] cacheBlock; /** * Starts or continues a SHA-1 message digest calculation. * Only the remaining bytes of the given ByteBuffer are used. * @param buffer input data */ public void update(ByteBuffer buffer) { length += buffer.remaining(); //Save current position to leave given buffer unchanged int position = buffer.position(); //Complete the final buffer if needed completeFinalBuffer(buffer); if(!buffer.hasArray() || buffer.isDirect()) { if(cacheBlock == null) // only allocate if we process direct byte buffers cacheBlock = new byte[cacheSize]; while(buffer.remaining() >= 64) { int toProcess = Math.min(buffer.remaining()-buffer.remaining()%64,cacheSize); buffer.get(cacheBlock, 0, toProcess); for(int i = 0;i < toProcess; i+=64) transform(cacheBlock,i); } } else // use direct array access for heap buffers { final int endPos = buffer.position()+buffer.remaining()-buffer.remaining()%64; final int internalEndPos = endPos+buffer.arrayOffset(); for(int i = buffer.arrayOffset()+buffer.position();i < internalEndPos;i+=64) transform(buffer.array(),i); buffer.position(endPos); } if(buffer.remaining() != 0) { finalBuffer.put(buffer); } buffer.position(position); } /** * Finishes the SHA-1 message digest calculation. * @return 20-byte hash result */ public byte[] digest() { byte[] result = new byte[20]; finalBuffer.put((byte)0x80); if(finalBuffer.remaining() < 8) { while(finalBuffer.remaining() > 0) { finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer.array(),0); finalBuffer.position(0); } while(finalBuffer.remaining() > 8) { finalBuffer.put((byte)0); } finalBuffer.putLong(length << 3); finalBuffer.position(0); transform(finalBuffer.array(),0); finalBuffer.position(0); finalBuffer.putInt(h0); finalBuffer.putInt(h1); finalBuffer.putInt(h2); finalBuffer.putInt(h3); finalBuffer.putInt(h4); finalBuffer.rewind(); finalBuffer.get(result, 0, 20); return result; } /** * Finishes the SHA-1 message digest calculation, by first performing a final update * from the given input buffer, then completing the calculation as with digest(). * @param buffer input data * @return 20-byte hash result */ public byte[] digest(ByteBuffer buffer) { update( buffer ); return digest(); } /** * Save the current digest state. * This allows the resuming of a SHA-1 calculation, even after a digest calculation * is finished with digest(). */ public void saveState() { s0=h0; s1=h1; s2=h2; s3=h3; s4=h4; saveLength = length; int position = finalBuffer.position(); finalBuffer.rewind(); finalBuffer.limit(position); saveBuffer.clear(); saveBuffer.put(finalBuffer); saveBuffer.flip(); finalBuffer.limit(64); finalBuffer.position( position ); } /** * Restore the digest to its previously-saved state. */ public void restoreState() { h0=s0; h1=s1; h2=s2; h3=s3; h4=s4; length = saveLength; finalBuffer.clear(); finalBuffer.put(saveBuffer); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/MD4Hasher.java0000644000175000017500000000332010373051004022516 0ustar adrianadrian/* * Created on 08-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.security.*; public class MD4Hasher { protected MessageDigest md4; /** * Uses bouncy castle provider * */ public MD4Hasher() { try{ md4 = MessageDigest.getInstance("MD4", "BC"); }catch( Throwable e ){ // should never get here Debug.printStackTrace( e ); } } public void reset() { md4.reset(); } public void update( byte[] data, int pos, int len ) { md4.update( data, pos, len ); } public void update( byte[] data ) { update( data, 0, data.length ); } public byte[] getDigest() { return( md4.digest()); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/ByteEncodedKeyHashMap.java0000644000175000017500000000215411232006330025100 0ustar adrianadrian/* * File : ByteEncodedKeyMap.java * Created : 31-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author parg */ import java.util.HashMap; import java.util.Map; public class ByteEncodedKeyHashMap extends HashMap { public ByteEncodedKeyHashMap() { super(); } public ByteEncodedKeyHashMap( Map map ) { super( map ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AEDiagnostics.java0000644000175000017500000003454111305665622023502 0ustar adrianadrian/* * Created on 22-Sep-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import com.aelitis.azureus.core.util.AEThreadMonitor; import com.aelitis.azureus.core.util.Java15Utils; /** * @author parg * */ import java.io.*; import java.lang.reflect.Method; import java.util.*; public class AEDiagnostics { // these can not be set true and have a usable AZ! public static final boolean ALWAYS_PASS_HASH_CHECKS = false; public static final boolean USE_DUMMY_FILE_DATA = false; public static final boolean CHECK_DUMMY_FILE_DATA = false; // these can safely be set true, things will work just slower public static final boolean DEBUG_MONITOR_SEM_USAGE = false; public static final boolean DEBUG_THREADS = true; // Leave this on by default for the moment public static final boolean TRACE_DIRECT_BYTE_BUFFERS = false; public static final boolean TRACE_DBB_POOL_USAGE = false; public static final boolean PRINT_DBB_POOL_USAGE = false; public static final boolean TRACE_TCP_TRANSPORT_STATS = false; public static final boolean TRACE_CONNECTION_DROPS = false; static{ if ( ALWAYS_PASS_HASH_CHECKS ){ System.out.println( "**** Always passing hash checks ****" ); } if ( USE_DUMMY_FILE_DATA ){ System.out.println( "**** Using dummy file data ****" ); } if ( CHECK_DUMMY_FILE_DATA ){ System.out.println( "**** Checking dummy file data ****" ); } if ( DEBUG_MONITOR_SEM_USAGE ){ System.out.println( "**** AEMonitor/AESemaphore debug on ****" ); } if ( TRACE_DIRECT_BYTE_BUFFERS ){ System.out.println( "**** DirectByteBuffer tracing on ****" ); } if ( TRACE_DBB_POOL_USAGE ){ System.out.println( "**** DirectByteBufferPool tracing on ****" ); } if ( PRINT_DBB_POOL_USAGE ){ System.out.println( "**** DirectByteBufferPool printing on ****" ); } if ( TRACE_TCP_TRANSPORT_STATS ){ System.out.println( "**** TCP_TRANSPORT_STATS tracing on ****" ); } int maxFileSize = 256 * 1024; try { String logSize = System.getProperty("diag.logsize", null); if (logSize != null) { if (logSize.toLowerCase().endsWith("m")) { maxFileSize = Integer.parseInt(logSize.substring(0, logSize.length() - 1)) * 1024 * 1024; } else { maxFileSize = Integer.parseInt(logSize); } } } catch (Throwable t) { } MAX_FILE_SIZE = maxFileSize; } private static final int MAX_FILE_SIZE; // get two of these per logger type private static final String CONFIG_KEY = "diagnostics.tidy_close"; private static File debug_dir; private static File debug_save_dir; private static boolean started_up; private static boolean startup_complete; private static boolean enable_pending_writes; private static Map loggers = new HashMap(); protected static boolean logging_enabled; protected static boolean loggers_enabled; private static List evidence_generators = new ArrayList(); public static synchronized void startup( boolean _enable_pending ) { if ( started_up ){ return; } started_up = true; enable_pending_writes = _enable_pending; try{ // Minimize risk of loading to much when in transitory startup mode boolean transitoryStartup = System.getProperty("transitory.startup", "0").equals("1"); if ( transitoryStartup ){ // no xxx_?.log logging for you! loggers_enabled = false; // skip tidy check and more! return; } debug_dir = FileUtil.getUserFile( "logs" ); debug_save_dir = new File( debug_dir, "save" ); COConfigurationManager.addAndFireParameterListeners( new String[]{ "Logger.Enabled", "Logger.DebugFiles.Enabled", }, new ParameterListener() { public void parameterChanged( String parameterName) { logging_enabled = COConfigurationManager.getBooleanParameter( "Logger.Enabled" ); loggers_enabled = logging_enabled && COConfigurationManager.getBooleanParameter( "Logger.DebugFiles.Enabled"); if ( !loggers_enabled ){ loggers_enabled = Constants.IS_CVS_VERSION || COConfigurationManager.getBooleanParameter( "Logger.DebugFiles.Enabled.Force" ); } } }); boolean was_tidy = COConfigurationManager.getBooleanParameter( CONFIG_KEY ); new AEThread2( "asyncify", true ) { public void run() { SimpleTimer.addEvent("AEDiagnostics:logCleaner",SystemTime.getCurrentTime() + 60000 + (int) (Math.random() * 15000), new TimerEventPerformer() { public void perform(TimerEvent event) { cleanOldLogs(); } }); } }.start(); if ( debug_dir.exists()){ long now = SystemTime.getCurrentTime(); File[] files = debug_dir.listFiles(); if ( files != null ){ boolean file_copied = false; for (int i=0;i 10 * 24 * 60 * 60 * 1000L) { file.delete(); } } } } } catch (Exception e) { } } public static boolean isStartupComplete() { return( startup_complete ); } public static File getLogDir() { startup( false ); return( debug_dir ); } public static synchronized void flushPendingLogs() { for ( AEDiagnosticsLogger logger: loggers.values()){ logger.writePending(); } enable_pending_writes = false; } public static synchronized AEDiagnosticsLogger getLogger( String name ) { AEDiagnosticsLogger logger = (AEDiagnosticsLogger)loggers.get(name); if ( logger == null ){ startup( false ); logger = new AEDiagnosticsLogger( debug_dir, name, MAX_FILE_SIZE, !enable_pending_writes ); loggers.put( name, logger ); } return( logger ); } public static void logWithStack( String logger_name, String str ) { log( logger_name, str + ": " + Debug.getCompressedStackTrace()); } public static void log( String logger_name, String str ) { getLogger( logger_name ).log( str ); } public static void markDirty() { try{ COConfigurationManager.setParameter( CONFIG_KEY, false ); COConfigurationManager.save(); }catch( Throwable e ){ Debug.printStackTrace( e ); } } public static boolean isDirty() { return( !COConfigurationManager.getBooleanParameter( CONFIG_KEY )); } public static void markClean() { try{ COConfigurationManager.setParameter( CONFIG_KEY, true ); COConfigurationManager.save(); }catch( Throwable e ){ Debug.printStackTrace( e ); } } private static final String[][] bad_dlls = { { "niphk", "y", }, { "nvappfilter", "y", }, { "netdog", "y", }, { "vlsp", "y", }, { "imon", "y", }, { "sarah", "y", }, { "MxAVLsp", "y", }, { "mclsp", "y", }, { "radhslib", "y", }, { "winsflt", "y", }, { "nl_lsp", "y", }, { "AxShlex", "y", }, { "iFW_Xfilter", "y", }, { "gapsp", "y", }, { "WSOCKHK", "n", }, }; public static void checkDumpsAndNatives() { try{ PlatformManager p_man = PlatformManagerFactory.getPlatformManager(); if ( p_man.getPlatformType() == PlatformManager.PT_WINDOWS && p_man.hasCapability( PlatformManagerCapabilities.TestNativeAvailability )){ for (int i=0;i most_recent_time && last_mod > one_week_ago){ most_recent_dump = f; most_recent_time = last_mod; } } } if ( most_recent_dump!= null ){ long last_done = COConfigurationManager.getLongParameter( "diagnostics.dump.lasttime", 0 ); if ( last_done < most_recent_time ){ COConfigurationManager.setParameter( "diagnostics.dump.lasttime", most_recent_time ); analyseDump( most_recent_dump ); } } } }catch( Throwable e ){ Debug.printStackTrace(e); } } protected static void analyseDump( File file ) { System.out.println( "Analysing " + file ); try{ LineNumberReader lnr = new LineNumberReader( new FileReader( file )); try{ boolean float_excep = false; String[] bad_dlls_uc = new String[bad_dlls.length]; for (int i=0;i 0) { diagLoggerLogAndOut(" " + _debug_msg, true); } if ( trace_trace_tail != null ){ diagLoggerLogAndOut( " " + trace_trace_tail, true); } if (_exception != null) { diagLoggerLogAndOut(_exception); } } public static String getLastCaller() { return getLastCaller(0); } public static String getLastCaller(int numToGoBackFurther) { try { throw new Exception(); } catch (Exception e) { // [0] = our throw // [1] = the line that called getLastCaller // [2] = the line that called the function that has getLastCaller StackTraceElement st[] = e.getStackTrace(); if (st == null || st.length == 0) return "??"; if (st.length > 3 + numToGoBackFurther) return st[3 + numToGoBackFurther].toString(); return st[st.length - 1].toString(); } } public static void outStackTrace() { // skip the last, since they'll most likely be main diagLoggerLogAndOut(getStackTrace(1),false); } private static String getStackTrace(int endNumToSkip) { String sStackTrace = ""; try { throw new Exception(); } catch (Exception e) { StackTraceElement st[] = e.getStackTrace(); for (int i = 1; i < st.length - endNumToSkip; i++) { if (!st[i].getMethodName().endsWith("StackTrace")) sStackTrace += st[i].toString() + "\n"; } if (e.getCause() != null) sStackTrace += "\tCaused By: " + getStackTrace(e.getCause()) + "\n"; } return sStackTrace; } public static void killAWTThreads() { ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); killAWTThreads( threadGroup ); } private static String getCompressedStackTrace( Throwable t, int frames_to_skip) { return getCompressedStackTrace(t, frames_to_skip, 200); } public static String getCompressedStackTrace( Throwable t, int frames_to_skip, int iMaxLines) { String sStackTrace = ""; StackTraceElement[] st = t.getStackTrace(); int iMax = Math.min(st.length, iMaxLines + frames_to_skip); for (int i = frames_to_skip; i < iMax; i++) { if (i > frames_to_skip) sStackTrace += ","; String cn = st[i].getClassName(); cn = cn.substring( cn.lastIndexOf(".")+1); sStackTrace += cn +"::"+st[i].getMethodName()+"::"+st[i].getLineNumber(); } Throwable cause = t.getCause(); if (cause != null) { sStackTrace += "\n\tCaused By: " + getCompressedStackTrace(cause, 0); } return sStackTrace; } public static String getStackTrace(boolean bCompressed, boolean bIncludeSelf) { return getStackTrace(bCompressed, bIncludeSelf, bIncludeSelf ? 0 : 1, 200); } public static String getStackTrace(boolean bCompressed, boolean bIncludeSelf, int iNumLinesToSkip, int iMaxLines) { if (bCompressed) return getCompressedStackTrace(bIncludeSelf ? 2 + iNumLinesToSkip : 3 + iNumLinesToSkip, iMaxLines); // bIncludeSelf not supported gor non Compressed yet return getStackTrace(1); } private static String getCompressedStackTrace(int frames_to_skip, int iMaxLines) { String trace_trace_tail = null; try { throw new Exception(); } catch (Exception e) { trace_trace_tail = getCompressedStackTrace(e, frames_to_skip, iMaxLines); } return (trace_trace_tail); } public static void killAWTThreads( ThreadGroup threadGroup ) { Thread[] threadList = new Thread[threadGroup.activeCount()]; threadGroup.enumerate(threadList); for (int i = 0; i < threadList.length; i++){ Thread t = threadList[i]; if ( t != null ){ String name = t.getName(); if ( name.startsWith( "AWT" )){ out( "Interrupting thread '".concat(t.toString()).concat("'" )); t.interrupt(); } } } if ( threadGroup.getParent() != null ){ killAWTThreads(threadGroup.getParent()); } } public static void dumpThreads( String name ) { out(name+":"); ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); dumpThreads( threadGroup, "\t" ); } public static void dumpThreads( ThreadGroup threadGroup, String indent ) { Thread[] threadList = new Thread[threadGroup.activeCount()]; threadGroup.enumerate(threadList); for (int i = 0; i < threadList.length; i++){ Thread t = threadList[i]; if ( t != null ){ out( indent.concat("active thread = ").concat(t.toString()).concat(", daemon = ").concat(String.valueOf(t.isDaemon()))); } } if ( threadGroup.getParent() != null ){ dumpThreads(threadGroup.getParent(),indent+"\t"); } } public static void dumpThreadsLoop( final String name ) { new AEThread("Thread Dumper") { public void runSupport() { while(true){ Debug.dumpThreads(name); try{ Thread.sleep(5000); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } }.start(); } public static void dumpSystemProperties() { out( "System Properties:"); Properties props = System.getProperties(); Iterator it = props.keySet().iterator(); while(it.hasNext()){ String name = (String)it.next(); out( "\t".concat(name).concat(" = '").concat(props.get(name).toString()).concat("'" )); } } public static String getNestedExceptionMessage( Throwable e ) { String last_message = ""; while( e != null ){ String this_message; if ( e instanceof UnknownHostException ){ this_message = "Unknown host " + e.getMessage(); }else if ( e instanceof FileNotFoundException ){ this_message = "File not found: " + e.getMessage(); }else{ this_message = e.getMessage(); } // if no exception message then pick up class name. if we have a deliberate // zero length string then we assume that the exception can be ignored for // logging purposes as it is just delegating if ( this_message == null ){ this_message = e.getClass().getName(); int pos = this_message.lastIndexOf("."); this_message = this_message.substring( pos+1 ).trim(); } if ( this_message.length() > 0 && last_message.indexOf( this_message ) == -1 ){ last_message += (last_message.length()==0?"":", " ) + this_message; } e = e.getCause(); } return( last_message ); } public static String getNestedExceptionMessageAndStack( Throwable e ) { return( getNestedExceptionMessage(e) + ", " + getCompressedStackTrace( e, 0 )); } public static String getCompressedStackTrace() { return( getCompressedStackTrace( new Throwable(), 2 )); } public static String getCompressedStackTrace(int iMaxLines) { return( getCompressedStackTrace( new Throwable(), 2, iMaxLines )); } public static String getExceptionMessage( Throwable e ) { String message = e.getMessage(); if ( message == null || message.length() == 0 ){ message = e.getClass().getName(); int pos = message.lastIndexOf("."); message = message.substring( pos+1 ); }else if ( e instanceof ClassNotFoundException ){ if ( message.toLowerCase().indexOf("found") == -1 ){ message = "Class " + message + " not found"; } } return( message ); } public static void printStackTrace(Throwable e) { printStackTrace(e, null); } public static void printStackTrace( Throwable e, Object context) { String header = "DEBUG::"; header = header + new Date(SystemTime.getCurrentTime()).toString() + "::"; String className = "?::"; String methodName = "?::"; int lineNumber = -1; try { throw new Exception(); }catch (Exception f) { StackTraceElement[] st = f.getStackTrace(); for (int i=1;i= 0) secretName += key.substring(iExtensionPos); return secretName; } public static void main(String[] args) { System.out.println(secretFileName("c:\\temp\\hello there.txt")); System.out.println(secretFileName("hello there.txt")); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/ByteArrayHashMap.java0000644000175000017500000002321011225551342024152 0ustar adrianadrian/* * Created on 22-Feb-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * * This is a hack based on Sun's implemenetation below to just support byte[] efficiently * * @(#)HashMap.java 1.57 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package org.gudy.azureus2.core3.util; import java.util.ArrayList; import java.util.List; public class ByteArrayHashMap { /** * The default initial capacity - MUST be a power of two. */ static final int DEFAULT_INITIAL_CAPACITY = 16; /** * The maximum capacity, used if a higher value is implicitly specified * by either of the constructors with arguments. * MUST be a power of two <= 1<<30. */ static final int MAXIMUM_CAPACITY = 1 << 30; static final float DEFAULT_LOAD_FACTOR = 0.75f; protected Entry[] table; protected int size; private int threshold; final float loadFactor; @SuppressWarnings("unchecked") public ByteArrayHashMap(int initialCapacity, float loadFactor) { if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException("Illegal load factor: " + loadFactor); // Find a power of 2 >= initialCapacity int capacity = 1; while (capacity < initialCapacity) capacity <<= 1; this.loadFactor = loadFactor; threshold = (int)(capacity * loadFactor); table = new Entry[capacity]; } public ByteArrayHashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } @SuppressWarnings("unchecked") public ByteArrayHashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); table = new Entry[DEFAULT_INITIAL_CAPACITY]; } public int size() { return size; } public boolean isEmpty() { return size == 0; } public T get(byte[] key, int offset, int len ) { byte[] k = new byte[len]; System.arraycopy( key, offset, k, 0, len ); return( get( k )); } public T get(byte[] key) { int hash = hash(key); int i = indexFor(hash, table.length); Entry e = table[i]; while (true) { if (e == null) return null; if (e.hash == hash && eq(key, e.key)) return e.value; e = e.next; } } public boolean containsKey( byte[] key ) { int hash = hash(key); int i = indexFor(hash, table.length); Entry e = table[i]; while (true) { if (e == null) return( false ); if (e.hash == hash && eq(key, e.key)) return( true ); e = e.next; } } public T put(byte[] key, T value) { int hash = hash(key); int i = indexFor(hash, table.length); for (Entry e = table[i]; e != null; e = e.next) { if (e.hash == hash && eq(key, e.key)) { T oldValue = e.value; e.value = value; return oldValue; } } addEntry(hash, key, value, i); return null; } public T remove(byte[] key) { Entry e = removeEntryForKey(key); return (e == null ? null : e.value); } public void clear() { Entry tab[] = table; for (int i = 0; i < tab.length; i++) tab[i] = null; size = 0; } public List keys() { List res = new ArrayList(); for (int j = 0; j < table.length; j++) { Entry e = table[j]; while( e != null ){ res.add( e.key ); e = e.next; } } return( res ); } public List values() { List res = new ArrayList(); for (int j = 0; j < table.length; j++) { Entry e = table[j]; while( e != null ){ res.add( e.value ); e = e.next; } } return( res ); } /** * Bit inefficient at the moment * @return */ public ByteArrayHashMap duplicate() { ByteArrayHashMap res = new ByteArrayHashMap(size,loadFactor); for (int j = 0; j < table.length; j++) { Entry e = table[j]; while( e != null ){ res.put( e.key, e.value ); e = e.next; } } return( res ); } ////////////////////////////////// @SuppressWarnings("unchecked") void resize(int newCapacity) { Entry[] oldTable = table; int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return; } Entry[] newTable = new Entry[newCapacity]; transfer(newTable); table = newTable; threshold = (int)(newCapacity * loadFactor); } void transfer(Entry[] newTable) { Entry[] src = table; int newCapacity = newTable.length; for (int j = 0; j < src.length; j++) { Entry e = src[j]; if (e != null) { src[j] = null; do { Entry next = e.next; int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } while (e != null); } } } Entry removeEntryForKey(byte[] key) { int hash = hash(key); int i = indexFor(hash, table.length); Entry prev = table[i]; Entry e = prev; while (e != null) { Entry next = e.next; if (e.hash == hash && eq(key, e.key)) { size--; if (prev == e) table[i] = next; else prev.next = next; return e; } prev = e; e = next; } return e; } protected static class Entry{ public final byte[] key; public S value; public final int hash; public Entry next; /** * Create new entry. */ Entry(int h, byte[] k, S v, Entry n) { value = v; next = n; key = k; hash = h; } public byte[] getKey() { return key; } public S getValue() { return value; } } void addEntry(int hash, byte[] key, T value, int bucketIndex) { table[bucketIndex] = new Entry(hash, key, value, table[bucketIndex]); if (size++ >= threshold) resize(2 * table.length); } void createEntry(int hash, byte[] key, T value, int bucketIndex) { table[bucketIndex] = new Entry(hash, key, value, table[bucketIndex]); size++; } private static final int hash(byte[] x) { int hash = 0; int len = x.length; for (int i = 0; i < len; i++){ hash = 31*hash + x[i]; } return( hash ); } private static final boolean eq(byte[] x, byte[] y) { if ( x == y ){ return( true ); } int len = x.length; if ( len != y.length ){ return( false ); } for (int i=0;i= 0 && classpath.charAt(start_pos) != '/' ){ start_pos--; } String app_name = classpath.substring( start_pos+1, dot_pos ); setApplicationName( app_name ); } } } } public static void setApplicationName( String name ) { if ( name != null && name.trim().length() > 0 ){ name = name.trim(); if ( user_path != null ){ if ( !name.equals( APPLICATION_NAME )){ System.out.println( "**** SystemProperties::setApplicationName called too late! ****" ); } } APPLICATION_NAME = name; } } public static void setApplicationIdentifier( String application_id ) { if ( application_id != null && application_id.trim().length() > 0 ){ APPLICATION_ID = application_id.trim(); } } public static void setApplicationEntryPoint( String entry_point ) { if ( entry_point != null && entry_point.trim().length() > 0 ){ APPLICATION_ENTRY_POINT = entry_point.trim(); } } public static String getApplicationName() { return( APPLICATION_NAME ); } public static void setApplicationVersion( String v ) { APPLICATION_VERSION = v; } public static String getApplicationVersion() { return( APPLICATION_VERSION ); } public static String getApplicationIdentifier() { return( APPLICATION_ID ); } public static String getApplicationEntryPoint() { return( APPLICATION_ENTRY_POINT ); } /** * Returns the full path to the user's home azureus directory. * Under unix, this is usually ~/.azureus/ * Under Windows, this is usually .../Documents and Settings/username/Application Data/Azureus/ * Under OSX, this is usually /Users/username/Library/Application Support/Azureus/ */ public static String getUserPath() { if (user_path != null) { return user_path; } // WATCH OUT!!!! possible recursion here if logging is changed so that it messes with // config initialisation - that's why we don't assign the user_path variable until it // is complete - an earlier bug resulted in us half-assigning it and using it due to // recursion. At least with this approach we'll get (worst case) stack overflow if // a similar change is made, and we'll spot it!!!! // Super Override -- no AZ_DIR or xxx_DEFAULT added at all. String temp_user_path = System.getProperty(SYS_PROP_CONFIG_OVERRIDE); try { if (temp_user_path != null) { if (!temp_user_path.endsWith(SEP)) { temp_user_path += SEP; } File dir = new File(temp_user_path); if (!dir.exists()) { FileUtil.mkdirs(dir); } if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "SystemProperties::getUserPath(Custom): user_path = " + temp_user_path)); return temp_user_path; } // No override, get it from platform manager try { PlatformManager platformManager = PlatformManagerFactory.getPlatformManager(); temp_user_path = platformManager.getLocation( PlatformManager.LOC_USER_DATA).getPath() + SEP; if (Logger.isEnabled()) { Logger.log(new LogEvent(LOGID, "SystemProperties::getUserPath: user_path = " + temp_user_path)); } } catch ( Throwable e ){ if (Logger.isEnabled()) { Logger.log(new LogEvent(LOGID, "Unable to retrieve user config path from " + "the platform manager. " + "Make sure aereg.dll is present.")); } } // If platform failed, try some hackery if (temp_user_path == null) { String userhome = System.getProperty("user.home"); if (Constants.isWindows) { temp_user_path = getEnvironmentalVariable("APPDATA"); if (temp_user_path != null && temp_user_path.length() > 0) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Using user config path from APPDATA env var instead: " + temp_user_path)); } else { temp_user_path = userhome + SEP + WIN_DEFAULT; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Using user config path from java user.home var instead: " + temp_user_path)); } temp_user_path = temp_user_path + SEP + APPLICATION_NAME + SEP; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "SystemProperties::getUserPath(Win): user_path = " + temp_user_path)); } else if (Constants.isOSX) { temp_user_path = userhome + SEP + OSX_DEFAULT + SEP + APPLICATION_NAME + SEP; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "SystemProperties::getUserPath(Mac): user_path = " + temp_user_path)); } else { // unix type temp_user_path = userhome + SEP + "." + APPLICATION_NAME.toLowerCase() + SEP; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "SystemProperties::getUserPath(Unix): user_path = " + temp_user_path)); } } //if the directory doesn't already exist, create it File dir = new File(temp_user_path); if (!dir.exists()) { FileUtil.mkdirs(dir); } return temp_user_path; } finally { user_path = temp_user_path; } } /** * Returns the full path to the directory where Azureus is installed * and running from. */ public static String getApplicationPath() { if ( app_path != null ){ return( app_path ); } String temp_app_path = System.getProperty("azureus.install.path", System.getProperty("user.dir")); if ( !temp_app_path.endsWith(SEP)){ temp_app_path += SEP; } app_path = temp_app_path; return( app_path ); } /** * Returns whether or not this running instance was started via * Java's Web Start system. */ public static boolean isJavaWebStartInstance() { try { String java_ws_prop = System.getProperty("azureus.javaws"); return ( java_ws_prop != null && java_ws_prop.equals( "true" ) ); } catch (Throwable e) { //we can get here if running in an applet, as we have no access to system props return false; } } /** * Will attempt to retrieve an OS-specific environmental var. */ public static String getEnvironmentalVariable( final String _var ) { // this approach doesn't work at all on Windows 95/98/ME - it just hangs // so get the hell outta here! if ( Constants.isWindows9598ME ){ return( "" ); } // getenv reinstated in 1.5 - try using it String res = System.getenv( _var ); if ( res != null ){ return( res ); } Properties envVars = new Properties(); BufferedReader br = null; try { Process p = null; Runtime r = Runtime.getRuntime(); if ( Constants.isWindows ) { p = r.exec( "cmd.exe /c set" ); } else { //we assume unix p = r.exec( "env" ); } String system_encoding = LocaleUtil.getSingleton().getSystemEncoding(); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "SystemProperties::getEnvironmentalVariable - " + _var + ", system encoding = " + system_encoding)); br = new BufferedReader( new InputStreamReader( p.getInputStream(), system_encoding), 8192); String line; while( (line = br.readLine()) != null ) { int idx = line.indexOf( '=' ); if (idx >= 0) { String key = line.substring( 0, idx ); String value = line.substring( idx+1 ); envVars.setProperty( key, value ); } } br.close(); } catch (Throwable t) { if (br != null) try { br.close(); } catch (Exception ingore) {} } return envVars.getProperty( _var, "" ); } public static String getDocPath() { File fDocPath = null; try { PlatformManager platformManager = PlatformManagerFactory.getPlatformManager(); fDocPath = platformManager.getLocation(PlatformManager.LOC_DOCUMENTS); } catch (Throwable e) { } if (fDocPath == null) { // should never happen.. but if we are missing a dll.. fDocPath = new File(getUserPath(), "Documents"); } return fDocPath.getAbsolutePath(); } public static String getAzureusJarPath() { String str = getApplicationPath(); if( Constants.isOSX ){ str += SystemProperties.getApplicationName() + ".app/Contents/Resources/Java/"; } return( str + "Azureus2.jar" ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AESemaphore.java0000644000175000017500000001167710730131242023146 0ustar adrianadrian/* * Created on 18-Sep-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author parg * */ public class AESemaphore extends AEMonSem { private int dont_wait = 0; private int total_reserve = 0; private int total_release = 0; private boolean released_forever = false; protected Thread latest_waiter; public AESemaphore( String _name ) { this( _name, 0 ); } public AESemaphore( String _name, int count ) { super( _name, false ); dont_wait = count; total_release = count; } public void reserve() { if ( !reserve(0)){ Debug.out( "AESemaphore: reserve completed without acquire [" + getString() + "]" ); } } public boolean reserve( long millis ) { return( reserveSupport( millis, 1 ) == 1 ); } public boolean reserveIfAvailable() { synchronized(this){ if ( released_forever || dont_wait > 0 ){ reserve(); return( true ); }else{ return( false ); } } } public int reserveSet( int max_to_reserve, long millis ) { return( reserveSupport( millis, max_to_reserve)); } public int reserveSet( int max_to_reserve ) { return( reserveSupport( 0, max_to_reserve)); } protected int reserveSupport( long millis, int max_to_reserve ) { if ( DEBUG ){ super.debugEntry(); } synchronized(this){ entry_count++; //System.out.println( name + "::reserve"); if ( released_forever ){ return(1); } if ( dont_wait == 0 ){ try{ waiting++; latest_waiter = Thread.currentThread(); if ( waiting > 1 ){ // System.out.println( "AESemaphore: " + name + " contended" ); } if ( millis == 0 ){ // we can get spurious wakeups (see Object javadoc) so we need to guard against // their possibility int spurious_count = 0; while( true ){ wait(); if ( total_reserve == total_release ){ spurious_count++; if ( spurious_count > 1024 ){ Debug.out( "AESemaphore: spurious wakeup limit exceeded" ); throw( new Throwable( "die die die" )); }else{ // Debug.out("AESemaphore: spurious wakeup, ignoring" ); } }else{ break; } } }else{ // we don't hugely care about spurious wakeups here, it'll just appear // as a failed reservation a bit early wait(millis); } if ( total_reserve == total_release ){ // here we have timed out on the wait without acquiring waiting--; return( 0 ); } total_reserve++; return( 1 ); }catch( Throwable e ){ waiting--; Debug.out( "**** semaphore operation interrupted ****" ); throw( new RuntimeException("Semaphore: operation interrupted", e )); }finally{ latest_waiter = null; } }else{ int num_to_get = max_to_reserve>dont_wait?dont_wait:max_to_reserve; dont_wait -= num_to_get; total_reserve += num_to_get; return( num_to_get ); } } } public void release() { try{ synchronized(this){ //System.out.println( name + "::release"); total_release++; if ( waiting != 0 ){ waiting--; notify(); }else{ dont_wait++; } } }finally{ if ( DEBUG ){ debugExit(); } } } public void releaseAllWaiters() { synchronized(this){ int x = waiting; for ( int i=0;i= Constants.CRAPPY_INFINITE_AS_LONG) return Constants.INFINITY_STRING; if (time_secs < 0) return ""; // secs, mins, hours, days int[] vals = { (int) time_secs % 60, (int) (time_secs / 60) % 60, (int) (time_secs / 3600) % 24, (int) (time_secs / 86400) % 365, (int) (time_secs / 31536000) }; int end = vals.length - 1; while (vals[end] == 0 && end > 0) { end--; } String result = vals[end] + TIME_SUFFIXES[end]; /* old logic removed to prefer showing consecutive units // skip until we have a non-zero time section do { end--; } while (end >= 0 && vals[end] == 0); */ end--; if (end >= 0) result += " " + twoDigits(vals[end]) + TIME_SUFFIXES[end]; return result; } public static String format100ths(long time_millis) { long time_secs = time_millis / 1000; int hundredths = (int)(time_millis - time_secs*1000)/10; if ( time_millis == 0 || time_secs >= 60 ){ return( format( time_secs )); } return( time_secs + "." + twoDigits( hundredths) + TIME_SUFFIXES[0]); } /** * Format time into "[[# y] # d] 00:00:00" format * * @param time time in seconds * @return */ public static String formatColon(long time) { if (time == Constants.CRAPPY_INFINITY_AS_INT || time >= Constants.CRAPPY_INFINITE_AS_LONG) return Constants.INFINITY_STRING; if (time < 0) return ""; int secs = (int) time % 60; int mins = (int) (time / 60) % 60; int hours = (int) (time /3600) % 24; int days = (int) (time / 86400) % 365; int years = (int) (time / 31536000); String result = ""; if (years > 0) result += years + "y "; if (years > 0 || days > 0) result += days + "d "; result += twoDigits(hours) + ":" + twoDigits(mins) + ":" + twoDigits(secs); return result; } private static String twoDigits(int i) { return (i < 10) ? "0" + i : String.valueOf(i); } /** * parse time in h:m:s format to SECONDS * @param str * @return */ public static int parseColon( String str ) { final int[] multipliers = { 1, 60, 3600, 86400, 31536000 }; String[] bits = str.split( ":" ); int result = 0; for (int i=0;i 0 ){ result += multipliers[i] * Integer.parseInt( bit ); } } return( result ); } public static String formatNanoAsMilli( long nanos ) { final long truncator = 60*1000000000L; nanos = nanos - ((nanos/truncator) * truncator); return( String.valueOf(((double)nanos)/1000000) + " ms" ); } public static String getHTTPDate( long millis ) { synchronized( http_date_format ){ return( http_date_format.format(new Date( millis ))); } } public static long parseHTTPDate( String date ) { try{ return( http_date_format.parse( date ).getTime()); }catch( Throwable e ){ Debug.out("Failed to parse HTTP date '" + date + "'" ); return( 0 ); } } public static String milliStamp() { long nanos = SystemTime.getHighPrecisionCounter(); final long truncator = 60*1000000000L; nanos = nanos - ((nanos/truncator) * truncator); String str = String.valueOf( nanos/1000000 ); while( str.length() < 5 ){ str = "0" + str; } return( str + ": " ); } public static void milliTrace( String str ) { System.out.println( milliStamp() + str ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/HostNameToIPResolverListener.java0000644000175000017500000000233210373051004026503 0ustar adrianadrian/* * Created on 29-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author parg * */ import java.net.InetAddress; public interface HostNameToIPResolverListener { /** * * @param address null if resolution failed */ public void hostNameResolutionComplete( InetAddress address ); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/TimerEventPerformer.java0000644000175000017500000000173007760277126024773 0ustar adrianadrian/* * File : TimerEventPerformer.java * Created : 23-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author parg * */ public interface TimerEventPerformer { public void perform( TimerEvent event ); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/BEncodableObject.java0000644000175000017500000000231611271211076024115 0ustar adrianadrian/* * Created on Oct 24, 2009 10:21:17 PM * Copyright (C) 2009 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.util; /** * Classes that implement this interface can be sent to a bencode * * @author TuxPaper * @created Oct 24, 2009 * */ public interface BEncodableObject { /** * @return Must return an object that is bencodable */ public Object toBencodeObject(); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/SystemTime.java0000644000175000017500000003627411275620514023132 0ustar adrianadrian/* * Created on Apr 16, 2004 Created by Alon Rohter Copyright (C) 2004, 2005, 2006 * Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros 8 Allee Lenotre, La Grille Royale, * 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.atomic.AtomicLong; /** * Utility class to retrieve current system time, and catch clock backward time * changes. */ public class SystemTime { public static final long TIME_GRANULARITY_MILLIS = 25; //internal update time ms private static SystemTimeProvider instance; // can't do that without some safeguarding code. // monotime does guarantee that time neither goes backwards nor performs leaps into the future. // the HPC doesn't jump backward but can jump forward in time private static final boolean SOD_IT_LETS_USE_HPC = false;// = Constants.isCVSVersion(); static { try { if (System.getProperty("azureus.time.use.raw.provider", "0").equals("1")) { System.out.println("Warning: Using Raw Provider"); instance = new RawProvider(); } else { instance = new SteppedProvider(); } } catch (Throwable e) { // might be in applet... instance = new SteppedProvider(); } } public static void useRawProvider() { if (!(instance instanceof RawProvider)) { Debug.out( "Whoa, someone already created a non-raw provider!" ); instance = new RawProvider(); } } private static volatile List systemTimeConsumers = new ArrayList(); private static volatile List monotoneTimeConsumers = new ArrayList(); private static volatile List clock_change_list = new ArrayList(); private static long hpc_base_time; private static long hpc_last_time; private static boolean no_hcp_logged; protected interface SystemTimeProvider { public long getTime(); public long getMonoTime(); public long getSteppedMonoTime(); } protected static class SteppedProvider implements SystemTimeProvider { private static final int STEPS_PER_SECOND = (int) (1000 / TIME_GRANULARITY_MILLIS); private static final long HPC_START = getHighPrecisionCounter()/1000000L; private final Thread updater; private volatile long stepped_time; private volatile long currentTimeOffset = System.currentTimeMillis(); private AtomicLong last_approximate_time = new AtomicLong(); //private volatile long last_approximate_time; private volatile int access_count; private volatile int slice_access_count; private volatile int access_average_per_slice; private volatile int drift_adjusted_granularity; private volatile long stepped_mono_time; private SteppedProvider() { // System.out.println("SystemTime: using stepped time provider"); stepped_time = 0; updater = new Thread("SystemTime") { public void run() { long adjustedTimeOffset = currentTimeOffset; // these averages rely on monotone time, thus won't be affected by system time changes final Average access_average = Average.getInstance(1000, 10); final Average drift_average = Average.getInstance(1000, 10); long lastOffset = adjustedTimeOffset; long lastSecond = -1000; int tick_count = 0; while (true) { long rawTime = System.currentTimeMillis(); /* * keep the monotone time in sync with the raw system * time, for this we need to know the offset of the * current time to the system time */ long newMonotoneTime = rawTime - adjustedTimeOffset; long delta = newMonotoneTime - stepped_time; /* * unless the system time jumps, then we just guess the * time that has passed and adjust the update, so that * the next round can be in sync with the system time * again */ if (delta < 0 || delta > 1000) { /* * jump occured, update monotone time offset, but * not the current time one, that only happens every * second */ stepped_time += TIME_GRANULARITY_MILLIS; adjustedTimeOffset = rawTime - stepped_time; } else { // time is good, keep it stepped_time = newMonotoneTime; } tick_count++; if (tick_count == STEPS_PER_SECOND) { if (lastOffset != adjustedTimeOffset) { final long change = adjustedTimeOffset - lastOffset; Iterator it = clock_change_list.iterator(); //Debug.outNoStack("Clock change of " + change + "ms detected"); while (it.hasNext()) { ((ChangeListener) it.next()).clockChanged(rawTime, change); } lastOffset = adjustedTimeOffset; // make the internal offset publicly visible after consumers have been notified currentTimeOffset = adjustedTimeOffset; } // averaging magic to estimate the amount of time that passes between each getTime invocation long drift = stepped_time - lastSecond - 1000; lastSecond = stepped_time; drift_average.addValue(drift); drift_adjusted_granularity = (int) (TIME_GRANULARITY_MILLIS + (drift_average.getAverage() / STEPS_PER_SECOND)); access_average.addValue(access_count); access_average_per_slice = (int) (access_average.getAverage() / STEPS_PER_SECOND); //System.out.println( "access count = " + access_count + ", average = " + access_average.getAverage() + ", per slice = " + access_average_per_slice + ", drift = " + drift +", average = " + drift_average.getAverage() + ", dag =" + drift_adjusted_granularity ); access_count = 0; tick_count = 0; } slice_access_count = 0; stepped_mono_time = stepped_time; // copy reference since we use unsynced COW semantics List consumersRef = monotoneTimeConsumers; for (int i = 0; i < consumersRef.size(); i++) { TickConsumer cons = (TickConsumer) consumersRef.get(i); try { cons.consume(stepped_time); } catch (Throwable e) { Debug.printStackTrace(e); } } /* * notify consumers with the external offset, internal * offset is only meant for updates */ consumersRef = systemTimeConsumers; long adjustedTime = stepped_time + currentTimeOffset; for (int i = 0; i < consumersRef.size(); i++) { TickConsumer cons = (TickConsumer) consumersRef.get(i); try { cons.consume(adjustedTime); } catch (Throwable e) { Debug.printStackTrace(e); } } try { Thread.sleep(TIME_GRANULARITY_MILLIS); } catch (Exception e) { Debug.printStackTrace(e); } } } }; updater.setDaemon(true); // we don't want this thread to lag much as it'll stuff up the upload/download rate mechanisms (for example) updater.setPriority(Thread.MAX_PRIORITY); updater.start(); } public long getTime() { return getMonoTime() + currentTimeOffset; } public long getMonoTime() { if ( SOD_IT_LETS_USE_HPC ){ return( ( getHighPrecisionCounter()/1000000) - HPC_START ); }else{ long adjusted_time; long averageSliceStep = access_average_per_slice; if (averageSliceStep > 0) { long sliceStep = (drift_adjusted_granularity * slice_access_count) / averageSliceStep; if (sliceStep >= drift_adjusted_granularity) { sliceStep = drift_adjusted_granularity - 1; } adjusted_time = sliceStep + stepped_time; } else adjusted_time = stepped_time; access_count++; slice_access_count++; // make sure we don't go backwards and our reference value for going backwards doesn't go backwards either long approxBuffered = last_approximate_time.get(); if (adjusted_time < approxBuffered) adjusted_time = approxBuffered; else last_approximate_time.compareAndSet(approxBuffered, adjusted_time); return adjusted_time; } } public long getSteppedMonoTime() { if ( SOD_IT_LETS_USE_HPC ){ return( getHighPrecisionCounter()/1000000 ); }else{ return( stepped_mono_time ); } } } protected static class RawProvider implements SystemTimeProvider { private static final int STEPS_PER_SECOND = (int) (1000 / TIME_GRANULARITY_MILLIS); private final Thread updater; private RawProvider() { System.out.println("SystemTime: using raw time provider"); updater = new Thread("SystemTime") { long last_time; public void run() { while (true) { long current_time = getTime(); if (last_time != 0) { long offset = current_time - last_time; if (offset < 0 || offset > 5000) { // clock's changed Iterator it = clock_change_list.iterator(); while (it.hasNext()) { ((ChangeListener) it.next()).clockChanged(current_time, offset); } } } last_time = current_time; List consumer_list_ref = systemTimeConsumers; for (int i = 0; i < consumer_list_ref.size(); i++) { TickConsumer cons = (TickConsumer) consumer_list_ref.get(i); try { cons.consume(current_time); } catch (Throwable e) { Debug.printStackTrace(e); } } consumer_list_ref = monotoneTimeConsumers; long mono_time = getMonoTime(); for (int i = 0; i < consumer_list_ref.size(); i++) { TickConsumer cons = (TickConsumer) consumer_list_ref.get(i); try { cons.consume(mono_time); } catch (Throwable e) { Debug.printStackTrace(e); } } try { Thread.sleep(TIME_GRANULARITY_MILLIS); } catch (Exception e) { Debug.printStackTrace(e); } } } }; updater.setDaemon(true); // we don't want this thread to lag much as it'll stuff up the upload/download rate mechanisms (for example) updater.setPriority(Thread.MAX_PRIORITY); updater.start(); } public long getTime() { return System.currentTimeMillis(); } /** * This implementation does not guarantee monotonous time increases with * 100% accuracy as the adjustedTimeOffset is only adjusted every * TIME_GRANULARITY_MILLIS */ public long getMonoTime() { return getHighPrecisionCounter()/1000000; } public long getSteppedMonoTime() { return getMonoTime(); } } /** * Note that this can this time can jump into the future or past due to * clock adjustments use getMonotonousTime() if you need steady increases * * @return current system time in millisecond since epoch */ public static long getCurrentTime() { return (instance.getTime()); } /** * Time that is guaranteed to grow monotonously and also ignores larger * jumps into the future which might be caused by adjusting the system clock
      *
      * * Do not mix times retrieved by this method with normal time! * * @return the amount of real time passed since the program start in * milliseconds */ public static long getMonotonousTime() { return instance.getMonoTime(); } /** * Like getMonotonousTime but only updated at TIME_GRANULARITY_MILLIS intervals (not interpolated) * As such it is likely to be cheaper to obtain * @return */ public static long getSteppedMonotonousTime() { return instance.getSteppedMonoTime(); } public static long getOffsetTime(long offsetMS) { return instance.getTime() + offsetMS; } public static void registerConsumer(TickConsumer c) { synchronized (instance) { List new_list = new ArrayList(systemTimeConsumers); new_list.add(c); systemTimeConsumers = new_list; } } public static void unregisterConsumer(TickConsumer c) { synchronized (instance) { List new_list = new ArrayList(systemTimeConsumers); new_list.remove(c); systemTimeConsumers = new_list; } } public static void registerMonotonousConsumer(TickConsumer c) { synchronized (instance) { List new_list = new ArrayList(monotoneTimeConsumers); new_list.add(c); monotoneTimeConsumers = new_list; } } public static void unregisterMonotonousConsumer(TickConsumer c) { synchronized (instance) { List new_list = new ArrayList(monotoneTimeConsumers); new_list.remove(c); monotoneTimeConsumers = new_list; } } public static void registerClockChangeListener(ChangeListener c) { synchronized (instance) { List new_list = new ArrayList(clock_change_list); new_list.add(c); clock_change_list = new_list; } } public static void unregisterClockChangeListener(ChangeListener c) { synchronized (instance) { List new_list = new ArrayList(clock_change_list); new_list.remove(c); clock_change_list = new_list; } } public interface TickConsumer { public void consume(long current_time); } public interface ChangeListener { public void clockChanged(long current_time, long change_millis); } public static long getHighPrecisionCounter() { return( System.nanoTime()); } public static void main(String[] args) { for (int i = 0; i < 1; i++) { //final int f_i = i; new Thread() { public void run() { /* * Average access_average = Average.getInstance( 1000, 10 ); * * long last = SystemTime.getCurrentTime(); * * int count = 0; * * while( true ){ * * long now = SystemTime.getCurrentTime(); * * long diff = now - last; * * System.out.println( "diff=" + diff ); * * last = now; * * access_average.addValue( diff ); * * count++; * * if ( count == 33 ){ * * System.out.println( "AVERAGE " + f_i + " = " + * access_average.getAverage()); * * count = 0; } * * try{ Thread.sleep( 3 ); * * }catch( Throwable e ){ } } */ long cstart = SystemTime.getCurrentTime(); long mstart = SystemTime.getMonotonousTime(); System.out.println("alter system clock to see differences between monotonous and current time"); long cLastRound = cstart; long mLastRound = mstart; while (true) { long mnow = SystemTime.getMonotonousTime(); long cnow = SystemTime.getCurrentTime(); //if(mLastRound > mnow) System.out.println("current: " + (cnow - cstart) + " monotonous:" + (mnow - mstart) + " delta current:" + (cnow - cLastRound) + " delta monotonous:" + (mnow - mLastRound)); cLastRound = cnow; mLastRound = mnow; try { Thread.sleep(15); } catch (Throwable e) {} } } }.start(); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/NonDaemonTaskRunner.java0000644000175000017500000001242110724170760024707 0ustar adrianadrian/* * File : NonDaemonTaskRunner.java * Created : 29-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; public class NonDaemonTaskRunner { public static final int LINGER_PERIOD = 2500; protected static NonDaemonTaskRunner singleton; protected static AEMonitor class_mon = new AEMonitor( "NonDaemonTaskRunner:class" ); protected Stack tasks = new Stack(); protected AEMonitor tasks_mon = new AEMonitor( "NonDaemonTaskRunner:tasks" ); protected AESemaphore task_sem = new AESemaphore("NonDaemonTaskRunner"); protected List wait_until_idle_list = new ArrayList(); protected AEThread2 current_thread; protected static NonDaemonTaskRunner getSingleton() { try{ class_mon.enter(); if ( singleton == null ){ singleton = new NonDaemonTaskRunner(); } return( singleton ); }finally{ class_mon.exit(); } } public static Object run( NonDaemonTask target ) throws Throwable { return(getSingleton().runSupport( target, false )); } public static Object runAsync( NonDaemonTask target ) throws Throwable { return(getSingleton().runSupport( target, true )); } protected Object runSupport( NonDaemonTask target, boolean async ) throws Throwable { // is this a recursive call? if so, run directly if ( current_thread != null && current_thread.isCurrentThread()){ return( target.run()); } taskWrapper wrapper = new taskWrapper( target ); try{ tasks_mon.enter(); tasks.push( wrapper ); task_sem.release(); if ( current_thread == null ){ final AESemaphore wait_sem = new AESemaphore("NonDaemonTaskRunnerTask: " + target.getName()); // NON-DAEMON!!! current_thread = new AEThread2( "NonDaemonTaskRunner", false ) { public void run() { wait_sem.release(); // System.out.println( "non daemon starts" ); while(true){ task_sem.reserve(LINGER_PERIOD); taskWrapper t = null; try{ tasks_mon.enter(); if ( tasks.isEmpty()){ current_thread = null; for (int i=0;i 0 ){ indent = indent.substring(INDENT_STRING.length()); } } public void setForce( boolean b ) { force = b; } public void close() { pw.close(); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/LightHashMap.java0000644000175000017500000004274211135607120023326 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.util.*; /** * A lighter (on memory) hash map
      * * Advantages over HashMap: *
        *
      • Lower memory footprint *
      • Everything is stored in a single array, this might improve cache performance (not verified) *
      • Read-only operations on Key and Value iterators should be concurrency-safe (Entry iterators are not) but they might return null values unexpectedly under concurrent modification (not verified) *
      * * Disadvantages: *
        *
      • removal is implemented with thombstone-keys, this can significantly increase the lookup time if many values are removed. Use compactify() for scrubbing *
      • entry set iterators and thus transfers to other maps are slower than compareable implementations *
      • the map does not store hashcodes and relies on either the key-objects themselves caching them (such as strings) or a fast computation of hashcodes *
      • concurrent modification detection is not as fail-fast as HashMap as no modification counter is used and only structural differences are noted *
      * * @author Aaron Grunthal * @create 28.11.2007 */ public class LightHashMap extends AbstractMap implements Cloneable { private static final Object THOMBSTONE = new Object(); private static final Object NULLKEY = new Object(); private static final float DEFAULT_LOAD_FACTOR = 0.75f; private static final int DEFAULT_CAPACITY = 8; public LightHashMap() { this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR); } public LightHashMap(final int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } public LightHashMap(final Map m) { this(0); if(m instanceof LightHashMap) { final LightHashMap lightMap = (LightHashMap)m; this.size = lightMap.size; this.data = (Object[])lightMap.data.clone(); } else putAll(m); } public Object clone() { try { final LightHashMap newMap = (LightHashMap) super.clone(); newMap.data = (Object[])data.clone(); return newMap; } catch (CloneNotSupportedException e) { // should not ever happen e.printStackTrace(); throw new RuntimeException(e); } } public LightHashMap(int initialCapacity, final float loadFactor) { if (loadFactor > 1) throw new IllegalArgumentException("Load factor must not be > 1"); this.loadFactor = loadFactor; int capacity = 1; while (capacity < initialCapacity) capacity <<= 1; data = new Object[capacity*2]; } final float loadFactor; int size; Object[] data; public Set entrySet() { return new EntrySet(); } private abstract class HashIterator implements Iterator { protected int nextIdx = -2; protected int currentIdx = -2; protected Object[] itData = data; public HashIterator() { findNext(); } private void findNext() { do nextIdx+=2; while (nextIdx < itData.length && (itData[nextIdx] == null || itData[nextIdx] == THOMBSTONE)); } public void remove() { if (currentIdx == -2) throw new IllegalStateException("No entry to delete, use next() first"); if (itData != data) throw new ConcurrentModificationException("removal opperation not supported as concurrent structural modification occured"); LightHashMap.this.removeForIndex(currentIdx); currentIdx = -2; } public boolean hasNext() { return nextIdx < itData.length; } public Object next() { if (!hasNext()) throw new IllegalStateException("No more entries"); currentIdx = nextIdx; findNext(); return nextIntern(); } abstract Object nextIntern(); } private class EntrySet extends AbstractSet { public Iterator iterator() { return new EntrySetIterator(); } public int size() { return size; } private class EntrySetIterator extends HashIterator { public Object nextIntern() { return new Entry(currentIdx); } private final class Entry implements Map.Entry { final int entryIndex; public Entry(final int idx) { entryIndex = idx; } public Object getKey() { final Object key = itData[entryIndex]; return key != NULLKEY ? key : null; } public Object getValue() { return itData[entryIndex+1]; } public Object setValue(final Object value) { final Object oldValue = itData[entryIndex+1]; itData[entryIndex+1] = value; return oldValue; } public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry e = (Map.Entry) o; return (getKey() == null ? e.getKey() == null : getKey().equals(e.getKey())) && (getValue() == null ? e.getValue() == null : getValue().equals(e.getValue())); } public int hashCode() { return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode()); } } } } private class KeySet extends AbstractSet { public Iterator iterator() { return new KeySetIterator(); } private class KeySetIterator extends HashIterator { Object nextIntern() { final Object key = itData[currentIdx]; return key != NULLKEY ? key : null; } } public int size() { return size; } } private class Values extends AbstractCollection { public Iterator iterator() { return new ValueIterator(); } private class ValueIterator extends HashIterator { Object nextIntern() { return itData[currentIdx+1]; } } public int size() { return size; } } public T put(final Object key, final Object value) { checkCapacity(1); return (T)add(key, value, false); } public void putAll(final Map m) { checkCapacity(m.size()); for (final Iterator it = m.entrySet().iterator(); it.hasNext();) { final Map.Entry entry = (Map.Entry) it.next(); add(entry.getKey(), entry.getValue(),true); } // compactify in case we overestimated the new size due to redundant entries //compactify(0.f); } public Set keySet() { return new KeySet(); } public Collection values() { return new Values(); } public int capacity() { return data.length>>1; } public T get(Object key) { if(key == null) key = NULLKEY; return (T)data[nonModifyingFindIndex(key)+1]; } private Object add(Object key, final Object value, final boolean bulkAdd) { if(key == null) key = NULLKEY; final int idx = bulkAdd ? nonModifyingFindIndex(key) : findIndex(key); final Object oldValue = data[idx+1]; if (data[idx] == null || data[idx] == THOMBSTONE) { data[idx] = key; size++; } data[idx+1] = value; return oldValue; } public T remove(Object key) { if(size == 0) return null; if(key == null) key = NULLKEY; final int idx = findIndex(key); if (keysEqual(data[idx], key)) return(T)removeForIndex(idx); return null; } private Object removeForIndex(final int idx) { final Object oldValue = data[idx+1]; data[idx] = THOMBSTONE; data[idx+1] = null; size--; return oldValue; } public void clear() { size = 0; int capacity = 1; while (capacity < DEFAULT_CAPACITY) capacity <<= 1; data = new Object[capacity*2]; } public boolean containsKey(Object key) { if(size == 0) return false; if(key == null) key = NULLKEY; return keysEqual(key, data[nonModifyingFindIndex(key)]); } public boolean containsValue(final Object value) { if (value != null) { for (int i = 0; i < data.length; i+=2) if (value.equals(data[i+1])) return true; } else for (int i = 0; i < data.length; i+=2) if (data[i+1] == null && data[i] != null && data[i] != THOMBSTONE) return true; return false; } private final boolean keysEqual(final Object o1, final Object o2) { return o1 == o2 || (o1 != null && o2 != null && o1.hashCode() == o2.hashCode() && o1.equals(o2)); } private int findIndex(final Object keyToFind) { final int hash = keyToFind.hashCode() << 1; /* hash ^= (hash >>> 20) ^ (hash >>> 12); * hash ^= (hash >>> 7) ^ (hash >>> 4); */ int probe = 1; int newIndex = hash & (data.length - 1); int thombStoneIndex = -1; int thombStoneCount = 0; final int thombStoneThreshold = Math.min((data.length>>1)-size, 100); // search until we find a free entry or an entry matching the key to insert while (data[newIndex] != null && !keysEqual(data[newIndex], keyToFind)) { if (data[newIndex] == THOMBSTONE) { if(thombStoneIndex == -1) thombStoneIndex = newIndex; thombStoneCount++; if(thombStoneCount * 2 > thombStoneThreshold) { compactify(0.f); thombStoneIndex = -1; probe = 0; thombStoneCount = 0; // not really necessary } } newIndex = (hash + probe + probe * probe) & (data.length - 1); probe++; } // if we didn't find an exact match then the first thombstone will do too for insert if (thombStoneIndex != -1 && !keysEqual(data[newIndex], keyToFind)) return thombStoneIndex; return newIndex; } private int nonModifyingFindIndex(final Object keyToFind) { final int hash = keyToFind.hashCode() << 1; /* hash ^= (hash >>> 20) ^ (hash >>> 12); * hash ^= (hash >>> 7) ^ (hash >>> 4); */ int probe = 1; int newIndex = hash & (data.length - 1); int thombStoneIndex = -1; // search until we find a free entry or an entry matching the key to insert while (data[newIndex] != null && !keysEqual(data[newIndex], keyToFind) && probe < (data.length>>1)) { if(data[newIndex] == THOMBSTONE && thombStoneIndex == -1) thombStoneIndex = newIndex; newIndex = (hash + probe + probe * probe) & (data.length - 1); probe++; } if (thombStoneIndex != -1 && !keysEqual(data[newIndex], keyToFind)) return thombStoneIndex; return newIndex; } private void checkCapacity(final int n) { final int currentCapacity = data.length>>1; if ((size + n) < currentCapacity * loadFactor) return; int newCapacity = currentCapacity; do newCapacity <<= 1; while (newCapacity * loadFactor < (size + n)); adjustCapacity(newCapacity); } /** * will shrink the internal storage size to the least possible amount, * should be used after removing many entries for example * * @param compactingLoadFactor * load factor for the compacting operation. Use 0f to compact * with the load factor specified during instantiation. Use * negative values of the desired load factors to compact only * when it would reduce the storage size. */ public void compactify(float compactingLoadFactor) { int newCapacity = 1; float adjustedLoadFactor = Math.abs(compactingLoadFactor); if (adjustedLoadFactor <= 0.f || adjustedLoadFactor >= 1.f) adjustedLoadFactor = loadFactor; while (newCapacity * adjustedLoadFactor < (size+1)) newCapacity <<= 1; if(newCapacity < data.length/2 || compactingLoadFactor >= 0.f ) adjustCapacity(newCapacity); } private void adjustCapacity(final int newSize) { final Object[] oldData = data; data = new Object[newSize*2]; size = 0; for (int i = 0; i < oldData.length; i+=2) { if (oldData[i] == null || oldData[i] == THOMBSTONE) continue; add(oldData[i], oldData[i+1], true); } } static void test() { final Random rnd = new Random(); final byte[] buffer = new byte[5]; final String[] fillData = new String[(int)((1<<21) * 0.93f)]; for (int i = 0; i < fillData.length; i++) { rnd.nextBytes(buffer); fillData[i] = new String(buffer); fillData[i].hashCode(); } long time; final Map m1 = new HashMap(); final Map m2 = new LightHashMap(); System.out.println("fill:"); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) m1.put(fillData[i], buffer); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) m2.put(fillData[i], buffer); System.out.println(System.currentTimeMillis() - time); System.out.println("replace-fill:"); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) m1.put(fillData[i], buffer); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) m2.put(fillData[i], buffer); System.out.println(System.currentTimeMillis() - time); System.out.println("get:"); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) m1.get(fillData[i]); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) m2.get(fillData[i]); System.out.println(System.currentTimeMillis() - time); System.out.println("compactify light map"); time = System.currentTimeMillis(); ((LightHashMap) m2).compactify(0.90f); System.out.println(System.currentTimeMillis() - time); System.out.println("transfer to hashmap"); time = System.currentTimeMillis(); new HashMap(m1); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); new HashMap(m2); System.out.println(System.currentTimeMillis() - time); System.out.println("transfer to lighthashmap"); time = System.currentTimeMillis(); new LightHashMap(m1); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); new LightHashMap(m2); System.out.println(System.currentTimeMillis() - time); System.out.println("remove entry by entry"); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) m1.remove(fillData[i]); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); for (int i = 0; i < fillData.length; i++) m2.remove(fillData[i]); System.out.println(System.currentTimeMillis() - time); } public static void main(final String[] args) { System.out.println("Call with -Xmx300m -Xcomp -server"); //Thread.currentThread().setPriority(Thread.MAX_PRIORITY); // some quadratic probing math test: /* boolean[] testArr = new boolean[1<<13]; int hash = 0xc8d3 << 1; int position = hash & (testArr.length -1); int probe = 0; do { position = (hash + probe + probe * probe) & (testArr.length - 1); probe++; testArr[position] = true; } while (probe < (testArr.length>>1)); for(int i = 0;i MAX_MAP_KEY_SIZE ){ String msg = "dictionary key is too large, max=" + MAX_MAP_KEY_SIZE + ": value=" + new String( keyBytes.array(), 0, 128 ); System.err.println( msg ); throw( new IOException( msg )); } CharBuffer cb = Constants.BYTE_CHARSET.decode(keyBytes); String key = new String(cb.array(),0,cb.limit()); // keys often repeat a lot - intern to save space if (internKeys) key = StringInterner.intern( key ); //decode value Object value = decodeInputStream(dbis,nesting+1,internKeys); // value interning is too CPU-intensive, let's skip that for now /*if(value instanceof byte[] && ((byte[])value).length < 17) value = StringInterner.internBytes((byte[])value);*/ if ( TRACE ){ System.out.println( key + "->" + value + ";" ); } // recover from some borked encodings that I have seen whereby the value has // not been encoded. This results in, for example, // 18:azureus_propertiesd0:e // we only get null back here if decoding has hit an 'e' or end-of-file // that is, there is no valid way for us to get a null 'value' here if ( value == null ){ System.err.println( "Invalid encoding - value not serialsied for '" + key + "' - ignoring" ); break; } if ( tempMap.put( key, value) != null ){ Debug.out( "BDecoder: key '" + key + "' already exists!" ); } } /* if ( tempMap.size() < 8 ){ tempMap = new CompactMap( tempMap ); }*/ dbis.mark(Integer.MAX_VALUE); tempByte = dbis.read(); dbis.reset(); if ( nesting > 0 && tempByte == -1 ){ throw( new BEncodingException( "BDecoder: invalid input data, 'e' missing from end of dictionary")); } }catch( Throwable e ){ if ( !recovery_mode ){ if ( e instanceof IOException ){ throw((IOException)e); } throw( new IOException( Debug.getNestedExceptionMessage(e))); } } if (tempMap instanceof LightHashMap) ((LightHashMap) tempMap).compactify(-0.9f); //return the map return tempMap; case 'l' : //create the list ArrayList tempList = new ArrayList(); try{ //create the key Object tempElement = null; while ((tempElement = decodeInputStream(dbis, nesting+1, internKeys)) != null) { //add the element tempList.add(tempElement); } tempList.trimToSize(); dbis.mark(Integer.MAX_VALUE); tempByte = dbis.read(); dbis.reset(); if ( nesting > 0 && tempByte == -1 ){ throw( new BEncodingException( "BDecoder: invalid input data, 'e' missing from end of list")); } }catch( Throwable e ){ if ( !recovery_mode ){ if ( e instanceof IOException ){ throw((IOException)e); } throw( new IOException( Debug.getNestedExceptionMessage(e))); } } //return the list return tempList; case 'e' : case -1 : return null; case 'i' : return Long.valueOf(getNumberFromStream(dbis, 'e')); case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : //move back one dbis.reset(); //get the string return getByteArrayFromStream(dbis); default :{ int rem_len = dbis.available(); if ( rem_len > 256 ){ rem_len = 256; } byte[] rem_data = new byte[rem_len]; dbis.read( rem_data ); throw( new BEncodingException( "BDecoder: unknown command '" + tempByte + ", remainder = " + new String( rem_data ))); } } } /* private long getNumberFromStream(InputStream dbis, char parseChar) throws IOException { StringBuffer sb = new StringBuffer(3); int tempByte = dbis.read(); while ((tempByte != parseChar) && (tempByte >= 0)) { sb.append((char)tempByte); tempByte = dbis.read(); } //are we at the end of the stream? if (tempByte < 0) { return -1; } String str = sb.toString(); // support some borked impls that sometimes don't bother encoding anything if ( str.length() == 0 ){ return( 0 ); } return Long.parseLong(str); } */ /** only create the array once per decoder instance (no issues with recursion as it's only used in a leaf method) */ private final char[] numberChars = new char[32]; private long getNumberFromStream( InputStream dbis, char parseChar) throws IOException { int tempByte = dbis.read(); int pos = 0; while ((tempByte != parseChar) && (tempByte >= 0)) { numberChars[pos++] = (char)tempByte; if ( pos == numberChars.length ){ throw( new NumberFormatException( "Number too large: " + new String(numberChars,0,pos) + "..." )); } tempByte = dbis.read(); } //are we at the end of the stream? if (tempByte < 0) { return -1; }else if ( pos == 0 ){ // support some borked impls that sometimes don't bother encoding anything return(0); } try{ return( parseLong( numberChars, 0, pos )); }catch( NumberFormatException e ){ String temp = new String( numberChars, 0, pos ); try{ double d = Double.parseDouble( temp ); long l = (long)d; Debug.out( "Invalid number '" + temp + "' - decoding as " + l + " and attempting recovery" ); return( l ); }catch( Throwable f ){ } throw( e ); } } // This is similar to Long.parseLong(String) source // It is also used in projects external to azureus2/azureus3 hence it is public public static long parseLong( char[] chars, int start, int length ) { if ( length > 0 ){ // Short Circuit: We don't support octal parsing, so if it // starts with 0, it's 0 if (chars[start] == '0') { return 0; } long result = 0; boolean negative = false; int i = start; long limit; if ( chars[i] == '-' ){ negative = true; limit = Long.MIN_VALUE; i++; }else{ // Short Circuit: If we are only processing one char, // and it wasn't a '-', just return that digit instead // of doing the negative junk if (length == 1) { int digit = chars[i] - '0'; if ( digit < 0 || digit > 9 ){ throw new NumberFormatException(new String(chars,start,length)); }else{ return digit; } } limit = -Long.MAX_VALUE; } int max = start + length; if ( i < max ){ int digit = chars[i++] - '0'; if ( digit < 0 || digit > 9 ){ throw new NumberFormatException(new String(chars,start,length)); }else{ result = -digit; } } long multmin = limit / 10; while ( i < max ){ // Accumulating negatively avoids surprises near MAX_VALUE int digit = chars[i++] - '0'; if ( digit < 0 || digit > 9 ){ throw new NumberFormatException(new String(chars,start,length)); } if ( result < multmin ){ throw new NumberFormatException(new String(chars,start,length)); } result *= 10; if ( result < limit + digit ){ throw new NumberFormatException(new String(chars,start,length)); } result -= digit; } if ( negative ){ if ( i > start+1 ){ return result; }else{ /* Only got "-" */ throw new NumberFormatException(new String(chars,start,length)); } }else{ return -result; } }else{ throw new NumberFormatException(new String(chars,start,length)); } } // This one causes lots of "Query Information" calls to the filesystem /* private long getNumberFromStreamOld(InputStream dbis, char parseChar) throws IOException { int length = 0; //place a mark dbis.mark(Integer.MAX_VALUE); int tempByte = dbis.read(); while ((tempByte != parseChar) && (tempByte >= 0)) { tempByte = dbis.read(); length++; } //are we at the end of the stream? if (tempByte < 0) { return -1; } //reset the mark dbis.reset(); //get the length byte[] tempArray = new byte[length]; int count = 0; int len = 0; //get the string while (count != length && (len = dbis.read(tempArray, count, length - count)) > 0) { count += len; } //jump ahead in the stream to compensate for the : dbis.skip(1); //return the value CharBuffer cb = Constants.DEFAULT_CHARSET.decode(ByteBuffer.wrap(tempArray)); String str_value = new String(cb.array(),0,cb.limit()); return Long.parseLong(str_value); } */ private byte[] getByteArrayFromStream( InputStream dbis ) throws IOException { int length = (int) getNumberFromStream(dbis, ':'); if (length < 0) { return null; } // note that torrent hashes can be big (consider a 55GB file with 2MB pieces // this generates a pieces hash of 1/2 meg if ( length > MAX_BYTE_ARRAY_SIZE ){ throw( new IOException( "Byte array length too large (" + length + ")")); } byte[] tempArray = new byte[length]; getByteArrayFromStream(dbis, length, tempArray); return tempArray; } private void getByteArrayFromStream(InputStream dbis, int length, byte[] targetArray) throws IOException { int count = 0; int len = 0; //get the string while (count != length && (len = dbis.read(targetArray, count, length - count)) > 0) count += len; if (count != length) throw (new IOException("BDecoder::getByteArrayFromStream: truncated")); } public void setRecoveryMode( boolean r ) { recovery_mode = r; } public static void print( Object obj ) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter( sw ); print( pw, obj ); pw.flush(); System.out.println( sw.toString()); } public static void print( PrintWriter writer, Object obj ) { print( writer, obj, "", false ); } private static void print( PrintWriter writer, Object obj, String indent, boolean skip_indent ) { String use_indent = skip_indent?"":indent; if ( obj instanceof Long ){ writer.println( use_indent + obj ); }else if ( obj instanceof byte[]){ byte[] b = (byte[])obj; if ( b.length==20 ){ writer.println( use_indent + " { "+ ByteFormatter.nicePrint( b )+ " }" ); }else if ( b.length < 64 ){ writer.println( new String(b) + " [" + ByteFormatter.encodeString( b ) + "]" ); }else{ writer.println( "[byte array length " + b.length ); } }else if ( obj instanceof String ){ writer.println( use_indent + obj ); }else if ( obj instanceof List ){ List l = (List)obj; writer.println( use_indent + "[" ); for (int i=0;i 256 ){ writer.print( indent + key.substring(0,256) + "... = " ); }else{ writer.print( indent + key + " = " ); } print( writer, m.get(key), indent + " ", true ); } } } /** * Converts any byte[] entries into UTF-8 strings * @param map * @return */ public static Map decodeStrings( Map map ) { if (map == null ){ return( null ); } Iterator it = map.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); Object value = entry.getValue(); if ( value instanceof byte[]){ try{ entry.setValue( new String((byte[])value,"UTF-8" )); }catch( Throwable e ){ System.err.println(e); } }else if ( value instanceof Map ){ decodeStrings((Map)value ); }else if ( value instanceof List ){ decodeStrings((List)value ); } } return( map ); } public static List decodeStrings( List list ) { if ( list == null ){ return( null ); } for (int i=0;i= count ){ return( -1 ); } if ( pos + length > count ){ length = count - pos; } if (length <= 0){ return( 0 ); } System.arraycopy(buffer, pos, b, offset, length); pos += length; return( length ); } public int available() throws IOException { return( count - pos ); } public boolean markSupported() { return( true ); } public void mark( int limit ) { mark = pos; } public void reset() throws IOException { pos = mark; } } public static void main( String[] args ) { print( new File( "C:\\Temp\\tables.config" ), new File( "C:\\Temp\\tables.txt" )); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AERunnableBoolean.java0000644000175000017500000000355411267524616024305 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author TuxPaper * @created Mar 21, 2007 * */ public abstract class AERunnableBoolean implements Runnable { private boolean[] returnValueObject; private AESemaphore sem; private String id = "AEReturningRunnable"; public void run() { try { //System.out.println(this + "]" + id + " run start"); boolean b = runSupport(); //System.out.println(this + "]" + id + " runSupport Done: ret=" + b); if (returnValueObject != null && returnValueObject.length > 0) { returnValueObject[0] = b; } } catch (Throwable e) { Debug.out(id, e); } finally { //System.out.println(this + "]" + id + " sem=" + sem); if (sem != null) { //System.out.println(this + "]" + id + " sem Release"); sem.releaseForever(); } } } public void setupReturn(String ID, boolean[] returnValueObject, AESemaphore sem) { id = ID; this.returnValueObject = returnValueObject; this.sem = sem; } public abstract boolean runSupport(); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/ListenerManager.java0000644000175000017500000003046011264071660024076 0ustar adrianadrian/* * File : ListenerManager.java * Created : 15-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author parg * */ /** * This class exists to support the invocation of listeners while *not* synchronized. * This is important as in general it is a bad idea to invoke an "external" component * whilst holding a lock on something as unexpected deadlocks can result. * It has been introduced to reduce the likelyhood of such deadlocks */ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; public class ListenerManager { private static final boolean TIME_LISTENERS = false; public static ListenerManager createManager( String name, ListenerManagerDispatcher target ) { return( new ListenerManager( name, target, false )); } public static ListenerManager createAsyncManager( String name, ListenerManagerDispatcher target ) { return( new ListenerManager( name, target, true )); } protected String name; protected ListenerManagerDispatcher target; protected ListenerManagerDispatcherWithException target_with_exception; protected boolean async; protected AEThread2 async_thread; protected List listeners = new ArrayList(0); protected List dispatch_queue; protected AESemaphore dispatch_sem; protected ListenerManager( String _name, ListenerManagerDispatcher _target, boolean _async ) { name = _name; target = _target; async = _async; if ( target instanceof ListenerManagerDispatcherWithException ){ target_with_exception = (ListenerManagerDispatcherWithException)target; } if ( async ){ dispatch_sem = new AESemaphore("ListenerManager::"+name); dispatch_queue = new LinkedList(); if ( target_with_exception != null ){ throw( new RuntimeException( "Can't have an async manager with exceptions!")); } } } public void addListener( T listener ) { synchronized( this ){ ArrayList new_listeners = new ArrayList( listeners ); if (new_listeners.contains(listener)) { Logger.log(new LogEvent(LogIDs.CORE, LogEvent.LT_WARNING, "addListener called but listener already added for " + name + "\n\t" + Debug.getStackTrace(true, false))); } new_listeners.add( listener ); if (new_listeners.size() > 50) { Logger.log(new LogEvent(LogIDs.CORE, LogEvent.LT_WARNING, "addListener: over 50 listeners added for " + name + "\n\t" + Debug.getStackTrace(true, false))); } listeners = new_listeners; if ( async && async_thread == null ){ async_thread = new AEThread2( name, true ) { public void run() { dispatchLoop(); } }; async_thread.start(); } } } public void removeListener( Object listener ) { synchronized( this ){ ArrayList new_listeners = new ArrayList( listeners ); new_listeners.remove( listener ); listeners = new_listeners; if ( async && listeners.size() == 0 ){ async_thread = null; // try and wake up the thread so it kills itself dispatch_sem.release(); } } } public boolean hasListener( T listener ) { synchronized( this ){ return( listeners.contains( listener )); } } public void clear() { synchronized( this ){ listeners = new ArrayList(); if ( async ){ async_thread = null; // try and wake up the thread so it kills itself dispatch_sem.release(); } } } public List getListenersCopy() { // we can just return the listeners as we copy on update return( listeners ); } public void dispatch( int type, Object value ) { dispatch( type, value, false ); } public void dispatch( int type, Object value, boolean blocking ) { if ( async ){ AESemaphore sem = null; if ( blocking ){ sem = new AESemaphore( "ListenerManager:blocker"); } synchronized( this ){ // if there's nobody listening then no point in queueing if ( listeners.size() == 0 ){ return; } // listeners are "copy on write" updated, hence we grab a reference to the // current listeners here. Any subsequent change won't affect our listeners dispatch_queue.add(new Object[]{listeners, new Integer(type), value, sem }); } dispatch_sem.release(); if ( sem != null ){ sem.reserve(); } }else{ if ( target_with_exception != null ){ throw( new RuntimeException( "call dispatchWithException, not dispatch")); } List listeners_ref; synchronized( this ){ listeners_ref = listeners; } try{ dispatchInternal( listeners_ref, type, value ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } public void dispatchWithException( int type, Object value ) throws Throwable { List listeners_ref; synchronized( this ){ listeners_ref = listeners; } dispatchInternal( listeners_ref, type, value ); } public void dispatch( T listener, int type, Object value ) { dispatch( listener, type, value, false ); } public void dispatch( T listener, int type, Object value, boolean blocking ) { if ( async ){ AESemaphore sem = null; if ( blocking ){ sem = new AESemaphore( "ListenerManager:blocker"); } synchronized( this ){ // 5 entries to denote single listener dispatch_queue.add(new Object[]{ listener, new Integer(type), value, sem, null }); if ( async_thread == null ){ async_thread = new AEThread2( name, true ) { public void run() { dispatchLoop(); } }; async_thread.start(); } } dispatch_sem.release(); if ( sem != null ){ sem.reserve(); } }else{ if ( target_with_exception != null ){ throw( new RuntimeException( "call dispatchWithException, not dispatch")); } doDispatch( listener, type, value ); } } protected String getListenerName( T listener ) { Class listener_class = listener.getClass(); String res = listener_class.getName(); try{ Method getString = listener_class.getMethod( "getString", new Class[0]); if ( getString != null ){ String s = (String)getString.invoke( listener, new Object[0] ); res += " (" + s + ")"; } }catch( Throwable e ){ } return( res ); } protected void doDispatch( T listener, int type, Object value ) { try{ if ( TIME_LISTENERS ){ long start = SystemTime.getCurrentTime(); try{ target.dispatch( listener, type, value ); }finally{ long duration = SystemTime.getCurrentTime() - start; System.out.println( name + "/" + type + ": " + getListenerName( listener ) + " - " + duration ); } }else{ target.dispatch( listener, type, value ); } }catch( Throwable e ){ Debug.printStackTrace( e ); } } protected void doDispatchWithException( T listener, int type, Object value ) throws Throwable { if ( TIME_LISTENERS ){ long start = SystemTime.getCurrentTime(); try{ target_with_exception.dispatchWithException( listener, type, value ); }finally{ long duration = SystemTime.getCurrentTime() - start; System.out.println( name + "/" + type + ": " + getListenerName( listener ) + " - " + duration ); } }else{ target_with_exception.dispatchWithException( listener, type, value ); } } protected void dispatchInternal( List listeners_ref, int type, Object value ) throws Throwable { for (int i=0;i 0 ){ data = (Object[])dispatch_queue.remove(0); } } if ( data != null ){ try{ if ( data.length == 4 ){ dispatchInternal((List)data[0], ((Integer)data[1]).intValue(), data[2] ); }else{ dispatchInternal((T)data[0], ((Integer)data[1]).intValue(), data[2] ); } }catch( Throwable e ){ Debug.printStackTrace( e ); }finally{ if ( data[3] != null ){ ((AESemaphore)data[3]).release(); } } } } // System.out.println( "ListenerManager::dispatch thread '" + Thread.currentThread() + "' ends"); } public static void dispatchWithTimeout( List _listeners, final ListenerManagerDispatcher _dispatcher, long _timeout ) { final List listeners = new ArrayList( _listeners ); final boolean[] completed = new boolean[listeners.size()]; final AESemaphore timeout_sem = new AESemaphore("ListenerManager:dwt:timeout"); for (int i=0;i start ){ _timeout = _timeout - ( end - start ); } } if ( timeout_occurred ){ String str = ""; for (int i=0;i 0 ){ Debug.out( "Listener dispatch timeout: failed = " + str ); } } } public long size() { if (listeners == null) return 0; return listeners.size(); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/DisplayFormatters.java0000644000175000017500000007440711252017366024503 0ustar adrianadrian/* * File : DisplayFormatters.java * Created : 07-Oct-2003 * By : gardnerpar * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author gardnerpar * */ import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; import java.text.NumberFormat; import org.gudy.azureus2.core3.download.*; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.internat.*; public class DisplayFormatters { final private static boolean ROUND_NO = true; //final private static boolean ROUND_YES = false; final private static boolean TRUNCZEROS_NO = false; final private static boolean TRUNCZEROS_YES = true; final public static int UNIT_B = 0; final public static int UNIT_KB = 1; final public static int UNIT_MB = 2; final public static int UNIT_GB = 3; final public static int UNIT_TB = 4; final private static int UNITS_PRECISION[] = { 0, // B 1, //KB 2, //MB 2, //GB 3 //TB }; final private static NumberFormat[] cached_number_formats = new NumberFormat[20]; private static NumberFormat percentage_format; private static String[] units; private static String[] units_bits; private static String[] units_rate; private static int unitsStopAt = UNIT_TB; private static String[] units_base10; private static String per_sec; private static boolean use_si_units; private static boolean force_si_values; private static boolean use_units_rate_bits; private static boolean not_use_GB_TB; private static int message_text_state = 0; private static boolean separate_prot_data_stats; private static boolean data_stats_only; private static char decimalSeparator; static{ COConfigurationManager.addAndFireParameterListeners( new String[]{ "config.style.useSIUnits", "config.style.forceSIValues", "config.style.useUnitsRateBits", "config.style.doNotUseGB", }, new ParameterListener() { public void parameterChanged( String x ) { use_si_units = COConfigurationManager.getBooleanParameter("config.style.useSIUnits"); force_si_values = COConfigurationManager.getBooleanParameter("config.style.forceSIValues"); use_units_rate_bits = COConfigurationManager.getBooleanParameter("config.style.useUnitsRateBits"); not_use_GB_TB = COConfigurationManager.getBooleanParameter("config.style.doNotUseGB"); unitsStopAt = (not_use_GB_TB) ? UNIT_MB : UNIT_TB; setUnits(); } }); COConfigurationManager.addListener( new COConfigurationListener() { public void configurationSaved() { setUnits(); loadMessages(); } }); COConfigurationManager.addAndFireParameterListeners( new String[]{ "config.style.dataStatsOnly", "config.style.separateProtDataStats" }, new ParameterListener() { public void parameterChanged( String x ) { separate_prot_data_stats = COConfigurationManager.getBooleanParameter("config.style.separateProtDataStats"); data_stats_only = COConfigurationManager.getBooleanParameter("config.style.dataStatsOnly"); } }); setUnits(); loadMessages(); } public static void setUnits() { // (1) http://physics.nist.gov/cuu/Units/binary.html // (2) http://www.isi.edu/isd/LOOM/documentation/unit-definitions.text units = new String[unitsStopAt + 1]; units_bits = new String[unitsStopAt + 1]; units_rate = new String[unitsStopAt + 1]; if ( use_si_units ){ // fall through intentional switch (unitsStopAt) { case UNIT_TB: units[UNIT_TB] = getUnit("TiB"); units_bits[UNIT_TB] = getUnit("Tibit"); units_rate[UNIT_TB] = (use_units_rate_bits) ? getUnit("Tibit") : getUnit("TiB"); case UNIT_GB: units[UNIT_GB]= getUnit("GiB"); units_bits[UNIT_GB]= getUnit("Gibit"); units_rate[UNIT_GB] = (use_units_rate_bits) ? getUnit("Gibit") : getUnit("GiB"); case UNIT_MB: units[UNIT_MB] = getUnit("MiB"); units_bits[UNIT_MB] = getUnit("Mibit"); units_rate[UNIT_MB] = (use_units_rate_bits) ? getUnit("Mibit") : getUnit("MiB"); case UNIT_KB: // can be upper or lower case k units[UNIT_KB] = getUnit("KiB"); units_bits[UNIT_KB] = getUnit("Kibit"); // can be upper or lower case k, upper more consistent units_rate[UNIT_KB] = (use_units_rate_bits) ? getUnit("Kibit") : getUnit("KiB"); case UNIT_B: units[UNIT_B] = getUnit("B"); units_bits[UNIT_B] = getUnit("bit"); units_rate[UNIT_B] = (use_units_rate_bits) ? getUnit("bit") : getUnit("B"); } }else{ switch (unitsStopAt) { case UNIT_TB: units[UNIT_TB] = getUnit("TB"); units_bits[UNIT_TB] = getUnit("Tbit"); units_rate[UNIT_TB] = (use_units_rate_bits) ? getUnit("Tbit") : getUnit("TB"); case UNIT_GB: units[UNIT_GB]= getUnit("GB"); units_bits[UNIT_GB]= getUnit("Gbit"); units_rate[UNIT_GB] = (use_units_rate_bits) ? getUnit("Gbit") : getUnit("GB"); case UNIT_MB: units[UNIT_MB] = getUnit("MB"); units_bits[UNIT_MB] = getUnit("Mbit"); units_rate[UNIT_MB] = (use_units_rate_bits) ? getUnit("Mbit") : getUnit("MB"); case UNIT_KB: // yes, the k should be lower case units[UNIT_KB] = getUnit("kB"); units_bits[UNIT_KB] = getUnit("kbit"); units_rate[UNIT_KB] = (use_units_rate_bits) ? getUnit("kbit") : getUnit("kB"); case UNIT_B: units[UNIT_B] = getUnit("B"); units_bits[UNIT_B] = getUnit("bit"); units_rate[UNIT_B] = (use_units_rate_bits) ? getUnit("bit") : getUnit("B"); } } per_sec = getResourceString( "Formats.units.persec", "/s" ); units_base10 = new String[]{ getUnit( "B"), getUnit("KB"), getUnit( "MB" ), getUnit( "GB"), getUnit( "TB" ) }; for (int i = 0; i <= unitsStopAt; i++) { units[i] = units[i]; units_rate[i] = units_rate[i] + per_sec; } Arrays.fill( cached_number_formats, null ); percentage_format = NumberFormat.getPercentInstance(); percentage_format.setMinimumFractionDigits(1); percentage_format.setMaximumFractionDigits(1); decimalSeparator = new DecimalFormatSymbols().getDecimalSeparator(); } private static String getUnit( String key ) { String res = " " + getResourceString( "Formats.units." + key, key ); return( res ); } private static String PeerManager_status_finished; private static String PeerManager_status_finishedin; private static String Formats_units_alot; private static String discarded; private static String ManagerItem_waiting; private static String ManagerItem_initializing; private static String ManagerItem_allocating; private static String ManagerItem_checking; private static String ManagerItem_finishing; private static String ManagerItem_ready; private static String ManagerItem_downloading; private static String ManagerItem_seeding; private static String ManagerItem_superseeding; private static String ManagerItem_stopping; private static String ManagerItem_stopped; private static String ManagerItem_paused; private static String ManagerItem_queued; private static String ManagerItem_error; private static String ManagerItem_forced; private static String yes; private static String no; public static void loadMessages() { PeerManager_status_finished = getResourceString( "PeerManager.status.finished", "Finished" ); PeerManager_status_finishedin = getResourceString( "PeerManager.status.finishedin", "Finished in" ); Formats_units_alot = getResourceString( "Formats.units.alot", "A lot" ); discarded = getResourceString( "discarded", "discarded" ); ManagerItem_waiting = getResourceString( "ManagerItem.waiting", "waiting" ); ManagerItem_initializing = getResourceString( "ManagerItem.initializing", "initializing" ); ManagerItem_allocating = getResourceString( "ManagerItem.allocating", "allocating" ); ManagerItem_checking = getResourceString( "ManagerItem.checking", "checking" ); ManagerItem_finishing = getResourceString( "ManagerItem.finishing", "finishing" ); ManagerItem_ready = getResourceString( "ManagerItem.ready", "ready" ); ManagerItem_downloading = getResourceString( "ManagerItem.downloading", "downloading" ); ManagerItem_seeding = getResourceString( "ManagerItem.seeding", "seeding" ); ManagerItem_superseeding = getResourceString( "ManagerItem.superseeding", "superseeding" ); ManagerItem_stopping = getResourceString( "ManagerItem.stopping", "stopping" ); ManagerItem_stopped = getResourceString( "ManagerItem.stopped", "stopped" ); ManagerItem_paused = getResourceString( "ManagerItem.paused", "paused" ); ManagerItem_queued = getResourceString( "ManagerItem.queued", "queued" ); ManagerItem_error = getResourceString( "ManagerItem.error", "error" ); ManagerItem_forced = getResourceString( "ManagerItem.forced", "forced" ); yes = getResourceString( "GeneralView.yes", "Yes" ); no = getResourceString( "GeneralView.no", "No" ); } private static String getResourceString( String key, String def ) { if ( message_text_state == 0 ){ // this fooling around is to permit the use of this class in the absence of the (large) overhead // of resource bundles try{ MessageText.class.getName(); message_text_state = 1; }catch( Throwable e ){ message_text_state = 2; } } if ( message_text_state == 1 ){ return( MessageText.getString( key )); }else{ return( def ); } } public static String getYesNo( boolean b ) { return( b?yes:no ); } public static String getRateUnit( int unit_size ) { return( units_rate[unit_size].substring(1, units_rate[unit_size].length()) ); } public static String getUnit( int unit_size ) { return( units[unit_size].substring(1, units[unit_size].length()) ); } public static String getRateUnitBase10(int unit_size) { return units_base10[unit_size] + per_sec; } public static String getUnitBase10(int unit_size) { return units_base10[unit_size]; } public static boolean isRateUsingBits() { return( use_units_rate_bits ); } public static String formatByteCountToKiBEtc(int n) { return( formatByteCountToKiBEtc((long)n)); } public static String formatByteCountToKiBEtc( long n ) { return( formatByteCountToKiBEtc( n, false, TRUNCZEROS_NO)); } public static String formatByteCountToKiBEtc( long n, boolean bTruncateZeros ) { return( formatByteCountToKiBEtc( n, false, bTruncateZeros )); } public static String formatByteCountToKiBEtc( long n, boolean rate, boolean bTruncateZeros) { return formatByteCountToKiBEtc(n, rate, bTruncateZeros, -1); } public static String formatByteCountToKiBEtc( long n, boolean rate, boolean bTruncateZeros, int precision) { double dbl = (rate && use_units_rate_bits) ? n * 8 : n; int unitIndex = UNIT_B; long div = force_si_values?1024:(use_si_units?1024:1000); while (dbl >= div && unitIndex < unitsStopAt){ dbl /= div; unitIndex++; } if (precision < 0) { precision = UNITS_PRECISION[unitIndex]; } // round for rating, because when the user enters something like 7.3kbps // they don't want it truncated and displayed as 7.2 // (7.3*1024 = 7475.2; 7475/1024.0 = 7.2998; trunc(7.2998, 1 prec.) == 7.2 // // Truncate for rest, otherwise we get complaints like: // "I have a 1.0GB torrent and it says I've downloaded 1.0GB.. why isn't // it complete? waaah" return formatDecimal(dbl, precision, bTruncateZeros, rate) + (rate ? units_rate[unitIndex] : units[unitIndex]); } public static boolean isDataProtSeparate() { return( separate_prot_data_stats ); } public static String formatDataProtByteCountToKiBEtc( long data, long prot ) { if ( separate_prot_data_stats ){ if ( data == 0 && prot == 0 ){ return( formatByteCountToKiBEtc(0)); }else if ( data == 0 ){ return( "(" + formatByteCountToKiBEtc( prot) + ")"); }else if ( prot == 0 ){ return( formatByteCountToKiBEtc( data )); }else{ return(formatByteCountToKiBEtc(data)+" ("+ formatByteCountToKiBEtc(prot)+")"); } }else if ( data_stats_only ){ return( formatByteCountToKiBEtc( data )); }else{ return( formatByteCountToKiBEtc( prot + data )); } } public static String formatDataProtByteCountToKiBEtcPerSec( long data, long prot ) { if ( separate_prot_data_stats ){ if ( data == 0 && prot == 0 ){ return(formatByteCountToKiBEtcPerSec(0)); }else if ( data == 0 ){ return( "(" + formatByteCountToKiBEtcPerSec( prot) + ")"); }else if ( prot == 0 ){ return( formatByteCountToKiBEtcPerSec( data )); }else{ return(formatByteCountToKiBEtcPerSec(data)+" ("+ formatByteCountToKiBEtcPerSec(prot)+")"); } }else if ( data_stats_only ){ return( formatByteCountToKiBEtcPerSec( data )); }else{ return( formatByteCountToKiBEtcPerSec( prot + data )); } } public static String formatByteCountToKiBEtcPerSec( long n ) { return( formatByteCountToKiBEtc(n,true,TRUNCZEROS_NO)); } public static String formatByteCountToKiBEtcPerSec( long n, boolean bTruncateZeros) { return( formatByteCountToKiBEtc(n,true, bTruncateZeros)); } // base 10 ones public static String formatByteCountToBase10KBEtc( long n) { if (n < 1000){ return n + units_base10[UNIT_B]; }else if (n < 1000 * 1000){ return (n / 1000) + "." + ((n % 1000) / 100) + units_base10[UNIT_KB]; }else if ( n < 1000L * 1000L * 1000L || not_use_GB_TB ){ return (n / (1000L * 1000L)) + "." + ((n % (1000L * 1000L)) / (1000L * 100L)) + units_base10[UNIT_MB]; }else if (n < 1000L * 1000L * 1000L * 1000L){ return (n / (1000L * 1000L * 1000L)) + "." + ((n % (1000L * 1000L * 1000L)) / (1000L * 1000L * 100L))+ units_base10[UNIT_GB]; }else if (n < 1000L * 1000L * 1000L * 1000L* 1000L){ return (n / (1000L * 1000L * 1000L* 1000L)) + "." + ((n % (1000L * 1000L * 1000L* 1000L)) / (1000L * 1000L * 1000L* 100L))+ units_base10[UNIT_TB]; }else{ return Formats_units_alot; } } public static String formatByteCountToBase10KBEtcPerSec( long n ) { return( formatByteCountToBase10KBEtc(n) + per_sec ); } /** * Print the BITS/second in an international format. * @param n - * @return String in an internationalized format. */ public static String formatByteCountToBitsPerSec( long n) { return formatBitCountToKiBEtcLocalImpl(n,true,true,-1,true); } /** * NOTE: This method is a copy of formatByteCountToKiBEtc. Since the "use_units_rate_bits" member is * static it cannot be used in a local context. Thus this method. More refactoring of this area * should be done. Also need testing of the method to make sure units are accurate. * * Takes a long value that is bytes/bits download and converts it into internationalized units. * @param n - value * @param rate - true if in ? per second. Otherwise false. * @param bTruncateZeros - true if truncating zeros. * @param precision - negative value if same as units. * @param useBits - true if using BITS, otherwise using BYTES. * @return String - with units internationalized properly. */ public static String formatBitCountToKiBEtcLocalImpl( long n, boolean rate, boolean bTruncateZeros, int precision, boolean useBits) { double dbl = (rate && useBits) ? n * 8 : n; int unitIndex = UNIT_B; long div = force_si_values?1024:(use_si_units?1024:1000); while (dbl >= div && unitIndex < unitsStopAt){ dbl /= div; unitIndex++; } if (precision < 0) { precision = UNITS_PRECISION[unitIndex]; } return formatDecimal(dbl, precision, bTruncateZeros, rate) + units_bits[unitIndex] + (rate?per_sec:""); } public static String formatETA(long eta) { if (eta == 0) return PeerManager_status_finished; if (eta == -1) return ""; if (eta > 0) return TimeFormatter.format(eta); return PeerManager_status_finishedin + " " + TimeFormatter.format(eta * -1); } public static String formatDownloaded( DownloadManagerStats stats ) { long total_discarded = stats.getDiscarded(); long total_received = stats.getTotalGoodDataBytesReceived(); if(total_discarded == 0){ return formatByteCountToKiBEtc(total_received); }else{ return formatByteCountToKiBEtc(total_received) + " ( " + DisplayFormatters.formatByteCountToKiBEtc(total_discarded) + " " + discarded + " )"; } } public static String formatHashFails( DownloadManager download_manager ) { TOTorrent torrent = download_manager.getTorrent(); if ( torrent != null ){ long bad = download_manager.getStats().getHashFailBytes(); // size can exceed int so ensure longs used in multiplication long count = bad / (long)torrent.getPieceLength(); String result = count + " ( " + formatByteCountToKiBEtc(bad) + " )"; return result; } return ""; } public static String formatDownloadStatus( DownloadManager manager ) { int state = manager.getState(); String tmp = ""; switch (state) { case DownloadManager.STATE_QUEUED: tmp = ManagerItem_queued; break; case DownloadManager.STATE_DOWNLOADING: tmp = ManagerItem_downloading; break; case DownloadManager.STATE_SEEDING:{ DiskManager diskManager = manager.getDiskManager(); if ((diskManager != null) && diskManager.getCompleteRecheckStatus() != -1) { int done = diskManager.getCompleteRecheckStatus(); if (done == -1) { done = 1000; } tmp = ManagerItem_seeding + " + " + ManagerItem_checking + ": " + formatPercentFromThousands(done); } else if (manager.getPeerManager() != null && manager.getPeerManager().isSuperSeedMode()) { tmp = ManagerItem_superseeding; } else { tmp = ManagerItem_seeding; } break; } case DownloadManager.STATE_STOPPED: tmp = manager.isPaused() ? ManagerItem_paused : ManagerItem_stopped; break; case DownloadManager.STATE_ERROR: tmp = ManagerItem_error + ": " + manager.getErrorDetails(); break; case DownloadManager.STATE_WAITING: tmp = ManagerItem_waiting; break; case DownloadManager.STATE_INITIALIZING: tmp = ManagerItem_initializing; break; case DownloadManager.STATE_INITIALIZED: tmp = ManagerItem_initializing; break; case DownloadManager.STATE_ALLOCATING:{ tmp = ManagerItem_allocating; DiskManager diskManager = manager.getDiskManager(); if (diskManager != null){ tmp += ": " + formatPercentFromThousands( diskManager.getPercentDone()); } break; } case DownloadManager.STATE_CHECKING: tmp = ManagerItem_checking + ": " + formatPercentFromThousands(manager.getStats().getCompleted()); break; case DownloadManager.STATE_FINISHING: tmp = ManagerItem_finishing; break; case DownloadManager.STATE_READY: tmp = ManagerItem_ready; break; case DownloadManager.STATE_STOPPING: tmp = ManagerItem_stopping; break; default: tmp = String.valueOf(state); } if (manager.isForceStart() && (state == DownloadManager.STATE_SEEDING || state == DownloadManager.STATE_DOWNLOADING)) tmp = ManagerItem_forced + " " + tmp; return( tmp ); } public static String formatDownloadStatusDefaultLocale( DownloadManager manager ) { int state = manager.getState(); String tmp = ""; DiskManager dm = manager.getDiskManager(); switch (state) { case DownloadManager.STATE_WAITING : tmp = MessageText.getDefaultLocaleString("ManagerItem.waiting"); break; case DownloadManager.STATE_INITIALIZING : tmp = MessageText.getDefaultLocaleString("ManagerItem.initializing"); break; case DownloadManager.STATE_INITIALIZED : tmp = MessageText.getDefaultLocaleString("ManagerItem.initializing"); break; case DownloadManager.STATE_ALLOCATING : tmp = MessageText.getDefaultLocaleString("ManagerItem.allocating"); break; case DownloadManager.STATE_CHECKING : tmp = MessageText.getDefaultLocaleString("ManagerItem.checking"); break; case DownloadManager.STATE_FINISHING : tmp = MessageText.getDefaultLocaleString("ManagerItem.finishing"); break; case DownloadManager.STATE_READY : tmp = MessageText.getDefaultLocaleString("ManagerItem.ready"); break; case DownloadManager.STATE_DOWNLOADING : tmp = MessageText.getDefaultLocaleString("ManagerItem.downloading"); break; case DownloadManager.STATE_SEEDING : if (dm != null && dm.getCompleteRecheckStatus() != -1 ) { int done = dm.getCompleteRecheckStatus(); if ( done == -1 ){ done = 1000; } tmp = MessageText.getDefaultLocaleString("ManagerItem.seeding") + " + " + MessageText.getDefaultLocaleString("ManagerItem.checking") + ": " + formatPercentFromThousands( done ); } else if(manager.getPeerManager()!= null && manager.getPeerManager().isSuperSeedMode()){ tmp = MessageText.getDefaultLocaleString("ManagerItem.superseeding"); } else { tmp = MessageText.getDefaultLocaleString("ManagerItem.seeding"); } break; case DownloadManager.STATE_STOPPING : tmp = MessageText.getDefaultLocaleString("ManagerItem.stopping"); break; case DownloadManager.STATE_STOPPED : tmp = MessageText.getDefaultLocaleString(manager.isPaused()?"ManagerItem.paused":"ManagerItem.stopped"); break; case DownloadManager.STATE_QUEUED : tmp = MessageText.getDefaultLocaleString("ManagerItem.queued"); break; case DownloadManager.STATE_ERROR : tmp = MessageText.getDefaultLocaleString("ManagerItem.error").concat(": ").concat(manager.getErrorDetails()); //$NON-NLS-1$ //$NON-NLS-2$ break; default : tmp = String.valueOf(state); } return( tmp ); } public static String trimDigits( String str, int num_digits ) { char[] chars = str.toCharArray(); String res = ""; int digits = 0; for (int i=0;i= 3 ){ }else{ res += c; } } return( res ); } public static String formatPercentFromThousands(int thousands) { return percentage_format.format(thousands / 1000.0); } public static String formatTimeStamp(long time) { StringBuffer sb = new StringBuffer(); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(time); sb.append('['); sb.append(formatIntToTwoDigits(calendar.get(Calendar.DAY_OF_MONTH))); sb.append('.'); sb.append(formatIntToTwoDigits(calendar.get(Calendar.MONTH)+1)); // 0 based sb.append('.'); sb.append(calendar.get(Calendar.YEAR)); sb.append(' '); sb.append(formatIntToTwoDigits(calendar.get(Calendar.HOUR_OF_DAY))); sb.append(':'); sb.append(formatIntToTwoDigits(calendar.get(Calendar.MINUTE))); sb.append(':'); sb.append(formatIntToTwoDigits(calendar.get(Calendar.SECOND))); sb.append(']'); return sb.toString(); } public static String formatIntToTwoDigits(int n) { return n < 10 ? "0".concat(String.valueOf(n)) : String.valueOf(n); } private static String formatDate(long date, String format) { if (date == 0) {return "";} SimpleDateFormat temp = new SimpleDateFormat(format); return temp.format(new Date(date)); } public static String formatDate(long date) { return formatDate(date, "dd-MMM-yyyy HH:mm:ss"); } public static String formatDateShort(long date) { return formatDate(date, "MMM dd, HH:mm"); } public static String formatDateNum(long date) { return formatDate(date, "yyyy-MM-dd HH:mm:ss"); } // // These methods will be exposed in the plugin API. // public static String formatCustomDateOnly(long date) { if (date == 0) {return "";} return formatDate(date, "dd-MMM-yyyy"); } public static String formatCustomTimeOnly(long date) { return formatCustomTimeOnly(date, true); } public static String formatCustomTimeOnly(long date, boolean with_secs) { if (date == 0) {return "";} return formatDate(date, (with_secs) ? "HH:mm:ss" : "HH:mm"); } public static String formatCustomDateTime(long date) { if (date == 0) {return "";} return formatDate(date); } // // End methods // public static String formatTime( long time ) { return( TimeFormatter.formatColon( time / 1000 )); } /** * Format a real number to the precision specified. Does not round the number * or truncate trailing zeros. * * @param value real number to format * @param precision # of digits after the decimal place * @return formatted string */ public static String formatDecimal( double value, int precision) { return formatDecimal(value, precision, TRUNCZEROS_NO, ROUND_NO); } /** * Format a real number * * @param value real number to format * @param precision max # of digits after the decimal place * @param bTruncateZeros remove any trailing zeros after decimal place * @param bRound Whether the number will be rounded to the precision, or * truncated off. * @return formatted string */ public static String formatDecimal( double value, int precision, boolean bTruncateZeros, boolean bRound) { if (Double.isNaN(value) || Double.isInfinite(value)) { return Constants.INFINITY_STRING; } double tValue; if (bRound) { tValue = value; } else { // NumberFormat rounds, so truncate at precision if (precision == 0) { tValue = (long) value; } else { double shift = Math.pow(10, precision); tValue = ((long) (value * shift)) / shift; } } int cache_index = (precision << 2) + ((bTruncateZeros ? 1 : 0) << 1) + (bRound ? 1 : 0); NumberFormat nf = null; if (cache_index < cached_number_formats.length) { nf = cached_number_formats[cache_index]; } if (nf == null) { nf = NumberFormat.getNumberInstance(); nf.setGroupingUsed(false); // no commas if (!bTruncateZeros) { nf.setMinimumFractionDigits(precision); } if (bRound) { nf.setMaximumFractionDigits(precision); } if (cache_index < cached_number_formats.length) { cached_number_formats[cache_index] = nf; } } return nf.format(tValue); } /** * Attempts vaguely smart string truncation by searching for largest token and truncating that * @param str * @param width * @return */ public static String truncateString( String str, int width ) { int excess = str.length() - width; if ( excess <= 0 ){ return( str ); } excess += 3; // for ... int token_start = -1; int max_len = 0; int max_start = 0; for (int i=0;i max_len ){ max_len = len; max_start = token_start; } } }else{ token_start = -1; } } if ( max_len >= excess ){ int trim_point = max_start + max_len; return( str.substring( 0, trim_point - excess ) + "..." + str.substring( trim_point )); }else{ return( str.substring( 0, width-3 ) + "..." ); } } // Used to test fractions and displayformatter. // Keep until everything works okay. public static void main(String[] args) { // set decimal display to "," //Locale.setDefault(Locale.GERMAN); double d = 0.000003991630774821635; NumberFormat nf = NumberFormat.getNumberInstance(); nf.setMaximumFractionDigits(6); nf.setMinimumFractionDigits(6); String s = nf.format(d); System.out.println("Actual: " + d); // Displays 3.991630774821635E-6 System.out.println("NF/6: " + s); // Displays 0.000004 // should display 0.000003 System.out.println("DF: " + DisplayFormatters.formatDecimal(d , 6)); // should display 0 System.out.println("DF 0: " + DisplayFormatters.formatDecimal(d , 0)); // should display 0.000000 System.out.println("0.000000:" + DisplayFormatters.formatDecimal(0 , 6)); // should display 0.001 System.out.println("0.001:" + DisplayFormatters.formatDecimal(0.001, 6, TRUNCZEROS_YES, ROUND_NO)); // should display 0 System.out.println("0:" + DisplayFormatters.formatDecimal(0 , 0)); // should display 123456 System.out.println("123456:" + DisplayFormatters.formatDecimal(123456, 0)); // should display 123456 System.out.println("123456:" + DisplayFormatters.formatDecimal(123456.999, 0)); System.out.println(DisplayFormatters.formatDecimal(0.0/0, 3)); } public static char getDecimalSeparator() { return decimalSeparator; } }azureus-4.3.0.6/org/gudy/azureus2/core3/util/HostNameToIPResolver.java0000644000175000017500000001336310715253666025025 0ustar adrianadrian/* * Created on 29-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; /** * @author parg * */ public class HostNameToIPResolver { static protected AEThread2 resolver_thread; static protected List request_queue = new ArrayList(); static protected AEMonitor request_queue_mon = new AEMonitor( "HostNameToIPResolver" ); static protected AESemaphore request_semaphore = new AESemaphore("HostNameToIPResolver"); public static boolean isNonDNSName( String host ) { return( AENetworkClassifier.categoriseAddress( host ) != AENetworkClassifier.AT_PUBLIC ); } public static InetAddress syncResolve( String host ) throws UnknownHostException { if ( isNonDNSName( host )){ throw( new HostNameToIPResolverException( "non-DNS name '" + host + "'", true )); } // handle any raw addresses up front byte[] bytes = textToNumericFormat( host ); if ( bytes != null ){ return( InetAddress.getByAddress( bytes )); } // filter out partially complete raw addresses by applying the basic rule in ftp://ftp.is.co.za/rfc/rfc3696.txt // at least one dot + not all numeric char[] chars = host.toCharArray(); boolean resolve = false; for (int i=0;i 255) return null; dst[cur] = (byte)(sum & 0xff); if (! saw_digit) { if (++octets > INADDRSZ) return null; saw_digit = true; } } else if (ch == '.' && saw_digit) { if (octets == INADDRSZ) return null; cur++; dst[cur] = 0; saw_digit = false; } else return null; } if (octets < INADDRSZ) return null; return dst; } protected static class request { protected String host; protected HostNameToIPResolverListener listener; protected request( String _host, HostNameToIPResolverListener _listener ) { host = _host; listener = _listener; } protected String getHost() { return( host ); } protected HostNameToIPResolverListener getListener() { return( listener ); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/TorrentUtils.java0000644000175000017500000014625011306337274023504 0ustar adrianadrian/* * File : TorrentUtils.java * Created : 13-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author parg * */ import java.io.*; import java.net.*; import java.util.*; import com.aelitis.azureus.core.*; import com.aelitis.azureus.core.util.CopyOnWriteList; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.internat.*; import org.gudy.azureus2.core3.logging.LogRelation; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.download.*; public class TorrentUtils { public static final int TORRENT_FLAG_LOW_NOISE = 0x00000001; private static final String TORRENT_AZ_PROP_DHT_BACKUP_ENABLE = "dht_backup_enable"; private static final String TORRENT_AZ_PROP_DHT_BACKUP_REQUESTED = "dht_backup_requested"; private static final String TORRENT_AZ_PROP_TORRENT_FLAGS = "torrent_flags"; private static final String TORRENT_AZ_PROP_PLUGINS = "plugins"; public static final String TORRENT_AZ_PROP_OBTAINED_FROM = "obtained_from"; public static final String TORRENT_AZ_PROP_PEER_CACHE = "peer_cache"; public static final String TORRENT_AZ_PROP_PEER_CACHE_VALID = "peer_cache_valid"; private static final String MEM_ONLY_TORRENT_PATH = "?/\\!:mem_only:!\\/?"; private static final long PC_MARKER = RandomUtils.nextLong(); private static final List created_torrents; private static final Set created_torrents_set; private static ThreadLocal tls = new ThreadLocal() { public Object initialValue() { return( new HashMap()); } }; private static volatile Set ignore_set; private static boolean bSaveTorrentBackup; private static CopyOnWriteList torrent_attribute_listeners = new CopyOnWriteList(); static { COConfigurationManager.addAndFireParameterListener("Save Torrent Backup", new ParameterListener() { public void parameterChanged(String parameterName) { bSaveTorrentBackup = COConfigurationManager.getBooleanParameter(parameterName); } }); created_torrents = COConfigurationManager.getListParameter( "my.created.torrents", new ArrayList()); created_torrents_set = new HashSet(); Iterator it = created_torrents.iterator(); while( it.hasNext()){ created_torrents_set.add( new HashWrapper((byte[])it.next())); } } public static TOTorrent readFromFile( File file, boolean create_delegate ) throws TOTorrentException { return( readFromFile( file, create_delegate, false )); } /** * If you set "create_delegate" to true then you must understand that this results * is piece hashes being discarded and then re-read from the torrent file if needed * Therefore, if you delete the original torrent file you're going to get errors * if you access the pieces after this (and they've been discarded) * @param file * @param create_delegate * @param force_initial_discard - use to get rid of pieces immediately * @return * @throws TOTorrentException */ public static ExtendedTorrent readDelegateFromFile( File file, boolean force_initial_discard ) throws TOTorrentException { return((ExtendedTorrent)readFromFile( file, true, force_initial_discard )); } public static TOTorrent readFromFile( File file, boolean create_delegate, boolean force_initial_discard ) throws TOTorrentException { TOTorrent torrent; try{ torrent = TOTorrentFactory.deserialiseFromBEncodedFile(file); // make an immediate backup if requested and one doesn't exist if (bSaveTorrentBackup) { File torrent_file_bak = new File(file.getParent(), file.getName() + ".bak"); if ( !torrent_file_bak.exists()){ try{ torrent.serialiseToBEncodedFile(torrent_file_bak); }catch( Throwable e ){ Debug.printStackTrace(e); } } } }catch (TOTorrentException e){ Debug.outNoStack( e.getMessage() ); File torrentBackup = new File(file.getParent(), file.getName() + ".bak"); if( torrentBackup.exists()){ torrent = TOTorrentFactory.deserialiseFromBEncodedFile(torrentBackup); // use the original torrent's file name so that when this gets saved // it writes back to the original and backups are made as required // - set below }else{ throw e; } } torrent.setAdditionalStringProperty("torrent filename", file.toString()); if ( create_delegate ){ torrentDelegate res = new torrentDelegate( torrent, file ); if ( force_initial_discard ){ res.discardPieces( SystemTime.getCurrentTime(), true ); } return( res ); }else{ return( torrent ); } } public static TOTorrent readFromBEncodedInputStream( InputStream is ) throws TOTorrentException { TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedInputStream( is ); // as we've just imported this torrent we want to clear out any possible attributes that we // don't want such as "torrent filename" torrent.removeAdditionalProperties(); return( torrent ); } public static void setMemoryOnly( TOTorrent torrent, boolean mem_only ) { if ( mem_only ){ torrent.setAdditionalStringProperty("torrent filename", MEM_ONLY_TORRENT_PATH ); }else{ String s = torrent.getAdditionalStringProperty("torrent filename"); if ( s != null && s.equals( MEM_ONLY_TORRENT_PATH )){ torrent.removeAdditionalProperty( "torrent filename" ); } } } public static void writeToFile( final TOTorrent torrent ) throws TOTorrentException { writeToFile( torrent, false ); } public static void writeToFile( TOTorrent torrent, boolean force_backup ) throws TOTorrentException { try{ torrent.getMonitor().enter(); String str = torrent.getAdditionalStringProperty("torrent filename"); if ( str == null ){ throw (new TOTorrentException("TorrentUtils::writeToFile: no 'torrent filename' attribute defined", TOTorrentException.RT_FILE_NOT_FOUND)); } if ( str.equals( MEM_ONLY_TORRENT_PATH )){ return; } // save first to temporary file as serialisation may require state to be re-read from // the existing file first and if we rename to .bak first then this aint good File torrent_file_tmp = new File(str + "._az"); torrent.serialiseToBEncodedFile( torrent_file_tmp ); // now backup if required File torrent_file = new File(str); if ( ( force_backup ||COConfigurationManager.getBooleanParameter("Save Torrent Backup")) && torrent_file.exists()) { File torrent_file_bak = new File(str + ".bak"); try{ // Will return false if it cannot be deleted (including if the file doesn't exist). torrent_file_bak.delete(); torrent_file.renameTo(torrent_file_bak); }catch( SecurityException e){ Debug.printStackTrace( e ); } } // now rename the temp file to required one if ( torrent_file.exists()){ torrent_file.delete(); } torrent_file_tmp.renameTo( torrent_file ); }finally{ torrent.getMonitor().exit(); } } public static void writeToFile( TOTorrent torrent, File file ) throws TOTorrentException { writeToFile( torrent, file, false ); } public static void writeToFile( TOTorrent torrent, File file, boolean force_backup ) throws TOTorrentException { torrent.setAdditionalStringProperty("torrent filename", file.toString()); writeToFile( torrent, force_backup ); } public static String getTorrentFileName( TOTorrent torrent ) throws TOTorrentException { String str = torrent.getAdditionalStringProperty("torrent filename"); if ( str == null ){ throw( new TOTorrentException("TorrentUtils::getTorrentFileName: no 'torrent filename' attribute defined", TOTorrentException.RT_FILE_NOT_FOUND)); } if ( str.equals( MEM_ONLY_TORRENT_PATH )){ return( null ); } return( str ); } public static void copyToFile( TOTorrent torrent, File file ) throws TOTorrentException { torrent.serialiseToBEncodedFile(file); } public static void delete( TOTorrent torrent ) throws TOTorrentException { try{ torrent.getMonitor().enter(); String str = torrent.getAdditionalStringProperty("torrent filename"); if ( str == null ){ throw( new TOTorrentException("TorrentUtils::delete: no 'torrent filename' attribute defined", TOTorrentException.RT_FILE_NOT_FOUND)); } if ( str.equals( MEM_ONLY_TORRENT_PATH )){ return; } if ( !new File(str).delete()){ throw( new TOTorrentException("TorrentUtils::delete: failed to delete '" + str + "'", TOTorrentException.RT_WRITE_FAILS)); } new File( str + ".bak" ).delete(); }finally{ torrent.getMonitor().exit(); } } public static void delete( File torrent_file, boolean force_no_recycle ) { if ( !FileUtil.deleteWithRecycle( torrent_file, force_no_recycle )){ Debug.out( "TorrentUtils::delete: failed to delete '" + torrent_file + "'" ); } new File( torrent_file.toString() + ".bak" ).delete(); } public static boolean move( File from_torrent, File to_torrent ) { if ( !FileUtil.renameFile(from_torrent, to_torrent )){ return( false ); } if ( new File( from_torrent.toString() + ".bak").exists()){ FileUtil.renameFile( new File( from_torrent.toString() + ".bak"), new File( to_torrent.toString() + ".bak")); } return( true ); } public static String exceptionToText( TOTorrentException e ) { String errorDetail; int reason = e.getReason(); if ( reason == TOTorrentException.RT_FILE_NOT_FOUND ){ errorDetail = MessageText.getString("DownloadManager.error.filenotfound" ); }else if ( reason == TOTorrentException.RT_ZERO_LENGTH ){ errorDetail = MessageText.getString("DownloadManager.error.fileempty"); }else if ( reason == TOTorrentException.RT_TOO_BIG ){ errorDetail = MessageText.getString("DownloadManager.error.filetoobig"); }else if ( reason == TOTorrentException.RT_DECODE_FAILS ){ errorDetail = MessageText.getString("DownloadManager.error.filewithouttorrentinfo" ); }else if ( reason == TOTorrentException.RT_UNSUPPORTED_ENCODING ){ errorDetail = MessageText.getString("DownloadManager.error.unsupportedencoding"); }else if ( reason == TOTorrentException.RT_READ_FAILS ){ errorDetail = MessageText.getString("DownloadManager.error.ioerror"); }else if ( reason == TOTorrentException.RT_HASH_FAILS ){ errorDetail = MessageText.getString("DownloadManager.error.sha1"); }else if ( reason == TOTorrentException.RT_CANCELLED ){ errorDetail = MessageText.getString("DownloadManager.error.operationcancancelled"); }else{ errorDetail = Debug.getNestedExceptionMessage(e); } String msg = Debug.getNestedExceptionMessage(e); if ( errorDetail.indexOf( msg ) == -1){ errorDetail += " (" + msg + ")"; } return( errorDetail ); } public static List> announceGroupsToList( TOTorrent torrent ) { List> groups = new ArrayList>(); TOTorrentAnnounceURLGroup group = torrent.getAnnounceURLGroup(); TOTorrentAnnounceURLSet[] sets = group.getAnnounceURLSets(); if ( sets.length == 0 ){ List s = new ArrayList(); s.add( torrent.getAnnounceURL().toString()); groups.add(s); }else{ for (int i=0;i s = new ArrayList(); TOTorrentAnnounceURLSet set = sets[i]; URL[] urls = set.getAnnounceURLs(); for (int j=0;j 0 ){ groups.add(s); } } } return( groups ); } public static void listToAnnounceGroups( List> groups, TOTorrent torrent ) { try{ TOTorrentAnnounceURLGroup tg = torrent.getAnnounceURLGroup(); if ( groups.size() == 1 ){ List set = (List)groups.get(0); if ( set.size() == 1 ){ torrent.setAnnounceURL( new URL((String)set.get(0))); tg.setAnnounceURLSets( new TOTorrentAnnounceURLSet[0]); return; } } Vector g = new Vector(); for (int i=0;i 0 ){ g.add( tg.createAnnounceURLSet( urls )); } } TOTorrentAnnounceURLSet[] sets = new TOTorrentAnnounceURLSet[g.size()]; g.copyInto( sets ); tg.setAnnounceURLSets( sets ); if ( sets.length == 0 ){ // hmm, no valid urls at all torrent.setAnnounceURL( new URL( "http://no.valid.urls.defined/announce")); } }catch( MalformedURLException e ){ Debug.printStackTrace( e ); } } public static void announceGroupsInsertFirst( TOTorrent torrent, String first_url ) { try{ announceGroupsInsertFirst( torrent, new URL( first_url )); }catch( MalformedURLException e ){ Debug.printStackTrace( e ); } } public static void announceGroupsInsertFirst( TOTorrent torrent, URL first_url ) { announceGroupsInsertFirst( torrent, new URL[]{ first_url }); } public static void announceGroupsInsertFirst( TOTorrent torrent, URL[] first_urls ) { TOTorrentAnnounceURLGroup group = torrent.getAnnounceURLGroup(); TOTorrentAnnounceURLSet[] sets = group.getAnnounceURLSets(); TOTorrentAnnounceURLSet set1 = group.createAnnounceURLSet( first_urls ); if ( sets.length > 0 ){ TOTorrentAnnounceURLSet[] new_sets = new TOTorrentAnnounceURLSet[sets.length+1]; new_sets[0] = set1; System.arraycopy( sets, 0, new_sets, 1, sets.length ); group.setAnnounceURLSets( new_sets ); }else{ TOTorrentAnnounceURLSet set2 = group.createAnnounceURLSet(new URL[]{torrent.getAnnounceURL()}); group.setAnnounceURLSets( new TOTorrentAnnounceURLSet[]{ set1, set2 }); } } public static void announceGroupsInsertLast( TOTorrent torrent, URL[] first_urls ) { TOTorrentAnnounceURLGroup group = torrent.getAnnounceURLGroup(); TOTorrentAnnounceURLSet[] sets = group.getAnnounceURLSets(); TOTorrentAnnounceURLSet set1 = group.createAnnounceURLSet( first_urls ); if ( sets.length > 0 ){ TOTorrentAnnounceURLSet[] new_sets = new TOTorrentAnnounceURLSet[sets.length+1]; new_sets[sets.length] = set1; System.arraycopy( sets, 0, new_sets, 0, sets.length ); group.setAnnounceURLSets( new_sets ); }else{ TOTorrentAnnounceURLSet set2 = group.createAnnounceURLSet(new URL[]{torrent.getAnnounceURL()}); group.setAnnounceURLSets( new TOTorrentAnnounceURLSet[]{ set2, set1 }); } } public static void announceGroupsSetFirst( TOTorrent torrent, String first_url ) { List groups = announceGroupsToList( torrent ); boolean found = false; outer: for (int i=0;i true Map m = getAzureusProperties( torrent ); Object obj = m.get( TORRENT_AZ_PROP_DHT_BACKUP_ENABLE ); if ( obj instanceof Long ){ return( ((Long)obj).longValue() == 1 ); } return( true ); } public static boolean isDHTBackupRequested( TOTorrent torrent ) { // missing -> false Map m = getAzureusProperties( torrent ); Object obj = m.get( TORRENT_AZ_PROP_DHT_BACKUP_REQUESTED ); if ( obj instanceof Long ){ return( ((Long)obj).longValue() == 1 ); } return( false ); } public static void setDHTBackupRequested( TOTorrent torrent, boolean requested ) { Map m = getAzureusProperties( torrent ); m.put( TORRENT_AZ_PROP_DHT_BACKUP_REQUESTED, new Long(requested?1:0)); } public static boolean isReallyPrivate(TOTorrent torrent) { if ( torrent == null ){ return( false ); } if ( UrlUtils.containsPasskey( torrent.getAnnounceURL())){ return torrent.getPrivate(); } return false; } public static boolean getPrivate( TOTorrent torrent ) { if ( torrent == null ){ return( false ); } return( torrent.getPrivate()); } public static void setPrivate( TOTorrent torrent, boolean _private ) { if ( torrent == null ){ return; } try{ torrent.setPrivate( _private ); }catch( Throwable e ){ Debug.printStackTrace(e); } } public static Set getIgnoreSet() { return(getIgnoreSetSupport(false)); } public static synchronized Set getIgnoreSetSupport( boolean force ) { if ( ignore_set == null || force ){ Set new_ignore_set = new HashSet(); String ignore_list = COConfigurationManager.getStringParameter( "File.Torrent.IgnoreFiles", TOTorrent.DEFAULT_IGNORE_FILES ); if ( ignore_set == null ){ // first time - add the listener COConfigurationManager.addParameterListener( "File.Torrent.IgnoreFiles", new ParameterListener() { public void parameterChanged( String parameterName) { getIgnoreSetSupport( true ); } }); } int pos = 0; while(true){ int p1 = ignore_list.indexOf( ";", pos ); String bit; if ( p1 == -1 ){ bit = ignore_list.substring(pos); }else{ bit = ignore_list.substring( pos, p1 ); pos = p1+1; } new_ignore_set.add(bit.trim().toLowerCase()); if ( p1 == -1 ){ break; } } ignore_set = new_ignore_set; } return( ignore_set ); } // this class exists to minimise memory requirements by discarding the piece hash values // when "idle" private static final int PIECE_HASH_TIMEOUT = 3*60*1000; private static Map torrent_delegates = new WeakHashMap(); static{ SimpleTimer.addPeriodicEvent( "TorrentUtils:pieceDiscard", PIECE_HASH_TIMEOUT/2, new TimerEventPerformer() { public void perform( TimerEvent event ) { long now = SystemTime.getCurrentTime(); synchronized( torrent_delegates ){ Iterator it = torrent_delegates.keySet().iterator(); while( it.hasNext()){ ((torrentDelegate)it.next()).discardPieces(now,false); } } } }); } private static HashSet torrentFluffKeyset = new HashSet(2); private static Map fluffThombstone = new HashMap(1); /** * Register keys that are used for heavyweight maps that should be discarded when the torrent is not in use * Make sure these keys are only ever used for Map objects! */ public static void registerMapFluff( String[] fluff ) { synchronized (TorrentUtils.class) { for (int i = 0; i < fluff.length; i++) torrentFluffKeyset.add(fluff[i]); } } public interface ExtendedTorrent extends TOTorrent { public byte[][] peekPieces() throws TOTorrentException; public void setDiscardFluff( boolean discard ); } private static class torrentDelegate extends LogRelation implements ExtendedTorrent { private TOTorrent delegate; private File file; private boolean fluff_dirty; private long last_pieces_read_time = SystemTime.getCurrentTime(); protected torrentDelegate( TOTorrent _delegate, File _file ) { delegate = _delegate; file = _file; synchronized( torrent_delegates ){ torrent_delegates.put( this, null ); } } public void setDiscardFluff( boolean discard ) { if ( discard && !torrentFluffKeyset.isEmpty() ){ //System.out.println( "Discarded fluff for " + new String(getName())); try{ getMonitor().enter(); try{ // if file is out of sync with fluff then force a write if ( fluff_dirty ){ boolean[] restored = restoreState( true, true ); delegate.serialiseToBEncodedFile( file ); fluff_dirty = false; if ( restored[0] ){ discardPieces( SystemTime.getCurrentTime(), true ); } } for(Iterator it = torrentFluffKeyset.iterator();it.hasNext();){ delegate.setAdditionalMapProperty( (String)it.next(), fluffThombstone ); } }catch( Throwable e ){ Debug.printStackTrace( e ); } }finally{ getMonitor().exit(); } } } public byte[] getName() { return( delegate.getName()); } public boolean isSimpleTorrent() { return( delegate.isSimpleTorrent()); } public byte[] getComment() { return( delegate.getComment()); } public void setComment( String comment ) { delegate.setComment( comment ); } public long getCreationDate() { return( delegate.getCreationDate()); } public void setCreationDate( long date ) { delegate.setCreationDate( date ); } public byte[] getCreatedBy() { return( delegate.getCreatedBy()); } public void setCreatedBy( byte[] cb ) { delegate.setCreatedBy( cb ); } public boolean isCreated() { return( delegate.isCreated()); } public URL getAnnounceURL() { return( delegate.getAnnounceURL()); } public boolean setAnnounceURL( URL url ) { return delegate.setAnnounceURL( url ); } public TOTorrentAnnounceURLGroup getAnnounceURLGroup() { return( delegate.getAnnounceURLGroup()); } protected void discardPieces( long now, boolean force ) { // handle clock changes backwards if ( now < last_pieces_read_time && !force ){ last_pieces_read_time = now; }else{ try{ if( ( now - last_pieces_read_time > PIECE_HASH_TIMEOUT || force ) && delegate.getPieces() != null ){ try{ getMonitor().enter(); // System.out.println( "clearing pieces for '" + new String(getName()) + "'"); delegate.setPieces( null ); }finally{ getMonitor().exit(); } } }catch( Throwable e ){ Debug.printStackTrace(e); } } } public byte[][] getPieces() throws TOTorrentException { byte[][] res = delegate.getPieces(); last_pieces_read_time = SystemTime.getCurrentTime(); if ( res == null ){ // System.out.println( "recovering pieces for '" + new String(getName()) + "'"); try{ getMonitor().enter(); restoreState( true, false ); res = delegate.getPieces(); }finally{ getMonitor().exit(); } } return( res ); } /** * monitor must be held before calling me * @param do_pieces * @param do_fluff * @throws TOTorrentException */ protected boolean[] restoreState( boolean do_pieces, boolean do_fluff ) throws TOTorrentException { boolean had_pieces = delegate.getPieces() != null; boolean had_fluff = true; for(Iterator it = torrentFluffKeyset.iterator();it.hasNext();){ had_fluff &= delegate.getAdditionalMapProperty( (String)it.next() ) != fluffThombstone; } if ( had_pieces ){ do_pieces = false; } if ( had_fluff ){ do_fluff = false; } if ( do_pieces || do_fluff ){ TOTorrent temp = readFromFile( file, false ); if ( do_pieces ){ byte[][] res = temp.getPieces(); delegate.setPieces( res ); } if ( do_fluff ){ for (Iterator it = torrentFluffKeyset.iterator(); it.hasNext();){ String fluffKey = (String) it.next(); // only update the discarded entries as non-discarded may be out of sync // with the file contents if ( delegate.getAdditionalMapProperty( fluffKey ) == fluffThombstone ){ delegate.setAdditionalMapProperty(fluffKey, temp.getAdditionalMapProperty(fluffKey)); } } } } return( new boolean[]{ do_pieces, do_fluff }); } /** * peeks the pieces, will return null if they are discarded * @return */ public byte[][] peekPieces() throws TOTorrentException { return( delegate.getPieces()); } public void setPieces( byte[][] pieces ) throws TOTorrentException { throw( new TOTorrentException( "Unsupported Operation", TOTorrentException.RT_WRITE_FAILS )); } public long getPieceLength() { return( delegate.getPieceLength()); } public int getNumberOfPieces() { return( delegate.getNumberOfPieces()); } public long getSize() { return( delegate.getSize()); } public TOTorrentFile[] getFiles() { return( delegate.getFiles()); } public byte[] getHash() throws TOTorrentException { return( delegate.getHash()); } public HashWrapper getHashWrapper() throws TOTorrentException { return( delegate.getHashWrapper()); } public void setHashOverride( byte[] hash ) throws TOTorrentException { throw( new TOTorrentException( "Not supported", TOTorrentException.RT_HASH_FAILS )); } public boolean getPrivate() { return( delegate.getPrivate()); } public void setPrivate( boolean _private ) throws TOTorrentException { // don't support this as it changes teh torrent hash throw( new TOTorrentException( "Can't amend private attribute", TOTorrentException.RT_WRITE_FAILS )); } public boolean hasSameHashAs( TOTorrent other ) { return( delegate.hasSameHashAs( other )); } public void setAdditionalStringProperty( String name, String value ) { delegate.setAdditionalStringProperty( name, value ); } public String getAdditionalStringProperty( String name ) { return( delegate.getAdditionalStringProperty( name )); } public void setAdditionalByteArrayProperty( String name, byte[] value ) { delegate.setAdditionalByteArrayProperty( name, value ); } public byte[] getAdditionalByteArrayProperty( String name ) { return( delegate.getAdditionalByteArrayProperty( name )); } public void setAdditionalLongProperty( String name, Long value ) { delegate.setAdditionalLongProperty( name, value ); } public Long getAdditionalLongProperty( String name ) { return( delegate.getAdditionalLongProperty( name )); } public void setAdditionalListProperty( String name, List value ) { delegate.setAdditionalListProperty( name, value ); } public List getAdditionalListProperty( String name ) { return( delegate.getAdditionalListProperty( name )); } public void setAdditionalMapProperty( String name, Map value ) { if ( torrentFluffKeyset.contains(name)){ //System.out.println( "Set fluff for " + new String(getName()) + " to " + value ); try{ getMonitor().enter(); delegate.setAdditionalMapProperty( name, value ); fluff_dirty = true; }finally{ getMonitor().exit(); } }else{ delegate.setAdditionalMapProperty( name, value ); } } public Map getAdditionalMapProperty( String name ) { if (torrentFluffKeyset.contains(name)){ try{ getMonitor().enter(); Map result = delegate.getAdditionalMapProperty( name ); if ( result == fluffThombstone ){ try{ restoreState( false, true ); Map res = delegate.getAdditionalMapProperty( name ); //System.out.println( "Restored fluff for " + new String(getName()) + " to " + res ); return( res ); }catch( Throwable e ){ Debug.out( "Property '" + name + " lost due to torrent read error", e ); } } }finally{ getMonitor().exit(); } } return( delegate.getAdditionalMapProperty( name )); } public Object getAdditionalProperty(String name) { if (torrentFluffKeyset.contains(name)) { try { getMonitor().enter(); Object result = delegate.getAdditionalProperty(name); if (result == fluffThombstone) { try { restoreState(false, true); Object res = delegate.getAdditionalProperty(name); //System.out.println( "Restored fluff for " + new String(getName()) + " to " + res ); return (res); } catch (Throwable e) { Debug.out("Property '" + name + " lost due to torrent read error", e); } } } finally { getMonitor().exit(); } } return delegate.getAdditionalProperty(name); } public void setAdditionalProperty( String name, Object value ) { if ( torrentFluffKeyset.contains(name)){ //System.out.println( "Set fluff for " + new String(getName()) + " to " + value ); try{ getMonitor().enter(); delegate.setAdditionalProperty( name, value ); fluff_dirty = true; }finally{ getMonitor().exit(); } }else{ delegate.setAdditionalProperty( name, value ); } } public void removeAdditionalProperty( String name ) { if(delegate.getAdditionalProperty(name) == null) return; if ( torrentFluffKeyset.contains(name)){ //System.out.println( "Set fluff for " + new String(getName()) + " to " + value ); try{ getMonitor().enter(); delegate.removeAdditionalProperty( name ); fluff_dirty = true; }finally{ getMonitor().exit(); } }else{ delegate.removeAdditionalProperty( name ); } } public void removeAdditionalProperties() { try{ getMonitor().enter(); delegate.removeAdditionalProperties(); fluff_dirty = true; }finally{ getMonitor().exit(); } } public void serialiseToBEncodedFile( File target_file ) throws TOTorrentException { // make sure pieces are current try{ getMonitor().enter(); boolean[] restored = restoreState( true, true ); delegate.serialiseToBEncodedFile( target_file ); if ( target_file.equals( file )){ fluff_dirty = false; } if ( restored[0] ){ discardPieces( SystemTime.getCurrentTime(), true ); } if ( restored[1] ){ for (Iterator it = torrentFluffKeyset.iterator(); it.hasNext();){ delegate.setAdditionalMapProperty( (String)it.next(), fluffThombstone ); } } }finally{ getMonitor().exit(); } } public Map serialiseToMap() throws TOTorrentException { // make sure pieces are current try{ getMonitor().enter(); boolean[] restored = restoreState( true, true ); Map result = delegate.serialiseToMap(); if ( restored[0] ){ discardPieces( SystemTime.getCurrentTime(), true ); } if ( restored[1]){ for (Iterator it = torrentFluffKeyset.iterator(); it.hasNext();){ delegate.setAdditionalMapProperty((String) it.next(), fluffThombstone); } } return( result ); }finally{ getMonitor().exit(); } } public void serialiseToXMLFile( File target_file ) throws TOTorrentException { // make sure pieces are current try{ getMonitor().enter(); boolean[] restored = restoreState( true, true ); delegate.serialiseToXMLFile( target_file ); if ( restored[0] ){ discardPieces( SystemTime.getCurrentTime(), true ); } if ( restored[1]){ for (Iterator it = torrentFluffKeyset.iterator(); it.hasNext();){ delegate.setAdditionalMapProperty((String) it.next(), fluffThombstone); } } }finally{ getMonitor().exit(); } } public AEMonitor getMonitor() { return( delegate.getMonitor()); } public void print() { delegate.print(); } public String getRelationText() { if (delegate instanceof LogRelation) return ((LogRelation)delegate).getRelationText(); return delegate.toString(); } public Object[] getQueryableInterfaces() { if (delegate instanceof LogRelation) return ((LogRelation)delegate).getQueryableInterfaces(); return super.getQueryableInterfaces(); } } /** * Copy a file to the Torrent Save Directory, taking into account all the * user config options related to that. *

      * Also makes the directory if it doesn't exist. * * @param f File to copy * @param persistent Whether the torrent is persistent * @return File after it's been copied (may be the same as f) * @throws IOException */ public static File copyTorrentFileToSaveDir(File f, boolean persistent) throws IOException { File torrentDir; boolean saveTorrents = persistent && COConfigurationManager.getBooleanParameter("Save Torrent Files"); if (saveTorrents) torrentDir = new File(COConfigurationManager .getDirectoryParameter("General_sDefaultTorrent_Directory")); else torrentDir = new File(f.getParent()); //if the torrent is already in the completed files dir, use this //torrent instead of creating a new one in the default dir boolean moveWhenDone = COConfigurationManager.getBooleanParameter("Move Completed When Done"); String completedDir = COConfigurationManager.getStringParameter( "Completed Files Directory", ""); if (moveWhenDone && completedDir.length() > 0) { File cFile = new File(completedDir, f.getName()); if (cFile.exists()) { //set the torrentDir to the completedDir torrentDir = new File(completedDir); } } FileUtil.mkdirs(torrentDir); File fDest = new File(torrentDir, f.getName().replaceAll("%20", ".")); if (fDest.equals(f)) { return f; } while (fDest.exists()) { fDest = new File(torrentDir, "_" + fDest.getName()); } fDest.createNewFile(); if (!FileUtil.copyFile(f, fDest)) { throw new IOException("File copy failed"); } return fDest; } /** * Get the DownloadManager related to a torrent's hashBytes * * @param hashBytes * @return */ public static DownloadManager getDownloadManager( HashWrapper hash ) { try { return AzureusCoreFactory.getSingleton().getGlobalManager() .getDownloadManager(hash); } catch (Exception e) { return null; } } /** * Deletes the given dir and all dirs underneath if empty. * Don't delete default save path or completed files directory, however, * allow deletion of their empty subdirectories * Files defined to be ignored for the sake of torrent creation are automatically deleted * For example, by default this includes thumbs.db */ public static void recursiveEmptyDirDelete(File f) { TorrentUtils.recursiveEmptyDirDelete(f, true); } /** * Same as #recursiveEmptyDirDelete(File), except allows disabling of logging * of any warnings * * @param f Dir to delete * @param log_warnings Whether to log warning */ public static void recursiveEmptyDirDelete(File f, boolean log_warnings) { Set ignore_map = getIgnoreSet(); FileUtil.recursiveEmptyDirDelete(f, ignore_map, log_warnings); } /** * A nice string of a Torrent's hash * * @param torrent Torrent to fromat hash of * @return Hash string in a nice format */ public static String nicePrintTorrentHash(TOTorrent torrent) { return nicePrintTorrentHash(torrent, false); } /** * A nice string of a Torrent's hash * * @param torrent Torrent to fromat hash of * @param tight No spaces between groups of numbers * * @return Hash string in a nice format */ public static String nicePrintTorrentHash(TOTorrent torrent, boolean tight) { byte[] hash; if (torrent == null) { hash = new byte[20]; } else { try { hash = torrent.getHash(); } catch (TOTorrentException e) { Debug.printStackTrace(e); hash = new byte[20]; } } return (ByteFormatter.nicePrint(hash, tight)); } /** * Runs a file through a series of test to verify if it is a torrent. * * @param filename File to test * @return true - file is a valid torrent file * * @throws FileNotFoundException * @throws IOException */ public static boolean isTorrentFile(String filename) throws FileNotFoundException, IOException { File check = new File(filename); if (!check.exists()) throw new FileNotFoundException("File "+filename+" not found."); if (!check.canRead()) throw new IOException("File "+filename+" cannot be read."); if (check.isDirectory()) throw new FileIsADirectoryException("File "+filename+" is a directory."); try { TOTorrentFactory.deserialiseFromBEncodedFile(check); return true; } catch (Throwable e) { return false; } } public static void addCreatedTorrent( TOTorrent torrent ) { synchronized( created_torrents ){ try{ byte[] hash = torrent.getHash(); //System.out.println( "addCreated:" + new String(torrent.getName()) + "/" + ByteFormatter.encodeString( hash )); if ( created_torrents.size() == 0 ){ COConfigurationManager.setParameter( "my.created.torrents", created_torrents ); } HashWrapper hw = new HashWrapper( hash ); if ( !created_torrents_set.contains( hw )){ created_torrents.add( hash ); created_torrents_set.add( hw ); COConfigurationManager.setDirty(); } }catch( TOTorrentException e ){ } } } public static void removeCreatedTorrent( TOTorrent torrent ) { synchronized( created_torrents ){ try{ HashWrapper hw = torrent.getHashWrapper(); byte[] hash = hw.getBytes(); //System.out.println( "removeCreated:" + new String(torrent.getName()) + "/" + ByteFormatter.encodeString( hash )); Iterator it = created_torrents.iterator(); while( it.hasNext()){ byte[] h = (byte[])it.next(); if ( Arrays.equals( hash, h )){ it.remove(); } } COConfigurationManager.setDirty(); created_torrents_set.remove( hw ); }catch( TOTorrentException e ){ } } } public static boolean isCreatedTorrent( TOTorrent torrent ) { synchronized( created_torrents ){ try{ HashWrapper hw = torrent.getHashWrapper(); boolean res = created_torrents_set.contains( hw ); // if we don't have a persistent record of creation, check the non-persisted version if ( !res ){ res = torrent.isCreated(); } // System.out.println( "isCreated:" + new String(torrent.getName()) + "/" + ByteFormatter.encodeString( hw.getBytes()) + " -> " + res ); return( res ); }catch( TOTorrentException e ){ Debug.printStackTrace(e); return( false ); } } } private static void fireAttributeListener( TOTorrent torrent, String attribute, Object value ) { Iterator it = torrent_attribute_listeners.iterator(); while( it.hasNext()){ try{ ((torrentAttributeListener)it.next()).attributeSet(torrent, attribute, value); }catch( Throwable e ){ Debug.printStackTrace(e); } } } public static void addTorrentAttributeListener( torrentAttributeListener listener ) { torrent_attribute_listeners.add( listener ); } public static void removeTorrentAttributeListener( torrentAttributeListener listener ) { torrent_attribute_listeners.remove( listener ); } public interface torrentAttributeListener { public void attributeSet( TOTorrent torrent, String attribute, Object value ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/TimerEventPeriodic.java0000644000175000017500000000550210766605566024574 0ustar adrianadrian/* * File : TimerEventPeriodic.java * Created : 07-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author parg * */ public class TimerEventPeriodic implements TimerEventPerformer { private Timer timer; private long frequency; private boolean absolute; private TimerEventPerformer performer; private String name; private TimerEvent current_event; private boolean cancelled; protected TimerEventPeriodic( Timer _timer, long _frequency, boolean _absolute, TimerEventPerformer _performer ) { timer = _timer; frequency = _frequency; absolute = _absolute; performer = _performer; long now = SystemTime.getCurrentTime(); current_event = timer.addEvent( name, now, now + frequency, absolute, this ); } public void setName( String _name ) { name = _name; synchronized( this ){ if ( current_event != null ){ current_event.setName( name ); } } } public String getName() { return( name ); } protected TimerEventPerformer getPerformer() { return( performer ); } public long getFrequency() { return( frequency ); } public boolean isCancelled() { return( cancelled ); } public void perform( TimerEvent event ) { if ( !cancelled ){ try{ performer.perform( event ); }catch( Throwable e ){ DebugLight.printStackTrace( e ); } synchronized( this ){ if ( !cancelled ){ long now = SystemTime.getCurrentTime(); current_event = timer.addEvent(name, now, now + frequency, absolute, this ); } } } } public synchronized void cancel() { if ( current_event != null ){ current_event.cancel(); cancelled = true; } } protected String getString() { TimerEvent ce = current_event; String ev_data; if ( ce == null ){ ev_data = "?"; }else{ ev_data = "when=" + ce.getWhen() + ",run=" + ce.hasRun() + ", can=" + ce.isCancelled(); } return( ev_data + ",freq=" + getFrequency() + ",target=" + getPerformer() + (name==null?"":(",name=" + name ))); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/PausableAverage.java0000644000175000017500000000377610506773016024061 0ustar adrianadrian/* * Created on 19-Sep-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; public class PausableAverage extends Average { public static PausableAverage getPausableInstance( int refreshRate, int period ) { if ( refreshRate < 100 ){ return null; } if (( period * 1000 ) < refreshRate ){ return null; } return new PausableAverage(refreshRate, period); } private long offset; private long pause_time; private PausableAverage( int _refreshRate, int _period ) { super( _refreshRate, _period ); } public void addValue( long value ) { super.addValue( value ); } public long getAverage() { long average = super.getAverage(); return( average ); } protected long getEffectiveTime() { return( SystemTime.getCurrentTime() - offset ); } public void pause() { if ( pause_time == 0 ){ pause_time = SystemTime.getCurrentTime(); } } public void resume() { if ( pause_time != 0 ){ long now = SystemTime.getCurrentTime(); if ( now > pause_time ){ offset += now - pause_time; } pause_time = 0; } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AEDiagnosticsEvidenceGenerator.java0000644000175000017500000000212010373051004026763 0ustar adrianadrian/* * Created on 29-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; public interface AEDiagnosticsEvidenceGenerator { public void generate( IndentWriter writer ); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AERunnableObject.java0000644000175000017500000000314510603354046024117 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author TuxPaper * @created Mar 22, 2007 * */ public abstract class AERunnableObject implements Runnable { private Object[] returnValueObject; private AESemaphore sem; private String id = "AEReturningRunnable"; public void run() { try { Object o = runSupport(); if (returnValueObject != null && returnValueObject.length > 0) { returnValueObject[0] = o; } } catch (Throwable e) { Debug.out(id, e); } finally { if (sem != null) { sem.release(); } } } public void setupReturn(String ID, Object[] returnValueObject, AESemaphore sem) { id = ID; this.returnValueObject = returnValueObject; this.sem = sem; } public abstract Object runSupport(); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/ThreadPool.java0000644000175000017500000003724111067033766023071 0ustar adrianadrian/* * File : ThreadPool.java * Created : 21-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author parg * */ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import com.aelitis.azureus.core.util.Java15Utils; public class ThreadPool { private static final boolean LOG_WARNINGS = false; private static final int WARN_TIME = 10000; private static List busy_pools = new ArrayList(); private static boolean busy_pool_timer_set = false; private static boolean debug_thread_pool; private static boolean debug_thread_pool_log_on; static{ if ( System.getProperty("transitory.startup", "0").equals("0")){ AEDiagnostics.addEvidenceGenerator( new AEDiagnosticsEvidenceGenerator() { public void generate( IndentWriter writer ) { writer.println( "Thread Pools" ); try{ writer.indent(); List pools; synchronized( busy_pools ){ pools = new ArrayList( busy_pools ); } for (int i=0;i " + diff_cpu + "/" + diff_millis ); } } }else{ runnable.run(); } } protected void checkWarning() { if (warn_when_full) { String task_names = ""; try { synchronized (ThreadPool.this) { for (int i = 0; i < busy.size(); i++) { threadPoolWorker x = (threadPoolWorker) busy.get(i); AERunnable r = x.runnable; if (x != null) { String name; if (r instanceof ThreadPoolTask) name = ((ThreadPoolTask) r).getName(); else name = x.getClass().getName(); task_names += (task_names.length() == 0 ? "" : ",") + name; } } } } catch (Throwable e) {} Debug.out("Thread pool '" + getName() + "' is full (busy=" + task_names + ")"); warn_when_full = false; } } public AERunnable[] getQueuedTasks() { synchronized (this) { AERunnable[] res = new AERunnable[task_queue.size()]; task_queue.toArray(res); return (res); } } public int getQueueSize() { synchronized (this) { return task_queue.size(); } } public boolean isQueued(AERunnable task) { synchronized (this) { return task_queue.contains(task); } } public AERunnable[] getRunningTasks() { List runnables = new ArrayList(); synchronized( this ){ Iterator it = busy.iterator(); while( it.hasNext()){ threadPoolWorker worker = (threadPoolWorker)it.next(); AERunnable runnable = worker.getRunnable(); if ( runnable != null ){ runnables.add( runnable ); } } } AERunnable[] res = new AERunnable[runnables.size()]; runnables.toArray(res); return( res ); } public int getRunningCount() { int res = 0; synchronized( this ){ Iterator it = busy.iterator(); while( it.hasNext()){ threadPoolWorker worker = (threadPoolWorker)it.next(); AERunnable runnable = worker.getRunnable(); if ( runnable != null ){ res++; } } } return( res ); } public boolean isFull() { return( thread_sem.getValue() == 0 ); } protected void checkTimeouts() { synchronized( this ){ long diff = task_total - task_total_last; task_average.addValue( diff ); task_total_last = task_total; if ( debug_thread_pool_log_on ){ System.out.println( "ThreadPool '" + getName() + "'/" + thread_name_index + ": max=" + max_size + ",sem=[" + thread_sem.getString() + "],busy=" + busy.size() + ",queue=" + task_queue.size()); } long now = SystemTime.getCurrentTime(); for (int i=0;i ( WARN_TIME * (x.warn_count+1))){ x.warn_count++; if ( LOG_WARNINGS ){ DebugLight.out( x.getWorkerName() + ": running, elapsed = " + elapsed + ", state = " + x.state ); } if ( execution_limit > 0 && elapsed > execution_limit ){ if ( LOG_WARNINGS ){ DebugLight.out( x.getWorkerName() + ": interrupting" ); } AERunnable r = x.runnable; if ( r != null ){ try{ if ( r instanceof ThreadPoolTask ){ ((ThreadPoolTask)r).interruptTask(); }else{ x.interrupt(); } }catch( Throwable e ){ DebugLight.printStackTrace( e ); } } } } } } } public String getName() { return (name); } void releaseManual(ThreadPoolTask toRelease) { if(!busy.contains(toRelease.worker) || toRelease.manualRelease != ThreadPoolTask.RELEASE_MANUAL_ALLOWED) throw new IllegalStateException("task already released or not manually releasable"); synchronized (this) { long elapsed = SystemTime.getCurrentTime() - toRelease.worker.run_start_time; if (elapsed > WARN_TIME && LOG_WARNINGS) DebugLight.out(toRelease.worker.getWorkerName() + ": terminated, elapsed = " + elapsed + ", state = " + toRelease.worker.state); busy.remove(toRelease.worker); // if debug is on we leave the pool registered so that we // can trace on the timeout events if (busy.size() == 0 && !debug_thread_pool) synchronized (busy_pools) { busy_pools.remove(this); } if(busy.size() == 0) thread_sem.release(); else new threadPoolWorker(); } } public void registerThreadAsChild(threadPoolWorker parent) { if(tls.get() == null || tls.get() == parent) tls.set(parent); else throw new IllegalStateException("another parent is already set for this thread"); } public void deregisterThreadAsChild(threadPoolWorker parent) { if(tls.get() == parent) tls.set(null); else throw new IllegalStateException("tls is not set to parent"); } class threadPoolWorker extends AEThread2 { private final String worker_name; private volatile AERunnable runnable; private long run_start_time; private int warn_count; private String state = ""; protected threadPoolWorker() { super(name + "[" + (thread_name_index++) + "]",true); setPriority(thread_priority); worker_name = name + "[" + (thread_name_index++) + "]"; start(); } public void run() { tls.set(threadPoolWorker.this); boolean autoRelease = true; try { do { try { synchronized (ThreadPool.this) { if (task_queue.size() > 0) runnable = (AERunnable) task_queue.remove(0); else break; } synchronized (ThreadPool.this) { run_start_time = SystemTime.getCurrentTime(); warn_count = 0; busy.add(threadPoolWorker.this); task_total++; if (busy.size() == 1) { synchronized (busy_pools) { if (!busy_pools.contains(ThreadPool.this)) { busy_pools.add(ThreadPool.this); if (!busy_pool_timer_set) { // we have to defer this action rather // than running as a static initialiser // due to the dependency between // ThreadPool, Timer and ThreadPool again COConfigurationManager.addAndFireParameterListeners(new String[] { "debug.threadpool.log.enable", "debug.threadpool.debug.trace" }, new ParameterListener() { public void parameterChanged(String name) { debug_thread_pool = COConfigurationManager.getBooleanParameter("debug.threadpool.log.enable", false); debug_thread_pool_log_on = COConfigurationManager.getBooleanParameter("debug.threadpool.debug.trace", false); } }); busy_pool_timer_set = true; SimpleTimer.addPeriodicEvent("ThreadPool:timeout", WARN_TIME, new TimerEventPerformer() { public void perform(TimerEvent event) { checkAllTimeouts(); } }); } } } } } if (runnable instanceof ThreadPoolTask) { ThreadPoolTask tpt = (ThreadPoolTask) runnable; tpt.worker = this; String task_name = tpt.getName(); try { if (task_name != null) setName(worker_name + "{" + task_name + "}"); tpt.taskStarted(); runIt(runnable); } finally { if (task_name != null) setName(worker_name); if(tpt.isAutoReleaseAndAllowManual()) tpt.taskCompleted(); else { autoRelease = false; break; } } } else runIt(runnable); } catch (Throwable e) { DebugLight.printStackTrace(e); } finally { if(autoRelease) { synchronized (ThreadPool.this) { long elapsed = SystemTime.getCurrentTime() - run_start_time; if (elapsed > WARN_TIME && LOG_WARNINGS) DebugLight.out(getWorkerName() + ": terminated, elapsed = " + elapsed + ", state = " + state); busy.remove(threadPoolWorker.this); // if debug is on we leave the pool registered so that we // can trace on the timeout events if (busy.size() == 0 && !debug_thread_pool) synchronized (busy_pools) { busy_pools.remove(ThreadPool.this); } } } } } while (runnable != null); } catch (Throwable e) { DebugLight.printStackTrace(e); } finally { if(autoRelease) thread_sem.release(); tls.set(null); } } public void setState(String _state) { //System.out.println( "state = " + _state ); state = _state; } public String getState() { return (state); } protected String getWorkerName() { return (worker_name); } protected ThreadPool getOwner() { return (ThreadPool.this); } protected AERunnable getRunnable() { return (runnable); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AESemaphore2.java0000644000175000017500000000212511163305126023221 0ustar adrianadrian/* * Created on Mar 27, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.core3.util; import java.util.concurrent.Semaphore; public class AESemaphore2 { private Semaphore sem = new Semaphore(0); public AESemaphore2( String name ) { } public void reserve() { sem.acquireUninterruptibly(); } public void release() { sem.release(); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AETemporaryFileHandler.java0000644000175000017500000000654511202247132025302 0ustar adrianadrian/* * Created on 29-Oct-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.io.File; import java.io.IOException; /** * @author parg * */ public class AETemporaryFileHandler { private static final String PREFIX = "AZU"; private static final String SUFFIX = ".tmp"; private static boolean started_up; private static File tmp_dir; public static synchronized void startup() { if ( started_up ){ return; } started_up = true; try{ tmp_dir = FileUtil.getUserFile( "tmp" ); if ( tmp_dir.exists()){ File[] files = tmp_dir.listFiles(); if ( files != null ){ for (int i=0;i", ">" }, new String[] { "<", "<" }, new String[] { "\"", """ }, new String[] { "'", "'" }, }; public static String getMagnetURI( byte[] hash ) { return( "magnet:?xt=urn:btih:" + Base32.encode( hash )); } /** * returns magnet uri if input is base 32 or base 16 encoded sha1 hash, null otherwise * @param base_hash * @return */ public static String normaliseMagnetURI( String base_hash ) { byte[] hash = decodeSHA1Hash( base_hash ); if ( hash != null ){ return( getMagnetURI( hash )); } return( null ); } public static byte[] decodeSHA1Hash( String str ) { if ( str == null ){ return( null ); } str = str.trim(); byte[] hash = null; try{ if ( str.length() == 40 ){ hash = ByteFormatter.decodeString( str ); }else if ( str.length() == 32 ){ hash = Base32.decode( str ); } }catch( Throwable e ){ } if ( hash != null ){ if ( hash.length != 20 ){ hash = null; } } return( hash ); } /** * test string for possibility that it's an URL. Considers 40 byte hex * strings as URLs * * @param sURL * @return */ public static boolean isURL(String sURL) { return parseTextForURL(sURL, true) != null; } public static boolean isURL(String sURL, boolean bGuess) { return parseTextForURL(sURL, true, bGuess) != null; } public static String parseTextForURL(String text, boolean accept_magnets) { return parseTextForURL(text, accept_magnets, true); } public static String getURL( String text ) { return( parseTextForURL(text, false, false )); } public static String parseTextForURL(String text, boolean accept_magnets, boolean guess) { if (text == null || text.length() < 5) { return null; } String href = parseHTMLforURL(text); if (href != null) { return href; } try { text = text.trim(); text = URLDecoder.decode(text); } catch (Exception e) { // sometimes fires a IllegalArgumentException // catch everything and ignore. } String textLower; try { textLower = text.toLowerCase(); } catch (Throwable e) { textLower = text; } int max = accept_magnets ? prefixes.length : MAGNETURL_STARTS_AT; int end = -1; int start = textLower.length(); String strURL = null; for (int i = 0; i < max; i++) { final int testBegin = textLower.indexOf(prefixes[i]); if (testBegin >= 0 && testBegin < start) { end = text.indexOf("\n", testBegin + prefixes[i].length()); String strURLTest = (end >= 0) ? text.substring(testBegin, end - 1) : text.substring(testBegin); try { URL parsedURL = new URL(strURLTest); strURL = parsedURL.toExternalForm(); } catch (MalformedURLException e1) { e1.printStackTrace(); if (i >= MAGNETURL_STARTS_AT) { strURL = strURLTest; } } } } if (strURL != null) { return strURL; } if (new File(text).exists()) { return null; } // accept raw hash of 40 hex chars if (accept_magnets && text.matches("^[a-fA-F0-9]{40}$")) { // convert from HEX to raw bytes byte[] infohash = ByteFormatter.decodeString(text.toUpperCase()); // convert to BASE32 return "magnet:?xt=urn:btih:" + Base32.encode(infohash); } // accept raw hash of 32 base-32 chars if (accept_magnets && text.matches("^[a-zA-Z2-7]{32}$")) { return "magnet:?xt=urn:btih:" + text; } // javascript:loadOrAlert('WVOPRHRPFSCLAW7UWHCXCH7QNQIU6TWG') // accept raw hash of 32 base-32 chars, with garbage around it if (accept_magnets && guess) { Pattern pattern = Pattern.compile("[^a-zA-Z2-7][a-zA-Z2-7]{32}[^a-zA-Z2-7]"); Matcher matcher = pattern.matcher(text); if (matcher.find()) { String hash = text.substring(matcher.start() + 1, matcher.start() + 33); return "magnet:?xt=urn:btih:" + hash; } pattern = Pattern.compile("[^a-fA-F0-9][a-fA-F0-9]{40}[^a-fA-F0-9]"); matcher = pattern.matcher(text); if (matcher.find()) { String hash = text.substring(matcher.start() + 1, matcher.start() + 41); // convert from HEX to raw bytes byte[] infohash = ByteFormatter.decodeString(hash.toUpperCase()); // convert to BASE32 return "magnet:?xt=urn:btih:" + Base32.encode(infohash); } } return null; } public static String parseHTMLforURL(String text) { if (text == null) { return null; } // examples: // test // test // moo Pattern pat = Pattern.compile("<.*a\\s++.*href=\"?([^\\'\"\\s>]++).*", Pattern.CASE_INSENSITIVE); Matcher m = pat.matcher(text); if (m.find()) { String sURL = m.group(1); try { sURL = URLDecoder.decode(sURL); } catch (Exception e) { // sometimes fires a IllegalArgumentException // catch everything and ignore. } return sURL; } return null; } public static void main(String[] args) { MagnetURIHandler.getSingleton(); byte[] infohash = ByteFormatter.decodeString("1234567890123456789012345678901234567890"); String[] test = { "http://moo.com", "http%3A%2F/moo%2Ecom", "magnet:?moo", "magnet%3A%3Fxt=urn:btih:26", "magnet%3A//%3Fmooo", "magnet:?xt=urn:btih:" + Base32.encode(infohash), "aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd", "magnet:?dn=OpenOffice.org_2.0.3_Win32Intel_install.exe&xt=urn:sha1:PEMIGLKMNFI4HZ4CCHZNPKZJNMAAORKN&xt=urn:tree:tiger:JMIJVWHCQUX47YYH7O4XIBCORNU2KYKHBBC6DHA&xt=urn:ed2k:1c0804541f34b6583a383bb8f2cec682&xl=96793015&xs=http://mirror.switch.ch/ftp/mirror/OpenOffice/stable/2.0.3/OOo_2.0.3_Win32Intel_install.exe" }; for (int i = 0; i < test.length; i++) { System.out.println("decode: " + test[i] + " -> " + URLDecoder.decode(test[i])); System.out.println("isURL: " + test[i] + " -> " + isURL(test[i])); System.out.println("parse: " + test[i] + " -> " + parseTextForURL(test[i], true)); } } /** * Like URLEncoder.encode, except translates spaces into %20 instead of + * @param s * @return */ public static String encode(String s) { if (s == null) { return ""; } try { return URLEncoder.encode(s, "UTF-8").replaceAll("\\+", "%20"); } catch (UnsupportedEncodingException e) { return URLEncoder.encode(s).replaceAll("\\+", "%20"); } } public static String decode(String s) { if (s == null) { return ""; } try { return( URLDecoder.decode(s, "UTF-8")); } catch (UnsupportedEncodingException e) { return( URLDecoder.decode(s)); } } public static String escapeXML(String s) { if (s == null) { return ""; } String ret = s; for (int i = 0; i < XMLescapes.length; i++) { String[] escapeEntry = (String[])XMLescapes[i]; ret = ret.replaceAll(escapeEntry[0], escapeEntry[1]); } return ret; } public static String unescapeXML(String s) { if (s == null) { return ""; } String ret = s; for (int i = 0; i < XMLescapes.length; i++) { String[] escapeEntry = (String[])XMLescapes[i]; ret = ret.replaceAll(escapeEntry[1], escapeEntry[0]); } return ret; } public static String convertIPV6Host( String host ) { if ( host.indexOf(':') != -1 ){ return( "[" + host + "]" ); } return( host ); } public static String expandIPV6Host( String host ) { if ( host.indexOf(':') != -1 ){ try{ return( InetAddress.getByAddress(InetAddress.getByName( host ).getAddress()).getHostAddress()); }catch( Throwable e ){ Debug.printStackTrace(e); } } return( host ); } public static void connectWithTimeout( final URLConnection connection, long connect_timeout ) throws IOException { connectWithTimeouts( connection, connect_timeout, -1 ); } public static void connectWithTimeouts( final URLConnection connection, long connect_timeout, long read_timeout ) throws IOException { if ( connect_timeout != -1 ){ Java15Utils.setConnectTimeout( connection, (int)connect_timeout ); } if ( read_timeout != -1 ){ Java15Utils.setReadTimeout( connection, (int)read_timeout ); } connection.connect(); } private static String last_headers = COConfigurationManager.getStringParameter( "metasearch.web.last.headers", null ); private static final String default_headers = "SG9zdDogbG9jYWxob3N0OjQ1MTAwClVzZXItQWdlbnQ6IE1vemlsbGEvNS4wIChXaW5kb3dzOyBVOyBXaW5kb3dzIE5UIDUuMTsgZW4tVVM7IHJ2OjEuOC4xLjE0KSBHZWNrby8yMDA4MDQwNCBGaXJlZm94LzIuMC4wLjE0CkFjY2VwdDogdGV4dC94bWwsYXBwbGljYXRpb24veG1sLGFwcGxpY2F0aW9uL3hodG1sK3htbCx0ZXh0L2h0bWw7cT0wLjksdGV4dC9wbGFpbjtxPTAuOCxpbWFnZS9wbmcsKi8qO3E9MC41CkFjY2VwdC1MYW5ndWFnZTogZW4tdXMsZW47cT0wLjUKQWNjZXB0LUVuY29kaW5nOiBnemlwLGRlZmxhdGUKQWNjZXB0LUNoYXJzZXQ6IElTTy04ODU5LTEsdXRmLTg7cT0wLjcsKjtxPTAuNwpLZWVwLUFsaXZlOiAzMDAKQ29ubmVjdGlvbjoga2VlcC1hbGl2ZQ=="; public static void setBrowserHeaders( ResourceDownloader rd, String referer ) { setBrowserHeaders( rd, null, referer ); } public static void setBrowserHeaders( ResourceDownloader rd, String encoded_headers, String referer ) { String headers_to_use = getBrowserHeadersToUse( encoded_headers ); try{ String header_string = new String( Base64.decode( headers_to_use ), "UTF-8" ); String[] headers = header_string.split( "\n" ); for (int i=0;i 0 ){ rd.setProperty( "URL_Referer", referer ); } }catch( Throwable e ){ } } public static void setBrowserHeaders( ResourceUploader ru, String encoded_headers, String referer ) { String headers_to_use = getBrowserHeadersToUse( encoded_headers ); try{ String header_string = new String( Base64.decode( headers_to_use ), "UTF-8" ); String[] headers = header_string.split( "\n" ); for (int i=0;i 0 ){ ru.setProperty( "URL_Referer", referer ); } }catch( Throwable e ){ } } public static void setBrowserHeaders( URLConnection connection, String referer ) { setBrowserHeaders( connection, null, referer ); } public static void setBrowserHeaders( URLConnection connection, String encoded_headers, String referer ) { String headers_to_use = getBrowserHeadersToUse( encoded_headers ); try{ String header_string = new String( Base64.decode( headers_to_use ), "UTF-8" ); String[] headers = header_string.split( "\n" ); for (int i=0;i 0 ){ connection.setRequestProperty( "Referer", referer ); } }catch( Throwable e ){ } } public static Map getBrowserHeaders( String referer ) { String headers_to_use = getBrowserHeadersToUse( null ); Map result = new HashMap(); try{ String header_string = new String( Base64.decode( headers_to_use ), "UTF-8" ); String[] headers = header_string.split( "\n" ); for (int i=0;i 0){ result.put( "Referer", referer ); } }catch( Throwable e ){ } return( result ); } private static String getBrowserHeadersToUse( String encoded_headers ) { String headers_to_use = encoded_headers; synchronized( UrlUtils.class ){ if ( headers_to_use == null ){ if ( last_headers != null ){ headers_to_use = last_headers; }else{ headers_to_use = default_headers; } }else{ if ( last_headers == null || !headers_to_use.equals( last_headers )){ COConfigurationManager.setParameter( "metasearch.web.last.headers", headers_to_use ); } last_headers = headers_to_use; } } return( headers_to_use ); } public static boolean queryHasParameter(String query_string, String param_name, boolean case_sensitive) { if (!case_sensitive) { query_string = query_string.toLowerCase(); param_name = param_name.toLowerCase(); } if (query_string.charAt(0) == '?') { query_string = '&' + query_string.substring(1); } else if (query_string.charAt(0) != '&') { query_string = '&' + query_string; } return query_string.indexOf("&" + param_name + "=") != -1; } public static boolean containsPasskey( URL url ) { String url_str = url.toExternalForm(); return( url_str.matches(".*[0-9a-z]{20,40}.*")); } public static URL setPort( URL u, int port ) { StringBuffer result = new StringBuffer(); result.append(u.getProtocol()); result.append(":"); String authority=u.getAuthority(); if (authority != null && authority.length() > 0) { result.append("//"); int pos = authority.indexOf( '@' ); if ( pos != -1 ){ result.append(authority.substring(0,pos+1)); authority = authority.substring(pos+1); } pos = authority.lastIndexOf(':'); if ( pos == -1 ){ result.append(authority + ":" + port ); }else{ result.append(authority.substring(0,pos+1) + port ); } } if (u.getPath() != null) { result.append(u.getPath()); } if (u.getQuery() != null) { result.append('?'); result.append(u.getQuery()); } if (u.getRef() != null) { result.append("#"); result.append(u.getRef()); } try{ return( new URL( result.toString())); }catch( Throwable e ){ Debug.out(e); return(u); } } public static URL setHost( URL u, String host ) { StringBuffer result = new StringBuffer(); result.append(u.getProtocol()); result.append(":"); String authority=u.getAuthority(); if (authority != null && authority.length() > 0) { result.append("//"); int pos = authority.indexOf( '@' ); if ( pos != -1 ){ result.append(authority.substring(0,pos+1)); authority = authority.substring(pos+1); } pos = authority.lastIndexOf(':'); if ( pos == -1 ){ result.append(host ); }else{ result.append(host + authority.substring(pos)); } } if (u.getPath() != null) { result.append(u.getPath()); } if (u.getQuery() != null) { result.append('?'); result.append(u.getQuery()); } if (u.getRef() != null) { result.append("#"); result.append(u.getRef()); } try{ return( new URL( result.toString())); }catch( Throwable e ){ Debug.out(e); return(u); } } /** * Returns an explicit IPv4 url if the supplied one has both IPv6 and IPv4 addresses * @param url * @return */ public static URL getIPV4Fallback( URL url ) { try{ InetAddress[] addresses = InetAddress.getAllByName( url.getHost()); if ( addresses.length > 0 ){ InetAddress ipv4 = null; InetAddress ipv6 = null; for ( InetAddress a: addresses ){ if ( a instanceof Inet4Address ){ ipv4 = a; }else{ ipv6 = a; } } if ( ipv4 != null && ipv6 != null ){ url = UrlUtils.setHost( url, ipv4.getHostAddress()); return( url ); } } }catch( Throwable f ){ } return( null ); } public static long getContentLength( HttpURLConnection con ) { long res = con.getContentLength(); if ( res == -1 ){ try{ String str = con.getHeaderField( "content-length" ); if ( str != null ){ res = Long.parseLong( str ); } }catch( Throwable e ){ } } return( res ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/UnresolvableHostManager.java0000644000175000017500000000423210373051004025574 0ustar adrianadrian/* * Created on 11-Oct-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.core3.logging.*; public class UnresolvableHostManager { // sometimes we need an IP address for a host in order to function (for example, when banning // peers) but the name we have got a host is unresolvable (for whatever reason, e.g. its the // name of an TOR hidden service). Here we map such hosts onto class E (i.e. experimental) IP // addresses so things mainly work protected static int next_address = 0xf0000000 + (int)(0x00ffffff*Math.random()); protected static Map host_map = new HashMap(); public static int getPseudoAddress( String str ) { synchronized( host_map ){ Integer res = (Integer)host_map.get(str); if ( res == null ){ res = new Integer( next_address++ ); if (Logger.isEnabled()) Logger.log(new LogEvent(LogIDs.NET, "Allocated pseudo IP address '" + Integer.toHexString(res.intValue()) + "' for host '" + str + "'")); host_map.put( str, res ); } return( res.intValue()); } } public static boolean isPseudoAddress( String str ) { synchronized( host_map ){ return( host_map.get(str) != null ); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/FileIsADirectoryException.java0000644000175000017500000000251111012742274026027 0ustar adrianadrian/* * Created on 09.11.2003 * * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.util; import java.io.FileNotFoundException; /** * @author Tobias Minich * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public class FileIsADirectoryException extends FileNotFoundException { /** * @param string */ public FileIsADirectoryException(String string) { super(string); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/jar/0000755000175000017500000000000011310377634020726 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/util/jar/AEJarReader.java0000644000175000017500000000420310130407476023632 0ustar adrianadrian/* * File : WUJarReader.java * Created : 31-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.jar; /** * @author parg * */ import java.util.*; import java.io.*; import java.util.jar.*; import org.gudy.azureus2.core3.util.Debug; public class AEJarReader { protected Map entries = new HashMap(); public AEJarReader( String name ) { InputStream is = null; JarInputStream jis = null; try{ is = getClass().getClassLoader().getResourceAsStream(name); jis = new JarInputStream(is ); while( true ){ JarEntry ent = jis.getNextJarEntry(); if ( ent == null ){ break; } if ( ent.isDirectory()){ continue; } ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[8192]; while( true ){ int l = jis.read( buffer ); if ( l <= 0 ){ break; } baos.write( buffer, 0, l ); } entries.put( ent.getName(), new ByteArrayInputStream( baos.toByteArray())); } }catch( Throwable e ){ Debug.printStackTrace( e ); }finally{ try{ if ( jis != null ){ jis.close(); } if (is != null){ is.close(); } }catch( Throwable e ){ } } } public InputStream getResource( String name ) { return((InputStream)entries.get(name)); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/jar/AEJarSigner2.java0000644000175000017500000001420711016075540023743 0ustar adrianadrian/* * Created on 04-Oct-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util.jar; import java.net.*; import java.io.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.*; /** * @author parg * */ public class AEJarSigner2 { protected static Class JarSigner_class; protected String keystore_name; protected String keystore_password; protected String alias; public AEJarSigner2( String _alias, String _keystore_name, String _keystore_password ) { alias = _alias; keystore_name = _keystore_name; keystore_password = _keystore_password; } protected void loadJarSigner() throws IOException { File tools_dir; String manual_tools_dir = COConfigurationManager.getStringParameter( "Security.JAR.tools.dir" ); if ( manual_tools_dir.length() == 0 ){ String java_home = System.getProperty( "java.home" ); // if it ends in "jre" then go up one dir // then look for lib/tools.jar File jh = new File( java_home ); if ( jh.getName().equalsIgnoreCase("jre")){ jh = jh.getParentFile(); }else{ // otherwise, for 1.5, see if the JDK is also installed in default position String dir_name = jh.getName(); if ( dir_name.startsWith( "jre" )){ dir_name = "jdk" + dir_name.substring(3); jh = new File( jh.getParentFile(), dir_name ); } } tools_dir = new File( jh, "lib" ); }else{ tools_dir = new File( manual_tools_dir ); } File tools_jar = new File( tools_dir, "tools.jar" ); // System.out.println( "tools_jar = " + tools_jar.toString() + ", exists = " + tools_jar.exists()); if ( tools_jar.exists()){ try{ ClassLoader cl = new URLClassLoader(new URL[]{tools_jar.toURL()},AEJarSigner2.class.getClassLoader()); JarSigner_class = cl.loadClass( "sun.security.tools.JarSigner" ); }catch( Throwable e ){ Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Security.jar.signfail"), new String[] { e .getMessage() }); Debug.printStackTrace(e); throw( new IOException( "JAR signing fails: " + e.getMessage())); } }else{ Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Security.jar.tools_not_found"), new String[] { tools_dir.toString() }); throw( new IOException( "JAR signing fails: tools.jar not found" )); } } protected void signJarFile( File input_file ) throws IOException { if ( JarSigner_class == null ){ loadJarSigner(); } PrintStream old_err = null; PrintStream old_out = null; String failure_msg = null; try{ Object jar_signer = JarSigner_class.newInstance(); String[] args = { "-keystore", keystore_name, "-storepass", keystore_password, input_file.toString(), alias }; old_err = System.err; old_out = System.out; ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); System.setErr( ps ); System.setOut( ps ); try{ JarSigner_class.getMethod( "run", new Class[]{ String[].class }).invoke( jar_signer, new Object[]{ args }); }catch( Throwable e ){ ps.close(); String err_msg = baos.toString(); if ( err_msg.length() > 0 ){ failure_msg = err_msg; }else{ Debug.printStackTrace(e); failure_msg = e.getMessage(); } } }catch( Throwable e ){ Debug.printStackTrace(e); failure_msg = e.getMessage(); }finally{ if ( old_err != null ){ System.setErr( old_err ); System.setOut( old_out ); } } if ( failure_msg != null ){ Debug.out( "JAR signing fails '" + failure_msg + "'" ); Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Security.jar.signfail"), new String[] { failure_msg }); throw( new IOException( "JAR signing fails: " + failure_msg )); } } public void signJarFile( File file, OutputStream os ) throws IOException { signJarFile( file ); FileInputStream fis = null; try{ fis = new FileInputStream( file ); FileUtil.copyFile( file, os, false ); }finally{ try{ if (fis != null) {fis.close();} }catch( Throwable e ){ Debug.printStackTrace(e); } } } public void signJarStream( InputStream is, OutputStream os ) throws IOException { File temp_file = AETemporaryFileHandler.createTempFile(); FileOutputStream fos = null; try{ byte[] buffer = new byte[8192]; fos = new FileOutputStream( temp_file ); while(true){ int len = is.read( buffer ); if ( len <= 0 ){ break; } fos.write( buffer, 0, len ); } fos.close(); fos = null; signJarFile( temp_file, os ); }finally{ try{ is.close(); }catch( Throwable e ){ Debug.printStackTrace( e ); } if ( fos != null ){ try{ fos.close(); }catch( Throwable e ){ Debug.printStackTrace( e ); } } temp_file.delete(); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/jar/AEJarBuilder.java0000644000175000017500000001403110343557140024016 0ustar adrianadrian/* * File : WUJarBuilder.java * Created : 10-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.jar; /** * @author parg * */ import java.io.*; import java.net.URL; import java.net.URI; import java.util.jar.*; import java.util.*; import org.gudy.azureus2.core3.security.SEKeyDetails; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.logging.*; public class AEJarBuilder { public static long buildFromPackages( OutputStream os, ClassLoader class_loader, String[] package_names, Map package_map, String sign_alias ) throws IOException { List resource_names = new ArrayList(); for (int i=0;i latest_time ){ latest_time = time; } } }catch( Throwable e ){ Debug.printStackTrace( e ); } JarEntry entry = new JarEntry(resource_name); writeEntry( jos, entry, is ); } }finally{ if ( is != null ){ is.close(); } } } JarEntry entry = new JarEntry("META-INF/MANIFEST.MF"); ByteArrayInputStream bais = new ByteArrayInputStream("Manifest-Version: 1.0\r\n\r\n".getBytes()); writeEntry( jos, entry, bais ); jos.flush(); jos.finish(); return( latest_time ); } private static void writeEntry( JarOutputStream jos, JarEntry entry, InputStream data ) throws IOException { jos.putNextEntry(entry); byte[] newBytes = new byte[4096]; int size = data.read(newBytes); while (size != -1){ jos.write(newBytes, 0, size); size = data.read(newBytes); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/jar/AEJarSigner.java0000644000175000017500000002116610373051052023660 0ustar adrianadrian/* * Created on 07-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util.jar; /** * @author parg * */ public class AEJarSigner { } /* import java.io.*; import java.security.*; import java.security.cert.*; import java.util.*; import java.util.jar.*; import org.gudy.azureus2.core3.util.Debug; import sun.misc.BASE64Encoder; import sun.security.util.ManifestDigester; import sun.security.util.SignatureFile; public class WUJarSigner { protected static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; protected String alias; protected PrivateKey privateKey; protected X509Certificate[] certChain; public WUJarSigner( String _alias, PrivateKey _privateKey, X509Certificate[] _certChain ) { alias = _alias; privateKey = _privateKey; certChain = _certChain; } protected Manifest getManifestFile( JarFile jarFile ) throws IOException { Manifest manifest = new Manifest(); JarEntry entry = jarFile.getJarEntry( MANIFEST_NAME ); if ( entry != null ){ manifest.read( jarFile.getInputStream( entry ) ); } return manifest; } protected Map removeMissingEntriesFromManifest( Manifest manifest, JarFile jarFile ) throws IOException { Map map = manifest.getEntries(); Iterator elements = map.keySet().iterator(); while( elements.hasNext() ){ String element = (String)elements.next(); if ( jarFile.getEntry( element ) == null ){ elements.remove(); } } return( map ); } private Map createEntries( Manifest manifest, JarFile jarFile ) throws IOException { Map entries = null; if( manifest.getEntries().size() > 0 ){ // already existing manifest, just remove any extra entries entries = removeMissingEntriesFromManifest( manifest, jarFile ); }else{ // new manifest, stick in default values Attributes attributes = manifest.getMainAttributes(); attributes.putValue( Attributes.Name.MANIFEST_VERSION.toString(), "1.0" ); attributes.putValue( "Created-By", System.getProperty( "java.version" ) + " (" + System.getProperty( "java.vendor" ) + ")" ); entries = manifest.getEntries(); } return entries; } protected String updateDigest( MessageDigest digest, InputStream inputStream ) throws IOException { byte[] buffer = new byte[8192]; while( true ){ int len = inputStream.read( buffer); if ( len <= 0 ){ break; } digest.update( buffer, 0, len ); } inputStream.close(); return( new BASE64Encoder().encode( digest.digest())); } protected Map updateManifestEntries( Manifest manifest, JarFile jar_file, MessageDigest message_digest, Map entries ) throws IOException { Enumeration jar_entries = jar_file.entries(); while ( jar_entries.hasMoreElements()){ JarEntry entry = (JarEntry)jar_entries.nextElement(); if ( entry.getName().startsWith( "META-INF" ) ){ continue; }else if ( manifest.getAttributes( entry.getName() ) != null ){ Attributes attributes = manifest.getAttributes( entry.getName() ); attributes.putValue( "SHA1-Digest", updateDigest( message_digest, jar_file.getInputStream( entry ) )); }else if ( !entry.isDirectory()){ Attributes attributes = new Attributes(); attributes.putValue( "SHA1-Digest", updateDigest( message_digest, jar_file.getInputStream( entry ) )); entries.put( entry.getName(), attributes ); } } return( entries ); } protected byte[] serialiseManifest( Manifest manifest ) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); manifest.write( baos ); baos.flush(); baos.close(); return( baos.toByteArray()); } protected SignatureFile createSignatureFile( Manifest manifest, MessageDigest messageDigest ) throws IOException { ManifestDigester manifestDigester = new ManifestDigester( serialiseManifest( manifest ) ); return( new SignatureFile( new MessageDigest[]{ messageDigest }, manifest, manifestDigester, alias, true )); } protected void writeJarEntry( JarEntry entry, JarFile jar_file, JarOutputStream jos ) throws IOException { jos.putNextEntry( new JarEntry( entry.getName())); byte[] buffer = new byte[8192]; InputStream is = jar_file.getInputStream( entry ); while( true ){ int len = is.read( buffer ); if ( len <= 0 ){ break; } jos.write( buffer, 0, len ); } jos.closeEntry(); } public void signJarFile( JarFile jar_file, OutputStream output_stream ) throws NoSuchAlgorithmException, InvalidKeyException, CertificateException, SignatureException, IOException { Manifest manifest = getManifestFile( jar_file ); Map entries = createEntries( manifest, jar_file ); MessageDigest messageDigest = MessageDigest.getInstance( "SHA1" ); updateManifestEntries( manifest, jar_file, messageDigest, entries ); SignatureFile signatureFile = createSignatureFile( manifest, messageDigest ); SignatureFile.Block block = signatureFile.generateBlock( privateKey, certChain, true ); String manifestFileName = MANIFEST_NAME; JarOutputStream jos = output_stream instanceof JarOutputStream?(JarOutputStream)output_stream:new JarOutputStream( output_stream ); JarEntry manifestFile = new JarEntry( manifestFileName ); jos.putNextEntry( manifestFile ); byte[] manifest_bytes = serialiseManifest( manifest ); jos.write( manifest_bytes ); jos.closeEntry(); String signatureFileName = signatureFile.getMetaName(); JarEntry signatureFileEntry = new JarEntry( signatureFileName ); jos.putNextEntry( signatureFileEntry ); signatureFile.write( jos ); jos.closeEntry(); String signatureBlockName = block.getMetaName(); JarEntry signatureBlockEntry = new JarEntry( signatureBlockName ); jos.putNextEntry( signatureBlockEntry ); block.write( jos ); jos.closeEntry(); Enumeration metaEntries = jar_file.entries(); while( metaEntries.hasMoreElements() ){ JarEntry metaEntry = (JarEntry)metaEntries.nextElement(); if ( metaEntry.getName().startsWith( "META-INF" ) && !( manifestFileName.equalsIgnoreCase( metaEntry.getName()) || signatureFileName.equalsIgnoreCase( metaEntry.getName()) || signatureBlockName.equalsIgnoreCase( metaEntry.getName()))){ writeJarEntry( metaEntry, jar_file, jos ); } } Enumeration allEntries = jar_file.entries(); while( allEntries.hasMoreElements() ){ JarEntry entry = (JarEntry)allEntries.nextElement(); if( !entry.getName().startsWith( "META-INF" )){ writeJarEntry( entry, jar_file, jos ); } } jos.flush(); jos.finish(); jar_file.close(); } public void signJarStream( InputStream is, OutputStream os ) throws NoSuchAlgorithmException, InvalidKeyException, CertificateException, SignatureException, IOException { File temp_file = File.createTempFile("AZU", null ); FileOutputStream fos = null; try{ byte[] buffer = new byte[8192]; fos = new FileOutputStream( temp_file ); while(true){ int len = is.read( buffer ); if ( len <= 0 ){ break; } fos.write( buffer, 0, len ); } fos.close(); fos = null; signJarFile( new JarFile(temp_file), os ); }finally{ try{ is.close(); }catch( Throwable e ){ Debug.printStackTrace( e ); } if ( fos != null ){ try{ fos.close(); }catch( Throwable e ){ Debug.printStackTrace( e ); } } temp_file.delete(); } } } */ azureus-4.3.0.6/org/gudy/azureus2/core3/util/jar/Test.java0000644000175000017500000000367510373051052022512 0ustar adrianadrian/* * Created on 07-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util.jar; /** * @author parg * */ import java.io.*; import org.gudy.azureus2.core3.security.*; import org.gudy.azureus2.core3.util.Debug; public class Test { public static void main( String[] args ) { try{ SESecurityManager.initialise(); System.out.println( System.getProperty( "java.home" )); String alias = "Azureus"; // SESecurityManager.DEFAULT_ALIAS; // SEKeyDetails kd = SESecurityManager.getKeyDetails( alias ); // WUJarSigner signer = new WUJarSigner(alias, (PrivateKey)kd.getKey(), kd.getCertificateChain()); AEJarSigner2 signer = new AEJarSigner2( alias, SESecurityManager.getKeystoreName(), SESecurityManager.getKeystorePassword()); FileOutputStream fos = new FileOutputStream( "c:\\temp\\sj.jar"); signer.signJarFile( new File( "c:\\temp\\si.jar"), fos ); fos.close(); }catch( Throwable e ){ Debug.printStackTrace( e ); } System.out.println("normal exit"); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/DelayedEvent.java0000644000175000017500000000300411021627464023361 0ustar adrianadrian/* * Created on 12-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author parg * */ public class DelayedEvent { private TimerEvent event; public DelayedEvent( String name, long delay_millis, final AERunnable target ) { event = SimpleTimer.addEvent( name, SystemTime.getCurrentTime() + delay_millis, new TimerEventPerformer() { public void perform( TimerEvent event ) { try{ target.run(); }finally{ } } }); } public void cancel() { event.cancel(); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/BrokenMd5Hasher.java0000644000175000017500000002526410336676050023750 0ustar adrianadrian/******************************************************************************** * * jMule - a Java massive parallel file sharing client * * Copyright (C) by the jMuleGroup ( see the CREDITS file ) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Plac(int)e, Suite 330, Boston, MA 02111-1307 USA * * $Id: BrokenMd5Hasher.java,v 1.1 2005/11/16 13:36:23 parg Exp $ * ********************************************************************************/ package org.gudy.azureus2.core3.util; import java.nio.ByteBuffer; import java.nio.ByteOrder; /** * Use this class for getting a MD5 message digest. * Create a MD5 and reuse it after a message digest calculation. There can be as * many MD5 objects as you want to have multiple calculations same time. * The message can be passed in one or a sequenze of parts wrapped in a * ByteBuffer to the update of the same MD5 instance. To finish the calculation * use final, it will reset the MD5 instance for a new calculation. * * @author emarant * @version $Revision: 1.1 $ *
      Last changed by $Author: parg $ on $Date: 2005/11/16 13:36:23 $ */ public final class BrokenMd5Hasher { private ByteBuffer buffer = ByteBuffer.allocate(64).order(ByteOrder.LITTLE_ENDIAN); private int stateA = 0x67452301; private int stateB = 0xEFCDAB89; private int stateC = 0x98BADCFE; private int stateD = 0x10325476; private long count = 0; /** * Constructor returns a MD6 ready for use. */ public BrokenMd5Hasher(){ } public byte[] calculateHash( byte[] data ) { ByteBuffer input_buffer = ByteBuffer.wrap(data); reset(); update(input_buffer); ByteBuffer result_buffer = ByteBuffer.allocate(16); finalDigest(result_buffer); byte[] result = new byte[16]; result_buffer.position(0); for(int i = 0 ; i < result.length ; i++) { result[i] = result_buffer.get(); } return result; } /** * Resets the MD5 to initial state for a new message digest calculation. */ public void reset(){ stateA = 0x67452301; stateB = 0xEFCDAB89; stateC = 0x98BADCFE; stateD = 0x10325476; count = 0; buffer.rewind(); for(int i=0;i<64;i++){ buffer.put((byte)0); } buffer.rewind(); } /** * Starts or continues a MD5 message digest calculation. * input.remaining() should be a multiple of 64 to be most efficant, but * other amounts work too. Only remaining bytes of the ByteBuffer are used * and input.position() will be input.limit() after return. * @param input hold a part of the message. input.order() have to be ByteOrder.LITTLE_ENDIAN */ public void update(ByteBuffer input){ int index, partLen, i, inputLen; inputLen = input.remaining(); index = ((int)count) & 63; count += inputLen; partLen = 64 - index; i = 0; if (inputLen >= partLen){ if (index>0){ int t = input.limit(); input.limit(input.position()+partLen); buffer.put(input); buffer.rewind(); input.limit(t); transform(buffer); buffer.rewind(); i = partLen; index = partLen; } while(i + 63 < inputLen){ transform(input); i += 64; } } if (ireset
      and so * ready for a new message digest calculation. * * @param digest should be a ByteBuffer with digest.remaining() >= 16 * */ public void finalDigest(ByteBuffer digest){ int index; index = ((int)count) & 63; if (index < 56){ buffer.put((byte)0x80); for(int i = index ; i < 55 ;i++) buffer.put((byte)0); buffer.putLong(count << 3); buffer.rewind(); transform(buffer); buffer.rewind(); }else{ buffer.put((byte)0x80); for(int i = index ; i < 63 ; i++) buffer.put((byte)0); buffer.rewind(); transform(buffer); buffer.rewind(); for(int i=0;i<56;i++) buffer.put((byte)0); buffer.putLong(count << 3); buffer.rewind(); transform(buffer); buffer.rewind(); } // save the result in digest digest.putInt(stateA); digest.putInt(stateB); digest.putInt(stateC); digest.putInt(stateD); reset(); } private void transform(ByteBuffer block) { int a, b, c, d; long e, f, g, h, i, j, k, l; a = stateA; b = stateB; c = stateC; d = stateD; e = block.getLong();// 0 1 f = block.getLong();// 2 3 g = block.getLong();// 4 5 h = block.getLong();// 6 7 i = block.getLong();// 8 9 j = block.getLong();//10 11 k = block.getLong();//12 13 l = block.getLong();//14 15 a = FF(a, b, c, d, (int)e, 7, 0xd76aa478); d = FF(d, a, b, c, (int)(e >>> 32), 12, 0xe8c7b756); c = FF(c, d, a, b, (int)f, 17, 0x242070db); b = FF(b, c, d, a, (int)(f >>> 32), 22, 0xc1bdceee); a = FF(a, b, c, d, (int)g, 7, 0xf57c0faf); d = FF(d, a, b, c, (int)(g >>> 32), 12, 0x4787c62a); c = FF(c, d, a, b, (int)h, 17, 0xa8304613); b = FF(b, c, d, a, (int)(h >>> 32), 22, 0xfd469501); a = FF(a, b, c, d, (int)i, 7, 0x698098d8); d = FF(d, a, b, c, (int)(i >>> 32), 12, 0x8b44f7af); c = FF(c, d, a, b, (int)j, 17, 0xffff5bb1); b = FF(b, c, d, a, (int)(j >>> 32), 22, 0x895cd7be); a = FF(a, b, c, d, (int)k, 7, 0x6b901122); d = FF(d, a, b, c, (int)(k >>> 32), 12, 0xfd987193); c = FF(c, d, a, b, (int)l, 17, 0xa679438e); b = FF(b, c, d, a, (int)(l >>> 32), 22, 0x49b40821); a = GG(a, b, c, d, (int)(e >>>32), 5, 0xf61e2562); d = GG(d, a, b, c, (int)h, 9, 0xc040b340); c = GG(c, d, a, b, (int)(j >>> 32), 14, 0x265e5a51); b = GG(b, c, d, a, (int)e, 20, 0xe9b6c7aa); a = GG(a, b, c, d, (int)(g >>> 32), 5, 0xd62f105d); d = GG(d, a, b, c, (int)j, 9, 0x02441453); c = GG(c, d, a, b, (int)(l >>> 32), 14, 0xd8a1e681); b = GG(b, c, d, a, (int)g, 20, 0xe7d3fbc8); a = GG(a, b, c, d, (int)(i >>> 32), 5, 0x21e1cde6); d = GG(d, a, b, c, (int)l, 9, 0xc33707d6); c = GG(c, d, a, b, (int)(f >>> 32), 14, 0xf4d50d87); b = GG(b, c, d, a, (int)i, 20, 0x455a14ed); a = GG(a, b, c, d, (int)(k >>> 32), 5, 0xa9e3e905); d = GG(d, a, b, c, (int)f, 9, 0xfcefa3f8); c = GG(c, d, a, b, (int)(h >>> 32), 14, 0x676f02d9); b = GG(b, c, d, a, (int)k, 20, 0x8d2a4c8a); a = HH(a, b, c, d, (int)(g >>> 32), 4, 0xfffa3942); d = HH(d, a, b, c, (int)i, 11, 0x8771f681); c = HH(c, d, a, b, (int)(j >>> 32), 16, 0x6d9d6122); b = HH(b, c, d, a, (int)l, 23, 0xfde5380c); a = HH(a, b, c, d, (int)(e >>>32), 4, 0xa4beea44); d = HH(d, a, b, c, (int)g, 11, 0x4bdecfa9); c = HH(c, d, a, b, (int)(h >>> 32), 16, 0xf6bb4b60); b = HH(b, c, d, a, (int)j, 23, 0xbebfbc70); a = HH(a, b, c, d, (int)(k >>> 32), 4, 0x289b7ec6); d = HH(d, a, b, c, (int)e, 11, 0xeaa127fa); c = HH(c, d, a, b, (int)(f >>> 32), 16, 0xd4ef3085); b = HH(b, c, d, a, (int)h, 23, 0x04881d05); a = HH(a, b, c, d, (int)(i >>> 32), 4, 0xd9d4d039); d = HH(d, a, b, c, (int)k, 11, 0xe6db99e5); c = HH(c, d, a, b, (int)(l >>> 32), 16, 0x1fa27cf8); b = HH(b, c, d, a, (int)f, 23, 0xc4ac5665); a = II(a, b, c, d, (int)e, 6, 0xf4292244); d = II(d, a, b, c, (int)(h >>> 32), 10, 0x432aff97); c = II(c, d, a, b, (int)l, 15, 0xab9423a7); b = II(b, c, d, a, (int)(g >>> 32), 21, 0xfc93a039); a = II(a, b, c, d, (int)k, 6, 0x655b59c3); d = II(d, a, b, c, (int)(f >>> 32), 10, 0x8f0ccc92); c = II(c, d, a, b, (int)j, 15, 0xffeff47d); b = II(b, c, d, a, (int)(e >>>32), 21, 0x85845dd1); a = II(a, b, c, d, (int)i, 6, 0x6fa87e4f); d = II(d, a, b, c, (int)(l >>> 32), 10, 0xfe2ce6e0); c = II(c, d, a, b, (int)h, 15, 0xa3014314); b = II(b, c, d, a, (int)(k >>> 32), 21, 0x4e0811a1); a = II(a, b, c, d, (int)g, 6, 0xf7537e82); d = II(d, a, b, c, (int)(j >>> 32), 10, 0xbd3af235); c = II(c, d, a, b, (int)f, 15, 0x2ad7d2bb); b = II(b, c, d, a, (int)(i >>> 32), 21, 0xeb86d391); stateA += a; stateB += b; stateC += c; stateD += d; } private static int FF(int a, int b, int c, int d, int x, int s, int t) { int r = a + x + t + (d ^ (b & (c ^ d))); return (r << s | r >>> (32 - s)) + b; } private static int GG(int a, int b, int c, int d, int x, int s, int t) { int r = a + x + t + (c ^ (d & (b ^ c))); return (r << s | r >>> (32 - s)) + b; } private static int HH(int a, int b, int c, int d, int x, int s, int t) { int r = a + x + t + (b ^ c ^ d); return (r << s | r >>> (32 - s)) + b; } private static int II(int a, int b, int c, int d, int x, int s, int t) { int r = a + x + t + (c ^ (b | ~d)); return (r << s | r >>> (32 - s)) + b; } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/BEncoder.java0000644000175000017500000005123711271211076022477 0ustar adrianadrian/* * BEncoder.java * * Created on June 4, 2003, 10:17 PM * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.util; import java.io.*; import java.net.URLEncoder; import java.nio.ByteBuffer; import java.util.*; import org.gudy.azureus2.core3.xml.util.XUXmlWriter; /** * A set of utility methods to encode a Map into a bencoded array of byte. * integer are represented as Long, String as byte[], dictionnaries as Map, and list as List. * * @author TdC_VgA */ public class BEncoder { private static final int BUFFER_DOUBLE_LIMIT = 256*1024; private static final byte[] MINUS_1_BYTES = "-1".getBytes(); public static byte[] encode( Map object ) throws IOException { return( encode( object, false )); } public static byte[] encode( Map object, boolean url_encode ) throws IOException { BEncoder encoder = new BEncoder(url_encode); encoder.encodeObject( object); return( encoder.toByteArray()); } private byte[] current_buffer = new byte[256]; private int current_buffer_pos = 0; private byte[][] old_buffers; private byte[] int_buffer = new byte[12]; private boolean url_encode; private BEncoder( boolean _url_encode ) { url_encode = _url_encode; } private boolean encodeObject( Object object) throws IOException { if (object instanceof BEncodableObject) { object = ((BEncodableObject)object).toBencodeObject(); } if ( object instanceof String || object instanceof Float){ String tempString = (object instanceof String) ? (String)object : String.valueOf((Float)object); // usually this is simpler to encode by hand as chars < 0x80 map directly in UTF-8 boolean simple = true; char[] chars = tempString.toCharArray(); int char_count = chars.length; byte[] encoded = new byte[char_count]; for (int i=0;i " + current_buffer_pos ); return( res ); }else{ int total = current_buffer_pos; for (int i=0;i " + str + "," + current_buffer_pos ); return( res ); } } private static Object normaliseObject( Object o ) { if ( o instanceof Integer ){ o = new Long(((Integer)o).longValue()); }else if ( o instanceof Boolean ){ o = new Long(((Boolean)o).booleanValue()?1:0); }else if ( o instanceof Float ){ o = String.valueOf((Float)o); }else if ( o instanceof byte[] ){ try{ o = new String((byte[])o,"UTF-8"); }catch( Throwable e ){ } } return( o ); } public static boolean isEncodable(Object toCheck) { if (toCheck instanceof Integer || toCheck instanceof Long || toCheck instanceof Boolean || toCheck instanceof Float || toCheck instanceof byte[] || toCheck instanceof String || toCheck instanceof BEncodableObject) return true; if (toCheck instanceof Map) { for (Iterator it = ((Map) toCheck).keySet().iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry) it.next(); Object key = entry.getKey(); if (!(key instanceof String || key instanceof byte[]) || !isEncodable(entry.getValue())) return false; } return true; } if (toCheck instanceof List) { for (Iterator it = ((List) toCheck).iterator(); it.hasNext();) if (!isEncodable(it.next())) return false; return true; } return false; } public static boolean objectsAreIdentical( Object o1, Object o2 ) { if ( o1 == null && o2 == null ){ return( true ); }else if ( o1 == null || o2 == null ){ return( false ); } if ( o1.getClass() != o2.getClass()){ if ( ( o1 instanceof Map && o2 instanceof Map ) || ( o1 instanceof List && o2 instanceof List )){ // things actually OK }else{ o1 = normaliseObject( o1 ); o2 = normaliseObject( o2 ); if ( o1.getClass() != o2.getClass()){ Debug.out( "Failed to normalise classes " + o1.getClass() + "/" + o2.getClass()); return( false ); } } } if ( o1 instanceof Long || o1 instanceof String ){ return( o1.equals( o2 )); }else if ( o1 instanceof byte[] ){ return( Arrays.equals((byte[])o1,(byte[])o2 )); }else if ( o1 instanceof List ){ return( listsAreIdentical((List)o1,(List)o2)); }else if ( o1 instanceof Map ){ return( mapsAreIdentical((Map)o1,(Map)o2)); }else if ( o1 instanceof Integer || o1 instanceof Boolean || o1 instanceof Float || o1 instanceof ByteBuffer ){ return( o1.equals( o2 )); }else{ Debug.out( "Invalid type: " + o1 ); return( false ); } } public static boolean listsAreIdentical( List list1, List list2 ) { if ( list1 == null && list2 == null ){ return( true ); }else if ( list1 == null || list2 == null ){ return( false ); } if ( list1.size() != list2.size()){ return( false ); } for ( int i=0;i= 65536) { q = i / 100; // really: r = i - (q * 100); r = i - ((q << 6) + (q << 5) + (q << 2)); i = q; int_buffer [--charPos] = DigitOnes[r]; int_buffer [--charPos] = DigitTens[r]; } // Fall thru to fast mode for smaller numbers // assert(i <= 65536, i); for (;;) { q = (i * 52429) >>> (16+3); r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... int_buffer [--charPos] = digits [r]; i = q; if (i == 0) break; } if (sign != 0) { int_buffer [--charPos] = sign; } return charPos; } protected static class XMLEncoder extends XUXmlWriter { protected XMLEncoder() { } protected StringBuffer encode( Map map, boolean simple ) { StringWriter writer = new StringWriter(1024); setOutputWriter( writer ); setGenericSimple( simple ); writeGeneric( map ); flushOutputStream(); return( writer.getBuffer()); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/ConcurrentHasherRequest.java0000644000175000017500000000645410373051004025640 0ustar adrianadrian/* * Created on 09-Sep-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.nio.ByteBuffer; /** * @author parg * */ public class ConcurrentHasherRequest { private static AEMonitor class_mon = new AEMonitor( "ConcHashRequest:class" ); private ConcurrentHasher concurrent_hasher; private ByteBuffer buffer; private ConcurrentHasherRequestListener listener; private int size; private byte[] result; private boolean cancelled; private boolean low_priority; private AESemaphore sem = new AESemaphore("ConcHashRequest"); protected ConcurrentHasherRequest( ConcurrentHasher _concurrent_hasher, ByteBuffer _buffer, ConcurrentHasherRequestListener _listener, boolean _low_priorty ) { concurrent_hasher = _concurrent_hasher; buffer = _buffer; listener = _listener; low_priority = _low_priorty; size = buffer.limit() - buffer.position(); } /** * synchronously get the result of the hash - null returned if it is cancelled * @return */ public byte[] getResult() { sem.reserve(); return( result ); } /** * cancel the hash request. If it is cancelled before it is completed then * a subsequent call to getResult will return null */ public void cancel() { if ( !cancelled ){ cancelled = true; sem.releaseForever(); ConcurrentHasherRequestListener listener_copy; try{ class_mon.enter(); listener_copy = listener; listener = null; }finally{ class_mon.exit(); } if ( listener_copy != null ){ listener_copy.complete( this ); } } } public boolean getCancelled() { return( cancelled ); } public int getSize() { return( size ); } public boolean isLowPriority() { return( low_priority ); } protected void run( SHA1Hasher hasher ) { if ( !cancelled ){ if ( AEDiagnostics.ALWAYS_PASS_HASH_CHECKS ){ result = new byte[0]; }else{ result = hasher.calculateHash( buffer ); } sem.releaseForever(); if ( !cancelled ){ ConcurrentHasherRequestListener listener_copy; try{ class_mon.enter(); listener_copy = listener; listener = null; }finally{ class_mon.exit(); } if ( listener_copy != null ){ listener_copy.complete( this ); } } } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/NonDaemonTask.java0000644000175000017500000000175310724170760023523 0ustar adrianadrian/* * File : NonDaemonTask.java * Created : 29-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author parg * */ public interface NonDaemonTask { public Object run() throws Throwable; public String getName(); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/HostNameToIPResolverException.java0000644000175000017500000000267511012742270026671 0ustar adrianadrian/* * Created on 07-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.net.UnknownHostException; /** * @author parg * */ public class HostNameToIPResolverException extends UnknownHostException { protected boolean is_anonymous = false; protected HostNameToIPResolverException( String msg ) { super( msg ); } protected HostNameToIPResolverException( String msg, boolean anonymous ) { super( msg ); is_anonymous = anonymous; } public boolean isAnonymous() { return( is_anonymous ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/FileUtil.java0000644000175000017500000013204211306337274022535 0ustar adrianadrian /* * Created on Oct 10, 2003 * Modified Apr 14, 2004 by Alon Rohter * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.io.*; import java.lang.reflect.Method; import java.net.SocketTimeoutException; import java.net.URI; import java.net.URL; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.plugins.platform.PlatformManagerException; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreOperation; import com.aelitis.azureus.core.AzureusCoreOperationTask; /** * File utility class. */ public class FileUtil { private static final LogIDs LOGID = LogIDs.CORE; public static final String DIR_SEP = System.getProperty("file.separator"); private static final int RESERVED_FILE_HANDLE_COUNT = 4; private static List reserved_file_handles = new ArrayList(); private static AEMonitor class_mon = new AEMonitor( "FileUtil:class" ); private static Method reflectOnUsableSpace; static { try { reflectOnUsableSpace = File.class.getMethod("getUsableSpace", (Class[])null); } catch (NoSuchMethodException e) { reflectOnUsableSpace = null; } } public static boolean isAncestorOf(File parent, File child) { parent = canonise(parent); child = canonise(child); if (parent.equals(child)) {return true;} String parent_s = parent.getPath(); String child_s = child.getPath(); if (parent_s.charAt(parent_s.length()-1) != File.separatorChar) { parent_s += File.separatorChar; } return child_s.startsWith(parent_s); } public static File canonise(File file) { try {return file.getCanonicalFile();} catch (IOException ioe) {return file;} } public static String getCanonicalFileName(String filename) { // Sometimes Windows use filename in 8.3 form and cannot // match .torrent extension. To solve this, canonical path // is used to get back the long form String canonicalFileName = filename; try { canonicalFileName = new File(filename).getCanonicalPath(); } catch (IOException ignore) {} return canonicalFileName; } public static File getUserFile(String filename) { return new File(SystemProperties.getUserPath(), filename); } public static File getApplicationFile(String filename) { String path = SystemProperties.getApplicationPath(); if(Constants.isOSX) { path = path + "/" + SystemProperties.getApplicationName() + ".app/Contents/"; } return new File(path, filename); } /** * Deletes the given dir and all files/dirs underneath */ public static boolean recursiveDelete(File f) { String defSaveDir = COConfigurationManager.getStringParameter("Default save path"); String moveToDir = COConfigurationManager.getStringParameter("Completed Files Directory", ""); try{ moveToDir = new File(moveToDir).getCanonicalPath(); }catch( Throwable e ){ } try{ defSaveDir = new File(defSaveDir).getCanonicalPath(); }catch( Throwable e ){ } try { if (f.getCanonicalPath().equals(moveToDir)) { System.out.println("FileUtil::recursiveDelete:: not allowed to delete the MoveTo dir !"); return( false ); } if (f.getCanonicalPath().equals(defSaveDir)) { System.out.println("FileUtil::recursiveDelete:: not allowed to delete the default data dir !"); return( false ); } if (f.isDirectory()) { File[] files = f.listFiles(); for (int i = 0; i < files.length; i++) { if ( !recursiveDelete(files[i])){ return( false ); } } if ( !f.delete()){ return( false ); } } else { if ( !f.delete()){ return( false ); } } } catch (Exception ignore) {/*ignore*/} return( true ); } public static boolean recursiveDeleteNoCheck(File f) { try { if (f.isDirectory()) { File[] files = f.listFiles(); for (int i = 0; i < files.length; i++) { if ( !recursiveDeleteNoCheck(files[i])){ return( false ); } } if ( !f.delete()){ return( false ); } } else { if ( !f.delete()){ return( false ); } } } catch (Exception ignore) {/*ignore*/} return( true ); } public static long getFileOrDirectorySize( File file ) { if ( file.isFile()){ return( file.length()); }else{ long res = 0; File[] files = file.listFiles(); if ( files != null ){ for (int i=0;i 0 ){ defSaveDir = new File(defSaveDir).getCanonicalPath(); } if ( moveToDir.trim().length() > 0 ){ moveToDir = new File(moveToDir).getCanonicalPath(); } if ( f.isDirectory()){ File[] files = f.listFiles(); if ( files == null ){ if (log_warnings ){ Debug.out("Empty folder delete: failed to list contents of directory " + f ); } return; } for (int i = 0; i < files.length; i++) { File x = files[i]; if ( x.isDirectory()){ recursiveEmptyDirDelete(files[i],ignore_set,log_warnings); }else{ if ( ignore_set.contains( x.getName().toLowerCase())){ if ( !x.delete()){ if ( log_warnings ){ Debug.out("Empty folder delete: failed to delete file " + x ); } } } } } if (f.getCanonicalPath().equals(moveToDir)) { if ( log_warnings ){ Debug.out("Empty folder delete: not allowed to delete the MoveTo dir !"); } return; } if (f.getCanonicalPath().equals(defSaveDir)) { if ( log_warnings ){ Debug.out("Empty folder delete: not allowed to delete the default data dir !"); } return; } File[] files_inside = f.listFiles(); if (files_inside.length == 0) { if ( !f.delete()){ if ( log_warnings ){ Debug.out("Empty folder delete: failed to delete directory " + f ); } } }else{ if ( log_warnings ){ Debug.out("Empty folder delete: " + files_inside.length + " file(s)/folder(s) still in \"" + f + "\" - first listed item is \"" + files_inside[0].getName() + "\". Not removing."); } } } } catch (Exception e) { Debug.out(e.toString()); } } public static String convertOSSpecificChars( String file_name_in, boolean is_folder ) { // this rule originally from DiskManager char[] chars = file_name_in.toCharArray(); for (int i=0;i= 0 && (chars[i] == '.' || chars[i] == ' ');chars[i] = '_',i--); } } // '/' is valid in mac file names, replace with space // so it seems are cr/lf for (int i=0;i" + file_name_out ); return( file_name_out ); } public static void writeResilientConfigFile( String file_name, Map data ) { File parent_dir = new File(SystemProperties.getUserPath()); boolean use_backups = COConfigurationManager.getBooleanParameter("Use Config File Backups" ); writeResilientFile( parent_dir, file_name, data, use_backups ); } public static void writeResilientFile( File file, Map data ) { writeResilientFile( file.getParentFile(), file.getName(), data, false ); } public static boolean writeResilientFileWithResult( File parent_dir, String file_name, Map data ) { return( writeResilientFile( parent_dir, file_name, data )); } public static void writeResilientFile( File parent_dir, String file_name, Map data, boolean use_backup ) { writeResilientFile( parent_dir, file_name, data, use_backup, true ); } public static void writeResilientFile( File parent_dir, String file_name, Map data, boolean use_backup, boolean copy_to_backup ) { if ( use_backup ){ File originator = new File( parent_dir, file_name ); if ( originator.exists()){ backupFile( originator, copy_to_backup ); } } writeResilientFile( parent_dir, file_name, data ); } // synchronise it to prevent concurrent attempts to write the same file private static boolean writeResilientFile( File parent_dir, String file_name, Map data ) { try{ class_mon.enter(); try{ getReservedFileHandles(); File temp = new File( parent_dir, file_name + ".saving"); BufferedOutputStream baos = null; try{ byte[] encoded_data = BEncoder.encode(data); FileOutputStream tempOS = new FileOutputStream( temp, false ); baos = new BufferedOutputStream( tempOS, 8192 ); baos.write( encoded_data ); baos.flush(); // thinking about removing this - just do so for CVS for the moment if ( !Constants.isCVSVersion()){ tempOS.getFD().sync(); } baos.close(); baos = null; //only use newly saved file if it got this far, i.e. it saved successfully if ( temp.length() > 1L ){ File file = new File( parent_dir, file_name ); if ( file.exists()){ if ( !file.delete()){ Debug.out( "Save of '" + file_name + "' fails - couldn't delete " + file.getAbsolutePath()); } } if ( temp.renameTo( file )){ return( true ); }else{ Debug.out( "Save of '" + file_name + "' fails - couldn't rename " + temp.getAbsolutePath() + " to " + file.getAbsolutePath()); } } return( false ); }catch( Throwable e ){ Debug.out( "Save of '" + file_name + "' fails", e ); return( false ); }finally{ try{ if (baos != null){ baos.close(); } }catch( Exception e){ Debug.out( "Save of '" + file_name + "' fails", e ); return( false ); } } }finally{ releaseReservedFileHandles(); } }finally{ class_mon.exit(); } } public static boolean resilientConfigFileExists( String name ) { File parent_dir = new File(SystemProperties.getUserPath()); boolean use_backups = COConfigurationManager.getBooleanParameter("Use Config File Backups" ); return( new File( parent_dir, name ).exists() || ( use_backups && new File( parent_dir, name + ".bak" ).exists())); } public static Map readResilientConfigFile( String file_name ) { File parent_dir = new File(SystemProperties.getUserPath()); boolean use_backups = COConfigurationManager.getBooleanParameter("Use Config File Backups" ); return( readResilientFile( parent_dir, file_name, use_backups )); } public static Map readResilientConfigFile( String file_name, boolean use_backups ) { File parent_dir = new File(SystemProperties.getUserPath()); if ( !use_backups ){ // override if a backup file exists. This is needed to cope with backups // of the main config file itself as when bootstrapping we can't get the // "use backups" if ( new File( parent_dir, file_name + ".bak").exists()){ use_backups = true; } } return( readResilientFile( parent_dir, file_name, use_backups )); } public static Map readResilientFile( File file ) { return( readResilientFile( file.getParentFile(),file.getName(),false, true)); } public static Map readResilientFile( File parent_dir, String file_name, boolean use_backup ) { return readResilientFile(parent_dir, file_name, use_backup, true); } public static Map readResilientFile( File parent_dir, String file_name, boolean use_backup, boolean intern_keys ) { File backup_file = new File( parent_dir, file_name + ".bak" ); if ( use_backup ){ use_backup = backup_file.exists(); } // if we've got a backup, don't attempt recovery here as the .bak file may be // fully OK Map res = readResilientFileSupport( parent_dir, file_name, !use_backup, intern_keys ); if ( res == null && use_backup ){ // try backup without recovery res = readResilientFileSupport( parent_dir, file_name + ".bak", false, intern_keys ); if ( res != null ){ Debug.out( "Backup file '" + backup_file + "' has been used for recovery purposes" ); // rewrite the good data, don't use backups here as we want to // leave the original backup in place for the moment writeResilientFile( parent_dir, file_name, res, false ); }else{ // neither main nor backup file ok, retry main file with recovery res = readResilientFileSupport( parent_dir, file_name, true, true ); } } if ( res == null ){ res = new HashMap(); } return( res ); } // synchronised against writes to make sure we get a consistent view private static Map readResilientFileSupport( File parent_dir, String file_name, boolean attempt_recovery, boolean intern_keys ) { try{ class_mon.enter(); try{ getReservedFileHandles(); Map res = null; try{ res = readResilientFile( file_name, parent_dir, file_name, 0, false, intern_keys ); }catch( Throwable e ){ // ignore, it'll be rethrown if we can't recover below } if ( res == null && attempt_recovery ){ res = readResilientFile( file_name, parent_dir, file_name, 0, true, intern_keys ); if ( res != null ){ Debug.out( "File '" + file_name + "' has been partially recovered, information may have been lost!" ); } } return( res ); }catch( Throwable e ){ Debug.printStackTrace( e ); return( null ); }finally{ releaseReservedFileHandles(); } }finally{ class_mon.exit(); } } private static Map readResilientFile( String original_file_name, File parent_dir, String file_name, int fail_count, boolean recovery_mode, boolean skip_key_intern) { // logging in here is only done during "non-recovery" mode to prevent subsequent recovery // attempts logging everything a second time. // recovery-mode allows the decoding process to "succeed" with a partially recovered file boolean using_backup = file_name.endsWith(".saving"); File file = new File( parent_dir, file_name ); //make sure the file exists and isn't zero-length if ( (!file.exists()) || file.length() <= 1L ){ if ( using_backup ){ if ( !recovery_mode ){ if ( fail_count == 1 ){ Debug.out( "Load of '" + original_file_name + "' fails, no usable file or backup" ); }else{ // drop this log, it doesn't really help to inform about the failure to // find a .saving file //if (Logger.isEnabled()) // Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "Load of '" // + file_name + "' fails, file not found")); } } return( null ); } if ( !recovery_mode ){ // kinda confusing log this as we get it under "normal" circumstances (loading a config // file that doesn't exist legitimately, e.g. shares or bad-ips // if (Logger.isEnabled()) // Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "Load of '" // + file_name + "' failed, " + "file not found or 0-sized.")); } return( readResilientFile( original_file_name, parent_dir, file_name + ".saving", 0, recovery_mode, true )); } BufferedInputStream bin = null; try{ int retry_limit = 5; while(true){ try{ bin = new BufferedInputStream( new FileInputStream(file), 16384 ); break; }catch( IOException e ){ if ( --retry_limit == 0 ){ throw( e ); } if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Failed to open '" + file.toString() + "', retrying", e)); Thread.sleep(500); } } BDecoder decoder = new BDecoder(); if ( recovery_mode ){ decoder.setRecoveryMode( true ); } Map res = decoder.decodeStream(bin, !skip_key_intern); if ( using_backup && !recovery_mode ){ Debug.out( "Load of '" + original_file_name + "' had to revert to backup file" ); } return( res ); }catch( Throwable e ){ Debug.printStackTrace( e ); try { if (bin != null){ bin.close(); bin = null; } } catch (Exception x) { Debug.printStackTrace( x ); } // if we're not recovering then backup the file if ( !recovery_mode ){ // Occurs when file is there but b0rked // copy it in case it actually contains useful data, so it won't be overwritten next save File bad; int bad_id = 0; while(true){ File test = new File( parent_dir, file.getName() + ".bad" + (bad_id==0?"":(""+bad_id))); if ( !test.exists()){ bad = test; break; } bad_id++; } if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Read of '" + original_file_name + "' failed, decoding error. " + "Renaming to " + bad.getName())); // copy it so its left in place for possible recovery copyFile( file, bad ); } if ( using_backup ){ if ( !recovery_mode ){ Debug.out( "Load of '" + original_file_name + "' fails, no usable file or backup" ); } return( null ); } return( readResilientFile( original_file_name, parent_dir, file_name + ".saving", 1, recovery_mode, true )); }finally{ try { if (bin != null){ bin.close(); } }catch (Exception e) { Debug.printStackTrace( e ); } } } public static void deleteResilientFile( File file ) { file.delete(); new File( file.getParentFile(), file.getName() + ".bak" ).delete(); } public static void deleteResilientConfigFile( String name ) { File parent_dir = new File(SystemProperties.getUserPath()); new File( parent_dir, name ).delete(); new File( parent_dir, name + ".bak" ).delete(); } private static void getReservedFileHandles() { try{ class_mon.enter(); while( reserved_file_handles.size() > 0 ){ // System.out.println( "releasing reserved file handle"); InputStream is = (InputStream)reserved_file_handles.remove(0); try{ is.close(); }catch( Throwable e ){ Debug.printStackTrace( e ); } } }finally{ class_mon.exit(); } } private static void releaseReservedFileHandles() { try{ class_mon.enter(); File lock_file = new File(SystemProperties.getUserPath() + ".lock"); lock_file.createNewFile(); while( reserved_file_handles.size() < RESERVED_FILE_HANDLE_COUNT ){ // System.out.println( "getting reserved file handle"); InputStream is = new FileInputStream( lock_file ); reserved_file_handles.add(is); } }catch( Throwable e ){ Debug.printStackTrace( e ); }finally{ class_mon.exit(); } } /** * Backup the given file to filename.bak, removing the old .bak file if necessary. * If _make_copy is true, the original file will copied to backup, rather than moved. * @param _filename name of file to backup * @param _make_copy copy instead of move */ public static void backupFile( final String _filename, final boolean _make_copy ) { backupFile( new File( _filename ), _make_copy ); } /** * Backup the given file to filename.bak, removing the old .bak file if necessary. * If _make_copy is true, the original file will copied to backup, rather than moved. * @param _file file to backup * @param _make_copy copy instead of move */ public static void backupFile( final File _file, final boolean _make_copy ) { if ( _file.length() > 0L ) { File bakfile = new File( _file.getAbsolutePath() + ".bak" ); if ( bakfile.exists() ) bakfile.delete(); if ( _make_copy ) { copyFile( _file, bakfile ); } else { _file.renameTo( bakfile ); } } } /** * Copy the given source file to the given destination file. * Returns file copy success or not. * @param _source_name source file name * @param _dest_name destination file name * @return true if file copy successful, false if copy failed */ public static boolean copyFile( final String _source_name, final String _dest_name ) { return copyFile( new File(_source_name), new File(_dest_name)); } /** * Copy the given source file to the given destination file. * Returns file copy success or not. * @param _source source file * @param _dest destination file * @return true if file copy successful, false if copy failed */ /* // FileChannel.transferTo() seems to fail under certain linux configurations. public static boolean copyFile( final File _source, final File _dest ) { FileChannel source = null; FileChannel dest = null; try { if( _source.length() < 1L ) { throw new IOException( _source.getAbsolutePath() + " does not exist or is 0-sized" ); } source = new FileInputStream( _source ).getChannel(); dest = new FileOutputStream( _dest ).getChannel(); source.transferTo(0, source.size(), dest); return true; } catch (Exception e) { Debug.out( e ); return false; } finally { try { if (source != null) source.close(); if (dest != null) dest.close(); } catch (Exception ignore) {} } } */ public static boolean copyFile( final File _source, final File _dest ) { try { copyFile( new FileInputStream( _source ), new FileOutputStream( _dest ) ); return true; } catch( Throwable e ) { Debug.printStackTrace( e ); return false; } } public static void copyFileWithException( final File _source, final File _dest ) throws IOException{ copyFile( new FileInputStream( _source ), new FileOutputStream( _dest ) ); } public static boolean copyFile( final File _source, final OutputStream _dest, boolean closeInputStream ) { try { copyFile( new FileInputStream( _source ), _dest, closeInputStream ); return true; } catch( Throwable e ) { Debug.printStackTrace( e ); return false; } } /** * copys the input stream to the file. always closes the input stream * @param _source * @param _dest * @throws IOException */ public static void copyFile( final InputStream _source, final File _dest ) throws IOException { FileOutputStream dest = null; boolean close_input = true; try{ dest = new FileOutputStream(_dest); // copyFile will close from now on, we don't need to close_input = false; copyFile( _source, dest, true ); }finally{ try{ if(close_input){ _source.close(); } }catch( IOException e ){ } if ( dest != null ){ dest.close(); } } } public static void copyFile( final InputStream _source, final File _dest, boolean _close_input_stream ) throws IOException { FileOutputStream dest = null; boolean close_input = _close_input_stream; try{ dest = new FileOutputStream(_dest); close_input = false; copyFile( _source, dest, close_input ); }finally{ try{ if( close_input ){ _source.close(); } }catch( IOException e ){ } if ( dest != null ){ dest.close(); } } } public static void copyFile( InputStream is, OutputStream os ) throws IOException { copyFile(is,os,true); } public static void copyFile( InputStream is, OutputStream os, boolean closeInputStream ) throws IOException { try{ if ( !(is instanceof BufferedInputStream )){ is = new BufferedInputStream(is); } byte[] buffer = new byte[65536*2]; while(true){ int len = is.read(buffer); if ( len == -1 ){ break; } os.write( buffer, 0, len ); } }finally{ try{ if(closeInputStream){ is.close(); } }catch( IOException e ){ } os.close(); } } public static void copyFileOrDirectory( File from_file_or_dir, File to_parent_dir ) throws IOException { if ( !from_file_or_dir.exists()){ throw( new IOException( "File '" + from_file_or_dir.toString() + "' doesn't exist" )); } if ( !to_parent_dir.exists()){ throw( new IOException( "File '" + to_parent_dir.toString() + "' doesn't exist" )); } if ( !to_parent_dir.isDirectory()){ throw( new IOException( "File '" + to_parent_dir.toString() + "' is not a directory" )); } if ( from_file_or_dir.isDirectory()){ File[] files = from_file_or_dir.listFiles(); File new_parent = new File( to_parent_dir, from_file_or_dir.getName()); FileUtil.mkdirs(new_parent); for (int i=0;i 0 ){ // This might be important or not. We'll make it a debug message if we had a filter, // or log it normally otherwise. if (file_filter == null) { Debug.out( "renameFile: files remain in '" + from_file.toString() + "', not deleting"); } else { /* Should we log this? How should we log this? */ return true; } }else{ if ( !from_file.delete()){ Debug.out( "renameFile: failed to delete '" + from_file.toString() + "'" ); } } return( true ); } // recover by moving files back for (int i=0;i fileDotIndex) { return ""; } return fName.substring(fileDotIndex); } public static String readFileAsString( File file, int size_limit, String charset) throws IOException { FileInputStream fis = new FileInputStream(file); try { return readInputStreamAsString(fis, size_limit, charset); } finally { fis.close(); } } public static String readFileAsString( File file, int size_limit ) throws IOException { FileInputStream fis = new FileInputStream(file); try { return readInputStreamAsString(fis, size_limit); } finally { fis.close(); } } public static String readInputStreamAsString( InputStream is, int size_limit ) throws IOException { return readInputStreamAsString(is, size_limit, "ISO-8859-1"); } public static String readInputStreamAsString( InputStream is, int size_limit, String charSet) throws IOException { StringBuffer result = new StringBuffer(1024); byte[] buffer = new byte[1024]; while (true) { int len = is.read(buffer); if (len <= 0) { break; } result.append(new String(buffer, 0, len, charSet)); if (size_limit >= 0 && result.length() > size_limit) { result.setLength(size_limit); break; } } return (result.toString()); } public static String readInputStreamAsStringWithTruncation( InputStream is, int size_limit ) throws IOException { StringBuffer result = new StringBuffer(1024); byte[] buffer = new byte[1024]; try{ while (true) { int len = is.read(buffer); if (len <= 0) { break; } result.append(new String(buffer, 0, len, "ISO-8859-1")); if (size_limit >= 0 && result.length() > size_limit) { result.setLength(size_limit); break; } } }catch( SocketTimeoutException e ){ } return (result.toString()); } public static String readFileEndAsString( File file, int size_limit ) throws IOException { FileInputStream fis = new FileInputStream( file ); try{ if (file.length() > size_limit) { fis.skip(file.length() - size_limit); } StringBuffer result = new StringBuffer(1024); byte[] buffer = new byte[1024]; while( true ){ int len = fis.read( buffer ); if ( len <= 0 ){ break; } result.append( new String( buffer, 0, len, "ISO-8859-1" )); if ( result.length() > size_limit ){ result.setLength( size_limit ); break; } } return( result.toString()); }finally{ fis.close(); } } public static byte[] readInputStreamAsByteArray( InputStream is ) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024); byte[] buffer = new byte[32*1024]; while( true ){ int len = is.read( buffer ); if ( len <= 0 ){ break; } baos.write( buffer, 0, len ); } return( baos.toByteArray()); } public static byte[] readFileAsByteArray( File file ) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream((int)file.length()); byte[] buffer = new byte[32*1024]; InputStream is = new FileInputStream( file ); try{ while( true ){ int len = is.read( buffer ); if ( len <= 0 ){ break; } baos.write( buffer, 0, len ); } return( baos.toByteArray()); }finally{ is.close(); } } public final static boolean getUsableSpaceSupported() { return reflectOnUsableSpace != null; } public final static long getUsableSpace(File f) { try { return ((Long)reflectOnUsableSpace.invoke(f, null)).longValue(); } catch (Exception e) { return -1; } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/DebugLight.java0000644000175000017500000000260010370156470023027 0ustar adrianadrian/* * Created on 01-Feb-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; public class DebugLight { /** * Used in environments where full debug may not be available * @param e */ public static void printStackTrace( Throwable e ) { try{ Debug.printStackTrace( e ); }catch( Throwable f ){ e.printStackTrace(); } } public static void out( String str ) { try{ Debug.out( str ); }catch( Throwable f ){ System.out.println( str ); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/RealTimeInfo.java0000644000175000017500000000412010714766226023336 0ustar adrianadrian/* * Created on Nov 8, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; public class RealTimeInfo { private static int realtime_task_count; private static long progressive_bytes_per_sec; public static synchronized void addRealTimeTask() { realtime_task_count++; //System.out.println( "RealTimeInfo: tasks=" + realtime_task_count ); } public static synchronized void removeRealTimeTask() { realtime_task_count--; //System.out.println( "RealTimeInfo: tasks=" + realtime_task_count ); } public static boolean isRealTimeTaskActive() { return( realtime_task_count > 0 ); } public static synchronized void setProgressiveActive( long bytes_per_sec ) { progressive_bytes_per_sec = bytes_per_sec; //System.out.println( "RealTimeInfo: progressive active, " + bytes_per_sec ); } public static synchronized void setProgressiveInactive() { progressive_bytes_per_sec = 0; //System.out.println( "RealTimeInfo: progressive inactive" ); } /** * Gives the currently active progressive download's speed if there is one, 0 otherwise * @return */ public static long getProgressiveActiveBytesPerSec() { return( progressive_bytes_per_sec ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/ByteFormatter.java0000644000175000017500000001332511245660470023610 0ustar adrianadrian/* * Created on 2 juil. 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author Olivier * */ import java.nio.ByteBuffer; public class ByteFormatter { final static char[] HEXDIGITS = { '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' }; public static String nicePrint( String str ) { return( nicePrint(str.getBytes(),true)); } public static String nicePrint(byte[] data) { return( nicePrint( data, false )); } public static String nicePrint(byte[] data, int max){ return( nicePrint( data, false, max )); } public static String nicePrint( ByteBuffer data ) { byte[] raw = new byte[ data.limit() ]; for( int i=0; i < raw.length; i++ ) { raw[i] = data.get( i ); } return nicePrint( raw ); } public static String nicePrint( byte[] data, boolean tight) { return( nicePrint( data, tight, 1024 )); } public static String nicePrint( byte[] data, boolean tight, int max_length ) { if (data == null) { return ""; } int dataLength = data.length; if (dataLength > max_length) { dataLength = max_length; } int size = dataLength * 2; if (!tight) { size += (dataLength - 1) / 4; } char[] out = new char[size]; try { int pos = 0; for (int i = 0; i < dataLength; i++) { if ((!tight) && (i % 4 == 0) && i > 0) { out[pos++] = ' '; } out[pos++] = HEXDIGITS[(byte) ((data[i] >> 4) & 0xF)]; out[pos++] = HEXDIGITS[(byte) (data[i] & 0xF)]; } } catch (Exception e) { Debug.printStackTrace(e); } try { return new String(out) + (data.length > max_length?"...":""); } catch (Exception e) { Debug.printStackTrace(e); } return ""; } public static String nicePrint(byte b) { byte b1 = (byte) ((b >> 4) & 0x0000000F); byte b2 = (byte) (b & 0x0000000F); return nicePrint2(b1) + nicePrint2(b2); } public static String nicePrint2(byte b) { String out = ""; switch (b) { case 0 : out = "0"; break; case 1 : out = "1"; break; case 2 : out = "2"; break; case 3 : out = "3"; break; case 4 : out = "4"; break; case 5 : out = "5"; break; case 6 : out = "6"; break; case 7 : out = "7"; break; case 8 : out = "8"; break; case 9 : out = "9"; break; case 10 : out = "A"; break; case 11 : out = "B"; break; case 12 : out = "C"; break; case 13 : out = "D"; break; case 14 : out = "E"; break; case 15 : out = "F"; break; } return out; } /** * Note this has a truncation limit at 1024 chars.... * @param bytes * @return */ public static String encodeString( byte[] bytes ) { return( nicePrint( bytes, true )); } public static String encodeStringFully( byte[] bytes ) { return( nicePrint( bytes, true, Integer.MAX_VALUE )); } public static String encodeString( byte[] bytes, int offset, int len ) { byte[] x = new byte[len]; System.arraycopy( bytes, offset, x, 0, len ); return( nicePrint( x, true )); } public static byte[] decodeString( String str ) { char[] chars = str.toCharArray(); int chars_length = chars.length - chars.length%2; byte[] res = new byte[chars_length/2]; for (int i=0;i " + to_host ); Map new_map; if ( host_map == null ){ new_map = new HashMap(); }else{ new_map = new HashMap( host_map ); } new_map.put( from_host, to_host ); host_map = new_map; } public static InetSocketAddress adjustTCPAddress( InetSocketAddress address, boolean ext_to_lan ) { return( adjustAddress( address, ext_to_lan, AZInstanceManager.AT_TCP )); } public static InetSocketAddress adjustUDPAddress( InetSocketAddress address, boolean ext_to_lan ) { return( adjustAddress( address, ext_to_lan, AZInstanceManager.AT_UDP )); } public static InetSocketAddress adjustDHTAddress( InetSocketAddress address, boolean ext_to_lan ) { return( adjustAddress( address, ext_to_lan, AZInstanceManager.AT_UDP_NON_DATA )); } private static InetSocketAddress adjustAddress( InetSocketAddress address, boolean ext_to_lan, int port_type ) { if ( instance_manager == null ){ try{ instance_manager = AzureusCoreFactory.getSingleton().getInstanceManager(); }catch( Throwable e ){ Debug.printStackTrace(e); } } if ( instance_manager == null || !instance_manager.isInitialized()){ return( address ); } InetSocketAddress adjusted_address; if ( ext_to_lan ){ adjusted_address = instance_manager.getLANAddress( address, port_type ); }else{ adjusted_address = instance_manager.getExternalAddress( address, port_type ); } if ( adjusted_address == null ){ adjusted_address = address; }else{ // System.out.println( "adj: " + address + "/" + ext_to_lan + " -> " + adjusted_address ); } return( adjusted_address ); } public static List getLANAddresses( String address ) { List result = new ArrayList(); result.add( address ); try{ InetAddress ad = InetAddress.getByName( address ); if ( isLANLocalAddress( address ) != LAN_LOCAL_NO ){ if ( instance_manager == null ){ try{ instance_manager = AzureusCoreFactory.getSingleton().getInstanceManager(); }catch( Throwable e ){ Debug.printStackTrace(e); } } if ( instance_manager == null || !instance_manager.isInitialized()){ return( result ); } AZInstance[] instances = instance_manager.getOtherInstances(); for (int i=0;i 6to4 > teredo * * @return null if no proper v6 address is found, best one otherwise */ public static InetAddress pickBestGlobalV6Address(List addrs) { InetAddress bestPick = null; int currentRanking = 0; for(InetAddress addr : addrs) { if(!isGlobalAddressV6(addr)) continue; int ranking = 3; if(isTeredo(addr)) ranking = 1; else if(is6to4(addr)) ranking = 2; if(ranking > currentRanking) { bestPick = addr; currentRanking = ranking; } } return bestPick; } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/RandomUtils.java0000644000175000017500000001130511147643640023257 0ustar adrianadrian/* * Created on Dec 30, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.security.SecureRandom; import java.util.Random; import org.gudy.azureus2.core3.config.COConfigurationManager; /** * @author MjrTom * 2006/Jan/02: added various methods, including some java.util.Random method aliases */ public class RandomUtils { public static final Random RANDOM = new Random( System.currentTimeMillis() ); public static final SecureRandom SECURE_RANDOM = new SecureRandom(); /** * Generate a random array of bytes. * @param num_to_generate number of bytes to generate * @return random byte array */ public static byte[] generateRandomBytes( int num_to_generate ) { byte[] id = new byte[ num_to_generate ]; RANDOM.nextBytes( id ); return id; } /** * Generate a random string of charactors. * @param num_to_generate number of chars to generate * @return random char string */ public static String generateRandomAlphanumerics( int num_to_generate ) { String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; StringBuffer buff = new StringBuffer( num_to_generate ); for( int i=0; i < num_to_generate; i++ ) { int pos = (int)( RANDOM.nextDouble() * alphabet.length() ); buff.append( alphabet.charAt( pos ) ); } return buff.toString(); } public static final int LISTEN_PORT_MIN = 10000; public static final int LISTEN_PORT_MAX = 65535; /** * Generate a random port number for binding a network IP listening socket to. * NOTE: Will return a valid non-privileged port number >= LISTEN_PORT_MIN and <= LISTEN_PORT_MAX. * @return random port number */ public static int generateRandomNetworkListenPort() { // DON'T use NetworkManager methods to get the ports here else startup can hang int existing_tcp = COConfigurationManager.getIntParameter( "TCP.Listen.Port" ); int existing_udp = COConfigurationManager.getIntParameter( "UDP.Listen.Port" ); int existing_udp2 = COConfigurationManager.getIntParameter( "UDP.NonData.Listen.Port" ); while( true ){ int min = LISTEN_PORT_MIN; int port = min + RANDOM.nextInt( LISTEN_PORT_MAX + 1 - min ); // skip magnet ports if ( port >= 45100 && port <= 45110 ){ continue; } if ( port != existing_tcp && port != existing_udp && port != existing_udp2){ return port; } } } /** * Generates a random +1 or -1 * @return +1 or -1 */ public static int generateRandomPlusMinus1() { return RANDOM.nextBoolean() ? -1:1; } public static float nextFloat() { return RANDOM.nextFloat(); } public static void nextBytes(byte[] bytes) { RANDOM.nextBytes(bytes); } public static void nextSecureBytes( byte[] bytes ) { SECURE_RANDOM.nextBytes( bytes ); } public static byte[] nextSecureHash() { byte[] hash = new byte[20]; SECURE_RANDOM.nextBytes( hash ); return( hash ); } public static byte[] nextHash() { byte[] hash = new byte[20]; RANDOM.nextBytes( hash ); return( hash ); } public static int nextInt(int n) { return RANDOM.nextInt(n); } public static byte nextByte() { return (byte)RANDOM.nextInt(); } public static int nextInt() { return RANDOM.nextInt(); } public static long nextLong() { return RANDOM.nextLong(); } /** * @return random int between 0 and max-1. e.g. param of 10 returns 0->9 */ public static int generateRandomIntUpto(int max) { return nextInt(max); } /** * @return random int between min and max, e.g params of [5,7] returns 5,6 or 7 */ public static int generateRandomIntBetween(int min, int max) { return min +generateRandomIntUpto(max + 1 - min); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/TrackersUtil.java0000644000175000017500000001257710672622612023444 0ustar adrianadrian/* * File : TrackersUtil.java * Created : 7 nov. 2003 12:09:56 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * @author Olivier * */ public class TrackersUtil { private List trackers; private Map multiTrackers; private Map webseeds; private static TrackersUtil instance; private static AEMonitor class_mon = new AEMonitor( "TrackersUtil:class" ); private TrackersUtil() { trackers = new ArrayList(); multiTrackers = new HashMap(); webseeds = new HashMap(); loadList(); } public static TrackersUtil getInstance() { try{ class_mon.enter(); if(instance == null) instance = new TrackersUtil(); return instance; }finally{ class_mon.exit(); } } public List getTrackersList() { if(trackers != null) return new ArrayList(trackers); else return null; } public void addTracker(String trackerAnnounceUrl) { if(trackers.contains(trackerAnnounceUrl)) return; trackers.add(0,trackerAnnounceUrl); saveList(); } public void addMultiTracker(String configName, List groups) { multiTrackers.put(configName,groups); saveList(); } public void removeMultiTracker(String configName) { multiTrackers.remove(configName); saveList(); } public Map getMultiTrackers() { return new HashMap(multiTrackers); } public void addWebSeed(String configName, Map ws) { webseeds.put(configName,ws); saveList(); } public void removeWebSeed(String configName) { webseeds.remove(configName); saveList(); } public Map getWebSeeds() { return new HashMap(webseeds); } public void clearAllTrackers(boolean save) { trackers = new ArrayList(); multiTrackers = new HashMap(); webseeds = new HashMap(); if (save) {saveList();} } private void loadList() { File fTrackers = FileUtil.getUserFile("trackers.config"); if(fTrackers.exists() && fTrackers.isFile()) { FileInputStream fin = null; BufferedInputStream bin = null; try { fin = new FileInputStream(fTrackers); bin = new BufferedInputStream(fin, 8192); Map map = BDecoder.decode(bin); List list = (List) map.get("trackers"); if(list != null) { Iterator iter = list.iterator(); while(iter.hasNext()) { String tracker = new String((byte[])iter.next()); trackers.add(tracker); } } Map mapMT = (Map) map.get("multi-trackers"); if(mapMT != null) { Iterator iter = mapMT.keySet().iterator(); while(iter.hasNext()) { String configName = (String) iter.next(); List groups = (List) mapMT.get(configName); List resGroups = new ArrayList(groups.size()); Iterator iterGroups = groups.iterator(); while(iterGroups.hasNext()) { List theseTrackers = (List) iterGroups.next(); List resTrackers = new ArrayList(theseTrackers.size()); Iterator iterTrackers = theseTrackers.iterator(); while(iterTrackers.hasNext()) { String tracker = new String((byte[]) iterTrackers.next()); resTrackers.add(tracker); } resGroups.add(resTrackers); } this.multiTrackers.put(configName,resGroups); } } webseeds = (Map)map.get( "webseeds" ); if ( webseeds == null ){ webseeds = new HashMap(); }else{ BDecoder.decodeStrings( webseeds ); } } catch(Exception e) { Debug.printStackTrace( e ); }finally{ if ( bin != null ){ try{ bin.close(); }catch( Throwable e ){ } } if ( fin != null ){ try{ fin.close(); }catch( Throwable e ){ } } } } } private void saveList() { Map map = new HashMap(); map.put("trackers",trackers); map.put("multi-trackers",multiTrackers); map.put("webseeds",webseeds ); FileOutputStream fos = null; try { // Open the file File fTrackers = FileUtil.getUserFile("trackers.config"); fos = new FileOutputStream(fTrackers); fos.write(BEncoder.encode(map)); fos.close(); } catch (Exception e) { Debug.printStackTrace( e ); } finally{ if ( fos != null ){ try{ fos.close(); }catch( Throwable e ){ } } } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/Base32.java0000644000175000017500000001066611000056616022033 0ustar adrianadrian/* * Created on 04-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author parg * Derived from com.bitzi.util.Base32.java * (PD) 2001 The Bitzi Corporation * Please see http://bitzi.com/publicdomain for more info. * */ public class Base32 { private static final String base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; private static final int[] base32Lookup = { 0xFF,0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, // '0', '1', '2', '3', '4', '5', '6', '7' 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // '8', '9', ':', ';', '<', '=', '>', '?' 0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06, // '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G' 0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E, // 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O' 0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16, // 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W' 0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF, // 'X', 'Y', 'Z', '[', '\', ']', '^', '_' 0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06, // '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g' 0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E, // 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o' 0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16, // 'p', 'q', 'r', 's', 't', 'u', 'v', 'w' 0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF // 'x', 'y', 'z', '{', '|', '}', '~', 'DEL' }; public static String encode( final byte[] bytes ) { int i =0, index = 0, digit = 0; int currByte, nextByte; StringBuffer base32 = new StringBuffer((bytes.length+7)*8/5); while(i < bytes.length) { currByte = (bytes[i]>=0) ? bytes[i] : (bytes[i]+256); // unsign /* Is the current digit going to span a byte boundary? */ if (index > 3) { if ((i+1)=0) ? bytes[i+1] : (bytes[i+1]+256); else nextByte = 0; digit = currByte & (0xFF >> index); index = (index + 5) % 8; digit <<= index; digit |= nextByte >> (8 - index); i++; } else { digit = (currByte >> (8 - (index + 5))) & 0x1F; index = (index + 5) % 8; if (index == 0) i++; } base32.append(base32Chars.charAt(digit)); } return base32.toString(); } public static byte[] decode( final String base32 ) { int i, index, lookup, offset, digit; byte[] bytes = new byte[base32.length()*5/8]; if ( bytes.length == 0 ){ return( bytes ); } for(i = 0, index = 0, offset = 0; i < base32.length(); i++) { lookup = base32.charAt(i) - '0'; /* Skip chars outside the lookup table */ if ( lookup < 0 || lookup >= base32Lookup.length) continue; digit = base32Lookup[lookup]; /* If this digit is not in the table, ignore it */ if (digit == 0xFF) continue; if (index <= 3) { index = (index + 5) % 8; if (index == 0) { bytes[offset] |= digit; offset++; if(offset>=bytes.length) break; } else bytes[offset] |= digit << (8 - index); } else { index = (index + 5) % 8; bytes[offset] |= (digit >>> index); offset++; if(offset>=bytes.length) break; bytes[offset] |= digit << (8 - index); } } return bytes; } }azureus-4.3.0.6/org/gudy/azureus2/core3/util/AEThread.java0000644000175000017500000000451611067033766022444 0ustar adrianadrian/* * Created on 28-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.util.WeakHashMap; /** * @author parg * @deprecated - use AEThread2 */ public abstract class AEThread extends Thread { private static WeakHashMap our_thread_map = new WeakHashMap(); public AEThread( String name ) { super(name); setDaemon( false ); } public AEThread( String name, boolean daemon ) { super(name); setDaemon( daemon ); } public void run() { if ( AEThread2.TRACE_TIMES ){ System.out.println( TimeFormatter.milliStamp() + ": AEThread:start: " + this ); } try{ /* if ( !isDaemon()){ System.out.println( "non-daemon thread:" + this ); } */ runSupport(); }catch( Throwable e ){ DebugLight.printStackTrace(e); } // System.out.println( "Stop: " + this ); } public abstract void runSupport(); public static boolean isOurThread( Thread thread ) { if ( thread instanceof AEThread ){ return( true ); } synchronized( our_thread_map ){ return( our_thread_map.get( thread ) != null ); } } public static void setOurThread() { setOurThread( Thread.currentThread()); } public static void setOurThread( Thread thread ) { if ( thread instanceof AEThread || thread instanceof AEThread2.threadWrapper ){ return; } synchronized( our_thread_map ){ our_thread_map.put( thread, "" ); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/SimpleTimer.java0000644000175000017500000000461610766605566023272 0ustar adrianadrian/* * Created on 12-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author parg * */ public class SimpleTimer { /** * A simple timer class for use by application components that want to schedule * low-overhead events (i.e. when fired the event shouldn't take significant processing * time as there is a limited thread pool to service it */ protected static final Timer timer; static{ timer = new Timer("Simple Timer",32); timer.setIndestructable(); timer.setWarnWhenFull(); // timer.setLogCPU(); // timer.setLogging(true); } public static TimerEvent addEvent( String name, long when, TimerEventPerformer performer ) { TimerEvent res = timer.addEvent( name, when, performer ); return( res ); } public static TimerEvent addEvent( String name, long when, boolean absolute, TimerEventPerformer performer ) { TimerEvent res = timer.addEvent( name, when, absolute, performer ); return( res ); } public static TimerEventPeriodic addPeriodicEvent( String name, long frequency, TimerEventPerformer performer ) { TimerEventPeriodic res = timer.addPeriodicEvent( name, frequency, performer ); return( res ); } public static TimerEventPeriodic addPeriodicEvent( String name, long frequency, boolean absolute, TimerEventPerformer performer ) { TimerEventPeriodic res = timer.addPeriodicEvent( name, frequency, absolute, performer ); return( res ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AEVerifierException.java0000644000175000017500000000250211012742276024651 0ustar adrianadrian/* * Created on 13 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; public class AEVerifierException extends Exception { public static final int FT_SIGNATURE_MISSING = 1; public static final int FT_SIGNATURE_BAD = 2; private int failure_type; public AEVerifierException( int type, String str ) { super( str ); failure_type = type; } public int getFailureType() { return( failure_type ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AEDiagnosticsLogger.java0000644000175000017500000002036111276111446024632 0ustar adrianadrian/* * Created on 22-Sep-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileWriter; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.LinkedList; import java.util.TimeZone; /** * @author parg * */ public class AEDiagnosticsLogger { private static final int MAX_PENDING = 8*1024; private String name; private int max_size; private File debug_dir; private boolean timestamp_enable = true; private boolean force; private boolean first_file = true; private boolean first_write = true; private PrintWriter current_writer; private LinkedList pending; private int pending_size; private boolean direct_writes; private boolean close_pws = false; private static final String start_date; private static final long timezone_offset; static{ long now = System.currentTimeMillis(); start_date = new SimpleDateFormat().format( new Date(now)); timezone_offset = TimeZone.getDefault().getOffset(now); } protected AEDiagnosticsLogger( File _debug_dir, String _name, int _max_size, boolean _direct_writes ) { debug_dir = _debug_dir; name = _name; max_size = _max_size; direct_writes = _direct_writes; try{ File f1 = getLogFile(); first_file = false; File f2 = getLogFile(); first_file = true; // if we were writing to the second file, carry on from there if ( f1.exists() && f2.exists()){ if ( f1.lastModified() < f2.lastModified()){ first_file = false; } } }catch( Throwable ignore ){ } } protected void setForced() { force = true; } protected String getName() { return( name ); } public void setMaxFileSize( int _max_size ) { max_size = _max_size; } public void enableTimeStamp( boolean enable ) { timestamp_enable = enable; } public void log( Throwable e ) { try{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintWriter pw = new PrintWriter( new OutputStreamWriter( baos )); e.printStackTrace( pw ); pw.close(); log( baos.toString()); }catch( Throwable ignore ){ } } public void logAndOut( String str ) { logAndOut( str, false ); } public void logAndOut( String str, boolean stderr ) { if ( stderr ){ System.err.println( str ); }else{ System.out.println( str ); } log( str ); } public void logAndOut( Throwable e ) { e.printStackTrace(); log( e ); } /* public static String getTimestamp() { Calendar now = GregorianCalendar.getInstance(); String timeStamp = "[" + format(now.get(Calendar.DAY_OF_MONTH))+format(now.get(Calendar.MONTH)+1) + " " + format(now.get(Calendar.HOUR_OF_DAY))+ ":" + format(now.get(Calendar.MINUTE)) + ":" + format(now.get(Calendar.SECOND)) + "] "; return( timeStamp ); } */ public static String getTimestamp() { long time = SystemTime.getCurrentTime(); time += timezone_offset; // we'll live with this changing... time /= 1000; int secs = (int)time % 60; int mins = (int)(time / 60) % 60; int hours = (int)(time /3600) % 24; char[] chars = new char[11]; chars[0] = '['; format( hours, chars, 1 ); chars[3] = ':'; format( mins, chars, 4 ); chars[6] = ':'; format( secs, chars, 7 ); chars[9] = ']'; chars[10] = ' '; return( new String( chars )); } private static final void format( int num, char[] chars, int pos ) { if ( num < 10 ){ chars[pos] = '0'; chars[pos+1] =(char)( '0' + num ); }else{ chars[pos] = (char)('0' + (num/10)); chars[pos+1] = (char)('0' + (num%10)); } } public void log( String _str ) { if ( !AEDiagnostics.loggers_enabled ){ if ( !force ){ return; } } StringBuilder str = new StringBuilder( _str.length() + 20 ); final String timeStamp; if ( timestamp_enable ){ timeStamp = getTimestamp(); }else{ timeStamp = null; } synchronized( this ){ if ( first_write ){ first_write = false; Calendar now = GregorianCalendar.getInstance(); str.append( "\r\n[" ); str.append( start_date ); str.append( "] Log File Opened for " ); str.append( Constants.APP_NAME ); str.append( " " ); str.append( Constants.AZUREUS_VERSION ); str.append( "\r\n" ); } if ( timeStamp != null ){ str.append( timeStamp ); } str.append( _str ); if ( !direct_writes ){ if ( pending == null ){ pending = new LinkedList(); } pending.add( str ); pending_size += str.length(); if ( pending_size > MAX_PENDING ){ writePending(); } return; } write( str ); } } private void write( StringBuilder str ) { try{ File log_file = getLogFile(); /** * log_file.length will return 0 if the file doesn't exist, so we don't need * to explicitly check for its existence. */ if ( log_file.length() >= max_size ){ if ( current_writer != null ){ current_writer.close(); current_writer = null; } first_file = !first_file; log_file = getLogFile(); // If the file doesn't exist, this will just return false. log_file.delete(); } if ( current_writer == null ){ current_writer = new PrintWriter(new FileWriter( log_file, true )); } current_writer.println( str ); current_writer.flush(); }catch( Throwable e ){ }finally{ if ( current_writer != null && close_pws ){ current_writer.close(); current_writer = null; } } } protected void writePending() { synchronized( this ){ if ( pending == null ){ return; } // System.out.println( getName() + ": flushing " + pending_size ); try{ File log_file = getLogFile(); /** * log_file.length will return 0 if the file doesn't exist, so we don't need * to explicitly check for its existence. */ if ( log_file.length() >= max_size ){ if ( current_writer != null ){ current_writer.close(); current_writer = null; } first_file = !first_file; log_file = getLogFile(); // If the file doesn't exist, this will just return false. log_file.delete(); } if ( current_writer == null ){ current_writer = new PrintWriter(new FileWriter( log_file, true )); } for ( StringBuilder str: pending ){ current_writer.println( str ); } current_writer.flush(); }catch( Throwable e ){ }finally{ direct_writes = true; pending = null; if ( current_writer != null && close_pws ){ current_writer.close(); current_writer = null; } } } } private File getLogFile() { return( new File( debug_dir, getName() + "_" + (first_file?"1":"2") + ".log" )); } private static String format( int n ) { if (n < 10){ return( "0" + n ); } return( String.valueOf(n)); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AENetworkClassifierListener.java0000644000175000017500000000221610373051004026354 0ustar adrianadrian/* * Created on 14-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author parg * */ public interface AENetworkClassifierListener { public String[] selectNetworks( String description, String[] tracker_networks ); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/ListenerManagerDispatcherWithException.java0000644000175000017500000000247110001566260030612 0ustar adrianadrian/* * File : ListenerManagerDispatcherWithException.java * Created : 15-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author parg * */ public abstract class ListenerManagerDispatcherWithException extends ListenerManagerDispatcher { public void dispatch( Object _listener, int type, Object value ) { throw( new RuntimeException( "ListenerManagerDispatcherWithException: you must invoke dispatchWithException")); } public abstract void dispatchWithException( Object _listener, int type, Object value ) throws Throwable; } azureus-4.3.0.6/org/gudy/azureus2/core3/util/ED2KHasher.java0000644000175000017500000000645110457472712022647 0ustar adrianadrian/* * File : ED2KHasher.java * Created : 16-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author parg * */ public class ED2KHasher { public static final int BLOCK_SIZE = 0x947000; protected MD4Hasher current_hasher = new MD4Hasher(); protected MD4Hasher block_hasher; protected int current_bytes; public ED2KHasher() { } public void update( byte[] data ) { update( data, 0, data.length ); } public void update( byte[] data, int pos, int len ) { int rem = len; while( rem > 0 ){ int space = BLOCK_SIZE - current_bytes; if ( rem <= space ){ current_hasher.update( data, pos, rem ); current_bytes += rem; break; }else{ if ( block_hasher == null ){ block_hasher = new MD4Hasher(); } if ( space == 0 ){ block_hasher.update( current_hasher.getDigest()); current_hasher = new MD4Hasher(); current_bytes = 0; }else{ current_hasher.update( data, pos, space ); pos += space; rem -= space; current_bytes += space; } } } } public byte[] getDigest() { // data that is a multiple of BLOCK_SIZE needs to have a null MD4 hash appended if ( current_bytes == BLOCK_SIZE ){ if ( block_hasher == null ){ block_hasher = new MD4Hasher(); } block_hasher.update( current_hasher.getDigest()); current_hasher = new MD4Hasher(); } if ( block_hasher == null ){ return( current_hasher.getDigest()); }else{ if ( current_bytes > 0 ){ block_hasher.update( current_hasher.getDigest()); } return( block_hasher.getDigest()); } } /* public static void main( String[] args ) { SESecurityManager.initialise(); ED2KHasher hasher = new ED2KHasher(); try{ FileInputStream fis = new FileInputStream( "C:\\temp\\dat.txt"); byte[] buffer = new byte[1024*1024]; while( true ){ int len = fis.read( buffer ); if ( len <= 0 ){ break; } hasher.update( buffer, 0, len ); } }catch( Throwable e ){ e.printStackTrace(); } byte[] bah = new byte[BLOCK_SIZE]; Arrays.fill( bah, (byte)'a' ); hasher.update( bah ); try{ FileOutputStream fos = new FileOutputStream( "C:\\temp\\data.txt" ); fos.write( bah ); fos.close(); }catch( Throwable e ){ e.printStackTrace(); } System.out.println( "hash=" + ByteFormatter.encodeString( hasher.getDigest())); } */ } azureus-4.3.0.6/org/gudy/azureus2/core3/util/MD5.java0000644000175000017500000002646410373051004021402 0ustar adrianadrian/* * Created on 16 avr. 2004 * Created by Olivier Chalouhi * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved */ package org.gudy.azureus2.core3.util; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.security.MessageDigest; /** * @author Olivier Chalouhi * */ public class MD5 { private int h0,h1,h2,h3; private int length; private ByteBuffer finalBuffer; public MD5() { finalBuffer = ByteBuffer.allocate(64); finalBuffer.position(0); finalBuffer.limit(64); reset(); } public void transform(ByteBuffer M) { int x0 , x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 , x9 , x10, x11, x12, x13, x14, x15; int a,b,c,d; /* * Crazy byte order for MD5 ... took me hours to find out * where the problem was .... words (32 bits) must be read starting * with the least significant byte ! */ ByteOrder order = M.order(); M.order(ByteOrder.LITTLE_ENDIAN); x0 = M.getInt(); x1 = M.getInt(); x2 = M.getInt(); x3 = M.getInt(); x4 = M.getInt(); x5 = M.getInt(); x6 = M.getInt(); x7 = M.getInt(); x8 = M.getInt(); x9 = M.getInt(); x10 = M.getInt(); x11 = M.getInt(); x12 = M.getInt(); x13 = M.getInt(); x14 = M.getInt(); x15 = M.getInt(); M.order(order); a = h0 ; b = h1 ; c = h2 ; d = h3 ; a += ((b & c) | ( ~b & d)) + x0 + 0xd76aa478; a = b + ((a << 7) | (a >>> 25)); d += ((a & b) | ( ~a & c)) + x1 + 0xe8c7b756; d = a + ((d << 12) | (d >>> 20)); c += ((d & a) | ( ~d & b)) + x2 + 0x242070db; c = d + ((c << 17) | (c >>> 15)); b += ((c & d) | ( ~c & a)) + x3 + 0xc1bdceee; b = c + ((b << 22) | (b >>> 10)); a += ((b & c) | ( ~b & d)) + x4 + 0xf57c0faf; a = b + ((a << 7) | (a >>> 25)); d += ((a & b) | ( ~a & c)) + x5 + 0x4787c62a; d = a + ((d << 12) | (d >>> 20)); c += ((d & a) | ( ~d & b)) + x6 + 0xa8304613; c = d + ((c << 17) | (c >>> 15)); b += ((c & d) | ( ~c & a)) + x7 + 0xfd469501; b = c + ((b << 22) | (b >>> 10)); a += ((b & c) | ( ~b & d)) + x8 + 0x698098d8; a = b + ((a << 7) | (a >>> 25)); d += ((a & b) | ( ~a & c)) + x9 + 0x8b44f7af; d = a + ((d << 12) | (d >>> 20)); c += ((d & a) | ( ~d & b)) + x10 + 0xffff5bb1; c = d + ((c << 17) | (c >>> 15)); b += ((c & d) | ( ~c & a)) + x11 + 0x895cd7be; b = c + ((b << 22) | (b >>> 10)); a += ((b & c) | ( ~b & d)) + x12 + 0x6b901122; a = b + ((a << 7) | (a >>> 25)); d += ((a & b) | ( ~a & c)) + x13 + 0xfd987193; d = a + ((d << 12) | (d >>> 20)); c += ((d & a) | ( ~d & b)) + x14 + 0xa679438e; c = d + ((c << 17) | (c >>> 15)); b += ((c & d) | ( ~c & a)) + x15 + 0x49b40821; b = c + ((b << 22) | (b >>> 10)); a += ((b & d) | (c & ~d)) + x1 + 0xf61e2562; a = b + ((a << 5) | (a >>> 27)); d += ((a & c) | (b & ~c)) + x6 + 0xc040b340; d = a + ((d << 9) | (d >>> 23)); c += ((d & b) | (a & ~b)) + x11 + 0x265e5a51; c = d + ((c << 14) | (c >>> 18)); b += ((c & a) | (d & ~a)) + x0 + 0xe9b6c7aa; b = c + ((b << 20) | (b >>> 12)); a += ((b & d) | (c & ~d)) + x5 + 0xd62f105d; a = b + ((a << 5) | (a >>> 27)); d += ((a & c) | (b & ~c)) + x10 + 0x2441453; d = a + ((d << 9) | (d >>> 23)); c += ((d & b) | (a & ~b)) + x15 + 0xd8a1e681; c = d + ((c << 14) | (c >>> 18)); b += ((c & a) | (d & ~a)) + x4 + 0xe7d3fbc8; b = c + ((b << 20) | (b >>> 12)); a += ((b & d) | (c & ~d)) + x9 + 0x21e1cde6; a = b + ((a << 5) | (a >>> 27)); d += ((a & c) | (b & ~c)) + x14 + 0xc33707d6; d = a + ((d << 9) | (d >>> 23)); c += ((d & b) | (a & ~b)) + x3 + 0xf4d50d87; c = d + ((c << 14) | (c >>> 18)); b += ((c & a) | (d & ~a)) + x8 + 0x455a14ed; b = c + ((b << 20) | (b >>> 12)); a += ((b & d) | (c & ~d)) + x13 + 0xa9e3e905; a = b + ((a << 5) | (a >>> 27)); d += ((a & c) | (b & ~c)) + x2 + 0xfcefa3f8; d = a + ((d << 9) | (d >>> 23)); c += ((d & b) | (a & ~b)) + x7 + 0x676f02d9; c = d + ((c << 14) | (c >>> 18)); b += ((c & a) | (d & ~a)) + x12 + 0x8d2a4c8a; b = c + ((b << 20) | (b >>> 12)); a += (b ^ c ^ d) + x5 + 0xfffa3942; a = b + ((a << 4) | (a >>> 28)); d += (a ^ b ^ c) + x8 + 0x8771f681; d = a + ((d << 11) | (d >>> 21)); c += (d ^ a ^ b) + x11 + 0x6d9d6122; c = d + ((c << 16) | (c >>> 16)); b += (c ^ d ^ a) + x14 + 0xfde5380c; b = c + ((b << 23) | (b >>> 9)); a += (b ^ c ^ d) + x1 + 0xa4beea44; a = b + ((a << 4) | (a >>> 28)); d += (a ^ b ^ c) + x4 + 0x4bdecfa9; d = a + ((d << 11) | (d >>> 21)); c += (d ^ a ^ b) + x7 + 0xf6bb4b60; c = d + ((c << 16) | (c >>> 16)); b += (c ^ d ^ a) + x10 + 0xbebfbc70; b = c + ((b << 23) | (b >>> 9)); a += (b ^ c ^ d) + x13 + 0x289b7ec6; a = b + ((a << 4) | (a >>> 28)); d += (a ^ b ^ c) + x0 + 0xeaa127fa; d = a + ((d << 11) | (d >>> 21)); c += (d ^ a ^ b) + x3 + 0xd4ef3085; c = d + ((c << 16) | (c >>> 16)); b += (c ^ d ^ a) + x6 + 0x4881d05; b = c + ((b << 23) | (b >>> 9)); a += (b ^ c ^ d) + x9 + 0xd9d4d039; a = b + ((a << 4) | (a >>> 28)); d += (a ^ b ^ c) + x12 + 0xe6db99e5; d = a + ((d << 11) | (d >>> 21)); c += (d ^ a ^ b) + x15 + 0x1fa27cf8; c = d + ((c << 16) | (c >>> 16)); b += (c ^ d ^ a) + x2 + 0xc4ac5665; b = c + ((b << 23) | (b >>> 9)); a += (c ^ (b | ~d)) + x0 + 0xf4292244; a = b + ((a << 6) | (a >>> 26)); d += (b ^ (a | ~c)) + x7 + 0x432aff97; d = a + ((d << 10) | (d >>> 22)); c += (a ^ (d | ~b)) + x14 + 0xab9423a7; c = d + ((c << 15) | (c >>> 17)); b += (d ^ (c | ~a)) + x5 + 0xfc93a039; b = c + ((b << 21) | (b >>> 11)); a += (c ^ (b | ~d)) + x12 + 0x655b59c3; a = b + ((a << 6) | (a >>> 26)); d += (b ^ (a | ~c)) + x3 + 0x8f0ccc92; d = a + ((d << 10) | (d >>> 22)); c += (a ^ (d | ~b)) + x10 + 0xffeff47d; c = d + ((c << 15) | (c >>> 17)); b += (d ^ (c | ~a)) + x1 + 0x85845dd1; b = c + ((b << 21) | (b >>> 11)); a += (c ^ (b | ~d)) + x8 + 0x6fa87e4f; a = b + ((a << 6) | (a >>> 26)); d += (b ^ (a | ~c)) + x15 + 0xfe2ce6e0; d = a + ((d << 10) | (d >>> 22)); c += (a ^ (d | ~b)) + x6 + 0xa3014314; c = d + ((c << 15) | (c >>> 17)); b += (d ^ (c | ~a)) + x13 + 0x4e0811a1; b = c + ((b << 21) | (b >>> 11)); a += (c ^ (b | ~d)) + x4 + 0xf7537e82; a = b + ((a << 6) | (a >>> 26)); d += (b ^ (a | ~c)) + x11 + 0xbd3af235; d = a + ((d << 10) | (d >>> 22)); c += (a ^ (d | ~b)) + x2 + 0x2ad7d2bb; c = d + ((c << 15) | (c >>> 17)); b += (d ^ (c | ~a)) + x9 + 0xeb86d391; b = c + ((b << 21) | (b >>> 11)); h0 += a; h1 += b; h2 += c; h3 += d; } /** * Resets the MD5 to initial state for a new message digest calculation. * Must be called before starting a new hash calculation. */ public void reset() { h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; length = 0; finalBuffer.clear(); } private void completeFinalBuffer(ByteBuffer buffer) { if(finalBuffer.position() == 0) return; while(buffer.remaining() > 0 && finalBuffer.remaining() > 0) { finalBuffer.put(buffer.get()); } if(finalBuffer.remaining() == 0) { finalBuffer.position(0); transform(finalBuffer); finalBuffer.position(0); } } /** * Starts or continues a MD5 message digest calculation. * Only the remaining bytes of the given ByteBuffer are used. * @param buffer input data */ public void update(ByteBuffer buffer) { length += buffer.remaining(); //Save current position to leave given buffer unchanged int position = buffer.position(); //Complete the final buffer if needed completeFinalBuffer(buffer); while(buffer.remaining() >= 64) { transform(buffer); } if(buffer.remaining() != 0) { finalBuffer.put(buffer); } buffer.position(position); } /** * Finishes the MD5-1 message digest calculation. * @return 16-byte hash result */ public byte[] digest() { byte[] result = new byte[16]; finalBuffer.put((byte)0x80); if(finalBuffer.remaining() < 8) { while(finalBuffer.remaining() > 0) { finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer); finalBuffer.position(0); } while(finalBuffer.remaining() > 8) { finalBuffer.put((byte)0); } finalBuffer.putLong(length << 3); finalBuffer.position(0); transform(finalBuffer); finalBuffer.position(0); finalBuffer.putInt(h3); finalBuffer.putInt(h2); finalBuffer.putInt(h1); finalBuffer.putInt(h0); finalBuffer.position(0); for(int i = 0 ; i < 16 ; i++) { result[15-i] = finalBuffer.get(); } return result; } /** * Finishes the MD5 message digest calculation, by first performing a final update * from the given input buffer, then completing the calculation as with digest(). * @param buffer input data * @return 16-byte hash result */ public byte[] digest(ByteBuffer buffer) { update( buffer ); return digest(); } public static void main(String args[]) throws Exception { MD5 md5Gudy = new MD5(); BrokenMd5Hasher md5Jmule = new BrokenMd5Hasher(); MessageDigest md5Sun = MessageDigest.getInstance("MD5"); ByteBuffer bhashJ = ByteBuffer.allocate(16); System.out.println("Gudy : " + ByteFormatter.nicePrint(md5Gudy.digest())); md5Gudy.reset(); md5Jmule.finalDigest(bhashJ); bhashJ.rewind(); byte hashJ[] = bhashJ.array(); System.out.println("Jmule: " + ByteFormatter.nicePrint(hashJ)); System.out.println("Sun: " + ByteFormatter.nicePrint(md5Sun.digest())); for(int i = 0 ; i < 1 ; i++) { ByteBuffer test = ByteBuffer.allocate(i); while(test.remaining() > 0) { test.put((byte)(Math.random() * 256)); } test.rewind(); byte hashG[] = md5Gudy.digest(test); md5Gudy.reset(); md5Jmule.update(test); bhashJ.rewind(); md5Jmule.finalDigest(bhashJ); bhashJ.rewind(); hashJ = bhashJ.array(); test.rewind(); md5Sun.update(test.array()); byte hashS[] = md5Sun.digest(); System.out.println("Gudy : " + ByteFormatter.nicePrint(hashG)); System.out.println("Jmule: " + ByteFormatter.nicePrint(hashJ)); System.out.println("Sun: " + ByteFormatter.nicePrint(hashS)); //boolean same = true; //System.out.println(i + " : " + same); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AECallback.java0000644000175000017500000000220010730634464022713 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * Generic interface so that we can callback * * @author TuxPaper * @created Dec 14, 2007 * */ public interface AECallback { public void callbackSuccess(Object o); public void callbackFailure(Throwable t); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/test/0000755000175000017500000000000011310377634021131 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/util/test/SHA1Old.java0000644000175000017500000004356210666155500023140 0ustar adrianadrian /* * Created on Apr 12, 2004 * Created by Olivier Chalouhi * Modified Apr 13, 2004 by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util.test; import java.nio.ByteBuffer; /** * SHA-1 message digest class. */ public final class SHA1Old { private int h0,h1,h2,h3,h4; private ByteBuffer finalBuffer; private ByteBuffer saveBuffer; private int s0,s1,s2,s3,s4; long length; long saveLength; /** * Create a new SHA-1 message digest hasher. */ public SHA1Old() { finalBuffer = ByteBuffer.allocate(64); finalBuffer.position(0); finalBuffer.limit(64); saveBuffer = ByteBuffer.allocate(64); saveBuffer.position(0); saveBuffer.limit(64); reset(); } private void transform(ByteBuffer M) { int w0 , w1 , w2 , w3 , w4 , w5 , w6 , w7 , w8 , w9 , w10, w11, w12, w13, w14, w15; int a,b,c,d,e; w0 = M.getInt(); w1 = M.getInt(); w2 = M.getInt(); w3 = M.getInt(); w4 = M.getInt(); w5 = M.getInt(); w6 = M.getInt(); w7 = M.getInt(); w8 = M.getInt(); w9 = M.getInt(); w10 = M.getInt(); w11 = M.getInt(); w12 = M.getInt(); w13 = M.getInt(); w14 = M.getInt(); w15 = M.getInt(); a = h0 ; b = h1 ; c = h2 ; d = h3 ; e = h4; e += ((a << 5) | ( a >>> 27)) + w0 + ((b & c) | ((~b ) & d)) + 0x5A827999 ; b = (b << 30) | (b >>> 2) ; d += ((e << 5) | ( e >>> 27)) + w1 + ((a & b) | ((~a ) & c)) + 0x5A827999 ; a = (a << 30) | (a >>> 2) ; c += ((d << 5) | ( d >>> 27)) + w2 + ((e & a) | ((~e ) & b)) + 0x5A827999 ; e = (e << 30) | (e >>> 2) ; b += ((c << 5) | ( c >>> 27)) + w3 + ((d & e) | ((~d ) & a)) + 0x5A827999 ; d = (d << 30) | (d >>> 2) ; a += ((b << 5) | ( b >>> 27)) + w4 + ((c & d) | ((~c ) & e)) + 0x5A827999 ; c = (c << 30) | (c >>> 2) ; e += ((a << 5) | ( a >>> 27)) + w5 + ((b & c) | ((~b ) & d)) + 0x5A827999 ; b = (b << 30) | (b >>> 2) ; d += ((e << 5) | ( e >>> 27)) + w6 + ((a & b) | ((~a ) & c)) + 0x5A827999 ; a = (a << 30) | (a >>> 2) ; c += ((d << 5) | ( d >>> 27)) + w7 + ((e & a) | ((~e ) & b)) + 0x5A827999 ; e = (e << 30) | (e >>> 2) ; b += ((c << 5) | ( c >>> 27)) + w8 + ((d & e) | ((~d ) & a)) + 0x5A827999 ; d = (d << 30) | (d >>> 2) ; a += ((b << 5) | ( b >>> 27)) + w9 + ((c & d) | ((~c ) & e)) + 0x5A827999 ; c = (c << 30) | (c >>> 2) ; e += ((a << 5) | ( a >>> 27)) + w10 + ((b & c) | ((~b ) & d)) + 0x5A827999 ; b = (b << 30) | (b >>> 2) ; d += ((e << 5) | ( e >>> 27)) + w11 + ((a & b) | ((~a ) & c)) + 0x5A827999 ; a = (a << 30) | (a >>> 2) ; c += ((d << 5) | ( d >>> 27)) + w12 + ((e & a) | ((~e ) & b)) + 0x5A827999 ; e = (e << 30) | (e >>> 2) ; b += ((c << 5) | ( c >>> 27)) + w13 + ((d & e) | ((~d ) & a)) + 0x5A827999 ; d = (d << 30) | (d >>> 2) ; a += ((b << 5) | ( b >>> 27)) + w14 + ((c & d) | ((~c ) & e)) + 0x5A827999 ; c = (c << 30) | (c >>> 2) ; e += ((a << 5) | ( a >>> 27)) + w15 + ((b & c) | ((~b ) & d)) + 0x5A827999 ; b = (b << 30) | (b >>> 2) ; w0 = w13 ^ w8 ^ w2 ^ w0; w0 = (w0 << 1) | (w0 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w0 + ((a & b) | ((~a ) & c)) + 0x5A827999 ; a = (a << 30) | (a >>> 2) ; w1 = w14 ^ w9 ^ w3 ^ w1; w1 = (w1 << 1) | (w1 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w1 + ((e & a) | ((~e ) & b)) + 0x5A827999 ; e = (e << 30) | (e >>> 2) ; w2 = w15 ^ w10 ^ w4 ^ w2; w2 = (w2 << 1) | (w2 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w2 + ((d & e) | ((~d ) & a)) + 0x5A827999 ; d = (d << 30) | (d >>> 2) ; w3 = w0 ^ w11 ^ w5 ^ w3; w3 = (w3 << 1) | (w3 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w3 + ((c & d) | ((~c ) & e)) + 0x5A827999 ; c = (c << 30) | (c >>> 2) ; w4 = w1 ^ w12 ^ w6 ^ w4; w4 = (w4 << 1) | (w4 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w4 + (b ^ c ^ d) + 0x6ED9EBA1 ; b = (b << 30) | (b >>> 2) ; w5 = w2 ^ w13 ^ w7 ^ w5; w5 = (w5 << 1) | (w5 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w5 + (a ^ b ^ c) + 0x6ED9EBA1 ; a = (a << 30) | (a >>> 2) ; w6 = w3 ^ w14 ^ w8 ^ w6; w6 = (w6 << 1) | (w6 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w6 + (e ^ a ^ b) + 0x6ED9EBA1 ; e = (e << 30) | (e >>> 2) ; w7 = w4 ^ w15 ^ w9 ^ w7; w7 = (w7 << 1) | (w7 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w7 + (d ^ e ^ a) + 0x6ED9EBA1 ; d = (d << 30) | (d >>> 2) ; w8 = w5 ^ w0 ^ w10 ^ w8; w8 = (w8 << 1) | (w8 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w8 + (c ^ d ^ e) + 0x6ED9EBA1 ; c = (c << 30) | (c >>> 2) ; w9 = w6 ^ w1 ^ w11 ^ w9; w9 = (w9 << 1) | (w9 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w9 + (b ^ c ^ d) + 0x6ED9EBA1 ; b = (b << 30) | (b >>> 2) ; w10 = w7 ^ w2 ^ w12 ^ w10; w10 = (w10 << 1) | (w10 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w10 + (a ^ b ^ c) + 0x6ED9EBA1 ; a = (a << 30) | (a >>> 2) ; w11 = w8 ^ w3 ^ w13 ^ w11; w11 = (w11 << 1) | (w11 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w11 + (e ^ a ^ b) + 0x6ED9EBA1 ; e = (e << 30) | (e >>> 2) ; w12 = w9 ^ w4 ^ w14 ^ w12; w12 = (w12 << 1) | (w12 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w12 + (d ^ e ^ a) + 0x6ED9EBA1 ; d = (d << 30) | (d >>> 2) ; w13 = w10 ^ w5 ^ w15 ^ w13; w13 = (w13 << 1) | (w13 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w13 + (c ^ d ^ e) + 0x6ED9EBA1 ; c = (c << 30) | (c >>> 2) ; w14 = w11 ^ w6 ^ w0 ^ w14; w14 = (w14 << 1) | (w14 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w14 + (b ^ c ^ d) + 0x6ED9EBA1 ; b = (b << 30) | (b >>> 2) ; w15 = w12 ^ w7 ^ w1 ^ w15; w15 = (w15 << 1) | (w15 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w15 + (a ^ b ^ c) + 0x6ED9EBA1 ; a = (a << 30) | (a >>> 2) ; w0 = w13 ^ w8 ^ w2 ^ w0; w0 = (w0 << 1) | (w0 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w0 + (e ^ a ^ b) + 0x6ED9EBA1 ; e = (e << 30) | (e >>> 2) ; w1 = w14 ^ w9 ^ w3 ^ w1; w1 = (w1 << 1) | (w1 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w1 + (d ^ e ^ a) + 0x6ED9EBA1 ; d = (d << 30) | (d >>> 2) ; w2 = w15 ^ w10 ^ w4 ^ w2; w2 = (w2 << 1) | (w2 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w2 + (c ^ d ^ e) + 0x6ED9EBA1 ; c = (c << 30) | (c >>> 2) ; w3 = w0 ^ w11 ^ w5 ^ w3; w3 = (w3 << 1) | (w3 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w3 + (b ^ c ^ d) + 0x6ED9EBA1 ; b = (b << 30) | (b >>> 2) ; w4 = w1 ^ w12 ^ w6 ^ w4; w4 = (w4 << 1) | (w4 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w4 + (a ^ b ^ c) + 0x6ED9EBA1 ; a = (a << 30) | (a >>> 2) ; w5 = w2 ^ w13 ^ w7 ^ w5; w5 = (w5 << 1) | (w5 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w5 + (e ^ a ^ b) + 0x6ED9EBA1 ; e = (e << 30) | (e >>> 2) ; w6 = w3 ^ w14 ^ w8 ^ w6; w6 = (w6 << 1) | (w6 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w6 + (d ^ e ^ a) + 0x6ED9EBA1 ; d = (d << 30) | (d >>> 2) ; w7 = w4 ^ w15 ^ w9 ^ w7; w7 = (w7 << 1) | (w7 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w7 + (c ^ d ^ e) + 0x6ED9EBA1 ; c = (c << 30) | (c >>> 2) ; w8 = w5 ^ w0 ^ w10 ^ w8; w8 = (w8 << 1) | (w8 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w8 + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ; b = (b << 30) | (b >>> 2) ; w9 = w6 ^ w1 ^ w11 ^ w9; w9 = (w9 << 1) | (w9 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w9 + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC ; a = (a << 30) | (a >>> 2) ; w10 = w7 ^ w2 ^ w12 ^ w10; w10 = (w10 << 1) | (w10 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w10 + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC ; e = (e << 30) | (e >>> 2) ; w11 = w8 ^ w3 ^ w13 ^ w11; w11 = (w11 << 1) | (w11 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w11 + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC ; d = (d << 30) | (d >>> 2) ; w12 = w9 ^ w4 ^ w14 ^ w12; w12 = (w12 << 1) | (w12 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w12 + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC ; c = (c << 30) | (c >>> 2) ; w13 = w10 ^ w5 ^ w15 ^ w13; w13 = (w13 << 1) | (w13 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w13 + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ; b = (b << 30) | (b >>> 2) ; w14 = w11 ^ w6 ^ w0 ^ w14; w14 = (w14 << 1) | (w14 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w14 + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC ; a = (a << 30) | (a >>> 2) ; w15 = w12 ^ w7 ^ w1 ^ w15; w15 = (w15 << 1) | (w15 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w15 + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC ; e = (e << 30) | (e >>> 2) ; w0 = w13 ^ w8 ^ w2 ^ w0; w0 = (w0 << 1) | (w0 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w0 + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC ; d = (d << 30) | (d >>> 2) ; w1 = w14 ^ w9 ^ w3 ^ w1; w1 = (w1 << 1) | (w1 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w1 + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC ; c = (c << 30) | (c >>> 2) ; w2 = w15 ^ w10 ^ w4 ^ w2; w2 = (w2 << 1) | (w2 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w2 + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ; b = (b << 30) | (b >>> 2) ; w3 = w0 ^ w11 ^ w5 ^ w3; w3 = (w3 << 1) | (w3 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w3 + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC ; a = (a << 30) | (a >>> 2) ; w4 = w1 ^ w12 ^ w6 ^ w4; w4 = (w4 << 1) | (w4 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w4 + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC ; e = (e << 30) | (e >>> 2) ; w5 = w2 ^ w13 ^ w7 ^ w5; w5 = (w5 << 1) | (w5 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w5 + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC ; d = (d << 30) | (d >>> 2) ; w6 = w3 ^ w14 ^ w8 ^ w6; w6 = (w6 << 1) | (w6 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w6 + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC ; c = (c << 30) | (c >>> 2) ; w7 = w4 ^ w15 ^ w9 ^ w7; w7 = (w7 << 1) | (w7 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w7 + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ; b = (b << 30) | (b >>> 2) ; w8 = w5 ^ w0 ^ w10 ^ w8; w8 = (w8 << 1) | (w8 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w8 + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC ; a = (a << 30) | (a >>> 2) ; w9 = w6 ^ w1 ^ w11 ^ w9; w9 = (w9 << 1) | (w9 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w9 + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC ; e = (e << 30) | (e >>> 2) ; w10 = w7 ^ w2 ^ w12 ^ w10; w10 = (w10 << 1) | (w10 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w10 + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC ; d = (d << 30) | (d >>> 2) ; w11 = w8 ^ w3 ^ w13 ^ w11; w11 = (w11 << 1) | (w11 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w11 + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC ; c = (c << 30) | (c >>> 2) ; w12 = w9 ^ w4 ^ w14 ^ w12; w12 = (w12 << 1) | (w12 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w12 + (b ^ c ^ d) + 0xCA62C1D6 ; b = (b << 30) | (b >>> 2) ; w13 = w10 ^ w5 ^ w15 ^ w13; w13 = (w13 << 1) | (w13 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w13 + (a ^ b ^ c) + 0xCA62C1D6 ; a = (a << 30) | (a >>> 2) ; w14 = w11 ^ w6 ^ w0 ^ w14; w14 = (w14 << 1) | (w14 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w14 + (e ^ a ^ b) + 0xCA62C1D6 ; e = (e << 30) | (e >>> 2) ; w15 = w12 ^ w7 ^ w1 ^ w15; w15 = (w15 << 1) | (w15 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w15 + (d ^ e ^ a) + 0xCA62C1D6 ; d = (d << 30) | (d >>> 2) ; w0 = w13 ^ w8 ^ w2 ^ w0; w0 = (w0 << 1) | (w0 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w0 + (c ^ d ^ e) + 0xCA62C1D6 ; c = (c << 30) | (c >>> 2) ; w1 = w14 ^ w9 ^ w3 ^ w1; w1 = (w1 << 1) | (w1 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w1 + (b ^ c ^ d) + 0xCA62C1D6 ; b = (b << 30) | (b >>> 2) ; w2 = w15 ^ w10 ^ w4 ^ w2; w2 = (w2 << 1) | (w2 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w2 + (a ^ b ^ c) + 0xCA62C1D6 ; a = (a << 30) | (a >>> 2) ; w3 = w0 ^ w11 ^ w5 ^ w3; w3 = (w3 << 1) | (w3 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w3 + (e ^ a ^ b) + 0xCA62C1D6 ; e = (e << 30) | (e >>> 2) ; w4 = w1 ^ w12 ^ w6 ^ w4; w4 = (w4 << 1) | (w4 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w4 + (d ^ e ^ a) + 0xCA62C1D6 ; d = (d << 30) | (d >>> 2) ; w5 = w2 ^ w13 ^ w7 ^ w5; w5 = (w5 << 1) | (w5 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w5 + (c ^ d ^ e) + 0xCA62C1D6 ; c = (c << 30) | (c >>> 2) ; w6 = w3 ^ w14 ^ w8 ^ w6; w6 = (w6 << 1) | (w6 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w6 + (b ^ c ^ d) + 0xCA62C1D6 ; b = (b << 30) | (b >>> 2) ; w7 = w4 ^ w15 ^ w9 ^ w7; w7 = (w7 << 1) | (w7 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w7 + (a ^ b ^ c) + 0xCA62C1D6 ; a = (a << 30) | (a >>> 2) ; w8 = w5 ^ w0 ^ w10 ^ w8; w8 = (w8 << 1) | (w8 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w8 + (e ^ a ^ b) + 0xCA62C1D6 ; e = (e << 30) | (e >>> 2) ; w9 = w6 ^ w1 ^ w11 ^ w9; w9 = (w9 << 1) | (w9 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w9 + (d ^ e ^ a) + 0xCA62C1D6 ; d = (d << 30) | (d >>> 2) ; w10 = w7 ^ w2 ^ w12 ^ w10; w10 = (w10 << 1) | (w10 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w10 + (c ^ d ^ e) + 0xCA62C1D6 ; c = (c << 30) | (c >>> 2) ; w11 = w8 ^ w3 ^ w13 ^ w11; w11 = (w11 << 1) | (w11 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w11 + (b ^ c ^ d) + 0xCA62C1D6 ; b = (b << 30) | (b >>> 2) ; w12 = w9 ^ w4 ^ w14 ^ w12; w12 = (w12 << 1) | (w12 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w12 + (a ^ b ^ c) + 0xCA62C1D6 ; a = (a << 30) | (a >>> 2) ; w13 = w10 ^ w5 ^ w15 ^ w13; w13 = (w13 << 1) | (w13 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w13 + (e ^ a ^ b) + 0xCA62C1D6 ; e = (e << 30) | (e >>> 2) ; w14 = w11 ^ w6 ^ w0 ^ w14; w14 = (w14 << 1) | (w14 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w14 + (d ^ e ^ a) + 0xCA62C1D6 ; d = (d << 30) | (d >>> 2) ; w15 = w12 ^ w7 ^ w1 ^ w15; w15 = (w15 << 1) | (w15 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w15 + (c ^ d ^ e) + 0xCA62C1D6 ; c = (c << 30) | (c >>> 2) ; h0 += a; h1 += b; h2 += c; h3 += d; h4 += e; } private void completeFinalBuffer(ByteBuffer buffer) { if(finalBuffer.position() == 0) return; while(buffer.remaining() > 0 && finalBuffer.remaining() > 0) { finalBuffer.put(buffer.get()); } if(finalBuffer.remaining() == 0) { finalBuffer.position(0); transform(finalBuffer); finalBuffer.position(0); } } /** * Resets the SHA-1 to initial state for a new message digest calculation. * Must be called before starting a new hash calculation. */ public void reset() { h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; h4 = 0xC3D2E1F0; length = 0; finalBuffer.clear(); } /** * Starts or continues a SHA-1 message digest calculation. * Only the remaining bytes of the given ByteBuffer are used. * @param buffer input data */ public void update(ByteBuffer buffer) { length += buffer.remaining(); //Save current position to leave given buffer unchanged int position = buffer.position(); //Complete the final buffer if needed completeFinalBuffer(buffer); while(buffer.remaining() >= 64) { transform(buffer); } if(buffer.remaining() != 0) { finalBuffer.put(buffer); } buffer.position(position); } /** * Finishes the SHA-1 message digest calculation. * @return 20-byte hash result */ public byte[] digest() { byte[] result = new byte[20]; finalBuffer.put((byte)0x80); if(finalBuffer.remaining() < 8) { while(finalBuffer.remaining() > 0) { finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer); finalBuffer.position(0); } while(finalBuffer.remaining() > 8) { finalBuffer.put((byte)0); } finalBuffer.putLong(length << 3); finalBuffer.position(0); transform(finalBuffer); finalBuffer.position(0); finalBuffer.putInt(h0); finalBuffer.putInt(h1); finalBuffer.putInt(h2); finalBuffer.putInt(h3); finalBuffer.putInt(h4); finalBuffer.position(0); for(int i = 0 ; i < 20 ; i++) { result[i] = finalBuffer.get(); } return result; } /** * Finishes the SHA-1 message digest calculation, by first performing a final update * from the given input buffer, then completing the calculation as with digest(). * @param buffer input data * @return 20-byte hash result */ public byte[] digest(ByteBuffer buffer) { update( buffer ); return digest(); } /** * Save the current digest state. * This allows the resuming of a SHA-1 calculation, even after a digest calculation * is finished with digest(). */ public void saveState() { s0=h0; s1=h1; s2=h2; s3=h3; s4=h4; saveLength = length; int position = finalBuffer.position(); finalBuffer.position(0); finalBuffer.limit(position); saveBuffer.clear(); saveBuffer.put(finalBuffer); saveBuffer.flip(); finalBuffer.limit(64); finalBuffer.position( position ); } /** * Restore the digest to its previously-saved state. */ public void restoreState() { h0=s0; h1=s1; h2=s2; h3=s3; h4=s4; length = saveLength; finalBuffer.clear(); finalBuffer.put(saveBuffer); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/test/SystemClockSpeedup.java0000644000175000017500000000317710373051020025554 0ustar adrianadrian/* * Created on Apr 11, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util.test; import org.gudy.azureus2.core3.util.Debug; public class SystemClockSpeedup { public static void main(String[] args) { for (int i=0; i < 20; i++) { new tester().start(); } } public static class tester extends Thread { public void run() { try { int count = 0; while (true) { System.currentTimeMillis(); count++; if (count == 30000) { count = 0; Thread.sleep(100); } } } catch (Exception e) { Debug.printStackTrace( e ); } } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/test/SHA1SpeedTest.java0000644000175000017500000001455011016137262024310 0ustar adrianadrian/* * Created on Mar 12, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.util.test; import java.nio.*; import java.util.Arrays; import java.util.Random; // import org.gudy.azureus2.core3.util.SHA1; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.SHA1; /** */ public class SHA1SpeedTest { private static final int BUFF_MAX_SIZE = 4 * 1024 * 1024; private static final int[] LOOPS = { 1000000, 30000, 15000, 4000, 3000, 2000, 1200, 800 }; private static final int[] TESTS = { 1, 16, 64, 256, 512, 1024, 2048, 4096 }; private static final int TEST_SPEED_FACTOR = 1; // use larger numbers for less tests public static void main(String[] args) { Random rnd = new Random(); SHA1Old oldsha = new SHA1Old(); SHA1 newsha = new SHA1(); ByteBuffer dBuffer = ByteBuffer.allocateDirect(BUFF_MAX_SIZE); ByteBuffer hBuffer = ByteBuffer.allocate(BUFF_MAX_SIZE); for (int i = 0; i < BUFF_MAX_SIZE; i++) { byte b = (byte) (rnd.nextInt()&0xFF); dBuffer.put(b); } dBuffer.rewind(); hBuffer.put(dBuffer); hBuffer.rewind(); dBuffer.rewind(); // allow time for setting thread to high-priority try { System.out.println("Setting high thread priority to decrease test jitter"); Thread.currentThread().setPriority(Thread.MAX_PRIORITY); Thread.sleep(2000); } catch (Exception ignore) { } for (int t = 0; t < TESTS.length; t++) { int buffsize = TESTS[t] * 1024; dBuffer.position(0); dBuffer.limit(buffsize); hBuffer.position(0); hBuffer.limit(buffsize); int loops = LOOPS[t]/TEST_SPEED_FACTOR; String info = " [" + buffsize / 1024 + "KB, " + loops + "x] = "; double totalMBytes = ((double) buffsize / (1024 * 1024)) * loops; long time; double speed; System.out.println("direct:"); System.out.print("Old SHA1"); time = System.currentTimeMillis(); for (int i = 0; i < loops; i++) { oldsha.reset(); oldsha.digest(dBuffer); } time = System.currentTimeMillis() - time; speed = totalMBytes / (time / (double)1024); System.out.println(info + time + " ms @ " + speed + " MiB/s"); System.out.print("New SHA1 "); time = System.currentTimeMillis(); for (int i = 0; i < loops; i++) { newsha.reset(); newsha.digest(dBuffer); } time = System.currentTimeMillis() - time; speed = totalMBytes / (time / (double)1024); System.out.println(info + time + " ms @ " + speed + " MiB/s"); System.out.println("heap:"); System.out.print("Old SHA1"); time = System.currentTimeMillis(); for (int i = 0; i < loops; i++) { oldsha.reset(); oldsha.digest(hBuffer); } time = System.currentTimeMillis() - time; speed = totalMBytes / (time / (double)1024); System.out.println(info + time + " ms @ " + speed + " MiB/s"); System.out.print("New SHA1 "); time = System.currentTimeMillis(); for (int i = 0; i < loops; i++) { newsha.reset(); newsha.digest(hBuffer); } time = System.currentTimeMillis() - time; speed = totalMBytes / (time / (double)1024); System.out.println(info + time + " ms @ " + speed + " MiB/s"); System.out.println(); } System.out.println("performing randomized buffer windowing checks, this may take a while"); byte[] oldd; byte[] newd; byte[] oldh; byte[] newh; int size; int offset; ByteBuffer dview; ByteBuffer hview; for(int i=0;i 1024000 ) remaining = 1024000; byte[] buffer = new byte[ new Long(remaining).intValue() ]; rand.nextBytes( buffer ); ByteBuffer bb = ByteBuffer.wrap( buffer ); position += fc.write( bb ); } fc.close(); } System.out.println("DONE\n"); } catch (Exception e) { Debug.printStackTrace( e ); } } public static void runTests() { try { //SHA1 sha1Jmule = new SHA1(); MessageDigest sha1Sun = MessageDigest.getInstance("SHA-1"); SHA1 sha1Gudy = new SHA1(); //SHA1Az shaGudyResume = new SHA1Az(); ByteBuffer buffer = ByteBuffer.allocate( 1024 * 1024 ); File dir = new File( dirname ); File[] files = dir.listFiles(); for (int i=0; i < files.length; i++) { FileChannel fc = new RandomAccessFile( files[i], "r" ).getChannel(); System.out.println("Testing " + files[i].getName() + " ..."); while( fc.position() < fc.size() ) { fc.read( buffer ); buffer.flip(); byte[] raw = new byte[ buffer.limit() ]; System.arraycopy( buffer.array(), 0, raw, 0, raw.length ); sha1Gudy.update( buffer ); sha1Gudy.saveState(); ByteBuffer bb = ByteBuffer.wrap( new byte[56081] ); sha1Gudy.digest( bb ); sha1Gudy.restoreState(); sha1Sun.update( raw ); buffer.clear(); } byte[] sun = sha1Sun.digest(); sha1Sun.reset(); byte[] gudy = sha1Gudy.digest(); sha1Gudy.reset(); if ( Arrays.equals( sun, gudy ) ) { System.out.println(" SHA1-Gudy: OK"); } else { System.out.println(" SHA1-Gudy: FAILED"); } buffer.clear(); fc.close(); System.out.println(); } } catch (Throwable e) { Debug.printStackTrace( e );} } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/test/Sha1AlgorithmHelper.java0000644000175000017500000001231010024761636025574 0ustar adrianadrian/* * File : Sha1AlgorithmHelper.java * Created : 12 mars 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.test; /** * @author Olivier * */ public class Sha1AlgorithmHelper { public static void main(String args[]) { algorithm2NoShift(); } //SHA1 Algorithm v2 using only 16 ints and changing variable meaning //Over a period of 5 iterations. // A SHA-1 Basic operation can be discribed as: // temp = F(a,b,c,d,e); // e = d ; d = c ; c = G(b) ; b = a ; a = temp; // The Goal of changing the variable meaning is to remove the allocations // made. // In order to do, let's replace the role of : // // e by d, // d by c, // c by b // b by a // a by e // // If we rewrite the 1st equation, we can see that : // e = F(a,b,c,d,e); and b = G(b); // However, next line will be : // d = F(b,c,d,e,a); and a = G(a); // Next will be : // c = F(c,d,e,a,b); and e = G(e); // b = F(d,e,a,b,c); and d = G(d); // a = F(e,a,b,c,d); and c = G(c); // And we loop to first 'kind' where : // e = F(a,b,c,d,e), and b = G(b); // On 80th iteration (that is for t=79), we've looped 80 = 5 * 16, // so we're back to the classic representation of variables a,b,c,d,e // and we can directly use them to increment the h0,h1,h2,h3,h4 variables. public static void algorithm2NoShift() { String variables = "abcde"; int mask = 0x0000000F; for(int t = 0 ; t <= 79 ; t++) { String a = "" + variables.charAt((85-t)%5); String b = "" + variables.charAt((85-t+1)%5); String c = "" + variables.charAt((85-t+2)%5); String d = "" + variables.charAt((85-t+3)%5); String e = "" + variables.charAt((85-t+4)%5); int s = t & mask; if(t >= 16) { System.out.println("w" + s + " = w" + ((s+13) & mask) + " ^ w" + ((s+8) & mask) + " ^ w" + ((s+2) & mask) + " ^ w" + s + "; w" + s + " = (w" + s + " << 1) | (w" + s + " >>> 31) ;"); } System.out.print(e + " += ((" + a + " << 5) | ( " + a + " >>> 27)) + w" + s + " + "); int ft = t / 20; if(ft == 0) { System.out.println("((" + b +" & " + c + ") | ((~" + b +" ) & " + d + ")) + 0x5A827999 ;"); } if(ft == 1) { System.out.println("(" + b +" ^ " + c + " ^ " + d + ") + 0x6ED9EBA1 ;"); } if(ft == 2) { System.out.println("((" + b +" & " + c + ") | (" + b + " & " + d + ") | (" + c + " & " + d + ")) + 0x8F1BBCDC ;"); } if(ft == 3) { System.out.println("(" + b + " ^ " + c + " ^ " + d + ") + 0xCA62C1D6 ;"); } System.out.println(b + " = (" + b + " << 30) | (" + b + " >>> 2) ;"); } } //SHA1 Algorithm v2 using only 16 ints (+ a,b,c,d,e and temp) public static void algorithm2() { int mask = 0x0000000F; for(int t = 0 ; t <= 79 ; t++) { int s = t & mask; if(t >= 16) { System.out.println("w" + s + " = w" + ((s+13) & mask) + " ^ w" + ((s+8) & mask) + " ^ w" + ((s+2) & mask) + " ^ w" + s + "; w" + s + " = (w" + s + " << 1) | (w" + s + " >>> 31) ;"); } System.out.print("temp = ((a << 5) | (a >>> 27)) + e + w" + s + " + "); int ft = t / 20; if(ft == 0) { System.out.println("((b & c) | ((~b) & d)) + 0x5A827999 ;"); } if(ft == 1) { System.out.println("(b ^ c ^ d) + 0x6ED9EBA1 ;"); } if(ft == 2) { System.out.println("((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ;"); } if(ft == 3) { System.out.println("(b ^ c ^ d) + 0xCA62C1D6 ;"); } System.out.println("e=d ; d=c ; c = (b << 30) | (b >>> 2) ; b=a ; a=temp;"); } } public static void part1() { for(int t = 16 ; t <= 79 ; t++) { System.out.println( "w" + t + " = w" + (t-3) + " ^ w" + (t-8) + " ^ w" + (t-14) + " ^ w" + (t-16) + ";"); System.out.println( "w" + t + " = (w" + t + " << 1) | (w" + t + " >>> 31);"); } } public static void part2() { for(int t=0; t<= 79 ; t++) { int fn = t / 20; System.out.print("temp = ((a << 5) | (a >>> 27)) + e + w" + t + " + "); if(fn == 0) { System.out.println("((b & c) | ((~b) & d)) + 0x5A827999 ;"); } if(fn == 1) { System.out.println("(b ^ c ^ d) + 0x6ED9EBA1 ;"); } if(fn == 2) { System.out.println("((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ;"); } if(fn == 3) { System.out.println("(b ^ c ^ d) + 0xCA62C1D6 ;"); } System.out.println("e = d ; d = c ; c = (b<<30) | (b >>> 2); b = a; a = temp;"); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/test/Md5AlgorithmHelper.java0000644000175000017500000001562510041320750025424 0ustar adrianadrian/* * File : Md5AlgorithmHelper.java * Created : 16 avr. 2004 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.test; /** * @author Olivier Chalouhi * */ public class Md5AlgorithmHelper { public static final int S11 = 7; public static final int S12 = 12; public static final int S13 = 17; public static final int S14 = 22; public static final int S21 = 5; public static final int S22 = 9; public static final int S23 = 14; public static final int S24 = 20; public static final int S31 = 4; public static final int S32 = 11; public static final int S33 = 16; public static final int S34 = 23; public static final int S41 = 6; public static final int S42 = 10; public static final int S43 = 15; public static final int S44 = 21; public static void main(String args[]) { /* Round 1 */ String a = "a"; String b = "b"; String c = "c"; String d = "d"; pFF (a, b, c, d, 0, S11, "0xd76aa478"); /* 1 */ pFF (d, a, b, c, 1, S12, "0xe8c7b756"); /* 2 */ pFF (c, d, a, b, 2, S13, "0x242070db"); /* 3 */ pFF (b, c, d, a, 3, S14, "0xc1bdceee"); /* 4 */ pFF (a, b, c, d, 4, S11, "0xf57c0faf"); /* 5 */ pFF (d, a, b, c, 5, S12, "0x4787c62a"); /* 6 */ pFF (c, d, a, b, 6, S13, "0xa8304613"); /* 7 */ pFF (b, c, d, a, 7, S14, "0xfd469501"); /* 8 */ pFF (a, b, c, d, 8, S11, "0x698098d8"); /* 9 */ pFF (d, a, b, c, 9, S12, "0x8b44f7af"); /* 10 */ pFF (c, d, a, b, 10, S13,"0xffff5bb1"); /* 11 */ pFF (b, c, d, a, 11, S14,"0x895cd7be"); /* 12 */ pFF (a, b, c, d, 12, S11,"0x6b901122"); /* 13 */ pFF (d, a, b, c, 13, S12,"0xfd987193"); /* 14 */ pFF (c, d, a, b, 14, S13,"0xa679438e"); /* 15 */ pFF (b, c, d, a, 15, S14,"0x49b40821"); /* 16 */ /* Round 2 */ pGG (a, b, c, d, 1, S21, "0xf61e2562"); /* 17 */ pGG (d, a, b, c, 6, S22, "0xc040b340"); /* 18 */ pGG (c, d, a, b, 11, S23,"0x265e5a51"); /* 19 */ pGG (b, c, d, a, 0, S24, "0xe9b6c7aa"); /* 20 */ pGG (a, b, c, d, 5, S21, "0xd62f105d"); /* 21 */ pGG (d, a, b, c, 10, S22,"0x02441453"); /* 22 */ pGG (c, d, a, b, 15, S23,"0xd8a1e681"); /* 23 */ pGG (b, c, d, a, 4, S24, "0xe7d3fbc8"); /* 24 */ pGG (a, b, c, d, 9, S21, "0x21e1cde6"); /* 25 */ pGG (d, a, b, c, 14, S22,"0xc33707d6"); /* 26 */ pGG (c, d, a, b, 3, S23, "0xf4d50d87"); /* 27 */ pGG (b, c, d, a, 8, S24, "0x455a14ed"); /* 28 */ pGG (a, b, c, d, 13, S21,"0xa9e3e905"); /* 29 */ pGG (d, a, b, c, 2, S22, "0xfcefa3f8"); /* 30 */ pGG (c, d, a, b, 7, S23, "0x676f02d9"); /* 31 */ pGG (b, c, d, a, 12, S24,"0x8d2a4c8a"); /* 32 */ /* Round 3 */ pHH (a, b, c, d, 5, S31, "0xfffa3942"); /* 33 */ pHH (d, a, b, c, 8, S32, "0x8771f681"); /* 34 */ pHH (c, d, a, b, 11, S33,"0x6d9d6122"); /* 35 */ pHH (b, c, d, a, 14, S34,"0xfde5380c"); /* 36 */ pHH (a, b, c, d, 1, S31, "0xa4beea44"); /* 37 */ pHH (d, a, b, c, 4, S32, "0x4bdecfa9"); /* 38 */ pHH (c, d, a, b, 7, S33, "0xf6bb4b60"); /* 39 */ pHH (b, c, d, a, 10, S34,"0xbebfbc70"); /* 40 */ pHH (a, b, c, d, 13, S31,"0x289b7ec6"); /* 41 */ pHH (d, a, b, c, 0, S32, "0xeaa127fa"); /* 42 */ pHH (c, d, a, b, 3, S33, "0xd4ef3085"); /* 43 */ pHH (b, c, d, a, 6, S34, "0x04881d05"); /* 44 */ pHH (a, b, c, d, 9, S31, "0xd9d4d039"); /* 45 */ pHH (d, a, b, c, 12, S32,"0xe6db99e5"); /* 46 */ pHH (c, d, a, b, 15, S33,"0x1fa27cf8"); /* 47 */ pHH (b, c, d, a, 2, S34, "0xc4ac5665"); /* 48 */ /* Round 4 */ pII (a, b, c, d, 0, S41, "0xf4292244"); /* 49 */ pII (d, a, b, c, 7, S42, "0x432aff97"); /* 50 */ pII (c, d, a, b, 14, S43,"0xab9423a7"); /* 51 */ pII (b, c, d, a, 5, S44, "0xfc93a039"); /* 52 */ pII (a, b, c, d, 12, S41,"0x655b59c3"); /* 53 */ pII (d, a, b, c, 3, S42, "0x8f0ccc92"); /* 54 */ pII (c, d, a, b, 10, S43,"0xffeff47d"); /* 55 */ pII (b, c, d, a, 1, S44, "0x85845dd1"); /* 56 */ pII (a, b, c, d, 8, S41, "0x6fa87e4f"); /* 57 */ pII (d, a, b, c, 15, S42,"0xfe2ce6e0"); /* 58 */ pII (c, d, a, b, 6, S43, "0xa3014314"); /* 59 */ pII (b, c, d, a, 13, S44,"0x4e0811a1"); /* 60 */ pII (a, b, c, d, 4, S41, "0xf7537e82"); /* 61 */ pII (d, a, b, c, 11, S42,"0xbd3af235"); /* 62 */ pII (c, d, a, b, 2, S43, "0x2ad7d2bb"); /* 63 */ pII (b, c, d, a, 9, S44, "0xeb86d391"); /* 64 */ } public static String F(String x,String y,String z) { return "((" + x + " & " + y + ") | ( ~" + x + " & " + z + "))"; } public static String G(String x,String y,String z) { return "((" + x + " & " + z + ") | (" + y + " & ~" + z + "))"; } public static String H(String x,String y,String z) { return "(" + x + " ^ " + y + " ^ " + z + ")"; } public static String I(String x,String y,String z) { return "(" + y + " ^ (" + x + " | ~" + z + "))"; } public static String rotateLeft(String x,int n) { return "((" + x + " << " + n + ") | (" + x + " >>> " + (32-n) + "))"; } public static int T(int i) { return (int) (4294967296.0 * Math.abs(Math.sin(i))); } public static String pFF(String a,String b,String c,String d,int x, int s, String Ti) { String result = a + " += " + F(b,c,d) + " + x" + x + " + " + Ti + ";"; result += "\n"; result += a + " = " + b + " + " + rotateLeft(a,s) + ";"; System.out.println(result); return result; } public static String pGG(String a,String b,String c,String d,int x, int s, String Ti) { String result = a + " += " + G(b,c,d) + " + x" + x + " + " + Ti + ";"; result += "\n"; result += a + " = " + b + " + " + rotateLeft(a,s) + ";"; System.out.println(result); return result; } public static String pHH(String a,String b,String c,String d,int x, int s, String Ti) { String result = a + " += " + H(b,c,d) + " + x" + x + " + " + Ti + ";"; result += "\n"; result += a + " = " + b + " + " + rotateLeft(a,s) + ";"; System.out.println(result); return result; } public static String pII(String a,String b,String c,String d,int x, int s, String Ti) { String result = a + " += " + I(b,c,d) + " + x" + x + " + " + Ti + ";"; result += "\n"; result += a + " = " + b + " + " + rotateLeft(a,s) + ";"; System.out.println(result); return result; } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AEVerifier.java0000644000175000017500000001061310443644774023007 0ustar adrianadrian/* * Created on 13 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.math.BigInteger; import java.security.KeyFactory; import java.security.Signature; import java.security.interfaces.RSAPublicKey; import java.security.spec.RSAPublicKeySpec; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class AEVerifier { private static final String pub_exp = "10001"; private static final String modulus = "9a68296f49bf47b2a83ae4ba3cdb5a840a2689e5b36a6f2bfc27b916fc4dc9437f9087c4f0b5ae2fc5127a901b3c048753aa63d29cd7f9da7c81d475380de68236bd919230b0074aa6f40f29a78ac4a14e84fb8946cbcb5a840d1c2f77d83c795c289e37135843b8da008e082654a83b8bd3341b9f2ff6064e20b6c7ba89a707a1f3e1d8b2e0035dae539b04e49775eba23e5cbe89e22290da6c84ec3f450d07"; public static void verifyData( File file ) throws AEVerifierException, Exception { KeyFactory key_factory = KeyFactory.getInstance("RSA"); RSAPublicKeySpec public_key_spec = new RSAPublicKeySpec( new BigInteger(modulus,16), new BigInteger(pub_exp,16)); RSAPublicKey public_key = (RSAPublicKey)key_factory.generatePublic( public_key_spec ); verifyData( file, public_key ); } protected static void verifyData( File file, RSAPublicKey key ) throws AEVerifierException, Exception { ZipInputStream zis = null; try{ zis = new ZipInputStream( new BufferedInputStream( new FileInputStream( file ) )); byte[] signature = null; Signature sig = Signature.getInstance("MD5withRSA" ); sig.initVerify( key ); while( true ){ ZipEntry entry = zis.getNextEntry(); if ( entry == null ){ break; } if ( entry.isDirectory()){ continue; } String name = entry.getName(); ByteArrayOutputStream output = null; if ( name.equalsIgnoreCase("azureus.sig")){ output = new ByteArrayOutputStream(); } byte[] buffer = new byte[65536]; while( true ){ int len = zis.read( buffer ); if ( len <= 0 ){ break; } if ( output == null ){ sig.update( buffer, 0, len ); }else{ output.write( buffer, 0, len ); } } if ( output != null ){ signature = output.toByteArray(); } } if ( signature == null ){ throw( new AEVerifierException( AEVerifierException.FT_SIGNATURE_MISSING, "Signature missing from file" )); } if ( !sig.verify( signature )){ throw( new AEVerifierException( AEVerifierException.FT_SIGNATURE_BAD, "Signature doesn't match data" )); } }finally{ if ( zis != null ){ zis.close(); } } } public static void verifyData( String data, byte[] signature ) throws AEVerifierException, Exception { KeyFactory key_factory = KeyFactory.getInstance("RSA"); RSAPublicKeySpec public_key_spec = new RSAPublicKeySpec( new BigInteger(modulus,16), new BigInteger(pub_exp,16)); RSAPublicKey public_key = (RSAPublicKey)key_factory.generatePublic( public_key_spec ); Signature sig = Signature.getInstance("MD5withRSA" ); sig.initVerify( public_key ); sig.update( data.getBytes( "UTF-8" )); if ( !sig.verify( signature )){ throw( new AEVerifierException( AEVerifierException.FT_SIGNATURE_BAD, "Data verification failed, signature doesn't match data" )); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/DirectByteBufferPool.java0000644000175000017500000000356511104244756025047 0ustar adrianadrian/* * Created on Jan 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Alon Rohter, All Rights Reserved. * * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.util; public abstract class DirectByteBufferPool { //According to reports (from the http://mina.apache.org folks), hotspot vms actually //work better with non-direct (heap) buffers for network and disk io these days. private static final DirectByteBufferPool impl; static{ if ( System.getProperty( "use.heap.buffers" ) != null ){ impl = new DirectByteBufferPoolHeap(); Debug.outNoStack( "******** USE_HEAP_BUFFERS MODE ENABLED ********" ); }else{ impl = new DirectByteBufferPoolReal(); } } public static DirectByteBuffer getBuffer( byte allocator, int length ) { return( impl.getBufferSupport( allocator, length )); } protected abstract DirectByteBuffer getBufferSupport( byte allocator, int length ); protected abstract void returnBufferSupport( DirectByteBuffer buffer ); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AEThread2.java0000644000175000017500000001776311264673734022542 0ustar adrianadrian/* * Created on Nov 9, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.util.LinkedList; import com.aelitis.azureus.core.util.Java15Utils; public abstract class AEThread2 { public static final boolean TRACE_TIMES = false; private static final int MIN_RETAINED = Math.max(Runtime.getRuntime().availableProcessors(),2); private static final int MAX_RETAINED = Math.max(MIN_RETAINED*4, 16); private static final int THREAD_TIMEOUT_CHECK_PERIOD = 10*1000; private static final int THREAD_TIMEOUT = 60*1000; private static final LinkedList daemon_threads = new LinkedList(); private static final class JoinLock { volatile boolean released = false; } private static long last_timeout_check; private static long total_starts; private static long total_creates; private threadWrapper wrapper; private String name; private boolean daemon; private int priority = Thread.NORM_PRIORITY; private volatile JoinLock lock = new JoinLock(); public AEThread2( String _name, boolean _daemon ) { name = _name; daemon = _daemon; } /** * multiple invocations of start() are possible, but discouraged if combined * with other thread operations such as interrupt() or join() */ public void start() { JoinLock currentLock = lock; JoinLock newLock; synchronized (currentLock) { // create new lock in case this is a restart, all old .join()s will be locked on the old thread and thus released by the old thread if(currentLock.released) newLock = lock = new JoinLock(); else newLock = currentLock; } if ( daemon ){ synchronized( daemon_threads ){ total_starts++; if ( daemon_threads.isEmpty()){ total_creates++; wrapper = new threadWrapper( name, true ); }else{ wrapper = (threadWrapper)daemon_threads.removeLast(); wrapper.setName( name ); } } }else{ wrapper = new threadWrapper( name, false ); } if ( priority != wrapper.getPriority() ){ wrapper.setPriority( priority ); } wrapper.currentLock = newLock; wrapper.start( this, name ); } public void setPriority( int _priority ) { priority = _priority; if ( wrapper != null ){ wrapper.setPriority( priority ); } } public void setName( String s ) { name = s; if ( wrapper != null ){ wrapper.setName( name ); } } public String getName() { return( name ); } public void interrupt() { if ( wrapper == null ){ throw new IllegalStateException( "Interrupted before started!" ); }else{ wrapper.interrupt(); } } public boolean isCurrentThread() { return( wrapper == Thread.currentThread()); } public String toString() { if ( wrapper == null ){ return( name + " [daemon=" + daemon + ",priority=" + priority + "]" ); }else{ return( wrapper.toString()); } } public abstract void run(); public static boolean isOurThread( Thread thread ) { return( AEThread.isOurThread( thread )); } public static void setOurThread() { AEThread.setOurThread(); } public static void setOurThread( Thread thread ) { AEThread.setOurThread( thread ); } public static void setDebug( Object debug ) { Thread current = Thread.currentThread(); if ( current instanceof threadWrapper ){ ((threadWrapper)current).setDebug( debug ); } } /** * entry 0 is debug object, 1 is Long mono-time it was set * @param t * @return */ public static Object[] getDebug( Thread t ) { if ( t instanceof threadWrapper ){ return(((threadWrapper)t).getDebug()); } return( null ); } protected static class threadWrapper extends Thread { private AESemaphore2 sem; private AEThread2 target; private JoinLock currentLock; private long last_active_time; private Object[] debug; protected threadWrapper( String name, boolean daemon ) { super( name ); setDaemon( daemon ); } public void run() { while( true ){ synchronized( currentLock ){ try{ if ( TRACE_TIMES ){ long start_time = SystemTime.getHighPrecisionCounter(); long start_cpu = Java15Utils.getThreadCPUTime(); try{ target.run(); }finally{ long time_diff = ( SystemTime.getHighPrecisionCounter() - start_time )/1000000; long cpu_diff = ( Java15Utils.getThreadCPUTime() - start_cpu ) / 1000000; if ( cpu_diff > 10 || time_diff > 10 ){ System.out.println( TimeFormatter.milliStamp() + ": Thread: " + target.getName() + ": " + cpu_diff + "/" + time_diff ); } } }else{ target.run(); } }catch( Throwable e ){ DebugLight.printStackTrace(e); }finally{ target = null; debug = null; currentLock.released = true; currentLock.notifyAll(); } } if ( isInterrupted() || !Thread.currentThread().isDaemon()){ break; }else{ synchronized( daemon_threads ){ last_active_time = SystemTime.getCurrentTime(); if ( last_active_time < last_timeout_check || last_active_time - last_timeout_check > THREAD_TIMEOUT_CHECK_PERIOD ){ last_timeout_check = last_active_time; while( daemon_threads.size() > 0 && daemon_threads.size() > MIN_RETAINED ){ threadWrapper thread = (threadWrapper)daemon_threads.getFirst(); long thread_time = thread.last_active_time; if ( last_active_time < thread_time || last_active_time - thread_time > THREAD_TIMEOUT ){ daemon_threads.removeFirst(); thread.retire(); }else{ break; } } } if ( daemon_threads.size() >= MAX_RETAINED ){ return; } daemon_threads.addLast( this ); setName( "AEThead2:parked[" + daemon_threads.size() + "]" ); // System.out.println( "AEThread2: queue=" + daemon_threads.size() + ",creates=" + total_creates + ",starts=" + total_starts ); } sem.reserve(); if ( target == null ){ break; } } } } protected void start( AEThread2 _target, String _name ) { target = _target; setName( _name ); if ( sem == null ){ sem = new AESemaphore2( "AEThread2" ); super.start(); }else{ sem.release(); } } protected void retire() { sem.release(); } protected void setDebug( Object d ) { debug = new Object[]{ d, SystemTime.getMonotonousTime() }; } protected Object[] getDebug() { return( debug ); } } public void join() { JoinLock currentLock = lock; // sync lock will be blocked by the thread synchronized( currentLock ){ // wait in case the thread is not running yet while (!currentLock.released ){ try{ currentLock.wait(); }catch( InterruptedException e ){ } } } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AEMonitor.java0000644000175000017500000001222610730131242022641 0ustar adrianadrian/* * Created on 18-Sep-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author parg * */ import java.util.*; public class AEMonitor extends AEMonSem { private int dont_wait = 1; private int nests = 0; private int total_reserve = 0; private int total_release = 1; protected Thread owner; protected Thread last_waiter; public AEMonitor( String _name ) { super( _name, true ); } public void enter() { if ( DEBUG ){ debugEntry(); } Thread current_thread = Thread.currentThread(); synchronized( this ){ entry_count++; if ( owner == current_thread ){ nests++; }else{ if ( dont_wait == 0 ){ try{ waiting++; last_waiter = current_thread; if ( waiting > 1 ){ // System.out.println( "AEMonitor: " + name + " contended" ); } // we can get spurious wakeups (see Object javadoc) so we need to guard against // their possibility int spurious_count = 0; while( true ){ wait(); if ( total_reserve == total_release ){ spurious_count++; if ( spurious_count > 1024 ){ waiting--; Debug.out( "AEMonitor: spurious wakeup limit exceeded" ); throw( new Throwable( "die die die" )); }else{ // Debug.out("AEMonitor: spurious wakeup, ignoring" ); } }else{ break; } } total_reserve++; }catch( Throwable e ){ // we know here that someone's got a finally clause to do the // balanced 'exit'. hence we should make it look as if we own it... waiting--; owner = current_thread; Debug.out( "**** monitor interrupted ****" ); throw( new RuntimeException("AEMonitor:interrupted" )); }finally{ last_waiter = null; } }else{ total_reserve++; dont_wait--; } owner = current_thread; } } } /* * Try and obtain it * @return true if got monitor, false otherwise */ public boolean enter( int max_millis ) { if ( DEBUG ){ debugEntry(); } Thread current_thread = Thread.currentThread(); synchronized( this ){ entry_count++; if ( owner == current_thread ){ nests++; }else{ if ( dont_wait == 0 ){ try{ waiting++; last_waiter = current_thread; wait( max_millis ); if ( total_reserve == total_release ){ // failed to obtain it, so we need to mark ourselves as no // longer waiting waiting--; return( false ); } total_reserve++; }catch( Throwable e ){ // we know here that someone's got a finally clause to do the // balanced 'exit'. hence we should make it look as if we own it... waiting--; owner = current_thread; Debug.out( "**** monitor interrupted ****" ); throw( new RuntimeException("AEMonitor:interrupted" )); }finally{ last_waiter = null; } }else{ total_reserve++; dont_wait--; } owner = current_thread; } } return( true ); } public void exit() { try{ synchronized( this ){ if ( nests > 0 ){ if ( DEBUG ){ if ( owner != Thread.currentThread()){ Debug.out( "nested exit but current thread not owner"); } } nests--; }else{ owner = null; total_release++; if ( waiting != 0 ){ waiting--; notify(); }else{ dont_wait++; if ( dont_wait > 1 ){ Debug.out( "**** AEMonitor '" + name + "': multiple exit detected" ); } } } } }finally{ if ( DEBUG ){ debugExit(); } } } public boolean isHeld() { return( owner == Thread.currentThread()); } public boolean hasWaiters() { synchronized( this ){ return( waiting > 0 ); } } public static Map getSynchronisedMap( Map m ) { return( Collections.synchronizedMap(m)); } }azureus-4.3.0.6/org/gudy/azureus2/core3/util/SHA1Simple.java0000644000175000017500000004456710450052360022671 0ustar adrianadrian /* * Created on Apr 12, 2004 * Created by Olivier Chalouhi * Modified Apr 13, 2004 by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.util.Arrays; import java.util.Random; /** * SHA-1 message digest class. */ public final class SHA1Simple { private int h0,h1,h2,h3,h4; private byte[] temp = new byte[64]; /** * Create a new SHA-1 message digest hasher. */ public SHA1Simple(){ } private void transform(byte[] M, int pos) { int w0 , w1 , w2 , w3 , w4 , w5 , w6 , w7 , w8 , w9 , w10, w11, w12, w13, w14, w15; int a,b,c,d,e; w0 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w1 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w2 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w3 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w4 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w5 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w6 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w7 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w8 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w9 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w10 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w11 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w12 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w13 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w14 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; w15 = (int)((((M[pos] & 0xff) << 24) |((M[pos+1] & 0xff) << 16) |((M[pos+2] & 0xff) << 8) |((M[pos+3] & 0xff) << 0))); pos+=4; a = h0 ; b = h1 ; c = h2 ; d = h3 ; e = h4; e += ((a << 5) | ( a >>> 27)) + w0 + ((b & c) | ((~b ) & d)) + 0x5A827999 ; b = (b << 30) | (b >>> 2) ; d += ((e << 5) | ( e >>> 27)) + w1 + ((a & b) | ((~a ) & c)) + 0x5A827999 ; a = (a << 30) | (a >>> 2) ; c += ((d << 5) | ( d >>> 27)) + w2 + ((e & a) | ((~e ) & b)) + 0x5A827999 ; e = (e << 30) | (e >>> 2) ; b += ((c << 5) | ( c >>> 27)) + w3 + ((d & e) | ((~d ) & a)) + 0x5A827999 ; d = (d << 30) | (d >>> 2) ; a += ((b << 5) | ( b >>> 27)) + w4 + ((c & d) | ((~c ) & e)) + 0x5A827999 ; c = (c << 30) | (c >>> 2) ; e += ((a << 5) | ( a >>> 27)) + w5 + ((b & c) | ((~b ) & d)) + 0x5A827999 ; b = (b << 30) | (b >>> 2) ; d += ((e << 5) | ( e >>> 27)) + w6 + ((a & b) | ((~a ) & c)) + 0x5A827999 ; a = (a << 30) | (a >>> 2) ; c += ((d << 5) | ( d >>> 27)) + w7 + ((e & a) | ((~e ) & b)) + 0x5A827999 ; e = (e << 30) | (e >>> 2) ; b += ((c << 5) | ( c >>> 27)) + w8 + ((d & e) | ((~d ) & a)) + 0x5A827999 ; d = (d << 30) | (d >>> 2) ; a += ((b << 5) | ( b >>> 27)) + w9 + ((c & d) | ((~c ) & e)) + 0x5A827999 ; c = (c << 30) | (c >>> 2) ; e += ((a << 5) | ( a >>> 27)) + w10 + ((b & c) | ((~b ) & d)) + 0x5A827999 ; b = (b << 30) | (b >>> 2) ; d += ((e << 5) | ( e >>> 27)) + w11 + ((a & b) | ((~a ) & c)) + 0x5A827999 ; a = (a << 30) | (a >>> 2) ; c += ((d << 5) | ( d >>> 27)) + w12 + ((e & a) | ((~e ) & b)) + 0x5A827999 ; e = (e << 30) | (e >>> 2) ; b += ((c << 5) | ( c >>> 27)) + w13 + ((d & e) | ((~d ) & a)) + 0x5A827999 ; d = (d << 30) | (d >>> 2) ; a += ((b << 5) | ( b >>> 27)) + w14 + ((c & d) | ((~c ) & e)) + 0x5A827999 ; c = (c << 30) | (c >>> 2) ; e += ((a << 5) | ( a >>> 27)) + w15 + ((b & c) | ((~b ) & d)) + 0x5A827999 ; b = (b << 30) | (b >>> 2) ; w0 = w13 ^ w8 ^ w2 ^ w0; w0 = (w0 << 1) | (w0 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w0 + ((a & b) | ((~a ) & c)) + 0x5A827999 ; a = (a << 30) | (a >>> 2) ; w1 = w14 ^ w9 ^ w3 ^ w1; w1 = (w1 << 1) | (w1 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w1 + ((e & a) | ((~e ) & b)) + 0x5A827999 ; e = (e << 30) | (e >>> 2) ; w2 = w15 ^ w10 ^ w4 ^ w2; w2 = (w2 << 1) | (w2 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w2 + ((d & e) | ((~d ) & a)) + 0x5A827999 ; d = (d << 30) | (d >>> 2) ; w3 = w0 ^ w11 ^ w5 ^ w3; w3 = (w3 << 1) | (w3 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w3 + ((c & d) | ((~c ) & e)) + 0x5A827999 ; c = (c << 30) | (c >>> 2) ; w4 = w1 ^ w12 ^ w6 ^ w4; w4 = (w4 << 1) | (w4 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w4 + (b ^ c ^ d) + 0x6ED9EBA1 ; b = (b << 30) | (b >>> 2) ; w5 = w2 ^ w13 ^ w7 ^ w5; w5 = (w5 << 1) | (w5 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w5 + (a ^ b ^ c) + 0x6ED9EBA1 ; a = (a << 30) | (a >>> 2) ; w6 = w3 ^ w14 ^ w8 ^ w6; w6 = (w6 << 1) | (w6 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w6 + (e ^ a ^ b) + 0x6ED9EBA1 ; e = (e << 30) | (e >>> 2) ; w7 = w4 ^ w15 ^ w9 ^ w7; w7 = (w7 << 1) | (w7 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w7 + (d ^ e ^ a) + 0x6ED9EBA1 ; d = (d << 30) | (d >>> 2) ; w8 = w5 ^ w0 ^ w10 ^ w8; w8 = (w8 << 1) | (w8 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w8 + (c ^ d ^ e) + 0x6ED9EBA1 ; c = (c << 30) | (c >>> 2) ; w9 = w6 ^ w1 ^ w11 ^ w9; w9 = (w9 << 1) | (w9 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w9 + (b ^ c ^ d) + 0x6ED9EBA1 ; b = (b << 30) | (b >>> 2) ; w10 = w7 ^ w2 ^ w12 ^ w10; w10 = (w10 << 1) | (w10 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w10 + (a ^ b ^ c) + 0x6ED9EBA1 ; a = (a << 30) | (a >>> 2) ; w11 = w8 ^ w3 ^ w13 ^ w11; w11 = (w11 << 1) | (w11 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w11 + (e ^ a ^ b) + 0x6ED9EBA1 ; e = (e << 30) | (e >>> 2) ; w12 = w9 ^ w4 ^ w14 ^ w12; w12 = (w12 << 1) | (w12 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w12 + (d ^ e ^ a) + 0x6ED9EBA1 ; d = (d << 30) | (d >>> 2) ; w13 = w10 ^ w5 ^ w15 ^ w13; w13 = (w13 << 1) | (w13 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w13 + (c ^ d ^ e) + 0x6ED9EBA1 ; c = (c << 30) | (c >>> 2) ; w14 = w11 ^ w6 ^ w0 ^ w14; w14 = (w14 << 1) | (w14 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w14 + (b ^ c ^ d) + 0x6ED9EBA1 ; b = (b << 30) | (b >>> 2) ; w15 = w12 ^ w7 ^ w1 ^ w15; w15 = (w15 << 1) | (w15 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w15 + (a ^ b ^ c) + 0x6ED9EBA1 ; a = (a << 30) | (a >>> 2) ; w0 = w13 ^ w8 ^ w2 ^ w0; w0 = (w0 << 1) | (w0 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w0 + (e ^ a ^ b) + 0x6ED9EBA1 ; e = (e << 30) | (e >>> 2) ; w1 = w14 ^ w9 ^ w3 ^ w1; w1 = (w1 << 1) | (w1 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w1 + (d ^ e ^ a) + 0x6ED9EBA1 ; d = (d << 30) | (d >>> 2) ; w2 = w15 ^ w10 ^ w4 ^ w2; w2 = (w2 << 1) | (w2 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w2 + (c ^ d ^ e) + 0x6ED9EBA1 ; c = (c << 30) | (c >>> 2) ; w3 = w0 ^ w11 ^ w5 ^ w3; w3 = (w3 << 1) | (w3 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w3 + (b ^ c ^ d) + 0x6ED9EBA1 ; b = (b << 30) | (b >>> 2) ; w4 = w1 ^ w12 ^ w6 ^ w4; w4 = (w4 << 1) | (w4 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w4 + (a ^ b ^ c) + 0x6ED9EBA1 ; a = (a << 30) | (a >>> 2) ; w5 = w2 ^ w13 ^ w7 ^ w5; w5 = (w5 << 1) | (w5 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w5 + (e ^ a ^ b) + 0x6ED9EBA1 ; e = (e << 30) | (e >>> 2) ; w6 = w3 ^ w14 ^ w8 ^ w6; w6 = (w6 << 1) | (w6 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w6 + (d ^ e ^ a) + 0x6ED9EBA1 ; d = (d << 30) | (d >>> 2) ; w7 = w4 ^ w15 ^ w9 ^ w7; w7 = (w7 << 1) | (w7 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w7 + (c ^ d ^ e) + 0x6ED9EBA1 ; c = (c << 30) | (c >>> 2) ; w8 = w5 ^ w0 ^ w10 ^ w8; w8 = (w8 << 1) | (w8 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w8 + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ; b = (b << 30) | (b >>> 2) ; w9 = w6 ^ w1 ^ w11 ^ w9; w9 = (w9 << 1) | (w9 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w9 + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC ; a = (a << 30) | (a >>> 2) ; w10 = w7 ^ w2 ^ w12 ^ w10; w10 = (w10 << 1) | (w10 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w10 + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC ; e = (e << 30) | (e >>> 2) ; w11 = w8 ^ w3 ^ w13 ^ w11; w11 = (w11 << 1) | (w11 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w11 + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC ; d = (d << 30) | (d >>> 2) ; w12 = w9 ^ w4 ^ w14 ^ w12; w12 = (w12 << 1) | (w12 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w12 + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC ; c = (c << 30) | (c >>> 2) ; w13 = w10 ^ w5 ^ w15 ^ w13; w13 = (w13 << 1) | (w13 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w13 + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ; b = (b << 30) | (b >>> 2) ; w14 = w11 ^ w6 ^ w0 ^ w14; w14 = (w14 << 1) | (w14 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w14 + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC ; a = (a << 30) | (a >>> 2) ; w15 = w12 ^ w7 ^ w1 ^ w15; w15 = (w15 << 1) | (w15 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w15 + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC ; e = (e << 30) | (e >>> 2) ; w0 = w13 ^ w8 ^ w2 ^ w0; w0 = (w0 << 1) | (w0 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w0 + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC ; d = (d << 30) | (d >>> 2) ; w1 = w14 ^ w9 ^ w3 ^ w1; w1 = (w1 << 1) | (w1 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w1 + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC ; c = (c << 30) | (c >>> 2) ; w2 = w15 ^ w10 ^ w4 ^ w2; w2 = (w2 << 1) | (w2 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w2 + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ; b = (b << 30) | (b >>> 2) ; w3 = w0 ^ w11 ^ w5 ^ w3; w3 = (w3 << 1) | (w3 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w3 + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC ; a = (a << 30) | (a >>> 2) ; w4 = w1 ^ w12 ^ w6 ^ w4; w4 = (w4 << 1) | (w4 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w4 + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC ; e = (e << 30) | (e >>> 2) ; w5 = w2 ^ w13 ^ w7 ^ w5; w5 = (w5 << 1) | (w5 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w5 + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC ; d = (d << 30) | (d >>> 2) ; w6 = w3 ^ w14 ^ w8 ^ w6; w6 = (w6 << 1) | (w6 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w6 + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC ; c = (c << 30) | (c >>> 2) ; w7 = w4 ^ w15 ^ w9 ^ w7; w7 = (w7 << 1) | (w7 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w7 + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC ; b = (b << 30) | (b >>> 2) ; w8 = w5 ^ w0 ^ w10 ^ w8; w8 = (w8 << 1) | (w8 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w8 + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC ; a = (a << 30) | (a >>> 2) ; w9 = w6 ^ w1 ^ w11 ^ w9; w9 = (w9 << 1) | (w9 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w9 + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC ; e = (e << 30) | (e >>> 2) ; w10 = w7 ^ w2 ^ w12 ^ w10; w10 = (w10 << 1) | (w10 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w10 + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC ; d = (d << 30) | (d >>> 2) ; w11 = w8 ^ w3 ^ w13 ^ w11; w11 = (w11 << 1) | (w11 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w11 + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC ; c = (c << 30) | (c >>> 2) ; w12 = w9 ^ w4 ^ w14 ^ w12; w12 = (w12 << 1) | (w12 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w12 + (b ^ c ^ d) + 0xCA62C1D6 ; b = (b << 30) | (b >>> 2) ; w13 = w10 ^ w5 ^ w15 ^ w13; w13 = (w13 << 1) | (w13 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w13 + (a ^ b ^ c) + 0xCA62C1D6 ; a = (a << 30) | (a >>> 2) ; w14 = w11 ^ w6 ^ w0 ^ w14; w14 = (w14 << 1) | (w14 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w14 + (e ^ a ^ b) + 0xCA62C1D6 ; e = (e << 30) | (e >>> 2) ; w15 = w12 ^ w7 ^ w1 ^ w15; w15 = (w15 << 1) | (w15 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w15 + (d ^ e ^ a) + 0xCA62C1D6 ; d = (d << 30) | (d >>> 2) ; w0 = w13 ^ w8 ^ w2 ^ w0; w0 = (w0 << 1) | (w0 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w0 + (c ^ d ^ e) + 0xCA62C1D6 ; c = (c << 30) | (c >>> 2) ; w1 = w14 ^ w9 ^ w3 ^ w1; w1 = (w1 << 1) | (w1 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w1 + (b ^ c ^ d) + 0xCA62C1D6 ; b = (b << 30) | (b >>> 2) ; w2 = w15 ^ w10 ^ w4 ^ w2; w2 = (w2 << 1) | (w2 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w2 + (a ^ b ^ c) + 0xCA62C1D6 ; a = (a << 30) | (a >>> 2) ; w3 = w0 ^ w11 ^ w5 ^ w3; w3 = (w3 << 1) | (w3 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w3 + (e ^ a ^ b) + 0xCA62C1D6 ; e = (e << 30) | (e >>> 2) ; w4 = w1 ^ w12 ^ w6 ^ w4; w4 = (w4 << 1) | (w4 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w4 + (d ^ e ^ a) + 0xCA62C1D6 ; d = (d << 30) | (d >>> 2) ; w5 = w2 ^ w13 ^ w7 ^ w5; w5 = (w5 << 1) | (w5 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w5 + (c ^ d ^ e) + 0xCA62C1D6 ; c = (c << 30) | (c >>> 2) ; w6 = w3 ^ w14 ^ w8 ^ w6; w6 = (w6 << 1) | (w6 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w6 + (b ^ c ^ d) + 0xCA62C1D6 ; b = (b << 30) | (b >>> 2) ; w7 = w4 ^ w15 ^ w9 ^ w7; w7 = (w7 << 1) | (w7 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w7 + (a ^ b ^ c) + 0xCA62C1D6 ; a = (a << 30) | (a >>> 2) ; w8 = w5 ^ w0 ^ w10 ^ w8; w8 = (w8 << 1) | (w8 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w8 + (e ^ a ^ b) + 0xCA62C1D6 ; e = (e << 30) | (e >>> 2) ; w9 = w6 ^ w1 ^ w11 ^ w9; w9 = (w9 << 1) | (w9 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w9 + (d ^ e ^ a) + 0xCA62C1D6 ; d = (d << 30) | (d >>> 2) ; w10 = w7 ^ w2 ^ w12 ^ w10; w10 = (w10 << 1) | (w10 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w10 + (c ^ d ^ e) + 0xCA62C1D6 ; c = (c << 30) | (c >>> 2) ; w11 = w8 ^ w3 ^ w13 ^ w11; w11 = (w11 << 1) | (w11 >>> 31) ; e += ((a << 5) | ( a >>> 27)) + w11 + (b ^ c ^ d) + 0xCA62C1D6 ; b = (b << 30) | (b >>> 2) ; w12 = w9 ^ w4 ^ w14 ^ w12; w12 = (w12 << 1) | (w12 >>> 31) ; d += ((e << 5) | ( e >>> 27)) + w12 + (a ^ b ^ c) + 0xCA62C1D6 ; a = (a << 30) | (a >>> 2) ; w13 = w10 ^ w5 ^ w15 ^ w13; w13 = (w13 << 1) | (w13 >>> 31) ; c += ((d << 5) | ( d >>> 27)) + w13 + (e ^ a ^ b) + 0xCA62C1D6 ; e = (e << 30) | (e >>> 2) ; w14 = w11 ^ w6 ^ w0 ^ w14; w14 = (w14 << 1) | (w14 >>> 31) ; b += ((c << 5) | ( c >>> 27)) + w14 + (d ^ e ^ a) + 0xCA62C1D6 ; d = (d << 30) | (d >>> 2) ; w15 = w12 ^ w7 ^ w1 ^ w15; w15 = (w15 << 1) | (w15 >>> 31) ; a += ((b << 5) | ( b >>> 27)) + w15 + (c ^ d ^ e) + 0xCA62C1D6 ; c = (c << 30) | (c >>> 2) ; h0 += a; h1 += b; h2 += c; h3 += d; h4 += e; } public byte[] calculateHash( byte[] buffer ) { return( calculateHash( buffer, 0, buffer.length )); } public byte[] calculateHash( final byte[] buffer, final int offset, final int length ) { h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; h4 = 0xC3D2E1F0; int pos = offset; int rem = length; while( rem >= 64) { transform( buffer, pos ); pos += 64; rem -= 64; } if ( rem > 0 ){ System.arraycopy( buffer, pos, temp, 0, rem ); pos = rem; }else{ pos = 0; } temp[pos++] = ((byte)0x80); if ( pos > 56 ){ for (int i=pos;i<64;i++){ temp[i] = 0; } transform( temp, 0 ); pos = 0; } for (int i=pos;i<56;i++){ temp[i] = 0; } long l = length << 3; temp[56] = (byte)(l >> 56); temp[57] = (byte)(l >> 48); temp[58] = (byte)(l >> 40); temp[59] = (byte)(l >> 32); temp[60] = (byte)(l >> 24); temp[61] = (byte)(l >> 16); temp[62] = (byte)(l >> 8); temp[63] = (byte)(l); transform( temp, 0 ); byte[] result = new byte[20]; result[0] = (byte)(h0>>24); result[1] = (byte)(h0>>16); result[2] = (byte)(h0>>8); result[3] = (byte)(h0>>0); result[4] = (byte)(h1>>24); result[5] = (byte)(h1>>16); result[6] = (byte)(h1>>8); result[7] = (byte)(h1>>0); result[8] = (byte)(h2>>24); result[9] = (byte)(h2>>16); result[10] = (byte)(h2>>8); result[11] = (byte)(h2>>0); result[12] = (byte)(h3>>24); result[13] = (byte)(h3>>16); result[14] = (byte)(h3>>8); result[15] = (byte)(h3>>0); result[16] = (byte)(h4>>24); result[17] = (byte)(h4>>16); result[18] = (byte)(h4>>8); result[19] = (byte)(h4>>0); return( result ); } public static void main( String[] args ) { SHA1Hasher s1 = new SHA1Hasher(); SHA1Simple s2 = new SHA1Simple(); Random r = new Random(); for (int i=0;i<10000;i++){ int len = r.nextInt(32); byte[] x = new byte[len]; r.nextBytes( x ); byte[] h1 = s1.calculateHash( x ); byte[] h2 = s2.calculateHash( x ); if ( Arrays.equals( h1, h2)){ System.out.println( ByteFormatter.nicePrint( h1 ) + " - " + ByteFormatter.nicePrint( x )); }else{ System.out.println( "arghh" ); return; } } System.out.println( "End" ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/AEMonitor2.java0000644000175000017500000000351211163305126022726 0ustar adrianadrian/* * Created on 18-Sep-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; /** * @author parg * */ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; public class AEMonitor2 { ReentrantLock lock = new ReentrantLock(); public AEMonitor2( String _name ) { } public void enter() { lock.lock(); } /* * Try and obtain it * @return true if got monitor, false otherwise */ public boolean enter( int max_millis ) { try{ if ( lock.tryLock( max_millis, TimeUnit.MILLISECONDS )){ return( true ); }else{ return( false ); } }catch( Throwable e ){ Debug.out( e ); return( false ); } } public void exit() { try{ lock.unlock(); }finally{ } } public boolean isHeld() { return( lock.isHeldByCurrentThread()); } public boolean hasWaiters() { return( lock.getQueueLength() > 0 ); } }azureus-4.3.0.6/org/gudy/azureus2/core3/util/TimeLimitedTask.java0000644000175000017500000000415111021627464024045 0ustar adrianadrian/* * Created on Jun 4, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.core3.util; import org.gudy.azureus2.core3.security.SESecurityManager; public class TimeLimitedTask { private String name; private int max_millis; private int priority; private task t; public TimeLimitedTask( String _name, int _max_millis, int _priority, task _t ) { name = _name; max_millis = _max_millis; priority = _priority; t = _t; } public Object run() throws Throwable { final Object[] result = { null }; final AESemaphore sem = new AESemaphore( name ); final Thread thread = new Thread( name ) { public void run() { try{ result[0] = t.run(); }catch( Throwable e ){ result[0] = e; }finally{ sem.releaseForever(); } } }; DelayedEvent ev = new DelayedEvent( name, max_millis, new AERunnable() { public void runSupport() { if ( !sem.isReleasedForever()){ SESecurityManager.stopThread( thread ); } } }); thread.setPriority( priority ); thread.start(); sem.reserve(); ev.cancel(); if ( result[0] instanceof Throwable ){ throw((Throwable)result[0] ); } return( result[0] ); } public interface task { public Object run() throws Exception; } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/HashWrapper2.java0000644000175000017500000000421211017174732023320 0ustar adrianadrian/* * Created on May 27, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.core3.util; /** * This class DOES NOT COPY THE UNDERLYING BYTES AND ONLY SUPPORTS Short.MAX_VALUE bytes * @author Azureus * */ public class HashWrapper2 { final private byte[] hash; final private short offset; final private short length; final private int hash_code; public HashWrapper2( byte[] hash ) { this( hash, 0, hash.length ); } public HashWrapper2( byte[] _hash, int _offset, int _length ) { if ( _offset >= Short.MAX_VALUE ){ throw( new RuntimeException( "Illegal value - offset too large" )); } if ( _length >= Short.MAX_VALUE ){ throw( new RuntimeException( "Illegal value - length too large" )); } hash = _hash; offset = (short)_offset; length = (short)_length; int hc = 0; for (int i=offset; i nbElements - 2 ){ slots = nbElements - 2; } if ( slots == 1 ){ return( getPointValue()); } long res = getSum(slots) / ( period * slots / ( nbElements - 2 )); return( res ); } public synchronized long getPointValue() { long timeFactor = getEffectiveTime() / refreshRate; //We first update the buffer update(timeFactor); return(values != null ? values[(int)((timeFactor-1)% nbElements)] : 0); } protected synchronized final long getSum() { //The sum of all elements used for the average. long sum = 0; if(values != null) { //We get the current timeFactor long timeFactor = getEffectiveTime() / refreshRate; //We first update the buffer update(timeFactor); //Starting on oldest one (the one after the next one) //Ending on last one fully updated (the one previous current one) for (long i = timeFactor + 2; i < timeFactor + nbElements; i++) { //Simple addition sum += values[(int) (i % nbElements)]; } } //We return the sum divided by the period return(sum); } protected synchronized final long getSum(int slots) { //We get the current timeFactor long timeFactor = getEffectiveTime() / refreshRate; //We first update the buffer update(timeFactor); //The sum of all elements used for the average. long sum = 0; if ( slots < 1 ){ slots = 1; }else if ( slots > nbElements-2 ){ slots = nbElements-2; } //Starting on oldest one (the one after the next one) //Ending on last one fully updated (the one previous current one) long end_slot = timeFactor + nbElements; long start_slot = end_slot - slots; if (values != null) for (long i = start_slot; i < end_slot; i++) { sum += values[(int) (i % nbElements)]; } //We return the sum divided by the period return(sum); } protected long getEffectiveTime() { return( SystemTime.getSteppedMonotonousTime()); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/Constants.java0000644000175000017500000002354511310376442022776 0ustar adrianadrian/* * Created on 16 juin 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.nio.charset.Charset; import java.util.Locale; import java.util.StringTokenizer; /** * * @author Olivier * */ public class Constants { public static final String EMPTY_STRING = ""; public static final String SF_WEB_SITE = "http://azureus.sourceforge.net/"; public static final String AELITIS_TORRENTS = "http://torrent.vuze.com:88/torrents/"; public static final String AELITIS_FILES = "http://torrent.vuze.com:88/files/"; public static final String AZUREUS_WIKI = "http://wiki.vuze.com/index.php/"; public static final String VERSION_SERVER_V4 = "version.vuze.com"; public static final String VERSION_SERVER_V6 = "version6.vuze.com"; public static final String DHT_SEED_ADDRESS_V4 = "dht.vuze.com"; public static final String DHT_SEED_ADDRESS_V6 = "dht6.vuze.com"; public static final String NAT_TEST_SERVER = "nettest.vuze.com"; public static final String NAT_TEST_SERVER_HTTP = "http://nettest.vuze.com/"; public static final String SPEED_TEST_SERVER = "speedtest.vuze.com"; public static final String PAIRING_URL = "http://pair.vuze.com/pairing"; public static final String[] AZUREUS_DOMAINS = { "azureusplatform.com", "azureus.com", "aelitis.com", "vuze.com" }; public static final String DEFAULT_ENCODING = "UTF8"; public static final String BYTE_ENCODING = "ISO-8859-1"; public static Charset BYTE_CHARSET; public static Charset DEFAULT_CHARSET; static{ try{ BYTE_CHARSET = Charset.forName( Constants.BYTE_ENCODING ); DEFAULT_CHARSET = Charset.forName( Constants.DEFAULT_ENCODING ); }catch( Throwable e ){ e.printStackTrace(); } } public static final Locale LOCALE_ENGLISH = new Locale("en", ""); public static final String INFINITY_STRING = "\u221E"; // "oo";pa public static final int CRAPPY_INFINITY_AS_INT = 365*24*3600; // seconds (365days) public static final long CRAPPY_INFINITE_AS_LONG = 10000*365*24*3600; // seconds (10k years) // keep the CVS style constant coz version checkers depend on it! // e.g. 2.0.8.3 // 2.0.8.3_CVS // 2.0.8.3_Bnn // incremental build public static String APP_NAME = "Vuze"; public static final String AZUREUS_NAME = "Azureus"; public static final String AZUREUS_VERSION = "4.3.0.6"; //4.3.0.7_CVS public static final byte[] VERSION_ID = ("-" + "AZ" + "4306" + "-").getBytes(); //MUST be 8 chars long! private static final boolean FORCE_NON_CVS = System.getProperty( "az.force.noncvs", "0" ).equals( "1" ); public static final boolean IS_CVS_VERSION = isCVSVersion( AZUREUS_VERSION ) && !FORCE_NON_CVS; public static final String OSName = System.getProperty("os.name"); public static final boolean isOSX = OSName.toLowerCase().startsWith("mac os"); public static final boolean isLinux = OSName.equalsIgnoreCase("Linux"); public static final boolean isSolaris = OSName.equalsIgnoreCase("SunOS"); public static final boolean isFreeBSD = OSName.equalsIgnoreCase("FreeBSD"); public static final boolean isWindowsXP = OSName.equalsIgnoreCase("Windows XP"); public static final boolean isWindowsVista = OSName.equalsIgnoreCase("Windows Vista"); public static final boolean isWindows95 = OSName.equalsIgnoreCase("Windows 95"); public static final boolean isWindows98 = OSName.equalsIgnoreCase("Windows 98"); public static final boolean isWindows2000 = OSName.equalsIgnoreCase("Windows 2000"); public static final boolean isWindowsME = OSName.equalsIgnoreCase("Windows ME"); public static final boolean isWindows9598ME = isWindows95 || isWindows98 || isWindowsME; public static boolean isSafeMode = false; public static final boolean isWindows = OSName.toLowerCase().startsWith("windows"); // If it isn't windows or osx, it's most likely an unix flavor public static final boolean isUnix = !isWindows && !isOSX; public static final boolean isWindowsVistaOrHigher; static{ if ( isWindows ){ Float ver = null; try{ ver = new Float( System.getProperty( "os.version" )); }catch (Throwable e){ } isWindowsVistaOrHigher = ver != null && ver.floatValue() >= 6; }else{ isWindowsVistaOrHigher = false; } } public static final boolean isOSX_10_5_OrHigher; public static final boolean isOSX_10_6_OrHigher; static{ if ( isOSX ){ int first_digit = 0; int second_digit = 0; try{ String os_version = System.getProperty( "os.version" ); String[] bits = os_version.split( "\\." ); first_digit = Integer.parseInt( bits[0] ); if ( bits.length > 1 ){ second_digit = Integer.parseInt( bits[1] ); } }catch( Throwable e ){ } isOSX_10_5_OrHigher = first_digit > 10 || ( first_digit == 10 && second_digit >= 5 ); isOSX_10_6_OrHigher = first_digit > 10 || ( first_digit == 10 && second_digit >= 6 ); }else{ isOSX_10_5_OrHigher = false; isOSX_10_6_OrHigher = false; } } public static final String JAVA_VERSION = System.getProperty("java.version"); public static final String FILE_WILDCARD = isWindows?"*.*":"*"; /** * Gets the current version, or if a CVS version, the one on which it is based * @return */ public static String getBaseVersion() { return( getBaseVersion( AZUREUS_VERSION )); } public static String getBaseVersion( String version ) { int p1 = version.indexOf("_"); // _CVS or _Bnn if ( p1 == -1 ){ return( version ); } return( version.substring(0,p1)); } /** * is this a formal build or CVS/incremental * @return */ public static boolean isCVSVersion() { return IS_CVS_VERSION; } public static boolean isCVSVersion( String version ) { return( version.indexOf("_") != -1 ); } /** * For CVS builds this returns the incremental build number. For people running their own * builds this returns -1 * @return */ public static int getIncrementalBuild() { return( getIncrementalBuild( AZUREUS_VERSION )); } public static int getIncrementalBuild( String version ) { if ( !isCVSVersion(version)){ return( 0 ); } int p1 = version.indexOf( "_B" ); if ( p1 == -1 ){ return( -1 ); } try{ return( Integer.parseInt( version.substring(p1+2))); }catch( Throwable e ){ System.out.println("can't parse version"); return( -1 ); } } /** * compare two version strings of form n.n.n.n (e.g. 1.2.3.4) * @param version_1 * @param version_2 * @return -ve -> version_1 lower, 0 = same, +ve -> version_1 higher */ public static int compareVersions( String version_1, String version_2 ) { try{ if ( version_1.startsWith("." )){ version_1 = "0" + version_1; } if ( version_2.startsWith("." )){ version_2 = "0" + version_2; } version_1 = version_1.replaceAll("[^0-9.]", "."); version_2 = version_2.replaceAll("[^0-9.]", "."); StringTokenizer tok1 = new StringTokenizer(version_1,"."); StringTokenizer tok2 = new StringTokenizer(version_2,"."); while( true ){ if ( tok1.hasMoreTokens() && tok2.hasMoreTokens()){ int i1 = Integer.parseInt(tok1.nextToken()); int i2 = Integer.parseInt(tok2.nextToken()); if ( i1 != i2 ){ return( i1 - i2 ); } }else if ( tok1.hasMoreTokens()){ int i1 = Integer.parseInt(tok1.nextToken()); if ( i1 != 0 ){ return( 1 ); } }else if ( tok2.hasMoreTokens()){ int i2 = Integer.parseInt(tok2.nextToken()); if ( i2 != 0 ){ return( -1 ); } }else{ return( 0 ); } } }catch( Throwable e ){ Debug.printStackTrace(e); return( 0 ); } } public static boolean isValidVersionFormat( String version ) { if ( version == null || version.length() == 0 ){ return( false ); } for (int i=0;i" + entry.getValue(); } System.out.println( "HB allocs: " + str ); } } }); } }else{ MIN_POOL = MAX_POOL = 0; pools = null; pool_sizes = null; } } protected DirectByteBuffer getBufferSupport( byte allocator, int length ) { if ( USE_POOLS ){ if ( TRACE ){ synchronized( sizes ){ Integer key = new Integer( length/32*32 ); Integer count = (Integer)sizes.get( key ); if ( count == null ){ sizes.put( key, new Integer(1)); }else{ sizes.put( key, new Integer( count.intValue() + 1 )); } } } int pool_index = getPoolIndex( length ); if ( pool_index != -1 ){ LinkedList pool = pools[pool_index]; synchronized( pool ){ if ( !pool.isEmpty()){ Object[] entry = (Object[])pool.removeLast(); ByteBuffer buff = (ByteBuffer)entry[0]; buff.clear(); buff.limit( length ); return( new DirectByteBuffer( allocator, buff, this )); } } DirectByteBuffer buffer = new DirectByteBuffer( allocator, ByteBuffer.allocate( pool_sizes[pool_index] ), this ); ByteBuffer buff = buffer.getBufferInternal(); buff.limit( length ); return( buffer ); }else{ return( new DirectByteBuffer( allocator, ByteBuffer.allocate( length ), this )); } }else{ return( new DirectByteBuffer( allocator, ByteBuffer.allocate( length ), this )); } } protected void returnBufferSupport( DirectByteBuffer buffer ) { if ( USE_POOLS ){ ByteBuffer buff = buffer.getBufferInternal(); int length = buff.capacity(); int pool_index = getPoolIndex( length ); if ( pool_index != -1 ){ LinkedList pool = pools[pool_index]; synchronized( pool ){ pool.addLast( new Object[]{ buff }); } } } } protected int getPoolIndex( int length ) { if ( length < MIN_POOL|| length > MAX_POOL ){ return( -1 ); } for (int i=0;i> headers = new HashMap>(); protected AZPluginConnection( URL _url ) { super( _url ); } public void connect() throws IOException { String url = getURL().toString(); int pos = url.indexOf( "?" ); if ( pos == -1 ){ throw( new IOException( "Malformed URL - ? missing" )); } url = url.substring( pos+1 ); String[] bits = url.split( "&" ); Map args = new HashMap(); for (int i=0;i> getHeaderFields() { return( headers ); } public String getHeaderField( String name ) { List values = headers.get( name ); if ( values == null || values.size() == 0 ){ return( null ); } return( values.get( values.size()-1 )); } public void setHeaderField( String name, String value ) { List values = headers.get( name ); if ( values == null ){ values = new ArrayList(); headers.put( name, values ); } values.add( value ); } public InputStream getInputStream() throws IOException { return( input_stream ); } public void setResponse( int _code, String _msg ) { response_code = _code; response_msg = _msg; } public int getResponseCode() { return( response_code ); } public String getResponseMessage() { return( response_msg ); } public boolean usingProxy() { return( false ); } public void disconnect() { } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/udp/0000755000175000017500000000000011310377634022603 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/udp/Handler.java0000644000175000017500000000204410123371014025006 0ustar adrianadrian/* * File : Handler.java * Created : 19-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.protocol.udp; /** * @author parg * */ import java.net.*; public class Handler extends URLStreamHandler { public URLConnection openConnection(URL u) { return new UDPURLConnection(u); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/udp/UDPURLConnection.java0000644000175000017500000000223610003133716026471 0ustar adrianadrian/* * File : UDPURLConnection.java * Created : 19-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.protocol.udp; /** * @author parg * */ import java.net.URL; import java.net.URLConnection; import java.io.*; class UDPURLConnection extends URLConnection { UDPURLConnection( URL u ) { super(u); } public void connect() throws IOException { throw( new IOException( "Not Implemented")); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/magnet/0000755000175000017500000000000011310377634023266 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/magnet/Handler.java0000644000175000017500000000234111305630416025500 0ustar adrianadrian/* * File : Handler.java * Created : 19-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.protocol.magnet; /** * @author parg * */ import java.net.*; public class Handler extends URLStreamHandler { public URLConnection openConnection(URL u) { // some anti-virus apps blocking loopback connection we initially used // in MagnetConnection so created variant based on direct communication to // the magnet handler return( new MagnetConnection2( u )); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/magnet/MagnetConnection.java0000644000175000017500000000574611305645002027367 0ustar adrianadrian/* * Created on 06-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util.protocol.magnet; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.Socket; import java.net.URL; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.net.magneturi.MagnetURIHandler; /** * @author parg * */ public class MagnetConnection extends HttpURLConnection { private Socket socket; private static final String NL = "\r\n"; private String status = ""; protected MagnetConnection( URL _url ) { super( _url ); } public void connect() throws IOException { socket = new Socket( "127.0.0.1", MagnetURIHandler.getSingleton().getPort()); String get = "GET " + "/download/" + getURL().toString().substring( 7 ) + " HTTP/1.0" + NL + NL; socket.getOutputStream().write( get.getBytes()); socket.getOutputStream().flush(); } public InputStream getInputStream() throws IOException { InputStream is = socket.getInputStream(); String line = ""; byte[] buffer = new byte[1]; byte[] line_bytes = new byte[2048]; int line_bytes_pos = 0; while(true){ int len = is.read( buffer ); if ( len == -1 ){ break; } line += (char)buffer[0]; line_bytes[line_bytes_pos++] = buffer[0]; if ( line.endsWith( NL )){ line = line.trim(); if ( line.length() == 0 ){ break; } if ( line.startsWith( "X-Report:")){ line = new String( line_bytes, 0, line_bytes_pos, "UTF-8" ); line = line.substring( 9 ); line = line.trim(); status = Character.toUpperCase( line.charAt(0)) + line.substring(1); } line = ""; line_bytes_pos = 0; } } return( is ); } public int getResponseCode() { return( HTTP_OK ); } public String getResponseMessage() { return( status ); } public boolean usingProxy() { return( false ); } public void disconnect() { try{ socket.close(); }catch( Throwable e ){ Debug.printStackTrace(e); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/magnet/MagnetConnection2.java0000644000175000017500000000752311306135602027445 0ustar adrianadrian/* * Created on 06-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util.protocol.magnet; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.net.magneturi.MagnetURIHandler; /** * @author parg * */ public class MagnetConnection2 extends HttpURLConnection { private static final String NL = "\r\n"; private OutputStream output_stream; private InputStream input_stream; private LinkedList status_list = new LinkedList(); protected MagnetConnection2( URL _url ) { super( _url ); } public void connect() throws IOException { String get = "/download/" + getURL().toString().substring( 7 ) + " HTTP/1.0" + NL + NL; PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(); pis.connect( pos ); input_stream = pis; output_stream = pos; MagnetURIHandler.getSingleton().process( get, new ByteArrayInputStream(new byte[0]), pos ); } public InputStream getInputStream() throws IOException { String line = ""; byte[] buffer = new byte[1]; byte[] line_bytes = new byte[2048]; int line_bytes_pos = 0; while(true){ int len = input_stream.read( buffer ); if ( len == -1 ){ break; } line += (char)buffer[0]; line_bytes[line_bytes_pos++] = buffer[0]; if ( line.endsWith( NL )){ line = line.trim(); if ( line.length() == 0 ){ break; } if ( line.startsWith( "X-Report:")){ line = new String( line_bytes, 0, line_bytes_pos, "UTF-8" ); line = line.substring( 9 ); line = line.trim(); synchronized( status_list ){ String str = Character.toUpperCase( line.charAt(0)) + line.substring(1); if ( status_list.size() == 0 ){ status_list.addLast( str ); }else if ( !status_list.getLast().equals( str )){ status_list.addLast( str ); } } } line = ""; line_bytes_pos = 0; } } return( input_stream ); } public int getResponseCode() { return( HTTP_OK ); } public String getResponseMessage() { synchronized( status_list ){ if ( status_list.size() == 0 ){ return( "" ); }else if ( status_list.size() == 1 ){ return( status_list.get( 0 )); }else{ return( status_list.removeFirst()); } } } public boolean usingProxy() { return( false ); } public void disconnect() { try{ output_stream.close(); }catch( Throwable e ){ Debug.printStackTrace(e); } try{ input_stream.close(); }catch( Throwable e ){ Debug.printStackTrace(e); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/socks5/0000755000175000017500000000000011310377634023222 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/socks5/Handler.java0000644000175000017500000000205210371433512025433 0ustar adrianadrian/* * File : Handler.java * Created : 19-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.protocol.socks5; /** * @author parg * */ import java.net.*; public class Handler extends URLStreamHandler { public URLConnection openConnection(URL u) { return new Socks5URLConnection(u); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/socks5/Socks5URLConnection.java0000644000175000017500000000224710371433512027636 0ustar adrianadrian/* * File : UDPURLConnection.java * Created : 19-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.protocol.socks5; /** * @author parg * */ import java.net.URL; import java.net.URLConnection; import java.io.*; class Socks5URLConnection extends URLConnection { Socks5URLConnection( URL u ) { super(u); } public void connect() throws IOException { throw( new IOException( "Not Implemented")); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/tcp/0000755000175000017500000000000011310377634022601 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/tcp/Handler.java0000644000175000017500000000204411145166426025022 0ustar adrianadrian/* * File : Handler.java * Created : 19-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.protocol.tcp; /** * @author parg * */ import java.net.*; public class Handler extends URLStreamHandler { public URLConnection openConnection(URL u) { return new TCPURLConnection(u); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/tcp/TCPURLConnection.java0000644000175000017500000000223611145166426026501 0ustar adrianadrian/* * File : UDPURLConnection.java * Created : 19-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.protocol.tcp; /** * @author parg * */ import java.net.URL; import java.net.URLConnection; import java.io.*; class TCPURLConnection extends URLConnection { TCPURLConnection( URL u ) { super(u); } public void connect() throws IOException { throw( new IOException( "Not Implemented")); } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/AzURLStreamHandlerFactory.java0000644000175000017500000000332411034214250027602 0ustar adrianadrian/** * Copyright (C) 2008 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros 8 Allee Lenotre, La Grille Royale, * 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util.protocol; import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; /** * @author Aaron Grunthal * @create 30.03.2008 */ public class AzURLStreamHandlerFactory implements URLStreamHandlerFactory { private static final String packageName = AzURLStreamHandlerFactory.class.getPackage().getName(); public URLStreamHandler createURLStreamHandler(String protocol) { // don't do classloading when called for protocols that are involved in classloading if(protocol.equals("file") || protocol.equals("jar")) return null; String clsName = packageName + "." + protocol + ".Handler"; try { Class cls = Class.forName(clsName); return (URLStreamHandler) cls.newInstance(); } catch (Throwable e) { // URLs are involved in classloading, evil things might happen } return null; } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/i2p/0000755000175000017500000000000011310377634022505 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/i2p/Handler.java0000644000175000017500000000260110160567050024717 0ustar adrianadrian/* * File : Handler.java * Created : 19-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.protocol.i2p; /** * @author parg * */ import java.io.IOException; import java.net.*; import org.gudy.azureus2.core3.util.Debug; public class Handler extends URLStreamHandler { public URLConnection openConnection(URL u) { String str = u.toString(); str = "http" + str.substring( 3 ); try{ return( new URL(str).openConnection()); }catch( MalformedURLException e ){ Debug.printStackTrace(e); return( null ); }catch( IOException e ){ Debug.printStackTrace(e); return( null ); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/dht/0000755000175000017500000000000011310377634022572 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/util/protocol/dht/Handler.java0000644000175000017500000000441411034570522025007 0ustar adrianadrian/* * File : Handler.java * Created : 19-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util.protocol.dht; /** * @author parg * */ import java.io.IOException; import java.net.*; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; public class Handler extends URLStreamHandler { public URLConnection openConnection(URL u) { // format is dht://[.dht]/[params] // treat as magnet magnet:?xt=urn:btih:/params URL magnet_url; try{ String str = u.toString(); str = str.substring( 6 ); int param_pos = str.indexOf( '/' ); String hash = param_pos==-1?str:str.substring( 0, param_pos ); hash = hash.trim(); int dot_pos = hash.indexOf( '.' ); if ( dot_pos != -1 ){ hash = hash.substring( 0, dot_pos ).trim(); } if ( hash.length() == 40 ){ hash = Base32.encode( ByteFormatter.decodeString( hash )); } magnet_url = new URL( "magnet:?xt=urn:btih:" + hash + "/" + (param_pos==-1?"":str.substring(param_pos+1))); }catch( Throwable e ){ Debug.out( "Failed to transform dht url '" + u + "'", e ); return( null ); } // System.out.println( "Transformed " + u + " -> " + magnet_url ); try{ return( magnet_url.openConnection()); }catch( MalformedURLException e ){ Debug.printStackTrace(e); return( null ); }catch( IOException e ){ Debug.printStackTrace(e); return( null ); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/DirectByteBufferPoolReal.java0000644000175000017500000006530311165353362025652 0ustar adrianadrian/* * Created on Nov 4, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.core3.util; import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import com.aelitis.azureus.core.diskmanager.cache.CacheFileManager; import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerFactory; import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerStats; public class DirectByteBufferPoolReal extends DirectByteBufferPool { private static final boolean disable_gc = System.getProperty( "az.disable.explicit.gc", "0" ).equals( "1" ); static{ if ( disable_gc ){ System.out.println( "Explicit GC disabled" ); } } protected static final boolean DEBUG_TRACK_HANDEDOUT = AEDiagnostics.TRACE_DBB_POOL_USAGE; protected static final boolean DEBUG_PRINT_MEM = AEDiagnostics.PRINT_DBB_POOL_USAGE; protected static final int DEBUG_PRINT_TIME = 120 * 1000; protected static final boolean DEBUG_HANDOUT_SIZES = false; protected static final boolean DEBUG_FREE_SIZES = false; // There is no point in allocating buffers smaller than 4K, // as direct ByteBuffers are page-aligned to the underlying // system, which is 4096 byte pages under most OS's. // If we want to save memory, we can distribute smaller-than-4K // buffers by using the slice() method to break up a standard buffer // into smaller chunks, but that's more work. private static final int START_POWER = 12; // 4096 private static final int END_POWER = 25; // 33554432 // without an extra bucket here we get lots of wastage with the file cache as typically // 16K data reads result in a buffer slightly bigger than 16K due to protocol header // This means we would bump up to 32K pool entries, hence wasting 16K per 16K entry private static final int[] EXTRA_BUCKETS = { DiskManager.BLOCK_SIZE + 128 }; public static final int MAX_SIZE = BigInteger.valueOf(2).pow(END_POWER).intValue(); private static final DirectByteBufferPoolReal pool = new DirectByteBufferPoolReal(); private final Map buffersMap = new LinkedHashMap(END_POWER - START_POWER + 1); private final Object poolsLock = new Object(); private static final int SLICE_END_SIZE = 2048; private static final int SLICE_ALLOC_CHUNK_SIZE = 4096; private static final short[] SLICE_ENTRY_SIZES = { 8, 16, 32, 64, 128, 256, 512, 1024, SLICE_END_SIZE }; private static final short[] SLICE_ALLOC_MAXS = { 256, 256, 128, 64, 64, 64, 64, 64, 64 }; private static final short[] SLICE_ENTRY_ALLOC_SIZES = new short[SLICE_ENTRY_SIZES.length]; private static final List[] slice_entries = new List[SLICE_ENTRY_SIZES.length]; private static final boolean[][] slice_allocs = new boolean[SLICE_ENTRY_SIZES.length][]; private static final boolean[] slice_alloc_fails = new boolean[SLICE_ENTRY_SIZES.length]; static{ int mult = COConfigurationManager.getIntParameter( "memory.slice.limit.multiplier" ); if ( mult > 1 ){ for (int i=0;ilength
      , and no larger than DirectByteBufferPool.MAX_SIZE */ protected DirectByteBuffer getBufferSupport( byte _allocator, int _length) { if (_length < 1) { Debug.out("requested length [" +_length+ "] < 1"); return null; } if (_length > MAX_SIZE) { Debug.out("requested length [" +_length+ "] > MAX_SIZE [" +MAX_SIZE+ "]"); return null; } return pool.getBufferHelper(_allocator,_length); } /** * Retrieve an appropriate buffer from the free pool, or * create a new one if the pool is empty. */ private DirectByteBuffer getBufferHelper( byte _allocator, int _length) { DirectByteBuffer res; if ( _length <= SLICE_END_SIZE ){ res = getSliceBuffer( _allocator, _length ); }else{ ByteBuffer buff = null; Integer reqVal = new Integer(_length); //loop through the buffer pools to find a buffer big enough Iterator it = buffersMap.keySet().iterator(); while (it.hasNext()) { Integer keyVal = (Integer)it.next(); // check if the buffers in this pool are big enough if (reqVal.compareTo(keyVal) <= 0) { ArrayList bufferPool = (ArrayList)buffersMap.get(keyVal); synchronized ( poolsLock ) { // make sure we don't remove a buffer when running compaction //if there are no free buffers in the pool, create a new one. //otherwise use one from the pool if (bufferPool.isEmpty()) { buff = allocateNewBuffer(keyVal.intValue()); }else{ synchronized ( bufferPool ) { buff = (ByteBuffer)bufferPool.remove(bufferPool.size() - 1); } } } break; } } if ( buff == null ){ Debug.out("Unable to find an appropriate buffer pool"); throw( new RuntimeException( "Unable to find an appropriate buffer pool" )); } res = new DirectByteBuffer( _allocator, buff, this ); } // clear doesn't actually zero the data, it just sets pos to 0 etc. ByteBuffer buff = res.getBufferInternal(); buff.clear(); //scrub the buffer buff.limit( _length ); bytesOut += buff.capacity(); if ( DEBUG_PRINT_MEM || DEBUG_TRACK_HANDEDOUT ){ synchronized( handed_out ){ if ( DEBUG_HANDOUT_SIZES ){ int trim_size; if ( _length < 32 ){ trim_size = 4; }else{ trim_size = 16; } int trim = ((_length+trim_size-1)/trim_size)*trim_size; Long count = (Long)size_counts.get(new Integer(trim)); if ( count == null ){ size_counts.put( new Integer( trim ), new Long(1)); }else{ size_counts.put( new Integer( trim), new Long( count.longValue() + 1 )); } } if ( handed_out.put( buff, res ) != null ){ Debug.out( "buffer handed out twice!!!!"); throw( new RuntimeException( "Buffer handed out twice" )); } //System.out.println( "[" + handed_out.size() + "] -> " + buff + ", bytesIn = " + bytesIn + ", bytesOut = " + bytesOut ); } } // addInUse( dbb.capacity() ); return( res ); } /** * Return the given buffer to the appropriate pool. */ protected void returnBufferSupport( DirectByteBuffer ddb ) { ByteBuffer buff = ddb.getBufferInternal(); int capacity = buff.capacity(); bytesIn += capacity; if ( DEBUG_TRACK_HANDEDOUT ){ synchronized( handed_out ){ if ( handed_out.remove( buff ) == null ){ Debug.out( "buffer not handed out" ); throw( new RuntimeException( "Buffer not handed out" )); } // System.out.println( "[" + handed_out.size() + "] <- " + buffer + ", bytesIn = " + bytesIn + ", bytesOut = " + bytesOut ); } } // remInUse( buffer.capacity() ); if ( capacity <= SLICE_END_SIZE ){ freeSliceBuffer( ddb ); }else{ Integer buffSize = new Integer(capacity); ArrayList bufferPool = (ArrayList)buffersMap.get(buffSize); if (bufferPool != null) { //no need to sync around 'poolsLock', as adding during compaction is ok synchronized ( bufferPool ){ bufferPool.add(buff); } }else{ Debug.out("Invalid buffer given; could not find proper buffer pool"); } } } /** * Clears the free buffer pools so that currently * unused buffers can be garbage collected. */ private void clearBufferPools() { Iterator it = buffersMap.values().iterator(); while (it.hasNext()) { ArrayList bufferPool = (ArrayList)it.next(); bufferPool.clear(); } } /** * Force system garbage collection. */ private void runGarbageCollection() { if ( !disable_gc ){ if( DEBUG_PRINT_MEM ) { System.out.println( "runGarbageCollection()" ); } System.runFinalization(); System.gc(); } } /** * Checks memory usage of free buffers in buffer pools, * and calls the compaction method if necessary. */ private void compactBuffers() { nonsliecd: synchronized (poolsLock) { long freeSize = bytesFree(); if (freeSize < MIN_FREE_BYTES) break nonsliecd; // apply cleanup pressure based on filling degree float remainingFactor; if (freeSize > MAX_FREE_BYTES) // downsize to 50% of the limit (not the current capacity!) if we're overlimit remainingFactor = 0.5f * MAX_FREE_BYTES / (float) freeSize; else // reduce to something between 50% (full: maximum reduction) and 100% (empty: no reduction) remainingFactor = 1.0f - 0.5f * freeSize / (float) MAX_FREE_BYTES; if (DEBUG_PRINT_MEM) System.out.println("Performing cleanup, reducing to " + remainingFactor * 100 + "%"); ArrayList pools = new ArrayList(buffersMap.values()); for (int i = pools.size() - 1; i >= 0; i--) { ArrayList pool = (ArrayList) pools.get(i); int limit = (int) (pool.size() * remainingFactor); // floor(), this way we can reach 0 at some point for (int j = pool.size() - 1; j >= limit; j--) pool.remove(j); } runGarbageCollection(); if (DEBUG_PRINT_MEM) { printInUse(false); System.out.println("Cleanup done\n"); } } compactSlices(); } private long bytesFree() { long bytesUsed = 0; synchronized( poolsLock ) { //count up total bytes used by free buffers Iterator it = buffersMap.keySet().iterator(); while (it.hasNext()) { Integer keyVal = (Integer)it.next(); ArrayList bufferPool = (ArrayList)buffersMap.get(keyVal); bytesUsed += keyVal.intValue() * bufferPool.size(); } } return bytesUsed; } /* private final HashMap in_use_counts = new HashMap(); private void addInUse( int size ) { Integer key = new Integer( size ); synchronized( in_use_counts ) { Integer count = (Integer)in_use_counts.get( key ); if( count == null ) count = new Integer( 1 ); else count = new Integer( count.intValue() + 1 ); in_use_counts.put( key, count ); } } private void remInUse( int size ) { Integer key = new Integer( size ); synchronized( in_use_counts ) { Integer count = (Integer)in_use_counts.get( key ); if( count == null ) System.out.println("count = null"); if( count.intValue() == 0 ) System.out.println("count = 0"); in_use_counts.put( key, new Integer( count.intValue() - 1 ) ); } } private void printInUse() { synchronized( in_use_counts ) { for( Iterator i = in_use_counts.keySet().iterator(); i.hasNext(); ) { Integer key = (Integer)i.next(); int count = ((Integer)in_use_counts.get( key )).intValue(); int size = key.intValue(); if( count > 0 ) { if( size < 1024 ) System.out.print("[" +size+ " x " +count+ "] "); else System.out.print("[" +size/1024+ "K x " +count+ "] "); } } System.out.println(); } } */ private void printInUse( boolean verbose ) { if ( DEBUG_PRINT_MEM ){ System.out.print("DIRECT: given=" +bytesOut/1024/1024+ "MB, returned=" +bytesIn/1024/1024+ "MB, "); long in_use = bytesOut - bytesIn; if( in_use < 1024*1024 ) System.out.print( "in use=" +in_use+ "B, " ); else System.out.print( "in use=" +in_use/1024/1024+ "MB, " ); long free = bytesFree(); if( free < 1024*1024 ) System.out.print( "free=" +free+ "B" ); else System.out.print( "free=" +free/1024/1024+ "MB" ); System.out.println(); CacheFileManager cm = null; try{ cm = CacheFileManagerFactory.getSingleton(); }catch( Throwable e ){ Debug.printStackTrace( e ); } synchronized( handed_out ){ Iterator it = handed_out.values().iterator(); Map cap_map = new TreeMap(); Map alloc_map = new TreeMap(); while( it.hasNext()){ DirectByteBuffer db = (DirectByteBuffer)it.next(); if ( verbose ){ String trace = db.getTraceString(); if ( trace != null ){ System.out.println( trace ); } } Integer cap = new Integer( db.getBufferInternal().capacity()); Byte alloc = new Byte( db.getAllocator()); myInteger c = (myInteger)cap_map.get(cap); if ( c == null ){ c = new myInteger(); cap_map.put( cap, c ); } c.value++; myInteger a = (myInteger)alloc_map.get(alloc); if ( a == null ){ a = new myInteger(); alloc_map.put( alloc, a ); } a.value++; } it = cap_map.keySet().iterator(); while( it.hasNext()){ Integer key = (Integer)it.next(); myInteger count = (myInteger)cap_map.get( key ); if( key.intValue() < 1024 ){ System.out.print("[" +key.intValue()+ " x " +count.value+ "] "); }else{ System.out.print("[" +key.intValue()/1024+ "K x " +count.value+ "] "); } } System.out.println(); it = alloc_map.keySet().iterator(); while( it.hasNext()){ Byte key = (Byte)it.next(); myInteger count = (myInteger)alloc_map.get( key ); System.out.print("[" + DirectByteBuffer.AL_DESCS[key.intValue()]+ " x " +count.value+ "] "); } if ( cm != null ){ CacheFileManagerStats stats = cm.getStats(); System.out.print( " - Cache: " ); System.out.print( "sz=" + stats.getSize()); System.out.print( ",us=" + stats.getUsedSize()); System.out.print( ",cw=" + stats.getBytesWrittenToCache()); System.out.print( ",cr=" + stats.getBytesReadFromCache()); System.out.print( ",fw=" + stats.getBytesWrittenToFile()); System.out.print( ",fr=" + stats.getBytesReadFromFile()); } System.out.println(); if ( DEBUG_HANDOUT_SIZES ){ it = size_counts.entrySet().iterator(); String str = ""; while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); str += (str.length()==0?"":",") + entry.getKey() + "=" + entry.getValue(); } System.out.println( str ); } String str = ""; for (int i=0;i 1024) { blocksize /= 1024; blocksuffix = "k";} if(blocksize > 1024) { blocksize /= 1024; blocksuffix = "M";} String footsuffix = ""; if(blockfootprint > 1024) { blockfootprint /= 1024; footsuffix = "k";} if(blockfootprint > 1024) { blockfootprint /= 1024; footsuffix = "M";} System.out.print("["+ blocksize + blocksuffix + ":" + blockfootprint + footsuffix + "] "); } } System.out.println(); } long free_mem = Runtime.getRuntime().freeMemory() /1024/1024; long max_mem = Runtime.getRuntime().maxMemory() /1024/1024; long total_mem = Runtime.getRuntime().totalMemory() /1024/1024; System.out.println("HEAP: max=" +max_mem+ "MB, total=" +total_mem+ "MB, free=" +free_mem+ "MB"); System.out.println(); } } // Slice buffer management private DirectByteBuffer getSliceBuffer( byte _allocator, int _length ) { int slice_index = getSliceIndex( _length ); List my_slice_entries = slice_entries[slice_index]; synchronized( my_slice_entries ){ boolean[] my_allocs = slice_allocs[slice_index]; sliceBuffer sb = null; if ( my_slice_entries.size() > 0 ){ sb = (sliceBuffer)my_slice_entries.remove(0); slice_use_count[slice_index]++; }else{ // find a free slot short slot = -1; for (short i=0;i= entries_per_alloc ){ synchronized( l ){ Collections.sort( l, new Comparator() { public int compare( Object o1, Object o2 ) { sliceBuffer sb1 = (sliceBuffer)o1; sliceBuffer sb2 = (sliceBuffer)o2; int res = sb1.getAllocID() - sb2.getAllocID(); if ( res == 0 ){ res = sb1.getSliceID() - sb2.getSliceID(); } return( res ); } }); boolean[] allocs = slice_allocs[i]; Iterator it = l.iterator(); int current_alloc = -1; int entry_count = 0; boolean freed_one = false; while( it.hasNext()){ sliceBuffer sb = (sliceBuffer)it.next(); int aid = sb.getAllocID(); if ( aid != current_alloc ){ if ( entry_count == entries_per_alloc ){ // System.out.println( "CompactSlices[" + SLICE_ENTRY_SIZES[i]+"] freeing " + aid ); freed_one = true; allocs[aid] = false; } current_alloc = aid; entry_count = 1; }else{ entry_count++; } } if ( entry_count == entries_per_alloc ){ // System.out.println( "CompactSlices[" + SLICE_ENTRY_SIZES[i]+"] freeing " + current_alloc ); freed_one = true; allocs[current_alloc] = false; } if ( freed_one ){ it = l.iterator(); while( it.hasNext()){ sliceBuffer sb = (sliceBuffer)it.next(); if ( !allocs[ sb.getAllocID()]){ it.remove(); } } } } } } } private int getSliceIndex( int _length ) { for (int i=0;i { public abstract void dispatch( T _listener, int type, Object value ); } azureus-4.3.0.6/org/gudy/azureus2/core3/util/Timer.java0000644000175000017500000002667511074350346022113 0ustar adrianadrian/* * File : Timer.java * Created : 21-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author parg * */ import java.lang.ref.WeakReference; import java.util.*; public class Timer extends AERunnable implements SystemTime.ChangeListener { private static boolean DEBUG_TIMERS = true; private static ArrayList timers = null; private static AEMonitor timers_mon = new AEMonitor("timers list"); private ThreadPool thread_pool; private Set events = new TreeSet(); private long unique_id_next = 0; private volatile boolean destroyed; private boolean indestructable; private boolean log; private int max_events_logged; public Timer( String name ) { this( name, 1 ); } public Timer( String name, int thread_pool_size ) { this(name, thread_pool_size, Thread.NORM_PRIORITY); } public Timer( String name, int thread_pool_size, int thread_priority ) { if (DEBUG_TIMERS) { try { timers_mon.enter(); if (timers == null) { timers = new ArrayList(); AEDiagnostics.addEvidenceGenerator(new evidenceGenerator()); } timers.add(new WeakReference(this)); } finally { timers_mon.exit(); } } thread_pool = new ThreadPool(name,thread_pool_size); SystemTime.registerClockChangeListener( this ); Thread t = new Thread(this, "Timer:" + name ); t.setDaemon( true ); t.setPriority(thread_priority); t.start(); } public void setIndestructable() { indestructable = true; } public synchronized List getEvents() { return( new ArrayList( events )); } public void setLogging( boolean _log ) { log = _log; } public boolean getLogging() { return log; } public void setWarnWhenFull() { thread_pool.setWarnWhenFull(); } public void setLogCPU() { thread_pool.setLogCPU(); } public void runSupport() { while( true ){ try{ TimerEvent event_to_run = null; synchronized(this){ if ( destroyed ){ break; } if ( events.isEmpty()){ // System.out.println( "waiting forever" ); this.wait(); }else{ long now = SystemTime.getCurrentTime(); TimerEvent next_event = (TimerEvent)events.iterator().next(); long delay = next_event.getWhen() - now; if ( delay > 0 ){ // System.out.println( "waiting for " + delay ); this.wait(delay); } } if ( destroyed ){ break; } long now = SystemTime.getCurrentTime(); Iterator it = events.iterator(); while( it.hasNext()){ TimerEvent event = (TimerEvent)it.next(); if ( event.getWhen() <= now ){ event_to_run = event; it.remove(); break; } } } if ( event_to_run != null ){ event_to_run.setHasRun(); if (log) { System.out.println( "running: " + event_to_run.getString() ); } thread_pool.run(event_to_run.getRunnable()); } }catch( Throwable e ){ Debug.printStackTrace( e ); } } } public void clockChanged( long current_time, long offset ) { // System.out.println( "Timer '" + thread_pool.getName() +"': clock change by " + offset ); if ( Math.abs( offset ) >= 60*1000 ){ // fix up the timers synchronized( this ){ boolean resort = false; Iterator it = events.iterator(); while (it.hasNext()){ TimerEvent event = (TimerEvent)it.next(); // absolute events don't have their timings fiddled with if ( event.isAbsolute()){ // event ordering may change resort = true; }else{ long old_when = event.getWhen(); long new_when = old_when + offset; TimerEventPerformer performer = event.getPerformer(); // sanity check for periodic events if ( performer instanceof TimerEventPeriodic ){ TimerEventPeriodic periodic_event = (TimerEventPeriodic)performer; long freq = periodic_event.getFrequency(); if ( new_when > current_time + freq + 5000 ){ long adjusted_when = current_time + freq; Debug.outNoStack( periodic_event.getName() + ": clock change sanity check. Reduced schedule time from " + new_when + " to " + adjusted_when ); new_when = adjusted_when; } } // don't wrap around by accident if ( old_when > 0 && new_when < 0 && offset > 0 ){ // Debug.out( "Ignoring wrap around for " + event.getName()); }else{ // System.out.println( " adjusted: " + old_when + " -> " + new_when ); event.setWhen( new_when ); } } } if ( resort ){ events = new TreeSet( events ); } notify(); } } } public void adjustAllBy( long offset ) { // fix up the timers synchronized (this) { // as we're adjusting all events by the same amount the ordering remains valid Iterator it = events.iterator(); while (it.hasNext()) { TimerEvent event = (TimerEvent) it.next(); long old_when = event.getWhen(); long new_when = old_when + offset; // don't wrap around by accident if ( old_when > 0 && new_when < 0 && offset > 0 ){ // Debug.out( "Ignoring wrap around for " + event.getName()); }else{ // System.out.println( " adjusted: " + old_when + " -> " + new_when ); event.setWhen( new_when ); } } notify(); } } public synchronized TimerEvent addEvent( long when, TimerEventPerformer performer ) { return( addEvent( SystemTime.getCurrentTime(), when, performer )); } public synchronized TimerEvent addEvent( String name, long when, TimerEventPerformer performer ) { return( addEvent( name, SystemTime.getCurrentTime(), when, performer )); } public synchronized TimerEvent addEvent( String name, long when, boolean absolute, TimerEventPerformer performer ) { return( addEvent( name, SystemTime.getCurrentTime(), when, absolute, performer )); } public synchronized TimerEvent addEvent( long creation_time, long when, TimerEventPerformer performer ) { return( addEvent( null, creation_time, when, performer )); } public synchronized TimerEvent addEvent( long creation_time, long when, boolean absolute, TimerEventPerformer performer ) { return( addEvent( null, creation_time, when, absolute, performer )); } public synchronized TimerEvent addEvent( String name, long creation_time, long when, TimerEventPerformer performer ) { return( addEvent( name, creation_time, when, false, performer )); } public synchronized TimerEvent addEvent( String name, long creation_time, long when, boolean absolute, TimerEventPerformer performer ) { TimerEvent event = new TimerEvent( this, unique_id_next++, creation_time, when, absolute, performer ); if ( name != null ){ event.setName( name ); } events.add( event ); if ( log ){ if ( events.size() > max_events_logged ){ max_events_logged = events.size(); System.out.println( "Timer '" + thread_pool.getName() + "' - events = " + max_events_logged ); } } // System.out.println( "event added (" + when + ") - queue = " + events.size()); notify(); return( event ); } public synchronized TimerEventPeriodic addPeriodicEvent( long frequency, TimerEventPerformer performer ) { return( addPeriodicEvent( null, frequency, performer )); } public synchronized TimerEventPeriodic addPeriodicEvent( String name, long frequency, TimerEventPerformer performer ) { return( addPeriodicEvent( name, frequency, false, performer )); } public synchronized TimerEventPeriodic addPeriodicEvent( String name, long frequency, boolean absolute, TimerEventPerformer performer ) { TimerEventPeriodic periodic_performer = new TimerEventPeriodic( this, frequency, absolute, performer ); if ( name != null ){ periodic_performer.setName( name ); } if ( log ){ System.out.println( "Timer '" + thread_pool.getName() + "' - added " + periodic_performer.getString()); } return( periodic_performer ); } protected synchronized void cancelEvent( TimerEvent event ) { if ( events.contains( event )){ events.remove( event ); // System.out.println( "event cancelled (" + event.getWhen() + ") - queue = " + events.size()); notify(); } } public synchronized void destroy() { if ( indestructable ){ Debug.out( "Attempt to destroy indestructable timer '" + getName() + "'" ); }else{ destroyed = true; notify(); SystemTime.unregisterClockChangeListener( this ); } if (DEBUG_TIMERS) { try { timers_mon.enter(); // crappy for (Iterator iter = timers.iterator(); iter.hasNext();) { WeakReference timerRef = (WeakReference) iter.next(); Object timer = timerRef.get(); if (timer == null || timer == this) { iter.remove(); } } } finally { timers_mon.exit(); } } } public String getName() { return( thread_pool.getName()); } public synchronized void dump() { System.out.println( "Timer '" + thread_pool.getName() + "': dump" ); Iterator it = events.iterator(); while(it.hasNext()){ TimerEvent ev = (TimerEvent)it.next(); System.out.println( "\t" + ev.getString()); } } private class evidenceGenerator implements AEDiagnosticsEvidenceGenerator { public void generate(IndentWriter writer) { if (!DEBUG_TIMERS) { return; } ArrayList lines = new ArrayList(); int count = 0; try { try { timers_mon.enter(); // crappy for (Iterator iter = timers.iterator(); iter.hasNext();) { WeakReference timerRef = (WeakReference) iter.next(); Timer timer = (Timer) timerRef.get(); if (timer == null) { iter.remove(); } else { count++; List events = timer.getEvents(); lines.add(timer.thread_pool.getName() + ", " + events.size() + " events:"); Iterator it = events.iterator(); while (it.hasNext()) { TimerEvent ev = (TimerEvent) it.next(); lines.add(" " + ev.getString()); } } } } finally { timers_mon.exit(); } writer.println("Timers: " + count); writer.indent(); for (Iterator iter = lines.iterator(); iter.hasNext();) { String line = (String) iter.next(); writer.println(line); } writer.exdent(); } catch (Throwable e) { writer.println(e.toString()); } } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/DirectByteBuffer.java0000644000175000017500000003511111144727440024205 0ustar adrianadrian/* * Created on Apr 21, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.util; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.SocketChannel; //import java.util.*; /** * Virtual direct byte buffer given out and tracker * by the buffer pool. */ public class DirectByteBuffer { // allocator constants public static final byte AL_NONE = 0; public static final byte AL_EXTERNAL = 1; public static final byte AL_OTHER = 2; public static final byte AL_PT_READ = 3; public static final byte AL_PT_LENGTH = 4; public static final byte AL_CACHE_READ = 5; public static final byte AL_DM_READ = 6; public static final byte AL_DM_ZERO = 7; public static final byte AL_DM_CHECK = 8; public static final byte AL_BT_PIECE = 9; public static final byte AL_CACHE_WRITE = 10; public static final byte AL_PROXY_RELAY = 11; public static final byte AL_MSG = 12; public static final byte AL_MSG_AZ_HAND = 13; public static final byte AL_MSG_AZ_PEX = 14; public static final byte AL_MSG_BT_CANCEL = 15; public static final byte AL_MSG_BT_HAND = 16; public static final byte AL_MSG_BT_HAVE = 17; public static final byte AL_MSG_BT_PIECE = 18; public static final byte AL_MSG_BT_REQUEST = 19; public static final byte AL_MSG_BT_KEEPALIVE = 20; public static final byte AL_MSG_BT_HEADER = 21; public static final byte AL_MSG_AZ_HEADER = 22; public static final byte AL_MSG_BT_PAYLOAD = 23; public static final byte AL_MSG_AZ_PAYLOAD = 24; public static final byte AL_FILE = 25; public static final byte AL_NET_CRYPT = 26; public static final byte AL_MSG_LT_EXT_MESSAGE = 27; public static final byte AL_MSG_LT_HANDSHAKE = 28; public static final byte AL_MSG_UT_PEX = 29; public static final byte AL_MSG_BT_DHT_PORT = 30; public static final String[] AL_DESCS = { "None", "Ext", "Other", "PeerRead", "PeerLen", "CacheRead", "DiskRead", "DiskZero", "DiskCheck", "BTPiece", "CacheWrite", "ProxyRelay", "Messaging", "AZHandshake", "AZPEX", "BTCancel", "BTHandshake", "BTHave", "BTPiece", "BTRequest", "BTKeepAlive", "BTHeader", "AZHeader", "BTPayload", "AZPayload", "File", "MsgCrypt", "LTExtMsg","LTExtHandshake","UTPEX", "BTDHTPort"}; // subsystem ids public static final byte SS_NONE = 0; // not used, required to id cycled buffers public static final byte SS_EXTERNAL = 1; public static final byte SS_OTHER = 2; public static final byte SS_CACHE = 3; public static final byte SS_FILE = 4; public static final byte SS_NET = 5; public static final byte SS_BT = 6; public static final byte SS_DR = 7; public static final byte SS_DW = 8; public static final byte SS_PEER = 9; public static final byte SS_PROXY = 10; public static final byte SS_MSG = 11; public static final String[] SS_DESCS = { "None", "Ext", "Other", "Cache", "File", "Net", "BT", "DiskRead", "DiskWrite", "Peer", "Proxy", "Messaging" }; public static final byte OP_LIMIT = 0; public static final byte OP_LIMIT_INT = 1; public static final byte OP_POSITION = 2; public static final byte OP_POSITION_INT = 3; public static final byte OP_CLEAR = 4; public static final byte OP_FLIP = 5; public static final byte OP_REMANING = 6; public static final byte OP_CAPACITY = 7; public static final byte OP_PUT_BYTEARRAY = 8; public static final byte OP_PUT_DBB = 9; public static final byte OP_PUT_BB = 10; public static final byte OP_PUTINT = 11; public static final byte OP_PUT_BYTE = 12; public static final byte OP_GET = 13; public static final byte OP_GET_INT = 14; public static final byte OP_GET_BYTEARRAY = 15; public static final byte OP_GETINT = 16; public static final byte OP_GETINT_INT = 17; public static final byte OP_HASREMAINING = 18; public static final byte OP_READ_FC = 19; public static final byte OP_WRITE_FC = 20; public static final byte OP_READ_SC = 21; public static final byte OP_WRITE_SC = 22; public static final byte OP_GETBUFFER = 23; public static final byte OP_GETSHORT = 24; public static final byte OP_PUTSHORT = 25; public static final String[] OP_DESCS = { "limit", "limit(int)", "position", "position(int)", "clear", "flip", "remaining", "capacity", "put(byte[])", "put(dbb)", "put(bbb)", "putInt", "put(byte)", "get", "get(int)", "get(byte[])", "getInt", "getInt(int", "hasRemaining", "read(fc)", "write(fc)", "read(sc)", "write(sc)", "getBuffer", "getShort", "putShort", }; protected static final boolean TRACE = AEDiagnostics.TRACE_DIRECT_BYTE_BUFFERS; protected static final int TRACE_BUFFER_SIZE = 64; // must be even private ByteBuffer buffer; private DirectByteBufferPool pool; private byte allocator; private boolean was_returned_to_pool = false; //private byte[] trace_buffer; //private int trace_buffer_pos; public DirectByteBuffer( ByteBuffer _buffer ) { this( AL_NONE, _buffer, null ); } public DirectByteBuffer( byte _allocator, ByteBuffer _buffer, DirectByteBufferPool _pool ) { if (_buffer == null) {throw new NullPointerException("buffer is null");} allocator = _allocator; buffer = _buffer; pool = _pool; if ( TRACE ){ /* trace_buffer = new byte[TRACE_BUFFER_SIZE]; Arrays.fill(trace_buffer,(byte)0); */ } } /** * constructor for reference counted version * @param basis */ protected DirectByteBuffer( DirectByteBuffer basis ) { allocator = basis.allocator; buffer = basis.buffer; pool = null; if (buffer == null) {throw new NullPointerException("basis.buffer is null");} } public ReferenceCountedDirectByteBuffer getReferenceCountedBuffer() { ReferenceCountedDirectByteBuffer res = new ReferenceCountedDirectByteBuffer( this ); return( res ); } protected void traceUsage( byte subsystem, byte operation ) { if ( TRACE ){ /* trace_buffer[trace_buffer_pos++] = subsystem; trace_buffer[trace_buffer_pos++] = operation; if ( trace_buffer_pos == TRACE_BUFFER_SIZE ){ trace_buffer_pos = 0; } */ } } protected String getTraceString() { if ( TRACE ){ /* StringBuffer sb = new StringBuffer(); sb.append( AL_DESCS[allocator]); sb.append( ":" ); boolean wrapped = false; int start = 0; int end = trace_buffer_pos; if ( trace_buffer[trace_buffer_pos] != 0 ){ start = trace_buffer_pos; wrapped = true; } if ( end == 0 && !wrapped ){ sb.append( "not used"); }else{ if ( wrapped ){ sb.append( "*" ); } int num = 0; do{ if ( num++ > 0 ){ sb.append(","); } sb.append( SS_DESCS[trace_buffer[start++]]); sb.append( "/" ); sb.append( OP_DESCS[trace_buffer[start++]]); if ( start == TRACE_BUFFER_SIZE ){ start = 0; } }while( start != end ); } return( sb.toString()); */ } return( null ); } protected void dumpTrace( Throwable e ) { if ( TRACE ){ System.out.println( getTraceString()); Ignore.ignore(e); } } protected ByteBuffer getBufferInternal() { return( buffer ); } protected byte getAllocator() { return( allocator ); } // **** accessor methods **** public int limit( byte subsystem ) { if ( TRACE ){ traceUsage( subsystem, OP_LIMIT ); } return( buffer.limit()); } public void limit( byte subsystem, int l ) { if ( TRACE ){ traceUsage( subsystem, OP_LIMIT_INT ); } if (buffer == null) { System.out.println("Trying to limit null buffer - returned? " + this.was_returned_to_pool); } buffer.limit(l); } public int position( byte subsystem ) { if ( TRACE ){ traceUsage( subsystem, OP_POSITION); } return( buffer.position()); } public void position( byte subsystem, int l ) { if ( TRACE ){ traceUsage( subsystem, OP_POSITION_INT); } buffer.position(l); } public void clear( byte subsystem) { if ( TRACE ){ traceUsage( subsystem, OP_CLEAR ); } buffer.clear(); } public void flip( byte subsystem ) { if ( TRACE ){ traceUsage( subsystem, OP_FLIP ); } buffer.flip(); } public int remaining( byte subsystem ) { if ( TRACE ){ traceUsage( subsystem, OP_REMANING ); } return( buffer.remaining()); } public int capacity( byte subsystem ) { if ( TRACE ){ traceUsage( subsystem, OP_CAPACITY ); } return( buffer.capacity()); } public void put( byte subsystem, byte[] data ) { if ( TRACE ){ traceUsage( subsystem, OP_PUT_BYTEARRAY ); } buffer.put( data ); } public void put( byte subsystem, byte[] data, int offset, int length ) { if ( TRACE ){ traceUsage( subsystem, OP_PUT_BYTEARRAY ); } buffer.put( data, offset, length ); } public void put( byte subsystem, DirectByteBuffer data ) { if ( TRACE ){ traceUsage( subsystem, OP_PUT_DBB); } buffer.put( data.buffer ); } public void put( byte subsystem, ByteBuffer data ) { if ( TRACE ){ traceUsage( subsystem, OP_PUT_BB); } buffer.put( data ); } public void put( byte subsystem, byte data ) { if ( TRACE ){ traceUsage( subsystem, OP_PUT_BYTE ); } buffer.put( data ); } public void putShort( byte subsystem, short x ) { if ( TRACE ){ traceUsage( subsystem, OP_PUTSHORT); } buffer.putShort( x ); } public void putInt( byte subsystem, int data ) { if ( TRACE ){ traceUsage( subsystem, OP_PUTINT); } buffer.putInt( data ); } public byte get( byte subsystem ) { if ( TRACE ){ traceUsage( subsystem, OP_GET); } return( buffer.get()); } public byte get( byte subsystem, int x ) { if ( TRACE ){ traceUsage( subsystem, OP_GET_INT); } return( buffer.get(x)); } public void get( byte subsystem, byte[] data ) { if ( TRACE ){ traceUsage( subsystem, OP_GET_BYTEARRAY); } buffer.get(data); } public short getShort( byte subsystem ) { if ( TRACE ){ traceUsage( subsystem, OP_GETSHORT); } return( buffer.getShort()); } public int getInt( byte subsystem ) { if ( TRACE ){ traceUsage( subsystem, OP_GETINT); } return( buffer.getInt()); } public int getInt( byte subsystem, int x ) { if ( TRACE ){ traceUsage( subsystem, OP_GETINT_INT ); } return( buffer.getInt(x)); } public boolean hasRemaining( byte subsystem ) { if ( TRACE ){ traceUsage( subsystem, OP_HASREMAINING ); } return( buffer.hasRemaining()); } public int read( byte subsystem, FileChannel chan ) throws IOException { if ( TRACE ){ traceUsage( subsystem, OP_READ_FC); } try{ return( chan.read(buffer )); }catch( IllegalArgumentException e ){ dumpTrace(e); throw( e ); } } public int write( byte subsystem, FileChannel chan ) throws IOException { if ( TRACE ){ traceUsage( subsystem, OP_WRITE_FC ); } try{ return( chan.write(buffer )); }catch( IllegalArgumentException e ){ dumpTrace(e); throw( e ); } } public int read( byte subsystem, SocketChannel chan ) throws IOException { if ( TRACE ){ traceUsage( subsystem, OP_READ_SC ); } try{ return( chan.read(buffer )); }catch( IllegalArgumentException e ){ dumpTrace(e); throw( e ); } } public int write( byte subsystem, SocketChannel chan ) throws IOException { if ( TRACE ){ traceUsage( subsystem, OP_WRITE_SC ); } try{ return( chan.write(buffer )); }catch( IllegalArgumentException e ){ dumpTrace(e); throw( e ); } } public ByteBuffer getBuffer( byte subsystem ) { if ( TRACE ){ traceUsage( subsystem, OP_GETBUFFER ); } return( buffer ); } public void returnToPool() { if ( pool != null ){ // we can't afford to return a buffer more than once to the pool as it'll get // handed out twice in parallel and cause weird problems. We haven't been able // to totally eliminiate duplicate returnToPool calls.... synchronized( this ){ if ( buffer == null ){ Debug.out( "Buffer already returned to pool"); }else{ pool.returnBufferSupport( this ); buffer = null; was_returned_to_pool = true; } } } } /** * Normally you should know when a buffer is/isn't free and NOT CALL THIS METHOD * However, there are some error situations where the existing code doesn't correctly * manage things - we know this and don't want spurious logs occuring as per the above * normal method */ public void returnToPoolIfNotFree() { if ( pool != null ){ // we can't afford to return a buffer more than once to the pool as it'll get // handed out twice in parallel and cause weird problems. We haven't been able // to totally eliminiate duplicate returnToPool calls.... synchronized( this ){ if ( buffer != null ){ pool.returnBufferSupport( this ); buffer = null; was_returned_to_pool = true; } } } } } azureus-4.3.0.6/org/gudy/azureus2/core3/util/TimerEvent.java0000644000175000017500000000626710766605566023126 0ustar adrianadrian/* * File : TimerEvent.java * Created : 21-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.util; /** * @author parg * */ public class TimerEvent extends ThreadPoolTask implements Comparable { private String name; private Timer timer; private long created; private long when; private TimerEventPerformer performer; private boolean absolute; private boolean cancelled; private boolean has_run; private long unique_id = 1; protected TimerEvent( Timer _timer, long _unique_id, long _created, long _when, boolean _absolute, TimerEventPerformer _performer ) { timer = _timer; unique_id = _unique_id; when = _when; absolute = _absolute; performer = _performer; created = _created; } public void setName( String _name ) { name = _name; } public String getName() { return( name ); } public long getCreatedTime() { return( created ); } public long getWhen() { return( when ); } protected void setWhen( long new_when ) { when = new_when; } protected AERunnable getRunnable() { return( this ); } protected TimerEventPerformer getPerformer() { return( performer ); } protected boolean isAbsolute() { return( absolute ); } public void runSupport() { performer.perform( this ); } public synchronized void cancel() { cancelled = true; timer.cancelEvent( this ); } public synchronized boolean isCancelled() { return( cancelled ); } protected void setHasRun() { has_run = true; } public boolean hasRun() { return( has_run ); } protected long getUniqueId() { return( unique_id ); } public int compareTo( Object other ) { long res = when - ((TimerEvent)other).getWhen(); if ( res == 0 ){ return((int)( unique_id - ((TimerEvent)other).getUniqueId())); }else{ return res < 0 ? -1 : 1; } } public void interruptTask() { } public String getString() { if ( performer instanceof TimerEventPeriodic ){ TimerEventPeriodic tep = (TimerEventPeriodic)performer; return( "when=" + getWhen() + ",run=" + hasRun() + ", can=" + isCancelled() + "/" + tep.isCancelled() + ",freq=" + tep.getFrequency() + ",target=" + tep.getPerformer()+ (name==null?"":",name=" + name )); }else{ return( "when=" + getWhen() + ",run=" + hasRun() + ", can=" + isCancelled() + ",target=" + getPerformer() + (name==null?"":",name=" + name )); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/0000755000175000017500000000000011310377634020130 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/peer/PEPeerManagerAdapter.java0000644000175000017500000000640511124122752024704 0ustar adrianadrian/* * Created on 11-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.peer; import org.gudy.azureus2.core3.disk.DiskManagerReadRequest; import org.gudy.azureus2.core3.disk.DiskManagerReadRequestListener; import org.gudy.azureus2.core3.logging.LogRelation; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import com.aelitis.azureus.core.peermanager.PeerManagerRegistration; public interface PEPeerManagerAdapter { public String getDisplayName(); public int getUploadRateLimitBytesPerSecond(); public int getDownloadRateLimitBytesPerSecond(); public int getMaxUploads(); public int getMaxConnections(); public int getMaxSeedConnections(); public boolean isExtendedMessagingEnabled(); public boolean isPeerExchangeEnabled(); /** * See NetworkManager.CRYPTO_OVERRIDE constants * @return */ public int getCryptoLevel(); public long getRandomSeed(); public boolean isPeriodicRescanEnabled(); public void setStateFinishing(); public void setStateSeeding( boolean never_downloaded ); public void restartDownload(boolean forceRecheck); public TRTrackerScraperResponse getTrackerScrapeResponse(); public String getTrackerClientExtensions(); public void setTrackerRefreshDelayOverrides( int percent ); public boolean isNATHealthy(); public void addPeer( PEPeer peer ); public void removePeer( PEPeer peer ); public void addPiece( PEPiece piece ); public void removePiece( PEPiece piece ); public void discarded( PEPeer peer, int bytes ); public void protocolBytesReceived( PEPeer peer, int bytes ); public void dataBytesReceived( PEPeer peer, int bytes ); public void protocolBytesSent( PEPeer peer, int bytes ); public void dataBytesSent( PEPeer peer, int bytes ); public PeerManagerRegistration getPeerManagerRegistration(); public void addHTTPSeed( String address, int port ); public byte[][] getSecrets( int crypto_level ); public void enqueueReadRequest( PEPeer peer, DiskManagerReadRequest request, DiskManagerReadRequestListener listener ); public LogRelation getLogRelation(); public int getPosition(); public boolean isPeerSourceEnabled( String peer_source ); public void priorityConnectionChanged( boolean added ); public boolean hasPriorityConnection(); } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/PEPeer.java0000644000175000017500000002223611257507206022120 0ustar adrianadrian/* * File : PEPeerSocket.java * Created : 15-Oct-2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on 4 juil. 2003 * */ package org.gudy.azureus2.core3.peer; import java.net.InetAddress; import org.gudy.azureus2.plugins.network.Connection; import com.aelitis.azureus.core.networkmanager.LimitedRateGroup; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags; /** * @author Olivier * @author MjrTom * 2005/Oct/08: lastPiece handling * */ public interface PEPeer { public final static int CONNECTING = 10; public final static int HANDSHAKING = 20; public final static int TRANSFERING = 30; public final static int CLOSING = 40; public final static int DISCONNECTED = 50; // these should be maintained to match above list ordinals /10 // if they don't than some debug info won't work right (not too big of a deal) public final static String[] StateNames = { "Twinkle", "Connecting", "Handshaking", "Transfering", "Closing", "Disconnected" }; public static final int MESSAGING_BT_ONLY = 1; public static final int MESSAGING_AZMP = 2; public static final int MESSAGING_LTEP = 3; //used for plugins, such as webseeds public static final int MESSAGING_EXTERN = 4; /** * Add peer listener. * @param listener */ public void addListener( PEPeerListener listener ); /** * Remove peer listener. * @param listener */ public void removeListener( PEPeerListener listener ); public int getPeerState(); // from above set public PEPeerManager getManager(); public String getPeerSource(); public byte[] getId(); public String getIp(); /** * @return an ipv6 address under which the peer should be connectable if it announced one, null otherwise */ public InetAddress getAlternativeIPv6(); /** * Get the peer's local TCP connection port. * @return local port */ public int getPort(); /** * Gets the host name for the IP, if possible, IP as string otherwise * @return hostname or IP */ public String getIPHostName(); /** * Get the TCP port this peer is listening for incoming connections on. * @return TCP port, or 0 if port is unknown */ public int getTCPListenPort(); /** * Get the UDP port this peer is listening for incoming connections on. * @return UDP port, or 0 if port is unknown */ public int getUDPListenPort(); /** * Get the UDP port this peer is listening on for non-data connections * @return */ public int getUDPNonDataListenPort(); public BitFlags getAvailable(); /** * @param pieceNumber int * @return true if this peers makes this piece available */ public boolean isPieceAvailable(int pieceNumber); public boolean transferAvailable(); public void setSnubbed(boolean b); // explicit un-snub /** * Is the peer choking me. * @return true if I am choked by the peer, false if not */ public boolean isChokingMe(); /** * Am I choking the peer. * @return true if the peer is choked, false if not */ public boolean isChokedByMe(); public void sendChoke(); public void sendUnChoke(); /** * Am I Interested in the peer. * @return true if peer is interesting, false if not */ public boolean isInteresting(); /** * Is the peer Interested in me. * @return true if the peer is interested in me, false if not */ public boolean isInterested(); /** * checks several factors within the object so the caller wouldn't need to * for convienience and speed. * @return true if none of several criteria indicate a request can't be made of the peer */ public boolean isDownloadPossible(); public boolean isSeed(); /** * @return true if the peer is only uploading and can't use the data we have * to offer (we're seeding) or we can't use the data he has to offer * (we're downloading) */ public boolean isRelativeSeed(); public boolean isSnubbed(); public long getSnubbedTime(); public PEPeerStats getStats(); public boolean isIncoming(); public boolean hasReceivedBitField(); /** * Get the peer's torrent completion percentage in thousand-notation, * i.e. 53.7% is returned as the value 0537. * @return the percentage the peer has complete */ public int getPercentDoneInThousandNotation(); public String getClient(); public boolean isOptimisticUnchoke(); public void setOptimisticUnchoke( boolean is_optimistic ); //Used in super-seed mode //The lower the better public void setUploadHint(int timeToSpread); public int getUploadHint(); public void setUniqueAnnounce(int uniquePieceNumber); public int getUniqueAnnounce(); public int getConsecutiveNoRequestCount(); public void setConsecutiveNoRequestCount( int num ); public void setUploadRateLimitBytesPerSecond( int bytes ); public void setDownloadRateLimitBytesPerSecond( int bytes ); public int getUploadRateLimitBytesPerSecond(); public int getDownloadRateLimitBytesPerSecond(); public void addRateLimiter( LimitedRateGroup limiter, boolean upload ); public void removeRateLimiter( LimitedRateGroup limiter, boolean upload ); /** To retreive arbitrary objects against a peer. */ public Object getData (String key); /** To store arbitrary objects against a peer. */ public void setData (String key, Object value); public Object getUserData (Object key); /** To store arbitrary objects against a peer. */ public void setUserData (Object key, Object value); /** * Get the connection that backs this peer. * @return connection */ public Connection getPluginConnection(); /** * Whether or not this peer supports the advanced messaging API. * @return true if extended messaging is supported, false if not */ public boolean supportsMessaging(); /** * @Return the handshaked messaging type, {@link PEPeer} constants */ public int getMessagingMode(); /** * Returns name of encryption used by the peer * @return */ public String getEncryption(); /** * Get the list of messages that this peer and us both understand. * @return messages available for use, or null of supported is yet unknown or unavailable */ public Message[] getSupportedMessages(); /** * Sets the reserved piece for piece picking by this peer */ public void setReservedPieceNumber(int pieceNumber); /** * Get the reserved piece for piece picking by this peer */ public int getReservedPieceNumber(); public int getIncomingRequestCount(); public int getOutgoingRequestCount(); /** * amount of data queued for delivery to peer * @return */ public int getOutboundDataQueueSize(); /** * get a list of piece numbers the peer has requested * @return list of Long() representing the piece number requested, in order */ public int[] getIncomingRequestedPieceNumbers(); /** * get a list of piece numbers the we have requested from peer * @return list of Long() representing the piece number requested, oldest * to newest */ public int[] getOutgoingRequestedPieceNumbers(); public int getPercentDoneOfCurrentIncomingRequest(); public int getPercentDoneOfCurrentOutgoingRequest(); public long getBytesRemaining(); /** * Get the time since this connection was first established. * NOTE: This method will always return 0 at any time before * the underlying transport is fully connected, i.e. before * handshaking begins. * @return time count in ms */ public long getTimeSinceConnectionEstablished(); public void setLastPiece(int i); public int getLastPiece(); public boolean isLANLocal(); /** * Send a request hint to the peer. * @param piece_number * @param offset * @param length * @param life * @return true if sent, false otherwise */ public boolean sendRequestHint( int piece_number, int offset, int length, int life ); /** * Get current request hint for a given piece for this peer. * @return null if no hint int[]{ piece_number, offset, length } if hint found */ public int[] getRequestHint(); public void clearRequestHint(); public void setHaveAggregationEnabled( boolean enabled ); public byte[] getHandshakeReservedBytes(); public String getClientNameFromPeerID(); public String getClientNameFromExtensionHandshake(); public boolean isPriorityConnection(); public void setPriorityConnection( boolean is_priority ); }azureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/0000755000175000017500000000000011310377634021071 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/PEPeerControlFactory.java0000644000175000017500000000273211165063176025752 0ustar adrianadrian/* * File : PEPeerControlFactory.java * Created : 21-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.peer.impl; /** * @author parg * */ import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.peer.PEPeerManagerAdapter; import org.gudy.azureus2.core3.peer.impl.control.*; public class PEPeerControlFactory { public static PEPeerControl create( byte[] peer_id, PEPeerManagerAdapter adapter, DiskManager diskManager ) { return( create( peer_id, adapter, diskManager, 0 )); } public static PEPeerControl create( byte[] peer_id, PEPeerManagerAdapter adapter, DiskManager diskManager, int id ) { return( new PEPeerControlImpl( peer_id, adapter, diskManager, id )); } } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/PEPeerStatsImpl.java0000644000175000017500000001545010713330440024710 0ustar adrianadrian/* * File : PEPeerStatsImpl.java * Created : 15-Oct-2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.peer.impl; /** * @author parg * */ import org.gudy.azureus2.core3.peer.*; import org.gudy.azureus2.core3.util.*; public class PEPeerStatsImpl implements PEPeerStats { private PEPeer owner; private long total_data_bytes_received = 0; private long total_protocol_bytes_received = 0; private final Average data_receive_speed = Average.getInstance( 1000, 10 ); //update every 1s, average over 10s private final Average protocol_receive_speed = Average.getInstance( 1000, 10 ); private long total_data_bytes_sent = 0; private long total_protocol_bytes_sent = 0; private final Average data_send_speed = Average.getInstance( 1000, 5 ); //update every 1s, average over 5s private final Average protocol_send_speed = Average.getInstance( 1000, 5 ); private final Average receive_speed_for_choking = Average.getInstance( 1000, 20 ); //update every 1s, average over 20s private final Average estimated_download_speed = Average.getInstance( 5000, 100 ); //update every 5s, average over 100s private final Average estimated_upload_speed = Average.getInstance( 3000, 60 ); //update every 3s, average over 60s private long total_bytes_discarded = 0; private long total_bytes_downloaded = 0; private long disk_read_bytes = 0; private int disk_read_count = 0; private int disk_aggregated_read_count = 0; private long last_new_piece_time; public PEPeerStatsImpl( PEPeer _owner ) { owner = _owner; } public PEPeer getPeer() { return( owner ); } /* (non-Javadoc) * @see org.gudy.azureus2.core3.peer.PEPeerStats#setPeer() */ public void setPeer(PEPeer peer) { owner = peer; } public void dataBytesSent( int num_bytes ) { total_data_bytes_sent += num_bytes; data_send_speed.addValue( num_bytes ); } public void protocolBytesSent( int num_bytes ) { total_protocol_bytes_sent += num_bytes; protocol_send_speed.addValue( num_bytes ); } public void dataBytesReceived( int num_bytes ) { total_data_bytes_received += num_bytes; data_receive_speed.addValue( num_bytes ); receive_speed_for_choking.addValue( num_bytes ); } public void protocolBytesReceived( int num_bytes ) { total_protocol_bytes_received += num_bytes; protocol_receive_speed.addValue( num_bytes ); //dont count protocol overhead towards a peer's choke/unchoke value, only piece data } public void bytesDiscarded( int num_bytes ) { total_bytes_discarded += num_bytes; } public void hasNewPiece( int piece_size ) { total_bytes_downloaded += piece_size; // ignore first few seconds here to avoid lazy-bitfield from totally spamming initial // stats if ( owner.getTimeSinceConnectionEstablished() > 5000 ){ estimated_download_speed.addValue( piece_size ); last_new_piece_time = SystemTime.getCurrentTime(); } } public long getEstimatedSecondsToCompletion() { long remaining = owner.getBytesRemaining(); if ( remaining == 0 ){ return( 0 ); } long download_rate = estimated_download_speed.getAverage(); long our_send_rate = getDataSendRate(); // make sure we at least take into account our own send speed if ( download_rate < our_send_rate ){ download_rate = our_send_rate; } if ( download_rate == 0 ){ return( Long.MAX_VALUE ); } if ( last_new_piece_time > 0 ){ long elapsed_secs = ( SystemTime.getCurrentTime() - last_new_piece_time )/1000; remaining -= elapsed_secs * download_rate; } long secs_remaining = remaining / download_rate; if ( secs_remaining <= 0 ){ secs_remaining = 1; } return( secs_remaining ); } public void statisticalSentPiece( int piece_size ) { estimated_upload_speed.addValue( piece_size ); } public long getDataReceiveRate() { return data_receive_speed.getAverage(); } public long getProtocolReceiveRate() { return protocol_receive_speed.getAverage(); } public long getDataSendRate() { return data_send_speed.getAverage(); } public long getProtocolSendRate() { return protocol_send_speed.getAverage(); } public long getSmoothDataReceiveRate() { return receive_speed_for_choking.getAverage(); } public long getTotalBytesDiscarded() { return total_bytes_discarded; } public long getTotalBytesDownloadedByPeer() { return total_bytes_downloaded; } public long getEstimatedDownloadRateOfPeer() { return estimated_download_speed.getAverage(); } public long getEstimatedUploadRateOfPeer() { return estimated_upload_speed.getAverage(); } public long getTotalDataBytesReceived() { return total_data_bytes_received; } public long getTotalProtocolBytesReceived() { return total_protocol_bytes_received; } public long getTotalDataBytesSent() { return total_data_bytes_sent; } public long getTotalProtocolBytesSent() { return total_protocol_bytes_sent; } public void diskReadComplete( long bytes ) { disk_read_bytes += bytes; disk_read_count++; if ( bytes > 0 ){ disk_aggregated_read_count++; } } public int getTotalDiskReadCount(){ return( disk_read_count ); } public int getAggregatedDiskReadCount(){ return( disk_aggregated_read_count ); } public long getTotalDiskReadBytes(){ return( disk_read_bytes ); } public void setUploadRateLimitBytesPerSecond( int bytes ){owner.setUploadRateLimitBytesPerSecond( bytes );} public void setDownloadRateLimitBytesPerSecond( int bytes ){owner.setDownloadRateLimitBytesPerSecond( bytes );} public int getUploadRateLimitBytesPerSecond(){return owner.getUploadRateLimitBytesPerSecond();} public int getDownloadRateLimitBytesPerSecond(){return owner.getDownloadRateLimitBytesPerSecond();} } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/PEPeerTransportFactory.java0000644000175000017500000000525610706246464026335 0ustar adrianadrian/* * File : PEPeerTransportFactory.java * Created : 21-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.peer.impl; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.core3.peer.impl.transport.PEPeerTransportProtocol; import com.aelitis.azureus.core.networkmanager.NetworkConnection; public class PEPeerTransportFactory { protected static Map extension_handlers = new HashMap(); /** * Create a new default outgoing connection transport. * @param control * @param ip * @param port * @return transport */ public static PEPeerTransport createTransport( PEPeerControl control, String peer_source, String ip, int tcp_port, int udp_port, boolean use_tcp, boolean require_crypto_handshake, byte crypto_level, Map initial_user_data ) { return new PEPeerTransportProtocol( control, peer_source, ip, tcp_port, udp_port, use_tcp, require_crypto_handshake, crypto_level, initial_user_data ); } //incoming public static PEPeerTransport createTransport( PEPeerControl control, String peer_source, NetworkConnection connection, Map initial_user_data ) { return new PEPeerTransportProtocol( control, peer_source, connection, initial_user_data ); } public static void registerExtensionHandler( String protocol_name, PEPeerTransportExtensionHandler handler ) { extension_handlers.put( protocol_name, handler ); } public static List createExtendedTransports( PEPeerControl manager, String protocol_name, Map details ) { System.out.println( "createExtendedTransports:" + protocol_name ); PEPeerTransportExtensionHandler handler = (PEPeerTransportExtensionHandler)extension_handlers.get( protocol_name ); if ( handler == null ){ System.out.println( "\tNo handler"); return( new ArrayList()); } return( handler.handleExtension( manager, details )); } } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/PEPeerTransportExtensionHandler.java0000644000175000017500000000221307767753006030176 0ustar adrianadrian/* * File : PEPeerTransportExtensionHandler.java * Created : 16-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.peer.impl; /** * @author parg * */ import java.util.*; public interface PEPeerTransportExtensionHandler { /** * * @param details * @return all PEPeerTransport instances for this extension */ public List handleExtension( PEPeerControl manager, Map details ); } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/PEPeerTransport.java0000644000175000017500000001357711257507206025006 0ustar adrianadrian/* * File : PEPeerTransport * Created : 15-Oct-2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on 4 juil. 2003 * */ package org.gudy.azureus2.core3.peer.impl; import java.util.List; import org.gudy.azureus2.core3.disk.DiskManagerReadRequest; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.IndentWriter; import com.aelitis.azureus.core.peermanager.peerdb.PeerItem; public interface PEPeerTransport extends PEPeer { public static final int CONNECTION_PENDING = 0; public static final int CONNECTION_CONNECTING = 1; public static final int CONNECTION_WAITING_FOR_HANDSHAKE = 2; public static final int CONNECTION_FULLY_ESTABLISHED = 4; /** * Start message processing for the peer */ public void start(); public void sendChoke(); public void sendUnChoke(); public void sendHave( int piece ); public void sendCancel( DiskManagerReadRequest request ); public void sendBadPiece( int piece_number ); /** * Two methods that allow a peer to aggregate the individual requests generated during an * allocation cycle if so desired * @return true if the peer is managing request priorities and doesn't want end-game random * allocation behaviour */ public boolean requestAllocationStarts( int[] base_priorities ); public void requestAllocationComplete(); /** * * @param pieceNumber * @param pieceOffset * @param pieceLength * @return request if actually requested, null otherwise */ public DiskManagerReadRequest request( int pieceNumber, int pieceOffset, int pieceLength ); /** * Returns the index of this request in the peer's queue or -1 if not found * @return */ public int getRequestIndex( DiskManagerReadRequest request ); /** * Close the peer connection * @param reason for closure */ public void closeConnection( String reason ); public boolean transferAvailable(); public List getExpiredRequests(); /** * peer-specific request max. return -1 to use the default piece-picker allocation method * @return */ public int getMaxNbRequests(); public int getNbRequests(); public PEPeerControl getControl(); /** * Any priority offsets this peer has, or null if none * @return */ public int[] getPriorityOffsets(); /** * Check if we need to send a keep-alive message. * A keep-alive is sent if no other message has been sent within the last 2min. */ public void doKeepAliveCheck(); /** * Check for possible connection timeouts. * @return true if the connection has been timed-out, false if not */ public boolean doTimeoutChecks(); /** * Perform checks related to performance optimizations, * i.e. tune buffering related to send/receive speed. */ public void doPerformanceTuningCheck(); /** * Get the specific peer connection state. * @return connection state */ public int getConnectionState(); /** * Get the time since the last (most-recent) data (payload) message was received. * @return time count in ms, or -1 if we've never received a data message from them */ public long getTimeSinceLastDataMessageReceived(); /** * Get the time since the most-recent data that was actually written to disk was received. * @return time count in ms, or -1 if we've never received usefull data from them */ public long getTimeSinceGoodDataReceived(); /** * Get the time since the last (most-recent) data (payload) message was sent. * @return time count in ms, or -1 if we've never sent them a data message */ public long getTimeSinceLastDataMessageSent(); /** * Do any peer exchange processing/updating. */ public void updatePeerExchange(); /** * Get the peer's address + port identification item. * @return id */ public PeerItem getPeerItemIdentity(); /** * is peer waiting for a disk read with no network writes queued * @return */ public boolean isStalledPendingLoad(); /** * Is the connection within the local LAN network. * @return true if within LAN, false of outside the LAN segment */ public boolean isLANLocal(); public boolean isTCP(); /** * if it doesn't go as expected when trying to find a piece to ask a peer for, * need to double check if we're still interested in them, and get the BT protocol sycnhed */ public void checkInterested(); /** * Attempts to reconnect to the same peer * @param tryUDP try to initate a UDP connection if true, just reestablish the previous state otherwise * @param tryIPv6 TODO * @return null if reconnect not possible, reconnected peer otherwise */ public PEPeerTransport reconnect(boolean tryUDP, boolean tryIPv6); /** * This method is called to check if it is safe to reconnect to a peer, i.e. avoid hammering * exchanging data with a peer should work as it takes time to setup the connection and negotiate things before that happens * @return true if we exchanged payload data with the peer during the current connection */ public boolean isSafeForReconnect(); public void generateEvidence( IndentWriter writer ); }azureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/PEPeerControl.java0000644000175000017500000000451211124122754024411 0ustar adrianadrian/* * File : PEPeerControl.java * Created : 21-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.peer.impl; /** * @author parg * */ import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import com.aelitis.azureus.core.peermanager.peerdb.PeerItem; public interface PEPeerControl extends PEPeerManager { public boolean validateReadRequest( PEPeerTransport originator, int pieceNumber, int offset, int length ); public boolean validateHintRequest( PEPeerTransport originator, int pieceNumber, int offset, int length ); public void havePiece( int pieceNumber, int pieceLength, PEPeer pcOrigin ); public void updateSuperSeedPiece( PEPeer peer, int pieceNumber); public boolean isExtendedMessagingEnabled(); public boolean isPeerExchangeEnabled(); public byte[][] getSecrets( int crypto_level ); public int getHiddenPiece(); public void addPeerTransport( PEPeerTransport transport ); public int getMaxConnections(); public boolean doOptimisticDisconnect( boolean pending_lan_local_peer, boolean force ); public int getNbActivePieces(); public int getNbPeersStalledPendingLoad(); // Snubbed peers accounting public void incNbPeersSnubbed(); public void decNbPeersSnubbed(); public void setNbPeersSnubbed(int n); public int getNbPeersSnubbed(); public void badPieceReported( PEPeerTransport originator, int piece_number ); public boolean isRTA(); public void peerDiscovered( PEPeerTransport finder, PeerItem pi ); }azureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/transport/0000755000175000017500000000000011310377634023125 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportDebugger.java0000644000175000017500000001003010373051052030453 0ustar adrianadrian/* * Created on 14-Oct-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.peer.impl.transport; /** * CURRENTLY UNUSED * */ import java.io.*; import java.nio.*; import java.nio.channels.*; public class PEPeerTransportDebugger { protected int piece_length; protected PEPeerTransportDebugger( PEPeerTransportProtocol transport ) { piece_length = transport.getControl().getPieceLength(0); } public int write( SocketChannel chan, ByteBuffer buffer ) throws IOException { int pos = buffer.position(); int len = chan.write( buffer ); if ( len > 0 ){ buffer.position( pos ); analyse( buffer, len ); } return( len ); } public long write( SocketChannel chan, ByteBuffer[] buffers, int array_offset, int array_length ) throws IOException { int[] pos = new int[buffers.length]; for (int i=array_offset;i 0 ){ buffer.position( pos[i] ); analyse( buffer, written ); } } return( len ); } protected static final int BT_READING_LENGTH_AND_TYPE = 1234567; protected int state = -1; //bt handshake protected byte[] data_read = new byte[68]; protected int data_read_pos; protected void analyse( ByteBuffer buffer, int length ) { byte[] data = new byte[length]; buffer.get(data); for (int i=0;i 20) { Iterator it = values().iterator(); long now = SystemTime.getMonotonousTime(); while(it.hasNext() && size() > 20) { QueueEntry eldest = (QueueEntry)it.next(); if( now - eldest.addTime > MAX_CACHE_AGE){ it.remove(); }else{ break; } } } } private static final class QueueEntry { public QueueEntry(PEPeerTransportProtocol trans) { transport = trans; } final PEPeerTransportProtocol transport; final long addTime = SystemTime.getMonotonousTime(); } // hardcap at 100 protected boolean removeEldestEntry(Map.Entry eldest) { return size() > 100; } synchronized public Object put(HashWrapper key, PEPeerTransportProtocol value) { performCleaning(); return super.put(key, new QueueEntry(value)); } synchronized public PEPeerTransportProtocol remove(HashWrapper key) { performCleaning(); QueueEntry entry = (QueueEntry)super.remove(key); if(entry != null) return entry.transport; else return null; } } private static final DisconnectedTransportQueue recentlyDisconnected = new DisconnectedTransportQueue(); private static boolean fast_unchoke_new_peers; private static final Random rnd = RandomUtils.SECURE_RANDOM; private static final byte[] sessionSecret; static { rnd.setSeed(SystemTime.getHighPrecisionCounter()); sessionSecret = new byte[20]; rnd.nextBytes(sessionSecret); COConfigurationManager.addAndFireParameterListeners( new String[]{ "Use Lazy Bitfield", "Peer.Fast.Initial.Unchoke.Enabled" }, new ParameterListener() { public final void parameterChanged( String ignore ) { final String prop = System.getProperty( "azureus.lazy.bitfield" ); ENABLE_LAZY_BITFIELD = prop != null && prop.equals( "1" ); ENABLE_LAZY_BITFIELD |= COConfigurationManager.getBooleanParameter( "Use Lazy Bitfield" ); fast_unchoke_new_peers = COConfigurationManager.getBooleanParameter( "Peer.Fast.Initial.Unchoke.Enabled" ); } }); } // reconnect stuff private HashWrapper peerSessionID; private HashWrapper mySessionID; // allow reconnect if we've sent or recieved at least 1 piece over the current connection private boolean allowReconnect; private boolean is_optimistic_unchoke = false; private PeerExchangerItem peer_exchange_item = null; private boolean peer_exchange_supported = false; protected PeerMessageLimiter message_limiter; private boolean request_hint_supported; private boolean bad_piece_supported; private boolean have_aggregation_disabled; //INCOMING public PEPeerTransportProtocol( PEPeerControl _manager, String _peer_source, NetworkConnection _connection, Map _initial_user_data ) { manager = _manager; peer_source = _peer_source; connection = _connection; data = _initial_user_data; incoming = true; diskManager =manager.getDiskManager(); piecePicker =manager.getPiecePicker(); nbPieces =diskManager.getNbPieces(); InetSocketAddress notional_address = _connection.getEndpoint().getNotionalAddress(); ip = notional_address.getAddress().getHostAddress(); port = notional_address.getPort(); peer_item_identity = PeerItemFactory.createPeerItem( ip, port, PeerItem.convertSourceID( _peer_source ), PeerItemFactory.HANDSHAKE_TYPE_PLAIN, 0, PeerItemFactory.CRYPTO_LEVEL_1, 0 ); //this will be recreated upon az handshake decode plugin_connection = new ConnectionImpl(connection, incoming); peer_stats = manager.createPeerStats( this ); changePeerState( PEPeer.CONNECTING ); } public void start() { // split out connection initiation from constructor so we can get access to the peer transport // before message processing starts if ( incoming ){ //"fake" a connect request to register our listener connection.connect( ProtocolEndpoint.CONNECT_PRIORITY_MEDIUM, new NetworkConnection.ConnectionListener() { public final void connectStarted() { connection_state = PEPeerTransport.CONNECTION_CONNECTING; } public final void connectSuccess( ByteBuffer remaining_initial_data ) { //will be called immediately if (Logger.isEnabled()) Logger.log(new LogEvent(PEPeerTransportProtocol.this, LOGID, "In: Established incoming connection")); generateSessionId(); initializeConnection(); /* * Waiting until we've received the initiating-end's full handshake, before sending back our own, * really should be the "proper" behavior. However, classic BT trackers running NAT checking will * only send the first 48 bytes (up to infohash) of the peer handshake, skipping peerid, which means * we'll never get their complete handshake, and thus never reply, which causes the NAT check to fail. * So, we need to send our handshake earlier, after we've verified the infohash. * NOTE: * This code makes the assumption that the inbound infohash has already been validated, * as we don't check their handshake fully before sending our own. */ sendBTHandshake(); } public final void connectFailure( Throwable failure_msg ) { //should never happen Debug.out( "ERROR: incoming connect failure: ", failure_msg ); closeConnectionInternally( "ERROR: incoming connect failure [" + PEPeerTransportProtocol.this + "] : " + failure_msg.getMessage(), true, true ); } public final void exceptionThrown( Throwable error ) { if( error.getMessage() == null ) { Debug.out( error ); } closeConnectionInternally( "connection exception: " + error.getMessage(), false, true ); } public String getDescription() { return( getString()); } }); }else{ // not pulled out startup from outbound connections yet... } } //OUTGOING public PEPeerTransportProtocol( PEPeerControl _manager, String _peer_source, String _ip, int _tcp_port, int _udp_port, boolean _use_tcp, boolean _require_crypto_handshake, byte _crypto_level, Map _initial_user_data ) { manager = _manager; diskManager =manager.getDiskManager(); piecePicker =manager.getPiecePicker(); nbPieces =diskManager.getNbPieces(); lastNeededUndonePieceChange =Long.MIN_VALUE; peer_source = _peer_source; ip = _ip; port = _tcp_port; tcp_listen_port = _tcp_port; udp_listen_port = _udp_port; crypto_level = _crypto_level; data = _initial_user_data; if ( data != null ){ Boolean pc = (Boolean)data.get( Peer.PR_PRIORITY_CONNECTION ); if ( pc != null && pc.booleanValue()){ setPriorityConnection( true ); } } udp_non_data_port = UDPNetworkManager.getSingleton().getUDPNonDataListeningPortNumber(); peer_item_identity = PeerItemFactory.createPeerItem( ip, tcp_listen_port, PeerItem.convertSourceID( _peer_source ), PeerItemFactory.HANDSHAKE_TYPE_PLAIN, _udp_port, crypto_level, 0 ); //this will be recreated upon az handshake decode incoming = false; peer_stats = manager.createPeerStats( this ); if( port < 0 || port > 65535 ) { closeConnectionInternally( "given remote port is invalid: " + port ); return; } // either peer specific or global pref plus optional per-download level boolean use_crypto = _require_crypto_handshake || NetworkManager.getCryptoRequired( manager.getAdapter().getCryptoLevel()); if( isLANLocal() ) use_crypto = false; //dont bother with PHE for lan peers InetSocketAddress endpoint_address; ProtocolEndpoint pe; if ( _use_tcp ){ endpoint_address = new InetSocketAddress( ip, tcp_listen_port ); pe = new ProtocolEndpointTCP( endpoint_address ); }else{ endpoint_address = new InetSocketAddress( ip, udp_listen_port ); pe = new ProtocolEndpointUDP( endpoint_address ); } ConnectionEndpoint connection_endpoint = new ConnectionEndpoint( endpoint_address ); connection_endpoint.addProtocol( pe ); connection = NetworkManager.getSingleton().createConnection( connection_endpoint, new BTMessageEncoder(), new BTMessageDecoder(), use_crypto, !_require_crypto_handshake, manager.getSecrets( _crypto_level )); plugin_connection = new ConnectionImpl(connection, incoming); changePeerState( PEPeer.CONNECTING ); ByteBuffer initial_outbound_data = null; if ( use_crypto ){ BTHandshake handshake = new BTHandshake( manager.getHash(), manager.getPeerId(), manager.isExtendedMessagingEnabled(), other_peer_handshake_version ); if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, "Sending encrypted handshake with reserved bytes: " + ByteFormatter.nicePrint(handshake.getReserved(), false))); DirectByteBuffer[] ddbs = handshake.getRawData(); int handshake_len = 0; for (int i=0;i ProtocolEndpoint.CONNECT_PRIORITY_HIGH ){ priority = ProtocolEndpoint.CONNECT_PRIORITY_HIGH; } } connection.connect( initial_outbound_data, priority, new NetworkConnection.ConnectionListener() { private boolean connect_ok; public final void connectStarted() { connection_state = PEPeerTransport.CONNECTION_CONNECTING; } public final void connectSuccess( ByteBuffer remaining_initial_data ) { connect_ok = true; if( closing ) { //Debug.out( "PEPeerTransportProtocol::connectSuccess() called when closing." ); return; } generateSessionId(); if (Logger.isEnabled()) Logger.log(new LogEvent(PEPeerTransportProtocol.this, LOGID, "Out: Established outgoing connection")); initializeConnection(); if ( remaining_initial_data != null && remaining_initial_data.remaining() > 0){ // queue as a *raw* message as already encoded connection.getOutgoingMessageQueue().addMessage( new BTRawMessage( new DirectByteBuffer( remaining_initial_data )), false ); } sendBTHandshake(); } public final void connectFailure( Throwable failure_msg ) { closeConnectionInternally( "failed to establish outgoing connection: " + failure_msg.getMessage(), true, true ); } public final void exceptionThrown( Throwable error ) { if( error.getMessage() == null ) { Debug.out( "error.getMessage() == null", error ); } closeConnectionInternally( "connection exception: " + error.getMessage(), !connect_ok, true ); } public String getDescription() { return( getString()); } }); if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, "Out: Creating outgoing connection")); } protected void initializeConnection() { if( closing ) return; recent_outgoing_requests = new LinkedHashMap( 16, .75F, true ) { public final boolean removeEldestEntry(Map.Entry eldest) { return size() > 16; } }; recent_outgoing_requests_mon = new AEMonitor( "PEPeerTransportProtocol:ROR" ); message_limiter = new PeerMessageLimiter(); /* //link in outgoing piece handler outgoing_piece_message_handler = new OutgoingBTPieceMessageHandler( this, connection.getOutgoingMessageQueue(), new OutgoingBTPieceMessageHandlerAdapter() { public void diskRequestCompleted( long bytes) { peer_stats.diskReadComplete( bytes ); } }, other_peer_piece_version);*/ //link in outgoing have message aggregator outgoing_have_message_aggregator = new OutgoingBTHaveMessageAggregator( connection.getOutgoingMessageQueue(), other_peer_bt_have_version, other_peer_az_have_version ); connection_established_time = SystemTime.getCurrentTime(); connection_state = PEPeerTransport.CONNECTION_WAITING_FOR_HANDSHAKE; changePeerState( PEPeer.HANDSHAKING ); registerForMessageHandling(); } public String getPeerSource() { return( peer_source ); } /** * Close the peer connection from within the PEPeerTransport object. * @param reason */ protected void closeConnectionInternally( String reason, boolean connect_failed, boolean network_failure ) { performClose( reason, connect_failed, false, network_failure ); } protected void closeConnectionInternally( String reason ) { performClose( reason, false, false, false ); } /** * Close the peer connection from the PEPeerControl manager side. * NOTE: This method assumes PEPeerControl already knows about the close. * This method is inteded to be only invoked by select administrative methods. * You probably should not invoke this directly. */ public void closeConnection( String reason ) { performClose( reason, false, true, false ); } private void performClose( String reason, boolean connect_failed, boolean externally_closed, boolean network_failure ) { try{ closing_mon.enter(); if( closing ) return; closing = true; // immediatly lose interest in peer interested_in_other_peer =false; lastNeededUndonePieceChange =Long.MAX_VALUE; if (isSnubbed()) manager.decNbPeersSnubbed(); if( identityAdded ) { //remove identity if( peer_id != null ) PeerIdentityManager.removeIdentity( manager.getPeerIdentityDataID(), peer_id, getPort()); else Debug.out( "PeerIdentity added but peer_id == null !!!" ); identityAdded = false; } changePeerState( PEPeer.CLOSING ); }finally{ closing_mon.exit(); } //cancel any pending requests (on the manager side) cancelRequests(); if( outgoing_have_message_aggregator != null ) { outgoing_have_message_aggregator.destroy(); } if( peer_exchange_item != null ) { peer_exchange_item.destroy(); } if( outgoing_piece_message_handler != null ) { outgoing_piece_message_handler.destroy(); } if( connection != null ) { //can be null if close is called within ::::, like when the given port is invalid connection.close(); } if ( ip_resolver_request != null ){ ip_resolver_request.cancel(); } removeAvailability(); changePeerState( PEPeer.DISCONNECTED ); if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, "Peer connection closed: " + reason)); if( !externally_closed ) { //if closed internally, notify manager, otherwise we assume it already knows manager.peerConnectionClosed( this, connect_failed, network_failure ); } setPriorityConnection( false ); /* * all managed references should have been removed by now * add to recently disconnected list and null some stuff to make the object lighter */ outgoing_have_message_aggregator = null; peer_exchange_item = null; outgoing_piece_message_handler = null; plugin_connection = null; // only save stats if it's worth doing so; ignore rapid connect-disconnects if (peer_stats.getTotalDataBytesReceived() > 0 || peer_stats.getTotalDataBytesSent() > 0 || SystemTime.getCurrentTime() - connection_established_time > 30 * 1000) recentlyDisconnected.put(mySessionID, this); } public PEPeerTransport reconnect(boolean tryUDP, boolean tryIPv6) { boolean use_tcp = isTCP() && !(tryUDP && getUDPListenPort() > 0); if ((use_tcp && getTCPListenPort() > 0) || (!use_tcp && getUDPListenPort() > 0)) { boolean use_crypto = getPeerItemIdentity().getHandshakeType() == PeerItemFactory.HANDSHAKE_TYPE_CRYPTO; PEPeerTransport new_conn = PEPeerTransportFactory.createTransport( manager, getPeerSource(), tryIPv6 && alternativeAddress != null ? alternativeAddress.getHostAddress() : getIp(), getTCPListenPort(), getUDPListenPort(), use_tcp, use_crypto, crypto_level, null ); // log to both relations Logger.log(new LogEvent(new Object[] {this, new_conn},LOGID,"attempting to reconnect, creating new connection")); if (new_conn instanceof PEPeerTransportProtocol) { PEPeerTransportProtocol pt = (PEPeerTransportProtocol) new_conn; pt.checkForReconnect(mySessionID); // carry over the alt address in case the reconnect fails and we try again with ipv6 pt.alternativeAddress = alternativeAddress; } manager.addPeer( new_conn ); return (new_conn); } else { return (null); } } /* (non-Javadoc) * @see org.gudy.azureus2.core3.peer.impl.PEPeerTransport#isSafeForReconnect() */ public boolean isSafeForReconnect() { return allowReconnect; } private void checkForReconnect(HashWrapper oldID) { PEPeerTransportProtocol oldTransport = recentlyDisconnected.remove(oldID); if(oldTransport != null) { Logger.log(new LogEvent(this,LOGID,LogAlert.AT_INFORMATION,"reassociating stats from "+oldTransport+" with this connection")); peerSessionID = oldTransport.peerSessionID; peer_stats = oldTransport.peer_stats; peer_stats.setPeer(this); unchokedTimeTotal += oldTransport.unchokedTimeTotal; unchokedTime += oldTransport.unchokedTime; setSnubbed(oldTransport.isSnubbed()); snubbed = oldTransport.snubbed; last_good_data_time = oldTransport.last_good_data_time; } } private void generateSessionId() { SHA1Hasher sha1 = new SHA1Hasher(); sha1.update(sessionSecret); sha1.update(manager.getHash()); sha1.update(getIp().getBytes()); mySessionID = sha1.getHash(); checkForReconnect(mySessionID); } private void addAvailability() { if (!availabilityAdded &&!closing &&peerHavePieces !=null &¤t_peer_state ==PEPeer.TRANSFERING) { final List peer_listeners_ref =peer_listeners_cow; if (peer_listeners_ref !=null) { for (int i =0; i CVS bug report forum.\n" + "Debug data: " + ByteFormatter.nicePrint(reserved) )); } } connection.getOutgoingMessageQueue().addMessage(handshake, false); } } // We could do this in a more automated way in future, but hardcoded is simple and quick, // so we'll do that instead. :) static Map lt_ext_map = UTPeerExchange.ENABLED ? Collections.singletonMap("ut_pex", new Integer(1) ) : Collections.EMPTY_MAP; private void sendLTHandshake() { String client_name = Constants.AZUREUS_NAME + " " + Constants.AZUREUS_VERSION; int localTcpPort = TCPNetworkManager.getSingleton().getTCPListeningPortNumber(); String tcpPortOverride = COConfigurationManager.getStringParameter("TCP.Listen.Port.Override"); try { localTcpPort = Integer.parseInt(tcpPortOverride); } catch (NumberFormatException e) {} // ignore as invalid input boolean require_crypto = NetworkManager.getCryptoRequired( manager.getAdapter().getCryptoLevel()); Map data_dict = new HashMap(); data_dict.put("m", lt_ext_map); data_dict.put("v", client_name); data_dict.put("p", new Integer(localTcpPort)); data_dict.put("e", new Long(require_crypto ? 1L : 0L)); data_dict.put("upload_only", new Long(manager.isSeeding() && !ENABLE_LAZY_BITFIELD ? 1L : 0L)); InetAddress defaultV6 = NetworkAdmin.getSingleton().hasIPV6Potential(true) ? NetworkAdmin.getSingleton().getDefaultPublicAddressV6() : null; if(defaultV6 != null) data_dict.put("ipv6",defaultV6.getAddress()); LTHandshake lt_handshake = new LTHandshake( data_dict, other_peer_bt_lt_ext_version ); connection.getOutgoingMessageQueue().addMessage(lt_handshake, false); } private void sendAZHandshake() { final Message[] avail_msgs = MessageManager.getSingleton().getRegisteredMessages(); final String[] avail_ids = new String[avail_msgs.length]; final byte[] avail_vers = new byte[avail_msgs.length]; for (int i = 0; i < avail_msgs.length; i++) { avail_ids[i] = avail_msgs[i].getID(); avail_vers[i] = avail_msgs[i].getVersion(); } int local_tcp_port = TCPNetworkManager.getSingleton().getTCPListeningPortNumber(); int local_udp_port = UDPNetworkManager.getSingleton().getUDPListeningPortNumber(); int local_udp2_port = UDPNetworkManager.getSingleton().getUDPNonDataListeningPortNumber(); String tcpPortOverride = COConfigurationManager.getStringParameter("TCP.Listen.Port.Override"); try { local_tcp_port = Integer.parseInt(tcpPortOverride); } catch (NumberFormatException e) {} // ignore as invalid input boolean require_crypto = NetworkManager.getCryptoRequired(manager.getAdapter().getCryptoLevel()); /* * we always send the Az-handshake immediately after the BT-handshake, before decoding the * other side's Az-handshake, thus there should be no peerSessionID unless this is a * reconnect */ if(peerSessionID != null) Logger.log(new LogEvent(this, LOGID, LogEvent.LT_INFORMATION,"notifying peer of reconnect attempt")); AZHandshake az_handshake = new AZHandshake( AZPeerIdentityManager.getAZPeerIdentity(), mySessionID, peerSessionID, Constants.AZUREUS_NAME, Constants.AZUREUS_VERSION, local_tcp_port, local_udp_port, local_udp2_port, NetworkAdmin.getSingleton().hasIPV6Potential(true) ? NetworkAdmin.getSingleton().getDefaultPublicAddressV6() : null, avail_ids, avail_vers, require_crypto ? AZHandshake.HANDSHAKE_TYPE_CRYPTO : AZHandshake.HANDSHAKE_TYPE_PLAIN, other_peer_handshake_version, manager.isSeeding() && !ENABLE_LAZY_BITFIELD); connection.getOutgoingMessageQueue().addMessage( az_handshake, false ); } public int getPeerState() { return current_peer_state; } public boolean isDownloadPossible() { if (!closing &&!choked_by_other_peer) { if (lastNeededUndonePieceChange 0) */ private void checkSeed() { // seed implicitly means *something* to send (right?) if (peerHavePieces !=null && nbPieces >0) setSeed((peerHavePieces.nbSet ==nbPieces)); else setSeed(false); if(manager.isSeeding() && isSeed()) // peer is a real seed so it's also a relative seed relativeSeeding |= RELATIVE_SEEDING_UPLOAD_ONLY_SEED; else if(manager.isSeeding() && (relativeSeeding & RELATIVE_SEEDING_UPLOAD_ONLY_INDICATED) != 0) // peer indicated upload-only, we're seeding so he's a relative seed relativeSeeding |= RELATIVE_SEEDING_UPLOAD_ONLY_SEED; else if(peerHavePieces !=null && nbPieces > 0) { int piecesDone = manager.getPiecePicker().getNbPiecesDone(); DiskManagerPiece[] dmPieces = diskManager.getPieces(); boolean couldBeSeed = true; if(!manager.isSeeding() && (relativeSeeding & RELATIVE_SEEDING_UPLOAD_ONLY_INDICATED) != 0) { /* * peer indicated upload-only, check if we can use any of the data, otherwise flag * as relative seed. Useful to disconnect not-useful pseudo-seeds during downloading */ for(int i = peerHavePieces.start;i <= peerHavePieces.end;i++) { // relative seed if peer doesn't have the piece, we already have it or we don't need it couldBeSeed &= !peerHavePieces.flags[i] || dmPieces[i].isDone() || !dmPieces[i].isNeeded(); if(!couldBeSeed) break; } } else if(manager.isSeeding() && piecesDone <= peerHavePieces.nbSet) { // we're seeding, check if peer has all the data we have (and more), flag as relative seed if so for(int i = peerHavePieces.start;i <= peerHavePieces.end;i++) { // relative seed if we don't have the piece or we have it and the peer has it too couldBeSeed &= !(dmPieces[i].isDone()) || peerHavePieces.flags[i]; if(!couldBeSeed) break; } } else couldBeSeed = false; if(couldBeSeed) relativeSeeding |= RELATIVE_SEEDING_UPLOAD_ONLY_SEED; else relativeSeeding &= ~RELATIVE_SEEDING_UPLOAD_ONLY_SEED; } else relativeSeeding &= ~RELATIVE_SEEDING_UPLOAD_ONLY_SEED; } public DiskManagerReadRequest request(final int pieceNumber, final int pieceOffset, final int pieceLength) { final DiskManagerReadRequest request =manager.createDiskManagerRequest(pieceNumber, pieceOffset, pieceLength); if (current_peer_state != TRANSFERING) { manager.requestCanceled(request); return null; } boolean added =false; try{ requested_mon.enter(); if (!requested.contains(request)) { requested.add(request); added =true; } }finally{ requested_mon.exit(); } if (added) { connection.getOutgoingMessageQueue().addMessage( new BTRequest( pieceNumber, pieceOffset, pieceLength, other_peer_request_version ), false ); _lastPiece =pieceNumber; try{ recent_outgoing_requests_mon.enter(); recent_outgoing_requests.put( request, null ); }finally{ recent_outgoing_requests_mon.exit(); } return request; } return null; } public int getRequestIndex( DiskManagerReadRequest request ) { try{ requested_mon.enter(); return( requested.indexOf( request )); }finally{ requested_mon.exit(); } } public void sendCancel( DiskManagerReadRequest request ) { if ( current_peer_state != TRANSFERING ) return; if ( hasBeenRequested( request ) ) { removeRequest( request ); connection.getOutgoingMessageQueue().addMessage( new BTCancel( request.getPieceNumber(), request.getOffset(), request.getLength(), other_peer_cancel_version ), false ); } } public void sendHave( int pieceNumber ) { if ( current_peer_state != TRANSFERING || pieceNumber == manager.getHiddenPiece()) return; //only force if the other peer doesn't have this piece and is not yet interested or we;ve disabled // aggregation final boolean force =!other_peer_interested_in_me &&peerHavePieces !=null &&!peerHavePieces.flags[pieceNumber]; outgoing_have_message_aggregator.queueHaveMessage( pieceNumber, force || have_aggregation_disabled ); checkInterested(); } public void sendChoke() { if ( current_peer_state != TRANSFERING ) return; //System.out.println( "["+(System.currentTimeMillis()/1000)+"] " +connection + " choked"); connection.getOutgoingMessageQueue().addMessage( new BTChoke( other_peer_choke_version ), false ); choking_other_peer = true; is_optimistic_unchoke = false; if(outgoing_piece_message_handler != null) { outgoing_piece_message_handler.removeAllPieceRequests(); outgoing_piece_message_handler.destroy(); outgoing_piece_message_handler = null; } } public void sendUnChoke() { if ( current_peer_state != TRANSFERING ) return; //System.out.println( "["+(System.currentTimeMillis()/1000)+"] " +connection + " unchoked"); if(outgoing_piece_message_handler == null) { outgoing_piece_message_handler = new OutgoingBTPieceMessageHandler( this, connection.getOutgoingMessageQueue(), new OutgoingBTPieceMessageHandlerAdapter() { public void diskRequestCompleted( long bytes) { peer_stats.diskReadComplete( bytes ); } }, other_peer_piece_version); } choking_other_peer = false; // set this first as with pseudo peers we can effectively synchronously act // on the unchoke advice and we don't want that borking with choked still set connection.getOutgoingMessageQueue().addMessage( new BTUnchoke(other_peer_unchoke_version), false ); } private void sendKeepAlive() { if ( current_peer_state != TRANSFERING ) return; if( outgoing_have_message_aggregator.hasPending() ) { outgoing_have_message_aggregator.forceSendOfPending(); } else { connection.getOutgoingMessageQueue().addMessage( new BTKeepAlive(other_peer_keep_alive_version), false ); } } private void sendMainlineDHTPort() { if (!this.ml_dht_enabled) {return;} MainlineDHTProvider provider = getDHTProvider(); if (provider == null) {return;} Message message = new BTDHTPort(provider.getDHTPort()); connection.getOutgoingMessageQueue().addMessage(message, false); } /** * Global checkInterested method. * Early-out scan of pieces to determine if the peer is interesting or not. * They're interesting if they have a piece that we Need and isn't Done */ public void checkInterested() { if (closing ||peerHavePieces ==null ||peerHavePieces.nbSet ==0) return; boolean is_interesting = false; if (piecePicker.hasDownloadablePiece()) { // there is a piece worth being interested in if (!isSeed() && !isRelativeSeed()) { // check individually if don't have all for (int i =peerHavePieces.start; i <=peerHavePieces.end; i++ ) { if (peerHavePieces.flags[i] && diskManager.isInteresting(i)) { is_interesting = true; break; } } } else is_interesting =true; } if (is_interesting &&!interested_in_other_peer) connection.getOutgoingMessageQueue().addMessage(new BTInterested(other_peer_interested_version), false); else if (!is_interesting &&interested_in_other_peer) connection.getOutgoingMessageQueue().addMessage(new BTUninterested(other_peer_uninterested_version), false); interested_in_other_peer = is_interesting; } /** @deprecated no longer used by CVS code * Checks if a particular piece makes us interested in the peer * @param pieceNumber the piece number that has been received */ /* private void checkInterested(int pieceNumber) { if (closing) return; // Do we need this piece and it's not Done? if (!interested_in_other_peer &&diskManager.isInteresting(pieceNumber)) { connection.getOutgoingMessageQueue().addMessage( new BTInterested(), false ); interested_in_other_peer =true; } } */ /** * Private method to send the bitfield. */ private void sendBitField() { if (closing) return; //In case we're in super seed mode, we don't send our bitfield if (manager.isSuperSeedMode()) return; //create bitfield final DirectByteBuffer buffer =DirectByteBufferPool.getBuffer(DirectByteBuffer.AL_MSG, (nbPieces +7) /8); final DiskManagerPiece[] pieces =diskManager.getPieces(); int num_pieces = pieces.length; HashSet lazies = null; int[] lazy_haves = null; if (ENABLE_LAZY_BITFIELD) { int bits_in_first_byte = Math.min(num_pieces, 8); int last_byte_start_bit = (num_pieces / 8) * 8; int bits_in_last_byte = num_pieces - last_byte_start_bit; if (bits_in_last_byte == 0) { bits_in_last_byte = 8; last_byte_start_bit -= 8; } lazies = new HashSet(); // one bit from first byte int first_byte_entry = rnd.nextInt(bits_in_first_byte); if (pieces[first_byte_entry].isDone()) { lazies.add(new MutableInteger(first_byte_entry)); } // one bit from last byte int last_byte_entry = last_byte_start_bit + rnd.nextInt(bits_in_last_byte); if (pieces[last_byte_entry].isDone()) { lazies.add(new MutableInteger(last_byte_entry)); } // random others missing int other_lazies = rnd.nextInt(16) + 4; for (int i = 0; i < other_lazies; i++) { int random_entry = rnd.nextInt(num_pieces); if (pieces[random_entry].isDone()) { lazies.add(new MutableInteger(random_entry)); } } int num_lazy = lazies.size(); if (num_lazy == 0) { lazies = null; } else { lazy_haves = new int[num_lazy]; Iterator it = lazies.iterator(); for (int i = 0; i < num_lazy; i++) { int lazy_have = ((MutableInteger) it.next()).getValue(); lazy_haves[i] = lazy_have; } if (num_lazy > 1) { for (int i = 0; i < num_lazy; i++) { int swap = rnd.nextInt(num_lazy); if (swap != i) { int temp = lazy_haves[swap]; lazy_haves[swap] = lazy_haves[i]; lazy_haves[i] = temp; } } } } } int bToSend = 0; int i = 0; MutableInteger mi = new MutableInteger(0); int hidden_piece = manager.getHiddenPiece(); for (; i " + i ); }else{ bToSend += 1; } }else{ bToSend += 1; } } if ((i %8) ==7){ buffer.put(DirectByteBuffer.SS_BT, (byte) bToSend); } } if ((i %8) !=0){ bToSend = bToSend << (8 - (i % 8)); buffer.put( DirectByteBuffer.SS_BT, (byte)bToSend ); } buffer.flip( DirectByteBuffer.SS_BT ); connection.getOutgoingMessageQueue().addMessage(new BTBitfield(buffer, other_peer_bitfield_version ), false); if ( lazy_haves != null ){ final int[] f_lazy_haves = lazy_haves; SimpleTimer.addEvent("LazyHaveSender", SystemTime.getCurrentTime() + 1000 + rnd.nextInt(2000), new TimerEventPerformer() { int next_have = 0; public void perform(TimerEvent event) { int lazy_have = f_lazy_haves[next_have++]; // System.out.println( "LazyDone: " + getIp() + " -> " + // lazy_have ); if ( current_peer_state == TRANSFERING ){ connection.getOutgoingMessageQueue().addMessage(new BTHave(lazy_have, other_peer_bt_have_version), false); if (next_have < f_lazy_haves.length && current_peer_state == TRANSFERING){ SimpleTimer.addEvent("LazyHaveSender", SystemTime.getCurrentTime() + rnd.nextInt(2000), this); } } } }); } } public byte[] getId() { return peer_id; } public String getIp() { return ip; } public InetAddress getAlternativeIPv6() { return alternativeAddress; } public int getPort() { return port; } public int getTCPListenPort() { return tcp_listen_port; } public int getUDPListenPort() { return udp_listen_port; } public int getUDPNonDataListenPort() { return( udp_non_data_port ); } public String getClient() { return client; } public boolean isIncoming() { return incoming; } public boolean isOptimisticUnchoke() { return is_optimistic_unchoke && !isChokedByMe(); } public void setOptimisticUnchoke( boolean is_optimistic ) { is_optimistic_unchoke = is_optimistic; } public PEPeerControl getControl() { return manager; } public PEPeerManager getManager() { return manager; } public PEPeerStats getStats() { return peer_stats; } public int[] getPriorityOffsets() { // normal peer has no special priority requirements return( null ); } public boolean requestAllocationStarts( int[] base_priorities ) { return( false ); } public void requestAllocationComplete() { } /** * @return null if no bitfield has been recieved yet * else returns BitFlags indicating what pieces the peer has */ public BitFlags getAvailable() { return peerHavePieces; } public boolean isPieceAvailable(int pieceNumber) { if (peerHavePieces !=null) return peerHavePieces.flags[pieceNumber]; return false; } public boolean isChokingMe() { return choked_by_other_peer; } public boolean isChokedByMe() { return choking_other_peer; } /** * @return true if the peer is interesting to us */ public boolean isInteresting() { return interested_in_other_peer; } /** * @return true if the peer is interested in what we're offering */ public boolean isInterested() { return other_peer_interested_in_me; } public boolean isSeed() { return seeding; } public boolean isRelativeSeed() { return (relativeSeeding & RELATIVE_SEEDING_UPLOAD_ONLY_SEED) != 0; } private void setSeed( boolean s ) { if ( seeding != s ){ seeding = s; if ( peer_exchange_item != null && s){ peer_exchange_item.seedStatusChanged(); } } } public boolean isSnubbed() { return snubbed !=0; } public long getSnubbedTime() { if (snubbed ==0) return 0; final long now =SystemTime.getCurrentTime(); if (now 0) unchokedTimeTotal +=unchoked; } } } } public void setUploadHint(int spreadTime) { spreadTimeHint = spreadTime; } public int getUploadHint() { return spreadTimeHint; } public void setUniqueAnnounce(int _uniquePiece) { uniquePiece = _uniquePiece; } public int getUniqueAnnounce() { return uniquePiece; } public Object getData(String key) { return( getUserData( key )); } public void setData(String key, Object value) { setUserData( key, value ); } /** To retreive arbitrary objects against a peer. */ public Object getUserData (Object key) { try{ general_mon.enter(); if (data == null) return null; return data.get(key); }finally{ general_mon.exit(); } } /** To store arbitrary objects against a peer. */ public void setUserData (Object key, Object value) { try{ general_mon.enter(); if (data == null) { data = new LightHashMap(); } if (value == null) { if (data.containsKey(key)){ data.remove(key); if ( data.size()==0 ){ data = null; } } } else { data.put(key, value); } }finally{ general_mon.exit(); } } public String getIPHostName() { if ( ip_resolved == null ){ ip_resolved = ip; ip_resolver_request = IPToHostNameResolver.addResolverRequest( ip_resolved, new IPToHostNameResolverListener() { public final void IPResolutionComplete( String res, boolean ok ) { ip_resolved = res; } }); } return( ip_resolved ); } private void cancelRequests() { if (!closing) { //cancel any unsent requests in the queue final Message[] type ={new BTRequest(-1, -1, -1, other_peer_request_version)}; connection.getOutgoingMessageQueue().removeMessagesOfType(type, false); } if (requested !=null &&requested.size() >0) { try{ requested_mon.enter(); if (!closing) { // may have unchoked us, gotten a request, then choked without filling it - snub them // if they actually have data coming in, they'll be unsnubbed as soon as it writes final long timeSinceGoodData =getTimeSinceGoodDataReceived(); if (timeSinceGoodData ==-1 ||timeSinceGoodData >60 *1000) setSnubbed(true); } for (int i = requested.size() - 1; i >= 0; i--) { final DiskManagerReadRequest request =(DiskManagerReadRequest) requested.remove(i); manager.requestCanceled(request); } }finally{ requested_mon.exit(); } } } public int getMaxNbRequests() { return( -1 ); } public int getNbRequests() { return requested.size(); } /** * * @return may be null for performance purposes */ public List getExpiredRequests() { List result = null; // this is frequently called, hence we operate without a monitor and // take the hit of possible exceptions due to concurrent list // modification (only out-of-bounds can occur) try{ for (int i =requested.size() -1; i >=0; i--) { final DiskManagerReadRequest request = (DiskManagerReadRequest) requested.get(i); if (request.isExpired()){ if ( result == null ){ result = new ArrayList(); } result.add(request); } } return( result ); }catch(Throwable e ){ return result; } } private boolean hasBeenRequested( DiskManagerReadRequest request ) { try{ requested_mon.enter(); return requested.contains( request ); } finally{ requested_mon.exit(); } } /** @deprecated no longer used by CVS code */ protected void addRequest( DiskManagerReadRequest request ) { try{ requested_mon.enter(); requested.add(request); }finally{ requested_mon.exit(); } _lastPiece =request.getPieceNumber(); } protected void removeRequest( DiskManagerReadRequest request ) { try{ requested_mon.enter(); requested.remove(request); }finally{ requested_mon.exit(); } final BTRequest msg = new BTRequest( request.getPieceNumber(), request.getOffset(), request.getLength(), other_peer_request_version ); connection.getOutgoingMessageQueue().removeMessage( msg, false ); msg.destroy(); } private void resetRequestsTime(final long now) { try{ requested_mon.enter(); final int requestedSize =requested.size(); for (int i =0; i 2*60*1000 ) { //2min keep-alive timer sendKeepAlive(); last_message_sent_time =now; //not quite true, but we don't want to queue multiple keep-alives before the first is actually sent } } public boolean doTimeoutChecks() { //Timeouts for states PEPeerTransport.CONNECTION_PENDING and //PEPeerTransport.CONNECTION_CONNECTING are handled by the ConnectDisconnectManager //so we don't need to deal with them here. final long now =SystemTime.getCurrentTime(); //make sure we time out stalled connections if( connection_state == PEPeerTransport.CONNECTION_FULLY_ESTABLISHED ) { if (last_message_received_time >now) last_message_received_time =now; if (last_data_message_received_time >now) last_data_message_received_time =now; if (now -last_message_received_time >5*60*1000 &&now -last_data_message_received_time >5*60*1000) { //5min timeout // assume this is due to a network failure // e.g. something that didn't close the TCP socket properly // will attempt reconnect closeConnectionInternally( "timed out while waiting for messages", false, true ); return true; } } //ensure we dont get stuck in the handshaking phases else if( connection_state == PEPeerTransport.CONNECTION_WAITING_FOR_HANDSHAKE ) { if (connection_established_time >now) connection_established_time =now; else if (now - connection_established_time > 3*60*1000 ) { //3min timeout closeConnectionInternally( "timed out while waiting for handshake" ); return true; } } return false; } public void doPerformanceTuningCheck() { Transport transport = connection.getTransport(); if( transport != null && peer_stats != null && outgoing_piece_message_handler != null ) { //send speed -based tuning final long send_rate = peer_stats.getDataSendRate() + peer_stats.getProtocolSendRate(); if( send_rate >= 3125000 ) { // 25 Mbit/s transport.setTransportMode( Transport.TRANSPORT_MODE_TURBO ); outgoing_piece_message_handler.setRequestReadAhead( 256 ); } else if( send_rate >= 1250000 ) { // 10 Mbit/s transport.setTransportMode( Transport.TRANSPORT_MODE_TURBO ); outgoing_piece_message_handler.setRequestReadAhead( 128 ); } else if( send_rate >= 125000 ) { // 1 Mbit/s if( transport.getTransportMode() < Transport.TRANSPORT_MODE_FAST ) { transport.setTransportMode( Transport.TRANSPORT_MODE_FAST ); } outgoing_piece_message_handler.setRequestReadAhead( 32 ); } else if( send_rate >= 62500 ) { // 500 Kbit/s outgoing_piece_message_handler.setRequestReadAhead( 16 ); } else if( send_rate >= 31250 ) { // 250 Kbit/s outgoing_piece_message_handler.setRequestReadAhead( 8 ); } else if( send_rate >= 12500 ) { // 100 Kbit/s outgoing_piece_message_handler.setRequestReadAhead( 4 ); } else { outgoing_piece_message_handler.setRequestReadAhead( 2 ); } //receive speed -based tuning final long receive_rate = peer_stats.getDataReceiveRate() + peer_stats.getProtocolReceiveRate(); if( receive_rate >= 1250000 ) { // 10 Mbit/s transport.setTransportMode( Transport.TRANSPORT_MODE_TURBO ); } else if( receive_rate >= 125000 ) { // 1 Mbit/s if( transport.getTransportMode() < Transport.TRANSPORT_MODE_FAST ) { transport.setTransportMode( Transport.TRANSPORT_MODE_FAST ); } } } } public int getConnectionState() { return connection_state; } public long getTimeSinceLastDataMessageReceived() { if( last_data_message_received_time == -1 ) { //never received return -1; } final long now =SystemTime.getCurrentTime(); if (last_data_message_received_time >now) last_data_message_received_time =now; //time went backwards return now -last_data_message_received_time; } public long getTimeSinceGoodDataReceived() { if (last_good_data_time ==-1) return -1; // never received final long now =SystemTime.getCurrentTime(); if (last_good_data_time >now) last_good_data_time =now; //time went backwards return now -last_good_data_time; } public long getTimeSinceLastDataMessageSent() { if( last_data_message_sent_time == -1 ) { //never sent return -1; } final long now =SystemTime.getCurrentTime(); if (last_data_message_sent_time >now) last_data_message_sent_time =now; //time went backwards return now -last_data_message_sent_time; } public long getTimeSinceConnectionEstablished() { if( connection_established_time == 0 ) { //fudge it while the transport is being connected return 0; } final long now =SystemTime.getCurrentTime(); if (connection_established_time >now) connection_established_time =now; return now -connection_established_time; } public int getConsecutiveNoRequestCount() { return( consecutive_no_request_count ); } public void setConsecutiveNoRequestCount( int num ) { consecutive_no_request_count = num; } protected void decodeBTHandshake( BTHandshake handshake ) { if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, "Received handshake with reserved bytes: " + ByteFormatter.nicePrint(handshake.getReserved(), false))); PeerIdentityDataID my_peer_data_id = manager.getPeerIdentityDataID(); if(getConnectionState() == CONNECTION_FULLY_ESTABLISHED) { handshake.destroy(); closeConnectionInternally("peer sent another handshake after the initial connect"); } if( !Arrays.equals( manager.getHash(), handshake.getDataHash() ) ) { closeConnectionInternally( "handshake has wrong infohash" ); handshake.destroy(); return; } peer_id = handshake.getPeerId(); // Decode a client identification string from the given peerID this.client_peer_id = this.client = StringInterner.intern(PeerClassifier.getClientDescription( peer_id )); //make sure the client type is not banned if( !PeerClassifier.isClientTypeAllowed( client ) ) { closeConnectionInternally( client+ " client type not allowed to connect, banned" ); handshake.destroy(); return; } //make sure we are not connected to ourselves if( Arrays.equals( manager.getPeerId(), peer_id ) ) { manager.peerVerifiedAsSelf( this ); //make sure we dont do it again closeConnectionInternally( "given peer id matches myself" ); handshake.destroy(); return; } //make sure we are not already connected to this peer boolean sameIdentity = PeerIdentityManager.containsIdentity( my_peer_data_id, peer_id, getPort()); boolean sameIP = false; //allow loopback connects for co-located proxy-based connections and testing boolean same_allowed = COConfigurationManager.getBooleanParameter( "Allow Same IP Peers" ) || ip.equals( "127.0.0.1" ); if( !same_allowed ){ if( PeerIdentityManager.containsIPAddress( my_peer_data_id, ip )) { sameIP = true; } } if( sameIdentity ) { boolean close = true; if( connection.isLANLocal() ) { //this new connection is lan-local PEPeerTransport existing = manager.getTransportFromIdentity( peer_id ); if( existing != null ){ String existing_ip = existing.getIp(); // normally we don't allow a lan-local to replace a lan-local connection. There is // however one exception - where the existing connection comes from the gateway address // and therefore actually denotes an effectively non-lan-local connection. Unfortunately // we don't have a good way of finding the default gateway, so just go for ending in .1 if ( !existing.isLANLocal() || ( existing_ip.endsWith( ".1" ) && !existing_ip.equals( ip ))) { //so drop the existing connection if it is an external (non lan-local) one Debug.outNoStack( "Dropping existing non-lanlocal peer connection [" +existing+ "] in favour of [" + this + "]" ); manager.removePeer( existing ); close = false; } } } if( close ) { closeConnectionInternally( "peer matches already-connected peer id" ); handshake.destroy(); return; } } if( sameIP ) { closeConnectionInternally( "peer matches already-connected IP address, duplicate connections not allowed" ); handshake.destroy(); return; } //make sure we haven't reached our connection limit final int maxAllowed = manager.getMaxNewConnectionsAllowed(); if ( maxAllowed ==0 && !manager.doOptimisticDisconnect( isLANLocal(), isPriorityConnection())) { final String msg = "too many existing peer connections [p" + PeerIdentityManager.getIdentityCount( my_peer_data_id ) +"/g" +PeerIdentityManager.getTotalIdentityCount() +", pmx" +PeerUtils.MAX_CONNECTIONS_PER_TORRENT+ "/gmx" +PeerUtils.MAX_CONNECTIONS_TOTAL+"/dmx" + manager.getMaxConnections()+ "]"; //System.out.println( msg ); closeConnectionInternally( msg ); handshake.destroy(); return; } try{ closing_mon.enter(); if( closing ){ final String msg = "connection already closing"; closeConnectionInternally( msg ); handshake.destroy(); return; } if ( !PeerIdentityManager.addIdentity( my_peer_data_id, peer_id, getPort(), ip )){ closeConnectionInternally( "peer matches already-connected peer id" ); handshake.destroy(); return; } identityAdded = true; }finally{ closing_mon.exit(); } if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, "In: has sent their handshake")); // Let's store the reserved bits somewhere so they can be examined later (externally). handshake_reserved_bytes = handshake.getReserved(); /* * Waiting until we've received the initiating-end's full handshake, before sending back our own, * really should be the "proper" behavior. However, classic BT trackers running NAT checking will * only send the first 48 bytes (up to infohash) of the peer handshake, skipping peerid, which means * we'll never get their complete handshake, and thus never reply, which causes the NAT check to fail. * So, we need to send our handshake earlier, after we've verified the infohash. * if( incoming ) { //wait until we've received their handshake before sending ours sendBTHandshake(); } */ this.ml_dht_enabled = (handshake_reserved_bytes[7] & 1) == 1; messaging_mode = decideExtensionProtocol(handshake); //extended protocol processing if (messaging_mode == MESSAGING_AZMP) { /** * We log when a non-Azureus client claims to support extended messaging... * Obviously other Azureus clients do, so there's no point logging about them! */ if (Logger.isEnabled() && client.indexOf("Azureus") == -1) { Logger.log(new LogEvent(this, LOGID, "Handshake claims extended AZ " + "messaging support... enabling AZ mode.")); } // Ignore the handshake setting - wait for the AZHandshake to indicate // support instead. this.ml_dht_enabled = false; Transport transport = connection.getTransport(); boolean enable_padding = transport.isTCP() && transport.isEncrypted(); connection.getIncomingMessageQueue().setDecoder(new AZMessageDecoder()); connection.getOutgoingMessageQueue().setEncoder(new AZMessageEncoder(enable_padding)); // We will wait until we get the Az handshake before considering the connection // initialised. this.sendAZHandshake(); handshake.destroy(); } else if (messaging_mode == MESSAGING_LTEP) { if (Logger.isEnabled()) { Logger.log(new LogEvent(this, LOGID, "Enabling LT extension protocol support...")); } connection.getIncomingMessageQueue().setDecoder(new LTMessageDecoder()); connection.getOutgoingMessageQueue().setEncoder(new LTMessageEncoder(this)); generateSessionId(); /** * We don't need to wait for the LT handshake, nor do we require it, nor * does it matter if the LT handshake comes later, nor does it matter if * it we receive it repeatedly. So there - we can initialise the connection * right now. :P */ this.initPostConnection(handshake); this.sendLTHandshake(); } else { this.client = ClientIdentifier.identifyBTOnly(this.client_peer_id, this.handshake_reserved_bytes); connection.getIncomingMessageQueue().getDecoder().resumeDecoding(); this.initPostConnection(handshake); } } private int decideExtensionProtocol(BTHandshake handshake) { boolean supports_azmp = (handshake.getReserved()[0] & 128) == 128; boolean supports_ltep = (handshake.getReserved()[5] & 16) == 16; if (!supports_azmp) { if (supports_ltep) { if (!manager.isExtendedMessagingEnabled()) { if (Logger.isEnabled()) { Logger.log(new LogEvent(this, LOGID, "Ignoring peer's LT extension protocol support," + " as disabled for this download.")); } return MESSAGING_BT_ONLY; // LTEP is supported, but disabled. } return MESSAGING_LTEP; // LTEP is supported. } return MESSAGING_BT_ONLY; // LTEP isn't supported. } if (!supports_ltep) { // Check if it is AZMP enabled. if(!manager.isExtendedMessagingEnabled()) { if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, "Ignoring peer's extended AZ messaging support," + " as disabled for this download.")); return MESSAGING_BT_ONLY; } // Check if the client is misbehaving... else if( client.indexOf( "Plus!" ) != -1) { if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, "Handshake mistakingly indicates" + " extended AZ messaging support...ignoring.")); return MESSAGING_BT_ONLY; } return MESSAGING_AZMP; } boolean enp_major_bit = (handshake.getReserved()[5] & 2) == 2; boolean enp_minor_bit = (handshake.getReserved()[5] & 1) == 1; // Only enable one of the blocks below. String their_ext_preference = ((enp_major_bit == enp_minor_bit) ? "Force " : "Prefer ") + ((enp_major_bit) ? "AZMP" : "LTEP"); // Force AZMP block. String our_ext_preference = "Force AZMP"; boolean use_azmp = enp_major_bit || enp_minor_bit; // Anything other than Force LTEP, then we force AZMP to be used. boolean we_decide = use_azmp; // Prefer AZMP block (untested). /* String our_ext_preference = "Prefer AZMP"; boolean use_azmp = enp_major_bit; // Requires other client to prefer or force AZMP. boolean we_decide = use_azmp && !enp_minor_bit; // We decide only if we are using AZMP and the other client didn't force it. */ // Prefer LTEP block (untested). /* String our_ext_preference = "Prefer LTEP"; boolean use_azmp = enp_major_bit && enp_minor_bit; // Only use it Force AZMP is enabled. boolean we_decide = enp_minor_bit && !use_azmp; // We decide only if we are using LTEP and the other client didn't force it. */ if (Logger.isEnabled()) { String msg = "Peer supports both AZMP and LTEP: "; msg += "\"" + our_ext_preference + "\"" + (we_decide ? ">" : "<") + ((our_ext_preference.equals(their_ext_preference)) ? "= " : " "); msg += "\"" + their_ext_preference + "\" - using " + (use_azmp ? "AZMP" : "LTEP"); Logger.log(new LogEvent(this, LOGID, msg)); } return (use_azmp) ? MESSAGING_AZMP : MESSAGING_LTEP; } protected void decodeLTHandshake(LTHandshake handshake) { String lt_handshake_name = handshake.getClientName(); if (lt_handshake_name != null) { this.client_handshake = StringInterner.intern(lt_handshake_name); this.client = StringInterner.intern(ClientIdentifier.identifyLTEP(this.client_peer_id, this.client_handshake, this.peer_id)); } if(handshake.getTCPListeningPort() > 0 ) { // Only use crypto if it was specifically requested. Not sure what the default // should be if they haven't indicated... Boolean crypto_requested = handshake.isCryptoRequested(); byte handshake_type = (crypto_requested != null && crypto_requested.booleanValue()) ? PeerItemFactory.HANDSHAKE_TYPE_CRYPTO : PeerItemFactory.HANDSHAKE_TYPE_PLAIN; tcp_listen_port = handshake.getTCPListeningPort(); peer_item_identity = PeerItemFactory.createPeerItem( ip, tcp_listen_port, PeerItem.convertSourceID(peer_source), handshake_type, udp_listen_port, // probably none crypto_level, 0 ); } if(handshake.isUploadOnly()) { relativeSeeding |= RELATIVE_SEEDING_UPLOAD_ONLY_INDICATED; checkSeed(); } if(AddressUtils.isGlobalAddressV6(handshake.getIPv6())) alternativeAddress = handshake.getIPv6(); LTMessageEncoder encoder = (LTMessageEncoder)connection.getOutgoingMessageQueue().getEncoder(); encoder.updateSupportedExtensions(handshake.getExtensionMapping()); this.ut_pex_enabled = UTPeerExchange.ENABLED && encoder.supportsUTPEX(); /** * Grr... this is one thing which I'm sure I had figured out much better than it is here... * Basically, we "initialise" the connection at the BT handshake stage, because the LT handshake * is mandatory or required to come first (unlike the AZ one). * * But when we receive an LT handshake, we have to "initialise" it like we did previously, because * we may have to set the internals up to indicate if PEX is supported. * * I'm not entirely sure this method is meant to be called more than once, and I'm less convinced * that it's safe to do it repeatedly over the lifetime of a properly-initialised, actually-doing-stuff * connection... but I'll worry about that later. */ this.doPostHandshakeProcessing(); handshake.destroy(); } protected void decodeAZHandshake(AZHandshake handshake) { if(getConnectionState() == CONNECTION_FULLY_ESTABLISHED) { handshake.destroy(); closeConnectionInternally("peer sent another az-handshake after the intial connect"); } this.client_handshake = StringInterner.intern(handshake.getClient()); this.client_handshake_version = StringInterner.intern(handshake.getClientVersion()); this.client = StringInterner.intern(ClientIdentifier.identifyAZMP(this.client_peer_id, client_handshake, client_handshake_version, this.peer_id)); if (handshake.getTCPListenPort() > 0) { // use the ports given in handshake tcp_listen_port = handshake.getTCPListenPort(); udp_listen_port = handshake.getUDPListenPort(); udp_non_data_port = handshake.getUDPNonDataListenPort(); final byte type = handshake.getHandshakeType() == AZHandshake.HANDSHAKE_TYPE_CRYPTO ? PeerItemFactory.HANDSHAKE_TYPE_CRYPTO : PeerItemFactory.HANDSHAKE_TYPE_PLAIN; // remake the id using the peer's remote listen port instead of // their random local port peer_item_identity = PeerItemFactory.createPeerItem(ip, tcp_listen_port, PeerItem.convertSourceID(peer_source), type, udp_listen_port, crypto_level, 0); } if(AddressUtils.isGlobalAddressV6(handshake.getIPv6())) alternativeAddress = handshake.getIPv6(); if(handshake.getReconnectSessionID() != null) { if (Logger.isEnabled()) { Logger.log(new LogEvent(this, LOGID, LogEvent.LT_INFORMATION, "received reconnect request ID: "+handshake.getReconnectSessionID().toBase32String())); } checkForReconnect(handshake.getReconnectSessionID()); } if(handshake.getRemoteSessionID() != null) peerSessionID = handshake.getRemoteSessionID(); if (handshake.isUploadOnly()) { relativeSeeding |= RELATIVE_SEEDING_UPLOAD_ONLY_INDICATED; checkSeed(); } String[] supported_message_ids = handshake.getMessageIDs(); byte[] supported_message_versions = handshake.getMessageVersions(); //find mutually available message types final ArrayList messages = new ArrayList(); for (int i = 0; i < handshake.getMessageIDs().length; i++) { Message msg = MessageManager.getSingleton().lookupMessage(supported_message_ids[i]); if (msg != null) { // mutual support! messages.add(msg); String id = msg.getID(); byte supported_version = supported_message_versions[i]; // we can use == safely if (id == BTMessage.ID_BT_BITFIELD) other_peer_bitfield_version = supported_version; else if (id == BTMessage.ID_BT_CANCEL) other_peer_cancel_version = supported_version; else if (id == BTMessage.ID_BT_CHOKE) other_peer_choke_version = supported_version; else if (id == BTMessage.ID_BT_HANDSHAKE) other_peer_handshake_version = supported_version; else if (id == BTMessage.ID_BT_HAVE) other_peer_bt_have_version = supported_version; else if (id == BTMessage.ID_BT_INTERESTED) other_peer_interested_version = supported_version; else if (id == BTMessage.ID_BT_KEEP_ALIVE) other_peer_keep_alive_version = supported_version; else if (id == BTMessage.ID_BT_PIECE) other_peer_piece_version = supported_version; else if (id == BTMessage.ID_BT_UNCHOKE) other_peer_unchoke_version = supported_version; else if (id == BTMessage.ID_BT_UNINTERESTED) other_peer_uninterested_version = supported_version; else if (id == BTMessage.ID_BT_REQUEST) other_peer_request_version = supported_version; else if (id == AZMessage.ID_AZ_PEER_EXCHANGE) other_peer_pex_version = supported_version; else if (id == AZMessage.ID_AZ_REQUEST_HINT) other_peer_az_request_hint_version = supported_version; else if (id == AZMessage.ID_AZ_HAVE) other_peer_az_have_version = supported_version; else if (id == AZMessage.ID_AZ_BAD_PIECE) other_peer_az_bad_piece_version = supported_version; else if (id == BTMessage.ID_BT_DHT_PORT) this.ml_dht_enabled = true; else { // we expect unmatched ones here at the moment as we're not // dealing with them yet or they don't make sense. // for example AZVER } } } supported_messages = (Message[]) messages.toArray(new Message[messages.size()]); if(outgoing_piece_message_handler != null){ outgoing_piece_message_handler.setPieceVersion(other_peer_piece_version); } if ( outgoing_have_message_aggregator != null ){ outgoing_have_message_aggregator.setHaveVersion(other_peer_bt_have_version, other_peer_az_have_version); } this.initPostConnection(handshake); } private void initPostConnection(Message handshake) { changePeerState(PEPeer.TRANSFERING); connection_state = PEPeerTransport.CONNECTION_FULLY_ESTABLISHED; sendBitField(); handshake.destroy(); addAvailability(); sendMainlineDHTPort(); } protected void decodeBitfield( BTBitfield bitfield ) { received_bitfield = true; final DirectByteBuffer field =bitfield.getBitfield(); final byte[] dataf =new byte[(nbPieces +7) /8]; if( field.remaining( DirectByteBuffer.SS_PEER ) < dataf.length ) { final String error = toString() + " has sent invalid Bitfield: too short [" +field.remaining( DirectByteBuffer.SS_PEER )+ "<" +dataf.length+ "]"; Debug.out( error ); if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, LogEvent.LT_ERROR, error )); bitfield.destroy(); return; } field.get( DirectByteBuffer.SS_PEER, dataf ); try{ closing_mon.enter(); if (closing) bitfield.destroy(); else { final BitFlags tempHavePieces; if (peerHavePieces ==null) { tempHavePieces =new BitFlags(nbPieces); } else { tempHavePieces =peerHavePieces; removeAvailability(); } for (int i =0; i >bit); if ((b &0x01) ==1) { tempHavePieces.set(i); manager.updateSuperSeedPiece(this,i); } } bitfield.destroy(); peerHavePieces =tempHavePieces; addAvailability(); checkSeed(); checkInterested(); } } finally{ closing_mon.exit(); } } protected void decodeMainlineDHTPort(BTDHTPort port) { int i_port = port.getDHTPort(); port.destroy(); if (!this.ml_dht_enabled) {return;} MainlineDHTProvider provider = getDHTProvider(); if (provider == null) {return;} try {provider.notifyOfIncomingPort(getIp(), i_port);} catch (Throwable t) {Debug.printStackTrace(t);} } protected void decodeChoke( BTChoke choke ) { choke.destroy(); if (!choked_by_other_peer) { choked_by_other_peer = true; cancelRequests(); final long unchoked =SystemTime.getCurrentTime() -unchokedTime; if (unchoked >0 &&!isSnubbed()) unchokedTimeTotal +=unchoked; } } protected void decodeUnchoke( BTUnchoke unchoke ) { unchoke.destroy(); if (choked_by_other_peer) { choked_by_other_peer = false; if (!isSnubbed()) unchokedTime =SystemTime.getCurrentTime(); } } protected void decodeInterested( BTInterested interested ) { interested.destroy(); // Don't allow known seeds to be interested in us other_peer_interested_in_me = !(isSeed() || isRelativeSeed()); if ( other_peer_interested_in_me && fast_unchoke_new_peers && isChokedByMe() && getData( "fast_unchoke_done" ) == null ){ setData( "fast_unchoke_done", "" ); sendUnChoke(); } } protected void decodeUninterested( BTUninterested uninterested ) { uninterested.destroy(); other_peer_interested_in_me = false; //force send any pending haves in case one of them would make the other peer interested again if( outgoing_have_message_aggregator != null ) { outgoing_have_message_aggregator.forceSendOfPending(); } } protected void decodeHave( BTHave have ) { final int pieceNumber =have.getPieceNumber(); have.destroy(); if ((pieceNumber >=nbPieces) ||(pieceNumber <0)) { closeConnectionInternally("invalid pieceNumber: " +pieceNumber); return; } if (closing) return; if (peerHavePieces ==null) peerHavePieces =new BitFlags(nbPieces); if (!peerHavePieces.flags[pieceNumber]) { if (!interested_in_other_peer &&diskManager.isInteresting(pieceNumber)) { connection.getOutgoingMessageQueue().addMessage(new BTInterested(other_peer_interested_version), false); interested_in_other_peer =true; } peerHavePieces.set(pieceNumber); final int pieceLength =manager.getPieceLength(pieceNumber); manager.havePiece(pieceNumber, pieceLength, this); checkSeed(); // maybe a seed using lazy bitfield, or suddenly became a seed; other_peer_interested_in_me &= !(isSeed() || isRelativeSeed()); // never consider seeds interested peer_stats.hasNewPiece(pieceLength); } } protected void decodeAZHave( AZHave have ) { final int[] pieceNumbers = have.getPieceNumbers(); have.destroy(); if ( closing ){ return; } if ( peerHavePieces == null ){ peerHavePieces = new BitFlags( nbPieces ); } boolean send_interested = false; boolean new_have = false; for (int i=0;i= nbPieces) ||(pieceNumber <0)) { closeConnectionInternally("invalid pieceNumber: " +pieceNumber); return; } if ( !peerHavePieces.flags[pieceNumber]){ new_have = true; if ( !( send_interested || interested_in_other_peer ) && diskManager.isInteresting(pieceNumber)){ send_interested = true; } peerHavePieces.set(pieceNumber); final int pieceLength =manager.getPieceLength(pieceNumber); manager.havePiece(pieceNumber, pieceLength, this); peer_stats.hasNewPiece(pieceLength); } } if ( new_have ){ checkSeed(); // maybe a seed using lazy bitfield, or suddenly became a seed; other_peer_interested_in_me &= !(isSeed() && isRelativeSeed()); // never consider seeds interested } if ( send_interested ){ connection.getOutgoingMessageQueue().addMessage(new BTInterested(other_peer_interested_version), false); interested_in_other_peer = true; } } protected long getBytesDownloaded() { if (peerHavePieces ==null ||peerHavePieces.flags.length ==0) return 0; final long total_done; if ( peerHavePieces.flags[nbPieces-1] ){ total_done = ((long)(peerHavePieces.nbSet -1) *diskManager.getPieceLength()) +diskManager.getPieceLength( nbPieces -1 ); }else{ total_done =(long)peerHavePieces.nbSet *diskManager.getPieceLength(); } return( Math.min( total_done, diskManager.getTotalLength())); } public long getBytesRemaining() { return( diskManager.getTotalLength() - getBytesDownloaded()); } public void sendBadPiece( int piece_number ) { if ( bad_piece_supported ){ AZBadPiece bp = new AZBadPiece( piece_number, other_peer_az_bad_piece_version ); connection.getOutgoingMessageQueue().addMessage( bp, false ); } } protected void decodeAZBadPiece( AZBadPiece bad_piece ) { final int piece_number = bad_piece.getPieceNumber(); bad_piece.destroy(); manager.badPieceReported( this, piece_number ); } protected void decodeRequest( BTRequest request ) { final int number = request.getPieceNumber(); final int offset = request.getPieceOffset(); final int length = request.getLength(); request.destroy(); if( !manager.validateReadRequest( this, number, offset, length ) ) { closeConnectionInternally( "request for piece #" + number + ":" + offset + "->" + (offset + length -1) + " is an invalid request" ); return; } if ( manager.getHiddenPiece() == number ){ closeConnectionInternally( "request for piece #" + number + " is invalid as piece is hidden" ); return; } if( !choking_other_peer ) { outgoing_piece_message_handler.addPieceRequest( number, offset, length ); allowReconnect = true; } else { if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, "decodeRequest(): peer request for piece #" + number + ":" + offset + "->" + (offset + length -1) + " ignored as peer is currently choked.")); } } protected void decodePiece( BTPiece piece ) { final int pieceNumber = piece.getPieceNumber(); final int offset = piece.getPieceOffset(); final DirectByteBuffer payload = piece.getPieceData(); final int length = payload.remaining( DirectByteBuffer.SS_PEER ); /* if ( AEDiagnostics.CHECK_DUMMY_FILE_DATA ){ int pos = payload.position( DirectByteBuffer.SS_PEER ); long off = ((long)number) * getControl().getPieceLength(0) + offset; for (int i=0;i" + (offset + length -1) + ", " ); } }; if( !manager.validatePieceReply( this, pieceNumber, offset, payload ) ) { peer_stats.bytesDiscarded( length ); manager.discarded( this, length ); requests_discarded++; printRequestStats(); piece.destroy(); if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, LogEvent.LT_ERROR, error_msg +"but piece block discarded as invalid.")); return; } final DiskManagerReadRequest request = manager.createDiskManagerRequest( pieceNumber, offset, length ); boolean piece_error = true; if( hasBeenRequested( request ) ) { //from active request removeRequest( request ); final long now =SystemTime.getCurrentTime(); resetRequestsTime(now); if( manager.isWritten( pieceNumber, offset ) ) { //oops, looks like this block has already been written peer_stats.bytesDiscarded( length ); manager.discarded( this, length ); if( manager.isInEndGameMode() ) { //we're probably in end-game mode then if (last_good_data_time !=-1 &&now -last_good_data_time <=60 *1000) setSnubbed(false); last_good_data_time =now; requests_discarded_endgame++; if (Logger.isEnabled()) Logger.log(new LogEvent(this, LogIDs.PIECES, LogEvent.LT_INFORMATION, error_msg +"but piece block ignored as already written in end-game mode.")); } else { // if they're not snubbed, then most likely this peer got a re-request after some other peer // snubbed themselves, and the slow peer finially finished the piece, but before this peer did // so give credit to this peer anyway for having delivered a block at this time if (!isSnubbed()) last_good_data_time =now; if (Logger.isEnabled()) Logger.log(new LogEvent(this, LogIDs.PIECES, LogEvent.LT_WARNING, error_msg +"but piece block discarded as already written.")); requests_discarded++; } printRequestStats(); } else { //successfully received block! manager.writeBlock( pieceNumber, offset, payload, this, false); if (last_good_data_time !=-1 &&now -last_good_data_time <=60 *1000) setSnubbed( false ); last_good_data_time =now; requests_completed++; piece_error = false; //dont destroy message, as we've passed the payload on to the disk manager for writing } } else { //initial request may have already expired, but check if we can use the data anyway if( !manager.isWritten( pieceNumber, offset ) ) { final boolean ever_requested; try{ recent_outgoing_requests_mon.enter(); ever_requested = recent_outgoing_requests.containsKey( request ); } finally{ recent_outgoing_requests_mon.exit(); } if( ever_requested ) { //security-measure: we dont want to be accepting any ol' random block manager.writeBlock( pieceNumber, offset, payload, this, true); final long now =SystemTime.getCurrentTime(); if (last_good_data_time !=-1 &&now -last_good_data_time <=60 *1000) setSnubbed(false); resetRequestsTime(now); last_good_data_time =now; requests_recovered++; printRequestStats(); piece_error = false; //dont destroy message, as we've passed the payload on to the disk manager for writing if (Logger.isEnabled()) Logger.log(new LogEvent(this, LogIDs.PIECES, LogEvent.LT_INFORMATION, error_msg +"expired piece block data recovered as useful.")); } else { System.out.println( "[" +client+ "]" +error_msg + "but expired piece block discarded as never requested." ); peer_stats.bytesDiscarded( length ); manager.discarded( this, length ); requests_discarded++; printRequestStats(); if (Logger.isEnabled()) Logger.log(new LogEvent(this, LogIDs.PIECES, LogEvent.LT_ERROR, error_msg +"but expired piece block discarded as never requested.")); } } else { peer_stats.bytesDiscarded( length ); manager.discarded( this, length ); requests_discarded++; printRequestStats(); if (Logger.isEnabled()) Logger.log(new LogEvent(this, LogIDs.PIECES, LogEvent.LT_WARNING, error_msg +"but expired piece block discarded as already written.")); } } if( piece_error ) piece.destroy(); else allowReconnect = true; } protected void decodeCancel( BTCancel cancel ) { int number = cancel.getPieceNumber(); int offset = cancel.getPieceOffset(); int length = cancel.getLength(); cancel.destroy(); if(outgoing_piece_message_handler != null) outgoing_piece_message_handler.removePieceRequest( number, offset, length ); } private void registerForMessageHandling() { //INCOMING MESSAGES connection.getIncomingMessageQueue().registerQueueListener( new IncomingMessageQueue.MessageQueueListener() { public final boolean messageReceived( Message message ) { if (Logger.isEnabled()) Logger.log(new LogEvent(PEPeerTransportProtocol.this, LogIDs.NET, "Received [" + message.getDescription() + "] message")); final long now =SystemTime.getCurrentTime(); last_message_received_time =now; if( message.getType() == Message.TYPE_DATA_PAYLOAD ) { last_data_message_received_time =now; } String message_id = message.getID(); if( message_id.equals( BTMessage.ID_BT_PIECE ) ) { decodePiece( (BTPiece)message ); return true; } if( closing ) { message.destroy(); return true; } if(message_id.equals( BTMessage.ID_BT_KEEP_ALIVE ) ) { message.destroy(); //make sure they're not spamming us if( !message_limiter.countIncomingMessage( message.getID(), 6, 60*1000 ) ) { //allow max 6 keep-alives per 60sec System.out.println( manager.getDisplayName() + ": Incoming keep-alive message flood detected, dropping spamming peer connection." +PEPeerTransportProtocol.this ); closeConnectionInternally( "Incoming keep-alive message flood detected, dropping spamming peer connection." ); } return true; } if( message_id.equals( BTMessage.ID_BT_HANDSHAKE ) ) { decodeBTHandshake( (BTHandshake)message ); return true; } if( message_id.equals( AZMessage.ID_AZ_HANDSHAKE ) ) { decodeAZHandshake( (AZHandshake)message ); return true; } if (message_id.equals(LTMessage.ID_LT_HANDSHAKE)) { decodeLTHandshake((LTHandshake)message); return true; } if( message_id.equals( BTMessage.ID_BT_BITFIELD ) ) { decodeBitfield( (BTBitfield)message ); return true; } if( message_id.equals( BTMessage.ID_BT_CHOKE ) ) { decodeChoke( (BTChoke)message ); if( choking_other_peer ) { connection.enableEnhancedMessageProcessing( false, manager.getPartitionID()); //downgrade back to normal handler } return true; } if( message_id.equals( BTMessage.ID_BT_UNCHOKE ) ) { decodeUnchoke( (BTUnchoke)message ); connection.enableEnhancedMessageProcessing( true, manager.getPartitionID() ); //make sure we use a fast handler for the resulting download return true; } if( message_id.equals( BTMessage.ID_BT_INTERESTED ) ) { decodeInterested( (BTInterested)message ); return true; } if( message_id.equals( BTMessage.ID_BT_UNINTERESTED ) ) { decodeUninterested( (BTUninterested)message ); return true; } if( message_id.equals( BTMessage.ID_BT_HAVE ) ) { decodeHave( (BTHave)message ); return true; } if( message_id.equals( BTMessage.ID_BT_REQUEST ) ) { decodeRequest( (BTRequest)message ); return true; } if( message_id.equals( BTMessage.ID_BT_CANCEL ) ) { decodeCancel( (BTCancel)message ); return true; } if (message_id.equals(BTMessage.ID_BT_DHT_PORT)) { decodeMainlineDHTPort((BTDHTPort)message); return true; } if( message_id.equals( AZMessage.ID_AZ_PEER_EXCHANGE ) ) { decodePeerExchange( (AZPeerExchange)message ); return true; } if (message_id.equals(LTMessage.ID_UT_PEX)) { decodePeerExchange((UTPeerExchange)message); return true; } if( message_id.equals( AZMessage.ID_AZ_REQUEST_HINT ) ) { decodeAZRequestHint( (AZRequestHint)message ); return true; } if( message_id.equals( AZMessage.ID_AZ_HAVE ) ) { decodeAZHave((AZHave)message ); return true; } if( message_id.equals( AZMessage.ID_AZ_BAD_PIECE ) ) { decodeAZBadPiece((AZBadPiece)message ); return true; } return false; } public final void protocolBytesReceived( int byte_count ) { //update stats peer_stats.protocolBytesReceived( byte_count ); manager.protocolBytesReceived( PEPeerTransportProtocol.this, byte_count ); } public final void dataBytesReceived( int byte_count ) { // Observe that the peer is sending data so that if theyre so slow that the whole // data block times out, we don't think theyre not sending anything at all last_data_message_received_time =SystemTime.getCurrentTime(); //update stats peer_stats.dataBytesReceived( byte_count ); manager.dataBytesReceived( PEPeerTransportProtocol.this, byte_count ); } }); //OUTGOING MESSAGES connection.getOutgoingMessageQueue().registerQueueListener( new OutgoingMessageQueue.MessageQueueListener() { public final boolean messageAdded( Message message ) { return true; } public final void messageQueued( Message message ) { /* ignore */ } public final void messageRemoved( Message message ) { /*ignore*/ } public final void messageSent( Message message ) { //update keep-alive info final long now =SystemTime.getCurrentTime(); last_message_sent_time =now; if( message.getType() == Message.TYPE_DATA_PAYLOAD ) { last_data_message_sent_time =now; } if( message.getID().equals( BTMessage.ID_BT_UNCHOKE ) ) { // is about to send piece data connection.enableEnhancedMessageProcessing( true, manager.getPartitionID() ); //so make sure we use a fast handler } else if( message.getID().equals( BTMessage.ID_BT_CHOKE ) ) { // is done sending piece data if( choked_by_other_peer ) { connection.enableEnhancedMessageProcessing( false, manager.getPartitionID() ); //so downgrade back to normal handler } } if (Logger.isEnabled()) Logger.log(new LogEvent(PEPeerTransportProtocol.this, LogIDs.NET, "Sent [" + message.getDescription() + "] message")); } public final void protocolBytesSent( int byte_count ) { //update stats peer_stats.protocolBytesSent( byte_count ); manager.protocolBytesSent( PEPeerTransportProtocol.this, byte_count ); } public final void dataBytesSent( int byte_count ) { //update stats peer_stats.dataBytesSent( byte_count ); manager.dataBytesSent( PEPeerTransportProtocol.this, byte_count ); } public void flush(){} }); //start message processing connection.addRateLimiter( manager.getUploadLimitedRateGroup(), true ); connection.addRateLimiter( manager.getDownloadLimitedRateGroup(), false ); connection.startMessageProcessing(); } public void addRateLimiter( LimitedRateGroup limiter, boolean upload ) { connection.addRateLimiter( limiter, upload ); } public void removeRateLimiter( LimitedRateGroup limiter, boolean upload ) { connection.removeRateLimiter( limiter, upload ); } public Connection getPluginConnection() { return plugin_connection; } public Message[] getSupportedMessages() { return supported_messages; } public boolean supportsMessaging() { return supported_messages != null; } public int getMessagingMode() { return messaging_mode; } public byte[] getHandshakeReservedBytes() { return this.handshake_reserved_bytes; } public void setHaveAggregationEnabled( boolean enabled ) { have_aggregation_disabled = !enabled; } public boolean hasReceivedBitField() { return( received_bitfield ); } public String getEncryption() { Transport transport = connection.getTransport(); if ( transport == null ){ return( "" ); } return( transport.getEncryption( false )); } public void addListener( PEPeerListener listener ) { try{ peer_listeners_mon.enter(); if( peer_listeners_cow == null ){ peer_listeners_cow = new ArrayList(); } final List new_listeners = new ArrayList( peer_listeners_cow ); new_listeners.add( listener ); peer_listeners_cow = new_listeners; }finally{ peer_listeners_mon.exit(); } } public void removeListener( PEPeerListener listener ) { try{ peer_listeners_mon.enter(); if ( peer_listeners_cow != null ){ List new_listeners = new ArrayList( peer_listeners_cow ); new_listeners.remove( listener ); if ( new_listeners.isEmpty()){ new_listeners = null; } peer_listeners_cow = new_listeners; } }finally{ peer_listeners_mon.exit(); } } private void changePeerState( int new_state ) { current_peer_state = new_state; if( current_peer_state == PEPeer.TRANSFERING ) { //YUCK! doPostHandshakeProcessing(); } final List peer_listeners_ref = peer_listeners_cow; if ( peer_listeners_ref != null ){ for( int i=0; i < peer_listeners_ref.size(); i++ ) { final PEPeerListener l = (PEPeerListener)peer_listeners_ref.get( i ); l.stateChanged(this, current_peer_state); } } } /** * this method might be called repeatedly since LTEP allows headers to be sent more than once * make sure that multiple invokations do not have unintended consequences */ private void doPostHandshakeProcessing() { //peer exchange registration if( manager.isPeerExchangeEnabled()) { //try and register all connections for their peer exchange info if(peer_exchange_item == null && canBePeerExchanged()){ peer_exchange_item = manager.createPeerExchangeConnection( this ); } if( peer_exchange_item != null ) { //check for peer exchange support if(ut_pex_enabled || peerSupportsMessageType(AZMessage.ID_AZ_PEER_EXCHANGE)) { peer_exchange_supported = true; } else { //no need to maintain internal states as we wont be sending/receiving peer exchange messages peer_exchange_item.disableStateMaintenance(); } } } request_hint_supported = peerSupportsMessageType( AZMessage.ID_AZ_REQUEST_HINT ); bad_piece_supported = peerSupportsMessageType( AZMessage.ID_AZ_BAD_PIECE ); } private boolean canBePeerExchanged() { if ( client_peer_id != null ){ // disable the exchange of location targetted peers boolean ok = !client_peer_id.startsWith( PeerClassifier.CACHE_LOGIC ); // System.out.println( "canPEX: " + client_peer_id + " -> " + ok ); return( ok ); }else{ Debug.out( "No client peer id!" ); return( false ); } } private boolean peerSupportsMessageType( String message_id ) { if( supported_messages != null ) { for( int i=0; i < supported_messages.length; i++ ) { if( supported_messages[i].getID().equals( message_id ) ) return true; } } return false; } public void updatePeerExchange() { if ( current_peer_state != TRANSFERING ) return; if( !peer_exchange_supported ) return; if( peer_exchange_item != null && manager.isPeerExchangeEnabled()) { final PeerItem[] adds = peer_exchange_item.getNewlyAddedPeerConnections(); final PeerItem[] drops = peer_exchange_item.getNewlyDroppedPeerConnections(); if( (adds != null && adds.length > 0) || (drops != null && drops.length > 0) ) { if (ut_pex_enabled) { connection.getOutgoingMessageQueue().addMessage( new UTPeerExchange(adds, drops, null, (byte)0), false); } else { connection.getOutgoingMessageQueue().addMessage( new AZPeerExchange( manager.getHash(), adds, drops, other_peer_pex_version ), false ); } } } } protected void decodePeerExchange( AZStylePeerExchange exchange ) { // if we're seeding ignore µT-PEXed seeds, Az won't send them in the first place final PeerItem[] added = exchange instanceof UTPeerExchange ? ((UTPeerExchange)exchange).getAddedPeers(!manager.isSeeding()) : exchange.getAddedPeers(); final PeerItem[] dropped = exchange.getDroppedPeers(); //make sure they're not spamming us if( !message_limiter.countIncomingMessage( exchange.getID(), 7, 120*1000 ) ) { //allow max 7 PEX per 2min //TODO reduce max after 2308 release? System.out.println( manager.getDisplayName() + ": Incoming PEX message flood detected, dropping spamming peer connection." +PEPeerTransportProtocol.this ); closeConnectionInternally( "Incoming PEX message flood detected, dropping spamming peer connection." ); return; } exchange.destroy(); if( ( added != null && added.length > exchange.getMaxAllowedPeersPerVolley(!this.has_received_initial_pex, true)) || ( dropped != null && dropped.length > exchange.getMaxAllowedPeersPerVolley(!this.has_received_initial_pex, false))) { //drop these too-large messages as they seem to be used for DOS by swarm poisoners closeConnectionInternally( "Invalid PEX message received: too large, dropping likely poisoner peer connection." ); return; } this.has_received_initial_pex = true; if( peer_exchange_supported && peer_exchange_item != null && manager.isPeerExchangeEnabled()){ if( added != null ) { for( int i=0; i < added.length; i++ ) { PeerItem pi = added[i]; manager.peerDiscovered( this, pi ); peer_exchange_item.addConnectedPeer( pi ); } } if( dropped != null ) { for( int i=0; i < dropped.length; i++ ) { peer_exchange_item.dropConnectedPeer( dropped[i] ); } } } else { if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, "Peer Exchange disabled for this download, " + "dropping received exchange message")); } } public boolean sendRequestHint( int piece_number, int offset, int length, int life ) { if ( request_hint_supported ){ AZRequestHint rh = new AZRequestHint( piece_number, offset, length, life, other_peer_az_request_hint_version ); connection.getOutgoingMessageQueue().addMessage( rh, false ); return( true ); }else{ return( false ); } } protected void decodeAZRequestHint( AZRequestHint hint ) { int piece_number = hint.getPieceNumber(); int offset = hint.getOffset(); int length = hint.getLength(); int life = hint.getLife(); hint.destroy(); if ( life > REQUEST_HINT_MAX_LIFE ){ life = REQUEST_HINT_MAX_LIFE; } if ( manager.validateHintRequest( this, piece_number, offset, length )){ if ( request_hint == null ){ // we ignore life time currently as once hinted we don't accept another hint // until that one is satisfied. This is to prevent too many pieces starting request_hint = new int[]{ piece_number, offset, length }; } } } public int[] getRequestHint() { return( request_hint ); } public void clearRequestHint() { request_hint = null; } public PeerItem getPeerItemIdentity() { return peer_item_identity; } public int getReservedPieceNumber() { return reservedPiece; } public void setReservedPieceNumber(int pieceNumber) { reservedPiece = pieceNumber; } public int getIncomingRequestCount() { if ( outgoing_piece_message_handler == null ){ return( 0 ); } return outgoing_piece_message_handler.getRequestCount(); } public int getOutgoingRequestCount() { return( getNbRequests()); } public int getOutboundDataQueueSize() { return( connection.getOutgoingMessageQueue().getTotalSize()); } public boolean isStalledPendingLoad() { if ( outgoing_piece_message_handler == null ){ return( false ); } return outgoing_piece_message_handler.isStalledPendingLoad(); } public int[] getIncomingRequestedPieceNumbers() { if ( outgoing_piece_message_handler == null ){ return( new int[0]); } return outgoing_piece_message_handler.getRequestedPieceNumbers(); } public int[] getOutgoingRequestedPieceNumbers() { try{ requested_mon.enter(); /** Cheap hack to reduce (but not remove all) the # of duplicate entries */ int iLastNumber = -1; // allocate max size needed (we'll shrink it later) final int[] pieceNumbers = new int[requested.size()]; int pos = 0; for (int i = 0; i < requested.size(); i++) { DiskManagerReadRequest request = null; try { request = (DiskManagerReadRequest) requested.get(i); } catch (Exception e) { Debug.printStackTrace(e); } if (request != null && iLastNumber != request.getPieceNumber()) { iLastNumber = request.getPieceNumber(); pieceNumbers[pos++] = iLastNumber; } } final int[] trimmed = new int[pos]; System.arraycopy(pieceNumbers, 0, trimmed, 0, pos); return trimmed; }finally{ requested_mon.exit(); } } public int getPercentDoneOfCurrentIncomingRequest() { return( connection.getIncomingMessageQueue().getPercentDoneOfCurrentMessage()); } public int getPercentDoneOfCurrentOutgoingRequest() { return( connection.getOutgoingMessageQueue().getPercentDoneOfCurrentMessage()); } /* (non-Javadoc) * @see org.gudy.azureus2.core3.logging.LogRelation#getLogRelationText() */ public String getRelationText() { String text = ""; if (manager instanceof LogRelation) text = ((LogRelation)manager).getRelationText() + "; "; text += "Peer: " + toString(); return text; } /* (non-Javadoc) * @see org.gudy.azureus2.core3.logging.LogRelation#queryForClass(java.lang.Class) */ public Object[] getQueryableInterfaces() { return new Object[] { manager }; } public int getLastPiece() { return _lastPiece; } public void setLastPiece(int pieceNumber) { _lastPiece =pieceNumber; } public boolean isLANLocal() { if( connection == null ) return( AddressUtils.isLANLocalAddress( ip ) == AddressUtils.LAN_LOCAL_YES ); return connection.isLANLocal(); } public boolean isTCP() { return( connection.getEndpoint().getProtocols()[0].getType() == ProtocolEndpoint.PROTOCOL_TCP ); } public long getUnchokedTimeTotal() { if (choked_by_other_peer) return unchokedTimeTotal; return unchokedTimeTotal +(SystemTime.getCurrentTime() -unchokedTime); } public void setUploadRateLimitBytesPerSecond( int bytes ){ connection.setUploadLimit( bytes ); } public void setDownloadRateLimitBytesPerSecond( int bytes ){ connection.setDownloadLimit( bytes ); } public int getUploadRateLimitBytesPerSecond(){ return connection.getUploadLimit(); } public int getDownloadRateLimitBytesPerSecond(){ return connection.getDownloadLimit(); } public String getClientNameFromPeerID() {return this.client_peer_id;} public String getClientNameFromExtensionHandshake() { if (!this.client_handshake.equals("") && !this.client_handshake_version.equals("")) { return this.client_handshake + " " + this.client_handshake_version; } return this.client_handshake; } private static MainlineDHTProvider getDHTProvider() { return AzureusCoreImpl.getSingleton().getGlobalManager().getMainlineDHTProvider(); } public void setPriorityConnection( boolean is_priority ) { synchronized( this ){ if ( priority_connection == is_priority ){ return; } priority_connection = is_priority; } manager.getAdapter().priorityConnectionChanged( is_priority ); } public boolean isPriorityConnection() { synchronized( this ){ return( priority_connection ); } } public void generateEvidence( IndentWriter writer ) { writer.println( "ip=" + getIp() + ",in=" + isIncoming() + ",port=" + getPort() + ",cli=" + client + ",tcp=" + getTCPListenPort() + ",udp=" + getUDPListenPort() + ",oudp=" + getUDPNonDataListenPort() + ",p_state=" + getPeerState() + ",c_state=" + getConnectionState() + ",seed=" + isSeed() + "partialSeed=" + isRelativeSeed() + ",pex=" + peer_exchange_supported + ",closing=" + closing ); writer.println( " choked=" + choked_by_other_peer + ",choking=" + choking_other_peer + ",unchoke_time=" + unchokedTime + ", unchoke_total=" + unchokedTimeTotal + ",is_opt=" + is_optimistic_unchoke ); writer.println( " interested=" + interested_in_other_peer + ",interesting=" + other_peer_interested_in_me + ",snubbed=" + snubbed ); writer.println( " lp=" + _lastPiece + ",up=" + uniquePiece + ",rp=" + reservedPiece ); writer.println( " last_sent=" + last_message_sent_time + "/" + last_data_message_sent_time + ",last_recv=" + last_message_received_time + "/" + last_data_message_received_time + "/" + last_good_data_time ); writer.println( " conn_at=" + connection_established_time + ",cons_no_reqs=" + consecutive_no_request_count + ",discard=" + requests_discarded + "/" + requests_discarded_endgame + ",recov=" + requests_recovered + ",comp=" + requests_completed ); } protected static class MutableInteger { private int value; protected MutableInteger( int v ) { value = v; } protected void setValue( int v ) { value = v; } protected int getValue() { return( value ); } public int hashCode() { return value; } public boolean equals( Object obj ) { if (obj instanceof MutableInteger) { return value == ((MutableInteger)obj).value; } return false; } } } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/control/0000755000175000017500000000000011310377634022551 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/control/SuperSeedPiece.java0000644000175000017500000000554410124101272026252 0ustar adrianadrian/* * File : SuperSeedPiece.java * Created : 13 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.peer.impl.control; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.impl.PEPeerControl; import org.gudy.azureus2.core3.util.*; /** * @author Olivier * */ public class SuperSeedPiece { //private PEPeerControl manager; private int pieceNumber; private int level; private long timeFirstDistributed; private PEPeer firstReceiver; //private int numberOfPeersWhenFirstReceived; private int timeToReachAnotherPeer; // use class monitor to reduce number of monitor objects (low contention here) private static AEMonitor class_mon = new AEMonitor( "SuperSeedPiece:class" ); public SuperSeedPiece(PEPeerControl manager,int _pieceNumber) { Ignore.ignore( manager ); pieceNumber = _pieceNumber; level = 0; } public void peerHasPiece(PEPeer peer) { try{ class_mon.enter(); if(level < 2) { firstReceiver = peer; timeFirstDistributed = SystemTime.getCurrentTime(); //numberOfPeersWhenFirstReceived = manager.getNbPeers(); } else { if(peer != null && firstReceiver != null) { timeToReachAnotherPeer = (int) (SystemTime.getCurrentTime() - timeFirstDistributed); firstReceiver.setUploadHint(timeToReachAnotherPeer); } } level = 2; }finally{ class_mon.exit(); } } public int getLevel() { return level; } public void pieceRevealedToPeer() { try{ class_mon.enter(); level = 1; }finally{ class_mon.exit(); } } /** * @return Returns the pieceNumber. */ public int getPieceNumber() { return pieceNumber; } public void peerLeft() { if(level == 1) level = 0; } public void updateTime() { if(level < 2) return; if(timeToReachAnotherPeer > 0) return; if(firstReceiver == null) return; int timeToSend = (int) (SystemTime.getCurrentTime() - timeFirstDistributed); if(timeToSend > firstReceiver.getUploadHint()) firstReceiver.setUploadHint(timeToSend); } } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/control/SuperSeedPeer.java0000644000175000017500000000235607766774100026146 0ustar adrianadrian/* * File : SuperSeedPeer.java * Created : 14 dc. 2003} * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.peer.impl.control; import org.gudy.azureus2.core3.peer.PEPeer; /** * @author Olivier * */ public class SuperSeedPeer implements Comparable{ public PEPeer peer; public SuperSeedPeer(PEPeer peer) { this.peer = peer; } public int compareTo(Object obj) { SuperSeedPeer otherPeer = (SuperSeedPeer) obj; return this.peer.getUploadHint() - otherPeer.peer.getUploadHint(); } } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/control/PEPeerControlImpl.java0000644000175000017500000034774011273741774026746 0ustar adrianadrian/* * Created by Olivier Chalouhi * Modified Apr 13, 2004 by Alon Rohter * Heavily modified Sep 2005 by Joseph Bridgewater * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.peer.impl.control; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.ipfilter.*; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.peer.*; import org.gudy.azureus2.core3.peer.impl.*; import org.gudy.azureus2.core3.peer.util.PeerIdentityDataID; import org.gudy.azureus2.core3.peer.util.PeerIdentityManager; import org.gudy.azureus2.core3.peer.util.PeerUtils; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponsePeer; import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.download.DownloadAnnounceResultPeer; import org.gudy.azureus2.plugins.peers.Peer; import org.gudy.azureus2.plugins.peers.PeerDescriptor; import com.aelitis.azureus.core.networkmanager.LimitedRateGroup; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPConnectionManager; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager; import com.aelitis.azureus.core.networkmanager.impl.udp.UDPNetworkManager; import com.aelitis.azureus.core.peermanager.control.PeerControlInstance; import com.aelitis.azureus.core.peermanager.control.PeerControlScheduler; import com.aelitis.azureus.core.peermanager.control.PeerControlSchedulerFactory; import com.aelitis.azureus.core.peermanager.nat.PeerNATInitiator; import com.aelitis.azureus.core.peermanager.nat.PeerNATTraversalAdapter; import com.aelitis.azureus.core.peermanager.nat.PeerNATTraverser; import com.aelitis.azureus.core.peermanager.peerdb.*; import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker; import com.aelitis.azureus.core.peermanager.piecepicker.PiecePickerFactory; import com.aelitis.azureus.core.peermanager.unchoker.Unchoker; import com.aelitis.azureus.core.peermanager.unchoker.UnchokerFactory; import com.aelitis.azureus.core.peermanager.unchoker.UnchokerUtil; import com.aelitis.azureus.core.peermanager.uploadslots.UploadHelper; import com.aelitis.azureus.core.peermanager.uploadslots.UploadSlotManager; import com.aelitis.azureus.core.util.FeatureAvailability; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.core.util.bloom.BloomFilterFactory; /** * manages all peer transports for a torrent * * @author MjrTom * 2005/Oct/08: Numerous changes for new piece-picking. Also * a few optimizations and multi-thread cleanups * 2006/Jan/02: refactoring piece picking related code */ @SuppressWarnings("serial") public class PEPeerControlImpl extends LogRelation implements PEPeerControl, ParameterListener, DiskManagerWriteRequestListener, PeerControlInstance, PeerNATInitiator, DiskManagerCheckRequestListener, IPFilterListener { private static final LogIDs LOGID = LogIDs.PEER; private static final int WARNINGS_LIMIT = 2; private static final int CHECK_REASON_DOWNLOADED = 1; private static final int CHECK_REASON_COMPLETE = 2; private static final int CHECK_REASON_SCAN = 3; private static final int CHECK_REASON_SEEDING_CHECK = 4; private static final int CHECK_REASON_BAD_PIECE_CHECK = 5; private static final int SEED_CHECK_WAIT_MARKER = 65526; // config private static boolean disconnect_seeds_when_seeding; private static boolean enable_seeding_piece_rechecks; private static int stalled_piece_timeout; private static boolean fast_unchoke_new_peers; private static float ban_peer_discard_ratio; private static int ban_peer_discard_min_kb; private static boolean udp_fallback_for_failed_connection; private static boolean udp_fallback_for_dropped_connection; private static boolean udp_probe_enabled; private static boolean hide_a_piece; private static boolean prefer_udp_default; static{ COConfigurationManager.addAndFireParameterListeners( new String[]{ "Disconnect Seed", "Seeding Piece Check Recheck Enable", "peercontrol.stalled.piece.write.timeout", "Peer.Fast.Initial.Unchoke.Enabled", "Ip Filter Ban Discard Ratio", "Ip Filter Ban Discard Min KB", "peercontrol.udp.fallback.connect.fail", "peercontrol.udp.fallback.connect.drop", "peercontrol.udp.probe.enable", "peercontrol.hide.piece", "peercontrol.prefer.udp", }, new ParameterListener() { public void parameterChanged( String name ) { disconnect_seeds_when_seeding = COConfigurationManager.getBooleanParameter("Disconnect Seed"); enable_seeding_piece_rechecks = COConfigurationManager.getBooleanParameter("Seeding Piece Check Recheck Enable"); stalled_piece_timeout = COConfigurationManager.getIntParameter( "peercontrol.stalled.piece.write.timeout", 60*1000 ); fast_unchoke_new_peers = COConfigurationManager.getBooleanParameter( "Peer.Fast.Initial.Unchoke.Enabled" ); ban_peer_discard_ratio = COConfigurationManager.getFloatParameter( "Ip Filter Ban Discard Ratio" ); ban_peer_discard_min_kb = COConfigurationManager.getIntParameter( "Ip Filter Ban Discard Min KB" ); udp_fallback_for_failed_connection = COConfigurationManager.getBooleanParameter( "peercontrol.udp.fallback.connect.fail" ); udp_fallback_for_dropped_connection = COConfigurationManager.getBooleanParameter( "peercontrol.udp.fallback.connect.drop" ); udp_probe_enabled = COConfigurationManager.getBooleanParameter( "peercontrol.udp.probe.enable" ); hide_a_piece = COConfigurationManager.getBooleanParameter( "peercontrol.hide.piece" ); if ( hide_a_piece ){ disconnect_seeds_when_seeding = false; } prefer_udp_default = COConfigurationManager.getBooleanParameter( "peercontrol.prefer.udp" ); } }); } private static IpFilter ip_filter = IpFilterManagerFactory.getSingleton().getIPFilter(); private volatile boolean is_running = false; private volatile boolean is_destroyed = false; private volatile ArrayList peer_transports_cow = new ArrayList(); // Copy on write! private final AEMonitor peer_transports_mon = new AEMonitor( "PEPeerControl:PT"); protected final PEPeerManagerAdapter adapter; private final DiskManager disk_mgr; private final DiskManagerPiece[] dm_pieces; private final PiecePicker piecePicker; private long lastNeededUndonePieceChange; /** literally seeding as in 100% torrent complete */ private boolean seeding_mode; private boolean restart_initiated; private final int _nbPieces; //how many pieces in the torrent private PEPieceImpl[] pePieces; //pieces that are currently in progress private int nbPiecesActive; // how many pieces are currently in progress private int nbPeersSnubbed; private PeerIdentityDataID _hash; private final byte[] _myPeerId; private PEPeerManagerStats _stats; //private final TRTrackerAnnouncer _tracker; // private int _maxUploads; private int _seeds, _peers,_remotesNoUdpNoLan; private long last_remote_time; private long _timeStarted; private long _timeStartedSeeding = -1; private long _timeFinished; private Average _averageReceptionSpeed; private long mainloop_loop_count; private static final int MAINLOOP_ONE_SECOND_INTERVAL = 1000 / PeerControlScheduler.SCHEDULE_PERIOD_MILLIS; private static final int MAINLOOP_FIVE_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 5; private static final int MAINLOOP_TEN_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 10; private static final int MAINLOOP_THIRTY_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 30; private static final int MAINLOOP_SIXTY_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 60; private static final int MAINLOOP_TEN_MINUTE_INTERVAL = MAINLOOP_SIXTY_SECOND_INTERVAL * 10; private volatile ArrayList peer_manager_listeners_cow = new ArrayList(); //copy on write private final List piece_check_result_list = new ArrayList(); private final AEMonitor piece_check_result_list_mon = new AEMonitor( "PEPeerControl:PCRL"); private boolean superSeedMode; private int superSeedModeCurrentPiece; private int superSeedModeNumberOfAnnounces; private SuperSeedPiece[] superSeedPieces; private final int hidden_piece; private final AEMonitor this_mon = new AEMonitor( "PEPeerControl"); private long ip_filter_last_update_time; private Map user_data; private Unchoker unchoker; private List external_rate_limiters_cow; private List sweepList = Collections.emptyList(); private int nextPEXSweepIndex = 0; private final UploadHelper upload_helper = new UploadHelper() { public int getPriority() { return UploadHelper.PRIORITY_NORMAL; //TODO also must call UploadSlotManager.getSingleton().updateHelper( upload_helper ); on priority change } public ArrayList getAllPeers() { return( peer_transports_cow ); } public boolean isSeeding() { return seeding_mode; } }; private PeerDatabase peer_database = PeerDatabaseFactory.createPeerDatabase(); private int bad_piece_reported = -1; private int next_rescan_piece = -1; private long rescan_piece_time = -1; private long last_eta; private long last_eta_calculation; private static final int MAX_UDP_CONNECTIONS = 16; private static final int PENDING_NAT_TRAVERSAL_MAX = 32; private static final int MAX_UDP_TRAVERSAL_COUNT = 3; private static final String PEER_NAT_TRAVERSE_DONE_KEY = PEPeerControlImpl.class.getName() + "::nat_trav_done"; private Map pending_nat_traversals = new LinkedHashMap(PENDING_NAT_TRAVERSAL_MAX,0.75f,true) { protected boolean removeEldestEntry( Map.Entry eldest) { return size() > PENDING_NAT_TRAVERSAL_MAX; } }; private int udp_traversal_count; private static final int UDP_RECONNECT_MAX = 16; private Map udp_reconnects = new LinkedHashMap(UDP_RECONNECT_MAX,0.75f,true) { protected boolean removeEldestEntry( Map.Entry eldest) { return size() > UDP_RECONNECT_MAX; } }; private static final int UDP_RECONNECT_MIN_MILLIS = 10*1000; private long last_udp_reconnect; private boolean prefer_udp; private static final int PREFER_UDP_BLOOM_SIZE = 10000; private volatile BloomFilter prefer_udp_bloom; private final LimitedRateGroup upload_limited_rate_group = new LimitedRateGroup() { public String getName() { return( "per_dl_up: " + getDisplayName()); } public int getRateLimitBytesPerSecond() { return adapter.getUploadRateLimitBytesPerSecond(); } }; private final LimitedRateGroup download_limited_rate_group = new LimitedRateGroup() { public String getName() { return( "per_dl_down: " + getDisplayName()); } public int getRateLimitBytesPerSecond() { return adapter.getDownloadRateLimitBytesPerSecond(); } }; private final int partition_id; public PEPeerControlImpl( byte[] _peer_id, PEPeerManagerAdapter _adapter, DiskManager _diskManager, int _partition_id ) { _myPeerId = _peer_id; adapter = _adapter; disk_mgr = _diskManager; partition_id = _partition_id; _nbPieces =disk_mgr.getNbPieces(); dm_pieces =disk_mgr.getPieces(); pePieces = new PEPieceImpl[_nbPieces]; hidden_piece = hide_a_piece?((int)(Math.abs(adapter.getRandomSeed())%_nbPieces)):-1; if ( hidden_piece >= 0 ){ System.out.println( "Hidden piece for " + getDisplayName() + " = " + hidden_piece ); } piecePicker = PiecePickerFactory.create( this ); COConfigurationManager.addParameterListener("Ip Filter Enabled", this); ip_filter.addListener( this ); } public void start() { //This torrent Hash try { _hash = PeerIdentityManager.createDataID( disk_mgr.getTorrent().getHash()); } catch (TOTorrentException e) { // this should never happen Debug.printStackTrace( e ); _hash = PeerIdentityManager.createDataID( new byte[20] ); } // the recovered active pieces for (int i =0; i <_nbPieces; i++ ) { final DiskManagerPiece dmPiece =dm_pieces[i]; if (!dmPiece.isDone() &&dmPiece.getNbWritten() >0) { addPiece(new PEPieceImpl(this, dmPiece, 0), i, true ); } } //The peer connections peer_transports_cow = new ArrayList(); //BtManager is threaded, this variable represents the // current loop iteration. It's used by some components only called // at some specific times. mainloop_loop_count = 0; //The current tracker state //this could be start or update _averageReceptionSpeed = Average.getInstance(1000, 30); // the stats _stats =new PEPeerManagerStatsImpl(this); superSeedMode = (COConfigurationManager.getBooleanParameter("Use Super Seeding") && this.getRemaining() == 0); superSeedModeCurrentPiece = 0; if (superSeedMode) { initialiseSuperSeedMode(); } // initial check on finished state - future checks are driven by piece check results // Moved out of mainLoop() so that it runs immediately, possibly changing // the state to seeding. checkFinished( true ); UploadSlotManager.getSingleton().registerHelper( upload_helper ); lastNeededUndonePieceChange =Long.MIN_VALUE; _timeStarted = SystemTime.getCurrentTime(); is_running = true; // activate after marked as running as we may synchronously add connections here due to pending activations adapter.getPeerManagerRegistration().activate( this ); PeerNATTraverser.getSingleton().register( this ); PeerControlSchedulerFactory.getSingleton(partition_id).register(this); } public void stopAll() { is_running =false; UploadSlotManager.getSingleton().deregisterHelper( upload_helper ); PeerControlSchedulerFactory.getSingleton(partition_id).unregister(this); PeerNATTraverser.getSingleton().unregister( this ); // remove legacy controller activation adapter.getPeerManagerRegistration().deactivate(); closeAndRemoveAllPeers("download stopped", false); // clear pieces for (int i =0; i <_nbPieces; i++ ) { if (pePieces[i] !=null) removePiece(pePieces[i], i); } // 5. Remove listeners COConfigurationManager.removeParameterListener("Ip Filter Enabled", this); ip_filter.removeListener(this); piecePicker.destroy(); final ArrayList peer_manager_listeners = peer_manager_listeners_cow; for( int i=0; i < peer_manager_listeners.size(); i++ ) { ((PEPeerManagerListener)peer_manager_listeners.get(i)).destroyed(); } sweepList = Collections.emptyList(); pending_nat_traversals.clear(); udp_reconnects.clear(); is_destroyed = true; } public int getPartitionID() { return( partition_id ); } public boolean isDestroyed() { return( is_destroyed ); } public DiskManager getDiskManager() { return disk_mgr; } public PiecePicker getPiecePicker() { return piecePicker; } public PEPeerManagerAdapter getAdapter(){ return( adapter ); } public String getDisplayName(){ return( adapter.getDisplayName()); } public String getName() { return( getDisplayName()); } public void schedule() { try { updateTrackerAnnounceInterval(); doConnectionChecks(); processPieceChecks(); // note that seeding_mode -> torrent totally downloaded, not just non-dnd files // complete, so there is no change of a new piece appearing done by a means such as // background periodic file rescans if ( !seeding_mode ){ checkCompletedPieces(); //check to see if we've completed anything else } checkBadPieces(); updateStats(); checkInterested(); // see if need to recheck Interested on all peers piecePicker.updateAvailability(); checkCompletionState(); // pick up changes in completion caused by dnd file changes checkSeeds(); if(!seeding_mode) { // if we're not finished checkRequests(); piecePicker.allocateRequests(); checkRescan(); checkSpeedAndReserved(); check99PercentBug(); } updatePeersInSuperSeedMode(); doUnchokes(); }catch (Throwable e) { Debug.printStackTrace( e ); } mainloop_loop_count++; } /** * A private method that does analysis of the result sent by the tracker. * It will mainly open new connections with peers provided * and set the timeToWait variable according to the tracker response. * @param tracker_response */ private void analyseTrackerResponse( TRTrackerAnnouncerResponse tracker_response ) { // tracker_response.print(); final TRTrackerAnnouncerResponsePeer[] peers = tracker_response.getPeers(); if ( peers != null ){ addPeersFromTracker( tracker_response.getPeers()); } final Map extensions = tracker_response.getExtensions(); if (extensions != null ){ addExtendedPeersFromTracker( extensions ); } } public void processTrackerResponse( TRTrackerAnnouncerResponse response ) { // only process new peers if we're still running if ( is_running ){ analyseTrackerResponse( response ); } } private void addExtendedPeersFromTracker( Map extensions ) { final Map protocols = (Map)extensions.get("protocols"); if ( protocols != null ){ System.out.println( "PEPeerControl: tracker response contained protocol extensions"); final Iterator protocol_it = protocols.keySet().iterator(); while( protocol_it.hasNext()){ final String protocol_name = (String)protocol_it.next(); final Map protocol = (Map)protocols.get(protocol_name); final List transports = PEPeerTransportFactory.createExtendedTransports( this, protocol_name, protocol ); for (int i=0;i getPeers() { return( peer_transports_cow ); } public List getPeers( String address ) { List result = new ArrayList(); Iterator it = peer_transports_cow.iterator(); while( it.hasNext()){ PEPeerTransport peer = (PEPeerTransport)it.next(); if ( peer.getIp().equals( address )){ result.add( peer ); } } return( result ); } public PeerDescriptor[] getPendingPeers() { return((PeerDescriptor[])peer_database.getDiscoveredPeers()); } public PeerDescriptor[] getPendingPeers( String address ) { return((PeerDescriptor[])peer_database.getDiscoveredPeers( address )); } public void addPeer( PEPeer _transport ) { if ( !( _transport instanceof PEPeerTransport )){ throw( new RuntimeException("invalid class")); } final PEPeerTransport transport = (PEPeerTransport)_transport; if (!ip_filter.isInRange(transport.getIp(), getDisplayName(), getTorrentHash())) { final ArrayList peer_transports = peer_transports_cow; if ( !peer_transports.contains(transport)){ addToPeerTransports( transport ); transport.start(); }else{ Debug.out( "addPeer():: peer_transports.contains(transport): SHOULD NEVER HAPPEN !" ); transport.closeConnection( "already connected" ); } }else{ transport.closeConnection( "IP address blocked by filters" ); } } protected byte[] getTorrentHash() { try{ return( disk_mgr.getTorrent().getHash()); }catch( Throwable e ){ return( null ); } } public void removePeer( PEPeer _transport ) { removePeer( _transport, "remove peer" ); } public void removePeer( PEPeer _transport, String reason ) { if ( !( _transport instanceof PEPeerTransport )){ throw( new RuntimeException("invalid class")); } PEPeerTransport transport = (PEPeerTransport)_transport; closeAndRemovePeer( transport, reason, true ); } private void closeAndRemovePeer( PEPeerTransport peer, String reason, boolean log_if_not_found ) { boolean removed =false; // copy-on-write semantics try{ peer_transports_mon.enter(); if ( peer_transports_cow.contains( peer )){ final ArrayList new_peer_transports = new ArrayList( peer_transports_cow ); new_peer_transports.remove(peer); peer_transports_cow =new_peer_transports; removed =true; } } finally{ peer_transports_mon.exit(); } if( removed ) { peer.closeConnection( reason ); peerRemoved(peer); //notify listeners } else { if ( log_if_not_found ){ // we know this happens due to timing issues... Debug.out( "closeAndRemovePeer(): peer not removed" ); } } } private void closeAndRemoveAllPeers( String reason, boolean reconnect ) { ArrayList peer_transports; try{ peer_transports_mon.enter(); peer_transports = peer_transports_cow; peer_transports_cow = new ArrayList( 0 ); } finally{ peer_transports_mon.exit(); } for( int i=0; i < peer_transports.size(); i++ ) { final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i ); try{ peer.closeConnection( reason ); }catch( Throwable e ){ // if something goes wrong with the close process (there's a bug in there somewhere whereby // we occasionally get NPEs then we want to make sure we carry on and close the rest Debug.printStackTrace(e); } try{ peerRemoved( peer ); //notify listeners }catch( Throwable e ){ Debug.printStackTrace(e); } } if( reconnect ) { for( int i=0; i < peer_transports.size(); i++ ) { final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i ); PEPeerTransport reconnected_peer = peer.reconnect(false, false); } } } public void addPeer( String ip_address, int tcp_port, int udp_port, boolean use_crypto, Map user_data ) { final byte type = use_crypto ? PeerItemFactory.HANDSHAKE_TYPE_CRYPTO : PeerItemFactory.HANDSHAKE_TYPE_PLAIN; final PeerItem peer_item = PeerItemFactory.createPeerItem( ip_address, tcp_port, PeerItem.convertSourceID( PEPeerSource.PS_PLUGIN ), type, udp_port, PeerItemFactory.CRYPTO_LEVEL_1, 0 ); byte crypto_level = PeerItemFactory.CRYPTO_LEVEL_1; if( !isAlreadyConnected( peer_item ) ) { String fail_reason; boolean tcp_ok = TCPNetworkManager.TCP_OUTGOING_ENABLED && tcp_port > 0; boolean udp_ok = UDPNetworkManager.UDP_OUTGOING_ENABLED && udp_port > 0; if ( tcp_ok && !( ( prefer_udp || prefer_udp_default ) && udp_ok )){ fail_reason = makeNewOutgoingConnection( PEPeerSource.PS_PLUGIN, ip_address, tcp_port, udp_port, true, use_crypto, crypto_level, user_data ); //directly inject the the imported peer }else if ( udp_ok ){ fail_reason = makeNewOutgoingConnection( PEPeerSource.PS_PLUGIN, ip_address, tcp_port, udp_port, false, use_crypto, crypto_level, user_data ); //directly inject the the imported peer }else{ fail_reason = "No usable protocol"; } if( fail_reason != null ) Debug.out( "Injected peer " + ip_address + ":" + tcp_port + " was not added - " + fail_reason ); } } private void addPeersFromTracker( TRTrackerAnnouncerResponsePeer[] peers ) { for (int i = 0; i < peers.length; i++){ final TRTrackerAnnouncerResponsePeer peer = peers[i]; final ArrayList peer_transports = peer_transports_cow; boolean already_connected = false; for( int x=0; x < peer_transports.size(); x++ ) { final PEPeerTransport transport = (PEPeerTransport)peer_transports.get( x ); // allow loopback connects for co-located proxy-based connections and testing if( peer.getAddress().equals( transport.getIp() )){ final boolean same_allowed = COConfigurationManager.getBooleanParameter( "Allow Same IP Peers" ) || transport.getIp().equals( "127.0.0.1" ); if( !same_allowed || peer.getPort() == transport.getPort() ) { already_connected = true; break; } } } if( already_connected ) continue; if( peer_database != null ){ byte type = peer.getProtocol() == DownloadAnnounceResultPeer.PROTOCOL_CRYPT ? PeerItemFactory.HANDSHAKE_TYPE_CRYPTO : PeerItemFactory.HANDSHAKE_TYPE_PLAIN; byte crypto_level = peer.getAZVersion() < TRTrackerAnnouncer.AZ_TRACKER_VERSION_3?PeerItemFactory.CRYPTO_LEVEL_1:PeerItemFactory.CRYPTO_LEVEL_2; PeerItem item = PeerItemFactory.createPeerItem( peer.getAddress(), peer.getPort(), PeerItem.convertSourceID( peer.getSource() ), type, peer.getUDPPort(), crypto_level, peer.getUploadSpeed()); peerDiscovered( null, item ); peer_database.addDiscoveredPeer( item ); } int http_port = peer.getHTTPPort(); if ( http_port != 0 ){ adapter.addHTTPSeed( peer.getAddress(), http_port ); } } } /** * Request a new outgoing peer connection. * @param address ip of remote peer * @param port remote peer listen port * @return null if the connection was added to the transport list, reason if rejected */ private String makeNewOutgoingConnection( String peer_source, String address, int tcp_port, int udp_port, boolean use_tcp, boolean require_crypto, byte crypto_level, Map user_data ) { //make sure this connection isn't filtered if( ip_filter.isInRange( address, getDisplayName(), getTorrentHash())) { return "IPFilter block"; } //make sure we need a new connection final int needed = getMaxNewConnectionsAllowed(); boolean is_priority_connection = false; if ( user_data != null ){ Boolean pc = (Boolean)user_data.get( Peer.PR_PRIORITY_CONNECTION ); if ( pc != null && pc.booleanValue()){ is_priority_connection = true; } } if( needed == 0 ){ if ( peer_source != PEPeerSource.PS_PLUGIN || !doOptimisticDisconnect( AddressUtils.isLANLocalAddress( address ) != AddressUtils.LAN_LOCAL_NO, is_priority_connection )){ return "Too many connections"; } } //make sure not already connected to the same IP address; allow loopback connects for co-located proxy-based connections and testing final boolean same_allowed = COConfigurationManager.getBooleanParameter( "Allow Same IP Peers" ) || address.equals( "127.0.0.1" ); if( !same_allowed && PeerIdentityManager.containsIPAddress( _hash, address ) ){ return "Already connected to IP"; } if( PeerUtils.ignorePeerPort( tcp_port ) ) { if (Logger.isEnabled()) Logger.log(new LogEvent(disk_mgr.getTorrent(), LOGID, "Skipping connect with " + address + ":" + tcp_port + " as peer port is in ignore list.")); return "TCP port in ignore list"; } //start the connection PEPeerTransport real = PEPeerTransportFactory.createTransport( this, peer_source, address, tcp_port, udp_port, use_tcp, require_crypto, crypto_level, user_data ); addToPeerTransports( real ); return null; } /** * A private method that checks if PEPieces being downloaded are finished * If all blocks from a PEPiece are written to disk, this method will * queue the piece for hash check. * Elsewhere, if it passes sha-1 check, it will be marked as downloaded, * otherwise, it will unmark it as fully downloaded, so blocks can be retreived again. */ private void checkCompletedPieces() { if ((mainloop_loop_count %MAINLOOP_ONE_SECOND_INTERVAL) !=0) return; //for every piece for (int i = 0; i <_nbPieces; i++) { final DiskManagerPiece dmPiece =dm_pieces[i]; //if piece is completly written, not already checking, and not Done if (dmPiece.isNeedsCheck()) { //check the piece from the disk dmPiece.setChecking(); DiskManagerCheckRequest req = disk_mgr.createCheckRequest( i, new Integer(CHECK_REASON_DOWNLOADED)); req.setAdHoc( false ); disk_mgr.enqueueCheckRequest( req, this ); } } } /** Checks given piece to see if it's active but empty, and if so deactivates it. * @param pieceNumber to check * @return true if the piece was removed and is no longer active (pePiece ==null) */ private boolean checkEmptyPiece( final int pieceNumber ) { if ( piecePicker.isInEndGameMode()){ return false; // be sure to not remove pieces in EGM } final PEPiece pePiece =pePieces[pieceNumber]; final DiskManagerPiece dmPiece =dm_pieces[pieceNumber]; if ( pePiece == null || pePiece.isRequested()) return false; if (dmPiece.getNbWritten() >0 ||pePiece.getNbUnrequested() < pePiece.getNbBlocks() ||pePiece.getReservedBy() !=null) return false; // reset in case dmpiece is in some skanky state pePiece.reset(); removePiece(pePiece, pieceNumber); return true; } /** * Check if a piece's Speed is too fast for it to be getting new data * and if a reserved pieced failed to get data within 120 seconds */ private void checkSpeedAndReserved() { // only check every 5 seconds if(mainloop_loop_count % MAINLOOP_FIVE_SECOND_INTERVAL != 0) return; final int nbPieces =_nbPieces; final PEPieceImpl[] pieces =pePieces; //for every piece for (int i =0; i 0 && timeSinceActivity*pieceSpeed*0.25 > DiskManager.BLOCK_SIZE/1024) { if(pePiece.getNbUnrequested() > 2) pePiece.setSpeed(pieceSpeed-1); else pePiece.setSpeed(0); } if(timeSinceActivity > 120) { pePiece.setSpeed(0); // has reserved piece gone stagnant? final String reservingPeer =pePiece.getReservedBy(); if(reservingPeer !=null) { final PEPeerTransport pt = getTransportFromAddress(reservingPeer); // Peer is too slow; Ban them and unallocate the piece // but, banning is no good for peer types that get pieces reserved // to them for other reasons, such as special seed peers if (needsMD5CheckOnCompletion(i)) badPeerDetected(reservingPeer, i); else if (pt != null) closeAndRemovePeer(pt, "Reserved piece data timeout; 120 seconds", true); pePiece.setReservedBy(null); } if (!piecePicker.isInEndGameMode()){ pePiece.checkRequests(); } checkEmptyPiece(i); } } } } private void check99PercentBug() { // there's a bug whereby pieces are left downloaded but never written. might have been fixed by // changes to the "write result" logic, however as a stop gap I'm adding code to scan for such // stuck pieces and reset them if ( mainloop_loop_count % MAINLOOP_SIXTY_SECOND_INTERVAL == 0 ) { long now = SystemTime.getCurrentTime(); for ( int i=0;i stalled_piece_timeout ){ // people with *very* slow disk writes can trigger this (I've been talking to a user // with a SAN that has .5 second write latencies when checking a file at the same time // this means that when dowloading > 32K/sec things start backing up). Eventually the // write controller will start blocking the network thread to prevent unlimited // queueing but until that time we need to handle this situation slightly better) // if there are any outstanding requests for this piece then leave it alone if ( !( disk_mgr.hasOutstandingWriteRequestForPiece( i ) || disk_mgr.hasOutstandingReadRequestForPiece( i ) || disk_mgr.hasOutstandingCheckRequestForPiece( i ) )){ Debug.out( "Fully downloaded piece stalled pending write, resetting p_piece " + i ); pe_piece.reset(); } } } } } } } } private void checkInterested() { if ( (mainloop_loop_count %MAINLOOP_ONE_SECOND_INTERVAL) != 0 ){ return; } if (lastNeededUndonePieceChange >=piecePicker.getNeededUndonePieceChange()) return; lastNeededUndonePieceChange =piecePicker.getNeededUndonePieceChange(); final ArrayList peer_transports = peer_transports_cow; int cntPeersSnubbed =0; // recount # snubbed peers while we're at it for (int i =0; i 0 ){ final List pieces; // process complete piece results try{ piece_check_result_list_mon.enter(); pieces = new ArrayList( piece_check_result_list ); piece_check_result_list.clear(); }finally{ piece_check_result_list_mon.exit(); } final Iterator it = pieces.iterator(); while (it.hasNext()) { final Object[] data = (Object[])it.next(); processPieceCheckResult((DiskManagerCheckRequest)data[0],((Integer)data[1]).intValue()); } } } private void checkBadPieces() { if ( mainloop_loop_count % MAINLOOP_SIXTY_SECOND_INTERVAL == 0 ){ if ( bad_piece_reported != -1 ){ DiskManagerCheckRequest req = disk_mgr.createCheckRequest( bad_piece_reported, new Integer( CHECK_REASON_BAD_PIECE_CHECK )); req.setLowPriority( true ); if ( Logger.isEnabled()){ Logger.log( new LogEvent( disk_mgr.getTorrent(), LOGID, "Rescanning reported-bad piece " + bad_piece_reported )); } bad_piece_reported = -1; try{ disk_mgr.enqueueCheckRequest( req, this ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } } private void checkRescan() { if ( rescan_piece_time == 0 ){ // pending a piece completion return; } if ( next_rescan_piece == -1 ){ if ( mainloop_loop_count % MAINLOOP_FIVE_SECOND_INTERVAL == 0 ){ if ( adapter.isPeriodicRescanEnabled()){ next_rescan_piece = 0; } } }else{ if ( mainloop_loop_count % MAINLOOP_TEN_MINUTE_INTERVAL == 0 ){ if ( !adapter.isPeriodicRescanEnabled()){ next_rescan_piece = -1; } } } if ( next_rescan_piece == -1 ){ return; } // delay as required final long now = SystemTime.getCurrentTime(); if ( rescan_piece_time > now ){ rescan_piece_time = now; } // 250K/sec limit final long piece_size = disk_mgr.getPieceLength(); final long millis_per_piece = piece_size / 250; if ( now - rescan_piece_time < millis_per_piece ){ return; } while( next_rescan_piece != -1 ){ int this_piece = next_rescan_piece; next_rescan_piece++; if ( next_rescan_piece == _nbPieces ){ next_rescan_piece = -1; } // this functionality is to pick up pieces that have been downloaded OUTSIDE of // Azureus - e.g. when two torrents are sharing a single file. Hence the check on // the piece NOT being done if ( pePieces[this_piece] == null && !dm_pieces[this_piece].isDone() && dm_pieces[this_piece].isNeeded()){ DiskManagerCheckRequest req = disk_mgr.createCheckRequest( this_piece, new Integer( CHECK_REASON_SCAN )); req.setLowPriority( true ); if ( Logger.isEnabled()){ Logger.log( new LogEvent( disk_mgr.getTorrent(), LOGID, "Rescanning piece " + this_piece )); } rescan_piece_time = 0; // mark as check piece in process try{ disk_mgr.enqueueCheckRequest( req, this ); }catch( Throwable e ){ rescan_piece_time = now; Debug.printStackTrace(e); } break; } } } public void badPieceReported( PEPeerTransport originator, int piece_number ) { Debug.outNoStack( getDisplayName() + ": bad piece #" + piece_number + " reported by " + originator.getIp()); if ( piece_number < 0 || piece_number >= _nbPieces ){ return; } bad_piece_reported = piece_number; } /** * This method checks if the downloading process is finished. * */ private void checkFinished( boolean start_of_day ) { final boolean all_pieces_done =disk_mgr.getRemainingExcludingDND() ==0; if (all_pieces_done) { seeding_mode = true; prefer_udp_bloom = null; piecePicker.clearEndGameChunks(); if (!start_of_day) adapter.setStateFinishing(); _timeFinished = SystemTime.getCurrentTime(); final ArrayList peer_transports = peer_transports_cow; //remove previous snubbing for (int i =0; i =0 ; i--) { final PEPeerTransport pc =(PEPeerTransport)peer_transports.get(i); if (pc.getPeerState() ==PEPeer.TRANSFERING) { final List expired = pc.getExpiredRequests(); if (expired !=null &&expired.size() >0) { // now we know there's a request that's > 60 seconds old final boolean isSeed =pc.isSeed(); // snub peers that haven't sent any good data for a minute final long timeSinceGoodData =pc.getTimeSinceGoodDataReceived(); if (timeSinceGoodData <0 ||timeSinceGoodData >60 *1000) pc.setSnubbed(true); //Only cancel first request if more than 2 mins have passed DiskManagerReadRequest request =(DiskManagerReadRequest) expired.get(0); final long timeSinceData =pc.getTimeSinceLastDataMessageReceived(); final boolean noData =(timeSinceData <0) ||timeSinceData >(1000 *(isSeed ?120 :60)); final long timeSinceOldestRequest = now - request.getTimeCreated(now); //for every expired request for (int j = (timeSinceOldestRequest >120 *1000 && noData) ? 0 : 1; j < expired.size(); j++) { //get the request object request =(DiskManagerReadRequest) expired.get(j); //Only cancel first request if more than 2 mins have passed pc.sendCancel(request); //cancel the request object //get the piece number final int pieceNumber = request.getPieceNumber(); PEPiece pe_piece = pePieces[pieceNumber]; //unmark the request on the block if ( pe_piece != null ) pe_piece.clearRequested(request.getOffset() /DiskManager.BLOCK_SIZE); // remove piece if empty so peers can choose something else, except in end game if (!piecePicker.isInEndGameMode()) checkEmptyPiece(pieceNumber); } } } } } private void updateTrackerAnnounceInterval() { if ( mainloop_loop_count % MAINLOOP_FIVE_SECOND_INTERVAL != 0 ){ return; } final int WANT_LIMIT = 100; int num_wanted = getMaxNewConnectionsAllowed(); final boolean has_remote = adapter.isNATHealthy(); if( has_remote ) { //is not firewalled, so can accept incoming connections, //which means no need to continually keep asking the tracker for peers num_wanted = (int)(num_wanted / 1.5); } if ( num_wanted < 0 || num_wanted > WANT_LIMIT ) { num_wanted = WANT_LIMIT; } int current_connection_count = PeerIdentityManager.getIdentityCount( _hash ); final TRTrackerScraperResponse tsr = adapter.getTrackerScrapeResponse(); if( tsr != null && tsr.isValid() ) { //we've got valid scrape info final int num_seeds = tsr.getSeeds(); final int num_peers = tsr.getPeers(); final int swarm_size; if( seeding_mode ) { //Only use peer count when seeding, as other seeds are unconnectable. //Since trackers return peers randomly (some of which will be seeds), //backoff by the seed2peer ratio since we're given only that many peers //on average each announce. final float ratio = (float)num_peers / (num_seeds + num_peers); swarm_size = (int)(num_peers * ratio); } else { swarm_size = num_peers + num_seeds; } if( swarm_size < num_wanted ) { //lower limit to swarm size if necessary num_wanted = swarm_size; } } if( num_wanted < 1 ) { //we dont need any more connections adapter.setTrackerRefreshDelayOverrides( 100 ); //use normal announce interval return; } if( current_connection_count == 0 ) current_connection_count = 1; //fudge it :) final int current_percent = (current_connection_count * 100) / (current_connection_count + num_wanted); adapter.setTrackerRefreshDelayOverrides( current_percent ); //set dynamic interval override } public boolean hasDownloadablePiece() { return( piecePicker.hasDownloadablePiece()); } public int[] getAvailability() { return piecePicker.getAvailability(); } //this only gets called when the My Torrents view is displayed public float getMinAvailability() { return piecePicker.getMinAvailability(); } public float getAvgAvail() { return piecePicker.getAvgAvail(); } public long getAvailWentBadTime() { return( piecePicker.getAvailWentBadTime()); } public void addPeerTransport( PEPeerTransport transport ) { if (!ip_filter.isInRange(transport.getIp(), getDisplayName(), getTorrentHash())) { final ArrayList peer_transports = peer_transports_cow; if (!peer_transports.contains( transport )) { addToPeerTransports(transport); } else{ Debug.out( "addPeerTransport():: peer_transports.contains(transport): SHOULD NEVER HAPPEN !" ); transport.closeConnection( "already connected" ); } } else { transport.closeConnection( "IP address blocked by filters" ); } } /** * Do all peer choke/unchoke processing. */ private void doUnchokes() { // logic below is either 1 second or 10 secondly, bail out early id neither if( !UploadSlotManager.AUTO_SLOT_ENABLE ) { //manual per-torrent unchoke slot mode if( mainloop_loop_count % MAINLOOP_ONE_SECOND_INTERVAL != 0 ) { return; } final int max_to_unchoke = adapter.getMaxUploads(); //how many simultaneous uploads we should consider final ArrayList peer_transports = peer_transports_cow; //determine proper unchoker if( seeding_mode ) { if( unchoker == null || !(unchoker.isSeedingUnchoker()) ) { unchoker = UnchokerFactory.getSingleton().getUnchoker( true ); } } else { if( unchoker == null || unchoker.isSeedingUnchoker()) { unchoker = UnchokerFactory.getSingleton().getUnchoker( false ); } } //do main choke/unchoke update every 10 secs if ( mainloop_loop_count % MAINLOOP_TEN_SECOND_INTERVAL == 0 ){ final boolean refresh = mainloop_loop_count % MAINLOOP_THIRTY_SECOND_INTERVAL == 0; unchoker.calculateUnchokes( max_to_unchoke, peer_transports, refresh, adapter.hasPriorityConnection()); ArrayList chokes = unchoker.getChokes(); ArrayList unchokes = unchoker.getUnchokes(); addFastUnchokes( unchokes ); UnchokerUtil.performChokes( chokes, unchokes ); }else if ( mainloop_loop_count % MAINLOOP_ONE_SECOND_INTERVAL == 0 ) { //do quick unchoke check every 1 sec ArrayList unchokes = unchoker.getImmediateUnchokes( max_to_unchoke, peer_transports ); addFastUnchokes( unchokes ); UnchokerUtil.performChokes( null, unchokes ); } } } private void addFastUnchokes( ArrayList peers_to_unchoke ) { for( Iterator it=peer_transports_cow.iterator();it.hasNext();) { PEPeerTransport peer = (PEPeerTransport)it.next(); if ( peer.getConnectionState() != PEPeerTransport.CONNECTION_FULLY_ESTABLISHED || !UnchokerUtil.isUnchokable( peer, true ) || peers_to_unchoke.contains( peer )){ continue; } if( peer.isLANLocal()){ peers_to_unchoke.add( peer ); }else if ( fast_unchoke_new_peers && peer.getData( "fast_unchoke_done" ) == null ){ peer.setData( "fast_unchoke_done", "" ); peers_to_unchoke.add( peer ); } } } // send the have requests out private void sendHave(int pieceNumber) { //fo final ArrayList peer_transports = peer_transports_cow; for (int i = 0; i < peer_transports.size(); i++) { //get a peer connection final PEPeerTransport pc = (PEPeerTransport) peer_transports.get(i); //send the have message pc.sendHave(pieceNumber); } } // Method that checks if we are connected to another seed, and if so, disconnect from him. private void checkSeeds() { //proceed on mainloop 1 second intervals if we're a seed and we want to force disconnects if ((mainloop_loop_count % MAINLOOP_ONE_SECOND_INTERVAL) != 0) return; if (!disconnect_seeds_when_seeding ){ return; } ArrayList to_close = null; final ArrayList peer_transports = peer_transports_cow; for (int i = 0; i < peer_transports.size(); i++) { final PEPeerTransport pc = (PEPeerTransport) peer_transports.get(i); if (pc != null && pc.getPeerState() == PEPeer.TRANSFERING && ((isSeeding() && pc.isSeed()) || pc.isRelativeSeed())) { if( to_close == null ) to_close = new ArrayList(); to_close.add( pc ); } } if( to_close != null ) { for( int i=0; i < to_close.size(); i++ ) { closeAndRemovePeer( (PEPeerTransport)to_close.get(i), "disconnect other seed when seeding", false ); } } } private void updateStats() { if ( (mainloop_loop_count %MAINLOOP_ONE_SECOND_INTERVAL) != 0 ){ return; } //calculate seeds vs peers final ArrayList peer_transports = peer_transports_cow; int new_seeds = 0; int new_peers = 0; int newTcpRemotes = 0; for (Iterator it=peer_transports.iterator();it.hasNext();){ final PEPeerTransport pc = (PEPeerTransport) it.next(); if (pc.getPeerState() == PEPeer.TRANSFERING) { if (pc.isSeed()) new_seeds++; else new_peers++; if(pc.isIncoming() && pc.isTCP() && !pc.isLANLocal()) { newTcpRemotes++; } } } _seeds = new_seeds; _peers = new_peers; _remotesNoUdpNoLan = newTcpRemotes; } /** * The way to unmark a request as being downloaded, or also * called by Peer connections objects when connection is closed or choked * @param request a DiskManagerReadRequest holding details of what was canceled */ public void requestCanceled(DiskManagerReadRequest request) { final int pieceNumber =request.getPieceNumber(); //get the piece number PEPiece pe_piece = pePieces[pieceNumber]; if (pe_piece != null ) pe_piece.clearRequested(request.getOffset() /DiskManager.BLOCK_SIZE); } public PEPeerControl getControl() { return( this ); } public byte[][] getSecrets( int crypto_level ) { return( adapter.getSecrets( crypto_level )); } // get the hash value public byte[] getHash() { return _hash.getDataID(); } public PeerIdentityDataID getPeerIdentityDataID() { return( _hash ); } // get the peer id value public byte[] getPeerId() { return _myPeerId; } // get the remaining percentage public long getRemaining() { return disk_mgr.getRemaining(); } public void discarded(PEPeer peer, int length) { if (length > 0){ _stats.discarded(peer, length); // discards are more likely during end-game-mode if ( ban_peer_discard_ratio > 0 && !( piecePicker.isInEndGameMode() || piecePicker.hasEndGameModeBeenAbandoned())){ long received = peer.getStats().getTotalDataBytesReceived(); long discarded = peer.getStats().getTotalBytesDiscarded(); long non_discarded = received - discarded; if ( non_discarded < 0 ){ non_discarded = 0; } if ( discarded >= ban_peer_discard_min_kb * 1024 ){ if ( non_discarded == 0 || ((float)discarded) / non_discarded >= ban_peer_discard_ratio ){ badPeerDetected( peer.getIp(), -1 ); } } } } } public void dataBytesReceived(PEPeer peer, int length) { if (length > 0) { _stats.dataBytesReceived(peer,length); _averageReceptionSpeed.addValue(length); } } public void protocolBytesReceived(PEPeer peer, int length ) { if (length > 0) { _stats.protocolBytesReceived(peer,length); } } public void dataBytesSent(PEPeer peer, int length) { if (length > 0) { _stats.dataBytesSent(peer, length ); } } public void protocolBytesSent( PEPeer peer, int length ) { if (length > 0) { _stats.protocolBytesSent(peer,length); } } /** DiskManagerWriteRequestListener message * @see org.gudy.azureus2.core3.disk.DiskManagerWriteRequestListener */ public void writeCompleted(DiskManagerWriteRequest request) { final int pieceNumber =request.getPieceNumber(); DiskManagerPiece dm_piece = dm_pieces[pieceNumber]; if (!dm_piece.isDone()){ final PEPiece pePiece =pePieces[pieceNumber]; if (pePiece !=null){ pePiece.setWritten((PEPeer)request.getUserData(), request.getOffset() /DiskManager.BLOCK_SIZE ); }else{ // this is a way of fixing a 99.9% bug where a dmpiece is left in a // fully downloaded state with the underlying pe_piece null. Possible explanation is // that a slow peer sends an entire piece at around the time a pe_piece gets reset // due to inactivity. // we also get here when recovering data that has come in late after the piece has // been abandoned dm_piece.setWritten( request.getOffset() /DiskManager.BLOCK_SIZE ); } } } public void writeFailed( DiskManagerWriteRequest request, Throwable cause ) { // if the write has failed then the download will have been stopped so there is no need to try // and reset the piece } /** * * @param data_offset MUST be block aligned within the TORRENT * @param data * @return buffers not yet written * @throws Exception */ public DirectByteBuffer[] write( long data_offset, DirectByteBuffer[] data ) throws Exception { if ( data_offset % DiskManager.BLOCK_SIZE != 0 ){ throw( new Exception( "data must start at a block offset" )); } int piece_length = disk_mgr.getPieceLength(); int data_length = 0; for( DirectByteBuffer buffer: data ){ data_length += buffer.remaining( DirectByteBuffer.SS_DW ); } long written = 0; int buffer_number = 0; for ( int i=0;i DiskManager.BLOCK_SIZE ){ rem = DiskManager.BLOCK_SIZE; } int piece_number = (int)( data_offset / piece_length ); DiskManagerPiece dm_piece = dm_pieces[piece_number]; int block_number = (int)(data_offset - ( piece_number * piece_length )) / DiskManager.BLOCK_SIZE; int block_size = dm_piece.getBlockSize( block_number ); if ( rem < block_size ){ break; } DirectByteBuffer chunk = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_BT_PIECE, block_size ); writeBlock( piece_number, block_number*DiskManager.BLOCK_SIZE, chunk, null, true ); written += rem; data_offset += rem; } List unwritten = new ArrayList(); for (int i=buffer_number;i= 0; i--) { final PEPeerTransport pc = (PEPeerTransport) peer_transports.get(i); if (pc !=pcOrigin &&pc.getPeerState() ==PEPeer.TRANSFERING &&pc.isPieceAvailable(pieceNumber)) ((PEPeerStatsImpl)pc.getStats()).statisticalSentPiece(pieceLength / availability); } } } public int getPieceLength(int pieceNumber) { return disk_mgr.getPieceLength(pieceNumber); } public int getNbPeers() { return _peers; } public int getNbSeeds() { return _seeds; } public int getNbRemoteConnectionsExcludingUDP() { return _remotesNoUdpNoLan; } public long getLastRemoteConnectionTime() { return( last_remote_time ); } public PEPeerManagerStats getStats() { return _stats; } public int getNbPeersStalledPendingLoad() { int res = 0; Iterator it = peer_transports_cow.iterator(); while( it.hasNext()){ PEPeerTransport transport = (PEPeerTransport)it.next(); if ( transport.isStalledPendingLoad()){ res ++; } } return( res ); } /** * Returns the ETA time in seconds. * If the returned time is 0, the download is complete. * If the returned time is negative, the download * is complete and it took -xxx time to complete. */ public long getETA() { final long now = SystemTime.getCurrentTime(); if ( now < last_eta_calculation || now - last_eta_calculation > 900 ){ long dataRemaining = disk_mgr.getRemainingExcludingDND(); if ( dataRemaining > 0 ){ int writtenNotChecked = 0; for (int i = 0; i < _nbPieces; i++) { if (dm_pieces[i].isInteresting()){ writtenNotChecked +=dm_pieces[i].getNbWritten() *DiskManager.BLOCK_SIZE; } } dataRemaining = dataRemaining - writtenNotChecked; if (dataRemaining < 0 ){ dataRemaining = 0; } } long result; if (dataRemaining == 0) { final long timeElapsed = (_timeFinished - _timeStarted)/1000; //if time was spent downloading....return the time as negative if(timeElapsed > 1){ result = timeElapsed * -1; }else{ result = 0; } }else{ final long averageSpeed = _averageReceptionSpeed.getAverage(); long lETA = (averageSpeed == 0) ? Constants.CRAPPY_INFINITE_AS_LONG : dataRemaining / averageSpeed; // stop the flickering of ETA from "Finished" to "x seconds" when we are // just about complete, but the data rate is jumpy. if (lETA == 0) lETA = 1; result = lETA; } last_eta = result; last_eta_calculation = now; } return( last_eta ); } public boolean isRTA() { return( piecePicker.getRTAProviders().size() > 0 ); } private void addToPeerTransports( PEPeerTransport peer ) { boolean added = false; List limiters; try{ peer_transports_mon.enter(); // if it is already disconnected (synchronous failure during connect // for example) don't add it if ( peer.getPeerState() == PEPeer.DISCONNECTED ){ return; } if( peer_transports_cow.contains( peer ) ){ Debug.out( "Transport added twice" ); return; //we do not want to close it } if( is_running ) { //copy-on-write semantics final ArrayList new_peer_transports = new ArrayList(peer_transports_cow.size() +1); new_peer_transports.addAll( peer_transports_cow ); new_peer_transports.add( peer ); peer_transports_cow = new_peer_transports; added = true; } limiters = external_rate_limiters_cow; } finally{ peer_transports_mon.exit(); } if( added ) { if ( peer.isIncoming()){ long connect_time = SystemTime.getCurrentTime(); if ( connect_time > last_remote_time ){ last_remote_time = connect_time; } } if ( limiters != null ){ for (int i=0;i transports; try{ peer_transports_mon.enter(); ArrayList new_limiters = new ArrayList( external_rate_limiters_cow==null?1:external_rate_limiters_cow.size()+1); if ( external_rate_limiters_cow != null ){ new_limiters.addAll( external_rate_limiters_cow ); } new_limiters.add( new Object[]{ group, new Boolean( upload )}); external_rate_limiters_cow = new_limiters; transports = peer_transports_cow; }finally{ peer_transports_mon.exit(); } for (int i=0;i 0; boolean canTryIpv6 = NetworkAdmin.getSingleton().hasIPV6Potential(true) && peer.getAlternativeIPv6() != null; if ( is_running ){ PeerItem peer_item = peer.getPeerItemIdentity(); PeerItem self_item = peer_database.getSelfPeer(); if ( self_item == null || !self_item.equals( peer_item )){ String ip = peer.getIp(); boolean wasIPv6; try { wasIPv6 = InetAddress.getByName(ip) instanceof Inet6Address; } catch (UnknownHostException e) { wasIPv6 = false; // something is fishy about the old address, don't try to reconnect with v6 canTryIpv6 = false; } //System.out.println("netfail="+network_failed+", connfail="+connect_failed+", can6="+canTryIpv6+", was6="+wasIPv6); String key = ip + ":" + udpPort; if ( peer.isTCP()){ if ( connect_failed ){ // TCP connect failure, try UDP later if necessary if ( canTryUDP && udp_fallback_for_failed_connection ){ pending_nat_traversals.put(key, peer); } else if (canTryIpv6 && !wasIPv6) { tcpReconnect = true; ipv6reconnect = true; } }else if ( canTryUDP && udp_fallback_for_dropped_connection && network_failed && seeding_mode && peer.isInterested() && !peer.isSeed() && !peer.isRelativeSeed() && peer.getStats().getEstimatedSecondsToCompletion() > 60 && FeatureAvailability.isUDPPeerReconnectEnabled()){ if (Logger.isEnabled()){ Logger.log(new LogEvent(peer, LOGID, LogEvent.LT_WARNING, "Unexpected stream closure detected, attempting recovery")); } // System.out.println( "Premature close of stream: " + getDisplayName() + "/" + peer.getIp()); udp_reconnects.put( key, peer ); }else if ( network_failed && peer.isSafeForReconnect() && !(seeding_mode && (peer.isSeed() || peer.isRelativeSeed() || peer.getStats().getEstimatedSecondsToCompletion() < 60)) && getMaxConnections() > 0 && getMaxNewConnectionsAllowed() > getMaxConnections() / 3 && FeatureAvailability.isGeneralPeerReconnectEnabled()){ tcpReconnect = true; } }else if ( connect_failed ){ // UDP connect failure if ( udp_fallback_for_failed_connection ){ if ( peer.getData(PEER_NAT_TRAVERSE_DONE_KEY) == null){ // System.out.println( "Direct reconnect failed, attempting NAT traversal" ); pending_nat_traversals.put(key, peer); } } } } } if( peer_transports_cow.contains( peer )) { final ArrayList new_peer_transports = new ArrayList( peer_transports_cow ); new_peer_transports.remove(peer); peer_transports_cow = new_peer_transports; connection_found = true; } } finally{ peer_transports_mon.exit(); } if ( connection_found ){ if( peer.getPeerState() != PEPeer.DISCONNECTED ) { System.out.println( "peer.getPeerState() != PEPeer.DISCONNECTED: " +peer.getPeerState() ); } peerRemoved( peer ); //notify listeners } if(tcpReconnect) peer.reconnect(false, ipv6reconnect); } public void peerAdded( PEPeer pc) { adapter.addPeer(pc); //async downloadmanager notification //sync peermanager notification final ArrayList peer_manager_listeners = peer_manager_listeners_cow; for( int i=0; i < peer_manager_listeners.size(); i++ ) { ((PEPeerManagerListener)peer_manager_listeners.get(i)).peerAdded( this, pc ); } } public void peerRemoved( PEPeer pc) { if ( is_running && !seeding_mode && ( prefer_udp || prefer_udp_default )){ int udp = pc.getUDPListenPort(); if ( udp != 0 && udp == pc.getTCPListenPort()){ BloomFilter filter = prefer_udp_bloom; if ( filter == null ){ filter = prefer_udp_bloom = BloomFilterFactory.createAddOnly( PREFER_UDP_BLOOM_SIZE ); } if ( filter.getEntryCount() < PREFER_UDP_BLOOM_SIZE / 10 ){ filter.add( pc.getIp().getBytes()); } } } final int piece = pc.getUniqueAnnounce(); if(piece != -1 && superSeedMode ) { superSeedModeNumberOfAnnounces--; superSeedPieces[piece].peerLeft(); } int reserved_piece = pc.getReservedPieceNumber(); if ( reserved_piece >= 0 ){ PEPiece pe_piece = pePieces[reserved_piece]; if ( pe_piece != null ){ String reserved_by = pe_piece.getReservedBy(); if ( reserved_by != null && reserved_by.equals( pc.getIp())){ pe_piece.setReservedBy( null ); } } } adapter.removePeer(pc); //async downloadmanager notification //sync peermanager notification final ArrayList peer_manager_listeners = peer_manager_listeners_cow; for( int i=0; i < peer_manager_listeners.size(); i++ ) { ((PEPeerManagerListener)peer_manager_listeners.get(i)).peerRemoved( this, pc ); } } /** Don't pass a null to this method. All activations of pieces must go through here. * @param piece PEPiece invoked; notifications of it's invocation need to be done * @param pieceNumber of the PEPiece */ public void addPiece(final PEPiece piece, final int pieceNumber) { addPiece( piece, pieceNumber, false ); } protected void addPiece(final PEPiece piece, final int pieceNumber, final boolean force_add ) { pePieces[pieceNumber] =(PEPieceImpl)piece; nbPiecesActive++; if ( is_running || force_add ){ // deal with possible piece addition by scheduler loop after closdown started adapter.addPiece(piece); } } /** Sends messages to listeners that the piece is no longer active. All closing * out (deactivation) of pieces must go through here. The piece will be null upon return. * @param pePiece PEPiece to remove * @param pieceNumber int */ public void removePiece(PEPiece pePiece, int pieceNumber) { if ( pePiece != null ){ adapter.removePiece(pePiece); } pePieces[pieceNumber] =null; nbPiecesActive--; } public int getNbActivePieces() { return nbPiecesActive; } public String getElapsedTime() { return TimeFormatter.format((SystemTime.getCurrentTime() - _timeStarted) / 1000); } // Returns time started in ms public long getTimeStarted() { return _timeStarted; } public long getTimeStartedSeeding() { return _timeStartedSeeding; } private byte[] computeMd5Hash(DirectByteBuffer buffer) { BrokenMd5Hasher md5 = new BrokenMd5Hasher(); md5.reset(); final int position = buffer.position(DirectByteBuffer.SS_DW); md5.update(buffer.getBuffer(DirectByteBuffer.SS_DW)); buffer.position(DirectByteBuffer.SS_DW, position); ByteBuffer md5Result = ByteBuffer.allocate(16); md5Result.position(0); md5.finalDigest( md5Result ); final byte[] result =new byte[16]; md5Result.position(0); for (int i =0; i 0; } private void processPieceCheckResult(DiskManagerCheckRequest request, int outcome) { final int check_type =((Integer) request.getUserData()).intValue(); try{ final int pieceNumber =request.getPieceNumber(); // System.out.println( "processPieceCheckResult(" + _finished + "/" + recheck_on_completion + "):" + pieceNumber + // "/" + piece + " - " + result ); // passed = 1, failed = 0, cancelled = 2 if (check_type ==CHECK_REASON_COMPLETE){ // this is a recheck, so don't send HAVE msgs if ( outcome == 0 ){ // piece failed; restart the download afresh Debug.out(getDisplayName() + ": Piece #" +pieceNumber +" failed final re-check. Re-downloading..."); if (!restart_initiated){ restart_initiated = true; adapter.restartDownload(true); } } return; }else if ( check_type == CHECK_REASON_SEEDING_CHECK || check_type == CHECK_REASON_BAD_PIECE_CHECK ){ if ( outcome == 0 ){ if ( check_type == CHECK_REASON_SEEDING_CHECK ){ Debug.out(getDisplayName() + "Piece #" +pieceNumber +" failed recheck while seeding. Re-downloading..."); }else{ Debug.out(getDisplayName() + "Piece #" +pieceNumber +" failed recheck after being reported as bad. Re-downloading..."); } Logger.log(new LogAlert(this, LogAlert.REPEATABLE, LogAlert.AT_ERROR, "Download '" + getDisplayName() + "': piece " + pieceNumber + " has been corrupted, re-downloading")); if ( !restart_initiated ){ restart_initiated = true; adapter.restartDownload(true); } } return; } // piece can be null when running a recheck on completion // actually, give the above code I don't think this is true anymore... final PEPieceImpl pePiece =pePieces[pieceNumber]; if ( outcome == 1 ){ // the piece has been written correctly try{ if (pePiece !=null){ if (needsMD5CheckOnCompletion(pieceNumber)){ MD5CheckPiece(pePiece, true); } final List list =pePiece.getPieceWrites(); if (list.size() >0 ){ //For each Block for (int i =0; i 1 ){ int maxWrites = 0; String bestWriter =null; PEPeerTransport bestWriter_transport = null; for (int i =0; i maxWrites ){ final String writer =(String) uniqueWriters.get(i); PEPeerTransport pt =getTransportFromAddress(writer); if ( pt !=null && pt.getReservedPieceNumber() ==-1 && !ip_filter.isInRange(writer, getDisplayName(),getTorrentHash())){ bestWriter = writer; maxWrites = writes; bestWriter_transport = pt; } } } if ( bestWriter !=null ){ pePiece.setReservedBy(bestWriter); bestWriter_transport.setReservedPieceNumber(pePiece.getPieceNumber()); pePiece.setRequestable(); for (int i =0; i = 0; // note that peer can be NULL but things still work in the main PEPeerTransport peer = getTransportFromAddress(ip); if ( hash_fail && peer != null ){ Iterator it = peer_manager_listeners_cow.iterator(); while( it.hasNext()){ try{ it.next().peerSentBadData( this, peer, piece_number ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } // Debug.out("Bad Peer Detected: " + peerIP + " [" + peer.getClient() + "]"); IpFilterManager filter_manager =IpFilterManagerFactory.getSingleton(); //Ban fist to avoid a fast reco of the bad peer int nbWarnings = filter_manager.getBadIps().addWarningForIp(ip); boolean disconnect_peer = false; // no need to reset the bad chunk count as the peer is going to be disconnected and // if it comes back it'll start afresh // warning limit only applies to hash-fails, discards cause immediate action if ( nbWarnings > WARNINGS_LIMIT ){ if (COConfigurationManager.getBooleanParameter("Ip Filter Enable Banning")){ // if a block-ban occurred, check other connections if (ip_filter.ban(ip, getDisplayName(), false )){ checkForBannedConnections(); } // Trace the ban if (Logger.isEnabled()){ Logger.log(new LogEvent(peer, LOGID, LogEvent.LT_ERROR, ip +" : has been banned and won't be able " +"to connect until you restart azureus")); } disconnect_peer = true; } }else if ( !hash_fail ){ // for failures due to excessive discard we boot the peer anyway disconnect_peer = true; } if ( disconnect_peer ){ if ( peer != null ){ final int ps =peer.getPeerState(); // might have been through here very recently and already started closing // the peer (due to multiple bad blocks being found from same peer when checking piece) if (!(ps ==PEPeer.CLOSING ||ps ==PEPeer.DISCONNECTED)) { // Close connection closeAndRemovePeer(peer, "has sent too many " + (hash_fail?"bad pieces":"discarded blocks") + ", " +WARNINGS_LIMIT +" max.", true); } } } } public PEPiece[] getPieces() { return pePieces; } public PEPiece getPiece(int pieceNumber) { return pePieces[pieceNumber]; } public PEPeerStats createPeerStats( PEPeer owner ) { return( new PEPeerStatsImpl( owner )); } public DiskManagerReadRequest createDiskManagerRequest( int pieceNumber, int offset, int length ) { return( disk_mgr.createReadRequest( pieceNumber, offset, length )); } public boolean requestExists( String peer_ip, int piece_number, int offset, int length ) { ArrayList peer_transports = peer_transports_cow; DiskManagerReadRequest request = null; for (int i=0; i < peer_transports.size(); i++) { PEPeerTransport conn = (PEPeerTransport)peer_transports.get( i ); if ( conn.getIp().equals( peer_ip )){ if ( request == null ){ request = createDiskManagerRequest( piece_number, offset, length ); } if ( conn.getRequestIndex( request ) != -1 ){ return( true ); } } } return( false ); } public boolean seedPieceRecheck() { if ( !( enable_seeding_piece_rechecks || isSeeding())){ return( false ); } int max_reads = 0; int max_reads_index = 0; for (int i=0;i SEED_CHECK_WAIT_MARKER ){ // recently been checked, skip for a while num--; if ( num == SEED_CHECK_WAIT_MARKER ){ num = 0; } dm_piece.setReadCount((short)num); }else{ if ( num > max_reads ){ max_reads = num; max_reads_index = i; } } } if ( max_reads > 0 ){ DiskManagerPiece dm_piece = dm_pieces[ max_reads_index ]; // if the piece has been read 3 times (well, assuming each block is read once, // which is obviously wrong, but...) if ( max_reads >= dm_piece.getNbBlocks() * 3 ){ DiskManagerCheckRequest req = disk_mgr.createCheckRequest( max_reads_index, new Integer( CHECK_REASON_SEEDING_CHECK ) ); req.setAdHoc( true ); req.setLowPriority( true ); if (Logger.isEnabled()) Logger.log(new LogEvent(disk_mgr.getTorrent(), LOGID, "Rechecking piece " + max_reads_index + " while seeding as most active")); disk_mgr.enqueueCheckRequest( req, this ); dm_piece.setReadCount((short)65535); // clear out existing, non delayed pieces so we start counting piece activity // again for (int i=0;i= 2 * nbUnchoke) return; //Find an available Peer PEPeer selectedPeer = null; List sortedPeers = null; final ArrayList peer_transports = peer_transports_cow; sortedPeers = new ArrayList(peer_transports.size()); Iterator iter = peer_transports.iterator(); while(iter.hasNext()) { sortedPeers.add(new SuperSeedPeer((PEPeer)iter.next())); } Collections.sort(sortedPeers); iter = sortedPeers.iterator(); while(iter.hasNext()) { final PEPeer peer = ((SuperSeedPeer)iter.next()).peer; if((peer.getUniqueAnnounce() == -1) && (peer.getPeerState() == PEPeer.TRANSFERING)) { selectedPeer = peer; break; } } if(selectedPeer == null ||selectedPeer.getPeerState() >=PEPeer.CLOSING) return; if(selectedPeer.getUploadHint() == 0) { //Set to infinite selectedPeer.setUploadHint(Constants.CRAPPY_INFINITY_AS_INT); } //Find a piece boolean found = false; SuperSeedPiece piece = null; while(!found) { piece = superSeedPieces[superSeedModeCurrentPiece]; if(piece.getLevel() > 0) { piece = null; superSeedModeCurrentPiece++; if(superSeedModeCurrentPiece >= _nbPieces) { superSeedModeCurrentPiece = 0; //quit superseed mode superSeedMode = false; closeAndRemoveAllPeers( "quiting SuperSeed mode", true ); return; } } else { found = true; } } if(piece == null) { return; } //If this peer already has this piece, return (shouldn't happen) if(selectedPeer.isPieceAvailable(piece.getPieceNumber())) { return; } selectedPeer.setUniqueAnnounce(piece.getPieceNumber()); superSeedModeNumberOfAnnounces++; piece.pieceRevealedToPeer(); ((PEPeerTransport)selectedPeer).sendHave(piece.getPieceNumber()); } public void updateSuperSeedPiece(PEPeer peer,int pieceNumber) { if (!superSeedMode) return; superSeedPieces[pieceNumber].peerHasPiece(null); if(peer.getUniqueAnnounce() == pieceNumber) { peer.setUniqueAnnounce(-1); superSeedModeNumberOfAnnounces--; } } public boolean isExtendedMessagingEnabled() { return( adapter.isExtendedMessagingEnabled()); } public boolean isPeerExchangeEnabled() { return( adapter.isPeerExchangeEnabled()); } public LimitedRateGroup getUploadLimitedRateGroup() { return upload_limited_rate_group; } public LimitedRateGroup getDownloadLimitedRateGroup() { return download_limited_rate_group; } /** To retreive arbitrary objects against this object. */ public Object getData( String key) { try{ this_mon.enter(); if (user_data == null) return null; return user_data.get(key); }finally{ this_mon.exit(); } } /** To store arbitrary objects against a control. */ public void setData( String key, Object value) { try{ this_mon.enter(); if (user_data == null) { user_data = new HashMap(); } if (value == null) { if (user_data.containsKey(key)) user_data.remove(key); } else { user_data.put(key, value); } }finally{ this_mon.exit(); } } private void doConnectionChecks() { //every 1 second if ( mainloop_loop_count % MAINLOOP_ONE_SECOND_INTERVAL == 0 ){ final ArrayList peer_transports = peer_transports_cow; int num_waiting_establishments = 0; int udp_connections = 0; for( int i=0; i < peer_transports.size(); i++ ) { final PEPeerTransport transport = (PEPeerTransport)peer_transports.get( i ); //update waiting count final int state = transport.getConnectionState(); if( state == PEPeerTransport.CONNECTION_PENDING || state == PEPeerTransport.CONNECTION_CONNECTING ) { num_waiting_establishments++; } if ( !transport.isTCP()){ udp_connections++; } } int allowed_seeds = getMaxSeedConnections(); if ( allowed_seeds > 0 ){ int to_disconnect = _seeds - allowed_seeds; if ( to_disconnect > 0 ){ // seeds are limited by people trying to get a reasonable upload by connecting // to leechers where possible. disconnect seeds from end of list to prevent // cycling of seeds for( int i=peer_transports.size()-1; i >= 0 && to_disconnect > 0; i-- ){ final PEPeerTransport transport = (PEPeerTransport)peer_transports.get( i ); if ( transport.isSeed()){ closeAndRemovePeer( transport, "Too many seeds", false ); to_disconnect--; } } } } //pass from storage to connector int allowed = getMaxNewConnectionsAllowed(); if( allowed < 0 || allowed > 1000 ) allowed = 1000; //ensure a very upper limit so it doesnt get out of control when using PEX if( adapter.isNATHealthy()) { //if unfirewalled, leave slots avail for remote connections final int free = getMaxConnections() / 20; //leave 5% allowed = allowed - free; } if( allowed > 0 ) { //try and connect only as many as necessary final int wanted = TCPConnectionManager.MAX_SIMULTANIOUS_CONNECT_ATTEMPTS - num_waiting_establishments; if( wanted > allowed ) { num_waiting_establishments += wanted - allowed; } int remaining = allowed; int tcp_remaining = TCPNetworkManager.getSingleton().getConnectDisconnectManager().getMaxOutboundPermitted(); int udp_remaining = UDPNetworkManager.getSingleton().getConnectionManager().getMaxOutboundPermitted(); //load stored peer-infos to be established while( num_waiting_establishments < TCPConnectionManager.MAX_SIMULTANIOUS_CONNECT_ATTEMPTS && ( tcp_remaining > 0 || udp_remaining > 0 )){ if( !is_running ) break; final PeerItem item = peer_database.getNextOptimisticConnectPeer(); if( item == null || !is_running ) break; final PeerItem self = peer_database.getSelfPeer(); if( self != null && self.equals( item ) ) { continue; } if( !isAlreadyConnected( item ) ) { final String source = PeerItem.convertSourceString( item.getSource() ); final boolean use_crypto = item.getHandshakeType() == PeerItemFactory.HANDSHAKE_TYPE_CRYPTO; int tcp_port = item.getTCPPort(); int udp_port = item.getUDPPort(); if ( udp_port == 0 && udp_probe_enabled ){ // for probing we assume udp port same as tcp udp_port = tcp_port; } boolean prefer_udp_overall = prefer_udp || prefer_udp_default; if ( prefer_udp_overall && udp_port == 0 ){ // see if we have previous record of this address as udp connectable byte[] address = item.getIP().getBytes(); BloomFilter bloom = prefer_udp_bloom; if ( bloom != null && bloom.contains( address )){ udp_port = tcp_port; } } boolean tcp_ok = TCPNetworkManager.TCP_OUTGOING_ENABLED && tcp_port > 0 && tcp_remaining > 0; boolean udp_ok = UDPNetworkManager.UDP_OUTGOING_ENABLED && udp_port > 0 && udp_remaining > 0; if ( tcp_ok && !( prefer_udp_overall && udp_ok )){ if ( makeNewOutgoingConnection( source, item.getAddressString(), tcp_port, udp_port, true, use_crypto, item.getCryptoLevel(), null) == null) { tcp_remaining--; num_waiting_establishments++; remaining--; } }else if ( udp_ok ){ if ( makeNewOutgoingConnection( source, item.getAddressString(), tcp_port, udp_port, false, use_crypto, item.getCryptoLevel(), null) == null) { udp_remaining--; num_waiting_establishments++; remaining--; } } } } if ( UDPNetworkManager.UDP_OUTGOING_ENABLED && remaining > 0 && udp_remaining > 0 && udp_connections < MAX_UDP_CONNECTIONS ){ doUDPConnectionChecks( remaining ); } } } //every 5 seconds if ( mainloop_loop_count % MAINLOOP_FIVE_SECOND_INTERVAL == 0 ) { final ArrayList peer_transports = peer_transports_cow; for( int i=0; i < peer_transports.size(); i++ ) { final PEPeerTransport transport = (PEPeerTransport)peer_transports.get( i ); //check for timeouts if( transport.doTimeoutChecks() ) continue; //keep-alive check transport.doKeepAliveCheck(); //speed tuning check transport.doPerformanceTuningCheck(); } } // every 10 seconds check for connected + banned peers if ( mainloop_loop_count % MAINLOOP_TEN_SECOND_INTERVAL == 0 ) { final long last_update = ip_filter.getLastUpdateTime(); if ( last_update != ip_filter_last_update_time ) { ip_filter_last_update_time = last_update; checkForBannedConnections(); } } //every 30 seconds if ( mainloop_loop_count % MAINLOOP_THIRTY_SECOND_INTERVAL == 0 ) { //if we're at our connection limit, time out the least-useful //one so we can establish a possibly-better new connection optimisticDisconnectCount = 0; if( getMaxNewConnectionsAllowed() == 0 ) { //we've reached limit doOptimisticDisconnect( false, false ); } } //sweep over all peers in a 60 second timespan float percentage = ((mainloop_loop_count % MAINLOOP_SIXTY_SECOND_INTERVAL) + 1F) / (1F *MAINLOOP_SIXTY_SECOND_INTERVAL); int goal; if(mainloop_loop_count % MAINLOOP_SIXTY_SECOND_INTERVAL == 0) { goal = 0; sweepList = peer_transports_cow; } else goal = (int)Math.floor(percentage * sweepList.size()); for( int i=nextPEXSweepIndex; i < goal && i < sweepList.size(); i++) { //System.out.println(mainloop_loop_count+" %:"+percentage+" start:"+nextPEXSweepIndex+" current:"+i+" <"+goal+"/"+sweepList.size()); final PEPeerTransport peer = (PEPeerTransport)sweepList.get( i ); peer.updatePeerExchange(); } nextPEXSweepIndex = goal; } private void doUDPConnectionChecks( int number ) { List new_connections = null; try{ peer_transports_mon.enter(); long now = SystemTime.getCurrentTime(); if ( udp_reconnects.size() > 0 && now - last_udp_reconnect >= UDP_RECONNECT_MIN_MILLIS ){ last_udp_reconnect = now; Iterator it = udp_reconnects.values().iterator(); PEPeerTransport peer = (PEPeerTransport)it.next(); it.remove(); if (Logger.isEnabled()){ Logger.log(new LogEvent(this, LOGID, LogEvent.LT_INFORMATION, "Reconnecting to previous failed peer " + peer.getPeerItemIdentity().getAddressString())); } if ( new_connections == null ){ new_connections = new ArrayList(); } new_connections.add( peer ); number--; if ( number <= 0 ){ return; } } if ( pending_nat_traversals.size() == 0 ){ return; } int max = MAX_UDP_TRAVERSAL_COUNT; // bigger the swarm, less chance of doing it if ( seeding_mode ){ if ( _peers > 8 ){ max = 0; }else{ max = 1; } }else if ( _seeds > 8 ){ max = 0; }else if ( _seeds > 4 ){ max = 1; } int avail = max - udp_traversal_count; int to_do = Math.min( number, avail ); Iterator it = pending_nat_traversals.values().iterator(); while( to_do > 0 && it.hasNext()){ to_do--; final PEPeerTransport peer = (PEPeerTransport)it.next(); it.remove(); PeerNATTraverser.getSingleton().create( this, new InetSocketAddress( peer.getPeerItemIdentity().getAddressString(), peer.getPeerItemIdentity().getUDPPort() ), new PeerNATTraversalAdapter() { private boolean done; public void success( InetSocketAddress target ) { complete(); PEPeerTransport newTransport = peer.reconnect(true, false); if( newTransport != null ){ newTransport.setData(PEER_NAT_TRAVERSE_DONE_KEY, ""); } } public void failed() { complete(); } protected void complete() { try{ peer_transports_mon.enter(); if ( !done ){ done = true; udp_traversal_count--; } }finally{ peer_transports_mon.exit(); } } }); udp_traversal_count++; } }finally{ peer_transports_mon.exit(); if ( new_connections != null ){ for (int i=0;i activeConnectionTimes = new ArrayList(peer_transports.size()); int lan_peer_count = 0; for( int i=0; i < peer_transports.size(); i++ ) { final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i ); if( peer.getConnectionState() == PEPeerTransport.CONNECTION_FULLY_ESTABLISHED ) { final long timeSinceConnection =peer.getTimeSinceConnectionEstablished(); final long timeSinceSentData =peer.getTimeSinceLastDataMessageSent(); activeConnectionTimes.add(timeSinceConnection); long peerTestTime = 0; if( seeding_mode){ if( timeSinceSentData != -1 ) peerTestTime = timeSinceSentData; //ensure we've sent them at least one data message to qualify for drop }else{ final long timeSinceGoodData =peer.getTimeSinceGoodDataReceived(); if( timeSinceGoodData == -1 ) peerTestTime +=timeSinceConnection; //never received else peerTestTime +=timeSinceGoodData; // try to drop unInteresting in favor of Interesting connections if (!peer.isInteresting()) { if (!peer.isInterested()) // if mutually unInterested, really try to drop the connection peerTestTime +=timeSinceConnection +timeSinceSentData; // if we never sent, it will subtract 1, which is good else peerTestTime +=(timeSinceConnection -timeSinceSentData); // try to give interested peers a chance to get data peerTestTime *=2; } peerTestTime +=peer.getSnubbedTime(); } if( !peer.isIncoming() ){ peerTestTime = peerTestTime * 2; //prefer to drop a local connection, to make room for more remotes } if ( peer.isLANLocal()){ lan_peer_count++; }else{ if( peerTestTime > max_non_lan_time ) { max_non_lan_time = peerTestTime; max_non_lan_transport = peer; } } // anti-leech checks if( !seeding_mode ) { // remove long-term snubbed peers with higher probability peerTestTime += peer.getSnubbedTime(); if(peer.getSnubbedTime() > 2*60) {peerTestTime*=1.5;} PEPeerStats pestats = peer.getStats(); // everybody has deserverd a chance of half an MB transferred data if(pestats.getTotalDataBytesReceived()+pestats.getTotalDataBytesSent() > 1024*512 ) { boolean goodPeer = true; // we don't like snubbed peers with a negative gain if( peer.isSnubbed() && pestats.getTotalDataBytesReceived() < pestats.getTotalDataBytesSent() ) { peerTestTime *= 1.5; goodPeer = false; } // we don't like peers with a very bad ratio (10:1) if( pestats.getTotalDataBytesSent() > pestats.getTotalDataBytesReceived() * 10 ) { peerTestTime *= 2; goodPeer = false; } // modify based on discarded : overall downloaded ratio if( pestats.getTotalDataBytesReceived() > 0 && pestats.getTotalBytesDiscarded() > 0 ) { peerTestTime = (long)(peerTestTime *( 1.0+((double)pestats.getTotalBytesDiscarded()/(double)pestats.getTotalDataBytesReceived()))); } // prefer peers that do some work, let the churn happen with peers that did nothing if(goodPeer) peerTestTime *= 0.7; } } if( peerTestTime > max_time ) { max_time = peerTestTime; max_transport = peer; } if ( peer.isSeed() || peer.isRelativeSeed()){ if( peerTestTime > max_seed_time ) { max_seed_time = peerTestTime; max_seed_transport = peer; } } } } long medianConnectionTime; if ( activeConnectionTimes.size() > 0 ){ Collections.sort(activeConnectionTimes); medianConnectionTime = activeConnectionTimes.get(activeConnectionTimes.size()/2); }else{ medianConnectionTime = 0; } // allow 1 disconnect every 30s per 30 peers; 2 at least every 30s int maxOptimistics = Math.max(getMaxConnections()/30,2); // avoid unnecessary churn, e.g. if(!pending_lan_local_peer && !force && optimisticDisconnectCount >= maxOptimistics && medianConnectionTime < 5*60*1000) return false; // don't boot lan peers if we can help it (unless we have a few of them) if ( max_transport != null ){ final int LAN_PEER_MAX = 4; if ( max_transport.isLANLocal() && lan_peer_count < LAN_PEER_MAX && max_non_lan_transport != null ){ // override lan local max with non-lan local max max_transport = max_non_lan_transport; max_time = max_non_lan_time; } // if we have a seed limit, kick seeds in preference to non-seeds if( getMaxSeedConnections() > 0 && max_seed_transport != null && max_time > 5*60*1000 ) { closeAndRemovePeer( max_seed_transport, "timed out by doOptimisticDisconnect()", true ); optimisticDisconnectCount++; return true; } if( max_transport != null && max_time > 5 *60*1000 ) { //ensure a 5 min minimum test time closeAndRemovePeer( max_transport, "timed out by doOptimisticDisconnect()", true ); optimisticDisconnectCount++; return true; } // kick worst peers to accomodate lan peer if ( pending_lan_local_peer && lan_peer_count < LAN_PEER_MAX ){ closeAndRemovePeer( max_transport, "making space for LAN peer in doOptimisticDisconnect()", true ); optimisticDisconnectCount++; return true; } if ( force ){ closeAndRemovePeer( max_transport, "force removal of worst peer in doOptimisticDisconnect()", true ); return true; } }else if ( force ){ if ( peer_transports.size() > 0 ){ PEPeerTransport pt = (PEPeerTransport)peer_transports.get( new Random().nextInt( peer_transports.size())); closeAndRemovePeer( pt, "force removal of random peer in doOptimisticDisconnect()", true ); return true; } } return false; } public PeerExchangerItem createPeerExchangeConnection( final PEPeerTransport base_peer ) { if( base_peer.getTCPListenPort() > 0 ) { //only accept peers whose remote port is known final PeerItem peer = PeerItemFactory.createPeerItem( base_peer.getIp(), base_peer.getTCPListenPort(), PeerItemFactory.PEER_SOURCE_PEER_EXCHANGE, base_peer.getPeerItemIdentity().getHandshakeType(), base_peer.getUDPListenPort(), PeerItemFactory.CRYPTO_LEVEL_1, 0 ); return peer_database.registerPeerConnection( peer, new PeerExchangerItem.Helper(){ public boolean isSeed() { return base_peer.isSeed(); } }); } return null; } private boolean isAlreadyConnected( PeerItem peer_id ) { final ArrayList peer_transports = peer_transports_cow; for( int i=0; i < peer_transports.size(); i++ ) { final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i ); if( peer.getPeerItemIdentity().equals( peer_id ) ) return true; } return false; } public void peerVerifiedAsSelf( PEPeerTransport self ) { if( self.getTCPListenPort() > 0 ) { //only accept self if remote port is known final PeerItem peer = PeerItemFactory.createPeerItem( self.getIp(), self.getTCPListenPort(), PeerItem.convertSourceID( self.getPeerSource() ), self.getPeerItemIdentity().getHandshakeType(), self.getUDPListenPort(),PeerItemFactory.CRYPTO_LEVEL_CURRENT, 0 ); peer_database.setSelfPeer( peer ); } } public boolean canIPBeBanned( String ip ) { return true; } public boolean canIPBeBlocked( String ip, byte[] torrent_hash ) { return true; } public long getHiddenBytes() { if ( hidden_piece < 0 ){ return( 0 ); } return( dm_pieces[hidden_piece].getLength()); } public int getHiddenPiece() { return( hidden_piece ); } public void IPBlockedListChanged(IpFilter filter) { Iterator it = peer_transports_cow.iterator(); String name = getDisplayName(); byte[] hash = getTorrentHash(); while( it.hasNext()){ try { PEPeerTransport peer = (PEPeerTransport)it.next(); if (filter.isInRange(peer.getIp(), name, hash )) { peer.closeConnection( "IP address blocked by filters" ); } } catch (Exception e) { } } } public void IPBanned(BannedIp ip) { for (int i =0; i <_nbPieces; i++ ) { if (pePieces[i] !=null) pePieces[i].reDownloadBlocks(ip.getIp()); } } public int getAverageCompletionInThousandNotation() { final ArrayList peer_transports = peer_transports_cow; if (peer_transports !=null) { final long total =disk_mgr.getTotalLength(); final int my_completion = total == 0 ? 1000 : (int) ((1000 * (total - disk_mgr.getRemainingExcludingDND())) / total); int sum = my_completion == 1000 ? 0 : my_completion; //add in our own percentage if not seeding int num = my_completion == 1000 ? 0 : 1; for (int i =0; i 0 ? sum / num : 0; } return -1; } public int getMaxConnections() { return( adapter.getMaxConnections()); } public int getMaxSeedConnections() { return( adapter.getMaxSeedConnections()); } public int getMaxNewConnectionsAllowed() { final int dl_max = getMaxConnections(); final int allowed_peers = PeerUtils.numNewConnectionsAllowed(getPeerIdentityDataID(), dl_max ); return( allowed_peers ); } public int getSchedulePriority() { return isSeeding() ? Integer.MAX_VALUE : adapter.getPosition(); } public boolean hasPotentialConnections() { return( pending_nat_traversals.size() + peer_database.getDiscoveredPeerCount() > 0 ); } public String getRelationText() { return( adapter.getLogRelation().getRelationText()); } public Object[] getQueryableInterfaces() { return( adapter.getLogRelation().getQueryableInterfaces()); } public PEPeerTransport getTransportFromIdentity( byte[] peer_id ) { final ArrayList peer_transports = peer_transports_cow; for( int i=0; i < peer_transports.size(); i++ ) { final PEPeerTransport conn = (PEPeerTransport)peer_transports.get( i ); if( Arrays.equals( peer_id, conn.getId() ) ) return conn; } return null; } /* peer item is not reliable for general use public PEPeerTransport getTransportFromPeerItem(PeerItem peerItem) { ArrayList peer_transports =peer_transports_cow; for (int i =0; i 0 ){ writer.println( " pending_udp=" + pending_udp ); } List traversals = PeerNATTraverser.getSingleton().getTraversals( this ); String active_udp = ""; Iterator it = traversals.iterator(); while( it.hasNext()){ InetSocketAddress ad = (InetSocketAddress)it.next(); active_udp += (active_udp.length()==0?"":",") + ad.getAddress().getHostAddress() + ":" + ad.getPort(); } if ( active_udp.length() > 0 ){ writer.println( " active_udp=" + active_udp ); } if ( !seeding_mode ){ writer.println( " Active Pieces" ); int num_active = 0; try{ writer.indent(); String str = ""; int num = 0; for (int i=0;i 0 ){ writer.println(str); } }finally{ writer.exdent(); } if ( num_active == 0 ){ writer.println( " Inactive Pieces (excluding done/skipped)" ); try{ writer.indent(); String str = ""; int num = 0; for (int i=0;i 0 ){ writer.println(str); } }finally{ writer.exdent(); } } piecePicker.generateEvidence( writer ); } try{ peer_transports_mon.enter(); writer.println( "Peers: total = " + peer_transports_cow.size()); writer.indent(); try{ writer.indent(); it = peer_transports_cow.iterator(); while( it.hasNext()){ PEPeerTransport peer = (PEPeerTransport)it.next(); peer.generateEvidence( writer ); } }finally{ writer.exdent(); } }finally{ peer_transports_mon.exit(); writer.exdent(); } disk_mgr.generateEvidence( writer ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/PEPieceImpl.java0000644000175000017500000004421510616565002024032 0ustar adrianadrian/* * File : PEPieceImpl.java * Created : 15-Oct-2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.peer.impl; /** * @author parg * @author MjrTom * 2005/Oct/08: numerous changes for new piece-picking * 2006/Jan/02: refactoring piece picking to elsewhere, and consolidations */ import java.util.*; import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.peer.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker; public class PEPieceImpl implements PEPiece { private static final LogIDs LOGID = LogIDs.PIECES; private final DiskManagerPiece dmPiece; private final PEPeerManager manager; private final int nbBlocks; // number of blocks in this piece private long creationTime; private final String[] requested; private boolean fully_requested; private final boolean[] downloaded; private boolean fully_downloaded; private long time_last_download; private final String[] writers; private List writes; private String reservedBy; // using address for when they send bad/disconnect/reconnect //In end game mode, this limitation isn't used private int speed; //slower peers dont slow down fast pieces too much private int resumePriority; private Object real_time_data; // experimental class level lock protected static final AEMonitor class_mon = new AEMonitor( "PEPiece:class"); /** piece for tracking partially downloaded pieces * @param _manager the PEPeerManager * @param _dm_piece the backing dmPiece * @param _pieceSpeed the speed threshold for potential new requesters */ public PEPieceImpl( PEPeerManager _manager, DiskManagerPiece _dm_piece, int _pieceSpeed) { creationTime =SystemTime.getCurrentTime(); manager =_manager; dmPiece =_dm_piece; speed =_pieceSpeed; nbBlocks =dmPiece.getNbBlocks(); requested =new String[nbBlocks]; final boolean[] written =dmPiece.getWritten(); if (written ==null) downloaded =new boolean[nbBlocks]; else downloaded =(boolean[])written.clone(); writers =new String[nbBlocks]; writes =new ArrayList(0); } public DiskManagerPiece getDMPiece() { return dmPiece; } public long getCreationTime() { final long now =SystemTime.getCurrentTime(); if (now >=creationTime &&creationTime >0) return creationTime; creationTime =now; return now; } public long getTimeSinceLastActivity() { final long now =SystemTime.getCurrentTime(); final long lastWriteTime =getLastDownloadTime(now); if (time_last_download >0 &&now >=time_last_download) return now -time_last_download; if (creationTime >0 &&now >=creationTime) return now -creationTime; creationTime =now; return 0; } public long getLastDownloadTime(final long now) { if (time_last_download <=now) return time_last_download; return time_last_download =now; } /** Tells if a block has been requested * @param blockNumber the block in question * @return true if the block is Requested already */ public boolean isRequested(int blockNumber) { return requested[blockNumber] !=null; } /** Tells if a block has been downloaded * @param blockNumber the block in question * @return true if the block is downloaded already */ public boolean isDownloaded(int blockNumber) { return downloaded[blockNumber]; } /** This flags the block at the given offset as having been downloaded * If all blocks are now downloaed, sets the dmPiece as downloaded * @param blockNumber */ public void setDownloaded(int offset) { time_last_download =SystemTime.getCurrentTime(); downloaded[offset /DiskManager.BLOCK_SIZE] =true; for (int i =0; i 0) { dmPiece.clearRequested(); if (Logger.isEnabled()) Logger.log(new LogEvent(dmPiece.getManager().getTorrent(), LOGID, LogEvent.LT_WARNING, "checkRequests(): piece #" +getPieceNumber()+" cleared " +cleared +" requests." + (nullPeer ?" Null peer was detected." :""))); } return cleared; } */ /* * Parg: replaced above commented out checking with one that verifies that the * requests still exist. As piece-picker activity and peer disconnect logic is multi-threaded * and full of holes, this is a stop-gap measure to prevent a piece from being left with * requests that no longer exist */ public void checkRequests() { if ( getTimeSinceLastActivity() < 30*1000 ){ return; } int cleared = 0; for (int i=0; i 0 ){ if (Logger.isEnabled()) Logger.log(new LogEvent(dmPiece.getManager().getTorrent(), LOGID, LogEvent.LT_WARNING, "checkRequests(): piece #" +getPieceNumber()+" cleared " +cleared +" requests" )); }else{ if ( fully_requested && getNbUnrequested() > 0 ){ if (Logger.isEnabled()) Logger.log(new LogEvent(dmPiece.getManager().getTorrent(), LOGID, LogEvent.LT_WARNING, "checkRequests(): piece #" +getPieceNumber()+" reset fully requested" )); fully_requested = false; } } } /** @return true if the piece has any blocks that are not; * Downloaded, Requested, or Written */ public boolean hasUnrequestedBlock() { final boolean[] written =dmPiece.getWritten(); for (int i =0; i 0){ return new int[] {i, blocksFound}; } } } } // scan piece to find first free block for (int i =0; i 0) return new int[] {i, blocksFound}; } return new int[] {-1, 0}; } public void getAndMarkBlock(PEPeer peer, int index ) { requested[index] = peer.getIp(); if ( getNbUnrequested() <= 0 ){ setRequested(); } } public int getNbRequests() { int result =0; for (int i =0; i speed ){ speed++; } } /** * @return Returns the manager. */ public PEPeerManager getManager() { return manager; } public void setReservedBy(String peer) { reservedBy =peer; } public String getReservedBy() { return reservedBy; } /** for a block that's already downloadedt, mark up the piece * so that the block will get downloaded again. This is used * when the piece fails hash-checking. */ public void reDownloadBlock(int blockNumber) { downloaded[blockNumber] =false; requested[blockNumber] =null; fully_downloaded = false; writers[blockNumber] = null; dmPiece.reDownloadBlock(blockNumber); } /** finds all blocks downloaded by the given address * and marks them up for re-downloading * @param address String */ public void reDownloadBlocks(String address) { for (int i =0; i 0 ){ last_data_received_seconds = (int)(SystemTime.getCurrentTime()/1000); } adapter.dataBytesReceived( peer, length ); } public void protocolBytesReceived(PEPeer peer, int length) { total_protocol_bytes_received += length; if ( peer.isLANLocal()){ total_protocol_bytes_received_lan += length; } protocol_receive_speed.addValue(length); adapter.protocolBytesReceived( peer, length ); } public void dataBytesSent(PEPeer peer, int length ) { total_data_bytes_sent += length; if ( peer.isLANLocal()){ total_data_bytes_sent_lan += length; } data_send_speed.addValue(length); if ( length > 0 ){ last_data_sent_seconds = (int)(SystemTime.getCurrentTime()/1000); } adapter.dataBytesSent( peer, length ); } public void protocolBytesSent(PEPeer peer, int length) { total_protocol_bytes_sent += length; if ( peer.isLANLocal()){ total_protocol_bytes_sent_lan += length; } protocol_send_speed.addValue(length); adapter.protocolBytesSent( peer, length ); } public void haveNewPiece(int pieceLength) { overallSpeed.addValue(pieceLength); } public long getDataReceiveRate() { return( data_receive_speed.getAverage()); } public long getProtocolReceiveRate() { return protocol_receive_speed.getAverage(); } public long getDataSendRate() { return( data_send_speed.getAverage()); } public long getProtocolSendRate() { return protocol_send_speed.getAverage(); } public long getTotalDiscarded() { return( totalDiscarded ); } public void setTotalDiscarded(long total) { this.totalDiscarded = total; } public long getTotalDataBytesSent() { return total_data_bytes_sent; } public long getTotalProtocolBytesSent() { return total_protocol_bytes_sent; } public long getTotalDataBytesReceived() { return total_data_bytes_received; } public long getTotalProtocolBytesReceived() { return total_protocol_bytes_received; } public long getTotalDataBytesSentNoLan() { return( Math.max( total_data_bytes_sent - total_data_bytes_sent_lan, 0 )); } public long getTotalProtocolBytesSentNoLan() { return( Math.max( total_protocol_bytes_sent - total_protocol_bytes_sent_lan, 0 )); } public long getTotalDataBytesReceivedNoLan() { return( Math.max( total_data_bytes_received - total_data_bytes_received_lan, 0 )); } public long getTotalProtocolBytesReceivedNoLan() { return( Math.max( total_protocol_bytes_received - total_protocol_bytes_received_lan, 0 )); } public long getTotalAverage() { return( overallSpeed.getAverage() + getDataReceiveRate() ); } public int getTimeSinceLastDataReceivedInSeconds() { if ( last_data_received_seconds == 0 ){ return( -1 ); } int now = (int)(SystemTime.getCurrentTime()/1000); if ( now < last_data_received_seconds ){ last_data_received_seconds = now; } return( now - last_data_received_seconds ); } public int getTimeSinceLastDataSentInSeconds() { if ( last_data_sent_seconds == 0 ){ return( -1 ); } int now = (int)(SystemTime.getCurrentTime()/1000); if ( now < last_data_sent_seconds ){ last_data_sent_seconds = now; } return( now - last_data_sent_seconds ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/impl/PEPieceWriteImpl.java0000644000175000017500000000267410366523256025057 0ustar adrianadrian/* * File : PEPieceWriteImpl.java * Created : 27-Dec-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.peer.impl; /** * @author parg * */ public class PEPieceWriteImpl { protected int blockNumber; protected String sender; protected byte[] hash; protected boolean correct; public PEPieceWriteImpl(int blockNumber,String sender, byte[] hash,boolean correct) { this.blockNumber = blockNumber; this.sender = sender; this.hash = hash; this.correct = correct; } public String getSender() { return( sender ); } public int getBlockNumber() { return( blockNumber ); } public byte[] getHash() { return( hash ); } public boolean isCorrect() { return( correct ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/PEPeerManagerListener.java0000644000175000017500000000313011135270206025101 0ustar adrianadrian/* * File : PEPeerManagerListener.java * Created : 22-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.peer; import com.aelitis.azureus.core.peermanager.peerdb.PeerItem; /** * @author parg * */ public interface PEPeerManagerListener { /** * The given peer has been added to the given manager. * @param manager to which peer belongs * @param peer added */ public void peerAdded( PEPeerManager manager, PEPeer peer ); /** * The given peer has been removed from the given manager. * @param manager to which peer belongs * @param peer removed */ public void peerRemoved( PEPeerManager manager, PEPeer peer ); public void peerDiscovered( PEPeerManager manager, PeerItem peer, PEPeer finder ); public void peerSentBadData( PEPeerManager manager, PEPeer peer, int piece_number ); public void destroyed(); } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/PEPeerSource.java0000644000175000017500000000477510737615354023317 0ustar adrianadrian/* * Created on 13-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.peer; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; /** * @author parg * */ public class PEPeerSource { /** * Class to enumerate the sources of peer connections */ // DON'T change these constants as they get serialised!!!! // (obviously you can add new networks to them). // If you add to them remember to update the configuration item default for // "Peer Source Selection Default." and // outgoing connections - details how the peer was discovered public static final String PS_BT_TRACKER = "Tracker"; public static final String PS_DHT = "DHT"; public static final String PS_OTHER_PEER = "PeerExchange"; public static final String PS_PLUGIN = "Plugin"; // incoming connections, we don't know much about these apart from the fact that they occurred public static final String PS_INCOMING = "Incoming"; public static final String[] PS_SOURCES = { PS_BT_TRACKER, PS_DHT, PS_OTHER_PEER, PS_PLUGIN, PS_INCOMING, }; public static boolean isPeerSourceEnabledByDefault( String ps ) { return( COConfigurationManager.getBooleanParameter( "Peer Source Selection Default." + ps )); } public static String[] getDefaultEnabledPeerSources() { List res = new ArrayList(); for (int i=0;i addPiece to simplify new piece-picking, getAvgAvail * */ import java.util.*; import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.peer.impl.PEPeerTransport; import org.gudy.azureus2.core3.peer.util.PeerIdentityDataID; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.plugins.peers.PeerDescriptor; import com.aelitis.azureus.core.networkmanager.LimitedRateGroup; import com.aelitis.azureus.core.peermanager.peerdb.PeerExchangerItem; import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker; public interface PEPeerManager { public DiskManager getDiskManager(); public PiecePicker getPiecePicker(); public PEPeerManagerAdapter getAdapter(); public void start(); public void stopAll(); public byte[] getHash(); public String getDisplayName(); public PeerIdentityDataID getPeerIdentityDataID(); public byte[] getPeerId(); public int[] getAvailability(); public int getAvailability(int pieceNumber); public float getAvgAvail(); public float getMinAvailability(); public long getAvailWentBadTime(); public boolean hasDownloadablePiece(); /** Often better to use getPiece(pieceNumber) */ public PEPiece[] getPieces(); /** @return PEPiece or null if piece not currently active */ public PEPiece getPiece(int pieceNumber); public PEPeerManagerStats getStats(); public void processTrackerResponse( TRTrackerAnnouncerResponse response ); public int getNbPeers(); public int getNbSeeds(); public int getPieceLength(int pieceNumber); public long getRemaining(); public long getHiddenBytes(); public long getETA(); public String getElapsedTime(); // Time Started in ms public long getTimeStarted(); public long getTimeStartedSeeding(); public void addListener( PEPeerManagerListener l ); public void removeListener( PEPeerManagerListener l ); public void addPiece(PEPiece piece, int pieceNumber); public boolean needsMD5CheckOnCompletion(int pieceNumber); public boolean isSeeding(); public boolean isSuperSeedMode(); public boolean canToggleSuperSeedMode(); public void setSuperSeedMode( boolean on ); public boolean seedPieceRecheck(); public int getNbRemoteConnectionsExcludingUDP(); public long getLastRemoteConnectionTime(); public int getMaxNewConnectionsAllowed(); public boolean hasPotentialConnections(); /** * Data bytes received. * @param l */ public void dataBytesReceived( PEPeer peer, int l ); /** * Data bytes sent. * @param l */ public void dataBytesSent( PEPeer peer, int l ); /** * Protocol bytes sent. * @param length */ public void protocolBytesSent( PEPeer peer, int length ); /** * Protocol bytes received. * @param length */ public void protocolBytesReceived( PEPeer peer, int length ); public void discarded( PEPeer peer, int l ); public PEPeerStats createPeerStats( PEPeer owner ); public List getPeers(); public List getPeers( String address ); public PeerDescriptor[] getPendingPeers(); public PeerDescriptor[] getPendingPeers( String address ); public void addPeer( PEPeer peer ); /** * Add a new peer, using the default internal PEPeer implementation * (like for peers given in announce reply), using the given address * and port. * @param ip_address of peer to inject * @param tcp_port of peer to inject * @param udp_port of peer to inject (0 if unknown) * @param use_crypto use encrypted transport */ public void addPeer( String ip_address, int tcp_port, int udp_port, boolean use_crypto, Map user_data ); public void removePeer( PEPeer peer ); public void removePeer( PEPeer peer, String reason ); public void peerAdded(PEPeer pc); public void peerRemoved(PEPeer pc); public DiskManagerReadRequest createDiskManagerRequest( int pieceNumber, int offset, int length ); public void requestCanceled( DiskManagerReadRequest item ); public boolean requestExists( String peer_ip, int piece_number, int offset, int length ); public boolean validatePieceReply( PEPeerTransport originator, int pieceNumber, int offset, DirectByteBuffer data ); public void writeBlock( int pieceNumber, int offset, DirectByteBuffer data, PEPeer sender, boolean cancel); // public void writeBlockAndCancelOutstanding(int pieceNumber, int offset, DirectByteBuffer data,PEPeer sender); public boolean isWritten( int piece_number, int offset ); /** * Are we in end-game mode? * @return true if in end game mode, false if not */ public boolean isInEndGameMode(); /** * Notify the manager that the given peer connection has been closed. * @param peer closed */ public void peerConnectionClosed( PEPeerTransport peer, boolean connect_failed, boolean network_failed ); /** * Register a peer connection for peer exchange handling. * NOTE: Creation could fail if the peer is not eligible for peer exchange (like if it's remote port is unknown). * @param base_peer exchaning with * @return peer database connection item, or null if creation failed */ public PeerExchangerItem createPeerExchangeConnection( PEPeerTransport base_peer ); /** * Notify that the given peer connection represents our own client. * @param self peer */ public void peerVerifiedAsSelf( PEPeerTransport self ); /** * Get the limited rate group used for upload limiting. * @return upload limit group */ public LimitedRateGroup getUploadLimitedRateGroup(); /** * Get the limited rate group used for download limiting. * @return download limit group */ public LimitedRateGroup getDownloadLimitedRateGroup(); public int getUploadRateLimitBytesPerSecond(); public int getDownloadRateLimitBytesPerSecond(); /** To retreive arbitrary objects against this object. */ public Object getData (String key); /** To store arbitrary objects against this object. */ public void setData (String key, Object value); /** * Get the average completion percentage of connected peers. * @return average percent complete in thousand notation */ public int getAverageCompletionInThousandNotation(); /** * Locate an existing transport via peer id byte identity. * @param peer_id to look for * @return transport with matching identity, or null if no match is found */ public PEPeerTransport getTransportFromIdentity( byte[] peer_id ); /** * Locate an existing transport via [IP] Address. * @param peer String to look for * @return PEPeerTransport with matching address String, or null if no match is found */ public PEPeerTransport getTransportFromAddress(String peer); public boolean getPreferUDP(); public void setPreferUDP( boolean prefer ); public void addRateLimiter( LimitedRateGroup group, boolean upload ); public void removeRateLimiter( LimitedRateGroup group, boolean upload ); public boolean isPeerSourceEnabled( String peer_source ); public int getPartitionID(); public void generateEvidence( IndentWriter writer ); } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/util/0000755000175000017500000000000011310377634021105 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/peer/util/PeerUtils.java0000644000175000017500000001403010660570402023655 0ustar adrianadrian/* * Created on Mar 20, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.peer.util; import java.util.HashSet; import java.util.Set; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.util.Constants; /** * Varies peer connection utility methods. */ public class PeerUtils { private static final String CONFIG_MAX_CONN_PER_TORRENT = "Max.Peer.Connections.Per.Torrent"; private static final String CONFIG_MAX_CONN_TOTAL = "Max.Peer.Connections.Total"; public static int MAX_CONNECTIONS_PER_TORRENT; public static int MAX_CONNECTIONS_TOTAL; static{ COConfigurationManager.addParameterListener( CONFIG_MAX_CONN_PER_TORRENT, new ParameterListener() { public void parameterChanged( String parameterName ) { MAX_CONNECTIONS_PER_TORRENT = COConfigurationManager.getIntParameter(CONFIG_MAX_CONN_PER_TORRENT); } }); MAX_CONNECTIONS_PER_TORRENT = COConfigurationManager.getIntParameter(CONFIG_MAX_CONN_PER_TORRENT); COConfigurationManager.addParameterListener( CONFIG_MAX_CONN_TOTAL, new ParameterListener() { public void parameterChanged( String parameterName ) { MAX_CONNECTIONS_TOTAL = COConfigurationManager.getIntParameter(CONFIG_MAX_CONN_TOTAL); } }); MAX_CONNECTIONS_TOTAL = COConfigurationManager.getIntParameter(CONFIG_MAX_CONN_TOTAL); } /** * Get the number of new peer connections allowed for the given data item, * within the configured per-torrent and global connection limits. * @return max number of new connections allowed, or -1 if there is no limit */ public static int numNewConnectionsAllowed( PeerIdentityDataID data_id, int specific_max ) { int curConnPerTorrent = PeerIdentityManager.getIdentityCount( data_id ); int curConnTotal = PeerIdentityManager.getTotalIdentityCount(); // specific max here will default to the global per-torrent default if not explicitly set // so we don't need to consider CONFIG_MAX_CONN_PER_TORRENT seperately int PER_TORRENT_LIMIT = specific_max; int perTorrentAllowed = -1; //default unlimited if ( PER_TORRENT_LIMIT != 0 ) { //if limited int allowed = PER_TORRENT_LIMIT - curConnPerTorrent; if ( allowed < 0 ) allowed = 0; perTorrentAllowed = allowed; } int totalAllowed = -1; //default unlimited if ( MAX_CONNECTIONS_TOTAL != 0 ) { //if limited int allowed = MAX_CONNECTIONS_TOTAL - curConnTotal; if ( allowed < 0 ) allowed = 0; totalAllowed = allowed; } int allowed = -1; //default unlimited if ( perTorrentAllowed > -1 && totalAllowed > -1 ) { //if both limited allowed = Math.min( perTorrentAllowed, totalAllowed ); } else if ( perTorrentAllowed == -1 || totalAllowed == -1 ) { //if either unlimited allowed = Math.max( perTorrentAllowed, totalAllowed ); } return allowed; } private static Set ignore_peer_ports = new HashSet(); static{ COConfigurationManager.addParameterListener( "Ignore.peer.ports", new ParameterListener() { public void parameterChanged( String parameterName ) { readIgnorePeerPorts(); } }); readIgnorePeerPorts(); } private static void readIgnorePeerPorts() { // XXX Optimize me for ranges!! String str = COConfigurationManager.getStringParameter( "Ignore.peer.ports" ).trim(); ignore_peer_ports.clear(); if ( str.length() > 0 ){ String[] ports = str.split("\\;"); if (ports != null && ports.length > 0) { for (int i = 0; i < ports.length; i++) { String port = ports[i]; int spreadPos = port.indexOf('-'); if (spreadPos > 0 && spreadPos < port.length() - 1) { try { int iMin = Integer.parseInt(port.substring(0, spreadPos).trim()); int iMax = Integer.parseInt(port.substring(spreadPos + 1).trim()); for (int j = iMin; j <= iMax; j++) { ignore_peer_ports.add("" + j); } } catch (Exception e) { } } else { ignore_peer_ports.add(port.trim()); } } } } } public static boolean ignorePeerPort( int port ) { return( ignore_peer_ports.contains( "" + port )); } static final String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; public static byte[] createPeerID() { byte[] peerId = new byte[20]; byte[] version = Constants.VERSION_ID; for (int i = 0; i < 8; i++) { peerId[i] = version[i]; } for (int i = 8; i < 20; i++) { int pos = (int) ( Math.random() * chars.length()); peerId[i] = (byte)chars.charAt(pos); } // System.out.println( "generated new peer id:" + ByteFormatter.nicePrint(peerId)); return( peerId ); } public static byte[] createWebSeedPeerID() { byte[] peerId = new byte[20]; peerId[0] = '-'; peerId[1] = 'W'; peerId[2] = 'S'; for (int i = 3; i < 20; i++) { int pos = (int) ( Math.random() * chars.length()); peerId[i] = (byte)chars.charAt(pos); } // System.out.println( "generated new peer id:" + ByteFormatter.nicePrint(peerId)); return( peerId ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/util/PeerIdentityDataID.java0000644000175000017500000000355710373051050025363 0ustar adrianadrian/* * Created on 20-Oct-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.peer.util; import java.util.*; public class PeerIdentityDataID { private final byte[] dataId; private final int hashcode; private Map peer_map; protected PeerIdentityDataID( byte[] _data_id ) { dataId = _data_id; this.hashcode = new String( dataId ).hashCode(); } public byte[] getDataID() { return( dataId ); } protected Map getPeerMap() { return( peer_map ); } protected void setPeerMap( Map m ) { peer_map = m; } public boolean equals( Object obj ) { if (this == obj) return true; if (obj != null && obj instanceof PeerIdentityDataID) { PeerIdentityDataID other = (PeerIdentityDataID)obj; return Arrays.equals(this.dataId, other.dataId); } return false; } public int hashCode() { return hashcode; } }azureus-4.3.0.6/org/gudy/azureus2/core3/peer/util/PeerIdentityManager.java0000644000175000017500000001671710737046232025663 0ustar adrianadrian/* * Created on Mar 18, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.peer.util; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.LightHashMap; /** * Maintains peer identity information. */ public class PeerIdentityManager { private static final boolean MUTLI_CONTROLLERS = COConfigurationManager.getBooleanParameter( "peer.multiple.controllers.per.torrent.enable", false ); private static final AEMonitor class_mon = new AEMonitor( "PeerIdentityManager:class"); private static final Map dataMap = new LightHashMap(); private static int totalIDs = 0; /* static{ new AEThread("mon",true) { public void runSupport() { monitor(); } }.start(); } static void monitor() { while( true ){ try{ class_mon.enter(); System.out.println( "tot = " + getTotalIdentityCount()); Iterator it = dataMap.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); PeerIdentityDataID id = (PeerIdentityDataID)entry.getKey(); Map vals = (Map)entry.getValue(); System.out.println( " id " + ByteFormatter.encodeString( id.getDataID())+ " -> " + vals.size()); } }finally{ class_mon.exit(); } try{ Thread.sleep(10000); }catch( Throwable e ){ } } } */ public static PeerIdentityDataID createDataID( byte[] data ) { PeerIdentityDataID data_id = new PeerIdentityDataID( data ); Map peerMap; try{ class_mon.enter(); peerMap = (Map)dataMap.get( data_id ); if( peerMap == null ){ peerMap = new LightHashMap(); dataMap.put( data_id, peerMap ); } }finally{ class_mon.exit(); } data_id.setPeerMap( peerMap ); return( data_id ); } //Main peer identity container. //Add new identity items (like pgp key, authentication user/pass, etc) //to this class if/when needed. private static class PeerIdentity { private final byte[] id; private final short port; private final int hashcode; private PeerIdentity( byte[] _id, int local_port ) { this.id = _id; port = (short)local_port; this.hashcode = new String( id ).hashCode(); } public boolean equals( Object obj ) { if (this == obj) return true; if (obj != null && obj instanceof PeerIdentity) { PeerIdentity other = (PeerIdentity)obj; if ( MUTLI_CONTROLLERS ){ if ( port != other.port ){ return( false ); } } return Arrays.equals(this.id, other.id); } return false; } public int hashCode() { return hashcode; } protected String getString() { return( ByteFormatter.encodeString( id )); } } /** * Add a new peer identity to the manager. * @param data_id unique id for the data item associated with this connection * @param peer_id unique id for this peer connection * @param ip remote peer's ip address */ public static boolean addIdentity( PeerIdentityDataID data_id, byte[] peer_id, int local_port, String ip ) { PeerIdentity peerID = new PeerIdentity( peer_id, local_port ); try{ class_mon.enter(); Map peerMap = (Map)dataMap.get( data_id ); if( peerMap == null ) { peerMap = new HashMap(); dataMap.put( data_id, peerMap ); } String old = (String)peerMap.put( peerID, ip ); if( old == null ) { totalIDs++; return( true ); }else{ return( false ); } }finally{ class_mon.exit(); } } /** * Remove a peer identity from the manager. * @param data_id id for the data item associated with this connection * @param peer_id id for this peer connection */ public static void removeIdentity( PeerIdentityDataID data_id, byte[] peer_id, int local_port ) { try{ class_mon.enter(); Map peerMap = (Map)dataMap.get( data_id ); if( peerMap != null ) { PeerIdentity peerID = new PeerIdentity( peer_id, local_port ); String old = (String)peerMap.remove( peerID ); if( old != null ) { totalIDs--; }else{ Debug.out( "id not present: id=" + peerID.getString()); } } }finally{ class_mon.exit(); } } /** * Check if the manager already has the given peer identity. * @param data_id id for the data item associated with this connection * @param peer_id id for this peer connection * @return true if the peer identity is found, false if not found */ public static boolean containsIdentity( PeerIdentityDataID data_id, byte[] peer_id, int local_port ) { PeerIdentity peerID = new PeerIdentity( peer_id, local_port ); try{ class_mon.enter(); Map peerMap = (Map)dataMap.get( data_id ); if( peerMap != null ) { if( peerMap.containsKey( peerID ) ) { return true; } } }finally{ class_mon.exit(); } return false; } /** * Get the total number of peer identities managed. * @return total number of peers over all data items */ public static int getTotalIdentityCount() { return totalIDs; } /** * Get the total number of peer identities managed for the given data item. * @param data_id data item to count over * @return total number of peers for this data item */ public static int getIdentityCount( PeerIdentityDataID data_id ) { return( data_id.getPeerMap().size()); } /** * Check if the given IP address is already present in the manager's * peer identity list for the given data item (i.e. check if there is * already a peer with that IP address). * @param data_id id for the data item associated with this connection * @param ip IP address to check for * @return true if the IP is found, false if not found */ public static boolean containsIPAddress( PeerIdentityDataID data_id, String ip ) { try{ class_mon.enter(); Map peerMap = (Map)dataMap.get( data_id ); if( peerMap != null ) { if( peerMap.containsValue( ip ) ) { return true; } } }finally{ class_mon.exit(); } return false; } } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/PEPeerManagerFactory.java0000644000175000017500000000264011165324620024733 0ustar adrianadrian/* * File : PEPeerManagerFactory.java * Created : 15-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.peer; /** * @author parg * */ import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.peer.impl.*; public class PEPeerManagerFactory { public static PEPeerManager create( byte[] peer_id, PEPeerManagerAdapter adapter, DiskManager diskManager ) { return( create( peer_id, adapter, diskManager, 0 )); } public static PEPeerManager create( byte[] peer_id, PEPeerManagerAdapter adapter, DiskManager diskManager, int id ) { return( PEPeerControlFactory.create( peer_id, adapter, diskManager, id )); } } azureus-4.3.0.6/org/gudy/azureus2/core3/peer/PEPeerManagerStats.java0000644000175000017500000000374311255054274024434 0ustar adrianadrian/* * File : PEPeerManagerStats.java * Created : 05-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.peer; public interface PEPeerManagerStats { public void discarded(PEPeer peer, int length); public void hashFailed(int length); public void dataBytesReceived(PEPeer peer, int length); public void protocolBytesReceived(PEPeer peer, int length); public void dataBytesSent(PEPeer peer, int length); public void protocolBytesSent(PEPeer peer, int length); public void haveNewPiece(int pieceLength); public long getDataReceiveRate(); public long getProtocolReceiveRate(); public long getDataSendRate(); public long getProtocolSendRate(); public long getTotalDataBytesSent(); public long getTotalProtocolBytesSent(); public long getTotalDataBytesReceived(); public long getTotalProtocolBytesReceived(); public long getTotalDataBytesSentNoLan(); public long getTotalProtocolBytesSentNoLan(); public long getTotalDataBytesReceivedNoLan(); public long getTotalProtocolBytesReceivedNoLan(); public long getTotalAverage(); public long getTotalHashFailBytes(); public long getTotalDiscarded(); public int getTimeSinceLastDataReceivedInSeconds(); public int getTimeSinceLastDataSentInSeconds(); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/0000755000175000017500000000000011310377634020127 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerReadRequestListener.java0000644000175000017500000000310110556302602027017 0ustar adrianadrian/* * Created on Jul 19, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk; import org.gudy.azureus2.core3.util.DirectByteBuffer; /** * Used for receiving notification of async read request completion. */ public interface DiskManagerReadRequestListener { /** * Notification that the read request has completed, * along with its accompanying buffer data. * @param request * @param data */ public void readCompleted( DiskManagerReadRequest request, DirectByteBuffer data ); public void readFailed( DiskManagerReadRequest request, Throwable cause ); public int getPriority(); public void requestExecuted( long bytes ); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManager.java0000644000175000017500000001456711274472052023173 0ustar adrianadrian/* * File : DiskManagerImpl.java * Created : 18-Oct-2003 * By : stuff * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.disk; import java.io.File; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceList; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceMap; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.IndentWriter; /** * @author MjrTom * 2005/Oct/08: Priority, getPieces done, etc changes for new piece-picking */ public interface DiskManager { public static final int INITIALIZING = 1; public static final int ALLOCATING = 2; public static final int CHECKING = 3; public static final int READY = 4; public static final int FAULTY = 10; // CHANGE THIS AND YOU MUST CHANGE NORMAL_REQUEST_SIZE in PeerReadRequest (plugin interface) public static final int BLOCK_SIZE_KB = 16; public static final int BLOCK_SIZE = BLOCK_SIZE_KB*1024; /** * Start checking/allocating */ public void start(); public void stop( boolean closing ); /** * @return whether all files exist and sizes match */ public boolean filesExist(); public DirectByteBuffer readBlock( int pieceNumber, int offset, int length ); public DiskManagerWriteRequest createWriteRequest( int pieceNumber, int offset, DirectByteBuffer data, Object user_data ); /** * enqueue an async write request * @param pieceNumber * @param offset * @param data * @param user_data this will be provided to the listener when called back * @param listener */ public void enqueueWriteRequest( DiskManagerWriteRequest request, DiskManagerWriteRequestListener listener ); public boolean hasOutstandingWriteRequestForPiece( int piece_number ); public DiskManagerReadRequest createReadRequest( int pieceNumber, int offset, int length ); /** * Enqueue an async disk read request. * @param request * @param listener */ public void enqueueReadRequest( DiskManagerReadRequest request, DiskManagerReadRequestListener listener ); public boolean hasOutstandingReadRequestForPiece( int piece_number ); /** * Create a request to check a particular piece * @param pieceNumber -1 for a complete recheck request * @param user_data * @return */ public DiskManagerCheckRequest createCheckRequest( int pieceNumber, Object user_data ); /** * enqueue an asynchronous single piece check * @param pieceNumber * @param listener * @param user_data */ public void enqueueCheckRequest( DiskManagerCheckRequest request, DiskManagerCheckRequestListener listener ); public boolean hasOutstandingCheckRequestForPiece( int piece_number ); /** * recheck the entire torrent asynchronously, reporting each piece to the listener * @param listener * @param user_data */ public void enqueueCompleteRecheckRequest( DiskManagerCheckRequest request, DiskManagerCheckRequestListener listener ); public void setPieceCheckingEnabled( boolean enabled ); public void saveResumeData( boolean interim_save ) throws Exception; public DiskManagerPiece[] getPieces(); public int getNbPieces(); public DiskManagerFileInfo[] getFiles(); public DiskManagerFileInfoSet getFileSet(); public DiskManagerPiece getPiece(int PieceNumber); /** * DON'T CACHE the DMPieceMap - as it is designed to be discarded when not in use * @return */ public DMPieceMap getPieceMap(); public DMPieceList getPieceList(int pieceNumber); public int getState(); public long getTotalLength(); public int getPieceLength(); public int getPieceLength( int piece_number ); public long getRemaining(); public long getRemainingExcludingDND(); /** * Get the percentage done during checking, allocation or initializing * * @return percent done * 1000 (1000 = 100%) */ public int getPercentDone(); public String getErrorMessage(); public void downloadEnded(); public void downloadRemoved(); public void moveDataFiles(File new_parent_dir, String dl_name); /** * returns -1 if no recheck in progress, percentage complete in 1000 notation otherwise * @return */ public int getCompleteRecheckStatus(); /** * method for checking that the block details are sensible * @param pieceNumber * @param offset * @param data * @return */ public boolean checkBlockConsistencyForWrite( String originator, int pieceNumber, int offset, DirectByteBuffer data ); /** * method for checking that the block details are sensible * @param pieceNumber * @param offset * @param length * @return */ public boolean checkBlockConsistencyForRead( String originator, int pieceNumber, int offset, int length ); public boolean checkBlockConsistencyForHint( String originator, int pieceNumber, int offset, int length ); public TOTorrent getTorrent(); public File getSaveLocation(); public void addListener( DiskManagerListener l ); public void removeListener( DiskManagerListener l ); public boolean hasListener( DiskManagerListener l ); /** * Save the individual file priorities map to * DownloadManager.getData( "file_priorities" ). */ public void saveState(); /** * @param pieceNumber * @return true if the pieceNumber is Needed and not Done */ public boolean isInteresting(int pieceNumber); public boolean isDone(int pieceNumber); public int getCacheMode(); public long[] getReadStats(); public void generateEvidence( IndentWriter writer ); }azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerFileInfoListener.java0000644000175000017500000000220610421017152026265 0ustar adrianadrian/* * Created on 14-Apr-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk; public interface DiskManagerFileInfoListener { public void dataWritten( long offset, long length ); public void dataChecked( long offset, long length ); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerRequest.java0000644000175000017500000000212110457566044024532 0ustar adrianadrian/* * Created on 19 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk; public interface DiskManagerRequest { public void requestStarts(); public void requestEnds( boolean ok ); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerReadRequest.java0000644000175000017500000000361310761466120025325 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.disk; import org.gudy.azureus2.plugins.peers.PeerReadRequest; /** * * This class represents a Bittorrent Request. * and a time stamp to know when it was created. * * Request may expire after some time, which is used to determine who is snubbed. * * @author Olivier * * */ public interface DiskManagerReadRequest extends PeerReadRequest, DiskManagerRequest { public int getPieceNumber(); public int getOffset(); public int getLength(); public long getTimeCreated(final long now); /** * If flush is set then data held in memory will be flushed to disk during the read operation * @param flush */ public void setFlush( boolean flush ); public boolean getFlush(); public void setUseCache( boolean cache ); public boolean getUseCache(); /** * We override the equals method * 2 requests are equals if * all their bt fields (piece number, offset, length) are equal */ public boolean equals(Object o); public int hashCode(); }azureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/0000755000175000017500000000000011310377634021070 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/DiskManagerPieceImpl.java0000644000175000017500000002262410650231602025704 0ustar adrianadrian/* * Created on 08-Oct-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk.impl; /** * @author parg * @author MjrTom * 2005/Oct/08: startPriority/resumePriority handling and minor clock fixes * 2006/Jan/02: refactoring, change booleans to statusFlags */ import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceList; public class DiskManagerPieceImpl implements DiskManagerPiece { //private static final LogIDs LOGID = LogIDs.PIECES; private static final byte PIECE_STATUS_NEEDED = 0x01; //want to have the piece private static final byte PIECE_STATUS_WRITTEN = 0x20; //piece fully written to storage private static final byte PIECE_STATUS_CHECKING = 0x40; //piece is being hash checked private static final byte PIECE_STATUS_MASK_DOWNLOADABLE = PIECE_STATUS_CHECKING | PIECE_STATUS_WRITTEN | PIECE_STATUS_NEEDED; // 0x65; // Needed IS once again included in this private static final byte PIECE_STATUS_MASK_NEEDS_CHECK = PIECE_STATUS_CHECKING | PIECE_STATUS_WRITTEN; //private static boolean statusTested =false; private final DiskManagerHelper diskManager; private final int pieceNumber; /** the number of blocks in this piece: can be short as this gives up to .5GB piece sizes with 16K blocks */ private final short nbBlocks; // to save memory the "written" field is only maintained for pieces that are // downloading. A value of "null" means that either the piece hasn't started // download or that it is complete. // access to "written" is single-threaded (by the peer manager) apart from when // the disk manager is saving resume data. // actually this is not longer strictly true, as setDone is called asynchronously // however, this issue can be worked around by working on a reference to the written data // as problems only occur when switching from all-written to done=true, both of which signify // the same state of affairs. protected volatile boolean[] written; private byte statusFlags; /** it's *very* important to accurately maintain the "done" state of a piece. Currently the statusFlags * are updated in a non-thread-safe manner so a 'done' field is maintained seperatly. Synchronizing * access to statusFlags or done would cause a tremendous performance hit. */ private short read_count; private boolean done; public DiskManagerPieceImpl(final DiskManagerHelper _disk_manager, final int pieceIndex, int length ) { diskManager =_disk_manager; pieceNumber = pieceIndex; nbBlocks =(short)((length +DiskManager.BLOCK_SIZE -1) /DiskManager.BLOCK_SIZE); statusFlags = PIECE_STATUS_NEEDED; } public DiskManager getManager() { return diskManager; } public int getPieceNumber() { return pieceNumber; } /** * @return int number of bytes in the piece */ public int getLength() { return( diskManager.getPieceLength( pieceNumber )); } public int getNbBlocks() { return nbBlocks; } public short getReadCount() { return( read_count ); } public void setReadCount( short c ) { read_count = c; } public int getBlockSize(final int blockNumber) { if ( blockNumber == nbBlocks -1 ){ int len = getLength() % DiskManager.BLOCK_SIZE; if ( len != 0 ){ return( len ); } } return DiskManager.BLOCK_SIZE; } public boolean isSkipped() { final DMPieceList pieceList =diskManager.getPieceList(pieceNumber); for (int i =0; i 0 &&file.getDownloaded() listeners_aggregator = ListenerManager.createAsyncManager( "DiskM:ListenAggregatorDispatcher", new ListenerManagerDispatcher() { public void dispatch( DiskManagerListener listener, int type, Object value ) { if (type == LDT_STATECHANGED){ int params[] = (int[])value; listener.stateChanged(params[0], params[1]); }else if (type == LDT_PRIOCHANGED) { listener.filePriorityChanged((DiskManagerFileInfo)value); }else if (type == LDT_PIECE_DONE_CHANGED) { listener.pieceDoneChanged((DiskManagerPiece)value); }else if (type == LDT_ACCESS_MODE_CHANGED) { Object[] o = (Object[])value; listener.fileAccessModeChanged( (DiskManagerFileInfo)o[0], ((Integer)o[1]).intValue(), ((Integer)o[2]).intValue()); } } }); private ListenerManager listeners = ListenerManager.createManager( "DiskM:ListenDispatcher", new ListenerManagerDispatcher() { public void dispatch( DiskManagerListener listener, int type, Object value ) { listeners_aggregator.dispatch( listener, type, value ); } }); private AEMonitor start_stop_mon = new AEMonitor( "DiskManager:startStop" ); private AEMonitor file_piece_mon = new AEMonitor( "DiskManager:filePiece" ); public DiskManagerImpl( TOTorrent _torrent, DownloadManager _dmanager) { torrent = _torrent; download_manager = _dmanager; pieces = new DiskManagerPieceImpl[0]; // in case things go wrong later setState( INITIALIZING ); percentDone = 0; if ( torrent == null ){ errorMessage = "Torrent not available"; setState( FAULTY ); return; } LocaleUtilDecoder locale_decoder = null; try{ locale_decoder = LocaleTorrentUtil.getTorrentEncoding( torrent ); }catch( TOTorrentException e ){ Debug.printStackTrace( e ); errorMessage = TorrentUtils.exceptionToText(e); setState( FAULTY ); return; }catch( Throwable e ){ Debug.printStackTrace( e ); errorMessage = "Initialisation failed - " + Debug.getNestedExceptionMessage(e); setState( FAULTY ); return; } piece_mapper = DMPieceMapperFactory.create( torrent ); try{ piece_mapper.construct( locale_decoder, download_manager.getAbsoluteSaveLocation().getName()); }catch( Throwable e ){ Debug.printStackTrace( e ); errorMessage = "Failed to build piece map - " + Debug.getNestedExceptionMessage(e); setState( FAULTY ); return; } totalLength = piece_mapper.getTotalLength(); remaining = totalLength; nbPieces = torrent.getNumberOfPieces(); pieceLength = (int)torrent.getPieceLength(); lastPieceLength = piece_mapper.getLastPieceLength(); pieces = new DiskManagerPieceImpl[nbPieces]; for (int i =0; i target_length ){ if ( COConfigurationManager.getBooleanParameter("File.truncate.if.too.large")){ file_info.setAccessMode( DiskManagerFileInfo.WRITE ); file_info.getCacheFile().setLength( target_length ); Debug.out( "Existing data file length too large [" +existing_length+ ">" +target_length+ "]: " + data_file.getAbsolutePath() + ", truncating" ); }else{ errorMessage = "Existing data file length too large [" +existing_length+ ">" +target_length+ "]: " + data_file.getAbsolutePath(); return false; } } }finally{ if ( close_it ){ file_info.getCacheFile().close(); } } }catch( Throwable e ){ errorMessage = Debug.getNestedExceptionMessage(e) + " (filesExist:" + relative_file.toString() + ")"; return( false ); } } return true; } private int allocateFiles() { Set file_set = new HashSet(); DMPieceMapperFile[] pm_files = piece_mapper.getFiles(); DiskManagerFileInfoImpl[] allocated_files = new DiskManagerFileInfoImpl[pm_files.length]; try{ allocation_scheduler.register( this ); setState( ALLOCATING ); allocated = 0; int numNewFiles = 0; String root_dir = download_manager.getAbsoluteSaveLocation().getParent(); if ( !torrent.isSimpleTorrent()){ root_dir += File.separator + download_manager.getAbsoluteSaveLocation().getName(); } root_dir += File.separator; String[] storage_types = getStorageTypes(); for ( int i=0;i target_length ){ if ( COConfigurationManager.getBooleanParameter("File.truncate.if.too.large")){ fileInfo.setAccessMode( DiskManagerFileInfo.WRITE ); cache_file.setLength( target_length ); fileInfo.setAccessMode( DiskManagerFileInfo.READ ); Debug.out( "Existing data file length too large [" +existing_length+ ">" +target_length+ "]: " +data_file.getAbsolutePath() + ", truncating" ); }else{ this.errorMessage = "Existing data file length too large [" +existing_length+ ">" +target_length+ "]: " + data_file.getAbsolutePath(); setState( FAULTY ); return( -1 ); } }else if ( existing_length < target_length ){ if ( !compact ){ // file is too small if ( !allocateFile( fileInfo, data_file, existing_length, target_length )){ // aborted return( -1 ); } } } }catch (Throwable e) { fileAllocFailed( data_file, target_length, false, e ); setState( FAULTY ); return( -1 ); } allocated += target_length; } else if ( mustExistOrAllocate ){ //we need to allocate it //make sure it hasn't previously been allocated if ( download_manager.isDataAlreadyAllocated() ){ this.errorMessage = "Data file missing: " + data_file.getAbsolutePath(); setState( FAULTY ); return( -1 ); } try{ if ( !allocateFile( fileInfo, data_file, -1, target_length )){ // aborted return( -1 ); } }catch( Throwable e ){ fileAllocFailed( data_file, target_length, true, e ); setState( FAULTY ); return( -1 ); } numNewFiles++; } } // make sure that "files" doens't become visible to the rest of the world until all // entries have been populated files = allocated_files; fileset = new DiskManagerFileInfoSetImpl(files,this); loadFilePriorities(); download_manager.setDataAlreadyAllocated( true ); return( numNewFiles ); }finally{ allocation_scheduler.unregister( this ); // if we failed to do the allocation make sure we close all the files that // we might have opened if ( files == null ){ for (int i=0;i 0 && COConfigurationManager.getBooleanParameter("XFS Allocation") ){ fileInfo.getCacheFile().setLength( target_length ); long resvp_start; long resvp_len; if ( existing_length > 0 ){ resvp_start = existing_length; resvp_len = target_length - existing_length; }else{ resvp_start = 0; resvp_len = target_length; } String[] cmd = {"/usr/sbin/xfs_io","-c", "resvsp " + resvp_start + " " + resvp_len, data_file.getAbsolutePath()}; ByteArrayOutputStream os = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; try { Process p = Runtime.getRuntime().exec(cmd); for (int count = p.getErrorStream().read(buffer); count > 0; count = p.getErrorStream().read(buffer)) { os.write(buffer, 0, count); } os.close(); p.waitFor(); } catch (IOException e) { String message = MessageText.getString("xfs.allocation.xfs_io.not.found", new String[] {e.getMessage()}); Logger.log(new LogAlert(this, LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, message)); } if (os.size() > 0) { String message = os.toString().trim(); if (message.endsWith("is not on an XFS filesystem")) { Logger.log(new LogEvent(this, LogIDs.DISK, "XFS file allocation impossible because \"" + data_file.getAbsolutePath() + "\" is not on an XFS filesystem. Original error reported by xfs_io : \"" + message + "\"")); } else { throw new Exception(message); } } allocated += target_length; }else if( COConfigurationManager.getBooleanParameter("Zero New") ) { //zero fill boolean successfulAlloc = false; try { successfulAlloc = writer.zeroFile( fileInfo, target_length ); }catch( Throwable e ){ // in case an error occured set the error message before we set it to FAULTY in the finally clause, the exception handler further down is too late fileAllocFailed( data_file, target_length, existing_length==-1, e ); throw( e ); }finally{ if (!successfulAlloc){ try{ // failed to zero it, delete it so it gets done next start fileInfo.getCacheFile().close(); fileInfo.getCacheFile().delete(); }catch (Throwable e){ } setState(FAULTY); } } // the zeroFile method updates allocation as it occurs }else{ //reserve the full file size with the OS file system fileInfo.getCacheFile().setLength( target_length ); allocated += target_length; } } fileInfo.setAccessMode( DiskManagerFileInfo.READ ); return( true ); } private void fileAllocFailed( File file, long length, boolean is_new, Throwable e ) { errorMessage = Debug.getNestedExceptionMessage(e) + " (allocateFiles " + (is_new?"new":"existing") + ":" + file.toString() + ")"; if ( errorMessage.indexOf( "not enough space" ) != -1 ){ if ( length >= 4*1024*1024*1024L ){ // might be FAT32 limit, see if we really have run out of space errorMessage = MessageText.getString( "DiskManager.error.nospace_fat32" ); }else{ errorMessage = MessageText.getString( "DiskManager.error.nospace" ); } } } public DiskAccessController getDiskAccessController() { return( disk_access_controller ); } public void enqueueReadRequest( DiskManagerReadRequest request, DiskManagerReadRequestListener listener ) { reader.readBlock( request, listener ); } public boolean hasOutstandingReadRequestForPiece( int piece_number ) { return( reader.hasOutstandingReadRequestForPiece( piece_number )); } public int getNbPieces() { return nbPieces; } public int getPercentDone() { return percentDone; } public void setPercentDone( int num ) { percentDone = num; } public long getRemaining() { return remaining; } public long getRemainingExcludingDND() { if ( skipped_file_set_changed ){ DiskManagerFileInfoImpl[] current_files = files; if ( current_files != null ){ skipped_file_set_changed = false; try{ file_piece_mon.enter(); skipped_file_set_size = 0; skipped_but_downloaded = 0; for (int i=0;ifile_length) { Debug.out("piece map entry length too large"); file_done =file_length; } if (this_file.isSkipped()) { skipped_but_downloaded +=(file_done -file_done_before); } this_file.setDownloaded(file_done); // change file modes based on whether or not the file is complete or not if ( file_done == file_length && this_file.getAccessMode() == DiskManagerFileInfo.WRITE ){ try{ this_file.setAccessMode(DiskManagerFileInfo.READ); DownloadManagerState state = download_manager.getDownloadState(); String suffix = state.getAttribute( DownloadManagerState.AT_INCOMP_FILE_SUFFIX ); if ( suffix != null && suffix.length() > 0 ){ File base_file = this_file.getFile( false ); File link = state.getFileLink( base_file ); if ( link != null ){ String name = link.getName(); if ( name.endsWith( suffix ) && name.length() > suffix.length()){ String new_name = name.substring( 0, name.length() - suffix.length()); File new_file = new File( link.getParentFile(), new_name ); if ( !new_file.exists()){ this_file.renameFile( new_name, false ); if ( base_file.equals( new_file )){ state.setFileLink( base_file, null ); }else{ state.setFileLink( base_file, new_file ); } } } } } }catch ( Throwable e ){ setFailed("Disk access error - " +Debug.getNestedExceptionMessage(e)); Debug.printStackTrace(e); } // note - we don't set the access mode to write if incomplete as we may // be rechecking a file and during this process the "file_done" amount // will not be file_length until the end. If the file is read-only then // changing to write will cause trouble! } } if ( getState() == READY ){ // don't start firing these until we're ready otherwise we send notifications // for complete pieces during initialisation listeners.dispatch(LDT_PIECE_DONE_CHANGED, dmPiece); } } } finally { file_piece_mon.exit(); } } public void accessModeChanged( DiskManagerFileInfoImpl file, int old_mode, int new_mode ) { listeners.dispatch( LDT_ACCESS_MODE_CHANGED, new Object[]{ file, new Integer(old_mode), new Integer(new_mode)}); } public DiskManagerPiece[] getPieces() { return pieces; } public DiskManagerPiece getPiece(int PieceNumber) { return pieces[PieceNumber]; } public int getPieceLength() { return pieceLength; } public int getPieceLength( int piece_number ) { if (piece_number == nbPieces -1 ){ return( lastPieceLength ); }else{ return( pieceLength ); } } public long getTotalLength() { return totalLength; } public int getLastPieceLength() { return lastPieceLength; } public int getState() { return state_set_via_method; } protected void setState( int _state ) { // we never move from a faulty state if ( state_set_via_method == FAULTY ){ if ( _state != FAULTY ){ Debug.out( "DiskManager: attempt to move from faulty state to " + _state ); } return; } if ( state_set_via_method != _state ){ int params[] = {state_set_via_method, _state}; state_set_via_method = _state; listeners.dispatch( LDT_STATECHANGED, params); } } public DiskManagerFileInfo[] getFiles() { return files; } public DiskManagerFileInfoSet getFileSet() { return fileset; } public String getErrorMessage() { return errorMessage; } public void setFailed( final String reason ) { /** * need to run this on a separate thread to avoid deadlock with the stopping * process - setFailed tends to be called from within the read/write activities * and stopping these requires this. */ new AEThread("DiskManager:setFailed") { public void runSupport() { errorMessage = reason; Logger.log(new LogAlert(DiskManagerImpl.this, LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, errorMessage)); setState( DiskManager.FAULTY ); DiskManagerImpl.this.stop( false ); } }.start(); } public void setFailed( final DiskManagerFileInfo file, final String reason ) { /** * need to run this on a separate thread to avoid deadlock with the stopping * process - setFailed tends to be called from within the read/write activities * and stopping these requires this. */ new AEThread("DiskManager:setFailed") { public void runSupport() { errorMessage = reason; Logger.log(new LogAlert(DiskManagerImpl.this, LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, errorMessage)); setState( DiskManager.FAULTY ); DiskManagerImpl.this.stop( false ); RDResumeHandler.recheckFile( download_manager, file ); } }.start(); } public int getCacheMode() { return( CacheFileOwner.CACHE_MODE_NORMAL ); } public long[] getReadStats() { if ( reader == null ){ return( new long[]{ 0, 0 }); } return( reader.getStats()); } public DMPieceMap getPieceMap() { DMPieceMap map = piece_map_use_accessor; if ( map == null ){ // System.out.println( "Creating piece list for " + new String( torrent.getName())); piece_map_use_accessor = map = piece_mapper.getPieceMap(); } piece_map_use_accessor_time = SystemTime.getCurrentTime(); return( map ); } public DMPieceList getPieceList( int piece_number ) { DMPieceMap map = getPieceMap(); return( map.getPieceList( piece_number )); } public void checkFreePieceList( boolean force_discard ) { if ( piece_map_use_accessor == null ){ return; } long now = SystemTime.getCurrentTime(); if ( !force_discard ){ if ( now < piece_map_use_accessor_time ){ piece_map_use_accessor_time = now; return; }else if ( now - piece_map_use_accessor_time < DM_FREE_PIECELIST_TIMEOUT ){ return; } } // System.out.println( "Discarding piece list for " + new String( torrent.getName())); piece_map_use_accessor = null; } public byte[] getPieceHash( int piece_number ) throws TOTorrentException { return( torrent.getPieces()[ piece_number ]); } public DiskManagerReadRequest createReadRequest( int pieceNumber, int offset, int length ) { return( reader.createReadRequest( pieceNumber, offset, length )); } public DiskManagerCheckRequest createCheckRequest( int pieceNumber, Object user_data ) { return( checker.createCheckRequest( pieceNumber, user_data )); } public boolean hasOutstandingCheckRequestForPiece( int piece_number ) { return( checker.hasOutstandingCheckRequestForPiece( piece_number )); } public void enqueueCompleteRecheckRequest( DiskManagerCheckRequest request, DiskManagerCheckRequestListener listener ) { checker.enqueueCompleteRecheckRequest( request, listener ); } public void enqueueCheckRequest( DiskManagerCheckRequest request, DiskManagerCheckRequestListener listener ) { checker.enqueueCheckRequest( request, listener ); } public int getCompleteRecheckStatus() { return ( checker.getCompleteRecheckStatus()); } public void setPieceCheckingEnabled( boolean enabled ) { checking_enabled = enabled; checker.setCheckingEnabled( enabled ); } public DirectByteBuffer readBlock( int pieceNumber, int offset, int length ) { return( reader.readBlock( pieceNumber, offset, length )); } public DiskManagerWriteRequest createWriteRequest( int pieceNumber, int offset, DirectByteBuffer data, Object user_data ) { return( writer.createWriteRequest( pieceNumber, offset, data, user_data )); } public void enqueueWriteRequest( DiskManagerWriteRequest request, DiskManagerWriteRequestListener listener ) { writer.writeBlock( request, listener ); } public boolean hasOutstandingWriteRequestForPiece( int piece_number ) { return( writer.hasOutstandingWriteRequestForPiece( piece_number )); } public boolean checkBlockConsistencyForWrite( String originator, int pieceNumber, int offset, DirectByteBuffer data ) { if (pieceNumber < 0) { if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, LogEvent.LT_ERROR, "Write invalid: " + originator + " pieceNumber=" + pieceNumber + " < 0")); return false; } if (pieceNumber >= this.nbPieces) { if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, LogEvent.LT_ERROR, "Write invalid: " + originator + " pieceNumber=" + pieceNumber + " >= this.nbPieces=" + this.nbPieces)); return false; } int length = this.pieceLength; if (pieceNumber == nbPieces - 1) { length = this.lastPieceLength; } if (offset < 0) { if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, LogEvent.LT_ERROR, "Write invalid: " + originator + " offset=" + offset + " < 0")); return false; } if (offset > length) { if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, LogEvent.LT_ERROR, "Write invalid: " + originator + " offset=" + offset + " > length=" + length)); return false; } int size = data.remaining(DirectByteBuffer.SS_DW); if (size <= 0) { if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, LogEvent.LT_ERROR, "Write invalid: " + originator + " size=" + size + " <= 0")); return false; } if (offset + size > length) { if (Logger.isEnabled()) Logger.log(new LogEvent(this, LOGID, LogEvent.LT_ERROR, "Write invalid: " + originator + " offset=" + offset + " + size=" + size + " > length=" + length)); return false; } return true; } public boolean checkBlockConsistencyForRead( String originator, int pieceNumber, int offset, int length ) { return( DiskManagerUtil.checkBlockConsistencyForRead(this, originator, pieceNumber, offset, length)); } public boolean checkBlockConsistencyForHint( String originator, int pieceNumber, int offset, int length ) { return( DiskManagerUtil.checkBlockConsistencyForHint(this, originator, pieceNumber, offset, length)); } public void saveResumeData( boolean interim_save ) throws Exception { resume_handler.saveResumeData( interim_save ); } public void downloadEnded() { moveDownloadFilesWhenEndedOrRemoved(false, true); } public void downloadRemoved () { moveDownloadFilesWhenEndedOrRemoved(true, true); } private boolean moveDownloadFilesWhenEndedOrRemoved(final boolean removing, final boolean torrent_file_exists) { try { start_stop_mon.enter(); final boolean ending = !removing; // Just a friendly alias. /** * It doesn't matter if we set alreadyMoved, but don't end up moving the files. * This is because we only get called once (when it matters), which is when the * download has finished. We only want this to apply when the download has finished, * not if the user restarts the (already completed) download. */ if (ending) { if (this.alreadyMoved) {return false;} this.alreadyMoved = true; } SaveLocationChange move_details; if (removing) { move_details = DownloadManagerMoveHandler.onRemoval(this.download_manager); } else { move_details = DownloadManagerMoveHandler.onCompletion(this.download_manager); } if (move_details != null) {moveFiles(move_details, true);} return true; } finally{ start_stop_mon.exit(); if (!removing) { try{ saveResumeData(false); }catch( Throwable e ){ setFailed("Resume data save fails: " + Debug.getNestedExceptionMessage(e)); } } } } public void moveDataFiles(File new_parent_dir, String new_name) { SaveLocationChange loc_change = new SaveLocationChange(); loc_change.download_location = new_parent_dir; loc_change.download_name = new_name; moveFiles(loc_change, false); } protected void moveFiles(SaveLocationChange loc_change, boolean change_to_read_only) { boolean move_files = false; if (loc_change.hasDownloadChange()) { move_files = !this.isFileDestinationIsItself(loc_change); } try { start_stop_mon.enter(); /** * The 0 suffix is indicate that these are quite internal, and are * only intended for use within this method. */ boolean files_moved = true; if (move_files) { files_moved = moveDataFiles0(loc_change, change_to_read_only); } if (loc_change.hasTorrentChange() && files_moved) { moveTorrentFile(loc_change); } } catch(Exception e) { Debug.printStackTrace(e); } finally{ start_stop_mon.exit(); } } // Helper function private void logMoveFileError(String destination_path, String message) { Logger.log(new LogEvent(this, LOGID, LogEvent.LT_ERROR, message)); Logger.logTextResource(new LogAlert(this, LogAlert.REPEATABLE, LogAlert.AT_ERROR, "DiskManager.alert.movefilefails"), new String[] {destination_path, message}); } private boolean isFileDestinationIsItself(SaveLocationChange loc_change) { File old_location = download_manager.getAbsoluteSaveLocation(); File new_location = loc_change.normaliseDownloadLocation(old_location); try { old_location = old_location.getCanonicalFile(); new_location = new_location.getCanonicalFile(); if (old_location.equals(new_location)) {return true;} if (!download_manager.getTorrent().isSimpleTorrent() && FileUtil.isAncestorOf(new_location, old_location)) { String msg = "Target is sub-directory of files"; logMoveFileError(new_location.toString(), msg); return true; } } catch (Throwable e) { Debug.out(e); } return false; } private boolean moveDataFiles0(SaveLocationChange loc_change, final boolean change_to_read_only) throws Exception { File move_to_dir_name = loc_change.download_location; if (move_to_dir_name == null) {move_to_dir_name = download_manager.getAbsoluteSaveLocation().getParentFile();} final String move_to_dir = move_to_dir_name.toString(); final String new_name = loc_change.download_name; // consider the two cases: // simple torrent: /temp/simple.avi // complex torrent: /temp/complex[/other.avi] // we are moving the files to the "move_to_arg" /M and possibly renaming to "wibble.x" // /temp/simple.avi, null -> /M/simple.avi // /temp, "wibble.x" -> /M/wibble.x // /temp/complex[/other.avi], null -> /M/complex[/other.avi] // /temp, "wibble.x" -> /M/wibble.x[/other.avi] if ( files == null ){return false;} if (isFileDestinationIsItself(loc_change)) {return false;} boolean simple_torrent = download_manager.getTorrent().isSimpleTorrent(); // absolute save location does not follow links // for simple: /temp/simple.avi // for complex: /temp/complex final File save_location = download_manager.getAbsoluteSaveLocation(); // It is important that we are able to get the canonical form of the directory to // move to, because later code determining new file paths will break otherwise. final String move_from_dir = save_location.getParentFile().getCanonicalFile().getPath(); File[] new_files = new File[files.length]; File[] old_files = new File[files.length]; boolean[] link_only = new boolean[files.length]; for (int i=0; i < files.length; i++) { File old_file = files[i].getFile(false); File linked_file = FMFileManagerFactory.getSingleton().getFileLink( torrent, old_file ); if ( !linked_file.equals(old_file)){ if ( simple_torrent ){ // simple torrent, only handle a link if its a simple rename if ( linked_file.getParentFile().getCanonicalPath().equals( save_location.getParentFile().getCanonicalPath())){ old_file = linked_file; }else{ link_only[i] = true; } }else{ // if we are linked to a file outside of the torrent's save directory then we don't // move the file if ( linked_file.getCanonicalPath().startsWith( save_location.getCanonicalPath())){ old_file = linked_file; }else{ link_only[i] = true; } } } /** * We are trying to calculate the relative path of the file within the original save * directory, and then use that to calculate the new save path of the file in the new * save directory. * * We have three cases which we may deal with: * 1) Where the file in the torrent has never been moved (therefore, old_file will * equals linked_file), * 2) Where the file in the torrent has been moved somewhere elsewhere inside the save * path (old_file will not equal linked_file, but we will overwrite the value of * old_file with linked_file), * 3) Where the file in the torrent has been moved outside of the download path - meaning * we set link_only[i] to true. This is just to update the internal reference of where * the file should be - it doesn't move the file at all. * * Below, we will determine a new path for the file, but only in terms of where it should be * inside the new download save location - if the file currently exists outside of the save * location, we will not move it. */ old_files[i] = old_file; /** * move_from_dir should be canonical (see earlier code). * * Need to get canonical form of the old file, because that's what we are using for determining * the relative path. */ String old_parent_path = old_file.getCanonicalFile().getParent(); String sub_path; /** * Calculate the sub path of where the file lives compared to the new save location. * * The code here has changed from what it used to be to fix bug 1636342: * https://sourceforge.net/tracker/?func=detail&atid=575154&aid=1636342&group_id=84122 */ if ( old_parent_path.startsWith(move_from_dir)){ sub_path = old_parent_path.substring(move_from_dir.length()); }else{ logMoveFileError(move_to_dir, "Could not determine relative path for file - " + old_parent_path); throw new IOException("relative path assertion failed: move_from_dir=\"" + move_from_dir + "\", old_parent_path=\"" + old_parent_path + "\""); } //create the destination dir if ( sub_path.startsWith( File.separator )){ sub_path = sub_path.substring(1); } // We may be doing a rename, and if this is a simple torrent, we have to keep the names in sync. File new_file; if ( new_name == null ){ new_file = new File( new File( move_to_dir, sub_path ), old_file.getName()); }else{ // renaming if ( simple_torrent ){ new_file = new File( new File( move_to_dir, sub_path ), new_name ); }else{ // subpath includes the old dir name, replace this with new int pos = sub_path.indexOf( File.separator ); String new_path; if (pos == -1) { new_path = new_name; } else { // Assertion check. String sub_sub_path = sub_path.substring(pos); String expected_old_name = sub_path.substring(0, pos); new_path = new_name + sub_sub_path; boolean assert_expected_old_name = expected_old_name.equals(save_location.getName()); if (!assert_expected_old_name) { Debug.out("Assertion check for renaming file in multi-name torrent " + (assert_expected_old_name ? "passed" : "failed") + "\n" + " Old parent path: " + old_parent_path + "\n" + " Subpath: " + sub_path + "\n" + " Sub-subpath: " + sub_sub_path + "\n" + " Expected old name: " + expected_old_name + "\n" + " Torrent pre-move name: " + save_location.getName() + "\n" + " New torrent name: " + new_name + "\n" + " Old file: " + old_file + "\n" + " Linked file: " + linked_file + "\n" + "\n" + " Move-to-dir: " + move_to_dir + "\n" + " New path: " + new_path + "\n" + " Old file [name]: " + old_file.getName() + "\n" ); } } new_file = new File( new File( move_to_dir, new_path ), old_file.getName()); } } new_files[i] = new_file; if ( !link_only[i] ){ if ( new_file.exists()){ String msg = "" + linked_file.getName() + " already exists in MoveTo destination dir"; Logger.log(new LogEvent(this, LOGID, LogEvent.LT_ERROR, msg)); Logger.logTextResource(new LogAlert(this, LogAlert.REPEATABLE, LogAlert.AT_ERROR, "DiskManager.alert.movefileexists"), new String[] { old_file.getName() }); Debug.out(msg); return false; } FileUtil.mkdirs(new_file.getParentFile()); } } for (int i=0; i < files.length; i++){ File new_file = new_files[i]; try{ files[i].moveFile( new_file, link_only[i] ); if ( change_to_read_only ){ files[i].setAccessMode(DiskManagerFileInfo.READ); } }catch( CacheFileManagerException e ){ String msg = "Failed to move " + old_files[i].toString() + " to destination dir"; Logger.log(new LogEvent(this, LOGID, LogEvent.LT_ERROR, msg)); Logger.logTextResource(new LogAlert(this, LogAlert.REPEATABLE, LogAlert.AT_ERROR, "DiskManager.alert.movefilefails"), new String[] { old_files[i].toString(), Debug.getNestedExceptionMessage(e) }); // try some recovery by moving any moved files back... for (int j=0;j 0 && COConfigurationManager.getBooleanParameter("Move Deleted Data To Recycle Bin" ) && (! force_no_recycle ) && mgr.hasCapability(PlatformManagerCapabilities.RecoverableFileDelete) ) { try { String dir = torrent_save_dir + File.separatorChar + torrent_save_file + File.separatorChar; // only delete the dir if there's only this torrent's files in it! if ( countFiles( new File(dir)) == countDataFiles( torrent, torrent_save_dir, torrent_save_file )){ mgr.performRecoverableFileDelete( dir ); }else{ deleteDataFileContents( torrent, torrent_save_dir, torrent_save_file, force_no_recycle ); } } catch(PlatformManagerException ex) { deleteDataFileContents( torrent, torrent_save_dir, torrent_save_file, force_no_recycle ); } } else{ deleteDataFileContents(torrent, torrent_save_dir, torrent_save_file, force_no_recycle); } } }catch( Throwable e ){ Debug.printStackTrace( e ); } } private static int countFiles( File f ) { if ( f.isFile()){ return( 1 ); }else{ int res = 0; File[] files = f.listFiles(); if ( files != null ){ for (int i=0;i " + newStroageType); if ( newStroageType == old_type ) { modified[i] = true; continue; } try{ File target_file = res[i].getFile( true ); // if the file doesn't exist then this is the start-of-day, most likely // being called from the torrent-opener, so we don't need to do any // file fiddling (in fact, if we do, we end up leaving zero length // files for dnd files which then force a recheck when the download // starts for the first time) if ( target_file.exists()){ CacheFile cache_file = CacheFileManagerFactory.getSingleton().createFile( new CacheFileOwner() { public String getCacheFileOwnerName() { return( download_manager.getInternalName()); } public TOTorrentFile getCacheFileTorrentFile() { return( res[idx].getTorrentFile() ); } public File getCacheFileControlFileDir() { return( download_manager.getDownloadState().getStateFile( )); } public int getCacheMode() { return( CacheFileOwner.CACHE_MODE_NORMAL ); } }, target_file, newStroageType==FileSkeleton.ST_LINEAR?CacheFile.CT_LINEAR:CacheFile.CT_COMPACT ); cache_file.close(); toSkip[i] = newStroageType == FileSkeleton.ST_COMPACT && !res[i].isSkipped(); if(toSkip[i]) toSkipCount++; } modified[i] = true; }catch( Throwable e ){ Debug.printStackTrace(e); Logger.log( new LogAlert(download_manager, LogAlert.REPEATABLE, LogAlert.AT_ERROR, "Failed to change storage type for '" + res[i].getFile(true) +"': " + Debug.getNestedExceptionMessage(e))); // download's not running - tag for recheck RDResumeHandler.recheckFile( download_manager, res[i] ); } types[i] = newStroageType== FileSkeleton.ST_LINEAR?"L":"C"; } /* * set storage type and skipped before we do piece clearing and file * clearing checks as those checks work better when skipped/stype is set * properly */ dmState.setListAttribute( DownloadManagerState.AT_FILE_STORE_TYPES, types); if(toSkipCount > 0) setSkipped(toSkip, true); for(int i=0;i 0) { res[i].downloaded = res[i].downloaded - cleared * res[i].getTorrentFile().getTorrent().getPieceLength(); if (res[i].downloaded < 0) res[i].downloaded = 0; } } storeFileDownloaded( download_manager, res, true ); DiskManagerUtil.doFileExistenceChecks(this, toChange, download_manager, newStroageType == FileSkeleton.ST_LINEAR); } finally { dmState.suppressStateSave(false); dmState.save(); } return modified; } }; for (int i=0;i btFileList = new ArrayList(); public PieceMapperImpl( TOTorrent _torrent ) { torrent = _torrent; int piece_length = (int)torrent.getPieceLength(); int piece_count = torrent.getNumberOfPieces(); long total_length = torrent.getSize(); last_piece_length = (int) (total_length - ((long) (piece_count - 1) * (long)piece_length)); } public void construct( LocaleUtilDecoder _locale_decoder, String _save_name ) throws UnsupportedEncodingException { //build something to hold the filenames/sizes TOTorrentFile[] torrent_files = torrent.getFiles(); if ( torrent.isSimpleTorrent()){ buildFileLookupTables( torrent_files[0], _save_name ); }else{ buildFileLookupTables( torrent_files, _locale_decoder ); } } // method for simple torrents private void buildFileLookupTables( TOTorrentFile torrent_file, String fileName ) { // not needed as fileName already normalised // fileName = FileUtil.convertOSSpecificChars( fileName, false ); btFileList.add(new PieceMapperImpl.fileInfo(torrent_file,"", fileName )); } private void buildFileLookupTables( TOTorrentFile[] torrent_files, LocaleUtilDecoder locale_decoder ) throws UnsupportedEncodingException { char separator = File.separatorChar; //for each file for (int i = 0; i < torrent_files.length; i++) { buildFileLookupTable(torrent_files[i], locale_decoder, separator); } } /** * Builds the path stored in fileDictionay, saving it in btFileList * @param fileDictionay * @param btFileList * @param localeUtil * @param separator * @return the length of the file as stored in fileDictionay */ // refactored out of initialize() - Moti // code further refactored for readibility private void buildFileLookupTable( TOTorrentFile torrent_file, LocaleUtilDecoder locale_decoder, final char separator) throws UnsupportedEncodingException { //build the path byte[][] path_components = torrent_file.getPathComponents(); /* replaced the following two calls: StringBuffer pathBuffer = new StringBuffer(256); pathBuffer.setLength(0); */ StringBuffer pathBuffer = new StringBuffer(0); int lastIndex = path_components.length - 1; for (int j = 0; j < lastIndex; j++) { //attach every element String comp = locale_decoder.decodeString( path_components[j]); comp = FileUtil.convertOSSpecificChars( comp, true); pathBuffer.append(comp); pathBuffer.append(separator); } //no, then we must be a part of the path //add the file entry to the file holder list String last_comp = locale_decoder.decodeString(path_components[lastIndex]); last_comp = FileUtil.convertOSSpecificChars( last_comp, false ); btFileList.add( new fileInfo( torrent_file, pathBuffer.toString(), last_comp )); } public DMPieceMap getPieceMap() { if ( btFileList.size() == 1 ){ // optimise for the single file case return( new DMPieceMapSimple( torrent, ((fileInfo)btFileList.get(0)).getFileInfo())); }else{ int piece_length = (int)torrent.getPieceLength(); int piece_count = torrent.getNumberOfPieces(); long total_length = torrent.getSize(); DMPieceList[] pieceMap = new DMPieceList[piece_count]; //for every piece, except the last one //add files to the piece list until we have built enough space to hold the piece //see how much space is available in the file //if the space available isnt 0 //add the file to the piece->file mapping list //if there is enough space available, stop //fix for 1 piece torrents int modified_piece_length = piece_length; if (total_length < modified_piece_length) { modified_piece_length = (int)total_length; } long fileOffset = 0; int currentFile = 0; for (int i = 0;(1 == piece_count && i < piece_count) || i < piece_count - 1; i++) { ArrayList pieceToFileList = new ArrayList(); int usedSpace = 0; while (modified_piece_length > usedSpace) { fileInfo tempFile = (fileInfo)btFileList.get(currentFile); long length = tempFile.getLength(); //get the available space long availableSpace = length - fileOffset; PieceMapEntryImpl tempPieceEntry = null; //how much space do we need to use? if (availableSpace <= (modified_piece_length - usedSpace)) { //use the rest of the file's space tempPieceEntry = new PieceMapEntryImpl(tempFile.getFileInfo(), fileOffset, (int)availableSpace //safe to convert here ); //update the used space usedSpace += availableSpace; //update the file offset fileOffset = 0; //move the the next file currentFile++; } else //we don't need to use the whole file { tempPieceEntry = new PieceMapEntryImpl(tempFile.getFileInfo(), fileOffset, modified_piece_length - usedSpace); //update the file offset fileOffset += modified_piece_length - usedSpace; //udate the used space usedSpace += modified_piece_length - usedSpace; } //add the temp pieceEntry to the piece list pieceToFileList.add(tempPieceEntry); } //add the list to the map pieceMap[i] = PieceListImpl.convert(pieceToFileList); } //take care of final piece if there was more than 1 piece in the torrent if (piece_count > 1) { pieceMap[piece_count - 1] = PieceListImpl.convert( buildLastPieceToFileList( btFileList, currentFile, fileOffset )); } return( new DMPieceMapImpl( pieceMap )); } } private List buildLastPieceToFileList( List file_list, int current_file, long file_offset ) { ArrayList piece_to_file_list = new ArrayList(); for ( int i=current_file;i 1000 ){ log_time = now; if ( Logger.isEnabled()){ Logger.log(new LogEvent(disk_manager, LOGID, "Waiting for reads to complete - " + (read_wait-i) + " remaining" )); } } } async_read_sem.reserve(); } } public DiskManagerReadRequest createReadRequest( int pieceNumber, int offset, int length ) { return( new DiskManagerReadRequestImpl( pieceNumber, offset, length )); } public boolean hasOutstandingReadRequestForPiece( int piece_number ) { try{ this_mon.enter(); Iterator it = read_requests.iterator(); while( it.hasNext()){ DiskManagerReadRequest request = (DiskManagerReadRequest)((Object[])it.next())[0]; if ( request.getPieceNumber() == piece_number ){ return( true ); } } return( false ); }finally{ this_mon.exit(); } } public long[] getStats() { return( new long[]{ total_read_ops, total_read_bytes }); } // returns null if the read can't be performed public DirectByteBuffer readBlock( int pieceNumber, int offset, int length ) { DiskManagerReadRequest request = createReadRequest( pieceNumber, offset, length ); final AESemaphore sem = new AESemaphore( "DMReader:readBlock" ); final DirectByteBuffer[] result = {null}; readBlock( request, new DiskManagerReadRequestListener() { public void readCompleted( DiskManagerReadRequest request, DirectByteBuffer data ) { result[0] = data; sem.release(); } public void readFailed( DiskManagerReadRequest request, Throwable cause ) { sem.release(); } public int getPriority() { return( -1 ); } public void requestExecuted(long bytes) { } }); sem.reserve(); return( result[0] ); } public void readBlock( final DiskManagerReadRequest request, final DiskManagerReadRequestListener _listener ) { request.requestStarts(); final DiskManagerReadRequestListener listener = new DiskManagerReadRequestListener() { public void readCompleted( DiskManagerReadRequest request, DirectByteBuffer data ) { request.requestEnds( true ); _listener.readCompleted( request, data ); } public void readFailed( DiskManagerReadRequest request, Throwable cause ) { request.requestEnds( false ); _listener.readFailed( request, cause ); } public int getPriority() { return( _listener.getPriority()); } public void requestExecuted(long bytes) { _listener.requestExecuted( bytes ); } }; DirectByteBuffer buffer = null; try{ int length = request.getLength(); buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_DM_READ,length ); if ( buffer == null ) { // Fix for bug #804874 Debug.out("DiskManager::readBlock:: ByteBufferPool returned null buffer"); listener.readFailed( request, new Exception( "Out of memory" )); return; } int pieceNumber = request.getPieceNumber(); int offset = request.getOffset(); DMPieceList pieceList = disk_manager.getPieceList(pieceNumber); // temporary fix for bug 784306 if ( pieceList.size() == 0 ){ Debug.out("no pieceList entries for " + pieceNumber); listener.readCompleted( request, buffer ); return; } long previousFilesLength = 0; int currentFile = 0; long fileOffset = pieceList.get(0).getOffset(); while (currentFile < pieceList.size() && pieceList.getCumulativeLengthToPiece(currentFile) < offset) { previousFilesLength = pieceList.getCumulativeLengthToPiece(currentFile); currentFile++; fileOffset = 0; } // update the offset (we're in the middle of a file) fileOffset += offset - previousFilesLength; List chunks = new ArrayList(); int buffer_position = 0; while ( buffer_position < length && currentFile < pieceList.size()) { DMPieceMapEntry map_entry = pieceList.get( currentFile ); int length_available = map_entry.getLength() - (int)( fileOffset - map_entry.getOffset()); //explicitly limit the read size to the proper length, rather than relying on the underlying file being correctly-sized //see long DMWriterAndCheckerImpl::checkPiece note int entry_read_limit = buffer_position + length_available; // now bring down to the required read length if this is shorter than this // chunk of data entry_read_limit = Math.min( length, entry_read_limit ); // this chunk denotes a read up to buffer offset "entry_read_limit" chunks.add( new Object[]{ map_entry.getFile().getCacheFile(), new Long(fileOffset), new Integer( entry_read_limit )}); buffer_position = entry_read_limit; currentFile++; fileOffset = 0; } if ( chunks.size() == 0 ){ Debug.out("no chunk reads for " + pieceNumber); listener.readCompleted( request, buffer ); return; } // this is where we go async and need to start counting requests for the sake // of shutting down tidily // have to wrap the request as we can validly have >1 for same piece/offset/length and // the request type itself overrides object equiv based on this... final Object[] request_wrapper = { request }; DiskManagerReadRequestListener l = new DiskManagerReadRequestListener() { public void readCompleted( DiskManagerReadRequest request, DirectByteBuffer data ) { complete(); listener.readCompleted( request, data ); } public void readFailed( DiskManagerReadRequest request, Throwable cause ) { complete(); listener.readFailed( request, cause ); } public int getPriority() { return( _listener.getPriority()); } public void requestExecuted(long bytes) { _listener.requestExecuted( bytes ); } protected void complete() { try{ this_mon.enter(); async_reads--; if ( !read_requests.remove( request_wrapper )){ Debug.out( "request not found" ); } if ( stopped ){ async_read_sem.release(); } }finally{ this_mon.exit(); } } }; try{ this_mon.enter(); if ( stopped ){ buffer.returnToPool(); listener.readFailed( request, new Exception( "Disk reader has been stopped" )); return; } async_reads++; read_requests.add( request_wrapper ); }finally{ this_mon.exit(); } new requestDispatcher( request, l, buffer, chunks ); }catch( Throwable e ){ if ( buffer != null ){ buffer.returnToPool(); } disk_manager.setFailed( "Disk read error - " + Debug.getNestedExceptionMessage(e)); Debug.printStackTrace( e ); listener.readFailed( request, e ); } } protected class requestDispatcher implements DiskAccessRequestListener { private DiskManagerReadRequest dm_request; private DiskManagerReadRequestListener listener; private DirectByteBuffer buffer; private List chunks; private int buffer_length; private int chunk_index; private int chunk_limit; protected requestDispatcher( DiskManagerReadRequest _request, DiskManagerReadRequestListener _listener, DirectByteBuffer _buffer, List _chunks ) { dm_request = _request; listener = _listener; buffer = _buffer; chunks = _chunks; /* String str = "Read: " + dm_request.getPieceNumber()+"/"+dm_request.getOffset()+"/"+dm_request.getLength()+":"; for (int i=0;i 32 ){ // for large numbers of chunks drop the recursion approach and // do it linearly (but on the async thread) for (int i=1;i 0 ){ total_read_bytes += bytes; total_read_ops ++; } listener.requestExecuted( bytes ); } }); sem.reserve(); if ( error[0] != null ){ throw( error[0] ); } } buffer.limit( DirectByteBuffer.SS_DR, buffer_length ); buffer.position( DirectByteBuffer.SS_DR, 0 ); listener.readCompleted( dm_request, buffer ); }else{ doRequest( this ); } } }catch( Throwable e ){ failed( e ); } } protected void doRequest( DiskAccessRequestListener l ) { Object[] stuff = (Object[])chunks.get( chunk_index++ ); if ( chunk_index > 0 ){ buffer.position( DirectByteBuffer.SS_DR, chunk_limit ); } chunk_limit = ((Integer)stuff[2]).intValue(); buffer.limit( DirectByteBuffer.SS_DR, chunk_limit ); short cache_policy = dm_request.getUseCache()?CacheFile.CP_READ_CACHE:CacheFile.CP_NONE; if ( dm_request.getFlush()){ cache_policy |= CacheFile.CP_FLUSH; } disk_access.queueReadRequest( (CacheFile)stuff[0], ((Long)stuff[1]).longValue(), buffer, cache_policy, l ); } public void requestComplete( DiskAccessRequest request ) { dispatch(); } public void requestCancelled( DiskAccessRequest request ) { // we never cancel so nothing to do here Debug.out( "shouldn't get here" ); } public void requestFailed( DiskAccessRequest request, Throwable cause ) { failed( cause ); } public int getPriority() { return( listener.getPriority()); } public void requestExecuted(long bytes) { if ( bytes > 0 ){ total_read_bytes += bytes; total_read_ops ++; } listener.requestExecuted( bytes ); } protected void failed( Throwable cause ) { buffer.returnToPool(); disk_manager.setFailed( "Disk read error - " + Debug.getNestedExceptionMessage(cause)); Debug.printStackTrace( cause ); listener.readFailed( dm_request, cause ); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerReadRequestImpl.java0000644000175000017500000001014510761466120031310 0ustar adrianadrian/* * File : DiskManagerRequestImpl.java * Created : 18-Oct-2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.disk.impl.access.impl; import org.gudy.azureus2.core3.disk.DiskManagerReadRequest; import org.gudy.azureus2.core3.util.SystemTime; /** * * This class represents a Bittorrent Request. * and a time stamp to know when it was created. * * Request may expire after some time, which is used to determine who is snubbed. * * @author Olivier * * */ public class DiskManagerReadRequestImpl extends DiskManagerRequestImpl implements DiskManagerReadRequest { //60 secs of expiration for any request. private static final int EXPIRATION_TIME = 1000 * 60; private final int pieceNumber; private final int offset; private final int length; private final int hashcode; private long timeCreated; private boolean flush; private boolean cancelled; private boolean use_cache = true; /** * Parameters correspond to bittorrent parameters * @param pieceNumber * @param offset * @param length */ public DiskManagerReadRequestImpl(final int _pieceNumber, final int _offset, final int _length) { pieceNumber = _pieceNumber; offset = _offset; length = _length; timeCreated = SystemTime.getCurrentTime(); hashcode = pieceNumber + offset + length; } protected String getName() { return( "Read: " + pieceNumber + ",off=" + offset +",len=" + length + ",fl=" + flush + ",uc=" + use_cache ); } /** * Method to determine if a Request has expired * @return true if the request is expired */ public boolean isExpired() { final long now =SystemTime.getCurrentTime(); if (now >=this.timeCreated) return (now -this.timeCreated) >EXPIRATION_TIME; //time error this.timeCreated =now; return false; } /** * Allow some more time to the request. * Typically used on peers that have just sent some data, we reset all * other requests to give them extra time. */ public void resetTime(final long now) { timeCreated =now; } //Getters public int getPieceNumber() { return this.pieceNumber; } public int getOffset() { return this.offset; } public int getLength() { return this.length; } public void setFlush( boolean _flush ) { flush = _flush; } public boolean getFlush() { return( flush ); } public void setUseCache( boolean cache ) { use_cache = cache; } public boolean getUseCache() { return( use_cache ); } public void cancel() { cancelled = true; } public boolean isCancelled() { return( cancelled ); } /** * We override the equals method * 2 requests are equals if * all their bt fields (piece number, offset, length) are equal */ public boolean equals(Object o) { if(! (o instanceof DiskManagerReadRequestImpl)) return false; DiskManagerReadRequestImpl otherRequest = (DiskManagerReadRequestImpl) o; if(otherRequest.pieceNumber != this.pieceNumber) return false; if(otherRequest.offset != this.offset) return false; if(otherRequest.length != this.length) return false; return true; } public int hashCode() { return hashcode; } public long getTimeCreated(final long now) { if (this.timeCreated >now) this.timeCreated =now; return this.timeCreated; } } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerRequestImpl.java0000644000175000017500000000502310457566044030523 0ustar adrianadrian/* * Created on 19 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk.impl.access.impl; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.disk.DiskManagerRequest; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.SystemTime; public abstract class DiskManagerRequestImpl implements DiskManagerRequest { private static final LogIDs LOGID = LogIDs.DISK; private static boolean DEBUG; private static int next_id; static{ COConfigurationManager.addAndFireParameterListener( "diskmanager.request.debug.enable", new ParameterListener() { public void parameterChanged( String name ) { DEBUG = COConfigurationManager.getBooleanParameter( name, false ); } }); } private long start_time; private String name; protected abstract String getName(); public void requestStarts() { if ( DEBUG ){ try{ int id; synchronized( DiskManagerRequestImpl.class ){ id = next_id++; } name = getName() + " [" + id + "]"; start_time = SystemTime.getCurrentTime(); Logger.log(new LogEvent( LOGID, "DMRequest start: " + name )); }catch( Throwable e ){ } } } public void requestEnds( boolean ok ) { if ( DEBUG ){ try{ Logger.log(new LogEvent( LOGID, "DMRequest end: " + name + ",ok=" + ok + ", time=" + ( SystemTime.getCurrentTime() - start_time ))); }catch( Throwable e ){ } } } } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/access/impl/DMWriterImpl.java0000644000175000017500000004236010745504120026452 0ustar adrianadrian/* * Created on 31-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk.impl.access.impl; import java.util.*; import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.disk.impl.DiskManagerFileInfoImpl; import org.gudy.azureus2.core3.disk.impl.DiskManagerHelper; import org.gudy.azureus2.core3.disk.impl.access.*; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceList; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceMapEntry; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.diskmanager.access.DiskAccessController; import com.aelitis.azureus.core.diskmanager.access.DiskAccessRequest; import com.aelitis.azureus.core.diskmanager.access.DiskAccessRequestListener; import com.aelitis.azureus.core.diskmanager.cache.*; /** * @author parg * */ public class DMWriterImpl implements DMWriter { private static final LogIDs LOGID = LogIDs.DISK; private static final int MIN_ZERO_BLOCK = 1*1024*1024; // must be mult of 1024 (see init below) private DiskManagerHelper disk_manager; private DiskAccessController disk_access; private int async_writes; private Set write_requests = new HashSet(); private AESemaphore async_write_sem = new AESemaphore("DMWriter::asyncWrite"); private boolean started; private volatile boolean stopped; private int pieceLength; private long totalLength; private boolean complete_recheck_in_progress; private AEMonitor this_mon = new AEMonitor( "DMWriter" ); public DMWriterImpl( DiskManagerHelper _disk_manager ) { disk_manager = _disk_manager; disk_access = disk_manager.getDiskAccessController(); pieceLength = disk_manager.getPieceLength(); totalLength = disk_manager.getTotalLength(); } public void start() { try{ this_mon.enter(); if ( started ){ throw( new RuntimeException( "DMWWriter: start while started")); } if ( stopped ){ throw( new RuntimeException( "DMWWriter: start after stopped")); } started = true; }finally{ this_mon.exit(); } } public void stop() { int write_wait; try{ this_mon.enter(); if ( stopped || !started ){ return; } stopped = true; write_wait = async_writes; }finally{ this_mon.exit(); } // wait for writes long log_time = SystemTime.getCurrentTime(); for (int i=0;i 1000 ){ log_time = now; if ( Logger.isEnabled()){ Logger.log(new LogEvent(disk_manager, LOGID, "Waiting for writes to complete - " + (write_wait-i) + " remaining" )); } } } async_write_sem.reserve(); } } public boolean isChecking() { return( complete_recheck_in_progress ); } public boolean zeroFile( DiskManagerFileInfoImpl file, long length ) throws DiskManagerException { CacheFile cache_file = file.getCacheFile(); try{ if( length == 0 ){ //create a zero-length file if it is listed in the torrent cache_file.setLength( 0 ); }else{ int buffer_size = pieceLength < MIN_ZERO_BLOCK?MIN_ZERO_BLOCK:pieceLength; buffer_size = ((buffer_size+1023)/1024)*1024; DirectByteBuffer buffer = DirectByteBufferPool.getBuffer(DirectByteBuffer.AL_DM_ZERO,buffer_size); long remainder = length; long written = 0; try{ final byte[] blanks = new byte[1024]; for (int i = 0; i < buffer_size/1024; i++ ){ buffer.put(DirectByteBuffer.SS_DW, blanks ); } buffer.position(DirectByteBuffer.SS_DW, 0); while ( remainder > 0 && !stopped ){ int write_size = buffer_size; if ( remainder < write_size ){ write_size = (int)remainder; buffer.limit(DirectByteBuffer.SS_DW, write_size); } final AESemaphore sem = new AESemaphore( "DMW&C:zeroFile" ); final Throwable[] op_failed = {null}; disk_access.queueWriteRequest( cache_file, written, buffer, false, new DiskAccessRequestListener() { public void requestComplete( DiskAccessRequest request ) { sem.release(); } public void requestCancelled( DiskAccessRequest request ) { op_failed[0] = new Throwable( "Request cancelled" ); sem.release(); } public void requestFailed( DiskAccessRequest request, Throwable cause ) { op_failed[0] = cause; sem.release(); } public int getPriority() { return( -1 ); } public void requestExecuted(long bytes) { } }); sem.reserve(); if ( op_failed[0] != null ){ throw( op_failed[0] ); } buffer.position(DirectByteBuffer.SS_DW, 0); written += write_size; remainder -= write_size; disk_manager.setAllocated( disk_manager.getAllocated() + write_size ); disk_manager.setPercentDone((int) ((disk_manager.getAllocated() * 1000) / totalLength)); } }finally{ buffer.returnToPool(); } cache_file.flushCache(); } if ( stopped ){ return false; } }catch ( Throwable e){ Debug.printStackTrace( e ); throw new DiskManagerException(e); } return true; } public DiskManagerWriteRequest createWriteRequest( int pieceNumber, int offset, DirectByteBuffer buffer, Object user_data ) { return( new DiskManagerWriteRequestImpl( pieceNumber, offset, buffer, user_data )); } public boolean hasOutstandingWriteRequestForPiece( int piece_number ) { try{ this_mon.enter(); Iterator it = write_requests.iterator(); while( it.hasNext()){ DiskManagerWriteRequest request = (DiskManagerWriteRequest)it.next(); if ( request.getPieceNumber() == piece_number ){ return( true ); } } return( false ); }finally{ this_mon.exit(); } } public void writeBlock( final DiskManagerWriteRequest request, final DiskManagerWriteRequestListener _listener ) { request.requestStarts(); final DiskManagerWriteRequestListener listener = new DiskManagerWriteRequestListener() { public void writeCompleted( DiskManagerWriteRequest request ) { request.requestEnds( true ); _listener.writeCompleted( request ); } public void writeFailed( DiskManagerWriteRequest request, Throwable cause ) { request.requestEnds( false ); _listener.writeFailed( request, cause ); } }; try{ int pieceNumber = request.getPieceNumber(); DirectByteBuffer buffer = request.getBuffer(); int offset = request.getOffset(); //Do not allow to write in a piece marked as done. we can get here if final DiskManagerPiece dmPiece = disk_manager.getPieces()[pieceNumber]; if ( dmPiece.isDone()){ // Debug.out( "write: piece already done (" + request.getPieceNumber() + "/" + request.getOffset()); buffer.returnToPool(); listener.writeCompleted( request ); //XXX: no writing was done; is this neccesary for complete()? }else{ int buffer_position = buffer.position(DirectByteBuffer.SS_DW); int buffer_limit = buffer.limit(DirectByteBuffer.SS_DW); // final long write_length = buffer_limit - buffer_position; int previousFilesLength = 0; int currentFile = 0; DMPieceList pieceList = disk_manager.getPieceList(pieceNumber); DMPieceMapEntry current_piece = pieceList.get(currentFile); long fileOffset = current_piece.getOffset(); while ((previousFilesLength + current_piece.getLength()) < offset) { previousFilesLength += current_piece.getLength(); currentFile++; fileOffset = 0; current_piece = pieceList.get(currentFile); } List chunks = new ArrayList(); // Now current_piece points to the first file that contains data for this block while ( buffer_position < buffer_limit ){ current_piece = pieceList.get(currentFile); long file_limit = buffer_position + ((current_piece.getFile().getLength() - current_piece.getOffset()) - (offset - previousFilesLength)); if ( file_limit > buffer_limit ){ file_limit = buffer_limit; } // could be a zero-length file if ( file_limit > buffer_position ){ long file_pos = fileOffset + (offset - previousFilesLength); chunks.add( new Object[]{ current_piece.getFile(), new Long( file_pos ), new Integer((int)file_limit )}); buffer_position = (int)file_limit; } currentFile++; fileOffset = 0; previousFilesLength = offset; } DiskManagerWriteRequestListener l = new DiskManagerWriteRequestListener() { public void writeCompleted( DiskManagerWriteRequest request ) { complete(); listener.writeCompleted( request ); } public void writeFailed( DiskManagerWriteRequest request, Throwable cause ) { complete(); if ( dmPiece.isDone()){ // There's a small chance of us ending up writing the same block twice around // the time that a file completes and gets toggled to read-only which then // fails with a non-writeable-channel exception // Debug.out( "writeFailed: piece already done (" + request.getPieceNumber() + "/" + request.getOffset() + "/" + write_length ); if ( Logger.isEnabled()){ Logger.log(new LogEvent(disk_manager, LOGID, "Piece " + dmPiece.getPieceNumber() + " write failed but already marked as done" )); } listener.writeCompleted( request ); }else{ disk_manager.setFailed( "Disk write error - " + Debug.getNestedExceptionMessage(cause)); Debug.printStackTrace( cause ); listener.writeFailed( request, cause ); } } protected void complete() { try{ this_mon.enter(); async_writes--; if ( !write_requests.remove( request )){ Debug.out( "request not found" ); } if ( stopped ){ async_write_sem.release(); } }finally{ this_mon.exit(); } } }; try{ this_mon.enter(); if ( stopped ){ buffer.returnToPool(); listener.writeFailed( request, new Exception( "Disk writer has been stopped" )); return; }else{ async_writes++; write_requests.add( request ); } }finally{ this_mon.exit(); } new requestDispatcher( request, l, buffer, chunks ); } }catch( Throwable e ){ request.getBuffer().returnToPool(); disk_manager.setFailed( "Disk write error - " + Debug.getNestedExceptionMessage(e)); Debug.printStackTrace( e ); listener.writeFailed( request, e ); } } protected class requestDispatcher implements DiskAccessRequestListener { private DiskManagerWriteRequest request; private DiskManagerWriteRequestListener listener; private DirectByteBuffer buffer; private List chunks; private int chunk_index; protected requestDispatcher( DiskManagerWriteRequest _request, DiskManagerWriteRequestListener _listener, DirectByteBuffer _buffer, List _chunks ) { request = _request; listener = _listener; buffer = _buffer; chunks = _chunks; /* String str = "Write: " + request.getPieceNumber() + "/" + request.getOffset() + ":"; for (int i=0;i 32 ){ // for large numbers of chunks drop the recursion approach and // do it linearly (but on the async thread) for (int i=1;i 0 ){ System.out.println( "async check queue size=" + async_check_queue.size()); } }finally{ class_mon.exit(); } ((DMCheckerImpl)entry[0]).enqueueCheckRequest( (DiskManagerCheckRequest)entry[1], (DiskManagerCheckRequestListener)entry[2], flush_pieces ); } } }.start(); } } static{ ParameterListener param_listener = new ParameterListener() { public void parameterChanged( String str ) { flush_pieces = COConfigurationManager.getBooleanParameter( "diskmanager.perf.cache.flushpieces" ); checking_read_priority = COConfigurationManager.getBooleanParameter( "diskmanager.perf.checking.read.priority" ); } }; COConfigurationManager.addAndFireParameterListeners( new String[]{ "diskmanager.perf.cache.flushpieces", "diskmanager.perf.checking.read.priority" }, param_listener ); } protected DiskManagerHelper disk_manager; protected int async_checks; protected AESemaphore async_check_sem = new AESemaphore("DMChecker::asyncCheck"); protected int async_reads; protected AESemaphore async_read_sem = new AESemaphore("DMChecker::asyncRead"); private boolean started; protected volatile boolean stopped; private volatile boolean complete_recheck_in_progress; private volatile int complete_recheck_progress; private boolean checking_enabled = true; protected AEMonitor this_mon = new AEMonitor( "DMChecker" ); public DMCheckerImpl( DiskManagerHelper _disk_manager ) { disk_manager = _disk_manager; } public void start() { try{ this_mon.enter(); if ( started ){ throw( new RuntimeException( "DMChecker: start while started")); } if ( stopped ){ throw( new RuntimeException( "DMChecker: start after stopped")); } started = true; }finally{ this_mon.exit(); } } public void stop() { int check_wait; int read_wait; try{ this_mon.enter(); if ( stopped || !started ){ return; } // when we exit here we guarantee that all file usage operations have completed // i.e. writes and checks (checks being doubly async) stopped = true; read_wait = async_reads; check_wait = async_checks; }finally{ this_mon.exit(); } long log_time = SystemTime.getCurrentTime(); // wait for reads for (int i=0;i 1000 ){ log_time = now; if ( Logger.isEnabled()){ Logger.log(new LogEvent(disk_manager, LOGID, "Waiting for check-reads to complete - " + (read_wait-i) + " remaining" )); } } } async_read_sem.reserve(); } log_time = SystemTime.getCurrentTime(); // wait for checks for (int i=0;i 1000 ){ log_time = now; if ( Logger.isEnabled()){ Logger.log(new LogEvent(disk_manager, LOGID, "Waiting for checks to complete - " + (read_wait-i) + " remaining" )); } } } async_check_sem.reserve(); } } public int getCompleteRecheckStatus() { if (complete_recheck_in_progress ){ return( complete_recheck_progress ); }else{ return( -1 ); } } public void setCheckingEnabled( boolean enabled ) { checking_enabled = enabled; } public DiskManagerCheckRequest createCheckRequest( int pieceNumber, Object user_data ) { return( new DiskManagerCheckRequestImpl( pieceNumber, user_data )); } public void enqueueCompleteRecheckRequest( final DiskManagerCheckRequest request, final DiskManagerCheckRequestListener listener ) { if ( !checking_enabled ){ listener.checkCompleted( request, true ); return; } complete_recheck_progress = 0; complete_recheck_in_progress = true; new AEThread2("DMChecker::completeRecheck", true ) { public void run() { DiskManagerRecheckInstance recheck_inst = disk_manager.getRecheckScheduler().register( disk_manager, true ); try{ final AESemaphore sem = new AESemaphore( "DMChecker::completeRecheck" ); int checks_submitted = 0; final AESemaphore run_sem = new AESemaphore( "DMChecker::completeRecheck:runsem", 2 ); int nbPieces = disk_manager.getNbPieces(); for ( int i=0; i < nbPieces; i++ ){ complete_recheck_progress = 1000*i / nbPieces; DiskManagerPiece dm_piece = disk_manager.getPiece(i); // only recheck the piece if it happens to be done (a complete dnd file that's // been set back to dnd for example) or the piece is part of a non-dnd file if ( dm_piece.isDone() || !dm_piece.isSkipped()){ run_sem.reserve(); while( !stopped ){ if ( recheck_inst.getPermission()){ break; } } if ( stopped ){ break; } enqueueCheckRequest( createCheckRequest( i, request.getUserData()), new DiskManagerCheckRequestListener() { public void checkCompleted( DiskManagerCheckRequest request, boolean passed ) { try{ listener.checkCompleted( request, passed ); }catch( Throwable e ){ Debug.printStackTrace(e); }finally{ complete(); } } public void checkCancelled( DiskManagerCheckRequest request ) { try{ listener.checkCancelled( request ); }catch( Throwable e ){ Debug.printStackTrace(e); }finally{ complete(); } } public void checkFailed( DiskManagerCheckRequest request, Throwable cause ) { try{ listener.checkFailed( request, cause ); }catch( Throwable e ){ Debug.printStackTrace(e); }finally{ complete(); } } protected void complete() { run_sem.release(); sem.release(); } }, false ); checks_submitted++; } } // wait for all to complete for (int i=0;i 0; for (int i = 0; i < pieceList.size(); i++) { DMPieceMapEntry piece_entry = pieceList.get(i); DiskManagerFileInfoImpl file_info = piece_entry.getFile(); CacheFile cache_file = file_info.getCacheFile(); if ( cache_file.compareLength( piece_entry.getOffset()) < 0 ){ listener.checkCompleted( request, false ); return; } if ( all_compact && ( cache_file.getStorageType() != CacheFile.CT_COMPACT || file_info.getNbPieces() <= 2 )){ all_compact = false; } } if ( all_compact ){ // System.out.println( "Piece " + pieceNumber + " is all compact, failing hash check" ); listener.checkCompleted( request, false ); return; } }catch( Throwable e ){ // we can fail here if the disk manager has been stopped as the cache file length access may be being // performed on a "closed" (i.e. un-owned) file listener.checkCancelled( request ); return; } int this_piece_length = disk_manager.getPieceLength( pieceNumber ); DiskManagerReadRequest read_request = disk_manager.createReadRequest( pieceNumber, 0, this_piece_length ); try{ this_mon.enter(); if ( stopped ){ listener.checkCancelled( request ); return; } async_reads++; }finally{ this_mon.exit(); } read_request.setFlush( read_flush ); read_request.setUseCache( !request.isAdHoc()); disk_manager.enqueueReadRequest( read_request, new DiskManagerReadRequestListener() { public void readCompleted( DiskManagerReadRequest read_request, DirectByteBuffer buffer ) { complete(); try{ this_mon.enter(); if ( stopped ){ buffer.returnToPool(); listener.checkCancelled( request ); return; } async_checks++; }finally{ this_mon.exit(); } try{ final DirectByteBuffer f_buffer = buffer; ConcurrentHasher.getSingleton().addRequest( buffer.getBuffer(DirectByteBuffer.SS_DW), new ConcurrentHasherRequestListener() { public void complete( ConcurrentHasherRequest hash_request ) { int async_result = 3; // cancelled try{ byte[] testHash = hash_request.getResult(); if ( testHash != null ){ async_result = 1; // success for (int i = 0; i < testHash.length; i++){ if ( testHash[i] != required_hash[i]){ async_result = 2; // failed; break; } } } }finally{ try{ if ( async_result == 1 ){ try{ for (int i = 0; i < pieceList.size(); i++) { DMPieceMapEntry piece_entry = pieceList.get(i); DiskManagerFileInfoImpl file_info = piece_entry.getFile(); CacheFile cache_file = file_info.getCacheFile(); cache_file.setPieceComplete( pieceNumber, f_buffer ); } }catch( Throwable e ){ f_buffer.returnToPool(); Debug.out( e ); listener.checkFailed( request, e ); return; } } f_buffer.returnToPool(); if ( async_result == 1 ){ listener.checkCompleted( request, true ); }else if ( async_result == 2 ){ listener.checkCompleted( request, false ); }else{ listener.checkCancelled( request ); } }finally{ try{ this_mon.enter(); async_checks--; if ( stopped ){ async_check_sem.release(); } }finally{ this_mon.exit(); } } } } }, request.isLowPriority()); }catch( Throwable e ){ Debug.printStackTrace(e); buffer.returnToPool(); listener.checkFailed( request, e ); } } public void readFailed( DiskManagerReadRequest read_request, Throwable cause ) { complete(); listener.checkFailed( request, cause ); } public int getPriority() { return( checking_read_priority?0:-1 ); } public void requestExecuted(long bytes) { } protected void complete() { try{ this_mon.enter(); async_reads--; if ( stopped ){ async_read_sem.release(); } }finally{ this_mon.exit(); } } }); }catch( Throwable e ){ disk_manager.setFailed( "Piece check error - " + Debug.getNestedExceptionMessage(e)); Debug.printStackTrace( e ); listener.checkFailed( request, e ); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/access/DMReader.java0000644000175000017500000000340311165562420024614 0ustar adrianadrian/* * Created on 31-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk.impl.access; import org.gudy.azureus2.core3.disk.DiskManagerReadRequest; import org.gudy.azureus2.core3.disk.DiskManagerReadRequestListener; import org.gudy.azureus2.core3.util.DirectByteBuffer; /** * @author parg * */ public interface DMReader { public void start(); public void stop(); public DirectByteBuffer readBlock( int pieceNumber, int offset, int length ); public DiskManagerReadRequest createReadRequest( int pieceNumber, int offset, int length ); public void readBlock( DiskManagerReadRequest request, DiskManagerReadRequestListener listener ); public boolean hasOutstandingReadRequestForPiece( int piece_number ); /** * 2 entries, first = read-ops, second = read-bytes * @return */ public long[] getStats(); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/access/DMWriter.java0000644000175000017500000000331610745504120024665 0ustar adrianadrian/* * Created on 31-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk.impl.access; import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.disk.impl.DiskManagerFileInfoImpl; import org.gudy.azureus2.core3.util.DirectByteBuffer; /** * @author parg * */ public interface DMWriter { public void start(); public void stop(); public boolean zeroFile( DiskManagerFileInfoImpl file, long length ) throws DiskManagerException; public DiskManagerWriteRequest createWriteRequest( int pieceNumber, int offset, DirectByteBuffer data, Object user_data ); public void writeBlock( DiskManagerWriteRequest request, DiskManagerWriteRequestListener listener ); public boolean hasOutstandingWriteRequestForPiece( int piece_number ); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/access/DMChecker.java0000644000175000017500000000323010745510774024764 0ustar adrianadrian/* * Created on 31-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk.impl.access; import org.gudy.azureus2.core3.disk.*; /** * @author parg * */ public interface DMChecker { public void start(); public void stop(); public DiskManagerCheckRequest createCheckRequest( int pieceNumber, Object user_data ); public void enqueueCompleteRecheckRequest( DiskManagerCheckRequest request, DiskManagerCheckRequestListener listener ); public void enqueueCheckRequest( DiskManagerCheckRequest request, DiskManagerCheckRequestListener listener ); public boolean hasOutstandingCheckRequestForPiece( int piece_number ); public int getCompleteRecheckStatus(); public void setCheckingEnabled( boolean enabled ); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoSetImpl.java0000644000175000017500000001126511017342722027031 0ustar adrianadrian/** * Copyright (C) 2008 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk.impl; import java.util.Arrays; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.disk.DiskManagerFileInfoSet; import org.gudy.azureus2.core3.disk.impl.DiskManagerImpl.FileSkeleton; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.diskmanager.cache.CacheFile; /** * @author Aaron Grunthal * @create 10.05.2008 */ public class DiskManagerFileInfoSetImpl implements DiskManagerFileInfoSet { final DiskManagerFileInfoImpl[] files; final DiskManagerHelper diskManager; public DiskManagerFileInfoSetImpl(DiskManagerFileInfoImpl[] files, DiskManagerHelper dm) { this.files = files; this.diskManager = dm; } public DiskManagerFileInfo[] getFiles() { return files; } public int nbFiles() { return files.length; } public void setPriority(boolean[] toChange, boolean setPriority) { if(toChange.length != files.length) throw new IllegalArgumentException("array length mismatches the number of files"); DownloadManagerState dmState = diskManager.getDownloadState(); try { dmState.suppressStateSave(true); for(int i=0;i compact conversion"); return modified; } try { dm_state.suppressStateSave(true); for (int i = 0; i < files.length; i++) { if(!toChange[i]) continue; int old_type = types[i].equals("L") ? DiskManagerFileInfo.ST_LINEAR : DiskManagerFileInfo.ST_COMPACT; if (newStroageType == old_type) { modified[i] = true; continue; } DiskManagerFileInfoImpl file = files[i]; try { file.getCacheFile().setStorageType(newStroageType == DiskManagerFileInfo.ST_LINEAR ? CacheFile.CT_LINEAR : CacheFile.CT_COMPACT); modified[i] = true; } catch (Throwable e) { Debug.printStackTrace(e); diskManager.setFailed(file, "Failed to change storage type for '" + file.getFile(true) + "': " + Debug.getNestedExceptionMessage(e)); break; } finally { types[i] = file.getCacheFile().getStorageType() == CacheFile.CT_LINEAR ? "L" : "C"; } } dm_state.setListAttribute(DownloadManagerState.AT_FILE_STORE_TYPES, types); DiskManagerUtil.doFileExistenceChecks(this, toChange, dm_state.getDownloadManager(), true); } finally { dm_state.suppressStateSave(false); dm_state.save(); } return modified; } } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/DiskManagerRecheckScheduler.java0000644000175000017500000001121011012726666027241 0ustar adrianadrian/* * Created on 19-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk.impl; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.RealTimeInfo; public class DiskManagerRecheckScheduler { private static boolean friendly_hashing; private static boolean smallest_first; static{ ParameterListener param_listener = new ParameterListener() { public void parameterChanged( String str ) { friendly_hashing = COConfigurationManager.getBooleanParameter( "diskmanager.friendly.hashchecking" ); smallest_first = COConfigurationManager.getBooleanParameter( "diskmanager.hashchecking.smallestfirst" ); } }; COConfigurationManager.addAndFireParameterListeners( new String[]{ "diskmanager.friendly.hashchecking", "diskmanager.hashchecking.smallestfirst" }, param_listener ); } private List instances = new ArrayList(); private AEMonitor instance_mon = new AEMonitor( "DiskManagerRecheckScheduler" ); public DiskManagerRecheckInstance register( DiskManagerHelper helper, boolean low_priority ) { try{ instance_mon.enter(); DiskManagerRecheckInstance res = new DiskManagerRecheckInstance( this, helper.getTorrent().getSize(), (int)helper.getTorrent().getPieceLength(), low_priority ); instances.add( res ); if ( smallest_first ){ Collections.sort( instances, new Comparator() { public int compare( Object o1, Object o2 ) { long comp = ((DiskManagerRecheckInstance)o1).getMetric() - ((DiskManagerRecheckInstance)o2).getMetric(); if ( comp < 0 ){ return( -1 ); }else if ( comp == 0 ){ return( 0 ); }else{ return( 1 ); } } }); } return( res ); }finally{ instance_mon.exit(); } } protected boolean getPermission( DiskManagerRecheckInstance instance ) { boolean result = false; int delay = 250; try{ instance_mon.enter(); if ( instances.get(0) == instance ){ boolean low_priority = instance.isLowPriority(); // defer low priority activities if we are running a real-time task if ( low_priority && RealTimeInfo.isRealTimeTaskActive()){ result = false; }else{ if ( friendly_hashing ){ delay = 0; // delay introduced elsewhere }else if ( !low_priority ){ delay = 1; // high priority recheck, just a smidge of a delay }else{ //delay a bit normally anyway, as we don't want to kill the user's system //during the post-completion check (10k of piece = 1ms of sleep) delay = instance.getPieceLength() /1024 /10; delay = Math.min( delay, 409 ); delay = Math.max( delay, 12 ); } result = true; } } }finally{ instance_mon.exit(); } if ( delay > 0 ){ try{ Thread.sleep( delay ); }catch( Throwable e ){ } } return( result ); } protected void unregister( DiskManagerRecheckInstance instance ) { try{ instance_mon.enter(); instances.remove( instance ); }finally{ instance_mon.exit(); } } } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoImpl.java0000644000175000017500000003026011225551342026352 0ustar adrianadrian/* * File : DiskManagerFileInfoImpl.java * Created : 18-Oct-2003 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.disk.impl; /* * Created on 3 juil. 2003 * */ import java.io.File; import java.io.IOException; import java.util.Iterator; import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.diskmanager.cache.CacheFile; import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerException; import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerFactory; import com.aelitis.azureus.core.diskmanager.cache.CacheFileOwner; import com.aelitis.azureus.core.util.CopyOnWriteList; /** * @author Olivier * */ public class DiskManagerFileInfoImpl implements DiskManagerFileInfo, CacheFileOwner { private File file; private int file_index; private CacheFile cache_file; private String extension; private long downloaded; private DiskManagerHelper diskManager; private TOTorrentFile torrent_file; boolean priority = false; boolean skipped = false; private CopyOnWriteList listeners; public DiskManagerFileInfoImpl( DiskManagerHelper _disk_manager, File _file, int _file_index, TOTorrentFile _torrent_file, boolean _linear_storage ) throws CacheFileManagerException { diskManager = _disk_manager; torrent_file = _torrent_file; file = _file; file_index = _file_index; cache_file = CacheFileManagerFactory.getSingleton().createFile( this, _file, _linear_storage?CacheFile.CT_LINEAR:CacheFile.CT_COMPACT ); // if compact storage then the file must be skipped if ( !_linear_storage ){ skipped = true; } } public String getCacheFileOwnerName() { return( diskManager.getInternalName()); } public TOTorrentFile getCacheFileTorrentFile() { return( torrent_file ); } public File getCacheFileControlFileDir() { return( diskManager.getDownloadState().getStateFile( )); } public int getCacheMode() { return( diskManager.getCacheMode()); } public void flushCache() throws Exception { cache_file.flushCache(); } public void moveFile( File newFile, boolean link_only ) throws CacheFileManagerException { if ( !link_only ){ cache_file.moveFile( newFile ); } file = newFile; } public void renameFile( String new_name, boolean link_only ) throws CacheFileManagerException { if ( !link_only ){ cache_file.renameFile( new_name ); } file = new File( file.getParentFile(), new_name ); } public CacheFile getCacheFile() { return( cache_file ); } public void setAccessMode( int mode ) throws CacheFileManagerException { int old_mode = cache_file.getAccessMode(); cache_file.setAccessMode( mode==DiskManagerFileInfo.READ?CacheFile.CF_READ:CacheFile.CF_WRITE ); if ( old_mode != mode ){ diskManager.accessModeChanged( this, old_mode, mode ); } } public int getAccessMode() { int mode = cache_file.getAccessMode(); return( mode == CacheFile.CF_READ?DiskManagerFileInfo.READ:DiskManagerFileInfo.WRITE); } /** * @return */ public long getDownloaded() { return downloaded; } /** * @return */ public String getExtension() { return extension; } /** * @return */ public File getFile( boolean follow_link ) { if ( follow_link ){ File res = getLink(); if ( res != null ){ return( res ); } } return( file ); } public TOTorrentFile getTorrentFile() { return( torrent_file ); } public boolean setLink( File link_destination ) { Debug.out( "setLink: download must be stopped" ); return( false ); } public boolean setLinkAtomic( File link_destination ) { Debug.out( "setLink: download must be stopped" ); return( false ); } public File getLink() { return( diskManager.getDownloadState().getFileLink( getFile( false ))); } public boolean setStorageType(int type) { DiskManagerFileInfoSet set = diskManager.getFileSet(); boolean[] toSet = new boolean[set.nbFiles()]; toSet[file_index] = true; return set.setStorageTypes(toSet, type)[file_index]; } public int getStorageType() { return( diskManager.getStorageType(file_index).equals( "L")?ST_LINEAR:ST_COMPACT ); } protected boolean isLinked() { return( getLink() != null ); } /** * @return */ public int getFirstPieceNumber() { return torrent_file.getFirstPieceNumber(); } public int getLastPieceNumber() { return torrent_file.getLastPieceNumber(); } /** * @return */ public long getLength() { return torrent_file.getLength(); } public int getIndex() { return( file_index ); } /** * @return */ public int getNbPieces() { return torrent_file.getNumberOfPieces(); } /** * @param l */ public void setDownloaded(long l) { downloaded = l; } /** * @param string */ public void setExtension(String string) { extension = StringInterner.intern(string); } /** * @return */ public boolean isPriority() { return priority; } /** * @param b */ public void setPriority(boolean b) { priority = b; diskManager.priorityChanged( this ); } /** * @return */ public boolean isSkipped() { return skipped; } /** * @param skipped */ public void setSkipped(boolean _skipped) { // currently a non-skipped file must be linear if ( !_skipped && getStorageType() == ST_COMPACT ){ if ( !setStorageType( ST_LINEAR )){ return; } } skipped = _skipped; diskManager.skippedFileSetChanged( this ); if(!_skipped) { boolean[] toCheck = new boolean[diskManager.getFileSet().nbFiles()]; toCheck[file_index] = true; DiskManagerUtil.doFileExistenceChecks(diskManager.getFileSet(), toCheck, diskManager.getDownloadState().getDownloadManager(), true); } } public DiskManager getDiskManager() { return diskManager; } public DownloadManager getDownloadManager() { DownloadManagerState state = diskManager.getDownloadState(); if ( state == null ){ return( null ); } return( state.getDownloadManager()); } public void dataWritten( long offset, long size ) { if ( listeners != null ){ Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((DiskManagerFileInfoListener)it.next()).dataWritten( offset, size ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } } public void dataChecked( long offset, long size ) { if ( listeners != null ){ Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((DiskManagerFileInfoListener)it.next()).dataChecked( offset, size ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } } public DirectByteBuffer read( long offset, int length ) throws IOException { DirectByteBuffer buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_DM_READ, length ); try{ cache_file.read( buffer, offset, CacheFile.CP_READ_CACHE ); }catch( Throwable e ){ buffer.returnToPool(); Debug.printStackTrace(e); throw( new IOException( e.getMessage())); } return( buffer ); } public void close() { // this doesn't need to do anything as overall closure is handled by the disk manager closing } public void addListener( final DiskManagerFileInfoListener listener ) { if ( listeners == null ){ listeners = new CopyOnWriteList(); } synchronized( listeners ){ if ( listeners.getList().contains( listener )){ return; } } listeners.add( listener ); new Runnable() { private long file_start; private long file_end; private long current_write_start = -1; private long current_write_end = -1; private long current_check_start = -1; private long current_check_end = -1; public void run() { TOTorrentFile[] tfs = torrent_file.getTorrent().getFiles(); long torrent_offset = 0; for (int i=0;i file_end ){ current_write_end = file_end; } if ( current_write_start < current_write_end ){ try{ listener.dataWritten( current_write_start-file_start, current_write_end-current_write_start ); }catch( Throwable e ){ Debug.printStackTrace(e); } } current_write_start = bit_start; current_write_end = bit_end; } // checked case if ( checked && current_check_start == -1 ){ current_check_start = bit_start; current_check_end = bit_end; }else if ( checked && current_check_end == bit_start ){ current_check_end = bit_end; }else{ if ( current_check_start < file_start ){ current_check_start = file_start; } if ( current_check_end > file_end ){ current_check_end = file_end; } if ( current_check_start < current_check_end ){ try{ listener.dataChecked( current_check_start-file_start, current_check_end-current_check_start ); }catch( Throwable e ){ Debug.printStackTrace(e); } } if ( checked ){ current_check_start = bit_start; current_check_end = bit_end; }else{ current_check_start = -1; current_check_end = -1; } } } }.run(); } public void removeListener( DiskManagerFileInfoListener listener ) { listeners.remove( listener ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/resume/0000755000175000017500000000000011310377634022370 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/disk/impl/resume/RDResumeHandler.java0000644000175000017500000007214411011505402026207 0ustar adrianadrian/* * Created on 31-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk.impl.resume; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.disk.DiskManagerCheckRequest; import org.gudy.azureus2.core3.disk.DiskManagerCheckRequestListener; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.disk.DiskManagerPiece; import org.gudy.azureus2.core3.disk.impl.DiskManagerFileInfoImpl; import org.gudy.azureus2.core3.disk.impl.DiskManagerImpl; import org.gudy.azureus2.core3.disk.impl.DiskManagerRecheckInstance; import org.gudy.azureus2.core3.disk.impl.access.DMChecker; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceList; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceMapEntry; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerException; /** * @author parg * */ public class RDResumeHandler { private static final LogIDs LOGID = LogIDs.DISK; private static final byte PIECE_NOT_DONE = 0; private static final byte PIECE_DONE = 1; private static final byte PIECE_RECHECK_REQUIRED = 2; private static final byte PIECE_STARTED = 3; private static boolean use_fast_resume; private static boolean use_fast_resume_recheck_all; static{ COConfigurationManager.addAndFireParameterListeners( new String[]{ "Use Resume", "On Resume Recheck All" }, new ParameterListener() { public void parameterChanged( String str ) { use_fast_resume = COConfigurationManager.getBooleanParameter("Use Resume"); use_fast_resume_recheck_all = COConfigurationManager.getBooleanParameter("On Resume Recheck All"); } }); } private DiskManagerImpl disk_manager; private DMChecker checker; private volatile boolean started; private volatile boolean stopped; private volatile boolean stopped_for_close; private volatile boolean check_in_progress; private volatile boolean check_resume_was_valid; private volatile boolean check_is_full_check; private volatile boolean check_interrupted; private volatile int check_position; public RDResumeHandler( DiskManagerImpl _disk_manager, DMChecker _writer_and_checker ) { disk_manager = _disk_manager; checker = _writer_and_checker; } public void start() { if ( started ){ Debug.out( "RDResumeHandler: reuse not supported" ); } started = true; } public void stop( boolean closing ) { stopped_for_close = stopped_for_close | closing; // can get in here > once during close if ( check_in_progress ){ check_interrupted = true; } stopped = true; } public void checkAllPieces( boolean newfiles ) { //long start = System.currentTimeMillis(); DiskManagerRecheckInstance recheck_inst = disk_manager.getRecheckScheduler().register( disk_manager, false ); final AESemaphore run_sem = new AESemaphore( "RDResumeHandler::checkAllPieces:runsem", 2 ); try{ boolean resume_data_complete = false; try{ check_in_progress = true; boolean resumeEnabled = use_fast_resume; //disable fast resume if a new file was created if ( newfiles ){ resumeEnabled = false; } final AESemaphore pending_checks_sem = new AESemaphore( "RD:PendingChecks" ); int pending_check_num = 0; DiskManagerPiece[] pieces = disk_manager.getPieces(); // calculate the current file sizes up front for performance reasons DiskManagerFileInfo[] files = disk_manager.getFiles(); Map file_sizes = new HashMap(); for (int i=0;i 0 ){ pending_checks_sem.reserve(); pending_check_num--; } if ( partialPieces != null ){ Iterator iter = partialPieces.entrySet().iterator(); while (iter.hasNext()) { Map.Entry key = (Map.Entry)iter.next(); int pieceNumber = Integer.parseInt((String)key.getKey()); DiskManagerPiece dm_piece = pieces[ pieceNumber ]; if ( !dm_piece.isDone()){ List blocks = (List)partialPieces.get(key.getKey()); Iterator iterBlock = blocks.iterator(); while (iterBlock.hasNext()) { dm_piece.setWritten(((Long)iterBlock.next()).intValue()); } } } } }else{ // resume not enabled, recheck everything for (int i = 0; i < pieces.length; i++){ check_position = i; disk_manager.setPercentDone(((i + 1) * 1000) / disk_manager.getNbPieces() ); boolean pieceCannotExist = false; // check if there is an underlying file for this piece, if not set it to not done DMPieceList list = disk_manager.getPieceList(i); for (int j=0;j 0 ){ pending_checks_sem.reserve(); pending_check_num--; } } }finally{ check_in_progress = false; } //dump the newly built resume data to the disk/torrent if ( !( stopped || resume_data_complete )){ try{ saveResumeData( true ); }catch( Exception e ){ Debug.out( "Failed to dump initial resume data to disk" ); Debug.printStackTrace( e ); } } }catch( Throwable e ){ // if something went wrong then log and continue. Debug.printStackTrace(e); }finally{ recheck_inst.unregister(); // System.out.println( "Check of '" + disk_manager.getDownloadManager().getDisplayName() + "' completed in " + (System.currentTimeMillis() - start)); } } public void saveResumeData( boolean interim_save ) // data is marked as "invalid" if this is true to enable checking on pieces on crash restart throws Exception { if ( check_in_progress && interim_save ){ // while we are rechecking it is important that an interim save doesn't come // along and overwite the persisted resume data. This is because should we crash // while rechecking we need the persisted state to be unchanged so that on // restart the rechecking occurs again // a non-interim save means that the user has decided to stop the download (or some // other such significant event) so we just persist the current state return; } // if file caching is enabled then this is an important time to ensure that the cache is // flushed as we are going to record details about the accuracy of written data. // First build the resume map from the data (as updates can still be goin on) // Then, flush the cache. This means that on a successful flush the built resume // data matches at least the valid state of the data // Then update the torrent DiskManagerFileInfo[] files = disk_manager.getFiles(); if ( !use_fast_resume ){ // flush cache even if resume disable as this is a good point to ensure that data // is persisted anyway for (int i=0;i= check_position ){ resume_pieces[i] = PIECE_RECHECK_REQUIRED; }else if ( piece.isDone()){ resume_pieces[i] = PIECE_DONE; }else if ( piece.getNbWritten() > 0 ){ resume_pieces[i] = PIECE_STARTED; }else{ resume_pieces[i] = PIECE_NOT_DONE; } } Map resume_data = new HashMap(); resume_data.put( "resume data", resume_pieces ); Map partialPieces = new HashMap(); for (int i = 0; i < pieces.length; i++) { DiskManagerPiece piece = pieces[i]; // save the partial pieces for any pieces that have not yet been completed // and are in-progress (i.e. have at least one block downloaded) boolean[] written = piece.getWritten(); if (( !piece.isDone()) && piece.getNbWritten() > 0 && written != null ){ boolean all_written = true; for (int j = 0; j < written.length; j++) { if ( !written[j] ){ all_written = false; break; } } if ( all_written ){ // just mark the entire piece for recheck as we've stopped the torrent at the // point where a check-piece was, or was about to be, scheduled resume_pieces[ i ] = PIECE_RECHECK_REQUIRED; }else{ List blocks = new ArrayList(); for (int j = 0; j < written.length; j++) { if (written[j]){ blocks.add(new Long(j)); } } partialPieces.put("" + i, blocks); } } } resume_data.put("blocks", partialPieces); long lValid; if ( check_interrupted ){ // set validity to what it was before the check started lValid = check_resume_was_valid?1:0; }else if ( interim_save ){ // set invalid so that not-done pieces get rechecked on startup lValid = 0; }else{ lValid = 1; } resume_data.put("valid", new Long(lValid)); for (int i=0;i lastPiece) break; if(currentFile.getFirstPieceNumber() <= firstPiece && firstPiece <= currentFile.getLastPieceNumber()) firstPieceShared |= !currentFile.isSkipped(); if(currentFile.getFirstPieceNumber() <= lastPiece && lastPiece <= currentFile.getLastPieceNumber()) lastPieceShared |= !currentFile.isSkipped(); } if(firstPieceShared) firstPiece++; if(lastPieceShared) lastPiece--; } if ( resume_pieces != null ){ for (int i=firstPiece;i<=lastPiece;i++){ if ( i >= resume_pieces.length ){ break; } if ( resume_pieces[i] == PIECE_DONE ){ pieces_cleared++; } resume_pieces[i] = recheck?PIECE_RECHECK_REQUIRED:PIECE_NOT_DONE; } } // clear any affected partial pieces Map partial_pieces = (Map)resume_data.get("blocks"); if ( partial_pieces != null ){ Iterator iter = partial_pieces.keySet().iterator(); while (iter.hasNext()) { int piece_number = Integer.parseInt((String)iter.next()); if ( piece_number >= firstPiece && piece_number <= lastPiece ){ iter.remove(); } } } // either way we're valid as // 1) clear -> pieces are set as not done // 2) recheck -> pieces are set as "recheck" and will be checked on restart resume_data.put( "valid", new Long(1)); saveResumeData( download_manager_state, resume_data ); return( pieces_cleared ); } /** * finds the first affected file via binary search, this is necessary as some methods might be * invoked for all files, which would result in O(n²) if we'd scan the whole file array every * time */ private static int findFirstFileWithPieceN(int firstPiece, DiskManagerFileInfo[] files) { int start = 0; int end = files.length-1; int pivot = 0; while (start <= end) { pivot = (start + end) >>> 1; int midVal = files[pivot].getLastPieceNumber(); if (midVal < firstPiece) start = pivot + 1; else if (midVal > firstPiece) end = pivot - 1; else { // some matching file, now slide leftwards to find the first one, shouldn't be that many while(pivot > 0 && files[pivot-1].getLastPieceNumber() == firstPiece) pivot--; break; } } return pivot; } public static boolean fileMustExist(DownloadManager download_manager, DiskManagerFileInfo file) { Map resumeData = getResumeData( download_manager ); byte[] resumePieces = resumeData != null ? (byte[])resumeData.get("resume data") : null; boolean sharesAnyNeededPieces = false; DiskManagerFileInfo[] files = download_manager.getDiskManagerFileInfo(); int firstPiece = file.getFirstPieceNumber(); int lastPiece = file.getLastPieceNumber(); int firstFile = findFirstFileWithPieceN(firstPiece, files); // we must sweep over the files, as any number of files could share the first/last piece of the file we're probing for (int i = firstFile; i < files.length && !sharesAnyNeededPieces; i++) { DiskManagerFileInfo currentFile = files[i]; if(currentFile.getLastPieceNumber() < firstPiece) continue; if (currentFile.getIndex() == file.getIndex() && resumePieces != null && file.getStorageType() != DiskManagerFileInfo.ST_COMPACT) for (int j = firstPiece; j <= lastPiece && !sharesAnyNeededPieces; j++) sharesAnyNeededPieces |= resumePieces[j] != PIECE_NOT_DONE; if (currentFile.getFirstPieceNumber() > lastPiece) break; if (currentFile.getFirstPieceNumber() <= firstPiece && firstPiece <= currentFile.getLastPieceNumber()) sharesAnyNeededPieces |= !currentFile.isSkipped(); if (currentFile.getFirstPieceNumber() <= lastPiece && lastPiece <= currentFile.getLastPieceNumber()) sharesAnyNeededPieces |= !currentFile.isSkipped(); } return sharesAnyNeededPieces; } public static int storageTypeChanged( DownloadManager download_manager, DiskManagerFileInfo file ) { return( clearResumeDataSupport( download_manager, file, false, true )); } public static void clearResumeData( DownloadManager download_manager, DiskManagerFileInfo file ) { clearResumeDataSupport( download_manager, file, false, false ); } public static void recheckFile( DownloadManager download_manager, DiskManagerFileInfo file ) { clearResumeDataSupport( download_manager, file, true, false ); } public static void setTorrentResumeDataNearlyComplete( DownloadManagerState download_manager_state ) { // backwards compatability, resume data key is the dir TOTorrent torrent = download_manager_state.getTorrent(); long piece_count = torrent.getNumberOfPieces(); byte[] resume_pieces = new byte[(int)piece_count]; Arrays.fill( resume_pieces, PIECE_DONE ); // randomly clear some pieces for (int i=0;i<3;i++){ int piece_num = (int)(Math.random()*piece_count); resume_pieces[piece_num]= PIECE_RECHECK_REQUIRED; } Map resumeMap = new HashMap(); resumeMap.put( "resume data", resume_pieces); Map partialPieces = new HashMap(); resumeMap.put("blocks", partialPieces); resumeMap.put("valid", new Long(0)); // recheck the not-done pieces saveResumeData(download_manager_state,resumeMap); } public static boolean isTorrentResumeDataComplete( DownloadManagerState dms ) { // backwards compatability, resume data key is the dir Map resume_data = getResumeData( dms ); return( isTorrentResumeDataComplete( dms, resume_data )); } protected static boolean isTorrentResumeDataComplete( DownloadManagerState download_manager_state, Map resume_data ) { try{ int piece_count = download_manager_state.getTorrent().getNumberOfPieces(); if ( resume_data != null ){ byte[] pieces = (byte[])resume_data.get("resume data"); Map blocks = (Map)resume_data.get("blocks"); boolean valid = ((Long)resume_data.get("valid")).intValue() == 1; // any partial pieced -> not complete if ( blocks == null || blocks.size() > 0 ){ return( false ); } if ( valid && pieces != null && pieces.length == piece_count ){ for (int i=0;i= dm.getNbPieces()) { if (Logger.isEnabled()) Logger.log(new LogEvent(dm, LOGID, LogEvent.LT_ERROR, "Hint invalid: " + originator + " pieceNumber=" + pieceNumber + " >= this.nbPieces=" + dm.getNbPieces())); return false; } int pLength = dm.getPieceLength(pieceNumber); if (offset < 0) { if (Logger.isEnabled()) Logger.log(new LogEvent(dm, LOGID, LogEvent.LT_ERROR, "Hint invalid: " + originator + " offset=" + offset + " < 0")); return false; } if (offset > pLength) { if (Logger.isEnabled()) Logger.log(new LogEvent(dm, LOGID, LogEvent.LT_ERROR, "Hint invalid: " + originator + " offset=" + offset + " > pLength=" + pLength)); return false; } if (offset + length > pLength) { if (Logger.isEnabled()) Logger.log(new LogEvent(dm, LOGID, LogEvent.LT_ERROR, "Hint invalid: " + originator + " offset=" + offset + " + length=" + length + " > pLength=" + pLength)); return false; } return true; } public static boolean checkBlockConsistencyForRead( DiskManager dm, String originator, int pieceNumber, int offset, int length) { if ( !checkBlockConsistencyForHint( dm, originator, pieceNumber, offset, length )){ return( false ); } if (length > max_read_block_size) { if (Logger.isEnabled()) Logger.log(new LogEvent(dm, LOGID, LogEvent.LT_ERROR, "Read invalid: " + originator + " length=" + length + " > " + max_read_block_size)); return false; } if(!dm.getPiece(pieceNumber).isDone()) { Logger.log(new LogEvent(dm, LOGID, LogEvent.LT_ERROR, "Read invalid: " + originator + " piece #" + pieceNumber + " not done")); return false; } return true; } public static void doFileExistenceChecks(DiskManagerFileInfoSet fileSet, boolean[] toCheck, DownloadManager dm, boolean allowAlloction) { DiskManagerFileInfo[] files = fileSet.getFiles(); int lastPieceScanned = -1; int windowStart = -1; int windowEnd = -1; String[] types = DiskManagerImpl.getStorageTypes(dm); // sweep over all files to see if adjacent files of changed files can be deleted or need allocation for(int i = 0; i< files.length;i++) { int firstPiece = files[i].getFirstPieceNumber(); int lastPiece = files[i].getLastPieceNumber(); if(toCheck[i]) { // found a file that changed, scan adjacent files if(lastPieceScanned < firstPiece) { // haven't checked the preceding files, slide backwards windowStart = firstPiece; while(i > 0 && files[i-1].getLastPieceNumber() >= windowStart) i--; } if(windowEnd < lastPiece) windowEnd = lastPiece; } if((windowStart <= firstPiece && firstPiece <= windowEnd) || (windowStart <= lastPiece && lastPiece <= windowEnd)) { // file falls in current scanning window, check it File currentFile = files[i].getFile(true); if(!RDResumeHandler.fileMustExist(dm, files[i])) { if(types[i].equals("C")) currentFile.delete(); } else if(allowAlloction && types[i].equals("L") && !currentFile.exists()) { /* * file must exist, does not exist and we just changed to linear * mode, assume that (re)allocation of adjacent files is necessary */ dm.setDataAlreadyAllocated(false); } lastPieceScanned = lastPiece; } } } } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerWriteRequest.java0000644000175000017500000000235110457566044025552 0ustar adrianadrian/* * Created on 05-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk; import org.gudy.azureus2.core3.util.DirectByteBuffer; public interface DiskManagerWriteRequest extends DiskManagerRequest { public int getPieceNumber(); public int getOffset(); public DirectByteBuffer getBuffer(); public Object getUserData(); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerFactory.java0000644000175000017500000000711611306337276024517 0ustar adrianadrian/* * File : DiskManagerFactory.java * Created : 18-Oct-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.disk; /** * @author parg * */ import org.gudy.azureus2.core3.disk.impl.DiskManagerImpl; import org.gudy.azureus2.core3.disk.impl.resume.RDResumeHandler; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.torrent.TOTorrent; import com.aelitis.azureus.core.util.CaseSensitiveFileMap; public class DiskManagerFactory { public static DiskManager create( TOTorrent torrent, DownloadManager manager) { DiskManagerImpl dm = new DiskManagerImpl( torrent, manager ); if ( dm.getState() != DiskManager.FAULTY ){ dm.start(); } return dm; } /* public static DiskManager createNoStart( TOTorrent torrent, DownloadManager manager) { return( new DiskManagerImpl( torrent, manager )); } */ /** * Method to preset resume data to indicate completely valid file. * Doesn't save the torrent * @param torrent */ public static void setResumeDataCompletelyValid( DownloadManagerState download_manager_state ) { RDResumeHandler.setTorrentResumeDataComplete( download_manager_state ); } /** * Sets resume data complete apart from a few random pieces. On torrent start these will be checked * This is used in the "open for seeding" mode to ensure that there's at least a chance that the * data they claim represents the data for the torrent is valid * @param torrent * @param torrent_save_dir * @param torrent_save_file */ public static void setTorrentResumeDataNearlyComplete( DownloadManagerState dms ) { RDResumeHandler.setTorrentResumeDataNearlyComplete( dms ); } public static boolean isTorrentResumeDataComplete( DownloadManagerState dms ) { return RDResumeHandler.isTorrentResumeDataComplete( dms ); } public static void deleteDataFiles( TOTorrent torrent, String torrent_save_dir, String torrent_save_file, boolean force_no_recycle ) { DiskManagerImpl.deleteDataFiles(torrent, torrent_save_dir, torrent_save_file, force_no_recycle ); } public static DiskManagerFileInfoSet getFileInfoSkeleton( DownloadManager download_manager, DiskManagerListener listener ) { return( DiskManagerImpl.getFileInfoSkeleton( download_manager, listener )); } public static void setFileLinks( DownloadManager download_manager, CaseSensitiveFileMap links ) { DiskManagerImpl.setFileLinks( download_manager, links ); } public static void clearResumeData( DownloadManager download_manager, DiskManagerFileInfo file ) { RDResumeHandler.clearResumeData( download_manager, file ); } public static void recheckFile( DownloadManager download_manager, DiskManagerFileInfo file ) { RDResumeHandler.recheckFile( download_manager, file ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerListener.java0000644000175000017500000000233410261621422024656 0ustar adrianadrian/* * File : DiskManagerListener.java * Created : 13-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.disk; /** * @author parg * */ public interface DiskManagerListener { public void stateChanged( int oldState, int newState ); public void filePriorityChanged( DiskManagerFileInfo file ); public void pieceDoneChanged( DiskManagerPiece piece ); public void fileAccessModeChanged( DiskManagerFileInfo file, int old_mode, int new_mode ); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerCheckRequest.java0000644000175000017500000000241510457566044025476 0ustar adrianadrian/* * Created on 12-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk; public interface DiskManagerCheckRequest extends DiskManagerRequest { public int getPieceNumber(); public Object getUserData(); public void setLowPriority( boolean low ); public boolean isLowPriority(); public void setAdHoc( boolean adhoc ); public boolean isAdHoc(); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerPiece.java0000644000175000017500000000705210600463216024122 0ustar adrianadrian/* * Created on 08-Oct-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk; /** * Represents a DiskManager Piece * * @author parg * @author MjrTom * 2005/Oct/08: priority handling * 2006/Jan/2: refactoring, mostly to base Piece interface */ public interface DiskManagerPiece { public DiskManager getManager(); public int getLength(); public int getPieceNumber(); public int getNbBlocks(); public int getBlockSize( int block_index ); public short getReadCount(); public void setReadCount(short c); public boolean calcNeeded(); public void clearNeeded(); /** @return true if any file the piece covers is neither Do Not Download nor Delete. * This is not a real-time indicator. Also, the results are not reliable for pieces that are Done. * Use calcNeeded() for guaranteed correct and up to date results * @see calcNeeded(), clearNeeded(), setNeeded(), setNeeded(boolean) */ public boolean isNeeded(); public void setNeeded(); public void setNeeded(boolean b); // a piece is Written if data has been written to storage for every block (without concern for if it's checked) public boolean isWritten(); public int getNbWritten(); public boolean[] getWritten(); /** * @param blockNumber int * @return true if the given blockNumber has already been written to disk */ public boolean isWritten(int blockNumber); public void setWritten(int blockNumber); // a piece is Checking if a hash check has been setup and the hash check hasn't finalized the result yet // this flag is asynch, so be careful, and it's also transitory (comapared to most of the others being kinda sticky) public void setChecking(); public boolean isChecking(); public boolean isNeedsCheck(); public boolean calcDone(); /** @return true when the hash check has passed and the DiskManager has asyncronously updated the Done status. * There is nothing further to be done regarding downloading for pieces that are Done. */ public boolean isDone(); public void setDone(boolean b); /** * @return true if a piece is Needed and not Done */ public boolean isInteresting(); /** This must not be used to qualify pieces in End Game Mode. * @return true if a piece is Needed but is not fully; Requested, Downloaded, Written, Checking, or Done. */ public boolean isDownloadable(); public void setDownloadable(); /** * returns true if all the files that the piece spans are skipped * @return */ public boolean isSkipped(); public void reDownloadBlock(int blockNumber); public void reset(); public String getString(); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerCheckRequestListener.java0000644000175000017500000000247410373051004027167 0ustar adrianadrian/* * Created on 08-Oct-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk; /** * @author parg * */ public interface DiskManagerCheckRequestListener { public void checkCompleted( DiskManagerCheckRequest request, boolean passed ); public void checkCancelled( DiskManagerCheckRequest request ); public void checkFailed( DiskManagerCheckRequest request, Throwable cause ); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerFileInfoSet.java0000644000175000017500000000243111011457630025240 0ustar adrianadrian/** * Copyright (C) 2008 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk; /** * @author Aaron Grunthal * @create 01.05.2008 */ public interface DiskManagerFileInfoSet { public boolean[] setStorageTypes(boolean[] toChange, int newStroageType); public void setPriority(boolean[] toChange, boolean setPriority); public void setSkipped(boolean[] toChange, boolean setSkipped); public DiskManagerFileInfo[] getFiles(); public int nbFiles(); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerException.java0000644000175000017500000000255211214105464025033 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk; /** * @author Aaron Grunthal * @create 22.01.2008 */ public class DiskManagerException extends Exception { public DiskManagerException(String message) { super(message); } public DiskManagerException(Throwable cause) { // pass "" to mark this as a delegating exception, else we get class name // in message which sucks super("",cause); } public DiskManagerException(String message, Throwable cause) { super(message, cause); } } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerFileInfo.java0000644000175000017500000000544011011457630024567 0ustar adrianadrian/* * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Created on 3 juil. 2003 * */ package org.gudy.azureus2.core3.disk; import java.io.File; import java.io.IOException; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.util.DirectByteBuffer; /** * @author Olivier * */ public interface DiskManagerFileInfo { public static final int READ = 1; public static final int WRITE = 2; public static final int ST_LINEAR = 1; public static final int ST_COMPACT = 2; // set methods public void setPriority(boolean b); public void setSkipped(boolean b); /** * Relink the file to the destination given - this method deals with if the file * is part of a simple torrent or not (so it may set the download name to keep it * in sync). If you just want a simple relink, use setLinkAtomic. * * @param link_destination * @return */ public boolean setLink( File link_destination ); public boolean setLinkAtomic(File link_destination); // gets the current link, null if none public File getLink(); /** * Download must be stopped before calling this! * @param type one of ST_LINEAR or ST_COMPACT */ public boolean setStorageType(int type ); public int getStorageType(); // get methods public int getAccessMode(); public long getDownloaded(); public String getExtension(); public int getFirstPieceNumber(); public int getLastPieceNumber(); public long getLength(); public int getNbPieces(); public boolean isPriority(); public boolean isSkipped(); public int getIndex(); public DownloadManager getDownloadManager(); public DiskManager getDiskManager(); public File getFile( boolean follow_link ); public TOTorrentFile getTorrentFile(); public DirectByteBuffer read( long offset, int length ) throws IOException; public void flushCache() throws Exception; public void close(); public void addListener( DiskManagerFileInfoListener listener ); public void removeListener( DiskManagerFileInfoListener listener ); } azureus-4.3.0.6/org/gudy/azureus2/core3/disk/DiskManagerWriteRequestListener.java0000644000175000017500000000234110373051004027235 0ustar adrianadrian/* * Created on 08-Oct-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.disk; /** * @author parg * */ public interface DiskManagerWriteRequestListener { public void writeCompleted( DiskManagerWriteRequest request ); public void writeFailed( DiskManagerWriteRequest request, Throwable cause ); } azureus-4.3.0.6/org/gudy/azureus2/core3/ipchecker/0000755000175000017500000000000011310377342021126 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/ipchecker/extipchecker/0000755000175000017500000000000011310377634023610 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/0000755000175000017500000000000011310377634024551 5ustar adrianadrian././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceImpl.javaazureus-4.3.0.6/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceImpl.jav0000644000175000017500000001652310175055702032722 0ustar adrianadrian/* * File : ExternalIPCheckerServiceImpl.java * Created : 09-Nov-2003 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.ipchecker.extipchecker.impl; /** * @author parg * */ import java.util.*; import java.io.*; import java.net.*; import org.gudy.azureus2.core3.internat.*; import org.gudy.azureus2.core3.ipchecker.extipchecker.*; import org.gudy.azureus2.core3.util.*; public abstract class ExternalIPCheckerServiceImpl implements ExternalIPCheckerService, Cloneable { private static final int MAX_PAGE_SIZE = 4096; private static final String MSG_KEY_ROOT = "IPChecker.external"; private String name; private String description; private String url; private boolean completed; private Vector listeners = new Vector(); private AEMonitor this_mon = new AEMonitor( "ExtIPCheckServ"); private AESemaphore timeout_sem = new AESemaphore( "ExtIPCheckServ" ); protected ExternalIPCheckerServiceImpl( String name_key ) { name = MessageText.getString( name_key + ".name" ); description = MessageText.getString( name_key + ".description" ); url = MessageText.getString( name_key + ".url" ); } public void initiateCheck( long timeout ) { _clone().initiateCheckSupport(timeout); } protected ExternalIPCheckerServiceImpl _clone() { try{ return((ExternalIPCheckerServiceImpl)clone()); }catch( CloneNotSupportedException e){ Debug.printStackTrace( e ); return( null ); } } protected void initiateCheckSupport( final long timeout ) { Thread t = new AEThread("IPChecker") { public void runSupport() { try{ initiateCheckSupport(); }finally{ setComplete(); } } }; t.setDaemon( true ); t.start(); if ( timeout > 0 ){ Thread t2 = new AEThread("IPChecker2") { public void runSupport() { try{ if ( !timeout_sem.reserve( timeout )){ if ( !completed ){ informFailure( "timeout" ); setComplete(); } } }catch( Throwable e ){ Debug.printStackTrace( e ); } } }; t2.setDaemon( true ); t2.start(); } } protected abstract void initiateCheckSupport(); protected void setComplete() { completed = true; } protected String loadPage( String url_string ) { try{ URL url = new URL( url_string ); HttpURLConnection connection = null; InputStream is = null; try{ connection = (HttpURLConnection)url.openConnection(); int response = connection.getResponseCode(); if( response == HttpURLConnection.HTTP_ACCEPTED || response == HttpURLConnection.HTTP_OK ){ is = connection.getInputStream(); String page = ""; while( page.length() < MAX_PAGE_SIZE ){ byte[] buffer = new byte[2048]; int len = is.read( buffer ); if ( len < 0 ){ break; } page += new String(buffer, 0, len); } return( page ); }else{ informFailure( "httpinvalidresponse", "" + response ); return( null ); } }finally{ try{ if ( is != null ){ is.close(); } if ( connection != null ){ connection.disconnect(); } }catch( Throwable e){ Debug.printStackTrace( e ); } } }catch( Throwable e ){ informFailure( "httploadfail", e.toString()); return( null ); } } protected String extractIPAddress( String str ) { int pos = 0; while(pos < str.length()){ int p1 = str.indexOf( '.', pos ); if ( p1 == -1 ){ informFailure( "ipnotfound" ); return( null ); } if ( p1 > 0 ){ if ( Character.isDigit(str.charAt(p1-1))){ int p2 = p1-1; while(p2>=0&&Character.isDigit(str.charAt(p2))){ p2--; } p2++; int p3 = p2+1; int dots = 0; while(p3 30000 ){ throw( new Exception( "Timeout" )); } } Thread.sleep( 50 ); } } }catch( Throwable t ) { Debug.out( "Nat check write failed", t ); } connection.close(); } public boolean autoCryptoFallback() { return( true ); } }, new MessageStreamFactory() { public MessageStreamEncoder createEncoder() { return new AZMessageEncoder(false); /* unused */} public MessageStreamDecoder createDecoder() { return new AZMessageDecoder(); /* unused */} }); } if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "NAT tester using central routing for " + "server socket")); } if ( !use_incoming_router ){ //different port than already listening on, start new listen server try{ server = new ServerSocket(); //unbound server.setReuseAddress( true ); //set SO_REUSEADDR InetSocketAddress address; if( bind_ip != null ) { address = new InetSocketAddress( bind_ip, _port ); }else { address = new InetSocketAddress( _port ); } server.bind( address ); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "NAT tester server socket bound to " +address )); }catch(Exception e) { Logger.log(new LogEvent(LOGID, "NAT tester failed to setup listener socket", e )); throw( e ); } } } protected ByteBuffer getMessage() throws IOException { Map map = new HashMap(); map.put( "check", check ); byte[] map_bytes = BEncoder.encode( map ); ByteBuffer msg = ByteBuffer.allocate( 4 + map_bytes.length ); msg.putInt( map_bytes.length ); msg.put( map_bytes ); msg.flip(); return( msg ); } public void runSupport() { while(bContinue) { try { if (use_incoming_router) { //just NOOP loop sleep while waiting for routing Thread.sleep(20); } else { //listen for accept Socket sck = server.accept(); sck.getOutputStream().write( getMessage().array()); sck.close(); } } catch(Exception e) { //Debug.printStackTrace(e); bContinue = false; } } } public void stopIt() { bContinue = false; if( use_incoming_router ) { if ( http_test ){ if ( bind_ip_set ){ HTTPNetworkManager.getSingleton().clearExplicitBindAddress(); } }else{ NetworkManager.getSingleton().cancelIncomingConnectionRouting( matcher ); if ( bind_ip_set ){ TCPNetworkManager.getSingleton().clearExplicitBindAddress(); } } } else if( server != null ) { try { server.close(); } catch(Throwable t) { t.printStackTrace(); } } } } azureus-4.3.0.6/org/gudy/azureus2/core3/ipchecker/natchecker/NatChecker.java0000644000175000017500000001620610714435044026115 0ustar adrianadrian/* * File : NatChecker.java * Created : 12 oct. 2003 18:46:00 * By : Olivier * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.gudy.azureus2.core3.ipchecker.natchecker; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.URL; import java.net.URLEncoder; import java.nio.ByteBuffer; import java.util.Map; import com.aelitis.azureus.core.*; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminASN; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.tracker.util.TRTrackerUtils; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.*; import com.aelitis.azureus.plugins.upnp.*; /** * @author Olivier * */ public class NatChecker { private static final LogIDs LOGID = LogIDs.NET; public static final int NAT_OK = 1; public static final int NAT_KO = 2; public static final int NAT_UNABLE = 3; private int result; private String additional_info = ""; private InetAddress ip_address; public NatChecker( AzureusCore azureus_core, InetAddress bind_ip, int port, boolean http_test ) { String check = "azureus_rand_" + String.valueOf( (int)(Math.random() * 100000) ); if ( port < 0 || port > 65535 || port == 6880 ){ result = NAT_UNABLE; additional_info = "Invalid port"; return; } NatCheckerServer server; try{ server = new NatCheckerServer( bind_ip, port, check, http_test ); }catch( Throwable e ){ result = NAT_UNABLE; additional_info = "Can't initialise server: " + Debug.getNestedExceptionMessage(e); return; } //do UPnP if necessary PluginInterface pi_upnp = azureus_core.getPluginManager().getPluginInterfaceByClass( UPnPPlugin.class ); UPnPMapping new_mapping = null; String upnp_str = null; if( pi_upnp != null ) { UPnPPlugin upnp = (UPnPPlugin)pi_upnp.getPlugin(); UPnPMapping mapping = upnp.getMapping( true, port ); if ( mapping == null ) { new_mapping = mapping = upnp.addMapping( "NAT Tester", true, port, true ); // give UPnP a chance to work try { Thread.sleep( 500 ); } catch (Throwable e) { Debug.printStackTrace( e ); } } UPnPPluginService[] services = upnp.getServices(); if ( services.length > 0 ){ upnp_str = ""; for (int i=0;i 0 ){ urlStr += "&as=" + URLEncoder.encode( as, "UTF8" ); urlStr += "&asn=" + URLEncoder.encode( asn, "UTF8" ); } urlStr += "&locale=" + MessageText.getCurrentLocale().toString(); String ip_override = TRTrackerUtils.getPublicIPOverride(); if ( ip_override != null ){ urlStr += "&ip=" + ip_override; } URL url = new URL( urlStr ); HttpURLConnection con = (HttpURLConnection)url.openConnection(); con.connect(); ByteArrayOutputStream message = new ByteArrayOutputStream(); InputStream is = con.getInputStream(); byte[] data = new byte[ 1024 ]; int expected_length = -1; while( true ){ int len = is.read( data ); if ( len <= 0 ){ break; } message.write( data, 0, len ); if ( expected_length == -1 && message.size() >= 4 ){ byte[] bytes = message.toByteArray(); ByteBuffer bb = ByteBuffer.wrap( bytes ); expected_length = bb.getInt(); message = new ByteArrayOutputStream(); if ( bytes.length > 4 ){ message.write( bytes, 4, bytes.length - 4 ); } } if ( expected_length != -1 && message.size() == expected_length ){ break; } } Map map = BDecoder.decode( message.toByteArray() ); int reply_result = ((Long)map.get( "result" )).intValue(); switch( reply_result ) { case 0 :{ byte[] reason = (byte[])map.get( "reason" ); if( reason != null ) { Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "NAT CHECK FAILED: " + new String(reason))); } result = NAT_KO; additional_info = reason==null?"Unknown":new String(reason, "UTF8"); break; } case 1 :{ result = NAT_OK; byte[] reply = (byte[])map.get( "reply" ); if( reply != null ) { additional_info = new String(reply, "UTF8"); } break; } default :{ result = NAT_UNABLE; additional_info = "Invalid response"; break; } } byte[] ip_bytes = (byte[])map.get( "ip_address" ); if ( ip_bytes != null ){ try{ ip_address = InetAddress.getByAddress( ip_bytes ); }catch( Throwable e ){ } } } catch (Exception e) { result = NAT_UNABLE; additional_info = "Error: " + Debug.getNestedExceptionMessage( e ); } finally { server.stopIt(); if( new_mapping != null ) { new_mapping.destroy(); } } } public int getResult() { return( result ); } public InetAddress getExternalAddress() { return( ip_address ); } public String getAdditionalInfo() { return( additional_info ); } } azureus-4.3.0.6/org/gudy/azureus2/core3/logging/0000755000175000017500000000000011310377634020623 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/logging/LogRelationUtils.java0000644000175000017500000000317110577641404024733 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.logging; /** * @author TuxPaper * @created Mar 19, 2007 * */ public class LogRelationUtils { public static Object queryForClass(Object[] objects, Class cla) { if (objects == null) { return null; } // Pass 1: Quick check if class is in objects for (int i = 0; i < objects.length; i++) { Object object = objects[i]; if (cla.isInstance(object)) { return object; } } // Pass 2: check LogRelations for (int i = 0; i < objects.length; i++) { Object object = objects[i]; if (object instanceof LogRelation) { LogRelation logRelation = (LogRelation)object; Object answer = logRelation.queryForClass(cla); if (answer != null) { return answer; } } } return null; } } azureus-4.3.0.6/org/gudy/azureus2/core3/logging/impl/0000755000175000017500000000000011310377634021564 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/core3/logging/impl/FileLoggingAdapter.java0000644000175000017500000000267510401034600026107 0ustar adrianadrian/* * Created on Feb 28, 2006 2:41:30 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.logging.impl; import org.gudy.azureus2.core3.logging.LogEvent; /** * Listeners for FileLogging * * @author TuxPaper * @created Feb 28, 2006 * */ public class FileLoggingAdapter { /** * Called when we are about to log an event to file. * * @param event Event being logged to file * @param lineOut line to be written to file (modifyable) * @return true-ok to log to file; false-skip logging to file */ public boolean logToFile(LogEvent event, StringBuffer lineOut) { return true; } } azureus-4.3.0.6/org/gudy/azureus2/core3/logging/impl/FileLogging.java0000644000175000017500000002260411061150316024606 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.logging.impl; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import org.gudy.azureus2.core3.config.COConfigurationListener; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.config.impl.ConfigurationManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.Debug; /** * Log events to a file. * * @author TuxPaper */ // TODO: Filter public class FileLogging implements ILogEventListener { public static final String LOG_FILE_NAME = "az.log"; public static final String BAK_FILE_NAME = "az.log.bak"; public static LogIDs[] configurableLOGIDs = {LogIDs.STDOUT, LogIDs.ALERT, LogIDs.CORE, LogIDs.DISK, LogIDs.GUI, LogIDs.NET, LogIDs.NWMAN, LogIDs.PEER, LogIDs.PLUGIN, LogIDs.TRACKER, LogIDs.CACHE, LogIDs.PIECES }; private static final String CFG_ENABLELOGTOFILE = "Logging Enable"; private boolean bLogToFile = false; private boolean bLogToFileErrorPrinted = false; private String sLogDir = ""; private int iLogFileMaxMB = 1; // List of components we don't log. // Array represents LogTypes (info, warning, error) private ArrayList[] ignoredComponents = new ArrayList[3]; private ArrayList listeners = new ArrayList(); public void initialize() { // Shorten from COConfigurationManager To make code more readable final ConfigurationManager config = ConfigurationManager.getInstance(); boolean overrideLog = System.getProperty("azureus.overridelog") != null; for (int i = 0; i < ignoredComponents.length; i++) { ignoredComponents[i] = new ArrayList(); } if (!overrideLog) { config.addListener(new COConfigurationListener() { public void configurationSaved() { checkLoggingConfig(); } }); } checkLoggingConfig(); config.addParameterListener(CFG_ENABLELOGTOFILE, new ParameterListener() { public void parameterChanged(String parameterName) { FileLogging.this.reloadLogToFileParam(); } }); } /** * */ protected void reloadLogToFileParam() { final ConfigurationManager config = ConfigurationManager.getInstance(); boolean bNewLogToFile = System.getProperty("azureus.overridelog") != null || config.getBooleanParameter(CFG_ENABLELOGTOFILE); if (bNewLogToFile != bLogToFile) { bLogToFile = bNewLogToFile; if (bLogToFile) Logger.addListener(this); else{ Logger.removeListener(this); synchronized( Logger.class ){ // close existing file checkAndSwapLog(); } } } } private void checkLoggingConfig() { try { // Shorten from COConfigurationManager To make code more readable final ConfigurationManager config = ConfigurationManager.getInstance(); String timeStampFormat; boolean overrideLog = System.getProperty("azureus.overridelog") != null; if (overrideLog) { // Don't set this - reloadLogToFileParam will do it. //bLogToFile = true; sLogDir = System.getProperty("azureus.overridelogdir", "."); iLogFileMaxMB = 2; timeStampFormat = "HH:mm:ss.SSS "; for (int i = 0; i < ignoredComponents.length; i++) { ignoredComponents[i].clear(); } reloadLogToFileParam(); } else { reloadLogToFileParam(); sLogDir = config.getStringParameter("Logging Dir", ""); iLogFileMaxMB = config.getIntParameter("Logging Max Size"); timeStampFormat = config.getStringParameter("Logging Timestamp")+" "; for (int i = 0; i < ignoredComponents.length; i++) { ignoredComponents[i].clear(); int logType = indexToLogType(i); for (int j = 0; j < configurableLOGIDs.length; j++) { if (!config.getBooleanParameter("bLog." + logType + "." + configurableLOGIDs[j], true)) ignoredComponents[i].add(configurableLOGIDs[j]); } } } synchronized (Logger.class) { // Create the date format first *before* we do checkAndSwapLog, // just in case we end up invoking logToFile... format = new SimpleDateFormat(timeStampFormat); checkAndSwapLog(); } } catch (Throwable t) { Debug.printStackTrace(t); } } private void logToFile(String str) { if (!bLogToFile) return; String dateStr = format.format(new Date()); synchronized (Logger.class) { // exception handling is done by FileWriter if(logFilePrinter != null) { logFilePrinter.print(dateStr); logFilePrinter.print(str); logFilePrinter.flush(); } checkAndSwapLog(); } // sync } private SimpleDateFormat format; private PrintWriter logFilePrinter; private void checkAndSwapLog() { if (!bLogToFile) { if(logFilePrinter != null) { logFilePrinter.close(); logFilePrinter = null; } return; } long lMaxBytes = (iLogFileMaxMB * 1024 * 1024) / 2; File logFile = new File(sLogDir + File.separator + LOG_FILE_NAME); if (logFile.length() > lMaxBytes && logFilePrinter != null) { File back_name = new File(sLogDir + File.separator + BAK_FILE_NAME); logFilePrinter.close(); logFilePrinter = null; if ((!back_name.exists()) || back_name.delete()) if (!logFile.renameTo(back_name)) logFile.delete(); else logFile.delete(); } if(logFilePrinter == null) { try { logFilePrinter = new PrintWriter(new FileWriter(logFile, true)); } catch (IOException e) { if (!bLogToFileErrorPrinted) { // don't just log errors, as it would cause infinite recursion bLogToFileErrorPrinted = true; Debug.out("Unable to write to log file: " + logFile); Debug.printStackTrace(e); /* java.io.PrintStream stderr = Logger.getOldStdErr(); stderr.println("Unable to write to log file: " + logFile); e.printStackTrace(stderr); */ } } } } private int logTypeToIndex(int entryType) { switch (entryType) { case LogEvent.LT_INFORMATION: return 0; case LogEvent.LT_WARNING: return 1; case LogEvent.LT_ERROR: return 2; } return 0; } private int indexToLogType(int index) { switch (index) { case 0: return LogEvent.LT_INFORMATION; case 1: return LogEvent.LT_WARNING; case 2: return LogEvent.LT_ERROR; } return LogEvent.LT_INFORMATION; } /* * (non-Javadoc) * * @see org.gudy.azureus2.core3.logging.ILoggerListener2#log(org.gudy.azureus2.core3.logging.LogEvent) */ private final static int DEFPADDING = 100; private int lastWidth = DEFPADDING; public void log(LogEvent event) { if (ignoredComponents[logTypeToIndex(event.entryType)] .contains(event.logID)) return; StringBuffer text = new StringBuffer(event.text.length()); text.append(event.entryType).append(" "); padAndAppend(text, event.logID.toString(), 8, 1); //text.append("|"); if (event.relatedTo != null) { lastWidth = padAndAppend(text, event.text, lastWidth, 1); if (lastWidth > 200) lastWidth = 200; for (int i = 0; i < event.relatedTo.length; i++) { Object obj = event.relatedTo[i]; if (obj == null) continue; if (i > 0) text.append("; "); if (obj instanceof LogRelation) { text.append(((LogRelation) obj).getRelationText()); } else { text.append("RelatedTo[") .append(obj.toString()) .append("]"); } } } else { text.append(event.text); lastWidth = DEFPADDING; } //text.append(event.text); if (event.text == null || !event.text.endsWith("\n")) text.append("\r\n"); boolean okToLog = true; for (Iterator iter = listeners.iterator(); iter.hasNext() && okToLog;) { FileLoggingAdapter listener = (FileLoggingAdapter) iter.next(); okToLog = listener.logToFile(event, text); } logToFile(text.toString()); } private int padAndAppend(StringBuffer appendTo, String s, int width, int growBy) { if (s == null) s = "null"; appendTo.append(s); int sLen = s.length(); int len = width - sLen; while (len <= 0) len += growBy; char[] padding = new char[len]; if (len > 5) { for (int i = 0; i < len; i += 2) padding[i] = ' '; for (int i = 1; i < len; i += 2) padding[i] = '.'; } else { for (int i = 0; i < len; i++) padding[i] = ' '; } appendTo.append(padding); return len + sLen; } public void addListener(FileLoggingAdapter listener) { if (!listeners.contains(listener)) listeners.add(listener); } public void removeListener(FileLoggingAdapter listener) { listeners.remove(listener); } public List getListeners() { return listeners; } } azureus-4.3.0.6/org/gudy/azureus2/core3/logging/impl/LoggerImpl.java0000644000175000017500000002023111053651632024463 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.logging.impl; import java.io.OutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.List; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.config.impl.ConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.ILogAlertListener; import org.gudy.azureus2.core3.logging.ILogEventListener; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEDiagnosticsLogger; import org.gudy.azureus2.core3.util.Debug; /** * Logging tool * * @author TuxPaper * @since 2.3.0.7 */ public class LoggerImpl { private final int MAXHISTORY = 256; private boolean bLogToStdOut = System.getProperty("azureus.log.stdout") != null; private boolean bEventLoggingEnabled = false; private PrintStream psOldOut = null; private PrintStream psOldErr = null; private PrintStream psOut; private PrintStream psErr; private List logListeners = new ArrayList(); private AEDiagnosticsLogger alertLogger; private List alertListeners = new ArrayList(); private List alertHistory = new ArrayList(); private boolean logToStdErrAllowed = true; /** * Initializes the Logger and sets up a file logger. */ public LoggerImpl() { doRedirects(); } /** * Must be seperate from constructor, because the code may call a Logger.* * method, which requires a loggerImpl to be not null. * */ public void init() { // temporarily set to true, to log any errors between now and setting // bEnabled properly. bEventLoggingEnabled = true; // Shorten from COConfigurationManager To make code more readable final ConfigurationManager config = ConfigurationManager.getInstance(); boolean overrideLog = System.getProperty("azureus.overridelog") != null; if (overrideLog) { bEventLoggingEnabled = true; } else { bEventLoggingEnabled = config.getBooleanParameter("Logger.Enabled"); config.addParameterListener("Logger.Enabled", new ParameterListener() { public void parameterChanged(String parameterName) { bEventLoggingEnabled = config.getBooleanParameter("Logger.Enabled"); } }); } } /** * Set up stdout/stderr redirects */ public void doRedirects() { try { if (System.out != psOut) { if (psOldOut == null) psOldOut = System.out; psOut = new PrintStream(new RedirectorStream(psOldOut, LogIDs.STDOUT, LogEvent.LT_INFORMATION)); System.setOut(psOut); } if (System.err != psErr) { if (psOldErr == null) psOldErr = System.err; psErr = new PrintStream(new RedirectorStream(psOldErr, LogIDs.STDERR, LogEvent.LT_ERROR)); System.setErr(psErr); } } catch (Throwable e) { Debug.printStackTrace(e); } } public boolean isEnabled() { return bEventLoggingEnabled; } /** * Redirects any incoming text to the logger */ private class RedirectorStream extends OutputStream { protected PrintStream ps; protected StringBuffer buffer = new StringBuffer(1024); protected LogIDs logID; protected int logType; protected RedirectorStream(PrintStream _ps, LogIDs _logID, int _logType) { ps = _ps; logType = _logType; logID = _logID; } public void write(int data) { char c = (char) data; if (c == '\n') { if (!bLogToStdOut) { ps.println(buffer); } log(new LogEvent(logID, logType, buffer.toString())); buffer.setLength(0); } else if (c != '\r') { buffer.append(c); } } public void write(byte b[], int off, int len) { for (int i = off; i < off + len; i++) { int d = b[i]; if (d < 0) d += 256; write(d); } } } // Log Event Functions // =================== /** * Log an event * * @param event * event to log */ public void log(LogEvent event) { /** * This highlights bits of code which log, but don't bother * to check whether logging is enabled or not. */ //if (!bEventLoggingEnabled) { // new Exception("No logging check done!").printStackTrace(psOldErr); //} if (bLogToStdOut && psOldOut != null) psOldOut.println(event.text); if (event.entryType == LogEvent.LT_ERROR) { if ( AEDiagnostics.isStartupComplete()){ // more recursive horrors here if we try and log too early Debug.outDiagLoggerOnly("[" + event.logID + "] " + event.text); } if (logToStdErrAllowed && psOldErr != null && event.logID != LogIDs.STDERR) { psOldErr.println("[" + event.logID + "] " + event.text); } } if (bEventLoggingEnabled) for (int i = 0; i < logListeners.size(); i++) { try { Object listener = logListeners.get(i); if (listener instanceof ILogEventListener) ((ILogEventListener) listener).log(event); } catch (Throwable e) { if (logToStdErrAllowed && psOldErr != null) { psOldErr.println("Error while logging: " + e.getMessage()); e.printStackTrace(psOldErr); } } } // Write error to stderr, which will eventually get back here if (event.err != null && event.entryType == LogEvent.LT_ERROR){ Debug.printStackTrace(event.err); } } public void logTextResource(LogEvent event) { event.text = MessageText.getString(event.text); log(event); } public void logTextResource(LogEvent event, String params[]) { event.text = MessageText.getString(event.text, params); log(event); } public void addListener(ILogEventListener aListener) { logListeners.add(aListener); } public void removeListener(ILogEventListener aListener) { logListeners.remove(aListener); } // Log Alert Functions // =================== public void log(LogAlert alert) { String logText = "Alert:" + alert.entryType + ":" + alert.text; // Log all Alerts as Events LogEvent alertEvent = new LogEvent(LogIDs.ALERT, alert.entryType, logText); alertEvent.err = alert.err; Logger.log(alertEvent); synchronized (this) { if (alertLogger == null) { alertLogger = AEDiagnostics.getLogger("alerts"); } } alertLogger.log(logText); alertHistory.add(alert); if (alertHistory.size() > MAXHISTORY) alertHistory.remove(0); for (int i = 0; i < alertListeners.size(); i++) { try { Object listener = alertListeners.get(i); if (listener instanceof ILogAlertListener) ((ILogAlertListener) listener).alertRaised(alert); } catch (Throwable f) { if (psOldErr != null) { psOldErr.println("Error while alerting: " + f.getMessage()); f.printStackTrace(psOldErr); } } } } public void logTextResource(LogAlert alert) { alert.text = MessageText.getString(alert.text); log(alert); } public void logTextResource(LogAlert alert, String params[]) { alert.text = MessageText.getString(alert.text, params); log(alert); } public void addListener(ILogAlertListener l) { alertListeners.add(l); for (int i = 0; i < alertHistory.size(); i++) { LogAlert alert = (LogAlert) alertHistory.get(i); l.alertRaised(alert); } } public void removeListener(ILogAlertListener l) { alertListeners.remove(l); } public PrintStream getOldStdErr() { return psOldErr; } public void allowLoggingToStdErr(boolean allowed) { this.logToStdErrAllowed = allowed; } } azureus-4.3.0.6/org/gudy/azureus2/core3/logging/Logger.java0000644000175000017500000001226411053652240022703 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.logging; import java.io.PrintStream; import org.gudy.azureus2.core3.logging.impl.FileLogging; import org.gudy.azureus2.core3.logging.impl.LoggerImpl; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; /** * A static implementation of the LoggerImpl class. * * @note Currently, LoggerImpl and Logger could be combined, but they are split * for future consideration (ie. allowing multiple LoggerImpl) * * @author TuxPaper * @since 2.3.0.7 */ public class Logger { private static final LogIDs LOGID = LogIDs.LOGGER; private static LoggerImpl loggerImpl = null; private static FileLogging fileLogging = new FileLogging(); static { try { loggerImpl = new LoggerImpl(); loggerImpl.init(); fileLogging.initialize(); if (loggerImpl.isEnabled()) { log(new LogEvent(LOGID, "**** Logging starts: " + Constants.APP_NAME + " " + Constants.AZUREUS_VERSION + " ****")); log(new LogEvent(LOGID, "java.home=" + System.getProperty("java.home"))); log(new LogEvent(LOGID, "java.version=" + System.getProperty("java.version"))); log(new LogEvent(LOGID, "os=" + System.getProperty("os.arch") + "/" + System.getProperty("os.name") + "/" + System.getProperty("os.version"))); log(new LogEvent(LOGID, "user.dir=" + System.getProperty("user.dir"))); log(new LogEvent(LOGID, "user.home=" + System.getProperty("user.home"))); } } catch (Throwable t) { t.printStackTrace(); Debug.out("Error initializing Logger", t); // loggerImpl will always be set, except for cases where there wasn't // enough memory. In that case, app will blork with null pointer exception // on first Logger.* call. However, since there's not enough memory, // application will probably blork somewhere else in the code first. } } /** * Determines whether events are logged * * @return true if events are logged */ public static boolean isEnabled() { return loggerImpl.isEnabled(); } /** * Log an event * * @param event * event to log */ public static void log(LogEvent event) { loggerImpl.log(event); } public static void log(LogAlert alert) { loggerImpl.log(alert); } /** * Log an event, loading text from out messagebundle. Fill event.text with * resource id. * * @param event * event to log */ public static void logTextResource(LogEvent event) { loggerImpl.logTextResource(event); } // dead public static void logTextResource(LogEvent event, String params[]) { loggerImpl.logTextResource(event, params); } // dead public static void logTextResource(LogAlert alert) { loggerImpl.logTextResource(alert); } public static void logTextResource(LogAlert alert, String params[]) { loggerImpl.logTextResource(alert, params); } /** * Redirect stdout and stderr to Logger. */ public static void doRedirects() { loggerImpl.doRedirects(); } /** * Add a listener that's triggered when an event is logged. * * @param aListener * Listener to call when an event is logged */ public static void addListener(ILogEventListener aListener) { loggerImpl.addListener(aListener); } /** * Add a listener that's triggered when an alert is logged. * * @param aListener * Listener to call when an alert is logged */ public static void addListener(ILogAlertListener aListener) { loggerImpl.addListener(aListener); } /** * Remove a previously added log listener * * @param aListener * Listener to remove */ public static void removeListener(ILogEventListener aListener) { loggerImpl.removeListener(aListener); } /** * Remove a previously added log listener * * @param aListener * Listener to remove */ public static void removeListener(ILogAlertListener aListener) { loggerImpl.removeListener(aListener); } /** * Retrieve the original stderr output before we hooked it. Handy for * printing out critical errors that need to bypass the logger capture. * * @return stderr */ public static PrintStream getOldStdErr() { return loggerImpl.getOldStdErr(); } public static FileLogging getFileLoggingInstance() { return fileLogging; } public static void allowLoggingToStdErr(boolean allowed) { loggerImpl.allowLoggingToStdErr(allowed); } } azureus-4.3.0.6/org/gudy/azureus2/core3/logging/LogEvent.java0000644000175000017500000000616710551551710023216 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.logging; import java.util.Date; /** * Container to hold Log Event information. * * @note There are no constructors without Log ID as a parameter. This is * intentional, as all log events should have a log id. * @author TuxPaper */ public class LogEvent { // log types public static final int LT_INFORMATION = 0; public static final int LT_WARNING = 1; public static final int LT_ERROR = 3; /** Date and Time this event occurred */ public Date timeStamp = new Date(); /** A list of events that this entry is related to */ public Object[] relatedTo; /** Log ID, categorizing the event */ public LogIDs logID; /** Type of entry, usually one of Event.LT_* constants */ public int entryType; /** Text of the event */ public String text; /** Error related to event */ public Throwable err = null; public LogEvent(Object[] relatedTo, LogIDs logID, int entryType, String text) { this.logID = logID; this.entryType = entryType; this.text = text; this.relatedTo = relatedTo; } public LogEvent(Object relatedTo, LogIDs logID, int entryType, String text) { this(new Object[] { relatedTo }, logID, entryType, text); } public LogEvent(LogIDs logID, int entryType, String text) { this(null, logID, entryType, text); } public LogEvent(Object[] relatedTo, LogIDs logID, String text) { this(relatedTo, logID, LT_INFORMATION, text); } public LogEvent(Object relatedTo, LogIDs logID, String text) { this(new Object[] { relatedTo }, logID, LT_INFORMATION, text); } public LogEvent(LogIDs logID, String text) { this(null, logID, LT_INFORMATION, text); } // Throwables public LogEvent(Object[] relatedTo, LogIDs logID, int entryType, String text, Throwable e) { this(relatedTo, logID, entryType, text); this.err = e; } public LogEvent(Object[] relatedTo, LogIDs logID, String text, Throwable e) { this(relatedTo, logID, LT_ERROR, text, e); } public LogEvent(Object relatedTo, LogIDs logID, String text, Throwable e) { this(new Object[] { relatedTo }, logID, text, e); } public LogEvent(LogIDs logID, int entryType, String text, Throwable e) { this(null, logID, entryType, text, e); } public LogEvent(LogIDs logID, String text, Throwable e) { this(null, logID, text, e); } } azureus-4.3.0.6/org/gudy/azureus2/core3/logging/ILogEventListener.java0000644000175000017500000000220010373051026025012 0ustar adrianadrian/* * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.logging; /** * @author TuxPaper * @since 2.3.0.7 */ public interface ILogEventListener { /** A LogEvent has been generated. * * @param event The newly generated LogEvent */ public void log(LogEvent event); } azureus-4.3.0.6/org/gudy/azureus2/core3/logging/LogRelation.java0000644000175000017500000000474610373051026023710 0ustar adrianadrian/* * File : LogRelation.java * Created : Nov 29, 2005 * By : TuxPaper * * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.logging; /** * @author TuxPaper * */ public class LogRelation { /** * A short description of what your class holds that can be printed by the logger * * @return */ public String getRelationText() { return toString(); } protected final String propogatedRelationText(Object o) { if (o instanceof LogRelation) return ((LogRelation)o).getRelationText(); return null; } /** * Query this class for a reference to another class that it may hold * * @param c Class desired * @return If found, the class desired. Otherwise, null. */ public Object[] getQueryableInterfaces() { return null; } public final Object queryForClass(Class c) { return queryForClass(c, getQueryableInterfaces()); } private boolean running = false; protected final Object queryForClass(Class c, Object[] queryObjects) { if (running || queryObjects == null) return null; try { running = true; if (c.isInstance(this)) return this; // Check if any of the objects are of c for (int i = 0; i < queryObjects.length; i++) { if (c.isInstance(queryObjects[i])) return queryObjects[i]; } // Query each object that is LogRelation for (int i = 0; i < queryObjects.length; i++) { if (queryObjects[i] instanceof LogRelation) { Object obj = ((LogRelation) queryObjects[i]).queryForClass(c, ((LogRelation) queryObjects[i]).getQueryableInterfaces()); if (obj != null) return obj; } } return null; } finally { running = false; } } } azureus-4.3.0.6/org/gudy/azureus2/core3/logging/ILogAlertListener.java0000644000175000017500000000221210373051026025003 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.logging; /** * @author TuxPaper * @since 2.3.0.7 */ public interface ILogAlertListener { /** An alert has been generated * * @param alert LogAlert that was generated */ public void alertRaised(LogAlert alert); } azureus-4.3.0.6/org/gudy/azureus2/core3/logging/LogAlert.java0000644000175000017500000000774111044765276023217 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.logging; import com.aelitis.azureus.core.util.GeneralUtils; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import java.util.ArrayList; import java.util.regex.Pattern; /** * @author TuxPaper */ public class LogAlert implements org.gudy.azureus2.plugins.logging.LogAlert { // log types public static final int AT_INFORMATION = LogEvent.LT_INFORMATION; public static final int AT_WARNING = LogEvent.LT_WARNING; public static final int AT_ERROR = LogEvent.LT_ERROR; public static final boolean REPEATABLE = true; public static final boolean UNREPEATABLE = false; public int entryType; public Throwable err = null; public boolean repeatable; public String text; /** A list of events that this entry is related to */ public Object[] relatedTo; // -1 -> default public int timeoutSecs = -1; /** * @param type * @param text * @param repeatable */ public LogAlert(boolean repeatable, int type, String text) { entryType = type; this.text = text; this.repeatable = repeatable; } /** * @param type * @param text * @param repeatable * @param timeoutSecs -1 -> use defaults 0 -> no timeout */ public LogAlert(boolean repeatable, int type, String text, int timeoutSecs) { entryType = type; this.text = text; this.repeatable = repeatable; this.timeoutSecs = timeoutSecs; } public LogAlert(Object[] relatedTo, boolean repeatable, int type, String text) { this(repeatable, type, text); this.relatedTo = relatedTo; } public LogAlert(Object relatedTo, boolean repeatable, int type, String text) { this(repeatable, type, text); this.relatedTo = new Object[] { relatedTo }; } public LogAlert(boolean repeatable, String text, Throwable err) { this(repeatable, AT_ERROR, text); this.err = err; } public LogAlert(boolean repeatable, int type, String text, Throwable err) { this(repeatable, type, text); this.err = err; } /** * @param downloadManagerImpl * @param b * @param string * @param e */ public LogAlert(Object relatedTo, boolean repeatable, String text, Throwable err) { this(repeatable, text, err); this.relatedTo = new Object[] { relatedTo }; } // Plugin methods. public int getGivenTimeoutSecs() {return timeoutSecs;} public String getText() {return text;} public Throwable getError() {return err;} public int getType() { switch (entryType) { case AT_INFORMATION: return LT_INFORMATION; case AT_ERROR: return LT_ERROR; case AT_WARNING: return LT_WARNING; default: return LT_INFORMATION; } } public Object[] getContext() { if (this.relatedTo == null) {return null;} ArrayList l = new ArrayList(); for (int i=0; i 0 ){ String message; try{ message = new String(message_bytes, "UTF-8" ); }catch( Throwable e ){ message = new String( message_bytes ); } String sig_key; int pos = key.indexOf('_'); if ( pos == -1 ){ sig_key = "message_sig"; }else{ sig_key = "message_sig" + key.substring( pos ); } String last_message_key = "CoreUpdateChecker.last" + key; String last = COConfigurationManager.getStringParameter( last_message_key, "" ); if ( !message.equals( last )){ byte[] signature = (byte[])reply.get( sig_key ); if ( signature == null ){ Logger.log( new LogEvent( LogIDs.LOGGER, "Signature missing from message" )); return; } try{ AEVerifier.verifyData( message, signature ); }catch( Throwable e ){ Logger.log( new LogEvent( LogIDs.LOGGER, "Message signature check failed", e )); return; } boolean completed = false; if ( message.startsWith( "x:" )){ // emergency patch application try{ URL jar_url = new URL( message.substring(2)); Logger.log( new LogEvent( LogIDs.LOGGER, "Patch application requsted: url=" + jar_url )); File temp_dir = AETemporaryFileHandler.createTempDir(); File jar_file = new File( temp_dir, "patch.jar" ); InputStream is = rdf.create( jar_url ).download(); try{ FileUtil.copyFile( is, jar_file ); is = null; AEVerifier.verifyData( jar_file ); ClassLoader cl = CoreUpdateChecker.class.getClassLoader(); if ( cl instanceof URLClassLoader ){ URL[] old = ((URLClassLoader)cl).getURLs(); URL[] new_urls = new URL[old.length+1]; System.arraycopy( old, 0, new_urls, 1, old.length ); new_urls[0]= jar_file.toURL(); cl = new URLClassLoader( new_urls, cl ); }else{ cl = new URLClassLoader( new URL[]{jar_file.toURL()}, cl ); } Class cla = cl.loadClass( "org.gudy.azureus2.update.version.Patch" ); cla.newInstance(); completed = true; }finally{ if ( is != null ){ is.close(); } } }catch( Throwable e ){ Logger.log( new LogEvent( LogIDs.LOGGER, "Patch application failed", e )); } } else if ( message.startsWith("u:") && message.length() > 4 ) { try { String type = message.substring(2, 3); String url = message.substring(4); UIFunctions uif = UIFunctionsManager.getUIFunctions(); if (uif != null) { uif.viewURL(url, null, 0.9, 0.9, true, type.equals("1")); } } catch (Throwable t) { Logger.log( new LogEvent( LogIDs.LOGGER, "URL message failed", t )); } // mark as complete even if errored completed = true; }else{ int alert_type = LogAlert.AT_WARNING; String alert_text = message; if ( alert_text.startsWith("i:" )){ alert_type = LogAlert.AT_INFORMATION; alert_text = alert_text.substring(2); } plugin_interface.getPluginProperties().setProperty( MESSAGE_PROPERTY, alert_text ); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, alert_type, alert_text, 0 )); completed = true; } if ( completed ){ COConfigurationManager.setParameter( last_message_key, message ); COConfigurationManager.save(); } } } } }catch( Throwable e ){ Debug.printStackTrace( e ); } } protected ResourceDownloader[] getPrimaryDownloaders( String latest_file_name ) { log.log( "Downloading primary mirrors" ); List res = new ArrayList(); try{ if ( latest_file_name == null ){ // very old method, non-mirror based res.add( new URL( Constants.SF_WEB_SITE + "Azureus2.jar" )); }else{ URL mirrors_url = new URL("http://prdownloads.sourceforge.net/azureus/" + latest_file_name + "?download"); ResourceDownloader rd = rdf.create( mirrors_url ); rd = rdf.getRetryDownloader( rd, RD_GET_MIRRORS_RETRIES ); rd.addListener( rd_logger ); String page = HTMLPageFactory.loadPage( rd.download()).getContent(); String pattern = "/azureus/" + latest_file_name + "?use_mirror="; int position = page.indexOf(pattern); while ( position > 0 ){ int end = page.indexOf(">", position); if (end < 0) { position = -1; }else{ String mirror = page.substring(position, end); if ( mirror.endsWith("\"")){ mirror = mirror.substring(0,mirror.length()-1); } try{ res.add( new URL( "http://prdownloads.sourceforge.net" + mirror )); }catch( Throwable e ){ log.log( "Invalid URL read:" + mirror, e ); } position = page.indexOf(pattern, position + 1); } } } }catch( Throwable e ){ log.log( "Failed to read primary mirror list", e ); } ResourceDownloader[] dls = new ResourceDownloader[res.size()]; for (int i=0;i 2.4.0.2 // 2) 2.4.0.1_CVS -> 2.4.0.2 // 3) 2.4.0.1_B12 -> 2.4.0.2 and 2.4.0.1_B14 // but NOT // 1) 2.4.0.0 -> 2.4.0.1_CVS or 2.4.0.1_B23 // 2) 2.4.0.1_CVS -> 2.4.0.1_B23 // for inc values: 0 = not CVS, -1 = _CVS, > 0 = Bnn int major_comp = Constants.compareVersions( current_base, latest_base ); if ( major_comp < 0 && latest_inc == 0 ){ return( true ); // latest is higher version and not CVS } // same version, both are B versions and latest B is more recent return( major_comp == 0 && current_inc > 0 && latest_inc > 0 && latest_inc > current_inc ); } public static void main( String[] args ) { String[][] tests = { { "2.4.0.0", "2.4.0.2", "true" }, { "2.4.0.1_CVS", "2.4.0.2", "true" }, { "2.4.0.1_B12", "2.4.0.2", "true" }, { "2.4.0.1_B12", "2.4.0.1_B34", "true" }, { "2.4.0.1_B12", "2.4.0.1_B6", "false" }, { "2.4.0.0", "2.4.0.1_CVS", "false" }, { "2.4.0.0", "2.4.0.1_B12", "false" }, { "2.4.0.0", "2.4.0.0" , "false" }, { "2.4.0.1_CVS", "2.4.0.1_CVS", "false" }, { "2.4.0.1_B2", "2.4.0.1_B2", "false" }, { "2.4.0.1_CVS", "2.4.0.1_B2", "false" }, { "2.4.0.1_B2", "2.4.0.1_CVS", "false" }, }; for (int i=0;i highest_p ){ highest_p = this_p; highest_p_file = files[i]; } }catch( Throwable e ){ Debug.printStackTrace( e ); } } } if ( CorePatchLevel.getCurrentPatchLevel() >= highest_p ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Core Patcher: no applicable patch found (highest = " + highest_p + ")")); // flip back from maybe as we now know it isn't needed if ( updater_update.getRestartRequired() == Update.RESTART_REQUIRED_MAYBE ){ updater_update.setRestartRequired( Update.RESTART_REQUIRED_NO ); } }else{ rd_log.reportActivity( "Applying patch '" + highest_p_file.getName() + "'"); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Core Patcher: applying patch '" + highest_p_file.toString() + "'")); InputStream pis = new FileInputStream( highest_p_file ); patchAzureus2( instance, pis, "P" + highest_p, plugin_interface.getLogger().getChannel( "CorePatcher" )); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_INFORMATION, "Patch " + highest_p_file.getName() + " ready to be applied")); String done_file = highest_p_file.toString(); done_file = done_file.substring(0,done_file.length()-1) + "x"; highest_p_file.renameTo( new File( done_file )); // flip the original update over to 'restart required' updater_update.setRestartRequired( Update.RESTART_REQUIRED_YES ); } }catch( Throwable e ){ Debug.printStackTrace( e ); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "Core Patcher failed", e)); } } public static void patchAzureus2( UpdateCheckInstance instance, InputStream pis, String resource_tag, LoggerChannel log ) throws Exception { String resource_name = "Azureus2_" + resource_tag + ".jar"; UpdateInstaller installer = instance.createInstaller(); File tmp = AETemporaryFileHandler.createTempFile(); OutputStream os = new FileOutputStream( tmp ); String az2_jar; if( Constants.isOSX ){ az2_jar = installer.getInstallDir() + "/" + SystemProperties.getApplicationName() + ".app/Contents/Resources/Java/"; }else{ az2_jar = installer.getInstallDir() + File.separator; } az2_jar += "Azureus2.jar"; InputStream is = new FileInputStream( az2_jar ); new UpdateJarPatcher( is, pis, os, log ); is.close(); pis.close(); os.close(); installer.addResource( resource_name, new FileInputStream( tmp )); tmp.delete(); installer.addMoveAction( resource_name, az2_jar ); } } azureus-4.3.0.6/org/gudy/azureus2/update/CorePatchLevel.java0000644000175000017500000000334211265567330023154 0ustar adrianadrian/* * Created on 26-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.update; /** * @author parg * */ public class CorePatchLevel { // everytime a patch is issued this number must go up by one // The resulting patch file must include this file and be named // Azureus2__P.pat // e.g. Azureus2_2.0.8.5_P1.pat // dont' reset to 1 on a new mainline, keep going up! // Level 1: 2302 - fix for DHT version propagation problem // Level 2: 2306 - fix for SF mirror parsing problem for core updates // Level 3: 4208 - fix for OSX Snow Leopard torrent opening problem // Level 4: 4208 - fix for OSX Snow Leopard torrent opening problem and UI hang on torrent with Tor URL add public static final int PATCH_LEVEL = 4; public static int getCurrentPatchLevel() { return( PATCH_LEVEL ); } } azureus-4.3.0.6/org/gudy/azureus2/update/UpdaterUpdateChecker.java0000644000175000017500000000325310625431442024342 0ustar adrianadrian/* * Created on 07-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.update; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.plugins.*; // Note this is unloadable because it shouldn't be loaded in the first place // Hence, on upgrade, a restart isn't required public class UpdaterUpdateChecker implements UnloadablePlugin { public static String getPluginID() { return( UpdaterUtils.AZUPDATER_PLUGIN_ID ); } public void initialize( PluginInterface pi ) { Properties props = pi.getPluginProperties(); props.setProperty( "plugin.mandatory", "true" ); if ( pi.getPluginVersion() == null ){ props.setProperty( "plugin.version", "1.0" ); } props.setProperty( "plugin.id", "azupdater" ); } public void unload() { } }azureus-4.3.0.6/org/gudy/azureus2/update/UpdaterUtils.java0000644000175000017500000001247211142504352022732 0ustar adrianadrian/* * Created on May 31, 2006 1:21:29 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.update; import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import com.aelitis.azureus.core.AzureusCoreFactory; import org.gudy.azureus2.plugins.PluginInterface; /** * Utility functions for Updater Plugin. *

      * Moved from UpdateUpdateChecker to reduce (cyclical) references */ public class UpdaterUtils { public static String AZUPDATER_PLUGIN_ID = "azupdater"; public static String AZUPDATERPATCHER_PLUGIN_ID = "azupdaterpatcher"; protected static String AZUPNPAV_PLUGIN_ID = "azupnpav"; public static boolean disableNativeCode( String version ) { try { File plugin_dir = null; // we can't check the user-dir here due to crazy recursion problems // during startup (platform manager init etc) File shared_plugin_dir = FileUtil.getApplicationFile("plugins"); File shared_updater_plugin = new File(shared_plugin_dir, AZUPDATER_PLUGIN_ID); if (shared_updater_plugin.exists()) { plugin_dir = shared_updater_plugin; } if ( plugin_dir == null ){ return (false); } return (new File(plugin_dir, "disnat" + version).exists()); } catch (Throwable e) { e.printStackTrace(); } return (false); } public static void checkBootstrapPlugins() { try{ File target_props = getPropsIfNotPresent( AZUPDATER_PLUGIN_ID, true ); if ( target_props != null ){ writePluginProperties( target_props, new String[]{ "plugin.class=org.gudy.azureus2.update.UpdaterUpdateChecker;org.gudy.azureus2.update.UpdaterPatcher", "plugin.name=Azureus Update Support;Azureus Updater Support Patcher" }); } // has to go into USER dir as currently VISTA plugin install into shared is BROKEN! target_props = getPropsIfNotPresent( AZUPNPAV_PLUGIN_ID, false ); if ( target_props != null ){ writePluginProperties( target_props, new String[]{ "plugin.class=com.aelitis.azureus.plugins.upnpmediaserver.UPnPMediaServer", "plugin.name=UPnP Media Server", "plugin.id=azupnpav" }); } }catch( Throwable e){ Debug.printStackTrace(e); } } public static boolean ensurePluginPresent( String id, String cla, String name ) { File target_props = getPropsIfNotPresent( id, false ); if ( target_props != null ){ writePluginProperties( target_props, new String[]{ "plugin.class=" + cla, "plugin.name=" + name, "plugin.id=" + id }); return( true ); } return( false ); } protected static void writePluginProperties( File target, String[] lines ) { try{ PrintWriter pw = null; try{ pw = new PrintWriter(new FileWriter(target)); for (int i=0;i 0) { rd.reportActivity("Adding update action for '" + name + "'"); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "PlatformManager:Win32 adding action for '" + name + "'")); installer.addResource(name, zip, false); installer.addMoveAction(name, installer.getInstallDir() + File.separator + name); } } } } catch (Throwable e) { rd.reportActivity("Update install failed:" + e.getMessage()); }finally{ if ( zip != null ){ try{ zip.close(); }catch( Throwable e ){ } } } } protected List splitMultiLine( String indent, String text ) { int pos = 0; String lc_text = text.toLowerCase(); List lines = new ArrayList(); while( true ){ String line; int p1 = lc_text.indexOf( "
      ", pos ); if ( p1 == -1 ){ line = text.substring(pos); }else{ line = text.substring(pos,p1); pos = p1+4; } lines.add( indent + line ); if ( p1 == -1 ){ break; } } return( lines ); } } azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/0000755000175000017500000000000011310377634022211 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/AEWin32AccessListener.java0000644000175000017500000000231610653601462027014 0ustar adrianadrian/* * Created on 30-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.win32.access; public interface AEWin32AccessListener { public static final int ET_SHUTDOWN = 0x0001; public static final int ET_SUSPEND = 0x0002; public static final int ET_RESUME = 0x0003; public void eventOccurred( int type ); } azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/0000755000175000017500000000000011310377634023152 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessImpl.java0000644000175000017500000003047111237540562027076 0ustar adrianadrian/* * Created on Apr 16, 2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.win32.access.impl; /** * @author parg * */ import java.io.File; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.*; // don't use any core stuff in here as we need this access stub to be able to run in isolation import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.platform.PlatformManagerPingCallback; import org.gudy.azureus2.platform.win32.access.*; import com.aelitis.azureus.util.MapUtils; public class AEWin32AccessImpl implements AEWin32Access, AEWin32AccessCallback { protected static AEWin32AccessImpl singleton; public static synchronized AEWin32Access getSingleton( boolean fully_initialise ) { if ( singleton == null ){ singleton = new AEWin32AccessImpl(fully_initialise); } return( singleton ); } private boolean fully_initialise; private int trace_id_next = new Random().nextInt(); private List listeners = new ArrayList(); protected AEWin32AccessImpl( boolean _fully_initialise ) { fully_initialise = _fully_initialise; if ( isEnabled()){ AEWin32AccessInterface.load( this, fully_initialise ); } } public boolean isEnabled() { return( AEWin32AccessInterface.isEnabled( fully_initialise )); } public long windowsMessage( int msg, int param1, long param2 ) { int type = -1; if ( msg == AEWin32AccessInterface.WM_ENDSESSION ){ type = AEWin32AccessListener.ET_SHUTDOWN; }else if ( msg == AEWin32AccessInterface.WM_POWERBROADCAST ){ if ( param1 == AEWin32AccessInterface.PBT_APMQUERYSUSPEND ){ type = AEWin32AccessListener.ET_SUSPEND; }else if ( param1 == AEWin32AccessInterface.PBT_APMRESUMESUSPEND ){ type = AEWin32AccessListener.ET_RESUME; } } if ( type != -1 ){ for (int i=0;i>24), (byte)(address>>16),(byte)(address>>8),(byte)address }; try{ InetAddress res = InetAddress.getByAddress(bytes); return( res ); }catch( UnknownHostException e ){ return( null ); } } public void addListener( AEWin32AccessListener listener ) { listeners.add( listener ); } public void removeListener( AEWin32AccessListener listener ) { listeners.remove( listener ); } protected class traceRouteCallback implements AEWin32AccessCallback { private boolean ping_mode; private PlatformManagerPingCallback cb; protected traceRouteCallback( boolean _ping_mode, PlatformManagerPingCallback _cb ) { ping_mode = _ping_mode; cb = _cb; } public long windowsMessage( int msg, int param1, long param2 ) { return(0); } public long generalMessage( String msg ) { StringTokenizer tok = new StringTokenizer( msg, "," ); int ttl = Integer.parseInt( tok.nextToken().trim()); int time = -1; InetAddress address; if ( tok.hasMoreTokens()){ int i_addr = Integer.parseInt( tok.nextToken().trim()); address = intToAddress( i_addr ); time = Integer.parseInt( tok.nextToken().trim()); //boolean is_udp = Integer.parseInt( tok.nextToken().trim()) == 1; // System.out.println( "udp = " + is_udp ); }else{ address = null; } return( cb.reportNode( ping_mode?-1:ttl, address, time )?1:0 ); } } public File[] getUSBDrives() { ArrayList listUSB = new ArrayList(); try { List availableDrives = AEWin32AccessInterface.getAvailableDrives(); if (availableDrives != null) { for (Object object : availableDrives) { File f = (File) object; Map driveInfo = AEWin32AccessInterface.getDriveInfo(f.getPath().charAt(0)); if (driveInfo != null) { boolean removeable = MapUtils.getMapBoolean(driveInfo, "Removable", false); // values GetDriveType long driveType = MapUtils.getMapLong(driveInfo, "DriveType", 0); // values STORAGE_BUS_TYPE long busType = MapUtils.getMapLong(driveInfo, "BusType", 0); // values MEDIA_TYPE long mediaType = MapUtils.getMapLong(driveInfo, "MediaType", 0); if (removeable && driveType == 2 && busType == 7 && mediaType == 11) { listUSB.add(f); } } } } return listUSB.toArray(new File[0]); } catch (UnsatisfiedLinkError ue) { Debug.outNoStack("Old aereg.dll"); } catch (Throwable e) { Debug.out(e); } return new File[0]; } } azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/aereg.sln0000644000175000017500000000155311236406276024761 0ustar adrianadrian Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aereg", "aereg.vcproj", "{283DCBCD-6013-4E01-87BC-A105A07AEB50}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {283DCBCD-6013-4E01-87BC-A105A07AEB50}.Debug|Win32.ActiveCfg = Debug|Win32 {283DCBCD-6013-4E01-87BC-A105A07AEB50}.Debug|Win32.Build.0 = Debug|Win32 {283DCBCD-6013-4E01-87BC-A105A07AEB50}.Release|Win32.ActiveCfg = Release|Win32 {283DCBCD-6013-4E01-87BC-A105A07AEB50}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessExceptionImpl.java0000644000175000017500000000241611012742464030747 0ustar adrianadrian/* * Created on Apr 16, 2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.win32.access.impl; /** * @author parg * */ import org.gudy.azureus2.platform.win32.access.*; public class AEWin32AccessExceptionImpl extends AEWin32AccessException { public AEWin32AccessExceptionImpl( String operation, String message ) { super(operation + ":" + message); } } azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessCallback.java0000644000175000017500000000222210525024526027656 0ustar adrianadrian/* * Created on 26-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.win32.access.impl; public interface AEWin32AccessCallback { public long windowsMessage( int msg, int param1, long param2 ); public long generalMessage( String msg ); } azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/Debug/0000755000175000017500000000000011310377420024171 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/aereg.dsp0000644000175000017500000001141310527476620024751 0ustar adrianadrian# Microsoft Developer Studio Project File - Name="aereg" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=aereg - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "aereg.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "aereg.mak" CFG="aereg - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "aereg - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "aereg - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "aereg - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "AEREG_EXPORTS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "C:\JDK1.4\include" /I "C:\JDK1.4\include\win32" /I "C:\j2sdk1.4.2_04\include" /I "C:\j2sdk1.4.2_04\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "UNICODE" /D "_USRDLL" /D "AEREG_EXPORTS" /FR /Yu"stdafx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "NDEBUG" # ADD RSC /l 0x809 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib shlwapi.lib Ws2_32.lib /nologo /dll /machine:I386 !ELSEIF "$(CFG)" == "aereg - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "AEREG_EXPORTS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "C:\j2sdk1.4.2_04\include" /I "C:\j2sdk1.4.2_04\include\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "AEREG_EXPORTS" /FR /Yu"stdafx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "_DEBUG" # ADD RSC /l 0x809 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 Ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib shlwapi.lib /nologo /dll /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "aereg - Win32 Release" # Name "aereg - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\aenet.cpp # End Source File # Begin Source File SOURCE=.\aereg.cpp # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"stdafx.h" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=.\aenet.h # End Source File # Begin Source File SOURCE=.\aereg.h # End Source File # Begin Source File SOURCE=.\org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface.h # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # Begin Source File SOURCE=.\ReadMe.txt # End Source File # End Target # End Project azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/aedevice.cpp0000644000175000017500000001451111236406276025427 0ustar adrianadrian #include "stdafx.h" #include #include #include #include "org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface.h" BOOL GetDriveGeometry(HANDLE hDevice, DISK_GEOMETRY *pdg) { BOOL bResult; // results flag DWORD junk; // discard results bResult = DeviceIoControl(hDevice, // device to be queried IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform NULL, 0, // no input buffer pdg, sizeof(*pdg), // output buffer &junk, // # bytes returned (LPOVERLAPPED) NULL); // synchronous I/O return (bResult); } BOOL GetStorageProperty(HANDLE hDevice, PSTORAGE_DEVICE_DESCRIPTOR *p) { DWORD junk; // discard results STORAGE_PROPERTY_QUERY Query; // input param for query // specify the query type Query.PropertyId = StorageDeviceProperty; Query.QueryType = PropertyStandardQuery; BOOL res = DeviceIoControl(hDevice, // device handle IOCTL_STORAGE_QUERY_PROPERTY, // info of device property &Query, sizeof(STORAGE_PROPERTY_QUERY), // input data buffer *p, (*p)->Size, // output data buffer &junk, // out's length (LPOVERLAPPED)NULL); return (res); } JNIEXPORT jobject JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getAvailableDrives (JNIEnv *env, jclass cla) { DISK_GEOMETRY pdg; // disk drive geometry structure BOOL bResult; // generic results flag ULONGLONG DiskSize; // size of the drive, in bytes HANDLE hDevice; // create List jclass clsArrayList = env->FindClass("java/util/ArrayList"); jmethodID constArrayList = env->GetMethodID(clsArrayList, "", "()V"); jobject arrayList = env->NewObject(clsArrayList, constArrayList, ""); jmethodID methAdd = env->GetMethodID(clsArrayList, "add", "(Ljava/lang/Object;)Z"); // each bit returned is one drive, starting with "A:" DWORD dwLogicalDrives = GetLogicalDrives(); for ( int nDrive = 0; nDrive<32; nDrive++ ) { if ( (dwLogicalDrives & (1 << nDrive)) == 0 ) { continue; } // Do an aditional check by using GetDriveGeometry. If it fails, then there's // no "disk" in the drive WCHAR drive[100]; wsprintfW(drive, L"\\\\.\\%C:", 'a' + nDrive); hDevice = CreateFileW((LPCWSTR) drive, // drive to open 0, // no access to the drive FILE_SHARE_READ | // share mode FILE_SHARE_WRITE, NULL, // default security attributes OPEN_EXISTING, // disposition 0, // file attributes NULL); // do not copy file attributes char drive2[4]; wsprintfA(drive2, "%C:\\", 'a' + nDrive); if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive { continue; } bResult = GetDriveGeometry (hDevice, &pdg); if (bResult) { // Create File jclass cls = env->FindClass("java/io/File"); jmethodID constructor = env->GetMethodID(cls, "", "(Ljava/lang/String;)V"); jobject object = env->NewObject(cls, constructor, env->NewStringUTF(drive2)); // add to list env->CallBooleanMethod( arrayList, methAdd, object ); } CloseHandle(hDevice); } return arrayList; } void addToMap(JNIEnv *env, jobject hashMap, jmethodID methPut, jclass clsLong, jmethodID longInit, char *key, jlong val) { jobject longObj = env->NewObject(clsLong, longInit, val); env->CallObjectMethod(hashMap, methPut, env->NewStringUTF(key), longObj); } void addToMap(JNIEnv *env, jobject hashMap, jmethodID methPut, jclass clsLong, jmethodID longInit, char *key, char *val) { env->CallObjectMethod(hashMap, methPut, env->NewStringUTF(key), env->NewStringUTF(val)); } JNIEXPORT jobject JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getDriveInfo (JNIEnv *env, jclass cla, jchar driveLetter) { jclass clsHashMap = env->FindClass("java/util/HashMap"); jmethodID constHashMap = env->GetMethodID(clsHashMap, "", "()V"); jobject hashMap = env->NewObject(clsHashMap, constHashMap, ""); jmethodID methPut = env->GetMethodID(clsHashMap, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); jclass clsLong = env->FindClass("java/lang/Long"); jmethodID longInit = env->GetMethodID(clsLong, "", "(J)V"); DISK_GEOMETRY pdg; // disk drive geometry structure BOOL bResult; // generic results flag ULONGLONG DiskSize; // size of the drive, in bytes HANDLE hDevice; WCHAR drive[100]; wsprintf(drive, L"\\\\.\\%C:", driveLetter); hDevice = CreateFile((LPCWSTR) drive, // drive to open 0, // no access to the drive FILE_SHARE_READ | // share mode FILE_SHARE_WRITE, NULL, // default security attributes OPEN_EXISTING, // disposition 0, // file attributes NULL); // do not copy file attributes WCHAR drive2[4]; wsprintf(drive2, L"%C:\\", driveLetter); DWORD uType = GetDriveType(drive2); addToMap(env, hashMap, methPut, clsLong, longInit, "DriveType", (jlong) uType); if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive { return hashMap; } bResult = GetDriveGeometry (hDevice, &pdg); if (bResult) { ULONG diskSize = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder * (ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector; addToMap(env, hashMap, methPut, clsLong, longInit, "MediaType", (jlong) pdg.MediaType); addToMap(env, hashMap, methPut, clsLong, longInit, "DiskSize", (jlong) diskSize); } char OutBuf[1024] = {0}; // good enough, usually about 100 bytes PSTORAGE_DEVICE_DESCRIPTOR pDevDesc = (PSTORAGE_DEVICE_DESCRIPTOR)OutBuf; pDevDesc->Size = sizeof(OutBuf); bResult = GetStorageProperty(hDevice, &pDevDesc); if (bResult) { addToMap(env, hashMap, methPut, clsLong, longInit, "BusType", (jlong) pDevDesc->BusType); addToMap(env, hashMap, methPut, clsLong, longInit, "DeviceType", (jlong) pDevDesc->DeviceType); addToMap(env, hashMap, methPut, clsLong, longInit, "Removable", (jlong) pDevDesc->RemovableMedia); if (pDevDesc->VendorIdOffset != 0) { addToMap(env, hashMap, methPut, clsLong, longInit, "VendorID", &OutBuf[pDevDesc->VendorIdOffset]); } if (pDevDesc->ProductIdOffset != 0) { addToMap(env, hashMap, methPut, clsLong, longInit, "ProductID", &OutBuf[pDevDesc->ProductIdOffset]); } } STORAGE_BUS_TYPE t; CloseHandle(hDevice); return hashMap; }azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/aereg.vcproj0000644000175000017500000001704711236406276025475 0ustar adrianadrian azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/StdAfx.cpp0000644000175000017500000000044410040345110025030 0ustar adrianadrian// stdafx.cpp : source file that includes just the standard includes // aereg.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "stdafx.h" // TODO: reference any additional headers you need in STDAFX.H // and not in this file azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/aereg.dsw0000644000175000017500000000102510040345110024731 0ustar adrianadrianMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "aereg"=.\aereg.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/aenet.cpp0000644000175000017500000004047610752765344024775 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ #include "stdafx.h" #include "stdio.h" #include "stdlib.h" #include "windows.h" #include "time.h" #include "winsock2.h" #include "WS2TCPIP.H" #include "aereg.h" #include "aenet.h" #include "org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface.h" // IP ftp://ftp.rfc-editor.org/in-notes/rfc791.txt // ICMP ftp://ftp.rfc-editor.org/in-notes/rfc792.txt // UDP ftp://ftp.rfc-editor.org/in-notes/rfc768.txt bool winsock_started_up = false; void initialiseWinsock() { if ( !winsock_started_up ){ winsock_started_up = true; WSADATA wdData; WSAStartup(MAKEWORD(2, 2), &wdData); } } unsigned short calculateChecksum( unsigned short const words[], int num_words ) { unsigned long sum = 0; while (num_words-- > 0){ sum += *(words++); } sum = (sum >> 16) + (sum & 0xFFFF); sum += sum >> 16; unsigned short result = ((unsigned short) ~sum); if ( result == 0 ){ result = 0xffff; } return( result ); } unsigned short calculateChecksum2( unsigned short const words1[], int num_words1, unsigned short const words2[], int num_words2 ) { unsigned long sum = 0; while (num_words1-- > 0){ sum += *(words1++); } while (num_words2-- > 0){ sum += *(words2++); } sum = (sum >> 16) + (sum & 0xFFFF); sum += sum >> 16; unsigned short result = ((unsigned short) ~sum); if ( result == 0 ){ result = 0xffff; } return( result ); } int sendTraceRouteMessage( JNIEnv* env, unsigned short trace_id, int time_to_live, unsigned int send_sock, unsigned int recv_sock, unsigned long source_ip, unsigned short source_port, unsigned long target_ip, unsigned short target_port, bool use_udp, bool use_icmp ) { // Advice is to use UDP rather than ICMP echos. However, reality is that UDP packets can be totally dropped with no ICMP response. So send both... // UDP if ( use_udp ){ udp_probe_packet udp_probe; struct sockaddr_in target; memset( &target, 0, sizeof( target )); target.sin_family = AF_INET; target.sin_addr.s_addr = htonl( target_ip ); target.sin_port = htons( target_port ); // printf( "Sending to %lx from %lx: ip=%d,udp=%d,tot=%d\n", target_ip, source_ip, sizeof( ip_header ), sizeof( udp_header ), sizeof( probe_packet )); memset( &udp_probe, 0, sizeof( udp_probe )); udp_probe.ip.ip_version = 4; udp_probe.ip.ip_header_len = sizeof( ip_header) >> 2; udp_probe.ip.tos = 0; udp_probe.ip.total_len = htons( sizeof( udp_probe_packet )); udp_probe.ip.ident = htons( trace_id ); udp_probe.ip.frag_and_flags = 0; udp_probe.ip.ttl = time_to_live; udp_probe.ip.protocol = IPPROTO_UDP; udp_probe.ip.checksum = 0; udp_probe.ip.source_ip = htonl( source_ip ); udp_probe.ip.dest_ip = htonl( target_ip ); udp_probe.ip.checksum = calculateChecksum((unsigned short*)&udp_probe.ip, sizeof( ip_header ) / 2 ); udp_probe.udp.source_port = htons( source_port ); udp_probe.udp.dest_port = htons( target_port ); udp_probe.udp.data_len = htons( sizeof( udp_probe_packet ) - sizeof( ip_header )); udp_probe.udp.checksum = 0; udp_probe.data = 1234; pseudo_udp_header puh; puh.source_ip = htonl( source_ip ); puh.dest_ip = htonl( target_ip ); puh.zero = 0; puh.protocol = IPPROTO_UDP; puh.data_len = htons( sizeof( udp_probe_packet ) - sizeof( ip_header )); udp_probe.udp.checksum = calculateChecksum2( (unsigned short*)&puh, sizeof( pseudo_udp_header ) / 2, (unsigned short *)&udp_probe.udp, (sizeof( udp_probe ) - sizeof( ip_header ))/2); /* char* bytes = (char *)&probe; for (int i=0;i> 2; icmp_probe.ip.tos = 0; icmp_probe.ip.total_len = htons( sizeof( icmp_probe_packet )); icmp_probe.ip.ident = htons( trace_id ); icmp_probe.ip.frag_and_flags = 0; icmp_probe.ip.ttl = time_to_live; icmp_probe.ip.protocol = IPPROTO_ICMP; icmp_probe.ip.checksum = 0; icmp_probe.ip.source_ip = htonl( source_ip ); icmp_probe.ip.dest_ip = htonl( target_ip ); icmp_probe.ip.checksum = calculateChecksum((unsigned short*)&icmp_probe.ip, sizeof( ip_header ) / 2 ); icmp_probe.icmp.type = ICMP_TYPE_ECHO; icmp_probe.icmp.code = 0; icmp_probe.icmp.checksum = 0; icmp_probe.icmp.ident = htons( trace_id ); icmp_probe.icmp.sequence = htons( target_port ); icmp_probe.icmp.checksum = calculateChecksum( (unsigned short*)&icmp_probe.icmp, sizeof( icmp_echo_header ) / 2 ); /* char* bytes = (char *)&probe; for (int i=0;iNewStringUTF( msg ); if ( j_msg == NULL ){ throwException( env, "NewStringUTF", "alloc failed" ); return 0; } int res = 0; jclass callback_class = env->GetObjectClass( callback ); if ( callback_class == NULL ){ throwException( env, "GetObjectClass", "failed" ); return 0; }else{ jmethodID method = env->GetMethodID( callback_class, "generalMessage", "(Ljava/lang/String;)J"); if ( method == NULL ){ throwException( env, "GetMethodID", "method not found" ); }else{ res = (long)env->CallLongMethod( callback, method, j_msg ); } env->DeleteLocalRef( callback_class ); } env->ReleaseStringUTFChars( j_msg, msg ); return( res ); } int traceRouteReportTimeout( JNIEnv *env, jobject callback, int ttl ) { char buffer[1024]; sprintf( buffer, "%ld", ttl ); return( traceRouteReport( env, callback, buffer )); } int traceRouteReportResult( JNIEnv *env, jobject callback, int ttl, unsigned long address, int time, bool udp ) { char buffer[1024]; sprintf( buffer, "%d, %ld, %d, %d", ttl, address, time, udp?1:0 ); return( traceRouteReport( env, callback, buffer )); } void traceRoute( JNIEnv* env, jobject callback, unsigned short trace_id, unsigned long source_ip, unsigned long target_ip, unsigned int send_sock, unsigned int receive_sock, bool ping_mode ) { char receive_buffer[ sizeof(ip_header) + sizeof(icmp_header) + 1024]; unsigned short source_port = TRACE_ROUTE_BASE_PORT; unsigned short target_port = TRACE_ROUTE_BASE_PORT; int seq = 0; int consec_bad = 0; bool complete = false; bool use_udp = true; bool use_icmp = true; int ttl; if ( ping_mode ){ ttl = 32; }else{ ttl = 0; } while( ttl < 33 && ( ping_mode || !complete )){ complete = false; if ( ping_mode ){ if ( consec_bad > 256 ){ throwException( env, "error", "too many consecutive bad packets in ping mode" ); return; } }else{ ttl++; } // try each node up to 3 times bool probe_successful = false; for (int probe_count=0; probe_count<3 && !( complete || probe_successful); probe_count++){ int probe_sequence = seq++; if ( !sendTraceRouteMessage( env, trace_id, ttl, send_sock, receive_sock, source_ip, source_port, target_ip, target_port + probe_sequence, use_udp, use_icmp )){ // send failed, exception already reported return; } unsigned long start_ticks = 0; while( !complete ){ int receive_timeout = PROBE_TIMEOUT; unsigned long current_ticks = GetTickCount(); if ( start_ticks == 0 ){ start_ticks = current_ticks; }else{ receive_timeout -= ( current_ticks - start_ticks ); } if ( receive_timeout <= 0 ){ if ( !traceRouteReportTimeout( env, callback, ttl )){ return; } consec_bad = 0; break; } if( setsockopt(receive_sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &receive_timeout, sizeof(receive_timeout)) == SOCKET_ERROR ){ throwException( env, "setsockopt", "failed to set receive timeout socket options" ); return; } struct sockaddr_in from; int from_len = sizeof( from ); unsigned int read_len = recvfrom( receive_sock, receive_buffer, sizeof( receive_buffer ), 0, (struct sockaddr *)&from, &from_len ); if ( read_len == SOCKET_ERROR ){ if ( WSAGetLastError() == WSAETIMEDOUT ){ if ( !traceRouteReportTimeout( env, callback, ttl )){ return; } consec_bad = 0; break; }else{ throwException( env, "recvfrom", "operation failed", WSAGetLastError()); return; } }else{ if ( read_len < sizeof( 4 )){ // printf( "invalid packet read - length < 4\n" ); consec_bad++; continue; } ip_header *ip = (ip_header *)receive_buffer; unsigned char ip_len = ip->ip_header_len << 2; unsigned short total_len = ntohs( ip->total_len ); // ensure we have a whole packet and an icmp reply if ( read_len != total_len || read_len < ip_len + sizeof(icmp_header)){ // printf( "invalid packet read - read_len != total_len\n" ); consec_bad++; continue; } int elapsed_time = (int)( GetTickCount() - current_ticks ); icmp_header *icmp = (icmp_header *)(receive_buffer + ip_len ); unsigned char icmp_type = icmp->type; if ( icmp_type == ICMP_TYPE_ECHO_REPLY ){ icmp_echo_header *icmp = (icmp_echo_header *)(receive_buffer + ip_len ); unsigned short reply_seq = ntohs( icmp->sequence ) - TRACE_ROUTE_BASE_PORT; if ( reply_seq != probe_sequence ){ consec_bad++; continue; } if ( !traceRouteReportResult( env, callback, ttl, ntohl( from.sin_addr.s_addr ), elapsed_time, false )){ return; } consec_bad = 0; if ( ping_mode ){ use_udp = false; } complete = true; break; } if ( read_len != total_len || read_len < ip_len + sizeof(icmp_header) + sizeof( ip_header ) + 2){ // printf( "invalid packet read - read_len != total_len\n" ); consec_bad++; continue; } ip_header* old_ip = (ip_header *)(receive_buffer + ip_len + sizeof( icmp_header )); if ( icmp_type != ICMP_TYPE_TTL_EXCEEDED && icmp_type != ICMP_TYPE_UNREACHABLE ){ // printf( "Unexpected ICMP reply type %d\n", icmp_type ); consec_bad++; continue; } if ( trace_id != ntohs(old_ip->ident )){ // not our reply consec_bad++; continue; } bool reply_was_udp; if ( old_ip->protocol == IPPROTO_ICMP ){ icmp_probe_packet* probe = (icmp_probe_packet *)(receive_buffer + ip_len + sizeof( icmp_header )); unsigned short reply_seq = ntohs( probe->icmp.sequence ) - TRACE_ROUTE_BASE_PORT; if ( reply_seq != probe_sequence ){ consec_bad++; continue; } reply_was_udp = false; }else{ udp_probe_packet* probe = (udp_probe_packet *)(receive_buffer + ip_len + sizeof( icmp_header )); unsigned short reply_seq = ntohs( probe->udp.dest_port ) - TRACE_ROUTE_BASE_PORT; if ( reply_seq != probe_sequence ){ consec_bad++; continue; } reply_was_udp = true; } probe_successful = true; if ( icmp_type == ICMP_TYPE_ECHO_REPLY ){ complete = true; }else if ( icmp_type == ICMP_TYPE_TTL_EXCEEDED ){ }else if ( icmp_type == ICMP_TYPE_UNREACHABLE ){ unsigned char icmp_code = icmp->code; if ( icmp_code == ICMP_CODE_PROTOCOL_UNREACHABLE || icmp_code == ICMP_CODE_PORT_UNREACHABLE ){ // these are received from the target host complete = true; }else{ } } if ( ping_mode ){ if ( reply_was_udp ){ use_icmp = false; }else{ use_udp = false; } } if ( !traceRouteReportResult( env, callback, ttl, ntohl( from.sin_addr.s_addr ), elapsed_time, reply_was_udp )){ return; } consec_bad = 0; break; } } } } return; } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_traceRoute( JNIEnv* env, jclass cla, jint trace_id, jint source_ip, jint target_ip, jint ping_mode, jobject callback ) { initialiseWinsock(); int receive_sock = socket( AF_INET, SOCK_RAW, IPPROTO_ICMP ); if ( receive_sock == SOCKET_ERROR ) { throwException( env, "socket", "failed to create receive socket" ); return; } int receive_timeout = PROBE_TIMEOUT; if( setsockopt(receive_sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &receive_timeout, sizeof(receive_timeout)) == SOCKET_ERROR ){ closesocket(receive_sock); throwException( env, "setsockopt", "failed to set receive timeout socket options" ); return; } int so_reuseaddress = 1; if( setsockopt(receive_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &so_reuseaddress, sizeof(so_reuseaddress)) == SOCKET_ERROR ){ closesocket(receive_sock); throwException( env, "setsockopt", "failed to set receive reuse address socket options" ); return; } // we have to bind the socket before we can receive ICMP messages on it struct sockaddr_in recv_bind_addr; recv_bind_addr.sin_family = AF_INET; recv_bind_addr.sin_addr.s_addr = htonl( source_ip ); recv_bind_addr.sin_port = 0; if ( bind( receive_sock, (struct sockaddr *)&recv_bind_addr, sizeof( recv_bind_addr )) == SOCKET_ERROR ){ closesocket(receive_sock); throwException( env, "socket", "failed to bind send socket" ); return; } int send_sock = socket( AF_INET, SOCK_RAW, IPPROTO_RAW ); if ( send_sock == SOCKET_ERROR ) { closesocket(receive_sock); throwException( env, "socket", "failed to create send socket" ); return; } int enable = 1; if ( setsockopt(send_sock, IPPROTO_IP, IP_HDRINCL, (char *)&enable,sizeof(enable)) == SOCKET_ERROR ){ closesocket(send_sock); closesocket(receive_sock); throwException( env, "setsockopt", "failed to set receive socket options" ); return; } traceRoute( env, callback, (unsigned short)trace_id, (unsigned long)source_ip, (unsigned long)target_ip, send_sock, receive_sock, ping_mode==1?true:false ); closesocket(send_sock); closesocket(receive_sock); } azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/Release/0000755000175000017500000000000011310377420024523 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/aereg.cpp0000644000175000017500000013342311236406276024751 0ustar adrianadrian/* * Created on Apr 16, 2004 * Created by Paul Gardner * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ #include "stdafx.h" #include "aereg.h" #include "stdio.h" #include "stdlib.h" #include "windows.h" #include "shlwapi.h" #include "process.h" #include "shellapi.h" #include "org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface.h" #define VERSION "1.18" HMODULE application_module; bool non_unicode = false; jclass AEWin32AccessInterface_class; jclass AEWin32AccessExceptionImpl_class; UINT uThreadId; HINSTANCE hInstance; LRESULT CALLBACK WndProcW(HWND, UINT, WPARAM, LPARAM); void RegisterWindowClassW(); LRESULT CALLBACK WndProcA(HWND, UINT, WPARAM, LPARAM); void RegisterWindowClassA(); HRESULT callback(UINT Msg, WPARAM wParam, LPARAM lParam) ; JavaVM* jvm; BOOL APIENTRY DllMain( HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { hInstance = hModule; OSVERSIONINFOA osvi; application_module = (HMODULE)hModule; osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); GetVersionExA(&osvi); non_unicode = ( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ); if ( non_unicode ){ RegisterWindowClassA(); }else{ RegisterWindowClassW(); } break; } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } CAereg::CAereg() { return; } void throwException( JNIEnv* env, char* operation, char* message ) { bool ok = false; if ( AEWin32AccessExceptionImpl_class != NULL ){ jmethodID method = env->GetMethodID( AEWin32AccessExceptionImpl_class, "", "(Ljava/lang/String;Ljava/lang/String;)V" ); if ( method != NULL ){ jobject new_object = env->NewObject( AEWin32AccessExceptionImpl_class, method, env->NewStringUTF((const char*)operation), env->NewStringUTF((const char*)message )); if ( new_object != NULL ){ env->Throw( (jthrowable)new_object ); ok = true; } }else{ fprintf( stderr, "AEWin32AccessInterface: failed to resolve constructor" ); } } if ( !ok ){ fprintf( stderr, "AEWin32AccessInterface: failed to throw exception %s: %s\n", operation, message ); } } void throwException( JNIEnv* env, char* operation, char* message, int error_code ) { char buffer[4096]; sprintf( buffer, "%s (error_code=%d)", message, error_code ); throwException( env, operation, buffer ); } HKEY mapHKEY( JNIEnv* env, jint _type ) { if ( _type == org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_HKEY_CLASSES_ROOT ){ return( HKEY_CLASSES_ROOT ); }else if ( _type == org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_HKEY_CURRENT_CONFIG ){ return( HKEY_CURRENT_CONFIG ); }else if ( _type == org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_HKEY_LOCAL_MACHINE ){ return( HKEY_LOCAL_MACHINE ); }else if ( _type == org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_HKEY_CURRENT_USER ){ return( HKEY_CURRENT_USER ); }else{ throwException( env, "readValue", "unsupported type" ); return( NULL ); } } // ****************************** bool jstringToCharsW( JNIEnv *env, jstring jstr, WCHAR *chars, int chars_len ) { if ( jstr == NULL ){ chars[0] = 0; }else{ int jdata_len = env->GetStringLength(jstr); if ( jdata_len >= chars_len ){ throwException( env, "jstringToChars", "jstring truncation occurred" ); return( false ); } const jchar *jdata = env->GetStringChars( jstr, NULL ); for (int i=0;iReleaseStringChars( jstr, jdata ); } return( true ); } // WINDOWS HOOK void RegisterWindowClassW() { WNDCLASSEXW wcex; wcex.cbSize = sizeof(WNDCLASSEXW); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProcW; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = 0; wcex.hCursor = 0; wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = 0; wcex.lpszClassName = L"Azureus Window Hook"; wcex.hIconSm = 0; RegisterClassExW(&wcex); } LRESULT CALLBACK WndProcW( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { long res = callback( Msg, wParam, lParam ); if ( res != -1 ){ return( res ); } return DefWindowProcW(hWnd, Msg, wParam, lParam); } unsigned WINAPI CreateWndThreadW( LPVOID pThreadParam) { HWND hWnd = CreateWindowW( L"Azureus Window Hook", NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if( hWnd == NULL){ printf( "Failed to create window\n" ); return( 0 ); }else{ MSG Msg; while(GetMessageW(&Msg, hWnd, 0, 0)) { TranslateMessage(&Msg); DispatchMessageW(&Msg); } return Msg.wParam; } } // void RegisterWindowClassA() { WNDCLASSEXA wcex; wcex.cbSize = sizeof(WNDCLASSEXA); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProcA; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = 0; wcex.hCursor = 0; wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = 0; wcex.lpszClassName = "Azureus Window Hook"; wcex.hIconSm = 0; RegisterClassExA(&wcex); } LRESULT CALLBACK WndProcA( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { long res = callback( Msg, wParam, lParam ); if ( res != -1 ){ return( res ); } return DefWindowProcA(hWnd, Msg, wParam, lParam); } unsigned WINAPI CreateWndThreadA( LPVOID pThreadParam) { HWND hWnd = CreateWindowA( "Azureus Window Hook", NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if( hWnd == NULL){ printf( "Failed to create window\n" ); return( 0 ); }else{ MSG Msg; while(GetMessageA(&Msg, hWnd, 0, 0)) { TranslateMessage(&Msg); DispatchMessageA(&Msg); } return Msg.wParam; } } HRESULT callback( UINT Msg, WPARAM wParam, LPARAM lParam) { JNIEnv *env; if ( jvm->AttachCurrentThread((void **)&env, NULL )){ fprintf( stderr, "failed to attach current thread to JVM\n" ); return( -1 ); } jlong result = -1; if ( AEWin32AccessInterface_class != NULL ){ jint j_msg = Msg; jint j_param1 = wParam; jlong j_param2 = lParam; jmethodID method = env->GetStaticMethodID( AEWin32AccessInterface_class, "callback", "(IIJ)J"); if ( method != NULL ){ result = env->CallStaticLongMethod( AEWin32AccessInterface_class, method, j_msg, j_param1, j_param2 ); }else{ fprintf( stderr, "failed to resolve callback method\n" ); } } jvm->DetachCurrentThread(); return((HRESULT)result ); } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_initialise( JNIEnv *env, jclass cla ) { HANDLE hThread; env->GetJavaVM(&jvm); jclass local_ref = env->FindClass("org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessInterface" ); if ( local_ref == NULL ){ fprintf( stderr, "failed to find AEWin32AccessInterface class\n" ); }else{ AEWin32AccessInterface_class = (jclass)env->NewGlobalRef( local_ref ); env->DeleteLocalRef( local_ref ); } local_ref = env->FindClass( "org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessExceptionImpl" ); if ( local_ref == NULL ){ fprintf( stderr, "failed to find AEWin32AccessExceptionImpl class\n" ); }else{ AEWin32AccessExceptionImpl_class = (jclass)env->NewGlobalRef( local_ref ); env->DeleteLocalRef( local_ref ); } if ( non_unicode ){ hThread = (HANDLE)_beginthreadex(NULL, 0, &CreateWndThreadA, NULL, 0, &uThreadId); }else{ hThread = (HANDLE)_beginthreadex(NULL, 0, &CreateWndThreadW, NULL, 0, &uThreadId); } if(!hThread){ throwException( env, "_beginthreadex", "initialisation failed" ); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_destroy( JNIEnv *env, jclass cla ) { if ( uThreadId ){ PostThreadMessage(uThreadId, WM_QUIT, 0, 0); } } // UNICODE METHODS JNIEXPORT jstring JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getModuleNameW( JNIEnv *env, jclass cla ) { WCHAR buffer[2048]; if ( !GetModuleFileNameW(application_module, buffer, sizeof( buffer ))){ throwException( env, "getModuleName", "GetModuleFileName fails" ); return( NULL ); } return( env->NewString((const jchar *)buffer, wcslen(buffer))); } JNIEXPORT jstring JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getVersionW( JNIEnv *env, jclass cla ) { jstring result = env->NewStringUTF((char *)VERSION); return( result ); } JNIEXPORT jstring JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_readStringValueW( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name ) { HKEY key; HKEY subkey; WCHAR subkey_name[1024]; WCHAR value_name[1024]; jstring result = NULL; key = mapHKEY( env, _type ); if ( key == NULL ){ return( NULL ); } if ( !jstringToCharsW( env, _subkey_name, subkey_name, sizeof( subkey_name ))){ return( NULL ); } if ( !jstringToCharsW( env, _value_name, value_name, sizeof( value_name ))){ return( NULL ); } if ( RegOpenKeyW( key, subkey_name, &subkey ) == ERROR_SUCCESS ){ BYTE value[1024]; DWORD value_length = sizeof( value ); DWORD type; if ( RegQueryValueExW( subkey, value_name, NULL, &type, (unsigned char*)value, &value_length ) == ERROR_SUCCESS){ if ( type == REG_SZ || type == REG_EXPAND_SZ || type == REG_MULTI_SZ ){ if ( type == REG_EXPAND_SZ ){ WCHAR expanded_value[2048]; ExpandEnvironmentStringsW((const WCHAR*)value, expanded_value, sizeof( expanded_value )); result = env->NewString((const jchar *)expanded_value,wcslen(expanded_value)); }else{ result = env->NewString((const jchar *)value,wcslen((WCHAR *)value)); } }else{ throwException( env, "readValue", "type mismach" ); } }else{ throwException( env, "readStringValue", "RegQueryValueEx failed" ); } RegCloseKey(subkey); }else{ throwException( env, "readStringValue", "RegOpenKey failed" ); } return( result ); } JNIEXPORT jint JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_readWordValueW( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name ) { HKEY key; HKEY subkey; WCHAR subkey_name[1024]; WCHAR value_name[1024]; jint result = 0; key = mapHKEY( env, _type ); if ( key == NULL ){ return( NULL ); } if ( !jstringToCharsW( env, _subkey_name, subkey_name, sizeof( subkey_name ))){ return( NULL ); } if ( !jstringToCharsW( env, _value_name, value_name, sizeof( value_name ))){ return( NULL ); } if ( RegOpenKeyW( key, subkey_name, &subkey ) == ERROR_SUCCESS ){ BYTE value[1024]; DWORD value_length = sizeof( value ); DWORD type; if ( RegQueryValueExW( subkey, value_name, NULL, &type, (unsigned char*)value, &value_length ) == ERROR_SUCCESS){ if ( type == REG_DWORD ){ result = (LONG)value[0]; }else{ throwException( env, "readValue", "type mismach" ); } }else{ throwException( env, "readStringValue", "RegQueryValueEx failed" ); } RegCloseKey(subkey); }else{ throwException( env, "readStringValue", "RegOpenKey failed" ); } return(result); } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_writeWordValueW( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name, jint _value_value ) { HKEY key; HKEY subkey; WCHAR subkey_name[1024]; WCHAR value_name[1024]; DWORD value_value = _value_value; key = mapHKEY( env, _type ); if ( key == NULL ){ return; } if ( !jstringToCharsW( env, _subkey_name, subkey_name, sizeof( subkey_name ))){ return; } if ( !jstringToCharsW( env, _value_name, value_name, sizeof( value_name ))){ return; } if ( RegCreateKeyExW( key, subkey_name, 0, REG_NONE, 0, KEY_ALL_ACCESS, NULL, &subkey, NULL ) == ERROR_SUCCESS ){ if ( RegSetValueExW( subkey, value_name, 0, REG_DWORD, (const BYTE*)&value_value, sizeof(DWORD)) == ERROR_SUCCESS){ }else{ throwException( env, "writeWordValue", "RegSetValueEx failed" ); } RegCloseKey(subkey); }else{ throwException( env, "writeWordValue", "RegCreateKeyEx failed" ); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_writeStringValueW( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name, jstring _value_value ) { HKEY key; HKEY subkey; WCHAR subkey_name[1024]; WCHAR value_name[1024]; WCHAR value_value[1024]; key = mapHKEY( env, _type ); if ( key == NULL ){ return; } if ( !jstringToCharsW( env, _subkey_name, subkey_name, sizeof( subkey_name ))){ return; } if ( !jstringToCharsW( env, _value_name, value_name, sizeof( value_name ))){ return; } if ( !jstringToCharsW( env, _value_value, value_value, sizeof( value_value ))){ return; } if ( RegCreateKeyExW( key, subkey_name, 0, REG_NONE, 0, KEY_ALL_ACCESS, NULL, &subkey, NULL ) == ERROR_SUCCESS ){ if ( RegSetValueExW( subkey, value_name, 0, REG_SZ, (const BYTE*)value_value, (wcslen(value_value)+1)*sizeof(WCHAR)) == ERROR_SUCCESS){ }else{ throwException( env, "writeStringValue", "RegSetValueEx failed" ); } RegCloseKey(subkey); }else{ throwException( env, "writeStringValue", "RegCreateKeyEx failed" ); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_deleteKeyW( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jboolean _recursive ) { HKEY key; HKEY subkey; WCHAR subkey_name[1024]; jstring result = NULL; key = mapHKEY( env, _type ); if ( key == NULL ){ return; } if ( !jstringToCharsW( env, _subkey_name, subkey_name, sizeof( subkey_name ))){ return; } if ( RegOpenKeyW( key, subkey_name, &subkey ) == ERROR_SUCCESS ){ RegCloseKey(subkey); if ( _recursive ){ if ( SHDeleteKeyW( key, subkey_name ) != ERROR_SUCCESS ){ throwException( env, "deleteKey", "SHDeleteKey failed" ); } }else{ if ( RegDeleteKeyW( key, subkey_name ) != ERROR_SUCCESS ){ throwException( env, "deleteKey", "RegDeleteKey failed" ); } } } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_deleteValueW( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name ) { HKEY key; HKEY subkey; WCHAR subkey_name[1024]; WCHAR value_name[1024]; jstring result = NULL; key = mapHKEY( env, _type ); if ( key == NULL ){ return; } if ( !jstringToCharsW( env, _subkey_name, subkey_name, sizeof( subkey_name ))){ return; } if ( !jstringToCharsW( env, _value_name, value_name, sizeof( value_name ))){ return; } if ( RegOpenKeyW( key, subkey_name, &subkey ) == ERROR_SUCCESS ){ RegCloseKey(subkey); if ( SHDeleteValueW( key, subkey_name, value_name ) != ERROR_SUCCESS ){ throwException( env, "deleteValue", "SHDeleteValue failed" ); } } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_createProcessW( JNIEnv* env, jclass cla, jstring _command_line, jboolean _inherit_handles ) { WCHAR command_line[16000]; STARTUPINFOW start_info; PROCESS_INFORMATION proc_info; if ( !jstringToCharsW( env, _command_line, command_line, sizeof( command_line ))){ return; } memset( &start_info, 0, sizeof( STARTUPINFO )); start_info.cb = sizeof( STARTUPINFO ); if ( CreateProcessW( NULL, // LPCTSTR lpApplicationName, command_line, // LPTSTR lpCommandLine, NULL, // LPSECURITY_ATTRIBUTES lpProcessAttributes, NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes, _inherit_handles, // BOOL bInheritHandles, DETACHED_PROCESS, // DWORD dwCreationFlags, NULL, // LPVOID lpEnvironment, NULL, // LPCTSTR lpCurrentDirectory, &start_info, // LPSTARTUPINFO lpStartupInfo, &proc_info )){ // LPPROCESS_INFORMATION lpProcessInformation CloseHandle( proc_info.hThread ); CloseHandle( proc_info.hProcess ); }else{ throwException( env, "createProcess", "CreateProcess failed" ); } }; JNIEXPORT jint JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_shellExecAndWaitW( JNIEnv* env, jclass cla, jstring _file, jstring _params ) { WCHAR file[2048]; WCHAR params[2048]; if ( !jstringToCharsW( env, _file, file, sizeof( file ))){ return(0); } if ( !jstringToCharsW( env, _params, params, sizeof( params ))){ return(0); } SHELLEXECUTEINFO shExecInfo; shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT; shExecInfo.hwnd = NULL; shExecInfo.lpVerb = L"runas"; shExecInfo.lpFile = file; shExecInfo.lpParameters = params; shExecInfo.lpDirectory = NULL; shExecInfo.nShow = SW_SHOWNORMAL; shExecInfo.hInstApp = NULL; ShellExecuteExW(&shExecInfo); int res = (int)shExecInfo.hInstApp; if ( res <= 32 ){ throwException( env, "shellExec", "ShellExecW failed", res ); return( 0 ); }else{ HANDLE process = shExecInfo.hProcess; WaitForSingleObject( process, INFINITE ); DWORD result; if ( GetExitCodeProcess( process, &result ) == 0 ){ throwException( env, "shellExec", "GetExitCodeProcess failed", GetLastError()); } CloseHandle( process ); return((jint)result); } }; JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_moveToRecycleBinW( JNIEnv *env, jclass cla, jstring _fileName ) { WCHAR file_name[16000]; SHFILEOPSTRUCTW opFile; if ( !jstringToCharsW( env, _fileName, file_name, sizeof( file_name )-1)){ return; } HANDLE file = CreateFileW ( file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); // Checks if file exists if ( file == INVALID_HANDLE_VALUE ){ throwException( env, "moveToRecycleBin", "file not found" ); return; } CloseHandle(file); file_name[ wcslen(file_name)+1 ] = 0; ZeroMemory(&opFile, sizeof(opFile)); opFile.wFunc = FO_DELETE; opFile.pFrom = file_name; opFile.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_SILENT; if (SHFileOperationW (&opFile)){ throwException( env, "moveToRecycleBin", "SHFileOperation failed" ); } } #define myheapalloc(x) (HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, x)) #define myheapfree(x) (HeapFree(GetProcessHeap(), 0, x)) JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_copyPermissionW( JNIEnv *env, jclass cla, jstring _fileNameIn, jstring _fileNameOut ) { WCHAR file_name_in[2048]; WCHAR file_name_out[2048]; if ( !jstringToCharsW( env, _fileNameIn, file_name_in, sizeof( file_name_in )-1)){ return; } if ( !jstringToCharsW( env, _fileNameOut, file_name_out, sizeof( file_name_out )-1)){ return; } SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION; DWORD cbFileSD = 0; PSECURITY_DESCRIPTOR pFileSD = NULL; BOOL ok = GetFileSecurityW(file_name_in, secInfo, pFileSD, 0, &cbFileSD); // API should have failed with insufficient buffer. if ( ok ){ throwException( env, "copyPermission", "GetFileSecurity ok" ); return; }else if (GetLastError() == ERROR_FILE_NOT_FOUND) { throwException( env, "copyPermission", "from file not found" ); return; }else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { throwException( env, "copyPermission", "GetFileSecurity unexpected response", GetLastError() ); return; }else{ pFileSD = myheapalloc( cbFileSD ); if (!pFileSD) { throwException( env, "copyPermission", "no memory" ); return; } ok = GetFileSecurityW(file_name_in, secInfo, pFileSD, cbFileSD, &cbFileSD ); if (!ok) { myheapfree( pFileSD ); throwException( env, "copyPermission", "GetFileSecurity", GetLastError()); return; } ok = SetFileSecurityW( file_name_out, secInfo, pFileSD ); myheapfree( pFileSD ); if ( !ok ){ if (GetLastError() == ERROR_FILE_NOT_FOUND) { throwException( env, "copyPermission", "to file not found" ); }else{ throwException( env, "copyPermission", "SetFileSecurity unexpected response", GetLastError() ); } } } } JNIEXPORT jboolean JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_testNativeAvailabilityW( JNIEnv *env, jclass cla, jstring _name ) { WCHAR name[2048]; if ( !jstringToCharsW( env, _name, name, sizeof( name )-1)){ return( 0 ); } HMODULE mod = LoadLibraryExW( name, NULL, LOAD_LIBRARY_AS_DATAFILE ); if ( mod == NULL ){ return( 0 ); }else{ FreeLibrary( mod ); return( 1 ); } } // 1.3 JNIEXPORT jint JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_shellExecuteW( JNIEnv *env, jclass cla, jstring _operation, jstring _file, jstring _parameters, jstring _directory, jint _showCmd ) { WCHAR operation[20]; WCHAR file[5192]; WCHAR parameters[16000]; WCHAR directory[5192]; INT showCmd = _showCmd; if ( !jstringToCharsW( env, _operation, operation, sizeof( operation ))){ return -1; } if ( !jstringToCharsW( env, _file, file, sizeof( file ))){ return -1; } if ( !jstringToCharsW( env, _parameters, parameters, sizeof( parameters ))){ return -1; } if ( !jstringToCharsW( env, _directory, directory, sizeof( directory ))){ return -1; } // Not sure if ShellExecute treats "\0" as NULL, so do explicit check return(jint) ShellExecuteW(NULL, _operation == NULL ? NULL : operation, _file == NULL ? NULL : file, _parameters == NULL ? NULL : parameters, _directory == NULL ? NULL : directory, showCmd); } // NON-UNICODE VARIANT FOR WIN95,98,ME bool jstringToCharsA( JNIEnv *env, jstring jstr, char *chars, int chars_len ) { if ( jstr == NULL ){ chars[0] = 0; }else{ int jdata_len = env->GetStringLength(jstr); if ( jdata_len >= chars_len ){ throwException( env, "jstringToChars", "jstring truncation occurred" ); return( false ); } const jchar *jdata = env->GetStringChars( jstr, NULL ); for (int i=0;iReleaseStringChars( jstr, jdata ); } return( true ); } JNIEXPORT jstring JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getModuleNameA( JNIEnv *env, jclass cla ) { char buffer[2048]; if ( !GetModuleFileNameA(application_module, buffer, sizeof( buffer ))){ throwException( env, "getModuleName", "GetModuleFileName fails" ); return( NULL ); } return( env->NewStringUTF((char *)buffer)); } JNIEXPORT jstring JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getVersionA( JNIEnv *env, jclass cla ) { jstring result = env->NewStringUTF((char *)VERSION); return( result ); } JNIEXPORT jstring JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_readStringValueA( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name ) { HKEY key; HKEY subkey; char subkey_name[1024]; char value_name[1024]; jstring result = NULL; key = mapHKEY( env, _type ); if ( key == NULL ){ return( NULL ); } if ( !jstringToCharsA( env, _subkey_name, subkey_name, sizeof( subkey_name ))){ return( NULL ); } if ( !jstringToCharsA( env, _value_name, value_name, sizeof( value_name ))){ return( NULL ); } if ( RegOpenKeyA( key, subkey_name, &subkey ) == ERROR_SUCCESS ){ BYTE value[1024]; DWORD value_length = sizeof( value ); DWORD type; if ( RegQueryValueExA( subkey, value_name, NULL, &type, (unsigned char*)value, &value_length ) == ERROR_SUCCESS){ if ( type == REG_SZ || type == REG_EXPAND_SZ || type == REG_MULTI_SZ ){ if ( type == REG_EXPAND_SZ ){ char expanded_value[2048]; ExpandEnvironmentStringsA((const char*)value, expanded_value, sizeof( expanded_value )); result = env->NewStringUTF((char *)expanded_value); }else{ result = env->NewStringUTF((char *)value); } }else{ throwException( env, "readValue", "type mismach" ); } }else{ throwException( env, "readStringValue", "RegQueryValueEx failed" ); } RegCloseKey(subkey); }else{ throwException( env, "readStringValue", "RegOpenKey failed" ); } return( result ); } JNIEXPORT jint JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_readWordValueA( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name ) { HKEY key; HKEY subkey; char subkey_name[1024]; char value_name[1024]; jint result = 0; key = mapHKEY( env, _type ); if ( key == NULL ){ return( NULL ); } if ( !jstringToCharsA( env, _subkey_name, subkey_name, sizeof( subkey_name ))){ return( NULL ); } if ( !jstringToCharsA( env, _value_name, value_name, sizeof( value_name ))){ return( NULL ); } if ( RegOpenKeyA( key, subkey_name, &subkey ) == ERROR_SUCCESS ){ BYTE value[1024]; DWORD value_length = sizeof( value ); DWORD type; if ( RegQueryValueExA( subkey, value_name, NULL, &type, (unsigned char*)value, &value_length ) == ERROR_SUCCESS){ if ( type == REG_DWORD ){ result = (LONG)value[0]; }else{ throwException( env, "readValue", "type mismach" ); } }else{ throwException( env, "readStringValue", "RegQueryValueEx failed" ); } RegCloseKey(subkey); }else{ throwException( env, "readStringValue", "RegOpenKey failed" ); } return(result); } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_writeWordValueA( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name, jint _value_value ) { HKEY key; HKEY subkey; char subkey_name[1024]; char value_name[1024]; DWORD value_value = _value_value; key = mapHKEY( env, _type ); if ( key == NULL ){ return; } if ( !jstringToCharsA( env, _subkey_name, subkey_name, sizeof( subkey_name ))){ return; } if ( !jstringToCharsA( env, _value_name, value_name, sizeof( value_name ))){ return; } if ( RegCreateKeyExA( key, subkey_name, 0, REG_NONE, 0, KEY_ALL_ACCESS, NULL, &subkey, NULL ) == ERROR_SUCCESS ){ if ( RegSetValueExA( subkey, value_name, 0, REG_DWORD, (const BYTE*)&value_value, sizeof(DWORD)) == ERROR_SUCCESS){ }else{ throwException( env, "writeWordValue", "RegSetValueEx failed" ); } RegCloseKey(subkey); }else{ throwException( env, "writeWordValue", "RegCreateKeyEx failed" ); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_writeStringValueA( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name, jstring _value_value ) { HKEY key; HKEY subkey; char subkey_name[1024]; char value_name[1024]; char value_value[1024]; key = mapHKEY( env, _type ); if ( key == NULL ){ return; } if ( !jstringToCharsA( env, _subkey_name, subkey_name, sizeof( subkey_name ))){ return; } if ( !jstringToCharsA( env, _value_name, value_name, sizeof( value_name ))){ return; } if ( !jstringToCharsA( env, _value_value, value_value, sizeof( value_value ))){ return; } if ( RegCreateKeyExA( key, subkey_name, 0, REG_NONE, 0, KEY_ALL_ACCESS, NULL, &subkey, NULL ) == ERROR_SUCCESS ){ if ( RegSetValueExA( subkey, value_name, 0, REG_SZ, (const BYTE*)value_value, strlen(value_value)+1 ) == ERROR_SUCCESS){ }else{ throwException( env, "writeStringValue", "RegSetValueEx failed" ); } RegCloseKey(subkey); }else{ throwException( env, "writeStringValue", "RegCreateKeyEx failed" ); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_deleteKeyA( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jboolean _recursive ) { HKEY key; HKEY subkey; char subkey_name[1024]; jstring result = NULL; key = mapHKEY( env, _type ); if ( key == NULL ){ return; } if ( !jstringToCharsA( env, _subkey_name, subkey_name, sizeof( subkey_name ))){ return; } if ( RegOpenKeyA( key, subkey_name, &subkey ) == ERROR_SUCCESS ){ RegCloseKey(subkey); if ( _recursive ){ if ( SHDeleteKeyA( key, subkey_name ) != ERROR_SUCCESS ){ throwException( env, "deleteKey", "SHDeleteKey failed" ); } }else{ if ( RegDeleteKeyA( key, subkey_name ) != ERROR_SUCCESS ){ throwException( env, "deleteKey", "RegDeleteKey failed" ); } } } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_deleteValueA( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name ) { HKEY key; HKEY subkey; char subkey_name[1024]; char value_name[1024]; jstring result = NULL; key = mapHKEY( env, _type ); if ( key == NULL ){ return; } if ( !jstringToCharsA( env, _subkey_name, subkey_name, sizeof( subkey_name ))){ return; } if ( !jstringToCharsA( env, _value_name, value_name, sizeof( value_name ))){ return; } if ( RegOpenKeyA( key, subkey_name, &subkey ) == ERROR_SUCCESS ){ RegCloseKey(subkey); if ( SHDeleteValueA( key, subkey_name, value_name ) != ERROR_SUCCESS ){ throwException( env, "deleteValue", "SHDeleteValue failed" ); } } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_createProcessA( JNIEnv* env, jclass cla, jstring _command_line, jboolean _inherit_handles ) { char command_line[16000]; STARTUPINFOA start_info; PROCESS_INFORMATION proc_info; if ( !jstringToCharsA( env, _command_line, command_line, sizeof( command_line ))){ return; } memset( &start_info, 0, sizeof( STARTUPINFOA )); start_info.cb = sizeof( STARTUPINFOA ); if ( CreateProcessA( NULL, // LPCTSTR lpApplicationName, command_line, // LPTSTR lpCommandLine, NULL, // LPSECURITY_ATTRIBUTES lpProcessAttributes, NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes, _inherit_handles, // BOOL bInheritHandles, DETACHED_PROCESS, // DWORD dwCreationFlags, NULL, // LPVOID lpEnvironment, NULL, // LPCTSTR lpCurrentDirectory, &start_info, // LPSTARTUPINFO lpStartupInfo, &proc_info )){ // LPPROCESS_INFORMATION lpProcessInformation CloseHandle( proc_info.hThread ); CloseHandle( proc_info.hProcess ); }else{ throwException( env, "createProcess", "CreateProcess failed" ); } }; JNIEXPORT jint JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_shellExecAndWaitA( JNIEnv* env, jclass cla, jstring _file, jstring _params ) { char file[2048]; char params[2048]; if ( !jstringToCharsA( env, _file, file, sizeof( file ))){ return(0); } if ( !jstringToCharsA( env, _params, params, sizeof( params ))){ return(0); } SHELLEXECUTEINFOA shExecInfo; shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOA); shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT; shExecInfo.hwnd = NULL; shExecInfo.lpVerb = "runas"; shExecInfo.lpFile = file; shExecInfo.lpParameters = params; shExecInfo.lpDirectory = NULL; shExecInfo.nShow = SW_SHOWNORMAL; shExecInfo.hInstApp = NULL; ShellExecuteExA(&shExecInfo); int res = (int)shExecInfo.hInstApp; if ( res <= 32 ){ throwException( env, "shellExec", "ShellExecA failed", res ); return( 0 ); }else{ HANDLE process = shExecInfo.hProcess; WaitForSingleObject( process, INFINITE ); DWORD result; if ( GetExitCodeProcess( process, &result ) == 0 ){ throwException( env, "shellExec", "GetExitCodeProcess failed", GetLastError()); } CloseHandle( process ); return((jint)result); } }; JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_moveToRecycleBinA( JNIEnv *env, jclass cla, jstring _fileName ) { char file_name[16000]; SHFILEOPSTRUCTA opFile; if ( !jstringToCharsA( env, _fileName, file_name, sizeof( file_name )-1)){ return; } HANDLE file = CreateFileA ( file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); // Checks if file exists if ( file == INVALID_HANDLE_VALUE ){ throwException( env, "moveToRecycleBin", "file not found" ); return; } CloseHandle(file); file_name[ strlen(file_name)+1 ] = 0; ZeroMemory(&opFile, sizeof(opFile)); opFile.wFunc = FO_DELETE; opFile.pFrom = file_name; opFile.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_SILENT; if (SHFileOperationA (&opFile)){ throwException( env, "moveToRecycleBin", "SHFileOperation failed" ); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_copyPermissionA( JNIEnv *env, jclass cla, jstring _fileNameIn, jstring _fileNameOut ) { char file_name_in[2048]; char file_name_out[2048]; if ( !jstringToCharsA( env, _fileNameIn, file_name_in, sizeof( file_name_in )-1)){ return; } if ( !jstringToCharsA( env, _fileNameOut, file_name_out, sizeof( file_name_out )-1)){ return; } SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION; DWORD cbFileSD = 0; PSECURITY_DESCRIPTOR pFileSD = NULL; BOOL ok = GetFileSecurityA(file_name_in, secInfo, pFileSD, 0, &cbFileSD); // API should have failed with insufficient buffer. if ( ok ){ throwException( env, "copyPermission", "GetFileSecurity ok" ); return; }else if (GetLastError() == ERROR_FILE_NOT_FOUND) { throwException( env, "copyPermission", "from file not found" ); return; }else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { throwException( env, "copyPermission", "GetFileSecurity unexpected response", GetLastError() ); return; }else{ pFileSD = myheapalloc( cbFileSD ); if (!pFileSD) { throwException( env, "copyPermission", "no memory" ); return; } ok = GetFileSecurityA(file_name_in, secInfo, pFileSD, cbFileSD, &cbFileSD ); if (!ok) { myheapfree( pFileSD ); throwException( env, "copyPermission", "GetFileSecurity", GetLastError()); return; } ok = SetFileSecurityA( file_name_out, secInfo, pFileSD ); myheapfree( pFileSD ); if ( !ok ){ if (GetLastError() == ERROR_FILE_NOT_FOUND) { throwException( env, "copyPermission", "to file not found" ); }else{ throwException( env, "copyPermission", "SetFileSecurity unexpected response", GetLastError() ); } } } } JNIEXPORT jboolean JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_testNativeAvailabilityA( JNIEnv *env, jclass cla, jstring _name ) { char name[2048]; if ( !jstringToCharsA( env, _name, name, sizeof( name )-1)){ return( 0 ); } HMODULE mod = LoadLibraryExA( name, NULL, LOAD_LIBRARY_AS_DATAFILE ); if ( mod == NULL ){ return( 0 ); }else{ FreeLibrary( mod ); return( 1 ); } } // 1.3 JNIEXPORT jint JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_shellExecuteA( JNIEnv *env, jclass cla, jstring _operation, jstring _file, jstring _parameters, jstring _directory, jint _showCmd ) { char operation[20]; char file[5192]; char parameters[16000]; char directory[5192]; INT showCmd = _showCmd; if ( !jstringToCharsA( env, _operation, operation, sizeof( operation ))){ return -1; } if ( !jstringToCharsA( env, _file, file, sizeof( file ))){ return -1; } if ( !jstringToCharsA( env, _parameters, parameters, sizeof( parameters ))){ return -1; } if ( !jstringToCharsA( env, _directory, directory, sizeof( directory ))){ return -1; } // Not sure if ShellExecute treats "\0" as NULL, so do explicit check return (jint)ShellExecuteA(NULL, _operation == NULL ? NULL : operation, _file == NULL ? NULL : file, _parameters == NULL ? NULL : parameters, _directory == NULL ? NULL : directory, showCmd); } // BLAH JNIEXPORT jstring JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getModuleName( JNIEnv *env, jclass cla ) { if ( non_unicode ){ return( Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getModuleNameA( env, cla )); }else{ return( Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getModuleNameW( env, cla )); } } JNIEXPORT jstring JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getVersion( JNIEnv *env, jclass cla ) { if ( non_unicode ){ return( Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getVersionA( env, cla )); }else{ return( Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getVersionW( env, cla )); } } JNIEXPORT jstring JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_readStringValue( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name ) { if ( non_unicode ){ return( Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_readStringValueA( env, cla, _type, _subkey_name, _value_name )); }else{ return( Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_readStringValueW( env, cla, _type, _subkey_name, _value_name )); } } JNIEXPORT jint JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_readWordValue( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name ) { if ( non_unicode ){ return( Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_readWordValueA( env, cla, _type, _subkey_name, _value_name )); }else{ return( Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_readWordValueW( env, cla, _type, _subkey_name, _value_name )); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_writeStringValue( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name, jstring _value_value ) { if ( non_unicode ){ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_writeStringValueA( env, cla, _type, _subkey_name, _value_name, _value_value ); }else{ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_writeStringValueW( env, cla, _type, _subkey_name, _value_name, _value_value ); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_writeWordValue( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name, jint _value_value ) { if ( non_unicode ){ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_writeWordValueA( env, cla, _type, _subkey_name, _value_name, _value_value ); }else{ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_writeWordValueW( env, cla, _type, _subkey_name, _value_name, _value_value ); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_deleteKey( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jboolean _recursive ) { if ( non_unicode ){ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_deleteKeyA( env, cla, _type, _subkey_name, _recursive ); }else{ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_deleteKeyW( env, cla, _type, _subkey_name, _recursive ); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_deleteValue( JNIEnv *env, jclass cla, jint _type, jstring _subkey_name, jstring _value_name ) { if ( non_unicode ){ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_deleteValueA( env, cla, _type, _subkey_name, _value_name ); }else{ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_deleteValueW( env, cla, _type, _subkey_name, _value_name ); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_createProcess( JNIEnv* env, jclass cla, jstring _command_line, jboolean _inherit_handles ) { if ( non_unicode ){ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_createProcessA( env, cla, _command_line, _inherit_handles ); }else{ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_createProcessW( env, cla, _command_line, _inherit_handles ); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_moveToRecycleBin( JNIEnv* env, jclass cla, jstring _file_name ) { if ( non_unicode ){ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_moveToRecycleBinA( env, cla, _file_name ); }else{ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_moveToRecycleBinW( env, cla, _file_name ); } } JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_copyPermission( JNIEnv *env, jclass cla, jstring _fileNameIn, jstring _fileNameOut ) { if ( non_unicode ){ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_copyPermissionA( env, cla, _fileNameIn, _fileNameOut ); }else{ Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_copyPermissionW( env, cla, _fileNameIn, _fileNameOut ); } } JNIEXPORT jboolean JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_testNativeAvailability( JNIEnv *env, jclass cla, jstring name ) { if ( non_unicode ){ return( Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_testNativeAvailabilityA( env, cla,name )); }else{ return( Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_testNativeAvailabilityW( env, cla, name )); } } JNIEXPORT jint JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_shellExecute( JNIEnv *env, jclass cla, jstring operation, jstring file, jstring parameters, jstring directory, jint showCmd ) { if ( non_unicode ){ return Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_shellExecuteA( env, cla, operation, file, parameters, directory, showCmd ); }else{ return Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_shellExecuteW( env, cla, operation, file, parameters, directory, showCmd ); } } JNIEXPORT jint JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_shellExecuteAndWait( JNIEnv* env, jclass cla, jstring _command_line, jstring _params ) { if ( non_unicode ){ return( Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_shellExecAndWaitA( env, cla, _command_line, _params )); }else{ return( Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_shellExecAndWaitW( env, cla, _command_line, _params )); } } azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessInterface.java0000644000175000017500000001307311236406276030076 0ustar adrianadrian/* * Created on Apr 16, 2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.win32.access.impl; /** * @author parg * */ import java.util.List; import java.util.Map; import org.gudy.azureus2.platform.win32.access.*; import org.gudy.azureus2.platform.win32.*; import org.gudy.azureus2.update.UpdaterUtils; public class AEWin32AccessInterface { public static final int HKEY_CLASSES_ROOT = AEWin32Access.HKEY_CLASSES_ROOT; public static final int HKEY_CURRENT_CONFIG = AEWin32Access.HKEY_CURRENT_CONFIG; public static final int HKEY_LOCAL_MACHINE = AEWin32Access.HKEY_LOCAL_MACHINE; public static final int HKEY_CURRENT_USER = AEWin32Access.HKEY_CURRENT_USER; public static final int WM_QUERYENDSESSION = 0x0011; public static final int WM_ENDSESSION = 0x0016; public static final int WM_POWERBROADCAST = 0x0218; public static final int PBT_APMQUERYSUSPEND = 0x0000; public static final int PBT_APMSUSPEND = 0x0004; public static final int PBT_APMRESUMESUSPEND = 0x0007; private static boolean enabled; private static boolean enabled_set; private static AEWin32AccessCallback cb; static{ System.loadLibrary( PlatformManagerImpl.DLL_NAME ); } protected static boolean isEnabled( boolean check_if_disabled ) { if ( !check_if_disabled ){ return( true ); } if ( enabled_set ){ return( enabled ); } try{ // protection against something really bad in the dll enabled = !UpdaterUtils.disableNativeCode( getVersion()); if ( !enabled ){ System.err.println( "Native code has been disabled" ); } }finally{ enabled_set = true; } return( enabled ); } protected static void load( AEWin32AccessCallback _callback, boolean _fully_initialise ) { cb = _callback; if ( _fully_initialise ){ try{ initialise(); }catch( Throwable e ){ // get here when running 2400 java against old non-updated aereg.dll (for example) // System.out.println( "Old aereg version, please update!" ); } } } public static long callback( int msg, int param1, long param2 ) { if ( cb == null ){ return( -1 ); }else{ return( cb.windowsMessage( msg, param1, param2 )); } } protected static native void initialise() throws AEWin32AccessExceptionImpl; protected static native void destroy() throws AEWin32AccessExceptionImpl; protected static native String getVersion(); protected static native String readStringValue( int type, // HKEY type from above String subkey, String value_name ) throws AEWin32AccessExceptionImpl; protected static native void writeStringValue( int type, // HKEY type from above String subkey, String value_name, String value_value ) throws AEWin32AccessExceptionImpl; protected static native int readWordValue( int type, // HKEY type from above String subkey, String value_name ) throws AEWin32AccessExceptionImpl; protected static native void writeWordValue( int type, // HKEY type from above String subkey, String value_name, int value_value ) throws AEWin32AccessExceptionImpl; protected static native void deleteKey( int type, String subkey, boolean recursive ) throws AEWin32AccessExceptionImpl; protected static native void deleteValue( int type, String subkey, String value_namae ) throws AEWin32AccessExceptionImpl; public static native void createProcess( String command_line, boolean inherit_handles ) throws AEWin32AccessException; public static native void moveToRecycleBin( String file_name ) throws AEWin32AccessException; public static native void copyPermission( String from_file_name, String to_file_name ) throws AEWin32AccessException; public static native boolean testNativeAvailability( String name ) throws AEWin32AccessException; /* public static native void ping( String address ) throws AEWin32AccessException; */ public static native void traceRoute( int trace_id, int source_address, int target_address, int pice_mode, AEWin32AccessCallback callback ) throws AEWin32AccessException; public static native int shellExecute( String operation, String file, String parameters, String directory, int sw_const ) throws AEWin32AccessExceptionImpl; public static native int shellExecuteAndWait( String file, String parameters ) throws AEWin32AccessExceptionImpl; public static native List getAvailableDrives() throws AEWin32AccessExceptionImpl; public static native Map getDriveInfo(char driveLetter) throws AEWin32AccessExceptionImpl; } azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/aenet.h0000644000175000017500000000466310525024526024424 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ #define PROBE_TIMEOUT 5000 #define TRACE_ROUTE_BASE_PORT 48132 #pragma pack (1) typedef struct { unsigned char ip_header_len:4; unsigned char ip_version:4; unsigned char tos; unsigned short total_len; unsigned short ident; unsigned short frag_and_flags; unsigned char ttl; unsigned char protocol; unsigned short checksum; unsigned int source_ip; unsigned int dest_ip; } ip_header; typedef struct { unsigned int source_ip; unsigned int dest_ip; unsigned char zero; unsigned char protocol; unsigned short data_len; } pseudo_udp_header; typedef struct { unsigned short source_port; unsigned short dest_port; unsigned short data_len; unsigned short checksum; } udp_header; // basic icmp header #define ICMP_TYPE_ECHO 8 #define ICMP_TYPE_ECHO_REPLY 0 #define ICMP_TYPE_UNREACHABLE 3 #define ICMP_TYPE_TTL_EXCEEDED 11 #define ICMP_CODE_PROTOCOL_UNREACHABLE 2 #define ICMP_CODE_PORT_UNREACHABLE 3 typedef struct { unsigned char type; unsigned char code; unsigned short checksum; unsigned int unused; } icmp_header; typedef struct { unsigned char type; unsigned char code; unsigned short checksum; unsigned short ident; unsigned short sequence; } icmp_echo_header; typedef struct { ip_header ip; udp_header udp; unsigned int data; } udp_probe_packet; typedef struct { ip_header ip; icmp_echo_header icmp; unsigned int data; } icmp_probe_packet;././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootazureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface.hazureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/org_gudy_azureus2_platform_win32_access0000644000175000017500000002003711236406276033027 0ustar adrianadrian/* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface */ #ifndef _Included_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface #define _Included_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface #ifdef __cplusplus extern "C" { #endif #undef org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_HKEY_CLASSES_ROOT #define org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_HKEY_CLASSES_ROOT 1L #undef org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_HKEY_CURRENT_CONFIG #define org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_HKEY_CURRENT_CONFIG 2L #undef org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_HKEY_LOCAL_MACHINE #define org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_HKEY_LOCAL_MACHINE 3L #undef org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_HKEY_CURRENT_USER #define org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_HKEY_CURRENT_USER 4L #undef org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_WM_QUERYENDSESSION #define org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_WM_QUERYENDSESSION 17L #undef org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_WM_ENDSESSION #define org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_WM_ENDSESSION 22L #undef org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_WM_POWERBROADCAST #define org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_WM_POWERBROADCAST 536L #undef org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_PBT_APMQUERYSUSPEND #define org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_PBT_APMQUERYSUSPEND 0L #undef org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_PBT_APMSUSPEND #define org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_PBT_APMSUSPEND 4L #undef org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_PBT_APMRESUMESUSPEND #define org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_PBT_APMRESUMESUSPEND 7L /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: initialise * Signature: ()V */ JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_initialise (JNIEnv *, jclass); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: destroy * Signature: ()V */ JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_destroy (JNIEnv *, jclass); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: getVersion * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getVersion (JNIEnv *, jclass); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: readStringValue * Signature: (ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_readStringValue (JNIEnv *, jclass, jint, jstring, jstring); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: writeStringValue * Signature: (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_writeStringValue (JNIEnv *, jclass, jint, jstring, jstring, jstring); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: readWordValue * Signature: (ILjava/lang/String;Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_readWordValue (JNIEnv *, jclass, jint, jstring, jstring); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: writeWordValue * Signature: (ILjava/lang/String;Ljava/lang/String;I)V */ JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_writeWordValue (JNIEnv *, jclass, jint, jstring, jstring, jint); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: deleteKey * Signature: (ILjava/lang/String;Z)V */ JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_deleteKey (JNIEnv *, jclass, jint, jstring, jboolean); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: deleteValue * Signature: (ILjava/lang/String;Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_deleteValue (JNIEnv *, jclass, jint, jstring, jstring); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: createProcess * Signature: (Ljava/lang/String;Z)V */ JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_createProcess (JNIEnv *, jclass, jstring, jboolean); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: moveToRecycleBin * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_moveToRecycleBin (JNIEnv *, jclass, jstring); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: copyPermission * Signature: (Ljava/lang/String;Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_copyPermission (JNIEnv *, jclass, jstring, jstring); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: testNativeAvailability * Signature: (Ljava/lang/String;)Z */ JNIEXPORT jboolean JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_testNativeAvailability (JNIEnv *, jclass, jstring); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: traceRoute * Signature: (IIIILorg/gudy/azureus2/platform/win32/access/impl/AEWin32AccessCallback;)V */ JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_traceRoute (JNIEnv *, jclass, jint, jint, jint, jint, jobject); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: shellExecute * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)I */ JNIEXPORT jint JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_shellExecute (JNIEnv *, jclass, jstring, jstring, jstring, jstring, jint); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: shellExecuteAndWait * Signature: (Ljava/lang/String;Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_shellExecuteAndWait (JNIEnv *, jclass, jstring, jstring); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: getAvailableDrives * Signature: ()Ljava/util/List; */ JNIEXPORT jobject JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getAvailableDrives (JNIEnv *, jclass); /* * Class: org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface * Method: getDriveInfo * Signature: (C)Ljava/util/Map; */ JNIEXPORT jobject JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_getDriveInfo (JNIEnv *, jclass, jchar); #ifdef __cplusplus } #endif #endif azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/Test.java0000644000175000017500000001131211236406276024734 0ustar adrianadrian/* * Created on Apr 16, 2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.win32.access.impl; /** * @author parg * */ import java.io.File; import java.net.InetAddress; import java.util.Iterator; import java.util.List; import java.util.Map; import org.gudy.azureus2.platform.PlatformManagerPingCallback; public class Test { public static void main( String[] args ) { try{ List availableDrives = AEWin32AccessInterface.getAvailableDrives(); for (Object object : availableDrives) { File f = (File) object; System.out.println(f.getAbsolutePath()); Map driveInfo = AEWin32AccessInterface.getDriveInfo(f.getPath().charAt(0)); for (Iterator iter = driveInfo.keySet().iterator(); iter.hasNext();) { Object key = (Object) iter.next(); Object val = driveInfo.get(key); System.out.println(key + ": " + val); } } if (true) return; /* AEWin32Access access = AEWin32Manager.getAccessor(); String app_data = access.getUserAppData(); System.out.println( "AppData = " + app_data ); String az_home = access.getApplicationInstallDir("azureus"); File az_exe = new File( az_home + File.separator + "Azureus.exe" ).getAbsoluteFile(); if ( az_exe.exists()){ // WriteRegStr HKCR ".torrent" "" "BitTorrent" // WriteRegStr HKCR "BitTorrent" "" "Bittorrent File" // WriteRegStr HKCR "BitTorrent\shell" "" "open" // WriteRegStr HKCR "BitTorrent\DefaultIcon" "" $INSTDIR\Azureus.exe,1 // WriteRegStr HKCR "BitTorrent\shell\open\command" "" '"$INSTDIR\Azureus.exe" "%1"' // WriteRegStr HKCR "BitTorrent\Content Type" "" "application/x-bittorrent" System.out.println( "current = " + access.readStringValue( AEWin32Access.HKEY_CLASSES_ROOT, "BitTorrent\\shell\\open\\command", "" )); access.deleteKey( AEWin32Access.HKEY_CLASSES_ROOT, ".torrent" ); access.deleteKey( AEWin32Access.HKEY_CLASSES_ROOT, "BitTorrent", true ); access.writeStringValue( AEWin32Access.HKEY_CLASSES_ROOT, ".torrent", "", "BitTorrent" ); access.writeStringValue( AEWin32Access.HKEY_CLASSES_ROOT, "BitTorrent", "", "Bittorrent File" ); access.writeStringValue( AEWin32Access.HKEY_CLASSES_ROOT, "BitTorrent\\shell", "", "open" ); access.writeStringValue( AEWin32Access.HKEY_CLASSES_ROOT, "BitTorrent\\DefaultIcon", "", az_exe.toString() + ",1" ); access.writeStringValue( AEWin32Access.HKEY_CLASSES_ROOT, "BitTorrent\\shell\\open\\command", "", "\"" + az_exe.toString() + "\" \"%1\"" ); access.writeStringValue( AEWin32Access.HKEY_CLASSES_ROOT, "BitTorrent\\Content Type" , "", "application/x-bittorrent" ); }else{ System.out.println( "can't find Azureus.exe"); } */ //AEWin32AccessInterface.copyPermission( "C:\\temp\\fred", "C:\\temp\\bill" ); /* AEWin32AccessImpl.getSingleton( false ).traceRoute( InetAddress.getByName( "192.168.1.143" ), InetAddress.getByName( "www.google.com"), new PlatformManagerPingCallback() { public boolean reportNode( int distance, InetAddress address, int millis ) { System.out.println( distance + ": " + address + " - " + millis ); return( true ); } }); */ // AEWin32AccessInterface.ping( "www.google.com" ); int res = AEWin32AccessImpl.getSingleton( false ).shellExecuteAndWait( "c:\\temp\\3110\\Vuze_3.1.1.0_windows.exe", "-VFORCE_LAUNCH=1" ); System.out.println( "res=" + res ); }catch( Throwable e ){ e.printStackTrace(); } } } azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/StdAfx.h0000644000175000017500000000144210040345110024474 0ustar adrianadrian// stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // #if !defined(AFX_STDAFX_H__EB4D9027_DB05_4618_9310_821A191B789B__INCLUDED_) #define AFX_STDAFX_H__EB4D9027_DB05_4618_9310_821A191B789B__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // Insert your headers here #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include // TODO: reference additional headers your program requires here //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_STDAFX_H__EB4D9027_DB05_4618_9310_821A191B789B__INCLUDED_) azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/aereg.suo0000644000175000017500000010400011236406276024762 0ustar adrianadrianࡱ>  A !",$%&'()*+-.8012345679:;<=>?@BRoot EntryP׷%ProjInfoExOutliningState3  TaskListUserTasks$  !"#$%&'I)+,-./01235689:;<=?@ABCDEFQJKLMNOPRSTVWXYZ[\]^_`abcdefghijklnoprsyz{|}~[fS*D<827 `C C:\workspace\az2\azureus2\org\gudy\azureus2\platform\win32\access\impl\VsToolboxService"DebuggerWatches DebuggerBreakpoints(DebuggerExceptions&rC:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src\mfc\C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src\atl\C:\Program Files\MicrosofDebuggerFindSource& DebuggerFindSymbol&DebuggerMemoryWindows,TExternalFilesProjectContents:t Visual Studio 9.0\VC\atlmfc\include\ <;.<.z{283DCBCD-6013-4E01-87BC-A105A07AEB50}|aereg.vcproj|c:\workspace\az2\azureus2\org\gudy\azureDocumentWindowPositions0 DocumentWindowUserData.(dSolutionConfiguration, *ObjMgrContentsV8"4us2\platform\win32\access\impl\org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}1234 <;.<.z`{283DCBCD-6013-4E01-87BC-A105A07AEB50}|aereg.vcproj|c:\workspace\az2\azureus2\org\gudy\azureus2\platform\win32\access\impl\aedevice.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}123456 <;.<.zZ{283DCBCD-6013-4E01-87BC-A105A07AEB50}|aereg.vcproj|c:\workspace\az2\azureus2\org\gudy\azureus2\platform\win32\access\impl\aereg{ͫ4q ͫ4k ͫ4.ͫ4MultiStartupProj=;4{283DCBCD-6013-4E01-87BC-A105A07AEB50}.dwStartupOpt=;StartupProject=&{283DCBCD-6013-4E01-87BC-A105A07AEB50};A{283DCBCD-6013-4E01-87BC-A105A07AEB50}.Release|Win32.BatchBldCtx= Release|Win32;?{283DCBCD-6013-4E01-87BC-A105A07AEB50}.Release|Win32.fBatchBld=;?{283DCBCD-6013-4E01-S$ A+HڪWLl #O¤EL%ү##G}'bm4S8fLd9Ll #O¤EL%ү##G}'bm4Q C:\workspace\az2\azureus2\orgClassViewContents$ProjExplorerState$7UnloadedProjects"HiddenSlnFolders"\gudy\azureus2\platform\win32\access\impl\aereg.vcprojC:\workspace\az2\azureus2\org\gudy\azureus2\platform\win32\access\impl\aereg.vcprojHeader FilesSource Files `c:\program files\java\jdk1.6.0_14\include\jni.hc:\worOutliningStateDir$>BookmarkStateG(TaskListShortcuts$HOutliningState2 Ukspace\az2\azureus2\org\gudy\azureus2\platform\win32\access\impl\aedevice.cppC:\workspace\az2\azureus2\org\gudy\azureus2\platform\win32\access\impl\aenet.cppC:\workspace\az2\azureus2\org\gudy\azureus2\platform\win32\$Bookmarks V001.01X .cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}1234 <;.<.zZ{283DCBCD-6013-4E01-87BC-A105A07AEB50}|aereg.vcproj|c:\workspace\az2\azureus2\org\gudy\azureus2\platform\win32\access\impl\aenet.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}1234access\impl\aereg.cppC:\workspace\az2\azureus2\org\gudy\azureus2\platform\win32\access\impl\org_gudy_azureus2_platform_win32c:\workspace\az2\azureus2\org\gudy\azureus2\platform\win32\access\impl\aereg.cppOk9>bchm )*+-AGRUot  DK$+PV|INis(/go 17\b%*EOpqrv~ (4:Cc:\workspace\az2\azureus2\org\gudy\azureus2\platform\win32\access\impl\aedevice.cppjOutliningState4 mXOutliningState1 qOutliningState5 xOutliningState6 #`9F*DEc:\workspace\az2\azureus2\org\gudy\azureus2\platform\win32\access\impl\aenet.cpp+-9=RXr44* /X ]e mu c:\workspace\az2\azureus2\org\gudy\azureus2\platform\win32\access\impl\org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface.ht!%)-159=AEIMQUY]aeimquy} rc:\program files\java\jdk1.6.0_14\include\win32\jni_md.h=6+.M87BC-A105A07AEB50}.Debug|Win32.BatchBldCtx= Debug|Win32;={28("!IK D  MED'' #>$&-').*,0-003479?AFO^ce5fhil*mo=prar_uv(wx(y ">>OutliningState8 OutliningState7 /3 +"  #  ##b b #&%(3(-A CG)I3NSW[]bglosw{    &Q#+-7             ' + - / 2 4 6 8 ; = ? A E G I K N P R T W Z _ "b i l n u v y    ( F     ) X     ) T 1 V     (      Y ( `        %" % ( . 7= I> H? 7E VF 7G mH 7K L 7T EU _ ` p q y z                         '             %        " ! ! + . 0 4 6 +`c:\program files\java\jdk1.6.0_14\include\jni.h]; "=>.MN`eox}-$11&1  . P$5M!0"$"%'(*+-$.1&24)58&9;&<>$?B5CF$GI+JM%NP<QXZ\^a&bd4ehjmBnuwy{~">>@<>@B= # &"%-'+-5(7:/<@BJ)LO0QUW_)ad0fj!lt+vy2{'.)0!#9;5573579 C  !#%')+.03 5<>@BE!GN+PR1TW"Y`%bd+fi"kr%tv+x{}'- *0"%+'-)/B@B<<>:<>@   "$&)6*,&-/>02<36)79):<@=?>@C&DGIKBLNPS,TV&WY&Z\(]_$`b&ce(fh*ilMmoDprDsuGvxAy{D|~GJ0**,(*,., 9 9 > A C G K O Q U W [ ^ b e j m q u '? y y                       *       1          $   " % ' + - 1 3 7 9 = ? '# C C I L N R T X Z ^ ` #J c c n q s w y }  4o       )    )    o( + S V     *         9        /       (   9 c:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\WinIoCtl.hVe "EL  "$$&,.7;=ACGJ%9MOQ)SUWY0[adl%nptw*x{#!+*    $ ,. 6 >@CFB G8 I #J!"KMQT_'`df~ !&? ?!$*!@ABC@,JNPTW[]acgimosuILy#}+)%#&"B  0,1369<?BEHKNPSVY\0/_cfim1aps-0;    B +- 24) 8 <> CE JLN#O: R 'T*"UZ[ []df~#pp $++#&;@U]_a|~!$%)("")$&)-07:)<ADJ RU,PVY\^acfhj ormsvz&|~ (,,  C"$*-'9:>@BEGL=MQWY_acejlnpy{+ P "'5'+-*51468< >CLN(PRTXoq%Zsz|~         $! "&$&(-/*16,;6:C+EJ9=JNU!W\eh(jntx|*z#M2"*& 0304:<A3&EIK+MOQS+UWY[)]bdf2htvx)) ),0268<>BDHJNPTVZ\`dhlpswy})'1 !%)-/37;>BFJMQSWZ) ^acgi knprvx|~*e82,&    0  -#'+-148;?B+!FHLTVZ\,N`bdhj,fnHo qy{#"w"3DCBCD-6013-4E01-87BC-A105A07AEB50}.Debug|Win32.fBatchBld=; ActiveCfg= Debug|Win32;_access_impl_AEWin32AccessInterface.hrc:\program files\java\jdk1.6.0_14\include\win32\jni_md.hc:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\WinIoCtl.h,nxosxtw,yUazureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/generate_ini.bat0000644000175000017500000000020310525024526026262 0ustar adrianadrianc:\j2sdk1.4.2_04\bin\javah -d . -classpath ..\..\..\..\..\..\.. org.gudy.azureus2.platform.win32.access.impl.AEWin32AccessInterfaceazureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/impl/aereg.h0000644000175000017500000000205710525024526024406 0ustar adrianadrian // The following ifdef block is the standard way of creating macros which make exporting // from a DLL simpler. All files within this DLL are compiled with the AEREG_EXPORTS // symbol defined on the command line. this symbol should not be defined on any project // that uses this DLL. This way any other project whose source files include this file see // AEREG_API functions as being imported from a DLL, wheras this DLL sees symbols // defined with this macro as being exported. #ifdef AEREG_EXPORTS #define AEREG_API __declspec(dllexport) #else #define AEREG_API __declspec(dllimport) #endif // This class is exported from the aereg.dll class AEREG_API CAereg { public: CAereg(void); // TODO: add your methods here. }; #include extern void throwException( JNIEnv* env, char* operation, char* message ); extern void throwException( JNIEnv* env, char* operation, char* message, int error_code ); extern bool jstringToCharsA( JNIEnv *env, jstring jstr, char *chars, int chars_len );azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/AEWin32Access.java0000644000175000017500000001162711236406276025317 0ustar adrianadrian/* * Created on Apr 16, 2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.win32.access; import java.io.File; import java.net.InetAddress; import org.gudy.azureus2.platform.PlatformManagerPingCallback; /** * @author parg * */ public interface AEWin32Access { public static final int HKEY_CLASSES_ROOT = 1; public static final int HKEY_CURRENT_CONFIG = 2; public static final int HKEY_LOCAL_MACHINE = 3; public static final int HKEY_CURRENT_USER = 4; public static final int SW_HIDE = 0; public static final int SW_NORMAL = 1; public static final int SW_SHOWNORMAL = 1; public static final int SW_SHOWMINIMIZED = 2; public static final int SW_SHOWMAXIMIZED = 3; public static final int SW_MAXIMIZE = 3; public static final int SW_SHOWNOACTIVATE = 4; public static final int SW_SHOW = 5; public static final int SW_MINIMIZE = 6; public static final int SW_SHOWMINNOACTIVE = 7; public static final int SW_SHOWNA = 8; public static final int SW_RESTORE = 9; public static final int SW_SHOWDEFAULT = 10; public static final int SW_FORCEMINIMIZE = 11; public static final int SW_MAX = 11; public boolean isEnabled(); public String getVersion(); public String readStringValue( int type, // HKEY type from above String subkey, String value_name ) throws AEWin32AccessException; public void writeStringValue( int type, // HKEY type from above String subkey, String value_name, String value_value ) throws AEWin32AccessException; public int readWordValue( int type, // HKEY type from above String subkey, String value_name ) throws AEWin32AccessException; public void writeWordValue( int type, // HKEY type from above String subkey, String value_name, int value_value ) throws AEWin32AccessException; public void deleteKey( int type, String subkey ) throws AEWin32AccessException; public void deleteKey( int type, String subkey, boolean recursuve ) throws AEWin32AccessException; public void deleteValue( int type, String subkey, String value_name ) throws AEWin32AccessException; public String getUserAppData() throws AEWin32AccessException; public String getProgramFilesDir() throws AEWin32AccessException; public String getApplicationInstallDir( String app_name ) throws AEWin32AccessException; public void createProcess( String command_line, boolean inherit_handles ) throws AEWin32AccessException; public void moveToRecycleBin( String file_name ) throws AEWin32AccessException; public void copyFilePermissions( String from_file_name, String to_file_name ) throws AEWin32AccessException; public boolean testNativeAvailability( String name ) throws AEWin32AccessException; public void traceRoute( InetAddress source_address, InetAddress target_address, PlatformManagerPingCallback callback ) throws AEWin32AccessException; public void ping( InetAddress source_address, InetAddress target_address, PlatformManagerPingCallback callback ) throws AEWin32AccessException; public void addListener( AEWin32AccessListener listener ); public void removeListener( AEWin32AccessListener listener ); /** * @return * @throws AEWin32AccessException */ String getUserDocumentsDir() throws AEWin32AccessException; /** * @return * @throws AEWin32AccessException */ String getUserMusicDir() throws AEWin32AccessException; /** * @return * @throws AEWin32AccessException */ String getUserVideoDir() throws AEWin32AccessException; /** * @return * @throws AEWin32AccessException */ String getCommonAppData() throws AEWin32AccessException; public int shellExecute( String operation, String file, String parameters, String directory, int SW_const) throws AEWin32AccessException; public int shellExecuteAndWait( String file, String params ) throws AEWin32AccessException; /** * @return * * @since 4.1.0.5 */ public File[] getUSBDrives(); } azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/AEWin32Manager.java0000644000175000017500000000236610443624136025464 0ustar adrianadrian/* * Created on Apr 16, 2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.win32.access; /** * @author parg * */ import org.gudy.azureus2.platform.win32.access.impl.*; public class AEWin32Manager { public static AEWin32Access getAccessor( boolean fully_initialise ) { return( AEWin32AccessImpl.getSingleton( fully_initialise )); } } azureus-4.3.0.6/org/gudy/azureus2/platform/win32/access/AEWin32AccessException.java0000644000175000017500000000222211012742464027157 0ustar adrianadrian/* * Created on Apr 16, 2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.win32.access; /** * @author parg * */ public class AEWin32AccessException extends Exception { public AEWin32AccessException( String str ) { super( str ); } } azureus-4.3.0.6/org/gudy/azureus2/platform/win32/PlatformManagerImpl.java0000644000175000017500000007245611273607160025530 0ustar adrianadrian/* * Created on 18-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.win32; /** * @author parg * */ import java.io.File; import java.net.InetAddress; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.platform.*; import org.gudy.azureus2.platform.win32.access.AEWin32Access; import org.gudy.azureus2.platform.win32.access.AEWin32AccessListener; import org.gudy.azureus2.platform.win32.access.AEWin32Manager; import org.gudy.azureus2.plugins.platform.PlatformManagerException; public class PlatformManagerImpl implements PlatformManager, AEWin32AccessListener { public static final int RT_NONE = 0; public static final int RT_AZ = 1; public static final int RT_OTHER = 2; public static String DLL_NAME = "aereg"; public static final String VUZE_ASSOC = "Vuze"; public static final String NEW_MAIN_ASSOC = "Azureus"; public static final String OLD_MAIN_ASS0C = "BitTorrent"; private static boolean initialising; private static boolean init_tried; private static PlatformManagerImpl singleton; private static AEMonitor class_mon = new AEMonitor( "PlatformManager"); private final Set capabilitySet = new HashSet(); private List listeners = new ArrayList(); static { if (System.getProperty("os.arch", "").contains("64")) { DLL_NAME += "64"; } } public static PlatformManagerImpl getSingleton() throws PlatformManagerException { try{ class_mon.enter(); if ( singleton != null ){ return( singleton ); } try{ if ( initialising ){ System.err.println( "PlatformManager: recursive entry during initialisation" ); } initialising = true; if ( !init_tried ){ init_tried = true; try{ singleton = new PlatformManagerImpl(); // gotta separate this so that a recursive call due to config access during // patching finds the singleton singleton.applyPatches(); }catch( PlatformManagerException e ){ throw( e ); }catch( Throwable e ){ if ( e instanceof PlatformManagerException ){ throw((PlatformManagerException)e); } throw( new PlatformManagerException( "Win32Platform: failed to initialise", e )); } } }finally{ initialising = false; } return( singleton ); }finally{ class_mon.exit(); } } private final AEWin32Access access; private final String app_name; private final String app_exe_name; private File az_exe; private boolean az_exe_checked; protected PlatformManagerImpl() throws PlatformManagerException { access = AEWin32Manager.getAccessor( true ); access.addListener( this ); app_name = SystemProperties.getApplicationName(); app_exe_name = app_name + ".exe"; initializeCapabilities(); } private void initializeCapabilities() { if ( access.isEnabled()){ capabilitySet.add(PlatformManagerCapabilities.CreateCommandLineProcess); capabilitySet.add(PlatformManagerCapabilities.GetUserDataDirectory); capabilitySet.add(PlatformManagerCapabilities.RecoverableFileDelete); capabilitySet.add(PlatformManagerCapabilities.RegisterFileAssociations); capabilitySet.add(PlatformManagerCapabilities.ShowFileInBrowser); capabilitySet.add(PlatformManagerCapabilities.GetVersion); capabilitySet.add(PlatformManagerCapabilities.SetTCPTOSEnabled); capabilitySet.add(PlatformManagerCapabilities.ComputerIDAvailability); if ( Constants.compareVersions( access.getVersion(), "1.11" ) >= 0 && !Constants.isWindows9598ME ){ capabilitySet.add(PlatformManagerCapabilities.CopyFilePermissions); } if ( Constants.compareVersions( access.getVersion(), "1.12" ) >= 0 ){ capabilitySet.add(PlatformManagerCapabilities.TestNativeAvailability); } if ( Constants.compareVersions( access.getVersion(), "1.14" ) >= 0 ){ capabilitySet.add(PlatformManagerCapabilities.TraceRouteAvailability); } if ( Constants.compareVersions( access.getVersion(), "1.15" ) >= 0 ){ capabilitySet.add(PlatformManagerCapabilities.PingAvailability); } }else{ // disabled -> only available capability is that to get the version // therefore allowing upgrade capabilitySet.add(PlatformManagerCapabilities.GetVersion); } } protected void applyPatches() { try{ File exe_loc = getApplicationEXELocation(); String az_exe_string = exe_loc.toString(); //int icon_index = getIconIndex(); String current = access.readStringValue( AEWin32Access.HKEY_CLASSES_ROOT, NEW_MAIN_ASSOC + "\\DefaultIcon", "" ); //System.out.println( "current = " + current ); String target = az_exe_string + "," + getIconIndex(); //System.out.println( "target = " + target ); // only patch if Azureus.exe in there if ( current.indexOf( app_exe_name ) != -1 && !current.equals(target)){ writeStringToHKCRandHKCU( NEW_MAIN_ASSOC + "\\DefaultIcon", "", target ); } }catch( Throwable e ){ //e.printStackTrace(); } // one off fix of permissions in app dir if ( hasCapability( PlatformManagerCapabilities.CopyFilePermissions ) && !COConfigurationManager.getBooleanParameter( "platform.win32.permfixdone2", false )){ try{ String str = SystemProperties.getApplicationPath(); if ( str.endsWith(File.separator)){ str = str.substring(0,str.length()-1); } fixPermissions( new File( str ), new File( str )); }catch( Throwable e ){ }finally{ COConfigurationManager.setParameter( "platform.win32.permfixdone2", true ); } } } protected void fixPermissions( File parent, File dir ) throws PlatformManagerException { File[] files = dir.listFiles(); if ( files == null ){ return; } for (int i=0;i 0 ){ return( host ); } return( null ); } public File getLocation( long location_id ) throws PlatformManagerException { if ( location_id == LOC_USER_DATA ){ return(new File(getUserDataDirectory())); }else if ( location_id == LOC_MUSIC ){ try{ return(new File(access.getUserMusicDir())); }catch( Throwable e ){ throw( new PlatformManagerException( "Failed to read registry details", e )); } } else if (location_id == LOC_DOCUMENTS) { try{ return(new File(access.getUserDocumentsDir())); }catch( Throwable e ){ throw( new PlatformManagerException( "Failed to read registry details", e )); } } else if (location_id == LOC_VIDEO) { try{ return(new File(access.getUserVideoDir())); }catch( Throwable e ){ throw( new PlatformManagerException( "Failed to read registry details", e )); } }else{ return( null ); } } public String getApplicationCommandLine() { try{ return( getApplicationEXELocation().toString()); }catch( Throwable e ){ return( null ); } } public boolean isApplicationRegistered() throws PlatformManagerException { // all this stuff needs the exe location so bail out early if unavailable File exe_loc = getApplicationEXELocation(); if ( exe_loc.exists()){ checkExeKey( exe_loc ); } try{ // always trigger magnet reg here if not owned so old users get it... registerMagnet( false ); }catch( Throwable e ){ Debug.printStackTrace(e); } try{ // always trigger magnet reg here if not owned so old users get it... if ( getAdditionalFileTypeRegistrationDetails( "DHT", ".dht" ) == RT_NONE ){ registerDHT(); } }catch( Throwable e ){ Debug.printStackTrace(e); } if ( isAdditionalFileTypeRegistered( OLD_MAIN_ASS0C, ".torrent" )){ unregisterAdditionalFileType( OLD_MAIN_ASS0C, ".torrent" ); registerAdditionalFileType( NEW_MAIN_ASSOC, Constants.APP_NAME + " Download", ".torrent", "application/x-bittorrent" ); } boolean reg = isAdditionalFileTypeRegistered( NEW_MAIN_ASSOC, ".torrent" ); // one off auto registration on new install if ( !reg && !COConfigurationManager.getBooleanParameter( "platform.win32.autoregdone", false )){ registerAdditionalFileType( NEW_MAIN_ASSOC, Constants.APP_NAME + " Download", ".torrent", "application/x-bittorrent" ); COConfigurationManager.setParameter( "platform.win32.autoregdone", true ); reg = true; } // always register .vuze association boolean vuze_reg = isAdditionalFileTypeRegistered( VUZE_ASSOC, ".vuze" ); if ( !vuze_reg ){ registerAdditionalFileType( VUZE_ASSOC, "Vuze File", ".vuze", "application/x-vuze" ); } return( reg ); } protected void checkExeKey( File exe ) { checkExeKey( AEWin32Access.HKEY_CURRENT_USER, exe ); checkExeKey( AEWin32Access.HKEY_LOCAL_MACHINE, exe ); } protected void checkExeKey( int hkey, File exe ) { String exe_str = exe.getAbsolutePath(); String str = null; try{ str = access.readStringValue( hkey, "software\\" + app_name, "exec" ); }catch( Throwable e ){ } try{ if ( str == null || !str.equals( exe_str )){ access.writeStringValue( hkey, "software\\" + app_name, "exec", exe_str ); } }catch( Throwable e ){ } } public boolean isAdditionalFileTypeRegistered( String name, String type ) throws PlatformManagerException { return( getAdditionalFileTypeRegistrationDetails( name, type ) == RT_AZ ); } public int getAdditionalFileTypeRegistrationDetails( String name, String type ) throws PlatformManagerException { String az_exe_str; try{ az_exe_str = getApplicationEXELocation().toString(); }catch( Throwable e ){ return( RT_NONE ); } try{ String test1 = access.readStringValue( AEWin32Access.HKEY_CLASSES_ROOT, name + "\\shell\\open\\command", "" ); if ( !test1.equals( "\"" + az_exe_str + "\" \"%1\"" )){ return( test1.length() ==0?RT_NONE:RT_OTHER ); } String test2 = access.readStringValue( AEWin32Access.HKEY_CLASSES_ROOT, type, ""); if ( !test2.equals( NEW_MAIN_ASSOC )) { return test2.length() == 0 ? RT_NONE : RT_OTHER; } // MRU list is just that, to remove the "always open with" we need to kill // the "application" entry, if it exists try{ String always_open_with = access.readStringValue( AEWin32Access.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\" + type, "Application" ); //System.out.println( "mru_list = " + mru_list ); if ( always_open_with.length() > 0 ){ // AZ is default so if this entry exists it denotes another (non-AZ) app return( RT_OTHER ); } }catch( Throwable e ){ // e.printStackTrace(); // failure means things are OK } /* try{ String mru_list = access.readStringValue( AEWin32Access.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.torrent\\OpenWithList", "MRUList" ); //System.out.println( "mru_list = " + mru_list ); if ( mru_list.length() > 0 ){ String mru = access.readStringValue( AEWin32Access.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.torrent\\OpenWithList", "" + mru_list.charAt(0) ); //System.out.println( "mru = " + mru ); return( mru.equalsIgnoreCase(app_exe_name)); } }catch( Throwable e ){ // e.printStackTrace(); // failure means things are OK } */ return( RT_AZ ); }catch( Throwable e ){ if ( e.getMessage() == null || e.getMessage().indexOf("RegOpenKey failed") == -1 ){ Debug.printStackTrace( e ); } return( RT_NONE ); } } public void registerApplication() throws PlatformManagerException { registerMagnet( true ); registerDHT(); registerAdditionalFileType( NEW_MAIN_ASSOC, Constants.APP_NAME + " Download", ".torrent", "application/x-bittorrent" ); registerAdditionalFileType( VUZE_ASSOC, "Vuze File", ".vuze", "application/x-vuze" ); } protected void registerMagnet( boolean force ) { try{ // see http://forum.vuze.com/thread.jspa?threadID=79692&tstart=0 String az_exe_string = getApplicationEXELocation().toString(); boolean magnet_exe_managing = false; try{ String existing = access.readStringValue( AEWin32Access.HKEY_CLASSES_ROOT, "magnet\\shell\\open\\command", "" ); magnet_exe_managing = existing.toLowerCase().indexOf( "\\magnet.exe" ) != -1; }catch( Throwable e ){ } if ( !magnet_exe_managing ){ if ( force || getAdditionalFileTypeRegistrationDetails( "Magnet", ".magnet" ) == RT_NONE ){ try{ registerAdditionalFileType( "Magnet", "Magnet URI", ".magnet", "application/x-magnet", true ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } // we always write this hierarchy in case magnet.exe installed in the future createKey( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet" ); createKey( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet\\Handlers" ); createKey( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet\\Handlers\\Azureus" ); access.writeStringValue( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet\\Handlers\\Azureus", "DefaultIcon", "\"" + az_exe_string + "," + getIconIndex() + "\"" ); access.writeStringValue( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet\\Handlers\\Azureus", "Description", "Download with Vuze (formerly Azureus)" ); access.writeStringValue( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet\\Handlers\\Azureus", "ShellExecute", "\"" + az_exe_string + "\" %URL" ); access.writeWordValue( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet\\Handlers\\Azureus\\Type", "urn:btih", 0 ); }catch( Throwable e ){ } } protected boolean createKey( int type, String key ) { try{ access.readStringValue( type, key, ""); return( true ); }catch( Throwable e ){ try{ access.writeStringValue( type, key, "", "" ); return( true ); }catch( Throwable f ){ return( false ); } } } protected void registerDHT() { try{ registerAdditionalFileType( "DHT", "DHT URI", ".dht", "application/x-dht", true ); }catch( Throwable e ){ Debug.printStackTrace(e); } } public void registerAdditionalFileType( String name, // e.g. "Azureus" String description, // e.g. "BitTorrent File" String type, // e.g. ".torrent" String content_type ) // e.g. "application/x-bittorrent" throws PlatformManagerException { registerAdditionalFileType( name, description, type, content_type, false ); } public void registerAdditionalFileType( String name, String description, String type, String content_type, boolean url_protocol) throws PlatformManagerException { // WriteRegStr HKCR ".torrent" "" "Azureus" // WriteRegStr HKCR "Azureus" "" "Vuze Torrent" // WriteRegStr HKCR "Azureus\shell" "" "open" // WriteRegStr HKCR "Azureus\DefaultIcon" "" $INSTDIR\Azureus.exe,1 // WriteRegStr HKCR "Azureus\shell\open\command" "" '"$INSTDIR\Azureus.exe" "%1"' // WriteRegStr HKCR "Azureus\Content Type" "" "application/x-bittorrent" try{ String az_exe_string = getApplicationEXELocation().toString(); unregisterAdditionalFileType( name, type ); writeStringToHKCRandHKCU( type, "", name ); writeStringToHKCRandHKCU( type, "Content Type", content_type ); writeStringToHKCRandHKCU( "MIME\\Database\\Content Type\\" + content_type, "Extension", type ); writeStringToHKCRandHKCU( name, "", description ); writeStringToHKCRandHKCU( name + "\\shell", "", "open" ); writeStringToHKCRandHKCU( name + "\\DefaultIcon", "", az_exe_string + "," + getIconIndex()); writeStringToHKCRandHKCU( name + "\\shell\\open\\command", "", "\"" + az_exe_string + "\" \"%1\"" ); writeStringToHKCRandHKCU( name, "Content Type", content_type ); if ( url_protocol ){ writeStringToHKCRandHKCU( name, "URL Protocol", "" ); } }catch( PlatformManagerException e ){ throw(e ); }catch( Throwable e ){ throw( new PlatformManagerException( "Failed to write registry details", e )); } } private void writeStringToHKCRandHKCU(String subkey, String name, String value) { // HKCU will most likely fail on Vista due to permissions try { access.writeStringValue(AEWin32Access.HKEY_CLASSES_ROOT, subkey, name, value); } catch (Throwable e) { if (!Constants.isWindowsVistaOrHigher) { Debug.out(e); } } try { access.writeStringValue(AEWin32Access.HKEY_CURRENT_USER, "Software\\Classes\\" + subkey, name, value); } catch (Throwable e) { Debug.out(e); } } public void unregisterAdditionalFileType( String name, // e.g. "Azureus" String type ) // e.g. ".torrent" throws PlatformManagerException { try{ try{ access.deleteValue( AEWin32Access.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\" + type, "Application" ); }catch( Throwable e ){ // e.printStackTrace(); } try{ access.deleteKey( AEWin32Access.HKEY_CLASSES_ROOT, type ); }catch( Throwable e ){ // Debug.printStackTrace( e ); } try{ access.deleteKey( AEWin32Access.HKEY_CLASSES_ROOT, name, true ); }catch( Throwable e ){ // Debug.printStackTrace( e ); } try{ access.deleteKey( AEWin32Access.HKEY_CURRENT_USER, "Software\\Classes\\" + type ); }catch( Throwable e ){ // Debug.printStackTrace( e ); } try{ access.deleteKey( AEWin32Access.HKEY_CURRENT_USER, "Software\\Classes\\" + name, true ); }catch( Throwable e ){ // Debug.printStackTrace( e ); } }catch( Throwable e ){ throw( new PlatformManagerException( "Failed to delete registry details", e )); } } public void createProcess( String command_line, boolean inherit_handles ) throws PlatformManagerException { try{ access.createProcess( command_line, inherit_handles ); }catch( Throwable e ){ throw( new PlatformManagerException( "Failed to create process", e )); } } public void performRecoverableFileDelete( String file_name ) throws PlatformManagerException { try{ access.moveToRecycleBin( file_name ); }catch( Throwable e ){ throw( new PlatformManagerException( "Failed to move file", e )); } } public void setTCPTOSEnabled( boolean enabled ) throws PlatformManagerException { try{ access.writeWordValue( AEWin32Access.HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\Tcpip\\Parameters", "DisableUserTOSSetting", enabled?0:1); }catch( Throwable e ){ throw( new PlatformManagerException( "Failed to write registry details", e )); } } public void copyFilePermissions( String from_file_name, String to_file_name ) throws PlatformManagerException { try{ access.copyFilePermissions( from_file_name, to_file_name ); }catch( Throwable e ){ throw( new PlatformManagerException( "Failed to copy file permissions", e )); } } /** * {@inheritDoc} */ public void showFile(String file_name) throws PlatformManagerException { try { File file = new File(file_name); access.createProcess( "explorer.exe " + ( file.isDirectory() ? "/e," : "/e,/select," ) + "\"" + file_name + "\"", false ); /* Runtime.getRuntime().exec( new String[] { "explorer.exe", file.isDirectory() ? "/e," : "/e,/select,", "\"" + file_name + "\"" }); */ } catch (Throwable e) { throw new PlatformManagerException("Failed to show file " + file_name, e); } } public boolean testNativeAvailability( String name ) throws PlatformManagerException { if ( !hasCapability( PlatformManagerCapabilities.TestNativeAvailability )){ throw new PlatformManagerException("Unsupported capability called on platform manager"); } try{ return( access.testNativeAvailability( name )); }catch( Throwable e ){ throw( new PlatformManagerException( "Failed to test availability", e )); } } public void traceRoute( InetAddress interface_address, InetAddress target, PlatformManagerPingCallback callback ) throws PlatformManagerException { if ( !hasCapability( PlatformManagerCapabilities.TraceRouteAvailability )){ throw new PlatformManagerException("Unsupported capability called on platform manager"); } try{ access.traceRoute( interface_address, target, callback ); }catch( Throwable e ){ throw( new PlatformManagerException( "Failed to trace route", e )); } } public void ping( InetAddress interface_address, InetAddress target, PlatformManagerPingCallback callback ) throws PlatformManagerException { if ( !hasCapability( PlatformManagerCapabilities.PingAvailability )){ throw new PlatformManagerException("Unsupported capability called on platform manager"); } try{ access.ping( interface_address, target, callback ); }catch( Throwable e ){ throw( new PlatformManagerException( "Failed to trace route", e )); } } public int shellExecute(String operation, String file, String parameters, String directory, int SW_const) throws PlatformManagerException { try { return access.shellExecute(operation, file, parameters, directory, SW_const); } catch (Throwable e) { throw( new PlatformManagerException( "Failed to shellExecute", e )); } } /** * {@inheritDoc} */ public boolean hasCapability( PlatformManagerCapabilities capability) { return capabilitySet.contains(capability); } /** * Does nothing */ public void dispose() { } public void eventOccurred( int type ) { int t_type; if ( type == AEWin32AccessListener.ET_SHUTDOWN ){ t_type = PlatformManagerListener.ET_SHUTDOWN; }else if ( type == AEWin32AccessListener.ET_SUSPEND ){ t_type = PlatformManagerListener.ET_SUSPEND; }else if ( type == AEWin32AccessListener.ET_RESUME ){ t_type = PlatformManagerListener.ET_RESUME; }else{ return; } if ( t_type != -1 ){ for (int i=0;i * The default for the ID is the AZID of the first user profile. * * @return ID */ public String getAzComputerID() { boolean needWrite = false; String cid = null; try { cid = access.readStringValue(AEWin32Access.HKEY_LOCAL_MACHINE, "SOFTWARE\\" + app_name, "CID"); } catch (Exception e) { } if (cid == null || cid.length() == 0) { needWrite = true; try { File commonPath = new File(access.getCommonAppData(),app_name); if (commonPath.isDirectory()) { File fCID = new File(commonPath, "azCID.txt"); if (fCID.exists()) { cid = FileUtil.readFileAsString(fCID, 255, "utf8"); } } } catch (Exception e) { } } if (cid == null || cid.length() == 0) { needWrite = true; cid = COConfigurationManager.getStringParameter("ID"); } if (cid == null || cid.length() == 0) { needWrite = true; cid = RandomUtils.generateRandomAlphanumerics(20); } if (needWrite) { setAzComputerID(cid); } return cid; } /** * @param cid */ private void setAzComputerID(String cid) { try { access.writeStringValue(AEWin32Access.HKEY_LOCAL_MACHINE, "SOFTWARE\\" + app_name, "CID", cid); } catch (Exception e) { Debug.out("Could not write CID: " + e.getMessage()); } try { String sCommonAppData = access.getCommonAppData(); if (sCommonAppData != null && sCommonAppData.length() > 0) { File commonPath = new File(sCommonAppData); if (commonPath.isDirectory()) { commonPath = new File(commonPath, app_name); FileUtil.mkdirs(commonPath); File fCID = new File(commonPath, "azCID.txt"); FileUtil.writeBytesAsFile(fCID.getAbsolutePath(), cid.getBytes("utf8")); } } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { try { PlatformManagerImpl impl = new PlatformManagerImpl(); System.out.println(impl.getAzComputerID()); } catch (PlatformManagerException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void requestUserAttention(int type, Object data) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } } azureus-4.3.0.6/org/gudy/azureus2/platform/PlatformManagerPingCallback.java0000644000175000017500000000247510525024530026162 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform; import java.net.InetAddress; public interface PlatformManagerPingCallback { /** * @param distance * @param address null -> timeout * @param millis elapsed time for successful op * @return true -> continue (where destination not reached) */ public boolean reportNode( int distance, InetAddress address, int millis ); } azureus-4.3.0.6/org/gudy/azureus2/platform/PlatformManagerCapabilities.java0000644000175000017500000000706211033073346026242 0ustar adrianadrian/* * Created on 13-Mar-2004 * Created by James Yeh * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform; /** * Enum for a PlatformManager's reported capabilities * @version 1.0 Initial Version * @since 1.4 * @author James Yeh */ public final class PlatformManagerCapabilities { public static final PlatformManagerCapabilities GetVersion = new PlatformManagerCapabilities("getVersion"); public static final PlatformManagerCapabilities CreateCommandLineProcess = new PlatformManagerCapabilities("CreateCommandLineProcess"); public static final PlatformManagerCapabilities UseNativeNotification = new PlatformManagerCapabilities("UseNativeNotification"); public static final PlatformManagerCapabilities UseNativeScripting = new PlatformManagerCapabilities("UseNativeScripting"); public static final PlatformManagerCapabilities PlaySystemAlert = new PlatformManagerCapabilities("PlaySystemAlert"); public static final PlatformManagerCapabilities GetUserDataDirectory = new PlatformManagerCapabilities("GetUserDataDirectory"); public static final PlatformManagerCapabilities RecoverableFileDelete = new PlatformManagerCapabilities("RecoverableFileDelete"); public static final PlatformManagerCapabilities RegisterFileAssociations = new PlatformManagerCapabilities("RegisterFileAssociations"); public static final PlatformManagerCapabilities ShowFileInBrowser = new PlatformManagerCapabilities("ShowFileInBrowser"); public static final PlatformManagerCapabilities ShowPathInCommandLine = new PlatformManagerCapabilities("ShowPathInCommandLine"); public static final PlatformManagerCapabilities SetTCPTOSEnabled = new PlatformManagerCapabilities("SetTCPTOSEnabled"); public static final PlatformManagerCapabilities CopyFilePermissions = new PlatformManagerCapabilities("CopyFilePermissions"); public static final PlatformManagerCapabilities TestNativeAvailability = new PlatformManagerCapabilities("TestNativeAvailability"); public static final PlatformManagerCapabilities TraceRouteAvailability = new PlatformManagerCapabilities("TraceRoute"); public static final PlatformManagerCapabilities PingAvailability = new PlatformManagerCapabilities("Ping"); public static final PlatformManagerCapabilities ComputerIDAvailability = new PlatformManagerCapabilities("CID"); public static final PlatformManagerCapabilities RequestUserAttention = new PlatformManagerCapabilities("RequestUserAttention"); private final String myName; // for debug only private PlatformManagerCapabilities(String name) { myName = name; } /** * {@inheritDoc} */ public String toString() { return myName; } } azureus-4.3.0.6/org/gudy/azureus2/platform/dummy/0000755000175000017500000000000011310377634021141 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/platform/dummy/PlatformManagerImpl.java0000644000175000017500000001516011133516744025710 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.platform.dummy; import java.io.File; import java.net.InetAddress; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.platform.PlatformManagerListener; import org.gudy.azureus2.platform.PlatformManagerPingCallback; import org.gudy.azureus2.plugins.platform.PlatformManagerException; /** * @version 1.0 */ public class PlatformManagerImpl implements PlatformManager { private static PlatformManager singleton; static { singleton = new PlatformManagerImpl(); } public static PlatformManager getSingleton() { return singleton; } private PlatformManagerImpl() {} /** * {@inheritDoc} */ public int getPlatformType() { return( PlatformManagerFactory.getPlatformType()); } /** * {@inheritDoc} */ public String getUserDataDirectory() throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } /** * {@inheritDoc} */ public boolean isApplicationRegistered() throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public String getApplicationCommandLine() throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public String getComputerName() { return null; } public File getLocation( long location_id ) throws PlatformManagerException { return( null ); } public boolean isAdditionalFileTypeRegistered( String name, // e.g. "BitTorrent" String type ) // e.g. ".torrent" throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void unregisterAdditionalFileType( String name, // e.g. "BitTorrent" String type ) // e.g. ".torrent" throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } /** * {@inheritDoc} */ public void registerApplication() throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void registerAdditionalFileType( String name, // e.g. "BitTorrent" String description, // e.g. "BitTorrent File" String type, // e.g. ".torrent" String content_type ) // e.g. "application/x-bittorrent" throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } /** * {@inheritDoc} */ public void createProcess(String command_line, boolean inherit_handles) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } /** * {@inheritDoc} */ public void performRecoverableFileDelete(String file_name) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } /** * {@inheritDoc} */ public String getVersion() throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } /** * {@inheritDoc} */ public void setTCPTOSEnabled( boolean enabled ) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void copyFilePermissions( String from_file_name, String to_file_name ) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } /** * {@inheritDoc} */ public void showFile(String file_name) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public boolean testNativeAvailability( String name ) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void traceRoute( InetAddress interface_address, InetAddress target, PlatformManagerPingCallback callback ) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void ping( InetAddress interface_address, InetAddress target, PlatformManagerPingCallback callback ) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } /** * {@inheritDoc} */ public boolean hasCapability(PlatformManagerCapabilities capability) { return false; } /** * Does nothing */ public void dispose() { } public void addListener( PlatformManagerListener listener ) { } public void removeListener( PlatformManagerListener listener ) { } // @see org.gudy.azureus2.platform.PlatformManager#getAzComputerID() public String getAzComputerID() throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void requestUserAttention(int type, Object data) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } } azureus-4.3.0.6/org/gudy/azureus2/platform/PlatformManagerPluginDelegate.java0000644000175000017500000000565211244700502026540 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform; import java.util.Properties; import org.gudy.azureus2.platform.unix.PlatformManagerUnixPlugin; import org.gudy.azureus2.plugins.Plugin; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.update.UpdatableComponent; import org.gudy.azureus2.plugins.update.UpdateChecker; /** * @author TuxPaper * @created Jul 24, 2007 * */ public class PlatformManagerPluginDelegate implements Plugin, UpdatableComponent // we have to implement this as it used as a mixin to declare that this plugin handles its own update process { // @see org.gudy.azureus2.plugins.Plugin#initialize(org.gudy.azureus2.plugins.PluginInterface) public void initialize(PluginInterface pluginInterface) throws PluginException { PlatformManager platform = PlatformManagerFactory.getPlatformManager(); int platformType = platform.getPlatformType(); if ( platformType == PlatformManager.PT_WINDOWS ){ org.gudy.azureus2.platform.win32.PlatformManagerUpdateChecker plugin = new org.gudy.azureus2.platform.win32.PlatformManagerUpdateChecker(); plugin.initialize(pluginInterface); }else if ( platformType == PlatformManager.PT_MACOSX ){ org.gudy.azureus2.platform.macosx.PlatformManagerUpdateChecker plugin = new org.gudy.azureus2.platform.macosx.PlatformManagerUpdateChecker(); plugin.initialize(pluginInterface); }else if ( platformType == PlatformManager.PT_UNIX ){ PlatformManagerUnixPlugin plugin = new PlatformManagerUnixPlugin(); plugin.initialize(pluginInterface); }else{ Properties pluginProperties = pluginInterface.getPluginProperties(); pluginProperties.setProperty("plugin.name", "Platform-Specific Support"); pluginProperties.setProperty("plugin.version", "1.0"); pluginProperties.setProperty("plugin.version.info", "Not required for this platform"); } } public String getName() { return( "Mixin only" ); } public int getMaximumCheckTime() { return( 0 ); } public void checkForUpdate( UpdateChecker checker ) { } } azureus-4.3.0.6/org/gudy/azureus2/platform/unix/0000755000175000017500000000000011310377634020771 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/platform/unix/ScriptAfterShutdown.java0000644000175000017500000000336110722646062025621 0ustar adrianadrianpackage org.gudy.azureus2.platform.unix; import java.io.*; import org.gudy.azureus2.core3.config.COConfigurationManager; public class ScriptAfterShutdown { private static PrintStream sysout; public static void main(String[] args) { // Set transitory so not everything gets loaded up. (such as the AEDiagnostic's tidy flag) System.setProperty("transitory.startup", "1"); // Since stdout will be in a shell script, redirect any stdout not coming // from us to stderr sysout = System.out; try { System.setOut(new PrintStream(new FileOutputStream("/dev/stderr"))); } catch (FileNotFoundException e) { } String extraCmds = COConfigurationManager.getStringParameter( "scriptaftershutdown", null); if (extraCmds != null) { boolean exit = COConfigurationManager.getBooleanParameter( "scriptaftershutdown.exit", false); if (exit) { COConfigurationManager.removeParameter("scriptaftershutdown.exit"); } COConfigurationManager.removeParameter("scriptaftershutdown"); COConfigurationManager.save(); sysout.println(extraCmds); if (exit) { sysout.println("exit"); } } else { log("No shutdown tasks to do"); } } public static void addExtraCommand(String s) { String extraCmds = COConfigurationManager.getStringParameter( "scriptaftershutdown", null); if (extraCmds == null) { extraCmds = s + "\n"; } else { extraCmds += s + "\n"; } COConfigurationManager.setParameter("scriptaftershutdown", extraCmds); } public static void setRequiresExit(boolean requiresExit) { if (requiresExit) { COConfigurationManager.setParameter("scriptaftershutdown.exit", true); } } private static void log(String string) { sysout.println("echo \"" + string.replaceAll("\"", "\\\"") + "\""); } } azureus-4.3.0.6/org/gudy/azureus2/platform/unix/PlatformManagerImpl.java0000644000175000017500000002263711133516744025547 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.unix; import java.io.File; import java.net.InetAddress; import java.util.HashSet; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.platform.*; import org.gudy.azureus2.plugins.platform.PlatformManagerException; /** * @author TuxPaper * @created Dec 18, 2006 * */ public class PlatformManagerImpl implements PlatformManager { private static final LogIDs LOGID = LogIDs.CORE; private static final String ERR_UNSUPPORTED = "Unsupported capability called on platform manager"; protected static PlatformManagerImpl singleton; protected static AEMonitor class_mon = new AEMonitor("PlatformManager"); private final HashSet capabilitySet = new HashSet(); private static final Object migrate_lock = new Object(); /** * Gets the platform manager singleton, which was already initialized */ public static PlatformManagerImpl getSingleton() { return singleton; } static { initializeSingleton(); } /** * Instantiates the singleton */ private static void initializeSingleton() { try { class_mon.enter(); singleton = new PlatformManagerImpl(); } catch (Throwable e) { Logger.log(new LogEvent(LOGID, "Failed to initialize platform manager" + " for Unix Compatable OS", e)); } finally { class_mon.exit(); } } /** * Creates a new PlatformManager and initializes its capabilities */ public PlatformManagerImpl() { capabilitySet.add(PlatformManagerCapabilities.GetUserDataDirectory); } // @see org.gudy.azureus2.platform.PlatformManager#copyFilePermissions(java.lang.String, java.lang.String) public void copyFilePermissions(String from_file_name, String to_file_name) throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.platform.PlatformManager#createProcess(java.lang.String, boolean) public void createProcess(String command_line, boolean inherit_handles) throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.platform.PlatformManager#dispose() public void dispose() { } // @see org.gudy.azureus2.platform.PlatformManager#getApplicationCommandLine() public String getApplicationCommandLine() throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.platform.PlatformManager#getPlatformType() public int getPlatformType() { return PT_UNIX; } // @see org.gudy.azureus2.platform.PlatformManager#getUserDataDirectory() public String getUserDataDirectory() throws PlatformManagerException { String userhome = System.getProperty("user.home"); String temp_user_path = userhome + SystemProperties.SEP + "." + SystemProperties.APPLICATION_NAME.toLowerCase() + SystemProperties.SEP; synchronized (migrate_lock) { File home = new File(temp_user_path); if (!home.exists()) { //might be a fresh install or might be an old non-migrated install String old_home_path = userhome + SystemProperties.SEP + "." + SystemProperties.APPLICATION_NAME + SystemProperties.SEP; File old_home = new File(old_home_path); if (old_home.exists()) { //migrate String msg = "Migrating unix user config dir [" + old_home_path + "] ===> [" + temp_user_path + "]"; System.out.println(msg); Logger.log(new LogEvent(LOGID, "SystemProperties::getUserPath(Unix): " + msg)); try { old_home.renameTo(home); } catch (Throwable t) { t.printStackTrace(); Logger.log(new LogEvent(LOGID, "migration rename failed:", t)); } } } } return temp_user_path; } public String getComputerName() { String host = System.getenv( "HOST" ); if ( host != null && host.length() > 0 ){ return( host ); } return( null ); } // @see org.gudy.azureus2.platform.PlatformManager#getVersion() public String getVersion() throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.platform.PlatformManager#hasCapability(org.gudy.azureus2.platform.PlatformManagerCapabilities) public boolean hasCapability(PlatformManagerCapabilities capability) { return capabilitySet.contains(capability); } // @see org.gudy.azureus2.platform.PlatformManager#isApplicationRegistered() public boolean isApplicationRegistered() throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.platform.PlatformManager#performRecoverableFileDelete(java.lang.String) public void performRecoverableFileDelete(String file_name) throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.platform.PlatformManager#ping(java.net.InetAddress, java.net.InetAddress, org.gudy.azureus2.platform.PlatformManagerPingCallback) public void ping(InetAddress interface_address, InetAddress target, PlatformManagerPingCallback callback) throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.platform.PlatformManager#registerApplication() public void registerApplication() throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.platform.PlatformManager#addListener(org.gudy.azureus2.platform.PlatformManagerListener) public void addListener(PlatformManagerListener listener) { // No Listener Functionality } // @see org.gudy.azureus2.platform.PlatformManager#removeListener(org.gudy.azureus2.platform.PlatformManagerListener) public void removeListener(PlatformManagerListener listener) { // No Listener Functionality } // @see org.gudy.azureus2.platform.PlatformManager#setTCPTOSEnabled(boolean) public void setTCPTOSEnabled(boolean enabled) throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.platform.PlatformManager#testNativeAvailability(java.lang.String) public boolean testNativeAvailability(String name) throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.platform.PlatformManager#traceRoute(java.net.InetAddress, java.net.InetAddress, org.gudy.azureus2.platform.PlatformManagerPingCallback) public void traceRoute(InetAddress interface_address, InetAddress target, PlatformManagerPingCallback callback) throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.plugins.platform.PlatformManager#getLocation(long) public File getLocation(long location_id) throws PlatformManagerException { switch ((int)location_id) { case LOC_USER_DATA: return( new File( getUserDataDirectory() )); case LOC_DOCUMENTS: return new File(System.getProperty("user.home")); case LOC_MUSIC: case LOC_VIDEO: default: return( null ); } } // @see org.gudy.azureus2.plugins.platform.PlatformManager#isAdditionalFileTypeRegistered(java.lang.String, java.lang.String) public boolean isAdditionalFileTypeRegistered(String name, String type) throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.plugins.platform.PlatformManager#registerAdditionalFileType(java.lang.String, java.lang.String, java.lang.String, java.lang.String) public void registerAdditionalFileType(String name, String description, String type, String content_type) throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.plugins.platform.PlatformManager#showFile(java.lang.String) public void showFile(String file_name) throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.plugins.platform.PlatformManager#unregisterAdditionalFileType(java.lang.String, java.lang.String) public void unregisterAdditionalFileType(String name, String type) throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } // @see org.gudy.azureus2.platform.PlatformManager#getAzComputerID() public String getAzComputerID() throws PlatformManagerException { throw new PlatformManagerException(ERR_UNSUPPORTED); } public void requestUserAttention(int type, Object data) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } } azureus-4.3.0.6/org/gudy/azureus2/platform/unix/PlatformManagerUnixPlugin.java0000644000175000017500000002157011307603746026745 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.unix; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.update.UpdaterUtils; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.UserPrompterResultListener; import org.gudy.azureus2.plugins.Plugin; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ui.UIInstance; import org.gudy.azureus2.plugins.ui.UIManagerListener; /** * @author TuxPaper * @created Jul 24, 2007 * */ public class PlatformManagerUnixPlugin implements Plugin { private PluginInterface plugin_interface; // @see org.gudy.azureus2.plugins.Plugin#initialize(org.gudy.azureus2.plugins.PluginInterface) public void initialize(PluginInterface _plugin_interface) throws PluginException { plugin_interface = _plugin_interface; plugin_interface.getPluginProperties().setProperty("plugin.name", "Platform-Specific Support"); String version = "1.0"; // default version if plugin not present PlatformManager platform = PlatformManagerFactory.getPlatformManager(); if (platform.hasCapability(PlatformManagerCapabilities.GetVersion)) { try { version = platform.getVersion(); } catch (Throwable e) { Debug.printStackTrace(e); } } else { plugin_interface.getPluginProperties().setProperty("plugin.version.info", "Not required for this platform"); } plugin_interface.getPluginProperties().setProperty("plugin.version", version); plugin_interface.getUIManager().addUIListener(new UIManagerListener() { boolean done = false; public void UIDetached(UIInstance instance) { } public void UIAttached(UIInstance instance) { if (!done){ done = true; if (Constants.compareVersions(UpdaterUtils.getUpdaterPluginVersion(),"1.8.5") >= 0) { checkStartupScript(); } } } }); } /** * * * @since 3.0.1.7 */ private void checkStartupScript() { COConfigurationManager.setIntDefault("unix.script.lastaskversion", -1); int lastAskedVersion = COConfigurationManager.getIntParameter("unix.script.lastaskversion"); String sVersion = System.getProperty("azureus.script.version", "0"); int version = 0; try { version = Integer.parseInt(sVersion); } catch (Throwable t) { } Pattern pat = Pattern.compile("SCRIPT_VERSION=([0-9]+)", Pattern.CASE_INSENSITIVE); File oldFilePath; String sScriptFile = System.getProperty("azureus.script", null); if (sScriptFile != null && new File(sScriptFile).exists()) { oldFilePath = new File(sScriptFile); } else { oldFilePath = new File(SystemProperties.getApplicationPath(), "azureus"); if (!oldFilePath.exists()) { return; } } final String oldFilePathString = oldFilePath.getAbsolutePath(); String oldStartupScript; try { oldStartupScript = FileUtil.readFileAsString(oldFilePath, 65535, "utf8"); } catch (IOException e) { oldStartupScript = ""; } // Case: Script with no version, we update it, user selects restart. // Restart doesn't include azureus.script.version yet, so we // would normally prompt again. This fix reads the version // from the file if we don't have a version yet, thus preventing // the second restart message if (version == 0) { Matcher matcher = pat.matcher(oldStartupScript); if (matcher.find()) { String sScriptVersion = matcher.group(1); try { version = Integer.parseInt(sScriptVersion); } catch (Throwable t) { } } } if (version <= lastAskedVersion) { return; } InputStream stream = getClass().getResourceAsStream("startupScript"); try { String startupScript = FileUtil.readInputStreamAsString(stream, 65535, "utf8"); Matcher matcher = pat.matcher(startupScript); if (matcher.find()) { String sScriptVersion = matcher.group(1); int latestVersion = 0; try { latestVersion = Integer.parseInt(sScriptVersion); } catch (Throwable t) { } if (latestVersion > version) { boolean bNotChanged = oldStartupScript.indexOf("SCRIPT_NOT_CHANGED=0") > 0; boolean bInformUserManual = true; if (bNotChanged) { if (version >= 1) { // make the shutdown script copy it final String newFilePath = new File( SystemProperties.getApplicationPath(), "azureus.new").getAbsolutePath(); FileUtil.writeBytesAsFile(newFilePath, startupScript.getBytes()); String s = "cp \"" + newFilePath + "\" \"" + oldFilePathString + "\"; chmod +x \"" + oldFilePathString + "\"; echo \"Script Update successful\""; ScriptAfterShutdown.addExtraCommand(s); ScriptAfterShutdown.setRequiresExit(true); bInformUserManual = false; } else { // overwrite! try { FileUtil.writeBytesAsFile(oldFilePathString, startupScript.getBytes()); Runtime.getRuntime().exec(new String[] { findCommand( "chmod" ), "+x", oldStartupScript }); bInformUserManual = false; } catch (Throwable t) { } } } if (bInformUserManual) { final String newFilePath = new File( SystemProperties.getApplicationPath(), "azureus.new").getAbsolutePath(); FileUtil.writeBytesAsFile(newFilePath, startupScript.getBytes()); showScriptManualUpdateDialog(newFilePath, oldFilePathString, latestVersion); } else { showScriptAutoUpdateDialog(); } } } } catch (Throwable t) { t.printStackTrace(); } } private String findCommand( String name ) { final String[] locations = { "/bin", "/usr/bin" }; for ( String s: locations ){ File f = new File( s, name ); if ( f.exists() && f.canRead()){ return( f.getAbsolutePath()); } } return( name ); } private void showScriptManualUpdateDialog(String newFilePath, String oldFilePath, final int version) { final UIFunctions uif = UIFunctionsManager.getUIFunctions(); if (uif != null) { final String sCopyLine = "cp \"" + newFilePath + "\" \"" + oldFilePath + "\""; uif.promptUser( MessageText.getString("unix.script.new.title"), MessageText.getString("unix.script.new.text", new String[] { newFilePath, sCopyLine }), new String[] { MessageText.getString("unix.script.new.button.quit"), MessageText.getString("unix.script.new.button.continue"), MessageText.getString("unix.script.new.button.asknomore"), }, 0, null, null, false, 0, new UserPrompterResultListener() { public void prompterClosed(int answer) { if (answer == 0) { System.out.println("The line you should run:\n" + sCopyLine); uif.dispose(false, false); } else if (answer == 2) { COConfigurationManager.setParameter("unix.script.lastaskversion", version); } } }); } else { System.out.println("NO UIF"); } } private void showScriptAutoUpdateDialog() { final UIFunctions uif = UIFunctionsManager.getUIFunctions(); if (uif != null) { uif.promptUser(MessageText.getString("unix.script.new.auto.title"), MessageText.getString("unix.script.new.auto.text", new String[] {}), new String[] { MessageText.getString("UpdateWindow.restart"), MessageText.getString("UpdateWindow.restartLater"), }, 0, null, null, false, 0, new UserPrompterResultListener() { public void prompterClosed(int answer) { if (answer == 0) { uif.dispose(true, false); } } }); } else { System.out.println("NO UIF"); } } } azureus-4.3.0.6/org/gudy/azureus2/platform/unix/ScriptBeforeStartup.java0000644000175000017500000002001611233154532025577 0ustar adrianadrianpackage org.gudy.azureus2.platform.unix; import java.io.*; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Iterator; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import com.aelitis.azureus.core.impl.AzureusCoreSingleInstanceClient; import org.gudy.azureus2.plugins.PluginManager; public class ScriptBeforeStartup { private static PrintStream sysout; private static Object display; public static void main(String[] args) { // Set transitory so not everything gets loaded up. (such as the AEDiagnostic's tidy flag) System.setProperty("transitory.startup", "1"); // Since stdout will be in a shell script, redirect any stdout not coming // from us to stderr sysout = System.out; try { System.setOut(new PrintStream(new FileOutputStream("/dev/stderr"))); } catch (FileNotFoundException e) { } String mi_str = System.getProperty(PluginManager.PR_MULTI_INSTANCE); boolean mi = mi_str != null && mi_str.equalsIgnoreCase("true"); if (!mi) { boolean argsSent = new AzureusCoreSingleInstanceClient().sendArgs(args, 500); if (argsSent) { // azureus was open.. String msg = "Passing startup args to already-running " + Constants.APP_NAME + " java process listening on [127.0.0.1: 6880]"; log(msg); sysout.println("exit"); return; } } // If the after shutdown script didn't run or crapped out, then // don't run again.. String scriptAfterShutdown = COConfigurationManager.getStringParameter( "scriptaftershutdown", null); COConfigurationManager.removeParameter("scriptaftershutdown.exit"); COConfigurationManager.removeParameter("scriptaftershutdown"); COConfigurationManager.save(); if (scriptAfterShutdown != null) { log("Script after " + Constants.APP_NAME + " shutdown did not run.. running now"); sysout.println(scriptAfterShutdown); if (scriptAfterShutdown.indexOf("$0") < 0) { // doesn't have a restart.. add one sysout.println("echo \"Restarting Azureus..\""); sysout.println("$0\n"); } // exit is a requirement sysout.println("exit"); return; } String moz = getNewGreDir(); if (moz != null) { String s = "export MOZILLA_FIVE_HOME=\"" + moz + "\"\n" + "if [ \"$LD_LIBRARY_PATH x\" = \" x\" ] ; then\n" + " export LD_LIBRARY_PATH=$MOZILLA_FIVE_HOME;\n" + "else\n" + " export LD_LIBRARY_PATH=$MOZILLA_FIVE_HOME:$LD_LIBRARY_PATH\n" + "fi\n"; sysout.println(s); log("setting LD_LIBRARY_PATH to: $LD_LIBRARY_PATH"); log("setting MOZILLA_FIVE_HOME to: $MOZILLA_FIVE_HOME"); } else { log("GRE/XULRunner automatically found"); } } public static String getNewGreDir() { // SWT does a pretty awesome job at finding GRE, most cases this will work if (canOpenBrowser()) { return null; } // TODO: Store last successful dir somewhere and check that first // COConfigurationManager probably a bad idea, since that may load // Logger and who knows what other libraries String grePath = null; final String[] confList = { "/etc/gre64.conf", "/etc/gre.d/gre64.conf", "/etc/gre.conf", "/etc/gre.d/gre.conf", "/etc/gre.d/xulrunner.conf", "/etc/gre.d/libxul0d.conf" }; log("Auto-scanning for GRE/XULRunner. You can skip this by appending the GRE path to LD_LIBRARY_PATH and setting MOZILLA_FIVE_HOME."); try { Pattern pat = Pattern.compile("GRE_PATH=(.*)", Pattern.CASE_INSENSITIVE); for (int i = 0; i < confList.length; i++) { File file = new File(confList[i]); if (file.isFile() && file.canRead()) { log(" checking " + file + " for GRE_PATH"); String fileText = FileUtil.readFileAsString(file, 16384); if (fileText != null) { Matcher matcher = pat.matcher(fileText); if (matcher.find()) { String possibleGrePath = matcher.group(1); if (isValidGrePath(new File(possibleGrePath))) { grePath = possibleGrePath; break; } } } } } if (grePath == null) { final ArrayList possibleDirs = new ArrayList(); File libDir = new File("/usr"); libDir.listFiles(new FileFilter() { public boolean accept(File pathname) { if (pathname.getName().startsWith("lib")) { possibleDirs.add(pathname); } return false; } }); possibleDirs.add(new File("/usr/local")); possibleDirs.add(new File("/opt")); final String[] possibleDirNames = { "mozilla", "firefox", "seamonkey", "xulrunner", }; FileFilter ffIsPossibleDir = new FileFilter() { public boolean accept(File pathname) { String name = pathname.getName().toLowerCase(); for (int i = 0; i < possibleDirNames.length; i++) { if (name.startsWith(possibleDirNames[i])) { return true; } } return false; } }; for (Iterator iter = possibleDirs.iterator(); iter.hasNext();) { File dir = (File) iter.next(); File[] possibleFullDirs = dir.listFiles(ffIsPossibleDir); for (int i = 0; i < possibleFullDirs.length; i++) { log(" checking " + possibleFullDirs[i] + " for GRE"); if (isValidGrePath(possibleFullDirs[i])) { grePath = possibleFullDirs[i].getAbsolutePath(); break; } } if (grePath != null) { break; } } } if (grePath != null) { log("GRE found at " + grePath + "."); System.setProperty("org.eclipse.swt.browser.XULRunnerPath", grePath); } } catch (Throwable t) { log("Error trying to find suitable GRE: " + Debug.getNestedExceptionMessage(t)); grePath = null; } if (!canOpenBrowser()) { log("Can't create browser. Will try to set LD_LIBRARY_PATH and hope " + Constants.APP_NAME + " has better luck."); } return grePath; } private static boolean canOpenBrowser() { try { Class claDisplay = Class.forName("org.eclipse.swt.widgets.Display"); if (display != null) { display = claDisplay.newInstance(); } Class claShell = Class.forName("org.eclipse.swt.widgets.Shell"); Constructor shellConstruct = claShell.getConstructor(new Class[] { claDisplay, }); Object shell = shellConstruct.newInstance(new Object[] { display }); Class claBrowser = Class.forName("org.eclipse.swt.browser.Browser"); Constructor[] constructors = claBrowser.getConstructors(); for (int i = 0; i < constructors.length; i++) { if (constructors[i].getParameterTypes().length == 2) { Object browser = constructors[i].newInstance(new Object[] { shell, new Integer(0) }); Method methSetUrl = claBrowser.getMethod("setUrl", new Class[] { String.class }); methSetUrl.invoke(browser, new Object[] { "about:blank" }); break; } } Method methDisposeShell = claShell.getMethod("dispose", new Class[] {}); methDisposeShell.invoke(shell, new Object[] {}); return true; } catch (Throwable e) { log("Browser check failed with: " + Debug.getNestedExceptionMessage(e)); return false; } } private static boolean isValidGrePath(File dir) { if (!dir.isDirectory()) { return false; } if (new File(dir, "components/libwidget_gtk.so").exists() || new File(dir, "libwidget_gtk.so").exists()) { log(" Can not use GRE from " + dir + " as it's too old (GTK2 version required)."); return false; } // newer GRE doesn't have libwidget at all, but older ones do, and it's // gtk2, we are good to go if (new File(dir, "components/libwidget_gtk2.so").exists() || new File(dir, "libwidget_gtk2.so").exists()) { return true; } if (!new File(dir, "components/libxpcom.so").exists() && !new File(dir, "libxpcom.so").exists()) { log(" Can not use GRE from " + dir + " because it's missing libxpcom.so."); return false; } return true; } private static void log(String string) { sysout.println("echo \"" + string.replaceAll("\"", "\\\"") + "\""); } } azureus-4.3.0.6/org/gudy/azureus2/platform/unix/startupScript0000644000175000017500000001257110673376366023625 0ustar adrianadrian#!/bin/bash ######## CONFIGURATION OPTIONS ######## SCRIPT_NOT_CHANGED=0 # change this to 1 if you don't want your script overwritten! JAVA_PROGRAM_DIR="" # use full path to java bin dir, ex. "/usr/java/j2sdk1.4.2/bin/" #PROGRAM_DIR="/home/username/apps/azureus" # use full path to Azureus bin dir JAVA_ARGS="-Xmx128m" #export MOZILLA_FIVE_HOME="/path/to/gre" # Full path to GRE/Mozilla. When commenting out this line, also comment out the next line #if [ "$LD_LIBRARY_PATH x" = " x" ]; then export LD_LIBRARY_PATH=$MOZILLA_FIVE_HOME; else export LD_LIBRARY_PATH=$MOZILLA_FIVE_HOME:$LD_LIBRARY_PATH; fi ####################################### ######## YOU PROBABLY DO NOT WANT TO TOUCH ANYTHING BELOW! ######## SCRIPT_VERSION=2 START_CLASS="org.gudy.azureus2.ui.swt.Main" MSG_LOADING="Loading Azureus:" MSG_STARTING="Starting Azureus..." MSG2="Java exec found in " MSG3="OOPS, your java version is too old " MSG4="You need to upgrade to JRE 1.4.x or newer from http://java.sun.com" MSG5="Suitable java version found " MSG6="Configuring environment..." MSG7="OOPS, you don't seem to have a valid JRE " MSG8="OOPS, unable to locate java exec in " MSG9=" hierarchy" MSG10="Java exec not found in PATH, starting auto-search..." MSG11="Java exec found in PATH. Verifying..." MSG_AZEXIT="Exit from Azureus complete" MSG_TERMINATED="Azureus TERMINATED." MSG_RECHECK="Re-checking with GCJ (Sun Java recommended).." MSG_ISGCJ="Java is GCJ.. looking for Sun Java.." MSG_JAVABORK="Java appeared to have crashed:" SKIP_GCJ=1 look_for_java() { if command -v java &>/dev/null; then if check_version ; then echo $MSG11 return 0 fi fi echo $MSG10 JAVA_CHECK_DIRS="/usr/java/latest /usr/java /usr/lib/jvm/latest /usr/lib/jvm" for JAVADIR in $JAVA_CHECK_DIRS; do IFS=$'\n' potential_java_dirs=(`ls -1 "$JAVADIR" | sort | tac 2>/dev/null`) IFS= for D in "${potential_java_dirs[@]}"; do if [[ -d "$JAVADIR/$D" && -x "$JAVADIR/$D/bin/java" ]]; then JAVA_PROGRAM_DIR="$JAVADIR/$D/bin/" echo $MSG2 $JAVA_PROGRAM_DIR if check_version ; then return 0 else return 1 fi fi done done if [ $SKIP_GCJ ] ; then echo $MSG_RECHECK SKIP_GCJ= if look_for_java ; then return 0 else return 1 fi else echo $MSG8 "${JAVADIR}/" $MSG9 ; echo $MSG4 fi return 1 } check_version() { if [ $SKIP_GCJ ] ; then JAVA_ISGCJ=`"${JAVA_PROGRAM_DIR}java" -version 2>&1 | grep "gcj"` if [ ! "$JAVA_ISGCJ x" = " x" ] ; then echo $MSG_ISGCJ return 1 fi fi JAVA_HEADER=`"${JAVA_PROGRAM_DIR}java" -version 2>&1 | head -n 1` JAVA_IMPL=`echo ${JAVA_HEADER} | cut -f1 -d' '` if [ "$JAVA_IMPL" = "java" ] ; then VERSION=`echo ${JAVA_HEADER} | sed "s/java version \"\(.*\)\"/\1/"` if echo $VERSION | grep "^1.[0-3]" ; then echo $MSG3 "[${JAVA_PROGRAM_DIR}java = ${VERSION}]" ; echo $MSG4 return 1 else echo $MSG5 "[${JAVA_PROGRAM_DIR}java = ${VERSION}]" ; echo $MSG6 return 0 fi elif [ "$JAVA_IMPL" = "#" ] ; then echo $MSG_JAVABORK ${JAVA_PROGRAM_DIR}java -version 2>&1 exit 1 else echo $MSG7 "[${JAVA_PROGRAM_DIR}java = ${JAVA_IMPL}]" ; echo $MSG4 return 1 fi } runJavaOutput() { # assume we can write to the user's home.. ${JAVA_PROGRAM_DIR}java "${JAVA_ARGS}" \ -cp "${CLASSPATH}" \ -Djava.library.path="${PROGRAM_DIR}" \ -Dazureus.install.path="${PROGRAM_DIR}" \ -Dazureus.script="$0" \ $JAVA_PROPS \ "$@" > ~/azScript if [ -f ~/azScript ]; then chmod +x ~/azScript . ~/azScript rm ~/azScript fi } echo $MSG_STARTING # locate and test the java executable if [ "$JAVA_PROGRAM_DIR" == "" ]; then if ! look_for_java ; then exit 1 fi fi # get the app dir if not already defined if [ -z "$PROGRAM_DIR" ]; then PROGRAM_DIR=`dirname "$0"` PROGRAM_DIR=`cd "$PROGRAM_DIR"; pwd` else if [ "$(echo ${PROGRAM_DIR}/*.jar)" = "${PROGRAM_DIR}/*.jar" ]; then echo "You seem to have set an invalid PROGRAM_DIR, unable to continue!" exit 1 elif [ ! -f "${PROGRAM_DIR}/Azureus2.jar" ]; then echo "Unable to locate Azureus2.jar in $PROGRAM_DIR, aborting!" exit 1 fi fi # Change path here so we can do for loop on program dirs with spaces cd "${PROGRAM_DIR}" # build the classpath for FILE in ./*.jar; do CLASSPATH="${CLASSPATH:+${CLASSPATH}:}$FILE" done # setup Java System Properties (no spaces in values) JAVA_PROPS="-Dazureus.script.version=${SCRIPT_VERSION}" if [ ! "$JAVA_ISGCJ x" = " x" ] ; then JAVA_PROPS="$JAVA_PROPS -Dgnu.gcj.runtime.VMClassLoader.library_control=never" fi # some distros symlink application level plugins into the users's plugin directory.. # remove all symlinks in user's plugin directory find ~/.azureus/plugins -maxdepth 1 -type l -xtype d -exec rm {} \; runJavaOutput "org.gudy.azureus2.platform.unix.ScriptBeforeStartup" "$@"; echo $MSG_LOADING echo "${JAVA_PROGRAM_DIR}java ${JAVA_ARGS} -cp \"${CLASSPATH}\" -Djava.library.path=\"${PROGRAM_DIR}\" -Dazureus.install.path=\"${PROGRAM_DIR}\" -Dazureus.script=\"$0\" $JAVA_PROPS $START_CLASS $@" # Don't use "exec -a Azureus ..." here as exec quits this script after completion, # preventing ScriptAfterShutdown from running, which installs updates and does # restarts ${JAVA_PROGRAM_DIR}java "${JAVA_ARGS}" \ -cp "${CLASSPATH}" \ -Djava.library.path="${PROGRAM_DIR}" \ -Dazureus.install.path="${PROGRAM_DIR}" \ -Dazureus.script="$0" \ $JAVA_PROPS \ $START_CLASS "$@" echo $MSG_AZEXIT runJavaOutput "org.gudy.azureus2.platform.unix.ScriptAfterShutdown" "$@"; echo $MSG_TERMINATED azureus-4.3.0.6/org/gudy/azureus2/platform/PlatformManagerFactory.java0000644000175000017500000000561111202665360025257 0ustar adrianadrian/* * Created on 18-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.platform.PlatformManagerException; /** * @author parg * */ public class PlatformManagerFactory { protected static PlatformManager platform_manager; protected static AEMonitor class_mon = new AEMonitor( "PlatformManagerFactory"); public static PlatformManager getPlatformManager() { try{ boolean force_dummy = System.getProperty( "azureus.platform.manager.disable", "false" ).equals( "true" ); class_mon.enter(); if ( platform_manager == null && !force_dummy ){ try{ if ( getPlatformType() == PlatformManager.PT_WINDOWS ){ platform_manager = org.gudy.azureus2.platform.win32.PlatformManagerImpl.getSingleton(); }else if( getPlatformType() == PlatformManager.PT_MACOSX ){ platform_manager = org.gudy.azureus2.platform.macosx.PlatformManagerImpl.getSingleton(); }else if( getPlatformType() == PlatformManager.PT_UNIX ){ platform_manager = org.gudy.azureus2.platform.unix.PlatformManagerImpl.getSingleton(); } }catch( PlatformManagerException e ){ // exception will already have been logged }catch( Throwable e ){ Debug.printStackTrace(e); } } if ( platform_manager == null ){ platform_manager = org.gudy.azureus2.platform.dummy.PlatformManagerImpl.getSingleton(); } return( platform_manager ); }finally{ class_mon.exit(); } } public static int getPlatformType() { if (Constants.isWindows) { return (PlatformManager.PT_WINDOWS ); } else if (Constants.isOSX) { return (PlatformManager.PT_MACOSX ); } else if (Constants.isUnix) { return (PlatformManager.PT_UNIX ); } else { return (PlatformManager.PT_OTHER ); } } } azureus-4.3.0.6/org/gudy/azureus2/platform/PlatformManagerListener.java0000644000175000017500000000226110653601462025435 0ustar adrianadrian/* * Created on 30-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform; public interface PlatformManagerListener { public static final int ET_SHUTDOWN = 1; public static final int ET_SUSPEND = 2; public static final int ET_RESUME = 3; public void eventOccurred( int type ); } azureus-4.3.0.6/org/gudy/azureus2/platform/PlatformManager.java0000644000175000017500000001023211133516744023726 0ustar adrianadrian/* * Created on 18-Apr-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform; import java.net.InetAddress; import org.gudy.azureus2.plugins.platform.PlatformManagerException; /** * @author parg * */ public interface PlatformManager extends org.gudy.azureus2.plugins.platform.PlatformManager { public static final int PT_WINDOWS = 1; public static final int PT_OTHER = 2; public static final int PT_MACOSX = 3; public static final int PT_UNIX = 4; public static final int USER_REQUEST_INFO = 1; public static final int USER_REQUEST_WARNING = 2; public static final int USER_REQUEST_QUESTION = 3; public int getPlatformType(); public String getVersion() throws PlatformManagerException; public String getUserDataDirectory() throws PlatformManagerException; public boolean isApplicationRegistered() throws PlatformManagerException; public void registerApplication() throws PlatformManagerException; public String getApplicationCommandLine() throws PlatformManagerException; public void createProcess( String command_line, boolean inherit_handles ) throws PlatformManagerException; public void performRecoverableFileDelete( String file_name ) throws PlatformManagerException; /** * enable or disable the platforms support for TCP TOS * @param enabled * @throws PlatformManagerException */ public void setTCPTOSEnabled( boolean enabled ) throws PlatformManagerException; public void copyFilePermissions( String from_file_name, String to_file_name ) throws PlatformManagerException; public boolean testNativeAvailability( String name ) throws PlatformManagerException; public void traceRoute( InetAddress interface_address, InetAddress target, PlatformManagerPingCallback callback ) throws PlatformManagerException; public void ping( InetAddress interface_address, InetAddress target, PlatformManagerPingCallback callback ) throws PlatformManagerException; /** *

      Gets whether the platform manager supports a capability

      *

      Users of PlatformManager should check for supported capabilities before calling * the corresponding methods

      *

      Note that support for a particular capability may change arbitrarily in * the duration of the application session, but the manager will cache where * necessary.

      * @param capability A platform manager capability * @return True if the manager supports the capability */ public boolean hasCapability( PlatformManagerCapabilities capability ); /** * Disposes system resources. This method is optional. */ public void dispose(); public void addListener( PlatformManagerListener listener ); public void removeListener( PlatformManagerListener listener ); /** * @return * @throws PlatformManagerException */ String getAzComputerID() throws PlatformManagerException; /** * Requests the user's attention such as bouncing the application icon on OSX * * @param type * @param data * @throws PlatformManagerException */ public void requestUserAttention( int type, Object data) throws PlatformManagerException; } azureus-4.3.0.6/org/gudy/azureus2/platform/macosx/0000755000175000017500000000000011310377634021300 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/platform/macosx/PlatformManagerUpdateChecker.java0000644000175000017500000002233111257035264027653 0ustar adrianadrian/* * Created on 07-May-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.macosx; /** * @author parg * */ import java.io.*; import java.util.*; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.net.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.html.HTMLUtils; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.platform.*; import org.gudy.azureus2.plugins.utils.resourcedownloader.*; import org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader.*; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.update.*; import org.gudy.azureus2.pluginsimpl.update.sf.*; public class PlatformManagerUpdateChecker implements Plugin, UpdatableComponent { private static final LogIDs LOGID = LogIDs.CORE; public static final String UPDATE_NAME = "Platform-specific support"; public static final int RD_SIZE_RETRIES = 3; public static final int RD_SIZE_TIMEOUT = 10000; protected PluginInterface plugin_interface; public void initialize( PluginInterface _plugin_interface) { plugin_interface = _plugin_interface; plugin_interface.getPluginProperties().setProperty( "plugin.name", "Platform-Specific Support" ); String version = "1.0"; // default version if plugin not present PlatformManager platform = PlatformManagerFactory.getPlatformManager(); if ( platform.getPlatformType() == PlatformManager.PT_MACOSX ){ if ( platform.hasCapability( PlatformManagerCapabilities.GetVersion )){ try{ version = platform.getVersion(); }catch( Throwable e ){ Debug.printStackTrace(e); } } plugin_interface.getUpdateManager().registerUpdatableComponent( this, false ); }else{ plugin_interface.getPluginProperties().setProperty( "plugin.version.info", "Not required for this platform" ); } plugin_interface.getPluginProperties().setProperty( "plugin.version", version ); } public String getName() { return( UPDATE_NAME ); } public int getMaximumCheckTime() { return(( RD_SIZE_RETRIES * RD_SIZE_TIMEOUT )/1000); } public void checkForUpdate( final UpdateChecker checker ) { try{ SFPluginDetails sf_details = SFPluginDetailsLoaderFactory.getSingleton().getPluginDetails( plugin_interface.getPluginID()); String current_version = plugin_interface.getPluginVersion(); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "PlatformManager:OSX update check starts: current = " + current_version)); boolean current_az_is_cvs = Constants.isCVSVersion(); String sf_plugin_version = sf_details.getVersion(); String sf_comp_version = sf_plugin_version; if ( current_az_is_cvs ){ String sf_cvs_version = sf_details.getCVSVersion(); if ( sf_cvs_version.length() > 0 ){ // sf cvs version ALWAYS entry in _CVS sf_plugin_version = sf_cvs_version; sf_comp_version = sf_plugin_version.substring(0,sf_plugin_version.length()-4); } } String target_version = null; if ( sf_comp_version.length() == 0 || !Character.isDigit(sf_comp_version.charAt(0))){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "PlatformManager:OSX no valid version to check against (" + sf_comp_version + ")")); }else if ( Constants.compareVersions( current_version, sf_comp_version ) < 0 ){ target_version = sf_comp_version; } checker.reportProgress( "OSX: current = " + current_version + ", latest = " + sf_comp_version ); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "PlatformManager:OSX update required = " + (target_version != null))); if ( target_version != null ){ String target_download = sf_details.getDownloadURL(); if ( current_az_is_cvs ){ String sf_cvs_version = sf_details.getCVSVersion(); if ( sf_cvs_version.length() > 0 ){ target_download = sf_details.getCVSDownloadURL(); } } ResourceDownloaderFactory rdf = ResourceDownloaderFactoryImpl.getSingleton(); ResourceDownloader direct_rdl = rdf.create( new URL( target_download )); String torrent_download = Constants.AELITIS_TORRENTS; int slash_pos = target_download.lastIndexOf("/"); if ( slash_pos == -1 ){ torrent_download += target_download; }else{ torrent_download += target_download.substring( slash_pos + 1 ); } torrent_download += ".torrent"; ResourceDownloader torrent_rdl = rdf.create( new URL( torrent_download )); torrent_rdl = rdf.getSuffixBasedDownloader( torrent_rdl ); // create an alternate downloader with torrent attempt first ResourceDownloader alternate_rdl = rdf.getAlternateDownloader( new ResourceDownloader[]{ torrent_rdl, direct_rdl }); // get size here so it is cached rdf.getTimeoutDownloader(rdf.getRetryDownloader(alternate_rdl,RD_SIZE_RETRIES),RD_SIZE_TIMEOUT).getSize(); List update_desc = new ArrayList(); List desc_lines = HTMLUtils.convertHTMLToText( "", sf_details.getDescription()); update_desc.addAll( desc_lines ); List comment_lines = HTMLUtils.convertHTMLToText( " ", sf_details.getComment()); update_desc.addAll( comment_lines ); String[] update_d = new String[update_desc.size()]; update_desc.toArray( update_d ); final Update update = checker.addUpdate( UPDATE_NAME, update_d, target_version, alternate_rdl, Update.RESTART_REQUIRED_YES ); update.setDescriptionURL(sf_details.getInfoURL()); alternate_rdl.addListener( new ResourceDownloaderAdapter() { public boolean completed( final ResourceDownloader downloader, InputStream data ) { installUpdate( checker, update, downloader, data ); return( true ); } }); } }catch( Throwable e ){ Debug.printStackTrace( e ); checker.reportProgress( "Failed to load plugin details for the platform manager: " + Debug.getNestedExceptionMessage(e)); checker.failed(); }finally{ checker.completed(); } } protected void installUpdate( UpdateChecker checker, Update update, ResourceDownloader rd, InputStream data ) { ZipInputStream zip = null; try { data = update.verifyData( data, true ); rd.reportActivity( "Data verified successfully" ); UpdateInstaller installer = checker.createInstaller(); zip = new ZipInputStream(data); ZipEntry entry = null; while ((entry = zip.getNextEntry()) != null) { String name = entry.getName(); if (name.toLowerCase().startsWith("osx/")) { // OSX only files name = name.substring(4); // skip the directory entry if ( name.length() > 0 ){ rd.reportActivity("Adding update action for '" + name + "'"); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "PlatformManager:OSX adding action for '" + name + "'")); // handle sub-dirs String resource_name = name.replaceAll( "/", "-" ); installer.addResource( resource_name, zip, false ); String target = installer.getInstallDir() + File.separator + SystemProperties.getApplicationName() + ".app" + File.separator + name; installer.addMoveAction( resource_name, target ); if ( name.endsWith( ".jnilib" ) || name.endsWith( "JavaApplicationStub" )){ installer.addChangeRightsAction( "755", target ); } } } } } catch (Throwable e) { rd.reportActivity("Update install failed:" + e.getMessage()); }finally{ if ( zip != null ){ try{ zip.close(); }catch( Throwable e ){ } } } } protected List splitMultiLine( String indent, String text ) { int pos = 0; String lc_text = text.toLowerCase(); List lines = new ArrayList(); while( true ){ String line; int p1 = lc_text.indexOf( "
      ", pos ); if ( p1 == -1 ){ line = text.substring(pos); }else{ line = text.substring(pos,p1); pos = p1+4; } lines.add( indent + line ); if ( p1 == -1 ){ break; } } return( lines ); } } azureus-4.3.0.6/org/gudy/azureus2/platform/macosx/PListEditor.java0000644000175000017500000001437711055102670024351 0ustar adrianadrian/* * Created on Apr 1, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package org.gudy.azureus2.platform.macosx; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import org.gudy.azureus2.core3.util.FileUtil; public class PListEditor { private String plistFile; public PListEditor( String plistFile ) throws IOException { this.plistFile = plistFile; File file = new File( plistFile ); if ( !file.exists()){ throw( new IOException( "plist file '" + file + "' doesn't exist" )); } if ( !file.canWrite()){ throw( new IOException( "plist file '" + file + "' is read only" )); } } public void setFileTypeExtensions( String[] extensions ) throws IOException { StringBuffer value = new StringBuffer(); StringBuffer find = new StringBuffer(); find.append("(?s).*?CFBundleDocumentTypes\\s*.*?CFBundleTypeExtensions\\s*"); for(int i = 0 ; i < extensions.length ; i++) { value.append("\n\t\t\t\t"); value.append(extensions[i]); value.append(""); find.append(".*?"); find.append(extensions[i]); } value.append("\n\t\t\t"); find.append(".*?.*"); String match = "(?s)(CFBundleDocumentTypes\\s*.*?CFBundleTypeExtensions\\s*)(.*?)()"; setValue(find.toString(), match, value.toString()); } public void setSimpleStringValue( String key, String value) throws IOException { String find = "(?s).*?" + key + "\\s*" + "" + value + ".*"; String match = "(?s)(" + key + "\\s*" + ")(.*?)()"; setValue(find, match, value); } public void setArrayValues( String key, String valueType, String[] values) throws IOException { StringBuffer value = new StringBuffer(); StringBuffer find = new StringBuffer(); find.append("(?s).*?" + key + "\\s*" + ""); for(int i = 0 ; i < values.length ; i++) { find.append("\\s*<" + valueType + ">" + values[i] + ""); value.append("\n\t\t\t\t<" + valueType + ">"); value.append(values[i]); value.append(""); } find.append("\\s*.*"); value.append("\n\t\t\t"); String match = "(?s)(" + key + "\\s*)(.*?)()"; setValue(find.toString(),match,value.toString()); } private boolean isValuePresent( String match ) throws IOException { String fileContent = getFileContent(); //System.out.println("Searching for:\n" + match); return fileContent.matches(match); } /** * * @param find the regex expression to find if the value is already present * @param match the regex expression that will match for the replace, it needs to capture 3 groups, the 2nd one being replaced by value * @param value the value that replaces the 2nd match group */ private void setValue( String find, String match, String value) throws IOException { String fileContent = getFileContent(); if( !isValuePresent(find)) { //System.out.println("Changing " +plistFile); fileContent = fileContent.replaceFirst(match, "$1"+value + "$3"); setFileContent(fileContent); touchFile(); } } private String getFileContent() throws IOException { FileReader fr = null; try{ fr = new FileReader(plistFile); //max 32KB int length = 32 * 1024; char[] buffer = new char[length]; int offset = 0; int len = 0; while((len = fr.read(buffer,offset,length-offset)) > 0) { offset += len; } String result = new String(buffer,0,offset); return result; } finally { if(fr != null) { fr.close(); } } //return FileUtil.readFileAsString(new File(plistFile), 64*1024, "UTF-8" ); } private void setFileContent( String fileContent ) throws IOException { File file = new File( plistFile ); File backup_file = new File( plistFile + ".bak" ); if ( file.exists()){ if ( !FileUtil.copyFile( file, backup_file )){ throw( new IOException( "Failed to backup plist file prior to modification" )); } } boolean ok = false; try{ FileWriter fw = null; try{ fw = new FileWriter(plistFile); fw.write(fileContent); } finally { if( fw != null ){ fw.close(); ok = true; } } }finally{ if ( ok ){ backup_file.delete(); }else{ if ( backup_file.exists()){ File bork_file = new File( plistFile + ".bad" ); file.renameTo( bork_file ); file.delete(); backup_file.renameTo( file ); } } } } public void touchFile() { File file = new File( plistFile ); for(int i = 0 ; i <= 2 ; i++) { if(file != null) { String command[] = new String[] { "touch", file.getAbsolutePath() }; try{ Runtime.getRuntime().exec(command); } catch(Exception e) { e.printStackTrace(); } } file = file.getParentFile(); } } public static void main(String args[]) { try{ PListEditor editor = new PListEditor("/Applications/Vuze.app/Contents/Info.plist"); editor.setFileTypeExtensions(new String[] {"torrent","tor","vuze","vuz"}); editor.setSimpleStringValue("CFBundleName", "Vuze"); editor.setSimpleStringValue("CFBundleTypeName", "Vuze Download"); editor.setSimpleStringValue("CFBundleGetInfoString","Vuze"); editor.setArrayValues("CFBundleURLSchemes", "string", new String[] {"magnet","dht"}); }catch( Throwable e ){ e.printStackTrace(); } } } azureus-4.3.0.6/org/gudy/azureus2/platform/macosx/NativeInvocationBridge.java0000644000175000017500000000601611245654514026545 0ustar adrianadrianpackage org.gudy.azureus2.platform.macosx; /* * Created on 26-Mar-2005 * Created by James Yeh * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ import org.gudy.azureus2.core3.util.Debug; import java.io.File; /** *

      Performs PlatformManager and platform-specific tasks using bridges like Cocoa-Java -> ObjC

      *

      The methods supplied are intended to reflect those that can be dealt with a way other than * OSAScript. Ensure that the method signatures match those of PlatformManagerImpl, but * they should generally return a boolean (false for failure).

      * @version 1.0 */ public abstract class NativeInvocationBridge { private static NativeInvocationBridge instance; protected NativeInvocationBridge(){} /** * Gets the singleton * @return The NativeInvocationBridge singleton */ protected static final NativeInvocationBridge sharedInstance() { if (instance == null) { try { Object newInstance = Class.forName( "org.gudy.azureus2.platform.macosx.access.cocoa.CocoaJavaBridge").getConstructor( null).newInstance(null); instance = (NativeInvocationBridge) newInstance; } catch (Throwable e) { Debug.out(e); instance = new DummyBridge(); } } return instance; } protected final static boolean hasSharedInstance() { return instance != null; } /** * @see PlatformManager#performRecoverableFileDelete(java.io.File) */ protected boolean performRecoverableFileDelete(File path) {return false;} /** * @see PlatformManagerImpl#showInFinder(java.io.File) */ protected boolean showInFinder(File path, String fb) {return false;} /** *

      Gets whether the invocation bridge is available for use

      *

      This method is used to anticipate scenarios such as where the bridge will fail due to missing classpaths

      */ protected abstract boolean isEnabled(); /** * Disposes system resources */ protected void dispose(){} /** * A NativeInvocationBridge that does nothing; isEnabled() always returns false. */ private static class DummyBridge extends NativeInvocationBridge { public boolean isEnabled() { return false; } } } azureus-4.3.0.6/org/gudy/azureus2/platform/macosx/access/0000755000175000017500000000000011310377420022532 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/platform/macosx/access/jnilib/0000755000175000017500000000000011310377634024010 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/platform/macosx/access/jnilib/OSXDriveDetectListener.java0000644000175000017500000000037711243145500031152 0ustar adrianadrianpackage org.gudy.azureus2.platform.macosx.access.jnilib; import java.io.File; import java.util.Map; public interface OSXDriveDetectListener { public void driveDetected(File mount, Map driveInfo); public void driveRemoved(File mount, Map driveInfo); } azureus-4.3.0.6/org/gudy/azureus2/platform/macosx/access/jnilib/OSXAccess.java0000644000175000017500000000756311256315502026454 0ustar adrianadrian/* * Created on Jul 21, 2006 3:19:03 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.platform.macosx.access.jnilib; import java.io.File; import java.util.Map; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.drivedetector.DriveDetectorFactory; import com.aelitis.azureus.util.MapUtils; /** * @author TuxPaper * @created Jul 21, 2006 * * javah -d . -classpath ../../../../../../../../bin org.gudy.azureus2.platform.macosx.access.jnilib.OSXAccess */ public class OSXAccess { private static boolean bLoaded = false; private static boolean DEBUG = false; static { if (!Constants.isOSX_10_5_OrHigher || !loadLibrary("OSXAccess_10.5")) { loadLibrary("OSXAccess"); } } private static boolean loadLibrary(String lib) { try { SystemLoadLibrary(lib); System.out.println(lib + " v" + getVersion() + " Load complete!"); bLoaded = true; initDriveDetection(); } catch (Throwable e1) { Debug.out("Could not find lib" + lib + ".jnilib", e1); } return bLoaded; } private static void SystemLoadLibrary(String lib) throws Throwable { try { System.loadLibrary(lib); } catch (Throwable t) { // if launched from eclipse, updates will put it into ./Azureus.app/Contents/Resources/Java/dll try { File f = new File("Azureus.app/Contents/Resources/Java/dll/lib" + lib + ".jnilib"); System.load(f.getAbsolutePath()); } catch (Throwable t2) { throw t; } } } private static void initDriveDetection() { try { initializeDriveDetection(new OSXDriveDetectListener() { public void driveRemoved(File mount, Map driveInfo) { if (DEBUG) { System.out.println("UNMounted " + mount); for (Object key : driveInfo.keySet()) { Object val = driveInfo.get(key); System.out.println("\t" + key + "\t:\t" + val); } } DriveDetectorFactory.getDeviceDetector().driveRemoved(mount); } public void driveDetected(File mount, Map driveInfo) { if (DEBUG) { System.out.println("Mounted " + mount); for (Object key : driveInfo.keySet()) { Object val = driveInfo.get(key); System.out.println("\t" + key + "\t:\t" + val); } } boolean isOptical = MapUtils.getMapLong(driveInfo, "isOptical", 0) != 0; boolean isRemovable = MapUtils.getMapLong(driveInfo, "Removable", 0) != 0; boolean isWritable = MapUtils.getMapLong(driveInfo, "Writable", 0) != 0; if (isRemovable && isWritable && !isOptical) { DriveDetectorFactory.getDeviceDetector().driveDetected(mount); } } }); } catch (Throwable t) { } } public static final native int AEGetParamDesc(int theAppleEvent, int theAEKeyword, int desiredType, Object result); //AEDesc result public static final native String getVersion(); // 1.02 public static final native String getDocDir(); // 1.03 public static final native void memmove(byte[] dest, int src, int size); // 1.04 public static final native void initializeDriveDetection( OSXDriveDetectListener d); public static boolean isLoaded() { return bLoaded; } } azureus-4.3.0.6/org/gudy/azureus2/platform/macosx/access/cocoa/0000755000175000017500000000000011310377634023625 5ustar adrianadrianazureus-4.3.0.6/org/gudy/azureus2/platform/macosx/access/cocoa/CocoaJavaBridge.java0000644000175000017500000003023711156364760027444 0ustar adrianadrianpackage org.gudy.azureus2.platform.macosx.access.cocoa; /* * Created on 27-Mar-2005 * Created by James Yeh * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ import com.apple.cocoa.foundation.NSAppleEventDescriptor; import com.apple.cocoa.foundation.NSAppleScript; import com.apple.cocoa.foundation.NSAutoreleasePool; import com.apple.cocoa.foundation.NSMutableDictionary; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.platform.macosx.NativeInvocationBridge; import java.io.File; import java.text.MessageFormat; /** *

      Performs PlatformManager tasks using Cocoa-Java (FoundationKit only)

      *

      For now, operations are performed using NSAppleScript, rather than using NSWorkspace. * This is still significantly faster than calling the cmd-line osascript.

      * @version 2.1 Apr 2, 2005 */ public final class CocoaJavaBridge extends NativeInvocationBridge { /** * The path the Cocoa-Java class files are located at */ protected static final String CLASS_PATH = "/system/library/java"; private static final String REVEAL_SCRIPT_FORMAT = "tell application \"System Events\"\ntell application \"{0}\"\nactivate\nreveal (posix file \"{1}\" as alias)\nend tell\nend tell"; private static final String DEL_SCRIPT_FORMAT = "tell application \"Finder\" to move (posix file \"{0}\" as alias) to the trash"; /** * Main NSAutoreleasePool */ private int mainPool; protected AEMonitor classMon = new AEMonitor("CocoaJavaBridge:C"); private AEMonitor scriptMon = new AEMonitor("CocoaJavaBridge:S"); protected boolean isDisposed = false; protected RunnableDispatcher scriptDispatcher; public CocoaJavaBridge() { try { classMon.enter(); mainPool = NSAutoreleasePool.push(); scriptDispatcher = new RunnableDispatcher(); } finally { classMon.exit(); } } // interface implementation /** * {@inheritDoc} */ protected boolean performRecoverableFileDelete(File path) { if(!path.exists()){ return false; } NSAppleEventDescriptor result = executeScriptWithAsync(DEL_SCRIPT_FORMAT, new Object[]{path.getAbsolutePath()}); // quick hack here for people where things take a while - too scared to make it a // sync call as I don't know the code... if ( result != null ){ final int sleep = 25; int sleep_to_go = 2500; while( path.exists()){ if ( sleep_to_go <= 0 ){ break; } try{ Thread.sleep( sleep ); sleep_to_go -= sleep; }catch( Throwable e ){ break; } } if ( path.exists()){ Debug.outNoStack( "Gave up waiting for delete to complete for " + path ); } } return( result != null ); } /** * {@inheritDoc} */ protected boolean showInFinder(File path, String fileBrowserApp) { if (!path.exists()) return false; NSAppleEventDescriptor result = null; int pool = NSAutoreleasePool.push(); try { result = executeScriptWithAsync(REVEAL_SCRIPT_FORMAT, new Object[] { fileBrowserApp, path.getAbsolutePath() }); } finally { NSAutoreleasePool.pop(pool); } return (result != null); } /** * {@inheritDoc} */ protected boolean isEnabled() { // simple check with classpath return System.getProperty("java.class.path").toLowerCase().indexOf(CLASS_PATH) != -1; } // class utility methods /** *

      Executes a new instance of NSAppleScript

      *

      The method is wrapped in an autorelease pool and an AEMonitor. If there are * no format parameters, MessageFormat is not used to parse the format string, and * the format string will be treated as the source itself.

      * @see MessageFormat#format(String, Object...) * @see NSAppleScript#execute(com.apple.cocoa.foundation.NSMutableDictionary) */ protected final NSAppleEventDescriptor executeScript(String scriptFormat, Object[] params) { try { scriptMon.enter(); int pool = NSAutoreleasePool.push(); long start = System.currentTimeMillis(); String src; if(params == null || params.length == 0) { src = scriptFormat; } else { src = MessageFormat.format(scriptFormat, params); } Debug.outNoStack("Executing: \n" + src); NSAppleScript scp = new NSAppleScript(src); NSAppleEventDescriptor result = scp.execute(new NSMutableDictionary()); Debug.outNoStack(MessageFormat.format("Elapsed time: {0}ms\n", new Object[]{new Long(System.currentTimeMillis() - start)})); NSAutoreleasePool.pop(pool); return result; } finally { scriptMon.exit(); } } /** *

      Executes a new instance of NSAppleScript in a forked AEThread

      *

      This method always returns a "true" event descriptor. Callbacks are currently unsupported * , so in the event of an error, the logger is autuomatically notified.

      *

      The thread's runSupport method is wrapped in an autorelease pool. If there are * no format parameters, MessageFormat is not used to parse the format string, and * the format string will be treated as the source itself.

      * @see org.gudy.azureus2.core3.util.AEThread#runSupport() * @see MessageFormat#format(String, Object...) * @see NSAppleScript#execute(com.apple.cocoa.foundation.NSMutableDictionary) * @return NSAppleEventDescriptor.descriptorWithBoolean(true) */ protected final NSAppleEventDescriptor executeScriptWithNewThread(final String scriptFormat, final Object[] params) { Thread worker = new AEThread("ScriptObject", true) { public void runSupport() { int pool = NSAutoreleasePool.push(); long start = System.currentTimeMillis(); String src; if(params == null || params.length == 0) { src = scriptFormat; } else { src = MessageFormat.format(scriptFormat, params); } Debug.outNoStack("Executing: \n" + src); NSMutableDictionary errorInfo = new NSMutableDictionary(); if(new NSAppleScript(src).execute(errorInfo) == null) { Debug.out(String.valueOf(errorInfo.objectForKey(NSAppleScript.AppleScriptErrorMessage))); //logWarning(String.valueOf(errorInfo.objectForKey(NSAppleScript.AppleScriptErrorBriefMessage))); } Debug.outNoStack(MessageFormat.format("Elapsed time: {0}ms\n", new Object[]{new Long(System.currentTimeMillis() - start)})); NSAutoreleasePool.pop(pool); } }; worker.setPriority(Thread.NORM_PRIORITY - 1); worker.start(); return NSAppleEventDescriptor.descriptorWithBoolean(true); } /** *

      Asynchronously executes a new instance of NSAppleScript

      *

      This method always returns a "true" event descriptor. Callbacks are currently unsupported * , so in the event of an error, the logger is autuomatically notified.

      *

      The thread's runSupport method is wrapped in an autorelease pool. If there are * no format parameters, MessageFormat is not used to parse the format string, and * the format string will be treated as the source itself.

      * @see org.gudy.azureus2.core3.util.AEThread#runSupport() * @see MessageFormat#format(String, Object...) * @see NSAppleScript#execute(com.apple.cocoa.foundation.NSMutableDictionary) * @return NSAppleEventDescriptor.descriptorWithBoolean(true) */ protected final NSAppleEventDescriptor executeScriptWithAsync(final String scriptFormat, final Object[] params) { final AERunnable worker = new AERunnable() { public void runSupport() { int pool = NSAutoreleasePool.push(); long start = System.currentTimeMillis(); String src; if(params == null || params.length == 0) { src = scriptFormat; } else { src = MessageFormat.format(scriptFormat, params); } Debug.outNoStack("Executing: \n" + src); NSMutableDictionary errorInfo = new NSMutableDictionary(); if(new NSAppleScript(src).execute(errorInfo) == null) { Debug.out(String.valueOf(errorInfo.objectForKey(NSAppleScript.AppleScriptErrorMessage))); //logWarning(String.valueOf(errorInfo.objectForKey(NSAppleScript.AppleScriptErrorBriefMessage))); } Debug.outNoStack(MessageFormat.format("Elapsed time: {0}ms\n", new Object[]{new Long(System.currentTimeMillis() - start)})); NSAutoreleasePool.pop(pool); } }; AEThread t = new AEThread("ScriptObject", true) { public void runSupport() { scriptDispatcher.exec(worker); } }; t.setPriority(Thread.NORM_PRIORITY - 1); t.start(); return NSAppleEventDescriptor.descriptorWithBoolean(true); } /** * Logs a warning message to Logger. The class monitor is used. * @param message A warning message */ private void logWarning(String message) { try { classMon.enter(); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_WARNING, message)); } finally { classMon.exit(); } } // disposal /** * {@inheritDoc} */ protected void dispose() { try { classMon.enter(); if(!isDisposed) { Debug.outNoStack("Disposing Native PlatformManager..."); NSAutoreleasePool.pop(mainPool); isDisposed = true; Debug.outNoStack("Done"); } } finally { classMon.exit(); } } /** * {@inheritDoc} */ protected void finalize() throws Throwable { dispose(); super.finalize(); } /** * A dispatch object to help facilitate asychronous script execution (from the main thread) in a more * predictable fashion. */ private static class RunnableDispatcher { /** * Executes a Runnable object while synchronizing the RunnableDispatcher instance. * @param runnable A Runnable */ private void exec(Runnable runnable) { synchronized(this) { runnable.run(); } } } } azureus-4.3.0.6/org/gudy/azureus2/platform/macosx/PlatformManagerImpl.java0000644000175000017500000006421411267524620026053 0ustar adrianadrian/* * Created on 13-Mar-2004 * Created by James Yeh * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.platform.macosx; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetAddress; import java.text.MessageFormat; import java.util.HashSet; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerListener; import org.gudy.azureus2.platform.PlatformManagerPingCallback; import org.gudy.azureus2.platform.macosx.access.jnilib.OSXAccess; import org.gudy.azureus2.plugins.platform.PlatformManagerException; import com.apple.cocoa.application.NSApplication; /** * Performs platform-specific operations with Mac OS X * * @author James Yeh * @version 1.0 Initial Version * @see PlatformManager */ public class PlatformManagerImpl implements PlatformManager, AEDiagnosticsEvidenceGenerator { private static final LogIDs LOGID = LogIDs.CORE; protected static PlatformManagerImpl singleton; protected static AEMonitor class_mon = new AEMonitor("PlatformManager"); private static String fileBrowserName = "Finder"; //T: PlatformManagerCapabilities private final HashSet capabilitySet = new HashSet(); private volatile String computer_name; private volatile boolean computer_name_tried; /** * Gets the platform manager singleton, which was already initialized */ public static PlatformManagerImpl getSingleton() { return singleton; } /** * Tries to enable cocoa-java access and instantiates the singleton */ static { initializeSingleton(); } /** * Instantiates the singleton */ private static void initializeSingleton() { try { class_mon.enter(); singleton = new PlatformManagerImpl(); } catch (Throwable e) { Logger.log(new LogEvent(LOGID, "Failed to initialize platform manager" + " for Mac OS X", e)); } finally { class_mon.exit(); } COConfigurationManager.addAndFireParameterListener("FileBrowse.usePathFinder", new ParameterListener() { public void parameterChanged(String parameterName) { fileBrowserName = COConfigurationManager.getBooleanParameter("FileBrowse.usePathFinder") ? "Path Finder" : "Finder"; } }); } /** * Creates a new PlatformManager and initializes its capabilities */ public PlatformManagerImpl() { capabilitySet.add(PlatformManagerCapabilities.RecoverableFileDelete); capabilitySet.add(PlatformManagerCapabilities.ShowFileInBrowser); capabilitySet.add(PlatformManagerCapabilities.ShowPathInCommandLine); capabilitySet.add(PlatformManagerCapabilities.CreateCommandLineProcess); capabilitySet.add(PlatformManagerCapabilities.GetUserDataDirectory); capabilitySet.add(PlatformManagerCapabilities.UseNativeScripting); capabilitySet.add(PlatformManagerCapabilities.PlaySystemAlert); capabilitySet.add(PlatformManagerCapabilities.RequestUserAttention); if (OSXAccess.isLoaded()) { capabilitySet.add(PlatformManagerCapabilities.GetVersion); } AEDiagnostics.addEvidenceGenerator(this); checkPList(); } /** * {@inheritDoc} */ public int getPlatformType() { return PT_MACOSX; } /** * {@inheritDoc} */ public String getVersion() throws PlatformManagerException { if (!OSXAccess.isLoaded()) { throw new PlatformManagerException("Unsupported capability called on platform manager"); } return OSXAccess.getVersion(); } protected PListEditor getPList() throws IOException { String plist = System.getProperty("user.dir") + SystemProperties.SEP+ SystemProperties.getApplicationName() + ".app/Contents/Info.plist"; if (!new File(plist).exists()) { Debug.out("WARNING: plist not found: " + plist); return null; } PListEditor editor = new PListEditor( plist ); return( editor ); } protected void checkPList() { try{ PListEditor editor = getPList(); if (editor == null) { return; } editor.setFileTypeExtensions(new String[] {"torrent","tor","vuze","vuz"}); editor.setSimpleStringValue("CFBundleName", "Vuze"); editor.setSimpleStringValue("CFBundleTypeName", "Vuze Download"); editor.setSimpleStringValue("CFBundleGetInfoString","Vuze"); editor.setSimpleStringValue("CFBundleShortVersionString",Constants.AZUREUS_VERSION); editor.setSimpleStringValue("CFBundleVersion",Constants.AZUREUS_VERSION); editor.setArrayValues("CFBundleURLSchemes", "string", new String[] { "magnet", "dht", "vuze"}); }catch( Throwable e ){ Debug.out( "Failed to update plist", e ); } } protected void touchPList() { try{ PListEditor editor = getPList(); editor.touchFile(); }catch( Throwable e ){ Debug.out( "Failed to touch plist", e ); } } /** * {@inheritDoc} * @see org.gudy.azureus2.core3.util.SystemProperties#getUserPath() */ public String getUserDataDirectory() throws PlatformManagerException { return new File(System.getProperty("user.home") + "/Library/Application Support/" + SystemProperties.APPLICATION_NAME).getPath() + SystemProperties.SEP; } public String getComputerName() { if ( computer_name_tried ){ return( computer_name ); } try{ String result = null; String hostname = System.getenv( "HOSTNAME" ); if ( hostname != null && hostname.length() > 0 ){ result = hostname; } if ( result == null ){ String host = System.getenv( "HOST" ); if ( host != null && host.length() > 0 ){ result = host; } } if ( result == null ){ try{ String[] to_run = new String[3]; to_run[0] = "/bin/sh"; to_run[1] = "-c"; to_run[2] = "echo $HOSTNAME"; Process p = Runtime.getRuntime().exec( to_run ); if ( p.waitFor() == 0 ){ String output = ""; InputStream is = p.getInputStream(); while( true ){ byte[] buffer = new byte[1024]; int len = is.read( buffer ); if ( len <= 0 ){ break; } output += new String( buffer, 0, len ); if ( output.length() > 64 ){ break; } } if ( output.length() > 0 ){ result = output.trim(); int pos = result.indexOf(' '); if ( pos != -1 ){ result = result.substring( 0, pos ).trim(); } } } }catch( Throwable e ){ } } if ( result != null ){ int pos = result.lastIndexOf( '.' ); if ( pos != -1 ){ result = result.substring( 0, pos ); } if ( result.length() > 0 ){ if ( result.length() > 32 ){ result = result.substring( 0, 32 ); } computer_name = result; } } return( computer_name ); }finally{ computer_name_tried = true; } } public File getLocation( long location_id ) throws PlatformManagerException { switch ((int)location_id) { case LOC_USER_DATA: return new File(getUserDataDirectory()); case LOC_DOCUMENTS: try { return new File(OSXAccess.getDocDir()); } catch (Throwable e) { // throws UnsatisfiedLinkError if no osxaccess // Sometimes throws NullPointerException // Usually in user.home + Documents return new File(System.getProperty("user.home"), "Documents"); } case LOC_MUSIC: case LOC_VIDEO: default: return( null ); } } /** * Not implemented; returns True */ public boolean isApplicationRegistered() throws PlatformManagerException { return true; } public String getApplicationCommandLine() throws PlatformManagerException { try{ String bundle_path = System.getProperty("user.dir") +SystemProperties.SEP+ SystemProperties.getApplicationName() + ".app"; File osx_app_bundle = new File( bundle_path ).getAbsoluteFile(); if( !osx_app_bundle.exists() ) { String msg = "OSX app bundle not found: [" +osx_app_bundle.toString()+ "]"; System.out.println( msg ); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, msg)); throw new PlatformManagerException( msg ); } return "open -a \"" +osx_app_bundle.toString()+ "\""; //return osx_app_bundle.toString() +"/Contents/MacOS/JavaApplicationStub"; } catch( Throwable t ){ t.printStackTrace(); return null; } } public boolean isAdditionalFileTypeRegistered( String name, // e.g. "BitTorrent" String type ) // e.g. ".torrent" throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void unregisterAdditionalFileType( String name, // e.g. "BitTorrent" String type ) // e.g. ".torrent" throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void registerAdditionalFileType( String name, // e.g. "BitTorrent" String description, // e.g. "BitTorrent File" String type, // e.g. ".torrent" String content_type ) // e.g. "application/x-bittorrent" throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void registerApplication() throws PlatformManagerException { touchPList(); } /** * {@inheritDoc} */ public void createProcess(String cmd, boolean inheritsHandles) throws PlatformManagerException { try { performRuntimeExec(cmd.split(" ")); } catch (Throwable e) { throw new PlatformManagerException("Failed to create process", e); } } /** * {@inheritDoc} */ public void performRecoverableFileDelete(String path) throws PlatformManagerException { File file = new File(path); if(!file.exists()) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Cannot find " + file.getName())); return; } boolean useOSA = !NativeInvocationBridge.sharedInstance().isEnabled() || !NativeInvocationBridge.sharedInstance().performRecoverableFileDelete(file); if(useOSA) { try { StringBuffer sb = new StringBuffer(); sb.append("tell application \""); sb.append("Finder"); sb.append("\" to move (posix file \""); sb.append(path); sb.append("\" as alias) to the trash"); performOSAScript(sb); } catch (Throwable e) { throw new PlatformManagerException("Failed to move file", e); } } } /** * {@inheritDoc} */ public boolean hasCapability(PlatformManagerCapabilities capability) { return capabilitySet.contains(capability); } /** * {@inheritDoc} */ public void dispose() { try { if (NativeInvocationBridge.hasSharedInstance()) { NativeInvocationBridge.sharedInstance().dispose(); } } catch (Throwable t) { Debug.out("Problem disposing NativeInvocationBridge", t); } } /** * {@inheritDoc} */ public void setTCPTOSEnabled(boolean enabled) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void copyFilePermissions( String from_file_name, String to_file_name ) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } /** * {@inheritDoc} */ public void showFile(String path) throws PlatformManagerException { File file = new File(path); if(!file.exists()) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Cannot find " + file.getName())); throw new PlatformManagerException("File not found"); } showInFinder(file); } // Public utility methods not shared across the interface /** * Plays the system alert (the jingle is specified by the user in System Preferences) */ public void playSystemAlert() { try { performRuntimeExec(new String[]{"beep"}); } catch (IOException e) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Cannot play system alert")); Logger.log(new LogEvent(LOGID, "", e)); } } /** *

      Shows the given file or directory in Finder

      * @param path Absolute path to the file or directory */ public void showInFinder(File path) { boolean useOSA = !NativeInvocationBridge.sharedInstance().isEnabled() || !NativeInvocationBridge.sharedInstance().showInFinder(path,fileBrowserName); if(useOSA) { StringBuffer sb = new StringBuffer(); sb.append("tell application \""); sb.append(getFileBrowserName()); sb.append("\"\n"); sb.append("reveal (posix file \""); sb.append(path); sb.append("\" as alias)\n"); sb.append("activate\n"); sb.append("end tell\n"); try { performOSAScript(sb); } catch (IOException e) { Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, e .getMessage())); } } } /** *

      Shows the given file or directory in Terminal by executing cd /absolute/path/to

      * @param path Absolute path to the file or directory */ public void showInTerminal(String path) { showInTerminal(new File(path)); } /** *

      Shows the given file or directory in Terminal by executing cd /absolute/path/to

      * @param path Absolute path to the file or directory */ public void showInTerminal(File path) { if (path.isFile()) { path = path.getParentFile(); } if (path != null && path.isDirectory()) { StringBuffer sb = new StringBuffer(); sb.append("tell application \""); sb.append("Terminal"); sb.append("\" to do script \"cd "); sb.append(path.getAbsolutePath().replaceAll(" ", "\\ ")); sb.append("\""); try { performOSAScript(sb); } catch (IOException e) { Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, e .getMessage())); } } else { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Cannot find " + path.getName())); } } // Internal utility methods /** * Compiles a new AppleScript instance and runs it * @param cmd AppleScript command to execute; do not surround command with extra quotation marks * @return Output of the script * @throws IOException If the script failed to execute */ protected static String performOSAScript(CharSequence cmd) throws IOException { return performOSAScript(new CharSequence[]{cmd}); } /** * Compiles a new AppleScript instance and runs it * @param cmds AppleScript Sequence of commands to execute; do not surround command with extra quotation marks * @return Output of the script * @throws IOException If the script failed to execute */ protected static String performOSAScript(CharSequence[] cmds) throws IOException { long start = System.currentTimeMillis(); Debug.outNoStack("Executing OSAScript: "); for (int i = 0; i < cmds.length; i++) { Debug.outNoStack("\t" + cmds[i]); } String[] cmdargs = new String[2 * cmds.length + 1]; cmdargs[0] = "osascript"; for (int i = 0; i < cmds.length; i++) { cmdargs[i * 2 + 1] = "-e"; cmdargs[i * 2 + 2] = String.valueOf(cmds[i]); } Process osaProcess = performRuntimeExec(cmdargs); BufferedReader reader = new BufferedReader(new InputStreamReader(osaProcess.getInputStream())); String line = reader.readLine(); reader.close(); Debug.outNoStack("OSAScript Output: " + line); reader = new BufferedReader(new InputStreamReader(osaProcess.getErrorStream())); String errorMsg = reader.readLine(); reader.close(); Debug.outNoStack("OSAScript Error (if any): " + errorMsg); Debug.outNoStack(MessageFormat.format("OSAScript execution ended ({0}ms)", new Object[]{String.valueOf(System.currentTimeMillis() - start)})); try { osaProcess.destroy(); } catch (Throwable t) { //ignore } if (errorMsg != null) { throw new IOException(errorMsg); } return line; } /** * Compiles a new AppleScript instance and runs it * @param script AppleScript file (.scpt) to execute * @return Output of the script * @throws IOException If the script failed to execute */ protected static String performOSAScript(File script) throws IOException { long start = System.currentTimeMillis(); Debug.outNoStack("Executing OSAScript from file: " + script.getPath()); Process osaProcess = performRuntimeExec(new String[]{"osascript", script.getPath()}); BufferedReader reader = new BufferedReader(new InputStreamReader(osaProcess.getInputStream())); String line = reader.readLine(); reader.close(); Debug.outNoStack("OSAScript Output: " + line); reader = new BufferedReader(new InputStreamReader(osaProcess.getErrorStream())); String errorMsg = reader.readLine(); reader.close(); Debug.outNoStack("OSAScript Error (if any): " + errorMsg); Debug.outNoStack(MessageFormat.format("OSAScript execution ended ({0}ms)", new Object[]{String.valueOf(System.currentTimeMillis() - start)})); try { osaProcess.destroy(); } catch (Throwable t) { //ignore } if (errorMsg != null) { throw new IOException(errorMsg); } return line; } /** * Compiles a new AppleScript instance to the specified location * @param cmd Command to compile; do not surround command with extra quotation marks * @param destination Destination location of the AppleScript file * @return True if compiled successfully */ protected static boolean compileOSAScript(CharSequence cmd, File destination) { return compileOSAScript(new CharSequence[]{cmd}, destination); } /** * Compiles a new AppleScript instance to the specified location * @param cmds Sequence of commands to compile; do not surround command with extra quotation marks * @param destination Destination location of the AppleScript file * @return True if compiled successfully */ protected static boolean compileOSAScript(CharSequence[] cmds, File destination) { long start = System.currentTimeMillis(); Debug.outNoStack("Compiling OSAScript: " + destination.getPath()); for (int i = 0; i < cmds.length; i++) { Debug.outNoStack("\t" + cmds[i]); } String[] cmdargs = new String[2 * cmds.length + 3]; cmdargs[0] = "osacompile"; for (int i = 0; i < cmds.length; i++) { cmdargs[i * 2 + 1] = "-e"; cmdargs[i * 2 + 2] = String.valueOf(cmds[i]); } cmdargs[cmdargs.length - 2] = "-o"; cmdargs[cmdargs.length - 1] = destination.getPath(); String errorMsg; try { Process osaProcess = performRuntimeExec(cmdargs); BufferedReader reader = new BufferedReader(new InputStreamReader(osaProcess.getErrorStream())); errorMsg = reader.readLine(); reader.close(); } catch (IOException e) { Debug.outNoStack("OSACompile Execution Failed: " + e.getMessage()); Debug.printStackTrace(e); return false; } Debug.outNoStack("OSACompile Error (if any): " + errorMsg); Debug.outNoStack(MessageFormat.format("OSACompile execution ended ({0}ms)", new Object[]{String.valueOf(System.currentTimeMillis() - start)})); return (errorMsg == null); } /** * @see Runtime#exec(String[]) */ protected static Process performRuntimeExec(String[] cmdargs) throws IOException { try { return Runtime.getRuntime().exec(cmdargs); } catch (IOException e) { Logger.log(new LogAlert(LogAlert.UNREPEATABLE, e.getMessage(), e)); throw e; } } /** *

      Gets the preferred file browser name

      *

      Currently supported browsers are Path Finder and Finder. If Path Finder is currently running * (not just installed), then "Path Finder is returned; else, "Finder" is returned.

      * @return "Path Finder" if it is currently running; else "Finder" */ private static String getFileBrowserName() { return fileBrowserName; } public boolean testNativeAvailability( String name ) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void traceRoute( InetAddress interface_address, InetAddress target, PlatformManagerPingCallback callback ) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void ping( InetAddress interface_address, InetAddress target, PlatformManagerPingCallback callback ) throws PlatformManagerException { throw new PlatformManagerException("Unsupported capability called on platform manager"); } public void addListener( PlatformManagerListener listener ) { } public void removeListener( PlatformManagerListener listener ) { } // @see org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator#generate(org.gudy.azureus2.core3.util.IndentWriter) public void generate(IndentWriter writer) { writer.println("PlatformManager: MacOSX"); try { writer.indent(); if (OSXAccess.isLoaded()) { try { writer.println("Version " + getVersion()); writer.println("User Data Dir: " + getLocation(LOC_USER_DATA)); writer.println("User Doc Dir: " + getLocation(LOC_DOCUMENTS)); } catch (PlatformManagerException e) { } } else { writer.println("Not loaded"); } writer.println("Computer Name: " + getComputerName()); } finally { writer.exdent(); } } // @see org.gudy.azureus2.platform.PlatformManager#getAzComputerID() public String getAzComputerID() throws PlatformManagerException { throw new PlatformManagerException( "Unsupported capability called on platform manager"); } /** * If the application is not active causes the application icon at the bottom to bounce until the application becomes active * If the application is already active then this method does nothing. * * Note: This is an undocumented feature from Apple so it's behavior may change without warning * * @param type one of USER_REQUEST_INFO, USER_REQUEST_WARNING */ public void requestUserAttention(int type, Object data) throws PlatformManagerException { try { NSApplication app = NSApplication.sharedApplication(); if (type == USER_REQUEST_INFO) { app.requestUserAttention(NSApplication.UserAttentionRequestInformational); } else if (type == USER_REQUEST_WARNING) { app.requestUserAttention(NSApplication.UserAttentionRequestCritical); } else if (type == USER_REQUEST_QUESTION) { // not applicable } } catch (Exception e) { throw new PlatformManagerException("Failed to request user attention", e); } } } azureus-4.3.0.6/org/apache/0000755000175000017500000000000011310377564014655 5ustar adrianadrianazureus-4.3.0.6/org/apache/commons/0000755000175000017500000000000011310377564016330 5ustar adrianadrianazureus-4.3.0.6/org/apache/commons/lang/0000755000175000017500000000000011310377632017245 5ustar adrianadrianazureus-4.3.0.6/org/apache/commons/lang/IntHashMap.java0000644000175000017500000002700411006705350022101 0ustar adrianadrian/* * Copyright 2002-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Note: originally released under the GNU LGPL v2.1, * but rereleased by the original author under the ASF license (above). */ package org.apache.commons.lang; /** *

      A hash map that uses primitive ints for the key rather than objects.

      * *

      Note that this class is for internal optimization purposes only, and may * not be supported in future releases of Jakarta Commons Lang. Utilities of * this sort may be included in future releases of Jakarta Commons Collections.

      * * @author Justin Couch * @author Alex Chaffee (alex@apache.org) * @author Stephen Colebourne * @since 2.0 * @version $Revision: 1.1 $ * @see java.util.HashMap */ class IntHashMap { /** * The hash table data. */ private transient Entry table[]; /** * The total number of entries in the hash table. */ private transient int count; /** * The table is rehashed when its size exceeds this threshold. (The * value of this field is (int)(capacity * loadFactor).) * * @serial */ private int threshold; /** * The load factor for the hashtable. * * @serial */ private float loadFactor; /** *

      Innerclass that acts as a datastructure to create a new entry in the * table.

      */ private static class Entry { int hash; int key; Object value; Entry next; /** *

      Create a new entry with the given values.

      * * @param hash The code used to hash the object with * @param key The key used to enter this in the table * @param value The value for this key * @param next A reference to the next entry in the table */ protected Entry(int hash, int key, Object value, Entry next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } } /** *

      Constructs a new, empty hashtable with a default capacity and load * factor, which is 20 and 0.75 respectively.

      */ public IntHashMap() { this(20, 0.75f); } /** *

      Constructs a new, empty hashtable with the specified initial capacity * and default load factor, which is 0.75.

      * * @param initialCapacity the initial capacity of the hashtable. * @throws IllegalArgumentException if the initial capacity is less * than zero. */ public IntHashMap(int initialCapacity) { this(initialCapacity, 0.75f); } /** *

      Constructs a new, empty hashtable with the specified initial * capacity and the specified load factor.

      * * @param initialCapacity the initial capacity of the hashtable. * @param loadFactor the load factor of the hashtable. * @throws IllegalArgumentException if the initial capacity is less * than zero, or if the load factor is nonpositive. */ public IntHashMap(int initialCapacity, float loadFactor) { super(); if (initialCapacity < 0) { throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); } if (loadFactor <= 0) { throw new IllegalArgumentException("Illegal Load: " + loadFactor); } if (initialCapacity == 0) { initialCapacity = 1; } this.loadFactor = loadFactor; table = new Entry[initialCapacity]; threshold = (int) (initialCapacity * loadFactor); } /** *

      Returns the number of keys in this hashtable.

      * * @return the number of keys in this hashtable. */ public int size() { return count; } /** *

      Tests if this hashtable maps no keys to values.

      * * @return true if this hashtable maps no keys to values; * false otherwise. */ public boolean isEmpty() { return count == 0; } /** *

      Tests if some key maps into the specified value in this hashtable. * This operation is more expensive than the containsKey * method.

      * *

      Note that this method is identical in functionality to containsValue, * (which is part of the Map interface in the collections framework).

      * * @param value a value to search for. * @return true if and only if some key maps to the * value argument in this hashtable as * determined by the equals method; * false otherwise. * @throws NullPointerException if the value is null. * @see #containsKey(int) * @see #containsValue(Object) * @see java.util.Map */ public boolean contains(Object value) { if (value == null) { throw new NullPointerException(); } Entry tab[] = table; for (int i = tab.length; i-- > 0;) { for (Entry e = tab[i]; e != null; e = e.next) { if (e.value.equals(value)) { return true; } } } return false; } /** *

      Returns true if this HashMap maps one or more keys * to this value.

      * *

      Note that this method is identical in functionality to contains * (which predates the Map interface).

      * * @param value value whose presence in this HashMap is to be tested. * @see java.util.Map * @since JDK1.2 */ public boolean containsValue(Object value) { return contains(value); } /** *

      Tests if the specified object is a key in this hashtable.

      * * @param key possible key. * @return true if and only if the specified object is a * key in this hashtable, as determined by the equals * method; false otherwise. * @see #contains(Object) */ public boolean containsKey(int key) { Entry tab[] = table; int hash = key; int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry e = tab[index]; e != null; e = e.next) { if (e.hash == hash) { return true; } } return false; } /** *

      Returns the value to which the specified key is mapped in this map.

      * * @param key a key in the hashtable. * @return the value to which the key is mapped in this hashtable; * null if the key is not mapped to any value in * this hashtable. * @see #put(int, Object) */ public Object get(int key) { Entry tab[] = table; int hash = key; int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry e = tab[index]; e != null; e = e.next) { if (e.hash == hash) { return e.value; } } return null; } /** *

      Increases the capacity of and internally reorganizes this * hashtable, in order to accommodate and access its entries more * efficiently.

      * *

      This method is called automatically when the number of keys * in the hashtable exceeds this hashtable's capacity and load * factor.

      */ protected void rehash() { int oldCapacity = table.length; Entry oldMap[] = table; int newCapacity = oldCapacity * 2 + 1; Entry newMap[] = new Entry[newCapacity]; threshold = (int) (newCapacity * loadFactor); table = newMap; for (int i = oldCapacity; i-- > 0;) { for (Entry old = oldMap[i]; old != null;) { Entry e = old; old = old.next; int index = (e.hash & 0x7FFFFFFF) % newCapacity; e.next = newMap[index]; newMap[index] = e; } } } /** *

      Maps the specified key to the specified * value in this hashtable. The key cannot be * null.

      * *

      The value can be retrieved by calling the get method * with a key that is equal to the original key.

      * * @param key the hashtable key. * @param value the value. * @return the previous value of the specified key in this hashtable, * or null if it did not have one. * @throws NullPointerException if the key is null. * @see #get(int) */ public Object put(int key, Object value) { // Makes sure the key is not already in the hashtable. Entry tab[] = table; int hash = key; int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry e = tab[index]; e != null; e = e.next) { if (e.hash == hash) { Object old = e.value; e.value = value; return old; } } if (count >= threshold) { // Rehash the table if the threshold is exceeded rehash(); tab = table; index = (hash & 0x7FFFFFFF) % tab.length; } // Creates the new entry. Entry e = new Entry(hash, key, value, tab[index]); tab[index] = e; count++; return null; } /** *

      Removes the key (and its corresponding value) from this * hashtable.

      * *

      This method does nothing if the key is not present in the * hashtable.

      * * @param key the key that needs to be removed. * @return the value to which the key had been mapped in this hashtable, * or null if the key did not have a mapping. */ public Object remove(int key) { Entry tab[] = table; int hash = key; int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash) { if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } count--; Object oldValue = e.value; e.value = null; return oldValue; } } return null; } /** *

      Clears this hashtable so that it contains no keys.

      */ public synchronized void clear() { Entry tab[] = table; for (int index = tab.length; --index >= 0;) { tab[index] = null; } count = 0; } } azureus-4.3.0.6/org/apache/commons/lang/Entities.java0000644000175000017500000007402211006705346021700 0ustar adrianadrian/* * Copyright 2002-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.lang; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; /** *

      Provides HTML and XML entity utilities.

      * * @see ISO Entities * @see
      HTML 3.2 Character Entities for ISO Latin-1 * @see
      HTML 4.0 Character entity references * @see
      HTML 4.01 Character References * @see
      HTML 4.01 Code positions * * @author Alexander Day Chaffee * @author Gary Gregory * @since 2.0 * @version $Id: Entities.java,v 1.1 2008/05/02 15:43:01 gudy Exp $ */ public class Entities { private static final String[][] BASIC_ARRAY = { {"quot", "34"}, // " - double-quote {"amp", "38"}, // & - ampersand {"lt", "60"}, // < - less-than {"gt", "62"}, // > - greater-than }; private static final String[][] APOS_ARRAY = { {"apos", "39"}, // XML apostrophe }; // package scoped for testing static final String[][] ISO8859_1_ARRAY = { {"nbsp", "160"}, // non-breaking space {"iexcl", "161"}, //inverted exclamation mark {"cent", "162"}, //cent sign {"pound", "163"}, //pound sign {"curren", "164"}, //currency sign {"yen", "165"}, //yen sign = yuan sign {"brvbar", "166"}, //broken bar = broken vertical bar {"sect", "167"}, //section sign {"uml", "168"}, //diaeresis = spacing diaeresis {"copy", "169"}, // - copyright sign {"ordf", "170"}, //feminine ordinal indicator {"laquo", "171"}, //left-pointing double angle quotation mark = left pointing guillemet {"not", "172"}, //not sign {"shy", "173"}, //soft hyphen = discretionary hyphen {"reg", "174"}, // - registered trademark sign {"macr", "175"}, //macron = spacing macron = overline = APL overbar {"deg", "176"}, //degree sign {"plusmn", "177"}, //plus-minus sign = plus-or-minus sign {"sup2", "178"}, //superscript two = superscript digit two = squared {"sup3", "179"}, //superscript three = superscript digit three = cubed {"acute", "180"}, //acute accent = spacing acute {"micro", "181"}, //micro sign {"para", "182"}, //pilcrow sign = paragraph sign {"middot", "183"}, //middle dot = Georgian comma = Greek middle dot {"cedil", "184"}, //cedilla = spacing cedilla {"sup1", "185"}, //superscript one = superscript digit one {"ordm", "186"}, //masculine ordinal indicator {"raquo", "187"}, //right-pointing double angle quotation mark = right pointing guillemet {"frac14", "188"}, //vulgar fraction one quarter = fraction one quarter {"frac12", "189"}, //vulgar fraction one half = fraction one half {"frac34", "190"}, //vulgar fraction three quarters = fraction three quarters {"iquest", "191"}, //inverted question mark = turned question mark {"Agrave", "192"}, // - uppercase A, grave accent {"Aacute", "193"}, // - uppercase A, acute accent {"Acirc", "194"}, // - uppercase A, circumflex accent {"Atilde", "195"}, // - uppercase A, tilde {"Auml", "196"}, // - uppercase A, umlaut {"Aring", "197"}, // - uppercase A, ring {"AElig", "198"}, // - uppercase AE {"Ccedil", "199"}, // - uppercase C, cedilla {"Egrave", "200"}, // - uppercase E, grave accent {"Eacute", "201"}, // - uppercase E, acute accent {"Ecirc", "202"}, // - uppercase E, circumflex accent {"Euml", "203"}, // - uppercase E, umlaut {"Igrave", "204"}, // - uppercase I, grave accent {"Iacute", "205"}, // - uppercase I, acute accent {"Icirc", "206"}, // - uppercase I, circumflex accent {"Iuml", "207"}, // - uppercase I, umlaut {"ETH", "208"}, // - uppercase Eth, Icelandic {"Ntilde", "209"}, // - uppercase N, tilde {"Ograve", "210"}, // - uppercase O, grave accent {"Oacute", "211"}, // - uppercase O, acute accent {"Ocirc", "212"}, // - uppercase O, circumflex accent {"Otilde", "213"}, // - uppercase O, tilde {"Ouml", "214"}, // - uppercase O, umlaut {"times", "215"}, //multiplication sign {"Oslash", "216"}, // - uppercase O, slash {"Ugrave", "217"}, // - uppercase U, grave accent {"Uacute", "218"}, // - uppercase U, acute accent {"Ucirc", "219"}, // - uppercase U, circumflex accent {"Uuml", "220"}, // - uppercase U, umlaut {"Yacute", "221"}, // - uppercase Y, acute accent {"THORN", "222"}, // - uppercase THORN, Icelandic {"szlig", "223"}, // - lowercase sharps, German {"agrave", "224"}, // - lowercase a, grave accent {"aacute", "225"}, // - lowercase a, acute accent {"acirc", "226"}, // - lowercase a, circumflex accent {"atilde", "227"}, // - lowercase a, tilde {"auml", "228"}, // - lowercase a, umlaut {"aring", "229"}, // - lowercase a, ring {"aelig", "230"}, // - lowercase ae {"ccedil", "231"}, // - lowercase c, cedilla {"egrave", "232"}, // - lowercase e, grave accent {"eacute", "233"}, // - lowercase e, acute accent {"ecirc", "234"}, // - lowercase e, circumflex accent {"euml", "235"}, // - lowercase e, umlaut {"igrave", "236"}, // - lowercase i, grave accent {"iacute", "237"}, // - lowercase i, acute accent {"icirc", "238"}, // - lowercase i, circumflex accent {"iuml", "239"}, // - lowercase i, umlaut {"eth", "240"}, // - lowercase eth, Icelandic {"ntilde", "241"}, // - lowercase n, tilde {"ograve", "242"}, // - lowercase o, grave accent {"oacute", "243"}, // - lowercase o, acute accent {"ocirc", "244"}, // - lowercase o, circumflex accent {"otilde", "245"}, // - lowercase o, tilde {"ouml", "246"}, // - lowercase o, umlaut {"divide", "247"}, // division sign {"oslash", "248"}, // - lowercase o, slash {"ugrave", "249"}, // - lowercase u, grave accent {"uacute", "250"}, // - lowercase u, acute accent {"ucirc", "251"}, // - lowercase u, circumflex accent {"uuml", "252"}, // - lowercase u, umlaut {"yacute", "253"}, // - lowercase y, acute accent {"thorn", "254"}, // - lowercase thorn, Icelandic {"yuml", "255"}, // - lowercase y, umlaut }; // http://www.w3.org/TR/REC-html40/sgml/entities.html // package scoped for testing static final String[][] HTML40_ARRAY = { // {"fnof", "402"}, //latin small f with hook = function= florin, U+0192 ISOtech --> // {"Alpha", "913"}, //greek capital letter alpha, U+0391 --> {"Beta", "914"}, //greek capital letter beta, U+0392 --> {"Gamma", "915"}, //greek capital letter gamma,U+0393 ISOgrk3 --> {"Delta", "916"}, //greek capital letter delta,U+0394 ISOgrk3 --> {"Epsilon", "917"}, //greek capital letter epsilon, U+0395 --> {"Zeta", "918"}, //greek capital letter zeta, U+0396 --> {"Eta", "919"}, //greek capital letter eta, U+0397 --> {"Theta", "920"}, //greek capital letter theta,U+0398 ISOgrk3 --> {"Iota", "921"}, //greek capital letter iota, U+0399 --> {"Kappa", "922"}, //greek capital letter kappa, U+039A --> {"Lambda", "923"}, //greek capital letter lambda,U+039B ISOgrk3 --> {"Mu", "924"}, //greek capital letter mu, U+039C --> {"Nu", "925"}, //greek capital letter nu, U+039D --> {"Xi", "926"}, //greek capital letter xi, U+039E ISOgrk3 --> {"Omicron", "927"}, //greek capital letter omicron, U+039F --> {"Pi", "928"}, //greek capital letter pi, U+03A0 ISOgrk3 --> {"Rho", "929"}, //greek capital letter rho, U+03A1 --> // {"Sigma", "931"}, //greek capital letter sigma,U+03A3 ISOgrk3 --> {"Tau", "932"}, //greek capital letter tau, U+03A4 --> {"Upsilon", "933"}, //greek capital letter upsilon,U+03A5 ISOgrk3 --> {"Phi", "934"}, //greek capital letter phi,U+03A6 ISOgrk3 --> {"Chi", "935"}, //greek capital letter chi, U+03A7 --> {"Psi", "936"}, //greek capital letter psi,U+03A8 ISOgrk3 --> {"Omega", "937"}, //greek capital letter omega,U+03A9 ISOgrk3 --> {"alpha", "945"}, //greek small letter alpha,U+03B1 ISOgrk3 --> {"beta", "946"}, //greek small letter beta, U+03B2 ISOgrk3 --> {"gamma", "947"}, //greek small letter gamma,U+03B3 ISOgrk3 --> {"delta", "948"}, //greek small letter delta,U+03B4 ISOgrk3 --> {"epsilon", "949"}, //greek small letter epsilon,U+03B5 ISOgrk3 --> {"zeta", "950"}, //greek small letter zeta, U+03B6 ISOgrk3 --> {"eta", "951"}, //greek small letter eta, U+03B7 ISOgrk3 --> {"theta", "952"}, //greek small letter theta,U+03B8 ISOgrk3 --> {"iota", "953"}, //greek small letter iota, U+03B9 ISOgrk3 --> {"kappa", "954"}, //greek small letter kappa,U+03BA ISOgrk3 --> {"lambda", "955"}, //greek small letter lambda,U+03BB ISOgrk3 --> {"mu", "956"}, //greek small letter mu, U+03BC ISOgrk3 --> {"nu", "957"}, //greek small letter nu, U+03BD ISOgrk3 --> {"xi", "958"}, //greek small letter xi, U+03BE ISOgrk3 --> {"omicron", "959"}, //greek small letter omicron, U+03BF NEW --> {"pi", "960"}, //greek small letter pi, U+03C0 ISOgrk3 --> {"rho", "961"}, //greek small letter rho, U+03C1 ISOgrk3 --> {"sigmaf", "962"}, //greek small letter final sigma,U+03C2 ISOgrk3 --> {"sigma", "963"}, //greek small letter sigma,U+03C3 ISOgrk3 --> {"tau", "964"}, //greek small letter tau, U+03C4 ISOgrk3 --> {"upsilon", "965"}, //greek small letter upsilon,U+03C5 ISOgrk3 --> {"phi", "966"}, //greek small letter phi, U+03C6 ISOgrk3 --> {"chi", "967"}, //greek small letter chi, U+03C7 ISOgrk3 --> {"psi", "968"}, //greek small letter psi, U+03C8 ISOgrk3 --> {"omega", "969"}, //greek small letter omega,U+03C9 ISOgrk3 --> {"thetasym", "977"}, //greek small letter theta symbol,U+03D1 NEW --> {"upsih", "978"}, //greek upsilon with hook symbol,U+03D2 NEW --> {"piv", "982"}, //greek pi symbol, U+03D6 ISOgrk3 --> // {"bull", "8226"}, //bullet = black small circle,U+2022 ISOpub --> // {"hellip", "8230"}, //horizontal ellipsis = three dot leader,U+2026 ISOpub --> {"prime", "8242"}, //prime = minutes = feet, U+2032 ISOtech --> {"Prime", "8243"}, //double prime = seconds = inches,U+2033 ISOtech --> {"oline", "8254"}, //overline = spacing overscore,U+203E NEW --> {"frasl", "8260"}, //fraction slash, U+2044 NEW --> // {"weierp", "8472"}, //script capital P = power set= Weierstrass p, U+2118 ISOamso --> {"image", "8465"}, //blackletter capital I = imaginary part,U+2111 ISOamso --> {"real", "8476"}, //blackletter capital R = real part symbol,U+211C ISOamso --> {"trade", "8482"}, //trade mark sign, U+2122 ISOnum --> {"alefsym", "8501"}, //alef symbol = first transfinite cardinal,U+2135 NEW --> // // {"larr", "8592"}, //leftwards arrow, U+2190 ISOnum --> {"uarr", "8593"}, //upwards arrow, U+2191 ISOnum--> {"rarr", "8594"}, //rightwards arrow, U+2192 ISOnum --> {"darr", "8595"}, //downwards arrow, U+2193 ISOnum --> {"harr", "8596"}, //left right arrow, U+2194 ISOamsa --> {"crarr", "8629"}, //downwards arrow with corner leftwards= carriage return, U+21B5 NEW --> {"lArr", "8656"}, //leftwards double arrow, U+21D0 ISOtech --> // {"uArr", "8657"}, //upwards double arrow, U+21D1 ISOamsa --> {"rArr", "8658"}, //rightwards double arrow,U+21D2 ISOtech --> // {"dArr", "8659"}, //downwards double arrow, U+21D3 ISOamsa --> {"hArr", "8660"}, //left right double arrow,U+21D4 ISOamsa --> // {"forall", "8704"}, //for all, U+2200 ISOtech --> {"part", "8706"}, //partial differential, U+2202 ISOtech --> {"exist", "8707"}, //there exists, U+2203 ISOtech --> {"empty", "8709"}, //empty set = null set = diameter,U+2205 ISOamso --> {"nabla", "8711"}, //nabla = backward difference,U+2207 ISOtech --> {"isin", "8712"}, //element of, U+2208 ISOtech --> {"notin", "8713"}, //not an element of, U+2209 ISOtech --> {"ni", "8715"}, //contains as member, U+220B ISOtech --> // {"prod", "8719"}, //n-ary product = product sign,U+220F ISOamsb --> // {"sum", "8721"}, //n-ary summation, U+2211 ISOamsb --> // {"minus", "8722"}, //minus sign, U+2212 ISOtech --> {"lowast", "8727"}, //asterisk operator, U+2217 ISOtech --> {"radic", "8730"}, //square root = radical sign,U+221A ISOtech --> {"prop", "8733"}, //proportional to, U+221D ISOtech --> {"infin", "8734"}, //infinity, U+221E ISOtech --> {"ang", "8736"}, //angle, U+2220 ISOamso --> {"and", "8743"}, //logical and = wedge, U+2227 ISOtech --> {"or", "8744"}, //logical or = vee, U+2228 ISOtech --> {"cap", "8745"}, //intersection = cap, U+2229 ISOtech --> {"cup", "8746"}, //union = cup, U+222A ISOtech --> {"int", "8747"}, //integral, U+222B ISOtech --> {"there4", "8756"}, //therefore, U+2234 ISOtech --> {"sim", "8764"}, //tilde operator = varies with = similar to,U+223C ISOtech --> // {"cong", "8773"}, //approximately equal to, U+2245 ISOtech --> {"asymp", "8776"}, //almost equal to = asymptotic to,U+2248 ISOamsr --> {"ne", "8800"}, //not equal to, U+2260 ISOtech --> {"equiv", "8801"}, //identical to, U+2261 ISOtech --> {"le", "8804"}, //less-than or equal to, U+2264 ISOtech --> {"ge", "8805"}, //greater-than or equal to,U+2265 ISOtech --> {"sub", "8834"}, //subset of, U+2282 ISOtech --> {"sup", "8835"}, //superset of, U+2283 ISOtech --> // {"sube", "8838"}, //subset of or equal to, U+2286 ISOtech --> {"supe", "8839"}, //superset of or equal to,U+2287 ISOtech --> {"oplus", "8853"}, //circled plus = direct sum,U+2295 ISOamsb --> {"otimes", "8855"}, //circled times = vector product,U+2297 ISOamsb --> {"perp", "8869"}, //up tack = orthogonal to = perpendicular,U+22A5 ISOtech --> {"sdot", "8901"}, //dot operator, U+22C5 ISOamsb --> // // {"lceil", "8968"}, //left ceiling = apl upstile,U+2308 ISOamsc --> {"rceil", "8969"}, //right ceiling, U+2309 ISOamsc --> {"lfloor", "8970"}, //left floor = apl downstile,U+230A ISOamsc --> {"rfloor", "8971"}, //right floor, U+230B ISOamsc --> {"lang", "9001"}, //left-pointing angle bracket = bra,U+2329 ISOtech --> // {"rang", "9002"}, //right-pointing angle bracket = ket,U+232A ISOtech --> // // {"loz", "9674"}, //lozenge, U+25CA ISOpub --> // {"spades", "9824"}, //black spade suit, U+2660 ISOpub --> // {"clubs", "9827"}, //black club suit = shamrock,U+2663 ISOpub --> {"hearts", "9829"}, //black heart suit = valentine,U+2665 ISOpub --> {"diams", "9830"}, //black diamond suit, U+2666 ISOpub --> // {"OElig", "338"}, // -- latin capital ligature OE,U+0152 ISOlat2 --> {"oelig", "339"}, // -- latin small ligature oe, U+0153 ISOlat2 --> // {"Scaron", "352"}, // -- latin capital letter S with caron,U+0160 ISOlat2 --> {"scaron", "353"}, // -- latin small letter s with caron,U+0161 ISOlat2 --> {"Yuml", "376"}, // -- latin capital letter Y with diaeresis,U+0178 ISOlat2 --> // {"circ", "710"}, // -- modifier letter circumflex accent,U+02C6 ISOpub --> {"tilde", "732"}, //small tilde, U+02DC ISOdia --> // {"ensp", "8194"}, //en space, U+2002 ISOpub --> {"emsp", "8195"}, //em space, U+2003 ISOpub --> {"thinsp", "8201"}, //thin space, U+2009 ISOpub --> {"zwnj", "8204"}, //zero width non-joiner,U+200C NEW RFC 2070 --> {"zwj", "8205"}, //zero width joiner, U+200D NEW RFC 2070 --> {"lrm", "8206"}, //left-to-right mark, U+200E NEW RFC 2070 --> {"rlm", "8207"}, //right-to-left mark, U+200F NEW RFC 2070 --> {"ndash", "8211"}, //en dash, U+2013 ISOpub --> {"mdash", "8212"}, //em dash, U+2014 ISOpub --> {"lsquo", "8216"}, //left single quotation mark,U+2018 ISOnum --> {"rsquo", "8217"}, //right single quotation mark,U+2019 ISOnum --> {"sbquo", "8218"}, //single low-9 quotation mark, U+201A NEW --> {"ldquo", "8220"}, //left double quotation mark,U+201C ISOnum --> {"rdquo", "8221"}, //right double quotation mark,U+201D ISOnum --> {"bdquo", "8222"}, //double low-9 quotation mark, U+201E NEW --> {"dagger", "8224"}, //dagger, U+2020 ISOpub --> {"Dagger", "8225"}, //double dagger, U+2021 ISOpub --> {"permil", "8240"}, //per mille sign, U+2030 ISOtech --> {"lsaquo", "8249"}, //single left-pointing angle quotation mark,U+2039 ISO proposed --> // {"rsaquo", "8250"}, //single right-pointing angle quotation mark,U+203A ISO proposed --> // {"euro", "8364"}, // -- euro sign, U+20AC NEW --> }; /** *

      The set of entities supported by standard XML.

      */ public static final Entities XML; /** *

      The set of entities supported by HTML 3.2.

      */ public static final Entities HTML32; /** *

      The set of entities supported by HTML 4.0.

      */ public static final Entities HTML40; static { XML = new Entities(); XML.addEntities(BASIC_ARRAY); XML.addEntities(APOS_ARRAY); } static { HTML32 = new Entities(); HTML32.addEntities(BASIC_ARRAY); HTML32.addEntities(ISO8859_1_ARRAY); } static { HTML40 = new Entities(); fillWithHtml40Entities(HTML40); } static void fillWithHtml40Entities(Entities entities) { entities.addEntities(BASIC_ARRAY); entities.addEntities(ISO8859_1_ARRAY); entities.addEntities(HTML40_ARRAY); } static interface EntityMap { void add(String name, int value); String name(int value); int value(String name); } static class PrimitiveEntityMap implements EntityMap { private Map mapNameToValue = new HashMap(); private IntHashMap mapValueToName = new IntHashMap(); public void add(String name, int value) { mapNameToValue.put(name, new Integer(value)); mapValueToName.put(value, name); } public String name(int value) { return (String) mapValueToName.get(value); } public int value(String name) { Object value = mapNameToValue.get(name); if (value == null) { return -1; } return ((Integer) value).intValue(); } } static abstract class MapIntMap implements Entities.EntityMap { protected Map mapNameToValue; protected Map mapValueToName; public void add(String name, int value) { mapNameToValue.put(name, new Integer(value)); mapValueToName.put(new Integer(value), name); } public String name(int value) { return (String) mapValueToName.get(new Integer(value)); } public int value(String name) { Object value = mapNameToValue.get(name); if (value == null) { return -1; } return ((Integer) value).intValue(); } } static class HashEntityMap extends MapIntMap { public HashEntityMap() { mapNameToValue = new HashMap(); mapValueToName = new HashMap(); } } static class TreeEntityMap extends MapIntMap { public TreeEntityMap() { mapNameToValue = new TreeMap(); mapValueToName = new TreeMap(); } } static class LookupEntityMap extends PrimitiveEntityMap { private String[] lookupTable; private int LOOKUP_TABLE_SIZE = 256; public String name(int value) { if (value < LOOKUP_TABLE_SIZE) { return lookupTable()[value]; } return super.name(value); } private String[] lookupTable() { if (lookupTable == null) { createLookupTable(); } return lookupTable; } private void createLookupTable() { lookupTable = new String[LOOKUP_TABLE_SIZE]; for (int i = 0; i < LOOKUP_TABLE_SIZE; ++i) { lookupTable[i] = super.name(i); } } } static class ArrayEntityMap implements EntityMap { protected int growBy = 100; protected int size = 0; protected String[] names; protected int[] values; public ArrayEntityMap() { names = new String[growBy]; values = new int[growBy]; } public ArrayEntityMap(int growBy) { this.growBy = growBy; names = new String[growBy]; values = new int[growBy]; } public void add(String name, int value) { ensureCapacity(size + 1); names[size] = name; values[size] = value; size++; } protected void ensureCapacity(int capacity) { if (capacity > names.length) { int newSize = Math.max(capacity, size + growBy); String[] newNames = new String[newSize]; System.arraycopy(names, 0, newNames, 0, size); names = newNames; int[] newValues = new int[newSize]; System.arraycopy(values, 0, newValues, 0, size); values = newValues; } } public String name(int value) { for (int i = 0; i < size; ++i) { if (values[i] == value) { return names[i]; } } return null; } public int value(String name) { for (int i = 0; i < size; ++i) { if (names[i].equals(name)) { return values[i]; } } return -1; } } static class BinaryEntityMap extends ArrayEntityMap { public BinaryEntityMap() { } public BinaryEntityMap(int growBy) { super(growBy); } // based on code in java.util.Arrays private int binarySearch(int key) { int low = 0; int high = size - 1; while (low <= high) { int mid = (low + high) >> 1; int midVal = values[mid]; if (midVal < key) { low = mid + 1; } else if (midVal > key) { high = mid - 1; } else { return mid; // key found } } return -(low + 1); // key not found. } public void add(String name, int value) { ensureCapacity(size + 1); int insertAt = binarySearch(value); if (insertAt > 0) { return; // note: this means you can't insert the same value twice } insertAt = -(insertAt + 1); // binarySearch returns it negative and off-by-one System.arraycopy(values, insertAt, values, insertAt + 1, size - insertAt); values[insertAt] = value; System.arraycopy(names, insertAt, names, insertAt + 1, size - insertAt); names[insertAt] = name; size++; } public String name(int value) { int index = binarySearch(value); if (index < 0) { return null; } return names[index]; } } // package scoped for testing EntityMap map = new Entities.LookupEntityMap(); public void addEntities(String[][] entityArray) { for (int i = 0; i < entityArray.length; ++i) { addEntity(entityArray[i][0], Integer.parseInt(entityArray[i][1])); } } public void addEntity(String name, int value) { map.add(name, value); } public String entityName(int value) { return map.name(value); } public int entityValue(String name) { return map.value(name); } /** *

      Escapes the characters in a String.

      * *

      For example, if you have called addEntity("foo", 0xA1), * escape("\u00A1") will return "&foo;"

      * * @param str The String to escape. * @return A new escaped String. */ public String escape(String str) { //todo: rewrite to use a Writer StringBuffer buf = new StringBuffer(str.length() * 2); int i; for (i = 0; i < str.length(); ++i) { char ch = str.charAt(i); String entityName = this.entityName(ch); if (entityName == null) { if (ch > 0x7F) { int intValue = ch; buf.append("&#"); buf.append(intValue); buf.append(';'); } else { buf.append(ch); } } else { buf.append('&'); buf.append(entityName); buf.append(';'); } } return buf.toString(); } /** *

      Unescapes the entities in a String.

      * *

      For example, if you have called addEntity("foo", 0xA1), * unescape("&foo;") will return "\u00A1"

      * * @param str The String to escape. * @return A new escaped String. */ public String unescape(String str) { StringBuffer buf = new StringBuffer(str.length()); int i; for (i = 0; i < str.length(); ++i) { char ch = str.charAt(i); if (ch == '&') { int semi = str.indexOf(';', i + 1); if (semi == -1) { buf.append(ch); continue; } String entityName = str.substring(i + 1, semi); int entityValue; if (entityName.charAt(0) == '#') { char charAt1 = entityName.charAt(1); if (charAt1 == 'x' || charAt1=='X') { entityValue = Integer.valueOf(entityName.substring(2), 16).intValue(); } else { entityValue = Integer.parseInt(entityName.substring(1)); } } else { entityValue = this.entityValue(entityName); } if (entityValue == -1) { buf.append('&'); buf.append(entityName); buf.append(';'); } else { buf.append((char) (entityValue)); } i = semi; } else { buf.append(ch); } } return buf.toString(); } } azureus-4.3.0.6/org/bouncycastle/0000755000175000017500000000000011310377632016123 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/LICENSE.java0000644000175000017500000000646110061400660020045 0ustar adrianadrianpackage org.bouncycastle; /** * The Bouncy Castle License * * Copyright (c) 2000 The Legion Of The Bouncy Castle (http://www.bouncycastle.org) *

      * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: *

      * The above copyright notice and this permission notice shall be included in all copies or substantial * portions of the Software. *

      * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ public class LICENSE { public static String licenseText = "Copyright (c) 2000 The Legion Of The Bouncy Castle (http://www.bouncycastle.org) " + System.getProperty("line.separator") + System.getProperty("line.separator") + "Permission is hereby granted, free of charge, to any person obtaining a copy of this software " + System.getProperty("line.separator") + "and associated documentation files (the \"Software\"), to deal in the Software without restriction, " + System.getProperty("line.separator") + "including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, " + System.getProperty("line.separator") + "and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so," + System.getProperty("line.separator") + "subject to the following conditions:" + System.getProperty("line.separator") + System.getProperty("line.separator") + "The above copyright notice and this permission notice shall be included in all copies or substantial" + System.getProperty("line.separator") + "portions of the Software." + System.getProperty("line.separator") + System.getProperty("line.separator") + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED," + System.getProperty("line.separator") + "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR" + System.getProperty("line.separator") + "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE" + System.getProperty("line.separator") + "LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR" + System.getProperty("line.separator") + "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER" + System.getProperty("line.separator") + "DEALINGS IN THE SOFTWARE."; public static void main( String[] args) { System.out.println(licenseText); } } azureus-4.3.0.6/org/bouncycastle/openssl/0000755000175000017500000000000011310377634017610 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/openssl/PasswordFinder.java0000644000175000017500000000026611026315672023407 0ustar adrianadrianpackage org.bouncycastle.openssl; /** * call back to allow a password to be fetched when one is requested. */ public interface PasswordFinder { public char[] getPassword(); } azureus-4.3.0.6/org/bouncycastle/openssl/PEMReader.java0000644000175000017500000004247311026315672022227 0ustar adrianadrianpackage org.bouncycastle.openssl; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.sec.ECPrivateKeyStructure; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.RSAPublicKeyStructure; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.jce.ECNamedCurveTable; import org.bouncycastle.jce.PKCS10CertificationRequest; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.x509.X509AttributeCertificate; import org.bouncycastle.x509.X509V2AttributeCertificate; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.Reader; import java.security.KeyFactory; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PublicKey; import java.security.cert.CertificateFactory; import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.security.spec.DSAPrivateKeySpec; import java.security.spec.DSAPublicKeySpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.RSAPrivateCrtKeySpec; import java.security.spec.RSAPublicKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.StringTokenizer; /** * Class for reading OpenSSL PEM encoded streams containing * X509 certificates, PKCS8 encoded keys and PKCS7 objects. *

      * In the case of PKCS7 objects the reader will return a CMS ContentInfo object. Keys and * Certificates will be returned using the appropriate java.security type. */ public class PEMReader extends BufferedReader { private final PasswordFinder pFinder; private final String provider; /** * Create a new PEMReader * * @param reader the Reader */ public PEMReader( Reader reader) { this(reader, null, "BC"); } /** * Create a new PEMReader with a password finder * * @param reader the Reader * @param pFinder the password finder */ public PEMReader( Reader reader, PasswordFinder pFinder) { this(reader, pFinder, "BC"); } /** * Create a new PEMReader with a password finder * * @param reader the Reader * @param pFinder the password finder * @param provider the cryptography provider to use */ public PEMReader( Reader reader, PasswordFinder pFinder, String provider) { super(reader); this.pFinder = pFinder; this.provider = provider; } public Object readObject() throws IOException { String line; while ((line = readLine()) != null) { if (line.indexOf("-----BEGIN PUBLIC KEY") != -1) { return readPublicKey("-----END PUBLIC KEY"); } if (line.indexOf("-----BEGIN RSA PUBLIC KEY") != -1) { return readRSAPublicKey("-----END RSA PUBLIC KEY"); } if (line.indexOf("-----BEGIN CERTIFICATE REQUEST") != -1) { return readCertificateRequest("-----END CERTIFICATE REQUEST"); } if (line.indexOf("-----BEGIN NEW CERTIFICATE REQUEST") != -1) { return readCertificateRequest("-----END NEW CERTIFICATE REQUEST"); } if (line.indexOf("-----BEGIN CERTIFICATE") != -1) { return readCertificate("-----END CERTIFICATE"); } if (line.indexOf("-----BEGIN PKCS7") != -1) { return readPKCS7("-----END PKCS7"); } if (line.indexOf("-----BEGIN X509 CERTIFICATE") != -1) { return readCertificate("-----END X509 CERTIFICATE"); } if (line.indexOf("-----BEGIN X509 CRL") != -1) { return readCRL("-----END X509 CRL"); } if (line.indexOf("-----BEGIN ATTRIBUTE CERTIFICATE") != -1) { return readAttributeCertificate("-----END ATTRIBUTE CERTIFICATE"); } if (line.indexOf("-----BEGIN RSA PRIVATE KEY") != -1) { try { return readKeyPair("RSA", "-----END RSA PRIVATE KEY"); } catch (Exception e) { throw new IOException( "problem creating RSA private key: " + e.toString()); } } if (line.indexOf("-----BEGIN DSA PRIVATE KEY") != -1) { try { return readKeyPair("DSA", "-----END DSA PRIVATE KEY"); } catch (Exception e) { throw new IOException( "problem creating DSA private key: " + e.toString()); } } if (line.indexOf("-----BEGIN EC PARAMETERS-----") != -1) { return readECParameters("-----END EC PARAMETERS-----"); } if (line.indexOf("-----BEGIN EC PRIVATE KEY-----") != -1) { return readECPrivateKey("-----END EC PRIVATE KEY-----"); } } return null; } private byte[] readBytes(String endMarker) throws IOException { String line; StringBuffer buf = new StringBuffer(); while ((line = readLine()) != null) { if (line.indexOf(endMarker) != -1) { break; } buf.append(line.trim()); } if (line == null) { throw new IOException(endMarker + " not found"); } return Base64.decode(buf.toString()); } private PublicKey readRSAPublicKey(String endMarker) throws IOException { ByteArrayInputStream bAIS = new ByteArrayInputStream(readBytes(endMarker)); ASN1InputStream ais = new ASN1InputStream(bAIS); Object asnObject = ais.readObject(); ASN1Sequence sequence = (ASN1Sequence) asnObject; RSAPublicKeyStructure rsaPubStructure = new RSAPublicKeyStructure(sequence); RSAPublicKeySpec keySpec = new RSAPublicKeySpec( rsaPubStructure.getModulus(), rsaPubStructure.getPublicExponent()); try { KeyFactory keyFact = KeyFactory.getInstance("RSA", provider); return keyFact.generatePublic(keySpec); } catch (NoSuchProviderException e) { throw new IOException("can't find provider " + provider); } catch (Exception e) { throw new IOException("problem extracting key: " + e.toString()); } } private PublicKey readPublicKey(String endMarker) throws IOException { KeySpec keySpec = new X509EncodedKeySpec(readBytes(endMarker)); String[] algorithms = { "DSA", "RSA" }; for (int i = 0; i < algorithms.length; i++) { try { KeyFactory keyFact = KeyFactory.getInstance(algorithms[i], provider); PublicKey pubKey = keyFact.generatePublic(keySpec); return pubKey; } catch (NoSuchAlgorithmException e) { // ignore } catch (InvalidKeySpecException e) { // ignore } catch (NoSuchProviderException e) { throw new RuntimeException("can't find provider " + provider); } } return null; } /** * Reads in a X509Certificate. * * @return the X509Certificate * @throws IOException if an I/O error occured */ private X509Certificate readCertificate( String endMarker) throws IOException { ByteArrayInputStream bIn = new ByteArrayInputStream(readBytes(endMarker)); try { CertificateFactory certFact = CertificateFactory.getInstance("X.509", provider); return (X509Certificate)certFact.generateCertificate(bIn); } catch (Exception e) { throw new IOException("problem parsing cert: " + e.toString()); } } /** * Reads in a X509CRL. * * @return the X509Certificate * @throws IOException if an I/O error occured */ private X509CRL readCRL( String endMarker) throws IOException { ByteArrayInputStream bIn = new ByteArrayInputStream(readBytes(endMarker)); try { CertificateFactory certFact = CertificateFactory.getInstance("X.509", provider); return (X509CRL)certFact.generateCRL(bIn); } catch (Exception e) { throw new IOException("problem parsing cert: " + e.toString()); } } /** * Reads in a PKCS10 certification request. * * @return the certificate request. * @throws IOException if an I/O error occured */ private PKCS10CertificationRequest readCertificateRequest( String endMarker) throws IOException { try { return new PKCS10CertificationRequest(readBytes(endMarker)); } catch (Exception e) { throw new IOException("problem parsing cert: " + e.toString()); } } /** * Reads in a X509 Attribute Certificate. * * @return the X509 Attribute Certificate * @throws IOException if an I/O error occured */ private X509AttributeCertificate readAttributeCertificate( String endMarker) throws IOException { return new X509V2AttributeCertificate(readBytes(endMarker)); } /** * Reads in a PKCS7 object. This returns a ContentInfo object suitable for use with the CMS * API. * * @return the X509Certificate * @throws IOException if an I/O error occured */ private ContentInfo readPKCS7( String endMarker) throws IOException { String line; StringBuffer buf = new StringBuffer(); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); while ((line = readLine()) != null) { if (line.indexOf(endMarker) != -1) { break; } line = line.trim(); buf.append(line.trim()); Base64.decode(buf.substring(0, (buf.length() / 4) * 4), bOut); buf.delete(0, (buf.length() / 4) * 4); } if (buf.length() != 0) { throw new RuntimeException("base64 data appears to be truncated"); } if (line == null) { throw new IOException(endMarker + " not found"); } ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray()); try { ASN1InputStream aIn = new ASN1InputStream(bIn); return ContentInfo.getInstance(aIn.readObject()); } catch (Exception e) { throw new IOException("problem parsing PKCS7 object: " + e.toString()); } } /** * Read a Key Pair */ private KeyPair readKeyPair( String type, String endMarker) throws Exception { boolean isEncrypted = false; String line = null; String dekInfo = null; StringBuffer buf = new StringBuffer(); while ((line = readLine()) != null) { if (line.startsWith("Proc-Type: 4,ENCRYPTED")) { isEncrypted = true; } else if (line.startsWith("DEK-Info:")) { dekInfo = line.substring(10); } else if (line.indexOf(endMarker) != -1) { break; } else { buf.append(line.trim()); } } // // extract the key // byte[] keyBytes = Base64.decode(buf.toString()); if (isEncrypted) { if (pFinder == null) { throw new IOException("No password finder specified, but a password is required"); } char[] password = pFinder.getPassword(); if (password == null) { throw new IOException("Password is null, but a password is required"); } StringTokenizer tknz = new StringTokenizer(dekInfo, ","); String dekAlgName = tknz.nextToken(); byte[] iv = Hex.decode(tknz.nextToken()); keyBytes = PEMUtilities.crypt(false, provider, keyBytes, password, dekAlgName, iv); } KeySpec pubSpec, privSpec; ByteArrayInputStream bIn = new ByteArrayInputStream(keyBytes); ASN1InputStream aIn = new ASN1InputStream(bIn); ASN1Sequence seq = (ASN1Sequence)aIn.readObject(); if (type.equals("RSA")) { // DERInteger v = (DERInteger)seq.getObjectAt(0); DERInteger mod = (DERInteger)seq.getObjectAt(1); DERInteger pubExp = (DERInteger)seq.getObjectAt(2); DERInteger privExp = (DERInteger)seq.getObjectAt(3); DERInteger p1 = (DERInteger)seq.getObjectAt(4); DERInteger p2 = (DERInteger)seq.getObjectAt(5); DERInteger exp1 = (DERInteger)seq.getObjectAt(6); DERInteger exp2 = (DERInteger)seq.getObjectAt(7); DERInteger crtCoef = (DERInteger)seq.getObjectAt(8); pubSpec = new RSAPublicKeySpec( mod.getValue(), pubExp.getValue()); privSpec = new RSAPrivateCrtKeySpec( mod.getValue(), pubExp.getValue(), privExp.getValue(), p1.getValue(), p2.getValue(), exp1.getValue(), exp2.getValue(), crtCoef.getValue()); } else // "DSA" { // DERInteger v = (DERInteger)seq.getObjectAt(0); DERInteger p = (DERInteger)seq.getObjectAt(1); DERInteger q = (DERInteger)seq.getObjectAt(2); DERInteger g = (DERInteger)seq.getObjectAt(3); DERInteger y = (DERInteger)seq.getObjectAt(4); DERInteger x = (DERInteger)seq.getObjectAt(5); privSpec = new DSAPrivateKeySpec( x.getValue(), p.getValue(), q.getValue(), g.getValue()); pubSpec = new DSAPublicKeySpec( y.getValue(), p.getValue(), q.getValue(), g.getValue()); } KeyFactory fact = KeyFactory.getInstance(type, provider); return new KeyPair( fact.generatePublic(pubSpec), fact.generatePrivate(privSpec)); } private ECNamedCurveParameterSpec readECParameters(String endMarker) throws IOException { DERObjectIdentifier oid = (DERObjectIdentifier)ASN1Object.fromByteArray(readBytes(endMarker)); return ECNamedCurveTable.getParameterSpec(oid.getId()); } private KeyPair readECPrivateKey(String endMarker) throws IOException { try { ECPrivateKeyStructure pKey = new ECPrivateKeyStructure((ASN1Sequence)ASN1Object.fromByteArray(readBytes(endMarker))); AlgorithmIdentifier algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, pKey.getParameters()); PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, pKey.getDERObject()); SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pKey.getPublicKey().getBytes()); PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privInfo.getEncoded()); X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubInfo.getEncoded()); KeyFactory fact = KeyFactory.getInstance("ECDSA", provider); return new KeyPair(fact.generatePublic(pubSpec), fact.generatePrivate(privSpec)); } catch (ClassCastException e) { throw new IOException("wrong ASN.1 object found in stream"); } catch (Exception e) { throw new IOException("problem parsing EC private key: " + e); } } } azureus-4.3.0.6/org/bouncycastle/openssl/PEMUtilities.java0000644000175000017500000001254311026315674022775 0ustar adrianadrianpackage org.bouncycastle.openssl; import org.bouncycastle.crypto.PBEParametersGenerator; import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator; import org.bouncycastle.crypto.params.KeyParameter; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.RC2ParameterSpec; import java.io.IOException; import java.security.Key; import java.security.spec.AlgorithmParameterSpec; final class PEMUtilities { static byte[] crypt( boolean encrypt, String provider, byte[] bytes, char[] password, String dekAlgName, byte[] iv) throws IOException { AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv); String alg; String blockMode = "CBC"; String padding = "PKCS5Padding"; Key sKey; // Figure out block mode and padding. if (dekAlgName.endsWith("-CFB")) { blockMode = "CFB"; padding = "NoPadding"; } if (dekAlgName.endsWith("-ECB") || "DES-EDE".equals(dekAlgName) || "DES-EDE3".equals(dekAlgName)) { // ECB is actually the default (though seldom used) when OpenSSL // uses DES-EDE (des2) or DES-EDE3 (des3). blockMode = "ECB"; paramSpec = null; } if (dekAlgName.endsWith("-OFB")) { blockMode = "OFB"; padding = "NoPadding"; } // Figure out algorithm and key size. if (dekAlgName.startsWith("DES-EDE")) { alg = "DESede"; // "DES-EDE" is actually des2 in OpenSSL-speak! // "DES-EDE3" is des3. boolean des2 = !dekAlgName.startsWith("DES-EDE3"); sKey = getKey(password, alg, 24, iv, des2); } else if (dekAlgName.startsWith("DES-")) { alg = "DES"; sKey = getKey(password, alg, 8, iv); } else if (dekAlgName.startsWith("BF-")) { alg = "Blowfish"; sKey = getKey(password, alg, 16, iv); } else if (dekAlgName.startsWith("RC2-")) { alg = "RC2"; int keyBits = 128; if (dekAlgName.startsWith("RC2-40-")) { keyBits = 40; } else if (dekAlgName.startsWith("RC2-64-")) { keyBits = 64; } sKey = getKey(password, alg, keyBits / 8, iv); if (paramSpec == null) // ECB block mode { paramSpec = new RC2ParameterSpec(keyBits); } else { paramSpec = new RC2ParameterSpec(keyBits, iv); } } else if (dekAlgName.startsWith("AES-")) { alg = "AES"; byte[] salt = iv; if (salt.length > 8) { salt = new byte[8]; System.arraycopy(iv, 0, salt, 0, 8); } int keyBits; if (dekAlgName.startsWith("AES-128-")) { keyBits = 128; } else if (dekAlgName.startsWith("AES-192-")) { keyBits = 192; } else if (dekAlgName.startsWith("AES-256-")) { keyBits = 256; } else { throw new IOException("unknown AES encryption with private key"); } sKey = getKey(password, "AES", keyBits / 8, salt); } else { throw new IOException("unknown encryption with private key"); } String transformation = alg + "/" + blockMode + "/" + padding; try { Cipher c = Cipher.getInstance(transformation, provider); int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE; if (paramSpec == null) // ECB block mode { c.init(mode, sKey); } else { c.init(mode, sKey, paramSpec); } return c.doFinal(bytes); } catch (Exception e) { throw new IOException("exception using cipher: " + e.toString()); } } private static SecretKey getKey( char[] password, String algorithm, int keyLength, byte[] salt) throws IOException { return getKey(password, algorithm, keyLength, salt, false); } private static SecretKey getKey( char[] password, String algorithm, int keyLength, byte[] salt, boolean des2) throws IOException { OpenSSLPBEParametersGenerator pGen = new OpenSSLPBEParametersGenerator(); pGen.init(PBEParametersGenerator.PKCS5PasswordToBytes(password), salt); KeyParameter keyParam; keyParam = (KeyParameter) pGen.generateDerivedParameters(keyLength * 8); byte[] key = keyParam.getKey(); if (des2 && key.length >= 24) { // For DES2, we must copy first 8 bytes into the last 8 bytes. System.arraycopy(key, 0, key, 16, 8); } return new javax.crypto.spec.SecretKeySpec(key, algorithm); } } azureus-4.3.0.6/org/bouncycastle/openssl/PEMWriter.java0000644000175000017500000002114711026315674022276 0ustar adrianadrianpackage org.bouncycastle.openssl; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure; import org.bouncycastle.asn1.x509.DSAParameter; import org.bouncycastle.jce.PKCS10CertificationRequest; import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.x509.X509AttributeCertificate; import org.bouncycastle.x509.X509V2AttributeCertificate; import java.io.BufferedWriter; import java.io.IOException; import java.io.Writer; import java.math.BigInteger; import java.security.Key; import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.cert.CRLException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPrivateKey; import java.security.interfaces.RSAPrivateCrtKey; import java.security.interfaces.RSAPrivateKey; /** * General purpose writer for OpenSSL PEM objects. */ public class PEMWriter extends BufferedWriter { private String provider; /** * Base constructor. * * @param out output stream to use. */ public PEMWriter(Writer out) { this(out, "BC"); } public PEMWriter( Writer out, String provider) { super(out); this.provider = provider; } private void writeHexEncoded(byte[] bytes) throws IOException { bytes = Hex.encode(bytes); for (int i = 0; i != bytes.length; i++) { this.write((char)bytes[i]); } } private void writeEncoded(byte[] bytes) throws IOException { char[] buf = new char[64]; bytes = Base64.encode(bytes); for (int i = 0; i < bytes.length; i += buf.length) { int index = 0; while (index != buf.length) { if ((i + index) >= bytes.length) { break; } buf[index] = (char)bytes[i + index]; index++; } this.write(buf, 0, index); this.newLine(); } } public void writeObject( Object o) throws IOException { String type; byte[] encoding; if (o instanceof X509Certificate) { type = "CERTIFICATE"; try { encoding = ((X509Certificate)o).getEncoded(); } catch (CertificateEncodingException e) { throw new IOException("Cannot encode object: " + e.toString()); } } else if (o instanceof X509CRL) { type = "X509 CRL"; try { encoding = ((X509CRL)o).getEncoded(); } catch (CRLException e) { throw new IOException("Cannot encode object: " + e.toString()); } } else if (o instanceof KeyPair) { writeObject(((KeyPair)o).getPrivate()); return; } else if (o instanceof PrivateKey) { PrivateKeyInfo info = new PrivateKeyInfo( (ASN1Sequence) ASN1Object.fromByteArray(((Key)o).getEncoded())); if (o instanceof RSAPrivateKey) { type = "RSA PRIVATE KEY"; encoding = info.getPrivateKey().getEncoded(); } else if (o instanceof DSAPrivateKey) { type = "DSA PRIVATE KEY"; DSAParameter p = DSAParameter.getInstance(info.getAlgorithmId().getParameters()); ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new DERInteger(0)); v.add(new DERInteger(p.getP())); v.add(new DERInteger(p.getQ())); v.add(new DERInteger(p.getG())); BigInteger x = ((DSAPrivateKey)o).getX(); BigInteger y = p.getG().modPow(x, p.getP()); v.add(new DERInteger(y)); v.add(new DERInteger(x)); encoding = new DERSequence(v).getEncoded(); } else { throw new IOException("Cannot identify private key"); } } else if (o instanceof PublicKey) { type = "PUBLIC KEY"; encoding = ((PublicKey)o).getEncoded(); } else if (o instanceof X509AttributeCertificate) { type = "ATTRIBUTE CERTIFICATE"; encoding = ((X509V2AttributeCertificate)o).getEncoded(); } else if (o instanceof PKCS10CertificationRequest) { type = "CERTIFICATE REQUEST"; encoding = ((PKCS10CertificationRequest)o).getEncoded(); } else if (o instanceof ContentInfo) { type = "PKCS7"; encoding = ((ContentInfo)o).getEncoded(); } else { throw new IOException("unknown object passed - can't encode."); } writeHeader(type); writeEncoded(encoding); writeFooter(type); } public void writeObject( Object obj, String algorithm, char[] password, SecureRandom random) throws IOException { if (obj instanceof KeyPair) { writeObject(((KeyPair)obj).getPrivate()); return; } String type = null; byte[] keyData = null; if (obj instanceof RSAPrivateCrtKey) { type = "RSA PRIVATE KEY"; RSAPrivateCrtKey k = (RSAPrivateCrtKey)obj; RSAPrivateKeyStructure keyStruct = new RSAPrivateKeyStructure( k.getModulus(), k.getPublicExponent(), k.getPrivateExponent(), k.getPrimeP(), k.getPrimeQ(), k.getPrimeExponentP(), k.getPrimeExponentQ(), k.getCrtCoefficient()); // convert to bytearray keyData = keyStruct.getEncoded(); } else if (obj instanceof DSAPrivateKey) { type = "DSA PRIVATE KEY"; DSAPrivateKey k = (DSAPrivateKey)obj; DSAParams p = k.getParams(); ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new DERInteger(0)); v.add(new DERInteger(p.getP())); v.add(new DERInteger(p.getQ())); v.add(new DERInteger(p.getG())); BigInteger x = k.getX(); BigInteger y = p.getG().modPow(x, p.getP()); v.add(new DERInteger(y)); v.add(new DERInteger(x)); keyData = new DERSequence(v).getEncoded(); } if (type == null || keyData == null) { // TODO Support other types? throw new IllegalArgumentException("Object type not supported: " + obj.getClass().getName()); } String dekAlgName = Strings.toUpperCase(algorithm); // Note: For backward compatibility if (dekAlgName.equals("DESEDE")) { dekAlgName = "DES-EDE3-CBC"; } int ivLength = dekAlgName.startsWith("AES-") ? 16 : 8; byte[] iv = new byte[ivLength]; random.nextBytes(iv); byte[] encData = PEMUtilities.crypt(true, provider, keyData, password, dekAlgName, iv); // write the data writeHeader(type); this.write("Proc-Type: 4,ENCRYPTED"); this.newLine(); this.write("DEK-Info: " + dekAlgName + ","); this.writeHexEncoded(iv); this.newLine(); this.newLine(); this.writeEncoded(encData); writeFooter(type); } private void writeHeader( String type) throws IOException { this.write("-----BEGIN " + type + "-----"); this.newLine(); } private void writeFooter( String type) throws IOException { this.write("-----END " + type + "-----"); this.newLine(); } } azureus-4.3.0.6/org/bouncycastle/asn1/0000755000175000017500000000000011310377632016765 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/asn1/IndefiniteLengthInputStream.java0000644000175000017500000000420711026315606025244 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.io.InputStream; class IndefiniteLengthInputStream extends LimitedInputStream { private int _b1; private int _b2; private boolean _eofReached = false; private boolean _eofOn00 = true; IndefiniteLengthInputStream( InputStream in) throws IOException { super(in); _b1 = in.read(); _b2 = in.read(); _eofReached = (_b2 < 0); } void setEofOn00( boolean eofOn00) { _eofOn00 = eofOn00; } boolean checkForEof() { if (_eofOn00 && (_b1 == 0x00 && _b2 == 0x00)) { _eofReached = true; setParentEofDetect(true); } return _eofReached; } public int read(byte[] b, int off, int len) throws IOException { // Only use this optimisation if we aren't checking for 00 if (_eofOn00 || len < 3) { return super.read(b, off, len); } if (_eofReached) { return -1; } int numRead = _in.read(b, off + 2, len - 2); if (numRead < 0) { // throw new EOFException(); _eofReached = true; return -1; } b[off] = (byte)_b1; b[off + 1] = (byte)_b2; _b1 = _in.read(); _b2 = _in.read(); if (_b2 < 0) { // Corrupted stream // throw new EOFException(); _eofReached = true; // Just fall thru... } return numRead + 2; } public int read() throws IOException { if (checkForEof()) { return -1; } int b = _in.read(); // // strictly speaking we should return b1 and b2, but if this happens the stream // is corrupted so we are already in trouble. // if (b < 0) { // Corrupted stream // throw new EOFException(); _eofReached = true; return -1; } int v = _b1; _b1 = _b2; _b2 = b; return v; } } azureus-4.3.0.6/org/bouncycastle/asn1/DERGenerator.java0000644000175000017500000000560411026315614022112 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public abstract class DERGenerator extends ASN1Generator { private boolean _tagged = false; private boolean _isExplicit; private int _tagNo; protected DERGenerator( OutputStream out) { super(out); } public DERGenerator( OutputStream out, int tagNo, boolean isExplicit) { super(out); _tagged = true; _isExplicit = isExplicit; _tagNo = tagNo; } private void writeLength( OutputStream out, int length) throws IOException { if (length > 127) { int size = 1; int val = length; while ((val >>>= 8) != 0) { size++; } out.write((byte)(size | 0x80)); for (int i = (size - 1) * 8; i >= 0; i -= 8) { out.write((byte)(length >> i)); } } else { out.write((byte)length); } } void writeDEREncoded( OutputStream out, int tag, byte[] bytes) throws IOException { out.write(tag); writeLength(out, bytes.length); out.write(bytes); } void writeDEREncoded( int tag, byte[] bytes) throws IOException { if (_tagged) { int tagNum = _tagNo | DERTags.TAGGED; if (_isExplicit) { int newTag = _tagNo | DERTags.CONSTRUCTED | DERTags.TAGGED; ByteArrayOutputStream bOut = new ByteArrayOutputStream(); writeDEREncoded(bOut, tag, bytes); writeDEREncoded(_out, newTag, bOut.toByteArray()); } else { if ((tag & DERTags.CONSTRUCTED) != 0) { writeDEREncoded(_out, tagNum | DERTags.CONSTRUCTED, bytes); } else { writeDEREncoded(_out, tagNum, bytes); } } } else { writeDEREncoded(_out, tag, bytes); } } void writeDEREncoded( OutputStream out, int tag, InputStream in) throws IOException { out.write(tag); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); int b = 0; while ((b = in.read()) >= 0) { bOut.write(b); } byte[] bytes = bOut.toByteArray(); writeLength(out, bytes.length); out.write(bytes); } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1StreamParser.java0000644000175000017500000001323711026315574022672 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayInputStream; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; public class ASN1StreamParser { InputStream _in; private int _limit; private boolean _eofFound; public ASN1StreamParser( InputStream in) { this(in, Integer.MAX_VALUE); } public ASN1StreamParser( InputStream in, int limit) { this._in = in; this._limit = limit; } public ASN1StreamParser( byte[] encoding) { this(new ByteArrayInputStream(encoding), encoding.length); } InputStream getParentStream() { return _in; } private int readLength() throws IOException { int length = _in.read(); if (length < 0) { throw new EOFException("EOF found when length expected"); } if (length == 0x80) { return -1; // indefinite-length encoding } if (length > 127) { int size = length & 0x7f; if (size > 4) { throw new IOException("DER length more than 4 bytes"); } length = 0; for (int i = 0; i < size; i++) { int next = _in.read(); if (next < 0) { throw new EOFException("EOF found reading length"); } length = (length << 8) + next; } if (length < 0) { throw new IOException("corrupted stream - negative length found"); } if (length >= _limit) // after all we must have read at least 1 byte { throw new IOException("corrupted stream - out of bounds length found"); } } return length; } public DEREncodable readObject() throws IOException { int tag = _in.read(); if (tag == -1) { if (_eofFound) { throw new EOFException("attempt to read past end of file."); } _eofFound = true; return null; } // // turn of looking for "00" while we resolve the tag // set00Check(false); // // calculate tag number // int baseTagNo = tag & ~DERTags.CONSTRUCTED; int tagNo = baseTagNo; if ((tag & DERTags.TAGGED) != 0) { tagNo = tag & 0x1f; // // with tagged object tag number is bottom 5 bits, or stored at the start of the content // if (tagNo == 0x1f) { tagNo = 0; int b = _in.read(); while ((b >= 0) && ((b & 0x80) != 0)) { tagNo |= (b & 0x7f); tagNo <<= 7; b = _in.read(); } if (b < 0) { _eofFound = true; throw new EOFException("EOF encountered inside tag value."); } tagNo |= (b & 0x7f); } } // // calculate length // int length = readLength(); if (length < 0) // indefinite length { IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in); switch (baseTagNo) { case DERTags.NULL: while (indIn.read() >= 0) { // make sure we skip to end of object } return BERNull.INSTANCE; case DERTags.OCTET_STRING: return new BEROctetStringParser(new ASN1ObjectParser(tag, tagNo, indIn)); case DERTags.SEQUENCE: return new BERSequenceParser(new ASN1ObjectParser(tag, tagNo, indIn)); case DERTags.SET: return new BERSetParser(new ASN1ObjectParser(tag, tagNo, indIn)); default: return new BERTaggedObjectParser(tag, tagNo, indIn); } } else { DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length); switch (baseTagNo) { case DERTags.INTEGER: return new DERInteger(defIn.toByteArray()); case DERTags.NULL: defIn.toByteArray(); // make sure we read to end of object bytes. return DERNull.INSTANCE; case DERTags.OBJECT_IDENTIFIER: return new DERObjectIdentifier(defIn.toByteArray()); case DERTags.OCTET_STRING: return new DEROctetString(defIn.toByteArray()); case DERTags.SEQUENCE: return new DERSequence(loadVector(defIn, length)).parser(); case DERTags.SET: return new DERSet(loadVector(defIn, length)).parser(); default: return new BERTaggedObjectParser(tag, tagNo, defIn); } } } private void set00Check(boolean enabled) { if (_in instanceof IndefiniteLengthInputStream) { ((IndefiniteLengthInputStream)_in).setEofOn00(enabled); } } private ASN1EncodableVector loadVector(InputStream in, int length) throws IOException { ASN1InputStream aIn = new ASN1InputStream(in, length); ASN1EncodableVector v = new ASN1EncodableVector(); DERObject obj; while ((obj = aIn.readObject()) != null) { v.add(obj); } return v; } } azureus-4.3.0.6/org/bouncycastle/asn1/BERSet.java0000644000175000017500000000241711026315604020713 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.util.Enumeration; public class BERSet extends DERSet { /** * create an empty sequence */ public BERSet() { } /** * create a set containing one object */ public BERSet( DEREncodable obj) { super(obj); } /** * @param v - a vector of objects making up the set. */ public BERSet( DEREncodableVector v) { super(v, false); } /** * @param v - a vector of objects making up the set. */ BERSet( DEREncodableVector v, boolean needsSorting) { super(v, needsSorting); } /* */ void encode( DEROutputStream out) throws IOException { if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) { out.write(SET | CONSTRUCTED); out.write(0x80); Enumeration e = getObjects(); while (e.hasMoreElements()) { out.writeObject(e.nextElement()); } out.write(0x00); out.write(0x00); } else { super.encode(out); } } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1Choice.java0000644000175000017500000000070411026315576021451 0ustar adrianadrianpackage org.bouncycastle.asn1; /** * Marker interface for CHOICE objects - if you implement this in a role your * own object any attempt to tag the object implicitly will convert the tag to * an explicit one as the encoding rules require. *

      * If you use this interface your class should also implement the getInstance * pattern which takes a tag object and the tagging mode used. */ public interface ASN1Choice { // marker interface } azureus-4.3.0.6/org/bouncycastle/asn1/BERTaggedObjectParser.java0000644000175000017500000001031711026315574023663 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.io.InputStream; public class BERTaggedObjectParser implements ASN1TaggedObjectParser { private int _baseTag; private int _tagNumber; private InputStream _contentStream; private boolean _indefiniteLength; protected BERTaggedObjectParser( int baseTag, int tagNumber, InputStream contentStream) { _baseTag = baseTag; _tagNumber = tagNumber; _contentStream = contentStream; _indefiniteLength = contentStream instanceof IndefiniteLengthInputStream; } public boolean isConstructed() { return (_baseTag & DERTags.CONSTRUCTED) != 0; } public int getTagNo() { return _tagNumber; } public DEREncodable getObjectParser( int tag, boolean isExplicit) throws IOException { if (isExplicit) { return new ASN1StreamParser(_contentStream).readObject(); } else { switch (tag) { case DERTags.SET: if (_indefiniteLength) { return new BERSetParser(new ASN1ObjectParser(_baseTag, _tagNumber, _contentStream)); } else { return new DERSet(loadVector(_contentStream)).parser(); } case DERTags.SEQUENCE: if (_indefiniteLength) { return new BERSequenceParser(new ASN1ObjectParser(_baseTag, _tagNumber, _contentStream)); } else { return new DERSequence(loadVector(_contentStream)).parser(); } case DERTags.OCTET_STRING: if (_indefiniteLength || this.isConstructed()) { return new BEROctetStringParser(new ASN1ObjectParser(_baseTag, _tagNumber, _contentStream)); } else { return new DEROctetString(((DefiniteLengthInputStream)_contentStream).toByteArray()).parser(); } } } throw new RuntimeException("implicit tagging not implemented"); } private ASN1EncodableVector loadVector(InputStream in) throws IOException { ASN1StreamParser aIn = new ASN1StreamParser(in); ASN1EncodableVector v = new ASN1EncodableVector(); DEREncodable obj = aIn.readObject(); while (obj != null) { v.add(obj.getDERObject()); obj = aIn.readObject(); } return v; } private ASN1EncodableVector rLoadVector(InputStream in) { try { return loadVector(in); } catch (IOException e) { throw new IllegalStateException(e.getMessage()); } } public DERObject getDERObject() { if (_indefiniteLength) { ASN1EncodableVector v = rLoadVector(_contentStream); if (v.size() > 1) { return new BERTaggedObject(false, _tagNumber, new BERSequence(v)); } else if (v.size() == 1) { return new BERTaggedObject(true, _tagNumber, v.get(0)); } else { return new BERTaggedObject(false, _tagNumber, new BERSequence()); } } else { if (this.isConstructed()) { ASN1EncodableVector v = rLoadVector(_contentStream); if (v.size() == 1) { return new DERTaggedObject(true, _tagNumber, v.get(0)); } return new DERTaggedObject(false, _tagNumber, new DERSequence(v)); } try { return new DERTaggedObject(false, _tagNumber, new DEROctetString(((DefiniteLengthInputStream)_contentStream).toByteArray())); } catch (IOException e) { throw new IllegalStateException(e.getMessage()); } } } } azureus-4.3.0.6/org/bouncycastle/asn1/DERObject.java0000644000175000017500000000060211026315620021360 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; public abstract class DERObject extends ASN1Encodable implements DERTags { public DERObject toASN1Object() { return this; } public abstract int hashCode(); public abstract boolean equals(Object o); abstract void encode(DEROutputStream out) throws IOException; } azureus-4.3.0.6/org/bouncycastle/asn1/BERSetParser.java0000644000175000017500000000071011026315620022060 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; public class BERSetParser implements ASN1SetParser { private ASN1ObjectParser _parser; BERSetParser(ASN1ObjectParser parser) { this._parser = parser; } public DEREncodable readObject() throws IOException { return _parser.readObject(); } public DERObject getDERObject() { return new BERSet(_parser.readVector()); } } azureus-4.3.0.6/org/bouncycastle/asn1/BERSequenceParser.java0000644000175000017500000000073411026315562023110 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; public class BERSequenceParser implements ASN1SequenceParser { private ASN1ObjectParser _parser; BERSequenceParser(ASN1ObjectParser parser) { this._parser = parser; } public DEREncodable readObject() throws IOException { return _parser.readObject(); } public DERObject getDERObject() { return new BERSequence(_parser.readVector()); } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1OutputStream.java0000644000175000017500000000133310061400650022714 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.io.OutputStream; public class ASN1OutputStream extends DEROutputStream { public ASN1OutputStream( OutputStream os) { super(os); } public void writeObject( Object obj) throws IOException { if (obj == null) { writeNull(); } else if (obj instanceof DERObject) { ((DERObject)obj).encode(this); } else if (obj instanceof DEREncodable) { ((DEREncodable)obj).getDERObject().encode(this); } else { throw new IOException("object not ASN1Encodable"); } } } azureus-4.3.0.6/org/bouncycastle/asn1/DERPrintableString.java0000644000175000017500000001103311026315600023257 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; /** * DER PrintableString object. */ public class DERPrintableString extends ASN1Object implements DERString { String string; /** * return a printable string from the passed in object. * * @exception IllegalArgumentException if the object cannot be converted. */ public static DERPrintableString getInstance( Object obj) { if (obj == null || obj instanceof DERPrintableString) { return (DERPrintableString)obj; } if (obj instanceof ASN1OctetString) { return new DERPrintableString(((ASN1OctetString)obj).getOctets()); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return a Printable String from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERPrintableString getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } /** * basic constructor - byte encoded string. */ public DERPrintableString( byte[] string) { char[] cs = new char[string.length]; for (int i = 0; i != cs.length; i++) { cs[i] = (char)(string[i] & 0xff); } this.string = new String(cs); } /** * basic constructor - this does not validate the string */ public DERPrintableString( String string) { this(string, false); } /** * Constructor with optional validation. * * @param string the base string to wrap. * @param validate whether or not to check the string. * @throws IllegalArgumentException if validate is true and the string * contains characters that should not be in a PrintableString. */ public DERPrintableString( String string, boolean validate) { if (validate && !isPrintableString(string)) { throw new IllegalArgumentException("string contains illegal characters"); } this.string = string; } public String getString() { return string; } public byte[] getOctets() { char[] cs = string.toCharArray(); byte[] bs = new byte[cs.length]; for (int i = 0; i != cs.length; i++) { bs[i] = (byte)cs[i]; } return bs; } void encode( DEROutputStream out) throws IOException { out.writeEncoded(PRINTABLE_STRING, this.getOctets()); } public int hashCode() { return this.getString().hashCode(); } boolean asn1Equals( DERObject o) { if (!(o instanceof DERPrintableString)) { return false; } DERPrintableString s = (DERPrintableString)o; return this.getString().equals(s.getString()); } public String toString() { return string; } /** * return true if the passed in String can be represented without * loss as a PrintableString, false otherwise. * * @return true if in printable set, false otherwise. */ public static boolean isPrintableString( String str) { for (int i = str.length() - 1; i >= 0; i--) { char ch = str.charAt(i); if (ch > 0x007f) { return false; } if ('a' <= ch && ch <= 'z') { continue; } if ('A' <= ch && ch <= 'Z') { continue; } if ('0' <= ch && ch <= '9') { continue; } switch (ch) { case ' ': case '\'': case '(': case ')': case '+': case '-': case '.': case ':': case '=': case '?': case '/': case ',': continue; } return false; } return true; } } azureus-4.3.0.6/org/bouncycastle/asn1/ConstructedOctetStream.java0000644000175000017500000000461211026315564024303 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.InputStream; import java.io.IOException; class ConstructedOctetStream extends InputStream { private final ASN1ObjectParser _parser; private boolean _first = true; private InputStream _currentStream; ConstructedOctetStream( ASN1ObjectParser parser) { _parser = parser; } public int read(byte[] b, int off, int len) throws IOException { if (_currentStream == null) { if (!_first) { return -1; } ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject(); if (s == null) { return -1; } _first = false; _currentStream = s.getOctetStream(); } int totalRead = 0; for (;;) { int numRead = _currentStream.read(b, off + totalRead, len - totalRead); if (numRead >= 0) { totalRead += numRead; if (totalRead == len) { return totalRead; } } else { ASN1OctetStringParser aos = (ASN1OctetStringParser)_parser.readObject(); if (aos == null) { _currentStream = null; return totalRead < 1 ? -1 : totalRead; } _currentStream = aos.getOctetStream(); } } } public int read() throws IOException { if (_currentStream == null) { if (!_first) { return -1; } ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject(); if (s == null) { return -1; } _first = false; _currentStream = s.getOctetStream(); } for (;;) { int b = _currentStream.read(); if (b >= 0) { return b; } ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject(); if (s == null) { _currentStream = null; return -1; } _currentStream = s.getOctetStream(); } } } azureus-4.3.0.6/org/bouncycastle/asn1/DERUnknownTag.java0000644000175000017500000000303011026315620022243 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; /** * We insert one of these when we find a tag we don't recognise. */ public class DERUnknownTag extends DERObject { int tag; byte[] data; /** * @param tag the tag value. * @param data the octets making up the time. */ public DERUnknownTag( int tag, byte[] data) { this.tag = tag; this.data = data; } public int getTag() { return tag; } public byte[] getData() { return data; } void encode( DEROutputStream out) throws IOException { out.writeEncoded(tag, data); } public boolean equals( Object o) { if (!(o instanceof DERUnknownTag)) { return false; } DERUnknownTag other = (DERUnknownTag)o; if (tag != other.tag) { return false; } if (data.length != other.data.length) { return false; } for (int i = 0; i < data.length; i++) { if(data[i] != other.data[i]) { return false; } } return true; } public int hashCode() { byte[] b = this.getData(); int value = 0; for (int i = 0; i != b.length; i++) { value ^= (b[i] & 0xff) << (i % 4); } return value ^ this.getTag(); } } azureus-4.3.0.6/org/bouncycastle/asn1/DERGeneralString.java0000644000175000017500000000413511026315612022724 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; public class DERGeneralString extends ASN1Object implements DERString { private String string; public static DERGeneralString getInstance( Object obj) { if (obj == null || obj instanceof DERGeneralString) { return (DERGeneralString) obj; } if (obj instanceof ASN1OctetString) { return new DERGeneralString(((ASN1OctetString) obj).getOctets()); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject) obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } public static DERGeneralString getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } public DERGeneralString(byte[] string) { char[] cs = new char[string.length]; for (int i = 0; i != cs.length; i++) { cs[i] = (char)(string[i] & 0xff); } this.string = new String(cs); } public DERGeneralString(String string) { this.string = string; } public String getString() { return string; } public String toString() { return string; } public byte[] getOctets() { char[] cs = string.toCharArray(); byte[] bs = new byte[cs.length]; for (int i = 0; i != cs.length; i++) { bs[i] = (byte) cs[i]; } return bs; } void encode(DEROutputStream out) throws IOException { out.writeEncoded(GENERAL_STRING, this.getOctets()); } public int hashCode() { return this.getString().hashCode(); } boolean asn1Equals(DERObject o) { if (!(o instanceof DERGeneralString)) { return false; } DERGeneralString s = (DERGeneralString) o; return this.getString().equals(s.getString()); } } azureus-4.3.0.6/org/bouncycastle/asn1/DEROctetString.java0000644000175000017500000000077010061400650022421 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; public class DEROctetString extends ASN1OctetString { /** * @param string the octets making up the octet string. */ public DEROctetString( byte[] string) { super(string); } public DEROctetString( DEREncodable obj) { super(obj); } void encode( DEROutputStream out) throws IOException { out.writeEncoded(OCTET_STRING, string); } } azureus-4.3.0.6/org/bouncycastle/asn1/BERSequence.java0000644000175000017500000000213610061400650021720 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.util.Enumeration; public class BERSequence extends DERSequence { /** * create an empty sequence */ public BERSequence() { } /** * create a sequence containing one object */ public BERSequence( DEREncodable obj) { super(obj); } /** * create a sequence containing a vector of objects. */ public BERSequence( DEREncodableVector v) { super(v); } /* */ void encode( DEROutputStream out) throws IOException { if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) { out.write(SEQUENCE | CONSTRUCTED); out.write(0x80); Enumeration e = getObjects(); while (e.hasMoreElements()) { out.writeObject(e.nextElement()); } out.write(0x00); out.write(0x00); } else { super.encode(out); } } } azureus-4.3.0.6/org/bouncycastle/asn1/DERBoolean.java0000644000175000017500000000476011026315620021542 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; public class DERBoolean extends ASN1Object { byte value; public static final DERBoolean FALSE = new DERBoolean(false); public static final DERBoolean TRUE = new DERBoolean(true); /** * return a boolean from the passed in object. * * @exception IllegalArgumentException if the object cannot be converted. */ public static DERBoolean getInstance( Object obj) { if (obj == null || obj instanceof DERBoolean) { return (DERBoolean)obj; } if (obj instanceof ASN1OctetString) { return new DERBoolean(((ASN1OctetString)obj).getOctets()); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return a DERBoolean from the passed in boolean. */ public static DERBoolean getInstance( boolean value) { return (value ? TRUE : FALSE); } /** * return a Boolean from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERBoolean getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } public DERBoolean( byte[] value) { this.value = value[0]; } public DERBoolean( boolean value) { this.value = (value) ? (byte)0xff : (byte)0; } public boolean isTrue() { return (value != 0); } void encode( DEROutputStream out) throws IOException { byte[] bytes = new byte[1]; bytes[0] = value; out.writeEncoded(BOOLEAN, bytes); } protected boolean asn1Equals( DERObject o) { if ((o == null) || !(o instanceof DERBoolean)) { return false; } return (value == ((DERBoolean)o).value); } public int hashCode() { return value; } public String toString() { return (value != 0) ? "TRUE" : "FALSE"; } } azureus-4.3.0.6/org/bouncycastle/asn1/DERConstructedSet.java0000644000175000017500000000326011026315570023132 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Enumeration; /** * * @deprecated use DERSet */ public class DERConstructedSet extends ASN1Set { public DERConstructedSet() { } /** * @param obj - a single object that makes up the set. */ public DERConstructedSet( DEREncodable obj) { this.addObject(obj); } /** * @param v - a vector of objects making up the set. */ public DERConstructedSet( DEREncodableVector v) { for (int i = 0; i != v.size(); i++) { this.addObject(v.get(i)); } } public void addObject( DEREncodable obj) { super.addObject(obj); } public int getSize() { return size(); } /* * A note on the implementation: *

      * As DER requires the constructed, definite-length model to * be used for structured types, this varies slightly from the * ASN.1 descriptions given. Rather than just outputing SET, * we also have to specify CONSTRUCTED, and the objects length. */ void encode( DEROutputStream out) throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); Enumeration e = this.getObjects(); while (e.hasMoreElements()) { Object obj = e.nextElement(); dOut.writeObject(obj); } dOut.close(); byte[] bytes = bOut.toByteArray(); out.writeEncoded(SET | CONSTRUCTED, bytes); } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1TaggedObject.java0000644000175000017500000001201511026315612022566 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; /** * ASN.1 TaggedObject - in ASN.1 nottation this is any object proceeded by * a [n] where n is some number - these are assume to follow the construction * rules (as with sequences). */ public abstract class ASN1TaggedObject extends ASN1Object implements ASN1TaggedObjectParser { int tagNo; boolean empty = false; boolean explicit = true; DEREncodable obj = null; static public ASN1TaggedObject getInstance( ASN1TaggedObject obj, boolean explicit) { if (explicit) { return (ASN1TaggedObject)obj.getObject(); } throw new IllegalArgumentException("implicitly tagged tagged object"); } static public ASN1TaggedObject getInstance( Object obj) { if (obj == null || obj instanceof ASN1TaggedObject) { return (ASN1TaggedObject)obj; } throw new IllegalArgumentException("unknown object in getInstance"); } /** * Create a tagged object in the explicit style. * * @param tagNo the tag number for this object. * @param obj the tagged object. */ public ASN1TaggedObject( int tagNo, DEREncodable obj) { this.explicit = true; this.tagNo = tagNo; this.obj = obj; } /** * Create a tagged object with the style given by the value of explicit. *

      * If the object implements ASN1Choice the tag style will always be changed * to explicit in accordance with the ASN.1 encoding rules. *

      * @param explicit true if the object is explicitly tagged. * @param tagNo the tag number for this object. * @param obj the tagged object. */ public ASN1TaggedObject( boolean explicit, int tagNo, DEREncodable obj) { if (obj instanceof ASN1Choice) { this.explicit = true; } else { this.explicit = explicit; } this.tagNo = tagNo; this.obj = obj; } boolean asn1Equals( DERObject o) { if (!(o instanceof ASN1TaggedObject)) { return false; } ASN1TaggedObject other = (ASN1TaggedObject)o; if (tagNo != other.tagNo || empty != other.empty || explicit != other.explicit) { return false; } if(obj == null) { if (other.obj != null) { return false; } } else { if (!(obj.getDERObject().equals(other.obj.getDERObject()))) { return false; } } return true; } public int hashCode() { int code = tagNo; if (obj != null) { code ^= obj.hashCode(); } return code; } public int getTagNo() { return tagNo; } /** * return whether or not the object may be explicitly tagged. *

      * Note: if the object has been read from an input stream, the only * time you can be sure if isExplicit is returning the true state of * affairs is if it returns false. An implicitly tagged object may appear * to be explicitly tagged, so you need to understand the context under * which the reading was done as well, see getObject below. */ public boolean isExplicit() { return explicit; } public boolean isEmpty() { return empty; } /** * return whatever was following the tag. *

      * Note: tagged objects are generally context dependent if you're * trying to extract a tagged object you should be going via the * appropriate getInstance method. */ public DERObject getObject() { if (obj != null) { return obj.getDERObject(); } return null; } /** * Return the object held in this tagged object as a parser assuming it has * the type of the passed in tag. If the object doesn't have a parser * associated with it, the base object is returned. */ public DEREncodable getObjectParser( int tag, boolean isExplicit) { switch (tag) { case DERTags.SET: return ASN1Set.getInstance(this, isExplicit).parser(); case DERTags.SEQUENCE: return ASN1Sequence.getInstance(this, isExplicit).parser(); case DERTags.OCTET_STRING: return ASN1OctetString.getInstance(this, isExplicit).parser(); } if (isExplicit) { return getObject(); } throw new RuntimeException("implicit tagging not implemented for tag: " + tag); } abstract void encode(DEROutputStream out) throws IOException; public String toString() { return "[" + tagNo + "]" + obj; } } azureus-4.3.0.6/org/bouncycastle/asn1/DEROutputStream.java0000644000175000017500000000347011026315570022640 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; public class DEROutputStream extends FilterOutputStream implements DERTags { public DEROutputStream( OutputStream os) { super(os); } private void writeLength( int length) throws IOException { if (length > 127) { int size = 1; int val = length; while ((val >>>= 8) != 0) { size++; } write((byte)(size | 0x80)); for (int i = (size - 1) * 8; i >= 0; i -= 8) { write((byte)(length >> i)); } } else { write((byte)length); } } void writeEncoded( int tag, byte[] bytes) throws IOException { write(tag); writeLength(bytes.length); write(bytes); } protected void writeNull() throws IOException { write(NULL); write(0x00); } public void write(byte[] buf) throws IOException { out.write(buf, 0, buf.length); } public void write(byte[] buf, int offSet, int len) throws IOException { out.write(buf, offSet, len); } public void writeObject( Object obj) throws IOException { if (obj == null) { writeNull(); } else if (obj instanceof DERObject) { ((DERObject)obj).encode(this); } else if (obj instanceof DEREncodable) { ((DEREncodable)obj).getDERObject().encode(this); } else { throw new IOException("object not DEREncodable"); } } } azureus-4.3.0.6/org/bouncycastle/asn1/misc/0000755000175000017500000000000011310377632017720 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/asn1/misc/NetscapeCertType.java0000644000175000017500000000315210061400654023777 0ustar adrianadrianpackage org.bouncycastle.asn1.misc; import org.bouncycastle.asn1.*; /** * The NetscapeCertType object. *

       *    NetscapeCertType ::= BIT STRING {
       *         SSLClient               (0),
       *         SSLServer               (1),
       *         S/MIME                  (2),
       *         Object Signing          (3),
       *         Reserved                (4),
       *         SSL CA                  (5),
       *         S/MIME CA               (6),
       *         Object Signing CA       (7) }
       * 
      */ public class NetscapeCertType extends DERBitString { public static final int sslClient = (1 << 7); public static final int sslServer = (1 << 6); public static final int smime = (1 << 5); public static final int objectSigning = (1 << 4); public static final int reserved = (1 << 3); public static final int sslCA = (1 << 2); public static final int smimeCA = (1 << 1); public static final int objectSigningCA = (1 << 0); /** * Basic constructor. * * @param usage - the bitwise OR of the Key Usage flags giving the * allowed uses for the key. * e.g. (X509NetscapeCertType.sslCA | X509NetscapeCertType.smimeCA) */ public NetscapeCertType( int usage) { super(getBytes(usage), getPadBits(usage)); } public NetscapeCertType( DERBitString usage) { super(usage.getBytes(), usage.getPadBits()); } public String toString() { return "NetscapeCertType: 0x" + Integer.toHexString(data[0] & 0xff); } } azureus-4.3.0.6/org/bouncycastle/asn1/misc/package.html0000644000175000017500000000013610061400654022172 0ustar adrianadrian Miscellaneous object identifiers and objects. azureus-4.3.0.6/org/bouncycastle/asn1/misc/CAST5CBCParameters.java0000644000175000017500000000327510061400654023736 0ustar adrianadrianpackage org.bouncycastle.asn1.misc; import org.bouncycastle.asn1.*; public class CAST5CBCParameters implements DEREncodable { DERInteger keyLength; ASN1OctetString iv; public static CAST5CBCParameters getInstance( Object o) { if (o instanceof CAST5CBCParameters) { return (CAST5CBCParameters)o; } else if (o instanceof ASN1Sequence) { return new CAST5CBCParameters((ASN1Sequence)o); } throw new IllegalArgumentException("unknown object in CAST5CBCParameter factory"); } public CAST5CBCParameters( byte[] iv, int keyLength) { this.iv = new DEROctetString(iv); this.keyLength = new DERInteger(keyLength); } public CAST5CBCParameters( ASN1Sequence seq) { iv = (ASN1OctetString)seq.getObjectAt(0); keyLength = (DERInteger)seq.getObjectAt(1); } public byte[] getIV() { return iv.getOctets(); } public int getKeyLength() { return keyLength.getValue().intValue(); } /** * Produce an object suitable for an ASN1OutputStream. *
           * cast5CBCParameters ::= SEQUENCE {
           *                           iv         OCTET STRING DEFAULT 0,
           *                                  -- Initialization vector
           *                           keyLength  INTEGER
           *                                  -- Key length, in bits
           *                      }
           * 
      */ public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(iv); v.add(keyLength); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java0000644000175000017500000000310410061400654024762 0ustar adrianadrianpackage org.bouncycastle.asn1.misc; import org.bouncycastle.asn1.DERObjectIdentifier; public interface MiscObjectIdentifiers { // // Netscape // iso/itu(2) joint-assign(16) us(840) uscompany(1) netscape(113730) cert-extensions(1) } // static final String netscape = "2.16.840.1.113730.1"; static final DERObjectIdentifier netscapeCertType = new DERObjectIdentifier(netscape + ".1"); static final DERObjectIdentifier netscapeBaseURL = new DERObjectIdentifier(netscape + ".2"); static final DERObjectIdentifier netscapeRevocationURL = new DERObjectIdentifier(netscape + ".3"); static final DERObjectIdentifier netscapeCARevocationURL = new DERObjectIdentifier(netscape + ".4"); static final DERObjectIdentifier netscapeRenewalURL = new DERObjectIdentifier(netscape + ".7"); static final DERObjectIdentifier netscapeCApolicyURL = new DERObjectIdentifier(netscape + ".8"); static final DERObjectIdentifier netscapeSSLServerName = new DERObjectIdentifier(netscape + ".12"); static final DERObjectIdentifier netscapeCertComment = new DERObjectIdentifier(netscape + ".13"); // // Verisign // iso/itu(2) joint-assign(16) us(840) uscompany(1) verisign(113733) cert-extensions(1) } // static final String verisign = "2.16.840.1.113733.1"; // // CZAG - country, zip, age, and gender // static final DERObjectIdentifier verisignCzagExtension = new DERObjectIdentifier(verisign + ".6.3"); } azureus-4.3.0.6/org/bouncycastle/asn1/misc/VerisignCzagExtension.java0000644000175000017500000000052510061400654025046 0ustar adrianadrianpackage org.bouncycastle.asn1.misc; import org.bouncycastle.asn1.*; public class VerisignCzagExtension extends DERIA5String { public VerisignCzagExtension( DERIA5String str) { super(str.getString()); } public String toString() { return "VerisignCzagExtension: " + this.getString(); } } azureus-4.3.0.6/org/bouncycastle/asn1/misc/NetscapeRevocationURL.java0000644000175000017500000000052510061400654024735 0ustar adrianadrianpackage org.bouncycastle.asn1.misc; import org.bouncycastle.asn1.*; public class NetscapeRevocationURL extends DERIA5String { public NetscapeRevocationURL( DERIA5String str) { super(str.getString()); } public String toString() { return "NetscapeRevocationURL: " + this.getString(); } } azureus-4.3.0.6/org/bouncycastle/asn1/misc/IDEACBCPar.java0000644000175000017500000000267010061400654022236 0ustar adrianadrianpackage org.bouncycastle.asn1.misc; import org.bouncycastle.asn1.*; public class IDEACBCPar implements DEREncodable { ASN1OctetString iv; public static IDEACBCPar getInstance( Object o) { if (o instanceof IDEACBCPar) { return (IDEACBCPar)o; } else if (o instanceof ASN1Sequence) { return new IDEACBCPar((ASN1Sequence)o); } throw new IllegalArgumentException("unknown object in IDEACBCPar factory"); } public IDEACBCPar( byte[] iv) { this.iv = new DEROctetString(iv); } public IDEACBCPar( ASN1Sequence seq) { if (seq.size() == 1) { iv = (ASN1OctetString)seq.getObjectAt(0); } else { iv = null; } } public byte[] getIV() { if (iv != null) { return iv.getOctets(); } else { return null; } } /** * Produce an object suitable for an ASN1OutputStream. *
           * IDEA-CBCPar ::= SEQUENCE {
           *                      iv    OCTET STRING OPTIONAL -- exactly 8 octets
           *                  }
           * 
      */ public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); if (iv != null) { v.add(iv); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/package.html0000644000175000017500000000021710061400650021233 0ustar adrianadrian A library for parsing and writing ASN.1 objects. Support is provided for DER and BER encoding. azureus-4.3.0.6/org/bouncycastle/asn1/BERConstructedSequence.java0000644000175000017500000000142011026315606024141 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.util.Enumeration; /** * @deprecated use BERSequence */ public class BERConstructedSequence extends DERConstructedSequence { /* */ void encode( DEROutputStream out) throws IOException { if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) { out.write(SEQUENCE | CONSTRUCTED); out.write(0x80); Enumeration e = getObjects(); while (e.hasMoreElements()) { out.writeObject(e.nextElement()); } out.write(0x00); out.write(0x00); } else { super.encode(out); } } } azureus-4.3.0.6/org/bouncycastle/asn1/DERApplicationSpecific.java0000644000175000017500000000745111026315612024075 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * Base class for an application specific object */ public class DERApplicationSpecific extends ASN1Object { private int tag; private byte[] octets; public DERApplicationSpecific( int tag, byte[] octets) { this.tag = tag; this.octets = octets; } public DERApplicationSpecific( int tag, DEREncodable object) throws IOException { this(true, tag, object); } public DERApplicationSpecific( boolean explicit, int tag, DEREncodable object) throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dos = new DEROutputStream(bOut); dos.writeObject(object); byte[] data = bOut.toByteArray(); if (tag >= 0x1f) { throw new IOException("unsupported tag number"); } if (explicit) { this.tag = tag | DERTags.CONSTRUCTED; this.octets = data; } else { this.tag = tag; int lenBytes = getLengthOfLength(data); byte[] tmp = new byte[data.length - lenBytes]; System.arraycopy(data, lenBytes, tmp, 0, tmp.length); this.octets = tmp; } } private int getLengthOfLength(byte[] data) { int count = 2; // TODO: assumes only a 1 byte tag number while((data[count - 1] & 0x80) != 0) { count++; } return count; } public boolean isConstructed() { return (tag & DERTags.CONSTRUCTED) != 0; } public byte[] getContents() { return octets; } public int getApplicationTag() { return tag; } public DERObject getObject() throws IOException { return new ASN1InputStream(getContents()).readObject(); } /** * Return the enclosed object assuming implicit tagging. * * @param derTagNo the type tag that should be applied to the object's contents. * @return the resulting object * @throws IOException if reconstruction fails. */ public DERObject getObject(int derTagNo) throws IOException { if (tag >= 0x1f) { throw new IOException("unsupported tag number"); } byte[] tmp = this.getEncoded(); tmp[0] = (byte)derTagNo; return new ASN1InputStream(tmp).readObject(); } /* (non-Javadoc) * @see org.bouncycastle.asn1.DERObject#encode(org.bouncycastle.asn1.DEROutputStream) */ void encode(DEROutputStream out) throws IOException { out.writeEncoded(DERTags.APPLICATION | tag, octets); } boolean asn1Equals( DERObject o) { if (!(o instanceof DERApplicationSpecific)) { return false; } DERApplicationSpecific other = (DERApplicationSpecific)o; if (tag != other.tag) { return false; } if (octets.length != other.octets.length) { return false; } for (int i = 0; i < octets.length; i++) { if (octets[i] != other.octets[i]) { return false; } } return true; } public int hashCode() { byte[] b = this.getContents(); int value = 0; for (int i = 0; i != b.length; i++) { value ^= (b[i] & 0xff) << (i % 4); } return value ^ this.getApplicationTag(); } } azureus-4.3.0.6/org/bouncycastle/asn1/DERConstructedSequence.java0000644000175000017500000000235610061400650024144 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Enumeration; /** * @deprecated use DERSequence. */ public class DERConstructedSequence extends ASN1Sequence { public void addObject( DEREncodable obj) { super.addObject(obj); } public int getSize() { return size(); } /* * A note on the implementation: *

      * As DER requires the constructed, definite-length model to * be used for structured types, this varies slightly from the * ASN.1 descriptions given. Rather than just outputing SEQUENCE, * we also have to specify CONSTRUCTED, and the objects length. */ void encode( DEROutputStream out) throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); Enumeration e = this.getObjects(); while (e.hasMoreElements()) { Object obj = e.nextElement(); dOut.writeObject(obj); } dOut.close(); byte[] bytes = bOut.toByteArray(); out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes); } } azureus-4.3.0.6/org/bouncycastle/asn1/DEREnumerated.java0000644000175000017500000000473511026315564022265 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.math.BigInteger; public class DEREnumerated extends ASN1Object { byte[] bytes; /** * return an integer from the passed in object * * @exception IllegalArgumentException if the object cannot be converted. */ public static DEREnumerated getInstance( Object obj) { if (obj == null || obj instanceof DEREnumerated) { return (DEREnumerated)obj; } if (obj instanceof ASN1OctetString) { return new DEREnumerated(((ASN1OctetString)obj).getOctets()); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return an Enumerated from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DEREnumerated getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } public DEREnumerated( int value) { bytes = BigInteger.valueOf(value).toByteArray(); } public DEREnumerated( BigInteger value) { bytes = value.toByteArray(); } public DEREnumerated( byte[] bytes) { this.bytes = bytes; } public BigInteger getValue() { return new BigInteger(bytes); } void encode( DEROutputStream out) throws IOException { out.writeEncoded(ENUMERATED, bytes); } boolean asn1Equals( DERObject o) { if (!(o instanceof DEREnumerated)) { return false; } DEREnumerated other = (DEREnumerated)o; if (bytes.length != other.bytes.length) { return false; } for (int i = 0; i != bytes.length; i++) { if (bytes[i] != other.bytes[i]) { return false; } } return true; } public int hashCode() { return this.getValue().hashCode(); } } azureus-4.3.0.6/org/bouncycastle/asn1/LimitedInputStream.java0000644000175000017500000000101111026315600023373 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.InputStream; abstract class LimitedInputStream extends InputStream { protected final InputStream _in; LimitedInputStream( InputStream in) { this._in = in; } InputStream getUnderlyingStream() { return _in; } protected void setParentEofDetect(boolean on) { if (_in instanceof IndefiniteLengthInputStream) { ((IndefiniteLengthInputStream)_in).setEofOn00(on); } } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/0000755000175000017500000000000011310377632017725 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/asn1/pkcs/SignedData.java0000644000175000017500000001032610061400652022564 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.BERSequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERTaggedObject; /** * a PKCS#7 signed data object. */ public class SignedData implements DEREncodable, PKCSObjectIdentifiers { private DERInteger version; private ASN1Set digestAlgorithms; private ContentInfo contentInfo; private ASN1Set certificates; private ASN1Set crls; private ASN1Set signerInfos; public static SignedData getInstance( Object o) { if (o instanceof SignedData) { return (SignedData)o; } else if (o instanceof ASN1Sequence) { return new SignedData((ASN1Sequence)o); } throw new IllegalArgumentException("unknown object in factory: " + o); } public SignedData( DERInteger _version, ASN1Set _digestAlgorithms, ContentInfo _contentInfo, ASN1Set _certificates, ASN1Set _crls, ASN1Set _signerInfos) { version = _version; digestAlgorithms = _digestAlgorithms; contentInfo = _contentInfo; certificates = _certificates; crls = _crls; signerInfos = _signerInfos; } public SignedData( ASN1Sequence seq) { Enumeration e = seq.getObjects(); version = (DERInteger)e.nextElement(); digestAlgorithms = ((ASN1Set)e.nextElement()); contentInfo = ContentInfo.getInstance(e.nextElement()); while (e.hasMoreElements()) { DERObject o = (DERObject)e.nextElement(); // // an interesting feature of SignedData is that there appear to be varying implementations... // for the moment we ignore anything which doesn't fit. // if (o instanceof DERTaggedObject) { DERTaggedObject tagged = (DERTaggedObject)o; switch (tagged.getTagNo()) { case 0: certificates = ASN1Set.getInstance(tagged, false); break; case 1: crls = ASN1Set.getInstance(tagged, false); break; default: throw new IllegalArgumentException("unknown tag value " + tagged.getTagNo()); } } else { signerInfos = (ASN1Set)o; } } } public DERInteger getVersion() { return version; } public ASN1Set getDigestAlgorithms() { return digestAlgorithms; } public ContentInfo getContentInfo() { return contentInfo; } public ASN1Set getCertificates() { return certificates; } public ASN1Set getCRLs() { return crls; } public ASN1Set getSignerInfos() { return signerInfos; } /** * Produce an object suitable for an ASN1OutputStream. *

           *  SignedData ::= SEQUENCE {
           *      version Version,
           *      digestAlgorithms DigestAlgorithmIdentifiers,
           *      contentInfo ContentInfo,
           *      certificates
           *          [0] IMPLICIT ExtendedCertificatesAndCertificates
           *                   OPTIONAL,
           *      crls
           *          [1] IMPLICIT CertificateRevocationLists OPTIONAL,
           *      signerInfos SignerInfos }
           * 
      */ public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(version); v.add(digestAlgorithms); v.add(contentInfo); if (certificates != null) { v.add(new DERTaggedObject(false, 0, certificates)); } if (crls != null) { v.add(new DERTaggedObject(false, 1, crls)); } v.add(signerInfos); return new BERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java0000644000175000017500000000314710061400652023162 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.math.BigInteger; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; public class PKCS12PBEParams implements DEREncodable { DERInteger iterations; ASN1OctetString iv; public PKCS12PBEParams( byte[] salt, int iterations) { this.iv = new DEROctetString(salt); this.iterations = new DERInteger(iterations); } public PKCS12PBEParams( ASN1Sequence seq) { iv = (ASN1OctetString)seq.getObjectAt(0); iterations = (DERInteger)seq.getObjectAt(1); } public static PKCS12PBEParams getInstance( Object obj) { if (obj instanceof PKCS12PBEParams) { return (PKCS12PBEParams)obj; } else if (obj instanceof ASN1Sequence) { return new PKCS12PBEParams((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public BigInteger getIterations() { return iterations.getValue(); } public byte[] getIV() { return iv.getOctets(); } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(iv); v.add(iterations); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/PBKDF2Params.java0000644000175000017500000000355410061400652022642 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.math.BigInteger; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; public class PBKDF2Params extends KeyDerivationFunc { DERObjectIdentifier id; ASN1OctetString octStr; DERInteger iterationCount; DERInteger keyLength; PBKDF2Params( ASN1Sequence seq) { super(seq); Enumeration e = seq.getObjects(); id = (DERObjectIdentifier)e.nextElement(); ASN1Sequence params = (ASN1Sequence)e.nextElement(); e = params.getObjects(); octStr = (ASN1OctetString)e.nextElement(); iterationCount = (DERInteger)e.nextElement(); if (e.hasMoreElements()) { keyLength = (DERInteger)e.nextElement(); } else { keyLength = null; } } public byte[] getSalt() { return octStr.getOctets(); } public BigInteger getIterationCount() { return iterationCount.getValue(); } public BigInteger getKeyLength() { if (keyLength != null) { return keyLength.getValue(); } return null; } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); ASN1EncodableVector subV = new ASN1EncodableVector(); v.add(id); subV.add(octStr); subV.add(iterationCount); if (keyLength != null) { subV.add(keyLength); } v.add(new DERSequence(subV)); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/Attribute.java0000644000175000017500000000345210061400652022526 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; public class Attribute implements DEREncodable { private DERObjectIdentifier attrType; private ASN1Set attrValues; /** * return an Attribute object from the given object. * * @param o the object we want converted. * @exception IllegalArgumentException if the object cannot be converted. */ public static Attribute getInstance( Object o) { if (o == null || o instanceof Attribute) { return (Attribute)o; } if (o instanceof ASN1Sequence) { return new Attribute((ASN1Sequence)o); } throw new IllegalArgumentException("unknown object in factory"); } public Attribute( ASN1Sequence seq) { attrType = (DERObjectIdentifier)seq.getObjectAt(0); attrValues = (ASN1Set)seq.getObjectAt(1); } public Attribute( DERObjectIdentifier attrType, ASN1Set attrValues) { this.attrType = attrType; this.attrValues = attrValues; } public DERObjectIdentifier getAttrType() { return attrType; } public ASN1Set getAttrValues() { return attrValues; } /** * Produce an object suitable for an ASN1OutputStream. *
           * Attribute ::= SEQUENCE {
           * 	attrType OBJECT IDENTIFIER,
           * 	attrValues SET OF AttributeValue
           * }
           * 
      */ public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(attrType); v.add(attrValues); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java0000644000175000017500000000345110061400652023427 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; /** * @deprecated - use AlgorithmIdentifier and PBES2Params */ public class PBES2Algorithms extends AlgorithmIdentifier implements PKCSObjectIdentifiers { private DERObjectIdentifier objectId; private KeyDerivationFunc func; private EncryptionScheme scheme; public PBES2Algorithms( ASN1Sequence obj) { super(obj); Enumeration e = obj.getObjects(); objectId = (DERObjectIdentifier)e.nextElement(); ASN1Sequence seq = (ASN1Sequence)e.nextElement(); e = seq.getObjects(); ASN1Sequence funcSeq = (ASN1Sequence)e.nextElement(); if (funcSeq.getObjectAt(0).equals(id_PBKDF2)) { func = new PBKDF2Params(funcSeq); } else { func = new KeyDerivationFunc(funcSeq); } scheme = new EncryptionScheme((ASN1Sequence)e.nextElement()); } public DERObjectIdentifier getObjectId() { return objectId; } public KeyDerivationFunc getKeyDerivationFunc() { return func; } public EncryptionScheme getEncryptionScheme() { return scheme; } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); ASN1EncodableVector subV = new ASN1EncodableVector(); v.add(objectId); subV.add(func); subV.add(scheme); v.add(new DERSequence(subV)); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java0000644000175000017500000000770611026315626023500 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import java.io.IOException; import java.math.BigInteger; import java.util.Enumeration; public class PrivateKeyInfo extends ASN1Encodable { private DERObject privKey; private AlgorithmIdentifier algId; private ASN1Set attributes; public static PrivateKeyInfo getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static PrivateKeyInfo getInstance( Object obj) { if (obj instanceof PrivateKeyInfo) { return (PrivateKeyInfo)obj; } else if (obj instanceof ASN1Sequence) { return new PrivateKeyInfo((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public PrivateKeyInfo( AlgorithmIdentifier algId, DERObject privateKey) { this(algId, privateKey, null); } public PrivateKeyInfo( AlgorithmIdentifier algId, DERObject privateKey, ASN1Set attributes) { this.privKey = privateKey; this.algId = algId; this.attributes = attributes; } public PrivateKeyInfo( ASN1Sequence seq) { Enumeration e = seq.getObjects(); BigInteger version = ((DERInteger)e.nextElement()).getValue(); if (version.intValue() != 0) { throw new IllegalArgumentException("wrong version for private key info"); } algId = new AlgorithmIdentifier((ASN1Sequence)e.nextElement()); try { ASN1InputStream aIn = new ASN1InputStream(((ASN1OctetString)e.nextElement()).getOctets()); privKey = aIn.readObject(); } catch (IOException ex) { throw new IllegalArgumentException("Error recoverying private key from sequence"); } if (e.hasMoreElements()) { attributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false); } } public AlgorithmIdentifier getAlgorithmId() { return algId; } public DERObject getPrivateKey() { return privKey; } public ASN1Set getAttributes() { return attributes; } /** * write out an RSA private key with it's asscociated information * as described in PKCS8. *
           *      PrivateKeyInfo ::= SEQUENCE {
           *                              version Version,
           *                              privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
           *                              privateKey PrivateKey,
           *                              attributes [0] IMPLICIT Attributes OPTIONAL 
           *                          }
           *      Version ::= INTEGER {v1(0)} (v1,...)
           *
           *      PrivateKey ::= OCTET STRING
           *
           *      Attributes ::= SET OF Attribute
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new DERInteger(0)); v.add(algId); v.add(new DEROctetString(privKey)); if (attributes != null) { v.add(new DERTaggedObject(false, 0, attributes)); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java0000644000175000017500000000176710061400652024153 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.BERSequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; public class AuthenticatedSafe implements DEREncodable { ContentInfo[] info; public AuthenticatedSafe( ASN1Sequence seq) { info = new ContentInfo[seq.size()]; for (int i = 0; i != info.length; i++) { info[i] = ContentInfo.getInstance(seq.getObjectAt(i)); } } public AuthenticatedSafe( ContentInfo[] info) { this.info = info; } public ContentInfo[] getContentInfo() { return info; } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); for (int i = 0; i != info.length; i++) { v.add(info[i]); } return new BERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/package.html0000644000175000017500000000020310061400652022170 0ustar adrianadrian Support classes useful for encoding and supporting the various RSA PKCS documents. azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/SafeBag.java0000644000175000017500000000342310061400652022051 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; public class SafeBag implements DEREncodable { DERObjectIdentifier bagId; DERObject bagValue; ASN1Set bagAttributes; public SafeBag( DERObjectIdentifier oid, DERObject obj) { this.bagId = oid; this.bagValue = obj; this.bagAttributes = null; } public SafeBag( DERObjectIdentifier oid, DERObject obj, ASN1Set bagAttributes) { this.bagId = oid; this.bagValue = obj; this.bagAttributes = bagAttributes; } public SafeBag( ASN1Sequence seq) { this.bagId = (DERObjectIdentifier)seq.getObjectAt(0); this.bagValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject(); if (seq.size() == 3) { this.bagAttributes = (ASN1Set)seq.getObjectAt(2); } } public DERObjectIdentifier getBagId() { return bagId; } public DERObject getBagValue() { return bagValue; } public ASN1Set getBagAttributes() { return bagAttributes; } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(bagId); v.add(new DERTaggedObject(0, bagValue)); if (bagAttributes != null) { v.add(bagAttributes); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/ContentInfo.java0000644000175000017500000000414710061400652023013 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.BERSequence; import org.bouncycastle.asn1.BERTaggedObject; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERTaggedObject; public class ContentInfo implements DEREncodable, PKCSObjectIdentifiers { private DERObjectIdentifier contentType; private DEREncodable content; public static ContentInfo getInstance( Object obj) { if (obj instanceof ContentInfo) { return (ContentInfo)obj; } else if (obj instanceof ASN1Sequence) { return new ContentInfo((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public ContentInfo( ASN1Sequence seq) { Enumeration e = seq.getObjects(); contentType = (DERObjectIdentifier)e.nextElement(); if (e.hasMoreElements()) { content = ((DERTaggedObject)e.nextElement()).getObject(); } } public ContentInfo( DERObjectIdentifier contentType, DEREncodable content) { this.contentType = contentType; this.content = content; } public DERObjectIdentifier getContentType() { return contentType; } public DEREncodable getContent() { return content; } /** * Produce an object suitable for an ASN1OutputStream. *
           * ContentInfo ::= SEQUENCE {
           *          contentType ContentType,
           *          content
           *          [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
           * 
      */ public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(contentType); if (content != null) { v.add(new BERTaggedObject(0, content)); } return new BERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/IssuerAndSerialNumber.java0000644000175000017500000000350210061400652024765 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.math.BigInteger; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.X509Name; public class IssuerAndSerialNumber implements DEREncodable { X509Name name; DERInteger certSerialNumber; public static IssuerAndSerialNumber getInstance( Object obj) { if (obj instanceof IssuerAndSerialNumber) { return (IssuerAndSerialNumber)obj; } else if (obj instanceof ASN1Sequence) { return new IssuerAndSerialNumber((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public IssuerAndSerialNumber( ASN1Sequence seq) { this.name = X509Name.getInstance(seq.getObjectAt(0)); this.certSerialNumber = (DERInteger)seq.getObjectAt(1); } public IssuerAndSerialNumber( X509Name name, BigInteger certSerialNumber) { this.name = name; this.certSerialNumber = new DERInteger(certSerialNumber); } public IssuerAndSerialNumber( X509Name name, DERInteger certSerialNumber) { this.name = name; this.certSerialNumber = certSerialNumber; } public X509Name getName() { return name; } public DERInteger getCertificateSerialNumber() { return certSerialNumber; } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(name); v.add(certSerialNumber); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java0000644000175000017500000001677610061400652024655 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import org.bouncycastle.asn1.DERObjectIdentifier; public interface PKCSObjectIdentifiers { // // pkcs-1 OBJECT IDENTIFIER ::= { // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } // static final String pkcs_1 = "1.2.840.113549.1.1"; static final DERObjectIdentifier rsaEncryption = new DERObjectIdentifier(pkcs_1 + ".1"); static final DERObjectIdentifier md2WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".2"); static final DERObjectIdentifier md4WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".3"); static final DERObjectIdentifier md5WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".4"); static final DERObjectIdentifier sha1WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".5"); static final DERObjectIdentifier srsaOAEPEncryptionSET = new DERObjectIdentifier(pkcs_1 + ".6"); static final DERObjectIdentifier sha256WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".11"); static final DERObjectIdentifier sha384WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".12"); static final DERObjectIdentifier sha512WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".13"); // // pkcs-3 OBJECT IDENTIFIER ::= { // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 } // static final String pkcs_3 = "1.2.840.113549.1.3"; static final DERObjectIdentifier dhKeyAgreement = new DERObjectIdentifier(pkcs_3 + ".1"); // // pkcs-5 OBJECT IDENTIFIER ::= { // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } // static final String pkcs_5 = "1.2.840.113549.1.5"; static final DERObjectIdentifier id_PBES2 = new DERObjectIdentifier(pkcs_5 + ".13"); static final DERObjectIdentifier id_PBKDF2 = new DERObjectIdentifier(pkcs_5 + ".12"); // // encryptionAlgorithm OBJECT IDENTIFIER ::= { // iso(1) member-body(2) us(840) rsadsi(113549) 3 } // static final String encryptionAlgorithm = "1.2.840.113549.3"; static final DERObjectIdentifier des_EDE3_CBC = new DERObjectIdentifier(encryptionAlgorithm + ".7"); static final DERObjectIdentifier RC2_CBC = new DERObjectIdentifier(encryptionAlgorithm + ".2"); // // object identifiers for digests // // // md2 OBJECT IDENTIFIER ::= // {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 2} // static final DERObjectIdentifier md2 = new DERObjectIdentifier("1.2.840.113549.2.2"); // // md5 OBJECT IDENTIFIER ::= // {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5} // static final DERObjectIdentifier md5 = new DERObjectIdentifier("1.2.840.113549.2.5"); // // pkcs-7 OBJECT IDENTIFIER ::= { // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } // static final String pkcs_7 = "1.2.840.113549.1.7"; static final DERObjectIdentifier data = new DERObjectIdentifier(pkcs_7 + ".1"); static final DERObjectIdentifier signedData = new DERObjectIdentifier(pkcs_7 + ".2"); static final DERObjectIdentifier envelopedData = new DERObjectIdentifier(pkcs_7 + ".3"); static final DERObjectIdentifier signedAndEnvelopedData = new DERObjectIdentifier(pkcs_7 + ".4"); static final DERObjectIdentifier digestedData = new DERObjectIdentifier(pkcs_7 + ".5"); static final DERObjectIdentifier encryptedData = new DERObjectIdentifier(pkcs_7 + ".6"); // // pkcs-9 OBJECT IDENTIFIER ::= { // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } // static final String pkcs_9 = "1.2.840.113549.1.9"; static final DERObjectIdentifier pkcs_9_at_emailAddress = new DERObjectIdentifier(pkcs_9 + ".1"); static final DERObjectIdentifier pkcs_9_at_unstructuredName = new DERObjectIdentifier(pkcs_9 + ".2"); static final DERObjectIdentifier pkcs_9_at_contentType = new DERObjectIdentifier(pkcs_9 + ".3"); static final DERObjectIdentifier pkcs_9_at_messageDigest = new DERObjectIdentifier(pkcs_9 + ".4"); static final DERObjectIdentifier pkcs_9_at_signingTime = new DERObjectIdentifier(pkcs_9 + ".5"); static final DERObjectIdentifier pkcs_9_at_counterSignature = new DERObjectIdentifier(pkcs_9 + ".6"); static final DERObjectIdentifier pkcs_9_at_challengePassword = new DERObjectIdentifier(pkcs_9 + ".7"); static final DERObjectIdentifier pkcs_9_at_unstructuredAddress = new DERObjectIdentifier(pkcs_9 + ".8"); static final DERObjectIdentifier pkcs_9_at_extendedCertificateAttributes = new DERObjectIdentifier(pkcs_9 + ".9"); static final DERObjectIdentifier pkcs_9_at_signingDescription = new DERObjectIdentifier(pkcs_9 + ".13"); static final DERObjectIdentifier pkcs_9_at_extensionRequest = new DERObjectIdentifier(pkcs_9 + ".14"); static final DERObjectIdentifier pkcs_9_at_smimeCapabilities = new DERObjectIdentifier(pkcs_9 + ".15"); static final DERObjectIdentifier pkcs_9_at_friendlyName = new DERObjectIdentifier(pkcs_9 + ".20"); static final DERObjectIdentifier pkcs_9_at_localKeyId = new DERObjectIdentifier(pkcs_9 + ".21"); static final DERObjectIdentifier x509certType = new DERObjectIdentifier(pkcs_9 + ".22.1"); static final DERObjectIdentifier id_ct_compressedData = new DERObjectIdentifier(pkcs_9 + ".16.1.9"); static final DERObjectIdentifier id_alg_PWRI_KEK = new DERObjectIdentifier(pkcs_9 + ".16.3.9"); // // SMIME capability sub oids. // static final DERObjectIdentifier preferSignedData = new DERObjectIdentifier(pkcs_9 + ".15.1"); static final DERObjectIdentifier canNotDecryptAny = new DERObjectIdentifier(pkcs_9 + ".15.2"); static final DERObjectIdentifier sMIMECapabilitiesVersions = new DERObjectIdentifier(pkcs_9 + ".15.3"); // // other SMIME attributes // // // id-aa OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840) // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)} // static String id_aa = "1.2.840.113549.1.9.16.2"; /* * id-aa-encrypKeyPref OBJECT IDENTIFIER ::= {id-aa 11} * */ static DERObjectIdentifier id_aa_encrypKeyPref = new DERObjectIdentifier(id_aa + ".11"); // // pkcs-12 OBJECT IDENTIFIER ::= { // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } // static final String pkcs_12 = "1.2.840.113549.1.12"; static final String bagtypes = pkcs_12 + ".10.1"; static final DERObjectIdentifier keyBag = new DERObjectIdentifier(bagtypes + ".1"); static final DERObjectIdentifier pkcs8ShroudedKeyBag = new DERObjectIdentifier(bagtypes + ".2"); static final DERObjectIdentifier certBag = new DERObjectIdentifier(bagtypes + ".3"); static final DERObjectIdentifier crlBag = new DERObjectIdentifier(bagtypes + ".4"); static final DERObjectIdentifier secretBag = new DERObjectIdentifier(bagtypes + ".5"); static final DERObjectIdentifier safeContentsBag = new DERObjectIdentifier(bagtypes + ".6"); } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java0000644000175000017500000001255211026315624025144 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.math.BigInteger; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; public class RSAPrivateKeyStructure extends ASN1Encodable { private int version; private BigInteger modulus; private BigInteger publicExponent; private BigInteger privateExponent; private BigInteger prime1; private BigInteger prime2; private BigInteger exponent1; private BigInteger exponent2; private BigInteger coefficient; private ASN1Sequence otherPrimeInfos = null; public static RSAPrivateKeyStructure getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static RSAPrivateKeyStructure getInstance( Object obj) { if (obj instanceof RSAPrivateKeyStructure) { return (RSAPrivateKeyStructure)obj; } else if (obj instanceof ASN1Sequence) { return new RSAPrivateKeyStructure((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public RSAPrivateKeyStructure( BigInteger modulus, BigInteger publicExponent, BigInteger privateExponent, BigInteger prime1, BigInteger prime2, BigInteger exponent1, BigInteger exponent2, BigInteger coefficient) { this.version = 0; this.modulus = modulus; this.publicExponent = publicExponent; this.privateExponent = privateExponent; this.prime1 = prime1; this.prime2 = prime2; this.exponent1 = exponent1; this.exponent2 = exponent2; this.coefficient = coefficient; } public RSAPrivateKeyStructure( ASN1Sequence seq) { Enumeration e = seq.getObjects(); BigInteger v = ((DERInteger)e.nextElement()).getValue(); if (v.intValue() != 0 && v.intValue() != 1) { throw new IllegalArgumentException("wrong version for RSA private key"); } version = v.intValue(); modulus = ((DERInteger)e.nextElement()).getValue(); publicExponent = ((DERInteger)e.nextElement()).getValue(); privateExponent = ((DERInteger)e.nextElement()).getValue(); prime1 = ((DERInteger)e.nextElement()).getValue(); prime2 = ((DERInteger)e.nextElement()).getValue(); exponent1 = ((DERInteger)e.nextElement()).getValue(); exponent2 = ((DERInteger)e.nextElement()).getValue(); coefficient = ((DERInteger)e.nextElement()).getValue(); if (e.hasMoreElements()) { otherPrimeInfos = (ASN1Sequence)e.nextElement(); } } public int getVersion() { return version; } public BigInteger getModulus() { return modulus; } public BigInteger getPublicExponent() { return publicExponent; } public BigInteger getPrivateExponent() { return privateExponent; } public BigInteger getPrime1() { return prime1; } public BigInteger getPrime2() { return prime2; } public BigInteger getExponent1() { return exponent1; } public BigInteger getExponent2() { return exponent2; } public BigInteger getCoefficient() { return coefficient; } /** * This outputs the key in PKCS1v2 format. *
           *      RSAPrivateKey ::= SEQUENCE {
           *                          version Version,
           *                          modulus INTEGER, -- n
           *                          publicExponent INTEGER, -- e
           *                          privateExponent INTEGER, -- d
           *                          prime1 INTEGER, -- p
           *                          prime2 INTEGER, -- q
           *                          exponent1 INTEGER, -- d mod (p-1)
           *                          exponent2 INTEGER, -- d mod (q-1)
           *                          coefficient INTEGER, -- (inverse of q) mod p
           *                          otherPrimeInfos OtherPrimeInfos OPTIONAL
           *                      }
           *
           *      Version ::= INTEGER { two-prime(0), multi(1) }
           *        (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
           * 
      *

      * This routine is written to output PKCS1 version 2.1, private keys. */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new DERInteger(version)); // version v.add(new DERInteger(getModulus())); v.add(new DERInteger(getPublicExponent())); v.add(new DERInteger(getPrivateExponent())); v.add(new DERInteger(getPrime1())); v.add(new DERInteger(getPrime2())); v.add(new DERInteger(getExponent1())); v.add(new DERInteger(getExponent2())); v.add(new DERInteger(getCoefficient())); if (otherPrimeInfos != null) { v.add(otherPrimeInfos); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/Pfx.java0000644000175000017500000000306610061400652021321 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.math.BigInteger; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.BERSequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; /** * the infamous Pfx from PKCS12 */ public class Pfx implements DEREncodable, PKCSObjectIdentifiers { private ContentInfo contentInfo; private MacData macData = null; public Pfx( ASN1Sequence seq) { BigInteger version = ((DERInteger)seq.getObjectAt(0)).getValue(); if (version.intValue() != 3) { throw new IllegalArgumentException("wrong version for PFX PDU"); } contentInfo = ContentInfo.getInstance(seq.getObjectAt(1)); if (seq.size() == 3) { macData = MacData.getInstance(seq.getObjectAt(2)); } } public Pfx( ContentInfo contentInfo, MacData macData) { this.contentInfo = contentInfo; this.macData = macData; } public ContentInfo getAuthSafe() { return contentInfo; } public MacData getMacData() { return macData; } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new DERInteger(3)); v.add(contentInfo); if (macData != null) { v.add(macData); } return new BERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/MacData.java0000644000175000017500000000413010061400652022047 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.math.BigInteger; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.DigestInfo; public class MacData implements DEREncodable { DigestInfo digInfo; byte[] salt; BigInteger iterationCount; public static MacData getInstance( Object obj) { if (obj instanceof MacData) { return (MacData)obj; } else if (obj instanceof ASN1Sequence) { return new MacData((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public MacData( ASN1Sequence seq) { this.digInfo = DigestInfo.getInstance(seq.getObjectAt(0)); this.salt = ((ASN1OctetString)seq.getObjectAt(1)).getOctets(); if (seq.size() == 3) { this.iterationCount = ((DERInteger)seq.getObjectAt(2)).getValue(); } else { this.iterationCount = BigInteger.valueOf(1); } } public MacData( DigestInfo digInfo, byte[] salt, int iterationCount) { this.digInfo = digInfo; this.salt = salt; this.iterationCount = BigInteger.valueOf(iterationCount); } public DigestInfo getMac() { return digInfo; } public byte[] getSalt() { return salt; } public BigInteger getIterationCount() { return iterationCount; } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(digInfo); v.add(new DEROctetString(salt)); v.add(new DERInteger(iterationCount)); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/CertificationRequest.java0000644000175000017500000000371310061400652024717 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; /** * PKCS10 Certfication request object. *

       * CertificationRequest ::= SEQUENCE {
       *   certificationRequestInfo  CertificationRequestInfo,
       *   signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
       *   signature                 BIT STRING
       * }
       * 
      */ public class CertificationRequest implements DEREncodable { protected CertificationRequestInfo reqInfo = null; protected AlgorithmIdentifier sigAlgId = null; protected DERBitString sigBits = null; protected CertificationRequest() { } public CertificationRequest( CertificationRequestInfo requestInfo, AlgorithmIdentifier algorithm, DERBitString signature) { this.reqInfo = requestInfo; this.sigAlgId = algorithm; this.sigBits = signature; } public CertificationRequest( ASN1Sequence seq) { reqInfo = CertificationRequestInfo.getInstance(seq.getObjectAt(0)); sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1)); sigBits = (DERBitString)seq.getObjectAt(2); } public CertificationRequestInfo getCertificationRequestInfo() { return reqInfo; } public AlgorithmIdentifier getSignatureAlgorithm() { return sigAlgId; } public DERBitString getSignature() { return sigBits; } public DERObject getDERObject() { // Construct the CertificateRequest ASN1EncodableVector v = new ASN1EncodableVector(); v.add(reqInfo); v.add(sigAlgId); v.add(sigBits); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/CertBag.java0000644000175000017500000000233110061400652022065 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; public class CertBag implements DEREncodable { ASN1Sequence seq; DERObjectIdentifier certId; DERObject certValue; public CertBag( ASN1Sequence seq) { this.seq = seq; this.certId = (DERObjectIdentifier)seq.getObjectAt(0); this.certValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject(); } public CertBag( DERObjectIdentifier certId, DERObject certValue) { this.certId = certId; this.certValue = certValue; } public DERObjectIdentifier getCertId() { return certId; } public DERObject getCertValue() { return certValue; } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(certId); v.add(new DERTaggedObject(0, certValue)); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/PBES2Parameters.java0000644000175000017500000000235410061400652023422 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; public class PBES2Parameters implements PKCSObjectIdentifiers, DEREncodable { private KeyDerivationFunc func; private EncryptionScheme scheme; public PBES2Parameters( ASN1Sequence obj) { Enumeration e = obj.getObjects(); ASN1Sequence funcSeq = (ASN1Sequence)e.nextElement(); if (funcSeq.getObjectAt(0).equals(id_PBKDF2)) { func = new PBKDF2Params(funcSeq); } else { func = new KeyDerivationFunc(funcSeq); } scheme = new EncryptionScheme((ASN1Sequence)e.nextElement()); } public KeyDerivationFunc getKeyDerivationFunc() { return func; } public EncryptionScheme getEncryptionScheme() { return scheme; } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(func); v.add(scheme); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/SignerInfo.java0000644000175000017500000001136010061400652022623 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.util.Enumeration; import org.bouncycastle.asn1.*; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; /** * a PKCS#7 signer info object. */ public class SignerInfo implements DEREncodable { private DERInteger version; private IssuerAndSerialNumber issuerAndSerialNumber; private AlgorithmIdentifier digAlgorithm; private ASN1Set authenticatedAttributes; private AlgorithmIdentifier digEncryptionAlgorithm; private ASN1OctetString encryptedDigest; private ASN1Set unauthenticatedAttributes; public static SignerInfo getInstance( Object o) { if (o instanceof SignerInfo) { return (SignerInfo)o; } else if (o instanceof ASN1Sequence) { return new SignerInfo((ASN1Sequence)o); } throw new IllegalArgumentException("unknown object in factory"); } public SignerInfo( DERInteger version, IssuerAndSerialNumber issuerAndSerialNumber, AlgorithmIdentifier digAlgorithm, ASN1Set authenticatedAttributes, AlgorithmIdentifier digEncryptionAlgorithm, ASN1OctetString encryptedDigest, ASN1Set unauthenticatedAttributes) { this.version = version; this.issuerAndSerialNumber = issuerAndSerialNumber; this.digAlgorithm = digAlgorithm; this.authenticatedAttributes = authenticatedAttributes; this.digEncryptionAlgorithm = digEncryptionAlgorithm; this.encryptedDigest = encryptedDigest; this.unauthenticatedAttributes = unauthenticatedAttributes; } public SignerInfo( ASN1Sequence seq) { Enumeration e = seq.getObjects(); version = (DERInteger)e.nextElement(); issuerAndSerialNumber = IssuerAndSerialNumber.getInstance(e.nextElement()); digAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement()); Object obj = e.nextElement(); if (obj instanceof ASN1TaggedObject) { authenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)obj, false); digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement()); } else { authenticatedAttributes = null; digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(obj); } encryptedDigest = DEROctetString.getInstance(e.nextElement()); if (e.hasMoreElements()) { unauthenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false); } else { unauthenticatedAttributes = null; } } public DERInteger getVersion() { return version; } public IssuerAndSerialNumber getIssuerAndSerialNumber() { return issuerAndSerialNumber; } public ASN1Set getAuthenticatedAttributes() { return authenticatedAttributes; } public AlgorithmIdentifier getDigestAlgorithm() { return digAlgorithm; } public ASN1OctetString getEncryptedDigest() { return encryptedDigest; } public AlgorithmIdentifier getDigestEncryptionAlgorithm() { return digEncryptionAlgorithm; } public ASN1Set getUnauthenticatedAttributes() { return unauthenticatedAttributes; } /** * Produce an object suitable for an ASN1OutputStream. *
           *  SignerInfo ::= SEQUENCE {
           *      version Version,
           *      issuerAndSerialNumber IssuerAndSerialNumber,
           *      digestAlgorithm DigestAlgorithmIdentifier,
           *      authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
           *      digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
           *      encryptedDigest EncryptedDigest,
           *      unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
           *  }
           *
           *  EncryptedDigest ::= OCTET STRING
           *
           *  DigestAlgorithmIdentifier ::= AlgorithmIdentifier
           *
           *  DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
           * 
      */ public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(version); v.add(issuerAndSerialNumber); v.add(digAlgorithm); if (authenticatedAttributes != null) { v.add(new DERTaggedObject(false, 0, authenticatedAttributes)); } v.add(digEncryptionAlgorithm); v.add(encryptedDigest); if (unauthenticatedAttributes != null) { v.add(new DERTaggedObject(false, 1, unauthenticatedAttributes)); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/EncryptionScheme.java0000644000175000017500000000147610061400652024046 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; public class EncryptionScheme extends AlgorithmIdentifier { DERObject objectId; DERObject obj; EncryptionScheme( ASN1Sequence seq) { super(seq); objectId = (DERObject)seq.getObjectAt(0); obj = (DERObject)seq.getObjectAt(1); } public DERObject getObject() { return obj; } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(objectId); v.add(obj); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/DHParameter.java0000644000175000017500000000321110061400652022710 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.math.BigInteger; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; public class DHParameter implements DEREncodable { DERInteger p, g, l; public DHParameter( BigInteger p, BigInteger g, int l) { this.p = new DERInteger(p); this.g = new DERInteger(g); if (l != 0) { this.l = new DERInteger(l); } else { this.l = null; } } public DHParameter( ASN1Sequence seq) { Enumeration e = seq.getObjects(); p = (DERInteger)e.nextElement(); g = (DERInteger)e.nextElement(); if (e.hasMoreElements()) { l = (DERInteger)e.nextElement(); } else { l = null; } } public BigInteger getP() { return p.getPositiveValue(); } public BigInteger getG() { return g.getPositiveValue(); } public BigInteger getL() { if (l == null) { return null; } return l.getPositiveValue(); } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(p); v.add(g); if (this.getL() != null) { v.add(l); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/EncryptedData.java0000644000175000017500000000475410542072476023335 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import org.bouncycastle.asn1.*; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; /** * The EncryptedData object. *
       *      EncryptedData ::= SEQUENCE {
       *           version Version,
       *           encryptedContentInfo EncryptedContentInfo
       *      }
       *
       *
       *      EncryptedContentInfo ::= SEQUENCE {
       *          contentType ContentType,
       *          contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
       *          encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
       *    }
       *
       *    EncryptedContent ::= OCTET STRING
       * 
      */ public class EncryptedData implements DEREncodable { ASN1Sequence data; DERObjectIdentifier bagId; DERObject bagValue; public static EncryptedData getInstance( Object obj) { if (obj instanceof EncryptedData) { return (EncryptedData)obj; } else if (obj instanceof ASN1Sequence) { return new EncryptedData((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public EncryptedData( ASN1Sequence seq) { int version = ((DERInteger)seq.getObjectAt(0)).getValue().intValue(); if (version != 0) { throw new IllegalArgumentException("sequence not version 0"); } this.data = (ASN1Sequence)seq.getObjectAt(1); } public EncryptedData( DERObjectIdentifier contentType, AlgorithmIdentifier encryptionAlgorithm, DEREncodable content) { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(contentType); v.add(encryptionAlgorithm.getDERObject()); v.add(new BERTaggedObject(false, 0, content)); data = new BERSequence(v); } public DERObjectIdentifier getContentType() { return (DERObjectIdentifier)data.getObjectAt(0); } public AlgorithmIdentifier getEncryptionAlgorithm() { return AlgorithmIdentifier.getInstance(data.getObjectAt(1)); } public ASN1OctetString getContent() { if (data.size() == 3) { DERTaggedObject o = (DERTaggedObject)data.getObjectAt(2); return ASN1OctetString.getInstance(o.getObject()); } return null; } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new DERInteger(0)); v.add(data); return new BERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java0000644000175000017500000000365610061400652023330 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.math.BigInteger; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; public class RC2CBCParameter implements DEREncodable { DERInteger version; ASN1OctetString iv; public static RC2CBCParameter getInstance( Object o) { if (o instanceof ASN1Sequence) { return new RC2CBCParameter((ASN1Sequence)o); } throw new IllegalArgumentException("unknown object in RC2CBCParameter factory"); } public RC2CBCParameter( byte[] iv) { this.version = null; this.iv = new DEROctetString(iv); } public RC2CBCParameter( int parameterVersion, byte[] iv) { this.version = new DERInteger(parameterVersion); this.iv = new DEROctetString(iv); } public RC2CBCParameter( ASN1Sequence seq) { if (seq.size() == 1) { version = null; iv = (ASN1OctetString)seq.getObjectAt(0); } else { version = (DERInteger)seq.getObjectAt(0); iv = (ASN1OctetString)seq.getObjectAt(1); } } public BigInteger getRC2ParameterVersion() { if (version == null) { return null; } return version.getValue(); } public byte[] getIV() { return iv.getOctets(); } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); if (version != null) { v.add(version); } v.add(iv); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java0000644000175000017500000000712010061400652025527 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.X509Name; /** * PKCS10 CertificationRequestInfo object. *
       *  CertificationRequestInfo ::= SEQUENCE {
       *   version             INTEGER { v1(0) } (v1,...),
       *   subject             Name,
       *   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
       *   attributes          [0] Attributes{{ CRIAttributes }}
       *  }
       *
       *  Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
       *
       *  Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
       *    type    ATTRIBUTE.&id({IOSet}),
       *    values  SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
       *  }
       * 
      */ public class CertificationRequestInfo implements DEREncodable { DERInteger version = new DERInteger(0); X509Name subject; SubjectPublicKeyInfo subjectPKInfo; ASN1Set attributes = null; public static CertificationRequestInfo getInstance( Object obj) { if (obj instanceof CertificationRequestInfo) { return (CertificationRequestInfo)obj; } else if (obj instanceof ASN1Sequence) { return new CertificationRequestInfo((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public CertificationRequestInfo( X509Name subject, SubjectPublicKeyInfo pkInfo, ASN1Set attributes) { this.subject = subject; this.subjectPKInfo = pkInfo; this.attributes = attributes; if ((subject == null) || (version == null) || (subjectPKInfo == null)) { throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator."); } } public CertificationRequestInfo( ASN1Sequence seq) { version = (DERInteger)seq.getObjectAt(0); subject = X509Name.getInstance(seq.getObjectAt(1)); subjectPKInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(2)); // // some CertificationRequestInfo objects seem to treat this field // as optional. // if (seq.size() > 3) { DERTaggedObject tagobj = (DERTaggedObject)seq.getObjectAt(3); attributes = ASN1Set.getInstance(tagobj, false); } if ((subject == null) || (version == null) || (subjectPKInfo == null)) { throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator."); } } public DERInteger getVersion() { return version; } public X509Name getSubject() { return subject; } public SubjectPublicKeyInfo getSubjectPublicKeyInfo() { return subjectPKInfo; } public ASN1Set getAttributes() { return attributes; } public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(version); v.add(subject); v.add(subjectPKInfo); if (attributes != null) { v.add(new DERTaggedObject(false, 0, attributes)); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java0000644000175000017500000000043510061400652024152 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; public class KeyDerivationFunc extends AlgorithmIdentifier { KeyDerivationFunc( ASN1Sequence seq) { super(seq); } } azureus-4.3.0.6/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java0000644000175000017500000000346310061400652025342 0ustar adrianadrianpackage org.bouncycastle.asn1.pkcs; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; public class EncryptedPrivateKeyInfo implements PKCSObjectIdentifiers, DEREncodable { private AlgorithmIdentifier algId; private ASN1OctetString data; public EncryptedPrivateKeyInfo( ASN1Sequence seq) { Enumeration e = seq.getObjects(); algId = new AlgorithmIdentifier((ASN1Sequence)e.nextElement()); data = (ASN1OctetString)e.nextElement(); } public EncryptedPrivateKeyInfo( AlgorithmIdentifier algId, byte[] encoding) { this.algId = algId; this.data = new DEROctetString(encoding); } public AlgorithmIdentifier getEncryptionAlgorithm() { return algId; } public byte[] getEncryptedData() { return data.getOctets(); } /** * Produce an object suitable for an ASN1OutputStream. *
           * EncryptedPrivateKeyInfo ::= SEQUENCE {
           *      encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
           *      encryptedData EncryptedData
           * }
           *
           * EncryptedData ::= OCTET STRING
           *
           * KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
           *          ... -- For local profiles
           * }
           * 
      */ public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(algId); v.add(data); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1OctetString.java0000644000175000017500000000724411026315604022522 0ustar adrianadrianpackage org.bouncycastle.asn1; import org.bouncycastle.util.encoders.Hex; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.Vector; public abstract class ASN1OctetString extends ASN1Object implements ASN1OctetStringParser { byte[] string; /** * return an Octet String from a tagged object. * * @param obj the tagged object holding the object we want. * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static ASN1OctetString getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } /** * return an Octet String from the given object. * * @param obj the object we want converted. * @exception IllegalArgumentException if the object cannot be converted. */ public static ASN1OctetString getInstance( Object obj) { if (obj == null || obj instanceof ASN1OctetString) { return (ASN1OctetString)obj; } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } if (obj instanceof ASN1Sequence) { Vector v = new Vector(); Enumeration e = ((ASN1Sequence)obj).getObjects(); while (e.hasMoreElements()) { v.addElement(e.nextElement()); } return new BERConstructedOctetString(v); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * @param string the octets making up the octet string. */ public ASN1OctetString( byte[] string) { this.string = string; } public ASN1OctetString( DEREncodable obj) { try { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); dOut.writeObject(obj); dOut.close(); this.string = bOut.toByteArray(); } catch (IOException e) { throw new IllegalArgumentException("Error processing object : " + e.toString()); } } public InputStream getOctetStream() { return new ByteArrayInputStream(string); } public ASN1OctetStringParser parser() { return this; } public byte[] getOctets() { return string; } public int hashCode() { byte[] b = this.getOctets(); int value = 0; for (int i = 0; i != b.length; i++) { value ^= (b[i] & 0xff) << (i % 4); } return value; } boolean asn1Equals( DERObject o) { if (!(o instanceof ASN1OctetString)) { return false; } ASN1OctetString other = (ASN1OctetString)o; byte[] b1 = other.string; byte[] b2 = this.string; if (b1.length != b2.length) { return false; } for (int i = 0; i != b1.length; i++) { if (b1[i] != b2[i]) { return false; } } return true; } abstract void encode(DEROutputStream out) throws IOException; public String toString() { return "#"+new String(Hex.encode(string)); } } azureus-4.3.0.6/org/bouncycastle/asn1/DERUTCTime.java0000644000175000017500000001440711026315612021435 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.SimpleTimeZone; /** * UTC time object. */ public class DERUTCTime extends ASN1Object { String time; /** * return an UTC Time from the passed in object. * * @exception IllegalArgumentException if the object cannot be converted. */ public static DERUTCTime getInstance( Object obj) { if (obj == null || obj instanceof DERUTCTime) { return (DERUTCTime)obj; } if (obj instanceof ASN1OctetString) { return new DERUTCTime(((ASN1OctetString)obj).getOctets()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return an UTC Time from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERUTCTime getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } /** * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were * never encoded. When you're creating one of these objects from scratch, that's * what you want to use, otherwise we'll try to deal with whatever gets read from * the input stream... (this is why the input format is different from the getTime() * method output). *

      * * @param time the time string. */ public DERUTCTime( String time) { this.time = time; try { this.getDate(); } catch (ParseException e) { throw new IllegalArgumentException("invalid date string: " + e.getMessage()); } } /** * base constructer from a java.util.date object */ public DERUTCTime( Date time) { SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'"); dateF.setTimeZone(new SimpleTimeZone(0,"Z")); this.time = dateF.format(time); } DERUTCTime( byte[] bytes) { // // explicitly convert to characters // char[] dateC = new char[bytes.length]; for (int i = 0; i != dateC.length; i++) { dateC[i] = (char)(bytes[i] & 0xff); } this.time = new String(dateC); } /** * return the time as a date based on whatever a 2 digit year will return. For * standardised processing use getAdjustedDate(). * * @return the resulting date * @exception ParseException if the date string cannot be parsed. */ public Date getDate() throws ParseException { SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz"); return dateF.parse(getTime()); } /** * return the time as an adjusted date * in the range of 1950 - 2049. * * @return a date in the range of 1950 to 2049. * @exception ParseException if the date string cannot be parsed. */ public Date getAdjustedDate() throws ParseException { SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); dateF.setTimeZone(new SimpleTimeZone(0, "Z")); return dateF.parse(getAdjustedTime()); } /** * return the time - always in the form of * YYMMDDhhmmssGMT(+hh:mm|-hh:mm). *

      * Normally in a certificate we would expect "Z" rather than "GMT", * however adding the "GMT" means we can just use: *

           *     dateF = new SimpleDateFormat("yyMMddHHmmssz");
           * 
      * To read in the time and get a date which is compatible with our local * time zone. *

      * Note: In some cases, due to the local date processing, this * may lead to unexpected results. If you want to stick the normal * convention of 1950 to 2049 use the getAdjustedTime() method. */ public String getTime() { // // standardise the format. // if (time.indexOf('-') < 0 && time.indexOf('+') < 0) { if (time.length() == 11) { return time.substring(0, 10) + "00GMT+00:00"; } else { return time.substring(0, 12) + "GMT+00:00"; } } else { int index = time.indexOf('-'); if (index < 0) { index = time.indexOf('+'); } String d = time; if (index == time.length() - 3) { d += "00"; } if (index == 10) { return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15); } else { return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17); } } } /** * return a time string as an adjusted date with a 4 digit year. This goes * in the range of 1950 - 2049. */ public String getAdjustedTime() { String d = this.getTime(); if (d.charAt(0) < '5') { return "20" + d; } else { return "19" + d; } } private byte[] getOctets() { char[] cs = time.toCharArray(); byte[] bs = new byte[cs.length]; for (int i = 0; i != cs.length; i++) { bs[i] = (byte)cs[i]; } return bs; } void encode( DEROutputStream out) throws IOException { out.writeEncoded(UTC_TIME, this.getOctets()); } boolean asn1Equals( DERObject o) { if (!(o instanceof DERUTCTime)) { return false; } return time.equals(((DERUTCTime)o).time); } public int hashCode() { return time.hashCode(); } public String toString() { return time; } } azureus-4.3.0.6/org/bouncycastle/asn1/BEROctetStringParser.java0000644000175000017500000000175311026315602023602 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.InputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; public class BEROctetStringParser implements ASN1OctetStringParser { private ASN1ObjectParser _parser; protected BEROctetStringParser( ASN1ObjectParser parser) { _parser = parser; } public InputStream getOctetStream() { return new ConstructedOctetStream(_parser); } public DERObject getDERObject() { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); InputStream in = this.getOctetStream(); int ch; try { while ((ch = in.read()) >= 0) { bOut.write(ch); } } catch (IOException e) { throw new IllegalStateException("IOException converting stream to byte array: " + e.getMessage()); } return new BERConstructedOctetString(bOut.toByteArray()); } } azureus-4.3.0.6/org/bouncycastle/asn1/DERObjectIdentifier.java0000644000175000017500000001761311026315600023373 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.math.BigInteger; public class DERObjectIdentifier extends ASN1Object { String identifier; /** * return an OID from the passed in object * * @exception IllegalArgumentException if the object cannot be converted. */ public static DERObjectIdentifier getInstance( Object obj) { if (obj == null || obj instanceof DERObjectIdentifier) { return (DERObjectIdentifier)obj; } if (obj instanceof ASN1OctetString) { return new DERObjectIdentifier(((ASN1OctetString)obj).getOctets()); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return an Object Identifier from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERObjectIdentifier getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } DERObjectIdentifier( byte[] bytes) { StringBuffer objId = new StringBuffer(); long value = 0; BigInteger bigValue = null; boolean first = true; for (int i = 0; i != bytes.length; i++) { int b = bytes[i] & 0xff; if (value < 0x80000000000000L) { value = value * 128 + (b & 0x7f); if ((b & 0x80) == 0) // end of number reached { if (first) { switch ((int)value / 40) { case 0: objId.append('0'); break; case 1: objId.append('1'); value -= 40; break; default: objId.append('2'); value -= 80; } first = false; } objId.append('.'); objId.append(value); value = 0; } } else { if (bigValue == null) { bigValue = BigInteger.valueOf(value); } bigValue = bigValue.shiftLeft(7); bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f)); if ((b & 0x80) == 0) { objId.append('.'); objId.append(bigValue); bigValue = null; value = 0; } } } this.identifier = objId.toString(); } public DERObjectIdentifier( String identifier) { if (!isValidIdentifier(identifier)) { throw new IllegalArgumentException("string " + identifier + " not an OID"); } this.identifier = identifier; } public String getId() { return identifier; } private void writeField( OutputStream out, long fieldValue) throws IOException { if (fieldValue >= (1L << 7)) { if (fieldValue >= (1L << 14)) { if (fieldValue >= (1L << 21)) { if (fieldValue >= (1L << 28)) { if (fieldValue >= (1L << 35)) { if (fieldValue >= (1L << 42)) { if (fieldValue >= (1L << 49)) { if (fieldValue >= (1L << 56)) { out.write((int)(fieldValue >> 56) | 0x80); } out.write((int)(fieldValue >> 49) | 0x80); } out.write((int)(fieldValue >> 42) | 0x80); } out.write((int)(fieldValue >> 35) | 0x80); } out.write((int)(fieldValue >> 28) | 0x80); } out.write((int)(fieldValue >> 21) | 0x80); } out.write((int)(fieldValue >> 14) | 0x80); } out.write((int)(fieldValue >> 7) | 0x80); } out.write((int)fieldValue & 0x7f); } private void writeField( OutputStream out, BigInteger fieldValue) throws IOException { int byteCount = (fieldValue.bitLength()+6)/7; if (byteCount == 0) { out.write(0); } else { BigInteger tmpValue = fieldValue; byte[] tmp = new byte[byteCount]; for (int i = byteCount-1; i >= 0; i--) { tmp[i] = (byte) ((tmpValue.intValue() & 0x7f) | 0x80); tmpValue = tmpValue.shiftRight(7); } tmp[byteCount-1] &= 0x7f; out.write(tmp); } } void encode( DEROutputStream out) throws IOException { OIDTokenizer tok = new OIDTokenizer(identifier); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); writeField(bOut, Integer.parseInt(tok.nextToken()) * 40 + Integer.parseInt(tok.nextToken())); while (tok.hasMoreTokens()) { String token = tok.nextToken(); if (token.length() < 18) { writeField(bOut, Long.parseLong(token)); } else { writeField(bOut, new BigInteger(token)); } } dOut.close(); byte[] bytes = bOut.toByteArray(); out.writeEncoded(OBJECT_IDENTIFIER, bytes); } public int hashCode() { return identifier.hashCode(); } boolean asn1Equals( DERObject o) { if (!(o instanceof DERObjectIdentifier)) { return false; } return identifier.equals(((DERObjectIdentifier)o).identifier); } public String toString() { return getId(); } private static boolean isValidIdentifier( String identifier) { if (identifier.length() < 3 || identifier.charAt(1) != '.') { return false; } char first = identifier.charAt(0); if (first < '0' || first > '2') { return false; } boolean periodAllowed = false; for (int i = identifier.length() - 1; i >= 2; i--) { char ch = identifier.charAt(i); if ('0' <= ch && ch <= '9') { periodAllowed = true; continue; } if (ch == '.') { if (!periodAllowed) { return false; } periodAllowed = false; continue; } return false; } return periodAllowed; } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1TaggedObjectParser.java0000644000175000017500000000040311026315614023743 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; public interface ASN1TaggedObjectParser extends DEREncodable { public int getTagNo(); public DEREncodable getObjectParser(int tag, boolean isExplicit) throws IOException; } azureus-4.3.0.6/org/bouncycastle/asn1/DERIA5String.java0000644000175000017500000000742711026315564021742 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; /** * DER IA5String object - this is an ascii string. */ public class DERIA5String extends ASN1Object implements DERString { String string; /** * return a IA5 string from the passed in object * * @exception IllegalArgumentException if the object cannot be converted. */ public static DERIA5String getInstance( Object obj) { if (obj == null || obj instanceof DERIA5String) { return (DERIA5String)obj; } if (obj instanceof ASN1OctetString) { return new DERIA5String(((ASN1OctetString)obj).getOctets()); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return an IA5 String from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERIA5String getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } /** * basic constructor - with bytes. */ public DERIA5String( byte[] string) { char[] cs = new char[string.length]; for (int i = 0; i != cs.length; i++) { cs[i] = (char)(string[i] & 0xff); } this.string = new String(cs); } /** * basic constructor - without validation. */ public DERIA5String( String string) { this(string, false); } /** * Constructor with optional validation. * * @param string the base string to wrap. * @param validate whether or not to check the string. * @throws IllegalArgumentException if validate is true and the string * contains characters that should not be in an IA5String. */ public DERIA5String( String string, boolean validate) { if (validate && !isIA5String(string)) { throw new IllegalArgumentException("string contains illegal characters"); } this.string = string; } public String getString() { return string; } public String toString() { return string; } public byte[] getOctets() { char[] cs = string.toCharArray(); byte[] bs = new byte[cs.length]; for (int i = 0; i != cs.length; i++) { bs[i] = (byte)cs[i]; } return bs; } void encode( DEROutputStream out) throws IOException { out.writeEncoded(IA5_STRING, this.getOctets()); } public int hashCode() { return this.getString().hashCode(); } boolean asn1Equals( DERObject o) { if (!(o instanceof DERIA5String)) { return false; } DERIA5String s = (DERIA5String)o; return this.getString().equals(s.getString()); } /** * return true if the passed in String can be represented without * loss as an IA5String, false otherwise. * * @return true if in printable set, false otherwise. */ public static boolean isIA5String( String str) { for (int i = str.length() - 1; i >= 0; i--) { char ch = str.charAt(i); if (ch > 0x007f) { return false; } } return true; } } azureus-4.3.0.6/org/bouncycastle/asn1/OIDTokenizer.java0000644000175000017500000000163510061400650022130 0ustar adrianadrianpackage org.bouncycastle.asn1; /** * class for breaking up an OID into it's component tokens, ala * java.util.StringTokenizer. We need this class as some of the * lightweight Java environment don't support classes like * StringTokenizer. */ public class OIDTokenizer { private String oid; private int index; public OIDTokenizer( String oid) { this.oid = oid; this.index = 0; } public boolean hasMoreTokens() { return (index != -1); } public String nextToken() { if (index == -1) { return null; } String token; int end = oid.indexOf('.', index); if (end == -1) { token = oid.substring(index); index = -1; return token; } token = oid.substring(index, end); index = end + 1; return token; } } azureus-4.3.0.6/org/bouncycastle/asn1/DERT61String.java0000644000175000017500000000530211026315604021717 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; /** * DER T61String (also the teletex string) */ public class DERT61String extends ASN1Object implements DERString { String string; /** * return a T61 string from the passed in object. * * @exception IllegalArgumentException if the object cannot be converted. */ public static DERT61String getInstance( Object obj) { if (obj == null || obj instanceof DERT61String) { return (DERT61String)obj; } if (obj instanceof ASN1OctetString) { return new DERT61String(((ASN1OctetString)obj).getOctets()); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return an T61 String from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERT61String getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } /** * basic constructor - with bytes. */ public DERT61String( byte[] string) { char[] cs = new char[string.length]; for (int i = 0; i != cs.length; i++) { cs[i] = (char)(string[i] & 0xff); } this.string = new String(cs); } /** * basic constructor - with string. */ public DERT61String( String string) { this.string = string; } public String getString() { return string; } public String toString() { return string; } void encode( DEROutputStream out) throws IOException { out.writeEncoded(T61_STRING, this.getOctets()); } public byte[] getOctets() { char[] cs = string.toCharArray(); byte[] bs = new byte[cs.length]; for (int i = 0; i != cs.length; i++) { bs[i] = (byte)cs[i]; } return bs; } boolean asn1Equals( DERObject o) { if (!(o instanceof DERT61String)) { return false; } return this.getString().equals(((DERT61String)o).getString()); } public int hashCode() { return this.getString().hashCode(); } } azureus-4.3.0.6/org/bouncycastle/asn1/BEROutputStream.java0000644000175000017500000000133010061400650022617 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.io.OutputStream; public class BEROutputStream extends DEROutputStream { public BEROutputStream( OutputStream os) { super(os); } public void writeObject( Object obj) throws IOException { if (obj == null) { writeNull(); } else if (obj instanceof DERObject) { ((DERObject)obj).encode(this); } else if (obj instanceof DEREncodable) { ((DEREncodable)obj).getDERObject().encode(this); } else { throw new IOException("object not BEREncodable"); } } } azureus-4.3.0.6/org/bouncycastle/asn1/sec/0000755000175000017500000000000011310377632017537 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java0000644000175000017500000000501111026315672024613 0ustar adrianadrianpackage org.bouncycastle.asn1.sec; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import java.math.BigInteger; import java.util.Enumeration; /** * the elliptic curve private key object from SEC 1 */ public class ECPrivateKeyStructure extends ASN1Encodable { private ASN1Sequence seq; public ECPrivateKeyStructure( ASN1Sequence seq) { this.seq = seq; } public ECPrivateKeyStructure( BigInteger key) { byte[] bytes = key.toByteArray(); if (bytes[0] == 0) { byte[] tmp = new byte[bytes.length - 1]; System.arraycopy(bytes, 1, tmp, 0, tmp.length); bytes = tmp; } ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new DERInteger(1)); v.add(new DEROctetString(bytes)); seq = new DERSequence(v); } public BigInteger getKey() { ASN1OctetString octs = (ASN1OctetString)seq.getObjectAt(1); return new BigInteger(1, octs.getOctets()); } public DERBitString getPublicKey() { return (DERBitString)getObjectInTag(1); } public ASN1Object getParameters() { return getObjectInTag(0); } private ASN1Object getObjectInTag(int tagNo) { Enumeration e = seq.getObjects(); while (e.hasMoreElements()) { DEREncodable obj = (DEREncodable)e.nextElement(); if (obj instanceof ASN1TaggedObject) { ASN1TaggedObject tag = (ASN1TaggedObject)obj; if (tag.getTagNo() == tagNo) { return (ASN1Object)((DEREncodable)tag.getObject()).getDERObject(); } } } return null; } /** * ECPrivateKey ::= SEQUENCE { * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), * privateKey OCTET STRING, * parameters [0] Parameters OPTIONAL, * publicKey [1] BIT STRING OPTIONAL } */ public DERObject toASN1Object() { return seq; } } azureus-4.3.0.6/org/bouncycastle/asn1/sec/package.html0000644000175000017500000000015410061400660022006 0ustar adrianadrian Classes for support of the SEC standard for Elliptic Curve. azureus-4.3.0.6/org/bouncycastle/asn1/DERNumericString.java0000644000175000017500000001002211026315570022744 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; /** * DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }. */ public class DERNumericString extends ASN1Object implements DERString { String string; /** * return a Numeric string from the passed in object * * @exception IllegalArgumentException if the object cannot be converted. */ public static DERNumericString getInstance( Object obj) { if (obj == null || obj instanceof DERNumericString) { return (DERNumericString)obj; } if (obj instanceof ASN1OctetString) { return new DERNumericString(((ASN1OctetString)obj).getOctets()); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return an Numeric String from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERNumericString getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } /** * basic constructor - with bytes. */ public DERNumericString( byte[] string) { char[] cs = new char[string.length]; for (int i = 0; i != cs.length; i++) { cs[i] = (char)(string[i] & 0xff); } this.string = new String(cs); } /** * basic constructor - without validation.. */ public DERNumericString( String string) { this(string, false); } /** * Constructor with optional validation. * * @param string the base string to wrap. * @param validate whether or not to check the string. * @throws IllegalArgumentException if validate is true and the string * contains characters that should not be in a NumericString. */ public DERNumericString( String string, boolean validate) { if (validate && !isNumericString(string)) { throw new IllegalArgumentException("string contains illegal characters"); } this.string = string; } public String getString() { return string; } public String toString() { return string; } public byte[] getOctets() { char[] cs = string.toCharArray(); byte[] bs = new byte[cs.length]; for (int i = 0; i != cs.length; i++) { bs[i] = (byte)cs[i]; } return bs; } void encode( DEROutputStream out) throws IOException { out.writeEncoded(NUMERIC_STRING, this.getOctets()); } public int hashCode() { return this.getString().hashCode(); } boolean asn1Equals( DERObject o) { if (!(o instanceof DERNumericString)) { return false; } DERNumericString s = (DERNumericString)o; return this.getString().equals(s.getString()); } /** * Return true if the string can be represented as a NumericString ('0'..'9', ' ') * * @param str string to validate. * @return true if numeric, fale otherwise. */ public static boolean isNumericString( String str) { for (int i = str.length() - 1; i >= 0; i--) { char ch = str.charAt(i); if (ch > 0x007f) { return false; } if (('0' <= ch && ch <= '9') || ch == ' ') { continue; } return false; } return true; } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1OctetStringParser.java0000644000175000017500000000025211026315574023675 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.InputStream; public interface ASN1OctetStringParser extends DEREncodable { public InputStream getOctetStream(); } azureus-4.3.0.6/org/bouncycastle/asn1/DERBitString.java0000644000175000017500000001515211026315614022070 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; public class DERBitString extends ASN1Object implements DERString { private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; protected byte[] data; protected int padBits; /** * return the correct number of pad bits for a bit string defined in * a 32 bit constant */ static protected int getPadBits( int bitString) { int val = 0; for (int i = 3; i >= 0; i--) { // // this may look a little odd, but if it isn't done like this pre jdk1.2 // JVM's break! // if (i != 0) { if ((bitString >> (i * 8)) != 0) { val = (bitString >> (i * 8)) & 0xFF; break; } } else { if (bitString != 0) { val = bitString & 0xFF; break; } } } if (val == 0) { return 7; } int bits = 1; while (((val <<= 1) & 0xFF) != 0) { bits++; } return 8 - bits; } /** * return the correct number of bytes for a bit string defined in * a 32 bit constant */ static protected byte[] getBytes(int bitString) { int bytes = 4; for (int i = 3; i >= 1; i--) { if ((bitString & (0xFF << (i * 8))) != 0) { break; } bytes--; } byte[] result = new byte[bytes]; for (int i = 0; i < bytes; i++) { result[i] = (byte) ((bitString >> (i * 8)) & 0xFF); } return result; } /** * return a Bit String from the passed in object * * @exception IllegalArgumentException if the object cannot be converted. */ public static DERBitString getInstance( Object obj) { if (obj == null || obj instanceof DERBitString) { return (DERBitString)obj; } if (obj instanceof ASN1OctetString) { byte[] bytes = ((ASN1OctetString)obj).getOctets(); int padBits = bytes[0]; byte[] data = new byte[bytes.length - 1]; System.arraycopy(bytes, 1, data, 0, bytes.length - 1); return new DERBitString(data, padBits); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return a Bit String from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERBitString getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } protected DERBitString( byte data, int padBits) { this.data = new byte[1]; this.data[0] = data; this.padBits = padBits; } /** * @param data the octets making up the bit string. * @param padBits the number of extra bits at the end of the string. */ public DERBitString( byte[] data, int padBits) { this.data = data; this.padBits = padBits; } public DERBitString( byte[] data) { this(data, 0); } public DERBitString( DEREncodable obj) { try { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); dOut.writeObject(obj); dOut.close(); this.data = bOut.toByteArray(); this.padBits = 0; } catch (IOException e) { throw new IllegalArgumentException("Error processing object : " + e.toString()); } } public byte[] getBytes() { return data; } public int getPadBits() { return padBits; } /** * @return the value of the bit string as an int (truncating if necessary) */ public int intValue() { int value = 0; for (int i = 0; i != data.length && i != 4; i++) { value |= (data[i] & 0xff) << (8 * i); } return value; } void encode( DEROutputStream out) throws IOException { byte[] bytes = new byte[getBytes().length + 1]; bytes[0] = (byte)getPadBits(); System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1); out.writeEncoded(BIT_STRING, bytes); } public int hashCode() { int value = 0; for (int i = 0; i != data.length; i++) { value ^= (data[i] & 0xff) << (i % 4); } return value; } protected boolean asn1Equals( DERObject o) { if (!(o instanceof DERBitString)) { return false; } DERBitString other = (DERBitString)o; if (data.length != other.data.length) { return false; } for (int i = 0; i != data.length; i++) { if (data[i] != other.data[i]) { return false; } } return (padBits == other.padBits); } public String getString() { StringBuffer buf = new StringBuffer("#"); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); ASN1OutputStream aOut = new ASN1OutputStream(bOut); try { aOut.writeObject(this); } catch (IOException e) { throw new RuntimeException("internal error encoding BitString"); } byte[] string = bOut.toByteArray(); for (int i = 0; i != string.length; i++) { buf.append(table[(string[i] >>> 4) & 0xf]); buf.append(table[string[i] & 0xf]); } return buf.toString(); } public String toString() { return getString(); } } azureus-4.3.0.6/org/bouncycastle/asn1/BERTaggedObject.java0000644000175000017500000000654511026315606022512 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.util.Enumeration; /** * BER TaggedObject - in ASN.1 nottation this is any object proceeded by * a [n] where n is some number - these are assume to follow the construction * rules (as with sequences). */ public class BERTaggedObject extends DERTaggedObject { /** * @param tagNo the tag number for this object. * @param obj the tagged object. */ public BERTaggedObject( int tagNo, DEREncodable obj) { super(tagNo, obj); } /** * @param explicit true if an explicitly tagged object. * @param tagNo the tag number for this object. * @param obj the tagged object. */ public BERTaggedObject( boolean explicit, int tagNo, DEREncodable obj) { super(explicit, tagNo, obj); } /** * create an implicitly tagged object that contains a zero * length sequence. */ public BERTaggedObject( int tagNo) { super(false, tagNo, new BERSequence()); } void encode( DEROutputStream out) throws IOException { if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) { out.write(CONSTRUCTED | TAGGED | tagNo); out.write(0x80); if (!empty) { if (!explicit) { if (obj instanceof ASN1OctetString) { Enumeration e; if (obj instanceof BERConstructedOctetString) { e = ((BERConstructedOctetString)obj).getObjects(); } else { ASN1OctetString octs = (ASN1OctetString)obj; BERConstructedOctetString berO = new BERConstructedOctetString(octs.getOctets()); e = berO.getObjects(); } while (e.hasMoreElements()) { out.writeObject(e.nextElement()); } } else if (obj instanceof ASN1Sequence) { Enumeration e = ((ASN1Sequence)obj).getObjects(); while (e.hasMoreElements()) { out.writeObject(e.nextElement()); } } else if (obj instanceof ASN1Set) { Enumeration e = ((ASN1Set)obj).getObjects(); while (e.hasMoreElements()) { out.writeObject(e.nextElement()); } } else { throw new RuntimeException("not implemented: " + obj.getClass().getName()); } } else { out.writeObject(obj); } } out.write(0x00); out.write(0x00); } else { super.encode(out); } } } azureus-4.3.0.6/org/bouncycastle/asn1/DERNull.java0000644000175000017500000000061111026315616021071 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; /** * A NULL object. */ public class DERNull extends ASN1Null { public static final DERNull INSTANCE = new DERNull(); byte[] zeroBytes = new byte[0]; public DERNull() { } void encode( DEROutputStream out) throws IOException { out.writeEncoded(NULL, zeroBytes); } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1Object.java0000644000175000017500000000167311026315566021472 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; public abstract class ASN1Object extends DERObject { /** * Create a base ASN.1 object from a byte stream. * * @param data the byte stream to parse. * @return the base ASN.1 object represented by the byte stream. * @exception IOException if there is a problem parsing the data. */ public static ASN1Object fromByteArray(byte[] data) throws IOException { ASN1InputStream aIn = new ASN1InputStream(data); return (ASN1Object)aIn.readObject(); } public final boolean equals(Object o) { if (this == o) { return true; } return (o instanceof DEREncodable) && asn1Equals(((DEREncodable)o).getDERObject()); } public abstract int hashCode(); abstract void encode(DEROutputStream out) throws IOException; abstract boolean asn1Equals(DERObject o); } azureus-4.3.0.6/org/bouncycastle/asn1/BERGenerator.java0000644000175000017500000000375011026315604022107 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class BERGenerator extends ASN1Generator { private boolean _tagged = false; private boolean _isExplicit; private int _tagNo; protected BERGenerator( OutputStream out) { super(out); } public BERGenerator( OutputStream out, int tagNo, boolean isExplicit) { super(out); _tagged = true; _isExplicit = isExplicit; _tagNo = tagNo; } public OutputStream getRawOutputStream() { return _out; } private void writeHdr( int tag) throws IOException { _out.write(tag); _out.write(0x80); } protected void writeBERHeader( int tag) throws IOException { if (_tagged) { int tagNum = _tagNo | DERTags.TAGGED; if (_isExplicit) { writeHdr(tagNum | DERTags.CONSTRUCTED); writeHdr(tag); } else { if ((tag & DERTags.CONSTRUCTED) != 0) { writeHdr(tagNum | DERTags.CONSTRUCTED); } else { writeHdr(tagNum); } } } else { writeHdr(tag); } } protected void writeBERBody( InputStream contentStream) throws IOException { int ch; while ((ch = contentStream.read()) >= 0) { _out.write(ch); } } protected void writeBEREnd() throws IOException { _out.write(0x00); _out.write(0x00); if (_tagged && _isExplicit) // write extra end for tag header { _out.write(0x00); _out.write(0x00); } } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1SequenceParser.java0000644000175000017500000000027011026315614023173 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; public interface ASN1SequenceParser extends DEREncodable { DEREncodable readObject() throws IOException; } azureus-4.3.0.6/org/bouncycastle/asn1/DERInteger.java0000644000175000017500000000553011026315616021561 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.math.BigInteger; public class DERInteger extends ASN1Object { byte[] bytes; /** * return an integer from the passed in object * * @exception IllegalArgumentException if the object cannot be converted. */ public static DERInteger getInstance( Object obj) { if (obj == null || obj instanceof DERInteger) { return (DERInteger)obj; } if (obj instanceof ASN1OctetString) { return new DERInteger(((ASN1OctetString)obj).getOctets()); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return an Integer from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERInteger getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } public DERInteger( int value) { bytes = BigInteger.valueOf(value).toByteArray(); } public DERInteger( BigInteger value) { bytes = value.toByteArray(); } public DERInteger( byte[] bytes) { this.bytes = bytes; } public BigInteger getValue() { return new BigInteger(bytes); } /** * in some cases positive values get crammed into a space, * that's not quite big enough... */ public BigInteger getPositiveValue() { return new BigInteger(1, bytes); } void encode( DEROutputStream out) throws IOException { out.writeEncoded(INTEGER, bytes); } public int hashCode() { int value = 0; for (int i = 0; i != bytes.length; i++) { value ^= (bytes[i] & 0xff) << (i % 4); } return value; } boolean asn1Equals( DERObject o) { if (!(o instanceof DERInteger)) { return false; } DERInteger other = (DERInteger)o; if (bytes.length != other.bytes.length) { return false; } for (int i = 0; i != bytes.length; i++) { if (bytes[i] != other.bytes[i]) { return false; } } return true; } public String toString() { return getValue().toString(); } } azureus-4.3.0.6/org/bouncycastle/asn1/BERSequenceGenerator.java0000644000175000017500000000152111026315612023571 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.io.OutputStream; public class BERSequenceGenerator extends BERGenerator { public BERSequenceGenerator( OutputStream out) throws IOException { super(out); writeBERHeader(DERTags.CONSTRUCTED | DERTags.SEQUENCE); } public BERSequenceGenerator( OutputStream out, int tagNo, boolean isExplicit) throws IOException { super(out, tagNo, isExplicit); writeBERHeader(DERTags.CONSTRUCTED | DERTags.SEQUENCE); } public void addObject( DEREncodable object) throws IOException { object.getDERObject().encode(new DEROutputStream(_out)); } public void close() throws IOException { writeBEREnd(); } } azureus-4.3.0.6/org/bouncycastle/asn1/DERUniversalString.java0000644000175000017500000000571311026315606023325 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * DER UniversalString object. */ public class DERUniversalString extends ASN1Object implements DERString { private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; private byte[] string; /** * return a Universal String from the passed in object. * * @exception IllegalArgumentException if the object cannot be converted. */ public static DERUniversalString getInstance( Object obj) { if (obj == null || obj instanceof DERUniversalString) { return (DERUniversalString)obj; } if (obj instanceof ASN1OctetString) { return new DERUniversalString(((ASN1OctetString)obj).getOctets()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return a Universal String from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERUniversalString getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } /** * basic constructor - byte encoded string. */ public DERUniversalString( byte[] string) { this.string = string; } public String getString() { StringBuffer buf = new StringBuffer("#"); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); ASN1OutputStream aOut = new ASN1OutputStream(bOut); try { aOut.writeObject(this); } catch (IOException e) { throw new RuntimeException("internal error encoding BitString"); } byte[] string = bOut.toByteArray(); for (int i = 0; i != string.length; i++) { buf.append(table[(string[i] >>> 4) & 0xf]); buf.append(table[string[i] & 0xf]); } return buf.toString(); } public String toString() { return getString(); } public byte[] getOctets() { return string; } void encode( DEROutputStream out) throws IOException { out.writeEncoded(UNIVERSAL_STRING, this.getOctets()); } boolean asn1Equals( DERObject o) { if (!(o instanceof DERUniversalString)) { return false; } return this.getString().equals(((DERUniversalString)o).getString()); } public int hashCode() { return this.getString().hashCode(); } } azureus-4.3.0.6/org/bouncycastle/asn1/DEREncodableVector.java0000644000175000017500000000126011026315566023223 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.util.Vector; /** * a general class for building up a vector of DER encodable objects - * this will eventually be superceded by ASN1EncodableVector so you should * use that class in preference. */ public class DEREncodableVector { private Vector v = new Vector(); /** * @deprecated use ASN1EncodableVector instead. */ public DEREncodableVector() { } public void add( DEREncodable obj) { v.addElement(obj); } public DEREncodable get( int i) { return (DEREncodable)v.elementAt(i); } public int size() { return v.size(); } } azureus-4.3.0.6/org/bouncycastle/asn1/util/0000755000175000017500000000000011310377632017742 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/asn1/util/DERDump.java0000644000175000017500000000127510061400654022043 0ustar adrianadrianpackage org.bouncycastle.asn1.util; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; /** * @deprecated use ASN1Dump. */ public class DERDump extends ASN1Dump { /** * dump out a DER object as a formatted string * * @param obj the DERObject to be dumped out. */ public static String dumpAsString( DERObject obj) { return _dumpAsString("", obj); } /** * dump out a DER object as a formatted string * * @param obj the DERObject to be dumped out. */ public static String dumpAsString( DEREncodable obj) { return _dumpAsString("", obj.getDERObject()); } } azureus-4.3.0.6/org/bouncycastle/asn1/util/package.html0000644000175000017500000000010710061400654022212 0ustar adrianadrian An ASN.1 dump utility. azureus-4.3.0.6/org/bouncycastle/asn1/util/Dump.java0000644000175000017500000000077610061400654021515 0ustar adrianadrianpackage org.bouncycastle.asn1.util; import java.io.FileInputStream; import org.bouncycastle.asn1.ASN1InputStream; public class Dump { public static void main( String args[]) throws Exception { FileInputStream fIn = new FileInputStream(args[0]); ASN1InputStream bIn = new ASN1InputStream(fIn); Object obj = null; while ((obj = bIn.readObject()) != null) { System.out.println(ASN1Dump.dumpAsString(obj)); } } } azureus-4.3.0.6/org/bouncycastle/asn1/util/ASN1Dump.java0000644000175000017500000002112510061400654022127 0ustar adrianadrianpackage org.bouncycastle.asn1.util; import java.util.Enumeration; import org.bouncycastle.asn1.*; import org.bouncycastle.util.encoders.Hex; public class ASN1Dump { private static String TAB = " "; /** * dump a DER object as a formatted string with indentation * * @param obj the DERObject to be dumped out. */ public static String _dumpAsString( String indent, DERObject obj) { if (obj instanceof ASN1Sequence) { StringBuffer buf = new StringBuffer(); Enumeration e = ((ASN1Sequence)obj).getObjects(); String tab = indent + TAB; buf.append(indent); if (obj instanceof BERConstructedSequence) { buf.append("BER ConstructedSequence"); } else if (obj instanceof DERConstructedSequence) { buf.append("DER ConstructedSequence"); } else if (obj instanceof DERSequence) { buf.append("DER Sequence"); } else if (obj instanceof BERSequence) { buf.append("BER Sequence"); } else { buf.append("Sequence"); } buf.append(System.getProperty("line.separator")); while (e.hasMoreElements()) { Object o = e.nextElement(); if (o == null || o.equals(new DERNull())) { buf.append(tab); buf.append("NULL"); buf.append(System.getProperty("line.separator")); } else if (o instanceof DERObject) { buf.append(_dumpAsString(tab, (DERObject)o)); } else { buf.append(_dumpAsString(tab, ((DEREncodable)o).getDERObject())); } } return buf.toString(); } else if (obj instanceof DERTaggedObject) { StringBuffer buf = new StringBuffer(); String tab = indent + TAB; buf.append(indent); if (obj instanceof BERTaggedObject) { buf.append("BER Tagged ["); } else { buf.append("Tagged ["); } DERTaggedObject o = (DERTaggedObject)obj; buf.append(Integer.toString(o.getTagNo())); buf.append("]"); if (!o.isExplicit()) { buf.append(" IMPLICIT "); } buf.append(System.getProperty("line.separator")); if (o.isEmpty()) { buf.append(tab); buf.append("EMPTY"); buf.append(System.getProperty("line.separator")); } else { buf.append(_dumpAsString(tab, o.getObject())); } return buf.toString(); } else if (obj instanceof DERConstructedSet) { StringBuffer buf = new StringBuffer(); Enumeration e = ((ASN1Set)obj).getObjects(); String tab = indent + TAB; buf.append(indent); buf.append("ConstructedSet"); buf.append(System.getProperty("line.separator")); while (e.hasMoreElements()) { Object o = e.nextElement(); if (o == null) { buf.append(tab); buf.append("NULL"); buf.append(System.getProperty("line.separator")); } else if (o instanceof DERObject) { buf.append(_dumpAsString(tab, (DERObject)o)); } else { buf.append(_dumpAsString(tab, ((DEREncodable)o).getDERObject())); } } return buf.toString(); } else if (obj instanceof BERSet) { StringBuffer buf = new StringBuffer(); Enumeration e = ((ASN1Set)obj).getObjects(); String tab = indent + TAB; buf.append(indent); buf.append("BER Set"); buf.append(System.getProperty("line.separator")); while (e.hasMoreElements()) { Object o = e.nextElement(); if (o == null) { buf.append(tab); buf.append("NULL"); buf.append(System.getProperty("line.separator")); } else if (o instanceof DERObject) { buf.append(_dumpAsString(tab, (DERObject)o)); } else { buf.append(_dumpAsString(tab, ((DEREncodable)o).getDERObject())); } } return buf.toString(); } else if (obj instanceof DERSet) { StringBuffer buf = new StringBuffer(); Enumeration e = ((ASN1Set)obj).getObjects(); String tab = indent + TAB; buf.append(indent); buf.append("DER Set"); buf.append(System.getProperty("line.separator")); while (e.hasMoreElements()) { Object o = e.nextElement(); if (o == null) { buf.append(tab); buf.append("NULL"); buf.append(System.getProperty("line.separator")); } else if (o instanceof DERObject) { buf.append(_dumpAsString(tab, (DERObject)o)); } else { buf.append(_dumpAsString(tab, ((DEREncodable)o).getDERObject())); } } return buf.toString(); } else if (obj instanceof DERObjectIdentifier) { return indent + "ObjectIdentifier(" + ((DERObjectIdentifier)obj).getId() + ")" + System.getProperty("line.separator"); } else if (obj instanceof DERBoolean) { return indent + "Boolean(" + ((DERBoolean)obj).isTrue() + ")" + System.getProperty("line.separator"); } else if (obj instanceof DERInteger) { return indent + "Integer(" + ((DERInteger)obj).getValue() + ")" + System.getProperty("line.separator"); } else if (obj instanceof DEROctetString) { return indent + obj.toString() + "[" + ((ASN1OctetString)obj).getOctets().length + "] " + System.getProperty("line.separator"); } else if (obj instanceof DERIA5String) { return indent + "IA5String(" + ((DERIA5String)obj).getString() + ") " + System.getProperty("line.separator"); } else if (obj instanceof DERPrintableString) { return indent + "PrintableString(" + ((DERPrintableString)obj).getString() + ") " + System.getProperty("line.separator"); } else if (obj instanceof DERVisibleString) { return indent + "VisibleString(" + ((DERVisibleString)obj).getString() + ") " + System.getProperty("line.separator"); } else if (obj instanceof DERBMPString) { return indent + "BMPString(" + ((DERBMPString)obj).getString() + ") " + System.getProperty("line.separator"); } else if (obj instanceof DERT61String) { return indent + "T61String(" + ((DERT61String)obj).getString() + ") " + System.getProperty("line.separator"); } else if (obj instanceof DERUTCTime) { return indent + "UTCTime(" + ((DERUTCTime)obj).getTime() + ") " + System.getProperty("line.separator"); } else if (obj instanceof DERUnknownTag) { return indent + "Unknown " + Integer.toString(((DERUnknownTag)obj).getTag(), 16) + " " + new String(Hex.encode(((DERUnknownTag)obj).getData())) + System.getProperty("line.separator"); } else { return indent + obj.toString() + System.getProperty("line.separator"); } } /** * dump out a DER object as a formatted string * * @param obj the DERObject to be dumped out. */ public static String dumpAsString( Object obj) { if (obj instanceof DERObject) { return _dumpAsString("", (DERObject)obj); } else if (obj instanceof DEREncodable) { return _dumpAsString("", ((DEREncodable)obj).getDERObject()); } return "unknown object type " + obj.toString(); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/0000755000175000017500000000000011310377632017472 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/asn1/x509/Targets.java0000644000175000017500000000621511026315644021751 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import java.util.Enumeration; /** * Targets structure used in target information extension for attribute * certificates from RFC 3281. * *

       *            Targets ::= SEQUENCE OF Target
       *           
       *            Target  ::= CHOICE {
       *              targetName          [0] GeneralName,
       *              targetGroup         [1] GeneralName,
       *              targetCert          [2] TargetCert
       *            }
       *           
       *            TargetCert  ::= SEQUENCE {
       *              targetCertificate    IssuerSerial,
       *              targetName           GeneralName OPTIONAL,
       *              certDigestInfo       ObjectDigestInfo OPTIONAL
       *            }
       * 
      * * @see org.bouncycastle.asn1.x509.Target * @see org.bouncycastle.asn1.x509.TargetInformation */ public class Targets extends ASN1Encodable { private ASN1Sequence targets; /** * Creates an instance of a Targets from the given object. *

      * obj can be a Targets or a {@link ASN1Sequence} * * @param obj The object. * @return A Targets instance. * @throws IllegalArgumentException if the given object cannot be * interpreted as Target. */ public static Targets getInstance(Object obj) { if (obj instanceof Targets) { return (Targets)obj; } else if (obj instanceof ASN1Sequence) { return new Targets((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory: " + obj.getClass()); } /** * Constructor from ASN1Sequence. * * @param targets The ASN.1 SEQUENCE. * @throws IllegalArgumentException if the contents of the sequence are * invalid. */ private Targets(ASN1Sequence targets) { this.targets = targets; } /** * Constructor from given targets. *

      * The vector is copied. * * @param targets A Vector of {@link Target}s. * @see Target * @throws IllegalArgumentException if the vector contains not only Targets. */ public Targets(Target[] targets) { this.targets = new DERSequence(targets); } /** * Returns the targets in a Vector. *

      * The vector is cloned before it is returned. * * @return Returns the targets. */ public Target[] getTargets() { Target[] targs = new Target[targets.size()]; int count = 0; for (Enumeration e = targets.getObjects(); e.hasMoreElements();) { targs[count++] = Target.getInstance(e.nextElement()); } return targs; } /** * Produce an object suitable for an ASN1OutputStream. * * Returns: * *

           *            Targets ::= SEQUENCE OF Target
           * 
      * * @return a DERObject */ public DERObject toASN1Object() { return targets; } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/GeneralNames.java0000644000175000017500000000432411026315666022704 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; public class GeneralNames extends ASN1Encodable { ASN1Sequence seq; public static GeneralNames getInstance( Object obj) { if (obj == null || obj instanceof GeneralNames) { return (GeneralNames)obj; } if (obj instanceof ASN1Sequence) { return new GeneralNames((ASN1Sequence)obj); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } public static GeneralNames getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } /** * Construct a GeneralNames object containing one GeneralName. * * @param name the name to be contained. */ public GeneralNames( GeneralName name) { this.seq = new DERSequence(name); } public GeneralNames( ASN1Sequence seq) { this.seq = seq; } public GeneralName[] getNames() { GeneralName[] names = new GeneralName[seq.size()]; for (int i = 0; i != seq.size(); i++) { names[i] = GeneralName.getInstance(seq.getObjectAt(i)); } return names; } /** * Produce an object suitable for an ASN1OutputStream. *
           * GeneralNames ::= SEQUENCE SIZE {1..MAX} OF GeneralName
           * 
      */ public DERObject toASN1Object() { return seq; } public String toString() { StringBuffer buf = new StringBuffer(); String sep = System.getProperty("line.separator"); GeneralName[] names = getNames(); buf.append("GeneralNames:"); buf.append(sep); for (int i = 0; i != names.length; i++) { buf.append(" "); buf.append(names[i]); buf.append(sep); } return buf.toString(); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/TargetInformation.java0000644000175000017500000000627611026315632024000 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import java.util.Enumeration; /** * Target information extension for attributes certificates according to RFC * 3281. * *
       *           SEQUENCE OF Targets
       * 
      * */ public class TargetInformation extends ASN1Encodable { private ASN1Sequence targets; /** * Creates an instance of a TargetInformation from the given object. *

      * obj can be a TargetInformation or a {@link ASN1Sequence} * * @param obj The object. * @return A TargetInformation instance. * @throws IllegalArgumentException if the given object cannot be * interpreted as TargetInformation. */ public static TargetInformation getInstance(Object obj) { if (obj instanceof TargetInformation) { return (TargetInformation) obj; } else if (obj instanceof ASN1Sequence) { return new TargetInformation((ASN1Sequence) obj); } throw new IllegalArgumentException("unknown object in factory: " + obj.getClass()); } /** * Constructor from a ASN1Sequence. * * @param seq The ASN1Sequence. * @throws IllegalArgumentException if the sequence does not contain * correctly encoded Targets elements. */ private TargetInformation(ASN1Sequence seq) { targets = seq; } /** * Returns the targets in this target information extension. * * @return Returns the targets. */ public Targets[] getTargetsObjects() { Targets[] copy = new Targets[targets.size()]; int count = 0; for (Enumeration e = targets.getObjects(); e.hasMoreElements();) { copy[count++] = Targets.getInstance(e.nextElement()); } return copy; } /** * Constructs a target information from a single targets element. * According to RFC 3281 only one targets element must be produced. * * @param targets A Targets instance. */ public TargetInformation(Targets targets) { this.targets = new DERSequence(targets); } /** * According to RFC 3281 only one targets element must be produced. If * multiple targets are given they must be merged in * into one targets element. * * @param targets An array with {@link Targets}. */ public TargetInformation(Target[] targets) { this(new Targets(targets)); } /** * Produce an object suitable for an ASN1OutputStream. * * Returns: * *

           *          SEQUENCE OF Targets
           * 
      * *

      * According to RFC 3281 only one targets element must be produced. If * multiple targets are given in the constructor they are merged into one * targets element. If this was produced from a * {@link org.bouncycastle.asn1.ASN1Sequence} the encoding is kept. * * @return a DERObject */ public DERObject toASN1Object() { return targets; } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/CertificateList.java0000644000175000017500000000541311026315626023415 0ustar adrianadrian package org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; /** * PKIX RFC-2459 * * The X.509 v2 CRL syntax is as follows. For signature calculation, * the data that is to be signed is ASN.1 DER encoded. * *

       * CertificateList  ::=  SEQUENCE  {
       *      tbsCertList          TBSCertList,
       *      signatureAlgorithm   AlgorithmIdentifier,
       *      signatureValue       BIT STRING  }
       * 
      */ public class CertificateList extends ASN1Encodable { TBSCertList tbsCertList; AlgorithmIdentifier sigAlgId; DERBitString sig; public static CertificateList getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static CertificateList getInstance( Object obj) { if (obj instanceof CertificateList) { return (CertificateList)obj; } else if (obj instanceof ASN1Sequence) { return new CertificateList((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public CertificateList( ASN1Sequence seq) { if (seq.size() == 3) { tbsCertList = TBSCertList.getInstance(seq.getObjectAt(0)); sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1)); sig = DERBitString.getInstance(seq.getObjectAt(2)); } else { throw new IllegalArgumentException("sequence wrong size for CertificateList"); } } public TBSCertList getTBSCertList() { return tbsCertList; } public TBSCertList.CRLEntry[] getRevokedCertificates() { return tbsCertList.getRevokedCertificates(); } public AlgorithmIdentifier getSignatureAlgorithm() { return sigAlgId; } public DERBitString getSignature() { return sig; } public int getVersion() { return tbsCertList.getVersion(); } public X509Name getIssuer() { return tbsCertList.getIssuer(); } public Time getThisUpdate() { return tbsCertList.getThisUpdate(); } public Time getNextUpdate() { return tbsCertList.getNextUpdate(); } public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(tbsCertList); v.add(sigAlgId); v.add(sig); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/PolicyMappings.java0000644000175000017500000000354611026315632023277 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import java.util.Hashtable; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; /** * PolicyMappings V3 extension, described in RFC3280. *
       *    PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
       *      issuerDomainPolicy      CertPolicyId,
       *      subjectDomainPolicy     CertPolicyId }
       * 
      * * @see RFC 3280, section 4.2.1.6 */ public class PolicyMappings extends ASN1Encodable { ASN1Sequence seq = null; /** * Creates a new PolicyMappings instance. * * @param seq an ASN1Sequence constructed as specified * in RFC 3280 */ public PolicyMappings (ASN1Sequence seq) { this.seq = seq; } /** * Creates a new PolicyMappings instance. * * @param mappings a HashMap value that maps * String oids * to other String oids. */ public PolicyMappings (Hashtable mappings) { ASN1EncodableVector dev = new ASN1EncodableVector(); Enumeration it = mappings.keys(); while (it.hasMoreElements()) { String idp = (String) it.nextElement(); String sdp = (String) mappings.get(idp); ASN1EncodableVector dv = new ASN1EncodableVector(); dv.add(new DERObjectIdentifier(idp)); dv.add(new DERObjectIdentifier(sdp)); dev.add(new DERSequence(dv)); } seq = new DERSequence(dev); } public DERObject toASN1Object() { return seq; } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/AttCertValidityPeriod.java0000644000175000017500000000420011026315662024547 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERGeneralizedTime; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; public class AttCertValidityPeriod extends ASN1Encodable { DERGeneralizedTime notBeforeTime; DERGeneralizedTime notAfterTime; public static AttCertValidityPeriod getInstance( Object obj) { if (obj instanceof AttCertValidityPeriod) { return (AttCertValidityPeriod)obj; } else if (obj instanceof ASN1Sequence) { return new AttCertValidityPeriod((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public AttCertValidityPeriod( ASN1Sequence seq) { if (seq.size() != 2) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } notBeforeTime = DERGeneralizedTime.getInstance(seq.getObjectAt(0)); notAfterTime = DERGeneralizedTime.getInstance(seq.getObjectAt(1)); } /** * @param notBeforeTime * @param notAfterTime */ public AttCertValidityPeriod( DERGeneralizedTime notBeforeTime, DERGeneralizedTime notAfterTime) { this.notBeforeTime = notBeforeTime; this.notAfterTime = notAfterTime; } public DERGeneralizedTime getNotBeforeTime() { return notBeforeTime; } public DERGeneralizedTime getNotAfterTime() { return notAfterTime; } /** * Produce an object suitable for an ASN1OutputStream. *
           *  AttCertValidityPeriod  ::= SEQUENCE {
           *       notBeforeTime  GeneralizedTime,
           *       notAfterTime   GeneralizedTime
           *  } 
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(notBeforeTime); v.add(notAfterTime); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/CRLDistPoint.java0000644000175000017500000000464611026315632022621 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; public class CRLDistPoint extends ASN1Encodable { ASN1Sequence seq = null; public static CRLDistPoint getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static CRLDistPoint getInstance( Object obj) { if (obj instanceof CRLDistPoint || obj == null) { return (CRLDistPoint)obj; } else if (obj instanceof ASN1Sequence) { return new CRLDistPoint((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public CRLDistPoint( ASN1Sequence seq) { this.seq = seq; } public CRLDistPoint( DistributionPoint[] points) { ASN1EncodableVector v = new ASN1EncodableVector(); for (int i = 0; i != points.length; i++) { v.add(points[i]); } seq = new DERSequence(v); } /** * Return the distribution points making up the sequence. * * @return DistributionPoint[] */ public DistributionPoint[] getDistributionPoints() { DistributionPoint[] dp = new DistributionPoint[seq.size()]; for (int i = 0; i != seq.size(); i++) { dp[i] = DistributionPoint.getInstance(seq.getObjectAt(i)); } return dp; } /** * Produce an object suitable for an ASN1OutputStream. *
           * CRLDistPoint ::= SEQUENCE SIZE {1..MAX} OF DistributionPoint
           * 
      */ public DERObject toASN1Object() { return seq; } public String toString() { StringBuffer buf = new StringBuffer(); String sep = System.getProperty("line.separator"); buf.append("CRLDistPoint:"); buf.append(sep); DistributionPoint dp[] = getDistributionPoints(); for (int i = 0; i != dp.length; i++) { buf.append(" "); buf.append(dp[i]); buf.append(sep); } return buf.toString(); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java0000644000175000017500000001521311026315664025004 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.SHA1Digest; import java.math.BigInteger; import java.util.Enumeration; /** * The AuthorityKeyIdentifier object. *
       * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
       *
       *   AuthorityKeyIdentifier ::= SEQUENCE {
       *      keyIdentifier             [0] IMPLICIT KeyIdentifier           OPTIONAL,
       *      authorityCertIssuer       [1] IMPLICIT GeneralNames            OPTIONAL,
       *      authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL  }
       *
       *   KeyIdentifier ::= OCTET STRING
       * 
      * */ public class AuthorityKeyIdentifier extends ASN1Encodable { ASN1OctetString keyidentifier=null; GeneralNames certissuer=null; DERInteger certserno=null; public static AuthorityKeyIdentifier getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static AuthorityKeyIdentifier getInstance( Object obj) { if (obj instanceof AuthorityKeyIdentifier) { return (AuthorityKeyIdentifier)obj; } if (obj instanceof ASN1Sequence) { return new AuthorityKeyIdentifier((ASN1Sequence)obj); } if (obj instanceof X509Extension) { return getInstance(X509Extension.convertValueToObject((X509Extension)obj)); } throw new IllegalArgumentException("unknown object in factory"); } public AuthorityKeyIdentifier( ASN1Sequence seq) { Enumeration e = seq.getObjects(); while (e.hasMoreElements()) { ASN1TaggedObject o = DERTaggedObject.getInstance(e.nextElement()); switch (o.getTagNo()) { case 0: this.keyidentifier = ASN1OctetString.getInstance(o, false); break; case 1: this.certissuer = GeneralNames.getInstance(o, false); break; case 2: this.certserno = DERInteger.getInstance(o, false); break; default: throw new IllegalArgumentException("illegal tag"); } } } /** * * Calulates the keyidentifier using a SHA1 hash over the BIT STRING * from SubjectPublicKeyInfo as defined in RFC2459. * * Example of making a AuthorityKeyIdentifier: *
           *   SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
           *       publicKey.getEncoded()).readObject());
           *   AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
           * 
      * **/ public AuthorityKeyIdentifier( SubjectPublicKeyInfo spki) { Digest digest = new SHA1Digest(); byte[] resBuf = new byte[digest.getDigestSize()]; byte[] bytes = spki.getPublicKeyData().getBytes(); digest.update(bytes, 0, bytes.length); digest.doFinal(resBuf, 0); this.keyidentifier = new DEROctetString(resBuf); } /** * create an AuthorityKeyIdentifier with the GeneralNames tag and * the serial number provided as well. */ public AuthorityKeyIdentifier( SubjectPublicKeyInfo spki, GeneralNames name, BigInteger serialNumber) { Digest digest = new SHA1Digest(); byte[] resBuf = new byte[digest.getDigestSize()]; byte[] bytes = spki.getPublicKeyData().getBytes(); digest.update(bytes, 0, bytes.length); digest.doFinal(resBuf, 0); this.keyidentifier = new DEROctetString(resBuf); this.certissuer = GeneralNames.getInstance(name.toASN1Object()); this.certserno = new DERInteger(serialNumber); } /** * create an AuthorityKeyIdentifier with the GeneralNames tag and * the serial number provided. */ public AuthorityKeyIdentifier( GeneralNames name, BigInteger serialNumber) { this.keyidentifier = null; this.certissuer = GeneralNames.getInstance(name.toASN1Object()); this.certserno = new DERInteger(serialNumber); } /** * create an AuthorityKeyIdentifier with a precomupted key identifier */ public AuthorityKeyIdentifier( byte[] keyIdentifier) { this.keyidentifier = new DEROctetString(keyIdentifier); this.certissuer = null; this.certserno = null; } /** * create an AuthorityKeyIdentifier with a precomupted key identifier * and the GeneralNames tag and the serial number provided as well. */ public AuthorityKeyIdentifier( byte[] keyIdentifier, GeneralNames name, BigInteger serialNumber) { this.keyidentifier = new DEROctetString(keyIdentifier); this.certissuer = GeneralNames.getInstance(name.toASN1Object()); this.certserno = new DERInteger(serialNumber); } public byte[] getKeyIdentifier() { if (keyidentifier != null) { return keyidentifier.getOctets(); } return null; } public GeneralNames getAuthorityCertIssuer() { return certissuer; } public BigInteger getAuthorityCertSerialNumber() { if (certserno != null) { return certserno.getValue(); } return null; } /** * Produce an object suitable for an ASN1OutputStream. */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); if (keyidentifier != null) { v.add(new DERTaggedObject(false, 0, keyidentifier)); } if (certissuer != null) { v.add(new DERTaggedObject(false, 1, certissuer)); } if (certserno != null) { v.add(new DERTaggedObject(false, 2, certserno)); } return new DERSequence(v); } public String toString() { return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.getOctets() + ")"); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/GeneralName.java0000644000175000017500000002101711026315636022514 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Choice; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERIA5String; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.util.IPAddress; import org.bouncycastle.util.Strings; /** * The GeneralName object. *
       * GeneralName ::= CHOICE {
       *      otherName                       [0]     OtherName,
       *      rfc822Name                      [1]     IA5String,
       *      dNSName                         [2]     IA5String,
       *      x400Address                     [3]     ORAddress,
       *      directoryName                   [4]     Name,
       *      ediPartyName                    [5]     EDIPartyName,
       *      uniformResourceIdentifier       [6]     IA5String,
       *      iPAddress                       [7]     OCTET STRING,
       *      registeredID                    [8]     OBJECT IDENTIFIER}
       *
       * OtherName ::= SEQUENCE {
       *      type-id    OBJECT IDENTIFIER,
       *      value      [0] EXPLICIT ANY DEFINED BY type-id }
       *
       * EDIPartyName ::= SEQUENCE {
       *      nameAssigner            [0]     DirectoryString OPTIONAL,
       *      partyName               [1]     DirectoryString }
       * 
       * Name ::= CHOICE { RDNSequence }
       * 
      */ public class GeneralName extends ASN1Encodable implements ASN1Choice { public static final int otherName = 0; public static final int rfc822Name = 1; public static final int dNSName = 2; public static final int x400Address = 3; public static final int directoryName = 4; public static final int ediPartyName = 5; public static final int uniformResourceIdentifier = 6; public static final int iPAddress = 7; public static final int registeredID = 8; DEREncodable obj; int tag; public GeneralName( X509Name dirName) { this.obj = dirName; this.tag = 4; } /** * @deprecated this constructor seems the wrong way round! Use GeneralName(tag, name). */ public GeneralName( DERObject name, int tag) { this.obj = name; this.tag = tag; } /** * When the subjectAltName extension contains an Internet mail address, * the address MUST be included as an rfc822Name. The format of an * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822]. * * When the subjectAltName extension contains a domain name service * label, the domain name MUST be stored in the dNSName (an IA5String). * The name MUST be in the "preferred name syntax," as specified by RFC * 1034 [RFC 1034]. * * When the subjectAltName extension contains a URI, the name MUST be * stored in the uniformResourceIdentifier (an IA5String). The name MUST * be a non-relative URL, and MUST follow the URL syntax and encoding * rules specified in [RFC 1738]. The name must include both a scheme * (e.g., "http" or "ftp") and a scheme-specific-part. The scheme- * specific-part must include a fully qualified domain name or IP * address as the host. * * When the subjectAltName extension contains a iPAddress, the address * MUST be stored in the octet string in "network byte order," as * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of * each octet is the LSB of the corresponding byte in the network * address. For IP Version 4, as specified in RFC 791, the octet string * MUST contain exactly four octets. For IP Version 6, as specified in * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC * 1883]. */ public GeneralName( int tag, ASN1Encodable name) { this.obj = name; this.tag = tag; } /** * Create a GeneralName for the given tag from the passed in String. *

      * This constructor can handle: *

        *
      • rfc822Name *
      • iPAddress *
      • directoryName *
      • dNSName *
      • uniformResourceIdentifier *
      • registeredID *
      * For x400Address, otherName and ediPartyName there is no common string * format defined. *

      * Note: A directory name can be encoded in different ways into a byte * representation. Be aware of this if the byte representation is used for * comparing results. * * @param tag tag number * @param name string representation of name * @throws IllegalArgumentException if the string encoding is not correct or * not supported. */ public GeneralName( int tag, String name) { this.tag = tag; if (tag == rfc822Name || tag == dNSName || tag == uniformResourceIdentifier) { this.obj = new DERIA5String(name); } else if (tag == registeredID) { this.obj = new DERObjectIdentifier(name); } else if (tag == directoryName) { this.obj = new X509Name(name); } else if (tag == iPAddress) { if (IPAddress.isValid(name)) { this.obj = new DEROctetString(Strings.toUTF8ByteArray(name)); } else { throw new IllegalArgumentException("IP Address is invalid"); } } else { throw new IllegalArgumentException("can't process String for tag: " + tag); } } public static GeneralName getInstance( Object obj) { if (obj == null || obj instanceof GeneralName) { return (GeneralName)obj; } if (obj instanceof ASN1TaggedObject) { ASN1TaggedObject tagObj = (ASN1TaggedObject)obj; int tag = tagObj.getTagNo(); switch (tag) { case otherName: return new GeneralName(tag, ASN1Sequence.getInstance(tagObj, false)); case rfc822Name: return new GeneralName(tag, DERIA5String.getInstance(tagObj, false)); case dNSName: return new GeneralName(tag, DERIA5String.getInstance(tagObj, false)); case x400Address: throw new IllegalArgumentException("unknown tag: " + tag); case directoryName: return new GeneralName(tag, ASN1Sequence.getInstance(tagObj, true)); case ediPartyName: return new GeneralName(tag, ASN1Sequence.getInstance(tagObj, false)); case uniformResourceIdentifier: return new GeneralName(tag, DERIA5String.getInstance(tagObj, false)); case iPAddress: return new GeneralName(tag, ASN1OctetString.getInstance(tagObj, false)); case registeredID: return new GeneralName(tag, DERObjectIdentifier.getInstance(tagObj, false)); } } throw new IllegalArgumentException("unknown object in getInstance"); } public static GeneralName getInstance( ASN1TaggedObject tagObj, boolean explicit) { return GeneralName.getInstance(ASN1TaggedObject.getInstance(tagObj, true)); } public int getTagNo() { return tag; } public DEREncodable getName() { return obj; } public String toString() { StringBuffer buf = new StringBuffer(); buf.append(tag); buf.append(": "); switch (tag) { case rfc822Name: case dNSName: case uniformResourceIdentifier: buf.append(DERIA5String.getInstance(obj).getString()); break; case directoryName: buf.append(X509Name.getInstance(obj).toString()); break; default: buf.append(obj.toString()); } return buf.toString(); } public DERObject toASN1Object() { if (tag == directoryName) // directoryName is explicitly tagged as it is a CHOICE { return new DERTaggedObject(true, tag, obj); } else { return new DERTaggedObject(false, tag, obj); } } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/KeyUsage.java0000644000175000017500000000447011026315640022052 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.DERBitString; /** * The KeyUsage object. *

       *    id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
       *
       *    KeyUsage ::= BIT STRING {
       *         digitalSignature        (0),
       *         nonRepudiation          (1),
       *         keyEncipherment         (2),
       *         dataEncipherment        (3),
       *         keyAgreement            (4),
       *         keyCertSign             (5),
       *         cRLSign                 (6),
       *         encipherOnly            (7),
       *         decipherOnly            (8) }
       * 
      */ public class KeyUsage extends DERBitString { public static final int digitalSignature = (1 << 7); public static final int nonRepudiation = (1 << 6); public static final int keyEncipherment = (1 << 5); public static final int dataEncipherment = (1 << 4); public static final int keyAgreement = (1 << 3); public static final int keyCertSign = (1 << 2); public static final int cRLSign = (1 << 1); public static final int encipherOnly = (1 << 0); public static final int decipherOnly = (1 << 15); public static DERBitString getInstance(Object obj) // needs to be DERBitString for other VMs { if (obj instanceof KeyUsage) { return (KeyUsage)obj; } if (obj instanceof X509Extension) { return new KeyUsage(DERBitString.getInstance(X509Extension.convertValueToObject((X509Extension)obj))); } return new KeyUsage(DERBitString.getInstance(obj)); } /** * Basic constructor. * * @param usage - the bitwise OR of the Key Usage flags giving the * allowed uses for the key. * e.g. (KeyUsage.keyEncipherment | KeyUsage.dataEncipherment) */ public KeyUsage( int usage) { super(getBytes(usage), getPadBits(usage)); } public KeyUsage( DERBitString usage) { super(usage.getBytes(), usage.getPadBits()); } public String toString() { if (data.length == 1) { return "KeyUsage: 0x" + Integer.toHexString(data[0] & 0xff); } return "KeyUsage: 0x" + Integer.toHexString((data[1] & 0xff) << 8 | (data[0] & 0xff)); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/CertPolicyId.java0000644000175000017500000000056411026315636022674 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.DERObjectIdentifier; /** * CertPolicyId, used in the CertificatePolicies and PolicyMappings * X509V3 Extensions. * *
       *     CertPolicyId ::= OBJECT IDENTIFIER
       * 
      */ public class CertPolicyId extends DERObjectIdentifier { public CertPolicyId (String id) { super(id); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java0000644000175000017500000000766511026315640027347 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERGeneralizedTime; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERSet; /** * Generator for Version 2 AttributeCertificateInfo *
       * AttributeCertificateInfo ::= SEQUENCE {
       *       version              AttCertVersion -- version is v2,
       *       holder               Holder,
       *       issuer               AttCertIssuer,
       *       signature            AlgorithmIdentifier,
       *       serialNumber         CertificateSerialNumber,
       *       attrCertValidityPeriod   AttCertValidityPeriod,
       *       attributes           SEQUENCE OF Attribute,
       *       issuerUniqueID       UniqueIdentifier OPTIONAL,
       *       extensions           Extensions OPTIONAL
       * }
       * 
      * */ public class V2AttributeCertificateInfoGenerator { private DERInteger version; private Holder holder; private AttCertIssuer issuer; private AlgorithmIdentifier signature; private DERInteger serialNumber; private ASN1EncodableVector attributes; private DERBitString issuerUniqueID; private X509Extensions extensions; // Note: validity period start/end dates stored directly //private AttCertValidityPeriod attrCertValidityPeriod; private DERGeneralizedTime startDate, endDate; public V2AttributeCertificateInfoGenerator() { this.version = new DERInteger(1); attributes = new ASN1EncodableVector(); } public void setHolder(Holder holder) { this.holder = holder; } public void addAttribute(String oid, ASN1Encodable value) { attributes.add(new Attribute(new DERObjectIdentifier(oid), new DERSet(value))); } /** * @param attribute */ public void addAttribute(Attribute attribute) { attributes.add(attribute); } public void setSerialNumber( DERInteger serialNumber) { this.serialNumber = serialNumber; } public void setSignature( AlgorithmIdentifier signature) { this.signature = signature; } public void setIssuer( AttCertIssuer issuer) { this.issuer = issuer; } public void setStartDate( DERGeneralizedTime startDate) { this.startDate = startDate; } public void setEndDate( DERGeneralizedTime endDate) { this.endDate = endDate; } public void setIssuerUniqueID( DERBitString issuerUniqueID) { this.issuerUniqueID = issuerUniqueID; } public void setExtensions( X509Extensions extensions) { this.extensions = extensions; } public AttributeCertificateInfo generateAttributeCertificateInfo() { if ((serialNumber == null) || (signature == null) || (issuer == null) || (startDate == null) || (endDate == null) || (holder == null) || (attributes == null)) { throw new IllegalStateException("not all mandatory fields set in V2 AttributeCertificateInfo generator"); } ASN1EncodableVector v = new ASN1EncodableVector(); v.add(version); v.add(holder); v.add(issuer); v.add(signature); v.add(serialNumber); // // before and after dates => AttCertValidityPeriod // AttCertValidityPeriod validity = new AttCertValidityPeriod(startDate, endDate); v.add(validity); // Attributes v.add(new DERSequence(attributes)); if (issuerUniqueID != null) { v.add(issuerUniqueID); } if (extensions != null) { v.add(extensions); } return new AttributeCertificateInfo(new DERSequence(v)); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/CRLReason.java0000644000175000017500000000553511026315640022130 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.DEREnumerated; /** * The CRLReason enumeration. *
       * CRLReason ::= ENUMERATED {
       *  unspecified             (0),
       *  keyCompromise           (1),
       *  cACompromise            (2),
       *  affiliationChanged      (3),
       *  superseded              (4),
       *  cessationOfOperation    (5),
       *  certificateHold         (6),
       *  removeFromCRL           (8),
       *  privilegeWithdrawn      (9),
       *  aACompromise           (10)
       * }
       * 
      */ public class CRLReason extends DEREnumerated { /** * @deprecated use lower case version */ public static final int UNSPECIFIED = 0; /** * @deprecated use lower case version */ public static final int KEY_COMPROMISE = 1; /** * @deprecated use lower case version */ public static final int CA_COMPROMISE = 2; /** * @deprecated use lower case version */ public static final int AFFILIATION_CHANGED = 3; /** * @deprecated use lower case version */ public static final int SUPERSEDED = 4; /** * @deprecated use lower case version */ public static final int CESSATION_OF_OPERATION = 5; /** * @deprecated use lower case version */ public static final int CERTIFICATE_HOLD = 6; /** * @deprecated use lower case version */ public static final int REMOVE_FROM_CRL = 8; /** * @deprecated use lower case version */ public static final int PRIVILEGE_WITHDRAWN = 9; /** * @deprecated use lower case version */ public static final int AA_COMPROMISE = 10; public static final int unspecified = 0; public static final int keyCompromise = 1; public static final int cACompromise = 2; public static final int affiliationChanged = 3; public static final int superseded = 4; public static final int cessationOfOperation = 5; public static final int certificateHold = 6; // 7 -> unknown public static final int removeFromCRL = 8; public static final int privilegeWithdrawn = 9; public static final int aACompromise = 10; private static final String[] reasonString = { "unspecified", "keyCompromise", "cACompromise", "affiliationChanged", "superseded", "cessationOfOperation", "certificateHold", "unknown", "removeFromCRL", "privilegeWithdrawn", "aACompromise" }; public CRLReason( int reason) { super(reason); } public CRLReason( DEREnumerated reason) { super(reason.getValue().intValue()); } public String toString() { String str; int reason = getValue().intValue(); if (reason < 0 || reason > 10) { str = "invalid"; } else { str = reasonString[reason]; } return "CRLReason: " + str; } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/PrivateKeyUsagePeriod.java0000644000175000017500000000445311026315634024554 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERGeneralizedTime; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; import java.util.Enumeration; /** *
       *    PrivateKeyUsagePeriod ::= SEQUENCE {
       *      notBefore       [0]     GeneralizedTime OPTIONAL,
       *      notAfter        [1]     GeneralizedTime OPTIONAL }
       * 
      */ public class PrivateKeyUsagePeriod extends ASN1Encodable { public static PrivateKeyUsagePeriod getInstance(Object obj) { if (obj instanceof PrivateKeyUsagePeriod) { return (PrivateKeyUsagePeriod)obj; } if (obj instanceof ASN1Sequence) { return new PrivateKeyUsagePeriod((ASN1Sequence)obj); } if (obj instanceof X509Extension) { return getInstance(X509Extension.convertValueToObject((X509Extension)obj)); } throw new IllegalArgumentException("unknown object in getInstance"); } private DERGeneralizedTime _notBefore, _notAfter; private PrivateKeyUsagePeriod(ASN1Sequence seq) { Enumeration en = seq.getObjects(); while (en.hasMoreElements()) { ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement(); if (tObj.getTagNo() == 0) { _notBefore = DERGeneralizedTime.getInstance(tObj, false); } else if (tObj.getTagNo() == 1) { _notAfter = DERGeneralizedTime.getInstance(tObj, false); } } } public DERGeneralizedTime getNotBefore() { return _notBefore; } public DERGeneralizedTime getNotAfter() { return _notAfter; } public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); if (_notBefore != null) { v.add(new DERTaggedObject(false, 0, _notBefore)); } if (_notAfter != null) { v.add(new DERTaggedObject(false, 1, _notAfter)); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/X509DefaultEntryConverter.java0000644000175000017500000000345611026315634025227 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.DERGeneralizedTime; import org.bouncycastle.asn1.DERIA5String; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERPrintableString; import org.bouncycastle.asn1.DERUTF8String; import java.io.IOException; /** * The default converter for X509 DN entries when going from their * string value to ASN.1 strings. */ public class X509DefaultEntryConverter extends X509NameEntryConverter { /** * Apply default coversion for the given value depending on the oid * and the character range of the value. * * @param oid the object identifier for the DN entry * @param value the value associated with it * @return the ASN.1 equivalent for the string value. */ public DERObject getConvertedValue( DERObjectIdentifier oid, String value) { if (value.length() != 0 && value.charAt(0) == '#') { try { return convertHexEncoded(value, 1); } catch (IOException e) { throw new RuntimeException("can't recode value for oid " + oid.getId()); } } else if (oid.equals(X509Name.EmailAddress) || oid.equals(X509Name.DC)) { return new DERIA5String(value); } else if (oid.equals(X509Name.DATE_OF_BIRTH)) // accept time string as well as # (for compatibility) { return new DERGeneralizedTime(value); } else if (oid.equals(X509Name.C) || oid.equals(X509Name.SN) || oid.equals(X509Name.DN_QUALIFIER)) { return new DERPrintableString(value); } return new DERUTF8String(value); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/Attribute.java0000644000175000017500000000415711026315656022311 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; public class Attribute extends ASN1Encodable { private DERObjectIdentifier attrType; private ASN1Set attrValues; /** * return an Attribute object from the given object. * * @param o the object we want converted. * @exception IllegalArgumentException if the object cannot be converted. */ public static Attribute getInstance( Object o) { if (o == null || o instanceof Attribute) { return (Attribute)o; } if (o instanceof ASN1Sequence) { return new Attribute((ASN1Sequence)o); } throw new IllegalArgumentException("unknown object in factory"); } public Attribute( ASN1Sequence seq) { if (seq.size() != 2) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } attrType = DERObjectIdentifier.getInstance(seq.getObjectAt(0)); attrValues = ASN1Set.getInstance(seq.getObjectAt(1)); } public Attribute( DERObjectIdentifier attrType, ASN1Set attrValues) { this.attrType = attrType; this.attrValues = attrValues; } public DERObjectIdentifier getAttrType() { return attrType; } public ASN1Set getAttrValues() { return attrValues; } /** * Produce an object suitable for an ASN1OutputStream. *
           * Attribute ::= SEQUENCE {
           *     attrType OBJECT IDENTIFIER,
           *     attrValues SET OF AttributeValue
           * }
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(attrType); v.add(attrValues); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/ReasonFlags.java0000644000175000017500000000504411026315630022536 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.DERBitString; /** * The ReasonFlags object. *
       * ReasonFlags ::= BIT STRING {
       *      unused                  (0),
       *      keyCompromise           (1),
       *      cACompromise            (2),
       *      affiliationChanged      (3),
       *      superseded              (4),
       *      cessationOfOperation    (5),
       *      certificateHold         (6),
       *      privilegeWithdrawn      (7),
       *      aACompromise            (8) }
       * 
      */ public class ReasonFlags extends DERBitString { /** * @deprecated use lower case version */ public static final int UNUSED = (1 << 7); /** * @deprecated use lower case version */ public static final int KEY_COMPROMISE = (1 << 6); /** * @deprecated use lower case version */ public static final int CA_COMPROMISE = (1 << 5); /** * @deprecated use lower case version */ public static final int AFFILIATION_CHANGED = (1 << 4); /** * @deprecated use lower case version */ public static final int SUPERSEDED = (1 << 3); /** * @deprecated use lower case version */ public static final int CESSATION_OF_OPERATION = (1 << 2); /** * @deprecated use lower case version */ public static final int CERTIFICATE_HOLD = (1 << 1); /** * @deprecated use lower case version */ public static final int PRIVILEGE_WITHDRAWN = (1 << 0); /** * @deprecated use lower case version */ public static final int AA_COMPROMISE = (1 << 15); public static final int unused = (1 << 7); public static final int keyCompromise = (1 << 6); public static final int cACompromise = (1 << 5); public static final int affiliationChanged = (1 << 4); public static final int superseded = (1 << 3); public static final int cessationOfOperation = (1 << 2); public static final int certificateHold = (1 << 1); public static final int privilegeWithdrawn = (1 << 0); public static final int aACompromise = (1 << 15); /** * @param reasons - the bitwise OR of the Key Reason flags giving the * allowed uses for the key. */ public ReasonFlags( int reasons) { super(getBytes(reasons), getPadBits(reasons)); } public ReasonFlags( DERBitString reasons) { super(reasons.getBytes(), reasons.getPadBits()); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/X509CertificateStructure.java0000644000175000017500000000563511026315666025102 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; /** * an X509Certificate structure. *
       *  Certificate ::= SEQUENCE {
       *      tbsCertificate          TBSCertificate,
       *      signatureAlgorithm      AlgorithmIdentifier,
       *      signature               BIT STRING
       *  }
       * 
      */ public class X509CertificateStructure extends ASN1Encodable implements X509ObjectIdentifiers, PKCSObjectIdentifiers { ASN1Sequence seq; TBSCertificateStructure tbsCert; AlgorithmIdentifier sigAlgId; DERBitString sig; public static X509CertificateStructure getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static X509CertificateStructure getInstance( Object obj) { if (obj instanceof X509CertificateStructure) { return (X509CertificateStructure)obj; } else if (obj instanceof ASN1Sequence) { return new X509CertificateStructure((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public X509CertificateStructure( ASN1Sequence seq) { this.seq = seq; // // correct x509 certficate // if (seq.size() == 3) { tbsCert = TBSCertificateStructure.getInstance(seq.getObjectAt(0)); sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1)); sig = DERBitString.getInstance(seq.getObjectAt(2)); } else { throw new IllegalArgumentException("sequence wrong size for a certificate"); } } public TBSCertificateStructure getTBSCertificate() { return tbsCert; } public int getVersion() { return tbsCert.getVersion(); } public DERInteger getSerialNumber() { return tbsCert.getSerialNumber(); } public X509Name getIssuer() { return tbsCert.getIssuer(); } public Time getStartDate() { return tbsCert.getStartDate(); } public Time getEndDate() { return tbsCert.getEndDate(); } public X509Name getSubject() { return tbsCert.getSubject(); } public SubjectPublicKeyInfo getSubjectPublicKeyInfo() { return tbsCert.getSubjectPublicKeyInfo(); } public AlgorithmIdentifier getSignatureAlgorithm() { return sigAlgId; } public DERBitString getSignature() { return sig; } public DERObject toASN1Object() { return seq; } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/IetfAttrSyntax.java0000644000175000017500000001105111026315632023260 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import java.util.Enumeration; import java.util.Vector; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.DERUTF8String; /** * Implementation of IetfAttrSyntax as specified by RFC3281. */ public class IetfAttrSyntax extends ASN1Encodable { public static final int VALUE_OCTETS = 1; public static final int VALUE_OID = 2; public static final int VALUE_UTF8 = 3; GeneralNames policyAuthority = null; Vector values = new Vector(); int valueChoice = -1; /** * */ public IetfAttrSyntax(ASN1Sequence seq) { int i = 0; if (seq.getObjectAt(0) instanceof ASN1TaggedObject) { policyAuthority = GeneralNames.getInstance(((ASN1TaggedObject)seq.getObjectAt(0)), false); i++; } else if (seq.size() == 2) { // VOMS fix policyAuthority = GeneralNames.getInstance(seq.getObjectAt(0)); i++; } if (!(seq.getObjectAt(i) instanceof ASN1Sequence)) { throw new IllegalArgumentException("Non-IetfAttrSyntax encoding"); } seq = (ASN1Sequence)seq.getObjectAt(i); for (Enumeration e = seq.getObjects(); e.hasMoreElements();) { DERObject obj = (DERObject)e.nextElement(); int type; if (obj instanceof DERObjectIdentifier) { type = VALUE_OID; } else if (obj instanceof DERUTF8String) { type = VALUE_UTF8; } else if (obj instanceof DEROctetString) { type = VALUE_OCTETS; } else { throw new IllegalArgumentException("Bad value type encoding IetfAttrSyntax"); } if (valueChoice < 0) { valueChoice = type; } if (type != valueChoice) { throw new IllegalArgumentException("Mix of value types in IetfAttrSyntax"); } values.addElement(obj); } } public GeneralNames getPolicyAuthority() { return policyAuthority; } public int getValueType() { return valueChoice; } public Object[] getValues() { if (this.getValueType() == VALUE_OCTETS) { ASN1OctetString[] tmp = new ASN1OctetString[values.size()]; for (int i = 0; i != tmp.length; i++) { tmp[i] = (ASN1OctetString)values.elementAt(i); } return tmp; } else if (this.getValueType() == VALUE_OID) { DERObjectIdentifier[] tmp = new DERObjectIdentifier[values.size()]; for (int i = 0; i != tmp.length; i++) { tmp[i] = (DERObjectIdentifier)values.elementAt(i); } return tmp; } else { DERUTF8String[] tmp = new DERUTF8String[values.size()]; for (int i = 0; i != tmp.length; i++) { tmp[i] = (DERUTF8String)values.elementAt(i); } return tmp; } } /** * *
           * 
           *  IetfAttrSyntax ::= SEQUENCE {
           *    policyAuthority [0] GeneralNames OPTIONAL,
           *    values SEQUENCE OF CHOICE {
           *      octets OCTET STRING,
           *      oid OBJECT IDENTIFIER,
           *      string UTF8String
           *    }
           *  }
           *  
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); if (policyAuthority != null) { v.add(new DERTaggedObject(0, policyAuthority)); } ASN1EncodableVector v2 = new ASN1EncodableVector(); for (Enumeration i = values.elements(); i.hasMoreElements();) { v2.add((ASN1Encodable)i.nextElement()); } v.add(new DERSequence(v2)); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/DistributionPoint.java0000644000175000017500000001033011026315666024026 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; /** * The DistributionPoint object. *
       * DistributionPoint ::= SEQUENCE {
       *      distributionPoint [0] DistributionPointName OPTIONAL,
       *      reasons           [1] ReasonFlags OPTIONAL,
       *      cRLIssuer         [2] GeneralNames OPTIONAL
       * }
       * 
      */ public class DistributionPoint extends ASN1Encodable { DistributionPointName distributionPoint; ReasonFlags reasons; GeneralNames cRLIssuer; public static DistributionPoint getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static DistributionPoint getInstance( Object obj) { if(obj == null || obj instanceof DistributionPoint) { return (DistributionPoint)obj; } if(obj instanceof ASN1Sequence) { return new DistributionPoint((ASN1Sequence)obj); } throw new IllegalArgumentException("Invalid DistributionPoint: " + obj.getClass().getName()); } public DistributionPoint( ASN1Sequence seq) { for (int i = 0; i != seq.size(); i++) { ASN1TaggedObject t = ASN1TaggedObject.getInstance(seq.getObjectAt(i)); switch (t.getTagNo()) { case 0: distributionPoint = DistributionPointName.getInstance(t, true); break; case 1: reasons = new ReasonFlags(DERBitString.getInstance(t, false)); break; case 2: cRLIssuer = GeneralNames.getInstance(t, false); } } } public DistributionPoint( DistributionPointName distributionPoint, ReasonFlags reasons, GeneralNames cRLIssuer) { this.distributionPoint = distributionPoint; this.reasons = reasons; this.cRLIssuer = cRLIssuer; } public DistributionPointName getDistributionPoint() { return distributionPoint; } public ReasonFlags getReasons() { return reasons; } public GeneralNames getCRLIssuer() { return cRLIssuer; } public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); if (distributionPoint != null) { // // as this is a CHOICE it must be explicitly tagged // v.add(new DERTaggedObject(0, distributionPoint)); } if (reasons != null) { v.add(new DERTaggedObject(false, 1, reasons)); } if (cRLIssuer != null) { v.add(new DERTaggedObject(false, 2, cRLIssuer)); } return new DERSequence(v); } public String toString() { String sep = System.getProperty("line.separator"); StringBuffer buf = new StringBuffer(); buf.append("DistributionPoint: ["); buf.append(sep); if (distributionPoint != null) { appendObject(buf, sep, "distributionPoint", distributionPoint.toString()); } if (reasons != null) { appendObject(buf, sep, "reasons", reasons.toString()); } if (cRLIssuer != null) { appendObject(buf, sep, "cRLIssuer", cRLIssuer.toString()); } buf.append("]"); buf.append(sep); return buf.toString(); } private void appendObject(StringBuffer buf, String sep, String name, String value) { String indent = " "; buf.append(indent); buf.append(name); buf.append(":"); buf.append(sep); buf.append(indent); buf.append(indent); buf.append(value); buf.append(sep); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java0000644000175000017500000000614011026315632023530 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; /** * The extendedKeyUsage object. *
       *      extendedKeyUsage ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
       * 
      */ public class ExtendedKeyUsage extends ASN1Encodable { Hashtable usageTable = new Hashtable(); ASN1Sequence seq; public static ExtendedKeyUsage getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static ExtendedKeyUsage getInstance( Object obj) { if (obj instanceof ExtendedKeyUsage) { return (ExtendedKeyUsage)obj; } if(obj instanceof ASN1Sequence) { return new ExtendedKeyUsage((ASN1Sequence)obj); } if (obj instanceof X509Extension) { return getInstance(X509Extension.convertValueToObject((X509Extension)obj)); } throw new IllegalArgumentException("Invalid ExtendedKeyUsage: " + obj.getClass().getName()); } public ExtendedKeyUsage( KeyPurposeId usage) { this.seq = new DERSequence(usage); this.usageTable.put(usage, usage); } public ExtendedKeyUsage( ASN1Sequence seq) { this.seq = seq; Enumeration e = seq.getObjects(); while (e.hasMoreElements()) { Object o = e.nextElement(); if (!(o instanceof DERObjectIdentifier)) { throw new IllegalArgumentException("Only DERObjectIdentifiers allowed in ExtendedKeyUsage."); } this.usageTable.put(o, o); } } public ExtendedKeyUsage( Vector usages) { ASN1EncodableVector v = new ASN1EncodableVector(); Enumeration e = usages.elements(); while (e.hasMoreElements()) { DERObject o = (DERObject)e.nextElement(); v.add(o); this.usageTable.put(o, o); } this.seq = new DERSequence(v); } public boolean hasKeyPurposeId( KeyPurposeId keyPurposeId) { return (usageTable.get(keyPurposeId) != null); } /** * Returns all extended key usages. * The returned vector contains DERObjectIdentifiers. * @return A vector with all key purposes. */ public Vector getUsages() { Vector temp = new Vector(); for (Enumeration it = usageTable.elements(); it.hasMoreElements();) { temp.addElement(it.nextElement()); } return temp; } public int size() { return usageTable.size(); } public DERObject toASN1Object() { return seq; } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/PolicyQualifierId.java0000644000175000017500000000152011026315626023710 0ustar adrianadrian package org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.DERObjectIdentifier; /** * PolicyQualifierId, used in the CertificatePolicies * X509V3 extension. * *
       *    id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }
       *    id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
       *    id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
       *  PolicyQualifierId ::=
       *       OBJECT IDENTIFIER (id-qt-cps | id-qt-unotice)
       * 
      */ public class PolicyQualifierId extends DERObjectIdentifier { private static final String id_qt = "1.3.6.1.5.5.7.2"; private PolicyQualifierId(String id) { super(id); } public static final PolicyQualifierId id_qt_cps = new PolicyQualifierId(id_qt + ".1"); public static final PolicyQualifierId id_qt_unotice = new PolicyQualifierId(id_qt + ".2"); } azureus-4.3.0.6/org/bouncycastle/asn1/x509/BasicConstraints.java0000644000175000017500000001070511026315670023607 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBoolean; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import java.math.BigInteger; public class BasicConstraints extends ASN1Encodable { DERBoolean cA = new DERBoolean(false); DERInteger pathLenConstraint = null; public static BasicConstraints getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static BasicConstraints getInstance( Object obj) { if (obj == null || obj instanceof BasicConstraints) { return (BasicConstraints)obj; } if (obj instanceof ASN1Sequence) { return new BasicConstraints((ASN1Sequence)obj); } if (obj instanceof X509Extension) { return getInstance(X509Extension.convertValueToObject((X509Extension)obj)); } throw new IllegalArgumentException("unknown object in factory"); } public BasicConstraints( ASN1Sequence seq) { if (seq.size() == 0) { this.cA = null; this.pathLenConstraint = null; } else { if (seq.getObjectAt(0) instanceof DERBoolean) { this.cA = DERBoolean.getInstance(seq.getObjectAt(0)); } else { this.cA = null; this.pathLenConstraint = DERInteger.getInstance(seq.getObjectAt(0)); } if (seq.size() > 1) { if (this.cA != null) { this.pathLenConstraint = DERInteger.getInstance(seq.getObjectAt(1)); } else { throw new IllegalArgumentException("wrong sequence in constructor"); } } } } /** * @deprecated use one of the other two unambigous constructors. * @param cA * @param pathLenConstraint */ public BasicConstraints( boolean cA, int pathLenConstraint) { if (cA) { this.cA = new DERBoolean(cA); this.pathLenConstraint = new DERInteger(pathLenConstraint); } else { this.cA = null; this.pathLenConstraint = null; } } public BasicConstraints( boolean cA) { if (cA) { this.cA = new DERBoolean(true); } else { this.cA = null; } this.pathLenConstraint = null; } /** * create a cA=true object for the given path length constraint. * * @param pathLenConstraint */ public BasicConstraints( int pathLenConstraint) { this.cA = new DERBoolean(true); this.pathLenConstraint = new DERInteger(pathLenConstraint); } public boolean isCA() { return (cA != null) && cA.isTrue(); } public BigInteger getPathLenConstraint() { if (pathLenConstraint != null) { return pathLenConstraint.getValue(); } return null; } /** * Produce an object suitable for an ASN1OutputStream. *
           * BasicConstraints := SEQUENCE {
           *    cA                  BOOLEAN DEFAULT FALSE,
           *    pathLenConstraint   INTEGER (0..MAX) OPTIONAL
           * }
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); if (cA != null) { v.add(cA); } if (pathLenConstraint != null) // yes some people actually do this when cA is false... { v.add(pathLenConstraint); } return new DERSequence(v); } public String toString() { if (pathLenConstraint == null) { if (cA == null) { return "BasicConstraints: isCa(false)"; } return "BasicConstraints: isCa(" + this.isCA() + ")"; } return "BasicConstraints: isCa(" + this.isCA() + "), pathLenConstraint = " + pathLenConstraint.getValue(); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/package.html0000644000175000017500000000016710061400650021744 0ustar adrianadrian Support classes useful for encoding and processing X.509 certificates. azureus-4.3.0.6/org/bouncycastle/asn1/x509/V1TBSCertificateGenerator.java0000644000175000017500000000611411026315636025210 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.DERUTCTime; /** * Generator for Version 1 TBSCertificateStructures. *
       * TBSCertificate ::= SEQUENCE {
       *      version          [ 0 ]  Version DEFAULT v1(0),
       *      serialNumber            CertificateSerialNumber,
       *      signature               AlgorithmIdentifier,
       *      issuer                  Name,
       *      validity                Validity,
       *      subject                 Name,
       *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
       *      }
       * 
      * */ public class V1TBSCertificateGenerator { DERTaggedObject version = new DERTaggedObject(0, new DERInteger(0)); DERInteger serialNumber; AlgorithmIdentifier signature; X509Name issuer; Time startDate, endDate; X509Name subject; SubjectPublicKeyInfo subjectPublicKeyInfo; public V1TBSCertificateGenerator() { } public void setSerialNumber( DERInteger serialNumber) { this.serialNumber = serialNumber; } public void setSignature( AlgorithmIdentifier signature) { this.signature = signature; } public void setIssuer( X509Name issuer) { this.issuer = issuer; } public void setStartDate( Time startDate) { this.startDate = startDate; } public void setStartDate( DERUTCTime startDate) { this.startDate = new Time(startDate); } public void setEndDate( Time endDate) { this.endDate = endDate; } public void setEndDate( DERUTCTime endDate) { this.endDate = new Time(endDate); } public void setSubject( X509Name subject) { this.subject = subject; } public void setSubjectPublicKeyInfo( SubjectPublicKeyInfo pubKeyInfo) { this.subjectPublicKeyInfo = pubKeyInfo; } public TBSCertificateStructure generateTBSCertificate() { if ((serialNumber == null) || (signature == null) || (issuer == null) || (startDate == null) || (endDate == null) || (subject == null) || (subjectPublicKeyInfo == null)) { throw new IllegalStateException("not all mandatory fields set in V1 TBScertificate generator"); } ASN1EncodableVector seq = new ASN1EncodableVector(); // seq.add(version); - not required as default value. seq.add(serialNumber); seq.add(signature); seq.add(issuer); // // before and after dates // ASN1EncodableVector validity = new ASN1EncodableVector(); validity.add(startDate); validity.add(endDate); seq.add(new DERSequence(validity)); seq.add(subject); seq.add(subjectPublicKeyInfo); return new TBSCertificateStructure(new DERSequence(seq)); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/UserNotice.java0000644000175000017500000000603311026315626022416 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; /** * UserNotice class, used in * CertificatePolicies X509 extensions (in policy * qualifiers). *
       * UserNotice ::= SEQUENCE {
       *      noticeRef        NoticeReference OPTIONAL,
       *      explicitText     DisplayText OPTIONAL}
       *
       * 
      * * @see PolicyQualifierId * @see PolicyInformation */ public class UserNotice extends ASN1Encodable { private NoticeReference noticeRef; private DisplayText explicitText; /** * Creates a new UserNotice instance. * * @param noticeRef a NoticeReference value * @param explicitText a DisplayText value */ public UserNotice( NoticeReference noticeRef, DisplayText explicitText) { this.noticeRef = noticeRef; this.explicitText = explicitText; } /** * Creates a new UserNotice instance. * * @param noticeRef a NoticeReference value * @param str the explicitText field as a String. */ public UserNotice( NoticeReference noticeRef, String str) { this.noticeRef = noticeRef; this.explicitText = new DisplayText(str); } /** * Creates a new UserNotice instance. *

      Useful from reconstructing a UserNotice instance * from its encodable/encoded form. * * @param as an ASN1Sequence value obtained from either * calling @{link toASN1Object()} for a UserNotice * instance or from parsing it from a DER-encoded stream. */ public UserNotice( ASN1Sequence as) { if (as.size() == 2) { noticeRef = NoticeReference.getInstance(as.getObjectAt(0)); explicitText = DisplayText.getInstance(as.getObjectAt(1)); } else if (as.size() == 1) { if (as.getObjectAt(0).getDERObject() instanceof ASN1Sequence) { noticeRef = NoticeReference.getInstance(as.getObjectAt(0)); } else { explicitText = DisplayText.getInstance(as.getObjectAt(0)); } } else { throw new IllegalArgumentException("Bad sequence size: " + as.size()); } } public NoticeReference getNoticeRef() { return noticeRef; } public DisplayText getExplicitText() { return explicitText; } public DERObject toASN1Object() { ASN1EncodableVector av = new ASN1EncodableVector(); if (noticeRef != null) { av.add(noticeRef); } if (explicitText != null) { av.add(explicitText); } return new DERSequence(av); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java0000644000175000017500000001720211026315640025365 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBoolean; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; /** *

       * IssuingDistributionPoint ::= SEQUENCE { 
       *   distributionPoint          [0] DistributionPointName OPTIONAL, 
       *   onlyContainsUserCerts      [1] BOOLEAN DEFAULT FALSE, 
       *   onlyContainsCACerts        [2] BOOLEAN DEFAULT FALSE, 
       *   onlySomeReasons            [3] ReasonFlags OPTIONAL, 
       *   indirectCRL                [4] BOOLEAN DEFAULT FALSE,
       *   onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
       * 
      */ public class IssuingDistributionPoint extends ASN1Encodable { private DistributionPointName distributionPoint; private boolean onlyContainsUserCerts; private boolean onlyContainsCACerts; private ReasonFlags onlySomeReasons; private boolean indirectCRL; private boolean onlyContainsAttributeCerts; private ASN1Sequence seq; public static IssuingDistributionPoint getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static IssuingDistributionPoint getInstance( Object obj) { if (obj == null || obj instanceof IssuingDistributionPoint) { return (IssuingDistributionPoint)obj; } else if (obj instanceof ASN1Sequence) { return new IssuingDistributionPoint((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } /** * Constructor from given details. * * @param distributionPoint * May contain an URI as pointer to most current CRL. * @param onlyContainsUserCerts Covers revocation information for end certificates. * @param onlyContainsCACerts Covers revocation information for CA certificates. * * @param onlySomeReasons * Which revocation reasons does this point cover. * @param indirectCRL * If true then the CRL contains revocation * information about certificates ssued by other CAs. * @param onlyContainsAttributeCerts Covers revocation information for attribute certificates. */ public IssuingDistributionPoint( DistributionPointName distributionPoint, boolean onlyContainsUserCerts, boolean onlyContainsCACerts, ReasonFlags onlySomeReasons, boolean indirectCRL, boolean onlyContainsAttributeCerts) { this.distributionPoint = distributionPoint; this.indirectCRL = indirectCRL; this.onlyContainsAttributeCerts = onlyContainsAttributeCerts; this.onlyContainsCACerts = onlyContainsCACerts; this.onlyContainsUserCerts = onlyContainsUserCerts; this.onlySomeReasons = onlySomeReasons; ASN1EncodableVector vec = new ASN1EncodableVector(); if (distributionPoint != null) { // CHOICE item so explicitly tagged vec.add(new DERTaggedObject(true, 0, distributionPoint)); } if (!onlyContainsUserCerts) { vec.add(new DERTaggedObject(false, 1, new DERBoolean(true))); } if (!onlyContainsCACerts) { vec.add(new DERTaggedObject(false, 2, new DERBoolean(true))); } if (onlySomeReasons != null) { vec.add(new DERTaggedObject(false, 3, onlySomeReasons)); } if (!indirectCRL) { vec.add(new DERTaggedObject(false, 4, new DERBoolean(true))); } if (!onlyContainsAttributeCerts) { vec.add(new DERTaggedObject(false, 5, new DERBoolean(true))); } seq = new DERSequence(vec); } /** * Constructor from ASN1Sequence */ public IssuingDistributionPoint( ASN1Sequence seq) { this.seq = seq; for (int i = 0; i != seq.size(); i++) { ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(i)); switch (o.getTagNo()) { case 0: // CHOICE so explicit distributionPoint = DistributionPointName.getInstance(o, true); break; case 1: onlyContainsUserCerts = DERBoolean.getInstance(o, false).isTrue(); break; case 2: onlyContainsCACerts = DERBoolean.getInstance(o, false).isTrue(); break; case 3: onlySomeReasons = new ReasonFlags(ReasonFlags.getInstance(o, false)); break; case 4: indirectCRL = DERBoolean.getInstance(o, false).isTrue(); break; case 5: onlyContainsAttributeCerts = DERBoolean.getInstance(o, false).isTrue(); break; default: throw new IllegalArgumentException( "unknown tag in IssuingDistributionPoint"); } } } public boolean onlyContainsUserCerts() { return onlyContainsUserCerts; } public boolean onlyContainsCACerts() { return onlyContainsCACerts; } public boolean isIndirectCRL() { return indirectCRL; } public boolean onlyContainsAttributeCerts() { return onlyContainsAttributeCerts; } /** * @return Returns the distributionPoint. */ public DistributionPointName getDistributionPoint() { return distributionPoint; } /** * @return Returns the onlySomeReasons. */ public ReasonFlags getOnlySomeReasons() { return onlySomeReasons; } public DERObject toASN1Object() { return seq; } public String toString() { String sep = System.getProperty("line.separator"); StringBuffer buf = new StringBuffer(); buf.append("IssuingDistributionPoint: ["); buf.append(sep); if (distributionPoint != null) { appendObject(buf, sep, "distributionPoint", distributionPoint.toString()); } if (onlyContainsUserCerts) { appendObject(buf, sep, "onlyContainsUserCerts", booleanToString(onlyContainsUserCerts)); } if (onlyContainsCACerts) { appendObject(buf, sep, "onlyContainsCACerts", booleanToString(onlyContainsCACerts)); } if (onlySomeReasons != null) { appendObject(buf, sep, "onlySomeReasons", onlySomeReasons.toString()); } if (onlyContainsAttributeCerts) { appendObject(buf, sep, "onlyContainsAttributeCerts", booleanToString(onlyContainsAttributeCerts)); } if (indirectCRL) { appendObject(buf, sep, "indirectCRL", booleanToString(indirectCRL)); } buf.append("]"); buf.append(sep); return buf.toString(); } private void appendObject(StringBuffer buf, String sep, String name, String value) { String indent = " "; buf.append(indent); buf.append(name); buf.append(":"); buf.append(sep); buf.append(indent); buf.append(indent); buf.append(value); buf.append(sep); } private String booleanToString(boolean value) { return value ? "true" : "false"; } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/CertificatePolicies.java0000644000175000017500000000752411026315636024257 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import java.util.Enumeration; import java.util.Vector; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; public class CertificatePolicies extends ASN1Encodable { static final DERObjectIdentifier anyPolicy = new DERObjectIdentifier("2.5.29.32.0"); Vector policies = new Vector(); /** * @deprecated use an ASN1Sequence of PolicyInformation */ public static CertificatePolicies getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } /** * @deprecated use an ASN1Sequence of PolicyInformation */ public static CertificatePolicies getInstance( Object obj) { if (obj instanceof CertificatePolicies) { return (CertificatePolicies)obj; } else if (obj instanceof ASN1Sequence) { return new CertificatePolicies((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } /** * @deprecated use an ASN1Sequence of PolicyInformation */ public CertificatePolicies( ASN1Sequence seq) { Enumeration e = seq.getObjects(); while (e.hasMoreElements()) { ASN1Sequence s = ASN1Sequence.getInstance(e.nextElement()); policies.addElement(s.getObjectAt(0)); } // For now we just don't handle PolicyQualifiers } /** * create a certificate policy with the given OID. * @deprecated use an ASN1Sequence of PolicyInformation */ public CertificatePolicies( DERObjectIdentifier p) { policies.addElement(p); } /** * create a certificate policy with the policy given by the OID represented * by the string p. * @deprecated use an ASN1Sequence of PolicyInformation */ public CertificatePolicies( String p) { this(new DERObjectIdentifier(p)); } public void addPolicy( String p) { policies.addElement(new DERObjectIdentifier(p)); } public String getPolicy(int nr) { if (policies.size() > nr) { return ((DERObjectIdentifier)policies.elementAt(nr)).getId(); } return null; } /** *
           * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
           *
           * PolicyInformation ::= SEQUENCE {
           *   policyIdentifier   CertPolicyId,
           *   policyQualifiers   SEQUENCE SIZE (1..MAX) OF
           *                           PolicyQualifierInfo OPTIONAL }
           *
           * CertPolicyId ::= OBJECT IDENTIFIER
           *
           * PolicyQualifierInfo ::= SEQUENCE {
           *   policyQualifierId  PolicyQualifierId,
           *   qualifier          ANY DEFINED BY policyQualifierId }
           *
           * PolicyQualifierId ::=
           *   OBJECT IDENTIFIER (id-qt-cps | id-qt-unotice)
           * 
      * @deprecated use an ASN1Sequence of PolicyInformation */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); // We only do policyIdentifier yet... for (int i=0;i * CRLNumber::= INTEGER(0..MAX) * */ public class CRLNumber extends DERInteger { public CRLNumber( BigInteger number) { super(number); } public BigInteger getCRLNumber() { return getPositiveValue(); } public String toString() { return "CRLNumber: " + getCRLNumber(); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/V2Form.java0000644000175000017500000000656011026315644021456 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; public class V2Form extends ASN1Encodable { GeneralNames issuerName; IssuerSerial baseCertificateID; ObjectDigestInfo objectDigestInfo; public static V2Form getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static V2Form getInstance( Object obj) { if (obj == null || obj instanceof V2Form) { return (V2Form)obj; } else if (obj instanceof ASN1Sequence) { return new V2Form((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public V2Form( GeneralNames issuerName) { this.issuerName = issuerName; } public V2Form( ASN1Sequence seq) { if (seq.size() > 3) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } int index = 0; if (!(seq.getObjectAt(0) instanceof ASN1TaggedObject)) { index++; this.issuerName = GeneralNames.getInstance(seq.getObjectAt(0)); } for (int i = index; i != seq.size(); i++) { ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(i)); if (o.getTagNo() == 0) { baseCertificateID = IssuerSerial.getInstance(o, false); } else if (o.getTagNo() == 1) { objectDigestInfo = ObjectDigestInfo.getInstance(o, false); } else { throw new IllegalArgumentException("Bad tag number: " + o.getTagNo()); } } } public GeneralNames getIssuerName() { return issuerName; } public IssuerSerial getBaseCertificateID() { return baseCertificateID; } public ObjectDigestInfo getObjectDigestInfo() { return objectDigestInfo; } /** * Produce an object suitable for an ASN1OutputStream. *
           *  V2Form ::= SEQUENCE {
           *       issuerName            GeneralNames  OPTIONAL,
           *       baseCertificateID     [0] IssuerSerial  OPTIONAL,
           *       objectDigestInfo      [1] ObjectDigestInfo  OPTIONAL
           *         -- issuerName MUST be present in this profile
           *         -- baseCertificateID and objectDigestInfo MUST NOT
           *         -- be present in this profile
           *  }
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); if (issuerName != null) { v.add(issuerName); } if (baseCertificateID != null) { v.add(new DERTaggedObject(false, 0, baseCertificateID)); } if (objectDigestInfo != null) { v.add(new DERTaggedObject(false, 1, objectDigestInfo)); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java0000644000175000017500000000771011026315636025215 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.DERUTCTime; /** * Generator for Version 3 TBSCertificateStructures. *
       * TBSCertificate ::= SEQUENCE {
       *      version          [ 0 ]  Version DEFAULT v1(0),
       *      serialNumber            CertificateSerialNumber,
       *      signature               AlgorithmIdentifier,
       *      issuer                  Name,
       *      validity                Validity,
       *      subject                 Name,
       *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
       *      issuerUniqueID    [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
       *      subjectUniqueID   [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
       *      extensions        [ 3 ] Extensions OPTIONAL
       *      }
       * 
      * */ public class V3TBSCertificateGenerator { DERTaggedObject version = new DERTaggedObject(0, new DERInteger(2)); DERInteger serialNumber; AlgorithmIdentifier signature; X509Name issuer; Time startDate, endDate; X509Name subject; SubjectPublicKeyInfo subjectPublicKeyInfo; X509Extensions extensions; private boolean altNamePresentAndCritical; public V3TBSCertificateGenerator() { } public void setSerialNumber( DERInteger serialNumber) { this.serialNumber = serialNumber; } public void setSignature( AlgorithmIdentifier signature) { this.signature = signature; } public void setIssuer( X509Name issuer) { this.issuer = issuer; } public void setStartDate( DERUTCTime startDate) { this.startDate = new Time(startDate); } public void setStartDate( Time startDate) { this.startDate = startDate; } public void setEndDate( DERUTCTime endDate) { this.endDate = new Time(endDate); } public void setEndDate( Time endDate) { this.endDate = endDate; } public void setSubject( X509Name subject) { this.subject = subject; } public void setSubjectPublicKeyInfo( SubjectPublicKeyInfo pubKeyInfo) { this.subjectPublicKeyInfo = pubKeyInfo; } public void setExtensions( X509Extensions extensions) { this.extensions = extensions; if (extensions != null) { X509Extension altName = extensions.getExtension(X509Extensions.SubjectAlternativeName); if (altName != null && altName.isCritical()) { altNamePresentAndCritical = true; } } } public TBSCertificateStructure generateTBSCertificate() { if ((serialNumber == null) || (signature == null) || (issuer == null) || (startDate == null) || (endDate == null) || (subject == null && !altNamePresentAndCritical) || (subjectPublicKeyInfo == null)) { throw new IllegalStateException("not all mandatory fields set in V3 TBScertificate generator"); } ASN1EncodableVector v = new ASN1EncodableVector(); v.add(version); v.add(serialNumber); v.add(signature); v.add(issuer); // // before and after dates // ASN1EncodableVector validity = new ASN1EncodableVector(); validity.add(startDate); validity.add(endDate); v.add(new DERSequence(validity)); if (subject != null) { v.add(subject); } else { v.add(new DERSequence()); } v.add(subjectPublicKeyInfo); if (extensions != null) { v.add(new DERTaggedObject(3, extensions)); } return new TBSCertificateStructure(new DERSequence(v)); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/X509NameEntryConverter.java0000644000175000017500000000653111026315634024520 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERPrintableString; import org.bouncycastle.util.Strings; import java.io.IOException; /** * It turns out that the number of standard ways the fields in a DN should be * encoded into their ASN.1 counterparts is rapidly approaching the * number of machines on the internet. By default the X509Name class * will produce UTF8Strings in line with the current recommendations (RFC 3280). *

      * An example of an encoder look like below: *

       * public class X509DirEntryConverter
       *     extends X509NameEntryConverter
       * {
       *     public DERObject getConvertedValue(
       *         DERObjectIdentifier  oid,
       *         String               value)
       *     {
       *         if (str.length() != 0 && str.charAt(0) == '#')
       *         {
       *             return convertHexEncoded(str, 1);
       *         }
       *         if (oid.equals(EmailAddress))
       *         {
       *             return new DERIA5String(str);
       *         }
       *         else if (canBePrintable(str))
       *         {
       *             return new DERPrintableString(str);
       *         }
       *         else if (canBeUTF8(str))
       *         {
       *             return new DERUTF8String(str);
       *         }
       *         else
       *         {
       *             return new DERBMPString(str);
       *         }
       *     }
       * }
       */
      public abstract class X509NameEntryConverter
      {
          /**
           * Convert an inline encoded hex string rendition of an ASN.1
           * object back into its corresponding ASN.1 object.
           * 
           * @param str the hex encoded object
           * @param off the index at which the encoding starts
           * @return the decoded object
           */
          protected DERObject convertHexEncoded(
              String  str,
              int     off)
              throws IOException
          {
              str = Strings.toLowerCase(str);
              byte[] data = new byte[(str.length() - off) / 2];
              for (int index = 0; index != data.length; index++)
              {
                  char left = str.charAt((index * 2) + off);
                  char right = str.charAt((index * 2) + off + 1);
                  
                  if (left < 'a')
                  {
                      data[index] = (byte)((left - '0') << 4);
                  }
                  else
                  {
                      data[index] = (byte)((left - 'a' + 10) << 4);
                  }
                  if (right < 'a')
                  {
                      data[index] |= (byte)(right - '0');
                  }
                  else
                  {
                      data[index] |= (byte)(right - 'a' + 10);
                  }
              }
      
              ASN1InputStream aIn = new ASN1InputStream(data);
                                                  
              return aIn.readObject();
          }
          
          /**
           * return true if the passed in String can be represented without
           * loss as a PrintableString, false otherwise.
           */
          protected boolean canBePrintable(
              String  str)
          {
              return DERPrintableString.isPrintableString(str);
          }
          
          /**
           * Convert the passed in String value into the appropriate ASN.1
           * encoded object.
           * 
           * @param oid the oid associated with the value in the DN.
           * @param value the value of the particular DN component.
           * @return the ASN.1 equivalent for the value.
           */
          public abstract DERObject getConvertedValue(DERObjectIdentifier oid, String value);
      }
      azureus-4.3.0.6/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java0000644000175000017500000001356611026315634024527 0ustar  adrianadrianpackage org.bouncycastle.asn1.x509;
      
      import java.io.IOException;
      import java.util.Enumeration;
      import java.util.Vector;
      
      import org.bouncycastle.asn1.ASN1EncodableVector;
      import org.bouncycastle.asn1.ASN1Sequence;
      import org.bouncycastle.asn1.DERGeneralizedTime;
      import org.bouncycastle.asn1.DERInteger;
      import org.bouncycastle.asn1.DEROctetString;
      import org.bouncycastle.asn1.DERSequence;
      import org.bouncycastle.asn1.DERTaggedObject;
      import org.bouncycastle.asn1.DERUTCTime;
      
      /**
       * Generator for Version 2 TBSCertList structures.
       * 
       *  TBSCertList  ::=  SEQUENCE  {
       *       version                 Version OPTIONAL,
       *                                    -- if present, shall be v2
       *       signature               AlgorithmIdentifier,
       *       issuer                  Name,
       *       thisUpdate              Time,
       *       nextUpdate              Time OPTIONAL,
       *       revokedCertificates     SEQUENCE OF SEQUENCE  {
       *            userCertificate         CertificateSerialNumber,
       *            revocationDate          Time,
       *            crlEntryExtensions      Extensions OPTIONAL
       *                                          -- if present, shall be v2
       *                                 }  OPTIONAL,
       *       crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
       *                                          -- if present, shall be v2
       *                                 }
       * 
      * * Note: This class may be subject to change */ public class V2TBSCertListGenerator { DERInteger version = new DERInteger(1); AlgorithmIdentifier signature; X509Name issuer; Time thisUpdate, nextUpdate=null; X509Extensions extensions=null; private Vector crlentries=null; public V2TBSCertListGenerator() { } public void setSignature( AlgorithmIdentifier signature) { this.signature = signature; } public void setIssuer( X509Name issuer) { this.issuer = issuer; } public void setThisUpdate( DERUTCTime thisUpdate) { this.thisUpdate = new Time(thisUpdate); } public void setNextUpdate( DERUTCTime nextUpdate) { this.nextUpdate = new Time(nextUpdate); } public void setThisUpdate( Time thisUpdate) { this.thisUpdate = thisUpdate; } public void setNextUpdate( Time nextUpdate) { this.nextUpdate = nextUpdate; } public void addCRLEntry( ASN1Sequence crlEntry) { if (crlentries == null) { crlentries = new Vector(); } crlentries.addElement(crlEntry); } public void addCRLEntry(DERInteger userCertificate, DERUTCTime revocationDate, int reason) { addCRLEntry(userCertificate, new Time(revocationDate), reason); } public void addCRLEntry(DERInteger userCertificate, Time revocationDate, int reason) { addCRLEntry(userCertificate, revocationDate, reason, null); } public void addCRLEntry(DERInteger userCertificate, Time revocationDate, int reason, DERGeneralizedTime invalidityDate) { Vector extOids = new Vector(); Vector extValues = new Vector(); if (reason != 0) { CRLReason crlReason = new CRLReason(reason); try { extOids.addElement(X509Extensions.ReasonCode); extValues.addElement(new X509Extension(false, new DEROctetString(crlReason.getEncoded()))); } catch (IOException e) { throw new IllegalArgumentException("error encoding reason: " + e); } } if (invalidityDate != null) { try { extOids.addElement(X509Extensions.InvalidityDate); extValues.addElement(new X509Extension(false, new DEROctetString(invalidityDate.getEncoded()))); } catch (IOException e) { throw new IllegalArgumentException("error encoding invalidityDate: " + e); } } if (extOids.size() != 0) { addCRLEntry(userCertificate, revocationDate, new X509Extensions(extOids, extValues)); } else { addCRLEntry(userCertificate, revocationDate, null); } } public void addCRLEntry(DERInteger userCertificate, Time revocationDate, X509Extensions extensions) { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(userCertificate); v.add(revocationDate); if (extensions != null) { v.add(extensions); } addCRLEntry(new DERSequence(v)); } public void setExtensions( X509Extensions extensions) { this.extensions = extensions; } public TBSCertList generateTBSCertList() { if ((signature == null) || (issuer == null) || (thisUpdate == null)) { throw new IllegalStateException("Not all mandatory fields set in V2 TBSCertList generator."); } ASN1EncodableVector v = new ASN1EncodableVector(); v.add(version); v.add(signature); v.add(issuer); v.add(thisUpdate); if (nextUpdate != null) { v.add(nextUpdate); } // Add CRLEntries if they exist if (crlentries != null) { ASN1EncodableVector certs = new ASN1EncodableVector(); Enumeration it = crlentries.elements(); while(it.hasMoreElements()) { certs.add((ASN1Sequence)it.nextElement()); } v.add(new DERSequence(certs)); } if (extensions != null) { v.add(new DERTaggedObject(0, extensions)); } return new TBSCertList(new DERSequence(v)); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/AttributeCertificate.java0000644000175000017500000000507111026315632024442 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; public class AttributeCertificate extends ASN1Encodable { AttributeCertificateInfo acinfo; AlgorithmIdentifier signatureAlgorithm; DERBitString signatureValue; /** * @param obj * @return an AttributeCertificate object */ public static AttributeCertificate getInstance(Object obj) { if (obj instanceof AttributeCertificate) { return (AttributeCertificate)obj; } else if (obj instanceof ASN1Sequence) { return new AttributeCertificate((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public AttributeCertificate( AttributeCertificateInfo acinfo, AlgorithmIdentifier signatureAlgorithm, DERBitString signatureValue) { this.acinfo = acinfo; this.signatureAlgorithm = signatureAlgorithm; this.signatureValue = signatureValue; } public AttributeCertificate( ASN1Sequence seq) { if (seq.size() != 3) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } this.acinfo = AttributeCertificateInfo.getInstance(seq.getObjectAt(0)); this.signatureAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1)); this.signatureValue = DERBitString.getInstance(seq.getObjectAt(2)); } public AttributeCertificateInfo getAcinfo() { return acinfo; } public AlgorithmIdentifier getSignatureAlgorithm() { return signatureAlgorithm; } public DERBitString getSignatureValue() { return signatureValue; } /** * Produce an object suitable for an ASN1OutputStream. *
           *  AttributeCertificate ::= SEQUENCE {
           *       acinfo               AttributeCertificateInfo,
           *       signatureAlgorithm   AlgorithmIdentifier,
           *       signatureValue       BIT STRING
           *  }
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(acinfo); v.add(signatureAlgorithm); v.add(signatureValue); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/AccessDescription.java0000644000175000017500000000504211026315632023737 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; /** * The AccessDescription object. *
       * AccessDescription  ::=  SEQUENCE {
       *       accessMethod          OBJECT IDENTIFIER,
       *       accessLocation        GeneralName  }
       * 
      */ public class AccessDescription extends ASN1Encodable { public final static DERObjectIdentifier id_ad_caIssuers = new DERObjectIdentifier("1.3.6.1.5.5.7.48.2"); public final static DERObjectIdentifier id_ad_ocsp = new DERObjectIdentifier("1.3.6.1.5.5.7.48.1"); DERObjectIdentifier accessMethod = null; GeneralName accessLocation = null; public static AccessDescription getInstance( Object obj) { if (obj instanceof AccessDescription) { return (AccessDescription)obj; } else if (obj instanceof ASN1Sequence) { return new AccessDescription((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public AccessDescription( ASN1Sequence seq) { if (seq.size() != 2) { throw new IllegalArgumentException("wrong number of elements in inner sequence"); } accessMethod = DERObjectIdentifier.getInstance(seq.getObjectAt(0)); accessLocation = GeneralName.getInstance(seq.getObjectAt(1)); } /** * create an AccessDescription with the oid and location provided. */ public AccessDescription( DERObjectIdentifier oid, GeneralName location) { accessMethod = oid; accessLocation = location; } /** * * @return the access method. */ public DERObjectIdentifier getAccessMethod() { return accessMethod; } /** * * @return the access location */ public GeneralName getAccessLocation() { return accessLocation; } public DERObject toASN1Object() { ASN1EncodableVector accessDescription = new ASN1EncodableVector(); accessDescription.add(accessMethod); accessDescription.add(accessLocation); return new DERSequence(accessDescription); } public String toString() { return ("AccessDescription: Oid(" + this.accessMethod.getId() + ")"); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java0000644000175000017500000001122211026315644025254 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; public class AttributeCertificateInfo extends ASN1Encodable { private DERInteger version; private Holder holder; private AttCertIssuer issuer; private AlgorithmIdentifier signature; private DERInteger serialNumber; private AttCertValidityPeriod attrCertValidityPeriod; private ASN1Sequence attributes; private DERBitString issuerUniqueID; private X509Extensions extensions; public static AttributeCertificateInfo getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static AttributeCertificateInfo getInstance( Object obj) { if (obj instanceof AttributeCertificateInfo) { return (AttributeCertificateInfo)obj; } else if (obj instanceof ASN1Sequence) { return new AttributeCertificateInfo((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public AttributeCertificateInfo( ASN1Sequence seq) { if (seq.size() < 7 || seq.size() > 9) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } this.version = DERInteger.getInstance(seq.getObjectAt(0)); this.holder = Holder.getInstance(seq.getObjectAt(1)); this.issuer = AttCertIssuer.getInstance(seq.getObjectAt(2)); this.signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(3)); this.serialNumber = DERInteger.getInstance(seq.getObjectAt(4)); this.attrCertValidityPeriod = AttCertValidityPeriod.getInstance(seq.getObjectAt(5)); this.attributes = ASN1Sequence.getInstance(seq.getObjectAt(6)); for (int i = 7; i < seq.size(); i++) { ASN1Encodable obj = (ASN1Encodable)seq.getObjectAt(i); if (obj instanceof DERBitString) { this.issuerUniqueID = DERBitString.getInstance(seq.getObjectAt(i)); } else if (obj instanceof ASN1Sequence || obj instanceof X509Extensions) { this.extensions = X509Extensions.getInstance(seq.getObjectAt(i)); } } } public DERInteger getVersion() { return version; } public Holder getHolder() { return holder; } public AttCertIssuer getIssuer() { return issuer; } public AlgorithmIdentifier getSignature() { return signature; } public DERInteger getSerialNumber() { return serialNumber; } public AttCertValidityPeriod getAttrCertValidityPeriod() { return attrCertValidityPeriod; } public ASN1Sequence getAttributes() { return attributes; } public DERBitString getIssuerUniqueID() { return issuerUniqueID; } public X509Extensions getExtensions() { return extensions; } /** * Produce an object suitable for an ASN1OutputStream. *
           *  AttributeCertificateInfo ::= SEQUENCE {
           *       version              AttCertVersion -- version is v2,
           *       holder               Holder,
           *       issuer               AttCertIssuer,
           *       signature            AlgorithmIdentifier,
           *       serialNumber         CertificateSerialNumber,
           *       attrCertValidityPeriod   AttCertValidityPeriod,
           *       attributes           SEQUENCE OF Attribute,
           *       issuerUniqueID       UniqueIdentifier OPTIONAL,
           *       extensions           Extensions OPTIONAL
           *  }
           *
           *  AttCertVersion ::= INTEGER { v2(1) }
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(version); v.add(holder); v.add(issuer); v.add(signature); v.add(serialNumber); v.add(attrCertValidityPeriod); v.add(attributes); if (issuerUniqueID != null) { v.add(issuerUniqueID); } if (extensions != null) { v.add(extensions); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/X509Attributes.java0000644000175000017500000000032611026315634023050 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.DERObjectIdentifier; public class X509Attributes { public static final DERObjectIdentifier RoleSyntax = new DERObjectIdentifier("2.5.4.72"); } azureus-4.3.0.6/org/bouncycastle/asn1/x509/Holder.java0000644000175000017500000001473011026315664021560 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; /** * The Holder object. *

      * For an v2 attribute certificate this is: * *

       *            Holder ::= SEQUENCE {
       *                  baseCertificateID   [0] IssuerSerial OPTIONAL,
       *                           -- the issuer and serial number of
       *                           -- the holder's Public Key Certificate
       *                  entityName          [1] GeneralNames OPTIONAL,
       *                           -- the name of the claimant or role
       *                  objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
       *                           -- used to directly authenticate the holder,
       *                           -- for example, an executable
       *            }
       * 
      * *

      * For an v1 attribute certificate this is: * *

       *         subject CHOICE {
       *          baseCertificateID [0] IssuerSerial,
       *          -- associated with a Public Key Certificate
       *          subjectName [1] GeneralNames },
       *          -- associated with a name
       * 
      */ public class Holder extends ASN1Encodable { IssuerSerial baseCertificateID; GeneralNames entityName; ObjectDigestInfo objectDigestInfo; private int version = 1; public static Holder getInstance(Object obj) { if (obj instanceof Holder) { return (Holder)obj; } else if (obj instanceof ASN1Sequence) { return new Holder((ASN1Sequence)obj); } else if (obj instanceof ASN1TaggedObject) { return new Holder((ASN1TaggedObject)obj); } throw new IllegalArgumentException("unknown object in factory"); } /** * Constructor for a holder for an v1 attribute certificate. * * @param tagObj The ASN.1 tagged holder object. */ public Holder(ASN1TaggedObject tagObj) { switch (tagObj.getTagNo()) { case 0: baseCertificateID = IssuerSerial.getInstance(tagObj, false); break; case 1: entityName = GeneralNames.getInstance(tagObj, false); break; default: throw new IllegalArgumentException("unknown tag in Holder"); } version = 0; } /** * Constructor for a holder for an v2 attribute certificate. * * * @param seq The ASN.1 sequence. */ public Holder(ASN1Sequence seq) { if (seq.size() > 3) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } for (int i = 0; i != seq.size(); i++) { ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(seq .getObjectAt(i)); switch (tObj.getTagNo()) { case 0: baseCertificateID = IssuerSerial.getInstance(tObj, false); break; case 1: entityName = GeneralNames.getInstance(tObj, false); break; case 2: objectDigestInfo = ObjectDigestInfo.getInstance(tObj, false); break; default: throw new IllegalArgumentException("unknown tag in Holder"); } } version = 1; } public Holder(IssuerSerial baseCertificateID) { this.baseCertificateID = baseCertificateID; } /** * Constructs a holder from a IssuerSerial. * @param baseCertificateID The IssuerSerial. * @param version The version of the attribute certificate. */ public Holder(IssuerSerial baseCertificateID, int version) { this.baseCertificateID = baseCertificateID; this.version = version; } /** * Returns 1 for v2 attribute certificates or 0 for v1 attribute * certificates. * @return The version of the attribute certificate. */ public int getVersion() { return version; } /** * Constructs a holder with an entityName for v2 attribute certificates or * with a subjectName for v1 attribute certificates. * * @param entityName The entity or subject name. */ public Holder(GeneralNames entityName) { this.entityName = entityName; } /** * Constructs a holder with an entityName for v2 attribute certificates or * with a subjectName for v1 attribute certificates. * * @param entityName The entity or subject name. * @param version The version of the attribute certificate. */ public Holder(GeneralNames entityName, int version) { this.entityName = entityName; this.version = version; } /** * Constructs a holder from an object digest info. * * @param objectDigestInfo The object digest info object. */ public Holder(ObjectDigestInfo objectDigestInfo) { this.objectDigestInfo = objectDigestInfo; } public IssuerSerial getBaseCertificateID() { return baseCertificateID; } /** * Returns the entityName for an v2 attribute certificate or the subjectName * for an v1 attribute certificate. * * @return The entityname or subjectname. */ public GeneralNames getEntityName() { return entityName; } public ObjectDigestInfo getObjectDigestInfo() { return objectDigestInfo; } public DERObject toASN1Object() { if (version == 1) { ASN1EncodableVector v = new ASN1EncodableVector(); if (baseCertificateID != null) { v.add(new DERTaggedObject(false, 0, baseCertificateID)); } if (entityName != null) { v.add(new DERTaggedObject(false, 1, entityName)); } if (objectDigestInfo != null) { v.add(new DERTaggedObject(false, 2, objectDigestInfo)); } return new DERSequence(v); } else { if (entityName != null) { return new DERTaggedObject(false, 1, entityName); } else { return new DERTaggedObject(false, 0, baseCertificateID); } } } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/RSAPublicKeyStructure.java0000644000175000017500000000473611026315642024522 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import java.math.BigInteger; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; public class RSAPublicKeyStructure extends ASN1Encodable { private BigInteger modulus; private BigInteger publicExponent; public static RSAPublicKeyStructure getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static RSAPublicKeyStructure getInstance( Object obj) { if(obj == null || obj instanceof RSAPublicKeyStructure) { return (RSAPublicKeyStructure)obj; } if(obj instanceof ASN1Sequence) { return new RSAPublicKeyStructure((ASN1Sequence)obj); } throw new IllegalArgumentException("Invalid RSAPublicKeyStructure: " + obj.getClass().getName()); } public RSAPublicKeyStructure( BigInteger modulus, BigInteger publicExponent) { this.modulus = modulus; this.publicExponent = publicExponent; } public RSAPublicKeyStructure( ASN1Sequence seq) { if (seq.size() != 2) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } Enumeration e = seq.getObjects(); modulus = DERInteger.getInstance(e.nextElement()).getPositiveValue(); publicExponent = DERInteger.getInstance(e.nextElement()).getPositiveValue(); } public BigInteger getModulus() { return modulus; } public BigInteger getPublicExponent() { return publicExponent; } /** * This outputs the key in PKCS1v2 format. *
           *      RSAPublicKey ::= SEQUENCE {
           *                          modulus INTEGER, -- n
           *                          publicExponent INTEGER, -- e
           *                      }
           * 
      *

      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new DERInteger(getModulus())); v.add(new DERInteger(getPublicExponent())); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/NoticeReference.java0000644000175000017500000000771111026315644023402 0ustar adrianadrian package org.bouncycastle.asn1.x509; import java.util.Enumeration; import java.util.Vector; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; /** * NoticeReference class, used in * CertificatePolicies X509 V3 extensions * (in policy qualifiers). * *

       *  NoticeReference ::= SEQUENCE {
       *      organization     DisplayText,
       *      noticeNumbers    SEQUENCE OF INTEGER }
       *
       * 
      * * @see PolicyQualifierInfo * @see PolicyInformation */ public class NoticeReference extends ASN1Encodable { private DisplayText organization; private ASN1Sequence noticeNumbers; /** * Creates a new NoticeReference instance. * * @param orgName a String value * @param numbers a Vector value */ public NoticeReference( String orgName, Vector numbers) { organization = new DisplayText(orgName); Object o = numbers.elementAt(0); ASN1EncodableVector av = new ASN1EncodableVector(); if (o instanceof Integer) { Enumeration it = numbers.elements(); while (it.hasMoreElements()) { Integer nm = (Integer) it.nextElement(); DERInteger di = new DERInteger(nm.intValue()); av.add (di); } } noticeNumbers = new DERSequence(av); } /** * Creates a new NoticeReference instance. * * @param orgName a String value * @param numbers an ASN1EncodableVector value */ public NoticeReference( String orgName, ASN1Sequence numbers) { organization = new DisplayText (orgName); noticeNumbers = numbers; } /** * Creates a new NoticeReference instance. * * @param displayTextType an int value * @param orgName a String value * @param numbers an ASN1EncodableVector value */ public NoticeReference( int displayTextType, String orgName, ASN1Sequence numbers) { organization = new DisplayText(displayTextType, orgName); noticeNumbers = numbers; } /** * Creates a new NoticeReference instance. *

      Useful for reconstructing a NoticeReference * instance from its encodable/encoded form. * * @param as an ASN1Sequence value obtained from either * calling @{link toASN1Object()} for a NoticeReference * instance or from parsing it from a DER-encoded stream. */ public NoticeReference( ASN1Sequence as) { if (as.size() != 2) { throw new IllegalArgumentException("Bad sequence size: " + as.size()); } organization = DisplayText.getInstance(as.getObjectAt(0)); noticeNumbers = ASN1Sequence.getInstance(as.getObjectAt(1)); } public static NoticeReference getInstance( Object as) { if (as instanceof NoticeReference) { return (NoticeReference)as; } else if (as instanceof ASN1Sequence) { return new NoticeReference((ASN1Sequence)as); } throw new IllegalArgumentException("unknown object in getInstance."); } public DisplayText getOrganization() { return organization; } public ASN1Sequence getNoticeNumbers() { return noticeNumbers; } /** * Describe toASN1Object method here. * * @return a DERObject value */ public DERObject toASN1Object() { ASN1EncodableVector av = new ASN1EncodableVector(); av.add (organization); av.add (noticeNumbers); return new DERSequence (av); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java0000644000175000017500000000501511026315630024312 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.DERObjectIdentifier; public interface X509ObjectIdentifiers { // // base id // static final String id = "2.5.4"; static final DERObjectIdentifier commonName = new DERObjectIdentifier(id + ".3"); static final DERObjectIdentifier countryName = new DERObjectIdentifier(id + ".6"); static final DERObjectIdentifier localityName = new DERObjectIdentifier(id + ".7"); static final DERObjectIdentifier stateOrProvinceName = new DERObjectIdentifier(id + ".8"); static final DERObjectIdentifier organization = new DERObjectIdentifier(id + ".10"); static final DERObjectIdentifier organizationalUnitName = new DERObjectIdentifier(id + ".11"); // id-SHA1 OBJECT IDENTIFIER ::= // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } // static final DERObjectIdentifier id_SHA1 = new DERObjectIdentifier("1.3.14.3.2.26"); // // ripemd160 OBJECT IDENTIFIER ::= // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) hashAlgorithm(2) RIPEMD-160(1)} // static final DERObjectIdentifier ripemd160 = new DERObjectIdentifier("1.3.36.3.2.1"); // // ripemd160WithRSAEncryption OBJECT IDENTIFIER ::= // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) rsaSignatureWithripemd160(2) } // static final DERObjectIdentifier ripemd160WithRSAEncryption = new DERObjectIdentifier("1.3.36.3.3.1.2"); static final DERObjectIdentifier id_ea_rsa = new DERObjectIdentifier("2.5.8.1.1"); // id-pkix static final DERObjectIdentifier id_pkix = new DERObjectIdentifier("1.3.6.1.5.5.7"); // // private internet extensions // static final DERObjectIdentifier id_pe = new DERObjectIdentifier(id_pkix + ".1"); // // authority information access // static final DERObjectIdentifier id_ad = new DERObjectIdentifier(id_pkix + ".48"); static final DERObjectIdentifier id_ad_caIssuers = new DERObjectIdentifier(id_ad + ".2"); static final DERObjectIdentifier id_ad_ocsp = new DERObjectIdentifier(id_ad + ".1"); // // OID for ocsp and crl uri in AuthorityInformationAccess extension // static final DERObjectIdentifier ocspAccessMethod = id_ad_ocsp; static final DERObjectIdentifier crlAccessMethod = id_ad_caIssuers; } azureus-4.3.0.6/org/bouncycastle/asn1/x509/DigestInfo.java0000644000175000017500000000402611026315642022367 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; /** * The DigestInfo object. *

       * DigestInfo::=SEQUENCE{
       *          digestAlgorithm  AlgorithmIdentifier,
       *          digest OCTET STRING }
       * 
      */ public class DigestInfo extends ASN1Encodable { private byte[] digest; private AlgorithmIdentifier algId; public static DigestInfo getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static DigestInfo getInstance( Object obj) { if (obj instanceof DigestInfo) { return (DigestInfo)obj; } else if (obj instanceof ASN1Sequence) { return new DigestInfo((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public DigestInfo( AlgorithmIdentifier algId, byte[] digest) { this.digest = digest; this.algId = algId; } public DigestInfo( ASN1Sequence obj) { Enumeration e = obj.getObjects(); algId = AlgorithmIdentifier.getInstance(e.nextElement()); digest = ASN1OctetString.getInstance(e.nextElement()).getOctets(); } public AlgorithmIdentifier getAlgorithmId() { return algId; } public byte[] getDigest() { return digest; } public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(algId); v.add(new DEROctetString(digest)); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/TBSCertificateStructure.java0000644000175000017500000001215011026315670025046 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; /** * The TBSCertificate object. *
       * TBSCertificate ::= SEQUENCE {
       *      version          [ 0 ]  Version DEFAULT v1(0),
       *      serialNumber            CertificateSerialNumber,
       *      signature               AlgorithmIdentifier,
       *      issuer                  Name,
       *      validity                Validity,
       *      subject                 Name,
       *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
       *      issuerUniqueID    [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
       *      subjectUniqueID   [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
       *      extensions        [ 3 ] Extensions OPTIONAL
       *      }
       * 
      *

      * Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class * will parse them, but you really shouldn't be creating new ones. */ public class TBSCertificateStructure extends ASN1Encodable implements X509ObjectIdentifiers, PKCSObjectIdentifiers { ASN1Sequence seq; DERInteger version; DERInteger serialNumber; AlgorithmIdentifier signature; X509Name issuer; Time startDate, endDate; X509Name subject; SubjectPublicKeyInfo subjectPublicKeyInfo; DERBitString issuerUniqueId; DERBitString subjectUniqueId; X509Extensions extensions; public static TBSCertificateStructure getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static TBSCertificateStructure getInstance( Object obj) { if (obj instanceof TBSCertificateStructure) { return (TBSCertificateStructure)obj; } else if (obj instanceof ASN1Sequence) { return new TBSCertificateStructure((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public TBSCertificateStructure( ASN1Sequence seq) { int seqStart = 0; this.seq = seq; // // some certficates don't include a version number - we assume v1 // if (seq.getObjectAt(0) instanceof DERTaggedObject) { version = DERInteger.getInstance(seq.getObjectAt(0)); } else { seqStart = -1; // field 0 is missing! version = new DERInteger(0); } serialNumber = DERInteger.getInstance(seq.getObjectAt(seqStart + 1)); signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqStart + 2)); issuer = X509Name.getInstance(seq.getObjectAt(seqStart + 3)); // // before and after dates // ASN1Sequence dates = (ASN1Sequence)seq.getObjectAt(seqStart + 4); startDate = Time.getInstance(dates.getObjectAt(0)); endDate = Time.getInstance(dates.getObjectAt(1)); subject = X509Name.getInstance(seq.getObjectAt(seqStart + 5)); // // public key info. // subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(seqStart + 6)); for (int extras = seq.size() - (seqStart + 6) - 1; extras > 0; extras--) { DERTaggedObject extra = (DERTaggedObject)seq.getObjectAt(seqStart + 6 + extras); switch (extra.getTagNo()) { case 1: issuerUniqueId = DERBitString.getInstance(extra, false); break; case 2: subjectUniqueId = DERBitString.getInstance(extra, false); break; case 3: extensions = X509Extensions.getInstance(extra); } } } public int getVersion() { return version.getValue().intValue() + 1; } public DERInteger getVersionNumber() { return version; } public DERInteger getSerialNumber() { return serialNumber; } public AlgorithmIdentifier getSignature() { return signature; } public X509Name getIssuer() { return issuer; } public Time getStartDate() { return startDate; } public Time getEndDate() { return endDate; } public X509Name getSubject() { return subject; } public SubjectPublicKeyInfo getSubjectPublicKeyInfo() { return subjectPublicKeyInfo; } public DERBitString getIssuerUniqueId() { return issuerUniqueId; } public DERBitString getSubjectUniqueId() { return subjectUniqueId; } public X509Extensions getExtensions() { return extensions; } public DERObject toASN1Object() { return seq; } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/X509Name.java0000644000175000017500000010641011026315644021604 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.DERString; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; /** *

       *     RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
       *
       *     RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
       *
       *     AttributeTypeAndValue ::= SEQUENCE {
       *                                   type  OBJECT IDENTIFIER,
       *                                   value ANY }
       * 
      */ public class X509Name extends ASN1Encodable { /** * country code - StringType(SIZE(2)) */ public static final DERObjectIdentifier C = new DERObjectIdentifier("2.5.4.6"); /** * organization - StringType(SIZE(1..64)) */ public static final DERObjectIdentifier O = new DERObjectIdentifier("2.5.4.10"); /** * organizational unit name - StringType(SIZE(1..64)) */ public static final DERObjectIdentifier OU = new DERObjectIdentifier("2.5.4.11"); /** * Title */ public static final DERObjectIdentifier T = new DERObjectIdentifier("2.5.4.12"); /** * common name - StringType(SIZE(1..64)) */ public static final DERObjectIdentifier CN = new DERObjectIdentifier("2.5.4.3"); /** * device serial number name - StringType(SIZE(1..64)) */ public static final DERObjectIdentifier SN = new DERObjectIdentifier("2.5.4.5"); /** * street - StringType(SIZE(1..64)) */ public static final DERObjectIdentifier STREET = new DERObjectIdentifier("2.5.4.9"); /** * device serial number name - StringType(SIZE(1..64)) */ public static final DERObjectIdentifier SERIALNUMBER = SN; /** * locality name - StringType(SIZE(1..64)) */ public static final DERObjectIdentifier L = new DERObjectIdentifier("2.5.4.7"); /** * state, or province name - StringType(SIZE(1..64)) */ public static final DERObjectIdentifier ST = new DERObjectIdentifier("2.5.4.8"); /** * Naming attributes of type X520name */ public static final DERObjectIdentifier SURNAME = new DERObjectIdentifier("2.5.4.4"); public static final DERObjectIdentifier GIVENNAME = new DERObjectIdentifier("2.5.4.42"); public static final DERObjectIdentifier INITIALS = new DERObjectIdentifier("2.5.4.43"); public static final DERObjectIdentifier GENERATION = new DERObjectIdentifier("2.5.4.44"); public static final DERObjectIdentifier UNIQUE_IDENTIFIER = new DERObjectIdentifier("2.5.4.45"); /** * businessCategory - DirectoryString(SIZE(1..128) */ public static final DERObjectIdentifier BUSINESS_CATEGORY = new DERObjectIdentifier( "2.5.4.15"); /** * postalCode - DirectoryString(SIZE(1..40) */ public static final DERObjectIdentifier POSTAL_CODE = new DERObjectIdentifier( "2.5.4.17"); /** * dnQualifier - DirectoryString(SIZE(1..64) */ public static final DERObjectIdentifier DN_QUALIFIER = new DERObjectIdentifier( "2.5.4.46"); /** * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64) */ public static final DERObjectIdentifier PSEUDONYM = new DERObjectIdentifier( "2.5.4.65"); /** * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z */ public static final DERObjectIdentifier DATE_OF_BIRTH = new DERObjectIdentifier( "1.3.6.1.5.5.7.9.1"); /** * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128) */ public static final DERObjectIdentifier PLACE_OF_BIRTH = new DERObjectIdentifier( "1.3.6.1.5.5.7.9.2"); /** * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f" */ public static final DERObjectIdentifier GENDER = new DERObjectIdentifier( "1.3.6.1.5.5.7.9.3"); /** * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166 * codes only */ public static final DERObjectIdentifier COUNTRY_OF_CITIZENSHIP = new DERObjectIdentifier( "1.3.6.1.5.5.7.9.4"); /** * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166 * codes only */ public static final DERObjectIdentifier COUNTRY_OF_RESIDENCE = new DERObjectIdentifier( "1.3.6.1.5.5.7.9.5"); /** * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64) */ public static final DERObjectIdentifier NAME_AT_BIRTH = new DERObjectIdentifier("1.3.36.8.3.14"); /** * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF * DirectoryString(SIZE(1..30)) */ public static final DERObjectIdentifier POSTAL_ADDRESS = new DERObjectIdentifier( "2.5.4.16"); /** * Email address (RSA PKCS#9 extension) - IA5String. *

      Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here. */ public static final DERObjectIdentifier EmailAddress = PKCSObjectIdentifiers.pkcs_9_at_emailAddress; /** * more from PKCS#9 */ public static final DERObjectIdentifier UnstructuredName = PKCSObjectIdentifiers.pkcs_9_at_unstructuredName; public static final DERObjectIdentifier UnstructuredAddress = PKCSObjectIdentifiers.pkcs_9_at_unstructuredAddress; /** * email address in Verisign certificates */ public static final DERObjectIdentifier E = EmailAddress; /* * others... */ public static final DERObjectIdentifier DC = new DERObjectIdentifier("0.9.2342.19200300.100.1.25"); /** * LDAP User id. */ public static final DERObjectIdentifier UID = new DERObjectIdentifier("0.9.2342.19200300.100.1.1"); /** * look up table translating OID values into their common symbols - this static is scheduled for deletion */ public static Hashtable OIDLookUp = new Hashtable(); /** * determines whether or not strings should be processed and printed * from back to front. */ public static boolean DefaultReverse = false; /** * default look up table translating OID values into their common symbols following * the convention in RFC 2253 with a few extras */ public static Hashtable DefaultSymbols = OIDLookUp; /** * look up table translating OID values into their common symbols following the convention in RFC 2253 * */ public static Hashtable RFC2253Symbols = new Hashtable(); /** * look up table translating OID values into their common symbols following the convention in RFC 1779 * */ public static Hashtable RFC1779Symbols = new Hashtable(); /** * look up table translating string values into their OIDS - * this static is scheduled for deletion */ public static Hashtable SymbolLookUp = new Hashtable(); /** * look up table translating common symbols into their OIDS. */ public static Hashtable DefaultLookUp = SymbolLookUp; private static final Boolean TRUE = new Boolean(true); // for J2ME compatibility private static final Boolean FALSE = new Boolean(false); static { DefaultSymbols.put(C, "C"); DefaultSymbols.put(O, "O"); DefaultSymbols.put(T, "T"); DefaultSymbols.put(OU, "OU"); DefaultSymbols.put(CN, "CN"); DefaultSymbols.put(L, "L"); DefaultSymbols.put(ST, "ST"); DefaultSymbols.put(SN, "SERIALNUMBER"); DefaultSymbols.put(EmailAddress, "E"); DefaultSymbols.put(DC, "DC"); DefaultSymbols.put(UID, "UID"); DefaultSymbols.put(STREET, "STREET"); DefaultSymbols.put(SURNAME, "SURNAME"); DefaultSymbols.put(GIVENNAME, "GIVENNAME"); DefaultSymbols.put(INITIALS, "INITIALS"); DefaultSymbols.put(GENERATION, "GENERATION"); DefaultSymbols.put(UnstructuredAddress, "unstructuredAddress"); DefaultSymbols.put(UnstructuredName, "unstructuredName"); DefaultSymbols.put(UNIQUE_IDENTIFIER, "UniqueIdentifier"); DefaultSymbols.put(DN_QUALIFIER, "DN"); DefaultSymbols.put(PSEUDONYM, "Pseudonym"); DefaultSymbols.put(POSTAL_ADDRESS, "PostalAddress"); DefaultSymbols.put(NAME_AT_BIRTH, "NameAtBirth"); DefaultSymbols.put(COUNTRY_OF_CITIZENSHIP, "CountryOfCitizenship"); DefaultSymbols.put(COUNTRY_OF_RESIDENCE, "CountryOfResidence"); DefaultSymbols.put(GENDER, "Gender"); DefaultSymbols.put(PLACE_OF_BIRTH, "PlaceOfBirth"); DefaultSymbols.put(DATE_OF_BIRTH, "DateOfBirth"); DefaultSymbols.put(POSTAL_CODE, "PostalCode"); DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory"); RFC2253Symbols.put(C, "C"); RFC2253Symbols.put(O, "O"); RFC2253Symbols.put(OU, "OU"); RFC2253Symbols.put(CN, "CN"); RFC2253Symbols.put(L, "L"); RFC2253Symbols.put(ST, "ST"); RFC2253Symbols.put(STREET, "STREET"); RFC2253Symbols.put(DC, "DC"); RFC2253Symbols.put(UID, "UID"); RFC1779Symbols.put(C, "C"); RFC1779Symbols.put(O, "O"); RFC1779Symbols.put(OU, "OU"); RFC1779Symbols.put(CN, "CN"); RFC1779Symbols.put(L, "L"); RFC1779Symbols.put(ST, "ST"); RFC1779Symbols.put(STREET, "STREET"); DefaultLookUp.put("c", C); DefaultLookUp.put("o", O); DefaultLookUp.put("t", T); DefaultLookUp.put("ou", OU); DefaultLookUp.put("cn", CN); DefaultLookUp.put("l", L); DefaultLookUp.put("st", ST); DefaultLookUp.put("sn", SN); DefaultLookUp.put("serialnumber", SN); DefaultLookUp.put("street", STREET); DefaultLookUp.put("emailaddress", E); DefaultLookUp.put("dc", DC); DefaultLookUp.put("e", E); DefaultLookUp.put("uid", UID); DefaultLookUp.put("surname", SURNAME); DefaultLookUp.put("givenname", GIVENNAME); DefaultLookUp.put("initials", INITIALS); DefaultLookUp.put("generation", GENERATION); DefaultLookUp.put("unstructuredaddress", UnstructuredAddress); DefaultLookUp.put("unstructuredname", UnstructuredName); DefaultLookUp.put("uniqueidentifier", UNIQUE_IDENTIFIER); DefaultLookUp.put("dn", DN_QUALIFIER); DefaultLookUp.put("pseudonym", PSEUDONYM); DefaultLookUp.put("postaladdress", POSTAL_ADDRESS); DefaultLookUp.put("nameofbirth", NAME_AT_BIRTH); DefaultLookUp.put("countryofcitizenship", COUNTRY_OF_CITIZENSHIP); DefaultLookUp.put("countryofresidence", COUNTRY_OF_RESIDENCE); DefaultLookUp.put("gender", GENDER); DefaultLookUp.put("placeofbirth", PLACE_OF_BIRTH); DefaultLookUp.put("dateofbirth", DATE_OF_BIRTH); DefaultLookUp.put("postalcode", POSTAL_CODE); DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY); } private X509NameEntryConverter converter = null; private Vector ordering = new Vector(); private Vector values = new Vector(); private Vector added = new Vector(); private ASN1Sequence seq; /** * Return a X509Name based on the passed in tagged object. * * @param obj tag object holding name. * @param explicit true if explicitly tagged false otherwise. * @return the X509Name */ public static X509Name getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static X509Name getInstance( Object obj) { if (obj == null || obj instanceof X509Name) { return (X509Name)obj; } else if (obj instanceof ASN1Sequence) { return new X509Name((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory \"" + obj.getClass().getName()+"\""); } /** * Constructor from ASN1Sequence * * the principal will be a list of constructed sets, each containing an (OID, String) pair. */ public X509Name( ASN1Sequence seq) { this.seq = seq; Enumeration e = seq.getObjects(); while (e.hasMoreElements()) { ASN1Set set = ASN1Set.getInstance(e.nextElement()); for (int i = 0; i < set.size(); i++) { ASN1Sequence s = ASN1Sequence.getInstance(set.getObjectAt(i)); if (s.size() != 2) { throw new IllegalArgumentException("badly sized pair"); } ordering.addElement(DERObjectIdentifier.getInstance(s.getObjectAt(0))); DEREncodable value = s.getObjectAt(1); if (value instanceof DERString) { values.addElement(((DERString)value).getString()); } else { values.addElement("#" + bytesToString(Hex.encode(value.getDERObject().getDEREncoded()))); } added.addElement((i != 0) ? TRUE : FALSE); // to allow earlier JDK compatibility } } } /** * constructor from a table of attributes. *

      * it's is assumed the table contains OID/String pairs, and the contents * of the table are copied into an internal table as part of the * construction process. *

      * Note: if the name you are trying to generate should be * following a specific ordering, you should use the constructor * with the ordering specified below. * @deprecated use an ordered constructor! The hashtable ordering is rarely correct */ public X509Name( Hashtable attributes) { this(null, attributes); } /** * Constructor from a table of attributes with ordering. *

      * it's is assumed the table contains OID/String pairs, and the contents * of the table are copied into an internal table as part of the * construction process. The ordering vector should contain the OIDs * in the order they are meant to be encoded or printed in toString. */ public X509Name( Vector ordering, Hashtable attributes) { this(ordering, attributes, new X509DefaultEntryConverter()); } /** * Constructor from a table of attributes with ordering. *

      * it's is assumed the table contains OID/String pairs, and the contents * of the table are copied into an internal table as part of the * construction process. The ordering vector should contain the OIDs * in the order they are meant to be encoded or printed in toString. *

      * The passed in converter will be used to convert the strings into their * ASN.1 counterparts. */ public X509Name( Vector ordering, Hashtable attributes, X509NameEntryConverter converter) { this.converter = converter; if (ordering != null) { for (int i = 0; i != ordering.size(); i++) { this.ordering.addElement(ordering.elementAt(i)); this.added.addElement(FALSE); } } else { Enumeration e = attributes.keys(); while (e.hasMoreElements()) { this.ordering.addElement(e.nextElement()); this.added.addElement(FALSE); } } for (int i = 0; i != this.ordering.size(); i++) { DERObjectIdentifier oid = (DERObjectIdentifier)this.ordering.elementAt(i); if (attributes.get(oid) == null) { throw new IllegalArgumentException("No attribute for object id - " + oid.getId() + " - passed to distinguished name"); } this.values.addElement(attributes.get(oid)); // copy the hash table } } /** * Takes two vectors one of the oids and the other of the values. */ public X509Name( Vector oids, Vector values) { this(oids, values, new X509DefaultEntryConverter()); } /** * Takes two vectors one of the oids and the other of the values. *

      * The passed in converter will be used to convert the strings into their * ASN.1 counterparts. */ public X509Name( Vector oids, Vector values, X509NameEntryConverter converter) { this.converter = converter; if (oids.size() != values.size()) { throw new IllegalArgumentException("oids vector must be same length as values."); } for (int i = 0; i < oids.size(); i++) { this.ordering.addElement(oids.elementAt(i)); this.values.addElement(values.elementAt(i)); this.added.addElement(FALSE); } } /** * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or * some such, converting it into an ordered set of name attributes. */ public X509Name( String dirName) { this(DefaultReverse, DefaultLookUp, dirName); } /** * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or * some such, converting it into an ordered set of name attributes with each * string value being converted to its associated ASN.1 type using the passed * in converter. */ public X509Name( String dirName, X509NameEntryConverter converter) { this(DefaultReverse, DefaultLookUp, dirName, converter); } /** * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or * some such, converting it into an ordered set of name attributes. If reverse * is true, create the encoded version of the sequence starting from the * last element in the string. */ public X509Name( boolean reverse, String dirName) { this(reverse, DefaultLookUp, dirName); } /** * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or * some such, converting it into an ordered set of name attributes with each * string value being converted to its associated ASN.1 type using the passed * in converter. If reverse is true the ASN.1 sequence representing the DN will * be built by starting at the end of the string, rather than the start. */ public X509Name( boolean reverse, String dirName, X509NameEntryConverter converter) { this(reverse, DefaultLookUp, dirName, converter); } /** * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or * some such, converting it into an ordered set of name attributes. lookUp * should provide a table of lookups, indexed by lowercase only strings and * yielding a DERObjectIdentifier, other than that OID. and numeric oids * will be processed automatically. *
      * If reverse is true, create the encoded version of the sequence * starting from the last element in the string. * @param reverse true if we should start scanning from the end (RFC 2553). * @param lookUp table of names and their oids. * @param dirName the X.500 string to be parsed. */ public X509Name( boolean reverse, Hashtable lookUp, String dirName) { this(reverse, lookUp, dirName, new X509DefaultEntryConverter()); } private DERObjectIdentifier decodeOID( String name, Hashtable lookUp) { if (Strings.toUpperCase(name).startsWith("OID.")) { return new DERObjectIdentifier(name.substring(4)); } else if (name.charAt(0) >= '0' && name.charAt(0) <= '9') { return new DERObjectIdentifier(name); } DERObjectIdentifier oid = (DERObjectIdentifier)lookUp.get(Strings.toLowerCase(name)); if (oid == null) { throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name"); } return oid; } /** * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or * some such, converting it into an ordered set of name attributes. lookUp * should provide a table of lookups, indexed by lowercase only strings and * yielding a DERObjectIdentifier, other than that OID. and numeric oids * will be processed automatically. The passed in converter is used to convert the * string values to the right of each equals sign to their ASN.1 counterparts. *
      * @param reverse true if we should start scanning from the end, false otherwise. * @param lookUp table of names and oids. * @param dirName the string dirName * @param converter the converter to convert string values into their ASN.1 equivalents */ public X509Name( boolean reverse, Hashtable lookUp, String dirName, X509NameEntryConverter converter) { this.converter = converter; X509NameTokenizer nTok = new X509NameTokenizer(dirName); while (nTok.hasMoreTokens()) { String token = nTok.nextToken(); int index = token.indexOf('='); if (index == -1) { throw new IllegalArgumentException("badly formated directory string"); } String name = token.substring(0, index); String value = token.substring(index + 1); DERObjectIdentifier oid = decodeOID(name, lookUp); if (value.indexOf('+') > 0) { X509NameTokenizer vTok = new X509NameTokenizer(value, '+'); this.ordering.addElement(oid); this.values.addElement(vTok.nextToken()); this.added.addElement(FALSE); while (vTok.hasMoreTokens()) { String sv = vTok.nextToken(); int ndx = sv.indexOf('='); String nm = sv.substring(0, ndx); String vl = sv.substring(ndx + 1); this.ordering.addElement(decodeOID(nm, lookUp)); this.values.addElement(vl); this.added.addElement(TRUE); } } else { this.ordering.addElement(oid); this.values.addElement(value); this.added.addElement(FALSE); } } if (reverse) { Vector o = new Vector(); Vector v = new Vector(); Vector a = new Vector(); int count = 1; for (int i = 0; i < this.ordering.size(); i++) { if (((Boolean)this.added.elementAt(i)).booleanValue()) { o.insertElementAt(this.ordering.elementAt(i), count); v.insertElementAt(this.values.elementAt(i), count); a.insertElementAt(this.added.elementAt(i), count); count++; } else { o.insertElementAt(this.ordering.elementAt(i), 0); v.insertElementAt(this.values.elementAt(i), 0); a.insertElementAt(this.added.elementAt(i), 0); count = 1; } } this.ordering = o; this.values = v; this.added = a; } } /** * return a vector of the oids in the name, in the order they were found. */ public Vector getOIDs() { Vector v = new Vector(); for (int i = 0; i != ordering.size(); i++) { v.addElement(ordering.elementAt(i)); } return v; } /** * return a vector of the values found in the name, in the order they * were found. */ public Vector getValues() { Vector v = new Vector(); for (int i = 0; i != values.size(); i++) { v.addElement(values.elementAt(i)); } return v; } /** * return a vector of the values found in the name, in the order they * were found, with the DN label corresponding to passed in oid. */ public Vector getValues( DERObjectIdentifier oid) { Vector v = new Vector(); for (int i = 0; i != values.size(); i++) { if (ordering.elementAt(i).equals(oid)) { v.addElement(values.elementAt(i)); } } return v; } public DERObject toASN1Object() { if (seq == null) { ASN1EncodableVector vec = new ASN1EncodableVector(); ASN1EncodableVector sVec = new ASN1EncodableVector(); DERObjectIdentifier lstOid = null; for (int i = 0; i != ordering.size(); i++) { ASN1EncodableVector v = new ASN1EncodableVector(); DERObjectIdentifier oid = (DERObjectIdentifier)ordering.elementAt(i); v.add(oid); String str = (String)values.elementAt(i); v.add(converter.getConvertedValue(oid, str)); if (lstOid == null || ((Boolean)this.added.elementAt(i)).booleanValue()) { sVec.add(new DERSequence(v)); } else { vec.add(new DERSet(sVec)); sVec = new ASN1EncodableVector(); sVec.add(new DERSequence(v)); } lstOid = oid; } vec.add(new DERSet(sVec)); seq = new DERSequence(vec); } return seq; } /** * @param inOrder if true the order of both X509 names must be the same, * as well as the values associated with each element. */ public boolean equals(Object obj, boolean inOrder) { if (!inOrder) { return this.equals(obj); } if (obj == this) { return true; } if (!(obj instanceof X509Name || obj instanceof ASN1Sequence)) { return false; } DERObject derO = ((DEREncodable)obj).getDERObject(); if (this.getDERObject().equals(derO)) { return true; } X509Name other; try { other = X509Name.getInstance(obj); } catch (IllegalArgumentException e) { return false; } int orderingSize = ordering.size(); if (orderingSize != other.ordering.size()) { return false; } for (int i = 0; i < orderingSize; i++) { DERObjectIdentifier oid = (DERObjectIdentifier)ordering.elementAt(i); DERObjectIdentifier oOid = (DERObjectIdentifier)other.ordering.elementAt(i); if (oid.equals(oOid)) { String value = (String)values.elementAt(i); String oValue = (String)other.values.elementAt(i); if (!equivalentStrings(value, oValue)) { return false; } } else { return false; } } return true; } /** * test for equality - note: case is ignored. */ public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof X509Name || obj instanceof ASN1Sequence)) { return false; } DERObject derO = ((DEREncodable)obj).getDERObject(); if (this.getDERObject().equals(derO)) { return true; } X509Name other; try { other = X509Name.getInstance(obj); } catch (IllegalArgumentException e) { return false; } int orderingSize = ordering.size(); if (orderingSize != other.ordering.size()) { return false; } boolean[] indexes = new boolean[orderingSize]; int start, end, delta; if (ordering.elementAt(0).equals(other.ordering.elementAt(0))) // guess forward { start = 0; end = orderingSize; delta = 1; } else // guess reversed - most common problem { start = orderingSize - 1; end = -1; delta = -1; } for (int i = start; i != end; i += delta) { boolean found = false; DERObjectIdentifier oid = (DERObjectIdentifier)ordering.elementAt(i); String value = (String)values.elementAt(i); for (int j = 0; j < orderingSize; j++) { if (indexes[j]) { continue; } DERObjectIdentifier oOid = (DERObjectIdentifier)other.ordering.elementAt(j); if (oid.equals(oOid)) { String oValue = (String)other.values.elementAt(j); if (equivalentStrings(value, oValue)) { indexes[j] = true; found = true; break; } } } if (!found) { return false; } } return true; } private boolean equivalentStrings(String s1, String s2) { String value = Strings.toLowerCase(s1.trim()); String oValue = Strings.toLowerCase(s2.trim()); if (!value.equals(oValue)) { value = stripInternalSpaces(value); oValue = stripInternalSpaces(oValue); if (!value.equals(oValue)) { return false; } } return true; } private String stripInternalSpaces( String str) { StringBuffer res = new StringBuffer(); if (str.length() != 0) { char c1 = str.charAt(0); res.append(c1); for (int k = 1; k < str.length(); k++) { char c2 = str.charAt(k); if (!(c1 == ' ' && c2 == ' ')) { res.append(c2); } c1 = c2; } } return res.toString(); } public int hashCode() { ASN1Sequence seq = (ASN1Sequence)this.getDERObject(); Enumeration e = seq.getObjects(); int hashCode = 0; while (e.hasMoreElements()) { hashCode ^= e.nextElement().hashCode(); } return hashCode; } private void appendValue( StringBuffer buf, Hashtable oidSymbols, DERObjectIdentifier oid, String value) { String sym = (String)oidSymbols.get(oid); if (sym != null) { buf.append(sym); } else { buf.append(oid.getId()); } buf.append('='); int index = buf.length(); buf.append(value); int end = buf.length(); while (index != end) { if ((buf.charAt(index) == ',') || (buf.charAt(index) == '"') || (buf.charAt(index) == '\\') || (buf.charAt(index) == '+') || (buf.charAt(index) == '<') || (buf.charAt(index) == '>') || (buf.charAt(index) == ';')) { buf.insert(index, "\\"); index++; end++; } index++; } } /** * convert the structure to a string - if reverse is true the * oids and values are listed out starting with the last element * in the sequence (ala RFC 2253), otherwise the string will begin * with the first element of the structure. If no string definition * for the oid is found in oidSymbols the string value of the oid is * added. Two standard symbol tables are provided DefaultSymbols, and * RFC2253Symbols as part of this class. * * @param reverse if true start at the end of the sequence and work back. * @param oidSymbols look up table strings for oids. */ public String toString( boolean reverse, Hashtable oidSymbols) { StringBuffer buf = new StringBuffer(); Vector components = new Vector(); boolean first = true; StringBuffer ava = null; for (int i = 0; i < ordering.size(); i++) { if (((Boolean)added.elementAt(i)).booleanValue()) { ava.append('+'); appendValue(ava, oidSymbols, (DERObjectIdentifier)ordering.elementAt(i), (String)values.elementAt(i)); } else { ava = new StringBuffer(); appendValue(ava, oidSymbols, (DERObjectIdentifier)ordering.elementAt(i), (String)values.elementAt(i)); components.addElement(ava); } } if (reverse) { for (int i = components.size() - 1; i >= 0; i--) { if (first) { first = false; } else { buf.append(','); } buf.append(components.elementAt(i).toString()); } } else { for (int i = 0; i < components.size(); i++) { if (first) { first = false; } else { buf.append(','); } buf.append(components.elementAt(i).toString()); } } return buf.toString(); } private String bytesToString( byte[] data) { char[] cs = new char[data.length]; for (int i = 0; i != cs.length; i++) { cs[i] = (char)(data[i] & 0xff); } return new String(cs); } public String toString() { return toString(DefaultReverse, DefaultSymbols); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/KeyPurposeId.java0000644000175000017500000000267310061400650022715 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.DERObjectIdentifier; /** * The KeyPurposeId object. *

       *     KeyPurposeId ::= OBJECT IDENTIFIER
       * 
      */ public class KeyPurposeId extends DERObjectIdentifier { private static final String id_kp = "1.3.6.1.5.5.7.3"; private KeyPurposeId( String id) { super(id); } public static final KeyPurposeId anyExtendedKeyUsage = new KeyPurposeId(X509Extensions.ExtendedKeyUsage.getId() + ".0"); public static final KeyPurposeId id_kp_serverAuth = new KeyPurposeId(id_kp + ".1"); public static final KeyPurposeId id_kp_clientAuth = new KeyPurposeId(id_kp + ".2"); public static final KeyPurposeId id_kp_codeSigning = new KeyPurposeId(id_kp + ".3"); public static final KeyPurposeId id_kp_emailProtection = new KeyPurposeId(id_kp + ".4"); public static final KeyPurposeId id_kp_ipsecEndSystem = new KeyPurposeId(id_kp + ".5"); public static final KeyPurposeId id_kp_ipsecTunnel = new KeyPurposeId(id_kp + ".6"); public static final KeyPurposeId id_kp_ipsecUser = new KeyPurposeId(id_kp + ".7"); public static final KeyPurposeId id_kp_timeStamping = new KeyPurposeId(id_kp + ".8"); public static final KeyPurposeId id_kp_OCSPSigning = new KeyPurposeId(id_kp + ".9"); // // microsoft key purpose ids // public static final KeyPurposeId id_kp_smartcardlogon = new KeyPurposeId("1.3.6.1.4.1.311.20.2.2"); } azureus-4.3.0.6/org/bouncycastle/asn1/x509/RoleSyntax.java0000644000175000017500000001627311026315662022455 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERString; import org.bouncycastle.asn1.DERTaggedObject; /** * Implementation of the RoleSyntax object as specified by the RFC3281. * *
       * RoleSyntax ::= SEQUENCE {
       *                 roleAuthority  [0] GeneralNames OPTIONAL,
       *                 roleName       [1] GeneralName
       *           } 
       * 
      */ public class RoleSyntax extends ASN1Encodable { private GeneralNames roleAuthority; private GeneralName roleName; /** * RoleSyntax factory method. * @param obj the object used to construct an instance of * RoleSyntax. It must be an instance of RoleSyntax * or ASN1Sequence. * @return the instance of RoleSyntax built from the * supplied object. * @throws java.lang.IllegalArgumentException if the object passed * to the factory is not an instance of RoleSyntax or * ASN1Sequence. */ public static RoleSyntax getInstance( Object obj) { if(obj == null || obj instanceof RoleSyntax) { return (RoleSyntax)obj; } else if(obj instanceof ASN1Sequence) { return new RoleSyntax((ASN1Sequence)obj); } throw new IllegalArgumentException("Unknown object in RoleSyntax factory."); } /** * Constructor. * @param roleAuthority the role authority of this RoleSyntax. * @param roleName the role name of this RoleSyntax. */ public RoleSyntax( GeneralNames roleAuthority, GeneralName roleName) { if(roleName == null || roleName.getTagNo() != GeneralName.uniformResourceIdentifier || ((DERString)roleName.getName()).getString().equals("")) { throw new IllegalArgumentException("the role name MUST be non empty and MUST " + "use the URI option of GeneralName"); } this.roleAuthority = roleAuthority; this.roleName = roleName; } /** * Constructor. Invoking this constructor is the same as invoking * new RoleSyntax(null, roleName). * @param roleName the role name of this RoleSyntax. */ public RoleSyntax( GeneralName roleName) { this(null, roleName); } /** * Utility constructor. Takes a String argument representing * the role name, builds a GeneralName to hold the role name * and calls the constructor that takes a GeneralName. * @param roleName */ public RoleSyntax( String roleName) { this(new GeneralName(GeneralName.uniformResourceIdentifier, (roleName == null)? "": roleName)); } /** * Constructor that builds an instance of RoleSyntax by * extracting the encoded elements from the ASN1Sequence * object supplied. * @param seq an instance of ASN1Sequence that holds * the encoded elements used to build this RoleSyntax. */ public RoleSyntax( ASN1Sequence seq) { if (seq.size() < 1 || seq.size() > 2) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } for (int i = 0; i != seq.size(); i++) { ASN1TaggedObject taggedObject = ASN1TaggedObject.getInstance(seq.getObjectAt(i)); switch (taggedObject.getTagNo()) { case 0: roleAuthority = GeneralNames.getInstance(taggedObject, false); break; case 1: roleName = GeneralName.getInstance(taggedObject, false); break; default: throw new IllegalArgumentException("Unknown tag in RoleSyntax"); } } } /** * Gets the role authority of this RoleSyntax. * @return an instance of GeneralNames holding the * role authority of this RoleSyntax. */ public GeneralNames getRoleAuthority() { return this.roleAuthority; } /** * Gets the role name of this RoleSyntax. * @return an instance of GeneralName holding the * role name of this RoleSyntax. */ public GeneralName getRoleName() { return this.roleName; } /** * Gets the role name as a java.lang.String object. * @return the role name of this RoleSyntax represented as a * java.lang.String object. */ public String getRoleNameAsString() { DERString str = (DERString)this.roleName.getName(); return str.getString(); } /** * Gets the role authority as a String[] object. * @return the role authority of this RoleSyntax represented as a * String[] array. */ public String[] getRoleAuthorityAsString() { if(roleAuthority == null) { return new String[0]; } GeneralName[] names = roleAuthority.getNames(); String[] namesString = new String[names.length]; for(int i = 0; i < names.length; i++) { DEREncodable value = names[i].getName(); if(value instanceof DERString) { namesString[i] = ((DERString)value).getString(); } else { namesString[i] = value.toString(); } } return namesString; } /** * Implementation of the method toASN1Object as * required by the superclass ASN1Encodable. * *
           * RoleSyntax ::= SEQUENCE {
           *                 roleAuthority  [0] GeneralNames OPTIONAL,
           *                 roleName       [1] GeneralName
           *           } 
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); if(this.roleAuthority != null) { v.add(new DERTaggedObject(false, 0, roleAuthority)); } v.add(new DERTaggedObject(false, 1, roleName)); return new DERSequence(v); } public String toString() { StringBuffer buff = new StringBuffer("Name: " + this.getRoleNameAsString() + " - Auth: "); if(this.roleAuthority == null || roleAuthority.getNames().length == 0) { buff.append("N/A"); } else { String[] names = this.getRoleAuthorityAsString(); buff.append('[').append(names[0]); for(int i = 1; i < names.length; i++) { buff.append(", ").append(names[i]); } buff.append(']'); } return buff.toString(); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/AuthorityInformationAccess.java0000644000175000017500000000530211026315632025651 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; /** * The AuthorityInformationAccess object. *
       * id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
       *
       * AuthorityInfoAccessSyntax  ::=
       *      SEQUENCE SIZE (1..MAX) OF AccessDescription
       * AccessDescription  ::=  SEQUENCE {
       *       accessMethod          OBJECT IDENTIFIER,
       *       accessLocation        GeneralName  }
       *
       * id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
       * id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
       * id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
       * 
      */ public class AuthorityInformationAccess extends ASN1Encodable { private AccessDescription[] descriptions; public static AuthorityInformationAccess getInstance( Object obj) { if (obj instanceof AuthorityInformationAccess) { return (AuthorityInformationAccess)obj; } if (obj instanceof ASN1Sequence) { return new AuthorityInformationAccess((ASN1Sequence)obj); } if (obj instanceof X509Extension) { return getInstance(X509Extension.convertValueToObject((X509Extension)obj)); } throw new IllegalArgumentException("unknown object in factory"); } public AuthorityInformationAccess( ASN1Sequence seq) { descriptions = new AccessDescription[seq.size()]; for (int i = 0; i != seq.size(); i++) { descriptions[i] = AccessDescription.getInstance(seq.getObjectAt(i)); } } /** * create an AuthorityInformationAccess with the oid and location provided. */ public AuthorityInformationAccess( DERObjectIdentifier oid, GeneralName location) { descriptions = new AccessDescription[1]; descriptions[0] = new AccessDescription(oid, location); } /** * * @return the access descriptions contained in this object. */ public AccessDescription[] getAccessDescriptions() { return descriptions; } public DERObject toASN1Object() { ASN1EncodableVector vec = new ASN1EncodableVector(); for (int i = 0; i != descriptions.length; i++) { vec.add(descriptions[i]); } return new DERSequence(vec); } public String toString() { return ("AuthorityInformationAccess: Oid(" + this.descriptions[0].getAccessMethod().getId() + ")"); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java0000644000175000017500000000531311026315630024725 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DEROutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Hashtable; import java.util.Vector; /** * Generator for X.509 extensions */ public class X509ExtensionsGenerator { private Hashtable extensions = new Hashtable(); private Vector extOrdering = new Vector(); /** * Reset the generator */ public void reset() { extensions = new Hashtable(); extOrdering = new Vector(); } /** * Add an extension with the given oid and the passed in value to be included * in the OCTET STRING associated with the extension. * * @param oid OID for the extension. * @param critical true if critical, false otherwise. * @param value the ASN.1 object to be included in the extension. */ public void addExtension( DERObjectIdentifier oid, boolean critical, DEREncodable value) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(value); } catch (IOException e) { throw new IllegalArgumentException("error encoding value: " + e); } this.addExtension(oid, critical, bOut.toByteArray()); } /** * Add an extension with the given oid and the passed in byte array to be wrapped in the * OCTET STRING associated with the extension. * * @param oid OID for the extension. * @param critical true if critical, false otherwise. * @param value the byte array to be wrapped. */ public void addExtension( DERObjectIdentifier oid, boolean critical, byte[] value) { if (extensions.containsKey(oid)) { throw new IllegalArgumentException("extension " + oid + " already added"); } extOrdering.addElement(oid); extensions.put(oid, new X509Extension(critical, new DEROctetString(value))); } /** * Return true if there are no extension present in this generator. * * @return true if empty, false otherwise */ public boolean isEmpty() { return extOrdering.isEmpty(); } /** * Generate an X509Extensions object based on the current state of the generator. * * @return an X09Extensions object. */ public X509Extensions generate() { return new X509Extensions(extOrdering, extensions); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java0000644000175000017500000000460311026315646024414 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.SHA1Digest; /** * The SubjectKeyIdentifier object. *
       * SubjectKeyIdentifier::= OCTET STRING
       * 
      */ public class SubjectKeyIdentifier extends ASN1Encodable { private byte[] keyidentifier; public static SubjectKeyIdentifier getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1OctetString.getInstance(obj, explicit)); } public static SubjectKeyIdentifier getInstance( Object obj) { if (obj instanceof SubjectKeyIdentifier) { return (SubjectKeyIdentifier)obj; } if (obj instanceof SubjectPublicKeyInfo) { return new SubjectKeyIdentifier((SubjectPublicKeyInfo)obj); } if (obj instanceof ASN1OctetString) { return new SubjectKeyIdentifier((ASN1OctetString)obj); } if (obj instanceof X509Extension) { return getInstance(X509Extension.convertValueToObject((X509Extension)obj)); } throw new IllegalArgumentException("Invalid SubjectKeyIdentifier: " + obj.getClass().getName()); } public SubjectKeyIdentifier( byte[] keyid) { this.keyidentifier=keyid; } public SubjectKeyIdentifier( ASN1OctetString keyid) { this.keyidentifier=keyid.getOctets(); } /** * * Calulates the keyidentifier using a SHA1 hash over the BIT STRING * from SubjectPublicKeyInfo as defined in RFC2459. * **/ public SubjectKeyIdentifier( SubjectPublicKeyInfo spki) { Digest digest = new SHA1Digest(); byte[] resBuf = new byte[digest.getDigestSize()]; byte[] bytes = spki.getPublicKeyData().getBytes(); digest.update(bytes, 0, bytes.length); digest.doFinal(resBuf, 0); this.keyidentifier=resBuf; } public byte[] getKeyIdentifier() { return keyidentifier; } public DERObject toASN1Object() { return new DEROctetString(keyidentifier); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/DSAParameter.java0000644000175000017500000000417111026315626022607 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import java.math.BigInteger; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; public class DSAParameter extends ASN1Encodable { DERInteger p, q, g; public static DSAParameter getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static DSAParameter getInstance( Object obj) { if(obj == null || obj instanceof DSAParameter) { return (DSAParameter)obj; } if(obj instanceof ASN1Sequence) { return new DSAParameter((ASN1Sequence)obj); } throw new IllegalArgumentException("Invalid DSAParameter: " + obj.getClass().getName()); } public DSAParameter( BigInteger p, BigInteger q, BigInteger g) { this.p = new DERInteger(p); this.q = new DERInteger(q); this.g = new DERInteger(g); } public DSAParameter( ASN1Sequence seq) { if (seq.size() != 3) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } Enumeration e = seq.getObjects(); p = DERInteger.getInstance(e.nextElement()); q = DERInteger.getInstance(e.nextElement()); g = DERInteger.getInstance(e.nextElement()); } public BigInteger getP() { return p.getPositiveValue(); } public BigInteger getQ() { return q.getPositiveValue(); } public BigInteger getG() { return g.getPositiveValue(); } public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(p); v.add(q); v.add(g); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java0000644000175000017500000000644511026315626024370 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import java.io.IOException; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; /** * The object that contains the public key stored in a certficate. *

      * The getEncoded() method in the public keys in the JCE produces a DER * encoded one of these. */ public class SubjectPublicKeyInfo extends ASN1Encodable { private AlgorithmIdentifier algId; private DERBitString keyData; public static SubjectPublicKeyInfo getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static SubjectPublicKeyInfo getInstance( Object obj) { if (obj instanceof SubjectPublicKeyInfo) { return (SubjectPublicKeyInfo)obj; } else if (obj instanceof ASN1Sequence) { return new SubjectPublicKeyInfo((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public SubjectPublicKeyInfo( AlgorithmIdentifier algId, DEREncodable publicKey) { this.keyData = new DERBitString(publicKey); this.algId = algId; } public SubjectPublicKeyInfo( AlgorithmIdentifier algId, byte[] publicKey) { this.keyData = new DERBitString(publicKey); this.algId = algId; } public SubjectPublicKeyInfo( ASN1Sequence seq) { if (seq.size() != 2) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } Enumeration e = seq.getObjects(); this.algId = AlgorithmIdentifier.getInstance(e.nextElement()); this.keyData = DERBitString.getInstance(e.nextElement()); } public AlgorithmIdentifier getAlgorithmId() { return algId; } /** * for when the public key is an encoded object - if the bitstring * can't be decoded this routine throws an IOException. * * @exception IOException - if the bit string doesn't represent a DER * encoded object. */ public DERObject getPublicKey() throws IOException { ASN1InputStream aIn = new ASN1InputStream(keyData.getBytes()); return aIn.readObject(); } /** * for when the public key is raw bits... */ public DERBitString getPublicKeyData() { return keyData; } /** * Produce an object suitable for an ASN1OutputStream. *

           * SubjectPublicKeyInfo ::= SEQUENCE {
           *                          algorithm AlgorithmIdentifier,
           *                          publicKey BIT STRING }
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(algId); v.add(keyData); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java0000644000175000017500000000620011026315666024267 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; public class AlgorithmIdentifier extends ASN1Encodable { private DERObjectIdentifier objectId; private DEREncodable parameters; private boolean parametersDefined = false; public static AlgorithmIdentifier getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static AlgorithmIdentifier getInstance( Object obj) { if (obj== null || obj instanceof AlgorithmIdentifier) { return (AlgorithmIdentifier)obj; } if (obj instanceof DERObjectIdentifier) { return new AlgorithmIdentifier((DERObjectIdentifier)obj); } if (obj instanceof String) { return new AlgorithmIdentifier((String)obj); } if (obj instanceof ASN1Sequence) { return new AlgorithmIdentifier((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public AlgorithmIdentifier( DERObjectIdentifier objectId) { this.objectId = objectId; } public AlgorithmIdentifier( String objectId) { this.objectId = new DERObjectIdentifier(objectId); } public AlgorithmIdentifier( DERObjectIdentifier objectId, DEREncodable parameters) { parametersDefined = true; this.objectId = objectId; this.parameters = parameters; } public AlgorithmIdentifier( ASN1Sequence seq) { if (seq.size() < 1 || seq.size() > 2) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } objectId = DERObjectIdentifier.getInstance(seq.getObjectAt(0)); if (seq.size() == 2) { parametersDefined = true; parameters = seq.getObjectAt(1); } else { parameters = null; } } public DERObjectIdentifier getObjectId() { return objectId; } public DEREncodable getParameters() { return parameters; } /** * Produce an object suitable for an ASN1OutputStream. *
           *      AlgorithmIdentifier ::= SEQUENCE {
           *                            algorithm OBJECT IDENTIFIER,
           *                            parameters ANY DEFINED BY algorithm OPTIONAL }
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(objectId); if (parametersDefined) { v.add(parameters); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/PolicyInformation.java0000644000175000017500000000433311026315666024010 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; public class PolicyInformation extends ASN1Encodable { private DERObjectIdentifier policyIdentifier; private ASN1Sequence policyQualifiers; public PolicyInformation( ASN1Sequence seq) { if (seq.size() < 1 || seq.size() > 2) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } policyIdentifier = DERObjectIdentifier.getInstance(seq.getObjectAt(0)); if (seq.size() > 1) { policyQualifiers = ASN1Sequence.getInstance(seq.getObjectAt(1)); } } public PolicyInformation( DERObjectIdentifier policyIdentifier) { this.policyIdentifier = policyIdentifier; } public PolicyInformation( DERObjectIdentifier policyIdentifier, ASN1Sequence policyQualifiers) { this.policyIdentifier = policyIdentifier; this.policyQualifiers = policyQualifiers; } public static PolicyInformation getInstance( Object obj) { if (obj == null || obj instanceof PolicyInformation) { return (PolicyInformation)obj; } return new PolicyInformation(ASN1Sequence.getInstance(obj)); } public DERObjectIdentifier getPolicyIdentifier() { return policyIdentifier; } public ASN1Sequence getPolicyQualifiers() { return policyQualifiers; } /* * PolicyInformation ::= SEQUENCE { * policyIdentifier CertPolicyId, * policyQualifiers SEQUENCE SIZE (1..MAX) OF * PolicyQualifierInfo OPTIONAL } */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(policyIdentifier); if (policyQualifiers != null) { v.add(policyQualifiers); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/AttCertIssuer.java0000644000175000017500000000451011026315634023074 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Choice; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERTaggedObject; public class AttCertIssuer extends ASN1Encodable implements ASN1Choice { ASN1Encodable obj; DERObject choiceObj; public static AttCertIssuer getInstance( Object obj) { if (obj instanceof AttCertIssuer) { return (AttCertIssuer)obj; } else if (obj instanceof V2Form) { return new AttCertIssuer(V2Form.getInstance(obj)); } else if (obj instanceof GeneralNames) { return new AttCertIssuer((GeneralNames)obj); } else if (obj instanceof ASN1TaggedObject) { return new AttCertIssuer(V2Form.getInstance((ASN1TaggedObject)obj, false)); } else if (obj instanceof ASN1Sequence) { return new AttCertIssuer(GeneralNames.getInstance(obj)); } throw new IllegalArgumentException("unknown object in factory: " + obj.getClass()); } public static AttCertIssuer getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); // must be explictly tagged } /** * Don't use this one if you are trying to be RFC 3281 compliant. * Use it for v1 attribute certificates only. * * @param names our GeneralNames structure */ public AttCertIssuer( GeneralNames names) { obj = names; choiceObj = obj.getDERObject(); } public AttCertIssuer( V2Form v2Form) { obj = v2Form; choiceObj = new DERTaggedObject(false, 0, obj); } public ASN1Encodable getIssuer() { return obj; } /** * Produce an object suitable for an ASN1OutputStream. *
           *  AttCertIssuer ::= CHOICE {
           *       v1Form   GeneralNames,  -- MUST NOT be used in this
           *                               -- profile
           *       v2Form   [0] V2Form     -- v2 only
           *  }
           * 
      */ public DERObject toASN1Object() { return choiceObj; } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/CertificatePair.java0000644000175000017500000001203611026315640023370 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; import java.util.Enumeration; /** * This class helps to support crossCerfificatePairs in a LDAP directory * according RFC 2587 * *
       *     crossCertificatePairATTRIBUTE::={
       *       WITH SYNTAX   CertificatePair
       *       EQUALITY MATCHING RULE certificatePairExactMatch
       *       ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
       * 
      * *
      The forward elements of the crossCertificatePair attribute of a * CA's directory entry shall be used to store all, except self-issued * certificates issued to this CA. Optionally, the reverse elements of the * crossCertificatePair attribute, of a CA's directory entry may contain a * subset of certificates issued by this CA to other CAs. When both the forward * and the reverse elements are present in a single attribute value, issuer name * in one certificate shall match the subject name in the other and vice versa, * and the subject public key in one certificate shall be capable of verifying * the digital signature on the other certificate and vice versa. * * When a reverse element is present, the forward element value and the reverse * element value need not be stored in the same attribute value; in other words, * they can be stored in either a single attribute value or two attribute * values.
      * *
       *       CertificatePair ::= SEQUENCE {
       *         forward        [0]    Certificate OPTIONAL,
       *         reverse        [1]    Certificate OPTIONAL,
       *         -- at least one of the pair shall be present -- } 
       * 
      */ public class CertificatePair extends ASN1Encodable { private X509CertificateStructure forward; private X509CertificateStructure reverse; public static CertificatePair getInstance(Object obj) { if (obj == null || obj instanceof CertificatePair) { return (CertificatePair)obj; } if (obj instanceof ASN1Sequence) { return new CertificatePair((ASN1Sequence)obj); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * Constructor from ASN1Sequence. *

      * The sequence is of type CertificatePair: *

      *

           *       CertificatePair ::= SEQUENCE {
           *         forward        [0]    Certificate OPTIONAL,
           *         reverse        [1]    Certificate OPTIONAL,
           *         -- at least one of the pair shall be present -- }
           * 
      * * @param seq The ASN.1 sequence. */ private CertificatePair(ASN1Sequence seq) { if (seq.size() != 1 && seq.size() != 2) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } Enumeration e = seq.getObjects(); while (e.hasMoreElements()) { ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement()); if (o.getTagNo() == 0) { forward = X509CertificateStructure.getInstance(o, true); } else if (o.getTagNo() == 1) { reverse = X509CertificateStructure.getInstance(o, true); } else { throw new IllegalArgumentException("Bad tag number: " + o.getTagNo()); } } } /** * Constructor from a given details. * * @param forward Certificates issued to this CA. * @param reverse Certificates issued by this CA to other CAs. */ public CertificatePair(X509CertificateStructure forward, X509CertificateStructure reverse) { this.forward = forward; this.reverse = reverse; } /** * Produce an object suitable for an ASN1OutputStream. *

      * Returns: *

      *

           *       CertificatePair ::= SEQUENCE {
           *         forward        [0]    Certificate OPTIONAL,
           *         reverse        [1]    Certificate OPTIONAL,
           *         -- at least one of the pair shall be present -- }
           * 
      * * @return a DERObject */ public DERObject toASN1Object() { ASN1EncodableVector vec = new ASN1EncodableVector(); if (forward != null) { vec.add(new DERTaggedObject(0, forward)); } if (reverse != null) { vec.add(new DERTaggedObject(1, reverse)); } return new DERSequence(vec); } /** * @return Returns the forward. */ public X509CertificateStructure getForward() { return forward; } /** * @return Returns the reverse. */ public X509CertificateStructure getReverse() { return reverse; } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/Target.java0000644000175000017500000000706011026315646021567 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Choice; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERTaggedObject; /** * Target structure used in target information extension for attribute * certificates from RFC 3281. * *
       *     Target  ::= CHOICE {
       *       targetName          [0] GeneralName,
       *       targetGroup         [1] GeneralName,
       *       targetCert          [2] TargetCert
       *     }
       * 
      * *

      * The targetCert field is currently not supported and must not be used * according to RFC 3281. */ public class Target extends ASN1Encodable implements ASN1Choice { public static final int targetName = 0; public static final int targetGroup = 1; private GeneralName targName; private GeneralName targGroup; /** * Creates an instance of a Target from the given object. *

      * obj can be a Target or a {@link ASN1TaggedObject} * * @param obj The object. * @return A Target instance. * @throws IllegalArgumentException if the given object cannot be * interpreted as Target. */ public static Target getInstance(Object obj) { if (obj instanceof Target) { return (Target) obj; } else if (obj instanceof ASN1TaggedObject) { return new Target((ASN1TaggedObject)obj); } throw new IllegalArgumentException("unknown object in factory: " + obj.getClass()); } /** * Constructor from ASN1TaggedObject. * * @param tagObj The tagged object. * @throws IllegalArgumentException if the encoding is wrong. */ private Target(ASN1TaggedObject tagObj) { switch (tagObj.getTagNo()) { case targetName: // GeneralName is already a choice so explicit targName = GeneralName.getInstance(tagObj, true); break; case targetGroup: targGroup = GeneralName.getInstance(tagObj, true); break; default: throw new IllegalArgumentException("unknown tag: " + tagObj.getTagNo()); } } /** * Constructor from given details. *

      * Exactly one of the parameters must be not null. * * @param type the choice type to apply to the name. * @param name the general name. * @throws IllegalArgumentException if type is invalid. */ public Target(int type, GeneralName name) { this(new DERTaggedObject(type, name)); } /** * @return Returns the targetGroup. */ public GeneralName getTargetGroup() { return targGroup; } /** * @return Returns the targetName. */ public GeneralName getTargetName() { return targName; } /** * Produce an object suitable for an ASN1OutputStream. * * Returns: * *

           *     Target  ::= CHOICE {
           *       targetName          [0] GeneralName,
           *       targetGroup         [1] GeneralName,
           *       targetCert          [2] TargetCert
           *     }
           * 
      * * @return a DERObject */ public DERObject toASN1Object() { // GeneralName is a choice already so most be explicitly tagged if (targName != null) { return new DERTaggedObject(true, 0, targName); } else { return new DERTaggedObject(true, 1, targGroup); } } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/X509NameTokenizer.java0000644000175000017500000000375411026315656023511 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; /** * class for breaking up an X500 Name into it's component tokens, ala * java.util.StringTokenizer. We need this class as some of the * lightweight Java environment don't support classes like * StringTokenizer. */ public class X509NameTokenizer { private String value; private int index; private char seperator; private StringBuffer buf = new StringBuffer(); public X509NameTokenizer( String oid) { this(oid, ','); } public X509NameTokenizer( String oid, char seperator) { this.value = oid; this.index = -1; this.seperator = seperator; } public boolean hasMoreTokens() { return (index != value.length()); } public String nextToken() { if (index == value.length()) { return null; } int end = index + 1; boolean quoted = false; boolean escaped = false; buf.setLength(0); while (end != value.length()) { char c = value.charAt(end); if (c == '"') { if (!escaped) { quoted = !quoted; } else { buf.append(c); } escaped = false; } else { if (escaped || quoted) { buf.append(c); escaped = false; } else if (c == '\\') { escaped = true; } else if (c == seperator) { break; } else { buf.append(c); } } end++; } index = end; return buf.toString().trim(); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/Time.java0000644000175000017500000000626211026315644021240 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Choice; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERGeneralizedTime; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERUTCTime; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.SimpleTimeZone; public class Time extends ASN1Encodable implements ASN1Choice { DERObject time; public static Time getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); // must be explicitly tagged } public Time( DERObject time) { if (!(time instanceof DERUTCTime) && !(time instanceof DERGeneralizedTime)) { throw new IllegalArgumentException("unknown object passed to Time"); } this.time = time; } /** * creates a time object from a given date - if the date is between 1950 * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime * is used. */ public Time( Date date) { SimpleTimeZone tz = new SimpleTimeZone(0, "Z"); SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss"); dateF.setTimeZone(tz); String d = dateF.format(date) + "Z"; int year = Integer.parseInt(d.substring(0, 4)); if (year < 1950 || year > 2049) { time = new DERGeneralizedTime(d); } else { time = new DERUTCTime(d.substring(2)); } } public static Time getInstance( Object obj) { if (obj instanceof Time) { return (Time)obj; } else if (obj instanceof DERUTCTime) { return new Time((DERUTCTime)obj); } else if (obj instanceof DERGeneralizedTime) { return new Time((DERGeneralizedTime)obj); } throw new IllegalArgumentException("unknown object in factory"); } public String getTime() { if (time instanceof DERUTCTime) { return ((DERUTCTime)time).getAdjustedTime(); } else { return ((DERGeneralizedTime)time).getTime(); } } public Date getDate() { try { if (time instanceof DERUTCTime) { return ((DERUTCTime)time).getAdjustedDate(); } else { return ((DERGeneralizedTime)time).getDate(); } } catch (ParseException e) { // this should never happen throw new IllegalStateException("invalid date string: " + e.getMessage()); } } /** * Produce an object suitable for an ASN1OutputStream. *
           * Time ::= CHOICE {
           *             utcTime        UTCTime,
           *             generalTime    GeneralizedTime }
           * 
      */ public DERObject toASN1Object() { return time; } public String toString() { return getTime(); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/NameConstraints.java0000644000175000017500000000510311026315642023441 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import java.util.Enumeration; import java.util.Vector; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; public class NameConstraints extends ASN1Encodable { private ASN1Sequence permitted, excluded; public NameConstraints(ASN1Sequence seq) { Enumeration e = seq.getObjects(); while (e.hasMoreElements()) { ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement()); switch (o.getTagNo()) { case 0: permitted = ASN1Sequence.getInstance(o, false); break; case 1: excluded = ASN1Sequence.getInstance(o, false); break; } } } /** * Constructor from a given details. * *

      * permitted and excluded are Vectors of GeneralSubtree objects. * * @param permitted * Permitted subtrees * @param excluded * Excludes subtrees */ public NameConstraints( Vector permitted, Vector excluded) { if (permitted != null) { this.permitted = createSequence(permitted); } if (excluded != null) { this.excluded = createSequence(excluded); } } private DERSequence createSequence(Vector subtree) { ASN1EncodableVector vec = new ASN1EncodableVector(); Enumeration e = subtree.elements(); while (e.hasMoreElements()) { vec.add((GeneralSubtree)e.nextElement()); } return new DERSequence(vec); } public ASN1Sequence getPermittedSubtrees() { return permitted; } public ASN1Sequence getExcludedSubtrees() { return excluded; } /* * NameConstraints ::= SEQUENCE { permittedSubtrees [0] GeneralSubtrees * OPTIONAL, excludedSubtrees [1] GeneralSubtrees OPTIONAL } */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); if (permitted != null) { v.add(new DERTaggedObject(false, 0, permitted)); } if (excluded != null) { v.add(new DERTaggedObject(false, 1, excluded)); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/TBSCertList.java0000644000175000017500000001326711026315644022447 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERGeneralizedTime; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.DERUTCTime; /** * PKIX RFC-2459 - TBSCertList object. *

       * TBSCertList  ::=  SEQUENCE  {
       *      version                 Version OPTIONAL,
       *                                   -- if present, shall be v2
       *      signature               AlgorithmIdentifier,
       *      issuer                  Name,
       *      thisUpdate              Time,
       *      nextUpdate              Time OPTIONAL,
       *      revokedCertificates     SEQUENCE OF SEQUENCE  {
       *           userCertificate         CertificateSerialNumber,
       *           revocationDate          Time,
       *           crlEntryExtensions      Extensions OPTIONAL
       *                                         -- if present, shall be v2
       *                                }  OPTIONAL,
       *      crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
       *                                         -- if present, shall be v2
       *                                }
       * 
      */ public class TBSCertList extends ASN1Encodable { public class CRLEntry extends ASN1Encodable { ASN1Sequence seq; DERInteger userCertificate; Time revocationDate; X509Extensions crlEntryExtensions; public CRLEntry( ASN1Sequence seq) { if (seq.size() < 2 || seq.size() > 3) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } this.seq = seq; userCertificate = DERInteger.getInstance(seq.getObjectAt(0)); revocationDate = Time.getInstance(seq.getObjectAt(1)); if (seq.size() == 3) { crlEntryExtensions = X509Extensions.getInstance(seq.getObjectAt(2)); } } public DERInteger getUserCertificate() { return userCertificate; } public Time getRevocationDate() { return revocationDate; } public X509Extensions getExtensions() { return crlEntryExtensions; } public DERObject toASN1Object() { return seq; } } ASN1Sequence seq; DERInteger version; AlgorithmIdentifier signature; X509Name issuer; Time thisUpdate; Time nextUpdate; CRLEntry[] revokedCertificates; X509Extensions crlExtensions; public static TBSCertList getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static TBSCertList getInstance( Object obj) { if (obj instanceof TBSCertList) { return (TBSCertList)obj; } else if (obj instanceof ASN1Sequence) { return new TBSCertList((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory"); } public TBSCertList( ASN1Sequence seq) { if (seq.size() < 3 || seq.size() > 7) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } int seqPos = 0; this.seq = seq; if (seq.getObjectAt(seqPos) instanceof DERInteger) { version = DERInteger.getInstance(seq.getObjectAt(seqPos++)); } else { version = new DERInteger(0); } signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqPos++)); issuer = X509Name.getInstance(seq.getObjectAt(seqPos++)); thisUpdate = Time.getInstance(seq.getObjectAt(seqPos++)); if (seqPos < seq.size() && (seq.getObjectAt(seqPos) instanceof DERUTCTime || seq.getObjectAt(seqPos) instanceof DERGeneralizedTime || seq.getObjectAt(seqPos) instanceof Time)) { nextUpdate = Time.getInstance(seq.getObjectAt(seqPos++)); } if (seqPos < seq.size() && !(seq.getObjectAt(seqPos) instanceof DERTaggedObject)) { ASN1Sequence certs = ASN1Sequence.getInstance(seq.getObjectAt(seqPos++)); revokedCertificates = new CRLEntry[certs.size()]; for (int i = 0; i < revokedCertificates.length; i++) { revokedCertificates[i] = new CRLEntry(ASN1Sequence.getInstance(certs.getObjectAt(i))); } } if (seqPos < seq.size() && seq.getObjectAt(seqPos) instanceof DERTaggedObject) { crlExtensions = X509Extensions.getInstance(seq.getObjectAt(seqPos++)); } } public int getVersion() { return version.getValue().intValue() + 1; } public DERInteger getVersionNumber() { return version; } public AlgorithmIdentifier getSignature() { return signature; } public X509Name getIssuer() { return issuer; } public Time getThisUpdate() { return thisUpdate; } public Time getNextUpdate() { return nextUpdate; } public CRLEntry[] getRevokedCertificates() { return revokedCertificates; } public X509Extensions getExtensions() { return crlExtensions; } public DERObject toASN1Object() { return seq; } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/GeneralSubtree.java0000644000175000017500000001142311026315642023242 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; import java.math.BigInteger; /** * Class for containing a restriction object subtrees in NameConstraints. See * RFC 3280. * *
       *       
       *       GeneralSubtree ::= SEQUENCE 
       *       {
       *         base                    GeneralName,
       *         minimum         [0]     BaseDistance DEFAULT 0,
       *         maximum         [1]     BaseDistance OPTIONAL 
       *       }
       * 
      * * @see org.bouncycastle.asn1.x509.NameConstraints * */ public class GeneralSubtree extends ASN1Encodable { private static final BigInteger ZERO = BigInteger.valueOf(0); private GeneralName base; private DERInteger minimum; private DERInteger maximum; public GeneralSubtree( ASN1Sequence seq) { base = GeneralName.getInstance(seq.getObjectAt(0)); switch (seq.size()) { case 1: break; case 2: ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(1)); switch (o.getTagNo()) { case 0: minimum = DERInteger.getInstance(o, false); break; case 1: maximum = DERInteger.getInstance(o, false); break; default: throw new IllegalArgumentException("Bad tag number: " + o.getTagNo()); } break; case 3: minimum = DERInteger.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(1))); maximum = DERInteger.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(2))); break; default: throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } } /** * Constructor from a given details. * * According RFC 3280, the minimum and maximum fields are not used with any * name forms, thus minimum MUST be zero, and maximum MUST be absent. *

      * If minimum is null, zero is assumed, if * maximum is null, maximum is absent. * * @param base * A restriction. * @param minimum * Minimum * * @param maximum * Maximum */ public GeneralSubtree( GeneralName base, BigInteger minimum, BigInteger maximum) { this.base = base; if (maximum != null) { this.maximum = new DERInteger(maximum); } if (minimum == null) { this.minimum = null; } else { this.minimum = new DERInteger(minimum); } } public GeneralSubtree(GeneralName base) { this(base, null, null); } public static GeneralSubtree getInstance( ASN1TaggedObject o, boolean explicit) { return new GeneralSubtree(ASN1Sequence.getInstance(o, explicit)); } public static GeneralSubtree getInstance( Object obj) { if (obj == null) { return null; } if (obj instanceof GeneralSubtree) { return (GeneralSubtree) obj; } return new GeneralSubtree(ASN1Sequence.getInstance(obj)); } public GeneralName getBase() { return base; } public BigInteger getMinimum() { if (minimum == null) { return ZERO; } return minimum.getValue(); } public BigInteger getMaximum() { if (maximum == null) { return null; } return maximum.getValue(); } /** * Produce an object suitable for an ASN1OutputStream. * * Returns: * *

           *       GeneralSubtree ::= SEQUENCE 
           *       {
           *         base                    GeneralName,
           *         minimum         [0]     BaseDistance DEFAULT 0,
           *         maximum         [1]     BaseDistance OPTIONAL 
           *       }
           * 
      * * @return a DERObject */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(base); if (minimum != null && !minimum.getValue().equals(ZERO)) { v.add(new DERTaggedObject(false, 0, minimum)); } if (maximum != null) { v.add(new DERTaggedObject(false, 1, maximum)); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java0000644000175000017500000000570611026315626024261 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERIA5String; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; /** * Policy qualifiers, used in the X509V3 CertificatePolicies * extension. * *
       *   PolicyQualifierInfo ::= SEQUENCE {
       *       policyQualifierId  PolicyQualifierId,
       *       qualifier          ANY DEFINED BY policyQualifierId }
       * 
      */ public class PolicyQualifierInfo extends ASN1Encodable { private DERObjectIdentifier policyQualifierId; private DEREncodable qualifier; /** * Creates a new PolicyQualifierInfo instance. * * @param policyQualifierId a PolicyQualifierId value * @param qualifier the qualifier, defined by the above field. */ public PolicyQualifierInfo( DERObjectIdentifier policyQualifierId, DEREncodable qualifier) { this.policyQualifierId = policyQualifierId; this.qualifier = qualifier; } /** * Creates a new PolicyQualifierInfo containing a * cPSuri qualifier. * * @param cps the CPS (certification practice statement) uri as a * String. */ public PolicyQualifierInfo( String cps) { policyQualifierId = PolicyQualifierId.id_qt_cps; qualifier = new DERIA5String (cps); } /** * Creates a new PolicyQualifierInfo instance. * * @param as PolicyQualifierInfo X509 structure * encoded as an ASN1Sequence. */ public PolicyQualifierInfo( ASN1Sequence as) { if (as.size() != 2) { throw new IllegalArgumentException("Bad sequence size: " + as.size()); } policyQualifierId = DERObjectIdentifier.getInstance(as.getObjectAt(0)); qualifier = as.getObjectAt(1); } public static PolicyQualifierInfo getInstance( Object as) { if (as instanceof PolicyQualifierInfo) { return (PolicyQualifierInfo)as; } else if (as instanceof ASN1Sequence) { return new PolicyQualifierInfo((ASN1Sequence)as); } throw new IllegalArgumentException("unknown object in getInstance."); } public DERObjectIdentifier getPolicyQualifierId() { return policyQualifierId; } public DEREncodable getQualifier() { return qualifier; } /** * Returns a DER-encodable representation of this instance. * * @return a DERObject value */ public DERObject toASN1Object() { ASN1EncodableVector dev = new ASN1EncodableVector(); dev.add(policyQualifierId); dev.add(qualifier); return new DERSequence(dev); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/X509Extension.java0000644000175000017500000000371711026315642022704 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.DERBoolean; import java.io.IOException; /** * an object for the elements in the X.509 V3 extension block. */ public class X509Extension { boolean critical; ASN1OctetString value; public X509Extension( DERBoolean critical, ASN1OctetString value) { this.critical = critical.isTrue(); this.value = value; } public X509Extension( boolean critical, ASN1OctetString value) { this.critical = critical; this.value = value; } public boolean isCritical() { return critical; } public ASN1OctetString getValue() { return value; } public int hashCode() { if (this.isCritical()) { return this.getValue().hashCode(); } return ~this.getValue().hashCode(); } public boolean equals( Object o) { if (!(o instanceof X509Extension)) { return false; } X509Extension other = (X509Extension)o; return other.getValue().equals(this.getValue()) && (other.isCritical() == this.isCritical()); } /** * Convert the value of the passed in extension to an object * @param ext the extension to parse * @return the object the value string contains * @exception IllegalArgumentException if conversion is not possible */ public static ASN1Object convertValueToObject( X509Extension ext) throws IllegalArgumentException { try { return ASN1Object.fromByteArray(ext.getValue().getOctets()); } catch (IOException e) { throw new IllegalArgumentException("can't convert extension: " + e); } } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/IssuerSerial.java0000644000175000017500000000505211026315630022743 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; public class IssuerSerial extends ASN1Encodable { GeneralNames issuer; DERInteger serial; DERBitString issuerUID; public static IssuerSerial getInstance( Object obj) { if (obj == null || obj instanceof IssuerSerial) { return (IssuerSerial)obj; } if (obj instanceof ASN1Sequence) { return new IssuerSerial((ASN1Sequence)obj); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } public static IssuerSerial getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public IssuerSerial( ASN1Sequence seq) { if (seq.size() != 2 && seq.size() != 3) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } issuer = GeneralNames.getInstance(seq.getObjectAt(0)); serial = DERInteger.getInstance(seq.getObjectAt(1)); if (seq.size() == 3) { issuerUID = DERBitString.getInstance(seq.getObjectAt(2)); } } public IssuerSerial( GeneralNames issuer, DERInteger serial) { this.issuer = issuer; this.serial = serial; } public GeneralNames getIssuer() { return issuer; } public DERInteger getSerial() { return serial; } public DERBitString getIssuerUID() { return issuerUID; } /** * Produce an object suitable for an ASN1OutputStream. *
           *  IssuerSerial  ::=  SEQUENCE {
           *       issuer         GeneralNames,
           *       serial         CertificateSerialNumber,
           *       issuerUID      UniqueIdentifier OPTIONAL
           *  }
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(issuer); v.add(serial); if (issuerUID != null) { v.add(issuerUID); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/X509Extensions.java0000644000175000017500000002536611026315626023075 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBoolean; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; public class X509Extensions extends ASN1Encodable { /** * Subject Directory Attributes */ public static final DERObjectIdentifier SubjectDirectoryAttributes = new DERObjectIdentifier("2.5.29.9"); /** * Subject Key Identifier */ public static final DERObjectIdentifier SubjectKeyIdentifier = new DERObjectIdentifier("2.5.29.14"); /** * Key Usage */ public static final DERObjectIdentifier KeyUsage = new DERObjectIdentifier("2.5.29.15"); /** * Private Key Usage Period */ public static final DERObjectIdentifier PrivateKeyUsagePeriod = new DERObjectIdentifier("2.5.29.16"); /** * Subject Alternative Name */ public static final DERObjectIdentifier SubjectAlternativeName = new DERObjectIdentifier("2.5.29.17"); /** * Issuer Alternative Name */ public static final DERObjectIdentifier IssuerAlternativeName = new DERObjectIdentifier("2.5.29.18"); /** * Basic Constraints */ public static final DERObjectIdentifier BasicConstraints = new DERObjectIdentifier("2.5.29.19"); /** * CRL Number */ public static final DERObjectIdentifier CRLNumber = new DERObjectIdentifier("2.5.29.20"); /** * Reason code */ public static final DERObjectIdentifier ReasonCode = new DERObjectIdentifier("2.5.29.21"); /** * Hold Instruction Code */ public static final DERObjectIdentifier InstructionCode = new DERObjectIdentifier("2.5.29.23"); /** * Invalidity Date */ public static final DERObjectIdentifier InvalidityDate = new DERObjectIdentifier("2.5.29.24"); /** * Delta CRL indicator */ public static final DERObjectIdentifier DeltaCRLIndicator = new DERObjectIdentifier("2.5.29.27"); /** * Issuing Distribution Point */ public static final DERObjectIdentifier IssuingDistributionPoint = new DERObjectIdentifier("2.5.29.28"); /** * Certificate Issuer */ public static final DERObjectIdentifier CertificateIssuer = new DERObjectIdentifier("2.5.29.29"); /** * Name Constraints */ public static final DERObjectIdentifier NameConstraints = new DERObjectIdentifier("2.5.29.30"); /** * CRL Distribution Points */ public static final DERObjectIdentifier CRLDistributionPoints = new DERObjectIdentifier("2.5.29.31"); /** * Certificate Policies */ public static final DERObjectIdentifier CertificatePolicies = new DERObjectIdentifier("2.5.29.32"); /** * Policy Mappings */ public static final DERObjectIdentifier PolicyMappings = new DERObjectIdentifier("2.5.29.33"); /** * Authority Key Identifier */ public static final DERObjectIdentifier AuthorityKeyIdentifier = new DERObjectIdentifier("2.5.29.35"); /** * Policy Constraints */ public static final DERObjectIdentifier PolicyConstraints = new DERObjectIdentifier("2.5.29.36"); /** * Extended Key Usage */ public static final DERObjectIdentifier ExtendedKeyUsage = new DERObjectIdentifier("2.5.29.37"); /** * Freshest CRL */ public static final DERObjectIdentifier FreshestCRL = new DERObjectIdentifier("2.5.29.46"); /** * Inhibit Any Policy */ public static final DERObjectIdentifier InhibitAnyPolicy = new DERObjectIdentifier("2.5.29.54"); /** * Authority Info Access */ public static final DERObjectIdentifier AuthorityInfoAccess = new DERObjectIdentifier("1.3.6.1.5.5.7.1.1"); /** * Subject Info Access */ public static final DERObjectIdentifier SubjectInfoAccess = new DERObjectIdentifier("1.3.6.1.5.5.7.1.11"); /** * Logo Type */ public static final DERObjectIdentifier LogoType = new DERObjectIdentifier("1.3.6.1.5.5.7.1.12"); /** * BiometricInfo */ public static final DERObjectIdentifier BiometricInfo = new DERObjectIdentifier("1.3.6.1.5.5.7.1.2"); /** * QCStatements */ public static final DERObjectIdentifier QCStatements = new DERObjectIdentifier("1.3.6.1.5.5.7.1.3"); /** * Audit identity extension in attribute certificates. */ public static final DERObjectIdentifier AuditIdentity = new DERObjectIdentifier("1.3.6.1.5.5.7.1.4"); /** * NoRevAvail extension in attribute certificates. */ public static final DERObjectIdentifier NoRevAvail = new DERObjectIdentifier("2.5.29.56"); /** * TargetInformation extension in attribute certificates. */ public static final DERObjectIdentifier TargetInformation = new DERObjectIdentifier("2.5.29.55"); private Hashtable extensions = new Hashtable(); private Vector ordering = new Vector(); public static X509Extensions getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } public static X509Extensions getInstance( Object obj) { if (obj == null || obj instanceof X509Extensions) { return (X509Extensions)obj; } if (obj instanceof ASN1Sequence) { return new X509Extensions((ASN1Sequence)obj); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * Constructor from ASN1Sequence. * * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString) */ public X509Extensions( ASN1Sequence seq) { Enumeration e = seq.getObjects(); while (e.hasMoreElements()) { ASN1Sequence s = ASN1Sequence.getInstance(e.nextElement()); if (s.size() == 3) { extensions.put(s.getObjectAt(0), new X509Extension(DERBoolean.getInstance(s.getObjectAt(1)), ASN1OctetString.getInstance(s.getObjectAt(2)))); } else if (s.size() == 2) { extensions.put(s.getObjectAt(0), new X509Extension(false, ASN1OctetString.getInstance(s.getObjectAt(1)))); } else { throw new IllegalArgumentException("Bad sequence size: " + s.size()); } ordering.addElement(s.getObjectAt(0)); } } /** * constructor from a table of extensions. *

      * it's is assumed the table contains OID/String pairs. */ public X509Extensions( Hashtable extensions) { this(null, extensions); } /** * Constructor from a table of extensions with ordering. *

      * It's is assumed the table contains OID/String pairs. */ public X509Extensions( Vector ordering, Hashtable extensions) { Enumeration e; if (ordering == null) { e = extensions.keys(); } else { e = ordering.elements(); } while (e.hasMoreElements()) { this.ordering.addElement(e.nextElement()); } e = this.ordering.elements(); while (e.hasMoreElements()) { DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); X509Extension ext = (X509Extension)extensions.get(oid); this.extensions.put(oid, ext); } } /** * Constructor from two vectors * * @param objectIDs a vector of the object identifiers. * @param values a vector of the extension values. */ public X509Extensions( Vector objectIDs, Vector values) { Enumeration e = objectIDs.elements(); while (e.hasMoreElements()) { this.ordering.addElement(e.nextElement()); } int count = 0; e = this.ordering.elements(); while (e.hasMoreElements()) { DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); X509Extension ext = (X509Extension)values.elementAt(count); this.extensions.put(oid, ext); count++; } } /** * return an Enumeration of the extension field's object ids. */ public Enumeration oids() { return ordering.elements(); } /** * return the extension represented by the object identifier * passed in. * * @return the extension if it's present, null otherwise. */ public X509Extension getExtension( DERObjectIdentifier oid) { return (X509Extension)extensions.get(oid); } /** *

           *     Extensions        ::=   SEQUENCE SIZE (1..MAX) OF Extension
           *
           *     Extension         ::=   SEQUENCE {
           *        extnId            EXTENSION.&id ({ExtensionSet}),
           *        critical          BOOLEAN DEFAULT FALSE,
           *        extnValue         OCTET STRING }
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector vec = new ASN1EncodableVector(); Enumeration e = ordering.elements(); while (e.hasMoreElements()) { DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); X509Extension ext = (X509Extension)extensions.get(oid); ASN1EncodableVector v = new ASN1EncodableVector(); v.add(oid); if (ext.isCritical()) { v.add(new DERBoolean(true)); } v.add(ext.getValue()); vec.add(new DERSequence(v)); } return new DERSequence(vec); } public boolean equivalent( X509Extensions other) { if (extensions.size() != other.extensions.size()) { return false; } Enumeration e1 = extensions.keys(); while (e1.hasMoreElements()) { Object key = e1.nextElement(); if (!extensions.get(key).equals(other.extensions.get(key))) { return false; } } return true; } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/ObjectDigestInfo.java0000644000175000017500000001226211026315642023517 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DEREnumerated; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; /** * ObjectDigestInfo ASN.1 structure used in v2 attribute certificates. * *
       *  
       *    ObjectDigestInfo ::= SEQUENCE {
       *         digestedObjectType  ENUMERATED {
       *                 publicKey            (0),
       *                 publicKeyCert        (1),
       *                 otherObjectTypes     (2) },
       *                         -- otherObjectTypes MUST NOT
       *                         -- be used in this profile
       *         otherObjectTypeID   OBJECT IDENTIFIER OPTIONAL,
       *         digestAlgorithm     AlgorithmIdentifier,
       *         objectDigest        BIT STRING
       *    }
       *   
       * 
      * */ public class ObjectDigestInfo extends ASN1Encodable { /** * The public key is hashed. */ public final static int publicKey = 0; /** * The public key certificate is hashed. */ public final static int publicKeyCert = 1; /** * An other object is hashed. */ public final static int otherObjectDigest = 2; DEREnumerated digestedObjectType; DERObjectIdentifier otherObjectTypeID; AlgorithmIdentifier digestAlgorithm; DERBitString objectDigest; public static ObjectDigestInfo getInstance( Object obj) { if (obj == null || obj instanceof ObjectDigestInfo) { return (ObjectDigestInfo)obj; } if (obj instanceof ASN1Sequence) { return new ObjectDigestInfo((ASN1Sequence)obj); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } public static ObjectDigestInfo getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } /** * Constructor from given details. *

      * If digestedObjectType is not {@link #publicKeyCert} or * {@link #publicKey} otherObjectTypeID must be given, * otherwise it is ignored. * * @param digestedObjectType The digest object type. * @param otherObjectTypeID The object type ID for * otherObjectDigest. * @param digestAlgorithm The algorithm identifier for the hash. * @param objectDigest The hash value. */ public ObjectDigestInfo( int digestedObjectType, String otherObjectTypeID, AlgorithmIdentifier digestAlgorithm, byte[] objectDigest) { this.digestedObjectType = new DEREnumerated(digestedObjectType); if (digestedObjectType == otherObjectDigest) { this.otherObjectTypeID = new DERObjectIdentifier(otherObjectTypeID); } this.digestAlgorithm = digestAlgorithm; this.objectDigest = new DERBitString(objectDigest); } private ObjectDigestInfo( ASN1Sequence seq) { if (seq.size() > 4 || seq.size() < 3) { throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } digestedObjectType = DEREnumerated.getInstance(seq.getObjectAt(0)); int offset = 0; if (seq.size() == 4) { otherObjectTypeID = DERObjectIdentifier.getInstance(seq.getObjectAt(1)); offset++; } digestAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1 + offset)); objectDigest = DERBitString.getInstance(seq.getObjectAt(2 + offset)); } public DEREnumerated getDigestedObjectType() { return digestedObjectType; } public DERObjectIdentifier getOtherObjectTypeID() { return otherObjectTypeID; } public AlgorithmIdentifier getDigestAlgorithm() { return digestAlgorithm; } public DERBitString getObjectDigest() { return objectDigest; } /** * Produce an object suitable for an ASN1OutputStream. * *

           *  
           *    ObjectDigestInfo ::= SEQUENCE {
           *         digestedObjectType  ENUMERATED {
           *                 publicKey            (0),
           *                 publicKeyCert        (1),
           *                 otherObjectTypes     (2) },
           *                         -- otherObjectTypes MUST NOT
           *                         -- be used in this profile
           *         otherObjectTypeID   OBJECT IDENTIFIER OPTIONAL,
           *         digestAlgorithm     AlgorithmIdentifier,
           *         objectDigest        BIT STRING
           *    }
           *   
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(digestedObjectType); if (otherObjectTypeID != null) { v.add(otherObjectTypeID); } v.add(digestAlgorithm); v.add(objectDigest); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/DisplayText.java0000644000175000017500000001062211026315666022613 0ustar adrianadrian package org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Choice; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERBMPString; import org.bouncycastle.asn1.DERIA5String; import org.bouncycastle.asn1.DERUTF8String; import org.bouncycastle.asn1.DERVisibleString; import org.bouncycastle.asn1.DERString; /** * DisplayText class, used in * CertificatePolicies X509 V3 extensions (in policy qualifiers). * *

      It stores a string in a chosen encoding. *

       * DisplayText ::= CHOICE {
       *      ia5String        IA5String      (SIZE (1..200)),
       *      visibleString    VisibleString  (SIZE (1..200)),
       *      bmpString        BMPString      (SIZE (1..200)),
       *      utf8String       UTF8String     (SIZE (1..200)) }
       * 
      * @see PolicyQualifierInfo * @see PolicyInformation */ public class DisplayText extends ASN1Encodable implements ASN1Choice { /** * Constant corresponding to ia5String encoding. * */ public static final int CONTENT_TYPE_IA5STRING = 0; /** * Constant corresponding to bmpString encoding. * */ public static final int CONTENT_TYPE_BMPSTRING = 1; /** * Constant corresponding to utf8String encoding. * */ public static final int CONTENT_TYPE_UTF8STRING = 2; /** * Constant corresponding to visibleString encoding. * */ public static final int CONTENT_TYPE_VISIBLESTRING = 3; /** * Describe constant DISPLAY_TEXT_MAXIMUM_SIZE here. * */ public static final int DISPLAY_TEXT_MAXIMUM_SIZE = 200; int contentType; DERString contents; /** * Creates a new DisplayText instance. * * @param type the desired encoding type for the text. * @param text the text to store. Strings longer than 200 * characters are truncated. */ public DisplayText (int type, String text) { if (text.length() > DISPLAY_TEXT_MAXIMUM_SIZE) { // RFC3280 limits these strings to 200 chars // truncate the string text = text.substring (0, DISPLAY_TEXT_MAXIMUM_SIZE); } contentType = type; switch (type) { case CONTENT_TYPE_IA5STRING: contents = (DERString)new DERIA5String (text); break; case CONTENT_TYPE_UTF8STRING: contents = (DERString)new DERUTF8String(text); break; case CONTENT_TYPE_VISIBLESTRING: contents = (DERString)new DERVisibleString(text); break; case CONTENT_TYPE_BMPSTRING: contents = (DERString)new DERBMPString(text); break; default: contents = (DERString)new DERUTF8String(text); break; } } /** * Creates a new DisplayText instance. * * @param text the text to encapsulate. Strings longer than 200 * characters are truncated. */ public DisplayText (String text) { // by default use UTF8String if (text.length() > DISPLAY_TEXT_MAXIMUM_SIZE) { text = text.substring(0, DISPLAY_TEXT_MAXIMUM_SIZE); } contentType = CONTENT_TYPE_UTF8STRING; contents = new DERUTF8String(text); } /** * Creates a new DisplayText instance. *

      Useful when reading back a DisplayText class * from it's ASN1Encodable/DEREncodable form. * * @param de a DEREncodable instance. */ public DisplayText(DERString de) { contents = de; } public static DisplayText getInstance(Object de) { if (de instanceof DERString) { return new DisplayText((DERString)de); } else if (de instanceof DisplayText) { return (DisplayText)de; } throw new IllegalArgumentException("illegal object in getInstance"); } public static DisplayText getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); // must be explicitly tagged } public DERObject toASN1Object() { return (DERObject)contents; } /** * Returns the stored String object. * * @return the stored text as a String. */ public String getString() { return contents.getString(); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/DistributionPointName.java0000644000175000017500000000675411026315644024642 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import org.bouncycastle.asn1.ASN1Choice; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERTaggedObject; /** * The DistributionPointName object. *

       * DistributionPointName ::= CHOICE {
       *     fullName                 [0] GeneralNames,
       *     nameRelativeToCRLIssuer  [1] RelativeDistinguishedName
       * }
       * 
      */ public class DistributionPointName extends ASN1Encodable implements ASN1Choice { DEREncodable name; int type; public static final int FULL_NAME = 0; public static final int NAME_RELATIVE_TO_CRL_ISSUER = 1; public static DistributionPointName getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1TaggedObject.getInstance(obj, true)); } public static DistributionPointName getInstance( Object obj) { if (obj == null || obj instanceof DistributionPointName) { return (DistributionPointName)obj; } else if (obj instanceof ASN1TaggedObject) { return new DistributionPointName((ASN1TaggedObject)obj); } throw new IllegalArgumentException("unknown object in factory"); } /* * @deprecated use ASN1Encodable */ public DistributionPointName( int type, DEREncodable name) { this.type = type; this.name = name; } public DistributionPointName( int type, ASN1Encodable name) { this.type = type; this.name = name; } /** * Return the tag number applying to the underlying choice. * * @return the tag number for this point name. */ public int getType() { return this.type; } /** * Return the tagged object inside the distribution point name. * * @return the underlying choice item. */ public ASN1Encodable getName() { return (ASN1Encodable)name; } public DistributionPointName( ASN1TaggedObject obj) { this.type = obj.getTagNo(); if (type == 0) { this.name = GeneralNames.getInstance(obj, false); } else { this.name = ASN1Set.getInstance(obj, false); } } public DERObject toASN1Object() { return new DERTaggedObject(false, type, name); } public String toString() { String sep = System.getProperty("line.separator"); StringBuffer buf = new StringBuffer(); buf.append("DistributionPointName: ["); buf.append(sep); if (type == FULL_NAME) { appendObject(buf, sep, "fullName", name.toString()); } else { appendObject(buf, sep, "nameRelativeToCRLIssuer", name.toString()); } buf.append("]"); buf.append(sep); return buf.toString(); } private void appendObject(StringBuffer buf, String sep, String name, String value) { String indent = " "; buf.append(indent); buf.append(name); buf.append(":"); buf.append(sep); buf.append(indent); buf.append(indent); buf.append(value); buf.append(sep); } } azureus-4.3.0.6/org/bouncycastle/asn1/x509/SubjectDirectoryAttributes.java0000644000175000017500000000727111026315636025677 0ustar adrianadrianpackage org.bouncycastle.asn1.x509; import java.util.Enumeration; import java.util.Vector; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; /** * This extension may contain further X.500 attributes of the subject. See also * RFC 3039. * *
       *     SubjectDirectoryAttributes ::= Attributes
       *     Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
       *     Attribute ::= SEQUENCE 
       *     {
       *       type AttributeType 
       *       values SET OF AttributeValue 
       *     }
       *     
       *     AttributeType ::= OBJECT IDENTIFIER
       *     AttributeValue ::= ANY DEFINED BY AttributeType
       * 
      * * @see org.bouncycastle.asn1.x509.X509Name for AttributeType ObjectIdentifiers. */ public class SubjectDirectoryAttributes extends ASN1Encodable { private Vector attributes = new Vector(); public static SubjectDirectoryAttributes getInstance( Object obj) { if (obj == null || obj instanceof SubjectDirectoryAttributes) { return (SubjectDirectoryAttributes)obj; } if (obj instanceof ASN1Sequence) { return new SubjectDirectoryAttributes((ASN1Sequence)obj); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * Constructor from ASN1Sequence. * * The sequence is of type SubjectDirectoryAttributes: * *
           *      SubjectDirectoryAttributes ::= Attributes
           *      Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
           *      Attribute ::= SEQUENCE 
           *      {
           *        type AttributeType 
           *        values SET OF AttributeValue 
           *      }
           *      
           *      AttributeType ::= OBJECT IDENTIFIER
           *      AttributeValue ::= ANY DEFINED BY AttributeType
           * 
      * * @param seq * The ASN.1 sequence. */ public SubjectDirectoryAttributes(ASN1Sequence seq) { Enumeration e = seq.getObjects(); while (e.hasMoreElements()) { ASN1Sequence s = ASN1Sequence.getInstance(e.nextElement()); attributes.addElement(new Attribute(s)); } } /** * Constructor from a vector of attributes. * * The vector consists of attributes of type {@link Attribute Attribute} * * @param attributes * The attributes. * */ public SubjectDirectoryAttributes(Vector attributes) { Enumeration e = attributes.elements(); while (e.hasMoreElements()) { this.attributes.addElement(e.nextElement()); } } /** * Produce an object suitable for an ASN1OutputStream. * * Returns: * *
           *      SubjectDirectoryAttributes ::= Attributes
           *      Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
           *      Attribute ::= SEQUENCE 
           *      {
           *        type AttributeType 
           *        values SET OF AttributeValue 
           *      }
           *      
           *      AttributeType ::= OBJECT IDENTIFIER
           *      AttributeValue ::= ANY DEFINED BY AttributeType
           * 
      * * @return a DERObject */ public DERObject toASN1Object() { ASN1EncodableVector vec = new ASN1EncodableVector(); Enumeration e = attributes.elements(); while (e.hasMoreElements()) { vec.add((Attribute)e.nextElement()); } return new DERSequence(vec); } /** * @return Returns the attributes. */ public Vector getAttributes() { return attributes; } } azureus-4.3.0.6/org/bouncycastle/asn1/DERTaggedObject.java0000644000175000017500000000422111026315566022506 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * DER TaggedObject - in ASN.1 nottation this is any object proceeded by * a [n] where n is some number - these are assume to follow the construction * rules (as with sequences). */ public class DERTaggedObject extends ASN1TaggedObject { /** * @param tagNo the tag number for this object. * @param obj the tagged object. */ public DERTaggedObject( int tagNo, DEREncodable obj) { super(tagNo, obj); } /** * @param explicit true if an explicitly tagged object. * @param tagNo the tag number for this object. * @param obj the tagged object. */ public DERTaggedObject( boolean explicit, int tagNo, DEREncodable obj) { super(explicit, tagNo, obj); } /** * create an implicitly tagged object that contains a zero * length sequence. */ public DERTaggedObject( int tagNo) { super(false, tagNo, new DERSequence()); } void encode( DEROutputStream out) throws IOException { if (!empty) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); dOut.writeObject(obj); dOut.close(); byte[] bytes = bOut.toByteArray(); if (explicit) { out.writeEncoded(CONSTRUCTED | TAGGED | tagNo, bytes); } else { // // need to mark constructed types... // if ((bytes[0] & CONSTRUCTED) != 0) { bytes[0] = (byte)(CONSTRUCTED | TAGGED | tagNo); } else { bytes[0] = (byte)(TAGGED | tagNo); } out.write(bytes); } } else { out.writeEncoded(CONSTRUCTED | TAGGED | tagNo, new byte[0]); } } } azureus-4.3.0.6/org/bouncycastle/asn1/DERUTF8String.java0000644000175000017500000000460511026315606022102 0ustar adrianadrianpackage org.bouncycastle.asn1; import org.bouncycastle.util.Strings; import java.io.IOException; /** * DER UTF8String object. */ public class DERUTF8String extends ASN1Object implements DERString { String string; /** * return an UTF8 string from the passed in object. * * @exception IllegalArgumentException * if the object cannot be converted. */ public static DERUTF8String getInstance(Object obj) { if (obj == null || obj instanceof DERUTF8String) { return (DERUTF8String)obj; } if (obj instanceof ASN1OctetString) { return new DERUTF8String(((ASN1OctetString)obj).getOctets()); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return an UTF8 String from a tagged object. * * @param obj * the tagged object holding the object we want * @param explicit * true if the object is meant to be explicitly tagged false * otherwise. * @exception IllegalArgumentException * if the tagged object cannot be converted. */ public static DERUTF8String getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } /** * basic constructor - byte encoded string. */ DERUTF8String(byte[] string) { this.string = Strings.fromUTF8ByteArray(string); } /** * basic constructor */ public DERUTF8String(String string) { this.string = string; } public String getString() { return string; } public String toString() { return string; } public int hashCode() { return this.getString().hashCode(); } boolean asn1Equals(DERObject o) { if (!(o instanceof DERUTF8String)) { return false; } DERUTF8String s = (DERUTF8String)o; return this.getString().equals(s.getString()); } void encode(DEROutputStream out) throws IOException { out.writeEncoded(UTF8_STRING, Strings.toUTF8ByteArray(string)); } } azureus-4.3.0.6/org/bouncycastle/asn1/DERVisibleString.java0000644000175000017500000000534011026315576022754 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; /** * DER VisibleString object. */ public class DERVisibleString extends ASN1Object implements DERString { String string; /** * return a Visible String from the passed in object. * * @exception IllegalArgumentException if the object cannot be converted. */ public static DERVisibleString getInstance( Object obj) { if (obj == null || obj instanceof DERVisibleString) { return (DERVisibleString)obj; } if (obj instanceof ASN1OctetString) { return new DERVisibleString(((ASN1OctetString)obj).getOctets()); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return a Visible String from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERVisibleString getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } /** * basic constructor - byte encoded string. */ public DERVisibleString( byte[] string) { char[] cs = new char[string.length]; for (int i = 0; i != cs.length; i++) { cs[i] = (char)(string[i] & 0xff); } this.string = new String(cs); } /** * basic constructor */ public DERVisibleString( String string) { this.string = string; } public String getString() { return string; } public String toString() { return string; } public byte[] getOctets() { char[] cs = string.toCharArray(); byte[] bs = new byte[cs.length]; for (int i = 0; i != cs.length; i++) { bs[i] = (byte)cs[i]; } return bs; } void encode( DEROutputStream out) throws IOException { out.writeEncoded(VISIBLE_STRING, this.getOctets()); } boolean asn1Equals( DERObject o) { if (!(o instanceof DERVisibleString)) { return false; } return this.getString().equals(((DERVisibleString)o).getString()); } public int hashCode() { return this.getString().hashCode(); } } azureus-4.3.0.6/org/bouncycastle/asn1/DERGeneralizedTime.java0000644000175000017500000001665111026315610023234 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.SimpleTimeZone; import java.util.TimeZone; /** * Generalized time object. */ public class DERGeneralizedTime extends ASN1Object { String time; /** * return a generalized time from the passed in object * * @exception IllegalArgumentException if the object cannot be converted. */ public static DERGeneralizedTime getInstance( Object obj) { if (obj == null || obj instanceof DERGeneralizedTime) { return (DERGeneralizedTime)obj; } if (obj instanceof ASN1OctetString) { return new DERGeneralizedTime(((ASN1OctetString)obj).getOctets()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return a Generalized Time object from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERGeneralizedTime getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } /** * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z * for local time, or Z+-HHMM on the end, for difference between local * time and UTC time. The fractional second amount f must consist of at * least one number with trailing zeroes removed. * * @param time the time string. * @exception IllegalArgumentException if String is an illegal format. */ public DERGeneralizedTime( String time) { this.time = time; try { this.getDate(); } catch (ParseException e) { throw new IllegalArgumentException("invalid date string: " + e.getMessage()); } } /** * base constructer from a java.util.date object */ public DERGeneralizedTime( Date time) { SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'"); dateF.setTimeZone(new SimpleTimeZone(0,"Z")); this.time = dateF.format(time); } DERGeneralizedTime( byte[] bytes) { // // explicitly convert to characters // char[] dateC = new char[bytes.length]; for (int i = 0; i != dateC.length; i++) { dateC[i] = (char)(bytes[i] & 0xff); } this.time = new String(dateC); } /** * Return the time. * @return The time string as it appeared in the encoded object. */ public String getTimeString() { return time; } /** * return the time - always in the form of * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm). *

      * Normally in a certificate we would expect "Z" rather than "GMT", * however adding the "GMT" means we can just use: *

           *     dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
           * 
      * To read in the time and get a date which is compatible with our local * time zone. */ public String getTime() { // // standardise the format. // if (time.charAt(time.length() - 1) == 'Z') { return time.substring(0, time.length() - 1) + "GMT+00:00"; } else { int signPos = time.length() - 5; char sign = time.charAt(signPos); if (sign == '-' || sign == '+') { return time.substring(0, signPos) + "GMT" + time.substring(signPos, signPos + 3) + ":" + time.substring(signPos + 3); } else { signPos = time.length() - 3; sign = time.charAt(signPos); if (sign == '-' || sign == '+') { return time.substring(0, signPos) + "GMT" + time.substring(signPos) + ":00"; } } } return time + calculateGMTOffset(); } private String calculateGMTOffset() { String sign = "+"; TimeZone timeZone = TimeZone.getDefault(); int offset = timeZone.getRawOffset(); if (offset < 0) { sign = "-"; offset = -offset; } int hours = offset / (60 * 60 * 1000); int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000); try { if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate())) { hours += sign.equals("+") ? 1 : -1; } } catch (ParseException e) { // we'll do our best and ignore daylight savings } return "GMT" + sign + convert(hours) + ":" + convert(minutes); } private String convert(int time) { if (time < 10) { return "0" + time; } return Integer.toString(time); } public Date getDate() throws ParseException { SimpleDateFormat dateF; String d = time; if (time.endsWith("Z")) { if (hasFractionalSeconds()) { dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSS'Z'"); } else { dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'"); } dateF.setTimeZone(new SimpleTimeZone(0, "Z")); } else if (time.indexOf('-') > 0 || time.indexOf('+') > 0) { d = this.getTime(); if (hasFractionalSeconds()) { dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSSz"); } else { dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); } dateF.setTimeZone(new SimpleTimeZone(0, "Z")); } else { if (hasFractionalSeconds()) { dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSS"); } else { dateF = new SimpleDateFormat("yyyyMMddHHmmss"); } dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID())); } return dateF.parse(d); } private boolean hasFractionalSeconds() { return time.indexOf('.') == 14; } private byte[] getOctets() { char[] cs = time.toCharArray(); byte[] bs = new byte[cs.length]; for (int i = 0; i != cs.length; i++) { bs[i] = (byte)cs[i]; } return bs; } void encode( DEROutputStream out) throws IOException { out.writeEncoded(GENERALIZED_TIME, this.getOctets()); } boolean asn1Equals( DERObject o) { if (!(o instanceof DERGeneralizedTime)) { return false; } return time.equals(((DERGeneralizedTime)o).time); } public int hashCode() { return time.hashCode(); } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1Generator.java0000644000175000017500000000042311026315606022175 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.OutputStream; public abstract class ASN1Generator { protected OutputStream _out; public ASN1Generator(OutputStream out) { _out = out; } public abstract OutputStream getRawOutputStream(); } azureus-4.3.0.6/org/bouncycastle/asn1/DERSet.java0000644000175000017500000000403411026315610020707 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Enumeration; /** * A DER encoded set object */ public class DERSet extends ASN1Set { /** * create an empty set */ public DERSet() { } /** * @param obj - a single object that makes up the set. */ public DERSet( DEREncodable obj) { this.addObject(obj); } /** * @param v - a vector of objects making up the set. */ public DERSet( DEREncodableVector v) { this(v, true); } /** * create a set from an array of objects. */ public DERSet( ASN1Encodable[] a) { for (int i = 0; i != a.length; i++) { this.addObject(a[i]); } this.sort(); } /** * @param v - a vector of objects making up the set. */ DERSet( DEREncodableVector v, boolean needsSorting) { for (int i = 0; i != v.size(); i++) { this.addObject(v.get(i)); } if (needsSorting) { this.sort(); } } /* * A note on the implementation: *

      * As DER requires the constructed, definite-length model to * be used for structured types, this varies slightly from the * ASN.1 descriptions given. Rather than just outputing SET, * we also have to specify CONSTRUCTED, and the objects length. */ void encode( DEROutputStream out) throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); Enumeration e = this.getObjects(); while (e.hasMoreElements()) { Object obj = e.nextElement(); dOut.writeObject(obj); } dOut.close(); byte[] bytes = bOut.toByteArray(); out.writeEncoded(SET | CONSTRUCTED, bytes); } } azureus-4.3.0.6/org/bouncycastle/asn1/teletrust/0000755000175000017500000000000011310377632021020 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java0000644000175000017500000000204310061400656027065 0ustar adrianadrianpackage org.bouncycastle.asn1.teletrust; import org.bouncycastle.asn1.DERObjectIdentifier; public interface TeleTrusTObjectIdentifiers { static final String teleTrusTAlgorithm = "1.3.36.3"; static final DERObjectIdentifier ripemd160 = new DERObjectIdentifier(teleTrusTAlgorithm + ".2.1"); static final DERObjectIdentifier ripemd128 = new DERObjectIdentifier(teleTrusTAlgorithm + ".2.2"); static final DERObjectIdentifier ripemd256 = new DERObjectIdentifier(teleTrusTAlgorithm + ".2.3"); static final String teleTrusTRSAsignatureAlgorithm = teleTrusTAlgorithm + ".3.1"; static final DERObjectIdentifier rsaSignatureWithripemd160 = new DERObjectIdentifier(teleTrusTRSAsignatureAlgorithm + ".2"); static final DERObjectIdentifier rsaSignatureWithripemd128 = new DERObjectIdentifier(teleTrusTRSAsignatureAlgorithm + ".3"); static final DERObjectIdentifier rsaSignatureWithripemd256 = new DERObjectIdentifier(teleTrusTRSAsignatureAlgorithm + ".4"); } azureus-4.3.0.6/org/bouncycastle/asn1/DERInputStream.java0000644000175000017500000001616211026315576022447 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayInputStream; import java.io.EOFException; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; /** * Don't use this class. It will eventually disappear, use ASN1InputStream. *
      * This class is scheduled for removal. * @deprecated use ASN1InputStream */ public class DERInputStream extends FilterInputStream implements DERTags { /** * @deprecated use ASN1InputStream */ public DERInputStream( InputStream is) { super(is); } protected int readLength() throws IOException { int length = read(); if (length < 0) { throw new IOException("EOF found when length expected"); } if (length == 0x80) { return -1; // indefinite-length encoding } if (length > 127) { int size = length & 0x7f; if (size > 4) { throw new IOException("DER length more than 4 bytes"); } length = 0; for (int i = 0; i < size; i++) { int next = read(); if (next < 0) { throw new IOException("EOF found reading length"); } length = (length << 8) + next; } if (length < 0) { throw new IOException("corrupted stream - negative length found"); } } return length; } protected void readFully( byte[] bytes) throws IOException { int left = bytes.length; if (left == 0) { return; } while (left > 0) { int l = read(bytes, bytes.length - left, left); if (l < 0) { throw new EOFException("unexpected end of stream"); } left -= l; } } /** * build an object given its tag and a byte stream to construct it * from. */ protected DERObject buildObject( int tag, byte[] bytes) throws IOException { switch (tag) { case NULL: return null; case SEQUENCE | CONSTRUCTED: ByteArrayInputStream bIn = new ByteArrayInputStream(bytes); BERInputStream dIn = new BERInputStream(bIn); DERConstructedSequence seq = new DERConstructedSequence(); try { for (;;) { DERObject obj = dIn.readObject(); seq.addObject(obj); } } catch (EOFException ex) { return seq; } case SET | CONSTRUCTED: bIn = new ByteArrayInputStream(bytes); dIn = new BERInputStream(bIn); ASN1EncodableVector v = new ASN1EncodableVector(); try { for (;;) { DERObject obj = dIn.readObject(); v.add(obj); } } catch (EOFException ex) { return new DERConstructedSet(v); } case BOOLEAN: return new DERBoolean(bytes); case INTEGER: return new DERInteger(bytes); case ENUMERATED: return new DEREnumerated(bytes); case OBJECT_IDENTIFIER: return new DERObjectIdentifier(bytes); case BIT_STRING: int padBits = bytes[0]; byte[] data = new byte[bytes.length - 1]; System.arraycopy(bytes, 1, data, 0, bytes.length - 1); return new DERBitString(data, padBits); case UTF8_STRING: return new DERUTF8String(bytes); case PRINTABLE_STRING: return new DERPrintableString(bytes); case IA5_STRING: return new DERIA5String(bytes); case T61_STRING: return new DERT61String(bytes); case VISIBLE_STRING: return new DERVisibleString(bytes); case UNIVERSAL_STRING: return new DERUniversalString(bytes); case GENERAL_STRING: return new DERGeneralString(bytes); case BMP_STRING: return new DERBMPString(bytes); case OCTET_STRING: return new DEROctetString(bytes); case UTC_TIME: return new DERUTCTime(bytes); case GENERALIZED_TIME: return new DERGeneralizedTime(bytes); default: // // with tagged object tag number is bottom 5 bits // if ((tag & TAGGED) != 0) { if ((tag & 0x1f) == 0x1f) { throw new IOException("unsupported high tag encountered"); } if (bytes.length == 0) // empty tag! { if ((tag & CONSTRUCTED) == 0) { return new DERTaggedObject(false, tag & 0x1f, new DERNull()); } else { return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence()); } } // // simple type - implicit... return an octet string // if ((tag & CONSTRUCTED) == 0) { return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes)); } bIn = new ByteArrayInputStream(bytes); dIn = new BERInputStream(bIn); DEREncodable dObj = dIn.readObject(); // // explicitly tagged (probably!) - if it isn't we'd have to // tell from the context // if (dIn.available() == 0) { return new DERTaggedObject(tag & 0x1f, dObj); } // // another implicit object, we'll create a sequence... // seq = new DERConstructedSequence(); seq.addObject(dObj); try { for (;;) { dObj = dIn.readObject(); seq.addObject(dObj); } } catch (EOFException ex) { // ignore -- } return new DERTaggedObject(false, tag & 0x1f, seq); } return new DERUnknownTag(tag, bytes); } } public DERObject readObject() throws IOException { int tag = read(); if (tag == -1) { throw new EOFException(); } int length = readLength(); byte[] bytes = new byte[length]; readFully(bytes); return buildObject(tag, bytes); } } azureus-4.3.0.6/org/bouncycastle/asn1/DERSequenceGenerator.java0000644000175000017500000000173411026315576023612 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; public class DERSequenceGenerator extends DERGenerator { private final ByteArrayOutputStream _bOut = new ByteArrayOutputStream(); public DERSequenceGenerator( OutputStream out) throws IOException { super(out); } public DERSequenceGenerator( OutputStream out, int tagNo, boolean isExplicit) throws IOException { super(out, tagNo, isExplicit); } public void addObject( DEREncodable object) throws IOException { object.getDERObject().encode(new DEROutputStream(_bOut)); } public OutputStream getRawOutputStream() { return _bOut; } public void close() throws IOException { writeDEREncoded(DERTags.CONSTRUCTED | DERTags.SEQUENCE, _bOut.toByteArray()); } } azureus-4.3.0.6/org/bouncycastle/asn1/BERInputStream.java0000644000175000017500000001346311026315624022440 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.util.Vector; /** * @deprecated use ASN1InputStream */ public class BERInputStream extends DERInputStream { private static final DERObject END_OF_STREAM = new DERObject() { void encode( DEROutputStream out) throws IOException { throw new IOException("Eeek!"); } public int hashCode() { return 0; } public boolean equals( Object o) { return o == this; } }; public BERInputStream( InputStream is) { super(is); } /** * read a string of bytes representing an indefinite length object. */ private byte[] readIndefiniteLengthFully() throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); int b, b1; b1 = read(); while ((b = read()) >= 0) { if (b1 == 0 && b == 0) { break; } bOut.write(b1); b1 = b; } return bOut.toByteArray(); } private BERConstructedOctetString buildConstructedOctetString() throws IOException { Vector octs = new Vector(); for (;;) { DERObject o = readObject(); if (o == END_OF_STREAM) { break; } octs.addElement(o); } return new BERConstructedOctetString(octs); } public DERObject readObject() throws IOException { int tag = read(); if (tag == -1) { throw new EOFException(); } int length = readLength(); if (length < 0) // indefinite length method { switch (tag) { case NULL: return null; case SEQUENCE | CONSTRUCTED: BERConstructedSequence seq = new BERConstructedSequence(); for (;;) { DERObject obj = readObject(); if (obj == END_OF_STREAM) { break; } seq.addObject(obj); } return seq; case OCTET_STRING | CONSTRUCTED: return buildConstructedOctetString(); case SET | CONSTRUCTED: ASN1EncodableVector v = new ASN1EncodableVector(); for (;;) { DERObject obj = readObject(); if (obj == END_OF_STREAM) { break; } v.add(obj); } return new BERSet(v); default: // // with tagged object tag number is bottom 5 bits // if ((tag & TAGGED) != 0) { if ((tag & 0x1f) == 0x1f) { throw new IOException("unsupported high tag encountered"); } // // simple type - implicit... return an octet string // if ((tag & CONSTRUCTED) == 0) { byte[] bytes = readIndefiniteLengthFully(); return new BERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes)); } // // either constructed or explicitly tagged // DERObject dObj = readObject(); if (dObj == END_OF_STREAM) // empty tag! { return new DERTaggedObject(tag & 0x1f); } DERObject next = readObject(); // // explicitly tagged (probably!) - if it isn't we'd have to // tell from the context // if (next == END_OF_STREAM) { return new BERTaggedObject(tag & 0x1f, dObj); } // // another implicit object, we'll create a sequence... // seq = new BERConstructedSequence(); seq.addObject(dObj); do { seq.addObject(next); next = readObject(); } while (next != END_OF_STREAM); return new BERTaggedObject(false, tag & 0x1f, seq); } throw new IOException("unknown BER object encountered"); } } else { if (tag == 0 && length == 0) // end of contents marker. { return END_OF_STREAM; } byte[] bytes = new byte[length]; readFully(bytes); return buildObject(tag, bytes); } } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1ObjectParser.java0000644000175000017500000000237011026315560022634 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.InputStream; import java.io.IOException; public class ASN1ObjectParser { private int _baseTag; private int _tagNumber; private ASN1StreamParser _aIn; protected ASN1ObjectParser( int baseTag, int tagNumber, InputStream contentStream) { _baseTag = baseTag; _tagNumber = tagNumber; _aIn = new ASN1StreamParser(contentStream); } /** * Return the tag number for this object. * * @return the tag number. */ int getTagNumber() { return _tagNumber; } int getBaseTag() { return _baseTag; } DEREncodable readObject() throws IOException { return _aIn.readObject(); } ASN1EncodableVector readVector() throws IllegalStateException { ASN1EncodableVector v = new ASN1EncodableVector(); DEREncodable obj; try { while ((obj = readObject()) != null) { v.add(obj.getDERObject()); } } catch (IOException e) { throw new IllegalStateException(e.getMessage()); } return v; } } azureus-4.3.0.6/org/bouncycastle/asn1/BEROctetStringGenerator.java0000644000175000017500000000454711026315610024277 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.io.OutputStream; public class BEROctetStringGenerator extends BERGenerator { public BEROctetStringGenerator(OutputStream out) throws IOException { super(out); writeBERHeader(DERTags.CONSTRUCTED | DERTags.OCTET_STRING); } public BEROctetStringGenerator( OutputStream out, int tagNo, boolean isExplicit) throws IOException { super(out, tagNo, isExplicit); writeBERHeader(DERTags.CONSTRUCTED | DERTags.OCTET_STRING); } public OutputStream getOctetOutputStream() { return getOctetOutputStream(new byte[1000]); // limit for CER encoding. } public OutputStream getOctetOutputStream( byte[] buf) { return new BufferedBEROctetStream(buf); } private class BufferedBEROctetStream extends OutputStream { private byte[] _buf; private int _off; BufferedBEROctetStream( byte[] buf) { _buf = buf; _off = 0; } public void write( int b) throws IOException { _buf[_off++] = (byte)b; if (_off == _buf.length) { _out.write(new DEROctetString(_buf).getEncoded()); _off = 0; } } public void write(byte[] b, int off, int len) throws IOException { while (len > 0) { int numToCopy = Math.min(len, _buf.length - _off); System.arraycopy(b, off, _buf, _off, numToCopy); _off += numToCopy; if (_off < _buf.length) { break; } _out.write(new DEROctetString(_buf).getEncoded()); _off = 0; off += numToCopy; len -= numToCopy; } } public void close() throws IOException { if (_off != 0) { byte[] bytes = new byte[_off]; System.arraycopy(_buf, 0, bytes, 0, _off); _out.write(new DEROctetString(bytes).getEncoded()); } writeBEREnd(); } } } azureus-4.3.0.6/org/bouncycastle/asn1/BERNull.java0000644000175000017500000000077311026315576021105 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; /** * A BER NULL object. */ public class BERNull extends DERNull { public static final BERNull INSTANCE = new BERNull(); public BERNull() { } void encode( DEROutputStream out) throws IOException { if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) { out.write(NULL); } else { super.encode(out); } } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1EncodableVector.java0000644000175000017500000000042211026315562023306 0ustar adrianadrianpackage org.bouncycastle.asn1; /** * the parent class for this will eventually disappear. Use this one! */ public class ASN1EncodableVector extends DEREncodableVector { // migrating from DEREncodeableVector public ASN1EncodableVector() { } } azureus-4.3.0.6/org/bouncycastle/asn1/DERTags.java0000644000175000017500000000321411026315624021056 0ustar adrianadrianpackage org.bouncycastle.asn1; public interface DERTags { public static final int BOOLEAN = 0x01; public static final int INTEGER = 0x02; public static final int BIT_STRING = 0x03; public static final int OCTET_STRING = 0x04; public static final int NULL = 0x05; public static final int OBJECT_IDENTIFIER = 0x06; public static final int EXTERNAL = 0x08; public static final int ENUMERATED = 0x0a; public static final int SEQUENCE = 0x10; public static final int SEQUENCE_OF = 0x10; // for completeness public static final int SET = 0x11; public static final int SET_OF = 0x11; // for completeness public static final int NUMERIC_STRING = 0x12; public static final int PRINTABLE_STRING = 0x13; public static final int T61_STRING = 0x14; public static final int VIDEOTEX_STRING = 0x15; public static final int IA5_STRING = 0x16; public static final int UTC_TIME = 0x17; public static final int GENERALIZED_TIME = 0x18; public static final int GRAPHIC_STRING = 0x19; public static final int VISIBLE_STRING = 0x1a; public static final int GENERAL_STRING = 0x1b; public static final int UNIVERSAL_STRING = 0x1c; public static final int BMP_STRING = 0x1e; public static final int UTF8_STRING = 0x0c; public static final int CONSTRUCTED = 0x20; public static final int APPLICATION = 0x40; public static final int TAGGED = 0x80; } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1SetParser.java0000644000175000017500000000027211026315612022156 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; public interface ASN1SetParser extends DEREncodable { public DEREncodable readObject() throws IOException; } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1Sequence.java0000644000175000017500000001303511026315616022023 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; import java.util.Enumeration; import java.util.Vector; public abstract class ASN1Sequence extends ASN1Object { private Vector seq = new Vector(); /** * return an ASN1Sequence from the given object. * * @param obj the object we want converted. * @exception IllegalArgumentException if the object cannot be converted. */ public static ASN1Sequence getInstance( Object obj) { if (obj == null || obj instanceof ASN1Sequence) { return (ASN1Sequence)obj; } throw new IllegalArgumentException("unknown object in getInstance"); } /** * Return an ASN1 sequence from a tagged object. There is a special * case here, if an object appears to have been explicitly tagged on * reading but we were expecting it to be implictly tagged in the * normal course of events it indicates that we lost the surrounding * sequence - so we need to add it back (this will happen if the tagged * object is a sequence that contains other sequences). If you are * dealing with implicitly tagged sequences you really should * be using this method. * * @param obj the tagged object. * @param explicit true if the object is meant to be explicitly tagged, * false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static ASN1Sequence getInstance( ASN1TaggedObject obj, boolean explicit) { if (explicit) { if (!obj.isExplicit()) { throw new IllegalArgumentException("object implicit - explicit expected."); } return (ASN1Sequence)obj.getObject(); } else { // // constructed object which appears to be explicitly tagged // when it should be implicit means we have to add the // surrounding sequence. // if (obj.isExplicit()) { if (obj instanceof BERTaggedObject) { return new BERSequence(obj.getObject()); } else { return new DERSequence(obj.getObject()); } } else { if (obj.getObject() instanceof ASN1Sequence) { return (ASN1Sequence)obj.getObject(); } } } throw new IllegalArgumentException( "unknown object in getInstanceFromTagged"); } public Enumeration getObjects() { return seq.elements(); } public ASN1SequenceParser parser() { final ASN1Sequence outer = this; return new ASN1SequenceParser() { private final int max = size(); private int index; public DEREncodable readObject() throws IOException { if (index == max) { return null; } DEREncodable obj = getObjectAt(index++); if (obj instanceof ASN1Sequence) { return ((ASN1Sequence)obj).parser(); } if (obj instanceof ASN1Set) { return ((ASN1Set)obj).parser(); } return obj; } public DERObject getDERObject() { return outer; } }; } /** * return the object at the sequence postion indicated by index. * * @param index the sequence number (starting at zero) of the object * @return the object at the sequence postion indicated by index. */ public DEREncodable getObjectAt( int index) { return (DEREncodable)seq.elementAt(index); } /** * return the number of objects in this sequence. * * @return the number of objects in this sequence. */ public int size() { return seq.size(); } public int hashCode() { Enumeration e = this.getObjects(); int hashCode = 0; while (e.hasMoreElements()) { Object o = e.nextElement(); if (o != null) { hashCode ^= o.hashCode(); } } return hashCode; } boolean asn1Equals( DERObject o) { if (!(o instanceof ASN1Sequence)) { return false; } ASN1Sequence other = (ASN1Sequence)o; if (this.size() != other.size()) { return false; } Enumeration s1 = this.getObjects(); Enumeration s2 = other.getObjects(); while (s1.hasMoreElements()) { DERObject o1 = ((DEREncodable)s1.nextElement()).getDERObject(); DERObject o2 = ((DEREncodable)s2.nextElement()).getDERObject(); if (o1 == o2 || (o1 != null && o1.equals(o2))) { continue; } return false; } return true; } protected void addObject( DEREncodable obj) { seq.addElement(obj); } abstract void encode(DEROutputStream out) throws IOException; public String toString() { return seq.toString(); } } azureus-4.3.0.6/org/bouncycastle/asn1/DERBMPString.java0000644000175000017500000000537611026315600021772 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; /** * DER BMPString object. */ public class DERBMPString extends ASN1Object implements DERString { String string; /** * return a BMP String from the given object. * * @param obj the object we want converted. * @exception IllegalArgumentException if the object cannot be converted. */ public static DERBMPString getInstance( Object obj) { if (obj == null || obj instanceof DERBMPString) { return (DERBMPString)obj; } if (obj instanceof ASN1OctetString) { return new DERBMPString(((ASN1OctetString)obj).getOctets()); } if (obj instanceof ASN1TaggedObject) { return getInstance(((ASN1TaggedObject)obj).getObject()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return a BMP String from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static DERBMPString getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } /** * basic constructor - byte encoded string. */ public DERBMPString( byte[] string) { char[] cs = new char[string.length / 2]; for (int i = 0; i != cs.length; i++) { cs[i] = (char)((string[2 * i] << 8) | (string[2 * i + 1] & 0xff)); } this.string = new String(cs); } /** * basic constructor */ public DERBMPString( String string) { this.string = string; } public String getString() { return string; } public String toString() { return string; } public int hashCode() { return this.getString().hashCode(); } protected boolean asn1Equals( DERObject o) { if (!(o instanceof DERBMPString)) { return false; } DERBMPString s = (DERBMPString)o; return this.getString().equals(s.getString()); } void encode( DEROutputStream out) throws IOException { char[] c = string.toCharArray(); byte[] b = new byte[c.length * 2]; for (int i = 0; i != c.length; i++) { b[2 * i] = (byte)(c[i] >> 8); b[2 * i + 1] = (byte)c[i]; } out.writeEncoded(BMP_STRING, b); } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1Encodable.java0000644000175000017500000000357611026315602022133 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; public abstract class ASN1Encodable implements DEREncodable { public static final String DER = "DER"; public static final String BER = "BER"; public byte[] getEncoded() throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); ASN1OutputStream aOut = new ASN1OutputStream(bOut); aOut.writeObject(this); return bOut.toByteArray(); } public byte[] getEncoded( String encoding) throws IOException { if (encoding.equals(DER)) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); dOut.writeObject(this); return bOut.toByteArray(); } return this.getEncoded(); } /** * Return the DER encoding of the object, null if the DER encoding can not be made. * * @return a DER byte array, null otherwise. */ public byte[] getDEREncoded() { try { return this.getEncoded(DER); } catch (IOException e) { return null; } } public int hashCode() { return this.toASN1Object().hashCode(); } public boolean equals( Object o) { if (this == o) { return true; } if (!(o instanceof DEREncodable)) { return false; } DEREncodable other = (DEREncodable)o; return this.toASN1Object().equals(other.getDERObject()); } public DERObject getDERObject() { return this.toASN1Object(); } public abstract DERObject toASN1Object(); } azureus-4.3.0.6/org/bouncycastle/asn1/DERSequence.java0000644000175000017500000000336711026315600021733 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Enumeration; public class DERSequence extends ASN1Sequence { /** * create an empty sequence */ public DERSequence() { } /** * create a sequence containing one object */ public DERSequence( DEREncodable obj) { this.addObject(obj); } /** * create a sequence containing a vector of objects. */ public DERSequence( DEREncodableVector v) { for (int i = 0; i != v.size(); i++) { this.addObject(v.get(i)); } } /** * create a sequence containing an array of objects. */ public DERSequence( ASN1Encodable[] a) { for (int i = 0; i != a.length; i++) { this.addObject(a[i]); } } /* * A note on the implementation: *

      * As DER requires the constructed, definite-length model to * be used for structured types, this varies slightly from the * ASN.1 descriptions given. Rather than just outputing SEQUENCE, * we also have to specify CONSTRUCTED, and the objects length. */ void encode( DEROutputStream out) throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); Enumeration e = this.getObjects(); while (e.hasMoreElements()) { Object obj = e.nextElement(); dOut.writeObject(obj); } dOut.close(); byte[] bytes = bOut.toByteArray(); out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes); } } azureus-4.3.0.6/org/bouncycastle/asn1/DefiniteLengthInputStream.java0000644000175000017500000000341711026315604024715 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.EOFException; import java.io.InputStream; import java.io.IOException; class DefiniteLengthInputStream extends LimitedInputStream { private int _length; DefiniteLengthInputStream( InputStream in, int length) { super(in); if (length < 0) { throw new IllegalArgumentException("negative lengths not allowed"); } this._length = length; } public int read() throws IOException { if (_length > 0) { int b = _in.read(); if (b < 0) { throw new EOFException(); } --_length; return b; } setParentEofDetect(true); return -1; } public int read(byte[] buf, int off, int len) throws IOException { if (_length > 0) { int toRead = Math.min(len, _length); int numRead = _in.read(buf, off, toRead); if (numRead < 0) throw new EOFException(); _length -= numRead; return numRead; } setParentEofDetect(true); return -1; } byte[] toByteArray() throws IOException { byte[] bytes = new byte[_length]; if (_length > 0) { int pos = 0; do { int read = _in.read(bytes, pos, _length - pos); if (read < 0) { throw new EOFException(); } pos += read; } while (pos < _length); _length = 0; } setParentEofDetect(true); return bytes; } } azureus-4.3.0.6/org/bouncycastle/asn1/cms/0000755000175000017500000000000011310377632017547 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/asn1/cms/ContentInfo.java0000644000175000017500000000427411026315670022645 0ustar adrianadrianpackage org.bouncycastle.asn1.cms; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.BERSequence; import org.bouncycastle.asn1.BERTaggedObject; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; public class ContentInfo extends ASN1Encodable implements CMSObjectIdentifiers { private DERObjectIdentifier contentType; private DEREncodable content; public static ContentInfo getInstance( Object obj) { if (obj instanceof ContentInfo) { return (ContentInfo)obj; } else if (obj instanceof ASN1Sequence) { return new ContentInfo((ASN1Sequence)obj); } throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName()); } public ContentInfo( ASN1Sequence seq) { Enumeration e = seq.getObjects(); contentType = (DERObjectIdentifier)e.nextElement(); if (e.hasMoreElements()) { content = ((ASN1TaggedObject)e.nextElement()).getObject(); } } public ContentInfo( DERObjectIdentifier contentType, DEREncodable content) { this.contentType = contentType; this.content = content; } public DERObjectIdentifier getContentType() { return contentType; } public DEREncodable getContent() { return content; } /** * Produce an object suitable for an ASN1OutputStream. *

           * ContentInfo ::= SEQUENCE {
           *          contentType ContentType,
           *          content
           *          [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
           * 
      */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(contentType); if (content != null) { v.add(new BERTaggedObject(0, content)); } return new BERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java0000644000175000017500000000150511026315670024350 0ustar adrianadrianpackage org.bouncycastle.asn1.cms; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; public interface CMSObjectIdentifiers { static final DERObjectIdentifier data = PKCSObjectIdentifiers.data; static final DERObjectIdentifier signedData = PKCSObjectIdentifiers.signedData; static final DERObjectIdentifier envelopedData = PKCSObjectIdentifiers.envelopedData; static final DERObjectIdentifier signedAndEnvelopedData = PKCSObjectIdentifiers.signedAndEnvelopedData; static final DERObjectIdentifier digestedData = PKCSObjectIdentifiers.digestedData; static final DERObjectIdentifier encryptedData = PKCSObjectIdentifiers.encryptedData; static final DERObjectIdentifier compressedData = PKCSObjectIdentifiers.id_ct_compressedData; } azureus-4.3.0.6/org/bouncycastle/asn1/DERString.java0000644000175000017500000000022110061400650021411 0ustar adrianadrianpackage org.bouncycastle.asn1; /** * basic interface for DER string objects. */ public interface DERString { public String getString(); } azureus-4.3.0.6/org/bouncycastle/asn1/DEREncodable.java0000644000175000017500000000014710061400650022026 0ustar adrianadrianpackage org.bouncycastle.asn1; public interface DEREncodable { public DERObject getDERObject(); } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1Null.java0000644000175000017500000000104511026315624021162 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.IOException; /** * A NULL object. */ public abstract class ASN1Null extends ASN1Object { public ASN1Null() { } public int hashCode() { return 0; } boolean asn1Equals( DERObject o) { if (!(o instanceof ASN1Null)) { return false; } return true; } abstract void encode(DEROutputStream out) throws IOException; public String toString() { return "NULL"; } } azureus-4.3.0.6/org/bouncycastle/asn1/BERConstructedOctetString.java0000644000175000017500000000764411026315610024647 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Enumeration; import java.util.Vector; public class BERConstructedOctetString extends DEROctetString { private static final int MAX_LENGTH = 1000; /** * convert a vector of octet strings into a single byte string */ static private byte[] toBytes( Vector octs) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); for (int i = 0; i != octs.size(); i++) { try { DEROctetString o = (DEROctetString)octs.elementAt(i); bOut.write(o.getOctets()); } catch (ClassCastException e) { throw new IllegalArgumentException(octs.elementAt(i).getClass().getName() + " found in input should only contain DEROctetString"); } catch (IOException e) { throw new IllegalArgumentException("exception converting octets " + e.toString()); } } return bOut.toByteArray(); } private Vector octs; /** * @param string the octets making up the octet string. */ public BERConstructedOctetString( byte[] string) { super(string); } public BERConstructedOctetString( Vector octs) { super(toBytes(octs)); this.octs = octs; } public BERConstructedOctetString( DERObject obj) { super(obj); } public BERConstructedOctetString( DEREncodable obj) { super(obj.getDERObject()); } public byte[] getOctets() { return string; } /** * return the DER octets that make up this string. */ public Enumeration getObjects() { if (octs == null) { return generateOcts().elements(); } return octs.elements(); } private Vector generateOcts() { int start = 0; int end = 0; Vector vec = new Vector(); while ((end + 1) < string.length) { if (string[end] == 0 && string[end + 1] == 0) { byte[] nStr = new byte[end - start + 1]; System.arraycopy(string, start, nStr, 0, nStr.length); vec.addElement(new DEROctetString(nStr)); start = end + 1; } end++; } byte[] nStr = new byte[string.length - start]; System.arraycopy(string, start, nStr, 0, nStr.length); vec.addElement(new DEROctetString(nStr)); return vec; } public void encode( DEROutputStream out) throws IOException { if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) { out.write(CONSTRUCTED | OCTET_STRING); out.write(0x80); // // write out the octet array // if (octs != null) { for (int i = 0; i != octs.size(); i++) { out.writeObject(octs.elementAt(i)); } } else { for (int i = 0; i < string.length; i += MAX_LENGTH) { int end; if (i + MAX_LENGTH > string.length) { end = string.length; } else { end = i + MAX_LENGTH; } byte[] nStr = new byte[end - i]; System.arraycopy(string, i, nStr, 0, nStr.length); out.writeObject(new DEROctetString(nStr)); } } out.write(0x00); out.write(0x00); } else { super.encode(out); } } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1Set.java0000644000175000017500000002065111026315620021003 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Enumeration; import java.util.Vector; abstract public class ASN1Set extends ASN1Object { protected Vector set = new Vector(); /** * return an ASN1Set from the given object. * * @param obj the object we want converted. * @exception IllegalArgumentException if the object cannot be converted. */ public static ASN1Set getInstance( Object obj) { if (obj == null || obj instanceof ASN1Set) { return (ASN1Set)obj; } throw new IllegalArgumentException("unknown object in getInstance"); } /** * Return an ASN1 set from a tagged object. There is a special * case here, if an object appears to have been explicitly tagged on * reading but we were expecting it to be implictly tagged in the * normal course of events it indicates that we lost the surrounding * set - so we need to add it back (this will happen if the tagged * object is a sequence that contains other sequences). If you are * dealing with implicitly tagged sets you really should * be using this method. * * @param obj the tagged object. * @param explicit true if the object is meant to be explicitly tagged * false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. */ public static ASN1Set getInstance( ASN1TaggedObject obj, boolean explicit) { if (explicit) { if (!obj.isExplicit()) { throw new IllegalArgumentException("object implicit - explicit expected."); } return (ASN1Set)obj.getObject(); } else { // // constructed object which appears to be explicitly tagged // and it's really implicit means we have to add the // surrounding sequence. // if (obj.isExplicit()) { ASN1Set set = new DERSet(obj.getObject()); return set; } else { if (obj.getObject() instanceof ASN1Set) { return (ASN1Set)obj.getObject(); } // // in this case the parser returns a sequence, convert it // into a set. // ASN1EncodableVector v = new ASN1EncodableVector(); if (obj.getObject() instanceof ASN1Sequence) { ASN1Sequence s = (ASN1Sequence)obj.getObject(); Enumeration e = s.getObjects(); while (e.hasMoreElements()) { v.add((DEREncodable)e.nextElement()); } return new DERSet(v, false); } } } throw new IllegalArgumentException( "unknown object in getInstanceFromTagged"); } public ASN1Set() { } public Enumeration getObjects() { return set.elements(); } /** * return the object at the set postion indicated by index. * * @param index the set number (starting at zero) of the object * @return the object at the set postion indicated by index. */ public DEREncodable getObjectAt( int index) { return (DEREncodable)set.elementAt(index); } /** * return the number of objects in this set. * * @return the number of objects in this set. */ public int size() { return set.size(); } public ASN1SetParser parser() { final ASN1Set outer = this; return new ASN1SetParser() { private final int max = size(); private int index; public DEREncodable readObject() throws IOException { if (index == max) { return null; } DEREncodable obj = getObjectAt(index++); if (obj instanceof ASN1Sequence) { return ((ASN1Sequence)obj).parser(); } if (obj instanceof ASN1Set) { return ((ASN1Set)obj).parser(); } return obj; } public DERObject getDERObject() { return outer; } }; } public int hashCode() { Enumeration e = this.getObjects(); int hashCode = 0; while (e.hasMoreElements()) { hashCode ^= e.nextElement().hashCode(); } return hashCode; } boolean asn1Equals( DERObject o) { if (!(o instanceof ASN1Set)) { return false; } ASN1Set other = (ASN1Set)o; if (this.size() != other.size()) { return false; } Enumeration s1 = this.getObjects(); Enumeration s2 = other.getObjects(); while (s1.hasMoreElements()) { DERObject o1 = ((DEREncodable)s1.nextElement()).getDERObject(); DERObject o2 = ((DEREncodable)s2.nextElement()).getDERObject(); if (o1 == o2 || (o1 != null && o1.equals(o2))) { continue; } return false; } return true; } /** * return true if a <= b (arrays are assumed padded with zeros). */ private boolean lessThanOrEqual( byte[] a, byte[] b) { if (a.length <= b.length) { for (int i = 0; i != a.length; i++) { int l = a[i] & 0xff; int r = b[i] & 0xff; if (r > l) { return true; } else if (l > r) { return false; } } return true; } else { for (int i = 0; i != b.length; i++) { int l = a[i] & 0xff; int r = b[i] & 0xff; if (r > l) { return true; } else if (l > r) { return false; } } return false; } } private byte[] getEncoded( DEREncodable obj) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); ASN1OutputStream aOut = new ASN1OutputStream(bOut); try { aOut.writeObject(obj); } catch (IOException e) { throw new IllegalArgumentException("cannot encode object added to SET"); } return bOut.toByteArray(); } protected void sort() { if (set.size() > 1) { boolean swapped = true; int lastSwap = set.size() - 1; while (swapped) { int index = 0; int swapIndex = 0; byte[] a = getEncoded((DEREncodable)set.elementAt(0)); swapped = false; while (index != lastSwap) { byte[] b = getEncoded((DEREncodable)set.elementAt(index + 1)); if (lessThanOrEqual(a, b)) { a = b; } else { Object o = set.elementAt(index); set.setElementAt(set.elementAt(index + 1), index); set.setElementAt(o, index + 1); swapped = true; swapIndex = index; } index++; } lastSwap = swapIndex; } } } protected void addObject( DEREncodable obj) { set.addElement(obj); } abstract void encode(DEROutputStream out) throws IOException; public String toString() { return set.toString(); } } azureus-4.3.0.6/org/bouncycastle/asn1/x9/0000755000175000017500000000000011310377632017325 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/asn1/x9/OtherInfo.java0000644000175000017500000000445510407566336022104 0ustar adrianadrianpackage org.bouncycastle.asn1.x9; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; /** * ANS.1 def for Diffie-Hellman key exchange OtherInfo structure. See * RFC 2631, or X9.42, for further details. */ public class OtherInfo implements DEREncodable { private KeySpecificInfo keyInfo; private ASN1OctetString partyAInfo; private ASN1OctetString suppPubInfo; public OtherInfo( KeySpecificInfo keyInfo, ASN1OctetString partyAInfo, ASN1OctetString suppPubInfo) { this.keyInfo = keyInfo; this.partyAInfo = partyAInfo; this.suppPubInfo = suppPubInfo; } public OtherInfo( ASN1Sequence seq) { Enumeration e = seq.getObjects(); keyInfo = new KeySpecificInfo((ASN1Sequence)e.nextElement()); while (e.hasMoreElements()) { DERTaggedObject o = (DERTaggedObject)e.nextElement(); if (o.getTagNo() == 0) { partyAInfo = (ASN1OctetString)o.getObject(); } else if (o.getTagNo() == 2) { suppPubInfo = (ASN1OctetString)o.getObject(); } } } public KeySpecificInfo getKeyInfo() { return keyInfo; } public ASN1OctetString getPartyAInfo() { return partyAInfo; } public ASN1OctetString getSuppPubInfo() { return suppPubInfo; } /** * Produce an object suitable for an ASN1OutputStream. *
           *  OtherInfo ::= SEQUENCE {
           *      keyInfo KeySpecificInfo,
           *      partyAInfo [0] OCTET STRING OPTIONAL,
           *      suppPubInfo [2] OCTET STRING
           *  }
           * 
      */ public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(keyInfo); if (partyAInfo != null) { v.add(new DERTaggedObject(0, partyAInfo)); } v.add(new DERTaggedObject(2, suppPubInfo)); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x9/X9Curve.java0000644000175000017500000000460410407566336021510 0ustar adrianadrianpackage org.bouncycastle.asn1.x9; import java.math.BigInteger; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.math.ec.ECCurve; /** * ASN.1 def for Elliptic-Curve Curve structure. See * X9.62, for further details. */ public class X9Curve implements DEREncodable, X9ObjectIdentifiers { private ECCurve curve; private byte[] seed; public X9Curve( ECCurve curve) { this.curve = curve; this.seed = null; } public X9Curve( ECCurve curve, byte[] seed) { this.curve = curve; this.seed = seed; } public X9Curve( X9FieldID fieldID, ASN1Sequence seq) { if (fieldID.getIdentifier().equals(prime_field)) { BigInteger q = ((DERInteger)fieldID.getParameters()).getValue(); X9FieldElement x9A = new X9FieldElement(true, q, (ASN1OctetString)seq.getObjectAt(0)); X9FieldElement x9B = new X9FieldElement(true, q, (ASN1OctetString)seq.getObjectAt(1)); curve = new ECCurve.Fp(q, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger()); } else { throw new RuntimeException("not implemented"); } if (seq.size() == 3) { seed = ((DERBitString)seq.getObjectAt(2)).getBytes(); } } public ECCurve getCurve() { return curve; } public byte[] getSeed() { return seed; } /** * Produce an object suitable for an ASN1OutputStream. *
           *  Curve ::= SEQUENCE {
           *      a               FieldElement,
           *      b               FieldElement,
           *      seed            BIT STRING      OPTIONAL
           *  }
           * 
      */ public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new X9FieldElement(curve.getA()).getDERObject()); v.add(new X9FieldElement(curve.getB()).getDERObject()); if (seed != null) { v.add(new DERBitString(seed)); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x9/package.html0000644000175000017500000000017110407566336021614 0ustar adrianadrian Support classes useful for encoding and supporting X9.62 elliptic curve. azureus-4.3.0.6/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java0000644000175000017500000000614410407566336024021 0ustar adrianadrianpackage org.bouncycastle.asn1.x9; import org.bouncycastle.asn1.DERObjectIdentifier; public interface X9ObjectIdentifiers { // // X9.62 // // ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2) // us(840) ansi-x962(10045) } // static final String ansi_X9_62 = "1.2.840.10045"; static final String id_fieldType = ansi_X9_62 + ".1"; static final DERObjectIdentifier prime_field = new DERObjectIdentifier(id_fieldType + ".1"); static final DERObjectIdentifier characteristic_two_field = new DERObjectIdentifier(id_fieldType + ".2"); static final DERObjectIdentifier gnBasis = new DERObjectIdentifier(id_fieldType + ".2.3.1"); static final DERObjectIdentifier tpBasis = new DERObjectIdentifier(id_fieldType + ".2.3.2"); static final DERObjectIdentifier ppBasis = new DERObjectIdentifier(id_fieldType + ".2.3.3"); static final String id_ecSigType = ansi_X9_62 + ".4"; static final DERObjectIdentifier ecdsa_with_SHA1 = new DERObjectIdentifier(id_ecSigType + ".1"); static final String id_publicKeyType = ansi_X9_62 + ".2"; static final DERObjectIdentifier id_ecPublicKey = new DERObjectIdentifier(id_publicKeyType + ".1"); // // named curves // static final String ellipticCurve = ansi_X9_62 + ".3"; // // Prime // static final String primeCurve = ellipticCurve + ".1"; static final DERObjectIdentifier prime192v1 = new DERObjectIdentifier(primeCurve + ".1"); static final DERObjectIdentifier prime192v2 = new DERObjectIdentifier(primeCurve + ".2"); static final DERObjectIdentifier prime192v3 = new DERObjectIdentifier(primeCurve + ".3"); static final DERObjectIdentifier prime239v1 = new DERObjectIdentifier(primeCurve + ".4"); static final DERObjectIdentifier prime239v2 = new DERObjectIdentifier(primeCurve + ".5"); static final DERObjectIdentifier prime239v3 = new DERObjectIdentifier(primeCurve + ".6"); static final DERObjectIdentifier prime256v1 = new DERObjectIdentifier(primeCurve + ".7"); // // Diffie-Hellman // // dhpublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2) // us(840) ansi-x942(10046) number-type(2) 1 } // static final DERObjectIdentifier dhpublicnumber = new DERObjectIdentifier("1.2.840.10046.2.1"); // // DSA // // dsapublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2) // us(840) ansi-x957(10040) number-type(4) 1 } static final DERObjectIdentifier id_dsa = new DERObjectIdentifier("1.2.840.10040.4.1"); /** * id-dsa-with-sha1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) * us(840) x9-57 (10040) x9cm(4) 3 } */ public static final DERObjectIdentifier id_dsa_with_sha1 = new DERObjectIdentifier("1.2.840.10040.4.3"); } azureus-4.3.0.6/org/bouncycastle/asn1/x9/X9ECPoint.java0000644000175000017500000000174610407566336021731 0ustar adrianadrianpackage org.bouncycastle.asn1.x9; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; /** * class for describing an ECPoint as a DER object. */ public class X9ECPoint implements DEREncodable { ECPoint p; public X9ECPoint( ECPoint p) { this.p = p; } public X9ECPoint( ECCurve c, ASN1OctetString s) { this.p = c.decodePoint(s.getOctets()); } public ECPoint getPoint() { return p; } /** * Produce an object suitable for an ASN1OutputStream. *
           *  ECPoint ::= OCTET STRING
           * 
      *

      * Octet string produced using ECPoint.getEncoded(). */ public DERObject getDERObject() { return new DEROctetString(p.getEncoded()); } } azureus-4.3.0.6/org/bouncycastle/asn1/x9/X9ECParameters.java0000644000175000017500000000675110407566336022744 0ustar adrianadrianpackage org.bouncycastle.asn1.x9; import java.math.BigInteger; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; /** * ASN.1 def for Elliptic-Curve ECParameters structure. See * X9.62, for further details. */ public class X9ECParameters implements DEREncodable, X9ObjectIdentifiers { private static BigInteger ONE = BigInteger.valueOf(1); private X9FieldID fieldID; private ECCurve curve; private ECPoint g; private BigInteger n; private BigInteger h; private byte[] seed; public X9ECParameters( ASN1Sequence seq) { if (!(seq.getObjectAt(0) instanceof DERInteger) || !((DERInteger)seq.getObjectAt(0)).getValue().equals(ONE)) { throw new IllegalArgumentException("bad version in X9ECParameters"); } X9Curve x9c = new X9Curve( new X9FieldID((ASN1Sequence)seq.getObjectAt(1)), (ASN1Sequence)seq.getObjectAt(2)); this.curve = x9c.getCurve(); this.g = new X9ECPoint(curve, (ASN1OctetString)seq.getObjectAt(3)).getPoint(); this.n = ((DERInteger)seq.getObjectAt(4)).getValue(); this.seed = x9c.getSeed(); if (seq.size() == 6) { this.h = ((DERInteger)seq.getObjectAt(5)).getValue(); } else { this.h = ONE; } } public X9ECParameters( ECCurve curve, ECPoint g, BigInteger n) { this(curve, g, n, ONE, null); } public X9ECParameters( ECCurve curve, ECPoint g, BigInteger n, BigInteger h) { this(curve, g, n, h, null); } public X9ECParameters( ECCurve curve, ECPoint g, BigInteger n, BigInteger h, byte[] seed) { this.curve = curve; this.g = g; this.n = n; this.h = h; this.seed = seed; if (curve instanceof ECCurve.Fp) { this.fieldID = new X9FieldID(prime_field, ((ECCurve.Fp)curve).getQ()); } else { this.fieldID = new X9FieldID(characteristic_two_field, null); } } public ECCurve getCurve() { return curve; } public ECPoint getG() { return g; } public BigInteger getN() { return n; } public BigInteger getH() { return h; } public byte[] getSeed() { return seed; } /** * Produce an object suitable for an ASN1OutputStream. *

           *  ECParameters ::= SEQUENCE {
           *      version         INTEGER { ecpVer1(1) } (ecpVer1),
           *      fieldID         FieldID {{FieldTypes}},
           *      curve           X9Curve,
           *      base            X9ECPoint,
           *      order           INTEGER,
           *      cofactor        INTEGER OPTIONAL
           *  }
           * 
      */ public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new DERInteger(1)); v.add(fieldID); v.add(new X9Curve(curve, seed)); v.add(new X9ECPoint(g)); v.add(new DERInteger(n)); if (!h.equals(BigInteger.valueOf(1))) { v.add(new DERInteger(h)); } return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x9/X962NamedCurves.java0000644000175000017500000002043610417277760023012 0ustar adrianadrianpackage org.bouncycastle.asn1.x9; import java.math.BigInteger; import java.util.Enumeration; import java.util.Hashtable; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.util.encoders.Hex; /** * table of the current named curves defined in X.962 EC-DSA. */ public class X962NamedCurves { static final ECCurve cFp192v1 = new ECCurve.Fp( new BigInteger("6277101735386680763835789423207666416083908700390324961279"), new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); static final X9ECParameters prime192v1 = new X9ECParameters( cFp192v1, cFp192v1.decodePoint( Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16), BigInteger.valueOf(1), Hex.decode("3045AE6FC8422f64ED579528D38120EAE12196D5")); static final ECCurve cFp192v2 = new ECCurve.Fp( new BigInteger("6277101735386680763835789423207666416083908700390324961279"), new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16)); static final X9ECParameters prime192v2 = new X9ECParameters( cFp192v2, cFp192v2.decodePoint( Hex.decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")), new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", 16), // parg fixed F->E... BigInteger.valueOf(1), Hex.decode("31a92ee2029fd10d901b113e990710f0d21ac6b6")); static final ECCurve cFp192v3 = new ECCurve.Fp( new BigInteger("6277101735386680763835789423207666416083908700390324961279"), new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16)); static final X9ECParameters prime192v3 = new X9ECParameters( cFp192v3, cFp192v3.decodePoint( Hex.decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")), new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16), BigInteger.valueOf(1), Hex.decode("c469684435deb378c4b65ca9591e2a5763059a2e")); static final ECCurve cFp239v1 = new ECCurve.Fp( new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); static final X9ECParameters prime239v1 = new X9ECParameters( cFp239v1, cFp239v1.decodePoint( Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16), BigInteger.valueOf(1), Hex.decode("e43bb460f0b80cc0c0b075798e948060f8321b7d")); static final ECCurve cFp239v2 = new ECCurve.Fp( new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16)); static final X9ECParameters prime239v2 = new X9ECParameters( cFp239v2, cFp239v2.decodePoint( Hex.decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")), new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16), BigInteger.valueOf(1), Hex.decode("e8b4011604095303ca3b8099982be09fcb9ae616")); static final ECCurve cFp239v3 = new ECCurve.Fp( new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16)); static final X9ECParameters prime239v3 = new X9ECParameters( cFp239v3, cFp239v3.decodePoint( Hex.decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")), new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16), BigInteger.valueOf(1), Hex.decode("7d7374168ffe3471b60a857686a19475d3bfa2ff")); static final ECCurve cFp256v1 = new ECCurve.Fp( new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951"), new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)); static final X9ECParameters prime256v1 = new X9ECParameters( cFp256v1, cFp256v1.decodePoint( Hex.decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")), new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), BigInteger.valueOf(1), Hex.decode("c49d360886e704936a6678e1139d26b7819f7e90")); static final Hashtable objIds = new Hashtable(); static final Hashtable curves = new Hashtable(); static final Hashtable names = new Hashtable(); static { objIds.put("prime192v1", X9ObjectIdentifiers.prime192v1); objIds.put("prime192v2", X9ObjectIdentifiers.prime192v2); objIds.put("prime192v3", X9ObjectIdentifiers.prime192v3); objIds.put("prime239v1", X9ObjectIdentifiers.prime239v1); objIds.put("prime239v2", X9ObjectIdentifiers.prime239v2); objIds.put("prime239v3", X9ObjectIdentifiers.prime239v3); objIds.put("prime256v1", X9ObjectIdentifiers.prime256v1); names.put(X9ObjectIdentifiers.prime192v1, "prime192v1"); names.put(X9ObjectIdentifiers.prime192v2, "prime192v2"); names.put(X9ObjectIdentifiers.prime192v3, "prime192v3"); names.put(X9ObjectIdentifiers.prime239v1, "prime239v1"); names.put(X9ObjectIdentifiers.prime239v2, "prime239v2"); names.put(X9ObjectIdentifiers.prime239v3, "prime239v3"); names.put(X9ObjectIdentifiers.prime256v1, "prime256v1"); curves.put(X9ObjectIdentifiers.prime192v1, prime192v1); curves.put(X9ObjectIdentifiers.prime192v2, prime192v2); curves.put(X9ObjectIdentifiers.prime192v3, prime192v3); curves.put(X9ObjectIdentifiers.prime239v1, prime239v1); curves.put(X9ObjectIdentifiers.prime239v2, prime239v2); curves.put(X9ObjectIdentifiers.prime239v3, prime239v3); curves.put(X9ObjectIdentifiers.prime256v1, prime256v1); } public static X9ECParameters getByName( String name) { DERObjectIdentifier oid = (DERObjectIdentifier)objIds.get(name); if (oid != null) { return (X9ECParameters)curves.get(oid); } return null; } /** * return the X9ECParameters object for the named curve represented by * the passed in object identifier. Null if the curve isn't present. * * @param oid an object identifier representing a named curve, if present. */ public static X9ECParameters getByOID( DERObjectIdentifier oid) { return (X9ECParameters)curves.get(oid); } /** * return the object identifier signified by the passed in name. Null * if there is no object identifier associated with name. * * @return the object identifier associated with name, if present. */ public static DERObjectIdentifier getOID( String name) { return (DERObjectIdentifier)objIds.get(name); } /** * return the named curve name represented by the given object identifier. */ public static String getName( DERObjectIdentifier oid) { return (String)names.get(oid); } /** * returns an enumeration containing the name strings for curves * contained in this structure. */ public static Enumeration getNames() { return objIds.keys(); } } azureus-4.3.0.6/org/bouncycastle/asn1/x9/X9IntegerConverter.java0000644000175000017500000000203210767602140023673 0ustar adrianadrianpackage org.bouncycastle.asn1.x9; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECFieldElement; import java.math.BigInteger; public class X9IntegerConverter { public int getByteLength( ECCurve c) { return (c.getFieldSize() + 7) / 8; } public int getByteLength( ECFieldElement fe) { return (fe.getFieldSize() + 7) / 8; } public byte[] integerToBytes( BigInteger s, int qLength) { byte[] bytes = s.toByteArray(); if (qLength < bytes.length) { byte[] tmp = new byte[qLength]; System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length); return tmp; } else if (qLength > bytes.length) { byte[] tmp = new byte[qLength]; System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length); return tmp; } return bytes; } } azureus-4.3.0.6/org/bouncycastle/asn1/x9/KeySpecificInfo.java0000644000175000017500000000317110407566336023213 0ustar adrianadrianpackage org.bouncycastle.asn1.x9; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; /** * ASN.1 def for Diffie-Hellman key exchange KeySpecificInfo structure. See * RFC 2631, or X9.42, for further details. */ public class KeySpecificInfo implements DEREncodable { private DERObjectIdentifier algorithm; private ASN1OctetString counter; public KeySpecificInfo( DERObjectIdentifier algorithm, ASN1OctetString counter) { this.algorithm = algorithm; this.counter = counter; } public KeySpecificInfo( ASN1Sequence seq) { Enumeration e = seq.getObjects(); algorithm = (DERObjectIdentifier)e.nextElement(); counter = (ASN1OctetString)e.nextElement(); } public DERObjectIdentifier getAlgorithm() { return algorithm; } public ASN1OctetString getCounter() { return counter; } /** * Produce an object suitable for an ASN1OutputStream. *
           *  KeySpecificInfo ::= SEQUENCE {
           *      algorithm OBJECT IDENTIFIER,
           *      counter OCTET STRING SIZE (4..4)
           *  }
           * 
      */ public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(algorithm); v.add(counter); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x9/X9FieldID.java0000644000175000017500000000307610407566336021666 0ustar adrianadrianpackage org.bouncycastle.asn1.x9; import java.math.BigInteger; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSequence; /** * ASN.1 def for Elliptic-Curve Field ID structure. See * X9.62, for further details. */ public class X9FieldID implements DEREncodable, X9ObjectIdentifiers { private DERObjectIdentifier id; private DERObject parameters; public X9FieldID( DERObjectIdentifier id, BigInteger primeP) { this.id = id; this.parameters = new DERInteger(primeP); } public X9FieldID( ASN1Sequence seq) { this.id = (DERObjectIdentifier)seq.getObjectAt(0); this.parameters = (DERObject)seq.getObjectAt(1); } public DERObjectIdentifier getIdentifier() { return id; } public DERObject getParameters() { return parameters; } /** * Produce a DER encoding of the following structure. *
           *  FieldID ::= SEQUENCE {
           *      fieldType       FIELD-ID.&id({IOSet}),
           *      parameters      FIELD-ID.&Type({IOSet}{@fieldType})
           *  }
           * 
      */ public DERObject getDERObject() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(this.id); v.add(this.parameters); return new DERSequence(v); } } azureus-4.3.0.6/org/bouncycastle/asn1/x9/X9FieldElement.java0000644000175000017500000000310410407566336022753 0ustar adrianadrianpackage org.bouncycastle.asn1.x9; import java.math.BigInteger; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.math.ec.ECFieldElement; /** * class for processing an FieldElement as a DER object. */ public class X9FieldElement implements DEREncodable { private ECFieldElement f; public X9FieldElement( ECFieldElement f) { this.f = f; } public X9FieldElement( boolean fP, BigInteger q, ASN1OctetString s) { if (fP) { this.f = new ECFieldElement.Fp(q, new BigInteger(1, s.getOctets())); } else { throw new RuntimeException("not implemented"); } } public ECFieldElement getValue() { return f; } /** * Produce an object suitable for an ASN1OutputStream. *
           *  FieldElement ::= OCTET STRING
           * 
      *

      *

        *
      1. if q is an odd prime then the field element is * processed as an Integer and converted to an octet string * according to x 9.62 4.3.1.
      2. *
      3. if q is 2m then the bit string * contained in the field element is converted into an octet * string with the same ordering padded at the front if necessary. *
      4. *
      */ public DERObject getDERObject() { return new DEROctetString(f.toBigInteger().toByteArray()); } } azureus-4.3.0.6/org/bouncycastle/asn1/x9/X962Parameters.java0000644000175000017500000000215010407566336022671 0ustar adrianadrianpackage org.bouncycastle.asn1.x9; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; public class X962Parameters implements DEREncodable { private DERObject params = null; public X962Parameters( X9ECParameters ecParameters) { this.params = ecParameters.getDERObject(); } public X962Parameters( DERObjectIdentifier namedCurve) { this.params = namedCurve; } public X962Parameters( DERObject obj) { this.params = obj; } public boolean isNamedCurve() { return (params instanceof DERObjectIdentifier); } public DERObject getParameters() { return params; } /** * Produce an object suitable for an ASN1OutputStream. *
           * Parameters ::= CHOICE {
           *    ecParameters ECParameters,
           *    namedCurve   CURVES.&id({CurveNames}),
           *    implicitlyCA NULL
           * }
           * 
      */ public DERObject getDERObject() { return params; } } azureus-4.3.0.6/org/bouncycastle/asn1/ASN1InputStream.java0000644000175000017500000003151311026315610022521 0ustar adrianadrianpackage org.bouncycastle.asn1; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Vector; /** * a general purpose ASN.1 decoder - note: this class differs from the * others in that it returns null after it has read the last object in * the stream. If an ASN.1 NULL is encountered a DER/BER Null object is * returned. */ public class ASN1InputStream extends FilterInputStream implements DERTags { private static final DERObject END_OF_STREAM = new DERObject() { void encode( DEROutputStream out) throws IOException { throw new IOException("Eeek!"); } public int hashCode() { return 0; } public boolean equals( Object o) { return o == this; } }; boolean eofFound = false; int limit = Integer.MAX_VALUE; public ASN1InputStream( InputStream is) { super(is); } /** * Create an ASN1InputStream based on the input byte array. The length of DER objects in * the stream is automatically limited to the length of the input array. * * @param input array containing ASN.1 encoded data. */ public ASN1InputStream( byte[] input) { this(new ByteArrayInputStream(input), input.length); } /** * Create an ASN1InputStream where no DER object will be longer than limit. * * @param input stream containing ASN.1 encoded data. * @param limit maximum size of a DER encoded object. */ public ASN1InputStream( InputStream input, int limit) { super(input); this.limit = limit; } protected int readLength() throws IOException { int length = read(); if (length < 0) { throw new IOException("EOF found when length expected"); } if (length == 0x80) { return -1; // indefinite-length encoding } if (length > 127) { int size = length & 0x7f; if (size > 4) { throw new IOException("DER length more than 4 bytes"); } length = 0; for (int i = 0; i < size; i++) { int next = read(); if (next < 0) { throw new IOException("EOF found reading length"); } length = (length << 8) + next; } if (length < 0) { throw new IOException("corrupted stream - negative length found"); } if (length >= limit) // after all we must have read at least 1 byte { throw new IOException("corrupted stream - out of bounds length found"); } } return length; } protected void readFully( byte[] bytes) throws IOException { int left = bytes.length; int len; if (left == 0) { return; } while ((len = read(bytes, bytes.length - left, left)) > 0) { if ((left -= len) == 0) { return; } } if (left != 0) { throw new EOFException("EOF encountered in middle of object"); } } /** * build an object given its tag and the number of bytes to construct it from. */ protected DERObject buildObject( int tag, int tagNo, int length) throws IOException { if ((tag & APPLICATION) != 0) { return new DERApplicationSpecific(tagNo, readDefiniteLengthFully(length)); } boolean isConstructed = (tag & CONSTRUCTED) != 0; if (isConstructed) { switch (tag) { case SEQUENCE | CONSTRUCTED: return new DERSequence(buildDerEncodableVector(length)); case SET | CONSTRUCTED: return new DERSet(buildDerEncodableVector(length), false); case OCTET_STRING | CONSTRUCTED: return buildDerConstructedOctetString(length); default: { // // with tagged object tag number is bottom 5 bits // if ((tag & TAGGED) != 0) { if (length == 0) // empty tag! { return new DERTaggedObject(false, tagNo, new DERSequence()); } ASN1EncodableVector v = buildDerEncodableVector(length); if (v.size() == 1) { // // explicitly tagged (probably!) - if it isn't we'd have to // tell from the context // return new DERTaggedObject(tagNo, v.get(0)); } return new DERTaggedObject(false, tagNo, new DERSequence(v)); } return new DERUnknownTag(tag, readDefiniteLengthFully(length)); } } } byte[] bytes = readDefiniteLengthFully(length); switch (tag) { case NULL: return DERNull.INSTANCE; case BOOLEAN: return new DERBoolean(bytes); case INTEGER: return new DERInteger(bytes); case ENUMERATED: return new DEREnumerated(bytes); case OBJECT_IDENTIFIER: return new DERObjectIdentifier(bytes); case BIT_STRING: { int padBits = bytes[0]; byte[] data = new byte[bytes.length - 1]; System.arraycopy(bytes, 1, data, 0, bytes.length - 1); return new DERBitString(data, padBits); } case NUMERIC_STRING: return new DERNumericString(bytes); case UTF8_STRING: return new DERUTF8String(bytes); case PRINTABLE_STRING: return new DERPrintableString(bytes); case IA5_STRING: return new DERIA5String(bytes); case T61_STRING: return new DERT61String(bytes); case VISIBLE_STRING: return new DERVisibleString(bytes); case GENERAL_STRING: return new DERGeneralString(bytes); case UNIVERSAL_STRING: return new DERUniversalString(bytes); case BMP_STRING: return new DERBMPString(bytes); case OCTET_STRING: return new DEROctetString(bytes); case UTC_TIME: return new DERUTCTime(bytes); case GENERALIZED_TIME: return new DERGeneralizedTime(bytes); default: { // // with tagged object tag number is bottom 5 bits // if ((tag & TAGGED) != 0) { if (bytes.length == 0) // empty tag! { return new DERTaggedObject(false, tagNo, DERNull.INSTANCE); } // // simple type - implicit... return an octet string // return new DERTaggedObject(false, tagNo, new DEROctetString(bytes)); } return new DERUnknownTag(tag, bytes); } } } private byte[] readDefiniteLengthFully(int length) throws IOException { byte[] bytes = new byte[length]; readFully(bytes); return bytes; } /** * read a string of bytes representing an indefinite length object. */ private byte[] readIndefiniteLengthFully() throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); int b, b1; b1 = read(); while ((b = read()) >= 0) { if (b1 == 0 && b == 0) { break; } bOut.write(b1); b1 = b; } return bOut.toByteArray(); } private BERConstructedOctetString buildConstructedOctetString(DERObject sentinel) throws IOException { Vector octs = new Vector(); DERObject o; while ((o = readObject()) != sentinel) { octs.addElement(o); } return new BERConstructedOctetString(octs); } // // yes, people actually do this... // private BERConstructedOctetString buildDerConstructedOctetString(int length) throws IOException { DefiniteLengthInputStream dIn = new DefiniteLengthInputStream(this, length); ASN1InputStream aIn = new ASN1InputStream(dIn, length); return aIn.buildConstructedOctetString(null); } private ASN1EncodableVector buildEncodableVector(DERObject sentinel) throws IOException { ASN1EncodableVector v = new ASN1EncodableVector(); DERObject o; while ((o = readObject()) != sentinel) { v.add(o); } return v; } private ASN1EncodableVector buildDerEncodableVector(int length) throws IOException { DefiniteLengthInputStream dIn = new DefiniteLengthInputStream(this, length); ASN1InputStream aIn = new ASN1InputStream(dIn, length); return aIn.buildEncodableVector(null); } public DERObject readObject() throws IOException { int tag = read(); if (tag == -1) { if (eofFound) { throw new EOFException("attempt to read past end of file."); } eofFound = true; return null; } int tagNo = 0; if ((tag & TAGGED) != 0 || (tag & APPLICATION) != 0) { tagNo = readTagNumber(tag); } int length = readLength(); if (length < 0) // indefinite length method { switch (tag) { case NULL: return BERNull.INSTANCE; case SEQUENCE | CONSTRUCTED: return new BERSequence(buildEncodableVector(END_OF_STREAM)); case SET | CONSTRUCTED: return new BERSet(buildEncodableVector(END_OF_STREAM), false); case OCTET_STRING | CONSTRUCTED: return buildConstructedOctetString(END_OF_STREAM); default: { // // with tagged object tag number is bottom 5 bits // if ((tag & TAGGED) != 0) { // // simple type - implicit... return an octet string // if ((tag & CONSTRUCTED) == 0) { byte[] bytes = readIndefiniteLengthFully(); return new BERTaggedObject(false, tagNo, new DEROctetString(bytes)); } // // either constructed or explicitly tagged // ASN1EncodableVector v = buildEncodableVector(END_OF_STREAM); if (v.size() == 0) // empty tag! { return new DERTaggedObject(tagNo); } if (v.size() == 1) { // // explicitly tagged (probably!) - if it isn't we'd have to // tell from the context // return new BERTaggedObject(tagNo, v.get(0)); } return new BERTaggedObject(false, tagNo, new BERSequence(v)); } throw new IOException("unknown BER object encountered"); } } } else { if (tag == 0 && length == 0) // end of contents marker. { return END_OF_STREAM; } return buildObject(tag, tagNo, length); } } private int readTagNumber(int tag) throws IOException { int tagNo = tag & 0x1f; if (tagNo == 0x1f) { int b = read(); tagNo = 0; while ((b >= 0) && ((b & 0x80) != 0)) { tagNo |= (b & 0x7f); tagNo <<= 7; b = read(); } if (b < 0) { eofFound = true; throw new EOFException("EOF found inside tag value."); } tagNo |= (b & 0x7f); } return tagNo; } } azureus-4.3.0.6/org/bouncycastle/jce/0000755000175000017500000000000011310377634016666 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/jce/provider/0000755000175000017500000000000011310377634020520 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/jce/provider/ElGamalUtil.java0000644000175000017500000000321710061400650023511 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.security.InvalidKeyException; import java.security.PrivateKey; import java.security.PublicKey; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.ElGamalParameters; import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters; import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters; import org.bouncycastle.jce.interfaces.ElGamalPrivateKey; import org.bouncycastle.jce.interfaces.ElGamalPublicKey; /** * utility class for converting jce/jca ElGamal objects * objects into their org.bouncycastle.crypto counterparts. */ public class ElGamalUtil { static public AsymmetricKeyParameter generatePublicKeyParameter( PublicKey key) throws InvalidKeyException { if (key instanceof ElGamalPublicKey) { ElGamalPublicKey k = (ElGamalPublicKey)key; return new ElGamalPublicKeyParameters(k.getY(), new ElGamalParameters(k.getParams().getP(), k.getParams().getG())); } throw new InvalidKeyException("can't identify ElGamal public key."); } static public AsymmetricKeyParameter generatePrivateKeyParameter( PrivateKey key) throws InvalidKeyException { if (key instanceof ElGamalPrivateKey) { ElGamalPrivateKey k = (ElGamalPrivateKey)key; return new ElGamalPrivateKeyParameters(k.getX(), new ElGamalParameters(k.getParams().getP(), k.getParams().getG())); } throw new InvalidKeyException("can't identify ElGamal private key."); } } azureus-4.3.0.6/org/bouncycastle/jce/provider/JDKDSASigner.java0000644000175000017500000001610210407566336023500 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.SignatureException; import java.security.interfaces.DSAKey; import java.security.spec.AlgorithmParameterSpec; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERInputStream; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DSA; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.crypto.params.ParametersWithRandom; //import org.bouncycastle.crypto.signers.DSASigner; import org.bouncycastle.crypto.signers.ECDSASigner; import org.bouncycastle.jce.interfaces.ECKey; public class JDKDSASigner extends Signature implements PKCSObjectIdentifiers, X509ObjectIdentifiers { private Digest digest; private DSA signer; private SecureRandom random; protected JDKDSASigner( String name, Digest digest, DSA signer) { super(name); this.digest = digest; this.signer = signer; } protected void engineInitVerify( PublicKey publicKey) throws InvalidKeyException { CipherParameters param = null; if (publicKey instanceof ECKey) { param = ECUtil.generatePublicKeyParameter(publicKey); } else if (publicKey instanceof DSAKey) { param = DSAUtil.generatePublicKeyParameter(publicKey); } else { try { /* byte[] bytes = publicKey.getEncoded(); publicKey = JDKKeyFactory.createPublicKeyFromDERStream( new ByteArrayInputStream(bytes)); if (publicKey instanceof ECKey) { param = ECUtil.generatePublicKeyParameter(publicKey); } else if (publicKey instanceof DSAKey) { param = DSAUtil.generatePublicKeyParameter(publicKey); } else { */ throw new InvalidKeyException("can't recognise key type in DSA based signer"); //} } catch (Exception e) { throw new InvalidKeyException("can't recognise key type in DSA based signer"); } } digest.reset(); signer.init(false, param); } protected void engineInitSign( PrivateKey privateKey, SecureRandom random) throws InvalidKeyException { this.random = random; engineInitSign(privateKey); } protected void engineInitSign( PrivateKey privateKey) throws InvalidKeyException { CipherParameters param = null; if (privateKey instanceof ECKey) { param = ECUtil.generatePrivateKeyParameter(privateKey); } else { param = DSAUtil.generatePrivateKeyParameter(privateKey); } digest.reset(); if (random != null) { signer.init(true, new ParametersWithRandom(param, random)); } else { signer.init(true, param); } } protected void engineUpdate( byte b) throws SignatureException { digest.update(b); } protected void engineUpdate( byte[] b, int off, int len) throws SignatureException { digest.update(b, off, len); } protected byte[] engineSign() throws SignatureException { byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); try { BigInteger[] sig = signer.generateSignature(hash); return derEncode(sig[0], sig[1]); } catch (Exception e) { throw new SignatureException(e.toString()); } } protected boolean engineVerify( byte[] sigBytes) throws SignatureException { byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); BigInteger[] sig; try { sig = derDecode(sigBytes); } catch (Exception e) { throw new SignatureException("error decoding signature bytes."); } return signer.verifySignature(hash, sig[0], sig[1]); } protected void engineSetParameter( AlgorithmParameterSpec params) { throw new UnsupportedOperationException("engineSetParameter unsupported"); } /** * @deprecated replaced with */ protected void engineSetParameter( String param, Object value) { throw new UnsupportedOperationException("engineSetParameter unsupported"); } /** * @deprecated */ protected Object engineGetParameter( String param) { throw new UnsupportedOperationException("engineSetParameter unsupported"); } private byte[] derEncode( BigInteger r, BigInteger s) throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new DERInteger(r)); v.add(new DERInteger(s)); dOut.writeObject(new DERSequence(v)); return bOut.toByteArray(); } private BigInteger[] derDecode( byte[] encoding) throws IOException { ByteArrayInputStream bIn = new ByteArrayInputStream(encoding); DERInputStream dIn = new DERInputStream(bIn); ASN1Sequence s = (ASN1Sequence)dIn.readObject(); BigInteger[] sig = new BigInteger[2]; sig[0] = ((DERInteger)s.getObjectAt(0)).getValue(); sig[1] = ((DERInteger)s.getObjectAt(1)).getValue(); return sig; } /* static public class stdDSA extends JDKDSASigner { public stdDSA() { super("SHA1withDSA", new SHA1Digest(), new DSASigner()); } } */ static public class ecDSA extends JDKDSASigner { public ecDSA() { super("SHA1withECDSA", new SHA1Digest(), new ECDSASigner()); } } } azureus-4.3.0.6/org/bouncycastle/jce/provider/X509CRLObject.java0000644000175000017500000002035710061400650023512 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Principal; import java.security.Provider; import java.security.PublicKey; import java.security.Security; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CRLException; import java.security.cert.Certificate; import java.security.cert.X509CRL; import java.security.cert.X509CRLEntry; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.ASN1OutputStream; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.x509.CertificateList; import org.bouncycastle.asn1.x509.TBSCertList; import org.bouncycastle.asn1.x509.X509Extension; import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.jce.X509Principal; /** * The following extensions are listed in RFC 2459 as relevant to CRLs * * Authority Key Identifier * Issuer Alternative Name * CRL Number * Delta CRL Indicator (critical) * Issuing Distribution Point (critical) */ public class X509CRLObject extends X509CRL { private CertificateList c; public X509CRLObject( CertificateList c) { this.c = c; } /** * Will return true if any extensions are present and marked * as critical as we currently dont handle any extensions! */ public boolean hasUnsupportedCriticalExtension() { Set extns = getCriticalExtensionOIDs(); if ( extns != null && !extns.isEmpty() ) { return true; } return false; } private Set getExtensionOIDs(boolean critical) { if (this.getVersion() == 2) { HashSet set = new HashSet(); X509Extensions extensions = c.getTBSCertList().getExtensions(); Enumeration e = extensions.oids(); while (e.hasMoreElements()) { DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); X509Extension ext = extensions.getExtension(oid); if (critical == ext.isCritical()) { set.add(oid.getId()); } } return set; } return null; } public Set getCriticalExtensionOIDs() { return getExtensionOIDs(true); } public Set getNonCriticalExtensionOIDs() { return getExtensionOIDs(false); } public byte[] getExtensionValue(String oid) { X509Extensions exts = c.getTBSCertList().getExtensions(); if (exts != null) { X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid)); if (ext != null) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(ext.getValue()); return bOut.toByteArray(); } catch (Exception e) { throw new RuntimeException("error encoding " + e.toString()); } } } return null; } public byte[] getEncoded() throws CRLException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(c); return bOut.toByteArray(); } catch (IOException e) { throw new CRLException(e.toString()); } } public void verify(PublicKey key) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { verify(key, "BC"); } public void verify(PublicKey key, String sigProvider) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { if ( !c.getSignatureAlgorithm().equals(c.getTBSCertList().getSignature()) ) { throw new CRLException("Signature algorithm on CertifcateList does not match TBSCertList."); } Signature sig = Signature.getInstance(getSigAlgName(), sigProvider); sig.initVerify(key); sig.update(this.getTBSCertList()); if ( !sig.verify(this.getSignature()) ) { throw new SignatureException("CRL does not verify with supplied public key."); } } public int getVersion() { return c.getVersion(); } public Principal getIssuerDN() { return new X509Principal(c.getIssuer()); } public X500Principal getIssuerX500Principal() { try { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); ASN1OutputStream aOut = new ASN1OutputStream(bOut); aOut.writeObject(c.getIssuer()); return new X500Principal(bOut.toByteArray()); } catch (IOException e) { throw new IllegalStateException("can't encode issuer DN"); } } public Date getThisUpdate() { return c.getThisUpdate().getDate(); } public Date getNextUpdate() { if (c.getNextUpdate() != null) { return c.getNextUpdate().getDate(); } return null; } public X509CRLEntry getRevokedCertificate(BigInteger serialNumber) { TBSCertList.CRLEntry[] certs = c.getRevokedCertificates(); if ( certs != null ) { for ( int i = 0; i < certs.length; i++ ) { if ( certs[i].getUserCertificate().getValue().equals(serialNumber) ) { return new X509CRLEntryObject(certs[i]); } } } return null; } public Set getRevokedCertificates() { TBSCertList.CRLEntry[] certs = c.getRevokedCertificates(); if ( certs != null ) { HashSet set = new HashSet(); for ( int i = 0; i < certs.length; i++ ) { set.add(new X509CRLEntryObject(certs[i])); } return set; } return null; } public byte[] getTBSCertList() throws CRLException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(c.getTBSCertList()); return bOut.toByteArray(); } catch (IOException e) { throw new CRLException(e.toString()); } } public byte[] getSignature() { return c.getSignature().getBytes(); } public String getSigAlgName() { Provider prov = Security.getProvider("BC"); String algName = prov.getProperty("Alg.Alias.Signature." + this.getSigAlgOID()); if ( algName != null ) { return algName; } Provider[] provs = Security.getProviders(); // // search every provider looking for a real algorithm // for (int i = 0; i != provs.length; i++) { algName = provs[i].getProperty("Alg.Alias.Signature." + this.getSigAlgOID()); if ( algName != null ) { return algName; } } return this.getSigAlgOID(); } public String getSigAlgOID() { return c.getSignatureAlgorithm().getObjectId().getId(); } public byte[] getSigAlgParams() { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); if ( c.getSignatureAlgorithm().getParameters() != null ) { try { DEROutputStream dOut = new DEROutputStream(bOut); dOut.writeObject(c.getSignatureAlgorithm().getParameters()); } catch (Exception e) { throw new RuntimeException("exception getting sig parameters " + e); } return bOut.toByteArray(); } return null; } /** * Returns a string representation of this CRL. * * @return a string representation of this CRL. */ public String toString() { return "X.509 CRL"; } /** * Checks whether the given certificate is on this CRL. * * @param cert the certificate to check for. * @return true if the given certificate is on this CRL, * false otherwise. */ public boolean isRevoked(Certificate cert) { if ( !cert.getType().equals("X.509") ) { throw new RuntimeException("X.509 CRL used with non X.509 Cert"); } TBSCertList.CRLEntry[] certs = c.getRevokedCertificates(); if ( certs != null ) { BigInteger serial = ((X509Certificate)cert).getSerialNumber(); for ( int i = 0; i < certs.length; i++ ) { if ( certs[i].getUserCertificate().getValue().equals(serial) ) { return true; } } } return false; } } azureus-4.3.0.6/org/bouncycastle/jce/provider/BouncyCastleProvider.java0000644000175000017500000011512510061400650025461 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.security.Provider; /** * To add the provider at runtime use: *
       * import java.security.Security;
       * import org.bouncycastle.jce.provider.BouncyCastleProvider;
       *
       * Security.addProvider(new BouncyCastleProvider());
       * 
      * The provider can also be configured as part of your environment via * static registration by adding an entry to the java.security properties * file (found in $JAVA_HOME/jre/lib/security/java.security, where * $JAVA_HOME is the location of your JDK/JRE distribution). You'll find * detailed instructions in the file but basically it comes down to adding * a line: *
       * 
       *    security.provider.<n>=org.bouncycastle.jce.provider.BouncyCastleProvider
       * 
       * 
      * Where <n> is the preference you want the provider at (1 being the * most prefered). *

      Note: JCE algorithm names should be uppercase only so the case insensitive * test for getInstance works. */ public final class BouncyCastleProvider extends Provider { private static String info = "BouncyCastle Security Provider v1.23"; public static String PROVIDER_NAME = "BC"; /** * Construct a new provider. This should only be required when * using runtime registration of the provider using the * Security.addProvider() mechanism. */ public BouncyCastleProvider() { super(PROVIDER_NAME, 1.23, info); // // KeyStore // put("KeyStore.BKS", "org.bouncycastle.jce.provider.JDKKeyStore"); put("KeyStore.BouncyCastle", "org.bouncycastle.jce.provider.JDKKeyStore$BouncyCastleStore"); put("KeyStore.PKCS12", "org.bouncycastle.jce.provider.JDKPKCS12KeyStore$BCPKCS12KeyStore"); put("KeyStore.BCPKCS12", "org.bouncycastle.jce.provider.JDKPKCS12KeyStore$BCPKCS12KeyStore"); put("KeyStore.PKCS12-DEF", "org.bouncycastle.jce.provider.JDKPKCS12KeyStore$DefPKCS12KeyStore"); put("Alg.Alias.KeyStore.UBER", "BouncyCastle"); put("Alg.Alias.KeyStore.BOUNCYCASTLE", "BouncyCastle"); put("Alg.Alias.KeyStore.bouncycastle", "BouncyCastle"); // // certificate factories. // put("CertificateFactory.X.509", "org.bouncycastle.jce.provider.JDKX509CertificateFactory"); put("Alg.Alias.CertificateFactory.X509", "X.509"); // // algorithm parameter generators // put("AlgorithmParameterGenerator.DH", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DH"); put("AlgorithmParameterGenerator.DSA", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DSA"); put("AlgorithmParameterGenerator.ELGAMAL", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$ElGamal"); put("AlgorithmParameterGenerator.DES", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DES"); put("AlgorithmParameterGenerator.DESEDE", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DES"); put("AlgorithmParameterGenerator.1.2.840.113549.3.7", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DES"); put("AlgorithmParameterGenerator.1.3.14.3.2.7", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DES"); put("AlgorithmParameterGenerator.IDEA", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$IDEA"); put("AlgorithmParameterGenerator.1.3.6.1.4.1.188.7.1.1.2", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$IDEA"); put("AlgorithmParameterGenerator.RC2", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$RC2"); put("AlgorithmParameterGenerator.1.2.840.113549.3.2", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$RC2"); put("AlgorithmParameterGenerator.CAST5", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$CAST5"); put("AlgorithmParameterGenerator.1.2.840.113533.7.66.10", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$CAST5"); put("AlgorithmParameterGenerator.AES", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$AES"); put("Alg.Alias.AlgorithmParameterGenerator.2.16.840.1.101.3.4.2", "AES"); // these first 3 are wrong, but seem to have got around put("Alg.Alias.AlgorithmParameterGenerator.2.16.840.1.101.3.4.22", "AES"); put("Alg.Alias.AlgorithmParameterGenerator.2.16.840.1.101.3.4.42", "AES"); put("Alg.Alias.AlgorithmParameterGenerator.2.16.840.1.101.3.4.1.2", "AES"); put("Alg.Alias.AlgorithmParameterGenerator.2.16.840.1.101.3.4.1.22", "AES"); put("Alg.Alias.AlgorithmParameterGenerator.2.16.840.1.101.3.4.1.42", "AES"); // // algorithm parameters // put("AlgorithmParameters.DH", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$DH"); put("AlgorithmParameters.DSA", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$DSA"); put("AlgorithmParameters.ELGAMAL", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$ElGamal"); put("AlgorithmParameters.IES", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IES"); put("AlgorithmParameters.PKCS12PBE", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$PKCS12PBE"); put("AlgorithmParameters.1.2.840.113549.3.7", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); put("AlgorithmParameters.IDEA", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IDEAAlgorithmParameters"); put("AlgorithmParameters.1.3.6.1.4.1.188.7.1.1.2", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IDEAAlgorithmParameters"); put("AlgorithmParameters.CAST5", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$CAST5AlgorithmParameters"); put("AlgorithmParameters.1.2.840.113533.7.66.10", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$CAST5AlgorithmParameters"); put("Alg.Alias.AlgorithmParameters.PBEWITHSHA1ANDRC2", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND3-KEYTRIPLEDES", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND2-KEYTRIPLEDES", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.PBEWITHSHAANDRC2", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.PBEWITHSHAANDRC4", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.PBEWITHSHAANDTWOFISH", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.PBEWITHSHAANDIDEA", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.1", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.2", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.3", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.4", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.5", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.6", "PKCS12PBE"); // // key agreement // put("KeyAgreement.DH", "org.bouncycastle.jce.provider.JCEDHKeyAgreement"); put("KeyAgreement.ECDH", "org.bouncycastle.jce.provider.JCEECDHKeyAgreement$DH"); put("KeyAgreement.ECDHC", "org.bouncycastle.jce.provider.JCEECDHKeyAgreement$DHC"); // // cipher engines // put("Cipher.DES", "org.bouncycastle.jce.provider.JCEBlockCipher$DES"); put("Cipher.DESEDE", "org.bouncycastle.jce.provider.JCEBlockCipher$DESede"); put("Cipher.1.2.840.113549.3.7", "org.bouncycastle.jce.provider.JCEBlockCipher$DESedeCBC"); put("Cipher.1.3.14.3.2.7", "org.bouncycastle.jce.provider.JCEBlockCipher$DESCBC"); put("Cipher.DESEDEWRAP", "org.bouncycastle.jce.provider.WrapCipherSpi$DESEDEWrap"); put("Cipher.1.2.840.113549.1.9.16.3.6", "org.bouncycastle.jce.provider.WrapCipherSpi$DESEDEWrap"); put("Cipher.SKIPJACK", "org.bouncycastle.jce.provider.JCEBlockCipher$Skipjack"); put("Cipher.BLOWFISH", "org.bouncycastle.jce.provider.JCEBlockCipher$Blowfish"); put("Cipher.TWOFISH", "org.bouncycastle.jce.provider.JCEBlockCipher$Twofish"); put("Cipher.RC2", "org.bouncycastle.jce.provider.JCEBlockCipher$RC2"); put("Cipher.RC2WRAP", "org.bouncycastle.jce.provider.WrapCipherSpi$RC2Wrap"); put("Cipher.1.2.840.113549.1.9.16.3.7", "org.bouncycastle.jce.provider.WrapCipherSpi$RC2Wrap"); put("Cipher.ARC4", "org.bouncycastle.jce.provider.JCEStreamCipher$RC4"); put("Cipher.RC4", "org.bouncycastle.jce.provider.JCEStreamCipher$RC4"); put("Alg.Alias.Cipher.1.2.840.113549.3.4", "RC4"); put("Cipher.RC5", "org.bouncycastle.jce.provider.JCEBlockCipher$RC5"); put("Cipher.1.2.840.113549.3.2", "org.bouncycastle.jce.provider.JCEBlockCipher$RC2CBC"); put("Alg.Alias.Cipher.RC5-32", "RC5"); put("Cipher.RC5-64", "org.bouncycastle.jce.provider.JCEBlockCipher$RC564"); put("Cipher.RC6", "org.bouncycastle.jce.provider.JCEBlockCipher$RC6"); put("Cipher.RIJNDAEL", "org.bouncycastle.jce.provider.JCEBlockCipher$Rijndael"); put("Cipher.AES", "org.bouncycastle.jce.provider.JCEBlockCipher$AES"); put("Alg.Alias.Cipher.2.16.840.1.101.3.4.2", "AES"); put("Alg.Alias.Cipher.2.16.840.1.101.3.4.22", "AES"); put("Alg.Alias.Cipher.2.16.840.1.101.3.4.42", "AES"); put("Cipher.2.16.840.1.101.3.4.1.2", "org.bouncycastle.jce.provider.JCEBlockCipher$AESCBC"); put("Cipher.2.16.840.1.101.3.4.1.22", "org.bouncycastle.jce.provider.JCEBlockCipher$AESCBC"); put("Cipher.2.16.840.1.101.3.4.1.42", "org.bouncycastle.jce.provider.JCEBlockCipher$AESCBC"); put("Cipher.AESWRAP", "org.bouncycastle.jce.provider.WrapCipherSpi$AESWrap"); put("Cipher.SERPENT", "org.bouncycastle.jce.provider.JCEBlockCipher$Serpent"); put("Cipher.CAST5", "org.bouncycastle.jce.provider.JCEBlockCipher$CAST5"); put("Cipher.1.2.840.113533.7.66.10", "org.bouncycastle.jce.provider.JCEBlockCipher$CAST5CBC"); put("Cipher.CAST6", "org.bouncycastle.jce.provider.JCEBlockCipher$CAST6"); put("Cipher.IDEA", "org.bouncycastle.jce.provider.JCEBlockCipher$IDEA"); put("Cipher.1.3.6.1.4.1.188.7.1.1.2", "org.bouncycastle.jce.provider.JCEBlockCipher$IDEACBC"); /* put("Cipher.DES/CFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$DES_CFB8"); put("Cipher.DESEDE/CFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$DESede_CFB8"); put("Cipher.SKIPJACK/CFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$Skipjack_CFB8"); put("Cipher.BLOWFISH/CFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$Blowfish_CFB8"); put("Cipher.TWOFISH/CFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$Twofish_CFB8"); put("Cipher.IDEA/CFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$IDEA_CFB8"); put("Alg.Alias.Cipher.DES/CFB8/NOPADDING", "DES/CFB8"); put("Alg.Alias.Cipher.DESEDE/CFB8/NOPADDING", "DESEDE/CFB8"); put("Alg.Alias.Cipher.SKIPJACK/CFB8/NOPADDING", "SKIPJACK/CFB8"); put("Alg.Alias.Cipher.BLOWFISH/CFB8/NOPADDING", "Blowfish/CFB8"); put("Alg.Alias.Cipher.TWOFISH/CFB8/NOPADDING", "Twofish/CFB8"); put("Alg.Alias.Cipher.IDEA/CFB8/NOPADDING", "IDEA/CFB8"); put("Cipher.DES/OFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$DES_OFB8"); put("Cipher.DESEDE/OFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$DESede_OFB8"); put("Cipher.SKIPJACK/OFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$Skipjack_OFB8"); put("Cipher.BLOWFISH/OFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$Blowfish_OFB8"); put("Cipher.TWOFISH/OFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$Twofish_OFB8"); put("Cipher.IDEA/OFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$IDEA_OFB8"); put("Alg.Alias.Cipher.DES/OFB8/NOPADDING", "DES/OFB8"); put("Alg.Alias.Cipher.DESEDE/OFB8/NOPADDING", "DESEDE/OFB8"); put("Alg.Alias.Cipher.SKIPJACK/OFB8/NOPADDING", "SKIPJACK/OFB8"); put("Alg.Alias.Cipher.BLOWFISH/OFB8/NOPADDING", "BLOWFISH/OFB8"); put("Alg.Alias.Cipher.TWOFISH/OFB8/NOPADDING", "TWOFISH/OFB8"); put("Alg.Alias.Cipher.IDEA/OFB8/NOPADDING", "IDEA/OFB8"); */ put("Cipher.RSA", "org.bouncycastle.jce.provider.JCERSACipher$NoPadding"); put("Cipher.RSA/RAW", "org.bouncycastle.jce.provider.JCERSACipher$NoPadding"); put("Cipher.RSA/PKCS1", "org.bouncycastle.jce.provider.JCERSACipher$PKCS1v1_5Padding"); put("Cipher.1.2.840.113549.1.1.1", "org.bouncycastle.jce.provider.JCERSACipher$PKCS1v1_5Padding"); put("Cipher.2.5.8.1.1", "org.bouncycastle.jce.provider.JCERSACipher$PKCS1v1_5Padding"); put("Cipher.RSA/1", "org.bouncycastle.jce.provider.JCERSACipher$PKCS1v1_5Padding_PrivateOnly"); put("Cipher.RSA/2", "org.bouncycastle.jce.provider.JCERSACipher$PKCS1v1_5Padding_PublicOnly"); put("Cipher.RSA/OAEP", "org.bouncycastle.jce.provider.JCERSACipher$OAEPPadding"); put("Cipher.1.2.840.113549.1.1.7", "org.bouncycastle.jce.provider.JCERSACipher$OAEPPadding"); put("Cipher.RSA/ISO9796-1", "org.bouncycastle.jce.provider.JCERSACipher$ISO9796d1Padding"); put("Cipher.ECIES", "org.bouncycastle.jce.provider.JCEIESCipher$ECIES"); put("Cipher.ELGAMAL", "org.bouncycastle.jce.provider.JCEElGamalCipher$NoPadding"); put("Cipher.ELGAMAL/PKCS1", "org.bouncycastle.jce.provider.JCEElGamalCipher$PKCS1v1_5Padding"); put("Alg.Alias.Cipher.RSA//RAW", "RSA"); put("Alg.Alias.Cipher.RSA//NOPADDING", "RSA"); put("Alg.Alias.Cipher.RSA//PKCS1PADDING", "RSA/PKCS1"); put("Alg.Alias.Cipher.RSA//OAEPPADDING", "RSA/OAEP"); put("Alg.Alias.Cipher.RSA//ISO9796-1PADDING", "RSA/ISO9796-1"); put("Alg.Alias.Cipher.RSA/ECB/NOPADDING", "RSA"); put("Alg.Alias.Cipher.RSA/ECB/PKCS1PADDING", "RSA/PKCS1"); put("Alg.Alias.Cipher.RSA/ECB/OAEPPADDING", "RSA/OAEP"); put("Alg.Alias.Cipher.RSA/ECB/ISO9796-1PADDING", "RSA/ISO9796-1"); put("Alg.Alias.Cipher.RSA/NONE/NOPADDING", "RSA"); put("Alg.Alias.Cipher.RSA/NONE/PKCS1PADDING", "RSA/PKCS1"); put("Alg.Alias.Cipher.RSA/NONE/OAEPPADDING", "RSA/OAEP"); put("Alg.Alias.Cipher.RSA/NONE/ISO9796-1PADDING", "RSA/ISO9796-1"); put("Alg.Alias.Cipher.RSA/1/PCKS1PADDING", "RSA/1"); put("Alg.Alias.Cipher.RSA/2/PCKS1PADDING", "RSA/2"); put("Alg.Alias.Cipher.ELGAMAL/ECB/PKCS1PADDING", "ELGAMAL/PKCS1"); put("Alg.Alias.Cipher.ELGAMAL/NONE/PKCS1PADDING", "ELGAMAL/PKCS1"); put("Cipher.PBEWITHMD5ANDDES", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithMD5AndDES"); put("Cipher.BROKENPBEWITHMD5ANDDES", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$BrokePBEWithMD5AndDES"); put("Cipher.PBEWITHMD5ANDRC2", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithMD5AndRC2"); put("Cipher.PBEWITHSHA1ANDDES", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHA1AndDES"); put("Cipher.BROKENPBEWITHSHA1ANDDES", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$BrokePBEWithSHA1AndDES"); put("Cipher.PBEWITHSHA1ANDRC2", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHA1AndRC2"); put("Cipher.PBEWITHSHAAND3-KEYTRIPLEDES-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAndDES3Key"); put("Cipher.BROKENPBEWITHSHAAND3-KEYTRIPLEDES-CBC", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$BrokePBEWithSHAAndDES3Key"); put("Cipher.OLDPBEWITHSHAAND3-KEYTRIPLEDES-CBC", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$OldPBEWithSHAAndDES3Key"); put("Cipher.PBEWITHSHAAND2-KEYTRIPLEDES-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAndDES2Key"); put("Cipher.BROKENPBEWITHSHAAND2-KEYTRIPLEDES-CBC", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$BrokePBEWithSHAAndDES2Key"); put("Cipher.PBEWITHSHAAND128BITRC2-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAnd128BitRC2"); put("Cipher.PBEWITHSHAAND40BITRC2-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAnd40BitRC2"); put("Cipher.PBEWITHSHAAND128BITRC4", "org.bouncycastle.jce.provider.JCEStreamCipher$PBEWithSHAAnd128BitRC4"); put("Cipher.PBEWITHSHAAND40BITRC4", "org.bouncycastle.jce.provider.JCEStreamCipher$PBEWithSHAAnd40BitRC4"); put("Cipher.PBEWITHSHAANDTWOFISH-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAndTwofish"); put("Cipher.OLDPBEWITHSHAANDTWOFISH-CBC", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$OldPBEWithSHAAndTwofish"); put("Cipher.PBEWITHSHAANDIDEA-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAndIDEA"); put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.1", "PBEWITHSHAAND128BITRC4"); put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.2", "PBEWITHSHAAND40BITRC4"); put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.3", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"); put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.4", "PBEWITHSHAAND2-KEYTRIPLEDES-CBC"); put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.5", "PBEWITHSHAAND128BITRC2-CBC"); put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.6", "PBEWITHSHAAND40BITRC2-CBC"); // // key generators. // put("KeyGenerator.DES", "org.bouncycastle.jce.provider.JCEKeyGenerator$DES"); put("Alg.Alias.KeyGenerator.1.3.14.3.2.7", "DES"); put("KeyGenerator.DESEDE", "org.bouncycastle.jce.provider.JCEKeyGenerator$DESede"); put("KeyGenerator.1.2.840.113549.3.7", "org.bouncycastle.jce.provider.JCEKeyGenerator$DESede3"); put("KeyGenerator.DESEDEWRAP", "org.bouncycastle.jce.provider.JCEKeyGenerator$DESede"); put("KeyGenerator.SKIPJACK", "org.bouncycastle.jce.provider.JCEKeyGenerator$Skipjack"); put("KeyGenerator.BLOWFISH", "org.bouncycastle.jce.provider.JCEKeyGenerator$Blowfish"); put("KeyGenerator.TWOFISH", "org.bouncycastle.jce.provider.JCEKeyGenerator$Twofish"); put("KeyGenerator.RC2", "org.bouncycastle.jce.provider.JCEKeyGenerator$RC2"); put("KeyGenerator.1.2.840.113549.3.2", "org.bouncycastle.jce.provider.JCEKeyGenerator$RC2"); put("KeyGenerator.RC4", "org.bouncycastle.jce.provider.JCEKeyGenerator$RC4"); put("Alg.Alias.KeyGenerator.ARC4", "RC4"); put("Alg.Alias.KeyGenerator.1.2.840.113549.3.4", "RC4"); put("KeyGenerator.RC5", "org.bouncycastle.jce.provider.JCEKeyGenerator$RC5"); put("Alg.Alias.KeyGenerator.RC5-32", "RC5"); put("KeyGenerator.RC5-64", "org.bouncycastle.jce.provider.JCEKeyGenerator$RC564"); put("KeyGenerator.RC6", "org.bouncycastle.jce.provider.JCEKeyGenerator$RC6"); put("KeyGenerator.RIJNDAEL", "org.bouncycastle.jce.provider.JCEKeyGenerator$Rijndael"); put("KeyGenerator.AES", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES"); put("KeyGenerator.2.16.840.1.101.3.4.2", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES128"); put("KeyGenerator.2.16.840.1.101.3.4.22", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES192"); put("KeyGenerator.2.16.840.1.101.3.4.42", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES256"); put("KeyGenerator.2.16.840.1.101.3.4.1.2", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES128"); put("KeyGenerator.2.16.840.1.101.3.4.1.22", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES192"); put("KeyGenerator.2.16.840.1.101.3.4.1.42", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES256"); put("KeyGenerator.AESWRAP", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES"); put("KeyGenerator.SERPENT", "org.bouncycastle.jce.provider.JCEKeyGenerator$Serpent"); put("KeyGenerator.CAST5", "org.bouncycastle.jce.provider.JCEKeyGenerator$CAST5"); put("KeyGenerator.1.2.840.113533.7.66.10", "org.bouncycastle.jce.provider.JCEKeyGenerator$CAST5"); put("KeyGenerator.CAST6", "org.bouncycastle.jce.provider.JCEKeyGenerator$CAST6"); put("KeyGenerator.IDEA", "org.bouncycastle.jce.provider.JCEKeyGenerator$IDEA"); put("KeyGenerator.1.3.6.1.4.1.188.7.1.1.2", "org.bouncycastle.jce.provider.JCEKeyGenerator$IDEA"); put("KeyGenerator.HMACMD2", "org.bouncycastle.jce.provider.JCEKeyGenerator$MD2HMAC"); put("KeyGenerator.HMACMD4", "org.bouncycastle.jce.provider.JCEKeyGenerator$MD4HMAC"); put("KeyGenerator.HMACMD5", "org.bouncycastle.jce.provider.JCEKeyGenerator$MD5HMAC"); put("KeyGenerator.HMACRIPEMD128", "org.bouncycastle.jce.provider.JCEKeyGenerator$RIPEMD128HMAC"); put("KeyGenerator.HMACRIPEMD160", "org.bouncycastle.jce.provider.JCEKeyGenerator$RIPEMD160HMAC"); put("KeyGenerator.HMACSHA1", "org.bouncycastle.jce.provider.JCEKeyGenerator$HMACSHA1"); put("KeyGenerator.HMACTIGER", "org.bouncycastle.jce.provider.JCEKeyGenerator$HMACTIGER"); // // key pair generators. // put("KeyPairGenerator.RSA", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$RSA"); put("KeyPairGenerator.DH", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$DH"); put("KeyPairGenerator.DSA", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$DSA"); put("KeyPairGenerator.ELGAMAL", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$ElGamal"); put("KeyPairGenerator.ECDSA", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$ECDSA"); put("KeyPairGenerator.ECDH", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$ECDH"); put("KeyPairGenerator.ECDHC", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$ECDHC"); put("KeyPairGenerator.ECIES", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$ECDH"); put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1.1", "RSA"); // // key factories // put("KeyFactory.RSA", "org.bouncycastle.jce.provider.JDKKeyFactory$RSA"); put("KeyFactory.DH", "org.bouncycastle.jce.provider.JDKKeyFactory$DH"); put("KeyFactory.DSA", "org.bouncycastle.jce.provider.JDKKeyFactory$DSA"); put("KeyFactory.ELGAMAL", "org.bouncycastle.jce.provider.JDKKeyFactory$ElGamal"); put("KeyFactory.ElGamal", "org.bouncycastle.jce.provider.JDKKeyFactory$ElGamal"); put("KeyFactory.EC", "org.bouncycastle.jce.provider.JDKKeyFactory$EC"); put("KeyFactory.ECDSA", "org.bouncycastle.jce.provider.JDKKeyFactory$ECDSA"); put("KeyFactory.ECDH", "org.bouncycastle.jce.provider.JDKKeyFactory$ECDH"); put("KeyFactory.ECDHC", "org.bouncycastle.jce.provider.JDKKeyFactory$ECDHC"); put("Alg.Alias.KeyFactory.1.2.840.113549.1.1.1", "RSA"); put("Alg.Alias.KeyFactory.1.2.840.10040.4.1", "DSA"); // // Algorithm parameters // put("AlgorithmParameters.DES", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); put("Alg.Alias.AlgorithmParameters.1.3.14.3.2.7", "DES"); put("AlgorithmParameters.DESEDE", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); put("AlgorithmParameters.1.2.840.113549.3.7", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); put("AlgorithmParameters.RC2", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$RC2AlgorithmParameters"); put("AlgorithmParameters.1.2.840.113549.3.2", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$RC2AlgorithmParameters"); put("AlgorithmParameters.RC5", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); put("AlgorithmParameters.RC6", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); put("AlgorithmParameters.IDEA", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IDEAAlgorithmParameters"); put("AlgorithmParameters.BLOWFISH", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); put("AlgorithmParameters.TWOFISH", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); put("AlgorithmParameters.SKIPJACK", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); put("AlgorithmParameters.RIJNDAEL", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); put("AlgorithmParameters.AES", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); put("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.2", "AES"); put("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.22", "AES"); put("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.42", "AES"); put("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.1.2", "AES"); put("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.1.22", "AES"); put("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.1.42", "AES"); // // secret key factories. // put("SecretKeyFactory.PBE/PKCS5", "org.bouncycastle.jce.provider.JCESecretKeyFactory$PBE_PKCS5"); put("SecretKeyFactory.PBE/PKCS12", "org.bouncycastle.jce.provider.JCESecretKeyFactory$PBE_PKCS12"); put("SecretKeyFactory.DES", "org.bouncycastle.jce.provider.JCESecretKeyFactory$DES"); put("SecretKeyFactory.DESEDE", "org.bouncycastle.jce.provider.JCESecretKeyFactory$DESede"); put("SecretKeyFactory.DESEDE", "org.bouncycastle.jce.provider.JCESecretKeyFactory$DESede"); put("Alg.Alias.SecretKeyFactory.PBE", "PBE/PKCS5"); put("Alg.Alias.SecretKeyFactory.PBEWITHMD5ANDDES", "PBE/PKCS5"); put("Alg.Alias.SecretKeyFactory.BROKENPBEWITHMD5ANDDES", "PBE/PKCS5"); put("Alg.Alias.SecretKeyFactory.PBEWITHMD5ANDRC2", "PBE/PKCS5"); put("Alg.Alias.SecretKeyFactory.PBEWITHSHA1ANDDES", "PBE/PKCS5"); put("Alg.Alias.SecretKeyFactory.BROKENPBEWITHSHA1ANDDES", "PBE/PKCS5"); put("Alg.Alias.SecretKeyFactory.PBEWITHSHA1ANDRC2", "PBE/PKCS5"); put("Alg.Alias.SecretKeyFactory.PBEWITHSHAAND3-KEYTRIPLEDES-CBC", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.OLDPBEWITHSHAAND3-KEYTRIPLEDES-CBC", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.BROKENPBEWITHSHAAND3-KEYTRIPLEDES-CBC", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.PBEWITHSHAAND2-KEYTRIPLEDES-CBC", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.BROKENPBEWITHSHAAND2-KEYTRIPLEDES-CBC", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.PBEWITHSHAAND128BITRC4", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.PBEWITHSHAAND40BITRC4", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.PBEWITHSHAAND128BITRC2-CBC", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.PBEWITHSHAAND40BITRC2-CBC", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.PBEWITHSHAANDTWOFISH-CBC", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.OLDPBEWITHSHAANDTWOFISH-CBC", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.PBEWITHSHAANDIDEA-CBC", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.PBEWITHHMACSHA", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.PBEWITHHMACRIPEMD160", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.1", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.2", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.3", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.4", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.5", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.6", "PBE/PKCS12"); put("Alg.Alias.SecretKeyFactory.1.3.14.3.2.26", "PBE/PKCS12"); // // MAC's // put("Mac.DESMAC", "org.bouncycastle.jce.provider.JCEMac$DES"); put("Alg.Alias.Mac.DES", "DESMAC"); put("Mac.DESMAC/CFB8", "org.bouncycastle.jce.provider.JCEMac$DESCFB8"); put("Alg.Alias.Mac.DES/CFB8", "DESMAC/CFB8"); put("Mac.DESEDEMAC", "org.bouncycastle.jce.provider.JCEMac$DESede"); put("Alg.Alias.Mac.DESEDE", "DESEDEMAC"); put("Mac.DESEDEMAC/CFB8", "org.bouncycastle.jce.provider.JCEMac$DESedeCFB8"); put("Alg.Alias.Mac.DESEDE/CFB8", "DESEDEMAC/CFB8"); put("Mac.SKIPJACKMAC", "org.bouncycastle.jce.provider.JCEMac$Skipjack"); put("Alg.Alias.Mac.SKIPJACK", "SKIPJACKMAC"); put("Mac.SKIPJACKMAC/CFB8", "org.bouncycastle.jce.provider.JCEMac$SkipjackCFB8"); put("Alg.Alias.Mac.SKIPJACK/CFB8", "SKIPJACKMAC/CFB8"); put("Mac.IDEAMAC", "org.bouncycastle.jce.provider.JCEMac$IDEA"); put("Alg.Alias.Mac.IDEA", "IDEAMAC"); put("Mac.IDEAMAC/CFB8", "org.bouncycastle.jce.provider.JCEMac$IDEACFB8"); put("Alg.Alias.Mac.IDEA/CFB8", "IDEAMAC/CFB8"); put("Mac.RC2MAC", "org.bouncycastle.jce.provider.JCEMac$RC2"); put("Alg.Alias.Mac.RC2", "RC2MAC"); put("Mac.RC2MAC/CFB8", "org.bouncycastle.jce.provider.JCEMac$RC2CFB8"); put("Alg.Alias.Mac.RC2/CFB8", "RC2MAC/CFB8"); put("Mac.RC5MAC", "org.bouncycastle.jce.provider.JCEMac$RC5"); put("Alg.Alias.Mac.RC5", "RC5MAC"); put("Mac.RC5MAC/CFB8", "org.bouncycastle.jce.provider.JCEMac$RC5CFB8"); put("Alg.Alias.Mac.RC5/CFB8", "RC5MAC/CFB8"); put("Mac.HMACMD2", "org.bouncycastle.jce.provider.JCEMac$MD2"); put("Alg.Alias.Mac.HMAC-MD2", "HMACMD2"); put("Alg.Alias.Mac.HMAC/MD2", "HMACMD2"); put("Mac.HMACMD4", "org.bouncycastle.jce.provider.JCEMac$MD4"); put("Alg.Alias.Mac.HMAC-MD4", "HMACMD4"); put("Alg.Alias.Mac.HMAC/MD4", "HMACMD4"); put("Mac.HMACMD5", "org.bouncycastle.jce.provider.JCEMac$MD5"); put("Alg.Alias.Mac.HMAC-MD5", "HMACMD5"); put("Alg.Alias.Mac.HMAC/MD5", "HMACMD5"); put("Mac.HMACRIPEMD128", "org.bouncycastle.jce.provider.JCEMac$RIPEMD128"); put("Alg.Alias.Mac.HMAC-RIPEMD128", "HMACRIPEMD128"); put("Alg.Alias.Mac.HMAC/RIPEMD128", "HMACRIPEMD128"); put("Mac.HMACRIPEMD160", "org.bouncycastle.jce.provider.JCEMac$RIPEMD160"); put("Alg.Alias.Mac.HMAC-RIPEMD160", "HMACRIPEMD160"); put("Alg.Alias.Mac.HMAC/RIPEMD160", "HMACRIPEMD160"); put("Mac.HMACSHA1", "org.bouncycastle.jce.provider.JCEMac$SHA1"); put("Alg.Alias.Mac.HMAC-SHA1", "HMACSHA1"); put("Alg.Alias.Mac.HMAC/SHA1", "HMACSHA1"); put("Mac.HMACSHA256", "org.bouncycastle.jce.provider.JCEMac$SHA256"); put("Alg.Alias.Mac.HMAC-SHA256", "HMACSHA256"); put("Alg.Alias.Mac.HMAC/SHA256", "HMACSHA256"); put("Mac.HMACSHA384", "org.bouncycastle.jce.provider.JCEMac$SHA384"); put("Alg.Alias.Mac.HMAC-SHA384", "HMACSHA384"); put("Alg.Alias.Mac.HMAC/SHA384", "HMACSHA384"); put("Mac.HMACSHA512", "org.bouncycastle.jce.provider.JCEMac$SHA512"); put("Alg.Alias.Mac.HMAC-SHA512", "HMACSHA512"); put("Alg.Alias.Mac.HMAC/SHA512", "HMACSHA512"); put("Mac.HMACTiger", "org.bouncycastle.jce.provider.JCEMac$Tiger"); put("Alg.Alias.Mac.HMAC-Tiger", "HMACTiger"); put("Alg.Alias.Mac.HMAC/Tiger", "HMACTiger"); put("Mac.PBEWITHHMACSHA", "org.bouncycastle.jce.provider.JCEMac$PBEWithSHA"); put("Mac.PBEWITHHMACRIPEMD160", "org.bouncycastle.jce.provider.JCEMac$PBEWithRIPEMD160"); put("Alg.Alias.Mac.1.3.14.3.2.26", "PBEWITHHMACSHA"); // // MessageDigests // put("MessageDigest.SHA-1", "org.bouncycastle.jce.provider.JDKMessageDigest$SHA1"); put("Alg.Alias.MessageDigest.SHA1", "SHA-1"); put("Alg.Alias.MessageDigest.SHA", "SHA-1"); put("Alg.Alias.MessageDigest.1.3.14.3.2.26", "SHA-1"); put("MessageDigest.SHA-256", "org.bouncycastle.jce.provider.JDKMessageDigest$SHA256"); put("MessageDigest.SHA-384", "org.bouncycastle.jce.provider.JDKMessageDigest$SHA384"); put("MessageDigest.SHA-512", "org.bouncycastle.jce.provider.JDKMessageDigest$SHA512"); put("MessageDigest.MD2", "org.bouncycastle.jce.provider.JDKMessageDigest$MD2"); put("MessageDigest.MD4", "org.bouncycastle.jce.provider.JDKMessageDigest$MD4"); put("MessageDigest.MD5", "org.bouncycastle.jce.provider.JDKMessageDigest$MD5"); put("MessageDigest.1.2.840.113549.2.5", "org.bouncycastle.jce.provider.JDKMessageDigest$MD5"); put("MessageDigest.RIPEMD128", "org.bouncycastle.jce.provider.JDKMessageDigest$RIPEMD128"); put("MessageDigest.RIPEMD160", "org.bouncycastle.jce.provider.JDKMessageDigest$RIPEMD160"); put("MessageDigest.RIPEMD256", "org.bouncycastle.jce.provider.JDKMessageDigest$RIPEMD256"); put("MessageDigest.RIPEMD320", "org.bouncycastle.jce.provider.JDKMessageDigest$RIPEMD320"); put("MessageDigest.Tiger", "org.bouncycastle.jce.provider.JDKMessageDigest$Tiger"); // // signature algorithms. // put("Signature.MD2WithRSAEncryption", "org.bouncycastle.jce.provider.JDKDigestSignature$MD2WithRSAEncryption"); put("Signature.MD5WithRSAEncryption", "org.bouncycastle.jce.provider.JDKDigestSignature$MD5WithRSAEncryption"); put("Signature.SHA1WithRSAEncryption", "org.bouncycastle.jce.provider.JDKDigestSignature$SHA1WithRSAEncryption"); put("Signature.RIPEMD160WithRSAEncryption", "org.bouncycastle.jce.provider.JDKDigestSignature$RIPEMD160WithRSAEncryption"); put("Signature.RIPEMD128WithRSAEncryption", "org.bouncycastle.jce.provider.JDKDigestSignature$RIPEMD128WithRSAEncryption"); put("Signature.RIPEMD256WithRSAEncryption", "org.bouncycastle.jce.provider.JDKDigestSignature$RIPEMD256WithRSAEncryption"); put("Signature.DSA", "org.bouncycastle.jce.provider.JDKDSASigner$stdDSA"); put("Signature.ECDSA", "org.bouncycastle.jce.provider.JDKDSASigner$ecDSA"); put("Signature.SHA1withRSA/ISO9796-2", "org.bouncycastle.jce.provider.JDKISOSignature$SHA1WithRSAEncryption"); put("Signature.MD5withRSA/ISO9796-2", "org.bouncycastle.jce.provider.JDKISOSignature$MD5WithRSAEncryption"); put("Signature.RIPEMD160withRSA/ISO9796-2", "org.bouncycastle.jce.provider.JDKISOSignature$RIPEMD160WithRSAEncryption"); put("Signature.SHA1withRSA/PSS", "org.bouncycastle.jce.provider.JDKPSSSigner$SHA1withRSA"); put("Signature.SHA256withRSA/PSS", "org.bouncycastle.jce.provider.JDKPSSSigner$SHA256withRSA"); put("Signature.SHA384withRSA/PSS", "org.bouncycastle.jce.provider.JDKPSSSigner$SHA384withRSA"); put("Signature.SHA512withRSA/PSS", "org.bouncycastle.jce.provider.JDKPSSSigner$SHA512withRSA"); put("Alg.Alias.Signature.MD2withRSAEncryption", "MD2WithRSAEncryption"); put("Alg.Alias.Signature.MD5withRSAEncryption", "MD5WithRSAEncryption"); put("Alg.Alias.Signature.SHA1withRSAEncryption", "SHA1WithRSAEncryption"); put("Alg.Alias.Signature.SHA256withRSAEncryption", "SHA256withRSA/PSS"); put("Alg.Alias.Signature.SHA384withRSAEncryption", "SHA384withRSA/PSS"); put("Alg.Alias.Signature.SHA512withRSAEncryption", "SHA512withRSA/PSS"); put("Alg.Alias.Signature.SHA256WithRSAEncryption", "SHA256withRSA/PSS"); put("Alg.Alias.Signature.SHA384WithRSAEncryption", "SHA384withRSA/PSS"); put("Alg.Alias.Signature.SHA512WithRSAEncryption", "SHA512withRSA/PSS"); put("Alg.Alias.Signature.SHA256WITHRSAENCRYPTION", "SHA256withRSA/PSS"); put("Alg.Alias.Signature.SHA384WITHRSAENCRYPTION", "SHA384withRSA/PSS"); put("Alg.Alias.Signature.SHA512WITHRSAENCRYPTION", "SHA512withRSA/PSS"); put("Alg.Alias.Signature.RIPEMD160withRSAEncryption", "RIPEMD160WithRSAEncryption"); put("Alg.Alias.Signature.1.2.840.113549.1.1.2", "MD2WithRSAEncryption"); put("Alg.Alias.Signature.MD2WithRSA", "MD2WithRSAEncryption"); put("Alg.Alias.Signature.MD2withRSA", "MD2WithRSAEncryption"); put("Alg.Alias.Signature.MD2/RSA", "MD2WithRSAEncryption"); put("Alg.Alias.Signature.MD5WithRSA", "MD5WithRSAEncryption"); put("Alg.Alias.Signature.MD5withRSA", "MD5WithRSAEncryption"); put("Alg.Alias.Signature.MD5/RSA", "MD5WithRSAEncryption"); put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5WithRSAEncryption"); put("Alg.Alias.Signature.SHA1WithRSA", "SHA1WithRSAEncryption"); put("Alg.Alias.Signature.SHA1withRSA", "SHA1WithRSAEncryption"); put("Alg.Alias.Signature.SHA1/RSA", "SHA1WithRSAEncryption"); put("Alg.Alias.Signature.SHA-1/RSA", "SHA1WithRSAEncryption"); put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1WithRSAEncryption"); put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.1", "SHA1WithRSAEncryption"); put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.5", "SHA1WithRSAEncryption"); put("Alg.Alias.Signature.1.2.840.113549.2.5with1.2.840.113549.1.1.1", "MD5WithRSAEncryption"); put("Alg.Alias.Signature.RIPEMD160WithRSA", "RIPEMD160WithRSAEncryption"); put("Alg.Alias.Signature.RIPEMD160withRSA", "RIPEMD160WithRSAEncryption"); put("Alg.Alias.Signature.RIPEMD128WithRSA", "RIPEMD128WithRSAEncryption"); put("Alg.Alias.Signature.RIPEMD128withRSA", "RIPEMD128WithRSAEncryption"); put("Alg.Alias.Signature.RIPEMD256WithRSA", "RIPEMD256WithRSAEncryption"); put("Alg.Alias.Signature.RIPEMD256withRSA", "RIPEMD256WithRSAEncryption"); put("Alg.Alias.Signature.RIPEMD-160/RSA", "RIPEMD160WithRSAEncryption"); put("Alg.Alias.Signature.RMD160withRSA", "RIPEMD160WithRSAEncryption"); put("Alg.Alias.Signature.RMD160/RSA", "RIPEMD160WithRSAEncryption"); put("Alg.Alias.Signature.1.3.36.3.3.1.2", "RIPEMD160WithRSAEncryption"); put("Alg.Alias.Signature.1.3.36.3.3.1.3", "RIPEMD128WithRSAEncryption"); put("Alg.Alias.Signature.1.3.36.3.3.1.4", "RIPEMD256WithRSAEncryption"); put("Alg.Alias.Signature.MD2WITHRSAENCRYPTION", "MD2WithRSAEncryption"); put("Alg.Alias.Signature.MD5WITHRSAENCRYPTION", "MD5WithRSAEncryption"); put("Alg.Alias.Signature.SHA1WITHRSAENCRYPTION", "SHA1WithRSAEncryption"); put("Alg.Alias.Signature.RIPEMD160WITHRSAENCRYPTION", "RIPEMD160WithRSAEncryption"); put("Alg.Alias.Signature.MD5WITHRSA", "MD5WithRSAEncryption"); put("Alg.Alias.Signature.SHA1WITHRSA", "SHA1WithRSAEncryption"); put("Alg.Alias.Signature.RIPEMD160WITHRSA", "RIPEMD160WithRSAEncryption"); put("Alg.Alias.Signature.RMD160WITHRSA", "RIPEMD160WithRSAEncryption"); put("Alg.Alias.Signature.RIPEMD160WITHRSA", "RIPEMD160WithRSAEncryption"); put("Alg.Alias.Signature.SHA1withECDSA", "ECDSA"); put("Alg.Alias.Signature.ECDSAwithSHA1", "ECDSA"); put("Alg.Alias.Signature.SHA1WITHECDSA", "ECDSA"); put("Alg.Alias.Signature.ECDSAWITHSHA1", "ECDSA"); put("Alg.Alias.Signature.SHA1WithECDSA", "ECDSA"); put("Alg.Alias.Signature.ECDSAWithSHA1", "ECDSA"); put("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA"); put("Alg.Alias.Signature.SHA/DSA", "DSA"); put("Alg.Alias.Signature.SHA1withDSA", "DSA"); put("Alg.Alias.Signature.SHA1WITHDSA", "DSA"); put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.1", "DSA"); put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.3", "DSA"); put("Alg.Alias.Signature.DSAwithSHA1", "DSA"); put("Alg.Alias.Signature.DSAWITHSHA1", "DSA"); put("Alg.Alias.Signature.SHA1WithDSA", "DSA"); put("Alg.Alias.Signature.DSAWithSHA1", "DSA"); put("Alg.Alias.Signature.1.2.840.10040.4.3", "DSA"); put("Alg.Alias.Signature.MD5WithRSA/ISO9796-2", "MD5withRSA/ISO9796-2"); put("Alg.Alias.Signature.SHA1WithRSA/ISO9796-2", "SHA1withRSA/ISO9796-2"); put("Alg.Alias.Signature.RIPEMD160WithRSA/ISO9796-2", "RIPEMD160withRSA/ISO9796-2"); // Certification Path API put("CertPathValidator.PKIX", "org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi" ); put("CertPathValidator.PKIX ValidationAlgorithm", "RFC2459"); put("CertPathBuilder.PKIX", "org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi" ); put("CertPathBuilder.PKIX ValidationAlgorithm", "RFC2459"); put("CertStore.Collection", "org.bouncycastle.jce.provider.CertStoreCollectionSpi" ); } } azureus-4.3.0.6/org/bouncycastle/jce/provider/CertStoreCollectionSpi.java0000644000175000017500000000524110061400650025752 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.security.InvalidAlgorithmParameterException; import java.security.cert.CRL; import java.security.cert.CRLSelector; import java.security.cert.CertSelector; import java.security.cert.CertStoreException; import java.security.cert.CertStoreParameters; import java.security.cert.CertStoreSpi; import java.security.cert.Certificate; import java.security.cert.CollectionCertStoreParameters; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class CertStoreCollectionSpi extends CertStoreSpi { private CollectionCertStoreParameters params; public CertStoreCollectionSpi(CertStoreParameters params) throws InvalidAlgorithmParameterException { super(params); if (!(params instanceof CollectionCertStoreParameters)) { throw new InvalidAlgorithmParameterException( "org.bouncycastle.jce.provider.CertStoreCollectionSpi: parameter must be a CollectionCertStoreParameters object\n" + params.toString() ); } this.params = (CollectionCertStoreParameters)params; } public Collection engineGetCertificates( CertSelector selector) throws CertStoreException { Set col = new HashSet(); Iterator iter = params.getCollection().iterator(); if (selector == null) { while (iter.hasNext()) { Object obj = iter.next(); if (obj instanceof Certificate) { col.add(obj); } } } else { while (iter.hasNext()) { Object obj = iter.next(); if ((obj instanceof Certificate) && selector.match((Certificate)obj)) { col.add(obj); } } } return col; } public Collection engineGetCRLs( CRLSelector selector) throws CertStoreException { Set col = new HashSet(); Iterator iter = params.getCollection().iterator(); if (selector == null) { while (iter.hasNext()) { Object obj = iter.next(); if (obj instanceof CRL) { col.add(obj); } } } else { while (iter.hasNext()) { Object obj = iter.next(); if ((obj instanceof CRL) && selector.match((CRL)obj)) { col.add(obj); } } } return col; } } azureus-4.3.0.6/org/bouncycastle/jce/provider/JCEECDHKeyAgreement.java0000644000175000017500000001065210416230324024703 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.KeyAgreementSpi; import javax.crypto.SecretKey; import javax.crypto.ShortBufferException; import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.crypto.BasicAgreement; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.agreement.ECDHBasicAgreement; //import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement; import org.bouncycastle.jce.interfaces.ECPrivateKey; import org.bouncycastle.jce.interfaces.ECPublicKey; /** * Diffie-Hellman key agreement using elliptic curve keys, ala IEEE P1363 * both the simple one, and the simple one with cofactors are supported. */ public class JCEECDHKeyAgreement extends KeyAgreementSpi { private BigInteger result; private CipherParameters privKey; private BasicAgreement agreement; protected JCEECDHKeyAgreement( BasicAgreement agreement) { this.agreement = agreement; } public Key doPhase( Key key, boolean lastPhase ) throws InvalidKeyException, IllegalStateException { return( engineDoPhase( key, lastPhase )); } protected Key engineDoPhase( Key key, boolean lastPhase) throws InvalidKeyException, IllegalStateException { if (privKey == null) { throw new IllegalStateException("EC Diffie-Hellman not initialised."); } if (!lastPhase) { throw new IllegalStateException("EC Diffie-Hellman can only be between two parties."); } if (!(key instanceof ECPublicKey)) { throw new InvalidKeyException("EC Key Agreement doPhase requires ECPublicKey"); } CipherParameters pubKey = ECUtil.generatePublicKeyParameter((PublicKey)key); result = agreement.calculateAgreement(pubKey); return null; } public byte[] generateSecret() throws IllegalStateException { return( engineGenerateSecret()); } protected byte[] engineGenerateSecret() throws IllegalStateException { return result.toByteArray(); } protected int engineGenerateSecret( byte[] sharedSecret, int offset) throws IllegalStateException, ShortBufferException { byte[] secret = result.toByteArray(); if (sharedSecret.length - offset < secret.length) { throw new ShortBufferException("ECKeyAgreement - buffer too short"); } System.arraycopy(secret, 0, sharedSecret, offset, secret.length); return secret.length; } protected SecretKey engineGenerateSecret( String algorithm) { return new SecretKeySpec(result.toByteArray(), algorithm); } public void init( Key key ) throws InvalidKeyException, InvalidAlgorithmParameterException { engineInit( key, null ); } protected void engineInit( Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { if (!(key instanceof ECPrivateKey)) { throw new InvalidKeyException("ECKeyAgreement requires ECPrivateKey for initialisation"); } privKey = ECUtil.generatePrivateKeyParameter((PrivateKey)key); agreement.init(privKey); } protected void engineInit( Key key, SecureRandom random) throws InvalidKeyException { if (!(key instanceof ECPrivateKey)) { throw new InvalidKeyException("ECKeyAgreement requires ECPrivateKey"); } privKey = ECUtil.generatePrivateKeyParameter((PrivateKey)key); agreement.init(privKey); } public static class DH extends JCEECDHKeyAgreement { public DH() { super(new ECDHBasicAgreement()); } } /* public static class DHC extends JCEECDHKeyAgreement { public DHC() { super(new ECDHCBasicAgreement()); } } */ } azureus-4.3.0.6/org/bouncycastle/jce/provider/JDKMessageDigest.java0000644000175000017500000001203410061400650024423 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.security.MessageDigest; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.*; public class JDKMessageDigest extends MessageDigest { Digest digest; protected JDKMessageDigest( Digest digest) { super(digest.getAlgorithmName()); this.digest = digest; } public void engineReset() { digest.reset(); } public void engineUpdate( byte input) { digest.update(input); } public void engineUpdate( byte[] input, int offset, int len) { digest.update(input, offset, len); } public byte[] engineDigest() { byte[] digestBytes = new byte[digest.getDigestSize()]; digest.doFinal(digestBytes, 0); return digestBytes; } /** * classes that extend directly off us. */ static public class SHA1 extends JDKMessageDigest implements Cloneable { public SHA1() { super(new SHA1Digest()); } public Object clone() throws CloneNotSupportedException { SHA1 d = (SHA1)super.clone(); d.digest = new SHA1Digest((SHA1Digest)digest); return d; } } static public class SHA256 extends JDKMessageDigest implements Cloneable { public SHA256() { super(new SHA256Digest()); } public Object clone() throws CloneNotSupportedException { SHA256 d = (SHA256)super.clone(); d.digest = new SHA256Digest((SHA256Digest)digest); return d; } } static public class SHA384 extends JDKMessageDigest implements Cloneable { public SHA384() { super(new SHA384Digest()); } public Object clone() throws CloneNotSupportedException { SHA384 d = (SHA384)super.clone(); d.digest = new SHA384Digest((SHA384Digest)digest); return d; } } static public class SHA512 extends JDKMessageDigest implements Cloneable { public SHA512() { super(new SHA512Digest()); } public Object clone() throws CloneNotSupportedException { SHA512 d = (SHA512)super.clone(); d.digest = new SHA512Digest((SHA512Digest)digest); return d; } } static public class MD2 extends JDKMessageDigest implements Cloneable { public MD2() { super(new MD2Digest()); } public Object clone() throws CloneNotSupportedException { MD2 d = (MD2)super.clone(); d.digest = new MD2Digest((MD2Digest)digest); return d; } } static public class MD4 extends JDKMessageDigest implements Cloneable { public MD4() { super(new MD4Digest()); } public Object clone() throws CloneNotSupportedException { MD4 d = (MD4)super.clone(); d.digest = new MD4Digest((MD4Digest)digest); return d; } } static public class MD5 extends JDKMessageDigest implements Cloneable { public MD5() { super(new MD5Digest()); } public Object clone() throws CloneNotSupportedException { MD5 d = (MD5)super.clone(); d.digest = new MD5Digest((MD5Digest)digest); return d; } } static public class RIPEMD128 extends JDKMessageDigest implements Cloneable { public RIPEMD128() { super(new RIPEMD128Digest()); } public Object clone() throws CloneNotSupportedException { RIPEMD128 d = (RIPEMD128)super.clone(); d.digest = new RIPEMD128Digest((RIPEMD128Digest)digest); return d; } } static public class RIPEMD160 extends JDKMessageDigest implements Cloneable { public RIPEMD160() { super(new RIPEMD160Digest()); } public Object clone() throws CloneNotSupportedException { RIPEMD160 d = (RIPEMD160)super.clone(); d.digest = new RIPEMD160Digest((RIPEMD160Digest)digest); return d; } } static public class RIPEMD256 extends JDKMessageDigest implements Cloneable { public RIPEMD256() { super(new RIPEMD256Digest()); } public Object clone() throws CloneNotSupportedException { RIPEMD256 d = (RIPEMD256)super.clone(); d.digest = new RIPEMD256Digest((RIPEMD256Digest)digest); return d; } } static public class RIPEMD320 extends JDKMessageDigest implements Cloneable { public RIPEMD320() { super(new RIPEMD320Digest()); } public Object clone() throws CloneNotSupportedException { RIPEMD320 d = (RIPEMD320)super.clone(); d.digest = new RIPEMD320Digest((RIPEMD320Digest)digest); return d; } } static public class Tiger extends JDKMessageDigest implements Cloneable { public Tiger() { super(new TigerDigest()); } public Object clone() throws CloneNotSupportedException { Tiger d = (Tiger)super.clone(); d.digest = new TigerDigest((TigerDigest)digest); return d; } } } azureus-4.3.0.6/org/bouncycastle/jce/provider/X509CertificateObject.java0000644000175000017500000004775710410357446025345 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Principal; import java.security.Provider; import java.security.PublicKey; import java.security.Security; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Enumeration; import java.util.HashSet; import java.util.Hashtable; import java.util.Set; import java.util.Vector; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.*; import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; import org.bouncycastle.asn1.misc.NetscapeCertType; import org.bouncycastle.asn1.misc.NetscapeRevocationURL; import org.bouncycastle.asn1.misc.VerisignCzagExtension; import org.bouncycastle.asn1.util.ASN1Dump; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.asn1.x509.X509CertificateStructure; import org.bouncycastle.asn1.x509.X509Extension; import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.jce.X509Principal; import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier; import org.bouncycastle.util.encoders.Hex; public class X509CertificateObject extends X509Certificate implements PKCS12BagAttributeCarrier { private X509CertificateStructure c; private Hashtable pkcs12Attributes = new Hashtable(); private Vector pkcs12Ordering = new Vector(); public X509CertificateObject( X509CertificateStructure c) { this.c = c; } public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException { this.checkValidity(new Date()); } public void checkValidity( Date date) throws CertificateExpiredException, CertificateNotYetValidException { if (date.after(this.getNotAfter())) { throw new CertificateExpiredException("certificate expired on " + c.getEndDate().getTime()); } if (date.before(this.getNotBefore())) { throw new CertificateNotYetValidException("certificate not valid till " + c.getStartDate().getTime()); } } public int getVersion() { return c.getVersion(); } public BigInteger getSerialNumber() { return c.getSerialNumber().getValue(); } public Principal getIssuerDN() { return new X509Principal(c.getIssuer()); } public X500Principal getIssuerX500Principal() { try { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); ASN1OutputStream aOut = new ASN1OutputStream(bOut); aOut.writeObject(c.getIssuer()); return new X500Principal(bOut.toByteArray()); } catch (IOException e) { throw new IllegalStateException("can't encode issuer DN"); } } public Principal getSubjectDN() { return new X509Principal(c.getSubject()); } public X500Principal getSubjectX500Principal() { try { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); ASN1OutputStream aOut = new ASN1OutputStream(bOut); aOut.writeObject(c.getSubject()); return new X500Principal(bOut.toByteArray()); } catch (IOException e) { throw new IllegalStateException("can't encode issuer DN"); } } public Date getNotBefore() { return c.getStartDate().getDate(); } public Date getNotAfter() { return c.getEndDate().getDate(); } public byte[] getTBSCertificate() throws CertificateEncodingException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(c.getTBSCertificate()); return bOut.toByteArray(); } catch (IOException e) { throw new CertificateEncodingException(e.toString()); } } public byte[] getSignature() { return c.getSignature().getBytes(); } /** * return a more "meaningful" representation for the signature algorithm used in * the certficate. */ public String getSigAlgName() { Provider prov = Security.getProvider("BC"); String algName = prov.getProperty("Alg.Alias.Signature." + this.getSigAlgOID()); if (algName != null) { return algName; } Provider[] provs = Security.getProviders(); // // search every provider looking for a real algorithm // for (int i = 0; i != provs.length; i++) { algName = provs[i].getProperty("Alg.Alias.Signature." + this.getSigAlgOID()); if (algName != null) { return algName; } } return this.getSigAlgOID(); } /** * return the object identifier for the signature. */ public String getSigAlgOID() { return c.getSignatureAlgorithm().getObjectId().getId(); } /** * return the signature parameters, or null if there aren't any. */ public byte[] getSigAlgParams() { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); if (c.getSignatureAlgorithm().getParameters() != null) { try { DEROutputStream dOut = new DEROutputStream(bOut); dOut.writeObject(c.getSignatureAlgorithm().getParameters()); } catch (Exception e) { throw new RuntimeException("exception getting sig parameters " + e); } return bOut.toByteArray(); } else { return null; } } public boolean[] getIssuerUniqueID() { DERBitString id = c.getTBSCertificate().getIssuerUniqueId(); if (id != null) { byte[] bytes = id.getBytes(); boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()]; for (int i = 0; i != boolId.length; i++) { boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; } return boolId; } return null; } public boolean[] getSubjectUniqueID() { DERBitString id = c.getTBSCertificate().getSubjectUniqueId(); if (id != null) { byte[] bytes = id.getBytes(); boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()]; for (int i = 0; i != boolId.length; i++) { boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; } return boolId; } return null; } public boolean[] getKeyUsage() { byte[] bytes = this.getExtensionBytes("2.5.29.15"); int length = 0; if (bytes != null) { try { DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(bytes)); DERBitString bits = (DERBitString)dIn.readObject(); bytes = bits.getBytes(); length = (bytes.length * 8) - bits.getPadBits(); } catch (Exception e) { throw new RuntimeException("error processing key usage extension"); } boolean[] keyUsage = new boolean[(length < 9) ? 9 : length]; for (int i = 0; i != length; i++) { keyUsage[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; } return keyUsage; } return null; } public int getBasicConstraints() { byte[] bytes = this.getExtensionBytes("2.5.29.19"); if (bytes != null) { try { DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(bytes)); ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); if (seq.size() == 2) { if (((DERBoolean)seq.getObjectAt(0)).isTrue()) { return ((DERInteger)seq.getObjectAt(1)).getValue().intValue(); } else { return -1; } } else if (seq.size() == 1) { if (seq.getObjectAt(0) instanceof DERBoolean) { if (((DERBoolean)seq.getObjectAt(0)).isTrue()) { return Integer.MAX_VALUE; } else { return -1; } } else { return -1; } } } catch (Exception e) { throw new RuntimeException("error processing key usage extension"); } } return -1; } public Set getCriticalExtensionOIDs() { if (this.getVersion() == 3) { HashSet set = new HashSet(); X509Extensions extensions = c.getTBSCertificate().getExtensions(); if (extensions != null) { Enumeration e = extensions.oids(); while (e.hasMoreElements()) { DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); X509Extension ext = extensions.getExtension(oid); if (ext.isCritical()) { set.add(oid.getId()); } } return set; } } return null; } private byte[] getExtensionBytes(String oid) { X509Extensions exts = c.getTBSCertificate().getExtensions(); if (exts != null) { X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid)); if (ext != null) { return ext.getValue().getOctets(); } } return null; } public byte[] getExtensionValue(String oid) { X509Extensions exts = c.getTBSCertificate().getExtensions(); if (exts != null) { X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid)); if (ext != null) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(ext.getValue()); return bOut.toByteArray(); } catch (Exception e) { throw new RuntimeException("error encoding " + e.toString()); } } } return null; } public Set getNonCriticalExtensionOIDs() { if (this.getVersion() == 3) { HashSet set = new HashSet(); X509Extensions extensions = c.getTBSCertificate().getExtensions(); if (extensions != null) { Enumeration e = extensions.oids(); while (e.hasMoreElements()) { DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); X509Extension ext = extensions.getExtension(oid); if (!ext.isCritical()) { set.add(oid.getId()); } } return set; } } return null; } public boolean hasUnsupportedCriticalExtension() { if (this.getVersion() == 3) { X509Extensions extensions = c.getTBSCertificate().getExtensions(); if (extensions != null) { Enumeration e = extensions.oids(); while (e.hasMoreElements()) { DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); if (oid.getId().equals("2.5.29.15") || oid.getId().equals("2.5.29.19")) { continue; } X509Extension ext = extensions.getExtension(oid); if (ext.isCritical()) { return true; } } } } return false; } public PublicKey getPublicKey() { return JDKKeyFactory.createPublicKeyFromPublicKeyInfo(c.getSubjectPublicKeyInfo()); } public byte[] getEncoded() throws CertificateEncodingException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(c); return bOut.toByteArray(); } catch (IOException e) { throw new CertificateEncodingException(e.toString()); } } public void setBagAttribute( DERObjectIdentifier oid, DEREncodable attribute) { pkcs12Attributes.put(oid, attribute); pkcs12Ordering.addElement(oid); } public DEREncodable getBagAttribute( DERObjectIdentifier oid) { return (DEREncodable)pkcs12Attributes.get(oid); } public Enumeration getBagAttributeKeys() { return pkcs12Ordering.elements(); } public String toString() { StringBuffer buf = new StringBuffer(); String nl = System.getProperty("line.separator"); buf.append(" [0] Version: " + this.getVersion() + nl); buf.append(" SerialNumber: " + this.getSerialNumber() + nl); buf.append(" IssuerDN: " + this.getIssuerDN() + nl); buf.append(" Start Date: " + this.getNotBefore() + nl); buf.append(" Final Date: " + this.getNotAfter() + nl); buf.append(" SubjectDN: " + this.getSubjectDN() + nl); buf.append(" Public Key: " + this.getPublicKey() + nl); buf.append(" Signature Algorithm: " + this.getSigAlgName() + nl); byte[] sig = this.getSignature(); buf.append(" Signature: " + new String(Hex.encode(sig, 0, 20)) + nl); for (int i = 20; i < sig.length; i += 20) { if (i < sig.length - 20) { buf.append(" " + new String(Hex.encode(sig, i, 20)) + nl); } else { buf.append(" " + new String(Hex.encode(sig, i, sig.length - i)) + nl); } } X509Extensions extensions = c.getTBSCertificate().getExtensions(); if (extensions != null) { Enumeration e = extensions.oids(); if (e.hasMoreElements()) { buf.append(" Extensions: \n"); } while (e.hasMoreElements()) { DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); X509Extension ext = extensions.getExtension(oid); if (ext.getValue() != null) { byte[] octs = ext.getValue().getOctets(); ByteArrayInputStream bIn = new ByteArrayInputStream(octs); DERInputStream dIn = new DERInputStream(bIn); buf.append(" critical(" + ext.isCritical() + ") "); try { if (oid.equals(X509Extensions.BasicConstraints)) { buf.append(new BasicConstraints((ASN1Sequence)dIn.readObject()) + nl); } else if (oid.equals(X509Extensions.KeyUsage)) { buf.append(new KeyUsage((DERBitString)dIn.readObject()) + nl); } else if (oid.equals(MiscObjectIdentifiers.netscapeCertType)) { buf.append(new NetscapeCertType((DERBitString)dIn.readObject()) + nl); } else if (oid.equals(MiscObjectIdentifiers.netscapeRevocationURL)) { buf.append(new NetscapeRevocationURL((DERIA5String)dIn.readObject()) + nl); } else if (oid.equals(MiscObjectIdentifiers.verisignCzagExtension)) { buf.append(new VerisignCzagExtension((DERIA5String)dIn.readObject()) + nl); } else { buf.append(oid.getId()); buf.append(" value = " + ASN1Dump.dumpAsString(dIn.readObject()) + nl); //buf.append(" value = " + "*****" + nl); } } catch (Exception ex) { buf.append(oid.getId()); // buf.append(" value = " + new String(Hex.encode(ext.getValue().getOctets())) + nl); buf.append(" value = " + "*****" + nl); } } else { buf.append(nl); } } } return buf.toString(); } public final void verify( PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { Signature signature = null; if (!c.getSignatureAlgorithm().equals(c.getTBSCertificate().getSignature())) { throw new CertificateException("signature algorithm in TBS cert not same as outer cert"); } try { signature = Signature.getInstance(c.getSignatureAlgorithm().getObjectId().getId(), "BC"); } catch (Exception e) { signature = Signature.getInstance(c.getSignatureAlgorithm().getObjectId().getId()); } signature.initVerify(key); signature.update(this.getTBSCertificate()); if (!signature.verify(this.getSignature())) { throw new InvalidKeyException("Public key presented not for certificate signature"); } } public final void verify( PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { Signature signature = Signature.getInstance(c.getSignatureAlgorithm().getObjectId().getId(), sigProvider); signature.initVerify(key); signature.update(this.getTBSCertificate()); if (!signature.verify(this.getSignature())) { throw new InvalidKeyException("Public key presented not for certificate signature"); } } } azureus-4.3.0.6/org/bouncycastle/jce/provider/ECUtil.java0000644000175000017500000000343410061400650022477 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.security.InvalidKeyException; import java.security.PrivateKey; import java.security.PublicKey; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.jce.interfaces.ECPrivateKey; import org.bouncycastle.jce.interfaces.ECPublicKey; import org.bouncycastle.jce.spec.ECParameterSpec; /** * utility class for converting jce/jca ECDSA, ECDH, and ECDHC * objects into their org.bouncycastle.crypto counterparts. */ public class ECUtil { static public AsymmetricKeyParameter generatePublicKeyParameter( PublicKey key) throws InvalidKeyException { if (key instanceof ECPublicKey) { ECPublicKey k = (ECPublicKey)key; ECParameterSpec s = k.getParams(); return new ECPublicKeyParameters( k.getQ(), new ECDomainParameters(s.getCurve(), s.getG(), s.getN())); } throw new InvalidKeyException("can't identify EC public key."); } static public AsymmetricKeyParameter generatePrivateKeyParameter( PrivateKey key) throws InvalidKeyException { if (key instanceof ECPrivateKey) { ECPrivateKey k = (ECPrivateKey)key; ECParameterSpec s = k.getParams(); return new ECPrivateKeyParameters( k.getD(), new ECDomainParameters(s.getCurve(), s.getG(), s.getN())); } throw new InvalidKeyException("can't identify EC private key."); } } azureus-4.3.0.6/org/bouncycastle/jce/provider/JDKKeyFactory.java0000644000175000017500000002372510410357446024004 0ustar adrianadrian/* * Created on 08-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.bouncycastle.jce.provider; /** * @author parg * */ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyFactorySpi; import java.security.PrivateKey; import java.security.PublicKey; import java.security.interfaces.DSAPrivateKey; import java.security.interfaces.DSAPublicKey; import java.security.interfaces.RSAPrivateCrtKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.RSAPrivateCrtKeySpec; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.interfaces.DHPrivateKey; import javax.crypto.interfaces.DHPublicKey; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERInputStream; import org.bouncycastle.asn1.x509.*; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.jce.interfaces.ElGamalPrivateKey; import org.bouncycastle.jce.interfaces.ElGamalPublicKey; import org.bouncycastle.jce.spec.ECPrivateKeySpec; import org.bouncycastle.jce.spec.ECPublicKeySpec; public abstract class JDKKeyFactory extends KeyFactorySpi { protected KeySpec engineGetKeySpec( Key key, Class spec) throws InvalidKeySpecException { if (spec.isAssignableFrom(PKCS8EncodedKeySpec.class) && key.getFormat().equals("PKCS#8")) { return new PKCS8EncodedKeySpec(key.getEncoded()); } else if (spec.isAssignableFrom(X509EncodedKeySpec.class) && key.getFormat().equals("X.509")) { return new X509EncodedKeySpec(key.getEncoded()); } else if (spec.isAssignableFrom(RSAPublicKeySpec.class) && key instanceof RSAPublicKey) { RSAPublicKey k = (RSAPublicKey)key; return new RSAPublicKeySpec(k.getModulus(), k.getPublicExponent()); } else if (spec.isAssignableFrom(RSAPrivateKeySpec.class) && key instanceof RSAPrivateKey) { RSAPrivateKey k = (RSAPrivateKey)key; return new RSAPrivateKeySpec(k.getModulus(), k.getPrivateExponent()); } else if (spec.isAssignableFrom(RSAPrivateCrtKeySpec.class) && key instanceof RSAPrivateCrtKey) { RSAPrivateCrtKey k = (RSAPrivateCrtKey)key; return new RSAPrivateCrtKeySpec( k.getModulus(), k.getPublicExponent(), k.getPrivateExponent(), k.getPrimeP(), k.getPrimeQ(), k.getPrimeExponentP(), k.getPrimeExponentQ(), k.getCrtCoefficient()); } throw new RuntimeException("not implemented yet " + key + " " + spec); } protected Key engineTranslateKey( Key key) throws InvalidKeyException { if (key instanceof RSAPublicKey) { return new JCERSAPublicKey((RSAPublicKey)key); } else if (key instanceof RSAPrivateCrtKey) { //return new JCERSAPrivateCrtKey((RSAPrivateCrtKey)key); } else if (key instanceof RSAPrivateKey) { //return new JCERSAPrivateKey((RSAPrivateKey)key); } else if (key instanceof DHPublicKey) { //return new JCEDHPublicKey((DHPublicKey)key); } else if (key instanceof DHPrivateKey) { //return new JCEDHPrivateKey((DHPrivateKey)key); } else if (key instanceof DSAPublicKey) { //return new JDKDSAPublicKey((DSAPublicKey)key); } else if (key instanceof DSAPrivateKey) { //return new JDKDSAPrivateKey((DSAPrivateKey)key); } else if (key instanceof ElGamalPublicKey) { //return new JCEElGamalPublicKey((ElGamalPublicKey)key); } else if (key instanceof ElGamalPrivateKey) { //return new JCEElGamalPrivateKey((ElGamalPrivateKey)key); } throw new InvalidKeyException("key type unknown"); } static PublicKey createPublicKeyFromDERStream( InputStream in) throws IOException { return createPublicKeyFromPublicKeyInfo( new SubjectPublicKeyInfo((ASN1Sequence)(new DERInputStream(in).readObject()))); } static PublicKey createPublicKeyFromPublicKeyInfo( SubjectPublicKeyInfo info) { AlgorithmIdentifier algId = info.getAlgorithmId(); if (algId.getObjectId().equals(PKCSObjectIdentifiers.rsaEncryption) || algId.getObjectId().equals(X509ObjectIdentifiers.id_ea_rsa)) { return new JCERSAPublicKey(info); } else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey)) { return new JCEECPublicKey(info); } else { throw new RuntimeException("algorithm identifier in key not recognised"); } } static PrivateKey createPrivateKeyFromDERStream( InputStream in) throws IOException { return createPrivateKeyFromPrivateKeyInfo( new PrivateKeyInfo((ASN1Sequence)(new DERInputStream(in).readObject()))); } /** * create a private key from the given public key info object. */ static PrivateKey createPrivateKeyFromPrivateKeyInfo( PrivateKeyInfo info) { AlgorithmIdentifier algId = info.getAlgorithmId(); /* if (algId.getObjectId().equals(PKCSObjectIdentifiers.rsaEncryption)) { return new JCERSAPrivateCrtKey(info); } else if (algId.getObjectId().equals(PKCSObjectIdentifiers.dhKeyAgreement)) { return new JCEDHPrivateKey(info); } else if (algId.getObjectId().equals(OIWObjectIdentifiers.elGamalAlgorithm)) { return new JCEElGamalPrivateKey(info); } else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_dsa)) { return new JDKDSAPrivateKey(info); } else */ if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey)) { return new JCEECPrivateKey(info); } else { throw new RuntimeException("algorithm identifier in key not recognised"); } } public static class EC extends JDKKeyFactory { String algorithm; public EC() { this("EC"); } public EC( String algorithm) { this.algorithm = algorithm; } protected PrivateKey engineGeneratePrivate( KeySpec keySpec) throws InvalidKeySpecException { if (keySpec instanceof PKCS8EncodedKeySpec) { try { return JDKKeyFactory.createPrivateKeyFromDERStream( new ByteArrayInputStream(((PKCS8EncodedKeySpec)keySpec).getEncoded())); } catch (Exception e) { throw new InvalidKeySpecException(e.toString()); } } else if (keySpec instanceof ECPrivateKeySpec) { return new JCEECPrivateKey(algorithm, (ECPrivateKeySpec)keySpec); } throw new InvalidKeySpecException("Unknown KeySpec type."); } protected PublicKey engineGeneratePublic( KeySpec keySpec) throws InvalidKeySpecException { if (keySpec instanceof X509EncodedKeySpec) { try { return JDKKeyFactory.createPublicKeyFromDERStream( new ByteArrayInputStream(((X509EncodedKeySpec)keySpec).getEncoded())); } catch (Exception e) { throw new InvalidKeySpecException(e.toString()); } } else if (keySpec instanceof ECPublicKeySpec) { return new JCEECPublicKey(algorithm, (ECPublicKeySpec)keySpec); } throw new InvalidKeySpecException("Unknown KeySpec type."); } } public static class ECDSA extends EC { public ECDSA() { super("ECDSA"); } } } azureus-4.3.0.6/org/bouncycastle/jce/provider/JCEECPublicKey.java0000644000175000017500000002042610407566336024015 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERInputStream; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X962NamedCurves; import org.bouncycastle.asn1.x9.X962Parameters; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.asn1.x9.X9ECPoint; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.jce.interfaces.ECPublicKey; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.jce.spec.ECParameterSpec; import org.bouncycastle.jce.spec.ECPublicKeySpec; import org.bouncycastle.math.ec.ECPoint; public class JCEECPublicKey implements ECPublicKey { private String algorithm = "EC"; private ECPoint q; private ECParameterSpec ecSpec; JCEECPublicKey( String algorithm, ECPublicKeySpec spec) { this.algorithm = algorithm; this.q = spec.getQ(); this.ecSpec = spec.getParams(); } JCEECPublicKey( String algorithm, ECPublicKeyParameters params, ECParameterSpec spec) { ECDomainParameters dp = params.getParameters(); this.algorithm = algorithm; this.q = params.getQ(); if (spec == null) { this.ecSpec = new ECParameterSpec( dp.getCurve(), dp.getG(), dp.getN(), dp.getH(), dp.getSeed()); } else { this.ecSpec = spec; } } JCEECPublicKey( String algorithm, ECPublicKey key) { this.q = key.getQ(); this.algorithm = key.getAlgorithm(); this.ecSpec = key.getParams(); } JCEECPublicKey( String algorithm, ECPoint q, ECParameterSpec ecSpec) { this.algorithm = algorithm; this.q = q; this.ecSpec = ecSpec; } JCEECPublicKey( SubjectPublicKeyInfo info) { X962Parameters params = new X962Parameters((DERObject)info.getAlgorithmId().getParameters()); if (params.isNamedCurve()) { DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); X9ECParameters ecP = X962NamedCurves.getByOID(oid); ecSpec = new ECNamedCurveParameterSpec( X962NamedCurves.getName(oid), ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed()); } else { X9ECParameters ecP = new X9ECParameters( (ASN1Sequence)params.getParameters()); ecSpec = new ECParameterSpec( ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed()); } DERBitString bits = info.getPublicKeyData(); byte[] data = bits.getBytes(); ASN1OctetString key = new DEROctetString(data); // // extra octet string - one of our old certs... // if (data[0] == 0x04 && data[1] == data.length - 2 && (data[2] == 0x02 || data[2] == 0x03)) { try { ByteArrayInputStream bIn = new ByteArrayInputStream(data); DERInputStream dIn = new DERInputStream(bIn); key = (ASN1OctetString)dIn.readObject(); } catch (IOException ex) { throw new IllegalArgumentException("error recovering public key"); } } X9ECPoint derQ = new X9ECPoint(ecSpec.getCurve(), key); this.q = derQ.getPoint(); } public String getAlgorithm() { return algorithm; } public String getFormat() { return "X.509"; } public byte[] getEncoded() { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); X962Parameters params = null; if (ecSpec instanceof ECNamedCurveParameterSpec) { params = new X962Parameters(X962NamedCurves.getOID(((ECNamedCurveParameterSpec)ecSpec).getName())); } else { X9ECParameters ecP = new X9ECParameters( ecSpec.getCurve(), ecSpec.getG(), ecSpec.getN(), ecSpec.getH(), ecSpec.getSeed()); params = new X962Parameters(ecP); } ASN1OctetString p = (ASN1OctetString)(new X9ECPoint(this.getQ()).getDERObject()); SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.getDERObject()), p.getOctets()); try { dOut.writeObject(info); dOut.close(); } catch (IOException e) { throw new RuntimeException("Error encoding EC public key"); } return bOut.toByteArray(); } public ECParameterSpec getParams() { return ecSpec; } public ECPoint getQ() { return q; } public String toString() { StringBuffer buf = new StringBuffer(); String nl = System.getProperty("line.separator"); buf.append("EC Public Key" + nl); buf.append(" X: " + this.getQ().getX().toBigInteger().toString(16) + nl); buf.append(" Y: " + this.getQ().getY().toBigInteger().toString(16) + nl); return buf.toString(); } /* private void readObject( ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); boolean named = in.readBoolean(); if (named) { ecSpec = new ECNamedCurveParameterSpec( in.readUTF(), (ECCurve)in.readObject(), (ECPoint)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject(), (byte[])in.readObject()); } else { ecSpec = new ECParameterSpec( (ECCurve)in.readObject(), (ECPoint)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject(), (byte[])in.readObject()); } } private void writeObject( ObjectOutputStream out) throws IOException { out.defaultWriteObject(); if (this.ecSpec instanceof ECNamedCurveParameterSpec) { ECNamedCurveParameterSpec namedSpec = (ECNamedCurveParameterSpec)ecSpec; out.writeBoolean(true); out.writeUTF(namedSpec.getName()); } else { out.writeBoolean(false); } out.writeObject(ecSpec.getCurve()); out.writeObject(ecSpec.getG()); out.writeObject(ecSpec.getN()); out.writeObject(ecSpec.getH()); out.writeObject(ecSpec.getSeed()); } */ } azureus-4.3.0.6/org/bouncycastle/jce/provider/JCEIESCipher.java0000644000175000017500000002375010407574662023475 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.io.ByteArrayOutputStream; import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.interfaces.DHPrivateKey; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.InvalidCipherTextException; //import org.bouncycastle.crypto.agreement.DHBasicAgreement; import org.bouncycastle.crypto.agreement.ECDHBasicAgreement; import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.crypto.engines.IESEngine; import org.bouncycastle.crypto.generators.KDF2BytesGenerator; import org.bouncycastle.crypto.macs.HMac; import org.bouncycastle.crypto.params.IESParameters; import org.bouncycastle.jce.interfaces.ECPrivateKey; import org.bouncycastle.jce.interfaces.IESKey; import org.bouncycastle.jce.spec.IESParameterSpec; public class JCEIESCipher //extends WrapCipherSpi { private IESEngine cipher; private int state = -1; private ByteArrayOutputStream buffer = new ByteArrayOutputStream(); private AlgorithmParameters engineParam = null; private IESParameterSpec engineParams = null; // // specs we can handle. // private Class[] availableSpecs = { IESParameterSpec.class }; public JCEIESCipher( IESEngine engine) { cipher = engine; } protected int engineGetBlockSize() { return 0; } protected byte[] engineGetIV() { return null; } protected int engineGetKeySize( Key key) { IESKey ieKey = (IESKey)key; if (ieKey.getPrivate() instanceof DHPrivateKey) { DHPrivateKey k = (DHPrivateKey)ieKey.getPrivate(); return k.getX().bitLength(); } else if (ieKey.getPrivate() instanceof ECPrivateKey) { ECPrivateKey k = (ECPrivateKey)ieKey.getPrivate(); return k.getD().bitLength(); } throw new IllegalArgumentException("not an IE key!"); } protected int engineGetOutputSize( int inputLen) { if (state == Cipher.ENCRYPT_MODE || state == Cipher.WRAP_MODE) { return buffer.size() + inputLen + 20; /* SHA1 MAC size */ } else if (state == Cipher.DECRYPT_MODE || state == Cipher.UNWRAP_MODE) { return buffer.size() + inputLen - 20; } else { throw new IllegalStateException("cipher not initialised"); } } protected AlgorithmParameters engineGetParameters() { if (engineParam == null) { if (engineParams != null) { String name = "IES"; try { engineParam = AlgorithmParameters.getInstance(name, "BC"); engineParam.init(engineParams); } catch (Exception e) { throw new RuntimeException(e.toString()); } } } return engineParam; } protected void engineSetMode( String mode) { throw new IllegalArgumentException("can't support mode " + mode); } protected void engineSetPadding( String padding) throws NoSuchPaddingException { throw new NoSuchPaddingException(padding + " unavailable with RSA."); } public void engineInit( int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { if (!(key instanceof IESKey)) { throw new InvalidKeyException("must be passed IE key"); } if (params == null && (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE)) { // // if nothing is specified we set up for a 128 bit mac, with // 128 bit derivation vectors. // byte[] d = new byte[16]; byte[] e = new byte[16]; if (random == null) { random = new SecureRandom(); } random.nextBytes(d); random.nextBytes(e); params = new IESParameterSpec(d, e, 128); } else if (!(params instanceof IESParameterSpec)) { throw new InvalidAlgorithmParameterException("must be passed IES parameters"); } IESKey ieKey = (IESKey)key; CipherParameters pubKey; CipherParameters privKey; if (ieKey.getPublic() instanceof JCEECPublicKey) { pubKey = ECUtil.generatePublicKeyParameter(ieKey.getPublic()); privKey = ECUtil.generatePrivateKeyParameter(ieKey.getPrivate()); } else { pubKey = DHUtil.generatePublicKeyParameter(ieKey.getPublic()); privKey = DHUtil.generatePrivateKeyParameter(ieKey.getPrivate()); } this.engineParams = (IESParameterSpec)params; IESParameters p = new IESParameters(engineParams.getDerivationV(), engineParams.getEncodingV(), engineParams.getMacKeySize()); this.state = opmode; buffer.reset(); switch (opmode) { case Cipher.ENCRYPT_MODE: case Cipher.WRAP_MODE: cipher.init(true, privKey, pubKey, p); break; case Cipher.DECRYPT_MODE: case Cipher.UNWRAP_MODE: cipher.init(false, privKey, pubKey, p); break; default: System.out.println("eeek!"); } } protected void engineInit( int opmode, Key key, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { AlgorithmParameterSpec paramSpec = null; if (params != null) { for (int i = 0; i != availableSpecs.length; i++) { try { paramSpec = params.getParameterSpec(availableSpecs[i]); break; } catch (Exception e) { continue; } } if (paramSpec == null) { throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString()); } } engineParam = params; engineInit(opmode, key, paramSpec, random); } protected void engineInit( int opmode, Key key, SecureRandom random) throws InvalidKeyException { if (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE) { try { engineInit(opmode, key, (AlgorithmParameterSpec)null, random); return; } catch (InvalidAlgorithmParameterException e) { // fall through... } } throw new IllegalArgumentException("can't handle null parameter spec in IES"); } public byte[] engineUpdate( byte[] input, int inputOffset, int inputLen) { buffer.write(input, inputOffset, inputLen); return null; } public int engineUpdate( byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) { buffer.write(input, inputOffset, inputLen); return 0; } public byte[] engineDoFinal( byte[] input, int inputOffset, int inputLen) throws IllegalBlockSizeException, BadPaddingException { if (inputLen != 0) { buffer.write(input, inputOffset, inputLen); } try { byte[] buf = buffer.toByteArray(); buffer.reset(); return cipher.processBlock(buf, 0, buf.length); } catch (InvalidCipherTextException e) { throw new BadPaddingException(e.getMessage()); } } public int engineDoFinal( byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws IllegalBlockSizeException, BadPaddingException { if (inputLen != 0) { buffer.write(input, inputOffset, inputLen); } try { byte[] buf = buffer.toByteArray(); buffer.reset(); buf = cipher.processBlock(buf, 0, buf.length); System.arraycopy(buf, 0, output, outputOffset, buf.length); return buf.length; } catch (InvalidCipherTextException e) { throw new BadPaddingException(e.getMessage()); } } /** * classes that inherit from us. */ static public class ECIES extends JCEIESCipher { public ECIES() { super(new IESEngine( new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest()), new HMac(new SHA1Digest()))); } } /* static public class IES extends JCEIESCipher { public IES() { super(new IESEngine( new DHBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest()), new HMac(new SHA1Digest()))); } } */ } azureus-4.3.0.6/org/bouncycastle/jce/provider/PKIXCertPath.java0000644000175000017500000001507110127351062023565 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.security.NoSuchProviderException; import java.security.cert.CertPath; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERInputStream; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.DERSequence; /** * CertPath implementation for X.509 certificates. *
      * TODO: add PKCS #7 encoding support **/ public class PKIXCertPath extends CertPath { static final List certPathEncodings; static { List encodings = new ArrayList(); encodings.add("PkiPath"); certPathEncodings = Collections.unmodifiableList( encodings ); } private List certificates; /** * Creates a CertPath of the specified type. * This constructor is protected because most users should use * a CertificateFactory to create CertPaths. * @param type the standard name of the type of Certificatesin this path **/ PKIXCertPath( List certificates ) { super("X.509"); this.certificates = new ArrayList( certificates ); } /** * Creates a CertPath of the specified type. * This constructor is protected because most users should use * a CertificateFactory to create CertPaths. * * TODO: implement PKCS7 decoding * * @param type the standard name of the type of Certificatesin this path **/ PKIXCertPath( InputStream inStream, String encoding) throws CertificateException { super("X.509"); try { if ( encoding.equals( "PkiPath" ) ) { DERInputStream derInStream = new DERInputStream(inStream); DERObject derObject = derInStream.readObject(); if ( derObject == null || ! ( derObject instanceof ASN1Sequence ) ) { throw new CertificateException("input stream does not contain a ASN1 SEQUENCE while reading PkiPath encoded data to load CertPath" ); } Enumeration enumx = ((ASN1Sequence)derObject).getObjects(); InputStream certInStream; ByteArrayOutputStream outStream; DEROutputStream derOutStream; certificates = new ArrayList(); CertificateFactory certFactory= CertificateFactory.getInstance( "X.509", "BC" ); while ( enumx.hasMoreElements() ) { outStream = new ByteArrayOutputStream(); derOutStream = new DEROutputStream(outStream); derOutStream.writeObject(enumx.nextElement()); derOutStream.close(); certInStream = new ByteArrayInputStream(outStream.toByteArray()); certificates.add(0,certFactory.generateCertificate(certInStream)); } } else { throw new CertificateException( "unsupported encoding" ); } } catch ( IOException ex ) { throw new CertificateException( "IOException throw while decoding CertPath:\n" + ex.toString() ); } catch ( NoSuchProviderException ex ) { throw new CertificateException( "BouncyCastle provider not found while trying to get a CertificateFactory:\n" + ex.toString() ); } } /** * Returns an iteration of the encodings supported by this * certification path, with the default encoding * first. Attempts to modify the returned Iterator via its * remove method result in an UnsupportedOperationException. * * @return an Iterator over the names of the supported encodings (as Strings) **/ public Iterator getEncodings() { return certPathEncodings.iterator(); } /** * Returns the encoded form of this certification path, using * the default encoding. * * @return the encoded bytes * @exception CertificateEncodingException if an encoding error occurs **/ public byte[] getEncoded() throws CertificateEncodingException { Iterator iter = getEncodings(); if ( iter.hasNext() ) { Object enc = iter.next(); if ( enc instanceof String ) { return getEncoded((String)enc); } } return null; } /** * Returns the encoded form of this certification path, using * the specified encoding. * * TODO: implement PKCS7 decoding * * @param encoding the name of the encoding to use * @return the encoded bytes * @exception CertificateEncodingException if an encoding error * occurs or the encoding requested is not supported * **/ public byte[] getEncoded(String encoding) throws CertificateEncodingException { DERObject encoded = null; if ( encoding.equals("PkiPath") ) { ASN1EncodableVector v = new ASN1EncodableVector(); // TODO check ListIterator implementation for JDK 1.1 ListIterator iter = certificates.listIterator(certificates.size()); while ( iter.hasPrevious() ) { v.add(getEncodedX509Certificate((X509Certificate)iter.previous())); } encoded = new DERSequence(v); } else throw new CertificateEncodingException( "unsupported encoding" ); if ( encoded == null ) return null; ByteArrayOutputStream outStream = new ByteArrayOutputStream(); DEROutputStream derOutStream = new DEROutputStream(outStream); try { derOutStream.writeObject( encoded ); derOutStream.close(); } catch ( IOException ex ) { throw new CertificateEncodingException( "IOExeption thrown: " + ex.toString() ); } return outStream.toByteArray(); } /** * Returns the list of certificates in this certification * path. The List returned must be immutable and thread-safe. * * TODO: return immutable List * * @return an immutable List of Certificates (may be empty, but not null) **/ public List getCertificates() { return new ArrayList( certificates ); } /** * Return a DERObject containing the encoded certificate. * * @param cert the X509Certificate object to be encoded * * @return the DERObject **/ private DERObject getEncodedX509Certificate( X509Certificate cert ) throws CertificateEncodingException { try { ByteArrayInputStream inStream = new ByteArrayInputStream( cert.getEncoded() ); DERInputStream derInStream = new DERInputStream( inStream ); return derInStream.readObject(); } catch ( IOException ex ) { throw new CertificateEncodingException( "IOException caught while encoding certificate\n" + ex.toString() ); } } } azureus-4.3.0.6/org/bouncycastle/jce/provider/RSAUtil.java0000644000175000017500000000243110061400650022631 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.security.interfaces.RSAPrivateCrtKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; /** * utility class for converting java.security RSA objects into their * org.bouncycastle.crypto counterparts. */ public class RSAUtil { static public RSAKeyParameters generatePublicKeyParameter( RSAPublicKey key) { return new RSAKeyParameters(false, key.getModulus(), key.getPublicExponent()); } static public RSAKeyParameters generatePrivateKeyParameter( RSAPrivateKey key) { if (key instanceof RSAPrivateCrtKey) { RSAPrivateCrtKey k = (RSAPrivateCrtKey)key; return new RSAPrivateCrtKeyParameters(k.getModulus(), k.getPublicExponent(), k.getPrivateExponent(), k.getPrimeP(), k.getPrimeQ(), k.getPrimeExponentP(), k.getPrimeExponentQ(), k.getCrtCoefficient()); } else { RSAPrivateKey k = key; return new RSAKeyParameters(true, k.getModulus(), k.getPrivateExponent()); } } } azureus-4.3.0.6/org/bouncycastle/jce/provider/DSAUtil.java0000644000175000017500000000317510061400650022621 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.security.InvalidKeyException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.interfaces.DSAPrivateKey; import java.security.interfaces.DSAPublicKey; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.DSAParameters; import org.bouncycastle.crypto.params.DSAPrivateKeyParameters; import org.bouncycastle.crypto.params.DSAPublicKeyParameters; /** * utility class for converting jce/jca DSA objects * objects into their org.bouncycastle.crypto counterparts. */ public class DSAUtil { static public AsymmetricKeyParameter generatePublicKeyParameter( PublicKey key) throws InvalidKeyException { if (key instanceof DSAPublicKey) { DSAPublicKey k = (DSAPublicKey)key; return new DSAPublicKeyParameters(k.getY(), new DSAParameters(k.getParams().getP(), k.getParams().getQ(), k.getParams().getG())); } throw new InvalidKeyException("can't identify DSA public key: " + key.getClass().getName()); } static public AsymmetricKeyParameter generatePrivateKeyParameter( PrivateKey key) throws InvalidKeyException { if (key instanceof DSAPrivateKey) { DSAPrivateKey k = (DSAPrivateKey)key; return new DSAPrivateKeyParameters(k.getX(), new DSAParameters(k.getParams().getP(), k.getParams().getQ(), k.getParams().getG())); } throw new InvalidKeyException("can't identify DSA private key."); } } azureus-4.3.0.6/org/bouncycastle/jce/provider/X509CRLEntryObject.java0000644000175000017500000000656310061400650024537 0ustar adrianadrian package org.bouncycastle.jce.provider; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.cert.CRLException; import java.security.cert.X509CRLEntry; import java.util.Date; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.x509.TBSCertList; import org.bouncycastle.asn1.x509.X509Extension; import org.bouncycastle.asn1.x509.X509Extensions; /** * The following extensions are listed in RFC 2459 as relevant to CRL Entries * * ReasonCode * Hode Instruction Code * Invalidity Date * Certificate Issuer (critical) */ public class X509CRLEntryObject extends X509CRLEntry { private TBSCertList.CRLEntry c; public X509CRLEntryObject( TBSCertList.CRLEntry c) { this.c = c; } /** * Will return true if any extensions are present and marked * as critical as we currently dont handle any extensions! */ public boolean hasUnsupportedCriticalExtension() { Set extns = getCriticalExtensionOIDs(); if ( extns != null && !extns.isEmpty() ) { return true; } return false; } private Set getExtensionOIDs(boolean critical) { X509Extensions extensions = c.getExtensions(); if ( extensions != null ) { HashSet set = new HashSet(); Enumeration e = extensions.oids(); while (e.hasMoreElements()) { DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); X509Extension ext = extensions.getExtension(oid); if (critical == ext.isCritical()) { set.add(oid.getId()); } } return set; } return null; } public Set getCriticalExtensionOIDs() { return getExtensionOIDs(true); } public Set getNonCriticalExtensionOIDs() { return getExtensionOIDs(false); } public byte[] getExtensionValue(String oid) { X509Extensions exts = c.getExtensions(); if (exts != null) { X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid)); if (ext != null) { return ext.getValue().getOctets(); } } return null; } public byte[] getEncoded() throws CRLException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(c); return bOut.toByteArray(); } catch (IOException e) { throw new CRLException(e.toString()); } } public BigInteger getSerialNumber() { return c.getUserCertificate().getValue(); } public Date getRevocationDate() { return c.getRevocationDate().getDate(); } public boolean hasExtensions() { return c.getExtensions() != null; } public String toString() { StringBuffer buf = new StringBuffer(); String nl = System.getProperty("line.separator"); buf.append(" userCertificate: " + this.getSerialNumber() + nl); buf.append(" revocationDate: " + this.getRevocationDate() + nl); X509Extensions extensions = c.getExtensions(); if ( extensions != null ) { Enumeration e = extensions.oids(); if ( e.hasMoreElements() ) { buf.append(" crlEntryExtensions:" + nl); while ( e.hasMoreElements() ) { DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); X509Extension ext = extensions.getExtension(oid); buf.append(ext); } } } return buf.toString(); } } azureus-4.3.0.6/org/bouncycastle/jce/provider/JDKKeyPairGenerator.java0000644000175000017500000003053110551530114025117 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.security.InvalidAlgorithmParameterException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.util.Hashtable; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.bouncycastle.crypto.params.*; import org.bouncycastle.jce.ECNamedCurveTable; import org.bouncycastle.jce.spec.ECParameterSpec; public abstract class JDKKeyPairGenerator extends KeyPairGenerator { public JDKKeyPairGenerator( String algorithmName) { super(algorithmName); } public abstract void initialize(int strength, SecureRandom random); public abstract KeyPair generateKeyPair(); /* PARG removed public static class RSA extends JDKKeyPairGenerator { final static BigInteger defaultPublicExponent = BigInteger.valueOf(0x10001); final static int defaultTests = 8; RSAKeyGenerationParameters param; RSAKeyPairGenerator engine; public RSA() { super("RSA"); engine = new RSAKeyPairGenerator(); param = new RSAKeyGenerationParameters(defaultPublicExponent, new SecureRandom(), 2048, defaultTests); engine.init(param); } public void initialize( int strength, SecureRandom random) { param = new RSAKeyGenerationParameters(defaultPublicExponent, random, strength, defaultTests); engine.init(param); } public void initialize( AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { if (!(params instanceof RSAKeyGenParameterSpec)) { throw new InvalidAlgorithmParameterException("parameter object not a RSAKeyGenParameterSpec"); } RSAKeyGenParameterSpec rsaParams = (RSAKeyGenParameterSpec)params; param = new RSAKeyGenerationParameters( rsaParams.getPublicExponent(), random, rsaParams.getKeysize(), defaultTests); engine.init(param); } public KeyPair generateKeyPair() { AsymmetricCipherKeyPair pair = engine.generateKeyPair(); RSAKeyParameters pub = (RSAKeyParameters)pair.getPublic(); RSAPrivateCrtKeyParameters priv = (RSAPrivateCrtKeyParameters)pair.getPrivate(); return new KeyPair(new JCERSAPublicKey(pub), new JCERSAPrivateCrtKey(priv)); } } public static class DH extends JDKKeyPairGenerator { DHKeyGenerationParameters param; DHBasicKeyPairGenerator engine = new DHBasicKeyPairGenerator(); int strength = 1024; int certainty = 20; SecureRandom random = new SecureRandom(); boolean initialised = false; public DH() { super("DH"); } public void initialize( int strength, SecureRandom random) { this.strength = strength; this.random = random; } public void initialize( AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { if (!(params instanceof DHParameterSpec)) { throw new InvalidAlgorithmParameterException("parameter object not a DHParameterSpec"); } DHParameterSpec dhParams = (DHParameterSpec)params; param = new DHKeyGenerationParameters(random, new DHParameters(dhParams.getP(), dhParams.getG())); engine.init(param); initialised = true; } public KeyPair generateKeyPair() { if (!initialised) { DHParametersGenerator pGen = new DHParametersGenerator(); pGen.init(strength, certainty, random); param = new DHKeyGenerationParameters(random, pGen.generateParameters()); engine.init(param); initialised = true; } AsymmetricCipherKeyPair pair = engine.generateKeyPair(); DHPublicKeyParameters pub = (DHPublicKeyParameters)pair.getPublic(); DHPrivateKeyParameters priv = (DHPrivateKeyParameters)pair.getPrivate(); return new KeyPair(new JCEDHPublicKey(pub), new JCEDHPrivateKey(priv)); } } public static class DSA extends JDKKeyPairGenerator { DSAKeyGenerationParameters param; DSAKeyPairGenerator engine = new DSAKeyPairGenerator(); int strength = 1024; int certainty = 20; SecureRandom random = new SecureRandom(); boolean initialised = false; public DSA() { super("DSA"); } public void initialize( int strength, SecureRandom random) { this.strength = strength; this.random = random; } public void initialize( AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { if (!(params instanceof DSAParameterSpec)) { throw new InvalidAlgorithmParameterException("parameter object not a DSAParameterSpec"); } DSAParameterSpec dsaParams = (DSAParameterSpec)params; param = new DSAKeyGenerationParameters(random, new DSAParameters(dsaParams.getP(), dsaParams.getQ(), dsaParams.getG())); engine.init(param); initialised = true; } public KeyPair generateKeyPair() { if (!initialised) { DSAParametersGenerator pGen = new DSAParametersGenerator(); pGen.init(strength, certainty, random); param = new DSAKeyGenerationParameters(random, pGen.generateParameters()); engine.init(param); initialised = true; } AsymmetricCipherKeyPair pair = engine.generateKeyPair(); DSAPublicKeyParameters pub = (DSAPublicKeyParameters)pair.getPublic(); DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)pair.getPrivate(); return new KeyPair(new JDKDSAPublicKey(pub), new JDKDSAPrivateKey(priv)); } } public static class ElGamal extends JDKKeyPairGenerator { ElGamalKeyGenerationParameters param; ElGamalKeyPairGenerator engine = new ElGamalKeyPairGenerator(); int strength = 1024; int certainty = 20; SecureRandom random = new SecureRandom(); boolean initialised = false; public ElGamal() { super("ElGamal"); } public void initialize( int strength, SecureRandom random) { this.strength = strength; this.random = random; } public void initialize( AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { if (!(params instanceof ElGamalParameterSpec)) { throw new InvalidAlgorithmParameterException("parameter object not a ElGamalParameterSpec"); } ElGamalParameterSpec elParams = (ElGamalParameterSpec)params; param = new ElGamalKeyGenerationParameters(random, new ElGamalParameters(elParams.getP(), elParams.getG())); engine.init(param); initialised = true; } public KeyPair generateKeyPair() { if (!initialised) { ElGamalParametersGenerator pGen = new ElGamalParametersGenerator(); pGen.init(strength, certainty, random); param = new ElGamalKeyGenerationParameters(random, pGen.generateParameters()); engine.init(param); initialised = true; } AsymmetricCipherKeyPair pair = engine.generateKeyPair(); ElGamalPublicKeyParameters pub = (ElGamalPublicKeyParameters)pair.getPublic(); ElGamalPrivateKeyParameters priv = (ElGamalPrivateKeyParameters)pair.getPrivate(); return new KeyPair(new JCEElGamalPublicKey(pub), new JCEElGamalPrivateKey(priv)); } } */ public static class EC extends JDKKeyPairGenerator { ECKeyGenerationParameters param; ECKeyPairGenerator engine = new ECKeyPairGenerator(); ECParameterSpec ecParams = null; int strength = 239; int certainty = 50; SecureRandom random = new SecureRandom(); boolean initialised = false; String algorithm; static private Hashtable ecParameters; static { ecParameters = new Hashtable(); ecParameters.put(new Integer(192), ECNamedCurveTable.getParameterSpec("prime192v1")); ecParameters.put(new Integer(239), ECNamedCurveTable.getParameterSpec("prime239v1")); ecParameters.put(new Integer(256), ECNamedCurveTable.getParameterSpec("prime256v1")); } public EC( String algorithm) { super(algorithm); this.algorithm = algorithm; } public void initialize( int strength, SecureRandom random) { this.strength = strength; this.random = random; this.ecParams = (ECParameterSpec)ecParameters.get(new Integer(strength)); if (ecParams != null) { param = new ECKeyGenerationParameters(new ECDomainParameters(ecParams.getCurve(), ecParams.getG(), ecParams.getN()), random); engine.init(param); initialised = true; } } public void initialize( AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { if (!(params instanceof ECParameterSpec)) { throw new InvalidAlgorithmParameterException("parameter object not a ECParameterSpec"); } this.ecParams = (ECParameterSpec)params; param = new ECKeyGenerationParameters(new ECDomainParameters(ecParams.getCurve(), ecParams.getG(), ecParams.getN()), random); engine.init(param); initialised = true; } public KeyPair generateKeyPair() { if (!initialised) { throw new IllegalStateException("EC Key Pair Generator not initialised"); } AsymmetricCipherKeyPair pair = engine.generateKeyPair(); ECPublicKeyParameters pub = (ECPublicKeyParameters)pair.getPublic(); ECPrivateKeyParameters priv = (ECPrivateKeyParameters)pair.getPrivate(); return new KeyPair(new JCEECPublicKey(algorithm, pub, ecParams), new JCEECPrivateKey(algorithm, priv, ecParams)); } } public static class ECDSA extends EC { public ECDSA() { super("ECDSA"); } } public static class ECDH extends EC { public ECDH() { super("ECDH"); } } public static class ECDHC extends EC { public ECDHC() { super("ECDHC"); } } } azureus-4.3.0.6/org/bouncycastle/jce/provider/JCEECPrivateKey.java0000644000175000017500000001770310407566336024215 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.sec.ECPrivateKeyStructure; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x9.X962NamedCurves; import org.bouncycastle.asn1.x9.X962Parameters; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.jce.interfaces.ECPrivateKey; import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.jce.spec.ECParameterSpec; import org.bouncycastle.jce.spec.ECPrivateKeySpec; public class JCEECPrivateKey implements ECPrivateKey, PKCS12BagAttributeCarrier { private String algorithm = "EC"; private BigInteger d; private ECParameterSpec ecSpec; private Hashtable pkcs12Attributes = new Hashtable(); private Vector pkcs12Ordering = new Vector(); protected JCEECPrivateKey() { } JCEECPrivateKey( ECPrivateKey key) { this.d = key.getD(); this.algorithm = key.getAlgorithm(); this.ecSpec = key.getParams(); } JCEECPrivateKey( String algorithm, ECPrivateKeySpec spec) { this.algorithm = algorithm; this.d = spec.getD(); this.ecSpec = spec.getParams(); } JCEECPrivateKey( String algorithm, ECPrivateKeyParameters params, ECParameterSpec spec) { ECDomainParameters dp = params.getParameters(); this.algorithm = algorithm; this.d = params.getD(); if (spec == null) { this.ecSpec = new ECParameterSpec( dp.getCurve(), dp.getG(), dp.getN(), dp.getH(), dp.getSeed()); } else { this.ecSpec = spec; } } JCEECPrivateKey( PrivateKeyInfo info) { X962Parameters params = new X962Parameters((DERObject)info.getAlgorithmId().getParameters()); if (params.isNamedCurve()) { DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); X9ECParameters ecP = X962NamedCurves.getByOID(oid); ecSpec = new ECNamedCurveParameterSpec( X962NamedCurves.getName(oid), ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed()); } else { X9ECParameters ecP = new X9ECParameters((ASN1Sequence)params.getParameters()); ecSpec = new ECParameterSpec(ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed()); } if (info.getPrivateKey() instanceof DERInteger) { DERInteger derD = (DERInteger)info.getPrivateKey(); this.d = derD.getValue(); } else { ECPrivateKeyStructure ec = new ECPrivateKeyStructure((ASN1Sequence)info.getPrivateKey()); this.d = ec.getKey(); } } public String getAlgorithm() { return algorithm; } /** * return the encoding format we produce in getEncoded(). * * @return the string "PKCS#8" */ public String getFormat() { return "PKCS#8"; } /** * Return a PKCS8 representation of the key. The sequence returned * represents a full PrivateKeyInfo object. * * @return a PKCS8 representation of the key. */ public byte[] getEncoded() { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); X962Parameters params = null; if (ecSpec instanceof ECNamedCurveParameterSpec) { params = new X962Parameters(X962NamedCurves.getOID(((ECNamedCurveParameterSpec)ecSpec).getName())); } else { X9ECParameters ecP = new X9ECParameters( ecSpec.getCurve(), ecSpec.getG(), ecSpec.getN(), ecSpec.getH(), ecSpec.getSeed()); params = new X962Parameters(ecP); } PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.getDERObject()), new ECPrivateKeyStructure(this.getD()).getDERObject()); try { dOut.writeObject(info); dOut.close(); } catch (IOException e) { throw new RuntimeException("Error encoding EC private key"); } return bOut.toByteArray(); } public ECParameterSpec getParams() { return ecSpec; } public BigInteger getD() { return d; } /* private void readObject( ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); boolean named = in.readBoolean(); if (named) { ecSpec = new ECNamedCurveParameterSpec( in.readUTF(), (ECCurve)in.readObject(), (ECPoint)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject(), (byte[])in.readObject()); } else { ecSpec = new ECParameterSpec( (ECCurve)in.readObject(), (ECPoint)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject(), (byte[])in.readObject()); } } private void writeObject( ObjectOutputStream out) throws IOException { out.defaultWriteObject(); if (this.ecSpec instanceof ECNamedCurveParameterSpec) { ECNamedCurveParameterSpec namedSpec = (ECNamedCurveParameterSpec)ecSpec; out.writeBoolean(true); out.writeUTF(namedSpec.getName()); } else { out.writeBoolean(false); } out.writeObject(ecSpec.getCurve()); out.writeObject(ecSpec.getG()); out.writeObject(ecSpec.getN()); out.writeObject(ecSpec.getH()); out.writeObject(ecSpec.getSeed()); } */ public void setBagAttribute( DERObjectIdentifier oid, DEREncodable attribute) { pkcs12Attributes.put(oid, attribute); pkcs12Ordering.addElement(oid); } public DEREncodable getBagAttribute( DERObjectIdentifier oid) { return (DEREncodable)pkcs12Attributes.get(oid); } public Enumeration getBagAttributeKeys() { return pkcs12Ordering.elements(); } } azureus-4.3.0.6/org/bouncycastle/jce/provider/JDKX509CertificateFactory.java0000644000175000017500000002334510061400650026046 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.security.cert.CRL; import java.security.cert.CRLException; import java.security.cert.CertPath; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactorySpi; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.BERInputStream; import org.bouncycastle.asn1.DERInputStream; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.pkcs.SignedData; import org.bouncycastle.asn1.x509.CertificateList; import org.bouncycastle.asn1.x509.X509CertificateStructure; import org.bouncycastle.util.encoders.Base64; /** * class for dealing with X509 certificates. *

      * At the moment this will deal with "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----" * base 64 encoded certs, as well as the BER binaries of certificates and some classes of PKCS#7 * objects. */ public class JDKX509CertificateFactory extends CertificateFactorySpi { private SignedData sData = null; private int sDataObjectCount = 0; private String readLine( InputStream in) throws IOException { int c; StringBuffer l = new StringBuffer(); while (((c = in.read()) != '\n') && (c >= 0)) { if (c == '\r') { continue; } l.append((char)c); } if (c < 0) { return null; } return l.toString(); } private Certificate readDERCertificate( InputStream in) throws IOException { DERInputStream dIn = new DERInputStream(in); ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); if (seq.size() > 1 && seq.getObjectAt(0) instanceof DERObjectIdentifier) { if (seq.getObjectAt(0).equals(PKCSObjectIdentifiers.signedData)) { sData = new SignedData(ASN1Sequence.getInstance( (ASN1TaggedObject)seq.getObjectAt(1), true)); return new X509CertificateObject( X509CertificateStructure.getInstance( sData.getCertificates().getObjectAt(sDataObjectCount++))); } } return new X509CertificateObject( X509CertificateStructure.getInstance(seq)); } /** * read in a BER encoded PKCS7 certificate. */ private Certificate readPKCS7Certificate( InputStream in) throws IOException { BERInputStream dIn = new BERInputStream(in); ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); if (seq.size() > 1 && seq.getObjectAt(0) instanceof DERObjectIdentifier) { if (seq.getObjectAt(0).equals(PKCSObjectIdentifiers.signedData)) { sData = new SignedData(ASN1Sequence.getInstance( (ASN1TaggedObject)seq.getObjectAt(1), true)); return new X509CertificateObject( X509CertificateStructure.getInstance( sData.getCertificates().getObjectAt(sDataObjectCount++))); } } return new X509CertificateObject( X509CertificateStructure.getInstance(seq)); } private Certificate readPEMCertificate( InputStream in) throws IOException { String line; StringBuffer pemBuf = new StringBuffer(); while ((line = readLine(in)) != null) { if (line.equals("-----BEGIN CERTIFICATE-----") || line.equals("-----BEGIN X509 CERTIFICATE-----")) { break; } } while ((line = readLine(in)) != null) { if (line.equals("-----END CERTIFICATE-----") || line.equals("-----END X509 CERTIFICATE-----")) { break; } pemBuf.append(line); } if (pemBuf.length() != 0) { ByteArrayInputStream bIn = new ByteArrayInputStream(Base64.decode(pemBuf.toString())); return readDERCertificate(bIn); } return null; } private CRL readDERCRL( InputStream in) throws IOException { DERInputStream dIn = new DERInputStream(in); return new X509CRLObject(new CertificateList((ASN1Sequence)dIn.readObject())); } private CRL readPEMCRL( InputStream in) throws IOException { String line; StringBuffer pemBuf = new StringBuffer(); while ((line = readLine(in)) != null) { if (line.equals("-----BEGIN CRL-----") || line.equals("-----BEGIN X509 CRL-----")) { break; } } while ((line = readLine(in)) != null) { if (line.equals("-----END CRL-----") || line.equals("-----END X509 CRL-----")) { break; } pemBuf.append(line); } if (pemBuf.length() != 0) { ByteArrayInputStream bIn = new ByteArrayInputStream(Base64.decode(pemBuf.toString())); return readDERCRL(bIn); } return null; } /** * Generates a certificate object and initializes it with the data * read from the input stream inStream. */ public Certificate engineGenerateCertificate( InputStream in) throws CertificateException { if (sData != null && sDataObjectCount != sData.getCertificates().size()) { return new X509CertificateObject( X509CertificateStructure.getInstance( sData.getCertificates().getObjectAt(sDataObjectCount++))); } if (!in.markSupported()) { in = new BufferedInputStream(in); } try { in.mark(10); int tag = in.read(); if (tag == -1) { return null; } if (tag != 0x30) // assume ascii PEM encoded. { in.reset(); return readPEMCertificate(in); } else if (in.read() == 0x80) // assume BER encoded. { in.reset(); return readPKCS7Certificate(in); } else { in.reset(); return readDERCertificate(in); } } catch (IOException e) { throw new CertificateException(e.toString()); } } /** * Returns a (possibly empty) collection view of the certificates * read from the given input stream inStream. */ public Collection engineGenerateCertificates( InputStream inStream) throws CertificateException { Certificate cert; ArrayList certs = new ArrayList(); while ((cert = engineGenerateCertificate(inStream)) != null) { certs.add(cert); } return certs; } /** * Generates a certificate revocation list (CRL) object and initializes * it with the data read from the input stream inStream. */ public CRL engineGenerateCRL( InputStream inStream) throws CRLException { if (!inStream.markSupported()) { inStream = new BufferedInputStream(inStream); } try { inStream.mark(10); if (inStream.read() != 0x30) // assume ascii PEM encoded. { inStream.reset(); return readPEMCRL(inStream); } else { inStream.reset(); return readDERCRL(inStream); } } catch (IOException e) { throw new CRLException(e.toString()); } } /** * Returns a (possibly empty) collection view of the CRLs read from * the given input stream inStream. * * The inStream may contain a sequence of DER-encoded CRLs, or * a PKCS#7 CRL set. This is a PKCS#7 SignedData object, with the * only signficant field being crls. In particular the signature * and the contents are ignored. */ public Collection engineGenerateCRLs( InputStream inStream) throws CRLException { return null; } public Iterator engineGetCertPathEncodings() { return PKIXCertPath.certPathEncodings.iterator(); } public CertPath engineGenerateCertPath( InputStream inStream) throws CertificateException { return engineGenerateCertPath( inStream, "PkiPath" ); } public CertPath engineGenerateCertPath( InputStream inStream, String encoding) throws CertificateException { return new PKIXCertPath( inStream, encoding ); } public CertPath engineGenerateCertPath( List certificates) throws CertificateException { Iterator iter = certificates.iterator(); Object obj; while ( iter.hasNext() ) { obj = iter.next(); if ( obj != null ) { if ( ! ( obj instanceof X509Certificate ) ) { throw new CertificateException( "list contains none X509Certificate object while creating CertPath\n" + obj.toString() ); } } } return new PKIXCertPath( certificates ); } } azureus-4.3.0.6/org/bouncycastle/jce/provider/PKIXPolicyNode.java0000644000175000017500000000657610061400650024125 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.security.cert.PolicyNode; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; public class PKIXPolicyNode implements PolicyNode { protected List children; protected int depth; protected Set expectedPolicies; protected PolicyNode parent; protected Set policyQualifiers; protected String validPolicy; protected boolean critical; /* * * CONSTRUCTORS * */ public PKIXPolicyNode( List _children, int _depth, Set _expectedPolicies, PolicyNode _parent, Set _policyQualifiers, String _validPolicy, boolean _critical) { children = _children; depth = _depth; expectedPolicies = _expectedPolicies; parent = _parent; policyQualifiers = _policyQualifiers; validPolicy = _validPolicy; critical = _critical; } public void addChild( PKIXPolicyNode _child) { children.add(_child); _child.setParent(this); } public Iterator getChildren() { return children.iterator(); } public int getDepth() { return depth; } public Set getExpectedPolicies() { return expectedPolicies; } public PolicyNode getParent() { return parent; } public Set getPolicyQualifiers() { return policyQualifiers; } public String getValidPolicy() { return validPolicy; } public boolean hasChildren() { return !children.isEmpty(); } public boolean isCritical() { return critical; } public void removeChild(PKIXPolicyNode _child) { children.remove(_child); } public void setCritical(boolean _critical) { critical = _critical; } public void setParent(PKIXPolicyNode _parent) { parent = _parent; } public String toString() { return toString(""); } public String toString(String _indent) { StringBuffer _buf = new StringBuffer(); _buf.append(_indent); _buf.append(validPolicy); _buf.append(" {\n"); for(int i = 0; i < children.size(); i++) { _buf.append(((PKIXPolicyNode)children.get(i)).toString(_indent + " ")); } _buf.append(_indent); _buf.append("}\n"); return _buf.toString(); } public Object clone() { return copy(); } public PKIXPolicyNode copy() { HashSet _expectedPolicies = new HashSet(); Iterator _iter = expectedPolicies.iterator(); while (_iter.hasNext()) { _expectedPolicies.add(new String((String)_iter.next())); } HashSet _policyQualifiers = new HashSet(); _iter = policyQualifiers.iterator(); while (_iter.hasNext()) { _policyQualifiers.add(new String((String)_iter.next())); } PKIXPolicyNode _node = new PKIXPolicyNode(new ArrayList(), depth, _expectedPolicies, null, _policyQualifiers, new String(validPolicy), critical); _iter = children.iterator(); while (_iter.hasNext()) { PKIXPolicyNode _child = ((PKIXPolicyNode)_iter.next()).copy(); _child.setParent(_node); _node.addChild(_child); } return _node; } } azureus-4.3.0.6/org/bouncycastle/jce/provider/JDKAlgorithmParameterGenerator.java0000644000175000017500000002522010061400650027336 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.security.AlgorithmParameterGeneratorSpi; import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.DSAParameterSpec; import javax.crypto.spec.DHGenParameterSpec; import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.RC2ParameterSpec; import org.bouncycastle.crypto.generators.DHParametersGenerator; import org.bouncycastle.crypto.generators.DSAParametersGenerator; import org.bouncycastle.crypto.generators.ElGamalParametersGenerator; import org.bouncycastle.crypto.params.DHParameters; import org.bouncycastle.crypto.params.DSAParameters; import org.bouncycastle.crypto.params.ElGamalParameters; import org.bouncycastle.jce.spec.ElGamalParameterSpec; public abstract class JDKAlgorithmParameterGenerator extends AlgorithmParameterGeneratorSpi { protected SecureRandom random; protected int strength = 1024; protected void engineInit( int strength, SecureRandom random) { this.strength = strength; this.random = random; } public static class DH extends JDKAlgorithmParameterGenerator { private int l = 0; protected void engineInit( AlgorithmParameterSpec genParamSpec, SecureRandom random) throws InvalidAlgorithmParameterException { if (!(genParamSpec instanceof DHGenParameterSpec)) { throw new InvalidAlgorithmParameterException("DH parameter generator requires a DHGenParameterSpec for initialisation"); } DHGenParameterSpec spec = (DHGenParameterSpec)genParamSpec; this.strength = spec.getPrimeSize(); this.l = spec.getExponentSize(); this.random = random; } protected AlgorithmParameters engineGenerateParameters() { DHParametersGenerator pGen = new DHParametersGenerator(); if ( random != null ) { pGen.init(strength, 20, random); } else { pGen.init(strength, 20, new SecureRandom()); } DHParameters p = pGen.generateParameters(); AlgorithmParameters params; try { params = AlgorithmParameters.getInstance("DH", "BC"); params.init(new DHParameterSpec(p.getP(), p.getG(), l)); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } return params; } } public static class DSA extends JDKAlgorithmParameterGenerator { protected void engineInit( AlgorithmParameterSpec genParamSpec, SecureRandom random) throws InvalidAlgorithmParameterException { throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for DSA parameter generation."); } protected AlgorithmParameters engineGenerateParameters() { DSAParametersGenerator pGen = new DSAParametersGenerator(); if ( random != null ) { pGen.init(strength, 20, random); } else { pGen.init(strength, 20, new SecureRandom()); } DSAParameters p = pGen.generateParameters(); AlgorithmParameters params; try { params = AlgorithmParameters.getInstance("DSA", "BC"); params.init(new DSAParameterSpec(p.getP(), p.getQ(), p.getG())); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } return params; } } public static class ElGamal extends JDKAlgorithmParameterGenerator { protected void engineInit( AlgorithmParameterSpec genParamSpec, SecureRandom random) throws InvalidAlgorithmParameterException { throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for ElGamal parameter generation."); } protected AlgorithmParameters engineGenerateParameters() { ElGamalParametersGenerator pGen = new ElGamalParametersGenerator(); if ( random != null ) { pGen.init(strength, 20, random); } else { pGen.init(strength, 20, new SecureRandom()); } ElGamalParameters p = pGen.generateParameters(); AlgorithmParameters params; try { params = AlgorithmParameters.getInstance("ElGamal", "BC"); params.init(new ElGamalParameterSpec(p.getP(), p.getG())); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } return params; } } public static class DES extends JDKAlgorithmParameterGenerator { protected void engineInit( AlgorithmParameterSpec genParamSpec, SecureRandom random) throws InvalidAlgorithmParameterException { throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for DES parameter generation."); } protected AlgorithmParameters engineGenerateParameters() { byte[] iv = new byte[8]; if (random == null) { random = new SecureRandom(); } random.nextBytes(iv); AlgorithmParameters params; try { params = AlgorithmParameters.getInstance("DES", "BC"); params.init(new IvParameterSpec(iv)); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } return params; } } public static class RC2 extends JDKAlgorithmParameterGenerator { RC2ParameterSpec spec = null; protected void engineInit( AlgorithmParameterSpec genParamSpec, SecureRandom random) throws InvalidAlgorithmParameterException { if (genParamSpec instanceof RC2ParameterSpec) { spec = (RC2ParameterSpec)genParamSpec; return; } throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for RC2 parameter generation."); } protected AlgorithmParameters engineGenerateParameters() { AlgorithmParameters params; if (spec == null) { byte[] iv = new byte[8]; if (random == null) { random = new SecureRandom(); } random.nextBytes(iv); try { params = AlgorithmParameters.getInstance("RC2", "BC"); params.init(new IvParameterSpec(iv)); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } else { try { params = AlgorithmParameters.getInstance("RC2", "BC"); params.init(spec); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } return params; } } public static class AES extends JDKAlgorithmParameterGenerator { protected void engineInit( AlgorithmParameterSpec genParamSpec, SecureRandom random) throws InvalidAlgorithmParameterException { throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for AES parameter generation."); } protected AlgorithmParameters engineGenerateParameters() { byte[] iv = new byte[16]; if (random == null) { random = new SecureRandom(); } random.nextBytes(iv); AlgorithmParameters params; try { params = AlgorithmParameters.getInstance("AES", "BC"); params.init(new IvParameterSpec(iv)); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } return params; } } public static class IDEA extends JDKAlgorithmParameterGenerator { protected void engineInit( AlgorithmParameterSpec genParamSpec, SecureRandom random) throws InvalidAlgorithmParameterException { throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for IDEA parameter generation."); } protected AlgorithmParameters engineGenerateParameters() { byte[] iv = new byte[8]; if (random == null) { random = new SecureRandom(); } random.nextBytes(iv); AlgorithmParameters params; try { params = AlgorithmParameters.getInstance("IDEA", "BC"); params.init(new IvParameterSpec(iv)); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } return params; } } public static class CAST5 extends JDKAlgorithmParameterGenerator { protected void engineInit( AlgorithmParameterSpec genParamSpec, SecureRandom random) throws InvalidAlgorithmParameterException { throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for CAST5 parameter generation."); } protected AlgorithmParameters engineGenerateParameters() { byte[] iv = new byte[8]; if (random == null) { random = new SecureRandom(); } random.nextBytes(iv); AlgorithmParameters params; try { params = AlgorithmParameters.getInstance("CAST5", "BC"); params.init(new IvParameterSpec(iv)); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } return params; } } } azureus-4.3.0.6/org/bouncycastle/jce/provider/JDKDigestSignature.java0000644000175000017500000001662610061400650025013 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.InvalidKeyException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.AlgorithmParameterSpec; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERInputStream; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.DigestInfo; import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; import org.bouncycastle.crypto.AsymmetricBlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.MD2Digest; import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.crypto.digests.RIPEMD128Digest; import org.bouncycastle.crypto.digests.RIPEMD160Digest; import org.bouncycastle.crypto.digests.RIPEMD256Digest; import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.crypto.encodings.PKCS1Encoding; import org.bouncycastle.crypto.engines.RSAEngine; public class JDKDigestSignature extends Signature implements PKCSObjectIdentifiers, X509ObjectIdentifiers { private Digest digest; private AsymmetricBlockCipher cipher; private AlgorithmIdentifier algId; protected JDKDigestSignature( String name, DERObjectIdentifier objId, Digest digest, AsymmetricBlockCipher cipher) { super(name); this.digest = digest; this.cipher = cipher; this.algId = new AlgorithmIdentifier(objId, null); } protected void engineInitVerify( PublicKey publicKey) throws InvalidKeyException { if ( !(publicKey instanceof RSAPublicKey) ) { throw new InvalidKeyException("Supplied key is not a RSAPublicKey instance"); } CipherParameters param = RSAUtil.generatePublicKeyParameter((RSAPublicKey)publicKey); digest.reset(); cipher.init(false, param); } protected void engineInitSign( PrivateKey privateKey) throws InvalidKeyException { if ( !(privateKey instanceof RSAPrivateKey) ) { throw new InvalidKeyException("Supplied key is not a RSAPrivateKey instance"); } CipherParameters param = RSAUtil.generatePrivateKeyParameter((RSAPrivateKey)privateKey); digest.reset(); cipher.init(true, param); } protected void engineUpdate( byte b) throws SignatureException { digest.update(b); } protected void engineUpdate( byte[] b, int off, int len) throws SignatureException { digest.update(b, off, len); } protected byte[] engineSign() throws SignatureException { byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); try { byte[] bytes = derEncode(hash); return cipher.processBlock(bytes, 0, bytes.length); } catch (ArrayIndexOutOfBoundsException e) { throw new SignatureException("key too small for signature type"); } catch (Exception e) { throw new SignatureException(e.toString()); } } protected boolean engineVerify( byte[] sigBytes) throws SignatureException { byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); DigestInfo digInfo; byte[] sig; try { sig = cipher.processBlock(sigBytes, 0, sigBytes.length); digInfo = derDecode(sig); } catch (Exception e) { return false; } if (!digInfo.getAlgorithmId().equals(algId)) { return false; } byte[] sigHash = digInfo.getDigest(); if (hash.length != sigHash.length) { return false; } for (int i = 0; i < hash.length; i++) { if (sigHash[i] != hash[i]) { return false; } } return true; } protected void engineSetParameter( AlgorithmParameterSpec params) { throw new UnsupportedOperationException("engineSetParameter unsupported"); } /** * @deprecated replaced with */ protected void engineSetParameter( String param, Object value) { throw new UnsupportedOperationException("engineSetParameter unsupported"); } /** * @deprecated */ protected Object engineGetParameter( String param) { throw new UnsupportedOperationException("engineSetParameter unsupported"); } private byte[] derEncode( byte[] hash) throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); DigestInfo dInfo = new DigestInfo(algId, hash); dOut.writeObject(dInfo); return bOut.toByteArray(); } private DigestInfo derDecode( byte[] encoding) throws IOException { ByteArrayInputStream bIn = new ByteArrayInputStream(encoding); DERInputStream dIn = new DERInputStream(bIn); return new DigestInfo((ASN1Sequence)dIn.readObject()); } static public class SHA1WithRSAEncryption extends JDKDigestSignature { public SHA1WithRSAEncryption() { super("SHA1withRSA", id_SHA1, new SHA1Digest(), new PKCS1Encoding(new RSAEngine())); } } static public class MD2WithRSAEncryption extends JDKDigestSignature { public MD2WithRSAEncryption() { super("MD2withRSA", md2, new MD2Digest(), new PKCS1Encoding(new RSAEngine())); } } static public class MD5WithRSAEncryption extends JDKDigestSignature { public MD5WithRSAEncryption() { super("MD5withRSA", md5, new MD5Digest(), new PKCS1Encoding(new RSAEngine())); } } static public class RIPEMD160WithRSAEncryption extends JDKDigestSignature { public RIPEMD160WithRSAEncryption() { super("RIPEMD160withRSA", TeleTrusTObjectIdentifiers.ripemd160, new RIPEMD160Digest(), new PKCS1Encoding(new RSAEngine())); } } static public class RIPEMD128WithRSAEncryption extends JDKDigestSignature { public RIPEMD128WithRSAEncryption() { super("RIPEMD128withRSA", TeleTrusTObjectIdentifiers.ripemd128, new RIPEMD128Digest(), new PKCS1Encoding(new RSAEngine())); } } static public class RIPEMD256WithRSAEncryption extends JDKDigestSignature { public RIPEMD256WithRSAEncryption() { super("RIPEMD256withRSA", TeleTrusTObjectIdentifiers.ripemd256, new RIPEMD256Digest(), new PKCS1Encoding(new RSAEngine())); } } } azureus-4.3.0.6/org/bouncycastle/jce/provider/JCERSAPublicKey.java0000644000175000017500000000666310061400650024140 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.interfaces.RSAPublicKey; import java.security.spec.RSAPublicKeySpec; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.RSAPublicKeyStructure; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.crypto.params.RSAKeyParameters; public class JCERSAPublicKey implements RSAPublicKey { private BigInteger modulus; private BigInteger publicExponent; JCERSAPublicKey( RSAKeyParameters key) { this.modulus = key.getModulus(); this.publicExponent = key.getExponent(); } JCERSAPublicKey( RSAPublicKeySpec spec) { this.modulus = spec.getModulus(); this.publicExponent = spec.getPublicExponent(); } JCERSAPublicKey( RSAPublicKey key) { this.modulus = key.getModulus(); this.publicExponent = key.getPublicExponent(); } JCERSAPublicKey( SubjectPublicKeyInfo info) { try { RSAPublicKeyStructure pubKey = new RSAPublicKeyStructure((ASN1Sequence)info.getPublicKey()); this.modulus = pubKey.getModulus(); this.publicExponent = pubKey.getPublicExponent(); } catch (IOException e) { throw new IllegalArgumentException("invalid info structure in RSA public key"); } } /** * return the modulus. * * @return the modulus. */ public BigInteger getModulus() { return modulus; } /** * return the public exponent. * * @return the public exponent. */ public BigInteger getPublicExponent() { return publicExponent; } public String getAlgorithm() { return "RSA"; } public String getFormat() { return "X.509"; } public byte[] getEncoded() { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, new DERNull()), new RSAPublicKeyStructure(getModulus(), getPublicExponent()).getDERObject()); try { dOut.writeObject(info); dOut.close(); } catch (IOException e) { throw new RuntimeException("Error encoding RSA public key"); } return bOut.toByteArray(); } public boolean equals(Object o) { if ( !(o instanceof RSAPublicKey) ) { return false; } if ( o == this ) { return true; } RSAPublicKey key = (RSAPublicKey)o; return getModulus().equals(key.getModulus()) && getPublicExponent().equals(key.getPublicExponent()); } public String toString() { StringBuffer buf = new StringBuffer(); String nl = System.getProperty("line.separator"); buf.append("RSA Public Key" + nl); buf.append(" modulus: " + this.getModulus().toString(16) + nl); buf.append(" public exponent: " + this.getPublicExponent().toString(16) + nl); return buf.toString(); } } azureus-4.3.0.6/org/bouncycastle/jce/provider/DHUtil.java0000644000175000017500000000313110061400650022475 0ustar adrianadrianpackage org.bouncycastle.jce.provider; import java.security.InvalidKeyException; import java.security.PrivateKey; import java.security.PublicKey; import javax.crypto.interfaces.DHPrivateKey; import javax.crypto.interfaces.DHPublicKey; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.DHParameters; import org.bouncycastle.crypto.params.DHPrivateKeyParameters; import org.bouncycastle.crypto.params.DHPublicKeyParameters; /** * utility class for converting jce/jca DH objects * objects into their org.bouncycastle.crypto counterparts. */ public class DHUtil { static public AsymmetricKeyParameter generatePublicKeyParameter( PublicKey key) throws InvalidKeyException { if (key instanceof DHPublicKey) { DHPublicKey k = (DHPublicKey)key; return new DHPublicKeyParameters(k.getY(), new DHParameters(k.getParams().getP(), k.getParams().getG(), null, k.getParams().getL())); } throw new InvalidKeyException("can't identify DH public key."); } static public AsymmetricKeyParameter generatePrivateKeyParameter( PrivateKey key) throws InvalidKeyException { if (key instanceof DHPrivateKey) { DHPrivateKey k = (DHPrivateKey)key; return new DHPrivateKeyParameters(k.getX(), new DHParameters(k.getParams().getP(), k.getParams().getG(), null, k.getParams().getL())); } throw new InvalidKeyException("can't identify DH private key."); } } azureus-4.3.0.6/org/bouncycastle/jce/X509Principal.java0000644000175000017500000000713110061400654022031 0ustar adrianadrianpackage org.bouncycastle.jce; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.Principal; import java.util.Hashtable; import java.util.Vector; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.x509.X509Name; public class X509Principal extends X509Name implements Principal { /** * Constructor from an encoded byte array. */ public X509Principal( byte[] bytes) throws IOException { super((ASN1Sequence)(new ASN1InputStream(new ByteArrayInputStream(bytes)).readObject())); } /** * Constructor from an X509Name object. */ public X509Principal( X509Name name) { super((ASN1Sequence)name.getDERObject()); } /** * constructor from a table of attributes. *

      * it's is assumed the table contains OID/String pairs. */ public X509Principal( Hashtable attributes) { super(attributes); } /** * constructor from a table of attributes and a vector giving the * specific ordering required for encoding or conversion to a string. *

      * it's is assumed the table contains OID/String pairs. */ public X509Principal( Vector ordering, Hashtable attributes) { super(ordering, attributes); } /** * constructor from a vector of attribute values and a vector of OIDs. */ public X509Principal( Vector oids, Vector values) { super(oids, values); } /** * takes an X509 dir name as a string of the format "C=AU,ST=Victoria", or * some such, converting it into an ordered set of name attributes. */ public X509Principal( String dirName) { super(dirName); } /** * Takes an X509 dir name as a string of the format "C=AU,ST=Victoria", or * some such, converting it into an ordered set of name attributes. If reverse * is false the dir name will be encoded in the order of the (name, value) pairs * presented, otherwise the encoding will start with the last (name, value) pair * and work back. */ public X509Principal( boolean reverse, String dirName) { super(reverse, dirName); } /** * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or * some such, converting it into an ordered set of name attributes. lookUp * should provide a table of lookups, indexed by lowercase only strings and * yielding a DERObjectIdentifier, other than that OID. and numeric oids * will be processed automatically. *

      * If reverse is true, create the encoded version of the sequence starting * from the last element in the string. */ public X509Principal( boolean reverse, Hashtable lookUp, String dirName) { super(reverse, lookUp, dirName); } public String getName() { return this.toString(); } /** * return a DER encoded byte array representing this object */ public byte[] getEncoded() { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(this); } catch (IOException e) { throw new RuntimeException(e.toString()); } return bOut.toByteArray(); } } azureus-4.3.0.6/org/bouncycastle/jce/PrincipalUtil.java0000644000175000017500000000447410061400654022310 0ustar adrianadrianpackage org.bouncycastle.jce; import java.io.*; import java.security.cert.*; import org.bouncycastle.asn1.*; import org.bouncycastle.asn1.x509.*; /** * a utility class that will extract X509Principal objects from X.509 certificates. */ public class PrincipalUtil { /** * return the issuer of the given cert as an X509PrincipalObject. */ public static X509Principal getIssuerX509Principal( X509Certificate cert) throws CertificateEncodingException { try { ByteArrayInputStream bIn = new ByteArrayInputStream( cert.getTBSCertificate()); ASN1InputStream aIn = new ASN1InputStream(bIn); TBSCertificateStructure tbsCert = new TBSCertificateStructure( (ASN1Sequence)aIn.readObject()); return new X509Principal(tbsCert.getIssuer()); } catch (IOException e) { throw new CertificateEncodingException(e.toString()); } } /** * return the subject of the given cert as an X509PrincipalObject. */ public static X509Principal getSubjectX509Principal( X509Certificate cert) throws CertificateEncodingException { try { ByteArrayInputStream bIn = new ByteArrayInputStream( cert.getTBSCertificate()); ASN1InputStream aIn = new ASN1InputStream(bIn); TBSCertificateStructure tbsCert = new TBSCertificateStructure( (ASN1Sequence)aIn.readObject()); return new X509Principal(tbsCert.getSubject()); } catch (IOException e) { throw new CertificateEncodingException(e.toString()); } } /** * return the issuer of the given CRL as an X509PrincipalObject. */ public static X509Principal getIssuerX509Principal( X509CRL crl) throws CRLException { try { ByteArrayInputStream bIn = new ByteArrayInputStream( crl.getTBSCertList()); ASN1InputStream aIn = new ASN1InputStream(bIn); TBSCertList tbsCertList = new TBSCertList( (ASN1Sequence)aIn.readObject()); return new X509Principal(tbsCertList.getIssuer()); } catch (IOException e) { throw new CRLException(e.toString()); } } } azureus-4.3.0.6/org/bouncycastle/jce/PKCS10CertificationRequest.java0000644000175000017500000002417210061400654024504 0ustar adrianadrianpackage org.bouncycastle.jce; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import java.util.Hashtable; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERInputStream; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.pkcs.CertificationRequest; import org.bouncycastle.asn1.pkcs.CertificationRequestInfo; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.X509Name; /** * A class for verifying and creating PKCS10 Certification requests. *

       * CertificationRequest ::= SEQUENCE {
       *   certificationRequestInfo  CertificationRequestInfo,
       *   signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
       *   signature                 BIT STRING
       * }
       *
       * CertificationRequestInfo ::= SEQUENCE {
       *   version             INTEGER { v1(0) } (v1,...),
       *   subject             Name,
       *   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
       *   attributes          [0] Attributes{{ CRIAttributes }}
       *  }
       *
       *  Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
       *
       *  Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
       *    type    ATTRIBUTE.&id({IOSet}),
       *    values  SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
       *  }
       * 
      */ public class PKCS10CertificationRequest extends CertificationRequest { private static Hashtable algorithms = new Hashtable(); private static Hashtable oids = new Hashtable(); static { algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2")); algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2")); algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4")); algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4")); algorithms.put("RSAWITHMD5", new DERObjectIdentifier("1.2.840.113549.1.1.4")); algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("RSAWITHSHA1", new DERObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("RIPEMD160WITHRSAENCRYPTION", new DERObjectIdentifier("1.3.36.3.3.1.2")); algorithms.put("RIPEMD160WITHRSA", new DERObjectIdentifier("1.3.36.3.3.1.2")); algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3")); algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3")); algorithms.put("SHA1WITHECDSA", new DERObjectIdentifier("1.2.840.10045.4.1")); algorithms.put("ECDSAWITHSHA1", new DERObjectIdentifier("1.2.840.10045.4.1")); // // reverse mappings // oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.5"), "SHA1WITHRSA"); oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA"); oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA"); oids.put(new DERObjectIdentifier("1.2.840.10040.4.3"), "DSAWITHSHA1"); } private static ASN1Sequence toDERSequence( byte[] bytes) { try { ByteArrayInputStream bIn = new ByteArrayInputStream(bytes); DERInputStream dIn = new DERInputStream(bIn); return (ASN1Sequence)dIn.readObject(); } catch (Exception e) { throw new IllegalArgumentException("badly encoded request"); } } /** * construct a PKCS10 certification request from a DER encoded * byte stream. */ public PKCS10CertificationRequest( byte[] bytes) { super(toDERSequence(bytes)); } public PKCS10CertificationRequest( ASN1Sequence sequence) { super(sequence); } /** * create a PKCS10 certfication request using the BC provider. */ public PKCS10CertificationRequest( String signatureAlgorithm, X509Name subject, PublicKey key, ASN1Set attributes, PrivateKey signingKey) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException { this(signatureAlgorithm, subject, key, attributes, signingKey, "BC"); } /** * create a PKCS10 certfication request using the named provider. */ public PKCS10CertificationRequest( String signatureAlgorithm, X509Name subject, PublicKey key, ASN1Set attributes, PrivateKey signingKey, String provider) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException { DERObjectIdentifier sigOID = (DERObjectIdentifier)algorithms.get(signatureAlgorithm.toUpperCase()); if (sigOID == null) { throw new IllegalArgumentException("Unknown signature type requested"); } if (subject == null) { throw new IllegalArgumentException("subject must not be null"); } if (key == null) { throw new IllegalArgumentException("public key must not be null"); } this.sigAlgId = new AlgorithmIdentifier(sigOID, null); byte[] bytes = key.getEncoded(); ByteArrayInputStream bIn = new ByteArrayInputStream(bytes); DERInputStream dIn = new DERInputStream(bIn); try { this.reqInfo = new CertificationRequestInfo(subject, new SubjectPublicKeyInfo((ASN1Sequence)dIn.readObject()), attributes); } catch (IOException e) { throw new IllegalArgumentException("can't encode public key"); } Signature sig = null; try { sig = Signature.getInstance(sigAlgId.getObjectId().getId(), provider); } catch (NoSuchAlgorithmException e) { sig = Signature.getInstance(signatureAlgorithm, provider); } sig.initSign(signingKey); try { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); dOut.writeObject(reqInfo); sig.update(bOut.toByteArray()); } catch (Exception e) { throw new SecurityException("exception encoding TBS cert request - " + e); } this.sigBits = new DERBitString(sig.sign()); } /** * return the public key associated with the certification request - * the public key is created using the BC provider. */ public PublicKey getPublicKey() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException { return getPublicKey("BC"); } public PublicKey getPublicKey( String provider) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException { SubjectPublicKeyInfo subjectPKInfo = reqInfo.getSubjectPublicKeyInfo(); try { X509EncodedKeySpec xspec = new X509EncodedKeySpec(new DERBitString(subjectPKInfo).getBytes()); AlgorithmIdentifier keyAlg = subjectPKInfo.getAlgorithmId (); return KeyFactory.getInstance(keyAlg.getObjectId().getId (), provider).generatePublic(xspec); } catch (InvalidKeySpecException e) { throw new InvalidKeyException("error encoding public key"); } } /** * verify the request using the BC provider. */ public boolean verify() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException { return verify("BC"); } public boolean verify( String provider) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException { Signature sig = null; try { sig = Signature.getInstance(sigAlgId.getObjectId().getId(), provider); } catch (NoSuchAlgorithmException e) { // // try an alternate // if (oids.get(sigAlgId.getObjectId().getId()) != null) { String signatureAlgorithm = (String)oids.get(sigAlgId.getObjectId().getId()); sig = Signature.getInstance(signatureAlgorithm, provider); } } sig.initVerify(this.getPublicKey(provider)); try { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); dOut.writeObject(reqInfo); sig.update(bOut.toByteArray()); } catch (Exception e) { throw new SecurityException("exception encoding TBS cert request - " + e); } return sig.verify(sigBits.getBytes()); } /** * return a DER encoded byte array representing this object */ public byte[] getEncoded() { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(this); } catch (IOException e) { throw new RuntimeException(e.toString()); } return bOut.toByteArray(); } } azureus-4.3.0.6/org/bouncycastle/jce/X509V1CertificateGenerator.java0000644000175000017500000002012210061400654024403 0ustar adrianadrianpackage org.bouncycastle.jce; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.SignatureException; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Hashtable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERInputStream; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.TBSCertificateStructure; import org.bouncycastle.asn1.x509.Time; import org.bouncycastle.asn1.x509.V1TBSCertificateGenerator; import org.bouncycastle.asn1.x509.X509CertificateStructure; import org.bouncycastle.asn1.x509.X509Name; import org.bouncycastle.jce.provider.X509CertificateObject; /** * class to produce an X.509 Version 1 certificate. */ public class X509V1CertificateGenerator { private V1TBSCertificateGenerator tbsGen; private DERObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; private static Hashtable algorithms = new Hashtable(); static { algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2")); algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2")); algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4")); algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4")); algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("RIPEMD160WITHRSAENCRYPTION", new DERObjectIdentifier("1.3.36.3.3.1.2")); algorithms.put("RIPEMD160WITHRSA", new DERObjectIdentifier("1.3.36.3.3.1.2")); algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3")); algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3")); algorithms.put("SHA1WITHECDSA", new DERObjectIdentifier("1.2.840.10045.4.1")); algorithms.put("ECDSAWITHSHA1", new DERObjectIdentifier("1.2.840.10045.4.1")); } public X509V1CertificateGenerator() { tbsGen = new V1TBSCertificateGenerator(); } /** * reset the generator */ public void reset() { tbsGen = new V1TBSCertificateGenerator(); } /** * set the serial number for the certificate. */ public void setSerialNumber( BigInteger serialNumber) { tbsGen.setSerialNumber(new DERInteger(serialNumber)); } /** * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the * certificate. */ public void setIssuerDN( X509Name issuer) { tbsGen.setIssuer(issuer); } public void setNotBefore( Date date) { tbsGen.setStartDate(new Time(date)); } public void setNotAfter( Date date) { tbsGen.setEndDate(new Time(date)); } /** * Set the subject distinguished name. The subject describes the entity associated with the public key. */ public void setSubjectDN( X509Name subject) { tbsGen.setSubject(subject); } public void setPublicKey( PublicKey key) { try { tbsGen.setSubjectPublicKeyInfo(new SubjectPublicKeyInfo((ASN1Sequence)new DERInputStream( new ByteArrayInputStream(key.getEncoded())).readObject())); } catch (Exception e) { throw new IllegalArgumentException("unable to process key - " + e.toString()); } } public void setSignatureAlgorithm( String signatureAlgorithm) { this.signatureAlgorithm = signatureAlgorithm; sigOID = (DERObjectIdentifier)algorithms.get(signatureAlgorithm.toUpperCase()); if (sigOID == null) { throw new IllegalArgumentException("Unknown signature type requested"); } sigAlgId = new AlgorithmIdentifier(this.sigOID, new DERNull()); tbsGen.setSignature(sigAlgId); } /** * generate an X509 certificate, based on the current issuer and subject * using the default provider "BC". */ public X509Certificate generateX509Certificate( PrivateKey key) throws SecurityException, SignatureException, InvalidKeyException { try { return generateX509Certificate(key, "BC", null); } catch (NoSuchProviderException e) { throw new SecurityException("BC provider not installed!"); } } /** * generate an X509 certificate, based on the current issuer and subject * using the default provider "BC" and the passed in source of randomness */ public X509Certificate generateX509Certificate( PrivateKey key, SecureRandom random) throws SecurityException, SignatureException, InvalidKeyException { try { return generateX509Certificate(key, "BC", random); } catch (NoSuchProviderException e) { throw new SecurityException("BC provider not installed!"); } } /** * generate an X509 certificate, based on the current issuer and subject, * using the passed in provider for the signing, and the passed in source * of randomness (if required). */ public X509Certificate generateX509Certificate( PrivateKey key, String provider) throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException { return generateX509Certificate(key, provider, null); } /** * generate an X509 certificate, based on the current issuer and subject, * using the passed in provider for the signing, and the passed in source * of randomness (if required). */ public X509Certificate generateX509Certificate( PrivateKey key, String provider, SecureRandom random) throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException { Signature sig = null; try { sig = Signature.getInstance(sigOID.getId(), provider); } catch (NoSuchAlgorithmException ex) { try { sig = Signature.getInstance(signatureAlgorithm, provider); } catch (NoSuchAlgorithmException e) { throw new SecurityException("exception creating signature: " + e.toString()); } } if (random != null) { sig.initSign(key, random); } else { sig.initSign(key); } TBSCertificateStructure tbsCert = tbsGen.generateTBSCertificate(); try { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); dOut.writeObject(tbsCert); sig.update(bOut.toByteArray()); } catch (Exception e) { throw new SecurityException("exception encoding TBS cert - " + e); } ASN1EncodableVector v = new ASN1EncodableVector(); v.add(tbsCert); v.add(sigAlgId); v.add(new DERBitString(sig.sign())); return new X509CertificateObject(new X509CertificateStructure(new DERSequence(v))); } } azureus-4.3.0.6/org/bouncycastle/jce/X509V2CRLGenerator.java0000644000175000017500000002346510061400654022617 0ustar adrianadrianpackage org.bouncycastle.jce; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.SecureRandom; import java.security.Signature; import java.security.SignatureException; import java.security.cert.X509CRL; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Hashtable; import java.util.SimpleTimeZone; import java.util.Vector; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERUTCTime; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.CertificateList; import org.bouncycastle.asn1.x509.TBSCertList; import org.bouncycastle.asn1.x509.V2TBSCertListGenerator; import org.bouncycastle.asn1.x509.X509Extension; import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.asn1.x509.X509Name; import org.bouncycastle.jce.provider.X509CRLObject; /** * class to produce an X.509 Version 2 CRL. *

      * Note: This class may be subject to change. */ public class X509V2CRLGenerator { private SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss"); private SimpleTimeZone tz = new SimpleTimeZone(0, "Z"); private V2TBSCertListGenerator tbsGen; private DERObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; private Hashtable extensions = null; private Vector extOrdering = null; private static Hashtable algorithms = new Hashtable(); static { algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2")); algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2")); algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4")); algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4")); algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("RIPEMD160WITHRSAENCRYPTION", new DERObjectIdentifier("1.3.36.3.3.1.2")); algorithms.put("RIPEMD160WITHRSA", new DERObjectIdentifier("1.3.36.3.3.1.2")); algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3")); algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3")); algorithms.put("SHA1WITHECDSA", new DERObjectIdentifier("1.2.840.10045.4.1")); algorithms.put("ECDSAWITHSHA1", new DERObjectIdentifier("1.2.840.10045.4.1")); } public X509V2CRLGenerator() { dateF.setTimeZone(tz); tbsGen = new V2TBSCertListGenerator(); } /** * reset the generator */ public void reset() { tbsGen = new V2TBSCertListGenerator(); } /** * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the * certificate. */ public void setIssuerDN( X509Name issuer) { tbsGen.setIssuer(issuer); } public void setThisUpdate( Date date) { tbsGen.setThisUpdate(new DERUTCTime(dateF.format(date) + "Z")); } public void setNextUpdate( Date date) { tbsGen.setNextUpdate(new DERUTCTime(dateF.format(date) + "Z")); } /** * Reason being as indicated by ReasonFlags, i.e. ReasonFlags.KEY_COMPROMISE * or 0 if ReasonFlags are not to be used **/ public void addCRLEntry(BigInteger userCertificate, Date revocationDate, int reason) { tbsGen.addCRLEntry(new DERInteger(userCertificate), new DERUTCTime(dateF.format(revocationDate) + "Z"), reason); } public void setSignatureAlgorithm( String signatureAlgorithm) { this.signatureAlgorithm = signatureAlgorithm; sigOID = (DERObjectIdentifier)algorithms.get(signatureAlgorithm.toUpperCase()); if (sigOID == null) { throw new IllegalArgumentException("Unknown signature type requested"); } sigAlgId = new AlgorithmIdentifier(this.sigOID, null); tbsGen.setSignature(sigAlgId); } /** * add a given extension field for the standard extensions tag (tag 3) */ public void addExtension( String OID, boolean critical, DEREncodable value) { this.addExtension(new DERObjectIdentifier(OID), critical, value); } /** * add a given extension field for the standard extensions tag (tag 0) */ public void addExtension( DERObjectIdentifier OID, boolean critical, DEREncodable value) { if (extensions == null) { extensions = new Hashtable(); extOrdering = new Vector(); } ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(value); } catch (IOException e) { throw new IllegalArgumentException("error encoding value: " + e); } this.addExtension(OID, critical, bOut.toByteArray()); } /** * add a given extension field for the standard extensions tag (tag 0) */ public void addExtension( String OID, boolean critical, byte[] value) { this.addExtension(new DERObjectIdentifier(OID), critical, value); } /** * add a given extension field for the standard extensions tag (tag 0) */ public void addExtension( DERObjectIdentifier OID, boolean critical, byte[] value) { if (extensions == null) { extensions = new Hashtable(); extOrdering = new Vector(); } extensions.put(OID, new X509Extension(critical, new DEROctetString(value))); extOrdering.addElement(OID); } /** * generate an X509 CRL, based on the current issuer and subject * using the default provider "BC". */ public X509CRL generateX509CRL( PrivateKey key) throws SecurityException, SignatureException, InvalidKeyException { try { return generateX509CRL(key, "BC", null); } catch (NoSuchProviderException e) { throw new SecurityException("BC provider not installed!"); } } /** * generate an X509 CRL, based on the current issuer and subject * using the default provider "BC" and an user defined SecureRandom object as * source of randomness. */ public X509CRL generateX509CRL( PrivateKey key, SecureRandom random) throws SecurityException, SignatureException, InvalidKeyException { try { return generateX509CRL(key, "BC", random); } catch (NoSuchProviderException e) { throw new SecurityException("BC provider not installed!"); } } /** * generate an X509 certificate, based on the current issuer and subject * using the passed in provider for the signing. */ public X509CRL generateX509CRL( PrivateKey key, String provider) throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException { return generateX509CRL(key, provider, null); } /** * generate an X509 CRL, based on the current issuer and subject, * using the passed in provider for the signing. */ public X509CRL generateX509CRL( PrivateKey key, String provider, SecureRandom random) throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException { Signature sig = null; try { sig = Signature.getInstance(sigOID.getId(), provider); } catch (NoSuchAlgorithmException ex) { try { sig = Signature.getInstance(signatureAlgorithm, provider); } catch (NoSuchAlgorithmException e) { throw new SecurityException("exception creating signature: " + e.toString()); } } if (random != null) { sig.initSign(key, random); } else { sig.initSign(key); } if (extensions != null) { tbsGen.setExtensions(new X509Extensions(extOrdering, extensions)); } TBSCertList tbsCrl = tbsGen.generateTBSCertList(); try { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); dOut.writeObject(tbsCrl); sig.update(bOut.toByteArray()); } catch (Exception e) { throw new SecurityException("exception encoding TBS cert - " + e); } // Construct the CRL ASN1EncodableVector v = new ASN1EncodableVector(); v.add(tbsCrl); v.add(sigAlgId); v.add(new DERBitString(sig.sign())); return new X509CRLObject(new CertificateList(new DERSequence(v))); } } azureus-4.3.0.6/org/bouncycastle/jce/X509V3CertificateGenerator.java0000644000175000017500000002430010061400654024407 0ustar adrianadrianpackage org.bouncycastle.jce; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.SignatureException; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Hashtable; import java.util.Vector; import org.bouncycastle.asn1.*; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.TBSCertificateStructure; import org.bouncycastle.asn1.x509.Time; import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator; import org.bouncycastle.asn1.x509.X509CertificateStructure; import org.bouncycastle.asn1.x509.X509Extension; import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.asn1.x509.X509Name; import org.bouncycastle.jce.provider.X509CertificateObject; /** * class to produce an X.509 Version 3 certificate. */ public class X509V3CertificateGenerator { private V3TBSCertificateGenerator tbsGen; private DERObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; private Hashtable extensions = null; private Vector extOrdering = null; private static Hashtable algorithms = new Hashtable(); static { algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2")); algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2")); algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4")); algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4")); algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("RIPEMD160WITHRSAENCRYPTION", new DERObjectIdentifier("1.3.36.3.3.1.2")); algorithms.put("RIPEMD160WITHRSA", new DERObjectIdentifier("1.3.36.3.3.1.2")); algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3")); algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3")); algorithms.put("SHA1WITHECDSA", new DERObjectIdentifier("1.2.840.10045.4.1")); algorithms.put("ECDSAWITHSHA1", new DERObjectIdentifier("1.2.840.10045.4.1")); } public X509V3CertificateGenerator() { tbsGen = new V3TBSCertificateGenerator(); } /** * reset the generator */ public void reset() { tbsGen = new V3TBSCertificateGenerator(); extensions = null; extOrdering = null; } /** * set the serial number for the certificate. */ public void setSerialNumber( BigInteger serialNumber) { tbsGen.setSerialNumber(new DERInteger(serialNumber)); } /** * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the * certificate. */ public void setIssuerDN( X509Name issuer) { tbsGen.setIssuer(issuer); } public void setNotBefore( Date date) { tbsGen.setStartDate(new Time(date)); } public void setNotAfter( Date date) { tbsGen.setEndDate(new Time(date)); } /** * Set the subject distinguished name. The subject describes the entity associated with the public key. */ public void setSubjectDN( X509Name subject) { tbsGen.setSubject(subject); } public void setPublicKey( PublicKey key) { try { tbsGen.setSubjectPublicKeyInfo(new SubjectPublicKeyInfo((ASN1Sequence)new DERInputStream( new ByteArrayInputStream(key.getEncoded())).readObject())); } catch (Exception e) { throw new IllegalArgumentException("unable to process key - " + e.toString()); } } public void setSignatureAlgorithm( String signatureAlgorithm) { this.signatureAlgorithm = signatureAlgorithm; sigOID = (DERObjectIdentifier)algorithms.get(signatureAlgorithm.toUpperCase()); if (sigOID == null) { throw new IllegalArgumentException("Unknown signature type requested"); } sigAlgId = new AlgorithmIdentifier(this.sigOID, new DERNull()); tbsGen.setSignature(sigAlgId); } /** * add a given extension field for the standard extensions tag (tag 3) */ public void addExtension( String OID, boolean critical, DEREncodable value) { this.addExtension(new DERObjectIdentifier(OID), critical, value); } /** * add a given extension field for the standard extensions tag (tag 3) */ public void addExtension( DERObjectIdentifier OID, boolean critical, DEREncodable value) { if (extensions == null) { extensions = new Hashtable(); extOrdering = new Vector(); } ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(value); } catch (IOException e) { throw new IllegalArgumentException("error encoding value: " + e); } this.addExtension(OID, critical, bOut.toByteArray()); } /** * add a given extension field for the standard extensions tag (tag 3) * The value parameter becomes the contents of the octet string associated * with the extension. */ public void addExtension( String OID, boolean critical, byte[] value) { this.addExtension(new DERObjectIdentifier(OID), critical, value); } /** * add a given extension field for the standard extensions tag (tag 3) */ public void addExtension( DERObjectIdentifier OID, boolean critical, byte[] value) { if (extensions == null) { extensions = new Hashtable(); extOrdering = new Vector(); } extensions.put(OID, new X509Extension(critical, new DEROctetString(value))); extOrdering.addElement(OID); } /** * generate an X509 certificate, based on the current issuer and subject * using the default provider "BC". */ public X509Certificate generateX509Certificate( PrivateKey key) throws SecurityException, SignatureException, InvalidKeyException { try { return generateX509Certificate(key, "BC", null); } catch (NoSuchProviderException e) { throw new SecurityException("BC provider not installed!"); } } /** * generate an X509 certificate, based on the current issuer and subject * using the default provider "BC", and the passed in source of randomness * (if required). */ public X509Certificate generateX509Certificate( PrivateKey key, SecureRandom random) throws SecurityException, SignatureException, InvalidKeyException { try { return generateX509Certificate(key, "BC", random); } catch (NoSuchProviderException e) { throw new SecurityException("BC provider not installed!"); } } /** * generate an X509 certificate, based on the current issuer and subject, * using the passed in provider for the signing. */ public X509Certificate generateX509Certificate( PrivateKey key, String provider) throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException { return generateX509Certificate(key, provider, null); } /** * generate an X509 certificate, based on the current issuer and subject, * using the passed in provider for the signing and the supplied source * of randomness, if required. */ public X509Certificate generateX509Certificate( PrivateKey key, String provider, SecureRandom random) throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException { Signature sig = null; if (sigOID == null) { throw new IllegalStateException("no signature algorithm specified"); } try { sig = Signature.getInstance(sigOID.getId(), provider); } catch (NoSuchAlgorithmException ex) { try { sig = Signature.getInstance(signatureAlgorithm, provider); } catch (NoSuchAlgorithmException e) { throw new SecurityException("exception creating signature: " + e.toString()); } } if (random != null) { sig.initSign(key, random); } else { sig.initSign(key); } if (extensions != null) { tbsGen.setExtensions(new X509Extensions(extOrdering, extensions)); } TBSCertificateStructure tbsCert = tbsGen.generateTBSCertificate(); try { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); dOut.writeObject(tbsCert); sig.update(bOut.toByteArray()); } catch (Exception e) { throw new SecurityException("exception encoding TBS cert - " + e); } ASN1EncodableVector v = new ASN1EncodableVector(); v.add(tbsCert); v.add(sigAlgId); v.add(new DERBitString(sig.sign())); return new X509CertificateObject(new X509CertificateStructure(new DERSequence(v))); } } azureus-4.3.0.6/org/bouncycastle/jce/ECNamedCurveTable.java0000644000175000017500000000263610407566336022756 0ustar adrianadrianpackage org.bouncycastle.jce; import java.util.Enumeration; import org.bouncycastle.asn1.x9.X962NamedCurves; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; /** * a table of locally supported named curves. */ public class ECNamedCurveTable { /** * return a parameter spec representing the passed in named * curve. The routine returns null if the curve is not present. * * @param name the name of the curve requested * @return a parameter spec for the curve, null if it is not available. */ public static ECNamedCurveParameterSpec getParameterSpec( String name) { X9ECParameters ecP = X962NamedCurves.getByName(name); if (ecP == null) { return null; } return new ECNamedCurveParameterSpec( name, ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed()); } /** * return an enumeration of the names of the available curves. * * @return an enumeration of the names of the available curves. */ public static Enumeration getNames() { return X962NamedCurves.getNames(); } } azureus-4.3.0.6/org/bouncycastle/jce/X509KeyUsage.java0000644000175000017500000000335210061400654021626 0ustar adrianadrianpackage org.bouncycastle.jce; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.x509.KeyUsage; /** * A holding class for constructing an X509 Key Usage extension. * *

       *    id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
       *
       *    KeyUsage ::= BIT STRING {
       *         digitalSignature        (0),
       *         nonRepudiation          (1),
       *         keyEncipherment         (2),
       *         dataEncipherment        (3),
       *         keyAgreement            (4),
       *         keyCertSign             (5),
       *         cRLSign                 (6),
       *         encipherOnly            (7),
       *         decipherOnly            (8) }
       * 
      */ public class X509KeyUsage implements DEREncodable { public static final int digitalSignature = (1 << 7); public static final int nonRepudiation = (1 << 6); public static final int keyEncipherment = (1 << 5); public static final int dataEncipherment = (1 << 4); public static final int keyAgreement = (1 << 3); public static final int keyCertSign = (1 << 2); public static final int cRLSign = (1 << 1); public static final int encipherOnly = (1 << 0); public static final int decipherOnly = (1 << 15); private int usage = 0; /** * Basic constructor. * * @param usage - the bitwise OR of the Key Usage flags giving the * allowed uses for the key. * e.g. (X509KeyUsage.keyEncipherment | X509KeyUsage.dataEncipherment) */ public X509KeyUsage( int usage) { this.usage = usage; } public DERObject getDERObject() { return new KeyUsage(usage); } } azureus-4.3.0.6/org/bouncycastle/jce/interfaces/0000755000175000017500000000000011310377634021011 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/jce/interfaces/ElGamalKey.java0000644000175000017500000000025710061400656023624 0ustar adrianadrianpackage org.bouncycastle.jce.interfaces; import org.bouncycastle.jce.spec.ElGamalParameterSpec; public interface ElGamalKey { public ElGamalParameterSpec getParams(); } azureus-4.3.0.6/org/bouncycastle/jce/interfaces/ECPublicKey.java0000644000175000017500000000046410061400656023750 0ustar adrianadrianpackage org.bouncycastle.jce.interfaces; import java.security.PublicKey; import org.bouncycastle.math.ec.ECPoint; /** * interface for elliptic curve public keys. */ public interface ECPublicKey extends ECKey, PublicKey { /** * return the public point Q */ public ECPoint getQ(); } azureus-4.3.0.6/org/bouncycastle/jce/interfaces/ElGamalPublicKey.java0000644000175000017500000000031610061400656024757 0ustar adrianadrianpackage org.bouncycastle.jce.interfaces; import java.math.BigInteger; import java.security.PublicKey; public interface ElGamalPublicKey extends ElGamalKey, PublicKey { public BigInteger getY(); } azureus-4.3.0.6/org/bouncycastle/jce/interfaces/BCKeyStore.java0000644000175000017500000000043410061400656023620 0ustar adrianadrianpackage org.bouncycastle.jce.interfaces; import java.security.SecureRandom; /** * all BC provider keystores implement this interface. */ public interface BCKeyStore { /** * set the random source for the key store */ public void setRandom(SecureRandom random); } azureus-4.3.0.6/org/bouncycastle/jce/interfaces/IESKey.java0000644000175000017500000000066310061400656022743 0ustar adrianadrianpackage org.bouncycastle.jce.interfaces; import java.security.Key; import java.security.PrivateKey; import java.security.PublicKey; /** * key pair for use with an integrated encryptor */ public interface IESKey extends Key { /** * return the intended recipient's/sender's public key. */ public PublicKey getPublic(); /** * return the local private key. */ public PrivateKey getPrivate(); } azureus-4.3.0.6/org/bouncycastle/jce/interfaces/ECPrivateKey.java0000644000175000017500000000046010061400656024140 0ustar adrianadrianpackage org.bouncycastle.jce.interfaces; import java.math.BigInteger; import java.security.PrivateKey; /** * interface for Elliptic Curve Private keys. */ public interface ECPrivateKey extends ECKey, PrivateKey { /** * return the private value D. */ public BigInteger getD(); } azureus-4.3.0.6/org/bouncycastle/jce/interfaces/ElGamalPrivateKey.java0000644000175000017500000000032110061400656025147 0ustar adrianadrianpackage org.bouncycastle.jce.interfaces; import java.math.BigInteger; import java.security.PrivateKey; public interface ElGamalPrivateKey extends ElGamalKey, PrivateKey { public BigInteger getX(); } azureus-4.3.0.6/org/bouncycastle/jce/interfaces/PKCS12BagAttributeCarrier.java0000644000175000017500000000101510061400656026353 0ustar adrianadrianpackage org.bouncycastle.jce.interfaces; import java.util.Enumeration; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObjectIdentifier; /** * allow us to set attributes on objects that can go into a PKCS12 store. */ public interface PKCS12BagAttributeCarrier { public void setBagAttribute( DERObjectIdentifier oid, DEREncodable attribute); public DEREncodable getBagAttribute( DERObjectIdentifier oid); public Enumeration getBagAttributeKeys(); } azureus-4.3.0.6/org/bouncycastle/jce/interfaces/ECKey.java0000644000175000017500000000050710061400656022607 0ustar adrianadrianpackage org.bouncycastle.jce.interfaces; import org.bouncycastle.jce.spec.ECParameterSpec; /** * generic interface for an Elliptic Curve Key. */ public interface ECKey { /** * return a parameter specification representing the EC domain parameters * for the key. */ public ECParameterSpec getParams(); } azureus-4.3.0.6/org/bouncycastle/jce/PKCS7SignedData.java0000644000175000017500000004453410350013254022302 0ustar adrianadrianpackage org.bouncycastle.jce; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CRL; import java.security.cert.CRLException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.bouncycastle.asn1.*; import org.bouncycastle.asn1.pkcs.ContentInfo; import org.bouncycastle.asn1.pkcs.IssuerAndSerialNumber; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.pkcs.SignedData; import org.bouncycastle.asn1.pkcs.SignerInfo; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.CertificateList; import org.bouncycastle.asn1.x509.X509CertificateStructure; import org.bouncycastle.asn1.x509.X509Name; import org.bouncycastle.jce.provider.X509CRLObject; import org.bouncycastle.jce.provider.X509CertificateObject; /** * Represents a PKCS#7 object - specifically the "Signed Data" * type. *

      * How to use it? To verify a signature, do: *

       * PKCS7SignedData pkcs7 = new PKCS7SignedData(der_bytes);		// Create it
       * pkcs7.update(bytes, 0, bytes.length);	// Update checksum
       * boolean verified = pkcs7.verify();		// Does it add up?
       *
       * To sign, do this:
       * PKCS7SignedData pkcs7 = new PKCS7SignedData(privKey, certChain, "MD5");
       * pkcs7.update(bytes, 0, bytes.length);	// Update checksum
       * pkcs7.sign();				// Create digest
       *
       * bytes = pkcs7.getEncoded();			// Write it somewhere
       * 
      *

      * This class is pretty close to obsolete, for a much better (and more complete) * implementation of PKCS7 have a look at the org.bouncycastle.cms package. */ public class PKCS7SignedData implements PKCSObjectIdentifiers { private int version, signerversion; private Set digestalgos; private Collection certs, crls; private X509Certificate signCert; private byte[] digest; private String digestAlgorithm, digestEncryptionAlgorithm; private Signature sig; private transient PrivateKey privKey; private final String ID_PKCS7_DATA = "1.2.840.113549.1.7.1"; private final String ID_PKCS7_SIGNED_DATA = "1.2.840.113549.1.7.2"; private final String ID_MD5 = "1.2.840.113549.2.5"; private final String ID_MD2 = "1.2.840.113549.2.2"; private final String ID_SHA1 = "1.3.14.3.2.26"; private final String ID_RSA = "1.2.840.113549.1.1.1"; private final String ID_DSA = "1.2.840.10040.4.1"; /** * Read an existing PKCS#7 object from a DER encoded byte array using * the BC provider. */ public PKCS7SignedData( byte[] in) throws SecurityException, CRLException, InvalidKeyException, CertificateException, NoSuchProviderException, NoSuchAlgorithmException { this(in, "BC"); } /** * Read an existing PKCS#7 object from a DER encoded byte array */ public PKCS7SignedData( byte[] in, String provider) throws SecurityException, CRLException, InvalidKeyException, CertificateException, NoSuchProviderException, NoSuchAlgorithmException { DERInputStream din = new DERInputStream(new ByteArrayInputStream(in)); // // Basic checks to make sure it's a PKCS#7 SignedData Object // DERObject pkcs; try { pkcs = din.readObject(); } catch (IOException e) { throw new SecurityException("can't decode PKCS7SignedData object"); } if (!(pkcs instanceof ASN1Sequence)) { throw new SecurityException("Not a valid PKCS#7 object - not a sequence"); } ContentInfo content = ContentInfo.getInstance(pkcs); if (!content.getContentType().equals(signedData)) { throw new SecurityException("Not a valid PKCS#7 signed-data object - wrong header " + content.getContentType().getId()); } SignedData data = SignedData.getInstance(content.getContent()); certs = new ArrayList(); if (data.getCertificates() != null) { Enumeration ec = ASN1Set.getInstance(data.getCertificates()).getObjects(); while (ec.hasMoreElements()) { certs.add(new X509CertificateObject(X509CertificateStructure.getInstance(ec.nextElement()))); } } crls = new ArrayList(); if (data.getCRLs() != null) { Enumeration ec = ASN1Set.getInstance(data.getCRLs()).getObjects(); while (ec.hasMoreElements()) { crls.add(new X509CRLObject(CertificateList.getInstance(ec.nextElement()))); } } version = data.getVersion().getValue().intValue(); // // Get the digest algorithm // digestalgos = new HashSet(); Enumeration e = data.getDigestAlgorithms().getObjects(); while (e.hasMoreElements()) { ASN1Sequence s = (ASN1Sequence)e.nextElement(); DERObjectIdentifier o = (DERObjectIdentifier)s.getObjectAt(0); digestalgos.add(o.getId()); } // // Get the SignerInfo // ASN1Set signerinfos = data.getSignerInfos(); if (signerinfos.size() != 1) { throw new SecurityException("This PKCS#7 object has multiple SignerInfos - only one is supported at this time"); } SignerInfo signerInfo = SignerInfo.getInstance(signerinfos.getObjectAt(0)); signerversion = signerInfo.getVersion().getValue().intValue(); IssuerAndSerialNumber isAnds = signerInfo.getIssuerAndSerialNumber(); // // Get the signing certificate // BigInteger serialNumber = isAnds.getCertificateSerialNumber().getValue(); X509Principal issuer = new X509Principal(isAnds.getName()); for (Iterator i = certs.iterator();i.hasNext();) { X509Certificate cert = (X509Certificate)i.next(); if (serialNumber.equals(cert.getSerialNumber()) && issuer.equals(cert.getIssuerDN())) { signCert = cert; break; } } if (signCert == null) { throw new SecurityException("Can't find signing certificate with serial "+serialNumber.toString(16)); } digestAlgorithm = signerInfo.getDigestAlgorithm().getObjectId().getId(); digest = signerInfo.getEncryptedDigest().getOctets(); digestEncryptionAlgorithm = signerInfo.getDigestEncryptionAlgorithm().getObjectId().getId(); sig = Signature.getInstance(getDigestAlgorithm(), provider); sig.initVerify(signCert.getPublicKey()); } /** * Create a new PKCS#7 object from the specified key using the BC provider. * * @param the private key to be used for signing. * @param the certifiacate chain associated with the private key. * @param hashAlgorithm the hashing algorithm used to compute the message digest. Must be "MD5", "MD2", "SHA1" or "SHA" */ public PKCS7SignedData( PrivateKey privKey, Certificate[] certChain, String hashAlgorithm) throws SecurityException, InvalidKeyException, NoSuchProviderException, NoSuchAlgorithmException { this(privKey, certChain, hashAlgorithm, "BC"); } /** * Create a new PKCS#7 object from the specified key. * * @param privKey the private key to be used for signing. * @param certChain the certificate chain associated with the private key. * @param hashAlgorithm the hashing algorithm used to compute the message digest. Must be "MD5", "MD2", "SHA1" or "SHA" * @param provider the provider to use. */ public PKCS7SignedData( PrivateKey privKey, Certificate[] certChain, String hashAlgorithm, String provider) throws SecurityException, InvalidKeyException, NoSuchProviderException, NoSuchAlgorithmException { this(privKey, certChain, null, hashAlgorithm, provider); } /** * Create a new PKCS#7 object from the specified key. * * @param privKey the private key to be used for signing. * @param certChain the certificate chain associated with the private key. * @param crlList the crl list associated with the private key. * @param hashAlgorithm the hashing algorithm used to compute the message digest. Must be "MD5", "MD2", "SHA1" or "SHA" * @param provider the provider to use. */ public PKCS7SignedData( PrivateKey privKey, Certificate[] certChain, CRL[] crlList, String hashAlgorithm, String provider) throws SecurityException, InvalidKeyException, NoSuchProviderException, NoSuchAlgorithmException { this.privKey = privKey; if (hashAlgorithm.equals("MD5")) { digestAlgorithm = ID_MD5; } else if (hashAlgorithm.equals("MD2")) { digestAlgorithm = ID_MD2; } else if (hashAlgorithm.equals("SHA")) { digestAlgorithm = ID_SHA1; } else if (hashAlgorithm.equals("SHA1")) { digestAlgorithm = ID_SHA1; } else { throw new NoSuchAlgorithmException("Unknown Hash Algorithm "+hashAlgorithm); } version = signerversion = 1; certs = new ArrayList(); crls = new ArrayList(); digestalgos = new HashSet(); digestalgos.add(digestAlgorithm); // // Copy in the certificates and crls used to sign the private key. // signCert = (X509Certificate)certChain[0]; for (int i = 0;i < certChain.length;i++) { certs.add(certChain[i]); } if (crlList != null) { for (int i = 0;i < crlList.length;i++) { crls.add(crlList[i]); } } // // Now we have private key, find out what the digestEncryptionAlgorithm is. // digestEncryptionAlgorithm = privKey.getAlgorithm(); if (digestEncryptionAlgorithm.equals("RSA")) { digestEncryptionAlgorithm = ID_RSA; } else if (digestEncryptionAlgorithm.equals("DSA")) { digestEncryptionAlgorithm = ID_DSA; } else { throw new NoSuchAlgorithmException("Unknown Key Algorithm "+digestEncryptionAlgorithm); } sig = Signature.getInstance(getDigestAlgorithm(), provider); sig.initSign(privKey); } /** * Get the algorithm used to calculate the message digest */ public String getDigestAlgorithm() { String da = digestAlgorithm; String dea = digestEncryptionAlgorithm; if (digestAlgorithm.equals(ID_MD5)) { da = "MD5"; } else if (digestAlgorithm.equals(ID_MD2)) { da = "MD2"; } else if (digestAlgorithm.equals(ID_SHA1)) { da = "SHA1"; } if (digestEncryptionAlgorithm.equals(ID_RSA)) { dea = "RSA"; } else if (digestEncryptionAlgorithm.equals(ID_DSA)) { dea = "DSA"; } return da + "with" + dea; } /** * Resets the PKCS7SignedData object to it's initial state, ready * to sign or verify a new buffer. */ public void reset() { try { if (privKey==null) { sig.initVerify(signCert.getPublicKey()); } else { sig.initSign(privKey); } } catch (Exception e) { throw new RuntimeException(e.toString()); } } /** * Get the X.509 certificates associated with this PKCS#7 object */ public Certificate[] getCertificates() { return (X509Certificate[])certs.toArray(new X509Certificate[certs.size()]); } /** * Get the X.509 certificate revocation lists associated with this PKCS#7 object */ public Collection getCRLs() { return crls; } /** * Get the X.509 certificate actually used to sign the digest. */ public X509Certificate getSigningCertificate() { return signCert; } /** * Get the version of the PKCS#7 object. Always 1 */ public int getVersion() { return version; } /** * Get the version of the PKCS#7 "SignerInfo" object. Always 1 */ public int getSigningInfoVersion() { return signerversion; } /** * Update the digest with the specified byte. This method is used both for signing and verifying */ public void update(byte buf) throws SignatureException { sig.update(buf); } /** * Update the digest with the specified bytes. This method is used both for signing and verifying */ public void update(byte[] buf, int off, int len) throws SignatureException { sig.update(buf, off, len); } /** * Verify the digest */ public boolean verify() throws SignatureException { return sig.verify(digest); } /** * Get the "issuer" from the TBSCertificate bytes that are passed in */ private DERObject getIssuer(byte[] enc) { try { DERInputStream in = new DERInputStream(new ByteArrayInputStream(enc)); ASN1Sequence seq = (ASN1Sequence)in.readObject(); return (DERObject)seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 3 : 2); } catch (IOException e) { throw new Error("IOException reading from ByteArray: "+e); } } /** * return the bytes for the PKCS7SignedData object. */ public byte[] getEncoded() { try { digest = sig.sign(); // Create the set of Hash algorithms. I've assumed this is the // set of all hash agorithms used to created the digest in the // "signerInfo" structure. I may be wrong. // ASN1EncodableVector v = new ASN1EncodableVector(); for (Iterator i = digestalgos.iterator(); i.hasNext();) { AlgorithmIdentifier a = new AlgorithmIdentifier( new DERObjectIdentifier((String)i.next()), null); v.add(a); } DERSet algos = new DERSet(v); // Create the contentInfo. Empty, I didn't implement this bit // DERSequence contentinfo = new DERSequence( new DERObjectIdentifier(ID_PKCS7_DATA)); // Get all the certificates // v = new ASN1EncodableVector(); for (Iterator i = certs.iterator();i.hasNext();) { DERInputStream tempstream = new DERInputStream(new ByteArrayInputStream(((X509Certificate)i.next()).getEncoded())); v.add(tempstream.readObject()); } DERSet dercertificates = new DERSet(v); // Create signerinfo structure. // ASN1EncodableVector signerinfo = new ASN1EncodableVector(); // Add the signerInfo version // signerinfo.add(new DERInteger(signerversion)); IssuerAndSerialNumber isAnds = new IssuerAndSerialNumber( new X509Name((ASN1Sequence)getIssuer(signCert.getTBSCertificate())), new DERInteger(signCert.getSerialNumber())); signerinfo.add(isAnds); // Add the digestAlgorithm // signerinfo.add(new AlgorithmIdentifier( new DERObjectIdentifier(digestAlgorithm), new DERNull())); // // Add the digestEncryptionAlgorithm // signerinfo.add(new AlgorithmIdentifier( new DERObjectIdentifier(digestEncryptionAlgorithm), new DERNull())); // // Add the digest // signerinfo.add(new DEROctetString(digest)); // // Finally build the body out of all the components above // ASN1EncodableVector body = new ASN1EncodableVector(); body.add(new DERInteger(version)); body.add(algos); body.add(contentinfo); body.add(new DERTaggedObject(false, 0, dercertificates)); if (crls.size()>0) { v = new ASN1EncodableVector(); for (Iterator i = crls.iterator();i.hasNext();) { DERInputStream t = new DERInputStream(new ByteArrayInputStream((((X509CRL)i.next()).getEncoded()))); v.add(t.readObject()); } DERSet dercrls = new DERSet(v); body.add(new DERTaggedObject(false, 1, dercrls)); } // Only allow one signerInfo // body.add(new DERSet(new DERSequence(signerinfo))); // Now we have the body, wrap it in it's PKCS7Signed shell // and return it // ASN1EncodableVector whole = new ASN1EncodableVector(); whole.add(new DERObjectIdentifier(ID_PKCS7_SIGNED_DATA)); whole.add(new DERTaggedObject(0, new DERSequence(body))); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dout = new DEROutputStream(bOut); dout.writeObject(new DERSequence(whole)); dout.close(); return bOut.toByteArray(); } catch (Exception e) { throw new RuntimeException(e.toString()); } } } azureus-4.3.0.6/org/bouncycastle/jce/spec/0000755000175000017500000000000011310377634017620 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/jce/spec/ECPublicKeySpec.java0000644000175000017500000000111110061400650023352 0ustar adrianadrianpackage org.bouncycastle.jce.spec; import org.bouncycastle.math.ec.ECPoint; /** * Elliptic Curve public key specification */ public class ECPublicKeySpec extends ECKeySpec { private ECPoint q; /** * base constructor * * @param q the public point on the curve. * @param spec the domain parameters for the curve. */ public ECPublicKeySpec( ECPoint q, ECParameterSpec spec) { super(spec); this.q = q; } /** * return the public point q */ public ECPoint getQ() { return q; } } azureus-4.3.0.6/org/bouncycastle/jce/spec/ECParameterSpec.java0000644000175000017500000000323710061400650023416 0ustar adrianadrianpackage org.bouncycastle.jce.spec; import java.math.BigInteger; import java.security.spec.AlgorithmParameterSpec; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; /** * basic domain parameters for an Elliptic Curve public or private key. */ public class ECParameterSpec implements AlgorithmParameterSpec { private ECCurve curve; private byte[] seed; private ECPoint G; private BigInteger n; private BigInteger h; public ECParameterSpec( ECCurve curve, ECPoint G, BigInteger n) { this.curve = curve; this.G = G; this.n = n; this.h = BigInteger.valueOf(1); this.seed = null; } public ECParameterSpec( ECCurve curve, ECPoint G, BigInteger n, BigInteger h) { this.curve = curve; this.G = G; this.n = n; this.h = h; this.seed = null; } public ECParameterSpec( ECCurve curve, ECPoint G, BigInteger n, BigInteger h, byte[] seed) { this.curve = curve; this.G = G; this.n = n; this.h = h; this.seed = seed; } /** * return the curve along which the base point lies. */ public ECCurve getCurve() { return curve; } /** * return the base point we are using for these domain parameters. */ public ECPoint getG() { return G; } /** * return the order N of G */ public BigInteger getN() { return n; } /** * return the cofactor H to the order of G. */ public BigInteger getH() { return h; } /** * return the seed used to generate this curve (if available). */ public byte[] getSeed() { return seed; } } azureus-4.3.0.6/org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java0000644000175000017500000000210510061400650025361 0ustar adrianadrianpackage org.bouncycastle.jce.spec; import java.math.BigInteger; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; /** * specification signifying that the curve parameters can also be * refered to by name. */ public class ECNamedCurveParameterSpec extends ECParameterSpec { private String name; public ECNamedCurveParameterSpec( String name, ECCurve curve, ECPoint G, BigInteger n) { super(curve, G, n); this.name = name; } public ECNamedCurveParameterSpec( String name, ECCurve curve, ECPoint G, BigInteger n, BigInteger h) { super(curve, G, n, h); this.name = name; } public ECNamedCurveParameterSpec( String name, ECCurve curve, ECPoint G, BigInteger n, BigInteger h, byte[] seed) { super(curve, G, n, h, seed); this.name = name; } /** * return the name of the curve the EC domain parameters belong to. */ public String getName() { return name; } } azureus-4.3.0.6/org/bouncycastle/jce/spec/ElGamalGenParameterSpec.java0000644000175000017500000000111010061400650025047 0ustar adrianadrianpackage org.bouncycastle.jce.spec; import java.security.spec.AlgorithmParameterSpec; public class ElGamalGenParameterSpec implements AlgorithmParameterSpec { private int primeSize; /* * @param primeSize the size (in bits) of the prime modulus. */ public ElGamalGenParameterSpec( int primeSize) { this.primeSize = primeSize; } /** * Returns the size in bits of the prime modulus. * * @return the size in bits of the prime modulus */ public int getPrimeSize() { return primeSize; } } azureus-4.3.0.6/org/bouncycastle/jce/spec/ElGamalParameterSpec.java0000644000175000017500000000171010061400650024423 0ustar adrianadrianpackage org.bouncycastle.jce.spec; import java.math.BigInteger; import java.security.spec.AlgorithmParameterSpec; public class ElGamalParameterSpec implements AlgorithmParameterSpec { private BigInteger p; private BigInteger g; /** * Constructs a parameter set for Diffie-Hellman, using a prime modulus * p and a base generator g. * * @param p the prime modulus * @param g the base generator */ public ElGamalParameterSpec( BigInteger p, BigInteger g) { this.p = p; this.g = g; } /** * Returns the prime modulus p. * * @return the prime modulus p */ public BigInteger getP() { return p; } /** * Returns the base generator g. * * @return the base generator g */ public BigInteger getG() { return g; } } azureus-4.3.0.6/org/bouncycastle/jce/spec/ECPrivateKeySpec.java0000644000175000017500000000112510061400650023553 0ustar adrianadrianpackage org.bouncycastle.jce.spec; import java.math.BigInteger; /** * Elliptic Curve private key specification. */ public class ECPrivateKeySpec extends ECKeySpec { private BigInteger d; /** * base constructor * * @param d the private number for the key. * @param spec the domain parameters for the curve being used. */ public ECPrivateKeySpec( BigInteger d, ECParameterSpec spec) { super(spec); this.d = d; } /** * return the private number D */ public BigInteger getD() { return d; } } azureus-4.3.0.6/org/bouncycastle/jce/spec/ElGamalPublicKeySpec.java0000644000175000017500000000115010061400650024370 0ustar adrianadrianpackage org.bouncycastle.jce.spec; import java.math.BigInteger; /** * This class specifies an ElGamal public key with its associated parameters. * * @see ElGamalPrivateKeySpec */ public class ElGamalPublicKeySpec extends ElGamalKeySpec { private BigInteger y; public ElGamalPublicKeySpec( BigInteger y, ElGamalParameterSpec spec) { super(spec); this.y = y; } /** * Returns the public value y. * * @return the public value y */ public BigInteger getY() { return y; } } azureus-4.3.0.6/org/bouncycastle/jce/spec/IEKeySpec.java0000644000175000017500000000237510061400650022236 0ustar adrianadrianpackage org.bouncycastle.jce.spec; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.KeySpec; import org.bouncycastle.jce.interfaces.IESKey; /** * key pair for use with an integrated encryptor - together * they provide what's required to generate the message. */ public class IEKeySpec implements KeySpec, IESKey { private PublicKey pubKey; private PrivateKey privKey; /** * @param privKey our private key. * @param pubKey the public key of the sender/recipient. */ public IEKeySpec( PrivateKey privKey, PublicKey pubKey) { this.privKey = privKey; this.pubKey = pubKey; } /** * return the intended recipient's/sender's public key. */ public PublicKey getPublic() { return pubKey; } /** * return the local private key. */ public PrivateKey getPrivate() { return privKey; } /** * return "IES" */ public String getAlgorithm() { return "IES"; } /** * return null */ public String getFormat() { return null; } /** * returns null */ public byte[] getEncoded() { return null; } } azureus-4.3.0.6/org/bouncycastle/jce/spec/ElGamalPrivateKeySpec.java0000644000175000017500000000115410061400650024570 0ustar adrianadrianpackage org.bouncycastle.jce.spec; import java.math.BigInteger; /** * This class specifies an ElGamal private key with its associated parameters. * * @see ElGamalPublicKeySpec */ public class ElGamalPrivateKeySpec extends ElGamalKeySpec { private BigInteger x; public ElGamalPrivateKeySpec( BigInteger x, ElGamalParameterSpec spec) { super(spec); this.x = x; } /** * Returns the private value x. * * @return the private value x */ public BigInteger getX() { return x; } } azureus-4.3.0.6/org/bouncycastle/jce/spec/ElGamalKeySpec.java0000644000175000017500000000053310061400650023235 0ustar adrianadrianpackage org.bouncycastle.jce.spec; import java.security.spec.KeySpec; public class ElGamalKeySpec implements KeySpec { private ElGamalParameterSpec spec; public ElGamalKeySpec( ElGamalParameterSpec spec) { this.spec = spec; } public ElGamalParameterSpec getParams() { return spec; } } azureus-4.3.0.6/org/bouncycastle/jce/spec/ECKeySpec.java0000644000175000017500000000065410061400650022226 0ustar adrianadrianpackage org.bouncycastle.jce.spec; import java.security.spec.KeySpec; /** * base class for an Elliptic Curve Key Spec */ public class ECKeySpec implements KeySpec { private ECParameterSpec spec; protected ECKeySpec( ECParameterSpec spec) { this.spec = spec; } /** * return the domain parameters for the curve */ public ECParameterSpec getParams() { return spec; } } azureus-4.3.0.6/org/bouncycastle/jce/spec/IESParameterSpec.java0000644000175000017500000000221710061400650023544 0ustar adrianadrianpackage org.bouncycastle.jce.spec; import java.security.spec.AlgorithmParameterSpec; /** * Parameter spec for an integrated encryptor, as in IEEE P1363a */ public class IESParameterSpec implements AlgorithmParameterSpec { private byte[] derivation; private byte[] encoding; private int macKeySize; public IESParameterSpec( byte[] derivation, byte[] encoding, int macKeySize) { this.derivation = new byte[derivation.length]; System.arraycopy(derivation, 0, this.derivation, 0, derivation.length); this.encoding = new byte[encoding.length]; System.arraycopy(encoding, 0, this.encoding, 0, encoding.length); this.macKeySize = macKeySize; } /** * return the derivation vector. */ public byte[] getDerivationV() { return derivation; } /** * return the encoding vector. */ public byte[] getEncodingV() { return encoding; } /** * return the key size in bits for the MAC used with the message */ public int getMacKeySize() { return macKeySize; } } azureus-4.3.0.6/org/bouncycastle/math/0000755000175000017500000000000011310377334017053 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/math/ec/0000755000175000017500000000000011310377634017445 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/math/ec/Tnaf.java0000644000175000017500000006352210767602136021213 0ustar adrianadrianpackage org.bouncycastle.math.ec; import java.math.BigInteger; /** * Class holding methods for point multiplication based on the window * τ-adic nonadjacent form (WTNAF). The algorithms are based on the * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves" * by Jerome A. Solinas. The paper first appeared in the Proceedings of * Crypto 1997. */ class Tnaf { private static final BigInteger MINUS_ONE = ECConstants.ONE.negate(); private static final BigInteger MINUS_TWO = ECConstants.TWO.negate(); private static final BigInteger MINUS_THREE = ECConstants.THREE.negate(); /** * The window width of WTNAF. The standard value of 4 is slightly less * than optimal for running time, but keeps space requirements for * precomputation low. For typical curves, a value of 5 or 6 results in * a better running time. When changing this value, the * αu's must be computed differently, see * e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson, * Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004, * p. 121-122 */ public static final byte WIDTH = 4; /** * 24 */ public static final byte POW_2_WIDTH = 16; /** * The αu's for a=0 as an array * of ZTauElements. */ public static final ZTauElement[] alpha0 = { null, new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null, new ZTauElement(MINUS_THREE, MINUS_ONE), null, new ZTauElement(MINUS_ONE, MINUS_ONE), null, new ZTauElement(ECConstants.ONE, MINUS_ONE), null }; /** * The αu's for a=0 as an array * of TNAFs. */ public static final byte[][] alpha0Tnaf = { null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, 1} }; /** * The αu's for a=1 as an array * of ZTauElements. */ public static final ZTauElement[] alpha1 = {null, new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null, new ZTauElement(MINUS_THREE, ECConstants.ONE), null, new ZTauElement(MINUS_ONE, ECConstants.ONE), null, new ZTauElement(ECConstants.ONE, ECConstants.ONE), null }; /** * The αu's for a=1 as an array * of TNAFs. */ public static final byte[][] alpha1Tnaf = { null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, -1} }; /** * Computes the norm of an element λ of * Z[τ]. * @param mu The parameter μ of the elliptic curve. * @param lambda The element λ of * Z[τ]. * @return The norm of λ. */ public static BigInteger norm(final byte mu, ZTauElement lambda) { BigInteger norm; // s1 = u^2 BigInteger s1 = lambda.u.multiply(lambda.u); // s2 = u * v BigInteger s2 = lambda.u.multiply(lambda.v); // s3 = 2 * v^2 BigInteger s3 = lambda.v.multiply(lambda.v).shiftLeft(1); if (mu == 1) { norm = s1.add(s2).add(s3); } else if (mu == -1) { norm = s1.subtract(s2).add(s3); } else { throw new IllegalArgumentException("mu must be 1 or -1"); } return norm; } /** * Computes the norm of an element λ of * R[τ], where λ = u + vτ * and u and u are real numbers (elements of * R). * @param mu The parameter μ of the elliptic curve. * @param u The real part of the element λ of * R[τ]. * @param v The τ-adic part of the element * λ of R[τ]. * @return The norm of λ. */ public static SimpleBigDecimal norm(final byte mu, SimpleBigDecimal u, SimpleBigDecimal v) { SimpleBigDecimal norm; // s1 = u^2 SimpleBigDecimal s1 = u.multiply(u); // s2 = u * v SimpleBigDecimal s2 = u.multiply(v); // s3 = 2 * v^2 SimpleBigDecimal s3 = v.multiply(v).shiftLeft(1); if (mu == 1) { norm = s1.add(s2).add(s3); } else if (mu == -1) { norm = s1.subtract(s2).add(s3); } else { throw new IllegalArgumentException("mu must be 1 or -1"); } return norm; } /** * Rounds an element λ of R[τ] * to an element of Z[τ], such that their difference * has minimal norm. λ is given as * λ = λ0 + λ1τ. * @param lambda0 The component λ0. * @param lambda1 The component λ1. * @param mu The parameter μ of the elliptic curve. Must * equal 1 or -1. * @return The rounded element of Z[τ]. * @throws IllegalArgumentException if lambda0 and * lambda1 do not have same scale. */ public static ZTauElement round(SimpleBigDecimal lambda0, SimpleBigDecimal lambda1, byte mu) { int scale = lambda0.getScale(); if (lambda1.getScale() != scale) { throw new IllegalArgumentException("lambda0 and lambda1 do not " + "have same scale"); } if (!((mu == 1) || (mu == -1))) { throw new IllegalArgumentException("mu must be 1 or -1"); } BigInteger f0 = lambda0.round(); BigInteger f1 = lambda1.round(); SimpleBigDecimal eta0 = lambda0.subtract(f0); SimpleBigDecimal eta1 = lambda1.subtract(f1); // eta = 2*eta0 + mu*eta1 SimpleBigDecimal eta = eta0.add(eta0); if (mu == 1) { eta = eta.add(eta1); } else { // mu == -1 eta = eta.subtract(eta1); } // check1 = eta0 - 3*mu*eta1 // check2 = eta0 + 4*mu*eta1 SimpleBigDecimal threeEta1 = eta1.add(eta1).add(eta1); SimpleBigDecimal fourEta1 = threeEta1.add(eta1); SimpleBigDecimal check1; SimpleBigDecimal check2; if (mu == 1) { check1 = eta0.subtract(threeEta1); check2 = eta0.add(fourEta1); } else { // mu == -1 check1 = eta0.add(threeEta1); check2 = eta0.subtract(fourEta1); } byte h0 = 0; byte h1 = 0; // if eta >= 1 if (eta.compareTo(ECConstants.ONE) >= 0) { if (check1.compareTo(MINUS_ONE) < 0) { h1 = mu; } else { h0 = 1; } } else { // eta < 1 if (check2.compareTo(ECConstants.TWO) >= 0) { h1 = mu; } } // if eta < -1 if (eta.compareTo(MINUS_ONE) < 0) { if (check1.compareTo(ECConstants.ONE) >= 0) { h1 = (byte)-mu; } else { h0 = -1; } } else { // eta >= -1 if (check2.compareTo(MINUS_TWO) < 0) { h1 = (byte)-mu; } } BigInteger q0 = f0.add(BigInteger.valueOf(h0)); BigInteger q1 = f1.add(BigInteger.valueOf(h1)); return new ZTauElement(q0, q1); } /** * Approximate division by n. For an integer * k, the value λ = s k / n is * computed to c bits of accuracy. * @param k The parameter k. * @param s The curve parameter s0 or * s1. * @param vm The Lucas Sequence element Vm. * @param a The parameter a of the elliptic curve. * @param m The bit length of the finite field * Fm. * @param c The number of bits of accuracy, i.e. the scale of the returned * SimpleBigDecimal. * @return The value λ = s k / n computed to * c bits of accuracy. */ public static SimpleBigDecimal approximateDivisionByN(BigInteger k, BigInteger s, BigInteger vm, byte a, int m, int c) { int _k = (m + 5)/2 + c; BigInteger ns = k.shiftRight(m - _k - 2 + a); BigInteger gs = s.multiply(ns); BigInteger hs = gs.shiftRight(m); BigInteger js = vm.multiply(hs); BigInteger gsPlusJs = gs.add(js); BigInteger ls = gsPlusJs.shiftRight(_k-c); if (gsPlusJs.testBit(_k-c-1)) { // round up ls = ls.add(ECConstants.ONE); } return new SimpleBigDecimal(ls, c); } /** * Computes the τ-adic NAF (non-adjacent form) of an * element λ of Z[τ]. * @param mu The parameter μ of the elliptic curve. * @param lambda The element λ of * Z[τ]. * @return The τ-adic NAF of λ. */ public static byte[] tauAdicNaf(byte mu, ZTauElement lambda) { if (!((mu == 1) || (mu == -1))) { throw new IllegalArgumentException("mu must be 1 or -1"); } BigInteger norm = norm(mu, lambda); // Ceiling of log2 of the norm int log2Norm = norm.bitLength(); // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52 int maxLength = log2Norm > 30 ? log2Norm + 4 : 34; // The array holding the TNAF byte[] u = new byte[maxLength]; int i = 0; // The actual length of the TNAF int length = 0; BigInteger r0 = lambda.u; BigInteger r1 = lambda.v; while(!((r0.equals(ECConstants.ZERO)) && (r1.equals(ECConstants.ZERO)))) { // If r0 is odd if (r0.testBit(0)) { u[i] = (byte) ECConstants.TWO.subtract((r0.subtract(r1.shiftLeft(1))).mod(ECConstants.FOUR)).intValue(); // r0 = r0 - u[i] if (u[i] == 1) { r0 = r0.clearBit(0); } else { // u[i] == -1 r0 = r0.add(ECConstants.ONE); } length = i; } else { u[i] = 0; } BigInteger t = r0; BigInteger s = r0.shiftRight(1); if (mu == 1) { r0 = r1.add(s); } else { // mu == -1 r0 = r1.subtract(s); } r1 = t.shiftRight(1).negate(); i++; } length++; // Reduce the TNAF array to its actual length byte[] tnaf = new byte[length]; System.arraycopy(u, 0, tnaf, 0, length); return tnaf; } /** * Applies the operation τ() to an * ECPoint.F2m. * @param p The ECPoint.F2m to which τ() is applied. * @return τ(p) */ public static ECPoint.F2m tau(ECPoint.F2m p) { if (p.isInfinity()) { return p; } ECFieldElement x = p.getX(); ECFieldElement y = p.getY(); return new ECPoint.F2m(p.getCurve(), x.square(), y.square(), p.isCompressed()); } /** * Returns the parameter μ of the elliptic curve. * @param curve The elliptic curve from which to obtain μ. * The curve must be a Koblitz curve, i.e. a equals * 0 or 1 and b equals * 1. * @return μ of the elliptic curve. * @throws IllegalArgumentException if the given ECCurve is not a Koblitz * curve. */ public static byte getMu(ECCurve.F2m curve) { BigInteger a = curve.getA().toBigInteger(); byte mu; if (a.equals(ECConstants.ZERO)) { mu = -1; } else if (a.equals(ECConstants.ONE)) { mu = 1; } else { throw new IllegalArgumentException("No Koblitz curve (ABC), " + "TNAF multiplication not possible"); } return mu; } /** * Calculates the Lucas Sequence elements Uk-1 and * Uk or Vk-1 and * Vk. * @param mu The parameter μ of the elliptic curve. * @param k The index of the second element of the Lucas Sequence to be * returned. * @param doV If set to true, computes Vk-1 and * Vk, otherwise Uk-1 and * Uk. * @return An array with 2 elements, containing Uk-1 * and Uk or Vk-1 * and Vk. */ public static BigInteger[] getLucas(byte mu, int k, boolean doV) { if (!((mu == 1) || (mu == -1))) { throw new IllegalArgumentException("mu must be 1 or -1"); } BigInteger u0; BigInteger u1; BigInteger u2; if (doV) { u0 = ECConstants.TWO; u1 = BigInteger.valueOf(mu); } else { u0 = ECConstants.ZERO; u1 = ECConstants.ONE; } for (int i = 1; i < k; i++) { // u2 = mu*u1 - 2*u0; BigInteger s = null; if (mu == 1) { s = u1; } else { // mu == -1 s = u1.negate(); } u2 = s.subtract(u0.shiftLeft(1)); u0 = u1; u1 = u2; // System.out.println(i + ": " + u2); // System.out.println(); } BigInteger[] retVal = {u0, u1}; return retVal; } /** * Computes the auxiliary value tw. If the width is * 4, then for mu = 1, tw = 6 and for * mu = -1, tw = 10 * @param mu The parameter μ of the elliptic curve. * @param w The window width of the WTNAF. * @return the auxiliary value tw */ public static BigInteger getTw(byte mu, int w) { if (w == 4) { if (mu == 1) { return BigInteger.valueOf(6); } else { // mu == -1 return BigInteger.valueOf(10); } } else { // For w <> 4, the values must be computed BigInteger[] us = getLucas(mu, w, false); BigInteger twoToW = ECConstants.ZERO.setBit(w); BigInteger u1invert = us[1].modInverse(twoToW); BigInteger tw; tw = ECConstants.TWO.multiply(us[0]).multiply(u1invert).mod(twoToW); // System.out.println("mu = " + mu); // System.out.println("tw = " + tw); return tw; } } /** * Computes the auxiliary values s0 and * s1 used for partial modular reduction. * @param curve The elliptic curve for which to compute * s0 and s1. * @throws IllegalArgumentException if curve is not a * Koblitz curve (Anomalous Binary Curve, ABC). */ public static BigInteger[] getSi(ECCurve.F2m curve) { if (!curve.isKoblitz()) { throw new IllegalArgumentException("si is defined for Koblitz curves only"); } int m = curve.getM(); int a = curve.getA().toBigInteger().intValue(); byte mu = curve.getMu(); int h = curve.getH().intValue(); int index = m + 3 - a; BigInteger[] ui = getLucas(mu, index, false); BigInteger dividend0; BigInteger dividend1; if (mu == 1) { dividend0 = ECConstants.ONE.subtract(ui[1]); dividend1 = ECConstants.ONE.subtract(ui[0]); } else if (mu == -1) { dividend0 = ECConstants.ONE.add(ui[1]); dividend1 = ECConstants.ONE.add(ui[0]); } else { throw new IllegalArgumentException("mu must be 1 or -1"); } BigInteger[] si = new BigInteger[2]; if (h == 2) { si[0] = dividend0.shiftRight(1); si[1] = dividend1.shiftRight(1).negate(); } else if (h == 4) { si[0] = dividend0.shiftRight(2); si[1] = dividend1.shiftRight(2).negate(); } else { throw new IllegalArgumentException("h (Cofactor) must be 2 or 4"); } return si; } /** * Partial modular reduction modulo * m - 1)/(τ - 1). * @param k The integer to be reduced. * @param m The bitlength of the underlying finite field. * @param a The parameter a of the elliptic curve. * @param s The auxiliary values s0 and * s1. * @param mu The parameter μ of the elliptic curve. * @param c The precision (number of bits of accuracy) of the partial * modular reduction. * @return ρ := k partmod (τm - 1)/(τ - 1) */ public static ZTauElement partModReduction(BigInteger k, int m, byte a, BigInteger[] s, byte mu, byte c) { // d0 = s[0] + mu*s[1]; mu is either 1 or -1 BigInteger d0; if (mu == 1) { d0 = s[0].add(s[1]); } else { d0 = s[0].subtract(s[1]); } BigInteger[] v = getLucas(mu, m, true); BigInteger vm = v[1]; SimpleBigDecimal lambda0 = approximateDivisionByN( k, s[0], vm, a, m, c); SimpleBigDecimal lambda1 = approximateDivisionByN( k, s[1], vm, a, m, c); ZTauElement q = round(lambda0, lambda1, mu); // r0 = n - d0*q0 - 2*s1*q1 BigInteger r0 = k.subtract(d0.multiply(q.u)).subtract( BigInteger.valueOf(2).multiply(s[1]).multiply(q.v)); // r1 = s1*q0 - s0*q1 BigInteger r1 = s[1].multiply(q.u).subtract(s[0].multiply(q.v)); return new ZTauElement(r0, r1); } /** * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} * by a BigInteger using the reduced τ-adic * NAF (RTNAF) method. * @param p The ECPoint.F2m to multiply. * @param k The BigInteger by which to multiply p. * @return k * p */ public static ECPoint.F2m multiplyRTnaf(ECPoint.F2m p, BigInteger k) { ECCurve.F2m curve = (ECCurve.F2m) p.getCurve(); int m = curve.getM(); byte a = (byte) curve.getA().toBigInteger().intValue(); byte mu = curve.getMu(); BigInteger[] s = curve.getSi(); ZTauElement rho = partModReduction(k, m, a, s, mu, (byte)10); return multiplyTnaf(p, rho); } /** * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} * by an element λ of Z[τ] * using the τ-adic NAF (TNAF) method. * @param p The ECPoint.F2m to multiply. * @param lambda The element λ of * Z[τ]. * @return λ * p */ public static ECPoint.F2m multiplyTnaf(ECPoint.F2m p, ZTauElement lambda) { ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); byte mu = curve.getMu(); byte[] u = tauAdicNaf(mu, lambda); ECPoint.F2m q = multiplyFromTnaf(p, u); return q; } /** * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} * by an element λ of Z[τ] * using the τ-adic NAF (TNAF) method, given the TNAF * of λ. * @param p The ECPoint.F2m to multiply. * @param u The the TNAF of λ.. * @return λ * p */ public static ECPoint.F2m multiplyFromTnaf(ECPoint.F2m p, byte[] u) { ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); ECPoint.F2m q = (ECPoint.F2m) curve.getInfinity(); for (int i = u.length - 1; i >= 0; i--) { q = tau(q); if (u[i] == 1) { q = (ECPoint.F2m)q.addSimple(p); } else if (u[i] == -1) { q = (ECPoint.F2m)q.subtractSimple(p); } } return q; } /** * Computes the [τ]-adic window NAF of an element * λ of Z[τ]. * @param mu The parameter μ of the elliptic curve. * @param lambda The element λ of * Z[τ] of which to compute the * [τ]-adic NAF. * @param width The window width of the resulting WNAF. * @param pow2w 2width. * @param tw The auxiliary value tw. * @param alpha The αu's for the window width. * @return The [τ]-adic window NAF of * λ. */ public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda, byte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha) { if (!((mu == 1) || (mu == -1))) { throw new IllegalArgumentException("mu must be 1 or -1"); } BigInteger norm = norm(mu, lambda); // Ceiling of log2 of the norm int log2Norm = norm.bitLength(); // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52 int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width; // The array holding the TNAF byte[] u = new byte[maxLength]; // 2^(width - 1) BigInteger pow2wMin1 = pow2w.shiftRight(1); // Split lambda into two BigIntegers to simplify calculations BigInteger r0 = lambda.u; BigInteger r1 = lambda.v; int i = 0; // while lambda <> (0, 0) while (!((r0.equals(ECConstants.ZERO))&&(r1.equals(ECConstants.ZERO)))) { // if r0 is odd if (r0.testBit(0)) { // uUnMod = r0 + r1*tw mod 2^width BigInteger uUnMod = r0.add(r1.multiply(tw)).mod(pow2w); byte uLocal; // if uUnMod >= 2^(width - 1) if (uUnMod.compareTo(pow2wMin1) >= 0) { uLocal = (byte) uUnMod.subtract(pow2w).intValue(); } else { uLocal = (byte) uUnMod.intValue(); } // uLocal is now in [-2^(width-1), 2^(width-1)-1] u[i] = uLocal; boolean s = true; if (uLocal < 0) { s = false; uLocal = (byte)-uLocal; } // uLocal is now >= 0 if (s) { r0 = r0.subtract(alpha[uLocal].u); r1 = r1.subtract(alpha[uLocal].v); } else { r0 = r0.add(alpha[uLocal].u); r1 = r1.add(alpha[uLocal].v); } } else { u[i] = 0; } BigInteger t = r0; if (mu == 1) { r0 = r1.add(r0.shiftRight(1)); } else { // mu == -1 r0 = r1.subtract(r0.shiftRight(1)); } r1 = t.shiftRight(1).negate(); i++; } return u; } /** * Does the precomputation for WTNAF multiplication. * @param p The ECPoint for which to do the precomputation. * @param a The parameter a of the elliptic curve. * @return The precomputation array for p. */ public static ECPoint.F2m[] getPreComp(ECPoint.F2m p, byte a) { ECPoint.F2m[] pu; pu = new ECPoint.F2m[16]; pu[1] = p; byte[][] alphaTnaf; if (a == 0) { alphaTnaf = Tnaf.alpha0Tnaf; } else { // a == 1 alphaTnaf = Tnaf.alpha1Tnaf; } int precompLen = alphaTnaf.length; for (int i = 3; i < precompLen; i = i + 2) { pu[i] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]); } return pu; } } azureus-4.3.0.6/org/bouncycastle/math/ec/ECPoint.java0000644000175000017500000004232710767602136021624 0ustar adrianadrianpackage org.bouncycastle.math.ec; import java.math.BigInteger; import org.bouncycastle.asn1.x9.X9IntegerConverter; /** * base class for points on elliptic curves. */ public abstract class ECPoint { ECCurve curve; ECFieldElement x; ECFieldElement y; protected boolean withCompression; protected ECMultiplier multiplier = null; protected PreCompInfo preCompInfo = null; private static X9IntegerConverter converter = new X9IntegerConverter(); protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y) { this.curve = curve; this.x = x; this.y = y; } public ECCurve getCurve() { return curve; } public ECFieldElement getX() { return x; } public ECFieldElement getY() { return y; } public boolean isInfinity() { return x == null && y == null; } public boolean isCompressed() { return withCompression; } public boolean equals( Object other) { if (other == this) { return true; } if (!(other instanceof ECPoint)) { return false; } ECPoint o = (ECPoint)other; if (this.isInfinity()) { return o.isInfinity(); } return x.equals(o.x) && y.equals(o.y); } public int hashCode() { if (this.isInfinity()) { return 0; } return x.hashCode() ^ y.hashCode(); } // /** // * Mainly for testing. Explicitly set the ECMultiplier. // * @param multiplier The ECMultiplier to be used to multiply // * this ECPoint. // */ // public void setECMultiplier(ECMultiplier multiplier) // { // this.multiplier = multiplier; // } /** * Sets the PreCompInfo. Used by ECMultipliers * to save the precomputation for this ECPoint to store the * precomputation result for use by subsequent multiplication. * @param preCompInfo The values precomputed by the * ECMultiplier. */ void setPreCompInfo(PreCompInfo preCompInfo) { this.preCompInfo = preCompInfo; } public abstract byte[] getEncoded(); public abstract ECPoint add(ECPoint b); public abstract ECPoint subtract(ECPoint b); public abstract ECPoint negate(); public abstract ECPoint twice(); /** * Sets the default ECMultiplier, unless already set. */ synchronized void assertECMultiplier() { if (this.multiplier == null) { this.multiplier = new FpNafMultiplier(); } } /** * Multiplies this ECPoint by the given number. * @param k The multiplicator. * @return k * this. */ public ECPoint multiply(BigInteger k) { if (this.isInfinity()) { return this; } if (k.signum() == 0) { return this.curve.getInfinity(); } assertECMultiplier(); return this.multiplier.multiply(this, k, preCompInfo); } /** * Elliptic curve points over Fp */ public static class Fp extends ECPoint { /** * Create a point which encodes with point compression. * * @param curve the curve to use * @param x affine x co-ordinate * @param y affine y co-ordinate */ public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y) { this(curve, x, y, false); } /** * Create a point that encodes with or without point compresion. * * @param curve the curve to use * @param x affine x co-ordinate * @param y affine y co-ordinate * @param withCompression if true encode with point compression */ public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) { super(curve, x, y); if ((x != null && y == null) || (x == null && y != null)) { throw new IllegalArgumentException("Exactly one of the field elements is null"); } this.withCompression = withCompression; } /** * return the field element encoded with point compression. (S 4.3.6) */ public byte[] getEncoded() { if (this.isInfinity()) { return new byte[1]; } int qLength = converter.getByteLength(x); if (withCompression) { byte PC; if (this.getY().toBigInteger().testBit(0)) { PC = 0x03; } else { PC = 0x02; } byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength); byte[] PO = new byte[X.length + 1]; PO[0] = PC; System.arraycopy(X, 0, PO, 1, X.length); return PO; } else { byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength); byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), qLength); byte[] PO = new byte[X.length + Y.length + 1]; PO[0] = 0x04; System.arraycopy(X, 0, PO, 1, X.length); System.arraycopy(Y, 0, PO, X.length + 1, Y.length); return PO; } } // B.3 pg 62 public ECPoint add(ECPoint b) { if (this.isInfinity()) { return b; } if (b.isInfinity()) { return this; } // Check if b = this or b = -this if (this.x.equals(b.x)) { if (this.y.equals(b.y)) { // this = b, i.e. this must be doubled return this.twice(); } // this = -b, i.e. the result is the point at infinity return this.curve.getInfinity(); } ECFieldElement gamma = b.y.subtract(this.y).divide(b.x.subtract(this.x)); ECFieldElement x3 = gamma.square().subtract(this.x).subtract(b.x); ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); return new ECPoint.Fp(curve, x3, y3); } // B.3 pg 62 public ECPoint twice() { if (this.isInfinity()) { // Twice identity element (point at infinity) is identity return this; } if (this.y.toBigInteger().signum() == 0) { // if y1 == 0, then (x1, y1) == (x1, -y1) // and hence this = -this and thus 2(x1, y1) == infinity return this.curve.getInfinity(); } ECFieldElement TWO = this.curve.fromBigInteger(BigInteger.valueOf(2)); ECFieldElement THREE = this.curve.fromBigInteger(BigInteger.valueOf(3)); ECFieldElement gamma = this.x.square().multiply(THREE).add(curve.a).divide(y.multiply(TWO)); ECFieldElement x3 = gamma.square().subtract(this.x.multiply(TWO)); ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); return new ECPoint.Fp(curve, x3, y3, this.withCompression); } // D.3.2 pg 102 (see Note:) public ECPoint subtract(ECPoint b) { if (b.isInfinity()) { return this; } // Add -b return add(b.negate()); } public ECPoint negate() { return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression); } // TODO Uncomment this to enable WNAF algorithm for Fp point multiplication // /** // * Sets the default ECMultiplier, unless already set. // */ // synchronized void assertECMultiplier() // { // if (this.multiplier == null) // { // this.multiplier = new WNafMultiplier(); // } // } } /** * Elliptic curve points over F2m */ public static class F2m extends ECPoint { /** * @param curve base curve * @param x x point * @param y y point */ public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y) { this(curve, x, y, false); } /** * @param curve base curve * @param x x point * @param y y point * @param withCompression true if encode with point compression. */ public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) { super(curve, x, y); if ((x != null && y == null) || (x == null && y != null)) { throw new IllegalArgumentException("Exactly one of the field elements is null"); } if (x != null) { // Check if x and y are elements of the same field ECFieldElement.F2m.checkFieldElements(this.x, this.y); // Check if x and a are elements of the same field if (curve != null) { ECFieldElement.F2m.checkFieldElements(this.x, this.curve.getA()); } } this.withCompression = withCompression; } /** * @deprecated use ECCurve.getInfinity() * Constructor for point at infinity */ public F2m(ECCurve curve) { super(curve, null, null); } /* (non-Javadoc) * @see org.bouncycastle.math.ec.ECPoint#getEncoded() */ public byte[] getEncoded() { if (this.isInfinity()) { return new byte[1]; } int byteCount = converter.getByteLength(this.x); byte[] X = converter.integerToBytes(this.getX().toBigInteger(), byteCount); byte[] PO; if (withCompression) { // See X9.62 4.3.6 and 4.2.2 PO = new byte[byteCount + 1]; PO[0] = 0x02; // X9.62 4.2.2 and 4.3.6: // if x = 0 then ypTilde := 0, else ypTilde is the rightmost // bit of y * x^(-1) // if ypTilde = 0, then PC := 02, else PC := 03 // Note: PC === PO[0] if (!(this.getX().toBigInteger().equals(ECConstants.ZERO))) { if (this.getY().multiply(this.getX().invert()) .toBigInteger().testBit(0)) { // ypTilde = 1, hence PC = 03 PO[0] = 0x03; } } System.arraycopy(X, 0, PO, 1, byteCount); } else { byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), byteCount); PO = new byte[byteCount + byteCount + 1]; PO[0] = 0x04; System.arraycopy(X, 0, PO, 1, byteCount); System.arraycopy(Y, 0, PO, byteCount + 1, byteCount); } return PO; } /** * Check, if two ECPoints can be added or subtracted. * @param a The first ECPoint to check. * @param b The second ECPoint to check. * @throws IllegalArgumentException if a and b * cannot be added. */ private static void checkPoints(ECPoint a, ECPoint b) { // Check, if points are on the same curve if (!(a.curve.equals(b.curve))) { throw new IllegalArgumentException("Only points on the same " + "curve can be added or subtracted"); } // ECFieldElement.F2m.checkFieldElements(a.x, b.x); } /* (non-Javadoc) * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint) */ public ECPoint add(ECPoint b) { checkPoints(this, b); return addSimple((ECPoint.F2m)b); } /** * Adds another ECPoints.F2m to this without * checking if both points are on the same curve. Used by multiplication * algorithms, because there all points are a multiple of the same point * and hence the checks can be omitted. * @param b The other ECPoints.F2m to add to * this. * @return this + b */ public ECPoint.F2m addSimple(ECPoint.F2m b) { ECPoint.F2m other = b; if (this.isInfinity()) { return other; } if (other.isInfinity()) { return this; } ECFieldElement.F2m x2 = (ECFieldElement.F2m)other.getX(); ECFieldElement.F2m y2 = (ECFieldElement.F2m)other.getY(); // Check if other = this or other = -this if (this.x.equals(x2)) { if (this.y.equals(y2)) { // this = other, i.e. this must be doubled return (ECPoint.F2m)this.twice(); } // this = -other, i.e. the result is the point at infinity return (ECPoint.F2m)this.curve.getInfinity(); } ECFieldElement.F2m lambda = (ECFieldElement.F2m)(this.y.add(y2)).divide(this.x.add(x2)); ECFieldElement.F2m x3 = (ECFieldElement.F2m)lambda.square().add(lambda).add(this.x).add(x2).add(this.curve.getA()); ECFieldElement.F2m y3 = (ECFieldElement.F2m)lambda.multiply(this.x.add(x3)).add(x3).add(this.y); return new ECPoint.F2m(curve, x3, y3, withCompression); } /* (non-Javadoc) * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint) */ public ECPoint subtract(ECPoint b) { checkPoints(this, b); return subtractSimple((ECPoint.F2m)b); } /** * Subtracts another ECPoints.F2m from this * without checking if both points are on the same curve. Used by * multiplication algorithms, because there all points are a multiple * of the same point and hence the checks can be omitted. * @param b The other ECPoints.F2m to subtract from * this. * @return this - b */ public ECPoint.F2m subtractSimple(ECPoint.F2m b) { if (b.isInfinity()) { return this; } // Add -b return addSimple((ECPoint.F2m)b.negate()); } /* (non-Javadoc) * @see org.bouncycastle.math.ec.ECPoint#twice() */ public ECPoint twice() { if (this.isInfinity()) { // Twice identity element (point at infinity) is identity return this; } if (this.x.toBigInteger().signum() == 0) { // if x1 == 0, then (x1, y1) == (x1, x1 + y1) // and hence this = -this and thus 2(x1, y1) == infinity return this.curve.getInfinity(); } ECFieldElement.F2m lambda = (ECFieldElement.F2m)this.x.add(this.y.divide(this.x)); ECFieldElement.F2m x3 = (ECFieldElement.F2m)lambda.square().add(lambda). add(this.curve.getA()); ECFieldElement ONE = this.curve.fromBigInteger(ECConstants.ONE); ECFieldElement.F2m y3 = (ECFieldElement.F2m)this.x.square().add( x3.multiply(lambda.add(ONE))); return new ECPoint.F2m(this.curve, x3, y3, withCompression); } public ECPoint negate() { return new ECPoint.F2m(curve, this.getX(), this.getY().add(this.getX()), withCompression); } // TODO Uncomment this to enable WNAF/WTNAF F2m point multiplication // /** // * Sets the appropriate ECMultiplier, unless already set. // */ // synchronized void assertECMultiplier() // { // if (this.multiplier == null) // { // if (((ECCurve.F2m)(this.curve)).isKoblitz()) // { // this.multiplier = new WTauNafMultiplier(); // } // else // { // this.multiplier = new WNafMultiplier(); // } // } // } } } azureus-4.3.0.6/org/bouncycastle/math/ec/ECMultiplier.java0000644000175000017500000000113610767602136022652 0ustar adrianadrianpackage org.bouncycastle.math.ec; import java.math.BigInteger; /** * Interface for classes encapsulating a point multiplication algorithm * for ECPoints. */ interface ECMultiplier { /** * Multiplies the ECPoint p by k, i.e. * p is added k times to itself. * @param p The ECPoint to be multiplied. * @param k The factor by which p i multiplied. * @return p multiplied by k. */ ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo); } azureus-4.3.0.6/org/bouncycastle/math/ec/IntArray.java0000644000175000017500000003103110767602136022042 0ustar adrianadrianpackage org.bouncycastle.math.ec; import org.bouncycastle.util.Arrays; import java.math.BigInteger; class IntArray { // TODO make m fixed for the IntArray, and hence compute T once and for all private int[] m_ints; public IntArray(int intLen) { m_ints = new int[intLen]; } public IntArray(int[] ints) { m_ints = ints; } public IntArray(BigInteger bigInt) { this(bigInt, 0); } public IntArray(BigInteger bigInt, int minIntLen) { if (bigInt.signum() == -1) { throw new IllegalArgumentException("Only positive Integers allowed"); } if (bigInt.equals(ECConstants.ZERO)) { m_ints = new int[] { 0 }; return; } byte[] barr = bigInt.toByteArray(); int barrLen = barr.length; int barrStart = 0; if (barr[0] == 0) { // First byte is 0 to enforce highest (=sign) bit is zero. // In this case ignore barr[0]. barrLen--; barrStart = 1; } int intLen = (barrLen + 3) / 4; if (intLen < minIntLen) { m_ints = new int[minIntLen]; } else { m_ints = new int[intLen]; } int iarrJ = intLen - 1; int rem = barrLen % 4 + barrStart; int temp = 0; int barrI = barrStart; if (barrStart < rem) { for (; barrI < rem; barrI++) { temp <<= 8; int barrBarrI = barr[barrI]; if (barrBarrI < 0) { barrBarrI += 256; } temp |= barrBarrI; } m_ints[iarrJ--] = temp; } for (; iarrJ >= 0; iarrJ--) { temp = 0; for (int i = 0; i < 4; i++) { temp <<= 8; int barrBarrI = barr[barrI++]; if (barrBarrI < 0) { barrBarrI += 256; } temp |= barrBarrI; } m_ints[iarrJ] = temp; } } public boolean isZero() { return m_ints.length == 0 || (m_ints[0] == 0 && getUsedLength() == 0); } public int getUsedLength() { int highestIntPos = m_ints.length; if (highestIntPos < 1) { return 0; } // Check if first element will act as sentinel if (m_ints[0] != 0) { while (m_ints[--highestIntPos] == 0) { } return highestIntPos + 1; } do { if (m_ints[--highestIntPos] != 0) { return highestIntPos + 1; } } while (highestIntPos > 0); return 0; } public int bitLength() { // JDK 1.5: see Integer.numberOfLeadingZeros() int intLen = getUsedLength(); if (intLen == 0) { return 0; } int last = intLen - 1; int highest = m_ints[last]; int bits = (last << 5) + 1; // A couple of binary search steps if ((highest & 0xffff0000) != 0) { if ((highest & 0xff000000) != 0) { bits += 24; highest >>>= 24; } else { bits += 16; highest >>>= 16; } } else if (highest > 0x000000ff) { bits += 8; highest >>>= 8; } while (highest != 1) { ++bits; highest >>>= 1; } return bits; } private int[] resizedInts(int newLen) { int[] newInts = new int[newLen]; int oldLen = m_ints.length; int copyLen = oldLen < newLen ? oldLen : newLen; System.arraycopy(m_ints, 0, newInts, 0, copyLen); return newInts; } public BigInteger toBigInteger() { int usedLen = getUsedLength(); if (usedLen == 0) { return ECConstants.ZERO; } int highestInt = m_ints[usedLen - 1]; byte[] temp = new byte[4]; int barrI = 0; boolean trailingZeroBytesDone = false; for (int j = 3; j >= 0; j--) { byte thisByte = (byte) (highestInt >>> (8 * j)); if (trailingZeroBytesDone || (thisByte != 0)) { trailingZeroBytesDone = true; temp[barrI++] = thisByte; } } int barrLen = 4 * (usedLen - 1) + barrI; byte[] barr = new byte[barrLen]; for (int j = 0; j < barrI; j++) { barr[j] = temp[j]; } // Highest value int is done now for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--) { for (int j = 3; j >= 0; j--) { barr[barrI++] = (byte) (m_ints[iarrJ] >>> (8 * j)); } } return new BigInteger(1, barr); } public void shiftLeft() { int usedLen = getUsedLength(); if (usedLen == 0) { return; } if (m_ints[usedLen - 1] < 0) { // highest bit of highest used byte is set, so shifting left will // make the IntArray one byte longer usedLen++; if (usedLen > m_ints.length) { // make the m_ints one byte longer, because we need one more // byte which is not available in m_ints m_ints = resizedInts(m_ints.length + 1); } } boolean carry = false; for (int i = 0; i < usedLen; i++) { // nextCarry is true if highest bit is set boolean nextCarry = m_ints[i] < 0; m_ints[i] <<= 1; if (carry) { // set lowest bit m_ints[i] |= 1; } carry = nextCarry; } } public IntArray shiftLeft(int n) { int usedLen = getUsedLength(); if (usedLen == 0) { return this; } if (n == 0) { return this; } if (n > 31) { throw new IllegalArgumentException("shiftLeft() for max 31 bits " + ", " + n + "bit shift is not possible"); } int[] newInts = new int[usedLen + 1]; int nm32 = 32 - n; newInts[0] = m_ints[0] << n; for (int i = 1; i < usedLen; i++) { newInts[i] = (m_ints[i] << n) | (m_ints[i - 1] >>> nm32); } newInts[usedLen] = m_ints[usedLen - 1] >>> nm32; return new IntArray(newInts); } public void addShifted(IntArray other, int shift) { int usedLenOther = other.getUsedLength(); int newMinUsedLen = usedLenOther + shift; if (newMinUsedLen > m_ints.length) { m_ints = resizedInts(newMinUsedLen); //System.out.println("Resize required"); } for (int i = 0; i < usedLenOther; i++) { m_ints[i + shift] ^= other.m_ints[i]; } } public int getLength() { return m_ints.length; } public boolean testBit(int n) { // theInt = n / 32 int theInt = n >> 5; // theBit = n % 32 int theBit = n & 0x1F; int tester = 1 << theBit; return ((m_ints[theInt] & tester) != 0); } public void flipBit(int n) { // theInt = n / 32 int theInt = n >> 5; // theBit = n % 32 int theBit = n & 0x1F; int flipper = 1 << theBit; m_ints[theInt] ^= flipper; } public void setBit(int n) { // theInt = n / 32 int theInt = n >> 5; // theBit = n % 32 int theBit = n & 0x1F; int setter = 1 << theBit; m_ints[theInt] |= setter; } public IntArray multiply(IntArray other, int m) { // Lenght of c is 2m bits rounded up to the next int (32 bit) int t = (m + 31) >> 5; if (m_ints.length < t) { m_ints = resizedInts(t); } IntArray b = new IntArray(other.resizedInts(other.getLength() + 1)); IntArray c = new IntArray((m + m + 31) >> 5); // IntArray c = new IntArray(t + t); int testBit = 1; for (int k = 0; k < 32; k++) { for (int j = 0; j < t; j++) { if ((m_ints[j] & testBit) != 0) { // The kth bit of m_ints[j] is set c.addShifted(b, j); } } testBit <<= 1; b.shiftLeft(); } return c; } // public IntArray multiplyLeftToRight(IntArray other, int m) { // // Lenght of c is 2m bits rounded up to the next int (32 bit) // int t = (m + 31) / 32; // if (m_ints.length < t) { // m_ints = resizedInts(t); // } // // IntArray b = new IntArray(other.resizedInts(other.getLength() + 1)); // IntArray c = new IntArray((m + m + 31) / 32); // // IntArray c = new IntArray(t + t); // int testBit = 1 << 31; // for (int k = 31; k >= 0; k--) { // for (int j = 0; j < t; j++) { // if ((m_ints[j] & testBit) != 0) { // // The kth bit of m_ints[j] is set // c.addShifted(b, j); // } // } // testBit >>>= 1; // if (k > 0) { // c.shiftLeft(); // } // } // return c; // } // TODO note, redPol.length must be 3 for TPB and 5 for PPB public void reduce(int m, int[] redPol) { for (int i = m + m - 2; i >= m; i--) { if (testBit(i)) { int bit = i - m; flipBit(bit); flipBit(i); int l = redPol.length; while (--l >= 0) { flipBit(redPol[l] + bit); } } } m_ints = resizedInts((m + 31) >> 5); } public IntArray square(int m) { // TODO make the table static final final int[] table = { 0x0, 0x1, 0x4, 0x5, 0x10, 0x11, 0x14, 0x15, 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 }; int t = (m + 31) >> 5; if (m_ints.length < t) { m_ints = resizedInts(t); } IntArray c = new IntArray(t + t); // TODO twice the same code, put in separate private method for (int i = 0; i < t; i++) { int v0 = 0; for (int j = 0; j < 4; j++) { v0 = v0 >>> 8; int u = (m_ints[i] >>> (j * 4)) & 0xF; int w = table[u] << 24; v0 |= w; } c.m_ints[i + i] = v0; v0 = 0; int upper = m_ints[i] >>> 16; for (int j = 0; j < 4; j++) { v0 = v0 >>> 8; int u = (upper >>> (j * 4)) & 0xF; int w = table[u] << 24; v0 |= w; } c.m_ints[i + i + 1] = v0; } return c; } public boolean equals(Object o) { if (!(o instanceof IntArray)) { return false; } IntArray other = (IntArray) o; int usedLen = getUsedLength(); if (other.getUsedLength() != usedLen) { return false; } for (int i = 0; i < usedLen; i++) { if (m_ints[i] != other.m_ints[i]) { return false; } } return true; } public int hashCode() { int usedLen = getUsedLength(); int hash = 0; for (int i = 0; i < usedLen; i++) { hash ^= m_ints[i]; } return hash; } public Object clone() { return new IntArray(Arrays.clone(m_ints)); } public String toString() { int usedLen = getUsedLength(); if (usedLen == 0) { return "0"; } StringBuffer sb = new StringBuffer(Integer .toBinaryString(m_ints[usedLen - 1])); for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--) { String hexString = Integer.toBinaryString(m_ints[iarrJ]); // Add leading zeroes, except for highest significant int for (int i = hexString.length(); i < 8; i++) { hexString = "0" + hexString; } sb.append(hexString); } return sb.toString(); } } azureus-4.3.0.6/org/bouncycastle/math/ec/ECCurve.java0000644000175000017500000005160210767602136021613 0ustar adrianadrianpackage org.bouncycastle.math.ec; import java.math.BigInteger; import java.util.Random; /** * base class for an elliptic curve */ public abstract class ECCurve { ECFieldElement a, b; public abstract int getFieldSize(); public abstract ECFieldElement fromBigInteger(BigInteger x); public abstract ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression); public abstract ECPoint decodePoint(byte[] encoded); public abstract ECPoint getInfinity(); public ECFieldElement getA() { return a; } public ECFieldElement getB() { return b; } /** * Elliptic curve over Fp */ public static class Fp extends ECCurve { BigInteger q; ECPoint.Fp infinity; public Fp(BigInteger q, BigInteger a, BigInteger b) { this.q = q; this.a = fromBigInteger(a); this.b = fromBigInteger(b); this.infinity = new ECPoint.Fp(this, null, null); } public BigInteger getQ() { return q; } public int getFieldSize() { return q.bitLength(); } public ECFieldElement fromBigInteger(BigInteger x) { return new ECFieldElement.Fp(this.q, x); } public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) { return new ECPoint.Fp(this, fromBigInteger(x), fromBigInteger(y), withCompression); } /** * Decode a point on this curve from its ASN.1 encoding. The different * encodings are taken account of, including point compression for * Fp (X9.62 s 4.2.1 pg 17). * @return The decoded point. */ public ECPoint decodePoint(byte[] encoded) { ECPoint p = null; switch (encoded[0]) { // infinity case 0x00: p = getInfinity(); break; // compressed case 0x02: case 0x03: int ytilde = encoded[0] & 1; byte[] i = new byte[encoded.length - 1]; System.arraycopy(encoded, 1, i, 0, i.length); ECFieldElement x = new ECFieldElement.Fp(this.q, new BigInteger(1, i)); ECFieldElement alpha = x.multiply(x.square().add(a)).add(b); ECFieldElement beta = alpha.sqrt(); // // if we can't find a sqrt we haven't got a point on the // curve - run! // if (beta == null) { throw new RuntimeException("Invalid point compression"); } int bit0 = (beta.toBigInteger().testBit(0) ? 1 : 0); if (bit0 == ytilde) { p = new ECPoint.Fp(this, x, beta, true); } else { p = new ECPoint.Fp(this, x, new ECFieldElement.Fp(this.q, q.subtract(beta.toBigInteger())), true); } break; // uncompressed case 0x04: // hybrid case 0x06: case 0x07: byte[] xEnc = new byte[(encoded.length - 1) / 2]; byte[] yEnc = new byte[(encoded.length - 1) / 2]; System.arraycopy(encoded, 1, xEnc, 0, xEnc.length); System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length); p = new ECPoint.Fp(this, new ECFieldElement.Fp(this.q, new BigInteger(1, xEnc)), new ECFieldElement.Fp(this.q, new BigInteger(1, yEnc))); break; default: throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16)); } return p; } public ECPoint getInfinity() { return infinity; } public boolean equals( Object anObject) { if (anObject == this) { return true; } if (!(anObject instanceof ECCurve.Fp)) { return false; } ECCurve.Fp other = (ECCurve.Fp) anObject; return this.q.equals(other.q) && a.equals(other.a) && b.equals(other.b); } public int hashCode() { return a.hashCode() ^ b.hashCode() ^ q.hashCode(); } } /** * Elliptic curves over F2m. The Weierstrass equation is given by * y2 + xy = x3 + ax2 + b. */ public static class F2m extends ECCurve { /** * The exponent m of F2m. */ private int m; // can't be final - JDK 1.1 /** * TPB: The integer k where xm + * xk + 1 represents the reduction polynomial * f(z).
      * PPB: The integer k1 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z).
      */ private int k1; // can't be final - JDK 1.1 /** * TPB: Always set to 0
      * PPB: The integer k2 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z).
      */ private int k2; // can't be final - JDK 1.1 /** * TPB: Always set to 0
      * PPB: The integer k3 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z).
      */ private int k3; // can't be final - JDK 1.1 /** * The order of the base point of the curve. */ private BigInteger n; // can't be final - JDK 1.1 /** * The cofactor of the curve. */ private BigInteger h; // can't be final - JDK 1.1 /** * The point at infinity on this curve. */ private ECPoint.F2m infinity; // can't be final - JDK 1.1 /** * The parameter μ of the elliptic curve if this is * a Koblitz curve. */ private byte mu = 0; /** * The auxiliary values s0 and * s1 used for partial modular reduction for * Koblitz curves. */ private BigInteger[] si = null; /** * Constructor for Trinomial Polynomial Basis (TPB). * @param m The exponent m of * F2m. * @param k The integer k where xm + * xk + 1 represents the reduction * polynomial f(z). * @param a The coefficient a in the Weierstrass equation * for non-supersingular elliptic curves over * F2m. * @param b The coefficient b in the Weierstrass equation * for non-supersingular elliptic curves over * F2m. */ public F2m( int m, int k, BigInteger a, BigInteger b) { this(m, k, 0, 0, a, b, null, null); } /** * Constructor for Trinomial Polynomial Basis (TPB). * @param m The exponent m of * F2m. * @param k The integer k where xm + * xk + 1 represents the reduction * polynomial f(z). * @param a The coefficient a in the Weierstrass equation * for non-supersingular elliptic curves over * F2m. * @param b The coefficient b in the Weierstrass equation * for non-supersingular elliptic curves over * F2m. * @param n The order of the main subgroup of the elliptic curve. * @param h The cofactor of the elliptic curve, i.e. * #Ea(F2m) = h * n. */ public F2m( int m, int k, BigInteger a, BigInteger b, BigInteger n, BigInteger h) { this(m, k, 0, 0, a, b, n, h); } /** * Constructor for Pentanomial Polynomial Basis (PPB). * @param m The exponent m of * F2m. * @param k1 The integer k1 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z). * @param k2 The integer k2 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z). * @param k3 The integer k3 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z). * @param a The coefficient a in the Weierstrass equation * for non-supersingular elliptic curves over * F2m. * @param b The coefficient b in the Weierstrass equation * for non-supersingular elliptic curves over * F2m. */ public F2m( int m, int k1, int k2, int k3, BigInteger a, BigInteger b) { this(m, k1, k2, k3, a, b, null, null); } /** * Constructor for Pentanomial Polynomial Basis (PPB). * @param m The exponent m of * F2m. * @param k1 The integer k1 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z). * @param k2 The integer k2 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z). * @param k3 The integer k3 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z). * @param a The coefficient a in the Weierstrass equation * for non-supersingular elliptic curves over * F2m. * @param b The coefficient b in the Weierstrass equation * for non-supersingular elliptic curves over * F2m. * @param n The order of the main subgroup of the elliptic curve. * @param h The cofactor of the elliptic curve, i.e. * #Ea(F2m) = h * n. */ public F2m( int m, int k1, int k2, int k3, BigInteger a, BigInteger b, BigInteger n, BigInteger h) { this.m = m; this.k1 = k1; this.k2 = k2; this.k3 = k3; this.n = n; this.h = h; if (k1 == 0) { throw new IllegalArgumentException("k1 must be > 0"); } if (k2 == 0) { if (k3 != 0) { throw new IllegalArgumentException("k3 must be 0 if k2 == 0"); } } else { if (k2 <= k1) { throw new IllegalArgumentException("k2 must be > k1"); } if (k3 <= k2) { throw new IllegalArgumentException("k3 must be > k2"); } } this.a = fromBigInteger(a); this.b = fromBigInteger(b); this.infinity = new ECPoint.F2m(this, null, null); } public int getFieldSize() { return m; } public ECFieldElement fromBigInteger(BigInteger x) { return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x); } public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) { return new ECPoint.F2m(this, fromBigInteger(x), fromBigInteger(y), withCompression); } /* (non-Javadoc) * @see org.bouncycastle.math.ec.ECCurve#decodePoint(byte[]) */ public ECPoint decodePoint(byte[] encoded) { ECPoint p = null; switch (encoded[0]) { // infinity case 0x00: p = getInfinity(); break; // compressed case 0x02: case 0x03: byte[] enc = new byte[encoded.length - 1]; System.arraycopy(encoded, 1, enc, 0, enc.length); if (encoded[0] == 0x02) { p = decompressPoint(enc, 0); } else { p = decompressPoint(enc, 1); } break; // uncompressed case 0x04: // hybrid case 0x06: case 0x07: byte[] xEnc = new byte[(encoded.length - 1) / 2]; byte[] yEnc = new byte[(encoded.length - 1) / 2]; System.arraycopy(encoded, 1, xEnc, 0, xEnc.length); System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length); p = new ECPoint.F2m(this, new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, new BigInteger(1, xEnc)), new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, new BigInteger(1, yEnc)), false); break; default: throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16)); } return p; } public ECPoint getInfinity() { return infinity; } /** * Returns true if this is a Koblitz curve (ABC curve). * @return true if this is a Koblitz curve (ABC curve), false otherwise */ public boolean isKoblitz() { return ((n != null) && (h != null) && ((a.toBigInteger().equals(ECConstants.ZERO)) || (a.toBigInteger().equals(ECConstants.ONE))) && (b.toBigInteger().equals(ECConstants.ONE))); } /** * Returns the parameter μ of the elliptic curve. * @return μ of the elliptic curve. * @throws IllegalArgumentException if the given ECCurve is not a * Koblitz curve. */ synchronized byte getMu() { if (mu == 0) { mu = Tnaf.getMu(this); } return mu; } /** * @return the auxiliary values s0 and * s1 used for partial modular reduction for * Koblitz curves. */ synchronized BigInteger[] getSi() { if (si == null) { si = Tnaf.getSi(this); } return si; } /** * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). * * @param xEnc * The encoding of field element xp. * @param ypBit * ~yp, an indication bit for the decompression of yp. * @return the decompressed point. */ private ECPoint decompressPoint( byte[] xEnc, int ypBit) { ECFieldElement xp = new ECFieldElement.F2m( this.m, this.k1, this.k2, this.k3, new BigInteger(1, xEnc)); ECFieldElement yp = null; if (xp.toBigInteger().equals(ECConstants.ZERO)) { yp = (ECFieldElement.F2m)b; for (int i = 0; i < m - 1; i++) { yp = yp.square(); } } else { ECFieldElement beta = xp.add(a).add( b.multiply(xp.square().invert())); ECFieldElement z = solveQuadradicEquation(beta); if (z == null) { throw new RuntimeException("Invalid point compression"); } int zBit = 0; if (z.toBigInteger().testBit(0)) { zBit = 1; } if (zBit != ypBit) { z = z.add(new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, ECConstants.ONE)); } yp = xp.multiply(z); } return new ECPoint.F2m(this, xp, yp); } /** * Solves a quadratic equation z2 + z = beta(X9.62 * D.1.6) The other solution is z + 1. * * @param beta * The value to solve the qradratic equation for. * @return the solution for z2 + z = beta or * null if no solution exists. */ private ECFieldElement solveQuadradicEquation(ECFieldElement beta) { ECFieldElement zeroElement = new ECFieldElement.F2m( this.m, this.k1, this.k2, this.k3, ECConstants.ZERO); if (beta.toBigInteger().equals(ECConstants.ZERO)) { return zeroElement; } ECFieldElement z = null; ECFieldElement gamma = zeroElement; Random rand = new Random(); do { ECFieldElement t = new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, new BigInteger(m, rand)); z = zeroElement; ECFieldElement w = beta; for (int i = 1; i <= m - 1; i++) { ECFieldElement w2 = w.square(); z = z.square().add(w2.multiply(t)); w = w2.add(beta); } if (!w.toBigInteger().equals(ECConstants.ZERO)) { return null; } gamma = z.square().add(z); } while (gamma.toBigInteger().equals(ECConstants.ZERO)); return z; } public boolean equals( Object anObject) { if (anObject == this) { return true; } if (!(anObject instanceof ECCurve.F2m)) { return false; } ECCurve.F2m other = (ECCurve.F2m)anObject; return (this.m == other.m) && (this.k1 == other.k1) && (this.k2 == other.k2) && (this.k3 == other.k3) && a.equals(other.a) && b.equals(other.b); } public int hashCode() { return this.a.hashCode() ^ this.b.hashCode() ^ m ^ k1 ^ k2 ^ k3; } public int getM() { return m; } /** * Return true if curve uses a Trinomial basis. * * @return true if curve Trinomial, false otherwise. */ public boolean isTrinomial() { return k2 == 0 && k3 == 0; } public int getK1() { return k1; } public int getK2() { return k2; } public int getK3() { return k3; } public BigInteger getN() { return n; } public BigInteger getH() { return h; } } } azureus-4.3.0.6/org/bouncycastle/math/ec/ECConstants.java0000644000175000017500000000064610767602136022505 0ustar adrianadrianpackage org.bouncycastle.math.ec; import java.math.BigInteger; public interface ECConstants { public static final BigInteger ZERO = BigInteger.valueOf(0); public static final BigInteger ONE = BigInteger.valueOf(1); public static final BigInteger TWO = BigInteger.valueOf(2); public static final BigInteger THREE = BigInteger.valueOf(3); public static final BigInteger FOUR = BigInteger.valueOf(4); } azureus-4.3.0.6/org/bouncycastle/math/ec/ECFieldElement.java0000644000175000017500000011527110767602136023067 0ustar adrianadrianpackage org.bouncycastle.math.ec; import java.math.BigInteger; import java.util.Random; public abstract class ECFieldElement implements ECConstants { public abstract BigInteger toBigInteger(); public abstract String getFieldName(); public abstract int getFieldSize(); public abstract ECFieldElement add(ECFieldElement b); public abstract ECFieldElement subtract(ECFieldElement b); public abstract ECFieldElement multiply(ECFieldElement b); public abstract ECFieldElement divide(ECFieldElement b); public abstract ECFieldElement negate(); public abstract ECFieldElement square(); public abstract ECFieldElement invert(); public abstract ECFieldElement sqrt(); public String toString() { return this.toBigInteger().toString(2); } public static class Fp extends ECFieldElement { BigInteger x; BigInteger q; public Fp(BigInteger q, BigInteger x) { this.x = x; if (x.compareTo(q) >= 0) { throw new IllegalArgumentException("x value too large in field element"); } this.q = q; } public BigInteger toBigInteger() { return x; } /** * return the field name for this field. * * @return the string "Fp". */ public String getFieldName() { return "Fp"; } public int getFieldSize() { return q.bitLength(); } public BigInteger getQ() { return q; } public ECFieldElement add(ECFieldElement b) { return new Fp(q, x.add(b.toBigInteger()).mod(q)); } public ECFieldElement subtract(ECFieldElement b) { return new Fp(q, x.subtract(b.toBigInteger()).mod(q)); } public ECFieldElement multiply(ECFieldElement b) { return new Fp(q, x.multiply(b.toBigInteger()).mod(q)); } public ECFieldElement divide(ECFieldElement b) { return new Fp(q, x.multiply(b.toBigInteger().modInverse(q)).mod(q)); } public ECFieldElement negate() { return new Fp(q, x.negate().mod(q)); } public ECFieldElement square() { return new Fp(q, x.multiply(x).mod(q)); } public ECFieldElement invert() { return new Fp(q, x.modInverse(q)); } // D.1.4 91 /** * return a sqrt root - the routine verifies that the calculation * returns the right value - if none exists it returns null. */ public ECFieldElement sqrt() { if (!q.testBit(0)) { throw new RuntimeException("not done yet"); } // p mod 4 == 3 if (q.testBit(1)) { // z = g^(u+1) + p, p = 4u + 3 ECFieldElement z = new Fp(q, x.modPow(q.shiftRight(2).add(ONE), q)); return z.square().equals(this) ? z : null; } // p mod 4 == 1 BigInteger qMinusOne = q.subtract(ECConstants.ONE); BigInteger legendreExponent = qMinusOne.shiftRight(1); if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) { return null; } BigInteger u = qMinusOne.shiftRight(2); BigInteger k = u.shiftLeft(1).add(ECConstants.ONE); BigInteger Q = this.x; BigInteger fourQ = Q.shiftLeft(2).mod(q); BigInteger U, V; Random rand = new Random(); do { BigInteger P; do { P = new BigInteger(q.bitLength(), rand); } while (P.compareTo(q) >= 0 || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne))); BigInteger[] result = lucasSequence(q, P, Q, k); U = result[0]; V = result[1]; if (V.multiply(V).mod(q).equals(fourQ)) { // Integer division by 2, mod q if (V.testBit(0)) { V = V.add(q); } V = V.shiftRight(1); //assert V.multiply(V).mod(q).equals(x); return new ECFieldElement.Fp(q, V); } } while (U.equals(ECConstants.ONE) || U.equals(qMinusOne)); return null; // BigInteger qMinusOne = q.subtract(ECConstants.ONE); // BigInteger legendreExponent = qMinusOne.shiftRight(1); //divide(ECConstants.TWO); // if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) // { // return null; // } // // Random rand = new Random(); // BigInteger fourX = x.shiftLeft(2); // // BigInteger r; // do // { // r = new BigInteger(q.bitLength(), rand); // } // while (r.compareTo(q) >= 0 // || !(r.multiply(r).subtract(fourX).modPow(legendreExponent, q).equals(qMinusOne))); // // BigInteger n1 = qMinusOne.shiftRight(2); //.divide(ECConstants.FOUR); // BigInteger n2 = n1.add(ECConstants.ONE); //q.add(ECConstants.THREE).divide(ECConstants.FOUR); // // BigInteger wOne = WOne(r, x, q); // BigInteger wSum = W(n1, wOne, q).add(W(n2, wOne, q)).mod(q); // BigInteger twoR = r.shiftLeft(1); //ECConstants.TWO.multiply(r); // // BigInteger root = twoR.modPow(q.subtract(ECConstants.TWO), q) // .multiply(x).mod(q) // .multiply(wSum).mod(q); // // return new Fp(q, root); } // private static BigInteger W(BigInteger n, BigInteger wOne, BigInteger p) // { // if (n.equals(ECConstants.ONE)) // { // return wOne; // } // boolean isEven = !n.testBit(0); // n = n.shiftRight(1);//divide(ECConstants.TWO); // if (isEven) // { // BigInteger w = W(n, wOne, p); // return w.multiply(w).subtract(ECConstants.TWO).mod(p); // } // BigInteger w1 = W(n.add(ECConstants.ONE), wOne, p); // BigInteger w2 = W(n, wOne, p); // return w1.multiply(w2).subtract(wOne).mod(p); // } // // private BigInteger WOne(BigInteger r, BigInteger x, BigInteger p) // { // return r.multiply(r).multiply(x.modPow(q.subtract(ECConstants.TWO), q)).subtract(ECConstants.TWO).mod(p); // } private static BigInteger[] lucasSequence( BigInteger p, BigInteger P, BigInteger Q, BigInteger k) { int n = k.bitLength(); int s = k.getLowestSetBit(); BigInteger Uh = ECConstants.ONE; BigInteger Vl = ECConstants.TWO; BigInteger Vh = P; BigInteger Ql = ECConstants.ONE; BigInteger Qh = ECConstants.ONE; for (int j = n - 1; j >= s + 1; --j) { Ql = Ql.multiply(Qh).mod(p); if (k.testBit(j)) { Qh = Ql.multiply(Q).mod(p); Uh = Uh.multiply(Vh).mod(p); Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); Vh = Vh.multiply(Vh).subtract(Qh.shiftLeft(1)).mod(p); } else { Qh = Ql; Uh = Uh.multiply(Vl).subtract(Ql).mod(p); Vh = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p); } } Ql = Ql.multiply(Qh).mod(p); Qh = Ql.multiply(Q).mod(p); Uh = Uh.multiply(Vl).subtract(Ql).mod(p); Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); Ql = Ql.multiply(Qh).mod(p); for (int j = 1; j <= s; ++j) { Uh = Uh.multiply(Vl).mod(p); Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p); Ql = Ql.multiply(Ql).mod(p); } return new BigInteger[]{ Uh, Vl }; } public boolean equals(Object other) { if (other == this) { return true; } if (!(other instanceof ECFieldElement.Fp)) { return false; } ECFieldElement.Fp o = (ECFieldElement.Fp)other; return q.equals(o.q) && x.equals(o.x); } public int hashCode() { return q.hashCode() ^ x.hashCode(); } } // /** // * Class representing the Elements of the finite field // * F2m in polynomial basis (PB) // * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial // * basis representations are supported. Gaussian normal basis (GNB) // * representation is not supported. // */ // public static class F2m extends ECFieldElement // { // BigInteger x; // // /** // * Indicates gaussian normal basis representation (GNB). Number chosen // * according to X9.62. GNB is not implemented at present. // */ // public static final int GNB = 1; // // /** // * Indicates trinomial basis representation (TPB). Number chosen // * according to X9.62. // */ // public static final int TPB = 2; // // /** // * Indicates pentanomial basis representation (PPB). Number chosen // * according to X9.62. // */ // public static final int PPB = 3; // // /** // * TPB or PPB. // */ // private int representation; // // /** // * The exponent m of F2m. // */ // private int m; // // /** // * TPB: The integer k where xm + // * xk + 1 represents the reduction polynomial // * f(z).
      // * PPB: The integer k1 where xm + // * xk3 + xk2 + xk1 + 1 // * represents the reduction polynomial f(z).
      // */ // private int k1; // // /** // * TPB: Always set to 0
      // * PPB: The integer k2 where xm + // * xk3 + xk2 + xk1 + 1 // * represents the reduction polynomial f(z).
      // */ // private int k2; // // /** // * TPB: Always set to 0
      // * PPB: The integer k3 where xm + // * xk3 + xk2 + xk1 + 1 // * represents the reduction polynomial f(z).
      // */ // private int k3; // // /** // * Constructor for PPB. // * @param m The exponent m of // * F2m. // * @param k1 The integer k1 where xm + // * xk3 + xk2 + xk1 + 1 // * represents the reduction polynomial f(z). // * @param k2 The integer k2 where xm + // * xk3 + xk2 + xk1 + 1 // * represents the reduction polynomial f(z). // * @param k3 The integer k3 where xm + // * xk3 + xk2 + xk1 + 1 // * represents the reduction polynomial f(z). // * @param x The BigInteger representing the value of the field element. // */ // public F2m( // int m, // int k1, // int k2, // int k3, // BigInteger x) // { //// super(x); // this.x = x; // // if ((k2 == 0) && (k3 == 0)) // { // this.representation = TPB; // } // else // { // if (k2 >= k3) // { // throw new IllegalArgumentException( // "k2 must be smaller than k3"); // } // if (k2 <= 0) // { // throw new IllegalArgumentException( // "k2 must be larger than 0"); // } // this.representation = PPB; // } // // if (x.signum() < 0) // { // throw new IllegalArgumentException("x value cannot be negative"); // } // // this.m = m; // this.k1 = k1; // this.k2 = k2; // this.k3 = k3; // } // // /** // * Constructor for TPB. // * @param m The exponent m of // * F2m. // * @param k The integer k where xm + // * xk + 1 represents the reduction // * polynomial f(z). // * @param x The BigInteger representing the value of the field element. // */ // public F2m(int m, int k, BigInteger x) // { // // Set k1 to k, and set k2 and k3 to 0 // this(m, k, 0, 0, x); // } // // public BigInteger toBigInteger() // { // return x; // } // // public String getFieldName() // { // return "F2m"; // } // // public int getFieldSize() // { // return m; // } // // /** // * Checks, if the ECFieldElements a and b // * are elements of the same field F2m // * (having the same representation). // * @param a field element. // * @param b field element to be compared. // * @throws IllegalArgumentException if a and b // * are not elements of the same field // * F2m (having the same // * representation). // */ // public static void checkFieldElements( // ECFieldElement a, // ECFieldElement b) // { // if ((!(a instanceof F2m)) || (!(b instanceof F2m))) // { // throw new IllegalArgumentException("Field elements are not " // + "both instances of ECFieldElement.F2m"); // } // // if ((a.toBigInteger().signum() < 0) || (b.toBigInteger().signum() < 0)) // { // throw new IllegalArgumentException( // "x value may not be negative"); // } // // ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a; // ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b; // // if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1) // || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3)) // { // throw new IllegalArgumentException("Field elements are not " // + "elements of the same field F2m"); // } // // if (aF2m.representation != bF2m.representation) // { // // Should never occur // throw new IllegalArgumentException( // "One of the field " // + "elements are not elements has incorrect representation"); // } // } // // /** // * Computes z * a(z) mod f(z), where f(z) is // * the reduction polynomial of this. // * @param a The polynomial a(z) to be multiplied by // * z mod f(z). // * @return z * a(z) mod f(z) // */ // private BigInteger multZModF(final BigInteger a) // { // // Left-shift of a(z) // BigInteger az = a.shiftLeft(1); // if (az.testBit(this.m)) // { // // If the coefficient of z^m in a(z) equals 1, reduction // // modulo f(z) is performed: Add f(z) to to a(z): // // Step 1: Unset mth coeffient of a(z) // az = az.clearBit(this.m); // // // Step 2: Add r(z) to a(z), where r(z) is defined as // // f(z) = z^m + r(z), and k1, k2, k3 are the positions of // // the non-zero coefficients in r(z) // az = az.flipBit(0); // az = az.flipBit(this.k1); // if (this.representation == PPB) // { // az = az.flipBit(this.k2); // az = az.flipBit(this.k3); // } // } // return az; // } // // public ECFieldElement add(final ECFieldElement b) // { // // No check performed here for performance reasons. Instead the // // elements involved are checked in ECPoint.F2m // // checkFieldElements(this, b); // if (b.toBigInteger().signum() == 0) // { // return this; // } // // return new F2m(this.m, this.k1, this.k2, this.k3, this.x.xor(b.toBigInteger())); // } // // public ECFieldElement subtract(final ECFieldElement b) // { // // Addition and subtraction are the same in F2m // return add(b); // } // // // public ECFieldElement multiply(final ECFieldElement b) // { // // Left-to-right shift-and-add field multiplication in F2m // // Input: Binary polynomials a(z) and b(z) of degree at most m-1 // // Output: c(z) = a(z) * b(z) mod f(z) // // // No check performed here for performance reasons. Instead the // // elements involved are checked in ECPoint.F2m // // checkFieldElements(this, b); // final BigInteger az = this.x; // BigInteger bz = b.toBigInteger(); // BigInteger cz; // // // Compute c(z) = a(z) * b(z) mod f(z) // if (az.testBit(0)) // { // cz = bz; // } // else // { // cz = ECConstants.ZERO; // } // // for (int i = 1; i < this.m; i++) // { // // b(z) := z * b(z) mod f(z) // bz = multZModF(bz); // // if (az.testBit(i)) // { // // If the coefficient of x^i in a(z) equals 1, b(z) is added // // to c(z) // cz = cz.xor(bz); // } // } // return new ECFieldElement.F2m(m, this.k1, this.k2, this.k3, cz); // } // // // public ECFieldElement divide(final ECFieldElement b) // { // // There may be more efficient implementations // ECFieldElement bInv = b.invert(); // return multiply(bInv); // } // // public ECFieldElement negate() // { // // -x == x holds for all x in F2m // return this; // } // // public ECFieldElement square() // { // // Naive implementation, can probably be speeded up using modular // // reduction // return multiply(this); // } // // public ECFieldElement invert() // { // // Inversion in F2m using the extended Euclidean algorithm // // Input: A nonzero polynomial a(z) of degree at most m-1 // // Output: a(z)^(-1) mod f(z) // // // u(z) := a(z) // BigInteger uz = this.x; // if (uz.signum() <= 0) // { // throw new ArithmeticException("x is zero or negative, " + // "inversion is impossible"); // } // // // v(z) := f(z) // BigInteger vz = ECConstants.ZERO.setBit(m); // vz = vz.setBit(0); // vz = vz.setBit(this.k1); // if (this.representation == PPB) // { // vz = vz.setBit(this.k2); // vz = vz.setBit(this.k3); // } // // // g1(z) := 1, g2(z) := 0 // BigInteger g1z = ECConstants.ONE; // BigInteger g2z = ECConstants.ZERO; // // // while u != 1 // while (!(uz.equals(ECConstants.ZERO))) // { // // j := deg(u(z)) - deg(v(z)) // int j = uz.bitLength() - vz.bitLength(); // // // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j // if (j < 0) // { // final BigInteger uzCopy = uz; // uz = vz; // vz = uzCopy; // // final BigInteger g1zCopy = g1z; // g1z = g2z; // g2z = g1zCopy; // // j = -j; // } // // // u(z) := u(z) + z^j * v(z) // // Note, that no reduction modulo f(z) is required, because // // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z))) // // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z)) // // = deg(u(z)) // uz = uz.xor(vz.shiftLeft(j)); // // // g1(z) := g1(z) + z^j * g2(z) // g1z = g1z.xor(g2z.shiftLeft(j)); //// if (g1z.bitLength() > this.m) { //// throw new ArithmeticException( //// "deg(g1z) >= m, g1z = " + g1z.toString(2)); //// } // } // return new ECFieldElement.F2m( // this.m, this.k1, this.k2, this.k3, g2z); // } // // public ECFieldElement sqrt() // { // throw new RuntimeException("Not implemented"); // } // // /** // * @return the representation of the field // * F2m, either of // * TPB (trinomial // * basis representation) or // * PPB (pentanomial // * basis representation). // */ // public int getRepresentation() // { // return this.representation; // } // // /** // * @return the degree m of the reduction polynomial // * f(z). // */ // public int getM() // { // return this.m; // } // // /** // * @return TPB: The integer k where xm + // * xk + 1 represents the reduction polynomial // * f(z).
      // * PPB: The integer k1 where xm + // * xk3 + xk2 + xk1 + 1 // * represents the reduction polynomial f(z).
      // */ // public int getK1() // { // return this.k1; // } // // /** // * @return TPB: Always returns 0
      // * PPB: The integer k2 where xm + // * xk3 + xk2 + xk1 + 1 // * represents the reduction polynomial f(z).
      // */ // public int getK2() // { // return this.k2; // } // // /** // * @return TPB: Always set to 0
      // * PPB: The integer k3 where xm + // * xk3 + xk2 + xk1 + 1 // * represents the reduction polynomial f(z).
      // */ // public int getK3() // { // return this.k3; // } // // public boolean equals(Object anObject) // { // if (anObject == this) // { // return true; // } // // if (!(anObject instanceof ECFieldElement.F2m)) // { // return false; // } // // ECFieldElement.F2m b = (ECFieldElement.F2m)anObject; // // return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2) // && (this.k3 == b.k3) // && (this.representation == b.representation) // && (this.x.equals(b.x))); // } // // public int hashCode() // { // return x.hashCode() ^ m ^ k1 ^ k2 ^ k3; // } // } /** * Class representing the Elements of the finite field * F2m in polynomial basis (PB) * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial * basis representations are supported. Gaussian normal basis (GNB) * representation is not supported. */ public static class F2m extends ECFieldElement { /** * Indicates gaussian normal basis representation (GNB). Number chosen * according to X9.62. GNB is not implemented at present. */ public static final int GNB = 1; /** * Indicates trinomial basis representation (TPB). Number chosen * according to X9.62. */ public static final int TPB = 2; /** * Indicates pentanomial basis representation (PPB). Number chosen * according to X9.62. */ public static final int PPB = 3; /** * TPB or PPB. */ private int representation; /** * The exponent m of F2m. */ private int m; /** * TPB: The integer k where xm + * xk + 1 represents the reduction polynomial * f(z).
      * PPB: The integer k1 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z).
      */ private int k1; /** * TPB: Always set to 0
      * PPB: The integer k2 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z).
      */ private int k2; /** * TPB: Always set to 0
      * PPB: The integer k3 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z).
      */ private int k3; /** * The IntArray holding the bits. */ private IntArray x; /** * The number of ints required to hold m bits. */ private int t; /** * Constructor for PPB. * @param m The exponent m of * F2m. * @param k1 The integer k1 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z). * @param k2 The integer k2 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z). * @param k3 The integer k3 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z). * @param x The BigInteger representing the value of the field element. */ public F2m( int m, int k1, int k2, int k3, BigInteger x) { // t = m / 32 rounded up to the next integer t = (m + 31) >> 5; this.x = new IntArray(x, t); if ((k2 == 0) && (k3 == 0)) { this.representation = TPB; } else { if (k2 >= k3) { throw new IllegalArgumentException( "k2 must be smaller than k3"); } if (k2 <= 0) { throw new IllegalArgumentException( "k2 must be larger than 0"); } this.representation = PPB; } if (x.signum() < 0) { throw new IllegalArgumentException("x value cannot be negative"); } this.m = m; this.k1 = k1; this.k2 = k2; this.k3 = k3; } /** * Constructor for TPB. * @param m The exponent m of * F2m. * @param k The integer k where xm + * xk + 1 represents the reduction * polynomial f(z). * @param x The BigInteger representing the value of the field element. */ public F2m(int m, int k, BigInteger x) { // Set k1 to k, and set k2 and k3 to 0 this(m, k, 0, 0, x); } private F2m(int m, int k1, int k2, int k3, IntArray x) { t = (m + 31) >> 5; this.x = x; this.m = m; this.k1 = k1; this.k2 = k2; this.k3 = k3; if ((k2 == 0) && (k3 == 0)) { this.representation = TPB; } else { this.representation = PPB; } } public BigInteger toBigInteger() { return x.toBigInteger(); } public String getFieldName() { return "F2m"; } public int getFieldSize() { return m; } /** * Checks, if the ECFieldElements a and b * are elements of the same field F2m * (having the same representation). * @param a field element. * @param b field element to be compared. * @throws IllegalArgumentException if a and b * are not elements of the same field * F2m (having the same * representation). */ public static void checkFieldElements( ECFieldElement a, ECFieldElement b) { if ((!(a instanceof F2m)) || (!(b instanceof F2m))) { throw new IllegalArgumentException("Field elements are not " + "both instances of ECFieldElement.F2m"); } ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a; ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b; if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1) || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3)) { throw new IllegalArgumentException("Field elements are not " + "elements of the same field F2m"); } if (aF2m.representation != bF2m.representation) { // Should never occur throw new IllegalArgumentException( "One of the field " + "elements are not elements has incorrect representation"); } } public ECFieldElement add(final ECFieldElement b) { // No check performed here for performance reasons. Instead the // elements involved are checked in ECPoint.F2m // checkFieldElements(this, b); IntArray iarrClone = (IntArray)this.x.clone(); F2m bF2m = (F2m)b; iarrClone.addShifted(bF2m.x, 0); return new F2m(m, k1, k2, k3, iarrClone); } public ECFieldElement subtract(final ECFieldElement b) { // Addition and subtraction are the same in F2m return add(b); } public ECFieldElement multiply(final ECFieldElement b) { // Right-to-left comb multiplication in the IntArray // Input: Binary polynomials a(z) and b(z) of degree at most m-1 // Output: c(z) = a(z) * b(z) mod f(z) // No check performed here for performance reasons. Instead the // elements involved are checked in ECPoint.F2m // checkFieldElements(this, b); F2m bF2m = (F2m)b; IntArray mult = x.multiply(bF2m.x, m); mult.reduce(m, new int[]{k1, k2, k3}); return new F2m(m, k1, k2, k3, mult); } public ECFieldElement divide(final ECFieldElement b) { // There may be more efficient implementations ECFieldElement bInv = b.invert(); return multiply(bInv); } public ECFieldElement negate() { // -x == x holds for all x in F2m return this; } public ECFieldElement square() { IntArray squared = x.square(m); squared.reduce(m, new int[]{k1, k2, k3}); return new F2m(m, k1, k2, k3, squared); } public ECFieldElement invert() { // Inversion in F2m using the extended Euclidean algorithm // Input: A nonzero polynomial a(z) of degree at most m-1 // Output: a(z)^(-1) mod f(z) // u(z) := a(z) IntArray uz = (IntArray)this.x.clone(); // v(z) := f(z) IntArray vz = new IntArray(t); vz.setBit(m); vz.setBit(0); vz.setBit(this.k1); if (this.representation == PPB) { vz.setBit(this.k2); vz.setBit(this.k3); } // g1(z) := 1, g2(z) := 0 IntArray g1z = new IntArray(t); g1z.setBit(0); IntArray g2z = new IntArray(t); // while u != 0 while (!uz.isZero()) // while (uz.getUsedLength() > 0) // while (uz.bitLength() > 1) { // j := deg(u(z)) - deg(v(z)) int j = uz.bitLength() - vz.bitLength(); // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j if (j < 0) { final IntArray uzCopy = uz; uz = vz; vz = uzCopy; final IntArray g1zCopy = g1z; g1z = g2z; g2z = g1zCopy; j = -j; } // u(z) := u(z) + z^j * v(z) // Note, that no reduction modulo f(z) is required, because // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z))) // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z)) // = deg(u(z)) // uz = uz.xor(vz.shiftLeft(j)); // jInt = n / 32 int jInt = j >> 5; // jInt = n % 32 int jBit = j & 0x1F; IntArray vzShift = vz.shiftLeft(jBit); uz.addShifted(vzShift, jInt); // g1(z) := g1(z) + z^j * g2(z) // g1z = g1z.xor(g2z.shiftLeft(j)); IntArray g2zShift = g2z.shiftLeft(jBit); g1z.addShifted(g2zShift, jInt); } return new ECFieldElement.F2m( this.m, this.k1, this.k2, this.k3, g2z); } public ECFieldElement sqrt() { throw new RuntimeException("Not implemented"); } /** * @return the representation of the field * F2m, either of * TPB (trinomial * basis representation) or * PPB (pentanomial * basis representation). */ public int getRepresentation() { return this.representation; } /** * @return the degree m of the reduction polynomial * f(z). */ public int getM() { return this.m; } /** * @return TPB: The integer k where xm + * xk + 1 represents the reduction polynomial * f(z).
      * PPB: The integer k1 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z).
      */ public int getK1() { return this.k1; } /** * @return TPB: Always returns 0
      * PPB: The integer k2 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z).
      */ public int getK2() { return this.k2; } /** * @return TPB: Always set to 0
      * PPB: The integer k3 where xm + * xk3 + xk2 + xk1 + 1 * represents the reduction polynomial f(z).
      */ public int getK3() { return this.k3; } public boolean equals(Object anObject) { if (anObject == this) { return true; } if (!(anObject instanceof ECFieldElement.F2m)) { return false; } ECFieldElement.F2m b = (ECFieldElement.F2m)anObject; return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2) && (this.k3 == b.k3) && (this.representation == b.representation) && (this.x.equals(b.x))); } public int hashCode() { return x.hashCode() ^ m ^ k1 ^ k2 ^ k3; } } } azureus-4.3.0.6/org/bouncycastle/math/ec/FpNafMultiplier.java0000644000175000017500000000175210767602136023361 0ustar adrianadrianpackage org.bouncycastle.math.ec; import java.math.BigInteger; /** * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm. */ class FpNafMultiplier implements ECMultiplier { /** * D.3.2 pg 101 * @see org.bouncycastle.math.ec.ECMultiplier#multiply(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger) */ public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) { // TODO Probably should try to add this // BigInteger e = k.mod(n); // n == order of p BigInteger e = k; BigInteger h = e.multiply(BigInteger.valueOf(3)); ECPoint neg = p.negate(); ECPoint R = p; for (int i = h.bitLength() - 2; i > 0; --i) { R = R.twice(); boolean hBit = h.testBit(i); boolean eBit = e.testBit(i); if (hBit != eBit) { R = R.add(hBit ? p : neg); } } return R; } } azureus-4.3.0.6/org/bouncycastle/math/ec/SimpleBigDecimal.java0000644000175000017500000001526210767602136023453 0ustar adrianadrianpackage org.bouncycastle.math.ec; import java.math.BigInteger; /** * Class representing a simple version of a big decimal. A * SimpleBigDecimal is basically a * {@link java.math.BigInteger BigInteger} with a few digits on the right of * the decimal point. The number of (binary) digits on the right of the decimal * point is called the scale of the SimpleBigDecimal. * Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted * automatically, but must be set manually. All SimpleBigDecimals * taking part in the same arithmetic operation must have equal scale. The * result of a multiplication of two SimpleBigDecimals returns a * SimpleBigDecimal with double scale. */ class SimpleBigDecimal //extends Number // not in J2ME - add compatibility class? { private static final long serialVersionUID = 1L; private final BigInteger bigInt; private final int scale; /** * Returns a SimpleBigDecimal representing the same numerical * value as value. * @param value The value of the SimpleBigDecimal to be * created. * @param scale The scale of the SimpleBigDecimal to be * created. * @return The such created SimpleBigDecimal. */ public static SimpleBigDecimal getInstance(BigInteger value, int scale) { return new SimpleBigDecimal(value.shiftLeft(scale), scale); } /** * Constructor for SimpleBigDecimal. The value of the * constructed SimpleBigDecimal equals bigInt / * 2scale. * @param bigInt The bigInt value parameter. * @param scale The scale of the constructed SimpleBigDecimal. */ public SimpleBigDecimal(BigInteger bigInt, int scale) { if (scale < 0) { throw new IllegalArgumentException("scale may not be negative"); } this.bigInt = bigInt; this.scale = scale; } private SimpleBigDecimal(SimpleBigDecimal limBigDec) { bigInt = limBigDec.bigInt; scale = limBigDec.scale; } private void checkScale(SimpleBigDecimal b) { if (scale != b.scale) { throw new IllegalArgumentException("Only SimpleBigDecimal of " + "same scale allowed in arithmetic operations"); } } public SimpleBigDecimal adjustScale(int newScale) { if (newScale < 0) { throw new IllegalArgumentException("scale may not be negative"); } if (newScale == scale) { return new SimpleBigDecimal(this); } return new SimpleBigDecimal(bigInt.shiftLeft(newScale - scale), newScale); } public SimpleBigDecimal add(SimpleBigDecimal b) { checkScale(b); return new SimpleBigDecimal(bigInt.add(b.bigInt), scale); } public SimpleBigDecimal add(BigInteger b) { return new SimpleBigDecimal(bigInt.add(b.shiftLeft(scale)), scale); } public SimpleBigDecimal negate() { return new SimpleBigDecimal(bigInt.negate(), scale); } public SimpleBigDecimal subtract(SimpleBigDecimal b) { return add(b.negate()); } public SimpleBigDecimal subtract(BigInteger b) { return new SimpleBigDecimal(bigInt.subtract(b.shiftLeft(scale)), scale); } public SimpleBigDecimal multiply(SimpleBigDecimal b) { checkScale(b); return new SimpleBigDecimal(bigInt.multiply(b.bigInt), scale + scale); } public SimpleBigDecimal multiply(BigInteger b) { return new SimpleBigDecimal(bigInt.multiply(b), scale); } public SimpleBigDecimal divide(SimpleBigDecimal b) { checkScale(b); BigInteger dividend = bigInt.shiftLeft(scale); return new SimpleBigDecimal(dividend.divide(b.bigInt), scale); } public SimpleBigDecimal divide(BigInteger b) { return new SimpleBigDecimal(bigInt.divide(b), scale); } public SimpleBigDecimal shiftLeft(int n) { return new SimpleBigDecimal(bigInt.shiftLeft(n), scale); } public int compareTo(SimpleBigDecimal val) { checkScale(val); return bigInt.compareTo(val.bigInt); } public int compareTo(BigInteger val) { return bigInt.compareTo(val.shiftLeft(scale)); } public BigInteger floor() { return bigInt.shiftRight(scale); } public BigInteger round() { SimpleBigDecimal oneHalf = new SimpleBigDecimal(ECConstants.ONE, 1); return add(oneHalf.adjustScale(scale)).floor(); } public int intValue() { return floor().intValue(); } public long longValue() { return floor().longValue(); } public double doubleValue() { return Double.valueOf(toString()).doubleValue(); } public float floatValue() { return Float.valueOf(toString()).floatValue(); } public int getScale() { return scale; } public String toString() { if (scale == 0) { return bigInt.toString(); } BigInteger floorBigInt = floor(); BigInteger fract = bigInt.subtract(floorBigInt.shiftLeft(scale)); if (bigInt.signum() == -1) { fract = ECConstants.ONE.shiftLeft(scale).subtract(fract); } if ((floorBigInt.signum() == -1) && (!(fract.equals(ECConstants.ZERO)))) { floorBigInt = floorBigInt.add(ECConstants.ONE); } String leftOfPoint = floorBigInt.toString(); char[] fractCharArr = new char[scale]; String fractStr = fract.toString(2); int fractLen = fractStr.length(); int zeroes = scale - fractLen; for (int i = 0; i < zeroes; i++) { fractCharArr[i] = '0'; } for (int j = 0; j < fractLen; j++) { fractCharArr[zeroes + j] = fractStr.charAt(j); } String rightOfPoint = new String(fractCharArr); StringBuffer sb = new StringBuffer(leftOfPoint); sb.append("."); sb.append(rightOfPoint); return sb.toString(); } public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof SimpleBigDecimal)) { return false; } SimpleBigDecimal other = (SimpleBigDecimal)o; return ((bigInt.equals(other.bigInt)) && (scale == other.scale)); } public int hashCode() { return bigInt.hashCode() ^ scale; } } azureus-4.3.0.6/org/bouncycastle/math/ec/PreCompInfo.java0000644000175000017500000000034510767602136022476 0ustar adrianadrianpackage org.bouncycastle.math.ec; /** * Interface for classes storing precomputation data for multiplication * algorithms. Used as a Memento (see GOF patterns) for * WNafMultiplier. */ interface PreCompInfo { } azureus-4.3.0.6/org/bouncycastle/math/ec/ZTauElement.java0000644000175000017500000000203510767602136022510 0ustar adrianadrianpackage org.bouncycastle.math.ec; import java.math.BigInteger; /** * Class representing an element of Z[τ]. Let * λ be an element of Z[τ]. Then * λ is given as λ = u + vτ. The * components u and v may be used directly, there * are no accessor methods. * Immutable class. */ class ZTauElement { /** * The "real" part of λ. */ public final BigInteger u; /** * The "τ-adic" part of λ. */ public final BigInteger v; /** * Constructor for an element λ of * Z[τ]. * @param u The "real" part of λ. * @param v The "τ-adic" part of * λ. */ public ZTauElement(BigInteger u, BigInteger v) { this.u = u; this.v = v; } } azureus-4.3.0.6/org/bouncycastle/util/0000755000175000017500000000000011310377634017102 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/util/IPAddress.java0000644000175000017500000000531711026315700021557 0ustar adrianadrianpackage org.bouncycastle.util; import java.math.BigInteger; public class IPAddress { private static final BigInteger ZERO = BigInteger.valueOf(0); /** * Validate the given IPv4 or IPv6 address. * * @param address the IP address as a String. * * @return true if a valid address, false otherwise */ public static boolean isValid( String address) { return isValidIPv4(address) || isValidIPv6(address); } /** * Validate the given IPv4 address. * * @param address the IP address as a String. * * @return true if a valid IPv4 address, false otherwise */ private static boolean isValidIPv4( String address) { if (address.length() == 0) { return false; } BigInteger octet; int octets = 0; String temp = address+"."; int pos; int start = 0; while (start < temp.length() && (pos = temp.indexOf('.', start)) > start) { if (octets == 4) { return false; } try { octet = (new BigInteger(temp.substring(start, pos))); } catch (NumberFormatException ex) { return false; } if (octet.compareTo(ZERO) == -1 || octet.compareTo(BigInteger.valueOf(255)) == 1) { return false; } start = pos + 1; octets++; } return octets == 4; } /** * Validate the given IPv6 address. * * @param address the IP address as a String. * * @return true if a valid IPv4 address, false otherwise */ private static boolean isValidIPv6( String address) { if (address.length() == 0) { return false; } BigInteger octet; int octets = 0; String temp = address + ":"; int pos; int start = 0; while (start < temp.length() && (pos = temp.indexOf(':', start)) > start) { if (octets == 8) { return false; } try { octet = (new BigInteger(temp.substring(start, pos), 16)); } catch (NumberFormatException ex) { return false; } if (octet.compareTo(ZERO) == -1 || octet.compareTo(BigInteger.valueOf(0xFFFF)) == 1) { return false; } start = pos + 1; octets++; } return octets == 8; } } azureus-4.3.0.6/org/bouncycastle/util/Strings.java0000644000175000017500000001436311026315700021373 0ustar adrianadrianpackage org.bouncycastle.util; import java.io.ByteArrayOutputStream; import java.util.Vector; public final class Strings { public static String fromUTF8ByteArray(byte[] bytes) { int i = 0; int length = 0; while (i < bytes.length) { length++; if ((bytes[i] & 0xf0) == 0xf0) { // surrogate pair length++; i += 4; } else if ((bytes[i] & 0xe0) == 0xe0) { i += 3; } else if ((bytes[i] & 0xc0) == 0xc0) { i += 2; } else { i += 1; } } char[] cs = new char[length]; i = 0; length = 0; while (i < bytes.length) { char ch; if ((bytes[i] & 0xf0) == 0xf0) { int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i+1] & 0x3F) << 12) | ((bytes[i+2] & 0x3F) << 6) | (bytes[i+3] & 0x3F); int U = codePoint - 0x10000; char W1 = (char)(0xD800 | (U >> 10)); char W2 = (char)(0xDC00 | (U & 0x3FF)); cs[length++] = W1; ch = W2; i += 4; } else if ((bytes[i] & 0xe0) == 0xe0) { ch = (char)(((bytes[i] & 0x0f) << 12) | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f)); i += 3; } else if ((bytes[i] & 0xd0) == 0xd0) { ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f)); i += 2; } else if ((bytes[i] & 0xc0) == 0xc0) { ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f)); i += 2; } else { ch = (char)(bytes[i] & 0xff); i += 1; } cs[length++] = ch; } return new String(cs); } public static byte[] toUTF8ByteArray(String string) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); char[] c = string.toCharArray(); int i = 0; while (i < c.length) { char ch = c[i]; if (ch < 0x0080) { bOut.write(ch); } else if (ch < 0x0800) { bOut.write(0xc0 | (ch >> 6)); bOut.write(0x80 | (ch & 0x3f)); } // surrogate pair else if (ch >= 0xD800 && ch <= 0xDFFF) { // in error - can only happen, if the Java String class has a // bug. if (i + 1 >= c.length) { throw new IllegalStateException("invalid UTF-16 codepoint"); } char W1 = ch; ch = c[++i]; char W2 = ch; // in error - can only happen, if the Java String class has a // bug. if (W1 > 0xDBFF) { throw new IllegalStateException("invalid UTF-16 codepoint"); } int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000; bOut.write(0xf0 | (codePoint >> 18)); bOut.write(0x80 | ((codePoint >> 12) & 0x3F)); bOut.write(0x80 | ((codePoint >> 6) & 0x3F)); bOut.write(0x80 | (codePoint & 0x3F)); } else { bOut.write(0xe0 | (ch >> 12)); bOut.write(0x80 | ((ch >> 6) & 0x3F)); bOut.write(0x80 | (ch & 0x3F)); } i++; } return bOut.toByteArray(); } /** * A locale independent version of toUpperCase. * * @param string input to be converted * @return a US Ascii uppercase version */ public static String toUpperCase(String string) { boolean changed = false; char[] chars = string.toCharArray(); for (int i = 0; i != chars.length; i++) { char ch = chars[i]; if ('a' <= ch && 'z' >= ch) { changed = true; chars[i] = (char)(ch - 'a' + 'A'); } } if (changed) { return new String(chars); } return string; } /** * A locale independent version of toLowerCase. * * @param string input to be converted * @return a US ASCII lowercase version */ public static String toLowerCase(String string) { boolean changed = false; char[] chars = string.toCharArray(); for (int i = 0; i != chars.length; i++) { char ch = chars[i]; if ('A' <= ch && 'Z' >= ch) { changed = true; chars[i] = (char)(ch - 'A' + 'a'); } } if (changed) { return new String(chars); } return string; } public static byte[] toByteArray(String string) { byte[] bytes = new byte[string.length()]; for (int i = 0; i != bytes.length; i++) { char ch = string.charAt(i); bytes[i] = (byte)ch; } return bytes; } public static String[] split(String input, char delimiter) { Vector v = new Vector(); boolean moreTokens = true; String subString; while (moreTokens) { int tokenLocation = input.indexOf(delimiter); if (tokenLocation > 0) { subString = input.substring(0, tokenLocation); v.addElement(subString); input = input.substring(tokenLocation + 1); } else { moreTokens = false; v.addElement(input); } } String[] res = new String[v.size()]; for (int i = 0; i != res.length; i++) { res[i] = (String)v.elementAt(i); } return res; } } azureus-4.3.0.6/org/bouncycastle/util/encoders/0000755000175000017500000000000011310377634020704 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/util/encoders/HexTranslator.java0000644000175000017500000000400010061400654024326 0ustar adrianadrianpackage org.bouncycastle.util.encoders; /** * Converters for going from hex to binary and back. Note: this class assumes ASCII processing. */ public class HexTranslator implements Translator { private static final byte[] hexTable = { (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f' }; /** * size of the output block on encoding produced by getDecodedBlockSize() * bytes. */ public int getEncodedBlockSize() { return 2; } public int encode( byte[] in, int inOff, int length, byte[] out, int outOff) { for (int i = 0, j = 0; i < length; i++, j += 2) { out[outOff + j] = hexTable[(in[inOff] >> 4) & 0x0f]; out[outOff + j + 1] = hexTable[in[inOff] & 0x0f]; inOff++; } return length * 2; } /** * size of the output block on decoding produced by getEncodedBlockSize() * bytes. */ public int getDecodedBlockSize() { return 1; } public int decode( byte[] in, int inOff, int length, byte[] out, int outOff) { int halfLength = length / 2; byte left, right; for (int i = 0; i < halfLength; i++) { left = in[inOff + i * 2]; right = in[inOff + i * 2 + 1]; if (left < (byte)'a') { out[outOff] = (byte)((left - '0') << 4); } else { out[outOff] = (byte)((left - 'a' + 10) << 4); } if (right < (byte)'a') { out[outOff] += (byte)(right - '0'); } else { out[outOff] += (byte)(right - 'a' + 10); } outOff++; } return halfLength; } } azureus-4.3.0.6/org/bouncycastle/util/encoders/Translator.java0000644000175000017500000000110210061400654023661 0ustar adrianadrianpackage org.bouncycastle.util.encoders; /** * general interface for an translator. */ public interface Translator { /** * size of the output block on encoding produced by getDecodedBlockSize() * bytes. */ public int getEncodedBlockSize(); public int encode(byte[] in, int inOff, int length, byte[] out, int outOff); /** * size of the output block on decoding produced by getEncodedBlockSize() * bytes. */ public int getDecodedBlockSize(); public int decode(byte[] in, int inOff, int length, byte[] out, int outOff); } azureus-4.3.0.6/org/bouncycastle/util/encoders/BufferedDecoder.java0000644000175000017500000000410110061400654024542 0ustar adrianadrianpackage org.bouncycastle.util.encoders; /** * a buffering class to allow translation from one format to another to * be done in discrete chunks. */ public class BufferedDecoder { protected byte[] buf; protected int bufOff; protected Translator translator; /** * @param translator the translator to use. * @param bufSize amount of input to buffer for each chunk. */ public BufferedDecoder( Translator translator, int bufSize) { this.translator = translator; if ((bufSize % translator.getEncodedBlockSize()) != 0) { throw new IllegalArgumentException("buffer size not multiple of input block size"); } buf = new byte[bufSize]; bufOff = 0; } public int processByte( byte in, byte[] out, int outOff) { int resultLen = 0; buf[bufOff++] = in; if (bufOff == buf.length) { resultLen = translator.decode(buf, 0, buf.length, out, outOff); bufOff = 0; } return resultLen; } public int processBytes( byte[] in, int inOff, int len, byte[] out, int outOff) { if (len < 0) { throw new IllegalArgumentException("Can't have a negative input length!"); } int resultLen = 0; int gapLen = buf.length - bufOff; if (len > gapLen) { System.arraycopy(in, inOff, buf, bufOff, gapLen); resultLen += translator.decode(buf, 0, buf.length, out, outOff); bufOff = 0; len -= gapLen; inOff += gapLen; outOff += resultLen; int chunkSize = len - (len % buf.length); resultLen += translator.decode(in, inOff, chunkSize, out, outOff); len -= chunkSize; inOff += chunkSize; } if (len != 0) { System.arraycopy(in, inOff, buf, bufOff, len); bufOff += len; } return resultLen; } } azureus-4.3.0.6/org/bouncycastle/util/encoders/Hex.java0000644000175000017500000000355210061400654022267 0ustar adrianadrianpackage org.bouncycastle.util.encoders; /** * Converters for going from hex to binary and back. *

      * Note: this class assumes ASCII processing. */ public class Hex { private static HexTranslator encoder = new HexTranslator(); private static final byte[] hexTable = { (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f' }; public static byte[] encode( byte[] array) { return encode(array, 0, array.length); } public static byte[] encode( byte[] array, int off, int length) { byte[] enc = new byte[length * 2]; encoder.encode(array, off, length, enc, 0); return enc; } public static byte[] decode( String string) { byte[] bytes = new byte[string.length() / 2]; String buf = string.toLowerCase(); for (int i = 0; i < buf.length(); i += 2) { char left = buf.charAt(i); char right = buf.charAt(i+1); int index = i / 2; if (left < 'a') { bytes[index] = (byte)((left - '0') << 4); } else { bytes[index] = (byte)((left - 'a' + 10) << 4); } if (right < 'a') { bytes[index] += (byte)(right - '0'); } else { bytes[index] += (byte)(right - 'a' + 10); } } return bytes; } public static byte[] decode( byte[] array) { byte[] bytes = new byte[array.length / 2]; encoder.decode(array, 0, array.length, bytes, 0); return bytes; } } azureus-4.3.0.6/org/bouncycastle/util/encoders/Base64.java0000644000175000017500000002100210612024262022554 0ustar adrianadrianpackage org.bouncycastle.util.encoders; import java.io.IOException; import java.io.OutputStream; public class Base64 { private static final byte[] encodingTable = { (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/' }; /** * encode the input data producong a base 64 encoded byte array. * * @return a byte array containing the base 64 encoded data. */ public static byte[] encode( byte[] data) { byte[] bytes; int modulus = data.length % 3; if (modulus == 0) { bytes = new byte[4 * data.length / 3]; } else { bytes = new byte[4 * ((data.length / 3) + 1)]; } int dataLength = (data.length - modulus); int a1, a2, a3; for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) { a1 = data[i] & 0xff; a2 = data[i + 1] & 0xff; a3 = data[i + 2] & 0xff; bytes[j] = encodingTable[(a1 >>> 2) & 0x3f]; bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]; bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]; bytes[j + 3] = encodingTable[a3 & 0x3f]; } /* * process the tail end. */ int b1, b2, b3; int d1, d2; switch (modulus) { case 0: /* nothing left to do */ break; case 1: d1 = data[data.length - 1] & 0xff; b1 = (d1 >>> 2) & 0x3f; b2 = (d1 << 4) & 0x3f; bytes[bytes.length - 4] = encodingTable[b1]; bytes[bytes.length - 3] = encodingTable[b2]; bytes[bytes.length - 2] = (byte)'='; bytes[bytes.length - 1] = (byte)'='; break; case 2: d1 = data[data.length - 2] & 0xff; d2 = data[data.length - 1] & 0xff; b1 = (d1 >>> 2) & 0x3f; b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f; b3 = (d2 << 2) & 0x3f; bytes[bytes.length - 4] = encodingTable[b1]; bytes[bytes.length - 3] = encodingTable[b2]; bytes[bytes.length - 2] = encodingTable[b3]; bytes[bytes.length - 1] = (byte)'='; break; } return bytes; } /* * set up the decoding table. */ private static final byte[] decodingTable; static { decodingTable = new byte[128]; for (int i = 'A'; i <= 'Z'; i++) { decodingTable[i] = (byte)(i - 'A'); } for (int i = 'a'; i <= 'z'; i++) { decodingTable[i] = (byte)(i - 'a' + 26); } for (int i = '0'; i <= '9'; i++) { decodingTable[i] = (byte)(i - '0' + 52); } decodingTable['+'] = 62; decodingTable['/'] = 63; } /** * decode the base 64 encoded input data. * * @return a byte array representing the decoded data. */ public static byte[] decode( byte[] data) { // PARG - fix up for zero length encodes/decodes if ( data.length == 0 ){ return( data ); } byte[] bytes; byte b1, b2, b3, b4; if (data[data.length - 2] == '=') { bytes = new byte[(((data.length / 4) - 1) * 3) + 1]; } else if (data[data.length - 1] == '=') { bytes = new byte[(((data.length / 4) - 1) * 3) + 2]; } else { bytes = new byte[((data.length / 4) * 3)]; } for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3) { b1 = decodingTable[data[i]]; b2 = decodingTable[data[i + 1]]; b3 = decodingTable[data[i + 2]]; b4 = decodingTable[data[i + 3]]; bytes[j] = (byte)((b1 << 2) | (b2 >> 4)); bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2)); bytes[j + 2] = (byte)((b3 << 6) | b4); } if (data[data.length - 2] == '=') { b1 = decodingTable[data[data.length - 4]]; b2 = decodingTable[data[data.length - 3]]; bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4)); } else if (data[data.length - 1] == '=') { b1 = decodingTable[data[data.length - 4]]; b2 = decodingTable[data[data.length - 3]]; b3 = decodingTable[data[data.length - 2]]; bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2)); } else { b1 = decodingTable[data[data.length - 4]]; b2 = decodingTable[data[data.length - 3]]; b3 = decodingTable[data[data.length - 2]]; b4 = decodingTable[data[data.length - 1]]; bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2)); bytes[bytes.length - 1] = (byte)((b3 << 6) | b4); } return bytes; } /** * decode the base 64 encoded String data. * * @return a byte array representing the decoded data. */ public static byte[] decode( String data) { // PARG - fix up for zero length encodes/decodes if ( data.length() == 0 ){ return( new byte[0] ); } byte[] bytes; byte b1, b2, b3, b4; if (data.charAt(data.length() - 2) == '=') { bytes = new byte[(((data.length() / 4) - 1) * 3) + 1]; } else if (data.charAt(data.length() - 1) == '=') { bytes = new byte[(((data.length() / 4) - 1) * 3) + 2]; } else { bytes = new byte[((data.length() / 4) * 3)]; } for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3) { b1 = decodingTable[data.charAt(i)]; b2 = decodingTable[data.charAt(i + 1)]; b3 = decodingTable[data.charAt(i + 2)]; b4 = decodingTable[data.charAt(i + 3)]; bytes[j] = (byte)((b1 << 2) | (b2 >> 4)); bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2)); bytes[j + 2] = (byte)((b3 << 6) | b4); } if (data.charAt(data.length() - 2) == '=') { b1 = decodingTable[data.charAt(data.length() - 4)]; b2 = decodingTable[data.charAt(data.length() - 3)]; bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4)); } else if (data.charAt(data.length() - 1) == '=') { b1 = decodingTable[data.charAt(data.length() - 4)]; b2 = decodingTable[data.charAt(data.length() - 3)]; b3 = decodingTable[data.charAt(data.length() - 2)]; bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2)); } else { b1 = decodingTable[data.charAt(data.length() - 4)]; b2 = decodingTable[data.charAt(data.length() - 3)]; b3 = decodingTable[data.charAt(data.length() - 2)]; b4 = decodingTable[data.charAt(data.length() - 1)]; bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2)); bytes[bytes.length - 1] = (byte)((b3 << 6) | b4); } return bytes; } /** * decode the base 64 encoded String data writing it to the given output stream * * @return the number of bytes produced. */ public static int decode( String data, OutputStream out) throws IOException { // PARG if ( data.length()== 0 ){ return( 0 ); } byte b1, b2, b3, b4; int length; if (data.charAt(data.length() - 2) == '=') { length = (((data.length() / 4) - 1) * 3) + 1; } else if (data.charAt(data.length() - 1) == '=') { length = (((data.length() / 4) - 1) * 3) + 2; } else { length = ((data.length() / 4) * 3); } for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3) { b1 = decodingTable[data.charAt(i)]; b2 = decodingTable[data.charAt(i + 1)]; b3 = decodingTable[data.charAt(i + 2)]; b4 = decodingTable[data.charAt(i + 3)]; out.write((b1 << 2) | (b2 >> 4)); out.write((b2 << 4) | (b3 >> 2)); out.write((b3 << 6) | b4); } if (data.charAt(data.length() - 2) == '=') { b1 = decodingTable[data.charAt(data.length() - 4)]; b2 = decodingTable[data.charAt(data.length() - 3)]; out.write((b1 << 2) | (b2 >> 4)); } else if (data.charAt(data.length() - 1) == '=') { b1 = decodingTable[data.charAt(data.length() - 4)]; b2 = decodingTable[data.charAt(data.length() - 3)]; b3 = decodingTable[data.charAt(data.length() - 2)]; out.write((b1 << 2) | (b2 >> 4)); out.write((b2 << 4) | (b3 >> 2)); } else { b1 = decodingTable[data.charAt(data.length() - 4)]; b2 = decodingTable[data.charAt(data.length() - 3)]; b3 = decodingTable[data.charAt(data.length() - 2)]; b4 = decodingTable[data.charAt(data.length() - 1)]; out.write((b1 << 2) | (b2 >> 4)); out.write((b2 << 4) | (b3 >> 2)); out.write((b3 << 6) | b4); } return length; } } azureus-4.3.0.6/org/bouncycastle/util/encoders/BufferedEncoder.java0000644000175000017500000000410110061400654024554 0ustar adrianadrianpackage org.bouncycastle.util.encoders; /** * a buffering class to allow translation from one format to another to * be done in discrete chunks. */ public class BufferedEncoder { protected byte[] buf; protected int bufOff; protected Translator translator; /** * @param translator the translator to use. * @param bufSize amount of input to buffer for each chunk. */ public BufferedEncoder( Translator translator, int bufSize) { this.translator = translator; if ((bufSize % translator.getEncodedBlockSize()) != 0) { throw new IllegalArgumentException("buffer size not multiple of input block size"); } buf = new byte[bufSize]; bufOff = 0; } public int processByte( byte in, byte[] out, int outOff) { int resultLen = 0; buf[bufOff++] = in; if (bufOff == buf.length) { resultLen = translator.encode(buf, 0, buf.length, out, outOff); bufOff = 0; } return resultLen; } public int processBytes( byte[] in, int inOff, int len, byte[] out, int outOff) { if (len < 0) { throw new IllegalArgumentException("Can't have a negative input length!"); } int resultLen = 0; int gapLen = buf.length - bufOff; if (len > gapLen) { System.arraycopy(in, inOff, buf, bufOff, gapLen); resultLen += translator.encode(buf, 0, buf.length, out, outOff); bufOff = 0; len -= gapLen; inOff += gapLen; outOff += resultLen; int chunkSize = len - (len % buf.length); resultLen += translator.encode(in, inOff, chunkSize, out, outOff); len -= chunkSize; inOff += chunkSize; } if (len != 0) { System.arraycopy(in, inOff, buf, bufOff, len); bufOff += len; } return resultLen; } } azureus-4.3.0.6/org/bouncycastle/util/Arrays.java0000644000175000017500000000445710767602136021223 0ustar adrianadrianpackage org.bouncycastle.util; /** * General array utilities. */ public final class Arrays { private Arrays() { // static class, hide constructor } public static boolean areEqual( byte[] a, byte[] b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (a.length != b.length) { return false; } for (int i = 0; i != a.length; i++) { if (a[i] != b[i]) { return false; } } return true; } public static boolean areEqual( int[] a, int[] b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (a.length != b.length) { return false; } for (int i = 0; i != a.length; i++) { if (a[i] != b[i]) { return false; } } return true; } public static void fill( byte[] array, byte value) { for (int i = 0; i < array.length; i++) { array[i] = value; } } public static void fill( long[] array, long value) { for (int i = 0; i < array.length; i++) { array[i] = value; } } public static void fill( short[] array, short value) { for (int i = 0; i < array.length; i++) { array[i] = value; } } public static int hashCode(byte[] data) { int value = 0; if (data != null) { for (int i = 0; i != data.length; i++) { value ^= (data[i] & 0xff) << (i % 4); } } return value; } public static byte[] clone(byte[] data) { byte[] copy = new byte[data.length]; System.arraycopy(data, 0, copy, 0, data.length); return copy; } public static int[] clone(int[] data) { int[] copy = new int[data.length]; System.arraycopy(data, 0, copy, 0, data.length); return copy; } } azureus-4.3.0.6/org/bouncycastle/util/Selector.java0000644000175000017500000000021011026315702021506 0ustar adrianadrianpackage org.bouncycastle.util; public interface Selector extends Cloneable { boolean match(Object obj); Object clone(); } azureus-4.3.0.6/org/bouncycastle/x509/0000755000175000017500000000000011310377634016632 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/x509/AttributeCertificateHolder.java0000644000175000017500000003003111026315676024740 0ustar adrianadrianpackage org.bouncycastle.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.Holder; import org.bouncycastle.asn1.x509.IssuerSerial; import org.bouncycastle.asn1.x509.ObjectDigestInfo; import org.bouncycastle.jce.PrincipalUtil; import org.bouncycastle.jce.X509Principal; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Selector; import javax.security.auth.x500.X500Principal; import java.io.IOException; import java.math.BigInteger; import java.security.MessageDigest; import java.security.Principal; import java.security.cert.CertSelector; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; /** * The Holder object. * *

       *          Holder ::= SEQUENCE {
       *                baseCertificateID   [0] IssuerSerial OPTIONAL,
       *                         -- the issuer and serial number of
       *                         -- the holder's Public Key Certificate
       *                entityName          [1] GeneralNames OPTIONAL,
       *                         -- the name of the claimant or role
       *                objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
       *                         -- used to directly authenticate the holder,
       *                         -- for example, an executable
       *          }
       * 
      * */ public class AttributeCertificateHolder implements CertSelector, Selector { final Holder holder; AttributeCertificateHolder(ASN1Sequence seq) { holder = Holder.getInstance(seq); } public AttributeCertificateHolder(X509Principal issuerName, BigInteger serialNumber) { holder = new org.bouncycastle.asn1.x509.Holder(new IssuerSerial( new GeneralNames(new DERSequence(new GeneralName(issuerName))), new DERInteger(serialNumber))); } public AttributeCertificateHolder(X500Principal issuerName, BigInteger serialNumber) { this(X509Util.convertPrincipal(issuerName), serialNumber); } public AttributeCertificateHolder(X509Certificate cert) throws CertificateParsingException { X509Principal name; try { name = PrincipalUtil.getIssuerX509Principal(cert); } catch (Exception e) { throw new CertificateParsingException(e.getMessage()); } holder = new Holder(new IssuerSerial(generateGeneralNames(name), new DERInteger(cert.getSerialNumber()))); } public AttributeCertificateHolder(X509Principal principal) { holder = new Holder(generateGeneralNames(principal)); } public AttributeCertificateHolder(X500Principal principal) { this(X509Util.convertPrincipal(principal)); } /** * Constructs a holder for v2 attribute certificates with a hash value for * some type of object. *

      * digestedObjectType can be one of the following: *

        *
      • 0 - publicKey - A hash of the public key of the holder must be * passed. *
      • 1 - publicKeyCert - A hash of the public key certificate of the * holder must be passed. *
      • 2 - otherObjectDigest - A hash of some other object type must be * passed. otherObjectTypeID must not be empty. *
      *

      * This cannot be used if a v1 attribute certificate is used. * * @param digestedObjectType The digest object type. * @param digestAlgorithm The algorithm identifier for the hash. * @param otherObjectTypeID The object type ID if * digestedObjectType is * otherObjectDigest. * @param objectDigest The hash value. */ public AttributeCertificateHolder(int digestedObjectType, String digestAlgorithm, String otherObjectTypeID, byte[] objectDigest) { holder = new Holder(new ObjectDigestInfo(digestedObjectType, otherObjectTypeID, new AlgorithmIdentifier(digestAlgorithm), Arrays .clone(objectDigest))); } /** * Returns the digest object type if an object digest info is used. *

      *

        *
      • 0 - publicKey - A hash of the public key of the holder must be * passed. *
      • 1 - publicKeyCert - A hash of the public key certificate of the * holder must be passed. *
      • 2 - otherObjectDigest - A hash of some other object type must be * passed. otherObjectTypeID must not be empty. *
      * * @return The digest object type or -1 if no object digest info is set. */ public int getDigestedObjectType() { if (holder.getObjectDigestInfo() != null) { return holder.getObjectDigestInfo().getDigestedObjectType() .getValue().intValue(); } return -1; } /** * Returns the other object type ID if an object digest info is used. * * @return The other object type ID or null if no object * digest info is set. */ public String getDigestAlgorithm() { if (holder.getObjectDigestInfo() != null) { holder.getObjectDigestInfo().getDigestAlgorithm().getObjectId() .getId(); } return null; } /** * Returns the hash if an object digest info is used. * * @return The hash or null if no object digest info is set. */ public byte[] getObjectDigest() { if (holder.getObjectDigestInfo() != null) { holder.getObjectDigestInfo().getObjectDigest().getBytes(); } return null; } /** * Returns the digest algorithm ID if an object digest info is used. * * @return The digest algorithm ID or null if no object * digest info is set. */ public String getOtherObjectTypeID() { if (holder.getObjectDigestInfo() != null) { holder.getObjectDigestInfo().getOtherObjectTypeID().getId(); } return null; } private GeneralNames generateGeneralNames(X509Principal principal) { return new GeneralNames(new DERSequence(new GeneralName(principal))); } private boolean matchesDN(X509Principal subject, GeneralNames targets) { GeneralName[] names = targets.getNames(); for (int i = 0; i != names.length; i++) { GeneralName gn = names[i]; if (gn.getTagNo() == GeneralName.directoryName) { try { if (new X509Principal(((ASN1Encodable)gn.getName()) .getEncoded()).equals(subject)) { return true; } } catch (IOException e) { } } } return false; } private Object[] getNames(GeneralName[] names) { List l = new ArrayList(names.length); for (int i = 0; i != names.length; i++) { if (names[i].getTagNo() == GeneralName.directoryName) { try { l.add(new X500Principal( ((ASN1Encodable)names[i].getName()).getEncoded())); } catch (IOException e) { throw new RuntimeException("badly formed Name object"); } } } return l.toArray(new Object[l.size()]); } private Principal[] getPrincipals(GeneralNames names) { Object[] p = this.getNames(names.getNames()); List l = new ArrayList(); for (int i = 0; i != p.length; i++) { if (p[i] instanceof Principal) { l.add(p[i]); } } return (Principal[])l.toArray(new Principal[l.size()]); } /** * Return any principal objects inside the attribute certificate holder * entity names field. * * @return an array of Principal objects (usually X500Principal), null if no * entity names field is set. */ public Principal[] getEntityNames() { if (holder.getEntityName() != null) { return getPrincipals(holder.getEntityName()); } return null; } /** * Return the principals associated with the issuer attached to this holder * * @return an array of principals, null if no BaseCertificateID is set. */ public Principal[] getIssuer() { if (holder.getBaseCertificateID() != null) { return getPrincipals(holder.getBaseCertificateID().getIssuer()); } return null; } /** * Return the serial number associated with the issuer attached to this * holder. * * @return the certificate serial number, null if no BaseCertificateID is * set. */ public BigInteger getSerialNumber() { if (holder.getBaseCertificateID() != null) { return holder.getBaseCertificateID().getSerial().getValue(); } return null; } public Object clone() { return new AttributeCertificateHolder((ASN1Sequence)holder .toASN1Object()); } public boolean match(Certificate cert) { if (!(cert instanceof X509Certificate)) { return false; } X509Certificate x509Cert = (X509Certificate)cert; try { if (holder.getBaseCertificateID() != null) { return holder.getBaseCertificateID().getSerial().getValue().equals(x509Cert.getSerialNumber()) && matchesDN(PrincipalUtil.getIssuerX509Principal(x509Cert), holder.getBaseCertificateID().getIssuer()); } if (holder.getEntityName() != null) { if (matchesDN(PrincipalUtil.getSubjectX509Principal(x509Cert), holder.getEntityName())) { return true; } } if (holder.getObjectDigestInfo() != null) { MessageDigest md = null; try { md = MessageDigest.getInstance(getDigestAlgorithm(), "BC"); } catch (Exception e) { return false; } switch (getDigestedObjectType()) { case ObjectDigestInfo.publicKey: // TODO: DSA Dss-parms md.update(cert.getPublicKey().getEncoded()); break; case ObjectDigestInfo.publicKeyCert: md.update(cert.getEncoded()); break; } if (!Arrays.areEqual(md.digest(), getObjectDigest())) { return false; } } } catch (CertificateEncodingException e) { return false; } return false; } public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof AttributeCertificateHolder)) { return false; } AttributeCertificateHolder other = (AttributeCertificateHolder)obj; return this.holder.equals(other.holder); } public int hashCode() { return this.holder.hashCode(); } public boolean match(Object obj) { if (!(obj instanceof X509Certificate)) { return false; } return match((Certificate)obj); } } azureus-4.3.0.6/org/bouncycastle/x509/X509V2AttributeCertificate.java0000644000175000017500000002221311026315676024403 0ustar adrianadrianpackage org.bouncycastle.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.bouncycastle.asn1.x509.X509Extension; import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.util.Arrays; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; /** * An implementation of a version 2 X.509 Attribute Certificate. */ public class X509V2AttributeCertificate implements X509AttributeCertificate { private AttributeCertificate cert; private Date notBefore; private Date notAfter; public X509V2AttributeCertificate( InputStream encIn) throws IOException { this(AttributeCertificate.getInstance(new ASN1InputStream(encIn).readObject())); } public X509V2AttributeCertificate( byte[] encoded) throws IOException { this(new ByteArrayInputStream(encoded)); } X509V2AttributeCertificate( AttributeCertificate cert) throws IOException { this.cert = cert; try { this.notAfter = cert.getAcinfo().getAttrCertValidityPeriod().getNotAfterTime().getDate(); this.notBefore = cert.getAcinfo().getAttrCertValidityPeriod().getNotBeforeTime().getDate(); } catch (ParseException e) { throw new IOException("invalid data structure in certificate!"); } } public int getVersion() { return cert.getAcinfo().getVersion().getValue().intValue(); } public BigInteger getSerialNumber() { return cert.getAcinfo().getSerialNumber().getValue(); } public AttributeCertificateHolder getHolder() { return new AttributeCertificateHolder((ASN1Sequence)cert.getAcinfo().getHolder().toASN1Object()); } public AttributeCertificateIssuer getIssuer() { return new AttributeCertificateIssuer(cert.getAcinfo().getIssuer()); } public Date getNotBefore() { return notBefore; } public Date getNotAfter() { return notAfter; } public boolean[] getIssuerUniqueID() { DERBitString id = cert.getAcinfo().getIssuerUniqueID(); if (id != null) { byte[] bytes = id.getBytes(); boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()]; for (int i = 0; i != boolId.length; i++) { boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; } return boolId; } return null; } public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException { this.checkValidity(new Date()); } public void checkValidity( Date date) throws CertificateExpiredException, CertificateNotYetValidException { if (date.after(this.getNotAfter())) { throw new CertificateExpiredException("certificate expired on " + this.getNotAfter()); } if (date.before(this.getNotBefore())) { throw new CertificateNotYetValidException("certificate not valid till " + this.getNotBefore()); } } public byte[] getSignature() { return cert.getSignatureValue().getBytes(); } public final void verify( PublicKey key, String provider) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { Signature signature = null; if (!cert.getSignatureAlgorithm().equals(cert.getAcinfo().getSignature())) { throw new CertificateException("Signature algorithm in certificate info not same as outer certificate"); } signature = Signature.getInstance(cert.getSignatureAlgorithm().getObjectId().getId(), provider); signature.initVerify(key); try { signature.update(cert.getAcinfo().getEncoded()); } catch (IOException e) { throw new SignatureException("Exception encoding certificate info object"); } if (!signature.verify(this.getSignature())) { throw new InvalidKeyException("Public key presented not for certificate signature"); } } public byte[] getEncoded() throws IOException { return cert.getEncoded(); } public byte[] getExtensionValue(String oid) { X509Extensions extensions = cert.getAcinfo().getExtensions(); if (extensions != null) { X509Extension ext = extensions.getExtension(new DERObjectIdentifier(oid)); if (ext != null) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(ext.getValue()); return bOut.toByteArray(); } catch (Exception e) { throw new RuntimeException("error encoding " + e.toString()); } } } return null; } private Set getExtensionOIDs( boolean critical) { X509Extensions extensions = cert.getAcinfo().getExtensions(); if (extensions != null) { Set set = new HashSet(); Enumeration e = extensions.oids(); while (e.hasMoreElements()) { DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); X509Extension ext = extensions.getExtension(oid); if (ext.isCritical() == critical) { set.add(oid.getId()); } } return set; } return null; } public Set getNonCriticalExtensionOIDs() { return getExtensionOIDs(false); } public Set getCriticalExtensionOIDs() { return getExtensionOIDs(true); } public boolean hasUnsupportedCriticalExtension() { Set extensions = getCriticalExtensionOIDs(); return extensions != null && !extensions.isEmpty(); } public X509Attribute[] getAttributes() { ASN1Sequence seq = cert.getAcinfo().getAttributes(); X509Attribute[] attrs = new X509Attribute[seq.size()]; for (int i = 0; i != seq.size(); i++) { attrs[i] = new X509Attribute((ASN1Encodable)seq.getObjectAt(i)); } return attrs; } public X509Attribute[] getAttributes(String oid) { ASN1Sequence seq = cert.getAcinfo().getAttributes(); List list = new ArrayList(); for (int i = 0; i != seq.size(); i++) { X509Attribute attr = new X509Attribute((ASN1Encodable)seq.getObjectAt(i)); if (attr.getOID().equals(oid)) { list.add(attr); } } if (list.size() == 0) { return null; } return (X509Attribute[])list.toArray(new X509Attribute[list.size()]); } public boolean equals( Object o) { if (o == this) { return true; } if (!(o instanceof X509AttributeCertificate)) { return false; } X509AttributeCertificate other = (X509AttributeCertificate)o; try { byte[] b1 = this.getEncoded(); byte[] b2 = other.getEncoded(); return Arrays.areEqual(b1, b2); } catch (IOException e) { return false; } } public int hashCode() { try { byte[] b = this.getEncoded(); int value = 0; for (int i = 0; i != b.length; i++) { value ^= (b[i] & 0xff) << (i % 4); } return value; } catch (IOException e) { return 0; } } } azureus-4.3.0.6/org/bouncycastle/x509/X509AttributeCertificate.java0000644000175000017500000000552411026315676024201 0ustar adrianadrianpackage org.bouncycastle.x509; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PublicKey; import java.security.SignatureException; import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Extension; import java.util.Date; /** * Interface for an X.509 Attribute Certificate. */ public interface X509AttributeCertificate extends X509Extension { /** * Return the version number for the certificate. * * @return the version number. */ public int getVersion(); /** * Return the serial number for the certificate. * * @return the serial number. */ public BigInteger getSerialNumber(); /** * Return the date before which the certificate is not valid. * * @return the "not valid before" date. */ public Date getNotBefore(); /** * Return the date after which the certificate is not valid. * * @return the "not valid afer" date. */ public Date getNotAfter(); /** * Return the holder of the certificate. * * @return the holder. */ public AttributeCertificateHolder getHolder(); /** * Return the issuer details for the certificate. * * @return the issuer details. */ public AttributeCertificateIssuer getIssuer(); /** * Return the attributes contained in the attribute block in the certificate. * * @return an array of attributes. */ public X509Attribute[] getAttributes(); /** * Return the attributes with the same type as the passed in oid. * * @param oid the object identifier we wish to match. * @return an array of matched attributes, null if there is no match. */ public X509Attribute[] getAttributes(String oid); public boolean[] getIssuerUniqueID(); public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException; public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException; public byte[] getSignature(); public void verify(PublicKey key, String provider) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException; /** * Return an ASN.1 encoded byte array representing the attribute certificate. * * @return an ASN.1 encoded byte array. * @throws IOException if the certificate cannot be encoded. */ public byte[] getEncoded() throws IOException; } azureus-4.3.0.6/org/bouncycastle/x509/X509Util.java0000644000175000017500000003515311026315676021011 0ustar adrianadrianpackage org.bouncycastle.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DERObjectIdentifier; //import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; //import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; //import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; //import org.bouncycastle.asn1.pkcs.RSASSAPSSparams; import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.jce.X509Principal; import org.bouncycastle.util.Strings; import javax.security.auth.x500.X500Principal; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.Provider; import java.security.SecureRandom; import java.security.Security; import java.security.Signature; import java.security.SignatureException; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Set; class X509Util { private static Hashtable algorithms = new Hashtable(); private static Hashtable params = new Hashtable(); private static Set noParams = new HashSet(); static { algorithms.put("MD2WITHRSAENCRYPTION", PKCSObjectIdentifiers.md2WithRSAEncryption); algorithms.put("MD2WITHRSA", PKCSObjectIdentifiers.md2WithRSAEncryption); algorithms.put("MD5WITHRSAENCRYPTION", PKCSObjectIdentifiers.md5WithRSAEncryption); algorithms.put("MD5WITHRSA", PKCSObjectIdentifiers.md5WithRSAEncryption); algorithms.put("SHA1WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha1WithRSAEncryption); algorithms.put("SHA1WITHRSA", PKCSObjectIdentifiers.sha1WithRSAEncryption); // algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption); // algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption); algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption); algorithms.put("SHA256WITHRSA", PKCSObjectIdentifiers.sha256WithRSAEncryption); algorithms.put("SHA384WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha384WithRSAEncryption); algorithms.put("SHA384WITHRSA", PKCSObjectIdentifiers.sha384WithRSAEncryption); algorithms.put("SHA512WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha512WithRSAEncryption); algorithms.put("SHA512WITHRSA", PKCSObjectIdentifiers.sha512WithRSAEncryption); // algorithms.put("SHA1WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); // algorithms.put("SHA224WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); // algorithms.put("SHA256WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); // algorithms.put("SHA384WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); // algorithms.put("SHA512WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); algorithms.put("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); algorithms.put("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); algorithms.put("SHA1WITHDSA", X9ObjectIdentifiers.id_dsa_with_sha1); algorithms.put("DSAWITHSHA1", X9ObjectIdentifiers.id_dsa_with_sha1); // algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224); // algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256); algorithms.put("SHA1WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA1); algorithms.put("ECDSAWITHSHA1", X9ObjectIdentifiers.ecdsa_with_SHA1); // algorithms.put("SHA224WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA224); // algorithms.put("SHA256WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256); // algorithms.put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384); // algorithms.put("SHA512WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512); // algorithms.put("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); // algorithms.put("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); // algorithms.put("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); // algorithms.put("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); // algorithms.put("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); // // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field. // The parameters field SHALL be NULL for RSA based signature algorithms. // noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA1); // noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA224); // noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA256); // noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA384); // noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA512); noParams.add(X9ObjectIdentifiers.id_dsa_with_sha1); // noParams.add(NISTObjectIdentifiers.dsa_with_sha224); // noParams.add(NISTObjectIdentifiers.dsa_with_sha256); // // RFC 4491 // // noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); // noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); // // explicit params // /* AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, new DERNull()); params.put("SHA1WITHRSAANDMGF1", creatPSSParams(sha1AlgId, 20)); AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha224, new DERNull()); params.put("SHA224WITHRSAANDMGF1", creatPSSParams(sha224AlgId, 28)); AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, new DERNull()); params.put("SHA256WITHRSAANDMGF1", creatPSSParams(sha256AlgId, 32)); AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha384, new DERNull()); params.put("SHA384WITHRSAANDMGF1", creatPSSParams(sha384AlgId, 48)); AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha512, new DERNull()); params.put("SHA512WITHRSAANDMGF1", creatPSSParams(sha512AlgId, 64)); */ } /* PARG - commented out a lot of these private static RSASSAPSSparams creatPSSParams(AlgorithmIdentifier hashAlgId, int saltSize) { return new RSASSAPSSparams( hashAlgId, new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, hashAlgId), new DERInteger(saltSize), new DERInteger(1)); } */ static DERObjectIdentifier getAlgorithmOID( String algorithmName) { algorithmName = Strings.toUpperCase(algorithmName); if (algorithms.containsKey(algorithmName)) { return (DERObjectIdentifier)algorithms.get(algorithmName); } return new DERObjectIdentifier(algorithmName); } static AlgorithmIdentifier getSigAlgID( DERObjectIdentifier sigOid, String algorithmName) { if (noParams.contains(sigOid)) { return new AlgorithmIdentifier(sigOid); } algorithmName = Strings.toUpperCase(algorithmName); if (params.containsKey(algorithmName)) { return new AlgorithmIdentifier(sigOid, (DEREncodable)params.get(algorithmName)); } else { return new AlgorithmIdentifier(sigOid, new DERNull()); } } static Iterator getAlgNames() { Enumeration e = algorithms.keys(); List l = new ArrayList(); while (e.hasMoreElements()) { l.add(e.nextElement()); } return l.iterator(); } static Signature getSignatureInstance( String algorithm) throws NoSuchAlgorithmException { return Signature.getInstance(algorithm); } static Signature getSignatureInstance( String algorithm, String provider) throws NoSuchProviderException, NoSuchAlgorithmException { if (provider != null) { return Signature.getInstance(algorithm, provider); } else { return Signature.getInstance(algorithm); } } static byte[] calculateSignature( DERObjectIdentifier sigOid, String sigName, PrivateKey key, SecureRandom random, ASN1Encodable object) throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { Signature sig; if (sigOid == null) { throw new IllegalStateException("no signature algorithm specified"); } sig = X509Util.getSignatureInstance(sigName); if (random != null) { sig.initSign(key, random); } else { sig.initSign(key); } sig.update(object.getEncoded(ASN1Encodable.DER)); return sig.sign(); } static byte[] calculateSignature( DERObjectIdentifier sigOid, String sigName, String provider, PrivateKey key, SecureRandom random, ASN1Encodable object) throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { Signature sig; if (sigOid == null) { throw new IllegalStateException("no signature algorithm specified"); } sig = X509Util.getSignatureInstance(sigName, provider); if (random != null) { sig.initSign(key, random); } else { sig.initSign(key); } sig.update(object.getEncoded(ASN1Encodable.DER)); return sig.sign(); } static X509Principal convertPrincipal( X500Principal principal) { try { return new X509Principal(principal.getEncoded()); } catch (IOException e) { throw new IllegalArgumentException("cannot convert principal"); } } static class Implementation { Object engine; Provider provider; Implementation( Object engine, Provider provider) { this.engine = engine; this.provider = provider; } Object getEngine() { return engine; } Provider getProvider() { return provider; } } /** * see if we can find an algorithm (or its alias and what it represents) in * the property table for the given provider. */ static Implementation getImplementation( String baseName, String algorithm, Provider prov) throws NoSuchAlgorithmException { algorithm = Strings.toUpperCase(algorithm); String alias; while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null) { algorithm = alias; } String className = prov.getProperty(baseName + "." + algorithm); if (className != null) { try { Class cls; ClassLoader clsLoader = prov.getClass().getClassLoader(); if (clsLoader != null) { cls = clsLoader.loadClass(className); } else { cls = Class.forName(className); } return new Implementation(cls.newInstance(), prov); } catch (ClassNotFoundException e) { throw new IllegalStateException( "algorithm " + algorithm + " in provider " + prov.getName() + " but no class \"" + className + "\" found!"); } catch (Exception e) { throw new IllegalStateException( "algorithm " + algorithm + " in provider " + prov.getName() + " but class \"" + className + "\" inaccessible!"); } } throw new NoSuchAlgorithmException("cannot find implementation " + algorithm + " for provider " + prov.getName()); } /** * return an implementation for a given algorithm/provider. * If the provider is null, we grab the first avalaible who has the required algorithm. */ static Implementation getImplementation( String baseName, String algorithm) throws NoSuchAlgorithmException { Provider[] prov = Security.getProviders(); // // search every provider looking for the algorithm we want. // for (int i = 0; i != prov.length; i++) { // // try case insensitive // Implementation imp = getImplementation(baseName, Strings.toUpperCase(algorithm), prov[i]); if (imp != null) { return imp; } try { imp = getImplementation(baseName, algorithm, prov[i]); } catch (NoSuchAlgorithmException e) { // continue } } throw new NoSuchAlgorithmException("cannot find implementation " + algorithm); } static Provider getProvider(String provider) throws NoSuchProviderException { Provider prov = Security.getProvider(provider); if (prov == null) { throw new NoSuchProviderException("Provider " + provider + " not found"); } return prov; } } azureus-4.3.0.6/org/bouncycastle/x509/X509Attribute.java0000644000175000017500000000410111026315674022022 0ustar adrianadrianpackage org.bouncycastle.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.x509.Attribute; /** * Class for carrying the values in an X.509 Attribute. */ public class X509Attribute extends ASN1Encodable { Attribute attr; /** * @param at an object representing an attribute. */ X509Attribute( ASN1Encodable at) { this.attr = Attribute.getInstance(at); } /** * Create an X.509 Attribute with the type given by the passed in oid and * the value represented by an ASN.1 Set containing value. * * @param oid type of the attribute * @param value value object to go into the atribute's value set. */ public X509Attribute( String oid, ASN1Encodable value) { this.attr = new Attribute(new DERObjectIdentifier(oid), new DERSet(value)); } /** * Create an X.59 Attribute with the type given by the passed in oid and the * value represented by an ASN.1 Set containing the objects in value. * * @param oid type of the attribute * @param value vector of values to go in the attribute's value set. */ public X509Attribute( String oid, ASN1EncodableVector value) { this.attr = new Attribute(new DERObjectIdentifier(oid), new DERSet(value)); } public String getOID() { return attr.getAttrType().getId(); } public ASN1Encodable[] getValues() { ASN1Set s = attr.getAttrValues(); ASN1Encodable[] values = new ASN1Encodable[s.size()]; for (int i = 0; i != s.size(); i++) { values[i] = (ASN1Encodable)s.getObjectAt(i); } return values; } public DERObject toASN1Object() { return attr.toASN1Object(); } } azureus-4.3.0.6/org/bouncycastle/x509/AttributeCertificateIssuer.java0000644000175000017500000001216611026315676025006 0ustar adrianadrianpackage org.bouncycastle.x509; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.AttCertIssuer; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.V2Form; import org.bouncycastle.jce.X509Principal; import org.bouncycastle.util.Selector; import javax.security.auth.x500.X500Principal; import java.io.IOException; import java.security.Principal; import java.security.cert.CertSelector; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; /** * Carrying class for an attribute certificate issuer. */ public class AttributeCertificateIssuer implements CertSelector, Selector { final ASN1Encodable form; /** * Set the issuer directly with the ASN.1 structure. * * @param issuer The issuer */ AttributeCertificateIssuer(AttCertIssuer issuer) { form = issuer.getIssuer(); } public AttributeCertificateIssuer(X500Principal principal) throws IOException { this(new X509Principal(principal.getEncoded())); } public AttributeCertificateIssuer(X509Principal principal) { form = new V2Form(new GeneralNames(new DERSequence(new GeneralName(principal)))); } private Object[] getNames() { GeneralNames name; if (form instanceof V2Form) { name = ((V2Form)form).getIssuerName(); } else { name = (GeneralNames)form; } GeneralName[] names = name.getNames(); List l = new ArrayList(names.length); for (int i = 0; i != names.length; i++) { if (names[i].getTagNo() == GeneralName.directoryName) { try { l.add(new X500Principal( ((ASN1Encodable)names[i].getName()).getEncoded())); } catch (IOException e) { throw new RuntimeException("badly formed Name object"); } } } return l.toArray(new Object[l.size()]); } /** * Return any principal objects inside the attribute certificate issuer * object. * * @return an array of Principal objects (usually X500Principal) */ public Principal[] getPrincipals() { Object[] p = this.getNames(); List l = new ArrayList(); for (int i = 0; i != p.length; i++) { if (p[i] instanceof Principal) { l.add(p[i]); } } return (Principal[])l.toArray(new Principal[l.size()]); } private boolean matchesDN(X500Principal subject, GeneralNames targets) { GeneralName[] names = targets.getNames(); for (int i = 0; i != names.length; i++) { GeneralName gn = names[i]; if (gn.getTagNo() == GeneralName.directoryName) { try { if (new X500Principal(((ASN1Encodable)gn.getName()).getEncoded()).equals(subject)) { return true; } } catch (IOException e) { } } } return false; } public Object clone() { return new AttributeCertificateIssuer(AttCertIssuer.getInstance(form)); } public boolean match(Certificate cert) { if (!(cert instanceof X509Certificate)) { return false; } X509Certificate x509Cert = (X509Certificate)cert; if (form instanceof V2Form) { V2Form issuer = (V2Form)form; if (issuer.getBaseCertificateID() != null) { return issuer.getBaseCertificateID().getSerial().getValue().equals(x509Cert.getSerialNumber()) && matchesDN(x509Cert.getIssuerX500Principal(), issuer.getBaseCertificateID().getIssuer()); } GeneralNames name = issuer.getIssuerName(); if (matchesDN(x509Cert.getSubjectX500Principal(), name)) { return true; } } else { GeneralNames name = (GeneralNames)form; if (matchesDN(x509Cert.getSubjectX500Principal(), name)) { return true; } } return false; } public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof AttributeCertificateIssuer)) { return false; } AttributeCertificateIssuer other = (AttributeCertificateIssuer)obj; return this.form.equals(other.form); } public int hashCode() { return this.form.hashCode(); } public boolean match(Object obj) { if (!(obj instanceof X509Certificate)) { return false; } return match((Certificate)obj); } } azureus-4.3.0.6/org/bouncycastle/crypto/0000755000175000017500000000000011310377632017443 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/crypto/CipherParameters.java0000644000175000017500000000017110061400652023532 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * all parameter classes implement this. */ public interface CipherParameters { } azureus-4.3.0.6/org/bouncycastle/crypto/BasicAgreement.java0000644000175000017500000000074210061400652023151 0ustar adrianadrianpackage org.bouncycastle.crypto; import java.math.BigInteger; /** * The basic interface that basic Diffie-Hellman implementations * conforms to. */ public interface BasicAgreement { /** * initialise the agreement engine. */ public void init(CipherParameters param); /** * given a public key from a given party calculate the next * message in the agreement sequence. */ public BigInteger calculateAgreement(CipherParameters pubKey); } azureus-4.3.0.6/org/bouncycastle/crypto/DSA.java0000644000175000017500000000211010061400652020676 0ustar adrianadrianpackage org.bouncycastle.crypto; import java.math.BigInteger; /** * interface for classes implementing the Digital Signature Algorithm */ public interface DSA { /** * initialise the signer for signature generation or signature * verification. * * @param forSigning true if we are generating a signature, false * otherwise. * @param param key parameters for signature generation. */ public void init(boolean forSigning, CipherParameters param); /** * sign the passed in message (usually the output of a hash function). * * @param message the message to be signed. * @return two big integers representing the r and s values respectively. */ public BigInteger[] generateSignature(byte[] message); /** * verify the message message against the signature values r and s. * * @param message the message that was supposed to have been signed. * @param r the r signature value. * @param s the s signature value. */ public boolean verifySignature(byte[] message, BigInteger r, BigInteger s); } azureus-4.3.0.6/org/bouncycastle/crypto/StreamBlockCipher.java0000644000175000017500000000546710061400652023652 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * a wrapper for block ciphers with a single byte block size, so that they * can be treated like stream ciphers. */ public class StreamBlockCipher implements StreamCipher { private BlockCipher cipher; private byte[] oneByte = new byte[1]; /** * basic constructor. * * @param cipher the block cipher to be wrapped. * @exception IllegalArgumentException if the cipher has a block size other than * one. */ public StreamBlockCipher( BlockCipher cipher) { if (cipher.getBlockSize() != 1) { throw new IllegalArgumentException("block cipher block size != 1."); } this.cipher = cipher; } /** * initialise the underlying cipher. * * @param forEncryption true if we are setting up for encryption, false otherwise. * @param param the necessary parameters for the underlying cipher to be initialised. */ public void init( boolean forEncryption, CipherParameters params) { cipher.init(forEncryption, params); } /** * return the name of the algorithm we are wrapping. * * @return the name of the algorithm we are wrapping. */ public String getAlgorithmName() { return cipher.getAlgorithmName(); } /** * encrypt/decrypt a single byte returning the result. * * @param in the byte to be processed. * @return the result of processing the input byte. */ public byte returnByte( byte in) { oneByte[0] = in; cipher.processBlock(oneByte, 0, oneByte, 0); return oneByte[0]; } /** * process a block of bytes from in putting the result into out. * * @param in the input byte array. * @param inOff the offset into the in array where the data to be processed starts. * @param len the number of bytes to be processed. * @param out the output buffer the processed bytes go into. * @param outOff the offset into the output byte array the processed data stars at. * @exception DataLengthException if the output buffer is too small. */ public void processBytes( byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException { if (outOff + len > out.length) { throw new DataLengthException("output buffer too small in processBytes()"); } for (int i = 0; i != len; i++) { cipher.processBlock(in, inOff + i, out, outOff + i); } } /** * reset the underlying cipher. This leaves it in the same state * it was at after the last init (if there was one). */ public void reset() { cipher.reset(); } } azureus-4.3.0.6/org/bouncycastle/crypto/CipherKeyGenerator.java0000644000175000017500000000143510061400652024032 0ustar adrianadrianpackage org.bouncycastle.crypto; import java.security.SecureRandom; /** * The base class for symmetric, or secret, cipher key generators. */ public class CipherKeyGenerator { protected SecureRandom random; protected int strength; /** * initialise the key generator. * * @param param the parameters to be used for key generation */ public void init( KeyGenerationParameters param) { this.random = param.getRandom(); this.strength = (param.getStrength() + 7) / 8; } /** * generate a secret key. * * @return a byte array containing the key value. */ public byte[] generateKey() { byte[] key = new byte[strength]; random.nextBytes(key); return key; } } azureus-4.3.0.6/org/bouncycastle/crypto/KeyGenerationParameters.java0000644000175000017500000000211710061400652025066 0ustar adrianadrianpackage org.bouncycastle.crypto; import java.security.SecureRandom; /** * The base class for parameters to key generators. */ public class KeyGenerationParameters { private SecureRandom random; private int strength; /** * initialise the generator with a source of randomness * and a strength (in bits). * * @param random the random byte source. * @param strength the size, in bits, of the keys we want to produce. */ public KeyGenerationParameters( SecureRandom random, int strength) { this.random = random; this.strength = strength; } /** * return the random source associated with this * generator. * * @return the generators random source. */ public SecureRandom getRandom() { return random; } /** * return the bit strength for keys produced by this generator, * * @return the strength of the keys this generator produces (in bits). */ public int getStrength() { return strength; } } azureus-4.3.0.6/org/bouncycastle/crypto/macs/0000755000175000017500000000000011310377634020370 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/crypto/macs/HMac.java0000644000175000017500000000467410407566336022063 0ustar adrianadrianpackage org.bouncycastle.crypto.macs; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.Mac; import org.bouncycastle.crypto.params.KeyParameter; /** * HMAC implementation based on RFC2104 * * H(K XOR opad, H(K XOR ipad, text)) */ public class HMac implements Mac { private final static int BLOCK_LENGTH = 64; private final static byte IPAD = (byte)0x36; private final static byte OPAD = (byte)0x5C; private Digest digest; private int digestSize; private byte[] inputPad = new byte[BLOCK_LENGTH]; private byte[] outputPad = new byte[BLOCK_LENGTH]; public HMac( Digest digest) { this.digest = digest; digestSize = digest.getDigestSize(); } public String getAlgorithmName() { return digest.getAlgorithmName() + "/HMAC"; } public Digest getUnderlyingDigest() { return digest; } public void init( CipherParameters params) { digest.reset(); byte[] key = ((KeyParameter)params).getKey(); if (key.length > BLOCK_LENGTH) { digest.update(key, 0, key.length); digest.doFinal(inputPad, 0); for (int i = digestSize; i < inputPad.length; i++) { inputPad[i] = 0; } } else { System.arraycopy(key, 0, inputPad, 0, key.length); for (int i = key.length; i < inputPad.length; i++) { inputPad[i] = 0; } } outputPad = new byte[inputPad.length]; System.arraycopy(inputPad, 0, outputPad, 0, inputPad.length); for (int i = 0; i < inputPad.length; i++) { inputPad[i] ^= IPAD; } for (int i = 0; i < outputPad.length; i++) { outputPad[i] ^= OPAD; } digest.update(inputPad, 0, inputPad.length); } public int getMacSize() { return digestSize; } public void update( byte in) { digest.update(in); } public void update( byte[] in, int inOff, int len) { digest.update(in, inOff, len); } public int doFinal( byte[] out, int outOff) { byte[] tmp = new byte[digestSize]; digest.doFinal(tmp, 0); digest.update(outputPad, 0, outputPad.length); digest.update(tmp, 0, tmp.length); int len = digest.doFinal(out, outOff); reset(); return len; } /** * Reset the mac generator. */ public void reset() { /* * reset the underlying digest. */ digest.reset(); /* * reinitialize the digest. */ digest.update(inputPad, 0, inputPad.length); } } azureus-4.3.0.6/org/bouncycastle/crypto/Digest.java0000644000175000017500000000245710061400652021524 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * interface that a message digest conforms to. */ public interface Digest { /** * return the algorithm name * * @return the algorithm name */ public String getAlgorithmName(); /** * return the size, in bytes, of the digest produced by this message digest. * * @return the size, in bytes, of the digest produced by this message digest. */ public int getDigestSize(); /** * update the message digest with a single byte. * * @param in the input byte to be entered. */ public void update(byte in); /** * update the message digest with a block of bytes. * * @param in the byte array containing the data. * @param inOff the offset into the byte array where the data starts. * @param len the length of the data. */ public void update(byte[] in, int inOff, int len); /** * close the digest, producing the final digest value. The doFinal * call leaves the digest reset. * * @param out the array the digest is to be copied into. * @param outOff the offset into the out array the digest is to start at. */ public int doFinal(byte[] out, int outOff); /** * reset the digest back to it's initial state. */ public void reset(); } azureus-4.3.0.6/org/bouncycastle/crypto/PBEParametersGenerator.java0000644000175000017500000000731210061400652024601 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * super class for all Password Based Encyrption (PBE) parameter generator classes. */ public abstract class PBEParametersGenerator { protected byte[] password; protected byte[] salt; protected int iterationCount; /** * base constructor. */ protected PBEParametersGenerator() { } /** * initialise the PBE generator. * * @param password the password converted into bytes (see below). * @param salt the salt to be mixed with the password. * @param iterationCount the number of iterations the "mixing" function * is to be applied for. */ public void init( byte[] password, byte[] salt, int iterationCount) { this.password = password; this.salt = salt; this.iterationCount = iterationCount; } /** * return the password byte array. * * @return the password byte array. */ public byte[] getPassword() { return password; } /** * return the salt byte array. * * @return the salt byte array. */ public byte[] getSalt() { return salt; } /** * return the iteration count. * * @return the iteration count. */ public int getIterationCount() { return iterationCount; } /** * generate derived parameters for a key of length keySize. * * @param keySize the length, in bits, of the key required. * @return a parameters object representing a key. */ public abstract CipherParameters generateDerivedParameters(int keySize); /** * generate derived parameters for a key of length keySize, and * an initialisation vector (IV) of length ivSize. * * @param keySize the length, in bits, of the key required. * @param ivSize the length, in bits, of the iv required. * @return a parameters object representing a key and an IV. */ public abstract CipherParameters generateDerivedParameters(int keySize, int ivSize); /** * generate derived parameters for a key of length keySize, specifically * for use with a MAC. * * @param keySize the length, in bits, of the key required. * @return a parameters object representing a key. */ public abstract CipherParameters generateDerivedMacParameters(int keySize); /** * converts a password to a byte array according to the scheme in * PKCS5 (ascii, no padding) * * @param password a character array reqpresenting the password. * @return a byte array representing the password. */ public static byte[] PKCS5PasswordToBytes( char[] password) { byte[] bytes = new byte[password.length]; for (int i = 0; i != bytes.length; i++) { bytes[i] = (byte)password[i]; } return bytes; } /** * converts a password to a byte array according to the scheme in * PKCS12 (unicode, big endian, 2 zero pad bytes at the end). * * @param password a character array reqpresenting the password. * @return a byte array representing the password. */ public static byte[] PKCS12PasswordToBytes( char[] password) { if (password.length > 0) { // +1 for extra 2 pad bytes. byte[] bytes = new byte[(password.length + 1) * 2]; for (int i = 0; i != password.length; i ++) { bytes[i * 2] = (byte)(password[i] >>> 8); bytes[i * 2 + 1] = (byte)password[i]; } return bytes; } else { return new byte[0]; } } } azureus-4.3.0.6/org/bouncycastle/crypto/BlockCipher.java0000644000175000017500000000346010061400652022465 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * Block cipher engines are expected to conform to this interface. */ public interface BlockCipher { /** * Initialise the cipher. * * @param forEncryption if true the cipher is initialised for * encryption, if false for decryption. * @param param the key and other data required by the cipher. * @exception IllegalArgumentException if the params argument is * inappropriate. */ public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException; /** * Return the name of the algorithm the cipher implements. * * @return the name of the algorithm the cipher implements. */ public String getAlgorithmName(); /** * Return the block size for this cipher (in bytes). * * @return the block size for this cipher in bytes. */ public int getBlockSize(); /** * Process one block of input from the array in and write it to * the out array. * * @param in the array containing the input data. * @param inOff offset into the in array the data starts at. * @param out the array the output data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ public int processBlock(byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException; /** * Reset the cipher. After resetting the cipher is in the same state * as it was after the last init (if there was one). */ public void reset(); } azureus-4.3.0.6/org/bouncycastle/crypto/engines/0000755000175000017500000000000011310377634021075 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/crypto/engines/IESEngine.java0000644000175000017500000001624710407566336023525 0ustar adrianadrianpackage org.bouncycastle.crypto.engines; import java.math.BigInteger; import org.bouncycastle.crypto.BasicAgreement; import org.bouncycastle.crypto.BufferedBlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DerivationFunction; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.Mac; import org.bouncycastle.crypto.params.IESParameters; import org.bouncycastle.crypto.params.IESWithCipherParameters; import org.bouncycastle.crypto.params.KDFParameters; import org.bouncycastle.crypto.params.KeyParameter; /** * support class for constructing intergrated encryption ciphers * for doing basic message exchanges on top of key agreement ciphers */ public class IESEngine { BasicAgreement agree; DerivationFunction kdf; Mac mac; BufferedBlockCipher cipher; byte[] macBuf; boolean forEncryption; CipherParameters privParam, pubParam; IESParameters param; /** * set up for use with stream mode, where the key derivation function * is used to provide a stream of bytes to xor with the message. * * @param agree the key agreement used as the basis for the encryption * @param kdf the key derivation function used for byte generation * @param mac the message authentication code generator for the message */ public IESEngine( BasicAgreement agree, DerivationFunction kdf, Mac mac) { this.agree = agree; this.kdf = kdf; this.mac = mac; this.macBuf = new byte[mac.getMacSize()]; this.cipher = null; } /** * set up for use in conjunction with a block cipher to handle the * message. * * @param agree the key agreement used as the basis for the encryption * @param kdf the key derivation function used for byte generation * @param mac the message authentication code generator for the message * @param cipher the cipher to used for encrypting the message */ public IESEngine( BasicAgreement agree, DerivationFunction kdf, Mac mac, BufferedBlockCipher cipher) { this.agree = agree; this.kdf = kdf; this.mac = mac; this.macBuf = new byte[mac.getMacSize()]; this.cipher = cipher; } /** * Initialise the encryptor. * * @param forEncryption whether or not this is encryption/decryption. * @param privParam our private key parameters * @param pubParam the recipient's/sender's public key parameters * @param param encoding and derivation parameters. */ public void init( boolean forEncryption, CipherParameters privParam, CipherParameters pubParam, CipherParameters param) { this.forEncryption = forEncryption; this.privParam = privParam; this.pubParam = pubParam; this.param = (IESParameters)param; } private byte[] decryptBlock( byte[] in_enc, int inOff, int inLen, byte[] z) throws InvalidCipherTextException { byte[] M = null; KeyParameter macKey = null; KDFParameters kParam = new KDFParameters(z, param.getDerivationV()); int macKeySize = param.getMacKeySize(); kdf.init(kParam); inLen -= mac.getMacSize(); if (cipher == null) // stream mode { byte[] buf = new byte[inLen + (macKeySize / 8)]; M = new byte[inLen]; kdf.generateBytes(buf, 0, buf.length); for (int i = 0; i != inLen; i++) { M[i] = (byte)(in_enc[inOff + i] ^ buf[i]); } macKey = new KeyParameter(buf, inLen, (macKeySize / 8)); } else { int cipherKeySize = ((IESWithCipherParameters)param).getCipherKeySize(); byte[] buf = new byte[(cipherKeySize / 8) + (macKeySize / 8)]; cipher.init(false, new KeyParameter(buf, 0, (cipherKeySize / 8))); byte[] tmp = new byte[cipher.getOutputSize(inLen)]; int off = cipher.processBytes(in_enc, inOff, inLen, tmp, 0); off += cipher.doFinal(tmp, off); M = new byte[off]; System.arraycopy(tmp, 0, M, 0, off); macKey = new KeyParameter(buf, (cipherKeySize / 8), (macKeySize / 8)); } byte[] macIV = param.getEncodingV(); mac.init(macKey); mac.update(in_enc, inOff, inLen); mac.update(macIV, 0, macIV.length); mac.doFinal(macBuf, 0); inOff += inLen; for (int t = 0; t < macBuf.length; t++) { if (macBuf[t] != in_enc[inOff + t]) { throw (new InvalidCipherTextException("Mac codes failed to equal.")); } } return M; } private byte[] encryptBlock( byte[] in, int inOff, int inLen, byte[] z) throws InvalidCipherTextException { byte[] C = null; KeyParameter macKey = null; KDFParameters kParam = new KDFParameters(z, param.getDerivationV()); int c_text_length = 0; int macKeySize = param.getMacKeySize(); kdf.init(kParam); if (cipher == null) // stream mode { byte[] buf = new byte[inLen + (macKeySize / 8)]; C = new byte[inLen + mac.getMacSize()]; c_text_length = inLen; kdf.generateBytes(buf, 0, buf.length); for (int i = 0; i != inLen; i++) { C[i] = (byte)(in[inOff + i] ^ buf[i]); } macKey = new KeyParameter(buf, inLen, (macKeySize / 8)); } else { int cipherKeySize = ((IESWithCipherParameters)param).getCipherKeySize(); byte[] buf = new byte[(cipherKeySize / 8) + (macKeySize / 8)]; cipher.init(true, new KeyParameter(buf, 0, (cipherKeySize / 8))); c_text_length = cipher.getOutputSize(inLen); C = new byte[c_text_length + mac.getMacSize()]; int off = cipher.processBytes(in, inOff, inLen, C, 0); cipher.doFinal(C, off); macKey = new KeyParameter(buf, (cipherKeySize / 8), (macKeySize / 8)); } byte[] macIV = param.getEncodingV(); mac.init(macKey); mac.update(C, 0, c_text_length); mac.update(macIV, 0, macIV.length); // // return the message and it's MAC // mac.doFinal(C, c_text_length); return C; } public byte[] processBlock( byte[] in, int inOff, int inLen) throws InvalidCipherTextException { agree.init(privParam); BigInteger z = agree.calculateAgreement(pubParam); if (forEncryption) { return encryptBlock(in, inOff, inLen, z.toByteArray()); } else { return decryptBlock(in, inOff, inLen, z.toByteArray()); } } } azureus-4.3.0.6/org/bouncycastle/crypto/engines/RC4Engine.java0000644000175000017500000000743710551530114023457 0ustar adrianadrianpackage org.bouncycastle.crypto.engines; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.StreamCipher; import org.bouncycastle.crypto.params.KeyParameter; public class RC4Engine implements StreamCipher { private final static int STATE_LENGTH = 256; /* * variables to hold the state of the RC4 engine * during encryption and decryption */ private byte[] engineState = null; private int x = 0; private int y = 0; private byte[] workingKey = null; /** * initialise a RC4 cipher. * * @param forEncryption whether or not we are for encryption. * @param params the parameters required to set up the cipher. * @exception IllegalArgumentException if the params argument is * inappropriate. */ public void init( boolean forEncryption, CipherParameters params ) { if (params instanceof KeyParameter) { /* * RC4 encryption and decryption is completely * symmetrical, so the 'forEncryption' is * irrelevant. */ workingKey = ((KeyParameter)params).getKey(); setKey(workingKey); return; } throw new IllegalArgumentException("invalid parameter passed to RC4 init - " + params.getClass().getName()); } public String getAlgorithmName() { return "RC4"; } public byte returnByte(byte in) { x = (x + 1) & 0xff; y = (engineState[x] + y) & 0xff; // swap byte tmp = engineState[x]; engineState[x] = engineState[y]; engineState[y] = tmp; // xor return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]); } public void processBytes( byte[] in, int inOff, int len, byte[] out, int outOff ) { for (int i = 0; i < len ; i++) { x = (x + 1) & 0xff; y = (engineState[x] + y) & 0xff; // swap byte tmp = engineState[x]; engineState[x] = engineState[y]; engineState[y] = tmp; // xor out[i+outOff] = (byte)(in[i + inOff] ^ engineState[(engineState[x] + engineState[y]) & 0xff]); } } /* public void processBytes( byte[] in, byte[] out ) { int len = in.length; for (int i = 0; i < len ; i++) { x = (x + 1) & 0xff; y = (engineState[x] + y) & 0xff; // swap byte tmp = engineState[x]; engineState[x] = engineState[y]; engineState[y] = tmp; // xor out[i] = (byte)(in[i] ^ engineState[(engineState[x] + engineState[y]) & 0xff]); } } */ public void reset() { setKey(workingKey); } // Private implementation private void setKey(byte[] keyBytes) { workingKey = keyBytes; // System.out.println("the key length is ; "+ workingKey.length); x = 0; y = 0; if (engineState == null) { engineState = new byte[STATE_LENGTH]; } // reset the state of the engine for (int i=0; i < STATE_LENGTH; i++) { engineState[i] = (byte)i; } int i1 = 0; int i2 = 0; for (int i=0; i < STATE_LENGTH; i++) { i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff; // do the byte-swap inline byte tmp = engineState[i]; engineState[i] = engineState[i2]; engineState[i2] = tmp; i1 = (i1+1) % keyBytes.length; } } } azureus-4.3.0.6/org/bouncycastle/crypto/engines/RSAEngine.java0000644000175000017500000001264210202232522023501 0ustar adrianadrianpackage org.bouncycastle.crypto.engines; import java.math.BigInteger; import org.bouncycastle.crypto.AsymmetricBlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; /** * this does your basic RSA algorithm. */ public class RSAEngine implements AsymmetricBlockCipher { private RSAKeyParameters key; private boolean forEncryption; /** * initialise the RSA engine. * * @param forEncryption true if we are encrypting, false otherwise. * @param param the necessary RSA key parameters. */ public void init( boolean forEncryption, CipherParameters param) { this.key = (RSAKeyParameters)param; this.forEncryption = forEncryption; } /** * Return the maximum size for an input block to this engine. * For RSA this is always one byte less than the key size on * encryption, and the same length as the key size on decryption. * * @return maximum size for an input block. */ public int getInputBlockSize() { int bitSize = key.getModulus().bitLength(); if (forEncryption) { return (bitSize + 7) / 8 - 1; } else { return (bitSize + 7) / 8; } } /** * Return the maximum size for an output block to this engine. * For RSA this is always one byte less than the key size on * decryption, and the same length as the key size on encryption. * * @return maximum size for an output block. */ public int getOutputBlockSize() { int bitSize = key.getModulus().bitLength(); if (forEncryption) { return (bitSize + 7) / 8; } else { return (bitSize + 7) / 8 - 1; } } /** * Process a single block using the basic RSA algorithm. * * @param in the input array. * @param inOff the offset into the input buffer where the data starts. * @param inLen the length of the data to be processed. * @return the result of the RSA process. * @exception DataLengthException the input block is too large. */ public byte[] processBlock( byte[] in, int inOff, int inLen) { if (inLen > (getInputBlockSize() + 1)) { throw new DataLengthException("input too large for RSA cipher.\n"); } else if (inLen == (getInputBlockSize() + 1) && (in[inOff] & 0x80) != 0) { throw new DataLengthException("input too large for RSA cipher.\n"); } byte[] block; if (inOff != 0 || inLen != in.length) { block = new byte[inLen]; System.arraycopy(in, inOff, block, 0, inLen); } else { block = in; } BigInteger input = new BigInteger(1, block); byte[] output; if (key instanceof RSAPrivateCrtKeyParameters) { // // we have the extra factors, use the Chinese Remainder Theorem - the author // wishes to express his thanks to Dirk Bonekaemper at rtsffm.com for // advice regarding the expression of this. // RSAPrivateCrtKeyParameters crtKey = (RSAPrivateCrtKeyParameters)key; BigInteger p = crtKey.getP(); BigInteger q = crtKey.getQ(); BigInteger dP = crtKey.getDP(); BigInteger dQ = crtKey.getDQ(); BigInteger qInv = crtKey.getQInv(); BigInteger mP, mQ, h, m; // mP = ((input mod p) ^ dP)) mod p mP = (input.remainder(p)).modPow(dP, p); // mQ = ((input mod q) ^ dQ)) mod q mQ = (input.remainder(q)).modPow(dQ, q); // h = qInv * (mP - mQ) mod p h = mP.subtract(mQ); h = h.multiply(qInv); h = h.mod(p); // mod (in Java) returns the positive residual // m = h * q + mQ m = h.multiply(q); m = m.add(mQ); output = m.toByteArray(); } else { output = input.modPow( key.getExponent(), key.getModulus()).toByteArray(); } if (forEncryption) { if (output[0] == 0 && output.length > getOutputBlockSize()) // have ended up with an extra zero byte, copy down. { byte[] tmp = new byte[output.length - 1]; System.arraycopy(output, 1, tmp, 0, tmp.length); return tmp; } if (output.length < getOutputBlockSize()) // have ended up with less bytes than normal, lengthen { byte[] tmp = new byte[getOutputBlockSize()]; System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length); return tmp; } } else { if (output[0] == 0) // have ended up with an extra zero byte, copy down. { byte[] tmp = new byte[output.length - 1]; System.arraycopy(output, 1, tmp, 0, tmp.length); return tmp; } } return output; } } azureus-4.3.0.6/org/bouncycastle/crypto/AsymmetricCipherKeyPairGenerator.java0000644000175000017500000000110310061400652026674 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * interface that a public/private key pair generator should conform to. */ public interface AsymmetricCipherKeyPairGenerator { /** * intialise the key pair generator. * * @param the parameters the key pair is to be initialised with. */ public void init(KeyGenerationParameters param); /** * return an AsymmetricCipherKeyPair containing the generated keys. * * @return an AsymmetricCipherKeyPair containing the generated keys. */ public AsymmetricCipherKeyPair generateKeyPair(); } azureus-4.3.0.6/org/bouncycastle/crypto/params/0000755000175000017500000000000011310377634020730 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/crypto/params/ECKeyParameters.java0000644000175000017500000000055510061400654024553 0ustar adrianadrianpackage org.bouncycastle.crypto.params; public class ECKeyParameters extends AsymmetricKeyParameter { ECDomainParameters params; protected ECKeyParameters( boolean isPrivate, ECDomainParameters params) { super(isPrivate); this.params = params; } public ECDomainParameters getParameters() { return params; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/KDFParameters.java0000644000175000017500000000100310061400654024204 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import org.bouncycastle.crypto.DerivationParameters; /** * parameters for Key derivation functions. */ public class KDFParameters implements DerivationParameters { byte[] iv; byte[] shared; public KDFParameters( byte[] shared, byte[] iv) { this.shared = shared; this.iv = iv; } public byte[] getSharedSecret() { return shared; } public byte[] getIV() { return iv; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DHKeyGenerationParameters.java0000644000175000017500000000101510061400654026563 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.security.SecureRandom; import org.bouncycastle.crypto.KeyGenerationParameters; public class DHKeyGenerationParameters extends KeyGenerationParameters { private DHParameters params; public DHKeyGenerationParameters( SecureRandom random, DHParameters params) { super(random, params.getP().bitLength() - 1); this.params = params; } public DHParameters getParameters() { return params; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DHValidationParameters.java0000644000175000017500000000162310061400654026116 0ustar adrianadrianpackage org.bouncycastle.crypto.params; public class DHValidationParameters { private byte[] seed; private int counter; public DHValidationParameters( byte[] seed, int counter) { this.seed = seed; this.counter = counter; } public boolean equals( Object o) { if (o == null || !(o instanceof DHValidationParameters)) { return false; } DHValidationParameters other = (DHValidationParameters)o; if (other.counter != this.counter) { return false; } if (other.seed.length != this.seed.length) { return false; } for (int i = 0; i != other.seed.length; i++) { if (other.seed[i] != this.seed[i]) { return false; } } return true; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DSAKeyParameters.java0000644000175000017500000000061110061400654024664 0ustar adrianadrianpackage org.bouncycastle.crypto.params; public class DSAKeyParameters extends AsymmetricKeyParameter { private DSAParameters params; public DSAKeyParameters( boolean isPrivate, DSAParameters params) { super(isPrivate); this.params = params; } public DSAParameters getParameters() { return params; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/ElGamalKeyParameters.java0000644000175000017500000000132010061400654025555 0ustar adrianadrianpackage org.bouncycastle.crypto.params; public class ElGamalKeyParameters extends AsymmetricKeyParameter { private ElGamalParameters params; protected ElGamalKeyParameters( boolean isPrivate, ElGamalParameters params) { super(isPrivate); this.params = params; } public ElGamalParameters getParameters() { return params; } public boolean equals( Object obj) { if (!(obj instanceof ElGamalKeyParameters)) { return false; } ElGamalKeyParameters dhKey = (ElGamalKeyParameters)obj; return (params != null && !params.equals(dhKey.getParameters())); } } azureus-4.3.0.6/org/bouncycastle/crypto/params/ElGamalPublicKeyParameters.java0000644000175000017500000000140210061400654026715 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; public class ElGamalPublicKeyParameters extends ElGamalKeyParameters { private BigInteger y; public ElGamalPublicKeyParameters( BigInteger y, ElGamalParameters params) { super(false, params); this.y = y; } public BigInteger getY() { return y; } public boolean equals( Object obj) { if (!(obj instanceof ElGamalPublicKeyParameters)) { return false; } ElGamalPublicKeyParameters pKey = (ElGamalPublicKeyParameters)obj; if (!pKey.getY().equals(y)) { return false; } return super.equals(obj); } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DHParameters.java0000644000175000017500000000437210061400654024107 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; import org.bouncycastle.crypto.CipherParameters; public class DHParameters implements CipherParameters { private BigInteger g; private BigInteger p; private BigInteger q; private int j; private DHValidationParameters validation; public DHParameters( BigInteger p, BigInteger g) { this.g = g; this.p = p; } public DHParameters( BigInteger p, BigInteger g, BigInteger q, int j) { this.g = g; this.p = p; this.q = q; this.j = j; } public DHParameters( BigInteger p, BigInteger g, BigInteger q, int j, DHValidationParameters validation) { this.g = g; this.p = p; this.q = q; this.j = j; } public BigInteger getP() { return p; } public BigInteger getG() { return g; } public BigInteger getQ() { return q; } public int getJ() { return j; } public DHValidationParameters getValidationParameters() { return validation; } public boolean equals( Object obj) { if (!(obj instanceof DHParameters)) { return false; } DHParameters pm = (DHParameters)obj; if (this.getValidationParameters() != null) { if (!this.getValidationParameters().equals(pm.getValidationParameters())) { return false; } } else { if (pm.getValidationParameters() != null) { return false; } } if (this.getQ() != null) { if (!this.getQ().equals(pm.getQ())) { return false; } } else { if (pm.getQ() != null) { return false; } } return (j == pm.getJ()) && pm.getP().equals(p) && pm.getG().equals(g); } } azureus-4.3.0.6/org/bouncycastle/crypto/params/KeyParameter.java0000644000175000017500000000102510061400654024151 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import org.bouncycastle.crypto.CipherParameters; public class KeyParameter implements CipherParameters { private byte[] key; public KeyParameter( byte[] key) { this(key, 0, key.length); } public KeyParameter( byte[] key, int keyOff, int keyLen) { this.key = new byte[keyLen]; System.arraycopy(key, keyOff, this.key, 0, keyLen); } public byte[] getKey() { return key; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/ISO18033KDFParameters.java0000644000175000017500000000063210777355064025207 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import org.bouncycastle.crypto.DerivationParameters; /** * parameters for Key derivation functions for ISO-18033 */ public class ISO18033KDFParameters implements DerivationParameters { byte[] seed; public ISO18033KDFParameters( byte[] seed) { this.seed = seed; } public byte[] getSeed() { return seed; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DESedeParameters.java0000644000175000017500000000251410061400654024701 0ustar adrianadrianpackage org.bouncycastle.crypto.params; public class DESedeParameters extends DESParameters { /* * DES-EDE Key length in bytes. */ static public final int DES_EDE_KEY_LENGTH = 24; public DESedeParameters( byte[] key) { super(key); if (isWeakKey(key, 0, 0)) { throw new IllegalArgumentException("attempt to create weak DESede key"); } } /** * return true if the passed in key is a DES-EDE weak key. * * @param key bytes making up the key * @param offset offset into the byte array the key starts at * @param length number of bytes making up the key */ public static boolean isWeakKey( byte[] key, int offset, int length) { for (int i = offset; i < length; i += DES_KEY_LENGTH) { if (DESParameters.isWeakKey(key, i)) { return true; } } return false; } /** * return true if the passed in key is a DES-EDE weak key. * * @param key bytes making up the key * @param offset offset into the byte array the key starts at */ public static boolean isWeakKey( byte[] key, int offset) { return isWeakKey(key, offset, key.length - offset); } } azureus-4.3.0.6/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java0000644000175000017500000000105310061400654026561 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.security.SecureRandom; import org.bouncycastle.crypto.KeyGenerationParameters; public class ECKeyGenerationParameters extends KeyGenerationParameters { private ECDomainParameters domainParams; public ECKeyGenerationParameters( ECDomainParameters domainParams, SecureRandom random) { super(random, domainParams.getN().bitLength()); this.domainParams = domainParams; } public ECDomainParameters getDomainParameters() { return domainParams; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/package.html0000644000175000017500000000015210061400654023176 0ustar adrianadrian Classes for parameter objects for ciphers and generators. azureus-4.3.0.6/org/bouncycastle/crypto/params/DSAKeyGenerationParameters.java0000644000175000017500000000102110061400654026674 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.security.SecureRandom; import org.bouncycastle.crypto.KeyGenerationParameters; public class DSAKeyGenerationParameters extends KeyGenerationParameters { private DSAParameters params; public DSAKeyGenerationParameters( SecureRandom random, DSAParameters params) { super(random, params.getP().bitLength() - 1); this.params = params; } public DSAParameters getParameters() { return params; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/RSAKeyGenerationParameters.java0000644000175000017500000000134310061400654026721 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; import java.security.SecureRandom; import org.bouncycastle.crypto.KeyGenerationParameters; public class RSAKeyGenerationParameters extends KeyGenerationParameters { private BigInteger publicExponent; private int certainty; public RSAKeyGenerationParameters( BigInteger publicExponent, SecureRandom random, int strength, int certainty) { super(random, strength); this.publicExponent = publicExponent; this.certainty = certainty; } public BigInteger getPublicExponent() { return publicExponent; } public int getCertainty() { return certainty; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/ParametersWithRandom.java0000644000175000017500000000154410061400654025666 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.security.SecureRandom; import org.bouncycastle.crypto.CipherParameters; public class ParametersWithRandom implements CipherParameters { private SecureRandom random; private CipherParameters parameters; public ParametersWithRandom( CipherParameters parameters, SecureRandom random) { this.random = random; this.parameters = parameters; } public ParametersWithRandom( CipherParameters parameters) { this.random = null; this.parameters = parameters; } public SecureRandom getRandom() { if (random == null) { random = new SecureRandom(); } return random; } public CipherParameters getParameters() { return parameters; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java0000644000175000017500000000134210061400654026105 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; public class DHPrivateKeyParameters extends DHKeyParameters { private BigInteger x; public DHPrivateKeyParameters( BigInteger x, DHParameters params) { super(true, params); this.x = x; } public BigInteger getX() { return x; } public boolean equals( Object obj) { if (!(obj instanceof DHPrivateKeyParameters)) { return false; } DHPrivateKeyParameters pKey = (DHPrivateKeyParameters)obj; if (!pKey.getX().equals(x)) { return false; } return super.equals(obj); } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java0000644000175000017500000000061110061400654026217 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; public class DSAPrivateKeyParameters extends DSAKeyParameters { private BigInteger x; public DSAPrivateKeyParameters( BigInteger x, DSAParameters params) { super(true, params); this.x = x; } public BigInteger getX() { return x; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/ECPublicKeyParameters.java0000644000175000017500000000060210061400654025703 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import org.bouncycastle.math.ec.ECPoint; public class ECPublicKeyParameters extends ECKeyParameters { ECPoint Q; public ECPublicKeyParameters( ECPoint Q, ECDomainParameters params) { super(false, params); this.Q = Q; } public ECPoint getQ() { return Q; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java0000644000175000017500000000105110061400654027572 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.security.SecureRandom; import org.bouncycastle.crypto.KeyGenerationParameters; public class ElGamalKeyGenerationParameters extends KeyGenerationParameters { private ElGamalParameters params; public ElGamalKeyGenerationParameters( SecureRandom random, ElGamalParameters params) { super(random, params.getP().bitLength() - 1); this.params = params; } public ElGamalParameters getParameters() { return params; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java0000644000175000017500000000057510061400654026110 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; public class ECPrivateKeyParameters extends ECKeyParameters { BigInteger d; public ECPrivateKeyParameters( BigInteger d, ECDomainParameters params) { super(true, params); this.d = d; } public BigInteger getD() { return d; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DHPublicKeyParameters.java0000644000175000017500000000133710061400654025715 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; public class DHPublicKeyParameters extends DHKeyParameters { private BigInteger y; public DHPublicKeyParameters( BigInteger y, DHParameters params) { super(false, params); this.y = y; } public BigInteger getY() { return y; } public boolean equals( Object obj) { if (!(obj instanceof DHPublicKeyParameters)) { return false; } DHPublicKeyParameters pKey = (DHPublicKeyParameters)obj; if (!pKey.getY().equals(y)) { return false; } return super.equals(obj); } } azureus-4.3.0.6/org/bouncycastle/crypto/params/MGFParameters.java0000644000175000017500000000110010061400654024207 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import org.bouncycastle.crypto.DerivationParameters; /** * parameters for mask derivation functions. */ public class MGFParameters implements DerivationParameters { byte[] seed; public MGFParameters( byte[] seed) { this.seed = seed; } public MGFParameters( byte[] seed, int off, int len) { this.seed = new byte[len]; System.arraycopy(seed, off, this.seed, 0, len); } public byte[] getSeed() { return seed; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/RC5Parameters.java0000644000175000017500000000125610061400654024203 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import org.bouncycastle.crypto.CipherParameters; public class RC5Parameters implements CipherParameters { private byte[] key; private int rounds; public RC5Parameters( byte[] key, int rounds) { if (key.length > 255) { throw new IllegalArgumentException("RC5 key length can be no greater than 255"); } this.key = new byte[key.length]; this.rounds = rounds; System.arraycopy(key, 0, this.key, 0, key.length); } public byte[] getKey() { return key; } public int getRounds() { return rounds; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java0000644000175000017500000000061010061400654026022 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; public class DSAPublicKeyParameters extends DSAKeyParameters { private BigInteger y; public DSAPublicKeyParameters( BigInteger y, DSAParameters params) { super(false, params); this.y = y; } public BigInteger getY() { return y; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/ElGamalPrivateKeyParameters.java0000644000175000017500000000140510061400654027114 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; public class ElGamalPrivateKeyParameters extends ElGamalKeyParameters { private BigInteger x; public ElGamalPrivateKeyParameters( BigInteger x, ElGamalParameters params) { super(true, params); this.x = x; } public BigInteger getX() { return x; } public boolean equals( Object obj) { if (!(obj instanceof ElGamalPrivateKeyParameters)) { return false; } ElGamalPrivateKeyParameters pKey = (ElGamalPrivateKeyParameters)obj; if (!pKey.getX().equals(x)) { return false; } return super.equals(obj); } } azureus-4.3.0.6/org/bouncycastle/crypto/params/RSAKeyParameters.java0000644000175000017500000000111510061400654024702 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; public class RSAKeyParameters extends AsymmetricKeyParameter { private BigInteger modulus; private BigInteger exponent; public RSAKeyParameters( boolean isPrivate, BigInteger modulus, BigInteger exponent) { super(isPrivate); this.modulus = modulus; this.exponent = exponent; } public BigInteger getModulus() { return modulus; } public BigInteger getExponent() { return exponent; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DSAValidationParameters.java0000644000175000017500000000202710061400654026231 0ustar adrianadrianpackage org.bouncycastle.crypto.params; public class DSAValidationParameters { private byte[] seed; private int counter; public DSAValidationParameters( byte[] seed, int counter) { this.seed = seed; this.counter = counter; } public int getCounter() { return counter; } public byte[] getSeed() { return seed; } public boolean equals( Object o) { if (o == null || !(o instanceof DSAValidationParameters)) { return false; } DSAValidationParameters other = (DSAValidationParameters)o; if (other.counter != this.counter) { return false; } if (other.seed.length != this.seed.length) { return false; } for (int i = 0; i != other.seed.length; i++) { if (other.seed[i] != this.seed[i]) { return false; } } return true; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DHKeyParameters.java0000644000175000017500000000125010061400654024550 0ustar adrianadrianpackage org.bouncycastle.crypto.params; public class DHKeyParameters extends AsymmetricKeyParameter { private DHParameters params; protected DHKeyParameters( boolean isPrivate, DHParameters params) { super(isPrivate); this.params = params; } public DHParameters getParameters() { return params; } public boolean equals( Object obj) { if (!(obj instanceof DHKeyParameters)) { return false; } DHKeyParameters dhKey = (DHKeyParameters)obj; return (params != null && !params.equals(dhKey.getParameters())); } } azureus-4.3.0.6/org/bouncycastle/crypto/params/RC2Parameters.java0000644000175000017500000000123310061400654024173 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import org.bouncycastle.crypto.CipherParameters; public class RC2Parameters implements CipherParameters { private byte[] key; private int bits; public RC2Parameters( byte[] key) { this(key, (key.length > 128) ? 1024 : (key.length * 8)); } public RC2Parameters( byte[] key, int bits) { this.key = new byte[key.length]; this.bits = bits; System.arraycopy(key, 0, this.key, 0, key.length); } public byte[] getKey() { return key; } public int getEffectiveKeyBits() { return bits; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/AsymmetricKeyParameter.java0000644000175000017500000000056110061400654026213 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import org.bouncycastle.crypto.CipherParameters; public class AsymmetricKeyParameter implements CipherParameters { boolean privateKey; public AsymmetricKeyParameter( boolean privateKey) { this.privateKey = privateKey; } public boolean isPrivate() { return privateKey; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DSAParameters.java0000644000175000017500000000253210061400654024217 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; import org.bouncycastle.crypto.CipherParameters; public class DSAParameters implements CipherParameters { private BigInteger g; private BigInteger q; private BigInteger p; private DSAValidationParameters validation; public DSAParameters( BigInteger p, BigInteger q, BigInteger g) { this.g = g; this.p = p; this.q = q; } public DSAParameters( BigInteger p, BigInteger q, BigInteger g, DSAValidationParameters params) { this.g = g; this.p = p; this.q = q; this.validation = params; } public BigInteger getP() { return p; } public BigInteger getQ() { return q; } public BigInteger getG() { return g; } public DSAValidationParameters getValidationParameters() { return validation; } public boolean equals( Object obj) { if (!(obj instanceof DSAParameters)) { return false; } DSAParameters pm = (DSAParameters)obj; return (pm.getP().equals(p) && pm.getQ().equals(q) && pm.getG().equals(g)); } } azureus-4.3.0.6/org/bouncycastle/crypto/params/ECDomainParameters.java0000644000175000017500000000225610061400654025232 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; import org.bouncycastle.math.ec.ECConstants; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; public class ECDomainParameters implements ECConstants { ECCurve curve; byte[] seed; ECPoint G; BigInteger n; BigInteger h; public ECDomainParameters( ECCurve curve, ECPoint G, BigInteger n) { this.curve = curve; this.G = G; this.n = n; this.h = ONE; this.seed = null; } public ECDomainParameters( ECCurve curve, ECPoint G, BigInteger n, BigInteger h) { this.curve = curve; this.G = G; this.n = n; this.h = h; this.seed = null; } public ECDomainParameters( ECCurve curve, ECPoint G, BigInteger n, BigInteger h, byte[] seed) { this.curve = curve; this.G = G; this.n = n; this.h = h; this.seed = seed; } public ECCurve getCurve() { return curve; } public ECPoint getG() { return G; } public BigInteger getN() { return n; } public BigInteger getH() { return h; } public byte[] getSeed() { return seed; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java0000644000175000017500000000223710061400654026714 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; public class RSAPrivateCrtKeyParameters extends RSAKeyParameters { private BigInteger e; private BigInteger p; private BigInteger q; private BigInteger dP; private BigInteger dQ; private BigInteger qInv; /** * */ public RSAPrivateCrtKeyParameters( BigInteger modulus, BigInteger publicExponent, BigInteger privateExponent, BigInteger p, BigInteger q, BigInteger dP, BigInteger dQ, BigInteger qInv) { super(true, modulus, privateExponent); this.e = publicExponent; this.p = p; this.q = q; this.dP = dP; this.dQ = dQ; this.qInv = qInv; } public BigInteger getPublicExponent() { return e; } public BigInteger getP() { return p; } public BigInteger getQ() { return q; } public BigInteger getDP() { return dP; } public BigInteger getDQ() { return dQ; } public BigInteger getQInv() { return qInv; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/ParametersWithIV.java0000644000175000017500000000152310061400654024761 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import org.bouncycastle.crypto.CipherParameters; public class ParametersWithIV implements CipherParameters { private byte[] iv; private CipherParameters parameters; public ParametersWithIV( CipherParameters parameters, byte[] iv) { this(parameters, iv, 0, iv.length); } public ParametersWithIV( CipherParameters parameters, byte[] iv, int ivOff, int ivLen) { this.iv = new byte[ivLen]; this.parameters = parameters; System.arraycopy(iv, ivOff, this.iv, 0, ivLen); } public byte[] getIV() { return iv; } public CipherParameters getParameters() { return parameters; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/DESParameters.java0000644000175000017500000000754410061400654024233 0ustar adrianadrianpackage org.bouncycastle.crypto.params; public class DESParameters extends KeyParameter { public DESParameters( byte[] key) { super(key); if (isWeakKey(key, 0)) { throw new IllegalArgumentException("attempt to create weak DES key"); } } /* * DES Key length in bytes. */ static public final int DES_KEY_LENGTH = 8; /* * Table of weak and semi-weak keys taken from Schneier pp281 */ static private final int N_DES_WEAK_KEYS = 16; static private byte[] DES_weak_keys = { /* weak keys */ (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e, (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, /* semi-weak keys */ (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1, (byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1, (byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe, (byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e, (byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e, (byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01, (byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e, (byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01, (byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1 }; /** * DES has 16 weak keys. This method will check * if the given DES key material is weak or semi-weak. * Key material that is too short is regarded as weak. *

      * See "Applied * Cryptography" by Bruce Schneier for more information. * * @return true if the given DES key material is weak or semi-weak, * false otherwise. */ public static boolean isWeakKey( byte[] key, int offset) { if (key.length - offset < DES_KEY_LENGTH) { throw new IllegalArgumentException("key material too short."); } nextkey: for (int i = 0; i < N_DES_WEAK_KEYS; i++) { for (int j = 0; j < DES_KEY_LENGTH; j++) { if (key[j + offset] != DES_weak_keys[i * DES_KEY_LENGTH + j]) { continue nextkey; } } return true; } return false; } /** * DES Keys use the LSB as the odd parity bit. This can * be used to check for corrupt keys. * * @param bytes the byte array to set the parity on. */ public static void setOddParity( byte[] bytes) { for (int i = 0; i < bytes.length; i++) { int b = bytes[i]; bytes[i] = (byte)((b & 0xfe) | ((((b >> 1) ^ (b >> 2) ^ (b >> 3) ^ (b >> 4) ^ (b >> 5) ^ (b >> 6) ^ (b >> 7)) ^ 0x01) & 0x01)); } } } azureus-4.3.0.6/org/bouncycastle/crypto/params/ElGamalParameters.java0000644000175000017500000000150610061400654025112 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import java.math.BigInteger; import org.bouncycastle.crypto.CipherParameters; public class ElGamalParameters implements CipherParameters { private BigInteger g; private BigInteger p; public ElGamalParameters( BigInteger p, BigInteger g) { this.g = g; this.p = p; } public BigInteger getP() { return p; } /** * return the generator - g */ public BigInteger getG() { return g; } public boolean equals( Object obj) { if (!(obj instanceof ElGamalParameters)) { return false; } ElGamalParameters pm = (ElGamalParameters)obj; return pm.getP().equals(p) && pm.getG().equals(g); } } azureus-4.3.0.6/org/bouncycastle/crypto/params/IESWithCipherParameters.java0000644000175000017500000000137610061400654026224 0ustar adrianadrianpackage org.bouncycastle.crypto.params; public class IESWithCipherParameters extends IESParameters { private int cipherKeySize; /** * @param derivation the derivation parameter for the KDF function. * @param encoding the encoding parameter for the KDF function. * @param macKeySize the size of the MAC key (in bits). * @param cipherKeySize the size of the associated Cipher key (in bits). */ public IESWithCipherParameters( byte[] derivation, byte[] encoding, int macKeySize, int cipherKeySize) { super(derivation, encoding, macKeySize); this.cipherKeySize = cipherKeySize; } public int getCipherKeySize() { return cipherKeySize; } } azureus-4.3.0.6/org/bouncycastle/crypto/params/IESParameters.java0000644000175000017500000000172510061400654024233 0ustar adrianadrianpackage org.bouncycastle.crypto.params; import org.bouncycastle.crypto.CipherParameters; /** * parameters for using an integrated cipher in stream mode. */ public class IESParameters implements CipherParameters { private byte[] derivation; private byte[] encoding; private int macKeySize; /** * @param derivation the derivation parameter for the KDF function. * @param encoding the encoding parameter for the KDF function. * @param macKeySize the size of the MAC key (in bits). */ public IESParameters( byte[] derivation, byte[] encoding, int macKeySize) { this.derivation = derivation; this.encoding = encoding; this.macKeySize = macKeySize; } public byte[] getDerivationV() { return derivation; } public byte[] getEncodingV() { return encoding; } public int getMacKeySize() { return macKeySize; } } azureus-4.3.0.6/org/bouncycastle/crypto/DerivationFunction.java0000644000175000017500000000066610061400652024117 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * base interface for general purpose byte derivation functions. */ public interface DerivationFunction { public void init(DerivationParameters param); /** * return the message digest used as the basis for the function */ public Digest getDigest(); public int generateBytes(byte[] out, int outOff, int len) throws DataLengthException, IllegalArgumentException; } azureus-4.3.0.6/org/bouncycastle/crypto/Mac.java0000644000175000017500000000431710061400652021002 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * The base interface for implementations of message authentication codes (MACs). */ public interface Mac { /** * Initialise the MAC. * * @param param the key and other data required by the MAC. * @exception IllegalArgumentException if the params argument is * inappropriate. */ public void init(CipherParameters params) throws IllegalArgumentException; /** * Return the name of the algorithm the MAC implements. * * @return the name of the algorithm the MAC implements. */ public String getAlgorithmName(); /** * Return the block size for this cipher (in bytes). * * @return the block size for this cipher in bytes. */ public int getMacSize(); /** * add a single byte to the mac for processing. * * @param in the byte to be processed. * @exception IllegalStateException if the MAC is not initialised. */ public void update(byte in) throws IllegalStateException; /** * @param in the array containing the input. * @param inOff the index in the array the data begins at. * @param len the length of the input starting at inOff. * @exception IllegalStateException if the MAC is not initialised. * @exception DataLengthException if there isn't enough data in in. */ public void update(byte[] in, int inOff, int len) throws DataLengthException, IllegalStateException; /** * Compute the final statge of the MAC writing the output to the out * parameter. *

      * doFinal leaves the MAC in the same state it was after the last init. * * @param out the array the MAC is to be output to. * @param outOff the offset into the out buffer the output is to start at. * @exception DataLengthException if there isn't enough space in out. * @exception IllegalStateException if the MAC is not initialised. */ public int doFinal(byte[] out, int outOff) throws DataLengthException, IllegalStateException; /** * Reset the MAC. At the end of resetting the MAC should be in the * in the same state it was after the last init (if there was one). */ public void reset(); } azureus-4.3.0.6/org/bouncycastle/crypto/RuntimeCryptoException.java0000644000175000017500000000101711012742206025000 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * the foundation class for the exceptions thrown by the crypto packages. */ public class RuntimeCryptoException extends RuntimeException { /** * base constructor. */ public RuntimeCryptoException() { } /** * create a RuntimeCryptoException with the given message. * * @param message the message to be carried with the exception. */ public RuntimeCryptoException( String message) { super(message); } } azureus-4.3.0.6/org/bouncycastle/crypto/BufferedBlockCipher.java0000644000175000017500000002107210061400652024127 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * A wrapper class that allows block ciphers to be used to process data in * a piecemeal fashion. The BufferedBlockCipher outputs a block only when the * buffer is full and more data is being added, or on a doFinal. *

      * Note: in the case where the underlying cipher is either a CFB cipher or an * OFB one the last block may not be a multiple of the block size. */ public class BufferedBlockCipher { protected byte[] buf; protected int bufOff; protected boolean forEncryption; protected BlockCipher cipher; protected boolean partialBlockOkay; protected boolean pgpCFB; /** * constructor for subclasses */ protected BufferedBlockCipher() { } /** * Create a buffered block cipher without padding. * * @param cipher the underlying block cipher this buffering object wraps. * @param padded true if the buffer should add, or remove, pad bytes, * false otherwise. */ public BufferedBlockCipher( BlockCipher cipher) { this.cipher = cipher; buf = new byte[cipher.getBlockSize()]; bufOff = 0; // // check if we can handle partial blocks on doFinal. // String name = cipher.getAlgorithmName(); int idx = name.indexOf('/') + 1; pgpCFB = (idx > 0 && name.startsWith("PGP", idx)); if (pgpCFB) { partialBlockOkay = true; } else { partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx))); } } /** * return the cipher this object wraps. * * @return the cipher this object wraps. */ public BlockCipher getUnderlyingCipher() { return cipher; } /** * initialise the cipher. * * @param forEncryption if true the cipher is initialised for * encryption, if false for decryption. * @param param the key and other data required by the cipher. * @exception IllegalArgumentException if the params argument is * inappropriate. */ public void init( boolean forEncryption, CipherParameters params) throws IllegalArgumentException { this.forEncryption = forEncryption; reset(); cipher.init(forEncryption, params); } /** * return the blocksize for the underlying cipher. * * @return the blocksize for the underlying cipher. */ public int getBlockSize() { return cipher.getBlockSize(); } /** * return the size of the output buffer required for an update * an input of len bytes. * * @param len the length of the input. * @return the space required to accommodate a call to update * with len bytes of input. */ public int getUpdateOutputSize( int len) { int total = len + bufOff; int leftOver; if (pgpCFB) { leftOver = total % buf.length - (cipher.getBlockSize() + 2); } else { leftOver = total % buf.length; } return total - leftOver; } /** * return the size of the output buffer required for an update plus a * doFinal with an input of len bytes. * * @param len the length of the input. * @return the space required to accommodate a call to update and doFinal * with len bytes of input. */ public int getOutputSize( int len) { int total = len + bufOff; int leftOver; if (pgpCFB) { leftOver = total % buf.length - (cipher.getBlockSize() + 2); } else { leftOver = total % buf.length; if (leftOver == 0) { return total; } } return total - leftOver + buf.length; } /** * process a single byte, producing an output block if neccessary. * * @param in the input byte. * @param out the space for any output that might be produced. * @param outOff the offset from which the output will be copied. * @return the number of output bytes copied to out. * @exception DataLengthException if there isn't enough space in out. * @exception IllegalStateException if the cipher isn't initialised. */ public int processByte( byte in, byte[] out, int outOff) throws DataLengthException, IllegalStateException { int resultLen = 0; buf[bufOff++] = in; if (bufOff == buf.length) { resultLen = cipher.processBlock(buf, 0, out, outOff); bufOff = 0; } return resultLen; } /** * process an array of bytes, producing output if necessary. * * @param in the input byte array. * @param inOff the offset at which the input data starts. * @param len the number of bytes to be copied out of the input array. * @param out the space for any output that might be produced. * @param outOff the offset from which the output will be copied. * @return the number of output bytes copied to out. * @exception DataLengthException if there isn't enough space in out. * @exception IllegalStateException if the cipher isn't initialised. */ public int processBytes( byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if (len < 0) { throw new IllegalArgumentException("Can't have a negative input length!"); } int blockSize = getBlockSize(); int length = getUpdateOutputSize(len); if (length > 0) { if ((outOff + length) > out.length) { throw new DataLengthException("output buffer too short"); } } int resultLen = 0; int gapLen = buf.length - bufOff; if (len > gapLen) { System.arraycopy(in, inOff, buf, bufOff, gapLen); resultLen += cipher.processBlock(buf, 0, out, outOff); bufOff = 0; len -= gapLen; inOff += gapLen; while (len > buf.length) { resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen); len -= blockSize; inOff += blockSize; } } System.arraycopy(in, inOff, buf, bufOff, len); bufOff += len; if (bufOff == buf.length) { resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen); bufOff = 0; } return resultLen; } /** * Process the last block in the buffer. * * @param out the array the block currently being held is copied into. * @param outOff the offset at which the copying starts. * @return the number of output bytes copied to out. * @exception DataLengthException if there is insufficient space in out for * the output, or the input is not block size aligned and should be. * @exception IllegalStateException if the underlying cipher is not * initialised. * @exception InvalidCipherTextException if padding is expected and not found. * @exception DataLengthException if the input is not block size * aligned. */ public int doFinal( byte[] out, int outOff) throws DataLengthException, IllegalStateException, InvalidCipherTextException { int resultLen = 0; if (outOff + bufOff > out.length) { throw new DataLengthException("output buffer too short for doFinal()"); } if (bufOff != 0 && partialBlockOkay) { cipher.processBlock(buf, 0, buf, 0); resultLen = bufOff; bufOff = 0; System.arraycopy(buf, 0, out, outOff, resultLen); } else if (bufOff != 0) { throw new DataLengthException("data not block size aligned"); } reset(); return resultLen; } /** * Reset the buffer and cipher. After resetting the object is in the same * state as it was after the last init (if there was one). */ public void reset() { // // clean the buffer. // for (int i = 0; i < buf.length; i++) { buf[i] = 0; } bufOff = 0; // // reset the underlying cipher. // cipher.reset(); } } azureus-4.3.0.6/org/bouncycastle/crypto/signers/0000755000175000017500000000000011310377634021117 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/crypto/signers/ECDSASigner.java0000644000175000017500000000661210407566336023763 0ustar adrianadrianpackage org.bouncycastle.crypto.signers; import java.math.BigInteger; import java.security.SecureRandom; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DSA; import org.bouncycastle.crypto.params.ECKeyParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.math.ec.ECConstants; import org.bouncycastle.math.ec.ECPoint; /** * EC-DSA as described in X9.62 */ public class ECDSASigner implements ECConstants, DSA { ECKeyParameters key; SecureRandom random; public void init( boolean forSigning, CipherParameters param) { if (forSigning) { if (param instanceof ParametersWithRandom) { ParametersWithRandom rParam = (ParametersWithRandom)param; this.random = rParam.getRandom(); this.key = (ECPrivateKeyParameters)rParam.getParameters(); } else { this.random = new SecureRandom(); this.key = (ECPrivateKeyParameters)param; } } else { this.key = (ECPublicKeyParameters)param; } } // 5.3 pg 28 /** * generate a signature for the given message using the key we were * initialised with. For conventional DSA the message should be a SHA-1 * hash of the message of interest. * * @param message the message that will be verified later. */ public BigInteger[] generateSignature( byte[] message) { BigInteger e = new BigInteger(1, message); BigInteger n = key.getParameters().getN(); BigInteger r = null; BigInteger s = null; // 5.3.2 do // generate s { BigInteger k = null; int nBitLength = n.bitLength(); do // generate r { do { k = new BigInteger(nBitLength, random); } while (k.equals(ZERO)); ECPoint p = key.getParameters().getG().multiply(k); // 5.3.3 BigInteger x = p.getX().toBigInteger(); r = x.mod(n); } while ( r.equals(ZERO) ); BigInteger d = ((ECPrivateKeyParameters)key).getD(); s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n); } while ( s.equals(ZERO) ); BigInteger[] res = new BigInteger[2]; res[0] = r; res[1] = s; return res; } // 5.4 pg 29 /** * return true if the value r and s represent a DSA signature for * the passed in message (for standard DSA the message should be * a SHA-1 hash of the real message to be verified). */ public boolean verifySignature( byte[] message, BigInteger r, BigInteger s) { BigInteger e = new BigInteger(1, message); BigInteger n = key.getParameters().getN(); // r in the range [1,n-1] if ( r.compareTo(ONE) < 0 || r.compareTo(n) >= 0 ) { return false; } // s in the range [1,n-1] if ( s.compareTo(ONE) < 0 || s.compareTo(n) >= 0 ) { return false; } BigInteger c = s.modInverse(n); BigInteger u1 = e.multiply(c).mod(n); BigInteger u2 = r.multiply(c).mod(n); ECPoint G = key.getParameters().getG(); ECPoint Q = ((ECPublicKeyParameters)key).getQ(); ECPoint point = G.multiply(u1).add(Q.multiply(u2)); BigInteger v = point.getX().toBigInteger().mod(n); return v.equals(r); } } azureus-4.3.0.6/org/bouncycastle/crypto/CryptoException.java0000644000175000017500000000076211012742206023442 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * the foundation class for the hard exceptions thrown by the crypto packages. */ public class CryptoException extends Exception { /** * base constructor. */ public CryptoException() { } /** * create a CryptoException with the given message. * * @param message the message to be carried with the exception. */ public CryptoException( String message) { super(message); } } azureus-4.3.0.6/org/bouncycastle/crypto/AsymmetricBlockCipher.java0000644000175000017500000000261610061400652024525 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * base interface that a public/private key block cipher needs * to conform to. */ public interface AsymmetricBlockCipher { /** * initialise the cipher. * * @param forEncryption if true the cipher is initialised for * encryption, if false for decryption. * @param param the key and other data required by the cipher. */ public void init(boolean forEncryption, CipherParameters param); /** * returns the largest size an input block can be. * * @return maximum size for an input block. */ public int getInputBlockSize(); /** * returns the maximum size of the block produced by this cipher. * * @return maximum size of the output block produced by the cipher. */ public int getOutputBlockSize(); /** * process the block of len bytes stored in in from offset inOff. * * @param in the input data * @param inOff offset into the in array where the data starts * @param len the length of the block to be processed. * @return the resulting byte array of the encryption/decryption process. * @exception InvalidCipherTextException data decrypts improperly. * @exception DataLengthException the input data is too large for the cipher. */ public byte[] processBlock(byte[] in, int inOff, int len) throws InvalidCipherTextException; } azureus-4.3.0.6/org/bouncycastle/crypto/digests/0000755000175000017500000000000011310377632021105 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/crypto/digests/SHA512Digest.java0000644000175000017500000000337510061400652023752 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; /** * Draft FIPS 180-2 implementation of SHA-512. Note: As this is * based on a draft this implementation is subject to change. * *

       *         block  word  digest
       * SHA-1   512    32    160
       * SHA-256 512    32    256
       * SHA-384 1024   64    384
       * SHA-512 1024   64    512
       * 
      */ public class SHA512Digest extends LongDigest { private static final int DIGEST_LENGTH = 64; /** * Standard constructor */ public SHA512Digest() { } /** * Copy constructor. This will copy the state of the provided * message digest. */ public SHA512Digest(SHA512Digest t) { super(t); } public String getAlgorithmName() { return "SHA-512"; } public int getDigestSize() { return DIGEST_LENGTH; } public int doFinal( byte[] out, int outOff) { finish(); unpackWord(H1, out, outOff); unpackWord(H2, out, outOff + 8); unpackWord(H3, out, outOff + 16); unpackWord(H4, out, outOff + 24); unpackWord(H5, out, outOff + 32); unpackWord(H6, out, outOff + 40); unpackWord(H7, out, outOff + 48); unpackWord(H8, out, outOff + 56); reset(); return DIGEST_LENGTH; } /** * reset the chaining variables */ public void reset() { super.reset(); /* SHA-512 initial hash value * The first 64 bits of the fractional parts of the square roots * of the first eight prime numbers */ H1 = 0x6a09e667f3bcc908l; H2 = 0xbb67ae8584caa73bl; H3 = 0x3c6ef372fe94f82bl; H4 = 0xa54ff53a5f1d36f1l; H5 = 0x510e527fade682d1l; H6 = 0x9b05688c2b3e6c1fl; H7 = 0x1f83d9abfb41bd6bl; H8 = 0x5be0cd19137e2179L; } } azureus-4.3.0.6/org/bouncycastle/crypto/digests/MD4Digest.java0000644000175000017500000001621410061400652023467 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; /** * implementation of MD4 as RFC 1320 by R. Rivest, MIT Laboratory for * Computer Science and RSA Data Security, Inc. *

      * NOTE: This algorithm is only included for backwards compatability * with legacy applications, it's not secure, don't use it for anything new! */ public class MD4Digest extends GeneralDigest { private static final int DIGEST_LENGTH = 16; private int H1, H2, H3, H4; // IV's private int[] X = new int[16]; private int xOff; /** * Standard constructor */ public MD4Digest() { reset(); } /** * Copy constructor. This will copy the state of the provided * message digest. */ public MD4Digest(MD4Digest t) { super(t); H1 = t.H1; H2 = t.H2; H3 = t.H3; H4 = t.H4; System.arraycopy(t.X, 0, X, 0, t.X.length); xOff = t.xOff; } public String getAlgorithmName() { return "MD4"; } public int getDigestSize() { return DIGEST_LENGTH; } protected void processWord( byte[] in, int inOff) { X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8) | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); if (xOff == 16) { processBlock(); } } protected void processLength( long bitLength) { if (xOff > 14) { processBlock(); } X[14] = (int)(bitLength & 0xffffffff); X[15] = (int)(bitLength >>> 32); } private void unpackWord( int word, byte[] out, int outOff) { out[outOff] = (byte)word; out[outOff + 1] = (byte)(word >>> 8); out[outOff + 2] = (byte)(word >>> 16); out[outOff + 3] = (byte)(word >>> 24); } public int doFinal( byte[] out, int outOff) { finish(); unpackWord(H1, out, outOff); unpackWord(H2, out, outOff + 4); unpackWord(H3, out, outOff + 8); unpackWord(H4, out, outOff + 12); reset(); return DIGEST_LENGTH; } /** * reset the chaining variables to the IV values. */ public void reset() { super.reset(); H1 = 0x67452301; H2 = 0xefcdab89; H3 = 0x98badcfe; H4 = 0x10325476; xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } // // round 1 left rotates // private static final int S11 = 3; private static final int S12 = 7; private static final int S13 = 11; private static final int S14 = 19; // // round 2 left rotates // private static final int S21 = 3; private static final int S22 = 5; private static final int S23 = 9; private static final int S24 = 13; // // round 3 left rotates // private static final int S31 = 3; private static final int S32 = 9; private static final int S33 = 11; private static final int S34 = 15; /* * rotate int x left n bits. */ private int rotateLeft( int x, int n) { return (x << n) | (x >>> (32 - n)); } /* * F, G, H and I are the basic MD4 functions. */ private int F( int u, int v, int w) { return (u & v) | (~u & w); } private int G( int u, int v, int w) { return (u & v) | (u & w) | (v & w); } private int H( int u, int v, int w) { return u ^ v ^ w; } protected void processBlock() { int a = H1; int b = H2; int c = H3; int d = H4; // // Round 1 - F cycle, 16 times. // a = rotateLeft((a + F(b, c, d) + X[ 0]), S11); d = rotateLeft((d + F(a, b, c) + X[ 1]), S12); c = rotateLeft((c + F(d, a, b) + X[ 2]), S13); b = rotateLeft((b + F(c, d, a) + X[ 3]), S14); a = rotateLeft((a + F(b, c, d) + X[ 4]), S11); d = rotateLeft((d + F(a, b, c) + X[ 5]), S12); c = rotateLeft((c + F(d, a, b) + X[ 6]), S13); b = rotateLeft((b + F(c, d, a) + X[ 7]), S14); a = rotateLeft((a + F(b, c, d) + X[ 8]), S11); d = rotateLeft((d + F(a, b, c) + X[ 9]), S12); c = rotateLeft((c + F(d, a, b) + X[10]), S13); b = rotateLeft((b + F(c, d, a) + X[11]), S14); a = rotateLeft((a + F(b, c, d) + X[12]), S11); d = rotateLeft((d + F(a, b, c) + X[13]), S12); c = rotateLeft((c + F(d, a, b) + X[14]), S13); b = rotateLeft((b + F(c, d, a) + X[15]), S14); // // Round 2 - G cycle, 16 times. // a = rotateLeft((a + G(b, c, d) + X[ 0] + 0x5a827999), S21); d = rotateLeft((d + G(a, b, c) + X[ 4] + 0x5a827999), S22); c = rotateLeft((c + G(d, a, b) + X[ 8] + 0x5a827999), S23); b = rotateLeft((b + G(c, d, a) + X[12] + 0x5a827999), S24); a = rotateLeft((a + G(b, c, d) + X[ 1] + 0x5a827999), S21); d = rotateLeft((d + G(a, b, c) + X[ 5] + 0x5a827999), S22); c = rotateLeft((c + G(d, a, b) + X[ 9] + 0x5a827999), S23); b = rotateLeft((b + G(c, d, a) + X[13] + 0x5a827999), S24); a = rotateLeft((a + G(b, c, d) + X[ 2] + 0x5a827999), S21); d = rotateLeft((d + G(a, b, c) + X[ 6] + 0x5a827999), S22); c = rotateLeft((c + G(d, a, b) + X[10] + 0x5a827999), S23); b = rotateLeft((b + G(c, d, a) + X[14] + 0x5a827999), S24); a = rotateLeft((a + G(b, c, d) + X[ 3] + 0x5a827999), S21); d = rotateLeft((d + G(a, b, c) + X[ 7] + 0x5a827999), S22); c = rotateLeft((c + G(d, a, b) + X[11] + 0x5a827999), S23); b = rotateLeft((b + G(c, d, a) + X[15] + 0x5a827999), S24); // // Round 3 - H cycle, 16 times. // a = rotateLeft((a + H(b, c, d) + X[ 0] + 0x6ed9eba1), S31); d = rotateLeft((d + H(a, b, c) + X[ 8] + 0x6ed9eba1), S32); c = rotateLeft((c + H(d, a, b) + X[ 4] + 0x6ed9eba1), S33); b = rotateLeft((b + H(c, d, a) + X[12] + 0x6ed9eba1), S34); a = rotateLeft((a + H(b, c, d) + X[ 2] + 0x6ed9eba1), S31); d = rotateLeft((d + H(a, b, c) + X[10] + 0x6ed9eba1), S32); c = rotateLeft((c + H(d, a, b) + X[ 6] + 0x6ed9eba1), S33); b = rotateLeft((b + H(c, d, a) + X[14] + 0x6ed9eba1), S34); a = rotateLeft((a + H(b, c, d) + X[ 1] + 0x6ed9eba1), S31); d = rotateLeft((d + H(a, b, c) + X[ 9] + 0x6ed9eba1), S32); c = rotateLeft((c + H(d, a, b) + X[ 5] + 0x6ed9eba1), S33); b = rotateLeft((b + H(c, d, a) + X[13] + 0x6ed9eba1), S34); a = rotateLeft((a + H(b, c, d) + X[ 3] + 0x6ed9eba1), S31); d = rotateLeft((d + H(a, b, c) + X[11] + 0x6ed9eba1), S32); c = rotateLeft((c + H(d, a, b) + X[ 7] + 0x6ed9eba1), S33); b = rotateLeft((b + H(c, d, a) + X[15] + 0x6ed9eba1), S34); H1 += a; H2 += b; H3 += c; H4 += d; // // reset the offset and clean out the word buffer. // xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } } azureus-4.3.0.6/org/bouncycastle/crypto/digests/RIPEMD128Digest.java0000644000175000017500000002362110061400652024316 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; /** * implementation of RIPEMD128 */ public class RIPEMD128Digest extends GeneralDigest { private static final int DIGEST_LENGTH = 16; private int H0, H1, H2, H3; // IV's private int[] X = new int[16]; private int xOff; /** * Standard constructor */ public RIPEMD128Digest() { reset(); } /** * Copy constructor. This will copy the state of the provided * message digest. */ public RIPEMD128Digest(RIPEMD128Digest t) { super(t); H0 = t.H0; H1 = t.H1; H2 = t.H2; H3 = t.H3; System.arraycopy(t.X, 0, X, 0, t.X.length); xOff = t.xOff; } public String getAlgorithmName() { return "RIPEMD128"; } public int getDigestSize() { return DIGEST_LENGTH; } protected void processWord( byte[] in, int inOff) { X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8) | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); if (xOff == 16) { processBlock(); } } protected void processLength( long bitLength) { if (xOff > 14) { processBlock(); } X[14] = (int)(bitLength & 0xffffffff); X[15] = (int)(bitLength >>> 32); } private void unpackWord( int word, byte[] out, int outOff) { out[outOff] = (byte)word; out[outOff + 1] = (byte)(word >>> 8); out[outOff + 2] = (byte)(word >>> 16); out[outOff + 3] = (byte)(word >>> 24); } public int doFinal( byte[] out, int outOff) { finish(); unpackWord(H0, out, outOff); unpackWord(H1, out, outOff + 4); unpackWord(H2, out, outOff + 8); unpackWord(H3, out, outOff + 12); reset(); return DIGEST_LENGTH; } /** * reset the chaining variables to the IV values. */ public void reset() { super.reset(); H0 = 0x67452301; H1 = 0xefcdab89; H2 = 0x98badcfe; H3 = 0x10325476; xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } /* * rotate int x left n bits. */ private final int RL( int x, int n) { return (x << n) | (x >>> (32 - n)); } /* * f1,f2,f3,f4 are the basic RIPEMD128 functions. */ /* * F */ private final int f1( int x, int y, int z) { return x ^ y ^ z; } /* * G */ private final int f2( int x, int y, int z) { return (x & y) | (~x & z); } /* * H */ private final int f3( int x, int y, int z) { return (x | ~y) ^ z; } /* * I */ private final int f4( int x, int y, int z) { return (x & z) | (y & ~z); } private final int F1( int a, int b, int c, int d, int x, int s) { return RL(a + f1(b, c, d) + x, s); } private final int F2( int a, int b, int c, int d, int x, int s) { return RL(a + f2(b, c, d) + x + 0x5a827999, s); } private final int F3( int a, int b, int c, int d, int x, int s) { return RL(a + f3(b, c, d) + x + 0x6ed9eba1, s); } private final int F4( int a, int b, int c, int d, int x, int s) { return RL(a + f4(b, c, d) + x + 0x8f1bbcdc, s); } private final int FF1( int a, int b, int c, int d, int x, int s) { return RL(a + f1(b, c, d) + x, s); } private final int FF2( int a, int b, int c, int d, int x, int s) { return RL(a + f2(b, c, d) + x + 0x6d703ef3, s); } private final int FF3( int a, int b, int c, int d, int x, int s) { return RL(a + f3(b, c, d) + x + 0x5c4dd124, s); } private final int FF4( int a, int b, int c, int d, int x, int s) { return RL(a + f4(b, c, d) + x + 0x50a28be6, s); } protected void processBlock() { int a, aa; int b, bb; int c, cc; int d, dd; a = aa = H0; b = bb = H1; c = cc = H2; d = dd = H3; // // Round 1 // a = F1(a, b, c, d, X[ 0], 11); d = F1(d, a, b, c, X[ 1], 14); c = F1(c, d, a, b, X[ 2], 15); b = F1(b, c, d, a, X[ 3], 12); a = F1(a, b, c, d, X[ 4], 5); d = F1(d, a, b, c, X[ 5], 8); c = F1(c, d, a, b, X[ 6], 7); b = F1(b, c, d, a, X[ 7], 9); a = F1(a, b, c, d, X[ 8], 11); d = F1(d, a, b, c, X[ 9], 13); c = F1(c, d, a, b, X[10], 14); b = F1(b, c, d, a, X[11], 15); a = F1(a, b, c, d, X[12], 6); d = F1(d, a, b, c, X[13], 7); c = F1(c, d, a, b, X[14], 9); b = F1(b, c, d, a, X[15], 8); // // Round 2 // a = F2(a, b, c, d, X[ 7], 7); d = F2(d, a, b, c, X[ 4], 6); c = F2(c, d, a, b, X[13], 8); b = F2(b, c, d, a, X[ 1], 13); a = F2(a, b, c, d, X[10], 11); d = F2(d, a, b, c, X[ 6], 9); c = F2(c, d, a, b, X[15], 7); b = F2(b, c, d, a, X[ 3], 15); a = F2(a, b, c, d, X[12], 7); d = F2(d, a, b, c, X[ 0], 12); c = F2(c, d, a, b, X[ 9], 15); b = F2(b, c, d, a, X[ 5], 9); a = F2(a, b, c, d, X[ 2], 11); d = F2(d, a, b, c, X[14], 7); c = F2(c, d, a, b, X[11], 13); b = F2(b, c, d, a, X[ 8], 12); // // Round 3 // a = F3(a, b, c, d, X[ 3], 11); d = F3(d, a, b, c, X[10], 13); c = F3(c, d, a, b, X[14], 6); b = F3(b, c, d, a, X[ 4], 7); a = F3(a, b, c, d, X[ 9], 14); d = F3(d, a, b, c, X[15], 9); c = F3(c, d, a, b, X[ 8], 13); b = F3(b, c, d, a, X[ 1], 15); a = F3(a, b, c, d, X[ 2], 14); d = F3(d, a, b, c, X[ 7], 8); c = F3(c, d, a, b, X[ 0], 13); b = F3(b, c, d, a, X[ 6], 6); a = F3(a, b, c, d, X[13], 5); d = F3(d, a, b, c, X[11], 12); c = F3(c, d, a, b, X[ 5], 7); b = F3(b, c, d, a, X[12], 5); // // Round 4 // a = F4(a, b, c, d, X[ 1], 11); d = F4(d, a, b, c, X[ 9], 12); c = F4(c, d, a, b, X[11], 14); b = F4(b, c, d, a, X[10], 15); a = F4(a, b, c, d, X[ 0], 14); d = F4(d, a, b, c, X[ 8], 15); c = F4(c, d, a, b, X[12], 9); b = F4(b, c, d, a, X[ 4], 8); a = F4(a, b, c, d, X[13], 9); d = F4(d, a, b, c, X[ 3], 14); c = F4(c, d, a, b, X[ 7], 5); b = F4(b, c, d, a, X[15], 6); a = F4(a, b, c, d, X[14], 8); d = F4(d, a, b, c, X[ 5], 6); c = F4(c, d, a, b, X[ 6], 5); b = F4(b, c, d, a, X[ 2], 12); // // Parallel round 1 // aa = FF4(aa, bb, cc, dd, X[ 5], 8); dd = FF4(dd, aa, bb, cc, X[14], 9); cc = FF4(cc, dd, aa, bb, X[ 7], 9); bb = FF4(bb, cc, dd, aa, X[ 0], 11); aa = FF4(aa, bb, cc, dd, X[ 9], 13); dd = FF4(dd, aa, bb, cc, X[ 2], 15); cc = FF4(cc, dd, aa, bb, X[11], 15); bb = FF4(bb, cc, dd, aa, X[ 4], 5); aa = FF4(aa, bb, cc, dd, X[13], 7); dd = FF4(dd, aa, bb, cc, X[ 6], 7); cc = FF4(cc, dd, aa, bb, X[15], 8); bb = FF4(bb, cc, dd, aa, X[ 8], 11); aa = FF4(aa, bb, cc, dd, X[ 1], 14); dd = FF4(dd, aa, bb, cc, X[10], 14); cc = FF4(cc, dd, aa, bb, X[ 3], 12); bb = FF4(bb, cc, dd, aa, X[12], 6); // // Parallel round 2 // aa = FF3(aa, bb, cc, dd, X[ 6], 9); dd = FF3(dd, aa, bb, cc, X[11], 13); cc = FF3(cc, dd, aa, bb, X[ 3], 15); bb = FF3(bb, cc, dd, aa, X[ 7], 7); aa = FF3(aa, bb, cc, dd, X[ 0], 12); dd = FF3(dd, aa, bb, cc, X[13], 8); cc = FF3(cc, dd, aa, bb, X[ 5], 9); bb = FF3(bb, cc, dd, aa, X[10], 11); aa = FF3(aa, bb, cc, dd, X[14], 7); dd = FF3(dd, aa, bb, cc, X[15], 7); cc = FF3(cc, dd, aa, bb, X[ 8], 12); bb = FF3(bb, cc, dd, aa, X[12], 7); aa = FF3(aa, bb, cc, dd, X[ 4], 6); dd = FF3(dd, aa, bb, cc, X[ 9], 15); cc = FF3(cc, dd, aa, bb, X[ 1], 13); bb = FF3(bb, cc, dd, aa, X[ 2], 11); // // Parallel round 3 // aa = FF2(aa, bb, cc, dd, X[15], 9); dd = FF2(dd, aa, bb, cc, X[ 5], 7); cc = FF2(cc, dd, aa, bb, X[ 1], 15); bb = FF2(bb, cc, dd, aa, X[ 3], 11); aa = FF2(aa, bb, cc, dd, X[ 7], 8); dd = FF2(dd, aa, bb, cc, X[14], 6); cc = FF2(cc, dd, aa, bb, X[ 6], 6); bb = FF2(bb, cc, dd, aa, X[ 9], 14); aa = FF2(aa, bb, cc, dd, X[11], 12); dd = FF2(dd, aa, bb, cc, X[ 8], 13); cc = FF2(cc, dd, aa, bb, X[12], 5); bb = FF2(bb, cc, dd, aa, X[ 2], 14); aa = FF2(aa, bb, cc, dd, X[10], 13); dd = FF2(dd, aa, bb, cc, X[ 0], 13); cc = FF2(cc, dd, aa, bb, X[ 4], 7); bb = FF2(bb, cc, dd, aa, X[13], 5); // // Parallel round 4 // aa = FF1(aa, bb, cc, dd, X[ 8], 15); dd = FF1(dd, aa, bb, cc, X[ 6], 5); cc = FF1(cc, dd, aa, bb, X[ 4], 8); bb = FF1(bb, cc, dd, aa, X[ 1], 11); aa = FF1(aa, bb, cc, dd, X[ 3], 14); dd = FF1(dd, aa, bb, cc, X[11], 14); cc = FF1(cc, dd, aa, bb, X[15], 6); bb = FF1(bb, cc, dd, aa, X[ 0], 14); aa = FF1(aa, bb, cc, dd, X[ 5], 6); dd = FF1(dd, aa, bb, cc, X[12], 9); cc = FF1(cc, dd, aa, bb, X[ 2], 12); bb = FF1(bb, cc, dd, aa, X[13], 9); aa = FF1(aa, bb, cc, dd, X[ 9], 12); dd = FF1(dd, aa, bb, cc, X[ 7], 5); cc = FF1(cc, dd, aa, bb, X[10], 15); bb = FF1(bb, cc, dd, aa, X[14], 8); dd += c + H1; // final result for H0 // // combine the results // H1 = H2 + d + aa; H2 = H3 + a + bb; H3 = H0 + b + cc; H0 = dd; // // reset the offset and clean out the word buffer. // xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } } azureus-4.3.0.6/org/bouncycastle/crypto/digests/SHA1Digest.java0000644000175000017500000001202010061400652023566 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; /** * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349. * * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5 * is the "endienness" of the word processing! */ public class SHA1Digest extends GeneralDigest { private static final int DIGEST_LENGTH = 20; private int H1, H2, H3, H4, H5; private int[] X = new int[80]; private int xOff; /** * Standard constructor */ public SHA1Digest() { reset(); } /** * Copy constructor. This will copy the state of the provided * message digest. */ public SHA1Digest(SHA1Digest t) { super(t); H1 = t.H1; H2 = t.H2; H3 = t.H3; H4 = t.H4; H5 = t.H5; System.arraycopy(t.X, 0, X, 0, t.X.length); xOff = t.xOff; } public String getAlgorithmName() { return "SHA-1"; } public int getDigestSize() { return DIGEST_LENGTH; } protected void processWord( byte[] in, int inOff) { X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16) | ((in[inOff + 2] & 0xff) << 8) | ((in[inOff + 3] & 0xff)); if (xOff == 16) { processBlock(); } } private void unpackWord( int word, byte[] out, int outOff) { out[outOff] = (byte)(word >>> 24); out[outOff + 1] = (byte)(word >>> 16); out[outOff + 2] = (byte)(word >>> 8); out[outOff + 3] = (byte)word; } protected void processLength( long bitLength) { if (xOff > 14) { processBlock(); } X[14] = (int)(bitLength >>> 32); X[15] = (int)(bitLength & 0xffffffff); } public int doFinal( byte[] out, int outOff) { finish(); unpackWord(H1, out, outOff); unpackWord(H2, out, outOff + 4); unpackWord(H3, out, outOff + 8); unpackWord(H4, out, outOff + 12); unpackWord(H5, out, outOff + 16); reset(); return DIGEST_LENGTH; } /** * reset the chaining variables */ public void reset() { super.reset(); H1 = 0x67452301; H2 = 0xefcdab89; H3 = 0x98badcfe; H4 = 0x10325476; H5 = 0xc3d2e1f0; xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } // // Additive constants // private static final int Y1 = 0x5a827999; private static final int Y2 = 0x6ed9eba1; private static final int Y3 = 0x8f1bbcdc; private static final int Y4 = 0xca62c1d6; private int f( int u, int v, int w) { return ((u & v) | ((~u) & w)); } private int h( int u, int v, int w) { return (u ^ v ^ w); } private int g( int u, int v, int w) { return ((u & v) | (u & w) | (v & w)); } private int rotateLeft( int x, int n) { return (x << n) | (x >>> (32 - n)); } protected void processBlock() { // // expand 16 word block into 80 word block. // for (int i = 16; i <= 79; i++) { X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1); } // // set up working variables. // int A = H1; int B = H2; int C = H3; int D = H4; int E = H5; // // round 1 // for (int j = 0; j <= 19; j++) { int t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1; E = D; D = C; C = rotateLeft(B, 30); B = A; A = t; } // // round 2 // for (int j = 20; j <= 39; j++) { int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2; E = D; D = C; C = rotateLeft(B, 30); B = A; A = t; } // // round 3 // for (int j = 40; j <= 59; j++) { int t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3; E = D; D = C; C = rotateLeft(B, 30); B = A; A = t; } // // round 4 // for (int j = 60; j <= 79; j++) { int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4; E = D; D = C; C = rotateLeft(B, 30); B = A; A = t; } H1 += A; H2 += B; H3 += C; H4 += D; H5 += E; // // reset the offset and clean out the word buffer. // xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } } azureus-4.3.0.6/org/bouncycastle/crypto/digests/LongDigest.java0000644000175000017500000002005510061400652024000 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; import org.bouncycastle.crypto.Digest; /** * Base class for SHA-384 and SHA-512. */ public abstract class LongDigest implements Digest { private byte[] xBuf; private int xBufOff; private long byteCount1; private long byteCount2; protected long H1, H2, H3, H4, H5, H6, H7, H8; private long[] W = new long[80]; private int wOff; /** * Constructor for variable length word */ protected LongDigest() { xBuf = new byte[8]; xBufOff = 0; reset(); } /** * Copy constructor. We are using copy constructors in place * of the Object.clone() interface as this interface is not * supported by J2ME. */ protected LongDigest(LongDigest t) { xBuf = new byte[t.xBuf.length]; System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); xBufOff = t.xBufOff; byteCount1 = t.byteCount1; byteCount2 = t.byteCount2; H1 = t.H1; H2 = t.H2; H3 = t.H3; H4 = t.H4; H5 = t.H5; H6 = t.H6; H7 = t.H7; H8 = t.H8; System.arraycopy(t.W, 0, W, 0, t.W.length); wOff = t.wOff; } public void update( byte in) { xBuf[xBufOff++] = in; if (xBufOff == xBuf.length) { processWord(xBuf, 0); xBufOff = 0; } byteCount1++; } public void update( byte[] in, int inOff, int len) { // // fill the current word // while ((xBufOff != 0) && (len > 0)) { update(in[inOff]); inOff++; len--; } // // process whole words. // while (len > xBuf.length) { processWord(in, inOff); inOff += xBuf.length; len -= xBuf.length; byteCount1 += xBuf.length; } // // load in the remainder. // while (len > 0) { update(in[inOff]); inOff++; len--; } } public void finish() { adjustByteCounts(); long lowBitLength = byteCount1 << 3; long hiBitLength = byteCount2; // // add the pad bytes. // update((byte)128); while (xBufOff != 0) { update((byte)0); } processLength(lowBitLength, hiBitLength); processBlock(); } public void reset() { byteCount1 = 0; byteCount2 = 0; xBufOff = 0; for ( int i = 0; i < xBuf.length; i++ ) { xBuf[i] = 0; } wOff = 0; for (int i = 0; i != W.length; i++) { W[i] = 0; } } protected void processWord( byte[] in, int inOff) { W[wOff++] = ((long)(in[inOff] & 0xff) << 56) | ((long)(in[inOff + 1] & 0xff) << 48) | ((long)(in[inOff + 2] & 0xff) << 40) | ((long)(in[inOff + 3] & 0xff) << 32) | ((long)(in[inOff + 4] & 0xff) << 24) | ((long)(in[inOff + 5] & 0xff) << 16) | ((long)(in[inOff + 6] & 0xff) << 8) | ((in[inOff + 7] & 0xff)); if (wOff == 16) { processBlock(); } } protected void unpackWord( long word, byte[] out, int outOff) { out[outOff] = (byte)(word >>> 56); out[outOff + 1] = (byte)(word >>> 48); out[outOff + 2] = (byte)(word >>> 40); out[outOff + 3] = (byte)(word >>> 32); out[outOff + 4] = (byte)(word >>> 24); out[outOff + 5] = (byte)(word >>> 16); out[outOff + 6] = (byte)(word >>> 8); out[outOff + 7] = (byte)word; } /** * adjust the byte counts so that byteCount2 represents the * upper long (less 3 bits) word of the byte count. */ private void adjustByteCounts() { if (byteCount1 > 0x1fffffffffffffffL) { byteCount2 += (byteCount1 >>> 61); byteCount1 &= 0x1fffffffffffffffL; } } protected void processLength( long lowW, long hiW) { if (wOff > 14) { processBlock(); } W[14] = hiW; W[15] = lowW; } protected void processBlock() { adjustByteCounts(); // // expand 16 word block into 80 word blocks. // for (int t = 16; t <= 79; t++) { W[t] = Sigma1(W[t - 2]) + W[t - 7] + Sigma0(W[t - 15]) + W[t - 16]; } // // set up working variables. // long a = H1; long b = H2; long c = H3; long d = H4; long e = H5; long f = H6; long g = H7; long h = H8; for (int t = 0; t <= 79; t++) { long T1, T2; T1 = h + Sum1(e) + Ch(e, f, g) + K[t] + W[t]; T2 = Sum0(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; } H1 += a; H2 += b; H3 += c; H4 += d; H5 += e; H6 += f; H7 += g; H8 += h; // // reset the offset and clean out the word buffer. // wOff = 0; for (int i = 0; i != W.length; i++) { W[i] = 0; } } private long rotateRight( long x, int n) { return (x >>> n) | (x << (64 - n)); } /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */ private long Ch( long x, long y, long z) { return ((x & y) ^ ((~x) & z)); } private long Maj( long x, long y, long z) { return ((x & y) ^ (x & z) ^ (y & z)); } private long Sum0( long x) { return rotateRight(x, 28) ^ rotateRight(x, 34) ^ rotateRight(x, 39); } private long Sum1( long x) { return rotateRight(x, 14) ^ rotateRight(x, 18) ^ rotateRight(x, 41); } private long Sigma0( long x) { return rotateRight(x, 1) ^ rotateRight(x, 8) ^ (x >>> 7); } private long Sigma1( long x) { return rotateRight(x, 19) ^ rotateRight(x, 61) ^ (x >>> 6); } /* SHA-384 and SHA-512 Constants * (represent the first 64 bits of the fractional parts of the * cube roots of the first sixty-four prime numbers) */ static final long K[] = { 0x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL, 0x3956c25bf348b538L, 0x59f111f1b605d019L, 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L, 0xd807aa98a3030242L, 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L, 0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L, 0xc19bf174cf692694L, 0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L, 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L, 0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L, 0x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L, 0xc6e00bf33da88fc2L, 0xd5a79147930aa725L, 0x06ca6351e003826fL, 0x142929670a0e6e70L, 0x27b70a8546d22ffcL, 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL, 0x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L, 0x92722c851482353bL, 0xa2bfe8a14cf10364L, 0xa81a664bbc423001L, 0xc24b8b70d0f89791L, 0xc76c51a30654be30L, 0xd192e819d6ef5218L, 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L, 0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L, 0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL, 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L, 0x748f82ee5defb2fcL, 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL, 0x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL, 0xca273eceea26619cL, 0xd186b8c721c0c207L, 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L, 0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL, 0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL, 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L }; } azureus-4.3.0.6/org/bouncycastle/crypto/digests/SHA384Digest.java0000644000175000017500000000321510061400652023752 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; /** * Draft FIPS 180-2 implementation of SHA-384. Note: As this is * based on a draft this implementation is subject to change. * *

       *         block  word  digest
       * SHA-1   512    32    160
       * SHA-256 512    32    256
       * SHA-384 1024   64    384
       * SHA-512 1024   64    512
       * 
      */ public class SHA384Digest extends LongDigest { private static final int DIGEST_LENGTH = 48; /** * Standard constructor */ public SHA384Digest() { } /** * Copy constructor. This will copy the state of the provided * message digest. */ public SHA384Digest(SHA384Digest t) { super(t); } public String getAlgorithmName() { return "SHA-384"; } public int getDigestSize() { return DIGEST_LENGTH; } public int doFinal( byte[] out, int outOff) { finish(); unpackWord(H1, out, outOff); unpackWord(H2, out, outOff + 8); unpackWord(H3, out, outOff + 16); unpackWord(H4, out, outOff + 24); unpackWord(H5, out, outOff + 32); unpackWord(H6, out, outOff + 40); reset(); return DIGEST_LENGTH; } /** * reset the chaining variables */ public void reset() { super.reset(); /* SHA-384 initial hash value * The first 64 bits of the fractional parts of the square roots * of the 9th through 16th prime numbers */ H1 = 0xcbbb9d5dc1059ed8l; H2 = 0x629a292a367cd507l; H3 = 0x9159015a3070dd17l; H4 = 0x152fecd8f70e5939l; H5 = 0x67332667ffc00b31l; H6 = 0x8eb44a8768581511l; H7 = 0xdb0c2e0d64f98fa7l; H8 = 0x47b5481dbefa4fa4l; } } azureus-4.3.0.6/org/bouncycastle/crypto/digests/TigerDigest.java0000644000175000017500000013500710061400652024157 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; import org.bouncycastle.crypto.Digest; /** * implementation of Tiger based on: * * http://www.cs.technion.ac.il/~biham/Reports/Tiger */ public class TigerDigest implements Digest { /* * S-Boxes. */ private static final long[] t1 = { 0x02AAB17CF7E90C5EL /* 0 */, 0xAC424B03E243A8ECL /* 1 */, 0x72CD5BE30DD5FCD3L /* 2 */, 0x6D019B93F6F97F3AL /* 3 */, 0xCD9978FFD21F9193L /* 4 */, 0x7573A1C9708029E2L /* 5 */, 0xB164326B922A83C3L /* 6 */, 0x46883EEE04915870L /* 7 */, 0xEAACE3057103ECE6L /* 8 */, 0xC54169B808A3535CL /* 9 */, 0x4CE754918DDEC47CL /* 10 */, 0x0AA2F4DFDC0DF40CL /* 11 */, 0x10B76F18A74DBEFAL /* 12 */, 0xC6CCB6235AD1AB6AL /* 13 */, 0x13726121572FE2FFL /* 14 */, 0x1A488C6F199D921EL /* 15 */, 0x4BC9F9F4DA0007CAL /* 16 */, 0x26F5E6F6E85241C7L /* 17 */, 0x859079DBEA5947B6L /* 18 */, 0x4F1885C5C99E8C92L /* 19 */, 0xD78E761EA96F864BL /* 20 */, 0x8E36428C52B5C17DL /* 21 */, 0x69CF6827373063C1L /* 22 */, 0xB607C93D9BB4C56EL /* 23 */, 0x7D820E760E76B5EAL /* 24 */, 0x645C9CC6F07FDC42L /* 25 */, 0xBF38A078243342E0L /* 26 */, 0x5F6B343C9D2E7D04L /* 27 */, 0xF2C28AEB600B0EC6L /* 28 */, 0x6C0ED85F7254BCACL /* 29 */, 0x71592281A4DB4FE5L /* 30 */, 0x1967FA69CE0FED9FL /* 31 */, 0xFD5293F8B96545DBL /* 32 */, 0xC879E9D7F2A7600BL /* 33 */, 0x860248920193194EL /* 34 */, 0xA4F9533B2D9CC0B3L /* 35 */, 0x9053836C15957613L /* 36 */, 0xDB6DCF8AFC357BF1L /* 37 */, 0x18BEEA7A7A370F57L /* 38 */, 0x037117CA50B99066L /* 39 */, 0x6AB30A9774424A35L /* 40 */, 0xF4E92F02E325249BL /* 41 */, 0x7739DB07061CCAE1L /* 42 */, 0xD8F3B49CECA42A05L /* 43 */, 0xBD56BE3F51382F73L /* 44 */, 0x45FAED5843B0BB28L /* 45 */, 0x1C813D5C11BF1F83L /* 46 */, 0x8AF0E4B6D75FA169L /* 47 */, 0x33EE18A487AD9999L /* 48 */, 0x3C26E8EAB1C94410L /* 49 */, 0xB510102BC0A822F9L /* 50 */, 0x141EEF310CE6123BL /* 51 */, 0xFC65B90059DDB154L /* 52 */, 0xE0158640C5E0E607L /* 53 */, 0x884E079826C3A3CFL /* 54 */, 0x930D0D9523C535FDL /* 55 */, 0x35638D754E9A2B00L /* 56 */, 0x4085FCCF40469DD5L /* 57 */, 0xC4B17AD28BE23A4CL /* 58 */, 0xCAB2F0FC6A3E6A2EL /* 59 */, 0x2860971A6B943FCDL /* 60 */, 0x3DDE6EE212E30446L /* 61 */, 0x6222F32AE01765AEL /* 62 */, 0x5D550BB5478308FEL /* 63 */, 0xA9EFA98DA0EDA22AL /* 64 */, 0xC351A71686C40DA7L /* 65 */, 0x1105586D9C867C84L /* 66 */, 0xDCFFEE85FDA22853L /* 67 */, 0xCCFBD0262C5EEF76L /* 68 */, 0xBAF294CB8990D201L /* 69 */, 0xE69464F52AFAD975L /* 70 */, 0x94B013AFDF133E14L /* 71 */, 0x06A7D1A32823C958L /* 72 */, 0x6F95FE5130F61119L /* 73 */, 0xD92AB34E462C06C0L /* 74 */, 0xED7BDE33887C71D2L /* 75 */, 0x79746D6E6518393EL /* 76 */, 0x5BA419385D713329L /* 77 */, 0x7C1BA6B948A97564L /* 78 */, 0x31987C197BFDAC67L /* 79 */, 0xDE6C23C44B053D02L /* 80 */, 0x581C49FED002D64DL /* 81 */, 0xDD474D6338261571L /* 82 */, 0xAA4546C3E473D062L /* 83 */, 0x928FCE349455F860L /* 84 */, 0x48161BBACAAB94D9L /* 85 */, 0x63912430770E6F68L /* 86 */, 0x6EC8A5E602C6641CL /* 87 */, 0x87282515337DDD2BL /* 88 */, 0x2CDA6B42034B701BL /* 89 */, 0xB03D37C181CB096DL /* 90 */, 0xE108438266C71C6FL /* 91 */, 0x2B3180C7EB51B255L /* 92 */, 0xDF92B82F96C08BBCL /* 93 */, 0x5C68C8C0A632F3BAL /* 94 */, 0x5504CC861C3D0556L /* 95 */, 0xABBFA4E55FB26B8FL /* 96 */, 0x41848B0AB3BACEB4L /* 97 */, 0xB334A273AA445D32L /* 98 */, 0xBCA696F0A85AD881L /* 99 */, 0x24F6EC65B528D56CL /* 100 */, 0x0CE1512E90F4524AL /* 101 */, 0x4E9DD79D5506D35AL /* 102 */, 0x258905FAC6CE9779L /* 103 */, 0x2019295B3E109B33L /* 104 */, 0xF8A9478B73A054CCL /* 105 */, 0x2924F2F934417EB0L /* 106 */, 0x3993357D536D1BC4L /* 107 */, 0x38A81AC21DB6FF8BL /* 108 */, 0x47C4FBF17D6016BFL /* 109 */, 0x1E0FAADD7667E3F5L /* 110 */, 0x7ABCFF62938BEB96L /* 111 */, 0xA78DAD948FC179C9L /* 112 */, 0x8F1F98B72911E50DL /* 113 */, 0x61E48EAE27121A91L /* 114 */, 0x4D62F7AD31859808L /* 115 */, 0xECEBA345EF5CEAEBL /* 116 */, 0xF5CEB25EBC9684CEL /* 117 */, 0xF633E20CB7F76221L /* 118 */, 0xA32CDF06AB8293E4L /* 119 */, 0x985A202CA5EE2CA4L /* 120 */, 0xCF0B8447CC8A8FB1L /* 121 */, 0x9F765244979859A3L /* 122 */, 0xA8D516B1A1240017L /* 123 */, 0x0BD7BA3EBB5DC726L /* 124 */, 0xE54BCA55B86ADB39L /* 125 */, 0x1D7A3AFD6C478063L /* 126 */, 0x519EC608E7669EDDL /* 127 */, 0x0E5715A2D149AA23L /* 128 */, 0x177D4571848FF194L /* 129 */, 0xEEB55F3241014C22L /* 130 */, 0x0F5E5CA13A6E2EC2L /* 131 */, 0x8029927B75F5C361L /* 132 */, 0xAD139FABC3D6E436L /* 133 */, 0x0D5DF1A94CCF402FL /* 134 */, 0x3E8BD948BEA5DFC8L /* 135 */, 0xA5A0D357BD3FF77EL /* 136 */, 0xA2D12E251F74F645L /* 137 */, 0x66FD9E525E81A082L /* 138 */, 0x2E0C90CE7F687A49L /* 139 */, 0xC2E8BCBEBA973BC5L /* 140 */, 0x000001BCE509745FL /* 141 */, 0x423777BBE6DAB3D6L /* 142 */, 0xD1661C7EAEF06EB5L /* 143 */, 0xA1781F354DAACFD8L /* 144 */, 0x2D11284A2B16AFFCL /* 145 */, 0xF1FC4F67FA891D1FL /* 146 */, 0x73ECC25DCB920ADAL /* 147 */, 0xAE610C22C2A12651L /* 148 */, 0x96E0A810D356B78AL /* 149 */, 0x5A9A381F2FE7870FL /* 150 */, 0xD5AD62EDE94E5530L /* 151 */, 0xD225E5E8368D1427L /* 152 */, 0x65977B70C7AF4631L /* 153 */, 0x99F889B2DE39D74FL /* 154 */, 0x233F30BF54E1D143L /* 155 */, 0x9A9675D3D9A63C97L /* 156 */, 0x5470554FF334F9A8L /* 157 */, 0x166ACB744A4F5688L /* 158 */, 0x70C74CAAB2E4AEADL /* 159 */, 0xF0D091646F294D12L /* 160 */, 0x57B82A89684031D1L /* 161 */, 0xEFD95A5A61BE0B6BL /* 162 */, 0x2FBD12E969F2F29AL /* 163 */, 0x9BD37013FEFF9FE8L /* 164 */, 0x3F9B0404D6085A06L /* 165 */, 0x4940C1F3166CFE15L /* 166 */, 0x09542C4DCDF3DEFBL /* 167 */, 0xB4C5218385CD5CE3L /* 168 */, 0xC935B7DC4462A641L /* 169 */, 0x3417F8A68ED3B63FL /* 170 */, 0xB80959295B215B40L /* 171 */, 0xF99CDAEF3B8C8572L /* 172 */, 0x018C0614F8FCB95DL /* 173 */, 0x1B14ACCD1A3ACDF3L /* 174 */, 0x84D471F200BB732DL /* 175 */, 0xC1A3110E95E8DA16L /* 176 */, 0x430A7220BF1A82B8L /* 177 */, 0xB77E090D39DF210EL /* 178 */, 0x5EF4BD9F3CD05E9DL /* 179 */, 0x9D4FF6DA7E57A444L /* 180 */, 0xDA1D60E183D4A5F8L /* 181 */, 0xB287C38417998E47L /* 182 */, 0xFE3EDC121BB31886L /* 183 */, 0xC7FE3CCC980CCBEFL /* 184 */, 0xE46FB590189BFD03L /* 185 */, 0x3732FD469A4C57DCL /* 186 */, 0x7EF700A07CF1AD65L /* 187 */, 0x59C64468A31D8859L /* 188 */, 0x762FB0B4D45B61F6L /* 189 */, 0x155BAED099047718L /* 190 */, 0x68755E4C3D50BAA6L /* 191 */, 0xE9214E7F22D8B4DFL /* 192 */, 0x2ADDBF532EAC95F4L /* 193 */, 0x32AE3909B4BD0109L /* 194 */, 0x834DF537B08E3450L /* 195 */, 0xFA209DA84220728DL /* 196 */, 0x9E691D9B9EFE23F7L /* 197 */, 0x0446D288C4AE8D7FL /* 198 */, 0x7B4CC524E169785BL /* 199 */, 0x21D87F0135CA1385L /* 200 */, 0xCEBB400F137B8AA5L /* 201 */, 0x272E2B66580796BEL /* 202 */, 0x3612264125C2B0DEL /* 203 */, 0x057702BDAD1EFBB2L /* 204 */, 0xD4BABB8EACF84BE9L /* 205 */, 0x91583139641BC67BL /* 206 */, 0x8BDC2DE08036E024L /* 207 */, 0x603C8156F49F68EDL /* 208 */, 0xF7D236F7DBEF5111L /* 209 */, 0x9727C4598AD21E80L /* 210 */, 0xA08A0896670A5FD7L /* 211 */, 0xCB4A8F4309EBA9CBL /* 212 */, 0x81AF564B0F7036A1L /* 213 */, 0xC0B99AA778199ABDL /* 214 */, 0x959F1EC83FC8E952L /* 215 */, 0x8C505077794A81B9L /* 216 */, 0x3ACAAF8F056338F0L /* 217 */, 0x07B43F50627A6778L /* 218 */, 0x4A44AB49F5ECCC77L /* 219 */, 0x3BC3D6E4B679EE98L /* 220 */, 0x9CC0D4D1CF14108CL /* 221 */, 0x4406C00B206BC8A0L /* 222 */, 0x82A18854C8D72D89L /* 223 */, 0x67E366B35C3C432CL /* 224 */, 0xB923DD61102B37F2L /* 225 */, 0x56AB2779D884271DL /* 226 */, 0xBE83E1B0FF1525AFL /* 227 */, 0xFB7C65D4217E49A9L /* 228 */, 0x6BDBE0E76D48E7D4L /* 229 */, 0x08DF828745D9179EL /* 230 */, 0x22EA6A9ADD53BD34L /* 231 */, 0xE36E141C5622200AL /* 232 */, 0x7F805D1B8CB750EEL /* 233 */, 0xAFE5C7A59F58E837L /* 234 */, 0xE27F996A4FB1C23CL /* 235 */, 0xD3867DFB0775F0D0L /* 236 */, 0xD0E673DE6E88891AL /* 237 */, 0x123AEB9EAFB86C25L /* 238 */, 0x30F1D5D5C145B895L /* 239 */, 0xBB434A2DEE7269E7L /* 240 */, 0x78CB67ECF931FA38L /* 241 */, 0xF33B0372323BBF9CL /* 242 */, 0x52D66336FB279C74L /* 243 */, 0x505F33AC0AFB4EAAL /* 244 */, 0xE8A5CD99A2CCE187L /* 245 */, 0x534974801E2D30BBL /* 246 */, 0x8D2D5711D5876D90L /* 247 */, 0x1F1A412891BC038EL /* 248 */, 0xD6E2E71D82E56648L /* 249 */, 0x74036C3A497732B7L /* 250 */, 0x89B67ED96361F5ABL /* 251 */, 0xFFED95D8F1EA02A2L /* 252 */, 0xE72B3BD61464D43DL /* 253 */, 0xA6300F170BDC4820L /* 254 */, 0xEBC18760ED78A77AL /* 255 */, }; private static final long[] t2 = { 0xE6A6BE5A05A12138L /* 256 */, 0xB5A122A5B4F87C98L /* 257 */, 0x563C6089140B6990L /* 258 */, 0x4C46CB2E391F5DD5L /* 259 */, 0xD932ADDBC9B79434L /* 260 */, 0x08EA70E42015AFF5L /* 261 */, 0xD765A6673E478CF1L /* 262 */, 0xC4FB757EAB278D99L /* 263 */, 0xDF11C6862D6E0692L /* 264 */, 0xDDEB84F10D7F3B16L /* 265 */, 0x6F2EF604A665EA04L /* 266 */, 0x4A8E0F0FF0E0DFB3L /* 267 */, 0xA5EDEEF83DBCBA51L /* 268 */, 0xFC4F0A2A0EA4371EL /* 269 */, 0xE83E1DA85CB38429L /* 270 */, 0xDC8FF882BA1B1CE2L /* 271 */, 0xCD45505E8353E80DL /* 272 */, 0x18D19A00D4DB0717L /* 273 */, 0x34A0CFEDA5F38101L /* 274 */, 0x0BE77E518887CAF2L /* 275 */, 0x1E341438B3C45136L /* 276 */, 0xE05797F49089CCF9L /* 277 */, 0xFFD23F9DF2591D14L /* 278 */, 0x543DDA228595C5CDL /* 279 */, 0x661F81FD99052A33L /* 280 */, 0x8736E641DB0F7B76L /* 281 */, 0x15227725418E5307L /* 282 */, 0xE25F7F46162EB2FAL /* 283 */, 0x48A8B2126C13D9FEL /* 284 */, 0xAFDC541792E76EEAL /* 285 */, 0x03D912BFC6D1898FL /* 286 */, 0x31B1AAFA1B83F51BL /* 287 */, 0xF1AC2796E42AB7D9L /* 288 */, 0x40A3A7D7FCD2EBACL /* 289 */, 0x1056136D0AFBBCC5L /* 290 */, 0x7889E1DD9A6D0C85L /* 291 */, 0xD33525782A7974AAL /* 292 */, 0xA7E25D09078AC09BL /* 293 */, 0xBD4138B3EAC6EDD0L /* 294 */, 0x920ABFBE71EB9E70L /* 295 */, 0xA2A5D0F54FC2625CL /* 296 */, 0xC054E36B0B1290A3L /* 297 */, 0xF6DD59FF62FE932BL /* 298 */, 0x3537354511A8AC7DL /* 299 */, 0xCA845E9172FADCD4L /* 300 */, 0x84F82B60329D20DCL /* 301 */, 0x79C62CE1CD672F18L /* 302 */, 0x8B09A2ADD124642CL /* 303 */, 0xD0C1E96A19D9E726L /* 304 */, 0x5A786A9B4BA9500CL /* 305 */, 0x0E020336634C43F3L /* 306 */, 0xC17B474AEB66D822L /* 307 */, 0x6A731AE3EC9BAAC2L /* 308 */, 0x8226667AE0840258L /* 309 */, 0x67D4567691CAECA5L /* 310 */, 0x1D94155C4875ADB5L /* 311 */, 0x6D00FD985B813FDFL /* 312 */, 0x51286EFCB774CD06L /* 313 */, 0x5E8834471FA744AFL /* 314 */, 0xF72CA0AEE761AE2EL /* 315 */, 0xBE40E4CDAEE8E09AL /* 316 */, 0xE9970BBB5118F665L /* 317 */, 0x726E4BEB33DF1964L /* 318 */, 0x703B000729199762L /* 319 */, 0x4631D816F5EF30A7L /* 320 */, 0xB880B5B51504A6BEL /* 321 */, 0x641793C37ED84B6CL /* 322 */, 0x7B21ED77F6E97D96L /* 323 */, 0x776306312EF96B73L /* 324 */, 0xAE528948E86FF3F4L /* 325 */, 0x53DBD7F286A3F8F8L /* 326 */, 0x16CADCE74CFC1063L /* 327 */, 0x005C19BDFA52C6DDL /* 328 */, 0x68868F5D64D46AD3L /* 329 */, 0x3A9D512CCF1E186AL /* 330 */, 0x367E62C2385660AEL /* 331 */, 0xE359E7EA77DCB1D7L /* 332 */, 0x526C0773749ABE6EL /* 333 */, 0x735AE5F9D09F734BL /* 334 */, 0x493FC7CC8A558BA8L /* 335 */, 0xB0B9C1533041AB45L /* 336 */, 0x321958BA470A59BDL /* 337 */, 0x852DB00B5F46C393L /* 338 */, 0x91209B2BD336B0E5L /* 339 */, 0x6E604F7D659EF19FL /* 340 */, 0xB99A8AE2782CCB24L /* 341 */, 0xCCF52AB6C814C4C7L /* 342 */, 0x4727D9AFBE11727BL /* 343 */, 0x7E950D0C0121B34DL /* 344 */, 0x756F435670AD471FL /* 345 */, 0xF5ADD442615A6849L /* 346 */, 0x4E87E09980B9957AL /* 347 */, 0x2ACFA1DF50AEE355L /* 348 */, 0xD898263AFD2FD556L /* 349 */, 0xC8F4924DD80C8FD6L /* 350 */, 0xCF99CA3D754A173AL /* 351 */, 0xFE477BACAF91BF3CL /* 352 */, 0xED5371F6D690C12DL /* 353 */, 0x831A5C285E687094L /* 354 */, 0xC5D3C90A3708A0A4L /* 355 */, 0x0F7F903717D06580L /* 356 */, 0x19F9BB13B8FDF27FL /* 357 */, 0xB1BD6F1B4D502843L /* 358 */, 0x1C761BA38FFF4012L /* 359 */, 0x0D1530C4E2E21F3BL /* 360 */, 0x8943CE69A7372C8AL /* 361 */, 0xE5184E11FEB5CE66L /* 362 */, 0x618BDB80BD736621L /* 363 */, 0x7D29BAD68B574D0BL /* 364 */, 0x81BB613E25E6FE5BL /* 365 */, 0x071C9C10BC07913FL /* 366 */, 0xC7BEEB7909AC2D97L /* 367 */, 0xC3E58D353BC5D757L /* 368 */, 0xEB017892F38F61E8L /* 369 */, 0xD4EFFB9C9B1CC21AL /* 370 */, 0x99727D26F494F7ABL /* 371 */, 0xA3E063A2956B3E03L /* 372 */, 0x9D4A8B9A4AA09C30L /* 373 */, 0x3F6AB7D500090FB4L /* 374 */, 0x9CC0F2A057268AC0L /* 375 */, 0x3DEE9D2DEDBF42D1L /* 376 */, 0x330F49C87960A972L /* 377 */, 0xC6B2720287421B41L /* 378 */, 0x0AC59EC07C00369CL /* 379 */, 0xEF4EAC49CB353425L /* 380 */, 0xF450244EEF0129D8L /* 381 */, 0x8ACC46E5CAF4DEB6L /* 382 */, 0x2FFEAB63989263F7L /* 383 */, 0x8F7CB9FE5D7A4578L /* 384 */, 0x5BD8F7644E634635L /* 385 */, 0x427A7315BF2DC900L /* 386 */, 0x17D0C4AA2125261CL /* 387 */, 0x3992486C93518E50L /* 388 */, 0xB4CBFEE0A2D7D4C3L /* 389 */, 0x7C75D6202C5DDD8DL /* 390 */, 0xDBC295D8E35B6C61L /* 391 */, 0x60B369D302032B19L /* 392 */, 0xCE42685FDCE44132L /* 393 */, 0x06F3DDB9DDF65610L /* 394 */, 0x8EA4D21DB5E148F0L /* 395 */, 0x20B0FCE62FCD496FL /* 396 */, 0x2C1B912358B0EE31L /* 397 */, 0xB28317B818F5A308L /* 398 */, 0xA89C1E189CA6D2CFL /* 399 */, 0x0C6B18576AAADBC8L /* 400 */, 0xB65DEAA91299FAE3L /* 401 */, 0xFB2B794B7F1027E7L /* 402 */, 0x04E4317F443B5BEBL /* 403 */, 0x4B852D325939D0A6L /* 404 */, 0xD5AE6BEEFB207FFCL /* 405 */, 0x309682B281C7D374L /* 406 */, 0xBAE309A194C3B475L /* 407 */, 0x8CC3F97B13B49F05L /* 408 */, 0x98A9422FF8293967L /* 409 */, 0x244B16B01076FF7CL /* 410 */, 0xF8BF571C663D67EEL /* 411 */, 0x1F0D6758EEE30DA1L /* 412 */, 0xC9B611D97ADEB9B7L /* 413 */, 0xB7AFD5887B6C57A2L /* 414 */, 0x6290AE846B984FE1L /* 415 */, 0x94DF4CDEACC1A5FDL /* 416 */, 0x058A5BD1C5483AFFL /* 417 */, 0x63166CC142BA3C37L /* 418 */, 0x8DB8526EB2F76F40L /* 419 */, 0xE10880036F0D6D4EL /* 420 */, 0x9E0523C9971D311DL /* 421 */, 0x45EC2824CC7CD691L /* 422 */, 0x575B8359E62382C9L /* 423 */, 0xFA9E400DC4889995L /* 424 */, 0xD1823ECB45721568L /* 425 */, 0xDAFD983B8206082FL /* 426 */, 0xAA7D29082386A8CBL /* 427 */, 0x269FCD4403B87588L /* 428 */, 0x1B91F5F728BDD1E0L /* 429 */, 0xE4669F39040201F6L /* 430 */, 0x7A1D7C218CF04ADEL /* 431 */, 0x65623C29D79CE5CEL /* 432 */, 0x2368449096C00BB1L /* 433 */, 0xAB9BF1879DA503BAL /* 434 */, 0xBC23ECB1A458058EL /* 435 */, 0x9A58DF01BB401ECCL /* 436 */, 0xA070E868A85F143DL /* 437 */, 0x4FF188307DF2239EL /* 438 */, 0x14D565B41A641183L /* 439 */, 0xEE13337452701602L /* 440 */, 0x950E3DCF3F285E09L /* 441 */, 0x59930254B9C80953L /* 442 */, 0x3BF299408930DA6DL /* 443 */, 0xA955943F53691387L /* 444 */, 0xA15EDECAA9CB8784L /* 445 */, 0x29142127352BE9A0L /* 446 */, 0x76F0371FFF4E7AFBL /* 447 */, 0x0239F450274F2228L /* 448 */, 0xBB073AF01D5E868BL /* 449 */, 0xBFC80571C10E96C1L /* 450 */, 0xD267088568222E23L /* 451 */, 0x9671A3D48E80B5B0L /* 452 */, 0x55B5D38AE193BB81L /* 453 */, 0x693AE2D0A18B04B8L /* 454 */, 0x5C48B4ECADD5335FL /* 455 */, 0xFD743B194916A1CAL /* 456 */, 0x2577018134BE98C4L /* 457 */, 0xE77987E83C54A4ADL /* 458 */, 0x28E11014DA33E1B9L /* 459 */, 0x270CC59E226AA213L /* 460 */, 0x71495F756D1A5F60L /* 461 */, 0x9BE853FB60AFEF77L /* 462 */, 0xADC786A7F7443DBFL /* 463 */, 0x0904456173B29A82L /* 464 */, 0x58BC7A66C232BD5EL /* 465 */, 0xF306558C673AC8B2L /* 466 */, 0x41F639C6B6C9772AL /* 467 */, 0x216DEFE99FDA35DAL /* 468 */, 0x11640CC71C7BE615L /* 469 */, 0x93C43694565C5527L /* 470 */, 0xEA038E6246777839L /* 471 */, 0xF9ABF3CE5A3E2469L /* 472 */, 0x741E768D0FD312D2L /* 473 */, 0x0144B883CED652C6L /* 474 */, 0xC20B5A5BA33F8552L /* 475 */, 0x1AE69633C3435A9DL /* 476 */, 0x97A28CA4088CFDECL /* 477 */, 0x8824A43C1E96F420L /* 478 */, 0x37612FA66EEEA746L /* 479 */, 0x6B4CB165F9CF0E5AL /* 480 */, 0x43AA1C06A0ABFB4AL /* 481 */, 0x7F4DC26FF162796BL /* 482 */, 0x6CBACC8E54ED9B0FL /* 483 */, 0xA6B7FFEFD2BB253EL /* 484 */, 0x2E25BC95B0A29D4FL /* 485 */, 0x86D6A58BDEF1388CL /* 486 */, 0xDED74AC576B6F054L /* 487 */, 0x8030BDBC2B45805DL /* 488 */, 0x3C81AF70E94D9289L /* 489 */, 0x3EFF6DDA9E3100DBL /* 490 */, 0xB38DC39FDFCC8847L /* 491 */, 0x123885528D17B87EL /* 492 */, 0xF2DA0ED240B1B642L /* 493 */, 0x44CEFADCD54BF9A9L /* 494 */, 0x1312200E433C7EE6L /* 495 */, 0x9FFCC84F3A78C748L /* 496 */, 0xF0CD1F72248576BBL /* 497 */, 0xEC6974053638CFE4L /* 498 */, 0x2BA7B67C0CEC4E4CL /* 499 */, 0xAC2F4DF3E5CE32EDL /* 500 */, 0xCB33D14326EA4C11L /* 501 */, 0xA4E9044CC77E58BCL /* 502 */, 0x5F513293D934FCEFL /* 503 */, 0x5DC9645506E55444L /* 504 */, 0x50DE418F317DE40AL /* 505 */, 0x388CB31A69DDE259L /* 506 */, 0x2DB4A83455820A86L /* 507 */, 0x9010A91E84711AE9L /* 508 */, 0x4DF7F0B7B1498371L /* 509 */, 0xD62A2EABC0977179L /* 510 */, 0x22FAC097AA8D5C0EL /* 511 */, }; private static final long[] t3 = { 0xF49FCC2FF1DAF39BL /* 512 */, 0x487FD5C66FF29281L /* 513 */, 0xE8A30667FCDCA83FL /* 514 */, 0x2C9B4BE3D2FCCE63L /* 515 */, 0xDA3FF74B93FBBBC2L /* 516 */, 0x2FA165D2FE70BA66L /* 517 */, 0xA103E279970E93D4L /* 518 */, 0xBECDEC77B0E45E71L /* 519 */, 0xCFB41E723985E497L /* 520 */, 0xB70AAA025EF75017L /* 521 */, 0xD42309F03840B8E0L /* 522 */, 0x8EFC1AD035898579L /* 523 */, 0x96C6920BE2B2ABC5L /* 524 */, 0x66AF4163375A9172L /* 525 */, 0x2174ABDCCA7127FBL /* 526 */, 0xB33CCEA64A72FF41L /* 527 */, 0xF04A4933083066A5L /* 528 */, 0x8D970ACDD7289AF5L /* 529 */, 0x8F96E8E031C8C25EL /* 530 */, 0xF3FEC02276875D47L /* 531 */, 0xEC7BF310056190DDL /* 532 */, 0xF5ADB0AEBB0F1491L /* 533 */, 0x9B50F8850FD58892L /* 534 */, 0x4975488358B74DE8L /* 535 */, 0xA3354FF691531C61L /* 536 */, 0x0702BBE481D2C6EEL /* 537 */, 0x89FB24057DEDED98L /* 538 */, 0xAC3075138596E902L /* 539 */, 0x1D2D3580172772EDL /* 540 */, 0xEB738FC28E6BC30DL /* 541 */, 0x5854EF8F63044326L /* 542 */, 0x9E5C52325ADD3BBEL /* 543 */, 0x90AA53CF325C4623L /* 544 */, 0xC1D24D51349DD067L /* 545 */, 0x2051CFEEA69EA624L /* 546 */, 0x13220F0A862E7E4FL /* 547 */, 0xCE39399404E04864L /* 548 */, 0xD9C42CA47086FCB7L /* 549 */, 0x685AD2238A03E7CCL /* 550 */, 0x066484B2AB2FF1DBL /* 551 */, 0xFE9D5D70EFBF79ECL /* 552 */, 0x5B13B9DD9C481854L /* 553 */, 0x15F0D475ED1509ADL /* 554 */, 0x0BEBCD060EC79851L /* 555 */, 0xD58C6791183AB7F8L /* 556 */, 0xD1187C5052F3EEE4L /* 557 */, 0xC95D1192E54E82FFL /* 558 */, 0x86EEA14CB9AC6CA2L /* 559 */, 0x3485BEB153677D5DL /* 560 */, 0xDD191D781F8C492AL /* 561 */, 0xF60866BAA784EBF9L /* 562 */, 0x518F643BA2D08C74L /* 563 */, 0x8852E956E1087C22L /* 564 */, 0xA768CB8DC410AE8DL /* 565 */, 0x38047726BFEC8E1AL /* 566 */, 0xA67738B4CD3B45AAL /* 567 */, 0xAD16691CEC0DDE19L /* 568 */, 0xC6D4319380462E07L /* 569 */, 0xC5A5876D0BA61938L /* 570 */, 0x16B9FA1FA58FD840L /* 571 */, 0x188AB1173CA74F18L /* 572 */, 0xABDA2F98C99C021FL /* 573 */, 0x3E0580AB134AE816L /* 574 */, 0x5F3B05B773645ABBL /* 575 */, 0x2501A2BE5575F2F6L /* 576 */, 0x1B2F74004E7E8BA9L /* 577 */, 0x1CD7580371E8D953L /* 578 */, 0x7F6ED89562764E30L /* 579 */, 0xB15926FF596F003DL /* 580 */, 0x9F65293DA8C5D6B9L /* 581 */, 0x6ECEF04DD690F84CL /* 582 */, 0x4782275FFF33AF88L /* 583 */, 0xE41433083F820801L /* 584 */, 0xFD0DFE409A1AF9B5L /* 585 */, 0x4325A3342CDB396BL /* 586 */, 0x8AE77E62B301B252L /* 587 */, 0xC36F9E9F6655615AL /* 588 */, 0x85455A2D92D32C09L /* 589 */, 0xF2C7DEA949477485L /* 590 */, 0x63CFB4C133A39EBAL /* 591 */, 0x83B040CC6EBC5462L /* 592 */, 0x3B9454C8FDB326B0L /* 593 */, 0x56F56A9E87FFD78CL /* 594 */, 0x2DC2940D99F42BC6L /* 595 */, 0x98F7DF096B096E2DL /* 596 */, 0x19A6E01E3AD852BFL /* 597 */, 0x42A99CCBDBD4B40BL /* 598 */, 0xA59998AF45E9C559L /* 599 */, 0x366295E807D93186L /* 600 */, 0x6B48181BFAA1F773L /* 601 */, 0x1FEC57E2157A0A1DL /* 602 */, 0x4667446AF6201AD5L /* 603 */, 0xE615EBCACFB0F075L /* 604 */, 0xB8F31F4F68290778L /* 605 */, 0x22713ED6CE22D11EL /* 606 */, 0x3057C1A72EC3C93BL /* 607 */, 0xCB46ACC37C3F1F2FL /* 608 */, 0xDBB893FD02AAF50EL /* 609 */, 0x331FD92E600B9FCFL /* 610 */, 0xA498F96148EA3AD6L /* 611 */, 0xA8D8426E8B6A83EAL /* 612 */, 0xA089B274B7735CDCL /* 613 */, 0x87F6B3731E524A11L /* 614 */, 0x118808E5CBC96749L /* 615 */, 0x9906E4C7B19BD394L /* 616 */, 0xAFED7F7E9B24A20CL /* 617 */, 0x6509EADEEB3644A7L /* 618 */, 0x6C1EF1D3E8EF0EDEL /* 619 */, 0xB9C97D43E9798FB4L /* 620 */, 0xA2F2D784740C28A3L /* 621 */, 0x7B8496476197566FL /* 622 */, 0x7A5BE3E6B65F069DL /* 623 */, 0xF96330ED78BE6F10L /* 624 */, 0xEEE60DE77A076A15L /* 625 */, 0x2B4BEE4AA08B9BD0L /* 626 */, 0x6A56A63EC7B8894EL /* 627 */, 0x02121359BA34FEF4L /* 628 */, 0x4CBF99F8283703FCL /* 629 */, 0x398071350CAF30C8L /* 630 */, 0xD0A77A89F017687AL /* 631 */, 0xF1C1A9EB9E423569L /* 632 */, 0x8C7976282DEE8199L /* 633 */, 0x5D1737A5DD1F7ABDL /* 634 */, 0x4F53433C09A9FA80L /* 635 */, 0xFA8B0C53DF7CA1D9L /* 636 */, 0x3FD9DCBC886CCB77L /* 637 */, 0xC040917CA91B4720L /* 638 */, 0x7DD00142F9D1DCDFL /* 639 */, 0x8476FC1D4F387B58L /* 640 */, 0x23F8E7C5F3316503L /* 641 */, 0x032A2244E7E37339L /* 642 */, 0x5C87A5D750F5A74BL /* 643 */, 0x082B4CC43698992EL /* 644 */, 0xDF917BECB858F63CL /* 645 */, 0x3270B8FC5BF86DDAL /* 646 */, 0x10AE72BB29B5DD76L /* 647 */, 0x576AC94E7700362BL /* 648 */, 0x1AD112DAC61EFB8FL /* 649 */, 0x691BC30EC5FAA427L /* 650 */, 0xFF246311CC327143L /* 651 */, 0x3142368E30E53206L /* 652 */, 0x71380E31E02CA396L /* 653 */, 0x958D5C960AAD76F1L /* 654 */, 0xF8D6F430C16DA536L /* 655 */, 0xC8FFD13F1BE7E1D2L /* 656 */, 0x7578AE66004DDBE1L /* 657 */, 0x05833F01067BE646L /* 658 */, 0xBB34B5AD3BFE586DL /* 659 */, 0x095F34C9A12B97F0L /* 660 */, 0x247AB64525D60CA8L /* 661 */, 0xDCDBC6F3017477D1L /* 662 */, 0x4A2E14D4DECAD24DL /* 663 */, 0xBDB5E6D9BE0A1EEBL /* 664 */, 0x2A7E70F7794301ABL /* 665 */, 0xDEF42D8A270540FDL /* 666 */, 0x01078EC0A34C22C1L /* 667 */, 0xE5DE511AF4C16387L /* 668 */, 0x7EBB3A52BD9A330AL /* 669 */, 0x77697857AA7D6435L /* 670 */, 0x004E831603AE4C32L /* 671 */, 0xE7A21020AD78E312L /* 672 */, 0x9D41A70C6AB420F2L /* 673 */, 0x28E06C18EA1141E6L /* 674 */, 0xD2B28CBD984F6B28L /* 675 */, 0x26B75F6C446E9D83L /* 676 */, 0xBA47568C4D418D7FL /* 677 */, 0xD80BADBFE6183D8EL /* 678 */, 0x0E206D7F5F166044L /* 679 */, 0xE258A43911CBCA3EL /* 680 */, 0x723A1746B21DC0BCL /* 681 */, 0xC7CAA854F5D7CDD3L /* 682 */, 0x7CAC32883D261D9CL /* 683 */, 0x7690C26423BA942CL /* 684 */, 0x17E55524478042B8L /* 685 */, 0xE0BE477656A2389FL /* 686 */, 0x4D289B5E67AB2DA0L /* 687 */, 0x44862B9C8FBBFD31L /* 688 */, 0xB47CC8049D141365L /* 689 */, 0x822C1B362B91C793L /* 690 */, 0x4EB14655FB13DFD8L /* 691 */, 0x1ECBBA0714E2A97BL /* 692 */, 0x6143459D5CDE5F14L /* 693 */, 0x53A8FBF1D5F0AC89L /* 694 */, 0x97EA04D81C5E5B00L /* 695 */, 0x622181A8D4FDB3F3L /* 696 */, 0xE9BCD341572A1208L /* 697 */, 0x1411258643CCE58AL /* 698 */, 0x9144C5FEA4C6E0A4L /* 699 */, 0x0D33D06565CF620FL /* 700 */, 0x54A48D489F219CA1L /* 701 */, 0xC43E5EAC6D63C821L /* 702 */, 0xA9728B3A72770DAFL /* 703 */, 0xD7934E7B20DF87EFL /* 704 */, 0xE35503B61A3E86E5L /* 705 */, 0xCAE321FBC819D504L /* 706 */, 0x129A50B3AC60BFA6L /* 707 */, 0xCD5E68EA7E9FB6C3L /* 708 */, 0xB01C90199483B1C7L /* 709 */, 0x3DE93CD5C295376CL /* 710 */, 0xAED52EDF2AB9AD13L /* 711 */, 0x2E60F512C0A07884L /* 712 */, 0xBC3D86A3E36210C9L /* 713 */, 0x35269D9B163951CEL /* 714 */, 0x0C7D6E2AD0CDB5FAL /* 715 */, 0x59E86297D87F5733L /* 716 */, 0x298EF221898DB0E7L /* 717 */, 0x55000029D1A5AA7EL /* 718 */, 0x8BC08AE1B5061B45L /* 719 */, 0xC2C31C2B6C92703AL /* 720 */, 0x94CC596BAF25EF42L /* 721 */, 0x0A1D73DB22540456L /* 722 */, 0x04B6A0F9D9C4179AL /* 723 */, 0xEFFDAFA2AE3D3C60L /* 724 */, 0xF7C8075BB49496C4L /* 725 */, 0x9CC5C7141D1CD4E3L /* 726 */, 0x78BD1638218E5534L /* 727 */, 0xB2F11568F850246AL /* 728 */, 0xEDFABCFA9502BC29L /* 729 */, 0x796CE5F2DA23051BL /* 730 */, 0xAAE128B0DC93537CL /* 731 */, 0x3A493DA0EE4B29AEL /* 732 */, 0xB5DF6B2C416895D7L /* 733 */, 0xFCABBD25122D7F37L /* 734 */, 0x70810B58105DC4B1L /* 735 */, 0xE10FDD37F7882A90L /* 736 */, 0x524DCAB5518A3F5CL /* 737 */, 0x3C9E85878451255BL /* 738 */, 0x4029828119BD34E2L /* 739 */, 0x74A05B6F5D3CECCBL /* 740 */, 0xB610021542E13ECAL /* 741 */, 0x0FF979D12F59E2ACL /* 742 */, 0x6037DA27E4F9CC50L /* 743 */, 0x5E92975A0DF1847DL /* 744 */, 0xD66DE190D3E623FEL /* 745 */, 0x5032D6B87B568048L /* 746 */, 0x9A36B7CE8235216EL /* 747 */, 0x80272A7A24F64B4AL /* 748 */, 0x93EFED8B8C6916F7L /* 749 */, 0x37DDBFF44CCE1555L /* 750 */, 0x4B95DB5D4B99BD25L /* 751 */, 0x92D3FDA169812FC0L /* 752 */, 0xFB1A4A9A90660BB6L /* 753 */, 0x730C196946A4B9B2L /* 754 */, 0x81E289AA7F49DA68L /* 755 */, 0x64669A0F83B1A05FL /* 756 */, 0x27B3FF7D9644F48BL /* 757 */, 0xCC6B615C8DB675B3L /* 758 */, 0x674F20B9BCEBBE95L /* 759 */, 0x6F31238275655982L /* 760 */, 0x5AE488713E45CF05L /* 761 */, 0xBF619F9954C21157L /* 762 */, 0xEABAC46040A8EAE9L /* 763 */, 0x454C6FE9F2C0C1CDL /* 764 */, 0x419CF6496412691CL /* 765 */, 0xD3DC3BEF265B0F70L /* 766 */, 0x6D0E60F5C3578A9EL /* 767 */, }; private static final long[] t4 = { 0x5B0E608526323C55L /* 768 */, 0x1A46C1A9FA1B59F5L /* 769 */, 0xA9E245A17C4C8FFAL /* 770 */, 0x65CA5159DB2955D7L /* 771 */, 0x05DB0A76CE35AFC2L /* 772 */, 0x81EAC77EA9113D45L /* 773 */, 0x528EF88AB6AC0A0DL /* 774 */, 0xA09EA253597BE3FFL /* 775 */, 0x430DDFB3AC48CD56L /* 776 */, 0xC4B3A67AF45CE46FL /* 777 */, 0x4ECECFD8FBE2D05EL /* 778 */, 0x3EF56F10B39935F0L /* 779 */, 0x0B22D6829CD619C6L /* 780 */, 0x17FD460A74DF2069L /* 781 */, 0x6CF8CC8E8510ED40L /* 782 */, 0xD6C824BF3A6ECAA7L /* 783 */, 0x61243D581A817049L /* 784 */, 0x048BACB6BBC163A2L /* 785 */, 0xD9A38AC27D44CC32L /* 786 */, 0x7FDDFF5BAAF410ABL /* 787 */, 0xAD6D495AA804824BL /* 788 */, 0xE1A6A74F2D8C9F94L /* 789 */, 0xD4F7851235DEE8E3L /* 790 */, 0xFD4B7F886540D893L /* 791 */, 0x247C20042AA4BFDAL /* 792 */, 0x096EA1C517D1327CL /* 793 */, 0xD56966B4361A6685L /* 794 */, 0x277DA5C31221057DL /* 795 */, 0x94D59893A43ACFF7L /* 796 */, 0x64F0C51CCDC02281L /* 797 */, 0x3D33BCC4FF6189DBL /* 798 */, 0xE005CB184CE66AF1L /* 799 */, 0xFF5CCD1D1DB99BEAL /* 800 */, 0xB0B854A7FE42980FL /* 801 */, 0x7BD46A6A718D4B9FL /* 802 */, 0xD10FA8CC22A5FD8CL /* 803 */, 0xD31484952BE4BD31L /* 804 */, 0xC7FA975FCB243847L /* 805 */, 0x4886ED1E5846C407L /* 806 */, 0x28CDDB791EB70B04L /* 807 */, 0xC2B00BE2F573417FL /* 808 */, 0x5C9590452180F877L /* 809 */, 0x7A6BDDFFF370EB00L /* 810 */, 0xCE509E38D6D9D6A4L /* 811 */, 0xEBEB0F00647FA702L /* 812 */, 0x1DCC06CF76606F06L /* 813 */, 0xE4D9F28BA286FF0AL /* 814 */, 0xD85A305DC918C262L /* 815 */, 0x475B1D8732225F54L /* 816 */, 0x2D4FB51668CCB5FEL /* 817 */, 0xA679B9D9D72BBA20L /* 818 */, 0x53841C0D912D43A5L /* 819 */, 0x3B7EAA48BF12A4E8L /* 820 */, 0x781E0E47F22F1DDFL /* 821 */, 0xEFF20CE60AB50973L /* 822 */, 0x20D261D19DFFB742L /* 823 */, 0x16A12B03062A2E39L /* 824 */, 0x1960EB2239650495L /* 825 */, 0x251C16FED50EB8B8L /* 826 */, 0x9AC0C330F826016EL /* 827 */, 0xED152665953E7671L /* 828 */, 0x02D63194A6369570L /* 829 */, 0x5074F08394B1C987L /* 830 */, 0x70BA598C90B25CE1L /* 831 */, 0x794A15810B9742F6L /* 832 */, 0x0D5925E9FCAF8C6CL /* 833 */, 0x3067716CD868744EL /* 834 */, 0x910AB077E8D7731BL /* 835 */, 0x6A61BBDB5AC42F61L /* 836 */, 0x93513EFBF0851567L /* 837 */, 0xF494724B9E83E9D5L /* 838 */, 0xE887E1985C09648DL /* 839 */, 0x34B1D3C675370CFDL /* 840 */, 0xDC35E433BC0D255DL /* 841 */, 0xD0AAB84234131BE0L /* 842 */, 0x08042A50B48B7EAFL /* 843 */, 0x9997C4EE44A3AB35L /* 844 */, 0x829A7B49201799D0L /* 845 */, 0x263B8307B7C54441L /* 846 */, 0x752F95F4FD6A6CA6L /* 847 */, 0x927217402C08C6E5L /* 848 */, 0x2A8AB754A795D9EEL /* 849 */, 0xA442F7552F72943DL /* 850 */, 0x2C31334E19781208L /* 851 */, 0x4FA98D7CEAEE6291L /* 852 */, 0x55C3862F665DB309L /* 853 */, 0xBD0610175D53B1F3L /* 854 */, 0x46FE6CB840413F27L /* 855 */, 0x3FE03792DF0CFA59L /* 856 */, 0xCFE700372EB85E8FL /* 857 */, 0xA7BE29E7ADBCE118L /* 858 */, 0xE544EE5CDE8431DDL /* 859 */, 0x8A781B1B41F1873EL /* 860 */, 0xA5C94C78A0D2F0E7L /* 861 */, 0x39412E2877B60728L /* 862 */, 0xA1265EF3AFC9A62CL /* 863 */, 0xBCC2770C6A2506C5L /* 864 */, 0x3AB66DD5DCE1CE12L /* 865 */, 0xE65499D04A675B37L /* 866 */, 0x7D8F523481BFD216L /* 867 */, 0x0F6F64FCEC15F389L /* 868 */, 0x74EFBE618B5B13C8L /* 869 */, 0xACDC82B714273E1DL /* 870 */, 0xDD40BFE003199D17L /* 871 */, 0x37E99257E7E061F8L /* 872 */, 0xFA52626904775AAAL /* 873 */, 0x8BBBF63A463D56F9L /* 874 */, 0xF0013F1543A26E64L /* 875 */, 0xA8307E9F879EC898L /* 876 */, 0xCC4C27A4150177CCL /* 877 */, 0x1B432F2CCA1D3348L /* 878 */, 0xDE1D1F8F9F6FA013L /* 879 */, 0x606602A047A7DDD6L /* 880 */, 0xD237AB64CC1CB2C7L /* 881 */, 0x9B938E7225FCD1D3L /* 882 */, 0xEC4E03708E0FF476L /* 883 */, 0xFEB2FBDA3D03C12DL /* 884 */, 0xAE0BCED2EE43889AL /* 885 */, 0x22CB8923EBFB4F43L /* 886 */, 0x69360D013CF7396DL /* 887 */, 0x855E3602D2D4E022L /* 888 */, 0x073805BAD01F784CL /* 889 */, 0x33E17A133852F546L /* 890 */, 0xDF4874058AC7B638L /* 891 */, 0xBA92B29C678AA14AL /* 892 */, 0x0CE89FC76CFAADCDL /* 893 */, 0x5F9D4E0908339E34L /* 894 */, 0xF1AFE9291F5923B9L /* 895 */, 0x6E3480F60F4A265FL /* 896 */, 0xEEBF3A2AB29B841CL /* 897 */, 0xE21938A88F91B4ADL /* 898 */, 0x57DFEFF845C6D3C3L /* 899 */, 0x2F006B0BF62CAAF2L /* 900 */, 0x62F479EF6F75EE78L /* 901 */, 0x11A55AD41C8916A9L /* 902 */, 0xF229D29084FED453L /* 903 */, 0x42F1C27B16B000E6L /* 904 */, 0x2B1F76749823C074L /* 905 */, 0x4B76ECA3C2745360L /* 906 */, 0x8C98F463B91691BDL /* 907 */, 0x14BCC93CF1ADE66AL /* 908 */, 0x8885213E6D458397L /* 909 */, 0x8E177DF0274D4711L /* 910 */, 0xB49B73B5503F2951L /* 911 */, 0x10168168C3F96B6BL /* 912 */, 0x0E3D963B63CAB0AEL /* 913 */, 0x8DFC4B5655A1DB14L /* 914 */, 0xF789F1356E14DE5CL /* 915 */, 0x683E68AF4E51DAC1L /* 916 */, 0xC9A84F9D8D4B0FD9L /* 917 */, 0x3691E03F52A0F9D1L /* 918 */, 0x5ED86E46E1878E80L /* 919 */, 0x3C711A0E99D07150L /* 920 */, 0x5A0865B20C4E9310L /* 921 */, 0x56FBFC1FE4F0682EL /* 922 */, 0xEA8D5DE3105EDF9BL /* 923 */, 0x71ABFDB12379187AL /* 924 */, 0x2EB99DE1BEE77B9CL /* 925 */, 0x21ECC0EA33CF4523L /* 926 */, 0x59A4D7521805C7A1L /* 927 */, 0x3896F5EB56AE7C72L /* 928 */, 0xAA638F3DB18F75DCL /* 929 */, 0x9F39358DABE9808EL /* 930 */, 0xB7DEFA91C00B72ACL /* 931 */, 0x6B5541FD62492D92L /* 932 */, 0x6DC6DEE8F92E4D5BL /* 933 */, 0x353F57ABC4BEEA7EL /* 934 */, 0x735769D6DA5690CEL /* 935 */, 0x0A234AA642391484L /* 936 */, 0xF6F9508028F80D9DL /* 937 */, 0xB8E319A27AB3F215L /* 938 */, 0x31AD9C1151341A4DL /* 939 */, 0x773C22A57BEF5805L /* 940 */, 0x45C7561A07968633L /* 941 */, 0xF913DA9E249DBE36L /* 942 */, 0xDA652D9B78A64C68L /* 943 */, 0x4C27A97F3BC334EFL /* 944 */, 0x76621220E66B17F4L /* 945 */, 0x967743899ACD7D0BL /* 946 */, 0xF3EE5BCAE0ED6782L /* 947 */, 0x409F753600C879FCL /* 948 */, 0x06D09A39B5926DB6L /* 949 */, 0x6F83AEB0317AC588L /* 950 */, 0x01E6CA4A86381F21L /* 951 */, 0x66FF3462D19F3025L /* 952 */, 0x72207C24DDFD3BFBL /* 953 */, 0x4AF6B6D3E2ECE2EBL /* 954 */, 0x9C994DBEC7EA08DEL /* 955 */, 0x49ACE597B09A8BC4L /* 956 */, 0xB38C4766CF0797BAL /* 957 */, 0x131B9373C57C2A75L /* 958 */, 0xB1822CCE61931E58L /* 959 */, 0x9D7555B909BA1C0CL /* 960 */, 0x127FAFDD937D11D2L /* 961 */, 0x29DA3BADC66D92E4L /* 962 */, 0xA2C1D57154C2ECBCL /* 963 */, 0x58C5134D82F6FE24L /* 964 */, 0x1C3AE3515B62274FL /* 965 */, 0xE907C82E01CB8126L /* 966 */, 0xF8ED091913E37FCBL /* 967 */, 0x3249D8F9C80046C9L /* 968 */, 0x80CF9BEDE388FB63L /* 969 */, 0x1881539A116CF19EL /* 970 */, 0x5103F3F76BD52457L /* 971 */, 0x15B7E6F5AE47F7A8L /* 972 */, 0xDBD7C6DED47E9CCFL /* 973 */, 0x44E55C410228BB1AL /* 974 */, 0xB647D4255EDB4E99L /* 975 */, 0x5D11882BB8AAFC30L /* 976 */, 0xF5098BBB29D3212AL /* 977 */, 0x8FB5EA14E90296B3L /* 978 */, 0x677B942157DD025AL /* 979 */, 0xFB58E7C0A390ACB5L /* 980 */, 0x89D3674C83BD4A01L /* 981 */, 0x9E2DA4DF4BF3B93BL /* 982 */, 0xFCC41E328CAB4829L /* 983 */, 0x03F38C96BA582C52L /* 984 */, 0xCAD1BDBD7FD85DB2L /* 985 */, 0xBBB442C16082AE83L /* 986 */, 0xB95FE86BA5DA9AB0L /* 987 */, 0xB22E04673771A93FL /* 988 */, 0x845358C9493152D8L /* 989 */, 0xBE2A488697B4541EL /* 990 */, 0x95A2DC2DD38E6966L /* 991 */, 0xC02C11AC923C852BL /* 992 */, 0x2388B1990DF2A87BL /* 993 */, 0x7C8008FA1B4F37BEL /* 994 */, 0x1F70D0C84D54E503L /* 995 */, 0x5490ADEC7ECE57D4L /* 996 */, 0x002B3C27D9063A3AL /* 997 */, 0x7EAEA3848030A2BFL /* 998 */, 0xC602326DED2003C0L /* 999 */, 0x83A7287D69A94086L /* 1000 */, 0xC57A5FCB30F57A8AL /* 1001 */, 0xB56844E479EBE779L /* 1002 */, 0xA373B40F05DCBCE9L /* 1003 */, 0xD71A786E88570EE2L /* 1004 */, 0x879CBACDBDE8F6A0L /* 1005 */, 0x976AD1BCC164A32FL /* 1006 */, 0xAB21E25E9666D78BL /* 1007 */, 0x901063AAE5E5C33CL /* 1008 */, 0x9818B34448698D90L /* 1009 */, 0xE36487AE3E1E8ABBL /* 1010 */, 0xAFBDF931893BDCB4L /* 1011 */, 0x6345A0DC5FBBD519L /* 1012 */, 0x8628FE269B9465CAL /* 1013 */, 0x1E5D01603F9C51ECL /* 1014 */, 0x4DE44006A15049B7L /* 1015 */, 0xBF6C70E5F776CBB1L /* 1016 */, 0x411218F2EF552BEDL /* 1017 */, 0xCB0C0708705A36A3L /* 1018 */, 0xE74D14754F986044L /* 1019 */, 0xCD56D9430EA8280EL /* 1020 */, 0xC12591D7535F5065L /* 1021 */, 0xC83223F1720AEF96L /* 1022 */, 0xC3A0396F7363A51FL /* 1023 */ }; private static final int DIGEST_LENGTH = 24; // // registers // private long a, b, c; private long byteCount; // // buffers // private byte[] buf = new byte[8]; private int bOff = 0; private long[] x = new long[8]; private int xOff = 0; /** * Standard constructor */ public TigerDigest() { reset(); } /** * Copy constructor. This will copy the state of the provided * message digest. */ public TigerDigest(TigerDigest t) { a = t.a; b = t.b; c = t.c; System.arraycopy(t.x, 0, x, 0, t.x.length); xOff = t.xOff; System.arraycopy(t.buf, 0, buf, 0, t.buf.length); bOff = t.bOff; byteCount = t.byteCount; } public String getAlgorithmName() { return "Tiger"; } public int getDigestSize() { return DIGEST_LENGTH; } private void processWord( byte[] b, int off) { x[xOff++] = ((long)(b[off + 7] & 0xff) << 56) | ((long)(b[off + 6] & 0xff) << 48) | ((long)(b[off + 5] & 0xff) << 40) | ((long)(b[off + 4] & 0xff) << 32) | ((long)(b[off + 3] & 0xff) << 24) | ((long)(b[off + 2] & 0xff) << 16) | ((long)(b[off + 1] & 0xff) << 8) | ((b[off + 0] & 0xff)); if (xOff == x.length) { processBlock(); } bOff = 0; } public void update( byte in) { buf[bOff++] = in; if (bOff == buf.length) { processWord(buf, 0); } byteCount++; } public void update( byte[] in, int inOff, int len) { // // fill the current word // while ((bOff != 0) && (len > 0)) { update(in[inOff]); inOff++; len--; } // // process whole words. // while (len > 8) { processWord(in, inOff); inOff += 8; len -= 8; byteCount += 8; } // // load in the remainder. // while (len > 0) { update(in[inOff]); inOff++; len--; } } private void roundABC( long x, long mul) { c ^= x ; a -= t1[(int)c & 0xff] ^ t2[(int)(c >> 16) & 0xff] ^ t3[(int)(c >> 32) & 0xff] ^ t4[(int)(c >> 48) & 0xff]; b += t4[(int)(c >> 8) & 0xff] ^ t3[(int)(c >> 24) & 0xff] ^ t2[(int)(c >> 40) & 0xff] ^ t1[(int)(c >> 56) & 0xff]; b *= mul; } private void roundBCA( long x, long mul) { a ^= x ; b -= t1[(int)a & 0xff] ^ t2[(int)(a >> 16) & 0xff] ^ t3[(int)(a >> 32) & 0xff] ^ t4[(int)(a >> 48) & 0xff]; c += t4[(int)(a >> 8) & 0xff] ^ t3[(int)(a >> 24) & 0xff] ^ t2[(int)(a >> 40) & 0xff] ^ t1[(int)(a >> 56) & 0xff]; c *= mul; } private void roundCAB( long x, long mul) { b ^= x ; c -= t1[(int)b & 0xff] ^ t2[(int)(b >> 16) & 0xff] ^ t3[(int)(b >> 32) & 0xff] ^ t4[(int)(b >> 48) & 0xff]; a += t4[(int)(b >> 8) & 0xff] ^ t3[(int)(b >> 24) & 0xff] ^ t2[(int)(b >> 40) & 0xff] ^ t1[(int)(b >> 56) & 0xff]; a *= mul; } private void keySchedule() { x[0] -= x[7] ^ 0xA5A5A5A5A5A5A5A5L; x[1] ^= x[0]; x[2] += x[1]; x[3] -= x[2] ^ ((~x[1]) << 19); x[4] ^= x[3]; x[5] += x[4]; x[6] -= x[5] ^ ((~x[4]) >>> 23); x[7] ^= x[6]; x[0] += x[7]; x[1] -= x[0] ^ ((~x[7]) << 19); x[2] ^= x[1]; x[3] += x[2]; x[4] -= x[3] ^ ((~x[2]) >>> 23); x[5] ^= x[4]; x[6] += x[5]; x[7] -= x[6] ^ 0x0123456789ABCDEFL; } private void processBlock() { // // save abc // long aa = a; long bb = b; long cc = c; // // rounds and schedule // roundABC(x[0], 5); roundBCA(x[1], 5); roundCAB(x[2], 5); roundABC(x[3], 5); roundBCA(x[4], 5); roundCAB(x[5], 5); roundABC(x[6], 5); roundBCA(x[7], 5); keySchedule(); roundCAB(x[0], 7); roundABC(x[1], 7); roundBCA(x[2], 7); roundCAB(x[3], 7); roundABC(x[4], 7); roundBCA(x[5], 7); roundCAB(x[6], 7); roundABC(x[7], 7); keySchedule(); roundBCA(x[0], 9); roundCAB(x[1], 9); roundABC(x[2], 9); roundBCA(x[3], 9); roundCAB(x[4], 9); roundABC(x[5], 9); roundBCA(x[6], 9); roundCAB(x[7], 9); // // feed forward // a ^= aa; b -= bb; c += cc; // // clear the x buffer // xOff = 0; for (int i = 0; i != x.length; i++) { x[i] = 0; } } public void unpackWord( long r, byte[] out, int outOff) { out[outOff + 7] = (byte)(r >> 56); out[outOff + 6] = (byte)(r >> 48); out[outOff + 5] = (byte)(r >> 40); out[outOff + 4] = (byte)(r >> 32); out[outOff + 3] = (byte)(r >> 24); out[outOff + 2] = (byte)(r >> 16); out[outOff + 1] = (byte)(r >> 8); out[outOff] = (byte)r; } private void processLength( long bitLength) { x[7] = bitLength; } private void finish() { long bitLength = (byteCount << 3); update((byte)0x01); while (bOff != 0) { update((byte)0); } processLength(bitLength); processBlock(); } public int doFinal( byte[] out, int outOff) { finish(); unpackWord(a, out, outOff); unpackWord(b, out, outOff + 8); unpackWord(c, out, outOff + 16); reset(); return DIGEST_LENGTH; } /** * reset the chaining variables */ public void reset() { a = 0x0123456789ABCDEFL; b = 0xFEDCBA9876543210L; c = 0xF096A5B4C3B2E187L; xOff = 0; for (int i = 0; i != x.length; i++) { x[i] = 0; } bOff = 0; for (int i = 0; i != buf.length; i++) { buf[i] = 0; } byteCount = 0; } } azureus-4.3.0.6/org/bouncycastle/crypto/digests/GeneralDigest.java0000644000175000017500000000450510061400652024460 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; import org.bouncycastle.crypto.Digest; /** * base implementation of MD4 family style digest as outlined in * "Handbook of Applied Cryptography", pages 344 - 347. */ public abstract class GeneralDigest implements Digest { private byte[] xBuf; private int xBufOff; private long byteCount; /** * Standard constructor */ protected GeneralDigest() { xBuf = new byte[4]; xBufOff = 0; } /** * Copy constructor. We are using copy constructors in place * of the Object.clone() interface as this interface is not * supported by J2ME. */ protected GeneralDigest(GeneralDigest t) { xBuf = new byte[t.xBuf.length]; System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); xBufOff = t.xBufOff; byteCount = t.byteCount; } public void update( byte in) { xBuf[xBufOff++] = in; if (xBufOff == xBuf.length) { processWord(xBuf, 0); xBufOff = 0; } byteCount++; } public void update( byte[] in, int inOff, int len) { // // fill the current word // while ((xBufOff != 0) && (len > 0)) { update(in[inOff]); inOff++; len--; } // // process whole words. // while (len > xBuf.length) { processWord(in, inOff); inOff += xBuf.length; len -= xBuf.length; byteCount += xBuf.length; } // // load in the remainder. // while (len > 0) { update(in[inOff]); inOff++; len--; } } public void finish() { long bitLength = (byteCount << 3); // // add the pad bytes. // update((byte)128); while (xBufOff != 0) { update((byte)0); } processLength(bitLength); processBlock(); } public void reset() { byteCount = 0; xBufOff = 0; for ( int i = 0; i < xBuf.length; i++ ) { xBuf[i] = 0; } } protected abstract void processWord(byte[] in, int inOff); protected abstract void processLength(long bitLength); protected abstract void processBlock(); } azureus-4.3.0.6/org/bouncycastle/crypto/digests/RIPEMD320Digest.java0000644000175000017500000003577310061400652024323 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; /** * implementation of RIPEMD 320. *

      * Note: this implementation offers the same level of security * as RIPEMD 160. */ public class RIPEMD320Digest extends GeneralDigest { private static final int DIGEST_LENGTH = 40; private int H0, H1, H2, H3, H4, H5, H6, H7, H8, H9; // IV's private int[] X = new int[16]; private int xOff; /** * Standard constructor */ public RIPEMD320Digest() { reset(); } /** * Copy constructor. This will copy the state of the provided * message digest. */ public RIPEMD320Digest(RIPEMD320Digest t) { super(t); H0 = t.H0; H1 = t.H1; H2 = t.H2; H3 = t.H3; H4 = t.H4; H5 = t.H5; H6 = t.H6; H7 = t.H7; H8 = t.H8; H9 = t.H9; System.arraycopy(t.X, 0, X, 0, t.X.length); xOff = t.xOff; } public String getAlgorithmName() { return "RIPEMD320"; } public int getDigestSize() { return DIGEST_LENGTH; } protected void processWord( byte[] in, int inOff) { X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8) | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); if (xOff == 16) { processBlock(); } } protected void processLength( long bitLength) { if (xOff > 14) { processBlock(); } X[14] = (int)(bitLength & 0xffffffff); X[15] = (int)(bitLength >>> 32); } private void unpackWord( int word, byte[] out, int outOff) { out[outOff] = (byte)word; out[outOff + 1] = (byte)(word >>> 8); out[outOff + 2] = (byte)(word >>> 16); out[outOff + 3] = (byte)(word >>> 24); } public int doFinal( byte[] out, int outOff) { finish(); unpackWord(H0, out, outOff); unpackWord(H1, out, outOff + 4); unpackWord(H2, out, outOff + 8); unpackWord(H3, out, outOff + 12); unpackWord(H4, out, outOff + 16); unpackWord(H5, out, outOff + 20); unpackWord(H6, out, outOff + 24); unpackWord(H7, out, outOff + 28); unpackWord(H8, out, outOff + 32); unpackWord(H9, out, outOff + 36); reset(); return DIGEST_LENGTH; } /** * reset the chaining variables to the IV values. */ public void reset() { super.reset(); H0 = 0x67452301; H1 = 0xefcdab89; H2 = 0x98badcfe; H3 = 0x10325476; H4 = 0xc3d2e1f0; H5 = 0x76543210; H6 = 0xFEDCBA98; H7 = 0x89ABCDEF; H8 = 0x01234567; H9 = 0x3C2D1E0F; xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } /* * rotate int x left n bits. */ private final int RL( int x, int n) { return (x << n) | (x >>> (32 - n)); } /* * f1,f2,f3,f4,f5 are the basic RIPEMD160 functions. */ /* * rounds 0-15 */ private final int f1( int x, int y, int z) { return x ^ y ^ z; } /* * rounds 16-31 */ private final int f2( int x, int y, int z) { return (x & y) | (~x & z); } /* * rounds 32-47 */ private final int f3( int x, int y, int z) { return (x | ~y) ^ z; } /* * rounds 48-63 */ private final int f4( int x, int y, int z) { return (x & z) | (y & ~z); } /* * rounds 64-79 */ private final int f5( int x, int y, int z) { return x ^ (y | ~z); } protected void processBlock() { int a, aa; int b, bb; int c, cc; int d, dd; int e, ee; int t; a = H0; b = H1; c = H2; d = H3; e = H4; aa = H5; bb = H6; cc = H7; dd = H8; ee = H9; // // Rounds 1 - 16 // // left a = RL(a + f1(b,c,d) + X[ 0], 11) + e; c = RL(c, 10); e = RL(e + f1(a,b,c) + X[ 1], 14) + d; b = RL(b, 10); d = RL(d + f1(e,a,b) + X[ 2], 15) + c; a = RL(a, 10); c = RL(c + f1(d,e,a) + X[ 3], 12) + b; e = RL(e, 10); b = RL(b + f1(c,d,e) + X[ 4], 5) + a; d = RL(d, 10); a = RL(a + f1(b,c,d) + X[ 5], 8) + e; c = RL(c, 10); e = RL(e + f1(a,b,c) + X[ 6], 7) + d; b = RL(b, 10); d = RL(d + f1(e,a,b) + X[ 7], 9) + c; a = RL(a, 10); c = RL(c + f1(d,e,a) + X[ 8], 11) + b; e = RL(e, 10); b = RL(b + f1(c,d,e) + X[ 9], 13) + a; d = RL(d, 10); a = RL(a + f1(b,c,d) + X[10], 14) + e; c = RL(c, 10); e = RL(e + f1(a,b,c) + X[11], 15) + d; b = RL(b, 10); d = RL(d + f1(e,a,b) + X[12], 6) + c; a = RL(a, 10); c = RL(c + f1(d,e,a) + X[13], 7) + b; e = RL(e, 10); b = RL(b + f1(c,d,e) + X[14], 9) + a; d = RL(d, 10); a = RL(a + f1(b,c,d) + X[15], 8) + e; c = RL(c, 10); // right aa = RL(aa + f5(bb,cc,dd) + X[ 5] + 0x50a28be6, 8) + ee; cc = RL(cc, 10); ee = RL(ee + f5(aa,bb,cc) + X[14] + 0x50a28be6, 9) + dd; bb = RL(bb, 10); dd = RL(dd + f5(ee,aa,bb) + X[ 7] + 0x50a28be6, 9) + cc; aa = RL(aa, 10); cc = RL(cc + f5(dd,ee,aa) + X[ 0] + 0x50a28be6, 11) + bb; ee = RL(ee, 10); bb = RL(bb + f5(cc,dd,ee) + X[ 9] + 0x50a28be6, 13) + aa; dd = RL(dd, 10); aa = RL(aa + f5(bb,cc,dd) + X[ 2] + 0x50a28be6, 15) + ee; cc = RL(cc, 10); ee = RL(ee + f5(aa,bb,cc) + X[11] + 0x50a28be6, 15) + dd; bb = RL(bb, 10); dd = RL(dd + f5(ee,aa,bb) + X[ 4] + 0x50a28be6, 5) + cc; aa = RL(aa, 10); cc = RL(cc + f5(dd,ee,aa) + X[13] + 0x50a28be6, 7) + bb; ee = RL(ee, 10); bb = RL(bb + f5(cc,dd,ee) + X[ 6] + 0x50a28be6, 7) + aa; dd = RL(dd, 10); aa = RL(aa + f5(bb,cc,dd) + X[15] + 0x50a28be6, 8) + ee; cc = RL(cc, 10); ee = RL(ee + f5(aa,bb,cc) + X[ 8] + 0x50a28be6, 11) + dd; bb = RL(bb, 10); dd = RL(dd + f5(ee,aa,bb) + X[ 1] + 0x50a28be6, 14) + cc; aa = RL(aa, 10); cc = RL(cc + f5(dd,ee,aa) + X[10] + 0x50a28be6, 14) + bb; ee = RL(ee, 10); bb = RL(bb + f5(cc,dd,ee) + X[ 3] + 0x50a28be6, 12) + aa; dd = RL(dd, 10); aa = RL(aa + f5(bb,cc,dd) + X[12] + 0x50a28be6, 6) + ee; cc = RL(cc, 10); t = a; a = aa; aa = t; // // Rounds 16-31 // // left e = RL(e + f2(a,b,c) + X[ 7] + 0x5a827999, 7) + d; b = RL(b, 10); d = RL(d + f2(e,a,b) + X[ 4] + 0x5a827999, 6) + c; a = RL(a, 10); c = RL(c + f2(d,e,a) + X[13] + 0x5a827999, 8) + b; e = RL(e, 10); b = RL(b + f2(c,d,e) + X[ 1] + 0x5a827999, 13) + a; d = RL(d, 10); a = RL(a + f2(b,c,d) + X[10] + 0x5a827999, 11) + e; c = RL(c, 10); e = RL(e + f2(a,b,c) + X[ 6] + 0x5a827999, 9) + d; b = RL(b, 10); d = RL(d + f2(e,a,b) + X[15] + 0x5a827999, 7) + c; a = RL(a, 10); c = RL(c + f2(d,e,a) + X[ 3] + 0x5a827999, 15) + b; e = RL(e, 10); b = RL(b + f2(c,d,e) + X[12] + 0x5a827999, 7) + a; d = RL(d, 10); a = RL(a + f2(b,c,d) + X[ 0] + 0x5a827999, 12) + e; c = RL(c, 10); e = RL(e + f2(a,b,c) + X[ 9] + 0x5a827999, 15) + d; b = RL(b, 10); d = RL(d + f2(e,a,b) + X[ 5] + 0x5a827999, 9) + c; a = RL(a, 10); c = RL(c + f2(d,e,a) + X[ 2] + 0x5a827999, 11) + b; e = RL(e, 10); b = RL(b + f2(c,d,e) + X[14] + 0x5a827999, 7) + a; d = RL(d, 10); a = RL(a + f2(b,c,d) + X[11] + 0x5a827999, 13) + e; c = RL(c, 10); e = RL(e + f2(a,b,c) + X[ 8] + 0x5a827999, 12) + d; b = RL(b, 10); // right ee = RL(ee + f4(aa,bb,cc) + X[ 6] + 0x5c4dd124, 9) + dd; bb = RL(bb, 10); dd = RL(dd + f4(ee,aa,bb) + X[11] + 0x5c4dd124, 13) + cc; aa = RL(aa, 10); cc = RL(cc + f4(dd,ee,aa) + X[ 3] + 0x5c4dd124, 15) + bb; ee = RL(ee, 10); bb = RL(bb + f4(cc,dd,ee) + X[ 7] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10); aa = RL(aa + f4(bb,cc,dd) + X[ 0] + 0x5c4dd124, 12) + ee; cc = RL(cc, 10); ee = RL(ee + f4(aa,bb,cc) + X[13] + 0x5c4dd124, 8) + dd; bb = RL(bb, 10); dd = RL(dd + f4(ee,aa,bb) + X[ 5] + 0x5c4dd124, 9) + cc; aa = RL(aa, 10); cc = RL(cc + f4(dd,ee,aa) + X[10] + 0x5c4dd124, 11) + bb; ee = RL(ee, 10); bb = RL(bb + f4(cc,dd,ee) + X[14] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10); aa = RL(aa + f4(bb,cc,dd) + X[15] + 0x5c4dd124, 7) + ee; cc = RL(cc, 10); ee = RL(ee + f4(aa,bb,cc) + X[ 8] + 0x5c4dd124, 12) + dd; bb = RL(bb, 10); dd = RL(dd + f4(ee,aa,bb) + X[12] + 0x5c4dd124, 7) + cc; aa = RL(aa, 10); cc = RL(cc + f4(dd,ee,aa) + X[ 4] + 0x5c4dd124, 6) + bb; ee = RL(ee, 10); bb = RL(bb + f4(cc,dd,ee) + X[ 9] + 0x5c4dd124, 15) + aa; dd = RL(dd, 10); aa = RL(aa + f4(bb,cc,dd) + X[ 1] + 0x5c4dd124, 13) + ee; cc = RL(cc, 10); ee = RL(ee + f4(aa,bb,cc) + X[ 2] + 0x5c4dd124, 11) + dd; bb = RL(bb, 10); t = b; b = bb; bb = t; // // Rounds 32-47 // // left d = RL(d + f3(e,a,b) + X[ 3] + 0x6ed9eba1, 11) + c; a = RL(a, 10); c = RL(c + f3(d,e,a) + X[10] + 0x6ed9eba1, 13) + b; e = RL(e, 10); b = RL(b + f3(c,d,e) + X[14] + 0x6ed9eba1, 6) + a; d = RL(d, 10); a = RL(a + f3(b,c,d) + X[ 4] + 0x6ed9eba1, 7) + e; c = RL(c, 10); e = RL(e + f3(a,b,c) + X[ 9] + 0x6ed9eba1, 14) + d; b = RL(b, 10); d = RL(d + f3(e,a,b) + X[15] + 0x6ed9eba1, 9) + c; a = RL(a, 10); c = RL(c + f3(d,e,a) + X[ 8] + 0x6ed9eba1, 13) + b; e = RL(e, 10); b = RL(b + f3(c,d,e) + X[ 1] + 0x6ed9eba1, 15) + a; d = RL(d, 10); a = RL(a + f3(b,c,d) + X[ 2] + 0x6ed9eba1, 14) + e; c = RL(c, 10); e = RL(e + f3(a,b,c) + X[ 7] + 0x6ed9eba1, 8) + d; b = RL(b, 10); d = RL(d + f3(e,a,b) + X[ 0] + 0x6ed9eba1, 13) + c; a = RL(a, 10); c = RL(c + f3(d,e,a) + X[ 6] + 0x6ed9eba1, 6) + b; e = RL(e, 10); b = RL(b + f3(c,d,e) + X[13] + 0x6ed9eba1, 5) + a; d = RL(d, 10); a = RL(a + f3(b,c,d) + X[11] + 0x6ed9eba1, 12) + e; c = RL(c, 10); e = RL(e + f3(a,b,c) + X[ 5] + 0x6ed9eba1, 7) + d; b = RL(b, 10); d = RL(d + f3(e,a,b) + X[12] + 0x6ed9eba1, 5) + c; a = RL(a, 10); // right dd = RL(dd + f3(ee,aa,bb) + X[15] + 0x6d703ef3, 9) + cc; aa = RL(aa, 10); cc = RL(cc + f3(dd,ee,aa) + X[ 5] + 0x6d703ef3, 7) + bb; ee = RL(ee, 10); bb = RL(bb + f3(cc,dd,ee) + X[ 1] + 0x6d703ef3, 15) + aa; dd = RL(dd, 10); aa = RL(aa + f3(bb,cc,dd) + X[ 3] + 0x6d703ef3, 11) + ee; cc = RL(cc, 10); ee = RL(ee + f3(aa,bb,cc) + X[ 7] + 0x6d703ef3, 8) + dd; bb = RL(bb, 10); dd = RL(dd + f3(ee,aa,bb) + X[14] + 0x6d703ef3, 6) + cc; aa = RL(aa, 10); cc = RL(cc + f3(dd,ee,aa) + X[ 6] + 0x6d703ef3, 6) + bb; ee = RL(ee, 10); bb = RL(bb + f3(cc,dd,ee) + X[ 9] + 0x6d703ef3, 14) + aa; dd = RL(dd, 10); aa = RL(aa + f3(bb,cc,dd) + X[11] + 0x6d703ef3, 12) + ee; cc = RL(cc, 10); ee = RL(ee + f3(aa,bb,cc) + X[ 8] + 0x6d703ef3, 13) + dd; bb = RL(bb, 10); dd = RL(dd + f3(ee,aa,bb) + X[12] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10); cc = RL(cc + f3(dd,ee,aa) + X[ 2] + 0x6d703ef3, 14) + bb; ee = RL(ee, 10); bb = RL(bb + f3(cc,dd,ee) + X[10] + 0x6d703ef3, 13) + aa; dd = RL(dd, 10); aa = RL(aa + f3(bb,cc,dd) + X[ 0] + 0x6d703ef3, 13) + ee; cc = RL(cc, 10); ee = RL(ee + f3(aa,bb,cc) + X[ 4] + 0x6d703ef3, 7) + dd; bb = RL(bb, 10); dd = RL(dd + f3(ee,aa,bb) + X[13] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10); t = c; c = cc; cc = t; // // Rounds 48-63 // // left c = RL(c + f4(d,e,a) + X[ 1] + 0x8f1bbcdc, 11) + b; e = RL(e, 10); b = RL(b + f4(c,d,e) + X[ 9] + 0x8f1bbcdc, 12) + a; d = RL(d, 10); a = RL(a + f4(b,c,d) + X[11] + 0x8f1bbcdc, 14) + e; c = RL(c, 10); e = RL(e + f4(a,b,c) + X[10] + 0x8f1bbcdc, 15) + d; b = RL(b, 10); d = RL(d + f4(e,a,b) + X[ 0] + 0x8f1bbcdc, 14) + c; a = RL(a, 10); c = RL(c + f4(d,e,a) + X[ 8] + 0x8f1bbcdc, 15) + b; e = RL(e, 10); b = RL(b + f4(c,d,e) + X[12] + 0x8f1bbcdc, 9) + a; d = RL(d, 10); a = RL(a + f4(b,c,d) + X[ 4] + 0x8f1bbcdc, 8) + e; c = RL(c, 10); e = RL(e + f4(a,b,c) + X[13] + 0x8f1bbcdc, 9) + d; b = RL(b, 10); d = RL(d + f4(e,a,b) + X[ 3] + 0x8f1bbcdc, 14) + c; a = RL(a, 10); c = RL(c + f4(d,e,a) + X[ 7] + 0x8f1bbcdc, 5) + b; e = RL(e, 10); b = RL(b + f4(c,d,e) + X[15] + 0x8f1bbcdc, 6) + a; d = RL(d, 10); a = RL(a + f4(b,c,d) + X[14] + 0x8f1bbcdc, 8) + e; c = RL(c, 10); e = RL(e + f4(a,b,c) + X[ 5] + 0x8f1bbcdc, 6) + d; b = RL(b, 10); d = RL(d + f4(e,a,b) + X[ 6] + 0x8f1bbcdc, 5) + c; a = RL(a, 10); c = RL(c + f4(d,e,a) + X[ 2] + 0x8f1bbcdc, 12) + b; e = RL(e, 10); // right cc = RL(cc + f2(dd,ee,aa) + X[ 8] + 0x7a6d76e9, 15) + bb; ee = RL(ee, 10); bb = RL(bb + f2(cc,dd,ee) + X[ 6] + 0x7a6d76e9, 5) + aa; dd = RL(dd, 10); aa = RL(aa + f2(bb,cc,dd) + X[ 4] + 0x7a6d76e9, 8) + ee; cc = RL(cc, 10); ee = RL(ee + f2(aa,bb,cc) + X[ 1] + 0x7a6d76e9, 11) + dd; bb = RL(bb, 10); dd = RL(dd + f2(ee,aa,bb) + X[ 3] + 0x7a6d76e9, 14) + cc; aa = RL(aa, 10); cc = RL(cc + f2(dd,ee,aa) + X[11] + 0x7a6d76e9, 14) + bb; ee = RL(ee, 10); bb = RL(bb + f2(cc,dd,ee) + X[15] + 0x7a6d76e9, 6) + aa; dd = RL(dd, 10); aa = RL(aa + f2(bb,cc,dd) + X[ 0] + 0x7a6d76e9, 14) + ee; cc = RL(cc, 10); ee = RL(ee + f2(aa,bb,cc) + X[ 5] + 0x7a6d76e9, 6) + dd; bb = RL(bb, 10); dd = RL(dd + f2(ee,aa,bb) + X[12] + 0x7a6d76e9, 9) + cc; aa = RL(aa, 10); cc = RL(cc + f2(dd,ee,aa) + X[ 2] + 0x7a6d76e9, 12) + bb; ee = RL(ee, 10); bb = RL(bb + f2(cc,dd,ee) + X[13] + 0x7a6d76e9, 9) + aa; dd = RL(dd, 10); aa = RL(aa + f2(bb,cc,dd) + X[ 9] + 0x7a6d76e9, 12) + ee; cc = RL(cc, 10); ee = RL(ee + f2(aa,bb,cc) + X[ 7] + 0x7a6d76e9, 5) + dd; bb = RL(bb, 10); dd = RL(dd + f2(ee,aa,bb) + X[10] + 0x7a6d76e9, 15) + cc; aa = RL(aa, 10); cc = RL(cc + f2(dd,ee,aa) + X[14] + 0x7a6d76e9, 8) + bb; ee = RL(ee, 10); t = d; d = dd; dd = t; // // Rounds 64-79 // // left b = RL(b + f5(c,d,e) + X[ 4] + 0xa953fd4e, 9) + a; d = RL(d, 10); a = RL(a + f5(b,c,d) + X[ 0] + 0xa953fd4e, 15) + e; c = RL(c, 10); e = RL(e + f5(a,b,c) + X[ 5] + 0xa953fd4e, 5) + d; b = RL(b, 10); d = RL(d + f5(e,a,b) + X[ 9] + 0xa953fd4e, 11) + c; a = RL(a, 10); c = RL(c + f5(d,e,a) + X[ 7] + 0xa953fd4e, 6) + b; e = RL(e, 10); b = RL(b + f5(c,d,e) + X[12] + 0xa953fd4e, 8) + a; d = RL(d, 10); a = RL(a + f5(b,c,d) + X[ 2] + 0xa953fd4e, 13) + e; c = RL(c, 10); e = RL(e + f5(a,b,c) + X[10] + 0xa953fd4e, 12) + d; b = RL(b, 10); d = RL(d + f5(e,a,b) + X[14] + 0xa953fd4e, 5) + c; a = RL(a, 10); c = RL(c + f5(d,e,a) + X[ 1] + 0xa953fd4e, 12) + b; e = RL(e, 10); b = RL(b + f5(c,d,e) + X[ 3] + 0xa953fd4e, 13) + a; d = RL(d, 10); a = RL(a + f5(b,c,d) + X[ 8] + 0xa953fd4e, 14) + e; c = RL(c, 10); e = RL(e + f5(a,b,c) + X[11] + 0xa953fd4e, 11) + d; b = RL(b, 10); d = RL(d + f5(e,a,b) + X[ 6] + 0xa953fd4e, 8) + c; a = RL(a, 10); c = RL(c + f5(d,e,a) + X[15] + 0xa953fd4e, 5) + b; e = RL(e, 10); b = RL(b + f5(c,d,e) + X[13] + 0xa953fd4e, 6) + a; d = RL(d, 10); // right bb = RL(bb + f1(cc,dd,ee) + X[12], 8) + aa; dd = RL(dd, 10); aa = RL(aa + f1(bb,cc,dd) + X[15], 5) + ee; cc = RL(cc, 10); ee = RL(ee + f1(aa,bb,cc) + X[10], 12) + dd; bb = RL(bb, 10); dd = RL(dd + f1(ee,aa,bb) + X[ 4], 9) + cc; aa = RL(aa, 10); cc = RL(cc + f1(dd,ee,aa) + X[ 1], 12) + bb; ee = RL(ee, 10); bb = RL(bb + f1(cc,dd,ee) + X[ 5], 5) + aa; dd = RL(dd, 10); aa = RL(aa + f1(bb,cc,dd) + X[ 8], 14) + ee; cc = RL(cc, 10); ee = RL(ee + f1(aa,bb,cc) + X[ 7], 6) + dd; bb = RL(bb, 10); dd = RL(dd + f1(ee,aa,bb) + X[ 6], 8) + cc; aa = RL(aa, 10); cc = RL(cc + f1(dd,ee,aa) + X[ 2], 13) + bb; ee = RL(ee, 10); bb = RL(bb + f1(cc,dd,ee) + X[13], 6) + aa; dd = RL(dd, 10); aa = RL(aa + f1(bb,cc,dd) + X[14], 5) + ee; cc = RL(cc, 10); ee = RL(ee + f1(aa,bb,cc) + X[ 0], 15) + dd; bb = RL(bb, 10); dd = RL(dd + f1(ee,aa,bb) + X[ 3], 13) + cc; aa = RL(aa, 10); cc = RL(cc + f1(dd,ee,aa) + X[ 9], 11) + bb; ee = RL(ee, 10); bb = RL(bb + f1(cc,dd,ee) + X[11], 11) + aa; dd = RL(dd, 10); // // do (e, ee) swap as part of assignment. // H0 += a; H1 += b; H2 += c; H3 += d; H4 += ee; H5 += aa; H6 += bb; H7 += cc; H8 += dd; H9 += e; // // reset the offset and clean out the word buffer. // xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } } azureus-4.3.0.6/org/bouncycastle/crypto/digests/RIPEMD256Digest.java0000644000175000017500000002413510061400652024321 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; /** * implementation of RIPEMD256. *

      * note: this algorithm offers the same level of security as RIPEMD128. */ public class RIPEMD256Digest extends GeneralDigest { private static final int DIGEST_LENGTH = 32; private int H0, H1, H2, H3, H4, H5, H6, H7; // IV's private int[] X = new int[16]; private int xOff; /** * Standard constructor */ public RIPEMD256Digest() { reset(); } /** * Copy constructor. This will copy the state of the provided * message digest. */ public RIPEMD256Digest(RIPEMD256Digest t) { super(t); H0 = t.H0; H1 = t.H1; H2 = t.H2; H3 = t.H3; H4 = t.H4; H5 = t.H5; H6 = t.H6; H7 = t.H7; System.arraycopy(t.X, 0, X, 0, t.X.length); xOff = t.xOff; } public String getAlgorithmName() { return "RIPEMD256"; } public int getDigestSize() { return DIGEST_LENGTH; } protected void processWord( byte[] in, int inOff) { X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8) | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); if (xOff == 16) { processBlock(); } } protected void processLength( long bitLength) { if (xOff > 14) { processBlock(); } X[14] = (int)(bitLength & 0xffffffff); X[15] = (int)(bitLength >>> 32); } private void unpackWord( int word, byte[] out, int outOff) { out[outOff] = (byte)word; out[outOff + 1] = (byte)(word >>> 8); out[outOff + 2] = (byte)(word >>> 16); out[outOff + 3] = (byte)(word >>> 24); } public int doFinal( byte[] out, int outOff) { finish(); unpackWord(H0, out, outOff); unpackWord(H1, out, outOff + 4); unpackWord(H2, out, outOff + 8); unpackWord(H3, out, outOff + 12); unpackWord(H4, out, outOff + 16); unpackWord(H5, out, outOff + 20); unpackWord(H6, out, outOff + 24); unpackWord(H7, out, outOff + 28); reset(); return DIGEST_LENGTH; } /** * reset the chaining variables to the IV values. */ public void reset() { super.reset(); H0 = 0x67452301; H1 = 0xefcdab89; H2 = 0x98badcfe; H3 = 0x10325476; H4 = 0x76543210; H5 = 0xFEDCBA98; H6 = 0x89ABCDEF; H7 = 0x01234567; xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } /* * rotate int x left n bits. */ private final int RL( int x, int n) { return (x << n) | (x >>> (32 - n)); } /* * f1,f2,f3,f4 are the basic RIPEMD128 functions. */ /* * F */ private final int f1( int x, int y, int z) { return x ^ y ^ z; } /* * G */ private final int f2( int x, int y, int z) { return (x & y) | (~x & z); } /* * H */ private final int f3( int x, int y, int z) { return (x | ~y) ^ z; } /* * I */ private final int f4( int x, int y, int z) { return (x & z) | (y & ~z); } private final int F1( int a, int b, int c, int d, int x, int s) { return RL(a + f1(b, c, d) + x, s); } private final int F2( int a, int b, int c, int d, int x, int s) { return RL(a + f2(b, c, d) + x + 0x5a827999, s); } private final int F3( int a, int b, int c, int d, int x, int s) { return RL(a + f3(b, c, d) + x + 0x6ed9eba1, s); } private final int F4( int a, int b, int c, int d, int x, int s) { return RL(a + f4(b, c, d) + x + 0x8f1bbcdc, s); } private final int FF1( int a, int b, int c, int d, int x, int s) { return RL(a + f1(b, c, d) + x, s); } private final int FF2( int a, int b, int c, int d, int x, int s) { return RL(a + f2(b, c, d) + x + 0x6d703ef3, s); } private final int FF3( int a, int b, int c, int d, int x, int s) { return RL(a + f3(b, c, d) + x + 0x5c4dd124, s); } private final int FF4( int a, int b, int c, int d, int x, int s) { return RL(a + f4(b, c, d) + x + 0x50a28be6, s); } protected void processBlock() { int a, aa; int b, bb; int c, cc; int d, dd; int t; a = H0; b = H1; c = H2; d = H3; aa = H4; bb = H5; cc = H6; dd = H7; // // Round 1 // a = F1(a, b, c, d, X[ 0], 11); d = F1(d, a, b, c, X[ 1], 14); c = F1(c, d, a, b, X[ 2], 15); b = F1(b, c, d, a, X[ 3], 12); a = F1(a, b, c, d, X[ 4], 5); d = F1(d, a, b, c, X[ 5], 8); c = F1(c, d, a, b, X[ 6], 7); b = F1(b, c, d, a, X[ 7], 9); a = F1(a, b, c, d, X[ 8], 11); d = F1(d, a, b, c, X[ 9], 13); c = F1(c, d, a, b, X[10], 14); b = F1(b, c, d, a, X[11], 15); a = F1(a, b, c, d, X[12], 6); d = F1(d, a, b, c, X[13], 7); c = F1(c, d, a, b, X[14], 9); b = F1(b, c, d, a, X[15], 8); aa = FF4(aa, bb, cc, dd, X[ 5], 8); dd = FF4(dd, aa, bb, cc, X[14], 9); cc = FF4(cc, dd, aa, bb, X[ 7], 9); bb = FF4(bb, cc, dd, aa, X[ 0], 11); aa = FF4(aa, bb, cc, dd, X[ 9], 13); dd = FF4(dd, aa, bb, cc, X[ 2], 15); cc = FF4(cc, dd, aa, bb, X[11], 15); bb = FF4(bb, cc, dd, aa, X[ 4], 5); aa = FF4(aa, bb, cc, dd, X[13], 7); dd = FF4(dd, aa, bb, cc, X[ 6], 7); cc = FF4(cc, dd, aa, bb, X[15], 8); bb = FF4(bb, cc, dd, aa, X[ 8], 11); aa = FF4(aa, bb, cc, dd, X[ 1], 14); dd = FF4(dd, aa, bb, cc, X[10], 14); cc = FF4(cc, dd, aa, bb, X[ 3], 12); bb = FF4(bb, cc, dd, aa, X[12], 6); t = a; a = aa; aa = t; // // Round 2 // a = F2(a, b, c, d, X[ 7], 7); d = F2(d, a, b, c, X[ 4], 6); c = F2(c, d, a, b, X[13], 8); b = F2(b, c, d, a, X[ 1], 13); a = F2(a, b, c, d, X[10], 11); d = F2(d, a, b, c, X[ 6], 9); c = F2(c, d, a, b, X[15], 7); b = F2(b, c, d, a, X[ 3], 15); a = F2(a, b, c, d, X[12], 7); d = F2(d, a, b, c, X[ 0], 12); c = F2(c, d, a, b, X[ 9], 15); b = F2(b, c, d, a, X[ 5], 9); a = F2(a, b, c, d, X[ 2], 11); d = F2(d, a, b, c, X[14], 7); c = F2(c, d, a, b, X[11], 13); b = F2(b, c, d, a, X[ 8], 12); aa = FF3(aa, bb, cc, dd, X[ 6], 9); dd = FF3(dd, aa, bb, cc, X[ 11], 13); cc = FF3(cc, dd, aa, bb, X[3], 15); bb = FF3(bb, cc, dd, aa, X[ 7], 7); aa = FF3(aa, bb, cc, dd, X[0], 12); dd = FF3(dd, aa, bb, cc, X[13], 8); cc = FF3(cc, dd, aa, bb, X[5], 9); bb = FF3(bb, cc, dd, aa, X[10], 11); aa = FF3(aa, bb, cc, dd, X[14], 7); dd = FF3(dd, aa, bb, cc, X[15], 7); cc = FF3(cc, dd, aa, bb, X[ 8], 12); bb = FF3(bb, cc, dd, aa, X[12], 7); aa = FF3(aa, bb, cc, dd, X[ 4], 6); dd = FF3(dd, aa, bb, cc, X[ 9], 15); cc = FF3(cc, dd, aa, bb, X[ 1], 13); bb = FF3(bb, cc, dd, aa, X[ 2], 11); t = b; b = bb; bb = t; // // Round 3 // a = F3(a, b, c, d, X[ 3], 11); d = F3(d, a, b, c, X[10], 13); c = F3(c, d, a, b, X[14], 6); b = F3(b, c, d, a, X[ 4], 7); a = F3(a, b, c, d, X[ 9], 14); d = F3(d, a, b, c, X[15], 9); c = F3(c, d, a, b, X[ 8], 13); b = F3(b, c, d, a, X[ 1], 15); a = F3(a, b, c, d, X[ 2], 14); d = F3(d, a, b, c, X[ 7], 8); c = F3(c, d, a, b, X[ 0], 13); b = F3(b, c, d, a, X[ 6], 6); a = F3(a, b, c, d, X[13], 5); d = F3(d, a, b, c, X[11], 12); c = F3(c, d, a, b, X[ 5], 7); b = F3(b, c, d, a, X[12], 5); aa = FF2(aa, bb, cc, dd, X[ 15], 9); dd = FF2(dd, aa, bb, cc, X[5], 7); cc = FF2(cc, dd, aa, bb, X[1], 15); bb = FF2(bb, cc, dd, aa, X[ 3], 11); aa = FF2(aa, bb, cc, dd, X[ 7], 8); dd = FF2(dd, aa, bb, cc, X[14], 6); cc = FF2(cc, dd, aa, bb, X[ 6], 6); bb = FF2(bb, cc, dd, aa, X[ 9], 14); aa = FF2(aa, bb, cc, dd, X[11], 12); dd = FF2(dd, aa, bb, cc, X[ 8], 13); cc = FF2(cc, dd, aa, bb, X[12], 5); bb = FF2(bb, cc, dd, aa, X[ 2], 14); aa = FF2(aa, bb, cc, dd, X[10], 13); dd = FF2(dd, aa, bb, cc, X[ 0], 13); cc = FF2(cc, dd, aa, bb, X[ 4], 7); bb = FF2(bb, cc, dd, aa, X[13], 5); t = c; c = cc; cc = t; // // Round 4 // a = F4(a, b, c, d, X[ 1], 11); d = F4(d, a, b, c, X[ 9], 12); c = F4(c, d, a, b, X[11], 14); b = F4(b, c, d, a, X[10], 15); a = F4(a, b, c, d, X[ 0], 14); d = F4(d, a, b, c, X[ 8], 15); c = F4(c, d, a, b, X[12], 9); b = F4(b, c, d, a, X[ 4], 8); a = F4(a, b, c, d, X[13], 9); d = F4(d, a, b, c, X[ 3], 14); c = F4(c, d, a, b, X[ 7], 5); b = F4(b, c, d, a, X[15], 6); a = F4(a, b, c, d, X[14], 8); d = F4(d, a, b, c, X[ 5], 6); c = F4(c, d, a, b, X[ 6], 5); b = F4(b, c, d, a, X[ 2], 12); aa = FF1(aa, bb, cc, dd, X[ 8], 15); dd = FF1(dd, aa, bb, cc, X[ 6], 5); cc = FF1(cc, dd, aa, bb, X[ 4], 8); bb = FF1(bb, cc, dd, aa, X[ 1], 11); aa = FF1(aa, bb, cc, dd, X[ 3], 14); dd = FF1(dd, aa, bb, cc, X[11], 14); cc = FF1(cc, dd, aa, bb, X[15], 6); bb = FF1(bb, cc, dd, aa, X[ 0], 14); aa = FF1(aa, bb, cc, dd, X[ 5], 6); dd = FF1(dd, aa, bb, cc, X[12], 9); cc = FF1(cc, dd, aa, bb, X[ 2], 12); bb = FF1(bb, cc, dd, aa, X[13], 9); aa = FF1(aa, bb, cc, dd, X[ 9], 12); dd = FF1(dd, aa, bb, cc, X[ 7], 5); cc = FF1(cc, dd, aa, bb, X[10], 15); bb = FF1(bb, cc, dd, aa, X[14], 8); t = d; d = dd; dd = t; H0 += a; H1 += b; H2 += c; H3 += d; H4 += aa; H5 += bb; H6 += cc; H7 += dd; // // reset the offset and clean out the word buffer. // xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } } azureus-4.3.0.6/org/bouncycastle/crypto/digests/MD5Digest.java0000644000175000017500000002151410061400652023467 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; /** * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347. */ public class MD5Digest extends GeneralDigest { private static final int DIGEST_LENGTH = 16; private int H1, H2, H3, H4; // IV's private int[] X = new int[16]; private int xOff; /** * Standard constructor */ public MD5Digest() { reset(); } /** * Copy constructor. This will copy the state of the provided * message digest. */ public MD5Digest(MD5Digest t) { super(t); H1 = t.H1; H2 = t.H2; H3 = t.H3; H4 = t.H4; System.arraycopy(t.X, 0, X, 0, t.X.length); xOff = t.xOff; } public String getAlgorithmName() { return "MD5"; } public int getDigestSize() { return DIGEST_LENGTH; } protected void processWord( byte[] in, int inOff) { X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8) | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); if (xOff == 16) { processBlock(); } } protected void processLength( long bitLength) { if (xOff > 14) { processBlock(); } X[14] = (int)(bitLength & 0xffffffff); X[15] = (int)(bitLength >>> 32); } private void unpackWord( int word, byte[] out, int outOff) { out[outOff] = (byte)word; out[outOff + 1] = (byte)(word >>> 8); out[outOff + 2] = (byte)(word >>> 16); out[outOff + 3] = (byte)(word >>> 24); } public int doFinal( byte[] out, int outOff) { finish(); unpackWord(H1, out, outOff); unpackWord(H2, out, outOff + 4); unpackWord(H3, out, outOff + 8); unpackWord(H4, out, outOff + 12); reset(); return DIGEST_LENGTH; } /** * reset the chaining variables to the IV values. */ public void reset() { super.reset(); H1 = 0x67452301; H2 = 0xefcdab89; H3 = 0x98badcfe; H4 = 0x10325476; xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } // // round 1 left rotates // private static final int S11 = 7; private static final int S12 = 12; private static final int S13 = 17; private static final int S14 = 22; // // round 2 left rotates // private static final int S21 = 5; private static final int S22 = 9; private static final int S23 = 14; private static final int S24 = 20; // // round 3 left rotates // private static final int S31 = 4; private static final int S32 = 11; private static final int S33 = 16; private static final int S34 = 23; // // round 4 left rotates // private static final int S41 = 6; private static final int S42 = 10; private static final int S43 = 15; private static final int S44 = 21; /* * rotate int x left n bits. */ private int rotateLeft( int x, int n) { return (x << n) | (x >>> (32 - n)); } /* * F, G, H and I are the basic MD5 functions. */ private int F( int u, int v, int w) { return (u & v) | (~u & w); } private int G( int u, int v, int w) { return (u & w) | (v & ~w); } private int H( int u, int v, int w) { return u ^ v ^ w; } private int K( int u, int v, int w) { return v ^ (u | ~w); } protected void processBlock() { int a = H1; int b = H2; int c = H3; int d = H4; // // Round 1 - F cycle, 16 times. // a = rotateLeft((a + F(b, c, d) + X[ 0] + 0xd76aa478), S11) + b; d = rotateLeft((d + F(a, b, c) + X[ 1] + 0xe8c7b756), S12) + a; c = rotateLeft((c + F(d, a, b) + X[ 2] + 0x242070db), S13) + d; b = rotateLeft((b + F(c, d, a) + X[ 3] + 0xc1bdceee), S14) + c; a = rotateLeft((a + F(b, c, d) + X[ 4] + 0xf57c0faf), S11) + b; d = rotateLeft((d + F(a, b, c) + X[ 5] + 0x4787c62a), S12) + a; c = rotateLeft((c + F(d, a, b) + X[ 6] + 0xa8304613), S13) + d; b = rotateLeft((b + F(c, d, a) + X[ 7] + 0xfd469501), S14) + c; a = rotateLeft((a + F(b, c, d) + X[ 8] + 0x698098d8), S11) + b; d = rotateLeft((d + F(a, b, c) + X[ 9] + 0x8b44f7af), S12) + a; c = rotateLeft((c + F(d, a, b) + X[10] + 0xffff5bb1), S13) + d; b = rotateLeft((b + F(c, d, a) + X[11] + 0x895cd7be), S14) + c; a = rotateLeft((a + F(b, c, d) + X[12] + 0x6b901122), S11) + b; d = rotateLeft((d + F(a, b, c) + X[13] + 0xfd987193), S12) + a; c = rotateLeft((c + F(d, a, b) + X[14] + 0xa679438e), S13) + d; b = rotateLeft((b + F(c, d, a) + X[15] + 0x49b40821), S14) + c; // // Round 2 - G cycle, 16 times. // a = rotateLeft((a + G(b, c, d) + X[ 1] + 0xf61e2562), S21) + b; d = rotateLeft((d + G(a, b, c) + X[ 6] + 0xc040b340), S22) + a; c = rotateLeft((c + G(d, a, b) + X[11] + 0x265e5a51), S23) + d; b = rotateLeft((b + G(c, d, a) + X[ 0] + 0xe9b6c7aa), S24) + c; a = rotateLeft((a + G(b, c, d) + X[ 5] + 0xd62f105d), S21) + b; d = rotateLeft((d + G(a, b, c) + X[10] + 0x02441453), S22) + a; c = rotateLeft((c + G(d, a, b) + X[15] + 0xd8a1e681), S23) + d; b = rotateLeft((b + G(c, d, a) + X[ 4] + 0xe7d3fbc8), S24) + c; a = rotateLeft((a + G(b, c, d) + X[ 9] + 0x21e1cde6), S21) + b; d = rotateLeft((d + G(a, b, c) + X[14] + 0xc33707d6), S22) + a; c = rotateLeft((c + G(d, a, b) + X[ 3] + 0xf4d50d87), S23) + d; b = rotateLeft((b + G(c, d, a) + X[ 8] + 0x455a14ed), S24) + c; a = rotateLeft((a + G(b, c, d) + X[13] + 0xa9e3e905), S21) + b; d = rotateLeft((d + G(a, b, c) + X[ 2] + 0xfcefa3f8), S22) + a; c = rotateLeft((c + G(d, a, b) + X[ 7] + 0x676f02d9), S23) + d; b = rotateLeft((b + G(c, d, a) + X[12] + 0x8d2a4c8a), S24) + c; // // Round 3 - H cycle, 16 times. // a = rotateLeft((a + H(b, c, d) + X[ 5] + 0xfffa3942), S31) + b; d = rotateLeft((d + H(a, b, c) + X[ 8] + 0x8771f681), S32) + a; c = rotateLeft((c + H(d, a, b) + X[11] + 0x6d9d6122), S33) + d; b = rotateLeft((b + H(c, d, a) + X[14] + 0xfde5380c), S34) + c; a = rotateLeft((a + H(b, c, d) + X[ 1] + 0xa4beea44), S31) + b; d = rotateLeft((d + H(a, b, c) + X[ 4] + 0x4bdecfa9), S32) + a; c = rotateLeft((c + H(d, a, b) + X[ 7] + 0xf6bb4b60), S33) + d; b = rotateLeft((b + H(c, d, a) + X[10] + 0xbebfbc70), S34) + c; a = rotateLeft((a + H(b, c, d) + X[13] + 0x289b7ec6), S31) + b; d = rotateLeft((d + H(a, b, c) + X[ 0] + 0xeaa127fa), S32) + a; c = rotateLeft((c + H(d, a, b) + X[ 3] + 0xd4ef3085), S33) + d; b = rotateLeft((b + H(c, d, a) + X[ 6] + 0x04881d05), S34) + c; a = rotateLeft((a + H(b, c, d) + X[ 9] + 0xd9d4d039), S31) + b; d = rotateLeft((d + H(a, b, c) + X[12] + 0xe6db99e5), S32) + a; c = rotateLeft((c + H(d, a, b) + X[15] + 0x1fa27cf8), S33) + d; b = rotateLeft((b + H(c, d, a) + X[ 2] + 0xc4ac5665), S34) + c; // // Round 4 - K cycle, 16 times. // a = rotateLeft((a + K(b, c, d) + X[ 0] + 0xf4292244), S41) + b; d = rotateLeft((d + K(a, b, c) + X[ 7] + 0x432aff97), S42) + a; c = rotateLeft((c + K(d, a, b) + X[14] + 0xab9423a7), S43) + d; b = rotateLeft((b + K(c, d, a) + X[ 5] + 0xfc93a039), S44) + c; a = rotateLeft((a + K(b, c, d) + X[12] + 0x655b59c3), S41) + b; d = rotateLeft((d + K(a, b, c) + X[ 3] + 0x8f0ccc92), S42) + a; c = rotateLeft((c + K(d, a, b) + X[10] + 0xffeff47d), S43) + d; b = rotateLeft((b + K(c, d, a) + X[ 1] + 0x85845dd1), S44) + c; a = rotateLeft((a + K(b, c, d) + X[ 8] + 0x6fa87e4f), S41) + b; d = rotateLeft((d + K(a, b, c) + X[15] + 0xfe2ce6e0), S42) + a; c = rotateLeft((c + K(d, a, b) + X[ 6] + 0xa3014314), S43) + d; b = rotateLeft((b + K(c, d, a) + X[13] + 0x4e0811a1), S44) + c; a = rotateLeft((a + K(b, c, d) + X[ 4] + 0xf7537e82), S41) + b; d = rotateLeft((d + K(a, b, c) + X[11] + 0xbd3af235), S42) + a; c = rotateLeft((c + K(d, a, b) + X[ 2] + 0x2ad7d2bb), S43) + d; b = rotateLeft((b + K(c, d, a) + X[ 9] + 0xeb86d391), S44) + c; H1 += a; H2 += b; H3 += c; H4 += d; // // reset the offset and clean out the word buffer. // xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } } azureus-4.3.0.6/org/bouncycastle/crypto/digests/RIPEMD160Digest.java0000644000175000017500000003455110061400652024316 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; /** * implementation of RIPEMD see, * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html */ public class RIPEMD160Digest extends GeneralDigest { private static final int DIGEST_LENGTH = 20; private int H0, H1, H2, H3, H4; // IV's private int[] X = new int[16]; private int xOff; /** * Standard constructor */ public RIPEMD160Digest() { reset(); } /** * Copy constructor. This will copy the state of the provided * message digest. */ public RIPEMD160Digest(RIPEMD160Digest t) { super(t); H0 = t.H0; H1 = t.H1; H2 = t.H2; H3 = t.H3; H4 = t.H4; System.arraycopy(t.X, 0, X, 0, t.X.length); xOff = t.xOff; } public String getAlgorithmName() { return "RIPEMD160"; } public int getDigestSize() { return DIGEST_LENGTH; } protected void processWord( byte[] in, int inOff) { X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8) | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); if (xOff == 16) { processBlock(); } } protected void processLength( long bitLength) { if (xOff > 14) { processBlock(); } X[14] = (int)(bitLength & 0xffffffff); X[15] = (int)(bitLength >>> 32); } private void unpackWord( int word, byte[] out, int outOff) { out[outOff] = (byte)word; out[outOff + 1] = (byte)(word >>> 8); out[outOff + 2] = (byte)(word >>> 16); out[outOff + 3] = (byte)(word >>> 24); } public int doFinal( byte[] out, int outOff) { finish(); unpackWord(H0, out, outOff); unpackWord(H1, out, outOff + 4); unpackWord(H2, out, outOff + 8); unpackWord(H3, out, outOff + 12); unpackWord(H4, out, outOff + 16); reset(); return DIGEST_LENGTH; } /** * reset the chaining variables to the IV values. */ public void reset() { super.reset(); H0 = 0x67452301; H1 = 0xefcdab89; H2 = 0x98badcfe; H3 = 0x10325476; H4 = 0xc3d2e1f0; xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } /* * rotate int x left n bits. */ private final int RL( int x, int n) { return (x << n) | (x >>> (32 - n)); } /* * f1,f2,f3,f4,f5 are the basic RIPEMD160 functions. */ /* * rounds 0-15 */ private final int f1( int x, int y, int z) { return x ^ y ^ z; } /* * rounds 16-31 */ private final int f2( int x, int y, int z) { return (x & y) | (~x & z); } /* * rounds 32-47 */ private final int f3( int x, int y, int z) { return (x | ~y) ^ z; } /* * rounds 48-63 */ private final int f4( int x, int y, int z) { return (x & z) | (y & ~z); } /* * rounds 64-79 */ private final int f5( int x, int y, int z) { return x ^ (y | ~z); } protected void processBlock() { int a, aa; int b, bb; int c, cc; int d, dd; int e, ee; a = aa = H0; b = bb = H1; c = cc = H2; d = dd = H3; e = ee = H4; // // Rounds 1 - 16 // // left a = RL(a + f1(b,c,d) + X[ 0], 11) + e; c = RL(c, 10); e = RL(e + f1(a,b,c) + X[ 1], 14) + d; b = RL(b, 10); d = RL(d + f1(e,a,b) + X[ 2], 15) + c; a = RL(a, 10); c = RL(c + f1(d,e,a) + X[ 3], 12) + b; e = RL(e, 10); b = RL(b + f1(c,d,e) + X[ 4], 5) + a; d = RL(d, 10); a = RL(a + f1(b,c,d) + X[ 5], 8) + e; c = RL(c, 10); e = RL(e + f1(a,b,c) + X[ 6], 7) + d; b = RL(b, 10); d = RL(d + f1(e,a,b) + X[ 7], 9) + c; a = RL(a, 10); c = RL(c + f1(d,e,a) + X[ 8], 11) + b; e = RL(e, 10); b = RL(b + f1(c,d,e) + X[ 9], 13) + a; d = RL(d, 10); a = RL(a + f1(b,c,d) + X[10], 14) + e; c = RL(c, 10); e = RL(e + f1(a,b,c) + X[11], 15) + d; b = RL(b, 10); d = RL(d + f1(e,a,b) + X[12], 6) + c; a = RL(a, 10); c = RL(c + f1(d,e,a) + X[13], 7) + b; e = RL(e, 10); b = RL(b + f1(c,d,e) + X[14], 9) + a; d = RL(d, 10); a = RL(a + f1(b,c,d) + X[15], 8) + e; c = RL(c, 10); // right aa = RL(aa + f5(bb,cc,dd) + X[ 5] + 0x50a28be6, 8) + ee; cc = RL(cc, 10); ee = RL(ee + f5(aa,bb,cc) + X[14] + 0x50a28be6, 9) + dd; bb = RL(bb, 10); dd = RL(dd + f5(ee,aa,bb) + X[ 7] + 0x50a28be6, 9) + cc; aa = RL(aa, 10); cc = RL(cc + f5(dd,ee,aa) + X[ 0] + 0x50a28be6, 11) + bb; ee = RL(ee, 10); bb = RL(bb + f5(cc,dd,ee) + X[ 9] + 0x50a28be6, 13) + aa; dd = RL(dd, 10); aa = RL(aa + f5(bb,cc,dd) + X[ 2] + 0x50a28be6, 15) + ee; cc = RL(cc, 10); ee = RL(ee + f5(aa,bb,cc) + X[11] + 0x50a28be6, 15) + dd; bb = RL(bb, 10); dd = RL(dd + f5(ee,aa,bb) + X[ 4] + 0x50a28be6, 5) + cc; aa = RL(aa, 10); cc = RL(cc + f5(dd,ee,aa) + X[13] + 0x50a28be6, 7) + bb; ee = RL(ee, 10); bb = RL(bb + f5(cc,dd,ee) + X[ 6] + 0x50a28be6, 7) + aa; dd = RL(dd, 10); aa = RL(aa + f5(bb,cc,dd) + X[15] + 0x50a28be6, 8) + ee; cc = RL(cc, 10); ee = RL(ee + f5(aa,bb,cc) + X[ 8] + 0x50a28be6, 11) + dd; bb = RL(bb, 10); dd = RL(dd + f5(ee,aa,bb) + X[ 1] + 0x50a28be6, 14) + cc; aa = RL(aa, 10); cc = RL(cc + f5(dd,ee,aa) + X[10] + 0x50a28be6, 14) + bb; ee = RL(ee, 10); bb = RL(bb + f5(cc,dd,ee) + X[ 3] + 0x50a28be6, 12) + aa; dd = RL(dd, 10); aa = RL(aa + f5(bb,cc,dd) + X[12] + 0x50a28be6, 6) + ee; cc = RL(cc, 10); // // Rounds 16-31 // // left e = RL(e + f2(a,b,c) + X[ 7] + 0x5a827999, 7) + d; b = RL(b, 10); d = RL(d + f2(e,a,b) + X[ 4] + 0x5a827999, 6) + c; a = RL(a, 10); c = RL(c + f2(d,e,a) + X[13] + 0x5a827999, 8) + b; e = RL(e, 10); b = RL(b + f2(c,d,e) + X[ 1] + 0x5a827999, 13) + a; d = RL(d, 10); a = RL(a + f2(b,c,d) + X[10] + 0x5a827999, 11) + e; c = RL(c, 10); e = RL(e + f2(a,b,c) + X[ 6] + 0x5a827999, 9) + d; b = RL(b, 10); d = RL(d + f2(e,a,b) + X[15] + 0x5a827999, 7) + c; a = RL(a, 10); c = RL(c + f2(d,e,a) + X[ 3] + 0x5a827999, 15) + b; e = RL(e, 10); b = RL(b + f2(c,d,e) + X[12] + 0x5a827999, 7) + a; d = RL(d, 10); a = RL(a + f2(b,c,d) + X[ 0] + 0x5a827999, 12) + e; c = RL(c, 10); e = RL(e + f2(a,b,c) + X[ 9] + 0x5a827999, 15) + d; b = RL(b, 10); d = RL(d + f2(e,a,b) + X[ 5] + 0x5a827999, 9) + c; a = RL(a, 10); c = RL(c + f2(d,e,a) + X[ 2] + 0x5a827999, 11) + b; e = RL(e, 10); b = RL(b + f2(c,d,e) + X[14] + 0x5a827999, 7) + a; d = RL(d, 10); a = RL(a + f2(b,c,d) + X[11] + 0x5a827999, 13) + e; c = RL(c, 10); e = RL(e + f2(a,b,c) + X[ 8] + 0x5a827999, 12) + d; b = RL(b, 10); // right ee = RL(ee + f4(aa,bb,cc) + X[ 6] + 0x5c4dd124, 9) + dd; bb = RL(bb, 10); dd = RL(dd + f4(ee,aa,bb) + X[11] + 0x5c4dd124, 13) + cc; aa = RL(aa, 10); cc = RL(cc + f4(dd,ee,aa) + X[ 3] + 0x5c4dd124, 15) + bb; ee = RL(ee, 10); bb = RL(bb + f4(cc,dd,ee) + X[ 7] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10); aa = RL(aa + f4(bb,cc,dd) + X[ 0] + 0x5c4dd124, 12) + ee; cc = RL(cc, 10); ee = RL(ee + f4(aa,bb,cc) + X[13] + 0x5c4dd124, 8) + dd; bb = RL(bb, 10); dd = RL(dd + f4(ee,aa,bb) + X[ 5] + 0x5c4dd124, 9) + cc; aa = RL(aa, 10); cc = RL(cc + f4(dd,ee,aa) + X[10] + 0x5c4dd124, 11) + bb; ee = RL(ee, 10); bb = RL(bb + f4(cc,dd,ee) + X[14] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10); aa = RL(aa + f4(bb,cc,dd) + X[15] + 0x5c4dd124, 7) + ee; cc = RL(cc, 10); ee = RL(ee + f4(aa,bb,cc) + X[ 8] + 0x5c4dd124, 12) + dd; bb = RL(bb, 10); dd = RL(dd + f4(ee,aa,bb) + X[12] + 0x5c4dd124, 7) + cc; aa = RL(aa, 10); cc = RL(cc + f4(dd,ee,aa) + X[ 4] + 0x5c4dd124, 6) + bb; ee = RL(ee, 10); bb = RL(bb + f4(cc,dd,ee) + X[ 9] + 0x5c4dd124, 15) + aa; dd = RL(dd, 10); aa = RL(aa + f4(bb,cc,dd) + X[ 1] + 0x5c4dd124, 13) + ee; cc = RL(cc, 10); ee = RL(ee + f4(aa,bb,cc) + X[ 2] + 0x5c4dd124, 11) + dd; bb = RL(bb, 10); // // Rounds 32-47 // // left d = RL(d + f3(e,a,b) + X[ 3] + 0x6ed9eba1, 11) + c; a = RL(a, 10); c = RL(c + f3(d,e,a) + X[10] + 0x6ed9eba1, 13) + b; e = RL(e, 10); b = RL(b + f3(c,d,e) + X[14] + 0x6ed9eba1, 6) + a; d = RL(d, 10); a = RL(a + f3(b,c,d) + X[ 4] + 0x6ed9eba1, 7) + e; c = RL(c, 10); e = RL(e + f3(a,b,c) + X[ 9] + 0x6ed9eba1, 14) + d; b = RL(b, 10); d = RL(d + f3(e,a,b) + X[15] + 0x6ed9eba1, 9) + c; a = RL(a, 10); c = RL(c + f3(d,e,a) + X[ 8] + 0x6ed9eba1, 13) + b; e = RL(e, 10); b = RL(b + f3(c,d,e) + X[ 1] + 0x6ed9eba1, 15) + a; d = RL(d, 10); a = RL(a + f3(b,c,d) + X[ 2] + 0x6ed9eba1, 14) + e; c = RL(c, 10); e = RL(e + f3(a,b,c) + X[ 7] + 0x6ed9eba1, 8) + d; b = RL(b, 10); d = RL(d + f3(e,a,b) + X[ 0] + 0x6ed9eba1, 13) + c; a = RL(a, 10); c = RL(c + f3(d,e,a) + X[ 6] + 0x6ed9eba1, 6) + b; e = RL(e, 10); b = RL(b + f3(c,d,e) + X[13] + 0x6ed9eba1, 5) + a; d = RL(d, 10); a = RL(a + f3(b,c,d) + X[11] + 0x6ed9eba1, 12) + e; c = RL(c, 10); e = RL(e + f3(a,b,c) + X[ 5] + 0x6ed9eba1, 7) + d; b = RL(b, 10); d = RL(d + f3(e,a,b) + X[12] + 0x6ed9eba1, 5) + c; a = RL(a, 10); // right dd = RL(dd + f3(ee,aa,bb) + X[15] + 0x6d703ef3, 9) + cc; aa = RL(aa, 10); cc = RL(cc + f3(dd,ee,aa) + X[ 5] + 0x6d703ef3, 7) + bb; ee = RL(ee, 10); bb = RL(bb + f3(cc,dd,ee) + X[ 1] + 0x6d703ef3, 15) + aa; dd = RL(dd, 10); aa = RL(aa + f3(bb,cc,dd) + X[ 3] + 0x6d703ef3, 11) + ee; cc = RL(cc, 10); ee = RL(ee + f3(aa,bb,cc) + X[ 7] + 0x6d703ef3, 8) + dd; bb = RL(bb, 10); dd = RL(dd + f3(ee,aa,bb) + X[14] + 0x6d703ef3, 6) + cc; aa = RL(aa, 10); cc = RL(cc + f3(dd,ee,aa) + X[ 6] + 0x6d703ef3, 6) + bb; ee = RL(ee, 10); bb = RL(bb + f3(cc,dd,ee) + X[ 9] + 0x6d703ef3, 14) + aa; dd = RL(dd, 10); aa = RL(aa + f3(bb,cc,dd) + X[11] + 0x6d703ef3, 12) + ee; cc = RL(cc, 10); ee = RL(ee + f3(aa,bb,cc) + X[ 8] + 0x6d703ef3, 13) + dd; bb = RL(bb, 10); dd = RL(dd + f3(ee,aa,bb) + X[12] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10); cc = RL(cc + f3(dd,ee,aa) + X[ 2] + 0x6d703ef3, 14) + bb; ee = RL(ee, 10); bb = RL(bb + f3(cc,dd,ee) + X[10] + 0x6d703ef3, 13) + aa; dd = RL(dd, 10); aa = RL(aa + f3(bb,cc,dd) + X[ 0] + 0x6d703ef3, 13) + ee; cc = RL(cc, 10); ee = RL(ee + f3(aa,bb,cc) + X[ 4] + 0x6d703ef3, 7) + dd; bb = RL(bb, 10); dd = RL(dd + f3(ee,aa,bb) + X[13] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10); // // Rounds 48-63 // // left c = RL(c + f4(d,e,a) + X[ 1] + 0x8f1bbcdc, 11) + b; e = RL(e, 10); b = RL(b + f4(c,d,e) + X[ 9] + 0x8f1bbcdc, 12) + a; d = RL(d, 10); a = RL(a + f4(b,c,d) + X[11] + 0x8f1bbcdc, 14) + e; c = RL(c, 10); e = RL(e + f4(a,b,c) + X[10] + 0x8f1bbcdc, 15) + d; b = RL(b, 10); d = RL(d + f4(e,a,b) + X[ 0] + 0x8f1bbcdc, 14) + c; a = RL(a, 10); c = RL(c + f4(d,e,a) + X[ 8] + 0x8f1bbcdc, 15) + b; e = RL(e, 10); b = RL(b + f4(c,d,e) + X[12] + 0x8f1bbcdc, 9) + a; d = RL(d, 10); a = RL(a + f4(b,c,d) + X[ 4] + 0x8f1bbcdc, 8) + e; c = RL(c, 10); e = RL(e + f4(a,b,c) + X[13] + 0x8f1bbcdc, 9) + d; b = RL(b, 10); d = RL(d + f4(e,a,b) + X[ 3] + 0x8f1bbcdc, 14) + c; a = RL(a, 10); c = RL(c + f4(d,e,a) + X[ 7] + 0x8f1bbcdc, 5) + b; e = RL(e, 10); b = RL(b + f4(c,d,e) + X[15] + 0x8f1bbcdc, 6) + a; d = RL(d, 10); a = RL(a + f4(b,c,d) + X[14] + 0x8f1bbcdc, 8) + e; c = RL(c, 10); e = RL(e + f4(a,b,c) + X[ 5] + 0x8f1bbcdc, 6) + d; b = RL(b, 10); d = RL(d + f4(e,a,b) + X[ 6] + 0x8f1bbcdc, 5) + c; a = RL(a, 10); c = RL(c + f4(d,e,a) + X[ 2] + 0x8f1bbcdc, 12) + b; e = RL(e, 10); // right cc = RL(cc + f2(dd,ee,aa) + X[ 8] + 0x7a6d76e9, 15) + bb; ee = RL(ee, 10); bb = RL(bb + f2(cc,dd,ee) + X[ 6] + 0x7a6d76e9, 5) + aa; dd = RL(dd, 10); aa = RL(aa + f2(bb,cc,dd) + X[ 4] + 0x7a6d76e9, 8) + ee; cc = RL(cc, 10); ee = RL(ee + f2(aa,bb,cc) + X[ 1] + 0x7a6d76e9, 11) + dd; bb = RL(bb, 10); dd = RL(dd + f2(ee,aa,bb) + X[ 3] + 0x7a6d76e9, 14) + cc; aa = RL(aa, 10); cc = RL(cc + f2(dd,ee,aa) + X[11] + 0x7a6d76e9, 14) + bb; ee = RL(ee, 10); bb = RL(bb + f2(cc,dd,ee) + X[15] + 0x7a6d76e9, 6) + aa; dd = RL(dd, 10); aa = RL(aa + f2(bb,cc,dd) + X[ 0] + 0x7a6d76e9, 14) + ee; cc = RL(cc, 10); ee = RL(ee + f2(aa,bb,cc) + X[ 5] + 0x7a6d76e9, 6) + dd; bb = RL(bb, 10); dd = RL(dd + f2(ee,aa,bb) + X[12] + 0x7a6d76e9, 9) + cc; aa = RL(aa, 10); cc = RL(cc + f2(dd,ee,aa) + X[ 2] + 0x7a6d76e9, 12) + bb; ee = RL(ee, 10); bb = RL(bb + f2(cc,dd,ee) + X[13] + 0x7a6d76e9, 9) + aa; dd = RL(dd, 10); aa = RL(aa + f2(bb,cc,dd) + X[ 9] + 0x7a6d76e9, 12) + ee; cc = RL(cc, 10); ee = RL(ee + f2(aa,bb,cc) + X[ 7] + 0x7a6d76e9, 5) + dd; bb = RL(bb, 10); dd = RL(dd + f2(ee,aa,bb) + X[10] + 0x7a6d76e9, 15) + cc; aa = RL(aa, 10); cc = RL(cc + f2(dd,ee,aa) + X[14] + 0x7a6d76e9, 8) + bb; ee = RL(ee, 10); // // Rounds 64-79 // // left b = RL(b + f5(c,d,e) + X[ 4] + 0xa953fd4e, 9) + a; d = RL(d, 10); a = RL(a + f5(b,c,d) + X[ 0] + 0xa953fd4e, 15) + e; c = RL(c, 10); e = RL(e + f5(a,b,c) + X[ 5] + 0xa953fd4e, 5) + d; b = RL(b, 10); d = RL(d + f5(e,a,b) + X[ 9] + 0xa953fd4e, 11) + c; a = RL(a, 10); c = RL(c + f5(d,e,a) + X[ 7] + 0xa953fd4e, 6) + b; e = RL(e, 10); b = RL(b + f5(c,d,e) + X[12] + 0xa953fd4e, 8) + a; d = RL(d, 10); a = RL(a + f5(b,c,d) + X[ 2] + 0xa953fd4e, 13) + e; c = RL(c, 10); e = RL(e + f5(a,b,c) + X[10] + 0xa953fd4e, 12) + d; b = RL(b, 10); d = RL(d + f5(e,a,b) + X[14] + 0xa953fd4e, 5) + c; a = RL(a, 10); c = RL(c + f5(d,e,a) + X[ 1] + 0xa953fd4e, 12) + b; e = RL(e, 10); b = RL(b + f5(c,d,e) + X[ 3] + 0xa953fd4e, 13) + a; d = RL(d, 10); a = RL(a + f5(b,c,d) + X[ 8] + 0xa953fd4e, 14) + e; c = RL(c, 10); e = RL(e + f5(a,b,c) + X[11] + 0xa953fd4e, 11) + d; b = RL(b, 10); d = RL(d + f5(e,a,b) + X[ 6] + 0xa953fd4e, 8) + c; a = RL(a, 10); c = RL(c + f5(d,e,a) + X[15] + 0xa953fd4e, 5) + b; e = RL(e, 10); b = RL(b + f5(c,d,e) + X[13] + 0xa953fd4e, 6) + a; d = RL(d, 10); // right bb = RL(bb + f1(cc,dd,ee) + X[12], 8) + aa; dd = RL(dd, 10); aa = RL(aa + f1(bb,cc,dd) + X[15], 5) + ee; cc = RL(cc, 10); ee = RL(ee + f1(aa,bb,cc) + X[10], 12) + dd; bb = RL(bb, 10); dd = RL(dd + f1(ee,aa,bb) + X[ 4], 9) + cc; aa = RL(aa, 10); cc = RL(cc + f1(dd,ee,aa) + X[ 1], 12) + bb; ee = RL(ee, 10); bb = RL(bb + f1(cc,dd,ee) + X[ 5], 5) + aa; dd = RL(dd, 10); aa = RL(aa + f1(bb,cc,dd) + X[ 8], 14) + ee; cc = RL(cc, 10); ee = RL(ee + f1(aa,bb,cc) + X[ 7], 6) + dd; bb = RL(bb, 10); dd = RL(dd + f1(ee,aa,bb) + X[ 6], 8) + cc; aa = RL(aa, 10); cc = RL(cc + f1(dd,ee,aa) + X[ 2], 13) + bb; ee = RL(ee, 10); bb = RL(bb + f1(cc,dd,ee) + X[13], 6) + aa; dd = RL(dd, 10); aa = RL(aa + f1(bb,cc,dd) + X[14], 5) + ee; cc = RL(cc, 10); ee = RL(ee + f1(aa,bb,cc) + X[ 0], 15) + dd; bb = RL(bb, 10); dd = RL(dd + f1(ee,aa,bb) + X[ 3], 13) + cc; aa = RL(aa, 10); cc = RL(cc + f1(dd,ee,aa) + X[ 9], 11) + bb; ee = RL(ee, 10); bb = RL(bb + f1(cc,dd,ee) + X[11], 11) + aa; dd = RL(dd, 10); dd += c + H1; H1 = H2 + d + ee; H2 = H3 + e + aa; H3 = H4 + a + bb; H4 = H0 + b + cc; H0 = dd; // // reset the offset and clean out the word buffer. // xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } } azureus-4.3.0.6/org/bouncycastle/crypto/digests/MD2Digest.java0000644000175000017500000001563210061400652023470 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; import org.bouncycastle.crypto.Digest; /** * implementation of MD2 * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992 */ public class MD2Digest implements Digest { private static final int DIGEST_LENGTH = 16; /* X buffer */ private byte[] X = new byte[48]; private int xOff; /* M buffer */ private byte[] M = new byte[16]; private int mOff; /* check sum */ private byte[] C = new byte[16]; private int COff; public MD2Digest() { reset(); } public MD2Digest(MD2Digest t) { System.arraycopy(t.X, 0, X, 0, t.X.length); xOff = t.xOff; System.arraycopy(t.M, 0, M, 0, t.M.length); mOff = t.mOff; System.arraycopy(t.C, 0, C, 0, t.C.length); COff = t.COff; } /** * return the algorithm name * * @return the algorithm name */ public String getAlgorithmName() { return "MD2"; } /** * return the size, in bytes, of the digest produced by this message digest. * * @return the size, in bytes, of the digest produced by this message digest. */ public int getDigestSize() { return DIGEST_LENGTH; } /** * close the digest, producing the final digest value. The doFinal * call leaves the digest reset. * * @param out the array the digest is to be copied into. * @param outOff the offset into the out array the digest is to start at. */ public int doFinal(byte[] out, int outOff) { // add padding byte paddingByte = (byte)(M.length-mOff); for (int i=mOff;i 0)) { update(in[inOff]); inOff++; len--; } // // process whole words. // while (len > 16) { System.arraycopy(in,inOff,M,0,16); processCheckSum(M); processBlock(M); len -= 16; inOff += 16; } // // load in the remainder. // while (len > 0) { update(in[inOff]); inOff++; len--; } } protected void processCheckSum(byte[] m) { int L = C[15]; for (int i=0;i<16;i++) { C[i] ^= S[(m[i] ^ L) & 0xff]; L = C[i]; } } protected void processBlock(byte[] m) { for (int i=0;i<16;i++) { X[i+16] = m[i]; X[i+32] = (byte)(m[i] ^ X[i]); } // encrypt block int t = 0; for (int j=0;j<18;j++) { for (int k=0;k<48;k++) { t = X[k] ^= S[t]; t = t & 0xff; } t = (t + j)%256; } } // 256-byte random permutation constructed from the digits of PI private static final byte[] S = { (byte)41,(byte)46,(byte)67,(byte)201,(byte)162,(byte)216,(byte)124, (byte)1,(byte)61,(byte)54,(byte)84,(byte)161,(byte)236,(byte)240, (byte)6,(byte)19,(byte)98,(byte)167,(byte)5,(byte)243,(byte)192, (byte)199,(byte)115,(byte)140,(byte)152,(byte)147,(byte)43,(byte)217, (byte)188,(byte)76,(byte)130,(byte)202,(byte)30,(byte)155,(byte)87, (byte)60,(byte)253,(byte)212,(byte)224,(byte)22,(byte)103,(byte)66, (byte)111,(byte)24,(byte)138,(byte)23,(byte)229,(byte)18,(byte)190, (byte)78,(byte)196,(byte)214,(byte)218,(byte)158,(byte)222,(byte)73, (byte)160,(byte)251,(byte)245,(byte)142,(byte)187,(byte)47,(byte)238, (byte)122,(byte)169,(byte)104,(byte)121,(byte)145,(byte)21,(byte)178, (byte)7,(byte)63,(byte)148,(byte)194,(byte)16,(byte)137,(byte)11, (byte)34,(byte)95,(byte)33,(byte)128,(byte)127,(byte)93,(byte)154, (byte)90,(byte)144,(byte)50,(byte)39,(byte)53,(byte)62,(byte)204, (byte)231,(byte)191,(byte)247,(byte)151,(byte)3,(byte)255,(byte)25, (byte)48,(byte)179,(byte)72,(byte)165,(byte)181,(byte)209,(byte)215, (byte)94,(byte)146,(byte)42,(byte)172,(byte)86,(byte)170,(byte)198, (byte)79,(byte)184,(byte)56,(byte)210,(byte)150,(byte)164,(byte)125, (byte)182,(byte)118,(byte)252,(byte)107,(byte)226,(byte)156,(byte)116, (byte)4,(byte)241,(byte)69,(byte)157,(byte)112,(byte)89,(byte)100, (byte)113,(byte)135,(byte)32,(byte)134,(byte)91,(byte)207,(byte)101, (byte)230,(byte)45,(byte)168,(byte)2,(byte)27,(byte)96,(byte)37, (byte)173,(byte)174,(byte)176,(byte)185,(byte)246,(byte)28,(byte)70, (byte)97,(byte)105,(byte)52,(byte)64,(byte)126,(byte)15,(byte)85, (byte)71,(byte)163,(byte)35,(byte)221,(byte)81,(byte)175,(byte)58, (byte)195,(byte)92,(byte)249,(byte)206,(byte)186,(byte)197,(byte)234, (byte)38,(byte)44,(byte)83,(byte)13,(byte)110,(byte)133,(byte)40, (byte)132, 9,(byte)211,(byte)223,(byte)205,(byte)244,(byte)65, (byte)129,(byte)77,(byte)82,(byte)106,(byte)220,(byte)55,(byte)200, (byte)108,(byte)193,(byte)171,(byte)250,(byte)36,(byte)225,(byte)123, (byte)8,(byte)12,(byte)189,(byte)177,(byte)74,(byte)120,(byte)136, (byte)149,(byte)139,(byte)227,(byte)99,(byte)232,(byte)109,(byte)233, (byte)203,(byte)213,(byte)254,(byte)59,(byte)0,(byte)29,(byte)57, (byte)242,(byte)239,(byte)183,(byte)14,(byte)102,(byte)88,(byte)208, (byte)228,(byte)166,(byte)119,(byte)114,(byte)248,(byte)235,(byte)117, (byte)75,(byte)10,(byte)49,(byte)68,(byte)80,(byte)180,(byte)143, (byte)237,(byte)31,(byte)26,(byte)219,(byte)153,(byte)141,(byte)51, (byte)159,(byte)17,(byte)131,(byte)20 }; } azureus-4.3.0.6/org/bouncycastle/crypto/digests/SHA256Digest.java0000644000175000017500000001342410061400652023753 0ustar adrianadrianpackage org.bouncycastle.crypto.digests; /** * Draft FIPS 180-2 implementation of SHA-256. Note: As this is * based on a draft this implementation is subject to change. * *

       *         block  word  digest
       * SHA-1   512    32    160
       * SHA-256 512    32    256
       * SHA-384 1024   64    384
       * SHA-512 1024   64    512
       * 
      */ public class SHA256Digest extends GeneralDigest { private static final int DIGEST_LENGTH = 32; private int H1, H2, H3, H4, H5, H6, H7, H8; private int[] X = new int[64]; private int xOff; /** * Standard constructor */ public SHA256Digest() { reset(); } /** * Copy constructor. This will copy the state of the provided * message digest. */ public SHA256Digest(SHA256Digest t) { super(t); H1 = t.H1; H2 = t.H2; H3 = t.H3; H4 = t.H4; H5 = t.H5; H6 = t.H6; H7 = t.H7; H8 = t.H8; System.arraycopy(t.X, 0, X, 0, t.X.length); xOff = t.xOff; } public String getAlgorithmName() { return "SHA-256"; } public int getDigestSize() { return DIGEST_LENGTH; } protected void processWord( byte[] in, int inOff) { X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16) | ((in[inOff + 2] & 0xff) << 8) | ((in[inOff + 3] & 0xff)); if (xOff == 16) { processBlock(); } } private void unpackWord( int word, byte[] out, int outOff) { out[outOff] = (byte)(word >>> 24); out[outOff + 1] = (byte)(word >>> 16); out[outOff + 2] = (byte)(word >>> 8); out[outOff + 3] = (byte)word; } protected void processLength( long bitLength) { if (xOff > 14) { processBlock(); } X[14] = (int)(bitLength >>> 32); X[15] = (int)(bitLength & 0xffffffff); } public int doFinal( byte[] out, int outOff) { finish(); unpackWord(H1, out, outOff); unpackWord(H2, out, outOff + 4); unpackWord(H3, out, outOff + 8); unpackWord(H4, out, outOff + 12); unpackWord(H5, out, outOff + 16); unpackWord(H6, out, outOff + 20); unpackWord(H7, out, outOff + 24); unpackWord(H8, out, outOff + 28); reset(); return DIGEST_LENGTH; } /** * reset the chaining variables */ public void reset() { super.reset(); /* SHA-256 initial hash value * The first 32 bits of the fractional parts of the square roots * of the first eight prime numbers */ H1 = 0x6a09e667; H2 = 0xbb67ae85; H3 = 0x3c6ef372; H4 = 0xa54ff53a; H5 = 0x510e527f; H6 = 0x9b05688c; H7 = 0x1f83d9ab; H8 = 0x5be0cd19; xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } protected void processBlock() { // // expand 16 word block into 64 word blocks. // for (int t = 16; t <= 63; t++) { X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16]; } // // set up working variables. // int a = H1; int b = H2; int c = H3; int d = H4; int e = H5; int f = H6; int g = H7; int h = H8; for (int t = 0; t <= 63; t++) { int T1, T2; T1 = h + Sum1(e) + Ch(e, f, g) + K[t] + X[t]; T2 = Sum0(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; } H1 += a; H2 += b; H3 += c; H4 += d; H5 += e; H6 += f; H7 += g; H8 += h; // // reset the offset and clean out the word buffer. // xOff = 0; for (int i = 0; i != X.length; i++) { X[i] = 0; } } private int rotateRight( int x, int n) { return (x >>> n) | (x << (32 - n)); } /* SHA-256 functions */ private int Ch( int x, int y, int z) { return ((x & y) ^ ((~x) & z)); } private int Maj( int x, int y, int z) { return ((x & y) ^ (x & z) ^ (y & z)); } private int Sum0( int x) { return rotateRight(x, 2) ^ rotateRight(x, 13) ^ rotateRight(x, 22); } private int Sum1( int x) { return rotateRight(x, 6) ^ rotateRight(x, 11) ^ rotateRight(x, 25); } private int Theta0( int x) { return rotateRight(x, 7) ^ rotateRight(x, 18) ^ (x >>> 3); } private int Theta1( int x) { return rotateRight(x, 17) ^ rotateRight(x, 19) ^ (x >>> 10); } /* SHA-256 Constants * (represent the first 32 bits of the fractional parts of the * cube roots of the first sixty-four prime numbers) */ static final int K[] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; } azureus-4.3.0.6/org/bouncycastle/crypto/DerivationParameters.java0000644000175000017500000000021110061400652024417 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * Parameters for key/byte stream derivation classes */ public interface DerivationParameters { } azureus-4.3.0.6/org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java0000644000175000017500000000742010061400652026166 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * a buffer wrapper for an asymmetric block cipher, allowing input * to be accumulated in a piecemeal fashion until final processing. */ public class BufferedAsymmetricBlockCipher { protected byte[] buf; protected int bufOff; private boolean forEncryption; private AsymmetricBlockCipher cipher; /** * base constructor. * * @param cipher the cipher this buffering object wraps. */ public BufferedAsymmetricBlockCipher( AsymmetricBlockCipher cipher) { this.cipher = cipher; } /** * return the underlying cipher for the buffer. * * @return the underlying cipher for the buffer. */ public AsymmetricBlockCipher getUnderlyingCipher() { return cipher; } /** * return the amount of data sitting in the buffer. * * @return the amount of data sitting in the buffer. */ public int getBufferPosition() { return bufOff; } /** * initialise the buffer and the underlying cipher. * * @param forEncryption if true the cipher is initialised for * encryption, if false for decryption. * @param param the key and other data required by the cipher. */ public void init( boolean forEncryption, CipherParameters params) { this.forEncryption = forEncryption; reset(); cipher.init(forEncryption, params); buf = new byte[cipher.getInputBlockSize()]; bufOff = 0; } /** * returns the largest size an input block can be. * * @return maximum size for an input block. */ public int getInputBlockSize() { return cipher.getInputBlockSize(); } /** * returns the maximum size of the block produced by this cipher. * * @return maximum size of the output block produced by the cipher. */ public int getOutputBlockSize() { return cipher.getOutputBlockSize(); } /** * add another byte for processing. * * @param in the input byte. */ public void processByte( byte in) { if (bufOff > buf.length) { throw new DataLengthException("attempt to process message to long for cipher"); } buf[bufOff++] = in; } /** * add len bytes to the buffer for processing. * * @param in the input data * @param inOff offset into the in array where the data starts * @param len the length of the block to be processed. */ public void processBytes( byte[] in, int inOff, int len) { if (len == 0) { return; } if (len < 0) { throw new IllegalArgumentException("Can't have a negative input length!"); } if (bufOff + len > buf.length) { throw new DataLengthException("attempt to process message to long for cipher"); } System.arraycopy(in, inOff, buf, bufOff, len); bufOff += len; } /** * process the contents of the buffer using the underlying * cipher. * * @return the result of the encryption/decryption process on the * buffer. * @exception InvalidCipherTextException if we are given a garbage block. */ public byte[] doFinal() throws InvalidCipherTextException { byte[] out = cipher.processBlock(buf, 0, bufOff); reset(); return out; } /** * Reset the buffer and the underlying cipher. */ public void reset() { /* * clean the buffer. */ if (buf != null) { for (int i = 0; i < buf.length; i++) { buf[0] = 0; } } bufOff = 0; } } azureus-4.3.0.6/org/bouncycastle/crypto/StreamCipher.java0000644000175000017500000000331210061400652022662 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * the interface stream ciphers conform to. */ public interface StreamCipher { /** * Initialise the cipher. * * @param forEncryption if true the cipher is initialised for * encryption, if false for decryption. * @param param the key and other data required by the cipher. * @exception IllegalArgumentException if the params argument is * inappropriate. */ public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException; /** * Return the name of the algorithm the cipher implements. * * @return the name of the algorithm the cipher implements. */ public String getAlgorithmName(); /** * encrypt/decrypt a single byte returning the result. * * @param in the byte to be processed. * @return the result of processing the input byte. */ public byte returnByte(byte in); /** * process a block of bytes from in putting the result into out. * * @param in the input byte array. * @param inOff the offset into the in array where the data to be processed starts. * @param len the number of bytes to be processed. * @param out the output buffer the processed bytes go into. * @param outOff the offset into the output byte array the processed data stars at. * @exception DataLengthException if the output buffer is too small. */ public void processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException; /** * reset the cipher. This leaves it in the same state * it was at after the last init (if there was one). */ public void reset(); } azureus-4.3.0.6/org/bouncycastle/crypto/modes/0000755000175000017500000000000011310377634020554 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/crypto/modes/OFBBlockCipher.java0000644000175000017500000001221210061400652024116 0ustar adrianadrianpackage org.bouncycastle.crypto.modes; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.params.ParametersWithIV; /** * implements a Output-FeedBack (OFB) mode on top of a simple cipher. */ public class OFBBlockCipher implements BlockCipher { private byte[] IV; private byte[] ofbV; private byte[] ofbOutV; private int blockSize; private BlockCipher cipher = null; private boolean encrypting; /** * Basic constructor. * * @param cipher the block cipher to be used as the basis of the * feedback mode. * @param blockSize the block size in bits (note: a multiple of 8) */ public OFBBlockCipher( BlockCipher cipher, int blockSize) { this.cipher = cipher; this.blockSize = blockSize / 8; this.IV = new byte[cipher.getBlockSize()]; this.ofbV = new byte[cipher.getBlockSize()]; this.ofbOutV = new byte[cipher.getBlockSize()]; } /** * return the underlying block cipher that we are wrapping. * * @return the underlying block cipher that we are wrapping. */ public BlockCipher getUnderlyingCipher() { return cipher; } /** * Initialise the cipher and, possibly, the initialisation vector (IV). * If an IV isn't passed as part of the parameter, the IV will be all zeros. * An IV which is too short is handled in FIPS compliant fashion. * * @param forEncryption if true the cipher is initialised for * encryption, if false for decryption. * @param param the key and other data required by the cipher. * @exception IllegalArgumentException if the params argument is * inappropriate. */ public void init( boolean encrypting, CipherParameters params) throws IllegalArgumentException { this.encrypting = encrypting; if (params instanceof ParametersWithIV) { ParametersWithIV ivParam = (ParametersWithIV)params; byte[] iv = ivParam.getIV(); if (iv.length < IV.length) { // prepend the supplied IV with zeros (per FIPS PUB 81) System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length); for (int i = 0; i < IV.length - iv.length; i++) { IV[i] = 0; } } else { System.arraycopy(iv, 0, IV, 0, IV.length); } reset(); cipher.init(true, ivParam.getParameters()); } else { reset(); cipher.init(true, params); } } /** * return the algorithm name and mode. * * @return the name of the underlying algorithm followed by "/OFB" * and the block size in bits */ public String getAlgorithmName() { return cipher.getAlgorithmName() + "/OFB" + (blockSize * 8); } /** * return the block size we are operating at (in bytes). * * @return the block size we are operating at (in bytes). */ public int getBlockSize() { return blockSize; } /** * Process one block of input from the array in and write it to * the out array. * * @param in the array containing the input data. * @param inOff offset into the in array the data starts at. * @param out the array the output data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ public int processBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if ((inOff + blockSize) > in.length) { throw new DataLengthException("input buffer too short"); } if ((outOff + blockSize) > out.length) { throw new DataLengthException("output buffer too short"); } cipher.processBlock(ofbV, 0, ofbOutV, 0); // // XOR the ofbV with the plaintext producing the cipher text (and // the next input block). // for (int i = 0; i < blockSize; i++) { out[outOff + i] = (byte)(ofbOutV[i] ^ in[inOff + i]); } // // change over the input block. // System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize); System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize); return blockSize; } /** * reset the feedback vector back to the IV and reset the underlying * cipher. */ public void reset() { System.arraycopy(IV, 0, ofbV, 0, IV.length); cipher.reset(); } } azureus-4.3.0.6/org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java0000644000175000017500000002270310061400652025301 0ustar adrianadrianpackage org.bouncycastle.crypto.modes; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; /** * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode * on top of a simple cipher. This class assumes the IV has been prepended * to the data stream already, and just accomodates the reset after * (blockSize + 2) bytes have been read. *

      * For further info see RFC 2440. */ public class OpenPGPCFBBlockCipher implements BlockCipher { private byte[] IV; private byte[] FR; private byte[] FRE; private byte[] tmp; private BlockCipher cipher; private int count; private int blockSize; private boolean forEncryption; /** * Basic constructor. * * @param cipher the block cipher to be used as the basis of the * feedback mode. */ public OpenPGPCFBBlockCipher( BlockCipher cipher) { this.cipher = cipher; this.blockSize = cipher.getBlockSize(); this.IV = new byte[blockSize]; this.FR = new byte[blockSize]; this.FRE = new byte[blockSize]; this.tmp = new byte[blockSize]; } /** * return the underlying block cipher that we are wrapping. * * @return the underlying block cipher that we are wrapping. */ public BlockCipher getUnderlyingCipher() { return cipher; } /** * return the algorithm name and mode. * * @return the name of the underlying algorithm followed by "/PGPCFB" * and the block size in bits. */ public String getAlgorithmName() { return cipher.getAlgorithmName() + "/OpenPGPCFB"; } /** * return the block size we are operating at. * * @return the block size we are operating at (in bytes). */ public int getBlockSize() { return cipher.getBlockSize(); } /** * Process one block of input from the array in and write it to * the out array. * * @param in the array containing the input data. * @param inOff offset into the in array the data starts at. * @param out the array the output data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ public int processBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { return (forEncryption) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff); } /** * reset the chaining vector back to the IV and reset the underlying * cipher. */ public void reset() { count = 0; for (int i = 0; i != FR.length; i++) { FR[i] = IV[i]; } cipher.reset(); } /** * Initialise the cipher and, possibly, the initialisation vector (IV). * If an IV isn't passed as part of the parameter, the IV will be all zeros. * An IV which is too short is handled in FIPS compliant fashion. * * @param forEncryption if true the cipher is initialised for * encryption, if false for decryption. * @param param the key and other data required by the cipher. * @exception IllegalArgumentException if the params argument is * inappropriate. */ public void init( boolean forEncryption, CipherParameters params) throws IllegalArgumentException { this.forEncryption = forEncryption; reset(); cipher.init(true, params); } /** * Encrypt one byte of data according to CFB mode. * @param data the byte to encrypt * @param where am i in the current block, determines when to resync the block * @returns the encrypted byte */ private byte encryptByte(byte data, int blockOff) { return (byte)(FRE[blockOff] ^ data); } /** * Do the appropriate processing for CFB IV mode encryption. * * @param in the array containing the data to be encrypted. * @param inOff offset into the in array the data starts at. * @param out the array the encrypted data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ private int encryptBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if ((inOff + blockSize) > in.length) { throw new DataLengthException("input buffer too short"); } if ((outOff + blockSize) > out.length) { throw new DataLengthException("output buffer too short"); } if (count > blockSize) { FR[blockSize - 2] = out[outOff] = encryptByte(in[inOff], blockSize - 2); FR[blockSize - 1] = out[outOff + 1] = encryptByte(in[inOff + 1], blockSize - 1); cipher.processBlock(FR, 0, FRE, 0); for (int n = 2; n < blockSize; n++) { out[outOff + n] = encryptByte(in[inOff + n], n - 2); } System.arraycopy(out, outOff + 2, FR, 0, blockSize - 2); } else if (count == 0) { cipher.processBlock(FR, 0, FRE, 0); for (int n = 0; n < blockSize; n++) { out[outOff + n] = encryptByte(in[inOff + n], n); } System.arraycopy(out, outOff, FR, 0, blockSize); count += blockSize; } else if (count == blockSize) { cipher.processBlock(FR, 0, FRE, 0); out[outOff] = encryptByte(in[inOff], 0); out[outOff + 1] = encryptByte(in[inOff + 1], 1); // // do reset // System.arraycopy(FR, 2, FR, 0, blockSize - 2); System.arraycopy(out, outOff, FR, blockSize - 2, 2); cipher.processBlock(FR, 0, FRE, 0); for (int n = 2; n < blockSize; n++) { out[outOff + n] = encryptByte(in[inOff + n], n - 2); } System.arraycopy(out, outOff + 2, FR, 0, blockSize - 2); count += blockSize; } return blockSize; } /** * Do the appropriate processing for CFB IV mode decryption. * * @param in the array containing the data to be decrypted. * @param inOff offset into the in array the data starts at. * @param out the array the encrypted data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ private int decryptBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if ((inOff + blockSize) > in.length) { throw new DataLengthException("input buffer too short"); } if ((outOff + blockSize) > out.length) { throw new DataLengthException("output buffer too short"); } if (count > blockSize) { // copy in buffer so that this mode works if in and out are the same System.arraycopy(in, inOff, tmp, 0, blockSize); out[outOff + 0] = encryptByte(tmp[0], blockSize - 2); out[outOff + 1] = encryptByte(tmp[1], blockSize - 1); System.arraycopy(tmp, 0, FR, blockSize - 2, 2); cipher.processBlock(FR, 0, FRE, 0); for (int n = 2; n < blockSize; n++) { out[outOff + n] = encryptByte(tmp[n], n - 2); } System.arraycopy(tmp, 2, FR, 0, blockSize - 2); } else if (count == 0) { cipher.processBlock(FR, 0, FRE, 0); for (int n = 0; n < blockSize; n++) { FR[n] = in[inOff + n]; out[n] = encryptByte(in[inOff + n], n); } count += blockSize; } else if (count == blockSize) { System.arraycopy(in, inOff, tmp, 0, blockSize); cipher.processBlock(FR, 0, FRE, 0); out[outOff + 0] = encryptByte(tmp[0], 0); out[outOff + 1] = encryptByte(tmp[1], 1); System.arraycopy(FR, 2, FR, 0, blockSize - 2); FR[blockSize - 2] = tmp[0]; FR[blockSize - 1] = tmp[1]; cipher.processBlock(FR, 0, FRE, 0); for (int n = 2; n < blockSize; n++) { FR[n - 2] = in[inOff + n]; out[outOff + n] = encryptByte(in[inOff + n], n - 2); } count += blockSize;; } return blockSize; } } azureus-4.3.0.6/org/bouncycastle/crypto/modes/package.html0000644000175000017500000000011510061400652023017 0ustar adrianadrian Modes for symmetric ciphers. azureus-4.3.0.6/org/bouncycastle/crypto/modes/CBCBlockCipher.java0000644000175000017500000001531010061400652024101 0ustar adrianadrianpackage org.bouncycastle.crypto.modes; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.params.ParametersWithIV; /** * implements Cipher-Block-Chaining (CBC) mode on top of a simple cipher. */ public class CBCBlockCipher implements BlockCipher { private byte[] IV; private byte[] cbcV; private byte[] cbcNextV; private int blockSize; private BlockCipher cipher = null; private boolean encrypting; /** * Basic constructor. * * @param cipher the block cipher to be used as the basis of chaining. */ public CBCBlockCipher( BlockCipher cipher) { this.cipher = cipher; this.blockSize = cipher.getBlockSize(); this.IV = new byte[blockSize]; this.cbcV = new byte[blockSize]; this.cbcNextV = new byte[blockSize]; } /** * return the underlying block cipher that we are wrapping. * * @return the underlying block cipher that we are wrapping. */ public BlockCipher getUnderlyingCipher() { return cipher; } /** * Initialise the cipher and, possibly, the initialisation vector (IV). * If an IV isn't passed as part of the parameter, the IV will be all zeros. * * @param forEncryption if true the cipher is initialised for * encryption, if false for decryption. * @param param the key and other data required by the cipher. * @exception IllegalArgumentException if the params argument is * inappropriate. */ public void init( boolean encrypting, CipherParameters params) throws IllegalArgumentException { this.encrypting = encrypting; if (params instanceof ParametersWithIV) { ParametersWithIV ivParam = (ParametersWithIV)params; byte[] iv = ivParam.getIV(); if (iv.length != blockSize) { throw new IllegalArgumentException("initialisation vector must be the same length as block size"); } System.arraycopy(iv, 0, IV, 0, iv.length); reset(); cipher.init(encrypting, ivParam.getParameters()); } else { reset(); cipher.init(encrypting, params); } } /** * return the algorithm name and mode. * * @return the name of the underlying algorithm followed by "/CBC". */ public String getAlgorithmName() { return cipher.getAlgorithmName() + "/CBC"; } /** * return the block size of the underlying cipher. * * @return the block size of the underlying cipher. */ public int getBlockSize() { return cipher.getBlockSize(); } /** * Process one block of input from the array in and write it to * the out array. * * @param in the array containing the input data. * @param inOff offset into the in array the data starts at. * @param out the array the output data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ public int processBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff); } /** * reset the chaining vector back to the IV and reset the underlying * cipher. */ public void reset() { System.arraycopy(IV, 0, cbcV, 0, IV.length); cipher.reset(); } /** * Do the appropriate chaining step for CBC mode encryption. * * @param in the array containing the data to be encrypted. * @param inOff offset into the in array the data starts at. * @param out the array the encrypted data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ private int encryptBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if ((inOff + blockSize) > in.length) { throw new DataLengthException("input buffer too short"); } /* * XOR the cbcV and the input, * then encrypt the cbcV */ for (int i = 0; i < blockSize; i++) { cbcV[i] ^= in[inOff + i]; } int length = cipher.processBlock(cbcV, 0, out, outOff); /* * copy ciphertext to cbcV */ System.arraycopy(out, outOff, cbcV, 0, cbcV.length); return length; } /** * Do the appropriate chaining step for CBC mode decryption. * * @param in the array containing the data to be decrypted. * @param inOff offset into the in array the data starts at. * @param out the array the decrypted data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ private int decryptBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if ((inOff + blockSize) > in.length) { throw new DataLengthException("input buffer too short"); } System.arraycopy(in, inOff, cbcNextV, 0, blockSize); int length = cipher.processBlock(in, inOff, out, outOff); /* * XOR the cbcV and the output */ for (int i = 0; i < blockSize; i++) { out[outOff + i] ^= cbcV[i]; } /* * swap the back up buffer into next position */ byte[] tmp; tmp = cbcV; cbcV = cbcNextV; cbcNextV = tmp; return length; } } azureus-4.3.0.6/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java0000644000175000017500000003227110061400652024460 0ustar adrianadrianpackage org.bouncycastle.crypto.modes; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.params.ParametersWithIV; /** * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode on top of a simple cipher. For further info see RFC 2440. */ public class PGPCFBBlockCipher implements BlockCipher { private byte[] IV; private byte[] FR; private byte[] FRE; private byte[] tmp; private BlockCipher cipher; private int count; private int blockSize; private boolean forEncryption; private boolean inlineIv; // if false we don't need to prepend an IV /** * Basic constructor. * * @param cipher the block cipher to be used as the basis of the * feedback mode. * @param inlineIv if true this is for PGP CFB with a prepended iv. */ public PGPCFBBlockCipher( BlockCipher cipher, boolean inlineIv) { this.cipher = cipher; this.inlineIv = inlineIv; this.blockSize = cipher.getBlockSize(); this.IV = new byte[blockSize]; this.FR = new byte[blockSize]; this.FRE = new byte[blockSize]; this.tmp = new byte[blockSize]; } /** * return the underlying block cipher that we are wrapping. * * @return the underlying block cipher that we are wrapping. */ public BlockCipher getUnderlyingCipher() { return cipher; } /** * return the algorithm name and mode. * * @return the name of the underlying algorithm followed by "/PGPCFB" * and the block size in bits. */ public String getAlgorithmName() { if (inlineIv) { return cipher.getAlgorithmName() + "/PGPCFBwithIV"; } else { return cipher.getAlgorithmName() + "/PGPCFB"; } } /** * return the block size we are operating at. * * @return the block size we are operating at (in bytes). */ public int getBlockSize() { return cipher.getBlockSize(); } /** * Process one block of input from the array in and write it to * the out array. * * @param in the array containing the input data. * @param inOff offset into the in array the data starts at. * @param out the array the output data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ public int processBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if (inlineIv) { return (forEncryption) ? encryptBlockWithIV(in, inOff, out, outOff) : decryptBlockWithIV(in, inOff, out, outOff); } else { return (forEncryption) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff); } } /** * reset the chaining vector back to the IV and reset the underlying * cipher. */ public void reset() { count = 0; for (int i = 0; i != FR.length; i++) { if (inlineIv) FR[i] = 0; else FR[i] = IV[i]; // if simple mode, key is IV (even if this is zero) } cipher.reset(); } /** * Initialise the cipher and, possibly, the initialisation vector (IV). * If an IV isn't passed as part of the parameter, the IV will be all zeros. * An IV which is too short is handled in FIPS compliant fashion. * * @param forEncryption if true the cipher is initialised for * encryption, if false for decryption. * @param param the key and other data required by the cipher. * @exception IllegalArgumentException if the params argument is * inappropriate. */ public void init( boolean forEncryption, CipherParameters params) throws IllegalArgumentException { this.forEncryption = forEncryption; if (params instanceof ParametersWithIV) { ParametersWithIV ivParam = (ParametersWithIV)params; byte[] iv = ivParam.getIV(); if (iv.length < IV.length) { // prepend the supplied IV with zeros (per FIPS PUB 81) System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length); for (int i = 0; i < IV.length - iv.length; i++) { IV[i] = 0; } } else { System.arraycopy(iv, 0, IV, 0, IV.length); } reset(); cipher.init(true, ivParam.getParameters()); } else { reset(); cipher.init(true, params); } } /** * Encrypt one byte of data according to CFB mode. * @param data the byte to encrypt * @param where am i in the current block, determines when to resync the block * @returns the encrypted byte */ private byte encryptByte(byte data, int blockOff) { return (byte)(FRE[blockOff] ^ data); } /** * Do the appropriate processing for CFB IV mode encryption. * * @param in the array containing the data to be encrypted. * @param inOff offset into the in array the data starts at. * @param out the array the encrypted data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ private int encryptBlockWithIV( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if ((inOff + blockSize) > in.length) { throw new DataLengthException("input buffer too short"); } if ((outOff + blockSize) > out.length) { throw new DataLengthException("output buffer too short"); } if (count == 0) { cipher.processBlock(FR, 0, FRE, 0); for (int n = 0; n < blockSize; n++) { out[outOff + n] = encryptByte(IV[n], n); } System.arraycopy(out, outOff, FR, 0, blockSize); cipher.processBlock(FR, 0, FRE, 0); out[outOff + blockSize] = encryptByte(IV[blockSize - 2], 0); out[outOff + blockSize + 1] = encryptByte(IV[blockSize - 1], 1); System.arraycopy(out, outOff + 2, FR, 0, blockSize); cipher.processBlock(FR, 0, FRE, 0); for (int n = 0; n < blockSize; n++) { out[outOff + blockSize + 2 + n] = encryptByte(in[inOff + n], n); } System.arraycopy(out, outOff + blockSize + 2, FR, 0, blockSize); count += 2 * blockSize + 2; return 2 * blockSize + 2; } else if (count >= blockSize + 2) { cipher.processBlock(FR, 0, FRE, 0); for (int n = 0; n < blockSize; n++) { out[outOff + n] = encryptByte(in[inOff + n], n); } System.arraycopy(out, outOff, FR, 0, blockSize); } return blockSize; } /** * Do the appropriate processing for CFB IV mode decryption. * * @param in the array containing the data to be decrypted. * @param inOff offset into the in array the data starts at. * @param out the array the encrypted data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ private int decryptBlockWithIV( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if ((inOff + blockSize) > in.length) { throw new DataLengthException("input buffer too short"); } if ((outOff + blockSize) > out.length) { throw new DataLengthException("output buffer too short"); } if (count == 0) { for (int n = 0; n < blockSize; n++) { FR[n] = in[inOff + n]; } cipher.processBlock(FR, 0, FRE, 0); count += blockSize; return 0; } else if (count == blockSize) { // copy in buffer so that this mode works if in and out are the same System.arraycopy(in, inOff, tmp, 0, blockSize); System.arraycopy(FR, 2, FR, 0, blockSize - 2); FR[blockSize - 2] = tmp[0]; FR[blockSize - 1] = tmp[1]; cipher.processBlock(FR, 0, FRE, 0); for (int n = 0; n < blockSize - 2; n++) { out[outOff + n] = encryptByte(tmp[n + 2], n); } System.arraycopy(tmp, 2, FR, 0, blockSize - 2); count += 2; return blockSize - 2; } else if (count >= blockSize + 2) { // copy in buffer so that this mode works if in and out are the same System.arraycopy(in, inOff, tmp, 0, blockSize); out[outOff + 0] = encryptByte(tmp[0], blockSize - 2); out[outOff + 1] = encryptByte(tmp[1], blockSize - 1); System.arraycopy(tmp, 0, FR, blockSize - 2, 2); cipher.processBlock(FR, 0, FRE, 0); for (int n = 0; n < blockSize - 2; n++) { out[outOff + n + 2] = encryptByte(tmp[n + 2], n); } System.arraycopy(tmp, 2, FR, 0, blockSize - 2); } return blockSize; } /** * Do the appropriate processing for CFB mode encryption. * * @param in the array containing the data to be encrypted. * @param inOff offset into the in array the data starts at. * @param out the array the encrypted data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ private int encryptBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if ((inOff + blockSize) > in.length) { throw new DataLengthException("input buffer too short"); } if ((outOff + blockSize) > out.length) { throw new DataLengthException("output buffer too short"); } cipher.processBlock(FR, 0, FRE, 0); for (int n = 0; n < blockSize; n++) out[outOff + n] = encryptByte(in[inOff + n], n); for (int n = 0; n < blockSize; n++) FR[n] = out[outOff + n]; return blockSize; } /** * Do the appropriate processing for CFB mode decryption. * * @param in the array containing the data to be decrypted. * @param inOff offset into the in array the data starts at. * @param out the array the encrypted data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ private int decryptBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if ((inOff + blockSize) > in.length) { throw new DataLengthException("input buffer too short"); } if ((outOff + blockSize) > out.length) { throw new DataLengthException("output buffer too short"); } cipher.processBlock(FR, 0, FRE, 0); for (int n = 0; n < blockSize; n++) out[outOff + n] = encryptByte(in[inOff + n], n); for (int n = 0; n < blockSize; n++) FR[n] = in[inOff + n]; return blockSize; } } azureus-4.3.0.6/org/bouncycastle/crypto/modes/PaddedBlockCipher.java0000644000175000017500000001616010061400652024677 0ustar adrianadrianpackage org.bouncycastle.crypto.modes; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.BufferedBlockCipher; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.InvalidCipherTextException; /** * A wrapper class that allows block ciphers to be used to process data in * a piecemeal fashion with PKCS5/PKCS7 padding. The PaddedBlockCipher * outputs a block only when the buffer is full and more data is being added, * or on a doFinal (unless the current block in the buffer is a pad block). * The padding mechanism used is the one outlined in PKCS5/PKCS7. * * @deprecated use org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher instead. */ public class PaddedBlockCipher extends BufferedBlockCipher { /** * Create a buffered block cipher with, or without, padding. * * @param cipher the underlying block cipher this buffering object wraps. */ public PaddedBlockCipher( BlockCipher cipher) { this.cipher = cipher; buf = new byte[cipher.getBlockSize()]; bufOff = 0; } /** * return the size of the output buffer required for an update plus a * doFinal with an input of len bytes. * * @param len the length of the input. * @return the space required to accommodate a call to update and doFinal * with len bytes of input. */ public int getOutputSize( int len) { int total = len + bufOff; int leftOver = total % buf.length; if (leftOver == 0) { if (forEncryption) { return total + buf.length; } return total; } return total - leftOver + buf.length; } /** * return the size of the output buffer required for an update * an input of len bytes. * * @param len the length of the input. * @return the space required to accommodate a call to update * with len bytes of input. */ public int getUpdateOutputSize( int len) { int total = len + bufOff; int leftOver = total % buf.length; if (leftOver == 0) { return total - buf.length; } return total - leftOver; } /** * process a single byte, producing an output block if neccessary. * * @param in the input byte. * @param out the space for any output that might be produced. * @param outOff the offset from which the output will be copied. * @exception DataLengthException if there isn't enough space in out. * @exception IllegalStateException if the cipher isn't initialised. */ public int processByte( byte in, byte[] out, int outOff) throws DataLengthException, IllegalStateException { int resultLen = 0; if (bufOff == buf.length) { resultLen = cipher.processBlock(buf, 0, out, outOff); bufOff = 0; } buf[bufOff++] = in; return resultLen; } /** * process an array of bytes, producing output if necessary. * * @param in the input byte array. * @param inOff the offset at which the input data starts. * @param len the number of bytes to be copied out of the input array. * @param out the space for any output that might be produced. * @param outOff the offset from which the output will be copied. * @exception DataLengthException if there isn't enough space in out. * @exception IllegalStateException if the cipher isn't initialised. */ public int processBytes( byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if (len < 0) { throw new IllegalArgumentException("Can't have a negative input length!"); } int blockSize = getBlockSize(); int length = getUpdateOutputSize(len); if (length > 0) { if ((outOff + length) > out.length) { throw new DataLengthException("output buffer too short"); } } int resultLen = 0; int gapLen = buf.length - bufOff; if (len > gapLen) { System.arraycopy(in, inOff, buf, bufOff, gapLen); resultLen += cipher.processBlock(buf, 0, out, outOff); bufOff = 0; len -= gapLen; inOff += gapLen; while (len > buf.length) { resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen); len -= blockSize; inOff += blockSize; } } System.arraycopy(in, inOff, buf, bufOff, len); bufOff += len; return resultLen; } /** * Process the last block in the buffer. If the buffer is currently * full and padding needs to be added a call to doFinal will produce * 2 * getBlockSize() bytes. * * @param out the array the block currently being held is copied into. * @param outOff the offset at which the copying starts. * @exception DataLengthException if there is insufficient space in out for * the output or we are decrypting and the input is not block size aligned. * @exception IllegalStateException if the underlying cipher is not * initialised. * @exception InvalidCipherTextException if padding is expected and not found. */ public int doFinal( byte[] out, int outOff) throws DataLengthException, IllegalStateException, InvalidCipherTextException { int blockSize = cipher.getBlockSize(); int resultLen = 0; if (forEncryption) { if (bufOff == blockSize) { if ((outOff + 2 * blockSize) > out.length) { throw new DataLengthException("output buffer too short"); } resultLen = cipher.processBlock(buf, 0, out, outOff); bufOff = 0; } // // add PKCS7 padding // byte code = (byte)(blockSize - bufOff); while (bufOff < blockSize) { buf[bufOff] = code; bufOff++; } resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen); } else { if (bufOff == blockSize) { resultLen = cipher.processBlock(buf, 0, buf, 0); bufOff = 0; } else { throw new DataLengthException("last block incomplete in decryption"); } // // remove PKCS7 padding // int count = buf[blockSize - 1] & 0xff; if ((count < 0) || (count > blockSize)) { throw new InvalidCipherTextException("pad block corrupted"); } resultLen -= count; System.arraycopy(buf, 0, out, outOff, resultLen); } reset(); return resultLen; } } azureus-4.3.0.6/org/bouncycastle/crypto/modes/CFBBlockCipher.java0000644000175000017500000001701110061400652024104 0ustar adrianadrianpackage org.bouncycastle.crypto.modes; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.params.ParametersWithIV; /** * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher. */ public class CFBBlockCipher implements BlockCipher { private byte[] IV; private byte[] cfbV; private byte[] cfbOutV; private int blockSize; private BlockCipher cipher = null; private boolean encrypting; /** * Basic constructor. * * @param cipher the block cipher to be used as the basis of the * feedback mode. * @param blockSize the block size in bits (note: a multiple of 8) */ public CFBBlockCipher( BlockCipher cipher, int bitBlockSize) { this.cipher = cipher; this.blockSize = bitBlockSize / 8; this.IV = new byte[cipher.getBlockSize()]; this.cfbV = new byte[cipher.getBlockSize()]; this.cfbOutV = new byte[cipher.getBlockSize()]; } /** * return the underlying block cipher that we are wrapping. * * @return the underlying block cipher that we are wrapping. */ public BlockCipher getUnderlyingCipher() { return cipher; } /** * Initialise the cipher and, possibly, the initialisation vector (IV). * If an IV isn't passed as part of the parameter, the IV will be all zeros. * An IV which is too short is handled in FIPS compliant fashion. * * @param forEncryption if true the cipher is initialised for * encryption, if false for decryption. * @param param the key and other data required by the cipher. * @exception IllegalArgumentException if the params argument is * inappropriate. */ public void init( boolean encrypting, CipherParameters params) throws IllegalArgumentException { this.encrypting = encrypting; if (params instanceof ParametersWithIV) { ParametersWithIV ivParam = (ParametersWithIV)params; byte[] iv = ivParam.getIV(); if (iv.length < IV.length) { // prepend the supplied IV with zeros (per FIPS PUB 81) System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length); for (int i = 0; i < IV.length - iv.length; i++) { IV[i] = 0; } } else { System.arraycopy(iv, 0, IV, 0, IV.length); } reset(); cipher.init(true, ivParam.getParameters()); } else { reset(); cipher.init(true, params); } } /** * return the algorithm name and mode. * * @return the name of the underlying algorithm followed by "/CFB" * and the block size in bits. */ public String getAlgorithmName() { return cipher.getAlgorithmName() + "/CFB" + (blockSize * 8); } /** * return the block size we are operating at. * * @return the block size we are operating at (in bytes). */ public int getBlockSize() { return blockSize; } /** * Process one block of input from the array in and write it to * the out array. * * @param in the array containing the input data. * @param inOff offset into the in array the data starts at. * @param out the array the output data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ public int processBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff); } /** * Do the appropriate processing for CFB mode encryption. * * @param in the array containing the data to be encrypted. * @param inOff offset into the in array the data starts at. * @param out the array the encrypted data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ public int encryptBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if ((inOff + blockSize) > in.length) { throw new DataLengthException("input buffer too short"); } if ((outOff + blockSize) > out.length) { throw new DataLengthException("output buffer too short"); } cipher.processBlock(cfbV, 0, cfbOutV, 0); // // XOR the cfbV with the plaintext producing the cipher text // for (int i = 0; i < blockSize; i++) { out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]); } // // change over the input block. // System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize); System.arraycopy(out, outOff, cfbV, cfbV.length - blockSize, blockSize); return blockSize; } /** * Do the appropriate processing for CFB mode decryption. * * @param in the array containing the data to be decrypted. * @param inOff offset into the in array the data starts at. * @param out the array the encrypted data will be copied into. * @param outOff the offset into the out array the output will start at. * @exception DataLengthException if there isn't enough data in in, or * space in out. * @exception IllegalStateException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ public int decryptBlock( byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if ((inOff + blockSize) > in.length) { throw new DataLengthException("input buffer too short"); } if ((outOff + blockSize) > out.length) { throw new DataLengthException("output buffer too short"); } cipher.processBlock(cfbV, 0, cfbOutV, 0); // // change over the input block. // System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize); System.arraycopy(in, inOff, cfbV, cfbV.length - blockSize, blockSize); // // XOR the cfbV with the plaintext producing the plain text // for (int i = 0; i < blockSize; i++) { out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]); } return blockSize; } /** * reset the chaining vector back to the IV and reset the underlying * cipher. */ public void reset() { System.arraycopy(IV, 0, cfbV, 0, IV.length); cipher.reset(); } } azureus-4.3.0.6/org/bouncycastle/crypto/modes/SICBlockCipher.java0000644000175000017500000000470510061400652024136 0ustar adrianadrianpackage org.bouncycastle.crypto.modes; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.params.ParametersWithIV; /** * Implements the Segmented Integer Counter (SIC) mode on top of a simple * block cipher. This mode is also known as CTR mode. */ public class SICBlockCipher implements BlockCipher { private BlockCipher cipher = null; private int blockSize; private byte[] IV; private byte[] counter; private byte[] counterOut; private boolean encrypting; /** * Basic constructor. * * @param c the block cipher to be used. */ public SICBlockCipher(BlockCipher c) { this.cipher = c; this.blockSize = cipher.getBlockSize(); this.IV = new byte[blockSize]; this.counter = new byte[blockSize]; this.counterOut = new byte[blockSize]; } /** * return the underlying block cipher that we are wrapping. * * @return the underlying block cipher that we are wrapping. */ public BlockCipher getUnderlyingCipher() { return cipher; } public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException { this.encrypting = forEncryption; if (params instanceof ParametersWithIV) { ParametersWithIV ivParam = (ParametersWithIV)params; byte[] iv = ivParam.getIV(); System.arraycopy(iv, 0, IV, 0, IV.length); reset(); cipher.init(true, ivParam.getParameters()); } } public String getAlgorithmName() { return cipher.getAlgorithmName() + "/SIC"; } public int getBlockSize() { return cipher.getBlockSize(); } public int processBlock(byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { cipher.processBlock(counter, 0, counterOut, 0); // // XOR the counterOut with the plaintext producing the cipher text // for (int i = 0; i < counterOut.length; i++) { out[outOff + i] = (byte)(counterOut[i] ^ in[inOff + i]); } int carry = 1; for (int i = counter.length - 1; i >= 0; i--) { int x = (counter[i] & 0xff) + carry; if (x > 0xff) { carry = 1; } else { carry = 0; } counter[i] = (byte)x; } return counter.length; } public void reset() { System.arraycopy(IV, 0, counter, 0, counter.length); cipher.reset(); } } azureus-4.3.0.6/org/bouncycastle/crypto/modes/CTSBlockCipher.java0000644000175000017500000001670710061400652024156 0ustar adrianadrianpackage org.bouncycastle.crypto.modes; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.BufferedBlockCipher; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.InvalidCipherTextException; /** * A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to * be used to produce cipher text which is the same length as the plain text. */ public class CTSBlockCipher extends BufferedBlockCipher { private int blockSize; /** * Create a buffered block cipher that uses Cipher Text Stealing * * @param cipher the underlying block cipher this buffering object wraps. */ public CTSBlockCipher( BlockCipher cipher) { if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher)) { throw new IllegalArgumentException("CTSBlockCipher can only accept ECB, or CBC ciphers"); } this.cipher = cipher; blockSize = cipher.getBlockSize(); buf = new byte[blockSize * 2]; bufOff = 0; } /** * return the size of the output buffer required for an update * an input of len bytes. * * @param len the length of the input. * @return the space required to accommodate a call to update * with len bytes of input. */ public int getUpdateOutputSize( int len) { int total = len + bufOff; int leftOver = total % buf.length; if (leftOver == 0) { return total - buf.length; } return total - leftOver; } /** * return the size of the output buffer required for an update plus a * doFinal with an input of len bytes. * * @param len the length of the input. * @return the space required to accommodate a call to update and doFinal * with len bytes of input. */ public int getOutputSize( int len) { return len + bufOff; } /** * process a single byte, producing an output block if neccessary. * * @param in the input byte. * @param out the space for any output that might be produced. * @param outOff the offset from which the output will be copied. * @return the number of output bytes copied to out. * @exception DataLengthException if there isn't enough space in out. * @exception IllegalStateException if the cipher isn't initialised. */ public int processByte( byte in, byte[] out, int outOff) throws DataLengthException, IllegalStateException { int resultLen = 0; if (bufOff == buf.length) { resultLen = cipher.processBlock(buf, 0, out, outOff); System.arraycopy(buf, blockSize, buf, 0, blockSize); bufOff = blockSize; } buf[bufOff++] = in; return resultLen; } /** * process an array of bytes, producing output if necessary. * * @param in the input byte array. * @param inOff the offset at which the input data starts. * @param len the number of bytes to be copied out of the input array. * @param out the space for any output that might be produced. * @param outOff the offset from which the output will be copied. * @return the number of output bytes copied to out. * @exception DataLengthException if there isn't enough space in out. * @exception IllegalStateException if the cipher isn't initialised. */ public int processBytes( byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException, IllegalStateException { if (len < 0) { throw new IllegalArgumentException("Can't have a negative input length!"); } int blockSize = getBlockSize(); int length = getUpdateOutputSize(len); if (length > 0) { if ((outOff + length) > out.length) { throw new DataLengthException("output buffer too short"); } } int resultLen = 0; int gapLen = buf.length - bufOff; if (len > gapLen) { System.arraycopy(in, inOff, buf, bufOff, gapLen); resultLen += cipher.processBlock(buf, 0, out, outOff); System.arraycopy(buf, blockSize, buf, 0, blockSize); bufOff = blockSize; len -= gapLen; inOff += gapLen; while (len > blockSize) { System.arraycopy(in, inOff, buf, bufOff, blockSize); resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen); System.arraycopy(buf, blockSize, buf, 0, blockSize); len -= blockSize; inOff += blockSize; } } System.arraycopy(in, inOff, buf, bufOff, len); bufOff += len; return resultLen; } /** * Process the last block in the buffer. * * @param out the array the block currently being held is copied into. * @param outOff the offset at which the copying starts. * @return the number of output bytes copied to out. * @exception DataLengthException if there is insufficient space in out for * the output. * @exception IllegalStateException if the underlying cipher is not * initialised. * @exception InvalidCipherTextException if cipher text decrypts wrongly (in * case the exception will never get thrown). */ public int doFinal( byte[] out, int outOff) throws DataLengthException, IllegalStateException, InvalidCipherTextException { if (bufOff + outOff > out.length) { throw new DataLengthException("output buffer to small in doFinal"); } int blockSize = cipher.getBlockSize(); int len = bufOff - blockSize; byte[] block = new byte[blockSize]; if (forEncryption) { cipher.processBlock(buf, 0, block, 0); for (int i = bufOff; i != buf.length; i++) { buf[i] = block[i - blockSize]; } for (int i = blockSize; i != bufOff; i++) { buf[i] ^= block[i - blockSize]; } if (cipher instanceof CBCBlockCipher) { BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher(); c.processBlock(buf, blockSize, out, outOff); } else { cipher.processBlock(buf, blockSize, out, outOff); } System.arraycopy(block, 0, out, outOff + blockSize, len); } else { byte[] lastBlock = new byte[blockSize]; if (cipher instanceof CBCBlockCipher) { BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher(); c.processBlock(buf, 0, block, 0); } else { cipher.processBlock(buf, 0, block, 0); } for (int i = blockSize; i != bufOff; i++) { lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]); } System.arraycopy(buf, blockSize, block, 0, len); cipher.processBlock(block, 0, out, outOff); System.arraycopy(lastBlock, 0, out, outOff + blockSize, len); } int offset = bufOff; reset(); return offset; } } azureus-4.3.0.6/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java0000644000175000017500000000174510061400652025041 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * a holding class for public/private parameter pairs. */ public class AsymmetricCipherKeyPair { private CipherParameters publicParam; private CipherParameters privateParam; /** * basic constructor. * * @param publicParam a public key parameters object. * @param privateParam the corresponding private key parameters. */ public AsymmetricCipherKeyPair( CipherParameters publicParam, CipherParameters privateParam) { this.publicParam = publicParam; this.privateParam = privateParam; } /** * return the public key parameters. * * @return the public key parameters. */ public CipherParameters getPublic() { return publicParam; } /** * return the private key parameters. * * @return the private key parameters. */ public CipherParameters getPrivate() { return privateParam; } } azureus-4.3.0.6/org/bouncycastle/crypto/DataLengthException.java0000644000175000017500000000127111012742212024166 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * this exception is thrown if a buffer that is meant to have output * copied into it turns out to be too short, or if we've been given * insufficient input. In general this exception will get thrown rather * than an ArrayOutOfBounds exception. */ public class DataLengthException extends RuntimeCryptoException { /** * base constructor. */ public DataLengthException() { } /** * create a DataLengthException with the given message. * * @param message the message to be carried with the exception. */ public DataLengthException( String message) { super(message); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/0000755000175000017500000000000011310377634021616 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java0000644000175000017500000000306710061400652026077 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import java.math.BigInteger; import java.security.SecureRandom; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; import org.bouncycastle.crypto.KeyGenerationParameters; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECKeyGenerationParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.math.ec.ECConstants; import org.bouncycastle.math.ec.ECPoint; public class ECKeyPairGenerator implements AsymmetricCipherKeyPairGenerator, ECConstants { ECDomainParameters params; SecureRandom random; public void init( KeyGenerationParameters param) { ECKeyGenerationParameters ecP = (ECKeyGenerationParameters)param; this.random = ecP.getRandom(); this.params = ecP.getDomainParameters(); } /** * Given the domain parameters this routine generates an EC key * pair in accordance with X9.62 section 5.2.1 pages 26, 27. */ public AsymmetricCipherKeyPair generateKeyPair() { BigInteger n = params.getN(); int nBitLength = n.bitLength(); BigInteger d; do { d = new BigInteger(nBitLength, random); } while (d.equals(ZERO) || (d.compareTo(n) >= 0)); ECPoint Q = params.getG().multiply(d); return new AsymmetricCipherKeyPair( new ECPublicKeyParameters(Q, params), new ECPrivateKeyParameters(d, params)); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/DESKeyGenerator.java0000644000175000017500000000100610061400652025376 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import org.bouncycastle.crypto.CipherKeyGenerator; import org.bouncycastle.crypto.params.DESParameters; public class DESKeyGenerator extends CipherKeyGenerator { public byte[] generateKey() { byte[] newKey = new byte[DESParameters.DES_KEY_LENGTH]; do { random.nextBytes(newKey); DESParameters.setOddParity(newKey); } while (DESParameters.isWeakKey(newKey, 0)); return newKey; } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java0000644000175000017500000000733710061400652027404 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.PBEParametersGenerator; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; /** * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 1. * Note this generator is limited to the size of the hash produced by the * digest used to drive it. *

      * The document this implementation is based on can be found at * * RSA's PKCS5 Page */ public class PKCS5S1ParametersGenerator extends PBEParametersGenerator { private Digest digest; /** * Construct a PKCS 5 Scheme 1 Parameters generator. * * @param digest the digest to be used as the source of derived keys. */ public PKCS5S1ParametersGenerator( Digest digest) { this.digest = digest; } /** * the derived key function, the ith hash of the password and the salt. */ private byte[] generateDerivedKey() { byte[] digestBytes = new byte[digest.getDigestSize()]; digest.update(password, 0, password.length); digest.update(salt, 0, salt.length); digest.doFinal(digestBytes, 0); for (int i = 1; i < iterationCount; i++) { digest.update(digestBytes, 0, digestBytes.length); digest.doFinal(digestBytes, 0); } return digestBytes; } /** * Generate a key parameter derived from the password, salt, and iteration * count we are currently initialised with. * * @param keySize the size of the key we want (in bits) * @return a KeyParameter object. * @exception IllegalArgumentException if the key length larger than the base hash size. */ public CipherParameters generateDerivedParameters( int keySize) { keySize = keySize / 8; if (keySize > digest.getDigestSize()) { throw new IllegalArgumentException( "Can't generate a derived key " + keySize + " bytes long."); } byte[] dKey = generateDerivedKey(); return new KeyParameter(dKey, 0, keySize); } /** * Generate a key with initialisation vector parameter derived from * the password, salt, and iteration count we are currently initialised * with. * * @param keySize the size of the key we want (in bits) * @param ivSize the size of the iv we want (in bits) * @return a ParametersWithIV object. * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size. */ public CipherParameters generateDerivedParameters( int keySize, int ivSize) { keySize = keySize / 8; ivSize = ivSize / 8; if ((keySize + ivSize) > digest.getDigestSize()) { throw new IllegalArgumentException( "Can't generate a derived key " + (keySize + ivSize) + " bytes long."); } byte[] dKey = generateDerivedKey(); return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize); } /** * Generate a key parameter for use with a MAC derived from the password, * salt, and iteration count we are currently initialised with. * * @param keySize the size of the key we want (in bits) * @return a KeyParameter object. * @exception IllegalArgumentException if the key length larger than the base hash size. */ public CipherParameters generateDerivedMacParameters( int keySize) { return generateDerivedParameters(keySize); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java0000644000175000017500000000315110061400652026057 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import org.bouncycastle.crypto.KeyGenerationParameters; import org.bouncycastle.crypto.params.DESedeParameters; public class DESedeKeyGenerator extends DESKeyGenerator { /** * initialise the key generator - if strength is set to zero * the key generated will be 192 bits in size, otherwise * strength can be 128 or 192 (or 112 or 168 if you don't count * parity bits), depending on whether you wish to do 2-key or 3-key * triple DES. * * @param param the parameters to be used for key generation */ public void init( KeyGenerationParameters param) { super.init(param); if (strength == 0 || strength == (168 / 8)) { strength = DESedeParameters.DES_EDE_KEY_LENGTH; } else if (strength == (112 / 8)) { strength = 2 * DESedeParameters.DES_KEY_LENGTH; } else if (strength != DESedeParameters.DES_EDE_KEY_LENGTH && strength != (2 * DESedeParameters.DES_KEY_LENGTH)) { throw new IllegalArgumentException("DESede key must be " + (DESedeParameters.DES_EDE_KEY_LENGTH * 8) + " or " + (2 * 8 * DESedeParameters.DES_KEY_LENGTH) + " bits long."); } } public byte[] generateKey() { byte[] newKey = new byte[strength]; do { random.nextBytes(newKey); DESedeParameters.setOddParity(newKey); } while (DESedeParameters.isWeakKey(newKey, 0, newKey.length)); return newKey; } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/KDF2BytesGenerator.java0000644000175000017500000000120210777355062026027 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import org.bouncycastle.crypto.Digest; /** * KFD2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033 *
      * This implementation is based on IEEE P1363/ISO 18033. */ public class KDF2BytesGenerator extends BaseKDFBytesGenerator { /** * Construct a KDF2 bytes generator. Generates key material * according to IEEE P1363 or ISO 18033 depending on the initialisation. *

      * @param digest the digest to be used as the source of derived keys. */ public KDF2BytesGenerator( Digest digest) { super(1, digest); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java0000644000175000017500000000312410061400652027104 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import java.math.BigInteger; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; import org.bouncycastle.crypto.KeyGenerationParameters; import org.bouncycastle.crypto.params.ElGamalKeyGenerationParameters; import org.bouncycastle.crypto.params.ElGamalParameters; import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters; import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters; /** * a ElGamal key pair generator. *

      * This generates keys consistent for use with ElGamal as described in * page 164 of "Handbook of Applied Cryptography". */ public class ElGamalKeyPairGenerator implements AsymmetricCipherKeyPairGenerator { private ElGamalKeyGenerationParameters param; public void init( KeyGenerationParameters param) { this.param = (ElGamalKeyGenerationParameters)param; } public AsymmetricCipherKeyPair generateKeyPair() { BigInteger p, g, x, y; int qLength = param.getStrength() - 1; ElGamalParameters elParams = param.getParameters(); p = elParams.getP(); g = elParams.getG(); // // calculate the private key // x = new BigInteger(qLength, param.getRandom()); // // calculate the public key. // y = g.modPow(x, p); return new AsymmetricCipherKeyPair( new ElGamalPublicKeyParameters(y, elParams), new ElGamalPrivateKeyParameters(x, elParams)); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/DHBasicKeyPairGenerator.java0000644000175000017500000000300510061400652027035 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import java.math.BigInteger; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; import org.bouncycastle.crypto.KeyGenerationParameters; import org.bouncycastle.crypto.params.DHKeyGenerationParameters; import org.bouncycastle.crypto.params.DHParameters; import org.bouncycastle.crypto.params.DHPrivateKeyParameters; import org.bouncycastle.crypto.params.DHPublicKeyParameters; /** * a basic Diffie-Helman key pair generator. * * This generates keys consistent for use with the basic algorithm for * Diffie-Helman. */ public class DHBasicKeyPairGenerator implements AsymmetricCipherKeyPairGenerator { private DHKeyGenerationParameters param; public void init( KeyGenerationParameters param) { this.param = (DHKeyGenerationParameters)param; } public AsymmetricCipherKeyPair generateKeyPair() { BigInteger p, g, x, y; int qLength = param.getStrength() - 1; DHParameters dhParams = param.getParameters(); p = dhParams.getP(); g = dhParams.getG(); // // calculate the private key // x = new BigInteger(qLength, param.getRandom()); // // calculate the public key. // y = g.modPow(x, p); return new AsymmetricCipherKeyPair( new DHPublicKeyParameters(y, dhParams), new DHPrivateKeyParameters(x, dhParams)); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java0000644000175000017500000000357310061400652027653 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import java.math.BigInteger; import java.security.SecureRandom; import org.bouncycastle.crypto.params.ElGamalParameters; public class ElGamalParametersGenerator { private int size; private int certainty; private SecureRandom random; private static BigInteger ONE = BigInteger.valueOf(1); private static BigInteger TWO = BigInteger.valueOf(2); public void init( int size, int certainty, SecureRandom random) { this.size = size; this.certainty = certainty; this.random = random; } /** * which generates the p and g values from the given parameters, * returning the ElGamalParameters object. *

      * Note: can take a while... */ public ElGamalParameters generateParameters() { BigInteger g, p, q; int qLength = size - 1; // // find a safe prime p where p = 2*q + 1, where p and q are prime. // for (;;) { q = new BigInteger(qLength, 1, random); if (q.bitLength() != qLength) { continue; } if (!q.isProbablePrime(certainty)) { continue; } p = q.multiply(TWO).add(ONE); if (p.isProbablePrime(certainty)) { break; } } // // calculate the generator g - the advantage of using the 2q+1 // approach is that we know the prime factorisation of (p - 1)... // for (;;) { g = new BigInteger(qLength, random); if (g.modPow(TWO, p).equals(ONE)) { continue; } if (g.modPow(q, p).equals(ONE)) { continue; } break; } return new ElGamalParameters(p, g); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java0000644000175000017500000000630410061400652026232 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import java.math.BigInteger; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; import org.bouncycastle.crypto.KeyGenerationParameters; import org.bouncycastle.crypto.params.RSAKeyGenerationParameters; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; /** * an RSA key pair generator. */ public class RSAKeyPairGenerator implements AsymmetricCipherKeyPairGenerator { private static BigInteger ONE = BigInteger.valueOf(1); private RSAKeyGenerationParameters param; public void init( KeyGenerationParameters param) { this.param = (RSAKeyGenerationParameters)param; } public AsymmetricCipherKeyPair generateKeyPair() { BigInteger p, q, n, d, e, pSub1, qSub1, phi; // // p and q values should have a length of half the strength in bits // int pbitlength = (param.getStrength() + 1) / 2; int qbitlength = (param.getStrength() - pbitlength); e = param.getPublicExponent(); // // generate p, prime and (p-1) relatively prime to e // for (;;) { p = new BigInteger(pbitlength, 1, param.getRandom()); if (p.mod(e).equals(ONE)) { continue; } if (!p.isProbablePrime(param.getCertainty())) { continue; } if (e.gcd(p.subtract(ONE)).equals(ONE)) { break; } } // // generate a modulus of the required length // for (;;) { // generate q, prime and (q-1) relatively prime to e, // and not equal to p // for (;;) { q = new BigInteger(qbitlength, 1, param.getRandom()); if (q.equals(p)) { continue; } if (q.mod(e).equals(ONE)) { continue; } if (!q.isProbablePrime(param.getCertainty())) { continue; } if (e.gcd(q.subtract(ONE)).equals(ONE)) { break; } } // // calculate the modulus // n = p.multiply(q); if (n.bitLength() == param.getStrength()) { break; } // // if we get here our primes aren't big enough, make the largest // of the two p and try again // p = p.max(q); } if (p.compareTo(q) < 0) { phi = p; p = q; q = phi; } pSub1 = p.subtract(ONE); qSub1 = q.subtract(ONE); phi = pSub1.multiply(qSub1); // // calculate the private exponent // d = e.modInverse(phi); // // calculate the CRT factors // BigInteger dP, dQ, qInv; dP = d.remainder(pSub1); dQ = d.remainder(qSub1); qInv = q.modInverse(p); return new AsymmetricCipherKeyPair( new RSAKeyParameters(false, n, e), new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv)); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/DSAParametersGenerator.java0000644000175000017500000001151410061400652026752 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import java.math.BigInteger; import java.security.SecureRandom; import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.crypto.params.DSAParameters; import org.bouncycastle.crypto.params.DSAValidationParameters; /** * generate suitable parameters for DSA, in line with FIPS 186-2. */ public class DSAParametersGenerator { private int size; private int certainty; private SecureRandom random; private static BigInteger ONE = BigInteger.valueOf(1); private static BigInteger TWO = BigInteger.valueOf(2); /** * initialise the key generator. * * @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments) * @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80). * @param random random byte source. */ public void init( int size, int certainty, SecureRandom random) { this.size = size; this.certainty = certainty; this.random = random; } /** * add value to b, returning the result in a. The a value is treated * as a BigInteger of length (a.length * 8) bits. The result is * modulo 2^a.length in case of overflow. */ private void add( byte[] a, byte[] b, int value) { int x = (b[b.length - 1] & 0xff) + value; a[b.length - 1] = (byte)x; x >>>= 8; for (int i = b.length - 2; i >= 0; i--) { x += (b[i] & 0xff); a[i] = (byte)x; x >>>= 8; } } /** * which generates the p and g values from the given parameters, * returning the DSAParameters object. *

      * Note: can take a while... */ public DSAParameters generateParameters() { byte[] seed = new byte[20]; byte[] part1 = new byte[20]; byte[] part2 = new byte[20]; byte[] u = new byte[20]; SHA1Digest sha1 = new SHA1Digest(); int n = (size - 1) / 160; byte[] w = new byte[size / 8]; BigInteger q = null, p = null, g = null; int counter = 0; boolean primesFound = false; while (!primesFound) { do { random.nextBytes(seed); sha1.update(seed, 0, seed.length); sha1.doFinal(part1, 0); System.arraycopy(seed, 0, part2, 0, seed.length); add(part2, seed, 1); sha1.update(part2, 0, part2.length); sha1.doFinal(part2, 0); for (int i = 0; i != u.length; i++) { u[i] = (byte)(part1[i] ^ part2[i]); } u[0] |= (byte)0x80; u[19] |= (byte)0x01; q = new BigInteger(1, u); } while (!q.isProbablePrime(certainty)); counter = 0; int offset = 2; while (counter < 4096) { for (int k = 0; k < n; k++) { add(part1, seed, offset + k); sha1.update(part1, 0, part1.length); sha1.doFinal(part1, 0); System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length, part1.length); } add(part1, seed, offset + n); sha1.update(part1, 0, part1.length); sha1.doFinal(part1, 0); System.arraycopy(part1, part1.length - ((w.length - (n) * part1.length)), w, 0, w.length - n * part1.length); w[0] |= (byte)0x80; BigInteger x = new BigInteger(1, w); BigInteger c = x.mod(q.multiply(TWO)); p = x.subtract(c.subtract(ONE)); if (p.testBit(size - 1)) { if (p.isProbablePrime(certainty)) { primesFound = true; break; } } counter += 1; offset += n + 1; } } // // calculate the generator g // BigInteger pMinusOneOverQ = p.subtract(ONE).divide(q); for (;;) { BigInteger h = new BigInteger(size, random); if (h.compareTo(ONE) <= 0 || h.compareTo(p.subtract(ONE)) >= 0) { continue; } g = h.modPow(pMinusOneOverQ, p); if (g.compareTo(ONE) <= 0) { continue; } break; } return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter)); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java0000644000175000017500000000320110061400652026205 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import java.math.BigInteger; import java.security.SecureRandom; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; import org.bouncycastle.crypto.KeyGenerationParameters; import org.bouncycastle.crypto.params.DSAKeyGenerationParameters; import org.bouncycastle.crypto.params.DSAParameters; import org.bouncycastle.crypto.params.DSAPrivateKeyParameters; import org.bouncycastle.crypto.params.DSAPublicKeyParameters; /** * a DSA key pair generator. * * This generates DSA keys in line with the method described * in FIPS 186-2. */ public class DSAKeyPairGenerator implements AsymmetricCipherKeyPairGenerator { private static BigInteger ZERO = BigInteger.valueOf(0); private DSAKeyGenerationParameters param; public void init( KeyGenerationParameters param) { this.param = (DSAKeyGenerationParameters)param; } public AsymmetricCipherKeyPair generateKeyPair() { BigInteger p, q, g, x, y; DSAParameters dsaParams = param.getParameters(); SecureRandom random = param.getRandom(); q = dsaParams.getQ(); p = dsaParams.getP(); g = dsaParams.getG(); do { x = new BigInteger(160, random); } while (x.equals(ZERO) || x.compareTo(q) >= 0); // // calculate the public key. // y = g.modPow(x, p); return new AsymmetricCipherKeyPair( new DSAPublicKeyParameters(y, dsaParams), new DSAPrivateKeyParameters(x, dsaParams)); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/MGF1BytesGenerator.java0000644000175000017500000000514210061400652026020 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.DerivationFunction; import org.bouncycastle.crypto.DerivationParameters; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.params.MGFParameters; /** * Generator for MGF1 as defined in PKCS 1v2 */ public class MGF1BytesGenerator implements DerivationFunction { private Digest digest; private byte[] seed; private int hLen; /** * @param digest the digest to be used as the source of generated bytes */ public MGF1BytesGenerator( Digest digest) { this.digest = digest; this.hLen = digest.getDigestSize(); } public void init( DerivationParameters param) { if (!(param instanceof MGFParameters)) { throw new IllegalArgumentException("MGF parameters required for MGF1Generator"); } MGFParameters p = (MGFParameters)param; seed = p.getSeed(); } /** * return the underlying digest. */ public Digest getDigest() { return digest; } /** * int to octet string. */ private void ItoOSP( int i, byte[] sp) { sp[0] = (byte)(i >>> 24); sp[1] = (byte)(i >>> 16); sp[2] = (byte)(i >>> 8); sp[3] = (byte)(i >>> 0); } /** * fill len bytes of the output buffer with bytes generated from * the derivation function. * * @throws IllegalArgumentException if the size of the request will cause an overflow. * @throws DataLengthException if the out buffer is too small. */ public int generateBytes( byte[] out, int outOff, int len) throws DataLengthException, IllegalArgumentException { byte[] hashBuf = new byte[hLen]; byte[] C = new byte[4]; int counter = 0; digest.reset(); do { ItoOSP(counter, C); digest.update(seed, 0, seed.length); digest.update(C, 0, C.length); digest.doFinal(hashBuf, 0); System.arraycopy(hashBuf, 0, out, outOff + counter * hLen, hLen); } while (++counter < (len / hLen)); if ((counter * hLen) < len) { ItoOSP(counter, C); digest.update(seed, 0, seed.length); digest.update(C, 0, C.length); digest.doFinal(hashBuf, 0); System.arraycopy(hashBuf, 0, out, outOff + counter * hLen, len - (counter * hLen)); } return len; } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java0000644000175000017500000001433210061400652027247 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.PBEParametersGenerator; import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.crypto.digests.RIPEMD160Digest; import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; /** * Generator for PBE derived keys and ivs as defined by PKCS 12 V1.0. *

      * The document this implementation is based on can be found at * * RSA's PKCS12 Page */ public class PKCS12ParametersGenerator extends PBEParametersGenerator { public static final int KEY_MATERIAL = 1; public static final int IV_MATERIAL = 2; public static final int MAC_MATERIAL = 3; private Digest digest; private int u; private int v; /** * Construct a PKCS 12 Parameters generator. This constructor will * accept MD5, SHA1, and RIPEMD160. * * @param digest the digest to be used as the source of derived keys. * @exception IllegalArgumentException if an unknown digest is passed in. */ public PKCS12ParametersGenerator( Digest digest) { this.digest = digest; if (digest instanceof MD5Digest) { u = 128 / 8; v = 512 / 8; } else if (digest instanceof SHA1Digest) { u = 160 / 8; v = 512 / 8; } else if (digest instanceof RIPEMD160Digest) { u = 160 / 8; v = 512 / 8; } else { throw new IllegalArgumentException("Digest " + digest.getAlgorithmName() + " unsupported"); } } /** * add a + b + 1, returning the result in a. The a value is treated * as a BigInteger of length (b.length * 8) bits. The result is * modulo 2^b.length in case of overflow. */ private void adjust( byte[] a, int aOff, byte[] b) { int x = (b[b.length - 1] & 0xff) + (a[aOff + b.length - 1] & 0xff) + 1; a[aOff + b.length - 1] = (byte)x; x >>>= 8; for (int i = b.length - 2; i >= 0; i--) { x += (b[i] & 0xff) + (a[aOff + i] & 0xff); a[aOff + i] = (byte)x; x >>>= 8; } } /** * generation of a derived key ala PKCS12 V1.0. */ private byte[] generateDerivedKey( int idByte, int n) { byte[] D = new byte[v]; byte[] dKey = new byte[n]; for (int i = 0; i != D.length; i++) { D[i] = (byte)idByte; } byte[] S; if ((salt != null) && (salt.length != 0)) { S = new byte[v * ((salt.length + v - 1) / v)]; for (int i = 0; i != S.length; i++) { S[i] = salt[i % salt.length]; } } else { S = new byte[0]; } byte[] P; if ((password != null) && (password.length != 0)) { P = new byte[v * ((password.length + v - 1) / v)]; for (int i = 0; i != P.length; i++) { P[i] = password[i % password.length]; } } else { P = new byte[0]; } byte[] I = new byte[S.length + P.length]; System.arraycopy(S, 0, I, 0, S.length); System.arraycopy(P, 0, I, S.length, P.length); byte[] B = new byte[v]; int c = (n + u - 1) / u; for (int i = 1; i <= c; i++) { byte[] A = new byte[u]; digest.update(D, 0, D.length); digest.update(I, 0, I.length); digest.doFinal(A, 0); for (int j = 1; j != iterationCount; j++) { digest.update(A, 0, A.length); digest.doFinal(A, 0); } for (int j = 0; j != B.length; j++) { B[j] = A[j % A.length]; } for (int j = 0; j != I.length / v; j++) { adjust(I, j * v, B); } if (i == c) { System.arraycopy(A, 0, dKey, (i - 1) * u, dKey.length - ((i - 1) * u)); } else { System.arraycopy(A, 0, dKey, (i - 1) * u, A.length); } } return dKey; } /** * Generate a key parameter derived from the password, salt, and iteration * count we are currently initialised with. * * @param keySize the size of the key we want (in bits) * @return a KeyParameter object. */ public CipherParameters generateDerivedParameters( int keySize) { keySize = keySize / 8; byte[] dKey = generateDerivedKey(KEY_MATERIAL, keySize); return new KeyParameter(dKey, 0, keySize); } /** * Generate a key with initialisation vector parameter derived from * the password, salt, and iteration count we are currently initialised * with. * * @param keySize the size of the key we want (in bits) * @param ivSize the size of the iv we want (in bits) * @return a ParametersWithIV object. */ public CipherParameters generateDerivedParameters( int keySize, int ivSize) { keySize = keySize / 8; ivSize = ivSize / 8; byte[] dKey = generateDerivedKey(KEY_MATERIAL, keySize); byte[] iv = generateDerivedKey(IV_MATERIAL, ivSize); return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), iv, 0, ivSize); } /** * Generate a key parameter for use with a MAC derived from the password, * salt, and iteration count we are currently initialised with. * * @param keySize the size of the key we want (in bits) * @return a KeyParameter object. */ public CipherParameters generateDerivedMacParameters( int keySize) { keySize = keySize / 8; byte[] dKey = generateDerivedKey(MAC_MATERIAL, keySize); return new KeyParameter(dKey, 0, keySize); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java0000644000175000017500000000745310777355062026556 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.DerivationFunction; import org.bouncycastle.crypto.DerivationParameters; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.params.ISO18033KDFParameters; import org.bouncycastle.crypto.params.KDFParameters; /** * Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033 *
      * This implementation is based on ISO 18033/P1363a. */ public class BaseKDFBytesGenerator implements DerivationFunction { private int counterStart; private Digest digest; private byte[] shared; private byte[] iv; /** * Construct a KDF Parameters generator. *

      * @param counterStart value of counter. * @param digest the digest to be used as the source of derived keys. */ protected BaseKDFBytesGenerator( int counterStart, Digest digest) { this.counterStart = counterStart; this.digest = digest; } public void init( DerivationParameters param) { if (param instanceof KDFParameters) { KDFParameters p = (KDFParameters)param; shared = p.getSharedSecret(); iv = p.getIV(); } else if (param instanceof ISO18033KDFParameters) { ISO18033KDFParameters p = (ISO18033KDFParameters)param; shared = p.getSeed(); iv = null; } else { throw new IllegalArgumentException("KDF parameters required for KDF2Generator"); } } /** * return the underlying digest. */ public Digest getDigest() { return digest; } /** * fill len bytes of the output buffer with bytes generated from * the derivation function. * * @throws IllegalArgumentException if the size of the request will cause an overflow. * @throws DataLengthException if the out buffer is too small. */ public int generateBytes( byte[] out, int outOff, int len) throws DataLengthException, IllegalArgumentException { if ((out.length - len) < outOff) { throw new DataLengthException("output buffer too small"); } long oBytes = len; int outLen = digest.getDigestSize(); // // this is at odds with the standard implementation, the // maximum value should be hBits * (2^32 - 1) where hBits // is the digest output size in bits. We can't have an // array with a long index at the moment... // if (oBytes > ((2L << 32) - 1)) { throw new IllegalArgumentException("Output length too large"); } int cThreshold = (int)((oBytes + outLen - 1) / outLen); byte[] dig = null; dig = new byte[digest.getDigestSize()]; int counter = counterStart; for (int i = 0; i < cThreshold; i++) { digest.update(shared, 0, shared.length); digest.update((byte)(counter >> 24)); digest.update((byte)(counter >> 16)); digest.update((byte)(counter >> 8)); digest.update((byte)counter); if (iv != null) { digest.update(iv, 0, iv.length); } digest.doFinal(dig, 0); if (len > outLen) { System.arraycopy(dig, 0, out, outOff, outLen); outOff += outLen; len -= outLen; } else { System.arraycopy(dig, 0, out, outOff, len); } counter++; } digest.reset(); return len; } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/DHParametersGenerator.java0000644000175000017500000000335510061400652026642 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import java.math.BigInteger; import java.security.SecureRandom; import org.bouncycastle.crypto.params.DHParameters; public class DHParametersGenerator { private int size; private int certainty; private SecureRandom random; private static BigInteger ONE = BigInteger.valueOf(1); private static BigInteger TWO = BigInteger.valueOf(2); public void init( int size, int certainty, SecureRandom random) { this.size = size; this.certainty = certainty; this.random = random; } /** * which generates the p and g values from the given parameters, * returning the DHParameters object. *

      * Note: can take a while... */ public DHParameters generateParameters() { BigInteger g, p, q; int qLength = size - 1; // // find a safe prime p where p = 2*q + 1, where p and q are prime. // for (;;) { q = new BigInteger(qLength, certainty, random); p = q.multiply(TWO).add(ONE); if (p.isProbablePrime(certainty)) { break; } } // // calculate the generator g - the advantage of using the 2q+1 // approach is that we know the prime factorisation of (p - 1)... // for (;;) { g = new BigInteger(qLength, random); if (g.modPow(TWO, p).equals(ONE)) { continue; } if (g.modPow(q, p).equals(ONE)) { continue; } break; } return new DHParameters(p, g, q, 2); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java0000644000175000017500000000745311026315700030165 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.PBEParametersGenerator; import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; /** * Generator for PBE derived keys and ivs as usd by OpenSSL. *

      * The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an * iteration count of 1. *

      */ public class OpenSSLPBEParametersGenerator extends PBEParametersGenerator { private Digest digest = new MD5Digest(); /** * Construct a OpenSSL Parameters generator. */ public OpenSSLPBEParametersGenerator() { } /** * Initialise - note the iteration count for this algorithm is fixed at 1. * * @param password password to use. * @param salt salt to use. */ public void init( byte[] password, byte[] salt) { super.init(password, salt, 1); } /** * the derived key function, the ith hash of the password and the salt. */ private byte[] generateDerivedKey( int bytesNeeded) { byte[] buf = new byte[digest.getDigestSize()]; byte[] key = new byte[bytesNeeded]; int offset = 0; for (;;) { digest.update(password, 0, password.length); digest.update(salt, 0, salt.length); digest.doFinal(buf, 0); int len = (bytesNeeded > buf.length) ? buf.length : bytesNeeded; System.arraycopy(buf, 0, key, offset, len); offset += len; // check if we need any more bytesNeeded -= len; if (bytesNeeded == 0) { break; } // do another round digest.reset(); digest.update(buf, 0, buf.length); } return key; } /** * Generate a key parameter derived from the password, salt, and iteration * count we are currently initialised with. * * @param keySize the size of the key we want (in bits) * @return a KeyParameter object. * @exception IllegalArgumentException if the key length larger than the base hash size. */ public CipherParameters generateDerivedParameters( int keySize) { keySize = keySize / 8; byte[] dKey = generateDerivedKey(keySize); return new KeyParameter(dKey, 0, keySize); } /** * Generate a key with initialisation vector parameter derived from * the password, salt, and iteration count we are currently initialised * with. * * @param keySize the size of the key we want (in bits) * @param ivSize the size of the iv we want (in bits) * @return a ParametersWithIV object. * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size. */ public CipherParameters generateDerivedParameters( int keySize, int ivSize) { keySize = keySize / 8; ivSize = ivSize / 8; byte[] dKey = generateDerivedKey(keySize + ivSize); return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize); } /** * Generate a key parameter for use with a MAC derived from the password, * salt, and iteration count we are currently initialised with. * * @param keySize the size of the key we want (in bits) * @return a KeyParameter object. * @exception IllegalArgumentException if the key length larger than the base hash size. */ public CipherParameters generateDerivedMacParameters( int keySize) { return generateDerivedParameters(keySize); } } azureus-4.3.0.6/org/bouncycastle/crypto/generators/DHKeyPairGenerator.java0000644000175000017500000000306510061400652026101 0ustar adrianadrianpackage org.bouncycastle.crypto.generators; import java.math.BigInteger; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; import org.bouncycastle.crypto.KeyGenerationParameters; import org.bouncycastle.crypto.params.DHKeyGenerationParameters; import org.bouncycastle.crypto.params.DHParameters; import org.bouncycastle.crypto.params.DHPrivateKeyParameters; import org.bouncycastle.crypto.params.DHPublicKeyParameters; /** * a Diffie-Helman key pair generator. * * This generates keys consistent for use in the MTI/A0 key agreement protocol * as described in "Handbook of Applied Cryptography", Pages 516-519. */ public class DHKeyPairGenerator implements AsymmetricCipherKeyPairGenerator { private DHKeyGenerationParameters param; public void init( KeyGenerationParameters param) { this.param = (DHKeyGenerationParameters)param; } public AsymmetricCipherKeyPair generateKeyPair() { BigInteger p, g, x, y; int qLength = param.getStrength() - 1; DHParameters dhParams = param.getParameters(); p = dhParams.getP(); g = dhParams.getG(); // // calculate the private key // x = new BigInteger(qLength, param.getRandom()); // // calculate the public key. // y = g.modPow(x, p); return new AsymmetricCipherKeyPair( new DHPublicKeyParameters(y, dhParams), new DHPrivateKeyParameters(x, dhParams)); } } azureus-4.3.0.6/org/bouncycastle/crypto/agreement/0000755000175000017500000000000011310377632021412 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java0000644000175000017500000000274410407566336025570 0ustar adrianadrianpackage org.bouncycastle.crypto.agreement; import java.math.BigInteger; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.crypto.BasicAgreement; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; /** * P1363 7.2.1 ECSVDP-DH * * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive, * Diffie-Hellman version. It is based on the work of [DH76], [Mil86], * and [Kob87]. This primitive derives a shared secret value from one * party's private key and another party's public key, where both have * the same set of EC domain parameters. If two parties correctly * execute this primitive, they will produce the same output. This * primitive can be invoked by a scheme to derive a shared secret key; * specifically, it may be used with the schemes ECKAS-DH1 and * DL/ECKAS-DH2. It assumes that the input keys are valid (see also * Section 7.2.2). */ public class ECDHBasicAgreement implements BasicAgreement { private ECPrivateKeyParameters key; public void init( CipherParameters key) { this.key = (ECPrivateKeyParameters)key; } public BigInteger calculateAgreement( CipherParameters pubKey) { ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey; ECPoint P = pub.getQ().multiply(key.getD()); // if ( p.isInfinity() ) throw new RuntimeException("d*Q == infinity"); return P.getX().toBigInteger(); } } azureus-4.3.0.6/org/bouncycastle/crypto/InvalidCipherTextException.java0000644000175000017500000000105311012742212025537 0ustar adrianadrianpackage org.bouncycastle.crypto; /** * this exception is thrown whenever we find something we don't expect in a * message. */ public class InvalidCipherTextException extends CryptoException { /** * base constructor. */ public InvalidCipherTextException() { } /** * create a InvalidCipherTextException with the given message. * * @param message the message to be carried with the exception. */ public InvalidCipherTextException( String message) { super(message); } } azureus-4.3.0.6/org/bouncycastle/crypto/encodings/0000755000175000017500000000000011310377634021416 5ustar adrianadrianazureus-4.3.0.6/org/bouncycastle/crypto/encodings/package.html0000644000175000017500000000013010061400652023656 0ustar adrianadrian Block encodings for asymmetric ciphers. azureus-4.3.0.6/org/bouncycastle/crypto/encodings/PKCS1Encoding.java0000644000175000017500000001165010061400652024541 0ustar adrianadrianpackage org.bouncycastle.crypto.encodings; import java.security.SecureRandom; import org.bouncycastle.crypto.AsymmetricBlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.ParametersWithRandom; /** * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this * depends on your application - see PKCS1 Version 2 for details. */ public class PKCS1Encoding implements AsymmetricBlockCipher { private static int HEADER_LENGTH = 10; private SecureRandom random; private AsymmetricBlockCipher engine; private boolean forEncryption; private boolean forPrivateKey; public PKCS1Encoding( AsymmetricBlockCipher cipher) { this.engine = cipher; } public AsymmetricBlockCipher getUnderlyingCipher() { return engine; } public void init( boolean forEncryption, CipherParameters param) { AsymmetricKeyParameter kParam; if (param instanceof ParametersWithRandom) { ParametersWithRandom rParam = (ParametersWithRandom)param; this.random = rParam.getRandom(); kParam = (AsymmetricKeyParameter)rParam.getParameters(); } else { this.random = new SecureRandom(); kParam = (AsymmetricKeyParameter)param; } engine.init(forEncryption, kParam); this.forPrivateKey = kParam.isPrivate(); this.forEncryption = forEncryption; } public int getInputBlockSize() { int baseBlockSize = engine.getInputBlockSize(); if (forEncryption) { return baseBlockSize - HEADER_LENGTH; } else { return baseBlockSize; } } public int getOutputBlockSize() { int baseBlockSize = engine.getOutputBlockSize(); if (forEncryption) { return baseBlockSize; } else { return baseBlockSize - HEADER_LENGTH; } } public byte[] processBlock( byte[] in, int inOff, int inLen) throws InvalidCipherTextException { if (forEncryption) { return encodeBlock(in, inOff, inLen); } else { return decodeBlock(in, inOff, inLen); } } private byte[] encodeBlock( byte[] in, int inOff, int inLen) throws InvalidCipherTextException { byte[] block = new byte[engine.getInputBlockSize()]; if (forPrivateKey) { block[0] = 0x01; // type code 1 for (int i = 1; i != block.length - inLen - 1; i++) { block[i] = (byte)0xFF; } } else { random.nextBytes(block); // random fill block[0] = 0x02; // type code 2 // // a zero byte marks the end of the padding, so all // the pad bytes must be non-zero. // for (int i = 1; i != block.length - inLen - 1; i++) { while (block[i] == 0) { block[i] = (byte)random.nextInt(); } } } block[block.length - inLen - 1] = 0x00; // mark the end of the padding System.arraycopy(in, inOff, block, block.length - inLen, inLen); return engine.processBlock(block, 0, block.length); } /** * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format. */ private byte[] decodeBlock( byte[] in, int inOff, int inLen) throws InvalidCipherTextException { byte[] block = engine.processBlock(in, inOff, inLen); if (block.length < getOutputBlockSize()) { throw new InvalidCipherTextException("block truncated"); } if (block[0] != 1 && block[0] != 2) { throw new InvalidCipherTextException("unknown block type"); } // // find and extract the message block. // int start; for (start = 1; start != block.length; start++) { if (block[start] == 0) { break; } } start++; // data should start at the next byte if (start >= block.length || start < HEADER_LENGTH) { throw new InvalidCipherTextException("no data in block"); } byte[] result = new byte[block.length - start]; System.arraycopy(block, start, result, 0, result.length); return result; } } azureus-4.3.0.6/org/bouncycastle/crypto/encodings/OAEPEncoding.java0000644000175000017500000002052310061400652024443 0ustar adrianadrianpackage org.bouncycastle.crypto.encodings; import java.security.SecureRandom; import org.bouncycastle.crypto.AsymmetricBlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.ParametersWithRandom; /** * Optimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2. */ public class OAEPEncoding implements AsymmetricBlockCipher { private byte[] defHash; private Digest hash; private AsymmetricBlockCipher engine; private SecureRandom random; private boolean forEncryption; public OAEPEncoding( AsymmetricBlockCipher cipher) { this(cipher, new SHA1Digest(), null); } public OAEPEncoding( AsymmetricBlockCipher cipher, Digest hash) { this(cipher, hash, null); } public OAEPEncoding( AsymmetricBlockCipher cipher, Digest hash, byte[] encodingParams) { this.engine = cipher; this.hash = hash; this.defHash = new byte[hash.getDigestSize()]; if (encodingParams != null) { hash.update(encodingParams, 0, encodingParams.length); } hash.doFinal(defHash, 0); } public AsymmetricBlockCipher getUnderlyingCipher() { return engine; } public void init( boolean forEncryption, CipherParameters param) { AsymmetricKeyParameter kParam; if (param instanceof ParametersWithRandom) { ParametersWithRandom rParam = (ParametersWithRandom)param; this.random = rParam.getRandom(); kParam = (AsymmetricKeyParameter)rParam.getParameters(); } else { this.random = new SecureRandom(); kParam = (AsymmetricKeyParameter)param; } engine.init(forEncryption, kParam); this.forEncryption = forEncryption; } public int getInputBlockSize() { int baseBlockSize = engine.getInputBlockSize(); if (forEncryption) { return baseBlockSize - 1 - 2 * defHash.length; } else { return baseBlockSize; } } public int getOutputBlockSize() { int baseBlockSize = engine.getOutputBlockSize(); if (forEncryption) { return baseBlockSize; } else { return baseBlockSize - 1 - 2 * defHash.length; } } public byte[] processBlock( byte[] in, int inOff, int inLen) throws InvalidCipherTextException { if (forEncryption) { return encodeBlock(in, inOff, inLen); } else { return decodeBlock(in, inOff, inLen); } } public byte[] encodeBlock( byte[] in, int inOff, int inLen) throws InvalidCipherTextException { byte[] block = new byte[getInputBlockSize() + 1 + 2 * defHash.length]; // // copy in the message // System.arraycopy(in, inOff, block, block.length - inLen, inLen); // // add sentinel // block[block.length - inLen - 1] = 0x01; // // as the block is already zeroed - there's no need to add PS (the >= 0 pad of 0) // // // add the hash of the encoding params. // System.arraycopy(defHash, 0, block, defHash.length, defHash.length); // // generate the seed. // byte[] seed = new byte[defHash.length]; random.nextBytes(seed); // // mask the message block. // byte[] mask = maskGeneratorFunction1(seed, 0, seed.length, block.length - defHash.length); for (int i = defHash.length; i != block.length; i++) { block[i] ^= mask[i - defHash.length]; } // // add in the seed // System.arraycopy(seed, 0, block, 0, defHash.length); // // mask the seed. // mask = maskGeneratorFunction1( block, defHash.length, block.length - defHash.length, defHash.length); for (int i = 0; i != defHash.length; i++) { block[i] ^= mask[i]; } return engine.processBlock(block, 0, block.length); } /** * @exception InvalidCipherTextException if the decryypted block turns out to * be badly formatted. */ public byte[] decodeBlock( byte[] in, int inOff, int inLen) throws InvalidCipherTextException { byte[] data = engine.processBlock(in, inOff, inLen); byte[] block = null; // // as we may have zeros in our leading bytes for the block we produced // on encryption, we need to make sure our decrypted block comes back // the same size. // if (data.length < engine.getOutputBlockSize()) { block = new byte[engine.getOutputBlockSize()]; System.arraycopy(data, 0, block, block.length - data.length, data.length); } else { block = data; } if (block.length < (2 * defHash.length) + 1) { throw new InvalidCipherTextException("data too short"); } // // unmask the seed. // byte[] mask = maskGeneratorFunction1( block, defHash.length, block.length - defHash.length, defHash.length); for (int i = 0; i != defHash.length; i++) { block[i] ^= mask[i]; } // // unmask the message block. // mask = maskGeneratorFunction1(block, 0, defHash.length, block.length - defHash.length); for (int i = defHash.length; i != block.length; i++) { block[i] ^= mask[i - defHash.length]; } // // check the hash of the encoding params. // for (int i = 0; i != defHash.length; i++) { if (defHash[i] != block[defHash.length + i]) { throw new InvalidCipherTextException("data hash wrong"); } } // // find the data block // int start; for (start = 2 * defHash.length; start != block.length; start++) { if (block[start] == 1 || block[start] != 0) { break; } } if (start >= (block.length - 1) || block[start] != 1) { throw new InvalidCipherTextException("data start wrong " + start); } start++; // // extract the data block // byte[] output = new byte[block.length - start]; System.arraycopy(block, start, output, 0, output.length); return output; } /** * int to octet string. */ private void ItoOSP( int i, byte[] sp) { sp[0] = (byte)(i >>> 24); sp[1] = (byte)(i >>> 16); sp[2] = (byte)(i >>> 8); sp[3] = (byte)(i >>> 0); } /** * mask generator function, as described in PKCS1v2. */ private byte[] maskGeneratorFunction1( byte[] Z, int zOff, int zLen, int length) { byte[] mask = new byte[length]; byte[] hashBuf = new byte[defHash.length]; byte[] C = new byte[4]; int counter = 0; hash.reset(); do { ItoOSP(counter, C); hash.update(Z, zOff, zLen); hash.update(C, 0, C.length); hash.doFinal(hashBuf, 0); System.arraycopy(hashBuf, 0, mask, counter * defHash.length, defHash.length); } while (++counter < (length / defHash.length)); if ((counter * defHash.length) < length) { ItoOSP(counter, C); hash.update(Z, zOff, zLen); hash.update(C, 0, C.length); hash.doFinal(hashBuf, 0); System.arraycopy(hashBuf, 0, mask, counter * defHash.length, mask.length - (counter * defHash.length)); } return mask; } } azureus-4.3.0.6/org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java0000644000175000017500000001554210061400652025142 0ustar adrianadrianpackage org.bouncycastle.crypto.encodings; import org.bouncycastle.crypto.AsymmetricBlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.crypto.params.RSAKeyParameters; /** * ISO 9796-1 padding. Note in the light of recent results you should * only use this with RSA (rather than the "simpler" Rabin keys) and you * should never use it with anything other than a hash (ie. even if the * message is small don't sign the message, sign it's hash) or some "random" * value. See your favorite search engine for details. */ public class ISO9796d1Encoding implements AsymmetricBlockCipher { private static byte[] shadows = { 0xe, 0x3, 0x5, 0x8, 0x9, 0x4, 0x2, 0xf, 0x0, 0xd, 0xb, 0x6, 0x7, 0xa, 0xc, 0x1 }; private static byte[] inverse = { 0x8, 0xf, 0x6, 0x1, 0x5, 0x2, 0xb, 0xc, 0x3, 0x4, 0xd, 0xa, 0xe, 0x9, 0x0, 0x7 }; private AsymmetricBlockCipher engine; private boolean forEncryption; private int bitSize; private int padBits = 0; public ISO9796d1Encoding( AsymmetricBlockCipher cipher) { this.engine = cipher; } public AsymmetricBlockCipher getUnderlyingCipher() { return engine; } public void init( boolean forEncryption, CipherParameters param) { RSAKeyParameters kParam = null; if (param instanceof ParametersWithRandom) { ParametersWithRandom rParam = (ParametersWithRandom)param; kParam = (RSAKeyParameters)rParam.getParameters(); } else { kParam = (RSAKeyParameters)param; } engine.init(forEncryption, kParam); bitSize = kParam.getModulus().bitLength(); this.forEncryption = forEncryption; } /** * return the input block size. The largest message we can process * is (key_size_in_bits + 3)/16, which in our world comes to * key_size_in_bytes / 2. */ public int getInputBlockSize() { int baseBlockSize = engine.getInputBlockSize(); if (forEncryption) { return (baseBlockSize + 1) / 2; } else { return baseBlockSize; } } /** * return the maximum possible size for the output. */ public int getOutputBlockSize() { int baseBlockSize = engine.getOutputBlockSize(); if (forEncryption) { return baseBlockSize; } else { return (baseBlockSize + 1) / 2; } } /** * set the number of bits in the next message to be treated as * pad bits. */ public void setPadBits( int padBits) { if (padBits > 7) { throw new IllegalArgumentException("padBits > 7"); } this.padBits = padBits; } /** * retrieve the number of pad bits in the last decoded message. */ public int getPadBits() { return padBits; } public byte[] processBlock( byte[] in, int inOff, int inLen) throws InvalidCipherTextException { if (forEncryption) { return encodeBlock(in, inOff, inLen); } else { return decodeBlock(in, inOff, inLen); } } private byte[] encodeBlock( byte[] in, int inOff, int inLen) throws InvalidCipherTextException { byte[] block = new byte[(bitSize + 7) / 8]; int r = padBits + 1; int z = inLen; int t = (bitSize + 13) / 16; for (int i = 0; i < t; i += z) { if (i > t - z) { System.arraycopy(in, inOff + inLen - (t - i), block, block.length - t, t - i); } else { System.arraycopy(in, inOff, block, block.length - (i + z), z); } } for (int i = block.length - 2 * t; i != block.length; i += 2) { byte val = block[block.length - t + i / 2]; block[i] = (byte)((shadows[(val & 0xff) >>> 4] << 4) | shadows[val & 0x0f]); block[i + 1] = val; } block[block.length - 2 * z] ^= r; block[block.length - 1] = (byte)((block[block.length - 1] << 4) | 0x06); int maxBit = (8 - (bitSize - 1) % 8); int offSet = 0; if (maxBit != 8) { block[0] &= 0xff >>> maxBit; block[0] |= 0x80 >>> maxBit; } else { block[0] = 0x00; block[1] |= 0x80; offSet = 1; } return engine.processBlock(block, offSet, block.length - offSet); } /** * @exception InvalidCipherTextException if the decrypted block is not a valid ISO 9796 bit string */ private byte[] decodeBlock( byte[] in, int inOff, int inLen) throws InvalidCipherTextException { byte[] block = engine.processBlock(in, inOff, inLen); int r = 1; int t = (bitSize + 13) / 16; if ((block[block.length - 1] & 0x0f) != 0x6) { throw new InvalidCipherTextException("invalid forcing byte in block"); } block[block.length - 1] = (byte)(((block[block.length - 1] & 0xff) >>> 4) | ((inverse[(block[block.length - 2] & 0xff) >> 4]) << 4)); block[0] = (byte)((shadows[(block[1] & 0xff) >>> 4] << 4) | shadows[block[1] & 0x0f]); boolean boundaryFound = false; int boundary = 0; for (int i = block.length - 1; i >= block.length - 2 * t; i -= 2) { int val = ((shadows[(block[i] & 0xff) >>> 4] << 4) | shadows[block[i] & 0x0f]); if (((block[i - 1] ^ val) & 0xff) != 0) { if (!boundaryFound) { boundaryFound = true; r = (block[i - 1] ^ val) & 0xff; boundary = i - 1; } else { throw new InvalidCipherTextException("invalid tsums in block"); } } } block[boundary] = 0; byte[] nblock = new byte[(block.length - boundary) / 2]; for (int i = 0; i < nblock.length; i++) { nblock[i] = block[2 * i + boundary + 1]; } padBits = r - 1; return nblock; } } azureus-4.3.0.6/org/bouncycastle/crypto/Wrapper.java0000644000175000017500000000074110061400652021717 0ustar adrianadrianpackage org.bouncycastle.crypto; public interface Wrapper { public void init(boolean forWrapping, CipherParameters param); /** * Return the name of the algorithm the wrapper implements. * * @return the name of the algorithm the wrapper implements. */ public String getAlgorithmName(); public byte[] wrap(byte[] in, int inOff, int inLen); public byte[] unwrap(byte[] in, int inOff, int inLen) throws InvalidCipherTextException; } azureus-4.3.0.6/org/pf/0000755000175000017500000000000011310377516014036 5ustar adrianadrianazureus-4.3.0.6/org/pf/programmers-friend.org.html0000644000175000017500000000241510024456444021316 0ustar adrianadrian Programmer's Friend

      Programmer's Friend

      Here I'm publishing useful Java components to share them freely with anybody who likes them.
      That includes binary and source code.

      Currently available:


      Contact: Programmer's Friend.


      Last Update: July 26, 2003


      azureus-4.3.0.6/org/pf/text/0000755000175000017500000000000011310377636015025 5ustar adrianadrianazureus-4.3.0.6/org/pf/text/StringUtil.java0000644000175000017500000015167110024456444020003 0ustar adrianadrian// =========================================================================== // CONTENT : CLASS StringUtil // AUTHOR : Manfred Duchrow // VERSION : 2.0 - 21/03/2003 // HISTORY : // 10/07/1999 duma CREATED // 09/12/1999 duma added -> SPACE, repeat() // moved -> from package com.mdcs.util // 25/01/2000 duma moved -> from package com.mdcs.text // 09/02/2000 duma changed -> renamed SPACE to CH_SPACE // added -> CH_CR, CH_TAB, ..., STR_SPACE, STR_NEWLINE, ... // 11/01/2002 duma added -> indexOf(), indexOfIgnoreCase(), contains(), containsIgnoreCase() // 17/05/2002 duma added -> copyFrom() // 03/07/2002 duma added -> cutHead(), prefix(), suffix() // 06/07/2002 duma added -> indexOf() and contains() for StringPattern and reverse() // 15/08/2002 duma added -> upTo(), startingFrom(), asMap() // 29/09/2002 duma added -> allParts() and allSubstrings() that don't skip empty elements // 06/03/2003 duma changed -> append() now uses System.arraycopy() // added -> remove( String[], String[] ), remove( String[], String ) // removeNull( String[] ) // 21/03/2003 duma added -> leftPad(), leftPadCh(), rightPad(), rightPadCh() for int values // // Copyright (c) 1999-2003, by Manfred Duchrow. All rights reserved. // =========================================================================== package org.pf.text; // =========================================================================== // IMPORT // =========================================================================== import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; import java.util.ArrayList; import java.io.PrintWriter; import java.io.StringWriter; /** * The sole instance of this class provides several convienience methods * for string manipulation such as substring replacement or character repetition. * * @author Manfred Duchrow * @version 2.0 */ public class StringUtil { // ========================================================================= // CONSTANTS // ========================================================================= /** Constant for the space character **/ public static final char CH_SPACE = '\u0020' ; /** Constant for the new line character **/ public static final char CH_NEWLINE = '\n' ; /** Constant for the carriage return character **/ public static final char CH_CR = '\r' ; /** Constant for the tabulator character **/ public static final char CH_TAB = '\t' ; /** Constant for the String representation of the space character **/ public static final String STR_SPACE = "\u0020" ; /** Constant for the String representation of the new line character **/ public static final String STR_NEWLINE = "\n" ; /** Constant for the String representation of the carriage return character **/ public static final String STR_CR = "\r" ; /** Constant for the String representation of the tabulator character **/ public static final String STR_TAB = "\t" ; private static final String WORD_DELIM = STR_SPACE + STR_TAB + STR_NEWLINE + STR_CR ; // ========================================================================= // CLASS VARIABLES // ========================================================================= private static StringUtil singleton = null ; private static StringUtil getSingleton() { return singleton ; } private static void setSingleton( StringUtil inst ) { singleton = inst ; } // ========================================================================= // PUBLIC CLASS METHODS // ========================================================================= /** * Returns the one and only instance of this class. */ public static StringUtil current() { if ( getSingleton() == null ) setSingleton( new StringUtil() ) ; return getSingleton() ; } // current() // ========================================================================= // PUBLIC INSTANCE METHODS // ========================================================================= /** * Returns the given string with all found oldSubStr replaced by newSubStr.
      * * Example: StringUtil.current().replaceAll( "Seven of ten", "even", "ix" ) ;
      * results in: "Six of ten" * * @param sourceStr The string that should be checked for occurrences of oldSubStr * @param oldSubStr The string that is searched for in sourceStr * @param newSubStr The new string that is placed everywhere the oldSubStr was found * @return The original string with all found substrings replaced by new strings */ public String replaceAll( String sourceStr, String oldSubStr, String newSubStr ) { String part = null ; String result = "" ; int index = -1 ; int subLen = 0 ; subLen = oldSubStr.length() ; part = sourceStr ; while ( ( part.length() > 0 ) && ( subLen > 0 ) ) { index = part.indexOf( oldSubStr ) ; if ( index >= 0 ) { result = result + part.substring( 0, index ) + newSubStr ; part = part.substring( index + subLen ) ; } else { result = result + part ; part = "" ; } } // while return result ; } // replaceAll() // ------------------------------------------------------------------------- /** * Returns a string with size of count and all characters initialized with ch.
      * * @param ch the character to be repeated in the result string. * @param count the number of times the given character should occur in the result string. * @return A string containing count characters ch. */ public String repeat( char ch, int count ) { StringBuffer buffer = null ; buffer = new StringBuffer( count ) ; for ( int i = 1 ; i <= count ; i++ ) { buffer.append( ch ) ; } return ( buffer.toString() ) ; } // repeat() // ------------------------------------------------------------------------- /** * Returns an array of substrings of the given text.
      * The delimiters between the substrings are the whitespace characters * SPACE, NEWLINE, CR and TAB. * * @see #parts(String, String) * @param text The string that should be splitted into whitespace separated words * @return An array of substrings of the given text */ public String[] words( String text ) { return this.parts( text, WORD_DELIM ) ; } // words() // ------------------------------------------------------------------------- /** * Returns an array of substrings of the given text.
      * The separators between the substrings are the given delimiters. * Each character in the delimiter string is treated as a separator. *
      * All consecutive delimiters are treated as one delimiter, that is there * will be no empty strings in the result. * * @see #allParts(String, String) * @see #substrings(String, String) * @see #allSubstrings(String, String) * @param text The string that should be splitted into substrings * @param delimiters All characters that should be recognized as a separator or substrings * @return An array of substrings of the given text */ public String[] parts( String text, String delimiters ) { return this.parts( text, delimiters, false ) ; } // parts() // ------------------------------------------------------------------------- /** * Returns an array of substrings of the given text.
      * The separators between the substrings are the given delimiters. * Each character in the delimiter string is treated as a separator. *
      * For each delimiter that is followed immediately by another delimiter an * empty string will be added to the result. There are no empty strings added * to the result for a delimiter at the very beginning of at the very end. *

      * Examples: *

      * allParts( "/A/B//", "/" ) --> { "A", "B", "" }
      * allParts( "/A,B/C;D", ",;/" ) --> { "A", "B", "C", "D" }
      * allParts( "A/B,C/D", "," ) --> { "A/B", "C/D" }
      * * @see #parts(String, String) * @see #substrings(String, String) * @see #allSubstrings(String, String) * @param text The string that should be splitted into substrings * @param delimiters All characters that should be recognized as a separator or substrings * @return An array of substrings of the given text */ public String[] allParts( String text, String delimiters ) { return this.parts( text, delimiters, true ) ; } // allParts() // ------------------------------------------------------------------------- /** * Returns the given text split up into an array of strings, at * the occurrances of the separator string. * * In contrary to method parts() the separator is a one or many * character sequence delimiter. That is, only the exact sequence * of the characters in separator identifies the end of a substring. * Subsequent occurences of separator will be skipped. Therefore * no empty strings ("") will be in the result array. * * @see #allSubstrings(String, String) * @see #parts(String, String) * @see #allParts(String, String) * @param text The text to be split up * @param separator The string that separates the substrings * @return An array of substrings not containing any separator anymore */ public String[] substrings( String text, String separator ) { return this.substrings( text, separator, false ) ; } // substrings() // ------------------------------------------------------------------------- /** * Returns the given text split up into an array of strings, at * the occurrances of the separator string. * * In contrary to method allParts() the separator is a one or many * character sequence delimiter. That is, only the exact sequence * of the characters in separator identifies the end of a substring. * Subsequent occurences of separator are not skipped. They are added * as empty strings to the result. * * @see #substrings(String, String) * @see #parts(String, String) * @see #allParts(String, String) * @param text The text to be split up * @param separator The string that separates the substrings * @return An array of substrings not containing any separator anymore */ public String[] allSubstrings( String text, String separator ) { return this.substrings( text, separator, true ) ; } // allSubstrings() // ------------------------------------------------------------------------- /** * Returns the first substring that is enclosed by the specified delimiters. *
      * The delimiters are not included in the return string. *

      * Example:
      * getDelimitedSubstring( "This {placeholder} belongs to me", "{", "}" ) * --> returns "placeholder" * * @param text The input string that contains the delimited part * @param startDelimiter The start delimiter of the substring * @param endDelimiter The end delimiter of the substring * @return The substring or an empty string, if no delimiters are found. */ public String getDelimitedSubstring( String text, String startDelimiter, String endDelimiter ) { int start ; int stop ; String subStr = "" ; if ( ( text != null ) && ( startDelimiter != null ) && ( endDelimiter != null ) ) { start = text.indexOf( startDelimiter ) ; if ( start >= 0 ) { stop = text.indexOf( endDelimiter, start + 1 ) ; if ( stop > start ) subStr = text.substring( start + 1, stop ) ; } } return subStr ; } // getDelimitedSubstring() // ------------------------------------------------------------------------- /** * Returns the first substring that is enclosed by the specified delimiter.
      * The delimiters are not included in the return string. *

      * Example:
      * getDelimitedSubstring( "File 'text.txt' not found.", "'", "'" ) * --> returns "text.txt" * * @param text The input string that contains the delimited part * @param delimiter The start and end delimiter of the substring * @return The substring or an empty string, if no delimiters are found. */ public String getDelimitedSubstring( String text, String delimiter ) { return this.getDelimitedSubstring( text, delimiter, delimiter ) ; } // getDelimitedSubstring() // ------------------------------------------------------------------------- /** * Prints the stack trace of the specified throwable to a * string and returns it. */ public String stackTrace( Throwable throwable ) { StringWriter sw = new StringWriter() ; PrintWriter pw = new PrintWriter( sw ) ; throwable.printStackTrace( pw ) ; pw.close() ; return sw.toString() ; } // stackTrace() // ------------------------------------------------------------------------- /** * Returns the given string filled (on the left) up to the specified * length with the given character.
      * Example: leftPadCh( "12", 6, '0' ) --> "000012" */ public String leftPadCh( String str, int len, char ch ) { return this.padCh( str, len, ch, true ) ; } // leftPadCh() // ------------------------------------------------------------------------- /** * Returns the given string filled (on the left) up to the specified * length with spaces.
      * Example: leftPad( "XX", 4 ) --> " XX" * * @param str The string that has to be filled up to the specified length * @param len The length of the result string */ public String leftPad( String str, int len ) { return this.leftPadCh( str, len, CH_SPACE ) ; } // leftPad() // ------------------------------------------------------------------------- /** * Returns the given integer as string filled (on the left) up to the * specified length with the given fill character.
      * Example: leftPad( 24, 5, '*' ) --> "***24" */ public String leftPadCh( int value, int len, char fillChar ) { return this.leftPadCh( Integer.toString(value), len, fillChar ) ; } // leftPadCh() // ------------------------------------------------------------------------- /** * Returns the given integer as string filled (on the left) up to the * specified length with zeroes.
      * Example: leftPad( 12, 4 ) --> "0012" */ public String leftPad( int value, int len ) { return this.leftPadCh( value, len, '0' ) ; } // leftPad() // ------------------------------------------------------------------------- /** * Returns the given string filled (on the right) up to the specified * length with the given character.
      * Example: rightPadCh( "34", 5, 'X' ) --> "34XXX" */ public String rightPadCh( String str, int len, char ch ) { return this.padCh( str, len, ch, false ) ; } // rightPadCh() // ------------------------------------------------------------------------- /** * Returns the given string filled (on the right) up to the specified * length with spaces.
      * Example: rightPad( "88", 6 ) --> "88 " */ public String rightPad( String str, int len ) { return this.rightPadCh( str, len, CH_SPACE ) ; } // rightPad() // ------------------------------------------------------------------------- /** * Returns the given integer as string filled (on the right) up to the * specified length with the given character.
      * Example: rightPad( "32", 4, '#' ) --> "32##" */ public String rightPadCh( int value, int len, char fillChar ) { return this.rightPadCh( Integer.toString(value), len, fillChar ) ; } // rightPad() // ------------------------------------------------------------------------- /** * Returns the given integer as string filled (on the right) up to the * specified length with spaces.
      * Example: rightPad( "17", 5 ) --> "17 " */ public String rightPad( int value, int len ) { return this.rightPadCh( value, len, CH_SPACE ) ; } // rightPad() // ------------------------------------------------------------------------- /** * Returns the given string filled equally left and right * up to the specified length with the given character.
      * Example: centerCh( "A", 5, '_' ) --> "__A__"
      * Example: centerCh( "XX", 7, '+' ) --> "++XX+++" */ public String centerCh( String str, int len, char ch ) { String buffer = null ; int missing = len - str.length() ; int half = 0 ; if ( missing <= 0 ) return str ; half = missing / 2 ; buffer = this.rightPadCh( str, len-half, ch ) ; return this.leftPadCh( buffer, len, ch ) ; } // centerCh() // ------------------------------------------------------------------------- /** * Returns the given string filled (on the right and right) * up to the specified length with spaces.
      * Example: center( "Mike", 10 ) --> " Mike " */ public String center( String str, int len ) { return this.centerCh( str, len, CH_SPACE ) ; } // center() // ------------------------------------------------------------------------- /** * Returns the given string array extended by one element * that hold the specified string. */ public String[] append( String[] strings, String string ) { String[] appStr = { string } ; return this.append( strings, appStr ) ; } // append() // ------------------------------------------------------------------------- /** * Returns an array of strings that contains all strings given * by the first and second string array. The strings from the * second array will be added at the end of the first array. * * @param strings The array of string to which to append * @param appendStrings The string to be appended to the first array */ public String[] append( String[] strings, String[] appendStrings ) { String[] newStrings = null ; if ( strings == null ) return appendStrings ; if ( appendStrings == null ) return strings ; newStrings = new String[strings.length + appendStrings.length] ; System.arraycopy( strings, 0, newStrings, 0, strings.length ) ; System.arraycopy( appendStrings, 0, newStrings, strings.length, appendStrings.length ) ; return newStrings ; } // append() // ------------------------------------------------------------------------- /** * Returns an array of strings that contains all strings given * in the first plus the specified string to append, if it is not * already in the given array. */ public String[] appendIfNotThere( String[] strings, String appendString ) { if ( this.contains( strings, appendString ) ) return strings ; else return this.append( strings, appendString ) ; } // appendIfNotThere() // ------------------------------------------------------------------------- /** * Returns an array of strings that contains all strings given * in the first plus all strings of the second array that are not * already in the first array. */ public String[] appendIfNotThere( String[] strings, String[] appendStrings ) { String[] newStrings = strings ; if ( appendStrings == null ) return newStrings ; for ( int i = 0 ; i < appendStrings.length ; i++ ) { newStrings = this.appendIfNotThere( newStrings, appendStrings[i] ) ; } return newStrings ; } // appendIfNotThere() // ------------------------------------------------------------------------- /** * Removes all string of the second array from the first array. * Returns a new array of string that contains all remaining strings of the * original strings array. * * @param strings The array from which to remove the strings * @param removeStrings The strings to be removed */ public String[] remove( String[] strings, String[] removeStrings ) { if ( ( strings == null ) || ( removeStrings == null ) || ( strings.length == 0 ) || ( removeStrings.length == 0 ) ) { return strings ; } return this.removeFromStringArray( strings, removeStrings ) ; } // remove() // ------------------------------------------------------------------------- /** * Removes the given string from the specified string array. * Returns a new array of string that contains all remaining strings of the * original strings array. * * @param strings The array from which to remove the string * @param removeString The string to be removed */ public String[] remove( String[] strings, String removeString ) { String[] removeStrings = { removeString } ; return this.remove( strings, removeStrings ) ; } // remove() // ------------------------------------------------------------------------- /** * Removes all null values from the given string array. * Returns a new string array that contains all none null values of the * input array. * * @param strings The array to be cleared of null values */ public String[] removeNull( String[] strings ) { if ( strings == null ) return strings ; return this.removeFromStringArray( strings, null ) ; } // removeNull() // ------------------------------------------------------------------------- /** * Returns a string that contains all given strings concatenated * and separated by the specified separator. * * @param strings The array of strings that should be concatenated * @param separator The separator between the strings * @return One string containing the concatenated strings separated by separator */ public String asString ( String[] strings, String separator ) { StringBuffer buffer = null ; buffer = new StringBuffer( strings.length * 20 ) ; if ( strings.length > 0 ) { buffer.append( strings[0].toString() ) ; for ( int i = 1 ; i < strings.length ; i++ ) { buffer.append( separator ) ; if ( strings[i] != null ) buffer.append( strings[i] ) ; } } return buffer.toString() ; } // asString() // ------------------------------------------------------------------------- /** * Returns a string that contains all given strings concatenated * and separated by comma. * * @param strings The array of strings that should be concatenated * @return One string containing the concatenated strings separated by comma (",") */ public String asString ( String[] strings ) { return this.asString( strings, "," ) ; } // asString() // ------------------------------------------------------------------------- /** * Returns the index of the first string in the given string array that * matches the specified string pattern. * If no string is found in the array the result is -1. * * @param strArray An array of string (may contain null elements) * @param pattern The pattern the searched string must match * @return The index of the matching string in the array or -1 if not found */ public int indexOf( String[] strArray, StringPattern pattern ) { if ( ( strArray == null ) || ( strArray.length == 0 ) ) return -1 ; boolean found = false ; for ( int i = 0 ; i < strArray.length ; i++ ) { if ( strArray[i] == null ) { if ( pattern == null ) found = true ; } else { if ( pattern != null ) found = pattern.matches( strArray[i] ) ; } if ( found ) return i ; } return -1 ; } // indexOf() // ------------------------------------------------------------------------- /** * Returns the index of the specified string in the given string array. * It returns the index of the first occurrence of the string. * If the string is not found in the array the result is -1. * The comparison of the strings is case-sensitive! * * @param strArray An array of string (may contain null elements) * @param searchStr The string to be looked up in the array (null allowed) * @return The index of the string in the array or -1 if not found */ public int indexOf( String[] strArray, String searchStr ) { return this.indexOfString( strArray, searchStr, false ) ; } // indexOf() // ------------------------------------------------------------------------- /** * Returns the index of the specified string in the given string array. * It returns the index of the first occurrence of the string. * If the string is not found in the array the result is -1. * The comparison of the strings is case-insensitive! * * @param strArray An array of string (may contain null elements) * @param searchStr The string to be looked up in the array (null allowed) * @return The index of the string in the array or -1 if not found */ public int indexOfIgnoreCase( String[] strArray, String searchStr ) { return this.indexOfString( strArray, searchStr, true ) ; } // indexOfIgnoreCase() // ------------------------------------------------------------------------- /** * Returns whether or not the specified string can be found * in the given string array. * * @param strArray An array of string (may contain null elements) * @param searchStr The string to be looked up in the array (null allowed) * @param ignoreCase Defines whether or not the comparison is case-sensitive. * @return true, if the specified array contains the given string */ public boolean contains( String[] strArray, String searchStr, boolean ignoreCase ) { if ( ignoreCase ) return this.containsIgnoreCase( strArray, searchStr ) ; else return this.contains( strArray, searchStr ) ; } // contains() // ------------------------------------------------------------------------- /** * Returns whether or not a string can be found in the given string array * that matches the specified string pattern. * * @param strArray An array of string (may contain null elements) * @param pattern The string pattern to match against in the array (null allowed) * @return true, if the specified array contains a string matching the pattern */ public boolean contains( String[] strArray, StringPattern pattern) { return ( this.indexOf( strArray, pattern ) >= 0 ) ; } // contains() // ------------------------------------------------------------------------- /** * Returns whether or not the specified string can be found * in the given string array. * The comparison of the strings is case-sensitive! * * @param strArray An array of string (may contain null elements) * @param searchStr The string to be looked up in the array (null allowed) * @return true, if the specified array contains the given string */ public boolean contains( String[] strArray, String searchStr ) { return ( this.indexOf( strArray, searchStr ) >= 0 ) ; } // contains() // ------------------------------------------------------------------------- /** * Returns whether or not the specified string can be found * in the given string array. * The comparison of the strings is case-insensitive! * * @param strArray An array of string (may contain null elements) * @param searchStr The string to be looked up in the array (null allowed) * @return true, if the specified array contains the given string */ public boolean containsIgnoreCase( String[] strArray, String searchStr ) { return ( this.indexOfIgnoreCase( strArray, searchStr ) >= 0 ) ; } // containsIgnoreCase() // ------------------------------------------------------------------------- /** * Returns all elements of string array from in a new array * from index start up to the end. * If start index is larger than the array's length, an empty array will be * returned. * * @param from The string array the elements should be copied from * @param start Index of the first element to copy */ public String[] copyFrom( String[] from, int start ) { if ( from == null ) return null ; return this.copyFrom( from, start, from.length - 1 ) ; } // copyFrom() // ------------------------------------------------------------------------- /** * Returns all elements of string array from in a new array * from index start up to index end (inclusive). * If end is larger than the last valid index, it will be reduced * to the last index. * If end index is less than start index, an empty array will be * returned. * * @param from The string array the elements should be copied from * @param start Index of the first element to copy * @param end Index of last element to be copied */ public String[] copyFrom( String[] from, int start, int end ) { String[] result ; int count ; int stop = end ; if ( from == null ) return null ; if ( stop > ( from.length - 1 ) ) stop = from.length - 1 ; count = stop - start + 1 ; if ( count < 1 ) return new String[0] ; result = new String[count] ; System.arraycopy( from, start, result, 0, count ) ; return result ; } // copyFrom() // ------------------------------------------------------------------------- /** * Returns the portion of the given string that comes before the last * occurance of the specified separator.
      * If the separator could not be found in the given string, then the * string is returned unchanged. *

      * Examples: *

      * cutTail( "A/B/C", "/" ) ; // returns "A/B" *
      * cutTail( "A/B/C", "," ) ; // returns "A/B/C" *

      * @see #prefix( String, String ) * @see #suffix( String, String ) * @see #cutHead( String, String ) * @see #startingFrom( String, String ) * @see #upTo( String, String ) * @param text The string from which to cut off the tail * @param separator The separator from where to cut off * @return the string without the separator and without the characters after the separator */ public String cutTail( String text, String separator ) { int index ; if ( ( text == null ) || ( separator == null ) ) return text ; index = text.lastIndexOf( separator ) ; if ( index < 0 ) return text ; return text.substring( 0, index ) ; } // cutTail() // ------------------------------------------------------------------------ /** * Returns the portion of the given string that stands after the last * occurance of the specified separator.
      * If the separator could not be found in the given string, then the * string is returned unchanged. *

      * Examples: *

      * cutHead( "A/B/C", "/" ) ; // returns "C" *
      * cutHead( "A/B/C", "," ) ; // returns "A/B/C" *

      * @see #prefix( String, String ) * @see #cutTail( String, String ) * @see #suffix( String, String ) * @see #startingFrom( String, String ) * @see #upTo( String, String ) * @param text The string from which to cut off the head * @param separator The separator up to which to cut off * @return the string without the separator and without the characters before the separator */ public String cutHead( String text, String separator ) { int index ; if ( ( text == null ) || ( separator == null ) ) return text ; index = text.lastIndexOf( separator ) ; if ( index < 0 ) return text ; return text.substring( index + 1 ) ; } // cutHead() // ------------------------------------------------------------------------ /** * Returns a string array with two elements where the first is the attribute * name and the second is the attribute value. * Splits the given string at the first occurance of separator and returns * the piece before the separator in element 0 and the piece after the * separator in the returned array. * If the separator is not found, the first element contains the full * string and the second an empty string. * * @param str The string that contains the name-value pair * @param separator The separator between name and value */ public String[] splitNameValue( String str, String separator ) { String[] result = { "", "" } ; int index ; if ( str != null ) { index = str.indexOf( separator ) ; if ( index > 0 ) { result[0] = str.substring( 0, index ) ; result[1] = str.substring( index + separator.length() ) ; } else { result[0] = str ; } } return result ; } // splitNameValue() // ------------------------------------------------------------------------- /** * Returns the substring of the given string that comes before the * first occurance of the specified separator. * If the string starts with a separator, the result will be an empty string. * If the string doesn't contain the separator the method returns null. *

      * Examples: *

      * prefix( "A/B/C", "/" ) ; // returns "A" *
      * prefix( "A/B/C", "," ) ; // returns null *

      * @see #suffix( String, String ) * @see #cutTail( String, String ) * @see #cutHead( String, String ) * @see #startingFrom( String, String ) * @see #upTo( String, String ) * @param str The string of which the prefix is desired * @param separator Separates the prefix from the rest of the string */ public String prefix( String str, String separator ) { return this.prefix( str, separator, true ) ; } // prefix() // ------------------------------------------------------------------------- /** * Returns the substring of the given string that comes after the * first occurance of the specified separator. * If the string ends with a separator, the result will be an empty string. * If the string doesn't contain the separator the method returns null. *

      * Examples: *

      * suffix( "A/B/C", "/" ) ; // returns "B/C" *
      * suffix( "A/B/C", "," ) ; // returns null *

      * @see #prefix( String, String ) * @see #cutTail( String, String ) * @see #cutHead( String, String ) * @see #startingFrom( String, String ) * @see #upTo( String, String ) * @param str The string of which the suffix is desired * @param separator Separates the suffix from the rest of the string */ public String suffix( String str, String separator ) { return this.suffix( str, separator, true ) ; } // suffix() // ------------------------------------------------------------------------- /** * Returns the substring of the given string that comes before the * first occurance of the specified separator. * If the string starts with a separator, the result will be an empty string. * If the string doesn't contain the separator the method returns the * whole string unchanged. *

      * Examples: *

      * upTo( "A/B/C", "/" ) ; // returns "A" *
      * upTo( "A/B/C", "," ) ; // returns "A/B/C" *
      * upTo( "/A/B/C", "/" ) ; // returns "" *

      * @see #prefix( String, String ) * @see #cutTail( String, String ) * @see #cutHead( String, String ) * @see #startingFrom( String, String ) * @see #suffix( String, String ) * @param str The string of which the prefix is desired * @param separator Separates the prefix from the rest of the string */ public String upTo( String str, String separator ) { return this.prefix( str, separator, false ) ; } // upTo() // ------------------------------------------------------------------------- /** * Returns the substring of the given string that comes after the * first occurance of the specified separator. * If the string doesn't contain the separator the method returns the * whole string unchanged. *

      * Examples: *

      * startingFrom( "A/B/C", "/" ) ; // returns "B/C" *
      * startingFrom( "A/B/C", "," ) ; // returns "A/B/C" *

      * @see #prefix( String, String ) * @see #cutTail( String, String ) * @see #cutHead( String, String ) * @see #suffix( String, String ) * @see #upTo( String, String ) * @param str The string of which the suffix is desired * @param separator Separates the suffix from the rest of the string */ public String startingFrom( String str, String separator ) { return this.suffix( str, separator, false ) ; } // startingFrom() // ------------------------------------------------------------------------- /** * Returns a string that contains all characters of the given string in * reverse order. */ public String reverse( String str ) { if ( str == null ) return null ; char[] newStr = new char[str.length()] ; StringCharacterIterator iterator = new StringCharacterIterator(str) ; int i = 0 ; for(char ch = iterator.last(); ch != CharacterIterator.DONE; ch = iterator.previous()) { newStr[i] = ch ; i++ ; } return new String( newStr ) ; } // reverse() // ------------------------------------------------------------------------- /** * Returns the given map with new entries from the specified String. * If the specified map is null a new empty java.util.Hashtable will be * created. *
      * The string is split up into elements separated by the elementSeparator * parameter. If this parameter is null the default separator "," is used. *
      * After that each part is split up to a key-value pair separated by the * keyValueSeparator parameter. If this parameter is null the default "=" is * used. *
      * Then the key-value pairs are added to the map and the map is returned. *

      * Be aware that all leading and trailing whitespaces of keys and values * will be removed! * * @param str The string that contains the list of key-value pairs * @param elementSeparator The separator between the elements of the list * @param keyValueSeparator The separator between the keys and values * @param map The map to which the key-value pairs are added */ public Map toMap( String str, String elementSeparator, String keyValueSeparator, Map map ) { Map result ; String elemSep ; String kvSep ; String[] assignments ; String[] nameValue ; if ( str == null ) return map ; result = ( map == null ? new Hashtable() : map ) ; elemSep = ( elementSeparator == null ) ? "," : elementSeparator ; kvSep = ( keyValueSeparator == null ) ? "=" : keyValueSeparator ; assignments = this.parts( str, elemSep ) ; for ( int i = 0 ; i < assignments.length ; i++ ) { nameValue = this.splitNameValue( assignments[i], kvSep ) ; nameValue[0] = nameValue[0].trim() ; nameValue[1] = nameValue[1].trim() ; if ( nameValue[0].length() > 0 ) result.put( nameValue[0], nameValue[1] ) ; } return result ; } // asMap() // ------------------------------------------------------------------------- /** * Returns a new map object that contains all key-value pairs of the * specified string. *
      * The separator between the elements is assumed to be "," * and "=" between key and value. *

      * Example:
      * "main=Fred,support1=John,support2=Stella,manager=Oscar" *

      * Be aware that all leading and trailing whitespaces of keys and values * will be removed! * * @param str The string with the list of key-value pairs */ public Map asMap( String str ) { return this.toMap( str, null, null, null ) ; } // asMap() // ------------------------------------------------------------------------- /** * Returns a new map object that contains all key-value pairs of the * specified string. *
      * The separator between the keys and values is assumed to be "=". *

      * Be aware that all leading and trailing whitespaces of keys and values * will be removed! * * @param str The string that contains the list of key-value pairs * @param elementSeparator The separator between the elements of the list */ public Map asMap( String str, String elementSeparator ) { return this.toMap( str, elementSeparator, null, null ) ; } // asMap() // ------------------------------------------------------------------------- /** * Returns a new map object that contains all key-value pairs of the * specified string. *

      * Be aware that all leading and trailing whitespaces of keys and values * will be removed! * * @param str The string that contains the list of key-value pairs * @param elementSeparator The separator between the elements of the list * @param keyValueSeparator The separator between the keys and values */ public Map asMap( String str, String elementSeparator, String keyValueSeparator ) { return this.toMap( str, elementSeparator, keyValueSeparator, null ) ; } // asMap() // ------------------------------------------------------------------------- /** * Returns the given map object with all key-value pairs of the * specified string added to it. *
      * The separator between the keys and values is assumed to be "=". *

      * Be aware that all leading and trailing whitespaces of keys and values * will be removed! * * @param str The string that contains the list of key-value pairs * @param elementSeparator The separator between the elements of the list * @param map The map to which the key-value pairs are added */ public Map toMap( String str, String elementSeparator, Map map ) { return this.toMap( str, elementSeparator, null, map ) ; } // toMap() // ------------------------------------------------------------------------- /** * Adds all key-value pairs of the given string to the specified map. *
      * The separator between the elements is assumed to be "," * and "=" between key and value. *

      * Be aware that all leading and trailing whitespaces of keys and values * will be removed! * * @param str The string that contains the list of key-value pairs * @param map The map to which the key-value pairs are added */ public Map toMap( String str, Map map ) { return this.toMap( str, null, null, map ) ; } // toMap() // ------------------------------------------------------------------------- /** * Adds all key-value pairs of the given string to a new properties object. *
      * The separator between the elements is assumed to be "," * and "=" between key and value. *

      * Be aware that all leading and trailing whitespaces of keys and values * will be removed! * * @param str The string that contains the list of key-value pairs */ public Properties asProperties( String str ) { return this.toProperties( str, null ) ; } // asProperties() // ------------------------------------------------------------------------- /** * Adds all key-value pairs of the given string to the specified properties. *
      * The separator between the elements is assumed to be "," * and "=" between key and value. *

      * Be aware that all leading and trailing whitespaces of keys and values * will be removed! * * @param str The string that contains the list of key-value pairs * @param properties The properties where the key-value pairs should be added */ public Properties toProperties( String str, Properties properties ) { Properties props = ( properties == null ) ? new Properties() : properties ; return (Properties)this.toMap( str, null, null, props ) ; } // toProperties() // ------------------------------------------------------------------------- // ========================================================================= // PROTECTED INSTANCE METHODS // ========================================================================= /** * Cuts off all leading and trailing occurences of separator in text. */ protected String trimSeparator( String text, String separator ) { int sepLen = separator.length() ; while ( text.startsWith( separator ) ) text = text.substring( separator.length() ) ; while ( text.endsWith( separator ) ) text = text.substring( 0, text.length() - sepLen ) ; return text ; } // trimSeparator() // ------------------------------------------------------------------------- /** * Returns an array of substrings of the given text.
      * The separators between the substrings are the given delimiters. * Each character in the delimiter string is treated as a separator. * * @param text The string that should be splitted into substrings * @param delimiters All characters that should be recognized as a separator or substrings * @param all If true, empty elements will be returned, otherwise thye are skipped * @return An array of substrings of the given text */ protected String[] parts( String text, String delimiters, boolean all ) { ArrayList result = null ; StringTokenizer tokenizer = null ; if ( text == null ) return null ; if ( ( delimiters == null ) || ( delimiters.length() == 0 ) ) { String[] resultArray = { text } ; return resultArray ; } if ( text.length() == 0 ) { return new String[0] ; } else { result = new ArrayList() ; tokenizer = new StringTokenizer( text, delimiters, all ) ; if ( all ) this.collectParts( result, tokenizer, delimiters ) ; else this.collectParts( result, tokenizer ) ; } return (String[])result.toArray( new String[0] ) ; } // parts() // ------------------------------------------------------------------------- protected void collectParts( List list, StringTokenizer tokenizer ) { while( tokenizer.hasMoreTokens() ) { list.add( tokenizer.nextToken() ) ; } } // collectParts() // ------------------------------------------------------------------------- protected void collectParts( List list, StringTokenizer tokenizer, String delimiter ) { String token ; boolean lastWasDelimiter = false ; while( tokenizer.hasMoreTokens() ) { token = tokenizer.nextToken() ; if ( delimiter.indexOf( token ) >= 0 ) { if ( lastWasDelimiter ) list.add( "" ) ; lastWasDelimiter = true ; } else { list.add( token ) ; lastWasDelimiter = false ; } } } // collectParts() // ------------------------------------------------------------------------- /** * Returns the given text split up into an array of strings, at * the occurrances of the separator string. * * In contrary to method parts() the separator is a one or many * character sequence delimiter. That is, only the exact sequence * of the characters in separator identifies the end of a substring. * Parameter all defines whether empty strings between consecutive * separators are added to the result or not. * * @see #parts(String, String, boolean) * @param text The text to be split up * @param separator The string that separates the substrings * @param all If true, empty strings are added, otherwise skipped * @return An array of substrings not containing any separator anymore */ protected String[] substrings( String text, String separator, boolean all ) { int index = 0 ; int start = 0 ; int sepLen = 0 ; int strLen = 0 ; String str = text ; ArrayList strings = new ArrayList() ; if ( text == null ) return new String[0] ; if ( ( separator == null ) || ( separator.length() == 0 ) ) { if ( text.length() == 0 ) return new String[0] ; String[] resultArray = { text } ; return resultArray ; } if ( ! all ) str = this.trimSeparator( text, separator ) ; strLen = str.length() ; if ( strLen > 0 ) { sepLen = separator.length() ; index = str.indexOf( separator, start ) ; while ( index >= 0 ) { if ( all ) { if ( index > 0 ) { strings.add( str.substring( start, index ) ) ; } } else { if ( index > ( start + sepLen ) ) strings.add( str.substring( start, index ) ) ; } start = index + sepLen ; index = str.indexOf( separator, start ) ; } if ( start < strLen ) strings.add( str.substring( start ) ) ; } return (String[])strings.toArray( new String[0] ) ; } // substrings() // ------------------------------------------------------------------------- protected String padCh( String str, int len, char ch, boolean left ) { StringBuffer buffer = null ; int missing = len - str.length() ; if ( missing <= 0 ) return str ; buffer = new StringBuffer( len ) ; if ( ! left ) buffer.append( str ) ; for ( int i = 1 ; i <= missing ; i++ ) buffer.append( ch ) ; if ( left ) buffer.append( str ) ; return buffer.toString() ; } // padCh() // ------------------------------------------------------------------------- protected int indexOfString( String[] strArray, String searchStr, boolean ignoreCase ) { if ( ( strArray == null ) || ( strArray.length == 0 ) ) return -1 ; boolean found = false ; for ( int i = 0 ; i < strArray.length ; i++ ) { if ( strArray[i] == null ) { if ( searchStr == null ) found = true ; } else { if ( ignoreCase ) found = strArray[i].equalsIgnoreCase( searchStr ) ; else found = strArray[i].equals( searchStr ) ; } if ( found ) return i ; } return -1 ; } // indexOfString() // ------------------------------------------------------------------------- /** * Returns the substring of the given string that comes before the * first occurance of the specified separator. * If the string starts with a separator, the result will be an empty string. * If the string doesn't contain the separator the method returns null or * the whole string, depending on the returnNull flag. * * @param str The string of which the prefix is desired * @param separator Separates the prefix from the rest of the string * @param returnNull Specifies if null will be returned if no separator is found */ protected String prefix( String str, String separator, boolean returnNull ) { if ( str == null ) return null ; if ( separator == null ) return ( returnNull ? null : str ) ; int index = str.indexOf( separator ) ; if ( index >= 0 ) return str.substring( 0, index ) ; else return ( returnNull ? null : str ) ; } // prefix() // ------------------------------------------------------------------------- /** * Returns the substring of the given string that comes after the * first occurance of the specified separator. * If the string ends with a separator, the result will be an empty string. * If the string doesn't contain the separator the method returns null or * the whole string, depending on the returnNull flag. * * @param str The string of which the suffix is desired * @param separator Separates the suffix from the rest of the string * @param returnNull Specifies if null will be returned if no separator is found */ protected String suffix( String str, String separator, boolean returnNull ) { if ( str == null ) return null ; if ( separator == null ) return ( returnNull ? null : str ) ; int index = str.indexOf( separator ) ; if ( index >= 0 ) return str.substring( index + separator.length() ) ; else return ( returnNull ? null : str ) ; } // suffix() // ------------------------------------------------------------------------- /** * Removes the given strings from the array. * If removeStrings is null it means that all null values are removed from * the first array. */ protected String[] removeFromStringArray( String[] strings, String[] removeStrings ) { List list ; boolean remains ; list = new ArrayList( strings.length ) ; for (int i = 0; i < strings.length; i++) { if ( removeStrings == null ) { remains = strings[i] != null ; } else { remains = ! this.contains( removeStrings, strings[i] ) ; } if ( remains ) { list.add( strings[i] ) ; } } return (String[])list.toArray( new String[list.size()] ) ; } // removeFromStringArray() // ------------------------------------------------------------------------- } // class StringUtil azureus-4.3.0.6/org/pf/text/StringExaminer.java0000644000175000017500000001533210024456444020627 0ustar adrianadrian// =========================================================================== // CONTENT : CLASS StringExaminer // AUTHOR : Manfred Duchrow // VERSION : 1.0 - 29/09/2002 // HISTORY : // 29/09/2002 duma CREATED // // Copyright (c) 2002, by Manfred Duchrow. All rights reserved. // =========================================================================== package org.pf.text ; // =========================================================================== // IMPORTS // =========================================================================== /** * As a subclass of StringScanner this class allows more advanced navigation * over the underlying string.
      * That includes moving to positions of specific substrings etc. * * @author Manfred Duchrow * @version 1.0 */ public class StringExaminer extends StringScanner { // ========================================================================= // CONSTANTS // ========================================================================= // ========================================================================= // INSTANCE VARIABLES // ========================================================================= private boolean ignoreCase = false ; protected boolean ignoreCase() { return ignoreCase ; } protected void ignoreCase( boolean newValue ) { ignoreCase = newValue ; } // ========================================================================= // CLASS METHODS // ========================================================================= // ========================================================================= // CONSTRUCTORS // ========================================================================= /** * Initialize the new instance with the string to examine.
      * The string will be treated case-sensitive. * * @param stringToExamine The string that should be examined */ public StringExaminer( String stringToExamine ) { this( stringToExamine, false ) ; } // StringExaminer() // ------------------------------------------------------------------------- /** * Initialize the new instance with the string to examine. * * @param stringToExamine The string that should be examined * @param ignoreCase Specified whether or not treating the string case insensitive */ public StringExaminer( String stringToExamine, boolean ignoreCase ) { super( stringToExamine ) ; this.ignoreCase( ignoreCase ) ; } // StringExaminer() // ------------------------------------------------------------------------- // ========================================================================= // PUBLIC INSTANCE METHODS // ========================================================================= /** * Increments the position pointer up to the last character that matched * the character sequence in the given matchString. * Returns true, if the matchString was found, otherwise false. *

      * If the matchString was found, the next invocation of method nextChar() * returns the first character after that matchString. * * @param matchString The string to look up */ public boolean skipAfter( String matchString ) { char ch = '-' ; char matchChar = ' ' ; boolean found = false ; int index = 0 ; if ( ( matchString == null ) || ( matchString.length() == 0 ) ) return false ; ch = this.nextChar() ; while ( ( endNotReached( ch ) ) && ( ! found ) ) { matchChar = matchString.charAt( index ) ; if ( this.charsAreEqual( ch, matchChar ) ) { index++ ; if ( index >= matchString.length() ) // whole matchString checked ? { found = true ; } else { ch = this.nextChar() ; } } else { if ( index == 0 ) { ch = this.nextChar() ; } else { index = 0 ; } } } return found ; } // skipAfter() // ------------------------------------------------------------------------- /** * Increments the position pointer up to the first character before * the character sequence in the given matchString. * Returns true, if the matchString was found, otherwise false. *

      * If the matchString was found, the next invocation of method nextChar() * returns the first character of that matchString from the position where * it was found inside the examined string. * * @param matchString The string to look up */ public boolean skipBefore( String matchString ) { boolean found ; found = this.skipAfter( matchString ) ; if ( found ) this.skip( 0 - matchString.length() ) ; return found ; } // skipBefore() // ------------------------------------------------------------------------- /** * Returns the a string containing all characters from the current position * up to the end of the examined string.
      * The character position of the examiner is not changed by this * method. */ public String peekUpToEnd() { return this.upToEnd( true ) ; } // peekUpToEnd() // ------------------------------------------------------------------------- /** * Returns the a string containing all characters from the current position * up to the end of the examined string.
      * The character position is put to the end by this method. * That means the next invocation of nextChar() returns END_REACHED. */ public String upToEnd() { return this.upToEnd( false ) ; } // upToEnd() // ------------------------------------------------------------------------- // ========================================================================= // PROTECTED INSTANCE METHODS // ========================================================================= protected boolean charsAreEqual( char char1, char char2) { return ( this.ignoreCase() ) ? ( Character.toUpperCase(char1) == Character.toUpperCase( char2 ) ) : ( char1 == char2 ) ; } // charsAreEqual() // ------------------------------------------------------------------------- /** * Returns the a string containing all characters from the current position * up to the end of the examined string.
      * Depending on the peek flag the character position of the examiner * is unchanged (true) after calling this method or points behind the strings * last character. */ protected String upToEnd( boolean peek ) { char result = '-' ; int lastPosition = 0 ; StringBuffer buffer = new StringBuffer( 100 ) ; lastPosition = this.getPosition() ; result = this.nextChar() ; while ( endNotReached( result ) ) { buffer.append( result ) ; result = this.nextChar() ; } if ( peek ) this.setPosition( lastPosition ) ; return buffer.toString() ; } // upToEnd() // ------------------------------------------------------------------------- } // class StringExaminerazureus-4.3.0.6/org/pf/text/StringScanner.java0000644000175000017500000001442510024456444020452 0ustar adrianadrian// =========================================================================== // CONTENT : CLASS StringScanner // AUTHOR : Manfred Duchrow // VERSION : 1.1 - 29/09/2002 // HISTORY : // 11/07/2001 duma CREATED // 29/09/2002 duma added -> endReached(), endNotReached() // // Copyright (c) 2001-2002, by Manfred Duchrow. All rights reserved. // =========================================================================== package org.pf.text; // =========================================================================== // IMPORTS // =========================================================================== /** * Simple scanner that allows to navigate over the characters of a string. * * @author Manfred Duchrow * @version 1.1 */ public class StringScanner { // ========================================================================= // CONSTANTS // ========================================================================= public static final char END_REACHED = (char)-1 ; // ========================================================================= // INSTANCE VARIABLES // ========================================================================= protected int length = 0 ; protected int position = 0 ; protected int pos_marker = 0 ; protected char[] buffer = null ; // ========================================================================= // PUBLIC CLASS METHODS // ========================================================================= /** * Returns true, if the given character indicates that the end of the * scanned string is reached. */ public boolean endReached( char character ) { return ( character == END_REACHED ) ; } // endReached() // ------------------------------------------------------------------------- /** * Returns true, if the given character does not indicate that the * end of the scanned string si reached. */ public boolean endNotReached( char character ) { return ( ! endReached( character ) ) ; } // endNotReached() // ------------------------------------------------------------------------- // ========================================================================= // CONSTRUCTORS // ========================================================================= /** * Initialize the new instance with the string that should be scanned. */ public StringScanner( String stringToScan ) { super() ; length = stringToScan.length() ; buffer = new char[length] ; stringToScan.getChars( 0, length, buffer, 0 ) ; } // StringScanner() // ========================================================================= // PUBLIC INSTANCE METHODS // ========================================================================= /** * Returns the string the scanner was initialized with */ public String toString() { return new String( buffer ) ; } // toString() // ------------------------------------------------------------------------- /** * Moves the position pointer count characters. * positive values move forwards, negative backwards. * The position never becomes negative ! */ public void skip( int count ) { position += count ; if ( position < 0 ) position = 0 ; } // skip() // ------------------------------------------------------------------------- /** * Returns the character at the current position without changing * the position, that is subsequent calls to this method return always * the same character. */ public char peek() { return ( position < length() ? buffer[position] : END_REACHED ) ; } // skip() // ------------------------------------------------------------------------- /** * Returns the character at the current position and increments * the position afterwards by 1. */ public char nextChar() { char next = this.peek() ; if ( endNotReached( next ) ) this.skip(1); return next ; } // nextChar() // ------------------------------------------------------------------------- /** * Returns true, if the scanner has reached the end and a further invocation * of nextChar() would return the END_REACHED character. */ public boolean atEnd() { return ( endReached( this.peek() ) ) ; } // atEnd() // ------------------------------------------------------------------------- /** * Returns true, if the scanner has not yet reached the end. */ public boolean hasNext() { return ! this.atEnd() ; } // hasNext() // ------------------------------------------------------------------------- /** * Returns the next character that is no whitespace and leaves the * position pointer one character after the returned one. */ public char nextNoneWhitespaceChar() { char next = this.nextChar() ; while ( ( endNotReached( next ) ) && ( Character.isWhitespace(next) ) ) { next = this.nextChar() ; } return next ; } // nextNoneWhitespaceChar() // ------------------------------------------------------------------------- /** * Returns the current position in the string */ public int getPosition() { return position ; } // getPosition() // ------------------------------------------------------------------------- /** * Remembers the current position for later use with restorePosition() */ public void markPosition() { pos_marker = position ; } // markPosition() // ------------------------------------------------------------------------- /** * Restores the position to the value of the latest markPosition() call */ public void restorePosition() { this.setPosition( pos_marker ) ; } // restorePosition() // ------------------------------------------------------------------------- // ========================================================================= // PROTECTED INSTANCE METHODS // ========================================================================= protected int length() { return length ; } // length() // ------------------------------------------------------------------------- protected void setPosition( int pos ) { if ( ( pos >= 0 ) && ( pos <= this.length() ) ) position = pos ; } // setPosition() // ------------------------------------------------------------------------- } // class StringScannerazureus-4.3.0.6/org/pf/text/StringPattern.java0000644000175000017500000003760110024456444020477 0ustar adrianadrian// =========================================================================== // CONTENT : CLASS StringPattern // AUTHOR : Manfred Duchrow // VERSION : 1.7 - 13/02/2003 // HISTORY : // 24/01/2000 duma CREATED // 08/01/2002 duma bugfix -> Handle *xxx (equal characters after star) correctly // 16/01/2002 duma changed -> Implements Serializable // 06/07/2002 duma bugfix -> Couldn't match "London" on "L*n" // 19/09/2002 duma bugfix -> Couldn't match "MA_DR_HRBLUB" on "*_HR*" // 19/09/2002 duma changed -> Using now StringExaminer instead of CharacterIterator // 29/09/2002 duma changed -> Refactored: Using StringExaminer instead of StringScanner // 26/12/2002 duma changed -> Comment of matches() was wrong / new hasWildcard() // 13/02/2003 duma added -> setDigitWildcardChar() // // Copyright (c) 2000-2003, by Manfred Duchrow. All rights reserved. // =========================================================================== package org.pf.text; // =========================================================================== // IMPORTS // =========================================================================== import java.io.Serializable ; /** * This class provides services for checking strings against string-patterns. * Currently it supports the wildcards
      * '*' for any number of any character and
      * '?' for any one character. * * The API is very simple:
      *
      * There are only the two class methods match() and matchIgnoreCase(). *
      * Example: *
      * StringPattern.match( 'Hello World", "H* W*" ) ; --> evaluates to true
      * StringPattern.matchIgnoreCase( 'StringPattern", "str???pat*" ) ; --> evaluates to true
      * * * @author Manfred Duchrow * @version 1.7 */ public class StringPattern implements Serializable { // ========================================================================= // CONSTANTS // ========================================================================= protected final static String MULTI_WILDCARD = "*" ; protected final static char MULTICHAR_WILDCARD = '*' ; protected final static char SINGLECHAR_WILDCARD = '?' ; // ========================================================================= // INSTANCE VARIABLES // ========================================================================= private boolean ignoreCase = false ; /** * Returns whether or not the pattern matching ignores upper and lower case */ public boolean getIgnoreCase() { return ignoreCase ; } /** * Sets whether the pattern matching should ignore case or not */ public void setIgnoreCase( boolean newValue ) { ignoreCase = newValue ; } private String pattern = null ; /** * Returns the pattern as string. */ public String getPattern() { return pattern ; } /** * Sets the pattern to a new value */ public void setPattern( String newValue ) { pattern = newValue ; } // ------------------------------------------------------------------------- private Character digitWildcard = null ; protected Character digitWildcard() { return digitWildcard ; } protected void digitWildcard( Character newValue ) { digitWildcard = newValue ; } // ========================================================================= // CLASS METHODS // ========================================================================= /** * Returns true, if the given probe string matches the given pattern.
      * The character comparison is done case sensitive. * * @param probe The string to check against the pattern. * @param pattern The patter, that probably contains wildcards ( '*' or '?' ) */ public static boolean match( String probe, String pattern ) { StringPattern stringPattern = new StringPattern( pattern, false ) ; return ( stringPattern.matches( probe ) ) ; } // match() // ------------------------------------------------------------------------- /** * Returns true, if the given probe string matches the given pattern.
      * The character comparison is done ignoring upper/lower-case. * * @param probe The string to check against the pattern. * @param pattern The patter, that probably contains wildcards ( '*' or '?' ) */ public static boolean matchIgnoreCase( String probe, String pattern ) { StringPattern stringPattern = new StringPattern( pattern, true ) ; return ( stringPattern.matches( probe ) ) ; } // matchIgnoreCase() // ------------------------------------------------------------------------- // ========================================================================= // CONSTRUCTORS // ========================================================================= /** * Initializes the new instance with the string pattern and the selecteion, * if case should be ignored when comparing characters. * * @param pattern The pattern to check against ( May contain '*' and '?' wildcards ) * @param ignoreCase Definition, if case sensitive character comparison or not. */ public StringPattern( String pattern, boolean ignoreCase ) { this.setPattern( pattern ) ; this.setIgnoreCase( ignoreCase ) ; } // StringPattern() // ------------------------------------------------------------------------- /** * Initializes the new instance with the string pattern. * The default is case sensitive checking. * * @param pattern The pattern to check against ( May contain '*' and '?' wildcards ) */ public StringPattern( String pattern ) { this( pattern, false) ; } // StringPattern() // ------------------------------------------------------------------------- /** * Initializes the new instance with the string pattern and a digit wildcard * character. * The default is case sensitive checking. * * @param pattern The pattern to check against ( May contain '*', '?' wildcards and the digit wildcard ) * @param digitWildcard A wildcard character that stands as placeholder for digits */ public StringPattern( String pattern, char digitWildcard ) { this( pattern, false, digitWildcard ) ; } // StringPattern() // ------------------------------------------------------------------------- /** * Initializes the new instance with the string pattern and the selecteion, * if case should be ignored when comparing characters plus a wildcard * character for digits. * * @param pattern The pattern to check against ( May contain '*' and '?' wildcards ) * @param ignoreCase Definition, if case sensitive character comparison or not. * @param digitWildcard A wildcard character that stands as placeholder for digits */ public StringPattern( String pattern, boolean ignoreCase, char digitWildcard ) { this.setPattern( pattern ) ; this.setIgnoreCase( ignoreCase ) ; this.setDigitWildcardChar( digitWildcard ) ; } // StringPattern() // ------------------------------------------------------------------------- // ========================================================================= // PUBLIC INSTANCE METHODS // ========================================================================= /** * Tests if a specified string matches the pattern. * * @param probe The string to compare to the pattern * @return true if and only if the probe matches the pattern, false otherwise. */ public boolean matches( String probe ) { StringExaminer patternIterator = null ; StringExaminer probeIterator = null ; char patternCh = '-' ; char probeCh = '-' ; String newPattern = null ; String subPattern = null ; int charIndex = 0 ; if ( probe == null ) return false ; if ( probe.length() == 0 ) return false ; patternIterator = this.newExaminer( this.getPattern() ) ; probeIterator = this.newExaminer( probe ) ; probeCh = probeIterator.nextChar() ; patternCh = this.getPatternChar( patternIterator, probeCh ) ; while ( ( this.endNotReached( patternCh ) ) && ( this.endNotReached( probeCh ) ) ) { if ( patternCh == MULTICHAR_WILDCARD ) { patternCh = this.skipWildcards( patternIterator ) ; if ( this.endReached( patternCh ) ) { return true ; // No more characters after multi wildcard - So everything matches } else { patternIterator.skip(-1) ; newPattern = this.upToEnd( patternIterator ) ; charIndex = newPattern.indexOf( MULTICHAR_WILDCARD ) ; if ( charIndex >= 0 ) { subPattern = newPattern.substring( 0, charIndex ) ; if ( this.skipAfter( probeIterator, subPattern ) ) { patternIterator = this.newExaminer( newPattern.substring( charIndex ) ) ; patternCh = probeCh ; } else { return false ; } } else { probeIterator.skip(-1) ; return this.matchReverse( newPattern, probeIterator ) ; } } } if ( this.charsAreEqual( probeCh, patternCh ) ) { if ( this.endNotReached(patternCh) ) { probeCh = probeIterator.nextChar() ; patternCh = this.getPatternChar( patternIterator, probeCh ) ; } } else { if ( patternCh != MULTICHAR_WILDCARD ) return false ; // character is not matching - return immediately } } // while() return ( ( this.endReached( patternCh ) ) && ( this.endReached( probeCh ) ) ) ; } // matches() // ------------------------------------------------------------------------- /** * Returns the pattern string. * * @see java.lang.Object#toString() */ public String toString() { if ( this.getPattern() == null ) return super.toString() ; else return this.getPattern() ; } // toString() // ------------------------------------------------------------------------- /** * Returns true if the pattern contains any '*' or '?' wildcard character. */ public boolean hasWildcard() { if ( this.getPattern() == null ) return false ; if ( this.hasDigitWildcard() ) { if ( this.getPattern().indexOf( this.digitWildcardChar() ) >= 0 ) return true ; } return ( this.getPattern().indexOf( MULTI_WILDCARD ) >= 0 ) || ( this.getPattern().indexOf( SINGLECHAR_WILDCARD ) >= 0 ) ; } // hasWildcard() // ------------------------------------------------------------------------- /** * Sets the given character as a wildcard character in this pattern to * match only digits ('0'-'9').
      * * @param digitWildcard The placeholder character for digits */ public void setDigitWildcardChar( char digitWildcard ) { if ( digitWildcard <= 0 ) { this.digitWildcard( null ) ; } else { this.digitWildcard( new Character( digitWildcard ) ) ; } } // setDigitWildcardChar() // ------------------------------------------------------------------------- // ========================================================================= // PROTECTED INSTANCE METHODS // ========================================================================= protected boolean hasDigitWildcard() { return this.digitWildcard() != null ; } // hasDigitWildcard() // ------------------------------------------------------------------------- protected char digitWildcardChar() { if ( this.hasDigitWildcard() ) return this.digitWildcard().charValue() ; else return '\0' ; } // digitWildcardChar() // ------------------------------------------------------------------------- /** * Moves the iterator position to the next character that is no wildcard. * Doesn't skip digit wildcards ! */ protected char skipWildcards( StringExaminer iterator ) { char result = '-' ; do { result = iterator.nextChar() ; } while ( ( result == MULTICHAR_WILDCARD ) || ( result == SINGLECHAR_WILDCARD ) ) ; return result ; } // skipWildcards() // ------------------------------------------------------------------------- /** * Increments the given iterator up to the last character that matched * the character sequence in the given matchString. * Returns true, if the matchString was found, otherwise false. * * @param matchString The string to be found (must not contain *) */ protected boolean skipAfter( StringExaminer examiner, String matchString ) { // Do not use the method of StringExaminer anymore, because digit wildcard // support is in the charsAreEqual() method which is unknown to the examiner. // return examiner.skipAfter( matchString ) ; char ch = '-' ; char matchChar = ' ' ; boolean found = false ; int index = 0 ; if ( ( matchString == null ) || ( matchString.length() == 0 ) ) return false ; ch = examiner.nextChar() ; while ( ( examiner.endNotReached( ch ) ) && ( ! found ) ) { matchChar = matchString.charAt( index ) ; if ( this.charsAreEqual( ch, matchChar ) ) { index++ ; if ( index >= matchString.length() ) // whole matchString checked ? { found = true ; } else { ch = examiner.nextChar() ; } } else { if ( index == 0 ) { ch = examiner.nextChar() ; } else { index = 0 ; } } } return found ; } // skipAfter() // ------------------------------------------------------------------------- protected String upToEnd( StringExaminer iterator ) { return iterator.upToEnd() ; } // upToEnd() // ------------------------------------------------------------------------- protected boolean matchReverse( String pattern, StringExaminer probeIterator ) { String newPattern ; String newProbe ; StringPattern newMatcher ; newPattern = MULTI_WILDCARD + pattern ; newProbe = this.upToEnd( probeIterator ) ; newPattern = this.strUtil().reverse( newPattern ) ; newProbe = this.strUtil().reverse( newProbe ) ; newMatcher = new StringPattern( newPattern, this.getIgnoreCase() ) ; if ( this.hasDigitWildcard() ) newMatcher.setDigitWildcardChar( this.digitWildcardChar() ) ; return newMatcher.matches( newProbe ) ; } // matchReverse() // ------------------------------------------------------------------------- protected boolean charsAreEqual( char probeChar, char patternChar ) { if ( this.hasDigitWildcard() ) { if ( patternChar == this.digitWildcardChar() ) { return Character.isDigit( probeChar ) ; } } if ( this.getIgnoreCase() ) { return ( Character.toUpperCase(probeChar) == Character.toUpperCase( patternChar ) ) ; } else { return ( probeChar == patternChar ) ; } } // charsAreEqual() // ------------------------------------------------------------------------- protected boolean endReached( char character ) { return ( character == StringExaminer.END_REACHED ) ; } // endReached() // ------------------------------------------------------------------------- protected boolean endNotReached( char character ) { return ( ! endReached( character ) ) ; } // endNotReached() // ------------------------------------------------------------------------- protected char getPatternChar( StringExaminer patternIterator , char probeCh ) { char patternCh ; patternCh = patternIterator.nextChar() ; return ( ( patternCh == SINGLECHAR_WILDCARD ) ? probeCh : patternCh ) ; } // getPatternChar() // ------------------------------------------------------------------------- protected StringExaminer newExaminer( String str ) { return new StringExaminer( str, this.getIgnoreCase() ) ; } // newExaminer() // ------------------------------------------------------------------------- protected StringUtil strUtil() { return StringUtil.current() ; } // strUtil() // ------------------------------------------------------------------------- } // class StringPatternazureus-4.3.0.6/org/pf/release-notes/0000755000175000017500000000000011310377516016604 5ustar adrianadrianazureus-4.3.0.6/org/pf/release-notes/pf.txt0000644000175000017500000000516610024456444017761 0ustar adrianadrianRELEASE NOTES FOR Programmer's Friend Library ============================================== Author : Manfred Duchrow Last Update : July 26, 2003 Version : 2.0 ------------------------------------------------------------------------------- VERSION 2.0 (26/07/2003) NOT RELEASED * PF-Settings 1.5 * PF-File 2.8 * PF-DB 1.4.1 ------------------------------------------------------------------------------- VERSION 1.9 (21/03/2003) * PF-Plugin 1.1 * PF-Net 1.1 * PF-Utilities 2.1 * PF-Text 4.3 * PF-File 2.7 * PF-PAX 1.2.1 * PF-SIX 1.7 ------------------------------------------------------------------------------- VERSION 1.8.1 (14/02/2003) * PF-Text 4.2.1 * PF-File 2.6 ------------------------------------------------------------------------------- VERSION 1.8 (07/02/2003) * PF-File 2.5 * PF-Reflect 1.3 * PF-Plugin 1.0 ------------------------------------------------------------------------------- VERSION 1.7.1 (15/01/2003) * PF-Settings 1.4.2 * PF-Utilities 2.0.1 ------------------------------------------------------------------------------- VERSION 1.7 (04/01/2003) * PF-Settings 1.4 * PF-Net 1.0 * PF-Reflect 1.2 * PF-Utilities 2.0 * PF-Text 4.2 ------------------------------------------------------------------------------- VERSION 1.6.1 (11/12/2002) * PF-Text 4.1.2 * PF-Utilities 1.9.1 ------------------------------------------------------------------------------- VERSION 1.6 (30/10/2002) * PF-Text 4.1.1 * PF-TextX 1.9 * PF-File 2.4 ------------------------------------------------------------------------------- VERSION 1.5 (6/10/2002) * PF-Reflect 1.0 * PF-Utilities 1.9 * PF-Text 4.1 ------------------------------------------------------------------------------- VERSION 1.4 (20.09.2002) * PF-Text 4.0 * PF-Utilities 1.8 ------------------------------------------------------------------------------- VERSION 1.3.2 (19.09.2002) * PF-Text 3.5.1 ------------------------------------------------------------------------------- VERSION 1.3.1 (06.08.2002) * PF-Settings 1.3.1 ------------------------------------------------------------------------------- VERSION 1.3 (25.07.2002) * PF-File 2.3 * PF-Utilities 1.7 * PF-SIX 1.6 ------------------------------------------------------------------------------- VERSION 1.2.1 (19.07.2002) * PF-File 2.2.1 ------------------------------------------------------------------------------- VERSION 1.2 (17.07.2002) * PF-DB 1.4 * PF-Utilities 1.6 * PF-Text 3.5 ------------------------------------------------------------------------------- azureus-4.3.0.6/org/pf/release-notes/pf-text.txt0000644000175000017500000002103210024456444020731 0ustar adrianadrianRELEASE NOTES FOR PACKAGE PF-Text ==================================== Author : Manfred Duchrow Last Update : March 21, 2003 Version : 4.3 ------------------------------------------------------------------------------- VERSION 4.3 (21/03/2003) * New methods in StringUtil - String[] remove( String[], String[] ) - String[] remove( String[], String ) - String[] removeNull( String[] ) - leftPad( int anInteger, int len ) - leftPadCh( int anInteger, int len, char ch ) - rightPad( int anInteger, int len ) - rightPadCh( int anInteger, int len, char ch ) * Optimized performance of methods StringUtil.append() by using System.arraycopy() * New methods in CommandLineArguments - CommandLineArguments( String[] args, String switchIndicator ) - copy() - addOption() - addOptionWithArgument() - removeOption() - removeOPtionWithArgument() * MatchAttribute supports now Integer values in the attributes map for proper integer comparisons ------------------------------------------------------------------------------- VERSION 4.2.1 (13/02/2003) * New methods in StringPattern to support digit wildcard character - setDigitWildcardChar() - 2 new constructors with a digit wildcard char Allows to define match patterns like "AB-###-*" where '#' stands for a single digit character (0-9) which means "AB-263-ff" would match the pattern but "AB-9R1-C" won't. ------------------------------------------------------------------------------- VERSION 4.2 (04/01/2003) * New method in StringPattern - hasWildcard() * MatchAttribute now supports operators - equals - greater - less - greater or equal - less or equal * Extended LdapFilterParser to recognize <= and >= operators * Extended MatchRuleChars with - getEqualsChar(), setEqualsChar() - getGreaterChar(), setGreaterChar() - getLessChar(), setLessChar() * Changed MatchRuleVisitor.attribute() signature to pass the attributes compare operator to it * Changed SqlMatchRuleVisitor to support the new operators * Changed LdapMatchRuleVisitor to support the new operators * Changed MatchRulePrinter to support the new operators ------------------------------------------------------------------------------- VERSION 4.1.2 (22/11/2002) * Support special characters in attribute names with MatchRuleChars.setSpecialNameCharacters() and a modified DefaultMatchRuleParser ------------------------------------------------------------------------------- VERSION 4.1.1 (24/10/2002) * BUGFIX: In MatchGroup.doMatch() Rules with different operators inside a group were evaluated wrong because of 'short circuit' implementation. ------------------------------------------------------------------------------- VERSION 4.1 (30/09/2002) * New methods in StringUtil - allParts() - allSubstrings() * New methods in StringScanner - endReached() - endNotReached() - atEnd() - hasNext() - setPosition() * New class StringExaminer * Refactored StringPattern (now using StringExaminer instead of StringScanner) * Changed all setXXXChar() methods in DefaultMatchRuleParser to visibility 'public' ------------------------------------------------------------------------------- VERSION 4.0 (19.09.2002) * New class DefaultMatchRuleParser which parses the normal MatchRule syntax e.g. (attr1{val1,val2} &! attr2{val3} | attr3{val4} ) * New class MatchRulePrinter which converts a MatchRule to a String using the normal MAtchRule syntax * Re-design of MatchRule, MatchGroup and MatchAttribute - Removed parsing (now done by extra class DefaultMatchRuleParser) - Changed toString() * New class LdapFilterParser to parse an LDAP search filter to a MatchRule * Added two instance variables with setters and getters to MatchRuleParseException - position - parseString * Added new instance variable with setters and getters to MatchAttribute - ignoreCaseInName * Changed methods in StringUtil - suffix() -> Now returns the substring after the first (!) occurance of the separator - cutHead() -> Now returns the substring after the last (!) occurance of the separator - cutTail() -> Now returns the substring before the last (!) occurance of the separator * New methods in StringUtil - upTo() - startingFrom() - toMap() - asMap() - toProperties() - asProperties() * BUGFIX: StringUtil.splitNameValue() didn't remove separators with more than one character correctly. ------------------------------------------------------------------------------- VERSION 3.5.1 (19.09.2002) * BUGFIX: org.pf.text.StringPattern didn't handle the following example correct: StringPattern.match( "MA_DR_HRBLUB", "*_HR*" ) Returned false! After fixing the bug it returns true. During the fix the usage of java.text.CharacterIterator was replaced by org.pf.text.StringScanner. ------------------------------------------------------------------------------- VERSION 3.5 (17.07.2002) * New class CommandLineArguments * BUGFIX: StringUtil.suffix() didn't work correctly for separators with more than one character. ------------------------------------------------------------------------------- VERSION 3.4 (06.07.2002) * Added to StringUtil - indexOf( String[] strArray, StringPattern pattern ) - contains( String[] strArray, StringPattern pattern) - reverse( String str ) * StringPattern.toString() now returns the pattern string * Bugfix in StringPattern.matches() Didn't match "London" on pattern "L*n" ------------------------------------------------------------------------------- VERSION 3.3 (03.07.2002) * Added to StringUtil - cutHead( String text, String separator ) - prefix( String text, String separator ) - suffix( String text, String separator ) ------------------------------------------------------------------------------- VERSION 3.2 (30.05.2002) * Added StringUtil.getDelimitedSubstring( String text, String startDelimiter, String endDelimiter ) * Added StringUtil.cutTail( String text, String separator ) ------------------------------------------------------------------------------- VERSION 3.1 (17.05.2002) - Added StringUtil.copyFrom() ------------------------------------------------------------------------------- VERSION 3.0 (29.04.2002) - Added StringUtil.splitNameValue() - Renamed package from "com.pf.text" to "org.pf.text" ------------------------------------------------------------------------------- VERSION 2.5.1 (16.01.2002) - Made StringPattern serializable ------------------------------------------------------------------------------- VERSION 2.5 (11.01.2002) - New methods in StringUtil - appendIfNotThere() - indexOf() - indexOfIgnoreCase() - contains() - containsIgnoreCase() ------------------------------------------------------------------------------- VERSION 2.4 (08.01.2002) - Made MatchRule, MatchGroup, MatchAttributes and MatchRuleChars serializable - BUGFIX: StringPattern.match() didn't handle "*xxx" patterns (multiple equal character after asterisk) correctly. ------------------------------------------------------------------------------- VERSION 2.3 (24.11.2001) - MatchRule upports now String[] and java.util.List of String as values of attributes inside a map. ------------------------------------------------------------------------------- VERSION 2.2 (12.11.2001) - New methods append( String[], String) and append( String[], String[]) in StringUtil - New methods asString( String[], String separator ) and asString( String[]) in StringUtil - MatchRule now supports NOT (!) before a group or attribute even if there's no preceeding AND/OR (&/|) operator. - Changed LdapMatchRuleVisitor and SqlMatchRuleVisitor to support NOT operation correctly ------------------------------------------------------------------------------- VERSION 2.1 (09.10.2001) - Changed MatchGroup and MatchAttribute and some of their methods to be public, which allows external code to build rules as well. ------------------------------------------------------------------------------- VERSION 2.0 (17.08.2001) - New interface MatchResultVisitor - New class SqlMatchResultVisitor - New class LdapMatchResultVisitor - New methods leftPad(), leftPadCh(), rightPad(), rightPadCh(), center(), centerCh() in class StringUtil azureus-4.3.0.6/org/pf/release-notes/pf-file.txt0000644000175000017500000000760510024456444020676 0ustar adrianadrianFile Utilities Realease-Notes Author: Manfred Duchrow Last update: July 26, 2003 Copyright (c) 2000-2003, by Manfred Duchrow. All rights reserved. ======================================================================= ----------------------------------------------------------------------- VERSION 2.8 ( July 26, 2003 ) * New interface LineProcessor * New methods in FileUtil - processTextLines( String, LineProcessor ) - processTextLines( InputStream, LineProcessor ) - processTextLines( Reader, LineProcessor ) * BUGFIX in FileWalker.walkThrough() NullPointerException if directory.listFiles(..) returns null for protected directories (e.g. "System Volume") * New methods in PropertyFileLoader - loadProperties( String, Properties ) - loadProperties( InputStream, Properties ) - loadProperties( InputStream ) ----------------------------------------------------------------------- VERSION 2.7 ( March 21, 2003 ) * New methods in FileUtil - standardize() - javaFilename() * Modified FileInfo to use FileUtil.javaFilename() * New methods in FileLocator - getStandardizedPath() - getStandardizedAbsolutePath() ----------------------------------------------------------------------- VERSION 2.6 ( February 15, 2003 ) * Reduced test data * ExtendedFileFilter now supports a digit wildcard character for more specific filtering of numeric patterns in filenames. * FileWalker now supports a digit wildcard character for more specific filtering of numeric patterns in filenames. - setDigitWildcardChar() - new constructor * New methods in FileFinder - File[] findFiles( String dir, String pattern, boolean recursive, char digitWildcard ) - File[] findFiles( String dir, String pattern, boolean recursive ) - File[] findFiles( String dir, String pattern ) ----------------------------------------------------------------------- VERSION 2.5 ( February 7, 2003 ) * New class ClasspathElement * New methods in FileUtil - close(InputStream) - close(OutputStream) ----------------------------------------------------------------------- VERSION 2.4 ( October 24, 2002 ) * New methods in FileUtil - readTextFrom( InputStream ) - readTextFrom( String ) - readTextFrom( File ) - copyText( reader, writer ) ----------------------------------------------------------------------- VERSION 2.3 ( July 25, 2002 ) * Depends now on PF-Utilities (NamedValueList, NamedValue, NamedText) * New class ArchiveTOC * New class FileInfo * Removed class ZipFileWalker ----------------------------------------------------------------------- VERSION 2.2.1 ( July 19, 2002 ) * BUGFIX: FileLocator did not recognize existing path that started from root (e.g. /usr/mylib/tets.jar) ----------------------------------------------------------------------- VERSION 2.2 ( June 21, 2002 ) * New method in FileLocator: realFile() ----------------------------------------------------------------------- VERSION 2.1 ( May 24, 2002 ) * FileLocator supports now filenames such as "file:\L:\Java\JDK1.3\lib\rt.jar!\java\util\Hashtable.class" * New methods in FileLocator - toURL() - getAbsolutePath() - isFile() - isDirectory() * FileFinder now returns a filename even if the file is inside an archive, which means that it exists but is not directly accessable. The best way to open an InputStream on such a file is FileLocator. * More UnitTests for PropertyFileLoader, FileFinder and FileLocator ----------------------------------------------------------------------- VERSION 2.0 ( May 18, 2002 ) * New class FileLocator (requires JRE 1.3.1 or later, because JRE 1.3 has a bug in zip.dll concerning the timestamp of zipped files) * New class FileUtil with copyStream() feature ----------------------------------------------------------------------- azureus-4.3.0.6/org/pf/file/0000755000175000017500000000000011310377640014753 5ustar adrianadrianazureus-4.3.0.6/org/pf/file/LineProcessor.java0000644000175000017500000000262010024456444020406 0ustar adrianadrian// =========================================================================== // CONTENT : INTERFACE LineProcessor // AUTHOR : Manfred Duchrow // VERSION : 1.0 - 02/07/2003 // HISTORY : // 02/07/2003 mdu CREATED // // Copyright (c) 2003, by Manfred Duchrow. All rights reserved. // =========================================================================== package org.pf.file ; // =========================================================================== // IMPORTS // =========================================================================== /** * A simple interface that allows processing a longer text line by line. * Usually used together with FileUtil.processTextLines(). * * @author Manfred Duchrow * @version 1.0 */ public interface LineProcessor { // ========================================================================= // PUBLIC INSTANCE METHODS // ========================================================================= /** * Processes the given line and returns true if the caller should continue. * If false is returned, the caller should stop. * * @param line The line to process (must not be null) * @param lineNo The linen number (starting with 1) */ public boolean processLine( String line, int lineNo ) ; // ------------------------------------------------------------------------- } // interface LineProcessor azureus-4.3.0.6/org/pf/file/FileWalker.java0000644000175000017500000001715010024456444017650 0ustar adrianadrian// =========================================================================== // CONTENT : CLASS FileWalker // AUTHOR : Manfred Duchrow // VERSION : 1.2 - 04/07/2003 // HISTORY : // 21/01/2000 duma CREATED // 14/02/2003 duma added -> Support for patterns with wildcards for digits // 04/07/2003 duma bugfix -> NullPointerException in walkThrough for protected directories // // Copyright (c) 2000-2003, by Manfred Duchrow. All rights reserved. // =========================================================================== package org.pf.file; // =========================================================================== // IMPORTS // =========================================================================== import java.io.File; import java.io.FilenameFilter; import org.pf.text.StringUtil; /** * This class provides services to navigate through a file directory and * handle files that match a name filter. * * @author Manfred Duchrow * @version 1.2 */ public class FileWalker { // ========================================================================= // CONSTANTS // ========================================================================= /** * The character to be used to separate filename patterns (';'). */ public static final char PATTERN_SEPARATOR_CHAR = ';' ; /** * The character to be used to separate filename patterns (';') as String. */ public static final String PATTERN_SEPARATOR = ";" ; // ========================================================================= // INSTANCE VARIABLES // ========================================================================= private FileHandler fileHandler = null ; protected FileHandler getFileHandler() { return fileHandler ; } protected void setFileHandler( FileHandler newValue ) { fileHandler = newValue ; } private boolean goOn = true ; protected boolean getGoOn() { return goOn ; } protected void setGoOn( boolean newValue ) { goOn = newValue ; } private Character digitWildcard = null ; protected Character getDigitWildcard() { return digitWildcard ; } protected void setDigitWildcard( Character newValue ) { digitWildcard = newValue ; } // ========================================================================= // CLASS METHODS // ========================================================================= // ========================================================================= // CONSTRUCTORS // ========================================================================= /** * Initialize the new instance with default values. */ public FileWalker( FileHandler handler ) { this.setFileHandler( handler ) ; } // FileWalker() // ------------------------------------------------------------------------- /** * Initialize the new instance with a file handler and a wildcard character * for digits. * * @param handler The file handler that gets all found files * @param digitWildcard A character that is used as wildcard for digits in filname patterns */ public FileWalker( FileHandler handler, char digitWildcard ) { this( handler ) ; this.setDigitWildcardChar( digitWildcard ) ; } // FileWalker() // ------------------------------------------------------------------------- // ========================================================================= // PUBLIC INSTANCE METHODS // ========================================================================= /** * This method starts in the given directory to search for all files * matching the given pattern(s).
      * There can be more than one pattern in the pattern parameter. They have * to be separated by the PATTERN_SEPARATOR (';').

      * If recursive is true it goes down to each subdirectory and doing * the same there.
      * For each matching file (non-directory) the defined FileHandler.handle() * is called. * * @param dir The directory where to start * @param pattern The file name pattern(s) for filtering out the correct files ( wildcards '*' and '?' ) * @param recursive If set to true, the file selection is going down to all subdirectories * @return the number of found files, that have matched the given pattern. */ public long walkThrough( String dir, String pattern, boolean recursive ) { ExtendedFileFilter filter = null ; String[] patterns = null ; String strPattern ; this.setGoOn( true ) ; filter = new ExtendedFileFilter() ; patterns = this.extractPatterns( pattern ) ; for (int i = 0; i < patterns.length; i++) { strPattern = patterns[i] ; if ( this.hasDigitWildcard() ) { filter.addPattern( strPattern, true, this.getDigitWildcardChar() ) ; } else { filter.addPattern( strPattern, true ) ; } } if ( recursive ) filter.alwaysIncludeDirectories() ; else filter.alwaysExcludeDirectories() ; return this.walkThrough( dir, filter, recursive ) ; } // walkThrough() // ------------------------------------------------------------------------- /** * Sets the given character as a wildcard character to match * digits ('0'-'9') only.
      * * @param digitWildcard The placeholder character for digits */ public void setDigitWildcardChar( char digitWildcard ) { if ( digitWildcard <= 0 ) { this.setDigitWildcard( null ) ; } else { this.setDigitWildcard( new Character( digitWildcard ) ) ; } } // setDigitWildcardChar() // ------------------------------------------------------------------------- // ========================================================================= // PROTECTED INSTANCE METHODS // ========================================================================= protected long walkThrough( String dir, FilenameFilter filter, boolean recursive ) { long counter = 0 ; File directory = null ; File file = null ; File[] files = null ; int index = 0 ; directory = new File( dir ) ; files = directory.listFiles( filter ) ; if ( files == null ) // BUGFIX suggested by Kyle Gossman return counter ; this.setGoOn( this.getFileHandler().directoryStart( directory, files.length ) ) ; if ( ! this.getGoOn() ) return counter ; for ( index = 0 ; index < files.length ; index++ ) { file = files[index] ; if ( file.isDirectory() ) { if ( recursive ) { counter += this.walkThrough( file.getPath(), filter, recursive ) ; } } else { this.setGoOn( this.getFileHandler().handleFile( file ) ) ; counter++ ; } if ( ! this.getGoOn() ) break ; } // for this.setGoOn( this.getFileHandler().directoryEnd( directory ) ) ; return counter ; } // walkThrough() // ------------------------------------------------------------------------- protected String[] extractPatterns( String pattern ) { return StringUtil.current().parts( pattern, PATTERN_SEPARATOR ) ; } // extractPatterns() // ------------------------------------------------------------------------- protected char getDigitWildcardChar() { if ( this.hasDigitWildcard() ) return this.getDigitWildcard().charValue() ; else return '\0' ; } // getDigitWildcardChar() // ------------------------------------------------------------------------- protected boolean hasDigitWildcard() { return this.getDigitWildcard() != null ; } // hasDigitWildcard() // ------------------------------------------------------------------------- } // class FileWalkerazureus-4.3.0.6/org/pf/file/FileHandler.java0000644000175000017500000000677310024456444020011 0ustar adrianadrian// =========================================================================== // CONTENT : INTERFACE FileHandler // AUTHOR : Manfred Duchrow // VERSION : 1.0 - 24/01/2000 // HISTORY : // 24/01/2000 duma CREATED // // Copyright (c) 2000, by MDCS. All rights reserved. // =========================================================================== package org.pf.file; // =========================================================================== // IMPORTS // =========================================================================== import java.io.File; /** * This interface must be implemented by classes, that want to use the generic * services of FileWalker.
      * It defines callback methods, that are invoked by a FileWalker instance, when * it is 'walking' through a directory(-tree). * * @see FileWalker * @author Manfred Duchrow * @version 1.0 */ public interface FileHandler { // ------------------------------------------------------------------------- // ========================================================================= // CONSTANTS // ========================================================================= // ========================================================================= // PUBLIC INSTANCE METHODS // ========================================================================= /** * This method is called for each file, that a FileWalker instance finds. * It must return true, if the FileWalker should continue. To stop the * calling FileWalker it can return false. * * @param The file, currently found by the FileWalker instance * @return true to continue, false to terminate processing of files */ public boolean handleFile( File file ) ; // ------------------------------------------------------------------------- /** * This method is called for whenever an exception occurs in walking through * the directories.
      * The method must return true, if the FileWalker should continue. To stop the * calling FileWalker it can return false. * * @param ex The exception to handle * @param The file, currently found by the FileWalker instance * @return true to continue, false to terminate processing of files */ public boolean handleException( Exception ex, File file ) ; // ------------------------------------------------------------------------- /** * This method is called for each directory, that a FileWalker finished to walk through. * It must return true, if the FileWalker should continue. To stop the * calling FileWalker it can return false. * * @param dir The directory, the FileWalker has finished to walk through * @return true to continue, false to terminate processing of files */ public boolean directoryEnd( File dir ) ; // ------------------------------------------------------------------------- /** * This method is called for each directory, that a FileWalker starts to walk through. * It must return true, if the FileWalker should continue. To stop the * calling FileWalker it can return false. * * @param dir The directory, the FileWalker is starting to walk through * @param count The number of files and directories the FileWalker found in the directory * @return true to continue, false to terminate processing of files */ public boolean directoryStart( File dir, int count ) ; // ------------------------------------------------------------------------- } // class FileHandlerazureus-4.3.0.6/org/pf/file/FileUtil.java0000644000175000017500000003210210024456444017332 0ustar adrianadrian// =========================================================================== // CONTENT : CLASS FileUtil // AUTHOR : Manfred Duchrow // VERSION : 1.1 - 14/03/2003 // HISTORY : // 17/05/2002 duma CREATED // 14/03/2003 duma added -> standardize(), javaFilename() // // Copyright (c) 2002-2003, by Manfred Duchrow. All rights reserved. // =========================================================================== package org.pf.file ; // =========================================================================== // IMPORTS // =========================================================================== import java.io.* ; import org.pf.text.StringUtil; /** * This class provides helper methods for file and stream handling. * It's an add-on to the java.io package. * The service is implemented as a singleton, so use the * FileUtil.current() method to get the sole instance. * * @author Manfred Duchrow * @version 1.1 */ public class FileUtil { // ========================================================================= // CONSTANTS // ========================================================================= /** The lines.separator from the system properties as a constant */ public static final String LINE_SEPARATOR = System.getProperty( "line.separator" ) ; protected static final int DEFAULT_BUFFER_SIZE = 1024 ; // ========================================================================= // CLASS VARIABLES // ========================================================================= private static FileUtil current = new FileUtil() ; // ========================================================================= // CLASS METHODS // ========================================================================= // ========================================================================= // CONSTRUCTORS // ========================================================================= /** * Initialize the new instance with default values. */ private FileUtil() { super() ; } // FileUtil() // ========================================================================= // PUBLIC CLASS METHODS // ========================================================================= public static FileUtil current() { return current ; } // current() // ========================================================================= // PUBLIC INSTANCE METHODS // ========================================================================= /** * Copies all data from the iniput stream to the output stream using * a buffer with the default size (1024 bytes). * After all data is copied both streams will be closed ! */ public void copyStream( InputStream inStream, OutputStream outStream ) throws IOException { this.copyStream( inStream, outStream, DEFAULT_BUFFER_SIZE ) ; } // copyStream() // ------------------------------------------------------------------------- /** * Copies all data from the iniput stream to the output stream using * a buffer of the given size in bytes. * After all data is copied both streams will be closed ! */ public void copyStream( InputStream inStream, OutputStream outStream, int bufSize ) throws IOException { byte[] buffer = new byte[bufSize] ; int count ; try { count = inStream.read(buffer) ; while ( count > -1 ) { outStream.write( buffer, 0, count ) ; count = inStream.read(buffer) ; } } finally { this.close(inStream) ; this.close(outStream) ; } } // copyStream() // ------------------------------------------------------------------------- /** * Reads the whole content of the given input stream and returns * it as a string. * The stream will be closed after calling this method. Even if an exception * occured! * * @param inStream The input stream to read * @return The text content of the given stream */ public String readTextFrom( InputStream inStream ) throws IOException { StringWriter writer ; writer = new StringWriter( 1024 ) ; this.copyText( inStream, writer ) ; return writer.toString() ; } // readTextFrom() // ------------------------------------------------------------------------- /** * Reads the whole content of the file with the given name and returns * it as a string. * * @param filename The name of the text containing file */ public String readTextFrom( String filename ) throws IOException { FileInputStream inStream ; inStream = new FileInputStream( filename ) ; return this.readTextFrom( inStream ) ; } // readTextFrom() // ------------------------------------------------------------------------- /** * Reads the whole content of the specified file and returns * it as a string. */ public String readTextFrom( File file ) throws IOException { FileInputStream inStream ; inStream = new FileInputStream( file ) ; return this.readTextFrom( inStream ) ; } // readTextFrom() // ------------------------------------------------------------------------- /** * Copies all text lines from the specified reader to the given writer. * After that the reader will be closed. Even if an exception occurs. * * @param reader The reader which provides the text to copy * @param writer The writer to which the text will be copied */ public void copyText( Reader reader, final StringWriter writer ) throws IOException { BufferedReader bufReader ; String line ; LineProcessor processor ; bufReader = new BufferedReader( reader ) ; try { processor = new LineProcessor() { public boolean processLine( String line, int lineNo ) { if ( lineNo > 1 ) writer.write( LINE_SEPARATOR ) ; writer.write( line ) ; return true ; } } ; this.processTextLines( bufReader, processor ) ; } finally { bufReader.close() ; } } // copyText() // ------------------------------------------------------------------------ /** * Reads all text lines from the file with the specified name and passes them * one by one to the given line processor. * The processing will be terminated, if the end of the text is reached or * if the processor returns false.
      * * @param filename The name of the text file to read * @param processor The processor that receives the lines from the text */ public void processTextLines( String filename, LineProcessor processor ) throws IOException { FileInputStream inStream ; if ( filename == null ) throw new IllegalArgumentException( "filename must not be null" ) ; inStream = new FileInputStream( filename ) ; this.processTextLines( inStream, processor ) ; } // processTextLines() // ------------------------------------------------------------------------- /** * Reads all text lines from the specified input stream and passes them * one by one to the given line processor. * The processing will be terminated, if the end of the text is reached or * if the processor returns false.
      * The given input stream will be closed after the execution of this method. * Even if an exception occured. * * @param inStream The input stream that contains the text * @param processor The processor that receives the lines from the text */ public void processTextLines( InputStream inStream, LineProcessor processor ) throws IOException { InputStreamReader reader ; if ( inStream == null ) throw new IllegalArgumentException( "inStream must not be null" ) ; reader = new InputStreamReader( inStream ) ; this.processTextLines( reader, processor ) ; } // processTextLines() // ------------------------------------------------------------------------- /** * Reads all text lines from the specified reader and passes them one by one * to the given line processor. * The processing will be terminated, if the end of the text is reached or * if the processor returns false. * * @param reader The reader that contains a text stream * @param processor The processor that receives the lines from the text */ public void processTextLines( Reader reader, LineProcessor processor ) throws IOException { BufferedReader bufReader ; String line ; int counter = 0 ; boolean continue_reading = true ; if ( reader == null ) throw new IllegalArgumentException( "reader must not be null" ) ; if ( processor == null ) throw new IllegalArgumentException( "processor must not be null" ) ; bufReader = new BufferedReader( reader ) ; while ( continue_reading && bufReader.ready() ) { line = bufReader.readLine() ; if ( line == null ) break ; counter++ ; continue_reading = processor.processLine( line, counter ) ; } } // processTextLines() // ------------------------------------------------------------------------ /** * Close the given stream ignoring any exception. * Returns true, if the stream was closed successfully, false otherwise */ public boolean close( InputStream stream ) { if ( stream == null ) { return false ; } try { stream.close() ; return true ; } catch (IOException e) { return false ; } } // close() // ------------------------------------------------------------------------- /** * Close the given stream ignoring any exception. * Returns true, if the stream was closed successfully, false otherwise */ public boolean close( OutputStream stream ) { if ( stream == null ) { return false ; } try { stream.close() ; return true ; } catch (IOException e) { return false ; } } // close() // ------------------------------------------------------------------------- /** * Convert the filename to a canonical (see java.io.File.getCanonicalPath()) * format and replace any backslashes '\' by slashes ('/'). * If possible all "." and ".." elements in the path are eliminated. * * @param filename The filename which has to be standardized * @return An absolute filename that uses slashes to separate its elements */ public String standardize( String filename ) { if ( filename == null ) return null ; return this.standardizeFilename( filename ) ; } // standardize() // ------------------------------------------------------------------------- /** * Returns the given filename in the platform independent way that Java * understands. That is all elements are separated by a forward slash rather * than back slashes as on Windows systems. * * @param filename The name to be modified */ public String javaFilename( String filename ) { if ( filename == null ) return null ; return filename.replace( '\\', '/' ) ; } // javaFilename() // ------------------------------------------------------------------------- // ========================================================================= // PROTECTED INSTANCE METHODS // ========================================================================= protected void copyText( InputStream inStream, StringWriter writer ) throws IOException { this.copyText( new InputStreamReader( inStream ), writer ) ; } // copyText() // ------------------------------------------------------------------------ protected String standardizeFilename( String filename ) { String[] nameElements ; boolean hasDriveLetter ; boolean startedFromRoot ; boolean isAbsolute ; int index ; filename = this.javaFilename(filename) ; startedFromRoot = filename.startsWith( "/" ) ; nameElements = this.str().parts( filename, "/" ) ; if ( nameElements.length > 0 ) { hasDriveLetter = nameElements[0].endsWith( ":" ) ; if ( hasDriveLetter ) { nameElements[0] = nameElements[0].toUpperCase() ; } else { if ( startedFromRoot ) { nameElements = this.str().append( new String[] { "" }, nameElements ); } } isAbsolute = hasDriveLetter || startedFromRoot ; for (int i = 0; i < nameElements.length; i++) { if ( ".".equals( nameElements[i] ) ) { nameElements[i] = null ; } else { if ( "..".equals( nameElements[i] ) ) { index = this.indexOfPreceedingNotNullElement( nameElements, i-1 ) ; if ( index >= 0 ) { if ( ( index > 0 ) || ( ! isAbsolute ) ) { nameElements[i] = null ; nameElements[index] = null ; } } } } } nameElements = this.str().removeNull( nameElements ) ; return this.str().asString( nameElements, "/" ) ; } else { return "" ; } } // standardizeFilename() // ------------------------------------------------------------------------- protected int indexOfPreceedingNotNullElement( String[] elements, int start ) { for (int i = start; i >= 0 ; i--) { if ( elements[i] != null ) { if ( "..".equals( elements[i] ) ) // This is not a valid not null element { return -1 ; } else { return i ; } } } return -1 ; } // indexOfPreceedingNotNullElement() // ------------------------------------------------------------------------- protected StringUtil str() { return StringUtil.current() ; } // str() // ------------------------------------------------------------------------- } // class FileUtilazureus-4.3.0.6/org/pf/file/FileLocator.java0000644000175000017500000004415010024456444020026 0ustar adrianadrian// =========================================================================== // CONTENT : CLASS FileLocator // AUTHOR : Manfred Duchrow // VERSION : 1.3 - 14/03/2003 // HISTORY : // 17/05/2002 duma CREATED // 24/05/2002 duma added -> toURL(), isFile(), isDirectory(), getAbsolutePath() // 21/06/2002 duma added -> realFile() // 14/03/2003 duma added -> getStandardizedPath(), getStandardizedAbsolutePath() // // Copyright (c) 2002-2003, by Manfred Duchrow. All rights reserved. // =========================================================================== package org.pf.file ; // =========================================================================== // IMPORTS // =========================================================================== import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.pf.text.StringUtil; /** * This class mainly supports access to files which can be in the normal * file directory structure or inside zip archives. * The main purpose is to provide methods that transparently treat files * the same way whether they are in the normal directory structure or * inside archives. * The syntax is simply to allow archive names in a path name at any place * where a sub-directory name can be.
      * Examples:
      *

        *
      • d:\temp\archive.zip\config\nls.properties
      • *
      • /usr/java/jdk1.3/src.jar/java/io/File.java
      • *
      * @author Manfred Duchrow * @version 1.3 */ public class FileLocator { // ========================================================================= // CONSTANTS // ========================================================================= private static final boolean DEBUG = false ; private static final String FILE_PROTOCOL_INDICATOR = "file:" + File.separator ; private static final String ARCHIVE_INDICATOR = "!" + File.separator ; // ========================================================================= // INSTANCE VARIABLES // ========================================================================= private FileLocator parent = null ; protected FileLocator getParent() { return parent ; } protected void setParent( FileLocator newValue ) { parent = newValue ; } private File file = null ; protected File getFile() { return file ; } protected void setFile( File newValue ) { file = newValue ; } private ZipFile zipFile = null ; protected ZipFile getZipFile() { return zipFile ; } protected void setZipFile( ZipFile newValue ) { zipFile = newValue ; } private boolean exists = true ; protected boolean getExists() { return exists ; } protected void setExists( boolean newValue ) { exists = newValue ; } private Exception exception = null ; protected Exception getException() { return exception ; } protected void setException( Exception newValue ) { exception = newValue ; } // ========================================================================= // CLASS METHODS // ========================================================================= /** * Create a file locator that corresponds to the given file name. */ public static FileLocator create( File file ) { FileLocator locator = new FileLocator() ; return locator.createFrom( file ) ; } // create() // ------------------------------------------------------------------------- /** * Create a file locator that corresponds to the given file name. */ public static FileLocator create( String filename ) { return create( new File( filename ) ) ; } // create() // ------------------------------------------------------------------------- private static FileLocator newWith( FileLocator aParent, String[] pathElements ) throws Exception { FileLocator locator = new FileLocator() ; return locator.createFrom( aParent, pathElements ) ; } // newWith() // ------------------------------------------------------------------------- // ========================================================================= // CONSTRUCTORS // ========================================================================= /** * Initialize the new instance with default values. */ private FileLocator() { super() ; } // FileLocator() // ------------------------------------------------------------------------- // ========================================================================= // PUBLIC INSTANCE METHODS // ========================================================================= /** * Returns the file that contains the data the locator points to. * If the locator points to a normal file in a directory, than * this file will be returned. * If the locator points to a file inside an archive, the file * will be unzipped into the temp directory and this * temp file will be returned. * If the locator points to a none existing file, this method * returns false. */ public File realFile() { File aFile ; try { aFile = this.fileRef() ; } catch (Exception e) { aFile = null ; } return aFile ; } // realFile() // ------------------------------------------------------------------------- /** * Returns whether or not the file specified by this locator exists. */ public boolean exists() { return this.getExists() ; } // exists() // ------------------------------------------------------------------------- /** * Returns whether or not the name specified by this locator * points to a file. */ public boolean isFile() { try { if ( this.exists() ) return this.isFileElement( this.getFile() ) ; else return false ; } catch(Exception e) { return false ; } } // isFile() // ------------------------------------------------------------------------- /** * Returns whether or not the name specified by this locator * points to a directory. */ public boolean isDirectory() { try { if ( this.exists() ) return ! this.isFileElement( this.getFile() ) ; else return false ; } catch(Exception e) { return false ; } } // isDirectory() // ------------------------------------------------------------------------- /** * Returns the size of the file or 0 if it does not exist. */ public long size() { ZipEntry entry ; try { if ( this.isInArchive() ) { entry = this.archiveEntry() ; // if ( DEBUG ) com.mdcs.joi.Inspector.inspectWait( entry ) ; return entry.getSize() ; } else { return this.getFile().length() ; } } catch(Exception ex) { if ( DEBUG ) ex.printStackTrace() ; return 0L ; } } // size() // ------------------------------------------------------------------------- /** * Returns the timestamp of when the file was last modified * or 0 in any case of error. */ public long lastModified() { ZipEntry entry ; try { if ( this.isInArchive() ) { entry = this.archiveEntry() ; return entry.getTime() ; } else { return this.getFile().lastModified() ; } } catch(Exception ex) { if ( DEBUG ) ex.printStackTrace() ; return 0L ; } } // lastModified() // ------------------------------------------------------------------------- /** * Returns an opened input stream on the file defined by this locator. */ public InputStream getInputStream() throws Exception { ZipEntry entry ; if ( this.isInArchive() ) { entry = this.archiveEntry() ; return this.container().getInputStream( entry ) ; } else { return new FileInputStream( this.getFile() ) ; } } // getInputStream() // ------------------------------------------------------------------------- /** * Returns whether or not the file specified by this locator * is inside an archive. */ public boolean isInArchive() { return this.getParent() != null ; } // isInArchive() // ------------------------------------------------------------------------- /** * Returns the full pathname. */ public String getPath() { return this.fullFilePath( false ).getPath() ; } // getPath() // ------------------------------------------------------------------------- /** * Returns the full absolute pathname. */ public String getAbsolutePath() { return this.fullFilePath( true ).getPath() ; } // getAbsolutePath() // ------------------------------------------------------------------------- /** * Returns the full pathname in a standardized for. * That is all ".." and "." elements are removed and forward slashes are * used as separators of the remaining elements. */ public String getStandardizedPath() { return this.fileUtil().standardize( this.getPath() ) ; } // getStandardizedPath() // ------------------------------------------------------------------------- /** * Returns the full absolute pathname in a standardized form. * That is all ".." and "." elements are removed and forward slashes are * used as separators of the remaining elements. */ public String getStandardizedAbsolutePath() { return this.fileUtil().standardize( this.getAbsolutePath() ) ; } // getStandardizedAbsolutePath() // ------------------------------------------------------------------------- /** * Returns the last exception that occured while using this locator * or null, if no exception was thrown at all. */ public Exception exception() { return this.getException() ; } // exception() // ------------------------------------------------------------------------- /** * Returns the name of the file as an URL. */ public URL toURL() throws MalformedURLException { StringBuffer buffer = new StringBuffer( 128 ) ; this.urlPath( buffer ) ; return new URL( buffer.toString() ) ; } // toURL() // ------------------------------------------------------------------------- // ========================================================================= // PROTECTED INSTANCE METHODS // ========================================================================= protected FileLocator createFrom( File filePath ) { FileLocator locator = null ; String[] parts = null ; File path = filePath ; if ( path.getPath().startsWith( FILE_PROTOCOL_INDICATOR ) ) path = this.convertFromURLSyntax( path ) ; parts = str().parts( path.getPath(), File.separator ) ; try { locator = this.initFromPath( parts, path.getPath().startsWith( File.separator ) ) ; } catch ( Exception ex ) { this.setException( ex ) ; this.doesNotExist( path ) ; locator = this ; } return locator ; } // createFrom() // ------------------------------------------------------------------------- private FileLocator createFrom( FileLocator aParent, String[] pathElements ) throws Exception { this.setParent( aParent ) ; return this.initFromPath( pathElements, false ) ; } // createFrom() // ------------------------------------------------------------------------- protected FileLocator initFromPath( String[] parts, boolean startsFromRoot ) throws Exception { FileLocator locator = this ; File pathElement = null ; String[] rest = null ; boolean elementExists = false ; if ( startsFromRoot ) pathElement = new File( File.separator ) ; for ( int i = 0 ; i < parts.length ; i++ ) { if ( pathElement == null ) pathElement = new File( parts[i] ) ; else pathElement = new File( pathElement, parts[i] ) ; elementExists = this.doesElementExist( pathElement ) ; if ( elementExists ) { this.setFile( pathElement ) ; if ( this.isFileElement( pathElement ) ) { if ( DEBUG ) System.out.println( "Locator(" + pathElement + ")" ) ; if ( i < ( parts.length - 1 ) ) // Is not last element ? { rest = str().copyFrom( parts, i + 1 ) ; // if (DEBUG) com.mdcs.joi.Inspector.inspect( "SubLocator", rest ) ; locator = FileLocator.newWith( this, rest ) ; } break ; } } else { if ( this.isInArchive() ) { if ( i < ( parts.length - 1 ) ) // Is not last element ? { // Directories are not always identifiable individually in zip archives. // Therefore it must be accepted that they are not found. // So in such case no exception will be thrown. } else { throw new Exception( "\"" + pathElement.getPath() + "\" does not exist" ); } } else { throw new Exception( "\"" + pathElement.getPath() + "\" does not exist" ); } } } return locator ; } // initFromPath() // ------------------------------------------------------------------------- protected boolean doesElementExist( File element ) throws Exception { if ( this.isInArchive() ) { return doesElementExistInArchive( element.getPath() ) ; } else { return element.exists() ; } } // doesElementExist() // ------------------------------------------------------------------------- protected boolean isFileElement( File element ) throws Exception { if ( this.isInArchive() ) { return isFileInArchive( element.getPath() ) ; } else { return element.isFile() ; } } // isFileElement() // ------------------------------------------------------------------------- protected boolean doesElementExistInArchive( String elementName ) throws Exception { ZipEntry entry ; entry = this.entryFromArchive( elementName ) ; return ( entry != null ) ; } // doesElementExistInArchive() // ------------------------------------------------------------------------- protected boolean isFileInArchive( String elementName ) throws Exception { ZipEntry entry ; entry = this.entryFromArchive( elementName ) ; // Unfortunately entry.isDirectory() returns false even for // pure directory entries inside a zip archive, so it can't be used here. // The trick below is problematic, because apart from // directories it will also not recognize files with size 0. return ( entry != null ) && ( entry.getSize() > 0 ) ; } // isFileInArchive() // ------------------------------------------------------------------------- protected ZipEntry entryFromArchive( String elementName ) throws Exception { ZipEntry entry ; ZipFile archive ; String name ; name = str().replaceAll( elementName, "\\", "/" ) ; archive = this.container() ; entry = archive.getEntry( name ) ; if (DEBUG) { // if ( entry == null ) com.mdcs.joi.Inspector.inspect( name ) ; System.out.print( archive.getName() + "::" + name + " --- " + ( entry != null ) ) ; if ( entry == null ) { System.out.println() ; } else { System.out.print( " (" + entry.getSize() + ")" ) ; System.out.print( " (T:" + entry.getTime() + ")" ) ; System.out.println( " (" + ( entry.isDirectory() ? "Dir" : "File" ) + ")" ) ; } } return entry ; } // entryFromArchive() // ------------------------------------------------------------------------- protected ZipEntry archiveEntry() throws Exception { return this.entryFromArchive( this.getFile().getPath() ) ; } // archiveEntry() // ------------------------------------------------------------------------- protected void doesNotExist( File file ) { this.setExists( false ) ; this.setFile( file ) ; } // doesNoTExist() // ------------------------------------------------------------------------- protected File fullFilePath( boolean absolute ) { File full ; if ( this.isInArchive() ) { full = new File( this.getParent().fullFilePath( absolute ), this.getFile().getPath() ) ; } else { if ( absolute ) full = this.getFile().getAbsoluteFile() ; else full = this.getFile() ; } return full ; } // fullFilePath() // ------------------------------------------------------------------------- protected void urlPath( StringBuffer buffer ) { if ( this.isInArchive() ) { this.getParent().urlPath( buffer ) ; buffer.append( ARCHIVE_INDICATOR ) ; } else { buffer.append( FILE_PROTOCOL_INDICATOR ) ; } buffer.append( this.getFile().getPath() ) ; } // urlPath() // ------------------------------------------------------------------------- protected File fileRef() throws Exception { InputStream archiveStream ; FileOutputStream fileStream ; ZipEntry entry ; File tempFile ; if ( this.isInArchive() ) { entry = this.archiveEntry() ; archiveStream = this.container().getInputStream( entry ) ; tempFile = File.createTempFile( "FLOC_", ".xtr" ) ; tempFile.deleteOnExit() ; fileStream = new FileOutputStream( tempFile ) ; fileUtil().copyStream( archiveStream, fileStream ) ; return tempFile ; } else { return this.getFile() ; } } // fileRef() // ------------------------------------------------------------------------- /** * Returns the file this locator presents as opened zip file or * null in any case of error. */ protected ZipFile archive() throws Exception { if ( this.getZipFile() == null ) { this.setZipFile( new ZipFile( this.fileRef() ) ) ; } return this.getZipFile() ; } // archive() // ------------------------------------------------------------------------- /** * Returns the zip file which is presented by the parent container * or null in any case of error. */ protected ZipFile container() throws Exception { if ( this.isInArchive() ) return this.getParent().archive() ; else return null ; } // container() // ------------------------------------------------------------------------- protected File convertFromURLSyntax( File file) { String newStr ; newStr = file.getPath().substring( FILE_PROTOCOL_INDICATOR.length() ) ; newStr = str().replaceAll( newStr, ARCHIVE_INDICATOR, File.separator ) ; return new File( newStr ) ; } // convertFromURLSyntax() // ------------------------------------------------------------------------- protected StringUtil str() { return StringUtil.current() ; } // str() // ------------------------------------------------------------------------- protected FileUtil fileUtil() { return FileUtil.current() ; } // fileUtil() // ------------------------------------------------------------------------- } // class FileLocatorazureus-4.3.0.6/org/pf/file/FileFinder.java0000644000175000017500000002553510024456444017640 0ustar adrianadrian// =========================================================================== // CONTENT : CLASS FileFinder // AUTHOR : Manfred Duchrow // VERSION : 1.2 - 14/02/2003 // HISTORY : // 02/12/2001 duma CREATED // 23/01/2002 duma added -> findFile() // 14/02/2003 duma added -> 3 File[] findFiles() methods // // Copyright (c) 2001-2003, by Manfred Duchrow. All rights reserved. // =========================================================================== package org.pf.file; // =========================================================================== // IMPORTS // =========================================================================== import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * Helper class with convenient methods to find files. * * @author Manfred Duchrow * @version 1.2 */ public class FileFinder implements FileHandler { // ========================================================================= // CONSTANTS // ========================================================================= // ========================================================================= // INSTANCE VARIABLES // ========================================================================= private List collectedFiles = null ; protected List getCollectedFiles() { return collectedFiles ; } protected void setCollectedFiles( List newValue ) { collectedFiles = newValue ; } // ========================================================================= // CLASS METHODS // ========================================================================= // ========================================================================= // CONSTRUCTORS // ========================================================================= /** * Initialize the new instance with default values. */ protected FileFinder() { super() ; this.setCollectedFiles( new ArrayList() ) ; } // FileFinder() // ========================================================================= // PUBLIC CLASS METHODS // ========================================================================= /** * Tries to find the file with the given Name on the classpath. * If the file was found and really exists, then it will be returned. * In all other cases null will be returned. */ public static File findFileOnClasspath( String filename ) { ClassLoader cl = null ; File file = null ; URL url = null ; try { cl = FileFinder.class.getClassLoader() ; if ( cl == null ) { // System.out.println( "No classloader found !\n

      " ) ; return null ; } url = cl.getResource( filename ) ; if ( url == null ) { // System.out.println( "Settings file '" + filename + "' not found in CLASSPATH !!!" ) ; } else { file = new File( url.getFile() ) ; // System.out.println( "Settings file '" + file.getAbsolutePath() + "' exists: " + file.exists() ) ; if ( ! fileExists( file ) ) file = null ; } } catch ( Exception ex ) { // ex.printStackTrace() ; } return file ; } // findFileOnClasspath() // ------------------------------------------------------------------------- /** * Tries to find the file with the given Name. * First it looks if the file exists directly under the given name. * If not, it searches the classpath to find it. * If the file was found and really exists, then it will be returned. * In all other cases null will be returned. */ public static File findFile( String filename ) { File aFile = null ; aFile = new File( filename ) ; if ( fileExists( aFile ) ) return aFile ; aFile = findFileOnClasspath( filename ) ; return aFile ; } // findFile() // ------------------------------------------------------------------------- /** * Return all files that match the given pattern(s) start searching in the * specified dir. Searches in all sub directories as well. * More than one pattern can be specified in parameter pattern. * They have to be separated by ';'. * * @param dir The directory to start searching (must not be null) * @param pattern The pattern(s) the filenames must match (must not be null ) * @return All file found that matched to at least one of the patterns * @throws IllegalArgumentException If dir or pattern is null */ public static File[] findFiles( String dir, String pattern ) { return findFiles( dir, pattern, true ) ; } // findFiles() // ------------------------------------------------------------------------- /** * Return all files that match the given pattern(s) start searching in the * specified dir. Look into sub directories if recursive is true. * More than one pattern can be specified in parameter pattern. * They have to be separated by ';'. * * @param dir The directory to start searching (must not be null) * @param pattern The pattern(s) the filenames must match (must not be null ) * @param recursive If false, only dir is searched, otherwise all sub directories as well * @return All file found that matched to at least one of the patterns * @throws IllegalArgumentException If dir or pattern is null */ public static File[] findFiles( String dir, String pattern, boolean recursive ) { return findFiles( dir, pattern, recursive, (char)0 ) ; } // findFiles() // ------------------------------------------------------------------------- /** * Return all files that match the given pattern(s) start searching in the * specified dir. Look into sub directories if recursive is true. * Use the given digit wildcard in patterns to match single digits in * filenames.
      * More than one pattern can be specified in parameter pattern. * They have to be separated by ';'. * * @param dir The directory to start searching (must not be null) * @param pattern The pattern(s) the filenames must match (must not be null ) * @param recursive If false, only dir is searched, otherwise all sub directories as well * @param digitWildcard The wildcard character for digit representation in the pattern(s) * @return All file found that matched to at least one of the patterns * @throws IllegalArgumentException If dir or pattern is null */ public static File[] findFiles( String dir, String pattern, boolean recursive, char digitWildcard ) { FileFinder finder ; Character digitChar = null ; if ( dir == null ) throw new IllegalArgumentException( "FileFinder.findFiles(): dir is null" ) ; if ( pattern == null ) throw new IllegalArgumentException( "FileFinder.findFiles(): pattern is null" ) ; if ( digitWildcard > 0 ) digitChar = new Character(digitWildcard) ; finder = new FileFinder() ; return finder.collectFiles( dir, pattern, recursive, digitChar ) ; } // findFiles() // ------------------------------------------------------------------------- // ========================================================================= // PRIVATE CLASS METHODS // ========================================================================= private static boolean fileExists( File file ) { boolean success = false ; if ( file != null ) { try { FileLocator locator = FileLocator.create( file ) ; success = locator.exists() ; } catch ( Exception ex ) { // nothing to do here } } return success ; } // fileExists() // ------------------------------------------------------------------------- // ========================================================================= // INTERFACE FileHandler METHODS // ========================================================================= /** * This method is called for each file, that a FileWalker instance finds. * It must return true, if the FileWalker should continue. To stop the * calling FileWalker it can return false. * * @param The file, currently found by the FileWalker instance * @return true to continue, false to terminate processing of files */ public boolean handleFile( File file ) { this.getCollectedFiles().add( file ) ; return true ; } // handleFile() // ------------------------------------------------------------------------- /** * This method is called for whenever an exception occurs in walking through * the directories.
      * The method must return true, if the FileWalker should continue. To stop the * calling FileWalker it can return false. * * @param ex The exception to handle * @param The file, currently found by the FileWalker instance * @return true to continue, false to terminate processing of files */ public boolean handleException( Exception ex, File file ) { // System.out.println( "Problem with '" + file + "'" ) ; // System.out.println( ex ) ; return false ; } // handleException() // ------------------------------------------------------------------------- /** * This method is called for each directory, that a FileWalker finished to walk through. * It must return true, if the FileWalker should continue. To stop the * calling FileWalker it can return false. * * @param dir The directory, the FileWalker has finished to walk through * @return true to continue, false to terminate processing of files */ public boolean directoryEnd( File dir ) { return true ; } // directoryEnd() // ------------------------------------------------------------------------- /** * This method is called for each directory, that a FileWalker starts to walk through. * It must return true, if the FileWalker should continue. To stop the * calling FileWalker it can return false. * * @param dir The directory, the FileWalker is starting to walk through * @param count The number of files and directories the FileWalker found in the directory * @return true to continue, false to terminate processing of files */ public boolean directoryStart( File dir, int count ) { return true ; } // directoryStart() // ------------------------------------------------------------------------- // ========================================================================= // PROTECTED INSTANCE METHODS // ========================================================================= protected File[] collectFiles( String dir, String pattern, boolean recursive, Character digitWildcard ) { FileWalker fileWalker ; List list ; fileWalker = new FileWalker( this ) ; if ( digitWildcard != null ) fileWalker.setDigitWildcardChar( digitWildcard.charValue() ) ; fileWalker.walkThrough( dir, pattern, recursive ) ; list = this.getCollectedFiles() ; return (File[])list.toArray( new File[list.size()]) ; } // collectFiles() // ------------------------------------------------------------------------- } // class FileFinderazureus-4.3.0.6/org/pf/file/ExtendedFileFilter.java0000644000175000017500000002103510024456444021326 0ustar adrianadrian// =========================================================================== // CONTENT : CLASS ExtendedFileFilter // AUTHOR : Manfred Duchrow // VERSION : 1.1 - 14/02/2003 // HISTORY : // 24/01/2000 duma CREATED // 14/02/2003 duma added -> Support for digit wildcard characher // // Copyright (c) 2000-2003, by Manfred Duchrow. All rights reserved. // =========================================================================== package org.pf.file; // =========================================================================== // IMPORTS // =========================================================================== import java.io.File; import java.io.FilenameFilter; import java.util.Iterator; import java.util.List; import java.util.Vector; import org.pf.text.StringPattern; /** * This filter implements the standard pattern matching on UNIX and Windows * platforms. It supports the wildcards '*' and '?' on file names.
      * It allows to set more than one pattern. * Apart from that it allows control over inclusion/exclusion of directories * independently from name patterns. * * @author Manfred Duchrow * @version 1.1 */ public class ExtendedFileFilter implements FilenameFilter { // ========================================================================= // CONSTANTS // ========================================================================= protected final static int DIR_CHECK_NAME = 1 ; protected final static int DIR_INCLUDE = 2 ; protected final static int DIR_EXCLUDE = 3 ; // ========================================================================= // INSTANCE VARIABLES // ========================================================================= private List stringPatterns = new Vector() ; protected List getStringPatterns() { return stringPatterns ; } protected void setStringPatterns( List newValue ) { stringPatterns = newValue ; } private int dirHandling = DIR_CHECK_NAME ; protected int getDirHandling() { return dirHandling ; } protected void setDirHandling( int newValue ) { dirHandling = newValue ; } // ========================================================================= // CLASS METHODS // ========================================================================= // ========================================================================= // CONSTRUCTORS // ========================================================================= /** * Initialize the new instance with default values. */ public ExtendedFileFilter() { } // ExtendedFileFilter() // ========================================================================= // PUBLIC INSTANCE METHODS // ========================================================================= /** * Adds a pattern. All filenames match this pattern are acceptable.
      * Case sensitivity is switched on ! * * @param pattern The pattern string containing optional wildcards ( '*', '?' ) */ public void addPattern( String pattern ) { StringPattern stringPattern = null ; stringPattern = new StringPattern( pattern, false ) ; this.getStringPatterns().add( stringPattern ) ; } // addPattern() // ------------------------------------------------------------------------- /** * Adds a pattern. All filenames match this pattern are acceptable.
      * Case sensitivity is switched on ! * The second parameter specifies a character that will be recognized in the * pattern as a placeholder for a single digit character.

      * A patterb "XX-####.log" with a digitWildcard set to '#' wil match to * "XX-2000.log" and "XX-7376.log" but not to "XX-C363.log" and "XX-dddd.log". * * @param pattern The pattern string containing optional wildcards ( '*', '?' ) * @param digitWildcard The character that will be treated as wildcard for digits ('0'-'9') */ public void addPattern( String pattern, char digitWildcard ) { StringPattern stringPattern = null ; stringPattern = new StringPattern( pattern, false, digitWildcard ) ; this.getStringPatterns().add( stringPattern ) ; } // addPattern() // ------------------------------------------------------------------------- /** * Adds a pattern. All filenames match this pattern are acceptable. * * @param pattern The pattern string containing optional wildcards ( '*', '?' ) * @param ignoreCase If true, all character comparisons are ignoring uppercase/lowercase */ public void addPattern( String pattern, boolean ignoreCase ) { StringPattern stringPattern = null ; stringPattern = new StringPattern( pattern, ignoreCase ) ; this.getStringPatterns().add( stringPattern ) ; } // addPattern() // ------------------------------------------------------------------------- /** * Adds a pattern. All filenames that match this pattern are acceptable. * Additionally to the standard wildcards '*' and '?' a wildcard for single * digit characters ('0' - '9') can be specified here. * * @param pattern The pattern string containing optional wildcards ( '*', '?' ) * @param ignoreCase If true, all character comparisons are ignoring uppercase/lowercase * @param digitWildcard The character that will be treated as wildcard for digits ('0'-'9') */ public void addPattern( String pattern, boolean ignoreCase, char digitWildcard ) { StringPattern stringPattern = null ; stringPattern = new StringPattern( pattern, ignoreCase, digitWildcard ) ; this.getStringPatterns().add( stringPattern ) ; } // addPattern() // ------------------------------------------------------------------------- /** * Sets the filter to only accept directories that match a defined pattern. */ public void checkNameOfDirectories() { this.setDirHandling( DIR_CHECK_NAME ) ; } // checkNameOfDirectories() // ------------------------------------------------------------------------- /** * Sets the filter to always accept directories, even if they don't match * a given pattern. */ public void alwaysIncludeDirectories() { this.setDirHandling( DIR_INCLUDE ) ; } // alwaysIncludeDirectories() // ------------------------------------------------------------------------- /** * Sets the filter to never accept directories. */ public void alwaysExcludeDirectories() { this.setDirHandling( DIR_EXCLUDE ) ; } // alwaysExcludeDirectories() // ------------------------------------------------------------------------- /** * Tests if a specified file should be included in a file list. * * @param dir the directory in which the file was found. * @param name the name of the file. * @return true if and only if the name should be included in the file list, false otherwise. */ public boolean accept( File dir, String name ) { File fileOrDir = null ; fileOrDir = new File( dir, name ) ; if ( fileOrDir.isDirectory() ) { if ( this.mustIncludeDirectories() ) return true ; if ( this.mustExcludeDirectories() ) return false ; } return ( this.checkAgainstPatterns( name ) ) ; } // accept() // ========================================================================= // PROTECTED INSTANCE METHODS // ========================================================================= protected boolean checkAgainstPatterns( String name ) { Iterator iterator = null ; StringPattern pattern = null ; iterator = this.getStringPatterns().iterator() ; while ( iterator.hasNext() ) { pattern = (StringPattern)iterator.next() ; if ( pattern.matches( name ) ) return true ; } // while return false ; // No pattern matched } // checkAgainstPatterns // ------------------------------------------------------------------------- /** * Returns true if the filter always accepts directories, even if they don't match * a given pattern. */ public boolean mustIncludeDirectories() { return ( this.getDirHandling() == DIR_INCLUDE ) ; } // mustIncludeDirectories() // ------------------------------------------------------------------------- /** * Returns true if the filter never accepts directories. */ public boolean mustExcludeDirectories() { return ( this.getDirHandling() == DIR_EXCLUDE ) ; } // mustExcludeDirectories() // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- } // class ExtendedFileFilterazureus-4.3.0.6/org/pf/readme.txt0000644000175000017500000000036310024456444016035 0ustar adrianadrianThis is a stripped down version of Manfred Duchrows Programmer's Freind class library. No code was changed, only classes irrelevant for Azureus were left out. The complete library can be found on its homepage: http://www.programmers-friend.orgazureus-4.3.0.6/az-build.xml0000644000175000017500000001072211053655300015067 0ustar adrianadrian azureus-4.3.0.6/GPL.txt0000644000175000017500000004227210665254374014044 0ustar adrianadrianThe GNU General Public License (GPL) Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. one line to give the program's name and a brief idea of what it does. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. azureus-4.3.0.6/dist/0000755000175000017500000000000011310377654013610 5ustar adrianadrianazureus-4.3.0.6/build.xml0000644000175000017500000000434311053655300014461 0ustar adrianadrian azureus-4.3.0.6/ChangeLog.txt0000644000175000017500000014665711310376442015252 0ustar adrianadrianVUZE CHANGELOG ----------------- 2009.12.10 | Vuze 4.3.0.6 BUGFIX: Core | Fixed bug where compact file types could lead to spurious 'file length too large' errors [Parg] 2009.11.20 | Vuze 4.3.0.4 BUGFIX: UI | Prevent main window from popping up when adding a torrent and "Add Torrent Silently" set [TuxPaper] BUGFIX: UI | Ensure that the correct progress reports are passed to listeners [Parg] BUGFIX: UI | Fixed bug whereby the destruction of the torrent-open window was cancelling torrent download dialogs [Parg] BUGFIX: UI | (OSX) Fixed bug where scrollers on some mice would cause table to blank [TuxPaper] BUGFIX: UIvz | Handle magnet links within internal browser [TuxPaper] BUGFIX: Plug | Improved the fallback lookup service by passing the all params [Parg] BUGFIX: Plug | Verify that downloaded torrents are valid before passing to caller [Parg] 2009.11.19 | Vuze 4.3.0.2 FEATURE: Core | Support per-url config for http seeds and max_speed setting [Parg] FEATURE: Plug | Start of a fallback magnet lookup service [Parg] FEATURE: UI | Clicking on dock icon always opens main window [TuxPaper] CHANGE: Core | Parse hex-encoded magnet URIs too [The 8472] CHANGE: Core | Immediate-close option for tracker socket connections [Parg] CHANGE: Core | Return IP address instead of DNS names for external seeds [Parg] CHANGE: Core | Support more non-conformant RSS feed dates [Parg] CHANGE: Core | Auto-speed bias towards min ping times rather than pure average [Parg] BUGFIX: Core | Reverted socket handling to initial 1.6 fix status to fix with network binding/stall problems [Parg] BUGFIX: Core | Added option to disable all IPv6 support and defaulted to 'disable' on OSX as some users experiencing crash when enabled [Parg] BUGFIX: Plug | Don't cause all dht torrents to perform an 'announce' when 'pause-all' selected [Parg] BUGFIX: Plug | Webplugin config section override was using the wrong variable prefix [Parg] BUGFIX: UI | Fixed name column sort [TuxPaper] BUGFIX: UI | (OSX) Fixed opening .vuze files when client isn't running [TuxPaper] BUGFIX: UI | Fixed table view not loading (showing gray area) sometimes [TuxPaper] BUGFIX: UI | (Windows) "Open Containing Folder" in default "folder association" app [TuxPaper] BUGFIX: UI | (*nix) Fixed name column blanking [TuxPaper] BUGFIX: UI | (OSX) Fixed Password option hanging UI [TuxPaper] BUGFIX: UI | Fixed sidebar font sizes (mostly for *nix) [TuxPaper] BUGFIX: UI | (OSX) Opening .torrent file when "Add Silently" is enable should no longer activate the main window [TuxPaper] BUGFIX: UI | Fix losing cursor indication on Sashes (and other widgets) [TuxPaper] BUGFIX: UI | Sidebar now accepts dropping torrents [TuxPaper] 2009.11.11 | Vuze 4.3.0.0 FEATURE: Core | Added support for UPnP based offline-downloader services [Parg] FEATURE: Core | Obfuscated lookups for the DHT to prevent leakage of key values during lookup stage [Parg] FEATURE: Core | Support copying of .mp3 and .wma files to PSP [Parg] FEATURE: Core | Implementation of a piece-reordering file manager [Parg] FEATURE: Core | DHT replication controls [Parg] FEATURE: Core | Initial pairing support [Parg] FEATURE: Core | Parse seed/leecher values from subscription text if found [Parg] FEATURE: Core | Added bloom-filter persistence [Parg] FEATURE: Core | Support ".utf-8" suffix for keys in .torrent files [TuxPaper] FEATURE: Plug | Added download-flags to Download object [Parg] FEATURE: Plug | Plugin access to subscriptions [Parg] FEATURE: Plug | Added verified plugins [Parg] FEATURE: UIvz | Added "Reset Columns" ability to some views (in Column Setup) [TuxPaper] FEATURE: UIvz | Client now opens to last used static view, or Library by default [TuxPaper] FEATURE: UI | Support for switching between carbon and cocoa on OSX [Parg] FEATURE: UI | Generic filter support for our tables [Parg] FEATURE: UI | Support for showing real SI values rather than just changing units displayed [Parg] FEATURE: UI | Advanced menu option for editing http seeds [Parg] CHANGE: Core | Remove replicate-on-join from DHT as causing excessive key storage [Parg] CHANGE: Core | Roll up subscription warnings when not expanded [Parg] CHANGE: Core | Improved IPv6-handshaking and reconnects with other clients (see http://www.azureuswiki.com/index.php/IPv6_compatibility for supported systems) [The 8472] CHANGE: Core | Switch back to k-select on OSX [Nolar] CHANGE: Core | Reduce CPU used for node-id calculation via MRU cache [Parg] CHANGE: Core | Remove LAN transfer totals from data reported to tracker [Parg] CHANGE: Core | Implemented port restriction for DHT node id generation [Parg] CHANGE: Core | Reduce memory/CPU by disabling the largely unused Vivaldi V2 impl [Parg] CHANGE: Core | Reduce DHT load by removing network-position derived tracking targets [Parg] CHANGE: Core | Back off the initial DHT seeding [Parg] CHANGE: Core | Cache redirects for http seeds CHANGE: Core | Use async keep-alive test to reduce thread creation on magnet download [Parg] CHANGE: Core | Change defaults for I2P and Tor networks to fase [Parg] CHANGE: Core | Support http seeds that don't support partial content [Parg] CHANGE: Core | Added option to disable TiVo support completely [Parg] CHANGE: Core | Support RSS feeds with incorrect 'summary' instead of 'description' entries [Parg] CHANGE: Core | Support trackers that returned gzipped torrents even when not asked to [Parg] CHANGE: Core | Migrate away from system-managed private keys [Parg] CHANGE: Core | Support meta-search incremental result injection [Parg] CHANGE: Core | Use cached scrape values on startup for DHT torrents to reduce thrashing [Parg] CHANGE: Core | Switch version check to use HTTP by default [Parg] CHANGE: Core | Resource resources by grabbing piecemap once during piece pick operation [Parg] CHANGE: Core | Reduce cost of handling DHT store operations [Parg] CHANGE: Core | Remove 'force write' option from random access file access [Parg] CHANGE: Core | Move a few things to use the less costly stepped-monotime method [Parg] CHANGE: Core | Re-use http connections when messaging the platform [Parg] CHANGE: Core | Don't write diagnostic files to disk by default [Parg] CHANGE: Core | Reduce small scratch file creation on startup [Parg] CHANGE: Core | Don't write tables.config every start [Parg] CHANGE: Core | If we don't have hosted content, don't write the config file [Parg] CHANGE: Core | Potentially less Tracker Announces for those trackers not supplying "min interval" [TuxPaper] CHANGE: Plug | Reduce frequency of UPnP device specification download attempts [Parg] CHANGE: UIvz | Removed Login and Friends, Content Networks menu [TuxPaper] CHANGE: UI | Order files in file view by torrent index if piece numbers same [Parg] CHANGE: UI | Pulled out the RSS feed generation for devices and put into common location [Parg] CHANGE: UI | Allows addition of http seeds to decentralised torrents [Parg] CHANGE: UI | Make regex matching mode more obvious [Parg] CHANGE: UI | Better "Associated Application" icon logic [TuxPaper] CHANGE: UI | (OSX) Switch to SWT for Cocoa Framework [TuxPaper] BUGFIX: Core | Don't reset manually selected Vuze meta search templates on load [Parg] BUGFIX: Core | Removed 'watched' tag from torrents on import [Parg] BUGFIX: Core | index-out-of-bounds fix when global peer limit reached [Parg] BUGFIX: Core | Fix incorrect sync of scrape hashes [Parg] BUGFIX: Core | Prevent unwanted selection of in-error subscriptions [Parg] BUGFIX: Plug | Force UPnP operations not to use socks/http proxy when defined [Parg] BUGFIX: UI | Fixed case where Open Torrents Window might erase existing files [TuxPaper] BUGFIX: UI | Fixed context menus sometimes hanging client on Windows 7 [TuxPaper] BUGFIX: UI | Fix missing icons for pause/resume in all-transfers bar [Parg] BUGFIX: UI | Fix invalid thread access in parameter change logic [Parg] BUGFIX: UI | Fix progress-dialog feedback for magnet downloads [Parg] BUGFIX: UI | Fix cases on OSX where a modal dialog box ended up under main window [TuxPaper] 2009.08.27 | Vuze 4.2.0.8 FEATURE: Core | Drive Detection for Devices for OSX (for PSP devices) [TuxPaper] FEATURE: Core | Factory option to allow switchable unchoke algorithms [Parg] CHANGE: UI | Less CPU usage for Seeding Rules [TuxPaper] CHANGE: Core | Only create the transcode directories when required [Parg] CHANGE: Core | Allow OSX platform component to be updated properly [Parg] BUGFIX: UI | Fixed Speedtest not working [TuxPaper] BUGFIX: UI | OSX 10.6 support (opening torrent from file) [TuxPaper] BUGFIX: Core | OSX 10.6 support (not getting data from connected peers) [Parg] BUGFIX: Core | Fixed deadlock during UI initialisation [Parg] 2009.08.06 | Vuze 4.2.0.6 FEATURE: UI | Support delete key for deleting transcoded content [Parg] FEATURE: UI | Added visual indication of buddy shares [Parg] FEATURE: UI | Added toolbar enablers for deleting subscriptions and devices [Parg] FEATURE: Core | Support for TiVo device [Parg] FEATURE: Core | Support for PSP device [Parg;TuxPaper] FEATURE: Core | Added RSS feed generation for device's transcoded content [Parg] FEATURE: Core | File-based RSS feeds [Parg] FEATURE: Core | Added ability to set category for downloads from a subscription [Parg] CHANGE: UI | Moved Column Setup and column related menu items to right click of column header [TuxPaper] CHANGE: UI | Made Library/My Torrents filter more visible [TuxPaper] CHANGE: UI | Moved "Rename" context menu in Library to context menu of Name column only [TuxPaper] CHANGE: UI | Gray out non-active devices [Parg] CHANGE: Core | Added more meta data for devices RSS Feed [TuxPaper] CHANGE: Plug | Added lifetime controls to DHT puts [Parg] BUGFIX: Core | HTTP seeding was incorrectly handling byte range requests [Parg] BUGFIX: Core | Catch failed transcodes and prevent partial files from being produced [Parg] BUGFIX: Core | Fixed potential deadlock on startup with Device loading [Parg] BUGFIX: Core | Support UTF marker chars in RSS feeds [Parg] 2009.07.08 | Vuze 4.2.0.4 FEATURE: Core | Subscription options for auto-starting auto-downloads [Parg] FEATURE: Core | Support for sharing .vuze files [Parg] FEATURE: Core | Added support for adding categories to transcoded content [Parg] FEATURE: Core | Added default transcode dir option [Parg] FEATURE: Core | Support for keep-alive and more gzip on web contexts [Parg] FEATURE: Core | Added percentage complete and eta to content descriptor [Parg] FEATURE: UIvz | UI displays while core initializes [TuxPaper] FEATURE: Plug | Plugin interface to the search functionality [Parg] CHANGE: Core | Added another non-standard RSS date format [Parg] CHANGE: Core | Allow HTTP seeding for simple torrents without knowledge of file name [Parg] CHANGE: Core | Keep log files open rather than continually opening and closing them [Parg] CHANGE: Core | Improved reporting of 'no disk space' errors for FAT32 [Parg] CHANGE: Core | Improved logging performance [Parg] CHANGE: Core | Support for updated via installer as opposed to incremental updates [Parg] BUGFIX: Core | Work around for broken socket handling on freebsd7.x [Parg] BUGFIX: Core | Recover from borked transcode queue config [Parg] BUGFIX: Core | Fix xml stats export with undefined characters [Parg] BUGFIX: Core | Support >2GB resource downloads [Parg] BUGFIX: Core | Fixed HTTP seeding when switching content on a keep-alive connection [Parg] BUGFIX: Core | Fix tracker announcer to pay attention to user options correctly [Parg] BUGFIX: Core | Multi-file torrents were borked in content directory [Parg] BUGFIX: UI | Set speeds in bits/sec when bits/sec display is selected [Parg] 2009.04.09 | Vuze 4.2.0.2 BUGFIX: UI | Fix wrap on category buttons [TuxPaper] BUGFIX: UI | Fix rare case when last sash position in My Torrents wasn't being obeyed [TuxPaper] BUGFIX: UI | Remove device toolbar when device feature not avail [TuxPaper] BUGFIX: Core | Fix hang on startup with some UPnP devices [Parg] BUGFIX: Plug | Force decode of HTTP headers to lowercase using ISO8859-1 charset to fix matching error in Turkish [Parg] 2009.03.23 | Vuze 4.2.0.0 FEATURE: Core | Devices [parg] FEATURE: UIvz | UI for Devices panel, individual Device panel, Device chooser, and Device Profile Chooser [TuxPaper] FEATURE: Plug | Transcoding [gudy,parg] BUGFIX: Core | Fix IP binding error when performing a NAT test under Vista [The 8472] BUGFIX: UIvz | Fix some notifications not getting pulled [TuxPaper] 2009.02.25 | Vuze 4.1.0.4 FEATURE: UI | Donation Window [TuxPaper] 2009.02.05 | Vuze 4.1.0.2 FEATURE: UI | Config option for max stalled seeding torrents (was hardcoded in 4100) [TuxPaper] BUGFIX: Core | Fix null-pointer-exception when initiasing old categorised shares [Parg] BUGFIX: Core | Remove accidental invocation of the get-networks Vuze RPC when running in classic UI [Parg] BUGFIX: Core | Remove null-pointer-exception in TCP connection manager [Parg] BUGFIX: Core | Fix subscription auto-download with sites where supplied referer caused error [Parg] BUGFIX: UIvz | Click area for Friend's "chat thought bubble" was wrong, preventing click to chat in some cases [TuxPaper] BUGFIX: UIvz | Fix share of vuze content (users could only share non-vuze content) [TuxPaper] BUGFIX: UI | Column Setup visual fixes for gtk [TuxPaper] BUGFIX: UI | Revert category buttons to working state [TuxPaper] BUGFIX: UI | Fixed memory leak in All-Peers view [Parg] BUGFIX: UI | Fixed resource disposal in config view causing some status bar icons to not draw [TuxPaper] CHANGE: Core | Remove various debug-spew [Parg] 2009.01.26 | Vuze 4.1.0.0 FEATURE: Core | New FP Ignore rule: Ignore 1st Priority after X hours of idle upload speed (default 24h) [TuxPaper] FEATURE: Core | Support for loading torrents when the HTTP response is an error (like 404, 500) but the data is still a torrent [TuxPaper] FEATURE: UIvz | Support multiple Content Networks [parg,tuxpaper] FEATURE: UI | Experimental neuronal speed algorithm [Gudy] FEATURE: UI | Added AS/ASN peer column [Parg] FEATURE: UI | Added properties view to buddies avatar widget [Parg] FEATURE: UI | Control+I in library to open torrent info (torrent details) page [TuxPaper] FEATURE: Plug | Share categories with friends as subscriptions [Parg] FEATURE: Plug | Support table column removal [Parg] FEATURE: Plug | Added getComputerName method [Parg] FEATURE: Plug | Cache connected friend details for faster reconnect on startup [Parg] CHANGE: Core | Pulled out Vuze related operations into ContentNetwork [Parg] CHANGE: Core | Go to CDP when torrent unauthorised if possible [Parg] CHANGE: Core | Added date field an modified case of response HTTP headers to improve behaviour of SSDP clients [Parg] CHANGE: Core | Limit # of stalled 'seeding' torrents to prevent cases where all completed torrents could start up [TuxPaper] CHANGE: Core | Give stalled torrents a seeding rank handicap based on how long they've been stalled for [TuxPaper] CHANGE: UI | (Memory) Images that are unused after 60 seconds are now disposed of [TuxPaper] CHANGE: UI | Fixed regression of Auto Open Tabs not opening seeding torrents (Config option now split) [TuxPaper] CHANGE: UI | Bring back classic-share menu for non-basic mode users [Parg] BUGFIX: Core | Setting files as do-not-download was deleting files [Parg] BUGFIX: Core | IPv6 compact tracker support [Parg] BUGFIX: Core | Fix possible deadlock in generic connection handling [Parg] BUGFIX: Core | Disable if-modified logic when editting RSS search templates to allow retrieval of results [Parg] BUGFIX: Core | Clear down TLS stuff to reduce memory usage when plugins unloaded [Parg] BUGFIX: UI | Fixed rare case where table rows would display blank [TuxPaper] BUGFIX: UI | Fixed 'close all details' in classic UI [Parg] BUGFIX: UI | Prevent constuction of mytorrents context menu from flipping download stats [Parg] BUGFIX: UI | Fix cursor transition in table cell [Parg] BUGFIX: UI | Fix incorrect handling of weak references for UI views that resulted in them never being released [Parg] BUGFIX: Plug | Various fixes to correctly release unloaded plugin resources [Parg] 2008.11.20 | Vuze 4.0.0.4 FEATURE: UIvz | Ability to change List modes in View menu [TuxPaper] FEATURE: UI | Added a 'mark all results unread' menu item [Parg] FEATURE: UI | Added specification of data save directory to config wizard [Parg] FEATURE: Core | Added subscription support to customisations [Parg] FEATURE: Core | Added an 'azplug' URL protocol to allow plugins to handle URLs [Parg] FEATURE: Core | Allow subscriptions to handle azplug protocols thus allowing plugins to be the source of subscription content [Parg] FEATURE: Core | Allow magnet links in search results [Parg] CHANGE: UIvz | Deleting via toolbar now lets you apply action to all selected entries [TuxPaper] CHANGE: UIvz | Search bar shrinks a bit when there's not enough width to display all toolbar buttons [TuxPaper] CHANGE: UI | Date Column auto-sizer now shows day of month (mm/dd) instead of year (yy/mm) when column is small [TuxPaper] CHANGE: Core | Only show feed errors after 3 consecutive fails to avoid distracting transient errors [Parg] CHANGE: Core | Add asset hash to subscriptions and auto-associate existing content on subscribe if avail [Parg] CHANGE: Core | Various performance improvements [Parg] CHANGE: Core | Modify DHT size calc algorithm to take account of firewalled contact [Parg] CHANGE: Plug | Assume buddies support chat [Parg] BUGFIX: UIvz | "Mark All Watched" now only affects completed content (which is also what Unwatched only shows) [TuxPaper] BUGFIX: UIvz | Fix Global Rating column not sorting properly [TuxPaper] BUGFIX: UIvz | (Mac) Fixed closing sidebar entries sometimes showing a blank area instead of selecting a new sidebar entry [TuxPaper] BUGFIX: UIvz | Fixed bug where "My Library" info bar displayed on Downloading sidebar entry [TuxPaper] BUGFIX: UIvz | Fix some notification entries losing their related avatar image [TuxPaper] BUGFIX: UIvz | Log View's "Show Config" button wasn't going to proper config section [TuxPaper] BUGFIX: UIvz | Fix default visible columns, order, and sort column for new installs for "Advanced" library Lists [TuxPaper] BUGFIX: UI | "Show Time" state on date columns now remembered accross sessions [TuxPaper] BUGFIX: UI | Fix "Pieces" column in Library view not updating unless you clicked it [TuxPaper] BUGFIX: UI | Info tab in Torrent Details now displays more columns that it couldn't before (like share ratio) [TuxPaper] BUGFIX: UI | Localize the date in the subscription view correctly [Parg] BUGFIX: Core | Synchonize access to file operations so that an close op can't be interleaved with file facade switching and bork disk channel operation [Parg] BUGFIX: Core | Filter out duplicate skew reports to get more accurate figures [Parg] BUGFIX: Core | Avoid NPE in chat when buddy unauthorised [Parg] BUGFIX: Core | Preserve argument case in magnet link operations [Parg] BUGFIX: Core | Fix mem leak when DHT router IP changed [Parg] BUGFIX: Plug | Use UTF-8 when decoding plugin descriptions [Parg] 2008.10.24 | Vuze 4.0.0.2 FEATURE: UIvz | Added column to detail the linkage between content and associated subscription, where present [Parg] FEATURE: UIvz | Simple view menu CHANGE: Core | Remove restriction on uniqueness of subscriptions names [Parg] CHANGE: Core | Add popularity to subscription properties and size better [Parg] CHANGE: Core | Impose lower limits on download and upload when auto-speed running [Parg] CHANGE: Core | Reduce subscription publication concurrency [Parg] CHANGE: Core | Reduce acceptance of inaccurate DHT store operations [Parg] CHANGE: Core | Auto-download content when marked as unread in an auto-download enabled subscription [Parg] CHANGE: UIvz | Image on left of search box now activates search when clicked [TuxPaper] CHANGE: UIvz | Toolbar's "Show Text" state now remembered across sessions [TuxPaper] CHANGE: UIvz | Classic users upgrading via the installer will start up in My Library in "small" mode (classic My Torrents View). Previously, only "Advanced UI" users got this. [TuxPaper] CHANGE: UIvz | If you hold the mouse down for a period of time on Up and Down toolbar items, it will move the selected items to the top/bottom (this was present in 4000, but now the tooltip says it) [TuxPaper] CHANGE: UIvz | Added tooltip to subscription wizard to show more details on subscription [Parg] CHANGE: UIvz | Drop into edit mode after creating an RSS subscription [Parg] CHANGE: UIvz | Reduce size shown for downloads to 3 digits max for subscriptions and searches [Parg] CHANGE: UIVz | In Library view fix sort so 'new' entries do sort to top [Parg] CHANGE: Plug | Reduce derived tracker targets by raising swarm size limits [Parg] BUGFIX: Core | Fix auto-subscription of DHT located singleton subscriptions [Parg] BUGFIX: Core | Subscription to already cached, unsubscribed subscriptions wasn't working [Parg] BUGFIX: Core | Fix 100% CPU problem due to unsafe HashSet modification [Parg] BUGFIX: Core | Remove duplicate results from subscriptions [Parg] BUGFIX: Core | Report subscription creation errors to user [Parg] BUGFIX: Core | If a subscription was deleted which being processed it used to report errors [Parg] BUGFIX: Core | Set subscription popularity on selection [Parg] BUGFIX: UIvz | Fixed missing of all incomplete-specific and complete-specific torrent columns in My Library in "big" mode [TuxPaper] BUGFIX: UIvz | If you previously chose top bar to be visible, and you aren't in advanced user mode, there was no way to remove top bar. Fixed by not showing top bar in non-advanced user mode [TuxPaper] BUGFIX: UIvz | Fixed sidebar sash disappearing when moving beyond minimum size [TuxPaper] BUGFIX: UIvz | Fixed "Close All Details" menu item always being disabled [TuxPaper] BUGFIX: UIvz | Fixed extremely slow Library view when one column was animating [TuxPaper] BUGFIX: UI | Table cells with cutoff text should show tooltip now [TuxPaper] BUGFIX: UI | Fixed copying cell's text to clipboard [TuxPaper] BUGFIX: UI | Info tab in Torrent Details now displays some columns that it couldn't before [TuxPaper] BUGFIX: UI | Clear log view widgets when not visible to reduce memory [Parg] BUGFIX: UI | Fix sub tabs in Torrent Details view not remembering their view after restoring from min. state [TuxPaper] 2008.10.15 | Vuze 4.0.0.0 FEATURE: Core | Async request processing for non-blocking tracker [Parg] FEATURE: Core | Support HTTP redirects between http/https protocols in resource downloader [Parg] FEATURE: Core | Add content to UPnP authentication dialogs [Parg] FEATURE: Core | Support PList mods for app registration on OSX [Parg] FEATURE: Core | Added http auth helper to support authenticated search templates/subscriptions [Parg] FEATURE: Core | Fix built in RSS feed parser to handle Atom feeds [Parg] FEATURE: Core | RSS based search templates [Parg] FEATURE: Core | Light weight seeds to allow seeding of simple content such as subscriptions [Parg] FEATURE: Core | Subscriptions [Parg] FEATURE: Core | Added a 'prefer UDP connections' option [Parg] FEATURE: Core | Config options for max queued outgoing connections [Parg] FEATURE: Core | Support dht:// URL protocol [Parg] FEATURE: Core | Advanced options for specifying TCP select timeouts [Parg] FEATURE: UI | Added "Column Setup" icon to the iconbar [amc1] FEATURE: UI | New console command - "plugin". Displays plugin information and can toggle startup status [amc1] FEATURE: UI | Console command "show" can now filter to list only torrents which are transferring [amc1] FEATURE: UIvz | SideBar (F7 to Hide/Show) [TuxPaper] FEATURE: UIvz | New ToolBar with hideable text [TuxPaper] FEATURE: UIvz | Library now has Large and Small view modes. Small view mode is classic My Torrents [TuxPaper] FEATURE: Plug | Added option to remove originators IP address from stored values [Parg] CHANGE: Core | Improve app startup time [Parg] CHANGE: Core | Make full name and namespace URI available to simple XML parser users [Parg] CHANGE: Core | Improved handling of mixed IPv4 and IPv6 bindings [The 8472] CHANGE: Core | New option to refresh UPnP mappings when we become firewalled [amc1] CHANGE: UI | Improve performance with single data source dispatch aggregator [Parg] CHANGE: UI | Debug messages are no longer displayed by default when running the console UI [amc1] CHANGE: UI | The comment icon column now displays a blank icon if there is no comment (rather than no icon) [amc1] CHANGE: UI | Delete priority is now properly reflected in the Priority column [The 8472] CHANGE: UIvz | Faster Startup [parg,TuxPaper] CHANGE: UIvz | Reduced UI memory footprint [TuxPaper] CHANGE: UIvz | Friends moved to the bottom of the sidebar [Khai] CHANGE: UIvz | All table views (Library, Notifications) now use native table widget [TuxPaper] CHANGE: Plug | Essential plugins are now automatically re-enabled if previously disabled by user [amc1] - the "Start / Stop Rules" plugin was disabled by users in the past, this was causing torrents to be stuck in "waiting" state CHANGE: Plug | New command line option - "azureus.safemode", to disable lots of functionality when debugging problems [amc1] CHANGE: Plug | Client ID plugin is removed [amc1] CHANGE: Plug | New command line option - "azureus.loadplugins", to skip plugins being loaded at startup [amc1] CHANGE: Plug | Accept store operations from furher away contacts to decrease store fails [Parg] CHANGE: Plug | Evict contacts sooner from DHT router to improve liveness [Parg] CHANGE: Plug | Delay DHT task init to save memory [Parg] CHANGE: Plug | Finer-mesh for DHT network position derived tracking [Parg] CHANGE: Plug | De-prioritise DHT tracker put ops [Parg] BUGFIX: Core | Fixed problem on Vista where "Failed to establish listen on port UDP:xxxxx" errors may be reported [parg] BUGFIX: Core | Treat any address binds as no bind IP when rewriting URLs [Parg] BUGFIX: Core | Added third party impressions urls for torrent ads [JR] BUGFIX: Core | Fix timer cancellation behaviour [Parg] BUGFIX: Core | Fixed DND deleting files in single-file torrents [The 8472] BUGFIX: Core | Fixed occasional deadlocks on startup under linux [The 8472] BUGFIX: Core | Fixed rare situation where user was prompted for authentication to connect to trackers which didn't need it [amc1] BUGFIX: Core | Made the load and unload buttons on the plugin page behave properly [amc1] BUGFIX: Core | Fixed problem where queueing rules do not enter "seeding-only" mode when there are queued downloads [amc1] BUGFIX: Plug | DHT storage manager key removal fix [Parg] BUGFIX: Plug | Various fixes to avoid DHT running out of control under extreme diversifications BUGFIX: Plug | Fix magnet download timeouts [Parg] BUGFIX; Plug | Fix DHT operation timeout bug introduced when moving to async exec [Parg] BUGFIX: Plug | Limit buddy reconnect to avoid thrashing [Parg] 2008.07.01 | Vuze 3.1.1.0 FEATURE: Core | Added Auto Starting rule to seed large swarms first; useful when many overseeded torrents are in the queue or the upload capacity is far above average [The 8472] FEATURE: UIv3 | Friend Chat (double click on friend icon to chat) [Gudy] FEATURE: UIv3 | Friends Online Status FEATURE: UIv3 | Ability to share content from your computer by dragging it to a Friend [Gudy] CHANGE: Core | Built-in plugins can now be disabled - it didn't work properly in earlier versions [amc1] CHANGE: UI | Create Vivaldi views for each DHT in use [Groundy] CHANGE: UI | Added support for rotation in Vivaldi view [Groundy] CHANGE: UI | Peers view hostname column now sorts host names by the most significant part first [The 8472] CHANGE: UIv3 | Finished fixes for the new styled dialog which are now default in Vuze/Vuze Advanced [knguyen] CHANGE: UIv3 | Added friend icon next to activity entry [TuxPaper] CHANGE: UIv3 | New plugin bar look (removed arrows, added selectable list all plugin bar views) [TuxPaper] BUGFIX: Core | Fixed bug which stopped downloads being stored in the chosen directory [amc1] BUGFIX: Core | Fixed bug which prevented torrent files from being moved properly [amc1] BUGFIX: Core | Reopening torrents does not delete files when setting some of the already existing files to DND anymore [The 8472] BUGFIX: Core | Fixed bug which prevented UPnP mappings from being successful when a SOCKS proxy was used [amc1] BUGFIX: UI | Fixed bug where delete icon on toolbar was not present on OSX [TuxPaper] BUGFIX: UI | Blank cells are now properly put at the bottom when sorting a table column [amc1] BUGFIX: UIv3 | Fixed bottom of list views not repainting properly [TuxPaper] BUGFIX: UIv3 | Remove type headers when switching to date sorting [TuxPaper] 2008.06.16 | Vuze 3.1.0.0 FEATURE: UI | Protocol overhead is now shown in the speed graph [The 8472] FEATURE: UI | Downloads can now be moved and renamed while running - torrent will be auto-paused [amc1] FEATURE: UI | New "rename" action which renames torrent file, save file and displayed name at same time [amc1] FEATURE: UI | Plugin log views now support autoscrolling, pausing and regex filtering [The 8472] FEATURE: UI | Plugin menu items which in the right-click menu now appear in the "Torrent" menu also [amc1] FEATURE: UIv3 | Friends (sharing, bandwidth boost) FEATURE: UIv3 | Greatly Improved Search FEATURE: UIv3 | Experimental option to use Mozilla/Firefox as browser widget on any platform (XulRunner or Firefox 3 must be installed) [The 8472] FEATURE: Plug | Added support for plugins to easily use an external configuration file for settings [amc1] FEATURE: Plug | Plugins can now have full control over on-complete and on-removal file moving [amc1] FEATURE: Plug | Added resource downloader to provide way to download files from Sourceforge [amc1] FEATURE: Plug | Added API methods to generically pop up the message box to a user [amc1] FEATURE: Plug | Added API methods to listen to download-complete events [amc1] FEATURE: Plug | Added various convenience methods for using log views and config models [amc1] FEATURE: Plug | Added API to allow native UI objects to be added to config views [amc1] FEATURE: Plug | Added some more methods for plugins to control some transport mechanisms [amc1] FEATURE: Plug | Added ability to add menus to status entry objects [amc1] FEATURE: Plug | Plugins can now open files using default application handlers [amc1] CHANGE: Core | added "upload_only" flag to AZMP/LTEP handshakes, disconnect any uploading_only peers we don't need / that don't need us when disconnect seeds when seeding is set [The 8472] CHANGE: Core | Further startup speed improvements [The 8472, amc1, Parg] CHANGE: Core | Speedup of various file batch operations (priority changes) [amc1, The 8472] CHANGE: Core | Added option to allow the removal of files linked outside the save directory when removing data [amc1] CHANGE: UI | Column menu option to disable fast renaming in files view, changed fast rename to behave more like the windows explorer [The 8472] CHANGE: UI | In console UI, shrunk help text down to be more concise [amc1] CHANGE: UIv3 | Removed Vuze Header (the top plugin bar is still there but you have to turn it on) BUGFIX: Core | Made change so that plugins could not inadvertently turn off Azureus extension protocol [amc1] BUGFIX: Core | The UDP tracker client option has been nonfunctional for quite a while now -> fixed [The 8472] BUGFIX: Core | Fixed various file-priority-change related bugs that resulted in error states [The 8472] 2008.04.10 | Azureus Vuze 3.0.5.2 FEATURE: UIv3 | Ability to rate directly from rating reminder activity entry [TuxPaper] FEATURE: UIv3 | Added progress spinner animation for the LightBox [knguyen] CHANGE: Core | Don't auto-UDP probe on initial announce if tracker not known to support UDP - hit on second and remember outcome [Parg] CHANGE: Core | Improve startup times by taking various torrent-load operations off main thread [Parg] CHANGE: Core | Add reason-messages for update check failures [Parg] CHANGE: Core | Use derived password to protect private key to allow us to persist password [Parg] CHANGE: Core | Get plugin update URL from version server to support potential future switch [Parg] CHANGE: UI | Run explicit tracker scrapes off UI thread to prevent blocking [Parg] CHANGE: UI | Allow UI initialisation to proceed before plugin init complete [Parg] CHANGE: UIv3 | Always start on "Dashboard" tab (unless Advanced UI chosen), instead of sometimes starting on "On Vuze" tab [TuxPaper] CHANGE: Plug | Ensure that DHT republish events are scheduled using absolute time so recover correctly from computer suspend [Parg] BUGFIX: Core | Handle some badly formed torrents more gracefully (corrupt announce-lists) [Parg] BUGFIX: Core | Handle multiple SSL certs from same URL [Parg] BUGFIX: Core | URLDecode torrent filenames [Parg] BUGFIX: Core | Fix non-crypto fallback outgoing connections [Parg] BUGFIX: Core | Better (esp for Vista) detection of and setting of Azureus' .torrent file association [TuxPaper] BUGFIX: UI | Fix broken per-torrent upload speed setting via options tab [Parg] BUGFIX: UI | Fix alternating bg color not updating after changing in config [TuxPaper] BUGFIX: UIv3 | Fix resource leaks related to light box (login window) [knguyen] 2008.03.05 | Azureus Vuze 3.0.5.0 FEATURE: Core | Added µTorrent PEX support [amc1] FEATURE: Core | Azureus probes trackers for UDP-capabilities on first scrape/announce now and uses udp instead of http where available [The 8472] FEATURE: Core | Added option to enforce IP bindings even when the specified interfaces are not available (useful when Azureus should not use certain network interfaces) [The 8472] FEATURE: Core | Intervene with http seeds if progressive stall imminent [Parg] FEATURE: Core | Message user on startup if they have installed Azureus to read-only location [Parg] FEATURE: Core | Added dnd status to XML stats [Parg] FEATURE: UI | Added option for "Open Containing Folder" menu action - which may integrate better with non-standard file browsers [amc1] FEATURE: UI | Added option for "Show Torrent Menu" -- Users can now decide to see the Torrent menu in the menubar or not [knguyen] FEATURE: UI | Fast Renaming (not moving) in the Files tab (click on name column) and Open Torrent dialog (click on dest. name column) [The 8472] FEATURE: UI | Completed downloaders column [The 8472] FEATURE: UI | Added start/stop to category menu [Parg] FEATURE: UI | Added per-category speed limits [Parg] FEATURE: UI | Added per-category option setting [Parg] FEATURE: UI | Added multiple-torrent options setting to MyTorrents view [Parg] FEATURE: UIv3 | New menu configuration for Vuze and Vuze Advanced UI's [knguyen] FEATURE: UIv3 | Activity Tab [TuxPaper] FEATURE: UIv3 | Vuze Login from client [knguyen] FEATURE: Plug | Added Network Status plugin to perform some basic network tests [Parg] FEATURE: Plug | Allow plugins to specify their minimum JDK requirements [Parg] CHANGE: Core | Further memory footprint reductions; for additional tweaks see http://www.azureuswiki.com/index.php/Reduce_memory_usage [The 8472] CHANGE: Core | Reimplemented LT extension protocol code [amc1] CHANGE: Core | DND/Compact (aka Delete) priority now deletes all files that do not share pieces with normal/high priority files [The 8472] CHANGE: Core | Queuing rules now don't start any further torrents if the global up/download speed limits are reached [The 8472] - makes "don't count torrent ..." minimum speed rules more useful to dynamically regulate the queue lengths - recovers faster from chain reactions in case of connection loss CHANGE: Core | Made the crypto handshake a bit less predictable [The 8472] CHANGE: Core | Added support for IPv6 compact announces (client) and udp-multiscrapes (client+server) [The 8472] CHANGE: Core | Take note of more peer-source selections [Parg] CHANGE: Plug | Added support for plugins which implement mainline DHT [amc1] BUGFIX: Core | Request limiting/Priorities no longer pinch off LAN peers if seperate LAN speeds are enabled [The 8472] BUGFIX: Core | Increase time Azureus holds open listen socket on close to reduce dual-start window [Parg] BUGFIX: Core | Allow ~ character in tracker addresses to support I2P [Parg] BUGFIX: Core | Determine app name correctly on OSX so that restart works for renamed apps [Parg] BUGFIX: UI | Shells no longer use the low-res frog icon, the normal main window icon is now used instead [amc1] BUGFIX: UI | Limiting comments in General View to 5k characters under WinXP to avoid crashes due to faulty comctl32.dll [The 8472] BUGFIX: UI | Setting speed parameters manually now disables autospeed [The 8472] BUGFIX: Plug | Encode spaces correctly in get-right web seed urls [Parg] 2007.12.21 | Azureus Vuze 3.0.4.2 FEATURE: UI | Added "Check Files Exist" menu option [amc1] FEATURE: Plug | Perform low resource usage tracking of online torrents for swarm cross-population purposes [Parg] CHANGE: Core | Added option to disable download speed focus [The 8472] CHANGE: Core | Reduced memory usage for many-torrent instances [The 8472] CHANGE: UI | Multiple selected torrent export now works [amc1] BUGFIX: Core | Fixed IP filters not working when ALLOW instead of DENY was used [Parg] BUGFIX: Core | Improve rebuffering behaviour when real-time pieces are too slow for any peers to get in time [Parg] BUGFIX: Core | Ensure minimum buffer requirements are factored into ETA calculation [Parg] BUGFIX: UI | Eliminated various memory leaks [The 8472] 2007.12.06 | Azureus Vuze 3.0.4.0 FEATURE: Core | Reconnect to peers after unexpected disconnect / recover stats of recently disconnected peers [Parg,The 8472] FEATURE: Core | Global download speed limit can also limit the number of outgoing requests, this should improve TCP performance [The 8472] -does not work with auto-speed since an explicit download speed-limit must be set -downloads from as few peers as possible when the global limit is reached -prioritizes downloads which are on the head of the queue FEATURE: Core | IP binding now provides primitive round-robin load balancing for users with multiple internet connections; accepts interface names and IPv6 binding (if supported on the platform) [The 8472] FEATURE: Core | Embed ChangeLog.txt in release jar [Nolar] FEATURE: UI | Column menu option to automatically put contents of cell into the tooltip [amc1] FEATURE: UI | Piece distribution view is now also available as a peer subview [The 8472] FEATURE: UI | Added 'time remaining' column to peers view [Parg] FEATURE: UI | Added option to suppress file download dialog [knguyen] FEATURE: UI | Various progress reports have been unified; main status bar can display progress for certain processes now [knguyen] FEATURE: Plug | Plugins can now change the color of rows [amc1] FEATURE: Plug | Plugins can add configuration colour parameters [amc1] CHANGE: Core | Attempt to re-open a file when access fails to try and recover from a transient error [Parg] CHANGE: Core | Auto speed default is now the new 'beta' (v2) algorithm [ranul] CHANGE: Core | Revised piece picking code to deal better with some edge cases and snubbed peers [The 8472] CHANGE: Core | Share Ratio/min Seeds ignore rule now applies even when no tracker scrape is available [The 8472] CHANGE: UI | Added private torrent indicator to the general tab [The 8472] CHANGE: UI | Logging Consoles now have regex-based filters [The 8472] CHANGE: UI | Tweaked table views to use a bit less memory and run better when items are being quickly removed/added [TuxPaper] BUGFIX: UI | Don't hang UI redraw if file access is slow [Parg] BUGFIX: UI | Fixed inconsistencies in the Torrent Open Dialog related to renaming and retargeting files and directories [The 8472] 2007.10.04 | Azureus 3.0.3.4 FEATURE: UI | Added "All Peers" view [amc1] CHANGE: Core | Added workarounds for some buggy UPnP router implementations [parg] CHANGE: UI | NAT status bar indicator and health icons now ignore UDP and LAN-local connections [The 8472] BUGFIX: Core | Fixed bug where a torrent's save location is "forgotten" when a recheck is done in some circumstances [amc1] BUGFIX: UI | times > 365 days (such as the uptime) are now displayed properly [The 8472] 2007.09.21 | Azureus 3.0.3.2 BUGFIX: Core | Fixed MacOSX playback bug [TuxPaper] BUGFIX: Core | Fixed update restart bug [Parg] 2007.09.20 | Azureus 3.0.3.0 FEATURE: Core | Added experimental support for LibTorrent extension protocol handshake [amc1] FEATURE: Core | Providing some experimental options for possible workarounds for a particular traffic shaping method See http://www.azureuswiki.com/index.php/Avoid_traffic_shaping#Level_5 for further details FEATURE: UI | Added available disk space indicators to the torrent open dialog (requires Java 1.6) [The 8472] FEATURE: UI | Added "handshake reserved bytes" column in peer view [amc1] FEATURE: UI | Added "Open Transfer Bar on start" and "Remember Transfer Bar" location options [amc1] FEATURE: UI | Added http-seed config to torrent creation wizard [Parg] FEATURE: UIv3 | Embedded Media Player [TuxPaper] CHANGE: Core | Speedup hash-checking by ~30% / less CPU usage [The 8472] CHANGE: Core | More improvements to client identification code [amc1] CHANGE: UI | Provide both "per-torrent" and "across-torrents" speed menu options [amc1] CHANGE: UI | Speed improvements for menu generation and changing file priority in "Files" view [amc1] CHANGE: UI | Allow minibars to stick to any screen border in multi monitor setups [The 8472] CHANGE: Plug | Plugins can now dynamically register language resource bundles [amc1] BUGFIX: Core | Fixed bug when trying to add torrents with semi-colon characters in filename [amc1] BUGFIX: Core | LAN peer detection for explicit IP addresses was broken [Parg] 2007.08.29 | Azureus 3.0.2.2 CHANGE: UI | Improved usability of speed scale widget. [TuxPaper] CHANGE: UI | Restored reposition functionality of torrent context menus [TuxPaper] BUGFIX: Core | *nix: Allowing multi-instance now works again [TuxPaper] BUGFIX: Core | IPv6 DHT v4 pollution fix [Parg] BUGFIX: UI | MacOSX: Fixed not remembering user turned off Maximized state [TuxPaper] BUGFIX: UI | MacOSX: Fixed Drag and Drop for moving torrents in My Torrents view [TuxPaper] BUGFIX: UI | A few config pages had their labels missing [TuxPaper] 2007.08.16 | Azureus 3.0.2.0 FEATURE: Core | Act on suspend/resume events on Windows [Parg] FEATURE: Core | Added new AZ message to inform of bad pieces [Parg] FEATURE: Core | Added new stacked HAVE message to reduce peer-peer overhead [Parg] FEATURE: Core | IPv6 support - dht, version server, tracker and improved transport [Parg] FEATURE: UI | New "Torrent" menu in the menu bar [amc1] FEATURE: UI | New "Piece Distribution" subview in the pieces tab [The 8472] FEATURE: UI | Auto-speed ping views in Tools->Statistics->Transfers when Auto Speed is enabled [Parg] FEATURE: UI | "Clear Resume Data" menu option added [amc1] FEATURE: UI | "Clear remembered save paths" option added (for the Open Torrent dialog) [amc1] CHANGE: Core | Optimise memory usage for single-file downloads [Parg] CHANGE: Core | Optimise memory usage for queued torrents (no need to keep resume data in memory) [Parg] CHANGE: Core | Much better peer ID identification code added, many more clients now correctly identified [amc1] CHANGE: Core | Changes made to identify some "fake" clients (or other clients which identify themselves in a problematic way) [amc1] CHANGE: Core | Biased optimistic disconnect slightly against leechy peers [The 8472] CHANGE: Core | Core changes in some places to allow "Default save path" to be used without requiring "Use default data dir" to be enabled [hasturkun] CHANGE: Core | Reduce CPU usage when many (queued) torrents are present and in the the pieces view [The 8472] CHANGE: Core | *nix: New startup script to detect Gecko/XULRunner and to allow better restarting [TuxPaper] CHANGE: UI | UL/DL speed selection on right click of status bar changed from menu to scale widget. [TuxPaper] Usage: (1) MouseDown+Drag+MouseUp (2) Click+Move+Click (3) Click+type number+Enter CHANGE: UI | Open Torrent Window now asks to create directories if they don't exist yet, instead of evilly auto-creating them when you click the Browse button [The 8472] CHANGE: UI | Added download status, distributed copies and completed piece count to the General torrent view [amc1, The 8472] CHANGE: UI | User Comment field more useful in General torrent view - easy edit link, hyperlink formatting, auto-resizing [amc1] CHANGE: UI | "Show Transfer Bar" menu option is now a checkbox menu item - so you can now hide the transfer bar using the menu item [amc1] CHANGE: Plug | Added setVisible method for plugin menu items [amc1] BUGFIX: Core | Fixed bug where renaming a download for a single file torrent would sometimes cause data to get out of sync and cause file errors [amc1] BUGFIX: Core | Allow pipelined http seed requests to switch torrents [Parg] BUGFIX: Core | Bootstrap DHT better when no contacts [Parg] BUGFIX: Core | Fixed bug where renaming a download in some conditions would generate "Target is sub-directory" errors [amc1] BUGFIX: UI | Fixed swarm view rendering bug where some incomplete peers were shown as full circles [The 8472] BUGFIX: Plug | Fixed bug where previously removed child menu items would still be present when generating some menus [amc1] 2007.06.20 | Azureus 3.0.1.6 FEATURE: Core | IP Filter Autoloading. Supports DAT (eMule), P2P (PeerGardian, splist), and P2B v1,2,3 (Peer Gardian 2) formats. [TuxPaper] FEATURE: UI | Option to display divider lines every 60 updates on the Statistics view [amc1] FEATURE: Plug | Added helper class to make listening to download events across all downloads easier [amc1] FEATURE: Core | Azureus AutoSpeed v2 Beta [ranul] BUGFIX: Core | Plugin installation/updates using Vista [parg,tuxpaper] 2007.05.24 | Azureus 3.0.1.4 FEATURE: Core | Byte-level download control for Downloads [Parg] FEATURE: Core | Speed tester wizard [ranul,Parg] FEATURE: UI | Added "Transfers Bar" (similar to the "Download Bar") [amc1] FEATURE: UI | Correctly identifies FoxTorrent and Blizzard Downloader peers [amc1] FEATURE: UI | Determines version information for Bits On Wheels and Opera peers [amc1] FEATURE: UI | Vivaldi view can use mouse wheel too zoom now (requires clicking on the view first) [TuxPaper] FEATURE: UI | Date Completed column [TuxPaper] FEATURE: UI | (Beta) Various Auto Speed algorithms [ranul] FEATURE: UI | Auto-open MyShares if any shares [Parg] CHANGE: Core | Handle 503s better with webseeds [Jochen Seifarth,Parg] CHANGE: Core | Disable HTTP authentication dialog for webseeds [Parg] CHANGE: Core | Reduce DHT registration counts for queued torrents [Parg] CHANGE: UI | Running Azureus while azureus is already running now brings Azureus to front [TuxPaper] CHANGE: UI | OSX: Make minimize to status bar icon hide the main window instead of putting it in the doc [TuxPaper] BUGFIX: Core | Updater now works on Vista with security challenged users [TuxPaper] BUGFIX: Core | Fixup "Get Right" webseed handling as per the spec [Jochen Seifarth] BUGFIX: Core | Fixed bug which sometimes prevented corrupted torrents being removed properly [amc1] BUGFIX: Core | Fix rare case where app dir on win32 could report wrong azureus dir on multi-az computers [TuxPaper] BUGFIX: Core | Prevent upnp dispatcher queue from growing too large [Parg] BUGFIX: Core | Limit UPnP write-request exec threads [Parg] BUGFIX: UI | Fixed force starting a torrent via the Open Torrent Window options. [TuxPaper] 2007.04.12 | Azureus 3.0.1.2 FEATURE: Core | Auto-speed: added control for forced-max network speed [Parg] BUGFIX: Core | 100% CPU problem in network code under some conditions [Parg] 2007.04.05 | Azureus 3.0.1.0 FEATURE: Core | Option to clear stored tracker list used for creating torrents [amc1] FEATURE: UI | Option to add full UPnP debug information to the log view [amc1] BUGFIX: UI | Fixed issue where excessive file checks were being done when generating the torrent context menu [amc1] 2007.03.15 | Azureus 3.0.0.8 FEATURE: Core | Alerts can now be shown in individual message popup boxes [amc1] FEATURE: Core | Alerts can now be suppressed and shown on demand [amc1] FEATURE: Core | Per-peer upload/download speed limits [Parg] FEATURE: Core | Per-category upload/download speed limits [Parg] FEATURE: Core | Per-torrent super-seeding via MyTorrents context menu [Parg] FEATURE: UI | Option to auto-download and install updates [TuxPaper] FEATURE: UI | Overall piece map for Piece View [TuxPaper] FEATURE: UI | New "Peer ID" columns in the Peers View [amc1] FEATURE: Plug | Plugins can now add their own status indicators on the status bar [amc1] FEATURE: Plug | Plugins can now add menu items to the system tray, download bars, menu bar [amc1] FEATURE: Plug | Plugins can now remove menu items that are created (allows for dynamic menus) [amc1] FEATURE: Plug | Added extra methods on DownloadManager making it easier to listen to download events [amc1] CHANGE: Core | Include msvcr71.dll in Windows installation bundles, for compatibility with Java6 [Nolar] CHANGE: Plug | Added full set of config parameter methods for completeness [amc1] BUGFIX: Plug | UPnP plugin now correctly attempts to remove existing mappings if they are in the way of new mappings [amc1] BUGFIX: Core | Fix Re-adding a torrent causing "1-" or "-1" directories or files [TuxPaper] BUGFIX: Core | Fixed bug where files were sometimes moved into a subdirectory, where the directory name was only one character long [amc1] BUGFIX: Plug | Fixed bug where some plugin menu items didn't appear under certain conditions [amc1] 2007.01.22 | Azureus 2.5.0.4 / 3.0.0.6 FEATURE: Core | New users default save directory is now located in their "My Documents" directory, under "Azureus Downloads" [TuxPaper] FEATURE: Core | Show alerts raised during closedown on next start as these often don't get displayed due to UI shutdown [Parg] FEATURE: Core | Allow plugin installs to place jars into the plugin-shared "shared/lib" directory [Parg] FEATURE: Plug | Unsafe config read/writing [parg] FEATURE: Plug | Plugins can now open and close download bars [amc1] CHANGE: Core | Added scrape delay for stopped/errored torrents, and torrents with high share ratios [TuxPaper] CHANGE: Core | Allow only one active scrape for each tracker [TuxPaper] CHANGE: Core | Release piece-map when not required [Parg] CHANGE: Core | ASN lookup via DNS queries only [Parg] CHANGE: Core | Full recheck of torrent when part of torrent fails hash check on completion [TuxPaper] CHANGE: Core | Take note of banned IPs when we have IP filter turned off - these are independent [Parg] CHANGE: Core | Disable download peer caching for private torrents [Parg] CHANGE: Core | Disconnect currently connected peers on tracker URL change for private torrents [Parg] CHANGE: Core | Remove unused download/upload specific stats from version-check message [Parg] CHANGE: Core | Include IP override in NAT check message for NAT check server to use [Parg] CHANGE: Plug | Timeout UPnP port releases during closedown to prevent Azureus hanging [Parg] BUGFIX: Core | Fix choke/unchoke cycle bug for lan local peers [Nolar] BUGFIX: Core | Fix auto moving torrent data with DND files [TuxPaper] BUGFIX: Core | Fix NPE causing XML stats not to be written [Parg] BUGFIX: UI | Fix crash when opening non-torrent URL when OS has no recognized HTML viewer [TuxPaper] BUGFIX: UI | Fix big icon in name column for OSes using GTK [TuxPaper] BUGFIX: UI | Make Download Basket work again for drag and dropping [TuxPaper] azureus-4.3.0.6/com/0000755000175000017500000000000011310377216013415 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/0000755000175000017500000000000011310377326015051 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/0000755000175000017500000000000011310377556016554 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/0000755000175000017500000000000011310377326020230 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/tracker/0000755000175000017500000000000011310377326021663 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/tracker/peerauth/0000755000175000017500000000000011310377630023476 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/tracker/peerauth/TrackerPeerAuthPlugin.java0000644000175000017500000004424411003335734030557 0ustar adrianadrian/* * Created on Jan 29, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.tracker.peerauth; import java.io.BufferedInputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.StringWriter; import java.net.*; import java.util.*; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.BEncoder; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.ThreadPool; import org.gudy.azureus2.plugins.Plugin; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadAnnounceResult; import org.gudy.azureus2.plugins.download.DownloadAnnounceResultPeer; import org.gudy.azureus2.plugins.download.DownloadManagerListener; import org.gudy.azureus2.plugins.download.DownloadPeerListener; import org.gudy.azureus2.plugins.download.DownloadScrapeResult; import org.gudy.azureus2.plugins.download.DownloadTrackerListener; import org.gudy.azureus2.plugins.logging.LoggerChannel; import org.gudy.azureus2.plugins.logging.LoggerChannelListener; import org.gudy.azureus2.plugins.peers.Peer; import org.gudy.azureus2.plugins.peers.PeerManager; import org.gudy.azureus2.plugins.peers.PeerManagerListener; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.plugins.ui.model.BasicPluginViewModel; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.core.util.bloom.BloomFilterFactory; public class TrackerPeerAuthPlugin implements Plugin, DownloadManagerListener { private static final String PLUGIN_NAME = "Tracker Peer Auth"; private static final String PLUGIN_CONFIGSECTION_ID = "Plugin.trackerpeerauth.name"; private static final int DEFAULT_CHECK_PERIOD = 30*1000; private static final String STATE_ENABLED = "enabled"; private static final String STATE_DISABLED = "disabled"; private static final int TIMER_PERIOD = 10*1000; private PluginInterface plugin_interface; private TorrentAttribute ta_state ; private LoggerChannel log; private Map dt_map = new HashMap(); private ThreadPool thread_pool = new ThreadPool("TrackerPeerAuthPlugin",8, true ); public static void load( PluginInterface plugin_interface ) { plugin_interface.getPluginProperties().setProperty( "plugin.version", "1.0" ); plugin_interface.getPluginProperties().setProperty( "plugin.name", PLUGIN_NAME ); } public void initialize( PluginInterface _plugin_interface ) { plugin_interface = _plugin_interface; ta_state = plugin_interface.getTorrentManager().getPluginAttribute( "state" ); log = plugin_interface.getLogger().getTimeStampedChannel(PLUGIN_NAME); UIManager ui_manager = plugin_interface.getUIManager(); BasicPluginConfigModel config = ui_manager.createBasicPluginConfigModel( ConfigSection.SECTION_PLUGINS, PLUGIN_CONFIGSECTION_ID ); config.addLabelParameter2( "Plugin.trackerpeerauth.info" ); final BasicPluginViewModel view_model = plugin_interface.getUIManager().createBasicPluginViewModel( "Plugin.trackerpeerauth.name" ); view_model.setConfigSectionID(PLUGIN_CONFIGSECTION_ID); view_model.getActivity().setVisible( false ); view_model.getProgress().setVisible( false ); log.addListener( new LoggerChannelListener() { public void messageLogged( int type, String content ) { view_model.getLogArea().appendText( content + "\n" ); } public void messageLogged( String str, Throwable error ) { if ( str.length() > 0 ){ view_model.getLogArea().appendText( str + "\n" ); } StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter( sw ); error.printStackTrace( pw ); pw.flush(); view_model.getLogArea().appendText( sw.toString() + "\n" ); } }); System.out.println( "**** tracker peer auth disabled ****" ); /* plugin_interface.getDownloadManager().addListener( this ); SimpleTimer.addPeriodicEvent( "TrackerPeerAuthPlugin:checker", TIMER_PERIOD, new TimerEventPerformer() { private long tick_count = 0; public void perform( TimerEvent event ) { tick_count++; synchronized( dt_map ){ Iterator it = dt_map.values().iterator(); while( it.hasNext()){ ((DownloadTracker)it.next()).checkPeers( tick_count ); } } } }); */ } public void downloadAdded( final Download download ) { Torrent torrent = download.getTorrent(); if ( torrent != null && torrent.isPrivate()){ download.addTrackerListener( new DownloadTrackerListener() { public void scrapeResult( DownloadScrapeResult result ) { } public void announceResult( DownloadAnnounceResult result ) { if ( result.getResponseType() == DownloadAnnounceResult.RT_SUCCESS ){ Map ext = result.getExtensions(); boolean enabled = true; int check_period = DEFAULT_CHECK_PERIOD; if ( ext != null ){ // TODO: detect enabled state // TODO: get check period } download.setAttribute( ta_state, enabled?STATE_ENABLED:STATE_DISABLED ); setState( download, enabled, check_period ); } } }); String state = download.getAttribute( ta_state ); if ( state != null ){ boolean enabled = state.equals( STATE_ENABLED ); setState( download, enabled, DEFAULT_CHECK_PERIOD ); } } } public void downloadRemoved( Download download ) { synchronized( dt_map ){ dt_map.remove( download ); } } protected void setState( Download download, boolean enabled, int check_period ) { synchronized( dt_map ){ if ( enabled ){ DownloadTracker existing = (DownloadTracker)dt_map.get( download ); if ( existing == null ){ DownloadTracker dt = new DownloadTracker( download, check_period ); dt_map.put( download, dt ); }else{ existing.setCheckPeriod( check_period ); } }else{ dt_map.remove( download ); } } } protected void log( Download download, String str ) { log.log( "Download '" + download.getName() + "' - " + str ); } protected class DownloadTracker implements DownloadPeerListener, PeerManagerListener, DownloadTrackerListener { private static final int BACKOFF_TICK_COUNT = 60*1000 / TIMER_PERIOD; // TODO: private static final int MAX_PEERS_PER_QUERY = 100; private static final int OK_BLOOM_INITIAL = 16*1024; private static final int OK_BLOOM_INC = 16*1024; private static final int OK_BLOOM_MAX = 128*1024; private static final int BAD_BLOOM_INITIAL = 4*1024; private static final int BAD_BLOOM_INC = 4*1024; private static final int BAD_BLOOM_MAX = 64*1024; private Download download; private BloomFilter ok_bloom = BloomFilterFactory.createAddOnly( OK_BLOOM_INITIAL ); private BloomFilter bad_bloom = BloomFilterFactory.createAddOnly( BAD_BLOOM_INITIAL ); private long pending_check_peer_count = 0; private boolean check_running; private int check_tick_count; private int backoff_tick_count; protected DownloadTracker( Download _download, int _min_check_period ) { download = _download; download.addTrackerListener( this ); download.addPeerListener( this ); setCheckPeriod( _min_check_period ); log( "enabled, check period=" + _min_check_period ); } protected void setCheckPeriod( int _min_check_period ) { check_tick_count = _min_check_period / TIMER_PERIOD; } protected void recordPeer( String source, byte[] id, String ip, int port, boolean ok ) { if ( id == null ){ return; } byte[] key = getKey( id, ip ); synchronized( this ){ if ( ok ){ int entries = ok_bloom.getEntryCount(); if ( entries > 0 && ( ok_bloom.getSize() / entries < 10 )){ int new_size = ok_bloom.getSize() + OK_BLOOM_INC; if ( new_size > OK_BLOOM_MAX ){ new_size = OK_BLOOM_MAX; } log( "Expanding ok bloom to " + new_size + " entries" ); BloomFilter new_ok_bloom = BloomFilterFactory.createAddOnly( new_size ); PeerManager pm = download.getPeerManager(); if ( pm != null ){ Peer[] peers = pm.getPeers(); for (int i=0;i 0 && ( bad_bloom.getSize() / entries < 10 )){ int new_size = bad_bloom.getSize() + BAD_BLOOM_INC; if ( new_size > BAD_BLOOM_MAX ){ new_size = BAD_BLOOM_MAX; } log( "Expanding bad bloom to " + new_size + " entries" ); bad_bloom = BloomFilterFactory.createAddOnly( new_size ); } bad_bloom.add( key ); } } } protected void checkPeers( long tick_count ) { if ( backoff_tick_count > 0 ){ backoff_tick_count--; return; } if ( tick_count % check_tick_count == 0 ){ synchronized( this ){ if ( pending_check_peer_count > 0 && !check_running){ pending_check_peer_count = 0; check_running = true; }else{ return; } } boolean gone_async = false; try{ PeerManager pm = download.getPeerManager(); if ( pm != null ){ Peer[] peers = pm.getPeers(); final List to_check = new ArrayList(); for (int i=0;i 0 ){ thread_pool.run( new AERunnable() { public void runSupport() { try{ check( to_check ); }finally{ synchronized( DownloadTracker.this ){ check_running = false; } } } }); gone_async = true; } } }finally{ if ( !gone_async ){ synchronized( this ){ check_running = false; } } } } } protected void check( List peers ) { DownloadAnnounceResult an = download.getLastAnnounceResult(); URL target = an==null?null:an.getURL(); if ( target == null ){ target = download.getTorrent().getAnnounceURL(); } OutputStreamWriter out = null; BufferedInputStream in = null; try{ String url_str = target.toString(); int pos = url_str.indexOf( "announce" ); if ( pos == -1 ){ // TODO: this should be logged once and checked earlier log( "announce URL '" + url_str + "' is non-conformant" ); return; } url_str = url_str.substring(0,pos) + "testauth" + url_str.substring( pos + 8 ); target = new URL( url_str ); Map map = new HashMap(); String peer_str = ""; for (int i=0;i 0 ){ view_model.getLogArea().appendText( str + "\n" ); } StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter( sw ); error.printStackTrace( pw ); pw.flush(); view_model.getLogArea().appendText( sw.toString() + "\n" ); } }); plugin_start_time = plugin_interface.getUtilities().getCurrentSystemTime(); // Assume we have a core, since this is a plugin instance_manager = AzureusCoreFactory.getSingleton().getInstanceManager(); instance_manager.addListener( this ); plugin_interface.getPluginconfig().addListener( new PluginConfigListener() { public void configSaved() { processSubNets( subnets.getValue(),include_wellknown.getValue() ); processAutoAdd( autoadd.getValue()); } }); processSubNets(subnets.getValue(), include_wellknown.getValue()); processAutoAdd(autoadd.getValue()); final DelayedTask dt = plugin_interface.getUtilities().createDelayedTask(new Runnable() { public void run() { plugin_interface.getDownloadManager().addListener( LocalTrackerPlugin.this ); } }); dt.queue(); } public void instanceFound( AZInstance instance ) { if ( !enabled.getValue()){ return; } log.log( "Found: " + instance.getString()); try{ mon.enter(); track_times.put( instance.getID(), new HashMap()); }finally{ mon.exit(); } checkActivation(); } protected void checkActivation() { try{ mon.enter(); if ( active ){ return; } active = true; plugin_interface.getUtilities().createThread( "Tracker", new Runnable() { public void run() { track(); } }); }finally{ mon.exit(); } } public void instanceChanged( AZInstance instance ) { if ( !enabled.getValue()){ return; } log.log( "Changed: " + instance.getString()); } public void instanceLost( AZInstance instance ) { try{ mon.enter(); track_times.remove( instance.getID()); }finally{ mon.exit(); } if ( !enabled.getValue()){ return; } log.log( "Lost: " + instance.getString()); } public void instanceTracked( AZInstanceTracked instance ) { if ( !enabled.getValue()){ return; } handleTrackResult( instance ); } protected void track() { long now = plugin_interface.getUtilities().getCurrentSystemTime(); if ( now - plugin_start_time < 60*1000 ){ try{ // initial small delay to let things stabilise Thread.sleep( 15*1000 ); }catch( Throwable e ){ } } plugin_interface.getUtilities().createTimer( "LanPeerFinder:Tracker", true ).addPeriodicEvent( 30*1000, new UTTimerEventPerformer() { public void perform( UTTimerEvent event ) { current_time = plugin_interface.getUtilities().getCurrentSystemTime(); try{ List todo = new ArrayList(); try{ mon.enter(); Iterator it = downloads.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); Download dl = (Download)entry.getKey(); long when = ((Long)entry.getValue()).longValue(); if ( when > current_time || current_time - when > ANNOUNCE_PERIOD ){ todo.add( dl ); } } }finally{ mon.exit(); } for (int i=0;i now || now - last_track > RE_ANNOUNCE_PERIOD ){ ok = true; downloads.put( download, new Long( now )); } }finally{ mon.exit(); } if ( ok ){ trackSupport( download ); } } protected void trackSupport( final Download download ) { if ( !enabled.getValue()){ return; } int state = download.getState(); if ( state == Download.ST_ERROR || state == Download.ST_STOPPED ){ return; } String[] sources = download.getListAttribute( ta_peer_sources ); boolean ok = false; for (int i=0;i interesting_downloads = new HashMap(); private int interesting_published = 0; private int interesting_pub_max = INTERESTING_PUB_MAX_DEFAULT; private Map running_downloads = new HashMap(); private Map registered_downloads = new HashMap(); private Map limited_online_tracking = new HashMap(); private Map query_map = new HashMap(); private Map in_progress = new HashMap(); // external config to limit plugin op to pure decentralised only private boolean track_only_decentralsed = COConfigurationManager.getBooleanParameter( "dhtplugin.track.only.decentralised", false ); private BooleanParameter track_normal_when_offline; private BooleanParameter track_limited_when_online; private LoggerChannel log; private Map scrape_injection_map = new WeakHashMap(); private Random random = new Random(); private boolean is_running; private AEMonitor this_mon = new AEMonitor( "DHTTrackerPlugin" ); private DHTNetworkPosition[] current_network_positions; private long last_net_pos_time; private AESemaphore initialised_sem = new AESemaphore( "DHTTrackerPlugin:init" ); public static void load( PluginInterface plugin_interface ) { plugin_interface.getPluginProperties().setProperty( "plugin.version", "1.0" ); plugin_interface.getPluginProperties().setProperty( "plugin.name", PLUGIN_NAME ); } public void initialize( PluginInterface _plugin_interface ) { plugin_interface = _plugin_interface; log = plugin_interface.getLogger().getTimeStampedChannel(PLUGIN_NAME); ta_networks = plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_NETWORKS ); ta_peer_sources = plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_PEER_SOURCES ); UIManager ui_manager = plugin_interface.getUIManager(); final BasicPluginViewModel model = ui_manager.createBasicPluginViewModel( PLUGIN_RESOURCE_ID ); model.setConfigSectionID(PLUGIN_CONFIGSECTION_ID); BasicPluginConfigModel config = ui_manager.createBasicPluginConfigModel( ConfigSection.SECTION_PLUGINS, PLUGIN_CONFIGSECTION_ID); track_normal_when_offline = config.addBooleanParameter2( "dhttracker.tracknormalwhenoffline", "dhttracker.tracknormalwhenoffline", TRACK_NORMAL_DEFAULT ); track_limited_when_online = config.addBooleanParameter2( "dhttracker.tracklimitedwhenonline", "dhttracker.tracklimitedwhenonline", TRACK_LIMITED_DEFAULT ); track_limited_when_online.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { configChanged(); } }); track_normal_when_offline.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { track_limited_when_online.setEnabled( track_normal_when_offline.getValue()); configChanged(); } }); if ( !track_normal_when_offline.getValue()){ track_limited_when_online.setEnabled( false ); } interesting_pub_max = plugin_interface.getPluginconfig().getPluginIntParameter( "dhttracker.presencepubmax", INTERESTING_PUB_MAX_DEFAULT ); if ( !TRACK_NORMAL_DEFAULT ){ // should be TRUE by default System.out.println( "**** DHT Tracker default set for testing purposes ****" ); } model.getActivity().setVisible( false ); model.getProgress().setVisible( false ); model.getLogArea().setMaximumSize( 80000 ); log.addListener( new LoggerChannelListener() { public void messageLogged( int type, String message ) { model.getLogArea().appendText( message+"\n"); } public void messageLogged( String str, Throwable error ) { model.getLogArea().appendText( error.toString()+"\n"); } }); model.getStatus().setText( "Initialising" ); log.log( "Waiting for Distributed Database initialisation" ); plugin_interface.addListener( new PluginListener() { public void initializationComplete() { boolean release_now = true; try{ final PluginInterface dht_pi = plugin_interface.getPluginManager().getPluginInterfaceByClass( DHTPlugin.class ); if ( dht_pi != null ){ dht = (DHTPlugin)dht_pi.getPlugin(); final DelayedTask dt = plugin_interface.getUtilities().createDelayedTask( new Runnable() { public void run() { AEThread2 t = new AEThread2( "DHTTrackerPlugin:init", true ) { public void run() { try{ if ( dht.isEnabled()){ log.log( "DDB Available" ); model.getStatus().setText( "Running" ); initialise(); }else{ log.log( "DDB Disabled" ); model.getStatus().setText( "Disabled, Distributed database not available" ); notRunning(); } }catch( Throwable e ){ log.log( "DDB Failed", e ); model.getStatus().setText( "Failed" ); notRunning(); }finally{ initialised_sem.releaseForever(); } } }; t.start(); } }); dt.queue(); release_now = false; }else{ log.log( "DDB Plugin missing" ); model.getStatus().setText( "Failed" ); notRunning(); } }finally{ if ( release_now ){ initialised_sem.releaseForever(); } } } public void closedownInitiated() { } public void closedownComplete() { } }); } protected void notRunning() { plugin_interface.getDownloadManager().addListener( new DownloadManagerListener() { public void downloadAdded( final Download download ) { addDownload( download ); } public void downloadRemoved( Download download ) { removeDownload( download ); } }); } protected void initialise() { is_running = true; plugin_interface.getDownloadManager().addListener( new DownloadManagerListener() { public void downloadAdded( Download download ) { addDownload( download ); } public void downloadRemoved( Download download ) { removeDownload( download ); } }); plugin_interface.getUtilities().createTimer("DHT Tracker", true ).addPeriodicEvent( 15000, new UTTimerEventPerformer() { private int ticks; public void perform( UTTimerEvent event) { ticks++; processRegistrations( ticks%8==0 ); if ( ticks == 2 || ticks%4==0 ){ processNonRegistrations(); } } }); } public void waitUntilInitialised() { initialised_sem.reserve(); } public boolean isRunning() { return( is_running ); } public void addDownload( final Download download ) { // bail on our low noise ones, these don't require decentralised tracking if ( download.getFlag( Download.FLAG_LOW_NOISE )){ return; } if ( track_only_decentralsed ){ Torrent torrent = download.getTorrent(); if ( torrent != null ){ if ( !TorrentUtils.isDecentralised( torrent.getAnnounceURL())){ return; } } } if ( is_running ){ String[] networks = download.getListAttribute( ta_networks ); Torrent torrent = download.getTorrent(); if ( torrent != null && networks != null ){ boolean public_net = false; for (int i=0;i start_time ){ delay = 0; }else{ delay = plugin_interface.getUtilities().getCurrentSystemTime() + INTERESTING_INIT_MIN_OURS + random.nextInt( INTERESTING_INIT_RAND_OURS ); } }else{ int min; int rand; if ( TorrentUtils.isDecentralised( torrent.getAnnounceURL())){ min = INTERESTING_DHT_INIT_MIN; rand = INTERESTING_DHT_INIT_RAND; }else{ min = INTERESTING_INIT_MIN_OTHERS; rand = INTERESTING_INIT_RAND_OTHERS; } delay = plugin_interface.getUtilities().getCurrentSystemTime() + min + random.nextInt( rand ); } try{ this_mon.enter(); interesting_downloads.put( download, new Long( delay )); }finally{ this_mon.exit(); } } } download.addAttributeListener(DHTTrackerPlugin.this, ta_networks, DownloadAttributeListener.WRITTEN); download.addAttributeListener(DHTTrackerPlugin.this, ta_peer_sources, DownloadAttributeListener.WRITTEN); download.addTrackerListener( DHTTrackerPlugin.this ); download.addListener( DHTTrackerPlugin.this ); checkDownloadForRegistration( download, true ); }else{ Torrent torrent = download.getTorrent(); if ( torrent != null && torrent.isDecentralised()){ download.addListener( new DownloadListener() { public void stateChanged( final Download download, int old_state, int new_state ) { int state = download.getState(); if ( state == Download.ST_DOWNLOADING || state == Download.ST_SEEDING ){ download.setAnnounceResult( new DownloadAnnounceResult() { public Download getDownload() { return( download ); } public int getResponseType() { return( DownloadAnnounceResult.RT_ERROR ); } public int getReportedPeerCount() { return( 0 ); } public int getSeedCount() { return( 0 ); } public int getNonSeedCount() { return( 0 ); } public String getError() { return( "Distributed Database Offline" ); } public URL getURL() { return( download.getTorrent().getAnnounceURL()); } public DownloadAnnounceResultPeer[] getPeers() { return( new DownloadAnnounceResultPeer[0] ); } public long getTimeToWait() { return( 0 ); } public Map getExtensions() { return( null ); } }); } } public void positionChanged( Download download, int oldPosition, int newPosition ) { } }); download.setScrapeResult( new DownloadScrapeResult() { public Download getDownload() { return( download ); } public int getResponseType() { return( RT_ERROR ); } public int getSeedCount() { return( -1 ); } public int getNonSeedCount() { return( -1 ); } public long getScrapeStartTime() { return( SystemTime.getCurrentTime()); } public void setNextScrapeStartTime( long nextScrapeStartTime) { } public long getNextScrapeStartTime() { return( -1 ); } public String getStatus() { return( "Distributed Database Offline" ); } public URL getURL() { return( download.getTorrent().getAnnounceURL()); } }); } } } public void removeDownload( Download download ) { if ( is_running ){ download.removeTrackerListener( DHTTrackerPlugin.this ); download.removeListener( DHTTrackerPlugin.this ); try{ this_mon.enter(); interesting_downloads.remove( download ); running_downloads.remove( download ); limited_online_tracking.remove( download ); }finally{ this_mon.exit(); } }else{ } } public void attributeEventOccurred(Download download, TorrentAttribute attr, int event_type) { checkDownloadForRegistration(download, false); } public void scrapeResult( DownloadScrapeResult result ) { checkDownloadForRegistration( result.getDownload(), false ); } public void announceResult( DownloadAnnounceResult result ) { checkDownloadForRegistration( result.getDownload(), false ); } protected void checkDownloadForRegistration( Download download, boolean first_time ) { int state = download.getState(); int register_type = REG_TYPE_NONE; String register_reason; Random random = new Random(); /* * Queued downloads are removed from the set to consider as we now have the "presence store" * mechanism to ensure that there are a number of peers out there to provide torrent download * if required. This has been done to avoid the large number of registrations that users with * large numbers of queued torrents were getting. */ if ( state == Download.ST_DOWNLOADING || state == Download.ST_SEEDING || // state == Download.ST_QUEUED || download.isPaused()){ // pause is a transitory state, don't dereg String[] networks = download.getListAttribute( ta_networks ); Torrent torrent = download.getTorrent(); if ( torrent != null && networks != null ){ boolean public_net = false; for (int i=0;i 0 ){ try{ this_mon.enter(); Integer existing_type = (Integer)running_downloads.get( download ); if ( register_type != REG_TYPE_NONE ){ if ( existing_type == null ){ log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, "Monitoring '" + download.getName() + "': " + register_reason); running_downloads.put( download, new Integer( register_type )); }else if ( existing_type.intValue() == REG_TYPE_DERIVED && register_type == REG_TYPE_FULL ){ // upgrade running_downloads.put( download, new Integer( register_type )); } }else{ if ( existing_type != null ){ log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, "Not monitoring '" + download.getName() + "': " + register_reason); running_downloads.remove( download ); // add back to interesting downloads for monitoring interesting_downloads.put( download, new Long( plugin_interface.getUtilities().getCurrentSystemTime() + INTERESTING_INIT_MIN_OTHERS )); }else{ if ( first_time ){ log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, "Not monitoring '" + download.getName() + "': " + register_reason); } } } }finally{ this_mon.exit(); } } } protected void processRegistrations( boolean full_processing ) { int tcp_port = plugin_interface.getPluginconfig().getIntParameter( "TCP.Listen.Port" ); String port_override = COConfigurationManager.getStringParameter("TCP.Listen.Port.Override"); if( !port_override.equals("")){ try{ tcp_port = Integer.parseInt( port_override ); }catch( Throwable e ){ } } if ( tcp_port == 0 ){ log.log( "TCP port=0, registration not performed" ); return; } String override_ips = COConfigurationManager.getStringParameter( "Override Ip", "" ); String override_ip = null; if ( override_ips.length() > 0 ){ // gotta select an appropriate override based on network type StringTokenizer tok = new StringTokenizer( override_ips, ";" ); while( tok.hasMoreTokens()){ String this_address = (String)tok.nextToken().trim(); if ( this_address.length() > 0 ){ String cat = AENetworkClassifier.categoriseAddress( this_address ); if ( cat == AENetworkClassifier.AT_PUBLIC ){ override_ip = this_address; break; } } } } if ( override_ip != null ){ try{ override_ip = PRHelpers.DNSToIPAddress( override_ip ); }catch( UnknownHostException e){ log.log( " Can't resolve IP override '" + override_ip + "'" ); override_ip = null; } } // format is [ip_override:]tcp_port[;C][;udp_port] String value_to_put = override_ip==null?"":(override_ip+":"); value_to_put += tcp_port; if ( NetworkManager.REQUIRE_CRYPTO_HANDSHAKE ){ value_to_put += ";C"; } int udp_port = plugin_interface.getPluginconfig().getIntParameter( "UDP.Listen.Port" ); int dht_port = dht.getLocalAddress().getAddress().getPort(); if ( udp_port != dht_port ){ value_to_put += ";" + udp_port; } putDetails put_details = new putDetails( value_to_put, override_ip, tcp_port, udp_port ); ArrayList rds; try{ this_mon.enter(); rds = new ArrayList(running_downloads.keySet()); }finally{ this_mon.exit(); } long now = SystemTime.getCurrentTime(); if ( full_processing ){ Iterator rds_it = rds.iterator(); List interesting = new ArrayList(); while( rds_it.hasNext()){ Download dl = rds_it.next(); int reg_type = REG_TYPE_NONE; try{ this_mon.enter(); Integer x = (Integer)running_downloads.get( dl ); if ( x != null ){ reg_type = x.intValue(); } }finally{ this_mon.exit(); } if ( reg_type == REG_TYPE_NONE ){ continue; } long metric = getDerivedTrackMetric( dl ); interesting.add( new Object[]{ dl, new Long( metric )} ); } Collections.sort( interesting, new Comparator() { public int compare( Object[] entry1, Object[] entry2) { long res = ((Long)entry2[1]).longValue() - ((Long)entry1[1]).longValue(); if( res < 0 ){ return( -1 ); }else if ( res > 0 ){ return( 1 ); }else{ return( 0 ); } } }); Iterator it = interesting.iterator(); int num = 0; while( it.hasNext()){ Object[] entry = it.next(); Download dl = (Download)entry[0]; long metric = ((Long)entry[1]).longValue(); num++; if ( metric > 0 ){ if ( num <= DL_DERIVED_MIN_TRACK ){ // leave as is }else if ( num <= DL_DERIVED_MAX_TRACK ){ // scale metric between limits metric = ( metric * ( DL_DERIVED_MAX_TRACK - num )) / ( DL_DERIVED_MAX_TRACK - DL_DERIVED_MIN_TRACK ); }else{ metric = 0; } } if ( metric > 0 ){ dl.setUserData( DL_DERIVED_METRIC_KEY, new Long( metric )); }else{ dl.setUserData( DL_DERIVED_METRIC_KEY, null ); } } } Iterator rds_it = rds.iterator(); // first off do any puts while( rds_it.hasNext()){ Download dl = rds_it.next(); int reg_type = REG_TYPE_NONE; try{ this_mon.enter(); Integer x = (Integer)running_downloads.get( dl ); if ( x != null ){ reg_type = x.intValue(); } }finally{ this_mon.exit(); } if ( reg_type == REG_TYPE_NONE ){ continue; } byte flags = isComplete( dl )?DHTPlugin.FLAG_SEEDING:DHTPlugin.FLAG_DOWNLOADING; RegistrationDetails registration = (RegistrationDetails)registered_downloads.get( dl ); boolean do_it = false; if ( registration == null ){ log.log( "Registering download '" + dl.getName() + "' as " + (flags == DHTPlugin.FLAG_SEEDING?"Seeding":"Downloading")); registration = new RegistrationDetails( dl, reg_type, put_details, flags ); registered_downloads.put( dl, registration ); do_it = true; }else{ boolean targets_changed = false; if ( full_processing ){ targets_changed = registration.updateTargets( dl, reg_type ); } if ( targets_changed || registration.getFlags() != flags || !registration.getPutDetails().sameAs( put_details )){ log.log((registration==null?"Registering":"Re-registering") + " download '" + dl.getName() + "' as " + (flags == DHTPlugin.FLAG_SEEDING?"Seeding":"Downloading")); registration.update( put_details, flags ); do_it = true; } } if ( do_it ){ try{ this_mon.enter(); query_map.put( dl, new Long( now )); }finally{ this_mon.exit(); } trackerPut( dl, registration ); } } // second any removals Iterator> rd_it = registered_downloads.entrySet().iterator(); while( rd_it.hasNext()){ Map.Entry entry = rd_it.next(); final Download dl = entry.getKey(); boolean unregister; try{ this_mon.enter(); unregister = !running_downloads.containsKey( dl ); }finally{ this_mon.exit(); } if ( unregister ){ log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "Unregistering download '" + dl.getName() + "'"); rd_it.remove(); try{ this_mon.enter(); query_map.remove( dl ); }finally{ this_mon.exit(); } trackerRemove( dl, entry.getValue()); } } // lastly gets rds_it = rds.iterator(); while( rds_it.hasNext()){ final Download dl = (Download)rds_it.next(); Long next_time; try{ this_mon.enter(); next_time = (Long)query_map.get( dl ); }finally{ this_mon.exit(); } if ( next_time != null && now >= next_time.longValue()){ int reg_type = REG_TYPE_NONE; try{ this_mon.enter(); query_map.remove( dl ); Integer x = (Integer)running_downloads.get( dl ); if ( x != null ){ reg_type = x.intValue(); } }finally{ this_mon.exit(); } final long start = SystemTime.getCurrentTime(); // if we're already connected to > NUM_WANT peers then don't bother with the main announce PeerManager pm = dl.getPeerManager(); // don't query if this download already has an active DHT operation boolean skip = isActive( dl ) || reg_type == REG_TYPE_NONE; if ( skip ){ log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "Deferring announce for '" + dl.getName() + "' as activity outstanding"); } RegistrationDetails registration = (RegistrationDetails)registered_downloads.get( dl ); if ( registration == null ){ Debug.out( "Inconsistent, registration should be non-null" ); continue; } boolean derived_only = false; if ( pm != null && !skip ){ int con = pm.getStats().getConnectedLeechers() + pm.getStats().getConnectedSeeds(); derived_only = con >= NUM_WANT; } if ( !skip ){ skip = trackerGet( dl, registration, derived_only ) == 0; } // if we didn't kick off a get then we have to reschedule here as normally // the get operation will do the rescheduling when it receives a result if ( skip ){ try{ this_mon.enter(); if ( running_downloads.containsKey( dl )){ // use "min" here as we're just deferring it query_map.put( dl, new Long( start + ANNOUNCE_MIN_DEFAULT )); } }finally{ this_mon.exit(); } } } } } protected long getDerivedTrackMetric( Download download ) { // metric between -100 and + 100. Note that all -ve mean 'don't do it' // they're just indicating different reasons Torrent t = download.getTorrent(); if ( t == null ){ return( -100 ); } if ( t.getSize() < 10*1024*1024 ){ return( -99 ); } DownloadAnnounceResult announce = download.getLastAnnounceResult(); if ( announce == null || announce.getResponseType() != DownloadAnnounceResult.RT_SUCCESS ){ return( -98 ); } DownloadScrapeResult scrape = download.getLastScrapeResult(); if ( scrape == null || scrape.getResponseType() != DownloadScrapeResult.RT_SUCCESS ){ return( -97 ); } int leechers = scrape.getNonSeedCount(); // int seeds = scrape.getSeedCount(); int total = leechers; // parg - changed to just use leecher count rather than seeds+leechers if ( total >= 2000 ){ return( 100 ); }else if ( total <= 200 ){ return( 0 ); }else{ return( ( total - 200 ) / 4 ); } } protected void trackerPut( final Download download, RegistrationDetails details ) { final long start = SystemTime.getCurrentTime(); trackerTarget[] targets = details.getTargets( true ); byte flags = details.getFlags(); for (int i=0;i " + encoded, encoded_bytes, flags, false, new DHTPluginOperationListener() { public void diversified() { } public void starts( byte[] key ) { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] key, boolean timeout_occurred ) { if ( target.getType() == REG_TYPE_FULL ){ log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, "Registration of '" + download.getName() + "'" + target.getDesc() + " completed (elapsed=" + (SystemTime.getCurrentTime() - start) + ")"); } // decreaseActive( dl ); } }); } } protected int trackerGet( final Download download, final RegistrationDetails details, final boolean derived_only ) { final long start = SystemTime.getCurrentTime(); final Torrent torrent = download.getTorrent(); final URL url_to_report = torrent.isDecentralised()?torrent.getAnnounceURL():DEFAULT_URL; trackerTarget[] targets = details.getTargets( false ); final long[] max_retry = { 0 }; int num_done = 0; for (int i=0;i addresses = new ArrayList(); List ports = new ArrayList(); List udp_ports = new ArrayList(); List is_seeds = new ArrayList(); List flags = new ArrayList(); int seed_count; int leecher_count; boolean complete; public void diversified() { } public void starts( byte[] key ) { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { synchronized( this ){ if ( complete ){ return; } try{ String[] tokens = new String(value.getValue()).split(";"); String tcp_part = tokens[0].trim(); int sep = tcp_part.indexOf(':'); String ip_str = null; String tcp_port_str; if ( sep == -1 ){ tcp_port_str = tcp_part; }else{ ip_str = tcp_part.substring( 0, sep ); tcp_port_str = tcp_part.substring( sep+1 ); } int tcp_port = Integer.parseInt( tcp_port_str ); if ( tcp_port > 0 && tcp_port < 65536 ){ String flag_str = null; int udp_port = -1; try{ for (int i=1;i 0 ){ if ( Character.isDigit( token.charAt( 0 ))){ udp_port = Integer.parseInt( token ); if ( udp_port <= 0 || udp_port >=65536 ){ udp_port = -1; } }else{ flag_str = token; } } } }catch( Throwable e ){ } addresses.add( ip_str==null?originator.getAddress().getAddress().getHostAddress():ip_str); ports.add( new Integer( tcp_port )); udp_ports.add( new Integer( udp_port==-1?originator.getAddress().getPort():udp_port)); flags.add( flag_str ); if (( value.getFlags() & DHTPlugin.FLAG_DOWNLOADING ) == 1 ){ leecher_count++; is_seeds.add( new Boolean( false )); }else{ is_seeds.add( new Boolean( true )); seed_count++; } } }catch( Throwable e ){ // in case we get crap back (someone spamming the DHT) just // silently ignore } } } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] key, boolean timeout_occurred ) { synchronized( this ){ if ( complete ){ return; } complete = true; } if ( target.getType() == REG_TYPE_FULL || ( target.getType() == REG_TYPE_DERIVED && seed_count + leecher_count > 1 )){ log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, "Get of '" + download.getName() + "'" + target.getDesc() + " completed (elapsed=" + (SystemTime.getCurrentTime() - start) + "), addresses=" + addresses.size() + ", seeds=" + seed_count + ", leechers=" + leecher_count); } decreaseActive(download); int peers_found = addresses.size(); List peers_for_announce = new ArrayList(); // scale min and max based on number of active torrents // we don't want more than a few announces a minute int announce_per_min = 4; int num_active = query_map.size(); int announce_min = Math.max( ANNOUNCE_MIN_DEFAULT, ( num_active / announce_per_min )*60*1000 ); int announce_max = derived_only?ANNOUNCE_MAX_DERIVED_ONLY:ANNOUNCE_MAX; announce_min = Math.min( announce_min, announce_max ); final long retry = announce_min + peers_found*(announce_max-announce_min)/NUM_WANT; try{ this_mon.enter(); if ( running_downloads.containsKey( download )){ long absolute_retry = SystemTime.getCurrentTime() + retry; if ( absolute_retry > max_retry[0] ){ // only update next query time if none set yet // or we appear to have set the existing one. If we // don't do this then we'll overwrite any rescheduled // announces Long existing = (Long)query_map.get( download ); if ( existing == null || existing.longValue() == max_retry[0] ){ max_retry[0] = absolute_retry; query_map.put( download, new Long( absolute_retry )); } } } }finally{ this_mon.exit(); } int download_state = download.getState(); boolean we_are_seeding = download_state == Download.ST_SEEDING; putDetails put_details = details.getPutDetails(); String ext_address = put_details.getIPOverride(); if ( ext_address == null ){ ext_address = dht.getLocalAddress().getAddress().getAddress().getHostAddress(); } for (int i=0;i 0 ){ PeerManager pm = download.getPeerManager(); if ( pm != null ){ // try some limited direct injection List temp = new ArrayList( peers_for_announce ); Random rand = new Random(); for (int i=0;i 0; i++ ){ DownloadAnnounceResultPeer peer = temp.remove( rand.nextInt( temp.size())); log.log( " Injecting derived peer " + peer.getAddress() + " into " + download.getName()); Map user_data = new HashMap(); user_data.put( Peer.PR_PRIORITY_CONNECTION, new Boolean( true )); pm.addPeer( peer.getAddress(), peer.getPort(), peer.getUDPPort(), peer.getProtocol() == DownloadAnnounceResultPeer.PROTOCOL_CRYPT, user_data ); } } } if ( download_state == Download.ST_DOWNLOADING || download_state == Download.ST_SEEDING ){ final DownloadAnnounceResultPeer[] peers = new DownloadAnnounceResultPeer[peers_for_announce.size()]; peers_for_announce.toArray( peers ); download.setAnnounceResult( new DownloadAnnounceResult() { public Download getDownload() { return( download ); } public int getResponseType() { return( DownloadAnnounceResult.RT_SUCCESS ); } public int getReportedPeerCount() { return( peers.length); } public int getSeedCount() { return( seed_count ); } public int getNonSeedCount() { return( leecher_count ); } public String getError() { return( null ); } public URL getURL() { return( url_to_report ); } public DownloadAnnounceResultPeer[] getPeers() { return( peers ); } public long getTimeToWait() { return( retry/1000 ); } public Map getExtensions() { return( null ); } }); } // only inject the scrape result if the torrent is decentralised. If we do this for // "normal" torrents then it can have unwanted side-effects, such as stopping the torrent // due to ignore rules if there are no downloaders in the DHT - bthub backup, for example, // isn't scrapable... // hmm, ok, try being a bit more relaxed about this, inject the scrape if // we have any peers. boolean inject_scrape = leecher_count > 0; DownloadScrapeResult result = download.getLastScrapeResult(); if ( result == null || result.getResponseType() == DownloadScrapeResult.RT_ERROR ){ }else{ // if the currently reported values are the same as the // ones we previously injected then overwrite them // note that we can't test the URL to see if we originated // the scrape values as this gets replaced when a normal // scrape fails :( int[] prev = (int[])scrape_injection_map.get( download ); if ( prev != null && prev[0] == result.getSeedCount() && prev[1] == result.getNonSeedCount()){ inject_scrape = true; } } if ( torrent.isDecentralised() || inject_scrape ){ // make sure that the injected scrape values are consistent // with our currently connected peers PeerManager pm = download.getPeerManager(); int local_seeds = 0; int local_leechers = 0; if ( pm != null ){ Peer[] dl_peers = pm.getPeers(); for (int i=0;i 0 ){ is_complete = false; } } } return( is_complete ); } protected void trackerRemove( final Download download, RegistrationDetails details ) { final long start = SystemTime.getCurrentTime(); trackerTarget[] targets = details.getTargets( true ); for (int i=0;i to_scrape = new ArrayList(); try{ this_mon.enter(); Iterator it = interesting_downloads.keySet().iterator(); while( it.hasNext() && ready_download == null ){ Download download = it.next(); Torrent torrent = download.getTorrent(); if ( torrent == null ){ continue; } Integer state = running_downloads.get( download ); if ( state == null || state.intValue() == REG_TYPE_DERIVED ){ // looks like we'll need the scrape below to_scrape.add( download ); } } }finally{ this_mon.exit(); } Map scrapes = new HashMap(); for (int i=0;i it = interesting_downloads.keySet().iterator(); while( it.hasNext() && ready_download == null ){ Download download = it.next(); Torrent torrent = download.getTorrent(); if ( torrent == null ){ continue; } Integer state = running_downloads.get( download ); if ( state == null || state.intValue() == REG_TYPE_DERIVED ){ boolean force = torrent.wasCreatedByUs(); if ( !force ){ if ( false && !dht.isReachable()){ continue; } if ( interesting_pub_max > 0 && interesting_published > interesting_pub_max ){ continue; } DownloadScrapeResult scrape = (DownloadScrapeResult)scrapes.get( download ); if ( scrape == null ){ // catch it next time round continue; } if ( scrape.getSeedCount() + scrape.getNonSeedCount() > NUM_WANT ){ continue; } } long target = ((Long)interesting_downloads.get( download )).longValue(); long check_period = TorrentUtils.isDecentralised( torrent.getAnnounceURL())?INTERESTING_DHT_CHECK_PERIOD:INTERESTING_CHECK_PERIOD; if ( target <= now ){ ready_download = download; ready_download_next_check = now + check_period; interesting_downloads.put( download, new Long( ready_download_next_check )); }else if ( target - now > check_period ){ interesting_downloads.put( download, new Long( now + (target%check_period))); } } } }finally{ this_mon.exit(); } if ( ready_download != null ){ final Download f_ready_download = ready_download; if ( dht.isDiversified( ready_download.getTorrent().getHash())){ // System.out.println( "presence query for " + f_ready_download.getName() + "-> diversified pre start" ); try{ this_mon.enter(); interesting_downloads.remove( f_ready_download ); }finally{ this_mon.exit(); } }else{ //System.out.println( "presence query for " + ready_download.getName()); final long start = now; final long f_next_check = ready_download_next_check; dht.get( ready_download.getTorrent().getHash(), "Presence query for '" + ready_download.getName() + "'", (byte)0, INTERESTING_AVAIL_MAX, ANNOUNCE_TIMEOUT, false, false, new DHTPluginOperationListener() { private boolean diversified; private int leechers = 0; private int seeds = 0; public void diversified() { diversified = true; } public void starts( byte[] key ) { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { if (( value.getFlags() & DHTPlugin.FLAG_DOWNLOADING ) == 1 ){ leechers++; }else{ seeds++; } } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] key, boolean timeout_occurred ) { // System.out.println( " presence query for " + f_ready_download.getName() + "->" + total + "/div = " + diversified ); int total = leechers + seeds; log.log( f_ready_download.getTorrent(), LoggerChannel.LT_INFORMATION, "Presence query for '" + f_ready_download.getName() + "': availability="+ (total==INTERESTING_AVAIL_MAX?(INTERESTING_AVAIL_MAX+"+"):(total+"")) + ",div=" + diversified + " (elapsed=" + (SystemTime.getCurrentTime() - start) + ")"); if ( diversified ){ try{ this_mon.enter(); interesting_downloads.remove( f_ready_download ); }finally{ this_mon.exit(); } }else if ( total < INTERESTING_AVAIL_MAX ){ // once we're registered we don't need to process this download any // more unless it goes active and then inactive again try{ this_mon.enter(); interesting_downloads.remove( f_ready_download ); }finally{ this_mon.exit(); } interesting_published++; dht.put( f_ready_download.getTorrent().getHash(), "Presence store '" + f_ready_download.getName() + "'", "0".getBytes(), // port 0, no connections (byte)0, new DHTPluginOperationListener() { public void diversified() { } public void starts( byte[] key ) { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] key, boolean timeout_occurred ) { } }); } f_ready_download.setScrapeResult( new DownloadScrapeResult() { public Download getDownload() { return( null ); } public int getResponseType() { return( RT_SUCCESS ); } public int getSeedCount() { return( seeds ); } public int getNonSeedCount() { return( leechers ); } public long getScrapeStartTime() { return( SystemTime.getCurrentTime()); } public void setNextScrapeStartTime( long nextScrapeStartTime) { } public long getNextScrapeStartTime() { return( f_next_check ); } public String getStatus() { return( "OK" ); } public URL getURL() { return( f_ready_download.getTorrent().getAnnounceURL()); } }); } }); } } } public void stateChanged( Download download, int old_state, int new_state ) { int state = download.getState(); try{ this_mon.enter(); if ( state == Download.ST_DOWNLOADING || state == Download.ST_SEEDING || state == Download.ST_QUEUED ){ // included queued here for the mo to avoid lots // of thrash for torrents that flip a lot if ( running_downloads.containsKey( download )){ // force requery query_map.put( download, new Long( SystemTime.getCurrentTime())); } } }finally{ this_mon.exit(); } // don't do anything if paused as we want things to just continue as they are (we would force an announce here otherwise) if ( !download.isPaused()){ checkDownloadForRegistration( download, false ); } } public void announceAll() { log.log( "Announce-all requested" ); Long now = new Long( SystemTime.getCurrentTime()); try{ this_mon.enter(); Iterator> it = query_map.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = it.next(); entry.setValue( now ); } }finally{ this_mon.exit(); } } public void positionChanged( Download download, int oldPosition, int newPosition ) { } protected void configChanged() { Download[] downloads = plugin_interface.getDownloadManager().getDownloads(); for (int i=0;i not_put_targets; private long derived_active_start = -1; private long previous_metric; protected RegistrationDetails( Download _download, int _reg_type, putDetails _put_details, byte _flags ) { put_details = _put_details; flags = _flags; getTrackerTargets( _download, _reg_type ); } protected void update( putDetails _put_details, byte _flags ) { put_details = _put_details; flags = _flags; } protected boolean updateTargets( Download _download, int _reg_type ) { trackerTarget[] old_put_targets = put_targets; getTrackerTargets( _download, _reg_type ); // first remove any redundant entries for (int i=0;i result = new ArrayList( Arrays.asList( put_targets )); for (int i=0;i result = new ArrayList(); if ( type == REG_TYPE_FULL ){ result.add( new trackerTarget( torrent_hash, REG_TYPE_FULL, "" )); } if ( ADD_ASN_DERIVED_TARGET ){ NetworkAdminASN net_asn = NetworkAdmin.getSingleton().getCurrentASN(); String as = net_asn.getAS(); String asn = net_asn.getASName(); if ( as.length() > 0 && asn.length() > 0 ){ String key = "azderived:asn:" + as; try{ byte[] asn_bytes = key.getBytes( "UTF-8" ); byte[] key_bytes = new byte[torrent_hash.length + asn_bytes.length]; System.arraycopy( torrent_hash, 0, key_bytes, 0, torrent_hash.length ); System.arraycopy( asn_bytes, 0, key_bytes, torrent_hash.length, asn_bytes.length ); result.add( new trackerTarget( key_bytes, REG_TYPE_DERIVED, asn + "/" + as )); }catch( Throwable e ){ Debug.printStackTrace(e); } } } if ( ADD_NETPOS_DERIVED_TARGETS ){ long now = SystemTime.getMonotonousTime(); boolean do_it; Long metric = (Long)download.getUserData( DL_DERIVED_METRIC_KEY ); boolean do_it_now = metric != null; if ( derived_active_start >= 0 && now - derived_active_start <= DERIVED_ACTIVE_MIN_MILLIS ){ do_it = true; if ( metric == null ){ metric = new Long( previous_metric ); } }else{ if ( do_it_now ){ do_it = true; }else{ derived_active_start = -1; do_it = false; } } boolean newly_active = false; if ( do_it_now ){ newly_active = derived_active_start == -1; derived_active_start = now; } List skipped_targets = null; if ( do_it ){ previous_metric = metric.longValue(); try{ DHTNetworkPosition[] positions = getNetworkPositions(); for (int i=0;i derived_results = getVivaldiTargets( torrent_hash, pos.getLocation()); int num_to_add = metric.intValue() * derived_results.size() / 100; // System.out.println( download.getName() + ": metric=" + metric + ", adding=" + num_to_add ); for (int j=0;j(); } skipped_targets.add( target ); } } } } } }catch( Throwable e ){ Debug.printStackTrace(e); } } not_put_targets = skipped_targets; } put_targets = result.toArray( new trackerTarget[result.size()]); } } protected DHTNetworkPosition[] getNetworkPositions() { DHTNetworkPosition[] res = current_network_positions; long now = SystemTime.getMonotonousTime(); if ( res == null || now - last_net_pos_time > 30*60*1000 ){ res = current_network_positions = DHTNetworkPositionManager.getLocalPositions(); last_net_pos_time = now; } return( res ); } public static List getVivaldiTargets( byte[] torrent_hash, double[] loc ) { List derived_results = new ArrayList(); String loc_str = ""; for (int j=0;j() { public int compare( Object[] entry1, Object[] entry2 ) { int d1 = ((Integer)entry1[0]).intValue(); int d2 = ((Integer)entry2[0]).intValue(); return( d1 - d2 ); } }); return( derived_results ); } protected static double getDistance( double x1, double y1, double x2, double y2 ) { return(Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))); } protected static class putDetails { private String encoded; private String ip_override; private int tcp_port; private int udp_port; private putDetails( String _encoded, String _ip, int _tcp_port, int _udp_port ) { encoded = _encoded; ip_override = _ip; tcp_port = _tcp_port; udp_port = _udp_port; } protected String getEncoded() { return( encoded ); } protected String getIPOverride() { return( ip_override ); } protected int getTCPPort() { return( tcp_port ); } protected int getUDPPort() { return( udp_port ); } protected boolean sameAs( putDetails other ) { return( getEncoded().equals( other.getEncoded())); } } public static class trackerTarget { private String desc; private byte[] hash; private int type; protected trackerTarget( byte[] _hash, int _type, String _desc ) { hash = _hash; type = _type; desc = _desc; } public int getType() { return( type ); } public byte[] getHash() { return( hash ); } public String getDesc() { if ( type != REG_TYPE_FULL ){ return( " (" + desc + ")" ); } return( "" ); } } public static class TriangleSlicer { int width; private double w; private double w2; private double h; private double tan60; public TriangleSlicer(int width) { this.width = width; this.w = (float) width; this.w2 = w / 2; this.h = Math.cos(Math.PI / 6) * w; this.tan60 = Math.tan(Math.PI / 3); } /** * * @param x * @param y * @return an array of int values being x,y coordinate pairs */ public int[] findVertices(double x,double y) { int yN = (int) Math.floor((y / h)); int xN = (int) Math.floor((x /w2)); double v1x,v2x,v3x,v1y,v2y,v3y; //weither the triangle is like /\ (true) or \/ (false) boolean upTriangle; if((xN+yN) % 2 == 0) { // we have a / separator in the "cell" if( (y-h*yN) > (x-w2*xN) * tan60 ) { //we're in the upper part upTriangle = false; v1x = w2 * (xN - 1); v1y = h * (yN + 1) ; } else { //we're in the lower part upTriangle = true; v1x = w2 * xN; v1y = h * yN; } } else { // We have a \ separator in the "cell" if( (y- h*yN) > (w2 - (x-w2*xN)) * tan60 ) { //we're in the upper part upTriangle = false; v1x = w2 * xN; v1y = h * (yN+1); } else { //we're in the lower part upTriangle = true; v1x = w2 * (xN - 1); v1y = h * yN; } } if(upTriangle) { v2x = v1x + w; v2y = v1y; v3x = v1x + w2; v3y = v1y + h; } else { v2x = v1x + w; v2y = v1y; v3x = v1x + w2; v3y = v1y - h; } int[] result = new int[6]; result[0] = (int) v1x; result[1] = (int) v1y; result[2] = (int) v2x; result[3] = (int) v2y; result[4] = (int) v3x; result[5] = (int) v3y; return result; } } } azureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/0000755000175000017500000000000011310377630021667 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/ExternalSeedReader.java0000644000175000017500000000506411270165270026245 0ustar adrianadrian/* * Created on 15-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.extseed; import java.util.List; import org.gudy.azureus2.plugins.peers.Peer; import org.gudy.azureus2.plugins.peers.PeerManager; import org.gudy.azureus2.plugins.peers.PeerReadRequest; import org.gudy.azureus2.plugins.torrent.Torrent; public interface ExternalSeedReader { public Torrent getTorrent(); public String getName(); public String getStatus(); // transient peers are moved from the download on failure public boolean isTransient(); public boolean isPermanentlyUnavailable(); public String getIP(); public int getPort(); public boolean isActive(); public boolean sameAs( ExternalSeedReader other ); public boolean checkActivation( PeerManager peer_manager, Peer peer ); public void addRequests( List requests ); public void cancelRequest( PeerReadRequest request ); public int getMaximumNumberOfRequests(); public void calculatePriorityOffsets( PeerManager peer_manager, int[] base_priorities ); public int[] getPriorityOffsets(); public void cancelAllRequests(); public int getRequestCount(); public List getExpiredRequests(); public List getRequests(); public int readBytes( int max ); public int getPercentDoneOfCurrentIncomingRequest(); public byte[] read( int piece_number, int offset, int length, int timeout ) throws ExternalSeedException; public void deactivate( String reason ); public void addListener( ExternalSeedReaderListener l ); public void removeListener( ExternalSeedReaderListener l ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/impl/0000755000175000017500000000000011310377630022630 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/impl/getright/0000755000175000017500000000000011310377630024445 5ustar adrianadrian././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderFactoryGetRight.javaazureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderFactoryGetRight.0000644000175000017500000001310711277161106033145 0ustar adrianadrian/* * Created on 15-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.extseed.impl.getright; import java.io.File; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.torrent.Torrent; import com.aelitis.azureus.plugins.extseed.ExternalSeedPlugin; import com.aelitis.azureus.plugins.extseed.ExternalSeedReader; import com.aelitis.azureus.plugins.extseed.ExternalSeedReaderFactory; public class ExternalSeedReaderFactoryGetRight implements ExternalSeedReaderFactory { public ExternalSeedReaderFactoryGetRight() { } public ExternalSeedReader[] getSeedReaders( ExternalSeedPlugin plugin, Download download ) { Torrent torrent = download.getTorrent(); try{ Map config = new HashMap(); Object obj = torrent.getAdditionalProperty( "url-list" ); if ( obj != null ){ config.put( "url-list", obj ); } obj = torrent.getAdditionalProperty( "url-list-params" ); if ( obj != null ){ config.put( "url-list-params", obj ); } obj = torrent.getAdditionalProperty( "url-list-params2" ); if ( obj != null ){ config.put( "url-list-params2", obj ); } return( getSeedReaders( plugin, download, config )); }catch( Throwable e ){ e.printStackTrace(); } return( new ExternalSeedReader[0] ); } public ExternalSeedReader[] getSeedReaders( ExternalSeedPlugin plugin, Download download, Map config ) { try{ Object obj = config.get( "url-list" ); /* resolve url-list according to specification * (http://www.getright.com/seedtorrent.html) */ if ( obj instanceof byte[] ){ List l = new ArrayList(); l.add(obj); obj = l; } if ( obj instanceof List ){ List urls = (List)obj; List readers = new ArrayList(); Object _global_params = config.get( "url-list-params" ); Object _specific_params = config.get( "url-list-params2" ); Map global_params = _global_params instanceof Map?(Map)_global_params:new HashMap(); List specific_params = _specific_params instanceof List?(List)_specific_params:new ArrayList(); for (int i=0;i= 0 ){ int retry_secs = http_downloader.getLast503RetrySecs(); setReconnectDelay( retry_secs * 1000, true ); throw( new ExternalSeedException( "Server temporarily unavailable, retrying in " + retry_secs + " seconds" )); }else{ throw(ese); } } }else{ long request_end = request_start + request_length; // System.out.println( "Req: start=" + request_start + ", len=" + request_length ); final byte[][] overlap_buffer = { null }; final int[] overlap_buffer_position = { 0 }; // we've got to multiplex the (possible) multiple request buffers onto (possible) multi files for (int i=0;i= request_end ){ break; } long sub_request_start = Math.max( request_start, this_start ); long sub_request_end = Math.min( request_end, this_end ); final int sub_len = (int)( sub_request_end - sub_request_start ); if ( sub_len == 0 ){ continue; } ExternalSeedHTTPDownloader http_downloader = http_downloaders[i]; // System.out.println( " sub_req: start=" + sub_request_start + ", len=" + sub_len + ",url=" + http_downloader.getURL()); ExternalSeedHTTPDownloaderListener sub_request = new ExternalSeedHTTPDownloaderListener() { private int bytes_read; private byte[] current_buffer = overlap_buffer[0]; private int current_buffer_position = overlap_buffer_position[0]; private int current_buffer_length = current_buffer==null?-1:Math.min( current_buffer.length, current_buffer_position + sub_len ); public byte[] getBuffer() throws ExternalSeedException { if ( current_buffer == null ){ current_buffer = listener.getBuffer(); current_buffer_position = 0; current_buffer_length = Math.min( current_buffer.length, sub_len - bytes_read ); } return( current_buffer ); } public void setBufferPosition( int position ) { current_buffer_position = position; listener.setBufferPosition( position ); } public int getBufferPosition() { return( current_buffer_position ); } public int getBufferLength() { return( current_buffer_length ); } public int getPermittedBytes() throws ExternalSeedException { return( listener.getPermittedBytes()); } public int getPermittedTime() { return( listener.getPermittedTime()); } public void reportBytesRead( int num ) { bytes_read += num; listener.reportBytesRead( num ); } public boolean isCancelled() { return( listener.isCancelled()); } public void done() { // the current buffer is full up to the declared length int rem = current_buffer.length - current_buffer_length; if ( bytes_read == sub_len ){ // this request is complete. save any partial buffer for // next request if ( rem == 0 ){ overlap_buffer[0] = null; overlap_buffer_position[0] = 0; }else{ overlap_buffer[0] = current_buffer; overlap_buffer_position[0] = current_buffer_length; } } // prepare for next buffer if needed current_buffer = null; if ( rem == 0 ){ listener.done(); } } }; try{ http_downloader.downloadRange( sub_request_start - this_start, sub_len, sub_request, isTransient()); }catch( ExternalSeedException ese ){ if ( http_downloader.getLastResponse() == 503 && http_downloader.getLast503RetrySecs() >= 0 ){ int retry_secs = http_downloader.getLast503RetrySecs(); setReconnectDelay( retry_secs * 1000, true ); throw( new ExternalSeedException( "Server temporarily unavailable, retrying in " + retry_secs + " seconds" )); }else{ throw(ese); } } } } } } azureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderImpl.java0000644000175000017500000007134511300412102030014 0ustar adrianadrian/* * Created on 15-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.extseed.impl; import java.util.*; import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.HostNameToIPResolver; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.clientid.ClientIDGenerator; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.peers.Peer; import org.gudy.azureus2.plugins.peers.PeerManager; import org.gudy.azureus2.plugins.peers.PeerManagerEvent; import org.gudy.azureus2.plugins.peers.PeerManagerListener2; import org.gudy.azureus2.plugins.peers.PeerReadRequest; import org.gudy.azureus2.plugins.peers.PeerStats; import org.gudy.azureus2.plugins.peers.Piece; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.utils.Monitor; import org.gudy.azureus2.plugins.utils.PooledByteBuffer; import org.gudy.azureus2.plugins.utils.Semaphore; import com.aelitis.azureus.core.util.CopyOnWriteSet; import com.aelitis.azureus.plugins.extseed.ExternalSeedException; import com.aelitis.azureus.plugins.extseed.ExternalSeedPeer; import com.aelitis.azureus.plugins.extseed.ExternalSeedPlugin; import com.aelitis.azureus.plugins.extseed.ExternalSeedReader; import com.aelitis.azureus.plugins.extseed.ExternalSeedReaderListener; import com.aelitis.azureus.plugins.extseed.util.ExternalSeedHTTPDownloaderListener; public abstract class ExternalSeedReaderImpl implements ExternalSeedReader, PeerManagerListener2 { public static final int RECONNECT_DEFAULT = 30*1000; public static final int INITIAL_DELAY = 30*1000; public static final int STALLED_DOWNLOAD_SPEED = 20*1024; public static final int STALLED_PEER_SPEED = 5*1024; public static final int TOP_PIECE_PRIORITY = 100*1000; private ExternalSeedPlugin plugin; private Torrent torrent; private String host; private String ip_use_accessor; private String status; private boolean active; private boolean permanent_fail; private long last_failed_read; private int consec_failures; private String user_agent; private long peer_manager_change_time; private volatile PeerManager current_manager; private List requests = new LinkedList(); private List dangling_requests; private Thread request_thread; private Semaphore request_sem; private Monitor requests_mon; private ExternalSeedReaderRequest active_read_request; private int[] priority_offsets; private boolean fast_activate; private int min_availability; private int min_download_speed; private int max_peer_speed; private long valid_until; private boolean transient_seed; private int reconnect_delay = RECONNECT_DEFAULT; private volatile ExternalSeedReaderRequest current_request; private List listeners = new ArrayList(); private AESemaphore rate_sem = new AESemaphore( "ExternalSeedReaderRequest" ); private int rate_bytes_read; private int rate_bytes_permitted; private volatile CopyOnWriteSet bad_pieces = new CopyOnWriteSet(); protected ExternalSeedReaderImpl( ExternalSeedPlugin _plugin, Torrent _torrent, String _host, Map _params ) { plugin = _plugin; torrent = _torrent; host = _host; fast_activate = getBooleanParam( _params, "fast_start", false ); min_availability = getIntParam( _params, "min_avail", 1 ); // default is avail based min_download_speed = getIntParam( _params, "min_speed", 0 ); max_peer_speed = getIntParam( _params, "max_speed", 0 ); valid_until = getIntParam( _params, "valid_ms", 0 ); if ( valid_until > 0 ){ valid_until += getSystemTime(); } transient_seed = getBooleanParam( _params, "transient", false ); requests_mon = plugin.getPluginInterface().getUtilities().getMonitor(); request_sem = plugin.getPluginInterface().getUtilities().getSemaphore(); PluginInterface pi = plugin.getPluginInterface(); user_agent = pi.getAzureusName(); try{ Properties props = new Properties(); pi.getClientIDManager().getGenerator().generateHTTPProperties( props ); String ua = props.getProperty( ClientIDGenerator.PR_USER_AGENT ); if ( ua != null ){ user_agent = ua; } }catch( Throwable e ){ } setActive( null, false ); } public String getIP() { synchronized( host ){ if ( ip_use_accessor == null ){ try{ ip_use_accessor = HostNameToIPResolver.syncResolve( host ).getHostAddress(); }catch( Throwable e ){ ip_use_accessor = host; Debug.out( e ); } } return( ip_use_accessor ); } } public Torrent getTorrent() { return( torrent ); } public String getStatus() { return( status ); } public boolean isTransient() { return( transient_seed ); } protected void log( String str ) { plugin.log( str ); } protected String getUserAgent() { return( user_agent ); } protected long getSystemTime() { return( plugin.getPluginInterface().getUtilities().getCurrentSystemTime()); } protected int getFailureCount() { return( consec_failures ); } protected long getLastFailTime() { return( last_failed_read ); } public boolean isPermanentlyUnavailable() { return( permanent_fail ); } protected void setReconnectDelay( int delay, boolean reset_failures ) { reconnect_delay = delay; if ( reset_failures ){ consec_failures = 0; } } public void eventOccurred( PeerManagerEvent event ) { if ( event.getType() == PeerManagerEvent.ET_PEER_SENT_BAD_DATA ){ if ( event.getPeer().getIp().equals( getIP())){ if ( bad_pieces.size() > 128 ){ return; } bad_pieces.add(new MutableInteger((Integer)event.getData())); } } } protected boolean readyToActivate( PeerManager peer_manager, Peer peer, long time_since_start ) { boolean early_days = time_since_start < INITIAL_DELAY; try{ // first respect failure count int fail_count = getFailureCount(); if ( fail_count > 0 ){ int delay = reconnect_delay; for (int i=1;i 30*60*1000 ){ break; } } long now = getSystemTime(); long last_fail = getLastFailTime(); if ( last_fail < now && now - last_fail < delay ){ return( false ); } } // next obvious things like validity and the fact that we're complete if ( valid_until > 0 && getSystemTime() > valid_until ){ return( false ); } if ( peer_manager.getDownload().getState() != Download.ST_DOWNLOADING ){ return( false ); } // check dnd completeness too if ( peer_manager.getDownload().isComplete()){ return( false ); } // now the more interesting stuff if ( transient_seed ){ // kick any existing peers that are running too slowly if the download appears // to be stalled Peer[] existing_peers = peer_manager.getPeers( getIP()); int existing_peer_count = existing_peers.length; int global_limit = TransferSpeedValidator.getGlobalDownloadRateLimitBytesPerSecond(); if ( global_limit > 0 ){ // if we have a global limit in force and we are near it then no point in // activating int current_down = plugin.getGlobalDownloadRateBytesPerSec(); if ( global_limit - current_down < 5*1024 ){ return( false ); } } int download_limit = peer_manager.getDownloadRateLimitBytesPerSecond(); if ( global_limit > 0 && global_limit < download_limit ){ download_limit = global_limit; } if ( ( download_limit == 0 || download_limit > STALLED_DOWNLOAD_SPEED + 5*1024 ) && peer_manager.getStats().getDownloadAverage() < STALLED_DOWNLOAD_SPEED ){ for (int i=0;i INITIAL_DELAY ){ if ( stats.getDownloadAverage() < STALLED_PEER_SPEED ){ existing_peer.close( "Replacing slow peer with web-seed", false, false ); existing_peer_count--; } } } } if ( existing_peer_count == 0 ){ // check to see if we have pending connections to the same address if ( peer_manager.getPendingPeers( getIP()).length == 0 ){ log( getName() + ": activating as transient seed and nothing blocking it" ); return( true ); } } } // availability and speed based stuff needs a little time before being applied if ( fast_activate || !early_days ){ if ( min_availability > 0 ){ float availability = peer_manager.getDownload().getStats().getAvailability(); if ( availability < min_availability){ log( getName() + ": activating as availability is poor" ); return( true ); } } if ( min_download_speed > 0 ){ if ( peer_manager.getStats().getDownloadAverage() < min_download_speed ){ log( getName() + ": activating as speed is slow" ); return( true ); } } } }catch( Throwable e ){ Debug.printStackTrace(e); } return( false ); } protected boolean readyToDeactivate( PeerManager peer_manager, Peer peer ) { try{ // obvious stuff first if ( valid_until > 0 && getSystemTime() > valid_until ){ return( true ); } if ( peer_manager.getDownload().getState() == Download.ST_SEEDING ){ return( true ); } // more interesting stuff if ( transient_seed ){ return( false ); } boolean deactivate = false; String reason = ""; if ( min_availability > 0 ){ float availability = peer_manager.getDownload().getStats().getAvailability(); if ( availability >= min_availability + 1 ){ reason = "availability is good"; deactivate = true; } } if ( min_download_speed > 0 ){ long my_speed = peer.getStats().getDownloadAverage(); long overall_speed = peer_manager.getStats().getDownloadAverage(); if ( overall_speed - my_speed > 2 * min_download_speed ){ reason += (reason.length()==0?"":", ") + "speed is good"; deactivate = true; }else{ deactivate = false; } } if ( deactivate ){ log( getName() + ": deactivating as " + reason ); return( true ); } }catch( Throwable e ){ Debug.printStackTrace(e); } return( false ); } public boolean checkActivation( PeerManager peer_manager, Peer peer ) { long now = getSystemTime(); if ( peer_manager == current_manager ){ if ( peer_manager_change_time > now ){ peer_manager_change_time = now; } long time_since_started = now - peer_manager_change_time; if ( peer_manager != null ){ if ( active ){ if ( now - peer_manager_change_time > INITIAL_DELAY && readyToDeactivate( peer_manager, peer )){ setActive( peer_manager, false ); }else{ if ( max_peer_speed > 0 ){ PeerStats ps = peer.getStats(); if ( ps != null && ps.getDownloadRateLimit() != max_peer_speed ){ ps.setDownloadRateLimit( max_peer_speed ); } } } }else{ if ( !isPermanentlyUnavailable()){ if ( readyToActivate( peer_manager, peer, time_since_started )){ if ( max_peer_speed > 0 ){ PeerStats ps = peer.getStats(); if ( ps != null ){ ps.setDownloadRateLimit( max_peer_speed ); } } setActive( peer_manager, true ); } } } } }else{ // if the peer manager's changed then we always go inactive for a period to wait for // download status to stabilise a bit peer_manager_change_time = now; PeerManager existing_manager = current_manager; if ( current_manager != null ){ current_manager.removeListener( this ); } current_manager = peer_manager; if ( current_manager != null ){ current_manager.addListener( this ); } setActive( existing_manager, false ); } return( active ); } public void deactivate( String reason ) { plugin.log( getName() + ": deactivating (" + reason + ")" ); checkActivation( null, null ); } protected void setActive( PeerManager _peer_manager, boolean _active ) { try{ requests_mon.enter(); active = _active; status = active?"Active":"Idle"; setActiveSupport( _peer_manager, _active ); }finally{ requests_mon.exit(); } } protected void setActiveSupport( PeerManager _peer_manager, boolean _active ) { // overridden if needed } public boolean isActive() { return( active ); } protected void processRequests() { try{ requests_mon.enter(); if ( request_thread != null ){ return; } request_thread = Thread.currentThread(); }finally{ requests_mon.exit(); } while( true ){ try{ if ( !request_sem.reserve(30000)){ try{ requests_mon.enter(); if ( requests.size() == 0 ){ dangling_requests = null; request_thread = null; break; } }finally{ requests_mon.exit(); } }else{ List selected_requests = new ArrayList(); PeerReadRequest cancelled_request = null; try{ requests_mon.enter(); // get an advisory set to process together int count = selectRequests( requests ); if ( count <= 0 || count > requests.size()){ Debug.out( "invalid count" ); count = 1; } for (int i=0;i 0 ){ // we've only got the sem for the first request, catch up for subsequent request_sem.reserve(); } } } dangling_requests = new ArrayList( selected_requests ); }finally{ requests_mon.exit(); } if ( cancelled_request != null ){ informCancelled( cancelled_request ); }else{ processRequests( selected_requests ); } } }catch( Throwable e ){ e.printStackTrace(); } } } /** * Rate handling */ public int readBytes( int max ) { // permission to read a bunch of bytes // we're out of step here due to multiple threads so we have to report what // has already happened and prepare for what will int res = 0; synchronized( rate_sem ){ if ( rate_bytes_read > 0 ){ res = rate_bytes_read; if ( res > max ){ res = max; } rate_bytes_read -= res; } int rem = max - res; if ( rem > rate_bytes_permitted ){ if ( rate_bytes_permitted == 0 ){ rate_sem.release(); } rate_bytes_permitted = rem; } } return( res ); } public int getPermittedBytes() throws ExternalSeedException { synchronized( rate_sem ){ if ( rate_bytes_permitted > 0 ){ return( rate_bytes_permitted ); } } if ( !rate_sem.reserve( 1000 )){ return( 1 ); // one byte a sec to check for connection liveness } return( rate_bytes_permitted ); } public void reportBytesRead( int num ) { synchronized( rate_sem ){ rate_bytes_read += num; rate_bytes_permitted -= num; if ( rate_bytes_permitted < 0 ){ rate_bytes_permitted = 0; } } } public int getPercentDoneOfCurrentIncomingRequest() { ExternalSeedReaderRequest cr = current_request; if ( cr == null ){ return( 0 ); } return( cr.getPercentDoneOfCurrentIncomingRequest()); } public int getMaximumNumberOfRequests() { if ( getRequestCount() == 0 ){ return((int)(( getPieceGroupSize() * torrent.getPieceSize() ) / PeerReadRequest.NORMAL_REQUEST_SIZE )); }else{ return( 0 ); } } public void calculatePriorityOffsets( PeerManager peer_manager, int[] base_priorities ) { try{ Piece[] pieces = peer_manager.getPieces(); int piece_group_size = getPieceGroupSize(); int[] contiguous_best_pieces = new int[piece_group_size]; int[] contiguous_highest_pri = new int[piece_group_size]; Arrays.fill( contiguous_highest_pri, -1 ); int contiguous = 0; int contiguous_best_pri = -1; int max_contiguous = 0; int max_free_reqs = 0; int max_free_reqs_piece = -1; MutableInteger mi = new MutableInteger(0); for (int i=0;i contiguous_best_pri ){ contiguous_best_pri = base_pri; } for (int j=0;j contiguous_highest_pri[j] ){ contiguous_highest_pri[j] = contiguous_best_pri; contiguous_best_pieces[j] = i - j; } if ( j+1 > max_contiguous ){ max_contiguous = j+1; } } }else{ contiguous = 0; contiguous_best_pri = -1; if ( max_contiguous == 0 ){ int free_reqs = piece.getAllocatableRequestCount(); if ( free_reqs > max_free_reqs ){ max_free_reqs = free_reqs; max_free_reqs_piece = i; } } } } if ( max_contiguous == 0 ){ if ( max_free_reqs_piece >= 0 ){ priority_offsets = new int[ (int)getTorrent().getPieceCount()]; priority_offsets[max_free_reqs_piece] = TOP_PIECE_PRIORITY; }else{ priority_offsets = null; } }else{ priority_offsets = new int[ (int)getTorrent().getPieceCount()]; int start_piece = contiguous_best_pieces[max_contiguous-1]; for (int i=start_piece;i requests ) { long next_start = -1; int last_piece_number = -1; for (int i=0;i requests ) { boolean ok = false; ExternalSeedReaderRequest request = new ExternalSeedReaderRequest( this, requests ); active_read_request = request; try{ current_request = request; readData( request ); ok = true; }catch( ExternalSeedException e ){ if ( e.isPermanentFailure()){ permanent_fail = true; } status = "Failed: " + Debug.getNestedExceptionMessage(e); request.failed(); }catch( Throwable e ){ status = "Failed: " + Debug.getNestedExceptionMessage(e); request.failed(); }finally{ active_read_request = null; if ( ok ){ last_failed_read = 0; consec_failures = 0; }else{ last_failed_read = getSystemTime(); consec_failures++; } } } public void addRequests( List new_requests ) { try{ requests_mon.enter(); if ( !active ){ Debug.out( "request added when not active!!!!" ); } for (int i=0;i getExpiredRequests() { List res = null; try{ requests_mon.enter(); for (int i=0;i(); } res.add( request ); } } }finally{ requests_mon.exit(); } return( res ); } public List getRequests() { List res = null; try{ requests_mon.enter(); res = new ArrayList( requests ); }finally{ requests_mon.exit(); } return( res ); } protected void informComplete( PeerReadRequest request, byte[] buffer ) { PooledByteBuffer pool_buffer = plugin.getPluginInterface().getUtilities().allocatePooledByteBuffer( buffer ); for (int i=0;i= 0 ){ int retry_secs = http_downloader.getLast503RetrySecs(); setReconnectDelay( retry_secs * 1000, true ); throw( new ExternalSeedException( "Server temporarily unavailable, retrying in " + retry_secs + " seconds" )); }else{ throw( ese ); } }catch( MalformedURLException e ){ throw( new ExternalSeedException( "URL encode fails", e )); } } } azureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderRequest.java0000644000175000017500000001026611270165270030557 0ustar adrianadrian/* * Created on 16 May 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.extseed.impl; import java.util.List; import org.gudy.azureus2.plugins.peers.PeerReadRequest; import com.aelitis.azureus.plugins.extseed.ExternalSeedException; import com.aelitis.azureus.plugins.extseed.util.ExternalSeedHTTPDownloaderListener; public class ExternalSeedReaderRequest implements ExternalSeedHTTPDownloaderListener { private ExternalSeedReaderImpl reader; private List requests; private int start_piece_number; private int start_piece_offset; private int length; private int current_request_index = 0; private PeerReadRequest current_request; private byte[] current_buffer; private int current_position; protected ExternalSeedReaderRequest( ExternalSeedReaderImpl _reader, List _requests ) { reader = _reader; requests = _requests; for (int i=0;i= requests.size()){ throw( new ExternalSeedException( "Insufficient buffers to satisfy request" )); } current_request = (PeerReadRequest)requests.get(current_request_index++); current_buffer = new byte[ current_request.getLength()]; current_position = 0; return( current_buffer ); } public boolean isCancelled() { for (int i=0;i requests = new ArrayList(); private RandomAccessFile raf = null; private File scratch_file = null; protected Downloader( ExternalSeedHTTPDownloaderListener _listener, boolean _con_fail_is_perm_fail ) { listener = _listener; con_fail_is_perm_fail = _con_fail_is_perm_fail; new AEThread2( "ES:downloader", true ) { public void run() { download(); } }.start(); } protected void download() { boolean connected = false; String outcome = ""; try{ InputStream is = null; try{ SESecurityManager.setThreadPasswordHandler( this ); synchronized( this ){ if ( destroyed ){ return; } scratch_file = AETemporaryFileHandler.createTempFile(); raf = new RandomAccessFile( scratch_file, "rw" ); } // System.out.println( "Connecting to " + url + ": " + Thread.currentThread().getId()); HttpURLConnection connection; int response; connection = (HttpURLConnection)original_url.openConnection(); connection.setRequestProperty( "Connection", "Keep-Alive" ); connection.setRequestProperty( "User-Agent", user_agent ); int time_remaining = listener.getPermittedTime(); if ( time_remaining > 0 ){ Java15Utils.setConnectTimeout( connection, time_remaining ); } connection.connect(); time_remaining = listener.getPermittedTime(); if ( time_remaining < 0 ){ throw( new IOException( "Timeout during connect" )); } Java15Utils.setReadTimeout( connection, time_remaining ); connected = true; response = connection.getResponseCode(); last_response = response; last_response_retry_after_secs = -1; if ( response == 503 ){ // webseed support for temp unavail - read the retry_after long retry_after_date = new Long(connection.getHeaderFieldDate("Retry-After", -1L)).longValue(); if ( retry_after_date <= -1 ){ last_response_retry_after_secs = connection.getHeaderFieldInt("Retry-After", -1); }else{ last_response_retry_after_secs = (int)((retry_after_date - System.currentTimeMillis())/1000); if ( last_response_retry_after_secs < 0 ){ last_response_retry_after_secs = -1; } } } is = connection.getInputStream(); if ( response == HttpURLConnection.HTTP_ACCEPTED || response == HttpURLConnection.HTTP_OK || response == HttpURLConnection.HTTP_PARTIAL ){ byte[] buffer = new byte[64*1024]; int requests_outstanding = 1; // should be one at least while( !destroyed ){ int permitted = listener.getPermittedBytes(); // idle if no reqs if ( requests_outstanding == 0 || permitted < 1 ){ permitted = 1; Thread.sleep( 100 ); } int len = is.read( buffer, 0, Math.min( permitted, buffer.length )); if ( len <= 0 ){ break; } synchronized( this ){ try{ raf.write( buffer, 0, len ); }catch( Throwable e ){ // assume out of space of something permanent, abandon outcome = "Write failed: " + e.getMessage(); ExternalSeedException error = new ExternalSeedException( outcome, e ); error.setPermanentFailure( true ); throw( error ); } } listener.reportBytesRead( len ); requests_outstanding = checkRequests(); } checkRequests(); }else{ outcome = "Connection failed: " + connection.getResponseMessage(); ExternalSeedException error = new ExternalSeedException( outcome ); error.setPermanentFailure( true ); throw( error ); } }catch( IOException e ){ if ( con_fail_is_perm_fail && !connected ){ outcome = "Connection failed: " + e.getMessage(); ExternalSeedException error = new ExternalSeedException( outcome ); error.setPermanentFailure( true ); throw( error ); }else{ outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e ); if ( last_response_retry_after_secs >= 0){ outcome += ", Retry-After: " + last_response_retry_after_secs + " seconds"; } ExternalSeedException excep = new ExternalSeedException( outcome, e ); if ( e instanceof FileNotFoundException ){ excep.setPermanentFailure( true ); } throw( excep ); } }catch( ExternalSeedException e ){ throw( e ); }catch( Throwable e ){ if ( e instanceof ExternalSeedException ){ throw((ExternalSeedException)e); } outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e ); throw( new ExternalSeedException("Connection failed", e )); }finally{ SESecurityManager.unsetThreadPasswordHandler(); // System.out.println( "Done to " + url + ": " + Thread.currentThread().getId() + ", outcome=" + outcome ); if ( is != null ){ try{ is.close(); }catch( Throwable e ){ } } } }catch( ExternalSeedException e ){ if ( !connected && con_fail_is_perm_fail ){ e.setPermanentFailure( true ); } destroy( e ); } // on successful completion we kill the read thread but leave things 'running' so we continue to service // requests. We will be de-activated when no longer required } protected Request addRequest( long offset, int length, ExternalSeedHTTPDownloaderListener listener ) throws ExternalSeedException { Request request; synchronized( this ){ if ( destroyed ){ throw( new ExternalSeedException( "downloader destroyed" )); } request = new Request( offset, length, listener ); requests.add( request ); } checkRequests(); return( request ); } protected int checkRequests() { try{ synchronized( this ){ if ( raf == null ){ // not yet initialised return( requests.size()); } long pos = raf.getFilePointer(); Iterator it = requests.iterator(); while( it.hasNext()){ Request request = it.next(); long end = request.getOffset() + request.getLength(); if ( pos >= end ){ ExternalSeedHTTPDownloaderListener listener = request.getListener(); try{ raf.seek( request.getOffset()); int total = 0; while( total < request.getLength()){ byte[] buffer = listener.getBuffer(); int buffer_len = listener.getBufferLength(); raf.read( buffer, 0, buffer_len ); total += buffer_len; listener.done(); } }finally{ raf.seek( pos ); } request.complete(); it.remove(); } } return( requests.size()); } }catch( Throwable e ){ Debug.out( e ); destroy( new ExternalSeedException( "read failed", e )); return( 0 ); } } protected void destroy( ExternalSeedException error ) { synchronized( this ){ if ( destroyed ){ return; } destroyed = true; if ( raf != null ){ try{ raf.close(); }catch( Throwable e ){ } } if ( scratch_file != null ){ scratch_file.delete(); } for ( Request r: requests ){ r.destroy( error ); } requests.clear(); } ExternalSeedHTTPDownloaderLinear.this.destoyed( this ); } public PasswordAuthentication getAuthentication( String realm, URL tracker ) { return( null ); } public void setAuthenticationOutcome( String realm, URL tracker, boolean success ) { } public void clearPasswords() { } } protected class Request { private long offset; private int length; private ExternalSeedHTTPDownloaderListener listener; private AESemaphore sem = new AESemaphore( "ES:wait" ); private volatile ExternalSeedException exception; protected Request( long _offset, int _length, ExternalSeedHTTPDownloaderListener _listener ) { offset = _offset; length = _length; listener = _listener; } protected long getOffset() { return( offset ); } protected int getLength() { return( length ); } protected ExternalSeedHTTPDownloaderListener getListener() { return( listener ); } protected void complete() { sem.release(); } protected void destroy( ExternalSeedException e ) { exception = e; sem.release(); } public boolean waitFor( int timeout ) throws ExternalSeedException { if ( !sem.reserve( timeout )){ return( false ); } if ( exception != null ){ throw( exception ); } return( true ); } } } azureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloader.java0000644000175000017500000000336311270165270030616 0ustar adrianadrian/* * Created on 16-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.extseed.util; import com.aelitis.azureus.plugins.extseed.ExternalSeedException; public interface ExternalSeedHTTPDownloader { public void download( int length, ExternalSeedHTTPDownloaderListener listener, boolean con_fail_is_perm_fail ) throws ExternalSeedException; public void downloadRange( long offset, int length, ExternalSeedHTTPDownloaderListener listener, boolean con_fail_is_perm_fail ) throws ExternalSeedException; public void downloadSocket( int length, ExternalSeedHTTPDownloaderListener listener, boolean con_fail_is_perm_fail ) throws ExternalSeedException; public int getLastResponse(); public int getLast503RetrySecs(); public void deactivate(); } azureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderRange.java0000644000175000017500000004206611270165270031576 0ustar adrianadrian/* * Created on 16-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.extseed.util; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.PasswordAuthentication; import java.net.Socket; import java.net.URL; import java.util.StringTokenizer; import org.gudy.azureus2.core3.security.SEPasswordListener; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.util.Java15Utils; import com.aelitis.azureus.plugins.extseed.ExternalSeedException; public class ExternalSeedHTTPDownloaderRange implements ExternalSeedHTTPDownloader, SEPasswordListener { public static final String NL = "\r\n"; private URL original_url; private String user_agent; private URL redirected_url; private int consec_redirect_fails; private int last_response; private int last_response_retry_after_secs; public ExternalSeedHTTPDownloaderRange( URL _url, String _user_agent ) { original_url = _url; user_agent = _user_agent; } public URL getURL() { return( original_url ); } public void download( int length, ExternalSeedHTTPDownloaderListener listener, boolean con_fail_is_perm_fail ) throws ExternalSeedException { download( new String[0], new String[0], length, listener, con_fail_is_perm_fail ); } public void downloadRange( long offset, int length, ExternalSeedHTTPDownloaderListener listener, boolean con_fail_is_perm_fail ) throws ExternalSeedException { download( new String[]{ "Range" }, new String[]{ "bytes=" + offset + "-" + (offset+length-1)}, length, listener, con_fail_is_perm_fail ); } public void download( String[] prop_names, String[] prop_values, int length, ExternalSeedHTTPDownloaderListener listener, boolean con_fail_is_perm_fail ) throws ExternalSeedException { boolean connected = false; InputStream is = null; String outcome = ""; try{ SESecurityManager.setThreadPasswordHandler( this ); // System.out.println( "Connecting to " + url + ": " + Thread.currentThread().getId()); HttpURLConnection connection; int response; while( true ){ URL target = redirected_url==null?original_url:redirected_url; connection = (HttpURLConnection)target.openConnection(); connection.setRequestProperty( "Connection", "Keep-Alive" ); connection.setRequestProperty( "User-Agent", user_agent ); for (int i=0;i 0 ){ Java15Utils.setConnectTimeout( connection, time_remaining ); } connection.connect(); time_remaining = listener.getPermittedTime(); if ( time_remaining < 0 ){ throw( new IOException( "Timeout during connect" )); } Java15Utils.setReadTimeout( connection, time_remaining ); connected = true; response = connection.getResponseCode(); if ( response == HttpURLConnection.HTTP_ACCEPTED || response == HttpURLConnection.HTTP_OK || response == HttpURLConnection.HTTP_PARTIAL ){ if ( redirected_url != null ){ consec_redirect_fails = 0; } break; } if ( redirected_url == null ){ break; } // try again with original URL consec_redirect_fails++; redirected_url = null; } URL final_url = connection.getURL(); if ( consec_redirect_fails < 10 && !original_url.toExternalForm().equals( final_url.toExternalForm())){ redirected_url = final_url; } last_response = response; last_response_retry_after_secs = -1; if ( response == 503 ){ // webseed support for temp unavail - read the retry_after long retry_after_date = new Long(connection.getHeaderFieldDate("Retry-After", -1L)).longValue(); if ( retry_after_date <= -1 ){ last_response_retry_after_secs = connection.getHeaderFieldInt("Retry-After", -1); }else{ last_response_retry_after_secs = (int)((retry_after_date - System.currentTimeMillis())/1000); if ( last_response_retry_after_secs < 0 ){ last_response_retry_after_secs = -1; } } } is = connection.getInputStream(); if ( response == HttpURLConnection.HTTP_ACCEPTED || response == HttpURLConnection.HTTP_OK || response == HttpURLConnection.HTTP_PARTIAL ){ int pos = 0; byte[] buffer = null; int buffer_pos = 0; int buffer_len = 0; while( pos < length ){ if ( buffer == null ){ buffer = listener.getBuffer(); buffer_pos = listener.getBufferPosition(); buffer_len = listener.getBufferLength(); } listener.setBufferPosition( buffer_pos ); int to_read = buffer_len - buffer_pos; int permitted = listener.getPermittedBytes(); if ( permitted < to_read ){ to_read = permitted; } int len = is.read( buffer, buffer_pos, to_read ); if ( len < 0 ){ break; } listener.reportBytesRead( len ); pos += len; buffer_pos += len; if ( buffer_pos == buffer_len ){ listener.done(); buffer = null; buffer_pos = 0; } } if ( pos != length ){ String log_str; if ( buffer == null ){ log_str = "No buffer assigned"; }else{ log_str = new String( buffer, 0, length ); if ( log_str.length() > 64 ){ log_str = log_str.substring( 0, 64 ); } } outcome = "Connection failed: data too short - " + length + "/" + pos + " [" + log_str + "]"; throw( new ExternalSeedException( outcome )); } outcome = "read " + pos + " bytes"; // System.out.println( "download length: " + pos ); }else{ outcome = "Connection failed: " + connection.getResponseMessage(); ExternalSeedException error = new ExternalSeedException( outcome ); error.setPermanentFailure( true ); throw( error ); } }catch( IOException e ){ if ( con_fail_is_perm_fail && !connected ){ outcome = "Connection failed: " + e.getMessage(); ExternalSeedException error = new ExternalSeedException( outcome ); error.setPermanentFailure( true ); throw( error ); }else{ outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e ); if ( last_response_retry_after_secs >= 0){ outcome += ", Retry-After: " + last_response_retry_after_secs + " seconds"; } ExternalSeedException excep = new ExternalSeedException( outcome, e ); if ( e instanceof FileNotFoundException ){ excep.setPermanentFailure( true ); } throw( excep ); } }catch( Throwable e ){ if ( e instanceof ExternalSeedException ){ throw((ExternalSeedException)e); } outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e ); throw( new ExternalSeedException("Connection failed", e )); }finally{ SESecurityManager.unsetThreadPasswordHandler(); // System.out.println( "Done to " + url + ": " + Thread.currentThread().getId() + ", outcome=" + outcome ); if ( is != null ){ try{ is.close(); }catch( Throwable e ){ } } } } public void downloadSocket( int length, ExternalSeedHTTPDownloaderListener listener, boolean con_fail_is_perm_fail ) throws ExternalSeedException { downloadSocket( new String[0], new String[0], length, listener, con_fail_is_perm_fail ); } public void downloadSocket( String[] prop_names, String[] prop_values, int length, ExternalSeedHTTPDownloaderListener listener, boolean con_fail_is_perm_fail ) throws ExternalSeedException { Socket socket = null; boolean connected = false; try{ String output_header = "GET " + original_url.getPath() + "?" + original_url.getQuery() + " HTTP/1.1" + NL + "Host: " + original_url.getHost() + (original_url.getPort()==-1?"":( ":" + original_url.getPort())) + NL + "Accept: */*" + NL + "Connection: Close" + NL + // if we want to support keep-alive we'll need to implement a socket cache etc. "User-Agent: " + user_agent + NL; for (int i=0;i 0 ){ socket = new Socket(); socket.connect( new InetSocketAddress( original_url.getHost(), original_url.getPort()==-1?original_url.getDefaultPort():original_url.getPort()), time_remaining ); }else{ socket = new Socket( original_url.getHost(), original_url.getPort()==-1?original_url.getDefaultPort():original_url.getPort()); } connected = true; time_remaining = listener.getPermittedTime(); if ( time_remaining < 0 ){ throw( new IOException( "Timeout during connect" )); }else if ( time_remaining > 0 ){ socket.setSoTimeout( time_remaining ); } OutputStream os = socket.getOutputStream(); os.write( output_header.getBytes( "ISO-8859-1" )); os.flush(); InputStream is = socket.getInputStream(); try{ String input_header = ""; while( true ){ byte[] buffer = new byte[1]; int len = is.read( buffer ); if ( len < 0 ){ throw( new IOException( "input too short reading header" )); } input_header += (char)buffer[0]; if ( input_header.endsWith(NL+NL)){ break; } } // HTTP/1.1 403 Forbidden int line_end = input_header.indexOf(NL); if ( line_end == -1 ){ throw( new IOException( "header too short" )); } String first_line = input_header.substring(0,line_end); StringTokenizer tok = new StringTokenizer(first_line, " " ); tok.nextToken(); int response = Integer.parseInt( tok.nextToken()); last_response = response; last_response_retry_after_secs = -1; String response_str = tok.nextToken(); if ( response == HttpURLConnection.HTTP_ACCEPTED || response == HttpURLConnection.HTTP_OK || response == HttpURLConnection.HTTP_PARTIAL ){ byte[] buffer = null; int buffer_pos = 0; int buffer_len = 0; int pos = 0; while( pos < length ){ if ( buffer == null ){ buffer = listener.getBuffer(); buffer_pos = listener.getBufferPosition(); buffer_len = listener.getBufferLength(); } int to_read = buffer_len - buffer_pos; int permitted = listener.getPermittedBytes(); if ( permitted < to_read ){ to_read = permitted; } int len = is.read( buffer, buffer_pos, to_read ); if ( len < 0 ){ break; } listener.reportBytesRead( len ); pos += len; buffer_pos += len; if ( buffer_pos == buffer_len ){ listener.done(); buffer = null; buffer_pos = 0; } } if ( pos != length ){ String log_str; if ( buffer == null ){ log_str = "No buffer assigned"; }else{ log_str = new String( buffer, 0, buffer_pos>64?64:buffer_pos ); } throw( new ExternalSeedException("Connection failed: data too short - " + length + "/" + pos + " [last=" + log_str + "]" )); } // System.out.println( "download length: " + pos ); }else if ( response == 503 ){ // webseed support for temp unavail - read the data String data_str = ""; while( true ){ byte[] buffer = new byte[1]; int len = is.read( buffer ); if ( len < 0 ){ break; } data_str += (char)buffer[0]; } last_response_retry_after_secs = Integer.parseInt( data_str ); // this gets trapped below and turned into an appropriate ExternalSeedException throw( new IOException( "Server overloaded" )); }else{ ExternalSeedException error = new ExternalSeedException("Connection failed: " + response_str ); error.setPermanentFailure( true ); throw( error ); } }finally{ is.close(); } }catch( IOException e ){ if ( con_fail_is_perm_fail && !connected ){ ExternalSeedException error = new ExternalSeedException("Connection failed: " + e.getMessage()); error.setPermanentFailure( true ); throw( error ); }else{ String outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e ); if ( last_response_retry_after_secs >= 0 ){ outcome += ", Retry-After: " + last_response_retry_after_secs + " seconds"; } throw( new ExternalSeedException( outcome, e )); } }catch( Throwable e ){ if ( e instanceof ExternalSeedException ){ throw((ExternalSeedException)e); } throw( new ExternalSeedException("Connection failed", e )); }finally{ if ( socket != null ){ try{ socket.close(); }catch( Throwable e ){ } } } } public void deactivate() { } public PasswordAuthentication getAuthentication( String realm, URL tracker ) { return( null ); } public void setAuthenticationOutcome( String realm, URL tracker, boolean success ) { } public void clearPasswords() { } public int getLastResponse() { return( last_response ); } public int getLast503RetrySecs() { return( last_response_retry_after_secs ); } public static void main( String[] args ) { try{ String url_str = ""; ExternalSeedHTTPDownloader downloader = new ExternalSeedHTTPDownloaderRange( new URL( url_str ), "Azureus" ); downloader.downloadRange( 0, 1, new ExternalSeedHTTPDownloaderListener() { private int position; public byte[] getBuffer() throws ExternalSeedException { return( new byte[1024] ); } public void setBufferPosition( int _position ) { position = _position; } public int getBufferPosition() { return( position ); } public int getBufferLength() { return( 1024 ); } public int getPermittedBytes() throws ExternalSeedException { return( 1024 ); } public int getPermittedTime() { return( Integer.MAX_VALUE ); } public void reportBytesRead( int num ) { System.out.println( "read " + num ); } public boolean isCancelled() { return false; } public void done() { System.out.println( "done" ); } }, true ); }catch( Throwable e ){ e.printStackTrace(); } } } azureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderListener.java0000644000175000017500000000276111270165270032325 0ustar adrianadrian/* * Created on 17 May 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.extseed.util; import com.aelitis.azureus.plugins.extseed.ExternalSeedException; public interface ExternalSeedHTTPDownloaderListener { public byte[] getBuffer() throws ExternalSeedException; public void setBufferPosition( int position ); public int getBufferPosition(); public int getBufferLength(); public int getPermittedBytes() throws ExternalSeedException; public int getPermittedTime(); public void reportBytesRead( int num ); public boolean isCancelled(); public void done(); } azureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/ExternalSeedException.java0000644000175000017500000000257111012742132026771 0ustar adrianadrian/* * Created on 15-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.extseed; public class ExternalSeedException extends Exception { private boolean permanent = false; public ExternalSeedException( String str ) { super( str ); } public ExternalSeedException( String str, Throwable e ) { super( str, e ); } public void setPermanentFailure( boolean b ) { permanent = b; } public boolean isPermanentFailure() { return( permanent ); } } azureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/ExternalSeedPeer.java0000644000175000017500000003303411142026436025732 0ustar adrianadrian/* * Created on 15-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.extseed; import java.util.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.messaging.Message; import org.gudy.azureus2.plugins.network.Connection; import org.gudy.azureus2.plugins.peers.*; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.utils.*; import com.aelitis.azureus.core.util.CopyOnWriteList; public class ExternalSeedPeer implements Peer, ExternalSeedReaderListener { private ExternalSeedPlugin plugin; private Download download; private PeerManager manager; private PeerStats stats; private Map user_data; private ExternalSeedReader reader; private int state; private byte[] peer_id; private boolean[] available; private boolean availabilityAdded; private long snubbed; private boolean is_optimistic; private Monitor connection_mon; private boolean peer_added; private List request_list = new ArrayList(); private CopyOnWriteList listeners; private Monitor listeners_mon; private boolean doing_allocations; protected ExternalSeedPeer( ExternalSeedPlugin _plugin, Download _download, ExternalSeedReader _reader ) { plugin = _plugin; download = _download; reader = _reader; connection_mon = plugin.getPluginInterface().getUtilities().getMonitor(); Torrent torrent = reader.getTorrent(); available = new boolean[(int)torrent.getPieceCount()]; Arrays.fill( available, true ); peer_id = new byte[20]; new Random().nextBytes( peer_id ); peer_id[0]='E'; peer_id[1]='x'; peer_id[2]='t'; peer_id[3]=' '; listeners = new CopyOnWriteList(); listeners_mon = plugin.getPluginInterface().getUtilities().getMonitor(); _reader.addListener( this ); } protected boolean sameAs( ExternalSeedPeer other ) { return( reader.sameAs( other.reader )); } protected void setManager( PeerManager _manager ) { setState(Peer.CONNECTING); try{ connection_mon.enter(); manager = _manager; if ( manager == null ){ stats = null; }else{ stats = manager.createPeerStats( this ); } checkConnection(); }finally{ connection_mon.exit(); } } public PeerManager getManager() { return( manager ); } protected Download getDownload() { return( download ); } protected ExternalSeedReader getReader() { return( reader ); } protected void setState( int newState ) { state = newState; fireEvent( PeerEvent.ET_STATE_CHANGED, new Integer( newState )); } protected boolean checkConnection() { boolean state_changed = false; try{ connection_mon.enter(); boolean active = reader.checkActivation( manager, this ); if ( manager != null && active != peer_added ){ state_changed = true; boolean peer_was_added = peer_added; peer_added = active; if ( active ){ addPeer(); }else{ if ( peer_was_added ){ removePeer(); } } } }finally{ connection_mon.exit(); } return( state_changed ); } protected void addPeer() { setState(Peer.HANDSHAKING); manager.addPeer( this ); // we can get synchronously disconnected - e.g. IP filter rules if ( peer_added ){ setState(Peer.TRANSFERING); try{ listeners_mon.enter(); if ( availabilityAdded ){ Debug.out( "availabililty already added" ); }else{ availabilityAdded = true; fireEvent( PeerEvent.ET_ADD_AVAILABILITY, getAvailable()); } }finally{ listeners_mon.exit(); } } } protected void removePeer() { setState(Peer.CLOSING); try{ listeners_mon.enter(); if ( availabilityAdded ){ availabilityAdded = false; fireEvent( PeerEvent.ET_REMOVE_AVAILABILITY, getAvailable()); } }finally{ listeners_mon.exit(); } manager.removePeer( this ); setState( Peer.DISCONNECTED ); } public void requestComplete( PeerReadRequest request, PooledByteBuffer data ) { PeerManager man = manager; if ( request.isCancelled() || man == null ){ data.returnToPool(); }else{ try{ man.requestComplete( request, data, this ); // moved to the rate-limiting code for more accurate stats // stats.received( request.getLength()); }catch( Throwable e ){ data.returnToPool(); e.printStackTrace(); } } } public void requestCancelled( PeerReadRequest request ) { PeerManager man = manager; if ( man != null ){ man.requestCancelled( request, this ); } } public void requestFailed( PeerReadRequest request ) { PeerManager man = manager; if ( man != null ){ man.requestCancelled( request, this ); try{ connection_mon.enter(); if ( peer_added ){ plugin.log( reader.getName() + " failed - " + reader.getStatus() + ", permanent = " + reader.isPermanentlyUnavailable()); peer_added = false; removePeer(); } }finally{ connection_mon.exit(); } if ( reader.isTransient() && reader.isPermanentlyUnavailable()){ plugin.removePeer( this ); } } } public int getState() { return state; } public byte[] getId() { return( peer_id ); } public String getIp() { return( reader.getIP()); } public int getTCPListenPort() { return( 0 ); } public int getUDPListenPort() { return( 0 ); } public int getUDPNonDataListenPort() { return( 0 ); } public int getPort() { return( reader.getPort()); } public final boolean[] getAvailable() { return( available ); } public final boolean isPieceAvailable( int pieceNumber ) { return( true ); } public boolean isTransferAvailable() { return( reader.isActive()); } public boolean isDownloadPossible() { return peer_added &&reader.isActive(); } public boolean isChoked() { return( false ); } public boolean isChoking() { return( false ); } public boolean isInterested() { return( false ); } public boolean isInteresting() { return( true ); } public boolean isSeed() { return( true ); } public boolean isSnubbed() { if ( snubbed != 0 ){ // mindless snubbing control - if we have no outstanding requests then we // drop the snubbed status :) if ( reader.getRequestCount() == 0 ){ snubbed = 0; } } return( snubbed != 0 ); } public long getSnubbedTime() { if ( !isSnubbed()){ return 0; } final long now = plugin.getPluginInterface().getUtilities().getCurrentSystemTime(); if ( now < snubbed ){ snubbed = now - 26; // odds are ... } return now - snubbed; } public void setSnubbed( boolean b) { if (!b){ snubbed = 0; }else if ( snubbed == 0 ){ snubbed = plugin.getPluginInterface().getUtilities().getCurrentSystemTime(); } } public boolean isOptimisticUnchoke() { return( is_optimistic ); } public void setOptimisticUnchoke( boolean _is_optimistic ) { is_optimistic = _is_optimistic; } public PeerStats getStats() { return( stats ); } public boolean isIncoming() { return( false ); } public int getPercentDone() { return( 1000 ); } public int getPercentDoneInThousandNotation() { return( 1000 ); } public String getClient() { return( reader.getName()); } public List getExpiredRequests() { return( reader.getExpiredRequests()); } public List getRequests() { return( reader.getRequests()); } public int getMaximumNumberOfRequests() { return( reader.getMaximumNumberOfRequests()); } public int getNumberOfRequests() { return( reader.getRequestCount() + request_list.size()); } public int[] getPriorityOffsets() { return( reader.getPriorityOffsets()); } public boolean requestAllocationStarts( int[] base_priorities ) { if ( doing_allocations ){ Debug.out( "recursive allocations" ); } doing_allocations = true; if ( request_list.size() != 0 ){ Debug.out( "req list must be empty" ); } PeerManager pm = manager; if ( pm != null ){ reader.calculatePriorityOffsets( pm, base_priorities ); } return( true ); } public void requestAllocationComplete() { reader.addRequests( request_list ); request_list.clear(); doing_allocations = false; } public boolean addRequest( PeerReadRequest request ) { if ( !doing_allocations ){ Debug.out( "request added when not in allocation phase" ); } request_list.add( request ); snubbed = 0; return( true ); } public void cancelRequest( PeerReadRequest request ) { reader.cancelRequest( request ); } public void close( String reason, boolean closedOnError, boolean attemptReconnect ) { boolean peer_was_added; try{ connection_mon.enter(); peer_was_added = peer_added; reader.cancelAllRequests(); reader.deactivate( reason ); peer_added = false; try{ listeners_mon.enter(); if ( availabilityAdded ){ availabilityAdded = false; fireEvent( PeerEvent.ET_REMOVE_AVAILABILITY, getAvailable()); } }finally{ listeners_mon.exit(); } }finally{ connection_mon.exit(); } if ( peer_was_added ){ manager.removePeer( this ); } setState( Peer.DISCONNECTED ); if ( reader.isTransient()){ plugin.removePeer( this ); } } public void addListener( PeerListener listener ) { try{ listeners_mon.enter(); listeners.add(listener); }finally{ listeners_mon.exit(); } } public void removeListener( PeerListener listener ) { try{ listeners_mon.enter(); listeners.remove(listener); }finally{ listeners_mon.exit(); } } public void addListener( PeerListener2 listener ) { try{ listeners_mon.enter(); listeners.add(listener); }finally{ listeners_mon.exit(); } } public void removeListener( PeerListener2 listener ) { try{ listeners_mon.enter(); listeners.remove(listener); }finally{ listeners_mon.exit(); } } protected void fireEvent( final int type, final Object data ) { try{ listeners_mon.enter(); List ref = listeners.getList(); for (int i =0; i 0 ){ stats.received( res ); } return( res ); } public int writeBytes( int max ) { throw( new RuntimeException( "Not supported" )); } public int getPercentDoneOfCurrentIncomingRequest() { return( reader.getPercentDoneOfCurrentIncomingRequest()); } public int getPercentDoneOfCurrentOutgoingRequest() { return( 0 ); } public Map getProperties() { return( new HashMap()); } public String getName() { return( reader.getName()); } public void setUserData( Object key, Object value ) { if ( user_data == null ){ user_data = new HashMap(); } user_data.put( key, value ); } public Object getUserData( Object key ) { if ( user_data == null ){ return( null ); } return( user_data.get( key )); } public byte[] getHandshakeReservedBytes() { return null; } public boolean isPriorityConnection() { return false; } public void setPriorityConnection(boolean is_priority) { } } azureus-4.3.0.6/com/aelitis/azureus/plugins/extseed/ExternalSeedPlugin.java0000644000175000017500000002725611272507260026311 0ustar adrianadrian/* * Created on 15-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.extseed; import java.io.PrintWriter; import java.io.StringWriter; import java.util.*; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.plugins.Plugin; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadManagerListener; import org.gudy.azureus2.plugins.download.DownloadManagerStats; import org.gudy.azureus2.plugins.download.DownloadPeerListener; import org.gudy.azureus2.plugins.logging.LoggerChannel; import org.gudy.azureus2.plugins.logging.LoggerChannelListener; import org.gudy.azureus2.plugins.peers.PeerManager; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.ui.components.UITextField; import org.gudy.azureus2.plugins.ui.model.BasicPluginViewModel; import org.gudy.azureus2.plugins.utils.*; import com.aelitis.azureus.plugins.extseed.impl.getright.ExternalSeedReaderFactoryGetRight; import com.aelitis.azureus.plugins.extseed.impl.webseed.ExternalSeedReaderFactoryWebSeed; public class ExternalSeedPlugin implements Plugin, DownloadManagerListener { private static ExternalSeedReaderFactory[] factories = { new ExternalSeedReaderFactoryGetRight(), new ExternalSeedReaderFactoryWebSeed(), }; private PluginInterface plugin_interface; private DownloadManagerStats dm_stats; private UITextField status_field; private LoggerChannel log; private Random random = new Random(); private Map download_map = new HashMap(); private Monitor download_mon; public static void load( PluginInterface plugin_interface ) { plugin_interface.getPluginProperties().setProperty( "plugin.version", "1.0" ); plugin_interface.getPluginProperties().setProperty( "plugin.name", "External Seed" ); } public void initialize( PluginInterface _plugin_interface ) { plugin_interface = _plugin_interface; dm_stats = plugin_interface.getDownloadManager().getStats(); log = plugin_interface.getLogger().getTimeStampedChannel( "External Seeds" ); final BasicPluginViewModel view_model = plugin_interface.getUIManager().createBasicPluginViewModel( "Plugin.extseed.name" ); view_model.getActivity().setVisible( false ); view_model.getProgress().setVisible( false ); log.addListener( new LoggerChannelListener() { public void messageLogged( int type, String content ) { view_model.getLogArea().appendText( content + "\n" ); } public void messageLogged( String str, Throwable error ) { if ( str.length() > 0 ){ view_model.getLogArea().appendText( str + "\n" ); } StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter( sw ); error.printStackTrace( pw ); pw.flush(); view_model.getLogArea().appendText( sw.toString() + "\n" ); } }); status_field = view_model.getStatus(); setStatus( "Initialising" ); download_mon = plugin_interface.getUtilities().getMonitor(); Utilities utilities = plugin_interface.getUtilities(); final DelayedTask dt = plugin_interface.getUtilities().createDelayedTask(new Runnable() { public void run() { AEThread2 t = new AEThread2( "ExternalSeedInitialise", true ) { public void run() { setStatus( "Running" ); plugin_interface.getDownloadManager().addListener( ExternalSeedPlugin.this); } }; t.setPriority( Thread.MIN_PRIORITY ); t.start(); } }); dt.queue(); UTTimer timer = utilities.createTimer("ExternalPeerScheduler", true); timer.addPeriodicEvent( 5000, new UTTimerEventPerformer() { public void perform( UTTimerEvent event ) { try{ Iterator it = download_map.values().iterator(); while( it.hasNext()){ List peers = randomiseList((List)it.next()); for (int i=0;i 0 ){ boolean add_listener = false; try{ download_mon.enter(); List existing_peers = (List)download_map.get( download ); if ( existing_peers == null ){ add_listener = true; existing_peers = new ArrayList(); download_map.put( download, existing_peers ); } Iterator it = peers.iterator(); while( it.hasNext()){ ExternalSeedPeer peer = (ExternalSeedPeer)it.next(); boolean skip = false; for (int j=0;j) String service_name = service_mapping.getString(); service_mapping.removeMapping( upnp_mapping ); if ( service_mapping.getMappings().size() == 0 ){ try{ connection.deletePortMapping( service_mapping.isTCP(), service_mapping.getPort()); log.log( "Mapping " + service_name + " removed" ); }catch( Throwable e ){ log.log( "Mapping " + service_name + " failed to delete", e ); } service_mappings.remove(service_mapping); }else{ log.log( "Mapping " + service_mapping.getString() + " not removed as interest remains" ); } } } } public serviceMapping[] getMappings() { try{ this_mon.enter(); return( service_mappings.toArray( new serviceMapping[service_mappings.size()])); }finally{ this_mon.exit(); } } public class serviceMapping { private List mappings = new ArrayList(); private boolean tcp; private int port; private String internal_host; private boolean external; // true -> not defined by us private List logged_mappings = new ArrayList(); protected serviceMapping( UPnPWANConnectionPortMapping device_mapping ) { tcp = device_mapping.isTCP(); port = device_mapping.getExternalPort(); internal_host = device_mapping.getInternalHost(); String desc = device_mapping.getDescription(); if ( desc == null || !( desc.equalsIgnoreCase( getOldDescriptionForPort( port )) || desc.equalsIgnoreCase( getDescriptionForPort( tcp, port )))){ external = true; } } protected serviceMapping( UPnPMapping _mapping ) { mappings.add( _mapping ); tcp = _mapping.isTCP(); port = _mapping.getPort(); internal_host = connection.getGenericService().getDevice().getRootDevice().getLocalAddress().getHostAddress(); } public boolean isExternal() { return( external ); } protected List getMappings() { return( mappings ); } protected void addMapping( UPnPMapping _mapping ) { if ( !mappings.contains( _mapping )){ mappings.add( _mapping ); } } protected void removeMapping( UPnPMapping _mapping ) { mappings.remove( _mapping ); } protected boolean getLogged( UPnPMapping mapping ) { return( logged_mappings.contains( mapping )); } protected void setLogged( UPnPMapping mapping ) { if ( !logged_mappings.contains( mapping )){ logged_mappings.add( mapping ); } } public boolean isTCP() { return( tcp ); } public int getPort() { return( port ); } public String getInternalHost() { return( internal_host ); } public String getString() { if ( mappings.size() == 0 ){ return( " (" + (isTCP()?"TCP":"UDP")+"/"+getPort()+")" ); }else{ String str = ""; for (int i=0;i TCP order to hopefully leave the more important one working :) addConfigPort( "upnp.mapping.dataport", false, "UDP.Listen.Port.Enable", "UDP.Listen.Port" ); // this is actually the UDP tracker client mapping, very badly named params... addConfigPort( "upnp.mapping.trackerclientudp", false, "Server Enable UDP", "UDP.NonData.Listen.Port" ); // note that the dht plugin registers its own mapping addConfigPort( "upnp.mapping.dataport", true, "TCP.Listen.Port.Enable", "TCP.Listen.Port" ); addConfigPort( "upnp.mapping.dataport", true, "HTTP.Data.Listen.Port.Enable", "HTTP.Data.Listen.Port" ); // tracker server TCP addConfigPort( "upnp.mapping.tcptrackerport", true, "Tracker Port Enable", "Tracker Port" ); addConfigPortX( "upnp.mapping.tcptrackerport", true, "Tracker Port Enable", "Tracker Port Backups" ); addConfigPort( "upnp.mapping.tcpssltrackerport", true, "Tracker Port SSL Enable", "Tracker Port SSL" ); addConfigPortX( "upnp.mapping.tcpssltrackerport", true, "Tracker Port SSL Enable", "Tracker Port SSL Backups" ); // tracker server UDP addConfigPort( "upnp.mapping.udptrackerport", false, "Tracker Port UDP Enable", "Tracker Port" ); } protected void serviceFound( UPnPWANConnection service ) { boolean save_config = false; if (( service.getCapabilities() & UPnPWANConnection.CAP_UDP_TCP_SAME_PORT ) == 0 ){ // doesn't support UDP and TCP on same port number - patch up // unfortunately some routers remember the stuffed ports and makes them unusable for // either UDP OR TCP until a HARD reset so we need to change both ports... UPnPMapping[] maps = getMappings(); for (int i=0;i mappings = new ArrayList(); private List services = new ArrayList(); private Map root_info_map = new HashMap(); private Map log_no_repeat_map = new HashMap(); protected AEMonitor this_mon = new AEMonitor( "UPnPPlugin" ); public static void load( PluginInterface plugin_interface ) { plugin_interface.getPluginProperties().setProperty( "plugin.version", "1.0" ); plugin_interface.getPluginProperties().setProperty( "plugin.name", "Universal Plug and Play (UPnP)" ); } public void initialize( PluginInterface _plugin_interface ) { plugin_interface = _plugin_interface; log = plugin_interface.getLogger().getTimeStampedChannel("UPnP"); UIManager ui_manager = plugin_interface.getUIManager(); final BasicPluginViewModel model = ui_manager.createBasicPluginViewModel( "UPnP"); model.setConfigSectionID(UPNP_PLUGIN_CONFIGSECTION_ID); BasicPluginConfigModel upnp_config = ui_manager.createBasicPluginConfigModel(ConfigSection.SECTION_PLUGINS, UPNP_PLUGIN_CONFIGSECTION_ID ); // NATPMP BasicPluginConfigModel natpmp_config = ui_manager.createBasicPluginConfigModel( UPNP_PLUGIN_CONFIGSECTION_ID, NATPMP_PLUGIN_CONFIGSECTION_ID ); natpmp_config.addLabelParameter2( "natpmp.info" ); ActionParameter natpmp_wiki = natpmp_config.addActionParameter2( "Utils.link.visit", "MainWindow.about.internet.wiki" ); natpmp_wiki.setStyle( ActionParameter.STYLE_LINK ); natpmp_wiki.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { try{ plugin_interface.getUIManager().openURL( new URL( "http://www.azureuswiki.com/index.php/NATPMP" )); }catch( Throwable e ){ e.printStackTrace(); } } }); natpmp_enable_param = natpmp_config.addBooleanParameter2( "natpmp.enable", "natpmp.enable", false ); nat_pmp_router = natpmp_config.addStringParameter2( "natpmp.routeraddress", "natpmp.routeraddress", "" ); natpmp_enable_param.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { setNATPMPEnableState(); } }); natpmp_enable_param.addEnabledOnSelection( nat_pmp_router ); // UPNP upnp_config.addLabelParameter2( "upnp.info" ); upnp_config.addHyperlinkParameter2("upnp.wiki_link", "http://www.azureuswiki.com/index.php/UPnP"); upnp_enable_param = upnp_config.addBooleanParameter2( "upnp.enable", "upnp.enable", true ); grab_ports_param = upnp_config.addBooleanParameter2( "upnp.grabports", "upnp.grabports", false ); release_mappings_param = upnp_config.addBooleanParameter2( "upnp.releasemappings", "upnp.releasemappings", true ); ActionParameter refresh_param = upnp_config.addActionParameter2( "upnp.refresh.label", "upnp.refresh.button" ); refresh_param.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { UPnPPlugin.this.refreshMappings(); } }); // Auto-refresh mappings every minute when enabled. final BooleanParameter auto_refresh_on_bad_nat_param = upnp_config.addBooleanParameter2( "upnp.refresh_on_bad_nat", "upnp.refresh_mappings_on_bad_nat", false); plugin_interface.getUtilities().createTimer("upnp mapping auto-refresh", true).addPeriodicEvent(1*60*1000, new UTTimerEventPerformer() { private long last_bad_nat = 0; public void perform(UTTimerEvent event) { if (upnp == null) {return;} if (!auto_refresh_on_bad_nat_param.getValue()) {return;} if (!upnp_enable_param.getValue()) {return;} int status = plugin_interface.getConnectionManager().getNATStatus(); if (status == ConnectionManager.NAT_BAD) { // Only try to refresh the mappings if this is the first bad NAT // message we've been given in the last 15 minutes - we don't want // to endlessly retry performing the mappings long now = plugin_interface.getUtilities().getCurrentSystemTime(); if (last_bad_nat + (15*60*1000) < now ) { last_bad_nat = now; log.log(LoggerChannel.LT_WARNING, "NAT status is firewalled - trying to refresh UPnP mappings"); refreshMappings(true); } } } }); upnp_config.addLabelParameter2( "blank.resource" ); alert_success_param = upnp_config.addBooleanParameter2( "upnp.alertsuccess", "upnp.alertsuccess", false ); alert_other_port_param = upnp_config.addBooleanParameter2( "upnp.alertothermappings", "upnp.alertothermappings", true ); alert_device_probs_param = upnp_config.addBooleanParameter2( "upnp.alertdeviceproblems", "upnp.alertdeviceproblems", true ); selected_interfaces_param = upnp_config.addStringParameter2( "upnp.selectedinterfaces", "upnp.selectedinterfaces", "" ); selected_addresses_param = upnp_config.addStringParameter2( "upnp.selectedaddresses", "upnp.selectedaddresses", "" ); ignore_bad_devices = upnp_config.addBooleanParameter2( "upnp.ignorebaddevices", "upnp.ignorebaddevices", true ); ignored_devices_list = upnp_config.addLabelParameter2( "upnp.ignorebaddevices.info" ); ActionParameter reset_param = upnp_config.addActionParameter2( "upnp.ignorebaddevices.reset", "upnp.ignorebaddevices.reset.action" ); reset_param.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { PluginConfig pc = plugin_interface.getPluginconfig(); for (int i=0;i 0 ){ log.log( "Devices currently being ignored: " + param ); } } String text = plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( "upnp.ignorebaddevices.info", new String[]{ param }); ignored_devices_list.setLabelText( text ); }catch( Throwable e ){ Debug.printStackTrace(e); } } protected void ignoreDevice( String USN, URL location ) { // only take note of this if enabled to do so if ( ignore_bad_devices.getValue()){ try{ PluginConfig pc = plugin_interface.getPluginconfig(); Map ignored = pc.getPluginMapParameter( "upnp.device.ignorelist", new HashMap()); Map entry = (Map)ignored.get( USN ); if ( entry == null ){ entry = new HashMap(); entry.put( "Location", location.toString().getBytes()); ignored.put( USN, entry ); pc.setPluginMapParameter( "upnp.device.ignorelist", ignored ); updateIgnoreList(); String text = plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( "upnp.ignorebaddevices.alert", new String[]{ location.toString() }); log.logAlertRepeatable( LoggerChannel.LT_WARNING, text ); } }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected void startUp() { if ( upnp != null ){ // already started up, must have been re-enabled refreshMappings(); return; } final LoggerChannel core_log = plugin_interface.getLogger().getChannel("UPnP Core"); try{ upnp = UPnPFactory.getSingleton( new UPnPAdapter() { Set exception_traces = new HashSet(); public SimpleXMLParserDocument parseXML( String data ) throws SimpleXMLParserDocumentException { return( plugin_interface.getUtilities().getSimpleXMLParserDocumentFactory().create( data )); } public ResourceDownloaderFactory getResourceDownloaderFactory() { return( plugin_interface.getUtilities().getResourceDownloaderFactory()); } public UTTimer createTimer( String name ) { return( plugin_interface.getUtilities().createTimer( name, true )); } public void createThread( String name, Runnable runnable ) { plugin_interface.getUtilities().createThread( name, runnable ); } public Comparator getAlphanumericComparator() { return( plugin_interface.getUtilities().getFormatters().getAlphanumericComparator( true )); } public void trace( String str ) { core_log.log( str ); if (trace_to_log.getValue()) { upnp_log_listener.log(str); } } public void log( Throwable e ) { String nested = Debug.getNestedExceptionMessage(e); if ( !exception_traces.contains( nested )){ exception_traces.add( nested ); if ( exception_traces.size() > 128 ){ exception_traces.clear(); } core_log.log( e ); }else{ core_log.log( nested ); } } public void log( String str ) { log.log( str ); } public String getTraceDir() { return( plugin_interface.getUtilities().getAzureusUserDir()); } }, getSelectedInterfaces()); upnp.addRootDeviceListener( this ); upnp_log_listener = new UPnPLogListener() { public void log( String str ) { log.log( str ); } public void logAlert( String str, boolean error, int type ) { boolean logged = false; if ( alert_device_probs_param.getValue()){ if ( type == UPnPLogListener.TYPE_ALWAYS ){ log.logAlertRepeatable( error?LoggerChannel.LT_ERROR:LoggerChannel.LT_WARNING, str ); logged = true; }else{ boolean do_it = false; if ( type == UPnPLogListener.TYPE_ONCE_EVER ){ byte[] fp = plugin_interface.getUtilities().getSecurityManager().calculateSHA1( str.getBytes()); String key = "upnp.alert.fp." + plugin_interface.getUtilities().getFormatters().encodeBytesToString( fp ); PluginConfig pc = plugin_interface.getPluginconfig(); if ( !pc.getPluginBooleanParameter( key, false )){ pc.setPluginParameter( key, true ); do_it = true; } }else{ do_it = true; } if ( do_it ){ log.logAlert( error?LoggerChannel.LT_ERROR:LoggerChannel.LT_WARNING, str ); logged = true; } } } if ( !logged ){ log.log( str ); } } }; upnp.addLogListener( upnp_log_listener ); mapping_manager.addListener( new UPnPMappingManagerListener() { public void mappingAdded( UPnPMapping mapping ) { addMapping( mapping ); } }); UPnPMapping[] upnp_mappings = mapping_manager.getMappings(); for (int i=0;i 0 ){ String address = location.getHost(); boolean found = false; boolean all_exclude = true; for (int i=0;i 0 ){ try{ this_mon.enter(); root_info_map.put( device.getLocation(), device.getInfo()); Iterator it = root_info_map.values().iterator(); String all_info = ""; List reported_info = new ArrayList(); while( it.hasNext()){ String info = (String)it.next(); if ( info != null && !reported_info.contains( info )){ reported_info.add( info ); all_info += (all_info.length()==0?"":",") + info; } } if ( all_info.length() > 0 ){ plugin_interface.getPluginconfig().setPluginParameter( "plugin.info", all_info ); } }finally{ this_mon.exit(); } } }catch( Throwable e ){ log.log( "Root device processing fails", e ); } } protected boolean checkDeviceStats( UPnPRootDevice root ) { return( checkDeviceStats( root.getUSN(), root.getLocation())); } protected boolean checkDeviceStats( String USN, URL location ) { long discovers = getDeviceStats( USN, STATS_DISCOVER ); long founds = getDeviceStats( USN, STATS_FOUND ); if ( discovers > 3 && founds == 0 ){ // discovered but never found - something went wrong with the device // construction process ignoreDevice( USN, location ); return( false ); }else if ( founds > 0 ){ // found ok before, reset details in case now its screwed setDeviceStats( USN, STATS_DISCOVER, 0 ); setDeviceStats( USN, STATS_FOUND, 0 ); } long map_ok = getDeviceStats( USN, STATS_MAP_OK ); long map_bad = getDeviceStats( USN, STATS_MAP_BAD ); if ( map_bad > 5 && map_ok == 0 ){ ignoreDevice( USN, location ); return( false ); }else if ( map_ok > 0 ){ setDeviceStats( USN, STATS_MAP_OK, 0 ); setDeviceStats( USN, STATS_MAP_BAD, 0 ); } return( true ); } protected long incrementDeviceStats( String USN, String stat_key ) { String key = "upnp.device.stats." + stat_key; PluginConfig pc = plugin_interface.getPluginconfig(); Map counts = pc.getPluginMapParameter( key, new HashMap()); Long count = (Long)counts.get( USN ); if ( count == null ){ count = new Long(1); }else{ count = new Long( count.longValue() + 1 ); } counts.put( USN, count ); pc.getPluginMapParameter( key, counts ); return( count.longValue()); } protected long getDeviceStats( String USN, String stat_key ) { String key = "upnp.device.stats." + stat_key; PluginConfig pc = plugin_interface.getPluginconfig(); Map counts = pc.getPluginMapParameter( key, new HashMap()); Long count = (Long)counts.get( USN ); if ( count == null ){ return( 0 ); } return( count.longValue()); } protected void setDeviceStats( String USN, String stat_key, long value ) { String key = "upnp.device.stats." + stat_key; PluginConfig pc = plugin_interface.getPluginconfig(); Map counts = pc.getPluginMapParameter( key, new HashMap()); counts.put( USN, new Long( value )); pc.getPluginMapParameter( key, counts ); } public void mappingResult( UPnPWANConnection connection, boolean ok ) { UPnPRootDevice root = connection.getGenericService().getDevice().getRootDevice(); incrementDeviceStats( root.getUSN(), ok?STATS_MAP_OK:STATS_MAP_BAD ); checkDeviceStats( root ); } public void mappingsReadResult( UPnPWANConnection connection, boolean ok ) { UPnPRootDevice root = connection.getGenericService().getDevice().getRootDevice(); incrementDeviceStats( root.getUSN(), ok?STATS_READ_OK:STATS_READ_BAD ); } protected String[] getSelectedInterfaces() { String si = selected_interfaces_param.getValue().trim(); StringTokenizer tok = new StringTokenizer( si, ";" ); List res = new ArrayList(); while( tok.hasMoreTokens()){ String s = tok.nextToken().trim(); if ( s.length() > 0 ){ res.add( s ); } } return( (String[])res.toArray( new String[res.size()])); } protected String[] getSelectedAddresses() { String si = selected_addresses_param.getValue().trim(); StringTokenizer tok = new StringTokenizer( si, ";" ); List res = new ArrayList(); while( tok.hasMoreTokens()){ String s = tok.nextToken().trim(); if ( s.length() > 0 ){ res.add( s ); } } return( (String[])res.toArray( new String[res.size()])); } protected int processDevice( UPnPDevice device ) throws UPnPException { int interesting = processServices( device, device.getServices()); UPnPDevice[] kids = device.getSubDevices(); for (int i=0;i 0 && speeds[1] > 0 ){ log.log( "Device speed: down=" + plugin_interface.getUtilities().getFormatters().formatByteCountToKiBEtcPerSec(speeds[0]/8) + ", up=" + plugin_interface.getUtilities().getFormatters().formatByteCountToKiBEtcPerSec(speeds[1]/8)); } }catch( Throwable e ){ log.log(e); } */ } } return( interesting ); } protected void addService( UPnPWANConnection wan_service ) throws UPnPException { wan_service.addListener( this ); mapping_manager.serviceFound( wan_service ); try{ this_mon.enter(); log.log( " Found " + ( wan_service.getGenericService().getServiceType().indexOf("PPP") == -1? "WANIPConnection":"WANPPPConnection" )); UPnPWANConnectionPortMapping[] ports; String usn = wan_service.getGenericService().getDevice().getRootDevice().getUSN(); if ( getDeviceStats( usn, STATS_READ_OK ) == 0 && getDeviceStats( usn, STATS_READ_BAD ) > 2 ){ ports = new UPnPWANConnectionPortMapping[0]; wan_service.periodicallyRecheckMappings( false ); log.log( " Not reading port mappings from device due to previous failures" ); }else{ ports = wan_service.getPortMappings(); } for (int j=0;j " + ports[j].getInternalHost()); } services.add(new UPnPPluginService( wan_service, ports, alert_success_param, grab_ports_param, alert_other_port_param, release_mappings_param )); if ( services.size() > 1 ){ // check this isn't a single device with multiple services String new_usn = wan_service.getGenericService().getDevice().getRootDevice().getUSN(); boolean multiple_found = false; for (int i=0;i res = new ArrayList(); try{ this_mon.enter(); for ( UPnPPluginService service: services ){ String this_usn = service.getService().getGenericService().getDevice().getRootDevice().getUSN(); if ( this_usn.equals( target_usn )){ res.add( service ); } } }finally{ this_mon.exit(); } return( res.toArray( new UPnPPluginService[res.size()] )); } // for external use, e.g. webui public UPnPMapping addMapping( String desc_resource, boolean tcp, int port, boolean enabled ) { return( mapping_manager.addMapping( desc_resource, tcp, port, enabled )); } public UPnPMapping getMapping( boolean tcp, int port ) { return( mapping_manager.getMapping( tcp, port )); } public UPnPMapping[] getMappings() { return( mapping_manager.getMappings()); } public boolean isEnabled() { return( upnp_enable_param.getValue()); } protected void setNATPMPEnableState() { boolean enabled = natpmp_enable_param.getValue() && upnp_enable_param.getValue(); try{ if ( enabled ){ if ( nat_pmp_upnp == null ){ nat_pmp_upnp = NatPMPUPnPFactory.create( upnp, NatPMPDeviceFactory.getSingleton( new NATPMPDeviceAdapter() { public String getRouterAddress() { return( nat_pmp_router.getValue()); } public void log( String str ) { log.log( "NAT-PMP: " + str ); } })); nat_pmp_upnp.addListener( this ); } nat_pmp_upnp.setEnabled( true ); }else{ if ( nat_pmp_upnp != null ){ nat_pmp_upnp.setEnabled( false ); } } }catch( Throwable e ){ log.log( "Failed to initialise NAT-PMP subsystem", e ); } } protected void logAlert( int type, String resource, String[] params ) { String text = plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( resource, params ); log.logAlertRepeatable( type, text ); } /** * Provided for use by other plugins. */ public void refreshMappings() { refreshMappings(false); } /** * Provided for use by other plugins. */ public void refreshMappings(boolean force) { if (force) { closeDown(true); startUp(); } else { this.upnp.reset(); } } } azureus-4.3.0.6/com/aelitis/azureus/plugins/upnp/UPnPMappingManagerListener.java0000644000175000017500000000215610373051020027204 0ustar adrianadrian/* * Created on 16-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.upnp; /** * @author parg * */ public interface UPnPMappingManagerListener { public void mappingAdded( UPnPMapping mapping ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/removerules/0000755000175000017500000000000011310377630022576 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/removerules/DownloadRemoveRulesPlugin.java0000644000175000017500000002541011273722432030564 0ustar adrianadrian/* * Created on 06-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.removerules; /** * @author parg * */ import java.net.InetAddress; import java.util.*; import org.gudy.azureus2.plugins.torrent.*; import org.gudy.azureus2.plugins.download.*; import org.gudy.azureus2.plugins.logging.LoggerChannel; import org.gudy.azureus2.plugins.ui.config.*; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.core3.util.*; public class DownloadRemoveRulesPlugin implements Plugin, DownloadManagerListener { public static final int INITIAL_DELAY = 60*1000; public static final int DELAYED_REMOVAL_PERIOD = 60*1000; public static final int AELITIS_BIG_TORRENT_SEED_LIMIT = 10000; public static final int AELITIS_SMALL_TORRENT_SEED_LIMIT = 1000; public static final int MAX_SEED_TO_PEER_RATIO = 10; // 10 to 1 public static final String UPDATE_TRACKER = "tracker.update.vuze.com"; // needs to be lowercase protected PluginInterface plugin_interface; protected boolean closing; protected Map dm_listener_map = new HashMap(10); protected List monitored_downloads = new ArrayList(); protected LoggerChannel log; protected BooleanParameter remove_unauthorised; protected BooleanParameter remove_unauthorised_seeding_only; protected BooleanParameter remove_unauthorised_data; protected BooleanParameter remove_update_torrents; public static void load( PluginInterface plugin_interface ) { plugin_interface.getPluginProperties().setProperty( "plugin.version", "1.0" ); plugin_interface.getPluginProperties().setProperty( "plugin.name", "Download Remove Rules" ); } public void initialize( PluginInterface _plugin_interface ) { plugin_interface = _plugin_interface; log = plugin_interface.getLogger().getChannel("DLRemRules"); BasicPluginConfigModel config = plugin_interface.getUIManager().createBasicPluginConfigModel( "torrents", "download.removerules.name" ); config.addLabelParameter2( "download.removerules.unauthorised.info" ); remove_unauthorised = config.addBooleanParameter2( "download.removerules.unauthorised", "download.removerules.unauthorised", false ); remove_unauthorised_seeding_only = config.addBooleanParameter2( "download.removerules.unauthorised.seedingonly", "download.removerules.unauthorised.seedingonly", true ); remove_unauthorised_data = config.addBooleanParameter2( "download.removerules.unauthorised.data", "download.removerules.unauthorised.data", false ); remove_unauthorised.addEnabledOnSelection( remove_unauthorised_seeding_only ); remove_unauthorised.addEnabledOnSelection( remove_unauthorised_data ); remove_update_torrents = config.addBooleanParameter2( "download.removerules.updatetorrents", "download.removerules.updatetorrents", true ); new DelayedEvent( "DownloadRemovalRules", INITIAL_DELAY, new AERunnable() { public void runSupport() { plugin_interface.getDownloadManager().addListener( DownloadRemoveRulesPlugin.this ); } }); } public void downloadAdded( final Download download ) { // we don't auto-remove non-persistent downloads as these are managed // elsewhere (e.g. shares) if ( !download.isPersistent()){ return; } DownloadTrackerListener listener = new DownloadTrackerListener() { public void scrapeResult( DownloadScrapeResult response ) { if ( closing ){ return; } handleScrape( download, response ); } public void announceResult( DownloadAnnounceResult response ) { if ( closing ){ return; } handleAnnounce( download, response ); } }; monitored_downloads.add( download ); dm_listener_map.put( download, listener ); download.addTrackerListener( listener ); } protected void handleScrape( Download download, DownloadScrapeResult response ) { String status = response.getStatus(); if ( status == null ){ status = ""; } handleAnnounceScrapeStatus( download, status ); } protected void handleAnnounce( Download download, DownloadAnnounceResult response ) { String reason = ""; if ( response.getResponseType() == DownloadAnnounceResult.RT_ERROR ){ reason = response.getError(); if ( reason == null ){ reason = ""; } } handleAnnounceScrapeStatus( download, reason ); } protected void handleAnnounceScrapeStatus( Download download, String status ) { if ( !monitored_downloads.contains( download )){ return; } status = status.toLowerCase(); boolean download_completed = download.isComplete(); if ( status.indexOf( "not authori" ) != -1 || status.toLowerCase().indexOf( "unauthori" ) != -1 ){ if ( remove_unauthorised.getValue() && ( (!remove_unauthorised_seeding_only.getValue()) || download_completed )){ log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, "Download '" + download.getName() + "' is unauthorised and removal triggered"); removeDownload( download, remove_unauthorised_data.getValue() ); return; } } Torrent torrent = download.getTorrent(); if ( torrent != null && torrent.getAnnounceURL() != null ){ String url_string = torrent.getAnnounceURL().toString().toLowerCase(); if ( url_string.indexOf( UPDATE_TRACKER ) != -1 ){ // emergency instruction from tracker if ( ( download_completed && status.indexOf( "too many seeds" ) != -1 ) || status.indexOf( "too many peers" ) != -1 ){ log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, "Download '" + download.getName() + "' being removed on instruction from the tracker"); removeDownloadDelayed( download, false ); }else if ( download_completed && remove_update_torrents.getValue()){ long seeds = download.getLastScrapeResult().getSeedCount(); long peers = download.getLastScrapeResult().getNonSeedCount(); // try to maintain an upper bound on seeds that isn't going to // kill the tracker if ( seeds / ( peers==0?1:peers ) > MAX_SEED_TO_PEER_RATIO ){ log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, "Download '" + download.getName() + "' being removed to reduce swarm size"); removeDownloadDelayed( download, false ); }else{ long creation_time = download.getCreationTime(); long running_mins = ( SystemTime.getCurrentTime() - creation_time )/(60*1000); if ( running_mins > 15 ){ // big is a relative term here and generally distinguishes between core updates // and plugin updates boolean big_torrent = torrent.getSize() > 1024*1024; if ( ( seeds > AELITIS_BIG_TORRENT_SEED_LIMIT && big_torrent ) || ( seeds > AELITIS_SMALL_TORRENT_SEED_LIMIT && !big_torrent )){ log.log( "Download '" + download.getName() + "' being removed to reduce swarm size" ); removeDownloadDelayed( download, false ); } } } } } } } protected void removeDownloadDelayed( final Download download, final boolean remove_data ) { monitored_downloads.remove( download ); // we need to delay this because other actions may be being performed // on the download (e.g. completion may trigger update install) plugin_interface.getUtilities().createThread( "delayedRemoval", new AERunnable() { public void runSupport() { try{ Thread.sleep( DELAYED_REMOVAL_PERIOD ); removeDownload( download, remove_data ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } }); } protected void removeDownload( final Download download, final boolean remove_data ) { monitored_downloads.remove( download ); if ( download.getState() == Download.ST_STOPPED ){ try{ download.remove( false, remove_data ); }catch( Throwable e ){ log.logAlert( "Automatic removal of download '" + download.getName() + "' failed", e ); } }else{ download.addListener( new DownloadListener() { public void stateChanged( Download download, int old_state, int new_state ) { log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, "download state changed to '" + new_state + "'"); if ( new_state == Download.ST_STOPPED ){ try{ download.remove( false, remove_data ); String msg = plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( "download.removerules.removed.ok", new String[] { download.getName() }); if (download.getFlag(Download.FLAG_LOW_NOISE)) { log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, msg); } else { log.logAlert(LoggerChannel.LT_INFORMATION, msg); } }catch( Throwable e ){ log.logAlert( "Automatic removal of download '" + download.getName() + "' failed", e ); } } } public void positionChanged( Download download, int oldPosition, int newPosition ) { } }); try{ download.stop(); }catch( DownloadException e ){ log.logAlert( "Automatic removal of download '" + download.getName() + "' failed", e ); } } } public void downloadRemoved( Download download ) { monitored_downloads.remove( download ); DownloadTrackerListener listener = (DownloadTrackerListener)dm_listener_map.remove(download); if ( listener != null ){ download.removeTrackerListener( listener ); } } public void destroyInitiated() { closing = true; } public void destroyed() { } } azureus-4.3.0.6/com/aelitis/azureus/plugins/clientid/0000755000175000017500000000000011310377630022021 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/clientid/ClientIDPlugin.java0000644000175000017500000000564211033473410025500 0ustar adrianadrian/* * Created on 29-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.clientid; import java.util.Properties; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.plugins.clientid.ClientIDGenerator; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.pluginsimpl.local.clientid.ClientIDManagerImpl; import org.gudy.azureus2.core3.peer.util.PeerUtils; import org.gudy.azureus2.core3.util.Constants; /** * @author parg * */ public class ClientIDPlugin { private static boolean send_os; public static void initialize() { final String param = "Tracker Client Send OS and Java Version"; COConfigurationManager.addAndFireParameterListener(param, new ParameterListener() { public void parameterChanged(String param) { send_os = COConfigurationManager.getBooleanParameter(param); } }); ClientIDManagerImpl.getSingleton().setGenerator( new ClientIDGenerator() { public byte[] generatePeerID( Torrent torrent, boolean for_tracker ) { return( PeerUtils.createPeerID()); } public void generateHTTPProperties( Properties properties ) { doHTTPProperties( properties ); } public String[] filterHTTP( String[] lines_in ) { return( lines_in ); } }, false ); } protected static void doHTTPProperties( Properties properties ) { String version = Constants.AZUREUS_VERSION; // trim of any _Bnn or _CVS suffix as unfortunately some trackers can't cope with this // (well, apparently can't cope with B10) // its not a big deal anyway int pos = version.indexOf('_'); if ( pos != -1 ){ version = version.substring(0,pos); } String agent = Constants.AZUREUS_NAME + " " + version; if ( send_os ){ agent += ";" + Constants.OSName; agent += ";Java " + Constants.JAVA_VERSION; } properties.put( ClientIDGenerator.PR_USER_AGENT, agent ); } } azureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/0000755000175000017500000000000011310377326023346 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/always/0000755000175000017500000000000011310377630024644 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/always/RunEverythingPlugin.java0000644000175000017500000002104510462403664031505 0ustar adrianadrian/* * Created on 05-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.startstoprules.always; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.gudy.azureus2.plugins.Plugin; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.PluginListener; import org.gudy.azureus2.plugins.PluginManager; import org.gudy.azureus2.plugins.PluginManagerDefaults; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadAnnounceResult; import org.gudy.azureus2.plugins.download.DownloadException; import org.gudy.azureus2.plugins.download.DownloadListener; import org.gudy.azureus2.plugins.download.DownloadManagerListener; import org.gudy.azureus2.plugins.download.DownloadScrapeResult; import org.gudy.azureus2.plugins.download.DownloadTrackerListener; import org.gudy.azureus2.plugins.logging.LoggerChannel; import org.gudy.azureus2.plugins.utils.Monitor; import org.gudy.azureus2.plugins.utils.Semaphore; import org.gudy.azureus2.plugins.utils.UTTimerEvent; import org.gudy.azureus2.plugins.utils.UTTimerEventPerformer; public class RunEverythingPlugin implements Plugin, DownloadManagerListener, DownloadListener, DownloadTrackerListener { private PluginInterface plugin_interface; private LoggerChannel logger; private Map downloads; private Monitor downloads_mon; private Semaphore work_sem; private volatile boolean closing; public static void load( PluginInterface _plugin_interface ) { PluginManagerDefaults defaults = PluginManager.getDefaults(); defaults.setDefaultPluginEnabled( PluginManagerDefaults.PID_START_STOP_RULES, false ); } public void initialize( PluginInterface _pi ) { plugin_interface = _pi; logger = plugin_interface.getLogger().getChannel( "RunEverythingSeedingRules" ); plugin_interface.addListener( new PluginListener() { public void initializationComplete() { } public void closedownInitiated() { closing = true; } public void closedownComplete() { } }); downloads = new HashMap(); downloads_mon = plugin_interface.getUtilities().getMonitor(); work_sem = plugin_interface.getUtilities().getSemaphore(); plugin_interface.getDownloadManager().addListener( this ); plugin_interface.getUtilities().createTimer("DownloadRules", true ).addPeriodicEvent( 10000, new UTTimerEventPerformer() { public void perform( UTTimerEvent event) { checkRules(); } }); plugin_interface.getUtilities().createThread( "DownloadRules", new Runnable() { public void run() { processLoop(); } }); } public void downloadAdded( Download download ) { log( "added: " + download.getName() + ", state = " + Download.ST_NAMES[ download.getState()]); downloadData dd = new downloadData( download ); try{ downloads_mon.enter(); downloads.put( download, dd ); }finally{ downloads_mon.exit(); } download.addListener( this ); checkRules(); } public void downloadRemoved( Download download ) { try{ downloads_mon.enter(); downloads.remove( download ); }finally{ downloads_mon.exit(); } download.removeListener( this ); checkRules(); } public void scrapeResult( DownloadScrapeResult result ) { checkRules(); } public void announceResult( DownloadAnnounceResult result ) { checkRules(); } public void stateChanged( Download download, int old_state, int new_state ) { log( "Rules: state change for " + download.getName() + ": " + Download.ST_NAMES[old_state] + "->" + Download.ST_NAMES[new_state]); checkRules(); } public void positionChanged( Download download, int oldPosition, int newPosition ) { checkRules(); } protected void checkRules() { work_sem.release(); } protected void processLoop() { while( !closing ){ work_sem.reserve(); while( work_sem.reserveIfAvailable()){ } try{ processSupport(); Thread.sleep( 250 ); }catch( Throwable e ){ e.printStackTrace(); } } } protected void processSupport() { if ( closing ){ return; } try{ downloads_mon.enter(); List dls = new ArrayList( downloads.values()); // remove any ignored ones Iterator it = dls.iterator(); while (it.hasNext()){ downloadData dd = (downloadData)it.next(); if ( dd.ignore()){ it.remove(); } } // execute an "initialize" on any waiting ones it = dls.iterator(); while (it.hasNext()){ downloadData dd = (downloadData)it.next(); if ( dd.getState() == Download.ST_WAITING ){ it.remove(); try{ log( "initialising " + dd.getName()); dd.getDownload().initialize(); }catch( DownloadException e ){ e.printStackTrace(); } } } // execute a "start" on any READY ones it = dls.iterator(); while (it.hasNext()){ downloadData dd = (downloadData)it.next(); if ( dd.getState() == Download.ST_READY ){ it.remove(); try{ log( "starting " + dd.getName()); dd.getDownload().start(); }catch( DownloadException e ){ e.printStackTrace(); } } } // start downloads it = dls.iterator(); while (it.hasNext()){ downloadData dd = (downloadData)it.next(); if ( dd.getState() == Download.ST_QUEUED && !dd.isComplete()){ try{ it.remove(); log( "restarting download " + dd.getName()); dd.getDownload().restart(); }catch( DownloadException e ){ e.printStackTrace(); } } } // start seeds it = dls.iterator(); while ( it.hasNext()){ downloadData dd = (downloadData)it.next(); if ( dd.isComplete() && dd.getState() == Download.ST_QUEUED ){ try{ it.remove(); log( "restarting seed " + dd.getName()); dd.getDownload().restart(); }catch( DownloadException e ){ e.printStackTrace(); } } } }finally{ downloads_mon.exit(); } } protected void log( String str ) { logger.log( str ); } protected class downloadData { private Download download; protected downloadData( Download _download ) { download = _download; } protected Download getDownload() { return( download ); } protected int getState() { return( download.getState()); } protected String getName() { return( download.getName()); } protected boolean isDownloading() { if ( isComplete()){ return( false ); } int state = download.getState(); return( state == Download.ST_WAITING || state == Download.ST_PREPARING || state == Download.ST_READY || state == Download.ST_DOWNLOADING ); } protected boolean isSeeding() { if ( !isComplete()){ return( false ); } int state = download.getState(); return( state == Download.ST_WAITING || state == Download.ST_PREPARING || state == Download.ST_READY || state == Download.ST_SEEDING ); } protected boolean isComplete() { return( download.isComplete() ); } protected boolean ignore() { int state = download.getState(); return( state == Download.ST_ERROR || state == Download.ST_STOPPED || state == Download.ST_STOPPING ); } } } azureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/0000755000175000017500000000000011310377630026207 5ustar adrianadrian././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesDefaultPlugin.javaazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesDefaultPlugin0000644000175000017500000021772611270174552033616 0ustar adrianadrian/* * File : StartStopRulesDefaultPlugin.java * Created : 12-Jan-2004 * By : TuxPaper * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.plugins.startstoprules.defaultplugin; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationListener; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.Plugin; import org.gudy.azureus2.plugins.PluginConfig; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.PluginListener; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.download.*; import org.gudy.azureus2.plugins.logging.LoggerChannel; import org.gudy.azureus2.plugins.ui.UIInstance; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.UIManagerListener; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.menus.MenuItemListener; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.plugins.ui.tables.TableRow; import org.gudy.azureus2.ui.swt.plugins.UISWTInstance; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.plugins.startstoprules.defaultplugin.ui.swt.StartStopRulesDefaultPluginSWTUI; /** Handles Starting and Stopping of torrents. * * TODO: RANK_TIMED is quite a hack and is spread all over. It needs to be * redone, probably with a timer on each seeding torrent which triggers * when time is up and it needs to stop. * * BUG: When "AutoStart 0 Peers" is on, and minSpeedForActivelySeeding is * enabled, the 0 peer torrents will continuously switch from seeding to * queued, probably due to the connection attempt registering speed. * This might be fixed by the "wait XX ms before switching active state" * code. * * Other Notes: * "CD" is often used to refer to "Seed" or "Seeding", because "C" sounds like * "See" */ public class StartStopRulesDefaultPlugin implements Plugin, COConfigurationListener, AEDiagnosticsEvidenceGenerator { // for debugging private static final String sStates = " WPRDS.XEQ"; /** Do not rank completed torrents */ public static final int RANK_NONE = 0; /** Rank completed torrents using Seeds:Peer Ratio */ public static final int RANK_SPRATIO = 1; /** Rank completed torrents using Seed Count method */ public static final int RANK_SEEDCOUNT = 2; /** Rank completed torrents using a timed rotation of minTimeAlive */ public static final int RANK_TIMED = 3; /** Rank completed torrents using the peers count, weighted by the seeds to peers ratio */ public static final int RANK_PEERCOUNT = 4; /** * Force at least one check every period of time (in ms). * Used in ChangeFlagCheckerTask */ private static final int FORCE_CHECK_PERIOD = 60000; /** * Check for non triggerable changes ever period of time (in ms) */ private static final int CHECK_FOR_GROSS_CHANGE_PERIOD = 30000; /** * Interval in ms between checks to see if the {@link #somethingChanged} * flag changed */ private static final int PROCESS_CHECK_PERIOD = 1500; /** Wait xx ms before starting completed torrents (so scrapes can come in) */ private static final int MIN_SEEDING_STARTUP_WAIT = 20000; /** Wait at least xx ms for first scrape, before starting completed torrents */ private static final int MIN_FIRST_SCRAPE_WAIT = 90000; private static final float IGNORE_SLOT_THRESHOLD_FACTOR = 0.9f; // Core/Plugin classes private AEMonitor this_mon = new AEMonitor("StartStopRules"); private PluginInterface pi; protected PluginConfig plugin_config; private DownloadManager download_manager; protected LoggerChannel log; /** Used only for RANK_TIMED. Recalculate ranks on a timer */ private RecalcSeedingRanksTask recalcSeedingRanksTask; /** Map to relate downloadData to a Download */ private static Map downloadDataMap = Collections.synchronizedMap(new HashMap()); /** * this is used to reduce the number of comperator invocations * by keeping a mostly sorted copy around, must be nulled whenever the map is changed */ private volatile DefaultRankCalculator[] sortedArrayCache; private volatile boolean closingDown; private volatile boolean somethingChanged; private Set ranksToRecalc = new LightHashSet(); private AEMonitor ranksToRecalc_mon = new AEMonitor("ranksToRecalc"); /** When rules class started. Used for initial waiting logic */ private long startedOn; // Config Settings /** Whether Debug Info is written to the log and tooltip */ protected boolean bDebugLog; /** Ranking System to use. One of RANK_* constants */ private int iRankType = -1; private int minSpeedForActiveSeeding; /** Maximimum # of stalled torrents that are in seeding mode */ private int maxStalledSeeding; // count x peers as a full copy, but.. private int numPeersAsFullCopy; // don't count x peers as a full copy if seeds below private int iFakeFullCopySeedStart; private int _maxActive; private boolean _maxActiveWhenSeedingEnabled; private int _maxActiveWhenSeeding; private int globalDownloadLimit; private int globalUploadLimit; private int globalUploadWhenSeedingLimit; private int maxDownloads; private int minDownloads; private boolean bAutoReposition; private long minTimeAlive; private boolean bAutoStart0Peers; private boolean bStopOnceBandwidthMet = false; private static boolean bAlreadyInitialized = false; // UI private TableColumn seedingRankColumn; // UI private TableContextMenuItem debugMenuItem = null; private boolean bSWTUI = false; private CopyOnWriteList listenersFP = new CopyOnWriteList(); public static boolean pauseChangeFlagChecker = false; public static void load( PluginInterface plugin_interface ) { plugin_interface.getPluginProperties().setProperty("plugin.version", "1.0"); plugin_interface.getPluginProperties().setProperty("plugin.name", "Start/Stop Rules"); } public void initialize(PluginInterface _plugin_interface) { if (bAlreadyInitialized) { System.err.println("StartStopRulesDefaultPlugin Already initialized!!"); } else { bAlreadyInitialized = true; } AEDiagnostics.addEvidenceGenerator(this); startedOn = SystemTime.getCurrentTime(); pi = _plugin_interface; plugin_config = pi.getPluginconfig(); plugin_config.setPluginConfigKeyPrefix(""); download_manager = pi.getDownloadManager(); // Create a configModel for StartStopRules // We always need to do this in order to set up configuration defaults UIManager manager = pi.getUIManager(); // TODO: don't name it Q final BasicPluginConfigModel configModel = manager.createBasicPluginConfigModel( ConfigSection.SECTION_ROOT, "Q"); setupConfigModel(configModel); pi.addListener(new PluginListener() { public void initializationComplete() {} public void closedownInitiated() { closingDown = true; // we don't want to go off recalculating stuff when config is saved // on closedown COConfigurationManager.removeListener(StartStopRulesDefaultPlugin.this); } public void closedownComplete() { /* not implemented */ } }); Runnable r = new Runnable() { public void run() { download_manager.addListener(new StartStopDMListener()); SimpleTimer.addPeriodicEvent("StartStop:gross", CHECK_FOR_GROSS_CHANGE_PERIOD, new ChangeCheckerTimerTask()); SimpleTimer.addPeriodicEvent("StartStop:check", PROCESS_CHECK_PERIOD, new ChangeFlagCheckerTask()); } }; pi.getUtilities().createDelayedTask(r).queue(); log = pi.getLogger().getTimeStampedChannel("StartStopRules"); log.log(LoggerChannel.LT_INFORMATION, "Default StartStopRules Plugin Initialisation"); COConfigurationManager.addListener(this); try { pi.getUIManager().createLoggingViewModel(log, true); pi.getUIManager().addUIListener(new UIManagerListener() { public void UIAttached(UIInstance instance) { TableManager tm = pi.getUIManager().getTableManager(); seedingRankColumn = tm.createColumn( TableManager.TABLE_MYTORRENTS_COMPLETE, "SeedingRank"); seedingRankColumn.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 80, TableColumn.INTERVAL_LIVE); SeedingRankColumnListener columnListener = new SeedingRankColumnListener( downloadDataMap, plugin_config); seedingRankColumn.addCellRefreshListener(columnListener); tm.addColumn(seedingRankColumn); if (instance instanceof UISWTInstance) { bSWTUI = true; // We have our own config model :) configModel.destroy(); new StartStopRulesDefaultPluginSWTUI(pi); } } public void UIDetached(UIInstance instance) { } }); } catch (Throwable e) { Debug.printStackTrace(e); } reloadConfigParams(); } /** * @param configModel * */ private void setupConfigModel(BasicPluginConfigModel configModel) { String PREFIX_RES = "ConfigView.label.seeding."; configModel.addIntParameter2( "StartStopManager_iRankType", "ConfigView.label.seeding.rankType", StartStopRulesDefaultPlugin.RANK_SPRATIO); configModel.addIntParameter2("StartStopManager_iRankTypeSeedFallback", "ConfigView.label.seeding.rankType.seed.fallback", 0); configModel.addBooleanParameter2("StartStopManager_bAutoReposition", "ConfigView.label.seeding.autoReposition", false); configModel.addIntParameter2("StartStopManager_iMinSeedingTime", "ConfigView.label.minSeedingTime", 60 * 10); // ignore rules subsection // --------- configModel.addBooleanParameter2("StartStopManager_bIgnore0Peers", "ConfigView.label.seeding.ignore0Peers", true); configModel.addIntParameter2("StartStopManager_iIgnoreSeedCount", "ConfigView.label.ignoreSeeds", 0); // for "Stop Peers Ratio" ignore rule configModel.addIntParameter2("StartStopManager_iIgnoreRatioPeersSeedStart", "ConfigView.label.seeding.fakeFullCopySeedStart", 0); // for "Stop Ratio" ignore rule configModel.addIntParameter2("StartStopManager_iIgnoreShareRatioSeedStart", "ConfigView.label.seeding.fakeFullCopySeedStart", 0); // Auto Starting // --------- configModel.addBooleanParameter2("StartStopManager_bPreferLargerSwarms", "ConfigView.label.seeding.preferLargerSwarms", true); configModel.addBooleanParameter2("StartStopManager_bAutoStart0Peers", "ConfigView.label.seeding.autoStart0Peers", false); configModel.addIntParameter2("StartStopManager_iMinPeersToBoostNoSeeds", "ConfigView.label.minPeersToBoostNoSeeds", 1); // queue section // --------- configModel.addIntParameter2("StartStopManager_iMinSpeedForActiveDL", "ConfigView.label.minSpeedForActiveDL", 512); configModel.addIntParameter2("StartStopManager_iMinSpeedForActiveSeeding", "ConfigView.label.minSpeedForActiveSeeding", 512); configModel.addIntParameter2("StartStopManager_iMaxStalledSeeding", "ConfigView.label.maxStalledSeeding", 5); configModel.addBooleanParameter2("StartStopManager_bDebugLog", "ConfigView.label.queue.debuglog", false); configModel.addBooleanParameter2("StartStopManager_bNewSeedsMoveTop", "ConfigView.label.queue.newseedsmovetop", true); configModel.addIntParameter2( "StartStopManager_iMaxActiveTorrentsWhenSeeding", "ConfigView.label.queue.maxactivetorrentswhenseeding", 0); configModel.addBooleanParameter2( "StartStopManager_bMaxActiveTorrentsWhenSeedingEnabled", "ConfigView.label.queue.maxactivetorrentswhenseeding", false); configModel.addBooleanParameter2( "StartStopManager_bStopOnceBandwidthMet", "ConfigView.label.queue.stoponcebandwidthmet", true); // first Priority subsection // --------- configModel.addIntParameter2("StartStopManager_iFirstPriority_Type", "ConfigView.label.seeding.firstPriority", DefaultRankCalculator.FIRSTPRIORITY_ANY); configModel.addIntParameter2("StartStopManager_iFirstPriority_ShareRatio", "ConfigView.label.seeding.firstPriority.shareRatio", 500); configModel.addIntParameter2( "StartStopManager_iFirstPriority_SeedingMinutes", "ConfigView.label.seeding.firstPriority.seedingMinutes", 0); configModel.addIntParameter2("StartStopManager_iFirstPriority_DLMinutes", "ConfigView.label.seeding.firstPriority.DLMinutes", 0); // for ignore FP rules configModel.addIntParameter2( "StartStopManager_iFirstPriority_ignoreSPRatio", "ConfigView.label.seeding.firstPriority.ignoreSPRatio", 0); configModel.addBooleanParameter2( "StartStopManager_bFirstPriority_ignore0Peer", "ConfigView.label.seeding.firstPriority.ignore0Peer", !COConfigurationManager.getStringParameter("ui", "").equals("az2")); configModel.addIntParameter2( "StartStopManager_iFirstPriority_ignoreIdleHours", "ConfigView.label.seeding.firstPriority.ignoreIdleHours", 24); // seeding subsection configModel.addIntParameter2("StartStopManager_iAddForSeedingDLCopyCount", "ConfigView.label.seeding.addForSeedingDLCopyCount", 1); configModel.addIntParameter2("StartStopManager_iNumPeersAsFullCopy", PREFIX_RES + "numPeersAsFullCopy", 0); configModel.addIntParameter2("StartStopManager_iFakeFullCopySeedStart", PREFIX_RES + "fakeFullCopySeedStart", 1); configModel.destroy(); } public static DefaultRankCalculator getRankCalculator(Download dl) { return (DefaultRankCalculator) downloadDataMap.get(dl); } private void recalcAllSeedingRanks(boolean force) { if (closingDown) { return; } try { this_mon.enter(); DefaultRankCalculator[] dlDataArray = (DefaultRankCalculator[]) downloadDataMap.values().toArray( new DefaultRankCalculator[0]); // Check Group #1: Ones that always should run since they set things for (int i = 0; i < dlDataArray.length; i++) { if (force) dlDataArray[i].getDownloadObject().setSeedingRank(0); dlDataArray[i].recalcSeedingRank(); } } finally { this_mon.exit(); } } /** A simple timer task to recalculate all seeding ranks. */ private class RecalcSeedingRanksTask implements TimerEventPerformer { boolean bCancel = false; public void perform(TimerEvent event) { if (bCancel) { event.cancel(); return; } // System.out.println("RecalcAllSeedingRanks"); recalcAllSeedingRanks(false); } /** * */ public void cancel() { bCancel = true; } } /** This class check if the somethingChanged flag and call process() when * its set. This allows pooling of changes, thus cutting down on the number * of sucessive process() calls. */ private class ChangeFlagCheckerTask implements TimerEventPerformer { final long FORCE_CHECK_CYCLES = FORCE_CHECK_PERIOD / PROCESS_CHECK_PERIOD; long cycleNo = 0; public void perform(TimerEvent event) { if (closingDown || pauseChangeFlagChecker ) { return; } cycleNo++; if (cycleNo > FORCE_CHECK_CYCLES) { if (bDebugLog) { log.log(LoggerChannel.LT_INFORMATION, ">>force process"); } somethingChanged = true; } if (somethingChanged) { try { cycleNo = 0; process(); } catch (Exception e) { Debug.printStackTrace(e); } } } } private volatile boolean immediateProcessingScheduled = false; /** Listen to Download changes and recalc SR if needed */ private class StartStopDownloadListener implements DownloadListener { public void stateChanged(Download download, int old_state, int new_state) { DefaultRankCalculator dlData = (DefaultRankCalculator) downloadDataMap.get(download); if (dlData != null) { // force a SR recalc, so that it gets position properly next process() requestProcessCycle(dlData); if ((new_state == Download.ST_READY || new_state == Download.ST_WAITING)) { if (immediateProcessingScheduled) { requestProcessCycle(dlData); } else { immediateProcessingScheduled = true; new AEThread2("processReady", true) { public void run() { process(); } }.start(); } } if (bDebugLog) log.log(dlData.dl.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: stateChange from " + sStates.charAt(old_state) + " (" + old_state + ") to " + sStates.charAt(new_state) + " (" + new_state + ")"); } } public void positionChanged(Download download, int oldPosition, int newPosition) { DefaultRankCalculator dlData = (DefaultRankCalculator) downloadDataMap.get(download); if (dlData != null) { requestProcessCycle(dlData); if (bDebugLog) log.log(dlData.dl.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: positionChanged from " + oldPosition + " to " + newPosition); } } } /** Update SeedingRank when a new scrape result comes in. */ private class StartStopDMTrackerListener implements DownloadTrackerListener { public void scrapeResult(DownloadScrapeResult result) { Download dl = result.getDownload(); DefaultRankCalculator dlData = (DefaultRankCalculator) downloadDataMap.get(dl); // Skip if error (which happens when listener is first added and the // torrent isn't scraped yet) if (result.getResponseType() == DownloadScrapeResult.RT_ERROR) { if (bDebugLog) log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "Ignored somethingChanged: new scrapeResult (RT_ERROR)"); if (dlData != null) dlData.lastScrapeResultOk = false; return; } if (dlData != null) { dlData.lastScrapeResultOk = true; requestProcessCycle(dlData); if (bDebugLog) log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: new scrapeResult S:" + result.getSeedCount() + ";P:" + result.getNonSeedCount()); } } public void announceResult(DownloadAnnounceResult result) { // Announces are useless to us. Even if the announce contains seed/peer // count, they are not stored in the DownloadAnnounceResult. Instead, // they are passed off to the DownloadScrapeResult, and a scrapeResult // is triggered } } private class StartStopDownloadActivationListener implements DownloadActivationListener { public boolean activationRequested(DownloadActivationEvent event) { //System.out.println("StartStop: activation request: count = " // + event.getActivationCount()); Download download = event.getDownload(); DefaultRankCalculator dlData = (DefaultRankCalculator) downloadDataMap.get(download); if (bDebugLog) { log.log(download, LoggerChannel.LT_INFORMATION, ">> somethingChanged: ActivationRequest"); } // ok to be null requestProcessCycle(dlData); if (download.isComplete()) { // quick and dirty check: keep connection if scrape peer count is 0 // there's a (good?) chance we'll start in the next process cycle DownloadScrapeResult sr = event.getDownload().getLastScrapeResult(); int numPeers = sr.getNonSeedCount(); if (numPeers <= 0) { return true; } } return false; } } /* Create/Remove downloadData object when download gets added/removed. * RecalcSeedingRank & process if necessary. */ private class StartStopDMListener implements DownloadManagerListener { private DownloadTrackerListener download_tracker_listener; private DownloadListener download_listener; private DownloadActivationListener download_activation_listener; public StartStopDMListener() { download_tracker_listener = new StartStopDMTrackerListener(); download_listener = new StartStopDownloadListener(); download_activation_listener = new StartStopDownloadActivationListener(); } public void downloadAdded(Download download) { DefaultRankCalculator dlData = null; if (downloadDataMap.containsKey(download)) { dlData = (DefaultRankCalculator) downloadDataMap.get(download); } else { dlData = new DefaultRankCalculator(StartStopRulesDefaultPlugin.this, download); sortedArrayCache = null; downloadDataMap.put(download, dlData); download.addListener(download_listener); download.addTrackerListener(download_tracker_listener, false); download.addActivationListener(download_activation_listener); } if (dlData != null) { requestProcessCycle(dlData); if (bDebugLog) log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: downloadAdded, state: " + sStates.charAt(download.getState())); } } public void downloadRemoved(Download download) { download.removeListener(download_listener); download.removeTrackerListener(download_tracker_listener); download.removeActivationListener(download_activation_listener); if (downloadDataMap.containsKey(download)) { sortedArrayCache = null; downloadDataMap.remove(download); } requestProcessCycle(null); if (bDebugLog) log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: downloadRemoved"); } } private long changeCheckCount = 0; private long changeCheckTotalMS = 0; private long changeCheckMaxMS = 0; private class ChangeCheckerTimerTask implements TimerEventPerformer { long lLastRunTime = 0; public void perform(TimerEvent event) { long now = 0; // make sure process isn't running and stop it from running while we do stuff try { this_mon.enter(); now = SystemTime.getCurrentTime(); //System.out.println(SystemTime.getCurrentTime() - lLastRunTime); if (now > lLastRunTime && now - lLastRunTime < 1000) { return; } lLastRunTime = now; DefaultRankCalculator[] dlDataArray = (DefaultRankCalculator[]) downloadDataMap.values().toArray( new DefaultRankCalculator[0]); int iNumDLing = 0; int iNumCDing = 0; for (int i = 0; i < dlDataArray.length; i++) { if (dlDataArray[i].changeChecker()) { requestProcessCycle(dlDataArray[i]); } // Check DLs for change in activeness (speed threshold) // (The call sets somethingChanged it was changed) if (dlDataArray[i].getActivelyDownloading()) iNumDLing++; // Check Seeders for change in activeness (speed threshold) // (The call sets somethingChanged it was changed) if (dlDataArray[i].getActivelySeeding()) { iNumCDing++; } } int iMaxSeeders = calcMaxSeeders(iNumDLing); if (iNumCDing > iMaxSeeders) { requestProcessCycle(null); if (bDebugLog) log.log(LoggerChannel.LT_INFORMATION, "somethingChanged: More Seeding than limit"); } } finally { if (now > 0) { changeCheckCount++; long timeTaken = (SystemTime.getCurrentTime() - now); changeCheckTotalMS += timeTaken; if (timeTaken > changeCheckMaxMS) { changeCheckMaxMS = timeTaken; } } this_mon.exit(); } } } // ConfigurationListener public void configurationSaved() { reloadConfigParams(); } private void reloadConfigParams() { try { this_mon.enter(); int iNewRankType = plugin_config.getIntParameter("StartStopManager_iRankType"); minSpeedForActiveSeeding = plugin_config.getIntParameter("StartStopManager_iMinSpeedForActiveSeeding"); maxStalledSeeding = plugin_config.getIntParameter("StartStopManager_iMaxStalledSeeding"); if (maxStalledSeeding <= 0) { // insanity :) maxStalledSeeding = 999; } _maxActive = plugin_config.getIntParameter("max active torrents"); _maxActiveWhenSeedingEnabled = plugin_config.getBooleanParameter("StartStopManager_bMaxActiveTorrentsWhenSeedingEnabled"); _maxActiveWhenSeeding = plugin_config.getIntParameter("StartStopManager_iMaxActiveTorrentsWhenSeeding"); minDownloads = plugin_config.getIntParameter("min downloads"); maxDownloads = plugin_config.getIntParameter("max downloads"); numPeersAsFullCopy = plugin_config.getIntParameter("StartStopManager_iNumPeersAsFullCopy"); iFakeFullCopySeedStart = plugin_config.getIntParameter("StartStopManager_iFakeFullCopySeedStart"); bAutoReposition = plugin_config.getBooleanParameter("StartStopManager_bAutoReposition"); minTimeAlive = plugin_config.getIntParameter("StartStopManager_iMinSeedingTime") * 1000; bDebugLog = plugin_config.getBooleanParameter("StartStopManager_bDebugLog"); bAutoStart0Peers = plugin_config.getBooleanParameter("StartStopManager_bAutoStart0Peers"); globalDownloadLimit = plugin_config.getIntParameter("Max Download Speed KBs", 0); globalUploadLimit = plugin_config.getIntParameter("Max Upload Speed KBs", 0); globalUploadWhenSeedingLimit = plugin_config.getBooleanParameter("enable.seedingonly.upload.rate") ? plugin_config.getIntParameter("Max Upload Speed Seeding KBs", 0) : globalUploadLimit; bStopOnceBandwidthMet = plugin_config.getBooleanParameter("StartStopManager_bStopOnceBandwidthMet"); boolean move_top = plugin_config.getBooleanParameter("StartStopManager_bNewSeedsMoveTop"); plugin_config.setBooleanParameter( PluginConfig.CORE_PARAM_BOOLEAN_NEW_SEEDS_START_AT_TOP, move_top); if (iNewRankType != iRankType) { iRankType = iNewRankType; // shorten recalc for timed rank type, since the calculation is fast and we want to stop on the second if (iRankType == RANK_TIMED) { if (recalcSeedingRanksTask == null) { recalcSeedingRanksTask = new RecalcSeedingRanksTask(); SimpleTimer.addPeriodicEvent("StartStop:recalcSR", 1000, recalcSeedingRanksTask); } } else if (recalcSeedingRanksTask != null) { recalcSeedingRanksTask.cancel(); recalcSeedingRanksTask = null; } } /* // limit _maxActive and maxDownloads based on TheColonel's specs // maxActive = max_upload_speed / (slots_per_torrent * min_speed_per_peer) if (_maxActive > 0) { int iSlotsPerTorrent = plugin_config.getIntParameter("Max Uploads"); // TODO: Track upload speed, storing the max upload speed over a minute // and use that for "unlimited" setting, or huge settings (like 200) if (iSlotsPerTorrent > 0) { int iMinSpeedPerPeer = 3; // for now. TODO: config value int _maxActiveLimit = iMaxUploadSpeed / (iSlotsPerTorrent * iMinSpeedPerPeer); if (_maxActive > _maxActiveLimit) { _maxActive = _maxActiveLimit; plugin_config.setIntParameter(PluginConfig.CORE_PARAM_INT_MAX_ACTIVE, _maxActive); } } if (maxDownloads > _maxActive) { maxDownloads = _maxActive; plugin_config.setIntParameter(PluginConfig.CORE_PARAM_INT_MAX_DOWNLOADS, maxDownloads); } } */ // force a recalc on all downloads by setting SR to 0, scheduling // a recalc on next process, and requsting a process cycle Collection allDownloads = downloadDataMap.values(); DefaultRankCalculator[] dlDataArray = (DefaultRankCalculator[]) allDownloads.toArray(new DefaultRankCalculator[0]); for (int i = 0; i < dlDataArray.length; i++) { dlDataArray[i].getDownloadObject().setSeedingRank(0); } try { ranksToRecalc_mon.enter(); ranksToRecalc.addAll(allDownloads); } finally { ranksToRecalc_mon.exit(); } requestProcessCycle(null); if (bDebugLog) { log.log(LoggerChannel.LT_INFORMATION, "somethingChanged: config reload"); try { if (debugMenuItem == null) { final String DEBUG_MENU_ID = "StartStopRules.menu.viewDebug"; MenuItemListener menuListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (!(target instanceof TableRow)) return; TableRow tr = (TableRow) target; Object ds = tr.getDataSource(); if (!(ds instanceof Download)) return; DefaultRankCalculator dlData = (DefaultRankCalculator) downloadDataMap.get(ds); if (dlData != null) { if (bSWTUI) StartStopRulesDefaultPluginSWTUI.openDebugWindow(dlData); else pi.getUIManager().showTextMessage( null, null, "FP:\n" + dlData.sExplainFP + "\n" + "SR:" + dlData.sExplainSR + "\n" + "TRACE:\n" + dlData.sTrace); } } }; TableManager tm = pi.getUIManager().getTableManager(); TableContextMenuItem menu; menu = tm.addContextMenuItem( TableManager.TABLE_MYTORRENTS_COMPLETE, DEBUG_MENU_ID); menu.addListener(menuListener); menu = tm.addContextMenuItem( TableManager.TABLE_MYTORRENTS_INCOMPLETE, DEBUG_MENU_ID); menu.addListener(menuListener); } } catch (Throwable t) { Debug.printStackTrace(t); } } } finally { this_mon.exit(); } } private int calcMaxSeeders(int iDLs) { // XXX put in subtraction logic here int maxActive = getMaxActive(); if (maxActive == 0) { return 999999; } return maxActive - iDLs; } protected int getMaxActive() { if (!_maxActiveWhenSeedingEnabled) return (_maxActive); if (download_manager.isSeedingOnly()) { if (_maxActiveWhenSeeding <= _maxActive) return (_maxActiveWhenSeeding); // danger here if we are in a position where allowing more to start when seeding // allows a non-seeding download to start (looping occurs) Download[] downloads = download_manager.getDownloads(); boolean danger = false; for (int i = 0; i < downloads.length && !danger; i++) { Download download = downloads[i]; int state = download.getState(); if (state == Download.ST_DOWNLOADING || state == Download.ST_SEEDING || state == Download.ST_STOPPED || state == Download.ST_STOPPING || state == Download.ST_ERROR) { // not interesting, they can't potentially cause trouble } else { // look for incomplete files DiskManagerFileInfo[] files = download.getDiskManagerFileInfo(); for (int j = 0; j < files.length; j++) { DiskManagerFileInfo file = files[j]; if ((!file.isSkipped()) && file.getDownloaded() != file.getLength()) { danger = true; break; } } } } if (!danger) return (_maxActiveWhenSeeding); } return (_maxActive); } private class TotalsStats { // total Forced Seeding doesn't include stalled torrents int forcedSeeding = 0; int forcedSeedingNonFP = 0; int waitingToSeed = 0; int waitingToDL = 0; int downloading = 0; int activelyDLing = 0; int activelyCDing = 0; int complete = 0; int incompleteQueued = 0; int firstPriority = 0; int stalledSeeders = 0; int stalledFPSeeders = 0; int forcedActive = 0; /** * Indicate whether it's ok to start seeding. *

      * Seeding can start right away when there's no auto-ranking or we are on * timed ranking. Otherwise, we wait until one of the following happens: *

        *
      • Any non-stopped/errored torrent gets a scrape result AND it's after * {@link #MIN_SEEDING_STARTUP_WAIT} *
      • All scrape results come in for completed, non-stopped/errored torrent *
      • Any completed non-stopped/errored torrent is FP *
      • Any torrent has 0 seeds (which, in most cases means it's the highest * rank) *
      *

      * If none of the above happen, then after {@link #MIN_FIRST_SCRAPE_WAIT}, * the flag will turned on. */ // not a total :) boolean bOkToStartSeeding; int maxSeeders; int maxActive; int maxTorrents; public int maxUploadSpeed() { return downloading == 0 ? globalUploadWhenSeedingLimit : globalUploadLimit; } /** * Default Constructor * * @param dlDataArray list of download data (rank calculators) objects * to base calculations on. */ public TotalsStats(DefaultRankCalculator[] dlDataArray) { bOkToStartSeeding = (iRankType == RANK_NONE) || (iRankType == RANK_TIMED) || (SystemTime.getCurrentTime() - startedOn > MIN_FIRST_SCRAPE_WAIT); // count the # of ok scrapes when !bOkToStartSeeding, and flip to true // if all scrapes for non-stopped/errored completes are okay. int totalOKScrapes = 0; // - Build a SeedingRank list for sorting // - Build Count Totals // - Do anything that doesn't need to be done in Queued order for (int i = 0; i < dlDataArray.length; i++) { DefaultRankCalculator dlData = dlDataArray[i]; if (dlData == null) { continue; } Download download = dlData.getDownloadObject(); int state = download.getState(); // No stats colllected on error or stopped torrents if (state == Download.ST_ERROR || state == Download.ST_STOPPED) { continue; } boolean completed = download.isComplete(); boolean bIsFirstP = false; // Count forced seedings as using a slot // Don't count forced downloading as using a slot if (!completed && download.isForceStart()) continue; if (completed) { // Only used when !bOkToStartSeeding.. set only to make compiler happy boolean bScrapeOk = true; if (!bOkToStartSeeding) { bScrapeOk = scrapeResultOk(download); if (calcSeedsNoUs(download) == 0 && bScrapeOk) bOkToStartSeeding = true; else if ((download.getSeedingRank() > 0) && (state == Download.ST_QUEUED || state == Download.ST_READY) && (SystemTime.getCurrentTime() - startedOn > MIN_SEEDING_STARTUP_WAIT)) bOkToStartSeeding = true; } complete++; if (!bOkToStartSeeding && bScrapeOk) totalOKScrapes++; if (dlData.isFirstPriority()) { if (!bOkToStartSeeding) bOkToStartSeeding = true; firstPriority++; bIsFirstP = true; } if (dlData.getActivelySeeding()) { if (dlData.isForceActive()) { forcedActive++; } activelyCDing++; if (download.isForceStart()) { forcedSeeding++; if (!bIsFirstP) forcedSeedingNonFP++; } } else if (state == Download.ST_SEEDING) { if (bIsFirstP) { stalledFPSeeders++; } stalledSeeders++; } if (state == Download.ST_READY || state == Download.ST_WAITING || state == Download.ST_PREPARING) { waitingToSeed++; } } else { // !completed if (state == Download.ST_DOWNLOADING) { downloading++; if (dlData.getActivelyDownloading()) activelyDLing++; } if (state == Download.ST_READY || state == Download.ST_WAITING || state == Download.ST_PREPARING) { waitingToDL++; } else if (state == Download.ST_QUEUED) { incompleteQueued++; } //if state } // if completionLevel } // for if (!bOkToStartSeeding && totalOKScrapes == complete) bOkToStartSeeding = true; maxSeeders = calcMaxSeeders(activelyDLing + waitingToDL); maxActive = getMaxActive(); if (maxActive == 0) { maxTorrents = 9999; } else if (maxUploadSpeed() == 0) { maxTorrents = maxActive + 4; } else { // Don't allow more "seeding/downloading" torrents than there is enough // bandwidth for. There needs to be enough bandwidth for at least // each torrent to get to its minSpeedForActiveSeeding // (we buffer it at 2x just to be safe). int minSpeedPerActive = (minSpeedForActiveSeeding * 2) / 1024; // Even more buffering/limiting. Limit to enough bandwidth for // each torrent to have potentially 3kbps. if (minSpeedPerActive < 3) minSpeedPerActive = 3; maxTorrents = (maxUploadSpeed() / minSpeedPerActive); // Allow user to do stupid things like have more slots than their // upload speed can handle if (maxTorrents < maxActive) maxTorrents = maxActive; //System.out.println("maxTorrents = " + maxTorrents + " = " + iMaxUploadSpeed + " / " + minSpeedPerActive); //System.out.println("totalTorrents = " + (activeSeedingCount + totalStalledSeeders + totalDownloading)); } } // constructor } /** * Running totals and stuff that gets used during a process run. * Split into class so complete/incomplete can be seperated into functions */ public class ProcessVars { /** Running count of torrents waiting or seeding, not including stalled */ int numWaitingOrSeeding; // Running Count int numWaitingOrDLing; // Running Count long accumulatedDownloadSpeed; long accumulatedUploadSpeed; /** * store whether there's a torrent higher in the list that is queued * We don't want to start a torrent lower in the list if there's a higherQueued */ boolean higherCDtoStart; boolean higherDLtoStart; /** * Tracks the position we should be at in the Completed torrents list * Updates position. */ int posComplete; boolean bStopAndQueued; int stalledSeeders; // Running Count } private long processCount = 0; private long processTotalMS = 0; private long processMaxMS = 0; private long processLastComplete = 0; private long processTotalGap = 0; private long processTotalRecalcs = 0; private long processTotalZeroRecalcs = 0; protected void process() { long now = 0; try { this_mon.enter(); now = SystemTime.getCurrentTime(); somethingChanged = false; Object[] recalcArray; try { ranksToRecalc_mon.enter(); recalcArray = ranksToRecalc.toArray(); ranksToRecalc.clear(); } finally { ranksToRecalc_mon.exit(); } for (int i = 0; i < recalcArray.length; i++) { DefaultRankCalculator rankObj = (DefaultRankCalculator) recalcArray[i]; if (bDebugLog) { long oldSR = rankObj.dl.getSeedingRank(); rankObj.recalcSeedingRank(); String s = "recalc seeding rank. old/new=" + oldSR + "/" + rankObj.dl.getSeedingRank(); log.log(rankObj.dl.getTorrent(), LoggerChannel.LT_INFORMATION, s); } else { rankObj.recalcSeedingRank(); } } processTotalRecalcs += recalcArray.length; if (recalcArray.length == 0) { processTotalZeroRecalcs++; } // pull the data into a local array, so we don't have to lock/synchronize DefaultRankCalculator[] dlDataArray; if(sortedArrayCache != null && sortedArrayCache.length == downloadDataMap.size()) dlDataArray = sortedArrayCache; else dlDataArray = sortedArrayCache = (DefaultRankCalculator[]) downloadDataMap.values().toArray( new DefaultRankCalculator[downloadDataMap.size()]); TotalsStats totals = new TotalsStats(dlDataArray); String[] mainDebugEntries = null; if (bDebugLog) { log.log(LoggerChannel.LT_INFORMATION, ">>process()"); mainDebugEntries = new String[] { "ok2Start=" + boolDebug(totals.bOkToStartSeeding), "tFrcdCding=" + totals.forcedSeeding, "actvCDs=" + totals.activelyCDing, "tW8tingToCd=" + totals.waitingToSeed, "tDLing=" + totals.downloading, "actvDLs=" + totals.activelyDLing, "tW8tingToDL=" + totals.waitingToDL, "tCom=" + totals.complete, "tIncQd=" + totals.incompleteQueued, "mxCdrs=" + totals.maxSeeders, "tFP=" + totals.firstPriority, "maxT=" + totals.maxTorrents, "maxA=" + totals.maxActive, }; } // Sort: SeedingRank Desc, Position Desc Arrays.sort(dlDataArray); ProcessVars vars = new ProcessVars(); // pre-included Forced Start torrents so a torrent "above" it doesn't // start (since normally it would start and assume the torrent below it // would stop) vars.numWaitingOrSeeding = totals.forcedSeeding; // Running Count vars.numWaitingOrDLing = 0; // Running Count vars.higherCDtoStart = false; vars.higherDLtoStart = false; vars.posComplete = 0; vars.stalledSeeders = 0; // Running Count; // Loop 2 of 2: // - Start/Stop torrents based on criteria for (int i = 0; i < dlDataArray.length; i++) { DefaultRankCalculator dlData = dlDataArray[i]; Download download = dlData.getDownloadObject(); vars.bStopAndQueued = false; dlData.sTrace = ""; // Initialize STATE_WAITING torrents if ((download.getState() == Download.ST_WAITING)) { try { download.initialize(); String s = "initialize: state is waiting"; log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, s); } catch (Exception ignore) { /*ignore*/ } if (bDebugLog && download.getState() == Download.ST_WAITING) { dlData.sTrace += "still in waiting state after initialize!\n"; } } if (bAutoReposition && (iRankType != RANK_NONE) && download.isComplete() && (totals.bOkToStartSeeding || totals.firstPriority > 0)) download.setPosition(++vars.posComplete); int state = download.getState(); // Never do anything to stopped entries if (state == Download.ST_STOPPING || state == Download.ST_STOPPED || state == Download.ST_ERROR) { continue; } if (download.isForceStart()) { if (state == Download.ST_STOPPED || state == Download.ST_QUEUED) { try { download.restart(); String s = "restart: isForceStart"; log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, s); dlData.sTrace += s + "\n"; } catch (DownloadException e) { } state = download.getState(); } if (state == Download.ST_READY) { try { download.start(); String s = "Start: isForceStart"; log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, s); dlData.sTrace += s + "\n"; } catch (DownloadException e) { /* ignore */ } } } // Handle incomplete DLs if (!download.isComplete()) { handleInCompleteDownload(dlData, vars, totals); } else { handleCompletedDownload(dlDataArray, dlData, vars, totals); } } // Loop 2/2 (Start/Stopping) if (bDebugLog) { String[] mainDebugEntries2 = new String[] { "ok2Start=" + boolDebug(totals.bOkToStartSeeding), "tFrcdCding=" + totals.forcedSeeding, "actvCDs=" + totals.activelyCDing, "tW8tingToCd=" + totals.waitingToSeed, "tDLing=" + totals.downloading, "actvDLs=" + totals.activelyDLing, "tW8tingToDL=" + totals.waitingToDL, "tCom=" + totals.complete, "tIncQd=" + totals.incompleteQueued, "mxCdrs=" + totals.maxSeeders, "tFP=" + totals.firstPriority, "maxT=" + totals.maxTorrents, "maxA=" + totals.maxActive, }; printDebugChanges("< 0) { processCount++; long timeTaken = (SystemTime.getCurrentTime() - now); if (bDebugLog) { log.log(LoggerChannel.LT_INFORMATION, "process() took " + timeTaken); } processTotalMS += timeTaken; if (timeTaken > processMaxMS) { processMaxMS = timeTaken; } if (processLastComplete > 0) { processTotalGap += (now - processLastComplete); } processLastComplete = now; } immediateProcessingScheduled = false; this_mon.exit(); } } // process() /** * @param dlData * @param vars * @param totals */ private void handleInCompleteDownload(DefaultRankCalculator dlData, ProcessVars vars, TotalsStats totals) { Download download = dlData.dl; int state = download.getState(); if (download.isForceStart()) { if (bDebugLog) { String s = "isForceStart.. rules skipped"; log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, s); dlData.sTrace += s + "\n"; } return; } // Don't mess with preparing torrents. they could be in the // middle of resume-data building, or file allocating. if (state == Download.ST_PREPARING) { vars.numWaitingOrDLing++; if (bDebugLog) { String s = "ST_PREPARING.. rules skipped. numW8tngorDLing=" + vars.numWaitingOrDLing; log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, s); dlData.sTrace += s + "\n"; } return; } int maxDLs = 0; if (totals.maxActive == 0) { maxDLs = maxDownloads; } else { int DLmax = 0; DLmax = totals.stalledFPSeeders + totals.forcedActive + totals.maxActive - totals.firstPriority - totals.forcedSeedingNonFP; maxDLs = (DLmax <= 0) ? 0 : maxDownloads - DLmax <= 0 ? maxDownloads : DLmax; } if (maxDLs < minDownloads) { maxDLs = minDownloads; } boolean bActivelyDownloading = dlData.getActivelyDownloading(); boolean globalDownLimitReached; boolean globalRateAdjustedActivelyDownloading; boolean fakedActively; if (bStopOnceBandwidthMet) { boolean isRunning = download.getState() == Download.ST_DOWNLOADING; globalDownLimitReached = globalDownloadLimit > 0 && vars.accumulatedDownloadSpeed/1024 > globalDownloadLimit * IGNORE_SLOT_THRESHOLD_FACTOR; globalRateAdjustedActivelyDownloading = bActivelyDownloading || (isRunning && globalDownLimitReached); fakedActively = globalRateAdjustedActivelyDownloading && !bActivelyDownloading; if(fakedActively) { totals.activelyDLing++; totals.maxSeeders = calcMaxSeeders(totals.activelyDLing + totals.waitingToDL); } } else { globalDownLimitReached = false; globalRateAdjustedActivelyDownloading = bActivelyDownloading; fakedActively = false; } if (bDebugLog) { String s = ">> DL state=" + sStates.charAt(download.getState()) + ";shareRatio=" + download.getStats().getShareRatio() + ";numW8tngorDLing=" + vars.numWaitingOrDLing + ";maxCDrs=" + totals.maxSeeders + ";forced=" + boolDebug(download.isForceStart()) + ";actvDLs=" + totals.activelyDLing + ";maxDLs=" + maxDLs + ";ActDLing=" + boolDebug(bActivelyDownloading) + ";globDwnRchd=" + boolDebug(globalDownLimitReached) + ";hgherQd=" + boolDebug(vars.higherDLtoStart) + ";isCmplt=" + boolDebug(download.isComplete()); log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, s); dlData.sTrace += s + "\n"; } // must use fresh getActivelyDownloading() in case state changed to // downloading if ((state == Download.ST_DOWNLOADING && globalRateAdjustedActivelyDownloading) || state == Download.ST_READY || state == Download.ST_WAITING || state == Download.ST_PREPARING) { vars.numWaitingOrDLing++; } if (state == Download.ST_READY || state == Download.ST_DOWNLOADING || state == Download.ST_WAITING) { // Stop torrent if over limit boolean bOverLimit = vars.numWaitingOrDLing > maxDLs || (vars.numWaitingOrDLing >= maxDLs && vars.higherDLtoStart); boolean bDownloading = state == Download.ST_DOWNLOADING; if ((maxDownloads != 0) && bOverLimit && (globalRateAdjustedActivelyDownloading || !bDownloading || (bDownloading && totals.maxActive != 0 && !globalRateAdjustedActivelyDownloading && totals.activelyCDing + totals.activelyDLing >= totals.maxActive) ) ) { try { if (bDebugLog) { String s = " stopAndQueue: " + vars.numWaitingOrDLing + " waiting or downloading, when limit is " + maxDLs + "(" + maxDownloads + ")"; if (vars.higherDLtoStart) { s += " and higher DL is starting"; } log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, s); dlData.sTrace += s + "\n"; } download.stopAndQueue(); // reduce counts vars.numWaitingOrDLing--; if (state == Download.ST_DOWNLOADING) { totals.downloading--; if (bActivelyDownloading || fakedActively) totals.activelyDLing--; } else { totals.waitingToDL--; } totals.maxSeeders = calcMaxSeeders(totals.activelyDLing + totals.waitingToDL); } catch (Exception ignore) { /* ignore */ } state = download.getState(); } else if (bDebugLog) { String s = "NOT queuing: "; if (maxDownloads == 0) { s += "maxDownloads = " + maxDownloads; } else if (!bOverLimit) { s += "not over limit. numWaitingOrDLing(" + vars.numWaitingOrDLing + ") <= maxDLs(" + maxDLs + ")"; } else if (!bActivelyDownloading || bDownloading) { s += "not actively downloading"; } else if (totals.maxActive == 0) { s += "unlimited active allowed (set)"; } else { s += "# active(" + (totals.activelyCDing + totals.activelyDLing) + ") < maxActive(" + totals.maxActive + ")"; } log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, s); dlData.sTrace += s + "\n"; } } if (state == Download.ST_READY) { if ((maxDownloads == 0) || (totals.activelyDLing < maxDLs)) { try { if (bDebugLog) { String s = " start: READY && activelyDLing (" + totals.activelyDLing + ") < maxDLs (" + maxDownloads + ")"; log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, s); dlData.sTrace += s + "\n"; } download.start(); // adjust counts totals.waitingToDL--; totals.activelyDLing++; totals.maxSeeders = calcMaxSeeders(totals.activelyDLing + totals.waitingToDL); } catch (Exception ignore) { /*ignore*/ } state = download.getState(); } } if (state == Download.ST_QUEUED) { if ((maxDownloads == 0) || (vars.numWaitingOrDLing < maxDLs)) { try { if (bDebugLog) { String s = " restart: QUEUED && numWaitingOrDLing (" + vars.numWaitingOrDLing + ") < maxDLS (" + maxDLs + ")"; log.log(LoggerChannel.LT_INFORMATION, s); dlData.sTrace += s + "\n"; } download.restart(); // increase counts vars.numWaitingOrDLing++; totals.waitingToDL++; totals.maxSeeders = calcMaxSeeders(totals.activelyDLing + totals.waitingToDL); } catch (Exception ignore) {/*ignore*/ } state = download.getState(); } } int oldState = state; state = download.getState(); if (oldState != state) { if (bDebugLog) { log.log(LoggerChannel.LT_INFORMATION, ">> somethingChanged: state"); } somethingChanged = true; } if (download.getSeedingRank() >= 0 && (state == Download.ST_QUEUED || state == Download.ST_READY || state == Download.ST_WAITING || state == Download.ST_PREPARING)) { vars.higherDLtoStart = true; } if (bDebugLog) { String s = "<< DL state=" + sStates.charAt(download.getState()) + ";shareRatio=" + download.getStats().getShareRatio() + ";numW8tngorDLing=" + vars.numWaitingOrDLing + ";maxCDrs=" + totals.maxSeeders + ";forced=" + boolDebug(download.isForceStart()) + ";actvDLs=" + totals.activelyDLing + ";hgherQd=" + boolDebug(vars.higherDLtoStart) + ";ActDLing=" + boolDebug(dlData.getActivelyDownloading()); log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION, s); dlData.sTrace += s + "\n"; } if (bStopOnceBandwidthMet) { vars.accumulatedDownloadSpeed += download.getStats().getDownloadAverage(); vars.accumulatedUploadSpeed += download.getStats().getUploadAverage(); } } /** * Process Completed (Seeding) downloads, starting and stopping as needed * * @param dlDataArray All download data (rank objects) we handle * @param dlData Current download data (rank object) we are processing * @param vars Running calculations * @param totals Summary values used in logic */ private void handleCompletedDownload(DefaultRankCalculator[] dlDataArray, DefaultRankCalculator dlData, ProcessVars vars, TotalsStats totals) { if (!totals.bOkToStartSeeding) return; Download download = dlData.dl; int state = download.getState(); boolean stateReadyOrSeeding = state == Download.ST_READY || state == Download.ST_SEEDING; String[] debugEntries = null; String sDebugLine = ""; // Queuing process: // 1) Torrent is Queued (Stopped) // 2) Slot becomes available // 3) Queued Torrent changes to Waiting // 4) Waiting Torrent changes to Ready // 5) Ready torrent changes to Seeding (with startDownload) // 6) Trigger stops Seeding torrent // a) Queue Ranking drops // b) User pressed stop // c) other // 7) Seeding Torrent changes to Queued. Go to step 1. int numPeers = dlData.lastModifiedScrapeResultPeers; boolean isFP = false; if (bDebugLog) { isFP = dlData.isFirstPriority(); debugEntries = new String[] { "CD state=" + sStates.charAt(state), "shareR=" + download.getStats().getShareRatio(), "nWorCDing=" + vars.numWaitingOrSeeding, "nWorDLing=" + vars.numWaitingOrDLing, "sr=" + download.getSeedingRank(), "hgherQd=" + boolDebug(vars.higherCDtoStart), "maxCDrs=" + totals.maxSeeders, "FP=" + boolDebug(isFP), "nActCDing=" + totals.activelyCDing, "ActCDing=" + boolDebug(dlData.getActivelySeeding()), "nSeeds=" + dlData.lastModifiedScrapeResultSeeds, "nPeers=" + dlData.lastModifiedScrapeResultPeers }; } try { boolean bScrapeOk = dlData.lastScrapeResultOk; // Ignore rules and other auto-starting rules do not apply when // bAutoStart0Peers and peers == 0. So, handle starting 0 peers // right at the beginning, and loop early if (bAutoStart0Peers && numPeers == 0 && bScrapeOk) { if (state == Download.ST_QUEUED) { try { if (bDebugLog) sDebugLine += "\nrestart() 0Peers"; download.restart(); // set to Waiting totals.waitingToSeed++; vars.numWaitingOrSeeding++; state = download.getState(); if (state == Download.ST_READY) { if (bDebugLog) sDebugLine += "\nstart(); 0Peers"; download.start(); totals.activelyCDing++; } } catch (Exception ignore) {/*ignore*/ } } if (state == Download.ST_READY) { try { if (bDebugLog) sDebugLine += "\nstart(); 0Peers"; download.start(); totals.activelyCDing++; vars.numWaitingOrSeeding++; } catch (Exception ignore) {/*ignore*/ } } return; } int rank = download.getSeedingRank(); // Short Circuit: if rank is set to IGNORED, we can skip everything // except when: // (1) torrent is force started // (2) the torrent is in ready or seeding state (we have to stop the torrent) // (3) we auto start 0 peers if (rank < DefaultRankCalculator.SR_IGNORED_LESS_THAN && !download.isForceStart() && !stateReadyOrSeeding && !bAutoStart0Peers) { if (bDebugLog) { sDebugLine += "\n Skip !forceStart"; int idx = rank * -1; if (idx < DefaultRankCalculator.SR_NEGATIVE_DEBUG.length) { sDebugLine += " && " + DefaultRankCalculator.SR_NEGATIVE_DEBUG[idx]; } } return; } // Short Circuit: if seed higher in the queue is marked to start, // we can skip everything, except when: // (1) torrent is force started // (2) we auto start 0 peers // (3) the torrent is in ready or seeding state (we have to stop the torrent) if (vars.higherCDtoStart && !download.isForceStart() && !bAutoStart0Peers && !stateReadyOrSeeding) { sDebugLine += " a torrent with a higher rank is queued or starting"; } if (bDebugLog && bAutoStart0Peers && numPeers == 0 && !bScrapeOk && (state == Download.ST_QUEUED || state == Download.ST_READY)) { sDebugLine += "\n NOT starting 0 Peer torrent because scrape isn't ok"; } if (!bDebugLog) { // In debug mode, we already calculated FP isFP = dlData.isFirstPriority(); } boolean bActivelySeeding = dlData.getActivelySeeding(); boolean globalDownLimitReached; boolean globalUpLimitReached; boolean globalRateAdjustedActivelySeeding; boolean fakedActively; if (bStopOnceBandwidthMet) { boolean isRunning = download.getState() == Download.ST_SEEDING; globalUpLimitReached = totals.maxUploadSpeed() > 0 && vars.accumulatedUploadSpeed/1024 > totals.maxUploadSpeed() * IGNORE_SLOT_THRESHOLD_FACTOR; globalDownLimitReached = globalDownloadLimit > 0 && vars.accumulatedDownloadSpeed/1024 > globalDownloadLimit * IGNORE_SLOT_THRESHOLD_FACTOR; globalRateAdjustedActivelySeeding = bActivelySeeding || (isRunning && (globalUpLimitReached || globalDownLimitReached)); fakedActively = globalRateAdjustedActivelySeeding && !bActivelySeeding; if(fakedActively) totals.activelyCDing++; } else { globalUpLimitReached = false; globalRateAdjustedActivelySeeding = bActivelySeeding; globalDownLimitReached = false; fakedActively = false; } if (state == Download.ST_SEEDING && !bActivelySeeding) { vars.stalledSeeders++; } // Is it OK to set this download to a queued state? // It is if: // 1) It is either READY or SEEDING; and // 2) It is either one of the following; and // a) Not a first priority torrent; or // b) There is a limit to the number of active torrents, and the number of // waiting and seeding torrents is already higher (or equal to) the number // of maximum allowed active torrents (taking away the number of minimum // required downloads). // // So I understand that to mean - it isn't first priority and leaving // this torrent running would mean that there aren't enough slots to // fulfil the minimum downloads requirement, because there are so many // torrents seeding (or waiting to seed) already. Or, in the case there // is no minimum downloads requirement - it's just overrun the maximum // active torrents count. // // 3) It hasn't been force started. boolean okToQueue = stateReadyOrSeeding && (!isFP || (isFP && ((totals.maxActive != 0 && vars.numWaitingOrSeeding >= totals.maxActive - minDownloads)))) //&& (!isFP || (isFP && ((vars.numWaitingOrSeeding >= totals.maxSeeders) || (!bActivelySeeding && (vars.numWaitingOrSeeding + totals.totalStalledSeeders) >= totals.maxSeeders))) ) && (!download.isForceStart()); // in RANK_TIMED mode, we use minTimeAlive for rotation time, so // skip check // XXX do we want changes to take effect immediately ? if (okToQueue && (state == Download.ST_SEEDING) && iRankType != RANK_TIMED) { long timeAlive = (SystemTime.getCurrentTime() - download.getStats().getTimeStarted()); okToQueue = (timeAlive >= minTimeAlive); if (!okToQueue && bDebugLog) sDebugLine += "\n Torrent can't be stopped yet, timeAlive(" + timeAlive + ") < minTimeAlive(" + minTimeAlive + ")"; } if (state != Download.ST_QUEUED && // Short circuit. (state == Download.ST_READY || state == Download.ST_WAITING || state == Download.ST_PREPARING || // Forced Start torrents are pre-included in count (state == Download.ST_SEEDING && globalRateAdjustedActivelySeeding && !download.isForceStart()))) { vars.numWaitingOrSeeding++; if (bDebugLog) sDebugLine += "\n Torrent is waiting or seeding"; } // Note: First Priority are sorted to the top, // so they will always start first // XXX Change to waiting if queued and we have an open slot if (!okToQueue && (state == Download.ST_QUEUED) && (totals.maxActive == 0 || vars.numWaitingOrSeeding < totals.maxSeeders) //&& (totals.maxActive == 0 || (activeSeedingCount + activeDLCount) < totals.maxActive) && && (rank >= DefaultRankCalculator.SR_IGNORED_LESS_THAN) && (vars.stalledSeeders < maxStalledSeeding) && !vars.higherCDtoStart) { try { if (bDebugLog) sDebugLine += "\n restart: ok2Q=" + okToQueue + "; QUEUED && numWaitingOrSeeding( " + vars.numWaitingOrSeeding + ") < maxSeeders (" + totals.maxSeeders + ")"; download.restart(); // set to Waiting okToQueue = false; totals.waitingToSeed++; vars.numWaitingOrSeeding++; if (iRankType == RANK_TIMED) dlData.recalcSeedingRank(); } catch (Exception ignore) {/*ignore*/ } state = download.getState(); } else if (bDebugLog && state == Download.ST_QUEUED) { sDebugLine += "\n NOT restarting:"; if (rank < DefaultRankCalculator.SR_IGNORED_LESS_THAN) { sDebugLine += " torrent is being ignored"; int idx = rank * -1; if (idx < DefaultRankCalculator.SR_NEGATIVE_DEBUG.length) { sDebugLine += ": " + DefaultRankCalculator.SR_NEGATIVE_DEBUG[idx]; } } else if (vars.higherCDtoStart) { sDebugLine += " a torrent with a higher rank is queued or starting"; } else { if (okToQueue) sDebugLine += " no starting of okToQueue'd;"; if (vars.numWaitingOrSeeding >= totals.maxSeeders) { sDebugLine += " at limit, numWaitingOrSeeding(" + vars.numWaitingOrSeeding + ") >= maxSeeders(" + totals.maxSeeders + ")"; } else if (vars.stalledSeeders >= maxStalledSeeding) { sDebugLine += " at limit, stalledSeeders(" + vars.stalledSeeders + ") >= maxStalledSeeding(" + maxStalledSeeding + ") "; } else { sDebugLine += "huh? qd=" + (state == Download.ST_QUEUED) + "; " + totals.maxActive + ";" + (vars.numWaitingOrSeeding < totals.maxSeeders) + ";" + (vars.stalledSeeders <= maxStalledSeeding) + ";ignore?" + (rank >= DefaultRankCalculator.SR_IGNORED_LESS_THAN); } } } boolean bForceStop = false; // Start download if ready and slot is available if (state == Download.ST_READY && totals.activelyCDing < totals.maxSeeders) { if (rank >= DefaultRankCalculator.SR_IGNORED_LESS_THAN || download.isForceStart()) { try { if (bDebugLog) sDebugLine += "\n start: READY && total activelyCDing(" + totals.activelyCDing + ") < maxSeeders(" + totals.maxSeeders + ")"; download.start(); okToQueue = false; } catch (Exception ignore) { /*ignore*/ } state = download.getState(); totals.activelyCDing++; globalRateAdjustedActivelySeeding = bActivelySeeding = true; vars.numWaitingOrSeeding++; } else if (okToQueue) { // In between switching from STATE_WAITING and STATE_READY, // and ignore rule was met, so move it back to Queued bForceStop = true; } } // if there's more torrents waiting/seeding than our max, or if // there's a higher ranked torrent queued, stop this one if (okToQueue || bForceStop) { boolean okToStop = bForceStop; if (!okToStop) { // break up the logic into variables to make more readable boolean bOverLimit = vars.numWaitingOrSeeding > totals.maxSeeders || (!bActivelySeeding && vars.stalledSeeders > maxStalledSeeding) || (vars.numWaitingOrSeeding >= totals.maxSeeders && vars.higherCDtoStart); boolean bSeeding = state == Download.ST_SEEDING; // not checking AND (at limit of seeders OR rank is set to ignore) AND // (Actively Seeding OR StartingUp OR Seeding a non-active download) okToStop = !download.isChecking() && (bOverLimit || rank < DefaultRankCalculator.SR_IGNORED_LESS_THAN) && (globalRateAdjustedActivelySeeding || !bSeeding || (!globalRateAdjustedActivelySeeding && bSeeding)); if (bDebugLog) { if (okToStop) { sDebugLine += "\n stopAndQueue: "; if (bOverLimit) { if (vars.higherCDtoStart) { sDebugLine += "higherQueued (it should be seeding instead of this one)"; } else if (!bActivelySeeding && vars.stalledSeeders > totals.maxSeeders) { sDebugLine += "over stale seeds limit"; } else { sDebugLine += "over limit"; } } else if (rank < DefaultRankCalculator.SR_IGNORED_LESS_THAN) sDebugLine += "ignoreRule met"; sDebugLine += " && "; if (bActivelySeeding) sDebugLine += "activelySeeding"; else if (!bSeeding) sDebugLine += "not SEEDING"; else if (!bActivelySeeding && bSeeding) sDebugLine += "SEEDING, but not actively"; } } else { sDebugLine += "\n NOT queuing: "; if (download.isChecking()) sDebugLine += "can't auto-queue a checking torrent"; else if (!bOverLimit) sDebugLine += "not over limit. numWaitingOrSeeding(" + vars.numWaitingOrSeeding + ") <= maxSeeders(" + totals.maxSeeders + ")"; else sDebugLine += "bActivelySeeding=" + bActivelySeeding + ";bSeeding" + bSeeding; } } else { if (bDebugLog) sDebugLine += "\n Forcing a stop.."; } if (okToStop) { try { if (state == Download.ST_READY) totals.waitingToSeed--; download.stopAndQueue(); vars.bStopAndQueued = true; // okToQueue only allows READY and SEEDING state.. and in both cases // we have to reduce counts if (bActivelySeeding || fakedActively) { totals.activelyCDing--; bActivelySeeding = false; } if(globalRateAdjustedActivelySeeding) { vars.numWaitingOrSeeding--; globalRateAdjustedActivelySeeding = false; } // force stop allows READY states in here, so adjust counts if (state == Download.ST_READY) totals.waitingToSeed--; } catch (Exception ignore) { /*ignore*/ } state = download.getState(); } } // move completed timed rank types to bottom of the list if (vars.bStopAndQueued && iRankType == RANK_TIMED) { for (int j = 0; j < dlDataArray.length; j++) { Download dl = dlDataArray[j].getDownloadObject(); int sr = dl.getSeedingRank(); if (sr > 0 && sr < DefaultRankCalculator.SR_TIMED_QUEUED_ENDS_AT) { // Move everyone up // We always start by setting SR to SR_TIMED_QUEUED_ENDS_AT - position // then, the torrent with the biggest starts seeding which is // (SR_TIMED_QUEUED_ENDS_AT - 1), leaving a gap. // when it's time to stop the torrent, move everyone up, and put // us at the end dl.setSeedingRank(sr + 1); } } rank = DefaultRankCalculator.SR_TIMED_QUEUED_ENDS_AT - totals.complete; download.setSeedingRank(rank); } state = download.getState(); if (rank >= 0 && (state == Download.ST_QUEUED || state == Download.ST_READY || state == Download.ST_WAITING || state == Download.ST_PREPARING)) { vars.higherCDtoStart = true; } } finally { if (bDebugLog) { String[] debugEntries2 = new String[] { "CD state=" + sStates.charAt(download.getState()), "shareR=" + download.getStats().getShareRatio(), "nWorCDing=" + vars.numWaitingOrSeeding, "nWorDLing=" + vars.numWaitingOrDLing, "sr=" + download.getSeedingRank(), "hgherQd=" + boolDebug(vars.higherCDtoStart), "maxCDrs=" + totals.maxSeeders, "FP=" + boolDebug(isFP), "nActCDing=" + totals.activelyCDing, "ActCDing=" + boolDebug(dlData.getActivelySeeding()), "nSeeds=" + dlData.lastModifiedScrapeResultSeeds, "nPeers=" + dlData.lastModifiedScrapeResultPeers }; printDebugChanges("", debugEntries, debugEntries2, sDebugLine, " ", true, dlData); } } if (bStopOnceBandwidthMet) { vars.accumulatedUploadSpeed += download.getStats().getUploadAverage(); } } private String boolDebug(boolean b) { return b ? "Y" : "N"; } private void printDebugChanges(String sPrefixFirstLine, String[] oldEntries, String[] newEntries, String sDebugLine, String sPrefix, boolean bAlwaysPrintNoChangeLine, DefaultRankCalculator dlData) { boolean bAnyChanged = false; String sDebugLineNoChange = sPrefixFirstLine; StringBuffer sDebugLineOld = new StringBuffer(120); StringBuffer sDebugLineNew = new StringBuffer(120); for (int j = 0; j < oldEntries.length; j++) { if (oldEntries[j].equals(newEntries[j])) sDebugLineNoChange += oldEntries[j] + ";"; else { sDebugLineOld.append(oldEntries[j]);sDebugLineOld.append(";"); sDebugLineNew.append(newEntries[j]);sDebugLineNew.append(";"); bAnyChanged = true; } } String sDebugLineOut = ((bAlwaysPrintNoChangeLine || bAnyChanged) ? sDebugLineNoChange : "") + (bAnyChanged ? "\nOld:" + sDebugLineOld + "\nNew:" + sDebugLineNew : "") + sDebugLine; if (!sDebugLineOut.equals("")) { String[] lines = sDebugLineOut.split("\n"); for (int i = 0; i < lines.length; i++) { String s = sPrefix + ((i > 0) ? " " : "") + lines[i]; if (dlData == null) { log.log(LoggerChannel.LT_INFORMATION, s); } else { log.log(dlData.dl.getTorrent(), LoggerChannel.LT_INFORMATION, s); dlData.sTrace += s + "\n"; } } } } /** * Get # of peers not including us * */ public int calcPeersNoUs(Download download) { int numPeers = 0; DownloadScrapeResult sr = download.getLastScrapeResult(); if (sr.getScrapeStartTime() > 0) { numPeers = sr.getNonSeedCount(); // If we've scraped after we started downloading // Remove ourselves from count if ((numPeers > 0) && (download.getState() == Download.ST_DOWNLOADING) && (sr.getScrapeStartTime() > download.getStats().getTimeStarted())) numPeers--; } if (numPeers == 0) { // Fallback to the # of peers we know of DownloadAnnounceResult ar = download.getLastAnnounceResult(); if (ar != null && ar.getResponseType() == DownloadAnnounceResult.RT_SUCCESS) numPeers = ar.getNonSeedCount(); if (numPeers == 0) { DownloadActivationEvent activationState = download.getActivationState(); if (activationState != null) { numPeers = activationState.getActivationCount(); } } } return numPeers; } private boolean scrapeResultOk(Download download) { DownloadScrapeResult sr = download.getLastScrapeResult(); return (sr.getResponseType() == DownloadScrapeResult.RT_SUCCESS); } /** Get # of seeds, not including us, AND including fake full copies * * @param download Download to get # of seeds for * @return seed count */ public int calcSeedsNoUs(Download download) { return calcSeedsNoUs(download, calcPeersNoUs(download)); } /** Get # of seeds, not including us, AND including fake full copies * * @param download Download to get # of seeds for * @param numPeers # peers we know of, required to calculate Fake Full Copies * @return seed count */ public int calcSeedsNoUs(Download download, int numPeers) { int numSeeds = 0; DownloadScrapeResult sr = download.getLastScrapeResult(); if (sr.getScrapeStartTime() > 0) { long seedingStartedOn = download.getStats().getTimeStartedSeeding(); numSeeds = sr.getSeedCount(); // If we've scraped after we started seeding // Remove ourselves from count if ((numSeeds > 0) && (seedingStartedOn > 0) && (download.getState() == Download.ST_SEEDING) && (sr.getScrapeStartTime() > seedingStartedOn)) numSeeds--; } if (numSeeds == 0) { // Fallback to the # of seeds we know of DownloadAnnounceResult ar = download.getLastAnnounceResult(); if (ar != null && ar.getResponseType() == DownloadAnnounceResult.RT_SUCCESS) numSeeds = ar.getSeedCount(); } if (numPeersAsFullCopy != 0 && numSeeds >= iFakeFullCopySeedStart) numSeeds += numPeers / numPeersAsFullCopy; return numSeeds; } /** * Request that the startstop rules process. Used when it's known that * something has changed that will effect torrent's state/position/rank. */ private long processMergeCount = 0; public void requestProcessCycle(DefaultRankCalculator rankToRecalc) { if (rankToRecalc != null) { try { ranksToRecalc_mon.enter(); ranksToRecalc.add(rankToRecalc); } finally { ranksToRecalc_mon.exit(); } } if (somethingChanged) { processMergeCount++; } else { somethingChanged = true; } } public void generate(IndentWriter writer) { writer.println("StartStopRules Manager"); try { writer.indent(); writer.println("Started " + TimeFormatter.format100ths(SystemTime.getCurrentTime() - startedOn) + " ago"); writer.println("debugging = " + bDebugLog); writer.println("downloadDataMap size = " + downloadDataMap.size()); if (changeCheckCount > 0) { writer.println("changeCheck CPU ms: avg=" + (changeCheckTotalMS / changeCheckCount) + "; max = " + changeCheckMaxMS); } if (processCount > 0) { writer.println("# process cycles: " + processCount); writer.println("process CPU ms: avg=" + (processTotalMS / processCount) + "; max = " + processMaxMS); if (processCount > 1) { writer.println("process avg gap: " + (processTotalGap / ((processCount - 1))) + "ms"); } writer.println("Avg # recalcs per process cycle: " + (processTotalRecalcs / processCount)); if (processTotalZeroRecalcs > 0) { writer.println("# process cycle with 0 recalcs: " + processTotalZeroRecalcs); } } } catch (Exception e) { // ignore } finally { writer.exdent(); } } public void addListener(StartStopRulesFPListener listener) { listenersFP.add(listener); } public void removeListener(StartStopRulesFPListener listener) { listenersFP.remove(listener); } public List getFPListeners() { return listenersFP.getList(); } } // class ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesFPListener.javaazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesFPListener.ja0000644000175000017500000000404210736157152033443 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.startstoprules.defaultplugin; import org.gudy.azureus2.plugins.download.Download; /** * @author TuxPaper * @created Jun 11, 2007 * */ public class StartStopRulesFPListener { /** * This method should return true to force a download to be first priority. You can only use this * listener to force downloads to be first priority - you can't force downloads not to be * first priority - if you return false, then the other first priority settings and logic will be * used to determine its status. * * Listeners will not be called for all downloads - the following checks may prevent listeners * being called: * - Non persistent downloads * - STOPPED or ERROR state * - Incomplete downloads * * This means that listeners don't have to do these basic checks. * * The StringBuffer argument is intended to output debug information about why the item * is (or isn't) first priority. The item may be null if debugging is not enabled. It is * not mandatory to log to the buffer. */ public boolean isFirstPriority(Download download, int numSeeds, int numPeers, StringBuffer debug) { return false; } } azureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/0000755000175000017500000000000011310377326026626 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/0000755000175000017500000000000011310377630027441 5ustar adrianadrian././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/StartStopRulesDefaultPluginSWTUI.javaazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/StartStopRulesDefaul0000644000175000017500000001154410566510040033464 0ustar adrianadrian/* * Created on 11-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.startstoprules.defaultplugin.ui.swt; import java.util.Timer; import java.util.TimerTask; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import com.aelitis.azureus.plugins.startstoprules.defaultplugin.DefaultRankCalculator; import org.gudy.azureus2.plugins.PluginInterface; public class StartStopRulesDefaultPluginSWTUI { public StartStopRulesDefaultPluginSWTUI(PluginInterface plugin_interface) { plugin_interface.addConfigSection(new ConfigSectionQueue()); plugin_interface.addConfigSection(new ConfigSectionSeeding()); plugin_interface.addConfigSection(new ConfigSectionSeedingAutoStarting()); plugin_interface.addConfigSection(new ConfigSectionSeedingFirstPriority()); plugin_interface.addConfigSection(new ConfigSectionSeedingIgnore()); } public static void openDebugWindow(final DefaultRankCalculator dlData) { final Shell shell = new Shell(Display.getCurrent(), SWT.ON_TOP | SWT.SHELL_TRIM | SWT.TOOL | SWT.CLOSE); GridLayout layout = new GridLayout(); layout.numColumns = 4; GridData gd; shell.setLayout(layout); shell.setText("Debug for " + dlData.getDownloadObject().getName()); final Text txtFP = new Text(shell, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL); gd = new GridData(GridData.FILL_BOTH); gd.horizontalSpan = 4; txtFP.setLayoutData(gd); final Button btnAutoRefresh = new Button(shell, SWT.CHECK); btnAutoRefresh.setText("Auto-Refresh"); btnAutoRefresh.setLayoutData(new GridData()); final Button btnRefresh = new Button(shell, SWT.NONE); btnRefresh.setLayoutData(new GridData()); btnRefresh.setText("Refresh"); final Button btnToClip = new Button(shell, SWT.NONE); btnToClip.setLayoutData(new GridData()); btnToClip.setText("To Clipboard"); btnToClip.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event event) { new Clipboard(Display.getCurrent()).setContents( new Object[] { txtFP.getText() }, new Transfer[] { TextTransfer.getInstance() }); } }); final Label lbl = new Label(shell, SWT.NONE); gd = new GridData(GridData.FILL_HORIZONTAL); lbl.setLayoutData(gd); final TimerTask task = new TimerTask() { String lastText = ""; public String formatString() { return "FP:\n" + dlData.sExplainFP + "\n" + "SR:" + dlData.sExplainSR + "\n" + "TRACE:\n" + dlData.sTrace; } public void setText(final String s) { lastText = s; txtFP.setText(s); } public void run() { if (shell.isDisposed()) return; shell.getDisplay().syncExec(new Runnable() { public void run() { if (shell.isDisposed()) { return; } String s = formatString(); if (s.compareTo(lastText) != 0) { if (lastText.length() == 0 || btnAutoRefresh.getSelection() || btnRefresh.getData("Pressing") != null) setText(s); else lbl.setText("Information is outdated. Press refresh."); } else { lbl.setText(""); } } }); } }; btnAutoRefresh.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event event) { if (btnAutoRefresh.getSelection()) lbl.setText(""); task.run(); } }); btnRefresh.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event event) { btnRefresh.setData("Pressing", "1"); task.run(); btnRefresh.setData("Pressing", null); } }); shell.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { shell.dispose(); } } }); shell.setSize(550, 350); shell.open(); Timer timer = new Timer(true); timer.schedule(task, 0, 2000); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingFirstPriority.javaazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeeding0000644000175000017500000002202711247070356033424 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.plugins.startstoprules.defaultplugin.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.BooleanParameter; import org.gudy.azureus2.ui.swt.config.IntListParameter; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import com.aelitis.azureus.plugins.startstoprules.defaultplugin.DefaultRankCalculator; /** First Priority Specific options. * @author TuxPaper * @created Jan 12, 2004 */ public class ConfigSectionSeedingFirstPriority implements UISWTConfigSection { public String configSectionGetParentSection() { return "queue.seeding"; } public String configSectionGetName() { return "queue.seeding.firstPriority"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 0; } public Composite configSectionCreate(Composite parent) { // Seeding Automation Setup GridData gridData; GridLayout layout; Label label; Composite cArea, cArea1; Composite cFirstPriorityArea = new Composite(parent, SWT.NULL); layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; cFirstPriorityArea.setLayout(layout); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cFirstPriorityArea.setLayoutData(gridData); label = new Label(cFirstPriorityArea, SWT.WRAP); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; gridData.widthHint = 300; label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.label.seeding.firstPriority.info"); // ** Begin No Touch area // Group FP Composite cFP = new Group(cFirstPriorityArea, SWT.NULL); layout = new GridLayout(); layout.numColumns = 2; layout.verticalSpacing = 6; cFP.setLayout(layout); gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cFP.setLayoutData(gridData); Messages.setLanguageText(cFP, "ConfigView.label.seeding.firstPriority.FP"); // row cArea = new Composite(cFP, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 3; cArea.setLayout(layout); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan = 3; cArea.setLayoutData(gridData); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.firstPriority"); String fpLabels[] = { MessageText.getString("ConfigView.text.all"), MessageText.getString("ConfigView.text.any") }; int fpValues[] = { DefaultRankCalculator.FIRSTPRIORITY_ALL, DefaultRankCalculator.FIRSTPRIORITY_ANY }; new IntListParameter(cArea, "StartStopManager_iFirstPriority_Type", fpLabels, fpValues); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.firstPriority.following"); // row label = new Label(cFP, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.firstPriority.shareRatio"); String minQueueLabels[] = new String[55]; int minQueueValues[] = new int[55]; minQueueLabels[0] = "1:2 (" + 0.5 + ")"; minQueueValues[0] = 500; minQueueLabels[1] = "3:4 (" + 0.75 +")"; minQueueValues[1] = 750; minQueueLabels[2] = "1:1"; minQueueValues[2] = 1000; minQueueLabels[3] = "5:4 (" + 1.25 +")"; minQueueValues[3] = 1250; minQueueLabels[4] = "3:2 (" + 1.50 +")"; minQueueValues[4] = 1500; minQueueLabels[5] = "7:4 (" + 1.75 +")"; minQueueValues[5] = 1750; for (int i = 6; i < minQueueLabels.length; i++) { minQueueLabels[i] = i - 4 + ":1"; minQueueValues[i] = (i - 4) * 1000; } new IntListParameter(cFP, "StartStopManager_iFirstPriority_ShareRatio", minQueueLabels, minQueueValues); String sMinutes = MessageText.getString("ConfigView.text.minutes"); String sHours = MessageText.getString("ConfigView.text.hours"); // row label = new Label(cFP, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.firstPriority.DLMinutes"); String dlTimeLabels[] = new String[15]; int dlTimeValues[] = new int[15]; dlTimeLabels[0] = MessageText.getString("ConfigView.text.ignore"); dlTimeValues[0] = 0; for (int i = 1; i < dlTimeValues.length; i++) { dlTimeLabels[i] = "<= " + (i + 2) + " " + sHours ; dlTimeValues[i] = (i + 2) * 60; } new IntListParameter(cFP, "StartStopManager_iFirstPriority_DLMinutes", dlTimeLabels, dlTimeValues); label = new Label(cFirstPriorityArea, SWT.WRAP); // row label = new Label(cFP, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.firstPriority.seedingMinutes"); String seedTimeLabels[] = new String[15]; int seedTimeValues[] = new int[15]; seedTimeLabels[0] = MessageText.getString("ConfigView.text.ignore"); seedTimeValues[0] = 0; seedTimeLabels[1] = "<= 90 " + sMinutes; seedTimeValues[1] = 90; for (int i = 2; i < seedTimeValues.length; i++) { seedTimeLabels[i] = "<= " + i + " " + sHours ; seedTimeValues[i] = i * 60; } new IntListParameter(cFP, "StartStopManager_iFirstPriority_SeedingMinutes", seedTimeLabels, seedTimeValues); // Group Ignore FP Composite cIgnoreFP = new Group(cFirstPriorityArea, SWT.NULL); layout = new GridLayout(); layout.numColumns = 2; layout.verticalSpacing = 6; cIgnoreFP.setLayout(layout); gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL); cIgnoreFP.setLayoutData(gridData); Messages.setLanguageText(cIgnoreFP, "ConfigView.label.seeding.firstPriority.ignore"); // Ignore S:P Ratio label = new Label(cIgnoreFP, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.firstPriority.ignoreSPRatio"); String ignoreSPRatioLabels[] = new String[15]; int ignoreSPRatioValues[] = new int[15]; ignoreSPRatioLabels[0] = MessageText.getString("ConfigView.text.ignore"); ignoreSPRatioValues[0] = 0; for (int i = 1; i < ignoreSPRatioLabels.length; i++) { ignoreSPRatioLabels[i] = i * 10 + " " + ":1" ; ignoreSPRatioValues[i] = i * 10; } new IntListParameter(cIgnoreFP, "StartStopManager_iFirstPriority_ignoreSPRatio", 0, ignoreSPRatioLabels, ignoreSPRatioValues); // Ignore 0 Peers new BooleanParameter(cIgnoreFP, "StartStopManager_bFirstPriority_ignore0Peer", "ConfigView.label.seeding.firstPriority.ignore0Peer"); label = new Label(cIgnoreFP, SWT.NULL); // Ignore idle hours label = new Label(cIgnoreFP, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.firstPriority.ignoreIdleHours"); int[] availIdleHours = { 2, 3, 4, 5, 6, 7, 8, 12, 18, 24, 48, 72, 168 }; String ignoreIdleHoursLabels[] = new String[availIdleHours.length + 1]; int ignoreIdleHoursValues[] = new int[availIdleHours.length + 1]; ignoreIdleHoursLabels[0] = MessageText.getString("ConfigView.text.ignore"); ignoreIdleHoursValues[0] = 0; for (int i = 0; i < availIdleHours.length; i++) { ignoreIdleHoursLabels[i + 1] = availIdleHours[i] + " " + sHours; ignoreIdleHoursValues[i + 1] = availIdleHours[i]; } new IntListParameter(cIgnoreFP, "StartStopManager_iFirstPriority_ignoreIdleHours", 0, ignoreIdleHoursLabels, ignoreIdleHoursValues); // row cArea1 = new Composite(cIgnoreFP, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 2; cArea1.setLayout(layout); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan = 2; cArea1.setLayoutData(gridData); label = new Label(cArea1, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.firstPriority.ignore.info"); return cFirstPriorityArea; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeeding.javaazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeeding0000644000175000017500000001462511256315674033436 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.plugins.startstoprules.defaultplugin.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** Seeding Automation Specific options * @author TuxPaper * @created Jan 12, 2004 * * TODO: StartStopManager_fAddForSeedingULCopyCount */ public class ConfigSectionSeeding implements UISWTConfigSection { public String configSectionGetParentSection() { return "queue"; } public String configSectionGetName() { return "queue.seeding"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 0; } public Composite configSectionCreate(Composite parent) { // Seeding Automation Setup GridData gridData; GridLayout layout; Label label; Composite cSeeding = new Composite(parent, SWT.NULL); layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; cSeeding.setLayout(layout); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cSeeding.setLayoutData(gridData); // General Seeding Options label = new Label(cSeeding, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.minSeedingTime"); gridData = new GridData(); new IntParameter(cSeeding, "StartStopManager_iMinSeedingTime").setLayoutData(gridData); gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(cSeeding, "Disconnect Seed", "ConfigView.label.disconnetseed").setLayoutData(gridData); gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(cSeeding, "Use Super Seeding", "ConfigView.label.userSuperSeeding").setLayoutData(gridData); gridData = new GridData(); gridData.horizontalSpan = 2; new BooleanParameter(cSeeding, "StartStopManager_bAutoReposition", "ConfigView.label.seeding.autoReposition").setLayoutData(gridData); label = new Label(cSeeding, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.addForSeedingDLCopyCount"); gridData = new GridData(); new IntParameter(cSeeding, "StartStopManager_iAddForSeedingDLCopyCount").setLayoutData(gridData); label = new Label(cSeeding, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.numPeersAsFullCopy"); Composite cArea = new Composite(cSeeding, SWT.NULL); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 2; cArea.setLayout(layout); gridData = new GridData(); cArea.setLayoutData(gridData); gridData = new GridData(); final IntParameter paramFakeFullCopy = new IntParameter(cArea, "StartStopManager_iNumPeersAsFullCopy"); paramFakeFullCopy.setLayoutData(gridData); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.peers"); final Composite cFullCopyOptionsArea = new Composite(cSeeding, SWT.NULL); layout = new GridLayout(); layout.numColumns = 4; layout.marginWidth = 0; layout.marginHeight = 0; cFullCopyOptionsArea.setLayout(layout); gridData = new GridData(); gridData.horizontalIndent = 15; gridData.horizontalSpan = 2; cFullCopyOptionsArea.setLayoutData(gridData); label = new Label(cFullCopyOptionsArea, SWT.NULL); ImageLoader.getInstance().setLabelImage(label, "subitem"); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); label = new Label(cFullCopyOptionsArea, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.fakeFullCopySeedStart"); gridData = new GridData(); new IntParameter(cFullCopyOptionsArea, "StartStopManager_iFakeFullCopySeedStart").setLayoutData(gridData); label = new Label(cFullCopyOptionsArea, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeds"); final int iNumPeersAsFullCopy = COConfigurationManager.getIntParameter("StartStopManager_iNumPeersAsFullCopy"); controlsSetEnabled(cFullCopyOptionsArea.getChildren(), iNumPeersAsFullCopy != 0); paramFakeFullCopy.addChangeListener(new ParameterChangeAdapter() { public void parameterChanged(Parameter p, boolean caused_internally) { Utils.execSWTThread(new AERunnable() { public void runSupport() { try { int value = paramFakeFullCopy.getValue(); boolean enabled = (value != 0); if (cFullCopyOptionsArea.getEnabled() != enabled) { cFullCopyOptionsArea.setEnabled(enabled); controlsSetEnabled(cFullCopyOptionsArea.getChildren(), enabled); } } catch (Exception e) { } } }); } }); paramFakeFullCopy.getControl().addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { } }); return cSeeding; } private void controlsSetEnabled(Control[] controls, boolean bEnabled) { for(int i = 0 ; i < controls.length ; i++) { if (controls[i] instanceof Composite) controlsSetEnabled(((Composite)controls[i]).getChildren(), bEnabled); controls[i].setEnabled(bEnabled); } } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingIgnore.javaazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeeding0000644000175000017500000001363411256315674033435 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.plugins.startstoprules.defaultplugin.ui.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** Config Section for items that make us ignore torrents when seeding * @author TuxPaper * @created Jan 12, 2004 */ public class ConfigSectionSeedingIgnore implements UISWTConfigSection { public String configSectionGetParentSection() { return "queue.seeding"; } public String configSectionGetName() { return "queue.seeding.ignore"; } public void configSectionSave() { } public void configSectionDelete() { } public int maxUserMode() { return 0; } public Composite configSectionCreate(Composite parent) { // Seeding Automation Setup GridData gridData; GridLayout layout; Label label; Composite cIgnoreRules = new Composite(parent, SWT.NULL); layout = new GridLayout(); layout.numColumns = 3; layout.marginHeight = 0; cIgnoreRules.setLayout(layout); label = new Label(cIgnoreRules, SWT.WRAP); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 3; gridData.widthHint = 300; label.setLayoutData(gridData); Messages.setLanguageText(label, "ConfigView.label.autoSeedingIgnoreInfo"); //$NON-NLS-1$ Composite cIgnore = new Group(cIgnoreRules, SWT.NULL); layout = new GridLayout(); layout.numColumns = 3; layout.verticalSpacing = 6; cIgnore.setLayout(layout); gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cIgnore.setLayoutData(gridData); Messages.setLanguageText(cIgnore, "ConfigView.label.seeding.ignore"); label = new Label(cIgnore, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.ignoreSeeds"); //$NON-NLS-1$ gridData = new GridData(); new IntParameter(cIgnore, "StartStopManager_iIgnoreSeedCount", 0, 9999).setLayoutData(gridData); label = new Label(cIgnore, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeds"); label = new Label(cIgnore, SWT.WRAP); Messages.setLanguageText(label, "ConfigView.label.seeding.ignoreRatioPeers"); //$NON-NLS-1$ gridData = new GridData(); new IntParameter(cIgnore, "Stop Peers Ratio", 0, 9999).setLayoutData(gridData); label = new Label(cIgnore, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.peers"); Composite cArea = new Composite(cIgnore, SWT.NULL); layout = new GridLayout(); layout.numColumns = 4; layout.marginWidth = 0; layout.marginHeight = 0; cArea.setLayout(layout); gridData = new GridData(); gridData.horizontalIndent = 15; gridData.horizontalSpan = 3; cArea.setLayoutData(gridData); label = new Label(cArea, SWT.NULL); ImageLoader.getInstance().setLabelImage(label, "subitem"); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.fakeFullCopySeedStart"); gridData = new GridData(); new IntParameter(cArea, "StartStopManager_iIgnoreRatioPeersSeedStart", 0, 9999).setLayoutData(gridData); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeds"); // Share Ratio label = new Label(cIgnore, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.ignoreShareRatio"); gridData = new GridData(); gridData.widthHint = 50; new FloatParameter(cIgnore, "Stop Ratio", 1, -1, true, 1).setLayoutData(gridData); label = new Label(cIgnore, SWT.NULL); label.setText(":1"); cArea = new Composite(cIgnore, SWT.NULL); layout = new GridLayout(); layout.numColumns = 4; layout.marginWidth = 0; layout.marginHeight = 0; cArea.setLayout(layout); gridData = new GridData(); gridData.horizontalIndent = 15; gridData.horizontalSpan = 3; cArea.setLayoutData(gridData); label = new Label(cArea, SWT.NULL); ImageLoader.getInstance().setLabelImage(label, "subitem"); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeding.fakeFullCopySeedStart"); gridData = new GridData(); new IntParameter(cArea, "StartStopManager_iIgnoreShareRatioSeedStart", 0, 9999).setLayoutData(gridData); label = new Label(cArea, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.seeds"); // Ignore 0 Peers gridData = new GridData(); gridData.horizontalSpan = 3; new BooleanParameter(cIgnore, "StartStopManager_bIgnore0Peers", "ConfigView.label.seeding.ignore0Peers").setLayoutData(gridData); return cIgnoreRules; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionQueue.javaazureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionQueue.j0000644000175000017500000002064411256315674033372 0ustar adrianadrian/* * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.plugins.startstoprules.defaultplugin.ui.swt; import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.config.*; import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.ui.config.ConfigSection; /** General Queueing options * @author TuxPaper * @created Jan 12, 2004 */ public class ConfigSectionQueue implements UISWTConfigSection { public String configSectionGetParentSection() { return ConfigSection.SECTION_ROOT; } public int maxUserMode() { return 0; } /** * Create the "Queue" Tab in the Configuration view */ public Composite configSectionCreate(Composite parent) { GridData gridData; GridLayout layout; Label label; // main tab set up Composite cSection = new Composite(parent, SWT.NULL); gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); cSection.setLayoutData(gridData); layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; cSection.setLayout(layout); // row label = new Label(cSection, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.maxdownloads"); gridData = new GridData(); final IntParameter maxDLs = new IntParameter(cSection, "max downloads"); maxDLs.setLayoutData(gridData); // row label = new Label(cSection, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.maxactivetorrents"); gridData = new GridData(); final IntParameter maxActiv = new IntParameter(cSection, "max active torrents"); maxActiv.setLayoutData(gridData); final Composite cMaxActiveOptionsArea = new Composite(cSection, SWT.NULL); layout = new GridLayout(); layout.numColumns = 3; layout.marginWidth = 0; layout.marginHeight = 0; cMaxActiveOptionsArea.setLayout(layout); gridData = new GridData(); gridData.horizontalIndent = 15; gridData.horizontalSpan = 2; cMaxActiveOptionsArea.setLayoutData(gridData); ImageLoader imageLoader = ImageLoader.getInstance(); label = new Label(cMaxActiveOptionsArea, SWT.NULL); imageLoader.setLabelImage(label, "subitem"); gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); label.setLayoutData(gridData); gridData = new GridData(); BooleanParameter maxActiveWhenSeedingEnabled = new BooleanParameter( cMaxActiveOptionsArea, "StartStopManager_bMaxActiveTorrentsWhenSeedingEnabled", "ConfigView.label.queue.maxactivetorrentswhenseeding"); maxActiveWhenSeedingEnabled.setLayoutData(gridData); gridData = new GridData(); final IntParameter maxActivWhenSeeding = new IntParameter( cMaxActiveOptionsArea, "StartStopManager_iMaxActiveTorrentsWhenSeeding"); maxActivWhenSeeding.setLayoutData(gridData); // row label = new Label(cSection, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.mindownloads"); gridData = new GridData(); final IntParameter minDLs = new IntParameter(cSection, "min downloads"); minDLs.setLayoutData(gridData); minDLs.setMaximumValue(maxDLs.getValue() / 2); // change controllers for above items maxActiveWhenSeedingEnabled.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( maxActivWhenSeeding)); maxDLs.addChangeListener(new ParameterChangeAdapter() { public void parameterChanged(Parameter p, boolean caused_internally) { int iMaxDLs = maxDLs.getValue(); minDLs.setMaximumValue(iMaxDLs / 2); int iMinDLs = minDLs.getValue(); int iMaxActive = maxActiv.getValue(); if ((iMaxDLs == 0 || iMaxDLs > iMaxActive) && iMaxActive != 0) { maxActiv.setValue(iMaxDLs); } } }); maxActiv.addChangeListener(new ParameterChangeAdapter() { public void parameterChanged(Parameter p, boolean caused_internally) { int iMaxDLs = maxDLs.getValue(); int iMaxActive = maxActiv.getValue(); if ((iMaxDLs == 0 || iMaxDLs > iMaxActive) && iMaxActive != 0) { maxDLs.setValue(iMaxActive); } } }); // row final ArrayList values = new ArrayList(); int exp = 29; for(int val = 0; val <= 8*1024*1024;) { values.add(new Integer(val)); if(val < 256) val+=64; else if(val < 1024) val+=256; else if(val < 16*1024) val+=1024; else val = (int)(Math.pow(2, exp++/2) + (exp % 2 == 0 ? Math.pow(2, (exp-3)/2) : 0)); } String[] activeDLLabels = new String[values.size()]; int[] activeDLValues = new int[activeDLLabels.length]; label = new Label(cSection, SWT.NULL); Messages.setLanguageText(label, "ConfigView.label.minSpeedForActiveDL"); for(int i=0;i= 0) { if (dlData.getCachedIsFP()) sText += MessageText.getString("StartStopRules.firstPriority") + " "; if (iRankType == StartStopRulesDefaultPlugin.RANK_TIMED) { //sText += "" + sr + " "; if (sr > DefaultRankCalculator.SR_TIMED_QUEUED_ENDS_AT) { long timeStarted = dl.getStats().getTimeStartedSeeding(); long timeLeft; if (dl.isForceStart()) timeLeft = Constants.CRAPPY_INFINITY_AS_INT; else if (timeStarted <= 0) timeLeft = minTimeAlive; else timeLeft = (minTimeAlive - (SystemTime.getCurrentTime() - timeStarted)); sText += TimeFormatter.format(timeLeft / 1000); } else if (sr > 0) { sText += MessageText.getString("StartStopRules.waiting"); } } else if (sr > 0) { sText += String.valueOf(sr); } } else if (sr == DefaultRankCalculator.SR_FP0PEERS) sText = MessageText.getString("StartStopRules.FP0Peers"); else if (sr == DefaultRankCalculator.SR_FP_SPRATIOMET) sText = MessageText.getString("StartStopRules.SPratioMet"); else if (sr == DefaultRankCalculator.SR_RATIOMET) sText = MessageText.getString("StartStopRules.ratioMet"); else if (sr == DefaultRankCalculator.SR_NUMSEEDSMET) sText = MessageText.getString("StartStopRules.numSeedsMet"); else if (sr == DefaultRankCalculator.SR_NOTQUEUED) sText = ""; else if (sr == DefaultRankCalculator.SR_0PEERS) sText = MessageText.getString("StartStopRules.0Peers"); else if (sr == DefaultRankCalculator.SR_SHARERATIOMET) sText = MessageText.getString("StartStopRules.shareRatioMet"); else { sText = "ERR" + sr; } // Add a Star if it's before minTimeAlive if (SystemTime.getCurrentTime() - dl.getStats().getTimeStartedSeeding() < minTimeAlive) sText = "* " + sText; cell.setText(sText); if (bDebugLog) { cell.setToolTip("FP:\n" + dlData.sExplainFP + "\n" + "SR:" + dlData.sExplainSR + "\n" + "TRACE:\n" + dlData.sTrace); } else { cell.setToolTip(null); } } /* (non-Javadoc) * @see org.gudy.azureus2.core3.config.COConfigurationListener#configurationSaved() */ public void configurationSaved() { minTimeAlive = pluginConfig .getUnsafeIntParameter("StartStopManager_iMinSeedingTime") * 1000; iRankType = pluginConfig.getUnsafeIntParameter("StartStopManager_iRankType"); bDebugLog = pluginConfig.getUnsafeBooleanParameter("StartStopManager_bDebugLog"); } } azureus-4.3.0.6/com/aelitis/azureus/plugins/startstoprules/defaultplugin/DefaultRankCalculator.java0000644000175000017500000007215611237540714033302 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.startstoprules.defaultplugin; import java.util.Iterator; import java.util.List; import org.gudy.azureus2.core3.config.COConfigurationListener; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.PluginConfig; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadStats; import org.gudy.azureus2.plugins.logging.LoggerChannel; /** * @author TuxPaper * @created Dec 13, 2005 * */ public class DefaultRankCalculator implements Comparable { /** All of the First Priority rules must match */ public static final int FIRSTPRIORITY_ALL = 0; /** Any of the First Priority rules must match */ public static final int FIRSTPRIORITY_ANY = 1; /** * Force torrent to be "Actively Seeding/Downloading" for this many ms upon * start of torrent. */ private static final int FORCE_ACTIVE_FOR = 30000; /** * Wait XX ms before really changing activity (DL or CDing) state when * state changes via speed change */ private static final int ACTIVE_CHANGE_WAIT = 10000; /** Maximium ranking that a torrent can get using the SPRATIO ranking type */ private static int SPRATIO_BASE_LIMIT = 99999; /** * Amount to shift over the rank of the SEEDONLY ranking type, to make room * in case the user has fallback to SPRATIO set. */ private static int SEEDONLY_SHIFT = SPRATIO_BASE_LIMIT + 1; /** * For loading config settings */ private static COConfigurationListener configListener = null; // // Seeding Rank (SR) Limits and Values /** Rank that complete starts at (and incomplete ends at + 1) */ public static final int SR_COMPLETE_STARTS_AT = 1000000000; // billion /** Maximimum ranking for time queue mode. 1 unit is a second */ public static final int SR_TIMED_QUEUED_ENDS_AT = 999999; // 11.57 days /** Ranks below this value are for torrents to be ignored (moved to bottom & queued) */ public static final int SR_IGNORED_LESS_THAN = -1; /** Seeding Rank value when download is marked as not queued */ public static final int SR_NOTQUEUED = -2; /** Seeding Rank value when download is marked as S:P Ratio Met for FP */ public static final int SR_FP_SPRATIOMET = -3; /** Seeding Rank value when download is marked as P:1S Ratio Met */ public static final int SR_RATIOMET = -4; /** Seeding Rank value when download is marked as # Seeds Met */ public static final int SR_NUMSEEDSMET = -5; /** Seeding Rank value when download is marked as 0 Peers and FP */ public static final int SR_FP0PEERS = -6; /** Seeding Rank value when download is marked as 0 Peers */ public static final int SR_0PEERS = -7; /** Seeding Rank value when download is marked as Share Ratio Met */ public static final int SR_SHARERATIOMET = -8; public static final String[] SR_NEGATIVE_DEBUG = { "?", "Not Qd", "FP SPRatioMet", "Ratio Met", "# CDs Met", "FP 0 Peers", "0 Peers", "Share Ratio Met" }; private static final long STALE_REFRESH_INTERVAL = 1000 * 60; // // Static config values /** Ranking System to use */ protected static int iRankType = -1; /** Min # of Peers needed before boosting the rank of downloads with no seeds */ private static int minPeersToBoostNoSeeds; /** Min Speed needed to count a incomplete download as being actively downloading */ private static int minSpeedForActiveDL; /** Min speed needed to count a complete download as being actively seeding */ private static int minSpeedForActiveSeeding; // Ignore torrent if seed count is at least.. private static int iIgnoreSeedCount; // Ignore even when First Priority private static boolean bIgnore0Peers; private static int iIgnoreShareRatio; private static int iIgnoreShareRatio_SeedStart; private static int iIgnoreRatioPeers; private static int iIgnoreRatioPeers_SeedStart; private static int iRankTypeSeedFallback; private static boolean bPreferLargerSwarms; private static int minQueueingShareRatio; // Ignore First Priority private static int iFirstPriorityIgnoreSPRatio; private static boolean bFirstPriorityIgnore0Peer; private static int iFirstPriorityType; private static int iFirstPrioritySeedingMinutes; private static int iFirstPriorityActiveMinutes; private static int iFirstPriorityIgnoreIdleHours; private static long minTimeAlive; private static boolean bAutoStart0Peers; // // Class variables protected Download dl; private boolean bActivelyDownloading; private long lDLActivelyChangedOn; private boolean bActivelySeeding; private long lCDActivelyChangedOn; private long staleCDSince; private long staleCDOffset; private long lastStaleCDRefresh; private boolean bIsFirstPriority; /** Public for tooltip to access it */ public String sExplainFP = ""; /** Public for tooltip to access it */ public String sExplainSR = ""; /** Public for tooltip to access it */ public String sTrace = ""; private AEMonitor downloadData_this_mon = new AEMonitor( "StartStopRules:downloadData"); private final StartStopRulesDefaultPlugin rules; // state-caches for sorting int lastModifiedScrapeResultPeers = 0; int lastModifiedScrapeResultSeeds = 0; int lastModifiedShareRatio = 0; // modified by a listener in StartStopRulesDefaultPlugin boolean lastScrapeResultOk = false; /** * Default Initializer * * @param _rules * @param _dl */ public DefaultRankCalculator(StartStopRulesDefaultPlugin _rules, Download _dl) { rules = _rules; dl = _dl; try { downloadData_this_mon.enter(); if (configListener == null) { configListener = new COConfigurationListener() { public void configurationSaved() { reloadConfigParams(rules.plugin_config); } }; COConfigurationManager.addListener(configListener); configListener.configurationSaved(); } } finally { downloadData_this_mon.exit(); } } /** * Load config values into the static variables * * @param cfg */ public static void reloadConfigParams(PluginConfig cfg) { final String PREFIX = "StartStopManager_"; iRankType = cfg.getUnsafeIntParameter(PREFIX + "iRankType"); minPeersToBoostNoSeeds = cfg.getUnsafeIntParameter(PREFIX + "iMinPeersToBoostNoSeeds"); minSpeedForActiveDL = cfg.getUnsafeIntParameter(PREFIX + "iMinSpeedForActiveDL"); minSpeedForActiveSeeding = cfg.getUnsafeIntParameter(PREFIX + "iMinSpeedForActiveSeeding"); iRankTypeSeedFallback = cfg.getUnsafeIntParameter(PREFIX + "iRankTypeSeedFallback"); bPreferLargerSwarms = cfg.getUnsafeBooleanParameter(PREFIX + "bPreferLargerSwarms"); minTimeAlive = cfg.getUnsafeIntParameter(PREFIX + "iMinSeedingTime") * 1000; bAutoStart0Peers = cfg.getUnsafeBooleanParameter(PREFIX + "bAutoStart0Peers"); // Ignore torrent if seed count is at least.. iIgnoreSeedCount = cfg.getUnsafeIntParameter(PREFIX + "iIgnoreSeedCount"); bIgnore0Peers = cfg.getUnsafeBooleanParameter(PREFIX + "bIgnore0Peers"); iIgnoreShareRatio = (int) (1000 * cfg.getFloatParameter("Stop Ratio")); iIgnoreShareRatio_SeedStart = cfg.getUnsafeIntParameter(PREFIX + "iIgnoreShareRatioSeedStart"); iIgnoreRatioPeers = cfg.getIntParameter("Stop Peers Ratio", 0); iIgnoreRatioPeers_SeedStart = cfg.getUnsafeIntParameter(PREFIX + "iIgnoreRatioPeersSeedStart", 0); minQueueingShareRatio = cfg.getUnsafeIntParameter(PREFIX + "iFirstPriority_ShareRatio"); iFirstPriorityType = cfg.getUnsafeIntParameter(PREFIX + "iFirstPriority_Type"); iFirstPrioritySeedingMinutes = cfg.getUnsafeIntParameter(PREFIX + "iFirstPriority_SeedingMinutes"); iFirstPriorityActiveMinutes = cfg.getUnsafeIntParameter(PREFIX + "iFirstPriority_DLMinutes"); // Ignore FP iFirstPriorityIgnoreSPRatio = cfg.getUnsafeIntParameter(PREFIX + "iFirstPriority_ignoreSPRatio"); bFirstPriorityIgnore0Peer = cfg.getUnsafeBooleanParameter(PREFIX + "bFirstPriority_ignore0Peer"); iFirstPriorityIgnoreIdleHours = cfg.getUnsafeIntParameter(PREFIX + "iFirstPriority_ignoreIdleHours"); } /** Sort first by SeedingRank Descending, then by Position Ascending. */ public int compareTo(Object obj) { if (!(obj instanceof DefaultRankCalculator)) { return -1; } DefaultRankCalculator dlData = (DefaultRankCalculator) obj; // Test FP. FP goes to top if (dlData.bIsFirstPriority && !bIsFirstPriority) return 1; if (!dlData.bIsFirstPriority && bIsFirstPriority) return -1; // Test Completeness. Complete go to bottom boolean aIsComplete = dlData.dl.isComplete(); boolean bIsComplete = dl.isComplete(); if (aIsComplete && !bIsComplete) return -1; if (!aIsComplete && bIsComplete) return 1; if (iRankType == StartStopRulesDefaultPlugin.RANK_NONE) { return dl.getPosition() - dlData.dl.getPosition(); } // Check Rank. Large to top int value = dlData.dl.getSeedingRank() - dl.getSeedingRank(); if (value != 0) return value; if (iRankType != StartStopRulesDefaultPlugin.RANK_TIMED) { // Test Large/Small Swarm pref int numPeersThem = dlData.lastModifiedScrapeResultPeers; int numPeersUs = lastModifiedScrapeResultPeers; if (bPreferLargerSwarms) value = numPeersThem - numPeersUs; else value = numPeersUs - numPeersThem; if (value != 0) return value; // Test Share Ratio value = lastModifiedShareRatio - dlData.lastModifiedShareRatio; if (value != 0) return value; } // Test Position return dl.getPosition() - dlData.dl.getPosition(); } public Download getDownloadObject() { return dl; } public boolean isForceActive() { DownloadStats stats = dl.getStats(); return SystemTime.getCurrentTime() - stats.getTimeStarted() <= FORCE_ACTIVE_FOR; } /** * Retrieves whether the torrent is "actively" downloading * * @return true: actively downloading */ public boolean getActivelyDownloading() { boolean bIsActive = false; DownloadStats stats = dl.getStats(); int state = dl.getState(); // In order to be active, // - Must be downloading (and thus incomplete) // - Must be above speed threshold, or started less than 30s ago if (state != Download.ST_DOWNLOADING) { bIsActive = false; } else if (SystemTime.getCurrentTime() - stats.getTimeStarted() <= FORCE_ACTIVE_FOR) { bIsActive = true; } else { // activity based on DL Average bIsActive = (stats.getDownloadAverage() >= minSpeedForActiveDL); if (bActivelyDownloading != bIsActive) { long now = SystemTime.getCurrentTime(); // Change if (lDLActivelyChangedOn == -1) { // Start Timer lDLActivelyChangedOn = now; bIsActive = !bIsActive; } else if (now - lDLActivelyChangedOn < ACTIVE_CHANGE_WAIT) { // Continue as old state until timer finishes bIsActive = !bIsActive; } } else { // no change, reset timer lDLActivelyChangedOn = -1; } } if (bActivelyDownloading != bIsActive) { bActivelyDownloading = bIsActive; if (rules != null) { rules.requestProcessCycle(null); if (rules.bDebugLog) rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: ActivelyDownloading changed"); } } return bActivelyDownloading; } /** * Retrieves whether the torrent is "actively" seeding * * @return true: actively seeding */ public boolean getActivelySeeding() { boolean bIsActive = false; DownloadStats stats = dl.getStats(); int state = dl.getState(); // Timed torrents don't use a speed threshold, since they are based on time! // However, First Priorities need to be checked for activity so that // timed ones can start when FPs are below threshold. Ditto for 0 Peers // when bAutoStart0Peers if (iRankType == StartStopRulesDefaultPlugin.RANK_TIMED && !isFirstPriority() && !(bAutoStart0Peers && rules.calcPeersNoUs(dl) == 0 && lastScrapeResultOk)) { bIsActive = (state == Download.ST_SEEDING); } else if (state != Download.ST_SEEDING || (bAutoStart0Peers && rules.calcPeersNoUs(dl) == 0)) { // Not active if we aren't seeding // Not active if we are AutoStarting 0 Peers, and peer count == 0 bIsActive = false; staleCDSince = -1; } else if (SystemTime.getCurrentTime() - stats.getTimeStarted() <= FORCE_ACTIVE_FOR) { bIsActive = true; staleCDSince = -1; } else { bIsActive = (stats.getUploadAverage() >= minSpeedForActiveSeeding); if (bActivelySeeding != bIsActive) { long now = SystemTime.getCurrentTime(); // Change if (lCDActivelyChangedOn < 0) { // Start Timer lCDActivelyChangedOn = now; bIsActive = !bIsActive; } else if (now - lCDActivelyChangedOn < ACTIVE_CHANGE_WAIT) { // Continue as old state until timer finishes bIsActive = !bIsActive; } if (bActivelySeeding != bIsActive) { if (bIsActive) { staleCDSince = -1; staleCDOffset = 0; } else { staleCDSince = System.currentTimeMillis(); } } } else { // no change, reset timer lCDActivelyChangedOn = -1; } } if (bActivelySeeding != bIsActive) { bActivelySeeding = bIsActive; if (rules != null) { rules.requestProcessCycle(null); if (rules.bDebugLog) rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: ActivelySeeding changed"); } } return bActivelySeeding; } /** Assign Seeding Rank based on RankType * @return New Seeding Rank Value */ public int recalcSeedingRank() { try { downloadData_this_mon.enter(); sExplainSR = ""; int oldSR = dl.getSeedingRank(); DownloadStats stats = dl.getStats(); int newSR = 0; // make undownloaded sort to top so they can start first. if (!dl.isComplete()) { newSR = SR_COMPLETE_STARTS_AT + (10000 - dl.getPosition()); dl.setSeedingRank(newSR); if ( rules.bDebugLog ){ sExplainSR += " not complete. SetSR " + newSR + "\n"; } return newSR; } // here we are seeding lastModifiedShareRatio = stats.getShareRatio(); lastModifiedScrapeResultPeers = rules.calcPeersNoUs(dl); lastModifiedScrapeResultSeeds = rules.calcSeedsNoUs(dl); boolean bScrapeResultsOk = (lastModifiedScrapeResultPeers > 0 || lastModifiedScrapeResultSeeds > 0 || lastScrapeResultOk) && (lastModifiedScrapeResultPeers >= 0 && lastModifiedScrapeResultSeeds >= 0); if (!isFirstPriority()) { // Check Ignore Rules // never apply ignore rules to First Priority Matches // (we don't want leechers circumventing the 0.5 rule) //0 means unlimited if (iIgnoreShareRatio != 0 && lastModifiedShareRatio >= iIgnoreShareRatio && (lastModifiedScrapeResultSeeds >= iIgnoreShareRatio_SeedStart || !bScrapeResultsOk) && lastModifiedShareRatio != -1) { if (rules.bDebugLog) sExplainSR += " shareratio met: shareRatio(" + lastModifiedShareRatio + ") >= " + iIgnoreShareRatio + "\n"; dl.setSeedingRank(SR_SHARERATIOMET); return SR_SHARERATIOMET; } else if (rules.bDebugLog && iIgnoreShareRatio != 0 && lastModifiedShareRatio >= iIgnoreShareRatio) { sExplainSR += " shareratio NOT met: "; if (lastModifiedScrapeResultSeeds >= iIgnoreShareRatio_SeedStart) sExplainSR += lastModifiedScrapeResultSeeds + " below seed threshold of " + iIgnoreShareRatio_SeedStart; sExplainSR += "\n"; } if (lastModifiedScrapeResultPeers == 0 && bScrapeResultsOk) { // If both bIgnore0Peers and bFirstPriorityIgnore0Peer are on, // we won't know which one it is at this point. // We have to use the normal SR_0PEERS in case it isn't FP if (bIgnore0Peers) { if (rules.bDebugLog) sExplainSR += " Ignore 0 Peers criteria met\n"; dl.setSeedingRank(SR_0PEERS); return SR_0PEERS; } // if (bFirstPriorityIgnore0Peer) { // if (rules.bDebugLog) // sExplainSR += " Ignore 0 Peers criteria for FP met\n"; // // dl.setSeedingRank(SR_FP0PEERS); // return SR_FP0PEERS; // } } else if (rules.bDebugLog && lastModifiedScrapeResultPeers == 0) { sExplainSR += " 0 Peer Ignore rule NOT applied: Scrape invalid\n"; } // if (numPeers != 0 && iFirstPriorityIgnoreSPRatio != 0 // && numSeeds / numPeers >= iFirstPriorityIgnoreSPRatio) { // if (rules.bDebugLog) // sExplainSR += " Ignore rule for S:P Ratio for FP met. Current: (" // + (numSeeds / numPeers) // + ") >= Threshold(" // + iFirstPriorityIgnoreSPRatio + ")\n"; // // dl.setSeedingRank(SR_FP_SPRATIOMET); // return SR_FP_SPRATIOMET; // } //0 means disabled if ((iIgnoreSeedCount != 0) && (lastModifiedScrapeResultSeeds >= iIgnoreSeedCount)) { if (rules.bDebugLog) sExplainSR += " SeedCount Ignore rule met. numSeeds(" + lastModifiedScrapeResultSeeds + " >= iIgnoreSeedCount(" + iIgnoreSeedCount + ")\n"; dl.setSeedingRank(SR_NUMSEEDSMET); return SR_NUMSEEDSMET; } // Ignore when P:S ratio met // (More Peers for each Seed than specified in Config) //0 means never stop if (iIgnoreRatioPeers != 0 && lastModifiedScrapeResultSeeds != 0) { float ratio = (float) lastModifiedScrapeResultPeers / lastModifiedScrapeResultSeeds; if (ratio <= iIgnoreRatioPeers && lastModifiedScrapeResultSeeds >= iIgnoreRatioPeers_SeedStart) { if (rules.bDebugLog) sExplainSR += " P:S Ignore rule met. ratio(" + ratio + " <= threshold(" + iIgnoreRatioPeers_SeedStart + ")\n"; dl.setSeedingRank(SR_RATIOMET); return SR_RATIOMET; } } } // Never do anything with rank type of none if (iRankType == StartStopRulesDefaultPlugin.RANK_NONE) { if (rules.bDebugLog) sExplainSR += " Ranking Type set to none.. blanking seeding rank\n"; // everythink ok! dl.setSeedingRank(newSR); return newSR; } if (iRankType == StartStopRulesDefaultPlugin.RANK_TIMED) { if (bIsFirstPriority) { newSR += SR_TIMED_QUEUED_ENDS_AT + 1; dl.setSeedingRank(newSR); return newSR; } int state = dl.getState(); if (state == Download.ST_STOPPING || state == Download.ST_STOPPED || state == Download.ST_ERROR) { if (rules.bDebugLog) sExplainSR += " Download stopping, stopped or in error\n"; dl.setSeedingRank(SR_NOTQUEUED); return SR_NOTQUEUED; } else if (state == Download.ST_SEEDING || state == Download.ST_READY || state == Download.ST_WAITING || state == Download.ST_PREPARING) { // force sort to top long lMsElapsed = 0; if (state == Download.ST_SEEDING && !dl.isForceStart()) lMsElapsed = (SystemTime.getCurrentTime() - stats .getTimeStartedSeeding()); if (lMsElapsed >= minTimeAlive) { dl.setSeedingRank(1); if (oldSR > SR_TIMED_QUEUED_ENDS_AT) { rules.requestProcessCycle(null); if (rules.bDebugLog) rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: TimeUp"); } } else { newSR = SR_TIMED_QUEUED_ENDS_AT + 1 + (int) (lMsElapsed / 1000); dl.setSeedingRank(newSR); if (oldSR <= SR_TIMED_QUEUED_ENDS_AT) { rules.requestProcessCycle(null); if (rules.bDebugLog) rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: strange timer change"); } } return newSR; } else { if (oldSR <= 0) { newSR = SR_TIMED_QUEUED_ENDS_AT - dl.getPosition(); dl.setSeedingRank(newSR); rules.requestProcessCycle(null); if (rules.bDebugLog) rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: NotIgnored"); } return newSR; } } /** * Add to SeedingRank based on Rank Type */ // SeedCount and SPRatio require Scrape Results.. if (bScrapeResultsOk) { if ( iRankType == StartStopRulesDefaultPlugin.RANK_PEERCOUNT ) { if(lastModifiedScrapeResultPeers > lastModifiedScrapeResultSeeds * 10) newSR = 100 * lastModifiedScrapeResultPeers * 10; else newSR = (int)((long)100 * lastModifiedScrapeResultPeers * lastModifiedScrapeResultPeers/(lastModifiedScrapeResultSeeds+1)); } else if ((iRankType == StartStopRulesDefaultPlugin.RANK_SEEDCOUNT) && (iRankTypeSeedFallback == 0 || iRankTypeSeedFallback > lastModifiedScrapeResultSeeds)) { if (lastModifiedScrapeResultSeeds < 10000) newSR = 10000 - lastModifiedScrapeResultSeeds; else newSR = 1; // shift over to make way for fallback newSR *= SEEDONLY_SHIFT; } else { // iRankType == RANK_SPRATIO or we are falling back if (lastModifiedScrapeResultPeers != 0) { if (lastModifiedScrapeResultSeeds == 0) { if (lastModifiedScrapeResultPeers >= minPeersToBoostNoSeeds) newSR += SPRATIO_BASE_LIMIT; } else { // numSeeds != 0 && numPeers != 0 float x = (float) lastModifiedScrapeResultSeeds / lastModifiedScrapeResultPeers; newSR += SPRATIO_BASE_LIMIT / ((x + 1) * (x + 1)); } } } } else { if (rules.bDebugLog) sExplainSR += " Can't calculate SR, no scrape results\n"; } if (staleCDOffset > 0) { // every 10 minutes of not being active, subtract one SR if (newSR > staleCDOffset) { newSR -= staleCDOffset; sExplainSR += " subtracted " + staleCDOffset + " due to non-activeness\n"; } else { staleCDOffset = 0; } } if (newSR < 0) newSR = 1; if (newSR != oldSR) dl.setSeedingRank(newSR); return newSR; } finally { downloadData_this_mon.exit(); } } // recalcSeedingRank /** Does the torrent match First Priority criteria? * @return FP State */ public boolean isFirstPriority() { boolean bFP = pisFirstPriority(); if (bIsFirstPriority != bFP) { bIsFirstPriority = bFP; rules.requestProcessCycle(null); if (rules.bDebugLog) rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: FP changed"); } return bIsFirstPriority; } private boolean pisFirstPriority() { if (rules.bDebugLog) sExplainFP = "FP if " + (iFirstPriorityType == FIRSTPRIORITY_ALL ? "all" : "any") + " criteria match:\n"; if (!dl.isPersistent()) { if (rules.bDebugLog) sExplainFP += "Not FP: Download not persistent\n"; return false; } if (dl.getState() == Download.ST_ERROR || dl.getState() == Download.ST_STOPPED) { if (rules.bDebugLog) sExplainFP += "Not FP: Download is ERROR or STOPPED\n"; return false; } // FP only applies to completed if (!dl.isComplete()) { if (rules.bDebugLog) sExplainFP += "Not FP: Download not complete\n"; return false; } List listeners = rules.getFPListeners(); StringBuffer fp_listener_debug = null; if (!listeners.isEmpty()) { if (rules.bDebugLog) fp_listener_debug = new StringBuffer(); for (Iterator iter = listeners.iterator(); iter.hasNext();) { StartStopRulesFPListener l = (StartStopRulesFPListener) iter.next(); boolean result = l.isFirstPriority(dl, lastModifiedScrapeResultSeeds, lastModifiedScrapeResultPeers, fp_listener_debug); if (fp_listener_debug != null && fp_listener_debug.length() > 0) { char last_ch = fp_listener_debug.charAt(fp_listener_debug.length() - 1); if (last_ch != '\n') fp_listener_debug.append('\n'); sExplainFP += fp_listener_debug; fp_listener_debug.setLength(0); } if (result) { return true; } } } // FP doesn't apply when S:P >= set SPratio (SPratio = 0 means ignore) if (lastModifiedScrapeResultPeers > 0 && lastModifiedScrapeResultSeeds > 0 && (lastModifiedScrapeResultSeeds / lastModifiedScrapeResultPeers) >= iFirstPriorityIgnoreSPRatio && iFirstPriorityIgnoreSPRatio != 0) { if (rules.bDebugLog) sExplainFP += "Not FP: S:P >= " + iFirstPriorityIgnoreSPRatio + ":1\n"; return false; } //not FP if no peers //Nolar, 2105 - Gouss, 2203 if (lastModifiedScrapeResultPeers == 0 && lastScrapeResultOk && bFirstPriorityIgnore0Peer) { if (rules.bDebugLog) sExplainFP += "Not FP: 0 peers\n"; return false; } if (iFirstPriorityIgnoreIdleHours > 0) { long lastUploadSecs = dl.getStats().getSecondsSinceLastUpload(); if (lastUploadSecs < 0) { lastUploadSecs = dl.getStats().getSecondsOnlySeeding(); } if (lastUploadSecs > 60 * 60 * iFirstPriorityIgnoreIdleHours) { if (rules.bDebugLog) sExplainFP += "Not FP: " + lastUploadSecs + "s > " + iFirstPriorityIgnoreIdleHours + "h of no upload\n"; return false; } } int shareRatio = dl.getStats().getShareRatio(); boolean bLastMatched = (shareRatio != -1) && (shareRatio < minQueueingShareRatio); if (rules.bDebugLog) sExplainFP += " shareRatio(" + shareRatio + ") < " + minQueueingShareRatio + "=" + bLastMatched + "\n"; if (!bLastMatched && iFirstPriorityType == FIRSTPRIORITY_ALL) { if (rules.bDebugLog) sExplainFP += "..Not FP. Exit Early\n"; return false; } if (bLastMatched && iFirstPriorityType == FIRSTPRIORITY_ANY) { if (rules.bDebugLog) sExplainFP += "..Is FP. Exit Early\n"; return true; } bLastMatched = (iFirstPrioritySeedingMinutes == 0); if (!bLastMatched) { long timeSeeding = dl.getStats().getSecondsOnlySeeding(); if (timeSeeding >= 0) { bLastMatched = (timeSeeding < (iFirstPrioritySeedingMinutes * 60)); if (rules.bDebugLog) sExplainFP += " SeedingTime(" + timeSeeding + ") < " + (iFirstPrioritySeedingMinutes * 60) + "=" + bLastMatched + "\n"; if (!bLastMatched && iFirstPriorityType == FIRSTPRIORITY_ALL) { if (rules.bDebugLog) sExplainFP += "..Not FP. Exit Early\n"; return false; } if (bLastMatched && iFirstPriorityType == FIRSTPRIORITY_ANY) { if (rules.bDebugLog) sExplainFP += "..Is FP. Exit Early\n"; return true; } } } else if (rules.bDebugLog) { sExplainFP += " Skipping Seeding Time check (user disabled)\n"; } bLastMatched = (iFirstPriorityActiveMinutes == 0); if (!bLastMatched) { long timeActive = dl.getStats().getSecondsDownloading() + dl.getStats().getSecondsOnlySeeding(); if (timeActive >= 0) { bLastMatched = (timeActive < (iFirstPriorityActiveMinutes * 60)); if (rules.bDebugLog) sExplainFP += " ActiveTime(" + timeActive + ") < " + (iFirstPriorityActiveMinutes * 60) + "=" + bLastMatched + "\n"; if (!bLastMatched && iFirstPriorityType == FIRSTPRIORITY_ALL) { if (rules.bDebugLog) sExplainFP += "..Not FP. Exit Early\n"; return false; } if (bLastMatched && iFirstPriorityType == FIRSTPRIORITY_ANY) { if (rules.bDebugLog) sExplainFP += "..Is FP. Exit Early\n"; return true; } } } else if (rules.bDebugLog) { sExplainFP += " Skipping DL Time check (user disabled)\n"; } if (iFirstPriorityType == FIRSTPRIORITY_ALL) { if (rules.bDebugLog) sExplainFP += "..Is FP\n"; return true; } if (rules.bDebugLog) sExplainFP += "..Not FP\n"; return false; } /** * * @return last calculated FP state */ public boolean getCachedIsFP() { return bIsFirstPriority; } public String toString() { return String.valueOf(dl.getSeedingRank()); } /** * Check Seeders for various changes not triggered by listeners * * @return True: something changed */ public boolean changeChecker() { if (getActivelySeeding()) { int shareRatio = dl.getStats().getShareRatio(); int numSeeds = rules.calcSeedsNoUs(dl); if (iIgnoreShareRatio != 0 && shareRatio >= iIgnoreShareRatio && (numSeeds >= iIgnoreShareRatio_SeedStart || !lastScrapeResultOk) && shareRatio != -1) { if (rules.bDebugLog) { rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: shareRatio changeChecker"); } return true; } } /* READY downloads are usually waiting for a seeding torrent to stop (the seeding torrent probably is within the "Minimum Seeding Time" setting) The rules may go through several cycles before a READY torrent is processed */ if (dl.getState() == Download.ST_READY) { if (rules.bDebugLog) rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: Download is ready"); return true; } if (staleCDSince > 0) { long now = SystemTime.getCurrentTime(); if (now - lastStaleCDRefresh > STALE_REFRESH_INTERVAL) { staleCDOffset += (now - lastStaleCDRefresh) / STALE_REFRESH_INTERVAL; lastStaleCDRefresh = now; if (rules.bDebugLog) { rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION, "somethingChanged: staleCD changeChecker"); } return true; } } return false; } } azureus-4.3.0.6/com/aelitis/azureus/plugins/magnet/0000755000175000017500000000000011310377630021501 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/magnet/MagnetPlugin.java0000644000175000017500000006176711306320274024754 0ustar adrianadrian/* * Created on 03-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.magnet; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.net.InetSocketAddress; import org.eclipse.swt.graphics.Image; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.BEncoder; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DelayedEvent; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.ddb.DistributedDatabase; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseContact; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseEvent; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseListener; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseProgressListener; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseTransferType; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseValue; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadException; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.ui.UIInstance; import org.gudy.azureus2.plugins.ui.UIManagerListener; import org.gudy.azureus2.plugins.ui.config.BooleanParameter; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.menus.MenuItemListener; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.plugins.ui.tables.TableRow; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderAdapter; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory; import org.gudy.azureus2.ui.swt.plugins.UISWTInstance; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.util.FeatureAvailability; import com.aelitis.net.magneturi.*; /** * @author parg * */ public class MagnetPlugin implements Plugin { private static final String SECONDARY_LOOKUP = "http://magnet.vuze.com/"; private static final int SECONDARY_LOOKUP_DELAY = 20*1000; private static final int SECONDARY_LOOKUP_MAX_TIME = 2*60*1000; private static final String PLUGIN_NAME = "Magnet URI Handler"; private static final String PLUGIN_CONFIGSECTION_ID = "plugins.magnetplugin"; private PluginInterface plugin_interface; private CopyOnWriteList listeners = new CopyOnWriteList(); private boolean first_download = true; private BooleanParameter secondary_lookup; public static void load( PluginInterface plugin_interface ) { plugin_interface.getPluginProperties().setProperty( "plugin.version", "1.0" ); plugin_interface.getPluginProperties().setProperty( "plugin.name", PLUGIN_NAME ); } public void initialize( PluginInterface _plugin_interface ) { plugin_interface = _plugin_interface; BasicPluginConfigModel config = plugin_interface.getUIManager().createBasicPluginConfigModel( ConfigSection.SECTION_PLUGINS, PLUGIN_CONFIGSECTION_ID); secondary_lookup = config.addBooleanParameter2( "MagnetPlugin.use.lookup.service", "MagnetPlugin.use.lookup.service", true ); MenuItemListener listener = new MenuItemListener() { public void selected( MenuItem _menu, Object _target ) { Download download = (Download)((TableRow)_target).getDataSource(); if ( download == null || download.getTorrent() == null ){ return; } Torrent torrent = download.getTorrent(); String cb_data = "magnet:?xt=urn:btih:" + Base32.encode( torrent.getHash()); // removed this as well - nothing wrong with allowing magnet copy // for private torrents - they still can't be tracked if you don't // have permission /*if ( torrent.isPrivate()){ cb_data = getMessageText( "private_torrent" ); }else if ( torrent.isDecentralised()){ */ // ok /* relaxed this as we allow such torrents to be downloaded via magnet links * (as opposed to tracked in the DHT) }else if ( torrent.isDecentralisedBackupEnabled()){ TorrentAttribute ta_peer_sources = plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_PEER_SOURCES ); String[] sources = download.getListAttribute( ta_peer_sources ); boolean ok = false; for (int i=0;i 0 ){ new DelayedEvent( "MP:sourceAdd", 10*1000, new AERunnable() { public void runSupport() { addExplicitSources(); } }); } }else if ( type == DistributedDatabaseEvent.ET_VALUE_READ ){ contactFound( event.getValue().getContact()); }else if ( type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE || type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ){ listener.reportActivity( getMessageText( "report.found", String.valueOf( found_set.size()))); // now inject any explicit sources addExplicitSources(); try{ potential_contacts_mon.enter(); lookup_complete[0] = true; }finally{ potential_contacts_mon.exit(); } potential_contacts_sem.release(); } } protected void addExplicitSources() { for (int i=0;i 0 ){ try{ potential_contacts_mon.enter(); if ( lookup_complete[0] && potential_contacts.size() == 0 && outstanding[0] == 0 ){ break; } }finally{ potential_contacts_mon.exit(); } while( remaining > 0 ){ long wait_start = SystemTime.getMonotonousTime(); boolean got_sem = potential_contacts_sem.reserve( 1000 ); long now = SystemTime.getMonotonousTime(); remaining -= ( now - wait_start ); if ( got_sem ){ last_found = now; break; }else{ if ( sl_enabled ){ if ( secondary_lookup_time == -1 ){ long base_time; if ( last_found == -1 || now - overall_start > 60*1000 ){ base_time = overall_start; }else{ base_time = last_found; } long time_so_far = now - base_time; if ( time_so_far > SECONDARY_LOOKUP_DELAY ){ secondary_lookup_time = SystemTime.getMonotonousTime(); doSecondaryLookup( listener, secondary_result, hash, args ); } }else{ try{ byte[] torrent = getSecondaryLookupResult( secondary_result ); if ( torrent != null ){ return( torrent ); } }catch( ResourceDownloaderException e ){ // ignore, we just continue processing } } } continue; } } DistributedDatabaseContact contact; boolean live_contact; try{ potential_contacts_mon.enter(); // System.out.println( "rem=" + remaining + ",pot=" + potential_contacts.size() + ",out=" + outstanding[0] ); if ( potential_contacts.size() == 0 ){ if ( outstanding[0] == 0 ){ break; }else{ continue; } }else{ Object[] entry = (Object[])potential_contacts.remove(0); live_contact = ((Boolean)entry[0]).booleanValue(); contact = (DistributedDatabaseContact)entry[1]; } }finally{ potential_contacts_mon.exit(); } // System.out.println( "magnetDownload: " + contact.getName() + ", live = " + live_contact ); if ( !live_contact ){ listener.reportActivity( getMessageText( "report.tunnel", contact.getName())); contact.openTunnel(); } try{ listener.reportActivity( getMessageText( "report.downloading", contact.getName())); DistributedDatabaseValue value = contact.read( new DistributedDatabaseProgressListener() { public void reportSize( long size ) { listener.reportSize( size ); } public void reportActivity( String str ) { listener.reportActivity( str ); } public void reportCompleteness( int percent ) { listener.reportCompleteness( percent ); } }, db.getStandardTransferType( DistributedDatabaseTransferType.ST_TORRENT ), db.createKey ( hash , "Torrent download content for '" + ByteFormatter.encodeString( hash ) + "'"), timeout ); if ( value != null ){ // let's verify the torrent byte[] data = (byte[])value.getValue(byte[].class); try{ TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedByteArray( data ); if ( Arrays.equals( hash, torrent.getHash())){ listener.reportContributor( contact.getAddress()); return( data ); }else{ listener.reportActivity( getMessageText( "report.error", "torrent invalid (hash mismatch)" )); } }catch( Throwable e ){ listener.reportActivity( getMessageText( "report.error", "torrent invalid (decode failed)" )); } } }catch( Throwable e ){ listener.reportActivity( getMessageText( "report.error", Debug.getNestedExceptionMessage(e))); Debug.printStackTrace(e); } } if ( sl_enabled ){ if ( secondary_lookup_time == -1 ){ secondary_lookup_time = SystemTime.getMonotonousTime(); doSecondaryLookup(listener, secondary_result, hash, args ); } while( SystemTime.getMonotonousTime() - secondary_lookup_time < SECONDARY_LOOKUP_MAX_TIME ){ try{ byte[] torrent = getSecondaryLookupResult( secondary_result ); if ( torrent != null ){ return( torrent ); } Thread.sleep( 500 ); }catch( ResourceDownloaderException e ){ break; } } } return( null ); // nothing found }catch( Throwable e ){ Debug.printStackTrace(e); listener.reportActivity( getMessageText( "report.error", Debug.getNestedExceptionMessage(e))); throw( new MagnetURIHandlerException( "MagnetURIHandler failed", e )); } } protected void doSecondaryLookup( final MagnetPluginProgressListener listener, final Object[] result, byte[] hash, String args ) { listener.reportActivity( getMessageText( "report.secondarylookup", null )); try{ ResourceDownloaderFactory rdf = plugin_interface.getUtilities().getResourceDownloaderFactory(); URL sl_url = new URL( SECONDARY_LOOKUP + "magnetLookup?hash=" + Base32.encode( hash ) + (args.length()==0?"":("&args=" + UrlUtils.encode( args )))); ResourceDownloader rd = rdf.create( sl_url ); rd.addListener( new ResourceDownloaderAdapter() { public boolean completed( ResourceDownloader downloader, InputStream data ) { listener.reportActivity( getMessageText( "report.secondarylookup.ok", null )); synchronized( result ){ result[0] = data; } return( true ); } public void failed( ResourceDownloader downloader, ResourceDownloaderException e ) { synchronized( result ){ result[0] = e; } listener.reportActivity( getMessageText( "report.secondarylookup.fail" )); } }); rd.asyncDownload(); }catch( Throwable e ){ listener.reportActivity( getMessageText( "report.secondarylookup.fail", Debug.getNestedExceptionMessage( e ) )); } } protected byte[] getSecondaryLookupResult( final Object[] result ) throws ResourceDownloaderException { Object x; synchronized( result ){ x = result[0]; result[0] = null; } if ( x instanceof InputStream ){ InputStream is = (InputStream)x; try{ TOTorrent t = TOTorrentFactory.deserialiseFromBEncodedInputStream( is ); TorrentUtils.setPeerCacheValid( t ); return( BEncoder.encode( t.serialiseToMap())); }catch( Throwable e ){ } }else if ( x instanceof ResourceDownloaderException ){ throw((ResourceDownloaderException)x); } return( null ); } protected String getMessageText( String resource ) { return( plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( "MagnetPlugin." + resource )); } protected String getMessageText( String resource, String param ) { return( plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( "MagnetPlugin." + resource, new String[]{ param })); } public void addListener( MagnetPluginListener listener ) { listeners.add( listener ); } public void removeListener( MagnetPluginListener listener ) { listeners.remove( listener ); } } azureus-4.3.0.6/com/aelitis/azureus/plugins/magnet/Magnet.gif0000644000175000017500000000567010220566320023406 0ustar adrianadrianGIF89aZ! !)19 6 &!?1 "-JTN K!R)J)R)R%N.O!1N+3O69L]o#? #};oe{-)s@ PaA'*/BTJRJ~,W2LXaGh7 6L'ÂA+XT#ǎIƌXV2m*T(]Ҽ*3<\ӛwmlŸ?qmҵo/JuM,XƂ l$-pL+ToݽڴD1bθT+o\…J`OƖWmӋ@#ZdH0RWՖ[n#^<Yzl\F-Tq\ 0/{dG0Xێ:U@#2^Fm{#'_h^(!*1(Gkr(Wx>L@Ot6mC#$ op0i|@qu G5etH00# A3 C C`=pj X`:~ Wh!H J E1hD#+7ЇWnq Cx@d C$P0Ta e5x2 Z (@d ?H% z'\ N /lR|6#ڑg4cX0,t DdA [BP @Ssc>A8 aKv`IdEBO mtC7bx!-q 0NDfQ a/ ` 0Ah$F,"P#2 ɨ51nxc22s=<0:E ajd zW t)9jՈN>!s*=n V |t׍mx9u p`ֺηMt]9 ۽8Gp[\^ZG7эo,<'y[;azureus-4.3.0.6/com/aelitis/azureus/plugins/magnet/MagnetPluginListener.java0000644000175000017500000000237110752576262026462 0ustar adrianadrian/* * Created on Feb 8, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.magnet; import java.util.Map; public interface MagnetPluginListener { public boolean set( String name, Map values ); /** * * @param name * @param values * @return Integer.MIN_VALUE if not handled */ public int get( String name, Map values ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/magnet/MagnetPluginProgressListener.java0000644000175000017500000000252011306320300030153 0ustar adrianadrian/* * Created on 07-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.magnet; import java.net.InetSocketAddress; /** * @author parg * */ public interface MagnetPluginProgressListener { public void reportSize( long size ); public void reportActivity( String str ); public void reportCompleteness( int percent ); public void reportContributor( InetSocketAddress address ); public boolean verbose(); } azureus-4.3.0.6/com/aelitis/azureus/plugins/magnet/icons/0000755000175000017500000000000011310377326022616 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/magnet/icons/magnet.gif0000644000175000017500000000155710332736756024601 0ustar adrianadrianGIF89a ccc!, LHp"L`BFd8` Q`ŋ l9^,iRʕ&?Rf4$3dN= ;azureus-4.3.0.6/com/aelitis/azureus/plugins/magnet/MagnetPluginException.java0000644000175000017500000000224511012742134026612 0ustar adrianadrian/* * Created on 07-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.magnet; /** * @author parg * */ public class MagnetPluginException extends Exception { public MagnetPluginException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/com/aelitis/azureus/plugins/sharing/0000755000175000017500000000000011310377326021663 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/sharing/hoster/0000755000175000017500000000000011310377630023165 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/sharing/hoster/ShareHosterPlugin.java0000644000175000017500000002300411275142106027433 0ustar adrianadrian/* * File : ShareHosterPlugin.java * Created : 05-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.plugins.sharing.hoster; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.logging.*; import org.gudy.azureus2.plugins.torrent.*; import org.gudy.azureus2.plugins.tracker.*; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.plugins.sharing.*; import org.gudy.azureus2.plugins.download.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; public class ShareHosterPlugin implements Plugin, PluginListener, ShareManagerListener { protected PluginInterface plugin_interface; protected LoggerChannel log; protected Tracker tracker; protected ShareManager share_manager; protected DownloadManager download_manager; protected Map resource_dl_map = new HashMap(); protected Map resource_tt_map = new HashMap(); protected Download download_being_removed; protected TrackerTorrent torrent_being_removed; public static void load( PluginInterface plugin_interface ) { plugin_interface.getPluginProperties().setProperty( "plugin.version", "1.0" ); plugin_interface.getPluginProperties().setProperty( "plugin.name", "Share Hoster" ); } public void initialize( PluginInterface _plugin_interface ) { plugin_interface = _plugin_interface; log = plugin_interface.getLogger().getChannel("ShareHosterPlugin"); log.log( LoggerChannel.LT_INFORMATION, "ShareHosterPlugin: initialisation starts"); plugin_interface.addListener( this ); } public void initializationComplete() { final DelayedTask dt = plugin_interface.getUtilities().createDelayedTask(new Runnable() { public void run() { initialise(); } }); dt.queue(); } protected void initialise() { log.log( LoggerChannel.LT_INFORMATION, "ShareHosterPlugin: initialisation complete"); Thread.currentThread().setPriority( Thread.MIN_PRIORITY ); try{ tracker = plugin_interface.getTracker(); download_manager = plugin_interface.getDownloadManager(); share_manager = plugin_interface.getShareManager(); share_manager.addListener( this ); share_manager.initialise(); }catch( ShareException e ){ Debug.printStackTrace( e ); log.log( e ); }finally{ plugin_interface.getPluginManager().firePluginEvent( PluginEvent.PEV_INITIAL_SHARING_COMPLETE ); } } public void closedownInitiated() { } public void closedownComplete() { } public void resourceAdded( final ShareResource resource ) { log.log( LoggerChannel.LT_INFORMATION, "Resource added:".concat(resource.getName())); try{ resource.addDeletionListener( new ShareResourceWillBeDeletedListener() { public void resourceWillBeDeleted( ShareResource resource ) throws ShareResourceDeletionVetoException { canResourceBeDeleted( resource ); } }); Download new_download = null; int type = resource.getType(); if ( type == ShareResource.ST_FILE ){ ShareResourceFile file_resource = (ShareResourceFile)resource; ShareItem item = file_resource.getItem(); Torrent torrent = item.getTorrent(); Download download = download_manager.getDownload( torrent ); if ( download == null ){ new_download = download_manager.addNonPersistentDownload( torrent, item.getTorrentFile(), file_resource.getFile()); } }else if ( type == ShareResource.ST_DIR ){ ShareResourceDir dir_resource = (ShareResourceDir)resource; ShareItem item = dir_resource.getItem(); Torrent torrent = item.getTorrent(); Download download = download_manager.getDownload( torrent ); if ( download == null ){ new_download = download_manager.addNonPersistentDownload( torrent, item.getTorrentFile(), dir_resource.getDir()); } } if ( new_download != null ){ final Download f_new_download = new_download; resource_dl_map.put( resource, new_download ); resource.addChangeListener( new ShareResourceListener() { public void shareResourceChanged( ShareResource resource, ShareResourceEvent event ) { if ( event.getType() == ShareResourceEvent.ET_ATTRIBUTE_CHANGED ){ TorrentAttribute attribute = (TorrentAttribute)event.getData(); // System.out.println( "sh: res -> ds: " + attribute.getName() + "/" + resource.getAttribute( attribute )); f_new_download.setAttribute( attribute, resource.getAttribute( attribute )); } } }); TorrentAttribute[] attributes = resource.getAttributes(); for (int i=0;i 0 ){ Iterator it2 = active.entrySet().iterator(); List track_now = new ArrayList(); while( it2.hasNext()){ Map.Entry entry = (Map.Entry)it2.next(); Download dl = (Download)entry.getKey(); boolean now = ((Boolean)entry.getValue()).booleanValue(); if ( now ){ track_now.add( dl ); } active_set.add( dl ); } if( track_now.size() > 0 ){ to_do.put( buddy, track_now ); } } } } synchronized( actively_tracking ){ Iterator it = active_set.iterator(); while( it.hasNext()){ Download dl = (Download)it.next(); if ( !actively_tracking.contains( dl )){ actively_tracking.add( dl ); trackPeers( dl ); } } it = actively_tracking.iterator(); while( it.hasNext()){ Download dl = (Download)it.next(); if ( !active_set.contains( dl )){ it.remove(); untrackPeers( dl ); } } } Iterator it = to_do.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); BuddyPluginBuddy buddy = (BuddyPluginBuddy)entry.getKey(); if ( !buddy.isOnline( false )){ continue; } InetAddress ip = buddy.getAdjustedIP(); if ( ip == null ){ continue; } int tcp_port = buddy.getTCPPort(); int udp_port = buddy.getUDPPort(); List downloads = (List)entry.getValue(); for (int i=0;i " + result + ",tested=" + tested ); return( result ); } } public void messageLogged( String str, boolean error ) { } public void enabledStateChanged( boolean _enabled ) { plugin_enabled = _enabled; checkEnabledState(); } public boolean isEnabled() { synchronized( this ){ return( plugin_enabled && tracker_enabled ); } } protected void checkEnabledState() { boolean seeding_change = false; boolean enabled_change = false; synchronized( this ){ boolean old_enabled = old_plugin_enabled && old_tracker_enabled; if ( plugin_enabled != old_plugin_enabled ){ log( "Plugin enabled state changed to " + plugin_enabled ); old_plugin_enabled = plugin_enabled; } if ( tracker_enabled != old_tracker_enabled ){ log( "Tracker enabled state changed to " + tracker_enabled ); old_tracker_enabled = tracker_enabled; } if ( seeding_only != old_seeding_only ){ log( "Seeding-only state changed to " + seeding_only ); old_seeding_only = seeding_only; seeding_change = true; } enabled_change = old_enabled != ( plugin_enabled && tracker_enabled ); } if ( seeding_change ){ updateSeedingMode(); } if ( enabled_change ){ fireEnabledChanged( isEnabled()); } } protected void updateSeedingMode() { updateNetworkStatus(); List online; synchronized( online_buddies ){ online = new ArrayList( online_buddies ); } for (int i=0;i 0 ){ long retry_millis = RETRY_SEND_MIN; for (int i=0;i RETRY_SEND_MAX ){ retry_millis = RETRY_SEND_MAX; break; } } long now = SystemTime.getMonotonousTime(); if ( now - last_fail >= retry_millis ){ last_fail = now; // assume we're going to fail so we avoid // falling through here multiple times before // actuallt failing again downloads_sent = null; downloads_sent_id = 0; } } // first check to see if completion state changed for any common downloads List comp_changed = new ArrayList(); synchronized( this ){ if ( downloads_in_common != null ){ Iterator it = downloads_in_common.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); Download d = (Download)entry.getKey(); buddyDownloadData bdd = (buddyDownloadData)entry.getValue(); boolean local_complete = d.isComplete( false ); if ( local_complete != bdd.isLocalComplete()){ bdd.setLocalComplete( local_complete ); comp_changed.add( d ); } } } } if ( comp_changed.size() > 0 ){ byte[][] change_details = exportFullIDs( comp_changed ); if( change_details[0].length > 0 ){ Map msg = new HashMap(); msg.put( "seeding", new Long( seeding_only?1:0 )); msg.put( "change", change_details[0] ); msg.put( "change_s", change_details[1] ); sendMessage( buddy, REQUEST_TRACKER_CHANGE, msg ); } } if ( id == downloads_sent_id ){ return; } Long key = new Long(((long)id) << 32 | (long)downloads_sent_id); Object[] diffs = (Object[])diff_map.get( key ); boolean incremental = downloads_sent != null; byte[] added_bytes; byte[] removed_bytes; if ( diffs == null ){ List added; List removed = new ArrayList(); if ( downloads_sent == null ){ added = new ArrayList( downloads ); }else{ added = new ArrayList(); Iterator it1 = downloads.iterator(); while( it1.hasNext()){ Download download = (Download)it1.next(); if ( okToTrack( download )){ if ( !downloads_sent.contains( download )){ added.add( download ); } } } Iterator it2 = downloads_sent.iterator(); while( it2.hasNext()){ Download download = (Download)it2.next(); if ( !downloads.contains( download )){ removed.add( download ); } } } added_bytes = exportShortIDs( added ); removed_bytes = exportFullIDs( removed )[0]; diff_map.put( key, new Object[]{ added_bytes, removed_bytes }); }else{ added_bytes = (byte[])diffs[0]; removed_bytes = (byte[])diffs[1]; } downloads_sent = downloads; downloads_sent_id = id; if ( added_bytes.length == 0 && removed_bytes.length == 0 ){ return; } Map msg = new HashMap(); if ( added_bytes.length > 0 ){ msg.put( "added", added_bytes ); } if ( removed_bytes.length > 0 ){ msg.put( "removed", removed_bytes ); } msg.put( "inc", new Long( incremental?1:0 )); msg.put( "seeding", new Long( seeding_only?1:0 )); sendMessage( buddy, REQUEST_TRACKER_SUMMARY, msg ); } protected Map updateRemote( Map msg ) { List added = importShortIDs((byte[])msg.get( "added" )); Map reply = new HashMap(); byte[][] add_details = exportFullIDs( added ); if( add_details[0].length > 0 ){ reply.put( "added", add_details[0] ); reply.put( "added_s", add_details[1] ); } synchronized( this ){ if ( downloads_in_common != null ){ Map removed = importFullIDs( (byte[])msg.get( "removed" ), null ); Iterator it = removed.keySet().iterator(); while( it.hasNext()){ Download d = (Download)it.next(); if ( downloads_in_common.remove( d ) != null ){ log( "Removed " + d.getName() + " common download", false, true ); } } if ( downloads_in_common.size() == 0 ){ downloads_in_common = null; } } } return( reply ); } protected void updateCommonDownloads( Map downloads, boolean incremental ) { synchronized( this ){ if ( downloads_in_common == null ){ downloads_in_common = new HashMap(); }else{ // if not incremental then remove any downloads that no longer // are in common if ( !incremental ){ Iterator it = downloads_in_common.keySet().iterator(); while( it.hasNext()){ Download download = (Download)it.next(); if ( !downloads.containsKey( download )){ log( "Removing " + download.getName() + " from common downloads", false, true ); it.remove(); } } } } Iterator it = downloads.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); Download d = (Download)entry.getKey(); buddyDownloadData bdd = (buddyDownloadData)entry.getValue(); buddyDownloadData existing = (buddyDownloadData)downloads_in_common.get( d ); if ( existing == null ){ log( "Adding " + d.getName() + " to common downloads (bdd=" + bdd.getString() + ")", false, true ); downloads_in_common.put( d, bdd ); }else{ boolean old_rc = existing.isRemoteComplete(); boolean new_rc = bdd.isRemoteComplete(); if ( old_rc != new_rc ){ existing.setRemoteComplete( new_rc ); log( "Changing " + d.getName() + " common downloads (bdd=" + existing.getString() + ")", false, true ); } } } if ( downloads_in_common.size() == 0 ){ downloads_in_common = null; } } } protected void updateStatus() { Map msg = new HashMap(); msg.put( "seeding", new Long( seeding_only?1:0 )); sendMessage( buddy, REQUEST_TRACKER_STATUS, msg ); } protected Map receiveMessage( int type, Map msg_in ) { int reply_type = -1; Map msg_out = null; Long l_seeding = (Long)msg_in.get( "seeding" ); if( l_seeding != null ){ boolean old = buddy_seeding_only; buddy_seeding_only = l_seeding.intValue() == 1; if ( old != buddy_seeding_only ){ log( "Seeding only changed to " + buddy_seeding_only ); } } if ( type == REQUEST_TRACKER_SUMMARY ){ reply_type = REPLY_TRACKER_SUMMARY; msg_out = updateRemote( msg_in ); msg_out.put( "inc", msg_in.get( "inc" )); }else if ( type == REQUEST_TRACKER_STATUS ){ reply_type = REPLY_TRACKER_STATUS; }else if ( type == REQUEST_TRACKER_CHANGE ){ reply_type = REPLY_TRACKER_STATUS; Map downloads = importFullIDs( (byte[])msg_in.get( "changed" ), (byte[])msg_in.get( "changed_s" ) ); updateCommonDownloads( downloads, true ); }else if ( type == REQUEST_TRACKER_ADD ){ reply_type = REPLY_TRACKER_ADD; Map downloads = importFullIDs( (byte[])msg_in.get( "added" ), (byte[])msg_in.get( "added_s" ) ); updateCommonDownloads( downloads, true ); }else if ( type == REPLY_TRACKER_SUMMARY ){ // full hashes on reply byte[] possible_matches = (byte[])msg_in.get( "added" ); byte[] possible_match_states = (byte[])msg_in.get( "added_s" ); boolean incremental = ((Long)msg_in.get( "inc" )).intValue() == 1; if ( possible_matches != null && possible_match_states != null ){ Map downloads = importFullIDs( possible_matches, possible_match_states ); if ( downloads.size() > 0 ){ updateCommonDownloads( downloads, incremental ); byte[][] common_details = exportFullIDs( new ArrayList( downloads.keySet())); if( common_details[0].length > 0 ){ Map msg = new HashMap(); msg.put( "seeding", new Long( seeding_only?1:0 )); msg.put( "added", common_details[0] ); msg.put( "added_s", common_details[1] ); sendMessage( buddy, REQUEST_TRACKER_ADD, msg ); } } } }else if ( type == REPLY_TRACKER_CHANGE || type == REPLY_TRACKER_STATUS || type == REPLY_TRACKER_ADD ){ // nothing interesting in reply for these }else{ log( "Unrecognised type " + type ); } if ( reply_type != -1 ){ Map reply = new HashMap(); reply.put( "type", new Long( reply_type )); if ( msg_out == null ){ msg_out = new HashMap(); } msg_out.put( "seeding", new Long( seeding_only?1:0 )); reply.put( "msg", msg_out ); return( reply ); } return( null ); } protected byte[] exportShortIDs( List downloads ) { byte[] res = new byte[ SHORT_ID_SIZE * downloads.size() ]; for (int i=0;i= TRACK_INTERVAL ){ log( d.getName() + " - tracking", false, true ); bdd.setTrackTime( now ); res.put( d, new Boolean( true )); }else{ res.put( d, new Boolean( false )); } } } } return( res ); } protected void resetTracking( Download download ) { synchronized( this ){ if ( downloads_in_common == null ){ return; } buddyDownloadData bdd = (buddyDownloadData)downloads_in_common.get( download ); if ( bdd != null ){ bdd.resetTrackTime(); } } } protected void log( String str ) { BuddyPluginTracker.this.log( buddy.getName() + ": " + str ); } protected void log( String str, boolean verbose, boolean no_buddy ) { BuddyPluginTracker.this.log( (no_buddy?"":( buddy.getName() + ": ")) + str, verbose ); } } private static class buddyDownloadData { private boolean local_is_complete; private boolean remote_is_complete; private long last_track; protected buddyDownloadData( Download download ) { local_is_complete = download.isComplete( false ); } protected void setLocalComplete( boolean b ) { local_is_complete = b; } protected boolean isLocalComplete() { return( local_is_complete ); } protected void setRemoteComplete( boolean b ) { remote_is_complete = b; } protected boolean isRemoteComplete() { return( remote_is_complete ); } protected void setTrackTime( long time ) { last_track = time; } protected long getTrackTime() { return( last_track ); } protected void resetTrackTime() { last_track = 0; } protected String getString() { return( "lic=" + local_is_complete + ",ric=" + remote_is_complete + ",lt=" + last_track ); } } private static class downloadData { private static final byte[] IV = {(byte)0x7A, (byte)0x7A, (byte)0xAD, (byte)0xAB, (byte)0x8E, (byte)0xBF, (byte)0xCD, (byte)0x39, (byte)0x87, (byte)0x0, (byte)0xA4, (byte)0xB8, (byte)0xFE, (byte)0x40, (byte)0xA2, (byte)0xE8 }; private HashWrapper id; protected downloadData( Download download ) { Torrent t = download.getTorrent(); if ( t != null ){ byte[] hash = t.getHash(); SHA1 sha1 = new SHA1(); sha1.update( ByteBuffer.wrap( IV )); sha1.update( ByteBuffer.wrap( hash )); id = new HashWrapper( sha1.digest() ); } } protected HashWrapper getID() { return( id ); } } } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/tracker/BuddyPluginTrackerListener.java0000644000175000017500000000206711017763500031675 0ustar adrianadrian/* * Created on May 29, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy.tracker; public interface BuddyPluginTrackerListener { public void enabledStateChanged( BuddyPluginTracker tracker, boolean enabled ); public void networkStatusChanged( BuddyPluginTracker tracker, int new_status ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessage.java0000644000175000017500000000444511006714446027522 0ustar adrianadrian/* * Created on Apr 23, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy; import java.util.Map; public class BuddyPluginBuddyMessage { private BuddyPluginBuddyMessageHandler handler; private int id; private int subsystem; private int timeout; private long create_time; private boolean deleted; protected BuddyPluginBuddyMessage( BuddyPluginBuddyMessageHandler _handler, int _id, int _subsystem, Map _request, int _timeout, long _create_time ) throws BuddyPluginException { handler = _handler; id = _id; subsystem = _subsystem; timeout = _timeout; create_time = _create_time; if ( _request != null ){ handler.writeRequest( this, _request ); } } public BuddyPluginBuddy getBuddy() { return( handler.getBuddy()); } public int getID() { return( id ); } public int getSubsystem() { return( subsystem ); } public Map getRequest() throws BuddyPluginException { return( handler.readRequest( this )); } /** * Only available for pending-success messages, so don't make public * @return * @throws BuddyPluginException */ protected Map getReply() throws BuddyPluginException { return( handler.readReply( this )); } protected int getTimeout() { return( timeout ); } protected long getCreateTime() { return( create_time ); } public void delete() { deleted = true; handler.deleteMessage( this ); } public boolean isDeleted() { return( deleted ); } } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/BuddyPluginTimeoutException.java0000644000175000017500000000215611020707052030437 0ustar adrianadrian/* * Created on Jun 1, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy; public class BuddyPluginTimeoutException extends BuddyPluginException { private boolean was_active; protected BuddyPluginTimeoutException( String str, boolean active ) { super( str ); was_active = active; } protected boolean wasActive() { return( was_active ); } } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessageHandler.java0000644000175000017500000005236311132045200031003 0ustar adrianadrian/* * Created on Apr 23, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy; import java.io.File; import java.util.*; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.BEncoder; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.util.CopyOnWriteList; public class BuddyPluginBuddyMessageHandler { private BuddyPluginBuddy buddy; private File store; private Map config_map; private int message_count; private int pending_deletes; private int next_message_id; private CopyOnWriteList listeners = new CopyOnWriteList(); private BuddyPluginBuddyMessage active_message; private long last_failure; private long last_pending_success; protected BuddyPluginBuddyMessageHandler( BuddyPluginBuddy _buddy, File _store ) { buddy = _buddy; store = _store; loadConfig(); if ( message_count > 0 ){ buddy.persistentDispatchPending(); } } public BuddyPluginBuddy getBuddy() { return( buddy ); } public BuddyPluginBuddyMessage queueMessage( int subsystem, Map content, int timeout_millis ) throws BuddyPluginException { BuddyPluginBuddyMessage message; boolean dispatch_pending; synchronized( this ){ int id = next_message_id++; message = new BuddyPluginBuddyMessage( this, id, subsystem, content, timeout_millis, SystemTime.getCurrentTime()); storeMessage( message ); dispatch_pending = message_count == 1; } Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((BuddyPluginBuddyMessageListener)it.next()).messageQueued( message ); }catch( Throwable e ){ Debug.printStackTrace(e); } } if ( dispatch_pending ){ buddy.persistentDispatchPending(); } return( message ); } protected void checkPersistentDispatch() { boolean request_dispatch = false; synchronized( this ){ long now = SystemTime.getCurrentTime(); if ( now < last_failure ){ last_failure = now; } if ( now < last_pending_success ){ last_pending_success = now; } if ( last_pending_success > 0 && now - last_pending_success >= BuddyPlugin.PERSISTENT_MSG_RETRY_PERIOD ){ request_dispatch = true; }else if ( active_message != null || message_count == 0 || last_failure == 0 ){ // no messages pending }else{ request_dispatch = now - last_failure >= BuddyPlugin.PERSISTENT_MSG_RETRY_PERIOD; } } if ( request_dispatch ){ buddy.persistentDispatchPending(); } } protected void persistentDispatch() { checkPendingSuccess(); synchronized( this ){ if ( active_message != null || message_count == 0 ){ return; } List messages = (List)config_map.get( "messages" ); Map map = (Map)messages.get(0); try{ active_message = restoreMessage( map ); }catch( Throwable e ){ // should never happen... Debug.out( "Failed to restore message, deleting it", e ); messages.remove(0); try{ saveConfig(); }catch( Throwable f ){ buddy.log( "Config save failed during delete of bad message", f ); } } } boolean request_ok = false; try{ Map request = active_message.getRequest(); request_ok = true; buddy.sendMessage( active_message.getSubsystem(), request, active_message.getTimeout(), new BuddyPluginBuddyReplyListener() { public void replyReceived( BuddyPluginBuddy from_buddy, Map reply ) { BuddyPluginBuddyMessage message = active_message; // inform listeners before deleting message as it gives them one // last chance to do something with the message if they so desire Iterator it = listeners.iterator(); boolean processing_ok = true; // prematurely reduce message count when informing listeners // so they see the "correct" value try{ synchronized( BuddyPluginBuddyMessageHandler.this ){ pending_deletes++; } while( it.hasNext()){ try{ if ( !((BuddyPluginBuddyMessageListener)it.next()).deliverySucceeded( message, reply )){ processing_ok = false; } }catch( Throwable e ){ Debug.printStackTrace(e); } } }finally{ synchronized( BuddyPluginBuddyMessageHandler.this ){ pending_deletes--; } } if ( processing_ok ){ message.delete(); }else{ synchronized( BuddyPluginBuddyMessageHandler.this ){ boolean found = false; List messages = (List)config_map.get( "messages" ); if ( messages != null ){ for ( int i=0;i 0; last_failure = 0; } if ( messages_queued ){ buddy.persistentDispatchPending(); } } public void sendFailed( BuddyPluginBuddy to_buddy, BuddyPluginException cause ) { BuddyPluginBuddyMessage message = active_message; synchronized( BuddyPluginBuddyMessageHandler.this ){ active_message = null; last_failure = SystemTime.getCurrentTime(); } reportFailed( message, cause, true ); } }); }catch( Throwable cause ){ BuddyPluginBuddyMessage message = active_message; synchronized( this ){ active_message = null; last_failure = SystemTime.getCurrentTime(); } boolean do_subsequent = true; if ( !request_ok && !( cause instanceof BuddyPluginPasswordException )){ buddy.logMessage( "Message request unavailable, deleting message" ); message.delete(); boolean messages_queued = false; synchronized( this ){ last_failure = 0; messages_queued = message_count > 0; } if ( messages_queued ){ do_subsequent = false; buddy.persistentDispatchPending(); } } reportFailed( message, cause, do_subsequent ); } } protected void reportFailed( BuddyPluginBuddyMessage message, Throwable cause, boolean do_subsequent ) { BuddyPluginException b_cause; if ( cause instanceof BuddyPluginException ){ b_cause = (BuddyPluginException)cause; }else{ b_cause = new BuddyPluginException( "Failed to send message", cause ); } reportFailedSupport( message, b_cause ); if ( do_subsequent ){ List other_messages = new ArrayList(); synchronized( this ){ List messages = (List)config_map.get( "messages" ); for (int i=0;i 0 ){ BuddyPluginException o_cause = new BuddyPluginException( "Reporting probable failure to subsequent messages" ); for (int i=0;i retrieveExplicitMessages( int type ) { List result = new ArrayList(); synchronized( this ){ List> messages = (List>)config_map.get( "explicit" ); if ( messages != null ){ for (int i=0;i 0 ){ Map last_msg = (Map)messages.get( message_count - 1 ); next_message_id = ((Long)last_msg.get( "id")).intValue() + 1; } } List pending_success = (List)config_map.get( "pending_success" ); if ( pending_success != null ){ int ps_count = pending_success.size(); if ( ps_count > 0 ){ Map last_msg = (Map)pending_success.get( ps_count - 1 ); next_message_id = Math.max( next_message_id, ((Long)last_msg.get( "id")).intValue() + 1 ); last_pending_success = SystemTime.getCurrentTime(); } } List explicit = (List)config_map.get( "explicit" ); if ( explicit != null ){ int exp_count = explicit.size(); if ( exp_count > 0 ){ Map last_msg = (Map)explicit.get( exp_count - 1 ); next_message_id = Math.max( next_message_id, ((Long)last_msg.get( "id")).intValue() + 1 ); } } } protected void saveConfig() throws BuddyPluginException { File config_file = new File( store, "messages.dat" ); List messages = (List)config_map.get( "messages" ); List pending = (List)config_map.get( "pending_success" ); List explicit = (List)config_map.get( "explicit" ); if ( ( messages == null || messages.size() == 0 ) && ( pending == null || pending.size() == 0 ) && ( explicit == null || explicit.size() == 0 )){ if ( store.exists()){ File[] files = store.listFiles(); for (int i=0;i= participants.size()){ return; } BuddyPluginAZ2.chatParticipant participant = (BuddyPluginAZ2.chatParticipant)participants.get(index); BuddyPluginBuddy buddy = participant.getBuddy(); if ( buddy == null ){ item.setForeground( 0, Colors.red ); }else if ( buddy.isOnline( false )){ item.setForeground( 0, Colors.black ); }else{ item.setForeground( 0, Colors.grey ); } item.setText(0, participant.getName()); } }); // Text final Text text = new Text( shell, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP | SWT.BORDER); grid_data = new GridData(GridData.FILL_HORIZONTAL ); grid_data.horizontalSpan = 2; grid_data.heightHint = 50; text.setLayoutData(grid_data); text.addKeyListener( new KeyListener() { public void keyPressed( KeyEvent e) { if ( e.keyCode == SWT.CR ){ e.doit = false; sendMessage( text.getText()); text.setText( "" ); } } public void keyReleased( KeyEvent e ) { } }); text.setFocus(); shell.addListener( SWT.Traverse, new Listener() { public void handleEvent( Event e ) { if ( e.character == SWT.ESC){ close(); } } }); BuddyPluginAZ2.chatParticipant[] existing_participants = chat.getParticipants(); synchronized( participants ){ participants.addAll( Arrays.asList( existing_participants )); } updateTable( false ); BuddyPluginAZ2.chatMessage[] history = chat.getHistory(); for (int i=0;i 32 ){ buddy_name = buddy_name.substring(0,16) + "..."; } int start = log.getText().length(); if ( msg.startsWith( "/me" )){ msg = msg.substring( 3 ).trim(); String me = "* " + buddy_name + " " + msg; log.append( me ); if ( colour != Colors.black ){ StyleRange styleRange = new StyleRange(); styleRange.start = start; styleRange.length = me.length(); styleRange.foreground = colour; log.setStyleRange(styleRange); } log.append( "\n" ); }else{ String says = lu.getLocalisedMessageText( "azbuddy.chat.says", new String[]{ buddy_name }) + "\n"; log.append( says ); if ( colour != Colors.black ){ StyleRange styleRange = new StyleRange(); styleRange.start = start; styleRange.length = says.length(); styleRange.foreground = colour; log.setStyleRange(styleRange); } log.append( msg + "\n" ); } log.setSelection( log.getText().length()); } } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewInstance.java0000644000175000017500000012724611267524616030376 0ustar adrianadrian/* * Created on Apr 2, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy.swt; import java.net.InetAddress; import java.text.SimpleDateFormat; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginConfig; import org.gudy.azureus2.plugins.ui.UIInputReceiver; import org.gudy.azureus2.plugins.ui.UIInputReceiverListener; import org.gudy.azureus2.plugins.ui.UIInstance; import org.gudy.azureus2.plugins.utils.LocaleUtilities; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.Cursors; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import com.aelitis.azureus.core.security.*; import com.aelitis.azureus.core.util.AZ3Functions; import com.aelitis.azureus.plugins.net.buddy.*; public class BuddyPluginViewInstance implements BuddyPluginListener, BuddyPluginBuddyRequestListener { private static final int LOG_NORMAL = 1; private static final int LOG_SUCCESS = 2; private static final int LOG_ERROR = 3; private BuddyPlugin plugin; private UIInstance ui_instance; private Composite composite; private Table buddy_table; private StyledText log; private List buddies = new ArrayList(); private boolean init_complete; protected BuddyPluginViewInstance( BuddyPlugin _plugin, UIInstance _ui_instance, Composite _composite ) { plugin = _plugin; ui_instance = _ui_instance; composite = _composite; final LocaleUtilities lu = plugin.getPluginInterface().getUtilities().getLocaleUtilities(); Composite main = new Composite(composite, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.marginHeight = 0; layout.marginWidth = 0; main.setLayout(layout); GridData grid_data = new GridData(GridData.FILL_BOTH ); main.setLayoutData(grid_data); if ( !plugin.isEnabled()){ Label control_label = new Label( main, SWT.NULL ); control_label.setText( lu.getLocalisedMessageText( "azbuddy.disabled" )); return; } // control area final Composite controls = new Composite(main, SWT.NONE); layout = new GridLayout(); layout.numColumns = 6; layout.marginHeight = 0; layout.marginWidth = 0; controls.setLayout(layout); grid_data = new GridData(GridData.FILL_HORIZONTAL ); controls.setLayoutData(grid_data); Label control_label = new Label( controls, SWT.NULL ); control_label.setText( lu.getLocalisedMessageText( "azbuddy.ui.new_buddy" ) + " " ); final Text control_text = new Text( controls, SWT.BORDER ); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); control_text.setLayoutData(gridData); final Button control_button = new Button( controls, SWT.NULL ); control_button.setText( lu.getLocalisedMessageText( "azbuddy.ui.add" )); control_button.setEnabled( false ); control_text.addModifyListener( new ModifyListener() { public void modifyText( ModifyEvent e ) { control_button.setEnabled( plugin.verifyPublicKey( control_text.getText().trim())); } }); control_button.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { plugin.addBuddy( control_text.getText().trim(), BuddyPlugin.SUBSYSTEM_AZ2 ); control_text.setText( "" ); } }); final Label control_lab_pk = new Label( controls, SWT.NULL ); control_lab_pk.setText( lu.getLocalisedMessageText( "azbuddy.ui.mykey" ) + " "); final Text control_val_pk = new Text( controls, SWT.NULL ); gridData = new GridData(); gridData.widthHint = 400; control_val_pk.setLayoutData(gridData); control_val_pk.setEditable( false ); control_val_pk.setBackground( control_lab_pk.getBackground()); control_val_pk.addKeyListener( new KeyListener() { public void keyPressed( KeyEvent event) { int key = event.character; if (key <= 26 && key > 0){ key += 'a' - 1; } if ( event.stateMask == SWT.MOD1 && key == 'a' ){ control_val_pk.setSelection( 0, control_val_pk.getText().length()); } } public void keyReleased( KeyEvent event) { } }); final CryptoManager crypt_man = CryptoManagerFactory.getSingleton(); byte[] public_key = crypt_man.getECCHandler().peekPublicKey(); if ( public_key == null ){ Messages.setLanguageText(control_val_pk, "ConfigView.section.security.publickey.undef"); }else{ control_val_pk.setText( Base32.encode( public_key )); } Messages.setLanguageText(control_val_pk, "ConfigView.copy.to.clipboard.tooltip", true); control_val_pk.setCursor(Cursors.handCursor); control_val_pk.setForeground(Colors.blue); control_val_pk.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { copyToClipboard(); } public void mouseDown(MouseEvent arg0) { copyToClipboard(); } protected void copyToClipboard() { new Clipboard(control_val_pk.getDisplay()).setContents(new Object[] {control_val_pk.getText()}, new Transfer[] {TextTransfer.getInstance()}); } }); crypt_man.addKeyListener( new CryptoManagerKeyListener() { public void keyChanged( final CryptoHandler handler ) { if ( control_val_pk.isDisposed()){ crypt_man.removeKeyListener( this ); }else if ( handler.getType() == CryptoManager.HANDLER_ECC ){ control_val_pk.getDisplay().asyncExec( new Runnable() { public void run() { byte[] public_key = handler.peekPublicKey(); if ( public_key == null ){ Messages.setLanguageText(control_val_pk, "ConfigView.section.security.publickey.undef"); }else{ control_val_pk.setText( Base32.encode( public_key )); } controls.layout(); } }); } } public void keyLockStatusChanged( CryptoHandler handler ) { } }); final Button config_button = new Button( controls, SWT.NULL ); config_button.setText( lu.getLocalisedMessageText( "plugins.basicview.config" )); config_button.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { plugin.showConfig(); } }); // table and log final Composite form = new Composite(main, SWT.NONE); FormLayout flayout = new FormLayout(); flayout.marginHeight = 0; flayout.marginWidth = 0; form.setLayout(flayout); gridData = new GridData(GridData.FILL_BOTH); form.setLayoutData(gridData); final Composite child1 = new Composite(form,SWT.NULL); layout = new GridLayout(); layout.numColumns = 1; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; child1.setLayout(layout); final Sash sash = new Sash(form, SWT.HORIZONTAL); final Composite child2 = new Composite(form,SWT.NULL); layout = new GridLayout(); layout.numColumns = 1; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; child2.setLayout(layout); FormData formData; // child1 formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.top = new FormAttachment(0, 0); child1.setLayoutData(formData); final FormData child1Data = formData; final int SASH_WIDTH = 4; // sash formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.top = new FormAttachment(child1); formData.height = SASH_WIDTH; sash.setLayoutData(formData); // child2 formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.bottom = new FormAttachment(100, 0); formData.top = new FormAttachment(sash); child2.setLayoutData(formData); final PluginConfig pc = plugin.getPluginInterface().getPluginconfig(); sash.setData( "PCT", new Float( pc.getPluginFloatParameter( "swt.sash.position", 0.7f ))); sash.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { if (e.detail == SWT.DRAG){ return; } child1Data.height = e.y + e.height - SASH_WIDTH; form.layout(); Float l = new Float((double)child1.getBounds().height / form.getBounds().height); sash.setData( "PCT", l ); pc.setPluginParameter( "swt.sash.position", l.floatValue()); } }); form.addListener( SWT.Resize, new Listener() { public void handleEvent(Event e) { Float l = (Float) sash.getData( "PCT" ); if ( l != null ){ child1Data.height = (int) (form.getBounds().height * l.doubleValue()); form.layout(); } } }); // table buddy_table = new Table(child1, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL); final String[] headers = { "azbuddy.ui.table.name", "azbuddy.ui.table.online", "azbuddy.ui.table.lastseen", "azbuddy.ui.table.last_ygm", "azbuddy.ui.table.last_msg", "azbuddy.ui.table.loc_cat", "azbuddy.ui.table.rem_cat", "azbuddy.ui.table.read_cat", "azbuddy.ui.table.con", "azbuddy.ui.table.msg_in", "azbuddy.ui.table.msg_out", "azbuddy.ui.table.msg_queued", "MyTrackerView.bytesin", "MyTrackerView.bytesout", "azbuddy.ui.table.ss" }; int[] sizes = { 250, 100, 100, 100, 200, 100, 100, 100, 75, 75, 75, 75, 75, 75, 40 }; int[] aligns = { SWT.LEFT, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.LEFT, SWT.LEFT, SWT.LEFT, SWT.LEFT, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER }; for (int i = 0; i < headers.length; i++){ TableColumn tc = new TableColumn(buddy_table, aligns[i]); tc.setWidth(sizes[i]); Messages.setLanguageText(tc, headers[i]); } buddy_table.setHeaderVisible(true); TableColumn[] columns = buddy_table.getColumns(); columns[0].setData(new Integer(FilterComparator.FIELD_NAME)); columns[1].setData(new Integer(FilterComparator.FIELD_ONLINE)); columns[2].setData(new Integer(FilterComparator.FIELD_LAST_SEEN)); columns[3].setData(new Integer(FilterComparator.FIELD_YGM)); columns[4].setData(new Integer(FilterComparator.FIELD_LAST_MSG)); columns[5].setData(new Integer(FilterComparator.FIELD_LOC_CAT)); columns[6].setData(new Integer(FilterComparator.FIELD_REM_CAT)); columns[7].setData(new Integer(FilterComparator.FIELD_READ_CAT)); columns[8].setData(new Integer(FilterComparator.FIELD_CON)); columns[9].setData(new Integer(FilterComparator.FIELD_MSG_IN)); columns[10].setData(new Integer(FilterComparator.FIELD_MSG_OUT)); columns[11].setData(new Integer(FilterComparator.FIELD_QUEUED)); columns[12].setData(new Integer(FilterComparator.FIELD_BYTES_IN)); columns[13].setData(new Integer(FilterComparator.FIELD_BYTES_OUT)); columns[14].setData(new Integer(FilterComparator.FIELD_SS)); final FilterComparator comparator = new FilterComparator(); Listener sort_listener = new Listener() { public void handleEvent( Event e ) { TableColumn tc = (TableColumn) e.widget; int field = ((Integer) tc.getData()).intValue(); comparator.setField( field ); Collections.sort( buddies,comparator); updateTable(); } }; for (int i=0;i= buddies.size()){ return; } BuddyPluginBuddy buddy = (BuddyPluginBuddy)buddies.get(index); item.setText(0, buddy.getName()); int os; if ( buddy.isOnline( false )){ os = buddy.getOnlineStatus(); }else{ os = BuddyPlugin.STATUS_APPEAR_OFFLINE; } if ( os == BuddyPlugin.STATUS_APPEAR_OFFLINE ){ item.setText( 1, "" ); }else{ item.setText(1, plugin.getOnlineStatus( os )); } long lo = buddy.getLastTimeOnline(); item.setText(2, lo==0?"":new SimpleDateFormat().format(new Date( lo ))); long last_ygm = buddy.getLastMessagePending();; item.setText(3, last_ygm==0?"":new SimpleDateFormat().format(new Date( last_ygm ))); String lm = buddy.getLastMessageReceived(); item.setText(4, lm==null?"":lm); String loc_cat = buddy.getLocalAuthorisedRSSCategoriesAsString(); if ( loc_cat == null ){ loc_cat = ""; } item.setText(5, "" + loc_cat); String rem_cat = buddy.getRemoteAuthorisedRSSCategoriesAsString(); if ( rem_cat == null ){ rem_cat = ""; } item.setText(6, "" + rem_cat); String read_cat = buddy.getLocalReadCategoriesAsString(); if ( read_cat == null ){ read_cat = ""; } item.setText(7, "" + read_cat); item.setText(8, "" + buddy.getConnectionsString()); String in_frag = buddy.getMessageInFragmentDetails(); item.setText(9, "" + buddy.getMessageInCount() + (in_frag.length()==0?"":("+" + in_frag ))); item.setText(10, "" + buddy.getMessageOutCount()); item.setText(11, "" + buddy.getMessageHandler().getMessageCount()); item.setText(12, "" + DisplayFormatters.formatByteCountToKiBEtc(buddy.getBytesInCount())); item.setText(13, "" + DisplayFormatters.formatByteCountToKiBEtc(buddy.getBytesOutCount())); item.setText(14, "" + buddy.getSubsystem() + " v" + buddy.getVersion()); item.setData( buddy ); } }); final Listener tt_label_listener = new Listener() { public void handleEvent(Event event) { Label label = (Label) event.widget; Shell shell = label.getShell(); switch (event.type) { case SWT.MouseDown: Event e = new Event(); e.item = (TableItem) label.getData("_TABLEITEM"); buddy_table.setSelection(new TableItem[] { (TableItem) e.item }); buddy_table.notifyListeners(SWT.Selection, e); // fall through case SWT.MouseExit: shell.dispose(); break; } } }; Listener tt_table_listener = new Listener() { private Shell tip = null; private Label label = null; public void handleEvent( Event event ) { switch (event.type){ case SWT.Dispose: case SWT.KeyDown: case SWT.MouseMove: { if (tip == null) break; tip.dispose(); tip = null; label = null; break; } case SWT.MouseHover: { Point mouse_position = new Point(event.x, event.y); TableItem item = buddy_table.getItem( mouse_position ); if (item != null) { if (tip != null && !tip.isDisposed()){ tip.dispose(); tip = null; } int index = buddy_table.indexOf(item); if ( index < 0 || index >= buddies.size()){ return; } BuddyPluginBuddy buddy = (BuddyPluginBuddy)buddies.get(index); int item_index = 0; for (int i=0;i 0 ){ writeToClipboard( sb.toString()); } }; }); // disconnect message if ( Constants.isCVSVersion()){ final MenuItem send_msg_item = new MenuItem(menu, SWT.PUSH); send_msg_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.disconnect" ) ); send_msg_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { TableItem[] selection = buddy_table.getSelection(); for (int i=0;i 0 ){ int pos = bit.indexOf( ':' ); if ( pos == -1 ){ continue; } String lhs = bit.substring( 0, pos ).trim(); String rhs = bit.substring( pos+1 ).trim(); if ( lhs.equals( "key" )){ buddy = plugin.getBuddyFromPublicKey( rhs ); }else if ( lhs.equals( "hash" )){ hash = Base32.decode( rhs ); }else if ( lhs.equals( "payload" )){ byte[] payload = Base32.decode( rhs ); if ( buddy != null ){ try{ BuddyPlugin.cryptoResult result = buddy.decrypt( payload ); byte[] sha1 = new SHA1Simple().calculateHash( result.getChallenge()); sb.append( "key: " ); sb.append( buddy.getPublicKey()); sb.append( "\r\n" ); sb.append( "hash_ok: " + Arrays.equals( hash, sha1 )); sb.append( "\r\n" ); sb.append( "payload: " ); sb.append( new String( result.getPayload(), "UTF-8" )); sb.append( "\r\n\r\n" ); }catch( Throwable e ){ print( "decrypt failed", e ); } } } } } if ( sb.length() > 0 ){ writeToClipboard( sb.toString()); } } }; }); // sign final MenuItem sign_item = new MenuItem(menu, SWT.PUSH); sign_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.sign" ) ); sign_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { String str = readFromClipboard(); if ( str != null ){ StringBuffer sb = new StringBuffer(); try{ sb.append( "key: " ); sb.append( plugin.getPublicKey()); sb.append( "\r\n" ); byte[] payload = str.getBytes( "UTF-8" ); sb.append( "data: " ); sb.append( Base32.encode( payload )); sb.append( "\r\n" ); byte[] sig = plugin.sign( payload ); sb.append( "sig: " ); sb.append( Base32.encode( sig )); sb.append( "\r\n" ); }catch( Throwable e ){ print( "sign failed", e ); } if ( sb.length() > 0 ){ writeToClipboard( sb.toString()); } } }; }); // verify final MenuItem verify_item = new MenuItem(menu, SWT.PUSH); verify_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.verify" ) ); verify_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { String str = readFromClipboard(); if ( str != null ){ String[] bits = str.split( "\n" ); StringBuffer sb = new StringBuffer(); String pk = null; byte[] data = null; for (int i=0;i 0 ){ int pos = bit.indexOf( ':' ); if ( pos == -1 ){ continue; } String lhs = bit.substring( 0, pos ).trim(); String rhs = bit.substring( pos+1 ).trim(); if ( lhs.equals( "key" )){ pk = rhs; }else if ( lhs.equals( "data" )){ data = Base32.decode( rhs ); }else if ( lhs.equals( "sig" )){ byte[] sig = Base32.decode( rhs ); if ( pk != null && data != null ){ try{ sb.append( "key: " ); sb.append( pk ); sb.append( "\r\n" ); boolean ok = plugin.verify( pk, data, sig ); sb.append( "sig_ok: " + ok ); sb.append( "\r\n" ); sb.append( "data: " ); sb.append( new String( data, "UTF-8" )); sb.append( "\r\n\r\n" ); }catch( Throwable e ){ print( "decrypt failed", e ); } } } } } if ( sb.length() > 0 ){ writeToClipboard( sb.toString()); } } }; }); // cats Menu cat_menu = new Menu(menu.getShell(), SWT.DROP_DOWN); MenuItem cat_item = new MenuItem(menu, SWT.CASCADE); Messages.setLanguageText(cat_item, "azbuddy.ui.menu.cat" ); cat_item.setMenu(cat_menu); // cats - share final MenuItem cat_share_item = new MenuItem(cat_menu, SWT.PUSH); cat_share_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.share" ) ); cat_share_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { UIInputReceiver prompter = ui_instance.getInputReceiver(); prompter.setLocalisedTitle( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.set" )); prompter.setLocalisedMessage( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.set_msg" )); prompter.prompt(new UIInputReceiverListener() { public void UIInputReceiverClosed(UIInputReceiver prompter) { String cats = prompter.getSubmittedInput(); if ( cats != null ){ cats = cats.trim(); if ( cats.equalsIgnoreCase( "None" )){ cats = ""; } TableItem[] selection = buddy_table.getSelection(); for (int i=0;i avail_cats = new TreeSet(); for (int i=0;i cats = buddy.getRemoteAuthorisedRSSCategories(); if ( cats != null ){ avail_cats.addAll( cats ); } } for ( final String cat: avail_cats ){ final MenuItem subs_item = new MenuItem( cat_subs_menu, SWT.PUSH ); subs_item.setText( cat ); subs_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { for (int i=0;i 0 ); get_pk_item.setEnabled( available && selection.length > 0 ); send_msg_item.setEnabled(available && selection.length > 0); chat_item.setEnabled(available && selection.length > 0); ping_item.setEnabled(available && selection.length > 0); ygm_item.setEnabled(available && selection.length > 0); encrypt_item.setEnabled(selection.length > 0); decrypt_item.setEnabled(true); sign_item.setEnabled(true); verify_item.setEnabled(true); } public void menuHidden( MenuEvent arg0 ) { } }); // log area log = new StyledText(child2,SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER); grid_data = new GridData(GridData.FILL_BOTH); grid_data.horizontalSpan = 1; grid_data.horizontalIndent = 4; log.setLayoutData(grid_data); log.setIndent( 4 ); buddies = plugin.getBuddies(); for (int i=0;i 32000 ){ log.replaceTextRange( 0, 1024, "" ); start = log.getText().length(); } log.append( str + "\n" ); } Color color; if ( f_log_type == LOG_NORMAL ){ color = Colors.black; }else if ( f_log_type == LOG_SUCCESS ){ color = Colors.green; }else{ color = Colors.red; } if ( color != Colors.black ){ StyleRange styleRange = new StyleRange(); styleRange.start = start; styleRange.length = str.length(); styleRange.foreground = color; log.setStyleRange(styleRange); } log.setSelection( log.getText().length()); } }); } } protected void destroy() { composite = null; plugin.removeListener( this ); plugin.removeRequestListener( this ); } protected class FilterComparator implements Comparator { boolean ascending = false; static final int FIELD_NAME = 0; static final int FIELD_ONLINE = 1; static final int FIELD_LAST_SEEN = 2; static final int FIELD_YGM = 3; static final int FIELD_LAST_MSG = 4; static final int FIELD_LOC_CAT = 5; static final int FIELD_REM_CAT = 6; static final int FIELD_READ_CAT = 7; static final int FIELD_CON = 8; static final int FIELD_MSG_IN = 9; static final int FIELD_MSG_OUT = 10; static final int FIELD_QUEUED = 11; static final int FIELD_BYTES_IN = 12; static final int FIELD_BYTES_OUT = 13; static final int FIELD_SS = 14; int field = FIELD_NAME; public int compare( Object arg0, Object arg1) { BuddyPluginBuddy b1 = (BuddyPluginBuddy) arg0; BuddyPluginBuddy b2 = (BuddyPluginBuddy) arg1; int res = 0; if(field == FIELD_NAME){ res = b1.getName().compareTo( b2.getName()); }else if(field == FIELD_ONLINE){ res = ( b1.isOnline( false )?1:0 ) - ( b2.isOnline( false )?1:0 ); }else if(field == FIELD_LAST_SEEN){ res = sortInt( b1.getLastTimeOnline() - b2.getLastTimeOnline()); }else if(field == FIELD_YGM){ res = sortInt( b1.getLastMessagePending() - b2.getLastMessagePending()); }else if(field == FIELD_LAST_MSG){ res = b1.getLastMessageReceived().compareTo( b2.getLastMessageReceived()); }else if(field == FIELD_LOC_CAT){ res = compareStrings( b1.getLocalAuthorisedRSSCategoriesAsString(), b2.getLocalAuthorisedRSSCategoriesAsString()); }else if(field == FIELD_REM_CAT){ res = compareStrings( b1.getRemoteAuthorisedRSSCategoriesAsString(), b2.getRemoteAuthorisedRSSCategoriesAsString()); }else if(field == FIELD_READ_CAT){ res = compareStrings( b1.getLocalReadCategoriesAsString(), b2.getLocalReadCategoriesAsString()); }else if(field == FIELD_CON){ res = b1.getConnectionsString().compareTo( b2.getConnectionsString()); }else if(field == FIELD_MSG_IN){ res = b1.getMessageInCount() - b2.getMessageInCount(); }else if(field == FIELD_MSG_OUT){ res = b1.getMessageOutCount() - b2.getMessageOutCount(); }else if(field == FIELD_QUEUED){ res = b1.getMessageHandler().getMessageCount() - b2.getMessageHandler().getMessageCount(); }else if(field == FIELD_BYTES_IN){ res = b1.getBytesInCount() - b2.getBytesInCount(); }else if(field == FIELD_BYTES_OUT){ res = b1.getBytesOutCount() - b2.getBytesOutCount(); }else if(field == FIELD_SS){ res = b1.getSubsystem() - b2.getSubsystem(); } return(( ascending ? 1 : -1) * res ); } protected int compareStrings( String s1, String s2 ) { if ( s1 == null && s2 == null ){ return(0); }else if ( s1 == null ){ return(-1); }else if ( s2 == null ){ return( 1 ); }else{ return( s1.compareTo(s2)); } } protected int sortInt( long l ) { if ( l < 0 ){ return( -1 ); }else if ( l > 0 ){ return( 1 ); }else{ return( 0 ); } } public void setField( int newField ) { if(field == newField) ascending = ! ascending; field = newField; } } } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginView.java0000644000175000017500000002441211276176312026674 0ustar adrianadrian/* * Created on Mar 19, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy.swt; import java.net.URL; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.plugins.UISWTInstance; import org.gudy.azureus2.ui.swt.plugins.UISWTStatusEntry; import org.gudy.azureus2.ui.swt.plugins.UISWTStatusEntryListener; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import com.aelitis.azureus.core.security.CryptoHandler; import com.aelitis.azureus.core.security.CryptoManager; import com.aelitis.azureus.core.security.CryptoManagerFactory; import com.aelitis.azureus.core.security.CryptoManagerKeyListener; import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin; import com.aelitis.azureus.plugins.net.buddy.BuddyPluginAZ2; import com.aelitis.azureus.plugins.net.buddy.BuddyPluginAZ2Listener; import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddy; import com.aelitis.azureus.plugins.net.buddy.BuddyPluginListener; import com.aelitis.azureus.plugins.net.buddy.tracker.BuddyPluginTracker; import com.aelitis.azureus.plugins.net.buddy.tracker.BuddyPluginTrackerListener; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; public class BuddyPluginView implements UISWTViewEventListener { private BuddyPlugin plugin; private UISWTInstance ui_instance; private BuddyPluginViewInstance current_instance; private Image iconNLI; private Image iconIDLE; private Image iconIN; private Image iconOUT; public BuddyPluginView( BuddyPlugin _plugin, UISWTInstance _ui_instance ) { plugin = _plugin; ui_instance = _ui_instance; plugin.getAZ2Handler().addListener( new BuddyPluginAZ2Listener() { public void chatCreated( final BuddyPluginAZ2.chatInstance chat ) { final Display display = ui_instance.getDisplay(); if ( !display.isDisposed()){ display.asyncExec( new Runnable() { public void run() { if ( !display.isDisposed()){ new BuddyPluginViewChat( plugin, display, chat ); } } }); } } public void chatDestroyed( BuddyPluginAZ2.chatInstance chat ) { } }); SimpleTimer.addEvent("BuddyStatusInit", SystemTime.getOffsetTime(1000), new TimerEventPerformer() { public void perform( TimerEvent event ) { UISWTStatusEntry label = ui_instance.createStatusEntry(); label.setText(MessageText.getString("azbuddy.tracker.bbb.status.title")); new statusUpdater(ui_instance); } }); Utils.execSWTThread(new AERunnable() { public void runSupport() { ImageLoader imageLoader = ImageLoader.getInstance(); iconNLI = imageLoader.getImage( "bbb_nli" ); iconIDLE = imageLoader.getImage( "bbb_idle" ); iconIN = imageLoader.getImage( "bbb_in" ); iconOUT = imageLoader.getImage( "bbb_out" ); } }); } public boolean eventOccurred( UISWTViewEvent event ) { switch( event.getType() ){ case UISWTViewEvent.TYPE_CREATE:{ if ( current_instance != null ){ return( false ); } break; } case UISWTViewEvent.TYPE_INITIALIZE:{ current_instance = new BuddyPluginViewInstance(plugin, ui_instance, (Composite)event.getData()); break; } case UISWTViewEvent.TYPE_CLOSE: case UISWTViewEvent.TYPE_DESTROY:{ try{ if ( current_instance != null ){ current_instance.destroy(); } }finally{ current_instance = null; } break; } } return true; } protected class statusUpdater implements BuddyPluginTrackerListener { private UISWTStatusEntry label; private UISWTStatusEntry status; private BuddyPluginTracker tracker; private TimerEventPeriodic update_event; private CryptoManager crypto; private boolean crypto_ok; private boolean has_buddies; protected statusUpdater( UISWTInstance instance ) { status = ui_instance.createStatusEntry(); label = ui_instance.createStatusEntry(); label.setText( MessageText.getString( "azbuddy.tracker.bbb.status.title" )); label.setTooltipText( MessageText.getString( "azbuddy.tracker.bbb.status.title.tooltip" )); tracker = plugin.getTracker(); status.setText( "" ); status.setImageEnabled( true ); tracker.addListener( this ); has_buddies = plugin.getBuddies().size() > 0; status.setVisible( tracker.isEnabled() && has_buddies); label.setVisible( tracker.isEnabled() && has_buddies); /* MenuItem mi = plugin.getPluginInterface().getUIManager().getMenuManager().addMenuItem( status.getMenuContext(), "dweeble" ); mi.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { System.out.println( "whee" ); } }); */ UISWTStatusEntryListener click_listener = new UISWTStatusEntryListener() { public void entryClicked( UISWTStatusEntry entry ) { try{ plugin.getPluginInterface().getUIManager().openURL( new URL( "http://faq.vuze.com/?View=entry&EntryID=239" )); }catch( Throwable e ){ Debug.printStackTrace(e); } } }; status.setListener( click_listener ); label.setListener( click_listener ); plugin.addListener( new BuddyPluginListener() { public void initialised( boolean available ) { } public void buddyAdded( BuddyPluginBuddy buddy ) { if ( !has_buddies ){ has_buddies = true; updateStatus(); } } public void buddyRemoved( BuddyPluginBuddy buddy ) { has_buddies = plugin.getBuddies().size() > 0; if ( !has_buddies ){ updateStatus(); } } public void buddyChanged( BuddyPluginBuddy buddy ) { } public void messageLogged( String str, boolean error ) { } public void enabledStateChanged( boolean enabled ) { } }); crypto = CryptoManagerFactory.getSingleton(); crypto.addKeyListener( new CryptoManagerKeyListener() { public void keyChanged( CryptoHandler handler ) { } public void keyLockStatusChanged( CryptoHandler handler ) { boolean ok = crypto.getECCHandler().isUnlocked(); if ( ok != crypto_ok ){ crypto_ok = ok; updateStatus(); } } }); crypto_ok = crypto.getECCHandler().isUnlocked(); updateStatus(); } public void networkStatusChanged( BuddyPluginTracker tracker, int new_status ) { updateStatus(); } protected synchronized void updateStatus() { if ( tracker.isEnabled() && has_buddies ){ status.setVisible( true ); label.setVisible( true ); if ( has_buddies && !crypto_ok ){ status.setImage( iconNLI ); status.setTooltipText( MessageText.getString( "azbuddy.tracker.bbb.status.nli" )); disableUpdates(); }else{ int network_status = tracker.getNetworkStatus(); if ( network_status == BuddyPluginTracker.BUDDY_NETWORK_IDLE ){ status.setImage( iconIDLE ); status.setTooltipText( MessageText.getString( "azbuddy.tracker.bbb.status.idle" )); disableUpdates(); }else if ( network_status == BuddyPluginTracker.BUDDY_NETWORK_INBOUND ){ status.setImage( iconIN ); enableUpdates(); }else{ status.setImage( iconOUT ); enableUpdates(); } } }else{ disableUpdates(); status.setVisible( false ); label.setVisible( false ); } } protected void enableUpdates() { if ( update_event == null ){ update_event = SimpleTimer.addPeriodicEvent( "Buddy:GuiUpdater", 2500, new TimerEventPerformer() { public void perform( TimerEvent event ) { synchronized( statusUpdater.this ){ if ( tracker.isEnabled() && ( crypto_ok || !has_buddies )){ String tt; int ns = tracker.getNetworkStatus(); if ( ns == BuddyPluginTracker.BUDDY_NETWORK_IDLE ){ tt = MessageText.getString( "azbuddy.tracker.bbb.status.idle" ); }else if ( ns == BuddyPluginTracker.BUDDY_NETWORK_INBOUND ){ tt = MessageText.getString( "azbuddy.tracker.bbb.status.in" ) + ": " + DisplayFormatters.formatByteCountToKiBEtcPerSec( tracker.getNetworkReceiveBytesPerSecond()); }else{ tt = MessageText.getString( "azbuddy.tracker.bbb.status.out" ) + ": " + DisplayFormatters.formatByteCountToKiBEtcPerSec( tracker.getNetworkSendBytesPerSecond()); } status.setTooltipText( tt ); } } } }); } } protected void disableUpdates() { if ( update_event != null ){ update_event.cancel(); update_event = null; } } public void enabledStateChanged( BuddyPluginTracker tracker, boolean enabled ) { updateStatus(); } } } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyRequestListener.java0000644000175000017500000000306711001330650031255 0ustar adrianadrian/* * Created on Apr 4, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy; import java.util.Map; public interface BuddyPluginBuddyRequestListener { /** * Request receieved for a buddy. If the buddy is not authorised then the BuddyPluginBuddy * is transient and should only be used for the duration of this request. Use outside of * this context is undefined. If you want to authorise a transient buddy then you need * to call BuddyPlugin.addBuddy with the required public key * * @param from_buddy * @param subsystem * @param request * @return * @throws BuddyPluginException */ public Map requestReceived( BuddyPluginBuddy from_buddy, int subsystem, Map request ) throws BuddyPluginException; public void pendingMessages( BuddyPluginBuddy[] from_buddies ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAdapter.java0000644000175000017500000000240711021353642026514 0ustar adrianadrian/* * Created on Jun 3, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy; public class BuddyPluginAdapter implements BuddyPluginListener { public void initialised( boolean available ) { } public void buddyAdded( BuddyPluginBuddy buddy ) { } public void buddyRemoved( BuddyPluginBuddy buddy ) { } public void buddyChanged( BuddyPluginBuddy buddy ) { } public void messageLogged( String str, boolean is_error ) { } public void enabledStateChanged( boolean enabled) { } } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyReplyListener.java0000644000175000017500000000207610777324122030737 0ustar adrianadrian/* * Created on Apr 3, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy; import java.util.Map; public interface BuddyPluginBuddyReplyListener { public void replyReceived( BuddyPluginBuddy from_buddy, Map reply ); public void sendFailed( BuddyPluginBuddy to_buddy, BuddyPluginException cause ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2.java0000644000175000017500000004710711147377516025555 0ustar adrianadrian/* * Created on Apr 10, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy; import java.security.SecureRandom; import java.util.*; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.RandomUtils; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.ui.UIManagerEvent; import com.aelitis.azureus.core.util.CopyOnWriteList; public class BuddyPluginAZ2 { public static final int RT_AZ2_REQUEST_MESSAGE = 1; public static final int RT_AZ2_REPLY_MESSAGE = 2; public static final int RT_AZ2_REQUEST_SEND_TORRENT = 3; public static final int RT_AZ2_REPLY_SEND_TORRENT = 4; public static final int RT_AZ2_REQUEST_CHAT = 5; public static final int RT_AZ2_REPLY_CHAT = 6; public static final int RT_AZ2_REQUEST_TRACK = 7; public static final int RT_AZ2_REPLY_TRACK = 8; public static final int RT_AZ2_REQUEST_RSS = 9; public static final int RT_AZ2_REPLY_RSS = 10; public static final int CHAT_MSG_TYPE_TEXT = 1; public static final int CHAT_MSG_TYPE_PARTICIPANTS_ADDED = 2; public static final int CHAT_MSG_TYPE_PARTICIPANTS_REMOVED = 3; private static final int SEND_TIMEOUT = 2*60*1000; private BuddyPlugin plugin; private Map chats = new HashMap(); private CopyOnWriteList listeners = new CopyOnWriteList(); private CopyOnWriteList track_listeners = new CopyOnWriteList(); protected BuddyPluginAZ2( BuddyPlugin _plugin ) { plugin = _plugin; plugin.addRequestListener( new BuddyPluginBuddyRequestListener() { public Map requestReceived( BuddyPluginBuddy from_buddy, int subsystem, Map request ) throws BuddyPluginException { if ( subsystem == BuddyPlugin.SUBSYSTEM_AZ2 ){ if ( !from_buddy.isAuthorised()){ throw( new BuddyPluginException( "Unauthorised" )); } return( processAZ2Request( from_buddy, request )); } return( null ); } public void pendingMessages( BuddyPluginBuddy[] from_buddies ) { } }); } protected Map processAZ2Request( final BuddyPluginBuddy from_buddy, Map request ) throws BuddyPluginException { logMessage( "AZ2 request received: " + from_buddy.getString() + " -> " + request ); int type = ((Long)request.get( "type" )).intValue(); Map reply = new HashMap(); if ( type == RT_AZ2_REQUEST_MESSAGE ){ try{ String msg = new String( (byte[])request.get( "msg" ), "UTF8" ); from_buddy.setLastMessageReceived( msg ); }catch( Throwable e ){ } reply.put( "type", new Long( RT_AZ2_REPLY_MESSAGE )); }else if ( type == RT_AZ2_REQUEST_SEND_TORRENT ){ try{ final Torrent torrent = plugin.getPluginInterface().getTorrentManager().createFromBEncodedData((byte[])request.get( "torrent" )); new AEThread2( "torrentAdder", true ) { public void run() { PluginInterface pi = plugin.getPluginInterface(); String msg = pi.getUtilities().getLocaleUtilities().getLocalisedMessageText( "azbuddy.addtorrent.msg", new String[]{ from_buddy.getName(), torrent.getName() }); long res = pi.getUIManager().showMessageBox( "azbuddy.addtorrent.title", "!" + msg + "!", UIManagerEvent.MT_YES | UIManagerEvent.MT_NO ); if ( res == UIManagerEvent.MT_YES ){ pi.getUIManager().openTorrent( torrent ); } } }.start(); reply.put( "type", new Long( RT_AZ2_REPLY_SEND_TORRENT )); }catch( Throwable e ){ throw( new BuddyPluginException( "Torrent receive failed " + type )); } }else if ( type == RT_AZ2_REQUEST_CHAT ){ Map msg = (Map)request.get( "msg" ); String id = new String((byte[])msg.get( "id" )); chatInstance chat; boolean new_chat = false; synchronized( chats ){ chat = (chatInstance)chats.get( id ); if ( chat == null ){ if ( chats.size() > 32 ){ throw( new BuddyPluginException( "Too many chats" )); } chat = new chatInstance( id ); chats.put( id, chat ); new_chat = true; } } if ( new_chat ){ informCreated( chat ); } chat.addParticipant( from_buddy ); chat.process( from_buddy, msg ); reply.put( "type", new Long( RT_AZ2_REPLY_CHAT )); }else if ( type == RT_AZ2_REQUEST_TRACK ){ Map msg = (Map)request.get( "msg" ); Iterator it = track_listeners.iterator(); boolean ok = false; while( it.hasNext()){ try{ Map res = ((BuddyPluginAZ2TrackerListener)it.next()).messageReceived( from_buddy, msg ); if ( res != null ){ reply.put( "msg", res ); reply.put( "type", new Long( RT_AZ2_REPLY_TRACK )); ok = true; break; } }catch( Throwable e ){ Debug.printStackTrace(e); } } if ( !ok ){ throw( new BuddyPluginException( "Unhandled request type " + type )); } }else if ( type == RT_AZ2_REQUEST_RSS ){ try{ Map res = new HashMap(); reply.put( "msg", res ); reply.put( "type", new Long( RT_AZ2_REPLY_RSS )); Map msg = (Map)request.get( "msg" ); String category = new String((byte[])msg.get( "cat"), "UTF-8" ); byte[] hash = (byte[])msg.get( "hash" ); if ( hash == null ){ byte[] if_mod = (byte[])msg.get( "if_mod" ); BuddyPlugin.feedDetails feed = plugin.getRSS( from_buddy, category, if_mod==null?null:new String( if_mod, "UTF-8" )); res.put( "rss", feed.getContent()); res.put( "last_mod", feed.getLastModified()); }else{ res.put( "torrent", plugin.getRSSTorrent( from_buddy, category, hash )); } }catch( BuddyPluginException e ){ throw( e ); }catch( Throwable e ){ throw( new BuddyPluginException( "Failed to handle rss", e )); } }else{ throw( new BuddyPluginException( "Unrecognised request type " + type )); } logMessage( "AZ2 reply sent: " + from_buddy.getString() + " <- " + reply ); return( reply ); } public chatInstance createChat( BuddyPluginBuddy[] buddies ) { byte[] id_bytes = new byte[20]; RandomUtils.SECURE_RANDOM.nextBytes( id_bytes ); String id = Base32.encode( id_bytes ); chatInstance chat; synchronized( chats ){ chat = new chatInstance( id ); chats.put( id, chat ); } logMessage( "Chat " + chat.getID() + " created" ); informCreated( chat ); chat.addParticipants( buddies, true ); return( chat ); } protected void destroyChat( chatInstance chat ) { synchronized( chats ){ chats.remove( chat.getID()); } logMessage( "Chat " + chat.getID() + " destroyed" ); informDestroyed( chat ); } protected void informCreated( chatInstance chat ) { Iterator it = listeners.iterator(); while( it.hasNext()){ ((BuddyPluginAZ2Listener)it.next()).chatCreated( chat ); } } protected void informDestroyed( chatInstance chat ) { Iterator it = listeners.iterator(); while( it.hasNext()){ ((BuddyPluginAZ2Listener)it.next()).chatDestroyed( chat ); } } public void sendAZ2Message( BuddyPluginBuddy buddy, String msg ) { try{ Map request = new HashMap(); request.put( "type", new Long( RT_AZ2_REQUEST_MESSAGE )); request.put( "msg", msg.getBytes()); sendMessage( buddy, request ); }catch( Throwable e ){ logMessageAndPopup( "Send message failed", e ); } } protected void sendAZ2Chat( BuddyPluginBuddy buddy, Map msg ) { try{ Map request = new HashMap(); request.put( "type", new Long( RT_AZ2_REQUEST_CHAT )); request.put( "msg", msg ); sendMessage( buddy, request ); }catch( Throwable e ){ logMessageAndPopup( "Send message failed", e ); } } public void sendAZ2Torrent( Torrent torrent, BuddyPluginBuddy buddy ) { try{ Map request = new HashMap(); request.put( "type", new Long( RT_AZ2_REQUEST_SEND_TORRENT )); request.put( "torrent", torrent.writeToBEncodedData()); sendMessage( buddy, request ); }catch( Throwable e ){ logMessageAndPopup( "Send torrent failed", e ); } } public void sendAZ2TrackerMessage( BuddyPluginBuddy buddy, Map msg, final BuddyPluginAZ2TrackerListener listener ) { logMessage( "AZ2 request sent: " + buddy.getString() + " <- " + msg ); try{ Map request = new HashMap(); request.put( "type", new Long( RT_AZ2_REQUEST_TRACK )); request.put( "msg", msg ); buddy.sendMessage( BuddyPlugin.SUBSYSTEM_AZ2, request, SEND_TIMEOUT, new BuddyPluginBuddyReplyListener() { public void replyReceived( BuddyPluginBuddy from_buddy, Map reply ) { int type = ((Long)reply.get( "type")).intValue(); if ( type != RT_AZ2_REPLY_TRACK ){ sendFailed( from_buddy, new BuddyPluginException( "Mismatched reply type" )); } listener.messageReceived( from_buddy, (Map)reply.get( "msg" )); } public void sendFailed( BuddyPluginBuddy to_buddy, BuddyPluginException cause ) { listener.messageFailed( to_buddy, cause ); } }); }catch( Throwable e ){ logMessageAndPopup( "Send message failed", e ); } } public void sendAZ2RSSMessage( BuddyPluginBuddy buddy, Map msg, final BuddyPluginAZ2TrackerListener listener ) { logMessage( "AZ2 request sent: " + buddy.getString() + " <- " + msg ); try{ Map request = new HashMap(); request.put( "type", new Long( RT_AZ2_REQUEST_RSS )); request.put( "msg", msg ); buddy.sendMessage( BuddyPlugin.SUBSYSTEM_AZ2, request, SEND_TIMEOUT, new BuddyPluginBuddyReplyListener() { public void replyReceived( BuddyPluginBuddy from_buddy, Map reply ) { int type = ((Long)reply.get( "type")).intValue(); if ( type != RT_AZ2_REPLY_RSS ){ sendFailed( from_buddy, new BuddyPluginException( "Mismatched reply type" )); } listener.messageReceived( from_buddy, (Map)reply.get( "msg" )); } public void sendFailed( BuddyPluginBuddy to_buddy, BuddyPluginException cause ) { listener.messageFailed( to_buddy, cause ); } }); }catch( Throwable e ){ logMessage( "Send message failed", e ); } } protected void sendMessage( BuddyPluginBuddy buddy, Map request ) throws BuddyPluginException { logMessage( "AZ2 request sent: " + buddy.getString() + " <- " + request ); buddy.getMessageHandler().queueMessage( BuddyPlugin.SUBSYSTEM_AZ2, request, SEND_TIMEOUT ); } public void addListener( BuddyPluginAZ2Listener listener ) { listeners.add( listener ); } public void removeListener( BuddyPluginAZ2Listener listener ) { listeners.remove( listener ); } public void addTrackerListener( BuddyPluginAZ2TrackerListener listener ) { track_listeners.add( listener ); } public void removeTrackerListener( BuddyPluginAZ2TrackerListener listener ) { track_listeners.remove( listener ); } protected void logMessageAndPopup( String str, Throwable e ) { logMessageAndPopup( str + ": " + Debug.getNestedExceptionMessage(e)); } protected void logMessageAndPopup( String str ) { logMessage( str ); plugin.getPluginInterface().getUIManager().showMessageBox( "azbuddy.msglog.title", "!" + str + "!", UIManagerEvent.MT_OK ); } protected void logMessage( String str ) { plugin.logMessage( str ); } protected void logMessage( String str, Throwable e ) { plugin.logMessage( str + ": " + Debug.getNestedExceptionMessage(e)); } public class chatInstance extends BuddyPluginAdapter { private String id; private Map participants = new HashMap(); private CopyOnWriteList listeners = new CopyOnWriteList(); private List history = new ArrayList(); protected chatInstance( String _id ) { id = _id; plugin.addListener( this ); } public String getID() { return( id ); } public void buddyAdded( BuddyPluginBuddy buddy ) { buddyChanged( buddy ); } public void buddyRemoved( BuddyPluginBuddy buddy ) { chatParticipant p = getParticipant( buddy ); if ( p != null ){ Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((BuddyPluginAZ2ChatListener)it.next()).participantRemoved( p ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } } public void buddyChanged( BuddyPluginBuddy buddy ) { chatParticipant p = getParticipant( buddy ); if ( p != null ){ Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((BuddyPluginAZ2ChatListener)it.next()).participantChanged( p ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } } protected void process( BuddyPluginBuddy from_buddy, Map msg ) { chatParticipant p = getOrAddParticipant( from_buddy ); int type = ((Long)msg.get( "type")).intValue(); if ( type == CHAT_MSG_TYPE_TEXT ){ Iterator it = listeners.iterator(); synchronized( history ){ history.add( new chatMessage( p.getName(), msg )); if ( history.size() > 128 ){ history.remove(0); } } while( it.hasNext()){ try{ ((BuddyPluginAZ2ChatListener)it.next()).messageReceived( p, msg ); }catch( Throwable e ){ Debug.printStackTrace(e); } } }else if ( type == CHAT_MSG_TYPE_PARTICIPANTS_ADDED ){ List added = (List)msg.get( "p" ); for (int i=0;i buddies = new ArrayList(); private List connected_at_close; private Map buddies_map = new HashMap(); private CopyOnWriteList listeners = new CopyOnWriteList(); private CopyOnWriteList request_listeners = new CopyOnWriteList(); private SESecurityManager sec_man; private GenericMessageRegistration msg_registration; private int inbound_limit; private int outbound_limit; private RateLimiter inbound_limiter = new RateLimiter() { public String getName() { return( "buddy_up" ); } public int getRateLimitBytesPerSecond() { return( inbound_limit ); } }; private RateLimiter outbound_limiter = new RateLimiter() { public String getName() { return( "buddy_down" ); } public int getRateLimitBytesPerSecond() { return( outbound_limit ); } }; private boolean config_dirty; private Random random = RandomUtils.SECURE_RANDOM; private BuddyPluginAZ2 az2_handler; private List publish_write_contacts = new ArrayList(); private int status_seq; { while( status_seq == 0 ){ status_seq = random.nextInt(); } } private Set pd_preinit = new HashSet(); private List pd_queue = new ArrayList(); private AESemaphore pd_queue_sem = new AESemaphore( "BuddyPlugin:persistDispatch"); private AEThread2 pd_thread; private boolean bogus_ygm_written; private BuddyPluginTracker buddy_tracker; private TorrentAttribute ta_category; private Set public_categories = new HashSet(); public static void load( PluginInterface plugin_interface ) { String name = plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( "Views.plugins." + VIEW_ID + ".title" ); plugin_interface.getPluginProperties().setProperty( "plugin.version", "1.0" ); plugin_interface.getPluginProperties().setProperty( "plugin.name", name ); } public void initialize( final PluginInterface _plugin_interface ) { plugin_interface = _plugin_interface; ta_category = plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_CATEGORY ); az2_handler = new BuddyPluginAZ2( this ); sec_man = plugin_interface.getUtilities().getSecurityManager(); logger = plugin_interface.getLogger().getChannel( "Friends" ); logger.setDiagnostic(); final LocaleUtilities lu = plugin_interface.getUtilities().getLocaleUtilities(); lu.addListener( new LocaleListener() { public void localeChanged( Locale l ) { updateLocale(lu); } }); updateLocale(lu); BasicPluginConfigModel config = plugin_interface.getUIManager().createBasicPluginConfigModel( "Views.plugins." + VIEW_ID + ".title" ); // enabled enabled_param = config.addBooleanParameter2( "azbuddy.enabled", "azbuddy.enabled", false ); // nickname nick_name_param = config.addStringParameter2( "azbuddy.nickname", "azbuddy.nickname", "" ); nick_name_param.setGenerateIntermediateEvents( false ); nick_name_param.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { updateNickName( nick_name_param.getValue()); } }); // online status String[] os_values = STATUS_VALUES; String[] os_labels = STATUS_STRINGS; online_status_param = config.addStringListParameter2( "azbuddy.online_status", "azbuddy.online_status", os_values, os_labels, os_values[0] ); online_status_param.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { int status = Integer.parseInt( online_status_param.getValue()); updateOnlineStatus( status ); } }); online_status_param.setVisible( SUPPORT_ONLINE_STATUS ); // If we add this then use proper message texts in the STATUS_STRINGS // protocol speed final IntParameter protocol_speed = config.addIntParameter2( "azbuddy.protocolspeed", "azbuddy.protocolspeed", 32 ); protocol_speed.setMinimumRequiredUserMode( Parameter.MODE_ADVANCED ); inbound_limit = protocol_speed.getValue()*1024; protocol_speed.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { inbound_limit = protocol_speed.getValue()*1024; } }); // chat notifications enable_chat_notifications = config.addBooleanParameter2( "azbuddy.enable_chat_notif", "azbuddy.enable_chat_notif", true ); // default published cats cat_pub = config.addStringParameter2( "azbuddy.enable_cat_pub", "azbuddy.enable_cat_pub", "" ); cat_pub.setGenerateIntermediateEvents( false ); setPublicCats( cat_pub.getValue(), false ); cat_pub.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { setPublicCats( cat_pub.getValue(), false); } }); // config end final TableContextMenuItem menu_item_itorrents = plugin_interface.getUIManager().getTableManager().addContextMenuItem(TableManager.TABLE_MYTORRENTS_INCOMPLETE, "azbuddy.contextmenu"); final TableContextMenuItem menu_item_ctorrents = plugin_interface.getUIManager().getTableManager().addContextMenuItem(TableManager.TABLE_MYTORRENTS_COMPLETE, "azbuddy.contextmenu"); menu_item_itorrents.setStyle(TableContextMenuItem.STYLE_MENU); menu_item_ctorrents.setStyle(TableContextMenuItem.STYLE_MENU); MenuItemFillListener menu_fill_listener = new MenuItemFillListener() { public void menuWillBeShown( MenuItem menu, Object _target ) { menu.removeAllChildItems(); if ( !( isEnabled() && isAvailable())){ menu.setEnabled( false ); return; } final List torrents = new ArrayList(); if ( _target instanceof TableRow ){ addDownload( torrents, (TableRow)_target ); }else{ TableRow[] rows = (TableRow[])_target; for ( TableRow row: rows ){ addDownload( torrents, row ); } } if ( torrents.size() == 0 ){ menu.setEnabled( false ); }else{ List buddies = getBuddies(); boolean incomplete = ((TableContextMenuItem)menu).getTableID() == TableManager.TABLE_MYTORRENTS_INCOMPLETE; TableContextMenuItem parent = incomplete?menu_item_itorrents:menu_item_ctorrents; for (int i=0;i torrents, TableRow row ) { Object obj = row.getDataSource(); Download download; if ( obj instanceof Download ){ download = (Download)obj; }else{ DiskManagerFileInfo file = (DiskManagerFileInfo)obj; try{ download = file.getDownload(); }catch( DownloadException e ){ Debug.printStackTrace(e); return; } } Torrent torrent = download.getTorrent(); if ( torrent != null && !TorrentUtils.isReallyPrivate( PluginCoreUtils.unwrap( torrent ))){ torrents.add( torrent ); } } }; menu_item_itorrents.addFillListener( menu_fill_listener ); menu_item_ctorrents.addFillListener( menu_fill_listener ); buddy_tracker = new BuddyPluginTracker( this, config ); plugin_interface.getUIManager().addUIListener( new UIManagerListener() { public void UIAttached( final UIInstance instance ) { if ( instance instanceof UISWTInstance ){ UISWTInstance swt_ui = (UISWTInstance)instance; BuddyPluginView view = new BuddyPluginView( BuddyPlugin.this, swt_ui ); swt_ui.addView( UISWTInstance.VIEW_MAIN, VIEW_ID, view ); //swt_ui.openMainView( VIEW_ID, view, null ); } setupDisablePrompt(instance); } public void UIDetached( UIInstance instance ) { } }); ParameterListener enabled_listener = new ParameterListener() { public void parameterChanged( Parameter param ) { boolean enabled = enabled_param.getValue(); nick_name_param.setEnabled( enabled ); // only toggle overall state on a real change if ( param != null ){ setEnabledInternal( enabled ); fireEnabledStateChanged(); } } }; enabled_listener.parameterChanged( null ); enabled_param.addListener( enabled_listener ); loadConfig(); registerMessageHandler(); plugin_interface.addListener( new PluginListener() { public void initializationComplete() { final DelayedTask dt = plugin_interface.getUtilities().createDelayedTask(new Runnable() { public void run() { new AEThread2( "BuddyPlugin:init", true ) { public void run() { startup(); } }.start(); } }); dt.queue(); } public void closedownInitiated() { saveConfig( true ); closedown(); } public void closedownComplete() { } }); } protected void updateLocale( LocaleUtilities lu ) { for ( int i=0;i buddies = getBuddies(); for ( BuddyPluginBuddy buddy: buddies ){ if ( buddy.getIP() != null && !buddy.isConnected()){ log( "Attempting reconnect to " + buddy.getString()); buddy.sendKeepAlive(); } } }catch( Throwable e ){ log( "Initialisation failed", e ); fireInitialised( false ); } } public boolean isEnabled() { if (enabled_param == null) {return false;} return( enabled_param.getValue()); } public void setEnabled( boolean enabled ) { if (enabled_param == null) {return;} enabled_param.setValue( enabled ); } protected void setEnabledInternal( boolean _enabled ) { synchronized( this ){ if ( latest_publish.isEnabled() != _enabled ){ publishDetails new_publish = latest_publish.getCopy(); new_publish.setEnabled( _enabled ); updatePublish( new_publish ); } } } public BuddyPluginTracker getTracker() { return( buddy_tracker ); } public String getNickname() { return( nick_name_param.getValue()); } public void setNickname( String str ) { nick_name_param.setValue( str ); } public void setOnlineStatus( int status ) { online_status_param.setValue( "" + status ); } public int getOnlineStatus() { return( latest_publish.getOnlineStatus()); } public BooleanParameter getEnableChatNotificationsParameter() { return( enable_chat_notifications ); } protected String normaliseCat( String str ) { if ( str == null ){ return( null ); }else if ( str.toLowerCase().equals( "all" )){ return( "All" ); }else{ return( str ); } } protected void normaliseCats( Set cats ) { if ( cats != null ){ boolean all_found = false; Iterator it = cats.iterator(); while( it.hasNext()){ if ( it.next().toLowerCase().equals( "all" )){ it.remove(); all_found = true; } } if ( all_found ){ cats.add( "All" ); } } } public boolean isPublicCategory( String cat ) { cat = normaliseCat( cat ); return( public_categories.contains( cat )); } public void addPublicCategory( String cat ) { cat = normaliseCat( cat ); Set new_cats = new HashSet( public_categories ); if ( new_cats.add( cat )){ setPublicCats( new_cats, true ); } } public void removePublicCategory( String cat ) { cat = normaliseCat( cat ); Set new_cats = new HashSet( public_categories ); if ( new_cats.remove( cat )){ setPublicCats( new_cats, true ); } } protected void setPublicCats( String str, boolean persist ) { Set new_pub_cats = new HashSet(); String[] bits = str.split(","); for (String s: bits ){ s = s.trim(); if ( bits.length > 0 ){ new_pub_cats.add( normaliseCat( s )); } } setPublicCats( new_pub_cats, persist ); } protected void setPublicCats( Set new_pub_cats, boolean persist ) { if ( !public_categories.equals( new_pub_cats )){ Set removed = new HashSet( public_categories ); removed.removeAll( new_pub_cats ); public_categories = new_pub_cats; if ( persist ){ String cat_str = ""; for ( String s: public_categories ){ cat_str += (cat_str.length()==0?"":",") + s; } cat_pub.setValue( cat_str ); } List buds = getBuddies(); for ( BuddyPluginBuddy b: buds ){ Set local = b.getLocalAuthorisedRSSCategories(); if ( local != null || new_pub_cats.size() > 0 ){ if ( local == null ){ local = new HashSet(); }else{ // gotta clone else we're messing with stuff that ain't ours local = new HashSet( local ); } local.addAll( new_pub_cats ); local.removeAll( removed ); b.setLocalAuthorisedRSSCategories( local ); } } } } protected void registerMessageHandler() { try{ addRequestListener( new BuddyPluginBuddyRequestListener() { public Map requestReceived( BuddyPluginBuddy from_buddy, int subsystem, Map request ) throws BuddyPluginException { if ( subsystem == SUBSYSTEM_INTERNAL ){ if ( !from_buddy.isAuthorised()){ throw( new BuddyPluginException( "Unauthorised" )); } return( processInternalRequest( from_buddy, request )); } return( null ); } public void pendingMessages( BuddyPluginBuddy[] from_buddies ) { } }); msg_registration = plugin_interface.getMessageManager().registerGenericMessageType( "AZBUDDY", "Buddy message handler", STREAM_CRYPTO, new GenericMessageHandler() { public boolean accept( GenericMessageConnection connection ) throws MessageException { if ( !isEnabled()){ return( false ); } final String originator = connection.getEndpoint().getNotionalAddress().getAddress().getHostAddress(); if ( TRACE ){ System.out.println( "accept " + originator ); } try{ String reason = "Friend: Incoming connection establishment (" + originator + ")"; addRateLimiters( connection ); connection = sec_man.getSTSConnection( connection, sec_man.getPublicKey( SEPublicKey.KEY_TYPE_ECC_192, reason ), new SEPublicKeyLocator() { public boolean accept( Object context, SEPublicKey other_key ) { String other_key_str = Base32.encode( other_key.encodeRawPublicKey()); if ( TRACE ){ System.out.println( "Incoming: acceptKey - " + other_key_str ); } try{ synchronized( BuddyPlugin.this ){ int unauth_count = 0; for (int i=0;i= 8 ){ Debug.out( "Too many recent unauthorised connection attempts from " + originator ); return( true ); } return( false ); } } protected void checkUnauthBloom() { synchronized( this ){ if ( unauth_bloom != null ){ long now = SystemTime.getCurrentTime(); if ( now < unauth_bloom_create_time ){ unauth_bloom_create_time = now; }else if ( now - unauth_bloom_create_time > UNAUTH_BLOOM_RECREATE ){ unauth_bloom = null; } } } } protected void checkMaxMessageSize( int size ) throws BuddyPluginException { if ( size > MAX_MESSAGE_SIZE ){ throw( new BuddyPluginException( "Message is too large to send, limit is " + DisplayFormatters.formatByteCountToKiBEtc( MAX_MESSAGE_SIZE ))); } } protected void checkPersistentDispatch() { List buddies_copy; synchronized( this ){ buddies_copy = new ArrayList( buddies ); } for (int i=0;i= STATUS_STRINGS.length || status < 0 ){ status = 0; } return( STATUS_STRINGS[status] ); } protected boolean stringsEqual( String s1, String s2 ) { if ( s1 == null && s2 == null ){ return( true ); } if ( s1 == null || s2 == null ){ return( false ); } return( s1.equals( s2 )); } protected void updateKey() { synchronized( this ){ publishDetails new_publish = latest_publish.getCopy(); new_publish.setPublicKey( null ); updatePublish( new_publish ); } } protected void updatePublish( final publishDetails details ) { latest_publish = details; if ( ddb == null || !ready_to_publish ){ return; } publish_dispatcher.dispatch( new AERunnable() { public void runSupport() { // only execute the most recent publish if ( publish_dispatcher.getQueueSize() > 0 ){ return; } updatePublishSupport( details ); } }); } protected void updatePublishSupport( publishDetails details ) { byte[] key_to_remove = null; publishDetails existing_details; boolean log_this; synchronized( this ){ log_this = !current_publish.getString().equals( details.getString()); existing_details = current_publish; if ( !details.isEnabled()){ if ( current_publish.isPublished()){ key_to_remove = current_publish.getPublicKey(); } }else{ if ( details.getPublicKey() == null ){ try{ details.setPublicKey( ecc_handler.getPublicKey( "Creating online status key" )); }catch( Throwable e ){ log( "Failed to publish details", e ); return; } } if ( current_publish.isPublished()){ byte[] existing_key = current_publish.getPublicKey(); if ( !Arrays.equals( existing_key, details.getPublicKey())){ key_to_remove = existing_key; } } } current_publish = details; } if ( key_to_remove != null ){ log( "Removing old status publish: " + existing_details.getString()); try{ ddb.delete( new DistributedDatabaseListener() { public void event( DistributedDatabaseEvent event ) { } }, getStatusKey( key_to_remove, "Friend status de-registration for old key" )); }catch( Throwable e ){ log( "Failed to remove existing publish", e ); } } if ( details.isEnabled()){ // ensure we have a sensible ip InetAddress ip = details.getIP(); if ( ip.isLoopbackAddress() || ip.isLinkLocalAddress() || ip.isSiteLocalAddress()){ log( "Can't publish as ip address is invalid: " + details.getString()); return; } details.setPublished( true ); Map payload = new HashMap(); if ( details.getTCPPort() > 0 ){ payload.put( "t", new Long( details.getTCPPort() )); } if ( details.getUDPPort() > 0 ){ payload.put( "u", new Long( details.getUDPPort() )); } payload.put( "i", ip.getAddress()); String nick = details.getNickName(); if ( nick != null ){ if ( nick.length() > 32 ){ nick = nick.substring( 0, 32 ); } payload.put( "n", nick ); } payload.put( "o", new Long( details.getOnlineStatus())); int next_seq = ++status_seq; if ( next_seq == 0 ){ next_seq = ++status_seq; } details.setSequence( next_seq ); payload.put( "s", new Long( next_seq )); payload.put( "v", new Long( VERSION_CURRENT )); boolean failed_to_get_key = true; try{ byte[] data = BEncoder.encode( payload ); DistributedDatabaseKey key = getStatusKey( details.getPublicKey(), "My buddy status registration " + payload ); byte[] signature = ecc_handler.sign( data, "Friend online status" ); failed_to_get_key = false; byte[] signed_payload = new byte[ 1 + signature.length + data.length ]; signed_payload[0] = (byte)signature.length; System.arraycopy( signature, 0, signed_payload, 1, signature.length ); System.arraycopy( data, 0, signed_payload, 1 + signature.length, data.length ); DistributedDatabaseValue value = ddb.createValue( signed_payload ); final AESemaphore sem = new AESemaphore( "BuddyPlugin:reg" ); if ( log_this ){ logMessage( "Publishing status starts: " + details.getString()); } last_publish_start = SystemTime.getMonotonousTime(); ddb.write( new DistributedDatabaseListener() { private List write_contacts = new ArrayList(); public void event( DistributedDatabaseEvent event ) { int type = event.getType(); if ( type == DistributedDatabaseEvent.ET_VALUE_WRITTEN ){ write_contacts.add( event.getContact()); }else if ( type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT || type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){ synchronized( publish_write_contacts ){ publish_write_contacts.clear(); publish_write_contacts.addAll( write_contacts ); } sem.release(); } } }, key, value ); sem.reserve(); if ( log_this ){ logMessage( "My status publish complete" ); } }catch( Throwable e ){ logMessage( "Failed to publish online status", e ); if ( failed_to_get_key ){ synchronized( this ){ if ( republish_delay_event != null ){ return; } if ( last_publish_start == 0 || SystemTime.getMonotonousTime() - last_publish_start > STATUS_REPUBLISH_PERIOD ){ log( "Rescheduling publish as failed to get key" ); republish_delay_event = SimpleTimer.addEvent( "BuddyPlugin:republish", SystemTime.getCurrentTime() + 60*1000, new TimerEventPerformer() { public void perform( TimerEvent event) { synchronized( BuddyPlugin.this ){ republish_delay_event = null; } if ( last_publish_start == 0 || SystemTime.getMonotonousTime() - last_publish_start > STATUS_REPUBLISH_PERIOD ){ if ( latest_publish.isEnabled()){ updatePublish( latest_publish ); } } } }); } } } } } } protected int getCurrentStatusSeq() { return( current_publish.getSequence()); } protected void closedown() { logMessage( "Closing down" ); List buddies = getAllBuddies(); synchronized( this ){ connected_at_close = new ArrayList(); for ( BuddyPluginBuddy buddy: buddies ){ if ( buddy.isConnected()){ connected_at_close.add( buddy ); } } } if ( ddb != null ){ boolean restarting = AzureusCoreFactory.isCoreAvailable() ? AzureusCoreFactory.getSingleton().isRestarting() : false; logMessage( " closing buddy connections" ); for (int i=0;i now ){ created_time = now; } String key = new String((byte[])details.get( "pk" )); List recent_ygm = (List)details.get( "ygm" ); String nick = decodeString((byte[])details.get( "n" )); Long l_seq = (Long)details.get( "ls" ); int last_seq = l_seq==null?0:l_seq.intValue(); Long l_lo = (Long)details.get( "lo" ); long last_time_online = l_lo==null?0:l_lo.longValue(); if ( last_time_online > now ){ last_time_online = now; } Long l_subsystem = (Long)details.get( "ss" ); int subsystem = l_subsystem==null?SUBSYSTEM_AZ2:l_subsystem.intValue(); if (subsystem == SUBSYSTEM_AZ3) { continue; } Long l_ver = (Long)details.get("v"); int ver = l_ver==null?VERSION_INITIAL:l_ver.intValue(); String loc_cat = decodeString((byte[])details.get( "lc" )); String rem_cat = decodeString((byte[])details.get( "rc" )); BuddyPluginBuddy buddy = new BuddyPluginBuddy( this, created_time, subsystem, true, key, nick, ver, loc_cat, rem_cat, last_seq, last_time_online, recent_ygm ); byte[] ip_bytes = (byte[])details.get( "ip" ); if ( ip_bytes != null ){ try{ InetAddress ip = InetAddress.getByAddress( ip_bytes ); int tcp_port = ((Long)details.get( "tcp" )).intValue(); int udp_port = ((Long)details.get( "udp" )).intValue(); buddy.setCachedStatus( ip, tcp_port, udp_port ); }catch( Throwable e ){ } } logMessage( "Loaded buddy " + buddy.getString()); buddies.add( buddy ); buddies_map.put( key, buddy ); } } } } int num_buddies = buddies.size(); for ( BuddyPluginBuddy b: buddies ){ b.setInitialStatus( now, num_buddies ); } } } protected String decodeString( byte[] bytes ) { if ( bytes == null ){ return( null ); } try{ return( new String( bytes, "UTF8" )); }catch( Throwable e ){ return( null ); } } protected void saveConfig() { saveConfig( false ); } protected void saveConfig( boolean force ) { synchronized( this ){ if ( config_dirty || force ){ List buddies_config = new ArrayList(); for (int i=0;i 0 ){ map.put( "friends", buddies_config ); writeConfig( map ); }else{ deleteConfig(); } config_dirty = false; } } } public BuddyPluginBuddy addBuddy( String key, int subsystem ) { return( addBuddy( key, subsystem, true )); } protected BuddyPluginBuddy addBuddy( String key, int subsystem, boolean authorised ) { if ( key.length() == 0 || !verifyPublicKey( key )){ return( null ); } BuddyPluginBuddy buddy_to_return = null; // buddy may be already present as unauthorised in which case we pick it up // and authorise it and send the added event (we don't fire added events for // unauthorised buddies) synchronized( this ){ for (int i=0;i period ){ if ( !buddy.statusCheckActive()){ if ( buddy.isAuthorised()){ updateBuddyStatus( buddy ); } } } } // trim any non-authorised buddies that have gone idle synchronized( this ){ for (int i=0;i latest_time ){ byte[] signed_stuff = (byte[])value.getValue( byte[].class ); Map new_status = verifyAndExtract( signed_stuff, public_key ); if ( new_status != null ){ status = new_status; latest_time = time; } } }catch( Throwable e ){ log( "Read failed", e ); } }else if ( type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT || type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){ if ( status == null ){ buddy.statusCheckFailed(); }else{ try{ int tcp_port = ((Long)status.get( "t" )).intValue(); int udp_port = ((Long)status.get( "u" )).intValue(); InetAddress ip = InetAddress.getByAddress((byte[])status.get("i")); String nick = decodeString((byte[])status.get( "n" )); Long l_seq = (Long)status.get( "s" ); int seq = l_seq==null?0:l_seq.intValue(); Long l_os = (Long)status.get( "o" ); int os = l_os==null?BuddyPlugin.STATUS_ONLINE:l_os.intValue(); Long l_ver = (Long)status.get( "v" ); int ver = l_ver==null?VERSION_INITIAL:l_ver.intValue(); buddy.statusCheckComplete( latest_time, ip, tcp_port, udp_port, nick, os, seq, ver ); }catch( Throwable e ){ buddy.statusCheckFailed(); log( "Status decode failed", e ); } } } } }, key, 120*1000 ); }catch( Throwable e ){ buddy.statusCheckFailed(); log( "Friend status update failed: " + buddy.getString(), e ); } } protected Map verifyAndExtract( byte[] signed_stuff, byte[] public_key ) throws BuddyPluginException { int signature_length = ((int)signed_stuff[0])&0xff; byte[] signature = new byte[ signature_length ]; byte[] data = new byte[ signed_stuff.length - 1 - signature_length]; System.arraycopy( signed_stuff, 1, signature, 0, signature_length ); System.arraycopy( signed_stuff, 1 + signature_length, data, 0, data.length ); try{ if ( ecc_handler.verify( public_key, data, signature )){ return( BDecoder.decode( data )); }else{ logMessage( "Signature verification failed" ); return( null ); } }catch( Throwable e ){ rethrow( "Verification failed", e ); return( null ); } } protected byte[] signAndInsert( Map plain_stuff, String reason ) throws BuddyPluginException { try{ byte[] data = BEncoder.encode( plain_stuff ); byte[] signature = ecc_handler.sign( data, reason ); byte[] signed_payload = new byte[ 1 + signature.length + data.length ]; signed_payload[0] = (byte)signature.length; System.arraycopy( signature, 0, signed_payload, 1, signature.length ); System.arraycopy( data, 0, signed_payload, 1 + signature.length, data.length ); return( signed_payload ); }catch( Throwable e ){ rethrow( "Signing failed", e ); return( null ); } } public boolean verify( String pk, byte[] payload, byte[] signature ) throws BuddyPluginException { return( verify( Base32.decode( pk ), payload, signature )); } protected boolean verify( BuddyPluginBuddy buddy, byte[] payload, byte[] signature ) throws BuddyPluginException { return( verify( buddy.getRawPublicKey(), payload, signature )); } protected boolean verify( byte[] pk, byte[] payload, byte[] signature ) throws BuddyPluginException { try{ return( ecc_handler.verify( pk, payload, signature )); }catch( Throwable e ){ rethrow( "Verification failed", e ); return( false ); } } public byte[] sign( byte[] payload ) throws BuddyPluginException { try{ return( ecc_handler.sign( payload, "Friend message signing" )); }catch( Throwable e ){ rethrow( "Signing failed", e ); return( null ); } } protected cryptoResult encrypt( BuddyPluginBuddy buddy, byte[] payload ) throws BuddyPluginException { return encrypt(buddy.getPublicKey(), payload, buddy.getName()); } public cryptoResult encrypt( String pk, byte[] payload, String forWho ) throws BuddyPluginException { try{ byte[] hash = new byte[20]; random.nextBytes( hash ); Map content = new HashMap(); content.put( "h", hash ); content.put( "p", payload ); final byte[] encrypted = ecc_handler.encrypt( Base32.decode(pk), BEncoder.encode( content ), "Encrypting message for " + forWho); final byte[] sha1_hash = new SHA1Simple().calculateHash( hash ); return( new cryptoResult() { public byte[] getChallenge() { return( sha1_hash ); } public byte[] getPayload() { return( encrypted ); } }); }catch( Throwable e ){ rethrow( "Encryption failed", e ); return( null ); } } protected cryptoResult decrypt( BuddyPluginBuddy buddy, byte[] content, String forName) throws BuddyPluginException { try{ final byte[] decrypted = ecc_handler.decrypt( buddy.getRawPublicKey(), content, "Decrypting message for " + buddy.getName()); final Map map = BDecoder.decode( decrypted ); return( new cryptoResult() { public byte[] getChallenge() { return((byte[])map.get("h")); } public byte[] getPayload() { return((byte[])map.get("p")); } }); }catch( Throwable e ){ rethrow( "Decryption failed", e ); return( null ); } } public cryptoResult decrypt( String public_key, byte[] content ) throws BuddyPluginException { try{ final byte[] decrypted = ecc_handler.decrypt( Base32.decode(public_key), content, "Decrypting message for " + public_key); final Map map = BDecoder.decode( decrypted ); return( new cryptoResult() { public byte[] getChallenge() { return((byte[])map.get("h")); } public byte[] getPayload() { return((byte[])map.get("p")); } }); }catch( Throwable e ){ rethrow( "Decryption failed", e ); return( null ); } } protected void setMessagePending( BuddyPluginBuddy buddy, final operationListener listener ) throws BuddyPluginException { try{ checkAvailable(); final String reason = "Friend YGM write for " + buddy.getName(); Map payload = new HashMap(); payload.put( "r", new Long( random.nextLong())); byte[] signed_payload = signAndInsert( payload, reason); Map envelope = new HashMap(); envelope.put( "pk", ecc_handler.getPublicKey( reason )); envelope.put( "ss", signed_payload ); DistributedDatabaseValue value = ddb.createValue( BEncoder.encode( envelope )); logMessage( reason + " starts: " + payload ); DistributedDatabaseKey key = getYGMKey( buddy.getRawPublicKey(), reason ); ddb.write( new DistributedDatabaseListener() { public void event( DistributedDatabaseEvent event ) { int type = event.getType(); if ( type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT || type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){ logMessage( reason + " complete" ); listener.complete(); } } }, key, value ); }catch( Throwable e ){ try{ rethrow( "Failed to publish YGM", e ); }finally{ listener.complete(); } } } public void checkMessagePending( int tick_count ) { log( "Checking YGM" ); if ( tick_count % YGM_BLOOM_LIFE_TICKS == 0 ){ synchronized( this ){ ygm_unauth_bloom = null; } } try{ String reason = "Friend YGM check"; byte[] public_key = ecc_handler.getPublicKey( reason ); DistributedDatabaseKey key = getYGMKey( public_key, reason ); ddb.read( new DistributedDatabaseListener() { private List new_ygm_buddies = new ArrayList(); private boolean unauth_permitted = false;; public void event( DistributedDatabaseEvent event ) { int type = event.getType(); if ( type == DistributedDatabaseEvent.ET_VALUE_READ ){ try{ DistributedDatabaseValue value = event.getValue(); byte[] envelope = (byte[])value.getValue( byte[].class ); Map map = BDecoder.decode( envelope ); byte[] pk = (byte[])map.get( "pk" ); if ( pk == null ){ return; } String pk_str = Base32.encode( pk ); BuddyPluginBuddy buddy = getBuddyFromPublicKey( pk_str ); if ( buddy == null || !buddy.isAuthorised() ){ if ( buddy == null ){ log( "YGM entry from unknown friend '" + pk_str + "' - ignoring" ); }else{ log( "YGM entry from unauthorised friend '" + pk_str + "' - ignoring" ); } byte[] address = event.getContact().getAddress().getAddress().getAddress(); synchronized( BuddyPlugin.this ){ if ( ygm_unauth_bloom == null ){ ygm_unauth_bloom = BloomFilterFactory.createAddOnly(512); } if ( !ygm_unauth_bloom.contains( address )){ ygm_unauth_bloom.add( address ); unauth_permitted = true; } } }else{ byte[] signed_stuff = (byte[])map.get( "ss" ); Map payload = verifyAndExtract( signed_stuff, pk ); if ( payload != null ){ long rand = ((Long)payload.get("r")).longValue(); if ( buddy.addYGMMarker( rand )){ new_ygm_buddies.add( buddy ); } } } }catch( Throwable e ){ log( "Read failed", e ); } }else if ( type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT || type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){ if ( new_ygm_buddies.size() > 0 || unauth_permitted ){ BuddyPluginBuddy[] b = new BuddyPluginBuddy[new_ygm_buddies.size()]; new_ygm_buddies.toArray( b ); fireYGM( b ); } } } }, key, 120*1000, DistributedDatabase.OP_EXHAUSTIVE_READ ); boolean write_bogus_ygm = false; synchronized( this ){ if ( !bogus_ygm_written ){ bogus_ygm_written = write_bogus_ygm = true; } } if ( write_bogus_ygm ){ final String reason2 = "Friend YGM write for myself"; Map envelope = new HashMap(); DistributedDatabaseValue value = ddb.createValue( BEncoder.encode( envelope )); logMessage( reason2 + " starts" ); ddb.write( new DistributedDatabaseListener() { public void event( DistributedDatabaseEvent event ) { int type = event.getType(); if ( type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){ logMessage( reason2 + " complete" ); } } }, key, value ); } }catch( Throwable e ){ logMessage( "YGM check failed", e ); } } public BuddyPluginBuddy getBuddyFromPublicKey( String key ) { synchronized( this ){ return((BuddyPluginBuddy)buddies_map.get( key )); } } public PluginInterface getPluginInterface() { return( plugin_interface ); } protected SESecurityManager getSecurityManager() { return( sec_man ); } protected GenericMessageRegistration getMessageRegistration() { return( msg_registration ); } /** * Returns authorised buddies only */ public List getBuddies() { synchronized( this ){ List result = new ArrayList(); for (int i=0;i getAllBuddies() { synchronized( this ){ return( new ArrayList( buddies )); } } public boolean isAvailable() { try{ checkAvailable(); return( true ); }catch( Throwable e ){ return( false ); } } protected void checkAvailable() throws BuddyPluginException { if ( initialisation_state == INIT_UNKNOWN ){ throw( new BuddyPluginException( "Plugin not yet initialised" )); }else if ( initialisation_state == INIT_BAD ){ throw( new BuddyPluginException( "Plugin unavailable" )); } } protected void fireInitialised( boolean ok ) { if ( ok ){ initialisation_state = INIT_OK; }else{ initialisation_state = INIT_BAD; } persistentDispatchInit(); if ( ok ){ buddy_tracker.initialise(); } List listeners_ref = listeners.getList(); for (int i=0;i msg = new HashMap(); final String if_mod = connection.getRequestProperty( "If-Modified-Since" ); try{ msg.put( "cat", category.getBytes( "UTF-8" )); if ( if_mod != null ){ msg.put( "if_mod", if_mod ); } // String etag = connection.getRequestProperty( "If-None-Match" ); }catch( Throwable e ){ Debug.out( e ); } final Object[] result = { null }; final AESemaphore result_sem = new AESemaphore( "BuddyPlugin:rss" ); final String etag = buddy.getPublicKey() + "-" + category; az2_handler.sendAZ2RSSMessage( buddy, msg, new BuddyPluginAZ2TrackerListener() { public Map messageReceived( BuddyPluginBuddy buddy, Map message ) { try{ byte[] bytes = (byte[])message.get( "rss" ); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); result[0] = bais; connection.setHeaderField( "ETag", etag ); byte[] b_last_mod = (byte[])message.get( "last_mod" ); if ( b_last_mod != null ){ String last_mod = new String( b_last_mod, "UTF-8" ); connection.setHeaderField( "Last-Modified", last_mod ); if ( if_mod != null && if_mod.equals( last_mod ) && bytes.length == 0 ){ connection.setResponse( HttpURLConnection.HTTP_NOT_MODIFIED, "Not Modified" ); } } result_sem.release(); }catch( Throwable e ){ messageFailed( buddy, e ); } return( null ); } public void messageFailed( BuddyPluginBuddy buddy, Throwable cause ) { result[0] = new IPCException( "Read failed", cause ); result_sem.release(); } }); result_sem.reserve( 60*1000 ); if ( result[0] == null ){ throw( new IPCException( "Timeout" )); }else if ( result[0] instanceof InputStream ){ return((InputStream)result[0]); }else{ throw((IPCException)result[0]); } } public InputStream handleUPTorrent( final AZPluginConnection connection, final BuddyPluginBuddy buddy, String category, final byte[] hash ) throws IPCException { final long timeout = 120*1000; final Object[] result = { null }; final AESemaphore result_sem = new AESemaphore( "BuddyPlugin:upt" ); log( "Attempting to download torrent for " + Base32.encode( hash )); // first try and get torrent direct from the buddy if ( buddy.isOnline( true )){ try{ Map msg = new HashMap(); try{ msg.put( "cat", category.getBytes( "UTF-8" )); msg.put( "hash", hash ); }catch( Throwable e ){ Debug.out( e ); } az2_handler.sendAZ2RSSMessage( buddy, msg, new BuddyPluginAZ2TrackerListener() { private boolean result_set; public Map messageReceived( BuddyPluginBuddy buddy, Map message ) { try{ byte[] bytes = (byte[])message.get( "torrent" ); log( " torrent downloaded from buddy" ); setResult( bytes ); }catch( Throwable e ){ messageFailed( buddy, e ); } return( null ); } public void messageFailed( BuddyPluginBuddy buddy, Throwable cause ) { setResult( new IPCException( "Read failed", cause )); } protected void setResult( Object obj ) { synchronized( result ){ if ( result_set ){ return; } result_set = true; if ( !( result[0] instanceof byte[] )){ result[0] = obj; } result_sem.release(); } } }); }catch( Throwable e ){ result[0] = new IPCException( "Buddy torrent get failed", e ); result_sem.release(); } }else{ result[0] = new IPCException( "Buddy is offline" ); result_sem.release(); } // second try and get via magnet final MagnetPlugin magnet_plugin = getMagnetPlugin(); if ( magnet_plugin == null ){ synchronized( result ){ if ( result[0] == null ){ result[0] = new IPCException( "Magnet plugin unavailable" ); } } result_sem.release(); }else{ new AEThread2( "BuddyPlugin:mag", true ) { private boolean result_set; public void run() { try{ if ( buddy.isOnline( true )){ Thread.sleep(10*1000); } synchronized( result ){ if ( result[0] instanceof byte[] ){ setResult( null ); return; } } byte[] torrent_data = magnet_plugin.download( new MagnetPluginProgressListener() { public void reportSize( long size ) { } public void reportActivity( String str ) { log( " MagnetDownload: " + str ); } public void reportCompleteness( int percent ) { } public void reportContributor( InetSocketAddress address ) { } public boolean verbose() { return( false ); } }, hash, "", new InetSocketAddress[0], timeout ); if ( torrent_data == null ){ setResult( new IPCException( "Magnet timeout" )); }else{ log( " torrent downloaded from magnet" ); setResult( torrent_data ); } }catch( Throwable e ){ setResult( new IPCException( "Magnet get failed", e )); } } protected void setResult( Object obj ) { synchronized( result ){ if ( result_set ){ return; } result_set = true; if ( obj != null ){ if ( result[0] == null || ( obj instanceof byte[] && !( result[0] instanceof byte[] ))){ result[0] = obj; } } result_sem.release(); } } }.start(); } long start = SystemTime.getMonotonousTime(); if ( result_sem.reserve(timeout )){ if ( !( result[0] instanceof byte[] )){ long rem = timeout - ( SystemTime.getMonotonousTime() - start ); if ( rem > 0 ){ result_sem.reserve(rem ); } } } if ( result[0] == null ){ log( " torrent download timeout" ); throw( new IPCException( "Timeout" )); }else if ( result[0] instanceof byte[] ){ return( new ByteArrayInputStream((byte[])result[0])); }else{ IPCException error = (IPCException)result[0]; log( " torrent downloaded failed: " + Debug.getNestedExceptionMessage( error )); throw( error ); } } protected MagnetPlugin getMagnetPlugin() { PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass( MagnetPlugin.class ); if ( pi == null ){ return( null ); } return((MagnetPlugin)pi.getPlugin()); } public feedDetails getRSS( BuddyPluginBuddy buddy, String category, String if_mod ) throws BuddyPluginException { if ( !buddy.isLocalRSSCategoryAuthorised( category )){ throw( new BuddyPluginException( "Unauthorised category '" + category + "'" )); } buddy.localRSSCategoryRead( category ); Download[] downloads = plugin_interface.getDownloadManager().getDownloads(); List selected_dls = new ArrayList(); long fingerprint = 0; for (int i=0;i 0 ){ if ( now < feed_date || now - feed_date > FEED_UPDATE_MIN_MILLIS ){ feed_date = now; pc.setPluginParameter( feed_date_key, feed_date ); } } }else{ pc.setPluginParameter( feed_finger_key, fingerprint ); // ensure feed date goes up if ( now <= feed_date ){ feed_date++; }else{ feed_date = now; } pc.setPluginParameter( feed_date_key, feed_date ); } String last_modified = TimeFormatter.getHTTPDate( feed_date ); if ( if_mod != null && if_mod.equals( last_modified )){ return( new feedDetails( new byte[0], last_modified )); } ByteArrayOutputStream os = new ByteArrayOutputStream(); AZ3Functions.provider az3 = AZ3Functions.getProvider(); try{ PrintWriter pw = new PrintWriter(new OutputStreamWriter( os, "UTF-8" )); pw.println( "" ); pw.println( "" ); pw.println( "" ); pw.println( "" + escape( category ) + "" ); Collections.sort( selected_dls, new Comparator() { public int compare( Download d1, Download d2) { long added1 = getAddedTime( d1 )/1000; long added2 = getAddedTime( d2 )/1000; return((int)(added2 - added1 )); } }); pw.println( "" + last_modified + "" ); for (int i=0;i" ); pw.println( "" + escape( download.getName()) + "" ); pw.println( "" + hash_str + "" ); if ( az3 != null ){ String cdp = az3.getCDPURL( core_download ); if ( cdp != null ){ pw.println( "" + escape(cdp) + "" ); } } long added = core_download.getDownloadState().getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME); pw.println( "" + TimeFormatter.getHTTPDate( added ) + "" ); pw.println( "" + torrent.getSize()+ "" ); pw.println( "" + hash_str + "" ); String url = "azplug:?id=azbuddy&name=Friends&arg="; String arg = "pk=" + getPublicKey() + "&cat=" + category + "&hash=" + Base32.encode(torrent.getHash()); url += URLEncoder.encode( arg, "UTF-8" ); pw.println( "" + escape( url ) + "" ); DownloadScrapeResult scrape = download.getLastScrapeResult(); if ( scrape != null && scrape.getResponseType() == DownloadScrapeResult.RT_SUCCESS ){ pw.println( "" + scrape.getSeedCount() + "" ); pw.println( "" + scrape.getNonSeedCount() + "" ); } pw.println( "" ); } pw.println( "" ); pw.println( "" ); pw.flush(); return( new feedDetails( os.toByteArray(), last_modified )); }catch( IOException e ){ throw( new BuddyPluginException( "", e )); } } public byte[] getRSSTorrent( BuddyPluginBuddy buddy, String category, byte[] hash ) throws BuddyPluginException { if ( !buddy.isLocalRSSCategoryAuthorised( category )){ throw( new BuddyPluginException( "Unauthorised category '" + category + "'" )); } try{ Download download = plugin_interface.getDownloadManager().getDownload( hash ); if ( download != null ){ Torrent torrent = download.getTorrent(); if ( torrent != null ){ String dl_cat = download.getAttribute( ta_category ); if ( category.equalsIgnoreCase( "all" ) || ( dl_cat != null && dl_cat.equals( category ))){ if ( !TorrentUtils.isReallyPrivate( PluginCoreUtils.unwrap( torrent ))){ torrent = torrent.removeAdditionalProperties(); return( torrent.writeToBEncodedData()); } } } } }catch( Throwable e ){ throw( new BuddyPluginException( "getTorrent failed", e )); } throw( new BuddyPluginException( "Not found" )); } protected long getAddedTime( Download download ) { DownloadManager core_download = PluginCoreUtils.unwrap( download ); return( core_download.getDownloadState().getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME)); } protected String escape( String str ) { return( XUXmlWriter.escapeXML(str)); } public void addRequestListener( BuddyPluginBuddyRequestListener listener ) { request_listeners.add( listener ); } public void removeRequestListener( BuddyPluginBuddyRequestListener listener ) { request_listeners.remove( listener ); } public void logMessage( String str, Throwable e ) { logMessage( str + ": " + Debug.getNestedExceptionMessage(e), true ); } public void logMessage( String str ) { logMessage( str, false ); } public void logMessage( String str, boolean is_error ) { log( str ); Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((BuddyPluginListener)it.next()).messageLogged( str, is_error ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } public void log( String str ) { logger.log( str ); } public void log( String str, Throwable e ) { logger.log( str + ": " + Debug.getNestedExceptionMessageAndStack( e )); } private class publishDetails implements Cloneable { private byte[] public_key; private InetAddress ip; private int tcp_port; private int udp_port; private String nick_name; private int online_status = STATUS_ONLINE; private boolean enabled; private boolean published; private int sequence; protected publishDetails getCopy() { try{ publishDetails copy = (publishDetails)clone(); copy.published = false; return( copy ); }catch( Throwable e ){ return( null); } } protected boolean isPublished() { return( published ); } protected void setPublished( boolean b ) { published = b; } protected boolean isEnabled() { return( enabled ); } protected void setEnabled( boolean _enabled ) { enabled = _enabled; } protected void setSequence( int seq ) { sequence = seq; } protected int getSequence() { return( sequence ); } protected byte[] getPublicKey() { return( public_key ); } protected void setPublicKey( byte[] k ) { public_key = k; } protected InetAddress getIP() { return( ip ); } protected void setIP( InetAddress _ip ) { ip = _ip; } protected int getTCPPort() { return( tcp_port ); } protected void setTCPPort( int _port ) { tcp_port = _port; } protected int getUDPPort() { return( udp_port ); } protected void setUDPPort( int _port ) { udp_port = _port; } protected String getNickName() { return( nick_name ); } protected void setNickName( String n ) { nick_name = n; } protected int getOnlineStatus() { return( online_status ); } protected void setOnlineStatus( int _status ) { online_status = _status; } protected String getString() { return( "enabled=" + enabled + ",ip=" + ip + ",tcp=" + tcp_port + ",udp=" + udp_port + ",stat=" + online_status + ",key=" + (public_key==null?"":Base32.encode( public_key ))); } } protected interface operationListener { public void complete(); } public interface cryptoResult { public byte[] getChallenge(); public byte[] getPayload(); } protected class feedDetails { private byte[] contents; private String last_modified; protected feedDetails( byte[] _contents, String _last_modified ) { contents = _contents; last_modified = _last_modified; } protected byte[] getContent() { return( contents ); } protected String getLastModified() { return( last_modified ); } } } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddy.java0000644000175000017500000017436011251553772026226 0ustar adrianadrian/* * Created on Apr 1, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy; import java.io.File; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URL; import java.net.URLEncoder; import java.util.*; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.AddressUtils; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.BEncoder; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DelayedEvent; import org.gudy.azureus2.core3.util.LightHashMap; import org.gudy.azureus2.core3.util.RandomUtils; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.messaging.MessageException; import org.gudy.azureus2.plugins.messaging.generic.GenericMessageConnection; import org.gudy.azureus2.plugins.messaging.generic.GenericMessageConnectionListener; import org.gudy.azureus2.plugins.messaging.generic.GenericMessageEndpoint; import org.gudy.azureus2.plugins.messaging.generic.GenericMessageRegistration; import org.gudy.azureus2.plugins.utils.PooledByteBuffer; import org.gudy.azureus2.plugins.utils.security.SEPublicKey; import org.gudy.azureus2.plugins.utils.security.SEPublicKeyLocator; import org.gudy.azureus2.plugins.utils.security.SESecurityManager; import com.aelitis.azureus.core.util.AZ3Functions; public class BuddyPluginBuddy { private static final boolean TRACE = BuddyPlugin.TRACE; private static final int CONNECTION_IDLE_TIMEOUT = 5*60*1000; private static final int CONNECTION_KEEP_ALIVE = 1*60*1000; private static final int MAX_ACTIVE_CONNECTIONS = 5; private static final int MAX_QUEUED_MESSAGES = 256; private static final int RT_REQUEST_DATA = 1; private static final int RT_REPLY_DATA = 2; private static final int RT_REPLY_ERROR = 99; private BuddyPlugin plugin; private long created_time; private int subsystem; private boolean authorised; private String public_key; private String nick_name; private List recent_ygm; private int last_status_seq; private long post_time; private InetAddress ip; private int tcp_port; private int udp_port; private int online_status = BuddyPlugin.STATUS_ONLINE; // default private int version = BuddyPlugin.VERSION_CHAT; // assume everyone now supports chat private boolean online; private long last_time_online; private long status_check_count; private long last_status_check_time; private boolean check_active; private List connections = new ArrayList(); private List messages = new ArrayList(); private buddyMessage current_message; private int next_connection_id; private int next_message_id; private boolean ygm_active; private boolean ygm_pending; private long latest_ygm_time; private String last_message_received; private Set offline_seq_set; private int message_out_count; private int message_in_count; private int message_out_bytes; private int message_in_bytes; private String received_frag_details = ""; private BuddyPluginBuddyMessageHandler persistent_msg_handler; private Map user_data = new LightHashMap(); private boolean keep_alive_outstanding; private volatile long last_connect_attempt = SystemTime.getCurrentTime(); private volatile int consec_connect_fails; private long last_auto_reconnect = -1; private Object rss_lock = new Object(); private Set rss_local_cats; private Set rss_remote_cats; private Set rss_cats_read; private AESemaphore outgoing_connect_sem = new AESemaphore( "BPB:outcon", 1 ); private volatile boolean closing; private volatile boolean destroyed; protected BuddyPluginBuddy( BuddyPlugin _plugin, long _created_time, int _subsystem, boolean _authorised, String _pk, String _nick_name, int _version, String _rss_local_cats, String _rss_remote_cats, int _last_status_seq, long _last_time_online, List _recent_ygm ) { plugin = _plugin; created_time = _created_time; subsystem = _subsystem; authorised = _authorised; public_key = _pk; nick_name = _nick_name; version = Math.max( version, _version ); rss_local_cats = stringToCats( _rss_local_cats ); rss_remote_cats = stringToCats( _rss_remote_cats ); last_status_seq = _last_status_seq; last_time_online = _last_time_online; recent_ygm = _recent_ygm; persistent_msg_handler = new BuddyPluginBuddyMessageHandler( this, new File(plugin.getBuddyConfigDir(), public_key )); } protected void setInitialStatus( long now, int num_buddies ) { // for inactive buddies we schedule their status checks so that on average we don't // do more than one check every 5 minutes if ( last_time_online == 0 && now - created_time > 7*24*60*60*1000L ){ last_status_check_time = now + RandomUtils.nextInt( 5*60*1000 * num_buddies ); } } protected BuddyPlugin getPlugin() { return( plugin ); } public BuddyPluginBuddyMessageHandler getMessageHandler() { return( persistent_msg_handler ); } protected void persistentDispatchPending() { plugin.persistentDispatchPending( this ); } protected void checkPersistentDispatch() { persistent_msg_handler.checkPersistentDispatch(); } protected void persistentDispatch() { persistent_msg_handler.persistentDispatch(); } public Map readConfigFile( File name ) { return( plugin.readConfigFile( name )); } public boolean writeConfigFile( File name, Map data ) { return( plugin.writeConfigFile( name, data )); } protected long getCreatedTime() { return( created_time ); } public int getSubsystem() { return( subsystem ); } protected void setSubsystem( int _s ) { subsystem = _s; } public boolean isAuthorised() { return( authorised ); } protected void setAuthorised( boolean _a ) { authorised = _a; } public String getPublicKey() { return( public_key ); } protected byte[] getRawPublicKey() { return( Base32.decode( public_key )); } protected String getShortString() { return( public_key.substring( 0, 16 ) + "..." ); } public String getNickName() { return( nick_name ); } public int getVersion() { return( version ); } protected void setVersion( int v ) { if ( version < v ){ version = v; plugin.fireDetailsChanged( this ); } } public String getLocalAuthorisedRSSCategoriesAsString() { synchronized( rss_lock ){ return( catsToString( rss_local_cats )); } } public Set getLocalAuthorisedRSSCategories() { synchronized( rss_lock ){ return( rss_local_cats ); } } public void addLocalAuthorisedRSSCategory( String category ) { category = plugin.normaliseCat( category ); boolean dirty; synchronized( rss_lock ){ if ( rss_local_cats == null ){ rss_local_cats = new HashSet(); } if ( dirty = !rss_local_cats.contains( category )){ rss_local_cats.add( category ); } } if ( dirty ){ plugin.setConfigDirty(); plugin.fireDetailsChanged( this ); // tell buddy of change if ( isConnected()){ sendKeepAlive(); } } } public void removeLocalAuthorisedRSSCategory( String category ) { category = plugin.normaliseCat( category ); boolean dirty; synchronized( rss_lock ){ if ( rss_local_cats == null ){ return; }else{ dirty = rss_local_cats.remove( category ); } } if ( dirty ){ plugin.setConfigDirty(); plugin.fireDetailsChanged( this ); // tell buddy of change if ( isConnected()){ sendKeepAlive(); } } } public void setLocalAuthorisedRSSCategories( String new_cats ) { setLocalAuthorisedRSSCategories( stringToCats( new_cats )); } public void setLocalAuthorisedRSSCategories( Set new_cats ) { plugin.normaliseCats( new_cats ); boolean dirty; synchronized( rss_lock ){ if ( dirty = !catsIdentical( new_cats, rss_local_cats) ){ rss_local_cats = new_cats; } } if ( dirty ){ plugin.setConfigDirty(); plugin.fireDetailsChanged( this ); // tell buddy of change if ( isConnected()){ sendKeepAlive(); } } } public Set getRemoteAuthorisedRSSCategories() { return( rss_remote_cats ); } public String getRemoteAuthorisedRSSCategoriesAsString() { return( catsToString( rss_remote_cats )); } protected void setRemoteAuthorisedRSSCategories( Set new_cats ) { plugin.normaliseCats( new_cats ); boolean dirty; synchronized( rss_lock ){ if ( dirty = !catsIdentical( new_cats, rss_remote_cats) ){ rss_remote_cats = new_cats; } } if ( dirty ){ plugin.setConfigDirty(); plugin.fireDetailsChanged( this ); } } public boolean isLocalRSSCategoryAuthorised( String category ) { category = plugin.normaliseCat( category ); synchronized( rss_lock ){ if ( rss_local_cats != null ){ return( rss_local_cats.contains( category )); } return( false ); } } public boolean isRemoteRSSCategoryAuthorised( String category ) { category = plugin.normaliseCat( category ); synchronized( rss_lock ){ if ( rss_remote_cats != null ){ return( rss_remote_cats.contains( category )); } return( false ); } } protected void localRSSCategoryRead( String str ) { boolean dirty; synchronized( rss_lock ){ if ( rss_cats_read == null ){ rss_cats_read = new HashSet(); } dirty = rss_cats_read.add( str ); } if ( dirty ){ // not persisted currently - plugin.setConfigDirty(); plugin.fireDetailsChanged( this ); } } public String getLocalReadCategoriesAsString() { synchronized( rss_lock ){ return( catsToString( rss_cats_read )); } } public URL getSubscriptionURL( String cat ) { String url = "azplug:?id=azbuddy&name=Friends&arg="; String arg = "pk=" + getPublicKey() + "&cat=" + cat; try{ url += URLEncoder.encode( arg, "UTF-8" ); return( new URL( url )); }catch( Throwable e ){ Debug.out( e ); return( null ); } } public void subscribeToCategory( String cat ) throws BuddyPluginException { AZ3Functions.provider az3 = AZ3Functions.getProvider(); if ( az3 == null ){ throw( new BuddyPluginException( "AZ3 subsystem not available" )); } try{ az3.subscribeToRSS( getName() + ": " + cat, getSubscriptionURL(cat), 15, false, getPublicKey() + ":" + cat ); }catch( Throwable e ){ throw( new BuddyPluginException( "Failed to add subscription", e )); } } public boolean isSubscribedToCategory( String cat, String creator_ref ) { if ( creator_ref == null ){ return( false ); } return( creator_ref.equals( getPublicKey() + ":" + cat )); } protected String catsToString( Set cats ) { if ( cats == null || cats.size() == 0 ){ return( null ); } String str = ""; for (String s:cats ){ str += (str.length()==0?"":",") + s; } return( str ); } protected boolean catsIdentical( Set c1, Set c2 ) { if ( c1 == null && c2 == null ){ return( true ); }else if ( c1 == null || c2 == null ){ return( false ); }else{ return( c1.equals( c2 )); } } protected Set stringToCats( String str ) { if ( str == null ){ return( null ); } String[] bits = str.split( "," ); Set res = new HashSet( bits.length ); for ( String b: bits ){ b = b.trim(); if ( b.length() > 0 ){ res.add( b ); } } if ( res.size() == 0 ){ return( null ); } return( res ); } public int getOnlineStatus() { return( online_status ); } protected void setOnlineStatus( int s ) { if ( online_status != s ){ online_status = s; plugin.fireDetailsChanged( this ); } } public String getName() { if ( nick_name != null ){ return( nick_name ); } return( getShortString()); } public void remove() { persistent_msg_handler.destroy(); plugin.removeBuddy( this ); } public InetAddress getIP() { return( ip ); } public InetAddress getAdjustedIP() { if ( ip == null ){ return( null ); } InetSocketAddress address = new InetSocketAddress( ip, tcp_port ); InetSocketAddress adjusted_address = AddressUtils.adjustTCPAddress( address, true ); if ( adjusted_address != address ){ return( adjusted_address.getAddress()); } address = new InetSocketAddress( ip, udp_port ); adjusted_address = AddressUtils.adjustUDPAddress( address, true ); if ( adjusted_address != address ){ return( adjusted_address.getAddress()); } return( ip ); } public List getAdjustedIPs() { List result = new ArrayList(); if ( ip == null ){ return( result ); } InetAddress adjusted = getAdjustedIP(); if ( adjusted == ip ){ result.add( ip ); }else{ List l = AddressUtils.getLANAddresses( adjusted.getHostAddress()); for (int i=0;i retrieveMessages( int type ) { return( persistent_msg_handler.retrieveExplicitMessages( type )); } public void setMessagePending() throws BuddyPluginException { synchronized( this ){ if ( ygm_active ){ ygm_pending = true; return; } ygm_active = true; } plugin.setMessagePending( this, new BuddyPlugin.operationListener() { public void complete() { boolean retry; synchronized( BuddyPluginBuddy.this ){ ygm_active = false; retry = ygm_pending; ygm_pending = false; } if ( retry ){ try{ setMessagePending(); }catch( BuddyPluginException e ){ log( "Failed to send YGM", e ); } } } }); } public long getLastMessagePending() { return( latest_ygm_time ); } protected boolean addYGMMarker( long marker ) { Long l = new Long( marker ); synchronized( this ){ if ( recent_ygm == null ){ recent_ygm = new ArrayList(); } if ( recent_ygm.contains( l )){ return( false ); } recent_ygm.add( l ); if ( recent_ygm.size() > 16 ){ recent_ygm.remove(0); } latest_ygm_time = SystemTime.getCurrentTime(); } plugin.setConfigDirty(); plugin.fireDetailsChanged( this ); return( true ); } protected void setLastMessageReceived( String str ) { last_message_received = str; plugin.fireDetailsChanged( this ); } public String getLastMessageReceived() { return( last_message_received==null?"":last_message_received ); } protected List getYGMMarkers() { return( recent_ygm ); } protected int getLastStatusSeq() { return( last_status_seq ); } protected void buddyConnectionEstablished( boolean outgoing ) { buddyActive(); } protected void buddyMessageSent( int size, boolean record_active ) { message_out_count++; message_out_bytes += size; if ( record_active ){ buddyActive(); } } protected void buddyMessageReceived( int size ) { message_in_count++; message_in_bytes += size; received_frag_details = ""; buddyActive(); } protected void buddyMessageFragmentReceived( int num_received, int total ) { received_frag_details = num_received + "/" + total; plugin.fireDetailsChanged( this ); } public String getMessageInFragmentDetails() { return( received_frag_details ); } public int getMessageInCount() { return( message_in_count ); } public int getMessageOutCount() { return( message_out_count ); } public int getBytesInCount() { return( message_in_bytes ); } public int getBytesOutCount() { return( message_out_bytes ); } public boolean isConnected() { boolean connected = false; synchronized( this ){ for (int i=0;i closing = new ArrayList(); synchronized( this ){ closing.addAll( connections ); } for (int i=0;i(); } offline_seq_set.add( new Long( last_status_seq )); offline_seq_set.add((Long)request.get( "os" )); if ( online ){ online = false; consec_connect_fails = 0; details_change = true; } } if ( details_change ){ plugin.fireDetailsChanged( this ); } } }catch( Throwable e ){ Debug.out( "Failed to decode close request", e ); } } public void sendMessage( final int subsystem, final Map content, final int timeout_millis, final BuddyPluginBuddyReplyListener listener ) throws BuddyPluginException { plugin.checkAvailable(); boolean wait = false; if ( ip == null ){ if ( check_active ){ wait = true; }else if ( SystemTime.getCurrentTime() - last_status_check_time > 30*1000 ){ plugin.updateBuddyStatus( this ); wait = true; } } if ( wait ){ new AEThread2( "BuddyPluginBuddy:sendWait", true ) { public void run() { try{ long start = SystemTime.getCurrentTime(); for (int i=0;i<20;i++){ if ( ip != null ){ break; } Thread.sleep( 1000 ); } long elapsed = SystemTime.getCurrentTime() - start; int new_tm = timeout_millis; if ( elapsed > 0 && timeout_millis > 0 ){ new_tm -= elapsed; if ( new_tm <= 0 ){ listener.sendFailed( BuddyPluginBuddy.this, new BuddyPluginException( "Timeout" )); return; } } sendMessageSupport( content, subsystem, new_tm, listener ); }catch( Throwable e ){ if ( e instanceof BuddyPluginException ){ listener.sendFailed( BuddyPluginBuddy.this, (BuddyPluginException)e); }else{ listener.sendFailed( BuddyPluginBuddy.this, new BuddyPluginException( "Send failed", e )); } } } }.start(); }else{ sendMessageSupport( content, subsystem, timeout_millis, listener ); } } protected void sendMessageSupport( final Map content, final int subsystem, final int timeout_millis, final BuddyPluginBuddyReplyListener original_listener ) throws BuddyPluginException { boolean too_many_messages = false; synchronized( this ){ too_many_messages = messages.size() >= MAX_QUEUED_MESSAGES; } if ( too_many_messages ){ throw( new BuddyPluginException( "Too many messages queued" )); } final buddyMessage message = new buddyMessage( subsystem, content, timeout_millis ); BuddyPluginBuddyReplyListener listener_delegate = new BuddyPluginBuddyReplyListener() { public void replyReceived( BuddyPluginBuddy from_buddy, Map reply ) { // logMessage( "Msg " + message.getString() + " ok" ); try{ synchronized( BuddyPluginBuddy.this ){ if ( current_message != message ){ Debug.out( "Inconsistent: reply received not for current message" ); } current_message = null; } original_listener.replyReceived( from_buddy, reply ); }finally{ dispatchMessage(); } } public void sendFailed( BuddyPluginBuddy to_buddy, BuddyPluginException cause ) { logMessage( "Msg " + message.getString() + " failed: " + Debug.getNestedExceptionMessage( cause )); try{ // only try and reconcile this failure with the current message if // the message has actually been sent boolean was_active; if ( cause instanceof BuddyPluginTimeoutException ){ was_active = ((BuddyPluginTimeoutException)cause).wasActive(); }else{ was_active = true; } if ( was_active ){ synchronized( BuddyPluginBuddy.this ){ if ( current_message != message ){ Debug.out( "Inconsistent: error received not for current message" ); } current_message = null; } } long now = SystemTime.getCurrentTime(); int retry_count = message.getRetryCount(); if ( retry_count < 1 && !message.timedOut( now )){ message.setRetry(); // logMessage( "Msg " + message.getString() + " retrying" ); synchronized( BuddyPluginBuddy.this ){ messages.add( 0, message ); } }else{ original_listener.sendFailed( to_buddy, cause ); } }finally{ dispatchMessage(); } } }; message.setListener( listener_delegate ); int size; synchronized( this ){ messages.add( message ); size = messages.size(); } // logMessage( "Msg " + message.getString() + " added: num=" + size ); dispatchMessage(); } protected void dispatchMessage() { buddyConnection bc = null; buddyMessage allocated_message = null; Throwable failed_msg_error = null; boolean inform_dirty = false; synchronized( this ){ if ( current_message != null || messages.size() == 0 || closing ){ return; } allocated_message = current_message = (buddyMessage)messages.remove( 0 ); for (int i=0;i= MAX_ACTIVE_CONNECTIONS ){ failed_msg_error = new BuddyPluginException( "Too many active connections" ); } } } if ( failed_msg_error != null ){ allocated_message.reportFailed( failed_msg_error ); return; } if ( bc == null ){ // single-thread outgoing connect attempts try{ outgoing_connect_sem.reserve(); synchronized( this ){ if ( current_message != allocated_message ){ failed_msg_error = new BuddyPluginException( "current message no longer active" ); }else if ( closing ){ return; } if ( failed_msg_error == null ){ for (int i=0;i= MAX_ACTIVE_CONNECTIONS ){ failed_msg_error = new BuddyPluginException( "Too many active connections" ); } } } } if ( bc == null && failed_msg_error == null ){ try{ // can't perform connect op while synchronized as may deadlock on password // aquisition GenericMessageConnection generic_connection = outgoingConnection(); synchronized( this ){ if ( current_message != allocated_message ){ failed_msg_error = new BuddyPluginException( "current message no longer active" ); generic_connection.close(); }else{ bc = new buddyConnection( generic_connection, true ); inform_dirty = connections.size() == 0; connections.add( bc ); // logMessage( "Con " + bc.getString() + " added: num=" + connections.size() ); } } }catch( Throwable e ){ failed_msg_error = e; } } }finally{ outgoing_connect_sem.release(); } } if ( failed_msg_error != null ){ allocated_message.reportFailed( failed_msg_error ); return; } try{ // logMessage( "Allocating msg " + allocated_message.getString() + " to con " + bc.getString()); bc.sendMessage( allocated_message ); }catch( BuddyPluginException e ){ allocated_message.reportFailed( e ); } if ( inform_dirty ){ plugin.setConfigDirty(); } } protected void removeConnection( buddyConnection bc ) { int size; synchronized( this ){ connections.remove( bc ); size = connections.size(); } if ( size == 0 ){ plugin.setConfigDirty(); } if ( size == 0 && bc.isConnected() && !bc.isClosing() && !bc.isRemoteClosing()){ // dropped connection, kick in a keep alive if ( consec_connect_fails < 3 ){ if ( consec_connect_fails == 0 ){ long now = SystemTime.getMonotonousTime(); boolean do_it = false; synchronized( this ){ if ( last_auto_reconnect == -1 || now - last_auto_reconnect > 30*1000 ){ last_auto_reconnect = now; do_it = true; } } if ( do_it ){ // delay a bit new DelayedEvent( "BuddyPluginBuddy:recon", new Random().nextInt( 3000 ), new AERunnable() { public void runSupport() { int size; synchronized( BuddyPluginBuddy.this ){ size = connections.size(); } if ( consec_connect_fails == 0 && size == 0 ){ log( "Attempting reconnect after dropped connection" ); sendKeepAlive(); } } }); } }else{ long delay = 60*1000; delay <<= Math.min( 3, consec_connect_fails ); if ( SystemTime.getCurrentTime() - last_connect_attempt >= delay ){ sendKeepAlive(); } } } } // logMessage( "Con " + bc.getString() + " removed: num=" + size ); // connection failed, see if we need to attempt to re-establish plugin.fireDetailsChanged( this ); dispatchMessage(); } protected long getLastStatusCheckTime() { return( last_status_check_time ); } protected boolean statusCheckActive() { synchronized( this ){ return( check_active ); } } protected boolean statusCheckStarts() { synchronized( this ){ if ( check_active ){ return( false ); } last_status_check_time = SystemTime.getCurrentTime(); check_active = true; } return( true ); } protected void statusCheckFailed() { boolean details_change = false; synchronized( this ){ try{ if ( online ){ online = false; consec_connect_fails = 0; details_change = true; } }finally{ status_check_count++; check_active = false; } } if ( details_change ){ plugin.fireDetailsChanged( this ); } } protected void setCachedStatus( InetAddress _ip, int _tcp_port, int _udp_port ) { synchronized( this ){ if ( ip == null ){ ip = _ip; tcp_port = _tcp_port; udp_port = _udp_port; } } } protected void statusCheckComplete( long _post_time, InetAddress _ip, int _tcp_port, int _udp_port, String _nick_name, int _online_status, int _status_seq, int _version ) { boolean details_change = false; boolean config_dirty = false; long now = SystemTime.getCurrentTime(); if ( now < last_time_online ){ last_time_online = now; } boolean is_connected = isConnected(); synchronized( this ){ try{ // do we explicitly know that this sequence number denotes an offline buddy if ( offline_seq_set != null ){ if ( offline_seq_set.contains(new Long( _status_seq ))){ return; }else{ offline_seq_set = null; } } boolean seq_change = _status_seq != last_status_seq; boolean timed_out; // change in sequence means we're online if ( seq_change ){ last_status_seq = _status_seq; last_time_online = now; timed_out = false; details_change = true; }else{ timed_out = now - last_time_online >= BuddyPlugin.STATUS_REPUBLISH_PERIOD * 3 ; } if ( online ){ if ( timed_out ){ online = false; consec_connect_fails = 0; details_change = true; } }else{ if ( seq_change || !timed_out ){ online = true; details_change = true; } } post_time = _post_time; if ( !addressesEqual( ip, _ip ) || tcp_port != _tcp_port || udp_port != _udp_port || version < _version ){ ip = _ip; tcp_port = _tcp_port; udp_port = _udp_port; if ( version < _version ){ version = _version; } details_change = true; } // if we are connected then we use the status sent over the connection // as it is more up to date if ( !is_connected && online_status != _online_status ){ online_status = _online_status; details_change = true; } if ( !plugin.stringsEqual( nick_name, _nick_name )){ nick_name = _nick_name; config_dirty = true; details_change = true; } }finally{ status_check_count++; check_active = false; } } if ( config_dirty ){ plugin.setConfigDirty(); } if ( details_change ){ if ( online ){ persistentDispatchPending(); } plugin.fireDetailsChanged( this ); } plugin.logMessage( getString()); } protected boolean addressesEqual( InetAddress ip1, InetAddress ip2 ) { if ( ip1 == null && ip2 == null ){ return( true ); }else if ( ip1 == null || ip2 == null ){ return( false ); }else{ return( ip1.equals( ip2 )); } } protected void checkTimeouts() { long now = SystemTime.getCurrentTime(); List failed = null; List connections_to_check = null; boolean messages_queued; synchronized( this ){ messages_queued = messages.size() > 0; if ( messages_queued ){ Iterator it = messages.iterator(); while( it.hasNext()){ buddyMessage message = (buddyMessage)it.next(); if ( message.timedOut( now )){ it.remove(); if ( failed == null ){ failed = new ArrayList(); } failed.add( message ); } } } if ( connections.size() > 0 ){ connections_to_check = new ArrayList( connections ); } } boolean send_keep_alive = false; if ( connections_to_check == null ){ // no active connections if ( online && ip != null && !messages_queued ){ // see if we should attempt a pre-emptive connect if ( consec_connect_fails < 3 ){ long delay = 60*1000; delay <<= Math.min( 3, consec_connect_fails ); send_keep_alive = now - last_connect_attempt >= delay; } } }else{ for (int i=0;i CONNECTION_KEEP_ALIVE ){ send_keep_alive = true; } } } } if ( send_keep_alive ){ sendKeepAlive(); } if ( failed != null ){ for (int i=0;i to_close = new ArrayList(); synchronized( this ){ destroyed = true; to_close.addAll( connections ); } for (int i=0;i 0 ){ tcp_target = new InetSocketAddress( ip, tcp_port ); } int udp_port = getUDPPort(); if ( udp_port > 0 ){ udp_target = new InetSocketAddress( ip, udp_port ); } InetSocketAddress notional_target = tcp_target; if ( notional_target == null ){ notional_target = udp_target; } if ( notional_target == null ){ throw( new BuddyPluginException( "Friend offline (no usable protocols)" )); } GenericMessageEndpoint endpoint = msg_registration.createEndpoint( notional_target ); if ( tcp_target != null ){ endpoint.addTCP( tcp_target ); } if ( udp_target != null ){ endpoint.addUDP( udp_target ); } GenericMessageConnection con = null; try{ last_connect_attempt = SystemTime.getCurrentTime(); con = msg_registration.createConnection( endpoint ); plugin.addRateLimiters( con ); String reason = "Friend: Outgoing connection establishment"; SESecurityManager sec_man = plugin.getSecurityManager(); con = sec_man.getSTSConnection( con, sec_man.getPublicKey( SEPublicKey.KEY_TYPE_ECC_192, reason ), new SEPublicKeyLocator() { public boolean accept( Object context, SEPublicKey other_key ) { String other_key_str = Base32.encode( other_key.encodeRawPublicKey()); if ( other_key_str.equals( public_key )){ consec_connect_fails = 0; return( true ); }else{ log( getString() + ": connection failed due to pk mismatch" ); return( false ); } } }, reason, BuddyPlugin.BLOCK_CRYPTO ); con.connect(); return( con ); }catch( Throwable e ){ if ( con != null ){ consec_connect_fails++; try{ con.close(); }catch( Throwable f ){ log( "Failed to close connection", f ); } } throw( new BuddyPluginException( "Failed to send message", e )); } } protected void incomingConnection( GenericMessageConnection _connection ) throws BuddyPluginException { addConnection( _connection ); } protected void addConnection( GenericMessageConnection _connection ) throws BuddyPluginException { //int size; buddyConnection bc = new buddyConnection( _connection, false ); boolean inform_dirty = false; synchronized( this ){ if ( destroyed ){ throw( new BuddyPluginException( "Friend has been destroyed" )); } inform_dirty = connections.size() == 0; connections.add( bc ); //size = connections.size(); } // logMessage( "Con " + bc.getString() + " added: num=" + size ); if ( inform_dirty ){ plugin.setConfigDirty(); } } public void setUserData( Object key, Object value ) { synchronized( user_data ){ user_data.put(key, value); } } public Object getUserData( Object key ) { synchronized( user_data ){ return( user_data.get( key )); } } protected void log( String str ) { plugin.log( str ); } protected void log( String str, Throwable e ) { plugin.log( str, e ); } public String getString() { return( "pk=" + getShortString() + (nick_name==null?"":(",nick=" + nick_name)) + ",ip=" + ip + ",tcp=" + tcp_port + ",udp=" + udp_port + ",online=" + online + ",age=" + (SystemTime.getCurrentTime() - post_time )); } protected class buddyMessage { private int message_id; private Map request; private int subsystem; private BuddyPluginBuddyReplyListener listener; private int timeout_millis; private long queue_time = SystemTime.getCurrentTime(); private boolean timed_out; private int retry_count; private boolean complete; protected buddyMessage( int _subsystem, Map _request, int _timeout ) { synchronized( BuddyPluginBuddy.this ){ message_id = next_message_id++; } request = _request; subsystem = _subsystem; timeout_millis = _timeout; } protected void setListener( BuddyPluginBuddyReplyListener _listener ) { listener = _listener; } protected int getRetryCount() { synchronized( this ){ return( retry_count ); } } protected void setDontRetry() { retry_count = 99; } protected void setRetry() { synchronized( this ){ retry_count++; complete = false; timed_out = false; } } protected boolean timedOut( long now ) { if ( timed_out ){ return( true ); } if ( now < queue_time ){ queue_time = now; return( false ); }else{ timed_out = now - queue_time >= timeout_millis; return( timed_out ); } } protected Map getRequest() { return( request ); } protected int getSubsystem() { return( subsystem ); } protected int getID() { return( message_id ); } protected void reportComplete( Map reply ) { synchronized( this ){ if ( complete ){ return; } complete = true; } try{ listener.replyReceived( BuddyPluginBuddy.this, reply ); }catch( Throwable e ){ Debug.printStackTrace(e); } } protected void reportFailed( Throwable error ) { synchronized( this ){ if ( complete ){ return; } complete = true; } try{ if ( error instanceof BuddyPluginException ){ listener.sendFailed( BuddyPluginBuddy.this, (BuddyPluginException)error ); }else{ listener.sendFailed( BuddyPluginBuddy.this, new BuddyPluginException( "", error )); } }catch( Throwable e ){ Debug.printStackTrace(e); } } protected String getString() { return( "id=" + message_id + ",ss=" + subsystem + (retry_count==0?"":(",retry="+retry_count))); } } protected class buddyConnection implements fragmentHandlerReceiver { private fragmentHandler fragment_handler; private int connection_id; private boolean outgoing; private String dir_str; private volatile buddyMessage active_message; private volatile boolean connected; private volatile boolean closing; private volatile boolean remote_closing; private volatile boolean failed; private long last_active = SystemTime.getCurrentTime(); protected buddyConnection( GenericMessageConnection _connection, boolean _outgoing ) { fragment_handler = new fragmentHandler( _connection, this ); outgoing = _outgoing; synchronized( BuddyPluginBuddy.this ){ connection_id = next_connection_id++; } dir_str = outgoing?"Outgoing":"Incoming"; if ( !outgoing ){ connected = true; buddyConnectionEstablished( false ); } fragment_handler.start(); } protected boolean isConnected() { return( connected ); } protected boolean hasFailed() { return( failed ); } protected boolean isOutgoing() { return( outgoing ); } protected long getLastActive( long now ) { if ( now < last_active ){ last_active = now; } return( last_active ); } protected void sendMessage( buddyMessage message ) throws BuddyPluginException { BuddyPluginException failed_error = null; buddyMessage msg_to_send = null; synchronized( this ){ if ( BuddyPluginBuddy.this.isClosing()){ throw( new BuddyPluginException( "Close in progress" )); } if ( active_message != null ){ Debug.out( "Inconsistent: active message already set" ); failed_error = new BuddyPluginException( "Inconsistent state" ); }else if ( failed || closing ){ throw( new BuddyPluginException( "Connection failed" )); }else{ active_message = message; if ( connected ){ msg_to_send = active_message; } } } if ( failed_error != null ){ failed( failed_error ); throw( failed_error ); } if ( msg_to_send != null ){ send( msg_to_send ); } } protected void sendCloseMessage( buddyMessage message ) { boolean ok_to_send; synchronized( this ){ ok_to_send = active_message == null && connected && !failed && !closing; } if ( ok_to_send ){ send( message ); } } public boolean isActive() { return( active_message != null ); } public void connected() { if ( TRACE ){ System.out.println( dir_str + " connected" ); } buddyMessage msg_to_send = null; synchronized( this ){ last_active = SystemTime.getCurrentTime(); connected = true; msg_to_send = active_message; } buddyConnectionEstablished( true ); if ( msg_to_send != null ){ send( msg_to_send ); } } protected boolean checkTimeout( long now ) { buddyMessage bm = null; boolean close = false; synchronized( this ){ if ( active_message != null ){ if ( active_message.timedOut( now )){ bm = active_message; active_message = null; } } if ( now < last_active ){ last_active = now; } if ( now - last_active > CONNECTION_IDLE_TIMEOUT ){ close = true; } } if ( bm != null ){ bm.reportFailed( new BuddyPluginTimeoutException( "Timeout", true )); } if ( close ){ close(); } return( close ); } protected void send( buddyMessage msg ) { Map request = msg.getRequest(); Map send_map = new HashMap(); send_map.put( "type", new Long( RT_REQUEST_DATA )); send_map.put( "req", request ); send_map.put( "ss", new Long( msg.getSubsystem())); send_map.put( "id", new Long( msg.getID())); send_map.put( "oz", new Long( plugin.getOnlineStatus())); send_map.put( "v", new Long( BuddyPlugin.VERSION_CURRENT )); String loc_cat = getLocalAuthorisedRSSCategoriesAsString(); if ( loc_cat != null ){ send_map.put( "cat", loc_cat ); } try{ // logMessage( "Sending " + msg.getString() + " to " + getString()); fragment_handler.send( send_map, true, true ); synchronized( this ){ last_active = SystemTime.getCurrentTime();; } }catch( BuddyPluginException e ){ try{ failed( e ); }catch( Throwable f ){ Debug.printStackTrace(f); } } } public void receive( Map data_map ) { synchronized( this ){ last_active = SystemTime.getCurrentTime();; } if ( TRACE ){ System.out.println( dir_str + " receive: " + data_map ); } try{ int type = ((Long)data_map.get("type")).intValue(); Long l_os = (Long)data_map.get( "oz" ); if ( l_os != null ){ setOnlineStatus( l_os.intValue()); } Long l_ver = (Long)data_map.get( "v" ); if ( l_ver != null ){ setVersion( l_ver.intValue()); } byte[] b_rem_cat = (byte[])data_map.get( "cat" ); if ( b_rem_cat == null ){ setRemoteAuthorisedRSSCategories( null ); }else{ setRemoteAuthorisedRSSCategories( stringToCats( new String( b_rem_cat, "UTF-8" ))); } if ( type == RT_REQUEST_DATA ){ // logMessage( "Received type=" + type + " from " + getString()); Long subsystem = (Long)data_map.get( "ss" ); Map reply; int reply_type; Map request = (Map)data_map.get( "req" ); String error = null; if ( request == null || subsystem == null ){ reply = null; }else{ try{ reply = plugin.requestReceived( BuddyPluginBuddy.this, subsystem.intValue(), request ); }catch( Throwable e ){ error = Debug.getNestedExceptionMessage(e); reply = null; } } if ( reply == null ){ reply_type = RT_REPLY_ERROR; reply = new HashMap(); reply.put( "error", error==null?"No handlers available to process request":error ); }else{ reply_type = RT_REPLY_DATA; } Map reply_map = new HashMap(); reply_map.put( "ss", subsystem ); reply_map.put( "type", new Long( reply_type )); reply_map.put( "id", data_map.get( "id" ) ); reply_map.put( "oz", new Long( plugin.getOnlineStatus())); String loc_cat = getLocalAuthorisedRSSCategoriesAsString(); if ( loc_cat != null ){ reply_map.put( "cat", loc_cat ); } reply_map.put( "rep", reply ); // don't record as active here as (1) we recorded as active above when // receiving request (2) we may be replying to a 'closing' message and // we don't want the reply to mark as online fragment_handler.send( reply_map, false, false ); }else if ( type == RT_REPLY_DATA || type == RT_REPLY_ERROR ){ long id = ((Long)data_map.get( "id" )).longValue(); buddyMessage bm; synchronized( this ){ if ( active_message != null && active_message.getID() == id ){ bm = active_message; active_message = null; }else{ bm = null; } } Map reply = (Map)data_map.get( "rep" ); if ( bm == null ){ logMessage( "reply discarded as no matching request: " + reply ); }else{ if ( type == RT_REPLY_ERROR ){ bm.setDontRetry(); bm.reportFailed( new BuddyPluginException(new String((byte[])reply.get( "error" )))); }else{ bm.reportComplete( reply ); } } }else{ // ignore unknown message types } }catch( Throwable e ){ failed( e ); } } protected void close() { closing = true; failed( new BuddyPluginException( "Closing" )); } protected boolean isClosing() { return( closing ); } protected void remoteClosing() { remote_closing = true; } protected boolean isRemoteClosing() { return( remote_closing ); } protected void disconnect() { fragment_handler.close(); } public void failed( Throwable error ) { buddyMessage bm = null; if ( !connected && outgoing ){ consec_connect_fails++; } synchronized( this ){ if ( failed ){ return; } failed = true; bm = active_message; active_message = null; } logMessage( "Con " + getString() + " failed: " + Debug.getNestedExceptionMessage( error )); try{ if ( !closing ){ if ( TRACE ){ System.out.println( dir_str + " connection error:" ); } } fragment_handler.close(); }finally{ removeConnection( this ); if ( bm != null ){ bm.reportFailed( error ); } } } protected String getString() { return( getString( false )); } protected String getString( boolean short_form ) { if ( short_form ){ return( fragment_handler.getString()); }else{ return("id=" + connection_id + ",dir=" + ( outgoing?"out":"in" )); } } } protected class fragmentHandler implements GenericMessageConnectionListener { private GenericMessageConnection connection; private fragmentHandlerReceiver receiver; private int next_fragment_id = 0; private fragmentAssembly current_request_frag; private fragmentAssembly current_reply_frag; private int send_count; private int recv_count; protected fragmentHandler( GenericMessageConnection _connection, fragmentHandlerReceiver _receiver ) { connection = _connection; receiver = _receiver; } public void start() { connection.addListener( this ); } public void connected( GenericMessageConnection connection ) { receiver.connected(); } public void failed( GenericMessageConnection connection, Throwable error ) throws MessageException { receiver.failed( error ); } protected void send( Map data_map, boolean is_request, boolean record_active ) throws BuddyPluginException { try{ byte[] data = BEncoder.encode( data_map ); int data_length = data.length; plugin.checkMaxMessageSize( data_length ); int max_chunk = connection.getMaximumMessageSize() - 1024; if ( data_length > max_chunk ){ int fragment_id; synchronized( this ){ fragment_id = next_fragment_id++; } int chunk_num = 0; for (int i=0;i i ){ byte[] chunk = new byte[ end-i ]; System.arraycopy( data, i, chunk, 0, chunk.length ); Map chunk_map = new HashMap(); chunk_map.put( "type", new Long( BuddyPlugin.RT_INTERNAL_FRAGMENT )); chunk_map.put( "f", new Long( fragment_id )); chunk_map.put( "l", new Long( data_length )); chunk_map.put( "c", new Long( max_chunk )); chunk_map.put( "i", new Long( chunk_num )); chunk_map.put( "q", new Long( is_request?1:0 )); chunk_map.put( "d", chunk ); byte[] chunk_data = BEncoder.encode( chunk_map ); PooledByteBuffer chunk_buffer = plugin.getPluginInterface().getUtilities().allocatePooledByteBuffer( chunk_data ); try{ connection.send( chunk_buffer ); chunk_buffer = null; }finally{ if ( chunk_buffer != null ){ chunk_buffer.returnToPool(); } } } chunk_num++; } }else{ PooledByteBuffer buffer = plugin.getPluginInterface().getUtilities().allocatePooledByteBuffer( data ); try{ connection.send( buffer ); buffer = null; }finally{ if ( buffer != null ){ buffer.returnToPool(); } } } buddyMessageSent( data.length, record_active ); send_count++; }catch( Throwable e ){ throw( new BuddyPluginException( "Send failed", e )); } } public void receive( GenericMessageConnection connection, PooledByteBuffer message ) throws MessageException { try{ // while in unauth state we only allow a few messages. max should be 1 // for an 'accept request' but I feel generous if ( recv_count >= 4 && !isAuthorised()){ throw( new MessageException( "Too many messages received while in unauthorised state" )); } byte[] content = message.toByteArray(); Map data_map = BDecoder.decode( content ); if (((Long)data_map.get( "type" )).intValue() == BuddyPlugin.RT_INTERNAL_FRAGMENT ){ Map chunk_map = data_map; int fragment_id = ((Long)chunk_map.get( "f" )).intValue(); int data_length = ((Long)chunk_map.get( "l" )).intValue(); int chunk_size = ((Long)chunk_map.get( "c" )).intValue(); int chunk_num = ((Long)chunk_map.get( "i" )).intValue(); boolean is_request = ((Long)chunk_map.get("q")).intValue() == 1; byte[] chunk_data = (byte[])chunk_map.get("d" ); plugin.checkMaxMessageSize( data_length ); fragmentAssembly assembly; if ( is_request ){ if ( current_request_frag == null ){ current_request_frag = new fragmentAssembly( fragment_id, data_length, chunk_size ); } assembly = current_request_frag; }else{ if ( current_reply_frag == null ){ current_reply_frag = new fragmentAssembly( fragment_id, data_length, chunk_size ); } assembly = current_reply_frag; } if ( assembly.getID() != fragment_id ){ throw( new BuddyPluginException( "Fragment receive error: concurrent decode not supported" )); } if ( assembly.receive( chunk_num, chunk_data )){ if ( is_request ){ current_request_frag = null; }else{ current_reply_frag = null; } buddyMessageReceived( data_length ); recv_count++; receiver.receive( BDecoder.decode( assembly.getData())); }else{ buddyMessageFragmentReceived( assembly.getChunksReceived(), assembly.getTotalChunks()); } }else{ buddyMessageReceived( content.length ); recv_count++; receiver.receive( data_map ); } }catch( Throwable e ){ receiver.failed( e ); }finally{ message.returnToPool(); } } protected void close() { try{ connection.close(); }catch( Throwable e ){ // Debug.printStackTrace( e ); }finally{ receiver.failed( new Exception( "Connection closed" )); } } protected String getString() { return( connection.getType()); } protected class fragmentAssembly { private int id; private byte[] data; private int chunk_size; private int num_chunks; private Set chunks_received = new HashSet(); protected fragmentAssembly( int _id, int _length, int _chunk_size ) { id = _id; chunk_size = _chunk_size; data = new byte[_length]; num_chunks = (_length + chunk_size - 1 )/chunk_size; } protected int getID() { return( id ); } protected int getChunksReceived() { return( chunks_received.size()); } protected int getTotalChunks() { return( num_chunks ); } protected boolean receive( int chunk_num, byte[] chunk ) { // System.out.println( "received chunk " + chunk_num + " of " + num_chunks ); Integer i = new Integer( chunk_num ); if ( chunks_received.contains( i )){ return( false ); } chunks_received.add( i ); System.arraycopy( chunk, 0, data, chunk_num*chunk_size, chunk.length ); return( chunks_received.size() == num_chunks ); } protected byte[] getData() { return( data ); } } } interface fragmentHandlerReceiver { public void connected(); public void receive( Map data ); public void failed( Throwable error ); } } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2Listener.java0000644000175000017500000000177711005750762027255 0ustar adrianadrian/* * Created on Apr 26, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy; public interface BuddyPluginAZ2Listener { public void chatCreated( BuddyPluginAZ2.chatInstance chat ); public void chatDestroyed( BuddyPluginAZ2.chatInstance chat ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/buddy/BuddyPluginListener.java0000644000175000017500000000231611021353642026720 0ustar adrianadrian/* * Created on Apr 1, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy; public interface BuddyPluginListener { public void initialised( boolean available ); public void buddyAdded( BuddyPluginBuddy buddy ); public void buddyRemoved( BuddyPluginBuddy buddy ); public void buddyChanged( BuddyPluginBuddy buddy ); public void messageLogged( String str, boolean is_error ); public void enabledStateChanged( boolean enabled); } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/netstatus/0000755000175000017500000000000011310377630023046 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/net/netstatus/NetStatusPlugin.java0000644000175000017500000001363011003335734027023 0ustar adrianadrian/* * Created on Jan 30, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.netstatus; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.logging.LoggerChannel; import org.gudy.azureus2.plugins.ui.UIInstance; import org.gudy.azureus2.plugins.ui.UIManagerListener; import org.gudy.azureus2.plugins.ui.config.ActionParameter; import org.gudy.azureus2.plugins.ui.config.Parameter; import org.gudy.azureus2.plugins.ui.config.ParameterListener; import org.gudy.azureus2.plugins.ui.config.StringParameter; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.ui.swt.plugins.UISWTInstance; import com.aelitis.azureus.plugins.net.netstatus.swt.NetStatusPluginView; public class NetStatusPlugin implements Plugin { public static final String VIEW_ID = "aznetstatus"; private PluginInterface plugin_interface; private LoggerChannel logger; private StringParameter ping_target; private ActionParameter test_button; private StringParameter test_address; private NetStatusProtocolTester protocol_tester; private AESemaphore protocol_tester_sem = new AESemaphore( "ProtTestSem" ); public static void load( PluginInterface plugin_interface ) { String name = plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( "Views.plugins." + VIEW_ID + ".title" ); plugin_interface.getPluginProperties().setProperty( "plugin.version", "1.0" ); plugin_interface.getPluginProperties().setProperty( "plugin.name", name ); } public void initialize( final PluginInterface _plugin_interface ) { plugin_interface = _plugin_interface; logger = plugin_interface.getLogger().getChannel( "NetStatus" ); logger.setDiagnostic(); BasicPluginConfigModel config = plugin_interface.getUIManager().createBasicPluginConfigModel( "Views.plugins." + VIEW_ID + ".title" ); ping_target = config.addStringParameter2( "plugin.aznetstatus.pingtarget", "plugin.aznetstatus.pingtarget", "www.google.com" ); if ( Constants.isCVSVersion()){ test_address = config.addStringParameter2( "plugin.aznetstatus.test_address", "plugin.aznetstatus.test_address", "" ); test_button = config.addActionParameter2( "test", "test " ); test_button.setEnabled( false ); test_button.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { protocol_tester.runTest( test_address.getValue().trim(), new NetStatusProtocolTesterListener() { public void sessionAdded( NetStatusProtocolTesterBT.Session session ) { } public void complete( NetStatusProtocolTesterBT tester ) { } public void log( String str ) { logger.log( str ); } public void logError( String str ) { logger.log( str ); } public void logError( String str, Throwable e ) { logger.log( str, e ); } }); } }); } plugin_interface.getUIManager().addUIListener( new UIManagerListener() { public void UIAttached( UIInstance instance ) { if ( instance instanceof UISWTInstance ){ UISWTInstance swt_ui = (UISWTInstance)instance; NetStatusPluginView view = new NetStatusPluginView( NetStatusPlugin.this ); swt_ui.addView( UISWTInstance.VIEW_MAIN, VIEW_ID, view ); //swt_ui.openMainView( VIEW_ID, view, null ); } } public void UIDetached( UIInstance instance ) { } }); plugin_interface.addListener( new PluginListener() { public void initializationComplete() { new AEThread2( "NetstatusPlugin:init", true ) { public void run() { try{ protocol_tester = new NetStatusProtocolTester( NetStatusPlugin.this, plugin_interface ); if ( test_button != null ){ test_button.setEnabled( true ); } }finally{ protocol_tester_sem.releaseForever(); } } }.start(); } public void closedownInitiated() { } public void closedownComplete() { } }); } public NetStatusProtocolTester getProtocolTester() { protocol_tester_sem.reserve(); return( protocol_tester ); } public String getPingTarget() { return( ping_target.getValue()); } public void setBooleanParameter( String name, boolean value ) { plugin_interface.getPluginconfig().setPluginParameter( name , value ); } public boolean getBooleanParameter( String name, boolean def ) { return( plugin_interface.getPluginconfig().getPluginBooleanParameter( name, def )); } public void log( String str ) { logger.log( str ); } public void log( String str, Throwable e ) { logger.log( str ); logger.log( e ); } } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTester.java0000644000175000017500000003502410763504776030576 0ustar adrianadrian/* * Created on Feb 15, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.netstatus; import java.net.InetSocketAddress; import java.util.*; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.BEncoder; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.DelayedEvent; import org.gudy.azureus2.core3.util.HashWrapper; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.core3.util.TimerEventPeriodic; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ddb.DistributedDatabase; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseContact; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseException; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseKey; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseProgressListener; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseTransferHandler; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseTransferType; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseValue; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.networkmanager.NetworkManager; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager; import com.aelitis.azureus.plugins.dht.DHTPlugin; import com.aelitis.azureus.plugins.net.netstatus.NetStatusProtocolTesterBT.Session; public class NetStatusProtocolTester implements DistributedDatabaseTransferHandler { private static final int REQUEST_HISTORY_MAX = 64; private static final int MAX_ACTIVE_TESTS = 3; private static final int MAX_TEST_TIME = 120*1000; private static final int TEST_TYPE_BT = 1; private static final int VERSION_INITIAL = 1; private static final int CURRENT_VERSION = VERSION_INITIAL; private static final int BT_MAX_SLAVES = 8; private NetStatusPlugin plugin; private PluginInterface plugin_interface; private DistributedDatabase ddb; private DHTPlugin dht_plugin; private testXferType transfer_type = new testXferType(); private Map request_history = new LinkedHashMap(REQUEST_HISTORY_MAX,0.75f,true) { protected boolean removeEldestEntry( Map.Entry eldest) { return size() > REQUEST_HISTORY_MAX; } }; private List active_tests = new ArrayList(); private TimerEventPeriodic timer_event = null; protected NetStatusProtocolTester( NetStatusPlugin _plugin, PluginInterface _plugin_interface ) { plugin = _plugin; plugin_interface = _plugin_interface; try{ PluginInterface dht_pi = plugin_interface.getPluginManager().getPluginInterfaceByClass( DHTPlugin.class ); if ( dht_pi != null ){ dht_plugin = (DHTPlugin)dht_pi.getPlugin(); } ddb = plugin_interface.getDistributedDatabase(); ddb.addTransferHandler( transfer_type, this ); log( "DDB transfer type registered" ); }catch( Throwable e ){ log( "DDB transfer type registration failed", e ); } } public NetStatusProtocolTesterBT runTest( final NetStatusProtocolTesterListener listener ) { return( runTest( "", listener )); } public NetStatusProtocolTesterBT runTest( String test_address, final NetStatusProtocolTesterListener listener ) { final NetStatusProtocolTesterBT bt_tester = new NetStatusProtocolTesterBT( this, true ); bt_tester.addListener( listener ); bt_tester.start(); addToActive( bt_tester ); try{ if ( test_address.length() == 0 ){ DHT[] dhts = dht_plugin.getDHTs(); DHT target_dht = null; int target_network = Constants.isCVSVersion()?DHT.NW_CVS:DHT.NW_MAIN; for (int i=0;i 0 ){ contact = (DHTTransportContact)f_contacts.remove(0); } } if ( contact == null ){ break; } try{ DistributedDatabaseContact ddb_contact = ddb.importContact( contact.getAddress()); if ( tryTest( bt_tester, ddb_contact )){ synchronized( ok ){ ok[0]++; } } }catch( Throwable e ){ listener.logError( "Contact import for " + contact.getName() + " failed", e ); } } }finally{ sem.release(); } } }.start(); } for (int i=0;i: " ); return( bt_tester ); } InetSocketAddress address = new InetSocketAddress( bits[0].trim(), Integer.parseInt( bits[1].trim())); DistributedDatabaseContact contact = ddb.importContact( address ); tryTest( bt_tester, contact ); } }catch( Throwable e ){ listener.logError( "Test failed", e ); }finally{ bt_tester.addListener( new NetStatusProtocolTesterListener() { public void sessionAdded( Session session) { } public void complete( NetStatusProtocolTesterBT tester ) { removeFromActive( tester ); } public void log( String str ) { } public void logError( String str ) { } public void logError( String str, Throwable e ) { } }); bt_tester.setOutboundConnectionsComplete(); new DelayedEvent( "NetStatus:killer", 10*1000, new AERunnable() { public void runSupport() { listener.log( "Destroying tester" ); bt_tester.destroy(); } }); } return( bt_tester ); } protected boolean tryTest( NetStatusProtocolTesterBT bt_tester, DistributedDatabaseContact contact ) { boolean use_crypto = NetworkManager.getCryptoRequired( NetworkManager.CRYPTO_OVERRIDE_NONE ); log( "Trying test to " + contact.getName()); Map request = new HashMap(); request.put( "v", new Long( CURRENT_VERSION )); request.put( "t", new Long( TEST_TYPE_BT )); request.put( "h", bt_tester.getServerHash()); request.put( "c", new Long( use_crypto?1:0 )); Map reply = sendRequest( contact, request ); byte[] server_hash = reply==null?null:(byte[])reply.get( "h" ); if ( server_hash != null ){ log( " " + contact.getName() + " accepted test" ); bt_tester.testOutbound( adjustLoopback( contact.getAddress()), server_hash, use_crypto ); return( true ); }else{ log( " " + contact.getName() + " declined test" ); return( false ); } } protected InetSocketAddress adjustLoopback( InetSocketAddress address ) { InetSocketAddress local = dht_plugin.getLocalAddress().getAddress(); if ( local.getAddress().getHostAddress().equals( address.getAddress().getHostAddress())){ return( new InetSocketAddress( "127.0.0.1", address.getPort())); }else{ return( address ); } } protected Map sendRequest( DistributedDatabaseContact contact, Map request ) { try{ log( "Sending DDB request to " + contact.getName() + " - " + request ); DistributedDatabaseKey key = ddb.createKey( BEncoder.encode( request )); DistributedDatabaseValue value = contact.read( new DistributedDatabaseProgressListener() { public void reportSize( long size ) { } public void reportActivity( String str ) { } public void reportCompleteness( int percent ) { } }, transfer_type, key, 10000 ); if ( value == null ){ return( null ); } Map reply = BDecoder.decode((byte[])value.getValue( byte[].class )); log( " received reply - " + reply ); return( reply ); }catch( Throwable e ){ log( "sendRequest failed", e ); return( null ); } } protected Map receiveRequest( InetSocketAddress originator, Map request ) { Map reply = new HashMap(); Long test_type = (Long)request.get( "t" ); reply.put( "v", new Long( CURRENT_VERSION )); if ( test_type != null ){ if ( test_type.intValue() == TEST_TYPE_BT ){ TCPNetworkManager tcp_man = TCPNetworkManager.getSingleton(); InetSocketAddress adjusted_originator = adjustLoopback( originator ); boolean test = adjusted_originator.getAddress().isLoopbackAddress(); if ( test || ( tcp_man.isTCPListenerEnabled() && tcp_man.getTCPListeningPortNumber() == ddb.getLocalContact().getAddress().getPort() && SystemTime.getCurrentTime() - tcp_man.getLastIncomingNonLocalConnectionTime() <= 24*60*60*1000 )){ byte[] their_hash = (byte[])request.get( "h" ); if ( their_hash != null ){ NetStatusProtocolTesterBT bt_tester; synchronized( active_tests ){ if ( active_tests.size() > MAX_ACTIVE_TESTS ){ log( "Too many active tests" ); return( reply ); }else{ bt_tester = new NetStatusProtocolTesterBT( this, false ); bt_tester.start(); addToActive( bt_tester ); } } Long l_crypto = (Long)request.get( "c" ); boolean use_crypto = l_crypto!=null&&l_crypto.longValue()==1; bt_tester.testOutbound( adjusted_originator, their_hash, use_crypto ); reply.put( "h", bt_tester.getServerHash()); } } } } return( reply ); } protected void addToActive( NetStatusProtocolTesterBT tester ) { synchronized( active_tests ){ active_tests.add( tester ); if ( timer_event == null ){ timer_event = SimpleTimer.addPeriodicEvent( "NetStatusProtocolTester:timer", 30*1000, new TimerEventPerformer() { public void perform( TimerEvent event ) { long now = SystemTime.getCurrentTime(); List to_remove = new ArrayList(); synchronized( active_tests ){ for (int i=0;i MAX_TEST_TIME ){ to_remove.add( tester ); } } } for ( int i=0;i= 2 ){ log( "Too many responder sessions" ); close(); return; } } sessions.add( this ); is_seed = initiator && sessions.size()%2 == 0; } } Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((NetStatusProtocolTesterListener)it.next()).sessionAdded( this ); }catch( Throwable e ){ Debug.printStackTrace(e); } } connection.connect( ProtocolEndpoint.CONNECT_PRIORITY_MEDIUM, new NetworkConnection.ConnectionListener() { final String type = initiator?"Outbound":"Inbound"; public final void connectStarted() { log( type + " connect start" ); } public final void connectSuccess( ByteBuffer remaining_initial_data ) { log( type + " connect success" ); connected = true; synchronized( NetStatusProtocolTesterBT.this ){ if ( initiator ){ outbound_connects++; }else{ inbound_connects++; } } connected(); } public final void connectFailure( Throwable e ) { if ( !closing ){ logError( type + " connection fail", e ); } close(); } public final void exceptionThrown( Throwable e ) { if ( !closing ){ logError( type + " connection fail", e ); } close(); } public String getDescription() { return( "NetStatusPlugin - " + type ); } }); } public boolean isInitiator() { return( initiator ); } public boolean isConnected() { return( connected ); } public boolean isSeed() { return( is_seed ); } public boolean isOK() { return( bitfield_received ); } protected void connected() { connection.getIncomingMessageQueue().registerQueueListener( new IncomingMessageQueue.MessageQueueListener() { public boolean messageReceived( Message message ) { try{ String message_id = message.getID(); log( "Incoming message received: " + message.getID()); if ( message_id.equals( BTMessage.ID_BT_HANDSHAKE )){ handshake_received = true; BTHandshake handshake = (BTHandshake)message; info_hash = handshake.getDataHash(); num_pieces = 500 + (info_hash[0]&0xff); // we use the piece at 'n' + 1 to indicate a close request by sending a HAVE for it // this helps us tidily close things if ( num_pieces%8 == 0 ){ num_pieces--; } if ( !is_seed ){ int missing = random.nextInt( num_pieces/2 ) + 5; for (int i=0;i public_addresses = new HashSet(); InetAddress def_pa = admin.getDefaultPublicAddress(); if ( def_pa != null ){ log( "Default public address is " + def_pa.getHostAddress()); addPublicAddress( public_addresses, def_pa ); checked_public = true; } if ( doTest( TEST_PING_ROUTE )){ log( "Testing routing for the following interfaces:" ); NetworkAdminNetworkInterface[] interfaces = admin.getInterfaces(); for (int i=0;i 0 ){ log( " " + intf.getName() + "/" + intf.getDisplayName() + ": " + a_str ); } } if ( admin.canPing()){ log( "Running ping tests" ); try{ InetAddress target_address = InetAddress.getByName( plugin.getPingTarget()); final Map active_pings = new HashMap(); admin.pingTargets( target_address, ROUTE_TIMEOUT, new NetworkAdminRoutesListener() { private int timeouts; public boolean foundNode( NetworkAdminNetworkInterfaceAddress intf, NetworkAdminNode[] route, int distance, int rtt ) { if ( test_cancelled ){ return( false ); } synchronized( active_pings ){ active_pings.put( intf, route ); } log( " " + intf.getAddress().getHostAddress() + " -> " + route[route.length-1].getAddress().getHostAddress()); return( false ); } public boolean timeout( NetworkAdminNetworkInterfaceAddress intf, NetworkAdminNode[] route, int distance ) { if ( test_cancelled ){ return( false ); } log( " " + intf.getAddress().getHostAddress() + " - timeout" ); timeouts++; if ( timeouts >= 3 ){ return( false ); } return( true ); } }); if ( test_cancelled ){ return; } int num_routes = active_pings.size(); if ( num_routes == 0 ){ logError( "No active pings found!" ); }else{ log( "Found " + num_routes + " pings(s)" ); Iterator it = active_pings.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); NetworkAdminNetworkInterfaceAddress address = (NetworkAdminNetworkInterfaceAddress)entry.getKey(); NetworkAdminNode[] route = (NetworkAdminNode[])entry.getValue(); String node_str = ""; for (int i=0;i " + ia.getHostAddress() + " (hop=" + distance + ")" + (as.length()==0?"":( " - " + as ))); return( true ); } public boolean timeout( NetworkAdminNetworkInterfaceAddress intf, NetworkAdminNode[] route, int distance ) { if ( test_cancelled ){ return( false ); } log( " " + intf.getAddress().getHostAddress() + " - timeout (hop=" + distance + ")" ); // see if we're getting nowhere if ( route.length == 0 && distance >= 5 ){ logError( " giving up, no responses" ); return( false ); } // see if we've got far enough if ( route.length >= 5 && distance > 6 ){ log( " truncating, sufficient responses" ); return( false ); } return( true ); } }); if ( test_cancelled ){ return; } int num_routes = active_routes.size(); if ( num_routes == 0 ){ logError( "No active routes found!" ); }else{ log( "Found " + num_routes + " route(s)" ); Iterator it = active_routes.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); NetworkAdminNetworkInterfaceAddress address = (NetworkAdminNetworkInterfaceAddress)entry.getKey(); NetworkAdminNode[] route = (NetworkAdminNode[])entry.getValue(); String node_str = ""; for (int i=0;i it = public_addresses.iterator(); log( public_addresses.size() + " public/external addresses found" ); while( it.hasNext()){ InetAddress pub_address = it.next(); log( " " + pub_address.getHostAddress()); try{ NetworkAdminASN asn = admin.lookupASN(pub_address); log( " AS details: " + asn.getString()); }catch( Throwable e ){ logError( " failed to lookup AS", e ); } } } } if ( doTest( TEST_BT_CONNECT )){ log( "Distributed protocol test" ); NetStatusProtocolTesterBT bt_test = plugin.getProtocolTester().runTest( new NetStatusProtocolTesterListener() { private List sessions = new ArrayList(); public void complete( NetStatusProtocolTesterBT tester ) { log( "Results" ); if ( tester.getOutboundConnects() < 4 ){ log( " insufficient outbound connects for analysis" ); return; } int outgoing_seed_ok = 0; int outgoing_leecher_ok = 0; int outgoing_seed_bad = 0; int outgoing_leecher_bad = 0; int incoming_connect_ok = 0; for (int i=0;i 0 && outgoing_seed_ok == 0 && outgoing_seed_bad > 0 ){ logError( " Outgoing seed connects appear to be failing while non-seeds succeed" ); } } public void sessionAdded( NetStatusProtocolTesterBT.Session session ) { synchronized( sessions ){ sessions.add( session ); } } public void log( String str ) { NetStatusPluginTester.this.log( " " + str ); } public void logError( String str ) { NetStatusPluginTester.this.logError( " " + str ); } public void logError( String str, Throwable e ) { NetStatusPluginTester.this.logError( " " + str, e ); } }); while( !bt_test.waitForCompletion( 5000 )){ if ( isCancelled()){ bt_test.destroy(); break; } log( " Status: " + bt_test.getStatus()); } } } protected void addPublicAddress( Set addresses, InetAddress address ) { if ( address == null ){ return; } if ( address.isAnyLocalAddress() || address.isLoopbackAddress() || address.isLinkLocalAddress()|| address.isSiteLocalAddress()){ return; } addresses.add( address ); } public void cancel() { test_cancelled = true; } public boolean isCancelled() { return( test_cancelled ); } protected void log( String str ) { logger.log( str ); } protected void logSuccess( String str ) { logger.logSuccess( str ); } protected void logInfo( String str ) { logger.logInfo( str ); } protected void log( String str, Throwable e ) { logger.log( str + ": " + e.getLocalizedMessage()); } protected void logError( String str ) { logger.logFailure( str ); } protected void logError( String str, Throwable e ) { logger.logFailure( str + ": " + e.getLocalizedMessage()); } public interface loggerProvider { public void log( String str ); public void logSuccess( String str ); public void logInfo( String str ); public void logFailure( String str ); } } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/netstatus/swt/NetStatusPluginView.java0000644000175000017500000002517111172274324030502 0ustar adrianadrian/* * Created on Jan 30, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.netstatus.swt; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT.TriggerInThread; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.plugins.net.netstatus.NetStatusPlugin; public class NetStatusPluginView implements UISWTViewEventListener { private NetStatusPlugin plugin; private boolean created = false; private Composite composite; private Button start_button; private Button cancel_button; private StyledText log; private int selected_tests; private NetStatusPluginTester current_test; private static final int LOG_NORMAL = 1; private static final int LOG_SUCCESS = 2; private static final int LOG_ERROR = 3; private static final int LOG_INFO = 4; private int log_type = LOG_NORMAL; public NetStatusPluginView( NetStatusPlugin _plugin ) { plugin = _plugin; } public boolean eventOccurred( UISWTViewEvent event ) { switch( event.getType() ){ case UISWTViewEvent.TYPE_CREATE:{ if ( created ){ return( false ); } created = true; break; } case UISWTViewEvent.TYPE_INITIALIZE:{ initialise((Composite)event.getData()); break; } case UISWTViewEvent.TYPE_CLOSE: case UISWTViewEvent.TYPE_DESTROY:{ try{ destroy(); }finally{ created = false; } break; } } return true; } protected void initialise( Composite _composite ) { composite = _composite; Composite main = new Composite(composite, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.marginHeight = 0; layout.marginWidth = 0; main.setLayout(layout); GridData grid_data = new GridData(GridData.FILL_BOTH ); main.setLayoutData(grid_data); // control Composite control = new Composite(main, SWT.NONE); layout = new GridLayout(); layout.numColumns = 3; layout.marginHeight = 4; layout.marginWidth = 4; control.setLayout(layout); grid_data = new GridData(GridData.FILL_HORIZONTAL); grid_data.horizontalSpan = 1; control.setLayoutData(grid_data); // start start_button = new Button( control, SWT.PUSH ); Messages.setLanguageText( start_button, "ConfigView.section.start"); start_button.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { start_button.setEnabled( false ); cancel_button.setEnabled( true ); startTest(); } }); // cancel cancel_button = new Button( control, SWT.PUSH ); Messages.setLanguageText( cancel_button, "UpdateWindow.cancel"); cancel_button.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { cancel_button.setEnabled( false ); cancelTest(); } }); cancel_button.setEnabled( false ); Composite options = new Composite(control, SWT.NONE); layout = new GridLayout(); layout.numColumns = 3; layout.marginHeight = 4; layout.marginWidth = 4; options.setLayout(layout); grid_data = new GridData(GridData.FILL_HORIZONTAL); options.setLayoutData(grid_data); Button opt1 = new Button( options, SWT.CHECK ); opt1.setText( "ping/route" ); addOption( opt1, NetStatusPluginTester.TEST_PING_ROUTE ); Button opt2 = new Button( options, SWT.CHECK ); opt2.setText( "outbound" ); addOption( opt2, NetStatusPluginTester.TEST_OUTBOUND ); Button opt3 = new Button( options, SWT.CHECK ); opt3.setText( "inbound" ); addOption( opt3, NetStatusPluginTester.TEST_INBOUND ); Button opt4 = new Button( options, SWT.CHECK ); opt4.setText( "nat/proxies" ); addOption( opt4, NetStatusPluginTester.TEST_NAT_PROXIES ); Button opt5 = new Button( options, SWT.CHECK ); opt5.setText( "BT connect" ); addOption( opt5, NetStatusPluginTester.TEST_BT_CONNECT ); // log area log = new StyledText(main,SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER); grid_data = new GridData(GridData.FILL_BOTH); grid_data.horizontalSpan = 1; grid_data.horizontalIndent = 4; log.setLayoutData(grid_data); log.setIndent( 4 ); } protected void addOption( final Button button, final int type ) { final String config = "test.option." + type; boolean selected = plugin.getBooleanParameter( config, true ); if ( selected ){ selected_tests |= type; }else{ selected_tests &= ~type; } button.setSelection( selected ); button.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { boolean selected = button.getSelection(); if ( selected ){ selected_tests |= type; }else{ selected_tests &= ~type; } plugin.setBooleanParameter( config, selected ); } }); } protected void startTest() { CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD, new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { startTestSupport(core); } }); } protected void cancelTest() { new AEThread2( "NetStatus:cancel", true ) { public void run() { cancelTestSupport(); } }.start(); } protected void startTestSupport(AzureusCore core) { try{ synchronized( this ){ if ( current_test != null ){ Debug.out( "Test already running!!!!" ); return; } current_test = new NetStatusPluginTester( plugin, selected_tests, new NetStatusPluginTester.loggerProvider() { public void log( String str) { println( str ); } public void logSuccess( String str) { try{ log_type = LOG_SUCCESS; println( str ); }finally{ log_type = LOG_NORMAL; } } public void logInfo( String str) { try{ log_type = LOG_INFO; println( str ); }finally{ log_type = LOG_NORMAL; } } public void logFailure( String str) { try{ log_type = LOG_ERROR; println( str ); }finally{ log_type = LOG_NORMAL; } } }); } println( "Test starting", true ); current_test.run(core); println( current_test.isCancelled()?"Test Cancelled":"Test complete" ); }catch( Throwable e ){ }finally{ try{ Composite c = composite; if ( c != null && !c.isDisposed()){ try{ c.getDisplay().asyncExec( new Runnable() { public void run() { if ( !start_button.isDisposed()){ start_button.setEnabled( true ); } if ( !cancel_button.isDisposed()){ cancel_button.setEnabled( false ); } } }); }catch( Throwable e ){ } } }finally{ synchronized( this ){ current_test.cancel(); current_test = null; } } } } protected void println( String str ) { print( str + "\n", false ); } protected void println( String str, boolean clear_first ) { print( str + "\n", clear_first ); } protected void print( final String str, final boolean clear_first ) { plugin.log( str ); if ( !( log.isDisposed() || log.getDisplay().isDisposed())){ final int f_log_type = log_type; log.getDisplay().asyncExec( new Runnable() { public void run() { if ( log.isDisposed()){ return; } int start; if ( clear_first ){ start = 0; log.setText( str ); }else{ start = log.getText().length(); log.append( str ); } Color color; if ( f_log_type == LOG_NORMAL ){ color = Colors.black; }else if ( f_log_type == LOG_SUCCESS ){ color = Colors.green; }else if ( f_log_type == LOG_INFO ){ color = Colors.blue; }else{ color = Colors.red; } StyleRange styleRange = new StyleRange(); styleRange.start = start; styleRange.length = str.length(); styleRange.foreground = color; log.setStyleRange(styleRange); log.setSelection( log.getText().length()); } }); } } protected void cancelTestSupport() { synchronized( this ){ if ( current_test != null ){ println( "Cancelling test..." ); current_test.cancel(); } } } protected void destroy() { cancelTest(); composite = null; } } azureus-4.3.0.6/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTesterListener.java0000644000175000017500000000223310761167746032300 0ustar adrianadrian/* * Created on Feb 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.netstatus; public interface NetStatusProtocolTesterListener { public void sessionAdded( NetStatusProtocolTesterBT.Session session ); public void complete( NetStatusProtocolTesterBT tester ); public void log( String str ); public void logError( String str ); public void logError( String str, Throwable e ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/dht/0000755000175000017500000000000011310377620021004 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/dht/DHTPlugin.java0000644000175000017500000012415011305326642023452 0ustar adrianadrian/* * Created on 24-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.dht; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.logging.LoggerChannel; import org.gudy.azureus2.plugins.logging.LoggerChannelListener; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.components.UITextField; import org.gudy.azureus2.plugins.ui.config.*; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.plugins.ui.model.BasicPluginViewModel; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.plugins.utils.UTTimerEvent; import org.gudy.azureus2.plugins.utils.UTTimerEventPerformer; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.DHTLogger; import com.aelitis.azureus.core.dht.control.DHTControlActivity; import com.aelitis.azureus.core.dht.control.DHTControlContact; import com.aelitis.azureus.core.dht.nat.DHTNATPuncher; import com.aelitis.azureus.core.dht.router.DHTRouterContact; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportFullStats; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTTransportUDPImpl; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.networkmanager.impl.udp.UDPNetworkManager; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; import com.aelitis.azureus.plugins.dht.impl.DHTPluginContactImpl; import com.aelitis.azureus.plugins.dht.impl.DHTPluginImpl; import com.aelitis.azureus.plugins.dht.impl.DHTPluginImplAdapter; import com.aelitis.azureus.plugins.upnp.UPnPMapping; import com.aelitis.azureus.plugins.upnp.UPnPPlugin; /** * @author parg * */ public class DHTPlugin implements Plugin { // data will be the DHT instance created public static final int EVENT_DHT_AVAILABLE = PluginEvent.PEV_FIRST_USER_EVENT; public static final int STATUS_DISABLED = 1; public static final int STATUS_INITALISING = 2; public static final int STATUS_RUNNING = 3; public static final int STATUS_FAILED = 4; public static final byte FLAG_SINGLE_VALUE = DHT.FLAG_SINGLE_VALUE; public static final byte FLAG_DOWNLOADING = DHT.FLAG_DOWNLOADING; public static final byte FLAG_SEEDING = DHT.FLAG_SEEDING; public static final byte FLAG_MULTI_VALUE = DHT.FLAG_MULTI_VALUE; public static final byte FLAG_STATS = DHT.FLAG_STATS; public static final byte FLAG_ANON = DHT.FLAG_ANON; public static final byte FLAG_PRECIOUS = DHT.FLAG_PRECIOUS; public static final byte DT_NONE = DHT.DT_NONE; public static final byte DT_FREQUENCY = DHT.DT_FREQUENCY; public static final byte DT_SIZE = DHT.DT_SIZE; public static final int MAX_VALUE_SIZE = DHT.MAX_VALUE_SIZE; private static final String PLUGIN_VERSION = "1.0"; private static final String PLUGIN_NAME = "Distributed DB"; private static final String PLUGIN_CONFIGSECTION_ID = "plugins.dht"; private static final String PLUGIN_RESOURCE_ID = "ConfigView.section.plugins.dht"; private static final boolean MAIN_DHT_ENABLE = COConfigurationManager.getBooleanParameter( "dht.net.main_v4.enable", true ); private static final boolean CVS_DHT_ENABLE = COConfigurationManager.getBooleanParameter( "dht.net.cvs_v4.enable", true ); private static final boolean MAIN_DHT_V6_ENABLE = COConfigurationManager.getBooleanParameter( "dht.net.main_v6.enable", true ); private PluginInterface plugin_interface; private int status = STATUS_DISABLED; private DHTPluginImpl[] dhts; private DHTPluginImpl main_dht; private DHTPluginImpl cvs_dht; private DHTPluginImpl main_v6_dht; private ActionParameter reseed; private boolean enabled; private int dht_data_port; private boolean got_extended_use; private boolean extended_use; private AESemaphore init_sem = new AESemaphore("DHTPlugin:init" ); private AEMonitor port_change_mon = new AEMonitor( "DHTPlugin:portChanger" ); private boolean port_changing; private int port_change_outstanding; private boolean[] ipfilter_logging = new boolean[1]; private BooleanParameter warn_user; private UPnPMapping upnp_mapping; private LoggerChannel log; private DHTLogger dht_log; private List listeners = new ArrayList(); private long start_mono_time = SystemTime.getMonotonousTime(); public static void load( PluginInterface plugin_interface ) { plugin_interface.getPluginProperties().setProperty( "plugin.version", PLUGIN_VERSION ); plugin_interface.getPluginProperties().setProperty( "plugin.name", PLUGIN_NAME ); } public void initialize( PluginInterface _plugin_interface ) { status = STATUS_INITALISING; plugin_interface = _plugin_interface; dht_data_port = UDPNetworkManager.getSingleton().getUDPNonDataListeningPortNumber(); log = plugin_interface.getLogger().getTimeStampedChannel(PLUGIN_NAME); UIManager ui_manager = plugin_interface.getUIManager(); final BasicPluginViewModel model = ui_manager.createBasicPluginViewModel( PLUGIN_RESOURCE_ID ); model.setConfigSectionID(PLUGIN_CONFIGSECTION_ID); BasicPluginConfigModel config = ui_manager.createBasicPluginConfigModel(ConfigSection.SECTION_PLUGINS, PLUGIN_CONFIGSECTION_ID); config.addLabelParameter2( "dht.info" ); final BooleanParameter enabled_param = config.addBooleanParameter2( "dht.enabled", "dht.enabled", true ); plugin_interface.getPluginconfig().addListener( new PluginConfigListener() { public void configSaved() { int new_dht_data_port = UDPNetworkManager.getSingleton().getUDPNonDataListeningPortNumber(); if ( new_dht_data_port != dht_data_port ){ changePort( new_dht_data_port ); } } }); LabelParameter reseed_label = config.addLabelParameter2( "dht.reseed.label" ); final StringParameter reseed_ip = config.addStringParameter2( "dht.reseed.ip", "dht.reseed.ip", "" ); final IntParameter reseed_port = config.addIntParameter2( "dht.reseed.port", "dht.reseed.port", 0 ); reseed = config.addActionParameter2( "dht.reseed.info", "dht.reseed"); reseed.setEnabled( false ); config.createGroup( "dht.reseed.group", new Parameter[]{ reseed_label, reseed_ip, reseed_port, reseed }); final BooleanParameter ipfilter_logging_param = config.addBooleanParameter2( "dht.ipfilter.log", "dht.ipfilter.log", true ); ipfilter_logging[0] = ipfilter_logging_param.getValue(); ipfilter_logging_param.addListener(new ParameterListener() { public void parameterChanged(Parameter p) { ipfilter_logging[0] = ipfilter_logging_param.getValue(); } }); warn_user = config.addBooleanParameter2( "dht.warn.user", "dht.warn.user", true ); final BooleanParameter advanced = config.addBooleanParameter2( "dht.advanced", "dht.advanced", false ); LabelParameter advanced_label = config.addLabelParameter2( "dht.advanced.label" ); final StringParameter override_ip = config.addStringParameter2( "dht.override.ip", "dht.override.ip", "" ); config.createGroup( "dht.advanced.group", new Parameter[]{ advanced_label, override_ip }); advanced.addEnabledOnSelection( advanced_label ); advanced.addEnabledOnSelection( override_ip ); final StringParameter command = config.addStringParameter2( "dht.execute.command", "dht.execute.command", "print" ); ActionParameter execute = config.addActionParameter2( "dht.execute.info", "dht.execute"); final BooleanParameter logging = config.addBooleanParameter2( "dht.logging", "dht.logging", false ); config.createGroup( "dht.diagnostics.group", new Parameter[]{ command, execute, logging }); logging.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { if ( dhts != null ){ for (int i=0;i contacts = dht.getRouter().getAllContacts(); Map counts = new TreeMap(); for ( DHTRouterContact r: contacts ){ DHTControlContact contact = (DHTControlContact)r.getAttachment(); byte v = contact.getTransportContact().getProtocolVersion(); Integer count = counts.get( v ); if ( count == null ){ counts.put( v, 1 ); }else{ counts.put( v, count+1 ); } } log.log( "Net " + dht.getTransport().getNetwork()); int total = contacts.size(); if ( total == 0 ){ log.log( " no contacts" ); }else{ String ver = ""; for ( Map.Entry entry: counts.entrySet()){ ver += (ver.length()==0?"":", " ) + entry.getKey() + "=" + 100*entry.getValue()/total + "%"; } log.log( " contacts=" + total + ": " + ver ); } }else if ( lc.equals( "testca" )){ ((DHTTransportUDPImpl)transport).testExternalAddressChange(); }else if ( lc.equals( "testnd" )){ ((DHTTransportUDPImpl)transport).testNetworkAlive( false ); }else if ( lc.equals( "testna" )){ ((DHTTransportUDPImpl)transport).testNetworkAlive( true ); }else{ int pos = c.indexOf( ' ' ); if ( pos != -1 ){ String lhs = lc.substring(0,pos); String rhs = c.substring(pos+1); if ( lhs.equals( "set" )){ pos = rhs.indexOf( '=' ); if ( pos != -1 ){ DHTPlugin.this.put( rhs.substring(0,pos).getBytes(), "DHT Plugin: set", rhs.substring(pos+1).getBytes(), (byte)0, log_polistener ); } }else if ( lhs.equals( "get" )){ DHTPlugin.this.get( rhs.getBytes(), "DHT Plugin: get", (byte)0, 1, 10000, true, false, log_polistener ); }else if ( lhs.equals( "query" )){ DHTPlugin.this.get( rhs.getBytes(), "DHT Plugin: get", DHTPlugin.FLAG_STATS, 1, 10000, true, false, log_polistener ); }else if ( lhs.equals( "punch" )){ Map originator_data = new HashMap(); originator_data.put( "hello", "mum" ); DHTNATPuncher puncher = dht.getNATPuncher(); if ( puncher != null ){ puncher.punch( "Test", transport.getLocalContact(), null, originator_data ); } }else if ( lhs.equals( "stats" )){ try{ pos = rhs.lastIndexOf( ":" ); DHTTransportContact contact; if ( pos == -1 ){ contact = transport.getLocalContact(); }else{ String host = rhs.substring(0,pos); int port = Integer.parseInt( rhs.substring(pos+1)); contact = transport.importContact( new InetSocketAddress( host, port ), transport.getProtocolVersion()); } log.log( "Stats request to " + contact.getName()); DHTTransportFullStats stats = contact.getStats(); log.log( "Stats:" + (stats==null?"":stats.getString())); DHTControlActivity[] activities = dht.getControl().getActivities(); for (int j=0;j0?false:timeout_occurred ); return; }else if ( complete_count > 2 ){ return; } // One of the two gets, see how much longer we're happy to hang around for // Only of interest if timeout then uninterested as the other will be // about to timeout if ( timeout_occurred ){ return; } // ignore a v6 completion ahead of a v4 if ( timeout_key == v6_key ){ return; } long now = SystemTime.getCurrentTime(); long elapsed = now - start_time; long rem = timeout - elapsed; if ( rem <= 0 ){ complete( timeout_key, true ); }else{ SimpleTimer.addEvent( "DHTPlugin:dual_dht_early_timeout", now + rem, new TimerEventPerformer() { public void perform( TimerEvent event) { complete( timeout_key, true ); } }); } } } }; // hack - use different keys so we can distinguish which completion event we // have received above main_dht.get( v4_key, description, flags, max_values, timeout, exhaustive, high_priority, dual_listener ); main_v6_dht.get( v6_key, description, flags, max_values, timeout, exhaustive, high_priority, dual_listener ); } } public boolean hasLocalKey( byte[] hash ) { if ( !isEnabled()){ throw( new RuntimeException( "DHT isn't enabled" )); } return( dhts[0].getLocalValue( hash ) != null ); } public void remove( final byte[] key, final String description, final DHTPluginOperationListener listener ) { if ( !isEnabled()){ throw( new RuntimeException( "DHT isn't enabled" )); } dhts[0].remove( key, description, listener ); for (int i=1;i 5000 ){ plugin_interface.getPluginconfig().setPluginParameter( "dht.skew", getClockSkew()); } } public long getClockSkew() { if ( dhts == null || dhts.length == 0 ){ return( 0 ); } long uptime = SystemTime.getMonotonousTime() - start_mono_time; if ( uptime < 5*60*1000 ){ return( loadClockSkew()); } long skew = dhts[0].getClockSkew(); if ( skew > 24*60*60*1000 ){ skew = 0; } skew = ( skew/500 )*500; return( skew ); } public DHTPluginKeyStats decodeStats( DHTPluginValue value ) { return( dhts[0].decodeStats( value )); } public void addListener( DHTPluginListener l ) { listeners.add(l); } public void removeListener( DHTPluginListener l ) { listeners.remove(l); } public void log( String str ) { log.log( str ); } } azureus-4.3.0.6/com/aelitis/azureus/plugins/dht/DHTPluginListener.java0000644000175000017500000000211610357020054025147 0ustar adrianadrian/* * Created on 04-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.dht; public interface DHTPluginListener { public void localAddressChanged( DHTPluginContact local_contact ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/dht/DHTPluginProgressListener.java0000644000175000017500000000230610373051014026673 0ustar adrianadrian/* * Created on 06-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.dht; /** * @author parg * */ public interface DHTPluginProgressListener { public void reportSize( long size ); public void reportActivity( String str ); public void reportCompleteness( int percent ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/dht/DHTPluginTransferHandler.java0000644000175000017500000000240310455333320026445 0ustar adrianadrian/* * Created on 22-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.dht; /** * @author parg * */ public interface DHTPluginTransferHandler { public String getName(); public byte[] handleRead( DHTPluginContact originator, byte[] key ); public void handleWrite( DHTPluginContact originator, byte[] key, byte[] value ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/dht/impl/0000755000175000017500000000000011310377630021746 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/plugins/dht/impl/DHTPluginImpl.java0000644000175000017500000006544311262527610025246 0ustar adrianadrian/* * Created on 24-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.dht.impl; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Properties; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.logging.LoggerChannel; import org.gudy.azureus2.plugins.peers.Peer; import org.gudy.azureus2.plugins.peers.PeerManager; import org.gudy.azureus2.plugins.ui.config.ActionParameter; import org.gudy.azureus2.plugins.ui.config.BooleanParameter; import org.gudy.azureus2.plugins.utils.UTTimerEvent; import org.gudy.azureus2.plugins.utils.UTTimerEventPerformer; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.DHTFactory; import com.aelitis.azureus.core.dht.DHTLogger; import com.aelitis.azureus.core.dht.DHTOperationListener; import com.aelitis.azureus.core.dht.DHTStorageKeyStats; import com.aelitis.azureus.core.dht.control.DHTControlStats; import com.aelitis.azureus.core.dht.db.DHTDBStats; import com.aelitis.azureus.core.dht.nat.DHTNATPuncherAdapter; import com.aelitis.azureus.core.dht.router.DHTRouterStats; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportException; import com.aelitis.azureus.core.dht.transport.DHTTransportFactory; import com.aelitis.azureus.core.dht.transport.DHTTransportListener; import com.aelitis.azureus.core.dht.transport.DHTTransportProgressListener; import com.aelitis.azureus.core.dht.transport.DHTTransportStats; import com.aelitis.azureus.core.dht.transport.DHTTransportTransferHandler; import com.aelitis.azureus.core.dht.transport.DHTTransportValue; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.plugins.dht.DHTPlugin; import com.aelitis.azureus.plugins.dht.DHTPluginContact; import com.aelitis.azureus.plugins.dht.DHTPluginKeyStats; import com.aelitis.azureus.plugins.dht.DHTPluginOperationListener; import com.aelitis.azureus.plugins.dht.DHTPluginProgressListener; import com.aelitis.azureus.plugins.dht.DHTPluginTransferHandler; import com.aelitis.azureus.plugins.dht.DHTPluginValue; import com.aelitis.azureus.plugins.dht.impl.DHTPluginStorageManager; /** * @author parg * */ public class DHTPluginImpl { private static final String SEED_ADDRESS_V4 = Constants.DHT_SEED_ADDRESS_V4; private static final String SEED_ADDRESS_V6 = Constants.DHT_SEED_ADDRESS_V6; private static final int SEED_PORT = 6881; private static final long MIN_ROOT_SEED_IMPORT_PERIOD = 8*60*60*1000; private PluginInterface plugin_interface; private int status; private String status_text; private ActionParameter reseed_param; private BooleanParameter warn_user_param; private DHT dht; private int port; private byte protocol_version; private int network; private boolean v6; private DHTTransportUDP transport; private DHTPluginStorageManager storage_manager; private long last_root_seed_import_time; private LoggerChannel log; private DHTLogger dht_log; private int stats_ticks; public DHTPluginImpl( PluginInterface _plugin_interface, DHTNATPuncherAdapter _nat_adapter, DHTPluginImplAdapter _adapter, byte _protocol_version, int _network, boolean _v6, String _ip, int _port, ActionParameter _reseed, BooleanParameter _warn_user_param, boolean _logging, LoggerChannel _log, DHTLogger _dht_log ) { plugin_interface = _plugin_interface; protocol_version = _protocol_version; network = _network; v6 = _v6; port = _port; reseed_param = _reseed; warn_user_param = _warn_user_param; log = _log; dht_log = _dht_log; final DHTPluginImplAdapter adapter = _adapter; try{ storage_manager = new DHTPluginStorageManager( network, dht_log, getDataDir( _network )); final PluginConfig conf = plugin_interface.getPluginconfig(); int send_delay = conf.getPluginIntParameter( "dht.senddelay", 25 ); int recv_delay = conf.getPluginIntParameter( "dht.recvdelay", 25 ); boolean bootstrap = conf.getPluginBooleanParameter( "dht.bootstrapnode", false ); // start off optimistic with reachable = true boolean initial_reachable = conf.getPluginBooleanParameter( "dht.reachable." + network, true ); transport = DHTTransportFactory.createUDP( _protocol_version, _network, _v6, _ip, storage_manager.getMostRecentAddress(), _port, 3, 1, 10000, // udp timeout - tried less but a significant number of // premature timeouts occurred send_delay, recv_delay, bootstrap, initial_reachable, dht_log ); transport.addListener( new DHTTransportListener() { public void localContactChanged( DHTTransportContact local_contact ) { storage_manager.localContactChanged( local_contact ); if ( adapter != null ){ adapter.localContactChanged( getLocalAddress()); } } public void currentAddress( String address ) { storage_manager.recordCurrentAddress( address ); } public void reachabilityChanged( boolean reacheable ) { } }); Properties props = new Properties(); /* System.out.println( "FRIGGED REFRESH PERIOD" ); props.put( DHT.PR_CACHE_REPUBLISH_INTERVAL, new Integer( 5*60*1000 )); */ if ( _network == DHT.NW_CVS ){ // reduce network usage //System.out.println( "CVS DHT cache republish interval modified" ); props.put( DHT.PR_CACHE_REPUBLISH_INTERVAL, new Integer( 1*60*60*1000 )); } dht = DHTFactory.create( transport, props, storage_manager, _nat_adapter, dht_log ); plugin_interface.firePluginEvent( new PluginEvent() { public int getType() { return( DHTPlugin.EVENT_DHT_AVAILABLE ); } public Object getValue() { return( dht ); } }); dht.setLogging( _logging ); DHTTransportContact root_seed = importRootSeed(); storage_manager.importContacts( dht ); plugin_interface.getUtilities().createTimer( "DHTExport", true ).addPeriodicEvent( 10*60*1000, new UTTimerEventPerformer() { public void perform( UTTimerEvent event ) { checkForReSeed(false); storage_manager.exportContacts( dht ); } }); integrateDHT( true, root_seed ); status = DHTPlugin.STATUS_RUNNING; status_text = "Running"; }catch( Throwable e ){ Debug.printStackTrace(e); log.log( "DHT integrtion fails", e ); status_text = "DHT Integration fails: " + Debug.getNestedExceptionMessage( e ); status = DHTPlugin.STATUS_FAILED; } } public void updateStats( int sample_stats_ticks ) { stats_ticks++; if ( transport != null ){ PluginConfig conf = plugin_interface.getPluginconfig(); boolean current_reachable = transport.isReachable(); if ( current_reachable != conf.getPluginBooleanParameter( "dht.reachable." + network, true )){ // reachability has changed conf.setPluginParameter( "dht.reachable." + network, current_reachable ); if ( !current_reachable ){ String msg = "If you have a router/firewall, please check that you have port " + port + " UDP open.\nDecentralised tracking requires this." ; int warned_port = plugin_interface.getPluginconfig().getPluginIntParameter( "udp_warned_port", 0 ); if ( warned_port == port || !warn_user_param.getValue() ){ log.log( msg ); }else{ plugin_interface.getPluginconfig().setPluginParameter( "udp_warned_port", port ); log.logAlert( LoggerChannel.LT_WARNING, msg ); } }else{ log.log( "Reachability changed for the better" ); } } if ( stats_ticks % sample_stats_ticks == 0 ){ logStats(); } } } public int getStatus() { return( status ); } public String getStatusText() { return( status_text ); } public boolean isReachable() { return( transport.isReachable()); } public void setLogging( boolean l ) { dht.setLogging( l ); } public void tick() { } public int getPort() { return( port ); } public void setPort( int new_port ) { port = new_port; try{ transport.setPort( port ); }catch( Throwable e ){ log.log( e ); } } public long getClockSkew() { return( transport.getStats().getSkewAverage()); } public void logStats() { DHTDBStats d_stats = dht.getDataBase().getStats(); DHTControlStats c_stats = dht.getControl().getStats(); DHTRouterStats r_stats = dht.getRouter().getStats(); DHTTransportStats t_stats = transport.getStats(); long[] rs = r_stats.getStats(); log.log( "DHT:ip=" + transport.getLocalContact().getAddress() + ",net=" + transport.getNetwork() + ",prot=V" + transport.getProtocolVersion()+ ",reach=" + transport.isReachable()); log.log( "Router" + ":nodes=" + rs[DHTRouterStats.ST_NODES] + ",leaves=" + rs[DHTRouterStats.ST_LEAVES] + ",contacts=" + rs[DHTRouterStats.ST_CONTACTS] + ",replacement=" + rs[DHTRouterStats.ST_REPLACEMENTS] + ",live=" + rs[DHTRouterStats.ST_CONTACTS_LIVE] + ",unknown=" + rs[DHTRouterStats.ST_CONTACTS_UNKNOWN] + ",failing=" + rs[DHTRouterStats.ST_CONTACTS_DEAD]); log.log( "Transport" + ":" + t_stats.getString()); int[] dbv_details = d_stats.getValueDetails(); log.log( "Control:dht=" + c_stats.getEstimatedDHTSize() + ", Database:keys=" + d_stats.getKeyCount() + ",vals=" + dbv_details[DHTDBStats.VD_VALUE_COUNT]+ ",loc=" + dbv_details[DHTDBStats.VD_LOCAL_SIZE]+ ",dir=" + dbv_details[DHTDBStats.VD_DIRECT_SIZE]+ ",ind=" + dbv_details[DHTDBStats.VD_INDIRECT_SIZE]+ ",div_f=" + dbv_details[DHTDBStats.VD_DIV_FREQ]+ ",div_s=" + dbv_details[DHTDBStats.VD_DIV_SIZE] ); } protected File getDataDir( int network ) { File dir = new File( plugin_interface.getUtilities().getAzureusUserDir(), "dht" ); if ( network != 0 ){ dir = new File( dir, "net" + network ); } FileUtil.mkdirs(dir); return( dir ); } public void integrateDHT( boolean first, DHTTransportContact remove_afterwards ) { try{ reseed_param.setEnabled( false ); log.log( "DHT " + (first?"":"re-") + "integration starts" ); long start = SystemTime.getCurrentTime(); dht.integrate( false ); if ( remove_afterwards != null ){ log.log( "Removing seed " + remove_afterwards.getString()); remove_afterwards.remove(); } long end = SystemTime.getCurrentTime(); log.log( "DHT " + (first?"":"re-") + "integration complete: elapsed = " + (end-start)); dht.print( false ); }finally{ reseed_param.setEnabled( true ); } } public void checkForReSeed( boolean force ) { int seed_limit = 32; try{ long[] router_stats = dht.getRouter().getStats().getStats(); if ( router_stats[ DHTRouterStats.ST_CONTACTS_LIVE] < seed_limit || force ){ if ( force ){ log.log( "Reseeding" ); }else{ log.log( "Less than 32 live contacts, reseeding" ); } int peers_imported = 0; // only try boostrapping off connected peers on the main network as it is unlikely // any of them are running CVS and hence the boostrap will fail if ( network == DHT.NW_MAIN || network == DHT.NW_MAIN_V6 ){ // first look for peers to directly import Download[] downloads = plugin_interface.getDownloadManager().getDownloads(); outer: for (int i=0;i seed_limit ){ break outer; } } } } } } DHTTransportContact root_to_remove = null; if ( peers_imported == 0 ){ root_to_remove = importRootSeed(); if ( root_to_remove != null ){ peers_imported++; } } if ( peers_imported > 0 ){ integrateDHT( false, root_to_remove ); }else{ log.log( "No valid peers found to reseed from" ); } } }catch( Throwable e ){ log.log(e); } } protected DHTTransportContact importRootSeed() { try{ long now = SystemTime.getCurrentTime(); if ( now - last_root_seed_import_time > MIN_ROOT_SEED_IMPORT_PERIOD ){ last_root_seed_import_time = now; return( importSeed( getSeedAddress(), SEED_PORT )); }else{ log.log( " root seed imported too recently, ignoring" ); } }catch( Throwable e ){ log.log(e); } return( null ); } public DHTTransportContact importSeed( String ip, int port ) { try{ return( importSeed( InetAddress.getByName( ip ), port )); }catch( Throwable e ){ log.log(e); return( null ); } } protected DHTTransportContact importSeed( InetAddress ia, int port ) { try{ return( transport.importContact( new InetSocketAddress(ia, port ), protocol_version )); }catch( Throwable e ){ log.log(e); return( null ); } } protected InetAddress getSeedAddress() { try{ return( InetAddress.getByName( v6?SEED_ADDRESS_V6:SEED_ADDRESS_V4 )); } catch (java.net.UnknownHostException e) { Debug.out("Could not get DHT seed address: " + e); return null; }catch( Throwable e ){ Debug.printStackTrace( e ); return( null ); } } public boolean isDiversified( byte[] key ) { return( dht.isDiversified( key )); } public void put( byte[] key, String description, byte[] value, byte flags, DHTPluginOperationListener listener) { put( key, description, value, flags, true, listener ); } public void put( final byte[] key, final String description, final byte[] value, final byte flags, final boolean high_priority, final DHTPluginOperationListener listener) { dht.put( key, description, value, flags, high_priority, new DHTOperationListener() { private boolean started; public void searching( DHTTransportContact contact, int level, int active_searches ) { if ( listener != null ){ synchronized( this ){ if ( started ){ return; } started = true; } listener.starts( key ); } } public void diversified( String desc ) { } public void found( DHTTransportContact contact, boolean is_closest ) { } public void read( DHTTransportContact _contact, DHTTransportValue _value ) { Debug.out( "read operation not supported for puts" ); } public void wrote( DHTTransportContact _contact, DHTTransportValue _value ) { // log.log( "Put: wrote " + _value.getString() + " to " + _contact.getString()); if ( listener != null ){ listener.valueWritten( new DHTPluginContactImpl(DHTPluginImpl.this, _contact ), mapValue( _value )); } } public void complete( boolean timeout ) { // log.log( "Put: complete, timeout = " + timeout ); if ( listener != null ){ listener.complete( key, timeout ); } } }); } public DHTPluginValue getLocalValue( byte[] key ) { final DHTTransportValue val = dht.getLocalValue( key ); if ( val == null ){ return( null ); } return( mapValue( val )); } public void get( final byte[] key, final String description, final byte flags, final int max_values, final long timeout, final boolean exhaustive, final boolean high_priority, final DHTPluginOperationListener listener ) { dht.get( key, description, flags, max_values, timeout, exhaustive, high_priority, new DHTOperationListener() { private boolean started = false; public void searching( DHTTransportContact contact, int level, int active_searches ) { if ( listener != null ){ synchronized( this ){ if ( started ){ return; } started = true; } listener.starts( key ); } } public void diversified( String desc ) { if ( listener != null ){ listener.diversified(); } } public void found( DHTTransportContact contact, boolean is_closest ) { } public void read( final DHTTransportContact contact, final DHTTransportValue value ) { // log.log( "Get: read " + value.getString() + " from " + contact.getString() + ", originator = " + value.getOriginator().getString()); if ( listener != null ){ listener.valueRead( new DHTPluginContactImpl( DHTPluginImpl.this, value.getOriginator()), mapValue( value )); } } public void wrote( final DHTTransportContact contact, final DHTTransportValue value ) { // log.log( "Get: wrote " + value.getString() + " to " + contact.getString()); } public void complete( boolean _timeout ) { // log.log( "Get: complete, timeout = " + _timeout ); if ( listener != null ){ listener.complete( key, _timeout ); } } }); } public void remove( final byte[] key, final String description, final DHTPluginOperationListener listener ) { dht.remove( key, description, new DHTOperationListener() { private boolean started; public void searching( DHTTransportContact contact, int level, int active_searches ) { if ( listener != null ){ synchronized( this ){ if ( started ){ return; } started = true; } listener.starts( key ); } } public void found( DHTTransportContact contact, boolean is_closest ) { } public void diversified( String desc ) { } public void read( DHTTransportContact contact, DHTTransportValue value ) { // log.log( "Remove: read " + value.getString() + " from " + contact.getString()); } public void wrote( DHTTransportContact contact, DHTTransportValue value ) { // log.log( "Remove: wrote " + value.getString() + " to " + contact.getString()); if ( listener != null ){ listener.valueWritten( new DHTPluginContactImpl( DHTPluginImpl.this, contact ), mapValue( value )); } } public void complete( boolean timeout ) { // log.log( "Remove: complete, timeout = " + timeout ); if ( listener != null ){ listener.complete( key, timeout ); } } }); } public void remove( final DHTPluginContact[] targets, final byte[] key, final String description, final DHTPluginOperationListener listener ) { DHTTransportContact[] t_contacts = new DHTTransportContact[ targets.length ]; for (int i=0;i ADDRESS_EXPIRY ){ it.remove(); } } } writeMapToFile( recent_addresses, "addresses" ); }catch( Throwable e ){ Debug.printStackTrace(e); }finally{ address_mon.exit(); } } protected void recordCurrentAddress( String address ) { try{ address_mon.enter(); recent_addresses.put( address, new Long( SystemTime.getCurrentTime())); recent_addresses.put( "most_recent", address.getBytes()); writeRecentAddresses(); }finally{ address_mon.exit(); } } protected String getMostRecentAddress() { byte[] addr = (byte[])recent_addresses.get( "most_recent" ); if ( addr == null ){ return( null ); } return( new String( addr )); } protected boolean isRecentAddress( String address ) { try{ address_mon.enter(); if ( recent_addresses.containsKey( address )){ return( true ); } String most_recent = getMostRecentAddress(); return( most_recent != null && most_recent.equals( address )); }finally{ address_mon.exit(); } } protected void localContactChanged( DHTTransportContact contact ) { purgeDirectKeyBlocks(); } protected Map readMapFromFile( String file_prefix ) { try{ File target = new File( data_dir, file_prefix + ".dat" ); if ( !target.exists()){ target = new File( data_dir, file_prefix + ".saving" ); } if ( target.exists()){ BufferedInputStream is = new BufferedInputStream( new FileInputStream( target )); try{ return( BDecoder.decode( is )); }finally{ is.close(); } } }catch( Throwable e ){ Debug.printStackTrace( e ); } return( new HashMap()); } protected void writeMapToFile( Map map, String file_prefix ) { try{ File saving = new File( data_dir, file_prefix + ".saving" ); File target = new File( data_dir, file_prefix + ".dat" ); saving.delete(); if ( map.size() == 0 ){ target.delete(); }else{ FileOutputStream os = null; boolean ok = false; try{ byte[] data = BEncoder.encode( map ); os = new FileOutputStream( saving ); os.write( data ); os.flush(); os.getFD().sync(); os.close(); ok = true; }finally{ if ( os != null ){ os.close(); if ( ok ){ target.delete(); saving.renameTo( target ); } } } } }catch( Throwable e ){ Debug.printStackTrace(e); } } protected void readVersionData() { try{ version_mon.enter(); version_map = readMapFromFile( "version" ); }finally{ version_mon.exit(); } } protected void writeVersionData() { try{ version_mon.enter(); writeMapToFile( version_map, "version" ); }finally{ version_mon.exit(); } } public int getNextValueVersions( int num ) { try{ version_mon.enter(); Long l_next = (Long)version_map.get( "next" ); int now = (int)(SystemTime.getCurrentTime()/1000); int next; if ( l_next == null ){ next = now; }else{ next = l_next.intValue(); // if "next" is in the future then we live with it to try and ensure increasing // values (system clock must have changed) if ( next < now ){ next = now; } } version_map.put( "next", new Long( next+num )); writeVersionData(); return( next ); }finally{ version_mon.exit(); } } // key storage public DHTStorageKey keyCreated( HashWrapper key, boolean local ) { //System.out.println( "DHT key created"); try{ storage_mon.enter(); return( getStorageKey( key )); }finally{ storage_mon.exit(); } } public void keyDeleted( DHTStorageKey key ) { //System.out.println( "DHT key deleted" ); try{ storage_mon.enter(); deleteStorageKey((storageKey)key ); }finally{ storage_mon.exit(); } } public int getKeyCount() { try{ storage_mon.enter(); return( local_storage_keys.size()); }finally{ storage_mon.exit(); } } public void keyRead( DHTStorageKey key, DHTTransportContact contact ) { //System.out.println( "DHT value read" ); try{ storage_mon.enter(); ((storageKey)key).read( contact ); }finally{ storage_mon.exit(); } } public void serialiseStats( storageKey key, DataOutputStream dos ) throws IOException { dos.writeByte( (byte)0 ); // version dos.writeInt( key.getEntryCount()); dos.writeInt( key.getSize()); dos.writeInt( key.getReadsPerMinute()); dos.writeByte( key.getDiversificationType()); } public DHTStorageKeyStats deserialiseStats( DataInputStream is ) throws IOException { byte version = is.readByte(); final int entry_count = is.readInt(); final int size = is.readInt(); final int reads = is.readInt(); final byte div = is.readByte(); return( new DHTStorageKeyStats() { public int getEntryCount() { return( entry_count ); } public int getSize() { return( size ); } public int getReadsPerMinute() { return( reads ); } public byte getDiversification() { return( div ); } public String getString() { return( "entries=" + getEntryCount() + ",size=" + getSize() + ",rpm=" + getReadsPerMinute() + ",div=" + getDiversification()); } }); } public void valueAdded( DHTStorageKey key, DHTTransportValue value ) { // System.out.println( network + ": DHT value added: " + DHTLog.getString2( ((storageKey)key).getKey().getBytes()) + " -> " + value.getString()); try{ storage_mon.enter(); ((storageKey)key).valueChanged( 1, value.getValue().length); }finally{ storage_mon.exit(); } } public void valueUpdated( DHTStorageKey key, DHTTransportValue old_value, DHTTransportValue new_value ) { //System.out.println( "DHT value updated" ); try{ storage_mon.enter(); ((storageKey)key).valueChanged( 0, new_value.getValue().length - old_value.getValue().length); }finally{ storage_mon.exit(); } } public void valueDeleted( DHTStorageKey key, DHTTransportValue value ) { //System.out.println( "DHT value deleted" ); try{ storage_mon.enter(); ((storageKey)key).valueChanged( -1, -value.getValue().length); }finally{ storage_mon.exit(); } } public boolean isDiversified( byte[] key ) { HashWrapper wrapper = new HashWrapper( key ); try{ storage_mon.enter(); return( lookupDiversification( wrapper ) != null ); }finally{ storage_mon.exit(); } } // get diversifications for put operations must deterministically return the same end points // but gets for gets should be randomised to load balance public byte[][] getExistingDiversification( byte[] key, boolean put_operation, boolean exhaustive, int max_depth ) { if ( suspendDivs()){ return( new byte[][]{ key }); } //System.out.println( "DHT get existing diversification: put = " + put_operation ); HashWrapper wrapper = new HashWrapper( key ); // must always return a value - original if no diversification exists try{ storage_mon.enter(); byte[][] res = followDivChain( wrapper, put_operation, exhaustive, max_depth ); if ( res.length > 0 && !Arrays.equals( res[0], key )){ String trace = ""; for (int i=0;i " + trace ); } return( res ); }finally{ storage_mon.exit(); } } public byte[][] createNewDiversification( String description, DHTTransportContact cause, byte[] key, boolean put_operation, byte diversification_type, boolean exhaustive, int max_depth ) { if ( suspendDivs()){ if ( put_operation ){ return( new byte[0][] ); } } // System.out.println( "DHT create new diversification: desc=" + description + ", put=" + put_operation +", type=" + diversification_type ); HashWrapper wrapper = new HashWrapper( key ); try{ storage_mon.enter(); diversification div = lookupDiversification( wrapper ); boolean created = false; if ( div == null ){ div = createDiversification( wrapper, diversification_type ); created = true; } byte[][] res = followDivChain( wrapper, put_operation, exhaustive, max_depth ); String trace = ""; for (int i=0;i " + trace + ", cause=" + (cause==null?"":cause.getString()) + ", desc=" + description ); return( res ); }finally{ storage_mon.exit(); } } protected byte[][] followDivChain( HashWrapper wrapper, boolean put_operation, boolean exhaustive, int max_depth ) { List list = new ArrayList(); list.add( wrapper ); list = followDivChainSupport( list, put_operation, 0, exhaustive, new ArrayList(), max_depth ); byte[][] res = new byte[list.size()][]; for (int i=0;i" ); */ // for each entry, if there are no diversifications then we just return the value // for those with divs we replace their entry with the diversified set (which can // include the entry itself under some circumstances ) for (int i=0;i 0 && suspend_divs_until > SystemTime.getCurrentTime()); } protected void readDiversifications() { if ( suspendDivs()){ return; } try{ storage_mon.enter(); Map map = readMapFromFile( "diverse" ); List keys = (List)map.get("local"); if ( keys != null ){ long now = SystemTime.getCurrentTime(); for (int i=0;i 0 ){ local_storage_keys.put( d.getKey(), d ); }else{ log.log( "SM: serialised sk: " + DHTLog.getString2( d.getKey().getBytes()) + " expired" ); } } } List divs = (List)map.get("remote"); if ( divs != null ){ long now = SystemTime.getCurrentTime(); for (int i=0;i 0 ){ diversification existing = (diversification)remote_diversifications.put( d.getKey(), d ); if ( existing != null ){ divRemoved( existing ); } divAdded( d ); }else{ log.log( "SM: serialised div: " + DHTLog.getString2( d.getKey().getBytes()) + " expired" ); } } } }finally{ storage_mon.exit(); } } protected void writeDiversifications() { if ( suspendDivs()){ return; } try{ storage_mon.enter(); Map map = new HashMap(); List keys = new ArrayList(); map.put( "local", keys ); Iterator it = local_storage_keys.values().iterator(); while( it.hasNext()){ storageKey key = (storageKey)it.next(); if ( key.getDiversificationType() != DHT.DT_NONE ){ keys.add(key.serialise()); } } List divs = new ArrayList(); map.put( "remote", divs ); it = remote_diversifications.values().iterator(); while( it.hasNext()){ divs.add(((diversification)it.next()).serialise()); } writeMapToFile( map, "diverse" ); }catch( Throwable e ){ Debug.printStackTrace(e); }finally{ storage_mon.exit(); } } protected diversification lookupDiversification( HashWrapper wrapper ) { diversification div = (diversification)remote_diversifications.get(wrapper); if ( div != null ){ if ( div.getExpiry() < SystemTime.getCurrentTime()){ log.log( "SM: div: " + DHTLog.getString2( div.getKey().getBytes()) + " expired" ); remote_diversifications.remove( wrapper ); divRemoved( div ); div = null; } } return( div ); } protected diversification createDiversification( HashWrapper wrapper, byte type ) { diversification div = new diversification( this, wrapper, type ); diversification existing = (diversification)remote_diversifications.put( wrapper, div ); if ( existing != null ){ divRemoved( existing ); } divAdded( div ); writeDiversifications(); return( div ); } protected void divAdded( diversification div ) { if ( div.getType() == DHT.DT_FREQUENCY ){ remote_freq_div_count++; }else{ remote_size_div_count++; } } protected void divRemoved( diversification div ) { if ( div.getType() == DHT.DT_FREQUENCY ){ remote_freq_div_count--; }else{ remote_size_div_count--; } } public int getRemoteFreqDivCount() { return( remote_freq_div_count ); } public int getRemoteSizeDivCount() { return( remote_size_div_count ); } protected static String formatExpiry( long l ) { long diff = l - SystemTime.getCurrentTime(); return( (diff<0?"-":"") + DisplayFormatters.formatTime(Math.abs(diff))); } // key blocks protected void readKeyBlocks() { try{ key_block_mon.enter(); Map map = readMapFromFile( "block" ); List entries = (List)map.get( "entries" ); int now_secs = (int)(SystemTime.getCurrentTime()/1000); ByteArrayHashMap new_map = new ByteArrayHashMap(); if ( entries != null ){ for (int i=0;i now_secs ){ recv = now_secs; } keyBlock kb = new keyBlock( request, cert, recv, direct ); // direct "add" values never timeout, however direct "removals" do, as do // indirect values if ( ( direct && kb.isAdd()) || now_secs - recv < KEY_BLOCK_TIMEOUT_SECS ){ if ( verifyKeyBlock( request, cert )){ log.log( "KB: deserialised " + DHTLog.getString2( kb.getKey()) + ",add=" + kb.isAdd() + ",dir=" + kb.isDirect()); new_map.put( kb.getKey(), kb ); } } }catch( Throwable e ){ Debug.printStackTrace(e); } } } key_block_map_cow = new_map; key_blocks_direct_cow = buildKeyBlockDetails( new_map ); }finally{ key_block_mon.exit(); } } protected DHTStorageBlock[] buildKeyBlockDetails( ByteArrayHashMap map ) { List kbs = map.values(); Iterator it = kbs.iterator(); while( it.hasNext()){ keyBlock kb = (keyBlock)it.next(); if ( !kb.isDirect()){ it.remove(); } } DHTStorageBlock[] new_blocks = new DHTStorageBlock[kbs.size()]; kbs.toArray( new_blocks ); return( new_blocks ); } protected void writeKeyBlocks() { try{ key_block_mon.enter(); Map map = new HashMap(); List entries = new ArrayList(); map.put( "entries", entries ); List kbs = key_block_map_cow.values(); for (int i=0;i unblock, 01 ->block if ( request.length <= 8 ){ return( null ); } keyBlock kb = new keyBlock(request, signature, (int)(SystemTime.getCurrentTime()/1000), originating_contact != null ); try{ key_block_mon.enter(); boolean add_it = false; try{ keyBlock old = (keyBlock)key_block_map_cow.get( kb.getKey()); if ( old != null ){ // never override a direct value with an indirect one as direct = first hand knowledge // whereas indirect is hearsay if ( old.isDirect() && !kb.isDirect()){ return( null ); } // don't let older instructions override newer ones if ( old.getCreated() > kb.getCreated()){ return( null ); } } if ( kb.isAdd()){ if ( old == null || !old.isAdd()){ if ( !verifyKeyBlock( kb, originating_contact )){ return( null ); } add_it = true; } return( kb ); }else{ // only direct operations can "remove" blocks if ( kb.isDirect() && ( old == null || old.isAdd())){ if ( !verifyKeyBlock( kb, originating_contact )){ return( null ); } add_it = true; } return( null ); } }finally{ if ( add_it ){ ByteArrayHashMap new_map = key_block_map_cow.duplicate(); new_map.put( kb.getKey(), kb ); // seeing as we've received this from someone there's no point in replicating it // back to them later - mark them to prevent this if ( originating_contact != null ){ kb.sentTo( originating_contact ); } key_block_map_cow = new_map; key_blocks_direct_cow = buildKeyBlockDetails( key_block_map_cow ); writeKeyBlocks(); } } }finally{ key_block_mon.exit(); } } protected boolean verifyKeyBlock( keyBlock kb, DHTTransportContact originator ) { byte[] id = originator==null?new byte[20]:originator.getID(); BloomFilter filter = kb_verify_fail_bloom; long now = SystemTime.getCurrentTime(); if ( filter == null || kb_verify_fail_bloom_create_time > now || now - kb_verify_fail_bloom_create_time > 30*60*1000 ){ kb_verify_fail_bloom_create_time = now; filter = BloomFilterFactory.createAddOnly(4000); kb_verify_fail_bloom = filter; } if ( filter.contains( id )){ log.log( "KB: request verify denied" ); return( false ); } try{ Signature verifier = Signature.getInstance("MD5withRSA" ); verifier.initVerify( key_block_public_key ); verifier.update( kb.getRequest() ); if ( !verifier.verify( kb.getCertificate())){ log.log( "KB: request verify failed for " + DHTLog.getString2( kb.getKey())); filter.add( id ); return( false ); } log.log( "KB: request verify ok " + DHTLog.getString2( kb.getKey()) + ", add = " + kb.isAdd() + ", direct = " + kb.isDirect()); return( true ); }catch( Throwable e ){ return( false ); } } public static boolean verifyKeyBlock( byte[] request, byte[] signature ) { try{ Signature verifier = Signature.getInstance("MD5withRSA" ); verifier.initVerify( key_block_public_key ); verifier.update( request ); if ( !verifier.verify( signature )){ return( false ); } return( true ); }catch( Throwable e ){ return( false ); } } public DHTStorageBlock getKeyBlockDetails( byte[] key ) { keyBlock kb = (keyBlock)key_block_map_cow.get( key ); if ( kb == null || !kb.isAdd()){ return( null ); } if ( !kb.getLogged()){ kb.setLogged(); log.log( "KB: Access to key '" + DHTLog.getFullString( kb.getKey()) + "' denied as it is blocked" ); } return( kb ); } public DHTStorageBlock[] getDirectKeyBlocks() { return( key_blocks_direct_cow ); } public byte[] getKeyForKeyBlock( byte[] request ) { if ( request.length <= 8 ){ return( new byte[0] ); } byte[] key = new byte[ request.length - 8 ]; System.arraycopy( request, 8, key, 0, key.length ); return( key ); } protected void purgeDirectKeyBlocks() { try{ key_block_mon.enter(); ByteArrayHashMap new_map = new ByteArrayHashMap(); Iterator it = key_block_map_cow.values().iterator(); boolean changed = false; while( it.hasNext()){ keyBlock kb = (keyBlock)it.next(); if ( kb.isDirect()){ changed = true; }else{ new_map.put( kb.getKey(), kb ); } } if ( changed ){ log.log( "KB: Purged direct entries on ID change" ); key_block_map_cow = new_map; key_blocks_direct_cow = buildKeyBlockDetails( key_block_map_cow ); writeKeyBlocks(); } }finally{ key_block_mon.exit(); } } public void setStorageForKey( String key, byte[] data ) { try{ storage_mon.enter(); Map map = readMapFromFile( "general" ); map.put( key, data ); writeMapToFile( map, "general" ); }finally{ storage_mon.exit(); } } public byte[] getStorageForKey( String key ) { try{ storage_mon.enter(); Map map = readMapFromFile( "general" ); return((byte[])map.get( key )); }finally{ storage_mon.exit(); } } protected static class keyBlock implements DHTStorageBlock { private byte[] request; private byte[] cert; private int received; private boolean direct; private BloomFilter sent_to_bloom; private boolean logged; protected keyBlock( byte[] _request, byte[] _cert, int _received, boolean _direct ) { request = _request; cert = _cert; received = _received; direct = _direct; } public byte[] getRequest() { return( request ); } public byte[] getCertificate() { return( cert ); } public byte[] getKey() { byte[] key = new byte[ request.length - 8 ]; System.arraycopy( request, 8, key, 0, key.length ); return( key ); } protected boolean isAdd() { return( request[0] == 0x01 ); } protected boolean getLogged() { return( logged ); } protected void setLogged() { logged = true; } protected int getCreated() { int created = (request[4]<<24)&0xff000000 | (request[5]<<16)&0x00ff0000 | (request[6]<< 8)&0x0000ff00 | request[7] &0x000000ff; return( created ); } protected int getReceived() { return( received ); } protected boolean isDirect() { return( direct ); } public boolean hasBeenSentTo( DHTTransportContact contact ) { BloomFilter filter = sent_to_bloom; if ( filter == null ){ return( false ); } return( filter.contains( contact.getID())); } public void sentTo( DHTTransportContact contact ) { BloomFilter filter = sent_to_bloom; if ( filter == null || filter.getEntryCount() > 100 ){ filter = BloomFilterFactory.createAddOnly(500); sent_to_bloom = filter; } filter.add( contact.getID()); } } protected static class diversification { private DHTPluginStorageManager manager; private HashWrapper key; private byte type; private long expiry; private int[] fixed_put_offsets; protected diversification( DHTPluginStorageManager _manager, HashWrapper _key, byte _type ) { manager = _manager; key = _key; type = _type; expiry = SystemTime.getCurrentTime() + DIV_EXPIRY_MIN + (long)(Math.random() * DIV_EXPIRY_RAND ); fixed_put_offsets = new int[DIV_FRAG_GET_SIZE]; int pos = 0; while( pos < DIV_FRAG_GET_SIZE ){ int i = (int)(Math.random()*DIV_WIDTH); boolean found = false; for (int j=0;j LOCAL_DIVERSIFICATION_READS_PER_MIN_SAMPLES*60*1000 ){ if ( ip_bloom_filter != null ){ int ip_entries = ip_bloom_filter.getEntryCount(); reads_per_min = (short)( ip_entries / LOCAL_DIVERSIFICATION_READS_PER_MIN_SAMPLES ); if ( reads_per_min == 0 && ip_entries > 0 ){ // show at least some activity! reads_per_min = 1; } if ( ip_entries > LOCAL_DIVERSIFICATION_READS_PER_MIN * LOCAL_DIVERSIFICATION_READS_PER_MIN_SAMPLES ){ if ( !manager.suspendDivs()){ type = DHT.DT_FREQUENCY; manager.log.log( "SM: sk freq created (" + ip_entries + "reads ) - " + DHTLog.getString2( key.getBytes())); manager.writeDiversifications(); } } } read_count_start = now; ip_bloom_filter = null; // just null it and drop this read, doesn't matter // and means that we don't bother creating a filter for // infrequently accessed data }else{ if ( ip_bloom_filter == null ){ // we want to hold enough IPs to detect a hit rate of reads_per_min*min // with a reasonable accuracy (sized to 10/3 to save space - this gives // an average of 100 adds required to detect 90 unique) ip_bloom_filter = BloomFilterFactory.createAddOnly( ( LOCAL_DIVERSIFICATION_READS_PER_MIN * LOCAL_DIVERSIFICATION_READS_PER_MIN_SAMPLES *10 ) / 3 ); } byte[] address_bytes = contact.getAddress().getAddress().getAddress(); ip_bloom_filter.add( address_bytes ); } } } protected void valueChanged( int entries_diff, int size_diff ) { entries += entries_diff; size += size_diff; if ( entries < 0 ){ Debug.out( "entries negative" ); entries = 0; } if ( size < 0 ){ Debug.out( "size negative" ); size = 0; } if ( type == DHT.DT_NONE ){ if ( !manager.suspendDivs()){ if ( size > LOCAL_DIVERSIFICATION_SIZE_LIMIT ){ type = DHT.DT_SIZE; manager.log.log( "SM: sk size total created (size " + size + ") - " + DHTLog.getString2( key.getBytes())); manager.writeDiversifications(); }else if ( entries > LOCAL_DIVERSIFICATION_ENTRIES_LIMIT ){ type = DHT.DT_SIZE; manager.log.log( "SM: sk size entries created (" + entries + " entries) - " + DHTLog.getString2( key.getBytes())); manager.writeDiversifications(); } } } // System.out.println( "value changed: entries = " + entries + "(" + entries_diff + "), size = " + size + "(" + size_diff + ")"); } } } azureus-4.3.0.6/com/aelitis/azureus/plugins/dht/impl/DHTPluginValueImpl.java0000644000175000017500000000305310551527776026245 0ustar adrianadrian/* * Created on 14-Jun-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.dht.impl; import com.aelitis.azureus.core.dht.transport.DHTTransportValue; import com.aelitis.azureus.plugins.dht.DHTPluginValue; public class DHTPluginValueImpl implements DHTPluginValue { private DHTTransportValue value; protected DHTPluginValueImpl( DHTTransportValue _value ) { value = _value; } public byte[] getValue() { return( value.getValue()); } public long getCreationTime() { return( value.getCreationTime()); } public long getVersion() { return( value.getVersion()); } public int getFlags() { return( value.getFlags()&0xff); } }azureus-4.3.0.6/com/aelitis/azureus/plugins/dht/impl/DHTPluginImplAdapter.java0000644000175000017500000000221410645412416026533 0ustar adrianadrian/* * Created on Jul 11, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.dht.impl; import com.aelitis.azureus.plugins.dht.DHTPluginContact; public interface DHTPluginImplAdapter { public void localContactChanged( DHTPluginContact contact ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/dht/impl/DHTPluginContactImpl.java0000644000175000017500000000617411265520552026557 0ustar adrianadrian/* * Created on 14-Jun-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.dht.impl; import java.net.InetSocketAddress; import java.util.Map; import com.aelitis.azureus.core.dht.nat.DHTNATPuncher; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportReplyHandlerAdapter; import com.aelitis.azureus.plugins.dht.DHTPluginContact; import com.aelitis.azureus.plugins.dht.DHTPluginOperationListener; import com.aelitis.azureus.plugins.dht.DHTPluginProgressListener; public class DHTPluginContactImpl implements DHTPluginContact { private DHTPluginImpl plugin; private DHTTransportContact contact; protected DHTPluginContactImpl( DHTPluginImpl _plugin, DHTTransportContact _contact ) { plugin = _plugin; contact = _contact; } public DHTPluginImpl getDHT() { return( plugin ); } protected DHTTransportContact getContact() { return( contact ); } public String getName() { return( contact.getName()); } public byte getProtocolVersion() { return( contact.getProtocolVersion()); } public InetSocketAddress getAddress() { return( contact.getAddress()); } public boolean isAlive( long timeout ) { return( contact.isAlive( timeout )); } public void isAlive( long timeout, final DHTPluginOperationListener listener ) { contact.isAlive( new DHTTransportReplyHandlerAdapter() { public void pingReply( DHTTransportContact contact ) { listener.complete( null, false ); } public void failed( DHTTransportContact contact, Throwable error ) { listener.complete( null, true ); } }, timeout ); } public boolean isOrHasBeenLocal() { return( plugin.isRecentAddress( contact.getAddress().getAddress().getHostAddress())); } public Map openTunnel() { DHTNATPuncher puncher = plugin.getDHT().getNATPuncher(); if ( puncher == null ){ return( null ); } return( puncher.punch( "Tunnel", contact, null, null )); } public byte[] read( DHTPluginProgressListener listener, byte[] handler_key, byte[] key, long timeout ) { return( plugin.read( listener, this, handler_key, key, timeout )); } }azureus-4.3.0.6/com/aelitis/azureus/plugins/dht/DHTPluginOperationListener.java0000644000175000017500000000256511043601320027032 0ustar adrianadrian/* * Created on 01-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.dht; /** * @author parg * */ public interface DHTPluginOperationListener { public void starts( byte[] key ); public void diversified(); public void valueRead( DHTPluginContact originator, DHTPluginValue value ); public void valueWritten( DHTPluginContact target, DHTPluginValue value ); public void complete( byte[] key, boolean timeout_occurred ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/dht/DHTPluginValue.java0000644000175000017500000000224310412370562024443 0ustar adrianadrian/* * Created on 05-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.dht; /** * @author parg * */ public interface DHTPluginValue { public byte[] getValue(); public long getCreationTime(); public long getVersion(); public int getFlags(); } azureus-4.3.0.6/com/aelitis/azureus/plugins/dht/DHTPluginContact.java0000644000175000017500000000307011265520560024763 0ustar adrianadrian/* * Created on 25-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.dht; import java.net.InetSocketAddress; import java.util.Map; /** * @author parg * */ public interface DHTPluginContact { public String getName(); public InetSocketAddress getAddress(); public byte getProtocolVersion(); public boolean isAlive( long timeout ); public void isAlive( long timeout, DHTPluginOperationListener listener ); public boolean isOrHasBeenLocal(); public Map openTunnel(); public byte[] read( final DHTPluginProgressListener listener, final byte[] handler_key, final byte[] key, final long timeout ); } azureus-4.3.0.6/com/aelitis/azureus/plugins/dht/DHTPluginKeyStats.java0000644000175000017500000000221110434652644025141 0ustar adrianadrian/* * Created on 23 May 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.plugins.dht; public interface DHTPluginKeyStats { public int getEntryCount(); public int getSize(); public int getReadsPerMinute(); public byte getDiversification(); } azureus-4.3.0.6/com/aelitis/azureus/launcher/0000755000175000017500000000000011310377630020346 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/launcher/classloading/0000755000175000017500000000000011310377630023011 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/launcher/classloading/SecondaryClassLoader.java0000644000175000017500000000275110736557060027735 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.launcher.classloading; import java.net.URL; import java.net.URLClassLoader; /** * @author Aaron Grunthal * @create 28.12.2007 */ public class SecondaryClassLoader extends URLClassLoader implements PeeringClassloader { public SecondaryClassLoader(URL[] urls, PrimaryClassloader parent) { super(urls,parent); parent.registerSecondaryClassloader(this); } Class findLoadedClassHelper(String name) { return findLoadedClass(name); } Class findClassHelper(String name) { try { return findClass(name); } catch (ClassNotFoundException e) { return null; } } } azureus-4.3.0.6/com/aelitis/azureus/launcher/classloading/PrimaryClassloader.java0000644000175000017500000001171410776567410027474 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.launcher.classloading; import java.io.File; import java.lang.ref.WeakReference; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; /** * @author Aaron Grunthal * @create 28.12.2007 */ public class PrimaryClassloader extends URLClassLoader implements PeeringClassloader { private final ArrayList peersLoaders = new ArrayList(); private final ClassLoader packageLoader; private static final String packageName = PrimaryClassloader.class.getPackage().getName(); /** * initialization path when loaded through bootstrapping */ private PrimaryClassloader() { super(generateURLs(),getSystemClassLoader().getParent()); this.packageLoader = getSystemClassLoader(); } /** * initialization path when loaded via * -Djava.system.class.loader=com.aelitis.azureus.launcher.classloading.PrimaryClassloader * instead of bootstrapping, has the advantage that this gets registered as system classloader * * @deprecated DO NOT INVOKE MANUALLY */ public PrimaryClassloader(ClassLoader parent) { super(generateURLs(),parent.getParent()); this.packageLoader = parent; } private static URL[] generateURLs() { String classpath = System.getProperty("java.class.path"); String[] paths = classpath.split(File.pathSeparator); URL[] urls = new URL[paths.length+1]; try { for(int i=0;i *

    2. follow normal delegation, circumventing the system classloader as we bootstraped it away
    3. *
    4. OR delegate to the system classloader iff it is for classes from this package, this allows us to rebootstrap and discard other branches in the hierarchy
    5. *
    6. check for loaded by peers
    7. *
    8. try to load from peers
    9. *
    */ protected Class loadClass(final String name, boolean resolve) throws ClassNotFoundException { //System.out.println(this+" loading "+name); Class c; try { if (!name.startsWith(packageName)) c = super.loadClass(name, resolve); else c = packageLoader.loadClass(name); } catch (ClassNotFoundException e) { c = peerFindLoadedClass(name); if (c == null) c = peerLoadClass(name); if (c == null) throw e; if (resolve) resolveClass(c); } return c; } private Class peerFindLoadedClass(String className) { Class c = null; synchronized (peersLoaders) { for (int i = 0; i < peersLoaders.size() && c == null; i++) { WeakReference ref = (WeakReference) peersLoaders.get(i); SecondaryClassLoader loader = (SecondaryClassLoader) ref.get(); if (loader != null) c = loader.findLoadedClassHelper(className); else peersLoaders.remove(i--); } } return c; } private Class peerLoadClass(String className) { Class c = null; synchronized (peersLoaders) { for(int i=0;i *
    * * This example shows how to implement a main class that ensures that it is * called through the primary class loader:
    	 * MyClass {
    	 * 	public static void main(String[] args) {
    	 * 		if(Launcher.checkAndLaunch(MyClass.class,args))
    	 * 			return;
    	 * 		... // normal main code
    	 * 	}
    	 * }
    	 * 
    * * * @param MainClass * @param args * @return true if bootstrapping was necessary and the main method was * called through a new classloader, false otherwise */ public static boolean checkAndLaunch(Class MainClass,String[] args) { if(isBootStrapped()) return false; launch(MainClass, args); return true; } /** * * @return true if the current classloader is part of the {@link PeeringClassloader} hierarchy */ public static boolean isBootStrapped() { if(!LOADER_ENABLED || ClassLoaderWitness.class.getClassLoader() instanceof PeeringClassloader) return true; return false; } public static SecondaryClassLoader getComponentLoader(URL[] urls) { if(!isBootStrapped()) throw new IllegalStateException("Current Classloader is not part of the peering hierarchy!"); ClassLoader primary = ClassLoaderWitness.class.getClassLoader(); while(!(primary instanceof PrimaryClassloader)) primary = primary.getParent(); return new SecondaryClassLoader(urls,(PrimaryClassloader)primary); } public static void main(String[] args) { // TODO unify commandline processing and GUI selection code here } } azureus-4.3.0.6/com/aelitis/azureus/launcher/ClassLoaderWitness.java0000644000175000017500000000214110736557060024770 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.launcher; /** * the only purpose of this class is to have a reference point for ClassLoader checks * * @author Aaron Grunthal * @create 28.12.2007 */ public abstract class ClassLoaderWitness {} azureus-4.3.0.6/com/aelitis/azureus/launcher/MainExecutor.java0000644000175000017500000000304410736557060023625 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.launcher; import java.lang.reflect.Method; /** * @author Aaron Grunthal * @create 28.12.2007 */ public class MainExecutor { static void load(final ClassLoader loader,final String mainClass, final String[] args) { Thread t = new Thread(new Runnable() { public void run() { try { Method main = loader.loadClass(mainClass).getMethod("main", new Class[] {String[].class}); main.invoke(null, new Object[] {args}); } catch (Exception e) { System.err.println("Invoking main failed"); e.printStackTrace(); System.exit(1); } } },"MainRunner"); t.setContextClassLoader(loader); t.start(); } } azureus-4.3.0.6/com/aelitis/azureus/launcher/LauncherTest.java0000644000175000017500000000320210736557060023617 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.launcher; import com.aelitis.azureus.launcher.classloading.PeeringClassloader; /** * @author Aaron Grunthal * @create 28.12.2007 */ public class LauncherTest { public static void main(String[] args) { System.out.println("current loader\t"+LauncherTest.class.getClassLoader()); System.out.println("classloader's loader\t"+LauncherTest.class.getClassLoader().getClass().getClassLoader()); System.out.println("classloader interface's loader\t"+PeeringClassloader.class.getClassLoader()); if(LauncherTest.class.getClassLoader() instanceof PeeringClassloader) System.out.println("success"); else { System.out.println("wrong classloader, invoking launcher"); Launcher.launch(LauncherTest.class, args); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/0000755000175000017500000000000011310377630017162 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/UIFunctions.java0000644000175000017500000000773311270547352022252 0ustar adrianadrian/* * Created on Jun 14, 2006 9:02:55 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui; import org.gudy.azureus2.core3.download.DownloadManager; import com.aelitis.azureus.core.AzureusCoreComponent; import com.aelitis.azureus.ui.common.updater.UIUpdater; /** * @author TuxPaper * @created Jun 14, 2006 * * * TODO: Replace showXxxx(..) with showView(ID, ..) + ID Constants */ public interface UIFunctions extends AzureusCoreComponent { public static int STATUSICON_NONE = 0; public static int STATUSICON_WARNING = 1; public static int STATUSICON_ERROR = 2; public static final int VIEW_CONSOLE = 0; public static final int VIEW_STATS = 1; public static final int VIEW_CONFIG = 4; public static final int VIEW_DM_DETAILS = 5; public static final int VIEW_DM_MULTI_OPTIONS = 6; public static final int VIEW_MYSHARES = 7; public static final int VIEW_MYTORRENTS = 8; public static final int VIEW_MYTRACKER = 9; public static final int VIEW_ALLPEERS = 10; public static final int VIEW_DETAILED_LISTVIEW = 11; public static final int VIEW_PEERS_STATS = 12; public static final int ACTION_FULL_UPDATE = 1; // arg: String - url; response Boolean - ok /** * Bring main window to the front */ void bringToFront(); /** * Bring main window to the front * * @param noTricks Don't try any tricks to force it to the top * * @since 3.0.1.7 */ void bringToFront(boolean noTricks); /** * Change/Refresh the language of the UI */ void refreshLanguage(); /** * */ void refreshIconBar(); /** * @param manager */ void removeManagerView(DownloadManager dm); /** * @param string */ void setStatusText(String string); void setStatusText(int statustype, String string, UIStatusTextClickListener l); /** * Request the UI be shut down. * * @return true - request granted, UI is being shut down * false - request denied (example: password entry failed) */ boolean dispose(boolean for_restart, boolean close_already_in_progress); boolean viewURL(String url, String target, int w, int h, boolean allowResize, boolean isModal); boolean viewURL(String url, String target, double wPct, double hPct, boolean allowResize, boolean isModal); void viewURL(String url, String target, String sourceRef); public UIFunctionsUserPrompter getUserPrompter(String title, String text, String[] buttons, int defaultOption); public void promptUser(String title, String text, String[] buttons, int defaultOption, String rememberID, String rememberText, boolean bRememberByDefault, int autoCloseInMS, UserPrompterResultListener l); /** * Retrieves the class that handles periodically updating the UI * * @return * * @since 3.1.1.1 */ public UIUpdater getUIUpdater(); /** * @param viewID * @param data * * @since 3.1.1.1 */ void openView(int viewID, Object datasource); void doSearch(String searchText); /** * * @param action_id * @param args * @param listener */ public void performAction( int action_id, Object args, actionListener listener ); interface actionListener { public void actionComplete( Object result ); } } azureus-4.3.0.6/com/aelitis/azureus/ui/selectedcontent/0000755000175000017500000000000011310377630022345 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/selectedcontent/SelectedContentManager.java0000644000175000017500000000763711167543452027612 0ustar adrianadrian/** * Created on May 6, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.selectedcontent; import java.util.ArrayList; import java.util.List; import org.gudy.azureus2.core3.download.DownloadManager; import com.aelitis.azureus.ui.common.table.TableView; /** * Manages the currently selected content in the visible display * * @author TuxPaper * @created May 6, 2008 * */ public class SelectedContentManager { private static List listeners = new ArrayList(); private static ISelectedContent[] currentlySelectedContent = new ISelectedContent[0]; private static String viewID = null; private static TableView tv = null; public static String getCurrentySelectedViewID() { return viewID; } public static void addCurrentlySelectedContentListener( SelectedContentListener l) { listeners.add(l); l.currentlySelectedContentChanged(currentlySelectedContent, viewID); } public static void clearCurrentlySelectedContent() { changeCurrentlySelectedContent(null, null, null); } public static void changeCurrentlySelectedContent(String viewID, ISelectedContent[] currentlySelectedContent) { changeCurrentlySelectedContent(viewID, currentlySelectedContent, null); } public static void changeCurrentlySelectedContent(String viewID, ISelectedContent[] currentlySelectedContent, TableView tv) { SelectedContentManager.tv = tv; if (currentlySelectedContent == null) { currentlySelectedContent = new ISelectedContent[0]; } /* System.out.println("change CURSEL for '" + viewID + "' to " + currentlySelectedContent.length + ";" + (currentlySelectedContent.length > 0 ? currentlySelectedContent[0] : "") + Debug.getCompressedStackTrace()); */ if (currentlySelectedContent.length == 0 && SelectedContentManager.viewID != null && viewID != null && !viewID.equals(SelectedContentManager.viewID)) { // don't allow clearing if someone else set the currently selected //System.out.println("-->abort because it's not " + SelectedContentManager.viewID); return; } SelectedContentManager.currentlySelectedContent = currentlySelectedContent == null ? new ISelectedContent[0] : currentlySelectedContent; SelectedContentManager.viewID = viewID; Object[] listenerArray = listeners.toArray(); for (int i = 0; i < listenerArray.length; i++) { SelectedContentListener l = (SelectedContentListener) listenerArray[i]; l.currentlySelectedContentChanged( SelectedContentManager.currentlySelectedContent, viewID); } } public static ISelectedContent[] getCurrentlySelectedContent() { return currentlySelectedContent; } public static DownloadManager[] getDMSFromSelectedContent() { ISelectedContent[] sc = SelectedContentManager.getCurrentlySelectedContent(); if (sc.length > 0) { int x = 0; DownloadManager[] dms = new DownloadManager[sc.length]; for (int i = 0; i < sc.length; i++) { ISelectedContent selectedContent = sc[i]; if (selectedContent == null) { continue; } dms[x] = selectedContent.getDownloadManager(); if (dms[x] != null) { x++; } } if (x > 0) { System.arraycopy(dms, 0, dms, 0, x); return dms; } } return null; } public static TableView getCurrentlySelectedTableView() { return tv; } } azureus-4.3.0.6/com/aelitis/azureus/ui/selectedcontent/SelectedContentV3.java0000644000175000017500000001157411167543450026521 0ustar adrianadrian/** * Created on Jun 9, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.selectedcontent; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; import com.aelitis.azureus.ui.selectedcontent.SelectedContent; import com.aelitis.azureus.util.PlayUtils; /** * @author TuxPaper * @created Jun 9, 2008 * */ public class SelectedContentV3 implements ISelectedContent { private final SelectedContent content; private boolean isPlatformContent; private boolean canPlay; private String thumbURL; private byte[] imageBytes; private DownloadUrlInfo downloadInfo; public SelectedContentV3(SelectedContent content) { this.content = content; this.setDownloadManager(content.getDownloadManager()); } public SelectedContentV3() { content = new SelectedContent(); } public SelectedContentV3(String hash, String displayName, boolean isPlatformContent, boolean canPlay) { this.isPlatformContent = isPlatformContent; this.canPlay = canPlay; content = new SelectedContent(hash, displayName); } public SelectedContentV3(DownloadManager dm) throws Exception { content = new SelectedContent(); setDownloadManager(dm); } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#getDisplayName() public String getDisplayName() { return content.getDisplayName(); } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#getDM() public DownloadManager getDownloadManager() { return content.getDownloadManager(); } public TOTorrent getTorrent(){ return content.getTorrent(); } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#getHash() public String getHash() { return content.getHash(); } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#setDisplayName(java.lang.String) public void setDisplayName(String displayName) { content.setDisplayName(displayName); } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#setDM(org.gudy.azureus2.core3.download.DownloadManager) public void setDownloadManager(DownloadManager dm) { content.setDownloadManager(dm); if ( dm != null ){ setTorrent( dm.getTorrent()); setDisplayName(PlatformTorrentUtils.getContentTitle2(dm)); } } public void setTorrent( TOTorrent torrent ){ content.setTorrent( torrent ); if ( torrent != null ){ try { setHash(torrent.getHashWrapper().toBase32String()); } catch (Exception e) { setHash(null); } setPlatformContent(PlatformTorrentUtils.isContent(torrent, true)); setDisplayName(PlatformTorrentUtils.getContentTitle( torrent )); setCanPlay(PlayUtils.canUseEMP(torrent)); setImageBytes(PlatformTorrentUtils.getContentThumbnail(torrent)); } } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#setHash(java.lang.String) public void setHash(String hash) { content.setHash(hash); } public void setHash(String hash, boolean isPlatformContent) { content.setHash(hash); setPlatformContent(isPlatformContent); } public boolean isPlatformContent() { return isPlatformContent; } public void setPlatformContent(boolean isPlatformContent) { this.isPlatformContent = isPlatformContent; } public boolean canPlay() { return canPlay; } public void setCanPlay(boolean canPlay) { this.canPlay = canPlay; } public String getThumbURL() { return thumbURL; } public void setThumbURL(String thumbURL) { this.thumbURL = thumbURL; } /** * @param imageBytes the imageBytes to set */ public void setImageBytes(byte[] imageBytes) { this.imageBytes = imageBytes; } /** * @return the imageBytes */ public byte[] getImageBytes() { return imageBytes; } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#getDownloadInfo() public DownloadUrlInfo getDownloadInfo() { return downloadInfo; } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#setDownloadInfo(com.aelitis.azureus.ui.selectedcontent.SelectedContentDownloadInfo) public void setDownloadInfo(DownloadUrlInfo info) { this.downloadInfo = info; } } azureus-4.3.0.6/com/aelitis/azureus/ui/selectedcontent/ISelectedVuzeFileContent.java0000644000175000017500000000174711167563052030074 0ustar adrianadrian/* * Created on Apr 9, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.ui.selectedcontent; import com.aelitis.azureus.core.vuzefile.VuzeFile; public interface ISelectedVuzeFileContent extends ISelectedContent { public VuzeFile getVuzeFile(); } azureus-4.3.0.6/com/aelitis/azureus/ui/selectedcontent/ISelectedContent.java0000644000175000017500000000305611167543452026417 0ustar adrianadrian/** * Created on Jun 9, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.selectedcontent; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.torrent.TOTorrent; /** * @author TuxPaper * @created Jun 9, 2008 * */ public interface ISelectedContent { public abstract String getHash(); public abstract void setHash(String hash); public abstract DownloadManager getDownloadManager(); public abstract void setDownloadManager(DownloadManager dm); public abstract TOTorrent getTorrent(); public void setTorrent( TOTorrent torrent ); public abstract String getDisplayName(); public abstract void setDisplayName(String displayName); /** * @since 3.1.1.1 */ public abstract DownloadUrlInfo getDownloadInfo(); /** * @since 3.1.1.1 */ public abstract void setDownloadInfo(DownloadUrlInfo downloadInfo); }azureus-4.3.0.6/com/aelitis/azureus/ui/selectedcontent/SelectedContent.java0000644000175000017500000000713111171750562026301 0ustar adrianadrian/** * Created on May 6, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.selectedcontent; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.HashWrapper; import com.aelitis.azureus.core.AzureusCoreFactory; /** * Represents a piece of content (torrent) that is selected * * @author TuxPaper * @created May 6, 2008 * */ public class SelectedContent implements ISelectedContent { private String hash; private DownloadManager dm; private TOTorrent torrent; private String displayName; private DownloadUrlInfo downloadInfo; /** * @param dm2 * @throws Exception */ public SelectedContent(DownloadManager dm){ setDownloadManager(dm); } /** * */ public SelectedContent(String hash, String displayName) { this.hash = hash; this.displayName = displayName; } public SelectedContent() { } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#getHash() public String getHash() { return hash; } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#setHash(java.lang.String) public void setHash(String hash) { this.hash = hash; } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#getDM() public DownloadManager getDownloadManager() { if (dm == null && hash != null) { try { GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); return gm.getDownloadManager(new HashWrapper(Base32.decode(hash))); } catch (Exception ignore) { } } return dm; } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#setDM(org.gudy.azureus2.core3.download.DownloadManager) public void setDownloadManager(DownloadManager _dm) { dm = _dm; if ( dm != null ){ setTorrent( dm.getTorrent()); setDisplayName(dm.getDisplayName()); } } public TOTorrent getTorrent() { return( torrent ); } public void setTorrent(TOTorrent _torrent) { torrent = _torrent; if ( torrent != null ){ try { hash = torrent.getHashWrapper().toBase32String(); } catch (Exception e) { hash = null; } } } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#getDisplayName() public String getDisplayName() { return displayName; } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#setDisplayName(java.lang.String) public void setDisplayName(String displayName) { this.displayName = displayName; } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#getDownloadInfo() public DownloadUrlInfo getDownloadInfo() { return downloadInfo; } // @see com.aelitis.azureus.ui.selectedcontent.ISelectedContent#setDownloadInfo(com.aelitis.azureus.ui.selectedcontent.SelectedContentDownloadInfo) public void setDownloadInfo(DownloadUrlInfo info) { this.downloadInfo = info; } } azureus-4.3.0.6/com/aelitis/azureus/ui/selectedcontent/SelectedContentListener.java0000644000175000017500000000176011044254630030003 0ustar adrianadrian/** * Created on May 6, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.selectedcontent; /** * @author TuxPaper * @created May 6, 2008 * */ public interface SelectedContentListener { public void currentlySelectedContentChanged( ISelectedContent[] currentContent, String viewID); } azureus-4.3.0.6/com/aelitis/azureus/ui/selectedcontent/DownloadUrlInfoContentNetwork.java0000644000175000017500000000251011131777306031166 0ustar adrianadrian/** * Created on Jan 9, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.selectedcontent; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo; /** * @author TuxPaper * @created Jan 9, 2009 * */ public class DownloadUrlInfoContentNetwork extends DownloadUrlInfo { private ContentNetwork cn; /** * @param url */ public DownloadUrlInfoContentNetwork(String url, ContentNetwork cn) { super(url); this.cn = cn; } public ContentNetwork getContentNetwork() { return cn; } public void setContentNetwork(ContentNetwork cn) { this.cn = cn; } } azureus-4.3.0.6/com/aelitis/azureus/ui/selectedcontent/DownloadUrlInfo.java0000644000175000017500000000447611131777020026267 0ustar adrianadrian/** * Created on Sep 12, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.selectedcontent; import java.util.Map; import org.gudy.azureus2.core3.util.LightHashMap; /** * @author TuxPaper * @created Sep 12, 2008 * */ public class DownloadUrlInfo { private String dlURL; private String referer; private Map requestProperties; private Map additionalProperties = null; /** * @param url */ public DownloadUrlInfo(String url) { setDownloadURL(url); } /** * @since 3.1.1.1 */ public String getDownloadURL() { return dlURL; } /** * @since 3.1.1.1 */ public void setDownloadURL(String dlURL) { this.dlURL = dlURL; } public void setReferer(String referer) { this.referer = referer; } public String getReferer() { return referer; } /** * @return * * @since 3.1.1.1 */ public Map getRequestProperties() { return requestProperties; } /** * @param requestProperties the requestProperties to set */ public void setRequestProperties(Map requestProperties) { this.requestProperties = requestProperties; } /** * @param additionalProperties the additionalProperties to set */ public void setAdditionalProperty(String key, Object value) { if (additionalProperties == null) { additionalProperties = new LightHashMap(1); } additionalProperties.put(key, value); } public void setAdditionalProperties(Map mapToCopy) { if (additionalProperties == null) { additionalProperties = new LightHashMap(1); } additionalProperties.putAll(mapToCopy); } /** * @return the additionalProperties */ public Map getAdditionalProperties() { return additionalProperties; } } azureus-4.3.0.6/com/aelitis/azureus/ui/Main.java0000644000175000017500000000321410623202472020706 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui; import java.lang.reflect.Constructor; /** * This is the main of all mains! * * @author TuxPaper * @created May 17, 2007 * */ public class Main { public static void main(String[] args) { // For now, fire off the old org.gudy.azureus2.ui.swt.Main class // // In the future, this class may do some logic to find out available // startup classes and pick one (like the uis one does) try { final Class startupClass = Class.forName("org.gudy.azureus2.ui.swt.Main"); final Constructor constructor = startupClass.getConstructor(new Class[] { String[].class }); constructor.newInstance(new Object[] { args }); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/console/0000755000175000017500000000000011310377630020624 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/console/MakeTorrent.java0000644000175000017500000001412010373051054023715 0ustar adrianadrian/* * Created on May 27th 2004 * Created by Olivier Chalouhi * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.console; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.security.*; /** * @author Olivier * */ public class MakeTorrent implements TOTorrentProgressListener { private boolean verbose; private static final String[] validKeys = {"comment","announce-list","target","force_piece_size_pow2","verbose"}; public void reportCurrentTask(String task_description) { if(verbose) { System.out.println(task_description); } } public void reportProgress(int percent_complete) { if(verbose) { System.out.print("\r" + percent_complete + "% "); } } public MakeTorrent(String file,URL url,Map parameters) { File fSrc = new File(file); String torrentName = (String) parameters.get("target"); if(torrentName == null) torrentName = file + ".torrent"; File fDst = new File(torrentName); if(parameters.get("verbose") != null) verbose = true; TOTorrent torrent = null; String pieceSizeStr = (String) parameters.get("force_piece_size_pow2"); if(pieceSizeStr != null) { try { long pieceSize = 1l << Integer.parseInt(pieceSizeStr); TOTorrentCreator creator = TOTorrentFactory.createFromFileOrDirWithFixedPieceLength(fSrc,url,pieceSize); creator.addListener( this ); torrent = creator.create(); }catch(Exception e) { Debug.printStackTrace( e ); return; } } else { try { TOTorrentCreator creator = TOTorrentFactory.createFromFileOrDirWithComputedPieceLength(fSrc,url); creator.addListener( this ); torrent = creator.create(); } catch(Exception e) { Debug.printStackTrace( e ); return; } } String comment = (String) parameters.get("comment"); if(comment != null) { torrent.setComment(comment); } String announceList = (String) parameters.get("announce-list"); if(announceList != null) { StringTokenizer st = new StringTokenizer(announceList,"|"); List list = new ArrayList(); List urls = new ArrayList(); while(st.hasMoreTokens()) { String _url = st.nextToken(); urls.add(_url); } list.add(urls); torrent.setAdditionalListProperty("announce-list",list); } try { torrent.serialiseToBEncodedFile(fDst); } catch(Exception e) { Debug.printStackTrace( e ); } } public static void main(String args[]) { if(args.length < 2) { usage(); SESecurityManager.exitVM(0); } Map parameters = new HashMap(); for(int i = 2 ; i < args.length ; i++) { boolean ok = parseParameter(args[i],parameters); if(!ok) SESecurityManager.exitVM(-1); } File f = new File(args[1]); if(!f.exists()) { System.out.println(args[1] + " is not a valid file / directory"); SESecurityManager.exitVM(-1); } URL url = null; try { url = new URL(args[0]); } catch(Exception e) { System.out.println(args[0] + " is not a valid url"); SESecurityManager.exitVM(-1); } new MakeTorrent(args[1],url,parameters); } public static void usage() { System.out.println("Usage :"); System.out.println("MakeTorrent [options]"); System.out.println("Options :"); System.out.println("--comment= Adds a comment to the torrent"); System.out.println("--force_piece_size_pow2= Specifies the piece size to use"); System.out.println("--target= Specifies a target torrent file"); System.out.println("--verbose Verbose"); System.out.println("--announce-list=url1[|url2|...] Use a list of trackers"); } public static boolean parseParameter(String parameter,Map parameters) { if(parameter == null) return false; if(parameter.equalsIgnoreCase("--v") || parameter.equalsIgnoreCase("--verbose")) { parameters.put("verbose",new Integer(1)); } if(parameter.startsWith("--")) { try { StringTokenizer st = new StringTokenizer(parameter.substring(2),"="); String key = st.nextToken(); String value = ""; String sep = ""; while(st.hasMoreTokens()) { value += sep + st.nextElement(); sep = "="; } boolean valid = false; for(int i = 0 ; i < validKeys.length ;i++) { if(validKeys[i].equalsIgnoreCase(key)) { valid = true; break; } } if(!valid) { System.out.println("Invalid parameter : " + key); return false; } parameters.put(key,value); return true; } catch(Exception e) { System.out.println("Cannot parse " + parameter); return false; } } System.out.println("Cannot parse " + parameter); return false; } } azureus-4.3.0.6/com/aelitis/azureus/ui/images/0000755000175000017500000000000011310377556020436 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/images/bullet_arrow_right.png0000644000175000017500000000032411054700060025022 0ustar adrianadrianPNG  IHDRjOesRGBbKGD̿ pHYs  tIME9( K5hXIDATMR 0 n(   - $v $]EaIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/torrent_up-disabled.png0000644000175000017500000000111710753237254025112 0ustar adrianadrianPNG  IHDRaIDATxڭN@c+?#G^p")6G!a I% 3s/&VXj69ݫ3?gc29f戙CfIfQ߿5L&]fN8B4 1RJf3MDOGGGxFy( 03:&ָsDt||@m;YޠriPJBy'ʀ8Z̐RRJj5!PJŕ3GBc@D0ƠVpqqh5 h`6 ܫ;FX.}J)a,MO"/n1UK-Z@zQju(0khBdYksbV Mja:,yey:<σyr!IixdtssuPJA)Ua !0p}}튢 (_]]uAEp9tzz~.//RZ1sX%H<>DKb"IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tc_bar_end.png0000644000175000017500000000523611153704420023217 0ustar adrianadrianPNG  IHDR h EiCCPICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧ5IDATcoLYRN1IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_lighter_mid.png0000644000175000017500000000015611042177176025026 0ustar adrianadrianPNG  IHDRW5IDATxu @0ZeȠz <3sg'JZI-?Po>.i~IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/qual_hd.png0000644000175000017500000000135011073604052022546 0ustar adrianadrianPNG  IHDR \sBIT|d pHYs  ~tEXtCreation Time10/9/08^[tEXtSoftwareAdobe Fireworks CS3FAIDAT8Mh\U}3C&!4 JTkԅM] 6nIpS;)ƅ(]JA)R\rӢFHg2.5yir99{:(*Π-MQ_yy;1yſ]~oIB !?⛲#|>5V͏k}nbW)ܗ[D3X$0]I7 qr7J '5+ VXI/M]0}ghޝϮV|G1dgIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/entry_frog.png0000644000175000017500000000076311070327036023317 0ustar adrianadrianPNG  IHDR;mGtEXtSoftwareAdobe ImageReadyqe<IDATxڴS;KPA. H\ :U" BHŹ q&s-%1iw<0O2]{{s1Eϙ9EDHpJϓ~D #vYHsLfYm@T} &(9хcArMq!htd*| l<YpI~.tJtRCMcoΐ ib5WMA=b"B͔@` c&c`,3,)C.oEbnU CIjH >%0#sZj%։, }Bddž:Lbiˇmb uc_#K瓥dIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/logo-150.png0000644000175000017500000001171611223317134022402 0ustar adrianadrianPNG  IHDR(sRGBIDATxyTյߩDIL#1FAĀ*A 1 8 3188 18$!)+2tu /<58@[ EtWuWwp~kꮪu={}9Wx5 &8YH 9kk(XBm*n~s|wFc~Ǡ; \)0ax]gMMzKbS80(F]b90bW8Q339PyS6CtӪ?v6hCk8sBVq|Z92yDh2d0 b4M)uڹ˄k<.uA7if XYtPD->#Ό:+05N!(3605 {S*/Z0(dEy3%0haj^ RsKM_ҕY S;msq L05'&i:aj^4U+S]֢dcx~9w[Ðś8Q&p89e=_署hzSZ?9Nbl>njmx/F`0.76MM>@blҽ SO,4i`WzһLhlT|ң s >mÀ$uo&4eHK&)[#mU5|A48m-S%B'4$t@پJcU0}{P@ʕe&_xB{]&:K, /-0 Z-L mcouQ-ߢ0^3A5O0fn=Lɫ=0ȯFIR~O6S{❜}zy ɍQ2aJvv#d߹8Sr:ҳSkTaJN<;*|Ô0쏘zN-0o{zWly).+䛏='(PJSJbz;gPNK68GZ^e 2:}2p8w_l^u?_|#:XxL[u֧j]ˎus&Ϋ_jY>~%WetCڼbx$nI"*+Wq.mx[,f*O_aW"n0d#gVA:OoJ Tpqs};hWLp}d`:wLLVEx7<\z(ߵIFgO7.A>PjMz^7xk?X0:FX#x߷˨,έ }ꚢ8dH(%J^T8s}ßbv2I-o^[tRu Tv`=L8H ԝ`ƺ'ێyF!ڢTK,0\rJ9's80Yu2s7vI65 SY{"逤jZH2}fԕP `ֆy1]Nf÷,L/H.&]Ґ:[1i=keҫ7:y̶rXR5diSu"0}Ñ*_fMz1~鮿t_;D݂X9E'Ob9c)O-lMq: Ig6.pg1Rˣ`әweuTZvECk]5lgZַB1B呠a |gd0u{(oBs ]?(n'XwuR 9c6+FNҮw A: ?t<9$znY&u4ܣ# 3Ӂ*F["[Y׀w0YW.qAʬxԵqN#LLDB.[/F pź$Buuࡊv ȝELP"QaGye]nmf ܚA:PєV08M*遭y=;h W}űP_#$6'QQ3+QAꃘ%i{pnCHgvsoT0@w߻NsHad5!xPj2=K:Ͻ(5<L 7:1໱/>`+ 8Z'h`ӐX.;G$;FS?~Q$}kS#bڧ׽T.ʋDV10镽ye-`+ky oz``1Ҿm "9pgfIR4:$QmPcEg7[&VGj Y9ShMzWMLM-+#kdfN\t8f״`NrkYUL[?lk :e=Hs::U8 }xGa. #0սԵ5RLg)-7Klyvꒋ1e^0yM7 q t' qwHKۋnU2ez#T 3 Q3u™STCN9dbaV) _vM™YGb YI΂cιMPxLpYZ,*3塬LD2!,4q]yPO]Έr(m ெ] g HioP.m-x +E2ÙsKRtKahs̱ c}R9nR3J%?q|+LCkk´]RI`F$-q 5DSlo {i[HQI쭜3،p!ؗqSyx^o90Y6t5> [9.P ]8(95csrkxv}b[9D´.<WPk#XDg:ItTxx8<QtX5-`_#Iwɫv_q9w`l`JngWP~}9'g 6ɜ{vVM ~P` ?v!64jJ*סl7󓘛m{_^H^w}mI0k12%.ɫn8wm h+1jX&葵K-xCIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/torrent_up.png0000644000175000017500000000115610753237254023350 0ustar adrianadrianPNG  IHDRa5IDATxڭK#QƿM,yȉFB*L:Õi.tBlRXXn!N#(Ym7˝Vw 301?ѨIMEA"H{{]h!٫ju c$ PDfy76wnnn&1qs2p:$ּ\\\t^onnփ HAPAQ i|ݽ.kphX#IJ%F]kl)`R0D}$14 @ex!,GrZk,,,(EEEcy$<n4XTFMӐR ϰF3 cTUDj(b0Ȳ{{;<͝:E@ΉםZCk=VJa<,K=ʧkmokkE8􄻻;DQ4t΅{{{>I3IEQD$^w?0w,;"FIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/wizard_header_bg.png0000644000175000017500000000035711073610034024414 0ustar adrianadrianPNG  IHDR*r~1|sBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time10/10/08F|GIDAT}1 P»975*(]J%eY]T TJ"nqGJw 1e7KYoT2OhIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_lighter_right-over.png0000644000175000017500000000022511042177150026330 0ustar adrianadrianPNG  IHDR\IDATxc@(dp1Y{O߿~a2Ϳ CC*G~h޽;人z;TjIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_lighter_right.png0000644000175000017500000000023211042177124025356 0ustar adrianadrianPNG  IHDRaIDATxc@(d !Kk/? b'߿,%_h?F$d_3Ǐ >O è;]IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/device.png0000644000175000017500000000071111160071574022374 0ustar adrianadrianPNG  IHDR4.tEXtSoftwareAdobe ImageReadyqe<kIDATxVKn0  Aޠn8D0=c%z Vu/nMfFH S#`Ll?OZi`İJV"y3BE kG/Dzm[Q׵;=h i 󤔂r64Qu@!ieϧ?WO/!Q&F$*يYLp)k`4D]W13a\=`LU^$ƵDs'2"Bs+"Io {| @)i \g0"c |=s2da x9rca8&qnvlY)uQ*y3-c\=MӄWcv1ec1.߲_ $=IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_right_scroll.png0000644000175000017500000000052311042177160025221 0ustar adrianadrianPNG  IHDR(aIDATx;JCA,%d q ف">DrA U7X)6VjQKHs-BH|Ź|w H$y}{U&z~){ ! f*V']^˫f$afyMN89HHQk!'cfӳe:=H"_ǹY {ᅪ yD;!}Er3K67QO䂤zw^9N({I( vv>GI9}[@̫^6;}sDb6ո$mqIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_lighter_left-over.png0000644000175000017500000000023411042177116026147 0ustar adrianadrianPNG  IHDRcIDATxՑK =^IbTC|6Ƅy/u19EZkX͈smp7cE慛Z{٫j ~$ՒU˴qh6N-;IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/icon_trash_matte.png0000644000175000017500000002015311100002152024436 0ustar adrianadrianPNG  IHDRAa[ssBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtXML:com.adobe.xmp Adobe Fireworks CS3 2008-10-22T21:25:04Z 2008-10-22T21:25:14Z image/png X3IDATxݜYdygKYIk6C";c#d(GC^aI`KI8ql'@ ?N$[eydHԐٻgުmHQk{o;r&']qcS=yJށ(1 ˜?׬mUF-ivl"t:hZiFJ+QF=^pL$xf2㝣i#"EIbllE/GA<|c?ԛ_3wz[O|xo?h}{(qAlFn( t@hh4bFVh(PJ(0Jx"ɤ "#'ys`2 dd0F!s.ژ _ԩwQ>CH%OwqFw':<+dY!t?[Yrf|y7#aHdB6]TR;HzM0DdŒ[¥5ZtŲ$/,c y$_Qqmm/0o6n\׭vťwhQe6Q*ןo{Qc_SK/EEQ2qeV:W_?Lyԃ?OU [Wv;Zh#P\:wvKayef ,A/V~(JP)V(@K'ܥT6qWx>KGEA$Ypw..e^0҈#:urSD% 㝃<)hڝvʭM/VE܈k-1yDw9v*gWVwc'$%LE1ݲ̙L%t"h(an4tWTt 5AT"}u-cZ(Qhkje(4VyPEAt zt(PjMpo{| ֠gO fVeoYwZWjsLjv}Q F*qFc;'?6ۢnM!DQ ,9Ntܖ5CT='s'Pf_P)8綊"_s̾ Һܛ9o:as\Yl~ _p}H;۽F*:aֿ_ؽs̾ \R5Q.uLT&~X:A\X=t?_5֢ReIQ UFax~2mvuc?j7" ,rS~s76~Ε;2 _=83J){ MY ԢvM J_bA\YxBj{{@4l4deY`h\m͔OH]3!8w's\&kFCN8;P)4l6QJ ,b,$*YLģy?om=ECU]U'E8qx`jh,..@l-غVzo zŋz'0729(K"khD1֚4MQJ!EQ001q㝣шh.IU~BUܪpJLr؜嗾i9jC,Pym1eY2LF#$A  FAǴ[-D0j!p ̧E܋~Ploi ( A@Y ,˺MHc Y2U Ukwe<#A=X^X`{k^ӧOsI<نO{8)gQ@L&[YE~ Yyc8'vڵkhy9s c,CkM$Es4MgAkMQUaT=Qa9? UQ١|7 N&}wUe6$a0'N-pYUPc A̸@)5FYźJu ?YwkBEyaN8A笭N2Fe0AOTEkj}6660`X[UNX,5?>S7ڵUm]VeAeYF$}.'N 2n޼^q-IHӔx<5I&IU;*՚8 IJ3Lצܗ%"lh._~WU돪ߋbd4"'kkkZ-x8FD looxѺ*FA6$ yNZKYVqa0e2e E{Ƞ 6 |g['JpE+ 1,..Xy20q,..2u9Y}beY277GEc(,˘L&sss3KׯWdZ .AT"y=w$xd$aHI/=0$Rp*3gE~n8i6$IB$dYFQUH}ǧQDD s0jqumxZBk1JS,S20L_r ,s4C[-Ξ=˹sPJjÐ8G`4Q"Bբl6vh@e3*׸1;U5T`W{JGZ88/9~m.е)tXZZ"Of^8pZ|!nk-v{ u:gj4 J)N8ANjVϣ* ւ(,C^XXցO/jpjln|ݠ%DQQܠ,KΞ=Kru$ZKEɓ'x";;;[-1F#!J):YڅXFFͪ~nEPTd;qw,+wX^$I3Ey8Z-^ynܸk#k4HӧOŋ$Ix20g6IS6VјD9F_?";gN_8 K˝ǟ|_lj#T85;mڝKK8ElôKaieN ш$iJex:sstmZve_9lPg}Ӵms~~8 Jk8zSoW gy'>(+'ޡ*Q OSnVt:Z-!EYt[置SF0$nƳ0њ,Y}8Ĉ!Z k}M`bL( KC {AMh]-+6upev1OKdL&c!"3}󋋟]~>nN#"ᡋ;."Tؠh6,xZӍVo:/'تiӠU M .w(8 G+I2k9]vYȝ[͕ew]vn'O}hI/4 8WxcA/.YUzBW={JpSU@k3HR* C;4Ss|[Dq,Κ|O坣 3Ύz2yGΜ|QDx;iܺ n)U٭+G8,(wKs#A}~k8vyietuxQDCȱ8a:MQ֊0 TdbMħN>#O?lmcL%{Ai1˫G$x%⋢,GEQ$Y_݌X/'|8]G=7VH)ep>ɌkchkUEyݲTKL"/th|k&idsNUw(*`A6Z6hm|"nƪh4<QIZ+~SJܝ5V@Do )ZkoVp+眒*TJ K%*^VJVRJcx ڠtLJ]Q5ҡ a TNuZ@ DsϝT h5뀞 ЕlWLh7&Y(Tq;JWn]~3Tc;> u6p'gs[ OWMA8A+]u~ @+"CPSW_)?s` d? RsB- Sޗ᏾F)0oR),`@jV #|AUTcW7Bhg;7lAomQ9``ʹ-mj:F49 >zR) LAXۼRo=Ýth1 * *"@pؤ~QcON pHeF[DDf#; 7X{<-IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb_expand.png0000644000175000017500000000034411100225700023064 0ustar adrianadrianPNG  IHDRsRGBIDATl6URս  0(@g   '>d(    - !Ҹ $ȧq)/cIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/notification_icon.png0000644000175000017500000000177111124350556024642 0ustar adrianadrianPNG  IHDRh1?sBIT|d pHYs B4tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time12/5/08@RIDAT8uk$E?U=32f4JfD(DPe (Ȳ=xAD<"+OdA]E7&Bftw{jgV cmllk6JS?H{`^P|\:xU'(?2  ...P(ptt^GѐJFӑL&Q4L*&4_U6MV5F? ܝ* i,q_M \oW >eYU,xBIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/icon-AzureusProduct-24x24.png0000644000175000017500000000236010535151162025642 0ustar adrianadrianPNG  IHDRw=IDATxڽu;gv'yzDj*uYyWyfBia!D3 A*"@)J@|}WSz]DO ܱ`8Q &%=ԗ)/\n\4˲\B]=sO\F#< &Sj8nH TU%28KpCtB[s#1Z)юS4ZZZ5*d3ӻhj_/₡o{{Gh >yuJ01NX.@ZZyA\G|`X}X7V+};ST b-ȗ PiA1Ɗk.üع<Ft>fƽrj6:VsIkK`0c 8<4ς{~ũ{!D_G1]S\z20"`&L2_:w1=p§лk ę%'>&1 \PLݞ%_@I$A=:,irHrR˽)ϩQ?`۫_ OlYk.OiINfF >H G!0ljĽ } $U쳁pg?E#`@:!+Rv!emC;B!foC "|R瓙e]L[ &̛,|⃠ yy/Z2$k<)>ׇ5CVji}'V/JVXS |~nmX4G{iL WE{zǵ <$>&CfhBa]\Sֆp+i\B5U=cIW12Հm P A6A*QlƀH%+&<,5[9t=dtܜߕ돡]!d`' 4XdLjmZmqJ>`"/G&)i;zbu%*JZu$I"g}SB'[ C:#/x=DB~ w,`qe-LVB* ܢ71~eFQCdFvt?* ̾vIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/entry_buddy_req.png0000644000175000017500000000071111042177176024340 0ustar adrianadrianPNG  IHDRaIDATxŒjQ44+*AWp7YI5DUmԐ*z35fw;>kOj=}Ӷ]η\ηIfNmC$M׌kLdvl$DfoFm:gHHP:t'v"3aL I ۓ~SfΛY/ã(e?`~?{b>YlRۂ$_e^ H=HIj Dޡ46%˯lޤ. "F}Q$m0)B԰Xr@DD?bR  5(7tn&qRr;! F  !׃[MIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_left-over.png0000644000175000017500000000023711042177132024432 0ustar adrianadrianPNG  IHDR{GfIDATxα 0E58BưT\ 8I@pu;K7yI ``f0Ny$E$ x9(“ LzI<]Ѵ@u_ Qm3 IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_left.png0000644000175000017500000000024611042177110023455 0ustar adrianadrianPNG  IHDR{GmIDATxŐ@PCJP_*QZd"Tr+yDؙ3+`4n&"$HE<>x+#O>L$%'D m[ @~8m_whIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/ranking_bars.png0000644000175000017500000000034211070320414023563 0ustar adrianadrianPNG  IHDRP ]:!gAMA7tEXtSoftwareAdobe ImageReadyqe<tIDATxbLI/$$ ($PYUH 159aDaPh4)4 @ @ FB@H!hRh4)4|PW8OIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/blueline.png0000644000175000017500000000015510535151164022735 0ustar adrianadrianPNG  IHDR PLTEjl!IDATx°;oMi' <1vIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/help-over.png0000644000175000017500000000071611042177162023042 0ustar adrianadrianPNG  IHDRaIDATxڭSJA="'9 \B*?a!UH'!`4JR B'Hm ?pW(Q ,ڜ]A}a޼yk'B-9 ;yU@q Jka<r1[2l$os`[RJpwRJ7cLJ<]ki3vORpxŤye*a[ۍFZzcuvO>W@!Ǣ18ߒe+QJIrp4VNHbyiZvEѺ^?1Ï9!$^,6l|:N-?lRJ1vJM^/GZIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/grayhline.png0000644000175000017500000000026710535151164023124 0ustar adrianadrianPNG  IHDR ,tEXtCreation TimeTue 13 Jun 2006 16:12:54 +0900BtIME  q pHYs  d_gAMA aIDATc;i4ZٍIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/lastsearch.gif0000644000175000017500000000023711021715204023241 0ustar adrianadrianGIF89aԿ!,@LХIEh`X&L[ 'f&IفF˨'`H, $"kպ;M w8jDM#¦`";azureus-4.3.0.6/com/aelitis/azureus/ui/images/icon-Globe-24x24.png0000644000175000017500000000107710535151162023677 0ustar adrianadrianPNG  IHDRJ~sgAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT8G$`!CF1b%F2H#IF2aVtk.fdDtb%k$i$vM|xo^l4RVٜE"!'~p3 0tyɿ ],w">/d/qCA>ֈD#Q{ع3/q쉧y9[ ~&8mTNP˲ѱ svVǶc3#r EJB$zr T1 Zygb~IT.o-W!bziq؀\AkSSjs3s}_W* q+Px;\[]5&oͶu?JNHTu)[Q)|>jX̅tgIxIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/torrent_down-disabled.png0000644000175000017500000000114710753237254025440 0ustar adrianadrianPNG  IHDRa.IDATxڭJ#aovw.F]dܻХ;b|"7 .\!lcd6pW3EAA9,sq||\+˲ UADru8ӝ/ƘN Ceq}}m]noo~899i{i$Z!"(񑋋kccvpzzZmmmN`|h$IȲ+koZ^/l C1p:2N^PqF#TK˲d4Q14uVE8KU3Tcjy籿OU8 ".!(93iS$A===5WVVxyy,K00L !l t0Xk- *Ʉ8q]8&EQUCڪf0x??J_b H&R)iZ!HR~V(R;;;S@i:fzzFA4%RTm/{u]EQzm۶鎱1Rm'VWW)$ x~~Ʋnj|uarzMj6WWWܐdpu=U˲zv! LLL033;<<<>@")eU\i6F٤3 2r!r\X.p˲H&c&]~jY1]X__R#ib}}}id2u]c8 uf}gmm0wwwGP qzz₭-4Mc``UU;ܷ{yxnoo1 !( yH!HMuI1\eo RGCpP4>>>DUNsjV+~+h28v @V#%IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/device_bel_logo.png0000644000175000017500000000401611256043612024236 0ustar adrianadrianPNG  IHDRz/*tEXtSoftwareAdobe ImageReadyqe<IDATxXwTWH$, 0TT:GʼnZ ʶ,ATZ[iU+" Bʐ/}{/f)J[["+QnczڇHKKKtLܥ :V|4G'2胩>^zZȣG6l(/722dY*@__v8wwdMM08**|ܸJ'&411c[[ Ea*toxxhof>>:xo0adӰӧϊ{_BSdk K"yzmt~^74deeII HIlliVsk^rjW#"jKJ|7771 ܜr&>>!0(^aj=z|C1¾wo=:Zfp8C ֐F}~~z VJCeXhy<},`T0R [/883*++8}̳gLjzBe˖?. B:\ݯ^*,|ک wwK_SO*)K4ۡJJJ+gB[[HkZ[Y!@_| ɓPB!7#hٌkiO&UUGS/_qDftfP) [ (Yhbe 7#X'! qqѝ2ĉ=z irr'c||V+In.ͯAi){{OE.^523i.;piqu ?A4bqP ܸ1HUx{ /_JͮU07]pAԺ~>vʺr1`*rnAr}8 ![v!T#y[.#JD'JRz٠&D6ƅH[ݝqE%W \:@ …tT(t4"5\mo}2i֭یldmmե) A]KnC+e@Jlaƌ/RihX$<&\6EE"-H^> HC ,(*-y*  D[R&uT7 OܢVy<3"5O:)dSmMIٯTߛd.q1NN |;vfYۗ&ԩSv999yymAKTscY>>11yw3/<4xCP`nnk?ÇE89Jr2T_a <9s*@\i߾h3~M88"knnjqI:\ڨeffvv4;>rԇU 9yoe DRWWGiipKgV"`$qJ!LlΜ1 )@x/fuIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/30px-itunes.png0000644000175000017500000000444711157162346023252 0ustar adrianadrianPNG  IHDR$DSsRGBIDATXYl\w}ƞx[YIBp'TRRJK M EmPU}( BJY MIB!1㉷/ޙ{MkCշ~ґw>:] )rG!$90V{_o+|I ms燫bhUP-rTϗWZI,[%P8@ PHpÍڅ]KW77GA^98ʱrLD&_@5,Kl12^!)+T %\åNڎY]Y|7[.oX94EXZR^M]u슎eئ 0ЎO=[7^>| b!G60L`0@>DUDR}8$ ` 8"zXw}r@ㅱJ#T0-$5pj""ӥX6)u\G bk|~zU_9j#fSsL*aA($A U[ancޤtP[_ Q { ŧC] oN8D,6Գlyֺ-U4x|gˊ@'݃V~.i!(hXƉ)Y $_Iln1Kѳ p^WI^orQo]r+&?t?>j +"w?e7,&Uaj* ̓h$4+u' b:P$4騑h ՎOT A*nh]yn[X7HɴH劌'd(Xz57}f޼5RӀĝNU,К/S_gEo^սP8wmO@SBðMLC y`=3!b.`9b8vMԸ'˷M*ZeɂEȐqtJ4ڧPptTemɎ_PO|伺glyȉc&\7[ǂ1[ɥTgrgܰn= X6(!H2U )FIWPIJx<&Κ^CkPJ:Lr9]T(Cfթw>ͷoc^8G%xk (F|4.pwFScѲإ5'+}2'ޭ$>LJ&kBu^JuO űv˽ <{eik0føNBΠPֱysu_o?Mrء f?78L}6t ^5mpSR[K,t&uT҆vlK(;KMsENd\#FTlTxjb6@2P D^k;:lXdq rLvUQNfu:DD[D7lT5;I^'xa|sGϟ}ŝ*sӣjuWF;$ezsKYq^ ~I!Q-'7yQ/[o1+j|{ʉSUk.d 6k.gQ#!/A$8H.+T氦+?{-wȅ,P W(O%9|oׯv Z}~]t6,$Fp-$EE1]CS$=1A_߱;^;ovb>0 }0g.2񚖆D0ˊZiB~x(9Ngi?k:4ۃ4-*xʝ7g+7pF˿2UIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb_menu.png0000644000175000017500000000033111100225700022545 0ustar adrianadrianPNG  IHDRsRGBIDAT-+ QW|tbq &un,,(­ \9/ZN_q`BA{OB9TMص$+IZێ:f_3L ^7[nˎEQsjGnBJIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tc_bar_0.png0000644000175000017500000000016411153704420022603 0ustar adrianadrianPNG  IHDR 絓sRGB.IDATcop&/2f``WtuIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/separator.gif0000644000175000017500000000014511004306436023112 0ustar adrianadrianGIF89a! ,PIES= (ffJ;azureus-4.3.0.6/com/aelitis/azureus/ui/images/icon_rss.png0000644000175000017500000000117711070320414022751 0ustar adrianadrianPNG  IHDRH-sBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time9/25/082LIDAT(m=Ha_7L-̴/, *xKjjiC-5C`!5$TАt!/v3^7%|xs<La>3LEmpl?Y}K7C 1p%Uh9ЏrKKBjV~Һۊj;h bOy»|yV}5[I r͓VKV7].puMj ٪4)/"ц~_IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/entry_buddy_new.png0000644000175000017500000000124511042177172024341 0ustar adrianadrianPNG  IHDRalIDATxڕKHQr:#:c2. I$2JZ `4rU:H4ȼz935};h4#A ι`?Jd*-eB=9)%Jow)twI̼HD`fl̼hkm݌9~) fv8iڝnó=`f?Kd"ɤë|>h<G,d_D6-3S?ɤ1; a:r$#p|[4~*e׈0?7"P9dFo 6 {Vv *"z҄Khy$$A0< _}wBQb10\)iLކT @[Uv # +UQ( noك$ XMVh7P(Oql")RRTPr^Q-\4W;"y1CA3m3;0P)6: >'dl]>//e6*X `mu1RJQ :&nn&1,,,8 @fqR sRC^p\HbPXZҺz!-DQ` &?p8)+%i~y w9Kw21qhTO֋H!P1-J|k䀢+ZE`Z>^#H=rݻnt:~zu8i\ |1Ȇ| ;nI@wIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/play_down.png0000644000175000017500000000172511073423036023541 0ustar adrianadrianPNG  IHDRvbKGD pHYs  ~tIME #)˷KbIDATxŗK+W?7̏8)> %D4JH@ +7U#"Z+.ۂkXWqx>̯ۅ!4 ;ܹw>{ι3M1 N%5q9$6`c yss[8>>VDNOr_G`J@& R>T*4M2 +++LLLpqqS&^?`x_JluuqpuR"6`qlu]FFFX[[#Ͽvp@JX\\DA,CyضeYx( G /,,܆ @ebYVl6[@(xvvΉmlTBb1|_@yloo3==./o_ nC0[y\Zahhk gHyB)%XB@Z%#WYd *H$(@_Q!IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/ic_delete.png0000644000175000017500000000154711073142772023471 0ustar adrianadrianPNG  IHDR1_sBIT|d pHYs  ~tEXtCreation Time10/8/08dG9>tEXtSoftwareAdobe Fireworks CS3FIDAT8͋SWܯ|unfԺPK2ӂAŝ.vY"JЎRZ_P nĕġN:g2I&dn9tћ]<1߲MwywuqRy$I07¶k_j5RsN^RR;9Bb! xqrwkxw-""f)I@^vR(q4zH(Fcm\p?=5JIպW@#Vگd/8pp$Y@ `h1 c"`iZg(4MLVuUpPVjau;RJ{UAr؞jaD77 R/R~h4>xx Z<~+nAp'h^0 k0 M ӧqsR|n<߿9+Iͷw)@ke,y%@|y϶fy9;d=uI[B+fJo Ov;[3ALwLԁ^*H@3y(x0!+󿦃qhB_7r$nozirv~%G.6ҽ9LJIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/view_l_m_down.png0000644000175000017500000000025311116360412024364 0ustar adrianadrianPNG  IHDR;sRGBeIDATӝ1 q?LAW59(j7Ib<#Xk ֚ "~lWjR !LH)}i^'~9J6,IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/ic_list_big.png0000644000175000017500000000024711116360412024006 0ustar adrianadrianPNG  IHDR v4AsRGBaIDAT(c π֭[@$`7$i޹xvvv(Ns(ׯSgeUm"){Q IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/sec_r_r_down.png0000644000175000017500000000071411073142772024212 0ustar adrianadrianPNG  IHDR GIDATxu=kAbγBMR{igmk؉ `c 5X8<یűM8}晇1T:3coϪ**J.0&V-w8AU9s&lpy_~DRJcPUsNR(`EU[>M7A!s(x=Z1sk- Xc {S՚@Ui *4 +=}UTk>=">猈-Rj)%RJ7 [P<~16o&S1&TͦB ł=0fQuTm!X) )Y<:yn<{xO{+}R_*IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/sec_r_r.png0000644000175000017500000000046111073142772023162 0ustar adrianadrianPNG  IHDR{IDATxu1KP<$TA orԩs.bK2R+I4y:֤/knzjOp{ݛ$NDI6w(?<\N|簳l2:q*):QV2`ER:NTUl骝ltz\n^=/ji)Nкsyf)"L_!GV_bO+[[c0Iztg a4IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/view_r_m_down.png0000644000175000017500000000026211116360412024372 0ustar adrianadrianPNG  IHDR;sRGBlIDATӥA Я/]zj7PPDm&̓Ypn9JǑ`AZ#H)IsFH)!B/qĶ3wIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/sec_l_r_down.png0000644000175000017500000000046311073142772024205 0ustar adrianadrianPNG  IHDR48IDATx}In0 Eh n#GźW`X0$)R(}sR<'OD^2$13ܜ@OW2w̨+fJ);ݙiy<13J)dn9iBDPUyER 2^dnI3@ZeM#ptشL2sG 23Z;8|h, 8Fv#"v[ \.}]dƢtY }(IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/view_sep.png0000644000175000017500000000015411116360412023355 0ustar adrianadrianPNG  IHDRDsRGB&IDATcǏW LLL L '>bb`y >h"ާIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/search_bg_lft.png0000644000175000017500000000046411073142772024333 0ustar adrianadrianPNG  IHDR 5^IDATx}KNQEOU?xMq8t.j4Q4]N[D+snJjJC8){xi%w~Ƭ}N yrRs2 %.Ra:Q*T"*B ,K)={8F U!"T dS|@*SYl;FwK`tG~+c:K3PVՊWfE۶ۂ;ijxo鵹H(acyH/AϏO ksbIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/search_bg_mid_small.png0000644000175000017500000000022111070605336025473 0ustar adrianadrianPNG  IHDR;̗sRGBKIDATc0qJeRSkp֭ ߿ϟLLLL L L dg`'v33}'6IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/ic_device.png0000644000175000017500000000102211160072146023444 0ustar adrianadrianPNG  IHDRNFsRGBIDAT8˵=kTQd*ZXȊMHR6V&HjǍŽw.x=sy3Òq8LO:`&"b)fpTCx$d&Nxd86B"mɯ^Lɨh65^J@+u %t/3VA~m+5a?߶]]Kԛ/.&;seM,wnx߄6nvv:E۶M 1EU! " 5T1:R _ED@$2L"26f!mf~|~|{3:1p605z" $Kj,FڶŪ uEU׉P"Ze4r7`t ,ۆ`G{$?h'IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/ic_start.png0000644000175000017500000000170511073142772023360 0ustar adrianadrianPNG  IHDR]sBIT|d pHYs  ~tEXtCreation Time10/8/08dG9>tEXtSoftwareAdobe Fireworks CS3FIDAT8}KoU3g>VqhRZi@rb`uU?@T?+,G SPZDriN3=:e9|7Gh0 @(n (R_9"9o}*JQtokAg81' dI`B<%.ZH ҀK@~ض%)uIKj-ҰpJ@a|UIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/ic_start_disabled.png0000644000175000017500000000127011073142772025204 0ustar adrianadrianPNG  IHDRtsBIT|d pHYs  ~tEXtCreation Time10/8/08dG9>tEXtSoftwareAdobe Fireworks CS3FIDAT(OkQϼ7C5kZpa ЅBiH ؍o, "AB5K4D$#E.L?AWB ۬D\8%13y.B5 -z=gsRFuc jbIBE@~lưXZx<B@`=LNTyT-3k5UU SzKwu]V{ W5Yi|Qp6kOMN%I5U hZFxH"&b3CHPiSJtEXtSoftwareAdobe Fireworks CS3FIDAT(mNSQ9%mi8u@`o6FhI\ i1ca:8l\tO,vbAsb}s{?0Dp &/R NN:V@Dfs4 j|b<^0D#PIǣV0aafMm; f.jqzvv"ٱefm,]k-. DT4@ɬ̛\E#)!1W^-Yk\k5Ԙ癈ZMGo.rWBGusr6)R !U?})ODWH&2Ot'%W\)Sv*W4J&H&U#m8U2!v$T)+$րIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/sec_sep.png0000644000175000017500000000031511073142772023165 0ustar adrianadrianPNG  IHDRDsBIT|d pHYs  ~tEXtCreation Time10/8/08dG9>tEXtSoftwareAdobe Fireworks CS3F&IDATc LLL L '>bb`y >]IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/download_disabled.png0000644000175000017500000000155711073142772025213 0ustar adrianadrianPNG  IHDR!bKGD pHYs  ~tIME ,(yIDATx͗K@?3Զ&\w V=?JJ6"^$V/^<z*ֺI$MS$:Ä7DgdBn Dqq `~joxwwmrr+ 1 HjuqAk_BJ)677Q\p,!B gq IÅ5Qe!TQۍ⍢0 Zb6ʊ, C @JY 2 l"y& QrFYemA%x?7ބ8֚0SR4@$!`vvn 3}hWJqppA~g!kK)i6ضWI?l=3J]$}jH=5VJPױmvO6bq v}.Ng `oo/U|/&TFAۥ][u >>RJ(je@iVqΘö. LownhNNN[nW Ӟmh<G#+e ~1FEFf1FkDsP5 YAIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/search_bg_mid.png0000644000175000017500000000037111073142772024314 0ustar adrianadrianPNG  IHDR sBIT|d pHYs  ~tEXtCreation Time10/8/08dG9>tEXtSoftwareAdobe Fireworks CS3FRIDATcpK4bfWyƔj$#-$"" aQ?x9;t%wIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/sec_r_l_down.png0000644000175000017500000000045111073142772024202 0ustar adrianadrianPNG  IHDR48IDATx}KN1 Dv%hp.6+"qbNwk"E"_'o@@U$QkE)$afPD`f>f3C)e TmC.XkI($q&:|9'r1ABC ΫF"Y\FJw?(VU, wG}9ras""0pw. 2X 콯hd w_KD@">weV'#IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/ic_list_big_down.png0000644000175000017500000000016111116360412025030 0ustar adrianadrianPNG  IHDR v4AsRGB+IDAT(c$@$`&n IIl8gOvIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/sec_m_down.png0000644000175000017500000000024011073142772023656 0ustar adrianadrianPNG  IHDR GgIDATxڽӱ 0 Xra)T( #+DOa듾m?2R11b$"N1""'Zz#jRUJ)圝Я:}n2!nIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/view_l_m.png0000644000175000017500000000023011116360412023330 0ustar adrianadrianPNG  IHDR;sRGBRIDATc 0^}EEE߿G@ %Gſji0&4r5ƛ8aE7ZXIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/view_r_l.png0000644000175000017500000000023111116360412023336 0ustar adrianadrianPNG  IHDR{sRGBSIDAT(c 0^}CEC߿ H?i*D?ĀtEXtSoftwareAdobe Fireworks CS3FKIDAT8kA߉ IHB.m*UZAK' M@*!UH!1XfBI,#\ngoٱy' ~ r@8 s85sRGIoN<Bru#?=KRK꫿A-Iia J\iuxD/'muo]Q9>ykGfP*yj6C=5=X*%['_6 ֲ4rriGL쩔K;ܼivN[b3H_E++\ܮ8;V΢D"Ab{71H}V3&k5#"uc 7AbI?:%B^dALGGVրvF#n{}GMM'yS yN; IJ2\lˊ J  IR!xKDpqU*䷁3 {#uvT\cR*=t O(pyn%@ @A0{5$" '}doa@IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/search_btn_small.png0000644000175000017500000000166311073142772025053 0ustar adrianadrianPNG  IHDRiMzIDATxڽKlU{gƲvL$u زBA(% !,(R,`Q  v.( J.**%q$Na6ɣAHh̙#*]P c:R4b#uwE O 5UG\օۭK*L 0m;l"NM6_I3Wɗ{$,i:9zxABJe_]`u=Gbڲ׆bJg8y~s<f8G}d ŽUlG|( +gGذ}oCم]R܄Pu6LqO̯lCa6n~Tm" g!{\djL*A\ hn!%I!_F,Ƴh鍴P&HAiY[N|rfŕk< xt\c4<|咱e[EڀxbBsT B+4!G:dG5@b2|\)*Ě6 7لeIJWG\?2Mdr<p!eK iv9֫4zOqO4uR2f㪥^}7N;=N6W+D#&+a[!VrǤ!,:pTrFNO.@d?FY\N7?'kǿvrm={'XLbegj:_36>Kbbم-n(sK|x#S ,!e*˨YU1L3:l{ ҥwY.JNIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/search_bg_rgt_small.png0000644000175000017500000000044711070605336025530 0ustar adrianadrianPNG  IHDR\sRGBIDATŋJAF;ΆLɲB@\++"6!>@&6X(+Dm 12?"b_s8mwy+X^2 Zwxhea#5lng(G8<ϱthD'`fR" DDGF+1FSP}qloxO99=tvEpk}㹪>3iR~b(PQ+IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/ic_launch_disabled.png0000644000175000017500000000102011073142772025312 0ustar adrianadrianPNG  IHDR KU'IDATxڭAkAn]%[A0{0PKЃ"DФ5$9 "^j-;oZ*Kex?3Mjxbk> \"!BU5 pgi23s ؔal CjwM/U/4~Ab,el 2X v?n$8q$"eh}sצ<:<:jܻy`}ЬxPD5dy"DQP[ֻo)`%"AZ@7V@7"RsRH98`1QM:Ƴnկ4rЊ |at! BHAD|gk݊J)h0 _hܾr~6wZ[*) 907{v4;s&TN_{zj*؛“s?yeK3s,'IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/download_down.png0000644000175000017500000000171711072436270024407 0ustar adrianadrianPNG  IHDR!bKGD pHYs  ~tIME :\IDATx͗O#G^@\ r掯 A $,[rs %\,p%ŝLُy)2.b{yޛ?`;" 4 gP0!, >@QD~t:\\\N@ *R, u9::B)5\ی80SJ8ZkD$H֎MfkX;mǹ35aq3z &QZk,˺"QOXY7B08S4D(Ɗ~'#  `8bv&Dǣ2znM_L b۔ñ Fכ]^^4;;#pLEc6"BhӨOҶUDQrY뢔bkknR2D=8SQJ,fm`YVzNբ9rLI*ʛ^7]4M,"+a 98iZ\VߘЎy|V}߷677+h4(Z5u]\`{{n/Z5؍O\V}mCcߌ+c?-J.P^^DT\.K>LR*dqqQxi=uSuDH.s-(\. Q@`, BA<LLLHPrh nWennNŢJ%YXXGߗeYYYJ"fI2AJyRL6^H{,1miZ]GT SvMY&Ni a-ఄIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/sec_l_l_down.png0000644000175000017500000000070211075230350024163 0ustar adrianadrianPNG  IHDR osRGB|IDAT(mn1?ހ H4@I"DR-HDğH.Y3)zsig9go_SK#eW8:>ѪܾsaH$UB󃧫?q0sFUQ 8[;gC1FnFD1R"LJi|Uua q fO]!L)؅^f/B쀘9ͦm>ypMo9krZMLFZ+DfJݯ8`f݀SJAUf6#!r{{ogܝZ+8cb>9_T7o 3[l z".mIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/view_l_r.png0000644000175000017500000000022611116360412023342 0ustar adrianadrianPNG  IHDReBsRGBPIDATc ݾ19Ep~#s?+/1?,eb@,7^so FqE7tIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/view_l_r_down.png0000644000175000017500000000045711116360412024377 0ustar adrianadrianPNG  IHDRL_sRGBIDAT(mKNC1 EO:@$&V$0{j~^$+m%n[q$" 3Cܝ;{";"BUn#"LeAD*"Bk ]"" vDIfN_F`XUQUHUq #{\ڕbl7Km6q;fN'23>Pugf꺮s}~y[ʢ|m/zPlU)IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/ic_list_small_down.png0000644000175000017500000000013611116360412025401 0ustar adrianadrianPNG  IHDR r|sRGBIDAT(czQFmkf`AIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/view_r_r.png0000644000175000017500000000047511116360412023356 0ustar adrianadrianPNG  IHDR{sRGBIDAT(ύJQE} 6 BA,Rjokg UA!J٨шD QoAo9sh-.T8hjԜ]\j^O9k?9G'Lމq0tEXtSoftwareAdobe Fireworks CS3F0IDAT8=KQ;;:q]5 XBHRTB* k+S )mVuG@\W;373:&-s59W>1fi05tQ23o}zv||l9"i~־0Z=$MSڝ5"vgf 8 (%./4✓8@l`_DQD>cuIӴ VE\\ UY4A]Ӻs(7ZӉN^NLvԪ|[jS;= (3Zj{Z*̭\娨!xQzgIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/search_btn.png0000644000175000017500000000203111073142772023651 0ustar adrianadrianPNG  IHDR( `:bKGD pHYs  ~tIME 6+[IDATx͘_L[U?BJ[ e6ȒEEe10Ü1`,FbbbKE 6uuN2L6;&KWʲBeu.'&~Ϲs~!Di 4 C:UM #, c:arބUR..uPrĜ\`/mzmbG%vn,͝f-Ͱai@`7ڼ1t1X0q~!Fwoi`. }x4^F/,OZ'q2gcӌML,PYU`޽wCƭ߉0|UX"}ϿEl6{v[J80s_˛_H ŋz[x6[D0LvM-`P2#yה|E'($$:^gA@>N$ME$#LykK&Y piL*t"Y$yp/WrU@m'_ JWUQQQ{oz %>}="D NM^Va} tEXtSoftwareAdobe Fireworks CS3F[IDAT8oG]ޑ*_M'Ep8ܟv޴ivVoXzpx•+??r`8iڟ;na8WVcʊR-..]mʜ27o  {v}Zir j͌Uyiڼrs7C 2? )?ٻ7F}`7oizɴ !" 4tƸ C#v[L ]u0qKJIEM B1jۭkτds[@z65r7 `lyz(.u>0l쌑CdosTdQa.z5ڏca@F2l Ěy!Q]|d. Br97Fż5P٪UTW˦y 8>zi.\Np8,OVBO1_#;;` )7V\dIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/sec_l_l.png0000644000175000017500000000045211073142772023146 0ustar adrianadrianPNG  IHDR;IDATxUJQEv(XȨ$X)|  bE{ζp$Sn^{Ѹ<)p4.wzzs{~ࠎ1Rc3{|+ !t͌% \\m; anUyE`}H$kRΐɴlaw2BTCBɝi$@gm}NgP 9ՍN/݂&Q1T IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/view_r_r_down.png0000644000175000017500000000070211116360412024376 0ustar adrianadrianPNG  IHDR osRGB|IDAT(ujA]eP[ ˊA#ƃA|#w0 (6^aawHglK|wRUM13J)*u]Sg/oRUUYg%~&MSr03r!k&M&T1FDGRJ;!HMܝ]m0lT=zi'Rؕvw_F3Ѵ78NR9gTVo=9NZPuRpZòlPU̚>r=s?Q51 1@?(R&D_?8}=Χ/NR:~z=Hy<_y\_k~Pv't!IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/play.png0000644000175000017500000000140711073423036022507 0ustar adrianadrianPNG  IHDRvbKGD pHYs  ~tIME #5IDATxŗKTQ?/gb6S"D !Mc LǨ(p)ED-iӏMqc)xB(+ߛOy /{s|<4`2M} Lpih[=Y,`ȩU@U6}&j +_-9qkBleff5p8"/" <&c}jG`̇&69&3wD\`W"b?rtL \P; `׃jEK 9]>STtDOm pGK~čVz:KJo%t74, TZE ܫ֜F\Hj=FO; qLܺ+ >qi` `rrS$y,8ش@y'E+Ms@SNHuL9?ٯz:d/+B HQ຀T֒k'N`ىn+9ǯIO&pVHa7SSS1`m٫jP\Sqɍ^+xXq [0xΓ"IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/view_l_l.png0000644000175000017500000000050611116360412023335 0ustar adrianadrianPNG  IHDR{sRGBIDAT(mJQ{g2H[&np nѺZpUhh6Bi@?hw <\ԩu:-{stNr@UbV}afQ\{s"ybyӶL)KB!jHIK2!%h}Y-DJ 4^|};LǬK :LJߟubgs k_IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/play_disabled.png0000644000175000017500000000156411073423036024342 0ustar adrianadrianPNG  IHDRvbKGD pHYs  ~tIME $RMoIDATxŗ_KX$i+b,0 kgbE0^ ޖ#HQ[Ek;,{Q۲Ύ=g/LBq^B{ϛ􍝝0.]M ϩ8ZVuooW?" N677?8樂?-//KP0H))񀥔?ei6Rq Rʏt]jڿ" 6}phj5d2R;==Ek…(t:\]]h4p]7 >99AkR#:tt^L&$` 8t #~5v IR%` \.]G ZJzN:& P,`T( Q{5T*rtTwA-֠zz!fCe;u=P˲, !Zkv-?`h!mضeYR)VVVf6z#Q`"4M2 |oEFJ8!puu+O~ ЯeYd2 À_ %u$X]<֘x p:> ,D$THcu{o_ _3IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/ic_up_disabled.png0000644000175000017500000000075111073142772024476 0ustar adrianadrianPNG  IHDR sBIT|d pHYs  ~tEXtCreation Time10/8/08dG9>tEXtSoftwareAdobe Fireworks CS3FBIDAT(AJBQ?G/xK TDEXIP0A'aT`EavP; g=z`swS87Vz`0 =$ O`:w@7!l=%; .or/obȳIH*Ek )j_WsEfVfͬ9WlCE'of53lf֗Tff}3 #ּRǧxr3ŷ~_x)I I9Iٙy'y3;Ij ;}no.1&@b\W~bB@!-OѹlPrIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/ic_down_disabled.png0000644000175000017500000000072011073142772025015 0ustar adrianadrianPNG  IHDR sBIT|d pHYs  ~tEXtCreation Time10/8/08dG9>tEXtSoftwareAdobe Fireworks CS3F)IDAT(AJPM-#zAXL -H 9@].Zu.\z{qUhWB:0y3c׷1{Ldć{z9>w n5fII՘8knUq]kEj`Q;y=q%Kv.Y$5 Wؤ1f(nޟK6vË4L"UlOjyIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/search_bg_rgt.png0000644000175000017500000000075011073142772024340 0ustar adrianadrianPNG  IHDR `sBIT|d pHYs  ~tEXtCreation Time10/8/08dG9>tEXtSoftwareAdobe Fireworks CS3FAIDAT(݌JQE{%K"iAAAP!B;Bk ; bo!ڨ(l!DTId +o,6̹C;{GifxqǻKGAB@H#OI*\.BDhN6VPw}Y+KeVPCb `]T`Ac1aA Jibc }PJ Q@`fr 'aYADIunb80'@윓w0WfN?]\dE8{{0Xd.K#Qo%I   p֯-IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/ic_list_small.png0000644000175000017500000000016511116360412024354 0ustar adrianadrianPNG  IHDR r|sRGB/IDAT(c K@A'\|d l22MZ, IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/view_r_l_down.png0000644000175000017500000000043711116360412024375 0ustar adrianadrianPNG  IHDRL_sRGBIDAT(mRm1nIҮ WyVFa1F_  3I*HH]n(^©۶af003;J)')"d~ $1&1H""ވHb>zoRWU0Zh'ywZA򵨩BU!"cqDZkZk0"2Zky=' >>W}.yP`3C=IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/view_l_l_down.png0000644000175000017500000000070511116360412024365 0ustar adrianadrianPNG  IHDR osRGBIDAT(ujQ[nLdLf-.ąK>FyA4OB $s\tDڂCũSǷsrQOO>Z|U%ƈ /%MsEY ;;f;ۻ(L&LSʲ$DJ 94R( ʲ( ! "1ӪM1v_![Y w19N#YGݑ1--Z|΃Is]Bؘ% m鶫Fib>j܍m!YSdlPؿ?BV'\|htIUUI!}_yWT]يΜ SSIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/sec_m.png0000644000175000017500000000023411073142772022632 0ustar adrianadrianPNG  IHDRYtcIDATxcLxC50k/%?JwM͔E%6S~(?` X L '.dghE:j{IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/search_bg_lft_small.png0000644000175000017500000000036011073142772025516 0ustar adrianadrianPNG  IHDR?9GIDATxڍAjPE{%Bu& \KPTP<FνWgM'!K;3v~5}dTMxLƯh<_h@>e@f⎈ "WEqTZ#Ws_k~xߛ{{ޚpdp<4w׿ur6HM,)IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/download.png0000644000175000017500000000152011072436270023350 0ustar adrianadrianPNG  IHDR!bKGD pHYs  ~tIME :#!&IDATx͗OHQ?3+Fm[Lp C%A RTFnX;x萭zhv^VR$y]fCuvg5z̼~~x/%p;`) 4 cP8a vvJ>!DĝG$vIIgyv^݀@8gE2P@* 2ͺLLHAvawL!%Jmp/`#T 'g-aO|>_{N%S*@adeUUm`M'Xջ%"IHf(]7ϗ L19^0P nHM}pFL38yD^199 ss偁YUU/(K f`;b{h4: {I#[p8{؃.'Ht(-"tcWlA{Or4>*MN$ dT[M,;IBɡ"nkq݂) "B#[0rp Y '\^2IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/tb/ic_stop_disabled.png0000644000175000017500000000141711073142772025037 0ustar adrianadrianPNG  IHDRasBIT|d pHYs  ~tEXtCreation Time10/8/08dG9>tEXtSoftwareAdobe Fireworks CS3FhIDAT8OHQǿuo9eQ1$i[]߰"(oGɸR[]4Px!V`.+?N&jJP̤P)*cL@^gٹ\<`>{{@RVq c, lPc uj*c1V,I]X5rq:[M| d~A<Gl|rs~\Rϩ-z\vR1)(yBܔW/7Z(d,Gz{}uEQ;4ԗo̖f쌝v'F ndd|J E`th^wͿ~-Wgy797`E(rD4ΞQ#n,EIs9$L&igAHeAT]`ύV~ OK_յnA4/USUSbKGD̿ pHYs  tIME &ljVIDATxK # R ({3""sIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/rss_bg.png0000644000175000017500000000401711073414754022423 0ustar adrianadrianPNG  IHDRL y/AbKGD pHYs  tIME , ;IDATxmTW;svvݡXSݦX6D(Z_ h}/M5U/ƤMJߐ@[ ҀVBV@- Y`gslw_dsd{9G4]q hj QI)!VJry t֎6B 9F0>jyb :%l D](H6xNf(i !>:[H֚EB 96Zy>##{8v*)jbyN8SgG^=r uT"j9OF<GkR u\97k?v=T*rM`\֓j;LyOS#76pC:|GSaE,D6w<Ŵ;(8 R) -dYb(D8d3#~ͯe#?拏bnaBjRXAATc. 䶹dVKftpq~CǾ:'Gi%^Rw)l8}U=[0>3kID}2]. :azl८ wܒ#BfR62\)ߏ{\#s|n)Ct[P(F82]|ho9*c B fui̓|OO=Pncn [5:-bة?%X>rrArU< %ndzy|X78tdQ>VyazμUt[p jק]ǯÍ7r&bRbI[XvK:n)50_Q!hOm)uDcڱio 5'UDf2>̚eL _(ɏuXCe!E $$/kcK{kT))Bm9*Rŷ5Z.y7s$%vsJό8V10-{zl UTb0A)isOo1&>XnsӶVw(h/2\Rc-y9ݴsvEi;Tpxpó/A9:J0A2jag/98')p2VLq ̔,PJي%*Lqűȥrf+tX*XŬ*QJl>*A . Q(c0LN^ 30K0NqT>(`"A#J%K8!0rt'AnP^ljQ-[QB꼵ymX,ᰒ\Lrz5g~\ ܳLY"IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_left_scroll-over.png0000644000175000017500000000062411042177134026012 0ustar adrianadrianPNG  IHDR(a[IDATxJQϨ4"Hn[YQԢuD/[ԺMB=A R3'GIf|ߪj~p?KOĝN( ոq? <m/&ɔH੨VNTD R7Z8e,IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/checkMark-14x14.png0000644000175000017500000000061010535151166023603 0ustar adrianadrianPNG  IHDRH-sBIT|d pHYs  ~tEXtCreation Time06/02/06>gtEXtSoftwareMacromedia Fireworks 8hxIDAT( 0Eo$ 7`7 4]@5) z{wo^GKl@[E[@ Qg5(?u/P쁣Q[q71.L/H*+3>)mJ[ f!h:);PxF(dբC8*܎bM]\TI}Y1N(9IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_lighter_left.png0000644000175000017500000000023211042177176025202 0ustar adrianadrianPNG  IHDRaIDATxб 0 D6lY$5n q ?}R-@#bg ef/yn6Ǹ9ǰjƗjo}:6SIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_mid-over.png0000644000175000017500000000013211042177124024244 0ustar adrianadrianPNG  IHDRle?!IDATxc˧l55 m.ވRP$QcQ4:)iH[d|NqrF<p@G(JcedEN $T.ʭRHrH"D)T$Gce(k^c_Hi@x~}e?O'Y4VM~9u1/2HR{HLP4d.l.@`5 ?Jw@pgG0j;crC*K b5N8Jm֤[Tv.R7ˎTǔ KkR.1[ZIT^r/xH1r'zZqi4)͒5^7sswll$Zn cnV8HdBc MX{W]<k`n 1koyDj4@A4(m\dܫNs^M.V3k&s1F<_دSUsѪO p֣G݇`{q]rp>k5*W8!G  YRJ%PIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_library.png0000644000175000017500000000176211071574042023666 0ustar adrianadrianPNG  IHDR-sBIT|d pHYs  ~tEXtCreation Time10/3/08F?tEXtSoftwareAdobe Fireworks CS3FKIDAT8]h#U3M&&5)Y[ć>,b*,"ԗT(-v|-R% >,bC]% }?viRڤM;ٙ{L63tM# J) eMJR5 8|SO`Dm =e("ZCD7J 45 8ήR 1 '.m w!DRJIH)jQ@JJaii:gVV1pB< $S:B Zx"ф=x6snY~` 377Wfggڵ e۶rnTe)4i }BfffBu]>~B.~O|)~;R ڭQ(z(X. BZJ))KI?i1JG8==]RJ)߽lC0 4_[&R^B ug k[6{!Ԁn*ʃR&@<+o7R> l6a#!GBBO7\w wm(Cg7"@7sэnLIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/bar26.png0000644000175000017500000000033411061446502022453 0ustar adrianadrianPNG  IHDRv6sBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time9/9/087#6IDAT @ Ą̧oHF:ݢZ?P$>+'I8,:'IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_auth.png0000644000175000017500000000105011067334526023157 0ustar adrianadrianPNG  IHDR Vu\tEXtSoftwareAdobe ImageReadyqe<IDATxmI!_):^_a&|+IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/beta.png0000644000175000017500000000042511160345264022456 0ustar adrianadrianPNG  IHDR gvsRGBIDAT(ՑQm@D_V%Bp!BB!@0C)?ȕ"+HFҹ"i҉-` @wN@H7_@LF GR vi@X0`ӂقN#O|,U-Pҹ= ,]ⷚ QN?E)Q-:s;j(ΫnGZoIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_device_rend.png0000644000175000017500000000120711140225434024456 0ustar adrianadrianPNG  IHDRVΎW,tEXtCreation TimeTue 27 Jan 2009 14:43:41 -08002 FtIME,3 pHYsodgAMA aIDATxڭT=o@}(.]\&$%G hPT|TQʔiIDy ](nvμU$rq&#Yc޼} 9+sׇ$ɗՠ")шüԀpj]~V-,0b6ǜl<76`[6@>ELEyvH)COf!IHوWwhk}*Wrc̎+HЮ) LcҧŰ!wu>96G*@*Q} -mX2# 4oúU4Jv`if\cEڦ<1i?4scq('|==iV#vWyw2<#+a9Lc}ј _=s8IHMcqXI68!9;,E|VHCMj&LJf ) 3z\Z1 ~`:ihCjOV0[u)c7yO) J\ɤS+*LZQg#ڣ-TJx^I+\ uB*ɀɐ qFňT3#%HVw+sWS޶,hKǝ?\s=cko-q*4K .izuH1؞, kGv-J?<:hIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/vitality_mid.png0000644000175000017500000000033111061435330024227 0ustar adrianadrianPNG  IHDRןsBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time9/9/087#3IDATU @0Dcelj({mi) )2fK>zlIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_x_selected.png0000644000175000017500000000057411071574042024341 0ustar adrianadrianPNG  IHDR osBIT|d pHYs  ~tEXtCreation Time10/3/08F?tEXtSoftwareAdobe Fireworks CS3FIDAT(m1JAߊX<=hn m`z,lFt ^ Hm368Yy߼BBUTM;2>ѥb¿w8UǸGcѲ,S5q7pm ;Rߔ;~,:ؑFWM_?460_[%B] &u(=a)EM [UF?lsIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_info.png0000644000175000017500000000037611154103440023145 0ustar adrianadrianPNG  IHDRdtIME7*Gn pHYs  ~gAMA aPLTERftRNS@fbIDATx] Ѓ @tWVbBi\,qٕGXiܞ!U6:uچ*Vkud-5+M0 f+n~rjIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_device_rout.png0000644000175000017500000000113711140225434024521 0ustar adrianadrianPNG  IHDRR;^j,tEXtCreation TimeTue 27 Jan 2009 14:48:44 -0800MtIME1Շ pHYsodgAMA aIDATxڵSK@}()(`B;F-*lGAũSUP"At[5b X bR״MZ+ow}\NZgXDPV-=M}XY PyKD-fDG*3 Zt}OZsSUP8/|%b lƳW<`Rfw:)%b _u&ly_dDQ,qd'YOK jBIH]88!<0 xײi&{ReLp t.z*tCx07֏tpj<x3P6]ї5 IG2t^{_8Kj5rՇ=ݎHoe~\Sp" wL~ OdxGĮ-org&~N#ɿ݊{IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/20px-ps3.png0000644000175000017500000000067211156644726023055 0ustar adrianadrianPNG  IHDR tEXtSoftwareAdobe ImageReadyqe<\IDATx+q&!)e(99)I!ʅ؃'mo6A.zksԧv35m6fkN'/*6qi4A]`WX+4^nBj3x. ʖmSo,+䛰9K;iXm^ܛy3ob*O k0&T%h&l (78^4:<[,JPMUa 9TK$,;ֱP ZdALjJ~_6l"Cp}L$X.?W.sop/Չ`KsuH~Y4s!n>FFvbIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/20px-psp.png0000644000175000017500000000065711236202400023127 0ustar adrianadrianPNG  IHDR U~tEXtSoftwareAdobe ImageReadyqe<QIDATxڜRN@.%D#/>@}Ʒ0^ <ɋKwKPdvf_F%fKbu;c ^G}Ԛz #0 30 \M|2daQD"O94r{̅^p!d+q!K>Lj,%z<62L8Wp=/KPB8(Pad@ɂ8ݜ-?E樲P|PV,mC aÙNilEWGUnqfY0d݊,$5K"C~PAn^_`YVIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/20px-itunes.png0000644000175000017500000000320711156371260023642 0ustar adrianadrianPNG  IHDR-tEXtSoftwareAdobe ImageReadyqe<)IDATxbVe037a8f)ի]3{rko  Lͯ# *')c9rP8Ui ZL5b $m9RuN'B3 A5;@) |+u>8'o0~8EBAYՁmϟ ^e^/?`"q^:/}e Rg~.|Z5!%s'Cm칻_ѐګ@/.9 AΊ@l]R\obK\u.{ed`b--,<-Z% 0C(e,@R_˃=}7eK&rg7ڮQmd!R4'MOQU!2 !&"%``Z[ .-& c9qNg>Mʜr>5_d\&K]:7","c@unj@=wV*U`CZN"#iDCZJXI$6v?yB:!"A쇮)(M#kͿs?X1Bx(O/%RD 5ͮop&q&/~\(R_1oj,z;hR|+LR{{s%q-(y>ZcLf}Y6liʕ=>WFZA~;x53y͈0OZ i 1IN${s!"J: AkRAkIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/vitality_lft.png0000644000175000017500000000055611061435330024254 0ustar adrianadrianPNG  IHDR5CsBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time9/9/087#IDAT} Pŏz!hkC.5, .-=DAoP[s -vnKC с3|#lekg#`za.mi̭5ڠ"B$.8F3"bտ?qRrS2稹 @Jpa{j"(@xHM/0xj̅hhcnVA:IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/20px-od-bel.png0000644000175000017500000000156611256043612023501 0ustar adrianadrianPNG  IHDR tEXtSoftwareAdobe ImageReadyqe<IDATxڬT;hQ}oIvF(ATlRke`l-* 6-Maec+AԄjf}=w~0ob޻s|c{ǫbמoբCZk%tdT$I>qۀR{?c Y?KR oǫtN33b ` joe8rhM+;C#<+Lf44eYCȰF{8wݩ &h8\4y1~C4p/MaJD>E)QNLRGľ!+hl4K ,Xo@6zא UwAq?c -<0,(Ϸ?ieqf2ܢ"i2e% 0{;TQK'(2pV#S#NA(:60O)ɿ`kRgW0L[/!sG *L,K@|nBG)(RP@12e?RJr.ȃm*di׀#2c.>eb{IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_x_over.png0000644000175000017500000000057011071574042023520 0ustar adrianadrianPNG  IHDR osBIT|d pHYs  ~tEXtCreation Time10/3/08F?tEXtSoftwareAdobe Fireworks CS3FIDAT(m!NA"P!$pY5`7@"8z,L\30y߼?#$BބكXzaǸb/hUU Mg8㭃))ESo*jߢCߕ;RhkD<4~)XiF]=_썷..#4o qJ` IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_download.png0000644000175000017500000000310411133271260024014 0ustar adrianadrianPNG  IHDR`sRGBIDAThOhE?EE&IlN"VQh/^A$QE7PP:0)`6EQDJX=I)~$B w{y[8hwd7}XaoWr>0վ.F.5`h}Ug뤲L0-[@;`)f|&"|h]|tD$p8nKU` `[Jp(x_E4pgMGݫV~"Cl](&AҶ>6Z n`QD|+2@Wo_~4Z} JLŸ>%'uDDĹS>_V9 FSNm6p|cz5Z͆/p0:0e3Zi`8Ry~&[~UK?e7ZSex|:xNh5e2el.O9k!e>nr`H)yhQg<LdќumMF+e$ *0Fiu~.2s2%|3q[U_)KxH[] 01ZDa#g=`)v}D|ȥV/Fy/iF+9,nyJ|&FuY <jȊUSo.K)>j̯\ x\Q_Nl25`5G2G{hv<0 h$uh(_MIkG>ΊkF1oP\K[U`r{r?MI@_6@UΟnpC^CېߣqX^gC+~$IN,(J9:H{.FeղTn q>;IY dɴMx?"kW {|#Gd휡z9|f#n,yyҤgˁnI(ӚvsR9LAY[gt4I7Z=#/VY+‹Y'2dd(\ɜO󯦔&bJ߉.  o'9k:8N>oZRr?-˭hGYLJ@!߯'7H׫ >Z'tL -% 2ՃoDG᷍V"@dmK8Vy xX6ZD7ljU4Z~>%Y+@vD_a147Zu7VV .$f1~JwT5̡'k J U_+}X!$cvh6O%G Zg}_ #gV5g#p,!Ο&}h8ޅRKJE/ׁ#%ۗgA4xx@f-!lRG{݁lTΫp풟< <2[+IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_vuze.png0000644000175000017500000000176011071574042023211 0ustar adrianadrianPNG  IHDRAsBIT|d pHYs  ~tEXtCreation Time10/3/08F?tEXtSoftwareAdobe Fireworks CS3FIIDAT8[he9Ϟݝqnל[)֚Ұh+hi/ A%«z J(DlĢbq<}%pPJnLllc&Dz0/'CMg_tASWS@Sp5t 4d')lᯙ1E8Vf|dEDE5LX9n^8iv|-ً2-`CؿX\4&`XÃ, c:R17-CCȇ*S\-XA I,΂< m puW$.0hݍlűGXKp`@ p$}V<;9VROf{tCQB22#]Y*ʬۗAK`(MqY!mB,eC8"Opwt}mp [2'tI7LR|թYˍPu hV0b<42\>S e>,zE(S7@Uk{/Sջo䘹IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/icon_arrow_toggle.png0000644000175000017500000000052211071574042025243 0ustar adrianadrianPNG  IHDR YsBIT|d pHYs  ~tEXtCreation Time10/3/08F?tEXtSoftwareAdobe Fireworks CS3FIDATmMNQ#x' ݡ피pN;NA'367@ZtR.)KKHi>C ƽ^S.7oc41r[4CUGUvxCU?e5=1]al4ݧ_oD=M_78u4k:J)[IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/bar24.png0000644000175000017500000000034311061435332022450 0ustar adrianadrianPNG  IHDR;̗sBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time9/9/087#=IDAT51&MRg}cw-A:$N)J}vKl#"9VQIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_x.png0000644000175000017500000000057311071574042022470 0ustar adrianadrianPNG  IHDR osBIT|d pHYs  ~tEXtCreation Time10/3/08F?tEXtSoftwareAdobe Fireworks CS3FIDAT(m!NA"P!$pb%a [ u[&\1 M^3BBnF~ 'TLlaǸc>Zeʺy}\3~:zhaGqRPZ7"oӁkt8JyY7cN#z&fxDh"d Gl0ȷ=RlcaIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_device_od.png0000644000175000017500000000127411245660464024150 0ustar adrianadrianPNG  IHDRa~e,tEXtCreation TimeWed 26 Aug 2009 09:29:20 -0800(ҬKtIME". pHYsodgAMA aAPLTE9JBkZk)kRBZ)RR΄JcJ!1c1kcZk֌B!)9kJ)ckZZB11ƌBZRcJRB11)kJ)9cΥZkRkR9{!֌1J1s{J!k)Z99!9k){k!k)!JR1JR!J))s1B)BsB)1!R9RZJJ19!J)R!B!!91JBZRcZsc{cksJJ99B)c9cRk1JRR{ބ!ZR1kB{Z֥1cc9{R{s)Rk)k,tRNS@fIDATxc`203ЅSRӐQ11q pA!a^7w'O/o_?+T%(]=}C#c6DDJZFVNN^NNUT"$"*&'./! / ($ w:3;+'7oYX0B o].τ'IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_search_selected.png0000644000175000017500000000107311071574042025332 0ustar adrianadrianPNG  IHDRasBIT|d pHYs  ~tEXtCreation Time10/3/08F?tEXtSoftwareAdobe Fireworks CS3FIDAT8QON),br WE kA!E vV{l岹#Dd!KvXdd73|<$=sɅ$KP*pά)p8<F^P(V*\.[.11f$Ʌ$ X$iZ}ڵ3I}Ca3V(r_9x<-0 J+^n{ktJr#a$q_N⨧&;L&qt^h6x{8ngaUǕ6: o3Yq38 `FJ :7D0>XfG79Gti&3@={8x6*mn!@3sv96ukFI~l0 `;YCwt&q4ğ>="rK;I{W6lWt(QN7Oh|6'8^JW b7'D`@ # ƴg0f2N8 @Ɣo=7 4ӘXv-l~SQJcP.Żg)Z36 MP$&p F"yzUN/_"{q?8{=w i{4RrҙTP{M!i=a`KW!Clp5>6=3IYw2|!j?#Ki:($c9 a7hFqv4q6/ i6MSG@) p8G?O }1T66-3.0wk p`ܓ9 g׋8CaKnQ{د:>c^Y˴f')mJ *\{Jι@b3W;I~D-1kܓ=iY)1>A6ն8:CE Q (〳=UƉf8vk氺a%qseTڜw:{'qs$f\IM*mȔ&1g3ӌ.n`[ٹJae7KW.Mޤ߬˒eشGrF >Vgcq=}kqX]o0TVisqa5*Q[A̐Hf цGb6P#v!!tJsĚ~E-OOZ(ƻqAs]Z.rXic]aй[M\'S{niTVivy9``%O.I*mfi+eх ./rgf qZQ=I[,7yp#k~RN je個иUeoS' m1{rL6ʃb3K M< `e o_NG5{ˋ4 Ki$,a/6S wxwGmFG#dskzCH;wx"R-3I_=n,ln^_cuW. )mI)mʆVf+4Yyp62'V (o!/8rÍ,5 ɳYktZ J~k\In#/e(W .L S(qΪ@yWN Eb JukxWt-Z%G<[0Pa ut'.s86[|G_Fvڒ2zn nd wuk!ٙ}lQ>m<%23ZI]MYWt=2/C& |jI]Qs~a魘KiaC1EULR5Iq0 "I&|3ud<ϰ/ (cӹ.2/3y;B/O4ǜlW-5VeW_ 0]{[@v'`DUd`^2 ࿞ ~]q͑ q6hJM6&NWOW[j|4Dhbc'sHʡ dW;nҬlsI0K):Dw>rŗ0Ѱe&g/@!AfXCcw˦AUS [TH{dX S૜}qV_lj3jZkrna'LO)#6HiQNPUP]8~;eG=սJ74J@%dzO3xGQVqWҸǐ%2*8JyFy'qtSjmeVd%vSBw, IFҐp=vQ)6i,4p:9Ҕew,f&Mwl>4Vgp]0kpٝuG'+2rY@ERF8Iٿ!e y6%ovkq=L+jlJv؍tm,=l|ylr5 6Qڌ)? .sMw ,3U1,w-zLk6gw\G+$&}q]cdקe8;E %`5?јB1^Y&˜6AN2qLj(҆c.&\ؖP P00?#σ4\7y/ e2OT!ЬM^V( ZQE>ǬV$S >YڅiPaᄌ`91SUЪ)S;BYſ<+hdn9,R=zk.FH+%Xo.s5Pla _ aL(mVY5c+mäfIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_rcm.png0000644000175000017500000000073411271763642023011 0ustar adrianadrianPNG  IHDRAZtIME *Fˍ pHYs  ~gAMA akIDATx-OKQd&3j!R hW ٷ-ZMAm¢M4eFJebfqt*{r~.G@(KY%Sy*\ۡ-K0;<:ؼń*.I#Q{j]9d#npr %t1 Kknn 4ѡsܛd)"K(:L 7FyYn [n 0Lկ>bFVhbEYGsK2Ddw"gt懌B oZO3˄Z \BL{RB?U6剦tjp>Tmrm=7JbDrǫ|@Ғ{jIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/bar24_selected.png0000644000175000017500000000033011064042156024315 0ustar adrianadrianPNG  IHDR;̗sBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time9/9/087#2IDAT} !YT/*!>Dlʵ}H ,f IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/bar20_selected.png0000644000175000017500000000031711064042156024316 0ustar adrianadrianPNG  IHDRLWsBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time9/9/087#)IDATcKӟP:u0\ %Q IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/20px-od-vuze.png0000644000175000017500000000126711247323674023737 0ustar adrianadrianPNG  IHDRa~e,tEXtCreation TimeWed 26 Aug 2009 09:29:20 -0800(ҬKtIME 9) ڏ pHYsttk$gAMA a>PLTE9JBkZk)kRBZ)RRJJ!1c1kcZkB!9J)cZZkB11BZRcJRB11)J)9cZkRkR9{!1J1sJk!k)Z9!99k){s!k)!JR1JR)J)s1B)Bs)B1!R1RZJJ1!9)J!R!B!19JBZRZccsc{kJs9JB9)c9cRk1JRR{!ZR1kB{Z1cc9{Rs{)Rk)k5~tRNS@fIDATxc`221хSRQ1q pA!!aAW7GwO/ow_? T(m]=}}C#cDDRJZFVVNVVUD"$,"'&/. ge;7 ,lȄ7a8CԹIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_search.png0000644000175000017500000000141011071574042023455 0ustar adrianadrianPNG  IHDRasBIT|d pHYs  ~tEXtCreation Time10/3/08F?tEXtSoftwareAdobe Fireworks CS3FaIDAT8kSA5 I)HQL+]TQ `Ѯ.+ "n`@A]XSjl m_̻\%-V0ߜ{Όbg٫Jڅ@~333ORzHe}}J\@MOO4AT=lsnVZ\\L:~EjХBp^@unR>5\YYX*.kO666ic vP@ h߁1 @! T*ۀcKGQDՊ? (PJMRJ ð]wv5bX|hmnn>B0f'FGGk$$3`Pk} `)omm5/;R8V}JIk8RԅL&sP(}֫ FBQbֺ"rsmmz|`e_."Mih'Ed9w5t:7F@kZ$Ή"r*N7z*v8~LsFD^[kh*3vIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/btn-turnon.png0000644000175000017500000000343211157360350023651 0ustar adrianadrianPNG  IHDR1 $tEXtSoftwareAdobe ImageReadyqe<IDATx4VKodGnG~ "i@Q"X IQV;$ل &d&g<~=nvWUU]Sw)gR_Gʥ(~m4I_I3@p@(ps(-Fhtr>8++i6a)ch.gkփ~C-8_I^.3 $ͬQ||{{jɔuR-4JOZ7 m͍ZJo\ .4!GΩ:. 2#}if[ۖ7 |جw-}VV"uݥuA`^ )]AJۚZ`h.#WxYtI'gHTZEh<pme٪E;_bYDN֪|oc|\|8? ,tJ&5nr^Se6 "2Pdڡt ?߽XbqqߘŃU\_['qya n+8Ne9bm '!|/  {3yb w#]O_q[P/{8E1eu&=ԫ5)Qr,r+ppCRdԥ ΋RO )ӃMe ΍Y5,܂2$#1;@ƙ˳ GE8D(O5R6)xuLR!scUFcv(tvdR |hAQ Ї~ Jrh+TiJ$'IdMlj:Nu\[dLC:;U)_V8׵Pta+A1m'Ќm G~oaif A0][4qH XW7|Fhu,tQ 0+U tLr\/Magn˽VONqt:`e Uŝ[G cJmo1_$Ҥx{F"9~7NR43uZ6ۃ޹+e*> ۗL잍9e~HS6cJekj lS&% #*R N>}8ׄ_ ea$5< Kդ翳"%y9:9__DJ:4 fʘI iE &&=4ґޘ$εEV=V5EӲ=W@lC4~Hir+IjӺ~ʫsSjhA9RG5_/m>yuyeś8Gs1gXG$Nn= [rr1Dkc`LfEg. .g\Ta WJ/7߹2VoKUPD=<IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/20px-tivo.png0000644000175000017500000000064411236202400023302 0ustar adrianadrianPNG  IHDR K7tEXtSoftwareAdobe ImageReadyqe<FIDATxbԵ(b' BA 9Tp/@16` &4 HbPM@`Jh ("]b] 3f $7%( k@ TXAi2@,&7J{k4` 21ރ4='Q)D(|ľ 4 I $w@$OA i@\6MWly 6b |?`&XPBC254q99ELBŢa5z @@X Pb@-X8= {dĀ\" ˀ*A"#@7z @<~f3IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/20px-other.png0000644000175000017500000000027611160005352023446 0ustar adrianadrianPNG  IHDR ,tEXtCreation TimeTue 17 Mar 2009 08:31:36 -0800/YtIME ?d pHYs  ~gAMA aIDATxc``Q0 T2IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/20px-xbox.png0000644000175000017500000000317711156371260023321 0ustar adrianadrianPNG  IHDR-tEXtSoftwareAdobe ImageReadyqe<!IDATxbgIZŽNl腦KhjE~6raR v珋>g+xoJX1|\1OWp<n@hZo4%&/Y7>\lG] G)2'qB8qC 7q֍nD^Ma Vfiƅ\3-_Cc]#/Ī),{ׯq; Fa!.(jAj]c߇qgNN9&fJf )ƻ~0Ɔ׌TrEki:ť Ŷ nvA+C%[Mp#I%Y[bnԦmj(L#AWtY z jkỶl>l+²Mƥ3T*D LVW"*eV|`?$eϷLiL~IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/vitality_rgt.png0000644000175000017500000000055511061435330024262 0ustar adrianadrianPNG  IHDR5CsBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time9/9/087#IDATcv5d[֑300000ǯ_}8lX:i01_J6.0Q"?Pea]X. /L_0`````jD,l,Xu?YYr0sdG1WII 9yhJ*;QQ b֧MO)POQ0IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_alert.png0000644000175000017500000000132011061435330023312 0ustar adrianadrianPNG  IHDRVΎWsBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time9/9/087#*IDAT8kAn&*&V*)=$Z *EUDOփDD EEh*D MyȦlڵP|.|7oF!"[1RA>< ādWFDn.ܐL`o<\D֩"wqQ߇f,`E Ef/&sڅ>} ѦWk&*wO=8ǡQנ=Ů+@: WaoztSۗqҔ5hlqj2J :h ^<}J.f.]RihnQ!hv<ęJp s%xH vcd)W`7I+ 4,L(f%1IP ɣ\0EL$rC4xz Xh=*PSNЫMT-_NIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/20px-wii.png0000644000175000017500000000113111160005352023104 0ustar adrianadrianPNG  IHDRW?,tEXtCreation TimeTue 17 Mar 2009 08:20:58 -0800tIME'"R pHYs  ~gAMA aPLTEֵƽƽƥks{ksss{{޵s{{kk{{s{֜{skckƄΔ޵ε筽"tRNS@fIDATxe O0][mȦQM4 &4Ig󄟑/}}3OL!S:oS8t+͙s%qr./$ xȬ$a&Y+"VF^,8`ߝ)9ޡK֏&;jT?MQ*-"E+d#ҊTn]kj4MTDЫYYVw eY]J=#RB0QIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/bar20.png0000644000175000017500000000033611061435330022444 0ustar adrianadrianPNG  IHDRLWsBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time9/9/087#8IDAT5ȱ@ @jv7Iw*ٝK@qPӕIFT /IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/sash_bg.png0000644000175000017500000000015011074245076023150 0ustar adrianadrianPNG  IHDRށ pHYs  IDATcLKKϞ=3@<n7${'IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/icon_arrow_toggle_down.png0000644000175000017500000000050111071574042026267 0ustar adrianadrianPNG  IHDR YsBIT|d pHYs  ~tEXtCreation Time10/3/08F?tEXtSoftwareAdobe Fireworks CS3FIDAT1j`'>^x8*b}dK'b,m7hy,7Bq|4|q* +2ELbnP]O]E'~(-~IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/sb/ic_device_int.png0000644000175000017500000000145511141747650024337 0ustar adrianadrianPNG  IHDR;֕J+tEXtCreation TimeMon 2 Feb 2009 11:39:23 -0800 tIME( Q pHYsodgAMA aIDATx]S1hQZnxA;Hf҂)8$Afk(HEGI tAHi:! +p{A.Qh}wnfhN\aTzP{c{1K Gp zXwߝ_'MтwSxh,!\*hMr?^*¹}] tY@N5~cF8rw0>*K"`$DjKڨ=o"4{ݟ QgZuGZ'!Bͻ THfA:QyzA uY%kp8@8 ERv#2xxI(ANۉ0bpߑ!aNuWe PW Nqc&/ y 3HHy_lm&fr%.A0?aQ$r2D\܈OYwJ^dgI:bx@+g>E;[!P o_oMqoaEcE+*S!xr V-wxD?uK e͍~*tHG\e'꟯6IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/30px-ps3.png0000644000175000017500000000110411157162346022433 0ustar adrianadrianPNG  IHDR$DSsRGBIDATXONQMDɈ1SnngjJ,F),X$bh(#f,Ib9MQb!asΝ?^5~u H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧ5IDATcoLYRN1IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/entry_featured.png0000644000175000017500000000135610755542354024173 0ustar adrianadrianPNG  IHDRabKGD pHYs  tIME%8 J{IDATx}?hQiR[m!hU:XRP" CEV.N"Hv] EIJ[~5]Zqsν\Dqӎ4PJ,z_*˚"@\0*"k"2Ps("b DHXO~3Xzx<[ZGD\N/@~jga:,687h=7"¯d[altݨh}eͅD"BϮs:Dt: 6dAk}ߵ訵vZл'7O=w5?<\eyyP-R}q:,Tqvim9?9g`1 0;;{ x&""WR)mlko!ihZ;."GC#;GD}]Q K476FZePJS~P"bت~oٲ;LDcE)UwdT*NNNn4ƐhwwɶMx M!Zw*0114D//yU)կw5jZ_ZG)ctz`lllFkfTl|6*>" g,˲<HIIgfMF/M_Ip\R^EG ƏON{zB(~pxԑKwpI!~dB%ۃqIYs9I,O`:9I|mo}ߛd} f9>=5ffOfj <=)}\Hzٺ| _\7R,LE <ꒆkʐ %;=IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/dismissX.gif0000644000175000017500000000134611100020266022710 0ustar adrianadrianGIF89a7򇙣磳sڿtq}n{|mrpsӲŦqm|}yun퀓!,7Z ZBL*EXX ZYX$T0>,4 YWYVVZVZM;P&F(6WW ZYWZVY !<+:8Uנs\Qˀ+J,|P٫iD1$]+ d2@UXkpe@+X4ʼn)FLy2o\1jiyQP X@h24AB\aULXC捓(۸ "A@A%.Y3iL r83*PɳӨS ;azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_mid.png0000644000175000017500000000014611042177166023306 0ustar adrianadrianPNG  IHDRle?-IDATxc?\NA+1!>`ЮL}k,7jgXUy-x.?+B4TDVfBS)e 8>4 β{۶!3!n;_,=;1se&a|>#leyv gl!/`M~#~πxݲSRz%L , Jk&n|[n~ޗ7tO75gn'K{ruIYWX$(XJ RHhN N3*}vǪ_1,$?=dy׭4EFg٫egzF[B8iLZ#˟?$7Y.Wn(zt(yYJ.ͶAVkEHZT#M =^$1rpWW\h?_aDADEP*0=J{)2NdnahAB&Tt>Nq](+ߖd۶m[T-W~Aa_YQJCxfzrŊPҟ/';x.D̐ )2bCys= f.Q eaظ`5k„ 6j,БAƠ00nc>}@]{B\ma6²m,_Fjs۞tޫ{ skݍ®EvΕ+WC۷o.QIġd D0'q$8IH<ːRFk 8KxK!(B+,DOiJU:hR*JR6Sb , [GQQ7'3-m} gkϓ[;QFT M۶B8SC0$*)JԻGhn>'ۿu)bb9Yhuq9Hg¾>^z_|׭3(syO5)MShNmr٩PuvR/H<ݱnt}?!o_*e>g:AbDreY\=)?k\!.TJ]ڈma[6໳RQ#,~ER:ce6W>F,A,B$`^.NTd2A( 0i 6mD(ڃEVWW̘fpRp"$p83sp2hXaGNZkө rۭ3sy^qض HQa8Q.[szkDTef=="Q\.w?LzvIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_right.png0000644000175000017500000000024011042177160023637 0ustar adrianadrianPNG  IHDR{GgIDATxл 0  Sd@1%" Pg6%)O"@g(|=/>{WPHA'I.yZU`eIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/entry_thumbsup.png0000644000175000017500000000064711042177150024231 0ustar adrianadrianPNG  IHDRanIDATxڕSJA%p שg+ QL#ڙ70X yNt69EPQ$?ŕ;Kb9;}|Ģr>Gx</ֿ#b fro?xx|rEQfgD:.2D#" E+w?d B"*_FPAΫi_Pf#P]U) !G𙹲ԝ "bHwNR䉈 'YvsBpwӅ "1` 1<۸A HDg(19U)x /e;Nb-A;wZ "h%=3g-BH|ݜ0\\^e?M2y*8,?:>U'N8Gfk!Hݽ~=9HHQB;V2iLqC7#HQyH@yk߁%/.=G1IOW s{JlCsAcwx}[͇;bu ))),/3HIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/entry_comments.png0000644000175000017500000000075510755542356024225 0ustar adrianadrianPNG  IHDRabKGD pHYs  tIME"m\zIDATxڥS1AYV(Pjptֆ ~0\ BG=֚iޝ+  3c\)%{Wf# Pƪi " yWWUEJ)SJ9WUcZKPu)rl6gUU*!CBo7KY7I$H6Ooڶ>MD^lܪ۶mMVS$'U]__T@%w?cyoSSжt&IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/entry_buddy_share.png0000644000175000017500000000050611070327036024646 0ustar adrianadrianPNG  IHDR;mGtEXtSoftwareAdobe ImageReadyqe<IDATxbd 8yH9 sӋ 1F & *d$XHpHq"\@q(yX`܈C4~PCF$qHspePc(?TA1!JĄ8;ND.9H!aPaX)v!P,@ v2H#8 CIlD&y~wZ=DPBbx%8-xy`0]{aqIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/icon_bullet_check.png0000644000175000017500000000053511070320414024563 0ustar adrianadrianPNG  IHDR w&sBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time9/25/082LIDAT1Ja/k-Bsr xXMii%B / h+x4?)Ǽ{3@DJ)&#k<XgorDbmɵ~T9"f߸/h" xUI?pMߡyo,V'nqñGkG{gn6A fIENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/network_closed_preview.png0000644000175000017500000001267311124350556025732 0ustar adrianadrianPNG  IHDR_\0sBIT|d pHYs B4tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time12/5/08@IDATx}PT, {. ;Db&XjHju0Zu4Z۴)qبMmF; ML"D!L̇DfPqHH,QdWe??x.n4{s{ys.*A C`Zol6ٺ zaqp8h4DDD~UVd9QQQ;߹rNJTThjji0É:9yO~JJ w&::&ivcp8]+VR$//_>,^0k,%IW/O>$O?< 2eʐ|[pĉ,\m۶ŋ)++c8.pݨj<nn}]:::xh4 8x<ʻnRoiii@7ӟĎ;cѢEc|AkgRYYI[[wvppPXX@QQ=hy'Yj5{n N0j^{5MśoJ";;8r7ߟqx5l۶3gcǎk$Ilڴ:l߾iӦaXͥٳg)((}v |ϻ\. |={_,ˀ%rssyyܹ7GYYdddp8pىtrhnn'b`Xx駹x"O?W,Z/^LKK 3qDCwwwuZZZͥFiȑ#*rя~bGEww7(((RVVFMM <:t';wNgj9C}ea.k1gێ!..'x?]vaӦMs??5k_r{{HHH={(_x_t:9x|*++}/]T9_YYɞ={8u6l.]$I?tk.rΝ`\p۷ՅO?/łdd2MZZqqq;vG*L#RXXnWw ˗+Xb Yp!$(css3{XuV~_PYYIff& , 0yd̙Cqq1>SNjvSWWGqq1/"s_ZZJff&n_~vy駹ٺu(2 >3fж=J}}="11(/_Α#GXxRƍr###ɶ G$dddo>$I"??ѣGZ,[L)'ojjR/iN4iXV X[/99yay9|0UUUg?$>LfffU@yvse\ˆ#އZ}}= .TUoh\SG()a(reyih4Ν;1 ݄ҥK+WڎlrZӑf!==;w*eXl2uIrr2l6IJJRJ9YG%^?}fĉܹK.t:Yz5ok={6FrNǪUhmm?1ܹsձo>}QV+شiֲe{a >{zzԑ޽{)//痿%ǏG!,oZRG}G}ŋ" lڵk}K/1qA'ٳ9~ѣygؼy3zjjjxgHJJRz֯_ʕ+%)) ^^'22H%=zhѣGdp/R?uyyy?_'77%KPTT󉉉QtnFv5kgƍ9+}sNz)-[@BB/AhrFzYȟ5Έ#Xh?<]{g>Wnhhb|$^n㭷"??}{l۶0HLL `𔔔 skjj4inttt_F3q!siz=111WӧOsqfϞݯ .pz}צ|'OD$} To2bbbrL:H SCBB뮻UۍVErUn7QQQʲ,#<>f! ;4л|%| xP So w:bJ ?J C j@V ~C s~!AUĄ\ ?J ĜC f! ;T'l=aEbb"kLĜC 08?}s~!AUNvxiQpԿZnkkwɓtvv2J stvvs)&Ld"<<F#CO> 8hhh`„ ?HDDaaaj_ :U..ƍlfȑzQTnur٨(FhD$!m:^$Iu];CUUuuu ;w.fF# J0, 8T*Z0Õͪ՗_~֭[iiiJYYeeeX~N'1#ry~!ro~^ dbܸq@q={{bXb$  +^ CRe:::j̚5S"IzZf7ޠR={6$bЀ`ٳHVVV@rQZZJcc#W.V]lII /^`֬Y$''c6V%cǎeرl޼6~mLBXX >3, Ffe\&KpkDGG3uTf3cǎ%22R <,\ݻwӧ9r$Zvn(cR d > #I>!jL2EɳZ\z!Gcc#V 6Tjkk #!!@I[,N8Akk+'OV8 z (&QQQJyӉr ib^[[fzCՒJEE@S^^$IhZl66 Njj*: 66o[^< DKK _}57Ϝ9ȓ$i:@oT]]Muu5<Ƞv222immСC+q1.]r1KpoVz Ӂށo[ ᆽ}B$Hll,@l6McwuEp렆^1Z󓬬,ň܌Wn޽|x<MFDD W.򊗌V'sN7n999/wdgg3eF3g(..V&&L ** Ne|;2^/j4͛jޣA۷Zbvߴr9FΝKaP&SO1uTL&jL&^}QV\F"vE{{w[|^8eWp#V$4&O̥KPv”zU** 6`6 h4b4ihhh42m4Mkk+$$$(s n-nOje`0({!!!*f~mwbݺu[v̿ 9r ***o{466R]]Mll2臚'P ρ\ʕ+޽\&MdB+D:_x>ϟ?q\6'Bj5:Nx M's2n8h4$%%1j(@p[qhZfΜIUU;/:A}P$ә9sϯ |A_jh멏@0&A@aq~!A@aTA'  PhP9IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/button_lighter_mid-over.png0000644000175000017500000000015511042177126025771 0ustar adrianadrianPNG  IHDRW4IDATxc0oL Lb`'~̅U/{0n0-IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/bullet_arrow_up.png0000644000175000017500000000030510535151164024340 0ustar adrianadrianPNG  IHDR#>SbKGD̿ pHYs  tIME &'y=VIDATxK؊ +   'UL IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/arrowSmall.gif0000644000175000017500000000126111100020266023224 0ustar adrianadrianGIF89asgs:y^ hw wYKrꉏ||~bلzi<{}wism񿈓ƂQt*dʌGEbsj;А| h,a%xx om+`~1/tJGNs v!_,fyao:!,wW\>iiKlIc5hXBMRgT~ )d*+ef~7$&}3O$kt1@A6PDN+|$6 o1L9 ;! ,(!'[m*2`KwFxGA< 3C )eРKvAÔ90بeD"Qㅑ8)WjhYB͑ 8_ptB, H4daJ!jUڧƓ r$J }q!M ;azureus-4.3.0.6/com/aelitis/azureus/ui/images/entry_news.png0000644000175000017500000000120111042177176023331 0ustar adrianadrianPNG  IHDRaHIDATxڕKUQ?R6(\,-Tx%AQ lR&r/PgQ^I#v}:q>{B  kַ6Q5嗝~- AP;r_l'$UAQ(xEwZt]*/)|ZfO_D. Hulku:Nn\XˬњhE5HҪEOQTm(B˨>Ybm!_Wx} ~B9xC5T5|﫬\aE:nG{F9[@CsxLM CLy@w>t8o*^-|Ү+KY>DA&F[-ٙeLN.[ϢX@;)3]R17O?yԝ;6>j|<5vHۧa)͍p'J[F)XФ(:M@N \3X[-ESdf 7wMQ5I0*IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/images/search_bg.png0000644000175000017500000000355311073414754023065 0ustar adrianadrianPNG  IHDRL y/AbKGD pHYs  tIME ,,dIDATxml[W\ڎ_2'$zh$ue ȺMH0]&TۚEH`IHҍo6B"J-u-%i`hUGnָIe!qbi$'=M{essUN8NCkTctq]p]x""A%o[k<`0VqLShka{xM5m{<}t"ZV8SV_*hk-JIg通Y<إ,Ol}GlJлmm-'NshR^0A,˙(jL]=E#2w9#i>15̞hb.1E Taέ# PSYlrkowU&2l} I%հ p)o|~v_7wW5Ɨ0@ v9) ViEvܱ ?§,]*Aʚ>jq~;Mys;[όͿ/w%Bm䕕/ p'?s> ";HziAL*jR;3_;铷TS{֭WMAK'>~N5ݥ[u8ڒ2F8X% ֡W q 9uQo_xw@$:8Q Lc+j:GuܔȍP$V`PI .r|r9?=>gy`!(IENDB`azureus-4.3.0.6/com/aelitis/azureus/ui/IUIIntializer.java0000644000175000017500000000371311171750564022520 0ustar adrianadrian/* * Created on May 29, 2006 3:06:06 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui; /** * @author TuxPaper * @created May 29, 2006 * */ public interface IUIIntializer { public void stopIt(boolean isForRestart, boolean isCloseAreadyInProgress); public void run(); /** * Add a listener that gets triggered on progress changes (tasks, percent) * * @param listener * * @since 3.0.1.3 */ public void addListener(InitializerListener listener); /** * Remove listener that gets triggered on progress changes (tasks, percent) * * @param listener * * @since 3.0.1.3 */ public void removeListener(InitializerListener listener); /** * * * @since 3.0.4.3 */ void increaseProgress(); /** * * @since 3.0.4.3 */ void abortProgress(); /** * @param currentTaskString * * @since 3.0.4.3 */ void reportCurrentTask(String currentTaskString); void reportPercent(int percent); void initializationComplete(); /** * Code that will be executed in the SWT Thread before {@link #run()} is * invoked * * @since 4.2.0.1 */ public void runInSWTThread(); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/0000755000175000017500000000000011310377632020001 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/UIFunctionsSWT.java0000644000175000017500000001006511223317136023446 0ustar adrianadrian/* * Created on Jul 12, 2006 3:11:00 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.plugins.PluginView; import org.gudy.azureus2.ui.swt.mainwindow.*; import org.gudy.azureus2.ui.swt.plugins.*; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl; import org.gudy.azureus2.ui.swt.views.AbstractIView; import org.gudy.azureus2.ui.swt.views.IView; import com.aelitis.azureus.ui.UIFunctions; /** * @author TuxPaper * @created Jul 12, 2006 * */ public interface UIFunctionsSWT extends UIFunctions { public static int MAIN_MENU_BAR = MainMenu.MENU_BAR; public static int MAIN_MENU_TRANSFER = MainMenu.MENU_TRANSFER; public Shell getMainShell(); /** * @param view */ void addPluginView(PluginView view); /** * @param view */ void openPluginView(PluginView view); /** * @param view */ public void openPluginView(UISWTPluginView view); /** * @param view */ void addPluginView(UISWTPluginView view); /** * @param view */ public void removePluginView(UISWTPluginView view); /** * @param viewID * @param l */ void addPluginView(String viewID, UISWTViewEventListener l); /** * */ public void closeDownloadBars(); public boolean isGlobalTransferBarShown(); public void showGlobalTransferBar(); public void closeGlobalTransferBar(); /** * @return */ public UISWTInstanceImpl getSWTPluginInstanceImpl(); /** * @return */ public UISWTView[] getPluginViews(); /** * * @param sParentID * @param sViewID * @param l * @param dataSource * @param bSetFocus */ public void openPluginView(String sParentID, String sViewID, UISWTViewEventListener l, Object dataSource, boolean bSetFocus); public void openPluginView(final AbstractIView view, final String name); /** * @param viewID */ public void removePluginView(String viewID); /** * @param impl */ public void closePluginView(IView view); public void closePluginViews(String sViewID); /** * @deprecated This method has been deprecated; menus should be retrieved directly * from an instance of IMainMenu. Because there may be multiple instances of IMainMenu * in the application this method will not be able to discern which menu to work with. * This is especially true for OSX where each shell has its own instance of IMainMenu. * @param id * @return */ public Menu getMenu(int id); public UISWTInstance getUISWTInstance(); public void refreshTorrentMenu(); public MainStatusBar getMainStatusBar(); /** * Creates the main application menu and attach it to the given Shell; * this is only used for OSX so that we can attach the global menu to popup dialogs which * is the expected behavior on OSX. Windows and Linux do not require this since they do not have * a global menu and because their main menu is already attached to the main application window. * @param shell * @return */ public IMainMenu createMainMenu(Shell shell); public IMainWindow getMainWindow(); /** * * * @since 3.1.1.1 */ public void closeAllDetails(); /** * @return * * @since 3.1.1.1 */ public boolean hasDetailViews(); public Shell showCoreWaitDlg(); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/toolbar/0000755000175000017500000000000011310377632021443 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/toolbar/ToolBarEnabler.java0000644000175000017500000000023111074501766025141 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.toolbar; import org.gudy.azureus2.ui.swt.IconBarEnabler; public interface ToolBarEnabler extends IconBarEnabler{ } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/toolbar/ToolBarItem.java0000644000175000017500000000636411076015140024470 0ustar adrianadrian/** * Created on Jul 22, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.toolbar; import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility; /** * @author TuxPaper * @created Jul 22, 2008 * */ public class ToolBarItem { String imageID; String id; private SWTSkinButtonUtility skinButton; boolean enabled = true; private String textID; private String tooltipID; private List listeners = Collections.EMPTY_LIST; /** * @param id * @param image */ public ToolBarItem(String id, String imageid) { super(); this.id = id; imageID = imageid; } public ToolBarItem(String id, String imageid, String textID) { super(); this.id = id; imageID = imageid; this.textID = textID; this.tooltipID = textID + ".tooltip"; } public void triggerToolBarItem() { Object[] array = listeners.toArray(); for (int i = 0; i < array.length; i++) { ToolBarItemListener l = (ToolBarItemListener) array[i]; l.pressed(this); } } public String getId() { return id; } public void setSkinButton(SWTSkinButtonUtility btn) { this.skinButton = btn; } public SWTSkinButtonUtility getSkinButton() { return skinButton; } public boolean isEnabled() { if (skinButton != null) { return !skinButton.isDisabled(); } return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; if (skinButton != null) { skinButton.setDisabled(!enabled); } } public String getImageID() { return imageID; } public void setImageID(String imageID) { this.imageID = imageID; } /** * @param textID the textID to set */ public void setTextID(String textID) { this.textID = textID; } /** * @return the textID */ public String getTextID() { return textID; } /** * @return * * @since 3.1.1.1 */ public boolean triggerToolBarItemHold() { Object[] array = listeners.toArray(); for (int i = 0; i < array.length; i++) { ToolBarItemListener l = (ToolBarItemListener) array[i]; if (l.held(this)) { return true; } } return false; } public String getTooltipID() { return tooltipID; } public void setTooltipID(String tooltipID) { this.tooltipID = tooltipID; } public void addListener(ToolBarItemListener l) { synchronized (ToolBarItem.class) { if (listeners == Collections.EMPTY_LIST) { listeners = new ArrayList(1); } listeners.add(l); } } public void removeListener(ToolBarItemListener l) { synchronized (ToolBarItem.class) { listeners.remove(l); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/toolbar/ToolBarEnablerSelectedContent.java0000644000175000017500000000217411167543450030154 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.toolbar; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.ui.swt.IconBarEnabler; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; public class ToolBarEnablerSelectedContent implements ISelectedContent { private IconBarEnabler enabler; public ToolBarEnablerSelectedContent(IconBarEnabler enabler) { this.enabler = enabler; } public DownloadManager getDownloadManager() { return null; } public TOTorrent getTorrent() { return null; } public String getDisplayName() { return ""; } public DownloadUrlInfo getDownloadInfo() { return null; } public String getHash() { return null; } public void setDownloadManager(DownloadManager dm) { } public void setTorrent(TOTorrent t ){ } public void setDisplayName(String displayName) { } public void setDownloadInfo(DownloadUrlInfo downloadInfo) { } public void setHash(String hash) { } public IconBarEnabler getIconBarEnabler() { return enabler; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/toolbar/ToolBarItemListener.java0000644000175000017500000000174411072433350026176 0ustar adrianadrian/** * Created on Oct 6, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.toolbar; /** * @author TuxPaper * @created Oct 6, 2008 * */ public interface ToolBarItemListener { public boolean held(ToolBarItem toolBarItem); public void pressed(ToolBarItem toolBarItem); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/UISkinnableManagerSWT.java0000644000175000017500000000423410577641404024711 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt; import java.util.*; /** * @author TuxPaper * @created Mar 18, 2007 * * TODO: seperate into class/impl */ public class UISkinnableManagerSWT { static UISkinnableManagerSWT instance = new UISkinnableManagerSWT(); public static UISkinnableManagerSWT getInstance() { return instance; } /** * Key: ID; * Value: ArrayList of UISkinnableSWTListener */ private Map mapSkinnables = new HashMap(); public UISkinnableSWTListener[] getSkinnableListeners(String id) { List listeners = (List) mapSkinnables.get(id); if (listeners == null) { return new UISkinnableSWTListener[0]; } UISkinnableSWTListener[] skinListeners = new UISkinnableSWTListener[listeners.size()]; skinListeners = (UISkinnableSWTListener[]) listeners.toArray(skinListeners); return skinListeners; } public void addSkinnableListener(String id, UISkinnableSWTListener l) { List listeners = (List) mapSkinnables.get(id); if (listeners == null) { listeners = new ArrayList(); listeners.add(l); mapSkinnables.put(id, listeners); } else { listeners.add(l); } } public void removeSkinnableListener(String id, UISkinnableSWTListener l) { List listeners = (List) mapSkinnables.get(id); if (listeners != null) { listeners.remove(l); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/UIFunctionsManagerSWT.java0000644000175000017500000000255410455543164024755 0ustar adrianadrian/* * Created on Jul 13, 2006 12:28:36 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; /** * @author TuxPaper * @created Jul 13, 2006 * */ public class UIFunctionsManagerSWT extends UIFunctionsManager { public static UIFunctionsSWT getUIFunctionsSWT() { UIFunctions uiFunctions = getUIFunctions(); if (uiFunctions instanceof UIFunctionsSWT) { return (UIFunctionsSWT)uiFunctions; } return null; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/0000755000175000017500000000000011310377556021466 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/subscriptions/0000755000175000017500000000000011310377632024370 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNbResults.java0000644000175000017500000000350611074035634032743 0ustar adrianadrian/** * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package com.aelitis.azureus.ui.swt.columns.subscriptions; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.subs.Subscription; /** * @author Olivier Chalouhi * @created Oct 7, 2008 * */ public class ColumnSubscriptionNbResults extends CoreTableColumn implements TableCellRefreshListener { public static String COLUMN_ID = "nb-results"; /** Default Constructor */ public ColumnSubscriptionNbResults(String sTableID) { super(COLUMN_ID, POSITION_LAST, 100, sTableID); setMinWidth(100); setMaxWidth(100); } public void refresh(TableCell cell) { int nbResults = 0; Subscription sub = (Subscription) cell.getDataSource(); if (sub != null) { nbResults = sub.getHistory().getNumUnread() + sub.getHistory().getNumRead(); } if (!cell.setSortValue(nbResults) && cell.isValid()) { return; } if (!cell.isShown()) { return; } cell.setText("" + nbResults); return; } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNbNewResults.javaazureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNbNewResults.java0000644000175000017500000000346011074035634033414 0ustar adrianadrian/** * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package com.aelitis.azureus.ui.swt.columns.subscriptions; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.subs.Subscription; /** * @author Olivier Chalouhi * @created Oct 7, 2008 * */ public class ColumnSubscriptionNbNewResults extends CoreTableColumn implements TableCellRefreshListener { public static String COLUMN_ID = "nb-new-results"; /** Default Constructor */ public ColumnSubscriptionNbNewResults(String sTableID) { super(COLUMN_ID, POSITION_LAST, 100, sTableID); setMinWidth(100); setMaxWidth(100); } public void refresh(TableCell cell) { int nbResults = 0; Subscription sub = (Subscription) cell.getDataSource(); if (sub != null) { nbResults = sub.getHistory().getNumUnread(); } if (!cell.setSortValue(nbResults) && cell.isValid()) { return; } if (!cell.isShown()) { return; } cell.setText("" + nbResults); return; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNew.java0000644000175000017500000000640411127403350031544 0ustar adrianadrian/** * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package com.aelitis.azureus.ui.swt.columns.subscriptions; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.activities.VuzeActivitiesEntry; import com.aelitis.azureus.core.subs.Subscription; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author Olivier Chalouhi * @created Oct 7, 2008 * */ public class ColumnSubscriptionNew extends CoreTableColumn implements TableCellRefreshListener,TableCellSWTPaintListener { public static final String COLUMN_ID = "new"; private static int WIDTH = 38; // enough to fit title private static Image imgNew; private Rectangle imgBounds; /** * @param name * @param tableID */ public ColumnSubscriptionNew(String tableID) { super(COLUMN_ID, tableID); initializeAsGraphic(WIDTH); setMinWidth(WIDTH); setMaxWidth(WIDTH); setVisible(true); imgNew = ImageLoader.getInstance().getImage("image.activity.unread"); imgBounds = imgNew.getBounds(); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellPaint(GC gc, TableCellSWT cell) { Subscription sub = (Subscription) cell.getDataSource(); if (sub.getHistory().getNumUnread() > 0) { Rectangle cellBounds = cell.getBounds(); gc.drawImage(imgNew, cellBounds.x + ((cellBounds.width - imgBounds.width) / 2), cellBounds.y + ((cellBounds.height - imgBounds.height) / 2)); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellAdded(TableCell cell) { cell.setMarginWidth(0); cell.setMarginHeight(0); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { Subscription sub = (Subscription) cell.getDataSource(); boolean isRead = sub.getHistory().getNumUnread() > 0; int sortVal = isRead ? 1 : 0; if (!cell.setSortValue(sortVal) && cell.isValid()) { return; } cell.invalidate(); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionCategory.java0000644000175000017500000000353211236650412032573 0ustar adrianadrian/** * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package com.aelitis.azureus.ui.swt.columns.subscriptions; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.subs.Subscription; /** * @author Olivier Chalouhi * @created Oct 7, 2008 * */ public class ColumnSubscriptionCategory extends CoreTableColumn implements TableCellRefreshListener { public static String COLUMN_ID = "category"; /** Default Constructor */ public ColumnSubscriptionCategory(String sTableID) { super(COLUMN_ID, POSITION_LAST, 100, sTableID); setMinWidth(100); setMaxWidth(100); } public void refresh(TableCell cell) { int nbResults = 0; Subscription sub = (Subscription) cell.getDataSource(); String category = null; if (sub != null) { category = sub.getCategory(); } if ( category == null ){ category = ""; } if (!cell.setSortValue(category) && cell.isValid()) { return; } if (!cell.isShown()) { return; } cell.setText(category); return; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionSubscribers.java0000644000175000017500000000347711157542626033325 0ustar adrianadrian/** * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package com.aelitis.azureus.ui.swt.columns.subscriptions; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.subs.Subscription; /** * @author Olivier Chalouhi * @created Oct 7, 2008 * */ public class ColumnSubscriptionSubscribers extends CoreTableColumn implements TableCellRefreshListener { public static String COLUMN_ID = "nb-subscribers"; /** Default Constructor */ public ColumnSubscriptionSubscribers(String sTableID) { super(COLUMN_ID, POSITION_INVISIBLE, 100, sTableID); setMinWidth(100); setMaxWidth(100); } public void refresh(TableCell cell) { int nbSubsribers = 0; Subscription sub = (Subscription) cell.getDataSource(); if (sub != null) { nbSubsribers = (int) sub.getCachedPopularity(); } if (!cell.setSortValue(nbSubsribers) && cell.isValid()) { return; } if (!cell.isShown()) { return; } cell.setText("" + nbSubsribers); return; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionName.java0000644000175000017500000000736211165533200031677 0ustar adrianadrian/** * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package com.aelitis.azureus.ui.swt.columns.subscriptions; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.subs.Subscription; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.subscriptions.SubscriptionManagerUI; import com.aelitis.azureus.ui.swt.subscriptions.SubscriptionManagerUI.sideBarItem; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author Olivier Chalouhi * @created Oct 7, 2008 * */ public class ColumnSubscriptionName extends CoreTableColumn implements TableCellRefreshListener, TableCellSWTPaintListener, TableCellMouseListener { public static String COLUMN_ID = "name"; int imageWidth = -1; int imageHeight = -1; /** Default Constructor */ public ColumnSubscriptionName(String sTableID) { super(COLUMN_ID, POSITION_LAST, 350, sTableID); setMinWidth(300); } public void refresh(TableCell cell) { String name = null; Subscription sub = (Subscription) cell.getDataSource(); if (sub != null) { name = sub.getName(); } if (name == null) { name = ""; } if (!cell.setSortValue(name) && cell.isValid()) { return; } if (!cell.isShown()) { return; } cell.setText(name); return; } public void cellPaint(GC gc, TableCellSWT cell) { Rectangle bounds = cell.getBounds(); ImageLoader imageLoader = ImageLoader.getInstance(); Image viewImage = imageLoader.getImage("ic_view"); if(imageWidth == -1 || imageHeight == -1) { imageWidth = viewImage.getBounds().width; imageHeight = viewImage.getBounds().height; } bounds.width -= (imageWidth + 5); GCStringPrinter.printString(gc, cell.getText(), bounds,true,false,SWT.LEFT); gc.drawImage(viewImage, bounds.x + bounds.width, bounds.y + bounds.height / 2 - imageHeight / 2); imageLoader.releaseImage("ic_view"); //gc.drawText(cell.getText(), bounds.x,bounds.y); } public void cellMouseTrigger(TableCellMouseEvent event) { if (event.eventType == TableCellMouseEvent.EVENT_MOUSEUP && event.button == 1) { TableCell cell = event.cell; int cellWidth = cell.getWidth(); if(event.x > cellWidth - imageWidth - 5 && event.x < cellWidth - 5) { Subscription sub = (Subscription) cell.getDataSource(); if(sub != null) { String key = "Subscription_" + ByteFormatter.encodeString(sub.getPublicKey()); SideBarEntrySWT entry = SideBar.getEntry(key); if (entry.isInTree()) { entry.getSidebar().showEntryByID(key); } } } } } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionAutoDownload.javaazureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionAutoDownload.java0000644000175000017500000000405011157767132033424 0ustar adrianadrian/** * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package com.aelitis.azureus.ui.swt.columns.subscriptions; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.subs.Subscription; import com.aelitis.azureus.core.subs.SubscriptionHistory; /** * @author Olivier Chalouhi * @created Mar 15, 2009 * */ public class ColumnSubscriptionAutoDownload extends CoreTableColumn implements TableCellRefreshListener { public static String COLUMN_ID = "auto-download"; /** Default Constructor */ public ColumnSubscriptionAutoDownload(String sTableID) { super(COLUMN_ID, ALIGN_CENTER, POSITION_LAST, 100, sTableID); setMinWidth(100); setMaxWidth(100); } public void refresh(TableCell cell) { boolean autoDownload = false; Subscription sub = (Subscription) cell.getDataSource(); if (sub != null) { SubscriptionHistory history = sub.getHistory(); if(history != null) { autoDownload = history.isAutoDownload(); } } if (!cell.setSortValue(autoDownload) && cell.isValid()) { return; } if (!cell.isShown()) { return; } cell.setText( DisplayFormatters.getYesNo( autoDownload )); return; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionLastChecked.java0000644000175000017500000000365611232555020033172 0ustar adrianadrian/** * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package com.aelitis.azureus.ui.swt.columns.subscriptions; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator; import org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer; import com.aelitis.azureus.core.subs.Subscription; /** * @author Olivier Chalouhi * @created Oct 7, 2008 * */ public class ColumnSubscriptionLastChecked extends ColumnDateSizer { public static String COLUMN_ID = "last-checked"; public ColumnSubscriptionLastChecked( String sTableID ) { super(Subscription.class, COLUMN_ID, TableColumnCreator.DATE_COLUMN_WIDTH, sTableID); setMinWidth(100); setMultiline( false ); setShowTime( true ); } public void refresh( TableCell cell, long timestamp ) { timestamp = 0; Subscription sub = (Subscription) cell.getDataSource(); if ( sub != null ){ timestamp = sub.getHistory().getLastScanTime(); } if (!cell.setSortValue(timestamp) && cell.isValid()) { return; } if (!cell.isShown()) { return; } if ( timestamp <= 0 ){ cell.setText( "--" ); }else{ super.refresh( cell, timestamp ); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/torrent/0000755000175000017500000000000011310377632023156 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbAndName.java0000644000175000017500000002234711300657702027510 0ustar adrianadrian/* * File : NameItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.columns.torrent; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.UIInputReceiver; import org.gudy.azureus2.plugins.ui.UIInputReceiverListener; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.menus.MenuItemListener; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow; import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3; import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3.ContentImageLoadedListener; /** Torrent name cell for My Torrents. * * @author Olivier * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter) */ public class ColumnThumbAndName extends CoreTableColumn implements TableCellLightRefreshListener, ObfusticateCellText, TableCellDisposeListener, TableCellSWTPaintListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "name"; private boolean showIcon; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_ESSENTIAL, CAT_CONTENT }); } /** * * @param sTableID */ public ColumnThumbAndName(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 250, sTableID); setObfustication(true); setRefreshInterval(INTERVAL_LIVE); initializeAsGraphic(250); setMinWidth(100); TableContextMenuItem menuItem = addContextMenuItem("MyTorrentsView.menu.rename.displayed"); menuItem.addMultiListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target == null) { return; } Object[] o = (Object[]) target; for (Object object : o) { if (object instanceof DownloadManager) { final DownloadManager dm = (DownloadManager) object; String msg_key_prefix = "MyTorrentsView.menu.rename.displayed.enter."; SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow( msg_key_prefix + "title", msg_key_prefix + "message"); entryWindow.setPreenteredText(dm.getDisplayName(), false); entryWindow.prompt(new UIInputReceiverListener() { public void UIInputReceiverClosed(UIInputReceiver entryWindow) { if (!entryWindow.hasSubmittedInput()) { return; } String value = entryWindow.getSubmittedInput(); if (value != null && value.length() > 0) { dm.getDownloadState().setDisplayName(value); } } }); } } } }); COConfigurationManager.addAndFireParameterListener( "NameColumn.showProgramIcon", new ParameterListener() { public void parameterChanged(String parameterName) { setShowIcon(COConfigurationManager.getBooleanParameter("NameColumn.showProgramIcon")); } }); } public void refresh(TableCell cell) { refresh(cell, false); } public void refresh(TableCell cell, boolean sortOnlyRefresh) { String name = null; DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm != null) { name = dm.getDisplayName(); } if (name == null) { name = ""; } cell.setSortValue(name); } public void cellPaint(GC gc, final TableCellSWT cell) { Object ds = cell.getDataSource(); Rectangle cellBounds = cell.getBounds(); int textX = cellBounds.x; if (!showIcon) { cellPaintName(cell, gc, cellBounds, textX); return; } Image[] imgThumbnail = TorrentUIUtilsV3.getContentImage(ds, cellBounds.height >= 20, new ContentImageLoadedListener() { public void contentImageLoaded(Image image, boolean wasReturned) { if (!wasReturned) { // this may be triggered many times, so only invalidate and don't // force a refresh() cell.invalidate(); } } }); if (imgThumbnail != null && ImageLoader.isRealImage(imgThumbnail[0])) { try { if (cellBounds.height > 30) { cellBounds.y += 1; cellBounds.height -= 3; } Rectangle imgBounds = imgThumbnail[0].getBounds(); int dstWidth; int dstHeight; if (imgBounds.height > cellBounds.height) { dstHeight = cellBounds.height; dstWidth = imgBounds.width * cellBounds.height / imgBounds.height; } else if (imgBounds.width > cellBounds.width) { dstWidth = cellBounds.width - 4; dstHeight = imgBounds.height * cellBounds.width / imgBounds.width; } else { dstWidth = imgBounds.width; dstHeight = imgBounds.height; } if (cellBounds.height <= 18) { dstWidth = Math.min(dstWidth, cellBounds.height); dstHeight = Math.min(dstHeight, cellBounds.height); if (imgBounds.width > 16) { cellBounds.y++; dstHeight -= 2; } } try { gc.setAdvanced(true); gc.setInterpolation(SWT.HIGH); } catch (Exception e) { } int x = cellBounds.x; textX = x + dstWidth + 3; int minWidth = dstHeight * 7 / 4; int imgPad = 0; if (dstHeight > 25) { if (dstWidth < minWidth) { imgPad = ((minWidth - dstWidth + 1) / 2); x = cellBounds.x + imgPad; textX = cellBounds.x + minWidth + 3; } } if (cellBounds.width - dstWidth - (imgPad * 2) < 100 && dstHeight > 18) { dstWidth = Math.min(32, dstHeight); x = cellBounds.x + ((32 - dstWidth + 1) / 2); dstHeight = imgBounds.height * dstWidth / imgBounds.width; textX = cellBounds.x + dstWidth + 3; } int y = cellBounds.y + ((cellBounds.height - dstHeight + 1) / 2); if (dstWidth > 0 && dstHeight > 0 && !imgBounds.isEmpty()) { Rectangle dst = new Rectangle(x, y, dstWidth, dstHeight); Rectangle lastClipping = gc.getClipping(); try { gc.setClipping(cellBounds); for (int i = 0; i < imgThumbnail.length; i++) { Image image = imgThumbnail[i]; if (image == null || image.isDisposed()) { continue; } Rectangle srcBounds = image.getBounds(); if (i == 0) { int w = dstWidth; int h = dstHeight; if (imgThumbnail.length > 1) { w = w * 9 / 10; h = h * 9 / 10; } gc.drawImage(image, srcBounds.x, srcBounds.y, srcBounds.width, srcBounds.height, x, y, w, h); } else { int w = dstWidth * 3 / 8; int h = dstHeight * 3 / 8; gc.drawImage(image, srcBounds.x, srcBounds.y, srcBounds.width, srcBounds.height, x + dstWidth - w, y + dstHeight - h, w, h); } } } catch (Exception e) { Debug.out(e); } finally { gc.setClipping(lastClipping); } } TorrentUIUtilsV3.releaseContentImage(ds); } catch (Throwable t) { Debug.out(t); } } cellPaintName(cell, gc, cellBounds, textX); } private void cellPaintName(TableCell cell, GC gc, Rectangle cellBounds, int textX) { String name = null; DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm != null) name = dm.getDisplayName(); if (name == null) name = ""; GCStringPrinter.printString(gc, name, new Rectangle(textX, cellBounds.y, cellBounds.x + cellBounds.width - textX, cellBounds.height), true, true, SWT.WRAP); } public String getObfusticatedText(TableCell cell) { String name = null; DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm != null) { name = dm.toString(); int i = name.indexOf('#'); if (i > 0) { name = name.substring(i + 1); } } if (name == null) name = ""; return name; } public void dispose(TableCell cell) { } /** * @param showIcon the showIcon to set */ public void setShowIcon(boolean showIcon) { this.showIcon = showIcon; } /** * @return the showIcon */ public boolean isShowIcon() { return showIcon; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/torrent/ColumnProgressETA.java0000644000175000017500000002536211274201302027332 0ustar adrianadrian/** * */ package com.aelitis.azureus.ui.swt.columns.torrent; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.download.DownloadManagerEnhancer; import com.aelitis.azureus.core.download.EnhancedDownloadManager; import com.aelitis.azureus.ui.common.table.TableRowCore; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory; import com.aelitis.azureus.ui.swt.skin.SWTSkinProperties; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Jun 13, 2006 * */ public class ColumnProgressETA extends CoreTableColumn implements TableCellAddedListener, TableCellMouseListener { public static final Class DATASOURCE_TYPE = DownloadTypeIncomplete.class; public static final String COLUMN_ID = "ProgressETA"; private static final int borderWidth = 1; private static final int COLUMN_WIDTH = 150; public static final long SHOW_ETA_AFTER_MS = 30000; private final static Object CLICK_KEY = new Object(); private static Font fontText = null; Display display; private Color cBG; private Color cFG; private Color cBorder; private Color cText; Color textColor; /** * */ public ColumnProgressETA(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, COLUMN_WIDTH, sTableID); initializeAsGraphic(COLUMN_WIDTH); setAlignment(ALIGN_LEAD); setMinWidth(COLUMN_WIDTH); display = SWTThread.getInstance().getDisplay(); SWTSkinProperties skinProperties = SWTSkinFactory.getInstance().getSkinProperties(); cBG = skinProperties.getColor("color.progress.bg"); if (cBG == null) { cBG = Colors.blues[Colors.BLUES_DARKEST]; } cFG = skinProperties.getColor("color.progress.fg"); if (cFG == null) { cFG = Colors.blues[Colors.BLUES_LIGHTEST]; } cBorder = skinProperties.getColor("color.progress.border"); if (cBorder == null) { cBorder = Colors.grey; } cText = skinProperties.getColor("color.progress.text"); if (cText == null) { cText = Colors.black; } } public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, CAT_ESSENTIAL, CAT_TIME, }); } public void cellAdded(TableCell cell) { new Cell(cell); } public void cellMouseTrigger(TableCellMouseEvent event) { DownloadManager dm = (DownloadManager) event.cell.getDataSource(); if (dm == null) { return; } String clickable = (String) dm.getUserData(CLICK_KEY); if (clickable == null) { return; } event.skipCoreFunctionality = true; if (event.eventType == TableCellMouseEvent.EVENT_MOUSEUP) { String url = UrlUtils.getURL(clickable); if (url != null) { Utils.launch(url); } } } private class Cell implements TableCellRefreshListener, TableCellSWTPaintListener { private static final int MAX_PROGRESS_FILL_HEIGHT = 19; int lastPercentDone = 0; long lastETA; public Cell(TableCell cell) { cell.addListeners(this); cell.setMarginHeight(3); } public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm == null) { return; } int percentDone = getPercentDone(cell); long sortValue = 0; long completedTime = dm.getDownloadState().getLongParameter( DownloadManagerState.PARAM_DOWNLOAD_COMPLETED_TIME); if (completedTime <= 0 || !dm.isDownloadComplete(false)) { sortValue = Long.MAX_VALUE - 10000 + percentDone; } else { sortValue = completedTime; } long eta = getETA(cell); if (!cell.setSortValue(sortValue) && cell.isValid() && lastPercentDone == percentDone && lastETA == eta) { return; } lastPercentDone = percentDone; lastETA = eta; cell.invalidate(); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT) public void cellPaint(GC gc, TableCellSWT cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm == null) { return; } int percentDone = getPercentDone(cell); long eta = getETA(cell); //Compute bounds ... int newWidth = cell.getWidth(); if (newWidth <= 0) { return; } int newHeight = cell.getHeight(); Color fgFirst = gc.getForeground(); Rectangle cellBounds = cell.getBounds(); int xStart = cellBounds.x + cell.getMarginWidth(); int yStart = cellBounds.y + cell.getMarginHeight(); int xRelProgressFillStart = borderWidth; int yRelProgressFillStart = borderWidth; int xRelProgressFillEnd = newWidth - xRelProgressFillStart - borderWidth; int yRelProgressFillEnd = yRelProgressFillStart + 13; boolean showSecondLine = yRelProgressFillEnd + 10 < newHeight; if (xRelProgressFillEnd < 10 || xRelProgressFillEnd < 10) { return; } boolean bDrawProgressBar = true; String sETALine = null; // Draw Progress bar if (bDrawProgressBar && percentDone < 1000) { ImageLoader imageLoader = ImageLoader.getInstance(); Image imgEnd = imageLoader.getImage("dl_bar_end"); Image img0 = imageLoader.getImage("dl_bar_0"); Image img1 = imageLoader.getImage("dl_bar_1"); gc.drawImage(imgEnd, xStart, yStart + yRelProgressFillStart); gc.drawImage(imgEnd, xStart + xRelProgressFillEnd - xRelProgressFillStart + 1, yStart + yRelProgressFillStart); int limit = ((xRelProgressFillEnd - xRelProgressFillStart) * percentDone) / 1000; gc.drawImage(img1, 0, 0, 1, 13, xStart + xRelProgressFillStart, yStart + yRelProgressFillStart, limit, 13); if (limit < xRelProgressFillEnd) { gc.drawImage(img0, 0, 0, 1, 13, xStart + limit + 1, yStart + yRelProgressFillStart, xRelProgressFillEnd - limit - 1, 13); } imageLoader.releaseImage("dl_bar_end"); imageLoader.releaseImage("dl_bar_0"); imageLoader.releaseImage("dl_bar_1"); } if (sETALine == null) { if (dm.isUnauthorisedOnTracker()) { sETALine = dm.getTrackerStatus(); // fgFirst = Colors.colorError; pftt, no colours allowed apparently } else { if (dm.isDownloadComplete(true)) { //sETALine = DisplayFormatters.formatByteCountToKiBEtc(dm.getSize()); } else if (eta > 0) { String sETA = TimeFormatter.format(eta); sETALine = MessageText.getString( "MyTorrents.column.ColumnProgressETA.2ndLine", new String[] { sETA }); } else { sETALine = DisplayFormatters.formatDownloadStatus(dm); } } int cursor_id; if (sETALine != null && sETALine.indexOf("http://") == -1) { dm.setUserData(CLICK_KEY, null); cursor_id = SWT.CURSOR_ARROW; } else { dm.setUserData(CLICK_KEY, sETALine); cursor_id = SWT.CURSOR_HAND; if (!cell.getTableRow().isSelected()) { fgFirst = Colors.blue; } } ((TableCellSWT) cell).setCursorID(cursor_id); } if (fontText == null) { fontText = Utils.getFontWithHeight(gc.getFont(), gc, 11); } gc.setTextAntialias(SWT.ON); gc.setFont(fontText); if (showSecondLine && sETALine != null) { gc.setForeground(fgFirst); boolean over = GCStringPrinter.printString(gc, sETALine, new Rectangle( xStart + 2, yStart + yRelProgressFillEnd, xRelProgressFillEnd, newHeight - yRelProgressFillEnd), true, false, SWT.CENTER); cell.setToolTip(over ? sETALine : null); } int middleY = (yRelProgressFillEnd - 12) / 2; if (percentDone == 1000) { gc.setForeground(fgFirst); long value; long completedTime = dm.getDownloadState().getLongParameter( DownloadManagerState.PARAM_DOWNLOAD_COMPLETED_TIME); if (completedTime <= 0) { value = dm.getDownloadState().getLongParameter( DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME); } else { value = completedTime; } String s = "Completed on " + DisplayFormatters.formatDateShort(value); GCStringPrinter.printString(gc, s, new Rectangle(xStart + 2, yStart, newWidth - 4, newHeight), true, false, SWT.WRAP); } else if (bDrawProgressBar) { long lSpeed = getSpeed(dm); String sSpeed = lSpeed <= 0 ? "" : "(" + DisplayFormatters.formatByteCountToKiBEtcPerSec(lSpeed, true) + ")"; gc.setForeground(cText); String sPercent = DisplayFormatters.formatPercentFromThousands(percentDone); gc.drawText(sSpeed, xStart + 50, yStart + yRelProgressFillStart + 1, true); gc.drawText(sPercent, xStart + 2, yStart + yRelProgressFillStart + 1, true); } gc.setFont(null); } private int getPercentDone(TableCell cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm == null) { return 0; } return dm.getStats().getDownloadCompleted(true); } private long getETA(TableCell cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm == null) { return 0; } long diff = SystemTime.getCurrentTime() - dm.getStats().getTimeStarted(); if (diff > SHOW_ETA_AFTER_MS) { return dm.getStats().getETA(); } return 0; } private int getState(TableCell cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm == null) { return DownloadManager.STATE_ERROR; } return dm.getState(); } private boolean isStopped(TableCell cell) { int state = getState(cell); return state == DownloadManager.STATE_QUEUED || state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_STOPPING || state == DownloadManager.STATE_ERROR; } private long getSpeed(DownloadManager dm) { if (dm == null) { return 0; } return dm.getStats().getDataReceiveRate(); } public EnhancedDownloadManager getEDM(DownloadManager dm) { DownloadManagerEnhancer dmEnhancer = DownloadManagerEnhancer.getSingleton(); if (dmEnhancer == null) { return null; } return dmEnhancer.getEnhancedDownload(dm); } private void log(TableCell cell, String s) { System.out.println(((TableRowCore) cell.getTableRow()).getIndex() + ":" + System.currentTimeMillis() + ": " + s); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbnail.java0000644000175000017500000001707211274205122027122 0ustar adrianadrian/* * File : HealthItem.java * Created : 24 nov. 2003 * By : Olivier * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.columns.torrent; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.ui.common.table.impl.TableColumnImpl; import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3; import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3.ContentImageLoadedListener; import com.aelitis.azureus.util.DataSourceUtils; import org.gudy.azureus2.plugins.ui.tables.*; /** * A non-interactive (no click no hover) thumbnail column * @author khai * */ public class ColumnThumbnail extends CoreTableColumn implements TableCellRefreshListener, TableCellSWTPaintListener, TableCellToolTipListener { public static final String COLUMN_ID = "Thumbnail"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT }); } private static final int WIDTH_SMALL = 35; private static final int WIDTH_BIG = 60; private static final int WIDTH_ACTIVITY = 80; /** * Each cell is mapped to a torrent */ private Map mapCellTorrent = new HashMap(); /** Default Constructor */ public ColumnThumbnail(String sTableID) { super(COLUMN_ID, ALIGN_CENTER, POSITION_LAST, 0, sTableID); if (TableManager.TABLE_ACTIVITY_BIG.equals(sTableID)) { initializeAsGraphic(WIDTH_ACTIVITY); } else { initializeAsGraphic(sTableID.endsWith(".big") ? WIDTH_BIG : WIDTH_SMALL); } } /** * @param column */ public ColumnThumbnail(TableColumn column) { super(null, null); column.initialize(ALIGN_CENTER, POSITION_LAST, WIDTH_BIG); column.addListeners(this); // cheat. TODO: Either auto-add (in above method), or provide // access via TableColumn instead of type casting ((TableColumnImpl)column).addCellOtherListener("SWTPaint", this); } public void dispose(TableCell cell) { mapCellTorrent.remove(cell); } public void refresh(final TableCell cell) { Object ds = cell.getDataSource(); TOTorrent newTorrent = DataSourceUtils.getTorrent(ds); //System.out.println("REF"); //TableCellImpl c1 = ((TableCellImpl) cell); //TableRowSWT tableRowSWT = c1.getTableRowSWT(); //TableViewSWTImpl view = (TableViewSWTImpl) tableRowSWT.getView(); //System.out.println(view.getComposite()); //view.getTableComposite().redraw(0, 0, 5000, 5000, true); //view.getTableComposite().update(); /* * For sorting we only create 2 buckets... Vuze content and non-vuze content */ long sortIndex = PlatformTorrentUtils.isContent(newTorrent, true) ? 0 : 1; boolean bChanged = cell.setSortValue(sortIndex); /* * Get the torrent for this cell */ TOTorrent torrent = (TOTorrent) mapCellTorrent.get(cell); /* * If the cell is not shown or nothing has changed then skip since there's nothing to update */ if (false == cell.isShown() || (newTorrent == torrent && !bChanged && cell.isValid())) { return; } torrent = newTorrent; mapCellTorrent.put(cell, torrent); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT) public void cellPaint(GC gc, final TableCellSWT cell) { Object ds = cell.getDataSource(); Rectangle cellBounds = cell.getBounds(); Image[] imgThumbnail = TorrentUIUtilsV3.getContentImage(ds, cellBounds.width >= 20 && cellBounds.height >= 20, new ContentImageLoadedListener() { public void contentImageLoaded(Image image, boolean wasReturned) { if (!wasReturned) { // this may be triggered many times, so only invalidate and don't // force a refresh() cell.invalidate(); } } }); if (imgThumbnail == null) { // don't need to release a null image return; } if (cellBounds.height > 30) { cellBounds.y += 2; cellBounds.height -= 4; } Rectangle imgBounds = imgThumbnail[0].getBounds(); int dstWidth; int dstHeight; if (imgBounds.height > cellBounds.height) { dstHeight = cellBounds.height; dstWidth = imgBounds.width * cellBounds.height / imgBounds.height; } else if (imgBounds.width > cellBounds.width) { dstWidth = cellBounds.width - 4; dstHeight = imgBounds.height * cellBounds.width / imgBounds.width; } else { dstWidth = imgBounds.width; dstHeight = imgBounds.height; } try { gc.setAdvanced(true); gc.setInterpolation(SWT.HIGH); } catch (Exception e) { } int x = cellBounds.x + ((cellBounds.width - dstWidth + 1) / 2); int y = cellBounds.y + ((cellBounds.height - dstHeight + 1) / 2); if (dstWidth > 0 && dstHeight > 0 && !imgBounds.isEmpty()) { Rectangle dst = new Rectangle(x, y, dstWidth, dstHeight); Rectangle lastClipping = gc.getClipping(); try { gc.setClipping(cellBounds); for (int i = 0; i < imgThumbnail.length; i++) { Image image = imgThumbnail[i]; Rectangle srcBounds = image.getBounds(); if (i == 0) { int w = dstWidth; int h = dstHeight; if (imgThumbnail.length > 1) { w = w * 9 / 10; h = h * 9 / 10; } gc.drawImage(image, srcBounds.x, srcBounds.y, srcBounds.width, srcBounds.height, x, y, w, h); } else { int w = dstWidth * 3 / 8; int h = dstHeight * 3 / 8; gc.drawImage(image, srcBounds.x, srcBounds.y, srcBounds.width, srcBounds.height, x + dstWidth - w, y + dstHeight - h, w, h); } } } catch (Exception e) { Debug.out(e); } finally { gc.setClipping(lastClipping); } } TorrentUIUtilsV3.releaseContentImage(ds); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHover(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellHover(TableCell cell) { final Object ds = cell.getDataSource(); Image[] imgThumbnail = TorrentUIUtilsV3.getContentImage(ds, true, new ContentImageLoadedListener() { public void contentImageLoaded(Image image, boolean wasReturned) { TorrentUIUtilsV3.releaseContentImage(ds); } }); cell.setToolTip(imgThumbnail == null ? null : imgThumbnail[0]); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHoverComplete(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellHoverComplete(TableCell cell) { Object ds = cell.getDataSource(); TorrentUIUtilsV3.releaseContentImage(ds); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/torrent/ColumnControls.java0000644000175000017500000001601211135264370027001 0ustar adrianadrian/** * Created on April 28, 2007 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.columns.torrent; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.ui.common.table.TableRowCore; import com.aelitis.azureus.ui.swt.columns.utils.ColumnImageClickArea; import com.aelitis.azureus.ui.swt.utils.ColorCache; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.Graphic; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Apr 28, 2007 * */ public class ColumnControls extends CoreTableColumn implements TableCellAddedListener { public static final Class DATASOURCE_TYPE = Download.class; public static String COLUMN_ID = "Controls"; private static final int COLUMN_WIDTH = 32; private static final boolean DEBUG = false; private Display display; public static Font fontText; List listClickAreas = new ArrayList(); public ColumnControls(String sTableID) { super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, COLUMN_WIDTH, sTableID); initializeAsGraphic(COLUMN_WIDTH); setMinWidth(COLUMN_WIDTH); setMaxWidth(COLUMN_WIDTH); display = SWTThread.getInstance().getDisplay(); ColumnImageClickArea clickArea; clickArea = new ColumnImageClickArea(COLUMN_ID, "up", "image.torrent.up"); clickArea.setPosition(0, 0); listClickAreas.add(clickArea); clickArea = new ColumnImageClickArea(COLUMN_ID, "down", "image.torrent.down"); clickArea.setPosition(16, 0); listClickAreas.add(clickArea); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellAdded(TableCell cell) { new Cell(cell); } private class Cell implements TableCellRefreshListener, TableCellDisposeListener, TableCellMouseListener, TableCellVisibilityListener { public Cell(TableCell cell) { cell.addListeners(this); cell.setMarginHeight(1); cell.setMarginWidth(0); cell.setFillCell(true); for (Iterator iter = listClickAreas.iterator(); iter.hasNext();) { ColumnImageClickArea clickArea = (ColumnImageClickArea) iter.next(); clickArea.addCell(cell); } } public void dispose(TableCell cell) { disposeExisting(cell); } public void refresh(TableCell cell) { refresh(cell, false); } private void refresh(TableCell cell, boolean bForce) { DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm == null) { disposeExisting(cell); return; } int position = dm.getPosition(); int cellWidth = cell.getWidth(); int cellHeight = cell.getHeight(); Image image = null; Graphic graphic = cell.getGraphic(); if (graphic instanceof UISWTGraphic) { image = ((UISWTGraphic)graphic).getImage(); } if (image != null) { Rectangle bounds = image.getBounds(); if (!cell.setSortValue(position) && cell.isValid() && bounds.width == cellWidth && bounds.height == cellHeight) { return; } } else { cell.setSortValue(position); } disposeExisting(cell); image = new Image(display, cellWidth, cellHeight); GC gcImage = new GC(image); try { Color background = ColorCache.getColor(display, cell.getBackground()); if (background != null) { gcImage.setBackground(background); gcImage.fillRectangle(0, 0, cellWidth, cellHeight); } // if (fontText == null) { // fontText = Utils.getFontWithHeight(gcImage.getFont(), gcImage, 15); // } // gcImage.setFont(fontText); int[] fg = cell.getForeground(); gcImage.setForeground(ColorCache.getColor(display, fg[0], fg[1], fg[2])); Rectangle bounds = image.getBounds(); GCStringPrinter.printString(gcImage, "" + position + (dm.getAssumedComplete() ? "^" : "v"), bounds, true, false, SWT.BOTTOM | SWT.CENTER); gcImage.setFont(null); for (Iterator iter = listClickAreas.iterator(); iter.hasNext();) { ColumnImageClickArea clickArea = (ColumnImageClickArea) iter.next(); clickArea.drawImage(cell, gcImage); } } finally { gcImage.dispose(); } disposeExisting(cell); if (cell instanceof TableCellSWT) { ((TableCellSWT) cell).setGraphic(image); } else { cell.setGraphic(new UISWTGraphicImpl(image)); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellMouseListener#cellMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent) public void cellMouseTrigger(TableCellMouseEvent event) { if (event.data instanceof ColumnImageClickArea) { DownloadManager dm = (DownloadManager) event.cell.getDataSource(); if (dm == null) { return; } ColumnImageClickArea clickArea = (ColumnImageClickArea) event.data; log(event.cell, "CLICK ON " + clickArea.getId()); if (clickArea.getId().equals("up")) { dm.getGlobalManager().moveUp(dm); } else if (clickArea.getId().equals("down")) { dm.getGlobalManager().moveDown(dm); } event.cell.getTableColumn().invalidateCells(); } } public void cellVisibilityChanged(TableCell cell, int visibility) { if (visibility == TableCellVisibilityListener.VISIBILITY_HIDDEN) { //log(cell, "whoo, save"); disposeExisting(cell); } else if (visibility == TableCellVisibilityListener.VISIBILITY_SHOWN) { //log(cell, "whoo, draw"); refresh(cell, true); } } private void disposeExisting(TableCell cell) { Graphic oldGraphic = cell.getGraphic(); //log(cell, oldGraphic); if (oldGraphic instanceof UISWTGraphic) { Image oldImage = ((UISWTGraphic) oldGraphic).getImage(); if (oldImage != null && !oldImage.isDisposed()) { //log(cell, "dispose"); cell.setGraphic(null); oldImage.dispose(); } } } private void log(TableCell cell, String s) { if (!DEBUG) { return; } System.out.println(((TableRowCore) cell.getTableRow()).getIndex() + ":" + System.currentTimeMillis() + ": " + s); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/torrent/ColumnUnopened.java0000644000175000017500000001075711135264370026765 0ustar adrianadrian/** * Created on Sep 19, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.columns.torrent; import org.eclipse.swt.graphics.Image; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Sep 19, 2008 * */ public class ColumnUnopened extends CoreTableColumn implements TableCellAddedListener, TableCellRefreshListener, TableCellMouseListener { public static final Class DATASOURCE_TYPE = Download.class; public static final String COLUMN_ID = "unopened"; public void fillTableColumnInfo(TableColumnInfo info) { info.addCategories(new String[] { CAT_CONTENT, CAT_ESSENTIAL }); } private static UISWTGraphicImpl graphicCheck; private static UISWTGraphicImpl graphicUnCheck; private static UISWTGraphicImpl[] graphicsProgress; private static int WIDTH = 38; // enough to fit title /** * @param name * @param tableID */ public ColumnUnopened(String tableID) { super(COLUMN_ID, tableID); if (graphicCheck == null) { Image img = ImageLoader.getInstance().getImage("image.unopened"); graphicCheck = new UISWTGraphicImpl(img); } if (graphicUnCheck == null) { Image img = ImageLoader.getInstance().getImage("image.opened"); graphicUnCheck = new UISWTGraphicImpl(img); } if (graphicsProgress == null) { Image[] imgs = ImageLoader.getInstance().getImages("image.sidebar.vitality.dl"); graphicsProgress = new UISWTGraphicImpl[imgs.length]; for(int i = 0 ; i < imgs.length ; i++) { graphicsProgress[i] = new UISWTGraphicImpl(imgs[i]); } } initializeAsGraphic(WIDTH); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellAdded(TableCell cell) { cell.setMarginWidth(0); cell.setMarginHeight(0); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { DownloadManager dm = (DownloadManager) cell.getDataSource(); if (dm == null) { return; } int sortVal; boolean complete = dm.getAssumedComplete(); boolean hasBeenOpened = false; if (complete) { hasBeenOpened = PlatformTorrentUtils.getHasBeenOpened(dm); sortVal = hasBeenOpened ? 1 : 0; } else { sortVal = isSortAscending()?2:-1; } if (!cell.setSortValue(sortVal) && cell.isValid()) { if(complete) { return; } } if (!cell.isShown()) { return; } if (complete) { cell.setGraphic(hasBeenOpened ? graphicUnCheck : graphicCheck); } else { if(dm.getState() == DownloadManager.STATE_DOWNLOADING) { int i = TableCellRefresher.getRefreshIndex(1, graphicsProgress.length); cell.setGraphic(graphicsProgress[i]); TableCellRefresher.addCell(this, cell); } else { cell.setGraphic(null); } } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellMouseListener#cellMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent) public void cellMouseTrigger(TableCellMouseEvent event) { if (event.eventType == TableRowMouseEvent.EVENT_MOUSEUP && event.button == 1) { DownloadManager dm = (DownloadManager) event.cell.getDataSource(); boolean complete = dm.getAssumedComplete(); if(!complete) return; boolean hasBeenOpened = !PlatformTorrentUtils.getHasBeenOpened(dm); PlatformTorrentUtils.setHasBeenOpened(dm, hasBeenOpened); event.cell.setGraphic(hasBeenOpened ? graphicUnCheck : graphicCheck); event.cell.invalidate(); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/vuzeactivity/0000755000175000017500000000000011310377632024227 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityNew.java0000644000175000017500000000727511272502272030526 0ustar adrianadrian/** * Created on Sep 25, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.columns.vuzeactivity; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.activities.VuzeActivitiesEntry; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Sep 25, 2008 * */ public class ColumnActivityNew extends CoreTableColumn implements TableCellSWTPaintListener, TableCellAddedListener, TableCellRefreshListener, TableCellMouseListener { public static final String COLUMN_ID = "activityNew"; private static int WIDTH = 38; // enough to fit title private static Image imgNew; private static Image imgOld; /** * @param name * @param tableID */ public ColumnActivityNew(String tableID) { super(COLUMN_ID, tableID); initializeAsGraphic(WIDTH); setAlignment(ALIGN_CENTER); imgNew = ImageLoader.getInstance().getImage("image.activity.unread"); imgOld = ImageLoader.getInstance().getImage("image.activity.read"); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellPaint(GC gc, TableCellSWT cell) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) cell.getDataSource(); Rectangle cellBounds = cell.getBounds(); Image img = entry.getReadOn() <= 0 ? imgNew : imgOld; if (img != null && !img.isDisposed()) { Rectangle imgBounds = img.getBounds(); gc.drawImage(img, cellBounds.x + ((cellBounds.width - imgBounds.width) / 2), cellBounds.y + ((cellBounds.height - imgBounds.height) / 2)); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellAdded(TableCell cell) { cell.setMarginWidth(0); cell.setMarginHeight(0); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) cell.getDataSource(); boolean isRead = entry.getReadOn() > 0; int sortVal = isRead ? 1 : 0; if (!cell.setSortValue(sortVal) && cell.isValid()) { return; } cell.invalidate(); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellMouseListener#cellMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent) public void cellMouseTrigger(final TableCellMouseEvent event) { if (event.eventType == TableRowMouseEvent.EVENT_MOUSEDOWN && event.button == 1) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) event.cell.getDataSource(); if (entry.canFlipRead()) { entry.setRead(!entry.isRead()); event.cell.invalidate(); } } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityType.java0000644000175000017500000000727311131054374030713 0ustar adrianadrian/** * Created on Sep 25, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.columns.vuzeactivity; import java.text.SimpleDateFormat; import java.util.Date; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.activities.VuzeActivitiesEntry; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader.ImageDownloaderListener; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; /** * @author TuxPaper * @created Sep 25, 2008 * */ public class ColumnActivityType extends CoreTableColumn implements TableCellSWTPaintListener, TableCellRefreshListener { public static final String COLUMN_ID = "activityType"; private static int WIDTH = 42; // enough to fit title in most cases private static SimpleDateFormat timeFormat = new SimpleDateFormat( "h:mm:ss a, EEEE, MMMM d, yyyy"); /** * @param name * @param alignment * @param position * @param width * @param tableID */ public ColumnActivityType(String tableID) { super(COLUMN_ID, tableID); initializeAsGraphic(WIDTH); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellPaint(GC gc, final TableCellSWT cell) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) cell.getDataSource(); Image imgIcon = null; String iconID = entry.getIconID(); if (iconID != null) { ImageLoader imageLoader = ImageLoader.getInstance(); if (iconID.startsWith("http")) { imgIcon = imageLoader.getUrlImage(iconID, new ImageDownloaderListener() { public void imageDownloaded(Image image, boolean returnedImmediately) { if (returnedImmediately) { return; } cell.invalidate(); } }); if (imgIcon == null) { return; } } else { imgIcon = imageLoader.getImage(iconID); } if (ImageLoader.isRealImage(imgIcon)) { Rectangle cellBounds = cell.getBounds(); Rectangle imgBounds = imgIcon.getBounds(); gc.drawImage(imgIcon, cellBounds.x + ((cellBounds.width - imgBounds.width) / 2), cellBounds.y + ((cellBounds.height - imgBounds.height) / 2)); } imageLoader.releaseImage(iconID); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) cell.getDataSource(); if (cell.setSortValue(entry.getTypeID()) || !cell.isValid()) { String ts = timeFormat.format(new Date(entry.getTimestamp())); cell.setToolTip("Activity occurred on " + ts); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityText.java0000644000175000017500000001741711267524522030726 0ustar adrianadrian/** * Created on Sep 25, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.columns.vuzeactivity; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter.URLInfo; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.activities.VuzeActivitiesEntry; import com.aelitis.azureus.core.util.GeneralUtils; import com.aelitis.azureus.ui.skin.SkinConstants; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory; import com.aelitis.azureus.ui.swt.skin.SWTSkinProperties; import com.aelitis.azureus.util.ContentNetworkUtils; import com.aelitis.azureus.util.StringCompareUtils; import com.aelitis.azureus.util.UrlFilter; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Sep 25, 2008 * */ public class ColumnActivityText extends CoreTableColumn implements TableCellSWTPaintListener, TableCellRefreshListener, TableCellMouseMoveListener, TableCellToolTipListener { public static final String COLUMN_ID = "activityText"; private Color colorLinkNormal; private Color colorLinkHover; private static Font font = null; /** * @param name * @param tableID */ public ColumnActivityText(String tableID) { super(COLUMN_ID, tableID); initializeAsGraphic(480); SWTSkinProperties skinProperties = SWTSkinFactory.getInstance().getSkinProperties(); colorLinkNormal = skinProperties.getColor("color.links.normal"); colorLinkHover = skinProperties.getColor("color.links.hover"); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellPaint(GC gc, TableCellSWT cell) { GCStringPrinter sp = setupStringPrinter(gc, cell); if (sp.hasHitUrl()) { URLInfo[] hitUrlInfo = sp.getHitUrlInfo(); for (int i = 0; i < hitUrlInfo.length; i++) { URLInfo info = hitUrlInfo[i]; info.urlUnderline = cell.getTableRow().isSelected(); if (info.urlUnderline) { info.urlColor = null; } else { info.urlColor = colorLinkNormal; } } int[] mouseOfs = cell.getMouseOffset(); if (mouseOfs != null) { Rectangle realBounds = cell.getBounds(); URLInfo hitUrl = sp.getHitUrl(mouseOfs[0] + realBounds.x, mouseOfs[1] + realBounds.y); if (hitUrl != null) { hitUrl.urlColor = colorLinkHover; } } } sp.printString(); gc.setFont(null); } private GCStringPrinter setupStringPrinter(GC gc, TableCellSWT cell) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) cell.getDataSource(); String text = entry.getText(); Rectangle drawBounds = getDrawBounds(cell); if (!entry.isRead()) { if (font == null) { FontData[] fontData = gc.getFont().getFontData(); fontData[0].setStyle(SWT.BOLD); font = new Font(gc.getDevice(), fontData); } gc.setFont(font); } int style = (drawBounds.height < 40) ? 0 : SWT.WRAP; GCStringPrinter sp = new GCStringPrinter(gc, text, drawBounds, true, true, style); sp.calculateMetrics(); return sp; } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) cell.getDataSource(); cell.setSortValue(entry.getText()); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellMouseListener#cellMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent) public void cellMouseTrigger(TableCellMouseEvent event) { String tooltip = null; boolean invalidateAndRefresh = false; VuzeActivitiesEntry entry = (VuzeActivitiesEntry) event.cell.getDataSource(); //Rectangle bounds = getDrawBounds((TableCellSWT) event.cell); Rectangle bounds = ((TableCellSWT) event.cell).getBounds(); String text = entry.getText(); GC gc = new GC(Display.getDefault()); GCStringPrinter sp = null; try { sp = setupStringPrinter(gc, (TableCellSWT) event.cell); } catch (Exception e) { Debug.out(e); } finally { gc.dispose(); } if (sp != null) { URLInfo hitUrl = sp.getHitUrl(event.x + bounds.x, event.y + bounds.y); int newCursor; if (hitUrl != null) { if (event.eventType == TableCellMouseEvent.EVENT_MOUSEDOWN) { if (!UrlFilter.getInstance().urlCanRPC(hitUrl.url)) { Utils.launch(hitUrl.url); } else { UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uif != null) { String target = hitUrl.target; if (target == null) { target = ContentNetworkUtils.getTarget(entry.getContentNetwork()); } uif.viewURL(hitUrl.url, target, "column.activity.text"); return; } } } newCursor = SWT.CURSOR_HAND; if (UrlFilter.getInstance().urlCanRPC(hitUrl.url)) { try { tooltip = hitUrl.title == null ? null : URLDecoder.decode( hitUrl.title, "utf-8"); } catch (UnsupportedEncodingException e) { } } else { tooltip = hitUrl.url; } } else { newCursor = SWT.CURSOR_ARROW; } int oldCursor = ((TableCellSWT) event.cell).getCursorID(); if (oldCursor != newCursor) { invalidateAndRefresh = true; ((TableCellSWT) event.cell).setCursorID(newCursor); } } Object o = event.cell.getToolTip(); if ((o == null) | (o instanceof String)) { String oldTooltip = (String) o; if (!StringCompareUtils.equals(oldTooltip, tooltip)) { invalidateAndRefresh = true; event.cell.setToolTip(tooltip); } } if (invalidateAndRefresh) { event.cell.invalidate(); ((TableCellSWT)event.cell).redraw(); } } private Rectangle getDrawBounds(TableCellSWT cell) { Rectangle bounds = cell.getBounds(); bounds.x += 4; bounds.width -= 4; return bounds; } // @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHover(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellHover(TableCell cell) { if (cell.getToolTip() != null) { return; } if (!(cell instanceof TableCellSWT)) { return; } if (!Utils.isThisThreadSWT()) { System.err.println("you broke it"); return; } GC gc = new GC(Display.getDefault()); try { GCStringPrinter sp = setupStringPrinter(gc, (TableCellSWT) cell); if (sp.isCutoff()) { cell.setToolTip(GeneralUtils.stripOutHyperlinks(sp.getText())); } } catch (Throwable t) { Debug.out(t); } finally { gc.dispose(); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHoverComplete(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellHoverComplete(TableCell cell) { cell.setToolTip(null); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityDate.java0000644000175000017500000000415611135264370030647 0ustar adrianadrian/** * Created on Sep 25, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.columns.vuzeactivity; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator; import org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer; import com.aelitis.azureus.activities.VuzeActivitiesEntry; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener; /** * @author TuxPaper * @created Sep 25, 2008 * */ public class ColumnActivityDate extends ColumnDateSizer implements TableCellAddedListener { public static final String COLUMN_ID = "activityDate"; /** * @param name * @param tableID */ public ColumnActivityDate(String tableID) { super(null, COLUMN_ID, TableColumnCreator.DATE_COLUMN_WIDTH, tableID); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellAdded(TableCell cell) { if (cell instanceof TableCellSWT) { ((TableCellSWT) cell).setTextAlpha(120); } } // @see org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell, long) public void refresh(TableCell cell, long timestamp) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) cell.getDataSource(); timestamp = entry.getTimestamp(); super.refresh(cell, timestamp); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityActions.java0000644000175000017500000002246411266266270031402 0ustar adrianadrian/** * Created on Sep 25, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.columns.vuzeactivity; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter.URLInfo; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.activities.VuzeActivitiesEntry; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory; import com.aelitis.azureus.ui.swt.skin.SWTSkinProperties; import com.aelitis.azureus.ui.swt.views.skin.TorrentListViewsUtils; import com.aelitis.azureus.util.*; /** * @author TuxPaper * @created Sep 25, 2008 * */ public class ColumnActivityActions extends CoreTableColumn implements TableCellSWTPaintListener, TableCellRefreshListener, TableCellMouseMoveListener, TableCellAddedListener { public static final String COLUMN_ID = "activityActions"; private Color colorLinkNormal; private Color colorLinkHover; private static Font font = null; /** * @param name * @param tableID */ public ColumnActivityActions(String tableID) { super(COLUMN_ID, tableID); initializeAsGraphic(150); SWTSkinProperties skinProperties = SWTSkinFactory.getInstance().getSkinProperties(); colorLinkNormal = skinProperties.getColor("color.links.normal"); colorLinkHover = skinProperties.getColor("color.links.hover"); } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT) public void cellPaint(GC gc, TableCellSWT cell) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) cell.getDataSource(); if (entry == null) { return; } String text = cell.getText(); if (text != null && text.length() > 0) { if (font == null) { FontData[] fontData = gc.getFont().getFontData(); fontData[0].setStyle(SWT.BOLD); font = new Font(gc.getDevice(), fontData); } gc.setFont(font); Rectangle bounds = getDrawBounds(cell); GCStringPrinter sp = new GCStringPrinter(gc, text, bounds, true, true, SWT.WRAP | SWT.CENTER); sp.calculateMetrics(); if (sp.hasHitUrl()) { URLInfo[] hitUrlInfo = sp.getHitUrlInfo(); for (int i = 0; i < hitUrlInfo.length; i++) { URLInfo info = hitUrlInfo[i]; // handle fake row when showing in column editor info.urlUnderline = cell.getTableRow() == null || cell.getTableRow().isSelected(); if (info.urlUnderline) { info.urlColor = null; } else { info.urlColor = colorLinkNormal; } } int[] mouseOfs = cell.getMouseOffset(); if (mouseOfs != null) { Rectangle realBounds = cell.getBounds(); URLInfo hitUrl = sp.getHitUrl(mouseOfs[0] + realBounds.x, mouseOfs[1] + realBounds.y); if (hitUrl != null) { hitUrl.urlColor = colorLinkHover; } } } sp.printString(); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellAdded(TableCell cell) { cell.setMarginHeight(0); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) cell.getDataSource(); if(entry == null) return; if (!cell.setSortValue(entry.getTypeID()) && cell.isValid()) { return; } DownloadManager dm = entry.getDownloadManger(); boolean canPlay = PlayUtils.canPlayDS(entry); boolean canDL = dm == null && entry.getDownloadManger() == null && (entry.getTorrent() != null || entry.getAssetHash() != null); boolean canRun = !canPlay && dm != null; if (canRun && dm != null && !dm.getAssumedComplete()) { canRun = false; } StringBuffer sb = new StringBuffer(); if (canDL) { if (sb.length() > 0) { sb.append(" | "); } sb.append("Download"); } if (canPlay) { if (sb.length() > 0) { sb.append(" | "); } sb.append("Play"); } if (canRun) { if (sb.length() > 0) { sb.append(", "); } sb.append("Launch"); } cell.setText(sb.toString()); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellMouseListener#cellMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent) public void cellMouseTrigger(TableCellMouseEvent event) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) event.cell.getDataSource(); String tooltip = null; boolean invalidateAndRefresh = false; Rectangle bounds = ((TableCellSWT) event.cell).getBounds(); String text = event.cell.getText(); GCStringPrinter sp = null; GC gc = new GC(Display.getDefault()); try { if (font != null) { gc.setFont(font); } Rectangle drawBounds = getDrawBounds((TableCellSWT) event.cell); sp = new GCStringPrinter(gc, text, drawBounds, true, true, SWT.WRAP | SWT.CENTER); sp.calculateMetrics(); } catch (Exception e) { Debug.out(e); } finally { gc.dispose(); } if (sp != null) { URLInfo hitUrl = sp.getHitUrl(event.x + bounds.x, event.y + bounds.y); int newCursor; if (hitUrl != null) { if (event.eventType == TableCellMouseEvent.EVENT_MOUSEUP) { if (hitUrl.url.equals("download")) { String referal = null; Object ds = event.cell.getDataSource(); if (ds instanceof VuzeActivitiesEntry) { if (((VuzeActivitiesEntry) ds).isDRM()) { if (DataSourceUtils.isPlatformContent(ds)) { TorrentListViewsUtils.viewDetailsFromDS( event.cell.getDataSource(), "activity-dl"); } return; } referal = DLReferals.DL_REFERAL_DASHACTIVITY + "-" + ((VuzeActivitiesEntry) ds).getTypeID(); } TorrentListViewsUtils.downloadDataSource(ds, false, referal); } else if (hitUrl.url.equals("play")) { String referal = null; Object ds = event.cell.getDataSource(); if (ds instanceof VuzeActivitiesEntry) { if (((VuzeActivitiesEntry) ds).isDRM() && ((VuzeActivitiesEntry) ds).getDownloadManger() == null) { if (DataSourceUtils.isPlatformContent(ds)) { TorrentListViewsUtils.viewDetailsFromDS( event.cell.getDataSource(), "thumb"); } return; } referal = DLReferals.DL_REFERAL_PLAYDASHACTIVITY + "-" + ((VuzeActivitiesEntry) ds).getTypeID(); } TorrentListViewsUtils.playOrStreamDataSource(ds, null, referal); } else if (hitUrl.url.equals("launch")) { // run via play or stream so we get the security warning Object ds = event.cell.getDataSource(); TorrentListViewsUtils.playOrStreamDataSource(ds, null, DLReferals.DL_REFERAL_LAUNCH); } else if (!UrlFilter.getInstance().urlCanRPC(hitUrl.url)) { Utils.launch(hitUrl.url); } else { UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uif != null) { String target = hitUrl.target; if (target == null) { target = ContentNetworkUtils.getTarget(entry.getContentNetwork()); } uif.viewURL(hitUrl.url, target, "column.activity.action"); return; } } } Object ds = event.cell.getDataSource(); newCursor = SWT.CURSOR_HAND; if (UrlFilter.getInstance().urlCanRPC(hitUrl.url)) { tooltip = hitUrl.title; } else { tooltip = hitUrl.url; } } else { newCursor = SWT.CURSOR_ARROW; } int oldCursor = ((TableCellSWT) event.cell).getCursorID(); if (oldCursor != newCursor) { invalidateAndRefresh = true; ((TableCellSWT) event.cell).setCursorID(newCursor); } } Object o = event.cell.getToolTip(); if ((o == null) || (o instanceof String)) { String oldTooltip = (String) o; if (!StringCompareUtils.equals(oldTooltip, tooltip)) { invalidateAndRefresh = true; event.cell.setToolTip(tooltip); } } if (invalidateAndRefresh) { event.cell.invalidate(); ((TableCellSWT)event.cell).redraw(); } } boolean bMouseDowned = false; private Rectangle getDrawBounds(TableCellSWT cell) { Rectangle bounds = cell.getBounds(); bounds.height -= 12; bounds.y += 6; bounds.x += 4; bounds.width -= 4; return bounds; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/utils/0000755000175000017500000000000011310377632022621 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/utils/ColumnImageClickArea.java0000644000175000017500000002151511127403350027420 0ustar adrianadrian/** * Created on April 29, 2007 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.columns.utils; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.ui.common.table.TableCellCore; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.utils.ColorCache; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Apr 29, 2007 * */ public class ColumnImageClickArea implements TableCellMouseMoveListener, TableRowMouseListener { private static final boolean DEBUG = false; private String imageID; private final String columnID; private Rectangle area; private String id; private Image image; private Rectangle imageArea; private Image imgOnRow; private Image imgOver; private Image imgOffRow; private boolean mouseDownOn; private boolean cellContainsMouse; private TableRow rowContainingMouse; private float scale = 1.0f; private String tooltip; private boolean isVisible = true; /** * @param id */ public ColumnImageClickArea(String columnID, String id, String imageID) { this.columnID = columnID; this.id = id; setImageID(imageID); } /** * @param imageID2 * * @since 3.0.1.5 */ public void setImageID(String imageID) { ImageLoader imageLoader = ImageLoader.getInstance(); if (imgOver != null) { imageLoader.releaseImage(this.imageID + "-over"); } if (imgOnRow != null) { imageLoader.releaseImage(this.imageID + "-mouseonrow"); } if (imgOffRow != null) { imageLoader.releaseImage(this.imageID); } this.imageID = imageID; if (imageID == null) { imgOffRow = null; imgOnRow = null; } else { imgOnRow = imageLoader.getImage(imageID + "-mouseonrow"); imgOver = imageLoader.getImage(imageID + "-over"); imgOffRow = imageLoader.getImage(imageID); if (!ImageLoader.isRealImage(imgOnRow)) { imgOnRow = imgOffRow; } if (!ImageLoader.isRealImage(imgOver)) { imgOver = imgOffRow; } } this.image = null; } public void addCell(TableCell cell) { cell.addListeners(this); TableRow row = cell.getTableRow(); if (row != null) { row.addMouseListener(this); } } /** * @return the area */ public Rectangle getArea() { if (area == null) { area = new Rectangle(0, 0, 0, 0); } return area; } /** * @param area the area to set */ public void setArea(Rectangle area) { this.area = area; } /** * @return the id */ public String getId() { return id; } /** * @return the image */ public Image getImage() { return image; } /** * @param image the image to set */ public void setImage(Image image) { if (!ImageLoader.isRealImage(image)) { this.image = null; imageArea = new Rectangle(0, 0, 0, 0); } else { this.image = image; imageArea = image.getBounds(); } if (area == null) { area = new Rectangle(imageArea.x, imageArea.y, imageArea.width, imageArea.height); return; } area.width = (int) (imageArea.width * scale); area.height = (int) (imageArea.height * scale); //System.out.println("setImage scale " + scale + ";" + area + ";" + imageArea); } public void setPosition(int x, int y) { if (area == null) { area = new Rectangle(x, y, 0, 0); return; } area.x = x; area.y = y; } /** * @param gcImage * * @since 3.0.1.7 */ public void drawImage(TableCell cell, GC gcImage) { if (!isVisible) { return; } Image image = this.image; if (image == null) { if (cellContainsMouse && ImageLoader.isRealImage(imgOver)) { image = imgOver; } else if (rowContainingMouse == cell.getTableRow() && ImageLoader.isRealImage(imgOnRow)) { image = imgOnRow; } else { image = imgOffRow; } } if (DEBUG && cellContainsMouse) { gcImage.setBackground(ColorCache.getColor(gcImage.getDevice(), mouseDownOn ? "#ffff00" : "#ff0000")); gcImage.fillRectangle(getArea()); } //image = imgOnRow; if (ImageLoader.isRealImage(image)) { imageArea = image.getBounds(); Rectangle area = getArea(); area.width = (int) (imageArea.width * scale); area.height = (int) (imageArea.height * scale); gcImage.drawImage(image, imageArea.x, imageArea.y, imageArea.width, imageArea.height, area.x, area.y, area.width, area.height); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellMouseListener#cellMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent) public void cellMouseTrigger(TableCellMouseEvent event) { if (!isVisible) { return; } // System.out.println(event.cell + ": " + event.eventType + ";" + event.x + "x" + event.y + "; b" // + event.button + "; " + event.keyboardState); if (event.eventType == TableCellMouseEvent.EVENT_MOUSEDOWN) { mouseDownOn = false; Point pt = new Point(event.x, event.y); mouseDownOn = getArea().contains(pt); TableCellCore cell = (TableCellCore) event.row.getTableCell(columnID); if (cell != null) { cell.invalidate(); cell.refreshAsync(); } } else if (event.eventType == TableCellMouseEvent.EVENT_MOUSEUP && mouseDownOn) { mouseDownOn = false; TableCellMouseEvent mouseEvent = new TableCellMouseEvent(); mouseEvent.button = event.button; mouseEvent.cell = event.cell; mouseEvent.eventType = TableCellMouseEvent.EVENT_MOUSEUP; // EVENT_MOUSECLICK would be nice.. mouseEvent.keyboardState = event.keyboardState; mouseEvent.skipCoreFunctionality = event.skipCoreFunctionality; mouseEvent.x = event.x; // TODO: Convert to coord relative to image? mouseEvent.y = event.y; mouseEvent.data = this; ((TableColumnCore) event.cell.getTableColumn()).invokeCellMouseListeners(mouseEvent); ((TableCellCore) event.cell).invokeMouseListeners(mouseEvent); } else if (event.eventType == TableCellMouseEvent.EVENT_MOUSEMOVE) { boolean contains = getArea().contains(event.x, event.y); setContainsMouse(event.cell, contains); } else if (event.eventType == TableCellMouseEvent.EVENT_MOUSEEXIT) { setContainsMouse(event.cell, false); } else if (event.eventType == TableCellMouseEvent.EVENT_MOUSEDOUBLECLICK) { event.skipCoreFunctionality = true; } } // @see org.gudy.azureus2.plugins.ui.tables.TableRowMouseListener#rowMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableRowMouseEvent) public void rowMouseTrigger(TableRowMouseEvent event) { if (!isVisible) { return; } if (event.eventType == TableCellMouseEvent.EVENT_MOUSEEXIT) { if (rowContainingMouse == event.row) { rowContainingMouse = null; } setContainsMouse(null, false); //System.out.println("d=" + image); TableCellCore cell = (TableCellCore) event.row.getTableCell(columnID); if (cell != null) { cell.invalidate(); cell.refreshAsync(); } } else if (event.eventType == TableCellMouseEvent.EVENT_MOUSEENTER) { rowContainingMouse = event.row; //System.out.println("e=" + image); TableCellCore cell = (TableCellCore) event.row.getTableCell(columnID); if (cell != null) { cell.invalidate(); cell.refreshAsync(); } } } private void setContainsMouse(TableCell cell, boolean contains) { if (cellContainsMouse != contains) { cellContainsMouse = contains; if (cell != null) { TableCellCore cellCore = (TableCellCore) cell; cellCore.invalidate(); cellCore.refreshAsync(); cellCore.setCursorID(cellContainsMouse ? SWT.CURSOR_HAND : SWT.CURSOR_ARROW); if (tooltip != null) { if (cellContainsMouse) { cellCore.setToolTip(tooltip); } else { Object oldTT = cellCore.getToolTip(); if (tooltip.equals(oldTT)) { cellCore.setToolTip(null); } } } } } } public float getScale() { return scale; } public void setScale(float scale) { this.scale = scale; setImage(image); } public Rectangle getImageArea() { return new Rectangle(imageArea.x, imageArea.y, imageArea.width, imageArea.height); } public String getTooltip() { return tooltip; } public void setTooltip(String tooltip) { this.tooltip = tooltip; } public boolean isVisible() { return isVisible; } public void setVisible(boolean isVisible) { this.isVisible = isVisible; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/columns/utils/TableColumnCreatorV3.java0000644000175000017500000003234511300657776027442 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.columns.utils; import java.lang.reflect.Constructor; import java.util.Iterator; import java.util.Map; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.LightHashMap; import org.gudy.azureus2.ui.swt.views.table.TableColumnCoreCreationListener; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import org.gudy.azureus2.ui.swt.views.tableitems.mytorrents.*; import com.aelitis.azureus.activities.VuzeActivitiesEntry; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.swt.columns.torrent.*; import com.aelitis.azureus.ui.swt.columns.vuzeactivity.*; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadTypeComplete; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.tables.TableColumn; /** * A utility class for creating some common column sets; this is a virtual clone of TableColumnCreator * with slight modifications * @author khai * */ public class TableColumnCreatorV3 { /** * @param tableMytorrentsAllBig * @param b * @return * * @since 4.0.0.1 */ public static TableColumnCore[] createAllDM(String tableID, boolean big) { final String[] defaultVisibleOrder = { ColumnUnopened.COLUMN_ID, ColumnThumbAndName.COLUMN_ID, "RatingColumn", "azsubs.ui.column.subs", SizeItem.COLUMN_ID, StatusItem.COLUMN_ID, ShareRatioItem.COLUMN_ID, DateCompletedItem.COLUMN_ID, }; TableColumnManager tcManager = TableColumnManager.getInstance(); Map mapTCs = tcManager.getTableColumnsAsMap( Download.class, tableID); tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder); if (!tcManager.loadTableColumnSettings(Download.class, tableID) || areNoneVisible(mapTCs)) { setVisibility(mapTCs, defaultVisibleOrder); DateCompletedItem tc = (DateCompletedItem) mapTCs.get(DateCompletedItem.COLUMN_ID); if (tc != null) { tcManager.setDefaultSortColumnName(tableID, DateCompletedItem.COLUMN_ID); tc.setSortAscending(false); } } // special changes StatusItem tcStatusItem = (StatusItem) mapTCs.get(StatusItem.COLUMN_ID); if (tcStatusItem != null) { tcStatusItem.setChangeRowFG(false); if (big) { tcStatusItem.setChangeCellFG(false); tcStatusItem.setShowTrackerErrors( true ); } } if (big) { ShareRatioItem tcShareRatioItem = (ShareRatioItem) mapTCs.get(ShareRatioItem.COLUMN_ID); if (tcShareRatioItem != null) { tcShareRatioItem.setChangeFG(false); tcShareRatioItem.setWidth(80); } } return mapTCs.values().toArray(new TableColumnCore[0]); } public static TableColumnCore[] createIncompleteDM(String tableID, boolean big) { final String[] defaultVisibleOrder = { ColumnThumbAndName.COLUMN_ID, "azsubs.ui.column.subs", SizeItem.COLUMN_ID, ColumnProgressETA.COLUMN_ID, SeedsItem.COLUMN_ID, PeersItem.COLUMN_ID, }; TableColumnManager tcManager = TableColumnManager.getInstance(); Map mapTCs = tcManager.getTableColumnsAsMap( DownloadTypeIncomplete.class, tableID); tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder); if (!tcManager.loadTableColumnSettings(DownloadTypeIncomplete.class, tableID) || areNoneVisible(mapTCs)) { setVisibility(mapTCs, defaultVisibleOrder); ColumnThumbAndName tc = (ColumnThumbAndName) mapTCs.get(ColumnThumbAndName.COLUMN_ID); if (tc != null) { tcManager.setDefaultSortColumnName(tableID, ColumnThumbAndName.COLUMN_ID); tc.setSortAscending(true); } } // special changes StatusItem tcStatusItem = (StatusItem) mapTCs.get(StatusItem.COLUMN_ID); if (tcStatusItem != null) { tcStatusItem.setChangeRowFG(false); if (big) { tcStatusItem.setChangeCellFG(false); } } if (big) { ShareRatioItem tcShareRatioItem = (ShareRatioItem) mapTCs.get(ShareRatioItem.COLUMN_ID); if (tcShareRatioItem != null) { tcShareRatioItem.setChangeFG(false); tcShareRatioItem.setWidth(80); } } return mapTCs.values().toArray(new TableColumnCore[0]); } /** * @param mapTCs * @param defaultVisibleOrder */ private static void setVisibility(Map mapTCs, String[] defaultVisibleOrder) { for (Iterator iter = mapTCs.values().iterator(); iter.hasNext();) { TableColumnCore tc = (TableColumnCore) iter.next(); tc.setVisible(false); } for (int i = 0; i < defaultVisibleOrder.length; i++) { String id = defaultVisibleOrder[i]; TableColumnCore tc = (TableColumnCore) mapTCs.get(id); if (tc != null) { tc.setVisible(true); tc.setPositionNoShift(i); } } } public static TableColumnCore[] createCompleteDM(String tableID, boolean big) { final String[] defaultVisibleOrder = { ColumnUnopened.COLUMN_ID, ColumnThumbAndName.COLUMN_ID, "RatingColumn", "azsubs.ui.column.subs", SizeItem.COLUMN_ID, StatusItem.COLUMN_ID, ShareRatioItem.COLUMN_ID, DateCompletedItem.COLUMN_ID, }; TableColumnManager tcManager = TableColumnManager.getInstance(); Map mapTCs = tcManager.getTableColumnsAsMap(DownloadTypeComplete.class, tableID); tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder); if (!tcManager.loadTableColumnSettings(DownloadTypeComplete.class, tableID) || areNoneVisible(mapTCs)) { setVisibility(mapTCs, defaultVisibleOrder); DateCompletedItem tc = (DateCompletedItem) mapTCs.get(DateCompletedItem.COLUMN_ID); if (tc != null) { tcManager.setDefaultSortColumnName(tableID, DateCompletedItem.COLUMN_ID); tc.setSortAscending(false); } } // special changes StatusItem tcStatusItem = (StatusItem) mapTCs.get(StatusItem.COLUMN_ID); if (tcStatusItem != null) { tcStatusItem.setChangeRowFG(false); if (big) { tcStatusItem.setChangeCellFG(false); } } if (big) { ShareRatioItem tcShareRatioItem = (ShareRatioItem) mapTCs.get(ShareRatioItem.COLUMN_ID); if (tcShareRatioItem != null) { tcShareRatioItem.setChangeFG(false); tcShareRatioItem.setWidth(80); } } return (TableColumnCore[]) mapTCs.values().toArray(new TableColumnCore[0]); } public static TableColumnCore[] createUnopenedDM(String tableID, boolean big) { final String[] defaultVisibleOrder = { ColumnUnopened.COLUMN_ID, ColumnThumbAndName.COLUMN_ID, "azsubs.ui.column.subs", SizeItem.COLUMN_ID, StatusItem.COLUMN_ID, DateCompletedItem.COLUMN_ID, }; TableColumnManager tcManager = TableColumnManager.getInstance(); Map mapTCs = tcManager.getTableColumnsAsMap(DownloadTypeIncomplete.class, tableID); tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder); if (!tcManager.loadTableColumnSettings(DownloadTypeIncomplete.class, tableID) || areNoneVisible(mapTCs)) { setVisibility(mapTCs, defaultVisibleOrder); DateCompletedItem tc = (DateCompletedItem) mapTCs.get(DateCompletedItem.COLUMN_ID); if (tc != null) { tcManager.setDefaultSortColumnName(tableID, DateCompletedItem.COLUMN_ID); tc.setSortAscending(false); } } // special changes StatusItem tcStatusItem = (StatusItem) mapTCs.get(StatusItem.COLUMN_ID); if (tcStatusItem != null) { tcStatusItem.setChangeRowFG(false); if (big) { tcStatusItem.setChangeCellFG(false); } } if (big) { ShareRatioItem tcShareRatioItem = (ShareRatioItem) mapTCs.get(ShareRatioItem.COLUMN_ID); if (tcShareRatioItem != null) { tcShareRatioItem.setChangeFG(false); tcShareRatioItem.setWidth(80); } } return (TableColumnCore[]) mapTCs.values().toArray(new TableColumnCore[0]); } public static TableColumnCore[] createActivitySmall(String tableID) { final String[] defaultVisibleOrder = { ColumnActivityNew.COLUMN_ID, ColumnActivityType.COLUMN_ID, ColumnActivityText.COLUMN_ID, ColumnActivityActions.COLUMN_ID, ColumnActivityDate.COLUMN_ID, }; TableColumnManager tcManager = TableColumnManager.getInstance(); Map mapTCs = tcManager.getTableColumnsAsMap(VuzeActivitiesEntry.class, tableID); tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder); if (!tcManager.loadTableColumnSettings(VuzeActivitiesEntry.class, tableID) || areNoneVisible(mapTCs)) { setVisibility(mapTCs, defaultVisibleOrder); ColumnActivityDate tc = (ColumnActivityDate) mapTCs.get(ColumnActivityDate.COLUMN_ID); if (tc != null) { tcManager.setDefaultSortColumnName(tableID, ColumnActivityDate.COLUMN_ID); tc.setSortAscending(false); } ColumnActivityText tcText = (ColumnActivityText) mapTCs.get(ColumnActivityText.COLUMN_ID); if (tcText != null) { tcText.setWidth(445); } } return (TableColumnCore[]) mapTCs.values().toArray(new TableColumnCore[0]); } public static TableColumnCore[] createActivityBig(String tableID) { final String[] defaultVisibleOrder = { ColumnActivityNew.COLUMN_ID, ColumnActivityType.COLUMN_ID, ColumnActivityText.COLUMN_ID, ColumnThumbnail.COLUMN_ID, ColumnActivityActions.COLUMN_ID, ColumnActivityDate.COLUMN_ID, }; TableColumnManager tcManager = TableColumnManager.getInstance(); Map mapTCs = tcManager.getTableColumnsAsMap(VuzeActivitiesEntry.class, tableID); tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder); if (!tcManager.loadTableColumnSettings(VuzeActivitiesEntry.class, tableID) || areNoneVisible(mapTCs)) { setVisibility(mapTCs, defaultVisibleOrder); ColumnActivityText tcText = (ColumnActivityText) mapTCs.get(ColumnActivityText.COLUMN_ID); if (tcText != null) { tcText.setWidth(350); } ColumnActivityDate tc = (ColumnActivityDate) mapTCs.get(ColumnActivityDate.COLUMN_ID); if (tc != null) { tcManager.setDefaultSortColumnName(tableID, ColumnActivityDate.COLUMN_ID); tc.setSortAscending(false); } } return (TableColumnCore[]) mapTCs.values().toArray(new TableColumnCore[0]); } /** * * * @since 3.1.1.1 */ private static boolean areNoneVisible(Map mapTCs) { boolean noneVisible = true; for (Iterator iter = mapTCs.values().iterator(); iter.hasNext();) { TableColumn tc = (TableColumn) iter.next(); if (tc.isVisible()) { noneVisible = false; break; } } return noneVisible; } /** * * * @since 3.1.1.1 */ public static void initCoreColumns() { TableColumnCreator.initCoreColumns(); // short variable names to reduce wrapping final Map c = new LightHashMap(7); c.put(ColumnUnopened.COLUMN_ID, new cInfo(ColumnUnopened.class, ColumnUnopened.DATASOURCE_TYPE)); c.put(ColumnThumbAndName.COLUMN_ID, new cInfo(ColumnThumbAndName.class, ColumnThumbAndName.DATASOURCE_TYPE)); c.put(DateAddedItem.COLUMN_ID, new cInfo(DateAddedItem.class, DateAddedItem.DATASOURCE_TYPE)); c.put(DateCompletedItem.COLUMN_ID, new cInfo(DateCompletedItem.class, DateCompletedItem.DATASOURCE_TYPE)); c.put(ColumnProgressETA.COLUMN_ID, new cInfo(ColumnProgressETA.class, ColumnProgressETA.DATASOURCE_TYPE)); ///////// final Class ac = VuzeActivitiesEntry.class; c.put(ColumnActivityNew.COLUMN_ID, new cInfo(ColumnActivityNew.class, ac)); c.put(ColumnActivityType.COLUMN_ID, new cInfo(ColumnActivityType.class, ac)); c.put(ColumnActivityText.COLUMN_ID, new cInfo(ColumnActivityText.class, ac)); c.put(ColumnActivityActions.COLUMN_ID, new cInfo( ColumnActivityActions.class, ac)); c.put(ColumnActivityDate.COLUMN_ID, new cInfo(ColumnActivityDate.class, ac)); c.put(ColumnThumbnail.COLUMN_ID, new cInfo(ColumnThumbnail.class, new Class[] { ac, })); // Core columns are implementors of TableColumn to save one class creation // Otherwise, we'd have to create a generic TableColumnImpl class, pass it // to another class so that it could manipulate it and act upon changes. TableColumnManager tcManager = TableColumnManager.getInstance(); TableColumnCoreCreationListener tcCreator = new TableColumnCoreCreationListener() { // @see org.gudy.azureus2.ui.swt.views.table.TableColumnCoreCreationListener#createTableColumnCore(java.lang.Class, java.lang.String, java.lang.String) public TableColumnCore createTableColumnCore(Class forDataSourceType, String tableID, String columnID) { cInfo info = c.get(columnID); try { Constructor constructor = info.cla.getDeclaredConstructor(new Class[] { String.class }); TableColumnCore column = (TableColumnCore) constructor.newInstance(new Object[] { tableID }); return column; } catch (Exception e) { Debug.out(e); } return null; } public void tableColumnCreated(TableColumn column) { } }; tcManager.unregisterColumn(NameItem.DATASOURCE_TYPE, NameItem.COLUMN_ID, null); for (Iterator iter = c.keySet().iterator(); iter.hasNext();) { String id = iter.next(); cInfo info = c.get(id); for (int i = 0; i < info.forDataSourceTypes.length; i++) { Class cla = info.forDataSourceTypes[i]; tcManager.registerColumn(cla, id, tcCreator); } } } private static class cInfo { public Class cla; public Class[] forDataSourceTypes; public cInfo(Class cla, Class forDataSourceType) { this.cla = cla; this.forDataSourceTypes = new Class[] { forDataSourceType }; } public cInfo(Class cla, Class[] forDataSourceTypes) { this.cla = cla; this.forDataSourceTypes = forDataSourceTypes; } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/Sleak.java0000644000175000017500000003053411073762652021716 0ustar adrianadrian/* * Created on Sep 10, 2003 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt; /* * Copyright (c) 2000, 2002 IBM Corp. All rights reserved. * This file is made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html */ import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; import org.eclipse.swt.widgets.List; import com.aelitis.azureus.launcher.Launcher; import com.aelitis.azureus.ui.swt.shells.main.MainWindow; /** * Code to detect swt leak * */ public class Sleak { Display display; Shell shell; List list; Canvas canvas; Button start, stop, check; Text text; Text label; Object[] oldObjects = new Object[0]; Error[] oldErrors = new Error[0]; Object[] objects = new Object[0]; Error[] errors = new Error[0]; Map all = new HashMap(); ArrayList oldNonResources = new ArrayList(); public void open() { display = Display.getCurrent(); shell = new Shell(display); shell.setText("S-Leak"); list = new List(shell, SWT.BORDER | SWT.V_SCROLL); list.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { refreshObject(); } }); text = new Text(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); canvas = new Canvas(shell, SWT.BORDER); canvas.addListener(SWT.Paint, new Listener() { public void handleEvent(Event event) { paintCanvas(event); } }); check = new Button(shell, SWT.CHECK); check.setText("Stack"); check.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { toggleStackTrace(); } }); start = new Button(shell, SWT.PUSH); start.setText("Snap"); start.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { refreshAll(); } }); stop = new Button(shell, SWT.PUSH); stop.setText("Diff"); stop.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { refreshDifference(); } }); label = new Text(shell, SWT.BORDER | SWT.READ_ONLY + SWT.MULTI); label.setText("0 object(s)"); shell.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { layout(); } }); check.setSelection(false); text.setVisible(false); Point size = shell.getSize(); shell.setSize(size.x / 2, size.y / 2); shell.open(); } void refreshLabel() { int colors = 0, cursors = 0, fonts = 0, gcs = 0, images = 0, regions = 0, others = 0, composites = 0, labels = 0; for (int i = 0; i < objects.length; i++) { Object object = objects[i]; if (object instanceof Color) { colors++; } else if (object instanceof Cursor) { cursors++; } else if (object instanceof Font) { fonts++; } else if (object instanceof GC) { gcs++; } else if (object instanceof Image) { images++; } else if (object instanceof Region) { regions++; } else if (object instanceof Composite) { composites++; } else if (object instanceof Label) { labels++; } else { others++; } } String string = ""; if (colors != 0) { string += colors + " Color(s)\n"; } if (cursors != 0) { string += cursors + " Cursor(s)\n"; } if (fonts != 0) { string += fonts + " Font(s)\n"; } if (gcs != 0) { string += gcs + " GC(s)\n"; } if (images != 0) { string += images + " Image(s)\n"; } if (composites != 0) { string += composites + " composite(s)\n"; } if (labels != 0) { string += labels + " label(s)\n"; } if (others != 0) { string += others + " Other(s)\n"; } /* Currently regions are not counted. */ // if (regions != 0) string += regions + " Region(s)\n"; if (string.length() != 0) { string = string.substring(0, string.length() - 1); } label.setText(string); } void refreshDifference() { DeviceData info = display.getDeviceData(); if (!info.tracking) { MessageBox dialog = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK); dialog.setText(shell.getText()); dialog.setMessage("Warning: Device is not tracking resource allocation"); dialog.open(); } Object[] newObjects = info.objects; Error[] newErrors = info.errors; Object[] diffObjects = new Object[newObjects.length]; Error[] diffErrors = new Error[newErrors.length]; int countResourceType = 0; for (int i = 0; i < newObjects.length; i++) { int index = 0; while (index < oldObjects.length) { if (newObjects[i] == oldObjects[index]) { break; } index++; } if (index == oldObjects.length) { diffObjects[countResourceType] = newObjects[i]; diffErrors[countResourceType] = newErrors[i]; countResourceType++; } } Shell[] shells = display.getShells(); ArrayList nonResourceList = new ArrayList(); for (int i = 0; i < shells.length; i++) { Shell shell = shells[i]; if (shell != this.shell) { buildObjectList(shell, nonResourceList); } } oldNonResources = nonResourceList; Object[] nonResources = nonResourceList.toArray(); int countNonResources = nonResources.length; int total = countResourceType + countNonResources; objects = new Object[total]; errors = new Error[total]; System.arraycopy(diffObjects, 0, objects, 0, countResourceType); System.arraycopy(diffErrors, 0, errors, 0, countResourceType); System.arraycopy(nonResources, 0, objects, countResourceType, countNonResources); list.removeAll(); text.setText(""); canvas.redraw(); for (int i = 0; i < objects.length; i++) { list.add(objectName(objects[i])); } System.out.println(countResourceType); refreshLabel(); layout(); } /** * @param shell2 * @param list2 */ private void buildObjectList(Control control, ArrayList list) { if (!oldNonResources.contains(control)) { list.add(control); } if (control instanceof Composite) { Composite c = (Composite) control; Control[] children = c.getChildren(); for (int i = 0; i < children.length; i++) { Control control2 = children[i]; buildObjectList(control2, list); } } } String objectName(Object object) { Date timeAdded = (Date)all.get(object); if (timeAdded == null) { timeAdded = new Date(); all.put(object, timeAdded); } String string = timeAdded + "] " + object.toString(); if (object instanceof Resource) { return string; } int index = string.indexOf(" {"); if (index == -1) { return string; } string = string.substring(0, index); if (object instanceof Composite) { Control[] children = ((Composite) object).getChildren(); string += ": " + children.length + " kids"; } return string; } void toggleStackTrace() { refreshObject(); layout(); } void paintCanvas(Event event) { canvas.setCursor(null); int index = list.getSelectionIndex(); if (index == -1) { return; } GC gc = event.gc; Object object = objects[index]; if (object instanceof Color) { if (((Color) object).isDisposed()) { gc.drawString("Color disposed", 0, 0); return; } gc.setBackground((Color) object); gc.fillRectangle(canvas.getClientArea()); return; } if (object instanceof Cursor) { if (((Cursor) object).isDisposed()) { gc.drawString("Cursor disposed", 0, 0); return; } canvas.setCursor((Cursor) object); return; } if (object instanceof Font) { if (((Font) object).isDisposed()) { gc.drawString("Font disposed", 0, 0); return; } gc.setFont((Font) object); FontData[] array = gc.getFont().getFontData(); String string = ""; String lf = text.getLineDelimiter(); for (int i = 0; i < array.length; i++) { FontData data = array[i]; String style = "NORMAL"; int bits = data.getStyle(); if (bits != 0) { if ((bits & SWT.BOLD) != 0) { style = "BOLD "; } if ((bits & SWT.ITALIC) != 0) { style += "ITALIC"; } } string += data.getName() + " " + data.getHeight() + " " + style + lf; } gc.drawString(string, 0, 0); return; } //NOTHING TO DRAW FOR GC // if (object instanceof GC) { // return; // } if (object instanceof Image) { if (((Image) object).isDisposed()) { gc.drawString("Image disposed", 0, 0); return; } Image image = (Image) object; gc.drawString(image.getBounds().toString(), 0, 0); gc.drawImage(image, 0, 15); return; } if (object instanceof Region) { if (((Region) object).isDisposed()) { return; } String string = ((Region) object).getBounds().toString(); gc.drawString(string, 0, 0); return; } if (object instanceof Control) { Control control = (Control) object; if (control.isDisposed()) { return; } Rectangle bounds = control.getBounds(); gc.drawString(object.toString(), 0, 0); gc.drawString(bounds.toString(), 0, 20); if (object instanceof Widget) { Object data = ((Widget)object).getData("sleak"); if (data != null) { gc.drawString(data.toString(), 0, 35); } } GC gcControl = new GC(control); try { Image img = new Image(control.getDisplay(), bounds.width, bounds.height); gcControl.copyArea(img, 0, 0); gc.drawImage(img, 0, 45); img.dispose(); } catch (Exception e) { } finally { gcControl.dispose(); } return; } } void refreshObject() { int index = list.getSelectionIndex(); if (index == -1) { return; } if (check.getSelection() && index < errors.length && errors[index] == null) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); PrintStream s = new PrintStream(stream); errors[index].printStackTrace(s); text.setText(stream.toString()); text.setVisible(true); canvas.setVisible(false); } else { canvas.setVisible(true); text.setVisible(false); canvas.redraw(); } } void refreshAll() { oldObjects = new Object[0]; oldErrors = new Error[0]; oldNonResources = new ArrayList(); refreshDifference(); oldObjects = objects; oldErrors = errors; } void layout() { Rectangle rect = shell.getClientArea(); int width = 0; String[] items = list.getItems(); GC gc = new GC(list); for (int i = 0; i < objects.length; i++) { width = Math.max(width, gc.stringExtent(items[i]).x); } gc.dispose(); Point size1 = start.computeSize(SWT.DEFAULT, SWT.DEFAULT); Point size2 = stop.computeSize(SWT.DEFAULT, SWT.DEFAULT); Point size3 = check.computeSize(SWT.DEFAULT, SWT.DEFAULT); Point size4 = label.computeSize(SWT.DEFAULT, SWT.DEFAULT); width = Math.max(size1.x, Math.max(size2.x, Math.max(size3.x, width))); width = Math.max(64, Math.max(size4.x, list.computeSize(width, SWT.DEFAULT).x)); start.setBounds(0, 0, width, size1.y); stop.setBounds(0, size1.y, width, size2.y); check.setBounds(0, size1.y + size2.y, width, size3.y); label.setBounds(0, rect.height - size4.y, width, size4.y); int height = size1.y + size2.y + size3.y; list.setBounds(0, height, width, rect.height - height - size4.y); text.setBounds(width, 0, rect.width - width, rect.height); canvas.setBounds(width, 0, rect.width - width, rect.height); } public static void main(String[] args) { if(Launcher.checkAndLaunch(Sleak.class, args)) return; DeviceData data = new DeviceData(); data.tracking = true; Display display = new Display(data); Sleak sleak = new Sleak(); sleak.open(); Initializer.main(args); while (!sleak.shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } try { if (!display.isDisposed()) { display.dispose(); } } catch (Exception e) { // TODO: handle exception } } }azureus-4.3.0.6/com/aelitis/azureus/ui/swt/search/0000755000175000017500000000000011310377556021253 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/search/network/0000755000175000017500000000000011310377632022737 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/search/network/NetworkSearch.java0000644000175000017500000000513611053302502026352 0ustar adrianadrian/* * Created on Jul 11, 2006 8:57:55 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.search.network; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.browser.Browser; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ipc.IPCInterface; import org.gudy.azureus2.pluginsimpl.local.ipc.IPCInterfaceImpl; import com.aelitis.azureus.core.AzureusCore; /** * @author PARG! * @created Jul 11, 2006 * */ public class NetworkSearch { private static final LogIDs LOGID = LogIDs.GUI; public static void search(AzureusCore core, String searchText, Browser browser) { new NetworkSearch(core, searchText, browser); } protected NetworkSearch(AzureusCore core, String searchText, Browser browser) { PluginInterface pi = core.getPluginManager().getPluginInterfaceByID( "azsearch", false); if (pi == null) { Logger.log(new LogEvent(LOGID, "Search plugin not found")); return; } if (!pi.getPluginState().isOperational()) { Logger.log(new LogEvent(LOGID, "Search plugin not operational")); return; } Logger.log(new LogEvent(LOGID, "Search plugin functionality disabled")); /* Map params = new HashMap(); params.put("expression", searchText); params.put("swtbrowser", browser); try { IPCInterface my_ipc = new IPCInterfaceImpl(this); pi.getIPC().invoke("search", new Object[] { my_ipc, params }); } catch (Throwable e) { Logger.log(new LogEvent(LOGID, "IPC to search plugin failed", e)); } */ } public void searchCallback(Map params) { System.out.println("NetworkSearch::callback - " + params); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/UIConfigDefaultsSWTv3.java0000644000175000017500000002036711276167306024664 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt; import java.io.File; import java.util.Map; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.impl.*; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.SystemProperties; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter; import com.aelitis.azureus.ui.skin.SkinConstants; /** * @author TuxPaper * @created Nov 3, 2006 * */ public class UIConfigDefaultsSWTv3 { public static void initialize(AzureusCore core) { ConfigurationManager config = ConfigurationManager.getInstance(); boolean configNeedsSave = false; if (System.getProperty("FORCE_PROGRESSIVE", "").length() > 0) { //TODO HACK FOR DEMO PURPOSES ONLY! config.setParameter("Prioritize First Piece", true); configNeedsSave = true; } // Up to az > 3.0.0.2, we did not store the original version the user starts // on. String sFirstVersion = config.getStringParameter("First Recorded Version"); final ConfigurationDefaults defaults = ConfigurationDefaults.getInstance(); // Always have the wizard complete when running az3 defaults.addParameter("Wizard Completed", true); defaults.addParameter("ui", "az3"); // Another hack to fix up some 3.x versions thinking their first version // was 2.5.0.0.. if (Constants.compareVersions(sFirstVersion, "2.5.0.0") == 0) { String sDefSavePath = config.getStringParameter("Default save path"); System.out.println(sDefSavePath); String sDefPath = null; try { sDefPath = defaults.getStringParameter("Default save path"); } catch (ConfigurationParameterNotFoundException e) { e.printStackTrace(); } if (sDefPath != null) { File fNewPath = new File(sDefPath); if (sDefSavePath != null && fNewPath.equals(new File(sDefSavePath))) { sFirstVersion = "3.0.0.5"; config.setParameter("First Recorded Version", sFirstVersion); configNeedsSave = true; } } } boolean virginSwitch = config.getBooleanParameter("az3.virgin.switch", false); boolean immediateSwitch = config.getBooleanParameter( "az3.switch.immediate", false); if (Constants.compareVersions(sFirstVersion, "3.0.0.0") >= 0 || immediateSwitch) { if (!config.isNewInstall() && Constants.compareVersions(sFirstVersion, "3.0.0.4") < 0) { // We can guess first version based on the Default save path. // In 3.0.0.0 to 3.0.0.3, we set it to userPath + "data". Anything // else is 2.x. We don't want to change the defaults for 2.x people String userPath = SystemProperties.getUserPath(); File fOldPath = new File(userPath, "data"); String sDefSavePath = config.getStringParameter("Default save path"); String sDefPath = ""; try { sDefPath = defaults.getStringParameter("Default save path"); } catch (ConfigurationParameterNotFoundException e) { } File fNewPath = new File(sDefPath); if (sDefSavePath != null && fNewPath.equals(new File(sDefSavePath))) { sFirstVersion = "3.0.0.5"; config.setParameter("First Recorded Version", sFirstVersion); configNeedsSave = true; } else if (sDefSavePath == null || !fOldPath.equals(new File(sDefSavePath))) { sFirstVersion = "2.5.0.0"; // guess config.setParameter("First Recorded Version", sFirstVersion); config.save(); return; } else { // first version was 3.0.0.0 - 3.0.0.3, which used userPath + "data" // remove save path, which will default it to Azureus' Doc dir config.removeParameter("Default save path"); } } defaults.addParameter("Auto Upload Speed Enabled", true); defaults.addParameter("Use default data dir", true); defaults.addParameter("Add URL Silently", true); defaults.addParameter("add_torrents_silently", true); defaults.addParameter("Popup Download Finished", false); defaults.addParameter("Popup Download Added", false); defaults.addParameter("Status Area Show SR", false); defaults.addParameter("Status Area Show NAT", false); defaults.addParameter("Status Area Show IPF", false); defaults.addParameter("Message Popup Autoclose in Seconds", 10 ); defaults.addParameter("window.maximized", true); defaults.addParameter("update.autodownload", true); defaults.addParameter("suppress_file_download_dialog", true); defaults.addParameter("auto_remove_inactive_items", false); defaults.addParameter("show_torrents_menu", false); } defaults.addParameter("v3.topbar.show.frog", false); defaults.addParameter("v3.topbar.show.plugin", false); defaults.addParameter("ui.toolbar.uiswitcher", false); defaults.addParameter(SkinConstants.VIEWID_PLUGINBAR + ".visible", false); config.removeParameter("v3.home-tab.starttab"); defaults.addParameter("v3.topbar.height", 60); defaults.addParameter("MyTorrentsView.table.style", 0); defaults.addParameter("v3.Show Welcome", true); int userMode = COConfigurationManager.getIntParameter("User Mode"); boolean startAdvanced = userMode > 1; defaults.addParameter("Library.viewmode", startAdvanced ? 1 : 0); defaults.addParameter("LibraryDL.viewmode", startAdvanced ? 1 : 0); defaults.addParameter("LibraryUnopened.viewmode", startAdvanced ? 1 : 0); defaults.addParameter("LibraryCD.viewmode", startAdvanced ? 1 : 0); defaults.addParameter("list.dm.dblclick", "0"); //=== defaults used by MainWindow defaults.addParameter("vista.adminquit", false); defaults.addParameter("Password enabled", false); defaults.addParameter("Start Minimized", false); defaults.addParameter("Password enabled", false); defaults.addParameter("ToolBar.showText", true); // by default, turn off some slidey warning // Since they are plugin configs, we need to set the default after the // plugin sets the default core.addLifecycleListener(new AzureusCoreLifecycleAdapter() { public void started(AzureusCore core) { defaults.addParameter("Plugin.DHT.dht.warn.user", false); defaults.addParameter("Plugin.UPnP.upnp.alertothermappings", false); defaults.addParameter("Plugin.UPnP.upnp.alertdeviceproblems", false); } }); // "v3.StartTab" didn't exist before 4209_B49 and is written at startup. // Use it as indicator to reset columns so beta users get correct columns // ("Big View" only). As a backup (in addition to), reset on first 4210 // run if (!COConfigurationManager.hasParameter("v3.StartTab", true) || (ConfigurationChecker.isNewVersion() && Constants.compareVersions( Constants.getBaseVersion(), "4.2.1.0") == 0)) { // Reset 'big' columns, remove some tables that no longer exist Map map = FileUtil.readResilientConfigFile("tables.config"); if (map != null && map.size() > 0) { Object[] keys = map.keySet().toArray(); boolean removedSome = false; for (int i = 0; i < keys.length; i++) { if (keys[i] instanceof String) { String sKey = (String) keys[i]; if (sKey.endsWith(".big") || sKey.startsWith("Table.library-") || sKey.startsWith("Table.Media") || sKey.startsWith("Table.activity.table") || sKey.equals("Table.Activity.big") || sKey.equals("Table.Activity_SB")) { map.remove(sKey); removedSome = true; } } } if (removedSome) { FileUtil.writeResilientConfigFile("tables.config", map); } } } if (configNeedsSave) { config.save(); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/0000755000175000017500000000000011310377632021273 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/uiswitcher/0000755000175000017500000000000011310377632023461 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/uiswitcher/images/0000755000175000017500000000000011310377556024733 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/uiswitcher/images/NewUI_130.jpg0000644000175000017500000003736011136506632027013 0ustar adrianadrianJFIFHHC     C   "  =?L83pa~@EU_3^\[ʄ, :*{ Tl:-Uy=EК]γo9C㢰Vٓ 01kၭMvǷ<ƕN^?0Viî;jtk& -BSC̿1ۮ X*xHH7m GeEcl%{ǴE<5 SLG|;>ZQ +'Ai"+Fn6 z{Ht.Vj-cV-oszqwN=u>Nֲ\}ώ:} Ec#>t¶ 떅6z3K,?;_Z|nkmM@A0dey쌽IsxtntzWt1^5 sH>]=/r{ sn4ޛM„taIa?=NE9Wca4ԯZ &uL&1*DP׸30 z76?Y[!.&Ms!0a­- KI I I I I I ^ҵ+%͙KLm\}-S풊hRkK:tg,!"%2#$1@C QcC#H)9q ך! d(X雦nf雦nf雦nf雦ng|yHܙܙވ:-UϯW׫CqROûPSjK񬍘)Y9,-:,Yj*iDoITDZfȊKI"/`[}o; >vDPJLnsc?1#VZūkJٸJU~%lFWLEUܴ)/dxete ME%i+%Mi÷Vy(E&G&>tq|㽒v,7*wTlZZ2@qQ"FܵP.scPDdqG>4‚G] [!]X(G5=Tm^65'| !w{QB"c7w"\EBG4ưc;ɒ8q0i+4m *wJgh 1$A"LJ ="H,&ށ`1=$0A#[`9|(e bk4skxq-LHqE7ntty.ys˞\ZXJHMpyRW#EṁfF >PXY~H~2WT.Y)#qwG#?/s'h"3PL-3)l="w}1J:ۿI>Iߥ$_A],wdbbzH_?n~";x?ɜ߷aM tt䱇]Eߧl/"-Q!Ւ|{b*E@ʌ1Y&}3I} `f F$#Eͺ}5d}RLX CK yGf!DT>-ipDi«!r7f݄RoKg#9;1\ș` V6`8UARu+>Vt\l";$բR=FCbrsӤck9ȊkŝUCx+";.>BZT oJ6R7B l+^ގگ~v:po3d'^j:Wϙoz[=fߴjĬ@1!Õ.lN3;c`Oє&p9EEVn x {"~ۥoaf-i9nwbkYoJL+8.!3LƦ6 JÚ@`n>nT}3s &Uܮi5?Lۄ`--ks( qBPc䃵PB Z@nx~<W31Q!"2AaCRq 03?kZB 'YCYT T5]\p%9 +j8AF,R$~J~Jޫz귪ޫz긙)OD&L**TB1 s@hĴ4Odؖ`UvªԜKwll#[ʓbc~e4_HP? i&@b'DvitWV|!Yqs# |N+ C6*#=ΊeH±6 ?udM8ӭ brגeDmZTQQiD@>ztN)iTb9 › \OzO.=2SQCFĀaPsKd⡘L/'SUխ^㨕L> GTF!&R@ Df(nx~x. OH !"1AQ23a#4Rq5Bbrs%CSd$@?G:ub&lYhoя~;i꧂M[vhʒN9ϡ n5а5{鑷nZI1iI\5 դf97;*Qcy[<Zt]Mh] At H.] At H-jFppԮܕbs [1[18swjƿKx7|WWWWTl60Ch"F*M>|;(7CaһBe=J3òitAѮk03YhȬ8Fet[nX#|JM(k9I:~l6ɧ#ЏvO6}ums"ۅl#Be ? x.x&AI]#OIJR[0z`mvdm2YIUM.kWL..]2gtrKp9],hkNsB U=hT4WeJsٞWq%Hg%^Gޜ(,L}gIIӜmĻ%DPr!M\L \#fDܴtqkZr;^_}t۟ڪunWޛc"n4pqe⬊FSAU,eݺ&ނ lV+M>>ed[#K Re$it{ntB7QA3tnz- ihozw~iCx(7QT l ކm>dUgoh:x'Ɇ皮@TRZ+EϹ;Mc714UnjˣES|FuwmڡZiQyn[vt╪ByԪ]AA=i /wpX s3ѤH,O['{@SZ(Y]SϢwhG`t5}*~`-lV,WRRb7ճܷ)34Omm YmI e@Cf)kYuxk(֌]YAgUe M3"gڍ+܇hDlY}+_ZmH!qB-; 4JS&N$NpcNVe;'Hwk,{,NwaT2%\OUʌ[uP:I~ر%vBNbp9atDXBg>:dmM5utgWvݪK Lyۻ3*f8W gգA1G5Kj6bYAGjHs|t,qFbm69kޚY{jltM,lr=@n;2>!d/dLwZdX=Koz@̕YZ\3s0qle4%B"qK5.EE%3cv[~ޏ  ]#|Mےٚ;5kuAVO,42 ę^$k?>eE[7no+6*I} 5fBQNZhm+ڌGyeѝI26 &Yg.VYg.VYg.VYg.VM*c?kcaoFE}5M)w{hMXӠ|U -ôm޺F4TL3ƜQ!ul;;ӟHƊҰ1-v$gg?z`xB^dNRF5zB0AjF4.N%|Q\_\{B7zLN"xi2ӴY"8mm[pF'Cveb&Q!oKց8hX(!1AQaq @?!!n*ER#eH;kyOڀ:prpO~'?}C>PO~'? ~"< `D'Л6[\RpN:GDX `Ip5zCf/@ QJĔHL7ct#t1JjX%rڃ\r]7DMR@TRw KVPmw z33a+ZN بAnj& Fhc)ttS.<@4wQD(} %v@4=Ұ4@ȧ$()'*B@Bê?BЋiu{v`uLF+U~_> A-M)@2OU\SPA oo~B4DH(AT?E=LYX,`[$@I@6t^(i\jȫ#o R!#,,.8xetc.|Frl+0L&25#LTt\Co/'&P@Z@QE!0*U0.|ꁴrf+)S 44#;ʬYQU :=F-21YM?! (^ 3);lx%o. O *AA- 0gGA8;X19A{ cM'7Ä}O'u LјdA.` DC3k*, @PKH0C֡"=&dؒ5f]%+<`VWSe$j5Ӿ%+33w?\YH sB36`1>Of YL p(a&/;(L\ 7Fŕ SqەY2"H# r3rMJ샆6dD%#̆#c =55GeV=9E2n.u>@*n8A,*)*)i$ +ѐ/@\$ sH_Ŭr! > "9$`Sx ,: G~DRQLJ&6CS:0``3[T3AF6pvj ;FEg&H6@:nSZ+bs`/Fj3.D5iB0eC1_DdPnq .B63 6xÙD,(iP(b37HDɞ pT=x)0`+0 Imp1ɍՀHy}"oFTz@8XyXm . xXTϼ ,",i&"g6L\B* ;qF͒9ivNС:)be6$~!@܂?~\J vu*ט ڀ6!X/$W6Ҥ6p[ ؟qC=f<,h(\eSeMKA ar ?82PAn%vDXL4l`E0" /$ɠ{K! lNB*/`*+MKhU5TcGbt5y љE,eD9B.`)#x^: 4s-4L MQѪ)p+ƬE`~=&Gjِ[xNzP!Ƽ;'ul ס +@%XNDps M[8( u{@)oăRqJtu>~ Mo+O@BVE4|x6qǽ}O4F*"~@8 -scK6gϲPP,c]bxdY!85gNǭ1:%QG\Rtɟ)~Vt5&!1AQaq0?"Sұ88Fs5+T[}ofP&PpG|NB iё;O-7`:C֏;֏;wD6u ;MCϪt@޼TV> Oo9: DXEwLy'Dv( Q&=[ªilrHxf|U+n+>CpIa L[@$왉ba3HL@rppLܠreDȐ!\c@At hj.4:iD@7W+:`t(|&'dnA\S H Z(7TA:P@O7 譈sT+ag_.6 !0Rdm-WD @]QIL~).PH _~*^_~/_~_CR|jzlFą@A(I4=ܬlE$'ֿ^@zÄ &A+t3PM]A|L|j9f~0D|;i2-% [jTM-5[knP:׬&.7F[, ]zosng!b;P;j[r`@*k~j)כ56vkͦ^k±AϾLQ46Tj&cbxj.t_9_XF]%4Ԩ;^ mkxJ}U!@SDA־\P|߬2Q 1ig҈NPL6-8Q㼰fqh *i.} `(y71޻ LTS}TӣbKGXpDۿ2BU0~/RccT`*,zx8"n5=j|MY氾r$;x":HB1?mWd[PK㻸gFGgvI k9"CqRR}q)-i43XƠFyLʰȋ VTya_8&(E& q3^?Mlڣ'Y/=+^g (OŊίGn[:R@#y $k4{-uh׃U24+ysjBJ7ug06TD{;6:j7Ia>A*| ~%I;m]e{lxzߌ+BRH1yD9g@w>ϸj}FTQl173NOܺΦB3U'.9œz %ֵ1Ө,p"-#y̪c_M<2T""t%b 3a|l6T I% @^}yqo <|7X$A}r4(6$7 z1V JOED.'f&[x8:7õ]ߌwn YH:N]xT+Wyĕ19$+7쀃>LryV$0S:CR4S' *HyVXR"m[c# %] ?0 N~s*! pVl :l?lQ&AFn$&}5fJHpw{Np @a髫29_@ l(󎕩 q̏['Q5`$E^fȈrs gA1o[aĪ*4+_W4Q; J k<"MPy Irτ'\P) mYϓ<d;VHLr#ssSrP{` @Pm*o67?%7H65OX4jU\-"R*OcI, a#%?z`^.$N8X#&S( `nԑY.i4Hhƫ6CMoe 0a-%kh5)zcYBͥ +ZaPӮjgc8=YJDT҈Q8 aK~ۍ&Ahh*y4L6[*JH}e0]ɞ@">_x\D0(/^Sa=c'8e%0<Ks䵚!bw o2azureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/uiswitcher/images/ClassicUI_130.jpg0000644000175000017500000003265611136506632027646 0ustar adrianadrianJFIFHHC     C   " ^L\eo\\L Hf h`%plC`86 ֻ۷!0X\9gWtZlޚ2K0X9GĕMu6>A&U[JJ& " Jt*4p]νR1pz1_nx0ܰ)1><+mҴHzY:ӟ?\ûk2-(˵&J(ת̷r3T/zgtݫNRh/Es+˅3Z&27J./0~F !/-%%  }\ʕY=3O^񽱖׬ϩہfVU.1nTn}zaXEK2I=O<+%$kĵOǒ.֯nxK?eXR71nDiI;9f(yؒ.CNruW8ϝ<3[lfu]npHv)%z$nKVM&$0N [ooLJ[%|:V6*7xo4Bgkq K- 4-A6 "OB,'"#3!5$2=s[1Z'yN3Pfl+%6aiI7sr\W+r\W++9 qU5LpHVWa jCO?{JS y Vxt'յm[Vյm[Vձl[Vձm[V՗~vRbжxDᲆJ,-U.T#]R%Bē h-[=3ni%<2=!b?ڃK WF:ĴAֱ8Zl_(% sZ(FdjXAU؞vS$ڶŇŪaaG K;{F~濏+Hd}8"~z=}U O;Jcj^ Խu2SZc\2ᕱ\!Dx+!Iy ,pjV _D }/@ _D }/@Rz`0^/L  J62wgP&/Q^|6+E}{:o% x¼a^0Q+l(W4 u)g{f6Z5S+ VzH\D0j%ZZ|mN+(<]'РX@Uɾes ԨEW͊gzgeIJӈᱸ̠m8;J8qd3ǩb"chFRU']ї@oY%3:$ąg+PV&E?g8#տE"*Y:Fjc&ݪ@3x~[B/ '=y w)b^[( 1ZTPhepa&g!h>ar a6q~][Čˌpb)O(jDa.XjEf@8lR d#Ol.vR2 OY+E3Jn^{Oməd9!obr7 bAI̤$LLI$ʾRu[%D3K:L'Na?Id%%LyLv3S,jSѫ|HwwoyG*C4EMo ;KnGUGhվXdrߡ]ÿa;KXߙoޥkh7ԉԍG*&{CT䳿Q :*S!֮tI**j+Qv+z5+]X\_m.B!1"2AQ#34aq$BRr5CbsS c?6D,ثg73F ]l|{LmNF`S k w*j3QG[YVMIɘ:$@4pWg^ 拘LexZۉHx8 ֻz)޺O0]? t.45{OZ?桪mBqL 0ǵ:@4Y,bYŴ]?Gq"^T/x: Siv\s&&{jX] l| h~%_i:^"٫@3:+U #Ļ4 6G,9.zipahupǴv1}1,Ƥv'Yڥv6 .oe7$mh+Em_ibcq*nLHg5%o4]855&bS$C0^3LU*A-lݪp*^"GCZh-bl.Vu: Kuv0D7iJ8T7=]3ܤ3 ɬJȤ]C1ͣFTqX+N0AP2Zc_dx}j &7N$!}1=,4?Eml.yiBSMSLkKRcTt3v5iӷO^*hLtֈ 04'=Rno[^Kkmy-%䶼ג[^Kkmy-%䶼גEF7z,6T +Ds3bYzY`QI>jo敖u$qd]ѓkZ{|i\55oQH9KD9wq.{}S;[S|}V1U7wm[s|}V1T \һyFlwbO|1H+gZA#\**ն~|x{i3QJ%z#c?^Dpeƍ0sэ5, ‚N$EyŽG!%j,lniY^"6)"e1]<ƍ&{>SEfF`bo8fnw , L]FǢbgSQ<φ|Q| GِSL_ LWMx C 5'Odoaf bbbb|bk C nE >S7c#B-]:l1ɨQw:w:Zۼ˰F&:ނGriFlFA#[o$NfQO Yц@rwn }>=lY¹hwO2/z>++uSi~]pRv;#ZÚw=.y ١KD<R7_C]4oY[UvKzf5FyDP&Ꜧj7&ĺĿ^Q)^'f4m)RnvSr:5bfq:kڼau$s }& ڿ#KPnOfw. VK.Cl{kLO\Cf1rܵgf{нi*iO% quGzLSy9 PjwۘN~9fB'L?{F,tQkk8փpRj5jڍv42JKmv?EV5|Krg.}bWDg{}V,.Bh ߈BHkPXD9`FIBFLa;bwbnN]ƨƴHѡF 8Ӝu> X6#BDw&It띁[5_f_|:YwYd7p{\1: d*) Ҩ $o@i;)XdHeD27՗IԌûM@nMnl~"ӿpO ޶4]ep*KY[kn T03-k䶖[Kifw<_$y”% ;<^q];WKbQ㧵 V[Np9UZP0$4)3L j2D&USGk4k.N@7 b볛KܟFLQ}UgwJWnc-XGƝM= Q{8#y2='!1AQaq ?!̀qS4P?am@M)uPy _ g[ F8ސ =RZ/CYb1RǶfdmѷFmѷFmѷFmѷ@[M˦(cc,9|ȱCVD9(\D 0PGIvy-z5RD;`źAlډSV~` ,Z'#pG<Ox?S//)eRd&1;aTzY0~@lwHY4P]B J>p[X&djcӤ$8 0;H!CU+/xv|N7!y8^|NgE m>)d/f@}a 5 gqNaPb@mp'XaEA-R^!׊9*n@^sP b1ŽM^&}D(}1L 5A tNZ^2<,: Q iIJYJfš1 ? UΜ D U!M^<8[D,rpט)alԀ\+6赉Xǵm?\k@${Ag!(hϰhX3mcGhc L޲#J/ .z̴UAU{*2VD ںWumRC<kE|U+$xA Ex&q;N'hV";uPW0Ѥ0dBgx2G!i*P Y RȰOPV'->͚LfXF$u};Bi _t tK`9}ӓ9=9=9=9}ӗ9}ӗ9}ӗ9=ӓ =,Ǵ {NCr'O9h ;*ĿkPjAI0(Q ''&:b HgFzfx(HCDā:|:*4 <CǏ@I$" 5]XETxf&!^B`NִH#fN }uP'f@lN4R@CX8碾!tXe.}<xs>>g};|<>g}<PȖ D JEb6 psϸAa8M;q8A1GaK'!1AqQa 0?7޺n;3֛U_ "LSbWfS)eJ*VAm\?j)z`JnV`:i Z<+{)U xju':U8(8,|zy 8u[},d_qY)XxDӜ\?|8s4䨖Tt=w˄B2Mw )?Ub,-olzKw}lNyGG|M{j:E w·>0E*sr@T*U>jNF;㣾\歙l'o9XJJKh[v"@wDrݝj2xUf8= o?ŎM'!1AQaq0?*oM^&&%i 9zLsh[%%%%%%%%=Zo)V׌DojS|MY,K%Po~-y#,EAGo:نqhٜWF ż?=jO#|<)K#a{rpɦ]*PxWq+qj~OkCpNJMi;`ogϷi/= 0 yoÿ8\h&`8sP9? ?G.~V׿y]IE'.܈m10Ou)AYZt1`|q)<3Ïii pҫM3iRKJSWgAE˧N;qr:*mh-5E9YѨ$4 Gl!(!1AQaq 0?zuN H6  ב'`mxXugZMUi%o ?Hhta'Q9;a-Ӑ [|M2,M*yL]EAZ6: 0Rx&Mg\ٕH>pPT:2 E!imG&w8 A_Գ X1LtBކbZB\x2 >1ɖXhZZRVvH%h;fќ ڪ.^};wb>YH9B_Q/glgퟌ~3~?gl/ퟅ~?eƱ?~'|k><罽Z_?W._i:t'+31:F<V2K u_8Tŋcv,G90# 3mU/ij5fh%&kF z~ߊT#ۧn 䬢1ĸY,XbNf 7f6 :݌N PG0/&{9TK=C`VP J1S?'AZ:Ca2lY0ҋ,mPk8L+@0Sl Q1z A)D+oLb8jx`1KX"d.iw];#Hk77*Pɓ#Aҧ^k-(`X9q !~zĘJx* 50 2}o^bD-'r w~pEĸ kzrb^uw*QXj,Y'7ut oC}Z') F/ rY}8(xV]!_^~'H nw} FT։C5ۮqļ`$t PH `6x* ТEQe1H尰 G U'Wr̯ '_'^և)1DZ]X8x1=8ǀ+wQTdK]g&PtħڶlGx ׀Ƣ&(Kڇp.} nxvtAk牗$[GHNsUiO v9C uSljl0bSF]tU]L7*@b | ~C-قE', p:6E]/ҁ Zy sग़4k4{T|Q$^|`tUub/g+H}g|b] 'ZBbAT3 "Eae]K6'p'1?888G+<^d$P***̨0X7jbNdxIwJNMl]bECo~(D;] %mVbp >+VE'ByH_ /wE  z "B1z z+ښ2dɓ&L2dᙆL%c/I"j_qsazureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/uiswitcher/UISwitcherWindow.java0000644000175000017500000002273611276126552027560 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.shells.uiswitcher; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.UISwitcherUtil; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; /** * @author TuxPaper * @created Feb 5, 2007 * */ public class UISwitcherWindow { private static String CFG_PREFIX = "window.uiswitcher."; private static String RESOURCE_LOC = "com/aelitis/azureus/ui/swt/shells/uiswitcher/images/"; private static String[] IMAGES = { "NewUI_130.jpg", "ClassicUI_130.jpg" }; private static String[] IDS = { "NewUI", "ClassicUI" }; private Shell shell; private Button btnOk; private int ui = -1; private List disposeList = new ArrayList(); public UISwitcherWindow() { // XXX forcing to allowCancel is temporary this(null, true); } /** * */ public UISwitcherWindow(Shell parentShell, final boolean allowCancel) { final String originalUIMode = UISwitcherUtil.calcUIMode(); try { final Image[] images = new Image[IMAGES.length]; final Button[] buttons = new Button[IMAGES.length]; GridData gd; int style = SWT.BORDER | SWT.TITLE | SWT.RESIZE; if (allowCancel) { style |= SWT.CLOSE; } shell = ShellFactory.createShell(parentShell, style); shell.setText(MessageText.getString(CFG_PREFIX + "title")); Utils.setShellIcon(shell); shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { Utils.disposeSWTObjects(disposeList); if (ui == 0) { // Full AZ3UI COConfigurationManager.setParameter("ui", "az3"); } else if (ui == 1) { COConfigurationManager.setParameter("ui", "az2"); } if (ui != -1) { COConfigurationManager.setParameter("ui.asked", true); UISwitcherUtil.triggerListeners(UISwitcherUtil.calcUIMode()); } } }); Display display = shell.getDisplay(); ClassLoader cl = UISwitcherWindow.class.getClassLoader(); GridLayout layout = new GridLayout(); layout.horizontalSpacing = 0; layout.marginWidth = 5; layout.marginHeight = 0; layout.verticalSpacing = 1; shell.setLayout(layout); Label title = new Label(shell, SWT.WRAP); gd = new GridData(GridData.FILL_HORIZONTAL); gd.verticalIndent = 3; title.setLayoutData(gd); Messages.setLanguageText(title, CFG_PREFIX + "text"); Listener radioListener = new Listener() { public void handleEvent(Event event) { int idx; if (event.widget instanceof Composite) { Long l = (Long) event.widget.getData("INDEX"); idx = l.intValue(); } else { Composite c = ((Control) event.widget).getParent(); Long l = (Long) c.getData("INDEX"); idx = l.intValue(); } for (int i = 0; i < buttons.length; i++) { boolean selected = idx == i; Composite c = buttons[i].getParent(); c.getParent().setBackground( selected ? c.getDisplay().getSystemColor( SWT.COLOR_LIST_SELECTION) : null); Color fg = selected ? c.getDisplay().getSystemColor( SWT.COLOR_LIST_SELECTION_TEXT) : null; Control[] children = c.getChildren(); for (int j = 0; j < children.length; j++) { Control control = children[j]; control.setForeground(fg); } buttons[i].setSelection(selected); } } }; FontData[] fontData = shell.getFont().getFontData(); fontData[0].setHeight((int) (fontData[0].getHeight() * 1.5)); fontData[0].setStyle(SWT.BOLD); final Font headerFont = new Font(shell.getDisplay(), fontData); disposeList.add(headerFont); for (int i = 0; i < IMAGES.length; i++) { String id = IMAGES[i]; final Composite c = new Composite(shell, SWT.NONE); c.setBackgroundMode(SWT.INHERIT_DEFAULT); gd = new GridData(GridData.FILL_BOTH); gd.verticalIndent = 0; c.setLayoutData(gd); GridLayout gridLayout = new GridLayout(2, false); gridLayout.horizontalSpacing = 0; gridLayout.marginWidth = 5; gridLayout.marginHeight = 3; gridLayout.verticalSpacing = 0; c.setLayout(gridLayout); c.setData("INDEX", new Long(i)); c.addListener(SWT.MouseDown, radioListener); Label label = new Label(c, SWT.CENTER); label.addListener(SWT.MouseDown, radioListener); try { InputStream is = cl.getResourceAsStream(RESOURCE_LOC + id); if (is != null) { images[i] = new Image(display, is); label.setImage(images[i]); disposeList.add(images[i]); } } catch (Exception e) { e.printStackTrace(); } Composite c2 = new Composite(c, SWT.NONE); c2.setBackgroundMode(SWT.INHERIT_FORCE); c2.setData("INDEX", new Long(i)); c2.setLayout(new GridLayout()); c2.setLayoutData(new GridData(GridData.FILL_BOTH)); buttons[i] = new Button(c2, SWT.RADIO); buttons[i].setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); Messages.setLanguageText(buttons[i], CFG_PREFIX + IDS[i] + ".title"); buttons[i].setData("INDEX", new Long(i)); buttons[i].addListener(SWT.Selection, radioListener); buttons[i].setFont(headerFont); buttons[i].addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ARROW_NEXT) { e.doit = true; e.detail = SWT.TRAVERSE_TAB_NEXT; } else if (e.detail == SWT.TRAVERSE_ARROW_PREVIOUS) { e.detail = SWT.TRAVERSE_TAB_PREVIOUS; e.doit = true; } else if (e.detail == SWT.TRAVERSE_TAB_NEXT || e.detail == SWT.TRAVERSE_TAB_PREVIOUS) { btnOk.setFocus(); e.doit = false; } else if (e.detail == SWT.TRAVERSE_RETURN) { e.doit = true; } else if (e.detail == SWT.TRAVERSE_ESCAPE) { e.doit = false; if (allowCancel) { ui = -1; shell.dispose(); } } else { e.doit = false; } } }); buttons[i].addListener(SWT.KeyDown, new Listener() { // @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) public void handleEvent(Event event) { if (event.keyCode == SWT.ARROW_UP) { shell.getDisplay().getFocusControl().traverse( SWT.TRAVERSE_ARROW_PREVIOUS); } else if (event.keyCode == SWT.ARROW_DOWN) { shell.getDisplay().getFocusControl().traverse( SWT.TRAVERSE_ARROW_NEXT); } } }); Label info = new Label(c2, SWT.WRAP); gd = new GridData(GridData.FILL_BOTH); gd.horizontalIndent = 20; info.setLayoutData(gd); Messages.setLanguageText(info, CFG_PREFIX + IDS[i] + ".text"); info.addListener(SWT.MouseDown, radioListener); } Event eventSelectFirst = new Event(); eventSelectFirst.widget = buttons[0]; radioListener.handleEvent(eventSelectFirst); Composite cBottom = new Composite(shell, SWT.NONE); layout = new GridLayout(2, false); layout.marginHeight = 0; layout.marginWidth = 0; cBottom.setLayout(layout); cBottom.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Label lblBottom = new Label(cBottom, SWT.WRAP); Messages.setLanguageText(lblBottom, "window.uiswitcher.bottom.text"); gd = Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER); gd.horizontalIndent = 10; lblBottom.setLayoutData(gd); btnOk = new Button(cBottom, SWT.PUSH); Messages.setLanguageText(btnOk, "Button.ok"); shell.setDefaultButton(btnOk); btnOk.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { for (int i = 0; i < buttons.length; i++) { if (buttons[i].getSelection()) { ui = i; break; } } shell.dispose(); } }); gd = new GridData(GridData.HORIZONTAL_ALIGN_END); gd.widthHint = 80; btnOk.setLayoutData(gd); Point point = shell.computeSize(630, SWT.DEFAULT); shell.setSize(point); Utils.centreWindow(shell); } catch (Exception e) { e.printStackTrace(); } } public void open() { shell.open(); } public static void main(String[] args) { Display display = Display.getDefault(); UISwitcherWindow window = new UISwitcherWindow(null, false); Shell shell = window.shell; while (!shell.isDisposed()) { if (!shell.getDisplay().readAndDispatch()) { shell.getDisplay().sleep(); } } System.out.println(window.ui); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/BrowserWindow.java0000644000175000017500000001450711273703132024754 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.shells; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import com.aelitis.azureus.core.messenger.ClientMessageContext; import com.aelitis.azureus.ui.swt.browser.BrowserContext; import com.aelitis.azureus.ui.swt.browser.listener.ConfigListener; import com.aelitis.azureus.ui.swt.browser.listener.DisplayListener; import com.aelitis.azureus.ui.swt.browser.listener.TorrentListener; import com.aelitis.azureus.ui.swt.browser.listener.VuzeListener; /** * @author TuxPaper * @created Oct 6, 2006 * */ public class BrowserWindow { private Shell shell; private ClientMessageContext context; private Browser browser; public BrowserWindow(Shell parent, String url, double wPct, double hPct, boolean allowResize, boolean isModal) { if (parent == null) { init(parent, url, 0, 0, allowResize, isModal); } else { Rectangle clientArea = parent.getClientArea(); init(parent, url, (int) (clientArea.width * wPct), (int) (clientArea.height * hPct), allowResize, isModal); } } /** * @param url * @param w * @param h * @param allowResize */ public BrowserWindow(Shell parent, String url, int w, int h, boolean allowResize, boolean isModal) { init(parent, url, w, h, allowResize, isModal); } public void init(Shell parent, String url, int w, int h, boolean allowResize, boolean isModal) { int style = SWT.DIALOG_TRIM; if (allowResize) { style |= SWT.RESIZE; } if (isModal) { style |= SWT.APPLICATION_MODAL; } shell = ShellFactory.createShell(parent, style); shell.setLayout(new FillLayout()); Utils.setShellIcon(shell); shell.setText(url); shell.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { shell.dispose(); e.doit = false; } } }); final Listener escListener = new Listener() { public void handleEvent(Event event) { if (event.keyCode == 27) { shell.dispose(); } } }; shell.getDisplay().addFilter(SWT.KeyDown, escListener); shell.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event event) { event.display.removeFilter(SWT.KeyDown, escListener); } }); browser = Utils.createSafeBrowser(shell, SWT.NONE); if (browser == null) { shell.dispose(); return; } context = new BrowserContext("browser-window" + Math.random(), browser, null, true); context.addMessageListener(new TorrentListener()); context.addMessageListener(new VuzeListener()); context.addMessageListener(new DisplayListener(browser)); context.addMessageListener(new ConfigListener(browser)); browser.addProgressListener(new ProgressListener() { public void completed(ProgressEvent event) { if (browser.isDisposed() || browser.getShell().isDisposed()) { return; } shell.open(); } public void changed(ProgressEvent event) { } }); browser.addCloseWindowListener(new CloseWindowListener() { public void close(WindowEvent event) { if (browser.isDisposed() || browser.getShell().isDisposed()) { return; } context.debug("window.close called"); shell.dispose(); } }); browser.addTitleListener(new TitleListener() { public void changed(TitleEvent event) { if (browser.isDisposed() || browser.getShell().isDisposed()) { return; } shell.setText(event.title); } }); browser.addStatusTextListener(new StatusTextListener() { public void changed(StatusTextEvent event) { if (browser.isDisposed() || browser.getShell().isDisposed()) { return; } if(MessageBoxShell.STATUS_TEXT_CLOSE.equals(event.text)) { //For some reason disposing the shell / browser in the same Thread makes //ieframe.dll crash on windows. Utils.execSWTThreadLater(0, new Runnable() { public void run() { if(!browser.isDisposed() && ! shell.isDisposed()) { shell.close(); } } }); } } }); SimpleTimer.addEvent("showWin", SystemTime.getOffsetTime(3000), new TimerEventPerformer() { public void perform(TimerEvent event) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (shell != null && !shell.isDisposed()) { shell.open(); } } }); } }); if (w > 0 && h > 0) { Rectangle computeTrim = shell.computeTrim(0, 0, w, h); shell.setSize(computeTrim.width, computeTrim.height); //shell.setSize(w, h); } Utils.centerWindowRelativeTo(shell, parent); browser.setUrl(url); browser.setData("StartURL", url); } public void waitUntilClosed() { Display display = shell.getDisplay(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } public ClientMessageContext getContext() { return( context ); } public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display, SWT.DIALOG_TRIM); new BrowserWindow(shell, "http://google.com", 500, 200, true, false); shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/main/0000755000175000017500000000000011310377632022217 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/main/MainWindow.java0000644000175000017500000020411611305664420025140 0ustar adrianadrian/* * Created on May 29, 2006 2:07:38 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.shells.main; import java.io.*; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.URLDecoder; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.impl.ConfigurationChecker; import org.gudy.azureus2.core3.config.impl.ConfigurationDefaults; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.global.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.plugins.ui.sidebar.SideBarEntry; import org.gudy.azureus2.plugins.ui.sidebar.SideBarOpenListener; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.associations.AssociationChecker; import org.gudy.azureus2.ui.swt.debug.ObfusticateShell; import org.gudy.azureus2.ui.swt.donations.DonationWindow; import org.gudy.azureus2.ui.swt.mainwindow.*; import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar; import org.gudy.azureus2.ui.swt.minibar.MiniBarManager; import org.gudy.azureus2.ui.swt.plugins.UISWTInstance; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.shells.MessageSlideShell; import org.gudy.azureus2.ui.swt.views.IView; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import org.gudy.azureus2.ui.systray.SystemTraySWT; import com.aelitis.azureus.activities.VuzeActivitiesManager; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.core.messenger.ClientMessageContext; import com.aelitis.azureus.core.messenger.PlatformMessenger; import com.aelitis.azureus.core.messenger.browser.BrowserMessage; import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher; import com.aelitis.azureus.core.messenger.config.*; import com.aelitis.azureus.core.messenger.config.PlatformConfigMessenger.PlatformLoginCompleteListener; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; import com.aelitis.azureus.launcher.Launcher; import com.aelitis.azureus.ui.IUIIntializer; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.skin.SkinConstants; import com.aelitis.azureus.ui.swt.*; import com.aelitis.azureus.ui.swt.Initializer; import com.aelitis.azureus.ui.swt.columns.utils.TableColumnCreatorV3; import com.aelitis.azureus.ui.swt.extlistener.StimulusRPC; import com.aelitis.azureus.ui.swt.skin.*; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter; import com.aelitis.azureus.ui.swt.utils.PlayNowList; import com.aelitis.azureus.ui.swt.views.skin.*; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager.SkinViewManagerListener; import com.aelitis.azureus.ui.swt.views.skin.sidebar.*; import com.aelitis.azureus.util.*; /** * @author TuxPaper * @created May 29, 2006 * */ public class MainWindow implements IMainWindow, ObfusticateShell, SideBarListener, AEDiagnosticsEvidenceGenerator, SideBarLogIdListener { private static final LogIDs LOGID = LogIDs.GUI; protected Shell shell; private Display display; private AzureusCore core; private IUIIntializer uiInitializer; private SWTSkin skin; private MainMenu menu; private UISWTInstanceImpl uiSWTInstanceImpl; private UIFunctionsImpl uiFunctions; private SystemTraySWT systemTraySWT; private static Map mapTrackUsage = null; private final static AEMonitor mapTrackUsage_mon = new AEMonitor( "mapTrackUsage"); private long lCurrentTrackTime = 0; private long lCurrentTrackTimeIdle = 0; private boolean disposedOrDisposing; private DownloadManager[] dms_Startup; protected boolean isReady = false; private MainStatusBar statusBar; private String lastShellStatus = null; private Color colorSearchTextBG; private Color colorSearchTextFGdef; private Color colorSearchTextFG; private boolean delayedCore; public static void main(String args[]) { if (Launcher.checkAndLaunch(MainWindow.class, args)) return; Initializer.main(new String[0]); //org.gudy.azureus2.ui.swt.Main.main(args); } /** * Old Initializer. AzureusCore is required to be started * * @param core * @param display * @param uiInitializer */ public MainWindow(AzureusCore core, Display display, final IUIIntializer uiInitializer) { delayedCore = false; this.core = core; this.display = display; this.uiInitializer = uiInitializer; AEDiagnostics.addEvidenceGenerator(this); disposedOrDisposing = false; // Hack for 3014 -> 3016 upgrades on Vista who become an Administrator // user after restart. if (Constants.isWindows && System.getProperty("os.name").indexOf("Vista") > 0 && !COConfigurationManager.getBooleanParameter("vista.adminquit")) { File fileFromInstall = FileUtil.getApplicationFile("license.txt"); if (fileFromInstall.exists() && fileFromInstall.lastModified() < new GregorianCalendar(2007, 06, 13).getTimeInMillis()) { // install older than 3016 GlobalManager gm = core.getGlobalManager(); if (gm != null && gm.getDownloadManagers().size() == 0 && gm.getStats().getTotalProtocolBytesReceived() < 1024 * 1024 * 100) { File fileTestWrite = FileUtil.getApplicationFile("testwrite.dll"); fileTestWrite.deleteOnExit(); try { FileOutputStream fos = new FileOutputStream(fileTestWrite); fos.write(23); fos.close(); COConfigurationManager.setParameter("vista.adminquit", true); MessageBoxShell mb = new MessageBoxShell( MessageText.getString("mb.azmustclose.title"), MessageText.getString("mb.azmustclose.text"), new String[] { MessageText.getString("Button.ok") }, 0); mb.open(null); mb.waitUntilClosed(); if (uiInitializer != null) { uiInitializer.abortProgress(); } dispose(false, false); return; } catch (Exception e) { } } } } Utils.execSWTThread(new AERunnable() { public void runSupport() { try { createWindow(uiInitializer); } catch (Throwable e) { Logger.log(new LogAlert(false, "Error Initialize MainWindow", e)); } if (uiInitializer != null) { uiInitializer.abortProgress(); } } }); // When a download is added, check for new meta data and // un-"wait state" the rating // TODO: smart refreshing of meta data ("Refresh On" attribute) GlobalManager gm = core.getGlobalManager(); dms_Startup = (DownloadManager[]) gm.getDownloadManagers().toArray( new DownloadManager[0]); gm.addListener(new GlobalManagerListener() { public void seedingStatusChanged(boolean seeding_only_mode, boolean b) { } public void downloadManagerRemoved(DownloadManager dm) { } public void downloadManagerAdded(final DownloadManager dm) { downloadAdded(new DownloadManager[] { dm }); } public void destroyed() { } public void destroyInitiated() { } }, false); gm.addDownloadWillBeRemovedListener(new GlobalManagerDownloadWillBeRemovedListener() { public void downloadWillBeRemoved(DownloadManager dm, boolean remove_torrent, boolean remove_data) throws GlobalManagerDownloadRemovalVetoException { TOTorrent torrent = dm.getTorrent(); if (PlatformTorrentUtils.isContentDRM(torrent) && remove_data) { String prefix = "v3.mb.deletePurchased."; String title = MessageText.getString(prefix + "title"); String text = MessageText.getString(prefix + "text", new String[] { dm.getDisplayName() }); MessageBoxShell mb = new MessageBoxShell(title, text, new String[] { MessageText.getString(prefix + "button.delete"), MessageText.getString(prefix + "button.cancel") }, 1); mb.setRelatedObject(dm); mb.open(null); int result = mb.waitUntilClosed(); if (result != 0) { throw new GlobalManagerDownloadRemovalVetoException("", true); } } } }); Alerts.addListener(new Alerts.AlertListener() { public boolean allowPopup(Object[] relatedObjects, int configID) { DownloadManager dm = (DownloadManager) LogRelationUtils.queryForClass( relatedObjects, DownloadManager.class); if (dm == null) { return true; } if (dm.getDownloadState().getFlag(DownloadManagerState.FLAG_LOW_NOISE)) { return false; } HashWrapper hw; try { hw = dm.getTorrent().getHashWrapper(); if (PlayNowList.contains(hw)) { return false; } } catch (TOTorrentException e) { } return true; } }); } /** * New Initializer. AzureusCore does not need to be started. * Use {@link #init(AzureusCore)} when core is available. * * @param display * @param uiInitializer */ public MainWindow(final Display display, final IUIIntializer uiInitializer) { delayedCore = true; this.display = display; this.uiInitializer = uiInitializer; Utils.execSWTThread(new AERunnable() { public void runSupport() { try { createWindow(uiInitializer); } catch (Throwable e) { Logger.log(new LogAlert(false, "Error Initialize MainWindow", e)); } while (!display.isDisposed() && display.readAndDispatch()); } }); } /** * Called only on STARTUP_UIFIRST */ public void init(final AzureusCore core) { Utils.execSWTThread(new AERunnable() { public void runSupport() { _init(core); if (uiInitializer != null) { uiInitializer.abortProgress(); } } }); } /** * Called only on STARTUP_UIFIRST */ public void _init(AzureusCore core) { this.core = core; AEDiagnostics.addEvidenceGenerator(this); disposedOrDisposing = false; if (!Constants.isSafeMode && COConfigurationManager.getBooleanParameter("Open Transfer Bar On Start")) { uiFunctions.showGlobalTransferBar(); } // Hack for 3014 -> 3016 upgrades on Vista who become an Administrator // user after restart. if (Constants.isWindows && System.getProperty("os.name").indexOf("Vista") > 0 && !COConfigurationManager.getBooleanParameter("vista.adminquit")) { File fileFromInstall = FileUtil.getApplicationFile("license.txt"); if (fileFromInstall.exists() && fileFromInstall.lastModified() < new GregorianCalendar(2007, 06, 13).getTimeInMillis()) { // install older than 3016 GlobalManager gm = core.getGlobalManager(); if (gm != null && gm.getDownloadManagers().size() == 0 && gm.getStats().getTotalProtocolBytesReceived() < 1024 * 1024 * 100) { File fileTestWrite = FileUtil.getApplicationFile("testwrite.dll"); fileTestWrite.deleteOnExit(); try { FileOutputStream fos = new FileOutputStream(fileTestWrite); fos.write(23); fos.close(); COConfigurationManager.setParameter("vista.adminquit", true); MessageBoxShell mb = new MessageBoxShell( MessageText.getString("mb.azmustclose.title"), MessageText.getString("mb.azmustclose.text"), new String[] { MessageText.getString("Button.ok") }, 0); mb.open(null); mb.waitUntilClosed(); if (uiInitializer != null) { uiInitializer.abortProgress(); } dispose(false, false); return; } catch (Exception e) { } } } } StimulusRPC.hookListeners(core, this); uiSWTInstanceImpl = new UISWTInstanceImpl(core); uiSWTInstanceImpl.init(uiInitializer); VuzeActivitiesManager.initialize(core); // When a download is added, check for new meta data and // un-"wait state" the rating // TODO: smart refreshing of meta data ("Refresh On" attribute) GlobalManager gm = core.getGlobalManager(); dms_Startup = (DownloadManager[]) gm.getDownloadManagers().toArray( new DownloadManager[0]); gm.addListener(new GlobalManagerListener() { public void seedingStatusChanged(boolean seeding_only_mode, boolean b) { } public void downloadManagerRemoved(DownloadManager dm) { } public void downloadManagerAdded(final DownloadManager dm) { downloadAdded(new DownloadManager[] { dm }); } public void destroyed() { } public void destroyInitiated() { } }, false); gm.addDownloadWillBeRemovedListener(new GlobalManagerDownloadWillBeRemovedListener() { public void downloadWillBeRemoved(DownloadManager dm, boolean remove_torrent, boolean remove_data) throws GlobalManagerDownloadRemovalVetoException { TOTorrent torrent = dm.getTorrent(); if (PlatformTorrentUtils.isContentDRM(torrent) && remove_data) { String prefix = "v3.mb.deletePurchased."; String title = MessageText.getString(prefix + "title"); String text = MessageText.getString(prefix + "text", new String[] { dm.getDisplayName() }); MessageBoxShell mb = new MessageBoxShell(title, text, new String[] { MessageText.getString(prefix + "button.delete"), MessageText.getString(prefix + "button.cancel") }, 1); mb.setRelatedObject(dm); mb.open(null); int result = mb.waitUntilClosed(); if (result != 0) { throw new GlobalManagerDownloadRemovalVetoException("", true); } } } }); Alerts.addListener(new Alerts.AlertListener() { public boolean allowPopup(Object[] relatedObjects, int configID) { DownloadManager dm = (DownloadManager) LogRelationUtils.queryForClass( relatedObjects, DownloadManager.class); if (dm == null) { return true; } if (dm.getDownloadState().getFlag(DownloadManagerState.FLAG_LOW_NOISE)) { return false; } HashWrapper hw; try { hw = dm.getTorrent().getHashWrapper(); if (PlayNowList.contains(hw)) { return false; } } catch (TOTorrentException e) { } return true; } }); core.triggerLifeCycleComponentCreated(uiFunctions); processStartupDMS(); } private void processStartupDMS() { // must be in a new thread because we don't want to block // initilization or any other add listeners AEThread2 thread = new AEThread2("v3.mw.dmAdded", true) { public void run() { long startTime = SystemTime.getCurrentTime(); if (dms_Startup == null || dms_Startup.length == 0) { dms_Startup = null; return; } downloadAdded(dms_Startup); dms_Startup = null; System.out.println("psDMS " + (SystemTime.getCurrentTime() - startTime) + "ms"); } }; thread.setPriority(Thread.MIN_PRIORITY); thread.start(); } private void downloadAdded(final DownloadManager[] dms) { boolean oneIsNotPlatform = false; for (final DownloadManager dm : dms) { if (dm == null) { continue; } DownloadManagerState dmState = dm.getDownloadState(); final TOTorrent torrent = dm.getTorrent(); if (torrent == null) { continue; } String hash = null; try { hash = torrent.getHashWrapper().toBase32String(); } catch (TOTorrentException e) { Debug.out(e); } String title = PlatformTorrentUtils.getContentTitle(torrent); if (title != null && title.length() > 0 && dmState.getDisplayName() == null) { dmState.setDisplayName(title); } if (ConfigurationChecker.isNewVersion() && dm.getAssumedComplete()) { String lastVersion = COConfigurationManager.getStringParameter("Last Version"); if (org.gudy.azureus2.core3.util.Constants.compareVersions(lastVersion, "3.1.1.1") <= 0) { long completedTime = dmState.getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_COMPLETED_TIME); if (completedTime < SystemTime.getOffsetTime(-(1000 * 60))) { PlatformTorrentUtils.setHasBeenOpened(dm, true); } } } boolean isContent = PlatformTorrentUtils.isContent(torrent, true) || PlatformTorrentUtils.getContentNetworkID(torrent) == ContentNetwork.CONTENT_NETWORK_VHDNL; if (!oneIsNotPlatform && !isContent && !dmState.getFlag(DownloadManagerState.FLAG_LOW_NOISE)) { oneIsNotPlatform = true; } final String fHash = hash; if (isContent) { long now = SystemTime.getCurrentTime(); long expiresOn = PlatformTorrentUtils.getExpiresOn(torrent); if (expiresOn > now) { SimpleTimer.addEvent("dm Expirey", expiresOn, new TimerEventPerformer() { public void perform(TimerEvent event) { dm.getDownloadState().setFlag( DownloadManagerState.FLAG_LOW_NOISE, true); ManagerUtils.remove(dm, null, true, true); } }); } } // isContent } if (oneIsNotPlatform && dms_Startup == null) { DonationWindow.checkForDonationPopup(); } } /** * @param uiInitializer * */ protected void createWindow(IUIIntializer uiInitializer) { long startTime = SystemTime.getCurrentTime(); uiFunctions = new UIFunctionsImpl(this); UIFunctionsManager.setUIFunctions(uiFunctions); Utils.disposeComposite(shell); increaseProgress(uiInitializer, "splash.initializeGui"); System.out.println("UIFunctions/ImageLoad took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); shell = new Shell(display, SWT.SHELL_TRIM); if (Constants.isWindows) { try { Class ehancerClass = Class.forName("org.gudy.azureus2.ui.swt.win32.Win32UIEnhancer"); Method method = ehancerClass.getMethod("initMainShell", new Class[] { Shell.class }); method.invoke(null, new Object[] { shell }); } catch (Exception e) { Debug.printStackTrace(e); } } try { shell.setData("class", this); shell.setText("Vuze"); Utils.setShellIcon(shell); Utils.linkShellMetricsToConfig(shell, "window"); //Shell activeShell = display.getActiveShell(); //shell.setVisible(true); //shell.moveBelow(activeShell); System.out.println("new shell took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); PlatformConfigMessenger.addPlatformLoginCompleteListener(new PlatformLoginCompleteListener() { public void platformLoginComplete() { Utils.execSWTThread(new AERunnable() { public void runSupport() { setupUsageTracker(); } }); } }); PlatformDevicesMessenger.setupDeviceSender(); increaseProgress(uiInitializer, "v3.splash.initSkin"); skin = SWTSkinFactory.getInstance(); /* * KN: passing the skin to the uifunctions so it can be used by UIFunctionsSWT.createMenu() */ uiFunctions.setSkin(skin); System.out.println("new shell setup took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); initSkinListeners(); increaseProgress(uiInitializer, "v3.splash.initSkin"); System.out.println("skinlisteners init took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); skin.initialize(shell, "main.shell", uiInitializer); increaseProgress(uiInitializer, "v3.splash.initSkin"); System.out.println("skin init took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); menu = new MainMenu(skin, shell); shell.setData("MainMenu", menu); System.out.println("MainMenu init took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); if (Constants.isOSX) { if (Utils.isCarbon) { try { Class ehancerClass = Class.forName("org.gudy.azureus2.ui.swt.osx.CarbonUIEnhancer"); Method method = ehancerClass.getMethod("registerToolbarToggle", new Class[] { Shell.class }); method.invoke(null, new Object[] { shell }); } catch (Exception e) { Debug.printStackTrace(e); } } else if (Utils.isCocoa) { try { Class ehancerClass = Class.forName("org.gudy.azureus2.ui.swt.osx.CocoaUIEnhancer"); Method mGetInstance = ehancerClass.getMethod("getInstance", new Class[0]); Object claObj = mGetInstance.invoke(null, new Object[0]); Method mregTBToggle = claObj.getClass().getMethod( "registerToolbarToggle", new Class[] { Shell.class }); if (mregTBToggle != null) { mregTBToggle.invoke(claObj, new Object[] { shell }); } } catch (Throwable e) { Debug.printStackTrace(e); } } Listener toggleListener = new Listener() { public void handleEvent(Event event) { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { tb.flipShowText(); } } }; shell.addListener(SWT.Expand, toggleListener); shell.addListener(SWT.Collapse, toggleListener); } System.out.println("createWindow init took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); increaseProgress(uiInitializer, "v3.splash.initSkin"); skin.layout(); System.out.println("skin layout took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); try { Utils.createTorrentDropTarget(shell, false); } catch (Throwable e) { Logger.log(new LogEvent(LOGID, "Drag and Drop not available", e)); } shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { dispose(false, false); } }); shell.addShellListener(new ShellAdapter() { public void shellClosed(ShellEvent event) { if (disposedOrDisposing) { return; } if (systemTraySWT != null && COConfigurationManager.getBooleanParameter("Enable System Tray") && COConfigurationManager.getBooleanParameter("Close To Tray")) { minimizeToTray(event); } else { event.doit = dispose(false, false); } } public void shellActivated(ShellEvent e) { Shell shellAppModal = Utils.findFirstShellWithStyle(SWT.APPLICATION_MODAL); if (shellAppModal != null) { shellAppModal.forceActive(); } else { shell.forceActive(); } } public void shellIconified(ShellEvent event) { if (disposedOrDisposing) { return; } if (systemTraySWT != null && COConfigurationManager.getBooleanParameter("Enable System Tray") && COConfigurationManager.getBooleanParameter("Minimize To Tray")) { minimizeToTray(event); } } public void shellDeiconified(ShellEvent e) { if (Constants.isOSX && COConfigurationManager.getBooleanParameter("Password enabled")) { shell.setVisible(false); if (PasswordWindow.showPasswordWindow(display)) { shell.setVisible(true); } } } }); increaseProgress(uiInitializer, "v3.splash.initSkin"); System.out.println("pre skin widgets init took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); if (core != null) { StimulusRPC.hookListeners(core, this); } increaseProgress(uiInitializer, "v3.splash.initSkin"); System.out.println("hooks init took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); initWidgets(); System.out.println("skin widgets (1/2) init took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); initWidgets2(); increaseProgress(uiInitializer, "v3.splash.initSkin"); System.out.println("skin widgets init took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { setupSideBar(sidebar); } else { SkinViewManager.addListener(new SkinViewManagerListener() { public void skinViewAdded(SkinView skinview) { if (skinview instanceof SideBar) { setupSideBar((SideBar) skinview); } } }); } System.out.println("pre SWTInstance init took " + (SystemTime.getCurrentTime() - startTime) + "ms"); increaseProgress(uiInitializer, "v3.splash.hookPluginUI"); startTime = SystemTime.getCurrentTime(); TableColumnCreatorV3.initCoreColumns(); System.out.println("Init Core Columns took " + (SystemTime.getCurrentTime() - startTime) + "ms"); increaseProgress(uiInitializer, "v3.splash.hookPluginUI"); startTime = SystemTime.getCurrentTime(); if (core != null) { // attach the UI to plugins // Must be done before initializing views, since plugins may register // table columns and other objects uiSWTInstanceImpl = new UISWTInstanceImpl(core); uiSWTInstanceImpl.init(uiInitializer); //uiSWTInstanceImpl.addView(UISWTInstance.VIEW_MYTORRENTS, // "PieceGraphView", new PieceGraphView()); } System.out.println("SWTInstance init took " + (SystemTime.getCurrentTime() - startTime) + "ms"); increaseProgress(uiInitializer, "splash.initializeGui"); startTime = SystemTime.getCurrentTime(); } catch (Throwable t) { Debug.out(t); } finally { String configID = SkinConstants.VIEWID_PLUGINBAR + ".visible"; if (false == ConfigurationDefaults.getInstance().doesParameterDefaultExist( configID)) { COConfigurationManager.setBooleanDefault(configID, true); } setVisible(WINDOW_ELEMENT_TOPBAR, COConfigurationManager.getBooleanParameter(configID) && COConfigurationManager.getIntParameter("User Mode") > 1); setVisible(WINDOW_ELEMENT_TABBAR, true); shell.layout(true, true); System.out.println("shell.layout took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); showMainWindow(); //================ increaseProgress(uiInitializer, "splash.initializeGui"); System.out.println("shell.open took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); processStartupDMS(); System.out.println("processStartupDMS took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); if (core != null) { VuzeActivitiesManager.initialize(core); } System.out.println("vuzeactivities init took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); NavigationHelper.addListener(new NavigationHelper.navigationListener() { public void processCommand(final int type, final String[] args) { Utils.execSWTThread(new AERunnable() { public void runSupport() { UIFunctions uif = UIFunctionsManager.getUIFunctions(); if (type == NavigationHelper.COMMAND_SWITCH_TO_TAB) { SideBar sideBar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sideBar == null) { return; } ContentNetworkUtils.setSourceRef(args[0], "menu", false); sideBar.showEntryByTabID(args[0]); if (uif != null) { uif.bringToFront(); } } else if (type == NavigationHelper.COMMAND_CONDITION_CHECK) { } } }); } }); } } /** * @param skinview * * @since 3.1.1.1 */ protected void setupSideBar(final SideBar sidebar) { // 3.2 TODO: set default sidebar item sidebar.addListener(this); Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { final String CFG_STARTTAB = "v3.StartTab"; String startTab; boolean showWelcome = COConfigurationManager.getBooleanParameter("v3.Show Welcome"); ContentNetwork startupCN = ContentNetworkManagerFactory.getSingleton().getStartupContentNetwork(); if (!startupCN.isServiceSupported(ContentNetwork.SERVICE_WELCOME)) { showWelcome = false; } if (showWelcome) { startTab = SideBar.SIDEBAR_SECTION_WELCOME; } else { if (!COConfigurationManager.hasParameter(CFG_STARTTAB, true)) { COConfigurationManager.setParameter(CFG_STARTTAB, SideBar.SIDEBAR_SECTION_LIBRARY); } startTab = COConfigurationManager.getStringParameter(CFG_STARTTAB); if (!SideBar.entryExists(startTab)) { startTab = SideBar.SIDEBAR_SECTION_LIBRARY; } } sidebar.showEntryByTabID(startTab); } }); sidebar.addListener(new SideBarListener() { public void sidebarItemSelected(SideBarEntrySWT newSideBarEntry, SideBarEntrySWT oldSideBarEntry) { COConfigurationManager.setParameter("v3.StartTab", newSideBarEntry.getId()); } }); // System.out.println("Activate sidebar " + startTab + " took " // + (SystemTime.getCurrentTime() - startTime) + "ms"); // startTime = SystemTime.getCurrentTime(); } /** * @param uiInitializer * @param taskKey TODO * * @since 3.0.4.3 */ private void increaseProgress(IUIIntializer uiInitializer, String taskKey) { if (uiInitializer != null) { uiInitializer.increaseProgress(); if (taskKey != null) { uiInitializer.reportCurrentTask(MessageText.getString(taskKey)); } } // XXX Disabled because plugin update window will pop up and take control // of the dispatch loop.. if (false && Utils.isThisThreadSWT()) { // clean the dispatch loop so the splash screen gets updated int i = 1000; while (display.readAndDispatch() && i > 0) { i--; } //if (i < 999) { // System.out.println("dispatched " + (1000 - i)); //} } } public boolean dispose(final boolean for_restart, final boolean close_already_in_progress) { if (disposedOrDisposing) { return true; } return Utils.execSWTThreadWithBool("v3.MainWindow.dispose", new AERunnableBoolean() { public boolean runSupport() { return _dispose(for_restart, close_already_in_progress); } }); } public boolean _dispose(boolean bForRestart, boolean bCloseAlreadyInProgress) { if (disposedOrDisposing) { return true; } isReady = false; disposedOrDisposing = true; if (core != null && !UIExitUtilsSWT.canClose(core.getGlobalManager(), bForRestart)) { disposedOrDisposing = false; return false; } UIExitUtilsSWT.uiShutdown(); if (systemTraySWT != null) { systemTraySWT.dispose(); } /** * Explicitly force the transfer bar location to be saved (if appropriate and open). * * We can't rely that the normal mechanism for doing this won't fail (which it usually does) * when the GUI is being disposed of. */ try { AllTransfersBar transfer_bar = AllTransfersBar.getBarIfOpen(core.getGlobalManager()); if (transfer_bar != null) { transfer_bar.forceSaveLocation(); } } catch (Exception ignore) { } mapTrackUsage_mon.enter(); try { if (mapTrackUsage != null) { String id = getUsageActiveTabID(); if (id != null) { if (lastShellStatus == null) { lastShellStatus = id; } updateMapTrackUsage(lastShellStatus); } Map map = new HashMap(); map.put("version", org.gudy.azureus2.core3.util.Constants.AZUREUS_VERSION); map.put("statsmap", mapTrackUsage); FileUtil.writeResilientFile(new File(SystemProperties.getUserPath(), "timingstats.dat"), map); } } finally { mapTrackUsage_mon.exit(); } if (!SWTThread.getInstance().isTerminated()) { SWTThread.getInstance().getInitializer().stopIt(bForRestart, false); } return true; } private String getUsageActiveTabID() { try { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { SideBarEntrySWT curEntry = sidebar.getCurrentEntry(); if (curEntry == null) { return "none"; } else { String id = curEntry.getLogID(); return id == null ? "null" : id; } } } catch (Exception e) { String name = e.getClass().getName(); int i = name.indexOf('.'); if (i > 0) { return name.substring(i); } return name; } return "unknown"; } /** * */ private void setupUsageTracker() { mapTrackUsage_mon.enter(); try { File f = new File(SystemProperties.getUserPath(), "timingstats.dat"); if (COConfigurationManager.getBooleanParameter("Send Version Info") && PlatformConfigMessenger.allowSendStats()) { mapTrackUsage = new HashMap(); if (f.exists()) { Map oldMapTrackUsage = FileUtil.readResilientFile(f); String version = MapUtils.getMapString(oldMapTrackUsage, "version", null); Map map = MapUtils.getMapMap(oldMapTrackUsage, "statsmap", null); if (version != null && map != null) { PlatformConfigMessenger.sendUsageStats(map, f.lastModified(), version, null); } } SimpleTimer.addPeriodicEvent("UsageTracker", 1000, new TimerEventPerformer() { long lLastMouseMove = SystemTime.getCurrentTime(); Point ptLastMousePos = new Point(0, 0); public void perform(TimerEvent event) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (shell == null || shell.isDisposed() || shell.getDisplay().getActiveShell() == null) { // so when we become active again, we count a few // seconds (if the mouse moves) if (ptLastMousePos.x > 0) { ptLastMousePos.x = 0; ptLastMousePos.y = 0; lLastMouseMove = 0; } return; } Point pt = shell.getDisplay().getCursorLocation(); if (pt.equals(ptLastMousePos)) { return; } ptLastMousePos = pt; long now = SystemTime.getCurrentTime(); if (lLastMouseMove > 0) { long diff = now - lLastMouseMove; if (diff < 10000) { lCurrentTrackTime += diff; } else { lCurrentTrackTimeIdle += diff; } } lLastMouseMove = now; } }); } }); Listener lActivateDeactivate = new Listener() { long start; public void handleEvent(Event event) { if (event.type == SWT.Activate) { lCurrentTrackTimeIdle = 0; if (start > 0 && lastShellStatus != null) { lCurrentTrackTime = SystemTime.getCurrentTime() - start; updateMapTrackUsage(lastShellStatus); } lastShellStatus = null; } else { updateMapTrackUsage(getUsageActiveTabID()); if (shell.getMinimized()) { lastShellStatus = "idle-minimized"; } else if (!shell.isVisible()) { lastShellStatus = "idle-invisible"; } else { lastShellStatus = "idle-nofocus"; } start = SystemTime.getCurrentTime(); } } }; shell.addListener(SWT.Activate, lActivateDeactivate); shell.addListener(SWT.Deactivate, lActivateDeactivate); } else { mapTrackUsage = null; // No use keeping old usage stats if we are told no one wants them try { if (f.exists()) { f.delete(); } } catch (Exception e) { } } } catch (Exception e) { Debug.out(e); } finally { mapTrackUsage_mon.exit(); } } private void showMainWindow() { boolean isOSX = org.gudy.azureus2.core3.util.Constants.isOSX; boolean bEnableTray = COConfigurationManager.getBooleanParameter("Enable System Tray"); boolean bPassworded = COConfigurationManager.getBooleanParameter("Password enabled"); boolean bStartMinimize = bEnableTray && (bPassworded || COConfigurationManager.getBooleanParameter("Start Minimized")); SWTSkinObject soMain = skin.getSkinObject("main"); if (soMain != null) { soMain.getControl().setVisible(true); } shell.addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { System.out.println("---------SHOWN AT " + SystemTime.getCurrentTime() + ";" + (SystemTime.getCurrentTime() - Initializer.startTime) + "ms"); } }); if (!bStartMinimize) { shell.open(); if (!isOSX) { shell.forceActive(); } } else if (Utils.isCarbon) { shell.setVisible(true); shell.setMinimized(true); } if (delayedCore) { // max 5 seconds of dispatching. We don't display.sleep here because // we only want to clear the backlog of SWT events, and sleep would // add new ones long endSWTDispatchOn = SystemTime.getOffsetTime(5000); while (SystemTime.getCurrentTime() < endSWTDispatchOn && !display.isDisposed() && display.readAndDispatch()); System.out.println("---------DONE DISPATCH AT " + SystemTime.getCurrentTime() + ";" + (SystemTime.getCurrentTime() - Initializer.startTime) + "ms"); if (display.isDisposed()) { return; } } if (bEnableTray) { try { systemTraySWT = new SystemTraySWT(); } catch (Throwable e) { e.printStackTrace(); Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "Upgrade to SWT3.0M8 or later for system tray support.")); } if (bStartMinimize) { minimizeToTray(null); } //Only show the password if not started minimized //Correct bug #878227 else { if (bPassworded) { minimizeToTray(null); setVisible(true); // invokes password } } } // do this before other checks as these are blocking dialogs to force order if (uiInitializer != null) { uiInitializer.initializationComplete(); } AssociationChecker.checkAssociations(); // Donation stuff Map map = VersionCheckClient.getSingleton().getMostRecentVersionCheckData(); DonationWindow.setInitialAskHours(MapUtils.getMapInt(map, "donations.askhrs", DonationWindow.getInitialAskHours())); if (core != null) { core.triggerLifeCycleComponentCreated(uiFunctions); } Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { fixupActionBarSize(); } }); System.out.println("---------READY AT " + SystemTime.getCurrentTime() + ";" + (SystemTime.getCurrentTime() - Initializer.startTime) + "ms"); isReady = true; //SESecurityManagerImpl.getSingleton().exitVM(0); } public void setVisible(final boolean visible) { setVisible(visible, true); } public void setVisible(final boolean visible, final boolean tryTricks) { Utils.execSWTThread(new AERunnable() { public void runSupport() { boolean currentlyVisible = shell.getVisible() && !shell.getMinimized(); if (visible && !currentlyVisible) { if (COConfigurationManager.getBooleanParameter("Password enabled")) { if (!PasswordWindow.showPasswordWindow(display)) { shell.setVisible(false); return; } } } ArrayList wasVisibleList = null; boolean bHideAndShow = false; // temp disabled //tryTricks && visible && Constants.isWindows && display.getActiveShell() != shell; if (bHideAndShow) { wasVisibleList = new ArrayList(); // We don't want the window to just flash and not open, so: // -Minimize main shell // -Set all shells invisible try { shell.setMinimized(true); Shell[] shells = shell.getDisplay().getShells(); for (int i = 0; i < shells.length; i++) { if (shells[i].isVisible()) { wasVisibleList.add(shells[i]); shells[i].setVisible(false); } } } catch (Exception e) { } } if (visible) { if (shell.getMinimized()) { shell.setMinimized(false); } if (!currentlyVisible && COConfigurationManager.getBooleanParameter("window.maximized")) { shell.setMaximized(true); } } else { // XXX hack for release.. should not access param outside Utils.linkShellMetrics COConfigurationManager.setParameter("window.maximized", shell.getMaximized()); } shell.setVisible(visible); if (visible) { shell.forceActive(); if (bHideAndShow) { try { Shell[] shells = shell.getDisplay().getShells(); for (int i = 0; i < shells.length; i++) { if (shells[i] != shell) { if (wasVisibleList.contains(shells[i])) { shells[i].setVisible(visible); } shells[i].setFocus(); } } } catch (Exception e) { } } } } }); } private void minimizeToTray(ShellEvent event) { //Added this test so that we can call this method with null parameter. if (event != null) { event.doit = false; } // XXX hack for release.. should not access param outside Utils.linkShellMetrics COConfigurationManager.setParameter("window.maximized", shell.getMaximized()); shell.setVisible(false); MiniBarManager.getManager().setAllVisible(true); } /** * Associates every view ID that we use to a class, and creates the class * on first EVENT_SHOW. */ private void initSkinListeners() { UISkinnableManagerSWT skinnableManagerSWT = UISkinnableManagerSWT.getInstance(); skinnableManagerSWT.addSkinnableListener(MessageBoxShell.class.toString(), new UISkinnableSWTListener() { public void skinBeforeComponents(Composite composite, Object skinnableObject, Object[] relatedObjects) { Color colorBG = skin.getSkinProperties().getColor("color.mainshell"); Color colorLink = skin.getSkinProperties().getColor( "color.links.normal"); Color colorText = skin.getSkinProperties().getColor("color.text.fg"); //composite.setBackground(colorBG); //composite.setForeground(colorText); MessageBoxShell shell = (MessageBoxShell) skinnableObject; //shell.setUrlColor(colorLink); TOTorrent torrent = null; DownloadManager dm = (DownloadManager) LogRelationUtils.queryForClass( relatedObjects, DownloadManager.class); if (dm != null) { torrent = dm.getTorrent(); } else { torrent = (TOTorrent) LogRelationUtils.queryForClass( relatedObjects, TOTorrent.class); } if (torrent != null && shell.getLeftImage() == null) { byte[] contentThumbnail = PlatformTorrentUtils.getContentThumbnail(torrent); if (contentThumbnail != null) { try { ByteArrayInputStream bis = new ByteArrayInputStream( contentThumbnail); final Image img = new Image(Display.getDefault(), bis); shell.setLeftImage(img); composite.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (!img.isDisposed()) { img.dispose(); } } }); } catch (Exception e) { } } } } public void skinAfterComponents(Composite composite, Object skinnableObject, Object[] relatedObjects) { } }); skinnableManagerSWT.addSkinnableListener( MessageSlideShell.class.toString(), new UISkinnableSWTListener() { public void skinBeforeComponents(Composite composite, Object skinnableObject, Object[] relatedObjects) { if (skinnableObject instanceof MessageSlideShell) { final Image image = new Image(composite.getDisplay(), 250, 300); TOTorrent torrent = null; DownloadManager dm = (DownloadManager) LogRelationUtils.queryForClass( relatedObjects, DownloadManager.class); if (dm != null) { torrent = dm.getTorrent(); } else { torrent = (TOTorrent) LogRelationUtils.queryForClass( relatedObjects, TOTorrent.class); } MessageSlideShell shell = (MessageSlideShell) skinnableObject; byte[] contentThumbnail = PlatformTorrentUtils.getContentThumbnail(torrent); GC gc = new GC(image); try { gc.setBackground(gc.getDevice().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND)); gc.fillRectangle(image.getBounds()); if (contentThumbnail != null) { try { ByteArrayInputStream bis = new ByteArrayInputStream( contentThumbnail); final Image img = new Image(Display.getDefault(), bis); Rectangle imgBounds = img.getBounds(); double pct = 35.0 / imgBounds.height; int w = (int) (imgBounds.width * pct); try { gc.setAdvanced(true); gc.setInterpolation(SWT.HIGH); } catch (Exception e) { // not important if we can't set advanced } gc.drawImage(img, 0, 0, imgBounds.width, imgBounds.height, 0, 265, w, 35); img.dispose(); } catch (Exception e) { } } } finally { gc.dispose(); } shell.setImgPopup(image); composite.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event event) { if (!image.isDisposed()) { image.dispose(); } } }); } } public void skinAfterComponents(Composite composite, Object skinnableObject, Object[] relatedObjects) { if (true) { return; // temp disable } Color bg = skin.getSkinProperties().getColor("color.mainshell"); if (bg != null) { composite.setBackground(bg); } Color fg = skin.getSkinProperties().getColor("color.section.header"); if (fg != null) { setChildrenFG(composite, fg); } composite.setBackgroundMode(SWT.INHERIT_DEFAULT); } }); } private void setChildrenFG(Control parent, Color color) { parent.setForeground(color); if (parent instanceof Composite) { Control[] children = ((Composite) parent).getChildren(); for (int i = 0; i < children.length; i++) { Control control = children[i]; if (!(control instanceof Button) || (((Button) control).getStyle() & SWT.CHECK) > 0) { setChildrenFG(control, color); } } } } /** * */ private void initWidgets() { SWTSkinObject skinObject; /* * Directly loading the buddies viewer since we need to access it * before it's even shown for the first time */ Class[] forceInits = new Class[] { SideBar.class, }; String[] forceInitsIDs = new String[] { SkinConstants.VIEWID_SIDEBAR, }; for (int i = 0; i < forceInits.length; i++) { Class cla = forceInits[i]; String id = forceInitsIDs[i]; try { skinObject = skin.getSkinObject(id); if (null != skinObject) { SkinView skinView = (SkinView) cla.newInstance(); skinView.setMainSkinObject(skinObject); skinObject.addListener(skinView); } } catch (Throwable t) { Debug.out(t); } } } private void initWidgets2() { SWTSkinObject skinObject = skin.getSkinObject("statusbar"); if (skinObject != null) { final Composite cArea = (Composite) skinObject.getControl(); statusBar = new MainStatusBar(); Composite composite = statusBar.initStatusBar(cArea); composite.setLayoutData(Utils.getFilledFormData()); } skinObject = skin.getSkinObject("search-text"); if (skinObject != null) { attachSearchBox(skinObject); } skinObject = skin.getSkinObject(SkinConstants.VIEWID_PLUGINBAR); if (skinObject != null) { Menu topbarMenu = new Menu(shell, SWT.POP_UP); if (COConfigurationManager.getIntParameter("User Mode") > 1) { MainMenu.createViewMenuItem(skin, topbarMenu, "v3.MainWindow.menu.view." + SkinConstants.VIEWID_PLUGINBAR, SkinConstants.VIEWID_PLUGINBAR + ".visible", SkinConstants.VIEWID_PLUGINBAR, true, -1); } final MenuItem itemShowText = new MenuItem(topbarMenu, SWT.CHECK); Messages.setLanguageText(itemShowText, "v3.MainWindow.menu.showActionBarText"); itemShowText.addSelectionListener(new SelectionAdapter() { // @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) public void widgetSelected(SelectionEvent e) { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { tb.flipShowText(); } } }); topbarMenu.addMenuListener(new MenuListener() { public void menuShown(MenuEvent e) { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { itemShowText.setSelection(tb.getShowText()); } } public void menuHidden(MenuEvent e) { } }); addMenuAndNonTextChildren((Composite) skinObject.getControl(), topbarMenu); skinObject = skin.getSkinObject("tabbar"); if (skinObject != null) { addMenuAndNonTextChildren((Composite) skinObject.getControl(), topbarMenu); } } } private void addMenuAndNonTextChildren(Composite parent, Menu menu) { parent.setMenu(menu); Control[] children = parent.getChildren(); for (int i = 0; i < children.length; i++) { Control control = children[i]; if (control instanceof Composite) { Composite c = (Composite) control; addMenuAndNonTextChildren(c, menu); } else if (!(control instanceof Text)) { control.setMenu(menu); } } } /** * @param skinObject */ private void attachSearchBox(SWTSkinObject skinObject) { Composite cArea = (Composite) skinObject.getControl(); shell.addListener(SWT.Resize, new Listener() { public void handleEvent(Event event) { fixupActionBarSize(); } }); final Text text = new Text(cArea, SWT.NONE); FormData filledFormData = Utils.getFilledFormData(); text.setLayoutData(filledFormData); text.addListener(SWT.Resize, new Listener() { Font lastFont = null; public void handleEvent(Event event) { Text text = (Text) event.widget; int h = text.getClientArea().height - 2; Font font = Utils.getFontWithHeight(text.getFont(), null, h); if (font != null) { text.setFont(font); Utils.disposeSWTObjects(new Object[] { lastFont }); text.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { Text text = (Text) e.widget; text.setFont(null); Utils.disposeSWTObjects(new Object[] { lastFont }); } }); } } }); text.setTextLimit(254); final String sDefault = MessageText.getString("v3.MainWindow.search.defaultText"); SWTSkinProperties properties = skinObject.getProperties(); colorSearchTextBG = properties.getColor("color.search.text.bg"); colorSearchTextFG = properties.getColor("color.search.text.fg"); colorSearchTextFGdef = properties.getColor("color.search.text.fg.default"); if (colorSearchTextFGdef != null) { text.setForeground(colorSearchTextFGdef); } if (colorSearchTextBG != null) { text.setBackground(colorSearchTextBG); } text.addMouseListener(new MouseListener() { public void mouseUp(MouseEvent e) { Text text = (Text) e.widget; if (text.getText().equals(sDefault)) { if (colorSearchTextFG != null) { text.setForeground(colorSearchTextFG); } text.setText(""); } } public void mouseDown(MouseEvent e) { } public void mouseDoubleClick(MouseEvent e) { } }); text.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { if (e.stateMask == SWT.MOD1) { int key = e.character; if (key <= 26 && key > 0) { key += 'a' - 1; } if (key == 'a') { text.selectAll(); } } } public void keyReleased(KeyEvent arg0) { // TODO Auto-generated method stub } }); text.addListener(SWT.KeyDown, new Listener() { public void handleEvent(Event event) { if (text.getText().equals(sDefault)) { if (colorSearchTextFG != null) { text.setForeground(colorSearchTextFG); } if (event.character != '\0') { text.setText(""); } return; } Text text = (Text) event.widget; if (event.keyCode == SWT.ESC) { text.setText(""); return; } if (event.character == SWT.CR) { doSearch(text.getText()); } } }); // must be done after layout text.setText(sDefault); //text.selectAll(); SWTSkinObject searchGo = skin.getSkinObject("search-go"); if (searchGo != null) { SWTSkinButtonUtility btnGo = new SWTSkinButtonUtility(searchGo); btnGo.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { String sSearchText = text.getText().trim(); doSearch(sSearchText); } }); } SWTSkinObject so = skin.getSkinObject("sidebar-list"); if (so != null && so.getProperties().getBooleanValue( so.getConfigID() + ".resizeSearch", false)) { Listener l = new Listener() { public void handleEvent(Event event) { SWTSkinObject soSearchArea = skin.getSkinObject("topbar-area-search"); if (soSearchArea != null) { Control c = soSearchArea.getControl(); Rectangle bounds = ((Control) event.widget).getBounds(); FormData fd = (FormData) c.getLayoutData(); int newWidth = bounds.width - 1 - c.getBounds().x; if (bounds.width < 125) { return; } fd.width = newWidth; Utils.relayout(c); } } }; so.getControl().addListener(SWT.Resize, l); } so = skin.getSkinObject("search-dropdown"); if (so != null) { SWTSkinButtonUtility btnSearchDD = new SWTSkinButtonUtility(so); btnSearchDD.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { String sSearchText = text.getText().trim(); doSearch(sSearchText); } }); } } /** * * * @since 4.0.0.1 */ protected void fixupActionBarSize() { Rectangle clientArea = shell.getClientArea(); SWTSkinObject soSearch = skin.getSkinObject("topbar-area-search"); if (soSearch == null) { return; } FormData fd = (FormData) soSearch.getControl().getLayoutData(); if (fd == null || fd.width <= 0) { return; } if (clientArea.width > 1024 && fd.width == 195) { return; } SWTSkinObject soTabBar = skin.getSkinObject(SkinConstants.VIEWID_TAB_BAR); if (soTabBar == null) { return; } Point size = soTabBar.getControl().computeSize(SWT.DEFAULT, SWT.DEFAULT); int oldWidth = fd.width; fd.width = clientArea.width - (size.x - oldWidth) - 5; if (fd.width < 100) { fd.width = 100; } else if (fd.width > 195) { fd.width = 195; } if (oldWidth != fd.width) { ((Composite) soTabBar.getControl()).layout(true, true); } } /** * @param searchText */ //TODO : Tux Move to utils? Could you also add a "mode" or something that would be added to the url // eg: &subscribe_mode=true public static void doSearch(final String sSearchText) { Utils.execSWTThread(new AERunnable() { public void runSupport() { doSearch(sSearchText, false); } }); } public static void doSearch(String sSearchText, boolean toSubscribe) { String sDefault = MessageText.getString("v3.MainWindow.search.defaultText"); if (sSearchText.equals(sDefault) || sSearchText.length() == 0) { return; } SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); String id = "Search"; SearchResultsTabArea searchClass = (SearchResultsTabArea) SkinViewManager.getByClass(SearchResultsTabArea.class); if (searchClass != null) { searchClass.anotherSearch(sSearchText, toSubscribe); } else { SearchResultsTabArea.SearchQuery sq = new SearchResultsTabArea.SearchQuery(); sq.term = sSearchText; sq.toSubscribe = toSubscribe; SideBarEntrySWT entry = sidebar.createEntryFromSkinRef(null, id, "main.area.searchresultstab", sSearchText, null, sq, true, -1); if (entry != null) { entry.setImageLeftID("image.sidebar.search"); } } sidebar.showEntryByID(id); } /** * */ private void updateMapTrackUsage(String sTabID) { //System.out.println("UPDATE: " + sTabID); if (mapTrackUsage != null) { mapTrackUsage_mon.enter(); try { if (lCurrentTrackTime > 0) { Long currentLength = (Long) mapTrackUsage.get(sTabID); long newLength; if (currentLength == null) { newLength = lCurrentTrackTime; } else { newLength = currentLength.longValue() + lCurrentTrackTime; } if (newLength > 1000) { mapTrackUsage.put(sTabID, new Long(newLength / 1000)); //System.out.println("UPDATE: " + sTabID + ";" + newLength); } } if (lCurrentTrackTimeIdle > 0) { String id = "idle-" + sTabID; Long currentLengthIdle = (Long) mapTrackUsage.get(id); long newLengthIdle = currentLengthIdle == null ? lCurrentTrackTimeIdle : currentLengthIdle.longValue() + lCurrentTrackTimeIdle; if (newLengthIdle > 1000) { mapTrackUsage.put(id, new Long(newLengthIdle / 1000)); //System.out.println("UPDATE: " + id + ";" + newLengthIdle); } } } finally { mapTrackUsage_mon.exit(); } } lCurrentTrackTime = 0; lCurrentTrackTimeIdle = 0; } public static void addUsageStat(String id, long value) { if (id == null) { return; } if (id.length() > 150) { id = id.substring(0, 150); } if (mapTrackUsage != null) { mapTrackUsage_mon.enter(); try { Long currentLength = (Long) mapTrackUsage.get(id); long newLength; if (currentLength == null) { newLength = value; } else { newLength = currentLength.longValue() + value; } if (newLength > 1000) { mapTrackUsage.put(id, new Long(newLength / 1000)); } } finally { mapTrackUsage_mon.exit(); } } } public UISWTInstance getUISWTInstanceImpl() { return uiSWTInstanceImpl; } /** * @param url * @param target */ public void showURL(final String url, String target) { if ("_blank".equalsIgnoreCase(target)) { Utils.launch(url); return; } if (target.startsWith("tab-")) { target = target.substring(4); } SideBar sideBar = (SideBar) SkinViewManager.getByClass(SideBar.class); // Note; We don't setSourceRef on ContentNetwork here like we do // everywhere else because the source ref should already be set // by the caller String id = sideBar.showEntryByTabID(target); if (id == null) { Utils.launch(url); return; } SideBarEntrySWT entry = SideBar.getEntry(id); entry.addListener(new SideBarOpenListener() { public void sideBarEntryOpen(SideBarEntry entry) { entry.removeListener(this); setVisible(true); if (!(entry instanceof SideBarEntrySWT)) { return; } SideBarEntrySWT entrySWT = (SideBarEntrySWT) entry; SWTSkinObjectBrowser soBrowser = SWTSkinUtils.findBrowserSO(entrySWT.getSkinObject()); if (soBrowser != null) { //((SWTSkinObjectBrowser) skinObject).getBrowser().setVisible(false); if (url == null || url.length() == 0) { soBrowser.restart(); } else { String fullURL = url; if (UrlFilter.getInstance().urlCanRPC(url)) { // 4010 Tux: This shouldn't be.. either determine ContentNetwork from // url or target, or do something.. fullURL = ConstantsVuze.getDefaultContentNetwork().appendURLSuffix( url, false, true); } soBrowser.setURL(fullURL); } } } }); } protected MainStatusBar getMainStatusBar() { return statusBar; } public boolean isVisible(int windowElement) { if (windowElement == IMainWindow.WINDOW_ELEMENT_TOOLBAR) { } else if (windowElement == IMainWindow.WINDOW_ELEMENT_TOPBAR) { SWTSkinObject skinObject = skin.getSkinObject(SkinConstants.VIEWID_PLUGINBAR); if (skinObject != null) { return skinObject.isVisible(); } } else if (windowElement == IMainWindow.WINDOW_ELEMENT_TABBAR) { SWTSkinObject skinObject = skin.getSkinObject("tabbar"); if (skinObject != null) { return skinObject.isVisible(); } } else if (windowElement == IMainWindow.WINDOW_ELEMENT_STATUSBAR) { //TODO: } else if (windowElement == IMainWindow.WINDOW_ELEMENT_MENU) { //TODO: } return false; } public void setVisible(int windowElement, boolean value) { if (windowElement == IMainWindow.WINDOW_ELEMENT_TOOLBAR) { } else if (windowElement == IMainWindow.WINDOW_ELEMENT_TOPBAR) { SWTSkinUtils.setVisibility(skin, SkinConstants.VIEWID_PLUGINBAR + ".visible", SkinConstants.VIEWID_PLUGINBAR, value, true, true); } else if (windowElement == IMainWindow.WINDOW_ELEMENT_STATUSBAR) { //TODO: } else if (windowElement == IMainWindow.WINDOW_ELEMENT_MENU) { //TODO: } else if (windowElement == IMainWindow.WINDOW_ELEMENT_TABBAR) { SWTSkinUtils.setVisibility(skin, "TabBar.visible", SkinConstants.VIEWID_TAB_BAR, value, true, true); } } public Rectangle getMetrics(int windowElement) { if (windowElement == IMainWindow.WINDOW_ELEMENT_TOOLBAR) { } else if (windowElement == IMainWindow.WINDOW_ELEMENT_TOPBAR) { SWTSkinObject skinObject = skin.getSkinObject(SkinConstants.VIEWID_PLUGINBAR); if (skinObject != null) { return skinObject.getControl().getBounds(); } } else if (windowElement == IMainWindow.WINDOW_ELEMENT_TABBAR) { SWTSkinObject skinObject = skin.getSkinObject("tabbar"); if (skinObject != null) { return skinObject.getControl().getBounds(); } } else if (windowElement == IMainWindow.WINDOW_ELEMENT_STATUSBAR) { return statusBar.getBounds(); } else if (windowElement == IMainWindow.WINDOW_CLIENT_AREA) { return shell.getClientArea(); } else if (windowElement == IMainWindow.WINDOW_CONTENT_DISPLAY_AREA) { Rectangle r = getMetrics(IMainWindow.WINDOW_CLIENT_AREA); r.height -= getMetrics(IMainWindow.WINDOW_ELEMENT_TOPBAR).height; r.height -= getMetrics(IMainWindow.WINDOW_ELEMENT_TABBAR).height; r.height -= getMetrics(IMainWindow.WINDOW_ELEMENT_STATUSBAR).height; return r; } return new Rectangle(0, 0, 0, 0); } public SWTSkin getSkin() { return skin; } public boolean isReady() { return isReady; } public Image generateObfusticatedImage() { // 3.2 TODO: Obfusticate! (esp advanced view) Image image; Rectangle clientArea = shell.getClientArea(); image = new Image(display, clientArea.width, clientArea.height); GC gc = new GC(shell); try { gc.copyArea(image, clientArea.x, clientArea.y); Control[] children = shell.getChildren(); for (int i = 0; i < children.length; i++) { Control control = children[i]; SWTSkinObject so = (SWTSkinObject) control.getData("SkinObject"); if (so != null) { Image obfusticatedImage = so.generateObfusticatedImage(); if (obfusticatedImage != null) { Rectangle bounds = so.getControl().getBounds(); gc.drawImage(obfusticatedImage, bounds.x, bounds.y); } } } } finally { gc.dispose(); } return image; } /** * @param cla * @param data * * @since 3.1.1.1 */ public void openView(final String parentID, final Class cla, String id, final Object data, final boolean closeable) { final SideBar sideBar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sideBar == null) { return; } if (id == null) { id = cla.getName(); int i = id.lastIndexOf('.'); if (i > 0) { id = id.substring(i + 1); } } IView viewFromID = sideBar.getIViewFromID(id); if (viewFromID != null) { sideBar.showEntryByID(id); } final String _id = id; Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { if (sideBar.showEntryByID(_id)) { return; } if (UISWTViewEventListener.class.isAssignableFrom(cla)) { UISWTViewEventListener l = null; try { Constructor constructor = cla.getConstructor(new Class[] { data.getClass() }); l = (UISWTViewEventListener) constructor.newInstance(new Object[] { data }); } catch (Exception e) { } try { if (l == null) { l = (UISWTViewEventListener) cla.newInstance(); } sideBar.createTreeItemFromEventListener(parentID, null, l, _id, closeable, data); } catch (Exception e) { Debug.out(e); } } else { sideBar.createTreeItemFromIViewClass(parentID, _id, null, cla, null, null, data, null, true); } sideBar.showEntryByID(_id); } }); } // @see com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarListener#sidebarItemSelected(com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarInfoSWT, com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarInfoSWT) public void sidebarItemSelected(SideBarEntrySWT newSideBarEntry, SideBarEntrySWT oldSideBarEntry) { if (newSideBarEntry == null) { return; } if (mapTrackUsage != null && oldSideBarEntry != null) { oldSideBarEntry.removeListener((SideBarLogIdListener) this); String id2 = null; SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { id2 = oldSideBarEntry.getLogID(); } if (id2 == null) { id2 = oldSideBarEntry.id; } updateMapTrackUsage(id2); } if (mapTrackUsage != null) { newSideBarEntry.addListener((SideBarLogIdListener) this); } } // @see com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarLogIdListener#sidebarLogIdChanged(com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT, java.lang.String, java.lang.String) public void sidebarLogIdChanged(SideBarEntrySWT sideBarEntrySWT, String oldID, String newID) { if (oldID == null) { oldID = "null"; } updateMapTrackUsage(oldID); } // @see org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator#generate(org.gudy.azureus2.core3.util.IndentWriter) public void generate(IndentWriter writer) { writer.println("SWT UI"); try { writer.indent(); TableColumnManager.getInstance().generateDiagnostics(writer); } finally { writer.exdent(); } } protected void setSelectedLanguageItem() { Messages.updateLanguageForControl(shell); if (systemTraySWT != null) { systemTraySWT.updateLanguage(); } if (statusBar != null) { statusBar.refreshStatusText(); } // download basket skin.triggerLanguageChange(); if (statusBar != null) { statusBar.updateStatusText(); } if (menu != null) { MenuFactory.updateMenuText(menu.getMenu(IMenuConstants.MENU_ID_MENU_BAR)); } } protected MainMenu getMainMenu() { return menu; } }azureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/main/DebugMenuHelper.java0000644000175000017500000001352411267524522026105 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.shells.main; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.donations.DonationWindow; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.util.ConstantsVuze; /** * A convenience class for creating the Debug menu *

    * This has been extracted out into its own class since it does not really belong to production code * @author knguyen * */ public class DebugMenuHelper { /** * Creates the Debug menu and its children * NOTE: This is a development only menu and so it's not modularized into separate menu items * because this menu is always rendered in its entirety * @param menu * @param mainWindow * @return */ public static MenuItem createDebugMenuItem(final Menu menuDebug) { MenuItem item; final UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (null == uiFunctions) { throw new IllegalStateException( "UIFunctionsManagerSWT.getUIFunctionsSWT() is returning null"); } item = new MenuItem(menuDebug, SWT.CASCADE); item.setText("Run GC"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { System.gc(); } }); item = new MenuItem(menuDebug, SWT.PUSH); item.setText("&CoreReq"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { new MessageBoxShell(0, "Done", "Core Now Avail").open(null); } }); } }); /* item = new MenuItem(menuDebug, SWT.CASCADE); item.setText("Subscriptions"); Menu menuSubscriptions = new Menu(menuDebug.getParent(), SWT.DROP_DOWN); item.setMenu(menuSubscriptions); item = new MenuItem(menuSubscriptions, SWT.NONE); item.setText("Create RSS Feed"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { final Shell shell = new Shell(uiFunctions.getMainShell()); shell.setLayout(new FormLayout()); Label label = new Label(shell,SWT.NONE); label.setText("RSS Feed URL :"); final Text urlText = new Text(shell,SWT.BORDER); urlText.setText(Utils.getLinkFromClipboard(shell.getDisplay(),false)); Label separator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL); Button cancel = new Button(shell,SWT.PUSH); cancel.setText("Cancel"); Button ok = new Button(shell,SWT.PUSH); ok.setText("Ok"); FormData data; data = new FormData(); data.left = new FormAttachment(0,5); data.right = new FormAttachment(100,-5); data.top = new FormAttachment(0,5); label.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0,5); data.right = new FormAttachment(100,-5); data.top = new FormAttachment(label); data.width = 400; urlText.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0,5); data.right = new FormAttachment(100,-5); data.top = new FormAttachment(urlText); separator.setLayoutData(data); data = new FormData(); data.right = new FormAttachment(ok); data.width = 100; data.top = new FormAttachment(separator); cancel.setLayoutData(data); data = new FormData(); data.right = new FormAttachment(100,-5); data.width = 100; data.top = new FormAttachment(separator); ok.setLayoutData(data); cancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { shell.dispose(); } }); ok.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { String url_str = urlText.getText(); shell.dispose(); try{ URL url = new URL( url_str ); SubscriptionManagerFactory.getSingleton().createSingletonRSS( url_str, url, 120, true ); }catch( Throwable e ){ Debug.printStackTrace(e); } } }); shell.pack(); Utils.centerWindowRelativeTo(shell, uiFunctions.getMainShell()); shell.open(); shell.setFocus(); urlText.setFocus(); } }); */ item = new MenuItem(menuDebug, SWT.CASCADE); item.setText("DW"); Menu menuBrowserTB = new Menu(menuDebug.getParent(), SWT.DROP_DOWN); item.setMenu(menuBrowserTB); item = new MenuItem(menuBrowserTB, SWT.NONE); item.setText("popup check"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { boolean oldDebug = DonationWindow.DEBUG; DonationWindow.DEBUG = true; DonationWindow.checkForDonationPopup(); DonationWindow.DEBUG = oldDebug; } }); item = new MenuItem(menuBrowserTB, SWT.NONE); item.setText("show"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { boolean oldDebug = DonationWindow.DEBUG; DonationWindow.DEBUG = true; DonationWindow.open(true, "debug"); DonationWindow.DEBUG = oldDebug; } }); item = new MenuItem(menuDebug, SWT.NONE); item.setText("FB"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { UIFunctionsManager.getUIFunctions().viewURL(ConstantsVuze.getDefaultContentNetwork().getSiteRelativeURL("facebookshare.start", true), null, null); } }); return item; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/main/UIFunctionsImpl.java0000644000175000017500000006400511306351434026114 0ustar adrianadrian/* * Created on Jul 13, 2006 6:15:55 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.shells.main; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginView; import org.gudy.azureus2.plugins.ui.sidebar.SideBarEntry; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.*; import org.gudy.azureus2.ui.swt.mainwindow.MainWindow; import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar; import org.gudy.azureus2.ui.swt.minibar.MiniBarManager; import org.gudy.azureus2.ui.swt.plugins.*; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.update.FullUpdateWindow; import org.gudy.azureus2.ui.swt.views.*; import org.gudy.azureus2.ui.swt.views.clientstats.ClientStatsView; import org.gudy.azureus2.ui.swt.views.stats.StatsView; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.ui.*; import com.aelitis.azureus.ui.common.updater.UIUpdater; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.swt.Initializer; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.shells.BrowserWindow; import com.aelitis.azureus.ui.swt.skin.*; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter; import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT; import com.aelitis.azureus.ui.swt.utils.ColorCache; import com.aelitis.azureus.ui.swt.views.skin.*; import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog.SkinnedDialogClosedListener; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.util.ContentNetworkUtils; import com.aelitis.azureus.util.UrlFilter; /** * @author TuxPaper * @created Jul 13, 2006 * */ public class UIFunctionsImpl implements UIFunctionsSWT { private final static LogIDs LOGID = LogIDs.GUI; private final com.aelitis.azureus.ui.swt.shells.main.MainWindow mainWindow; /** * This isn't presently populated. * mapPluginViews stores the plugin views that need to be added once the * oldMainWindow is created. Currently, we create the oldMainWindow * at startup. Once we swtich to delayed oldMainWindow creation, in theory * the code will work. */ private final Map mapPluginViews = new HashMap(); private final AEMonitor pluginViews_mon = new AEMonitor("v3.uif.pluginViews"); /** * Stores the current SWTSkin so it can be used by {@link #createMenu(Shell)} */ private SWTSkin skin = null; protected boolean isTorrentMenuVisible; /** * @param window */ public UIFunctionsImpl( com.aelitis.azureus.ui.swt.shells.main.MainWindow window) { this.mainWindow = window; COConfigurationManager.addAndFireParameterListener( "Menu.show.torrent.menu", new ParameterListener() { public void parameterChanged(String parameterName) { isTorrentMenuVisible = COConfigurationManager.getBooleanParameter("Menu.show.torrent.menu"); } }); } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#addPluginView(org.gudy.azureus2.plugins.PluginView) public void addPluginView(PluginView view) { try { pluginViews_mon.enter(); try { mapPluginViews.put(view, null); } finally { pluginViews_mon.exit(); } } catch (Exception e) { Logger.log(new LogEvent(LOGID, "addPluginView", e)); } } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#addPluginView(java.lang.String, org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener) public void addPluginView(final String viewID, final UISWTViewEventListener l) { try { Utils.execSWTThread(new AERunnable() { public void runSupport() { PluginsMenuHelper.getInstance().addPluginView(viewID, l); } }); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "addPluginView", e)); } } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#addPluginView(org.gudy.azureus2.ui.swt.plugins.UISWTPluginView) public void addPluginView(UISWTPluginView view) { try { pluginViews_mon.enter(); try { mapPluginViews.put(view, null); } finally { pluginViews_mon.exit(); } } catch (Exception e) { Logger.log(new LogEvent(LOGID, "addPluginView", e)); } } // @see com.aelitis.azureus.ui.UIFunctions#bringToFront() public void bringToFront() { bringToFront(true); } // @see com.aelitis.azureus.ui.UIFunctions#bringToFront(boolean) public void bringToFront(final boolean tryTricks) { Utils.execSWTThread(new AERunnable() { public void runSupport() { try { // this will force active and set !minimized after PW test mainWindow.setVisible(true, tryTricks); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "bringToFront", e)); } } }); } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#closeDownloadBars() public void closeDownloadBars() { try { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { MiniBarManager.getManager().closeAll(); } }); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "closeDownloadBars", e)); } } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#closePluginView(org.gudy.azureus2.ui.swt.views.IView) public void closePluginView(IView view) { try { SkinView sideBarView = SkinViewManager.getByClass(SideBar.class); if (sideBarView instanceof SideBar) { SideBar sideBar = (SideBar) sideBarView; String id; if (view instanceof UISWTViewImpl) { id = ((UISWTViewImpl)view).getViewID(); } else { id = view.getClass().getName(); int i = id.lastIndexOf('.'); if (i > 0) { id = id.substring(i + 1); } } sideBar.closeEntry(id); } } catch (Exception e) { Logger.log(new LogEvent(LOGID, "closePluginView", e)); } } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#closePluginViews(java.lang.String) public void closePluginViews(String sViewID) { try { SkinView sideBarView = SkinViewManager.getByClass(SideBar.class); if (sideBarView instanceof SideBar) { SideBar sideBar = (SideBar) sideBarView; sideBar.closeEntry(sViewID); } } catch (Exception e) { Logger.log(new LogEvent(LOGID, "closePluginViews", e)); } } // @see com.aelitis.azureus.ui.UIFunctions#dispose(boolean, boolean) public boolean dispose(boolean for_restart, boolean close_already_in_progress) { try { return mainWindow.dispose(for_restart, close_already_in_progress); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "Disposing MainWindow", e)); } return false; } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#getMainShell() public Shell getMainShell() { return mainWindow.shell; } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#getMenu(int) public Menu getMenu(int id) { // TODO Auto-generated method stub // XXX Don't use oldMainWindow, menu is global and oldMainWindow // shouldn't need to be initialized return null; } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#getPluginViews() public UISWTView[] getPluginViews() { try { return new UISWTView[0]; } catch (Exception e) { Logger.log(new LogEvent(LOGID, "getPluginViews", e)); } return new UISWTView[0]; } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#getSWTPluginInstanceImpl() public UISWTInstanceImpl getSWTPluginInstanceImpl() { try { return (UISWTInstanceImpl) mainWindow.getUISWTInstanceImpl(); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "getSWTPluginInstanceImpl", e)); } return null; } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#openPluginView(org.gudy.azureus2.ui.swt.views.AbstractIView, java.lang.String) public void openPluginView(AbstractIView view, String name) { try { SkinView sideBarView = SkinViewManager.getByClass(SideBar.class); if (sideBarView instanceof SideBar) { SideBar sideBar = (SideBar) sideBarView; if (sideBar.createTreeItemFromIView(null, view, name, null, true, true, true) != null) { return; } } } catch (Exception e) { Logger.log(new LogEvent(LOGID, "openPluginView", e)); } } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#openPluginView(org.gudy.azureus2.plugins.PluginView) public void openPluginView(PluginView view) { openPluginView(view, view.getPluginViewName()); } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#openPluginView(java.lang.String, java.lang.String, org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener, java.lang.Object, boolean) public void openPluginView(String sParentID, String sViewID, UISWTViewEventListener l, Object dataSource, boolean bSetFocus) { try { SideBar sideBar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sideBar != null) { String sidebarParentID = null; if (UISWTInstance.VIEW_MYTORRENTS.equals(sParentID)) { sidebarParentID = SideBar.SIDEBAR_SECTION_LIBRARY; } else if (!UISWTInstance.VIEW_MAIN.equals(sParentID)) { System.err.println("Can't find parent " + sParentID + " for " + sViewID); } sideBar.createTreeItemFromEventListener(sidebarParentID, null, l, sViewID, true, dataSource); if (bSetFocus) { sideBar.showEntryByID(sViewID); } } } catch (Exception e) { Logger.log(new LogEvent(LOGID, "openPluginView", e)); } } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#openPluginView(org.gudy.azureus2.ui.swt.plugins.UISWTPluginView) public void openPluginView(UISWTPluginView view) { openPluginView(view, view.getPluginViewName()); } // @see com.aelitis.azureus.ui.UIFunctions#refreshIconBar() public void refreshIconBar() { try { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { tb.refreshCoreToolBarItems(); } } catch (Exception e) { Logger.log(new LogEvent(LOGID, "refreshIconBar", e)); } } // @see com.aelitis.azureus.ui.UIFunctions#refreshLanguage() public void refreshLanguage() { try { mainWindow.setSelectedLanguageItem(); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "refreshLanguage", e)); } } // @see com.aelitis.azureus.ui.UIFunctions#removeManagerView(org.gudy.azureus2.core3.download.DownloadManager) public void removeManagerView(DownloadManager dm) { try { // TODO: ????! } catch (Exception e) { Logger.log(new LogEvent(LOGID, "removeManagerView", e)); } } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#removePluginView(java.lang.String) public void removePluginView(String viewID) { try { pluginViews_mon.enter(); try { mapPluginViews.remove(viewID); } finally { pluginViews_mon.exit(); } PluginsMenuHelper.getInstance().removePluginViews(viewID); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "removePluginView", e)); } } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#removePluginView(org.gudy.azureus2.ui.swt.plugins.UISWTPluginView) public void removePluginView(UISWTPluginView view) { try { pluginViews_mon.enter(); try { mapPluginViews.remove(view); } finally { pluginViews_mon.exit(); } PluginsMenuHelper.getInstance().removePluginView(view, view.getPluginViewName()); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "removePluginView", e)); } } // @see com.aelitis.azureus.ui.UIFunctions#setStatusText(java.lang.String) public void setStatusText(String string) { // TODO Auto-generated method stub // XXX Don't use oldMainWindow, status bar is global and oldMainWindow // shouldn't need to be initialized } // @see com.aelitis.azureus.ui.UIFunctions#setStatusText(int, java.lang.String, com.aelitis.azureus.ui.UIStatusTextClickListener) public void setStatusText(int statustype, String string, UIStatusTextClickListener l) { // TODO Auto-generated method stub } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#getMainStatusBar() public MainStatusBar getMainStatusBar() { return mainWindow.getMainStatusBar(); } // @see com.aelitis.azureus.ui.UIFunctions#showConfig(java.lang.String) public boolean showConfig(String section) { try { /* * Show in pop-up in Vuze UI's */ ConfigShell.getInstance().open(section); return true; } catch (Exception e) { Logger.log(new LogEvent(LOGID, "showConfig", e)); } return false; } public void openView(final int viewID, final Object data) { Utils.execSWTThread(new AERunnable() { public void runSupport() { _openView(viewID, data); } }); } private void _openView(int viewID, Object data) { switch (viewID) { case VIEW_CONSOLE: mainWindow.openView(SideBar.SIDEBAR_SECTION_TOOLS, LoggerView.class, null, data, true); break; case VIEW_ALLPEERS: mainWindow.openView(SideBar.SIDEBAR_SECTION_TOOLS, PeerSuperView.class, null, data, true); break; case VIEW_PEERS_STATS: mainWindow.openView(SideBar.SIDEBAR_SECTION_TOOLS, ClientStatsView.class, null, data, true); break; case VIEW_CONFIG: showConfig((data instanceof String) ? (String) data : null); break; case VIEW_DM_DETAILS: String id = "DMDetails_"; if (data instanceof DownloadManager) { DownloadManager dm = (DownloadManager) data; TOTorrent torrent = dm.getTorrent(); if (torrent != null) { try { id += torrent.getHashWrapper().toBase32String(); } catch (TOTorrentException e) { e.printStackTrace(); } } } mainWindow.openView(SideBar.SIDEBAR_SECTION_LIBRARY, ManagerView.class, id, data, true); break; case VIEW_DM_MULTI_OPTIONS: mainWindow.openView(SideBar.SIDEBAR_SECTION_LIBRARY, TorrentOptionsView.class, null, data, true); break; case VIEW_MYSHARES: mainWindow.openView(SideBar.SIDEBAR_SECTION_LIBRARY, MySharesView.class, null, data, true); break; case VIEW_MYTORRENTS: { SideBar sideBar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sideBar != null) { sideBar.showEntryByID(SideBar.SIDEBAR_SECTION_LIBRARY); } } break; case VIEW_MYTRACKER: mainWindow.openView(SideBar.SIDEBAR_SECTION_TOOLS, MyTrackerView.class, null, data, true); break; case VIEW_STATS: mainWindow.openView(SideBar.SIDEBAR_SECTION_TOOLS, StatsView.class, null, data, true); break; case VIEW_DETAILED_LISTVIEW: mainWindow.openView(SideBar.SIDEBAR_SECTION_TOOLS, DetailedListView.class, null, data, true); break; default: break; } } public UISWTInstance getUISWTInstance() { return mainWindow.getUISWTInstanceImpl(); } // @see com.aelitis.azureus.ui.UIFunctions#viewURL(java.lang.String, java.lang.String, java.lang.String) public void viewURL(String url, String target, String sourceRef) { ContentNetworkUtils.setSourceRef(target, sourceRef, false); viewURL(url, target, 0, 0, true, false); } public boolean viewURL(final String url, final String target, final int w, final int h, final boolean allowResize, final boolean isModal) { mainWindow.shell.getDisplay().syncExec(new AERunnable() { public void runSupport() { String realURL = url; ContentNetwork cn = ContentNetworkUtils.getContentNetworkFromTarget(target); if ( !realURL.startsWith( "http" )){ realURL = cn.getSiteRelativeURL(realURL, false ); } if (target == null) { if (UrlFilter.getInstance().urlCanRPC(realURL)) { realURL = cn.appendURLSuffix(realURL, false, true); } BrowserWindow window = new BrowserWindow(mainWindow.shell, realURL, w, h, allowResize, isModal); window.waitUntilClosed(); } else { mainWindow.showURL(realURL, target); } } }); return true; } public boolean viewURL(final String url, final String target, final double w, final double h, final boolean allowResize, final boolean isModal) { mainWindow.shell.getDisplay().syncExec(new AERunnable() { public void runSupport() { String realURL = url; ContentNetwork cn = ContentNetworkUtils.getContentNetworkFromTarget(target); if ( !realURL.startsWith( "http" )){ realURL = cn.getSiteRelativeURL(realURL, false ); } if (target == null) { if (UrlFilter.getInstance().urlCanRPC(realURL)) { realURL = cn.appendURLSuffix(realURL, false, true); } BrowserWindow window = new BrowserWindow(mainWindow.shell, realURL, w, h, allowResize, isModal); window.waitUntilClosed(); } else { mainWindow.showURL(realURL, target); } } }); return true; } public void oldMainWindowInitialized(MainWindow oldMainWindow) { UIFunctionsSWT uiFunctions = oldMainWindow.getUIFunctions(); if (uiFunctions == null) { return; } pluginViews_mon.enter(); try { for (Iterator iterator = mapPluginViews.keySet().iterator(); iterator.hasNext();) { Object key = iterator.next(); if (key instanceof PluginView) { uiFunctions.addPluginView((PluginView) key); } else if (key instanceof UISWTPluginView) { uiFunctions.addPluginView((UISWTPluginView) key); } else if (key instanceof String) { UISWTViewEventListener value = (UISWTViewEventListener) mapPluginViews.get(key); uiFunctions.addPluginView((String) key, value); } } mapPluginViews.clear(); } finally { pluginViews_mon.exit(); } } // @see com.aelitis.azureus.ui.UIFunctions#promptUser(java.lang.String, java.lang.String, java.lang.String[], int, java.lang.String, java.lang.String, boolean, int) public void promptUser(String title, String text, String[] buttons, int defaultOption, String rememberID, String rememberText, boolean rememberByDefault, int autoCloseInMS, UserPrompterResultListener l) { MessageBoxShell.open(getMainShell(), title, text, buttons, defaultOption, rememberID, rememberText, rememberByDefault, autoCloseInMS, l); } // @see com.aelitis.azureus.ui.UIFunctions#getUserPrompter(java.lang.String, java.lang.String, java.lang.String[], int) public UIFunctionsUserPrompter getUserPrompter(String title, String text, String[] buttons, int defaultOption) { MessageBoxShell mb = new MessageBoxShell(title, text, buttons, defaultOption); return mb; } public boolean isGlobalTransferBarShown() { if (!AzureusCoreFactory.isCoreRunning()) { return false; } return AllTransfersBar.getManager().isOpen( AzureusCoreFactory.getSingleton().getGlobalManager()); } public void showGlobalTransferBar() { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { AllTransfersBar.open(core.getGlobalManager(), getMainShell()); } }); } public void closeGlobalTransferBar() { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { AllTransfersBar.close(core.getGlobalManager()); } }); } public void refreshTorrentMenu() { if (!isTorrentMenuVisible) { return; } try { Utils.execSWTThread(new AERunnable() { public void runSupport() { final MenuItem torrentItem = MenuFactory.findMenuItem( mainWindow.getMainMenu().getMenu(IMenuConstants.MENU_ID_MENU_BAR), MenuFactory.MENU_ID_TORRENT, false); if (null != torrentItem) { DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent(); final DownloadManager[] dm_final = dms; final TableViewSWT tv_final = null; final boolean detailed_view_final = false; if (null == dm_final) { torrentItem.setEnabled(false); } else { torrentItem.setData("downloads", dm_final); torrentItem.setData("TableView", tv_final); torrentItem.setData("is_detailed_view", Boolean.valueOf(detailed_view_final)); torrentItem.setEnabled(true); } } } }); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "refreshTorrentMenu", e)); } } public IMainMenu createMainMenu(Shell shell) { return new MainMenu(getSkin(), shell); } public SWTSkin getSkin() { return skin; } public void setSkin(SWTSkin skin) { this.skin = skin; } public IMainWindow getMainWindow() { return mainWindow; } // @see com.aelitis.azureus.ui.UIFunctions#getUIUpdater() public UIUpdater getUIUpdater() { return UIUpdaterSWT.getInstance(); } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#closeAllDetails() public void closeAllDetails() { SkinView sideBarView = SkinViewManager.getByClass(SideBar.class); if (sideBarView instanceof SideBar) { SideBar sideBar = (SideBar) sideBarView; SideBarEntry[] sideBarEntries = sideBar.getEntries(); for (int i = 0; i < sideBarEntries.length; i++) { SideBarEntry entry = sideBarEntries[i]; String id = entry.getId(); if (id != null && id.startsWith("DMDetails_")) { sideBar.closeEntry(id); } } } } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#hasDetailViews() public boolean hasDetailViews() { SkinView sideBarView = SkinViewManager.getByClass(SideBar.class); if (sideBarView instanceof SideBar) { SideBar sideBar = (SideBar) sideBarView; SideBarEntry[] sideBarEntries = sideBar.getEntries(); for (int i = 0; i < sideBarEntries.length; i++) { SideBarEntry entry = sideBarEntries[i]; String id = entry.getId(); if (id != null && id.startsWith("DMDetails_")) { return true; } } } return false; } public void performAction( int action_id, Object args, actionListener listener ) { if ( action_id == ACTION_FULL_UPDATE ){ FullUpdateWindow.handleUpdate((String)args, listener ); }else{ Debug.out( "Unknown action " + action_id ); } } // @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#showCoreWaitDlg() public Shell showCoreWaitDlg() { final SkinnedDialog closeDialog = new SkinnedDialog( "skin3_dlg_coreloading", "coreloading.body", SWT.TITLE | SWT.BORDER | SWT.APPLICATION_MODAL); closeDialog.setTitle(MessageText.getString("dlg.corewait.title")); SWTSkin skin = closeDialog.getSkin(); SWTSkinObjectButton soButton = (SWTSkinObjectButton) skin.getSkinObject("close"); final SWTSkinObjectText soWaitTask = (SWTSkinObjectText) skin.getSkinObject("task"); final SWTSkinObject soWaitProgress = skin.getSkinObject("progress"); if (soWaitProgress != null) { soWaitProgress.getControl().addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { Control c = (Control) e.widget; Point size = c.getSize(); e.gc.setBackground(ColorCache.getColor(e.display, "#23a7df")); Object data = soWaitProgress.getData("progress"); if (data instanceof Long) { int waitProgress = ((Long) data).intValue(); int breakX = size.x * waitProgress / 100; e.gc.fillRectangle(0, 0, breakX, size.y); e.gc.setBackground(ColorCache.getColor(e.display, "#cccccc")); e.gc.fillRectangle(breakX, 0, size.x - breakX, size.y); } } }); } AzureusCore core = AzureusCoreFactory.getSingleton(); if (!AzureusCoreFactory.isCoreRunning()) { final Initializer initializer = Initializer.getLastInitializer(); if (initializer != null) { initializer.addListener(new InitializerListener() { public void reportPercent(final int percent) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (soWaitProgress != null && !soWaitProgress.isDisposed()) { soWaitProgress.setData("progress", new Long(percent)); soWaitProgress.getControl().redraw(); soWaitProgress.getControl().update(); } } }); if (percent > 100) { initializer.removeListener(this); } } public void reportCurrentTask(String currentTask) { if (soWaitTask != null && !soWaitTask.isDisposed()) { soWaitTask.setText(currentTask); } } }); } } if (soButton != null) { soButton.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { closeDialog.close(); } }); } closeDialog.addCloseListener(new SkinnedDialogClosedListener() { public void skinDialogClosed(SkinnedDialog dialog) { } }); closeDialog.open(); return closeDialog.getShell(); } // @see com.aelitis.azureus.ui.UIFunctions#doSearch(java.lang.String) public void doSearch(String searchText) { mainWindow.doSearch(searchText); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/main/MainMenu.java0000644000175000017500000004656111276126554024615 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.shells.main; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.config.impl.ConfigurationDefaults; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.IMainMenu; import org.gudy.azureus2.ui.swt.mainwindow.IMenuConstants; import org.gudy.azureus2.ui.swt.mainwindow.MenuFactory; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.ui.skin.SkinConstants; import com.aelitis.azureus.ui.swt.skin.SWTSkin; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import com.aelitis.azureus.ui.swt.skin.SWTSkinUtils; import com.aelitis.azureus.ui.swt.toolbar.ToolBarItem; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager; import com.aelitis.azureus.ui.swt.views.skin.ToolBarView; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.ContentNetworkUtils; public class MainMenu implements IMainMenu, IMenuConstants { private static final boolean ALLOW_ACTIONBAR_HIDING = false; private static final boolean ALLOW_SIDEBAR_HIDING = true; final String PREFIX_V2 = "MainWindow.menu"; final String PREFIX_V3 = "v3.MainWindow.menu"; private Menu menuBar; private final SWTSkin skin; /** * Creates the main menu on the supplied shell * * @param shell */ public MainMenu(SWTSkin skin, final Shell shell) { this.skin = skin; if (null == skin) { throw new NullPointerException( "The parameter [SWTSkin skin] can not be null"); } buildMenu(shell); } private void buildMenu(Shell parent) { //The Main Menu menuBar = new Menu(parent, SWT.BAR); parent.setMenuBar(menuBar); addFileMenu(); //addViewMenu(); addSimpleViewMenu(); addCommunityMenu(); addToolsMenu(); /* * The Torrents menu is a user-configured option */ if (true == COConfigurationManager.getBooleanParameter("show_torrents_menu")) { addTorrentMenu(); } addWindowMenu(); // ===== Debug menu (development only)==== if (org.gudy.azureus2.core3.util.Constants.isCVSVersion()) { Menu menuDebug = org.gudy.azureus2.ui.swt.mainwindow.DebugMenuHelper.createDebugMenuItem(menuBar); DebugMenuHelper.createDebugMenuItem(menuDebug); } addV3HelpMenu(); /* * Enabled/disable menus based on what ui mode we're in; this method call controls * which menus are enabled when we're in Vuze vs. Vuze Advanced */ MenuFactory.updateEnabledStates(menuBar); } /** * Creates the File menu and all its children */ private void addFileMenu() { MenuItem fileItem = MenuFactory.createFileMenuItem(menuBar); final Menu fileMenu = fileItem.getMenu(); builFileMenu(fileMenu); fileMenu.addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { MenuItem[] menuItems = fileMenu.getItems(); for (int i = 0; i < menuItems.length; i++) { menuItems[i].dispose(); } builFileMenu(fileMenu); } }); } /** * Builds the File menu dynamically * @param fileMenu */ private void builFileMenu(Menu fileMenu) { MenuItem openMenuItem = MenuFactory.createOpenMenuItem(fileMenu); Menu openSubMenu = openMenuItem.getMenu(); MenuFactory.addOpenTorrentMenuItem(openSubMenu); MenuFactory.addOpenTorrentForTrackingMenuItem(openSubMenu); MenuFactory.addOpenVuzeFileMenuItem(openSubMenu); int userMode = COConfigurationManager.getIntParameter("User Mode"); if ( userMode > 0 ){ Menu shareSubMenu = MenuFactory.createShareMenuItem(fileMenu).getMenu(); MenuFactory.addShareFileMenuItem(shareSubMenu); MenuFactory.addShareFolderMenuItem(shareSubMenu); MenuFactory.addShareFolderContentMenuItem(shareSubMenu); MenuFactory.addShareFolderContentRecursiveMenuItem(shareSubMenu); } MenuFactory.addCreateMenuItem(fileMenu); MenuFactory.addSeparatorMenuItem(fileMenu); MenuFactory.addCloseWindowMenuItem(fileMenu); MenuFactory.addCloseDetailsMenuItem(fileMenu); MenuFactory.addCloseDownloadBarsToMenu(fileMenu); MenuFactory.addSeparatorMenuItem(fileMenu); MenuFactory.createTransfersMenuItem(fileMenu); /* * No need for restart and exit on OS X since it's already handled on the application menu */ if (!Utils.isCarbon) { MenuFactory.addSeparatorMenuItem(fileMenu); MenuFactory.addRestartMenuItem(fileMenu); } if (!Constants.isOSX) { MenuFactory.addExitMenuItem(fileMenu); } } private void addSimpleViewMenu() { try { MenuItem viewItem = MenuFactory.createViewMenuItem(menuBar); final Menu viewMenu = viewItem.getMenu(); MenuFactory.addMenuItem(viewMenu, SWT.CHECK, PREFIX_V3 + ".view.sidebar", new Listener() { public void handleEvent(Event event) { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { sidebar.flipSideBarVisibility(); } } }); MenuFactory.addMenuItem(viewMenu, SWT.CHECK, PREFIX_V3 + ".view.toolbartext", new Listener() { public void handleEvent(Event event) { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { tb.flipShowText(); } } }); if (Constants.isCVSVersion()) { MenuItem itemStatusBar = MenuFactory.createTopLevelMenuItem(viewMenu, "v3.MainWindow.menu.view.statusbar"); itemStatusBar.setText(itemStatusBar.getText() + " (CVS Only)"); Menu menuStatusBar = itemStatusBar.getMenu(); final String[] statusAreaLangs = { "ConfigView.section.style.status.show_sr", "ConfigView.section.style.status.show_nat", "ConfigView.section.style.status.show_ddb", "ConfigView.section.style.status.show_ipf", }; final String[] statusAreaConfig = { "Status Area Show SR", "Status Area Show NAT", "Status Area Show DDB", "Status Area Show IPF", }; for (int i = 0; i < statusAreaConfig.length; i++) { final String configID = statusAreaConfig[i]; String langID = statusAreaLangs[i]; final MenuItem item = new MenuItem(menuStatusBar, SWT.CHECK); Messages.setLanguageText(item, langID); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { COConfigurationManager.setParameter(configID, !COConfigurationManager.getBooleanParameter(configID)); } }); menuStatusBar.addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { item.setSelection(COConfigurationManager.getBooleanParameter(configID)); } }); } } MenuFactory.addSeparatorMenuItem(viewMenu); MenuFactory.addMenuItem(viewMenu, SWT.RADIO, PREFIX_V3 + ".view.asSimpleList", new Listener() { public void handleEvent(Event event) { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { ToolBarItem item = tb.getToolBarItem("modeBig"); if (item != null) { item.triggerToolBarItem(); } } } }); MenuFactory.addMenuItem(viewMenu, SWT.RADIO, PREFIX_V3 + ".view.asAdvancedList", new Listener() { public void handleEvent(Event event) { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { ToolBarItem item = tb.getToolBarItem("modeSmall"); if (item != null) { item.triggerToolBarItem(); } } } }); viewMenu.addMenuListener(new MenuListener() { public void menuShown(MenuEvent e) { MenuItem sidebarMenuItem = MenuFactory.findMenuItem(viewMenu, PREFIX_V3 + ".view.sidebar"); if (sidebarMenuItem != null) { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { sidebarMenuItem.setSelection(sidebar.isVisible()); } } MenuItem itemShowText = MenuFactory.findMenuItem(viewMenu, PREFIX_V3 + ".view.toolbartext"); if (itemShowText != null) { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { itemShowText.setSelection(tb.getShowText()); } } MenuItem itemShowAsSimple = MenuFactory.findMenuItem(viewMenu, PREFIX_V3 + ".view.asSimpleList"); if (itemShowAsSimple != null) { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { ToolBarItem item = tb.getToolBarItem("modeBig"); if (item != null && item.isEnabled()) { itemShowAsSimple.setEnabled(true); itemShowAsSimple.setSelection(!item.getSkinButton().getSkinObject().getSuffix().equals( "")); } else { itemShowAsSimple.setEnabled(false); itemShowAsSimple.setSelection(false); } } } MenuItem itemShowAsAdv = MenuFactory.findMenuItem(viewMenu, PREFIX_V3 + ".view.asAdvancedList"); if (itemShowAsAdv != null) { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { ToolBarItem item = tb.getToolBarItem("modeSmall"); if (item != null && item.isEnabled()) { itemShowAsAdv.setEnabled(true); itemShowAsAdv.setSelection(!item.getSkinButton().getSkinObject().getSuffix().equals( "")); } else { itemShowAsAdv.setSelection(false); itemShowAsAdv.setEnabled(false); } } } } public void menuHidden(MenuEvent e) { } }); } catch (Exception e) { Debug.out("Error creating View Menu", e); } } /** * Creates the View menu and all its children */ private void addViewMenu() { try { MenuItem viewItem = MenuFactory.createViewMenuItem(menuBar); final Menu viewMenu = viewItem.getMenu(); addViewToolBarsMenu(viewMenu); //addViewMenuItems(viewMenu); } catch (Exception e) { Debug.out("Error creating View Menu", e); } } /** * * * @since 3.1.1.1 */ private void addViewToolBarsMenu(Menu parent) { try { MenuItem viewToolBarsItem = MenuFactory.createTopLevelMenuItem(parent, PREFIX_V3 + ".view.toolbars"); final Menu viewToolBarsMenu = viewToolBarsItem.getMenu(); if (ALLOW_SIDEBAR_HIDING) { MenuFactory.addMenuItem(viewToolBarsMenu, SWT.CHECK, PREFIX_V3 + ".view.sidebar", new Listener() { public void handleEvent(Event event) { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { sidebar.flipSideBarVisibility(); } } }); } if (ALLOW_ACTIONBAR_HIDING) { MenuFactory.addMenuItem(viewToolBarsMenu, SWT.CHECK, PREFIX_V3 + ".view.actionbar", new Listener() { public void handleEvent(Event event) { if (skin != null) { SWTSkinObject so = skin.getSkinObject(SkinConstants.VIEWID_TAB_BAR); if (so != null) { so.setVisible(!so.isVisible()); } } } }); } /* * NOTE: The following menu items must be created on-demand because * their creation code relies on the main window being in proper size already. * Adding these menus before the window is fully opened will result in improper * layout of the PluginBar and TabBar */ viewToolBarsMenu.addMenuListener(new MenuListener() { public void menuShown(MenuEvent e) { MenuItem sidebarMenuItem = MenuFactory.findMenuItem(viewToolBarsMenu, PREFIX_V3 + ".view.sidebar"); if (sidebarMenuItem != null) { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { sidebarMenuItem.setSelection(sidebar.isVisible()); } } MenuItem actionbarMenuItem = MenuFactory.findMenuItem( viewToolBarsMenu, PREFIX_V3 + ".view.actionbar"); if (actionbarMenuItem != null) { if (skin != null) { SWTSkinObject so = skin.getSkinObject(SkinConstants.VIEWID_TAB_BAR); if (so != null) { actionbarMenuItem.setSelection(so.isVisible()); } } } if (null == MenuFactory.findMenuItem(viewToolBarsMenu, PREFIX_V3 + ".view." + SkinConstants.VIEWID_PLUGINBAR)) { createViewMenuItem(skin, viewToolBarsMenu, PREFIX_V3 + ".view." + SkinConstants.VIEWID_PLUGINBAR, SkinConstants.VIEWID_PLUGINBAR + ".visible", SkinConstants.VIEWID_PLUGINBAR, true, 0); } } public void menuHidden(MenuEvent e) { // Do nothing } }); } catch (Exception e) { Debug.out("Error creating View Menu", e); } } private void addViewMenuItems(Menu viewMenu) { MenuFactory.addMenuItem(viewMenu, PREFIX_V3 + ".browse", new Listener() { public void handleEvent(Event event) { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); sidebar.showEntryByID(SideBar.SIDEBAR_SECTION_BROWSE); } }); MenuFactory.addMenuItem(viewMenu, PREFIX_V3 + ".library", new Listener() { public void handleEvent(Event event) { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); sidebar.showEntryByID(SideBar.SIDEBAR_SECTION_LIBRARY); } }); } /** * Creates the Tools menu and all its children */ private void addToolsMenu() { MenuItem toolsItem = MenuFactory.createToolsMenuItem(menuBar); Menu toolsMenu = toolsItem.getMenu(); MenuFactory.addMyTrackerMenuItem(toolsMenu); MenuFactory.addMySharesMenuItem(toolsMenu); MenuFactory.addConsoleMenuItem(toolsMenu); MenuFactory.addStatisticsMenuItem(toolsMenu); MenuFactory.addTransferBarToMenu(toolsMenu); MenuFactory.addAllPeersMenuItem(toolsMenu); MenuFactory.addClientStatsMenuItem(toolsMenu); MenuFactory.addBlockedIPsMenuItem(toolsMenu); MenuFactory.addSeparatorMenuItem(toolsMenu); MenuFactory.createPluginsMenuItem(toolsMenu, true); MenuFactory.addOptionsMenuItem(toolsMenu); } /** * Creates the Help menu and all its children */ private void addV3HelpMenu() { MenuItem helpItem = MenuFactory.createHelpMenuItem(menuBar); Menu helpMenu = helpItem.getMenu(); if (false == Constants.isOSX) { /* * The 'About' menu is on the application menu on OSX */ MenuFactory.addAboutMenuItem(helpMenu); MenuFactory.addSeparatorMenuItem(helpMenu); } MenuFactory.addMenuItem(helpMenu, PREFIX_V3 + ".getting_started", new Listener() { public void handleEvent(Event event) { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); sidebar.showEntryByID(SideBar.SIDEBAR_SECTION_WELCOME); } }); MenuFactory.addHelpSupportMenuItem( helpMenu, ContentNetworkUtils.getUrl( ConstantsVuze.getDefaultContentNetwork(), ContentNetwork.SERVICE_SUPPORT)); MenuFactory.addReleaseNotesMenuItem(helpMenu); if (false == SystemProperties.isJavaWebStartInstance()) { MenuFactory.addSeparatorMenuItem(helpMenu); MenuFactory.addCheckUpdateMenuItem(helpMenu); } MenuFactory.addDonationMenuItem(helpMenu); MenuFactory.addSeparatorMenuItem(helpMenu); MenuFactory.addConfigWizardMenuItem(helpMenu); MenuFactory.addNatTestMenuItem(helpMenu); MenuFactory.addSpeedTestMenuItem(helpMenu); MenuFactory.addSeparatorMenuItem(helpMenu); MenuFactory.addDebugHelpMenuItem(helpMenu); } /** * Creates the Window menu and all its children */ private void addWindowMenu() { MenuItem menu_window = MenuFactory.createWindowMenuItem(menuBar); Menu windowMenu = menu_window.getMenu(); MenuFactory.addMinimizeWindowMenuItem(windowMenu); MenuFactory.addZoomWindowMenuItem(windowMenu); MenuFactory.addSeparatorMenuItem(windowMenu); MenuFactory.addBringAllToFrontMenuItem(windowMenu); MenuFactory.addSeparatorMenuItem(windowMenu); MenuFactory.appendWindowMenuItems(windowMenu); } /** * Creates the Torrent menu and all its children */ private void addTorrentMenu() { MenuFactory.createTorrentMenuItem(menuBar); } public Menu getMenu(String id) { if (true == MENU_ID_MENU_BAR.equals(id)) { return menuBar; } return MenuFactory.findMenu(menuBar, id); } private void addCommunityMenu() { MenuItem item = MenuFactory.createTopLevelMenuItem(menuBar, MENU_ID_COMMUNITY); Menu communityMenu = item.getMenu(); MenuFactory.addMenuItem(communityMenu, MENU_ID_COMMUNITY_FORUMS, new Listener() { public void handleEvent(Event e) { Utils.launch(ContentNetworkUtils.getUrl( ConstantsVuze.getDefaultContentNetwork(), ContentNetwork.SERVICE_FORUMS)); } }); MenuFactory.addMenuItem(communityMenu, MENU_ID_COMMUNITY_WIKI, new Listener() { public void handleEvent(Event e) { Utils.launch(ContentNetworkUtils.getUrl( ConstantsVuze.getDefaultContentNetwork(), ContentNetwork.SERVICE_WIKI)); } }); MenuFactory.addMenuItem(communityMenu, MENU_ID_COMMUNITY_BLOG, new Listener() { public void handleEvent(Event e) { Utils.launch(ContentNetworkUtils.getUrl( ConstantsVuze.getDefaultContentNetwork(), ContentNetwork.SERVICE_BLOG)); } }); MenuFactory.addMenuItem(communityMenu, MENU_ID_FAQ, new Listener() { public void handleEvent(Event e) { Utils.launch(ContentNetworkUtils.getUrl( ConstantsVuze.getDefaultContentNetwork(), ContentNetwork.SERVICE_FAQ)); } }); } //==================================== /** * @deprecated This method has been replaced with {@link #getMenu(String)}; * use {@link #getMenu(IMenuConstants.MENU_ID_MENU_BAR)} instead * @return the menuBar */ public Menu getMenuBar() { return menuBar; } /** * @param viewMenu * @param string * @param string2 */ public static MenuItem createViewMenuItem(final SWTSkin skin, Menu viewMenu, final String textID, final String configID, final String viewID, final boolean fast, int menuIndex) { MenuItem item; if (!ConfigurationDefaults.getInstance().doesParameterDefaultExist(configID)) { COConfigurationManager.setBooleanDefault(configID, true); } item = MenuFactory.addMenuItem(viewMenu, SWT.CHECK, menuIndex, textID, new Listener() { public void handleEvent(Event event) { SWTSkinObject skinObject = skin.getSkinObject(viewID); if (skinObject != null) { boolean newVisibility = !skinObject.isVisible(); SWTSkinUtils.setVisibility(skin, configID, viewID, newVisibility, true, fast); } } }); SWTSkinUtils.setVisibility(skin, configID, viewID, COConfigurationManager.getBooleanParameter(configID), false, true); final MenuItem itemViewPluginBar = item; final ParameterListener listener = new ParameterListener() { public void parameterChanged(String parameterName) { itemViewPluginBar.setSelection(COConfigurationManager.getBooleanParameter(parameterName)); } }; COConfigurationManager.addAndFireParameterListener(configID, listener); item.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { COConfigurationManager.removeParameterListener(configID, listener); } }); return item; } // backward compat.. public static void setVisibility(SWTSkin skin, String configID, String viewID, boolean visible) { SWTSkinUtils.setVisibility(skin, configID, viewID, visible, true, false); } // backward compat.. public static void setVisibility(SWTSkin skin, String configID, String viewID, boolean visible, boolean save) { SWTSkinUtils.setVisibility(skin, configID, viewID, visible, save, false); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/shells/AuthorizeWindow.java0000644000175000017500000000445511136274462025313 0ustar adrianadrian/** * Created on Dec 2, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.shells; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.messenger.ClientMessageContext; import com.aelitis.azureus.core.messenger.browser.BrowserMessage; import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener; import com.aelitis.azureus.util.ContentNetworkUtils; /** * @author TuxPaper * @created Dec 2, 2008 * */ public class AuthorizeWindow { public static boolean open = false; public static boolean openAuthorizeWindow(final ContentNetwork cn) { if (open) { return false; } open = true; try { String authURL = ContentNetworkUtils.getUrl(cn, ContentNetwork.SERVICE_AUTHORIZE, new Object[] { cn.getPersistentProperty(ContentNetwork.PP_SOURCE_REF) }); BrowserWindow browserWindow = new BrowserWindow(Utils.findAnyShell(), authURL, 560, 390, false, true); final Boolean[] b = new Boolean[1]; b[0] = Boolean.FALSE; ClientMessageContext context = browserWindow.getContext(); context.addMessageListener(new AbstractBrowserMessageListener( "contentnetwork") { public void handleMessage(BrowserMessage message) { String opid = message.getOperationId(); if ("authorize".equals(opid)) { cn.setPersistentProperty(ContentNetwork.PP_AUTH_PAGE_SHOWN, Boolean.TRUE); b[0] = Boolean.TRUE; } } }); browserWindow.waitUntilClosed(); return b[0].booleanValue(); } finally { open = false; } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/extlistener/0000755000175000017500000000000011310377632022347 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/extlistener/StimulusRPC.java0000644000175000017500000002170111305664420025403 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.extlistener; import java.util.Collections; import java.util.Map; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.donations.DonationWindow; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.core.messenger.ClientMessageContext; import com.aelitis.azureus.core.messenger.PlatformMessenger; import com.aelitis.azureus.core.messenger.browser.BrowserMessage; import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfoContentNetwork; import com.aelitis.azureus.ui.swt.browser.listener.ConfigListener; import com.aelitis.azureus.ui.swt.browser.listener.DisplayListener; import com.aelitis.azureus.ui.swt.browser.listener.TorrentListener; import com.aelitis.azureus.ui.swt.shells.main.MainWindow; import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; import com.aelitis.azureus.util.*; /** * @author TuxPaper * @created Feb 7, 2008 * */ public class StimulusRPC { /** * Hooks some listeners * @param mainWindow */ public static void hookListeners(final AzureusCore core, final MainWindow mainWindow) { /* * This code block was moved here from being in-line in MainWindow */ ExternalStimulusHandler.addListener(new ExternalStimulusListener() { public boolean receive(String name, Map values) { try { if (values == null) { return false; } if (!name.equals("AZMSG")) { return false; } Object valueObj = values.get("value"); if (!(valueObj instanceof String)) { return false; } String value = (String) valueObj; ClientMessageContext context = PlatformMessenger.getClientMessageContext(); if (context == null) { return false; } // AZMSG;x;listener-id;op-id;params String[] splitVal = value.split(";", 5); if (splitVal.length != 5) { return false; } String lId = splitVal[2]; String opId = splitVal[3]; Map decodedMap = JSONUtils.decodeJSON(splitVal[4]); if (decodedMap == null) { decodedMap = Collections.EMPTY_MAP; } if (opId.equals(DisplayListener.OP_OPEN_URL)) { String url = MapUtils.getMapString(decodedMap, "url", null); if (!decodedMap.containsKey("target")) { context.debug("no target for url: " + url); } else if (UrlFilter.getInstance().urlIsBlocked(url)) { context.debug("url blocked: " + url); } else if (!UrlFilter.getInstance().urlCanRPC(url)) { context.debug("url not in whitelistL " + url); } else { // implicit bring to front final UIFunctions functions = UIFunctionsManager.getUIFunctions(); if (functions != null) { functions.bringToFront(); } // this is actually sync.. so we could add a completion listener // and return the boolean result if we wanted/needed BrowserMessageDispatcher dispatcher = context.getDispatcher(); if (dispatcher != null) { dispatcher.dispatch(new BrowserMessage(lId, opId, decodedMap)); } else { context.debug("No dispatcher for StimulusRPC" + opId); } return true; } } else if (opId.equals(TorrentListener.OP_LOAD_TORRENT)) { if (decodedMap.containsKey("b64")) { String b64 = MapUtils.getMapString(decodedMap, "b64", null); return TorrentListener.loadTorrentByB64(core, b64); } else if (decodedMap.containsKey("url")) { String url = MapUtils.getMapString(decodedMap, "url", null); boolean blocked = UrlFilter.getInstance().urlIsBlocked(url); // Security: Only allow torrents from whitelisted urls if (blocked) { Debug.out("stopped loading torrent URL because it's not in whitelist"); return false; } boolean playNow = MapUtils.getMapBoolean(decodedMap, "play-now", false); boolean playPrepare = MapUtils.getMapBoolean(decodedMap, "play-prepare", false); boolean bringToFront = MapUtils.getMapBoolean(decodedMap, "bring-to-front", true); // Content Network of context is invalid because it's the // internal one used for anythin. Get network id from params instead long contentNetworkID = MapUtils.getMapLong(decodedMap, "content-network", ConstantsVuze.getDefaultContentNetwork().getID()); ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetwork(contentNetworkID); if (cn == null) { cn = ConstantsVuze.getDefaultContentNetwork(); } DownloadUrlInfo dlInfo = new DownloadUrlInfoContentNetwork(url, cn); dlInfo.setReferer(MapUtils.getMapString(decodedMap, "referer", null)); TorrentUIUtilsV3.loadTorrent(dlInfo, playNow, playPrepare, bringToFront, false); return true; } } else if (opId.equals("is-ready")) { // The platform needs to know when it can call open-url, and it // determines this by the is-ready function return mainWindow.isReady(); } else if (opId.equals("is-version-ge")) { if (decodedMap.containsKey("version")) { String id = MapUtils.getMapString(decodedMap, "id", "client"); String version = MapUtils.getMapString(decodedMap, "version", ""); if (id.equals("client")) { return org.gudy.azureus2.core3.util.Constants.compareVersions( org.gudy.azureus2.core3.util.Constants.AZUREUS_VERSION, version) >= 0; } } return false; } else if (opId.equals("is-active-tab")) { if (decodedMap.containsKey("tab")) { String tabID = MapUtils.getMapString(decodedMap, "tab", ""); if (tabID.length() > 0) { // 3.2 TODO: Should we be checking for partial matches? SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); SideBarEntrySWT entry = sidebar.getCurrentEntry(); if (entry != null) { return entry.id.equals(tabID); } } } return false; } else if (ConfigListener.DEFAULT_LISTENER_ID.equals(lId)) { if (ConfigListener.OP_NEW_INSTALL.equals(opId)) { return COConfigurationManager.isNewInstall(); } else if (ConfigListener.OP_CHECK_FOR_UPDATES.equals(opId)) { ConfigListener.checkForUpdates(); return true; } else if (ConfigListener.OP_LOG_DIAGS.equals(opId)) { ConfigListener.logDiagnostics(); return true; } } else if (DisplayListener.DEFAULT_LISTENER_ID.equals(lId)) { if (DisplayListener.OP_REFRESH_TAB.equals(opId)) { DisplayListener.refreshTab(MapUtils.getMapString(decodedMap, "browser-id", "")); } else if (DisplayListener.OP_SWITCH_TO_TAB.equals(opId)) { DisplayListener.switchToTab(MapUtils.getMapString(decodedMap, "target", ""), MapUtils.getMapString(decodedMap, "source-ref", null)); } } else if (DisplayListener.OP_SHOW_DONATION_WINDOW.equals(lId)) { DonationWindow.open(true, MapUtils.getMapString(decodedMap, "source-ref", "SRPC")); } if (System.getProperty( "browser.route.all.external.stimuli.for.testing", "false").equalsIgnoreCase( "true")) { BrowserMessageDispatcher dispatcher = context.getDispatcher(); if (dispatcher != null) { dispatcher.dispatch(new BrowserMessage(lId, opId, decodedMap)); } } else { System.err.println("Unhandled external stimulus: " + value); } } catch (Exception e) { Debug.out(e); } return false; } public int query(String name, Map values) { return (Integer.MIN_VALUE); } }); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/subscriptions/0000755000175000017500000000000011310377632022710 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionSelectedContent.java0000644000175000017500000000645711276523212031255 0ustar adrianadrian/* * Created on Apr 8, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.ui.swt.subscriptions; import java.io.File; import java.net.URL; import java.util.Map; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentCreator; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.util.AETemporaryFileHandler; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.IconBarEnabler; import com.aelitis.azureus.core.subs.Subscription; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.ui.selectedcontent.ISelectedVuzeFileContent; import com.aelitis.azureus.ui.swt.toolbar.ToolBarEnablerSelectedContent; public class SubscriptionSelectedContent extends ToolBarEnablerSelectedContent implements ISelectedVuzeFileContent { private Subscription subs; private TOTorrent torrent; protected SubscriptionSelectedContent( IconBarEnabler _enabler, Subscription _subs ) { super( _enabler ); subs = _subs; } public String getDisplayName() { return( MessageText.getString( "subscriptions.column.name" ) + ": " + subs.getName()); } public String getHash() { return( subs.getID()); } public VuzeFile getVuzeFile() { try{ return( subs.getVuzeFile()); }catch( Throwable e ){ Debug.out(e); } return( null ); } public TOTorrent getTorrent() { synchronized( this ){ if ( torrent == null ){ // hack alert - we embed the vuze-file into a torrent to allow it to go through // the normal share route, then pick it out again when the recipient 'downloads' it try{ VuzeFile vf = subs.getVuzeFile(); // if not corrupt.... if ( vf != null ){ File f1 = AETemporaryFileHandler.createTempFile(); File f = new File( f1.getParent(), "Update Vuze to access this share_" + f1.getName()); f1.delete(); try{ vf.write( f ); TOTorrentCreator cr = TOTorrentFactory.createFromFileOrDirWithComputedPieceLength( f, new URL( "dht://" )); TOTorrent temp = cr.create(); Map vuze_map = vf.exportToMap(); Map torrent_map = temp.serialiseToMap(); torrent_map.putAll( vuze_map ); torrent = TOTorrentFactory.deserialiseFromMap( torrent_map ); }finally{ f.delete(); } } }catch( Throwable e ){ Debug.out( e ); } } } return( torrent ); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsView.java0000644000175000017500000002714211267524522027266 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.subscriptions; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.views.IView; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import com.aelitis.azureus.core.subs.Subscription; import com.aelitis.azureus.core.subs.SubscriptionManagerFactory; import com.aelitis.azureus.core.subs.SubscriptionManagerListener; import com.aelitis.azureus.ui.UserPrompterResultListener; import com.aelitis.azureus.ui.common.table.*; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.swt.columns.subscriptions.*; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.subscriptions.SubscriptionManagerUI.sideBarItem; import com.aelitis.azureus.ui.swt.toolbar.ToolBarEnabler; import com.aelitis.azureus.ui.swt.utils.ColorCache; public class SubscriptionsView implements UIUpdatable, IView, SubscriptionManagerListener, ToolBarEnabler { private static final String TABLE_ID = "subscriptions"; private TableViewSWT view; private Composite viewComposite; private Font textFont1; private Font textFont2; public SubscriptionsView() { } public void associationsChanged(byte[] association_hash) { // TODO Auto-generated method stub } public void subscriptionSelected( Subscription subscription ) { } public void subscriptionAdded(Subscription subscription) { if ( subscription.isSubscribed()){ view.addDataSource(subscription); } } public void subscriptionRemoved(Subscription subscription) { view.removeDataSource(subscription); } public void subscriptionChanged(Subscription subscription) { if ( view.getRow(subscription) == null ){ subscriptionAdded( subscription ); }else{ view.refreshTable(true); } } public boolean isEnabled(String itemKey) { if("remove".equals(itemKey) ) { return view.getSelectedRowsSize() > 0; } if("share".equals(itemKey) ) { TableRowCore[] rows = view.getSelectedRows(); if ( rows.length == 1 ){ Subscription subs = (Subscription) rows[0].getDataSource(); return( true ); } return( false ); } return false; } public String getUpdateUIName() { // TODO Auto-generated method stub return null; } public boolean isSelected(String itemKey) { return false; } public void itemActivated(String itemKey) { if("remove".equals(itemKey) ) { removeSelected(); } } private void removeSelected() { TableRowCore[] rows = view.getSelectedRows(); Subscription[] subs = new Subscription[rows.length]; int i = 0; for (Subscription subscription : subs) { subs[i] = (Subscription) rows[i++].getDataSource(); } removeSubs(subs, 0); } private void removeSubs(final Subscription[] toRemove, final int startIndex) { if (toRemove[startIndex] == null) { int nextIndex = startIndex + 1; if (nextIndex < toRemove.length) { removeSubs(toRemove, nextIndex); } return; } MessageBoxShell mb = new MessageBoxShell( MessageText.getString("message.confirm.delete.title"), MessageText.getString("message.confirm.delete.text", new String[] { toRemove[startIndex].getName() })); if (startIndex == toRemove.length - 1) { mb.setButtons(0, new String[] { MessageText.getString("Button.yes"), MessageText.getString("Button.no"), }, new Integer[] { 0, 1 }); } else { mb.setButtons(1, new String[] { MessageText.getString("Button.removeAll"), MessageText.getString("Button.yes"), MessageText.getString("Button.no"), }, new Integer[] { 2, 0, 1 }); } mb.open(new UserPrompterResultListener() { public void prompterClosed(int result) { if (result == 0) { toRemove[startIndex].remove(); } else if (result == 2) { for (int i = startIndex; i < toRemove.length; i++) { if (toRemove[i] != null) { toRemove[i].remove(); } } return; } int nextIndex = startIndex + 1; if (nextIndex < toRemove.length) { removeSubs(toRemove, nextIndex); } } }); } public void updateUI() { // TODO Auto-generated method stub } public void dataSourceChanged(Object newDataSource) { // TODO Auto-generated method stub } public void delete() { view.delete(); if (viewComposite != null && !viewComposite.isDisposed()) { viewComposite.dispose(); } if(textFont1 != null && ! textFont1.isDisposed()) { textFont1.dispose(); } if(textFont2 != null && ! textFont2.isDisposed()) { textFont2.dispose(); } } public void generateDiagnostics(IndentWriter writer) { view.generate(writer); } public Composite getComposite() { return viewComposite; } public String getData() { return "subscriptions.view.title"; } public String getFullTitle() { return MessageText.getString("subscriptions.view.title"); } public String getShortTitle() { return MessageText.getString("subscriptions.view.title"); } public void initialize(Composite parent) { viewComposite = new Composite(parent,SWT.NONE); viewComposite.setLayout(new FormLayout()); TableColumnCore[] columns = new TableColumnCore[] { new ColumnSubscriptionNew(TABLE_ID), new ColumnSubscriptionName(TABLE_ID), new ColumnSubscriptionNbNewResults(TABLE_ID), new ColumnSubscriptionNbResults(TABLE_ID), new ColumnSubscriptionLastChecked(TABLE_ID), new ColumnSubscriptionSubscribers(TABLE_ID), new ColumnSubscriptionAutoDownload(TABLE_ID), new ColumnSubscriptionCategory(TABLE_ID), }; view = new TableViewSWTImpl(Subscription.class, TABLE_ID, TABLE_ID, columns, "name", SWT.SINGLE | SWT.FULL_SELECTION | SWT.VIRTUAL); view.addLifeCycleListener(new TableLifeCycleListener() { public void tableViewInitialized() { SubscriptionManagerFactory.getSingleton().addListener( SubscriptionsView.this ); view.addDataSources(SubscriptionManagerFactory.getSingleton().getSubscriptions( true )); } public void tableViewDestroyed() { SubscriptionManagerFactory.getSingleton().removeListener( SubscriptionsView.this ); } }); view.addSelectionListener(new TableSelectionAdapter() { public void defaultSelected(TableRowCore[] rows, int stateMask) { if(rows.length == 1) { TableRowCore row = rows[0]; Subscription sub = (Subscription) row.getDataSource(); if(sub != null) { sideBarItem item = (sideBarItem) sub.getUserData(SubscriptionManagerUI.SUB_IVIEW_KEY); item.activate(); } } } public void selected(TableRowCore[] rows) { ISelectedContent[] sels = new ISelectedContent[rows.length]; for (int i=0;i 0; } catch (Exception e) {} saveButton.setEnabled(valid_url); } }); Label rssBackground = new Label(composite,SWT.NONE); imageLoader.setLabelImage(rssBackground, "rss_bg"); int width = rssBackground.getImage().getBounds().width; Label subTitle2 = new Label(composite,SWT.WRAP); //subTitle2.setFont(subTitleFont); subTitle2.setText(MessageText.getString("Wizard.Subscription.rss.subtitle2")); Label rssBullet = new Label(composite, SWT.NONE); imageLoader.setLabelImage(rssBullet, "rss"); Label subTitle3 = new Label(composite,SWT.WRAP); subTitle3.setFont(subTitleFont); subTitle3.setText(MessageText.getString("Wizard.Subscription.rss.subtitle3")); FormLayout layout = new FormLayout(); layout.marginWidth = 50; layout.marginTop = 25; composite.setLayout(layout); FormData data; data = new FormData(); data.top = new FormAttachment(0); data.left = new FormAttachment(0); data.right = new FormAttachment(100); subTitle1.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(subTitle1,5); data.left = new FormAttachment(50,-width/2); rssBackground.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(rssBackground,7,SWT.TOP); data.left = new FormAttachment(rssBackground, 45,SWT.LEFT); data.right = new FormAttachment(rssBackground, -8,SWT.RIGHT); feedUrl.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(rssBackground,15); data.left = new FormAttachment(0); rssBullet.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(rssBullet,-3,SWT.TOP); data.left = new FormAttachment(rssBullet,5); data.right = new FormAttachment(100); subTitle2.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(subTitle2,20); data.left = new FormAttachment(0); data.right = new FormAttachment(100); subTitle3.setLayoutData(data); return composite; } private Composite createCreateSearchComposite(Composite parent) { Composite composite = new Composite(parent,SWT.NONE); Label subTitle1 = new Label(composite,SWT.WRAP); subTitle1.setFont(subTitleFont); subTitle1.setText(MessageText.getString("Wizard.Subscription.search.subtitle1")); searchInput = new Text(composite, SWT.SINGLE); searchInput.setFont(textInputFont); // searchInput.setText(MessageText.getString("Wizard.Subscription.search.inputPrompt")); // searchInput.setData("visited",new Boolean(false)); // // searchInput.addListener(SWT.FocusIn, new Listener() { // public void handleEvent(Event arg0) { // boolean visited = ((Boolean) searchInput.getData("visited")).booleanValue(); // if(visited) return; // searchInput.setData("visited",new Boolean(true)); // searchInput.setText(""); // } // }); searchInput.addListener (SWT.DefaultSelection, searchListener); Label searchBackground = new Label(composite,SWT.NONE); imageLoader.setLabelImage(searchBackground, "search_bg"); int width = searchBackground.getImage().getBounds().width; Label subTitle2 = new Label(composite,SWT.WRAP); subTitle2.setFont(subTitleFont); subTitle2.setText(MessageText.getString("Wizard.Subscription.search.subtitle2")); Label checkBullet1 = new Label(composite, SWT.NONE); imageLoader.setLabelImage(checkBullet1, "icon_check"); Label checkBullet2 = new Label(composite, SWT.NONE); imageLoader.setLabelImage(checkBullet2, "icon_check"); Label description1 = new Label(composite,SWT.NONE); description1.setText(MessageText.getString("Wizard.Subscription.search.subtitle2.sub1")); Label description2 = new Label(composite,SWT.NONE); description2.setText(MessageText.getString("Wizard.Subscription.search.subtitle2.sub2")); Label subTitle3 = new Label(composite,SWT.WRAP); subTitle3.setFont(subTitleFont); subTitle3.setText(MessageText.getString("Wizard.Subscription.search.subtitle3")); FormLayout layout = new FormLayout(); layout.marginLeft = 50; layout.marginRight = 50; layout.marginTop = 25; //layout.spacing = 10; composite.setLayout(layout); FormData data; data = new FormData(); data.top = new FormAttachment(0); data.left = new FormAttachment(0); data.right = new FormAttachment(100); subTitle1.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(subTitle1,5); data.left = new FormAttachment(50,-width/2); searchBackground.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(searchBackground,7,SWT.TOP); data.left = new FormAttachment(searchBackground, 45,SWT.LEFT); data.right = new FormAttachment(searchBackground, -8,SWT.RIGHT); searchInput.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(searchBackground,15); data.left = new FormAttachment(0); data.right = new FormAttachment(100); subTitle2.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(subTitle2,5); data.left = new FormAttachment(0); checkBullet1.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(checkBullet1,5); data.left = new FormAttachment(0); checkBullet2.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(checkBullet1, 0, SWT.TOP); data.left = new FormAttachment(checkBullet1, 5); description1.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(checkBullet2, 0, SWT.TOP); data.left = new FormAttachment(checkBullet2, 5); description2.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(checkBullet2,15); data.left = new FormAttachment(0); data.right = new FormAttachment(100); subTitle3.setLayoutData(data); return composite; } private Composite createAvailableSubscriptionComposite(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); Label hsep1 = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL); Label hsep2 = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL); Label vsep = new Label(composite, SWT.SEPARATOR | SWT.VERTICAL); Label subtitle1 = new Label(composite, SWT.NONE); Label subtitle2 = new Label(composite, SWT.NONE); subtitle1.setFont(subTitleFont); subtitle2.setFont(subTitleFont); subtitle1.setText(MessageText.getString("Wizard.Subscription.subscribe.library")); subtitle2.setText(MessageText.getString("Wizard.Subscription.subscribe.subscriptions")); libraryTable = new Table(composite, SWT.FULL_SELECTION | SWT.VIRTUAL | SWT.V_SCROLL | SWT.SINGLE); final TableColumn torrentColumn = new TableColumn(libraryTable, SWT.NONE); torrentColumn.setWidth(50); final Composite compEmpty = new Composite(composite,SWT.NONE); compEmpty.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); compEmpty.setBackgroundMode(SWT.INHERIT_DEFAULT); FillLayout fl = new FillLayout(); fl.marginHeight = 15; fl.marginWidth = 15; compEmpty.setLayout(fl); compEmpty.setVisible(false); final Link labelEmpty = new Link(compEmpty,SWT.WRAP); labelEmpty.setText(MessageText.getString("Wizard.Subscription.subscribe.library.empty")); labelEmpty.setFont(subTitleFont); labelEmpty.setForeground(ColorCache.getColor(composite.getDisplay(), "#6D6F6E")); labelEmpty.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { if(event.text != null && (event.text.startsWith("http://") || event.text.startsWith("https://") ) ) { Utils.launch(event.text); } } }); final Table subscriptionTable = new Table(composite, SWT.FULL_SELECTION | SWT.VIRTUAL | SWT.V_SCROLL | SWT.SINGLE); final TableColumn nameColumn = new TableColumn(subscriptionTable, SWT.NONE); final TableColumn rankColumn = new TableColumn(subscriptionTable, SWT.NONE); //nameColumn.setText("name"); //rankColumn.setText("rank"); // subscriptionTable.setHeaderVisible(true); Listener resizeListener = new Listener() { int last_width; public void handleEvent(Event event) { Table table = (Table)event.widget ; Rectangle rect = table.getClientArea(); int width = rect.width - 3; if ( width == last_width ){ return; } last_width = width; int nbColumns = table.getColumnCount(); if(nbColumns == 1) { table.getColumns()[0].setWidth(width); } else { if(width > 100 + RANK_COLUMN_WIDTH) { table.getColumns()[1].setWidth(RANK_COLUMN_WIDTH); table.getColumns()[0].setWidth(width-RANK_COLUMN_WIDTH); } else { table.getColumns()[0].setWidth(100); table.getColumns()[1].setWidth(width-RANK_COLUMN_WIDTH); } } ((Table)event.widget).update(); } }; subscriptionTable.addListener(SWT.Resize , resizeListener); libraryTable.addListener(SWT.Resize , resizeListener); final Listener subscriptionSelectionListener = new Listener() { public void handleEvent(Event event) { if(subscriptionTable.getSelectionCount() == 1) { addButton.setEnabled(true); // TableItem item = subscriptionTable.getSelection()[0]; Subscription subscription = subscriptions[subscriptionTable.getSelectionIndex()]; if(subscription.isSubscribed()) { addButton.setEnabled(false); } else { addButton.setEnabled(true); } addButton.setData("subscription",subscription); } else { addButton.setEnabled(false); } } }; final Listener selectionListener = new Listener() { public void handleEvent(Event event) { TableItem item = (TableItem) event.item; subscriptions = (Subscription[]) item.getData("subscriptions"); if(subscriptions != null) { Arrays.sort(subscriptions,new Comparator() { public int compare(Object o1, Object o2) { if(! (o1 instanceof Subscription && o2 instanceof Subscription)) return 0; Subscription sub1 = (Subscription) o1; Subscription sub2 = (Subscription) o2; return (int) (sub2.getCachedPopularity() - sub1.getCachedPopularity()); } }); subscriptionTable.setItemCount(subscriptions.length); } addButton.setEnabled(false); addButton.setData("subscription",null); subscriptionTable.clearAll(); subscriptionTable.deselectAll(); if(subscriptionTable.getItemCount() > 0) { subscriptionTable.setSelection(0); subscriptionSelectionListener.handleEvent(null); } //subscriptionTable.setFocus(); } }; libraryTable.addListener(SWT.Selection, selectionListener); if(availableSubscriptions != null) { libraryTable.addListener(SWT.SetData, new Listener() { public void handleEvent(Event event) { TableItem item = (TableItem) event.item; int index = libraryTable.indexOf (item); SubscriptionDownloadDetails subInfo = availableSubscriptions[index]; item.setText (subInfo.getDownload().getDisplayName()); item.setData("subscriptions",subInfo.getSubscriptions()); boolean isSubscribed = false; Subscription[] subs = subInfo.getSubscriptions(); for(int i = 0 ; i < subs.length ; i++) { if(subs[i].isSubscribed()) isSubscribed = true; } if(isSubscribed) { item.setForeground(display.getSystemColor(SWT.COLOR_GRAY)); } if(subInfo.getDownload() == download) { libraryTable.setSelection(item); selectionListener.handleEvent(event); } if(index == 0 && download == null) { libraryTable.setSelection(item); selectionListener.handleEvent(event); } if(libraryTable.getSelectionIndex() == index) { //If the item was already selected and we got the SetData afterwards, then let's populate the //subscriptionsTable selectionListener.handleEvent(event); } } }); libraryTable.setItemCount(availableSubscriptions.length); if(availableSubscriptions.length == 0) { libraryTable.setVisible(false); compEmpty.setVisible(true); } } else { //Test code libraryTable.addListener(SWT.SetData, new Listener() { public void handleEvent(Event event) { TableItem item = (TableItem) event.item; int index = libraryTable.indexOf (item); item.setText ("test " + index); } }); libraryTable.setItemCount(20); } addButton.setEnabled(false); addButton.setData("subscription",null); subscriptionTable.addListener(SWT.Selection,subscriptionSelectionListener ); final Image rssIcon = imageLoader.getImage("icon_rss"); if(availableSubscriptions != null) { subscriptionTable.addListener(SWT.SetData, new Listener() { public void handleEvent(Event event) { final TableItem item = (TableItem) event.item; int index = subscriptionTable.indexOf (item); Subscription subscription = subscriptions[index]; item.setImage(rssIcon); item.setText(0, subscription.getName()); item.setData("tooltip", subscription.getNameEx()); item.setData("popularity", new Long(subscription.getCachedPopularity())); if(subscription.isSubscribed()) { item.setForeground(display.getSystemColor(SWT.COLOR_GRAY)); subscriptionTable.setSelection(item); } } }); } else { //Test code subscriptionTable.addListener(SWT.SetData, new Listener() { public void handleEvent(Event event) { TableItem item = (TableItem) event.item; int index = subscriptionTable.indexOf (item); item.setImage( rssIcon); item.setText (0,"sub test " + index); item.setData("popularity", new Long((int)(700*Math.random() - 100 ))); //item.setText (1,"" + index); //item.setImage(1, rssIcon); } }); } Listener paintListener = new Listener() { public void handleEvent(Event event) { GC gc = event.gc; TableItem item = (TableItem) event.item; switch (event.type) { case SWT.MeasureItem: event.height = 20; break; case SWT.EraseItem: Rectangle bounds = item.getBounds(1); gc.setBackground(item.getBackground(1)); gc.setForeground(item.getBackground(1)); gc.fillRectangle(bounds); break; case SWT.PaintItem : bounds = item.getBounds(1); bounds.width -= 3; bounds.height -= 7; bounds.x += 1; bounds.y += 3; gc.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); gc.fillRectangle(bounds); gc.setForeground(rankingBorderColor); gc.drawRectangle(bounds); bounds.width -= 2; bounds.height -= 2; bounds.x += 1; bounds.y += 1; Long pop = (Long) item.getData("popularity"); if(pop != null) { long popularity = pop.longValue(); //Rank in pixels between 0 and 80 //0 -> no subscriber //80 -> 1000 subscribers int rank = 80 * (int) popularity / 1000; if(rank > 80) rank = 80; if(rank < 5) rank = 5; Rectangle clipping = gc.getClipping(); bounds.width = rank; bounds.height -= 1; bounds.x += 1; bounds.y += 1; gc.setClipping(bounds); gc.drawImage(rankingBars, bounds.x, bounds.y); gc.setClipping(clipping); } break; default: break; } } }; // use this as native one end up with progress image overwriting tooltip new CustomTableTooltipHandler( subscriptionTable ); subscriptionTable.addListener(SWT.EraseItem, paintListener); subscriptionTable.addListener(SWT.PaintItem, paintListener); subscriptionTable.addListener(SWT.MeasureItem, paintListener); libraryTable.addListener(SWT.MeasureItem, paintListener); FormLayout layout = new FormLayout(); composite.setLayout(layout); FormData data; data = new FormData(); data.top = new FormAttachment(0, 0); data.left = new FormAttachment(40, 0); data.bottom = new FormAttachment(100, 0); vsep.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(0, 5); data.right = new FormAttachment(vsep, 0); data.left = new FormAttachment(0, 5); subtitle1.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(0, 5); data.left = new FormAttachment(vsep, 5); data.right = new FormAttachment(100, 0); subtitle2.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(subtitle1, 5); data.right = new FormAttachment(vsep, 0); data.left = new FormAttachment(0, 0); hsep1.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(subtitle2, 5); data.left = new FormAttachment(vsep, -1); data.right = new FormAttachment(100, 0); hsep2.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(hsep1, 0); data.right = new FormAttachment(vsep, 0); data.left = new FormAttachment(0, 0); data.bottom = new FormAttachment(100, 0); if(availableSubscriptions != null && availableSubscriptions.length > 0) { libraryTable.setLayoutData(data); } else { // hack: dispose libraryTable as it's not needed and draws over controls // (makes a white box covering text). Would be smarter to not // create the libraryTable at all.. libraryTable.dispose(); cancelButton.setFocus(); shell.setDefaultButton(cancelButton); compEmpty.setLayoutData(data); } data = new FormData(); data.top = new FormAttachment(hsep2, 0); data.left = new FormAttachment(vsep, 0); data.right = new FormAttachment(100, 0); data.bottom = new FormAttachment(100, 0); subscriptionTable.setLayoutData(data); return composite; } private void createFonts() { FontData[] fDatas = shell.getFont().getFontData(); for(int i = 0 ; i < fDatas.length ; i++) { fDatas[i].setStyle(SWT.BOLD); } boldFont = new Font(display,fDatas); for(int i = 0 ; i < fDatas.length ; i++) { if(org.gudy.azureus2.core3.util.Constants.isOSX) { fDatas[i].setHeight(12); } else { fDatas[i].setHeight(10); } } subTitleFont = new Font(display,fDatas); for(int i = 0 ; i < fDatas.length ; i++) { if(org.gudy.azureus2.core3.util.Constants.isOSX) { fDatas[i].setHeight(17); } else { fDatas[i].setHeight(14); } } titleFont = new Font(display,fDatas); for(int i = 0 ; i < fDatas.length ; i++) { if(org.gudy.azureus2.core3.util.Constants.isOSX) { fDatas[i].setHeight(14); } else { fDatas[i].setHeight(12); } fDatas[i].setStyle(SWT.NONE); } textInputFont = new Font(display,fDatas); } private void populateFooter(Composite footer) { yesButton = new Button(footer, SWT.PUSH); yesButton.setText(MessageText.getString("Button.yes")); yesButton.setFont(boldFont); addButton = new Button(footer, SWT.PUSH); addButton.setText(MessageText.getString("Button.add")); addButton.setFont(boldFont); saveButton = new Button(footer, SWT.PUSH); saveButton.setText(MessageText.getString("Button.save")); saveButton.setEnabled(false); saveButton.setFont(boldFont); searchButton = new Button(footer, SWT.PUSH); searchButton.setText(MessageText.getString("Button.search")); searchButton.setFont(boldFont); cancelButton = new Button(footer,SWT.PUSH); //cancelButton.setText(MessageText.getString("Button.cancel")); createButton = new Button(footer,SWT.PUSH); createButton.setText(MessageText.getString("Button.createNewSubscription")); availableButton = new Button(footer,SWT.PUSH); availableButton.setText(MessageText.getString("Button.availableSubscriptions")); FormLayout layout = new FormLayout(); layout.marginHeight = 5; layout.marginWidth = 5; layout.spacing = 5; footer.setLayout(layout); FormData data; data = new FormData(); data.right = new FormAttachment(100); data.width = 100; yesButton.setLayoutData(data); addButton.setLayoutData(data); searchButton.setLayoutData(data); data = new FormData(); data.right = new FormAttachment(100); data.width = 100; saveButton.setLayoutData(data); data = new FormData(); data.right = new FormAttachment(saveButton); data.width = 100; cancelButton.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0); data.width = 175; createButton.setLayoutData(data); availableButton.setLayoutData(data); yesButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { COConfigurationManager.setParameter("subscriptions.opted_in",true); COConfigurationManager.save(); setMode(MODE_SUBSCRIBE); } }); createButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { setMode(MODE_CREATE_SEARCH); } }); availableButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { setDefaultAvailableMode(); } }); cancelButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { shell.close(); } }); rssSaveListener = new Listener() { public void handleEvent(Event event) { try { String url_str = feedUrl.getText(); URL url = new URL(url_str); Map user_data = new HashMap(); user_data.put( SubscriptionManagerUI.SUB_EDIT_MODE_KEY, new Boolean( true )); SubscriptionManagerFactory.getSingleton().createRSS( url_str, url, SubscriptionHistory.DEFAULT_CHECK_INTERVAL_MINS, user_data ); shell.close(); } catch (Throwable e) { Utils.reportError( e ); } } }; saveButton.addListener(SWT.Selection, rssSaveListener); addButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { Subscription subscription = (Subscription) addButton.getData("subscription"); if(subscription != null) { subscription.setSubscribed(true); shell.close(); } } }); searchListener = new Listener() { public void handleEvent(Event event) { MainWindow.doSearch(searchInput.getText(),true); shell.close(); } }; searchButton.addListener(SWT.Selection, searchListener); } private void setDefaultAvailableMode() { boolean opted_in = COConfigurationManager.getBooleanParameter("subscriptions.opted_in"); if(!opted_in) { setMode(MODE_OPT_IN); } else { setMode(MODE_SUBSCRIBE); } } private void setMode(int mode) { addButton.setVisible(false); searchButton.setVisible(false); saveButton.setVisible(false); yesButton.setVisible(false); createButton.setVisible(false); availableButton.setVisible(false); cancelButton.setText(MessageText.getString("Button.cancel")); String titleText = TITLE_OPT_IN; switch (mode) { case MODE_SUBSCRIBE : mainLayout.topControl = availableSubscriptionComposite; titleText = TITLE_SUBSCRIBE; createButton.setVisible(true); addButton.setVisible(true); shell.setDefaultButton(addButton); break; case MODE_CREATE_RSS : mainLayout.topControl = createComposite; createTabFolder.setSelection(createRSSTabItem); titleText = TITLE_CREATE; availableButton.setVisible(true); saveButton.setVisible(true); shell.setDefaultButton(saveButton); break; case MODE_CREATE_SEARCH : mainLayout.topControl = createComposite; createTabFolder.setSelection(createSearchTabItem); titleText = TITLE_CREATE; availableButton.setVisible(true); searchButton.setVisible(true); shell.setDefaultButton(searchButton); break; case MODE_OPT_IN: default: mainLayout.topControl = optinComposite; cancelButton.setText(MessageText.getString("Button.no")); createButton.setVisible(true); yesButton.setVisible(true); shell.setDefaultButton(yesButton); break; } main.layout(true,true); title.setText(titleText); } public static void main(String args[]) { final SubscriptionWizard sw = new SubscriptionWizard(); while( ! sw.shell.isDisposed()) { if(! sw.display.readAndDispatch()) { sw.display.sleep(); } } sw.display.dispose(); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionManagerUI.java0000644000175000017500000020477211274201120027767 0ustar adrianadrian/* * Created on Jul 29, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.ui.swt.subscriptions; import java.io.File; import java.text.SimpleDateFormat; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.ProgressEvent; import org.eclipse.swt.browser.ProgressListener; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.category.Category; import org.gudy.azureus2.core3.category.CategoryManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginConfigListener; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.ui.*; import org.gudy.azureus2.plugins.ui.config.BooleanParameter; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.plugins.ui.config.HyperlinkParameter; import org.gudy.azureus2.plugins.ui.config.IntParameter; import org.gudy.azureus2.plugins.ui.config.Parameter; import org.gudy.azureus2.plugins.ui.config.ParameterListener; import org.gudy.azureus2.plugins.ui.menus.*; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.plugins.ui.sidebar.SideBarEntry; import org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage; import org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImageListener; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.plugins.utils.Utilities; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.CategoryAdderWindow; import org.gudy.azureus2.ui.swt.PropertiesWindow; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.plugins.UISWTInputReceiver; import org.gudy.azureus2.ui.swt.plugins.UISWTInstance; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.views.AbstractIView; import org.gudy.azureus2.ui.swt.views.IView; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.core.messenger.ClientMessageContext; import com.aelitis.azureus.core.metasearch.Engine; import com.aelitis.azureus.core.metasearch.impl.web.WebEngine; import com.aelitis.azureus.core.subs.*; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.UserPrompterResultListener; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.swt.browser.BrowserContext; import com.aelitis.azureus.ui.swt.browser.CookiesListener; import com.aelitis.azureus.ui.swt.browser.OpenCloseSearchDetailsListener; import com.aelitis.azureus.ui.swt.browser.listener.*; import com.aelitis.azureus.ui.swt.toolbar.ToolBarEnabler; import com.aelitis.azureus.ui.swt.views.skin.SkinView; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager.SkinViewManagerListener; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarListener; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.MapUtils; import com.aelitis.azureus.util.UrlFilter; public class SubscriptionManagerUI { public static final Object SUB_IVIEW_KEY = new Object(); public static final Object SUB_EDIT_MODE_KEY = new Object(); public static final String ALERT_IMAGE_ID = "image.sidebar.vitality.alert"; public static final String AUTH_IMAGE_ID = "image.sidebar.vitality.auth"; private static final String EDIT_MODE_MARKER = "&editMode=1"; private Graphic icon_rss_big; private Graphic icon_rss_small; private Graphic icon_rss_all_add_small; private Graphic icon_rss_all_add_big; private Graphic icon_rss_some_add_small; private Graphic icon_rss_some_add_big; private List icon_list = new ArrayList(); private SubscriptionManager subs_man; private MenuItemListener markAllResultsListener; private MenuItemListener unmarkAllResultsListener; private MenuItemListener deleteAllResultsListener; private MenuItemListener resetAuthListener; private MenuItemListener setCookieListener; private MenuItemListener resetResultsListener; private MenuItemListener exportListener; private MenuItemListener renameListener; private MenuItemListener removeListener; private MenuItemListener forceCheckListener; private MenuItemListener upgradeListener; private MenuItemListener propertiesListener; private boolean side_bar_setup; private List columns = new ArrayList(); protected UISWTInstance swt; private UIManager ui_manager; private PluginInterface default_pi; public SubscriptionManagerUI() { default_pi = PluginInitializer.getDefaultInterface(); final TableManager table_manager = default_pi.getUIManager().getTableManager(); if ( Constants.isCVSVersion()){ // check assoc { final TableContextMenuItem menu_item_itorrents = table_manager.addContextMenuItem(TableManager.TABLE_MYTORRENTS_INCOMPLETE, "azsubs.contextmenu.lookupassoc"); final TableContextMenuItem menu_item_ctorrents = table_manager.addContextMenuItem(TableManager.TABLE_MYTORRENTS_COMPLETE, "azsubs.contextmenu.lookupassoc"); menu_item_itorrents.setStyle(TableContextMenuItem.STYLE_PUSH); menu_item_ctorrents.setStyle(TableContextMenuItem.STYLE_PUSH); MenuItemListener listener = new MenuItemListener() { public void selected( MenuItem menu, Object target) { TableRow[] rows = (TableRow[])target; if ( rows.length > 0 ){ Download download = (Download)rows[0].getDataSource(); new SubscriptionListWindow(PluginCoreUtils.unwrap(download), false); } /* for (int i=0;i " + subscription.getName()); } public void complete( byte[] hash, Subscription[] subscriptions ) { log( " lookup: complete " + ByteFormatter.encodeString( hash ) + " -> " +subscriptions.length ); } public void failed( byte[] hash, SubscriptionException error ) { log( " lookup: failed", error ); } }); }catch( Throwable e ){ log( "Lookup failed", e ); } } }*/ } }; menu_item_itorrents.addMultiListener( listener ); menu_item_ctorrents.addMultiListener( listener ); } // make assoc - CVS only as for testing purposes if ( false ){ final TableContextMenuItem menu_item_itorrents = table_manager.addContextMenuItem(TableManager.TABLE_MYTORRENTS_INCOMPLETE, "azsubs.contextmenu.addassoc"); final TableContextMenuItem menu_item_ctorrents = table_manager.addContextMenuItem(TableManager.TABLE_MYTORRENTS_COMPLETE, "azsubs.contextmenu.addassoc"); menu_item_itorrents.setStyle(TableContextMenuItem.STYLE_MENU); menu_item_ctorrents.setStyle(TableContextMenuItem.STYLE_MENU); MenuItemFillListener menu_fill_listener = new MenuItemFillListener() { public void menuWillBeShown( MenuItem menu, Object target ) { if ( subs_man == null ){ return; } TableRow[] rows; if ( target instanceof TableRow[] ){ rows = (TableRow[])target; }else{ rows = new TableRow[]{ (TableRow)target }; } final List hashes = new ArrayList(); for (int i=0;i 0; if ( enabled ){ Subscription[] subs = subs_man.getSubscriptions(); boolean incomplete = ((TableContextMenuItem)menu).getTableID() == TableManager.TABLE_MYTORRENTS_INCOMPLETE; TableContextMenuItem parent = incomplete?menu_item_itorrents:menu_item_ctorrents; for (int i=0;i= 22?icon_rss_all_add_big:icon_rss_all_add_small; tooltip = MessageText.getString( "subscript.all.subscribed" ); }else if ( num_subscribed > 0 ){ graphic = height >= 22?icon_rss_some_add_big:icon_rss_some_add_small; tooltip = MessageText.getString( "subscript.some.subscribed" ); sort_order = 10000; }else{ graphic = height >= 22?icon_rss_big:icon_rss_small; tooltip = MessageText.getString( "subscript.none.subscribed" ); sort_order = 1000000; } } sort_order += 1000*num_unsubscribed + num_subscribed; cell.setGraphic( graphic ); cell.setToolTip( tooltip ); cell.setSortValue( sort_order ); cell.setCursorID( graphic==null?SWT.CURSOR_ARROW:SWT.CURSOR_HAND ); }else{ cell.setCursorID( SWT.CURSOR_ARROW ); cell.setSortValue( 0 ); } } }; final TableCellMouseListener subs_mouse_listener = new TableCellMouseListener() { public void cellMouseTrigger( TableCellMouseEvent event ) { if ( event.eventType == TableCellMouseEvent.EVENT_MOUSEDOWN ){ TableCell cell = event.cell; Download dl = (Download)cell.getDataSource(); Torrent torrent = dl.getTorrent(); if ( torrent != null ){ Subscription[] subs = subs_man.getKnownSubscriptions( torrent.getHash()); if ( subs.length > 0 ){ event.skipCoreFunctionality = true; new SubscriptionWizard(PluginCoreUtils.unwrap(dl)); //new SubscriptionListWindow(PluginCoreUtils.unwrap(dl),true); } } } } }; table_manager.registerColumn( Download.class, "azsubs.ui.column.subs", new TableColumnCreationListener() { public void tableColumnCreated(TableColumn result) { result.setAlignment(TableColumn.ALIGN_CENTER); result.setPosition(TableColumn.POSITION_LAST); result.setWidth(72); result.setRefreshInterval(TableColumn.INTERVAL_INVALID_ONLY); result.setType(TableColumn.TYPE_GRAPHIC); result.addCellRefreshListener( subs_refresh_listener ); result.addCellMouseListener( subs_mouse_listener ); columns.add(result); } }); final TableCellRefreshListener link_refresh_listener = new TableCellRefreshListener() { public void refresh( TableCell _cell ) { TableCellSWT cell = (TableCellSWT)_cell; if ( subs_man == null ){ return; } Download dl = (Download)cell.getDataSource(); if ( dl == null ){ return; } String str = ""; Torrent torrent = dl.getTorrent(); if ( torrent != null ){ byte[] hash = torrent.getHash(); Subscription[] subs = subs_man.getKnownSubscriptions( hash ); for (int i=0;i 0?SWT.CURSOR_HAND:SWT.CURSOR_ARROW ); cell.setText( str ); } }; final TableCellMouseListener link_mouse_listener = new TableCellMouseListener() { public void cellMouseTrigger( TableCellMouseEvent event ) { if ( event.eventType == TableCellMouseEvent.EVENT_MOUSEDOWN ){ TableCell cell = event.cell; Download dl = (Download)cell.getDataSource(); Torrent torrent = dl.getTorrent(); if ( torrent != null ){ byte[] hash = torrent.getHash(); Subscription[] subs = subs_man.getKnownSubscriptions( hash ); for (int i=0;i= 3 || auth_fail ){ warn = true; } } } warnSub.setVisible( warn ); if ( total > 0 ){ return( String.valueOf( total )); } } } return null; } }); String parentID = "sidebar." + SideBar.SIDEBAR_SECTION_SUBSCRIPTIONS; MenuManager menu_manager = ui_manager.getMenuManager(); MenuItem mi = menu_manager.addMenuItem( parentID, "ConfigView.title.short" ); mi.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { UIFunctions uif = UIFunctionsManager.getUIFunctions(); if ( uif != null ){ uif.openView( UIFunctions.VIEW_CONFIG, "Subscriptions" ); } } }); if (!mainSBEntry.isInTree()) { side_bar.createTreeItemFromIViewClass(null, SideBar.SIDEBAR_SECTION_SUBSCRIPTIONS, MessageText.getString("subscriptions.view.title"), SubscriptionsView.class, null, null, null, null, false); } } markAllResultsListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; Subscription subs = (Subscription) info.getDatasource(); subs.getHistory().markAllResultsRead(); refreshView( subs ); } } }; unmarkAllResultsListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; Subscription subs = (Subscription) info.getDatasource(); subs.getHistory().markAllResultsUnread(); refreshView( subs ); } } }; deleteAllResultsListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; Subscription subs = (Subscription) info.getDatasource(); subs.getHistory().deleteAllResults(); refreshView( subs ); } } }; resetAuthListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; Subscription subs = (Subscription) info.getDatasource(); try{ Engine engine = subs.getEngine(); if ( engine instanceof WebEngine ){ ((WebEngine)engine).setCookies( null ); } }catch( Throwable e ){ Debug.printStackTrace(e); } try{ subs.getManager().getScheduler().downloadAsync(subs, true); }catch( Throwable e ){ Debug.out(e); } } } }; setCookieListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; final Subscription subs = (Subscription) info.getDatasource(); try{ Engine engine = subs.getEngine(); if ( engine instanceof WebEngine ){ final WebEngine we = (WebEngine)engine; UISWTInputReceiver entry = (UISWTInputReceiver)swt_ui.getInputReceiver(); String[] req = we.getRequiredCookies(); String req_str = ""; for ( String r:req ){ req_str += (req_str.length()==0?"":";") + r + "=?"; } entry.setPreenteredText( req_str, true ); entry.maintainWhitespace(false); entry.allowEmptyInput( false ); entry.setTitle("general.enter.cookies"); entry.prompt(new UIInputReceiverListener() { public void UIInputReceiverClosed(UIInputReceiver entry) { if (!entry.hasSubmittedInput()){ return; } try { String input = entry.getSubmittedInput().trim(); if ( input.length() > 0 ){ we.setCookies( input ); subs.getManager().getScheduler().downloadAsync(subs, true); } }catch( Throwable e ){ Debug.printStackTrace(e); } } }); } }catch( Throwable e ){ Debug.printStackTrace(e); } } } }; resetResultsListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; Subscription subs = (Subscription) info.getDatasource(); subs.getHistory().reset(); try{ subs.getEngine().reset(); }catch( Throwable e ){ Debug.printStackTrace(e); } try{ subs.getManager().getScheduler().downloadAsync(subs, true); }catch( Throwable e ){ Debug.out(e); } } } }; exportListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; final Subscription subs = (Subscription) info.getDatasource(); final Shell shell = Utils.findAnyShell(); shell.getDisplay().asyncExec( new AERunnable() { public void runSupport() { FileDialog dialog = new FileDialog( shell, SWT.SYSTEM_MODAL | SWT.SAVE ); dialog.setFilterPath( TorrentOpener.getFilterPathData() ); dialog.setText(MessageText.getString("subscript.export.select.template.file")); dialog.setFilterExtensions(new String[] { "*.vuze", "*.vuz", Constants.FILE_WILDCARD }); dialog.setFilterNames(new String[] { "*.vuze", "*.vuz", Constants.FILE_WILDCARD }); String path = TorrentOpener.setFilterPathData( dialog.open()); if ( path != null ){ String lc = path.toLowerCase(); if ( !lc.endsWith( ".vuze" ) && !lc.endsWith( ".vuz" )){ path += ".vuze"; } try{ VuzeFile vf = subs.getVuzeFile(); vf.write( new File( path )); }catch( Throwable e ){ Debug.out( e ); } } } }); } } }; renameListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; final Subscription subs = (Subscription) info.getDatasource(); UISWTInputReceiver entry = (UISWTInputReceiver)swt_ui.getInputReceiver(); entry.setPreenteredText(subs.getName(), false ); entry.maintainWhitespace(false); entry.allowEmptyInput( false ); entry.setLocalisedTitle(MessageText.getString("label.rename", new String[] { subs.getName() })); entry.prompt(new UIInputReceiverListener() { public void UIInputReceiverClosed(UIInputReceiver entry) { if (!entry.hasSubmittedInput()){ return; } String input = entry.getSubmittedInput().trim(); if ( input.length() > 0 ){ try{ subs.setName( input ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } }); } } }; removeListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; Subscription subs = (Subscription) info.getDatasource(); removeWithConfirm( subs ); } } }; forceCheckListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; Subscription subs = (Subscription) info.getDatasource(); try{ subs.getManager().getScheduler().downloadAsync( subs, true ); }catch( Throwable e ){ Debug.out( e ); } } } }; upgradeListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; Subscription subs = (Subscription) info.getDatasource(); subs.resetHighestVersion(); } } }; propertiesListener = new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; Subscription subs = (Subscription) info.getDatasource(); showProperties( subs ); } } }; subs_man.addListener( new SubscriptionManagerListener() { public void subscriptionAdded( Subscription subscription ) { addSubscription( side_bar, subscription, true ); } public void subscriptionChanged( Subscription subscription ) { changeSubscription( side_bar, subscription ); } public void subscriptionSelected( Subscription subscription ) { sideBarItem item = (sideBarItem)subscription.getUserData(SubscriptionManagerUI.SUB_IVIEW_KEY); if (item != null ){ item.activate(); } } public void subscriptionRemoved( Subscription subscription ) { removeSubscription( side_bar, subscription ); } public void associationsChanged( byte[] association_hash ) { } }); Subscription[] subs = subs_man.getSubscriptions(); Arrays.sort( subs, new Comparator() { public int compare( Subscription o1, Subscription o2 ) { return( o1.getName().compareToIgnoreCase( o2.getName())); } }); for (int i=0;i 1000 ){ ((subscriptionView)view).updateBrowser( false ); } }finally{ last_select = SystemTime.getMonotonousTime(); } } } } }); } protected void changeSubscription( SideBar side_bar, final Subscription subs ) { if ( subs.isSubscribed()){ addSubscription( side_bar, subs, false ); }else{ removeSubscription( side_bar, subs); } } protected void addSubscription( final SideBar side_bar, final Subscription subs, final boolean show ) { if ( !subs.isSubscribed()){ return; } refreshColumns(); synchronized( this ){ final sideBarItem existing_si = (sideBarItem)subs.getUserData( SUB_IVIEW_KEY ); if ( existing_si == null ){ final sideBarItem new_si = new sideBarItem(); subs.setUserData( SUB_IVIEW_KEY, new_si ); // GetEngine used to be near menu item created, but was moved here // since it takes time on first start and we don't want it stalling // the UI Thread Engine e = null; try{ e = subs.getEngine(); }catch( Throwable ex ){ Debug.printStackTrace(ex); } final Engine engine = e; Utils.execSWTThread( new Runnable() { public void run() { synchronized( SubscriptionManagerUI.this ){ if ( new_si.isDestroyed()){ return; } subscriptionView view = new subscriptionView( subs ); new_si.setView( view ); String key = "Subscription_" + ByteFormatter.encodeString(subs.getPublicKey()); TreeItem tree_item = side_bar.createTreeItemFromIView( SideBar.SIDEBAR_SECTION_SUBSCRIPTIONS, view, key, subs, false, show, false ); SideBarEntrySWT entry = SideBar.getEntry( key ); new_si.setTreeItem( tree_item, entry ); setStatus( subs, new_si ); PluginInterface pi = PluginInitializer.getDefaultInterface(); UIManager uim = pi.getUIManager(); final MenuManager menuManager = uim.getMenuManager(); MenuItem menuItem; menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.forcecheck"); menuItem.setText(MessageText.getString("Subscription.menu.forcecheck")); menuItem.addListener(forceCheckListener); menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.clearall"); menuItem.addListener(markAllResultsListener); menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.dirtyall"); menuItem.addListener(unmarkAllResultsListener); menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.deleteall"); menuItem.addListener(deleteAllResultsListener); menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.reset"); menuItem.addListener(resetResultsListener); try{ if ( engine instanceof WebEngine ){ if (((WebEngine)engine).isNeedsAuth()){ menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.resetauth"); menuItem.addListener(resetAuthListener); menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.setcookies"); menuItem.addListener(setCookieListener); } } }catch( Throwable e ){ Debug.printStackTrace(e); } // sep menuManager.addMenuItem("sidebar." + key,"s1").setStyle( MenuItem.STYLE_SEPARATOR ); // category menuItem = menuManager.addMenuItem("sidebar." + key, "MyTorrentsView.menu.setCategory"); menuItem.setStyle( MenuItem.STYLE_MENU ); menuItem.addFillListener( new MenuItemFillListener() { public void menuWillBeShown( MenuItem menu, Object data ) { addCategorySubMenu( menuManager, menu, subs ); } }); if ( subs.isUpdateable()){ menuItem = menuManager.addMenuItem("sidebar." + key,"MyTorrentsView.menu.rename"); menuItem.addListener(renameListener); } menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.upgrade"); menuItem.addListener(upgradeListener); menuItem.addFillListener( new MenuItemFillListener() { public void menuWillBeShown( MenuItem menu, Object data ) { menu.setVisible( subs.getHighestVersion() > subs.getVersion()); } }); menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.export"); menuItem.addListener(exportListener); // sep menuManager.addMenuItem("sidebar." + key,"s2").setStyle( MenuItem.STYLE_SEPARATOR ); menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.remove"); menuItem.addListener(removeListener); menuManager.addMenuItem("sidebar." + key,"s3").setStyle( MenuItem.STYLE_SEPARATOR ); menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.properties"); menuItem.addListener(propertiesListener); } } }); }else{ Utils.execSWTThread( new Runnable() { public void run() { ViewTitleInfoManager.refreshTitleInfo( existing_si.getView()); SideBarEntrySWT mainSBEntry = SideBar.getEntry(SideBar.SIDEBAR_SECTION_SUBSCRIPTIONS); if ( mainSBEntry != null ){ ViewTitleInfoManager.refreshTitleInfo( mainSBEntry.getTitleInfo()); } setStatus( subs, existing_si ); } }); } } } private void addCategorySubMenu( MenuManager menu_manager, MenuItem menu, final Subscription subs ) { menu.removeAllChildItems(); Category[] categories = CategoryManager.getCategories(); Arrays.sort( categories ); MenuItem m; if ( categories.length > 0 ){ String assigned_category = subs.getCategory(); final Category uncat = CategoryManager.getCategory( Category.TYPE_UNCATEGORIZED ); if ( uncat != null ){ m = menu_manager.addMenuItem( menu, uncat.getName()); m.setStyle( MenuItem.STYLE_RADIO ); m.setData( new Boolean( assigned_category == null )); m.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { assignSelectedToCategory( uncat, subs ); } }); m = menu_manager.addMenuItem( menu, "sep1" ); m.setStyle( MenuItem.STYLE_SEPARATOR ); } for ( int i=0; i iter = columns.iterator(); iter.hasNext();){ TableColumn column = iter.next(); column.invalidateCells(); } } protected void showProperties( Subscription subs ) { SubscriptionHistory history = subs.getHistory(); SimpleDateFormat df = new SimpleDateFormat(); String last_error = history.getLastError(); if ( last_error == null ){ last_error = ""; } String engine_str; String auth_str = String.valueOf(false); try{ Engine engine = subs.getEngine(); engine_str = engine.getNameEx(); if ( engine instanceof WebEngine ){ WebEngine web_engine = (WebEngine)engine; if ( web_engine.isNeedsAuth()){ auth_str = String.valueOf(true) + ": cookies=" + toString( web_engine.getRequiredCookies()); } } }catch( Throwable e ){ engine_str = "Unknown"; auth_str = ""; } String[] keys = { "subs.prop.enabled", "subs.prop.is_public", "subs.prop.is_auto", "subs.prop.is_auto_ok", "subs.prop.update_period", "subs.prop.last_scan", "subs.prop.last_result", "subs.prop.next_scan", "subs.prop.last_error", "subs.prop.num_read", "subs.prop.num_unread", "subs.prop.assoc", "subs.prop.version", "subs.prop.high_version", "subscriptions.listwindow.popularity", "subs.prop.template", "subs.prop.auth", "TableColumn.header.category", }; String category_str; String category = subs.getCategory(); if ( category == null ){ category_str = MessageText.getString( "Categories.uncategorized" ); }else{ category_str = category; } String[] values = { String.valueOf( history.isEnabled()), String.valueOf( subs.isPublic()), String.valueOf( history.isAutoDownload()), String.valueOf( subs.isAutoDownloadSupported()), String.valueOf( history.getCheckFrequencyMins() + " " + MessageText.getString( "ConfigView.text.minutes")), df.format(new Date( history.getLastScanTime())), df.format(new Date( history.getLastNewResultTime())), df.format(new Date( history.getNextScanTime())), (last_error.length()==0?MessageText.getString("PeersView.uniquepiece.none"):last_error), String.valueOf( history.getNumRead()), String.valueOf( history.getNumUnread()), String.valueOf( subs.getAssociationCount()), String.valueOf( subs.getVersion()), subs.getHighestVersion() > subs.getVersion()?String.valueOf( subs.getHighestVersion()):null, subs.getCachedPopularity()<=1?null:String.valueOf( subs.getCachedPopularity()), engine_str, auth_str, category_str, }; new PropertiesWindow( subs.getName(), keys, values ); } private String toString( String[] strs ) { String res = ""; for(int i=0;i 1 ){ res += " (" + MessageText.getString("subscriptions.listwindow.popularity").toLowerCase() + "=" + pop + ")"; } return( res ); } case ViewTitleInfo.TITLE_INDICATOR_TEXT :{ if(subs.getHistory().getNumUnread() > 0) { return ( "" + subs.getHistory().getNumUnread()); } return null; } } return( null ); } public void initialize( Composite _parent_composite ) { parent_composite = _parent_composite; parent_composite.addListener( SWT.Show, new Listener() { public void handleEvent( Event arg0 ) { createBrowsers(); } }); parent_composite.addListener( SWT.Hide, new Listener() { public void handleEvent( Event arg0 ) { if (spinnerImage != null) { spinnerImage.setVisible(false); } destroyBrowsers(); } }); composite = new Composite( parent_composite, SWT.NULL ); composite.setLayout(new FormLayout()); //GridData grid_data = new GridData(GridData.FILL_BOTH ); //composite.setLayoutData(grid_data); //FormData data; // control area /* controls = new Composite(composite, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.marginHeight = 0; layout.marginWidth = 0; controls.setLayout(layout); data = new FormData(); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); data.top = new FormAttachment(0,0); controls.setLayoutData(data); GridData grid_data; info_lab = new Label( controls, SWT.NULL ); grid_data = new GridData(GridData.FILL_HORIZONTAL); info_lab.setLayoutData(grid_data); info_lab2 = new Label( controls, SWT.NULL ); grid_data = new GridData(GridData.FILL_HORIZONTAL); info_lab2.setLayoutData(grid_data); json_area = new StyledText(controls,SWT.BORDER); grid_data = new GridData(GridData.FILL_HORIZONTAL); grid_data.heightHint = 50; json_area.setLayoutData(grid_data); json_area.setWordWrap(true); */ subs.addListener( new SubscriptionListener() { public void subscriptionChanged( Subscription subs ) { Utils.execSWTThread( new Runnable() { public void run() { updateInfo(); } }); } public void subscriptionDownloaded( Subscription subs, boolean auto ) { if ( auto ){ updateBrowser( true ); } } }); updateInfo(); } protected void createBrowsers() { try{ mainBrowser = new Browser(composite,Utils.getInitialBrowserStyle(SWT.NONE)); mainBrowser.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { ((Browser)e.widget).setUrl("about:blank"); ((Browser)e.widget).setVisible(false); while (!e.display.isDisposed() && e.display.readAndDispatch()); } }); BrowserContext context = new BrowserContext("browser-window" + Math.random(), mainBrowser, null, true); context.addListener(new BrowserContext.loadingListener(){ public void browserLoadingChanged(boolean loading, String url) { if (spinnerImage != null) { spinnerImage.setVisible(loading); } } }); context.addMessageListener(new TorrentListener()); context.addMessageListener(new VuzeListener()); context.addMessageListener(new DisplayListener(mainBrowser)); context.addMessageListener(new ConfigListener(mainBrowser)); context.addMessageListener( new MetaSearchListener( this )); ContentNetwork contentNetwork = ContentNetworkManagerFactory.getSingleton().getContentNetwork( context.getContentNetworkID()); // contentNetwork won't be null because a new browser context // has the default content network String url = contentNetwork.getSubscriptionURL(subs.getID()); Boolean edit_mode = (Boolean)subs.getUserData( SUB_EDIT_MODE_KEY ); if ( edit_mode != null ){ if ( edit_mode.booleanValue()){ url += EDIT_MODE_MARKER; } subs.setUserData( SUB_EDIT_MODE_KEY, null ); } mainBrowser.setUrl(url); mainBrowser.setData("StartURL", url); FormData data = new FormData(); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); data.top = new FormAttachment(composite,0); data.bottom = new FormAttachment(100,0); mainBrowser.setLayoutData(data); detailsBrowser = new Browser(composite,Utils.getInitialBrowserStyle(SWT.NONE)); detailsBrowser.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { ((Browser)e.widget).setUrl("about:blank"); ((Browser)e.widget).setVisible(false); while (!e.display.isDisposed() && e.display.readAndDispatch()); } }); BrowserContext detailsContext = new BrowserContext("browser-window" + Math.random(), detailsBrowser, null, false); detailsContext.addListener(new BrowserContext.loadingListener(){ public void browserLoadingChanged(boolean loading, String url) { if (spinnerImage != null) { spinnerImage.setVisible(loading); } } }); ClientMessageContext.torrentURLHandler url_handler = new ClientMessageContext.torrentURLHandler() { public void handleTorrentURL( final String url ) { Utils.execSWTThreadWithObject( "SMUI", new AERunnableObject() { public Object runSupport() { String subscriptionId = (String)detailsBrowser.getData("subscription_id"); String subscriptionResultId = (String)detailsBrowser.getData("subscription_result_id"); if ( subscriptionId != null && subscriptionResultId != null ){ Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( subscriptionId ); if ( subs != null ){ subs.addPotentialAssociation( subscriptionResultId, url ); } } return( null ); } }, 10*1000 ); } }; detailsContext.setTorrentURLHandler( url_handler ); TorrentListener torrent_listener = new TorrentListener(); torrent_listener.setTorrentURLHandler( url_handler ); detailsContext.addMessageListener( torrent_listener ); detailsContext.addMessageListener(new VuzeListener()); detailsContext.addMessageListener(new DisplayListener(detailsBrowser)); detailsContext.addMessageListener(new ConfigListener(detailsBrowser)); url = "about:blank"; detailsBrowser.setUrl(url); detailsBrowser.setData("StartURL", url); final ExternalLoginCookieListener cookieListener = new ExternalLoginCookieListener(new CookiesListener() { public void cookiesFound(String cookies) { detailsBrowser.setData("current-cookies", cookies); } },detailsBrowser); cookieListener.hook(); data = new FormData(); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); data.top = new FormAttachment(mainBrowser,0); data.bottom = new FormAttachment(100,0); detailsBrowser.setLayoutData(data); mainBrowser.setVisible( true ); detailsBrowser.setVisible( false ); //detailsBrowser.set mainBrowser.getParent().layout(true,true); ISelectedContent[] sels = { new SubscriptionSelectedContent( new ToolBarEnabler() { public boolean isEnabled( String itemKey ) { return( "share".equals(itemKey) || "remove".equals(itemKey)); } public boolean isSelected( String itemKey ) { return( false ); } public void itemActivated( String itemKey ) { removeWithConfirm( subs ); } }, subs )}; SelectedContentManager.changeCurrentlySelectedContent("IconBarEnabler", sels ); }catch( Throwable e ){ Debug.printStackTrace(e); } } protected void destroyBrowsers() { if ( mainBrowser != null ){ mainBrowser.dispose(); mainBrowser = null; } if ( detailsBrowser != null ){ detailsBrowser.dispose(); detailsBrowser = null; } } public void closeSearchResults(final Map params) { Utils.execSWTThread(new AERunnable() { public void runSupport() { detailsBrowser.setVisible(false); FormData gd = (FormData) mainBrowser.getLayoutData(); gd.bottom = new FormAttachment(100, 0); mainBrowser.setLayoutData(gd); mainBrowser.getParent().layout(true); detailsBrowser.setUrl("about:blank"); //mainBrowser.setUrl( (String)mainBrowser.getData( "StartURL" )); } }); } public void openSearchResults(final Map params) { Utils.execSWTThread(new AERunnable() { public void runSupport() { String url = MapUtils.getMapString(params, "url", "http://google.com/search?q=" + Math.random()); if (UrlFilter.getInstance().urlCanRPC(url)) { url = ConstantsVuze.getDefaultContentNetwork().appendURLSuffix(url, false, true); } //Gudy, Not Tux, Listener Added String listenerAdded = (String) detailsBrowser.getData("g.nt.la"); if(listenerAdded == null) { detailsBrowser.setData("g.nt.la",""); detailsBrowser.addProgressListener(new ProgressListener() { public void changed(ProgressEvent event) {} public void completed(ProgressEvent event) { Browser search = (Browser) event.widget; String execAfterLoad = (String) search.getData("execAfterLoad"); //Erase it, so that it's only used once after the page loads search.setData("execAfterLoad",null); if(execAfterLoad != null && ! execAfterLoad.equals("")) { //String execAfterLoadDisplay = execAfterLoad.replaceAll("'","\\\\'"); //search.execute("alert('injecting script : " + execAfterLoadDisplay + "');"); boolean result = search.execute(execAfterLoad); //System.out.println("Injection : " + execAfterLoad + " (" + result + ")"); } } }); } //Store the "css" match string in the search cdp browser object String execAfterLoad = MapUtils.getMapString(params, "execAfterLoad", null); detailsBrowser.setData("execAfterLoad",execAfterLoad); detailsBrowser.setData("subscription_id", MapUtils.getMapString(params, "subs_id", null)); detailsBrowser.setData("subscription_result_id", MapUtils.getMapString(params, "subs_rid", null)); detailsBrowser.setUrl(url); detailsBrowser.setData("StartURL", url); detailsBrowser.setVisible(true); FormData data = (FormData) mainBrowser.getLayoutData(); data.bottom = null; data.height = MapUtils.getMapInt(params, "top-height", 120); //mainBrowser.setLayoutData(data); mainBrowser.getParent().layout(true,true); } }); } protected void updateBrowser( final boolean is_auto ) { if ( mainBrowser != null ){ Utils.execSWTThread( new Runnable() { public void run() { if ( mainBrowser != null && mainBrowser.isVisible()){ String url = (String)mainBrowser.getData( "StartURL" ); // see if end of edit process indicated by the subscription being // re-downloaded on auto-mode if ( is_auto && url.endsWith( EDIT_MODE_MARKER )){ url = url.substring(0,url.lastIndexOf( EDIT_MODE_MARKER )); mainBrowser.setData( "StartURL", url ); } mainBrowser.setUrl( url ); } } }); } } protected void updateInfo() { /* String engine_str = ""; try{ Engine engine = subs.getEngine(); engine_str = engine.getString(); }catch( Throwable e ){ engine_str = Debug.getNestedExceptionMessage(e); Debug.out(e); } info_lab.setText( "ID=" + subs.getID() + ", version=" + subs.getVersion() + ", subscribed=" + subs.isSubscribed() + ", public=" + subs.isPublic() + ", mine=" + subs.isMine() + ", popularity=" + subs.getCachedPopularity() + ", associations=" + subs.getAssociationCount() + ", engine=" + engine_str ); SubscriptionHistory history = subs.getHistory(); info_lab2.setText( "History: " + "enabled=" + history.isEnabled() + ", auto=" + history.isAutoDownload() + ", last_scan=" + new SimpleDateFormat().format(new Date( history.getLastScanTime())) + ", next_scan=" + new SimpleDateFormat().format(new Date( history.getNextScanTime())) + ", last_new=" + new SimpleDateFormat().format(new Date( history.getLastNewResultTime())) + ", read=" + history.getNumRead() + " ,unread=" + history.getNumUnread() + ", error=" + history.getLastError() + " [af=" + history.isAuthFail() + "]" ); try{ json_area.setText( subs.getJSON()); }catch( Throwable e ){ e.printStackTrace(); } */ } public Composite getComposite() { return( composite ); } public String getFullTitle() { return( subs.getName()); } public void resizeMainBrowser() { if ( mainBrowser != null ){ Utils.execSWTThreadLater(0, new Runnable() { public void run() { if ( mainBrowser != null && ! mainBrowser.isDisposed() && mainBrowser.isVisible()){ FormData data = (FormData) mainBrowser.getLayoutData(); data.bottom = new FormAttachment(100,-1); mainBrowser.getParent().layout(true); Utils.execSWTThreadLater(0, new Runnable() { public void run() { if ( mainBrowser != null && ! mainBrowser.isDisposed() && mainBrowser.isVisible()){ FormData data = (FormData) mainBrowser.getLayoutData(); data.bottom = new FormAttachment(100,0); mainBrowser.getParent().layout(true); } } } ); } } }); } } public void resizeSecondaryBrowser() { // TODO Auto-generated method stub } /** * @param spinnerImage * * @since 3.1.1.1 */ public void setSpinnerImage(SideBarVitalityImage spinnerImage) { this.spinnerImage = spinnerImage; } } public static class sideBarItem { private subscriptionView view; private SideBarEntrySWT sb_entry; private TreeItem tree_item; private boolean destroyed; private SideBarVitalityImage warning; private SideBarVitalityImage spinnerImage; protected sideBarItem() { } protected void setTreeItem( TreeItem _tree_item, SideBarEntrySWT _sb_entry ) { tree_item = _tree_item; sb_entry = _sb_entry; warning = sb_entry.addVitalityImage( ALERT_IMAGE_ID ); spinnerImage = sb_entry.addVitalityImage("image.sidebar.vitality.dots"); spinnerImage.setVisible(false); if ( view != null ){ view.setSpinnerImage(spinnerImage); } } protected TreeItem getTreeItem() { return( tree_item ); } protected void setView( subscriptionView _view ) { view = _view; if (view != null) { view.setSpinnerImage( spinnerImage ); } } protected subscriptionView getView() { return( view ); } protected void setWarning( Subscription subs ) { // possible during initialisation, status will be shown again on complete if ( warning == null ){ return; } SubscriptionHistory history = subs.getHistory(); String last_error = history.getLastError(); boolean auth_fail = history.isAuthFail(); // don't report problem until its happened a few times, but not for auth fails as this is a perm error if ( history.getConsecFails() < 3 && !auth_fail ){ last_error = null; } boolean trouble = last_error != null; if ( trouble ){ warning.setToolTip( last_error ); warning.setImageID( auth_fail?AUTH_IMAGE_ID:ALERT_IMAGE_ID ); warning.setVisible( true ); }else{ warning.setVisible( false ); warning.setToolTip( "" ); } } protected boolean isDestroyed() { return( destroyed ); } protected void destroy() { destroyed = true; } public void activate() { SideBar sideBar = (SideBar)SkinViewManager.getByClass(SideBar.class); if ( sideBar != null && sb_entry != null ){ sideBar.showEntryByID(sb_entry.getId()); } } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionListWindow.java0000644000175000017500000003532511275141736030277 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.subscriptions; import java.util.Arrays; import java.util.Comparator; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ProgressBar; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import com.aelitis.azureus.core.subs.Subscription; import com.aelitis.azureus.core.subs.SubscriptionAssociationLookup; import com.aelitis.azureus.core.subs.SubscriptionException; import com.aelitis.azureus.core.subs.SubscriptionLookupListener; import com.aelitis.azureus.core.subs.SubscriptionManager; import com.aelitis.azureus.core.subs.SubscriptionManagerFactory; import com.aelitis.azureus.core.subs.SubscriptionPopularityListener; import com.aelitis.azureus.ui.swt.widgets.AnimatedImage; public class SubscriptionListWindow implements SubscriptionLookupListener { private DownloadManager download; private boolean useCachedSubs; private Display display; private Shell shell; AnimatedImage animatedImage; Button action; Label loadingText; ProgressBar loadingProgress; boolean loadingDone = false; SubscriptionAssociationLookup lookup = null; Composite mainComposite; Composite loadingPanel; Composite listPanel; Table subscriptionsList; StackLayout mainLayout; private class SubscriptionItemModel { String name; long popularity; String popularityDisplay; Subscription subscription; boolean selected; } SubscriptionItemModel subscriptionItems[]; public SubscriptionListWindow(DownloadManager download, boolean useCachedSubs ) { this.download = download; this.useCachedSubs = useCachedSubs; shell = ShellFactory.createMainShell(SWT.TITLE); shell.setSize(400,300); Utils.centreWindow(shell); display = shell.getDisplay(); shell.setText(MessageText.getString("subscriptions.listwindow.title")); shell.setLayout(new FormLayout()); mainComposite = new Composite(shell,SWT.NONE); Label separator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL); Button cancel = new Button(shell,SWT.PUSH); action = new Button(shell,SWT.PUSH); cancel.setText(MessageText.getString("Button.cancel")); FormData data; data = new FormData(); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); data.top = new FormAttachment(0,0); data.bottom = new FormAttachment(separator,0); mainComposite.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); data.bottom = new FormAttachment(cancel,-2); separator.setLayoutData(data); data = new FormData(); data.right = new FormAttachment(action); data.width = 100; data.bottom = new FormAttachment(100,-5); cancel.setLayoutData(data); data = new FormData(); data.right = new FormAttachment(100,-5); data.width = 100; data.bottom = new FormAttachment(100,-5); action.setLayoutData(data); cancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { if(lookup != null) { lookup.cancel(); } if(!shell.isDisposed()) { shell.dispose(); } } }); mainLayout = new StackLayout(); mainComposite.setLayout(mainLayout); loadingPanel = new Composite(mainComposite,SWT.NONE); loadingPanel.setLayout(new FormLayout()); listPanel = new Composite(mainComposite,SWT.NONE); listPanel.setLayout(new FillLayout()); subscriptionsList = new Table(listPanel,SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION | SWT.VIRTUAL); subscriptionsList.setHeaderVisible(true); TableColumn name = new TableColumn(subscriptionsList,SWT.NONE); name.setText(MessageText.getString("subscriptions.listwindow.name")); name.setWidth(310); name.setResizable(false); TableColumn popularity = new TableColumn(subscriptionsList,SWT.NONE); popularity.setText(MessageText.getString("subscriptions.listwindow.popularity")); popularity.setWidth(70); popularity.setResizable(false); subscriptionsList.addListener(SWT.SetData, new Listener() { public void handleEvent(Event e) { TableItem item = (TableItem) e.item; int index = subscriptionsList.indexOf(item); if(index >= 0 && index < subscriptionItems.length) { SubscriptionItemModel subscriptionItem = subscriptionItems[index]; item.setText(0,subscriptionItem.name); item.setText(1,subscriptionItem.popularityDisplay); } } }); subscriptionsList.setSortColumn(popularity); subscriptionsList.setSortDirection(SWT.DOWN); subscriptionsList.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { action.setEnabled(subscriptionsList.getSelectionIndex() != -1); } }); Listener sortListener = new Listener() { public void handleEvent(Event e) { // determine new sort column and direction TableColumn sortColumn = subscriptionsList.getSortColumn(); TableColumn currentColumn = (TableColumn) e.widget; int dir = subscriptionsList.getSortDirection(); if (sortColumn == currentColumn) { dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; } else { subscriptionsList.setSortColumn(currentColumn); dir = SWT.DOWN; } subscriptionsList.setSortDirection(dir); sortAndRefresh(); } }; name.addListener(SWT.Selection, sortListener); popularity.addListener(SWT.Selection, sortListener); animatedImage = new AnimatedImage(loadingPanel); loadingText = new Label(loadingPanel,SWT.WRAP | SWT.CENTER); loadingProgress = new ProgressBar(loadingPanel,SWT.HORIZONTAL); animatedImage.setImageFromName("spinner_big"); String contentName = "Dummy"; if(download != null) { contentName = download.getDisplayName(); } loadingText.setText(MessageText.getString("subscriptions.listwindow.loadingtext", new String[] {contentName})); loadingProgress.setMinimum(0); loadingProgress.setMaximum(300); loadingProgress.setSelection(0); data = new FormData(); data.left = new FormAttachment(1,2,-16); data.top = new FormAttachment(1,2,-32); data.width = 32; data.height = 32; animatedImage.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0,5); data.right = new FormAttachment(100,-5); data.top = new FormAttachment(animatedImage.getControl(),10); data.height = 50; loadingText.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0,5); data.right = new FormAttachment(100,-5); data.top = new FormAttachment(loadingText,5); loadingProgress.setLayoutData(data); boolean autoCheck = COConfigurationManager.getBooleanParameter("subscriptions.autocheck"); if(autoCheck) { startChecking(); } else { action.setText(MessageText.getString("Button.yes")); Composite acceptPanel = new Composite(mainComposite,SWT.NONE); acceptPanel.setLayout(new FormLayout()); Label acceptLabel = new Label(acceptPanel,SWT.WRAP | SWT.CENTER); acceptLabel.setText(MessageText.getString("subscriptions.listwindow.autochecktext")); data = new FormData(); data.left = new FormAttachment(0,5); data.right = new FormAttachment(100,-5); data.top = new FormAttachment(1,3,0); acceptLabel.setLayoutData(data); action.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { action.removeListener(SWT.Selection,this); COConfigurationManager.setParameter("subscriptions.autocheck",true); startChecking(); mainComposite.layout(); } }); mainLayout.topControl = acceptPanel; } //shell.setSize(400,300); shell.open(); } private void startChecking() { action.setText(MessageText.getString("subscriptions.listwindow.subscribe")); action.setEnabled(false); try { if(download != null) { byte[] hash = download.getTorrent().getHash(); SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton(); if ( useCachedSubs ){ Subscription[] subs = subs_man.getKnownSubscriptions( hash ); complete(hash,subs); }else{ lookup = subs_man.lookupAssociations(hash, this); } } else { } loadingDone = false; AEThread2 progressMover = new AEThread2("progressMover",true) { public void run() { final int[] waitTime = new int[1]; waitTime[0]= 100; while(!loadingDone) { if(display != null && ! display.isDisposed()) { display.asyncExec(new Runnable() { public void run() { if(loadingProgress != null && !loadingProgress.isDisposed()) { int currentSelection = loadingProgress.getSelection() +1; loadingProgress.setSelection(currentSelection); if(currentSelection > (loadingProgress.getMaximum()) * 80 / 100) { waitTime[0] = 300; } if (currentSelection > (loadingProgress.getMaximum()) * 90 / 100) { waitTime[0] = 1000; } } else { loadingDone = true; } } }); } try { Thread.sleep(waitTime[0]); //Thread.sleep(100); } catch (Exception e) { loadingDone = true; } } } }; progressMover.start(); } catch(Exception e) { failed(null,null); } animatedImage.start(); mainLayout.topControl = loadingPanel; } /*private void populateSubscription(final Subscription subscription) { final TableItem item = new TableItem(subscriptionsList,SWT.NONE); item.setData("subscription",subscription); item.setText(0,subscription.getName()); try { item.setText(1,MessageText.getString("subscriptions.listwindow.popularity.reading")); action.setEnabled(true); }*/ public void found(byte[] hash, Subscription subscription) { // TODO Auto-generated method stub } public void complete(final byte[] hash,final Subscription[] subscriptions) { if( ! (subscriptions.length > 0) ) { failed(hash, null); } else { subscriptionItems = new SubscriptionItemModel[subscriptions.length]; for(int i = 0 ; i < subscriptions.length ; i++) { final SubscriptionItemModel subscriptionItem = new SubscriptionItemModel(); subscriptionItems[i] = subscriptionItem; subscriptionItem.name = subscriptions[i].getName(); subscriptionItem.popularity = -1; subscriptionItem.popularityDisplay = MessageText.getString("subscriptions.listwindow.popularity.reading"); subscriptionItem.subscription = subscriptions[i]; try { subscriptions[i].getPopularity( new SubscriptionPopularityListener() { public void gotPopularity( long popularity ) { update(subscriptionItem,popularity, popularity + "" ); } public void failed( SubscriptionException error ) { update(subscriptionItem,-2,MessageText.getString("subscriptions.listwindow.popularity.unknown")); } }); } catch(SubscriptionException e) { update(subscriptionItem,-2,MessageText.getString("subscriptions.listwindow.popularity.unknown")); } } if(display != null && !display.isDisposed()) { display.asyncExec(new Runnable() { public void run() { animatedImage.stop(); mainLayout.topControl = listPanel; mainComposite.layout(); sortAndRefresh(); subscriptionsList.setSelection(0); action.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { if(subscriptionsList != null && !subscriptionsList.isDisposed()) { int selectedIndex = subscriptionsList.getSelectionIndex(); if(selectedIndex >= 0 && selectedIndex < subscriptionItems.length) { Subscription subscription = (Subscription) subscriptionItems[selectedIndex].subscription; if(subscription != null) { subscription.setSubscribed(true); } } } } }); } }); } } } protected void update( final SubscriptionItemModel subscriptionItem, final long popularity, final String text ) { subscriptionItem.popularity = popularity; subscriptionItem.popularityDisplay = text; display.asyncExec( new Runnable() { public void run() { sortAndRefresh(); } }); } private void sortAndRefresh() { if ( subscriptionsList.isDisposed()){ return; } for(int i = 0 ; i < subscriptionItems.length ; i++) { subscriptionItems[i].selected = false; } int currentSelection = subscriptionsList.getSelectionIndex(); if(currentSelection >= 0 && currentSelection < subscriptionItems.length) { subscriptionItems[currentSelection].selected = true; } final int dir = subscriptionsList.getSortDirection() == SWT.DOWN ? 1 : -1; final boolean nameSort = subscriptionsList.getColumn(0) == subscriptionsList.getSortColumn(); Arrays.sort(subscriptionItems,new Comparator() { public int compare(Object arg0, Object arg1) { SubscriptionItemModel item0 = (SubscriptionItemModel) arg0; SubscriptionItemModel item1 = (SubscriptionItemModel) arg1; if(nameSort) { return dir * item0.name.compareTo(item1.name); } else { return dir * (int) (item1.popularity - item0.popularity); } } }); subscriptionsList.setItemCount(subscriptionItems.length); subscriptionsList.clearAll(); if(currentSelection >= 0 && currentSelection < subscriptionItems.length) { for(int i = 0 ; i < subscriptionItems.length ; i++) { if(subscriptionItems[i].selected) { subscriptionsList.setSelection(i); } } } } public void failed(byte[] hash,SubscriptionException error) { if(display != null && !display.isDisposed()) { display.asyncExec(new Runnable() { public void run() { animatedImage.stop(); animatedImage.dispose(); loadingProgress.dispose(); loadingText.setText(MessageText.getString("subscriptions.listwindow.failed")); } }); } } public static void main(String[] args) { Display display = new Display(); SubscriptionListWindow slw = new SubscriptionListWindow(null,false); while(!slw.shell.isDisposed()) { if(!display.readAndDispatch()) { display.sleep(); } } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/imageloader/0000755000175000017500000000000011310377632022252 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/imageloader/ImageLoader.java0000644000175000017500000005640311275165452025303 0ustar adrianadrian/* * Created on Jun 7, 2006 2:31:26 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.imageloader; import java.io.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.ImageRepository; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.skin.SkinProperties; import com.aelitis.azureus.ui.skin.SkinPropertiesImpl; import com.aelitis.azureus.ui.utils.ImageBytesDownloader; /** * Loads images from a skinProperty object. *

    * Will look for special suffixes (over, down, disabled) and try to * load resources using base key and suffix. ie. loadImage("foo-over") when * foo=image.png, will load image-over.png *

    * Will also create own disabled images if base image found and no disabled * image found. Disabled opacity can be set via imageloader.disabled-opacity * key * * @author TuxPaper * @created Jun 7, 2006 * */ public class ImageLoader implements AEDiagnosticsEvidenceGenerator { private static ImageLoader instance; private static final boolean DEBUG_UNLOAD = false; private static final boolean DEBUG_REFCOUNT = false; private static final int GC_INTERVAL = 60 * 1000; private final String[] sSuffixChecks = { "-over", "-down", "-disabled", "-selected", "-gray", }; private Display display; public static Image noImage; private final ConcurrentHashMap mapImages; private final ArrayList notFound; private CopyOnWriteArrayList skinProperties; //private final ClassLoader classLoader; private int disabledOpacity; private Set cached_resources = new HashSet(); private File cache_dir = new File(SystemProperties.getUserPath(), "cache" ); public static ImageLoader getInstance() { if (ImageLoader.instance == null) { ImageLoader.instance = new ImageLoader(Display.getDefault(), null); // always add az2 icons to instance SkinPropertiesImpl skinProperties = new SkinPropertiesImpl( ImageRepository.class.getClassLoader(), "org/gudy/azureus2/ui/icons/", "icons.properties"); ImageLoader.instance.addSkinProperties(skinProperties); } return ImageLoader.instance; } public ImageLoader(/*ClassLoader classLoader,*/Display display, SkinProperties skinProperties) { //this.classLoader = classLoader; File[] files = cache_dir.listFiles(); if ( files != null ){ for (File f: files ){ String name = f.getName(); if ( name.endsWith( ".ico" )){ cached_resources.add( name ); } } } mapImages = new ConcurrentHashMap(); notFound = new ArrayList(); this.display = display; this.skinProperties = new CopyOnWriteArrayList(); addSkinProperties(skinProperties); AEDiagnostics.addEvidenceGenerator(this); if (GC_INTERVAL > 0) { SimpleTimer.addPeriodicEvent("GC_ImageLoader", GC_INTERVAL, new TimerEventPerformer() { public void perform(TimerEvent event) { collectGarbage(); } }); } } /* private Image loadImage(Display display, String key) { for (SkinProperties sp : skinProperties) { String value = sp.getStringValue(key); if (value != null) { return loadImage(display, sp.getClassLoader(), value, key); } } return loadImage(display, null, null, key); } */ private Image[] findResources(String sKey) { if (Collections.binarySearch(notFound, sKey) >= 0) { return null; } for (int i = 0; i < sSuffixChecks.length; i++) { String sSuffix = sSuffixChecks[i]; if (sKey.endsWith(sSuffix)) { //System.out.println("YAY " + sSuffix + " for " + sKey); String sParentName = sKey.substring(0, sKey.length() - sSuffix.length()); String[] sParentFiles = null; ClassLoader cl = null; for (SkinProperties sp : skinProperties) { sParentFiles = sp.getStringArray(sParentName); if (sParentFiles != null) { cl = sp.getClassLoader(); break; } } if (sParentFiles != null) { boolean bFoundOne = false; Image[] images = parseValuesString(cl, sKey, sParentFiles, sSuffix); if (images != null) { for (int j = 0; j < images.length; j++) { Image image = images[j]; if (isRealImage(image)) { bFoundOne = true; } } if (!bFoundOne) { for (int j = 0; j < images.length; j++) { Image image = images[j]; if (isRealImage(image)) { image.dispose(); } } } else { return images; } } } else { // maybe there's another suffix.. Image[] images = findResources(sParentName); if (images != null) { return images; } } } } int i = Collections.binarySearch(notFound, sKey) * -1 - 1; if (i >= 0) { notFound.add(i, sKey); } return null; } /** * @param values * @param suffix * @return * * @since 3.1.1.1 */ private Image[] parseValuesString(ClassLoader cl, String sKey, String[] values, String suffix) { Image[] images = null; int splitX = 0; int locationStart = 0; if (values[0].equals("multi") && values.length > 2) { splitX = Integer.parseInt(values[1]); locationStart = 2; } if (locationStart == 0 || splitX <= 0) { images = new Image[values.length]; for (int i = 0; i < values.length; i++) { int index = values[i].lastIndexOf('.'); if (index > 0) { String sTryFile = values[i].substring(0, index) + suffix + values[i].substring(index); images[i] = loadImage(display, cl, sTryFile, sKey); if (images[i] == null) { sTryFile = values[i].substring(0, index) + suffix.replace('-', '_') + values[i].substring(index); images[i] = loadImage(display, cl, sTryFile, sKey); } } if (images[i] == null) { images[i] = getNoImage(); } } } else { Image image = null; String origFile = values[locationStart]; int index = origFile.lastIndexOf('.'); if (index > 0) { String sTryFile = origFile.substring(0, index) + suffix + origFile.substring(index); image = loadImage(display, cl, sTryFile, sKey); if (image == null) { sTryFile = origFile.substring(0, index) + suffix.replace('-', '_') + origFile.substring(index); image = loadImage(display, cl, sTryFile, sKey); } } if (image == null) { image = loadImage(display, cl, values[locationStart], sKey); } if (image != null) { Rectangle bounds = image.getBounds(); images = new Image[(bounds.width + splitX - 1) / splitX]; for (int i = 0; i < images.length; i++) { Image imgBG = Utils.createAlphaImage(display, splitX, bounds.height, (byte) 0); images[i] = Utils.blitImage(display, image, new Rectangle(i * splitX, 0, splitX, bounds.height), imgBG, new Point(0, 0)); imgBG.dispose(); } } } return images; } private Image loadImage(Display display, ClassLoader cl, String res, String sKey) { Image img = null; //System.out.println("LoadImage " + sKey + " - " + res); if (res == null) { for (int i = 0; i < sSuffixChecks.length; i++) { String sSuffix = sSuffixChecks[i]; if (sKey.endsWith(sSuffix)) { //System.out.println("Yay " + sSuffix + " for " + sKey); String sParentName = sKey.substring(0, sKey.length() - sSuffix.length()); String sParentFile = null; for (SkinProperties sp : skinProperties) { sParentFile = sp.getStringValue(sParentName); if (sParentFile != null) { if (cl == null) { cl = sp.getClassLoader(); } break; } } if (sParentFile != null) { int index = sParentFile.lastIndexOf('.'); if (index > 0) { String sTryFile = sParentFile.substring(0, index) + sSuffix + sParentFile.substring(index); img = loadImage(display, cl, sTryFile, sKey); if (img != null) { break; } sTryFile = sParentFile.substring(0, index) + sSuffix.replace('-', '_') + sParentFile.substring(index); img = loadImage(display, cl, sTryFile, sKey); if (img != null) { break; } } } } } } if (img == null) { try { if (cl != null) { InputStream is = cl.getResourceAsStream(res); if (is != null) { img = new Image(display, is); } } if (img == null) { if (sKey.endsWith("-disabled") || sKey.endsWith("_disabled")) { String id = sKey.substring(0, sKey.length() - 9); Image imgToFade = getImage(id); if (isRealImage(imgToFade)) { ImageData imageData = imgToFade.getImageData(); img = new Image(display, imageData); // decrease alpha if (imageData.alphaData != null) { if (disabledOpacity == -1) { for (int i = 0; i < imageData.alphaData.length; i++) { imageData.alphaData[i] = (byte) ((imageData.alphaData[i] & 0xff) >> 3); } } else { for (int i = 0; i < imageData.alphaData.length; i++) { imageData.alphaData[i] = (byte) ((imageData.alphaData[i] & 0xff) * disabledOpacity / 100); } } img = new Image(display, imageData); } else { Rectangle bounds = imgToFade.getBounds(); Image bg = Utils.createAlphaImage(display, bounds.width, bounds.height, (byte) 0); img = Utils.renderTransparency(display, bg, imgToFade, new Point(0, 0), disabledOpacity == -1 ? 64 : disabledOpacity * 255 / 100); bg.dispose(); } } releaseImage(id); }else if (sKey.endsWith("-gray")) { String id = sKey.substring(0, sKey.length() - 5); Image imgToGray = getImage(id); if (isRealImage(imgToGray)) { img = new Image( display, imgToGray, SWT.IMAGE_GRAY ); } releaseImage(id); } //System.err.println("ImageRepository:loadImage:: Resource not found: " + res); } } catch (Throwable e) { System.err.println("ImageRepository:loadImage:: Resource not found: " + res + "\n" + e); } } return img; } public void unLoadImages() { if (DEBUG_UNLOAD) { for (String key : mapImages.keySet()) { Image[] images = mapImages.get(key).getImages(); if (images != null) { for (int i = 0; i < images.length; i++) { Image image = images[i]; if (image != null && !image.isDisposed()) { System.out.println("dispose " + image + ";" + key); image.dispose(); } } } } } else { for (ImageLoaderRefInfo imageInfo : mapImages.values()) { Image[] images = imageInfo.getImages(); if (images != null) { for (int i = 0; i < images.length; i++) { Image image = images[i]; if (image != null && !image.isDisposed()) { image.dispose(); } } } } } } public Image[] getImages(String sKey) { if (!Utils.isThisThreadSWT()) { Debug.out("getImages called on non-SWT thread"); return new Image[0]; } //System.out.println("getImages " + sKey); if (sKey == null) { return new Image[0]; } ImageLoaderRefInfo imageInfo = mapImages.get(sKey); if (imageInfo != null && imageInfo.getImages() != null) { imageInfo.addref(); if (DEBUG_REFCOUNT) { System.out.println("ImageLoader: ++ refcount of " + sKey + " now " + imageInfo.getRefCount() + " via " + Debug.getCompressedStackTrace()); } return imageInfo.getImages(); } Image[] images; String[] locations = null; ClassLoader cl = null; for (SkinProperties sp : skinProperties) { locations = sp.getStringArray(sKey); if (locations != null && locations.length > 0) { cl = sp.getClassLoader(); break; } } // System.out.println(sKey + "=" + properties.getStringValue(sKey) // + ";" + ((locations == null) ? "null" : "" + locations.length)); if (locations == null || locations.length == 0) { images = findResources(sKey); if (images == null) { String cache_key = sKey.hashCode() + ".ico"; if ( cached_resources.contains( cache_key )){ File cache = new File( cache_dir, cache_key ); if (cache.exists()) { try { FileInputStream fis = new FileInputStream(cache); try { byte[] imageBytes = FileUtil.readInputStreamAsByteArray(fis); InputStream is = new ByteArrayInputStream(imageBytes); org.eclipse.swt.graphics.ImageLoader swtImageLoader = new org.eclipse.swt.graphics.ImageLoader(); ImageData[] imageDatas = swtImageLoader.load(is); images = new Image[imageDatas.length]; for (int i = 0; i < imageDatas.length; i++) { images[i] = new Image(Display.getCurrent(), imageDatas[i]); } try { is.close(); } catch (IOException e) { } } finally { fis.close(); } } catch (Throwable e) { Debug.printStackTrace(e); } } }else{ cached_resources.remove( cache_key ); } if (images == null) { images = new Image[0]; } } for (int i = 0; i < images.length; i++) { if (images[i] == null) { images[i] = getNoImage(); } } } else { images = parseValuesString(cl, sKey, locations, ""); } mapImages.put(sKey, new ImageLoaderRefInfo(images)); return images; } public Image getImage(String sKey) { Image[] images = getImages(sKey); if (images == null || images.length == 0 || images[0].isDisposed()) { return getNoImage(); } return images[0]; } public long releaseImage(String sKey) { if (sKey == null) { return 0; } ImageLoaderRefInfo imageInfo = mapImages.get(sKey); if (imageInfo != null) { imageInfo.unref(); if (false && imageInfo.getRefCount() < 0) { Image[] images = imageInfo.getImages(); System.out.println("ImageLoader refcount < 0 for " + sKey + " by " + Debug.getCompressedStackTrace() + "\n " + (images == null ? "null" : ("" + images.length + ";" + (images.length == 0 ? "0" : "" + (images[0] == noImage))))); } if (DEBUG_REFCOUNT) { System.out.println("ImageLoader: -- refcount of " + sKey + " now " + imageInfo.getRefCount() + " via " + Debug.getCompressedStackTrace()); } return imageInfo.getRefCount(); // TODO: cleanup? } return 0; } /** * Adds image to repository. refcount will be 1, or if key already exists, * refcount will increase. * * @param key * @param image * * @since 4.0.0.5 */ public void addImage(String key, Image image) { if (!Utils.isThisThreadSWT()) { Debug.out("addImage called on non-SWT thread"); return; } ImageLoaderRefInfo existing = mapImages.putIfAbsent(key, new ImageLoaderRefInfo(image)); if (existing != null) { // should probably fail if refcount > 0 existing.setImages(new Image[] { image }); existing.addref(); } } public void addImageNoDipose(String key, Image image) { if (!Utils.isThisThreadSWT()) { Debug.out("addImageNoDispose called on non-SWT thread"); return; } ImageLoaderRefInfo existing = mapImages.putIfAbsent(key, new ImageLoaderRefInfo(image)); if (existing != null) { existing.setNonDisposable(); // should probably fail if refcount > 0 existing.setImages(new Image[] { image }); existing.addref(); } } private static Image getNoImage() { if (noImage == null) { Display display = Display.getDefault(); final int SIZE = 10; noImage = new Image(display, SIZE, SIZE); GC gc = new GC(noImage); gc.setBackground(display.getSystemColor(SWT.COLOR_YELLOW)); gc.fillRectangle(0, 0, SIZE, SIZE); gc.setBackground(display.getSystemColor(SWT.COLOR_RED)); gc.drawRectangle(0, 0, SIZE - 1, SIZE - 1); gc.dispose(); } return noImage; } public boolean imageExists(String name) { boolean exists = isRealImage(getImage(name)); releaseImage(name); return exists; } public boolean imageAdded(String name) { Image[] images = getImages(name); boolean added = images != null && images.length > 0; releaseImage(name); return added; } public static boolean isRealImage(Image image) { return image != null && image != getNoImage() && !image.isDisposed(); } public int getAnimationDelay(String sKey) { for (SkinProperties sp : skinProperties) { int delay = sp.getIntValue(sKey + ".delay", -1); if (delay >= 0) { return delay; } } return 100; } public Image getUrlImage(final String url, final ImageDownloaderListener l) { if (!Utils.isThisThreadSWT()) { Debug.out("getUrlImage called on non-SWT thread"); return null; } if (l == null || url == null) { return null; } if (imageExists(url)) { Image image = getImage(url); l.imageDownloaded(image, true); return image; } final String cache_key = url.hashCode() + ".ico"; final File cache_file = new File( cache_dir, cache_key ); if ( cached_resources.contains( cache_key )){ if ( cache_file.exists()){ try { FileInputStream fis = new FileInputStream(cache_file); try { byte[] imageBytes = FileUtil.readInputStreamAsByteArray(fis); InputStream is = new ByteArrayInputStream(imageBytes); Image image = new Image(Display.getCurrent(), is); try { is.close(); } catch (IOException e) { } mapImages.put(url, new ImageLoaderRefInfo(image)); l.imageDownloaded(image, true); return image; } finally { fis.close(); } } catch (Throwable e) { Debug.printStackTrace(e); } }else{ cached_resources.remove( cache_key ); } } ImageBytesDownloader.loadImage(url, new ImageBytesDownloader.ImageDownloaderListener() { public void imageDownloaded(final byte[] imageBytes) { Utils.execSWTThread(new AERunnable() { public void runSupport() { FileUtil.writeBytesAsFile(cache_file.getAbsolutePath(), imageBytes); cached_resources.add( cache_key ); InputStream is = new ByteArrayInputStream(imageBytes); Image image = new Image(Display.getCurrent(), is); try { is.close(); } catch (IOException e) { } mapImages.put(url, new ImageLoaderRefInfo(image)); l.imageDownloaded(image, false); } }); } }); return null; } public static interface ImageDownloaderListener { public void imageDownloaded(Image image, boolean returnedImmediately); } // @see org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator#generate(org.gudy.azureus2.core3.util.IndentWriter) public void generate(IndentWriter writer) { writer.println("ImageLoader for " + skinProperties); writer.indent(); long[] sizeCouldBeFree = { 0 }; long[] totalSizeEstimate = { 0 }; try { writer.indent(); try { writer.println("Non-Disposable:"); writer.indent(); for (String key : mapImages.keySet()) { ImageLoaderRefInfo info = mapImages.get(key); if (!info.isNonDisposable()) { continue; } writeEvidenceLine(writer, key, info, totalSizeEstimate, sizeCouldBeFree); } writer.exdent(); writer.println("Disposable:"); writer.indent(); for (String key : mapImages.keySet()) { ImageLoaderRefInfo info = mapImages.get(key); if (info.isNonDisposable()) { continue; } writeEvidenceLine(writer, key, info, totalSizeEstimate, sizeCouldBeFree); } writer.exdent(); } finally { writer.exdent(); } if (totalSizeEstimate[0] > 0) { writer.println((totalSizeEstimate[0] / 1024) + "k estimated used for images"); } if (sizeCouldBeFree[0] > 0) { writer.println((sizeCouldBeFree[0] / 1024) + "k could be freed"); } } finally { writer.exdent(); } } /** * @param writer * @param info */ private void writeEvidenceLine(IndentWriter writer, String key, ImageLoaderRefInfo info, long[] totalSizeEstimate, long[] sizeCouldBeFree) { String line = info.getRefCount() + "] " + key; if (Utils.isThisThreadSWT()) { long sizeEstimate = 0; Image[] images = info.getImages(); for (int i = 0; i < images.length; i++) { Image img = images[i]; if (img != null) { if (img.isDisposed()) { line += "; *DISPOSED*"; } else { Rectangle bounds = img.getBounds(); long est = bounds.width * bounds.height * 4l; sizeEstimate += est; totalSizeEstimate[0] += est; if (info.canDispose()) { sizeCouldBeFree[0] += est; } } } } line += "; est " + sizeEstimate + " bytes"; } writer.println(line); } public void addSkinProperties(SkinProperties skinProperties) { if (skinProperties == null) { return; } this.skinProperties.add(skinProperties); disabledOpacity = skinProperties.getIntValue( "imageloader.disabled-opacity", -1); notFound.clear(); } /** * * * @since 4.0.0.5 */ public void collectGarbage() { Utils.execSWTThread(new AERunnable() { public void runSupport() { int numRemoved = 0; for (Iterator iter = mapImages.keySet().iterator(); iter.hasNext();) { String key = iter.next(); ImageLoaderRefInfo info = mapImages.get(key); // no one can addref in between canDispose and dispose because // all our addrefs are in SWT threads. if (info != null && info.canDispose()) { iter.remove(); numRemoved++; Image[] images = info.getImages(); for (int j = 0; j < images.length; j++) { Image image = images[j]; if (image != null && !image.isDisposed()) { image.dispose(); } } } } //System.out.println("ImageLoader: GC'd " + numRemoved); } }); } /** * @param label * @param key * * @since 4.0.0.5 */ public void setLabelImage(Label label, final String key) { Image bg = getImage(key); label.setImage(bg); label.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { releaseImage(key); } }); } public void setButtonImage(Button btn, final String key) { Image bg = getImage(key); btn.setImage(bg); btn.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { releaseImage(key); } }); } public void setBackgroundImage(Control control, final String key) { Image bg = getImage(key); control.setBackgroundImage(bg); control.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { releaseImage(key); } }); } public SkinProperties[] getSkinProperties() { return skinProperties.toArray(new SkinProperties[0]); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/imageloader/ImageLoaderRefInfo.java0000644000175000017500000000376311131314564026544 0ustar adrianadrian/* * Created on Jan 1, 2009 3:17:06 PM * Copyright (C) 2009 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.imageloader; import org.eclipse.swt.graphics.Image; /** * @author TuxPaper * @created Jan 1, 2009 * */ public class ImageLoaderRefInfo { private Image[] images; // -2: non-disposable; -1: someone over unref'd; 0: no refs (dispose!) private long refcount; protected ImageLoaderRefInfo(Image[] images) { this.images = images; refcount = 1; } protected ImageLoaderRefInfo(Image image) { this.images = new Image[] { image }; refcount = 1; } protected void setNonDisposable() { refcount = -2; } protected boolean isNonDisposable() { return refcount == -2; } protected void addref() { synchronized (this) { if (refcount >= 0) { refcount++; } } } protected void unref() { synchronized (this) { if (refcount >= 0) { refcount--; } } } protected boolean canDispose() { return refcount == 0 || refcount == -1; } protected long getRefCount() { return refcount; } protected Image[] getImages() { return images; } protected void setImages(Image[] images) { this.images = images; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/0000755000175000017500000000000011310377632020745 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectAdapter.java0000644000175000017500000000514111152777446025556 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.skin; import org.gudy.azureus2.core3.util.Debug; /** * Converts {@link SWTSkinObjectListener} events to method calls * * @author TuxPaper * @created Sep 30, 2006 * */ public class SWTSkinObjectAdapter implements SWTSkinObjectListener { public Object skinObjectShown(SWTSkinObject skinObject, Object params) { return null; } public Object skinObjectHidden(SWTSkinObject skinObject, Object params) { return null; } public Object skinObjectSelected(SWTSkinObject skinObject, Object params) { return null; } public Object skinObjectDestroyed(SWTSkinObject skinObject, Object params) { return null; } public Object skinObjectCreated(SWTSkinObject skinObject, Object params) { return null; } public Object updateLanguage(SWTSkinObject skinObject, Object params) { return null; } /* (non-Javadoc) * @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectListener#eventOccured(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, int, java.lang.Object) */ public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { try { switch (eventType) { case EVENT_SHOW: return skinObjectShown(skinObject, params); case EVENT_HIDE: return skinObjectHidden(skinObject, params); case EVENT_SELECT: return skinObjectSelected(skinObject, params); case EVENT_DESTROY: return skinObjectDestroyed(skinObject, params); case EVENT_CREATED: return skinObjectCreated(skinObject, params); case EVENT_LANGUAGE_CHANGE: return updateLanguage(skinObject, params); default: return null; } } catch (Exception e) { Debug.out("Skin Event " + NAMES[eventType] + " caused an error", e); } return null; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectContainer.java0000644000175000017500000002120311171750564026106 0ustar adrianadrian/* * Created on Jun 26, 2006 11:38:47 AM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AERunnableObject; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; /** * A SWTSkinObject that contains other SWTSkinObjects * * @author TuxPaper * @created Jun 26, 2006 * */ public class SWTSkinObjectContainer extends SWTSkinObjectBasic { boolean bPropogate = false; boolean bPropogateDown = false; public SWTSkinObjectContainer(SWTSkin skin, SWTSkinProperties properties, String sID, String sConfigID, SWTSkinObject parent) { super(skin, properties, sID, sConfigID, "container", parent); createComposite(); } public SWTSkinObjectContainer(SWTSkin skin, SWTSkinProperties properties, Control control, String sID, String sConfigID, String type, SWTSkinObject parent) { super(skin, properties, sID, sConfigID, type, parent); triggerListeners(SWTSkinObjectListener.EVENT_CREATED); if (control != null) { setControl(control); } } private void createComposite() { int style = SWT.NONE; if (properties.getIntValue(sConfigID + ".border", 0) == 1) { style = SWT.BORDER; } if (properties.getBooleanValue(sConfigID + ".doublebuffer", false)) { style |= SWT.DOUBLE_BUFFERED; } Composite createOn; if (parent == null) { createOn = skin.getShell(); } else { createOn = (Composite) parent.getControl(); } final int minWidth = properties.getIntValue(sConfigID + ".minwidth", -1); Composite parentComposite; if (SWTSkin.DEBUGLAYOUT) { System.out.println("linkIDtoParent: Create Composite " + sID + " on " + createOn); parentComposite = new Group(createOn, style); ((Group) parentComposite).setText(sConfigID == null ? sID : sConfigID); parentComposite.setData("DEBUG", "1"); } else { // Lovely SWT has a default size of 64x64 if no children have sizes. // Let's fix that.. parentComposite = new Composite(createOn, style) { // @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean) public Point computeSize(int wHint, int hHint, boolean changed) { Point size = super.computeSize(wHint, hHint, changed); if (getChildren().length == 0 && (size.x == 64 || size.y == 64)) { Object ld = getLayoutData(); if (ld instanceof FormData) { FormData fd = (FormData) ld; if (fd.width != 0 && fd.height != 0) { Rectangle trim = computeTrim (0, 0, fd.width, fd.height); return new Point(trim.width, trim.height); } } return new Point(1, 1); } if (minWidth > 0 && size.x < minWidth) { size.x = minWidth; } return size; } // @see org.eclipse.swt.widgets.Control#computeSize(int, int) public Point computeSize(int wHint, int hHint) { Point size = super.computeSize(wHint, hHint); if (getChildren().length == 0 && (size.x == 64 || size.y == 64)) { Object ld = getLayoutData(); if (ld instanceof FormData) { FormData fd = (FormData) ld; if (fd.width != 0 && fd.height != 0) { Rectangle trim = computeTrim (0, 0, fd.width, fd.height); return new Point(trim.width, trim.height); } } return new Point(1, 1); } if (minWidth > 0 && size.x < minWidth) { size.x = minWidth; } return size; } }; } parentComposite.setLayout(new FormLayout()); control = parentComposite; setControl(control); } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectBasic#setControl(org.eclipse.swt.widgets.Control) public void setControl(Control control) { bPropogateDown = properties.getIntValue(sConfigID + ".propogateDown", 1) == 1; super.setControl(control); } protected void setViewID(String viewID) { super.setViewID(viewID); if (SWTSkin.DEBUGLAYOUT && control != null) { ((Group) control).setText("[" + viewID + "]"); } } public SWTSkinObject[] getChildren() { if (isDisposed()) { return new SWTSkinObject[0]; } SWTSkinObject[] so = (SWTSkinObject[]) Utils.execSWTThreadWithObject( "getChildren", new AERunnableObject() { public Object runSupport() { if (control.isDisposed()) { return new SWTSkinObject[0]; } Control[] swtChildren = ((Composite) control).getChildren(); ArrayList list = new ArrayList(swtChildren.length); for (int i = 0; i < swtChildren.length; i++) { Control childControl = swtChildren[i]; SWTSkinObject so = (SWTSkinObject) childControl.getData("SkinObject"); if (so != null) { list.add(so); } } return (SWTSkinObject[]) list.toArray(new SWTSkinObject[list.size()]); } }, 2000); if (so == null) { System.err.println("Tell Tux to fix this " + Debug.getCompressedStackTrace()); return oldgetChildren(); } return so; } // TODO: Need find child(view id) public SWTSkinObject[] oldgetChildren() { String[] widgets = properties.getStringArray(sConfigID + ".widgets"); if (widgets == null) { return new SWTSkinObject[0]; } ArrayList list = new ArrayList(); for (int i = 0; i < widgets.length; i++) { String id = widgets[i]; SWTSkinObject skinObject = skin.getSkinObjectByID(id, this); if (skinObject != null) { list.add(skinObject); } } SWTSkinObject[] objects = new SWTSkinObject[list.size()]; objects = (SWTSkinObject[]) list.toArray(objects); return objects; } public Composite getComposite() { return (Composite) control; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectBasic#switchSuffix(java.lang.String) public String switchSuffix(final String suffix, final int level, boolean walkUp, boolean walkDown) { String sFullsuffix = super.switchSuffix(suffix, level, walkUp, walkDown); if (bPropogateDown && walkDown && suffix != null && control != null && !control.isDisposed()) { Utils.execSWTThread(new AERunnable() { public void runSupport() { SWTSkinObject[] children = getChildren(); for (int i = 0; i < children.length; i++) { children[i].switchSuffix(suffix, level, false); } } }); } return sFullsuffix; } public void setPropogation(boolean propogate) { bPropogate = propogate; if (SWTSkin.DEBUGLAYOUT) { ((Group) control).setText(((Group) control).getText() + (bPropogate ? ";P" : "")); } } public boolean getPropogation() { return bPropogate; } public void setDebugAndChildren(boolean b) { setDebug(true); SWTSkinObject[] children = getChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof SWTSkinObjectContainer) { ((SWTSkinObjectContainer)children[i]).setDebugAndChildren(b); } else { children[i].setDebug(b); } } } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectBasic#setIsVisible(boolean) protected boolean setIsVisible(boolean visible, boolean walkup) { boolean changed = super.setIsVisible(visible, walkup); // Currently we ignore "changed" and set visibility on children to ensure // things display if (!changed || true) { SWTSkinObject[] children = getChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof SWTSkinObjectBasic) { SWTSkinObjectBasic child = ((SWTSkinObjectBasic)children[i]); Control childControl = child.getControl(); if (childControl != null && !childControl.isDisposed()) { //child.setIsVisible(visible, false); child.setIsVisible(childControl.isVisible(), false); } } } } return changed; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesImpl.java0000644000175000017500000000510711051462664026016 0ustar adrianadrian/* * Created on Jun 1, 2006 4:16:52 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; import java.util.Map; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.util.LightHashMap; import com.aelitis.azureus.ui.skin.SkinPropertiesImpl; import com.aelitis.azureus.ui.swt.utils.ColorCache; /** * @author TuxPaper * @created Jun 1, 2006 * */ public class SWTSkinPropertiesImpl extends SkinPropertiesImpl implements SWTSkinProperties { private static Map colorMap = new LightHashMap(); /** * @param skinPath * @param mainSkinFile */ public SWTSkinPropertiesImpl(ClassLoader classLoader, String skinPath, String mainSkinFile) { super(classLoader, skinPath, mainSkinFile); } /** * */ public SWTSkinPropertiesImpl() { super(); } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinProperties#getColor(java.lang.String) public Color getColor(String sID) { Color color; if (colorMap.containsKey(sID)) { return (Color) colorMap.get(sID); } try { int[] rgb = getColorValue(sID); if (rgb[0] > -1) { color = ColorCache.getColor(Display.getCurrent(), rgb[0], rgb[1], rgb[2]); } else { color = ColorCache.getColor(Display.getCurrent(), getStringValue(sID)); } } catch (Exception e) { // IMP.getLogger().log(LoggerChannel.LT_ERROR, // "Failed loading color : color." + colorNames[i]); color = null; } colorMap.put(sID, color); return color; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinProperties#getColor(java.lang.String, org.eclipse.swt.graphics.Color) public Color getColor(String name, Color def) { Color color = getColor(name); if (color == null) { return def; } return color; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText2.java0000644000175000017500000004132711223315754025177 0ustar adrianadrian/* * Created on Aug 4, 2006 9:03:19 AM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; import java.text.NumberFormat; import java.text.ParseException; import java.util.Locale; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter.URLInfo; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManager; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.ui.swt.utils.ColorCache; /** * Text Skin Object. This one paints text on parent. * * @author TuxPaper * @created Aug 4, 2006 * */ public class SWTSkinObjectText2 extends SWTSkinObjectBasic implements SWTSkinObjectText, PaintListener { String sText; String sDisplayText; String sKey; boolean bIsTextDefault = false; private int style; private Canvas canvas; private boolean isUnderline; private int antialiasMode = SWT.DEFAULT; private boolean isAllcaps; private boolean hasShadow; private int hpadding; private int vpadding; private boolean relayoutOnTextChange = true; private boolean isItalic = false; private static Font font = null; private GCStringPrinter lastStringPrinter; private Color colorUrl; public SWTSkinObjectText2(SWTSkin skin, final SWTSkinProperties skinProperties, String sID, final String sConfigID, String[] typeParams, SWTSkinObject parent) { super(skin, skinProperties, sID, sConfigID, "text", parent); style = SWT.WRAP; String sAlign = skinProperties.getStringValue(sConfigID + ".align"); if (sAlign != null) { int align = SWTSkinUtils.getAlignment(sAlign, SWT.NONE); if (align != SWT.NONE) { style |= align; } } String sVAlign = skinProperties.getStringValue(sConfigID + ".v-align"); if (sVAlign != null) { int align = SWTSkinUtils.getAlignment(sVAlign, SWT.NONE); if (align != SWT.CENTER) { if (align != SWT.NONE) { style |= align; } else { style |= SWT.TOP; } } } else { style |= SWT.TOP; } if (skinProperties.getIntValue(sConfigID + ".border", 0) == 1) { style |= SWT.BORDER; } String sAntiAlias = skinProperties.getStringValue(sConfigID + ".antialias", (String) null); if (sAntiAlias != null && sAntiAlias.length() > 0) { antialiasMode = (sAntiAlias.equals("1") || sAntiAlias.toLowerCase().equals( "true")) ? SWT.ON : SWT.OFF; } relayoutOnTextChange = skinProperties.getBooleanValue(sConfigID + ".text.relayoutOnChange", true); Composite createOn; if (parent == null) { createOn = skin.getShell(); } else { createOn = (Composite) parent.getControl(); } canvas = new Canvas(createOn, SWT.DOUBLE_BUFFERED) { Point ptMax = new Point(0, 0); // @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean) public Point computeSize(int wHint, int hHint, boolean changed) { int border = getBorderWidth() * 2; Point pt = new Point(border, border); if (sDisplayText == null) { return pt; } Font existingFont = (Font) canvas.getData("font"); Color existingColor = (Color) canvas.getData("color"); GC gc = new GC(this); if (existingFont != null) { gc.setFont(existingFont); } if (existingColor != null) { gc.setForeground(existingColor); } if (antialiasMode != SWT.DEFAULT) { try { gc.setTextAntialias(antialiasMode); } catch (Exception e) { // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others } } GCStringPrinter sp = new GCStringPrinter(gc, sDisplayText, new Rectangle(0, 0, wHint == -1 ? 999999 : wHint, hHint == -1 ? 999999 : hHint), true, false, style & SWT.WRAP); sp.calculateMetrics(); pt = sp.getCalculatedSize(); pt.x += border + hpadding * 2; pt.y += border + vpadding * 2; gc.dispose(); if (isUnderline) { pt.y++; } if (hasShadow) { pt.x++; } if (isItalic) { pt.x += 4; } int fixedWidth = skinProperties.getIntValue(sConfigID + ".width", -1); if (fixedWidth >= 0) { pt.x = fixedWidth; } int fixedHeight = skinProperties.getIntValue(sConfigID + ".height", -1); if (fixedHeight >= 0) { pt.y = fixedHeight; } if (isVisible()) { if (pt.x > ptMax.x) { ptMax.x = pt.x; } if (pt.y > ptMax.y) { ptMax.y = pt.y; } } return pt; } }; if (false && font == null) { Display display = createOn.getDisplay(); FontData fd = new FontData("Arial", Utils.pixelsToPoint(10, display.getDPI().y), SWT.NORMAL); font = new Font(display, fd); } canvas.setData("font", font); setControl(canvas); if (typeParams.length > 1) { bIsTextDefault = true; sText = typeParams[1]; for (int i = 2; i < typeParams.length; i++) { sText += ", " + typeParams[i]; } this.sDisplayText = isAllcaps && sText != null ? sText.toUpperCase() : sText; } canvas.addMouseListener(new MouseListener() { public void mouseUp(MouseEvent e) { if (lastStringPrinter != null) { URLInfo hitUrl = lastStringPrinter.getHitUrl(e.x, e.y); if (hitUrl != null) { String url = hitUrl.url; try { ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetworkForURL(url); if (cn != null) { url = cn.appendURLSuffix(url, false, false); } if (url.contains("?")) { url += "&"; } else { url += "?"; } url += "fromWeb=false&os.name=" + UrlUtils.encode(Constants.OSName) + "&os.version=" + UrlUtils.encode(System.getProperty("os.version")) + "&java.version=" + UrlUtils.encode(Constants.JAVA_VERSION); } catch (Throwable t) { // ignore } Utils.launch(url); } } } public void mouseDown(MouseEvent e) { } public void mouseDoubleClick(MouseEvent e) { } }); canvas.addMouseMoveListener(new MouseMoveListener() { public void mouseMove(MouseEvent e) { if (lastStringPrinter != null && lastStringPrinter.hasHitUrl()) { URLInfo hitUrl = lastStringPrinter.getHitUrl(e.x, e.y); canvas.setCursor(hitUrl == null ? null : canvas.getDisplay().getSystemCursor(SWT.CURSOR_HAND)); } } }); setAlwaysHookPaintListener(true); updateFont(""); } public String switchSuffix(String suffix, int level, boolean walkUp, boolean walkDown) { suffix = super.switchSuffix(suffix, level, walkUp, walkDown); if (suffix == null) { return null; } String sPrefix = sConfigID + ".text"; if (sText == null || bIsTextDefault) { String text = properties.getStringValue(sPrefix + suffix); if (text != null) { sText = text; this.sDisplayText = isAllcaps && sText != null ? sText.toUpperCase() : sText; } } final String fSuffix = suffix; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (canvas == null || canvas.isDisposed()) { return; } updateFont(fSuffix); } }); return suffix; } private void updateFont(String suffix) { String sPrefix = sConfigID + ".text"; Color newColorURL = properties.getColor(sPrefix + ".urlcolor" + suffix); if (newColorURL != null) { colorUrl = newColorURL; } Color color = properties.getColor(sPrefix + ".color" + suffix); //System.out.println(this + "; " + sPrefix + ";" + suffix + "; " + color + "; " + text); if (color != null) { canvas.setData("color", color); } hpadding = properties.getIntValue(sPrefix + ".h-padding", 0); vpadding = properties.getIntValue(sPrefix + ".v-padding", 0); Font existingFont = (Font) canvas.getData("Font" + suffix); if (existingFont != null && !existingFont.isDisposed()) { canvas.setData("font", existingFont); } else { boolean bNewFont = false; int iFontSize = -1; int iFontWeight = -1; String sFontFace = null; FontData[] tempFontData = canvas.getFont().getFontData(); sFontFace = properties.getStringValue(sPrefix + ".font" + suffix); if (sFontFace != null) { tempFontData[0].setName(sFontFace); bNewFont = true; } String sStyle = properties.getStringValue(sPrefix + ".style" + suffix); if (sStyle != null) { isAllcaps = false; String[] sStyles = sStyle.toLowerCase().split(","); for (int i = 0; i < sStyles.length; i++) { String s = sStyles[i]; if (s.equals("allcaps")) { isAllcaps = true; } if (s.equals("bold")) { if (iFontWeight == -1) { iFontWeight = SWT.BOLD; } else { iFontWeight |= SWT.BOLD; } bNewFont = true; } if (s.equals("italic")) { if (iFontWeight == -1) { iFontWeight = SWT.ITALIC; } else { iFontWeight |= SWT.ITALIC; } bNewFont = true; isItalic = true; } else { isItalic = false; } isUnderline = s.equals("underline"); if (isUnderline) { canvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { int x = 0; Point pt = e.gc.textExtent(sDisplayText); Point size = ((Control) e.widget).getSize(); if (pt.x < size.x) { x = size.x - pt.x; size.x = pt.x; } e.gc.drawLine(x, size.y - 1, size.x - 1 + x, size.y - 1); } }); } if (s.equals("strike")) { canvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { Point size = ((Control) e.widget).getSize(); int y = size.y / 2; e.gc.drawLine(0, y, size.x - 1, y); } }); } if (s.equals("normal")) { bNewFont = true; } if (s.equals("shadow")) { hasShadow = true; } } this.sDisplayText = isAllcaps && sText != null ? sText.toUpperCase() : sText; } if (iFontWeight >= 0) { tempFontData[0].setStyle(iFontWeight); } String sSize = properties.getStringValue(sPrefix + ".size" + suffix); if (sSize != null) { FontData[] fd = canvas.getFont().getFontData(); try { char firstChar = sSize.charAt(0); if (firstChar == '+' || firstChar == '-') { sSize = sSize.substring(1); } double dSize = NumberFormat.getInstance(Locale.US).parse(sSize).doubleValue(); if (firstChar == '+') { iFontSize = (int) (fd[0].height + dSize); } else if (firstChar == '-') { iFontSize = (int) (fd[0].height - dSize); } else { if (sSize.endsWith("px")) { //iFontSize = Utils.getFontHeightFromPX(canvas.getFont(), null, (int) dSize); iFontSize = Utils.getFontHeightFromPX(canvas.getDisplay(), tempFontData, null, (int) dSize); //iFontSize = Utils.pixelsToPoint(dSize, canvas.getDisplay().getDPI().y); } else { iFontSize = (int) dSize; } } bNewFont = true; } catch (NumberFormatException e) { e.printStackTrace(); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (bNewFont) { FontData[] fd = canvas.getFont().getFontData(); if (iFontSize > 0) { fd[0].setHeight(iFontSize); } if (iFontWeight >= 0) { fd[0].setStyle(iFontWeight); } if (sFontFace != null) { fd[0].setName(sFontFace); } final Font canvasFont = new Font(canvas.getDisplay(), fd); canvas.setData("font", canvasFont); canvas.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { canvasFont.dispose(); } }); canvas.setData("Font" + suffix, canvasFont); } } canvas.redraw(); } /** * @param searchText */ public void setText(String text) { if (text == null) { text = ""; } if (text.equals(sText)) { return; } this.sText = text; this.sDisplayText = isAllcaps && sText != null ? sText.toUpperCase() : sText; this.sKey = null; bIsTextDefault = false; // Doing execSWTThreadLater delays the relayout for too long at skin startup // Since there are a lot of async execs at skin startup, we generally // see the window a second or two before this async call would get called // (if it were async) Utils.execSWTThread(new AERunnable() { public void runSupport() { if (canvas != null && !canvas.isDisposed()) { canvas.redraw(); if (relayoutOnTextChange) { Utils.relayout(canvas); } } } }); } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectBasic#paintControl(org.eclipse.swt.graphics.GC) public void paintControl(GC gc) { if (sText == null || sText.length() == 0) { return; } super.paintControl(gc); Composite composite = (Composite) control; Rectangle clientArea = composite.getClientArea(); clientArea.x += hpadding; clientArea.width -= hpadding * 2; clientArea.y += vpadding; clientArea.height -= vpadding * 2; Font existingFont = (Font) canvas.getData("font"); Color existingColor = (Color) canvas.getData("color"); if (existingFont != null) { gc.setFont(existingFont); } if (existingColor != null) { gc.setForeground(existingColor); } if (antialiasMode != SWT.DEFAULT) { try { gc.setTextAntialias(antialiasMode); } catch (Exception ex) { // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others } } if (hasShadow) { Rectangle r = new Rectangle(clientArea.x + 1, clientArea.y + 1, clientArea.width, clientArea.height); Color foreground = gc.getForeground(); Color color = ColorCache.getColor(gc.getDevice(), 0, 0, 0); gc.setForeground(color); gc.setAlpha(64); GCStringPrinter.printString(gc, sDisplayText, r, true, false, style); gc.setAlpha(255); gc.setForeground(foreground); } lastStringPrinter = new GCStringPrinter(gc, sDisplayText, clientArea, true, false, style); if (colorUrl != null) { lastStringPrinter.setUrlColor(colorUrl); } lastStringPrinter.printString(); } public void setTextID(String key) { if (key == null) { setText(""); } else if (key.equals(sKey)) { return; } this.sText = MessageText.getString(key); this.sDisplayText = isAllcaps && sText != null ? sText.toUpperCase() : sText; this.sKey = key; bIsTextDefault = false; Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { if (canvas == null || canvas.isDisposed()) { return; } canvas.redraw(); if (relayoutOnTextChange) { canvas.layout(true); Utils.relayout(canvas); } } }); } public void setTextID(String key, String[] params) { if (key == null) { setText(""); } /* * KN: disabling the caching of the key since this is parameterized it may be called * multiple times with different parameters */ // else if (key.equals(sKey)) { // return; // } this.sText = MessageText.getString(key, params); this.sDisplayText = isAllcaps && sText != null ? sText.toUpperCase() : sText; this.sKey = key; bIsTextDefault = false; Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { if (canvas == null || canvas.isDisposed()) { return; } canvas.redraw(); if (relayoutOnTextChange) { canvas.layout(true); Utils.relayout(canvas); } } }); } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectBasic#triggerListeners(int, java.lang.Object) public void triggerListeners(int eventType, Object params) { if (eventType == SWTSkinObjectListener.EVENT_LANGUAGE_CHANGE) { if (sKey != null) { setTextID(sKey); } } super.triggerListeners(eventType, params); } public int getStyle() { return style; } public void setStyle(int style) { this.style = style; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectText#getText() public String getText() { return sDisplayText; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectCheckbox.java0000644000175000017500000000644311124571142025712 0ustar adrianadrian/** * Created on Sep 21, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.skin; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; /** * Native checkbox * * @author TuxPaper * @created Dec 24, 2008 * */ public class SWTSkinObjectCheckbox extends SWTSkinObjectBasic { private Button button; // stored so we can access it after button is disposed, and so we can // retrieve without being on SWT thread private boolean checked; private List buttonListeners = new CopyOnWriteArrayList(); public SWTSkinObjectCheckbox(SWTSkin skin, SWTSkinProperties properties, String id, String configID, SWTSkinObject parentSkinObject) { super(skin, properties, id, configID, "checkbox", parentSkinObject); Composite createOn; if (parent == null) { createOn = skin.getShell(); } else { createOn = (Composite) parent.getControl(); } button = new Button(createOn, SWT.CHECK); checked = false; button.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { checked = button.getSelection(); for (SWTSkinCheckboxListener l : buttonListeners) { try { l.checkboxChanged(SWTSkinObjectCheckbox.this, checked); } catch (Exception ex) { Debug.out(ex); } } } public void widgetDefaultSelected(SelectionEvent e) { } }); setControl(button); } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectBasic#switchSuffix(java.lang.String, int, boolean) public String switchSuffix(String suffix, int level, boolean walkUp, boolean walkDown) { suffix = super.switchSuffix(suffix, level, walkUp, walkDown); if (suffix == null) { return null; } String sPrefix = sConfigID + ".text"; String text = properties.getStringValue(sPrefix + suffix); if (text != null) { setText(text); } return suffix; } public void addSelectionListener(SWTSkinCheckboxListener listener) { if (buttonListeners.contains(listener)) { return; } buttonListeners.add(listener); } public void setText(final String text) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (button != null && !button.isDisposed()) { button.setText(text); } } }); } public boolean isChecked() { return checked; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBrowser.java0000644000175000017500000001655011275141736025620 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.skin; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTError; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.swt.browser.BrowserContext; import com.aelitis.azureus.ui.swt.browser.BrowserContext.loadingListener; import com.aelitis.azureus.ui.swt.browser.listener.*; import com.aelitis.azureus.util.UrlFilter; /** * @author TuxPaper * @created Oct 9, 2006 * */ public class SWTSkinObjectBrowser extends SWTSkinObjectBasic { private Browser browser; private Composite cParent; private Composite cArea; private String sStartURL; private BrowserContext context; private String urlToUse; private boolean forceVisibleAfterLoad; private static boolean doneTheUglySWTFocusHack = false; /** * @param skin * @param properties * @param sID * @param sConfigID * @param type * @param parent */ public SWTSkinObjectBrowser(SWTSkin skin, SWTSkinProperties properties, String sID, String sConfigID, SWTSkinObject parent) { super(skin, properties, sID, sConfigID, "browser", parent); cParent = parent == null ? skin.getShell() : (Composite) parent.getControl(); cArea = cParent; cArea = new Canvas(cParent, SWT.NO_BACKGROUND); cArea.setLayout(new FormLayout()); setControl(cArea); if (cParent.isVisible()) { init(); } else { addListener(new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == SWTSkinObjectListener.EVENT_SHOW) { removeListener(this); init(); } return null; } }); } } public void init() { if (browser != null && !browser.isDisposed()) { return; } try { browser = new Browser(cArea, Utils.getInitialBrowserStyle(SWT.NONE)); browser.setLayoutData(Utils.getFilledFormData()); browser.getParent().layout(true); } catch (SWTError e) { System.err.println("Browser: " + e.toString()); return; } Control widgetIndicator = null; String sIndicatorWidgetID = properties.getStringValue(sConfigID + ".indicator"); if (sIndicatorWidgetID != null) { SWTSkinObject skinObjectIndicator = skin.getSkinObjectByID(sIndicatorWidgetID); if (skinObjectIndicator != null) { widgetIndicator = skinObjectIndicator.getControl(); } } String browserID = properties.getStringValue(sConfigID + ".view"); if (browserID == null) { browserID = sID; } forceVisibleAfterLoad = properties.getBooleanValue(sConfigID + ".forceVisibleAfterLoad", true); context = new BrowserContext(browserID, browser, widgetIndicator, forceVisibleAfterLoad); context.addMessageListener(new TorrentListener()); context.addMessageListener(new VuzeListener()); context.addMessageListener(new DisplayListener(browser)); context.addMessageListener(new ConfigListener(browser)); context.addListener(new loadingListener() { public void browserLoadingChanged(boolean loading, String url) { if (loading && browser.isVisible()) { // hack so search results page doesn't clear cur selected if (UrlFilter.getInstance().urlCanRPC(url)) { SelectedContentManager.clearCurrentlySelectedContent(); } } } }); String url = urlToUse != null ? urlToUse : sStartURL != null ? sStartURL : properties.getStringValue(sConfigID + ".url", (String) null); if (url != null) { setURL(url); } } public Browser getBrowser() { if (browser == null) { init(); } return browser; } public void setURL(final String url) { urlToUse = url; if (browser == null) { return; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (url == null) { browser.setText(""); } else { String urlToUse = url; if (UrlFilter.getInstance().urlCanRPC(url)){ ContentNetwork contentNetwork = ContentNetworkManagerFactory.getSingleton().getContentNetwork( context.getContentNetworkID()); if (contentNetwork != null) { urlToUse = contentNetwork.appendURLSuffix(urlToUse, false, true); } } if (browser != null) { browser.setUrl(urlToUse); if(browser.isVisible()) { browser.setFocus(); } } } if (sStartURL == null) { sStartURL = url; if (browser != null) { browser.setData("StartURL", url); } } //System.out.println(SystemTime.getCurrentTime() + "] Set URL: " + url); } }); } public void restart() { if (null != sStartURL) { String startURLUnique; String sRand = "rand=" + SystemTime.getCurrentTime(); if (sStartURL.indexOf("rand=") > 0) { startURLUnique = sStartURL.replaceAll("rand=[0-9.]+", sRand); } else if (sStartURL.indexOf('?') > 0) { startURLUnique = sStartURL + "&" + sRand; } else { startURLUnique = sStartURL + "?" + sRand; } System.out.println(startURLUnique); setURL(startURLUnique); } } /** * */ public void layout() { cParent.layout(); } public BrowserContext getContext() { return context; } public String getStartURL() { return sStartURL; } public void setStartURL(String url) { sStartURL = url; if (null != browser) { if (urlToUse == null) { browser.setUrl(url); } browser.setData("StartURL", url); } } public boolean isPageLoading() { return context == null ? false : context.isPageLoading(); } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectBasic#setVisible(boolean) public boolean setIsVisible(final boolean visible, boolean walkup) { boolean changed = super.setIsVisible(visible, walkup); if (changed) { // notify browser after we've fully processed visibility Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { if (!isDisposed() && context != null) { context.sendBrowserMessage("browser", visible ? "shown" : "hidden"); } } }); } return changed; } public void addListener(loadingListener l) { if (context != null) { context.addListener(l); } } public void refresh() { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (browser != null && !browser.isDisposed()) { browser.refresh(); } } }); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSetListener.java0000644000175000017500000000217710535151200025717 0ustar adrianadrian/* * Created on Jun 18, 2006 11:38:26 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; /** * @author TuxPaper * @created Jun 18, 2006 * */ public interface SWTSkinTabSetListener { public void tabChanged(SWTSkinTabSet tabSet, String oldTabID, String newTabID); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesParamImpl.java0000644000175000017500000000727611127403346027004 0ustar adrianadrian/* * Created on Jun 27, 2006 1:48:36 AM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; import java.util.ResourceBundle; import org.eclipse.swt.graphics.Color; /** * SWTSkinProperties delegator that always passes a set of parameters * to string requests. * * @author TuxPaper * @created Jun 27, 2006 * */ public class SWTSkinPropertiesParamImpl implements SWTSkinPropertiesParam { private final SWTSkinProperties properties; private final String[] sCloneParams; /** * @param properties */ public SWTSkinPropertiesParamImpl(SWTSkinProperties properties, String[] sCloneParams) { this.properties = properties; this.sCloneParams = sCloneParams; } public void addProperty(String name, String value) { properties.addProperty(name, value); } public Color getColor(String name) { return properties.getColor(name); } public int[] getColorValue(String name) { return properties.getColorValue(name); } public int getIntValue(String name, int def) { return properties.getIntValue(name, def); } public String[] getStringArray(String name, String[] params) { return properties.getStringArray(name, params); } public String[] getStringArray(String name) { return properties.getStringArray(name, sCloneParams); } public String getStringValue(String name, String def) { return properties.getStringValue(name, sCloneParams, def); } public String getStringValue(String name, String[] params, String def) { return properties.getStringValue(name, params, def); } public String getStringValue(String name, String[] params) { return properties.getStringValue(name, params); } public String getStringValue(String name) { return properties.getStringValue(name, sCloneParams); } // @see com.aelitis.azureus.ui.skin.SkinProperties#getBooleanValue(java.lang.String, boolean) public boolean getBooleanValue(String name, boolean def) { return properties.getBooleanValue(name, def); } public String[] getParamValues() { return sCloneParams; } public void clearCache() { properties.clearCache(); } // @see com.aelitis.azureus.ui.skin.SkinProperties#contains(java.lang.String) public boolean hasKey(String name) { return properties.hasKey(name); } public Color getColor(String name, Color def) { Color color = getColor(name); if (color == null) { return def; } return color; } // @see com.aelitis.azureus.ui.skin.SkinProperties#getReferenceID(java.lang.String) public String getReferenceID(String name) { return properties.getReferenceID(name); } // @see com.aelitis.azureus.ui.skin.SkinProperties#addResourceBundle(java.util.ResourceBundle) public void addResourceBundle(ResourceBundle subBundle) { properties.addResourceBundle(subBundle); } // @see com.aelitis.azureus.ui.skin.SkinProperties#getClassLoader() public ClassLoader getClassLoader() { return properties.getClassLoader(); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkin.java0000644000175000017500000015012711270166656023127 0ustar adrianadrian/* * Created on May 29, 2006 4:01:04 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; import java.util.*; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.ui.IUIIntializer; import com.aelitis.azureus.ui.skin.SkinProperties; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author TuxPaper * @created May 29, 2006 * */ public class SWTSkin { private static final SWTSkinObjectListener[] NOLISTENERS = new SWTSkinObjectListener[0]; static boolean DEBUGLAYOUT = System.getProperty("debuglayout") != null; private static int numSkins = 0; private Map mapImageLoaders = new ConcurrentHashMap(); private SWTSkinProperties skinProperties; private Listener handCursorListener; //private Listener ontopPaintListener; // Key = Skin Object ID; Value = Array of SWTSkinObject private HashMap mapIDsToSOs = new HashMap(); private AEMonitor mon_MapIDsToSOs = new AEMonitor("mapIDsToControls"); // Key = TabSet ID; Value = SWTSkinTabSet private HashMap mapTabSetToControls = new HashMap(); // Key = Widget ID; Value = Array of SWTSkinObject private HashMap mapPublicViewIDsToSOs = new HashMap(); private AEMonitor mon_mapPublicViewIDsToSOs = new AEMonitor("mapPVIDsToSOs"); private HashMap> mapPublicViewIDsToListeners = new HashMap>(); private AEMonitor mapPublicViewIDsToListeners_mon = new AEMonitor( "mapPVIDsToListeners"); private ArrayList ontopImages = new ArrayList(); private Shell shell; private boolean bLayoutComplete = false; private CopyOnWriteList listenersLayoutComplete = new CopyOnWriteList(); private boolean ourSkinProperties = false; private int currentSkinObjectcreationCount = 0; private ImageLoader imageLoader; private String startID; /** * */ public SWTSkin() { ourSkinProperties = true; init(new SWTSkinPropertiesImpl()); } public SWTSkin(ClassLoader classLoader, String skinPath, String mainSkinFile) { ourSkinProperties = true; init(new SWTSkinPropertiesImpl(classLoader, skinPath, mainSkinFile)); } private void init(SWTSkinProperties skinProperties) { numSkins++; this.skinProperties = skinProperties; // the first skin gets the default image loader. We don't add it to // the mapImageLoaders because non-skin objects may use the image loader // mapImageLoaders is used to dispose of images when the skin is disposed if (numSkins == 1) { imageLoader = ImageLoader.getInstance(); imageLoader.addSkinProperties(skinProperties); } else { imageLoader = new ImageLoader(Display.getDefault(), skinProperties); mapImageLoaders.put(skinProperties, imageLoader); } /* ontopPaintListener = new Listener() { public void handleEvent(Event event) { for (Iterator iter = ontopImages.iterator(); iter.hasNext();) { SWTSkinObject skinObject = (SWTSkinObject) iter.next(); Control control = skinObject.getControl(); if (control == null) { continue; } Rectangle bounds = control.getBounds(); Point point = control.toDisplay(0, 0); bounds.x = point.x; bounds.y = point.y; Rectangle eventBounds = event.getBounds(); point = ((Control) event.widget).toDisplay(0, 0); eventBounds.x += point.x; eventBounds.y += point.y; //System.out.println(eventBounds + ";" + bounds); if (eventBounds.intersects(bounds)) { Point dst = new Point(bounds.x - point.x, bounds.y - point.y); //System.out.println("Painting on " + event.widget + " at " + dst); Image image = (Image) control.getData("image"); // TODO: Clipping otherwise alpha will multiply //event.gc.setClipping(eventBounds); event.gc.drawImage(image, dst.x, dst.y); } } } }; */ } public ImageLoader getImageLoader(SkinProperties properties) { if (properties == this.skinProperties) { return imageLoader; } ImageLoader loader = mapImageLoaders.get(properties); if (loader != null) { return loader; } loader = new ImageLoader(Display.getDefault(), properties); mapImageLoaders.put(properties, loader); return loader; } public void addToControlMap(SWTSkinObject skinObject) { String sID = skinObject.getSkinObjectID(); if (DEBUGLAYOUT) { System.out.println("addToControlMap: " + sID + " : " + skinObject); } addToSOArrayMap(mapIDsToSOs, mon_MapIDsToSOs, sID, skinObject); // For SWT layout -- add a reverse lookup Control control = skinObject.getControl(); if (control != null) { control.setData("ConfigID", skinObject.getConfigID()); control.setData("SkinID", sID); } } private void addToSOArrayMap(Map arrayMap, AEMonitor mon, String key, SWTSkinObject object) { if (mon != null) { mon.enter(); } try { Object existing = arrayMap.get(key); if (existing instanceof SWTSkinObject[]) { SWTSkinObject[] existingObjects = (SWTSkinObject[]) existing; boolean bAlreadyPresent = false; for (int i = 0; i < existingObjects.length; i++) { //System.out.println(".." + existingObjects[i]); if (existingObjects[i] != null && existingObjects[i].equals(object)) { bAlreadyPresent = true; System.err.println("already present: " + key + "; " + object + "; existing: " + existingObjects[i] + " via " + Debug.getCompressedStackTrace()); break; } } if (!bAlreadyPresent) { int length = existingObjects.length; SWTSkinObject[] newObjects = new SWTSkinObject[length + 1]; System.arraycopy(existingObjects, 0, newObjects, 0, length); newObjects[length] = object; arrayMap.put(key, newObjects); // System.out.println("addToArrayMap: " + key + " : " + object + " #" // + (length + 1)); } } else { arrayMap.put(key, new SWTSkinObject[] { object }); } } finally { if (mon != null) { mon.exit(); } } } private Object getFromSOArrayMap(Map arrayMap, Object key, SWTSkinObject parent) { if (parent == null) { return null; } SWTSkinObject[] objects = arrayMap.get(key); if (objects == null) { return null; } for (int i = 0; i < objects.length; i++) { SWTSkinObject object = objects[i]; SWTSkinObject thisParent = object; while (thisParent != null) { if (thisParent.equals(parent)) { return object; } thisParent = thisParent.getParent(); } } return null; } private void setSkinObjectViewID(SWTSkinObject skinObject, String sViewID) { addToSOArrayMap(mapPublicViewIDsToSOs, mon_mapPublicViewIDsToSOs, sViewID, skinObject); } /* public void dumpObjects() { System.out.println("====="); FormData formdata; for (Iterator iter = mapIDsToControls.keySet().iterator(); iter.hasNext();) { String sID = (String) iter.next(); Control control = getSkinObjectByID(sID).getControl(); formdata = (FormData) control.getLayoutData(); System.out.println(sID); sID += ".attach."; if (formdata.left != null) { System.out.println(sID + "left=" + getAttachLine(formdata.left)); } if (formdata.right != null) { System.out.println(sID + "right=" + getAttachLine(formdata.right)); } if (formdata.top != null) { System.out.println(sID + "top=" + getAttachLine(formdata.top)); } if (formdata.bottom != null) { System.out.println(sID + "bottom=" + getAttachLine(formdata.bottom)); } } } */ public SWTSkinObject getSkinObjectByID(String sID) { SWTSkinObject[] objects = mapIDsToSOs.get(sID); if (objects == null) { return null; } return objects[0]; } protected SWTSkinObject getSkinObjectByID(String sID, SWTSkinObject parent) { if (parent == null) { // XXX Search for parent is shell directly return getSkinObjectByID(sID); } return (SWTSkinObject) getFromSOArrayMap(mapIDsToSOs, sID, parent); } public SWTSkinObject getSkinObject(String sViewID) { SWTSkinObject[] objects = mapPublicViewIDsToSOs.get(sViewID); if (objects == null || objects.length == 0) { if (!Utils.isThisThreadSWT()) { Debug.out("View " + sViewID + " does not exist. Skipping unattach check because not in SWT thread"); return null; } return createUnattachedView(sViewID, null); } return objects[0]; } /** * @param viewID * @return * * @since 3.1.1.1 */ private SWTSkinObject createUnattachedView(String viewID, SWTSkinObject parent) { String unattachedView = skinProperties.getStringValue("UnattachedView." + viewID); if (unattachedView != null) { if (unattachedView.indexOf(',') > 0) { String[] split = unattachedView.split(","); String parentID = split[1]; SWTSkinObject soParent = getSkinObjectByID(parentID, parent); if (soParent != null) { String configID = split[0]; return createSkinObject(configID, configID, soParent); } } SWTSkinObjectListener[] listeners = getSkinObjectListeners(viewID); for (int i = 0; i < listeners.length; i++) { SWTSkinObjectListener l = listeners[i]; Object o = l.eventOccured(null, SWTSkinObjectListener.EVENT_CREATE_REQUEST, new String[] { viewID, unattachedView }); if (o instanceof SWTSkinObject) { return (SWTSkinObject) o; } } } return null; } public SWTSkinObject getSkinObject(String sViewID, SWTSkinObject parent) { if (parent == null) { // XXX Search for parent is shell directly return getSkinObject(sViewID); } String parentViewID = parent.getViewID(); if (parentViewID != null && parentViewID.equals(sViewID)) { return parent; } SWTSkinObject so = (SWTSkinObject) getFromSOArrayMap( mapPublicViewIDsToSOs, sViewID, parent); if (so == null) { so = createUnattachedView(sViewID, parent); } return so; } public SWTSkinTabSet getTabSet(String sID) { return mapTabSetToControls.get(sID); } public SWTSkinObjectTab activateTab(SWTSkinObject skinObjectInTab) { if (skinObjectInTab == null) { return null; } if (skinObjectInTab instanceof SWTSkinObjectTab) { SWTSkinObjectTab tab = (SWTSkinObjectTab) skinObjectInTab; tab.getTabset().setActiveTab(tab); return tab; } for (Iterator iter = mapTabSetToControls.values().iterator(); iter.hasNext();) { SWTSkinTabSet tabset = iter.next(); SWTSkinObjectTab[] tabs = tabset.getTabs(); boolean bHasSkinObject = false; for (int i = 0; i < tabs.length; i++) { SWTSkinObjectTab tab = tabs[i]; SWTSkinObject[] activeWidgets = tab.getActiveWidgets(true); for (int j = 0; j < activeWidgets.length; j++) { SWTSkinObject object = activeWidgets[j]; //System.out.println("check " + tab + ";" + object + " for " + skinObjectInTab); if (hasSkinObject(object, skinObjectInTab)) { //System.out.println("FOUND"); tabset.setActiveTab(tab); return tab; } } } } System.out.println("NOT FOUND" + skinObjectInTab); return null; } private boolean hasSkinObject(SWTSkinObject start, SWTSkinObject skinObject) { if (start instanceof SWTSkinObjectContainer) { SWTSkinObject[] children = ((SWTSkinObjectContainer) start).getChildren(); for (int i = 0; i < children.length; i++) { SWTSkinObject object = children[i]; //System.out.println(" check " + object + " in " + start + " for " + skinObject); if (hasSkinObject(object, skinObject)) { return true; } } } //System.out.println(" check " + start + " for " + skinObject); return skinObject.equals(start); } public SWTSkinTabSet getTabSet(SWTSkinObject skinObject) { String sTabSetID = skinObject.getProperties().getStringValue( skinObject.getConfigID() + ".tabset"); return getTabSet(sTabSetID); } public boolean setActiveTab(String sTabSetID, String sTabViewID) { SWTSkinTabSet tabSet = getTabSet(sTabSetID); if (tabSet == null) { System.err.println(sTabSetID); return false; } return tabSet.setActiveTab(sTabViewID); } /** * @param shell2 * @param string * @param uiInitializer * * @since 3.0.5.3 */ public void initialize(Shell shell, String startID) { initialize(shell, startID, null); } public void initialize(final Shell shell, String startID, IUIIntializer uiInitializer) { this.shell = shell; this.startID = startID; FormLayout layout = new FormLayout(); shell.setLayout(layout); shell.setBackgroundMode(SWT.INHERIT_DEFAULT); shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { disposeSkin(); } }); Listener l = new Listener() { Control lastControl = null; public void handleEvent(Event event) { if (shell.isDisposed() && event.display != null) { event.display.removeFilter(SWT.MouseMove, this); event.display.removeFilter(SWT.MouseExit, this); return; } Control cursorControl = shell.getDisplay().getCursorControl(); //System.out.println("move from " + (lastControl == null ? null : lastControl.handle) + " to " + (cursorControl == null ? "null" : cursorControl.handle)); if (cursorControl != lastControl) { Point cursorLocation = shell.getDisplay().getCursorLocation(); while (lastControl != null && !lastControl.isDisposed()) { Point cursorLocationInControl = lastControl.toControl(cursorLocation); Point size = lastControl.getSize(); if (!new Rectangle(0, 0, size.x, size.y).contains(cursorLocationInControl)) { SWTSkinObjectBasic so = (SWTSkinObjectBasic) lastControl.getData("SkinObject"); if (so != null) { so.switchSuffix("", 3, false, false); } } lastControl = lastControl.getParent(); } lastControl = cursorControl; while (cursorControl != null) { SWTSkinObjectBasic so = (SWTSkinObjectBasic) cursorControl.getData("SkinObject"); if (so != null) { so.switchSuffix("-over", 3, false, false); } cursorControl = cursorControl.getParent(); } } } }; shell.getDisplay().addFilter(SWT.MouseMove, l); // can't just add a MouseExit listener to the shell, because it doesn't // get fired when a control is on the edge shell.getDisplay().addFilter(SWT.MouseExit, l); shell.addListener(SWT.Deactivate, l); shell.addListener(SWT.Activate, l); /****** REPLACED BY MouseMove // When shell activates or deactivates, send a MouseEnter or MouseExit // This fixes the problem where we are hovering over a skinobject with // a "-over" state, we tab away, move the mouse, and tab back again. // Without this code, the skinobject would still be in "-over" state shell.addListener(SWT.Deactivate, new Listener() { public void handleEvent(Event event) { Control cursorControl = shell.getDisplay().getCursorControl(); if (cursorControl != null) { while (cursorControl != null) { Event mouseExitEvent = new Event(); mouseExitEvent.type = SWT.MouseExit; mouseExitEvent.widget = cursorControl; shell.getDisplay().post(mouseExitEvent); System.out.println(cursorControl.getData("SkinObject")); cursorControl = cursorControl.getParent(); } } } }); shell.addListener(SWT.Activate, new Listener() { public void handleEvent(Event event) { Control cursorControl = shell.getDisplay().getCursorControl(); if (cursorControl != null) { while (cursorControl != null) { Event mouseExitEvent = new Event(); mouseExitEvent.type = SWT.MouseEnter; mouseExitEvent.widget = cursorControl; shell.getDisplay().post(mouseExitEvent); cursorControl = cursorControl.getParent(); } } } }); */ Color bg = skinProperties.getColor(startID + ".color"); if (bg != null) { shell.setBackground(bg); } Color fg = skinProperties.getColor(startID + ".fgcolor"); if (fg != null) { shell.setForeground(fg); } int width = skinProperties.getIntValue(startID + ".width", -1); int height = skinProperties.getIntValue(startID + ".height", -1); if (width > 0 && height > 0) { shell.setSize(width, height); } String title = skinProperties.getStringValue(startID + ".title", (String) null); if (title != null) { shell.setText(title); } String[] sMainGroups = skinProperties.getStringArray(startID + ".widgets"); if (sMainGroups == null) { System.out.println("NO " + startID + ".widgets!!"); sMainGroups = new String[] {}; } for (int i = 0; i < sMainGroups.length; i++) { String sID = sMainGroups[i]; if (DEBUGLAYOUT) { System.out.println("Container: " + sID); } if (uiInitializer != null) { uiInitializer.increaseProgress(); } linkIDtoParent(skinProperties, sID, sID, null, false, true); } } /** * * * @since 4.0.0.5 */ private void disposeSkin() { numSkins--; for (Iterator iter = mapImageLoaders.values().iterator(); iter.hasNext();) { ImageLoader loader = iter.next(); loader.unLoadImages(); } if (ourSkinProperties) { //skinProperties.dispose(); } } /** * * private void addPaintListenerToAll(Control control) { // XXX: Bug: When paint listener is set to shell, browser widget will flicker on OSX when resizing if (!(control instanceof Shell)) { control.addListener(SWT.Paint, ontopPaintListener); } if (control instanceof Composite) { Composite composite = (Composite) control; Control[] children = composite.getChildren(); for (int i = 0; i < children.length; i++) { addPaintListenerToAll(children[i]); } } } */ public void layout() { if (DEBUGLAYOUT) { System.out.println("==== Start Apply Layout"); } // Apply layout data from skin Object[] values = mapIDsToSOs.values().toArray(); for (int i = 0; i < values.length; i++) { SWTSkinObject[] skinObjects = (SWTSkinObject[]) values[i]; if (skinObjects != null) { for (int j = 0; j < skinObjects.length; j++) { SWTSkinObject skinObject = skinObjects[j]; if (DEBUGLAYOUT) { System.out.println("Apply Layout for " + skinObject); } attachControl(skinObject); } } } // Disabled due to Browser flickering //addPaintListenerToAll(shell); bLayoutComplete = true; int width = skinProperties.getIntValue(startID + ".width", -1); int height = skinProperties.getIntValue(startID + ".height", -1); if (width > 0 && height <= 0) { shell.pack(); shell.setSize(shell.computeSize(width, SWT.DEFAULT)); } for (SWTSkinLayoutCompleteListener l : listenersLayoutComplete) { l.skinLayoutCompleted(); } listenersLayoutComplete.clear(); if (DEBUGLAYOUT) { System.out.println("==== End Apply Layout"); } skinProperties.clearCache(); } /** * @param controlToLayout * @param id */ void attachControl(SWTSkinObject skinObject) { if (skinObject == null) { return; } Control controlToLayout = skinObject.getControl(); if (controlToLayout == null || controlToLayout.isDisposed()) { return; } if (controlToLayout.getData("skin.layedout") != null) { return; } String sConfigID = skinObject.getConfigID(); SWTSkinProperties properties = skinObject.getProperties(); final String[] sDirections = { "top", "bottom", "left", "right" }; // Because layout data is cached, we can't just set the data's properties // We need to create a brand new FormData. Object data = controlToLayout.getLayoutData(); if (data != null && !(data instanceof FormData)) { return; } FormData oldFormData = (FormData) controlToLayout.getLayoutData(); if (oldFormData == null) { oldFormData = new FormData(); } FormData newFormData = new FormData(oldFormData.width, oldFormData.height); String templateID = properties.getStringValue(sConfigID + ".attach.template"); if (templateID == null) { //templateID = skinObject.getSkinObjectID(); } for (int i = 0; i < sDirections.length; i++) { Control control = null; int offset = 0; int percent = 0; String sAlign = null; int align = SWT.DEFAULT; // grab any defaults from existing attachment FormAttachment attachment; switch (i) { case 0: attachment = oldFormData.top; break; case 1: attachment = oldFormData.bottom; break; case 2: attachment = oldFormData.left; break; case 3: attachment = oldFormData.right; break; default: attachment = null; } if (attachment != null) { control = attachment.control; offset = attachment.offset; align = attachment.alignment; // XXX Assumed: Denominator is 100 percent = attachment.numerator; } // parse skin config String suffix = ".attach." + sDirections[i]; String prefix = sConfigID; String[] sParams; sParams = properties.getStringArray(sConfigID + suffix); if (sParams == null && templateID != null) { sParams = properties.getStringArray(templateID + suffix); prefix = templateID; } if (sParams == null) { if (attachment != null) { if (control == null) { attachment = new FormAttachment(percent, offset); } else { attachment = new FormAttachment(control, offset, align); } } } else if (sParams.length == 0 || (sParams.length == 1 && sParams[0].length() == 0)) { attachment = null; } else { if (sParams[0].length() > 0 && Character.isDigit(sParams[0].charAt(0))) { // Percent, Offset try { percent = Integer.parseInt(sParams[0]); } catch (Exception e) { } if (sParams.length > 1) { try { offset = Integer.parseInt(sParams[1]); } catch (Exception e) { } } attachment = new FormAttachment(percent, offset); } else { // Object, Offset, Alignment String sWidget = sParams[0]; SWTSkinObject configSkinObject = getSkinObjectByID(sWidget, skinObject.getParent()); int iNextPos; if (configSkinObject != null) { control = configSkinObject.getControl(); iNextPos = 1; } else { iNextPos = 0; if (sWidget.length() != 0) { System.err.println("ERROR: Trying to attach " + sDirections[i] + " of widget '" + skinObject + "' to non-existant widget '" + sWidget + "'. Attachment Parameters: " + properties.getStringValue(prefix + suffix)); } } for (int j = iNextPos; j < sParams.length; j++) { if (sParams[j].length() > 0) { char c = sParams[j].charAt(0); if (Character.isDigit(c) || c == '-') { try { offset = Integer.parseInt(sParams[j]); } catch (Exception e) { } } else { sAlign = sParams[j]; } } } if (sAlign != null) { align = SWTSkinUtils.getAlignment(sAlign, align); } attachment = new FormAttachment(control, offset, align); } } if (controlToLayout.getData("DEBUG") != null && attachment != null) { if (controlToLayout instanceof Group) { Group group = (Group) controlToLayout; String sValue = properties.getStringValue(prefix + suffix); String sText = group.getText() + "; " + sDirections[i].substring(0, 1) + "=" + (sValue == null ? "(def)" : sValue); if (sText.length() < 20) { group.setText(sText); } group.setToolTipText(sText); } } if (DEBUGLAYOUT) { System.out.println("Attach: " + sConfigID + suffix + ": " + properties.getStringValue(prefix + suffix) + "/" + attachment); } // create new attachment switch (i) { case 0: newFormData.top = attachment; break; case 1: newFormData.bottom = attachment; break; case 2: newFormData.left = attachment; break; case 3: newFormData.right = attachment; break; } } if (Constants.isWindows && (controlToLayout instanceof Browser) && false) { if (newFormData.top != null) { newFormData.top.offset -= 2; } if (newFormData.right != null) { newFormData.right.offset += 2; } if (newFormData.left != null) { newFormData.left.offset -= 2; } if (newFormData.bottom != null) { newFormData.bottom.offset += 2; } } newFormData.height = properties.getIntValue(sConfigID + ".height", newFormData.height); newFormData.width = properties.getIntValue(sConfigID + ".width", newFormData.width); if (!skinObject.getDefaultVisibility()) { if (newFormData.width != 0 && newFormData.height != 0) { controlToLayout.setData("oldSize", new Point(newFormData.width, newFormData.height)); } newFormData.width = 0; newFormData.height = 0; } controlToLayout.setLayoutData(newFormData); controlToLayout.setData("skin.layedout", ""); } private SWTSkinObject createContainer(final SWTSkinProperties properties, String sID, final String sConfigID, SWTSkinObject parentSkinObject, boolean bForceCreate, boolean bPropogate, SWTSkinObject intoSkinObject) { String[] sItems = properties.getStringArray(sConfigID + ".widgets"); final String[] sItemsLater = null; // properties.getStringArray(sConfigID + ".widgets-onshow"); if (sItems == null && sItemsLater == null && !bForceCreate) { return null; } if (DEBUGLAYOUT) { System.out.println("createContainer: " + sID + ";" + properties.getStringValue(sConfigID + ".widgets")); } SWTSkinObject skinObject = getSkinObjectByID(sID, parentSkinObject); if (skinObject == null) { if (intoSkinObject == null) { skinObject = new SWTSkinObjectContainer(this, properties, sID, sConfigID, parentSkinObject); addToControlMap(skinObject); } else { skinObject = intoSkinObject; } } else { if (!(skinObject instanceof SWTSkinObjectContainer)) { return skinObject; } } if (!bPropogate) { bPropogate = properties.getIntValue(sConfigID + ".propogate", 0) == 1; } if (!bPropogate && (parentSkinObject instanceof SWTSkinObjectContainer)) { bPropogate = ((SWTSkinObjectContainer) parentSkinObject).getPropogation(); } if (bPropogate) { ((SWTSkinObjectContainer) skinObject).setPropogation(true); } if (sItems != null) { addContainerChildren(skinObject, sItems, properties); } if (sItemsLater != null) { skinObject.addListener(new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == EVENT_SHOW) { skinObject.removeListener(this); bLayoutComplete = false; addContainerChildren(skinObject, sItemsLater, properties); layout(); } return null; } }); } if (bLayoutComplete) { attachControl(skinObject); } return skinObject; } private void addContainerChildren(SWTSkinObject skinObject, String[] sItems, SWTSkinProperties properties) { String[] paramValues = null; if (properties instanceof SWTSkinPropertiesParam) { paramValues = ((SWTSkinPropertiesParam) properties).getParamValues(); } // Cloning is only for one level. Children get the original properties // object if (properties instanceof SWTSkinPropertiesClone) { properties = ((SWTSkinPropertiesClone) properties).getOriginalProperties(); } // Propogate any parameter values. // XXX This could get ugly, we should could the # of // SWTSkinPropertiesParam to determine if this needs optimizing // ie. if a top container has paramValues, every child will get a new // object. How would this affect memory/performace? if (paramValues != null) { properties = new SWTSkinPropertiesParamImpl(properties, paramValues); } for (int i = 0; i < sItems.length; i++) { String sItemID = sItems[i]; linkIDtoParent(properties, sItemID, sItemID, skinObject, false, true); } } private SWTSkinObject createSash(SWTSkinProperties properties, String sID, String sConfigID, SWTSkinObject parentSkinObject, final boolean bVertical) { int style = bVertical ? SWT.VERTICAL : SWT.HORIZONTAL; final String[] sItems = properties.getStringArray(sConfigID + ".widgets"); SWTSkinObject skinObject; Composite createOn; if (parentSkinObject == null) { createOn = shell; } else { createOn = (Composite) parentSkinObject.getControl(); } if (sItems == null) { // No widgets, so it's a sash Sash sash = new Sash(createOn, style); skinObject = new SWTSkinObjectBasic(this, properties, sash, sID, sConfigID, "sash", parentSkinObject); addToControlMap(skinObject); sash.setBackground(sash.getDisplay().getSystemColor(SWT.COLOR_RED)); sash.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { Sash sash = (Sash) e.widget; final boolean FASTDRAG = true; if (FASTDRAG && e.detail == SWT.DRAG) { return; } Rectangle parentArea = sash.getParent().getClientArea(); FormData formData = (FormData) sash.getLayoutData(); formData.left = new FormAttachment(e.x * 100 / parentArea.width); sash.getParent().layout(); } }); } else { // Widgets exist, so use a SashForm to split them final SashForm sashForm = new SashForm(createOn, style); skinObject = new SWTSkinObjectContainer(this, properties, sashForm, sID, sConfigID, "sash", parentSkinObject); addToControlMap(skinObject); int iSashWidth = properties.getIntValue(sConfigID + ".sash.width", -1); if (iSashWidth > 0) { sashForm.SASH_WIDTH = iSashWidth; } for (int i = 0; i < sItems.length; i++) { String sChildID = sItems[i]; linkIDtoParent(properties, sChildID, sChildID, skinObject, false, true); } } if (bLayoutComplete) { attachControl(skinObject); } return skinObject; } private SWTSkinObject createMySash(SWTSkinProperties properties, final String sID, String sConfigID, String[] typeParams, SWTSkinObject parentSkinObject, final boolean bVertical) { SWTSkinObject skinObject = new SWTSkinObjectSash(this, properties, sID, sConfigID, typeParams, parentSkinObject, bVertical); addToControlMap(skinObject); if (bLayoutComplete) { attachControl(skinObject); } return skinObject; } /** * Create a tab using a template. *

    * (objectid).view.template.(sTemplateKey)=(Reference to Template skin object) * * @param sID ID to give the new tab * @param sTemplateKey Template Key to read to get the tab's template skin object * @param tabHolder Where to read the template key from * * @return The new tab, or null if tab could not be created */ public SWTSkinObjectTab createTab(String sID, String sTemplateKey, SWTSkinObject tabHolder) { String sTemplateID = SWTSkinTabSet.getTemplateID(this, tabHolder, sTemplateKey); if (sTemplateID == null) { return null; } SWTSkinObject skinObject = linkIDtoParent(skinProperties, sID, sTemplateID, tabHolder, true, true); // SWTSkinObjectTab skinObject = _createTab(skinProperties, sID, sTemplateID, // tabHolder); if (bLayoutComplete && skinObject != null) { ((Composite) skinObject.getControl()).getParent().layout(true); } if (skinObject instanceof SWTSkinObjectTab) { return (SWTSkinObjectTab) skinObject; } System.err.println(skinObject + " not a SWTSkinObjectTab! Template: " + sTemplateID); return null; } /** * @param configID */ private SWTSkinObjectTab _createTab(SWTSkinProperties properties, String sID, String sConfigID, SWTSkinObject parentSkinObject) { //System.out.println("createTab " + sID + ", " + sConfigID + ", " + sParentID); SWTSkinObjectTab skinObjectTab = new SWTSkinObjectTab(this, properties, sID, sConfigID, parentSkinObject); createContainer(properties, sID, sConfigID, parentSkinObject, true, true, skinObjectTab); addToControlMap(skinObjectTab); String sTabSet = properties.getStringValue(sConfigID + ".tabset", "default"); SWTSkinTabSet tabset = mapTabSetToControls.get(sTabSet); if (tabset == null) { tabset = new SWTSkinTabSet(this, sTabSet); mapTabSetToControls.put(sTabSet, tabset); if (DEBUGLAYOUT) { System.out.println("New TabSet: " + sTabSet); } } tabset.addTab(skinObjectTab); if (DEBUGLAYOUT) { System.out.println("Tab " + sID + " added"); } if (bLayoutComplete) { attachControl(skinObjectTab); } return skinObjectTab; } private SWTSkinObject createTextLabel(SWTSkinProperties properties, String sID, String sConfigID, String[] typeParams, SWTSkinObject parentSkinObject) { SWTSkinObject skinObject = new SWTSkinObjectText2(this, properties, sID, sConfigID, typeParams, parentSkinObject); addToControlMap(skinObject); if (bLayoutComplete) { attachControl(skinObject); } return skinObject; } private SWTSkinObject createSlider(SWTSkinProperties properties, String sID, String sConfigID, String[] typeParams, SWTSkinObject parentSkinObject) { SWTSkinObject skinObject = new SWTSkinObjectSlider(this, properties, sID, sConfigID, typeParams, parentSkinObject); addToControlMap(skinObject); if (bLayoutComplete) { attachControl(skinObject); } return skinObject; } public Shell getShell() { return shell; } // private void createTextWidget(final String sConfigID) { // SWTSkinObject parent = getParent(sConfigID); // if (parent == null) { // return; // } // // SWTTextPaintListener listener = new SWTTextPaintListener(this, parent.getControl(), // sConfigID); // parent.getControl().addPaintListener(listener); // // //addToControlMap(listener, sConfigID); // // return; // } /* Used for dumpObjectsOnly private String getAttachLine(FormAttachment attach) { String s = ""; if (attach.control != null) { s += attach.control.getData("ConfigID"); if (attach.offset != 0 || attach.alignment != SWT.DEFAULT) { s += "," + attach.offset; } if (attach.alignment != SWT.DEFAULT) { if (attach.alignment == SWT.LEFT) { s += ",left"; } else if (attach.alignment == SWT.RIGHT) { s += ",right"; } else if (attach.alignment == SWT.TOP) { s += ",top"; } else if (attach.alignment == SWT.BOTTOM) { s += ",bottom"; } else if (attach.alignment == SWT.CENTER) { s += ",center"; } } } else { s += (int) (100.0 * attach.numerator / attach.denominator) + "," + attach.offset; } return s; } */ protected Listener getHandCursorListener(Display display) { if (handCursorListener == null) { final Cursor handCursor = new Cursor(display, SWT.CURSOR_HAND); handCursorListener = new Listener() { public void handleEvent(Event event) { if (event.type == SWT.MouseEnter) { ((Control) event.widget).setCursor(handCursor); } if (event.type == SWT.MouseExit) { ((Control) event.widget).setCursor(null); } } }; } return handCursorListener; } public SWTSkinObject createSkinObject(String sID, String sConfigID, SWTSkinObject parentSkinObject) { return createSkinObject(sID, sConfigID, parentSkinObject, null); } /** * Create a skin object based off an existing config "template" * * @param sID ID of new skin object * @param sConfigID config id to use to create new skin object * @param parentSkinObject location to place new skin object in * * @return new skin object */ public SWTSkinObject createSkinObject(String sID, String sConfigID, SWTSkinObject parentSkinObject, Object creationParams) { SWTSkinObject skinObject = null; Cursor cursor = shell.getCursor(); try { shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); boolean b = bLayoutComplete; bLayoutComplete = false; skinObject = linkIDtoParent(skinProperties, sID, sConfigID, parentSkinObject, true, true, creationParams); if (b && skinObject != null) { layout(); Control control = skinObject.getParent().getControl(); if (control instanceof Composite) { ((Composite) control).layout(true); } } bLayoutComplete = b; } catch (Exception e) { Debug.out("Trying to create " + sID + "." + sConfigID + " on " + parentSkinObject, e); } finally { shell.setCursor(cursor); } return skinObject; } public void addSkinObject(SWTSkinObject skinObject) { String sViewID = skinObject.getViewID(); if (sViewID != null) { setSkinObjectViewID(skinObject, sViewID); } attachControl(skinObject); } /** * @param skinObject * * @since 3.0.1.3 */ public void removeSkinObject(SWTSkinObject skinObject) { skinObject.triggerListeners(SWTSkinObjectListener.EVENT_DESTROY); String id = skinObject.getSkinObjectID(); mon_MapIDsToSOs.enter(); try { SWTSkinObject[] objects = mapIDsToSOs.get(id); if (objects != null) { int x = 0; for (int i = 0; i < objects.length; i++) { if (objects[i] != skinObject) { objects[x++] = objects[i]; } } SWTSkinObject[] newObjects = new SWTSkinObject[x]; System.arraycopy(objects, 0, newObjects, 0, x); mapIDsToSOs.put(id, newObjects); } } finally { mon_MapIDsToSOs.exit(); } mon_mapPublicViewIDsToSOs.enter(); try { id = skinObject.getViewID(); SWTSkinObject[] objects = mapPublicViewIDsToSOs.get(id); if (objects != null) { int x = 0; for (int i = 0; i < objects.length; i++) { if (objects[i] != skinObject) { objects[x++] = objects[i]; } } SWTSkinObject[] newObjects = new SWTSkinObject[x]; System.arraycopy(objects, 0, newObjects, 0, x); mapPublicViewIDsToSOs.put(id, newObjects); } } finally { mon_mapPublicViewIDsToSOs.exit(); } skinObject.dispose(); } private SWTSkinObject linkIDtoParent(SWTSkinProperties properties, String sID, String sConfigID, SWTSkinObject parentSkinObject, boolean bForceCreate, boolean bAddView) { return linkIDtoParent(properties, sID, sConfigID, parentSkinObject, bForceCreate, bAddView, null); } private SWTSkinObject linkIDtoParent(SWTSkinProperties properties, String sID, String sConfigID, SWTSkinObject parentSkinObject, boolean bForceCreate, boolean bAddView, Object creationParams) { currentSkinObjectcreationCount++; SWTSkinObject skinObject = null; try { if (sConfigID == null) { return null; } String[] sTypeParams = properties.getStringArray(sConfigID + ".type"); String sType; if (sTypeParams != null && sTypeParams.length > 0) { sType = sTypeParams[0]; bForceCreate = true; } else { // no type, use best guess sType = null; String sImageLoc = properties.getStringValue(sConfigID); if (sImageLoc != null) { sType = "image"; } else { String sText = properties.getStringValue(sConfigID + ".text"); if (sText != null) { sType = "text"; } else { String sWidgets = properties.getStringValue(sConfigID + ".widgets"); if (sWidgets != null || bForceCreate) { sType = "container"; } } } if (sType == null) { if (DEBUGLAYOUT) { System.err.println("no type defined for " + sConfigID); } return null; } sTypeParams = new String[] { sType }; } if (sType.equals("image")) { skinObject = createImageLabel(properties, sID, sConfigID, null, sTypeParams, parentSkinObject); } else if (sType.equals("image2")) { skinObject = createImageLabel2(properties, sID, parentSkinObject); } else if (sType.equals("container2")) { skinObject = createContainer2(properties, sID, sConfigID, parentSkinObject, bForceCreate, false, null); } else if (sType.equals("container")) { skinObject = createContainer(properties, sID, sConfigID, parentSkinObject, bForceCreate, false, null); } else if (sType.equals("text")) { skinObject = createTextLabel(properties, sID, sConfigID, sTypeParams, parentSkinObject); } else if (sType.equals("tab")) { skinObject = _createTab(properties, sID, sConfigID, parentSkinObject); } else if (sType.equals("v-sash")) { skinObject = createSash(properties, sID, sConfigID, parentSkinObject, true); } else if (sType.equals("h-sash")) { skinObject = createSash(properties, sID, sConfigID, parentSkinObject, false); } else if (sType.equals("v-mysash")) { skinObject = createMySash(properties, sID, sConfigID, sTypeParams, parentSkinObject, true); } else if (sType.equals("h-mysash")) { skinObject = createMySash(properties, sID, sConfigID, sTypeParams, parentSkinObject, false); } else if (sType.equals("clone")) { skinObject = createClone(properties, sID, sConfigID, sTypeParams, parentSkinObject); } else if (sType.equals("slider")) { skinObject = createSlider(properties, sID, sConfigID, sTypeParams, parentSkinObject); } else if (sType.equals("hidden")) { return null; } else if (sType.equals("browser")) { skinObject = createBrowser(properties, sID, sConfigID, parentSkinObject); } else if (sType.equals("separator")) { skinObject = createSeparator(properties, sID, sConfigID, sTypeParams, parentSkinObject); } else if (sType.equals("button")) { skinObject = createButton(properties, sID, sConfigID, sTypeParams, parentSkinObject); } else if (sType.equals("checkbox")) { skinObject = createCheckbox(properties, sID, sConfigID, sTypeParams, parentSkinObject); } else { System.err.println(sConfigID + ": Invalid type of " + sType); } skinObject.setData("CreationParams", creationParams); if (bAddView) { String sViewID = skinObject.getViewID(); if (sViewID != null) { setSkinObjectViewID(skinObject, sViewID); } } if (bLayoutComplete) { attachControl(skinObject); } } catch (Exception e) { e.printStackTrace(); } finally { currentSkinObjectcreationCount--; } if (skinObject != null) { skinObject.triggerListeners(SWTSkinObjectListener.EVENT_CREATED); } return skinObject; } /** * @param properties * @param sid * @param configID * @param typeParams * @param parentSkinObject * @return * * @since 3.1.1.1 */ private SWTSkinObject createButton(SWTSkinProperties properties, String id, String configID, String[] typeParams, SWTSkinObject parentSkinObject) { SWTSkinObject skinObject = new SWTSkinObjectButton(this, properties, id, configID, parentSkinObject); addToControlMap(skinObject); if (bLayoutComplete) { attachControl(skinObject); } return skinObject; } private SWTSkinObject createCheckbox(SWTSkinProperties properties, String id, String configID, String[] typeParams, SWTSkinObject parentSkinObject) { SWTSkinObject skinObject = new SWTSkinObjectCheckbox(this, properties, id, configID, parentSkinObject); addToControlMap(skinObject); if (bLayoutComplete) { attachControl(skinObject); } return skinObject; } /** * @param properties * @param sid * @param sConfigID * @param parentSkinObject * @return */ private SWTSkinObject createBrowser(SWTSkinProperties properties, String sID, String sConfigID, SWTSkinObject parentSkinObject) { SWTSkinObject skinObject = new SWTSkinObjectBrowser(this, properties, sID, sConfigID, parentSkinObject); addToControlMap(skinObject); if (bLayoutComplete) { attachControl(skinObject); } return skinObject; } private SWTSkinObject createClone(SWTSkinProperties properties, String sID, String sConfigID, String[] typeParams, SWTSkinObject parentSkinObject) { //System.out.println("Create Clone " + sID + " == " + sConfigID + " for " + parentSkinObject); if (sConfigID == "") { System.err.println("XXXXXXXX " + sID + " has no config ID.." + Debug.getStackTrace(false, false)); } String[] sCloneParams; if (typeParams.length > 1) { int size = typeParams.length - 1; sCloneParams = new String[size]; System.arraycopy(typeParams, 1, sCloneParams, 0, size); } else { sCloneParams = properties.getStringArray(sConfigID + ".clone"); if (sCloneParams == null || sCloneParams.length < 1) { return null; } } if (properties instanceof SWTSkinPropertiesClone) { properties = ((SWTSkinPropertiesClone) properties).getOriginalProperties(); } //System.out.println(sCloneParams[0]); SWTSkinPropertiesClone cloneProperties = new SWTSkinPropertiesClone( properties, sConfigID, sCloneParams); return linkIDtoParent(cloneProperties, sID, "", parentSkinObject, false, false); } private SWTSkinObject createImageLabel(SWTSkinProperties properties, String sID, String sConfigID, String sImageID, String[] typeParams, SWTSkinObject parentSkinObject) { if (sImageID == null) { sImageID = sConfigID; if (typeParams.length > 1) { properties.addProperty(sConfigID + ".image", typeParams[1]); sImageID = typeParams[1]; } } SWTSkinObjectImage skinObject = new SWTSkinObjectImage(this, properties, sID, sConfigID, sImageID, parentSkinObject); addToControlMap(skinObject); return skinObject; } private SWTSkinObject createContainer2(SWTSkinProperties properties, String sID, final String sConfigID, SWTSkinObject parentSkinObject, boolean bForceCreate, boolean bPropogate, SWTSkinObject intoSkinObject) { String[] sItems = properties.getStringArray(sConfigID + ".widgets"); if (sItems == null && !bForceCreate) { return null; } if (DEBUGLAYOUT) { System.out.println("createContainer: " + sID + ";" + properties.getStringValue(sConfigID + ".widgets")); } SWTSkinObject skinObject = getSkinObjectByID(sID, parentSkinObject); if (skinObject == null) { if (intoSkinObject == null) { //skinObject = new SWTSkinObjectImageContainer(this, properties, sID, // sConfigID, parentSkinObject); addToControlMap(skinObject); } else { skinObject = intoSkinObject; } } else { if (!(skinObject instanceof SWTSkinObjectContainer)) { return skinObject; } } if (!bPropogate) { bPropogate = properties.getIntValue(sConfigID + ".propogate", 0) == 1; } if (!bPropogate && (parentSkinObject instanceof SWTSkinObjectContainer)) { bPropogate = ((SWTSkinObjectContainer) parentSkinObject).getPropogation(); } if (bPropogate) { ((SWTSkinObjectContainer) skinObject).setPropogation(true); } if (sItems != null) { String[] paramValues = null; if (properties instanceof SWTSkinPropertiesParam) { paramValues = ((SWTSkinPropertiesParam) properties).getParamValues(); } // Cloning is only for one level. Children get the original properties // object if (properties instanceof SWTSkinPropertiesClone) { properties = ((SWTSkinPropertiesClone) properties).getOriginalProperties(); } // Propogate any parameter values. // XXX This could get ugly, we should could the # of // SWTSkinPropertiesParam to determine if this needs optimizing // ie. if a top container has paramValues, every child will get a new // object. How would this affect memory/performace? if (paramValues != null) { properties = new SWTSkinPropertiesParamImpl(properties, paramValues); } for (int i = 0; i < sItems.length; i++) { String sItemID = sItems[i]; linkIDtoParent(properties, sItemID, sItemID, skinObject, false, true); } } if (bLayoutComplete) { attachControl(skinObject); } return skinObject; } private SWTSkinObject createImageLabel2(SWTSkinProperties properties, final String sConfigID, SWTSkinObject parentSkinObject) { Composite createOn; if (parentSkinObject == null) { createOn = shell; } else { createOn = (Composite) parentSkinObject.getControl(); } final Canvas drawable = new Canvas(createOn, SWT.NO_BACKGROUND); drawable.setVisible(false); final ImageLoader imageLoader = getImageLoader(properties); Image image = imageLoader.getImage(sConfigID); if (ImageLoader.isRealImage(image)) { imageLoader.releaseImage(sConfigID); image = imageLoader.getImage(sConfigID + ".image"); drawable.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { imageLoader.releaseImage(sConfigID + ".image"); } }); } else { drawable.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { imageLoader.releaseImage(sConfigID); } }); } drawable.setData("image", image); SWTSkinObjectBasic skinObject = new SWTSkinObjectBasic(this, properties, drawable, sConfigID, sConfigID, "image", parentSkinObject); addToControlMap(skinObject); ontopImages.add(skinObject); return skinObject; } private SWTSkinObject createSeparator(SWTSkinProperties properties, String sID, String sConfigID, String[] typeParams, SWTSkinObject parentSkinObject) { SWTSkinObject skinObject = new SWTSkinObjectSeparator(this, properties, sID, sConfigID, parentSkinObject); addToControlMap(skinObject); if (bLayoutComplete) { attachControl(skinObject); } return skinObject; } public SWTSkinProperties getSkinProperties() { return skinProperties; } public void addListener(String viewID, SWTSkinObjectListener listener) { mapPublicViewIDsToListeners_mon.enter(); try { Object existing = mapPublicViewIDsToListeners.get(viewID); if (existing instanceof List) { List list = (List) existing; list.add(listener); } else { ArrayList list = new ArrayList(); list.add(listener); mapPublicViewIDsToListeners.put(viewID, list); } } finally { mapPublicViewIDsToListeners_mon.exit(); } } public void removeListener(String viewID, SWTSkinObjectListener listener) { mapPublicViewIDsToListeners_mon.enter(); try { Object existing = mapPublicViewIDsToListeners.get(viewID); if (existing instanceof List) { List list = (List) existing; list.remove(listener); } } finally { mapPublicViewIDsToListeners_mon.exit(); } } public SWTSkinObjectListener[] getSkinObjectListeners(String viewID) { if (viewID == null) { return NOLISTENERS; } mapPublicViewIDsToListeners_mon.enter(); try { ArrayList existing = mapPublicViewIDsToListeners.get(viewID); if (existing != null) { return existing.toArray(NOLISTENERS); } return NOLISTENERS; } finally { mapPublicViewIDsToListeners_mon.exit(); } } public boolean isLayoutComplete() { return bLayoutComplete; } public void addListener(SWTSkinLayoutCompleteListener l) { if (!listenersLayoutComplete.contains(l)) { listenersLayoutComplete.add(l); } } public static void main(String[] args) { java.util.Date d = new java.util.Date(); long t = d.getTime(); t -= (1156 * 24 * 60 * 60 * 1000l); t -= (6 * 60 * 60 * 1000l); t -= (17 * 60 * 1000l); Date then = new Date(t); System.out.println(d + ";" + then); } public boolean isCreatingSO() { return currentSkinObjectcreationCount > 0; } /** * * * @since 3.1.1.1 */ public void triggerLanguageChange() { Object[] values = mapIDsToSOs.values().toArray(); for (int i = 0; i < values.length; i++) { SWTSkinObject[] skinObjects = (SWTSkinObject[]) values[i]; if (skinObjects != null) { for (int j = 0; j < skinObjects.length; j++) { SWTSkinObject so = skinObjects[j]; so.triggerListeners(SWTSkinObjectListener.EVENT_LANGUAGE_CHANGE); } } } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinProperties.java0000644000175000017500000000264111051462662025172 0ustar adrianadrian/* * Created on Jun 26, 2006 7:28:15 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; import org.eclipse.swt.graphics.Color; import com.aelitis.azureus.ui.skin.SkinProperties; /** * Extends SkinProperties with SWT specific methods * * @author TuxPaper * @created Jun 26, 2006 * */ public interface SWTSkinProperties extends SkinProperties { /** * Retrieve a color property in as a SWT Color * @param name Property Name * @return a Color, or null */ public Color getColor(String name); public Color getColor(String name, Color def); }azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText1.java0000644000175000017500000002102111223315754025163 0ustar adrianadrian/* * Created on Jun 26, 2006 12:46:42 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; import java.text.NumberFormat; import java.text.ParseException; import java.util.Locale; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; /** * Text Skin Object. This one uses a label widget. * * @author TuxPaper * @created Jun 26, 2006 * */ public class SWTSkinObjectText1 extends SWTSkinObjectBasic implements SWTSkinObjectText { String sText; String sKey; boolean bIsTextDefault = false; Label label; private int style; public SWTSkinObjectText1(SWTSkin skin, SWTSkinProperties skinProperties, String sID, String sConfigID, String[] typeParams, SWTSkinObject parent) { super(skin, skinProperties, sID, sConfigID, "text", parent); style = SWT.WRAP; String sAlign = skinProperties.getStringValue(sConfigID + ".align"); if (sAlign != null) { int align = SWTSkinUtils.getAlignment(sAlign, SWT.NONE); if (align != SWT.NONE) { style |= align; } } if (skinProperties.getIntValue(sConfigID + ".border", 0) == 1) { style |= SWT.BORDER; } Composite createOn; if (parent == null) { createOn = skin.getShell(); } else { createOn = (Composite) parent.getControl(); } boolean bKeepMaxSize = properties.getStringValue( sConfigID + ".keepMaxSize", "").equals("1"); label = bKeepMaxSize ? new LabelNoShrink(createOn, style) : new Label( createOn, style); setControl(label); if (typeParams.length > 1) { bIsTextDefault = true; sText = typeParams[1]; label.setText(sText); } } public String switchSuffix(String suffix, int level, boolean walkUp, boolean walkDown) { suffix = super.switchSuffix(suffix, level, walkUp, walkDown); if (suffix == null) { return null; } String sPrefix = sConfigID + ".text"; if (sText == null || bIsTextDefault) { String text = properties.getStringValue(sPrefix + suffix); if (text != null) { label.setText(text); } } Color color = properties.getColor(sPrefix + ".color" + suffix); //System.out.println(this + "; " + sPrefix + ";" + suffix + "; " + color + "; " + text); if (color != null) { label.setForeground(color); } Font existingFont = (Font) label.getData("Font" + suffix); if (existingFont != null && !existingFont.isDisposed()) { label.setFont(existingFont); } else { boolean bNewFont = false; int iFontSize = -1; int iFontWeight = -1; String sFontFace = null; String sSize = properties.getStringValue(sPrefix + ".size" + suffix); if (sSize != null) { FontData[] fd = label.getFont().getFontData(); try { char firstChar = sSize.charAt(0); if (firstChar == '+' || firstChar == '-') { sSize = sSize.substring(1); } int iSize = NumberFormat.getInstance(Locale.US).parse(sSize).intValue(); if (firstChar == '+') { iFontSize = (int) (fd[0].height + iSize); } else if (firstChar == '-') { iFontSize = (int) (fd[0].height - iSize); } else { iFontSize = iSize; } if (sSize.endsWith("px")) { iFontSize = Utils.getFontHeightFromPX(label.getFont(), null, iSize); } bNewFont = true; } catch (NumberFormatException e) { e.printStackTrace(); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } } String sStyle = properties.getStringValue(sPrefix + ".style" + suffix); if (sStyle != null) { String[] sStyles = sStyle.toLowerCase().split(","); for (int i = 0; i < sStyles.length; i++) { String s = sStyles[i]; if (s.equals("bold")) { if (iFontWeight == -1) { iFontWeight = SWT.BOLD; } else { iFontWeight |= SWT.BOLD; } bNewFont = true; } if (s.equals("italic")) { if (iFontWeight == -1) { iFontWeight = SWT.ITALIC; } else { iFontWeight |= SWT.ITALIC; } bNewFont = true; } if (s.equals("underline")) { label.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { Point size = ((Control) e.widget).getSize(); e.gc.drawLine(0, size.y - 1, size.x - 1, size.y - 1); } }); } if (s.equals("strike")) { label.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { Point size = ((Control) e.widget).getSize(); int y = size.y / 2; e.gc.drawLine(0, y, size.x - 1, y); } }); } } } sFontFace = properties.getStringValue(sPrefix + ".font" + suffix); if (sFontFace != null) { bNewFont = true; } if (bNewFont) { FontData[] fd = label.getFont().getFontData(); if (iFontSize > 0) { fd[0].setHeight(iFontSize); } if (iFontWeight >= 0) { fd[0].setStyle(iFontWeight); } if (sFontFace != null) { fd[0].setName(sFontFace); } final Font labelFont = new Font(label.getDisplay(), fd); label.setFont(labelFont); label.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { labelFont.dispose(); } }); label.setData("Font" + suffix, labelFont); } } label.update(); return suffix; } /** * @param searchText */ public void setText(String text) { if (text == null) { text = ""; } if (text.equals(sText)) { return; } this.sText = text; this.sKey = null; bIsTextDefault = false; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (label != null && !label.isDisposed()) { label.setText(sText); Utils.relayout(label); } } }); } public void setTextID(final String key) { if (key == null) { setText(""); } else if (key.equals(sKey)) { return; } this.sText = MessageText.getString(key); this.sKey = key; bIsTextDefault = false; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (label != null && !label.isDisposed()) { Messages.setLanguageText(label, key); Utils.relayout(label); } } }); } public void setTextID(final String key, final String[] params) { if (key == null) { setText(""); } else if (key.equals(sKey)) { return; } this.sText = MessageText.getString(key); this.sKey = key; bIsTextDefault = false; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (label != null && !label.isDisposed()) { Messages.setLanguageText(label, key, params); Utils.relayout(label); } } }); } private class LabelNoShrink extends Label { Point ptMax; /** * Default Constructor * * @param parent * @param style */ public LabelNoShrink(Composite parent, int style) { super(parent, style | SWT.CENTER); ptMax = new Point(0, 0); } // I know what I'm doing. Maybe ;) public void checkSubclass() { } public Point computeSize(int wHint, int hHint, boolean changed) { Point pt = super.computeSize(wHint, hHint, changed); if (pt.x > ptMax.x) { ptMax.x = pt.x; } if (pt.y > ptMax.y) { ptMax.y = pt.y; } return ptMax; } } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectText#getStyle() public int getStyle() { return style; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectText#setStyle(int) public void setStyle(int style) { this.style = style; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectText#getText() public String getText() { return sText; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTBGImagePainter.java0000644000175000017500000004327211130557174024775 0ustar adrianadrian/** * */ package com.aelitis.azureus.ui.swt.skin; import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author TuxPaper * @created Jun 8, 2006 * */ public class SWTBGImagePainter implements Listener { private static boolean DEBUG = false; private static boolean TEST_SWT_PAINTING = false; //Constants.isOSX; private Rectangle lastResizeRect = Utils.EMPTY_RECT; private final Shell shell; private String imgSrcID; private String imgSrcLeftID; private String imgSrcRightID; private Image imgSrc; private Image imgSrcLeft; private Image imgSrcRight; private Rectangle imgSrcBounds; private Rectangle imgSrcLeftBounds; private Rectangle imgSrcRightBounds; private Image lastImage = null; boolean inEvent = false; Rectangle lastBounds = Utils.EMPTY_RECT; Point lastShellBGSize = new Point(0, 0); private final int tileMode; private final Control control; private boolean bDirty; private int fdWidth = -1; private int fdHeight = -1; private ImageLoader imageLoader = null; private SWTBGImagePainter(Control control, int tileMode) { this.control = control; this.shell = control.getShell(); this.tileMode = tileMode; control.setData("BGPainter", this); } public SWTBGImagePainter(Control control, Image bgImage, int tileMode) { this(control, null, null, bgImage, tileMode); } public SWTBGImagePainter(Control control, Image bgImageLeft, Image bgImageRight, Image bgImage, int tileMode) { this(control, tileMode); setImages(bgImageLeft, bgImageRight, bgImage); if (bDirty) { if (control.isVisible()) { buildBackground(control); } } if (!TEST_SWT_PAINTING) { control.addListener(SWT.Resize, this); control.addListener(SWT.Paint, this); control.getShell().addListener(SWT.Show, this); } control.addListener(SWT.Dispose, this); } public SWTBGImagePainter(Control control, ImageLoader imageLoader, String bgImageLeftId, String bgImageRightId, String bgImageId, int tileMode) { this(control, tileMode); setImage(imageLoader, bgImageLeftId, bgImageRightId, bgImageId); if (bDirty) { if (control.isVisible()) { buildBackground(control); } } if (!TEST_SWT_PAINTING) { control.addListener(SWT.Resize, this); control.addListener(SWT.Paint, this); control.getShell().addListener(SWT.Show, this); } control.addListener(SWT.Dispose, this); } public void dispose() { if (control == null || control.isDisposed()) { return; } if (!TEST_SWT_PAINTING) { control.removeListener(SWT.Resize, this); control.removeListener(SWT.Paint, this); control.getShell().removeListener(SWT.Show, this); } control.removeListener(SWT.Dispose, this); control.setBackgroundImage(null); FormData formData = (FormData) control.getLayoutData(); formData.width = SWT.DEFAULT; formData.height = SWT.DEFAULT; control.setData("BGPainter", null); } /** * @param bgImageLeft * @param bgImageRight * @param bgImage */ public void setImage(Image bgImageLeft, Image bgImageRight, Image bgImage) { setImages(bgImageLeft, bgImageRight, bgImage); if (bDirty) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (!control.isVisible()) { return; } buildBackground(control); } }); } } public void setImage(ImageLoader imageLoader, String idLeft, String idRight, String id) { setImages(imageLoader, idLeft, idRight, id); if (bDirty) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (!control.isVisible()) { return; } buildBackground(control); } }); } } private boolean imagesEqual(Image image1, Image image2) { if (image1 == image2) { return true; } if (!ImageLoader.isRealImage(image1) && !ImageLoader.isRealImage(image2)) { return true; } return false; } private void setImages(Image bgImageLeft, Image bgImageRight, Image bgImage) { if (imagesEqual(imgSrc, bgImage) && imagesEqual(imgSrcLeft, bgImageLeft) && imagesEqual(imgSrcRight, bgImageRight)) { if (DEBUG) { System.out.println("same"); } return; } imgSrcLeftID = null; imgSrcRightID = null; imgSrcID = null; if (DEBUG) { System.out.println("SI " + bgImageLeft + ";" + bgImageRight + ";" + bgImage + ";" + control.getData("SkinObject") + "/" + control.isVisible() + control.getSize() + "\\" + Debug.getStackTrace(true, false)); } imgSrc = bgImage; if (imgSrc != null) { imgSrcBounds = imgSrc.getBounds(); } lastShellBGSize = new Point(0, 0); if (ImageLoader.isRealImage(bgImageLeft)) { imgSrcLeft = bgImageLeft; imgSrcLeftBounds = imgSrcLeft.getBounds(); } else { imgSrcLeft = null; imgSrcLeftBounds = Utils.EMPTY_RECT; } if (ImageLoader.isRealImage(bgImageRight)) { imgSrcRight = bgImageRight; imgSrcRightBounds = imgSrcRight.getBounds(); } else { imgSrcRight = null; imgSrcRightBounds = Utils.EMPTY_RECT; } if (TEST_SWT_PAINTING) { control.removeListener(SWT.Resize, this); control.removeListener(SWT.Paint, this); if (imgSrcRight == null && imgSrcLeft == null && tileMode == SWTSkinUtils.TILE_NONE) { control.setBackgroundImage(imgSrc); } else { control.addListener(SWT.Resize, this); control.addListener(SWT.Paint, this); bDirty = true; buildBackground(control); } } else { bDirty = true; } if ((tileMode & SWTSkinUtils.TILE_BOTH) != SWTSkinUtils.TILE_BOTH) { int width = SWT.DEFAULT; int height = SWT.DEFAULT; if (tileMode == SWTSkinUtils.TILE_Y || tileMode == SWTSkinUtils.TILE_NONE) { width = imgSrcBounds.width + imgSrcLeftBounds.width + imgSrcRightBounds.width; } if (tileMode == SWTSkinUtils.TILE_X || tileMode == SWTSkinUtils.TILE_NONE) { height = imgSrcBounds.height; } FormData fd = (FormData) control.getLayoutData(); if (fd == null) { fd = new FormData(); } if (fd.width == fdWidth || fd.height == fdHeight) { if (fd.width == fdWidth) { fdWidth = fd.width = width; } if (fd.height == fdHeight) { fdHeight = fd.height = height; } control.setLayoutData(fd); if (control.isVisible()) { bDirty = true; control.getParent().layout(true, true); } } } } /** * @param bgImageLeftId * @param bgImageRightId * @param bgImageId * * @since 4.0.0.5 */ public void setImages(ImageLoader imageLoader, String bgImageLeftId, String bgImageRightId, String bgImageId) { this.imageLoader = imageLoader; imgSrcLeftID = bgImageLeftId; imgSrcRightID = bgImageRightId; imgSrcID = bgImageId; imgSrcLeftBounds = Utils.EMPTY_RECT; imgSrcRightBounds = Utils.EMPTY_RECT; if (imgSrcID != null) { Image imgSrc = imageLoader.getImage(imgSrcID); imgSrcBounds = imgSrc.getBounds(); imageLoader.releaseImage(imgSrcID); } Image imgSrcLeft = imageLoader.getImage(imgSrcLeftID); if (ImageLoader.isRealImage(imgSrcLeft)) { imgSrcLeftBounds = imgSrcLeft.getBounds(); } imageLoader.releaseImage(imgSrcLeftID); Image imgSrcRight = imageLoader.getImage(imgSrcRightID); if (ImageLoader.isRealImage(imgSrcRight)) { imgSrcRightBounds = imgSrcRight.getBounds(); } imageLoader.releaseImage(imgSrcRightID); if (TEST_SWT_PAINTING) { control.removeListener(SWT.Resize, this); control.removeListener(SWT.Paint, this); control.addListener(SWT.Resize, this); control.addListener(SWT.Paint, this); bDirty = true; buildBackground(control); } else { bDirty = true; } if ((tileMode & SWTSkinUtils.TILE_BOTH) != SWTSkinUtils.TILE_BOTH) { int width = SWT.DEFAULT; int height = SWT.DEFAULT; if (tileMode == SWTSkinUtils.TILE_Y || tileMode == SWTSkinUtils.TILE_NONE) { width = imgSrcBounds.width + imgSrcLeftBounds.width + imgSrcRightBounds.width; } if (tileMode == SWTSkinUtils.TILE_X || tileMode == SWTSkinUtils.TILE_NONE) { height = imgSrcBounds.height; } FormData fd = (FormData) control.getLayoutData(); if (fd == null) { fd = new FormData(); } if (fd.width == fdWidth || fd.height == fdHeight) { if (fd.width == fdWidth) { fdWidth = fd.width = width; } if (fd.height == fdHeight) { fdHeight = fd.height = height; } control.setLayoutData(fd); if (control.isVisible()) { bDirty = true; control.getParent().layout(true, true); } } } } public void buildBackground(Control control) { if (inEvent || shell == null || shell.isDisposed() || control == null || control.isDisposed()) { return; } //System.out.println("BB: " + control.getData("ConfigID")); inEvent = true; ArrayList imagesToRelease = new ArrayList(0); if (imgSrcLeftID != null && imageLoader.imageExists(imgSrcLeftID)) { imagesToRelease.add(imgSrcLeftID); imgSrcLeft = imageLoader.getImage(imgSrcLeftID); imgSrcLeftBounds = imgSrcLeft.getBounds(); } if (imgSrcRightID != null && imageLoader.imageExists(imgSrcRightID)) { imagesToRelease.add(imgSrcRightID); imgSrcRight = imageLoader.getImage(imgSrcRightID); imgSrcRightBounds = imgSrcRight.getBounds(); } if (imgSrcID != null) { Image[] images = imageLoader.getImages(imgSrcID); imagesToRelease.add(imgSrcID); if (images.length == 1) { imgSrc = images[0]; imgSrcBounds = imgSrc.getBounds(); } else if (images.length == 2) { imgSrcLeft = images[0]; imgSrcLeftBounds = imgSrcLeft.getBounds(); imgSrc = images[1]; imgSrcBounds = imgSrc.getBounds(); imgSrcRight = images[1]; imgSrcRightBounds = imgSrcRight.getBounds(); } else if (images.length == 3) { imgSrcLeft = images[0]; imgSrcLeftBounds = imgSrcLeft.getBounds(); imgSrc = images[1]; imgSrcBounds = imgSrc.getBounds(); imgSrcRight = images[2]; imgSrcRightBounds = imgSrcRight.getBounds(); } } try { Point size = control.getSize(); if (size.x <= 0 || size.y <= 0 || imgSrc == null || imgSrc.isDisposed()) { if (DEBUG) { System.out.println("- size " + control.getData("ConfigID")); } Image image = new Image(shell.getDisplay(), 1, 1); control.setBackgroundImage(image); if (lastImage != null) { lastImage.dispose(); } lastImage = image; imgSrc = image; imgSrcBounds = new Rectangle(0,0,1,1); lastBounds = control.getBounds(); inEvent = false; return; } Composite parent = control.getParent(); Image imgBG = parent.getBackgroundImage(); if (imgBG != null && imgBG.isDisposed()) { imgBG = null; } Rectangle imgBGBounds = imgBG == null ? new Rectangle(0, 0, 1, 1) : imgBG.getBounds(); Rectangle compositeArea = control.getBounds(); boolean bTileY = (tileMode & SWTSkinUtils.TILE_Y) > 0; boolean bTileX = (tileMode & SWTSkinUtils.TILE_X) > 0; // TODO: Can also exit early if size shrunk but position // same and imgBGBounds same. if (!bDirty && imgBG == null && bTileX && bTileY) { inEvent = false; return; } if (!bDirty && imgBG == null && compositeArea.width == lastBounds.width && compositeArea.height == lastBounds.height) { inEvent = false; return; } if (!bDirty && compositeArea.equals(lastBounds) && imgBGBounds.width == lastShellBGSize.x && imgBGBounds.height == lastShellBGSize.y) { inEvent = false; return; } if (TEST_SWT_PAINTING && !bDirty && compositeArea.width == lastBounds.width && compositeArea.height == lastBounds.height) { inEvent = false; return; } //control.setRedraw(false); if (DEBUG) { System.out.println(System.currentTimeMillis() + "@" + Integer.toHexString(hashCode()) + "BGPain: " + control.getData("SkinObject") + "/" + "; image" + size + ";" + tileMode + ";lB=" + lastBounds + "/" + compositeArea + ";" + "lBG=" + lastShellBGSize + "/" + imgBGBounds.width + "x" + imgBGBounds.height + ";" + bDirty); //+ "\n" + Debug.getCompressedStackTrace()); } lastBounds = compositeArea; lastShellBGSize = new Point(imgBGBounds.width, imgBGBounds.height); //System.out.println(size); //size.x = 10; //size.y = 10; Image newImage = new Image(shell.getDisplay(), size.x, size.y); // GC gc = new GC(newImage); // gc.setBackground(shell.getDisplay().getSystemColor( // (int) (Math.random() * 16))); // gc.fillRectangle(0, 0, size.x, size.y); // gc.dispose(); Point ofs; if (control.getParent() == shell) { ofs = control.getLocation(); Rectangle clientArea = shell.getClientArea(); ofs.x += clientArea.x; ofs.y += clientArea.y; } else { Point controlPos = new Point(0, 0); if (control instanceof Composite) { Composite composite = (Composite) control; Rectangle compArea = composite.getClientArea(); //System.out.println("comparea=" + compArea); controlPos.x = compArea.x; controlPos.y = compArea.y; } Point locControl = control.toDisplay(controlPos.x, controlPos.y); Rectangle clientArea = shell.getClientArea(); Point locShell = control.getParent().toDisplay(clientArea.x, clientArea.y); //System.out.println("locC="+ locControl + ";locS=" + locShell); ofs = new Point(locControl.x - locShell.x, locControl.y - locShell.y); } ofs.x = (ofs.x % imgBGBounds.width); ofs.y = (ofs.y % imgBGBounds.height); GC gc = new GC(newImage); try { control.setBackgroundImage(null); gc.setBackground(control.getBackground()); gc.fillRectangle(0, 0, size.x, size.y); if (imgBG != null) { for (int y = 0; y < size.y; y += imgBGBounds.height) { for (int x = 0; x < size.x; x += imgBGBounds.width) { gc.drawImage(imgBG, x - ofs.x, y - ofs.y); } } } int maxY = bTileY ? size.y : imgSrcBounds.height; int maxX = bTileX ? size.x : imgSrcBounds.width; int x0 = 0; if ((tileMode & SWTSkinUtils.TILE_CENTER_X) > 0) { x0 = (size.x - imgSrcBounds.width) / 2; maxX += x0; } int y0 = 0; if ((tileMode & SWTSkinUtils.TILE_CENTER_Y) > 0) { y0 = (size.y - imgSrcBounds.height) / 2; maxY += y0; } if (imgSrcRight != null) { int width = imgSrcRightBounds.width; maxX -= width; } if (imgSrcLeft != null) { // TODO: Tile down gc.drawImage(imgSrcLeft, 0, 0); x0 += imgSrcLeftBounds.width; } for (int y = y0; y < maxY; y += imgSrcBounds.height) { for (int x = x0; x < maxX; x += imgSrcBounds.width) { if (x + imgSrcBounds.width >= maxX) { int width = maxX - x; gc.drawImage(imgSrc, 0, 0, width, imgSrcBounds.height, x, y, width, imgSrcBounds.height); } else { gc.drawImage(imgSrc, x, y); } } } if (imgSrcRight != null) { // TODO: Tile down gc.drawImage(imgSrcRight, maxX, 0); } } finally { gc.dispose(); } control.setBackgroundImage(newImage); if (lastImage != null) { lastImage.dispose(); } lastImage = newImage; bDirty = false; } finally { for (String key : imagesToRelease) { imageLoader.releaseImage(key); } if (imgSrcID != null && imgSrc != null) { imgSrc = null; } if (imgSrcLeftID != null && imgSrcLeft != null) { imgSrcLeft = null; } if (imgSrcRightID != null && imgSrcRight != null) { imgSrcRight = null; } //control.setRedraw(true); //control.update(); //control.getShell().update(); // if (control instanceof Composite) { // Control[] children = ((Composite)control).getChildren(); // ((Composite)control).layout(true, true); // for (int i = 0; i < children.length; i++) { // Control control2 = children[i]; // control2.redraw(); // control2.update(); // } // } inEvent = false; } } public static void main(String[] args) { Display display = Display.getDefault(); Shell shell = new Shell(display, SWT.DIALOG_TRIM); shell.setLayout(new FillLayout()); Composite c = new Composite(shell, SWT.BORDER); c.setLayout(new FillLayout()); c.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { e.gc.drawLine(0, 0, 100, 50); } }); Label lbl = new Label(c, SWT.NONE); lbl.setText("text"); shell.open(); while (!shell.isDisposed()) { if (display.readAndDispatch()) { display.sleep(); } } } public void handleEvent(final Event event) { if (event.type == SWT.Resize) { Control control = (Control) event.widget; Rectangle resizeRect = control.getBounds(); if (resizeRect.equals(lastResizeRect)) { return; } lastResizeRect = resizeRect; if (DEBUG) { System.out.println("BGPaint:HE: " + control.getData("ConfigID") + ";" + event + ";" + control.isVisible()); } buildBackground(control); } else if (event.type == SWT.Paint) { Control control = (Control) event.widget; if (DEBUG) { System.out.println("BGPaint:P: " + control.getData("ConfigID") + ";" + event + ";" + control.isVisible()); } if (!TEST_SWT_PAINTING) { buildBackground(control); } } else if (event.type == SWT.Show) { if (DEBUG) { System.out.println("BGPaint:S: " + control.getData("ConfigID") + ";" + event + ";" + control.isVisible()); } if (!TEST_SWT_PAINTING) { buildBackground(control); } } else if (event.type == SWT.Dispose) { if (DEBUG) { System.out.println("dispose.. " + lastImage + ";" + control.getData("SkinObject")); } if (lastImage != null && !lastImage.isDisposed()) { lastImage.dispose(); lastImage = null; } } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectImage.java0000644000175000017500000003072011276661306025213 0ustar adrianadrian/** * */ package com.aelitis.azureus.ui.swt.skin; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader.ImageDownloaderListener; /** * @author TuxPaper * @created Jun 12, 2006 * */ public class SWTSkinObjectImage extends SWTSkinObjectBasic { protected static final Long DRAW_SCALE = new Long(1); protected static final Long DRAW_STRETCH = new Long(2); protected static final Long DRAW_NORMAL = new Long(0); protected static final Long DRAW_TILE = new Long(3); protected static final Long DRAW_CENTER = new Long(4); protected static final Long DRAW_HCENTER = new Long(5); private Canvas canvas; private boolean customImage; private String customImageID; private String currentImageID; private static PaintListener paintListener; private int h_align; static { paintListener = new PaintListener() { public void paintControl(PaintEvent e) { SWTSkinObject so = (SWTSkinObject) e.widget.getData("SkinObject"); try { e.gc.setAdvanced(true); e.gc.setInterpolation(SWT.HIGH); } catch (Exception ex) { } Canvas control = (Canvas) e.widget; Image imgSrc = (Image) control.getData("image"); Image imgRight = null; Image imgLeft = null; String idToRelease = null; ImageLoader imageLoader = null; if (imgSrc == null) { SWTSkinObjectImage soImage = (SWTSkinObjectImage) control.getData("SkinObject"); imageLoader = soImage.getSkin().getImageLoader( soImage.getProperties()); String imageID = (String) control.getData("ImageID"); if (imageLoader.imageExists(imageID)) { idToRelease = imageID; Image[] images = imageLoader.getImages(imageID); if (images.length == 3) { imgLeft = images[0]; imgSrc = images[1]; imgRight = images[2]; } else { imgSrc = images[0]; } } else { return; } } Rectangle imgSrcBounds = imgSrc.getBounds(); Point size = control.getSize(); Long drawMode = (Long) control.getData("drawmode"); if (drawMode == DRAW_STRETCH) { e.gc.drawImage(imgSrc, 0, 0, imgSrcBounds.width, imgSrcBounds.height, 0, 0, size.x, size.y); } else if (drawMode == DRAW_CENTER || drawMode == DRAW_NORMAL) { e.gc.drawImage(imgSrc, (size.x - imgSrcBounds.width) / 2, (size.y - imgSrcBounds.height) / 2); } else if (drawMode == DRAW_HCENTER) { e.gc.drawImage(imgSrc, (size.x - imgSrcBounds.width) / 2, 0); } else if (drawMode == DRAW_SCALE) { // TODO: real scale.. e.gc.drawImage(imgSrc, 0, 0, imgSrcBounds.width, imgSrcBounds.height, 0, 0, size.x, size.y); } else { int x0 = 0; int y0 = 0; int x1 = size.x; int y1 = size.y; if (imgRight == null) { imgRight = (Image) control.getData("image-right"); } if (imgRight != null) { int width = imgRight.getBounds().width; x1 -= width; } if (imgLeft == null) { imgLeft = (Image) control.getData("image-left"); } if (imgLeft != null) { // TODO: Tile down e.gc.drawImage(imgLeft, 0, 0); x0 += imgLeft.getBounds().width; } for (int y = y0; y < y1; y += imgSrcBounds.height) { for (int x = x0; x < x1; x += imgSrcBounds.width) { e.gc.drawImage(imgSrc, x, y); } } if (imgRight != null) { // TODO: Tile down e.gc.drawImage(imgRight, x1, 0); } } if (idToRelease != null && imageLoader != null) { imageLoader.releaseImage(idToRelease); } } }; } /** * @param skin * */ public SWTSkinObjectImage(SWTSkin skin, SWTSkinProperties skinProperties, String sID, String sConfigID, String sImageID, SWTSkinObject parent) { super(skin, skinProperties, sID, sConfigID, "image", parent); setControl(createImageWidget(sConfigID, sImageID)); customImage = false; customImageID = null; } private Canvas createImageWidget(String sConfigID, String sImageID) { currentImageID = sImageID; int style = SWT.WRAP | SWT.DOUBLE_BUFFERED; String sAlign = properties.getStringValue(sConfigID + ".align"); if (sAlign != null && !Constants.isUnix) { h_align = SWTSkinUtils.getAlignment(sAlign, SWT.NONE); if (h_align != SWT.NONE) { style |= h_align; } } if (properties.getIntValue(sConfigID + ".border", 0) == 1) { style |= SWT.BORDER; } Composite createOn; if (parent == null) { createOn = skin.getShell(); } else { createOn = (Composite) parent.getControl(); } canvas = new Canvas(createOn, style); canvas.setData("SkinObject", this); Color color = properties.getColor(sConfigID + ".color"); if (color != null) { canvas.setBackground(color); } final String sURL = properties.getStringValue(sConfigID + ".url"); if (sURL != null && sURL.length() > 0) { canvas.setToolTipText(sURL); canvas.addListener(SWT.MouseUp, new Listener() { public void handleEvent(Event arg0) { Utils.launch(UrlUtils.encode(sURL)); } }); } String sCursor = properties.getStringValue(sConfigID + ".cursor"); if (sCursor != null && sCursor.length() > 0) { if (sCursor.equalsIgnoreCase("hand")) { canvas.addListener(SWT.MouseEnter, skin.getHandCursorListener(canvas.getDisplay())); canvas.addListener(SWT.MouseExit, skin.getHandCursorListener(canvas.getDisplay())); } } // SWTBGImagePainter painter = (SWTBGImagePainter) parent.getData("BGPainter"); // if (painter != null) { // canvas.addListener(SWT.Paint, painter); // } canvas.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { String oldImageID = (String) canvas.getData("ImageID"); if (oldImageID != null && canvas.getData("image") != null) { ImageLoader imageLoader = skin.getImageLoader(properties); imageLoader.releaseImage(oldImageID); } } }); // needed to set paint listener and canvas size reallySetImage(); return canvas; } public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { reallySetImage(); } } //protected void setCanvasImage(String sConfigID, AECallback callback) { protected void setCanvasImage(String sImageID, AECallback callback) { setCanvasImage(sConfigID, sImageID, callback); } //private void setCanvasImage(final String sConfigID, final String sImageID, AECallback callback) { private void setCanvasImage(final String sConfigID, final String sImageID, AECallback callback) { Utils.execSWTThread(new AERunnableWithCallback(callback) { public Object runSupport() { if (canvas == null || canvas.isDisposed()) { return null; } String oldImageID = (String) canvas.getData("ImageID"); if (sImageID != null && sImageID.equals(oldImageID)) { return null; } ImageLoader imageLoader = skin.getImageLoader(properties); if (oldImageID != null && canvas.getData("image") != null) { imageLoader.releaseImage(oldImageID); } Image[] images = sImageID == null || sImageID.length() == 0 ? null : imageLoader.getImages(sImageID); Image image = null; if (images.length == 3) { Image imageLeft = images[0]; if (ImageLoader.isRealImage(imageLeft)) { canvas.setData("image-left", imageLeft); } image = images[1]; Image imageRight = images[2]; if (ImageLoader.isRealImage(imageRight)) { canvas.setData("image-right", imageRight); } } else if (images.length > 0) { image = images[0]; } if (image == null) { image = ImageLoader.noImage; } String sDrawMode = properties.getStringValue(sConfigID + ".drawmode"); if (sDrawMode == null) { sDrawMode = properties.getStringValue( SWTSkinObjectImage.this.sConfigID + ".drawmode", ""); } //allowImageDimming = sDrawMode.equalsIgnoreCase("dim"); Long drawMode; if (sDrawMode.equals("scale")) { drawMode = DRAW_SCALE; } else if (sDrawMode.equals("stretch")) { drawMode = DRAW_STRETCH; } else if (sDrawMode.equals("center")) { drawMode = DRAW_CENTER; } else if (sDrawMode.equals("h-center")) { drawMode = DRAW_HCENTER; } else if (sDrawMode.equalsIgnoreCase("tile")) { drawMode = DRAW_TILE; } else { drawMode = DRAW_NORMAL; } canvas.setData("drawmode", drawMode); Rectangle imgBounds = image.getBounds(); if (drawMode != DRAW_CENTER && drawMode != DRAW_HCENTER && drawMode != DRAW_STRETCH) { canvas.setSize(imgBounds.width, imgBounds.height); } //canvas.setData("image", image); if (drawMode == DRAW_TILE || drawMode == DRAW_NORMAL) { // XXX Huh? A tile of one? :) FormData fd = (FormData) canvas.getLayoutData(); if (fd == null) { fd = new FormData(imgBounds.width, imgBounds.height); } else { fd.width = imgBounds.width; fd.height = imgBounds.height; } canvas.setLayoutData(fd); Utils.relayout(canvas); } // remove in case already added canvas.removePaintListener(paintListener); canvas.addPaintListener(paintListener); canvas.setData("ImageID", sImageID); canvas.redraw(); SWTSkinUtils.addMouseImageChangeListeners(canvas); imageLoader.releaseImage(sImageID); return null; } }); } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#setBackground(java.lang.String, java.lang.String) public void setBackground(String sConfigID, String sSuffix) { // No background for images? } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#switchSuffix(java.lang.String) public String switchSuffix(String suffix, int level, boolean walkUp, boolean walkDown) { suffix = super.switchSuffix(suffix, level, walkUp, walkDown); if (customImage) { return suffix; } if (suffix == null) { return null; } final String fSuffix = suffix; Utils.execSWTThread(new AERunnable() { public void runSupport() { currentImageID = (customImageID == null ? (sConfigID + ".image") : customImageID) + fSuffix; if (isVisible()) { reallySetImage(); } } }); return suffix; } protected void reallySetImage() { if (currentImageID == null || customImage) { return; } ImageLoader imageLoader = skin.getImageLoader(properties); boolean imageExists = imageLoader.imageExists(currentImageID); if (!imageExists && imageLoader.imageExists(currentImageID + ".image")) { currentImageID = sConfigID + ".image"; imageExists = true; } if (!imageExists && suffixes != null) { for (int i = suffixes.length - 1; i >= 0; i--) { String suffixToRemove = suffixes[i]; if (suffixToRemove != null) { currentImageID = currentImageID.substring(0, currentImageID.length() - suffixToRemove.length()); if (imageLoader.imageExists(currentImageID)) { imageExists = true; break; } } } } if (imageExists) { setCanvasImage(currentImageID, null); } } public void setImage(Image image) { customImage = true; customImageID = null; canvas.setData("image", image); canvas.setData("image-left", null); canvas.setData("image-right", null); canvas.redraw(); Utils.relayout(canvas); } protected void setImageByID(String sConfigID, AECallback callback) { if (customImage == false && customImageID != null && customImageID.equals(sConfigID)) { if (callback != null) { callback.callbackFailure(null); } return; } customImage = false; customImageID = sConfigID; String sImageID = sConfigID + getSuffix(); ImageLoader imageLoader = skin.getImageLoader(properties); Image image = imageLoader.getImage(sImageID); if (ImageLoader.isRealImage(image)) { setCanvasImage(sConfigID, sImageID, callback); } else { setCanvasImage(sConfigID, sConfigID, callback); } imageLoader.releaseImage(sImageID); return; } public void setImageUrl(final String url) { if (customImage == false && customImageID != null && customImageID.equals(url)) { return; } customImage = false; customImageID = url; Utils.execSWTThread(new AERunnable() { public void runSupport() { final ImageLoader imageLoader = skin.getImageLoader(properties); imageLoader.getUrlImage(url, new ImageDownloaderListener() { public void imageDownloaded(Image image, boolean returnedImmediately) { setCanvasImage(url, null); imageLoader.releaseImage(url); } }); } }); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinCheckboxListener.java0000644000175000017500000000172111124571142026263 0ustar adrianadrian/** * Created on Dec 24, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.skin; /** * @author TuxPaper * @created Dec 24, 2008 * */ public interface SWTSkinCheckboxListener { public void checkboxChanged(SWTSkinObjectCheckbox so, boolean checked); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTab.java0000644000175000017500000000674011033325202024663 0ustar adrianadrian/* * Created on Jun 21, 2006 1:22:57 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; import java.util.ArrayList; /** * @author TuxPaper * @created Jun 21, 2006 * */ public class SWTSkinObjectTab extends SWTSkinObjectContainer { SWTSkinObject[] activeWidgets = null; SWTSkinObject activeWidgetsParent; SWTSkinTabSet tabset; public SWTSkinObjectTab(SWTSkin skin, SWTSkinProperties properties, String sID, String sConfigID, SWTSkinObject parent) { super(skin, properties, sID, sConfigID, parent); type = "tab"; } public String[] getActiveWidgetIDs() { String[] sIDs = properties.getStringArray(getConfigID() + ".active-widgets"); return sIDs; } public SWTSkinObject[] getActiveWidgets(boolean create) { if (activeWidgets == null) { String[] sIDs = getActiveWidgetIDs(); ArrayList skinObjectArray = new ArrayList(); if (sIDs != null) { for (int i = 0; i < sIDs.length; i++) { // System.out.println("Looking for " + sIDs[i] + " w/Parent " // + activeWidgetsParent); SWTSkinObject skinObject = getSkin().getSkinObjectByID(sIDs[i], activeWidgetsParent); if (skinObject == null && create) { SWTSkinObject soParent = skin.getSkinObjectByID( properties.getStringValue(getConfigID() + ".contentarea", (String) null), activeWidgetsParent); if (soParent != null) { skinObject = skin.createSkinObject(sIDs[i], sIDs[i], soParent); skin.layout(); skin.getShell().layout(true, true); } } if (skinObject != null) { skinObjectArray.add(skinObject); } } } if (skinObjectArray.size() == 0) { return new SWTSkinObject[0]; } activeWidgets = new SWTSkinObject[skinObjectArray.size()]; activeWidgets = (SWTSkinObject[]) skinObjectArray.toArray(activeWidgets); } return activeWidgets; } public void setActiveWidgets(SWTSkinObject[] skinObjects) { activeWidgets = skinObjects; } /** * Retrieve the parent skin object to which the active widgets belong to. * * @return Parent skin object, or null if it doesn't matter */ public SWTSkinObject getActiveWidgetsParent() { return activeWidgetsParent; } /** * Sets the parent skin object to which the active widgets belong to. *

    * This is usefull when there are multiple widgets with the same ID * * @param activeWidgetsParent */ public void setActiveWidgetsParent(SWTSkinObject activeWidgetsParent) { this.activeWidgetsParent = activeWidgetsParent; activeWidgets = null; } public SWTSkinTabSet getTabset() { return tabset; } public void setTabset(SWTSkinTabSet tabset) { this.tabset = tabset; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText.java0000644000175000017500000000262011223315754025106 0ustar adrianadrian/* * Created on Aug 4, 2006 9:18:52 AM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; /** * @author TuxPaper * @created Aug 4, 2006 * */ public interface SWTSkinObjectText extends SWTSkinObject { public void setText(String text); public void setTextID(String id); public void setTextID(String id, String[] params); /** * @return * * @since 3.1.1.1 */ int getStyle(); /** * @param style * * @since 3.1.1.1 */ void setStyle(int style); /** * @return * * @since 4.1.0.5 */ public String getText(); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectButton.java0000644000175000017500000000753611131562644025450 0ustar adrianadrian/** * Created on Sep 21, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.skin; import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter; /** * Native button. For non-native, use SWTSkinButtonUtility on any SWTSkinObject * * @author TuxPaper * @created Sep 21, 2008 * */ public class SWTSkinObjectButton extends SWTSkinObjectBasic { private Button button; private ArrayList buttonListeners = new ArrayList(1); public SWTSkinObjectButton(SWTSkin skin, final SWTSkinProperties properties, String id, String configID, SWTSkinObject parentSkinObject) { super(skin, properties, id, configID, "button", parentSkinObject); Composite createOn; if (parent == null) { createOn = skin.getShell(); } else { createOn = (Composite) parent.getControl(); } button = new Button(createOn, SWT.PUSH); button.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { Object[] listeners = buttonListeners.toArray(); for (int i = 0; i < listeners.length; i++) { ButtonListenerAdapter l = (ButtonListenerAdapter) listeners[i]; l.pressed(null); l.pressed(null, SWTSkinObjectButton.this, e.stateMask); } } public void widgetDefaultSelected(SelectionEvent e) { } }); setControl(button); } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectBasic#switchSuffix(java.lang.String, int, boolean) public String switchSuffix(String suffix, int level, boolean walkUp, boolean walkDown) { suffix = super.switchSuffix(suffix, level, walkUp, walkDown); if (suffix == null) { return null; } String sPrefix = sConfigID + ".text"; String text = properties.getStringValue(sPrefix + suffix); if (text != null) { setText(text); } return suffix; } public void addSelectionListener(ButtonListenerAdapter listener) { if (buttonListeners.contains(listener)) { return; } buttonListeners.add(listener); } /** * @param text * * @since 3.1.1.1 */ public void setText(final String text) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (button != null && !button.isDisposed()) { button.setText(text); int width = properties.getIntValue(sConfigID + ".width", -1); if (width == -1) { int minWidth = properties.getIntValue(sConfigID + ".minwidth", -1); if (minWidth >= 0) { FormData fd = (FormData) button.getLayoutData(); if (fd == null) { fd = new FormData(); } Point size = button.computeSize(SWT.DEFAULT, SWT.DEFAULT); if (size.x < minWidth) { fd.width = minWidth; } else { fd.width = -1; } button.setLayoutData(fd); Utils.relayout(control); } } } } }); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSet.java0000644000175000017500000001714411247620536024227 0ustar adrianadrian/** * */ package com.aelitis.azureus.ui.swt.skin; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; /** * @author TuxPaper * @created Jun 8, 2006 */ public class SWTSkinTabSet { private Listener tabMouseListener; private final SWTSkin skin; private final String sID; private SWTSkinObjectTab activeTab; /** List of SWTSKinObjectTab */ private List tabs; private ArrayList listeners = new ArrayList(); // XXX Do we need to pass in SkinProperties in case of cloning? public SWTSkinTabSet(SWTSkin skin, String sID) { this.sID = sID; this.skin = skin; tabs = new ArrayList(); } public void addTab(final SWTSkinObjectTab tab) { tabs.add(tab); tab.setTabset(this); //System.out.println("AddTab for " + sID + ": " + tab.getSkinObjectID()); addMouseListener(tab, tab.getControl()); skin.addListener(new SWTSkinLayoutCompleteListener() { public void skinLayoutCompleted() { setTabVisible(tab, activeTab == tab, null); } }); } public SWTSkinObjectTab getActiveTab() { return activeTab; } public SWTSkinObjectTab[] getTabs() { return (SWTSkinObjectTab[]) tabs.toArray(new SWTSkinObjectTab[0]); } public SWTSkinObjectTab getTabByID(String sID) { for (int i = 0; i < tabs.size(); i++) { SWTSkinObjectTab tab = (SWTSkinObjectTab) tabs.get(i); String sTabID = tab.getSkinObjectID(); if (sTabID.equals(sID)) { return tab; } } return null; } public SWTSkinObjectTab getTab(String sViewID) { for (int i = 0; i < tabs.size(); i++) { SWTSkinObjectTab tab = (SWTSkinObjectTab) tabs.get(i); String sTabViewID = tab.getViewID(); if (sTabViewID.equals(sViewID)) { return tab; } } return null; } /** * * @deprecated Use {@link #setActiveTab(String)} */ public boolean setActiveTabByID(String sID) { for (int i = 0; i < tabs.size(); i++) { SWTSkinObject tab = (SWTSkinObject) tabs.get(i); if (tab instanceof SWTSkinObjectTab) { String sTabID = tab.getSkinObjectID(); if (sTabID.equals(sID)) { setActiveTab((SWTSkinObjectTab) tab); return true; } } } return false; } public boolean setActiveTab(String viewID) { SWTSkinObject skinObject = skin.getSkinObject(viewID); if (skinObject == null) { return false; } return skin.activateTab(skinObject) != null; } public void setActiveTab(final SWTSkinObjectTab newTab) { setActiveTab(newTab, false); } private void setActiveTab(final SWTSkinObjectTab newTab, final boolean evenIfSame) { Utils.execSWTThread(new AERunnable() { public void runSupport() { Shell shell = skin.getShell(); Cursor cursor = shell.getCursor(); try { shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); swtSetActiveTab(newTab, evenIfSame); } finally { shell.setCursor(cursor); } } }); } protected void swtSetActiveTab(SWTSkinObjectTab newTab, boolean evenIfSame) { // Don't exit early if we are already on tab. We want to be notified if // the user clicks on the tab again (for example, for page refreshing) if (!tabs.contains(newTab)) { System.err.println("Not contain in " + sID + ": " + newTab); return; } String sOldID = activeTab == null ? "" : activeTab.getSkinObjectID(); if (newTab != activeTab) { SWTSkinObject[] objects = setTabVisible(newTab, true, null); if (activeTab != null) { setTabVisible(activeTab, false, objects); } activeTab = newTab; } else if (!evenIfSame) { return; } String sConfigID = activeTab.getConfigID(); String sNewID = activeTab.getSkinObjectID(); SWTSkinObject parent = skin.getSkinObject(activeTab.getProperties().getStringValue(sConfigID + ".activate")); if (parent != null) { parent.getControl().setFocus(); } triggerChangeListener(sOldID, sNewID); } private boolean hasSkinBrowser(SWTSkinObject skinObject) { if (skinObject instanceof SWTSkinObjectContainer) { SWTSkinObject[] children = ((SWTSkinObjectContainer) skinObject).getChildren(); for (int i = 0; i < children.length; i++) { SWTSkinObject object = children[i]; if (hasSkinBrowser(object)) { return true; } } } return (skinObject instanceof SWTSkinObjectBrowser); } /** * @param oldID * @param newID */ private void triggerChangeListener(String oldID, String newID) { for (Iterator iter = listeners.iterator(); iter.hasNext();) { try { SWTSkinTabSetListener l = (SWTSkinTabSetListener) iter.next(); l.tabChanged(this, oldID, newID); } catch (Exception e) { Debug.printStackTrace(e); } } } private void addMouseListener(SWTSkinObject tab, Control control) { if (tabMouseListener == null) { tabMouseListener = new Listener() { boolean bDownPressed = false; public void handleEvent(Event event) { if (event.type == SWT.MouseDown) { bDownPressed = true; return; } else if (!bDownPressed) { return; } bDownPressed = false; Control control = (Control) event.widget; setActiveTab((SWTSkinObjectTab) control.getData("Tab"), true); } }; } control.setData("Tab", tab); control.addListener(SWT.MouseUp, tabMouseListener); control.addListener(SWT.MouseDown, tabMouseListener); if (control instanceof Composite) { Control[] children = ((Composite) control).getChildren(); for (int i = 0; i < children.length; i++) { addMouseListener(tab, children[i]); } } } private SWTSkinObject[] setTabVisible(SWTSkinObjectTab tab, boolean visible, SWTSkinObject[] skipObjects) { String sSkinID = tab.getSkinObjectID(); SWTSkinObject soTabContent = skin.getSkinObjectByID(sSkinID); if (soTabContent == null) { return null; } String suffix = visible ? "-selected" : ""; soTabContent.switchSuffix(suffix, 1, true); SWTSkinObject[] activeWidgets = tab.getActiveWidgets(visible); for (int i = 0; i < activeWidgets.length; i++) { SWTSkinObject skinObject = activeWidgets[i]; boolean ok = true; if (skipObjects != null) { for (int j = 0; j < skipObjects.length; j++) { if (skinObject.equals(skipObjects[j])) { ok = false; break; } } } if (ok) { if (visible) { skinObject.setDefaultVisibility(); } else { skinObject.setVisible(visible); } //System.out.println(((visible ? "show" : "hide") + " " + skinObject) + Debug.getCompressedStackTrace()); } } tab.triggerListeners(SWTSkinObjectListener.EVENT_SELECT); return activeWidgets; } public void addListener(SWTSkinTabSetListener listener) { listeners.add(listener); } public String getID() { return sID; } protected static String[] getTemplateInfo(SWTSkin skin, SWTSkinObject skinObject, String sTemplateKey) { SWTSkinProperties skinProperties = skin.getSkinProperties(); String sID = skinObject.getConfigID() + ".view.template." + sTemplateKey; return skinProperties.getStringArray(sID); } protected static String getTemplateID(SWTSkin skin, SWTSkinObject skinObject, String sTemplateKey) { String[] templateInfo = getTemplateInfo(skin, skinObject, sTemplateKey); if (templateInfo != null) { return templateInfo[0]; } return null; } public static String getTabSetID(SWTSkin skin, SWTSkinObject skinObject, String sTemplateKey) { String[] templateInfo = getTemplateInfo(skin, skinObject, sTemplateKey); if (templateInfo != null && templateInfo.length > 1) { return templateInfo[1]; } return null; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinFactory.java0000644000175000017500000000267410671176506024461 0ustar adrianadrian/* * Created on Jun 1, 2006 2:06:48 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; /** * @author TuxPaper * @created Jun 1, 2006 * */ public class SWTSkinFactory { private static SWTSkin instance = null; public static SWTSkin getInstance() { if (instance == null) { instance = new SWTSkin(); } return instance; } public static void setInstance(SWTSkin skin) { instance = skin; } public static SWTSkin getNonPersistentInstance(ClassLoader classLoader, String skinPath, String mainSkinFile) { return new SWTSkin(classLoader, skinPath, mainSkinFile); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObject.java0000644000175000017500000000547011153412240024235 0ustar adrianadrian/** * */ package com.aelitis.azureus.ui.swt.skin; import org.eclipse.swt.widgets.Control; import org.gudy.azureus2.ui.swt.debug.ObfusticateShell; /** * @author TuxPaper * @created Jun 12, 2006 * */ public interface SWTSkinObject extends ObfusticateShell { /** * Retrieve the associated SWT Control used by the skin object * * @return SWT Control */ public Control getControl(); /** * Retrieve the type of widget. * @return * * TODO Move widget types to SWTSkinObject */ public String getType(); /** * Retrieve the Skin Object ID that represents this object. Typically the * same as {@link #getConfigID()}, however, may be different if a config * id is used to make independant copies * * @return An unique Skin Object ID */ public String getSkinObjectID(); /** * Retrieve the Config ID which is ID in the skin config file. * * @return Config ID */ public String getConfigID(); public SWTSkinObject getParent(); public SWTSkin getSkin(); public void setVisible(boolean visible); public boolean isVisible(); public void setDefaultVisibility(); /** * @param sConfigID * @param sSuffix */ void setBackground(String sConfigID, String sSuffix); /** * @param suffix * @param level * @param walkUp TODO * @return TODO */ String switchSuffix(String suffix, int level, boolean walkUp); String switchSuffix(String suffix, int level, boolean walkUp, boolean walkDown); /** * Convenience method for switching suffix using defaults * @param suffix * @return */ String switchSuffix(String suffix); /** * @return */ String getSuffix(); /** * @param properties */ void setProperties(SWTSkinProperties skinProperties); /** * @return */ SWTSkinProperties getProperties(); //void getTemplate(String property) public void addListener(SWTSkinObjectListener listener); public void removeListener(SWTSkinObjectListener listener); /** * @return */ public SWTSkinObjectListener[] getListeners(); public String getViewID(); /** * @param eventType */ void triggerListeners(int eventType); /** * @param eventType * @param params */ void triggerListeners(int eventType, Object params); /** * * * @since 3.0.1.3 */ public void dispose(); /** * @param id * * @since 3.0.4.3 */ void setTooltipID(String id); /** * @return * * @since 3.0.5.3 */ boolean getDefaultVisibility(); public Object getData(String id); public void setData(String id, Object data); /** * @return * * @since 3.1.1.1 */ boolean isDisposed(); /** * @return * * @since 3.1.1.1 */ boolean isDebug(); /** * @param walkup * @return * * @since 3.1.1.1 */ String getTooltipID(boolean walkup); /** * @param b * * @since 3.1.1.1 */ public void setDebug(boolean b); public void relayout(); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSlider.java0000644000175000017500000002673511127403350025412 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.skin; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author TuxPaper * @created Aug 28, 2007 * */ public class SWTSkinObjectSlider extends SWTSkinObjectBasic implements PaintListener, MouseListener, MouseMoveListener { private Image imageFG; private Object imageFGLeft; private Object imageFGRight; private Canvas canvas; private Image imageThumbRight; private Image imageThumb; private Image imageThumbLeft; private Image imageBGRight; private Image imageBG; private Image imageBGLeft; private double percent; private Rectangle imageFGbounds; private Rectangle imageBGbounds; private Rectangle imageThumbBounds; private Point maxSize = new Point(0, 0); private boolean mouseDown; private boolean mouseMoveAdjusts = true; private ArrayList listeners = new ArrayList(); private double draggingPercent; private boolean disabled; private List imagesToRelease = new ArrayList(); public SWTSkinObjectSlider(SWTSkin skin, SWTSkinProperties skinProperties, String sID, String sConfigID, String[] typeParams, SWTSkinObject parent) { super(skin, skinProperties, sID, sConfigID, "slider", parent); String sSuffix = ".complete"; final ImageLoader imageLoader = skin.getImageLoader(properties); String imagePrefix = sConfigID + sSuffix; Image[] images = imageLoader.getImages(imagePrefix); imagesToRelease.add(imagePrefix); if (images.length == 1 && ImageLoader.isRealImage(images[0])) { imageFG = images[0]; imageFGLeft = imageLoader.getImage(imagePrefix + "-left"); imageFGRight = imageLoader.getImage(imagePrefix + "-right"); imagesToRelease.add(imagePrefix + "-left"); imagesToRelease.add(imagePrefix + "-right"); } else if (images.length == 3 && ImageLoader.isRealImage(images[2])) { imageFGLeft = images[0]; imageFG = images[1]; imageFGRight = images[2]; } if (imageFG != null) { imageFGbounds = imageFG.getBounds(); } sSuffix = ".incomplete"; imagePrefix = sConfigID + sSuffix; images = imageLoader.getImages(imagePrefix); imagesToRelease.add(imagePrefix); if (images.length == 1 && ImageLoader.isRealImage(images[0])) { imageBG = images[0]; imageBGLeft = imageLoader.getImage(imagePrefix + "-left"); imageBGRight = imageLoader.getImage(imagePrefix + "-right"); imagesToRelease.add(imagePrefix + "-left"); imagesToRelease.add(imagePrefix + "-right"); } else if (images.length == 3 && ImageLoader.isRealImage(images[2])) { imageBGLeft = images[0]; imageBG = images[1]; imageBGRight = images[2]; } if (imageBG != null) { imageBGbounds = imageBG.getBounds(); } sSuffix = ".thumb"; imagePrefix = sConfigID + sSuffix; images = imageLoader.getImages(imagePrefix); imagesToRelease.add(imagePrefix); if (images.length == 1) { imageThumb = images[0]; imageThumbLeft = imageLoader.getImage(imagePrefix + "-left"); imageThumbRight = imageLoader.getImage(imagePrefix + "-right"); imagesToRelease.add(imagePrefix + "-left"); imagesToRelease.add(imagePrefix + "-right"); } else if (images.length == 3 && ImageLoader.isRealImage(images[2])) { imageThumbLeft = images[0]; imageThumb = images[1]; imageThumbRight = images[2]; } if (imageThumb != null) { imageThumbBounds = imageThumb.getBounds(); } maxSize = buildMaxSize(new Rectangle[] { imageThumbBounds, imageBGbounds, imageFGbounds }); if (skinProperties.getStringValue(sConfigID + ".width", "").equalsIgnoreCase( "auto")) { maxSize.x = 0; } int style = SWT.NONE; if (skinProperties.getIntValue(sConfigID + ".border", 0) == 1) { style |= SWT.BORDER; } Composite createOn; if (parent == null) { createOn = skin.getShell(); } else { createOn = (Composite) parent.getControl(); } canvas = new Canvas(createOn, style); canvas.setLayoutData(new FormData(maxSize.x == 0 ? SWT.DEFAULT : maxSize.x, maxSize.y)); canvas.setSize(SWT.DEFAULT, maxSize.y); setControl(canvas); canvas.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { try { for (String key : imagesToRelease) { imageLoader.releaseImage(key); } } catch (Exception ex) { Debug.out(ex); } } }); setAlwaysHookPaintListener(true); canvas.addMouseListener(this); canvas.addMouseMoveListener(this); } private Point buildMaxSize(Rectangle[] bounds) { Point maxSize = new Point(0, 0); for (int i = 0; i < bounds.length; i++) { if (bounds[i] == null) { continue; } if (bounds[i].width > maxSize.x) { maxSize.x = bounds[i].width; } if (bounds[i].height > maxSize.y) { maxSize.y = bounds[i].height; } } return maxSize; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectBasic#paintControl(org.eclipse.swt.graphics.GC) public void paintControl(GC gc) { super.paintControl(gc); int fullWidth = maxSize.x == 0 || imageFGbounds == null ? canvas.getClientArea().width : imageFGbounds.width; if (percent > 0 && imageFG != null) { int xDrawTo = (int) (fullWidth * percent); int xDrawToSrc = xDrawTo > imageFGbounds.width ? imageFGbounds.width : xDrawTo; int y = (maxSize.y - imageFGbounds.height) / 2; gc.drawImage(imageFG, 0, 0, xDrawToSrc, imageFGbounds.height, 0, y, xDrawTo, imageFGbounds.height); } if (percent < 100 && imageBG != null) { int xDrawFrom = (int) (imageBGbounds.width * percent); int xDrawWidth = imageBGbounds.width - xDrawFrom; gc.drawImage(imageBG, xDrawFrom, 0, xDrawWidth, imageFGbounds.height, xDrawFrom, 0, xDrawWidth, imageFGbounds.height); } int drawWidth = fullWidth - imageThumbBounds.width; int xThumbPos = (int) ((mouseDown && !mouseMoveAdjusts ? draggingPercent : percent) * drawWidth); gc.drawImage(imageThumb, xThumbPos, 0); } public double getPercent() { return percent; } public void setPercent(double percent) { setPercent(percent, false); } private boolean areDoublesEqual(double a, double b) { return Math.abs(a - b) < 0.000001; } private void setPercent(double newPercent, boolean triggerListeners) { if (areDoublesEqual(percent, newPercent)) { return; } newPercent = validatePercent(newPercent, triggerListeners); if (areDoublesEqual(percent, newPercent)) { return; } this.percent = newPercent; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (canvas != null && !canvas.isDisposed()) { canvas.redraw(); canvas.update(); } } }); if (triggerListeners) { Object[] listenersArray = listeners.toArray(); for (int i = 0; i < listenersArray.length; i++) { SWTSkinListenerSliderSelection l = (SWTSkinListenerSliderSelection) listenersArray[i]; l.selectionChanged(this.percent); } } } /** * @return * * @since 3.0.2.3 */ private double validatePercent(double percent, boolean triggerListeners) { if (triggerListeners) { Object[] listenersArray = listeners.toArray(); for (int i = 0; i < listenersArray.length; i++) { SWTSkinListenerSliderSelection l = (SWTSkinListenerSliderSelection) listenersArray[i]; Double changedPercent = l.selectionChanging(this.percent, percent); if (changedPercent != null) { return changedPercent.floatValue(); } } } if (percent < 0) { return 0; } else if (percent > 1) { return 1; } return percent; } // @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent) public void mouseDoubleClick(MouseEvent e) { } // @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent) public void mouseDown(MouseEvent e) { if (disabled) { return; } mouseDown = true; int offset = imageThumbBounds.width / 2; int sizeX = maxSize.x; if (maxSize.x == 0) { sizeX = canvas.getClientArea().width; } float newPercent = (e.x - offset) / (float) (sizeX - imageThumbBounds.width); if (mouseMoveAdjusts) { setPercent(newPercent, true); } else { draggingPercent = validatePercent(newPercent, true); Utils.execSWTThread(new AERunnable() { public void runSupport() { if (canvas != null && !canvas.isDisposed()) { canvas.redraw(); canvas.update(); } } }); } } // @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent) public void mouseUp(MouseEvent e) { if (disabled) { return; } mouseDown = false; if (!mouseMoveAdjusts) { int offset = imageThumbBounds.width / 2; int sizeX = maxSize.x; if (maxSize.x == 0) { sizeX = canvas.getClientArea().width; } float newPercent = (e.x - offset) / (float) (sizeX - imageThumbBounds.width); setPercent(newPercent, true); } } // @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent) public void mouseMove(MouseEvent e) { if (disabled) { return; } if (mouseDown) { int offset = imageThumbBounds.width / 2; int sizeX = maxSize.x; if (maxSize.x == 0) { sizeX = canvas.getClientArea().width; } float newPercent = (e.x - offset) / (float) (sizeX - imageThumbBounds.width); if (mouseMoveAdjusts) { setPercent(newPercent, true); } else { draggingPercent = validatePercent(newPercent, true); Utils.execSWTThread(new AERunnable() { public void runSupport() { if (canvas != null && !canvas.isDisposed()) { canvas.redraw(); canvas.update(); } } }); } } } public void addListener(SWTSkinListenerSliderSelection listener) { listeners.add(listener); } public static class SWTSkinListenerSliderSelection { /** * * @param oldPercent * @param newPercent * @return return null if you do not wish to change the value * * @since 3.0.2.3 */ public Double selectionChanging(double oldPercent, double newPercent) { return null; } public void selectionChanged(double percent) { } } public boolean getMouseMoveAdjusts() { return mouseMoveAdjusts; } public void setMouseMoveAdjusts(boolean mouseMoveAdjusts) { this.mouseMoveAdjusts = mouseMoveAdjusts; } public boolean isDisabled() { return disabled; } public void setDisabled(boolean disabled) { if (disabled == this.disabled) { return; } this.disabled = disabled; if (disabled) { mouseDown = false; } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBasic.java0000644000175000017500000006510011274452770025213 0ustar adrianadrian/** * */ package com.aelitis.azureus.ui.swt.skin; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.utils.ColorCache; import com.aelitis.azureus.ui.swt.views.skin.SkinView; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager; import com.aelitis.azureus.util.StringCompareUtils; /** * @author TuxPaper * @created Jun 12, 2006 * */ public class SWTSkinObjectBasic implements SWTSkinObject, PaintListener { protected static final int BORDER_ROUNDED = 1; protected static final int BORDER_ROUNDED_FILL = 2; protected static final int BORDER_GRADIENT = 3; protected Control control; protected String type; protected String sConfigID; protected SWTBGImagePainter painter; protected SWTSkinProperties properties; protected String sID; // XXX Might be wise to force this to SWTSkinObjectContainer protected SWTSkinObject parent; protected SWTSkin skin; protected String[] suffixes = null; protected ArrayList listeners = new ArrayList(); protected AEMonitor listeners_mon = new AEMonitor( "SWTSkinObjectBasic::listener"); private String sViewID; private boolean isVisible; protected Color bgColor; private Color colorBorder; private int[] colorBorderParams = null; private int[] colorFillParams; private int colorFillType; private boolean initialized = false; boolean paintListenerHooked = false; boolean alwaysHookPaintListener = false; private Map mapData = Collections.EMPTY_MAP; private boolean disposed = false; protected boolean debug = false; private List listGradients = new ArrayList(); private Image bgImage; private String tooltipID; protected boolean customTooltipID = false; private Listener resizeGradientBGListener; private SkinView skinView; /** * @param properties TODO * */ public SWTSkinObjectBasic(SWTSkin skin, SWTSkinProperties properties, Control control, String sID, String sConfigID, String type, SWTSkinObject parent) { this(skin, properties, sID, sConfigID, type, parent); setControl(control); } public SWTSkinObjectBasic(SWTSkin skin, SWTSkinProperties properties, String sID, String sConfigID, String type, SWTSkinObject parent) { this.skin = skin; this.properties = properties; this.sConfigID = sConfigID; this.sID = sID; this.type = type; this.parent = parent; setViewID(properties.getStringValue(sConfigID + ".view")); setDebug(properties.getBooleanValue(sConfigID + ".debug", false)); } public void setControl(final Control control) { if (!Utils.isThisThreadSWT()) { Debug.out("Warning: setControl not called in SWT thread for " + this); Utils.execSWTThread(new AERunnable() { public void runSupport() { setControl(control); } }); return; } resizeGradientBGListener = new Listener() { public void handleEvent(Event event) { if (bgImage != null && !bgImage.isDisposed()) { bgImage.dispose(); } Rectangle bounds = control.getBounds(); if (bounds.height <= 0) { return; } bgImage = new Image(control.getDisplay(), 5, bounds.height); GC gc = new GC(bgImage); try { try { gc.setAdvanced(true); gc.setInterpolation(SWT.HIGH); gc.setAntialias(SWT.ON); } catch (Exception ex) { } GradientInfo lastGradInfo = new GradientInfo(bgColor, 0); for (GradientInfo gradInfo : listGradients) { if (gradInfo.startPoint != lastGradInfo.startPoint) { gc.setForeground(lastGradInfo.color); gc.setBackground(gradInfo.color); int y = (int) (bounds.height * lastGradInfo.startPoint); int height = (int) (bounds.height * gradInfo.startPoint) - y; gc.fillGradientRectangle(0, y, 5, height, true); } lastGradInfo = gradInfo; } if (lastGradInfo.startPoint < 1) { gc.setForeground(lastGradInfo.color); gc.setBackground(lastGradInfo.color); int y = (int) (bounds.height * lastGradInfo.startPoint); int height = bounds.height - y; gc.fillGradientRectangle(0, y, 5, height, true); } } finally { gc.dispose(); } if (painter == null) { painter = new SWTBGImagePainter(control, null, null, bgImage, SWTSkinUtils.TILE_X); } else { painter.setImage(null, null, bgImage); } } }; this.control = control; control.setData("ConfigID", sConfigID); control.setData("SkinObject", this); SWTSkinUtils.addMouseImageChangeListeners(control); switchSuffix(null, 0, false); // setvisible is one time only if (!properties.getBooleanValue(sConfigID + ".visible", true)) { setVisible(false); } final Listener lShowHide = new Listener() { public void handleEvent(final Event event) { final boolean toBeVisible = event.type == SWT.Show; if (toBeVisible == control.isVisible() && isVisible == toBeVisible) { return; } //System.out.println(SWTSkinObjectBasic.this + ">show/hide " + ((event.widget).getData("SkinObject")) + ";" + ((Control)event.widget).isVisible() + ";" + Debug.getCompressedStackTrace()); // wait until show or hide event is processed to guarantee // isVisible will be correct for listener triggers Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { //System.out.println(">>show/hide " + ((event.widget).getData("SkinObject")) + ";" + ((Control) event.widget).isVisible()); if (control == null || control.isDisposed()) { setIsVisible(false, true); return; } if (event.widget == control) { setIsVisible(toBeVisible, true); return; } if (!toBeVisible || control.isVisible()) { setIsVisible(toBeVisible, true); return; } setIsVisible(control.isVisible(), true); } }); } }; setIsVisible(control.isVisible(), false); control.addListener(SWT.Show, lShowHide); control.addListener(SWT.Hide, lShowHide); final Shell shell = control.getShell(); shell.addListener(SWT.Show, lShowHide); shell.addListener(SWT.Hide, lShowHide); control.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { disposed = true; shell.removeListener(SWT.Show, lShowHide); shell.removeListener(SWT.Hide, lShowHide); skin.removeSkinObject(SWTSkinObjectBasic.this); } }); control.addListener(SWT.MouseHover, new Listener() { public void handleEvent(Event event) { String id = getTooltipID(true); if (id == null) { control.setToolTipText(null); } else { control.setToolTipText(MessageText.getString(id, (String) null)); } } }); if (skin.isLayoutComplete()) { skin.attachControl(this); } } /** * @param visible * * @since 3.0.4.3 */ protected boolean setIsVisible(boolean visible, boolean walkup) { //System.out.println(this + " SET IS VISIBLE " + visible + " via " + Debug.getCompressedStackTrace()); if (visible == isVisible) { return false; } isVisible = visible; switchSuffix(null, 0, false); triggerListeners(visible ? SWTSkinObjectListener.EVENT_SHOW : SWTSkinObjectListener.EVENT_HIDE); // only walkup when visible.. yes? if (walkup && visible) { SWTSkinObject p = parent; while (p instanceof SWTSkinObjectBasic) { ((SWTSkinObjectBasic) p).setIsVisible(visible, false); p = ((SWTSkinObjectBasic) p).getParent(); } } return true; } public Control getControl() { return control; } public String getType() { return type; } public String getConfigID() { return sConfigID; } public String getSkinObjectID() { return sID; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#getParent() public SWTSkinObject getParent() { return parent; } public void setBackground(String sConfigID, String sSuffix) { Image imageBG; Image imageBGLeft; Image imageBGRight; if (sConfigID == null) { return; } ImageLoader imageLoader = skin.getImageLoader(properties); String id = null; String idLeft = null; String idRight = null; String s = properties.getStringValue(sConfigID + sSuffix, (String) null); if (s != null && s.length() > 0) { Image[] images = imageLoader.getImages(sConfigID + sSuffix); if (images.length == 1 && ImageLoader.isRealImage(images[0])) { id = sConfigID + sSuffix; idLeft = id + "-left"; idRight = id + "-right"; } else if (images.length == 3 && ImageLoader.isRealImage(images[2])) { id = sConfigID + sSuffix; idLeft = id; idRight = id; } else if (images.length == 2 && ImageLoader.isRealImage(images[1])) { id = sConfigID + sSuffix; idLeft = id; idRight = id + "-right"; } else { id = sConfigID + sSuffix; //if (sSuffix.length() > 0) { // setBackground(sConfigID, ""); //} return; } } else { if (s != null && painter != null) { painter.dispose(); painter = null; } if (s == null) { //if (sSuffix.length() > 0) { // setBackground(sConfigID, ""); //} } return; } if (painter == null) { //control.setBackgroundImage doesn't handle transparency! //control.setBackgroundImage(image); // Workaround: create our own image with shell's background // for "transparent" area. Doesn't allow control's image to show // through. To do that, we'd have to walk up the tree until we // found a composite with an image //control.setBackgroundMode(SWT.INHERIT_NONE); //control.setBackgroundImage(imageBG); String sTileMode = properties.getStringValue(sConfigID + ".drawmode"); int tileMode = SWTSkinUtils.getTileMode(sTileMode); // painter = new SWTBGImagePainter(control, imageBGLeft, imageBGRight, // imageBG, tileMode); painter = new SWTBGImagePainter(control, imageLoader, idLeft, idRight, id, tileMode); } else { //System.out.println("setImage " + sConfigID + " " + sSuffix); painter.setImage(imageLoader, idLeft, idRight, id); } // XXX Is this needed? It causes flicker and slows things down. // Maybe a redraw instead (if anything at all)? //control.update(); } // @see java.lang.Object#toString() public String toString() { String s = "SWTSkinObjectBasic {" + sID; if (!sID.equals(sConfigID)) { s += "/" + sConfigID; } if (sViewID != null) { s += "/v=" + sViewID; } s += ", " + type + "; parent=" + ((parent == null) ? null : parent.getSkinObjectID() + "}"); return s; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#getSkin() public SWTSkin getSkin() { return skin; } // @see java.lang.Object#equals(java.lang.Object) public boolean equals(Object obj) { if (obj instanceof SWTSkinObject) { SWTSkinObject skinObject = (SWTSkinObject) obj; boolean bEquals = skinObject.getSkinObjectID().equals(sID); if (parent != null) { return bEquals && parent.equals(skinObject.getParent()); } return bEquals; } return super.equals(obj); } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#setVisible(boolean) public void setVisible(final boolean visible) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (control != null && !control.isDisposed()) { Object ld = control.getLayoutData(); if (ld instanceof FormData) { FormData fd = (FormData) ld; if (!visible) { if (fd.width != 0 && fd.height != 0) { control.setData("oldSize", new Point(fd.width, fd.height)); } fd.width = 0; fd.height = 0; } else { Object oldSize = control.getData("oldSize"); Point oldSizePoint = (oldSize instanceof Point) ? (Point) oldSize : new Point(SWT.DEFAULT, SWT.DEFAULT); if (fd.width <= 0) { fd.width = oldSizePoint.x; } if (fd.height <= 0) { fd.height = oldSizePoint.y; } } control.setLayoutData(fd); control.getParent().layout(true); Utils.relayout(control); } control.setVisible(visible); setIsVisible(visible, true); } } }); } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#setDefaultVisibility() public void setDefaultVisibility() { if (sConfigID == null) { return; } setVisible(getDefaultVisibility()); } public boolean getDefaultVisibility() { return properties.getBooleanValue(sConfigID + ".visible", true); } public boolean isVisible() { if (control == null || control.isDisposed()) { return false; } return isVisible; } /** * Switch the suffix using the default of 1 for level and false for walkUp */ public String switchSuffix(String suffix) { return switchSuffix(suffix, 1, false); } public final String switchSuffix(String suffix, int level, boolean walkUp) { return switchSuffix(suffix, level, walkUp, true); } public String switchSuffix(String newSuffixEntry, int level, boolean walkUp, boolean walkDown) { if (walkUp) { SWTSkinObject parentSkinObject = parent; SWTSkinObject skinObject = this; // Move up the tree until propogation stops while ((parentSkinObject instanceof SWTSkinObjectContainer) && ((SWTSkinObjectContainer) parentSkinObject).getPropogation()) { skinObject = parentSkinObject; parentSkinObject = parentSkinObject.getParent(); } if (skinObject != this) { //System.out.println(sConfigID + suffix + "; walkup"); skinObject.switchSuffix(newSuffixEntry, level, false); return null; } } String old = getSuffix(); if (level > 0) { //System.out.println(SystemTime.getCurrentTime() + ": " + this + suffix + "; switchy"); if (suffixes == null) { old = null; suffixes = new String[level]; } else if (suffixes.length < level) { String[] newSuffixes = new String[level]; System.arraycopy(suffixes, 0, newSuffixes, 0, suffixes.length); suffixes = newSuffixes; } suffixes[level - 1] = newSuffixEntry; } String fullSuffix = getSuffix(); if (newSuffixEntry != null) { if (sConfigID == null || control == null || control.isDisposed() || !isVisible || (newSuffixEntry != null && fullSuffix.equals(old))) { return fullSuffix; } } final String sSuffix = fullSuffix; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (control == null || control.isDisposed()) { return; } boolean needPaintHook = false; if (properties.hasKey(sConfigID + ".color" + sSuffix)) { control.removeListener(SWT.Resize, resizeGradientBGListener); Color color = properties.getColor(sConfigID + ".color" + sSuffix); bgColor = color; String colorStyle = properties.getStringValue(sConfigID + ".color.style" + sSuffix); if (colorStyle != null) { String[] split = colorStyle.split(","); if (split.length > 2) { try { colorFillParams = new int[] { Integer.parseInt(split[1]), Integer.parseInt(split[2]) }; } catch (NumberFormatException e) { //ignore } } if (split[0].equals("rounded")) { colorFillType = BORDER_ROUNDED; needPaintHook = true; } else if (split[0].equals("rounded-fill")) { colorFillType = BORDER_ROUNDED_FILL; needPaintHook = true; } else if (split[0].equals("gradient")) { colorFillType = BORDER_GRADIENT; Device device = Display.getDefault(); for (int i = 1; i < split.length; i += 2) { Color colorStop = ColorCache.getColor(device, split[i]); double posStop = 1; if (i != split.length - 1) { try { posStop = Double.parseDouble(split[i+1]); } catch (Exception ignore) { } } listGradients.add(new GradientInfo(colorStop, posStop)); } control.addListener(SWT.Resize, resizeGradientBGListener); resizeGradientBGListener.handleEvent(null); } control.redraw(); control.setBackground(null); } else { control.setBackground(bgColor); } } if (properties.hasKey(sConfigID + ".fgcolor" + sSuffix)) { Color fg = properties.getColor(sConfigID + ".fgcolor" + sSuffix); control.setForeground(fg); } // Color,[width] String sBorderStyle = properties.getStringValue(sConfigID + ".border" + sSuffix); colorBorder = null; colorBorderParams = null; if (sBorderStyle != null) { String[] split = sBorderStyle.split(","); colorBorder = ColorCache.getColor(control.getDisplay(), split[0]); needPaintHook |= colorBorder != null; if (split.length > 2) { colorBorderParams = new int[] { Integer.parseInt(split[1]), Integer.parseInt(split[2]) }; } } setBackground(sConfigID + ".background", sSuffix); String sCursor = properties.getStringValue(sConfigID + ".cursor"); if (sCursor != null && sCursor.length() > 0) { if (sCursor.equalsIgnoreCase("hand")) { Listener handCursorListener = skin.getHandCursorListener(control.getDisplay()); control.removeListener(SWT.MouseEnter, handCursorListener); control.removeListener(SWT.MouseExit, handCursorListener); control.addListener(SWT.MouseEnter, handCursorListener); control.addListener(SWT.MouseExit, handCursorListener); } } if (!customTooltipID ) { String newToolTipID = properties.getReferenceID(sConfigID + ".tooltip" + sSuffix); if (newToolTipID == null && sSuffix.length() > 0) { newToolTipID = properties.getReferenceID(sConfigID + ".tooltip"); } tooltipID = newToolTipID; } if (!alwaysHookPaintListener && needPaintHook != paintListenerHooked) { if (needPaintHook) { control.addPaintListener(SWTSkinObjectBasic.this); } else { control.removePaintListener(SWTSkinObjectBasic.this); } paintListenerHooked = needPaintHook; } } }); return fullSuffix; } public String getSuffix() { String suffix = ""; if (suffixes == null) { return suffix; } for (int i = 0; i < suffixes.length; i++) { if (suffixes[i] != null) { suffix += suffixes[i]; } } if (suffix.indexOf("-down-over") >= 0) { return suffix.replaceAll("-down-over", "-down"); } return suffix; } /** * @return the properties */ public SWTSkinProperties getProperties() { return properties; } public void setProperties(SWTSkinProperties skinProperties) { this.properties = skinProperties; } /* (non-Javadoc) * @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#addListener(com.aelitis.azureus.ui.swt.skin.SWTSkinObjectListener) */ public void addListener(final SWTSkinObjectListener listener) { listeners_mon.enter(); try { listeners.add(listener); } finally { listeners_mon.exit(); } if (initialized) { listener.eventOccured(this, SWTSkinObjectListener.EVENT_CREATED, null); } if (isVisible && initialized) { Utils.execSWTThread(new AERunnable() { public void runSupport() { listener.eventOccured(SWTSkinObjectBasic.this, SWTSkinObjectListener.EVENT_SHOW, null); } }); } } /* (non-Javadoc) * @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#removeListener(com.aelitis.azureus.ui.swt.skin.SWTSkinObjectListener) */ public void removeListener(SWTSkinObjectListener listener) { listeners_mon.enter(); try { listeners.remove(listener); } finally { listeners_mon.exit(); } } public SWTSkinObjectListener[] getListeners() { return (SWTSkinObjectListener[]) listeners.toArray(new SWTSkinObjectListener[0]); } public void triggerListeners(int eventType) { triggerListeners(eventType, null); } public void triggerListeners(final int eventType, final Object params) { // delay show and hide events while not initialized if (eventType == SWTSkinObjectListener.EVENT_SHOW || eventType == SWTSkinObjectListener.EVENT_HIDE) { if (!initialized) { //System.out.println("NOT INITIALIZED! " + SWTSkinObjectBasic.this + ";;;" + Debug.getCompressedStackTrace()); return; } if (eventType == SWTSkinObjectListener.EVENT_SHOW && !isVisible) { return; } else if (eventType == SWTSkinObjectListener.EVENT_HIDE && isVisible) { return; } } else if (eventType == SWTSkinObjectListener.EVENT_CREATED) { //System.out.println("INITIALIZED! " + SWTSkinObjectBasic.this + ";;;" + Debug.getCompressedStackTrace()); initialized = true; } // process listeners added locally SWTSkinObjectListener[] listenersArray = getListeners(); if (listenersArray.length > 0) { // don't use iterator as triggering code may try to remove itself for (SWTSkinObjectListener l : listenersArray) { try { l.eventOccured(this, eventType, params); } catch (Exception e) { Debug.out("Skin Event " + SWTSkinObjectListener.NAMES[eventType] + " caused an error for listener added locally", e); } } } // process listeners added to skin SWTSkinObjectListener[] listeners = skin.getSkinObjectListeners(sViewID); if (listeners.length > 0) { for (int i = 0; i < listeners.length; i++) { try { SWTSkinObjectListener l = listeners[i]; l.eventOccured(this, eventType, params); } catch (Exception e) { Debug.out("Skin Event " + SWTSkinObjectListener.NAMES[eventType] + " caused an error for listener added to skin", e); } } } if (eventType == SWTSkinObjectListener.EVENT_CREATED) { triggerListeners(isVisible ? SWTSkinObjectListener.EVENT_SHOW : SWTSkinObjectListener.EVENT_HIDE); } if (eventType == SWTSkinObjectListener.EVENT_SHOW && skinView == null) { String initClass = properties.getStringValue(sConfigID + ".onshow.skinviewclass"); if (initClass != null) { try { Class cla = (Class) Class.forName(initClass); skinView = cla.newInstance(); skinView.setMainSkinObject(this); // this will fire created and show for us addListener(skinView); } catch (Throwable e) { Debug.out(e); } } } } protected void setViewID(String viewID) { sViewID = viewID; } public String getViewID() { return sViewID; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#dispose() public void dispose() { if (disposed) { return; } if (control != null && !control.isDisposed()) { control.dispose(); } if (skinView != null) { removeListener(skinView); if (skinView instanceof UIUpdatable) { UIUpdatable updateable = (UIUpdatable) skinView; try { UIFunctionsManager.getUIFunctions().getUIUpdater().removeUpdater( updateable); } catch (Exception e) { Debug.out(e); } } } } public boolean isDisposed() { return disposed; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#setTooltipID(java.lang.String) public void setTooltipID(final String id) { if (isDisposed()) { return; } if (StringCompareUtils.equals(id, tooltipID)) { return; } tooltipID = id; customTooltipID = true; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#getTooltipID(boolean) public String getTooltipID(boolean walkup) { if (tooltipID != null || !walkup) { return tooltipID; } if (parent != null) { return parent.getTooltipID(true); } return null; } public void paintControl(GC gc) { } // @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent) public final void paintControl(PaintEvent e) { if (bgColor != null) { e.gc.setBackground(bgColor); } paintControl(e.gc); try { e.gc.setAdvanced(true); e.gc.setAntialias(SWT.ON); } catch (Exception ex) { } if (colorFillType > 0) { Rectangle bounds = (control instanceof Composite) ? ((Composite) control).getClientArea() : control.getBounds(); if (colorFillParams != null) { if (colorFillType == BORDER_ROUNDED_FILL) { e.gc.fillRoundRectangle(0, 0, bounds.width, bounds.height, colorFillParams[0], colorFillParams[1]); } else if (colorFillType == BORDER_ROUNDED) { Color oldFG = e.gc.getForeground(); e.gc.setForeground(bgColor); e.gc.drawRoundRectangle(0, 0, bounds.width - 1, bounds.height - 1, colorFillParams[0], colorFillParams[1]); e.gc.setForeground(oldFG); } } // if (colorFillType == BORDER_GRADIENT) { // Color oldFG = e.gc.getForeground(); // e.gc.setForeground(bgColor2); // e.gc.fillGradientRectangle(0, 0, bounds.width - 1, bounds.height - 1, true); // e.gc.setForeground(oldFG); // } } if (colorBorder != null) { e.gc.setForeground(colorBorder); Rectangle bounds = (control instanceof Composite) ? ((Composite) control).getClientArea() : control.getBounds(); bounds.width -= 1; bounds.height -= 1; if (colorBorderParams == null) { e.gc.drawRectangle(bounds); } else { e.gc.drawRoundRectangle(bounds.x, bounds.y, bounds.width, bounds.height, colorBorderParams[0], colorBorderParams[1]); } } } public boolean isAlwaysHookPaintListener() { return alwaysHookPaintListener; } public void setAlwaysHookPaintListener(boolean alwaysHookPaintListener) { this.alwaysHookPaintListener = alwaysHookPaintListener; if (alwaysHookPaintListener && !paintListenerHooked) { control.addPaintListener(SWTSkinObjectBasic.this); paintListenerHooked = true; } } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#getData(java.lang.String) public Object getData(String id) { return mapData.get(id); } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#setData(java.lang.String, java.lang.Object) public void setData(String id, Object data) { if (mapData == Collections.EMPTY_MAP) { mapData = new HashMap(1); } mapData.put(id, data); } // @see org.gudy.azureus2.ui.swt.debug.ObfusticateShell#generateObfusticatedImage() public Image generateObfusticatedImage() { return null; } /** * @param debug the debug to set */ public void setDebug(boolean debug) { this.debug = debug; } /** * @return the debug */ public boolean isDebug() { return debug; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#relayout() public void relayout() { if (!disposed) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (control.isDisposed()) { return; } control.getShell().layout(new Control[] { control }); } }); } } class GradientInfo { public Color color; public double startPoint; public GradientInfo(Color c, double d) { color = c; startPoint = d; } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectListener.java0000644000175000017500000000440411227757444025763 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.skin; /** * Allows monitoring of {@link SWTSkinObject}'s events * * @author TuxPaper * @created Sep 30, 2006 * */ public interface SWTSkinObjectListener { /** * Skin Object was shown */ public static int EVENT_SHOW = 0; /** * Skin Object was hidden */ public static int EVENT_HIDE = 1; /** * Skin Object was selected (activated) */ public static int EVENT_SELECT = 2; /** * Skin Object was destroyed */ public static int EVENT_DESTROY = 3; /** * Skin Object was created. All children are guaranteed to be created. */ public static int EVENT_CREATED = 4; /** * skinObject will be null, params will be an array { View ID, Config ID } * function who creates the object should return a SWTSkinObject */ public static int EVENT_CREATE_REQUEST = 5; /** * skinObject needs to update any text */ public static int EVENT_LANGUAGE_CHANGE = 6; /** * Friendly names of events, useful for debug */ public static String[] NAMES = { "Show", "Hide", "Select", "Destroy", "Created", "Create Request", "Lang Change" }; /** * Called when an event occurs * * @param skinObject skin object the event occurred on * @param eventType EVENT_* constant * @param params Any parameters the event needs to send you */ public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSash.java0000644000175000017500000004246311267755020025073 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.skin; import java.text.NumberFormat; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; /** *

    * Parameters: *

    *
    .startpos
    *
    Position in % or pixels of where to start the sash by default
    *
    .resize.container.min
    *
    *
    .dblclick
    *
    *
    *
    *
    * * @author TuxPaper * @created Oct 18, 2006 * */ public class SWTSkinObjectSash extends SWTSkinObjectBasic { /** * Fast Drag disables resizing left and right sides on each mouse move (when * mouse is down) * * Two problems with disabling FASTDRAG: * 1) The places we use the sash currently have very slow re-rendering * 2) when the user drags out of bounds (minsize, etc), and we set doit * to false. When the user lifts up the mouse button, we get one * selection event at the old position (because we cancelled) * * #2 can be fixed... #1 not so much.. */ private static final boolean FASTDRAG = true; protected String sControlBefore; protected String sControlAfter; private int resizeContainerAboveMin = -1; boolean ignoreContainerAboveMin = false; private Composite createOn; private final boolean isVertical; private Sash sash; Point lastSize = new Point(0, 0); private Composite parentComposite; private Composite above = null; private int aboveMin = 0; private Composite below = null; private int belowMin = 0; private double sashPct; private boolean noresize = false; private String sBorder; public SWTSkinObjectSash(final SWTSkin skin, final SWTSkinProperties properties, final String sID, final String sConfigID, String[] typeParams, SWTSkinObject parent, final boolean bVertical) { super(skin, properties, sID, sConfigID, "sash", parent); isVertical = bVertical; int style = bVertical ? SWT.VERTICAL : SWT.HORIZONTAL; if (typeParams.length > 2) { sControlBefore = typeParams[1]; sControlAfter = typeParams[2]; } if (parent == null) { createOn = skin.getShell(); } else { createOn = (Composite) parent.getControl(); } if (createOn == null || createOn.isDisposed()) { Debug.out("Can not create " + sID + " because parent is null or disposed"); return; } sash = new Sash(createOn, style); noresize = properties.getBooleanValue(sConfigID + ".noresize", false); String sMinContainerPos = properties.getStringValue(sConfigID + ".resize.container.min"); if (sMinContainerPos != null) { try { resizeContainerAboveMin = NumberFormat.getInstance().parse( sMinContainerPos).intValue(); } catch (Exception e) { Debug.out(e); } } int splitAt = COConfigurationManager.getIntParameter("v3." + sID + ".splitAt", -1); int splitAtPX = COConfigurationManager.getIntParameter("v3." + sID + ".splitAtPX", -1); if (noresize && splitAtPX >= 0) { if (splitAtPX < resizeContainerAboveMin) { splitAtPX = resizeContainerAboveMin; } sash.setData("PX", new Long(splitAtPX)); } else if (!noresize && splitAt >= 0) { sashPct = splitAt / 10000.0; if (sashPct > 1) { sashPct = 1; } else if (sashPct < 0) { sashPct = 0; } sash.setData("PCT", new Double(sashPct)); } else { String sPos = properties.getStringValue(sConfigID + ".startpos"); if (sPos != null) { try { long l = NumberFormat.getInstance().parse(sPos).longValue(); if (sPos.endsWith("%")) { sashPct = (double) l / 100; sash.setData("PCT", new Double(sashPct)); } else { sash.setData("PX", new Long(l)); } } catch (Exception e) { Debug.out(e); } } } parentComposite = createOn; SWTSkinObject soInitializeSashAfterCreated = parent == null ? this : parent; soInitializeSashAfterCreated.addListener(new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == SWTSkinObjectListener.EVENT_CREATED) { initialize(); } return null; } }); String sDblClick = properties.getStringValue(sConfigID + ".dblclick"); if (sDblClick != null) { sDblClick = sDblClick.toLowerCase(); final int dir = (sDblClick.equals("left")) ? SWT.LEFT : SWT.RIGHT; sash.addListener(SWT.MouseDoubleClick, new Listener() { // @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) public void handleEvent(Event e) { if (below == null || above == null) { return; } Double oldPCT = (Double) sash.getData("PCT"); if (oldPCT == null) { oldPCT = new Double(-1); } double pct; if (dir == SWT.LEFT) { if (oldPCT.doubleValue() == 1) { pct = 0; } else { pct = 1; } } else { if (oldPCT.doubleValue() == 0) { pct = 1; } else { pct = 0; } } setPercent(pct, sash, above, below, bVertical, parentComposite, aboveMin, belowMin); above.getParent().layout(); } }); } // dblclick sBorder = properties.getStringValue(sConfigID + ".border", (String) null); if (sBorder != null) { sash.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { e.gc.setForeground(e.gc.getDevice().getSystemColor( SWT.COLOR_WIDGET_NORMAL_SHADOW)); Point size = sash.getSize(); if (bVertical) { e.gc.drawLine(0, 0, 0, size.y); if (!sBorder.startsWith("thin-top")) { int x = size.x - 1; e.gc.drawLine(x, 0, x, 0 + size.y); } } else { e.gc.drawLine(0, 0, 0 + size.x, 0); if (!sBorder.startsWith("thin-top")) { int y = size.y - 1; e.gc.drawLine(0, y, 0 + size.x, y); } } } }); } setControl(sash); } /** * * * @since 3.1.0.1 */ protected void initialize() { SWTSkinObject skinObject; skinObject = skin.getSkinObjectByID(sControlBefore); if (skinObject != null) { above = (Composite) skinObject.getControl(); aboveMin = skinObject.getProperties().getIntValue( getConfigID() + ".above" + (isVertical ? ".minwidth" : ".minheight"), 0); } skinObject = skin.getSkinObjectByID(sControlAfter); if (skinObject != null) { below = (Composite) skinObject.getControl(); } if (below == null) { return; } belowMin = skinObject.getProperties().getIntValue( getConfigID() + ".below" + (isVertical ? ".minwidth" : ".minheight"), 0); Listener l = new Listener() { private boolean skipResize = false; public void handleEvent(Event e) { if (e.type == SWT.MouseUp) { if (e.button == 3 || (e.button == 1 && (e.stateMask & SWT.MOD1) > 0)) { String sPos = properties.getStringValue(sConfigID + ".startpos"); if (sPos == null) { return; } try { long l = NumberFormat.getInstance().parse(sPos).longValue(); if (sPos.endsWith("%")) { sashPct = (double) l / 100; sash.setData("PCT", new Double(sashPct)); } else { sash.setData("PX", new Long(l)); sash.setData("PCT", null); } // FALL THROUGH e.type = SWT.Show; } catch (Exception ex) { Debug.out(ex); return; } } else { return; } } if (e.type == SWT.Resize && skipResize) { return; } if (e.type == SWT.Resize || e.type == SWT.Show) { handleShowResize(e); } else if (e.type == SWT.Selection) { skipResize = true; if (FASTDRAG && e.detail == SWT.DRAG) { return; } Rectangle area = parentComposite.getBounds(); FormData aboveData = (FormData) above.getLayoutData(); FormData belowData = (FormData) below.getLayoutData(); if (isVertical) { // Need to figure out if we have to use border width elsewhere // in calculations (probably) aboveData.width = e.x - above.getBorderWidth(); if (aboveData.width < aboveMin) { aboveData.width = aboveMin; e.x = aboveMin; } else { int excess = area.width - (above.getBorderWidth() * 2) - sash.getSize().x; if (excess - aboveData.width < belowMin) { aboveData.width = excess - belowMin; e.doit = false; } } ignoreContainerAboveMin = aboveData.width < resizeContainerAboveMin; } else { aboveData.height = e.y - above.getBorderWidth(); if (aboveData.height < aboveMin) { aboveData.height = aboveMin; e.y = aboveMin; } else { int excess = area.height - (above.getBorderWidth() * 2) - sash.getSize().y; if (excess - aboveData.height < belowMin) { aboveData.height = excess - belowMin; e.doit = false; } } } parentComposite.layout(true); double d; double aboveNewSize; if (isVertical) { aboveNewSize = above.getBounds().width + (sash.getSize().x / 2.0); d = aboveNewSize / parentComposite.getBounds().width; } else { aboveNewSize = above.getBounds().height + (sash.getSize().y / 2.0); d = aboveNewSize / parentComposite.getBounds().height; } sashPct = ensureVisibilityStates(d, above, below, isVertical); sash.setData("PCT", new Double(sashPct)); if (noresize) { sash.setData("PX", new Long((long) aboveNewSize)); } if (e.detail != SWT.DRAG) { COConfigurationManager.setParameter("v3." + sID + ".splitAt", (int) (sashPct * 10000)); } skipResize = false; } } }; if (!noresize) { createOn.addListener(SWT.Resize, l); } sash.addListener(SWT.Selection, l); sash.addListener(SWT.MouseUp, l); sash.getShell().addListener(SWT.Show, l); Event event = new Event(); event.type = SWT.Show; handleShowResize(event); } public void dispose() { if (noresize) { Long px = (Long) sash.getData("PX"); if (px != null && px.longValue() != 0) { COConfigurationManager.setParameter("v3." + sID + ".splitAtPX", px.longValue()); } } super.dispose(); } /** * @param e * * @since 3.1.0.1 */ protected void handleShowResize(Event e) { if (!createOn.isVisible() && e.type != SWT.Show) { return; } Double l = (Double) sash.getData("PCT"); Long px = (Long) sash.getData("PX"); if (noresize && px == null && e.type != SWT.Show) { Point size = createOn.getSize(); size.x -= createOn.getBorderWidth() * 2; size.x -= sash.getSize().x; px = new Long((long) (size.x * l.doubleValue())); sash.setData("PX", px); } if (l != null && (!noresize || e.type == SWT.Show)) { Point size = createOn.getSize(); if (isVertical && size.x == lastSize.x) { return; } else if (!isVertical && size.y == lastSize.y) { return; } lastSize = size; setPercent(l.doubleValue(), sash, above, below, isVertical, parentComposite, aboveMin, belowMin); } else if (px != null) { int i = (isVertical) ? parentComposite.getSize().x : parentComposite.getSize().y; if (i == 0) { return; } double pctAbove = px.doubleValue() / i; FormData aboveData = (FormData) above.getLayoutData(); if (aboveData == null) { aboveData = Utils.getFilledFormData(); above.setLayoutData(aboveData); } if (isVertical) { int parentWidth = parentComposite.getBounds().width; aboveData.width = (int) (parentWidth * pctAbove); if (parentWidth - aboveData.width < aboveMin) { aboveData.width = parentWidth - aboveMin; } if (noresize) { sash.setData("PX", new Long(aboveData.width)); } } else { int parentHeight = parentComposite.getBounds().height; aboveData.height = (int) (parentHeight * pctAbove); if (parentHeight - aboveData.width < aboveMin) { aboveData.height = parentHeight - aboveMin; } if (noresize) { sash.setData("PX", new Long(aboveData.height)); } } if (pctAbove >= 0 && pctAbove <= 1.0) { sashPct = pctAbove; sash.setData("PCT", new Double(pctAbove)); } ignoreContainerAboveMin = px.longValue() < resizeContainerAboveMin; // layout in resize is not needed (and causes browser widget to blink) } if (e.type == SWT.Show) { parentComposite.layout(true); } } public void setPercent(double pct) { setPercent(pct, sash, above, below, isVertical, parentComposite, aboveMin, belowMin); } public double getPercent() { if (noresize) { Long px = (Long) sash.getData("PX"); int i = (isVertical) ? parentComposite.getSize().x : parentComposite.getSize().y; return px.doubleValue() / i; } return sashPct; } /** * @param below * @param bVertical * @param parentComposite * @param sash * @param above * */ protected void setPercent(double pctAbove, Control sash, Composite above, Composite below, boolean bVertical, Control parentComposite, int minAbove, int belowMin) { FormData aboveData = (FormData) above.getLayoutData(); if (aboveData == null) { return; } boolean layoutNeeded = false; if (bVertical) { int parentWidth = parentComposite.getBounds().width - (parentComposite.getBorderWidth() * 2) - sash.getSize().x; int newWidth = (int) (parentWidth * pctAbove); if (newWidth != aboveData.width) { aboveData.width = newWidth; layoutNeeded = true; } //System.out.println("ignore=" + ignoreContainerAboveMin + ";above=" + aboveWidth + ";d=" + d); if (!ignoreContainerAboveMin && resizeContainerAboveMin > 0 && pctAbove != 0.0 && pctAbove != 1.0) { minAbove = Math.max(resizeContainerAboveMin, minAbove); } if (pctAbove != 0.0 && parentWidth - aboveData.width - sash.getSize().x < minAbove) { aboveData.width = parentWidth - minAbove - sash.getSize().x; layoutNeeded = true; //d = (double) (aboveData.width + sash.getSize().x) / parentWidth; } else if (aboveData.width < belowMin) { layoutNeeded = true; aboveData.width = belowMin; } else { ignoreContainerAboveMin = aboveData.width <= resizeContainerAboveMin; } if (noresize) { sash.setData("PX", new Long(aboveData.width)); } } else { int parentHeight = parentComposite.getBounds().height - (parentComposite.getBorderWidth() * 2) - sash.getSize().y; int newHeight = (int) (parentHeight * pctAbove); if (aboveData.height != newHeight) { aboveData.height = newHeight; layoutNeeded = true; } if (pctAbove != 0.0 && parentHeight - aboveData.height < minAbove && parentHeight >= minAbove) { aboveData.height = parentHeight - minAbove; layoutNeeded = true; } else if (aboveData.height < belowMin) { layoutNeeded = true; aboveData.height = belowMin; } if (noresize) { sash.setData("PX", new Long(aboveData.height)); } } if (layoutNeeded) { above.getParent().layout(); } pctAbove = ensureVisibilityStates(pctAbove, above, below, bVertical); sash.setData("PCT", new Double(pctAbove)); sashPct = pctAbove; if (sashPct != 0 && sashPct != 100) { COConfigurationManager.setParameter("v3." + sID + ".splitAt", (int) (pctAbove * 10000)); } } private double ensureVisibilityStates(double pct, Composite above, Composite below, boolean bVertical) { if (pct > 1) { pct = 1; } else if (pct < 0) { pct = 0; } int sizeBelow = bVertical ? below.getSize().x : below.getSize().y; int sizeAbove = bVertical ? above.getSize().x : above.getSize().y; if ((pct == 1.0 || sizeBelow <= 1) && below != null && below.getVisible()) { below.setVisible(false); below.setData("SashSetVisibility", new Boolean(true)); } else if (below != null && !below.isVisible() && (below.getData("SashSetVisibility") != null)) { below.setVisible(true); below.setData("SashSetVisibility", null); } if ((pct == 0.0 || sizeAbove <= 1) && above != null && above.getVisible()) { above.setVisible(false); above.setData("SashSetVisibility", new Boolean(true)); } else if (above != null && !above.isVisible() && (above.getData("SashSetVisibility") != null)) { above.setVisible(true); above.setData("SashSetVisibility", null); } return pct; } /** * @param toolbarHeight * * @since 3.1.1.1 */ public void setBelowPX(int px) { double sashHeight = sash.getSize().y; double parentHeight = parentComposite.getBounds().height - (parentComposite.getBorderWidth() * 2); double want = parentHeight - sashHeight - px; double pct = want / parentHeight; setPercent(pct); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinButtonUtility.java0000644000175000017500000001503511157635304025700 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.skin; import java.util.ArrayList; import java.util.Iterator; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; /** * Simple encapsulation of SWTSkinObjectContainer that provides typical button * funtionality * */ public class SWTSkinButtonUtility { ArrayList listeners = new ArrayList(); private final SWTSkinObject skinObject; private final String imageViewID; public static class ButtonListenerAdapter { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { } /** * * @param buttonUtility * * @deprecated */ public void pressed(SWTSkinButtonUtility buttonUtility) { } public boolean held(SWTSkinButtonUtility buttonUtility) { return false; } public void disabledStateChanged(SWTSkinButtonUtility buttonUtility, boolean disabled) { } } public SWTSkinButtonUtility(SWTSkinObject skinObject) { this(skinObject, null); } public SWTSkinButtonUtility(SWTSkinObject skinObject, String imageViewID) { this.skinObject = skinObject; this.imageViewID = imageViewID; if (skinObject instanceof SWTSkinObjectButton) { return; } Listener l = new Listener() { boolean bDownPressed; private TimerEvent timerEvent; public void handleEvent(Event event) { if (event.type == SWT.MouseDown) { if (timerEvent == null) { timerEvent = SimpleTimer.addEvent("MouseHold", SystemTime.getOffsetTime(1000), new TimerEventPerformer() { public void perform(TimerEvent event) { timerEvent = null; if (!bDownPressed) { return; } bDownPressed = false; boolean stillPressed = true; for (Iterator iter = listeners.iterator(); iter.hasNext();) { ButtonListenerAdapter l = (ButtonListenerAdapter) iter.next(); stillPressed &= !l.held(SWTSkinButtonUtility.this); } bDownPressed = stillPressed; } }); } bDownPressed = true; return; } else { if (timerEvent != null) { timerEvent.cancel(); timerEvent = null; } if (!bDownPressed) { return; } } bDownPressed = false; if (isDisabled()) { return; } for (Iterator iter = listeners.iterator(); iter.hasNext();) { ButtonListenerAdapter l = (ButtonListenerAdapter) iter.next(); l.pressed(SWTSkinButtonUtility.this); l.pressed(SWTSkinButtonUtility.this, SWTSkinButtonUtility.this.skinObject, event.stateMask); } } }; if (skinObject instanceof SWTSkinObjectContainer) { Utils.addListenerAndChildren((Composite) skinObject.getControl(), SWT.MouseUp, l); Utils.addListenerAndChildren((Composite) skinObject.getControl(), SWT.MouseDown, l); } else { skinObject.getControl().addListener(SWT.MouseUp, l); skinObject.getControl().addListener(SWT.MouseDown, l); } } public boolean isDisabled() { return skinObject.getSuffix().indexOf("-disabled") >= 0; } private boolean inSetDisabled = false; public void setDisabled(boolean disabled) { if (inSetDisabled) { return; } inSetDisabled = true; try { if (disabled == isDisabled()) { return; } String suffix = disabled ? "-disabled" : ""; skinObject.switchSuffix(suffix, 1, false); for (Iterator iter = listeners.iterator(); iter.hasNext();) { ButtonListenerAdapter l = (ButtonListenerAdapter) iter.next(); l.disabledStateChanged(SWTSkinButtonUtility.this, disabled); } } finally { inSetDisabled = false; } } public void addSelectionListener(ButtonListenerAdapter listener) { if (skinObject instanceof SWTSkinObjectButton) { ((SWTSkinObjectButton)skinObject).addSelectionListener(listener); return; } if (listeners.contains(listener)) { return; } listeners.add(listener); } public SWTSkinObject getSkinObject() { return skinObject; } public void setTextID(final String id) { if (skinObject instanceof SWTSkinObjectButton) { ((SWTSkinObjectButton)skinObject).setText(MessageText.getString(id)); return; } Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { if (skinObject instanceof SWTSkinObjectText) { SWTSkinObjectText skinTextObject = (SWTSkinObjectText) skinObject; skinTextObject.setTextID(id); } else if (skinObject instanceof SWTSkinObjectContainer) { SWTSkinObject[] children = ((SWTSkinObjectContainer) skinObject).getChildren(); if (children.length > 0 && children[0] instanceof SWTSkinObjectText) { SWTSkinObjectText skinTextObject = (SWTSkinObjectText) children[0]; skinTextObject.setTextID(id); } } Utils.relayout(skinObject.getControl()); } }); } public void setImage(final String id) { if (skinObject instanceof SWTSkinObjectButton) { // TODO implement return; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (imageViewID != null) { SWTSkinObject skinImageObject = skinObject.getSkin().getSkinObject(imageViewID, skinObject); if (skinImageObject instanceof SWTSkinObjectImage) { ((SWTSkinObjectImage) skinImageObject).setImageByID(id, null); return; } } if (skinObject instanceof SWTSkinObjectImage) { SWTSkinObjectImage skinImageObject = (SWTSkinObjectImage) skinObject; skinImageObject.setImageByID(id, null); } else if (skinObject instanceof SWTSkinObjectContainer) { SWTSkinObject[] children = ((SWTSkinObjectContainer) skinObject).getChildren(); if (children.length > 0 && children[0] instanceof SWTSkinObjectImage) { SWTSkinObjectImage skinImageObject = (SWTSkinObjectImage) children[0]; skinImageObject.setImageByID(id, null); } } } }); } public void setTooltipID(final String id) { if (skinObject instanceof SWTSkinObjectButton) { // TODO implement return; } if (skinObject instanceof SWTSkinObjectImage) { SWTSkinObjectImage skinImageObject = (SWTSkinObjectImage) skinObject; skinImageObject.setTooltipID(id); } else if (skinObject instanceof SWTSkinObjectContainer) { SWTSkinObject[] children = ((SWTSkinObjectContainer) skinObject).getChildren(); if (children.length > 0 && children[0] instanceof SWTSkinObjectImage) { SWTSkinObjectImage skinImageObject = (SWTSkinObjectImage) children[0]; skinImageObject.setTooltipID(id); } } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSeparator.java0000644000175000017500000000122111002321702026077 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.skin; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; public class SWTSkinObjectSeparator extends SWTSkinObjectBasic { private Label separator; public SWTSkinObjectSeparator(SWTSkin skin, SWTSkinProperties properties, String sid, String configID, SWTSkinObject parent) { super(skin, properties, sid, configID, "separator", parent); Composite createOn; if (parent == null) { createOn = skin.getShell(); } else { createOn = (Composite) parent.getControl(); } separator = new Label(createOn, SWT.NONE); setControl(separator); } }azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTTextPaintListener.java0000644000175000017500000000436110572025362025637 0ustar adrianadrian/** * */ package com.aelitis.azureus.ui.swt.skin; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; /** * @author TuxPaper * @created Jun 8, 2006 * * XXX NOT USED XXX */ public class SWTTextPaintListener implements PaintListener { private int align; private Color bgcolor; private Color fgcolor; private Font font; private String text; private SWTSkinProperties skinProperties; /** * */ public SWTTextPaintListener(SWTSkin skin, Control createOn, String sConfigID) { skinProperties = skin.getSkinProperties(); bgcolor = skinProperties.getColor(sConfigID + ".color"); text = skinProperties.getStringValue(sConfigID + ".text"); fgcolor = skinProperties.getColor(sConfigID + ".text.color"); align = SWT.NONE; String sAlign = skinProperties.getStringValue(sConfigID + ".align"); if (sAlign != null) { align = SWTSkinUtils.getAlignment(sAlign, SWT.NONE); } String sSize = skinProperties.getStringValue(sConfigID + ".text.size"); if (sSize != null) { FontData[] fd = createOn.getFont().getFontData(); try { char firstChar = sSize.charAt(0); if (firstChar == '+' || firstChar == '-') { sSize = sSize.substring(1); } int iSize = Integer.parseInt(sSize); if (firstChar == '+') { fd[0].height += iSize; } else if (firstChar == '-') { fd[0].height -= iSize; } else { fd[0].height = iSize; } font = new Font(createOn.getDisplay(), fd); createOn.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { font.dispose(); } }); } catch (NumberFormatException e) { e.printStackTrace(); } } } public void paintControl(PaintEvent e) { e.gc.setClipping(e.x, e.y, e.width, e.height); if (bgcolor != null) { e.gc.setBackground(bgcolor); } if (fgcolor != null) { e.gc.setForeground(fgcolor); } if (font != null) { e.gc.setFont(font); } if (text != null) { Rectangle clientArea = ((Composite) e.widget).getClientArea(); GCStringPrinter.printString(e.gc, text, clientArea, true, true, align); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinImageChanger.java0000644000175000017500000000755211073641616025360 0ustar adrianadrian/** * */ package com.aelitis.azureus.ui.swt.skin; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.*; /** * @author TuxPaper * @created Jun 8, 2006 * */ public class SWTSkinImageChanger implements Listener { private final static boolean DEBUG = false; private final String suffix; private final int eventOn; private final int eventOff; private Control lastControl; /** * Default Constructor * * @param suffix * @param eventOff * @param eventOn */ public SWTSkinImageChanger(String suffix, int eventOn, int eventOff) { this.suffix = suffix; this.eventOn = eventOn; this.eventOff = eventOff; } public void handleEvent(Event event) { Control control = (Control) event.widget; if (control == null) { return; } //System.out.println("event " + event.type + ";" + control.handle); try { boolean isExit = event.type == SWT.MouseExit || event.type == SWT.Deactivate; if (isExit && lastControl != null) { if (control.getParent() == lastControl) { if (DEBUG) { System.out.println("skip because parent is last control"); } return; } } SWTSkinObject skinObject = (SWTSkinObject) control.getData("SkinObject"); if (skinObject != null && (DEBUG || skinObject.isDebug())) { System.out.println("exit " + skinObject); } if (isExit && (skinObject instanceof SWTSkinObjectContainer)) { // check if exiting and going into child SWTSkinObjectContainer soContainer = (SWTSkinObjectContainer) skinObject; if (soContainer.getPropogation()) { Point pt = control.toDisplay(event.x, event.y); Composite composite = soContainer.getComposite(); Point relPt = composite.toControl(pt); // mouse exit and enter happens on client area (not full widget area) Rectangle bounds = composite.getClientArea(); if (bounds.contains(relPt) && composite.getDisplay().getActiveShell() != null) { if (skinObject != null && (DEBUG || skinObject.isDebug())) { System.out.println("skip " + skinObject + " because going into child"); } return; } } } if (isExit && control.getParent() != null) { // check if exiting and going into parent Composite parent = control.getParent(); SWTSkinObject soParent = (SWTSkinObject) parent.getData("SkinObject"); if (soParent != null && (soParent instanceof SWTSkinObjectContainer)) { SWTSkinObjectContainer container = (SWTSkinObjectContainer) soParent; if (container.getPropogation()) { Point pt = control.toDisplay(event.x, event.y); Point relPt = container.getComposite().toControl(pt); Rectangle bounds = parent.getClientArea(); if (bounds.contains(relPt) && parent.getDisplay().getActiveShell() != null) { if (skinObject != null && (DEBUG || skinObject.isDebug())) { System.out.println("skip " + skinObject + " because going into parent " + bounds + ";" + relPt + ";" + parent.getDisplay().getActiveShell()); } // XXX Disabled for now as it doesn't always work //return; } } } } if (skinObject != null) { String sSuffix = (event.type == eventOn) ? suffix : ""; if (skinObject != null && (DEBUG || skinObject.isDebug())) { System.out.println(System.currentTimeMillis() + ": " + skinObject + "--" + sSuffix); } Point ptMouse = control.toDisplay(0, 0); while (skinObject != null) { Rectangle bounds = skinObject.getControl().getBounds(); Point pt = skinObject.getControl().toDisplay(0, 0); bounds.x = pt.x; bounds.y = pt.y; if (bounds.contains(ptMouse)) { skinObject.switchSuffix(sSuffix, 2, false, false); skinObject = skinObject.getParent(); } else { break; } } } } finally { lastControl = control; } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinUtils.java0000644000175000017500000002325711266266270024151 0ustar adrianadrian/** * */ package com.aelitis.azureus.ui.swt.skin; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AERunnableBoolean; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; /** * @author TuxPaper * @created Jun 8, 2006 * */ public class SWTSkinUtils { public static final int TILE_NONE = 0; public static final int TILE_Y = 1; public static final int TILE_X = 2; public static final int TILE_CENTER_X = 4; public static final int TILE_CENTER_Y = 8; public static final int TILE_BOTH = TILE_X | TILE_Y; private static Listener imageDownListener; //private static Listener imageOverListener; static { //imageOverListener = new SWTSkinImageChanger("-over", SWT.MouseEnter, // SWT.MouseExit); imageDownListener = new SWTSkinImageChanger("-down", SWT.MouseDown, SWT.MouseUp); } public static int getAlignment(String sAlign, int def) { int align; if (sAlign == null) { align = def; } else if (sAlign.equalsIgnoreCase("center")) { align = SWT.CENTER; } else if (sAlign.equalsIgnoreCase("bottom")) { align = SWT.BOTTOM; } else if (sAlign.equalsIgnoreCase("top")) { align = SWT.TOP; } else if (sAlign.equalsIgnoreCase("left")) { align = SWT.LEFT; } else if (sAlign.equalsIgnoreCase("right")) { align = SWT.RIGHT; } else { align = def; } return align; } /** * @param tileMode * @return */ public static int getTileMode(String sTileMode) { int tileMode = TILE_NONE; if (sTileMode == null || sTileMode == "") { return tileMode; } sTileMode = sTileMode.toLowerCase(); if (sTileMode.equals("tile")) { tileMode = TILE_X | TILE_Y; } else if (sTileMode.equals("tile-x")) { tileMode = TILE_X; } else if (sTileMode.equals("tile-y")) { tileMode = TILE_Y; } else if (sTileMode.equals("center-x")) { tileMode = TILE_CENTER_X; } else if (sTileMode.equals("center-y")) { tileMode = TILE_CENTER_Y; } return tileMode; } static void addMouseImageChangeListeners(Control widget) { if (widget.getData("hasMICL") != null) { return; } //widget.addListener(SWT.MouseEnter, imageOverListener); //widget.addListener(SWT.MouseExit, imageOverListener); // new MouseEnterExitListener(widget); widget.addListener(SWT.MouseDown, imageDownListener); widget.addListener(SWT.MouseUp, imageDownListener); widget.setData("hasMICL", "1"); } public static void setVisibility(SWTSkin skin, String configID, String viewID, boolean visible) { setVisibility(skin, configID, viewID, visible, true, false); } public static void setVisibility(SWTSkin skin, String configID, String viewID, final boolean visible, boolean save, boolean fast) { SWTSkinObject skinObject = skin.getSkinObject(viewID); if (skinObject == null) { Debug.out("setVisibility on non existing skin object: " + viewID); return; } if (skinObject.isVisible() == visible && skin.getShell().isVisible()) { return; } final Control control = skinObject.getControl(); if (control != null && !control.isDisposed()) { Point size; if (visible) { final FormData fd = (FormData) control.getLayoutData(); size = (Point) control.getData("v3.oldHeight"); //System.out.println(control.getData("SkinID") + " oldHeight = " + size + ";v=" + control.getVisible() + ";s=" + control.getSize()); if (size == null) { size = control.computeSize(SWT.DEFAULT, SWT.DEFAULT); if (fd.height > 0) { size.y = fd.height; } if (fd.width > 0) { size.x = fd.width; } } } else { size = new Point(0, 0); } setVisibility(skin, configID, skinObject, size, save, fast, null); } } public static void setVisibility(SWTSkin skin, String configID, final SWTSkinObject skinObject, final Point destSize, boolean save, boolean fast, Runnable runAfterSlide) { boolean visible = destSize.x != 0 || destSize.y != 0; try { if (skinObject == null) { return; } final Control control = skinObject.getControl(); if (control != null && !control.isDisposed()) { if (visible) { FormData fd = (FormData) control.getLayoutData(); fd.width = 0; fd.height = 0; control.setData("oldSize", new Point(0, 0)); skinObject.setVisible(visible); // FormData should now be 0,0, but setVisible may have // explicitly changed it fd = (FormData) control.getLayoutData(); if (fd.width != 0 || fd.height != 0) { return; } if (destSize != null) { if (fd != null && (fd.width != destSize.x || fd.height != destSize.y)) { if (fast) { fd.width = destSize.x; fd.height = destSize.y; control.setLayoutData(fd); Utils.relayout(control); } else { slide(skinObject, fd, destSize, runAfterSlide); runAfterSlide = null; // prevent calling again } } } else { if (fd.width == 0) { fd.width = SWT.DEFAULT; } if (fd.height == 0) { fd.height = SWT.DEFAULT; } control.setLayoutData(fd); Utils.relayout(control); } control.setData("v3.oldHeight", null); } else { final FormData fd = (FormData) control.getLayoutData(); if (fd != null) { Point oldSize = new Point(fd.width, fd.height); if (oldSize.y <= 0) { oldSize = null; } control.setData("v3.oldHeight", oldSize); if (fast) { skinObject.setVisible(false); } else { slide(skinObject, fd, destSize, runAfterSlide); runAfterSlide = null; // prevent calling again } } } } } finally { if (save && COConfigurationManager.getBooleanParameter(configID) != visible) { COConfigurationManager.setParameter(configID, visible); } if (runAfterSlide != null) { runAfterSlide.run(); } } } public static void slide(final SWTSkinObject skinObject, final FormData fd, final Point destSize, final Runnable runOnCompletion) { final Control control = skinObject.getControl(); //System.out.println("slide to " + size + " via "+ Debug.getCompressedStackTrace()); boolean exit = Utils.execSWTThreadWithBool("slide", new AERunnableBoolean() { public boolean runSupport() { boolean exit = control.getData("slide.active") != null; Runnable oldROC = (Runnable) control.getData("slide.runOnCompletion"); if (oldROC != null) { oldROC.run(); } control.setData("slide.destSize", destSize); control.setData("slide.runOnCompletion", runOnCompletion); if (destSize.y > 0) { skinObject.setVisible(true); } return exit; } }, 1000); if (exit) { return; } AERunnable runnable = new AERunnable() { boolean firstTime = true; float pct = 0.4f; public void runSupport() { if (control.isDisposed()) { return; } Point size = (Point) control.getData("slide.destSize"); if (size == null) { return; } if (firstTime) { firstTime = false; control.setData("slide.active", "1"); } int newWidth = (int) (fd.width + (size.x - fd.width) * pct); int h = fd.height >= 0 ? fd.height : control.getSize().y; int newHeight = (int) (h + (size.y - h) * pct); pct += 0.01; //System.out.println(control + "] newh=" + newHeight + "/" + newWidth + " to " + size.y); if (newWidth == fd.width && newHeight == h) { fd.width = size.x; fd.height = size.y; //System.out.println(control + "] side to " + size.y + " done" + size.x); control.setLayoutData(fd); Utils.relayout(control); control.getParent().layout(); control.setData("slide.active", null); control.setData("slide.destSize", null); if (newHeight == 0) { skinObject.setVisible(false); Utils.relayout(control); } Runnable oldROC = (Runnable) control.getData("slide.runOnCompletion"); if (oldROC != null) { control.setData("slide.runOnCompletion", null); oldROC.run(); } } else { fd.width = newWidth; fd.height = newHeight; control.setLayoutData(fd); //Utils.relayout(control, false); control.getParent().layout(); Utils.execSWTThreadLater(20, this); } } }; control.getDisplay().asyncExec(runnable); } public static class MouseEnterExitListener implements Listener { boolean bOver = false; public MouseEnterExitListener(Widget widget) { widget.addListener(SWT.MouseMove, this); widget.addListener(SWT.MouseExit, this); } public void handleEvent(Event event) { Control control = (Control) event.widget; SWTSkinObject skinObject = (SWTSkinObject) control.getData("SkinObject"); if (event.type == SWT.MouseMove) { if (bOver) { return; } System.out.println(System.currentTimeMillis() + ": " + skinObject + "-- OVER"); bOver = true; skinObject.switchSuffix("-over", 2, true); } else { bOver = false; System.out.println(System.currentTimeMillis() + ": " + skinObject + "-- NOOVER"); skinObject.switchSuffix("", 2, true); } } } public static SWTSkinObjectBrowser findBrowserSO(SWTSkinObject so) { if (so instanceof SWTSkinObjectBrowser) { return (SWTSkinObjectBrowser) so; } if (so instanceof SWTSkinObjectContainer) { SWTSkinObjectContainer soContainer = (SWTSkinObjectContainer) so; SWTSkinObject[] children = soContainer.getChildren(); for (int i = 0; i < children.length; i++) { SWTSkinObject child = children[i]; SWTSkinObjectBrowser found = findBrowserSO(child); if (found != null) { return found; } } } return null; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinLayoutCompleteListener.java0000644000175000017500000000206610617361126027513 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.skin; /** * @author TuxPaper * @created Apr 18, 2007 * */ public interface SWTSkinLayoutCompleteListener { public void skinLayoutCompleted(); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesParam.java0000644000175000017500000000217410572025362026153 0ustar adrianadrian/* * Created on Jun 27, 2006 1:54:46 AM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; /** * @author TuxPaper * @created Jun 27, 2006 * */ public interface SWTSkinPropertiesParam extends SWTSkinProperties { /** * @return */ String[] getParamValues(); }azureus-4.3.0.6/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesClone.java0000644000175000017500000002141511127403346026151 0ustar adrianadrian/* * Created on Jun 26, 2006 7:25:11 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.skin; import java.util.ResourceBundle; import org.eclipse.swt.graphics.Color; import org.gudy.azureus2.core3.util.Debug; /** * Simple extension of SWTSkinProperties that first checks the original * cloning id before checking the keys that it's cloning. *

    * Cloned Skin Objects will be calling this class with a Config ID of "" plus * whatever property name string they add on. * * @author TuxPaper * @created Jun 26, 2006 * */ public class SWTSkinPropertiesClone implements SWTSkinPropertiesParam { private static final String IGNORE_NAME = ".type"; private static final boolean DEBUG = true; private final SWTSkinProperties properties; private final String sCloneConfigID; private final String sTemplateConfigID; private final String[] sCloneParams; /** * Initialize * * @param properties Where to read properties from * @param sCloneConfigID The config key that told us to clone something */ public SWTSkinPropertiesClone(SWTSkinProperties properties, String sCloneConfigID, String[] sCloneParams) { this.properties = properties; this.sCloneConfigID = sCloneConfigID; this.sCloneParams = sCloneParams; this.sTemplateConfigID = sCloneParams[0]; } /** * @param name */ private void checkName(String name) { if (name.startsWith(sTemplateConfigID)) { System.err.println(name + " shouldn't have template prefix of " + sTemplateConfigID + "; " + Debug.getStackTrace(true, false)); } if (name.startsWith(sCloneConfigID)) { System.err.println(name + " shouldn't have clone prefix of " + sCloneConfigID + "; " + Debug.getStackTrace(true, false)); } } public void addProperty(String name, String value) { properties.addProperty(sCloneConfigID + name, value); } public Color getColor(String name) { if (name == null) { return null; } if (DEBUG) { checkName(name); } if (name.length() > 0 && name.charAt(0) != '.') { return properties.getColor(name); } Color val = properties.getColor(sCloneConfigID + name); if (val != null) { return val; } return properties.getColor(sTemplateConfigID + name); } public int[] getColorValue(String name) { if (name == null) { return new int[] { -1, -1, -1 }; } if (DEBUG) { checkName(name); } if (name.length() > 0 && name.charAt(0) != '.') { return properties.getColorValue(name); } if (!name.equals(IGNORE_NAME)) { int[] val = properties.getColorValue(sCloneConfigID + name); if (val[0] < 0) { return val; } } return properties.getColorValue(sTemplateConfigID + name); } public int getIntValue(String name, int def) { if (name == null) { return def; } if (DEBUG) { checkName(name); } if (name.length() > 0 && name.charAt(0) != '.') { return properties.getIntValue(name, def); } if (!name.equals(IGNORE_NAME)) { if (properties.getStringValue(sCloneConfigID + name) != null) { return properties.getIntValue(sCloneConfigID + name, def); } } return properties.getIntValue(sTemplateConfigID + name, def); } public String[] getStringArray(String name) { if (name == null) { return null; } if (DEBUG) { checkName(name); } if (name.length() > 0 && name.charAt(0) != '.') { return properties.getStringArray(name); } if (!name.equals(IGNORE_NAME)) { String[] val = properties.getStringArray(sCloneConfigID + name, sCloneParams); if (val != null) { return val; } } return properties.getStringArray(sTemplateConfigID + name, sCloneParams); } public String getStringValue(String name, String def) { if (name == null) { return def; } if (DEBUG) { checkName(name); } if (name.length() > 0 && name.charAt(0) != '.') { return properties.getStringValue(name, def); } if (!name.equals(IGNORE_NAME)) { String val = properties.getStringValue(sCloneConfigID + name, sCloneParams); if (val != null) { return val; } } return properties.getStringValue(sTemplateConfigID + name, sCloneParams, def); } public String getStringValue(String name) { if (name == null) { return null; } if (DEBUG) { checkName(name); } if (name.length() > 0 && name.charAt(0) != '.') { return properties.getStringValue(name); } if (!name.equals(IGNORE_NAME)) { String val = properties.getStringValue(sCloneConfigID + name, sCloneParams); if (val != null) { return val; } } return properties.getStringValue(sTemplateConfigID + name, sCloneParams); } public String[] getStringArray(String name, String[] params) { if (name == null) { return null; } if (DEBUG) { checkName(name); } if (name.length() > 0 && name.charAt(0) != '.') { return properties.getStringArray(name, params); } if (!name.equals(IGNORE_NAME)) { String[] val = properties.getStringArray(sCloneConfigID + name, params); if (val != null) { return val; } } return properties.getStringArray(sTemplateConfigID + name, params); } public String getStringValue(String name, String[] params, String def) { if (name == null) { return def; } if (DEBUG) { checkName(name); } if (name.length() > 0 && name.charAt(0) != '.') { return properties.getStringValue(name, params, def); } if (!name.equals(IGNORE_NAME)) { String val = properties.getStringValue(sCloneConfigID + name, params); if (val != null) { return val; } } return properties.getStringValue(sTemplateConfigID + name, params, def); } public String getStringValue(String name, String[] params) { if (name == null) { return null; } if (DEBUG) { checkName(name); } if (name.length() > 0 && name.charAt(0) != '.') { return properties.getStringValue(name, params); } if (!name.equals(IGNORE_NAME)) { String val = properties.getStringValue(sCloneConfigID + name, params); if (val != null) { return val; } } return properties.getStringValue(sTemplateConfigID + name, params); } public SWTSkinProperties getOriginalProperties() { return properties; } public String[] getParamValues() { return sCloneParams; } // @see com.aelitis.azureus.ui.skin.SkinProperties#getBooleanValue(java.lang.String, boolean) public boolean getBooleanValue(String name, boolean def) { if (name == null) { return def; } if (DEBUG) { checkName(name); } if (name.length() > 0 && name.charAt(0) != '.') { return properties.getBooleanValue(name, def); } if (!name.equals(IGNORE_NAME)) { if (properties.getStringValue(sCloneConfigID + name) != null) { return properties.getBooleanValue(sCloneConfigID + name, def); } } return properties.getBooleanValue(sTemplateConfigID + name, def); } // @see com.aelitis.azureus.ui.skin.SkinProperties#clearCache() public void clearCache() { properties.clearCache(); } // @see com.aelitis.azureus.ui.skin.SkinProperties#contains(java.lang.String) public boolean hasKey(String name) { return properties.hasKey(name); } public Color getColor(String name, Color def) { Color color = getColor(name); if (color == null) { return def; } return color; } // @see com.aelitis.azureus.ui.skin.SkinProperties#getReferenceID(java.lang.String) public String getReferenceID(String name) { if (name == null) { return null; } if (DEBUG) { checkName(name); } if (name.length() > 0 && name.charAt(0) != '.') { return properties.getReferenceID(name); } if (!name.equals(IGNORE_NAME)) { String val = properties.getReferenceID(sCloneConfigID + name); if (val != null) { return val; } } return properties.getReferenceID(sTemplateConfigID + name); } // @see com.aelitis.azureus.ui.skin.SkinProperties#addResourceBundle(java.util.ResourceBundle) public void addResourceBundle(ResourceBundle subBundle) { properties.addResourceBundle(subBundle); } // @see com.aelitis.azureus.ui.skin.SkinProperties#getClassLoader() public ClassLoader getClassLoader() { return properties.getClassLoader(); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/layout/0000755000175000017500000000000011310377632021316 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/layout/SimpleReorderableListLayoutData.java0000644000175000017500000000024311022465112030373 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.layout; public class SimpleReorderableListLayoutData { public int position = 0; public int width; public int height; } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/layout/SimpleReorderableListLayout.java0000644000175000017500000000734211131313160027604 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.layout; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Layout; public class SimpleReorderableListLayout extends Layout { public int margin; public boolean wrap; public boolean center; public int borderW = 3; public int borderH = 3; private int itemsPerRow; private int maxHeight = 0; private int maxWidth = 0; private int extraSpacing; private int previouswHint = SWT.DEFAULT; private boolean cached = false; private Point cachedSize = null; protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { if(flushCache || ! cached || cachedSize == null) { Control[] controls = composite.getChildren(); for(int i = 0 ; i < controls.length ; i++) { Object layoutData = controls[i].getLayoutData(); if(layoutData != null && layoutData instanceof SimpleReorderableListLayoutData) { SimpleReorderableListLayoutData sData = (SimpleReorderableListLayoutData) layoutData; if(sData.height > maxHeight) maxHeight = sData.height; if(sData.width > maxWidth) maxWidth = sData.width; } } if((wHint != SWT.DEFAULT || previouswHint != SWT.DEFAULT) && wrap) { if(wHint != SWT.DEFAULT) { previouswHint = wHint; } else { wHint = previouswHint; } itemsPerRow = 1; int width = 2 * borderW + maxWidth; while(width < wHint) { width += margin + maxWidth; if(width < wHint) { itemsPerRow++; } } if(center) { width = 2 * borderW + (margin + maxWidth) * itemsPerRow - margin; extraSpacing = itemsPerRow == 0 ? 0 : (wHint - width) / (itemsPerRow); } else { extraSpacing = 0; } } else { itemsPerRow = controls.length; } //Avoid dividing by 0 when there are no items int nbRows = itemsPerRow > 0 ? (controls.length+itemsPerRow-1) / itemsPerRow : 1; cached = true; cachedSize = new Point(2 * borderW + (maxWidth+margin) * itemsPerRow - margin, 2 * borderH + (margin + maxHeight) * nbRows - margin); } return cachedSize; } protected void layout(Composite composite, boolean flushCache) { Control[] controls = composite.getChildren(); List sortedControls = new ArrayList(controls.length); for(int i = 0 ; i < controls.length ; i++) { sortedControls.add(controls[i]); } Collections.sort(sortedControls,new Comparator() { public int compare(Object o1, Object o2) { Control c1 = (Control) o1; Control c2 = (Control) o2; Object layoutData1 = c1.getLayoutData(); Object layoutData2 = c2.getLayoutData(); if(layoutData1 == null || ! (layoutData1 instanceof SimpleReorderableListLayoutData) ) return 0; if(layoutData2 == null || ! (layoutData2 instanceof SimpleReorderableListLayoutData) ) return 0; SimpleReorderableListLayoutData data1 = (SimpleReorderableListLayoutData) layoutData1; SimpleReorderableListLayoutData data2 = (SimpleReorderableListLayoutData) layoutData2; return data1.position - data2.position; } }); for(int i = 0 ; i < sortedControls.size() ; i++) { int xn = i % itemsPerRow; int yn = i / itemsPerRow; Control control = (Control) sortedControls.get(i); //int x = borderW + (margin + maxWidth + extraSpacing) * xn + extraSpacing; int x = borderW + (margin + maxWidth + extraSpacing) * xn; int y = borderH + (margin + maxHeight) * yn; control.setLocation(x,y); //control.setBounds(x,y,maxWidth,maxHeight); control.setBounds(x,y,maxWidth + extraSpacing,maxHeight); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/0000755000175000017500000000000011310377632021453 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/columns/0000755000175000017500000000000011310377632023133 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_LastSeen.java0000644000175000017500000000361111271263334027256 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.content.columns; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.ui.common.table.TableColumnCore; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnRC_LastSeen implements TableCellRefreshListener { public static final String COLUMN_ID = "rc_lastseen"; /** * * @param sTableID */ public ColumnRC_LastSeen(TableColumn column) { column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_INVISIBLE, 90 ); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); if ( column instanceof TableColumnCore ){ ((TableColumnCore)column).setUseCoreDataSource( true ); } } public void refresh(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if (rc == null) { return; } long last_seen = rc.getLastSeenSecs(); if ( cell.setSortValue( last_seen )){ cell.setText( DisplayFormatters.formatDateShort( last_seen*1000 )); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Level.java0000644000175000017500000000343611252431162026607 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.content.columns; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.ui.common.table.TableColumnCore; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnRC_Level implements TableCellRefreshListener { public static final String COLUMN_ID = "rc_level"; /** * * @param sTableID */ public ColumnRC_Level(TableColumn column) { column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_INVISIBLE, 40 ); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); if ( column instanceof TableColumnCore ){ ((TableColumnCore)column).setUseCoreDataSource( true ); } } public void refresh(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if (rc == null) { return; } int level = rc.getLevel(); if ( cell.setSortValue( level )){ cell.setText( String.valueOf( level )); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Title.java0000644000175000017500000000530211246405524026621 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.content.columns; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.ui.common.table.TableColumnCore; //import com.aelitis.azureus.ui.swt.shells.main.MainWindow; //import org.eclipse.swt.SWT; //import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.plugins.ui.tables.*; //import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnRC_Title implements TableCellRefreshListener //, TableCellMouseListener, TableCellAddedListener { public static final String COLUMN_ID = "rc_title"; /** * * @param sTableID */ public ColumnRC_Title(TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 400); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); if ( column instanceof TableColumnCore ){ ((TableColumnCore)column).setUseCoreDataSource( true ); } } public void refresh(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if (rc == null) { return; } String text = rc.getTitle(); if ( text == null || text.length() == 0 ){ return; } cell.setText(text); } /* public void cellAdded(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if ( cell instanceof TableCellSWT && rc != null ){ ((TableCellSWT)cell).setCursorID( SWT.CURSOR_HAND ); cell.setToolTip( MessageText.getString( "rcm.rc_title.tt" )); } } public void cellMouseTrigger(final TableCellMouseEvent event) { if (event.eventType == TableRowMouseEvent.EVENT_MOUSEDOWN && event.button == 1) { RelatedContent rc = (RelatedContent) event.cell.getDataSource(); if ( rc != null ){ rc.setUnread( false ); String title = rc.getTitle(); MainWindow.doSearch( title ); } } } */ } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_New.java0000644000175000017500000000674411264277162026311 0ustar adrianadrian/** * Created on Sep 25, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.content.columns; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Sep 25, 2008 * */ public class ColumnRC_New implements TableCellSWTPaintListener, TableCellAddedListener, TableCellRefreshListener, TableCellMouseListener { public static final String COLUMN_ID = "rc_new"; private static int WIDTH = 38; // enough to fit title private static Image imgNew; private static Image imgOld; public ColumnRC_New(TableColumn column ) { column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, WIDTH ); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_GRAPHIC); if ( column instanceof TableColumnCore ){ ((TableColumnCore)column).addCellOtherListener("SWTPaint", this ); } imgNew = ImageLoader.getInstance().getImage("image.activity.unread"); imgOld = ImageLoader.getInstance().getImage("image.activity.read"); } public void cellPaint(GC gc, TableCellSWT cell) { RelatedContent entry = (RelatedContent) cell.getDataSource(); Rectangle cellBounds = cell.getBounds(); Image img = entry== null || entry.isUnread() ? imgNew : imgOld; if (img != null && !img.isDisposed()) { Rectangle imgBounds = img.getBounds(); gc.drawImage(img, cellBounds.x + ((cellBounds.width - imgBounds.width) / 2), cellBounds.y + ((cellBounds.height - imgBounds.height) / 2)); } } public void cellAdded(TableCell cell) { cell.setMarginWidth(0); cell.setMarginHeight(0); if ( cell instanceof TableCellSWT ){ ((TableCellSWT)cell).setCursorID( SWT.CURSOR_HAND ); } } public void refresh(TableCell cell) { RelatedContent entry = (RelatedContent) cell.getDataSource(); if ( entry != null ){ boolean unread = entry.isUnread(); long sortVal = ((unread ? 2 : 1) << 62) + entry.getLastSeenSecs(); if (!cell.setSortValue(sortVal) && cell.isValid()) { return; } } } public void cellMouseTrigger(final TableCellMouseEvent event) { if (event.eventType == TableRowMouseEvent.EVENT_MOUSEDOWN && event.button == 1) { RelatedContent entry = (RelatedContent) event.cell.getDataSource(); if ( entry != null ){ entry.setUnread(!entry.isUnread()); event.cell.invalidate(); } } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Seeds.java0000644000175000017500000000364211271263334026607 0ustar adrianadrian/** * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package com.aelitis.azureus.ui.swt.content.columns; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.ui.common.table.TableColumnCore; /** * @author Olivier Chalouhi * @created Oct 7, 2008 * */ public class ColumnRC_Seeds implements TableCellRefreshListener { public static String COLUMN_ID = "rc_seeds"; public ColumnRC_Seeds( TableColumn column ) { column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, 60 ); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); if ( column instanceof TableColumnCore ){ ((TableColumnCore)column).setUseCoreDataSource( true ); } } public void refresh(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if (rc == null) { return; } long seeds = rc.getSeeds(); if ( cell.setSortValue( seeds )){ cell.setText( seeds < 0?"--":String.valueOf(seeds)); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Actions.java0000644000175000017500000001525111245374540027146 0ustar adrianadrian/** * Created on Aug 25, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.content.columns; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter.URLInfo; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.swt.shells.main.MainWindow; import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory; import com.aelitis.azureus.ui.swt.skin.SWTSkinProperties; /** * @author TuxPaper * @created Aug 25, 2009 * */ public class ColumnRC_Actions implements TableCellRefreshListener, TableCellMouseMoveListener, TableCellSWTPaintListener { public static final String COLUMN_ID = "rc_actions"; private static Font font = null; private Color colorLinkNormal; private Color colorLinkHover; public ColumnRC_Actions(TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 215); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_GRAPHIC); if (column instanceof TableColumnCore) { ((TableColumnCore) column).setUseCoreDataSource(true); ((TableColumnCore) column).addCellOtherListener("SWTPaint", this); } SWTSkinProperties skinProperties = SWTSkinFactory.getInstance().getSkinProperties(); colorLinkNormal = skinProperties.getColor("color.links.normal"); colorLinkHover = skinProperties.getColor("color.links.hover"); } public void cellPaint(GC gc, TableCellSWT cell) { String text = cell.getText(); if (text != null && text.length() > 0) { if (font == null) { FontData[] fontData = gc.getFont().getFontData(); fontData[0].setStyle(SWT.BOLD); font = new Font(gc.getDevice(), fontData); } gc.setFont(font); Rectangle bounds = getDrawBounds(cell); GCStringPrinter sp = new GCStringPrinter(gc, text, bounds, true, true, SWT.WRAP | SWT.CENTER); sp.calculateMetrics(); if (sp.hasHitUrl()) { URLInfo[] hitUrlInfo = sp.getHitUrlInfo(); for (int i = 0; i < hitUrlInfo.length; i++) { URLInfo info = hitUrlInfo[i]; // handle fake row when showing in column editor info.urlUnderline = cell.getTableRow() == null || cell.getTableRow().isSelected(); if (info.urlUnderline) { info.urlColor = null; } else { info.urlColor = colorLinkNormal; } } int[] mouseOfs = cell.getMouseOffset(); if (mouseOfs != null) { Rectangle realBounds = cell.getBounds(); URLInfo hitUrl = sp.getHitUrl(mouseOfs[0] + realBounds.x, mouseOfs[1] + realBounds.y); if (hitUrl != null) { hitUrl.urlColor = colorLinkHover; } } } sp.printString(GCStringPrinter.FLAG_FULLLINESONLY); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellAdded(TableCell cell) { cell.setMarginHeight(0); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if (rc == null) { return; } boolean downloadable = rc.getHash() != null; if (!cell.setSortValue(downloadable ? 1 : 0) && cell.isValid()) { return; } String s; s = "" + MessageText.getString("Button.search") + ""; if (downloadable) { s += " | " + MessageText.getString("v3.MainWindow.button.download") + ""; } cell.setText(s); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellMouseListener#cellMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent) public void cellMouseTrigger(TableCellMouseEvent event) { RelatedContent rc = (RelatedContent) event.cell.getDataSource(); if (rc == null) { return; } boolean invalidateAndRefresh = event.eventType == event.EVENT_MOUSEEXIT; Rectangle bounds = ((TableCellSWT) event.cell).getBounds(); String text = event.cell.getText(); GCStringPrinter sp = null; GC gc = new GC(Display.getDefault()); try { if (font != null) { gc.setFont(font); } Rectangle drawBounds = getDrawBounds((TableCellSWT) event.cell); sp = new GCStringPrinter(gc, text, drawBounds, true, true, SWT.WRAP | SWT.CENTER); sp.calculateMetrics(); } catch (Exception e) { Debug.out(e); } finally { gc.dispose(); } if (sp != null) { URLInfo hitUrl = sp.getHitUrl(event.x + bounds.x, event.y + bounds.y); int newCursor; if (hitUrl != null) { if (event.eventType == TableCellMouseEvent.EVENT_MOUSEUP && event.button == 1) { if (hitUrl.url.equals("dl")) { byte[] hash = rc.getHash(); if ( hash != null ){ rc.setUnread( false ); TorrentOpener.openTorrent( ByteFormatter.encodeString( hash )); } } else if (hitUrl.url.equals("search")) { rc.setUnread( false ); String title = rc.getTitle(); MainWindow.doSearch( title ); } } newCursor = SWT.CURSOR_HAND; } else { newCursor = SWT.CURSOR_ARROW; } int oldCursor = ((TableCellSWT) event.cell).getCursorID(); if (oldCursor != newCursor) { invalidateAndRefresh = true; ((TableCellSWT) event.cell).setCursorID(newCursor); } } if (invalidateAndRefresh) { event.cell.invalidate(); ((TableCellSWT)event.cell).redraw(); } } private Rectangle getDrawBounds(TableCellSWT cell) { Rectangle bounds = cell.getBounds(); return bounds; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Peers.java0000644000175000017500000000364511271263334026625 0ustar adrianadrian/** * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package com.aelitis.azureus.ui.swt.content.columns; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.ui.common.table.TableColumnCore; /** * @author Olivier Chalouhi * @created Oct 7, 2008 * */ public class ColumnRC_Peers implements TableCellRefreshListener { public static String COLUMN_ID = "rc_peers"; public ColumnRC_Peers( TableColumn column ) { column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, 60 ); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); if ( column instanceof TableColumnCore ){ ((TableColumnCore)column).setUseCoreDataSource( true ); } } public void refresh(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if (rc == null) { return; } long peers = rc.getLeechers(); if ( cell.setSortValue( peers )){ cell.setText( peers < 0?"--":String.valueOf(peers)); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Created.java0000644000175000017500000000377311271263334027120 0ustar adrianadrian/** * Copyright (C) 2008 Vuze Inc., All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package com.aelitis.azureus.ui.swt.content.columns; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.ui.common.table.TableColumnCore; /** * @author Olivier Chalouhi * @created Oct 7, 2008 * */ public class ColumnRC_Created implements TableCellRefreshListener { public static String COLUMN_ID = "rc_created"; public ColumnRC_Created( TableColumn column ) { column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 90 ); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); if ( column instanceof TableColumnCore ){ ((TableColumnCore)column).setUseCoreDataSource( true ); } } public void refresh(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if (rc == null) { return; } long date = rc.getPublishDate(); if ( cell.setSortValue( date )){ cell.setText( date <= 0?"--":DisplayFormatters.formatCustomDateOnly( date )); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Tracker.java0000644000175000017500000000611311247370226027135 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.content.columns; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.ui.common.table.TableColumnCore; import org.eclipse.swt.SWT; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnRC_Tracker implements TableCellRefreshListener, TableCellAddedListener // , TableCellMouseListener { public static final String COLUMN_ID = "rc_tracker"; public ColumnRC_Tracker(TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_INVISIBLE, 215); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); if ( column instanceof TableColumnCore ){ ((TableColumnCore)column).setUseCoreDataSource( true ); } } public void refresh(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if (rc == null) { return; } String tracker = rc.getTracker(); if ( !validTracker( tracker )){ return; } cell.setText(tracker); } public void cellAdded(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if ( cell instanceof TableCellSWT && rc != null && validTracker( rc.getTracker())){ ((TableCellSWT)cell).setCursorID( SWT.CURSOR_HAND ); cell.setToolTip( MessageText.getString( "rcm.rc_tracker.tt" )); } } public void cellMouseTrigger(final TableCellMouseEvent event) { if (event.eventType == TableRowMouseEvent.EVENT_MOUSEDOWN && event.button == 1) { RelatedContent rc = (RelatedContent) event.cell.getDataSource(); String tracker = rc.getTracker(); if ( validTracker( tracker )){ rc.setUnread( false ); Utils.launch( "http://" + tracker + "/" ); } } } private boolean validTracker( String tracker ) { if ( tracker == null || tracker.length() == 0 ){ return( false ); } int pos = tracker.lastIndexOf( '.' ); if ( pos == -1 ){ return( false ); } for ( int i=pos+1;i 0 && cell.setSortValue( size )){ cell.setText( DisplayFormatters.formatByteCountToKiBEtc( size )); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Rank.java0000644000175000017500000000342211245374540026436 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.content.columns; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.ui.common.table.TableColumnCore; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnRC_Rank implements TableCellRefreshListener { public static final String COLUMN_ID = "rc_rank"; /** * * @param sTableID */ public ColumnRC_Rank(TableColumn column) { column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, 40 ); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); if ( column instanceof TableColumnCore ){ ((TableColumnCore)column).setUseCoreDataSource( true ); } } public void refresh(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if (rc == null) { return; } int rank = rc.getRank(); if ( cell.setSortValue( rank )){ cell.setText( String.valueOf( rank )); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Hash.java0000644000175000017500000000544111247370224026426 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.content.columns; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.ui.common.table.TableColumnCore; import org.eclipse.swt.SWT; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnRC_Hash implements TableCellRefreshListener, TableCellAddedListener // , TableCellMouseListener { public static final String COLUMN_ID = "rc_hash"; /** * * @param sTableID */ public ColumnRC_Hash(TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_INVISIBLE, 215); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); if ( column instanceof TableColumnCore ){ ((TableColumnCore)column).setUseCoreDataSource( true ); } } public void cellAdded(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if ( cell instanceof TableCellSWT && rc != null && rc.getHash() != null ){ ((TableCellSWT)cell).setCursorID( SWT.CURSOR_HAND ); cell.setToolTip( MessageText.getString( "rcm.rc_hash.tt" )); } } public void refresh(TableCell cell) { RelatedContent rc = (RelatedContent) cell.getDataSource(); if (rc == null) { return; } byte[] hash = rc.getHash(); if ( hash == null ){ return; } cell.setText(ByteFormatter.encodeString(hash)); } public void cellMouseTrigger(final TableCellMouseEvent event) { if (event.eventType == TableRowMouseEvent.EVENT_MOUSEDOWN && event.button == 1) { RelatedContent rc = (RelatedContent) event.cell.getDataSource(); byte[] hash = rc.getHash(); if ( hash != null ){ rc.setUnread( false ); TorrentOpener.openTorrent( ByteFormatter.encodeString( hash )); } } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/SBC_RCMView.java0000644000175000017500000005347111300622572024266 0ustar adrianadrian/** * Created on Feb 24, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.content; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.views.table.*; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.core.content.RelatedContentManager; import com.aelitis.azureus.core.content.RelatedContentManagerListener; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.table.*; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.swt.content.columns.*; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectContainer; import com.aelitis.azureus.ui.swt.toolbar.ToolBarEnablerSelectedContent; import com.aelitis.azureus.ui.swt.views.skin.SkinView; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; public class SBC_RCMView extends SkinView implements UIUpdatable, IconBarEnabler, TableViewFilterCheck { public static final String TABLE_RCM = "RCM"; private static boolean columnsAdded = false; private static RelatedContentManager manager; static{ try{ manager = RelatedContentManager.getSingleton(); }catch( Throwable e ){ Debug.out(e); } } private TableViewSWT tv_related_content; private SideBarEntrySWT sidebar_entry; private Composite table_parent; private boolean space_reserved; private Text txtFilter; public Object skinObjectInitialShow( SWTSkinObject skinObject, Object params ) { AzureusCoreFactory.addCoreRunningListener( new AzureusCoreRunningListener() { public void azureusCoreRunning( AzureusCore core ) { initColumns( core ); } }); SideBar sidebar = (SideBar)SkinViewManager.getByClass(SideBar.class); if ( sidebar != null ){ sidebar_entry = sidebar.getCurrentEntry(); sidebar_entry.setIconBarEnabler(this); if ( !sidebar_entry.getId().equals( SideBar.SIDEBAR_SECTION_RELATED_CONTENT )){ manager.reserveTemporarySpace(); space_reserved = true; } } SWTSkinObject soFilterArea = getSkinObject("filterarea"); if (soFilterArea != null) { Composite parent = (Composite) soFilterArea.getControl(); FormData fd; CLabel lblFilter = new CLabel(parent, SWT.CENTER); Messages.setLanguageText(lblFilter, "MyTorrentsView.filter"); fd = Utils.getFilledFormData(); fd.right = null; lblFilter.setLayoutData(fd); txtFilter = new Text(parent, SWT.BORDER); fd = new FormData(); fd.left = new FormAttachment(lblFilter, 10); fd.top = new FormAttachment(lblFilter, 0, SWT.CENTER); fd.right = new FormAttachment(100, -10); txtFilter.setLayoutData(fd); parent.layout(true); } return null; } private void initColumns( AzureusCore core ) { synchronized( SBC_RCMView.class ){ if ( columnsAdded ){ return; } columnsAdded = true; } UIManager uiManager = PluginInitializer.getDefaultInterface().getUIManager(); TableManager tableManager = uiManager.getTableManager(); tableManager.registerColumn( RelatedContent.class, ColumnRC_New.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnRC_New(column); } }); tableManager.registerColumn( RelatedContent.class, ColumnRC_Rank.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnRC_Rank(column); } }); tableManager.registerColumn( RelatedContent.class, ColumnRC_Level.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnRC_Level(column); } }); tableManager.registerColumn( RelatedContent.class, ColumnRC_Title.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnRC_Title(column); } }); tableManager.registerColumn( RelatedContent.class, ColumnRC_Actions.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnRC_Actions(column); } }); tableManager.registerColumn( RelatedContent.class, ColumnRC_Hash.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnRC_Hash(column); } }); tableManager.registerColumn( RelatedContent.class, ColumnRC_Tracker.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnRC_Tracker(column); } }); tableManager.registerColumn( RelatedContent.class, ColumnRC_Size.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnRC_Size(column); } }); tableManager.registerColumn( RelatedContent.class, ColumnRC_Created.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnRC_Created(column); } }); tableManager.registerColumn( RelatedContent.class, ColumnRC_Seeds.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnRC_Seeds(column); } }); tableManager.registerColumn( RelatedContent.class, ColumnRC_Peers.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnRC_Peers(column); } }); tableManager.registerColumn( RelatedContent.class, ColumnRC_LastSeen.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnRC_LastSeen(column); } }); } public Object skinObjectShown( SWTSkinObject skinObject, Object params ) { super.skinObjectShown(skinObject, params); SWTSkinObject so_list = getSkinObject("rcm-list"); if ( so_list != null ){ initTable((Composite) so_list.getControl()); } return null; } public Object skinObjectHidden( SWTSkinObject skinObject, Object params ) { synchronized( this ){ if ( tv_related_content != null ){ tv_related_content.delete(); tv_related_content = null; } } Utils.disposeSWTObjects(new Object[] { table_parent, }); return( super.skinObjectHidden(skinObject, params)); } public Object skinObjectDestroyed( SWTSkinObject skinObject, Object params ) { synchronized( this ){ if ( tv_related_content != null ){ tv_related_content.delete(); tv_related_content = null; } } Utils.disposeSWTObjects(new Object[] { table_parent, }); if ( space_reserved ){ manager.releaseTemporarySpace(); } return( super.skinObjectDestroyed(skinObject, params)); } private void initTable( Composite control ) { tv_related_content = new TableViewSWTImpl( RelatedContent.class, TABLE_RCM, TABLE_RCM, new TableColumnCore[0], ColumnRC_New.COLUMN_ID, SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL ); if (txtFilter != null) { tv_related_content.enableFilterCheck(txtFilter, this); } tv_related_content.setRowDefaultHeight(16); SWTSkinObject soSizeSlider = getSkinObject("table-size-slider"); if (soSizeSlider instanceof SWTSkinObjectContainer) { SWTSkinObjectContainer so = (SWTSkinObjectContainer) soSizeSlider; if (!tv_related_content.enableSizeSlider(so.getComposite(), 16, 100)) { so.setVisible(false); } } table_parent = new Composite(control, SWT.NONE); table_parent.setLayoutData(Utils.getFilledFormData()); GridLayout layout = new GridLayout(); layout.marginHeight = layout.marginWidth = layout.verticalSpacing = layout.horizontalSpacing = 0; table_parent.setLayout(layout); tv_related_content.addSelectionListener(new TableSelectionListener() { public void selected( TableRowCore[] rows) { ArrayList valid = new ArrayList(); for (int i=0;i content_set = new HashSet(); private int liveness_marker; private RelatedContentManagerListener current_rcm_listener; public void tableViewInitialized() { final int current_liveness_marker = ++liveness_marker; current_rcm_listener = new RelatedContentManagerListener() { public void contentFound( RelatedContent[] content ) { } public void contentChanged( RelatedContent[] content ) { final java.util.List hits = new ArrayList( content.length ); synchronized( content_set ){ if ( liveness_marker != current_liveness_marker ){ return; } for ( RelatedContent c: content ){ if ( content_set.contains( c )){ hits.add( c ); } } } if ( hits.size() > 0 ){ for (RelatedContent rc : hits) { TableRowCore row = tv_related_content.getRow(rc); if (row != null) { row.refresh(true); } } } } public void contentRemoved( final RelatedContent[] content ) { final java.util.List hits = new ArrayList( content.length ); synchronized( content_set ){ if ( liveness_marker != current_liveness_marker ){ return; } for ( RelatedContent c: content ){ if ( content_set.remove( c )){ hits.add( c ); } } } if ( hits.size() > 0 ){ Utils.execSWTThread( new Runnable() { public void run() { if ( tv_related_content != null ){ tv_related_content.removeDataSources( hits.toArray( new RelatedContent[ hits.size()] )); } } }); } } public void contentChanged() { if ( tv_related_content != null ){ tv_related_content.refreshTable( false ); } } public void contentReset() { if ( tv_related_content != null ){ tv_related_content.removeAllTableRows(); } } }; manager.addListener( current_rcm_listener ); Object data_source = sidebar_entry.getDatasource(); if ( data_source instanceof RelatedContentEnumerator ){ final TableViewSWT f_table = tv_related_content; ((RelatedContentEnumerator)data_source).enumerate( new RelatedContentEnumerator.RelatedContentEnumeratorListener() { public void contentFound( RelatedContent[] content ) { ArrayList new_content = null; synchronized( content_set ){ if ( liveness_marker != current_liveness_marker ){ return; } for ( RelatedContent c: content ){ if ( content_set.contains( c )){ if ( new_content == null ){ new_content = new ArrayList( content.length ); for ( RelatedContent c2: content ){ if ( c == c2 ){ break; } new_content.add( c2 ); } } }else{ if ( new_content != null ){ new_content.add( c ); } } } if ( new_content != null ){ content = new_content.toArray( new RelatedContent[ new_content.size()]); } content_set.addAll( Arrays.asList( content )); } if ( content.length > 0 ){ final RelatedContent[] f_content = content; Utils.execSWTThread( new Runnable() { public void run() { if ( tv_related_content == f_table ){ synchronized( content_set ){ if ( liveness_marker != current_liveness_marker ){ return; } } f_table.addDataSources( f_content ); } } }); } } }); } } public void tableViewDestroyed() { manager.removeListener( current_rcm_listener ); synchronized( content_set ){ liveness_marker++; content_set.clear(); } } }); tv_related_content.addMenuFillListener( new TableViewSWTMenuFillListener() { public void fillMenu(String sColumnName, Menu menu) { Object[] _related_content = tv_related_content.getSelectedDataSources().toArray(); final RelatedContent[] related_content = new RelatedContent[_related_content.length]; System.arraycopy(_related_content, 0, related_content, 0, related_content.length); final MenuItem assoc_item = new MenuItem(menu, SWT.PUSH); assoc_item.setText(MessageText.getString("rcm.contextmenu.lookupassoc")); final ArrayList assoc_ok = new ArrayList(); for ( RelatedContent c: related_content ){ if ( c.getHash() != null ){ assoc_ok.add( c ); } } assoc_item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e ){ int i = 0; RelatedContentUI ui = RelatedContentUI.getSingleton(); for ( RelatedContent c: assoc_ok ){ ui.addSearch( c.getHash(), c.getTitle()); i++; if ( i > 8 ){ break; } } }; }); if ( assoc_ok.size() == 0 ){ assoc_item.setEnabled( false ); } MenuItem item = new MenuItem(menu, SWT.PUSH); item.setText("gis"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { String s = related_content[0].getTitle(); s = s.replaceAll("[-_]", " "); Utils.launch("http://images.google.com/images?q=" + UrlUtils.encode(s)); }; }); item = new MenuItem(menu, SWT.PUSH); item.setText("g"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { String s = related_content[0].getTitle(); s = s.replaceAll("[-_]", " "); Utils.launch("http://google.com/search?q=" + UrlUtils.encode(s)); }; }); new MenuItem(menu, SWT.SEPARATOR ); final MenuItem remove_item = new MenuItem(menu, SWT.PUSH); remove_item.setText(MessageText.getString("azbuddy.ui.menu.remove")); Utils.setMenuItemImage( remove_item, "delete" ); remove_item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { manager.delete( related_content ); }; }); } public void addThisColumnSubMenu( String columnName, Menu menuThisColumn) { } }); tv_related_content.addKeyListener( new KeyListener() { public void keyPressed( KeyEvent e ) { if ( e.stateMask == 0 && e.keyCode == SWT.DEL ){ Object[] selected; synchronized (this) { if ( tv_related_content == null ){ selected = new Object[0]; }else{ selected = tv_related_content.getSelectedDataSources().toArray(); } } RelatedContent[] content = new RelatedContent[ selected.length ]; for ( int i=0;i 0 ); } return( false ); } public boolean isSelected( String key ) { return( false ); } public void itemActivated( String key ) { Object[] _related_content = tv_related_content.getSelectedDataSources().toArray(); if ( _related_content.length > 0 ){ RelatedContent[] related_content = new RelatedContent[_related_content.length]; System.arraycopy( _related_content, 0, related_content, 0, related_content.length ); manager.delete( related_content ); } } public String getUpdateUIName() { return( "RCMView" ); } public void updateUI() { if ( tv_related_content != null ){ tv_related_content.refreshTable( false ); } } // @see org.gudy.azureus2.ui.swt.views.table.TableViewFilterCheck#filterCheck(java.lang.Object, java.lang.String, boolean) public boolean filterCheck(RelatedContent ds, String filter, boolean regex) { if ( filter == null || filter.length() == 0 ){ return( true ); } try { String name = ds.getTitle(); String s = regex ? filter : "\\Q" + filter.replaceAll("[|;]", "\\\\E|\\\\Q") + "\\E"; Pattern pattern = Pattern.compile(s, Pattern.CASE_INSENSITIVE); return pattern.matcher(name).find(); } catch (Exception e) { return true; } } // @see org.gudy.azureus2.ui.swt.views.table.TableViewFilterCheck#filterSet(java.lang.String) public void filterSet(String filter) { } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/RelatedContentEnumerator.java0000644000175000017500000000215211227512640027270 0ustar adrianadrian/* * Created on Jul 14, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.ui.swt.content; import com.aelitis.azureus.core.content.RelatedContent; public interface RelatedContentEnumerator { public void enumerate( RelatedContentEnumeratorListener listener ); interface RelatedContentEnumeratorListener { public void contentFound( RelatedContent[] content ); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/content/RelatedContentUI.java0000644000175000017500000005463011275212020025464 0ustar adrianadrian/* * Created on Jul 14, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.ui.swt.content; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.widgets.TreeItem; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AsyncDispatcher; import org.gudy.azureus2.core3.util.ByteArrayHashMap; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.ui.UIInstance; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.UIManagerListener; import org.gudy.azureus2.plugins.ui.config.BooleanParameter; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.plugins.ui.config.IntParameter; import org.gudy.azureus2.plugins.ui.config.Parameter; import org.gudy.azureus2.plugins.ui.config.ParameterListener; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.menus.MenuItemListener; import org.gudy.azureus2.plugins.ui.menus.MenuManager; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.plugins.ui.sidebar.SideBarCloseListener; import org.gudy.azureus2.plugins.ui.sidebar.SideBarEntry; import org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage; import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.plugins.ui.tables.TableRow; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.plugins.UISWTInstance; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.content.ContentException; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.core.content.RelatedContentLookupListener; import com.aelitis.azureus.core.content.RelatedContentManager; import com.aelitis.azureus.core.content.RelatedContentManagerListener; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager; import com.aelitis.azureus.ui.swt.views.skin.SkinView; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager.SkinViewManagerListener; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; public class RelatedContentUI { private static RelatedContentUI singleton; public static synchronized RelatedContentUI getSingleton() { if ( singleton == null ){ singleton = new RelatedContentUI(); } return( singleton ); } private PluginInterface plugin_interface; private UIManager ui_manager; private RelatedContentManager manager; private boolean ui_setup; private SideBar side_bar; private boolean root_menus_added; private MainViewInfo main_view_info; private ByteArrayHashMap rcm_item_map = new ByteArrayHashMap(); private AsyncDispatcher async_dispatcher = new AsyncDispatcher(); public RelatedContentUI() { plugin_interface = PluginInitializer.getDefaultInterface(); ui_manager = plugin_interface.getUIManager(); ui_manager.addUIListener( new UIManagerListener() { public void UIAttached( UIInstance instance ) { if ( instance instanceof UISWTInstance ){ AzureusCoreFactory.addCoreRunningListener( new AzureusCoreRunningListener() { public void azureusCoreRunning( AzureusCore core ) { uiAttachedAndCoreRunning(core); } }); } } public void UIDetached( UIInstance instance ) { } }); } private void uiAttachedAndCoreRunning( AzureusCore core ) { Utils.execSWTThread( new AERunnable() { public void runSupport() { SideBar sideBar = (SideBar) SkinViewManager.getByClass(SideBar.class); if ( sideBar != null ){ setupUI(sideBar); } else { SkinViewManager.addListener( new SkinViewManagerListener() { public void skinViewAdded( SkinView skinview ) { if (skinview instanceof SideBar) { setupUI((SideBar) skinview); SkinViewManager.RemoveListener(this); } } }); } } }); } protected void setupUI( SideBar _side_bar ) { synchronized( this ){ if ( ui_setup ){ return; } ui_setup = true; } side_bar = _side_bar; try{ manager = RelatedContentManager.getSingleton(); if ( !manager.isUIEnabled()){ return; } BasicPluginConfigModel config_model = ui_manager.createBasicPluginConfigModel( ConfigSection.SECTION_ROOT, "Associations"); final BooleanParameter enabled = config_model.addBooleanParameter2( "rcm.config.enabled", "rcm.config.enabled", manager.isUIEnabled()); enabled.addListener( new ParameterListener() { public void parameterChanged( Parameter param) { manager.setUIEnabled( enabled.getValue()); buildSideBar(); } }); final IntParameter max_results = config_model.addIntParameter2( "rcm.config.max_results", "rcm.config.max_results", manager.getMaxResults()); max_results.addListener( new ParameterListener() { public void parameterChanged( Parameter param) { manager.setMaxResults( max_results.getValue()); } }); final IntParameter max_level = config_model.addIntParameter2( "rcm.config.max_level", "rcm.config.max_level", manager.getMaxSearchLevel()); max_level.addListener( new ParameterListener() { public void parameterChanged( Parameter param) { manager.setMaxSearchLevel( max_level.getValue()); } }); enabled.addEnabledOnSelection( max_results ); enabled.addEnabledOnSelection( max_level ); main_view_info = new MainViewInfo(); hookMenus(); buildSideBar(); manager.addListener( new RelatedContentManagerListener() { private int last_unread; public void contentFound( RelatedContent[] content ) { check(); } public void contentChanged( RelatedContent[] content ) { contentChanged(); } public void contentChanged() { check(); List items; synchronized( RelatedContentUI.this ){ items = new ArrayList( rcm_item_map.values()); } for ( RCMItem item: items ){ item.updateNumUnread(); } } public void contentRemoved( RelatedContent[] content ) { check(); List items; synchronized( RelatedContentUI.this ){ items = new ArrayList( rcm_item_map.values()); } for ( RCMItem item: items ){ item.contentRemoved( content ); } } public void contentReset() { check(); } protected void check() { int unread = manager.getNumUnread(); synchronized( this ){ if ( unread == last_unread ){ return; } last_unread = unread; } ViewTitleInfoManager.refreshTitleInfo( main_view_info ); } }); }catch( Throwable e ){ Debug.out( e ); } } protected void hookMenus() { TableManager table_manager = plugin_interface.getUIManager().getTableManager(); String[] table_ids = { TableManager.TABLE_MYTORRENTS_INCOMPLETE, TableManager.TABLE_MYTORRENTS_COMPLETE, TableManager.TABLE_MYTORRENTS_ALL_BIG, TableManager.TABLE_MYTORRENTS_COMPLETE_BIG, TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG, }; for ( String table_id: table_ids ){ TableContextMenuItem menu_item = table_manager.addContextMenuItem( table_id, "rcm.contextmenu.lookupassoc"); menu_item.setStyle( TableContextMenuItem.STYLE_PUSH ); MenuItemListener listener = new MenuItemListener() { public void selected( MenuItem menu, Object target) { TableRow[] rows = (TableRow[])target; if ( rows.length > 0 ){ Download download = (Download)rows[0].getDataSource(); explicitSearch( download ); } } }; menu_item.addMultiListener( listener ); } } protected void explicitSearch( Download download ) { addSearch( download ); } protected void buildSideBar() { final String parent_id = "sidebar." + SideBar.SIDEBAR_SECTION_RELATED_CONTENT; final SideBarEntrySWT main_sb_entry = SideBar.getEntry( SideBar.SIDEBAR_SECTION_RELATED_CONTENT ); if ( main_sb_entry != null ){ SideBarEntrySWT subs_entry = SideBar.getEntry( SideBar.SIDEBAR_SECTION_SUBSCRIPTIONS ); int index = side_bar.getIndexOfEntryRelativeToParent( subs_entry ); if ( index >= 0 ){ index++; } if ( main_sb_entry.getTreeItem() == null ){ if ( manager.isUIEnabled()){ side_bar.createEntryFromSkinRef( null, SideBar.SIDEBAR_SECTION_RELATED_CONTENT, "rcmview", main_view_info.getTitle(), main_view_info, null, false, index ); main_sb_entry.setImageLeftID( "image.sidebar.rcm" ); main_sb_entry.setDatasource( new RelatedContentEnumerator() { private RelatedContentManagerListener base_listener; private RelatedContentEnumeratorListener current_listener; public void enumerate( RelatedContentEnumeratorListener listener ) { current_listener = listener; if ( base_listener == null ){ base_listener = new RelatedContentManagerListener() { public void contentFound( RelatedContent[] content ) { current_listener.contentFound( content ); } public void contentChanged( RelatedContent[] content ) { } public void contentRemoved( RelatedContent[] content ) { } public void contentChanged() { } public void contentReset() { } }; manager.addListener( base_listener ); } RelatedContent[] current_content = manager.getRelatedContent(); listener.contentFound( current_content ); } }); }else{ return; } }else if ( !manager.isUIEnabled()){ main_sb_entry.getTreeItem().dispose(); return; } if ( !root_menus_added ){ root_menus_added = true; MenuManager menu_manager = ui_manager.getMenuManager(); MenuItem menu_item = menu_manager.addMenuItem( parent_id, "v3.activity.button.readall" ); menu_item.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { manager.setAllRead(); } }); menu_item = menu_manager.addMenuItem( parent_id, "Subscription.menu.deleteall"); menu_item.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { manager.deleteAll(); } }); menu_item = menu_manager.addMenuItem( parent_id, "Subscription.menu.reset" ); menu_item.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { for ( RCMItem item: rcm_item_map.values()){ item.getTreeItem().dispose(); } manager.reset(); } }); menu_item = menu_manager.addMenuItem( parent_id, "sep" ); menu_item.setStyle( MenuItem.STYLE_SEPARATOR ); menu_item = menu_manager.addMenuItem( parent_id, "ConfigView.title.short" ); menu_item.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { UIFunctions uif = UIFunctionsManager.getUIFunctions(); if ( uif != null ){ uif.openView( UIFunctions.VIEW_CONFIG, "Associations" ); } } }); } } } protected void addSearch( final Download download ) { Torrent torrent = download.getTorrent(); if ( torrent == null ){ return; } final byte[] hash = torrent.getHash(); addSearch( hash, download.getName()); } protected void addSearch( final byte[] hash, final String name ) { synchronized( this ){ final RCMItem existing_si = rcm_item_map.get( hash ); if ( existing_si == null ){ final RCMItem new_si = new RCMItem( hash ); rcm_item_map.put( hash, new_si ); Utils.execSWTThread( new Runnable() { public void run() { synchronized( RelatedContentUI.this ){ if ( new_si.isDestroyed()){ return; } RCMView view = new RCMView( SideBar.SIDEBAR_SECTION_RELATED_CONTENT, name ); new_si.setView( view ); String key = "RCM_" + ByteFormatter.encodeString( hash ); SideBarEntrySWT entry = side_bar.createEntryFromSkinRef( SideBar.SIDEBAR_SECTION_RELATED_CONTENT, key, "rcmview", view.getTitle(), view, null, true, -1 ); new_si.setTreeItem( entry.getTreeItem(), entry ); /* TreeItem tree_item = side_bar.createTreeItemFromIView( SideBar.SIDEBAR_SECTION_RELATED_CONTENT, view, key, null, true, true, false ); SideBarEntrySWT entry = SideBar.getEntry( key ); new_si.setTreeItem( tree_item, entry ); */ /* PluginInterface pi = PluginInitializer.getDefaultInterface(); UIManager uim = pi.getUIManager(); MenuManager menuManager = uim.getMenuManager(); MenuItem menuItem; */ new_si.activate(); } } }); }else{ Utils.execSWTThread( new Runnable() { public void run() { ViewTitleInfoManager.refreshTitleInfo( existing_si.getView()); SideBarEntrySWT mainSBEntry = SideBar.getEntry(SideBar.SIDEBAR_SECTION_RELATED_CONTENT ); if ( mainSBEntry != null ){ ViewTitleInfoManager.refreshTitleInfo( mainSBEntry.getTitleInfo()); } existing_si.activate(); } }); } } } protected class MainViewInfo implements ViewTitleInfo { protected MainViewInfo() { } public Object getTitleInfoProperty( int propertyID ) { if ( propertyID == TITLE_TEXT ){ return( getTitle()); }else if ( propertyID == TITLE_INDICATOR_TEXT ){ int unread = manager.getNumUnread(); if ( unread > 0 ){ return( String.valueOf( unread )); } }else if ( propertyID == TITLE_INDICATOR_COLOR ){ } return null; } public String getTitle() { return( MessageText.getString("rcm.view.title")); } } protected class RCMView implements ViewTitleInfo { private String parent_key; private String name; private int num_unread; protected RCMView( String _parent_key, String _name ) { parent_key = _parent_key; name = _name; } public Object getTitleInfoProperty( int propertyID ) { if ( propertyID == TITLE_TEXT ){ return( getTitle()); }else if ( propertyID == TITLE_INDICATOR_TEXT ){ if ( num_unread > 0 ){ return( String.valueOf( num_unread )); } }else if ( propertyID == TITLE_INDICATOR_COLOR ){ } return null; } public String getTitle() { return( name ); } protected void setNumUnread( int n ) { num_unread = n; ViewTitleInfoManager.refreshTitleInfo( this ); } } private static final String SPINNER_IMAGE_ID = "image.sidebar.vitality.dl"; protected static void hideIcon( SideBarVitalityImage x ) { if ( x == null ){ return; } x.setVisible( false ); x.setToolTip( "" ); } protected static void showIcon( SideBarVitalityImage x , String t ) { if ( x == null ){ return; } x.setToolTip( t ); x.setVisible( true ); } public class RCMItem implements RelatedContentEnumerator, SideBarCloseListener { private byte[] hash; private RCMView view; private SideBarEntrySWT sb_entry; private TreeItem tree_item; private boolean destroyed; private SideBarVitalityImage spinner; private List content_list = new ArrayList(); private int num_unread; private CopyOnWriteList listeners = new CopyOnWriteList(); private boolean lookup_complete; protected RCMItem( byte[] _hash ) { hash = _hash; } protected void setTreeItem( TreeItem _tree_item, SideBarEntrySWT _sb_entry ) { tree_item = _tree_item; sb_entry = _sb_entry; sb_entry.setDatasource( this ); sb_entry.addListener( this ); spinner = sb_entry.addVitalityImage( SPINNER_IMAGE_ID ); try{ showIcon( spinner, null ); manager.lookupContent( hash, new RelatedContentLookupListener() { public void lookupStart() { } public void contentFound( RelatedContent[] content ) { synchronized( RCMItem.this ){ if ( !destroyed ){ for ( RelatedContent c: content ){ if ( !content_list.contains( c )){ content_list.add( c ); } } } } updateNumUnread(); for ( RelatedContentEnumeratorListener listener: listeners ){ try{ listener.contentFound( content ); }catch( Throwable e ){ Debug.out( e ); } } } public void lookupComplete() { synchronized( RCMItem.this ){ lookup_complete = true; } hideIcon( spinner ); } public void lookupFailed( ContentException e ) { lookupComplete(); } }); }catch( Throwable e ){ lookup_complete = true; Debug.out( e ); hideIcon( spinner ); } } protected void contentRemoved( RelatedContent[] content ) { boolean deleted = false; synchronized( RCMItem.this ){ for ( RelatedContent c: content ){ if ( content_list.remove( c )){ deleted = true; } } } if ( deleted ){ updateNumUnread(); } } protected void updateNumUnread() { synchronized( RCMItem.this ){ int num = 0; for ( RelatedContent c: content_list ){ if ( c.isUnread()){ num++; } } if ( num != num_unread ){ num_unread = num; final int f_num = num; async_dispatcher.dispatch( new AERunnable() { public void runSupport() { if ( async_dispatcher.getQueueSize() > 0 ){ return; } view.setNumUnread( f_num ); } }); } } } public void enumerate( final RelatedContentEnumeratorListener listener ) { RelatedContent[] already_found; synchronized( this ){ if ( !lookup_complete ){ listeners.add( listener ); } already_found = content_list.toArray( new RelatedContent[ content_list.size()]); } if ( already_found.length > 0 ){ listener.contentFound( already_found ); } } protected TreeItem getTreeItem() { return( tree_item ); } protected SideBarEntrySWT getSideBarEntry() { return( sb_entry ); } protected void setView( RCMView _view ) { view = _view; } protected RCMView getView() { return( view ); } protected boolean isDestroyed() { return( destroyed ); } public void sidebarClosed( SideBarEntry entry ) { destroy(); } protected void destroy() { synchronized( this ){ content_list.clear(); destroyed = true; } synchronized( RelatedContentUI.this ){ rcm_item_map.remove( hash ); } } public void activate() { SideBar sideBar = (SideBar)SkinViewManager.getByClass(SideBar.class); if ( sideBar != null && sb_entry != null ){ sideBar.showEntryByID(sb_entry.getId()); } } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/0000755000175000017500000000000011310377632021136 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/TopBarView.java0000644000175000017500000003254711172114374024034 0ustar adrianadrian/** * Created on Jun 27, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.Transform; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.plugins.UISWTInstance; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl; import org.gudy.azureus2.ui.swt.views.IView; import org.gudy.azureus2.ui.swt.views.stats.VivaldiView; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.skin.SkinConstants; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.skin.*; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter; import com.aelitis.azureus.ui.swt.views.skin.SkinView; /** * @author TuxPaper * @created Jun 27, 2008 * */ public class TopBarView extends SkinView { private List topbarViews = new ArrayList(); private IView activeTopBar; private SWTSkin skin; private org.eclipse.swt.widgets.List listPlugins; private Composite cPluginArea; public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) { this.skin = skinObject.getSkin(); skin.addListener("topbar-plugins", new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == SWTSkinObjectListener.EVENT_SHOW) { skin.removeListener("topbar-plugins", this); // building needs UISWTInstance, which needs core. AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { buildTopBarViews(); } }); } }); } return null; } }); // trigger autobuild skin.getSkinObject("topbar-area-plugin"); return null; } /** * @param skinObject * * @since 3.0.1.1 */ public void buildTopBarViews() { // TODO actually use plugins.. SWTSkinObject skinObject = skin.getSkinObject("topbar-plugins"); if (skinObject == null) { return; } try { IView[] coreTopBarViews = { new ViewDownSpeedGraph(), new ViewUpSpeedGraph(), new VivaldiView(false) }; cPluginArea = (Composite) skinObject.getControl(); final UIUpdatable updatable = new UIUpdatable() { public void updateUI() { Object[] views = topbarViews.toArray(); for (int i = 0; i < views.length; i++) { try { IView view = (IView) views[i]; if (view.getComposite().isVisible()) { view.refresh(); } } catch (Exception e) { Debug.out(e); } } } public String getUpdateUIName() { return "TopBar"; } }; try { UIFunctionsManager.getUIFunctions().getUIUpdater().addUpdater(updatable); } catch (Exception e) { Debug.out(e); } skinObject.getControl().addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { try { UIFunctionsManager.getUIFunctions().getUIUpdater().removeUpdater( updatable); } catch (Exception ex) { Debug.out(ex); } Object[] views = topbarViews.toArray(); topbarViews.clear(); for (int i = 0; i < views.length; i++) { IView view = (IView) views[i]; view.delete(); } } }); SWTSkinObject soPrev = skin.getSkinObject("topbar-plugin-prev"); if (soPrev != null) { SWTSkinButtonUtility btnPrev = new SWTSkinButtonUtility(soPrev); btnPrev.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { //System.out.println("prev click " + activeTopBar + " ; " // + topbarViews.size()); if (activeTopBar == null || topbarViews.size() <= 1) { return; } int i = topbarViews.indexOf(activeTopBar) - 1; if (i < 0) { i = topbarViews.size() - 1; } activateTopBar((IView) topbarViews.get(i)); } }); } SWTSkinObject soNext = skin.getSkinObject("topbar-plugin-next"); if (soNext != null) { SWTSkinButtonUtility btnNext = new SWTSkinButtonUtility(soNext); btnNext.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { //System.out.println("next click"); if (activeTopBar == null || topbarViews.size() <= 1) { return; } int i = topbarViews.indexOf(activeTopBar) + 1; if (i >= topbarViews.size()) { i = 0; } activateTopBar((IView) topbarViews.get(i)); } }); } SWTSkinObject soTitle = skin.getSkinObject("topbar-plugin-title"); if (soTitle != null) { final Composite cTitle = (Composite) soTitle.getControl(); cTitle.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { e.gc.setAdvanced(true); //Font font = new Font(e.gc.getDevice(), "Sans", 8, SWT.NORMAL); //e.gc.setFont(font); if (e.gc.getAdvanced() && activeTopBar != null) { try { e.gc.setTextAntialias(SWT.ON); } catch (Exception ex) { // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others } try { Transform transform = new Transform(e.gc.getDevice()); transform.rotate(270); e.gc.setTransform(transform); String s = activeTopBar.getShortTitle(); Point size = e.gc.textExtent(s); e.gc.drawText(s, -size.x, 0, true); //e.gc.drawText(s, 0,0, true); transform.dispose(); } catch (Exception ex) { // setTransform can trhow a ERROR_NO_GRAPHICS_LIBRARY error // no use trying to draw.. it would look weird } //font.dispose(); } } }); } SWTSkinObject soList = skin.getSkinObject("topbar-plugin-list"); if (soList != null) { final Composite cList = (Composite) soList.getControl(); listPlugins = new org.eclipse.swt.widgets.List(cList, SWT.None); listPlugins.setLayoutData(Utils.getFilledFormData()); listPlugins.setBackground(cList.getBackground()); listPlugins.setForeground(cList.getForeground()); listPlugins.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { int i = listPlugins.getSelectionIndex(); if (i >= 0 && i < topbarViews.size()) { activateTopBar((IView) topbarViews.get(i)); COConfigurationManager.setParameter("topbar.viewindex", i); } } public void widgetDefaultSelected(SelectionEvent e) { } }); } skinObject = skin.getSkinObject(SkinConstants.VIEWID_PLUGINBAR); if (skinObject != null) { Listener l = new Listener() { private int mouseDownAt = 0; public void handleEvent(Event event) { Composite c = (Composite) event.widget; if (event.type == SWT.MouseDown) { Rectangle clientArea = c.getClientArea(); if (event.y > clientArea.height - 10) { mouseDownAt = event.y; } } else if (event.type == SWT.MouseUp && mouseDownAt > 0) { int diff = event.y - mouseDownAt; mouseDownAt = 0; FormData formData = (FormData) c.getLayoutData(); formData.height += diff; if (formData.height < 50) { formData.height = 50; } else { Rectangle clientArea = c.getShell().getClientArea(); int max = clientArea.height - 350; if (formData.height > max) { formData.height = max; } } COConfigurationManager.setParameter("v3.topbar.height", formData.height); Utils.relayout(c); } else if (event.type == SWT.MouseMove) { Rectangle clientArea = c.getClientArea(); boolean draggable = (event.y > clientArea.height - 10); c.setCursor(draggable ? c.getDisplay().getSystemCursor( SWT.CURSOR_SIZENS) : null); } else if (event.type == SWT.MouseExit) { c.setCursor(null); } } }; Control control = skinObject.getControl(); control.addListener(SWT.MouseDown, l); control.addListener(SWT.MouseUp, l); control.addListener(SWT.MouseMove, l); control.addListener(SWT.MouseExit, l); skinObject.addListener(new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == EVENT_SHOW) { int h = COConfigurationManager.getIntParameter("v3.topbar.height"); Control control = skinObject.getControl(); FormData formData = (FormData) control.getLayoutData(); formData.height = h; control.setLayoutData(formData); Utils.relayout(control); } return null; } }); } int toActiveView = COConfigurationManager.getIntParameter( "topbar.viewindex", 0); int viewIndex = toActiveView; for (int i = 0; i < coreTopBarViews.length; i++) { IView view = coreTopBarViews[i]; addTopBarView(view, cPluginArea); if (toActiveView-- == 0) { activateTopBar(view); if (listPlugins != null) { listPlugins.setSelection(viewIndex); } } } UISWTInstanceImpl uiSWTinstance = (UISWTInstanceImpl) UIFunctionsManagerSWT.getUIFunctionsSWT().getUISWTInstance(); Map pluginViews = null; pluginViews = uiSWTinstance.getViewListeners(UISWTInstance.VIEW_TOPBAR); if (pluginViews != null) { String[] sNames = (String[]) pluginViews.keySet().toArray(new String[0]); for (int i = 0; i < sNames.length; i++) { UISWTViewEventListener l = (UISWTViewEventListener) pluginViews.get(sNames[i]); if (l != null) { try { UISWTViewImpl view = new UISWTViewImpl(UISWTInstance.VIEW_TOPBAR, sNames[i], l); addTopBarView(view, cPluginArea); if (toActiveView-- == 0) { activateTopBar(view); if (listPlugins != null) { listPlugins.setSelection(viewIndex); } } } catch (Exception e) { e.printStackTrace(); // skip, plugin probably specifically asked to not be added } } } } if (toActiveView >= 0 && topbarViews.size() > 0) { activeTopBar = (IView) topbarViews.get(0); activeTopBar.getComposite().setVisible(true); } skinObject.getControl().getParent().layout(true); } catch (Exception e) { Debug.out(e); } } /** * @param view * * @since 3.0.1.1 */ protected void activateTopBar(IView view) { if (activeTopBar != null) { Composite c = activeTopBar.getComposite(); while (c.getParent() != cPluginArea) { c = c.getParent(); } c.setVisible(false); } activeTopBar = view; Composite c = activeTopBar.getComposite(); while (c.getParent() != cPluginArea) { c = c.getParent(); } c.setVisible(true); SWTSkinObject soTitle = skin.getSkinObject("topbar-plugin-title"); //System.out.println("Hello" + soTitle); if (soTitle != null) { soTitle.getControl().redraw(); } } /** * @param view * * @since 3.0.1.1 */ private void addTopBarView(IView view, Composite composite) { Composite parent = new Composite(composite, SWT.None); parent.setLayoutData(Utils.getFilledFormData()); parent.setLayout(new FormLayout()); view.initialize(parent); parent.setVisible(false); Control[] children = parent.getChildren(); for (int i = 0; i < children.length; i++) { Control control = children[i]; Object ld = control.getLayoutData(); boolean useGridLayout = ld != null && (ld instanceof GridData); if (useGridLayout) { GridLayout gridLayout = new GridLayout(); gridLayout.horizontalSpacing = 0; gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; gridLayout.verticalSpacing = 0; parent.setLayout(gridLayout); break; } else if (ld == null) { control.setLayoutData(Utils.getFilledFormData()); } } topbarViews.add(view); if (listPlugins != null) { String s = view.getFullTitle(); if (MessageText.keyExists(s)) { s = MessageText.getString(s); } listPlugins.add(s); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/ViewDownSpeedGraph.java0000644000175000017500000001130011215610214025467 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.views; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerStats; import org.gudy.azureus2.core3.stats.transfer.OverallStats; import org.gudy.azureus2.core3.stats.transfer.StatsFactory; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.core3.util.TimerEventPeriodic; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.graphics.SpeedGraphic; import org.gudy.azureus2.ui.swt.views.AbstractIView; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory; import com.aelitis.azureus.ui.swt.skin.SWTSkinProperties; /** * @author TuxPaper * @created Apr 7, 2007 * */ public class ViewDownSpeedGraph extends AbstractIView { GlobalManager manager = null; GlobalManagerStats stats = null; Canvas downSpeedCanvas; SpeedGraphic downSpeedGraphic; TimerEventPeriodic timerEvent; private boolean everRefreshed = false; public ViewDownSpeedGraph() { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { manager = core.getGlobalManager(); stats = manager.getStats(); } }); } public void periodicUpdate() { if (manager == null || stats == null) { return; } int swarms_peer_speed = (int) stats.getTotalSwarmsPeerRate(true, false); downSpeedGraphic.addIntsValue(new int[] { stats.getDataReceiveRate() + stats.getProtocolReceiveRate(), stats.getProtocolReceiveRate(), COConfigurationManager.getIntParameter("Max Download Speed KBs") * 1024, swarms_peer_speed }); } public void initialize(Composite composite) { GridData gridData; downSpeedCanvas = new Canvas(composite, SWT.DOUBLE_BUFFERED); gridData = new GridData(GridData.FILL_BOTH); downSpeedCanvas.setLayoutData(gridData); downSpeedGraphic = SpeedGraphic.getInstance(); downSpeedGraphic.initialize(downSpeedCanvas); //downSpeedGraphic.setAutoAlpha(true); SWTSkinProperties skinProperties = SWTSkinFactory.getInstance().getSkinProperties(); Color cBG1 = skinProperties.getColor("color.topbar.speed.bg1"); Color cBG2 = skinProperties.getColor("color.topbar.speed.bg2"); Color cBG3 = skinProperties.getColor("color.topbar.speed.bg3"); downSpeedGraphic.setColors(cBG1, cBG2, cBG3); downSpeedGraphic.setLineColors(skinProperties.getColor("color.topbar.speed.average"), skinProperties.getColor("color.topbar.speed.value0"), skinProperties.getColor("color.topbar.speed.overhead"), skinProperties.getColor("color.topbar.speed.value1"), skinProperties.getColor("color.topbar.speed.value2plus"), skinProperties.getColor("color.topbar.speed.trimmed")); } public void delete() { Utils.disposeComposite(downSpeedCanvas); downSpeedGraphic.dispose(); } public String getFullTitle() { return "DL Speed"; } public Composite getComposite() { return downSpeedCanvas; } public void refresh() { if (!everRefreshed) { everRefreshed = true; timerEvent = SimpleTimer.addPeriodicEvent("TopBarSpeedGraphicView", 1000, new TimerEventPerformer() { public void perform(TimerEvent event) { if ( downSpeedCanvas.isDisposed()){ timerEvent.cancel(); }else{ periodicUpdate(); } } }); } downSpeedGraphic.refresh(); } public String getData() { return "SpeedView.title.full"; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/ViewUpSpeedGraph.java0000644000175000017500000000762011215610214025156 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.views; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerStats; import org.gudy.azureus2.core3.stats.transfer.OverallStats; import org.gudy.azureus2.core3.stats.transfer.StatsFactory; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.core3.util.TimerEventPeriodic; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.graphics.SpeedGraphic; import org.gudy.azureus2.ui.swt.views.AbstractIView; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; /** * @author TuxPaper * @created Apr 7, 2007 * */ public class ViewUpSpeedGraph extends AbstractIView { GlobalManager manager = null; GlobalManagerStats stats = null; Canvas upSpeedCanvas; SpeedGraphic upSpeedGraphic; TimerEventPeriodic timerEvent; private boolean everRefreshed = false; public ViewUpSpeedGraph() { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { manager = core.getGlobalManager(); stats = manager.getStats(); } }); } public void initialize(Composite composite) { GridData gridData; upSpeedCanvas = new Canvas(composite, SWT.DOUBLE_BUFFERED); gridData = new GridData(GridData.FILL_BOTH); upSpeedCanvas.setLayoutData(gridData); upSpeedGraphic = SpeedGraphic.getInstance(); upSpeedGraphic.initialize(upSpeedCanvas); //upSpeedGraphic.setAutoAlpha(true); } public void periodicUpdate() { if (stats == null || manager == null) { return; } int swarms_peer_speed = (int) stats.getTotalSwarmsPeerRate(true, false); upSpeedGraphic.addIntsValue(new int[] { stats.getDataSendRate() + stats.getProtocolSendRate(), stats.getProtocolSendRate(), COConfigurationManager.getIntParameter(TransferSpeedValidator.getActiveUploadParameter(manager)) * 1024, swarms_peer_speed }); } public void delete() { Utils.disposeComposite(upSpeedCanvas); upSpeedGraphic.dispose(); } public String getFullTitle() { return "UL Speed"; } public Composite getComposite() { return upSpeedCanvas; } public void refresh() { if (!everRefreshed) { everRefreshed = true; timerEvent = SimpleTimer.addPeriodicEvent("TopBarSpeedGraphicView", 1000, new TimerEventPerformer() { public void perform(TimerEvent event) { if ( upSpeedCanvas.isDisposed()){ timerEvent.cancel(); }else{ periodicUpdate(); } } }); } upSpeedGraphic.refresh(); } public String getData() { return "SpeedView.title.full"; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/PieceGraphView.java0000644000175000017500000003632111051462664024652 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.views; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.disk.DiskManagerPiece; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.peer.PEPiece; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.plugins.UISWTView; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener; import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory; import com.aelitis.azureus.ui.swt.skin.SWTSkinProperties; import com.aelitis.azureus.ui.swt.utils.ColorCache; /** * @author TuxPaper * @created Apr 9, 2007 * */ public class PieceGraphView implements UISWTViewCoreEventListener { // TODO: Buffer private boolean onePiecePerBlock = false; private int BLOCK_FILLSIZE = 21; private final static int BLOCK_SPACING = 3; private int BLOCK_SIZE = BLOCK_FILLSIZE + BLOCK_SPACING; private final static int BLOCKCOLOR_HAVEALL = 0; private final static int BLOCKCOLOR_NOHAVE = 1; private final static int BLOCKCOLOR_UPLOADING = 2; private final static int BLOCKCOLOR_DOWNLOADING = 3; private final static int BLOCKCOLOR_NOAVAIL = 4; private final static int BLOCKCOLOR_HAVESOME = 5; private Color[] blockColors; private Canvas canvas; private Image img; private Image imgHaveAll; private Image imgNoHave; private DownloadManager dlm; private Comparator compFindPEPiece; private final SWTSkinProperties properties; private double[] squareCache; private UISWTView swtView; public PieceGraphView() { this.properties = SWTSkinFactory.getInstance().getSkinProperties(); } // @see org.gudy.azureus2.ui.swt.views.AbstractIView#initialize(org.eclipse.swt.widgets.Composite) private void initialize(Composite parent) { blockColors = new Color[] { properties.getColor("color.pieceview.alldone"), properties.getColor("color.pieceview.notdone"), properties.getColor("color.pieceview.uploading"), properties.getColor("color.pieceview.downloading"), properties.getColor("color.pieceview.noavail"), properties.getColor("color.pieceview.havesome"), }; compFindPEPiece = new Comparator() { public int compare(Object arg0, Object arg1) { int arg0no = (arg0 instanceof PEPiece) ? ((PEPiece) arg0).getPieceNumber() : ((Long) arg0).intValue(); int arg1no = (arg1 instanceof PEPiece) ? ((PEPiece) arg1).getPieceNumber() : ((Long) arg1).intValue(); return arg0no - arg1no; } }; canvas = new Canvas(parent, SWT.NO_BACKGROUND); canvas.setLayout(new FillLayout()); canvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { if (img != null && !img.isDisposed()) { Rectangle bounds = img.getBounds(); if (bounds.width >= e.width && bounds.height >= e.height) { e.gc.drawImage(img, e.x, e.y, e.width, e.height, e.x, e.y, e.width, e.height); } } else { e.gc.fillRectangle(e.x, e.y, e.width, e.height); } } }); canvas.addListener(SWT.Resize, new Listener() { public void handleEvent(Event event) { calcBlockSize(); } }); } // @see org.gudy.azureus2.ui.swt.views.AbstractIView#dataSourceChanged(java.lang.Object) private void dataSourceChanged(Object newDataSource) { if (newDataSource instanceof DownloadManager) { dlm = (DownloadManager) newDataSource; } else { dlm = null; } calcBlockSize(); } // @see org.gudy.azureus2.ui.swt.views.AbstractIView#refresh() private void refresh() { buildImage(); } private void calcBlockSize() { if (!onePiecePerBlock) { buildImage(); return; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (canvas == null || canvas.isDisposed()) { return; } TOTorrent torrent = dlm == null ? null : dlm.getTorrent(); if (torrent == null) { BLOCK_SIZE = 21 + BLOCK_SPACING; } else { long numPieces = torrent.getNumberOfPieces(); Rectangle bounds = canvas.getClientArea(); BLOCK_SIZE = (int) Math.sqrt((double) (bounds.width * bounds.height) / numPieces); if (BLOCK_SIZE <= 0) { BLOCK_SIZE = 1; } // since calc above doesn't account for not splitting squares accross // rows, make sure we can fit. If we can't, we have to shrink int numCanFit = (bounds.width / BLOCK_SIZE) * (bounds.height / BLOCK_SIZE); if (numCanFit < numPieces) { BLOCK_SIZE--; } //System.out.println((float)(bounds.width * bounds.height) / numPieces); //System.out.println(BLOCK_SIZE + ";" + (bounds.width / BLOCK_SIZE)); if (BLOCK_SIZE < 2) { BLOCK_SIZE = 2; } } BLOCK_FILLSIZE = BLOCK_SIZE - BLOCK_SPACING; Utils.disposeSWTObjects(new Object[] { imgHaveAll, imgNoHave }); buildImage(); } }); } private void buildImage() { if (canvas == null || canvas.isDisposed()) { return; } //canvas.setBackground(ColorCache.getColor(canvas.getDisplay(), "#1b1b1b")); Rectangle bounds = canvas.getClientArea(); if (bounds.isEmpty()) { return; } if (dlm == null) { canvas.redraw(); return; } DiskManagerPiece[] dm_pieces = null; PEPeerManager pm = dlm.getPeerManager(); DiskManager dm = dlm.getDiskManager(); if (pm == null || dm == null) { canvas.redraw(); return; } dm_pieces = dm.getPieces(); if (dm_pieces == null || dm_pieces.length == 0) { canvas.redraw(); return; } int numPieces = dm_pieces.length; if (imgHaveAll == null || imgHaveAll.isDisposed()) { imgHaveAll = new Image(canvas.getDisplay(), BLOCK_SIZE, BLOCK_SIZE); GC gc = new GC(imgHaveAll); try { try { gc.setAntialias(SWT.ON); } catch (Exception e) { // ignore } gc.setBackground(canvas.getBackground()); gc.fillRectangle(imgHaveAll.getBounds()); gc.setBackground(blockColors[BLOCKCOLOR_HAVEALL]); gc.fillRoundRectangle(1, 1, BLOCK_FILLSIZE, BLOCK_FILLSIZE, BLOCK_FILLSIZE, BLOCK_FILLSIZE); } finally { gc.dispose(); } } if (imgNoHave == null || imgNoHave.isDisposed()) { imgNoHave = new Image(canvas.getDisplay(), BLOCK_SIZE, BLOCK_SIZE); GC gc = new GC(imgNoHave); try { try { gc.setAntialias(SWT.ON); } catch (Exception e) { // ignore } gc.setBackground(canvas.getBackground()); gc.fillRectangle(imgNoHave.getBounds()); gc.setBackground(blockColors[BLOCKCOLOR_NOHAVE]); gc.fillRoundRectangle(1, 1, BLOCK_FILLSIZE, BLOCK_FILLSIZE, BLOCK_FILLSIZE, BLOCK_FILLSIZE); } finally { gc.dispose(); } } boolean clearImage = img == null || img.isDisposed() || img.getBounds().width != bounds.width || img.getBounds().height != bounds.height; if (clearImage) { if (img != null && !img.isDisposed()) { img.dispose(); } //System.out.println("clear " + img); img = new Image(canvas.getDisplay(), bounds.width, bounds.height); squareCache = null; } PEPiece[] currentDLPieces = dlm.getCurrentPieces(); Arrays.sort(currentDLPieces, compFindPEPiece); // find upload pieces ArrayList currentULPieces = new ArrayList(); ArrayList futureULPieces = new ArrayList(); PEPeer[] peers = (PEPeer[]) pm.getPeers().toArray(new PEPeer[0]); for (int i = 0; i < peers.length; i++) { PEPeer peer = peers[i]; int[] peerRequestedPieces = peer.getIncomingRequestedPieceNumbers(); if (peerRequestedPieces != null && peerRequestedPieces.length > 0) { currentULPieces.add(new Long(peerRequestedPieces[0])); for (int j = 1; j < peerRequestedPieces.length; j++) { futureULPieces.add(new Long(peerRequestedPieces[j])); } } // we'll have duplicates Collections.sort(currentULPieces); Collections.sort(futureULPieces); } int iNumCols = bounds.width / BLOCK_SIZE; int iNumRows = bounds.height / BLOCK_SIZE; int numSquares = onePiecePerBlock ? numPieces : iNumCols * iNumRows; double numPiecesPerSquare = numPieces / (double) numSquares; //System.out.println("numPiecesPerSquare=" + numPiecesPerSquare); if (squareCache == null || squareCache.length != numSquares) { squareCache = new double[numSquares]; Arrays.fill(squareCache, -1); } int[] availability = pm.getAvailability(); int numRedraws = 0; GC gc = new GC(img); try { int iRow = 0; if (clearImage) { gc.setBackground(canvas.getBackground()); gc.fillRectangle(bounds); } try { gc.setAdvanced(true); gc.setAntialias(SWT.ON); gc.setInterpolation(SWT.HIGH); } catch (Exception e) { // ignore } int iCol = 0; for (int squareNo = 0; squareNo < numSquares; squareNo++) { if (iCol >= iNumCols) { iCol = 0; iRow++; } int startNo = (int) (squareNo * numPiecesPerSquare); int count = (int) ((squareNo + 1) * numPiecesPerSquare) - startNo; if (count == 0) { count = 1; } //if (count > 1) System.out.println("!!! " + startNo); //System.out.println(startNo + ";" + count); double pctDone = getPercentDone(startNo, count, dm_pieces); //System.out.print(pctDone + ";"); int colorIndex; int iXPos = iCol * BLOCK_SIZE; int iYPos = iRow * BLOCK_SIZE; if (pctDone == 1) { if (squareCache[squareNo] != pctDone) { squareCache[squareNo] = pctDone; gc.drawImage(imgHaveAll, iXPos, iYPos); if (!clearImage) { numRedraws++; canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false); } } } else if (pctDone == 0) { if (squareCache[squareNo] != pctDone) { squareCache[squareNo] = pctDone; gc.drawImage(imgNoHave, iXPos, iYPos); if (!clearImage) { numRedraws++; canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false); } } } else { // !done boolean isDownloading = false; for (int i = startNo; i < startNo + count; i++) { if (Arrays.binarySearch(currentDLPieces, new Long(i), compFindPEPiece) >= 0) { isDownloading = true; break; } } double val = pctDone + (isDownloading ? 0 : 1); if (squareCache[squareNo] != val) { squareCache[squareNo] = val; gc.drawImage(imgNoHave, iXPos, iYPos); int size = (int) (BLOCK_FILLSIZE * pctDone); if (size == 0) { size = 1; } int q = (int) ((BLOCK_FILLSIZE - size) / 2.0 + 0.5) + 1; colorIndex = isDownloading ? BLOCKCOLOR_DOWNLOADING : BLOCKCOLOR_HAVESOME; gc.setBackground(blockColors[colorIndex]); gc.fillOval(iXPos + q, iYPos + q, size, size); //gc.fillRoundRectangle(iXPos + q, iYPos + q, size, size, size, size); if (!clearImage) { numRedraws++; canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false); } } } for (int i = startNo; i < startNo + count; i++) { if (Collections.binarySearch(currentULPieces, new Long(i)) >= 0) { colorIndex = BLOCKCOLOR_UPLOADING; int size = BLOCK_FILLSIZE + 1; gc.setForeground(blockColors[colorIndex]); gc.drawRoundRectangle(iXPos, iYPos, size, size, size, size); if (!clearImage) { numRedraws++; canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false); } squareCache[squareNo] = -1; break; } else if (Collections.binarySearch(futureULPieces, new Long(i)) >= 0) { colorIndex = BLOCKCOLOR_UPLOADING; int size = BLOCK_FILLSIZE + 1; gc.setForeground(blockColors[colorIndex]); gc.setLineStyle(SWT.LINE_DOT); gc.drawRoundRectangle(iXPos, iYPos, size, size, size, size); if (!clearImage) { numRedraws++; canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false); } gc.setLineStyle(SWT.LINE_SOLID); squareCache[squareNo] = -1; break; } } if (availability != null) { boolean hasNoAvail = false; for (int i = startNo; i < startNo + count; i++) { if (availability[i] == 0) { hasNoAvail = true; squareCache[squareNo] = -1; break; } } if (hasNoAvail) { gc.setForeground(blockColors[BLOCKCOLOR_NOAVAIL]); gc.drawRectangle(iXPos, iYPos, BLOCK_FILLSIZE + 1, BLOCK_FILLSIZE + 1); if (!clearImage) { numRedraws++; canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false); } } } iCol++; } //System.out.println("redraws " + numRedraws); } catch (Exception e) { Debug.out(e); } finally { gc.dispose(); } //canvas.redraw(); } /** * @param startNo * @param count * @param dm_pieces * @return * * @since 3.0.1.1 */ private double getPercentDone(int startNo, int count, DiskManagerPiece[] dm_pieces) { int totalComplete = 0; int totalBlocks = 0; for (int i = startNo; i < startNo + count; i++) { DiskManagerPiece piece = dm_pieces == null ? null : dm_pieces[i]; int numBlocks = piece.getNbBlocks(); totalBlocks += numBlocks; boolean done = (piece == null) ? false : piece.isDone(); if (done) { totalComplete += numBlocks; } else { // !done totalComplete += piece.getNbWritten(); } } return (double) totalComplete / totalBlocks; } public boolean eventOccurred(UISWTViewEvent event) { switch (event.getType()) { case UISWTViewEvent.TYPE_CREATE: swtView = (UISWTView)event.getData(); break; case UISWTViewEvent.TYPE_DESTROY: delete(); break; case UISWTViewEvent.TYPE_INITIALIZE: initialize((Composite)event.getData()); break; case UISWTViewEvent.TYPE_LANGUAGEUPDATE: Messages.updateLanguageForControl(canvas); break; case UISWTViewEvent.TYPE_DATASOURCE_CHANGED: dataSourceChanged(event.getData()); break; case UISWTViewEvent.TYPE_REFRESH: refresh(); break; } return true; } /** * * * @since 3.1.0.1 */ private void delete() { // TODO Auto-generated method stub } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/0000755000175000017500000000000011310377632022102 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView_Big.java0000644000175000017500000000251711077221310027420 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.views.skin; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.swt.columns.utils.TableColumnCreatorV3; import org.gudy.azureus2.plugins.ui.tables.TableManager; public class SBC_LibraryTableView_Big extends SBC_LibraryTableView { public String getUpdateUIName() { return "SBC_LibraryTableView_Big"; } public int getTableMode() { return SBC_LibraryView.MODE_BIGTABLE; } public boolean useBigTable() { return true; } public TableColumnCore[] getColumns() { TableColumnCore[] columns = null; if (torrentFilterMode == SBC_LibraryView.TORRENTS_COMPLETE) { columns = TableColumnCreatorV3.createCompleteDM( TableManager.TABLE_MYTORRENTS_COMPLETE_BIG, true); } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_INCOMPLETE) { columns = TableColumnCreatorV3.createIncompleteDM( TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG, true); } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_UNOPENED) { columns = TableColumnCreatorV3.createUnopenedDM( TableManager.TABLE_MYTORRENTS_UNOPENED_BIG, true); } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_ALL) { columns = TableColumnCreatorV3.createAllDM( TableManager.TABLE_MYTORRENTS_ALL_BIG, true); } if (columns == null) { return null; } return columns; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/MyTorrentsView_Big.java0000644000175000017500000000627611306337236026523 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.views.skin; import org.eclipse.swt.SWT; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.views.MyTorrentsView; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.TableRowCore; import com.aelitis.azureus.util.DLReferals; import com.aelitis.azureus.util.DataSourceUtils; import com.aelitis.azureus.util.PlayUtils; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadTypeComplete; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.tables.TableManager; public class MyTorrentsView_Big extends MyTorrentsView { private final int torrentFilterMode; public MyTorrentsView_Big(AzureusCore _azureus_core, int torrentFilterMode, TableColumnCore[] basicItems) { this.torrentFilterMode = torrentFilterMode; init( _azureus_core, SBC_LibraryView.getTableIdFromFilterMode(torrentFilterMode, true), torrentFilterMode == SBC_LibraryView.TORRENTS_INCOMPLETE ? false : true, basicItems); //setForceHeaderVisible(true); } public boolean isOurDownloadManager(DownloadManager dm) { if (PlatformTorrentUtils.isAdvancedViewOnly(dm)) { return false; } if (torrentFilterMode == SBC_LibraryView.TORRENTS_UNOPENED) { if (PlatformTorrentUtils.getHasBeenOpened(dm)) { return false; } } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_ALL) { return isInCurrentCategory(dm); } return super.isOurDownloadManager(dm); } protected TableViewSWT createTableView(TableColumnCore[] basicItems) { String tableID; Class forDataSourceType; switch (torrentFilterMode) { case SBC_LibraryView.TORRENTS_COMPLETE: tableID = TableManager.TABLE_MYTORRENTS_COMPLETE_BIG; forDataSourceType = DownloadTypeComplete.class; break; case SBC_LibraryView.TORRENTS_INCOMPLETE: tableID = TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG; forDataSourceType = DownloadTypeIncomplete.class; break; case SBC_LibraryView.TORRENTS_UNOPENED: tableID = TableManager.TABLE_MYTORRENTS_UNOPENED_BIG; forDataSourceType = Download.class; break; case SBC_LibraryView.TORRENTS_ALL: tableID = TableManager.TABLE_MYTORRENTS_ALL_BIG; forDataSourceType = Download.class; break; default: tableID = "bad"; forDataSourceType = null; break; } TableViewSWTImpl tv = new TableViewSWTImpl(forDataSourceType, tableID, "MyTorrentsView_Big", basicItems, "#", SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL | SWT.BORDER); return tv; } // @see org.gudy.azureus2.ui.swt.views.MyTorrentsView#defaultSelected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void defaultSelected(TableRowCore[] rows, int stateMask) { SBC_LibraryTableView.doDefaultClick(rows, stateMask, !isSeedingView); } protected int getRowDefaultHeight() { return 36; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/ToolBarView.java0000644000175000017500000007743111276523212025154 0ustar adrianadrian/** * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import org.gudy.azureus2.ui.swt.IconBarEnabler; import org.gudy.azureus2.ui.swt.TorrentUtil; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.views.tableitems.mytorrents.RankItem; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.devices.DeviceManager; import com.aelitis.azureus.core.devices.DeviceManagerFactory; import com.aelitis.azureus.core.devices.TranscodeException; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.ui.common.table.TableView; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; import com.aelitis.azureus.ui.selectedcontent.ISelectedVuzeFileContent; import com.aelitis.azureus.ui.selectedcontent.SelectedContentListener; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.devices.DeviceManagerUI; import com.aelitis.azureus.ui.swt.devices.TranscodeChooser; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectText; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter; import com.aelitis.azureus.ui.swt.toolbar.ToolBarEnablerSelectedContent; import com.aelitis.azureus.ui.swt.toolbar.ToolBarItem; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager.SkinViewManagerListener; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; import com.aelitis.azureus.util.DLReferals; import com.aelitis.azureus.util.PlayUtils; import org.gudy.azureus2.plugins.ui.UIPluginView; import org.gudy.azureus2.plugins.ui.tables.TableColumn; /** * @author TuxPaper * @created Jul 20, 2008 */ public class ToolBarView extends SkinView { private static toolbarButtonListener buttonListener; private Map items = new LinkedHashMap(); //private GlobalManager gm; Control lastControl = null; private boolean showText = true; private SWTSkinObject skinObject; private SWTSkinObject so2nd; private SWTSkinObject soGap; private boolean initComplete = false; // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#showSupport(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectInitialShow(final SWTSkinObject skinObject, Object params) { this.skinObject = skinObject; buttonListener = new toolbarButtonListener(); so2nd = skinObject.getSkin().getSkinObject("global-toolbar-2nd"); soGap = skinObject.getSkin().getSkinObject("toolbar-gap"); if (soGap != null) { Control cGap = soGap.getControl(); FormData fd = (FormData) cGap.getLayoutData(); if (fd.width == SWT.DEFAULT) { cGap.getParent().addListener(SWT.Resize, new Listener() { public void handleEvent(Event event) { resizeGap(); } }); } else { soGap = null; } } ToolBarItem item; // ==download item = new ToolBarItem("download", "image.button.download", "v3.MainWindow.button.download") { // @see com.aelitis.azureus.ui.swt.toolbar.ToolBarItem#triggerToolBarItem() public void triggerToolBarItem() { String viewID = SelectedContentManager.getCurrentySelectedViewID(); if (viewID == null && triggerIViewToolBar(getId())) { return; } // This is for our CDP pages ISelectedContent[] sc = SelectedContentManager.getCurrentlySelectedContent(); if (sc != null && sc.length == 1 && (sc[0].getHash() != null || sc[0].getDownloadInfo() != null)) { TorrentListViewsUtils.downloadDataSource(sc[0], false, DLReferals.DL_REFERAL_TOOLBAR); } } }; addToolBarItem(item); // ==play item = new ToolBarItem("play", "image.button.play", "iconBar.play") { // @see com.aelitis.azureus.ui.swt.toolbar.ToolBarItem#triggerToolBarItem() public void triggerToolBarItem() { String viewID = SelectedContentManager.getCurrentySelectedViewID(); if (viewID == null && triggerIViewToolBar(getId())) { return; } ISelectedContent[] sc = SelectedContentManager.getCurrentlySelectedContent(); if (sc != null) { TorrentListViewsUtils.playOrStreamDataSource(sc[0], this.getSkinButton(), DLReferals.DL_REFERAL_TOOLBAR); } } }; addToolBarItem(item); addSeperator("toolbar.area.item.sep", soMain); lastControl = null; boolean first = true; // ==OPEN // item = new ToolBarItem("open", "image.toolbar.open", "iconBar.open") { // public void triggerToolBarItem() { // TorrentOpener.openTorrentWindow(); // } // }; // addToolBarItem(item); // ==transcode if (!DeviceManagerUI.DISABLED) { item = new ToolBarItem("transcode", "image.button.transcode", "iconBar.transcode") { // @see com.aelitis.azureus.ui.swt.toolbar.ToolBarItem#triggerToolBarItem() public void triggerToolBarItem() { String viewID = SelectedContentManager.getCurrentySelectedViewID(); if (viewID == null && triggerIViewToolBar(getId())) { return; } final ISelectedContent[] contents = SelectedContentManager.getCurrentlySelectedContent(); if (contents.length == 0) { return; } TranscodeChooser deviceChooser = new TranscodeChooser() { public void closed() { DeviceManager deviceManager = DeviceManagerFactory.getSingleton(); if (selectedTranscodeTarget != null && selectedProfile != null) { for (int i = 0; i < contents.length; i++) { ISelectedContent selectedContent = contents[i]; DownloadManager dm = selectedContent.getDownloadManager(); if (dm == null) { continue; } DiskManagerFileInfo[] files = dm.getDiskManagerFileInfo(); for (DiskManagerFileInfo file : files) { try { deviceManager.getTranscodeManager().getQueue().add( selectedTranscodeTarget, selectedProfile, (org.gudy.azureus2.plugins.disk.DiskManagerFileInfo) PluginCoreUtils.convert( file, false)); } catch (TranscodeException e) { Debug.out(e); } } } } } }; deviceChooser.show(); } }; addToolBarItem(item, "toolbar.area.sitem.left", so2nd); addSeperator(so2nd); first = false; } // ==run item = new ToolBarItem("run", "image.toolbar.run", "iconBar.run") { public void triggerToolBarItem() { String viewID = SelectedContentManager.getCurrentySelectedViewID(); if (viewID == null && triggerIViewToolBar(getId())) { return; } boolean isIconBarEnabler = "IconBarEnabler".equals(viewID); ISelectedContent[] currentContent = SelectedContentManager.getCurrentlySelectedContent(); if (isIconBarEnabler && currentContent.length > 0 && currentContent[0] != null && currentContent[0] instanceof ToolBarEnablerSelectedContent) { ToolBarEnablerSelectedContent ibeSelected = (ToolBarEnablerSelectedContent) currentContent[0]; IconBarEnabler enabler = ibeSelected.getIconBarEnabler(); if (enabler != null) { enabler.itemActivated("start"); } } else { DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent(); if (dms != null) { TorrentUtil.runTorrents(dms); for (int i = 0; i < dms.length; i++) { DownloadManager dm = dms[i]; PlatformTorrentUtils.setHasBeenOpened(dm, true); } } } } }; addToolBarItem(item, "toolbar.area.sitem", so2nd); addSeperator(so2nd); // ==UP item = new ToolBarItem("up", "image.toolbar.up", "v3.iconBar.up") { public void triggerToolBarItem() { if (!AzureusCoreFactory.isCoreRunning()) { return; } String viewID = SelectedContentManager.getCurrentySelectedViewID(); if (viewID == null && triggerIViewToolBar(getId())) { return; } boolean isIconBarEnabler = "IconBarEnabler".equals(viewID); ISelectedContent[] currentContent = SelectedContentManager.getCurrentlySelectedContent(); if (isIconBarEnabler && currentContent.length > 0 && currentContent[0] != null && currentContent[0] instanceof ToolBarEnablerSelectedContent) { ToolBarEnablerSelectedContent ibeSelected = (ToolBarEnablerSelectedContent) currentContent[0]; IconBarEnabler enabler = ibeSelected.getIconBarEnabler(); if (enabler != null) { enabler.itemActivated("up"); } } else { DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent(); if (dms != null) { Arrays.sort(dms, new Comparator() { public int compare(DownloadManager a, DownloadManager b) { return a.getPosition() - b.getPosition(); } }); GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); for (int i = 0; i < dms.length; i++) { DownloadManager dm = dms[i]; if (gm.isMoveableUp(dm)) { gm.moveUp(dm); } } } } } // @see com.aelitis.azureus.ui.swt.toolbar.ToolBarItem#triggerToolBarItemHold() public boolean triggerToolBarItemHold() { if (!AzureusCoreFactory.isCoreRunning()) { return false; } GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent(); if (dms != null) { gm.moveTop(dms); } return true; } }; addToolBarItem(item, "toolbar.area.sitem", so2nd); addSeperator(so2nd); // ==down item = new ToolBarItem("down", "image.toolbar.down", "v3.iconBar.down") { public void triggerToolBarItem() { if (!AzureusCoreFactory.isCoreRunning()) { return; } String viewID = SelectedContentManager.getCurrentySelectedViewID(); if (viewID == null && triggerIViewToolBar(getId())) { return; } boolean isIconBarEnabler = "IconBarEnabler".equals(viewID); ISelectedContent[] currentContent = SelectedContentManager.getCurrentlySelectedContent(); if (isIconBarEnabler && currentContent.length > 0 && currentContent[0] != null && currentContent[0] instanceof ToolBarEnablerSelectedContent) { ToolBarEnablerSelectedContent ibeSelected = (ToolBarEnablerSelectedContent) currentContent[0]; IconBarEnabler enabler = ibeSelected.getIconBarEnabler(); if (enabler != null) { enabler.itemActivated("down"); } } else { GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent(); if (dms != null) { Arrays.sort(dms, new Comparator() { public int compare(DownloadManager a, DownloadManager b) { return b.getPosition() - a.getPosition(); } }); for (int i = 0; i < dms.length; i++) { DownloadManager dm = dms[i]; if (gm.isMoveableDown(dm)) { gm.moveDown(dm); } } } } } // @see com.aelitis.azureus.ui.swt.toolbar.ToolBarItem#triggerToolBarItemHold() public boolean triggerToolBarItemHold() { if (!AzureusCoreFactory.isCoreRunning()) { return false; } GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent(); if (dms != null) { gm.moveEnd(dms); } return true; } }; addToolBarItem(item, "toolbar.area.sitem", so2nd); addSeperator(so2nd); // ==start item = new ToolBarItem("start", "image.toolbar.start", "iconBar.start") { public void triggerToolBarItem() { String viewID = SelectedContentManager.getCurrentySelectedViewID(); if (viewID == null && triggerIViewToolBar(getId())) { return; } boolean isIconBarEnabler = "IconBarEnabler".equals(viewID); ISelectedContent[] currentContent = SelectedContentManager.getCurrentlySelectedContent(); if (isIconBarEnabler && currentContent.length > 0 && currentContent[0] != null && currentContent[0] instanceof ToolBarEnablerSelectedContent) { ToolBarEnablerSelectedContent ibeSelected = (ToolBarEnablerSelectedContent) currentContent[0]; IconBarEnabler enabler = ibeSelected.getIconBarEnabler(); if (enabler != null) { enabler.itemActivated("start"); } } else { DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent(); if (dms != null) { TorrentUtil.queueTorrents(dms, null); } } } }; addToolBarItem(item, "toolbar.area.sitem", so2nd); //SWTSkinObjectContainer so = (SWTSkinObjectContainer) item.getSkinButton().getSkinObject(); //so.setDebugAndChildren(true); addSeperator(so2nd); // ==stop item = new ToolBarItem("stop", "image.toolbar.stop", "iconBar.stop") { public void triggerToolBarItem() { String viewID = SelectedContentManager.getCurrentySelectedViewID(); if (viewID == null && triggerIViewToolBar(getId())) { return; } boolean isIconBarEnabler = "IconBarEnabler".equals(viewID); ISelectedContent[] currentContent = SelectedContentManager.getCurrentlySelectedContent(); if (isIconBarEnabler && currentContent.length > 0 && currentContent[0] != null && currentContent[0] instanceof ToolBarEnablerSelectedContent) { ToolBarEnablerSelectedContent ibeSelected = (ToolBarEnablerSelectedContent) currentContent[0]; IconBarEnabler enabler = ibeSelected.getIconBarEnabler(); if (enabler != null) { enabler.itemActivated("stop"); } } else { DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent(); if (dms != null) { TorrentUtil.stopTorrents(dms, null); } } } }; addToolBarItem(item, "toolbar.area.sitem", so2nd); addSeperator(so2nd); // ==remove item = new ToolBarItem("remove", "image.toolbar.remove", "iconBar.remove") { public void triggerToolBarItem() { String viewID = SelectedContentManager.getCurrentySelectedViewID(); if (viewID == null && triggerIViewToolBar(getId())) { return; } boolean isActivityView = "Activity".equals(viewID); boolean isIconBarEnabler = "IconBarEnabler".equals(viewID); ISelectedContent[] currentContent = SelectedContentManager.getCurrentlySelectedContent(); if (isIconBarEnabler && currentContent.length > 0 && currentContent[0] != null && currentContent[0] instanceof ToolBarEnablerSelectedContent) { ToolBarEnablerSelectedContent ibeSelected = (ToolBarEnablerSelectedContent) currentContent[0]; IconBarEnabler enabler = ibeSelected.getIconBarEnabler(); if (enabler != null) { enabler.itemActivated("remove"); } } else if (isActivityView) { SkinView view = SkinViewManager.getBySkinObjectID("Activity"); if (view instanceof SBC_ActivityView) { SBC_ActivityView viewActivity = (SBC_ActivityView) view; viewActivity.removeSelected(); } } else { DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent(); TorrentListViewsUtils.removeDownloads(dms); } } }; addToolBarItem(item, "toolbar.area.sitem.right", so2nd); /////////////////////// addSeperator("toolbar.area.item.sep3", so2nd); addNonToolBar("toolbar.area.sitem.left2", so2nd); // == mode big item = new ToolBarItem("modeBig", "image.toolbar.table_large", "v3.iconBar.view.big"); addToolBarItem(item, "toolbar.area.vitem.left", so2nd); item.setEnabled(false); Control bigItem = item.getSkinButton().getSkinObject().getControl(); SWTSkinObject soTitle = skin.getSkinObject("toolbar-item-title", item.getSkinButton().getSkinObject()); if (soTitle instanceof SWTSkinObjectText) { ((SWTSkinObjectText) soTitle).setStyle(SWT.RIGHT); } addSeperator(so2nd); // == mode small item = new ToolBarItem("modeSmall", "image.toolbar.table_normal", "v3.iconBar.view.small"); addToolBarItem(item, "toolbar.area.vitem.right", so2nd); item.setEnabled(false); Control smallItem = item.getSkinButton().getSkinObject().getControl(); soTitle = skin.getSkinObject("toolbar-item-title", item.getSkinButton().getSkinObject()); if (soTitle instanceof SWTSkinObjectText) { ((SWTSkinObjectText) soTitle).setStyle(SWT.LEFT); } //addSeperator(so2nd); resizeGap(); SelectedContentManager.addCurrentlySelectedContentListener(new SelectedContentListener() { public void currentlySelectedContentChanged( ISelectedContent[] currentContent, String viewID) { updateCoreItems(currentContent, viewID); UIFunctionsManagerSWT.getUIFunctionsSWT().refreshTorrentMenu(); } }); try { if (!COConfigurationManager.getBooleanParameter("ToolBar.showText")) { flipShowText(); } } catch (Throwable t) { Debug.out(t); } initComplete = true; return null; } /** * * * @since 3.1.1.1 */ protected void resizeGap() { if (soGap == null) { skinObject.getControl().getParent().layout(); return; } Rectangle boundsLeft = skinObject.getControl().getBounds(); Rectangle boundsRight = so2nd.getControl().getBounds(); Rectangle clientArea = soGap.getControl().getParent().getClientArea(); FormData fd = (FormData) soGap.getControl().getLayoutData(); fd.width = clientArea.width - (boundsLeft.x + boundsLeft.width) - (boundsRight.width); if (fd.width < 0) { fd.width = 0; } else if (fd.width > 50) { fd.width -= 30; } else if (fd.width > 20) { fd.width = 20; } soGap.getControl().getParent().layout(); } /** * * * @since 3.1.1.1 */ protected void updateCoreItems(ISelectedContent[] currentContent, String viewID) { String[] itemsNeedingSelection = {}; String[] itemsNeedingRealDMSelection = { "remove", "up", "down", "top", "bottom", "transcode", }; String[] itemsRequiring1SelectionWithHash = { "details", "comment", }; String[] itemsRequiring1DMSelection = {}; boolean isActivityView = "Activity".equals(viewID); boolean isIconBarEnabler = "IconBarEnabler".equals(viewID); int numSelection = currentContent.length; boolean hasSelection = numSelection > 0; boolean has1Selection = numSelection == 1; boolean has1SelectionWithHash = has1Selection && currentContent[0].getHash() != null; ToolBarItem item; for (int i = 0; i < itemsNeedingSelection.length; i++) { String itemID = itemsNeedingSelection[i]; item = getToolBarItem(itemID); if (item != null) { item.setEnabled(hasSelection); } } TableView tv = SelectedContentManager.getCurrentlySelectedTableView(); boolean hasRealDM = tv != null; if (!hasRealDM) { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { SideBarEntrySWT entry = sidebar.getCurrentEntry(); if (entry != null) { if (entry.datasource instanceof DownloadManager) { hasRealDM = true; } else if ((entry.iview instanceof UIPluginView) && (((UIPluginView) entry.iview).getDataSource() instanceof DownloadManager)) { hasRealDM = true; } } } } DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent(); boolean isDMSelection = dms != null && dms.length > 0; for (int i = 0; i < itemsNeedingRealDMSelection.length; i++) { String itemID = itemsNeedingRealDMSelection[i]; item = getToolBarItem(itemID); if (item != null) { item.setEnabled(hasSelection && isDMSelection && hasRealDM); } } for (int i = 0; i < itemsRequiring1SelectionWithHash.length; i++) { String itemID = itemsRequiring1SelectionWithHash[i]; item = getToolBarItem(itemID); if (item != null) { item.setEnabled(has1SelectionWithHash); } } for (int i = 0; i < itemsRequiring1DMSelection.length; i++) { String itemID = itemsRequiring1DMSelection[i]; item = getToolBarItem(itemID); if (item != null) { item.setEnabled(has1Selection && isDMSelection); } } boolean canStart = false; boolean canStop = false; if (isIconBarEnabler && currentContent.length > 0 && currentContent[0] != null && currentContent[0] instanceof ToolBarEnablerSelectedContent) { ToolBarEnablerSelectedContent ibeSelected = (ToolBarEnablerSelectedContent) currentContent[0]; IconBarEnabler enabler = ibeSelected.getIconBarEnabler(); if (enabler != null) { String[] TBKEYS = new String[] { "download", "play", "run", "up", "down", "start", "stop", "remove" }; //String[] OLD_TBKEYS = new String[] {"run","up","down","start","stop","delete"}; for (String item_key : TBKEYS) { item = getToolBarItem(item_key); if (item != null) { boolean enabled = enabler.isEnabled(item_key); item.setEnabled(enabled); if (enabled) { if (item_key.equals("start")) { canStart = true; } else if (item_key.equals("stop")) { canStop = true; } } } } } } else if (isActivityView) { item = getToolBarItem("up"); if (item != null) { item.setEnabled(false); } item = getToolBarItem("down"); if (item != null) { item.setEnabled(false); } item = getToolBarItem("remove"); if (item != null) { SkinView view = SkinViewManager.getBySkinObjectID("Activity"); if (view instanceof SBC_ActivityView) { SBC_ActivityView viewActivity = (SBC_ActivityView) view; if (viewActivity.isVisible()) { item.setEnabled(viewActivity.getNumSelected() > 0); } else { item.setEnabled(false); } } else { item.setEnabled(false); } } } else if (currentContent.length > 0 && hasRealDM) { for (int i = 0; i < currentContent.length; i++) { ISelectedContent content = currentContent[i]; DownloadManager dm = content.getDownloadManager(); if (!canStart && ManagerUtils.isStartable(dm)) { canStart = true; } if (!canStop && ManagerUtils.isStopable(dm)) { canStop = true; } } } item = getToolBarItem("run"); if (item != null) { boolean canRun = has1Selection; if (canRun) { ISelectedContent content = currentContent[0]; DownloadManager dm = content.getDownloadManager(); if (dm == null) { canRun = false; } else { TOTorrent torrent = dm.getTorrent(); if (torrent == null) { canRun = false; } else if (!dm.getAssumedComplete() && torrent.isSimpleTorrent()) { canRun = false; } else if (PlatformTorrentUtils.useEMP(torrent) && PlatformTorrentUtils.embeddedPlayerAvail() && PlayUtils.canProgressiveOrIsComplete(torrent)) { // play button enabled and not UMP.. don't need launch canRun = false; } } } item.setEnabled(canRun); } item = getToolBarItem("start"); if (item != null) { item.setEnabled(canStart); } item = getToolBarItem("stop"); if (item != null) { item.setEnabled(canStop); } item = getToolBarItem("play"); if (item != null) { item.setEnabled(has1Selection && (!(currentContent[0] instanceof ISelectedVuzeFileContent )) && PlayUtils.canPlayDS(currentContent[0])); } item = getToolBarItem("download"); if (item != null) { boolean enabled = has1Selection && (!(currentContent[0] instanceof ISelectedVuzeFileContent )) && currentContent[0].getDownloadManager() == null && (currentContent[0].getHash() != null || currentContent[0].getDownloadInfo() != null); item.setEnabled(enabled); } if (tv != null) { TableColumn tc = tv.getTableColumn(RankItem.COLUMN_ID); if (tc != null && !tc.isVisible()) { item = getToolBarItem("up"); if (item != null) { item.setEnabled(false); } item = getToolBarItem("down"); if (item != null) { item.setEnabled(false); } } } } /** * @param toolBarItem * * @since 3.1.1.1 */ protected void activateViaSideBar(ToolBarItem toolBarItem) { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { SideBarEntrySWT entry = sidebar.getCurrentEntry(); if (entry.iview != null) { entry.iview.itemActivated(toolBarItem.getId()); } } } /** * @param itemID * @return * * @since 3.1.1.1 */ public ToolBarItem getToolBarItem(String itemID) { return items.get(itemID); } public ToolBarItem[] getAllToolBarItems() { return items.values().toArray(new ToolBarItem[0]); } public void refreshCoreToolBarItems() { Utils.execSWTThread(new AERunnable() { public void runSupport() { _refreshCoreToolBarItems(); } }); } public void _refreshCoreToolBarItems() { ISelectedContent[] sc = SelectedContentManager.getCurrentlySelectedContent(); String sv = SelectedContentManager.getCurrentySelectedViewID(); if (sv != null) { updateCoreItems(sc, sv); } else { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { ToolBarItem[] allToolBarItems = getAllToolBarItems(); SideBarEntrySWT entry = sidebar.getCurrentEntry(); IconBarEnabler enabler = entry.getIconBarEnabler(); if (enabler == null) { if (entry.iview != null) { enabler = entry.iview; } else { for (int i = 0; i < allToolBarItems.length; i++) { ToolBarItem toolBarItem = allToolBarItems[i]; toolBarItem.setEnabled(false); } return; } } for (int i = 0; i < allToolBarItems.length; i++) { ToolBarItem toolBarItem = allToolBarItems[i]; toolBarItem.setEnabled(enabler.isEnabled(toolBarItem.getId())); } } } } private boolean triggerIViewToolBar(String id) { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { SideBarEntrySWT entry = sidebar.getCurrentEntry(); IconBarEnabler enabler = entry.getIconBarEnabler(); if (enabler == null && entry.iview != null) { enabler = entry.iview; } enabler.itemActivated(id); return true; } return false; } public void addToolBarItem(final ToolBarItem item) { addToolBarItem(item, "toolbar.area.item", soMain); } public void addToolBarItem(final ToolBarItem item, String templateID, SWTSkinObject soMain) { SWTSkinObject so = skin.createSkinObject("toolbar:" + item.getId(), templateID, soMain); if (so != null) { so.setTooltipID(item.getTooltipID()); if (lastControl != null) { FormData fd = (FormData) so.getControl().getLayoutData(); fd.left = new FormAttachment(lastControl); } so.setData("toolbaritem", item); SWTSkinButtonUtility btn = new SWTSkinButtonUtility(so, "toolbar-item-image"); btn.setImage(item.getImageID()); btn.addSelectionListener(buttonListener); item.setSkinButton(btn); SWTSkinObject soTitle = skin.getSkinObject("toolbar-item-title", so); if (soTitle instanceof SWTSkinObjectText) { ((SWTSkinObjectText) soTitle).setTextID(item.getTextID()); } if (initComplete) { Utils.relayout(so.getControl().getParent()); } lastControl = item.getSkinButton().getSkinObject().getControl(); items.put(item.getId(), item); } } private void addSeperator(SWTSkinObject soMain) { addSeperator("toolbar.area.sitem.sep", soMain); } private void addSeperator(String id, SWTSkinObject soMain) { SWTSkinObject so = skin.createSkinObject("toolbar_sep" + Math.random(), id, soMain); if (so != null) { if (lastControl != null) { FormData fd = (FormData) so.getControl().getLayoutData(); fd.left = new FormAttachment(lastControl, fd.left == null ? 0 : fd.left.offset); } lastControl = so.getControl(); } } private void addNonToolBar(String skinid, SWTSkinObject soMain) { SWTSkinObject so = skin.createSkinObject("toolbar_d" + Math.random(), skinid, soMain); if (so != null) { if (lastControl != null) { FormData fd = (FormData) so.getControl().getLayoutData(); fd.left = new FormAttachment(lastControl, fd.left == null ? 0 : fd.left.offset); } lastControl = so.getControl(); } } /** * @param showText the showText to set */ public void setShowText(boolean showText) { this.showText = showText; ToolBarItem[] allToolBarItems = getAllToolBarItems(); for (int i = 0; i < allToolBarItems.length; i++) { ToolBarItem tbi = allToolBarItems[i]; SWTSkinObject so = tbi.getSkinButton().getSkinObject(); SWTSkinObject soTitle = skin.getSkinObject("toolbar-item-title", so); soTitle.setVisible(showText); } } /** * @return the showText */ public boolean getShowText() { return showText; } private static class toolbarButtonListener extends ButtonListenerAdapter { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { ToolBarItem item = (ToolBarItem) buttonUtility.getSkinObject().getData( "toolbaritem"); item.triggerToolBarItem(); } public boolean held(SWTSkinButtonUtility buttonUtility) { ToolBarItem item = (ToolBarItem) buttonUtility.getSkinObject().getData( "toolbaritem"); buttonUtility.getSkinObject().switchSuffix("", 0, false, true); boolean triggerToolBarItemHold = item.triggerToolBarItemHold(); return triggerToolBarItemHold; } public void disabledStateChanged(SWTSkinButtonUtility buttonUtility, boolean disabled) { ToolBarItem item = (ToolBarItem) buttonUtility.getSkinObject().getData( "toolbaritem"); item.setEnabled(!disabled); } } public void flipShowText() { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb == null) { SkinViewManager.addListener(new SkinViewManagerListener() { public void skinViewAdded(SkinView skinview) { if (skinview instanceof ToolBarView) { SkinViewManager.RemoveListener(this); flipShowText(); } } }); return; } try { boolean showText = !tb.getShowText(); COConfigurationManager.setParameter("ToolBar.showText", showText); tb.setShowText(showText); SWTSkinObject skinObject; skinObject = skin.getSkinObject("search-text"); if (skinObject != null) { Control control = skinObject.getControl(); FormData fd = (FormData) control.getLayoutData(); fd.top.offset = showText ? 6 : 5; fd.bottom.offset = showText ? -3 : -2; } skinObject = skin.getSkinObject("topgap"); if (skinObject != null) { Control control = skinObject.getControl(); FormData fd = (FormData) control.getLayoutData(); fd.height = showText ? 6 : 2; } skinObject = skin.getSkinObject("tabbar"); if (skinObject != null) { Control control = skinObject.getControl(); FormData fd = (FormData) control.getLayoutData(); fd.height = showText ? 50 : 32; //Utils.relayout(control); skinObject.switchSuffix(showText ? "" : "-small", 4, true); Shell shell = control.getShell(); shell.layout(true, true); shell.redraw(); } } catch (Exception e) { Debug.out(e); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/Browse.java0000644000175000017500000003011411273703132024201 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.views.skin; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.ProgressEvent; import org.eclipse.swt.browser.ProgressListener; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ui.UIInputReceiver; import org.gudy.azureus2.plugins.ui.UIInputReceiverListener; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.menus.MenuItemListener; import org.gudy.azureus2.plugins.ui.menus.MenuManager; import org.gudy.azureus2.plugins.ui.sidebar.SideBarCloseListener; import org.gudy.azureus2.plugins.ui.sidebar.SideBarEntry; import org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.messenger.config.PlatformConfigMessenger; import com.aelitis.azureus.ui.common.RememberedDecisionsManager; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.browser.BrowserContext; import com.aelitis.azureus.ui.swt.skin.*; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter; import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog.SkinnedDialogClosedListener; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarListener; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.ContentNetworkUtils; /** * @author TuxPaper * @created Sep 30, 2006 * */ public class Browse extends SkinView implements SideBarCloseListener { protected static final String CFG_SHOWCLOSE = "contentnetwork.close.reminder"; private SWTSkinObjectBrowser browserSkinObject; public SWTSkinObjectBrowser getBrowserSkinObject() { return browserSkinObject; } private SWTSkin skin; private SWTSkinObject soMain; private SideBarVitalityImage vitalityImage; private ContentNetwork contentNetwork; // Only accessed in SWT thread private static List listAlreadyCalledLoginRPC = new ArrayList(); // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#skinObjectCreated(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectCreated(SWTSkinObject skinObject, Object params) { final SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { final SideBarEntrySWT entry = sidebar.getEntryBySkinView(this); if (entry != null) { entry.addListener(this); } } return super.skinObjectCreated(skinObject, params); } /* (non-Javadoc) * @see com.aelitis.azureus.ui.swt.views.SkinView#showSupport(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) */ public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) { this.soMain = skinObject; skin = skinObject.getSkin(); Object creationParams = skinObject.getData("CreationParams"); if (creationParams instanceof ContentNetwork) { contentNetwork = (ContentNetwork) creationParams; } else { contentNetwork = ConstantsVuze.getDefaultContentNetwork(); } // Vuze network login happens in Initializer. The rest can be initialized // when browser area is created (here) long cnID = contentNetwork.getID(); if (cnID != ContentNetwork.CONTENT_NETWORK_VUZE) { if (!listAlreadyCalledLoginRPC.contains(new Long(cnID))) { PlatformConfigMessenger.login(contentNetwork.getID(), 0); listAlreadyCalledLoginRPC.add(new Long(cnID)); } } browserSkinObject = SWTSkinUtils.findBrowserSO(soMain); final SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { final SideBarEntrySWT entry = sidebar.getEntryBySkinView(this); if (entry != null) { vitalityImage = entry.addVitalityImage("image.sidebar.vitality.dots"); vitalityImage.setVisible(false); sidebar.addListener(new SideBarListener() { long lastSelect = 0; public void sidebarItemSelected(SideBarEntrySWT newSideBarEntry, SideBarEntrySWT oldSideBarEntry) { if (entry == newSideBarEntry) { if (entry == oldSideBarEntry) { if (lastSelect < SystemTime.getOffsetTime(-1000)) { if (browserSkinObject != null) { browserSkinObject.restart(); } } } else { lastSelect = SystemTime.getCurrentTime(); } } } }); } } browserSkinObject.addListener(new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == EVENT_SHOW) { browserSkinObject.removeListener(this); browserSkinObject.addListener(new BrowserContext.loadingListener() { public void browserLoadingChanged(boolean loading, String url) { if (vitalityImage != null) { vitalityImage.setVisible(loading); } } }); browserSkinObject.getContext().setContentNetworkID(contentNetwork.getID()); browserSkinObject.setStartURL(ContentNetworkUtils.getUrl(contentNetwork, ContentNetwork.SERVICE_BIG_BROWSE)); } return null; } }); PluginInterface pi = PluginInitializer.getDefaultInterface(); UIManager uim = pi.getUIManager(); MenuManager menuManager = uim.getMenuManager(); String menuID = "sidebar." + ContentNetworkUtils.getTarget(contentNetwork); MenuItem item = menuManager.addMenuItem(menuID, "Button.reload"); item.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { browserSkinObject.refresh(); } }); if (org.gudy.azureus2.core3.util.Constants.isCVSVersion()) { MenuItem parent = menuManager.addMenuItem(menuID, "CVS Only"); parent.setStyle(MenuItem.STYLE_MENU); MenuItem menuItem = menuManager.addMenuItem(parent, "Button.reset"); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { browserSkinObject.getContext().executeInBrowser("sendMessage('display','reset-url', {});"); //browserSkinObject.restart(); } }); menuItem = menuManager.addMenuItem(parent, "Tux RPC Test"); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { browserSkinObject.setURL("c:\\test\\BrowserMessaging.html"); } }); menuItem = menuManager.addMenuItem(parent, "URL.."); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow("", "!URL!"); entryWindow.prompt(new UIInputReceiverListener() { public void UIInputReceiverClosed(UIInputReceiver entryWindow) { if (entryWindow.hasSubmittedInput()) { browserSkinObject.setURL(entryWindow.getSubmittedInput()); } } }); } }); if (contentNetwork != ConstantsVuze.getDefaultContentNetwork()) { menuItem = menuManager.addMenuItem(parent, "Remove HD Network"); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (sidebar != null) { final SideBarEntrySWT entry = sidebar.getEntryBySkinView(Browse.this); if (entry != null) { entry.removeListener(Browse.this); } sidebar.closeEntry(ContentNetworkUtils.getTarget(contentNetwork)); } contentNetwork.remove(); } }); menuItem = menuManager.addMenuItem(parent, "Reset IP Flag && Close"); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { contentNetwork.setPersistentProperty( ContentNetwork.PP_AUTH_PAGE_SHOWN, Boolean.FALSE); if (sidebar != null) { final SideBarEntrySWT entry = sidebar.getEntryBySkinView(Browse.this); if (entry != null) { entry.removeListener(Browse.this); } sidebar.closeEntry(ContentNetworkUtils.getTarget(contentNetwork)); } } }); } menuItem = menuManager.addMenuItem(parent, "Source Ref: " + contentNetwork.getPersistentProperty(ContentNetwork.PP_SOURCE_REF)); menuItem.setEnabled(false); } return null; } public void sidebarClosed(SideBarEntry entry) { boolean wasActive = false; Object prop = contentNetwork.getPersistentProperty(ContentNetwork.PP_ACTIVE); if (prop instanceof Boolean) { wasActive = ((Boolean) prop).booleanValue(); } contentNetwork.setPersistentProperty(ContentNetwork.PP_ACTIVE, Boolean.FALSE); // send sidebar close event to webapp Utils.execSWTThread(new AERunnable() { public void runSupport() { Shell shell = null; String url = ContentNetworkUtils.getUrl(contentNetwork, ContentNetwork.SERVICE_SIDEBAR_CLOSE); if (url == null) { return; } UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { shell = uiFunctions.getMainShell(); } if (shell == null) { return; } final Browser browser = Utils.createSafeBrowser(shell, SWT.NONE); if (browser == null) { return; } browser.setVisible(false); browser.addProgressListener(new ProgressListener() { public void completed(ProgressEvent event) { Utils.execSWTThreadLater(1000, new AERunnable() { public void runSupport() { if (browser.isDisposed() || browser.getShell().isDisposed()) { return; } browser.setUrl("about:blank"); browser.dispose(); } }); } public void changed(ProgressEvent event) { } }); browser.setUrl(url); } }); if (!wasActive) { return; } int decision = RememberedDecisionsManager.getRememberedDecision(CFG_SHOWCLOSE); if (decision != 1) { final SkinnedDialog closeDialog = new SkinnedDialog( "skin3_close_notification", "close-notification.body"); closeDialog.setTitle(MessageText.getString("v3.dialog.cnclose.title", new String[] { contentNetwork.getName() })); SWTSkin skin = closeDialog.getSkin(); SWTSkinObjectButton soButton = (SWTSkinObjectButton) skin.getSkinObject("close"); if (soButton != null) { soButton.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { closeDialog.close(); } }); } closeDialog.addCloseListener(new SkinnedDialogClosedListener() { public void skinDialogClosed(SkinnedDialog dialog) { SWTSkin skin = closeDialog.getSkin(); SWTSkinObjectCheckbox soCheck = (SWTSkinObjectCheckbox) skin.getSkinObject("noshowagain"); if (soCheck != null && soCheck.isChecked()) { RememberedDecisionsManager.setRemembered(CFG_SHOWCLOSE, 1); } } }); closeDialog.open(); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityView.java0000644000175000017500000001337211120653320026057 0ustar adrianadrian/** * Created on Jul 2, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.activities.VuzeActivitiesEntry; import com.aelitis.azureus.activities.VuzeActivitiesManager; import com.aelitis.azureus.ui.skin.SkinConstants; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import com.aelitis.azureus.ui.swt.toolbar.ToolBarItem; import com.aelitis.azureus.ui.swt.toolbar.ToolBarItemListener; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; /** * @author TuxPaper * @created Jul 2, 2008 * */ public class SBC_ActivityView extends SkinView { public final static String ID = "activity-list"; public final static int MODE_BIGTABLE = -1; public final static int MODE_SMALLTABLE = 0; public final static int MODE_DEFAULT = MODE_SMALLTABLE; private final static String[] modeViewIDs = { //SkinConstants.VIEWID_SIDEBAR_ACTIVITY_BIG, SkinConstants.VIEWID_SIDEBAR_ACTIVITY_SMALL, }; private final static String[] modeIDs = { //"activity.table.big", "activity.table.small", }; private int viewMode = -1; private SWTSkinButtonUtility btnSmallTable; private SWTSkinButtonUtility btnBigTable; private SWTSkinObject soListArea; // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#showSupport(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) { soListArea = getSkinObject(ID + "-area"); SWTSkinObject so; so = getSkinObject(ID + "-button-smalltable"); if (so != null) { btnSmallTable = new SWTSkinButtonUtility(so); btnSmallTable.addSelectionListener(new SWTSkinButtonUtility.ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { setViewMode(MODE_SMALLTABLE, true); } }); } so = getSkinObject(ID + "-button-bigtable"); if (so != null) { btnBigTable = new SWTSkinButtonUtility(so); btnBigTable.addSelectionListener(new SWTSkinButtonUtility.ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { setViewMode(MODE_BIGTABLE, true); } }); } so = getSkinObject(ID + "-button-right"); if (so != null) { so.setVisible(true); SWTSkinButtonUtility btnReadAll = new SWTSkinButtonUtility(so); btnReadAll.setTextID("v3.activity.button.readall"); btnReadAll.addSelectionListener(new SWTSkinButtonUtility.ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { VuzeActivitiesEntry[] allEntries = VuzeActivitiesManager.getAllEntries(); for (int i = 0; i < allEntries.length; i++) { VuzeActivitiesEntry entry = allEntries[i]; entry.setRead(true); } } }); } setViewMode(COConfigurationManager.getIntParameter(ID + ".viewmode", MODE_DEFAULT), false); return null; } public int getViewMode() { return viewMode; } public void setViewMode(int viewMode, boolean save) { if (viewMode >= modeViewIDs.length || viewMode < 0) { viewMode = MODE_DEFAULT; } if (viewMode == this.viewMode) { return; } int oldViewMode = this.viewMode; this.viewMode = viewMode; soListArea = getSkinObject(ID + "-area"); soListArea.getControl().setData("ViewMode", new Long(viewMode)); if (oldViewMode >= 0 && oldViewMode < modeViewIDs.length) { SWTSkinObject soOldViewArea = getSkinObject(modeViewIDs[oldViewMode]); if (soOldViewArea != null) { soOldViewArea.setVisible(false); } } SWTSkinObject soViewArea = getSkinObject(modeViewIDs[viewMode]); if (soViewArea == null) { soViewArea = skin.createSkinObject(modeIDs[viewMode], modeIDs[viewMode], soListArea); skin.layout(); soViewArea.setVisible(true); soViewArea.getControl().setLayoutData(Utils.getFilledFormData()); } else { soViewArea.setVisible(true); } if (btnSmallTable != null) { btnSmallTable.getSkinObject().switchSuffix( viewMode == MODE_SMALLTABLE ? "-selected" : ""); } if (btnBigTable != null) { btnBigTable.getSkinObject().switchSuffix( viewMode == MODE_BIGTABLE ? "-selected" : ""); } if (save) { COConfigurationManager.setParameter(ID + ".viewmode", viewMode); } SideBarEntrySWT entry = SideBar.getEntry(SideBar.SIDEBAR_SECTION_ACTIVITIES); if (entry != null) { entry.setLogID(SideBar.SIDEBAR_SECTION_ACTIVITIES + "-" + viewMode); } } protected void removeSelected() { SBC_ActivityTableView tv = (SBC_ActivityTableView) SkinViewManager.getBySkinObjectID(modeIDs[viewMode]); if (tv != null) { tv.removeSelected(); } } public int getNumSelected() { SBC_ActivityTableView tv = (SBC_ActivityTableView) SkinViewManager.getBySkinObjectID(modeIDs[viewMode]); if (tv != null) { return tv.getView().getSelectedRowsSize(); } return 0; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView.java0000644000175000017500000003752311274203460026651 0ustar adrianadrian/** * Created on Jul 3, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin; import java.util.Iterator; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.plugins.ui.tables.TableRow; import org.gudy.azureus2.plugins.ui.tables.TableRowRefreshListener; import org.gudy.azureus2.ui.swt.IconBarEnabler; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.views.IView; import org.gudy.azureus2.ui.swt.views.MyTorrentsSuperView; import org.gudy.azureus2.ui.swt.views.MyTorrentsView; import org.gudy.azureus2.ui.swt.views.table.TableRowSWT; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.TableRowCore; import com.aelitis.azureus.ui.common.table.TableSelectionAdapter; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfoContentNetwork; import com.aelitis.azureus.ui.swt.columns.utils.TableColumnCreatorV3; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectContainer; import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3; import com.aelitis.azureus.util.DLReferals; import com.aelitis.azureus.util.DataSourceUtils; import com.aelitis.azureus.util.PlayUtils; /** * Classic My Torrents view wrapped in a SkinView * * @author TuxPaper * @created Jul 3, 2008 * */ public class SBC_LibraryTableView extends SkinView implements UIUpdatable, IconBarEnabler { private final static String ID = "SBC_LibraryTableView"; private IView view; private Composite viewComposite; private TableViewSWT tv; protected int torrentFilterMode = SBC_LibraryView.TORRENTS_ALL; private SWTSkinObject soParent; public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) { soParent = skinObject.getParent(); AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(final AzureusCore core) { Utils.execSWTThread(new AERunnable() { public void runSupport() { initShow(core); } }); } }); return null; } public void initShow(AzureusCore core) { Object data = soParent.getControl().getData("TorrentFilterMode"); if (data instanceof Long) { torrentFilterMode = (int) ((Long) data).longValue(); } boolean useBigTable = useBigTable(); // columns not needed for small mode, all torrents TableColumnCore[] columns = useBigTable || torrentFilterMode != SBC_LibraryView.TORRENTS_ALL ? getColumns() : null; if (null != columns) { TableColumnManager tcManager = TableColumnManager.getInstance(); tcManager.addColumns(columns); } if (useBigTable) { if (torrentFilterMode == SBC_LibraryView.TORRENTS_COMPLETE || torrentFilterMode == SBC_LibraryView.TORRENTS_INCOMPLETE || torrentFilterMode == SBC_LibraryView.TORRENTS_UNOPENED) { view = new MyTorrentsView_Big(core, torrentFilterMode, columns); } else { //view = new MyTorrentsSuperView_Big(); view = new MyTorrentsView_Big(core, torrentFilterMode, columns); } } else { String tableID = SBC_LibraryView.getTableIdFromFilterMode( torrentFilterMode, false); if (torrentFilterMode == SBC_LibraryView.TORRENTS_COMPLETE) { view = new MyTorrentsView(core, tableID, true, columns); } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_INCOMPLETE) { view = new MyTorrentsView(core, tableID, false, columns); } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_UNOPENED) { view = new MyTorrentsView(core, tableID, true, columns) { public boolean isOurDownloadManager(DownloadManager dm) { if (PlatformTorrentUtils.getHasBeenOpened(dm)) { return false; } return super.isOurDownloadManager(dm); } }; } else { view = new MyTorrentsSuperView() { public void initializeDone() { MyTorrentsView seedingview = getSeedingview(); if (seedingview != null) { seedingview.overrideDefaultSelected(new TableSelectionAdapter() { public void defaultSelected(TableRowCore[] rows, int stateMask) { doDefaultClick(rows, stateMask, false); } }); MyTorrentsView torrentview = getTorrentview(); if (torrentview != null) { torrentview.overrideDefaultSelected(new TableSelectionAdapter() { public void defaultSelected(TableRowCore[] rows, int stateMask) { doDefaultClick(rows, stateMask, false); } }); } } } }; } if (view instanceof MyTorrentsView) { ((MyTorrentsView) view).overrideDefaultSelected(new TableSelectionAdapter() { public void defaultSelected(TableRowCore[] rows, int stateMask) { doDefaultClick(rows, stateMask, false); } }); } } SWTSkinObjectContainer soContents = new SWTSkinObjectContainer(skin, skin.getSkinProperties(), getUpdateUIName(), "", soMain); skin.layout(); viewComposite = soContents.getComposite(); viewComposite.setBackground(viewComposite.getDisplay().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND)); viewComposite.setForeground(viewComposite.getDisplay().getSystemColor( SWT.COLOR_WIDGET_FOREGROUND)); viewComposite.setLayoutData(Utils.getFilledFormData()); GridLayout gridLayout = new GridLayout(); gridLayout.horizontalSpacing = gridLayout.verticalSpacing = gridLayout.marginHeight = gridLayout.marginWidth = 0; viewComposite.setLayout(gridLayout); view.initialize(viewComposite); if (tv == null) { if (view instanceof TableViewTab) { TableViewTab tvt = (TableViewTab) view; tv = tvt.getTableView(); } else if (view instanceof TableViewSWT) { tv = (TableViewSWT) view; } } SWTSkinObject soSizeSlider = skin.getSkinObject("table-size-slider", soParent.getParent()); if (soSizeSlider instanceof SWTSkinObjectContainer) { SWTSkinObjectContainer so = (SWTSkinObjectContainer) soSizeSlider; if (tv != null && !tv.enableSizeSlider(so.getComposite(), 16, 100)) { so.setVisible(false); } } if (torrentFilterMode == SBC_LibraryView.TORRENTS_ALL && tv != null) { tv.addRefreshListener(new TableRowRefreshListener() { public void rowRefresh(TableRow row) { TableRowSWT rowCore = (TableRowSWT)row; DownloadManager dm = (DownloadManager) rowCore.getDataSource(true); boolean changed = false; boolean assumedComplete = dm.getAssumedComplete(); if (!assumedComplete) { changed |= rowCore.setAlpha(160); changed |= rowCore.setFontStyle(SWT.NORMAL); } else if (!PlatformTorrentUtils.getHasBeenOpened(dm)) { changed |= rowCore.setAlpha(255); changed |= rowCore.setFontStyle(SWT.BOLD); } else { changed |= rowCore.setAlpha(255); changed |= rowCore.setFontStyle(SWT.NORMAL); } } }); } if (tv != null) { tv.addKeyListener(new KeyListener() { public void keyReleased(KeyEvent e) { } public void keyPressed(KeyEvent e) { if (e.character == 15 && e.stateMask == (SWT.SHIFT | SWT.CONTROL)) { Object[] selectedDataSources = tv.getSelectedDataSources().toArray(); for (int i = 0; i < selectedDataSources.length; i++) { DownloadManager dm = (DownloadManager) selectedDataSources[i]; if (dm != null) { TOTorrent torrent = dm.getTorrent(); String contentHash = PlatformTorrentUtils.getContentHash(torrent); if (contentHash != null && contentHash.length() > 0) { ContentNetwork cn = DataSourceUtils.getContentNetwork(torrent); if (cn == null) { new MessageBoxShell(SWT.OK, "coq", "Not in Content Network List").open(null); return; } String url = cn.getTorrentDownloadService(contentHash, "coq"); DownloadUrlInfo dlInfo = new DownloadUrlInfoContentNetwork( url, cn); TorrentUIUtilsV3.loadTorrent(dlInfo, false, false, true, false); } } } } } }); } if (torrentFilterMode == SBC_LibraryView.TORRENTS_UNOPENED) { SWTSkinObject so = skin.getSkinObject("library-list-button-right", soParent.getParent()); if (so != null) { so.setVisible(true); SWTSkinButtonUtility btn = new SWTSkinButtonUtility(so); btn.setTextID("Mark All UnNew"); btn.addSelectionListener(new SWTSkinButtonUtility.ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { TableViewSWT tv = ((MyTorrentsView) view).getTableView(); Object[] dataSources = tv.getDataSources().toArray(); for (int i = 0; i < dataSources.length; i++) { Object ds = dataSources[i]; if (ds instanceof DownloadManager) { PlatformTorrentUtils.setHasBeenOpened((DownloadManager) ds, true); // give user visual indication right away tv.removeDataSource(ds); } } } }); } } viewComposite.getParent().layout(true); } public static void doDefaultClick(TableRowCore[] rows, int stateMask, boolean neverPlay) { if (rows == null || rows.length != 1) { return; } Object ds = rows[0].getDataSource(true); String mode = COConfigurationManager.getStringParameter("list.dm.dblclick"); if (mode.equals("1")) { // OMG! Show Details! I <3 you! DownloadManager dm = DataSourceUtils.getDM(ds); if (dm != null) { UIFunctionsManager.getUIFunctions().openView(UIFunctions.VIEW_DM_DETAILS, dm); return; } } else if (mode.equals("2")) { // Show in explorer DownloadManager dm = DataSourceUtils.getDM(ds); if (dm != null) { boolean openMode = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled"); ManagerUtils.open(dm, openMode); return; } } if (neverPlay) { return; } // fallback if (PlayUtils.canPlayDS(ds) || (stateMask & SWT.CONTROL) > 0) { TorrentListViewsUtils.playOrStreamDataSource(ds, null, DLReferals.DL_REFERAL_DBLCLICK); } } // @see com.aelitis.azureus.ui.swt.utils.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { return ID; } // @see com.aelitis.azureus.ui.swt.utils.UIUpdatable#updateUI() public void updateUI() { if (viewComposite == null || viewComposite.isDisposed() || !viewComposite.isVisible() || view == null) { return; } view.refresh(); } // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectShown(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectShown(SWTSkinObject skinObject, Object params) { super.skinObjectShown(skinObject, params); if (torrentFilterMode == SBC_LibraryView.TORRENTS_UNOPENED && AzureusCoreFactory.isCoreRunning()) { if (view instanceof MyTorrentsView) { MyTorrentsView torrentsView = (MyTorrentsView) view; TableViewSWT tv = torrentsView.getTableView(); List dms = AzureusCoreFactory.getSingleton().getGlobalManager().getDownloadManagers(); for (Iterator iter = dms.iterator(); iter.hasNext();) { DownloadManager dm = (DownloadManager) iter.next(); if (!torrentsView.isOurDownloadManager(dm)) { tv.removeDataSource(dm); } else { tv.addDataSource(dm); } } } } if (view instanceof MyTorrentsView) { ((MyTorrentsView)view).updateSelectedContent(); } updateUI(); return null; } // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectHidden(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectHidden(SWTSkinObject skinObject, Object params) { if (view instanceof MyTorrentsView) { ((MyTorrentsView)view).updateSelectedContent(); } return super.skinObjectHidden(skinObject, params); } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#isEnabled(java.lang.String) public boolean isEnabled(String itemKey) { try { if (view != null) { return view.isEnabled(itemKey); } } catch (Throwable t) { Debug.out(t); } return false; } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#isSelected(java.lang.String) public boolean isSelected(String itemKey) { try { if (view != null) { return view.isSelected(itemKey); } } catch (Throwable t) { Debug.out(t); } return false; } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#itemActivated(java.lang.String) public void itemActivated(String itemKey) { try { if (view != null) { view.itemActivated(itemKey); } } catch (Throwable t) { Debug.out(t); } } /** * Return either MODE_SMALLTABLE or MODE_BIGTABLE * Subclasses may override * @return */ protected int getTableMode() { return SBC_LibraryView.MODE_SMALLTABLE; } /** * Returns whether the big version of the tables should be used * Subclasses may override * @return */ protected boolean useBigTable() { return false; } /** * Returns the appropriate set of columns for the completed or incomplete torrents views * Subclasses may override to return different sets of columns * @return */ protected TableColumnCore[] getColumns() { if (torrentFilterMode == SBC_LibraryView.TORRENTS_COMPLETE) { return TableColumnCreator.createCompleteDM(TableManager.TABLE_MYTORRENTS_COMPLETE); } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_INCOMPLETE) { return TableColumnCreator.createIncompleteDM(TableManager.TABLE_MYTORRENTS_INCOMPLETE); } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_UNOPENED) { return TableColumnCreatorV3.createUnopenedDM( TableManager.TABLE_MYTORRENTS_UNOPENED, false); } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_ALL) { return TableColumnCreator.createCompleteDM(TableManager.TABLE_MYTORRENTS_ALL_BIG); } return null; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#skinObjectDestroyed(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectDestroyed(SWTSkinObject skinObject, Object params) { if (view != null) { view.delete(); } return super.skinObjectDestroyed(skinObject, params); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityTableView.java0000644000175000017500000002572711267524522027053 0ustar adrianadrian/** * Created on Sep 25, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.ui.swt.IconBarEnabler; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import com.aelitis.azureus.activities.*; import com.aelitis.azureus.ui.UserPrompterResultListener; import com.aelitis.azureus.ui.common.table.*; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.swt.columns.utils.TableColumnCreatorV3; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectContainer; import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectListener; /** * @author TuxPaper * @created Sep 25, 2008 * */ public class SBC_ActivityTableView extends SkinView implements UIUpdatable, IconBarEnabler, VuzeActivitiesListener { private static final String TABLE_ID_PREFIX = "activity-"; private TableViewSWT view; private String tableID; private Composite viewComposite; private int viewMode = SBC_ActivityView.MODE_SMALLTABLE; // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectInitialShow(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) { skinObject.addListener(new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == SWTSkinObjectListener.EVENT_SHOW) { SelectedContentManager.changeCurrentlySelectedContent(tableID, getCurrentlySelectedContent(), view); } else if (eventType == SWTSkinObjectListener.EVENT_HIDE) { SelectedContentManager.changeCurrentlySelectedContent(tableID, null, view); } return null; } }); SWTSkinObject soParent = skinObject.getParent(); Object data = soParent.getControl().getData( "ViewMode"); if (data instanceof Long) { viewMode = (int) ((Long) data).longValue(); } boolean big = viewMode == SBC_ActivityView.MODE_BIGTABLE; tableID = big ? TableManager.TABLE_ACTIVITY_BIG : TableManager.TABLE_ACTIVITY; TableColumnCore[] columns = big ? TableColumnCreatorV3.createActivityBig(tableID) : TableColumnCreatorV3.createActivitySmall(tableID); view = new TableViewSWTImpl(VuzeActivitiesEntry.class, tableID, tableID, columns, "name", SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL); view.setRowDefaultHeight(big ? 50 : 32); view.addKeyListener(new KeyListener() { public void keyReleased(KeyEvent e) { } public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.DEL) { removeSelected(); } else if (e.keyCode == SWT.F5) { if ((e.stateMask & SWT.SHIFT) > 0) { VuzeActivitiesManager.resetRemovedEntries(); } if ((e.stateMask & SWT.CONTROL) > 0) { System.out.println("pull all vuze news entries"); VuzeActivitiesManager.clearLastPullTimes(); VuzeActivitiesManager.pullActivitiesNow(0); } else { System.out.println("pull latest vuze news entries"); VuzeActivitiesManager.pullActivitiesNow(0); } } } }); view.addSelectionListener(new TableSelectionAdapter() { // @see com.aelitis.azureus.ui.common.table.TableSelectionAdapter#selected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void selected(TableRowCore[] rows) { selectionChanged(); for (int i = 0; i < rows.length; i++) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) rows[i].getDataSource(true); if (entry != null && !entry.isRead() && entry.canFlipRead()) { entry.setRead(true); } } } public void defaultSelected(TableRowCore[] rows, int stateMask) { if (rows.length == 1) { TorrentListViewsUtils.playOrStreamDataSource(rows[0].getDataSource(), null); } } public void deselected(TableRowCore[] rows) { selectionChanged(); } public void selectionChanged() { Utils.execSWTThread(new AERunnable() { public void runSupport() { ISelectedContent[] contents = getCurrentlySelectedContent(); if (soMain.isVisible()) { SelectedContentManager.changeCurrentlySelectedContent(tableID, contents, view); } } }); } }, false); view.addLifeCycleListener(new TableLifeCycleListener() { public void tableViewInitialized() { view.addDataSources(VuzeActivitiesManager.getAllEntries()); } public void tableViewDestroyed() { } }); SWTSkinObjectContainer soContents = new SWTSkinObjectContainer(skin, skin.getSkinProperties(), getUpdateUIName(), "", soMain); skin.layout(); viewComposite = soContents.getComposite(); viewComposite.setBackground(viewComposite.getDisplay().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND)); viewComposite.setForeground(viewComposite.getDisplay().getSystemColor( SWT.COLOR_WIDGET_FOREGROUND)); viewComposite.setLayoutData(Utils.getFilledFormData()); GridLayout gridLayout = new GridLayout(); gridLayout.horizontalSpacing = gridLayout.verticalSpacing = gridLayout.marginHeight = gridLayout.marginWidth = 0; viewComposite.setLayout(gridLayout); view.initialize(viewComposite); VuzeActivitiesManager.addListener(this); return null; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#skinObjectDestroyed(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectDestroyed(SWTSkinObject skinObject, Object params) { view.delete(); return super.skinObjectDestroyed(skinObject, params); } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { return tableID; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI() public void updateUI() { view.refreshTable(false); } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#isEnabled(java.lang.String) public boolean isEnabled(String itemKey) { return false; } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#isSelected(java.lang.String) public boolean isSelected(String itemKey) { return false; } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#itemActivated(java.lang.String) public void itemActivated(String itemKey) { } public ISelectedContent[] getCurrentlySelectedContent() { if (view == null) { return null; } List listContent = new ArrayList(); Object[] selectedDataSources = view.getSelectedDataSources(true); for (int i = 0; i < selectedDataSources.length; i++) { VuzeActivitiesEntry ds = (VuzeActivitiesEntry) selectedDataSources[i]; if (ds != null) { ISelectedContent currentContent; try { currentContent = ds.createSelectedContentObject(); if (currentContent != null) { listContent.add(currentContent); } } catch (Exception e) { e.printStackTrace(); } } } return (ISelectedContent[]) listContent.toArray(new ISelectedContent[listContent.size()]); } // @see com.aelitis.azureus.util.VuzeNewsListener#vuzeNewsEntriesAdded(com.aelitis.azureus.util.VuzeNewsEntry[]) public void vuzeNewsEntriesAdded(VuzeActivitiesEntry[] entries) { view.addDataSources(entries); } // @see com.aelitis.azureus.util.VuzeNewsListener#vuzeNewsEntriesRemoved(com.aelitis.azureus.util.VuzeNewsEntry[]) public void vuzeNewsEntriesRemoved(VuzeActivitiesEntry[] entries) { view.removeDataSources(entries); view.processDataSourceQueue(); } // @see com.aelitis.azureus.util.VuzeActivitiesListener#vuzeNewsEntryChanged(com.aelitis.azureus.util.VuzeActivitiesEntry) public void vuzeNewsEntryChanged(VuzeActivitiesEntry entry) { TableRowCore row = view.getRow(entry); if (row != null) { row.invalidate(); } } private void removeEntries(final VuzeActivitiesEntry[] toRemove, final int startIndex) { final VuzeActivitiesEntry entry = toRemove[startIndex]; if (entry == null || VuzeActivitiesConstants.TYPEID_HEADER.equals(entry.getTypeID())) { int nextIndex = startIndex + 1; if (nextIndex < toRemove.length) { removeEntries(toRemove, nextIndex); } return; } MessageBoxShell mb = new MessageBoxShell( MessageText.getString("v3.activity.remove.title"), MessageText.getString("v3.activity.remove.text", new String[] { entry.getText() })); mb.setRemember(tableID + "-Remove", false, MessageText.getString("MessageBoxWindow.nomoreprompting")); if (startIndex == toRemove.length - 1) { mb.setButtons(0, new String[] { MessageText.getString("Button.yes"), MessageText.getString("Button.no"), }, new Integer[] { 0, 1 }); mb.setRememberOnlyIfButton(0); } else { mb.setButtons(1, new String[] { MessageText.getString("Button.removeAll"), MessageText.getString("Button.yes"), MessageText.getString("Button.no"), }, new Integer[] { 2, 0, 1 }); mb.setRememberOnlyIfButton(1); } mb.setHandleHTML(false); mb.open(new UserPrompterResultListener() { public void prompterClosed(int result) { if (result == 2) { int numToRemove = toRemove.length - startIndex; VuzeActivitiesEntry[] toGroupRemove = new VuzeActivitiesEntry[numToRemove]; System.arraycopy(toRemove, startIndex, toGroupRemove, 0, numToRemove); VuzeActivitiesManager.removeEntries(toGroupRemove); return; } else if (result == 0) { VuzeActivitiesManager.removeEntries(new VuzeActivitiesEntry[] { entry } ); } int nextIndex = startIndex + 1; if (nextIndex < toRemove.length) { removeEntries(toRemove, nextIndex); } } }); } protected void removeSelected() { VuzeActivitiesEntry[] selectedEntries = view.getSelectedDataSources().toArray(new VuzeActivitiesEntry[0]); removeEntries(selectedEntries, 0); } public TableViewSWT getView() { return view; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/SearchResultsTabArea.java0000644000175000017500000004504711276176766027006 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.views.skin; import java.io.File; import java.util.Arrays; import java.util.Comparator; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.*; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.menus.*; import org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.PropertiesWindow; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.metasearch.Engine; import com.aelitis.azureus.core.metasearch.MetaSearchManagerFactory; import com.aelitis.azureus.core.metasearch.impl.web.WebEngine; import com.aelitis.azureus.core.metasearch.impl.web.json.JSONEngine; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager; import com.aelitis.azureus.ui.skin.SkinConstants; import com.aelitis.azureus.ui.swt.browser.BrowserContext; import com.aelitis.azureus.ui.swt.browser.CookiesListener; import com.aelitis.azureus.ui.swt.browser.OpenCloseSearchDetailsListener; import com.aelitis.azureus.ui.swt.browser.BrowserContext.loadingListener; import com.aelitis.azureus.ui.swt.browser.listener.ExternalLoginCookieListener; import com.aelitis.azureus.ui.swt.browser.listener.MetaSearchListener; import com.aelitis.azureus.ui.swt.skin.*; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.MapUtils; import com.aelitis.azureus.util.UrlFilter; /** * @author TuxPaper * @created Sep 30, 2006 * */ public class SearchResultsTabArea extends SkinView implements ViewTitleInfo, OpenCloseSearchDetailsListener { private SWTSkinObjectBrowser browserSkinObject; private SWTSkin skin; private String searchText; private boolean searchResultsInitialized = false; protected String title; private MenuItem menuItem; private SideBarVitalityImage vitalityImage; public static class SearchQuery { public String term; public boolean toSubscribe; } /* (non-Javadoc) * @see com.aelitis.azureus.ui.swt.views.SkinView#showSupport(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) */ public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) { skin = skinObject.getSkin(); browserSkinObject = (SWTSkinObjectBrowser) skin.getSkinObject( SkinConstants.VIEWID_BROWSER_SEARCHRESULTS, skinObject); browserSkinObject.addListener(new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == EVENT_SHOW) { browserSkinObject.removeListener(this); createBrowseArea(browserSkinObject); } return null; } }); /** final SWTSkinTabSet tabSetMain = skin.getTabSet(SkinConstants.TABSET_MAIN); if (tabSetMain != null) { final SWTSkinObjectTab tab = tabSetMain.getTab(SkinConstants.VIEWID_SEARCHRESULTS_TAB); if (tab != null) { SWTSkinObjectListener l = new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == SWTSkinObjectListener.EVENT_SELECT) { tab.setVisible(tabSetMain.getActiveTab() == tab); } return null; } }; tab.addListener(l); } } **/ AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(final AzureusCore core) { Utils.execSWTThread(new AERunnable() { public void runSupport() { initCoreStuff(core); } }); } }); if (browserSkinObject != null) { Object o = skinObject.getData("CreationParams"); if(o instanceof String) { anotherSearch((String) o); } if(o instanceof SearchQuery) { SearchQuery sq = (SearchQuery) o; anotherSearch(sq.term,sq.toSubscribe); } } closeSearchResults(null); return null; } private void initCoreStuff(AzureusCore core) { PluginInterface pi = PluginInitializer.getDefaultInterface(); UIManager uim = pi.getUIManager(); final MenuManager menuManager = uim.getMenuManager(); if ( menuItem == null ){ menuItem = menuManager.addMenuItem("sidebar.Search","Search.menu.engines"); menuItem.setStyle( MenuItem.STYLE_MENU ); menuItem.addFillListener( new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { menuItem.removeAllChildItems(); Engine[] engines = MetaSearchManagerFactory.getSingleton().getMetaSearch().getEngines( true, false ); Arrays.sort( engines, new Comparator() { public int compare( Object o1, Object o2) { return(((Engine)o1).getName().compareToIgnoreCase(((Engine)o2).getName())); } }); for (int i=0;i 0 ){ MenuItem mi = menuManager.addMenuItem( engine_menu, "Subscription.menu.resetauth" ); mi.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target) { we.setCookies( null ); } }); } } } if ( engine_menu.getItems().length > 0 ){ MenuItem mi = menuManager.addMenuItem( engine_menu, "Subscription.menu.sep" ); mi.setStyle( MenuItem.STYLE_SEPARATOR ); } MenuItem mi = menuManager.addMenuItem( engine_menu, "Subscription.menu.properties" ); mi.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target) { String engine_str; String auth_str = String.valueOf(false); engine_str = engine.getNameEx(); if ( engine instanceof WebEngine ){ WebEngine web_engine = (WebEngine)engine; if ( web_engine.isNeedsAuth()){ auth_str = String.valueOf(true) + ": cookies=" + toString( web_engine.getRequiredCookies()); } } String[] keys = { "subs.prop.template", "subs.prop.auth", }; String[] values = { engine_str, auth_str, }; new PropertiesWindow( engine.getName(), keys, values ); } private String toString( String[] strs ) { String res = ""; for(int i=0;i 0) { title = title.substring(i + 9); } } }); final ExternalLoginCookieListener cookieListener = new ExternalLoginCookieListener(new CookiesListener() { public void cookiesFound(String cookies) { browser.setData("current-cookies", cookies); } },browser); cookieListener.hook(); } } }); } Utils.execSWTThread(new AERunnable() { public void runSupport() { SWTSkinObject soSearchResults = getSkinObject("searchresults-search-results"); if (soSearchResults == null) { return; } Control controlTop = browserSkinObject.getControl(); Control controlBottom = soSearchResults.getControl(); Browser search = ((SWTSkinObjectBrowser) soSearchResults).getBrowser(); String url = MapUtils.getMapString(params, "url", "http://google.com/search?q=" + Math.random()); if (UrlFilter.getInstance().urlCanRPC(url)) { url = ConstantsVuze.getDefaultContentNetwork().appendURLSuffix(url, false, true); } //Gudy, Not Tux, Listener Added String listenerAdded = (String) search.getData("g.nt.la"); if (listenerAdded == null) { search.setData("g.nt.la", ""); search.addProgressListener(new ProgressListener() { public void changed(ProgressEvent event) { } public void completed(ProgressEvent event) { Browser search = (Browser) event.widget; String execAfterLoad = (String) search.getData("execAfterLoad"); //Erase it, so that it's only used once after the page loads search.setData("execAfterLoad", null); if (execAfterLoad != null && !execAfterLoad.equals("")) { //String execAfterLoadDisplay = execAfterLoad.replaceAll("'","\\\\'"); //search.execute("alert('injecting script : " + execAfterLoadDisplay + "');"); boolean result = search.execute(execAfterLoad); //System.out.println("Injection : " + execAfterLoad + " (" + result + ")"); } } }); } //Store the "css" match string in the search cdp browser object String execAfterLoad = MapUtils.getMapString(params, "execAfterLoad", null); search.setData("execAfterLoad", execAfterLoad); search.setUrl(url); FormData gd = (FormData) controlBottom.getLayoutData(); gd.top = new FormAttachment(controlTop, 0); gd.height = SWT.DEFAULT; controlBottom.setLayoutData(gd); soSearchResults.setVisible(true); controlBottom.setVisible(true); search.setVisible(true); gd = (FormData) controlTop.getLayoutData(); gd.bottom = null; gd.height = MapUtils.getMapInt(params, "top-height", 120); controlTop.setLayoutData(gd); controlTop.getParent().layout(true); } }); } public void closeSearchResults(final Map params) { Utils.execSWTThread(new AERunnable() { public void runSupport() { SWTSkinObject soSearchResults = skin.getSkinObject("searchresults-search-results"); if (soSearchResults == null) { return; } Control controlTop = browserSkinObject.getControl(); Control controlBottom = soSearchResults.getControl(); Browser search = ((SWTSkinObjectBrowser) soSearchResults).getBrowser(); soSearchResults.setVisible(false); FormData gd = (FormData) controlBottom.getLayoutData(); if (gd == null) { return; } gd.top = null; gd.height = 0; controlBottom.setLayoutData(gd); gd = (FormData) controlTop.getLayoutData(); gd.bottom = new FormAttachment(controlBottom, 0); gd.height = SWT.DEFAULT; controlTop.setLayoutData(gd); controlBottom.getParent().layout(true); search.setUrl("about:blank"); BrowserContext context = browserSkinObject.getContext(); if (context != null) { context.executeInBrowser("searchResultsClosed()"); } } }); } public void resizeMainBrowser() { // TODO Auto-generated method stub } public void resizeSecondaryBrowser() { // TODO Auto-generated method stub } public void anotherSearch(String searchText) { anotherSearch(searchText,false); } public void anotherSearch(String searchText,boolean toSubscribe) { this.searchText = searchText; String url = ConstantsVuze.getDefaultContentNetwork().getSearchService( searchText ); if (System.getProperty("metasearch", "1").equals("1")) { url = ConstantsVuze.getDefaultContentNetwork().getXSearchService( searchText, toSubscribe ); } closeSearchResults(null); browserSkinObject.setURL(url); ViewTitleInfoManager.refreshTitleInfo(this); } // @see com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo#getTitleInfoProperty(int) public Object getTitleInfoProperty(int propertyID) { if (propertyID == TITLE_SKINVIEW) { return this; } if (propertyID == TITLE_TEXT) { return searchText; } return null; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/sidebar/0000755000175000017500000000000011310377632023513 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarVitalityImageSWT.java0000644000175000017500000001666311247620536030775 0ustar adrianadrian/** * Created on Sep 15, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin.sidebar; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import org.gudy.azureus2.plugins.ui.sidebar.*; /** * @author TuxPaper * @created Sep 15, 2008 * */ public class SideBarVitalityImageSWT implements SideBarVitalityImage { private String imageID; private final SideBarEntrySWT sideBarEntry; private List listeners = Collections.EMPTY_LIST; private String tooltip; private Rectangle hitArea; private boolean visible = true; private int currentAnimationIndex; private String suffix = ""; private TimerEventPerformer performer; private TimerEventPeriodic timerEvent; private Image[] images; private int delayTime = -1; private String fullImageID; private int alignment = SWT.RIGHT; /** * @param imageID */ public SideBarVitalityImageSWT( SideBarEntrySWT entry, String imageID ) { performer = new TimerEventPerformer() { private boolean exec_pending = false; private Object lock = this; public void perform( TimerEvent event ) { synchronized( lock ){ if ( exec_pending ){ return; } exec_pending = true; } Utils.execSWTThread( new AERunnable() { public void runSupport() { synchronized( lock ){ exec_pending = false; } if (images == null || images.length == 0 || !visible || hitArea == null) { return; } currentAnimationIndex++; if (currentAnimationIndex >= images.length) { currentAnimationIndex = 0; } TreeItem treeItem = sideBarEntry.getTreeItem(); if (treeItem == null || treeItem.isDisposed()) { return; } Tree parent = treeItem.getParent(); // SWT.PAINTITEM won't fire on Cocoa unless whole row is dirtied Rectangle redrawBounds = Utils.isCocoa ? treeItem.getBounds() : hitArea; parent.redraw(redrawBounds.x, redrawBounds.y, redrawBounds.width, redrawBounds.height, true); parent.update(); } }); } }; this.sideBarEntry = entry; entry.addListener(new SideBarCloseListener() { public void sidebarClosed(SideBarEntry entry) { ImageLoader imageLoader = ImageLoader.getInstance(); if (fullImageID != null) { imageLoader.releaseImage(fullImageID); } } }); setImageID(imageID); } // @see org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage#getImageID() public String getImageID() { return imageID; } /** * @return the sideBarEntry */ public SideBarEntry getSideBarEntry() { return sideBarEntry; } // @see org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage#addListener(org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImageListener) public void addListener(SideBarVitalityImageListener l) { if (listeners == Collections.EMPTY_LIST) { listeners = new ArrayList(1); } listeners.add(l); } public void triggerClickedListeners(int x, int y) { Object[] list = listeners.toArray(); for (int i = 0; i < list.length; i++) { SideBarVitalityImageListener l = (SideBarVitalityImageListener) list[i]; try { l.sbVitalityImage_clicked(x, y); } catch (Exception e) { Debug.out(e); } } } // @see org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage#setTooltip(java.lang.String) public void setToolTip(String tooltip) { this.tooltip = tooltip; } public String getToolTip() { return tooltip; } /** * @param bounds * * @since 3.1.1.1 */ public void setHitArea(Rectangle hitArea) { this.hitArea = hitArea; } public Rectangle getHitArea() { return hitArea; } // @see org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage#getVisible() public boolean isVisible() { return visible; } // @see org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage#setVisible(boolean) public void setVisible(boolean visible) { if (this.visible == visible) { return; } this.visible = visible; if (visible) { createTimerEvent(); } else if (timerEvent != null) { timerEvent.cancel(); } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (sideBarEntry != null) { sideBarEntry.redraw(); } } }); } /** * * * @since 3.1.1.1 */ private void createTimerEvent() { if (timerEvent != null) { timerEvent.cancel(); } if (images.length > 1) { ImageLoader imageLoader = ImageLoader.getInstance(); int delay = delayTime == -1 ? imageLoader.getAnimationDelay(imageID) : delayTime; timerEvent = SimpleTimer.addPeriodicEvent("Animate " + imageID + suffix, delay, performer); } } /** * @param images * @return the currentAnimationIndex */ public int getCurrentAnimationIndex(Image[] images) { if (currentAnimationIndex >= images.length) { currentAnimationIndex = 0; } else if (currentAnimationIndex < 0) { currentAnimationIndex = 0; } return currentAnimationIndex; } public void switchSuffix(String suffix) { if (suffix == null) { suffix = ""; } if (suffix.equals(this.suffix)) { return; } this.suffix = suffix; setImageID(imageID); } public void setImageID(String id) { ImageLoader imageLoader = ImageLoader.getInstance(); String newFullImageID = id + suffix; if (newFullImageID.equals(fullImageID)) { return; } if (fullImageID != null) { imageLoader.releaseImage(fullImageID); } this.imageID = id; images = imageLoader.getImages(newFullImageID); if (images == null || images.length == 0) { imageLoader.releaseImage(newFullImageID); newFullImageID = id; images = imageLoader.getImages(id); } fullImageID = newFullImageID; currentAnimationIndex = 0; createTimerEvent(); } /** * @return * * @since 3.1.1.1 */ public Image getImage() { if (images == null || images.length == 0 || currentAnimationIndex >= images.length) { return null; } return images[currentAnimationIndex]; } /** * @param delayTime the delayTime to set */ public void setDelayTime(int delayTime) { if (this.delayTime == delayTime) { return; } this.delayTime = delayTime; createTimerEvent(); } /** * @return the delayTime */ public int getDelayTime() { return delayTime; } public int getAlignment() { return alignment; } public void setAlignment(int alignment) { this.alignment = alignment; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarToolTips.java0000644000175000017500000001457211120653320027364 0ustar adrianadrian/** * Created on Aug 13, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin.sidebar; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.*; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo; import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT; import org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage; /** * @author TuxPaper * @created Aug 13, 2008 * */ public class SideBarToolTips implements Listener, UIUpdatable { Shell toolTipShell = null; Shell mainShell = null; Label toolTipLabel = null; private final Tree tree; private final SideBar sidebar; private SideBarEntrySWT sidebarEntry; private Point lastMouseHoverPos; /** * Initialize */ public SideBarToolTips(SideBar sidebar, Tree tree) { this.sidebar = sidebar; this.tree = tree; mainShell = tree.getShell(); tree.addListener(SWT.Dispose, this); tree.addListener(SWT.KeyDown, this); tree.addListener(SWT.MouseMove, this); tree.addListener(SWT.MouseHover, this); mainShell.addListener(SWT.Deactivate, this); tree.addListener(SWT.Deactivate, this); } public void handleEvent(Event event) { switch (event.type) { case SWT.MouseHover: { handleHover(new Point(event.x, event.y)); break; } case SWT.Dispose: if (mainShell != null && !mainShell.isDisposed()) { mainShell.removeListener(SWT.Deactivate, this); } // fall through default: if (toolTipShell != null) { toolTipShell.dispose(); toolTipShell = null; toolTipLabel = null; } break; } // switch } // handlEvent() /** * * * @since 3.1.1.1 */ private void handleHover(Point mousePos) { if (toolTipShell != null && !toolTipShell.isDisposed()) toolTipShell.dispose(); if (tree.getItemCount() == 0) { return; } int indent = tree.getItem(0).getBounds().x; TreeItem treeItem = tree.getItem(new Point(indent, mousePos.y)); if (treeItem == null) { return; } String id = (String) treeItem.getData("Plugin.viewID"); sidebarEntry = SideBar.getEntry(id); String sToolTip = getToolTip(mousePos); if (sToolTip == null) { return; } lastMouseHoverPos = mousePos; Display d = tree.getDisplay(); if (d == null) return; // We don't get mouse down notifications on trim or borders.. toolTipShell = new Shell(tree.getShell(), SWT.ON_TOP); toolTipShell.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event event) { UIUpdaterSWT.getInstance().removeUpdater(SideBarToolTips.this); } }); FillLayout f = new FillLayout(); try { f.marginWidth = 3; f.marginHeight = 1; } catch (NoSuchFieldError e) { /* Ignore for Pre 3.0 SWT.. */ } toolTipShell.setLayout(f); toolTipShell.setBackground(d.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); toolTipLabel = new Label(toolTipShell, SWT.WRAP); toolTipLabel.setForeground(d.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); toolTipLabel.setBackground(d.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); toolTipLabel.setText(sToolTip.replaceAll("&", "&&")); // compute size on label instead of shell because label // calculates wrap, while shell doesn't Point size = toolTipLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT); if (size.x > 600) { size = toolTipLabel.computeSize(600, SWT.DEFAULT, true); } size.x += toolTipShell.getBorderWidth() * 2 + 2; size.y += toolTipShell.getBorderWidth() * 2; try { size.x += toolTipShell.getBorderWidth() * 2 + (f.marginWidth * 2); size.y += toolTipShell.getBorderWidth() * 2 + (f.marginHeight * 2); } catch (NoSuchFieldError e) { /* Ignore for Pre 3.0 SWT.. */ } Point pt = tree.toDisplay(mousePos.x, mousePos.y); Rectangle displayRect; try { displayRect = tree.getMonitor().getClientArea(); } catch (NoSuchMethodError e) { displayRect = tree.getDisplay().getClientArea(); } if (pt.x + size.x > displayRect.x + displayRect.width) { pt.x = displayRect.x + displayRect.width - size.x; } if (pt.y + size.y > displayRect.y + displayRect.height) { pt.y -= size.y + 2; } else { pt.y += 21; } if (pt.y < displayRect.y) pt.y = displayRect.y; toolTipShell.setBounds(pt.x, pt.y, size.x, size.y); toolTipShell.setVisible(true); UIUpdaterSWT.getInstance().addUpdater(this); } /** * @return * * @since 3.1.1.1 */ private String getToolTip(Point mousePos) { SideBarVitalityImage[] vitalityImages = sidebarEntry.getVitalityImages(); for (int i = 0; i < vitalityImages.length; i++) { SideBarVitalityImageSWT vitalityImage = (SideBarVitalityImageSWT) vitalityImages[i]; String indicatorToolTip = vitalityImage.getToolTip(); if (indicatorToolTip == null || !vitalityImage.isVisible()) { continue; } Rectangle hitArea = vitalityImage.getHitArea(); if (hitArea == null) { continue; } if (hitArea.contains(mousePos)) { return indicatorToolTip; } } if (sidebarEntry.titleInfo != null) { return (String) sidebarEntry.titleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_INDICATOR_TEXT_TOOLTIP); } return null; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { return "SideBarToolTips"; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI() public void updateUI() { if (toolTipLabel == null || toolTipLabel.isDisposed()) { return; } if (sidebarEntry == null || sidebarEntry.titleInfo == null) { return; } String sToolTip = getToolTip(lastMouseHoverPos); if (sToolTip == null) { return; } toolTipLabel.setText(sToolTip.replaceAll("&", "&&")); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarEntrySWT.java0000644000175000017500000002532111301136112027274 0ustar adrianadrian/** * Created on Aug 13, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin.sidebar; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import org.gudy.azureus2.ui.swt.IconBarEnabler; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.IconBar.IconBarListener; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import org.gudy.azureus2.ui.swt.views.IView; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import org.gudy.azureus2.plugins.ui.sidebar.*; /** * @author TuxPaper * @created Aug 13, 2008 * */ public class SideBarEntrySWT implements SideBarEntry { final public String id; public String parentID; public Object datasource; public ViewTitleInfo titleInfo; SWTSkinObject skinObject; TreeItem treeItem; boolean pullTitleFromIView; public IView iview; public boolean closeable; public UISWTViewEventListener eventListener; public Class iviewClass; public Class[] iviewClassArgs; public Object[] iviewClassVals; public boolean disableCollapse; private List listVitalityImages = Collections.EMPTY_LIST; private String imageLeftID; private List listCloseListeners = Collections.EMPTY_LIST; private List listLogIDListeners = Collections.EMPTY_LIST; private List listOpenListeners = Collections.EMPTY_LIST; private List listDropListeners = Collections.EMPTY_LIST; private IconBarEnabler iconBarEnabler; private final SideBar sidebar; private String logID; private Image imageLeft; public SideBarEntrySWT(SideBar sidebar, String id) { this.id = id; if (id == null) { logID = "null"; } else { int i = id.indexOf('_'); if (i > 0) { logID = id.substring(0, i); } else { logID = id; } } this.sidebar = sidebar; } public String getParentID() { return parentID; } public void setParentID(String parentID) { this.parentID = parentID; } public Object getDatasourceCore() { return datasource; } public Object getDatasource() { return PluginCoreUtils.convert(datasource, false); } public void setDatasource(Object datasource) { this.datasource = datasource; } public ViewTitleInfo getTitleInfo() { return titleInfo; } public void setTitleInfo(ViewTitleInfo titleInfo) { this.titleInfo = titleInfo; sidebar.linkTitleInfoToEntry(titleInfo, this); if (treeItem != null && !treeItem.isDisposed()) { String newText = (String) titleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_TEXT); if (newText != null) { pullTitleFromIView = false; treeItem.setData("text", newText); redraw(); } } } public SWTSkinObject getSkinObject() { return skinObject; } public void setSkinObject(SWTSkinObject skinObject) { this.skinObject = skinObject; } public TreeItem getTreeItem() { return treeItem; } public void setTreeItem(TreeItem treeItem) { this.treeItem = treeItem; } public boolean isPullTitleFromIView() { return pullTitleFromIView; } public void setPullTitleFromIView(boolean pullTitleFromIView) { this.pullTitleFromIView = pullTitleFromIView; } public IView getIView() { return iview; } public void setIView(IView iview) { this.iview = iview; } public boolean isCloseable() { return closeable; } public void setCloseable(boolean closeable) { this.closeable = closeable; } public UISWTViewEventListener getEventListener() { return eventListener; } public void setEventListener(UISWTViewEventListener eventListener) { this.eventListener = eventListener; } public Class getIViewClass() { return iviewClass; } public void setIViewClass(Class iviewClass) { this.iviewClass = iviewClass; } public Class[] getIViewClassArgs() { return iviewClassArgs; } public void setIViewClassArgs(Class[] iviewClassArgs) { this.iviewClassArgs = iviewClassArgs; } public Object[] getIViewClassVals() { return iviewClassVals; } public void setIViewClassVals(Object[] iviewClassVals) { this.iviewClassVals = iviewClassVals; } public String getId() { return id; } // @see org.gudy.azureus2.plugins.ui.sidebar.SideBarEntry#addVitalityImage(java.lang.String) public SideBarVitalityImage addVitalityImage(String imageID) { SideBarVitalityImageSWT vitalityImage = new SideBarVitalityImageSWT(this, imageID); if (listVitalityImages == Collections.EMPTY_LIST) { listVitalityImages = new ArrayList(1); } listVitalityImages.add(vitalityImage); return vitalityImage; } public SideBarVitalityImage[] getVitalityImages() { return (SideBarVitalityImage[]) listVitalityImages.toArray(new SideBarVitalityImage[0]); } public SideBarVitalityImage getVitalityImage(int hitX, int hitY) { SideBarVitalityImage[] vitalityImages = getVitalityImages(); for (int i = 0; i < vitalityImages.length; i++) { SideBarVitalityImageSWT vitalityImage = (SideBarVitalityImageSWT) vitalityImages[i]; if (!vitalityImage.isVisible()) { continue; } Rectangle hitArea = vitalityImage.getHitArea(); if (hitArea != null && hitArea.contains(hitX, hitY)) { return vitalityImage; } } return null; } public void redraw() { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (treeItem == null || treeItem.isDisposed()) { return; } Tree tree = treeItem.getParent(); Rectangle bounds = treeItem.getBounds(); Rectangle treeBounds = tree.getBounds(); tree.redraw(0, bounds.y, treeBounds.width, bounds.height, true); //tree.update(); } }); } public Rectangle getBounds() { if (treeItem == null || treeItem.isDisposed()) { return null; } Tree tree = treeItem.getParent(); Rectangle bounds = treeItem.getBounds(); Rectangle treeBounds = tree.getBounds(); return new Rectangle(0, bounds.y, treeBounds.width, bounds.height); } public void setImageLeftID(String id) { imageLeftID = id; imageLeft = null; } public String getImageLeftID() { return( imageLeftID ); } /** * @param imageLeft the imageLeft to set */ public void setImageLeft(Image imageLeft) { this.imageLeft = imageLeft; imageLeftID = null; redraw(); } public Image getImageLeft(String suffix) { if (imageLeft != null) { return imageLeft; } if (imageLeftID == null) { return null; } Image img = null; if (suffix == null) { img = ImageLoader.getInstance().getImage(imageLeftID); } else { img = ImageLoader.getInstance().getImage(imageLeftID + suffix); } if (ImageLoader.isRealImage(img)) { return img; } return null; } public void releaseImageLeft(String suffix) { if (imageLeft != null) { ImageLoader.getInstance().releaseImage(imageLeftID + suffix); } } /** * @param l * * @since 4.0.0.5 */ public void addListener(SideBarCloseListener l) { if (listCloseListeners == Collections.EMPTY_LIST) { listCloseListeners = new ArrayList(1); } listCloseListeners.add(l); } public void removeListener(SideBarCloseListener l) { listCloseListeners.remove(l); } protected void triggerCloseListeners() { Object[] list = listCloseListeners.toArray(); for (int i = 0; i < list.length; i++) { SideBarCloseListener l = (SideBarCloseListener) list[i]; try { l.sidebarClosed(this); } catch (Exception e) { Debug.out(e); } } } public void addListener(SideBarLogIdListener l) { if (listLogIDListeners == Collections.EMPTY_LIST) { listLogIDListeners = new ArrayList(1); } listLogIDListeners.add(l); } public void removeListener(SideBarLogIdListener sideBarLogIdListener) { listLogIDListeners.remove(sideBarLogIdListener); } protected void triggerLogIDListeners(String oldID) { Object[] list = listLogIDListeners.toArray(); for (int i = 0; i < list.length; i++) { SideBarLogIdListener l = (SideBarLogIdListener) list[i]; l.sidebarLogIdChanged(this, oldID, logID); } } public void addListener(SideBarOpenListener l) { if (listOpenListeners == Collections.EMPTY_LIST) { listOpenListeners = new ArrayList(1); } listOpenListeners.add(l); if (treeItem != null) { l.sideBarEntryOpen(this); } } public void removeListener(SideBarOpenListener l) { listOpenListeners.remove(l); } protected void triggerOpenListeners() { Object[] list = listOpenListeners.toArray(); for (int i = 0; i < list.length; i++) { SideBarOpenListener l = (SideBarOpenListener) list[i]; l.sideBarEntryOpen(this); } } public void addListener(SideBarDropListener l) { if (listDropListeners == Collections.EMPTY_LIST) { listDropListeners = new ArrayList(1); } listDropListeners.add(l); } public void removeListener(SideBarDropListener l) { listDropListeners.remove(l); } protected boolean hasDropListeners() { return listDropListeners != null && listDropListeners.size() > 0; } /** * * @param o * @return true: handled; false: not handled */ protected boolean triggerDropListeners(Object o) { boolean handled = false; Object[] list = listDropListeners.toArray(); for (int i = 0; i < list.length; i++) { SideBarDropListener l = (SideBarDropListener) list[i]; handled = l.sideBarEntryDrop(this, o); if (handled) { break; } } return handled; } public String getLogID() { return logID; } public void setLogID(String logID) { if (logID == null || logID.equals("" + this.logID)) { return; } String oldID = this.logID; this.logID = logID; triggerLogIDListeners(oldID); } public SideBar getSidebar() { return sidebar; } /** * @return */ public boolean isInTree() { return treeItem != null && !treeItem.isDisposed(); } public IconBarEnabler getIconBarEnabler() { return iconBarEnabler; } public void setIconBarEnabler(IconBarEnabler iconBarEnabler) { this.iconBarEnabler = iconBarEnabler; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBar.java0000644000175000017500000026543611306337762025714 0ustar adrianadrian/** * Created on Jun 23, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin.sidebar; import java.lang.reflect.Constructor; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.UIPluginView; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.menus.MenuItemListener; import org.gudy.azureus2.plugins.ui.menus.MenuManager; import org.gudy.azureus2.plugins.ui.sidebar.SideBarDropListener; import org.gudy.azureus2.plugins.ui.sidebar.SideBarEntry; import org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.common.util.MenuItemManager; import org.gudy.azureus2.ui.swt.MenuBuildUtils; import org.gudy.azureus2.ui.swt.URLTransfer; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.*; import org.gudy.azureus2.ui.swt.mainwindow.PluginsMenuHelper.IViewInfo; import org.gudy.azureus2.ui.swt.mainwindow.PluginsMenuHelper.PluginAddedViewListener; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewEventCancelledException; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT.TriggerInThread; import org.gudy.azureus2.ui.swt.views.*; import org.gudy.azureus2.ui.swt.views.stats.StatsView; import com.aelitis.azureus.activities.VuzeActivitiesEntry; import com.aelitis.azureus.activities.VuzeActivitiesListener; import com.aelitis.azureus.activities.VuzeActivitiesManager; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManager; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.table.TableView; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoListener; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.selectedcontent.SelectedContentV3; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.shells.AuthorizeWindow; import com.aelitis.azureus.ui.swt.skin.*; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter; import com.aelitis.azureus.ui.swt.toolbar.ToolBarEnabler; import com.aelitis.azureus.ui.swt.toolbar.ToolBarEnablerSelectedContent; import com.aelitis.azureus.ui.swt.toolbar.ToolBarItem; import com.aelitis.azureus.ui.swt.utils.ColorCache; import com.aelitis.azureus.ui.swt.utils.ContentNetworkUI; import com.aelitis.azureus.ui.swt.utils.ContentNetworkUI.ContentNetworkImageLoadedListener; import com.aelitis.azureus.ui.swt.views.skin.*; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.ContentNetworkUtils; import com.aelitis.azureus.util.MapUtils; /** * @author TuxPaper * @created Jun 23, 2008 * */ public class SideBar extends SkinView implements UIUpdatable, ViewTitleInfoListener { private static final boolean END_INDENT = Constants.isLinux || Constants.isWindows2000 || Constants.isWindows9598ME; private static final boolean USE_PAINTITEM = Utils.isCocoa || Constants.isWindows; // Need to use paint even on Cocoa, because there's cases where an area // will become invalidated and we don't get a paintitem :( private static final boolean USE_PAINT = !Constants.isWindows; private static final boolean HIDE_NATIVE_EXPANDER = false; private static final int SIDEBAR_SPACING = 2; public static final String SIDEBAR_SECTION_PLUGINS = "Plugins"; public static final String SIDEBAR_SECTION_LIBRARY = "Library"; public static final String SIDEBAR_SECTION_LIBRARY_DL = "LibraryDL"; public static final String SIDEBAR_SECTION_LIBRARY_CD = "LibraryCD"; public static final String SIDEBAR_SECTION_LIBRARY_UNOPENED = "LibraryUnopened"; public static final String SIDEBAR_SECTION_TOOLS = "Tools"; public static String SIDEBAR_SECTION_BROWSE = "ContentNetwork.1"; public static final String SIDEBAR_SECTION_WELCOME = "Welcome"; public static final String SIDEBAR_SECTION_SUBSCRIPTIONS = "Subscriptions"; public static final String SIDEBAR_SECTION_DEVICES = "Devices"; public static final String SIDEBAR_SECTION_RELATED_CONTENT = "RelatedContent"; public static final boolean SHOW_ALL_PLUGINS = false; public static final boolean SHOW_TOOLS = false; public static final boolean SHOW_DEVICES = true; public static final String SIDEBAR_SECTION_ACTIVITIES = "Activity"; private static final int IMAGELEFT_SIZE = 20; private static final int IMAGELEFT_GAP = 5; private static final boolean ALWAYS_IMAGE_GAP = true; private static final String[] default_indicator_colors = { "#000000", "#000000", "#166688", "#1c2056" }; private static final boolean DO_OUR_OWN_TREE_INDENT = false; private SWTSkin skin; private SWTSkinObject soSideBarContents; private SWTSkinObject soSideBarList; private Tree tree; private Font fontHeader; private Font font; private SideBarEntrySWT currentSideBarEntry; private static Map mapTitleInfoToEntry = new LightHashMap(); private static Map mapIdToEntries = new LightHashMap(); private static List listTreeItemsNoTitleInfo = new ArrayList(); private static DisposeListener disposeTreeItemListener; private CopyOnWriteList listeners = new CopyOnWriteList(); double lastPercent = 0.8; private Color bg; private Color fg; private Color bgSel; private Color fgSel; private Color colorFocus; private Image imgClose; private SWTSkinObject soSideBarPopout; private SelectionListener dropDownSelectionListener; private ImageLoader imageLoader; private int maxIndicatorWidth; private Image imgCloseSelected; private static Map mapAutoOpen = new LightHashMap(); private Image treeImage; private Image lastImage; //private Image imgUntwist; //private Image imgTwist; private Shell shellFade; private DropTarget dropTarget; protected SideBarEntrySWT draggingOver; public static SideBar instance = null; static { SIDEBAR_SECTION_BROWSE = ContentNetworkUtils.getTarget(ConstantsVuze.getDefaultContentNetwork()); disposeTreeItemListener = new DisposeListener() { public void widgetDisposed(final DisposeEvent e) { final TreeItem treeItem = (TreeItem) e.widget; final Tree tree = treeItem.getParent(); final int itemIndex = tree.indexOf(treeItem); final String id = (String) treeItem.getData("Plugin.viewID"); Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { // even though execThreadLater will not run on close off app because // the display is disposed, do a double chek of tree disposal just // in case. We don't want to trigger close listeners or // remove autoopen parameters if the user is closing the app (as // opposed to closing the sidebar) if (tree.isDisposed()) { return; } listTreeItemsNoTitleInfo.remove(treeItem); //TreeItem currentItem = treeItem.getParent().getSelection()[0]; if (id != null) { try { SideBarEntrySWT entry = getEntry(id); entry.treeItem = null; entry.triggerCloseListeners(); if (entry.iview != null) { IView iviewDelete = entry.iview; entry.iview = null; iviewDelete.delete(); } if (entry.skinObject != null) { SWTSkinObject so = entry.skinObject; entry.skinObject = null; so.getSkin().removeSkinObject(so); } COConfigurationManager.removeParameter("SideBar.AutoOpen." + id); if (Constants.isOSX && !tree.isDisposed() && tree.getSelectionCount() == 0) { if (entry.parentID != null) { entry.getSidebar().showEntryByID(entry.parentID); } else { int i = itemIndex; if (i >= tree.getItemCount() || i < 0) { i = tree.getItemCount() - 1; } TreeItem item = tree.getItem(i); entry.getSidebar().itemSelected(item); } } } catch (Exception e2) { Debug.out(e2); } mapAutoOpen.remove(id); mapIdToEntries.remove(id); return; } // find treeitem.. for (Iterator iter = mapIdToEntries.keySet().iterator(); iter.hasNext();) { String id = (String) iter.next(); SideBarEntrySWT entry = getEntry(id); if (entry != null && entry.treeItem == treeItem) { iter.remove(); } } } }); } }; } public SideBar() { if (instance == null) { instance = this; } } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#skinObjectCreated(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectCreated(SWTSkinObject skinObject, Object params) { skin = skinObject.getSkin(); soSideBarContents = skin.getSkinObject("sidebar-contents"); soSideBarList = skin.getSkinObject("sidebar-list"); soSideBarPopout = skin.getSkinObject("sidebar-pop"); imageLoader = skin.getImageLoader(skinObject.getProperties()); imgClose = imageLoader.getImage("image.sidebar.closeitem"); imgCloseSelected = imageLoader.getImage("image.sidebar.closeitem-selected"); //imgTwist = imageLoader.getImage("image.sidebar.twist"); //imgUntwist = imageLoader.getImage("image.sidebar.untwist"); // addTestMenus(); ViewTitleInfoManager.addListener(this); createSideBar(); setupDefaultItems(); try { UIFunctionsManager.getUIFunctions().getUIUpdater().addUpdater(this); } catch (Exception e) { Debug.out(e); } Display.getDefault().addFilter(SWT.KeyDown, new Listener() { public void handleEvent(Event event) { // F9 is standard Seamonkey, but doesn't work on OSX // Command Option T is standard on OSX // F7 works on both if (event.keyCode == SWT.F9 || event.keyCode == SWT.F7 || (event.keyCode == 116 && event.stateMask == (SWT.COMMAND | SWT.ALT))) { event.doit = false; event.keyCode = 0; event.character = '\0'; flipSideBarVisibility(); } } }); return null; } /** * * * @since 3.1.0.1 */ /* private void addTestMenus() { // Add some test menus PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager(); PluginInterface pi = pm.getDefaultPluginInterface(); UIManager uim = pi.getUIManager(); MenuManager menuManager = uim.getMenuManager(); MenuItem menuItem = menuManager.addMenuItem("sidebar", "test menu"); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { System.out.println("Found download Toolbar"); ToolBarItem dlItem = tb.getToolBarItem("download"); System.out.println("Download ToolBar Item is " + dlItem); if (dlItem != null) { System.out.println(dlItem.getSkinButton().getSkinObject()); } dlItem.setEnabled(!dlItem.isEnabled()); } if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; System.err.println(info.getId() + " of " + info.getParentID() + ";ds=" + info.getDatasource()); } } }); menuItem = menuManager.addMenuItem("sidebar." + SIDEBAR_SECTION_ACTIVITIES, "Activity Only Menu"); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; System.err.println(info.getId() + " of " + info.getParentID() + ";ds=" + info.getDatasource()); } } }); } */ private void addMenuNotifications() { PluginInterface pi = PluginInitializer.getDefaultInterface(); UIManager uim = pi.getUIManager(); MenuManager menuManager = uim.getMenuManager(); MenuItem menuItem = menuManager.addMenuItem("sidebar." + SIDEBAR_SECTION_ACTIVITIES, "v3.activity.button.readall"); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { VuzeActivitiesEntry[] allEntries = VuzeActivitiesManager.getAllEntries(); for (int i = 0; i < allEntries.length; i++) { VuzeActivitiesEntry entry = allEntries[i]; entry.setRead(true); } } }); } private void addMenuUnwatched() { PluginInterface pi = PluginInitializer.getDefaultInterface(); UIManager uim = pi.getUIManager(); MenuManager menuManager = uim.getMenuManager(); MenuItem menuItem = menuManager.addMenuItem("sidebar." + SIDEBAR_SECTION_LIBRARY_UNOPENED, "v3.activity.button.watchall"); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { CoreWaiterSWT.waitForCore(TriggerInThread.ANY_THREAD, new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { GlobalManager gm = core.getGlobalManager(); List downloadManagers = gm.getDownloadManagers(); for (Iterator iter = downloadManagers.iterator(); iter.hasNext();) { DownloadManager dm = (DownloadManager) iter.next(); if (!PlatformTorrentUtils.getHasBeenOpened(dm) && dm.getAssumedComplete()) { PlatformTorrentUtils.setHasBeenOpened(dm, true); } } } }); } }); } /** * * * @since 3.1.1.1 */ public void flipSideBarVisibility() { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { SWTSkinObjectSash soSash = (SWTSkinObjectSash) skin.getSkinObject("sidebar-sash"); if (soSash.getPercent() == 0) { if (lastPercent != 0) { soSash.setPercent(lastPercent); } if (soSideBarPopout != null) { Object ld = soSideBarPopout.getControl().getLayoutData(); if (ld instanceof FormData) { FormData fd = (FormData) ld; fd.width = 0; } soSideBarPopout.setVisible(false); Utils.relayout(soSideBarPopout.getControl()); } } else { // invisible lastPercent = soSash.getPercent(); soSash.setPercent(0); if (soSideBarPopout != null) { Object ld = soSideBarPopout.getControl().getLayoutData(); if (ld instanceof FormData) { FormData fd = (FormData) ld; fd.width = 24; } soSideBarPopout.setVisible(true); soSideBarPopout.getControl().moveAbove(null); Utils.relayout(soSideBarPopout.getControl()); } } } }); } public boolean isVisible() { SWTSkinObjectSash soSash = (SWTSkinObjectSash) skin.getSkinObject("sidebar-sash"); return soSash.getPercent() != 0.0; } // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#showSupport(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) { // force visible on first launch if (!isVisible()) { flipSideBarVisibility(); } return null; } public Object skinObjectDestroyed(SWTSkinObject skinObject, Object params) { try { UIFunctionsManager.getUIFunctions().getUIUpdater().removeUpdater(this); } catch (Exception e) { Debug.out(e); } imageLoader = skin.getImageLoader(skinObject.getProperties()); if (imageLoader != null) { imageLoader.releaseImage("image.sidebar.closeitem"); imageLoader.releaseImage("image.sidebar.closeitem-selected"); } return null; } private void createSideBar() { Composite parent = (Composite) soSideBarList.getControl(); // there isn't a SWT.NO_SCROLL in pre 3.4 final int NO_SCROLL = 1 << 4; tree = new Tree(parent, SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.DOUBLE_BUFFERED | NO_SCROLL); tree.setHeaderVisible(false); new SideBarToolTips(this, tree); tree.setLayoutData(Utils.getFilledFormData()); SWTSkinProperties skinProperties = skin.getSkinProperties(); bg = skinProperties.getColor("color.sidebar.bg"); fg = skinProperties.getColor("color.sidebar.fg"); bgSel = skinProperties.getColor("color.sidebar.selected.bg"); fgSel = skinProperties.getColor("color.sidebar.selected.fg"); colorFocus = skinProperties.getColor("color.sidebar.focus"); tree.setBackground(bg); tree.setForeground(fg); int fontHeight = 13 + (tree.getItemHeight() > 18 ? tree.getItemHeight() - 18 : 0); FontData[] fontData = tree.getFont().getFontData(); Utils.getFontHeightFromPX(tree.getDisplay(), fontData, null, fontHeight - 1); font = new Font(tree.getDisplay(), fontData); tree.setFont(font); //fontData[0].setHeight(fontData[0].getHeight() + 1); fontData[0].setStyle(SWT.BOLD); //fontData[0].setName("Helvetica"); Utils.getFontHeightFromPX(tree.getDisplay(), fontData, null, fontHeight); fontHeader = new Font(tree.getDisplay(), fontData); Listener treeListener = new Listener() { TreeItem lastTopItem = null; boolean mouseDowned = false; public void handleEvent(final Event event) { TreeItem treeItem = (TreeItem) event.item; switch (event.type) { case SWT.MeasureItem: { int clientWidth = tree.getClientArea().width; String text = treeItem.getText(event.index); Point size = event.gc.textExtent(text); if (event.x + event.width < clientWidth) { event.width = size.x + event.x; // tree.getClientArea().width; event.x = 0; } if (Constants.isWindows) { event.width = clientWidth - event.x; } int padding = 4; //String id = (String) treeItem.getData("Plugin.viewID"); //SideBarEntrySWT entry = getSideBarInfo(id); //if (entry.imageLeft != null) { //padding += 4; //} event.height = 24;// Math.max(event.height, size.y + padding); break; } case SWT.PaintItem: { if (USE_PAINTITEM) { String id = (String) ((TreeItem) event.item).getData("Plugin.viewID"); //System.out.println("PaintItem: " + event.item + ";" + event.index + ";" + event.detail + ";" + id + ";" + event.getBounds() + ";" + event.gc.getClipping()); SideBarEntrySWT entry = getEntry(id); paintSideBar(event, entry); } break; } case SWT.Paint: { if (HIDE_NATIVE_EXPANDER) { boolean selected = (event.detail & SWT.SELECTED) > 0; Rectangle bounds = event.getBounds(); int indent = END_INDENT ? tree.getClientArea().width - 1 : 0; int y = event.y + 1; treeItem = tree.getItem(new Point(indent, y)); while (treeItem != null) { String id = (String) treeItem.getData("Plugin.viewID"); SideBarEntrySWT entry = getEntry(id); Rectangle itemBounds = entry.getBounds(); if (itemBounds != null && entry.disableCollapse) { Rectangle paintArea = treeItem.getBounds(); paintArea.x = 0; paintArea.width = 17; selected = tree.getSelectionCount() == 1 && tree.getSelection()[0].equals(treeItem); paintEntryBG(selected, event.gc, paintArea, entry); y = itemBounds.y + itemBounds.height + 1; } else { y += tree.getItemHeight(); } if (y > bounds.y + bounds.height) { break; } treeItem = tree.getItem(new Point(indent, y)); } } //System.out.println("Paint: " + event.getBounds() + ";" + event.detail + ";" + event.index + ";" + event.gc.getClipping() + " " + Debug.getCompressedStackTrace()); if (!USE_PAINT) { return; } Rectangle bounds = event.getBounds(); int indent = END_INDENT ? tree.getClientArea().width - 1 : 0; int y = event.y + 1; treeItem = tree.getItem(new Point(indent, y)); while (treeItem != null) { String id = (String) treeItem.getData("Plugin.viewID"); SideBarEntrySWT entry = getEntry(id); Rectangle itemBounds = entry.getBounds(); // null itemBounds is weird, the entry must be disposed. it // happened once, so let's check.. if (itemBounds != null) { event.item = treeItem; boolean selected = tree.getSelectionCount() == 1 && tree.getSelection()[0].equals(treeItem); event.detail = selected ? SWT.SELECTED : SWT.NONE; Rectangle newClip = bounds.intersection(itemBounds); //System.out.println("Paint " + id + " @ " + newClip); event.setBounds(newClip); event.gc.setClipping(newClip); paintSideBar(event, entry); y = itemBounds.y + itemBounds.height + 1; } else { y += tree.getItemHeight(); } if (y > bounds.y + bounds.height) { break; } treeItem = tree.getItem(new Point(indent, y)); } if (tree.getTopItem() != lastTopItem) { lastTopItem = tree.getTopItem(); SideBarEntrySWT[] sideBarEntries = (SideBarEntrySWT[]) mapIdToEntries.values().toArray( new SideBarEntrySWT[0]); updateSideBarHitAreasY(sideBarEntries); } break; } case SWT.EraseItem: { //event.detail &= ~SWT.FOREGROUND; //event.detail &= ~(SWT.FOREGROUND | SWT.BACKGROUND); event.doit = true; break; } case SWT.Resize: { tree.redraw(); break; } case SWT.Selection: { itemSelected(treeItem); break; } case SWT.MouseDown: { mouseDowned = true; } case SWT.MouseUp: { if (!mouseDowned) { return; } mouseDowned = false; if (tree.getItemCount() == 0 || event.button != 1) { return; } int indent = END_INDENT ? tree.getClientArea().width - 1 : 0; treeItem = tree.getItem(new Point(indent, event.y)); if (treeItem == null) { return; } String id = (String) treeItem.getData("Plugin.viewID"); SideBarEntrySWT entry = getEntry(id); Rectangle closeArea = (Rectangle) treeItem.getData("closeArea"); if (closeArea != null && closeArea.contains(event.x, event.y)) { treeItem.dispose(); } else if (currentSideBarEntry != entry && Constants.isOSX) { itemSelected(entry.treeItem); } SideBarVitalityImage[] vitalityImages = entry.getVitalityImages(); for (int i = 0; i < vitalityImages.length; i++) { SideBarVitalityImageSWT vitalityImage = (SideBarVitalityImageSWT) vitalityImages[i]; if (!vitalityImage.isVisible()) { continue; } Rectangle hitArea = vitalityImage.getHitArea(); if (hitArea == null) { continue; } if (hitArea.contains(event.x, event.y)) { vitalityImage.triggerClickedListeners(event.x, event.y); break; } } break; } case SWT.Dispose: { fontHeader.dispose(); font.dispose(); if (dropTarget != null && !dropTarget.isDisposed()) { dropTarget.dispose(); } saveCloseables(); break; } case SWT.Collapse: { String id = (String) treeItem.getData("Plugin.viewID"); SideBarEntrySWT entry = getEntry(id); if (entry.disableCollapse) { tree.setRedraw(false); Display.getDefault().asyncExec(new Runnable() { public void run() { ((TreeItem) event.item).setExpanded(true); tree.setRedraw(true); } }); } break; } } } }; tree.addListener(SWT.MeasureItem, treeListener); tree.addListener(SWT.Resize, treeListener); tree.addListener(SWT.Paint, treeListener); if (USE_PAINTITEM) { tree.addListener(SWT.PaintItem, treeListener); tree.addListener(SWT.EraseItem, treeListener); } tree.addListener(SWT.Selection, treeListener); tree.addListener(SWT.Dispose, treeListener); // For icons tree.addListener(SWT.MouseUp, treeListener); tree.addListener(SWT.MouseDown, treeListener); // to disable collapsing tree.addListener(SWT.Collapse, treeListener); dropTarget = new DropTarget(tree, DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_TARGET_MOVE); dropTarget.setTransfer(new Transfer[] { URLTransfer.getInstance(), FileTransfer.getInstance(), TextTransfer.getInstance(), }); dropTarget.addDropListener(new DropTargetAdapter() { public void dropAccept(DropTargetEvent event) { event.currentDataType = URLTransfer.pickBestType(event.dataTypes, event.currentDataType); } // @see org.eclipse.swt.dnd.DropTargetAdapter#dragOver(org.eclipse.swt.dnd.DropTargetEvent) public void dragOver(DropTargetEvent event) { TreeItem treeItem = (event.item instanceof TreeItem) ? (TreeItem) event.item : null; if (treeItem != null) { String id = (String) treeItem.getData("Plugin.viewID"); SideBarEntrySWT entry = getEntry(id); draggingOver = entry; } else { draggingOver = null; } if (Constants.isOSX) { tree.redraw(); } if ((event.operations & DND.DROP_LINK) > 0) event.detail = DND.DROP_LINK; else if ((event.operations & DND.DROP_DEFAULT) > 0) event.detail = DND.DROP_DEFAULT; else if ((event.operations & DND.DROP_COPY) > 0) event.detail = DND.DROP_COPY; } // @see org.eclipse.swt.dnd.DropTargetAdapter#dragLeave(org.eclipse.swt.dnd.DropTargetEvent) public void dragLeave(DropTargetEvent event) { draggingOver = null; tree.redraw(); } public void drop(DropTargetEvent event) { draggingOver = null; tree.redraw(); if (!(event.item instanceof TreeItem)) { defaultDrop(event); return; } TreeItem treeItem = (TreeItem) event.item; String id = (String) treeItem.getData("Plugin.viewID"); SideBarEntrySWT entry = getEntry(id); boolean handled = entry.triggerDropListeners(event.data); if (!handled) { defaultDrop(event); } } }); final Menu menuTree = new Menu(tree); tree.setMenu(menuTree); menuTree.addMenuListener(new MenuListener() { boolean bShown = false; public void menuHidden(MenuEvent e) { bShown = false; if (Constants.isOSX) { return; } // Must dispose in an asyncExec, otherwise SWT.Selection doesn't // get fired (async workaround provided by Eclipse Bug #87678) Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { if (bShown || menuTree.isDisposed()) { return; } Utils.disposeSWTObjects(menuTree.getItems()); } }); } public void menuShown(MenuEvent e) { Utils.disposeSWTObjects(menuTree.getItems()); bShown = true; Point ptMouse = tree.toControl(e.display.getCursorLocation()); int indent = END_INDENT ? tree.getClientArea().width - 1 : 0; TreeItem treeItem = tree.getItem(new Point(indent, ptMouse.y)); if (treeItem == null) { return; } String id = (String) treeItem.getData("Plugin.viewID"); SideBarEntrySWT entry = getEntry(id); fillMenu(menuTree, entry); if (menuTree.getItemCount() == 0) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { menuTree.setVisible(false); } }); } } }); if (soSideBarPopout != null) { SWTSkinObject soDropDown = skin.getSkinObject("sidebar-dropdown"); if (soDropDown != null) { final Menu menuDropDown = new Menu(soDropDown.getControl()); menuDropDown.addMenuListener(new MenuListener() { boolean bShown = false; public void menuHidden(MenuEvent e) { bShown = false; if (Constants.isOSX) { return; } // Must dispose in an asyncExec, otherwise SWT.Selection doesn't // get fired (async workaround provided by Eclipse Bug #87678) Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { if (bShown || menuDropDown.isDisposed()) { return; } Utils.disposeSWTObjects(menuDropDown.getItems()); } }); } public void menuShown(MenuEvent e) { Utils.disposeSWTObjects(menuDropDown.getItems()); bShown = true; fillDropDownMenu(menuDropDown, tree.getItems(), 0); } }); dropDownSelectionListener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { String id = (String) e.widget.getData("Plugin.viewID"); showEntryByID(id); } public void widgetDefaultSelected(SelectionEvent e) { } }; SWTSkinButtonUtility btnDropDown = new SWTSkinButtonUtility(soDropDown); btnDropDown.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { Control c = buttonUtility.getSkinObject().getControl(); menuDropDown.setLocation(c.getDisplay().getCursorLocation()); menuDropDown.setVisible(!menuDropDown.getVisible()); } }); } SWTSkinObject soExpand = skin.getSkinObject("sidebar-expand"); if (soExpand != null) { SWTSkinButtonUtility btnExpand = new SWTSkinButtonUtility(soExpand); btnExpand.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { flipSideBarVisibility(); } }); } } } /** * @param event */ protected void defaultDrop(DropTargetEvent event) { TorrentOpener.openDroppedTorrents(event, false); } /** * @param menuDropDown * * @since 3.1.1.1 */ protected void fillDropDownMenu(Menu menuDropDown, TreeItem[] items, int indent) { String s = ""; for (int i = 0; i < indent; i++) { s += " "; } for (int i = 0; i < items.length; i++) { TreeItem treeItem = items[i]; org.eclipse.swt.widgets.MenuItem menuItem = new org.eclipse.swt.widgets.MenuItem( menuDropDown, SWT.RADIO); String id = (String) treeItem.getData("Plugin.viewID"); menuItem.setData("Plugin.viewID", id); SideBarEntrySWT entry = getEntry(id); ViewTitleInfo titleInfo = entry.getTitleInfo(); String ind = ""; if (titleInfo != null) { String o = (String) titleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_INDICATOR_TEXT); if (o != null) { ind = " (" + o + ")"; //ind = "\t" + o; } } menuItem.setText(s + treeItem.getData("text") + ind); menuItem.addSelectionListener(dropDownSelectionListener); if (currentSideBarEntry != null && currentSideBarEntry.id.equals(id)) { menuItem.setSelection(true); } TreeItem[] subItems = treeItem.getItems(); if (subItems.length > 0) { fillDropDownMenu(menuDropDown, subItems, ++indent); } } } /** * @param menuTree * * @since 3.1.0.1 */ protected void fillMenu(Menu menuTree, final SideBarEntry entry) { org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items; menu_items = MenuItemManager.getInstance().getAllAsArray("sidebar"); MenuBuildUtils.addPluginMenuItems((Composite) soMain.getControl(), menu_items, menuTree, false, true, new MenuBuildUtils.MenuItemPluginMenuControllerImpl(new Object[] { entry })); if (entry != null) { menu_items = MenuItemManager.getInstance().getAllAsArray( "sidebar." + entry.getId()); MenuBuildUtils.addPluginMenuItems((Composite) soMain.getControl(), menu_items, menuTree, false, true, new MenuBuildUtils.MenuItemPluginMenuControllerImpl(new Object[] { entry })); if (currentSideBarEntry != null && currentSideBarEntry.datasource instanceof DownloadManager) { DownloadManager[] downloads = new DownloadManager[] { (DownloadManager) currentSideBarEntry.datasource }; org.eclipse.swt.widgets.MenuItem mi = MenuFactory.createTorrentMenuItem(menuTree); mi.setData("downloads", downloads); mi.setData("is_detailed_view", new Boolean(true)); } } } private Color paintEntryBG(boolean selected, GC gc, Rectangle drawBounds, SideBarEntrySWT sideBarEntry) { Color fgText = Colors.black; if (selected) { //System.out.println("gmmm" + drawBounds + ": " + Debug.getCompressedStackTrace()); gc.setClipping((Rectangle)null); if (fgSel != null) { fgText = fgSel; } if (bgSel != null) { gc.setBackground(bgSel); } Color color1; Color color2; if (tree.isFocusControl()) { color1 = ColorCache.getColor(gc.getDevice(), "#166688"); color2 = ColorCache.getColor(gc.getDevice(), "#1c2458"); } else { color1 = ColorCache.getColor(gc.getDevice(), "#447281"); color2 = ColorCache.getColor(gc.getDevice(), "#393e58"); } gc.setBackground(color1); gc.fillRectangle(drawBounds.x, drawBounds.y, drawBounds.width, 3); gc.setForeground(color1); gc.setBackground(color2); //System.out.println("FOO"); //gc.fillGradientRectangle(itemBounds.x, itemBounds.y, itemBounds.width, itemBounds.height, true); gc.fillGradientRectangle(drawBounds.x, drawBounds.y + 3, drawBounds.width, drawBounds.height - 3, true); } else { if (fg != null) { fgText = fg; } if (bg != null) { gc.setBackground(bg); } if (sideBarEntry == draggingOver) { gc.setBackground(ColorCache.getColor(gc.getDevice(), "#2688aa")); } gc.fillRectangle(drawBounds); } return fgText; } /** * @param event * @param sideBarEntry * * @since 3.1.0.1 */ protected void paintSideBar(Event event, SideBarEntrySWT sideBarEntry) { TreeItem treeItem = (TreeItem) event.item; Rectangle itemBounds = treeItem.getBounds(); Rectangle drawBounds = Utils.isCocoa || Constants.isWindows ? event.gc.getClipping() : event.getBounds(); if (drawBounds.isEmpty()) { return; } String text = (String) treeItem.getData("text"); if (text == null) text = ""; //Point size = event.gc.textExtent(text); //Rectangle treeBounds = tree.getBounds(); GC gc = event.gc; gc.setAntialias(SWT.ON); gc.setAdvanced(true); //gc.setClipping((Rectangle) null); boolean selected = (event.detail & SWT.SELECTED) > 0; Color fgText = paintEntryBG(selected, gc, drawBounds, sideBarEntry); Rectangle treeArea = tree.getClientArea(); gc.setFont(tree.getFont()); if (sideBarEntry == null) { String id = (String) treeItem.getData("Plugin.viewID"); sideBarEntry = getEntry(id); } if (DO_OUR_OWN_TREE_INDENT) { int indentLevel = 0; TreeItem tempItem = treeItem; while (tempItem != null) { tempItem = tempItem.getParentItem(); indentLevel++; } itemBounds.x += (18 * indentLevel); } int x1IndicatorOfs = SIDEBAR_SPACING; int x0IndicatorOfs = itemBounds.x; //System.out.println(System.currentTimeMillis() + "] refresh " + sideBarEntry.getId() + "; " + itemBounds + ";clip=" + event.gc.getClipping() + ";eb=" + event.getBounds()); if (sideBarEntry.titleInfo != null) { String textIndicator = (String) sideBarEntry.titleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_INDICATOR_TEXT); if (textIndicator != null) { Point textSize = gc.textExtent(textIndicator); Point minTextSize = gc.textExtent("99"); if (textSize.x < minTextSize.x + 2) { textSize.x = minTextSize.x + 2; } int width = textSize.x + textSize.y / 2 + 2; x1IndicatorOfs += width + SIDEBAR_SPACING; int startX = treeArea.width - x1IndicatorOfs; int textOffsetY = 0; int height = textSize.y + 3; int startY = itemBounds.y + (itemBounds.height - height) / 2; //gc.fillRectangle(startX, startY, width, height); Pattern pattern; Color color1; Color color2; String[] colors = (String[]) sideBarEntry.titleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_INDICATOR_COLOR); if (colors == null || colors.length != 4) { colors = default_indicator_colors; } if (selected) { color1 = ColorCache.getColor(gc.getDevice(), colors[0]); color2 = ColorCache.getColor(gc.getDevice(), colors[1]); pattern = new Pattern(gc.getDevice(), 0, startY, 0, startY + height, color1, 127, color2, 4); } else { color1 = ColorCache.getColor(gc.getDevice(), colors[2]); color2 = ColorCache.getColor(gc.getDevice(), colors[3]); pattern = new Pattern(gc.getDevice(), 0, startY, 0, startY + height, color1, color2); } gc.setBackgroundPattern(pattern); gc.fillRoundRectangle(startX, startY, width, height, textSize.y + 1, height); gc.setBackgroundPattern(null); pattern.dispose(); if (maxIndicatorWidth > width) { maxIndicatorWidth = width; } gc.setForeground(Colors.white); GCStringPrinter.printString(gc, textIndicator, new Rectangle(startX, startY + textOffsetY, width, height), true, false, SWT.CENTER); } } //if (x1IndicatorOfs < 30) { // x1IndicatorOfs = 30; //} if (sideBarEntry.closeable) { Image img = selected ? imgCloseSelected : imgClose; Rectangle closeArea = img.getBounds(); closeArea.x = treeArea.width - closeArea.width - SIDEBAR_SPACING - x1IndicatorOfs; closeArea.y = itemBounds.y + (itemBounds.height - closeArea.height) / 2; x1IndicatorOfs += closeArea.width + SIDEBAR_SPACING; //gc.setBackground(treeItem.getBackground()); //gc.fillRectangle(closeArea); gc.drawImage(img, closeArea.x, closeArea.y); treeItem.setData("closeArea", closeArea); } SideBarVitalityImage[] vitalityImages = sideBarEntry.getVitalityImages(); for (int i = 0; i < vitalityImages.length; i++) { SideBarVitalityImageSWT vitalityImage = (SideBarVitalityImageSWT) vitalityImages[i]; if (!vitalityImage.isVisible() || vitalityImage.getAlignment() != SWT.RIGHT) { continue; } vitalityImage.switchSuffix(selected ? "-selected" : ""); Image image = vitalityImage.getImage(); if (image != null && !image.isDisposed()) { Rectangle bounds = image.getBounds(); bounds.x = treeArea.width - bounds.width - SIDEBAR_SPACING - x1IndicatorOfs; bounds.y = itemBounds.y + (itemBounds.height - bounds.height) / 2; x1IndicatorOfs += bounds.width + SIDEBAR_SPACING; gc.drawImage(image, bounds.x, bounds.y); vitalityImage.setHitArea(bounds); } } boolean greyScale = false; if ( sideBarEntry.titleInfo != null ){ Object active_state = sideBarEntry.titleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_ACTIVE_STATE); if ( active_state instanceof Long ){ greyScale = (Long)active_state == 2; } } String suffix = selected ? "-selected" : null; Image imageLeft = sideBarEntry.getImageLeft(suffix); if (imageLeft == null && selected) { sideBarEntry.releaseImageLeft(suffix); suffix = null; imageLeft = sideBarEntry.getImageLeft(null); } if (imageLeft != null) { Rectangle bounds = imageLeft.getBounds(); int x = x0IndicatorOfs + ((IMAGELEFT_SIZE - bounds.width) / 2); int y = itemBounds.y + ((itemBounds.height - bounds.height) / 2); Rectangle clipping = gc.getClipping(); gc.setClipping(x0IndicatorOfs, itemBounds.y, IMAGELEFT_SIZE, itemBounds.height); boolean drawn = false; if ( greyScale ){ String imageLeftID = sideBarEntry.getImageLeftID(); if ( imageLeftID != null ){ Image grey = ImageLoader.getInstance().getImage(imageLeftID + "-gray" ); if ( grey != null ){ gc.drawImage( grey, x, y); ImageLoader.getInstance().releaseImage(imageLeftID + "-gray" ); drawn = true; } } } if ( !drawn ){ gc.drawImage(imageLeft, x, y); } sideBarEntry.releaseImageLeft(suffix); gc.setClipping(clipping); // 0, 0, bounds.width, bounds.height, // x0IndicatorOfs, itemBounds.y // + ((itemBounds.height - IMAGELEFT_SIZE) / 2), IMAGELEFT_SIZE, // IMAGELEFT_SIZE); x0IndicatorOfs += IMAGELEFT_SIZE + IMAGELEFT_GAP; } else if (ALWAYS_IMAGE_GAP) { x0IndicatorOfs += IMAGELEFT_SIZE + IMAGELEFT_GAP; } else { if (treeItem.getParentItem() != null) { x0IndicatorOfs += 30 - 18; } } // gc.setAdvanced(true); // gc.setTextAntialias(SWT.ON); // gc.setAntialias(SWT.ON); // gc.setInterpolation(SWT.HIGH); if (treeItem.getParentItem() == null) { gc.setFont(fontHeader); gc.setForeground(ColorCache.getColor(gc.getDevice(), "#2B2D32")); } gc.setForeground(fgText); Rectangle clipping = new Rectangle(x0IndicatorOfs, itemBounds.y, treeArea.width - x1IndicatorOfs - SIDEBAR_SPACING - x0IndicatorOfs, itemBounds.height); //System.out.println("itemBounds=" + itemBounds + ";event=" + event.getBounds() + ";" + event.gc.getClipping() + ";" + text); if (drawBounds.intersects(clipping)) { //gc.setClipping(clipping); if (text.startsWith(" ")) { text = text.substring(1); clipping.x += 30; clipping.width -= 30; } //System.out.println("draw at " + clipping + " " + text); GCStringPrinter sp = new GCStringPrinter(gc, text, clipping, true, false, SWT.NONE); sp.printString(); clipping.x += sp.getCalculatedSize().x + 5; //gc.setClipping((Rectangle) null); } for (int i = 0; i < vitalityImages.length; i++) { SideBarVitalityImageSWT vitalityImage = (SideBarVitalityImageSWT) vitalityImages[i]; if (!vitalityImage.isVisible() || vitalityImage.getAlignment() != SWT.LEFT) { continue; } vitalityImage.switchSuffix(selected ? "-selected" : ""); Image image = vitalityImage.getImage(); if (image != null && !image.isDisposed()) { Rectangle bounds = image.getBounds(); bounds.x = clipping.x; bounds.y = itemBounds.y + (itemBounds.height - bounds.height) / 2; clipping.x += bounds.width + SIDEBAR_SPACING; if (clipping.x > (treeArea.width - x1IndicatorOfs)) { vitalityImage.setHitArea(null); continue; } gc.drawImage(image, bounds.x, bounds.y); vitalityImage.setHitArea(bounds); } } // OSX overrides the twisty, and we can't use the default twisty // on Windows because it doesn't have transparency and looks ugly if (treeItem.getItemCount() > 0 && !sideBarEntry.disableCollapse && (!Utils.isCocoa || !HIDE_NATIVE_EXPANDER)) { gc.setAntialias(SWT.ON); Color oldBG = gc.getBackground(); gc.setBackground(gc.getForeground()); if (treeItem.getExpanded()) { int xStart = 15; if (Utils.isCocoa) { xStart -= 5; } int arrowSize = 8; int yStart = itemBounds.height - (itemBounds.height + arrowSize) / 2; gc.fillPolygon(new int[] { itemBounds.x - xStart, itemBounds.y + yStart, itemBounds.x - xStart + arrowSize, itemBounds.y + yStart, itemBounds.x - xStart + (arrowSize / 2), itemBounds.y + 16, }); } else { int xStart = 15; if (Utils.isCocoa) { xStart -= 5; } int arrowSize = 8; int yStart = itemBounds.height - (itemBounds.height + arrowSize) / 2; gc.fillPolygon(new int[] { itemBounds.x - xStart, itemBounds.y + yStart, itemBounds.x - xStart + arrowSize, itemBounds.y + yStart + 4, itemBounds.x - xStart, itemBounds.y + yStart + 8, }); } gc.setBackground(oldBG); gc.setFont(fontHeader); } } /** * * * @since 3.1.1.1 */ private void updateSideBarHitAreasY(SideBarEntrySWT[] entries) { for (int x = 0; x < entries.length; x++) { SideBarEntrySWT entry = entries[x]; TreeItem treeItem = entry.treeItem; if (treeItem == null || treeItem.isDisposed()) { continue; } Rectangle itemBounds = entry.getBounds(); if (entry.closeable) { Rectangle closeArea = (Rectangle) treeItem.getData("closeArea"); if (closeArea != null) { closeArea.y = itemBounds.y + (itemBounds.height - closeArea.height) / 2; } } SideBarVitalityImage[] vitalityImages = entry.getVitalityImages(); for (int i = 0; i < vitalityImages.length; i++) { SideBarVitalityImageSWT vitalityImage = (SideBarVitalityImageSWT) vitalityImages[i]; if (!vitalityImage.isVisible()) { continue; } Image image = vitalityImage.getImage(); if (image != null) { Rectangle bounds = vitalityImage.getHitArea(); if (bounds == null) { continue; } bounds.y = itemBounds.y + (itemBounds.height - bounds.height) / 2; } } } } /** * * * @since 3.1.1.1 */ private void setupDefaultItems() { TreeItem treeItem; // Put TitleInfo in another class final ViewTitleInfo titleInfoActivityView = new ViewTitleInfo() { public Object getTitleInfoProperty(int propertyID) { if (propertyID == TITLE_INDICATOR_TEXT) { int count = 0; VuzeActivitiesEntry[] allEntries = VuzeActivitiesManager.getAllEntries(); for (int i = 0; i < allEntries.length; i++) { VuzeActivitiesEntry entry = allEntries[i]; if (!entry.isRead()) { count++; } } if (count > 0) { return "" + count; } else { return null; } } else if (propertyID == TITLE_IMAGEID) { return "image.sidebar.activity"; } return null; } }; VuzeActivitiesManager.addListener(new VuzeActivitiesListener() { public void vuzeNewsEntryChanged(VuzeActivitiesEntry entry) { } public void vuzeNewsEntriesRemoved(VuzeActivitiesEntry[] entries) { ViewTitleInfoManager.refreshTitleInfo(titleInfoActivityView); } public void vuzeNewsEntriesAdded(VuzeActivitiesEntry[] entries) { ViewTitleInfoManager.refreshTitleInfo(titleInfoActivityView); } }); SideBarEntrySWT entry; ImageLoader imageLoader = ImageLoader.getInstance(); entry = createEntryFromSkinRef(null, SIDEBAR_SECTION_LIBRARY, "library", MessageText.getString("sidebar." + SIDEBAR_SECTION_LIBRARY), null, null, false, -1); entry.setImageLeftID("image.sidebar.library"); entry.disableCollapse = true; createEntryFromSkinRef(SIDEBAR_SECTION_LIBRARY, SIDEBAR_SECTION_LIBRARY_DL, "library", MessageText.getString("sidebar.LibraryDL"), null, null, false, -1); createEntryFromSkinRef(SIDEBAR_SECTION_LIBRARY, SIDEBAR_SECTION_LIBRARY_UNOPENED, "library", MessageText.getString("sidebar.LibraryUnopened"), null, null, false, -1); addMenuUnwatched(); entry = createEntryFromSkinRef(null, SIDEBAR_SECTION_BROWSE, "main.area.browsetab", MessageText.getString("sidebar.VuzeHDNetwork"), null, null, false, -1); entry.setImageLeftID("image.sidebar.vuze"); ContentNetworkManager cnm = ContentNetworkManagerFactory.getSingleton(); if (cnm != null) { ContentNetwork[] contentNetworks = cnm.getContentNetworks(); for (ContentNetwork cn : contentNetworks) { if (cn == null) { continue; } if (cn.getID() == ConstantsVuze.getDefaultContentNetwork().getID()) { cn.setPersistentProperty(ContentNetwork.PP_ACTIVE, Boolean.TRUE); continue; } Object oIsActive = cn.getPersistentProperty(ContentNetwork.PP_ACTIVE); boolean isActive = (oIsActive instanceof Boolean) ? ((Boolean) oIsActive).booleanValue() : false; if (isActive) { createContentNetworkSideBarEntry(cn); } } } SideBarEntrySWT entryActivity = createEntryFromSkinRef(null, SIDEBAR_SECTION_ACTIVITIES, "activity", MessageText.getString("sidebar." + SIDEBAR_SECTION_ACTIVITIES), titleInfoActivityView, null, false, -1); addMenuNotifications(); //entry.setImageLeftID("image.sidebar.subscriptions"); //new TreeItem(tree, SWT.NONE).setText("Search"); if (SHOW_TOOLS) { createEntryFromSkinRef(null, SIDEBAR_SECTION_TOOLS, "main.area.hood", "Under The Hood", null, null, false, -1); createTreeItemFromIViewClass(SIDEBAR_SECTION_TOOLS, PeerSuperView.class.getSimpleName(), "All Peers", PeerSuperView.class, true); createTreeItemFromIViewClass(SIDEBAR_SECTION_TOOLS, StatsView.class.getSimpleName(), "Stats", StatsView.class, true); createTreeItemFromIViewClass(SIDEBAR_SECTION_TOOLS, MyTrackerView.class.getSimpleName(), "My Tracker", MyTrackerView.class, true); createTreeItemFromIViewClass(SIDEBAR_SECTION_TOOLS, MySharesView.class.getSimpleName(), "My Classic-Shares", MySharesView.class, true); createTreeItemFromIViewClass(SIDEBAR_SECTION_TOOLS, LoggerView.class.getSimpleName(), "Logger", LoggerView.class, true); createTreeItemFromIViewClass(SIDEBAR_SECTION_TOOLS, ConfigView.class.getSimpleName(), "Config", ConfigView.class, true); } if (SHOW_ALL_PLUGINS) { SideBarEntrySWT pluginsEntry = createEntryFromSkinRef(null, SIDEBAR_SECTION_PLUGINS, "main.area.plugins", "Plugins", null, null, false, -1); IViewInfo[] pluginViewsInfo = PluginsMenuHelper.getInstance().getPluginViewsInfo(); for (int i = 0; i < pluginViewsInfo.length; i++) { IViewInfo viewInfo = pluginViewsInfo[i]; treeItem = new TreeItem(pluginsEntry.treeItem, SWT.NONE); treeItem.addDisposeListener(disposeTreeItemListener); treeItem.setData("text", viewInfo.name); treeItem.setData("Plugin.viewID", viewInfo.viewID); SideBarEntrySWT entryPlugin = getEntry(viewInfo.viewID); entryPlugin.treeItem = treeItem; entryPlugin.iview = viewInfo.view; entryPlugin.eventListener = viewInfo.event_listener; } TreeItem itemPluginLogs = new TreeItem(pluginsEntry.treeItem, SWT.NONE); itemPluginLogs.setText("Log Views"); IViewInfo[] pluginLogViewsInfo = PluginsMenuHelper.getInstance().getPluginLogViewsInfo(); for (int i = 0; i < pluginLogViewsInfo.length; i++) { IViewInfo viewInfo = pluginLogViewsInfo[i]; treeItem = new TreeItem(itemPluginLogs, SWT.NONE); treeItem.addDisposeListener(disposeTreeItemListener); treeItem.setData("text", viewInfo.name); treeItem.setData("Plugin.viewID", viewInfo.viewID); SideBarEntrySWT entryPlugin = getEntry(viewInfo.viewID); entryPlugin.treeItem = treeItem; entryPlugin.iview = viewInfo.view; entryPlugin.eventListener = viewInfo.event_listener; } } SBC_LibraryView.setupViewTitle(); // building plugin views needs UISWTInstance, which needs core. AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener(){ public void azureusCoreRunning(AzureusCore core) { Utils.execSWTThread(new AERunnable(){ public void runSupport() { setupPluginViews(); } }); } }); loadCloseables(); Composite parent = tree.getParent(); if (parent.isVisible()) { parent.layout(true, true); } } protected void setupPluginViews() { UISWTInstanceImpl uiSWTInstance = (UISWTInstanceImpl) UIFunctionsManagerSWT.getUIFunctionsSWT().getUISWTInstance(); if (uiSWTInstance != null) { Map allViews = uiSWTInstance.getAllViews(); Object[] parentIDs = allViews.keySet().toArray(); for (int i = 0; i < parentIDs.length; i++) { String parentID = (String) parentIDs[i]; Map mapSubViews = (Map) allViews.get(parentID); if (mapSubViews != null) { Object[] viewIDs = mapSubViews.keySet().toArray(); for (int j = 0; j < viewIDs.length; j++) { String viewID = (String) viewIDs[j]; UISWTViewEventListener l = (UISWTViewEventListener) mapSubViews.get(viewID); if (l != null) { // TODO: Datasource // TODO: Multiple open boolean open = COConfigurationManager.getBooleanParameter( "SideBar.AutoOpen." + viewID, false); if (open) { createTreeItemFromEventListener(parentID, null, l, viewID, true, null); } } } } } } PluginsMenuHelper.getInstance().addPluginAddedViewListener( new PluginAddedViewListener() { // @see org.gudy.azureus2.ui.swt.mainwindow.PluginsMenuHelper.PluginAddedViewListener#pluginViewAdded(org.gudy.azureus2.ui.swt.mainwindow.PluginsMenuHelper.IViewInfo) public void pluginViewAdded(IViewInfo viewInfo) { //System.out.println("PluginView Added: " + viewInfo.viewID); Object o = mapAutoOpen.get(viewInfo.viewID); if (o instanceof Map) { processAutoOpenMap(viewInfo.viewID, (Map) o, viewInfo); } } }); } /** * @param entry * * @since 4.1.0.3 */ private void addDropTest(SideBarEntrySWT entry) { if (!Constants.isCVSVersion()) { return; } entry.addListener(new SideBarDropListener() { public boolean sideBarEntryDrop(SideBarEntry entry, Object droppedObject) { String s = "You just dropped " + droppedObject.getClass() + "\n" + droppedObject + "\n\n"; if (droppedObject.getClass().isArray()) { Object[] o = (Object[]) droppedObject; for (int i = 0; i < o.length; i++) { s += "" + i + ": "; Object object = o[i]; if (object == null) { s += "null"; } else { s += object.getClass() + ";" + object; } s += "\n"; } } new MessageBoxShell(SWT.OK, "test", s).open(null); return true; } }); } /** * * * @return * @since 3.1.1.1 */ private SideBarEntrySWT createWelcomeSection() { SideBarEntrySWT entry = createEntryFromSkinRef(null, SIDEBAR_SECTION_WELCOME, "main.area.welcome", MessageText.getString( "v3.MainWindow.menu.getting_started").replaceAll("&", ""), null, null, true, 0); entry.setImageLeftID("image.sidebar.welcome"); addDropTest(entry); return entry; } public TreeItem createTreeItemFromIView(String parentID, IView iview, String id, Object datasource, boolean closeable, boolean show) { return (createTreeItemFromIView(parentID, iview, id, datasource, closeable, show, true)); } public TreeItem createTreeItemFromIView(String parentID, IView iview, String id, Object datasource, boolean closeable, boolean show, boolean expand) { if (id == null) { id = iview.getClass().getName(); int i = id.lastIndexOf('.'); if (i > 0) { id = id.substring(i + 1); } } TreeItem treeItem = null; SideBarEntrySWT entry = getEntry(id); if (entry.treeItem != null) { treeItem = entry.treeItem; } else { SideBarEntrySWT sideBarInfoParent = getEntry(parentID); TreeItem parentTreeItem = sideBarInfoParent.treeItem; treeItem = createTreeItem(parentTreeItem, id, datasource, null, iview.getFullTitle(), closeable, -1); setupTreeItem(null, treeItem, id, null, iview.getFullTitle(), null, datasource, closeable, expand); entry.parentID = parentID; createSideBarContentArea(id, iview, treeItem, datasource, closeable, expand); iview.dataSourceChanged(datasource); } if (show) { showTreeItem(treeItem); } return treeItem; } public void showTreeItem(TreeItem treeItem) { if (treeItem != null) { treeItem.getParent().select(treeItem); treeItem.getParent().showItem(treeItem); itemSelected(treeItem); } } public TreeItem createTreeItemFromIViewClass(String parent, String id, String title, Class iviewClass, boolean closeable) { return createTreeItemFromIViewClass(parent, id, title, iviewClass, null, null, null, null, closeable); } public TreeItem createTreeItemFromIViewClass(String parent, String id, String title, Class iviewClass, Class[] iviewClassArgs, Object[] iviewClassVals, Object datasource, ViewTitleInfo titleInfo, boolean closeable) { SideBarEntrySWT entry = getEntry(id); if (entry.treeItem != null) { return entry.treeItem; } TreeItem parentItem = parent == null ? null : getEntry(parent).treeItem; TreeItem treeItem; if (parentItem != null) { treeItem = new TreeItem(parentItem, SWT.NONE); } else { treeItem = new TreeItem(tree, SWT.NONE); } entry.iviewClass = iviewClass; entry.iviewClassArgs = iviewClassArgs; entry.iviewClassVals = iviewClassVals; entry.closeable = closeable; entry.parentID = parent; setupTreeItem(null, treeItem, id, titleInfo, title, null, datasource, closeable, false ); return treeItem; } private TreeItem createTreeItem(Object parentTreeItem, String id, Object datasource, ViewTitleInfo titleInfo, String title, boolean closeable, int index) { TreeItem treeItem; if (parentTreeItem == null) { parentTreeItem = tree; } if (parentTreeItem instanceof Tree) { Tree tree = (Tree) parentTreeItem; if (tree.isDisposed()) { return null; } if (index >= 0) { treeItem = new TreeItem(tree, SWT.NONE, index); } else { treeItem = new TreeItem(tree, SWT.NONE); } } else { if (((TreeItem) parentTreeItem).isDisposed()) { return null; } if (index >= 0) { treeItem = new TreeItem((TreeItem) parentTreeItem, SWT.NONE, index); } else { treeItem = new TreeItem((TreeItem) parentTreeItem, SWT.NONE); } } return treeItem; } private void setupTreeItem(final IView iview, TreeItem treeItem, String id, ViewTitleInfo titleInfo, String title, Composite initializeView, Object datasource, boolean closeable, boolean expand) { final SideBarEntrySWT entry = getEntry(id); boolean pull = true; if (treeItem.getParentItem() != null && expand) { treeItem.getParentItem().setExpanded(true); } if (!expand) { treeItem.setExpanded(false); } treeItem.removeDisposeListener(disposeTreeItemListener); treeItem.addDisposeListener(disposeTreeItemListener); treeItem.setData("Plugin.viewID", id); if (iview != null) { entry.iview = iview; } if (title != null) { treeItem.setData("text", title); } else { if (entry.iview != null) { treeItem.setData("text", entry.iview.getFullTitle()); } } if (titleInfo == null) { if (entry.iview instanceof ViewTitleInfo) { titleInfo = (ViewTitleInfo) entry.iview; } else if (entry.iview instanceof UISWTViewImpl) { UISWTViewEventListener eventListener = ((UISWTViewImpl) entry.iview).getEventListener(); if (eventListener instanceof ViewTitleInfo) { titleInfo = (ViewTitleInfo) eventListener; } } } if (titleInfo != null) { entry.titleInfo = titleInfo; } if (entry.titleInfo != null) { mapTitleInfoToEntry.put(entry.titleInfo, entry); String newText = (String) entry.titleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_TEXT); if (newText != null) { pull = false; treeItem.setData("text", newText); } String imageID = (String) entry.titleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_IMAGEID); if (imageID != null) { entry.setImageLeftID(imageID.length() == 0 ? null : imageID); } listTreeItemsNoTitleInfo.remove(treeItem); } else { if (!listTreeItemsNoTitleInfo.contains(treeItem)) { listTreeItemsNoTitleInfo.add(treeItem); } } if (treeItem != null) { entry.treeItem = treeItem; } if (datasource != null) { entry.datasource = datasource; } entry.closeable = closeable; entry.pullTitleFromIView = pull; if (closeable) { Map autoOpenInfo = new LightHashMap(); if (entry.parentID != null) { autoOpenInfo.put("parentID", entry.parentID); } if (entry.iviewClass != null) { autoOpenInfo.put("iviewClass", entry.iviewClass.getName()); } if (entry.eventListener != null) { autoOpenInfo.put("eventlistenerid", id); } if (entry.iview != null) { autoOpenInfo.put("title", entry.iview.getFullTitle()); } if (entry.datasource instanceof DownloadManager) { try { autoOpenInfo.put( "dm", ((DownloadManager) entry.datasource).getTorrent().getHashWrapper().toBase32String()); } catch (Throwable t) { } } mapAutoOpen.put(id, autoOpenInfo); } if (initializeView != null) { iview.initialize(initializeView); initializeView.setVisible(false); Composite composite = iview.getComposite(); if (composite != null && !composite.isDisposed()) { composite.setVisible(false); composite.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (entry.treeItem != null && !entry.treeItem.isDisposed()) { try { entry.treeItem.dispose(); } catch (NullPointerException npe) { // ignore swt bug } } } }); } if (entry.datasource != null) { iview.dataSourceChanged(entry.datasource); } initializeView.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (entry.iview != null) { try { entry.iview.delete(); } catch (Throwable t) { Debug.out(t); } entry.iview = null; } } }); } } public static SideBarEntrySWT getEntry(String id) { if ("Browse".equalsIgnoreCase(id)) { id = SIDEBAR_SECTION_BROWSE; } SideBarEntrySWT entry = (SideBarEntrySWT) mapIdToEntries.get(id); if (entry == null) { entry = new SideBarEntrySWT(instance, id); mapIdToEntries.put(id, entry); } return entry; } public static boolean entryExists(String id) { if ("Browse".equalsIgnoreCase(id)) { id = SIDEBAR_SECTION_BROWSE; } SideBarEntrySWT entry = (SideBarEntrySWT) mapIdToEntries.get(id); if (entry == null) { return false; } return entry.treeItem != null; } /** * @param treeItem * * @since 3.1.1.1 */ private void itemSelected(final TreeItem treeItem) { Utils.execSWTThread(new AERunnable() { public void runSupport() { _itemSelected(treeItem); } }); } private void disabledViewModes() { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { ToolBarItem itemModeSmall = tb.getToolBarItem("modeSmall"); if (itemModeSmall != null) { itemModeSmall.getSkinButton().getSkinObject().switchSuffix(""); itemModeSmall.setEnabled(false); } ToolBarItem itemModeBig = tb.getToolBarItem("modeBig"); if (itemModeBig != null) { itemModeBig.getSkinButton().getSkinObject().switchSuffix(""); itemModeBig.setEnabled(false); } } } private void _itemSelected(TreeItem treeItem) { if (treeItem == null) { return; } TreeItem[] selection = tree.getSelection(); if (selection == null || selection.length == 0 || selection[0] != treeItem) { tree.showItem(treeItem); tree.select(treeItem); } final String id = (String) treeItem.getData("Plugin.viewID"); final SideBarEntrySWT newEntry = getEntry(id); if (currentSideBarEntry == newEntry) { triggerSelectionListener(newEntry, newEntry); return; } // We'll have an iview if we've previously created one IView newIView = newEntry.iview; // Otherwise, we have two ways of creating an IView.. via IViewClass, // or UISWTViewEventListener if (newIView == null) { if (newEntry.iviewClass != null) { newIView = createSideBarContentArea(id, newEntry); if (newIView == null) { return; } setupTreeItem(newIView, treeItem, (String) treeItem.getData("Plugin.viewID"), null, newIView.getFullTitle(), null, null, newEntry.closeable, true); } } if (newIView == null && newEntry.eventListener != null) { newIView = createTreeItemFromEventListener(null, treeItem, newEntry.eventListener, id, newEntry.closeable, null); } if (newIView != null) { if (newIView instanceof ToolBarEnabler) { ISelectedContent[] sels = new ISelectedContent[1]; sels[0] = new ToolBarEnablerSelectedContent((ToolBarEnabler) newIView); TableView tv = null; if (newIView instanceof TableView) { tv = (TableView) newIView; } SelectedContentManager.changeCurrentlySelectedContent("IconBarEnabler", sels, tv); } else { SelectedContentManager.clearCurrentlySelectedContent(); } disabledViewModes(); Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { flipVisibilityTo(newEntry); } }); } } protected void flipVisibilityTo(SideBarEntrySWT newSideBarInfo) { if (tree.isDisposed()) { return; } final SideBarEntrySWT oldEntry = currentSideBarEntry; // show new currentSideBarEntry = newSideBarInfo; SWTSkinObjectContainer container; if (currentSideBarEntry.iview instanceof UISWTViewImpl) { Object ds = ((UISWTViewImpl) currentSideBarEntry.iview).getDataSource(); DownloadManager dm = null; if (ds instanceof DownloadManager) { dm = (DownloadManager) ds; } else if (ds instanceof Download) { dm = PluginCoreUtils.unwrap((Download) ds); } if (dm != null) { try { TableView tv = null; if (currentSideBarEntry.iview instanceof TableView) { tv = (TableView) currentSideBarEntry.iview; } SelectedContentManager.changeCurrentlySelectedContent( currentSideBarEntry.id, new ISelectedContent[] { new SelectedContentV3(dm) }, tv); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } container = (SWTSkinObjectContainer) newSideBarInfo.skinObject; if (container != null) { //container.setVisible(true); Composite composite = container.getComposite(); if (composite != null && !composite.isDisposed()) { composite.setVisible(true); composite.moveAbove(null); //composite.setFocus(); } } Composite c = currentSideBarEntry.iview.getComposite(); if (c != null && !c.isDisposed()) { c.setVisible(true); } if (currentSideBarEntry.iview instanceof IViewExtension) { try { ((IViewExtension)currentSideBarEntry.iview).viewActivated(); } catch (Exception e) { Debug.out(e); } } // hide old if (oldEntry != null && oldEntry != newSideBarInfo) { if (lastImage != null && !lastImage.isDisposed()) { lastImage.dispose(); lastImage = null; } if (oldEntry.skinObject != null) { container = (SWTSkinObjectContainer) oldEntry.skinObject; if (container != null) { Control oldComposite = container.getControl(); doFade(oldComposite); container.setVisible(false); if (!oldComposite.isDisposed()) { oldComposite.getShell().update(); } } } if (oldEntry.iview != null) { Composite oldComposite = oldEntry.iview.getComposite(); if (oldComposite != null && !oldComposite.isDisposed()) { doFade(oldComposite); oldComposite.setVisible(false); oldComposite.getShell().update(); } if (oldEntry.iview instanceof IViewExtension) { try { ((IViewExtension)oldEntry.iview).viewDeactivated(); } catch (Exception e) { Debug.out(e); } } } } triggerSelectionListener(newSideBarInfo, oldEntry); } /** * @param oldComposite * * @since 3.1.1.1 */ private void doFade(final Control oldComposite) { if (true) { return; } if (oldComposite.isDisposed() || (shellFade != null && !shellFade.isDisposed())) { return; } final Shell parentShell = oldComposite.getShell(); if (parentShell != oldComposite.getDisplay().getActiveShell()) { return; } if (lastImage == null || lastImage.isDisposed()) { Rectangle bounds = oldComposite.getBounds(); if (bounds.isEmpty()) { return; } lastImage = new Image(oldComposite.getDisplay(), bounds.width, bounds.height); GC gc = new GC(oldComposite); gc.copyArea(lastImage, 0, 0); gc.dispose(); int style = SWT.NO_TRIM; if (Constants.isOSX) { style |= SWT.ON_TOP; } shellFade = new Shell(soSideBarContents.getControl().getShell(), style); Point pos = soSideBarContents.getControl().toDisplay(0, 0); shellFade.setBackgroundImage(lastImage); shellFade.setLocation(pos); shellFade.setSize(soSideBarContents.getControl().getSize()); shellFade.setAlpha(255); shellFade.setVisible(true); shellFade.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event event) { if (lastImage != null && !lastImage.isDisposed()) { lastImage.dispose(); } } }); Utils.execSWTThreadLater(15, new AERunnable() { long lastTime; public void runSupport() { if (shellFade.isDisposed()) { return; } if (lastImage == null || lastImage.isDisposed() || parentShell != parentShell.getDisplay().getActiveShell()) { shellFade.dispose(); return; } int alpha = shellFade.getAlpha(); alpha -= 50; long now = SystemTime.getCurrentTime(); if (alpha < 0 || lastImage == null || lastImage.isDisposed()) { shellFade.dispose(); return; } shellFade.setAlpha(alpha); //System.out.println(alpha); if (lastTime > 0 && now - lastTime > 50) { Utils.execSWTThreadLater(0, this); } else { Utils.execSWTThreadLater(15, this); } lastTime = now; }; }); } } /** * @param parentID * @param l * @param datasource * @return * * @since 3.1.1.1 */ public IView createTreeItemFromEventListener(String parentID, TreeItem treeItem, UISWTViewEventListener l, String id, boolean closeable, Object datasource) { final String originialID = id; SideBarEntrySWT entry = getEntry(id); if (entry.treeItem != null && entry.iview != null) { if (entry.eventListener == l) { System.err.println("Already created view " + id); } id = id + "_" + SystemTime.getCurrentTime(); entry = getEntry(id); } String name = entry.treeItem == null ? id : (String) entry.treeItem.getData("text"); if (treeItem == null) { TreeItem parentTreeItem = parentID == null ? null : getEntry(parentID).treeItem; IViewInfo foundViewInfo = null; IViewInfo[] pluginViewsInfo = PluginsMenuHelper.getInstance().getPluginViewsInfo(); for (int i = 0; i < pluginViewsInfo.length; i++) { IViewInfo viewInfo = pluginViewsInfo[i]; if (viewInfo.event_listener == l) { foundViewInfo = viewInfo; break; } } if (foundViewInfo == null) { pluginViewsInfo = PluginsMenuHelper.getInstance().getPluginLogViewsInfo(); for (int i = 0; i < pluginViewsInfo.length; i++) { IViewInfo viewInfo = pluginViewsInfo[i]; if (viewInfo.event_listener == l) { foundViewInfo = viewInfo; break; } } } if (foundViewInfo != null) { IViewInfo[] pluginLogViewsInfo = PluginsMenuHelper.getInstance().getPluginLogViewsInfo(); for (int i = 0; i < pluginLogViewsInfo.length; i++) { IViewInfo viewInfo = pluginLogViewsInfo[i]; if (viewInfo.event_listener == l) { foundViewInfo = viewInfo; break; } } } name = foundViewInfo == null ? id : foundViewInfo.name; entry.eventListener = l; entry.parentID = parentID; treeItem = createTreeItem(parentTreeItem, id, datasource, null, name, closeable, -1); } IView iview = null; try { iview = new UISWTViewImpl(parentID, id, l, datasource); ((UISWTViewImpl) iview).setTitle(name); iview.dataSourceChanged(datasource); if (l instanceof UISWTViewEventListenerSkinObject) { ((UISWTViewImpl) iview).setUseCoreDataSource(true); } Composite parent = (Composite) soSideBarContents.getControl(); parent.setBackgroundMode(SWT.INHERIT_NONE); Composite viewComposite = new Composite(parent, SWT.NONE); viewComposite.setBackgroundMode(SWT.INHERIT_NONE); viewComposite.setLayoutData(Utils.getFilledFormData()); viewComposite.setBackground(parent.getDisplay().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND)); viewComposite.setForeground(parent.getDisplay().getSystemColor( SWT.COLOR_WIDGET_FOREGROUND)); if (l instanceof UISWTViewEventListenerSkinObject) { viewComposite.setLayout(new FormLayout()); } else { GridLayout gridLayout = new GridLayout(); gridLayout.horizontalSpacing = gridLayout.verticalSpacing = gridLayout.marginHeight = gridLayout.marginWidth = 0; viewComposite.setLayout(gridLayout); } viewComposite.setVisible(false); SWTSkinObjectContainer soContents = new SWTSkinObjectContainer(skin, skin.getSkinProperties(), viewComposite, "Contents." + id + "." + (mapIdToEntries.size() + 1), "", "container", soSideBarContents); entry.skinObject = soContents; entry.eventListener = l; entry.parentID = parentID; setupTreeItem(iview, treeItem, id, null, iview.getFullTitle(), viewComposite, datasource, closeable, true); if (parent.isVisible()) { parent.layout(true, true); } if (closeable) { COConfigurationManager.setParameter("SideBar.AutoOpen." + id, true); } else { COConfigurationManager.removeParameter("SideBar.AutoOpen." + id); } } catch (UISWTViewEventCancelledException e) { if (treeItem != null && !treeItem.isDisposed()) { treeItem.dispose(); } showEntryByID(originialID); } catch (Exception e) { e.printStackTrace(); try { final String id2 = id; l = new UISWTViewEventListener() { public boolean eventOccurred(UISWTViewEvent event) { if (event.getType() == UISWTViewEvent.TYPE_INITIALIZE) { Composite c = (Composite) event.getData(); Label label = new Label(c, SWT.CENTER); label.setText("Plugin " + id2 + " did not want to initialize"); } return true; } }; iview = new UISWTViewImpl("SideBar.Plugins", id, l, datasource); String text = (String) treeItem.getData("text"); if (text != null) { ((UISWTViewImpl) iview).setTitle(text); } Composite parent = (Composite) soSideBarContents.getControl(); Composite viewComposite = new Composite(parent, SWT.NONE); viewComposite.setLayoutData(Utils.getFilledFormData()); viewComposite.setLayout(new FormLayout()); viewComposite.setBackground(parent.getDisplay().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND)); viewComposite.setForeground(parent.getDisplay().getSystemColor( SWT.COLOR_WIDGET_FOREGROUND)); SWTSkinObjectContainer soContents = new SWTSkinObjectContainer(skin, skin.getSkinProperties(), viewComposite, "Contents" + (mapIdToEntries.size() + 1), "", "container", soSideBarContents); entry.skinObject = soContents; entry.eventListener = l; setupTreeItem(iview, treeItem, id, null, iview.getFullTitle(), viewComposite, datasource, closeable, true); parent.layout(true, true); } catch (Exception e1) { Debug.out(e1); } if (!(e instanceof UISWTViewEventCancelledException)) { Debug.out(e); } } return iview; } /** * Creates an IView based on class. Doesn't add it to the tree * @param id * * @param iview * @param iviewClass * @param args * * @since 3.1.0.1 */ private IView createSideBarContentArea(String id, SideBarEntrySWT sideBarInfo) { if (id == null) { return null; } IView iview = null; try { if (sideBarInfo.iviewClassArgs == null) { iview = (IView) sideBarInfo.iviewClass.newInstance(); } else { Constructor constructor = sideBarInfo.iviewClass.getConstructor(sideBarInfo.iviewClassArgs); iview = (IView) constructor.newInstance(sideBarInfo.iviewClassVals); } createSideBarContentArea(id, iview, sideBarInfo.treeItem, sideBarInfo.datasource, sideBarInfo.closeable, true); } catch (Exception e) { e.printStackTrace(); if (iview != null) { iview.delete(); } iview = null; } return iview; } /** * Take an already created IView and put it into a new Container Skin Object. * Doesn't add it to the tree * @param id * * @param view * @param closeable * @return * * @since 3.1.1.1 */ private IView createSideBarContentArea(String id, IView view, TreeItem item, Object datasource, boolean closeable, boolean expand) { try { Composite parent = (Composite) soSideBarContents.getControl(); SWTSkinObjectContainer soContents = new SWTSkinObjectContainer(skin, skin.getSkinProperties(), "Contents" + (mapIdToEntries.size() + 1), "", soSideBarContents); Composite viewComposite = soContents.getComposite(); viewComposite.setBackground(parent.getDisplay().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND)); viewComposite.setForeground(parent.getDisplay().getSystemColor( SWT.COLOR_WIDGET_FOREGROUND)); viewComposite.setLayoutData(Utils.getFilledFormData()); GridLayout gridLayout = new GridLayout(); gridLayout.horizontalSpacing = gridLayout.verticalSpacing = gridLayout.marginHeight = gridLayout.marginWidth = 0; viewComposite.setLayout(gridLayout); SideBarEntrySWT entry = getEntry((String) item.getData("Plugin.viewID")); entry.skinObject = soContents; setupTreeItem(view, item, id, null, null, viewComposite, datasource, closeable, expand); Composite iviewComposite = view.getComposite(); Object existingLayout = iviewComposite.getLayoutData(); if (existingLayout == null || (existingLayout instanceof GridData)) { GridData gridData = new GridData(GridData.FILL_BOTH); iviewComposite.setLayoutData(gridData); } if (iviewComposite.isVisible()) { parent.layout(true, true); } } catch (Exception e) { Debug.out("Error creating sidebar content area for " + id, e); if (view != null) { view.delete(); } view = null; item.dispose(); } return view; } public SideBarEntrySWT createEntryFromSkinRef(String parentID, final String id, final String configID, String title, ViewTitleInfo titleInfo, final Object params, boolean closeable, int index) { // temp until we start passing ds Object datasource = null; SideBarEntrySWT entry = getEntry(id); if (entry.treeItem != null) { return entry; } TreeItem treeItem = null; UISWTViewEventListener l = new UISWTViewEventListenerSkinObject() { public boolean eventOccurred(UISWTViewEvent event) { switch (event.getType()) { case UISWTViewEvent.TYPE_INITIALIZE: { Composite parent = (Composite) event.getData(); SWTSkinObject soParent = (SWTSkinObject) parent.getData("SkinObject"); Shell shell = parent.getShell(); Cursor cursor = shell.getCursor(); try { shell.setCursor(shell.getDisplay().getSystemCursor( SWT.CURSOR_WAIT)); skinObject = skin.createSkinObject(id, configID, soParent, params); skinObject.getControl().setLayoutData(Utils.getFilledFormData()); skinObject.getControl().getParent().layout(true); } finally { shell.setCursor(cursor); } } break; case UISWTViewEvent.TYPE_REFRESH: { break; } case UISWTViewEvent.TYPE_DESTROY: { break; } } return true; } }; entry.eventListener = l; TreeItem parentTreeItem = parentID == null ? null : getEntry(parentID).treeItem; entry.parentID = parentID; treeItem = createTreeItem(parentTreeItem == null ? (Object) tree : (Object) parentTreeItem, id, datasource, titleInfo, title, closeable, index); setupTreeItem(null, treeItem, id, titleInfo, title, null, datasource, closeable, true); return entry; } // @see com.aelitis.azureus.ui.swt.utils.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { if (currentSideBarEntry == null || currentSideBarEntry.iview == null) { return "Sidebar"; } if (currentSideBarEntry.iview instanceof UIPluginView) { UIPluginView uiPluginView = (UIPluginView) currentSideBarEntry.iview; return uiPluginView.getViewID(); } return currentSideBarEntry.iview.getFullTitle(); } // @see com.aelitis.azureus.ui.swt.utils.UIUpdatable#updateUI() public void updateUI() { if (currentSideBarEntry == null || currentSideBarEntry.iview == null || tree.getSelectionCount() == 0) { return; } currentSideBarEntry.iview.refresh(); SideBarEntrySWT entry = getEntry(currentSideBarEntry.id); if (entry.pullTitleFromIView && entry.treeItem != null && !entry.treeItem.isDisposed()) { entry.treeItem.setData("text", currentSideBarEntry.iview.getFullTitle()); } } public static abstract class UISWTViewEventListenerSkinObject implements UISWTViewEventListener { protected SWTSkinObject skinObject; public SWTSkinObject getSkinObject() { return skinObject; } } // @see com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoListener#viewTitleInfoRefresh(com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo) public void viewTitleInfoRefresh(final ViewTitleInfo titleIndicator) { if (titleIndicator == null) { return; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (tree == null || tree.isDisposed()) { return; } SideBarEntrySWT sideBarEntry = (SideBarEntrySWT) mapTitleInfoToEntry.get(titleIndicator); if (sideBarEntry == null) { Object o = titleIndicator.getTitleInfoProperty(ViewTitleInfo.TITLE_SKINVIEW); if (o instanceof SkinView) { SkinView skinView = (SkinView) o; String id = skinView.getMainSkinObject().getSkinObjectID(); if (id != null) { for (Iterator iter = listTreeItemsNoTitleInfo.iterator(); iter.hasNext();) { TreeItem searchTreeItem = (TreeItem) iter.next(); if (searchTreeItem.isDisposed()) { iter.remove(); continue; } String treeItemID = (String) searchTreeItem.getData("Plugin.viewID"); if (treeItemID != null && treeItemID.equals(id)) { sideBarEntry = getEntry(treeItemID); if (sideBarEntry.treeItem != null) { sideBarEntry.titleInfo = titleIndicator; mapTitleInfoToEntry.put(titleIndicator, sideBarEntry); } break; } } } } if (sideBarEntry == null || sideBarEntry.treeItem == null) { return; } } if (sideBarEntry.treeItem == null || sideBarEntry.treeItem.isDisposed()) { return; } String newText = (String) titleIndicator.getTitleInfoProperty(ViewTitleInfo.TITLE_TEXT); if (newText != null) { sideBarEntry.pullTitleFromIView = false; sideBarEntry.treeItem.setData("text", newText); } String imageID = (String) titleIndicator.getTitleInfoProperty(ViewTitleInfo.TITLE_IMAGEID); if (imageID != null) { sideBarEntry.setImageLeftID(imageID.length() == 0 ? null : imageID); } sideBarEntry.redraw(); String logID = (String) titleIndicator.getTitleInfoProperty(ViewTitleInfo.TITLE_LOGID); if (logID != null) { sideBarEntry.setLogID(logID); } } }); } public SideBarEntrySWT getCurrentEntry() { return currentSideBarEntry; } public void addListener(SideBarListener l) { if (listeners.contains(l)) { return; } listeners.add(l); } public void removeListener(SideBarListener l) { listeners.remove(l); } private void triggerSelectionListener(SideBarEntrySWT newSideBarEntry, SideBarEntrySWT oldSideBarEntry) { for (Iterator iter = listeners.iterator(); iter.hasNext();) { SideBarListener l = (SideBarListener) iter.next(); l.sidebarItemSelected(newSideBarEntry, oldSideBarEntry); } } public IView getIViewFromID(String id) { if (id == null) { return null; } return getEntry(id).iview; } public void saveCloseables() { // update title for (Iterator iter = mapAutoOpen.keySet().iterator(); iter.hasNext();) { String id = (String) iter.next(); Object o = mapAutoOpen.get(id); if (o instanceof Map) { SideBarEntrySWT entry = getEntry(id); Map autoOpenInfo = (Map) o; if (entry.treeItem != null && !entry.treeItem.isDisposed()) { String s = (String) entry.treeItem.getData("text"); if (s != null) { autoOpenInfo.put("title", s); } } } } FileUtil.writeResilientConfigFile("sidebarauto.config", mapAutoOpen); } public void loadCloseables() { mapAutoOpen = FileUtil.readResilientConfigFile("sidebarauto.config", true); if (mapAutoOpen.isEmpty()) { return; } BDecoder.decodeStrings(mapAutoOpen); for (Iterator iter = mapAutoOpen.keySet().iterator(); iter.hasNext();) { String id = (String) iter.next(); Object o = mapAutoOpen.get(id); if (o instanceof Map) { if (!processAutoOpenMap(id, (Map) o, null)) { iter.remove(); } } } } /** * @param viewInfo * @param o * * @since 3.1.1.1 */ private boolean processAutoOpenMap(String id, Map autoOpenInfo, IViewInfo viewInfo) { try { SideBarEntrySWT entry = getEntry(id); if (entry.treeItem != null) { return true; } if (id.equals(SIDEBAR_SECTION_WELCOME)) { createWelcomeSection(); } String title = MapUtils.getMapString(autoOpenInfo, "title", id); String parentID = (String) autoOpenInfo.get("parentID"); if (viewInfo != null) { if (viewInfo.view != null) { createTreeItemFromIView(parentID, viewInfo.view, id, null, true, false); } else if (viewInfo.event_listener != null) { createTreeItemFromEventListener(parentID, null, viewInfo.event_listener, id, true, null); } if (entry.iview == null) { createSideBarContentArea(id, entry); } } Class cla = Class.forName(MapUtils.getMapString(autoOpenInfo, "iviewClass", "")); if (cla != null) { String dmHash = MapUtils.getMapString(autoOpenInfo, "dm", null); Object ds = null; if (dmHash != null) { HashWrapper hw = new HashWrapper(Base32.decode(dmHash)); GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); ds = gm.getDownloadManager(hw); // XXX Skip auto open DM for now return false; } createTreeItemFromIViewClass(parentID, id, title, cla, null, null, ds, null, true); if (entry.iview == null) { IView view = createSideBarContentArea(id, entry); if (view == null) { return false; } } } } catch (ClassNotFoundException ce) { // ignore } catch (Throwable e) { Debug.out(e); } return true; } /** * * TODO {@link #showEntryByID(String)} and {@link #showEntryByID(String)} * absolutely need to be combined since they do the same thing * but have different logic.. */ public boolean showEntryByID(String id) { SideBarEntrySWT entry = getEntry(id); if (entry.treeItem != null) { itemSelected(entry.treeItem); return true; } if (id.equals(SIDEBAR_SECTION_WELCOME)) { SideBarEntrySWT entryWelcome = createWelcomeSection(); itemSelected(entryWelcome.treeItem); return true; } else if (id.startsWith("ContentNetwork.")) { long networkID = Long.parseLong(id.substring(15)); handleContentNetworkSwitch(id, networkID); return true; } return false; } /** * @param tabID * * @since 3.1.0.1 * * TODO {@link #showEntryByID(String)} and {@link #showEntryByID(String)} * absolutely need to be combined since they do the same thing * but have different logic.. */ public String showEntryByTabID(String tabID) { if (tabID == null) { return null; } String id; SideBarEntrySWT entry = getEntry(tabID); if (entry.isInTree()) { id = tabID; } else if (tabID.equals("library") || tabID.equals("minilibrary")) { id = SIDEBAR_SECTION_LIBRARY; } else if (tabID.equals("activities")) { id = SIDEBAR_SECTION_ACTIVITIES; } else if (tabID.startsWith("ContentNetwork.")) { id = tabID; } else if (tabID.equals(SIDEBAR_SECTION_WELCOME)) { id = tabID; } else { // everything else can go to browse.. id = SIDEBAR_SECTION_BROWSE; } final String itemID = id; entry = getEntry(itemID); if (entry.isInTree()) { itemSelected(entry.treeItem); return id; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (tree.isDisposed()) { return; } showEntryByID(itemID); } }); return id; } /** * @param tabID * * @since 4.0.0.3 */ protected void handleContentNetworkSwitch(String tabID, long networkID) { try { ContentNetworkManager cnManager = ContentNetworkManagerFactory.getSingleton(); if (cnManager == null) { showEntryByID(SIDEBAR_SECTION_BROWSE); return; } ContentNetwork cn = cnManager.getContentNetwork(networkID); if (cn == null) { showEntryByID(SIDEBAR_SECTION_BROWSE); return; } if (networkID == ContentNetwork.CONTENT_NETWORK_VUZE) { showEntryByID(SIDEBAR_SECTION_BROWSE); cn.setPersistentProperty(ContentNetwork.PP_ACTIVE, Boolean.TRUE); return; } boolean doneAuth = false; Object oDoneAuth = cn.getPersistentProperty(ContentNetwork.PP_AUTH_PAGE_SHOWN); if (oDoneAuth instanceof Boolean) { doneAuth = ((Boolean) oDoneAuth).booleanValue(); } if (!doneAuth && cn.isServiceSupported(ContentNetwork.SERVICE_AUTHORIZE)) { if (!AuthorizeWindow.openAuthorizeWindow(cn)) { return; } } createContentNetworkSideBarEntry(cn); showEntryByID(tabID); return; } catch (Exception e) { Debug.out(e); } showEntryByID(SIDEBAR_SECTION_BROWSE); } public void createContentNetworkSideBarEntry(ContentNetwork cn) { String entryID = ContentNetworkUtils.getTarget(cn); if (entryExists(entryID)) { return; } String name = cn.getName(); SideBarEntrySWT entryBrowse = getEntry(SIDEBAR_SECTION_BROWSE); int position = entryBrowse == null ? 3 : tree.indexOf(entryBrowse.getTreeItem()) + 1; Object prop = cn.getProperty(ContentNetwork.PROPERTY_REMOVEABLE); boolean closeable = (prop instanceof Boolean) ? ((Boolean) prop).booleanValue() : false; final SideBarEntrySWT entry = createEntryFromSkinRef(null, entryID, "main.area.browsetab", name, null, cn, closeable, position); ContentNetworkUI.loadImage(cn.getID(), new ContentNetworkImageLoadedListener() { public void contentNetworkImageLoaded(Long contentNetworkID, Image image, boolean wasReturned) { entry.setImageLeft(image); } }); cn.setPersistentProperty(ContentNetwork.PP_ACTIVE, Boolean.TRUE); cn.setPersistentProperty(ContentNetwork.PP_SHOW_IN_MENU, Boolean.TRUE); } /** * @param browse * @return * * @since 3.1.1.1 */ public SideBarEntrySWT getEntryBySkinView(SkinView skinView) { SWTSkinObject so = skinView.getMainSkinObject(); Object[] sideBarEntries = mapIdToEntries.values().toArray(); for (int i = 0; i < sideBarEntries.length; i++) { SideBarEntrySWT entry = (SideBarEntrySWT) sideBarEntries[i]; SWTSkinObject entrySO = entry.getSkinObject(); SWTSkinObject entrySOParent = entrySO == null ? entrySO : entrySO.getParent(); if (entrySO == so || entrySO == so.getParent() || entrySOParent == so) { return entry; } } return null; } public SideBarEntry[] getEntries() { return (SideBarEntry[]) mapIdToEntries.values().toArray(new SideBarEntry[0]); } public int getIndexOfEntryRelativeToParent( SideBarEntrySWT entry ) { TreeItem[] items = tree.getItems(); for (int i=0;i, List> mapSkinViews = new HashMap, List>(); private static AEMonitor2 mon_skinViews = new AEMonitor2("skinViews"); /** * Map SkinObjectID to skin view */ private static Map skinIDs = new HashMap(); private static List listeners = new ArrayList(); /** * @param key * @param skinView */ public static void add(final SkinView skinView) { mon_skinViews.enter(); try { List list = mapSkinViews.get(skinView); if (list == null) { list = new ArrayList(1); mapSkinViews.put(skinView.getClass(), list); } list.add(skinView); } finally { mon_skinViews.exit(); } SWTSkinObject mainSkinObject = skinView.getMainSkinObject(); if (mainSkinObject != null) { skinIDs.put(mainSkinObject.getSkinObjectID(), skinView); } triggerViewAddedListeners(skinView); } public static void remove(SkinView skinView) { if (skinView == null) { return; } mon_skinViews.enter(); try { List list = mapSkinViews.get(skinView.getClass()); if (list != null) { list.remove(skinView); if (list.isEmpty()) { mapSkinViews.remove(skinView.getClass()); } } } finally { mon_skinViews.exit(); } SWTSkinObject mainSkinObject = skinView.getMainSkinObject(); if (mainSkinObject != null) { skinIDs.remove(mainSkinObject.getSkinObjectID()); } } /** * Gets the first SkinView created of the specified class * * @param cla * @return */ public static SkinView getByClass(Class cla) { List list = mapSkinViews.get(cla); if (list == null) { return null; } Object[] skinViews = list.toArray(); for (int i = 0; i < skinViews.length; i++) { SkinView sv = (SkinView) skinViews[i]; SWTSkinObject so = sv.getMainSkinObject(); if (so != null) { if (!so.isDisposed()) { return sv; } remove(sv); } } return null; } /** * Return all added SkinViews of a certain class * * @param cla * @return */ public static SkinView[] getMultiByClass(Class cla) { List list = mapSkinViews.get(cla); if (list == null) { return new SkinView[0]; } return list.toArray(new SkinView[0]); } /** * Get the SkinView related to a SkinObjectID * * @param id * @return */ public static SkinView getBySkinObjectID(String id) { SkinView sv = skinIDs.get(id); if (sv != null) { SWTSkinObject so = sv.getMainSkinObject(); if (so != null && so.isDisposed()) { remove(sv); return null; } } return sv; } /** * Listen in on SkinView adds * * @param l */ public static void addListener(SkinViewManagerListener l) { synchronized (SkinViewManager.class) { if (!listeners.contains(l)) { listeners.add(l); } } } public static void RemoveListener(SkinViewManagerListener l) { synchronized (SkinViewManager.class) { listeners.remove(l); } } public static void triggerViewAddedListeners(SkinView skinView) { Object[] array = listeners.toArray(); for (int i = 0; i < array.length; i++) { SkinViewManagerListener l = (SkinViewManagerListener) array[i]; try { l.skinViewAdded(skinView); } catch (Exception e) { Debug.out(e); } } } public static interface SkinViewManagerListener { public void skinViewAdded(SkinView skinview); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/WelcomeView.java0000644000175000017500000000564311272502242025175 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.views.skin; import org.gudy.azureus2.core3.config.COConfigurationManager; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.ui.skin.SkinConstants; import com.aelitis.azureus.ui.swt.browser.BrowserContext.loadingListener; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectBrowser; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.ContentNetworkUtils; import org.gudy.azureus2.plugins.ui.sidebar.SideBarCloseListener; import org.gudy.azureus2.plugins.ui.sidebar.SideBarEntry; /** * @author TuxPaper * @created Oct 1, 2006 * */ public class WelcomeView extends SkinView { private SWTSkinObjectBrowser browserSkinObject; public Object skinObjectInitialShow(final SWTSkinObject skinObject, Object params) { browserSkinObject = (SWTSkinObjectBrowser) skin.getSkinObject( SkinConstants.VIEWID_BROWSER_WELCOME, soMain); browserSkinObject.addListener(new loadingListener() { public void browserLoadingChanged(boolean loading, String url) { if (!loading) { skinObject.getControl().getParent().layout(true, true); } } }); COConfigurationManager.setParameter("v3.Show Welcome", false); Object o = skinObject.getData("CreationParams"); if (o instanceof String) { browserSkinObject.setURL((String) o); } else { String sURL = ContentNetworkUtils.getUrl( ConstantsVuze.getDefaultContentNetwork(), ContentNetwork.SERVICE_WELCOME); browserSkinObject.setURL(sURL); } SideBarEntrySWT entry = SideBar.getEntry(SideBar.SIDEBAR_SECTION_WELCOME); entry.addListener(new SideBarCloseListener() { public void sidebarClosed(SideBarEntry entry) { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { sidebar.showEntryByID(SideBar.SIDEBAR_SECTION_LIBRARY); } } }); return null; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/FakeTableCell.java0000644000175000017500000002077211136257644025401 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.views.skin; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.TableRowCore; import org.gudy.azureus2.plugins.ui.Graphic; import org.gudy.azureus2.plugins.ui.tables.*; /** * Legacy support for EMP. Class moved to * {@link org.gudy.azureus2.ui.swt.views.table.impl.FakeTableCell} * * @author TuxPaper * @created Jan 1, 2008 * */ public class FakeTableCell implements TableCell { org.gudy.azureus2.ui.swt.views.table.impl.FakeTableCell cell; public FakeTableCell(TableColumn column) { cell = new org.gudy.azureus2.ui.swt.views.table.impl.FakeTableCell(column); } public FakeTableCell(TableColumnCore column) { cell = new org.gudy.azureus2.ui.swt.views.table.impl.FakeTableCell(column); } public void refresh() { cell.refresh(); cell.redraw(); } public void addDisposeListener(TableCellDisposeListener listener) { cell.addDisposeListener(listener); } public void addListeners(Object listenerObject) { cell.addListeners(listenerObject); } public void addMouseListener(TableCellMouseListener listener) { cell.addMouseListener(listener); } public void addMouseMoveListener(TableCellMouseMoveListener listener) { cell.addMouseMoveListener(listener); } public void addRefreshListener(TableCellRefreshListener listener) { cell.addRefreshListener(listener); } public void addToolTipListener(TableCellToolTipListener listener) { cell.addToolTipListener(listener); } public void addVisibilityListener(TableCellVisibilityListener listener) { cell.addVisibilityListener(listener); } public int compareTo(Object arg0) { return cell.compareTo(arg0); } public void dispose() { cell.dispose(); } public void doPaint(GC gc, Rectangle bounds) { cell.doPaint(gc, bounds); } public boolean equals(Object obj) { return cell.equals(obj); } public int[] getBackground() { return cell.getBackground(); } public Graphic getBackgroundGraphic() { return cell.getBackgroundGraphic(); } public int getCursorID() { return cell.getCursorID(); } public Object getDataSource() { return cell.getDataSource(); } public int[] getForeground() { return cell.getForeground(); } public Graphic getGraphic() { return cell.getGraphic(); } public int getHeight() { return cell.getHeight(); } public int getMaxLines() { return cell.getMaxLines(); } public String getObfusticatedText() { return cell.getObfusticatedText(); } public Comparable getSortValue() { return cell.getSortValue(); } public TableColumn getTableColumn() { return cell.getTableColumn(); } public String getTableID() { return cell.getTableID(); } public TableRow getTableRow() { return cell.getTableRow(); } public TableRowCore getTableRowCore() { return cell.getTableRowCore(); } public String getText() { return cell.getText(); } public Object getToolTip() { return cell.getToolTip(); } public boolean getVisuallyChangedSinceRefresh() { return cell.getVisuallyChangedSinceRefresh(); } public int getWidth() { return cell.getWidth(); } public int hashCode() { return cell.hashCode(); } public void invalidate() { cell.invalidate(); } public void invalidate(boolean mustRefresh) { cell.invalidate(mustRefresh); } public void invokeMouseListeners(TableCellMouseEvent event) { cell.invokeMouseListeners(event); } public void invokeToolTipListeners(int type) { cell.invokeToolTipListeners(type); } public void invokeVisibilityListeners(int visibility, boolean invokeColumnListeners) { cell.invokeVisibilityListeners(visibility, invokeColumnListeners); } public boolean isDisposed() { return cell.isDisposed(); } public boolean isMouseOver() { return cell.isMouseOver(); } public boolean isShown() { return cell.isShown(); } public boolean isUpToDate() { return cell.isUpToDate(); } public boolean isValid() { return cell.isValid(); } public void locationChanged() { cell.locationChanged(); } public void mouseDoubleClick(MouseEvent e) { cell.mouseDoubleClick(e); } public void mouseDown(MouseEvent e) { cell.mouseDown(e); } public void mouseEnter(MouseEvent e) { cell.mouseEnter(e); } public void mouseExit(MouseEvent e) { cell.mouseExit(e); } public void mouseHover(MouseEvent e) { cell.mouseHover(e); } public void mouseMove(MouseEvent e) { cell.mouseMove(e); } public void mouseUp(MouseEvent e) { cell.mouseUp(e); } public boolean needsPainting() { return cell.needsPainting(); } public void paintControl(PaintEvent e) { cell.paintControl(e); } public boolean refresh(boolean doGraphics, boolean rowVisible, boolean cellVisible) { return cell.refresh(doGraphics, rowVisible, cellVisible); } public boolean refresh(boolean doGraphics, boolean rowVisible) { return cell.refresh(doGraphics, rowVisible); } public boolean refresh(boolean doGraphics) { return cell.refresh(doGraphics); } public void removeDisposeListener(TableCellDisposeListener listener) { cell.removeDisposeListener(listener); } public void removeMouseListener(TableCellMouseListener listener) { cell.removeMouseListener(listener); } public void removeMouseMoveListener(TableCellMouseMoveListener listener) { cell.removeMouseMoveListener(listener); } public void removeRefreshListener(TableCellRefreshListener listener) { cell.removeRefreshListener(listener); } public void removeToolTipListener(TableCellToolTipListener listener) { cell.removeToolTipListener(listener); } public void removeVisibilityListener(TableCellVisibilityListener listener) { cell.removeVisibilityListener(listener); } public void setControl(Composite composite) { cell.setControl(composite); } public void setCursorID(int cursorID) { cell.setCursorID(cursorID); } public void setDataSource(Object datasource) { cell.setDataSource(datasource); } public void setFillCell(boolean fillCell) { cell.setFillCell(fillCell); } public boolean setForeground(int red, int green, int blue) { return cell.setForeground(red, green, blue); } public boolean setForeground(int[] rgb) { return cell.setForeground(rgb); } public boolean setForegroundToErrorColor() { return cell.setForegroundToErrorColor(); } public boolean setGraphic(Graphic img) { return cell.setGraphic(img); } public void setMarginHeight(int height) { cell.setMarginHeight(height); } public void setMarginWidth(int width) { cell.setMarginWidth(width); } public void setOrentation(int o) { cell.setOrentation(o); } public boolean setSortValue(Comparable valueToSort) { return cell.setSortValue(valueToSort); } public boolean setSortValue(float valueToSort) { return cell.setSortValue(valueToSort); } public boolean setSortValue(long valueToSort) { return cell.setSortValue(valueToSort); } public boolean setText(String text) { return cell.setText(text); } public void setToolTip(Object tooltip) { cell.setToolTip(tooltip); } public void setUpToDate(boolean upToDate) { cell.setUpToDate(upToDate); } public String toString() { return cell.toString(); } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getMouseOffset() public int[] getMouseOffset() { return cell.getMouseOffset(); } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getMarginHeight() public int getMarginHeight() { return cell.getMarginHeight(); } // @see org.gudy.azureus2.plugins.ui.tables.TableCell#getMarginWidth() public int getMarginWidth() { return cell.getMarginWidth(); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryView.java0000644000175000017500000006154711306337236025711 0ustar adrianadrian/** * Created on Jul 2, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin; import java.util.Iterator; import java.util.List; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Control; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerListener; import org.gudy.azureus2.core3.download.impl.DownloadManagerAdapter; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerAdapter; import org.gudy.azureus2.core3.global.GlobalManagerStats; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.networkmanager.NetworkManager; import com.aelitis.azureus.core.speedmanager.SpeedManager; import com.aelitis.azureus.core.torrent.HasBeenOpenedListener; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.ui.InitializerListener; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.skin.SkinConstants; import com.aelitis.azureus.ui.swt.Initializer; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectText; import com.aelitis.azureus.ui.swt.toolbar.ToolBarItem; import com.aelitis.azureus.ui.swt.toolbar.ToolBarItemListener; import com.aelitis.azureus.ui.swt.utils.ColorCache; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarVitalityImageSWT; /** * @author TuxPaper * @created Jul 2, 2008 * */ public class SBC_LibraryView extends SkinView { private final static String ID = "library-list"; public final static int MODE_BIGTABLE = 0; public final static int MODE_SMALLTABLE = 1; public static final int TORRENTS_ALL = 0; public static final int TORRENTS_COMPLETE = 1; public static final int TORRENTS_INCOMPLETE = 2; public static final int TORRENTS_UNOPENED = 3; private final static String[] modeViewIDs = { SkinConstants.VIEWID_SIDEBAR_LIBRARY_BIG, SkinConstants.VIEWID_SIDEBAR_LIBRARY_SMALL }; private final static String[] modeIDs = { "library.table.big", "library.table.small" }; private static final String ID_VITALITY_ACTIVE = "image.sidebar.vitality.dl"; private static final String ID_VITALITY_ALERT = "image.sidebar.vitality.alert"; private static final long DL_VITALITY_REFRESH_RATE = 15000; private static final boolean DL_VITALITY_CONSTANT = true; private static int numSeeding = 0; private static int numDownloading = 0; private static int numComplete = 0; private static int numIncomplete = 0; private static int numErrorComplete = 0; private static String errorInCompleteTooltip; private static int numErrorInComplete = 0; private static String errorCompleteTooltip; private static int numUnOpened = 0; private int viewMode = -1; private SWTSkinButtonUtility btnSmallTable; private SWTSkinButtonUtility btnBigTable; private SWTSkinObject soListArea; private int torrentFilterMode = TORRENTS_ALL; private String torrentFilter; private ToolBarItem itemModeSmall; private ToolBarItem itemModeBig; private SWTSkinObject soWait; private SWTSkinObject soWaitProgress; private SWTSkinObjectText soWaitTask; private int waitProgress = 0; // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#showSupport(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) { soWait = null; try { soWait = getSkinObject("library-wait"); soWaitProgress = getSkinObject("library-wait-progress"); soWaitTask = (SWTSkinObjectText) getSkinObject("library-wait-task"); if (soWaitProgress != null) { soWaitProgress.getControl().addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { Control c = (Control) e.widget; Point size = c.getSize(); e.gc.setBackground(ColorCache.getColor(e.display, "#23a7df")); int breakX = size.x * waitProgress / 100; e.gc.fillRectangle(0, 0, breakX, size.y); e.gc.setBackground(ColorCache.getColor(e.display, "#cccccc")); e.gc.fillRectangle(breakX, 0, size.x - breakX, size.y); } }); } } catch (Exception e) { } AzureusCore core = AzureusCoreFactory.getSingleton(); if (!AzureusCoreFactory.isCoreRunning()) { if (soWait != null) { soWait.setVisible(true); } final Initializer initializer = Initializer.getLastInitializer(); if (initializer != null) { initializer.addListener(new InitializerListener() { public void reportPercent(final int percent) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (soWaitProgress != null && !soWaitProgress.isDisposed()) { waitProgress = percent; soWaitProgress.getControl().redraw(); soWaitProgress.getControl().update(); } } }); if (percent > 100) { initializer.removeListener(this); } } public void reportCurrentTask(String currentTask) { if (soWaitTask != null && !soWaitTask.isDisposed()) { soWaitTask.setText(currentTask); } } }); } } AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(final AzureusCore core) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (soWait != null) { soWait.setVisible(false); } } }); } }); torrentFilter = skinObject.getSkinObjectID(); if (torrentFilter.equalsIgnoreCase(SideBar.SIDEBAR_SECTION_LIBRARY_DL)) { torrentFilterMode = TORRENTS_INCOMPLETE; } else if (torrentFilter.equalsIgnoreCase(SideBar.SIDEBAR_SECTION_LIBRARY_CD)) { torrentFilterMode = TORRENTS_COMPLETE; } else if (torrentFilter.equalsIgnoreCase(SideBar.SIDEBAR_SECTION_LIBRARY_UNOPENED)) { torrentFilterMode = TORRENTS_UNOPENED; } soListArea = getSkinObject(ID + "-area"); soListArea.getControl().setData("TorrentFilterMode", new Long(torrentFilterMode)); setViewMode(COConfigurationManager.getIntParameter(torrentFilter + ".viewmode"), false); SWTSkinObject so; so = getSkinObject(ID + "-button-smalltable"); if (so != null) { btnSmallTable = new SWTSkinButtonUtility(so); btnSmallTable.addSelectionListener(new SWTSkinButtonUtility.ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { setViewMode(MODE_SMALLTABLE, true); } }); } so = getSkinObject(ID + "-button-bigtable"); if (so != null) { btnBigTable = new SWTSkinButtonUtility(so); btnBigTable.addSelectionListener(new SWTSkinButtonUtility.ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { setViewMode(MODE_BIGTABLE, true); } }); } SkinViewManager.addListener(new SkinViewManager.SkinViewManagerListener() { public void skinViewAdded(SkinView skinview) { if (skinview instanceof ToolBarView) { initToolBarView((ToolBarView) skinview); } } }); ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { initToolBarView(tb); } return null; } protected void initToolBarView(ToolBarView tb) { itemModeSmall = tb.getToolBarItem("modeSmall"); if (itemModeSmall != null) { itemModeSmall.addListener(new ToolBarItemListener() { public void pressed(ToolBarItem toolBarItem) { if (isVisible()) { setViewMode(MODE_SMALLTABLE, true); } } public boolean held(ToolBarItem toolBarItem) { return false; } }); } itemModeBig = tb.getToolBarItem("modeBig"); if (itemModeBig != null) { itemModeBig.addListener(new ToolBarItemListener() { public void pressed(ToolBarItem toolBarItem) { if (isVisible()) { setViewMode(MODE_BIGTABLE, true); } } public boolean held(ToolBarItem toolBarItem) { return false; } }); } } // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectShown(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectShown(SWTSkinObject skinObject, Object params) { super.skinObjectShown(skinObject, params); ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { ToolBarItem itemModeSmall = tb.getToolBarItem("modeSmall"); if (itemModeSmall != null) { itemModeSmall.setEnabled(true); itemModeSmall.getSkinButton().getSkinObject().switchSuffix( viewMode == MODE_BIGTABLE ? "" : "-down"); } ToolBarItem itemModeBig = tb.getToolBarItem("modeBig"); if (itemModeBig != null) { itemModeBig.setEnabled(true); itemModeBig.getSkinButton().getSkinObject().switchSuffix( viewMode == MODE_BIGTABLE ? "-down" : ""); } } return null; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#skinObjectHidden(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectHidden(SWTSkinObject skinObject, Object params) { return super.skinObjectHidden(skinObject, params); } public int getViewMode() { return viewMode; } public void setViewMode(int viewMode, boolean save) { if (viewMode >= modeViewIDs.length || viewMode < 0 || viewMode == this.viewMode) { return; } if (itemModeSmall != null) { itemModeSmall.getSkinButton().getSkinObject().switchSuffix( viewMode == MODE_BIGTABLE ? "" : "-down"); } if (itemModeBig != null) { itemModeBig.getSkinButton().getSkinObject().switchSuffix( viewMode == MODE_BIGTABLE ? "-down" : ""); } int oldViewMode = this.viewMode; this.viewMode = viewMode; if (oldViewMode >= 0 && oldViewMode < modeViewIDs.length) { SWTSkinObject soOldViewArea = getSkinObject(modeViewIDs[oldViewMode]); //SWTSkinObject soOldViewArea = skin.getSkinObjectByID(modeIDs[oldViewMode]); if (soOldViewArea != null) { soOldViewArea.setVisible(false); } } SelectedContentManager.clearCurrentlySelectedContent(); SWTSkinObject soViewArea = getSkinObject(modeViewIDs[viewMode]); if (soViewArea == null) { soViewArea = skin.createSkinObject(modeIDs[viewMode] + torrentFilterMode, modeIDs[viewMode], soListArea); skin.layout(); soViewArea.setVisible(true); soViewArea.getControl().setLayoutData(Utils.getFilledFormData()); } else { soViewArea.setVisible(true); } if (save) { COConfigurationManager.setParameter(torrentFilter + ".viewmode", viewMode); } String entryID = null; if (torrentFilterMode == TORRENTS_ALL) { entryID = SideBar.SIDEBAR_SECTION_LIBRARY; } else if (torrentFilterMode == TORRENTS_COMPLETE) { entryID = SideBar.SIDEBAR_SECTION_LIBRARY_CD; } else if (torrentFilterMode == TORRENTS_INCOMPLETE) { entryID = SideBar.SIDEBAR_SECTION_LIBRARY_DL; } else if (torrentFilterMode == TORRENTS_UNOPENED) { entryID = SideBar.SIDEBAR_SECTION_LIBRARY_UNOPENED; } if (entryID != null) { SideBarEntrySWT entry = SideBar.getEntry(entryID); if (entry != null) { entry.setLogID(entryID + "-" + viewMode); } } } public static void setupViewTitle() { final ViewTitleInfo titleInfoDownloading = new ViewTitleInfo() { public Object getTitleInfoProperty(int propertyID) { if (propertyID == TITLE_INDICATOR_TEXT) { if (numIncomplete > 0) return numIncomplete + ""; // + " of " + numIncomplete; } if (propertyID == TITLE_INDICATOR_TEXT_TOOLTIP) { return "There are " + numIncomplete + " incomplete torrents, " + numDownloading + " of which are currently downloading"; } return null; } }; SideBarEntrySWT infoDL = SideBar.getEntry(SideBar.SIDEBAR_SECTION_LIBRARY_DL); if (infoDL != null) { SideBarVitalityImage vitalityImage = infoDL.addVitalityImage(ID_VITALITY_ACTIVE); vitalityImage.setVisible(false); vitalityImage = infoDL.addVitalityImage(ID_VITALITY_ALERT); vitalityImage.setVisible(false); infoDL.setTitleInfo(titleInfoDownloading); if (!DL_VITALITY_CONSTANT) { SimpleTimer.addPeriodicEvent("DLVitalityRefresher", DL_VITALITY_REFRESH_RATE, new TimerEventPerformer() { public void perform(TimerEvent event) { SideBarEntrySWT entry = SideBar.getEntry(SideBar.SIDEBAR_SECTION_LIBRARY_DL); SideBarVitalityImage[] vitalityImages = entry.getVitalityImages(); for (int i = 0; i < vitalityImages.length; i++) { SideBarVitalityImage vitalityImage = vitalityImages[i]; if (vitalityImage.getImageID().equals(ID_VITALITY_ACTIVE)) { refreshDLSpinner((SideBarVitalityImageSWT) vitalityImage); } } } }); } } final ViewTitleInfo titleInfoSeeding = new ViewTitleInfo() { public Object getTitleInfoProperty(int propertyID) { if (propertyID == TITLE_INDICATOR_TEXT) { return null; //numSeeding + " of " + numComplete; } if (propertyID == TITLE_INDICATOR_TEXT_TOOLTIP) { return "There are " + numComplete + " complete torrents, " + numSeeding + " of which are currently seeding"; } return null; } }; SideBarEntrySWT infoCD = SideBar.getEntry(SideBar.SIDEBAR_SECTION_LIBRARY_CD); if (infoCD != null) { SideBarVitalityImage vitalityImage = infoCD.addVitalityImage(ID_VITALITY_ALERT); vitalityImage.setVisible(false); infoCD.setTitleInfo(titleInfoSeeding); } SideBarEntrySWT infoLibraryUn = SideBar.getEntry(SideBar.SIDEBAR_SECTION_LIBRARY_UNOPENED); if (infoLibraryUn != null) { infoLibraryUn.setTitleInfo(new ViewTitleInfo() { public Object getTitleInfoProperty(int propertyID) { if (propertyID == TITLE_INDICATOR_TEXT && numUnOpened > 0) { return "" + numUnOpened; } return null; } }); } AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { setupViewTitleWithCore(core); } }); PlatformTorrentUtils.addHasBeenOpenedListener(new HasBeenOpenedListener() { public void hasBeenOpenedChanged(DownloadManager dm, boolean opened) { recountUnopened(); refreshAllLibraries(); } }); } protected static void setupViewTitleWithCore(AzureusCore core) { final GlobalManager gm = core.getGlobalManager(); final DownloadManagerListener dmListener = new DownloadManagerAdapter() { public void stateChanged(DownloadManager dm, int state) { if (PlatformTorrentUtils.isAdvancedViewOnly(dm)) { return; } if (dm.getAssumedComplete()) { boolean isSeeding = dm.getState() == DownloadManager.STATE_SEEDING; Boolean wasSeedingB = (Boolean) dm.getUserData("wasSeeding"); boolean wasSeeding = wasSeedingB == null ? false : wasSeedingB.booleanValue(); if (isSeeding != wasSeeding) { if (isSeeding) { numSeeding++; } else { numSeeding--; } dm.setUserData("wasSeeding", new Boolean(isSeeding)); } } else { boolean isDownloading = dm.getState() == DownloadManager.STATE_DOWNLOADING; Boolean wasDownloadingB = (Boolean) dm.getUserData("wasDownloading"); boolean wasDownloading = wasDownloadingB == null ? false : wasDownloadingB.booleanValue(); if (isDownloading != wasDownloading) { if (isDownloading) { numDownloading++; } else { numDownloading--; } dm.setUserData("wasDownloading", new Boolean(isDownloading)); } } boolean complete = dm.getAssumedComplete(); Boolean wasErrorStateB = (Boolean) dm.getUserData("wasErrorState"); boolean wasErrorState = wasErrorStateB == null ? false : wasErrorStateB.booleanValue(); boolean isErrorState = state == DownloadManager.STATE_ERROR; if (isErrorState != wasErrorState) { int rel = isErrorState ? 1 : -1; if (complete) { numErrorComplete += rel; } else { numErrorInComplete += rel; } updateErrorTooltip(); dm.setUserData("wasErrorState", new Boolean(isErrorState)); } refreshAllLibraries(); } public void completionChanged(DownloadManager dm, boolean completed) { if (PlatformTorrentUtils.isAdvancedViewOnly(dm)) { return; } if (completed) { numComplete++; numIncomplete--; if (dm.getState() == DownloadManager.STATE_ERROR) { numErrorComplete++; numErrorInComplete--; } } else { numIncomplete++; numComplete--; if (dm.getState() == DownloadManager.STATE_ERROR) { numErrorComplete--; numErrorInComplete++; } } recountUnopened(); updateErrorTooltip(); refreshAllLibraries(); } protected void updateErrorTooltip() { if (numErrorComplete < 0) { numErrorComplete = 0; } if (numErrorInComplete < 0) { numErrorInComplete = 0; } if (numErrorComplete > 0 || numErrorInComplete > 0) { String comp_error = null; String incomp_error = null; List downloads = gm.getDownloadManagers(); for (int i = 0; i < downloads.size(); i++) { DownloadManager download = (DownloadManager) downloads.get(i); if (download.getState() == DownloadManager.STATE_ERROR) { if (download.getAssumedComplete()) { if (comp_error == null) { comp_error = download.getDisplayName() + ": " + download.getErrorDetails(); } else { comp_error += "..."; } } else { if (incomp_error == null) { incomp_error = download.getDisplayName() + ": " + download.getErrorDetails(); } else { incomp_error += "..."; } } } } errorCompleteTooltip = comp_error; errorInCompleteTooltip = incomp_error; } } }; gm.addListener(new GlobalManagerAdapter() { public void downloadManagerRemoved(DownloadManager dm) { if (PlatformTorrentUtils.isAdvancedViewOnly(dm)) { return; } recountUnopened(); if (dm.getAssumedComplete()) { numComplete--; Boolean wasDownloadingB = (Boolean) dm.getUserData("wasDownloading"); if (wasDownloadingB != null && wasDownloadingB.booleanValue()) { numDownloading--; } } else { numIncomplete--; Boolean wasSeedingB = (Boolean) dm.getUserData("wasSeeding"); if (wasSeedingB != null && wasSeedingB.booleanValue()) { numSeeding--; } } refreshAllLibraries(); dm.removeListener(dmListener); } public void downloadManagerAdded(DownloadManager dm) { if (PlatformTorrentUtils.isAdvancedViewOnly(dm)) { return; } dm.addListener(dmListener, false); recountUnopened(); if (dm.getAssumedComplete()) { numComplete++; if (dm.getState() == DownloadManager.STATE_SEEDING) { numSeeding++; } } else { numIncomplete++; if (dm.getState() == DownloadManager.STATE_DOWNLOADING) { dm.setUserData("wasDownloading", new Boolean(true)); numSeeding++; } else { dm.setUserData("wasDownloading", new Boolean(false)); } } refreshAllLibraries(); } }, false); List downloadManagers = gm.getDownloadManagers(); for (Iterator iter = downloadManagers.iterator(); iter.hasNext();) { DownloadManager dm = (DownloadManager) iter.next(); if (PlatformTorrentUtils.isAdvancedViewOnly(dm)) { continue; } dm.addListener(dmListener, false); if (dm.getAssumedComplete()) { numComplete++; if (dm.getState() == DownloadManager.STATE_SEEDING) { dm.setUserData("wasSeeding", new Boolean(true)); numSeeding++; } else { dm.setUserData("wasSeeding", new Boolean(false)); } } else { numIncomplete++; if (dm.getState() == DownloadManager.STATE_DOWNLOADING) { numSeeding++; } } } recountUnopened(); } private static void recountUnopened() { if (!AzureusCoreFactory.isCoreRunning()) { return; } GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); List dms = gm.getDownloadManagers(); numUnOpened = 0; for (Iterator iter = dms.iterator(); iter.hasNext();) { DownloadManager dm = (DownloadManager) iter.next(); if (!PlatformTorrentUtils.getHasBeenOpened(dm) && dm.getAssumedComplete()) { numUnOpened++; } } } /** * * * @since 3.1.1.1 */ protected static void refreshAllLibraries() { SideBarEntrySWT entry = SideBar.getEntry(SideBar.SIDEBAR_SECTION_LIBRARY_DL); SideBarVitalityImage[] vitalityImages = entry.getVitalityImages(); for (int i = 0; i < vitalityImages.length; i++) { SideBarVitalityImage vitalityImage = vitalityImages[i]; if (vitalityImage.getImageID().equals(ID_VITALITY_ACTIVE)) { vitalityImage.setVisible(numDownloading > 0); refreshDLSpinner((SideBarVitalityImageSWT) vitalityImage); } else if (vitalityImage.getImageID().equals(ID_VITALITY_ALERT)) { vitalityImage.setVisible(numErrorInComplete > 0); if (numErrorInComplete > 0) { vitalityImage.setToolTip(errorInCompleteTooltip); } } } ViewTitleInfoManager.refreshTitleInfo(entry.getTitleInfo()); entry = SideBar.getEntry(SideBar.SIDEBAR_SECTION_LIBRARY_CD); vitalityImages = entry.getVitalityImages(); for (int i = 0; i < vitalityImages.length; i++) { SideBarVitalityImage vitalityImage = vitalityImages[i]; if (vitalityImage.getImageID().equals(ID_VITALITY_ALERT)) { vitalityImage.setVisible(numErrorComplete > 0); if (numErrorComplete > 0) { vitalityImage.setToolTip(errorCompleteTooltip); } } } entry = SideBar.getEntry(SideBar.SIDEBAR_SECTION_LIBRARY_UNOPENED); ViewTitleInfoManager.refreshTitleInfo(entry.getTitleInfo()); } public static void refreshDLSpinner(SideBarVitalityImageSWT vitalityImage) { if (DL_VITALITY_CONSTANT) { return; } if (vitalityImage.getImageID().equals(ID_VITALITY_ACTIVE)) { if (!vitalityImage.isVisible()) { return; } SpeedManager sm = AzureusCoreFactory.getSingleton().getSpeedManager(); if (sm != null) { GlobalManagerStats stats = AzureusCoreFactory.getSingleton().getGlobalManager().getStats(); int delay = 100; int limit = NetworkManager.getMaxDownloadRateBPS(); if (limit <= 0) { limit = sm.getEstimatedDownloadCapacityBytesPerSec().getBytesPerSec(); } // smoothing int current = stats.getDataReceiveRate() / 10; limit /= 10; if (limit > 0) { if (current > limit) { delay = 25; } else { // 40 incrememnts of 5.. max 200 current += 39; delay = (40 - (current * 40 / limit)) * 5; if (delay < 35) { delay = 35; } else if (delay > 200) { delay = 200; } } if (vitalityImage instanceof SideBarVitalityImageSWT) { SideBarVitalityImageSWT viSWT = (SideBarVitalityImageSWT) vitalityImage; if (viSWT.getDelayTime() != delay) { viSWT.setDelayTime(delay); //System.out.println("new delay: " + delay + "; via " + current + " / " + limit); } } } } } } public static String getTableIdFromFilterMode(int torrentFilterMode, boolean big) { if (torrentFilterMode == SBC_LibraryView.TORRENTS_COMPLETE) { return big ? TableManager.TABLE_MYTORRENTS_COMPLETE_BIG : TableManager.TABLE_MYTORRENTS_COMPLETE; } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_INCOMPLETE) { return big ? TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG : TableManager.TABLE_MYTORRENTS_INCOMPLETE; } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_UNOPENED) { return big ? TableManager.TABLE_MYTORRENTS_UNOPENED_BIG : TableManager.TABLE_MYTORRENTS_UNOPENED; } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_ALL) { return TableManager.TABLE_MYTORRENTS_ALL_BIG; } return null; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java0000644000175000017500000005606111267524522027310 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.views.skin; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.util.Map; import org.eclipse.swt.program.Program; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.download.ForceRecheckListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadException; import org.gudy.azureus2.pluginsimpl.local.download.DownloadImpl; import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import com.aelitis.azureus.activities.VuzeActivitiesEntry; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.download.DownloadManagerEnhancer; import com.aelitis.azureus.core.download.EnhancedDownloadManager; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.core.vuzefile.VuzeFileComponent; import com.aelitis.azureus.core.vuzefile.VuzeFileHandler; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.UserPrompterResultListener; import com.aelitis.azureus.ui.common.table.TableRowCore; import com.aelitis.azureus.ui.common.table.TableView; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfoContentNetwork; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.browser.listener.DownloadUrlInfoSWT; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility; import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3; import com.aelitis.azureus.util.ContentNetworkUtils; import com.aelitis.azureus.util.DLReferals; import com.aelitis.azureus.util.DataSourceUtils; import com.aelitis.azureus.util.PlayUtils; import com.aelitis.azureus.util.win32.Win32Utils; /** * @author TuxPaper * @created Oct 12, 2006 * */ public class TorrentListViewsUtils { public static final boolean ENABLE_ON_HOVER = false; /** * @param dm * * @since 3.0.1.5 */ public static void stop(DownloadManager dm) { int state = dm.getState(); if (state == DownloadManager.STATE_ERROR) { dm.stopIt(DownloadManager.STATE_QUEUED, false, false); } else if (state == DownloadManager.STATE_STOPPED) { ManagerUtils.queue(dm, null); } else { ManagerUtils.stop(dm, null); } } public static void viewDetails(TableRowCore row, String ref) { Object ds = row.getDataSource(true); viewDetails(DataSourceUtils.getContentNetwork(ds), DataSourceUtils.getHash(ds), ref); } public static boolean canViewDetails(DownloadManager dm) { if (dm == null) { return( false ); } if (!PlatformTorrentUtils.isContent(dm.getTorrent(), true)) { return( false ); } try{ return( canViewDetails(DataSourceUtils.getContentNetwork(dm.getTorrent()), dm.getTorrent().getHashWrapper().toBase32String())); } catch (Throwable e) { Debug.out(e); return( false ); } } public static void viewDetails(DownloadManager dm, String ref) { if (dm == null) { return; } if (!PlatformTorrentUtils.isContent(dm.getTorrent(), true)) { return; } try { viewDetails(DataSourceUtils.getContentNetwork(dm.getTorrent()), dm.getTorrent().getHashWrapper().toBase32String(), ref); } catch (Throwable e) { Debug.out(e); } } public static void viewDetails(ContentNetwork cn, String hash, String ref) { if (hash == null || cn == null) { return; } String url = cn.getContentDetailsService( hash, ref ); UIFunctions functions = UIFunctionsManager.getUIFunctions(); if (functions != null) { functions.viewURL(url, ContentNetworkUtils.getTarget(cn), ref); } } public static boolean canViewDetails(ContentNetwork cn, String hash) { if (hash == null || cn == null ) { return( false ); } String url = cn.getContentDetailsService( hash, "" ); UIFunctions functions = UIFunctionsManager.getUIFunctions(); return( functions != null && url != null ); } public static String getDetailsURL( DownloadManager dm ) { try { ContentNetwork cn = DataSourceUtils.getContentNetwork(dm.getTorrent()); if ( cn == null ){ return( null ); } TOTorrent torrent = dm.getTorrent(); if ( torrent == null ){ return( null ); } String hash = torrent.getHashWrapper().toBase32String(); String url = cn.getContentDetailsService( hash, "" ); return( url ); }catch(Throwable e ){ Debug.out(e); return( null ); } } /** * @param ds * @param ref * * @since 4.0.0.5 */ public static void viewDetailsFromDS(Object ds, String ref) { String hash = DataSourceUtils.getHash(ds); if (hash == null) { return; } viewDetails(DataSourceUtils.getContentNetwork(ds), hash, ref); } public static void playOrStreamDataSource(Object ds, SWTSkinButtonUtility btn) { String referal = DLReferals.DL_REFERAL_UNKNOWN; if (ds instanceof VuzeActivitiesEntry) { referal = DLReferals.DL_REFERAL_PLAYDASHACTIVITY; } else if (ds instanceof DownloadManager) { referal = DLReferals.DL_REFERAL_PLAYDM; } else if (ds instanceof ISelectedContent) { referal = DLReferals.DL_REFERAL_SELCONTENT; } playOrStreamDataSource(ds, btn, referal); } public static void playOrStreamDataSource(Object ds, SWTSkinButtonUtility btn, String referal) { DownloadManager dm = DataSourceUtils.getDM(ds); if (dm == null) { downloadDataSource(ds, true, referal); } else { playOrStream(dm, btn); } } public static void downloadDataSource(Object ds, boolean playNow, String referal) { TOTorrent torrent = DataSourceUtils.getTorrent(ds); // handle encapsulated vuze file try{ Map torrent_map = torrent.serialiseToMap(); torrent_map.remove( "info" ); VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile( torrent_map ); if ( vf != null ){ VuzeFileHandler.getSingleton().handleFiles( new VuzeFile[]{ vf }, VuzeFileComponent.COMP_TYPE_NONE ); return; } }catch( Throwable e ){ } // we want to re-download the torrent if it's ours, since the existing // one is likely stale if (torrent != null && !DataSourceUtils.isPlatformContent(ds)) { TorrentUIUtilsV3.addTorrentToGM(torrent); } else { DownloadUrlInfo dlInfo = DataSourceUtils.getDownloadInfo(ds); if (dlInfo instanceof DownloadUrlInfoSWT) { TorrentUIUtilsV3.loadTorrent(dlInfo, playNow, false, true, true); return; } String hash = DataSourceUtils.getHash(ds); if (hash != null) { ContentNetwork cn = DataSourceUtils.getContentNetwork(ds); if (cn == null) { return; } if (ds instanceof VuzeActivitiesEntry) { if (((VuzeActivitiesEntry) ds).isDRM()) { TorrentListViewsUtils.viewDetails(cn, hash, "drm-play"); return; } } String url = cn.getTorrentDownloadService(hash, referal); dlInfo = new DownloadUrlInfoContentNetwork(url, cn); TorrentUIUtilsV3.loadTorrent(dlInfo, playNow, false, true, true); } else if (dlInfo != null) { TorrentUIUtilsV3.loadTorrent(dlInfo, playNow, false, true, true); } } } public static void playOrStream(final DownloadManager dm, final SWTSkinButtonUtility btn) { _playOrStream(dm, btn); } private static void _playOrStream(final DownloadManager dm, final SWTSkinButtonUtility btn) { if (dm == null) { return; } // if (!canPlay(dm)) { // return false; // } final TOTorrent torrent = dm.getTorrent(); if (PlayUtils.canUseEMP(torrent)) { debug("Can use EMP"); if (openInEMP(dm)) { PlatformTorrentUtils.setHasBeenOpened(dm, true); return; } else { debug("Open EMP Failed"); } // fallback to normal } else { debug("Can't use EMP. torrent says " + PlatformTorrentUtils.useEMP(torrent)); } if (btn != null) { btn.setDisabled(true); } boolean reenableButton = false; try { if (!PlayUtils.canProgressiveOrIsComplete(torrent)) { return; } File file; String sFile = null; EnhancedDownloadManager edm = DownloadManagerEnhancer.getSingleton().getEnhancedDownload( dm); if (edm != null) { boolean doProgressive = edm.getProgressiveMode(); if (doProgressive && edm.getProgressivePlayETA() > 0) { return; } if (!doProgressive && dm.getDiskManagerFileInfo().length > 1 && PlatformTorrentUtils.getContentPrimaryFileIndex(torrent) == -1) { // multi-file torrent that we aren't progressive playing or useEMPing Utils.launch(dm.getSaveLocation().getAbsolutePath()); reenableButton = true; PlatformTorrentUtils.setHasBeenOpened(dm, true); return; } file = edm.getPrimaryFile().getFile(true); sFile = file.getAbsolutePath(); } else { sFile = dm.getDownloadState().getPrimaryFile(); file = new File(sFile); } final String sfFile = sFile; String ext = FileUtil.getExtension(sFile); try { if (ext.equalsIgnoreCase(".exe") && DataSourceUtils.isPlatformContent(dm) && "Game".equalsIgnoreCase(PlatformTorrentUtils.getContentType(dm.getTorrent()))) { reenableButton = true; Utils.launch(sFile); PlatformTorrentUtils.setHasBeenOpened(dm, true); return; } } catch (Exception e) { Debug.out(e); } final String sPrefix = "v3.mb.openFile."; UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (functionsSWT == null) { return; } final Program program = Program.findProgram(ext); String sTextID; String sFileType; if (program == null) { sTextID = sPrefix + "text.unknown"; sFileType = ext; } else { sTextID = sPrefix + "text.known"; sFileType = program.getName(); } String[] buttons = new String[(program == null ? 2 : 3)]; buttons[0] = MessageText.getString(sPrefix + "button.guide"); buttons[buttons.length-1] = MessageText.getString(sPrefix + "button.cancel"); MessageBoxShell mb = null; if(program != null) { buttons[1] = MessageText.getString(sPrefix + "button.play"); mb = new MessageBoxShell(MessageText.getString(sPrefix + "title"), MessageText.getString(sTextID, new String[] { dm.getDisplayName(), sFileType, ext }), buttons, 0); mb.setRemember(sPrefix + ".remember_id", false, MessageText.getString(sPrefix + "remember")); mb.setRememberOnlyIfButton(1); mb.setRelatedObject(dm); } else { mb = new MessageBoxShell(MessageText.getString(sPrefix + "title"), MessageText.getString(sTextID, new String[] { dm.getDisplayName(), sFileType, ext }), buttons, 0); mb.setRelatedObject(dm); } reenableButton = false; mb.open(new UserPrompterResultListener() { public void prompterClosed(int i) { if(i == 0) { String url = MessageText.getString(sPrefix + "guideurl"); if(UrlUtils.isURL(url)) { Utils.launch(url); return; } } if (i != 1 || program == null) { return; } boolean bComplete = dm.isDownloadComplete(false); if (bComplete) { if (btn != null) { btn.setDisabled(false); } runFile(dm.getTorrent(), sfFile); } else { if (btn != null) { btn.setDisabled(false); } try { playViaMediaServer(DownloadManagerImpl.getDownloadStatic(dm)); } catch (DownloadException e) { Debug.out(e); } } } }); } finally { if (btn != null && reenableButton) { btn.setDisabled(false); } } } /** * @param string * * @since 3.0.3.3 */ private static void debug(String string) { if (org.gudy.azureus2.core3.util.Constants.isCVSVersion()) { System.out.println(string); } } private static void runFile(TOTorrent torrent, String runFile) { runFile(torrent, runFile, false); } private static void runFile(final TOTorrent torrent, final String runFile, final boolean forceWMP) { AEThread2 thread = new AEThread2("runFile", true) { public void run() { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (PlayUtils.canUseEMP(torrent)) { Debug.out("Shouldn't call runFile with EMP torrent."); } if (PlatformTorrentUtils.isContentDRM(torrent) || forceWMP) { if (!runInMediaPlayer(runFile)) { Utils.launch(runFile); } } else { Utils.launch(runFile); } } }); } }; thread.start(); } /** * New version accepts map with ASX parameters. If the params are null then is uses the * old version to start the player. If the * * * @param dm - DownloadManager * @return - boolean * @since 3.0.4.4 - */ private static boolean openInEMP(DownloadManager dm) { Class epwClass = null; try { // Assumed we have a core, since we are passed a // DownloadManager PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( "azemp"); if (pi == null) { return (false); } epwClass = pi.getPlugin().getClass().getClassLoader().loadClass( "com.azureus.plugins.azemp.ui.swt.emp.EmbeddedPlayerWindowSWT"); } catch (ClassNotFoundException e1) { return false; } //Data is passed to the openWindow via download manager. try { debug("EmbeddedPlayerWindowSWT - openWindow"); Method method = epwClass.getMethod("openWindow", new Class[] { DownloadManager.class }); method.invoke(null, new Object[] { dm }); return true; } catch (Throwable e) { e.printStackTrace(); if (e.getMessage() == null || !e.getMessage().toLowerCase().endsWith("only")) { Debug.out(e); } } return false; }//openInEMP /** * @param dm * * @since 3.0.0.7 */ private static void handleNoFileExists(final DownloadManager dm) { final UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (functionsSWT == null) { return; } ManagerUtils.start(dm); String sPrefix = "v3.mb.PlayFileNotFound."; MessageBoxShell mb = new MessageBoxShell( MessageText.getString(sPrefix + "title"), MessageText.getString(sPrefix + "text", new String[] { dm.getDisplayName(), }), new String[] { MessageText.getString(sPrefix + "button.remove"), MessageText.getString(sPrefix + "button.redownload"), MessageText.getString("Button.cancel"), }, 2); mb.setRelatedObject(dm); mb.open(new UserPrompterResultListener() { public void prompterClosed(int i) { if (i == 0) { ManagerUtils.remove(dm, functionsSWT.getMainShell(), true, false); } else if (i == 1) { dm.forceRecheck(new ForceRecheckListener() { public void forceRecheckComplete(DownloadManager dm) { ManagerUtils.start(dm); } }); } } }); } /** * @param string */ private static boolean runInMediaPlayer(String mediaFile) { if (Constants.isWindows) { String wmpEXE = Win32Utils.getWMP(); if (new File(wmpEXE).exists()) { try { Runtime.getRuntime().exec(wmpEXE + " \"" + mediaFile + "\""); return true; } catch (IOException e) { Debug.out("error playing " + mediaFile + " via WMP " + mediaFile, e); } } } return false; } /** * XXX DO NOT USE. Only for EMP <= 2.0.14 support * @param dm * @return */ public static String getMediaServerContentURL(DownloadManager dm) { try { return PlayUtils.getMediaServerContentURL(DownloadManagerImpl.getDownloadStatic(dm)); } catch (DownloadException e) { } return null; } /** * */ public static void playViaMediaServer(Download download) { try { final DownloadManager dm = ((DownloadImpl) download).getDownload(); TOTorrent torrent = dm.getTorrent(); runFile(torrent, PlayUtils.getContentUrl(dm), true); } catch (Throwable e) { Logger.log(new LogEvent(LogIDs.UI3, "IPC to media server plugin failed", e)); } } public static void removeDownloads(final DownloadManager[] dms) { if (dms == null) { return; } // confusing code: // for loop goes through erasing published and low noise torrents until // it reaches a normal one. We then prompt the user, and stop the loop. // When the user finally chooses an option, we act on it. If the user // chose to act on all, we do immediately all and quit. // If the user chose an action just for the one torrent, we do that action, // remove that item from the array (by nulling it), and then call // removeDownloads again so we can prompt again (or erase more published/low noise torrents) for (int i = 0; i < dms.length; i++) { DownloadManager dm = dms[i]; if (dm != null) { if (dm.getDownloadState().getFlag( Download.FLAG_DO_NOT_DELETE_DATA_ON_REMOVE)) { ManagerUtils.remove(dm, null, true, false, null); continue; } boolean deleteTorrent = true; boolean deleteData = true; if (!dm.getDownloadState().getFlag(DownloadManagerState.FLAG_LOW_NOISE)) { String title = MessageText.getString("deletedata.title"); String text = MessageText.getString("v3.deleteContent.message", new String[] { dm.getDisplayName() }); final MessageBoxShell mb = new MessageBoxShell(title, text, new String[] { MessageText.getString("Button.cancel"), MessageText.getString("Button.deleteContent.fromComputer"), MessageText.getString("Button.deleteContent.fromLibrary"), }, 2); int numLeft = (dms.length - i); if (numLeft > 1) { mb.setRemember("na", false, MessageText.getString( "v3.deleteContent.applyToAll", new String[] { "" + numLeft })); mb.setRememberOnlyIfButton(-3); } mb.setRelatedObject(dm); mb.setLeftImage(ImageLoader.getInstance().getImage("image.trash")); final int index = i; mb.open(new UserPrompterResultListener() { public void prompterClosed(int result) { ImageLoader.getInstance().releaseImage("image.trash"); if (result == -1) { // user pressed ESC (as opposed to clicked Cancel), cancel whole // list return; } if (mb.isRemembered()) { if (result == 1 || result == 2) { boolean deleteData = result == 2 ? false : true; boolean deleteTorrent = true; for (int i = index; i < dms.length; i++) { DownloadManager dm = dms[i]; ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED, deleteTorrent, deleteData, null); } } //else cancel } else { // not remembered if (result == 1 || result == 2) { boolean deleteData = result == 2 ? false : true; boolean deleteTorrent = true; DownloadManager dm = dms[index]; ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED, deleteTorrent, deleteData, null); } // remove the one we just did and go through loop again dms[index] = null; if (index != dms.length - 1) { removeDownloads(dms); } } } }); return; } else { ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED, deleteTorrent, deleteData, null); } dms[i] = null; }} } public static void removeDownload(final DownloadManager dm, final TableView tableView) { debug("removeDownload"); AERunnable failure = null; if (tableView != null) { tableView.removeDataSource(dm); tableView.processDataSourceQueue(); failure = new AERunnable() { public void runSupport() { tableView.addDataSource(dm); tableView.processDataSourceQueue(); } }; } final AERunnable ffailure = failure; if (dm.getDownloadState().getFlag( Download.FLAG_DO_NOT_DELETE_DATA_ON_REMOVE)) { ManagerUtils.remove(dm, null, true, false, failure); return; } boolean deleteTorrent = true; boolean deleteData = true; if (!dm.getDownloadState().getFlag(DownloadManagerState.FLAG_LOW_NOISE)) { String path = dm.getSaveLocation().toString(); String title = MessageText.getString("deletedata.title"); String text = MessageText.getString("v3.deleteContent.message", new String[] { dm.getDisplayName() }); MessageBoxShell mb = new MessageBoxShell(title, text, new String[] { MessageText.getString("Button.cancel"), MessageText.getString("Button.deleteContent.fromComputer"), MessageText.getString("Button.deleteContent.fromLibrary"), }, 2); mb.setRelatedObject(dm); mb.setLeftImage(ImageLoader.getInstance().getImage("image.trash")); mb.open(new UserPrompterResultListener() { public void prompterClosed(int result) { ImageLoader.getInstance().releaseImage("image.trash"); boolean deleteData = true; boolean deleteTorrent = true; if (result == 1 || result == 2) { if (result == 2) { deleteData = false; } ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED, deleteTorrent, deleteData, ffailure); } else { if (ffailure != null) { ffailure.runSupport(); } return; } } }); } else { ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED, deleteTorrent, deleteData, failure); } } /** * @param dm * * @since 3.0.2.3 */ public static void showHomeHint(final DownloadManager dm) { } public static void playOrStream(final DownloadManager dm) { playOrStream(dm, null); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/InfoBarUtil.java0000644000175000017500000001434411160651174025130 0ustar adrianadrian/** * Created on Mar 1, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.ui.common.RememberedDecisionsManager; import com.aelitis.azureus.ui.swt.skin.*; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter; /** * @author TuxPaper * @created Mar 1, 2009 * */ public abstract class InfoBarUtil { private final SWTSkinObject forSO; private final boolean top; private SWTSkin skin; private SWTSkinObject soInfoBar; private final String stateConfigID; private final String textPrefix; private final String skintemplateid; public InfoBarUtil(SWTSkinObject forSO, boolean top, final String stateConfigID, String textPrefix) { this(forSO, "library.top.info", top, stateConfigID, textPrefix); } public InfoBarUtil(final SWTSkinObject forSO, String skintemplateid, boolean top, final String stateConfigID, String textPrefix) { this.forSO = forSO; this.skintemplateid = skintemplateid; this.stateConfigID = stateConfigID; this.textPrefix = textPrefix; this.skin = forSO.getSkin(); this.top = top; // Migrate existing state config to remembered decision manager so user // can get them back if (COConfigurationManager.hasParameter( stateConfigID, true)) { RememberedDecisionsManager.setRemembered(stateConfigID, COConfigurationManager.getBooleanParameter(stateConfigID) ? 1 : 0); COConfigurationManager.removeParameter(stateConfigID); } forSO.addListener(new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == EVENT_SHOW) { forSO.removeListener(this); boolean show = RememberedDecisionsManager.getRememberedDecision(stateConfigID) != 0; if (show && allowShow() && soInfoBar == null) { createInfoBar(); } } return null; } }); } protected void createInfoBar() { Object ldForSO = forSO.getControl().getLayoutData(); if (!(ldForSO instanceof FormData)) { return; } FormData fdForSO = (FormData) ldForSO; SWTSkinObject parent = forSO.getParent(); soInfoBar = skin.createSkinObject("infobarutil", skintemplateid, parent); FormData fdInfoBar = (FormData) soInfoBar.getControl().getLayoutData(); if (fdInfoBar == null) { fdInfoBar = Utils.getFilledFormData(); } if (top) { fdInfoBar.top = new FormAttachment(fdForSO.top.control, fdForSO.top.offset, fdForSO.top.alignment); fdInfoBar.bottom = null; soInfoBar.getControl().setLayoutData(fdInfoBar); fdForSO.top = new FormAttachment(soInfoBar.getControl(), 0, SWT.BOTTOM); forSO.getControl().setLayoutData(fdForSO); } else { if (fdForSO.bottom.control == null) { fdInfoBar.bottom = new FormAttachment(fdForSO.bottom.numerator, fdForSO.bottom.denominator, fdForSO.bottom.offset); } else { fdInfoBar.bottom = new FormAttachment(fdForSO.bottom.control, fdForSO.bottom.offset, fdForSO.bottom.alignment); } fdInfoBar.top = null; soInfoBar.getControl().setLayoutData(fdInfoBar); fdForSO.bottom = new FormAttachment(soInfoBar.getControl(), 0, SWT.TOP); forSO.getControl().setLayoutData(fdForSO); } ((SWTSkinObjectContainer) parent).getComposite().layout(true); SWTSkinObject soClose = skin.getSkinObject("close", parent); if (soClose != null) { SWTSkinButtonUtility btnClose = new SWTSkinButtonUtility(soClose); btnClose.addSelectionListener(new ButtonListenerAdapter() { // @see com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter#pressed(com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility, com.aelitis.azureus.ui.swt.skin.SWTSkinObject, int) public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { soInfoBar.setVisible(false); RememberedDecisionsManager.setRemembered(stateConfigID, 0); } }); } soInfoBar.addListener(new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == EVENT_SHOW) { RememberedDecisionsManager.setRemembered(stateConfigID, 1); } return null; } }); SWTSkinObject soText1 = skin.getSkinObject("infobar-title-1", parent); if (soText1 instanceof SWTSkinObjectText) { SWTSkinObjectText soText = (SWTSkinObjectText) soText1; String id = textPrefix + ".text1"; if (MessageText.keyExists(id)) { soText.setTextID(id); } } SWTSkinObject soText2 = skin.getSkinObject("infobar-title-2", parent); if (soText2 instanceof SWTSkinObjectText) { SWTSkinObjectText soText = (SWTSkinObjectText) soText2; String id = textPrefix + ".text2"; if (MessageText.keyExists(id)) { soText.setTextID(id); } } created(parent); soInfoBar.setVisible(true); } /** * * * @param parent * @since 4.1.0.5 */ protected void created(SWTSkinObject parent) { } public void hide(boolean permanently) { if (soInfoBar != null && !soInfoBar.isDisposed()) { soInfoBar.setVisible(false); } if (permanently) { RememberedDecisionsManager.setRemembered(stateConfigID, 0); } } public void show() { RememberedDecisionsManager.setRemembered(stateConfigID, 1); if (soInfoBar == null) { createInfoBar(); } else { soInfoBar.setVisible(true); } } public abstract boolean allowShow(); }azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/SkinnedDialog.java0000644000175000017500000000650111223316350025453 0ustar adrianadrian/** * Created on Dec 23, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.skin.SWTSkin; import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory; /** * @author TuxPaper * @created Dec 23, 2008 * */ public class SkinnedDialog { private final String shellSkinObjectID; private Shell shell; private SWTSkin skin; private List closeListeners = new CopyOnWriteArrayList(); public SkinnedDialog(String skinFile, String shellSkinObjectID) { this(skinFile, shellSkinObjectID, SWT.DIALOG_TRIM | SWT.RESIZE); } public SkinnedDialog(String skinFile, String shellSkinObjectID, int style) { this.shellSkinObjectID = shellSkinObjectID; Shell mainShell = UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell(); shell = ShellFactory.createShell(mainShell, style); Utils.setShellIcon(shell); skin = SWTSkinFactory.getNonPersistentInstance( SkinnedDialog.class.getClassLoader(), "com/aelitis/azureus/ui/skin/", skinFile + ".properties"); skin.initialize(shell, shellSkinObjectID); shell.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { shell.close(); } } }); shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { //skin.destroy; for (SkinnedDialogClosedListener l : closeListeners) { try { l.skinDialogClosed(SkinnedDialog.this); } catch (Exception e2) { Debug.out(e2); } } } }); skin.layout(); Utils.centerWindowRelativeTo(shell, mainShell); } public void open() { shell.open(); } public SWTSkin getSkin() { return skin; } /** * * * @since 4.0.0.5 */ public void close() { shell.close(); } public void addCloseListener(SkinnedDialogClosedListener l) { closeListeners.add(l); } public interface SkinnedDialogClosedListener { public void skinDialogClosed(SkinnedDialog dialog); } /** * @param string * * @since 4.0.0.5 */ public void setTitle(String string) { if (shell != null && !shell.isDisposed()) { shell.setText(string); } } /** * @return the shell */ public Shell getShell() { return shell; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/views/skin/SkinView.java0000644000175000017500000000710511227757444024521 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.views.skin; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.swt.skin.*; /** * Converts {@link SWTSkinObjectListener} events to method calls, and * ensures we only "show" (initialize) once. *

    * Available SkinViews are managed by {@link SkinViewManager} * * @author TuxPaper * @created Sep 30, 2006 * */ public abstract class SkinView extends SWTSkinObjectAdapter { private boolean shownOnce; private boolean visible; protected SWTSkinObject soMain; protected SWTSkin skin; /** * */ public SkinView() { shownOnce = false; if (this instanceof UIUpdatable) { UIUpdatable updateable = (UIUpdatable) this; try { UIFunctionsManager.getUIFunctions().getUIUpdater().addUpdater( updateable); } catch (Exception e) { Debug.out(e); } } } /** * @return the visible */ public boolean isVisible() { return visible; } public Object skinObjectShown(SWTSkinObject skinObject, Object params) { setMainSkinObject(skinObject); visible = true; if (shownOnce) { return null; } shownOnce = true; try { return skinObjectInitialShow(skinObject, params); } catch (Exception e) { Debug.out(e); } return null; } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#skinObjectHidden(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectHidden(SWTSkinObject skinObject, Object params) { visible = false; return super.skinObjectHidden(skinObject, params); } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#skinObjectDestroyed(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectDestroyed(SWTSkinObject skinObject, Object params) { SkinViewManager.remove(this); if (this instanceof UIUpdatable) { UIUpdatable updateable = (UIUpdatable) this; try { UIFunctionsManager.getUIFunctions().getUIUpdater().removeUpdater( updateable); } catch (Exception e) { Debug.out(e); } } return null; } /** * @param skinObject * @param params * @return */ public abstract Object skinObjectInitialShow(SWTSkinObject skinObject, Object params); public SWTSkinObject getMainSkinObject() { return soMain; } final public void setMainSkinObject(SWTSkinObject main) { if (soMain != null) { return; } soMain = main; if (soMain != null) { skin = soMain.getSkin(); } SkinViewManager.add(this); } final public SWTSkin getSkin() { return skin; } final public SWTSkinObject getSkinObject(String viewID) { return skin.getSkinObject(viewID, soMain); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/UISkinnableSWTListener.java0000644000175000017500000000240210577641404025117 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt; import org.eclipse.swt.widgets.Composite; /** * @author TuxPaper * @created Mar 18, 2007 * */ public interface UISkinnableSWTListener { public void skinBeforeComponents(Composite composite, Object skinnableObject, Object[] relatedObjects); public void skinAfterComponents(Composite composite, Object skinnableObject, Object[] relatedObjects); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/Initializer.java0000644000175000017500000004231511271457300023131 0ustar adrianadrian/* * Created on May 29, 2006 2:13:41 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt; import java.io.File; import java.util.Iterator; import java.util.List; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerDownloadRemovalVetoException; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginEvent; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; import org.gudy.azureus2.ui.common.util.UserAlerts; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.auth.AuthenticatorWindow; import org.gudy.azureus2.ui.swt.auth.CertificateTrustWindow; import org.gudy.azureus2.ui.swt.auth.CryptoWindow; import org.gudy.azureus2.ui.swt.mainwindow.*; import org.gudy.azureus2.ui.swt.networks.SWTNetworkSelection; import org.gudy.azureus2.ui.swt.pluginsinstaller.InstallPluginWizard; import org.gudy.azureus2.ui.swt.progress.ProgressWindow; import org.gudy.azureus2.ui.swt.update.UpdateMonitor; import org.gudy.azureus2.ui.swt.updater2.PreUpdateChecker; import org.gudy.azureus2.ui.swt.updater2.SWTUpdateChecker; import com.aelitis.azureus.core.*; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.messenger.ClientMessageContext; import com.aelitis.azureus.core.messenger.PlatformMessenger; import com.aelitis.azureus.core.messenger.config.PlatformConfigMessenger; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.launcher.Launcher; import com.aelitis.azureus.ui.IUIIntializer; import com.aelitis.azureus.ui.InitializerListener; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.swt.browser.listener.*; import com.aelitis.azureus.ui.swt.browser.msg.MessageDispatcherSWT; import com.aelitis.azureus.ui.swt.content.RelatedContentUI; import com.aelitis.azureus.ui.swt.devices.DeviceManagerUI; import com.aelitis.azureus.ui.swt.shells.main.MainWindow; import com.aelitis.azureus.ui.swt.subscriptions.SubscriptionManagerUI; import com.aelitis.azureus.ui.swt.utils.UIMagnetHandler; import com.aelitis.azureus.util.InitialisationFunctions; /** * @author TuxPaper * @created May 29, 2006 * */ public class Initializer implements IUIIntializer { // Whether to initialize the UI before the core has been started private static boolean STARTUP_UIFIRST = System.getProperty("ui.startfirst", "1").equals("1"); // Used in debug to find out how long initialization took public static final long startTime = System.currentTimeMillis(); private static StartServer startServer; private final AzureusCore core; private final String[] args; private CopyOnWriteList listeners = new CopyOnWriteList(); private AEMonitor listeners_mon = new AEMonitor("Initializer:l"); private int curPercent = 0; private AESemaphore init_task = new AESemaphore("delayed init"); private MainWindow mainWindow; private static Initializer lastInitializer; public static void main(final String args[]) { if (Launcher.checkAndLaunch(Initializer.class, args)) return; if (System.getProperty("ui.temp") == null) { System.setProperty("ui.temp", "az3"); } org.gudy.azureus2.ui.swt.Main.main(args); } /** * Main Initializer. Usually called by reflection * @param core * @param args */ public Initializer(AzureusCore core, boolean createSWTThreadAndRun, String[] args) { this.core = core; this.args = args; lastInitializer = this; if (createSWTThreadAndRun) { try { SWTThread.createInstance(this); } catch (SWTThreadAlreadyInstanciatedException e) { Debug.printStackTrace(e); } } else { initializePlatformClientMessageContext(); new AEThread2("cleanupOldStuff", true) { public void run() { cleanupOldStuff(); } }.start(); PlatformConfigMessenger.login(ContentNetwork.CONTENT_NETWORK_VUZE, 0); // typically the caller will call run() now } } private void cleanupOldStuff() { File v3Shares = new File(SystemProperties.getUserPath(), "v3shares"); if (v3Shares.isDirectory()) { FileUtil.recursiveDeleteNoCheck(v3Shares); } File dirFriends = new File(SystemProperties.getUserPath(), "friends"); if (dirFriends.isDirectory()) { FileUtil.recursiveDeleteNoCheck(dirFriends); } File dirMedia = new File(SystemProperties.getUserPath(), "media"); if (dirMedia.isDirectory()) { FileUtil.recursiveDeleteNoCheck(dirMedia); } deleteConfig("v3.Friends.dat"); deleteConfig("unsentdata.config"); AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(final AzureusCore core) { new AEThread2("cleanupOldStuff", true) { public void run() { GlobalManager gm = core.getGlobalManager(); List dms = gm.getDownloadManagers(); for (Object o : dms) { DownloadManager dm = (DownloadManager) o; if (dm != null) { String val = PlatformTorrentUtils.getContentMapString( dm.getTorrent(), "Ad ID"); if (val != null) { try { gm.removeDownloadManager(dm, true, true); } catch (Exception e) { } } } } } }.start(); } }); } private void deleteConfig(String name) { try { File file = new File(SystemProperties.getUserPath(), name); if (file.exists()) { file.delete(); } } catch (Exception e) { } try { File file = new File(SystemProperties.getUserPath(), name + ".bak"); if (file.exists()) { file.delete(); } } catch (Exception e) { } } public void runInSWTThread() { COConfigurationManager.setBooleanDefault("ui.startfirst", true); STARTUP_UIFIRST = STARTUP_UIFIRST && COConfigurationManager.getBooleanParameter("ui.startfirst", true); if (!STARTUP_UIFIRST) { return; } // Ensure colors initialized Colors.getInstance(); UIConfigDefaultsSWT.initialize(); UIConfigDefaultsSWTv3.initialize(core); mainWindow = new MainWindow(Display.getDefault(), this); } public void run() { DelayedTask delayed_task = UtilitiesImpl.addDelayedTask( "SWT Initialisation", new Runnable() { public void run() { init_task.reserve(); } }); delayed_task.queueFirst(); // initialise the SWT locale util long startTime = SystemTime.getCurrentTime(); new LocaleUtilSWT(core); final Display display = SWTThread.getInstance().getDisplay(); new UIMagnetHandler(core); if (!STARTUP_UIFIRST) { UIConfigDefaultsSWT.initialize(); UIConfigDefaultsSWTv3.initialize(core); } else { COConfigurationManager.setBooleanDefault("Show Splash", false); } if (COConfigurationManager.getBooleanParameter("Show Splash")) { display.asyncExec(new AERunnable() { public void runSupport() { new SplashWindow(display, Initializer.this); } }); } System.out.println("Locale Initializing took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); core.addListener(new AzureusCoreListener() { int fakePercent = Math.min(70, 100 - curPercent); long startTime = SystemTime.getCurrentTime(); long lastTaskTimeSecs = startTime / 500; String sLastTask; public void reportCurrentTask(AzureusCoreOperation op, String currentTask) { if (op.getOperationType() != AzureusCoreOperation.OP_INITIALISATION) { return; } Initializer.this.reportCurrentTask(currentTask); long now = SystemTime.getCurrentTime(); if (fakePercent > 0 && lastTaskTimeSecs != now / 200) { lastTaskTimeSecs = SystemTime.getCurrentTime() / 200; fakePercent--; Initializer.this.reportPercent(curPercent + 1); } if (sLastTask != null && !sLastTask.startsWith("Loading Torrent")) { long diff = now - startTime; if (diff > 10 && diff < 1000 * 60 * 5) { System.out.println(TimeFormatter.milliStamp() + " Core: " + diff + "ms for activity between '" + sLastTask + "' and '" + currentTask + "'"); } startTime = SystemTime.getCurrentTime(); } sLastTask = currentTask; //System.out.println(currentTask); } public void reportPercent(AzureusCoreOperation op, int percent) { /* if (op.getOperationType() != AzureusCoreOperation.OP_INITIALISATION) { return; } if (percent == 100) { long now = SystemTime.getCurrentTime(); long diff = now - startTime; if (diff > 10 && diff < 1000 * 60 * 5) { System.out.println(" Core: " + diff + "ms for " + sLastTask); } } */ // TODO Auto-generated method stub } }); core.addLifecycleListener(new AzureusCoreLifecycleAdapter() { private GlobalManager gm; public void componentCreated(AzureusCore core, AzureusCoreComponent component) { Initializer.this.reportPercent(curPercent + 1); if (component instanceof GlobalManager) { reportCurrentTaskByKey("splash.initializePlugins"); gm = (GlobalManager) component; InitialisationFunctions.earlyInitialisation(core); } } // @see com.aelitis.azureus.core.AzureusCoreLifecycleAdapter#started(com.aelitis.azureus.core.AzureusCore) public void started(AzureusCore core) { boolean main_window_will_report_complete = false; try { InitialisationFunctions.lateInitialisation(core); if (gm == null) { return; } // Ensure colors initialized Colors.getInstance(); Initializer.this.reportPercent(curPercent + 1); new UserAlerts(gm); reportCurrentTaskByKey("splash.initializeGui"); Initializer.this.reportPercent(curPercent + 1); Cursors.init(); Initializer.this.reportPercent(curPercent + 1); main_window_will_report_complete = true; if (STARTUP_UIFIRST) { mainWindow.init(core); } else { new MainWindow(core, Display.getDefault(), Initializer.this); } reportCurrentTaskByKey("splash.openViews"); SWTUpdateChecker.initialize(); PreUpdateChecker.initialize(core, COConfigurationManager.getStringParameter("ui")); UpdateMonitor.getSingleton(core); // setup the update monitor //Tell listeners that all is initialized : Alerts.initComplete(); //Finally, open torrents if any. for (int i = 0; i < args.length; i++) { try { TorrentOpener.openTorrent(args[i]); } catch (Throwable e) { Debug.printStackTrace(e); } } } finally{ if ( !main_window_will_report_complete ){ init_task.release(); } } } public void stopping(AzureusCore core) { Alerts.stopInitiated(); } public void stopped(AzureusCore core) { } public boolean syncInvokeRequired() { return (true); } public boolean requiresPluginInitCompleteBeforeStartedEvent() { return( false ); } public boolean stopRequested(AzureusCore _core) throws AzureusCoreException { return org.gudy.azureus2.ui.swt.mainwindow.Initializer.handleStopRestart(false); } public boolean restartRequested(final AzureusCore core) { return org.gudy.azureus2.ui.swt.mainwindow.Initializer.handleStopRestart(true); } }); reportCurrentTaskByKey("splash.initializeCore"); try{ new SubscriptionManagerUI(); }catch( Throwable e ){ Debug.printStackTrace(e); } try{ RelatedContentUI.getSingleton(); }catch( Throwable e ){ Debug.printStackTrace(e); } try{ new DeviceManagerUI( core ); }catch( Throwable e ){ Debug.printStackTrace(e); } core.start(); reportPercent(50); System.out.println("Core Initializing took " + (SystemTime.getCurrentTime() - startTime) + "ms"); startTime = SystemTime.getCurrentTime(); reportCurrentTaskByKey("splash.initializeUIElements"); // Ensure colors initialized Colors.getInstance(); reportPercent(curPercent + 1); Alerts.init(); reportPercent(curPercent + 1); ProgressWindow.register(core); reportPercent(curPercent + 1); new SWTNetworkSelection(); reportPercent(curPercent + 1); new AuthenticatorWindow(); new CryptoWindow(); reportPercent(curPercent + 1); new CertificateTrustWindow(); InstallPluginWizard.register(core, display); } public void stopIt(boolean isForRestart, boolean isCloseAreadyInProgress) throws AzureusCoreException { if (core != null && !isCloseAreadyInProgress) { if (isForRestart) { core.checkRestartSupported(); } } try { // Cursors.dispose(); try { UIFunctionsManager.getUIFunctions().getUIUpdater().stopIt(); } catch (Exception e) { Debug.out(e); } Utils.execSWTThread(new AERunnable() { public void runSupport() { SWTThread.getInstance().terminate(); } }); } finally { try{ if ( core != null && !isCloseAreadyInProgress) { try { if (isForRestart) { core.restart(); } else { long lStopStarted = System.currentTimeMillis(); System.out.println("core.stop"); core.stop(); System.out.println("core.stop done in " + (System.currentTimeMillis() - lStopStarted)); } } catch (Throwable e) { // don't let any failure here cause the stop operation to fail Debug.out(e); } } }finally{ // do this after closing core to minimise window when the we aren't // listening and therefore another Azureus start can potentially get // in and screw things up if (startServer != null) { startServer.stopIt(); } } } } // @see com.aelitis.azureus.ui.IUIIntializer#addListener(org.gudy.azureus2.ui.swt.mainwindow.InitializerListener) public void addListener(InitializerListener listener) { try { listeners_mon.enter(); listeners.add(listener); } finally { listeners_mon.exit(); } } // @see com.aelitis.azureus.ui.IUIIntializer#removeListener(org.gudy.azureus2.ui.swt.mainwindow.InitializerListener) public void removeListener(InitializerListener listener) { try { listeners_mon.enter(); listeners.remove(listener); } finally { listeners_mon.exit(); } } public void reportCurrentTask(String currentTaskString) { try { listeners_mon.enter(); Iterator iter = listeners.iterator(); while (iter.hasNext()) { InitializerListener listener = (InitializerListener) iter.next(); try { listener.reportCurrentTask(currentTaskString); } catch (Exception e) { // ignore } } } finally { listeners_mon.exit(); } } private void reportCurrentTaskByKey(String key) { reportCurrentTask(MessageText.getString(key)); } public void increaseProgress() { if (curPercent < 100) { reportPercent(curPercent + 1); } } // @see com.aelitis.azureus.ui.IUIIntializer#abortProgress() public void abortProgress() { reportPercent(101); } public void reportPercent(int percent) { if (curPercent > percent) { return; } curPercent = percent; try { listeners_mon.enter(); Iterator iter = listeners.iterator(); while (iter.hasNext()) { InitializerListener listener = (InitializerListener) iter.next(); try { listener.reportPercent(percent); } catch (Exception e) { // ignore } } if (percent > 100) { listeners.clear(); } } finally { listeners_mon.exit(); } } public void initializationComplete() { core.getPluginManager().firePluginEvent( PluginEvent.PEV_INITIALISATION_UI_COMPLETES ); new DelayedEvent( "SWTInitComplete:delay", 2500, new AERunnable() { public void runSupport() { //System.out.println("Release Init. Task"); init_task.release(); } }); } /** * * * @since 3.0.5.3 */ private void initializePlatformClientMessageContext() { ClientMessageContext clientMsgContext = PlatformMessenger.getClientMessageContext(); if (clientMsgContext != null) { clientMsgContext.setMessageDispatcher(new MessageDispatcherSWT(clientMsgContext)); clientMsgContext.addMessageListener(new TorrentListener()); clientMsgContext.addMessageListener(new VuzeListener()); clientMsgContext.addMessageListener(new DisplayListener(null)); clientMsgContext.addMessageListener(new ConfigListener(null)); } } public static Initializer getLastInitializer() { return lastInitializer; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/0000755000175000017500000000000011310377632021423 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/DeviceInfoArea.java0000644000175000017500000003217311227757444025112 0ustar adrianadrian/** * Created on Mar 2, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.devices.*; import com.aelitis.azureus.ui.common.RememberedDecisionsManager; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import com.aelitis.azureus.ui.swt.views.skin.SkinView; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.installer.*; import org.gudy.azureus2.plugins.update.UpdateCheckInstance; /** * @author TuxPaper * @created Mar 2, 2009 * */ public class DeviceInfoArea extends SkinView { private SideBarEntrySWT sidebarEntry; private DeviceMediaRenderer device; private Composite main; private Composite parent; // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectInitialShow(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { sidebarEntry = sidebar.getCurrentEntry(); device = (DeviceMediaRenderer) sidebarEntry.getDatasource(); } parent = (Composite) skinObject.getControl(); return null; } // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectShown(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectShown(SWTSkinObject skinObject, Object params) { super.skinObjectShown(skinObject, params); if (device == null) { initDeviceOverview(); } else { initDeviceView(); } return null; } // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectHidden(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectHidden(SWTSkinObject skinObject, Object params) { Utils.disposeComposite(main); return super.skinObjectHidden(skinObject, params); } /** * * * @since 4.1.0.5 */ private void initDeviceView() { main = new Composite( parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.marginTop = 4; layout.marginBottom = 4; layout.marginHeight = 4; layout.marginWidth = 4; main.setLayout(layout); GridData grid_data; main.setLayoutData(Utils.getFilledFormData()); // control Composite control = new Composite(main, SWT.NONE); layout = new GridLayout(); layout.numColumns = 3; layout.marginLeft = 0; control.setLayout(layout); // browse to local dir grid_data = new GridData(GridData.FILL_HORIZONTAL); grid_data.horizontalSpan = 1; control.setLayoutData(grid_data); Label dir_lab = new Label( control, SWT.NONE ); dir_lab.setText( "Local directory: " + device.getWorkingDirectory().getAbsolutePath()); Button show_folder_button = new Button( control, SWT.PUSH ); Messages.setLanguageText( show_folder_button, "MyTorrentsView.menu.explore"); show_folder_button.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { ManagerUtils.open( device.getWorkingDirectory()); } }); new Label( control, SWT.NONE ); if ( device.canFilterFilesView()){ final Button show_xcode_button = new Button( control, SWT.CHECK ); Messages.setLanguageText( show_xcode_button, "devices.xcode.only.show"); show_xcode_button.setSelection( device.getFilterFilesView()); show_xcode_button.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { device.setFilterFilesView( show_xcode_button.getSelection()); } }); } final Button btnReset = new Button(main, SWT.PUSH); btnReset.setText("Forget Default Profile Choice"); btnReset.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { device.setDefaultTranscodeProfile(null); btnReset.setEnabled(false); } public void widgetDefaultSelected(SelectionEvent e) { } }); try { btnReset.setEnabled(device.getDefaultTranscodeProfile() != null); } catch (TranscodeException e1) { btnReset.setEnabled(false); } btnReset.setLayoutData(new GridData()); parent.getParent().layout(); } protected void initDeviceOverview() { // DeviceInfoArea isn't used, but if it were we'd want to // do a check to see if Core is available yet.. final PluginInstaller installer = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInstaller(); boolean hasItunes = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( "azitunes") != null; main = new Composite( parent, SWT.NONE); main.setLayoutData(Utils.getFilledFormData()); FormLayout layout = new FormLayout(); layout.marginWidth = layout.marginHeight = 5; main.setLayout(layout); FormData fd; Control top; if (hasItunes) { Button itunes_button = new Button(main, SWT.NULL); top = itunes_button; itunes_button.setText("Install iTunes Integration"); itunes_button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { try { StandardPlugin itunes_plugin = installer.getStandardPlugin("azitunes"); itunes_plugin.install(false); } catch (Throwable e) { Debug.printStackTrace(e); } } }); fd = new FormData(); fd.left = new FormAttachment(0, 0); fd.top = new FormAttachment(0, 4); itunes_button.setLayoutData(fd); } else { Label lblItunesInstalled = new Label(main, SWT.WRAP); top = lblItunesInstalled; lblItunesInstalled.setText("iTunes support is available"); } if (Constants.isCVSVersion()) { //buildBetaArea(main, top); } parent.getParent().layout(); } private void buildBetaArea(Composite parent, Control above) { FormData fd; Group betaArea = new Group(parent, SWT.NONE); betaArea.setText("Beta Debug"); betaArea.setLayout(new FormLayout()); fd = Utils.getFilledFormData(); fd.top = new FormAttachment(above, 5); betaArea.setLayoutData(fd); fd = new FormData(); fd.left = new FormAttachment(0,0); fd.right = new FormAttachment(100,0); fd.top = new FormAttachment(0, 0); Label label = new Label( betaArea, SWT.NULL ); label.setText( "Transcode Providers:" ); label.setLayoutData( fd ); Button vuze_button = new Button( betaArea, SWT.NULL ); vuze_button.setText( "Install Vuze Transcoder" ); if (AzureusCoreFactory.isCoreRunning()) { final PluginInstaller installer = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInstaller(); StandardPlugin vuze_plugin = null; try{ vuze_plugin = installer.getStandardPlugin( "vuzexcode" ); }catch( Throwable e ){ } if ( vuze_plugin == null || vuze_plugin.isAlreadyInstalled()){ vuze_button.setEnabled( false ); } final StandardPlugin f_vuze_plugin = vuze_plugin; vuze_button.addListener( SWT.Selection, new Listener() { public void handleEvent( Event arg0 ) { try{ f_vuze_plugin.install( false ); }catch( Throwable e ){ Debug.printStackTrace(e); } } }); fd = new FormData(); fd.left = new FormAttachment(0,0); fd.top = new FormAttachment(label,4); vuze_button.setLayoutData( fd ); } Control top = vuze_button; TranscodeProvider[] providers = DeviceManagerFactory.getSingleton().getTranscodeManager().getProviders(); for ( TranscodeProvider provider: providers ){ fd = new FormData(); fd.left = new FormAttachment(0,10); fd.right = new FormAttachment(100,0); fd.top = new FormAttachment(top,4); Label prov_lab = new Label( betaArea, SWT.NULL ); prov_lab.setText( provider.getName()); prov_lab.setLayoutData( fd ); top = prov_lab; TranscodeProfile[] profiles = provider.getProfiles(); String line = null; for ( TranscodeProfile profile: profiles ){ if (line == null) { line = profile.getName(); } else { line += ", " + profile.getName(); } } if (line != null) { fd = new FormData(); fd.left = new FormAttachment(0,25); fd.right = new FormAttachment(100,0); fd.top = new FormAttachment(top,4); Label prof_lab = new Label( betaArea, SWT.WRAP ); prof_lab.setText("Profiles: " + line); prof_lab.setLayoutData( fd ); top = prof_lab; } } // both - installer test final Button both_button = new Button( betaArea, SWT.NULL ); both_button.setText( "Test! Install RSSGen and AZBlog!" ); if (AzureusCoreFactory.isCoreRunning()) { final PluginInstaller installer = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInstaller(); StandardPlugin plugin1 = null; StandardPlugin plugin2 = null; try{ plugin1 = installer.getStandardPlugin( "azrssgen" ); }catch( Throwable e ){ } try{ plugin2 = installer.getStandardPlugin( "azblog" ); }catch( Throwable e ){ } if ( plugin1 != null && plugin2 != null ){ final Composite install_area = new Composite( betaArea, SWT.BORDER ); fd = new FormData(); fd.left = new FormAttachment(both_button,0); fd.right = new FormAttachment(100,0); fd.top = new FormAttachment(top,4); fd.bottom = new FormAttachment(100,0); install_area.setLayoutData( fd ); final StandardPlugin f_plugin1 = plugin1; final StandardPlugin f_plugin2 = plugin2; both_button.addListener( SWT.Selection, new Listener() { public void handleEvent( Event arg0 ) { both_button.setEnabled( false ); try{ Map properties = new HashMap(); properties.put( UpdateCheckInstance.PT_UI_STYLE, UpdateCheckInstance.PT_UI_STYLE_SIMPLE ); properties.put( UpdateCheckInstance.PT_UI_PARENT_SWT_COMPOSITE, install_area ); properties.put( UpdateCheckInstance.PT_UI_DISABLE_ON_SUCCESS_SLIDEY, true ); installer.install( new InstallablePlugin[]{ f_plugin1, f_plugin2 }, false, properties, new PluginInstallationListener() { public void completed() { System.out.println( "Install completed!" ); tidy(); } public void cancelled() { System.out.println( "Install cancelled" ); tidy(); } public void failed( PluginException e ) { System.out.println( "Install failed: " + e ); tidy(); } protected void tidy() { Utils.execSWTThread( new Runnable() { public void run() { Control[] kids = install_area.getChildren(); for ( Control c: kids ){ c.dispose(); } both_button.setEnabled( true ); } }); } }); }catch( Throwable e ){ Debug.printStackTrace(e); } } }); }else{ both_button.setEnabled(false); } fd = new FormData(); fd.left = new FormAttachment(0,0); fd.top = new FormAttachment(top,4); fd.bottom = new FormAttachment(100,0); both_button.setLayoutData( fd ); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/0000755000175000017500000000000011310377632023103 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Duration.java0000644000175000017500000000337611160331424027307 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import com.aelitis.azureus.core.devices.TranscodeFile; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnTJ_Duration implements TableCellRefreshListener { public static final String COLUMN_ID = "duration"; public ColumnTJ_Duration(TableColumn column) { column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 85); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { TranscodeFile tf = (TranscodeFile) cell.getDataSource(); if (tf == null) { return; } long duration = tf.getDurationMillis(); cell.setText( duration==0?"":TimeFormatter.format( duration/1000 )); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Completion.java0000644000175000017500000001471611247605474027652 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import java.util.HashMap; import java.util.Locale; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.internat.MessageText.MessageTextListener; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import com.aelitis.azureus.core.devices.*; import com.aelitis.azureus.ui.common.table.impl.TableColumnImpl; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.utils.ColorCache; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnTJ_Completion implements TableCellAddedListener, TableCellRefreshListener, TableCellDisposeListener, TableCellSWTPaintListener { private static final int borderWidth = 1; public static final String COLUMN_ID = "trancode_completion"; private static Font fontText; private Map mapCellLastPercentDone = new HashMap(); private int marginHeight = -1; private String na_text; Color textColor; public ColumnTJ_Completion(final TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 145); column.addListeners(this); // cheat. TODO: Either auto-add (in above method), or provide // access via TableColumn instead of type casting ((TableColumnImpl)column).addCellOtherListener("SWTPaint", this); column.setType(TableColumn.TYPE_GRAPHIC); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); MessageText.addAndFireListener(new MessageTextListener() { public void localeChanged(Locale old_locale, Locale new_locale) { na_text = MessageText.getString( "general.na.short" ); column.invalidateCells(); } }); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellAdded(TableCell cell) { if (marginHeight != -1) { cell.setMarginHeight(marginHeight); } else { cell.setMarginHeight(2); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellDisposeListener#dispose(org.gudy.azureus2.plugins.ui.tables.TableCell) public void dispose(TableCell cell) { mapCellLastPercentDone.remove(cell); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { TranscodeFile tf = (TranscodeFile) cell.getDataSource(); int percentDone = getPerThouDone(tf); Integer intObj = (Integer) mapCellLastPercentDone.get(cell); int lastPercentDone = intObj == null ? 0 : intObj.intValue(); if (!cell.setSortValue(percentDone) && cell.isValid() && lastPercentDone == percentDone) { return; } } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT) public void cellPaint(GC gcImage, TableCellSWT cell) { TranscodeFile tf = (TranscodeFile) cell.getDataSource(); int perThouDone = getPerThouDone(tf); Rectangle bounds = cell.getBounds(); int yOfs = (bounds.height - 13) / 2 ; int x1 = bounds.width - borderWidth - 2; int y1 = bounds.height - 3 - yOfs; if (x1 < 10 || y1 < 3) { return; } mapCellLastPercentDone.put(cell, new Integer(perThouDone)); ImageLoader imageLoader = ImageLoader.getInstance(); Image imgEnd = imageLoader.getImage("tc_bar_end"); Image img0 = imageLoader.getImage("tc_bar_0"); Image img1 = imageLoader.getImage("tc_bar_1"); //draw begining and end if (!imgEnd.isDisposed()) { gcImage.drawImage(imgEnd, bounds.x , bounds.y + yOfs); gcImage.drawImage(imgEnd, bounds.x + x1 + 1, bounds.y + yOfs); } int limit = (x1 * perThouDone) / 1000; if (!img1.isDisposed() && limit > 0) { Rectangle imgBounds = img1.getBounds(); gcImage.drawImage(img1, 0, 0, imgBounds.width, imgBounds.height, bounds.x + 1, bounds.y + yOfs, limit, imgBounds.height); } if (perThouDone < 1000 && !img0.isDisposed()) { Rectangle imgBounds = img0.getBounds(); gcImage.drawImage(img0, 0, 0, imgBounds.width, imgBounds.height, bounds.x + limit + 1, bounds.y + yOfs, x1 - limit, imgBounds.height); } imageLoader.releaseImage("tc_bar_end"); imageLoader.releaseImage("tc_bar_0"); imageLoader.releaseImage("tc_bar_1"); if(textColor == null) { textColor = ColorCache.getColor(gcImage.getDevice(), "#006600" ); } gcImage.setForeground(textColor); if (fontText == null) { fontText = Utils.getFontWithHeight(gcImage.getFont(), gcImage, 10); } gcImage.setFont(fontText); String sText; if ( tf != null && perThouDone == 1000 && !tf.getTranscodeRequired()){ sText = na_text; }else{ sText = DisplayFormatters.formatPercentFromThousands(perThouDone); if ( tf != null && perThouDone < 1000 ){ String eta = getETA(tf); if ( eta != null ){ sText += " - " + eta; } } } GCStringPrinter.printString(gcImage, sText, new Rectangle(bounds.x + 4, bounds.y + yOfs, bounds.width - 4,13), true, false, SWT.CENTER); } private int getPerThouDone(TranscodeFile tf) { if (tf == null) { return 0; } TranscodeJob job = tf.getJob(); if (job == null) { return tf.isComplete()?1000:0; } return job.getPercentComplete()*10; } private String getETA(TranscodeFile tf) { if (tf == null) { return null; } TranscodeJob job = tf.getJob(); if (job == null) { return null; } return job.getETA(); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Name.java0000644000175000017500000000434011160623306026375 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText; import com.aelitis.azureus.core.devices.TranscodeFile; import com.aelitis.azureus.util.DataSourceUtils; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnTJ_Name implements TableCellRefreshListener, ObfusticateCellText, TableCellDisposeListener { public static final String COLUMN_ID = "transcode_name"; /** * * @param sTableID */ public ColumnTJ_Name(TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 215); column.addListeners(this); column.setObfustication(true); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); } public void refresh(TableCell cell) { TranscodeFile tf = (TranscodeFile) cell.getDataSource(); if (tf == null) { return; } String text = tf.getName(); if ( text == null || text.length() == 0 ){ return; } cell.setText(text); } public String getObfusticatedText(TableCell cell) { String name = null; DownloadManager dm = DataSourceUtils.getDM(cell.getDataSource()); if (dm != null) { name = dm.toString(); int i = name.indexOf('#'); if (i > 0) { name = name.substring(i + 1); } } if (name == null) name = ""; return name; } public void dispose(TableCell cell) { } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_CopiedToDevice.java0000644000175000017500000000514511231553254030352 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import java.util.Locale; import com.aelitis.azureus.core.devices.Device; import com.aelitis.azureus.core.devices.DeviceMediaRenderer; import com.aelitis.azureus.core.devices.TranscodeFile; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.internat.MessageText.MessageTextListener; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumn; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnTJ_CopiedToDevice implements TableCellRefreshListener { public static final String COLUMN_ID = "copied"; private String na_text; public ColumnTJ_CopiedToDevice(final TableColumn column) { column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, 50); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); MessageText.addAndFireListener(new MessageTextListener() { public void localeChanged(Locale old_locale, Locale new_locale) { na_text = MessageText.getString( "general.na.short" ); column.invalidateCells(); } }); } public void refresh(TableCell cell) { TranscodeFile tf = (TranscodeFile) cell.getDataSource(); if (tf == null) { return; } Device d = tf.getDevice(); String value = null; if ( d instanceof DeviceMediaRenderer ){ DeviceMediaRenderer dmr = (DeviceMediaRenderer)d; if (!(dmr.canCopyToDevice()|| dmr.canCopyToFolder())){ value = na_text; } } if ( value == null ){ value = DisplayFormatters.getYesNo( tf.isCopiedToDevice()); } if (cell.setSortValue(value) || !cell.isValid()) { cell.setText(value); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Status.java0000644000175000017500000000442511247605474027005 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import java.util.Locale; import com.aelitis.azureus.core.devices.DeviceOfflineDownload; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.internat.MessageText.MessageTextListener; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnOD_Status implements TableCellRefreshListener { public static final String COLUMN_ID = "od_status"; private static final String[] js_resource_keys = { "devices.od.idle", "devices.od.xfering", }; private static String[] js_resources = new String[js_resource_keys.length]; public ColumnOD_Status(final TableColumn column) { column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, 80); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); MessageText.addAndFireListener(new MessageTextListener() { public void localeChanged(Locale old_locale, Locale new_locale) { for (int i = 0; i < js_resources.length; i++) { js_resources[i] = MessageText.getString(js_resource_keys[i]); } column.invalidateCells(); } }); } public void refresh(TableCell cell) { DeviceOfflineDownload od = (DeviceOfflineDownload) cell.getDataSource(); if (od == null) { return; } String text = od.isTransfering()?js_resources[1]:js_resources[0]; if ( text == null || text.length() == 0 ){ return; } cell.setText(text); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Name.java0000644000175000017500000000315711247605474026403 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import com.aelitis.azureus.core.devices.DeviceOfflineDownload; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnOD_Name implements TableCellRefreshListener { public static final String COLUMN_ID = "od_name"; public ColumnOD_Name(TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 300); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); } public void refresh(TableCell cell) { DeviceOfflineDownload od = (DeviceOfflineDownload) cell.getDataSource(); if (od == null) { return; } String text = od.getDownload().getName(); if ( text == null || text.length() == 0 ){ return; } cell.setText(text); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Status.java0000644000175000017500000001176611161114042027003 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import java.util.Locale; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.internat.MessageText.MessageTextListener; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.TimeFormatter; import com.aelitis.azureus.core.devices.TranscodeFile; import com.aelitis.azureus.core.devices.TranscodeJob; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.ui.swt.Utils; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnTJ_Status implements TableCellRefreshListener { public static final String COLUMN_ID = "transcode_status"; private static final String[] js_resource_keys = { "ManagerItem.queued", "devices.converting", "ManagerItem.paused", "sidebar.LibraryCD", "Progress.reporting.status.canceled", "ManagerItem.error", // 5 "ManagerItem.stopped", "devices.copy.fail", // 7 "devices.on.demand", // 8 "devices.ready", // 9 "devices.downloading", // 10 }; private static String[] js_resources; private static String eta_text; public ColumnTJ_Status(final TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 160); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); MessageText.addAndFireListener(new MessageTextListener() { public void localeChanged(Locale old_locale, Locale new_locale) { js_resources = new String[js_resource_keys.length]; for (int i = 0; i < js_resources.length; i++) { js_resources[i] = MessageText.getString(js_resource_keys[i]); } eta_text = MessageText.getString( "TableColumn.header.eta" ); column.invalidateCells(); } }); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { TranscodeFile tf = (TranscodeFile) cell.getDataSource(); if (tf == null) { return; } TranscodeJob job = tf.getJob(); String tooltip = null; String text = null; boolean error = false; if ( job == null ){ try{ if ( tf.isComplete() && !tf.getTargetFile().getFile().exists()){ tooltip = "File '" + tf.getTargetFile().getFile().getAbsolutePath() + "' not found"; text = js_resources[5] + ": File not found"; error = true; } }catch( Throwable e ){ } if ( text == null ){ if ( tf.getCopyToDeviceFails() > 0 ){ text = js_resources[7]; error = true; }else if ( tf.isTemplate() && !tf.isComplete()){ text = js_resources[8]; }else{ text = js_resources[9]; } } }else{ int state = job.getState(); text = js_resources[state]; if ( state == TranscodeJob.ST_QUEUED ){ long eta = job.getDownloadETA(); if ( eta > 0 ){ text = js_resources[10] + ": " + eta_text + " " + ( eta==Long.MAX_VALUE?Constants.INFINITY_STRING:TimeFormatter.format( eta )); } }else{ text = js_resources[state]; if ( state == TranscodeJob.ST_FAILED ) { String error_msg = job.getError(); if ( error_msg != null ){ // error message can be very large and technical as it includes output // from ffmpeg error etc. So trim it back for user consumption. // currently we try to ensure that tech info appears after second // comma try{ int pos = error_msg.indexOf( '\n' ); if ( pos >= 0 ){ error_msg = error_msg.substring( 0, pos ); } pos = error_msg.indexOf( ',' ); if ( pos >= 0 ){ pos = error_msg.indexOf( ',', pos+1 ); if ( pos >= 0 ){ error_msg = error_msg.substring( 0, pos ); } } text += ": " + error_msg.trim(); }catch( Throwable e ){ } } tooltip = "See transcode log for more details"; error = true; } } } cell.setText( text ); cell.setToolTip(tooltip); if ( error){ cell.setForegroundToErrorColor(); }else{ cell.setForeground(Utils.colorToIntArray(null)); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnDevices_Name.java0000644000175000017500000000322611155100574027445 0ustar adrianadrian/** * Created on Feb 24, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn; import com.aelitis.azureus.core.devices.TranscodeProvider; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; /** * @author TuxPaper * @created Feb 24, 2009 * */ public class ColumnDevices_Name extends CoreTableColumn implements TableCellRefreshListener { public static final String COLUMN_ID = "name"; /** * @param name * @param tableID */ public ColumnDevices_Name(String tableID) { super(COLUMN_ID, tableID); setForDataSourceType(TranscodeProvider.class); initialize(ALIGN_LEAD | ALIGN_TOP, POSITION_INVISIBLE, 150, INTERVAL_INVALID_ONLY); } public void refresh(TableCell cell) { TranscodeProvider ds = (TranscodeProvider) cell.getDataSource(); String name = ds.getName(); cell.setText(name); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Profile.java0000644000175000017500000000323211160145526027117 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import com.aelitis.azureus.core.devices.TranscodeFile; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnTJ_Profile implements TableCellRefreshListener { public static final String COLUMN_ID = "profile"; public ColumnTJ_Profile(TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 80); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_INVALID_ONLY); column.setType(TableColumn.TYPE_TEXT_ONLY); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { TranscodeFile tf = (TranscodeFile) cell.getDataSource(); if (tf == null) { return; } cell.setText(tf.getTranscodeRequired()?tf.getProfileName():""); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Completion.java0000644000175000017500000001356411250374170027625 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.views.table.TableCellSWT; import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener; import com.aelitis.azureus.core.devices.DeviceOfflineDownload; import com.aelitis.azureus.ui.common.table.impl.TableColumnImpl; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.utils.ColorCache; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnOD_Completion implements TableCellAddedListener, TableCellRefreshListener, TableCellDisposeListener, TableCellSWTPaintListener { private static final int borderWidth = 1; public static final String COLUMN_ID = "od_completion"; private static Font fontText; private Map mapCellLastPercentDone = new HashMap(); private int marginHeight = -1; Color textColor; public ColumnOD_Completion(final TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 145); column.addListeners(this); // cheat. TODO: Either auto-add (in above method), or provide // access via TableColumn instead of type casting ((TableColumnImpl)column).addCellOtherListener("SWTPaint", this); column.setType(TableColumn.TYPE_GRAPHIC); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell) public void cellAdded(TableCell cell) { if (marginHeight != -1) { cell.setMarginHeight(marginHeight); } else { cell.setMarginHeight(2); } } // @see org.gudy.azureus2.plugins.ui.tables.TableCellDisposeListener#dispose(org.gudy.azureus2.plugins.ui.tables.TableCell) public void dispose(TableCell cell) { mapCellLastPercentDone.remove(cell); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { DeviceOfflineDownload od = (DeviceOfflineDownload) cell.getDataSource(); int percentDone = getPerThouDone(od); Integer intObj = mapCellLastPercentDone.get(cell); int lastPercentDone = intObj == null ? 0 : intObj.intValue(); if (!cell.setSortValue(percentDone) && cell.isValid() && lastPercentDone == percentDone) { return; } } // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT) public void cellPaint(GC gcImage, TableCellSWT cell) { DeviceOfflineDownload od = (DeviceOfflineDownload) cell.getDataSource(); Rectangle bounds = cell.getBounds(); int yOfs = (bounds.height - 13) / 2 ; int x1 = bounds.width - borderWidth - 2; int y1 = bounds.height - 3 - yOfs; if (x1 < 10 || y1 < 3) { return; } if ( !od.isTransfering()){ gcImage.fillRectangle( bounds ); return; } int percentDone = getPerThouDone(od); mapCellLastPercentDone.put(cell, new Integer(percentDone)); ImageLoader imageLoader = ImageLoader.getInstance(); Image imgEnd = imageLoader.getImage("tc_bar_end"); Image img0 = imageLoader.getImage("tc_bar_0"); Image img1 = imageLoader.getImage("tc_bar_1"); //draw begining and end if (!imgEnd.isDisposed()) { gcImage.drawImage(imgEnd, bounds.x , bounds.y + yOfs); gcImage.drawImage(imgEnd, bounds.x + x1 + 1, bounds.y + yOfs); } int limit = (x1 * percentDone) / 1000; if (!img1.isDisposed() && limit > 0) { Rectangle imgBounds = img1.getBounds(); gcImage.drawImage(img1, 0, 0, imgBounds.width, imgBounds.height, bounds.x + 1, bounds.y + yOfs, limit, imgBounds.height); } if (percentDone < 1000 && !img0.isDisposed()) { Rectangle imgBounds = img0.getBounds(); gcImage.drawImage(img0, 0, 0, imgBounds.width, imgBounds.height, bounds.x + limit + 1, bounds.y + yOfs, x1 - limit, imgBounds.height); } imageLoader.releaseImage("tc_bar_end"); imageLoader.releaseImage("tc_bar_0"); imageLoader.releaseImage("tc_bar_1"); if(textColor == null) { textColor = ColorCache.getColor(gcImage.getDevice(), "#006600" ); } gcImage.setForeground(textColor); if (fontText == null) { fontText = Utils.getFontWithHeight(gcImage.getFont(), gcImage, 10); } gcImage.setFont(fontText); String sText = DisplayFormatters.formatPercentFromThousands(percentDone); GCStringPrinter.printString(gcImage, sText, new Rectangle(bounds.x + 4, bounds.y + yOfs, bounds.width - 4,13), true, false, SWT.CENTER); } private int getPerThouDone(DeviceOfflineDownload od) { if (od == null) { return 0; } long total = od.getCurrentTransferSize(); long rem = od.getRemaining(); if ( total == 0 || total < rem ){ return( 0 ); } if ( rem == 0 ){ return( 1000 ); } return((int)( 1000 * ( total - rem ) / total )); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Device.java0000644000175000017500000000326611160145526026725 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import com.aelitis.azureus.core.devices.*; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnTJ_Device implements TableCellRefreshListener { public static final String COLUMN_ID = "device"; public ColumnTJ_Device(TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 80); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_INVALID_ONLY); column.setType(TableColumn.TYPE_TEXT_ONLY); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { TranscodeFile tf = (TranscodeFile) cell.getDataSource(); if (tf == null) { return; } Device device = tf.getDevice(); if (device == null) { return; } cell.setText(device.getName()); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Rank.java0000644000175000017500000000425511160331424026412 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import com.aelitis.azureus.core.devices.TranscodeFile; import com.aelitis.azureus.core.devices.TranscodeJob; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener; import org.gudy.azureus2.plugins.ui.tables.TableColumn; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnTJ_Rank implements TableCellRefreshListener { public static final String COLUMN_ID = "trancode_qpos"; public ColumnTJ_Rank(TableColumn column) { column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 25); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { TranscodeFile tf = (TranscodeFile) cell.getDataSource(); if (tf == null) { return; } TranscodeJob job = tf.getJob(); long value; if (job == null) { try { value = Integer.MAX_VALUE + tf.getCreationDateMillis() + 1; } catch (Throwable t) { value = Integer.MAX_VALUE + 1L; } } else { value = job.getIndex(); } if (cell.setSortValue(value) || !cell.isValid()) { if (value > Integer.MAX_VALUE) { cell.setText(""); } else { cell.setText("" + value); } } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Resolution.java0000644000175000017500000000334711160145526027671 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import com.aelitis.azureus.core.devices.TranscodeFile; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnTJ_Resolution implements TableCellRefreshListener { public static final String COLUMN_ID = "resolution"; public ColumnTJ_Resolution(TableColumn column) { column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, 80); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { TranscodeFile tf = (TranscodeFile) cell.getDataSource(); if (tf == null) { return; } long width = tf.getVideoWidth(); long height = tf.getVideoHeight(); cell.setText((width==0||height==0)?"":(width+"x"+height)); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Remaining.java0000644000175000017500000000327411247605474027434 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import com.aelitis.azureus.core.devices.DeviceOfflineDownload; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnOD_Remaining implements TableCellRefreshListener { public static final String COLUMN_ID = "od_remaining"; public ColumnOD_Remaining(final TableColumn column) { column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, 80); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC); column.setType(TableColumn.TYPE_TEXT_ONLY); } public void refresh(TableCell cell) { DeviceOfflineDownload od = (DeviceOfflineDownload) cell.getDataSource(); if (od == null) { return; } long remaining = od.getRemaining(); cell.setText( remaining==0?"":DisplayFormatters.formatByteCountToKiBEtc( remaining )); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Category.java0000644000175000017500000000340611171235600027272 0ustar adrianadrian/** * Created on Feb 26, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.columns; import com.aelitis.azureus.core.devices.TranscodeFile; import org.gudy.azureus2.plugins.ui.tables.*; /** * @author TuxPaper * @created Feb 26, 2009 * */ public class ColumnTJ_Category implements TableCellRefreshListener { public static final String COLUMN_ID = "category"; public ColumnTJ_Category(TableColumn column) { column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_INVISIBLE, 80); column.addListeners(this); column.setRefreshInterval(TableColumn.INTERVAL_INVALID_ONLY); column.setType(TableColumn.TYPE_TEXT_ONLY); } // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell) public void refresh(TableCell cell) { TranscodeFile tf = (TranscodeFile) cell.getDataSource(); if (tf == null) { return; } String[] cats = tf.getCategories(); String str = ""; for (String cat: cats ){ str += (str.length()==0?"":",") + cat; } cell.setText( str ); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/SBC_DevicesView.java0000644000175000017500000011541111272502256025174 0ustar adrianadrian/** * Created on Feb 24, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices; import java.io.File; import java.net.URL; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.*; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.category.Category; import org.gudy.azureus2.core3.category.CategoryManager; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.URLTransfer; import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.devices.*; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.UserPrompterResultListener; import com.aelitis.azureus.ui.common.table.*; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.swt.columns.torrent.ColumnThumbnail; import com.aelitis.azureus.ui.swt.devices.columns.*; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectText; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter; import com.aelitis.azureus.ui.swt.views.skin.InfoBarUtil; import com.aelitis.azureus.ui.swt.views.skin.SkinView; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; /** * @author TuxPaper * @created Feb 24, 2009 * */ public class SBC_DevicesView extends SkinView implements TranscodeQueueListener, IconBarEnabler, UIUpdatable, TranscodeTargetListener { public static final String TABLE_DEVICES = "Devices"; public static final String TABLE_TRANSCODE_QUEUE = "TranscodeQueue"; public static final String TABLE_DEVICE_LIBRARY = "DeviceLibrary"; private static boolean columnsAdded = false; private DeviceManager device_manager; private TranscodeManager transcode_manager; private TranscodeQueue transcode_queue; private TableViewSWTImpl tvDevices; private DragSource dragSource; private DropTarget dropTarget; private int drag_drop_line_start = -1; private TableRowCore[] drag_drop_rows; private TableViewSWTImpl tvFiles; private SideBarEntrySWT sidebarEntry; private Composite tableJobsParent; private Device device; private TranscodeTarget transTarget; // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectInitialShow(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { initColumns(core); } }); device_manager = DeviceManagerFactory.getSingleton(); transcode_manager = device_manager.getTranscodeManager(); transcode_queue = transcode_manager.getQueue(); SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sidebar != null) { sidebarEntry = sidebar.getCurrentEntry(); sidebarEntry.setIconBarEnabler(this); device = (Device) sidebarEntry.getDatasource(); } if (device instanceof TranscodeTarget) { transTarget = (TranscodeTarget) device; } if (device == null) { new InfoBarUtil(skinObject, "devicesview.infobar", false, "DeviceView.infobar", "v3.deviceview.infobar") { public boolean allowShow() { return true; } }; } else if (device instanceof DeviceMediaRenderer) { DeviceMediaRenderer renderer = (DeviceMediaRenderer) device; int species = renderer.getRendererSpecies(); String speciesID = null; switch (species) { case DeviceMediaRenderer.RS_ITUNES: speciesID = "itunes"; break; case DeviceMediaRenderer.RS_PS3: speciesID = "ps3"; break; case DeviceMediaRenderer.RS_XBOX: speciesID = "xbox"; break; case DeviceMediaRenderer.RS_OTHER:{ String classification = renderer.getClassification(); if ( classification.equals( "sony.PSP")){ speciesID = "psp"; }else if ( classification.startsWith( "tivo.")){ speciesID = "tivo"; } } default: break; } if (speciesID != null) { final String fSpeciesID = speciesID; new InfoBarUtil(skinObject, "devicesview.infobar", false, "DeviceView.infobar." + speciesID, "v3.deviceview.infobar") { public boolean allowShow() { return true; } // @see com.aelitis.azureus.ui.swt.views.skin.InfoBarUtil#created(com.aelitis.azureus.ui.swt.skin.SWTSkinObject) protected void created(SWTSkinObject parent) { SWTSkinObjectText soLine1 = (SWTSkinObjectText) skin.getSkinObject( "line1", parent); soLine1.setTextID("v3.deviceview.infobar.line1.generic", new String[] { device.getName() }); SWTSkinObjectText soLine2 = (SWTSkinObjectText) skin.getSkinObject( "line2", parent); soLine2.setTextID("v3.deviceview.infobar.line2." + fSpeciesID); } }; } } SWTSkinObject soAdvInfo = getSkinObject("advinfo"); if (soAdvInfo != null) { initAdvInfo(soAdvInfo); } if (device != null) { SWTSkinObject soTitle = getSkinObject("title"); if (soTitle instanceof SWTSkinObjectText) { ((SWTSkinObjectText) soTitle).setTextID("device.view.heading", new String[] { device.getName() }); } } return null; } /** * * * @since 4.1.0.5 */ private void initColumns(AzureusCore core) { if (columnsAdded) { return; } columnsAdded = true; UIManager uiManager = PluginInitializer.getDefaultInterface().getUIManager(); TableManager tableManager = uiManager.getTableManager(); tableManager.registerColumn(TranscodeFile.class, ColumnTJ_Rank.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnTJ_Rank(column); if (!column.getTableID().equals(TABLE_TRANSCODE_QUEUE)) { column.setVisible(false); } } }); tableManager.registerColumn(TranscodeFile.class, ColumnThumbnail.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnThumbnail(column); column.setWidth(70); } }); tableManager.registerColumn(TranscodeFile.class, ColumnTJ_Name.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnTJ_Name(column); if (column.getTableID().equals(TABLE_TRANSCODE_QUEUE)) { column.setWidth(200); } else if (!column.getTableID().endsWith(":type=1")) { column.setWidth(140); } } }); tableManager.registerColumn(TranscodeFile.class, ColumnTJ_Duration.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnTJ_Duration(column); } }); tableManager.registerColumn(TranscodeFile.class, ColumnTJ_Device.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnTJ_Device(column); column.setVisible(false); } }); tableManager.registerColumn(TranscodeFile.class, ColumnTJ_Profile.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnTJ_Profile(column); if (column.getTableID().equals(TABLE_TRANSCODE_QUEUE)) { column.setWidth(70); } } }); tableManager.registerColumn(TranscodeFile.class, ColumnTJ_Resolution.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnTJ_Resolution(column); column.setVisible(false); if (column.getTableID().equals(TABLE_TRANSCODE_QUEUE)) { column.setWidth(95); } } }); tableManager.registerColumn(TranscodeFile.class, ColumnTJ_Status.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnTJ_Status(column); } }); tableManager.registerColumn(TranscodeFile.class, ColumnTJ_Completion.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnTJ_Completion(column); column.setWidth(145); } }); tableManager.registerColumn(TranscodeFile.class, ColumnTJ_CopiedToDevice.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnTJ_CopiedToDevice(column); if (column.getTableID().endsWith(":type=1") || column.getTableID().equals(TABLE_TRANSCODE_QUEUE)) { column.setVisible(false); } } }); tableManager.registerColumn(TranscodeFile.class, ColumnTJ_Category.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnTJ_Category(column); } }); } // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectShown(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectShown(SWTSkinObject skinObject, Object params) { super.skinObjectShown(skinObject, params); transcode_queue.addListener(this); if (transTarget != null) { transTarget.addListener(this); } SWTSkinObject soDeviceList = getSkinObject("device-list"); if (soDeviceList != null) { initDeviceListTable((Composite) soDeviceList.getControl()); } SWTSkinObject soTranscodeQueue = getSkinObject("transcode-queue"); if (soTranscodeQueue != null) { initTranscodeQueueTable((Composite) soTranscodeQueue.getControl()); } if (device instanceof TranscodeTarget){ createDragDrop( tvFiles!=null?tvFiles:tvDevices); } setAdditionalInfoTitle(false); // This is bad. Example: // 1) Do a search // 2) Sidebar entry opens under Devices // 3) Close search sidebar // 4) Device entry gets auto-selected // 5) User gets ftux // 6) User says no, anger increases // 7) Go to 1 //DevicesFTUX.ensureInstalled(); return null; } /** * @param soAdvInfo * * @since 4.1.0.5 */ private void initAdvInfo(SWTSkinObject soAdvInfo) { SWTSkinButtonUtility btnAdvInfo = new SWTSkinButtonUtility(soAdvInfo); btnAdvInfo.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { SWTSkinObject soArea = getSkinObject("advinfo-area"); if (soArea != null) { boolean newVisibility = !soArea.isVisible(); setAdditionalInfoTitle(newVisibility); } } }); setAdditionalInfoTitle(false); } /** * @param newVisibility * * @since 4.1.0.5 */ protected void setAdditionalInfoTitle(boolean newVisibility) { SWTSkinObject soArea = getSkinObject("advinfo-area"); if (soArea != null) { soArea.setVisible(newVisibility); } SWTSkinObject soText = getSkinObject("advinfo-title"); if (soText instanceof SWTSkinObjectText) { String s = (newVisibility ? "[-]" : "[+]"); if (device != null) { s += "Additional Device Info and Settings"; } else { s += "General Options"; } ((SWTSkinObjectText) soText).setText(s); } } // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectHidden(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectHidden(SWTSkinObject skinObject, Object params) { transcode_queue.removeListener(this); if (transTarget != null) { transTarget.removeListener(this); } synchronized (this) { if (tvFiles != null) { tvFiles.delete(); tvFiles = null; } } Utils.disposeSWTObjects(new Object[] { tableJobsParent, dropTarget, dragSource, }); if (tvDevices != null) { tvDevices.delete(); tvDevices = null; } return super.skinObjectHidden(skinObject, params); } /** * @param control * * @since 4.1.0.5 */ private void initTranscodeQueueTable(Composite control) { String tableID; if (device == null) { tableID = TABLE_TRANSCODE_QUEUE; } else { tableID = TABLE_DEVICE_LIBRARY; if (device instanceof DeviceMediaRenderer) { DeviceMediaRenderer dmr = (DeviceMediaRenderer)device; if (!(dmr.canCopyToDevice()||dmr.canCopyToFolder())) { tableID += ":type=1"; } } } tvFiles = new TableViewSWTImpl(TranscodeFile.class, tableID, tableID, new TableColumnCore[0], device == null ? ColumnTJ_Rank.COLUMN_ID : ColumnTJ_Status.COLUMN_ID, SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL); tvFiles.setRowDefaultHeight(50); tvFiles.setHeaderVisible(true); tvFiles.setParentDataSource(device); tableJobsParent = new Composite(control, SWT.NONE); tableJobsParent.setLayoutData(Utils.getFilledFormData()); GridLayout layout = new GridLayout(); layout.marginHeight = layout.marginWidth = layout.verticalSpacing = layout.horizontalSpacing = 0; tableJobsParent.setLayout(layout); tvFiles.addSelectionListener(new TableSelectionListener() { public void selected(TableRowCore[] row) { SelectedContentManager.clearCurrentlySelectedContent(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } public void mouseExit(TableRowCore row) { } public void mouseEnter(TableRowCore row) { } public void focusChanged(TableRowCore focus) { SelectedContentManager.clearCurrentlySelectedContent(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } public void deselected(TableRowCore[] rows) { SelectedContentManager.clearCurrentlySelectedContent(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } public void defaultSelected(TableRowCore[] rows, int stateMask) { SelectedContentManager.clearCurrentlySelectedContent(); } }, false); tvFiles.addLifeCycleListener(new TableLifeCycleListener() { public void tableViewInitialized() { if (transTarget == null) { // just add all jobs' files TranscodeJob[] jobs = transcode_queue.getJobs(); for (TranscodeJob job : jobs) { TranscodeFile file = job.getTranscodeFile(); if (file != null) { tvFiles.addDataSource(file); } } } else { tvFiles.addDataSources(transTarget.getFiles()); } } public void tableViewDestroyed() { } }); tvFiles.addMenuFillListener(new TableViewSWTMenuFillListener() { public void fillMenu(String sColumnName, Menu menu) { SBC_DevicesView.this.fillMenu(menu); } public void addThisColumnSubMenu(String columnName, Menu menuThisColumn) { } }); tvFiles.addKeyListener( new KeyListener() { public void keyPressed( KeyEvent e ) { if ( e.stateMask == 0 && e.keyCode == SWT.DEL ){ TranscodeFile[] selected; synchronized (this) { if ( tvFiles == null ){ selected = new TranscodeFile[0]; }else{ List selectedDataSources = tvFiles.getSelectedDataSources(); selected = selectedDataSources.toArray(new TranscodeFile[0]); } } deleteFiles(selected, 0); e.doit = false; } } public void keyReleased( KeyEvent arg0 ) { } }); tvFiles.initialize(tableJobsParent); control.layout(true); } /** * @param menu * * @since 4.0.0.5 */ protected void fillMenu(Menu menu) { Object[] _files = tvFiles.getSelectedDataSources().toArray(); final TranscodeFile[] files = new TranscodeFile[_files.length]; System.arraycopy(_files, 0, files, 0, files.length); // open file final MenuItem open_item = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(open_item, "MyTorrentsView.menu.open"); Utils.setMenuItemImage(open_item, "run"); File target_file = null; File source_file = null; try { if (files.length == 1) { target_file = files[0].getTargetFile().getFile(); if (!target_file.exists()) { target_file = null; } } } catch (Throwable e) { Debug.out(e); } try { if (files.length == 1) { source_file = files[0].getSourceFile().getFile(); if (!source_file.exists()) { source_file = null; } } } catch (Throwable e) { Debug.out(e); } final File f_target_file = target_file; final File f_source_file = source_file; open_item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent ev) { Utils.launch(f_target_file.getAbsolutePath()); }; }); open_item.setEnabled(target_file != null); // show in explorer final boolean use_open_containing_folder = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled"); final MenuItem show_item = new MenuItem(menu, SWT.PUSH); Messages.setLanguageText(show_item, "MyTorrentsView.menu." + (use_open_containing_folder ? "open_parent_folder" : "explore")); show_item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { ManagerUtils.open( f_target_file != null ? f_target_file : f_source_file, use_open_containing_folder); }; }); show_item.setEnabled((source_file != null && !files[0].isComplete()) || (target_file != null && files[0].isComplete())); // category Menu menu_category = new Menu(menu.getShell(), SWT.DROP_DOWN); final MenuItem item_category = new MenuItem(menu, SWT.CASCADE); Messages.setLanguageText(item_category, "MyTorrentsView.menu.setCategory"); item_category.setMenu(menu_category); addCategorySubMenu( menu_category, files ); new MenuItem(menu, SWT.SEPARATOR); // pause final MenuItem pause_item = new MenuItem(menu, SWT.PUSH); pause_item.setText(MessageText.getString("v3.MainWindow.button.pause")); pause_item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { for (int i = 0; i < files.length; i++) { TranscodeJob job = files[i].getJob(); if (job != null) { job.pause(); } } }; }); // resume final MenuItem resume_item = new MenuItem(menu, SWT.PUSH); resume_item.setText(MessageText.getString("v3.MainWindow.button.resume")); resume_item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { for (int i = 0; i < files.length; i++) { TranscodeJob job = files[i].getJob(); if (job != null) { job.resume(); } } }; }); // separator new MenuItem(menu, SWT.SEPARATOR); if (device instanceof DeviceMediaRenderer) { DeviceMediaRenderer dmr = (DeviceMediaRenderer) device; if (dmr.canCopyToDevice() || dmr.canCopyToFolder()) { // retry final MenuItem retry_item = new MenuItem(menu, SWT.PUSH); retry_item.setText(MessageText.getString("device.retry.copy")); retry_item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { for (int i = 0; i < files.length; i++) { TranscodeFile file = files[i]; if ( file.getCopyToDeviceFails() > 0 || file.isCopiedToDevice() ){ file.retryCopyToDevice(); } } }; }); retry_item.setEnabled(false); for (TranscodeFile file : files) { if ( file.getCopyToDeviceFails() > 0 || file.isCopiedToDevice()) { retry_item.setEnabled(true); } } // separator new MenuItem(menu, SWT.SEPARATOR); } } // copy stream uri final MenuItem sc_item = new MenuItem(menu, SWT.PUSH); sc_item.setText(MessageText.getString("devices.copy_url")); if (files.length == 1) { final URL url = files[0].getStreamURL(); if (url != null) { sc_item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { ClipboardCopy.copyToClipBoard(url.toExternalForm()); }; }); } else { sc_item.setEnabled(false); } } else { sc_item.setEnabled(false); } // remove final MenuItem remove_item = new MenuItem(menu, SWT.PUSH); remove_item.setText(MessageText.getString("azbuddy.ui.menu.remove")); Utils.setMenuItemImage(remove_item, "delete"); remove_item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { deleteFiles(files, 0); }; }); // separator new MenuItem(menu, SWT.SEPARATOR); // Logic to disable items boolean has_selection = files.length > 0; remove_item.setEnabled(has_selection); boolean can_pause = has_selection; boolean can_resume = has_selection; int job_count = 0; for (int i = 0; i < files.length; i++) { TranscodeJob job = files[i].getJob(); if (job == null) { continue; } job_count++; int state = job.getState(); if (state != TranscodeJob.ST_RUNNING || !job.canPause()) { can_pause = false; } if (state != TranscodeJob.ST_PAUSED) { can_resume = false; } } pause_item.setEnabled(can_pause && job_count > 0); resume_item.setEnabled(can_resume && job_count > 0); } private void addCategorySubMenu( Menu menu_category, final TranscodeFile[] files ) { MenuItem[] items = menu_category.getItems(); int i; for (i = 0; i < items.length; i++) { items[i].dispose(); } Category[] categories = CategoryManager.getCategories(); Arrays.sort(categories); if (categories.length > 0) { Category catUncat = CategoryManager.getCategory(Category.TYPE_UNCATEGORIZED); if (catUncat != null) { final MenuItem itemCategory = new MenuItem(menu_category, SWT.PUSH); Messages.setLanguageText(itemCategory, catUncat.getName()); itemCategory.setData("Category", catUncat); itemCategory.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { MenuItem item = (MenuItem)event.widget; assignSelectedToCategory((Category)item.getData("Category"),files); } }); new MenuItem(menu_category, SWT.SEPARATOR); } for (i = 0; i < categories.length; i++) { if (categories[i].getType() == Category.TYPE_USER) { final MenuItem itemCategory = new MenuItem(menu_category, SWT.PUSH); itemCategory.setText(categories[i].getName()); itemCategory.setData("Category", categories[i]); itemCategory.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { MenuItem item = (MenuItem)event.widget; assignSelectedToCategory((Category)item.getData("Category"),files); } }); } } new MenuItem(menu_category, SWT.SEPARATOR); } final MenuItem itemAddCategory = new MenuItem(menu_category, SWT.PUSH); Messages.setLanguageText(itemAddCategory, "MyTorrentsView.menu.setCategory.add"); itemAddCategory.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { addCategory(files); } }); } private void addCategory( TranscodeFile[] files ) { CategoryAdderWindow adderWindow = new CategoryAdderWindow(Display.getDefault()); Category newCategory = adderWindow.getNewCategory(); if (newCategory != null) assignSelectedToCategory(newCategory,files); } private void assignSelectedToCategory( Category category, TranscodeFile[] files ) { String[] cats; if ( category.getType() == Category.TYPE_UNCATEGORIZED ){ cats = new String[0]; }else{ cats = new String[]{ category.getName()}; } for ( TranscodeFile file: files ){ file.setCategories( cats ); } } /** * * * @param parent * @since 4.1.0.5 */ private void initDeviceListTable(Composite control) { tvDevices = new TableViewSWTImpl(TranscodeProvider.class, TABLE_DEVICES, TABLE_DEVICES, new TableColumnCore[0], ColumnTJ_Rank.COLUMN_ID); tvDevices.setRowDefaultHeight(50); tvDevices.setHeaderVisible(true); Composite parent = new Composite(control, SWT.NONE); parent.setLayoutData(Utils.getFilledFormData()); GridLayout layout = new GridLayout(); layout.marginHeight = layout.marginWidth = layout.verticalSpacing = layout.horizontalSpacing = 0; parent.setLayout(layout); tvDevices.initialize(parent); } // @see com.aelitis.azureus.core.devices.TranscodeQueueListener#jobAdded(com.aelitis.azureus.core.devices.TranscodeJob) public void jobAdded(TranscodeJob job) { synchronized (this) { if (tvFiles == null) { return; } if (transTarget == null) { TranscodeFile file = job.getTranscodeFile(); if (file != null) { tvFiles.addDataSource(file); } } } } // @see com.aelitis.azureus.core.devices.TranscodeQueueListener#jobChanged(com.aelitis.azureus.core.devices.TranscodeJob) public void jobChanged(TranscodeJob job) { synchronized (this) { if (tvFiles == null) { return; } TableRowCore row = tvFiles.getRow(job.getTranscodeFile()); if (row != null) { row.invalidate(); if (row.isVisible()) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } } } } // @see com.aelitis.azureus.core.devices.TranscodeQueueListener#jobRemoved(com.aelitis.azureus.core.devices.TranscodeJob) public void jobRemoved(TranscodeJob job) { synchronized (this) { if (tvFiles == null) { return; } if (transTarget == null) { TranscodeFile file = job.getTranscodeFile(); if (file != null) { tvFiles.removeDataSource(file); } } else { TableRowCore row = tvFiles.getRow(job.getTranscodeFile()); if (row != null) { row.invalidate(); if (row.isVisible()) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } } } } } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#isEnabled(java.lang.String) public boolean isEnabled(String itemKey) { Object[] selectedDS; int size; synchronized (this) { if (tvFiles == null) { return false; } selectedDS = tvFiles.getSelectedDataSources().toArray(); size = tvFiles.size(false); } if (selectedDS.length == 0) { return (false); } if (itemKey.equals("remove")) { return (true); } boolean can_stop = true; boolean can_queue = true; boolean can_move_up = true; boolean can_move_down = true; boolean hasJob = false; for (Object ds : selectedDS) { TranscodeJob job = ((TranscodeFile) ds).getJob(); if (job == null) { continue; } hasJob = true; int index = job.getIndex(); if (index == 1) { can_move_up = false; } if (index == size) { can_move_down = false; } int state = job.getState(); if (state != TranscodeJob.ST_PAUSED && state != TranscodeJob.ST_RUNNING && state != TranscodeJob.ST_FAILED && state != TranscodeJob.ST_QUEUED) { can_stop = false; } if (state != TranscodeJob.ST_PAUSED && state != TranscodeJob.ST_STOPPED && state != TranscodeJob.ST_FAILED) { can_queue = false; } } if (!hasJob) { can_stop = can_queue = can_move_down = can_move_up = false; } if (itemKey.equals("stop")) { return (can_stop); } if (itemKey.equals("start")) { return (can_queue); } if (itemKey.equals("up")) { return (can_move_up); } if (itemKey.equals("down")) { return (can_move_down); } return (false); } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#isSelected(java.lang.String) public boolean isSelected(String itemKey) { return false; } // @see org.gudy.azureus2.ui.swt.IconBarEnabler#itemActivated(java.lang.String) public void itemActivated(final String itemKey) { // assumed to be on SWT thread, so it's safe to use tvFiles without a sync if (tvFiles == null) { return; } TranscodeFile[] selectedDS = tvFiles.getSelectedDataSources().toArray(new TranscodeFile[0]); if (selectedDS.length == 0) { return; } if (itemKey.equals("remove")) { deleteFiles(selectedDS, 0); return; } java.util.List jobs = new ArrayList( selectedDS.length); for (int i = 0; i < selectedDS.length; i++) { TranscodeFile file = (TranscodeFile) selectedDS[i]; TranscodeJob job = file.getJob(); if (job != null) { jobs.add(job); } } if (jobs.size() == 0) { return; } if (itemKey.equals("up") || itemKey.equals("down")) { Collections.sort(jobs, new Comparator() { public int compare(TranscodeJob j1, TranscodeJob j2) { return ((itemKey.equals("up") ? 1 : -1) * (j1.getIndex() - j2.getIndex())); } }); } boolean forceSort = false; for (TranscodeJob job : jobs) { if (itemKey.equals("stop")) { job.stop(); } else if (itemKey.equals("start")) { job.queue(); } else if (itemKey.equals("up")) { job.moveUp(); TableColumnCore sortColumn = tvFiles.getSortColumn(); forceSort = sortColumn != null && sortColumn.getName().equals(ColumnTJ_Rank.COLUMN_ID); } else if (itemKey.equals("down")) { job.moveDown(); TableColumnCore sortColumn = tvFiles.getSortColumn(); forceSort = sortColumn != null && sortColumn.getName().equals(ColumnTJ_Rank.COLUMN_ID); } } tvFiles.refreshTable(forceSort); } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName() public String getUpdateUIName() { return "DevicesView"; } // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI() public void updateUI() { if (tvFiles != null) { tvFiles.refreshTable(false); } } // @see com.aelitis.azureus.core.devices.TranscodeTargetListener#fileAdded(com.aelitis.azureus.core.devices.TranscodeFile) public void fileAdded(TranscodeFile file) { synchronized (this) { if (tvFiles != null) { tvFiles.addDataSource(file); } } } // @see com.aelitis.azureus.core.devices.TranscodeTargetListener#fileChanged(com.aelitis.azureus.core.devices.TranscodeFile, int, java.lang.Object) public void fileChanged(TranscodeFile file, int type, Object data) { synchronized (this) { if (tvFiles == null) { return; } TableRowCore row = tvFiles.getRow(file); if (row != null) { row.invalidate(); if (row.isVisible()) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } } } } // @see com.aelitis.azureus.core.devices.TranscodeTargetListener#fileRemoved(com.aelitis.azureus.core.devices.TranscodeFile) public void fileRemoved(TranscodeFile file) { synchronized (this) { if (tvFiles != null) { tvFiles.removeDataSource(file); } } } protected void deleteFiles(final TranscodeFile[] toRemove, final int startIndex) { if (toRemove[startIndex] == null) { int nextIndex = startIndex + 1; if (nextIndex < toRemove.length) { deleteFiles(toRemove, nextIndex); } return; } final TranscodeFile file = toRemove[startIndex]; try { File cache_file = file.getCacheFileIfExists(); if (cache_file != null && cache_file.exists() && file.isComplete()) { String path = cache_file.toString(); String title = MessageText.getString("xcode.deletedata.title"); String copy_text = ""; Device device = file.getDevice(); if (device instanceof DeviceMediaRenderer) { DeviceMediaRenderer dmr = (DeviceMediaRenderer)device; File copy_to = dmr.getCopyToFolder(); if ( dmr.canCopyToDevice() || ( dmr.canCopyToFolder() && copy_to != null && copy_to.exists())){ copy_text = MessageText.getString("xcode.deletedata.message.2", new String[] { device.getName() }); } } String text = MessageText.getString("xcode.deletedata.message", new String[] { file.getName(), file.getProfileName(), copy_text }); MessageBoxShell mb = new MessageBoxShell(title, text); mb.setRemember("xcode.deletedata.noconfirm.key", false, MessageText.getString("deletedata.noprompt")); if (startIndex == toRemove.length - 1) { mb.setButtons(0, new String[] { MessageText.getString("Button.yes"), MessageText.getString("Button.no"), }, new Integer[] { 0, 1 }); mb.setRememberOnlyIfButton(0); } else { mb.setButtons(1, new String[] { MessageText.getString("Button.removeAll"), MessageText.getString("Button.yes"), MessageText.getString("Button.no"), }, new Integer[] { 2, 0, 1 }); mb.setRememberOnlyIfButton(1); } DownloadManager dm = null; if (dm != null) { mb.setRelatedObject(dm); } mb.setLeftImage(SWT.ICON_WARNING); mb.open(new UserPrompterResultListener() { public void prompterClosed(int result) { if (result == -1) { return; } else if (result == 0) { deleteNoCheck(file); } else if (result == 2) { for (int i = startIndex; i < toRemove.length; i++) { if (toRemove[i] != null) { deleteNoCheck(toRemove[i]); } } return; } int nextIndex = startIndex + 1; if (nextIndex < toRemove.length) { deleteFiles(toRemove, nextIndex); } } }); } else { deleteNoCheck(file); } } catch (Throwable e) { Debug.out(e); } } private void deleteNoCheck(TranscodeFile file) { TranscodeJob job = file.getJob(); if (job != null) { job.remove(); } try { file.delete(file.getCacheFileIfExists() != null); } catch (TranscodeException e) { Debug.out(e); } } private void createDragDrop( final TableViewSWTImpl table ) { try { Transfer[] types = new Transfer[] { TextTransfer.getInstance() }; if (dragSource != null && !dragSource.isDisposed()) { dragSource.dispose(); } if (dropTarget != null && !dropTarget.isDisposed()) { dropTarget.dispose(); } dragSource = table.createDragSource(DND.DROP_MOVE | DND.DROP_COPY); if (dragSource != null) { dragSource.setTransfer(types); dragSource.addDragListener(new DragSourceAdapter() { private String eventData; public void dragStart(DragSourceEvent event) { TableRowCore[] rows = table.getSelectedRows(); if (rows.length != 0) { event.doit = true; // System.out.println("DragStart"); drag_drop_line_start = rows[0].getIndex(); drag_drop_rows = rows; } else { event.doit = false; drag_drop_line_start = -1; drag_drop_rows = null; } // Build eventData here because on OSX, selection gets cleared // by the time dragSetData occurs java.util.List selectedFiles = table.getSelectedDataSources(); eventData="TranscodeFile\n"; for ( Object o: selectedFiles ){ TranscodeFile file = (TranscodeFile)o; if ( file.isComplete()){ try{ eventData += file.getTargetFile().getFile().getAbsolutePath() + "\n"; }catch( Throwable e ){ } } } } public void dragSetData(DragSourceEvent event) { // System.out.println("DragSetData"); event.data = eventData; } }); } dropTarget = table.createDropTarget(DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_TARGET_MOVE); if (dropTarget != null) { dropTarget.setTransfer(new Transfer[] { HTMLTransfer.getInstance(), URLTransfer.getInstance(), FileTransfer.getInstance(), TextTransfer.getInstance() }); dropTarget.addDropListener(new DropTargetAdapter() { public void dropAccept(DropTargetEvent event) { event.currentDataType = URLTransfer.pickBestType(event.dataTypes, event.currentDataType); } public void dragEnter(DropTargetEvent event) { // no event.data on dragOver, use drag_drop_line_start to determine // if ours if (drag_drop_line_start < 0) { if (event.detail != DND.DROP_COPY) { if ((event.operations & DND.DROP_LINK) > 0) event.detail = DND.DROP_LINK; else if ((event.operations & DND.DROP_COPY) > 0) event.detail = DND.DROP_COPY; } } else if (TextTransfer.getInstance().isSupportedType( event.currentDataType)) { event.detail = event.item == null ? DND.DROP_NONE : DND.DROP_MOVE; event.feedback = DND.FEEDBACK_SCROLL | DND.FEEDBACK_INSERT_BEFORE; } } public void dragOver(DropTargetEvent event) { if (drag_drop_line_start >= 0) { event.detail = event.item == null ? DND.DROP_NONE : DND.DROP_MOVE; event.feedback = DND.FEEDBACK_SCROLL | DND.FEEDBACK_INSERT_BEFORE; } } public void drop(DropTargetEvent event) { try{ if ( event.data instanceof String && ((String) event.data).startsWith("TranscodeFile\n")) { // todo: support drag and drop reordering of xcode queue? return; } event.detail = DND.DROP_NONE; DeviceManagerUI.handleDrop((TranscodeTarget)device, event.data ); }finally{ drag_drop_line_start = -1; drag_drop_rows = null; } } }); } } catch (Throwable t) { Debug.out( "failed to init drag-n-drop", t); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/add/0000755000175000017500000000000011310377632022153 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/add/DeviceTemplateChooser.java0000644000175000017500000001261611267524524027247 0ustar adrianadrian/** * Created on Jul 16, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.add; import java.util.Arrays; import java.util.Comparator; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import com.aelitis.azureus.core.devices.DeviceTemplate; import com.aelitis.azureus.core.devices.DeviceManager.DeviceManufacturer; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.devices.TranscodeChooser; import com.aelitis.azureus.ui.swt.skin.*; import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog; import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog.SkinnedDialogClosedListener; /** * @author TuxPaper * @created Jul 16, 2009 * */ public class DeviceTemplateChooser { private DeviceTemplateClosedListener listener; private SkinnedDialog skinnedDialog; private DeviceTemplate selectedDeviceTemplate; private DeviceManufacturer mf; private SWTSkinObjectContainer soList; /** * */ public DeviceTemplateChooser(DeviceManufacturer mf) { this.mf = mf; } public void open(DeviceTemplateClosedListener l) { this.listener = l; skinnedDialog = new SkinnedDialog("skin3_dlg_deviceadd_mfchooser", "shell", SWT.TITLE | SWT.BORDER); skinnedDialog.addCloseListener(new SkinnedDialogClosedListener() { public void skinDialogClosed(SkinnedDialog dialog) { if (listener != null) { listener.deviceTemplateChooserClosed(selectedDeviceTemplate); } } }); SWTSkin skin = skinnedDialog.getSkin(); SWTSkinObject so= skin.getSkinObject("list"); if (so instanceof SWTSkinObjectContainer) { soList = (SWTSkinObjectContainer) so; createDeviceTemplateList2(soList); } skinnedDialog.open(); } private void createDeviceTemplateList2(SWTSkinObjectContainer soList) { DeviceTemplate[] devices = mf.getDeviceTemplates(); if (devices.length == 0) { noDevices(); return; } Arrays.sort(devices, new Comparator() { public int compare(DeviceTemplate o1, DeviceTemplate o2) { return o1.getName().compareToIgnoreCase(o2.getName()); } }); Composite parent = soList.getComposite(); if (parent.getChildren().length > 0) { Utils.disposeComposite(parent, false); } SWTSkin skin = skinnedDialog.getSkin(); SWTSkinObjectText soInfoTitle = (SWTSkinObjectText) skin.getSkinObject("info-title"); SWTSkinObjectText soInfoText = (SWTSkinObjectText) skin.getSkinObject("info-text"); RowLayout layout = new RowLayout(SWT.HORIZONTAL); layout.spacing = 0; layout.marginLeft = layout.marginRight = 0; layout.wrap = true; layout.justify = true; layout.fill = true; parent.setLayout(layout); Listener clickListener = new Listener() { boolean down = false; public void handleEvent(Event event) { if (event.type == SWT.MouseDown) { down = true; } else if (event.type == SWT.MouseUp && down) { Widget widget = (event.widget instanceof Label) ? ((Label) event.widget).getParent() : event.widget; selectedDeviceTemplate = (DeviceTemplate) widget.getData("obj"); if (selectedDeviceTemplate == null) { Debug.out("selectedDeviceTemplate is null!"); } skinnedDialog.close(); down = false; } } }; GridData gridData; for (DeviceTemplate deviceTemplate : devices) { if (deviceTemplate.isAuto()) { continue; } String iconURL = null; // deviceTemplate.getIconURL(); TranscodeChooser.addImageBox(parent, clickListener, null, deviceTemplate, iconURL, deviceTemplate.getName()); } SWTSkinObjectText soTitle = (SWTSkinObjectText) skin.getSkinObject("title"); if (soTitle != null) { soTitle.setTextID("devices.choose.device.title"); } SWTSkinObjectText soSubTitle = (SWTSkinObjectText) skin.getSkinObject("subtitle"); if (soSubTitle != null) { soSubTitle.setTextID("label.clickone"); } Point computeSize = skinnedDialog.getShell().computeSize(600, SWT.DEFAULT, true); skinnedDialog.getShell().setSize(computeSize); Shell mainShell = UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell(); Utils.centerWindowRelativeTo(skinnedDialog.getShell(), mainShell); } /** * * * @since 4.1.0.5 */ private void noDevices() { new MessageBoxShell( SWT.OK, "No Devices Found", "We couldn't find any devices. Maybe you didn't install the Vuze Transcoder Plugin?").open(null); skinnedDialog.close(); } public static interface DeviceTemplateClosedListener { public void deviceTemplateChooserClosed(DeviceTemplate deviceTemplate); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/add/ManufacturerChooser.java0000644000175000017500000000736411227776600027014 0ustar adrianadrian/** * Created on Jul 14, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices.add; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.core.devices.*; import com.aelitis.azureus.core.devices.DeviceManager.DeviceManufacturer; import com.aelitis.azureus.ui.swt.skin.SWTSkin; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectContainer; import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog; import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog.SkinnedDialogClosedListener; /** * @author TuxPaper * @created Jul 14, 2009 * */ public class ManufacturerChooser { private SkinnedDialog skinnedDialog; private ClosedListener listener; protected DeviceManufacturer chosenMF; public void open(ClosedListener l) { this.listener = l; skinnedDialog = new SkinnedDialog("skin3_dlg_deviceadd_mfchooser", "shell", SWT.TITLE | SWT.BORDER); skinnedDialog.addCloseListener(new SkinnedDialogClosedListener() { public void skinDialogClosed(SkinnedDialog dialog) { if (listener != null) { listener.MfChooserClosed(chosenMF); } } }); SWTSkin skin = skinnedDialog.getSkin(); SWTSkinObject so= skin.getSkinObject("list"); if (so instanceof SWTSkinObjectContainer) { SWTSkinObjectContainer soList = (SWTSkinObjectContainer) so; Composite parent = soList.getComposite(); Canvas centerCanvas = new Canvas(parent, SWT.NONE); FormData fd = Utils.getFilledFormData(); fd.bottom = null; fd.height = 0; centerCanvas.setLayoutData(fd); Composite area = new Composite(parent, SWT.NONE); RowLayout rowLayout = new RowLayout(SWT.VERTICAL); rowLayout.fill = true; area.setLayout(rowLayout); fd = Utils.getFilledFormData(); fd.left = new FormAttachment(centerCanvas, 50, SWT.CENTER); fd.right = null; area.setLayoutData(fd); Listener btnListener = new Listener() { public void handleEvent(Event event) { chosenMF = (DeviceManufacturer) event.widget.getData("mf"); skinnedDialog.close(); } }; DeviceManager deviceManager = DeviceManagerFactory.getSingleton(); DeviceManufacturer[] mfs = deviceManager.getDeviceManufacturers(Device.DT_MEDIA_RENDERER); for (DeviceManufacturer mf : mfs) { DeviceTemplate[] deviceTemplates = mf.getDeviceTemplates(); boolean hasNonAuto = false; for (DeviceTemplate deviceTemplate : deviceTemplates) { if (!deviceTemplate.isAuto()) { hasNonAuto = true; break; } } if (!hasNonAuto) { continue; } Button button = new Button(area, SWT.PUSH); button.setText(mf.getName()); button.setData("mf", mf); button.addListener(SWT.MouseUp, btnListener); } } skinnedDialog.getShell().pack(); skinnedDialog.open(); } public static interface ClosedListener { public void MfChooserClosed(DeviceManufacturer mf); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/DevicesFTUX.java0000644000175000017500000002663111275141740024366 0ustar adrianadrian/** * Created on Mar 7, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.events.*; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.installer.*; import org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage; import org.gudy.azureus2.plugins.update.UpdateCheckInstance; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.devices.Device; import com.aelitis.azureus.core.devices.DeviceManager; import com.aelitis.azureus.core.devices.DeviceManagerFactory; import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger; import com.aelitis.azureus.ui.swt.browser.BrowserContext; import com.aelitis.azureus.ui.swt.browser.listener.*; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; import com.aelitis.azureus.util.ConstantsVuze; /** * @author TuxPaper * @created Mar 7, 2009 * */ public class DevicesFTUX { private static final String URL_LEARN_MORE = "http://www.vuze.com/devices/qos.start"; private static final String URL_DEVICES_INFO = "http://www.vuze.com/devices/turnon.start"; public static DevicesFTUX instance; Shell shell; private Browser browser; private Button checkITunes; private Button btnInstall; private Button btnCancel; private Composite install_area; private Button checkQOS; private Composite install_area_parent; /** * @return * * @since 4.1.0.5 */ private boolean isDisposed() { return shell.isDisposed(); } /** * * * @since 4.1.0.5 */ private void setFocus() { shell.forceActive(); shell.forceFocus(); } private void open() { // This is a simple dialog box, so instead of using SkinnedDialog, we'll // just built it old school shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM); shell.setText(MessageText.getString("devices.turnon.title")); Utils.setShellIcon(shell); try { browser = Utils.createSafeBrowser(shell, SWT.NONE); if (browser != null) { BrowserContext context = new BrowserContext("DevicesFTUX", browser, null, true); context.addMessageListener(new TorrentListener()); context.addMessageListener(new VuzeListener()); context.addMessageListener(new DisplayListener(browser)); context.addMessageListener(new ConfigListener(browser)); } } catch (Throwable t) { } Label lblInfo = new Label(shell, SWT.WRAP); Messages.setLanguageText(lblInfo, "devices.turnon.prepageload"); checkITunes = new Button(shell, SWT.CHECK); checkITunes.setSelection(true); Messages.setLanguageText(checkITunes, "devices.turnon.itunes"); checkQOS = new Button(shell, SWT.CHECK); checkQOS.setSelection(true); Messages.setLanguageText(checkQOS, "devices.turnon.qos"); Link lblLearnMore = new Link(shell, SWT.NONE); lblLearnMore.setText("" + MessageText.getString("label.learnmore") + ""); lblLearnMore.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Utils.launch(e.text); } }); btnInstall = new Button(shell, SWT.NONE); Messages.setLanguageText(btnInstall, "Button.turnon"); btnInstall.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { boolean sendQOS = checkQOS.getSelection(); doInstall(checkITunes.getSelection(), sendQOS); } }); shell.setDefaultButton(btnInstall); btnCancel = new Button(shell, SWT.NONE); Messages.setLanguageText(btnCancel, "Button.cancel"); btnCancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { shell.dispose(); } }); shell.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { shell.dispose(); } } }); install_area_parent = new Composite(shell, SWT.NONE); install_area_parent.setLayout(new FormLayout()); install_area_parent.setVisible(false); install_area = new Composite(install_area_parent, SWT.NONE); FormLayout formLayout = new FormLayout(); formLayout.marginWidth = formLayout.marginHeight = 0; shell.setLayout(formLayout); FormData fd; fd = Utils.getFilledFormData(); fd.bottom = new FormAttachment(checkITunes, -5); fd.top = new FormAttachment(0, 8); fd.left = new FormAttachment(0, 8); fd.right = new FormAttachment(100, -8); lblInfo.setLayoutData(fd); fd = Utils.getFilledFormData(); fd.bottom = new FormAttachment(checkITunes, -5); fd.width = 550; fd.height = 490; browser.setLayoutData(fd); fd = new FormData(); fd.bottom = new FormAttachment(100, -10); fd.right = new FormAttachment(100, -10); btnCancel.setLayoutData(fd); fd = new FormData(); fd.bottom = new FormAttachment(100, -10); fd.right = new FormAttachment(btnCancel, -12); btnInstall.setLayoutData(fd); fd = new FormData(); fd.bottom = new FormAttachment(checkQOS, -3); fd.left = new FormAttachment(0, 10); fd.right = new FormAttachment(btnInstall, -12); checkITunes.setLayoutData(fd); fd = new FormData(); fd.bottom = new FormAttachment(100, -5); fd.left = new FormAttachment(0, 10); checkQOS.setLayoutData(fd); fd = new FormData(); fd.top = new FormAttachment(checkQOS, 0, SWT.CENTER); fd.left = new FormAttachment(checkQOS, 5); lblLearnMore.setLayoutData(fd); fd = new FormData(); fd.top = new FormAttachment(browser, 0); fd.bottom = new FormAttachment(100, 0); fd.left = new FormAttachment(0, 0); fd.right = new FormAttachment(100, 0); install_area_parent.setLayoutData(fd); fd = new FormData(); fd.height = btnInstall.computeSize(SWT.DEFAULT, SWT.DEFAULT).y; fd.bottom = new FormAttachment(100, -5); fd.left = new FormAttachment(0, 5); fd.right = new FormAttachment(100, -12); install_area.setLayoutData(fd); String url = ConstantsVuze.getDefaultContentNetwork().appendURLSuffix( URL_DEVICES_INFO, false, true); browser.setUrl(url); shell.pack(); Utils.centreWindow(shell); btnInstall.setFocus(); shell.open(); } /** * @param sendQos * @param selection * * @since 4.1.0.5 */ protected void doInstall(final boolean itunes, final boolean sendQOS) { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { _doInstall(core, itunes, sendQOS); } }); } protected void _doInstall(AzureusCore core, boolean itunes, boolean sendQOS) { COConfigurationManager.setParameter(PlatformDevicesMessenger.CFG_SEND_QOS, sendQOS); if (sendQOS) { try { PlatformDevicesMessenger.qosTurnOn(itunes); } catch (Throwable ignore) { } try { // catch any devices we found before installing additional plugins DeviceManager device_manager = DeviceManagerFactory.getSingleton(); Device[] devices = device_manager.getDevices(); for (Device device : devices) { try { PlatformDevicesMessenger.qosFoundDevice(device); } catch (Throwable ignore) { } } } catch (Throwable ignore) { } } List plugins = new ArrayList(2); final PluginInstaller installer = core.getPluginManager().getPluginInstaller(); StandardPlugin vuze_plugin = null; try { vuze_plugin = installer.getStandardPlugin("vuzexcode"); } catch (Throwable e) { } if (vuze_plugin != null && !vuze_plugin.isAlreadyInstalled()) { plugins.add(vuze_plugin); } if (itunes) { StandardPlugin itunes_plugin = null; try { itunes_plugin = installer.getStandardPlugin("azitunes"); } catch (Throwable e) { } if (itunes_plugin != null && !itunes_plugin.isAlreadyInstalled()) { plugins.add(itunes_plugin); } } if (plugins.size() == 0) { close(); return; } InstallablePlugin[] installablePlugins = plugins.toArray(new InstallablePlugin[0]); try { install_area_parent.setVisible(true); install_area_parent.moveAbove(null); Map properties = new HashMap(); properties.put(UpdateCheckInstance.PT_UI_STYLE, UpdateCheckInstance.PT_UI_STYLE_SIMPLE); properties.put(UpdateCheckInstance.PT_UI_PARENT_SWT_COMPOSITE, install_area); properties.put(UpdateCheckInstance.PT_UI_DISABLE_ON_SUCCESS_SLIDEY, true); installer.install(installablePlugins, false, properties, new PluginInstallationListener() { public void completed() { close(); SideBarEntrySWT sb = SideBar.getEntry( SideBar.SIDEBAR_SECTION_DEVICES ); SideBarVitalityImage[] vitalityImages = sb.getVitalityImages(); for (SideBarVitalityImage vi : vitalityImages) { if (vi.getImageID().contains("turnon")) { vi.setVisible(false); } } } public void cancelled(){ close(); } public void failed(PluginException e) { Debug.out(e); //Utils.openMessageBox(Utils.findAnyShell(), SWT.OK, "Error", // e.toString()); close(); } }); } catch (Throwable e) { Debug.printStackTrace(e); } } /** * * * @since 4.1.0.5 */ protected void close() { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (shell != null && !shell.isDisposed()) { shell.dispose(); } } }); } /** * @return * * @since 4.1.0.5 */ public static boolean ensureInstalled() { DeviceManager device_manager = DeviceManagerFactory.getSingleton(); if (device_manager.getTranscodeManager().getProviders().length == 0) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (instance == null || instance.isDisposed()) { instance = new DevicesFTUX(); instance.open(); } else { instance.setFocus(); } } }); return false; } return true; } public static void showForDebug() { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (instance == null || instance.isDisposed()) { instance = new DevicesFTUX(); instance.open(); } else { instance.setFocus(); } } }); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/TranscodeChooser.java0000644000175000017500000005615711267524522025554 0ustar adrianadrian/** * Created on Mar 1, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import com.aelitis.azureus.core.devices.*; import com.aelitis.azureus.core.devices.Device; import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader.ImageDownloaderListener; import com.aelitis.azureus.ui.swt.skin.*; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter; import com.aelitis.azureus.ui.swt.utils.ColorCache; import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog; /** * @author TuxPaper * @created Mar 1, 2009 * */ public abstract class TranscodeChooser { private static final String skinFile = "skin3_transcodechooser"; private static final String shellSkinObjectID = "shell"; private Shell shell; private SWTSkin skin; private Font fontDevice; protected TranscodeTarget selectedTranscodeTarget; protected TranscodeProfile selectedProfile; protected DeviceTemplate selectedDeviceTemplate; private SWTSkinObjectContainer soList; private Shell mainShell; private SWTSkinObjectContainer soBottomContainer; private Button btnNoPrompt; private int transcodeRequirement; private java.util.List listImageIDsToRelease = new ArrayList(); private SWTSkinObjectText soInfoTitle; private SWTSkinObjectText soInfoText; private Font fontDeviceDesc; private TranscodeProfile[] transcodeProfiles; public TranscodeChooser() { this((TranscodeTarget) null); } public TranscodeChooser(TranscodeTarget tt) { selectedTranscodeTarget = tt; } public TranscodeChooser(TranscodeProfile[] transcodeProfiles) { this.transcodeProfiles = transcodeProfiles; } public void show() { // Check if plugin is installed if (!DevicesFTUX.ensureInstalled()) { return; } mainShell = UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell(); shell = ShellFactory.createShell(mainShell, SWT.DIALOG_TRIM | SWT.RESIZE); Utils.setShellIcon(shell); skin = SWTSkinFactory.getNonPersistentInstance( SkinnedDialog.class.getClassLoader(), "com/aelitis/azureus/ui/skin/", skinFile + ".properties"); skin.initialize(shell, shellSkinObjectID); shell.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { shell.close(); } } }); shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { closed(); } }); skin.layout(); SWTSkinObject soBottom = skin.getSkinObject("bottom"); if (soBottom instanceof SWTSkinObjectContainer) { soBottomContainer = (SWTSkinObjectContainer) soBottom; soBottomContainer.addListener(new SWTSkinObjectListener() { public Object eventOccured(SWTSkinObject skinObject, int eventType, Object params) { if (eventType == EVENT_SHOW) { skinObject.removeListener(this); initBottom(); } return null; } }); soBottomContainer.setVisible(selectedTranscodeTarget != null); } soList = (SWTSkinObjectContainer) skin.getSkinObject("list"); if (soList != null) { if (transcodeProfiles != null) { createProfileList(soList, "drop"); } else if (selectedTranscodeTarget == null) { createDeviceList(soList); } else { transcodeProfiles = selectedTranscodeTarget.getTranscodeProfiles(); createProfileList(soList, "drop"); } } // we may have disposed of shell during device/profile list building // (ex. no devices avail) if (shell.isDisposed()) { return; } shell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { Utils.disposeSWTObjects(new Object[] { fontDevice, fontDeviceDesc }); for (String id : listImageIDsToRelease) { ImageLoader.getInstance().releaseImage(id); } } }); shell.open(); } /** * @param soBottomContainer2 * * @since 4.1.0.5 */ protected void initBottom() { Composite composite = soBottomContainer.getComposite(); btnNoPrompt = new Button(composite, SWT.CHECK); Messages.setLanguageText(btnNoPrompt, "option.rememberthis"); Label lblXCode = new Label(composite, SWT.NONE); lblXCode.setText(MessageText.getString("device.xcode")); final Combo cmbXCode = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY); cmbXCode.add(MessageText.getString("device.xcode.whenreq")); cmbXCode.add(MessageText.getString("device.xcode.always")); cmbXCode.add(MessageText.getString("device.xcode.never")); transcodeRequirement = selectedTranscodeTarget.getTranscodeRequirement(); switch (transcodeRequirement) { case TranscodeTarget.TRANSCODE_ALWAYS: cmbXCode.select(1); break; case TranscodeTarget.TRANSCODE_NEVER: cmbXCode.select(2); break; case TranscodeTarget.TRANSCODE_WHEN_REQUIRED: default: cmbXCode.select(0); break; } cmbXCode.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { int i = cmbXCode.getSelectionIndex(); switch (i) { case 0: transcodeRequirement = TranscodeTarget.TRANSCODE_WHEN_REQUIRED; break; case 1: transcodeRequirement = TranscodeTarget.TRANSCODE_ALWAYS; break; case 2: transcodeRequirement = TranscodeTarget.TRANSCODE_NEVER; break; } } public void widgetDefaultSelected(SelectionEvent e) { } }); FormData fd; fd = new FormData(); fd.left = new FormAttachment(0, 10); fd.top = new FormAttachment(cmbXCode, 0, SWT.CENTER); btnNoPrompt.setLayoutData(fd); fd = new FormData(); fd.right = new FormAttachment(100, -10); fd.top = new FormAttachment(0, 5); fd.bottom = new FormAttachment(100, -5); cmbXCode.setLayoutData(fd); fd = new FormData(); fd.right = new FormAttachment(cmbXCode, -5); fd.top = new FormAttachment(cmbXCode, 0, SWT.CENTER); lblXCode.setLayoutData(fd); int userMode = COConfigurationManager.getIntParameter("User Mode"); if (userMode == 0) { lblXCode.setVisible(false); cmbXCode.setVisible(false); } Point computeSize = shell.computeSize(300, SWT.DEFAULT, true); shell.setSize(computeSize); } /** * @param soList * * @since 4.1.0.5 */ private void createProfileList(SWTSkinObjectContainer soList, String source) { if (selectedTranscodeTarget == null && selectedDeviceTemplate == null) { new MessageBoxShell(SWT.OK, "No Device", "No Device Selected!?").open(null); shell.dispose(); return; } if (selectedTranscodeTarget != null) { try { PlatformDevicesMessenger.qosTranscodeRequest(selectedTranscodeTarget, source); } catch (Throwable ignore) { } try { TranscodeProfile defaultProfile = selectedTranscodeTarget.getDefaultTranscodeProfile(); if (defaultProfile != null) { // user chose not to ask selectedProfile = defaultProfile; shell.dispose(); return; } } catch (TranscodeException e) { } } if (transcodeProfiles.length == 0) { new MessageBoxShell(SWT.OK, "No Profiles", "No Profiles for " + selectedTranscodeTarget.getDevice().getName()).open(null); shell.dispose(); return; } if (transcodeProfiles.length == 1) { selectedProfile = transcodeProfiles[0]; shell.dispose(); return; } Arrays.sort(transcodeProfiles, new Comparator() { public int compare(TranscodeProfile o1, TranscodeProfile o2) { return o1.getName().compareToIgnoreCase(o2.getName()); } }); Composite parent = soList.getComposite(); if (parent.getChildren().length > 0) { Utils.disposeComposite(parent, false); } soInfoTitle = (SWTSkinObjectText) skin.getSkinObject("info-title"); soInfoText = (SWTSkinObjectText) skin.getSkinObject("info-text"); resetProfileInfoBox(false); RowLayout layout = new RowLayout(SWT.HORIZONTAL); layout.spacing = 0; layout.marginLeft = layout.marginRight = 0; layout.wrap = true; layout.justify = true; layout.fill = true; parent.setLayout(layout); Listener listenerMouseInout = new Listener() { public void handleEvent(Event event) { Widget widget = (event.widget instanceof Canvas) ? ((Canvas) event.widget).getParent() : event.widget; Composite c = TranscodeChooser.this.soList.getComposite(); Rectangle bounds = c.getClientArea(); c.redraw(bounds.x, bounds.y, bounds.width, bounds.height, true); TranscodeProfile profile = (TranscodeProfile) widget.getData("obj"); if (profile == null) { return; } if (event.type == SWT.MouseEnter) { String description = profile.getDescription(); if (description == null || description.length() == 0) { resetProfileInfoBox(true); } else { if (soInfoTitle != null) { soInfoTitle.setTextID( "devices.choose.profile.info.title.selected", new String[] { profile.getName() }); } if (soInfoText != null) { soInfoText.setText(description); Point computeSize = shell.computeSize( shell.getClientArea().width, SWT.DEFAULT, true); if (computeSize.y > shell.getSize().y) { shell.setSize(computeSize); } } } } } }; parent.addListener(SWT.MouseEnter, new Listener() { public void handleEvent(Event event) { resetProfileInfoBox(true); } }); Listener clickListener = new Listener() { boolean down = false; public void handleEvent(Event event) { if (event.type == SWT.MouseDown) { down = true; } else if (event.type == SWT.MouseUp && down) { Widget widget = (event.widget instanceof Label) ? ((Label) event.widget).getParent() : event.widget; selectedProfile = (TranscodeProfile) widget.getData("obj"); if (selectedProfile == null) { Debug.out("profile is null!"); } else { if (btnNoPrompt != null) { if (btnNoPrompt.getSelection()) { selectedTranscodeTarget.setDefaultTranscodeProfile(selectedProfile); } } } shell.dispose(); down = false; } } }; GridData gridData; for (TranscodeProfile profile : transcodeProfiles) { addImageBox(parent, clickListener, listenerMouseInout, profile, profile.getIconURL(), profile.getName()); } SWTSkinObjectText soTitle = (SWTSkinObjectText) skin.getSkinObject("title"); if (soTitle != null) { soTitle.setTextID("devices.choose.profile.title"); } SWTSkinObjectText soSubTitle = (SWTSkinObjectText) skin.getSkinObject("subtitle"); if (soSubTitle != null) { soSubTitle.setTextID("label.clickone"); } if (soBottomContainer != null) { soBottomContainer.setVisible(true); } SWTSkinObjectContainer soButtonBottomArea = (SWTSkinObjectContainer) skin.getSkinObject("button-bottom"); if (soButtonBottomArea != null) { soButtonBottomArea.setVisible(false); } Point computeSize = shell.computeSize(600, SWT.DEFAULT, true); shell.setSize(computeSize); Utils.centerWindowRelativeTo(shell, mainShell); } /** * * * @since 4.1.0.5 */ public static void addImageBox(Composite parent, Listener clickListener, Listener listenerMouseInout, Object obj, String iconURL, String name) { GridData gridData; final Shell shell = parent.getShell(); final Composite c = new Composite(parent, SWT.NONE); GridLayout clayout = new GridLayout(); clayout.marginWidth = clayout.horizontalSpacing = 0; c.setLayout(clayout); c.setCursor(c.getDisplay().getSystemCursor(SWT.CURSOR_HAND)); c.addListener(SWT.MouseUp, clickListener); c.addListener(SWT.MouseDown, clickListener); c.setData("obj", obj); if (listenerMouseInout != null) { c.addListener(SWT.MouseEnter, listenerMouseInout); c.addListener(SWT.MouseExit, listenerMouseInout); } final Canvas lblImage = new Canvas(c, SWT.DOUBLE_BUFFERED); if (listenerMouseInout != null) { lblImage.addListener(SWT.MouseEnter, listenerMouseInout); lblImage.addListener(SWT.MouseExit, listenerMouseInout); } lblImage.addListener(SWT.MouseUp, clickListener); lblImage.addListener(SWT.MouseDown, clickListener); lblImage.setData("obj", obj); lblImage.addListener(SWT.Paint, new Listener() { public void handleEvent(Event event) { Image image = (Image) lblImage.getData("Image"); if (image != null) { Rectangle bounds = image.getBounds(); Rectangle area = lblImage.getBounds(); Rectangle carea = c.getBounds(); Point ptInDisplay = c.toDisplay(0, 0); event.gc.setAdvanced(true); event.gc.setAntialias(SWT.ON); event.gc.setLineWidth(2); if (new Rectangle(ptInDisplay.x, ptInDisplay.y, carea.width, carea.height).contains(event.display.getCursorLocation())) { //if (event.display.getCursorControl() == lblImage) { Color color1 = ColorCache.getColor(event.gc.getDevice(), 252, 253, 255); Color color2 = ColorCache.getColor(event.gc.getDevice(), 169, 195, 252); Pattern pattern = new Pattern(event.gc.getDevice(), 0, 0, 0, area.height, color1, 0, color2, 200); event.gc.setBackgroundPattern(pattern); event.gc.fillRoundRectangle(0, 0, area.width - 1, area.height - 1, 20, 20); event.gc.setBackgroundPattern(null); pattern.dispose(); pattern = new Pattern(event.gc.getDevice(), 0, 0, 0, area.height, color2, 50, color2, 255); event.gc.setForegroundPattern(pattern); event.gc.drawRoundRectangle(0, 0, area.width - 1, area.height - 1, 20, 20); event.gc.setForegroundPattern(null); pattern.dispose(); } event.gc.drawImage(image, bounds.x, bounds.y, bounds.width, bounds.height, 8, 5, bounds.width, bounds.height); } else { Rectangle ca = lblImage.getClientArea(); event.gc.drawRectangle(ca.x, ca.y, ca.width - 1, ca.height - 1); } } }); gridData = new GridData(GridData.FILL_VERTICAL); gridData.heightHint = 100; gridData.widthHint = 120; if (iconURL != null) { ImageLoader imageLoader = ImageLoader.getInstance(); Image image = imageLoader.getUrlImage(iconURL, new ImageDownloaderListener() { public void imageDownloaded(Image image, boolean returnedImmediately) { if (!returnedImmediately) { lblImage.setData("Image", image); Rectangle bounds = image.getBounds(); GridData gridData = (GridData) lblImage.getLayoutData(); gridData.heightHint = bounds.height + 10; gridData.widthHint = bounds.width + 16; lblImage.setLayoutData(gridData); lblImage.getShell().layout(new Control[] { lblImage }); Point computeSize = shell.computeSize(600, SWT.DEFAULT, true); shell.setSize(computeSize); } } }); if (image != null) { lblImage.setData("Image", image); Rectangle bounds = image.getBounds(); gridData.heightHint = bounds.height + 10; gridData.widthHint = bounds.width + 16; } } lblImage.setLayoutData(gridData); Label label = new Label(c, SWT.WRAP | SWT.CENTER); if (listenerMouseInout != null) { label.addListener(SWT.MouseEnter, listenerMouseInout); } label.addListener(SWT.MouseUp, clickListener); label.addListener(SWT.MouseDown, clickListener); gridData = new GridData(GridData.FILL_HORIZONTAL); label.setLayoutData(gridData); String s = name; //s += " (via " + profile.getProvider().getName() + ")"; label.setText(s); label.setCursor(c.getDisplay().getSystemCursor(SWT.CURSOR_HAND)); } /** * * * @param layout * @since 4.1.0.5 */ protected void resetProfileInfoBox(boolean layout) { if (soInfoTitle != null) { soInfoTitle.setTextID("devices.choose.profile.info.title"); } if (soInfoText != null) { soInfoText.setTextID("devices.choose.profile.info.text"); if (layout) { Point computeSize = shell.computeSize(shell.getClientArea().width, SWT.DEFAULT, true); shell.setSize(computeSize); } } } private void createDeviceList(SWTSkinObjectContainer soDeviceList) { Composite parent = soDeviceList.getComposite(); parent.setBackgroundMode(SWT.INHERIT_FORCE); FormLayout layout = new FormLayout(); layout.marginLeft = 10; layout.marginHeight = 15; parent.setLayout(layout); DeviceManager device_manager = DeviceManagerFactory.getSingleton(); Device[] devices = device_manager.getDevices(); if (devices.length == 0) { noDevices(); return; } Arrays.sort(devices, new Comparator() { public int compare(Device o1, Device o2) { return o1.getName().compareToIgnoreCase(o2.getName()); } }); fontDevice = Utils.getFontWithHeight(parent.getFont(), null, 16, SWT.BOLD); fontDeviceDesc = Utils.getFontWithHeight(parent.getFont(), null, 16, SWT.NONE); /** PaintListener paintListener = new PaintListener() { public void paintControl(PaintEvent e) { Rectangle ca = ((Composite) e.widget).getClientArea(); e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); e.gc.setBackground(e.display.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW)); e.gc.setAntialias(SWT.ON); e.gc.fillRoundRectangle(ca.x, ca.y, ca.width - 1, ca.height - 1, 10, 10); e.gc.drawRoundRectangle(ca.x, ca.y, ca.width - 1, ca.height - 1, 10, 10); } }; **/ boolean hide_generic = COConfigurationManager.getBooleanParameter( DeviceManagerUI.CONFIG_VIEW_HIDE_REND_GENERIC, true); int numDevices = 0; Button lastButton = null; for (Device device : devices) { if (device.getType() != Device.DT_MEDIA_RENDERER || device.isHidden() || !(device instanceof DeviceMediaRenderer)) { continue; } DeviceMediaRenderer renderer = (DeviceMediaRenderer) device; if (hide_generic && renderer.isGeneric()) { continue; } TranscodeTarget transcodeTarget = (TranscodeTarget) device; if (transcodeTarget.getTranscodeProfiles().length == 0) { continue; } String imageID = null; if (device instanceof DeviceMediaRenderer) { imageID = "image.sidebar.device." + ((DeviceMediaRenderer) device).getRendererSpecies() + ".big"; } lastButton = createDeviceButton(parent, device, device.getName(), device.getShortDescription(), imageID, lastButton); numDevices++; } if (numDevices == 0) { noDevices(); return; } SWTSkinObjectText soTitle = (SWTSkinObjectText) skin.getSkinObject("title"); if (soTitle != null) { soTitle.setTextID("devices.choose.device.title"); } SWTSkinObjectText soSubTitle = (SWTSkinObjectText) skin.getSkinObject("subtitle"); if (soSubTitle != null) { soSubTitle.setText(""); } SWTSkinObjectContainer soButtonBottomArea = (SWTSkinObjectContainer) skin.getSkinObject("button-bottom"); if (soButtonBottomArea != null) { soButtonBottomArea.setVisible(true); SWTSkinObjectButton soOk = (SWTSkinObjectButton) skin.getSkinObject("ok"); if (soOk != null) { shell.setDefaultButton((Button) soOk.getControl()); soOk.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { transcodeProfiles = selectedTranscodeTarget.getTranscodeProfiles(); createProfileList(soList, "chooser"); } }); } SWTSkinObjectButton soCancel = (SWTSkinObjectButton) skin.getSkinObject("cancel"); if (soCancel != null) { soCancel.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { shell.close(); } }); } } if (soBottomContainer != null) { soBottomContainer.setVisible(false); } //shell.pack(); Point computeSize = shell.computeSize(400, SWT.DEFAULT, true); shell.setSize(computeSize); shell.layout(true); Utils.centerWindowRelativeTo(shell, mainShell); } private Button createDeviceButton(Composite parent, Object deviceObj, String name, String shortDescription, String imageID, Button lastButton) { Button button = new Button(parent, SWT.LEFT | SWT.RADIO); StringBuffer sb = new StringBuffer(name); button.setFont(fontDevice); button.setData("Device", deviceObj); button.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { Object device = e.widget.getData("Device"); if (device instanceof TranscodeTarget) { selectedTranscodeTarget = (TranscodeTarget) device; } else if (device instanceof DeviceTemplate) { selectedDeviceTemplate = (DeviceTemplate) device; } } public void widgetDefaultSelected(SelectionEvent e) { } }); if (lastButton == null) { button.setSelection(true); if (deviceObj instanceof TranscodeTarget) { selectedTranscodeTarget = (TranscodeTarget) deviceObj; } } Image imgRenderer = null; if (imageID != null) { listImageIDsToRelease.add(imageID); imgRenderer = ImageLoader.getInstance().getImage(imageID); } if (ImageLoader.isRealImage(imgRenderer)) { button.setImage(imgRenderer); // buttons are center when they have an image.. // fill with a bunch of spaces so it left aligns //char[] c = new char[100]; //Arrays.fill(c, ' '); //sb.append(c); } else { sb.insert(0, ' '); } button.setText(sb.toString()); FormData fd = new FormData(); fd.left = new FormAttachment(0, 0); if (lastButton == null) { fd.top = new FormAttachment(0, 0); } else { fd.top = new FormAttachment(lastButton, 15); } button.setLayoutData(fd); if (shortDescription != null && shortDescription.length() > 0) { Label label = new Label(parent, SWT.None); label.setText("(" + shortDescription + ")"); fd = new FormData(); fd.top = new FormAttachment(button, 0, SWT.CENTER); fd.left = new FormAttachment(button, 5); label.setLayoutData(fd); } return button; } /** * * * @since 4.1.0.5 */ private void noDevices() { new MessageBoxShell( SWT.OK, "No Devices Found", "We couldn't find any devices. Maybe you didn't install the Vuze Transcoder Plugin?").open(null); shell.dispose(); } public abstract void closed(); public int getTranscodeRequirement() { return transcodeRequirement; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/DeviceInternetView.java0000644000175000017500000002170311172274330026031 0ustar adrianadrian/* * Created on Feb 2, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.ui.swt.devices; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT.TriggerInThread; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.devices.Device; import com.aelitis.azureus.plugins.net.netstatus.NetStatusPlugin; import com.aelitis.azureus.plugins.net.netstatus.swt.NetStatusPluginTester; public class DeviceInternetView extends DeviceManagerUI.categoryView { private DeviceManagerUI device_manager_ui; private NetStatusPlugin plugin; private Composite main; private Button start_button; private Button cancel_button; private StyledText log; private static final int selected_tests = NetStatusPluginTester.TEST_INBOUND | NetStatusPluginTester.TEST_OUTBOUND | NetStatusPluginTester.TEST_NAT_PROXIES; private NetStatusPluginTester current_test; private static final int LOG_NORMAL = 1; private static final int LOG_SUCCESS = 2; private static final int LOG_ERROR = 3; private static final int LOG_INFO = 4; private int log_type = LOG_NORMAL; protected DeviceInternetView( DeviceManagerUI dm_ui, String title ) { super( dm_ui, Device.DT_INTERNET, title ); device_manager_ui = dm_ui; } public void initialize( Composite parent ) { PluginInterface pi = device_manager_ui.getPluginInterface().getPluginManager().getPluginInterfaceByClass( NetStatusPlugin.class ); plugin = (NetStatusPlugin)pi.getPlugin(); main = new Composite( parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.marginTop = 4; layout.marginBottom = 4; layout.marginHeight = 4; layout.marginWidth = 4; main.setLayout(layout); GridData grid_data = new GridData(GridData.FILL_BOTH ); main.setLayoutData(grid_data); Label info_lab = new Label( main, SWT.NONE ); info_lab.setText( "Test your internet connection" ); // control Composite control = new Composite(main, SWT.NONE); layout = new GridLayout(); layout.numColumns = 3; layout.marginHeight = 4; layout.marginWidth = 4; control.setLayout(layout); grid_data = new GridData(GridData.FILL_HORIZONTAL); grid_data.horizontalSpan = 1; control.setLayoutData(grid_data); // start start_button = new Button( control, SWT.PUSH ); Messages.setLanguageText( start_button, "ConfigView.section.start"); start_button.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { start_button.setEnabled( false ); cancel_button.setEnabled( true ); startTest(); } }); // cancel cancel_button = new Button( control, SWT.PUSH ); Messages.setLanguageText( cancel_button, "UpdateWindow.cancel"); cancel_button.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { cancel_button.setEnabled( false ); cancelTest(); } }); cancel_button.setEnabled( false ); // log area log = new StyledText(main,SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER); grid_data = new GridData(GridData.FILL_BOTH); grid_data.horizontalSpan = 1; grid_data.horizontalIndent = 4; log.setLayoutData(grid_data); log.setIndent( 4 ); } protected void startTest() { CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD, new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { startTestSupport(core); } }); } protected void cancelTest() { new AEThread2( "NetStatus:cancel", true ) { public void run() { cancelTestSupport(); } }.start(); } protected void startTestSupport( AzureusCore core) { try{ synchronized( this ){ if ( current_test != null ){ Debug.out( "Test already running!!!!" ); return; } current_test = new NetStatusPluginTester( plugin, selected_tests, new NetStatusPluginTester.loggerProvider() { public void log( String str) { println( str ); } public void logSuccess( String str) { try{ log_type = LOG_SUCCESS; println( str ); }finally{ log_type = LOG_NORMAL; } } public void logInfo( String str) { try{ log_type = LOG_INFO; println( str ); }finally{ log_type = LOG_NORMAL; } } public void logFailure( String str) { try{ log_type = LOG_ERROR; println( str ); }finally{ log_type = LOG_NORMAL; } } }); } println( "Test starting", true ); current_test.run(core); println( current_test.isCancelled()?"Test Cancelled":"Test complete" ); }catch( Throwable e ){ }finally{ try{ Composite c = main; if ( c != null && !c.isDisposed()){ try{ c.getDisplay().asyncExec( new Runnable() { public void run() { if ( !start_button.isDisposed()){ start_button.setEnabled( true ); } if ( !cancel_button.isDisposed()){ cancel_button.setEnabled( false ); } } }); }catch( Throwable e ){ } } }finally{ synchronized( this ){ current_test.cancel(); current_test = null; } } } } protected void println( String str ) { print( str + "\n", false ); } protected void println( String str, boolean clear_first ) { print( str + "\n", clear_first ); } protected void print( final String str, final boolean clear_first ) { if ( !( log.isDisposed() || log.getDisplay().isDisposed())){ final int f_log_type = log_type; log.getDisplay().asyncExec( new Runnable() { public void run() { if ( log.isDisposed()){ return; } int start; if ( clear_first ){ start = 0; log.setText( str ); }else{ start = log.getText().length(); log.append( str ); } Color color; if ( f_log_type == LOG_NORMAL ){ color = Colors.black; }else if ( f_log_type == LOG_SUCCESS ){ color = Colors.green; }else if ( f_log_type == LOG_INFO ){ color = Colors.blue; }else{ color = Colors.red; } StyleRange styleRange = new StyleRange(); styleRange.start = start; styleRange.length = str.length(); styleRange.foreground = color; log.setStyleRange(styleRange); log.setSelection( log.getText().length()); } }); } } protected void cancelTestSupport() { synchronized( this ){ if ( current_test != null ){ println( "Cancelling test..." ); current_test.cancel(); } } } public Composite getComposite() { return( main ); } public void delete() { super.delete(); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/SBC_DevicesODView.java0000644000175000017500000003366011272502260025417 0ustar adrianadrian/** * Created on Feb 24, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.devices.Device; import com.aelitis.azureus.core.devices.DeviceListener; import com.aelitis.azureus.core.devices.DeviceOfflineDownload; import com.aelitis.azureus.core.devices.DeviceOfflineDownloader; import com.aelitis.azureus.core.devices.DeviceOfflineDownloaderListener; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.table.*; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.swt.columns.torrent.ColumnThumbnail; import com.aelitis.azureus.ui.swt.devices.columns.*; import com.aelitis.azureus.ui.swt.skin.SWTSkinObject; import com.aelitis.azureus.ui.swt.views.skin.SkinView; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; public class SBC_DevicesODView extends SkinView implements UIUpdatable, IconBarEnabler { public static final String TABLE_RCM = "DevicesOD"; private static boolean columnsAdded = false; private DeviceOfflineDownloader device; private TableViewSWTImpl tv_downloads; private SideBarEntrySWT sidebar_entry; private Composite control_parent; public Object skinObjectInitialShow( SWTSkinObject skinObject, Object params ) { AzureusCoreFactory.addCoreRunningListener( new AzureusCoreRunningListener() { public void azureusCoreRunning( AzureusCore core ) { initColumns( core ); } }); SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); if ( sidebar != null ){ sidebar_entry = sidebar.getCurrentEntry(); sidebar_entry.setIconBarEnabler( this ); device = (DeviceOfflineDownloader)sidebar_entry.getDatasource(); } return null; } private void initColumns( AzureusCore core ) { synchronized( SBC_DevicesODView.class ){ if ( columnsAdded ){ return; } columnsAdded = true; } UIManager uiManager = PluginInitializer.getDefaultInterface().getUIManager(); TableManager tableManager = uiManager.getTableManager(); tableManager.registerColumn( DeviceOfflineDownload.class, ColumnThumbnail.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnThumbnail(column); column.setWidth(70); } }); tableManager.registerColumn( DeviceOfflineDownload.class, ColumnOD_Name.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnOD_Name(column); } }); tableManager.registerColumn( DeviceOfflineDownload.class, ColumnOD_Status.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnOD_Status(column); } }); tableManager.registerColumn( DeviceOfflineDownload.class, ColumnOD_Completion.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnOD_Completion(column); } }); tableManager.registerColumn( DeviceOfflineDownload.class, ColumnOD_Remaining.COLUMN_ID, new TableColumnCreationListener() { public void tableColumnCreated(TableColumn column) { new ColumnOD_Remaining(column); } }); } public Object skinObjectShown( SWTSkinObject skinObject, Object params ) { super.skinObjectShown(skinObject, params); SWTSkinObject so_list = getSkinObject("devicesod-list"); if ( so_list != null ){ initTable((Composite) so_list.getControl()); } return null; } public Object skinObjectHidden( SWTSkinObject skinObject, Object params ) { synchronized( this ){ if ( tv_downloads != null ){ tv_downloads.delete(); tv_downloads = null; } } Utils.disposeSWTObjects(new Object[] { control_parent, }); return( super.skinObjectHidden(skinObject, params)); } public Object skinObjectDestroyed( SWTSkinObject skinObject, Object params ) { synchronized( this ){ if ( tv_downloads != null ){ tv_downloads.delete(); tv_downloads = null; } } Utils.disposeSWTObjects(new Object[] { control_parent, }); return( super.skinObjectDestroyed(skinObject, params)); } private void initTable( final Composite control ) { control_parent = new Composite(control, SWT.NONE); control_parent.setLayoutData(Utils.getFilledFormData()); final StackLayout stack_layout = new StackLayout(); control_parent.setLayout( stack_layout ); // enabled final Composite enabled_device_parent = new Composite( control_parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginHeight = layout.marginWidth = layout.verticalSpacing = layout.horizontalSpacing = 0; enabled_device_parent.setLayout(layout); tv_downloads = new TableViewSWTImpl( DeviceOfflineDownload.class, TABLE_RCM, TABLE_RCM, new TableColumnCore[0], ColumnOD_Name.COLUMN_ID, SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL ); tv_downloads.setRowDefaultHeight(50); tv_downloads.setHeaderVisible(true); tv_downloads.addSelectionListener( new TableSelectionListener() { public void selected( TableRowCore[] row ) { refreshIconBar(); } public void mouseExit( TableRowCore row ) { } public void mouseEnter( TableRowCore row ) { } public void focusChanged( TableRowCore focus ) { refreshIconBar(); } public void deselected( TableRowCore[] rows) { refreshIconBar(); } public void defaultSelected(TableRowCore[] rows, int stateMask) { refreshIconBar(); } protected void refreshIconBar() { SelectedContentManager.clearCurrentlySelectedContent(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.refreshIconBar(); } } }, false ); tv_downloads.addLifeCycleListener( new TableLifeCycleListener() { private final TableViewSWTImpl f_table = tv_downloads; private Set download_set = new HashSet(); private boolean destroyed; private DeviceOfflineDownloaderListener od_listener = new DeviceOfflineDownloaderListener() { public void downloadAdded( final DeviceOfflineDownload download ) { synchronized( download_set ){ if ( destroyed ){ return; } if ( download_set.contains( download )){ return; } download_set.add( download ); } Utils.execSWTThread( new Runnable() { public void run() { if ( tv_downloads == f_table && !f_table.isDisposed()){ synchronized( download_set ){ if ( destroyed ){ return; } } f_table.addDataSources( new DeviceOfflineDownload[]{ download }); } } }); } public void downloadChanged( final DeviceOfflineDownload download ) { synchronized( download_set ){ if ( destroyed ){ return; } if ( !download_set.contains( download )){ return; } } Utils.execSWTThread( new Runnable() { public void run() { if ( tv_downloads == f_table && !f_table.isDisposed()){ synchronized( download_set ){ if ( destroyed ){ return; } } TableRowCore row = f_table.getRow( download ); if ( row != null ){ row.refresh(true ); } } } }); } public void downloadRemoved( final DeviceOfflineDownload download ) { synchronized( download_set ){ if ( destroyed ){ return; } if ( !download_set.remove( download )){ return; } } Utils.execSWTThread( new Runnable() { public void run() { if ( tv_downloads == f_table && !f_table.isDisposed()){ synchronized( download_set ){ if ( destroyed ){ return; } } f_table.removeDataSources( new DeviceOfflineDownload[]{ download }); } } }); } }; public void tableViewInitialized() { device.addListener( od_listener ); DeviceOfflineDownload[] downloads = device.getDownloads(); final ArrayList new_downloads = new ArrayList( downloads.length ); synchronized( download_set ){ if ( destroyed ){ return; } for ( DeviceOfflineDownload download: downloads ){ if ( !download_set.contains( download )){ download_set.add( download ); new_downloads.add( download ); } } } if ( new_downloads.size() > 0 ){ Utils.execSWTThread( new Runnable() { public void run() { if ( tv_downloads == f_table && !f_table.isDisposed()){ synchronized( download_set ){ if ( destroyed ){ return; } } f_table.addDataSources( new_downloads.toArray( new DeviceOfflineDownload[ new_downloads.size()])); } } }); } } public void tableViewDestroyed() { device.removeListener( od_listener ); synchronized( download_set ){ destroyed = true; download_set.clear(); } } }); tv_downloads.initialize( enabled_device_parent ); // disabled final Composite disabled_device_parent = new Composite( control_parent, SWT.NONE); layout = new GridLayout(); layout.marginHeight = layout.marginWidth = layout.verticalSpacing = layout.horizontalSpacing = 0; disabled_device_parent.setLayout(layout); Label l = new Label( disabled_device_parent, SWT.NULL ); GridData grid_data = new GridData( GridData.FILL_HORIZONTAL ); grid_data.horizontalIndent = 5; l.setLayoutData( grid_data ); l.setText( MessageText.getString( "device.is.disabled" )); device.addListener( new DeviceListener() { public void deviceChanged( Device d ) { Composite x = device.isEnabled()?enabled_device_parent:disabled_device_parent; if ( x.isDisposed()){ device.removeListener( this ); }else{ if ( x != stack_layout.topControl ){ Utils.execSWTThread( new Runnable() { public void run() { Composite x = device.isEnabled()?enabled_device_parent:disabled_device_parent; if ( !x.isDisposed() && x != stack_layout.topControl ){ stack_layout.topControl = x; control.layout( true, true ); } } }); } } } }); stack_layout.topControl = device.isEnabled()?enabled_device_parent:disabled_device_parent; control.layout(true); } public boolean isEnabled( String key ) { return( false ); } public boolean isSelected( String key ) { return( false ); } public void itemActivated( String key ) { } public String getUpdateUIName() { return( "DevicesODView" ); } public void updateUI() { if ( tv_downloads != null ){ tv_downloads.refreshTable( false ); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/DevicesODFTUX.java0000644000175000017500000003010611307644112024576 0ustar adrianadrian/** * Created on Mar 7, 2009 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.devices; import java.net.URLEncoder; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.LinkLabel; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import com.aelitis.azureus.core.devices.DeviceManagerException; import com.aelitis.azureus.core.devices.DeviceOfflineDownloader; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; /** * @author TuxPaper * @created Mar 7, 2009 * */ public class DevicesODFTUX { private static final String URL_LEARN_MORE = "http://www.vuze.com/devices/offlinedownloader.start"; private DeviceOfflineDownloader device; private Display display; private Shell shell; private Font boldFont; private Font titleFont; private Font subTitleFont; private Font textInputFont; private Button turnOnButton; private Label noSpaceWarning; private String dev_image_key; private ImageLoader imageLoader; protected DevicesODFTUX( DeviceOfflineDownloader _device ) throws DeviceManagerException { device = _device; final long avail = device.getSpaceAvailable( false ); Utils.execSWTThread( new AERunnable() { public void runSupport() { open( avail == 0 ); } }); } private void open( boolean no_space_available ) { imageLoader = ImageLoader.getInstance(); shell = ShellFactory.createMainShell(SWT.TITLE | SWT.CLOSE | SWT.RESIZE); shell.setSize(650,400); Utils.centreWindow(shell); shell.setMinimumSize(550,400); display = shell.getDisplay(); Utils.setShellIcon(shell); createFonts(); shell.setText(MessageText.getString("devices.activation")); shell.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event event) { imageLoader.releaseImage("wizard_header_bg"); if ( dev_image_key != null ){ imageLoader.releaseImage( dev_image_key ); } if(titleFont != null && !titleFont.isDisposed()) { titleFont.dispose(); } if(textInputFont != null && !textInputFont.isDisposed()) { textInputFont.dispose(); } if(boldFont != null && !boldFont.isDisposed()) { boldFont.dispose(); } if(subTitleFont != null && !subTitleFont.isDisposed()) { subTitleFont.dispose(); } } }); Composite header = new Composite(shell, SWT.NONE); header.setBackgroundMode(SWT.INHERIT_DEFAULT); header.setBackgroundImage(imageLoader.getImage("wizard_header_bg")); Label topSeparator = new Label(shell,SWT.SEPARATOR |SWT.HORIZONTAL); Composite main = new Composite(shell, SWT.NONE); main.setBackground( Colors.white ); Label bottomSeparator = new Label(shell,SWT.SEPARATOR |SWT.HORIZONTAL); Composite footer = new Composite(shell, SWT.NONE); FormLayout layout = new FormLayout(); shell.setLayout(layout); FormData data; data = new FormData(); data.top = new FormAttachment(0,0); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); //data.height = 50; header.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(header,0); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); topSeparator.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(topSeparator,0); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); data.bottom = new FormAttachment(bottomSeparator,0); main.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); data.bottom = new FormAttachment(footer,0); bottomSeparator.setLayoutData(data); data = new FormData(); data.bottom = new FormAttachment(100,0); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); footer.setLayoutData(data); populateHeader(header); populateMain( main, no_space_available ); populateFooter( footer, no_space_available ); shell.setDefaultButton(turnOnButton); shell.layout(); Utils.centreWindow(shell); turnOnButton.setFocus(); shell.open(); } private void populateHeader( Composite header) { header.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); Label title = new Label(header, SWT.WRAP); title.setFont(titleFont); title.setText( MessageText.getString("devices.turnon.title") ); FillLayout layout = new FillLayout(); layout.marginHeight = 10; layout.marginWidth = 10; header.setLayout(layout); } private void populateMain( Composite main, boolean no_space_available ) { String manufacturer = device.getManufacturer(); boolean is_belkin = manufacturer.toLowerCase().contains( "belkin"); Label image_area = new Label(main, SWT.NONE); String router_text; if ( is_belkin ){ dev_image_key = "image.device.logo.belkin"; router_text = MessageText.getString( "devices.router" ); }else{ router_text = MessageText.getString( "devices.od" ); } if ( dev_image_key != null ){ image_area.setImage(imageLoader.getImage( dev_image_key )); } Label text1 = new Label(main, SWT.WRAP); text1.setBackground( Colors.white ); text1.setFont( textInputFont ); text1.setText( MessageText.getString("devices.od.turnon.text1", new String[]{ (is_belkin?"Belkin":"Vuze" ) + " " + router_text })); Label text2 = new Label(main, SWT.WRAP); text2.setBackground( Colors.white ); text2.setFont( textInputFont ); text2.setText( MessageText.getString("devices.od.turnon.text2", new String[]{ router_text })); noSpaceWarning = new Label(main, SWT.WRAP); noSpaceWarning.setBackground( Colors.white ); noSpaceWarning.setFont( textInputFont ); noSpaceWarning.setText( MessageText.getString("devices.od.turnon.text3", new String[]{ router_text })); noSpaceWarning.setForeground( Colors.red ); noSpaceWarning.setVisible( no_space_available ); Label link = new Label(main, SWT.WRAP); link.setBackground( Colors.white ); link.setFont( textInputFont ); link.setText( MessageText.getString("devices.od.turnon.learn") ); String url = URL_LEARN_MORE; try{ url += "?man=" + URLEncoder.encode( manufacturer, "UTF-8" ); }catch( Throwable e ){ Debug.out( e ); } LinkLabel.makeLinkedLabel( link, url ); FormLayout layout = new FormLayout(); layout.marginHeight = 5; layout.marginWidth = 50; layout.spacing = 5; main.setLayout(layout); FormData data; data = new FormData(); data.top = new FormAttachment(0, 20); data.left = new FormAttachment(0); image_area.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(image_area,10); data.left = new FormAttachment(0); data.right = new FormAttachment(100); text1.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(text1, 10 ); data.left = new FormAttachment(0); data.right = new FormAttachment(100); text2.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(text2, 10 ); data.left = new FormAttachment(0); data.right = new FormAttachment(100); noSpaceWarning.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(noSpaceWarning, 10 ); data.left = new FormAttachment(0); link.setLayoutData(data); } private void createFonts() { FontData[] fDatas = shell.getFont().getFontData(); for(int i = 0 ; i < fDatas.length ; i++) { fDatas[i].setStyle(SWT.BOLD); } boldFont = new Font(display,fDatas); for(int i = 0 ; i < fDatas.length ; i++) { if(org.gudy.azureus2.core3.util.Constants.isOSX) { fDatas[i].setHeight(12); } else { fDatas[i].setHeight(10); } } subTitleFont = new Font(display,fDatas); for(int i = 0 ; i < fDatas.length ; i++) { if(org.gudy.azureus2.core3.util.Constants.isOSX) { fDatas[i].setHeight(17); } else { fDatas[i].setHeight(14); } } titleFont = new Font(display,fDatas); for(int i = 0 ; i < fDatas.length ; i++) { if(org.gudy.azureus2.core3.util.Constants.isOSX) { fDatas[i].setHeight(14); } else { fDatas[i].setHeight(12); } fDatas[i].setStyle(SWT.NONE); } textInputFont = new Font(display,fDatas); } private void populateFooter( Composite footer, final boolean no_space_available ) { final Button dont_ask_again = new Button( footer, SWT.CHECK ); dont_ask_again.setText(MessageText.getString("general.dont.ask.again")); dont_ask_again.setSelection( true ); Button cancelButton = new Button(footer,SWT.PUSH); cancelButton.setText(MessageText.getString("button.nothanks")); turnOnButton = new Button(footer,SWT.PUSH); turnOnButton.setText(MessageText.getString("Button.turnon")); FormLayout layout = new FormLayout(); layout.marginHeight = 5; layout.marginWidth = 5; layout.spacing = 5; footer.setLayout(layout); FormData data; data = new FormData(); data.left = new FormAttachment(0,45); data.right = new FormAttachment(turnOnButton); dont_ask_again.setLayoutData(data); data = new FormData(); data.right = new FormAttachment(100); data.width = 100; cancelButton.setLayoutData(data); data = new FormData(); data.right = new FormAttachment( cancelButton ); data.width = 100; turnOnButton.setLayoutData(data); turnOnButton.addListener( SWT.Selection, new Listener() { public void handleEvent( Event arg0 ) { device.setEnabled( true ); device.setShownFTUX(); shell.close(); } }); turnOnButton.setEnabled( !no_space_available ); new AEThread2( "scanner", true ) { private long last_avail = no_space_available?0:Long.MAX_VALUE; public void run() { while( !shell.isDisposed()){ try{ Thread.sleep(10*1000); final long avail = device.getSpaceAvailable( true ); if ( avail != last_avail ){ last_avail = avail; Utils.execSWTThread( new AERunnable() { public void runSupport() { if ( !turnOnButton.isDisposed()){ turnOnButton.setEnabled( avail > 0 ); } if ( !noSpaceWarning.isDisposed()){ noSpaceWarning.setVisible( avail <= 0 ); } } }); } }catch( Throwable e ){ } } } }.start(); cancelButton.addListener( SWT.Selection, new Listener() { public void handleEvent( Event arg0 ) { device.setEnabled( false ); if ( dont_ask_again.getSelection()){ device.setShownFTUX(); } shell.close(); } }); } protected void close() { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (shell != null && !shell.isDisposed()) { shell.dispose(); } } }); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/DeviceManagerUI.java0000644000175000017500000025447411301136114025222 0ustar adrianadrian/* * Created on Jan 27, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.ui.swt.devices; import java.io.File; import java.net.InetAddress; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.installer.PluginInstaller; import org.gudy.azureus2.plugins.installer.StandardPlugin; import org.gudy.azureus2.plugins.ui.*; import org.gudy.azureus2.plugins.ui.config.*; import org.gudy.azureus2.plugins.ui.menus.*; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.plugins.ui.sidebar.*; import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.plugins.ui.tables.TableRow; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.plugins.UISWTInputReceiver; import org.gudy.azureus2.ui.swt.plugins.UISWTInstance; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import org.gudy.azureus2.ui.swt.views.AbstractIView; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.devices.*; import com.aelitis.azureus.core.devices.DeviceManager.DeviceManufacturer; import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice; import com.aelitis.azureus.core.download.DiskManagerFileInfoFile; import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.UserPrompterResultListener; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.swt.devices.add.DeviceTemplateChooser; import com.aelitis.azureus.ui.swt.devices.add.ManufacturerChooser; import com.aelitis.azureus.ui.swt.devices.add.DeviceTemplateChooser.DeviceTemplateClosedListener; import com.aelitis.azureus.ui.swt.devices.add.ManufacturerChooser.ClosedListener; import com.aelitis.azureus.ui.swt.toolbar.ToolBarEnabler; import com.aelitis.azureus.ui.swt.toolbar.ToolBarEnablerSelectedContent; import com.aelitis.azureus.ui.swt.views.skin.SkinView; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager; import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager.SkinViewManagerListener; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarListener; public class DeviceManagerUI { // Not supported for Unix and OSX PPC public static boolean DISABLED; private static final int MIN_FILE_SIZE_FOR_XCODE = 128*1024; private static final int MAX_FILES_FOR_MULTI_XCODE = 64; private static final Object DEVICE_IVIEW_KEY = new Object(); private static final String CONFIG_VIEW_TYPE = "device.sidebar.ui.viewtype"; static final String CONFIG_VIEW_HIDE_REND_GENERIC = "device.sidebar.ui.rend.hidegeneric"; private static final String SPINNER_IMAGE_ID = "image.sidebar.vitality.dl"; private static final String INFO_IMAGE_ID = "image.sidebar.vitality.info"; private static final String ALERT_IMAGE_ID = "image.sidebar.vitality.alert"; private static final boolean SHOW_RENDERER_VITALITY = false; private static final boolean SHOW_OD_VITALITY = true; private static final String[] to_copy_indicator_colors = { "#000000", "#000000", "#168866", "#1c5620" }; private DeviceManager device_manager; private DeviceManagerListener device_manager_listener; private final PluginInterface plugin_interface; private final UIManager ui_manager; private UISWTInstance swt_ui; private boolean ui_setup; private SideBar side_bar; private boolean sidebar_built; private static final int SBV_SIMPLE = 0; private static final int SBV_FULL = 0x7FFFFFFF; private int side_bar_view_type = COConfigurationManager.getIntParameter( CONFIG_VIEW_TYPE, SBV_SIMPLE ); private boolean side_bar_hide_rend_gen = COConfigurationManager.getBooleanParameter( CONFIG_VIEW_HIDE_REND_GENERIC, true ); private int next_sidebar_id; private List categories = new ArrayList(); private MenuItemListener properties_listener; private MenuItemListener hide_listener; private MenuItemListener rename_listener; private MenuItemFillListener will_remove_listener; private MenuItemListener remove_listener; private MenuItemFillListener show_fill_listener; private MenuItemListener show_listener; private MenuItemFillListener will_browse_listener; private boolean offline_menus_setup; static { try { if (Constants.isOSX) { String arch = System.getProperty("os.arch", ""); DISABLED = arch.equalsIgnoreCase("powerpc") || arch.equalsIgnoreCase("ppc"); } else { DISABLED = Constants.isUnix; } } catch (Throwable t) { // Benefit of the doubt? DISABLED = false; } } public DeviceManagerUI( AzureusCore core ) { plugin_interface = PluginInitializer.getDefaultInterface(); ui_manager = plugin_interface.getUIManager(); if (DISABLED) { return; } ui_manager.addUIListener( new UIManagerListener() { public void UIAttached( UIInstance instance ) { if ( instance instanceof UISWTInstance ){ swt_ui = (UISWTInstance)instance; AzureusCoreFactory.addCoreRunningListener( new AzureusCoreRunningListener() { public void azureusCoreRunning( AzureusCore core ) { uiAttachedAndCoreRunning(core); } }); } } public void UIDetached( UIInstance instance ) { } }); } private void uiAttachedAndCoreRunning(AzureusCore core) { Utils.execSWTThread(new AERunnable() { public void runSupport() { SideBar sideBar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sideBar != null) { setupUI(sideBar); } else { SkinViewManager.addListener(new SkinViewManagerListener() { public void skinViewAdded(SkinView skinview) { if (skinview instanceof SideBar) { setupUI((SideBar) skinview); SkinViewManager.RemoveListener(this); } } }); } } }); UIExitUtilsSWT.addListener( new UIExitUtilsSWT.canCloseListener() { public boolean canClose() { try { final TranscodeJob job = device_manager.getTranscodeManager().getQueue().getCurrentJob(); if ( job == null || job.getState() != TranscodeJob.ST_RUNNING ){ return( true ); } String title = MessageText.getString("device.quit.transcoding.title"); String text = MessageText.getString( "device.quit.transcoding.text", new String[] { job.getName(), job.getTarget().getDevice().getName(), String.valueOf( job.getPercentComplete()) }); MessageBoxShell mb = new MessageBoxShell( title, text, new String[] { MessageText.getString("UpdateWindow.quit"), MessageText.getString("Content.alert.notuploaded.button.abort") }, 1); mb.open(null); mb.waitUntilClosed(); return mb.getResult() == 0; } catch (Exception e) { Debug.out(e); return true; } } }); } protected DeviceManager getDeviceManager() { return( device_manager ); } protected PluginInterface getPluginInterface() { return( plugin_interface ); } protected void setupUI( SideBar _side_bar ) { synchronized( this ){ if ( ui_setup ){ return; } ui_setup = true; } side_bar = _side_bar; device_manager = DeviceManagerFactory.getSingleton(); device_manager.addListener(new DeviceManagerListener() { public void deviceRemoved(Device device) { } public void deviceManagerLoaded() { device_manager.removeListener(this); Utils.execSWTThread(new AERunnable() { public void runSupport() { setupUIwithDeviceManager(); } }); } public void deviceChanged(Device device) { } public void deviceAttentionRequest(Device device) { } public void deviceAdded(Device device) { } }); } private void setupUIwithDeviceManager() { device_manager_listener = new DeviceManagerListener() { public void deviceAdded( Device device ) { addOrChangeDevice( device ); } public void deviceChanged( Device device ) { addOrChangeDevice( device ); } public void deviceAttentionRequest( Device device ) { showDevice( device ); } public void deviceRemoved( Device device ) { removeDevice( device ); } public void deviceManagerLoaded() { } }; TranscodeManager transMan = device_manager.getTranscodeManager(); TranscodeQueue transQ = transMan.getQueue(); transQ.addListener( new TranscodeQueueListener() { int last_job_count = 0; public void jobAdded( TranscodeJob job ) { check(); } public void jobChanged( TranscodeJob job ) { check(); } public void jobRemoved( TranscodeJob job ) { check(); } protected void check() { int job_count = device_manager.getTranscodeManager().getQueue().getJobCount(); if ( job_count != last_job_count ){ if ( job_count == 0 || last_job_count == 0 ){ SideBarEntrySWT main_sb_entry = SideBar.getEntry( SideBar.SIDEBAR_SECTION_DEVICES ); if ( main_sb_entry != null ){ ViewTitleInfoManager.refreshTitleInfo( main_sb_entry.getTitleInfo()); } } last_job_count = job_count; } } }); setupListeners(); buildSideBar( false ); BasicPluginConfigModel configModel = ui_manager.createBasicPluginConfigModel( ConfigSection.SECTION_ROOT, "Devices"); // auto search final BooleanParameter as = configModel.addBooleanParameter2( "device.search.auto", "device.search.auto", device_manager.getAutoSearch()); as.addListener( new ParameterListener() { public void parameterChanged( Parameter param) { device_manager.setAutoSearch( as.getValue()); if ( device_manager.getAutoSearch()){ search(); } } }); final BooleanParameter qosParam = configModel.addBooleanParameter2( PlatformDevicesMessenger.CFG_SEND_QOS, "devices.turnon.qos", false); // send qos qosParam.setValue(COConfigurationManager.getBooleanParameter( PlatformDevicesMessenger.CFG_SEND_QOS, false)); qosParam.addListener( new ParameterListener() { public void parameterChanged(Parameter param) { COConfigurationManager.setParameter( PlatformDevicesMessenger.CFG_SEND_QOS, qosParam.getValue()); } }); // config - simple view final BooleanParameter config_simple_view = configModel.addBooleanParameter2( CONFIG_VIEW_TYPE, "devices.sidebar.simple", side_bar_view_type == SBV_SIMPLE ); config_simple_view.addListener( new ParameterListener() { public void parameterChanged( Parameter param) { COConfigurationManager.setParameter( CONFIG_VIEW_TYPE, config_simple_view.getValue()?SBV_SIMPLE:SBV_FULL ); } }); COConfigurationManager.addParameterListener( CONFIG_VIEW_TYPE, new org.gudy.azureus2.core3.config.ParameterListener() { public void parameterChanged(String parameterName ) { config_simple_view.setValue( COConfigurationManager.getIntParameter( CONFIG_VIEW_TYPE, SBV_SIMPLE ) == SBV_SIMPLE ); } }); // generic devices configModel.addBooleanParameter2( "!" + CONFIG_VIEW_HIDE_REND_GENERIC + "!", "devices.sidebar.hide.rend.generic", side_bar_hide_rend_gen ); // transcoding // default dir String def = device_manager.getDefaultWorkingDirectory().getAbsolutePath(); final DirectoryParameter def_work_dir = configModel.addDirectoryParameter2( "device.config.xcode.workdir", "device.config.xcode.workdir", def ); def_work_dir.setValue( def ); def_work_dir.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { device_manager.setDefaultWorkingDirectory(new File( def_work_dir.getValue())); } }); // max xcode final IntParameter max_xcode = configModel.addIntParameter2( "device.config.xcode.maxbps", "device.config.xcode.maxbps", (int)(device_manager.getTranscodeManager().getQueue().getMaxBytesPerSecond()/1024), 0, Integer.MAX_VALUE ); max_xcode.addListener( new ParameterListener() { public void parameterChanged( Parameter param) { device_manager.getTranscodeManager().getQueue().setMaxBytesPerSecond( max_xcode.getValue()*1024 ); } }); // itunes final ActionParameter btnITunes = configModel.addActionParameter2("devices.button.installitunes", "UpdateWindow.columns.install"); btnITunes.setEnabled(false); AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { boolean hasItunes = core.getPluginManager().getPluginInterfaceByID( "azitunes") != null; btnITunes.setEnabled(!hasItunes); } }); btnITunes.addListener(new ParameterListener() { public void parameterChanged(Parameter param) { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { try { PluginInstaller installer = core.getPluginManager().getPluginInstaller(); StandardPlugin itunes_plugin = installer.getStandardPlugin("azitunes"); itunes_plugin.install(false); } catch (Throwable e) { Debug.printStackTrace(e); } } }); } }); configModel.createGroup( "device.xcode.group", new Parameter[] { def_work_dir, max_xcode, btnITunes }); // rss final BooleanParameter rss_enable = configModel.addBooleanParameter2( "device.rss.enable", "device.rss.enable", device_manager.isRSSPublishEnabled()); rss_enable.addListener( new ParameterListener() { public void parameterChanged( Parameter param) { device_manager.setRSSPublishEnabled( rss_enable.getValue()); } }); HyperlinkParameter rss_view = configModel.addHyperlinkParameter2( "device.rss.view", device_manager.getRSSLink()); rss_enable.addEnabledOnSelection( rss_view ); configModel.createGroup( "device.rss.group", new Parameter[] { rss_enable, rss_view, }); // offline downloaders // enable final DeviceOfflineDownloaderManager dodm = device_manager.getOfflineDownlaoderManager(); final BooleanParameter od_enable = configModel.addBooleanParameter2( "device.od.enable", "device.od.enable", dodm.isOfflineDownloadingEnabled()); od_enable.addListener( new ParameterListener() { public void parameterChanged( Parameter param) { dodm.setOfflineDownloadingEnabled( od_enable.getValue()); rebuildSideBar(); } }); // auto manage final BooleanParameter od_auto_enable = configModel.addBooleanParameter2( "device.odauto.enable", "device.odauto.enable", dodm.getOfflineDownloadingIsAuto()); od_auto_enable.addListener( new ParameterListener() { public void parameterChanged( Parameter param) { dodm.setOfflineDownloadingIsAuto( od_auto_enable.getValue()); } }); // private torrents final BooleanParameter od_pt_enable = configModel.addBooleanParameter2( "device.odpt.enable", "device.odpt.enable", dodm.getOfflineDownloadingIncludePrivate()); od_pt_enable.addListener( new ParameterListener() { public void parameterChanged( Parameter param) { dodm.setOfflineDownloadingIncludePrivate( od_pt_enable.getValue()); } }); od_auto_enable.addEnabledOnSelection( od_pt_enable ); configModel.createGroup( "device.od.group", new Parameter[] { od_enable, od_auto_enable, od_pt_enable, }); final BooleanParameter tivo_enable = configModel.addBooleanParameter2( "device.tivo.enable", "device.tivo.enable", false ); tivo_enable.setValue(device_manager.isTiVoEnabled()); tivo_enable.addListener( new ParameterListener() { public void parameterChanged( Parameter param) { device_manager.setTiVoEnabled( tivo_enable.getValue()); rebuildSideBar(); } }); addAllDevices(); setupTranscodeMenus(); } protected String getRSSLink( int port ) { return( "http://127.0.0.1:" + port + "/" ); } protected void setupListeners() { properties_listener = new MenuItemListener() { public void selected( MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; Device device = (Device)info.getDatasource(); showProperties( device ); } } }; hide_listener = new MenuItemListener() { public void selected( MenuItem menu, Object target) { if (target instanceof SideBarEntry){ SideBarEntry info = (SideBarEntry) target; Device device = (Device)info.getDatasource(); device.setHidden( true ); } } }; rename_listener = new MenuItemListener() { public void selected( MenuItem menu, Object target) { if (target instanceof SideBarEntry){ SideBarEntry info = (SideBarEntry) target; final Device device = (Device)info.getDatasource(); UISWTInputReceiver entry = (UISWTInputReceiver)swt_ui.getInputReceiver(); entry.setPreenteredText(device.getName(), false ); entry.maintainWhitespace(false); entry.allowEmptyInput( false ); entry.setLocalisedTitle(MessageText.getString("label.rename", new String[] { device.getName() })); entry.prompt(new UIInputReceiverListener() { public void UIInputReceiverClosed(UIInputReceiver entry) { if (!entry.hasSubmittedInput()) { return; } String input = entry.getSubmittedInput().trim(); if ( input.length() > 0 ){ device.setName( input ); } } }); } } }; will_remove_listener = new MenuItemFillListener() { public void menuWillBeShown( MenuItem menu, Object targets) { Object[] rows; if ( targets instanceof Object[] ){ rows = (Object[])targets; }else{ rows = new Object[]{ targets }; } if ( rows.length > 0 && rows[0] instanceof SideBarEntry ){ SideBarEntry info = (SideBarEntry)rows[0]; Device device = (Device)info.getDatasource(); menu.setEnabled( device.canRemove()); }else{ menu.setEnabled( false ); } } }; remove_listener = new MenuItemListener() { public void selected( MenuItem menu, Object target) { if (target instanceof SideBarEntry){ SideBarEntry info = (SideBarEntry) target; Device device = (Device)info.getDatasource(); device.remove(); } } }; will_browse_listener = new MenuItemFillListener() { public void menuWillBeShown( MenuItem menu, Object targets) { menu.removeAllChildItems(); boolean enabled = false; Object[] rows; if ( targets instanceof Object[] ){ rows = (Object[])targets; }else{ rows = new Object[]{ targets }; } if ( rows.length > 0 && rows[0] instanceof SideBarEntry ){ SideBarEntry info = (SideBarEntry)rows[0]; Device device = (Device)info.getDatasource(); Device.browseLocation[] locs = device.getBrowseLocations(); enabled = locs.length > 0; MenuManager menuManager = ui_manager.getMenuManager(); for ( final Device.browseLocation loc: locs ){ MenuItem loc_menu = menuManager.addMenuItem( menu, loc.getName()); loc_menu.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { Utils.launch( loc.getURL().toExternalForm()); } }); } } menu.setEnabled( enabled ); } }; show_listener = new MenuItemListener() { public void selected( MenuItem menu, Object target) { if ( target instanceof SideBarEntry ){ SideBarEntry info = (SideBarEntry)target; Object ds = info.getDatasource(); if ( ds instanceof Device ){ // shouldn't get here really as its hidden :) Device device = (Device)ds; device.setHidden( true ); }else{ int category_type = ds==null?Device.DT_UNKNOWN:(Integer)ds; Device[] devices = device_manager.getDevices(); for ( Device device: devices ){ if ( category_type == Device.DT_UNKNOWN || device.getType() == category_type && device.isHidden()){ device.setHidden( false ); } } } } } }; show_fill_listener = new MenuItemFillListener() { public void menuWillBeShown( MenuItem menu, Object targets) { boolean enabled = false; Object[] rows; if ( targets instanceof Object[] ){ rows = (Object[])targets; }else{ rows = new Object[]{ targets }; } for ( Object row: rows ){ if ( row instanceof SideBarEntry ){ SideBarEntry info = (SideBarEntry)row; Object ds = info.getDatasource(); if ( ds instanceof Device ){ }else{ int category_type = ds==null?Device.DT_UNKNOWN:(Integer)ds; Device[] devices = device_manager.getDevices(); for ( Device device: devices ){ if ( category_type == Device.DT_UNKNOWN || device.getType() == category_type && device.isHidden()){ if ( device.isHidden()){ enabled = true; } } } } } } menu.setEnabled( enabled ); } }; side_bar.addListener( new SideBarListener() { public void sidebarItemSelected( SideBarEntrySWT new_entry, SideBarEntrySWT old_entry ) { Object data_source = new_entry.getDatasource(); if ( data_source instanceof Device ){ final Device device = (Device)data_source; ISelectedContent[] sels = { new ToolBarEnablerSelectedContent( new ToolBarEnabler() { public boolean isEnabled( String itemKey ) { return( "remove".equals(itemKey)); } public boolean isSelected( String itemKey ) { return( false ); } public void itemActivated( String itemKey ) { MessageBoxShell mb = new MessageBoxShell( MessageText.getString("message.confirm.delete.title"), MessageText.getString("message.confirm.delete.text", new String[] { device.getName() }), new String[] { MessageText.getString("Button.yes"), MessageText.getString("Button.no") }, 1 ); mb.open(new UserPrompterResultListener() { public void prompterClosed(int result) { if (result == 0) { device.remove(); } } }); } })}; SelectedContentManager.changeCurrentlySelectedContent("IconBarEnabler", sels ); } } }); COConfigurationManager.addAndFireParameterListeners( new String[]{ CONFIG_VIEW_TYPE, CONFIG_VIEW_HIDE_REND_GENERIC, }, new org.gudy.azureus2.core3.config.ParameterListener() { public void parameterChanged( String parameterName ) { side_bar_view_type = COConfigurationManager.getIntParameter( CONFIG_VIEW_TYPE, SBV_SIMPLE ); side_bar_hide_rend_gen = COConfigurationManager.getBooleanParameter( CONFIG_VIEW_HIDE_REND_GENERIC, true ); rebuildSideBar(); } }); } protected static void hideIcon( SideBarVitalityImage x ) { if ( x == null ){ return; } x.setVisible( false ); x.setToolTip( "" ); } protected static void showIcon( SideBarVitalityImage x , String t ) { if ( x == null ){ return; } x.setToolTip( t ); x.setVisible( true ); } protected void rebuildSideBar() { if ( sidebar_built ){ Utils.execSWTThread( new Runnable() { public void run() { removeAllDevices(); buildSideBar( true ); addAllDevices(); } }); } } protected void buildSideBar( boolean rebuild ) { final SideBarEntrySWT main_sb_entry = SideBar.getEntry( SideBar.SIDEBAR_SECTION_DEVICES ); if ( main_sb_entry != null ){ MenuManager menu_manager = ui_manager.getMenuManager(); if ( !rebuild ){ addDefaultDropListener( main_sb_entry ); side_bar.createEntryFromSkinRef(null, SideBar.SIDEBAR_SECTION_DEVICES, "devicesview", MessageText.getString("devices.view.title"), null, null, false, -1); /* and away you go! SideBarVitalityImage addDevice = main_sb_entry.addVitalityImage("image.sidebar.subs.add"); addDevice.setToolTip("Add Device"); addDevice.addListener( new SideBarVitalityImageListener() { public void sbVitalityImage_clicked( int x, int y) { addNewDevice(); //new DevicesWizard( DeviceManagerUI.this ); } }); */ if (device_manager.getTranscodeManager().getProviders().length == 0) { SideBarVitalityImage turnon = main_sb_entry.addVitalityImage("image.sidebar.turnon"); turnon.addListener(new SideBarVitalityImageListener() { public void sbVitalityImage_clicked(int x, int y) { DevicesFTUX.ensureInstalled(); } }); } SideBarVitalityImage beta = main_sb_entry.addVitalityImage("image.sidebar.beta"); beta.setAlignment(SWT.LEFT); main_sb_entry.setImageLeftID( "image.sidebar.devices" ); main_sb_entry.setTitleInfo( new ViewTitleInfo() { private int last_indicator = 0; SideBarVitalityImage spinner = main_sb_entry.addVitalityImage( SPINNER_IMAGE_ID ); SideBarVitalityImage warning = main_sb_entry.addVitalityImage( ALERT_IMAGE_ID ); SideBarVitalityImage info = main_sb_entry.addVitalityImage( INFO_IMAGE_ID ); { hideIcon( spinner ); hideIcon( warning ); hideIcon( info ); } public Object getTitleInfoProperty( int propertyID ) { boolean expanded = main_sb_entry.getTreeItem().getExpanded(); if ( propertyID == TITLE_TEXT ){ return MessageText.getString( "devices.view.title" ); }else if ( propertyID == TITLE_INDICATOR_TEXT ){ spinner.setVisible( !expanded && device_manager.isBusy()); if ( !expanded ){ Device[] devices = device_manager.getDevices(); last_indicator = 0; String all_errors = ""; String all_infos = ""; for ( Device device: devices ){ String error = device.getError(); if ( error != null ){ all_errors += (all_errors.length()==0?"":"; ") + error; } String info = device.getInfo(); if ( info != null ){ all_infos += (all_infos.length()==0?"":"; ") + info; } if ( device instanceof DeviceMediaRenderer ){ if ( SHOW_RENDERER_VITALITY ){ DeviceMediaRenderer renderer = (DeviceMediaRenderer)device; last_indicator += renderer.getCopyToDevicePending() + renderer.getCopyToFolderPending(); } }else if ( device instanceof DeviceOfflineDownloader ){ if ( SHOW_OD_VITALITY ){ DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device; last_indicator += dod.getTransferingCount(); } } } if ( all_errors.length() > 0 ){ hideIcon( info ); showIcon( warning, all_errors ); }else{ hideIcon( warning ); if ( all_infos.length() > 0 ){ showIcon( info, all_infos ); }else{ hideIcon( info ); } } if ( last_indicator > 0 ){ return( String.valueOf( last_indicator )); } }else{ hideIcon( warning ); hideIcon( info ); } }else if ( propertyID == TITLE_INDICATOR_COLOR ){ /* if ( last_indicator > 0 ){ if ( SHOW_VITALITY ){ return( to_copy_indicator_colors ); } } */ } return null; } }); // devices String parentID = "sidebar." + SideBar.SIDEBAR_SECTION_DEVICES; MenuItem de_menu_item = menu_manager.addMenuItem( parentID, "device.search" ); de_menu_item.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { search(); } }); // show hidden de_menu_item = menu_manager.addMenuItem( parentID, "device.show" ); de_menu_item.addListener( show_listener ); de_menu_item.addFillListener( show_fill_listener ); // simple de_menu_item = menu_manager.addMenuItem( parentID, "devices.sidebar.simple" ); de_menu_item.setStyle( MenuItem.STYLE_CHECK ); de_menu_item.addFillListener( new MenuItemFillListener() { public void menuWillBeShown( MenuItem menu, Object data) { menu.setData( COConfigurationManager.getIntParameter( CONFIG_VIEW_TYPE, SBV_SIMPLE ) == SBV_SIMPLE ); } }); de_menu_item.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { COConfigurationManager.setParameter( CONFIG_VIEW_TYPE, ((Boolean)menu.getData())?SBV_SIMPLE:SBV_FULL ); } }); de_menu_item = menu_manager.addMenuItem( parentID, "sep" ); de_menu_item.setStyle( MenuItem.STYLE_SEPARATOR ); // options de_menu_item = menu_manager.addMenuItem( parentID, "ConfigView.title.short" ); de_menu_item.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { UIFunctions uif = UIFunctionsManager.getUIFunctions(); if ( uif != null ){ uif.openView( UIFunctions.VIEW_CONFIG, "Devices" ); } } }); if (Constants.isCVSVersion()) { de_menu_item = menu_manager.addMenuItem(parentID, "!(CVS Only)Show FTUX!"); de_menu_item.addListener(new MenuItemListener(){ public void selected(MenuItem menu, Object target) { DevicesFTUX.showForDebug(); } }); } } if ( rebuild ){ for ( categoryView category: categories ){ category.destroy(); } } categories.clear(); if ( side_bar_view_type == SBV_FULL ){ // renderers categoryView renderers_category = addDeviceCategory( Device.DT_MEDIA_RENDERER, "device.renderer.view.title", "image.sidebar.device.renderer" ); categories.add( renderers_category ); MenuItem re_menu_item = menu_manager.addMenuItem( "sidebar." + renderers_category.getKey(), "device.show" ); re_menu_item.addListener( show_listener ); re_menu_item.addFillListener( show_fill_listener ); // media servers categoryView media_servers_category = addDeviceCategory( Device.DT_CONTENT_DIRECTORY, "device.mediaserver.view.title", "image.sidebar.device.mediaserver" ); categories.add( media_servers_category ); MenuItem ms_menu_item = menu_manager.addMenuItem( "sidebar." + media_servers_category.getKey(), "device.show" ); ms_menu_item.addListener( show_listener ); ms_menu_item.addFillListener( show_fill_listener ); ms_menu_item = menu_manager.addMenuItem( "sidebar." + media_servers_category.getKey(), "device.mediaserver.configure"); ms_menu_item.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { UIFunctions uif = UIFunctionsManager.getUIFunctions(); if ( uif != null ){ uif.openView( UIFunctions.VIEW_CONFIG, "upnpmediaserver.name" ); } } }); // routers categoryView routers_category = addDeviceCategory( Device.DT_INTERNET_GATEWAY, "device.router.view.title", "image.sidebar.device.router" ); categories.add( routers_category ); MenuItem rt_menu_item = menu_manager.addMenuItem( "sidebar." + routers_category.getKey(), "device.show" ); rt_menu_item.addListener( show_listener ); rt_menu_item.addFillListener( show_fill_listener ); rt_menu_item = menu_manager.addMenuItem( "sidebar." + routers_category.getKey(), "device.router.configure" ); rt_menu_item.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { UIFunctions uif = UIFunctionsManager.getUIFunctions(); if ( uif != null ){ uif.openView( UIFunctions.VIEW_CONFIG, "UPnP" ); } } }); // offline downloaders if ( device_manager.getOfflineDownlaoderManager().isOfflineDownloadingEnabled()){ categoryView od_category = addDeviceCategory( Device.DT_OFFLINE_DOWNLOADER, "device.offlinedownloader.view.title", "image.sidebar.device.offlinedownloader" ); categories.add( od_category ); } // internet categoryView internet_category = addDeviceCategory( Device.DT_INTERNET, "MainWindow.about.section.internet", "image.sidebar.device.internet" ); categories.add( internet_category ); } } sidebar_built = true; } /** * * * @since 4.1.0.5 */ protected void addNewDevice() { ManufacturerChooser mfChooser = new ManufacturerChooser(); mfChooser.open(new ClosedListener() { public void MfChooserClosed(DeviceManufacturer mf) { if (mf == null) { return; } DeviceTemplateChooser deviceTemplateChooser = new DeviceTemplateChooser(mf); deviceTemplateChooser.open(new DeviceTemplateClosedListener() { public void deviceTemplateChooserClosed(DeviceTemplate deviceTemplate) { if (deviceTemplate == null) { return; } Device device; try { device = deviceTemplate.createInstance(deviceTemplate.getName() + " test!" ); device.requestAttention(); } catch (DeviceManagerException e) { Debug.out(e); } /* Don't really need to choose a profile now.. TranscodeProfile[] profiles = null;// deviceTemplate.getTranscodeProfiles(); new TranscodeChooser(profiles) { public void closed() { Utils.openMessageBox(null, 0, "CHOSE", "You chose " + (selectedProfile == null ? "NULL" : selectedProfile.getName())); } }; */ } }); } }); } private void setupTranscodeMenus() { // top level menus final String[] tables = { TableManager.TABLE_MYTORRENTS_INCOMPLETE, TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG, TableManager.TABLE_MYTORRENTS_COMPLETE, TableManager.TABLE_MYTORRENTS_COMPLETE_BIG, TableManager.TABLE_TORRENT_FILES, TableManager.TABLE_MYTORRENTS_UNOPENED, TableManager.TABLE_MYTORRENTS_UNOPENED_BIG, TableManager.TABLE_MYTORRENTS_ALL_BIG, }; TableManager table_manager = plugin_interface.getUIManager().getTableManager(); MenuItemFillListener menu_fill_listener = new MenuItemFillListener() { public void menuWillBeShown( MenuItem menu, Object _target ) { final TableRow[] target; if ( _target instanceof TableRow ){ target = new TableRow[]{ (TableRow)_target }; }else{ target = (TableRow[])_target; } boolean enabled = target.length > 0; for ( TableRow row: target ){ Object obj = row.getDataSource(); if ( obj instanceof Download ){ Download download = (Download)obj; if ( download.getState() == Download.ST_ERROR ){ enabled = false; } }else{ DiskManagerFileInfo file = (DiskManagerFileInfo)obj; try{ if ( file.getDownload().getState() == Download.ST_ERROR ){ enabled = false; } }catch( Throwable e ){ enabled = false; } } } menu.setEnabled( enabled ); menu.removeAllChildItems(); if ( enabled ){ Device[] devices = device_manager.getDevices(); int devices_added = 0; for ( Device device: devices ){ if ( device instanceof TranscodeTarget ){ devices_added++; final TranscodeTarget renderer = (TranscodeTarget)device; TranscodeProfile[] profiles = renderer.getTranscodeProfiles(); TableContextMenuItem device_item = plugin_interface.getUIManager().getTableManager().addContextMenuItem( (TableContextMenuItem)menu, "!" + device.getName() + (profiles.length==0?" (No Profiles)":"") + "!"); device_item.setStyle( MenuItem.STYLE_MENU ); if ( profiles.length == 0 ){ device_item.setEnabled( false ); }else{ for ( final TranscodeProfile profile: profiles ){ TableContextMenuItem profile_item = plugin_interface.getUIManager().getTableManager().addContextMenuItem( device_item, "!" + profile.getName() + "!"); profile_item.addMultiListener( new MenuItemListener() { public void selected( MenuItem menu, Object x ) { for ( TableRow row: target ){ Object obj = row.getDataSource(); try{ if ( obj instanceof Download ){ Download download = (Download)obj; addDownload( renderer, profile, -1, download ); }else{ DiskManagerFileInfo file = (DiskManagerFileInfo)obj; addFile( renderer, profile, -1, file ); } }catch( Throwable e ){ Debug.out( e ); } } } }); } } } } if ( devices_added == 0 ){ TableContextMenuItem device_item = plugin_interface.getUIManager().getTableManager().addContextMenuItem( (TableContextMenuItem)menu, "!(No Devices)!"); device_item.setEnabled( false ); } } } }; // TUX TODO: make a table_manager.addContentMenuItem(Class forDataSourceType, String resourceKey) // instead of forcing a loop like this for( String table: tables ){ TableContextMenuItem menu = table_manager.addContextMenuItem(table, "devices.contextmenu.xcode" ); menu.setStyle(TableContextMenuItem.STYLE_MENU); menu.addFillListener( menu_fill_listener ); } } private void setupOfflineDownloadingMenus() { final String[] tables = { TableManager.TABLE_MYTORRENTS_INCOMPLETE, TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG, TableManager.TABLE_MYTORRENTS_ALL_BIG, }; TableManager table_manager = plugin_interface.getUIManager().getTableManager(); final DeviceOfflineDownloaderManager dodm = device_manager.getOfflineDownlaoderManager(); MenuItemFillListener menu_fill_listener = new MenuItemFillListener() { public void menuWillBeShown( MenuItem menu, Object _target ) { menu.removeAllChildItems(); if ( dodm.getOfflineDownloadingIsAuto()){ menu.setEnabled( true ); TableContextMenuItem auto_item = plugin_interface.getUIManager().getTableManager().addContextMenuItem( (TableContextMenuItem)menu, "devices.contextmenu.od.auto"); auto_item.setEnabled( false ); return; } final TableRow[] target; if ( _target instanceof TableRow ){ target = new TableRow[]{ (TableRow)_target }; }else{ target = (TableRow[])_target; } boolean all_non_manual = true; boolean all_manual = true; final List downloads = new ArrayList(); for ( TableRow row: target ){ Object obj = row.getDataSource(); if ( obj instanceof Download ){ Download download = (Download)obj; downloads.add( download ); if ( dodm.isManualDownload( download )){ all_non_manual = false; }else{ all_manual = false; } } } boolean enabled = downloads.size() > 0; menu.setEnabled( enabled ); if ( enabled ){ TableContextMenuItem manual_item = plugin_interface.getUIManager().getTableManager().addContextMenuItem( (TableContextMenuItem)menu, "devices.contextmenu.od.enable" + (all_manual?"d":"")); final boolean f_all_manual = all_manual; manual_item.setData( new Boolean( f_all_manual )); manual_item.setStyle( MenuItem.STYLE_CHECK ); manual_item.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { Download[] d = downloads.toArray( new Download[ downloads.size()]); if ( f_all_manual ){ dodm.removeManualDownloads( d ); }else{ dodm.addManualDownloads( d ); } } }); } } }; // TUX TODO: make a table_manager.addContentMenuItem(Class forDataSourceType, String resourceKey) // instead of forcing a loop like this for( String table: tables ){ TableContextMenuItem menu = table_manager.addContextMenuItem(table, "devices.contextmenu.od" ); menu.setStyle(TableContextMenuItem.STYLE_MENU); menu.addFillListener( menu_fill_listener ); } } protected void search() { device_manager.search( 10*1000, new DeviceSearchListener() { public void deviceFound( Device device ) { } public void complete() { } }); } protected void addOrChangeDevice( final Device device ) { int type = device.getType(); if ( !device_manager.getOfflineDownlaoderManager().isOfflineDownloadingEnabled() && type == Device.DT_OFFLINE_DOWNLOADER ){ return; } String parent_key = null; if ( side_bar_view_type == SBV_FULL ){ for ( categoryView view: categories ){ if ( view.getDeviceType() == type ){ parent_key = view.getKey(); break; } } }else{ if ( type != Device.DT_MEDIA_RENDERER && type != Device.DT_OFFLINE_DOWNLOADER ){ return; } parent_key = SideBar.SIDEBAR_SECTION_DEVICES; } if ( parent_key == null ){ Debug.out( "Unknown device type: " + device.getString()); return; } boolean hide_device = device.isHidden(); if ( type == Device.DT_MEDIA_RENDERER && side_bar_hide_rend_gen ){ DeviceMediaRenderer rend = (DeviceMediaRenderer)device; if ( rend.isGeneric()){ hide_device = true; } } if ( hide_device ){ removeDevice( device ); return; } final String parent = parent_key; synchronized( this ){ final deviceItem existing_di = (deviceItem)device.getTransientProperty( DEVICE_IVIEW_KEY ); if ( existing_di == null ){ if ( type == Device.DT_OFFLINE_DOWNLOADER ){ if ( !offline_menus_setup ){ offline_menus_setup = true; setupOfflineDownloadingMenus(); } DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device; if ( !dod.hasShownFTUX()){ try{ new DevicesODFTUX( dod ); }catch( Throwable e ){ Debug.out( "Failed to show offline downloader FTUX", e ); } } } if ( !device.isHidden()){ final deviceItem new_di = new deviceItem(); device.setTransientProperty( DEVICE_IVIEW_KEY, new_di ); Utils.execSWTThread( new Runnable() { public void run() { synchronized( DeviceManagerUI.this ){ if ( new_di.isDestroyed()){ return; } deviceView view = new deviceView( parent, device ); new_di.setView( view ); String key = parent + "/" + device.getID() + ":" + nextSidebarID(); final SideBarEntrySWT entry; int device_type = device.getType(); if ( device_type == Device.DT_MEDIA_RENDERER ){ entry = side_bar.createEntryFromSkinRef( parent, key, "devicerendererview", device.getName(), view, null, false, -1); String id = null; int species = ((DeviceMediaRenderer)device).getRendererSpecies(); if ( species != DeviceMediaRenderer.RS_OTHER ){ id = "image.sidebar.device." + species + ".small"; }else{ String classification = device.getClassification(); if ( classification.equals( "sony.PSP")){ id = "psp"; }else if ( classification.startsWith( "tivo.")){ id = "tivo"; }else{ id = String.valueOf( species ); } id = "image.sidebar.device." + id + ".small"; } if ( id != null ){ entry.setImageLeftID(id); } }else if ( device_type == Device.DT_OFFLINE_DOWNLOADER ){ entry = side_bar.createEntryFromSkinRef( parent, key, "devicesodview", device.getName(), view, null, false, -1); DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device; String id; String manufacturer = dod.getManufacturer(); if ( manufacturer.toLowerCase().contains( "vuze" )){ id = "vuze"; }else if ( manufacturer.toLowerCase().contains( "belkin" )){ id = "bel"; }else{ id = "other"; } entry.setImageLeftID( "image.sidebar.device.od." + id + ".small" ); }else{ side_bar.createTreeItemFromIView( parent, view, key, device, false, false, false ); entry = SideBar.getEntry( key ); } entry.setDatasource( device ); entry.setLogID(parent + "-" + device.getName()); new_di.setTreeItem( entry.getTreeItem(), entry ); setStatus( device, new_di ); if ( device instanceof TranscodeTarget ){ entry.addListener( new SideBarDropListener() { public boolean sideBarEntryDrop( SideBarEntry entry, Object payload ) { return handleDrop((TranscodeTarget)device, payload ); } }); } final MenuManager menu_manager = ui_manager.getMenuManager(); boolean need_sep = false; if ( device instanceof TranscodeTarget ){ need_sep = true; MenuItem explore_menu_item = menu_manager.addMenuItem("sidebar." + key, "v3.menu.device.exploreTranscodes"); explore_menu_item.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { ManagerUtils.open( ((TranscodeTarget) device).getWorkingDirectory()); } }); } if ( device instanceof DeviceMediaRenderer ){ need_sep = true; // filter view final DeviceMediaRenderer renderer = (DeviceMediaRenderer) device; if ( renderer.canFilterFilesView()){ MenuItem filterfiles_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.only.show"); filterfiles_menu_item.setStyle(MenuItem.STYLE_CHECK); filterfiles_menu_item.addFillListener(new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { menu.setData(new Boolean(renderer.getFilterFilesView())); } }); filterfiles_menu_item.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { renderer.setFilterFilesView( (Boolean) menu.getData()); } }); } // show cats if ( renderer.canShowCategories()){ MenuItem showcat_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.show.cat"); showcat_menu_item.setStyle(MenuItem.STYLE_CHECK); showcat_menu_item.addFillListener(new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { menu.setData(new Boolean(renderer.getShowCategories())); } }); showcat_menu_item.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { renderer.setShowCategories( (Boolean) menu.getData()); } }); } // cache files MenuItem alwayscache_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.always.cache"); alwayscache_menu_item.setStyle(MenuItem.STYLE_CHECK); alwayscache_menu_item.addFillListener(new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { menu.setData(new Boolean(renderer.getAlwaysCacheFiles())); } }); alwayscache_menu_item.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { renderer.setAlwaysCacheFiles( (Boolean) menu.getData()); } }); } if ( need_sep ){ menu_manager.addMenuItem("sidebar." + key, "1" ).setStyle( MenuItem.STYLE_SEPARATOR ); } need_sep = false; if ( device instanceof DeviceMediaRenderer ){ final DeviceMediaRenderer renderer = (DeviceMediaRenderer) device; if ( renderer.canCopyToFolder()){ need_sep = true; MenuItem autocopy_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.autoCopy"); autocopy_menu_item.setStyle(MenuItem.STYLE_CHECK); autocopy_menu_item.addFillListener(new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { menu.setData(new Boolean(renderer.getAutoCopyToFolder())); } }); autocopy_menu_item.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { renderer.setAutoCopyToFolder((Boolean) menu.getData()); } }); final MenuItem mancopy_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.mancopy"); mancopy_menu_item.setStyle(MenuItem.STYLE_PUSH); mancopy_menu_item.addListener(new MenuItemListener() { public void selected( MenuItem menu, Object target) { try{ renderer.manualCopy(); }catch( Throwable e ){ Debug.out( e ); } } }); mancopy_menu_item.addFillListener( new MenuItemFillListener() { public void menuWillBeShown( MenuItem menu, Object data ) { boolean enabled = false; if ( !renderer.getAutoCopyToFolder()){ File target = renderer.getCopyToFolder(); if ( target != null && target.exists()){ enabled = renderer.getCopyToFolderPending() > 0; } } mancopy_menu_item.setEnabled( enabled ); } }); MenuItem setcopyto_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.setcopyto"); setcopyto_menu_item.setStyle(MenuItem.STYLE_PUSH); setcopyto_menu_item.addListener(new MenuItemListener() { public void selected( MenuItem menu, Object target) { Shell shell = entry.getTreeItem().getDisplay().getActiveShell(); DirectoryDialog dd = new DirectoryDialog( shell ); File existing = renderer.getCopyToFolder(); if ( existing != null ){ dd.setFilterPath( existing.getAbsolutePath()); } dd.setText( MessageText.getString( "devices.xcode.setcopyto.title" )); String path = dd.open(); if ( path != null ){ renderer.setCopyToFolder( new File( path )); } } }); } if ( renderer.canAutoStartDevice()){ need_sep = true; MenuItem autostart_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.autoStart"); autostart_menu_item.setStyle(MenuItem.STYLE_CHECK); autostart_menu_item.addFillListener(new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { menu.setData(new Boolean(renderer.getAutoStartDevice())); } }); autostart_menu_item.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { renderer.setAutoStartDevice((Boolean) menu.getData()); } }); } if ( renderer.canAssociate()){ need_sep = true; final MenuItem menu_associate = menu_manager.addMenuItem( "sidebar." + key, "devices.associate"); menu_associate.setStyle(MenuItem.STYLE_MENU); menu_associate.addFillListener( new MenuItemFillListener() { public void menuWillBeShown( MenuItem menu, Object data ) { menu_associate.removeAllChildItems(); if ( renderer.isAlive()){ InetAddress a = renderer.getAddress(); String address = a==null?"":a.getHostAddress(); MenuItem menu_none = menu_manager.addMenuItem( menu_associate, "!" + MessageText.getString( "devices.associate.already" ) + ": " + address + "!" ); menu_none.setEnabled( false ); menu_associate.setEnabled( true ); }else{ UnassociatedDevice[] unassoc = device_manager.getUnassociatedDevices(); if ( unassoc.length == 0 ){ menu_associate.setEnabled( false ); }else{ menu_associate.setEnabled( true ); for ( final UnassociatedDevice un: unassoc ){ MenuItem menu_un = menu_manager.addMenuItem( menu_associate, "!" + un.getAddress().getHostAddress() + ": " + un.getDescription() + "!"); menu_un.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target) { renderer.associate( un ); } }); } } } } }); } TranscodeProfile[] transcodeProfiles = renderer.getTranscodeProfiles(); if (transcodeProfiles.length > 0) { need_sep = true; MenuItem menu_default_profile = menu_manager.addMenuItem( "sidebar." + key, "v3.menu.device.defaultprofile"); menu_default_profile.setStyle(MenuItem.STYLE_MENU); MenuItem menu_profile_none = menu_manager.addMenuItem( menu_default_profile, "option.askeverytime"); menu_profile_none.setStyle(MenuItem.STYLE_RADIO); menu_profile_none.setData(Boolean.FALSE); menu_profile_none.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { renderer.setDefaultTranscodeProfile(null); } }); menu_profile_none.addFillListener(new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { TranscodeProfile profile = null; try { profile = renderer.getDefaultTranscodeProfile(); } catch (TranscodeException e) { } menu.setData((profile == null) ? Boolean.TRUE : Boolean.FALSE); } }); for (final TranscodeProfile profile : transcodeProfiles) { MenuItem menuItem = menu_manager.addMenuItem( menu_default_profile, "!" + profile.getName() + "!"); menuItem.setStyle(MenuItem.STYLE_RADIO); menuItem.setData(Boolean.FALSE); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { renderer.setDefaultTranscodeProfile(profile); } }); menuItem.addFillListener(new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { TranscodeProfile dprofile = null; try { dprofile = renderer.getDefaultTranscodeProfile(); } catch (TranscodeException e) { } menu.setData((profile.equals(dprofile)) ? Boolean.TRUE : Boolean.FALSE); } }); } } // publish to RSS feed if ( true ){ need_sep = true; MenuItem rss_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.rsspub"); rss_menu_item.setStyle(MenuItem.STYLE_CHECK); rss_menu_item.addFillListener(new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { menu.setData(new Boolean(device_manager.isRSSPublishEnabled() && renderer.isRSSPublishEnabled())); } }); rss_menu_item.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { renderer.setRSSPublishEnabled((Boolean) menu.getData()); } }); rss_menu_item.setEnabled( device_manager.isRSSPublishEnabled()); } } if ( device instanceof DeviceOfflineDownloader ){ final DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device; need_sep = true; MenuItem configure_menu_item = menu_manager.addMenuItem("sidebar." + key, "device.configure"); configure_menu_item.addFillListener(new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { menu.setEnabled( dod.isAlive()); } }); configure_menu_item.addListener( new MenuItemListener() { public void selected( MenuItem menu, Object target ) { try{ new DevicesODFTUX( dod ); }catch( Throwable e ){ Debug.out( e ); } } }); MenuItem enabled_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.contextmenu.od.enable" ); enabled_menu_item.setStyle(MenuItem.STYLE_CHECK); enabled_menu_item.addFillListener(new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { menu.setData(new Boolean( dod.isEnabled())); } }); enabled_menu_item.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { dod.setEnabled((Boolean) menu.getData()); } }); } if ( device.isBrowsable()){ need_sep = true; MenuItem browse_menu_item = menu_manager.addMenuItem("sidebar." + key, "device.browse"); browse_menu_item.setStyle( MenuItem.STYLE_MENU ); browse_menu_item.addFillListener( will_browse_listener ); } if ( need_sep ){ menu_manager.addMenuItem("sidebar." + key, "s2" ).setStyle( MenuItem.STYLE_SEPARATOR ); } MenuItem rename_menu_item = menu_manager.addMenuItem("sidebar." + key, "MyTorrentsView.menu.rename" ); rename_menu_item.addListener( rename_listener ); MenuItem hide_menu_item = menu_manager.addMenuItem("sidebar." + key, "device.hide"); hide_menu_item.addListener( hide_listener ); MenuItem remove_menu_item = menu_manager.addMenuItem("sidebar." + key, "MySharesView.menu.remove"); remove_menu_item.addFillListener( will_remove_listener ); remove_menu_item.addListener( remove_listener ); // sep menu_manager.addMenuItem("sidebar." + key, "s3" ).setStyle( MenuItem.STYLE_SEPARATOR ); // props MenuItem menu_item = menu_manager.addMenuItem("sidebar." + key,"Subscription.menu.properties"); menu_item.addListener( properties_listener ); } } }); } }else{ Utils.execSWTThread( new Runnable() { public void run() { ViewTitleInfoManager.refreshTitleInfo( existing_di.getView()); setStatus( device, existing_di ); } }); } } } protected void showDevice( Device device ) { synchronized( this ){ final deviceItem existing_di = (deviceItem)device.getTransientProperty( DEVICE_IVIEW_KEY ); if ( existing_di != null ){ Utils.execSWTThread( new Runnable() { public void run() { synchronized( DeviceManagerUI.this ){ TreeItem ti = existing_di.getTreeItem(); if ( ti != null ){ TreeItem x = ti; while( x != null ){ x.setExpanded( true ); x = x.getParentItem(); } ti.getParent().setSelection( ti ); } } } }); } } } public static boolean handleDrop( TranscodeTarget target, final Object payload ) { if (!(payload instanceof String[]) && !(payload instanceof String)) { return false; } TranscodeChooser deviceChooser = new TranscodeChooser(target) { public void closed() { if ( selectedTranscodeTarget != null && selectedProfile != null ){ handleDrop( selectedTranscodeTarget, selectedProfile, payload, getTranscodeRequirement()); } } }; deviceChooser.show(); return true; } protected static void addDownload( TranscodeTarget target, TranscodeProfile profile, int transcode_requirement, byte[] hash ) { try{ addDownload( target, profile, transcode_requirement, AzureusCoreFactory.getSingleton().getPluginManager().getDefaultPluginInterface().getShortCuts().getDownload(hash)); }catch( Throwable e ){ Debug.out( e ); } } protected static void addDownload( TranscodeTarget target, TranscodeProfile profile, int transcode_requirement, Download download ) { // we could use the primary file // int index = DownloadManagerEnhancer.getSingleton().getEnhancedDownload(hash).getPrimaryFile().getIndex(); // DiskManagerFileInfo dm_file = plugin_interface.getShortCuts().getDownload(hash).getDiskManagerFileInfo()[index]; // but lets just grab all files DiskManagerFileInfo[] dm_files = download.getDiskManagerFileInfo(); int num_added = 0; for ( DiskManagerFileInfo dm_file: dm_files ){ // limit number of files we can add to avoid crazyness if ( num_added > MAX_FILES_FOR_MULTI_XCODE ){ break; } // could be smarter here and check extension or whatever if ( dm_files.length == 1 || dm_file.getLength() >= MIN_FILE_SIZE_FOR_XCODE ){ addFile( target, profile, transcode_requirement, dm_file ); num_added++; } } } protected static void addFile( TranscodeTarget target, TranscodeProfile profile, int transcode_requirement, DiskManagerFileInfo file ) { try{ DeviceManagerFactory.getSingleton().getTranscodeManager().getQueue().add( target, profile, file, transcode_requirement); }catch( Throwable e ){ Debug.out( e ); } } protected static void addDirectory( TranscodeTarget target, TranscodeProfile profile, int transcode_requirement, File file ) { if ( !file.isDirectory()){ return; } File[] files = file.listFiles(); int num_added = 0; for ( File f: files ){ if ( num_added > MAX_FILES_FOR_MULTI_XCODE ){ break; } if ( f.isDirectory()){ continue; } if ( f.length() > MIN_FILE_SIZE_FOR_XCODE ){ addFile( target, profile, transcode_requirement, f ); num_added++; } } } protected static void addFile( TranscodeTarget target, TranscodeProfile profile, int transcode_requirement, File file ) { if ( file.exists() && file.isFile()){ try{ DeviceManagerFactory.getSingleton().getTranscodeManager().getQueue().add( target, profile, new DiskManagerFileInfoFile( file ), transcode_requirement ); }catch( Throwable e ){ Debug.out( e ); } }else{ Debug.out( "Drop to " + target.getDevice().getName() + " for " + file + " failed, file doesn't exist" ); } } protected static void handleDrop( TranscodeTarget target, TranscodeProfile profile, Object payload, int transcode_requirement ) { if ( payload instanceof String[]){ String[] files = (String[])payload; for ( String file: files ){ File f = new File( file ); if ( f.isFile()){ addFile( target, profile, transcode_requirement, f ); }else{ addDirectory( target, profile, transcode_requirement, f ); } } }else if ( payload instanceof String ){ String stuff = (String)payload; if ( stuff.startsWith( "DownloadManager\n" ) ||stuff.startsWith( "DiskManagerFileInfo\n" )){ String[] bits = stuff.split( "\n" ); for (int i=1;i() { public int compare( Device o1, Device o2) { return( o1.getName().compareToIgnoreCase( o2.getName())); } }); for ( Device device: devices ){ addOrChangeDevice( device ); } } }); } protected void removeAllDevices() { device_manager.removeListener( device_manager_listener ); Utils.execSWTThread( new Runnable() { public void run() { Device[] devices = device_manager.getDevices(); for ( Device device: devices ){ removeDevice( device ); } } }); } protected void removeDevice( final Device device ) { synchronized( this ){ final deviceItem existing_di = (deviceItem)device.getTransientProperty( DEVICE_IVIEW_KEY ); if ( existing_di != null ){ device.setTransientProperty( DEVICE_IVIEW_KEY, null ); existing_di.destroy(); } } } protected categoryView addDeviceCategory( int device_type, String category_title, String category_image_id ) { String key = "Device_" + category_title + ":" + nextSidebarID(); categoryView view; if ( device_type == Device.DT_INTERNET ){ view = new DeviceInternetView( this, category_title ); }else{ view = new categoryViewGeneric( this, device_type, category_title ); } TreeItem item = side_bar.createTreeItemFromIView( SideBar.SIDEBAR_SECTION_DEVICES, view, key, new Integer( device_type ), false, false, true ); SideBarEntrySWT entry = SideBar.getEntry( key ); addDefaultDropListener( entry ); entry.setImageLeftID( category_image_id ); view.setDetails( entry, item, key ); return( view ); } protected void addDefaultDropListener( SideBarEntrySWT entry ) { entry.addListener( new SideBarDropListener() { public boolean sideBarEntryDrop( SideBarEntry entry, Object payload ) { return handleDrop(null, payload); } }); } protected void showProperties( Device device ) { String[][] props = device.getDisplayProperties(); new PropertiesWindow( device.getName(), props[0], props[1] ); } protected int nextSidebarID() { synchronized( this ){ return( next_sidebar_id++ ); } } protected abstract static class categoryView extends AbstractIView implements ViewTitleInfo { private DeviceManagerUI ui; private int device_type; private String title; private TreeItem tree_item; private String key; private SideBarVitalityImage spinner; private SideBarVitalityImage warning; private SideBarVitalityImage info; private int last_indicator; protected categoryView( DeviceManagerUI _ui, int _device_type, String _title ) { ui = _ui; device_type = _device_type; title = _title; } protected void setDetails( SideBarEntrySWT _entry, TreeItem _ti, String _key ) { tree_item = _ti; key = _key; spinner = _entry.addVitalityImage( SPINNER_IMAGE_ID ); hideIcon( spinner ); warning = _entry.addVitalityImage( ALERT_IMAGE_ID ); hideIcon( warning ); info = _entry.addVitalityImage( INFO_IMAGE_ID ); hideIcon( info ); } protected int getDeviceType() { return( device_type ); } protected String getKey() { return( key ); } protected String getTitle() { return( MessageText.getString( title )); } public Object getTitleInfoProperty( int propertyID ) { boolean expanded = tree_item != null && tree_item.getExpanded(); if ( propertyID == TITLE_TEXT ){ return( getTitle()); }else if ( propertyID == TITLE_INDICATOR_TEXT ){ if ( device_type == Device.DT_MEDIA_RENDERER || device_type == Device.DT_OFFLINE_DOWNLOADER ){ if ( spinner != null ){ spinner.setVisible( !expanded && ui.getDeviceManager().isBusy()); } if ( !expanded ){ Device[] devices = ui.getDeviceManager().getDevices(); last_indicator = 0; String all_errors = ""; String all_infos = ""; for ( Device device: devices ){ String error = device.getError(); if ( error != null ){ all_errors += (all_errors.length()==0?"":"; ") + error; } String info = device.getInfo(); if ( info != null ){ all_infos += (all_infos.length()==0?"":"; ") + info; } if ( device instanceof DeviceMediaRenderer ){ if ( SHOW_RENDERER_VITALITY ){ DeviceMediaRenderer renderer = (DeviceMediaRenderer)device; last_indicator += renderer.getCopyToDevicePending() + renderer.getCopyToFolderPending(); } }else if ( device instanceof DeviceOfflineDownloader ){ if ( SHOW_OD_VITALITY ){ DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device; last_indicator += dod.getTransferingCount(); } } } if ( all_errors.length() > 0 ){ showIcon( warning, all_errors ); }else{ hideIcon( warning ); if ( all_infos.length() > 0 ){ showIcon( info, all_infos ); }else{ hideIcon( info ); } } if ( last_indicator > 0 ){ return( String.valueOf( last_indicator )); } }else{ hideIcon( warning ); hideIcon( info ); } } }else if ( propertyID == TITLE_INDICATOR_COLOR ){ /* if ( last_indicator > 0 ){ if ( SHOW_VITALITY ){ return( to_copy_indicator_colors ); } } */ } return null; } protected void destroy() { if ( Utils.isThisThreadSWT()){ tree_item.dispose(); delete(); }else{ Utils.execSWTThread( new Runnable() { public void run() { tree_item.dispose(); delete(); } }); } } } protected static class categoryViewGeneric extends categoryView { private Composite composite; protected categoryViewGeneric( DeviceManagerUI _ui, int _device_type, String _title ) { super( _ui, _device_type, _title ); } public void initialize( Composite parent_composite ) { composite = new Composite( parent_composite, SWT.NULL ); FormLayout layout = new FormLayout(); layout.marginTop = 4; layout.marginLeft = 4; layout.marginRight = 4; layout.marginBottom = 4; composite.setLayout( layout ); FormData data = new FormData(); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); data.top = new FormAttachment(composite,0); data.bottom = new FormAttachment(100,0); Label label = new Label( composite, SWT.NULL ); label.setText( "Nothing to show for " + getTitle()); label.setLayoutData( data ); } public Composite getComposite() { return( composite ); } public void delete() { super.delete(); } } protected static class deviceView extends AbstractIView implements ViewTitleInfo, TranscodeTargetListener { private String parent_key; private Device device; private Composite parent_composite; private Composite composite; private int last_indicator; protected deviceView( String _parent_key, Device _device ) { parent_key = _parent_key; device = _device; if ( device instanceof DeviceMediaRenderer ){ DeviceMediaRenderer renderer = (DeviceMediaRenderer)device; renderer.addListener( this ); } } public void initialize( Composite _parent_composite ) { parent_composite = _parent_composite; composite = new Composite( parent_composite, SWT.NULL ); FormLayout layout = new FormLayout(); layout.marginTop = 4; layout.marginLeft = 4; layout.marginRight = 4; layout.marginBottom = 4; composite.setLayout( layout ); FormData data = new FormData(); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); data.top = new FormAttachment(composite,0); data.bottom = new FormAttachment(100,0); Label label = new Label( composite, SWT.NULL ); label.setText( "Nothing to show for " + device.getName()); label.setLayoutData( data ); } public Composite getComposite() { return( composite ); } public Object getTitleInfoProperty( int propertyID ) { if ( propertyID == TITLE_TEXT ){ return( getTitle()); }else if ( propertyID == TITLE_INDICATOR_TEXT ){ if ( device instanceof DeviceMediaRenderer ){ if ( SHOW_RENDERER_VITALITY ){ DeviceMediaRenderer renderer = (DeviceMediaRenderer)device; last_indicator = renderer.getCopyToDevicePending() + renderer.getCopyToFolderPending(); } }else if ( device instanceof DeviceOfflineDownloader ){ if ( SHOW_OD_VITALITY ){ DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device; last_indicator = dod.getTransferingCount(); } } if ( last_indicator > 0 ){ return( String.valueOf( last_indicator )); } }else if ( propertyID == TITLE_INDICATOR_COLOR ){ /* if ( last_indicator > 0 ){ if ( SHOW_VITALITY ){ return( to_copy_indicator_colors ); } } */ }else if ( propertyID == TITLE_ACTIVE_STATE ){ if ( device.isLivenessDetectable()){ return( new Long( device.isAlive()?1:2 )); } } return null; } public String getTitle() { return( device.getName()); } public void fileAdded( TranscodeFile file ) { } public void fileChanged( TranscodeFile file, int type, Object data ) { if ( type == TranscodeTargetListener.CT_PROPERTY && data == TranscodeFile.PT_COMPLETE ){ refreshTitles(); } } protected void refreshTitles() { ViewTitleInfoManager.refreshTitleInfo( this ); String key = parent_key; while( key != null ){ SideBarEntrySWT parent = SideBar.getEntry( key ); if ( parent != null ){ ViewTitleInfoManager.refreshTitleInfo(parent.getTitleInfo()); key = parent.getParentID(); } } } public void fileRemoved( TranscodeFile file ) { } public void delete() { super.delete(); if ( device instanceof DeviceMediaRenderer ){ DeviceMediaRenderer renderer = (DeviceMediaRenderer)device; renderer.removeListener( this ); } } } public class deviceItem { private deviceView view; private SideBarEntrySWT sb_entry; private TreeItem tree_item; private boolean destroyed; private SideBarVitalityImage warning; private SideBarVitalityImage spinner; private SideBarVitalityImage info; protected deviceItem() { } protected void setTreeItem( TreeItem _tree_item, SideBarEntrySWT _sb_entry ) { tree_item = _tree_item; sb_entry = _sb_entry; warning = sb_entry.addVitalityImage( ALERT_IMAGE_ID ); hideIcon( warning ); spinner = sb_entry.addVitalityImage( SPINNER_IMAGE_ID ); hideIcon( spinner ); info = sb_entry.addVitalityImage( INFO_IMAGE_ID ); hideIcon( info ); } protected TreeItem getTreeItem() { return( tree_item ); } protected SideBarEntrySWT getSideBarEntry() { return( sb_entry ); } protected void setView( deviceView _view ) { view = _view; } protected deviceView getView() { return( view ); } protected void setStatus( Device device ) { // possible during initialisation, status will be shown again on complete if ( warning != null && info != null ){ String error = device.getError(); if ( error != null ){ hideIcon( info ); warning.setToolTip( error ); warning.setImageID( ALERT_IMAGE_ID ); warning.setVisible( true ); }else{ hideIcon( warning ); String info_str = device.getInfo(); if ( info_str != null ){ showIcon( info, info_str ); }else{ hideIcon( info ); } } } if ( spinner != null ){ spinner.setVisible( device.isBusy()); } if ( view != null ){ view.refreshTitles(); } } protected boolean isDestroyed() { return( destroyed ); } protected void destroy() { destroyed = true; Utils.execSWTThread( new Runnable() { public void run() { synchronized( DeviceManagerUI.this ){ if ( tree_item != null && !tree_item.isDisposed()){ tree_item.dispose(); } } view.delete(); } }); } public void activate() { SideBar sideBar = (SideBar)SkinViewManager.getByClass(SideBar.class); if ( sideBar != null && sb_entry != null ){ sideBar.showEntryByID(sb_entry.getId()); } } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/devices/DevicesWizard.java0000644000175000017500000001466111275141740025040 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.devices; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import com.aelitis.azureus.core.devices.Device; import com.aelitis.azureus.core.devices.DeviceTemplate; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; public class DevicesWizard { private DeviceManagerUI device_manager_ui; private Display display; private Shell shell; private Label title; private Font boldFont; private Font titleFont; private Font subTitleFont; private Font textInputFont; private Composite main; private ImageLoader imageLoader; public DevicesWizard( DeviceManagerUI dm_ui ) { device_manager_ui = dm_ui; imageLoader = ImageLoader.getInstance(); shell = ShellFactory.createMainShell(SWT.TITLE | SWT.CLOSE | SWT.ICON | SWT.RESIZE); shell.setSize(650,400); Utils.centreWindow(shell); shell.setMinimumSize(550,400); display = shell.getDisplay(); Utils.setShellIcon(shell); createFonts(); shell.setText(MessageText.getString("wizard.device.title")); shell.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event event) { imageLoader.releaseImage("wizard_header_bg"); if(titleFont != null && !titleFont.isDisposed()) { titleFont.dispose(); } if(textInputFont != null && !textInputFont.isDisposed()) { textInputFont.dispose(); } if(boldFont != null && !boldFont.isDisposed()) { boldFont.dispose(); } if(subTitleFont != null && !subTitleFont.isDisposed()) { subTitleFont.dispose(); } } }); Composite header = new Composite(shell, SWT.NONE); header.setBackgroundMode(SWT.INHERIT_DEFAULT); header.setBackgroundImage(imageLoader.getImage("wizard_header_bg")); Label topSeparator = new Label(shell,SWT.SEPARATOR |SWT.HORIZONTAL); main = new Composite(shell, SWT.NONE); Label bottomSeparator = new Label(shell,SWT.SEPARATOR |SWT.HORIZONTAL); Composite footer = new Composite(shell, SWT.NONE); FormLayout layout = new FormLayout(); shell.setLayout(layout); FormData data; data = new FormData(); data.top = new FormAttachment(0,0); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); //data.height = 50; header.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(header,0); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); topSeparator.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(topSeparator,0); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); data.bottom = new FormAttachment(bottomSeparator,0); main.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); data.bottom = new FormAttachment(footer,0); bottomSeparator.setLayoutData(data); data = new FormData(); data.bottom = new FormAttachment(100,0); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); footer.setLayoutData(data); populateHeader(header); populateFooter(footer); shell.layout(); shell.open(); } private void populateHeader( Composite header) { header.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); title = new Label(header, SWT.WRAP); title.setFont(titleFont); title.setText( MessageText.getString("device.wizard.header") ); FillLayout layout = new FillLayout(); layout.marginHeight = 10; layout.marginWidth = 10; header.setLayout(layout); } private void createFonts() { FontData[] fDatas = shell.getFont().getFontData(); for(int i = 0 ; i < fDatas.length ; i++) { fDatas[i].setStyle(SWT.BOLD); } boldFont = new Font(display,fDatas); for(int i = 0 ; i < fDatas.length ; i++) { if(org.gudy.azureus2.core3.util.Constants.isOSX) { fDatas[i].setHeight(12); } else { fDatas[i].setHeight(10); } } subTitleFont = new Font(display,fDatas); for(int i = 0 ; i < fDatas.length ; i++) { if(org.gudy.azureus2.core3.util.Constants.isOSX) { fDatas[i].setHeight(17); } else { fDatas[i].setHeight(14); } } titleFont = new Font(display,fDatas); for(int i = 0 ; i < fDatas.length ; i++) { if(org.gudy.azureus2.core3.util.Constants.isOSX) { fDatas[i].setHeight(14); } else { fDatas[i].setHeight(12); } fDatas[i].setStyle(SWT.NONE); } textInputFont = new Font(display,fDatas); } private void populateFooter( Composite footer) { Button cancelButton; Button createButton; cancelButton = new Button(footer,SWT.PUSH); cancelButton.setText(MessageText.getString("Button.cancel")); createButton = new Button(footer,SWT.PUSH); createButton.setText(MessageText.getString("device.wizard.create")); FormLayout layout = new FormLayout(); layout.marginHeight = 5; layout.marginWidth = 5; layout.spacing = 5; footer.setLayout(layout); FormData data; data = new FormData(); data.right = new FormAttachment(100); data.width = 100; cancelButton.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0); data.width = 175; createButton.setLayoutData(data); createButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { try{ DeviceTemplate[] templates = device_manager_ui.getDeviceManager().getDeviceTemplates( Device.DT_MEDIA_RENDERER ); for ( DeviceTemplate template: templates ){ if ( !template.isAuto()){ Device device = template.createInstance( template.getName() + " test!" ); device.requestAttention(); break; } } }catch( Throwable e ){ Debug.printStackTrace(e); } } }); cancelButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { shell.close(); } }); } public static void main( String args[]) { final DevicesWizard sw = new DevicesWizard( null ); while( ! sw.shell.isDisposed()) { if(! sw.display.readAndDispatch()) { sw.display.sleep(); } } sw.display.dispose(); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/utils/0000755000175000017500000000000011310377632021141 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/utils/ContentNetworkUI.java0000644000175000017500000001066711145221762025236 0ustar adrianadrian/** * Created on Dec 2, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.utils; import java.io.*; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.utils.ImageBytesDownloader; import com.aelitis.azureus.ui.utils.ImageBytesDownloader.ImageDownloaderListener; import com.aelitis.azureus.util.ContentNetworkUtils; /** * @author TuxPaper * @created Dec 2, 2008 * */ public class ContentNetworkUI { // If we ever clear mapImages, don't forget to ImageLoderFactory.releaseImage if needed public static Map mapImages = new HashMap(); /** * @param cn * @param cnImageLoadedListener * * @since 4.0.0.5 */ public static Image loadImage(final long contentNetworkID, final ContentNetworkImageLoadedListener cnImageLoadedListener) { Image image = mapImages.get(new Long(contentNetworkID)); if (image != null && cnImageLoadedListener != null) { cnImageLoadedListener.contentNetworkImageLoaded(contentNetworkID, image, true); return image; } ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetwork( contentNetworkID); if (cn == null) { return image; } String imgURL = ContentNetworkUtils.getUrl(cn, ContentNetwork.SERVICE_GET_ICON); if (imgURL != null) { final File cache = new File(SystemProperties.getUserPath(), "cache" + File.separator + imgURL.hashCode() + ".ico"); boolean loadImage = true; if (cache.exists()) { try { FileInputStream fis = new FileInputStream(cache); try { byte[] imageBytes = FileUtil.readInputStreamAsByteArray(fis); InputStream is = new ByteArrayInputStream(imageBytes); image = new Image(Display.getCurrent(), is); try { is.close(); } catch (IOException e) { } mapImages.put(new Long(contentNetworkID), image); if (cnImageLoadedListener != null) { cnImageLoadedListener.contentNetworkImageLoaded(contentNetworkID, image, true); } } finally { fis.close(); } loadImage = false; } catch (Throwable e) { Debug.printStackTrace(e); } } if (loadImage) { ImageBytesDownloader.loadImage(imgURL, new ImageBytesDownloader.ImageDownloaderListener() { public void imageDownloaded(final byte[] imageBytes) { Utils.execSWTThread(new AERunnable() { public void runSupport() { FileUtil.writeBytesAsFile(cache.getAbsolutePath(), imageBytes); InputStream is = new ByteArrayInputStream(imageBytes); Image image = new Image(Display.getCurrent(), is); try { is.close(); } catch (IOException e) { } mapImages.put(new Long(contentNetworkID), image); if (cnImageLoadedListener != null) { cnImageLoadedListener.contentNetworkImageLoaded( contentNetworkID, image, false); } } }); } }); } } else if (contentNetworkID == ContentNetwork.CONTENT_NETWORK_VUZE && cnImageLoadedListener != null) { image = ImageLoader.getInstance().getImage("image.sidebar.vuze"); mapImages.put(new Long(contentNetworkID), image); cnImageLoadedListener.contentNetworkImageLoaded(contentNetworkID, image, true); } return image; } public static interface ContentNetworkImageLoadedListener { public void contentNetworkImageLoaded(Long contentNetworkID, Image image, boolean wasReturned); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/utils/UIMagnetHandler.java0000644000175000017500000001030511267524620024754 0ustar adrianadrian/** * Created on May 27, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.utils; import java.util.Map; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.UISwitcherUtil; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.core.*; import com.aelitis.azureus.plugins.magnet.MagnetPlugin; import com.aelitis.azureus.plugins.magnet.MagnetPluginListener; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.UserPrompterResultListener; import com.aelitis.net.magneturi.MagnetURIHandler; import org.gudy.azureus2.plugins.PluginInterface; /** * @author TuxPaper * @created May 27, 2008 * */ public class UIMagnetHandler { /** * @param azureus_core */ public UIMagnetHandler(AzureusCore core) { int val = Integer.parseInt(Constants.getBaseVersion().replaceAll("\\.", "")); String ui = COConfigurationManager.getStringParameter("ui"); if (!"az2".equals(ui)) { val += 10000; } MagnetURIHandler magnetURIHandler = MagnetURIHandler.getSingleton(); magnetURIHandler.addInfo("get-version-info", val); core.addLifecycleListener(new AzureusCoreLifecycleAdapter() { public void componentCreated(final AzureusCore core, AzureusCoreComponent component) { if (component instanceof PluginInterface) { PluginInterface pi = (PluginInterface) component; if (pi.getPlugin() instanceof MagnetPlugin) { MagnetPlugin magnetPlugin = (MagnetPlugin) pi.getPlugin(); magnetPlugin.addListener(new MagnetPluginListener() { public boolean set(String name, Map values) { if (name.equals("AZMSG") && values != null) { String val = (String) values.get("value"); if (val.indexOf(";switch-ui;") > 0) { if (COConfigurationManager.getStringParameter("ui", "az3").equals( "az3")) { return false; } if (!UISwitcherUtil.isAZ3Avail()) { return false; } UIFunctions uif = UIFunctionsManager.getUIFunctions(); if (uif == null) { core.addLifecycleListener(new AzureusCoreLifecycleAdapter() { public void componentCreated(AzureusCore core, AzureusCoreComponent component) { if (component instanceof UIFunctions) { uiswitch(core, (UIFunctions) component); } } }); } else { uiswitch(core, uif); } return true; } } return false; } public int get(String name, Map values) { return Integer.MIN_VALUE; } }); } } } }); } private static void uiswitch(final AzureusCore core, final UIFunctions uif) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { uif.bringToFront(); uif.promptUser(MessageText.getString("dialog.uiswitch.title"), MessageText.getString("dialog.uiswitch.text"), new String[] { MessageText.getString("dialog.uiswitch.button"), }, 0, null, null, false, 0, new UserPrompterResultListener() { public void prompterClosed(int returnVal) { if (returnVal != 0) { return; } COConfigurationManager.setParameter("ui", "az3"); COConfigurationManager.save(); core.requestRestart(); } }); } }); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/utils/ColorCache.java0000644000175000017500000001526411050147110024001 0ustar adrianadrian/* * Created on Jun 30, 2006 6:22:44 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.utils; import java.util.*; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.RGB; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.Colors; /** * @author TuxPaper * @created Jun 30, 2006 * */ public class ColorCache { private final static boolean DEBUG = Constants.isCVSVersion(); private final static Map mapColors = new HashMap(); private final static int SYSTEMCOLOR_INDEXSTART = 17; private final static String[] systemColorNames = { "COLOR_WIDGET_DARK_SHADOW", "COLOR_WIDGET_NORMAL_SHADOW", "COLOR_WIDGET_LIGHT_SHADOW", "COLOR_WIDGET_HIGHLIGHT_SHADOW", "COLOR_WIDGET_FOREGROUND", "COLOR_WIDGET_BACKGROUND", "COLOR_WIDGET_BORDER", "COLOR_LIST_FOREGROUND", "COLOR_LIST_BACKGROUND", "COLOR_LIST_SELECTION", "COLOR_LIST_SELECTION_TEXT", "COLOR_INFO_FOREGROUND", "COLOR_INFO_BACKGROUND", "COLOR_TITLE_FOREGROUND", "COLOR_TITLE_BACKGROUND", }; static { AEDiagnostics.addEvidenceGenerator(new AEDiagnosticsEvidenceGenerator() { public void generate(IndentWriter writer) { writer.println("Colors:"); writer.indent(); writer.println("# cached: " + mapColors.size()); writer.exdent(); } }); } public static Color getColor(Device device, int red, int green, int blue) { if (mapColors.size() == 0) { for (int i = 1; i <= 16; i++) { Color color = device.getSystemColor(i); Long key = new Long(((long) color.getRed() << 16) + (color.getGreen() << 8) + color.getBlue()); addColor(key, color); } if (DEBUG) { SimpleTimer.addPeriodicEvent("ColorCacheChecker", 60000, new TimerEventPerformer() { public void perform(TimerEvent event) { Utils.execSWTThread(new AERunnable() { public void runSupport() { for (Iterator iter = mapColors.keySet().iterator(); iter.hasNext();) { Long key = (Long) iter.next(); Color color = (Color) mapColors.get(key); if (color.isDisposed()) { Logger.log(new LogAlert(false, LogAlert.AT_ERROR, "Someone disposed of color " + Long.toHexString(key.longValue()) + ". Please report this on the " + "forum")); iter.remove(); } } } }); } }); } } Long key = new Long(((long) red << 16) + (green << 8) + blue); Color color = (Color) mapColors.get(key); if (color == null || color.isDisposed()) { try { if (red < 0) { red = 0; } else if (red > 255) { red = 255; } if (green < 0) { green = 0; } else if (green > 255) { green = 255; } if (blue < 0) { blue = 0; } else if (blue > 255) { blue = 255; } color = new Color(device, red, green, blue); } catch (IllegalArgumentException e) { Debug.out("One Invalid: " + red + ";" + green + ";" + blue, e); } addColor(key, color); } return color; } public static Color getColor(Device device, String value) { int[] colors = new int[3]; if (value == null || value.length() == 0) { return null; } try { if (value.charAt(0) == '#') { // hex color string long l = Long.parseLong(value.substring(1), 16); colors[0] = (int) ((l >> 16) & 255); colors[1] = (int) ((l >> 8) & 255); colors[2] = (int) (l & 255); } else if (value.indexOf(',') > 0) { StringTokenizer st = new StringTokenizer(value, ","); colors[0] = Integer.parseInt(st.nextToken()); colors[1] = Integer.parseInt(st.nextToken()); colors[2] = Integer.parseInt(st.nextToken()); } else { value = value.toUpperCase(); if (value.startsWith("COLOR_")) { for (int i = 0; i < systemColorNames.length; i++) { String name = systemColorNames[i]; if (name.equals(value)) { return device.getSystemColor(i + SYSTEMCOLOR_INDEXSTART); } } } else if (value.startsWith("BLUE.FADED.")) { int idx = Integer.parseInt(value.substring(11)); return Colors.faded[idx]; } else if (value.startsWith("BLUE.")) { int idx = Integer.parseInt(value.substring(5)); return Colors.blues[idx]; } else if (value.equals("ALTROW")) { return Colors.colorAltRow; } return null; } } catch (Exception e) { Debug.out(value, e); return null; } return getColor(device, colors[0], colors[1], colors[2]); } private static void addColor(Long key, Color color) { mapColors.put(key, color); } /** * @param device * @param color * @return * * @since 3.0.4.3 */ public static Color getColor(Device device, int[] rgb) { if (rgb == null || rgb.length < 3) { return null; } return getColor(device, rgb[0], rgb[1], rgb[2]); } public static Color getRandomColor() { if (mapColors.size() == 0) { return Colors.black; } int r = (int) (Math.random() * mapColors.size()); return (Color) mapColors.values().toArray()[r]; } /** * @param display * @param hsb * @return * * @since 3.1.1.1 */ public static Color getColor(Device device, float[] hsb) { if (hsb[0] < 0) { hsb[0] = 0; } else if (hsb[0] > 360) { hsb[0] = 360; } if (hsb[1] < 0) { hsb[1] = 0; } else if (hsb[1] > 1) { hsb[1] = 1; } if (hsb[2] < 0) { hsb[2] = 0; } else if (hsb[2] > 1) { hsb[2] = 1; } RGB rgb = new RGB(hsb[0], hsb[1], hsb[2]); return getColor(device, rgb.red, rgb.green, rgb.blue); } /** * @param device * @param rgb * @return * * @since 3.1.1.1 */ public static Color getColor(Device device, RGB rgb) { return getColor(device, rgb.red, rgb.green, rgb.blue); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/utils/ImageResizer.java0000644000175000017500000003700511275141736024403 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.utils; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; public class ImageResizer { static private final int RESIZE_STEPS = 100000; static private final int MARGIN = 20; private int minWidth, minHeight; private int displayWidth, displayHeight; private Display display; private Shell parent; private Shell shell; private Cursor cursor; private Canvas canvas; private Scale scale; private long lastUpdate = 0l; private Image original; private int originalWidth, originalHeight; private Image currentImage; private Image overlay; private Image overlayDragging; private Image overlayNotDragging; private boolean done; private Image result; private float zoomRatio; private float minZoomRatio; private float maxZoomRatio; private Point offset; private Listener moveImageListener = new Listener() { private boolean mouseDown = false; private Point pointDown; public void handleEvent(Event event) { //System.out.println(event); switch (event.type) { case SWT.MouseDown: mouseDown = true; pointDown = new Point(event.x, event.y); overlay = overlayDragging; drawCurrentImage(); break; case SWT.MouseUp: mouseDown = false; overlay = overlayNotDragging; drawCurrentImage(); break; case SWT.MouseMove: if (!mouseDown) { break; } offset.x = offset.x + event.x - pointDown.x; offset.y = offset.y + event.y - pointDown.y; insureOffsetIsCorrect(); pointDown.x = event.x; pointDown.y = event.y; drawCurrentImage(); break; case SWT.MouseEnter: break; case SWT.MouseExit: break; } } }; private ImageResizerListener imageResizerListener; public ImageResizer(Display display, int width, int height, Shell parent) { this.parent = parent; this.display = display; this.minWidth = width; this.minHeight = height; } public void resize(Image original, ImageResizerListener l) throws ImageResizeException { this.original = original; this.imageResizerListener = l; //If the image is too small, let's just not deal with it if (!checkSize(original)) { dispose(); throw new ImageResizeException(MessageText.getString( "ImageResizer.image.too.small", new String[] { minWidth + "", minHeight + "" })); } originalWidth = original.getBounds().width; originalHeight = original.getBounds().height; currentImage = new Image(display, internalResize(original, (int) (originalWidth * zoomRatio), (int) (originalHeight * zoomRatio))); offset = new Point(0, 0); if (minWidth != original.getBounds().width || minHeight != original.getBounds().height) { displayWidth = minWidth + 2 * (MARGIN + 1); displayHeight = minHeight + 2 * (MARGIN + 1); overlay = overlayNotDragging = createOverlayImage((byte) 255, 0x00FFFFFF, (byte) 255, 0x00000000); overlayDragging = createOverlayImage((byte) 80, 0x00FFFFFF, (byte) 255, 0x00FFFFFF); initUI(); done = false; } else { result = computeResultImage(); l.imageResized(result); } } private void initUI() { cursor = new Cursor(display, SWT.CURSOR_HAND); if (parent != null) { shell = ShellFactory.createShell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); } else { shell = ShellFactory.createMainShell(SWT.CLOSE | SWT.BORDER); } shell.setText("Thumbnail Assistant"); Utils.setShellIcon(shell); shell.addListener(SWT.Close, new Listener() { public void handleEvent(Event event) { event.doit = false; result = null; done = true; shell = null; dispose(); imageResizerListener.imageResized(result); } }); FormLayout layout = new FormLayout(); layout.marginBottom = 5; layout.marginTop = 5; layout.marginLeft = 5; layout.marginRight = 5; FormData data; shell.setLayout(layout); Label title = new Label(shell, SWT.WRAP); title.setText(MessageText.getString("ImageResizer.title")); data = new FormData(); data.width = displayWidth; title.setLayoutData(data); canvas = new Canvas(shell, SWT.BORDER); canvas.setCursor(cursor); data = new FormData(); data.width = displayWidth; data.height = displayHeight; data.top = new FormAttachment(title, 5); canvas.setLayoutData(data); canvas.addListener(SWT.MouseDown, moveImageListener); canvas.addListener(SWT.MouseUp, moveImageListener); canvas.addListener(SWT.MouseMove, moveImageListener); canvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent arg0) { drawCurrentImage(); } }); offset.x = (minWidth - currentImage.getBounds().width) / 2; offset.y = (minHeight - currentImage.getBounds().height) / 2; Label label = new Label(shell, SWT.WRAP); //The label text depends on the presence of the scale, //Thefore we delay the size computation as well as //Assiging any FormData (layout) to it see (1) //The Control to witch the Buttons OK and Cancel are going to be attached //Depends on the presence of the scale Control attach = label; if (minZoomRatio < 1) { scale = new Scale(shell, SWT.HORIZONTAL); data = new FormData(); data.width = displayWidth; data.top = new FormAttachment(label, 5); scale.setLayoutData(data); scale.setMaximum((int) (RESIZE_STEPS * maxZoomRatio)); scale.setMinimum((int) (RESIZE_STEPS * minZoomRatio)); scale.setIncrement((int) ((maxZoomRatio - minZoomRatio) * RESIZE_STEPS / 10)); scale.setPageIncrement((int) ((maxZoomRatio - minZoomRatio) * RESIZE_STEPS / 10)); scale.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { final long timestamp = SystemTime.getCurrentTime(); lastUpdate = timestamp; final int position = scale.getSelection(); AEThread t = new AEThread("") { public void runSupport() { try { Thread.sleep(150); } catch (Exception e) { e.printStackTrace(); } if (timestamp == lastUpdate) { if (display != null && !display.isDisposed()) { display.asyncExec(new Runnable() { public void run() { refreshCurrentImage(position); } }); } } } }; t.setDaemon(true); t.start(); } }); attach = scale; label.setText(MessageText.getString("ImageResizer.move.image.with.slider")); } else { label.setText(MessageText.getString("ImageResizer.move.image")); } // (1) Layout of the label, depending on the text in it int width = label.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; if (width > displayWidth) { width = displayWidth; } data = new FormData(); data.width = width; data.top = new FormAttachment(canvas, 5); data.left = new FormAttachment(canvas, 0, SWT.CENTER); label.setLayoutData(data); Button btnCancel = new Button(shell, SWT.PUSH); btnCancel.setText("Cancel"); data = new FormData(); data.width = 70; data.top = new FormAttachment(attach, 10); data.right = new FormAttachment(100, -10); btnCancel.setLayoutData(data); btnCancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { result = null; done = true; dispose(); imageResizerListener.imageResized(result); } }); Button btnOk = new Button(shell, SWT.PUSH); btnOk.setText("OK"); data = new FormData(); data.width = 70; data.top = new FormAttachment(attach, 10); data.right = new FormAttachment(btnCancel, -10); btnOk.setLayoutData(data); btnOk.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { result = computeResultImage(); done = true; dispose(); imageResizerListener.imageResized(result); } }); shell.setDefaultButton(btnOk); btnOk.setFocus(); shell.setSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT)); if (parent != null) { Utils.centerWindowRelativeTo(shell, parent); } shell.open(); drawCurrentImage(); } private boolean checkSize(Image image) { //If the image is smaller than the minimal size, we shouldn't accept it Rectangle size = image.getBounds(); if (size.width < minWidth || size.height < minHeight) { return false; } float minHRatio = (float) (minHeight) / size.height; float minWRatio = (float) (minWidth) / size.width; float maxHRatio = (float) (minHeight * 4) / size.height; float maxWRatio = (float) (minWidth * 4) / size.width; //We must keep the min zoom bigger than the "biggest" ratio (ie, smallest zoom out) minZoomRatio = minHRatio > minWRatio ? minHRatio : minWRatio; maxZoomRatio = maxHRatio > maxWRatio ? maxHRatio : maxWRatio; if (maxZoomRatio > 1) { maxZoomRatio = 1; } zoomRatio = minZoomRatio; return true; } private ImageData internalResize(Image image, int newWidth, int newHeight) { ImageData srcData = image.getImageData(); //int width = srcData.width,height = srcData.height; ImageData data = srcData; //int newWidth = (int)(width*zoomRatio); //int newHeight = (int)(height*zoomRatio); final ImageData copy = new ImageData(newWidth, newHeight, 24, new PaletteData(0x00FF0000, 0x0000FF00, 0x000000FF)); Image src = new Image(display, srcData); Image dst = new Image(display, copy); GC gc = new GC(dst); gc.setAdvanced(true); try { gc.setInterpolation(SWT.HIGH); } catch (Exception e) { // may not be avail } gc.drawImage(src, 0, 0, srcData.width, srcData.height, 0, 0, copy.width, copy.height); //gc.setAlpha(50); //gc.drawImage(src,2,2,srcData.width-2,srcData.height-2,0,0,copy.width,copy.height); gc.dispose(); data = dst.getImageData(); src.dispose(); dst.dispose(); return data; } private void drawCurrentImage() { GC gcCanvas = new GC(canvas); Image temp = new Image(display, displayWidth, displayHeight); GC gc = new GC(temp); gc.drawImage(currentImage, offset.x + MARGIN + 1, offset.y + MARGIN + 1); //gc.setAlpha(128); gc.drawImage(overlay, 0, 0); //gc.setTextAntialias(SWT.ON); //gc.drawText("This is a test", 15, displayHeight-15,true); gc.dispose(); gcCanvas.drawImage(temp, 0, 0); temp.dispose(); gcCanvas.dispose(); } private void insureOffsetIsCorrect() { int minX = minWidth - currentImage.getBounds().width; if (offset.x < minX) { offset.x = minX; } int minY = minHeight - currentImage.getBounds().height; if (offset.y < minY) { offset.y = minY; } if (offset.x > 0) { offset.x = 0; } if (offset.y > 0) { offset.y = 0; } } private void dispose() { if (shell != null && !shell.isDisposed()) { shell.dispose(); } if (currentImage != null && !currentImage.isDisposed()) { currentImage.dispose(); } if (overlayDragging != null && !overlayDragging.isDisposed()) { overlayDragging.dispose(); } if (overlayNotDragging != null && !overlayNotDragging.isDisposed()) { overlayNotDragging.dispose(); } if (cursor != null && !cursor.isDisposed()) { cursor.dispose(); } } private Image computeResultImage() { Image img = new Image(display, minWidth, minHeight); /*ImageData srcData = original.getImageData(); ImageData dstData = new ImageData( currentImage.getBounds().width, currentImage.getBounds().height, 32, new PaletteData(0xFF,0xFF00,0xFF0000)); Resample resample = new Resample(); resample.setFilter(Resample.FILTER_TYPE_LANCZOS3, 7.0f); resample.process(srcData, dstData); Image filtered = new Image(display,dstData); */ GC gc = new GC(img); gc.drawImage(currentImage, offset.x, offset.y); gc.dispose(); //filtered.dispose(); return img; } private Image createOverlayImage(final byte marginAlpha, final int marginColor, final byte borderAlpha, final int borderColor) { int width = displayWidth; int height = displayHeight; ImageData data = new ImageData(width, height, 32, new PaletteData( 0x000000FF, 0x0000FF00, 0x00FF0000)); byte[] transparency = new byte[width * height]; int[] pixels = new int[width * height]; byte rowAlpha[] = new byte[width]; int rowPixels[] = new int[width]; //Top //Pattern for (int i = 0; i < width; i++) { rowAlpha[i] = marginAlpha; rowPixels[i] = marginColor; } //Fill for (int i = 0; i < MARGIN; i++) { System.arraycopy(rowAlpha, 0, transparency, i * width, width); System.arraycopy(rowPixels, 0, pixels, i * width, width); } //Main area //Pattern for (int i = 0; i < MARGIN; i++) { rowAlpha[i] = marginAlpha; rowAlpha[width - i - 1] = marginAlpha; } for (int i = MARGIN; i < width - MARGIN; i++) { rowAlpha[i] = 0; } //Fill for (int i = MARGIN; i < height - MARGIN; i++) { System.arraycopy(rowAlpha, 0, transparency, i * width, width); System.arraycopy(rowPixels, 0, pixels, i * width, width); } //Bottom //Pattern for (int i = 0; i < width; i++) { rowAlpha[i] = marginAlpha; } //Fill for (int i = height - MARGIN - 1; i < height; i++) { System.arraycopy(rowAlpha, 0, transparency, i * width, width); System.arraycopy(rowPixels, 0, pixels, i * width, width); } //Let's do the border part for (int i = MARGIN; i < width - MARGIN; i++) { transparency[width * MARGIN + i] = borderAlpha; pixels[width * MARGIN + i] = borderColor; } for (int j = MARGIN; j < height - MARGIN; j++) { transparency[j * width + MARGIN] = borderAlpha; pixels[j * width + MARGIN] = borderColor; transparency[j * width + width - MARGIN - 1] = borderAlpha; pixels[j * width + width - MARGIN - 1] = borderColor; } for (int i = MARGIN; i < width - MARGIN; i++) { transparency[width * (height - MARGIN - 1) + i] = borderAlpha; pixels[width * (height - MARGIN - 1) + i] = borderColor; } data.alphaData = transparency; data.setPixels(0, 0, width * height, pixels, 0); Image overlay = new Image(display, data); return overlay; } private void refreshCurrentImage(int position) { float previousZoom = zoomRatio; zoomRatio = (float) position / RESIZE_STEPS; if (zoomRatio > 1) { zoomRatio = 1; } if (zoomRatio < minZoomRatio) { zoomRatio = minZoomRatio; } if (previousZoom != zoomRatio) { Image previous = currentImage; currentImage = new Image(display, internalResize(original, (int) (originalWidth * zoomRatio), (int) (originalHeight * zoomRatio))); //float ratio = zoomRatio / previousZoom; offset.x += (previous.getBounds().width - currentImage.getBounds().width) / 2; offset.y += (previous.getBounds().height - currentImage.getBounds().height) / 2; if (previous != null && !previous.isDisposed()) { previous.dispose(); } insureOffsetIsCorrect(); drawCurrentImage(); } } public interface ImageResizerListener { void imageResized(Image image); } public static void main(final String args[]) throws Exception { final Display display = Display.getDefault(); final Shell test = new Shell(display); ImageResizer resizer = new ImageResizer(display, 228, 128, null); String file = new FileDialog(test).open(); Image img = new Image(display, file); resizer.resize(img, new ImageResizerListener() { public void imageResized(Image thumbnail) { System.out.println(thumbnail); thumbnail.dispose(); test.dispose(); if (args.length == 0) { display.dispose(); } } }); } }azureus-4.3.0.6/com/aelitis/azureus/ui/swt/utils/ImageResizeException.java0000644000175000017500000000025110572025364026066 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.utils; public class ImageResizeException extends Exception { public ImageResizeException(String message) { super(message); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/utils/PlayNowList.java0000644000175000017500000000263610673225400024234 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.utils; import java.util.ArrayList; import org.gudy.azureus2.core3.util.HashWrapper; /** * @author TuxPaper * @created Sep 15, 2007 * */ public class PlayNowList { private static ArrayList playNowList = new ArrayList(); /** * @param hw * * @since 3.0.1.7 */ public static void add(HashWrapper hw) { playNowList.add(hw); } public static void remove(HashWrapper hw) { playNowList.remove(hw); } public static boolean contains(HashWrapper hw) { return playNowList.contains(hw); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/utils/TorrentUIUtilsV3.java0000644000175000017500000003610611300667040025131 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.utils; import java.io.ByteArrayInputStream; import java.io.File; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerAdapter; import org.gudy.azureus2.core3.global.GlobalManagerListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloader; import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderCallBackInterface; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfoContentNetwork; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.ui.swt.browser.listener.DownloadUrlInfoSWT; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader.ImageDownloaderListener; import com.aelitis.azureus.ui.swt.views.skin.TorrentListViewsUtils; import com.aelitis.azureus.util.*; /** * @author TuxPaper * @created Sep 16, 2007 * */ public class TorrentUIUtilsV3 { private final static String MSG_ALREADY_EXISTS = "OpenTorrentWindow.mb.alreadyExists"; private final static String MSG_ALREADY_EXISTS_NAME = MSG_ALREADY_EXISTS + ".default.name"; //catches http://www.vuze.com/download/CHJW43PLS277RC7U3S5XRS2PZ4UUG7RS.torrent private static final Pattern hashPattern = Pattern.compile("download/([A-Z0-9]{32})\\.torrent"); public static void loadTorrent( final DownloadUrlInfo dlInfo, final boolean playNow, // open player final boolean playPrepare, // as for open player but don't actually open it final boolean bringToFront, final boolean forceDRMtoCDP) { CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { _loadTorrent(core, dlInfo, playNow, playPrepare, bringToFront, forceDRMtoCDP); } }); } private static void _loadTorrent(final AzureusCore core, final DownloadUrlInfo dlInfo, final boolean playNow, // open player final boolean playPrepare, // as for open player but don't actually open it final boolean bringToFront, final boolean forceDRMtoCDP) { if (dlInfo instanceof DownloadUrlInfoSWT) { DownloadUrlInfoSWT dlInfoSWT = (DownloadUrlInfoSWT) dlInfo; dlInfoSWT.invoke(playNow ? "play" : "download"); return; } String url = dlInfo.getDownloadURL(); try { Matcher m = hashPattern.matcher(url); if (m.find()) { String hash = m.group(1); GlobalManager gm = core.getGlobalManager(); final DownloadManager dm = gm.getDownloadManager(new HashWrapper( Base32.decode(hash))); if (dm != null) { if (playNow || playPrepare) { new AEThread2("playExisting", true) { public void run() { if (playNow) { Debug.outNoStack("loadTorrent already exists.. playing", false); TorrentListViewsUtils.playOrStream(dm); } else { Debug.outNoStack("loadTorrent already exists.. preparing", false); PlayUtils.prepareForPlay(dm); } } }.start(); } else { new MessageBoxShell(SWT.OK, MSG_ALREADY_EXISTS, new String[] { " ", dm.getDisplayName(), MessageText.getString(MSG_ALREADY_EXISTS_NAME), }).open(null); } return; } } // If it's going to our URLs, add some extra authenication if (UrlFilter.getInstance().urlCanRPC(url)) { ContentNetwork cn = null; if (dlInfo instanceof DownloadUrlInfoContentNetwork) { cn = ((DownloadUrlInfoContentNetwork) dlInfo).getContentNetwork(); } if (cn == null) { cn = ConstantsVuze.getDefaultContentNetwork(); } url = cn.appendURLSuffix(url, false, true); } UIFunctionsSWT uiFunctions = (UIFunctionsSWT) UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { if (!COConfigurationManager.getBooleanParameter("add_torrents_silently")) { if (bringToFront) { uiFunctions.bringToFront(); } } Shell shell = uiFunctions.getMainShell(); if (shell != null) { new FileDownloadWindow(shell, url, dlInfo.getReferer(), dlInfo.getRequestProperties(), new TorrentDownloaderCallBackInterface() { public void TorrentDownloaderEvent(int state, TorrentDownloader inf) { if (state == TorrentDownloader.STATE_FINISHED) { File file = inf.getFile(); file.deleteOnExit(); // Do a quick check to see if it's a torrent if (!TorrentUtil.isFileTorrent(file, null, file.getName())) { Matcher m = hashPattern.matcher(inf.getURL()); if (m.find()) { String hash = m.group(1); ContentNetwork cn = null; if (dlInfo instanceof DownloadUrlInfoContentNetwork) { cn = ((DownloadUrlInfoContentNetwork) dlInfo).getContentNetwork(); } if (cn == null) { cn = ConstantsVuze.getDefaultContentNetwork(); } TorrentListViewsUtils.viewDetails(cn, hash, "loadtorrent"); } else { TorrentUtil.isFileTorrent(file, Utils.findAnyShell(), file.getName()); } return; } TOTorrent torrent; try { torrent = TorrentUtils.readFromFile(file, false); } catch (TOTorrentException e) { Debug.out(e); return; } // Security: Only allow torrents from whitelisted trackers if (playNow && !PlatformTorrentUtils.isPlatformTracker(torrent)) { Debug.out("stopped loading torrent because it's not in whitelist"); return; } HashWrapper hw; try { hw = torrent.getHashWrapper(); } catch (TOTorrentException e1) { Debug.out(e1); return; } if (forceDRMtoCDP && (PlatformTorrentUtils.isContentDRM(torrent) || PlatformTorrentUtils.isContentPurchased(torrent))) { TorrentListViewsUtils.viewDetailsFromDS(torrent, "loadtorrent"); return; } GlobalManager gm = core.getGlobalManager(); if (playNow || playPrepare) { DownloadManager existingDM = gm.getDownloadManager(hw); if (existingDM != null) { if (playNow) { TorrentListViewsUtils.playOrStream(existingDM); } else { PlayUtils.prepareForPlay(existingDM); } return; } } final HashWrapper fhw = hw; GlobalManagerListener l = new GlobalManagerAdapter() { public void downloadManagerAdded(DownloadManager dm) { try { core.getGlobalManager().removeListener(this); handleDMAdded(dm, playNow, playPrepare, fhw); } catch (Exception e) { Debug.out(e); } } }; gm.addListener(l, false); if (playNow || playPrepare) { PlayNowList.add(hw); } TorrentOpener.openTorrent(file.getAbsolutePath()); } } }); } } } catch (Exception e) { Debug.out(e); } } private static void handleDMAdded(final DownloadManager dm, final boolean playNow, final boolean playPrepare, final HashWrapper fhw) { new AEThread2("playDM", true) { public void run() { try { HashWrapper hw = dm.getTorrent().getHashWrapper(); if (!hw.equals(fhw)) { return; } if (playNow || playPrepare) { if (playNow) { TorrentListViewsUtils.playOrStream(dm); } else { PlayUtils.prepareForPlay(dm); } } } catch (Exception e) { Debug.out(e); } } }.start(); } /** * No clue if we have a easy way to add a TOTorrent to the GM, so here it is * @param torrent * @return * * @since 3.0.5.3 */ public static void addTorrentToGM(final TOTorrent torrent) { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { File tempTorrentFile; try { tempTorrentFile = File.createTempFile("AZU", ".torrent"); tempTorrentFile.deleteOnExit(); String filename = tempTorrentFile.getAbsolutePath(); torrent.serialiseToBEncodedFile(tempTorrentFile); String savePath = COConfigurationManager.getStringParameter("Default save path"); if (savePath == null || savePath.length() == 0) { savePath = "."; } core.getGlobalManager().addDownloadManager(filename, savePath); } catch (Throwable t) { Debug.out(t); } } }); } /** * Retrieves the thumbnail for the content, pulling it from the web if * it can * * @param datasource * @param l When the thumbnail is available, this listener is triggered * @return If the image is immediately available, the image will be returned * as well as the trigger being fired. If the image isn't available * null will be returned and the listener will trigger when avail * * @since 4.0.0.5 */ public static Image[] getContentImage(Object datasource, boolean big, final ContentImageLoadedListener l) { if (l == null) { return null; } TOTorrent torrent = DataSourceUtils.getTorrent(datasource); if (torrent == null) { l.contentImageLoaded(null, true); return null; } final ImageLoader imageLoader = ImageLoader.getInstance(); String thumbnailUrl = PlatformTorrentUtils.getContentThumbnailUrl(torrent); //System.out.println("thumburl= " + thumbnailUrl); if (thumbnailUrl != null && imageLoader.imageExists(thumbnailUrl)) { //System.out.println("return thumburl"); Image image = imageLoader.getImage(thumbnailUrl); l.contentImageLoaded(image, true); return new Image[] { image }; } String hash = null; try { hash = torrent.getHashWrapper().toBase32String(); } catch (TOTorrentException e) { } if (hash == null) { l.contentImageLoaded(null, true); return null; } final String id = "Thumbnail." + hash; Image image = imageLoader.imageAdded(id) ? imageLoader.getImage(id) : null; //System.out.println("image = " + image); if (image != null && !image.isDisposed()) { l.contentImageLoaded(image, true); return new Image[] { image }; } final byte[] imageBytes = PlatformTorrentUtils.getContentThumbnail(torrent); //System.out.println("imageBytes = " + imageBytes); if (imageBytes != null) { image = (Image) Utils.execSWTThreadWithObject("thumbcreator", new AERunnableObject() { public Object runSupport() { ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes); Image image = new Image(Display.getDefault(), bis); return image; } }, 500); } /** if ((image == null || image.isDisposed()) && thumbnailUrl != null) { //System.out.println("get image from " + thumbnailUrl); image = imageLoader.getUrlImage(thumbnailUrl, new ImageDownloaderListener() { public void imageDownloaded(Image image, boolean returnedImmediately) { l.contentImageLoaded(image, returnedImmediately); //System.out.println("got image from thumburl"); } }); //System.out.println("returning " + image + " (url loading)"); return image == null ? null : new Image[] { image }; } **/ if (image == null || image.isDisposed()) { //System.out.println("build image from files"); DownloadManager dm = DataSourceUtils.getDM(datasource); /* * Try to get an image from the OS */ String path = null; if (dm == null) { if (torrent != null) { TOTorrentFile[] files = torrent.getFiles(); if (files.length > 0) { path = files[0].getRelativePath(); } } } else { path = dm.getDownloadState().getPrimaryFile(); } if (path != null) { image = ImageRepository.getPathIcon(path, big, false); if (image != null && torrent != null && !torrent.isSimpleTorrent()) { Image[] images = new Image[] { image, ImageRepository.getPathIcon(new File(path).getParent(), false, false) }; return images; } } if (image == null) { imageLoader.addImageNoDipose(id, ImageLoader.noImage); } else { imageLoader.addImageNoDipose(id, image); } } else { //System.out.println("has mystery image"); imageLoader.addImage(id, image); } l.contentImageLoaded(image, true); return new Image[] { image }; } public static void releaseContentImage(Object datasource) { TOTorrent torrent = DataSourceUtils.getTorrent(datasource); if (torrent == null) { return; } ImageLoader imageLoader = ImageLoader.getInstance(); String thumbnailUrl = PlatformTorrentUtils.getContentThumbnailUrl(torrent); if (thumbnailUrl != null) { imageLoader.releaseImage(thumbnailUrl); } else { String hash = null; try { hash = torrent.getHashWrapper().toBase32String(); } catch (TOTorrentException e) { } if (hash == null) { return; } String id = "Thumbnail." + hash; imageLoader.releaseImage(id); } } public static interface ContentImageLoadedListener { /** * @param image * @param wasReturned Image was also returned from getContentImage * * @since 4.0.0.5 */ public void contentImageLoaded(Image image, boolean wasReturned); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/uiupdater/0000755000175000017500000000000011310377632022003 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/uiupdater/UIUpdaterSWT.java0000644000175000017500000002211411036613130025075 0ustar adrianadrian/* * Created on Jun 15, 2006 12:29:32 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.uiupdater; import java.util.*; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.MainStatusBar; import com.aelitis.azureus.ui.common.updater.UIUpdatable; import com.aelitis.azureus.ui.common.updater.UIUpdatableAlways; import com.aelitis.azureus.ui.common.updater.UIUpdater; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; /** * @author TuxPaper * */ public class UIUpdaterSWT extends AEThread2 implements ParameterListener, UIUpdater { private static final LogIDs LOGID = LogIDs.UI3; private static final String CFG_REFRESH_INTERVAL = "GUI Refresh"; private static final String CFG_REFRESH_INACTIVE_FACTOR = "Refresh When Inactive"; /** Calculate timer statistics for GUI update */ private static final boolean DEBUG_TIMER = Constants.isCVSVersion(); private static UIUpdater updater = null; private int waitTimeMS; private boolean finished = false; private boolean refreshed = true; private ArrayList updateables = new ArrayList(); private ArrayList alwaysUpdateables = new ArrayList(); private AEMonitor updateables_mon = new AEMonitor("updateables"); private int inactiveFactor; private int inactiveTicks; Map averageTimes = DEBUG_TIMER ? new HashMap() : null; public static UIUpdater getInstance() { if (updater == null) { updater = new UIUpdaterSWT(); updater.start(); } return updater; } public UIUpdaterSWT() { super("UI Updater", true); COConfigurationManager.addAndFireParameterListeners(new String[] { CFG_REFRESH_INTERVAL, CFG_REFRESH_INACTIVE_FACTOR }, this); } // @see org.gudy.azureus2.core3.util.AEThread2#run() public void run() { while (!finished) { if (refreshed) { refreshed = false; if (!Utils.execSWTThread(new AERunnable() { public void runSupport() { try { Display display = Utils.getDisplay(); if (display == null) { return; } if (display.getActiveShell() == null) { Shell[] shells = display.getShells(); boolean noneVisible = true; for (int i = 0; i < shells.length; i++) { if (shells[i].isVisible() && !shells[i].getMinimized()) { noneVisible = false; break; } } if (noneVisible) { //System.out.println("nothing visible!"); if (alwaysUpdateables.size() > 0) { update(alwaysUpdateables); } return; } // inactive used to mean "active shell is not mainwindow", but // now that this is more generic (can be used with any shell), // inactive means "active shell is not one of our app's" if (inactiveTicks++ % inactiveFactor != 0) { return; } } update(updateables); } catch (Exception e) { Logger.log(new LogEvent(LOGID, "Error while trying to update GUI", e)); } finally { refreshed = true; } } })) { refreshed = true; } } try { Thread.sleep(waitTimeMS); } catch (Exception e) { Debug.printStackTrace(e); } } } // @see org.gudy.azureus2.core3.config.ParameterListener#parameterChanged(java.lang.String) public void parameterChanged(String parameterName) { waitTimeMS = COConfigurationManager.getIntParameter(CFG_REFRESH_INTERVAL); inactiveFactor = COConfigurationManager.getIntParameter(CFG_REFRESH_INACTIVE_FACTOR); } // @see com.aelitis.azureus.ui.swt.utils.UIUpdater#addUpdater(com.aelitis.azureus.ui.swt.utils.UIUpdatable) public void addUpdater(UIUpdatable updateable) { updateables_mon.enter(); try { if (updateable instanceof UIUpdatableAlways) { if (!alwaysUpdateables.contains(updateable)) { alwaysUpdateables.add(updateable); } } if (!updateables.contains(updateable)) { updateables.add(updateable); } else { System.out.println("WARNING: already added UIUpdatable " + updateable); } } finally { updateables_mon.exit(); } } // @see com.aelitis.azureus.ui.swt.utils.UIUpdater#removeUpdater(com.aelitis.azureus.ui.swt.utils.UIUpdatable) public void removeUpdater(UIUpdatable updateable) { updateables_mon.enter(); try { updateables.remove(updateable); if (updateable instanceof UIUpdatableAlways) { alwaysUpdateables.remove(updateable); } } finally { updateables_mon.exit(); } } // @see com.aelitis.azureus.ui.swt.utils.UIUpdater#stopIt() public void stopIt() { finished = true; COConfigurationManager.removeParameterListener(CFG_REFRESH_INTERVAL, this); } private void update(List updateables) { long start = 0; Map mapTimeMap = DEBUG_TIMER ? new HashMap() : null; Display display = Utils.getDisplay(); if (display == null || display.isDisposed()) { return; } Object[] updateablesArray = updateables.toArray(); for (int i = 0; i < updateablesArray.length; i++) { UIUpdatable updateable = (UIUpdatable) updateablesArray[i]; if (updateable == null) { removeUpdater(updateable); } try { if (DEBUG_TIMER) { start = SystemTime.getCurrentTime(); } updateable.updateUI(); if (DEBUG_TIMER) { long diff = SystemTime.getCurrentTime() - start; if (diff > 0) { mapTimeMap.put(updateable, new Long(diff)); } } } catch (Throwable t) { Logger.log(new LogEvent(LOGID, "Error while trying to update UI Element " + updateable.getUpdateUIName(), t)); } } if (DEBUG_TIMER) { makeDebugToolTip(mapTimeMap); } } private void makeDebugToolTip(Map timeMap) { final int IDX_AVG = 0; final int IDX_SIZE = 1; final int IDX_MAX = 2; final int IDX_LAST = 3; final int IDX_TIME = 4; long ttl = 0; for (Iterator iter = timeMap.keySet().iterator(); iter.hasNext();) { Object key = iter.next(); if (!averageTimes.containsKey(key)) averageTimes.put(key, new Object[] { new Long(0), new Long(0), new Long(0), new Long(0), new Long(System.currentTimeMillis()) }); Object[] average = (Object[]) averageTimes.get(key); long diff = ((Long) timeMap.get(key)).longValue(); if (diff > 0) { long count = ((Long) average[IDX_SIZE]).longValue(); // Limit to 20. Gives slightly scewed averages, but doesn't // require storing all 20 values and averaging them each time if (count >= 20) count = 19; long lNewAverage = ((((Long) average[IDX_AVG]).longValue() * count) + diff) / (count + 1); average[IDX_AVG] = new Long(lNewAverage); average[IDX_SIZE] = new Long(count + 1); if (diff > ((Long) average[IDX_MAX]).longValue()) average[IDX_MAX] = new Long(diff); average[IDX_LAST] = new Long(diff); average[IDX_TIME] = new Long(System.currentTimeMillis()); } else { average[IDX_LAST] = new Long(diff); } ttl += diff; averageTimes.put(key, average); } //System.out.println(SystemTime.getCurrentTime() + "] Refresh " + ttl + "ms"); MainStatusBar mainStatusBar = UIFunctionsManagerSWT.getUIFunctionsSWT().getMainStatusBar(); if (mainStatusBar != null && mainStatusBar.isMouseOver()) { StringBuffer sb = new StringBuffer(); for (Iterator iter = averageTimes.keySet().iterator(); iter.hasNext();) { Object key = iter.next(); Object[] average = (Object[]) averageTimes.get(key); long lLastUpdated = ((Long) average[IDX_TIME]).longValue(); if (System.currentTimeMillis() - lLastUpdated > 10000) { iter.remove(); continue; } long lTime = ((Long) average[IDX_AVG]).longValue(); if (lTime > 0) { if (sb.length() > 0) sb.append("\n"); sb.append(lTime * 100 / waitTimeMS); sb.append("% "); sb.append(lTime + "ms avg: "); sb.append("[" + ((UIUpdatable) key).getUpdateUIName() + "]"); sb.append(average[IDX_SIZE] + " samples"); sb.append("; max:" + average[IDX_MAX]); sb.append("; last:" + average[IDX_LAST]); } } mainStatusBar.setDebugInfo(sb.toString()); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/widgets/0000755000175000017500000000000011310377632021447 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/widgets/AnimatedImage.java0000644000175000017500000000545511127403350025001 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.widgets; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.AEThread2; import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; public class AnimatedImage { //wait time in ms private static final int SPEED = 100; Canvas canvas; boolean running; private AEThread2 runner; private Image[] images; private int currentImage = 0; private String imageName; public AnimatedImage(Composite parent) { canvas = new Canvas(parent,SWT.NONE); Color background = null; Composite p = parent; while(p != null && background == null) { background = p.getBackground(); if(background != null) { System.out.println("background : " + background + ", composite : " + p); } p = p.getParent(); } canvas.setBackground(background); canvas.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event event) { stop(); disposeImages(); } }); } private void renderNextImage() { if(!canvas.isDisposed()) { Display display = canvas.getDisplay(); if(!display.isDisposed()) { display.asyncExec( new Runnable() { public void run() { if(!canvas.isDisposed() && images != null) { currentImage++; if(currentImage >= images.length) { currentImage = 0; } if(currentImage < images.length) { Image image = images[currentImage]; if(image != null && !image.isDisposed()) { GC gc = new GC(canvas); Point canvasSize = canvas.getSize(); Rectangle imageBounds = image.getBounds(); gc.drawImage(image, (canvasSize.x-imageBounds.width)/2, (canvasSize.y-imageBounds.height)/2); gc.dispose(); } } } } }); } } } public void setLayoutData(Object data) { canvas.setLayoutData(data); } public void start() { running = true; runner = new AEThread2("image runner",true) { public void run() { while(running) { try { renderNextImage(); Thread.sleep(SPEED); } catch (Exception e) { running = false; } } } }; runner.start(); } public void stop() { running = false; } public Control getControl() { return canvas; } public void dispose() { if(canvas != null && !canvas.isDisposed()) { canvas.dispose(); } } public void setImageFromName(String imageName) { this.imageName = imageName; ImageLoader imageLoader = ImageLoader.getInstance(); images = imageLoader.getImages(imageName); } private void setImages(Image[] images) { disposeImages(); this.images = images; } private void disposeImages() { if(images != null) { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.releaseImage(imageName); images = null; } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/browser/0000755000175000017500000000000011310377632021464 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/browser/OpenCloseSearchDetailsListener.java0000644000175000017500000000045511074625016030363 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.browser; import java.util.Map; public interface OpenCloseSearchDetailsListener { public void openSearchResults(final Map params); public void closeSearchResults(final Map params); public void resizeMainBrowser(); public void resizeSecondaryBrowser(); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/browser/CookiesListener.java0000644000175000017500000000020011051137136025414 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.browser; public interface CookiesListener { public void cookiesFound(String cookies); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/browser/listener/0000755000175000017500000000000011310377632023311 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/browser/listener/TorrentListener.java0000644000175000017500000001106711266266270027331 0ustar adrianadrianpackage com.aelitis.azureus.ui.swt.browser.listener; import java.io.File; import java.util.Map; import org.eclipse.swt.widgets.Shell; import org.bouncycastle.util.encoders.Base64; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.core.messenger.ClientMessageContext; import com.aelitis.azureus.core.messenger.ClientMessageContext.torrentURLHandler; import com.aelitis.azureus.core.messenger.browser.BrowserMessage; import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfoContentNetwork; import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3; import com.aelitis.azureus.util.MapUtils; public class TorrentListener extends AbstractBrowserMessageListener { public static final String DEFAULT_LISTENER_ID = "torrent"; public static final String OP_LOAD_TORRENT_OLD = "loadTorrent"; public static final String OP_LOAD_TORRENT = "load-torrent"; private ClientMessageContext.torrentURLHandler torrentURLHandler; public TorrentListener(String id) { super(id); } public TorrentListener() { this(DEFAULT_LISTENER_ID); } public void setTorrentURLHandler( torrentURLHandler handler) { torrentURLHandler = handler; } public void setShell(Shell shell) { } public void handleMessage(final BrowserMessage message) { String opid = message.getOperationId(); if (OP_LOAD_TORRENT.equals(opid) || OP_LOAD_TORRENT_OLD.equals(opid)) { final Map decodedMap = message.getDecodedMap(); String url = MapUtils.getMapString(decodedMap, "url", null); final boolean playNow = MapUtils.getMapBoolean(decodedMap, "play-now", false); final boolean playPrepare = MapUtils.getMapBoolean(decodedMap, "play-prepare", false); final boolean bringToFront = MapUtils.getMapBoolean(decodedMap, "bring-to-front", true); if (url != null) { if ( torrentURLHandler != null ){ try{ torrentURLHandler.handleTorrentURL( url ); }catch( Throwable e ){ Debug.printStackTrace(e); } } final DownloadUrlInfo dlInfo = new DownloadUrlInfoContentNetwork(url, ContentNetworkManagerFactory.getSingleton().getContentNetwork( context.getContentNetworkID())); dlInfo.setReferer(message.getReferer()); AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { TorrentUIUtilsV3.loadTorrent(dlInfo, playNow, playPrepare, bringToFront, false); } }); } else { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { loadTorrentByB64(core, message, MapUtils.getMapString(decodedMap, "b64", null)); } }); } } else { throw new IllegalArgumentException("Unknown operation: " + opid); } } public static boolean loadTorrentByB64(AzureusCore core, String b64) { return loadTorrentByB64(core, null, b64); } /** * @param mapString * * @since 3.0.1.7 */ private static boolean loadTorrentByB64(AzureusCore core, BrowserMessage message, String b64) { if (b64 == null) { return false; } byte[] decodedTorrent = Base64.decode(b64); File tempTorrentFile; try { tempTorrentFile = File.createTempFile("AZU", ".torrent"); tempTorrentFile.deleteOnExit(); String filename = tempTorrentFile.getAbsolutePath(); FileUtil.writeBytesAsFile(filename, decodedTorrent); TOTorrent torrent = TorrentUtils.readFromFile(tempTorrentFile, false); // Security: Only allow torrents from whitelisted trackers if (!PlatformTorrentUtils.isPlatformTracker(torrent)) { Debug.out("stopped loading torrent because it's not in whitelist"); return false; } String savePath = COConfigurationManager.getStringParameter("Default save path"); if (savePath == null || savePath.length() == 0) { savePath = "."; } core.getGlobalManager().addDownloadManager(filename, savePath); } catch (Throwable t) { if (message != null) { message.debug("loadUrl error", t); } else { Debug.out(t); } return false; } return true; } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/browser/listener/MetaSearchListener.java0000644000175000017500000016021111306150472027673 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.ui.swt.browser.listener; import java.io.File; import java.net.URL; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerAdapter; import org.gudy.azureus2.core3.global.GlobalManagerListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.core.custom.CustomizationManagerFactory; import com.aelitis.azureus.core.messenger.browser.BrowserMessage; import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener; import com.aelitis.azureus.core.metasearch.*; import com.aelitis.azureus.core.metasearch.impl.ExternalLoginListener; import com.aelitis.azureus.core.metasearch.impl.ExternalLoginWindow; import com.aelitis.azureus.core.metasearch.impl.web.CookieParser; import com.aelitis.azureus.core.metasearch.impl.web.WebEngine; import com.aelitis.azureus.core.subs.Subscription; import com.aelitis.azureus.core.subs.SubscriptionDownloadListener; import com.aelitis.azureus.core.subs.SubscriptionException; import com.aelitis.azureus.core.subs.SubscriptionHistory; import com.aelitis.azureus.core.subs.SubscriptionManagerFactory; import com.aelitis.azureus.core.subs.SubscriptionResult; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.core.vuzefile.VuzeFileComponent; import com.aelitis.azureus.core.vuzefile.VuzeFileHandler; import com.aelitis.azureus.ui.swt.browser.OpenCloseSearchDetailsListener; import com.aelitis.azureus.ui.swt.views.skin.TorrentListViewsUtils; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.JSONUtils; import com.aelitis.azureus.util.UrlFilter; public class MetaSearchListener extends AbstractBrowserMessageListener { public static final String LISTENER_ID = "metasearch"; public static final String OP_SEARCH = "search"; public static final String OP_GET_ENGINES = "get-engines"; public static final String OP_GET_ALL_ENGINES = "get-all-engines"; public static final String OP_ENGINE_PREFERRED = "engine-preferred"; public static final String OP_CHANGE_ENGINE_SELECTION = "change-engine-selection"; public static final String OP_SET_SELECTED_ENGINES = "set-selected-engines"; public static final String OP_GET_AUTO_MODE = "get-auto-mode"; public static final String OP_SAVE_TEMPLATE = "save-template"; public static final String OP_LOAD_TEMPLATE = "load-template"; public static final String OP_DELETE_TEMPLATE = "delete-template"; public static final String OP_TEST_TEMPLATE = "test-template"; public static final String OP_EXPORT_TEMPLATE = "export-template"; public static final String OP_IMPORT_TEMPLATE = "import-template"; public static final String OP_OPEN_SEARCH_RESULTS = "open-search-results"; public static final String OP_CLOSE_SEARCH_RESULTS = "close-search-results"; public static final String OP_LOAD_TORRENT = "load-torrent"; public static final String OP_HAS_LOAD_TORRENT = "has-load-torrent"; public static final String OP_ENGINE_LOGIN = "engine-login"; public static final String OP_GET_LOGIN_COOKIES = "get-login-cookies"; public static final String OP_CREATE_SUBSCRIPTION = "create-subscription"; public static final String OP_READ_SUBSCRIPTION = "read-subscription"; public static final String OP_UPDATE_SUBSCRIPTION = "update-subscription"; public static final String OP_READ_SUBSCRIPTION_RESULTS = "read-subscription-results"; public static final String OP_DELETE_SUBSCRIPTION_RESULTS = "delete-subscription-results"; public static final String OP_MARK_SUBSCRIPTION_RESULTS = "mark-subscription-results"; public static final String OP_DOWNLOAD_SUBSCRIPTION = "download-subscription"; public static final String OP_SUBSCRIPTION_SET_AUTODL = "subscription-set-auto-download"; public static final String OP_IS_CUSTOMISED = "is-customized"; private static final Set active_subs_auth = new HashSet(); private static final Set pending_play_now_urls = new HashSet(); static{ TorrentUtils.addTorrentAttributeListener( new TorrentUtils.torrentAttributeListener() { public void attributeSet( TOTorrent torrent, String attribute, Object value ) { if ( attribute == TorrentUtils.TORRENT_AZ_PROP_OBTAINED_FROM ){ try{ String torrent_url = (String)value; boolean hook_dm = false; synchronized(pending_play_now_urls ){ if ( pending_play_now_urls.remove( torrent_url )){ // ok, we now have the torrent associated with the URL hook_dm = true; } } if ( !hook_dm ) { return; } if (!AzureusCoreFactory.isCoreRunning()) { // shouldn't happen, but.. Debug.out("Core wasn't available for pending play now" ); } else { final HashWrapper hash = torrent.getHashWrapper(); AzureusCore core = AzureusCoreFactory.getSingleton(); final GlobalManager gm = core.getGlobalManager(); DownloadManager existing = gm.getDownloadManager( hash ); if ( existing != null) { playOrStream( existing ); return; } GlobalManagerListener l = new GlobalManagerAdapter() { private final long listener_add_time = SystemTime.getMonotonousTime(); public void downloadManagerAdded( DownloadManager dm ) { try{ TOTorrent t = dm.getTorrent(); if ( t.getHashWrapper().equals( hash )){ gm.removeListener( this ); playOrStream( dm ); } }catch( Throwable e ){ Debug.out( e ); }finally{ if ( SystemTime.getMonotonousTime() - listener_add_time > 5*60*1000 ){ gm.removeListener( this ); } } } }; gm.addListener( l, false ); } }catch( Throwable e ){ Debug.printStackTrace(e); } } } }); } private static void playOrStream( final DownloadManager download ) { new AEThread2( "MSL:POS", true ) { public void run() { TorrentListViewsUtils.playOrStream( download ); } }.start(); } private final OpenCloseSearchDetailsListener openCloseSearchDetailsListener; public MetaSearchListener( OpenCloseSearchDetailsListener openCloseSearchDetailsListener ) { super(LISTENER_ID); this.openCloseSearchDetailsListener = openCloseSearchDetailsListener; } public void handleMessage(BrowserMessage message) { String opid = message.getOperationId(); MetaSearchManager metaSearchManager = MetaSearchManagerFactory.getSingleton(); metaSearchManager.log( "BrowserListener: received " + message ); if (OP_SEARCH.equals(opid)) { Map decodedMap = message.getDecodedMap(); search( decodedMap, null ); }else if ( OP_ENGINE_PREFERRED.equals( opid )){ final Map decodedMap = message.getDecodedMap(); long engine_id = ((Long)decodedMap.get("engine_id")).longValue(); Engine engine = getEngineFromId( engine_id ); if ( engine != null ){ metaSearchManager.getMetaSearch().enginePreferred( engine ); } } else if(OP_ENGINE_LOGIN.equals(opid)) { final Map decodedMap = message.getDecodedMap(); long engine_id = ((Long)decodedMap.get("engine_id")).longValue(); final Long sid = (Long)decodedMap.get( "sid" ); final Engine engine = getEngineFromId(engine_id); if ( engine != null && engine instanceof WebEngine){ final WebEngine webEngine = (WebEngine) engine; Utils.execSWTThread( new Runnable() { public void run() { new ExternalLoginWindow( new ExternalLoginListener() { private String previous_cookies; private boolean search_done; public void canceled( ExternalLoginWindow window ) { /* gouss doesn't wan't anything on cancel if ( !outcome_informed ){ outcome_informed = true; Map params = getParams( webEngine ); params.put( "error", "operation cancelled" ); sendBrowserMessage("metasearch", "engineFailed", params ); } */ } public void cookiesFound( ExternalLoginWindow window, String cookies ) { if ( handleCookies( cookies, false )){ window.close(); } } public void done( ExternalLoginWindow window, String cookies ) { handleCookies( cookies, true ); /* if ( !outcome_informed ){ outcome_informed = true; Map params = getParams( webEngine ); sendBrowserMessage("metasearch", "engineCompleted", params ); } */ } private boolean handleCookies( String cookies, boolean force_if_ready ) { if ( search_done ){ return( false ); } String[] required = webEngine.getRequiredCookies(); boolean skip_search = required.length == 0 && !force_if_ready; if ( CookieParser.cookiesContain( required, cookies )){ webEngine.setCookies(cookies); if ( previous_cookies == null || !previous_cookies.equals( cookies )){ previous_cookies = cookies; if ( !skip_search ){ // search operation will report outcome search_done = true; search( decodedMap, webEngine ); } } } return( search_done ); } /* protected Map getParams( Engine engine ) { Map params = new HashMap(); params.put("id", new Long(engine.getId())); params.put("name", engine.getName()); params.put("favicon", engine.getIcon()); params.put("dl_link_css", engine.getDownloadLinkCSS()); params.put("shareable", new Boolean( engine.isShareable())); if ( sid != null ){ params.put( "sid", sid ); } return( params ); } */ }, webEngine.getName(), webEngine.getLoginPageUrl(), false, webEngine.getAuthMethod(), engine.isMine()); } }); }else{ Map params = new HashMap(); if ( sid != null ){ params.put( "sid", sid ); } params.put( "error", "engine not found or not a web engine" ); sendBrowserMessage("metasearch", "engineFailed", params ); } } else if(OP_GET_LOGIN_COOKIES.equals(opid)) { final Map decodedMap = message.getDecodedMap(); final String url = ((String) decodedMap.get("url")).replaceAll("%s", ""); Utils.execSWTThread( new Runnable() { public void run() { new ExternalLoginWindow( new ExternalLoginListener() { public void canceled(ExternalLoginWindow window) { sendBrowserMessage("metasearch", "setCookiesFailed", new HashMap() ); }; public void cookiesFound(ExternalLoginWindow window, String cookies) {}; public void done(ExternalLoginWindow window, String cookies) { String[] cookieNames = CookieParser.getCookiesNames(cookies); Map params = new HashMap(); params.put("cookieNames", cookieNames); params.put("currentCookie",cookies); params.put("cookieMethod", window.proxyCaptureModeRequired()?WebEngine.AM_PROXY:WebEngine.AM_TRANSPARENT ); sendBrowserMessage("metasearch", "setCookies", params ); }; }, url, url, true, WebEngine.AM_PROXY, true ); } }); } else if(OP_GET_ENGINES.equals(opid)) { String subscriptionId = null; try { final Map decodedMap = message.getDecodedMap(); subscriptionId = ((String)decodedMap.get("subs_id")); } catch(Exception e) { //No parameters } Engine[] engines = null; if ( subscriptionId != null ){ engines = new Engine[0]; Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( subscriptionId ); if ( subs != null ){ try{ Engine engine = subs.getEngine(); if ( engine != null ){ engines = new Engine[]{ engine }; } }catch( Throwable e ){ Debug.out( e ); } } } if ( engines == null ){ engines = metaSearchManager.getMetaSearch().getEngines( true, true ); } List params = new ArrayList(); for(int i = 0 ; i < engines.length ; i++) { Engine engine = engines[i]; if ( !engine.isActive() || engine.getSource() == Engine.ENGINE_SOURCE_UNKNOWN ){ // don't skip if this is an explicit get if ( subscriptionId == null ){ continue; } } Map engineMap = new HashMap(); engineMap.put("id", new Long(engine.getId())); engineMap.put("name", engine.getName()); engineMap.put("favicon", engine.getIcon()); engineMap.put("dl_link_css", engine.getDownloadLinkCSS()); engineMap.put("selected", Engine.SEL_STATE_STRINGS[ engine.getSelectionState()]); engineMap.put("type", Engine.ENGINE_SOURCE_STRS[ engine.getSource()]); engineMap.put("shareable", new Boolean( engine.isShareable())); params.add(engineMap); } sendBrowserMessage("metasearch", "enginesUsed",params); } else if(OP_GET_ALL_ENGINES.equals(opid)) { Engine[] engines = metaSearchManager.getMetaSearch().getEngines( false, true ); List params = new ArrayList(); for(int i = 0 ; i < engines.length ; i++) { Engine engine = engines[i]; if ( engine.getSource() == Engine.ENGINE_SOURCE_UNKNOWN ){ continue; } Map engineMap = new HashMap(); engineMap.put("id", new Long(engine.getId())); engineMap.put("name", engine.getName()); engineMap.put("favicon", engine.getIcon()); engineMap.put("dl_link_css", engine.getDownloadLinkCSS()); engineMap.put("selected", Engine.SEL_STATE_STRINGS[ engine.getSelectionState()]); engineMap.put("type", Engine.ENGINE_SOURCE_STRS[ engine.getSource()]); engineMap.put("shareable", new Boolean( engine.isShareable())); params.add(engineMap); } sendBrowserMessage("metasearch", "engineList",params); } else if( OP_SET_SELECTED_ENGINES.equals(opid)){ Map decodedMap = message.getDecodedMap(); List template_ids = (List)decodedMap.get( "template_ids" ); long[] ids = new long[template_ids.size()]; for (int i=0;i context = new HashMap(); context.put( Engine.SC_FORCE_FULL, "true" ); context.put( Engine.SC_BATCH_PERIOD, "1000" ); context.put( Engine.SC_REMOVE_DUP_HASH, "true" ); if ( target == null ){ metaSearchManager.getMetaSearch().search( listener, parameters, headers, context, max_per_engine ); }else{ metaSearchManager.getMetaSearch().search( new Engine[]{ target }, listener, parameters, headers, context, max_per_engine ); } } protected void encodeResults( Subscription subs, Map result ) { JSONArray results_list = new JSONArray(); SubscriptionResult[] results = subs.getHistory().getResults( false ); for(int i=0; i list = new ArrayList(); DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent(); for (DownloadManager dm : dms) { if (dm != null) { Map mapDM = new HashMap(); TOTorrent torrent = dm.getTorrent(); if (torrent != null && !TorrentUtils.isReallyPrivate(torrent)) { try { // make a copy of the torrent Map torrent_map = torrent.serialiseToMap(); TOTorrent torrent_to_send = TOTorrentFactory.deserialiseFromMap( torrent_map ); Map vuze_map = (Map)torrent_map.get( "vuze" ); // remove any non-standard stuff (e.g. resume data) torrent_to_send.removeAdditionalProperties(); torrent_map = torrent_to_send.serialiseToMap(); if ( vuze_map != null ){ torrent_map.put( "vuze", vuze_map ); } byte[] encode = BEncoder.encode(torrent_map); mapDM.put("name", PlatformTorrentUtils.getContentTitle2(dm)); mapDM.put("torrent", Base32.encode(encode)); list.add(mapDM); } catch (Throwable t) { Debug.out(t); } } } } if (list.size() > 0 && context != null) { context.executeInBrowser(callback + "(" + JSONUtils.encodeToJSON(list) + ")"); } } /** * @param message * @param decodedMap * * @since 3.1.1.1 */ private void setSelectedContent(BrowserMessage message, Map decodedMap) { String hash = MapUtils.getMapString(decodedMap, "torrent-hash", null); String displayName = MapUtils.getMapString(decodedMap, "display-name", null); String dlURL = MapUtils.getMapString(decodedMap, "download-url", null); String referer = MapUtils.getMapString(decodedMap, "referer", "displaylistener"); if (hash == null && dlURL == null) { SelectedContentManager.changeCurrentlySelectedContent(referer, null); } String callback = MapUtils.getMapString(decodedMap, "callback", null); if (callback != null && context != null) { DownloadUrlInfoSWT dlInfo = new DownloadUrlInfoSWT(context, callback, hash); boolean canPlay = MapUtils.getMapBoolean(decodedMap, "can-play", false); boolean isVuzeContent = MapUtils.getMapBoolean(decodedMap, "is-vuze-content", true); SelectedContentV3 content = new SelectedContentV3(hash, displayName, isVuzeContent, canPlay); content.setDownloadInfo(dlInfo); SelectedContentManager.changeCurrentlySelectedContent(referer, new ISelectedContent[] { content }); return; } if (displayName != null) { String dlReferer = MapUtils.getMapString(decodedMap, "download-referer", null); String dlCookies = MapUtils.getMapString(decodedMap, "download-cookies", null); Map dlHeader = MapUtils.getMapMap(decodedMap, "download-header", null); boolean canPlay = MapUtils.getMapBoolean(decodedMap, "can-play", false); boolean isVuzeContent = MapUtils.getMapBoolean(decodedMap, "is-vuze-content", true); SelectedContentV3 content = new SelectedContentV3(hash, displayName, isVuzeContent, canPlay); content.setThumbURL(MapUtils.getMapString(decodedMap, "thumbnail.url", null)); DownloadUrlInfo dlInfo = new DownloadUrlInfoContentNetwork(dlURL, ContentNetworkManagerFactory.getSingleton().getContentNetwork( context.getContentNetworkID())); dlInfo.setReferer(dlReferer); if (dlCookies != null) { if (dlHeader == null) { dlHeader = new HashMap(); } dlHeader.put("Cookie", dlCookies); } dlInfo.setRequestProperties(dlHeader); String subID = MapUtils.getMapString(decodedMap, "subscription-id", null); String subresID = MapUtils.getMapString(decodedMap, "subscription-result-id", null); if (subID != null && subresID != null) { Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( subID); if (subs != null) { subs.addPotentialAssociation(subresID, dlURL); } } // pass decodeMap down to TorrentUIUtilsV3.loadTorrent in case // is needs some other params dlInfo.setAdditionalProperties(decodedMap); content.setDownloadInfo(dlInfo); SelectedContentManager.changeCurrentlySelectedContent(referer, new ISelectedContent[] { content }); } else { SelectedContentManager.changeCurrentlySelectedContent(referer, null); } } /** * @param string * * @since 3.0.0.7 */ public static void switchToTab(String tabID, String sourceRef) { SideBar sideBar = (SideBar) SkinViewManager.getByClass(SideBar.class); if (sideBar == null) { return; } if (sourceRef != null) { ContentNetworkUtils.setSourceRef(tabID, sourceRef, false); } sideBar.showEntryByTabID(tabID); } /** * */ private void bringToFront() { final UIFunctions functions = UIFunctionsManager.getUIFunctions(); if (functions != null) { functions.bringToFront(); } } /** * */ private void resetURL() { if (browser == null || browser.isDisposed()) { return; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (browser == null || browser.isDisposed()) { return; } String sURL = (String) browser.getData("StartURL"); context.debug("reset " + sURL); if (sURL != null && sURL.length() > 0) { String startURLUnique; String sRand = "rand=" + SystemTime.getCurrentTime(); if (sURL.indexOf("rand=") > 0) { startURLUnique = sURL.replaceAll("rand=[0-9.]+", sRand); } else if (sURL.indexOf('?') > 0) { startURLUnique = sURL + "&" + sRand; } else { startURLUnique = sURL + "?" + sRand; } browser.setUrl(startURLUnique); } } }); } /** * @param string * * @since 3.0.5.0 */ public static void refreshTab(String tabID) { if (null == tabID || tabID.length() < 1) { return; } SWTSkin skin = SWTSkinFactory.getInstance(); /* * Refreshes all except the currently active tab */ if (true == VZ_NON_ACTIVE.equals(tabID)) { // 3.2 TODO: Need to fix this up List browserViewIDs = new ArrayList(); // Check if not active view and refresh (personally, sounds dangerous) for (Iterator iterator = browserViewIDs.iterator(); iterator.hasNext();) { refreshBrowser(iterator.next().toString()); } } else { refreshBrowser(tabID); } } private static void refreshBrowser(final String browserID) { Utils.execSWTThread(new AERunnable() { public void runSupport() { SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class); SideBarEntrySWT entry = SideBar.getEntry(browserID); SWTSkinObjectBrowser soBrowser = SWTSkinUtils.findBrowserSO(entry.getSkinObject()); if (soBrowser != null) { soBrowser.refresh(); return; } SWTSkin skin = SWTSkinFactory.getInstance(); SWTSkinObject skinObject = skin.getSkinObject(browserID); if (skinObject instanceof SWTSkinObjectBrowser) { final Browser browser = ((SWTSkinObjectBrowser) skinObject).getBrowser(); if (null != browser && false == browser.isDisposed()) { browser.refresh(); } } } }); } private void launchUrl(final String url) { if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("mailto:")) { Utils.launch(url); } } private void sendEmail(final String to, final String subject, final String body) { String url = "mailto:" + to + "?subject=" + UrlUtils.encode(subject); if (body != null) { url = url + "&body=" + UrlUtils.encode(body); } Utils.launch(url); } private void copyToClipboard(final String text) { if (browser == null || browser.isDisposed()) { return; } Utils.execSWTThread(new AERunnable() { public void runSupport() { if (browser == null || browser.isDisposed()) { return; } final Clipboard cb = new Clipboard(browser.getDisplay()); TextTransfer textTransfer = TextTransfer.getInstance(); cb.setContents(new Object[] { text }, new Transfer[] { textTransfer }); cb.dispose(); } }); } private void openIrc(final String server, final String channel, final String alias) { try { PluginManager pluginManager = PluginInitializer.getDefaultInterface().getPluginManager(); PluginInterface piChat = pluginManager.getPluginInterfaceByID("azplugins"); UIManager manager = piChat.getUIManager(); manager.addUIListener(new UIManagerListener() { public void UIDetached(UIInstance instance) { } public void UIAttached(UIInstance instance) { if (instance instanceof UISWTInstance) { try { debug("Opening IRC channel " + channel + " on " + server + " for user " + alias); UISWTInstance swtInstance = (UISWTInstance) instance; UISWTView[] openViews = swtInstance.getOpenViews(UISWTInstance.VIEW_MAIN); for (int i = 0; i < openViews.length; i++) { UISWTView view = openViews[i]; // if only there was a way to tell if it was our IRC view.closeView(); } swtInstance.openView(UISWTInstance.VIEW_MAIN, "IRC", new String[] { server, channel, alias }); } catch (Exception e) { debug("Failure opening IRC channel " + channel + " on " + server, e); } } } }); } catch (Exception e) { debug("Failure opening IRC channel " + channel + " on " + server, e); } } private void showBrowser(final String url, final String target, final int w, final int h, final boolean allowResize, final BrowserMessage message, final String sourceRef) { final UIFunctions functions = UIFunctionsManager.getUIFunctions(); if (functions == null) { AEThread2 thread = new AEThread2("show browser " + url, true) { public void run() { final Display display = Display.getDefault(); display.asyncExec(new AERunnable() { public void runSupport() { BrowserWindow window = new BrowserWindow( display.getActiveShell(), url, w, h, allowResize, false); window.waitUntilClosed(); message.complete(false, true, null); } }); } }; thread.start(); return; } AEThread2 thread = new AEThread2("show browser " + url, true) { public void run() { if (w == 0 && target != null) { functions.viewURL(url, target, sourceRef); } else { functions.viewURL(url, target, w, h, allowResize, false); } message.complete(false, true, null); } }; thread.start(); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/browser/listener/ConfigListener.java0000644000175000017500000001205711171750562027076 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.swt.browser.listener; import java.util.Map; import org.eclipse.swt.browser.Browser; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEDiagnosticsLogger; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.swt.update.UpdateMonitor; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.messenger.browser.BrowserMessage; import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.MapUtils; import com.aelitis.net.magneturi.MagnetURIHandler; /** * @author TuxPaper * @created Mar 30, 2007 * */ public class ConfigListener extends AbstractBrowserMessageListener { public static final String DEFAULT_LISTENER_ID = "config"; public static final String OP_GET_VERSION = "get-version"; public static final String OP_NEW_INSTALL = "is-new-install"; public static final String OP_CHECK_FOR_UPDATES = "check-for-updates"; public static final String OP_GET_MAGNET_PORT = "get-magnet-port"; public static final String OP_LOG_DIAGS = "log-diags"; public static final String OP_LOG = "log"; public ConfigListener(String id, Browser browser) { super(id); } /** * */ public ConfigListener(Browser browser) { this(DEFAULT_LISTENER_ID, browser); } // @see com.aelitis.azureus.ui.swt.browser.msg.AbstractMessageListener#handleMessage(com.aelitis.azureus.ui.swt.browser.msg.BrowserMessage) public void handleMessage(BrowserMessage message) { try { String opid = message.getOperationId(); if (OP_GET_VERSION.equals(opid)) { Map decodedMap = message.getDecodedMap(); String callback = MapUtils.getMapString(decodedMap, "callback", null); if (callback != null) { context.executeInBrowser(callback + "('" + Constants.AZUREUS_VERSION + "')"); } else { message.debug("bad or no callback param"); } } else if (OP_NEW_INSTALL.equals(opid)) { Map decodedMap = message.getDecodedMap(); String callback = MapUtils.getMapString(decodedMap, "callback", null); if (callback != null) { context.executeInBrowser(callback + "(" + COConfigurationManager.isNewInstall() + ")"); } else { message.debug("bad or no callback param"); } } else if (OP_CHECK_FOR_UPDATES.equals(opid)) { checkForUpdates(); } else if (OP_GET_MAGNET_PORT.equals(opid)) { Map decodedMap = message.getDecodedMap(); String callback = MapUtils.getMapString(decodedMap, "callback", null); if (callback != null) { context.executeInBrowser(callback + "('" + MagnetURIHandler.getSingleton().getPort() + "')"); } else { message.debug("bad or no callback param"); } }else if ( OP_LOG_DIAGS.equals( opid )){ logDiagnostics(); } else if ( OP_LOG.equals(opid)) { Map decodedMap = message.getDecodedMap(); String loggerName = MapUtils.getMapString(decodedMap, "log-name", "browser"); String text = MapUtils.getMapString(decodedMap, "text", ""); AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger(loggerName); diag_logger.log(text); if (ConstantsVuze.DIAG_TO_STDOUT) { System.out.println(Thread.currentThread().getName() + "|" + System.currentTimeMillis() + "] " + text); } } } catch (Throwable t) { message.debug("handle Config message", t); } } public static void logDiagnostics() { AEDiagnostics.dumpThreads(); } /** * * * @since 3.0.5.3 */ public static void checkForUpdates() { UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { uiFunctions.bringToFront(); } AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { UpdateMonitor.getSingleton(core).performCheck(true, false, false, null); } }); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/browser/listener/DownloadUrlInfoSWT.java0000644000175000017500000000330311074301046027610 0ustar adrianadrian/** * Created on Sep 17, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.browser.listener; import com.aelitis.azureus.core.messenger.ClientMessageContext; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo; /** * @author TuxPaper * @created Sep 17, 2008 * */ public class DownloadUrlInfoSWT extends DownloadUrlInfo { private final ClientMessageContext context; private final String callback; private final String hash; /** * @param hash * @param url */ public DownloadUrlInfoSWT(ClientMessageContext context, String callback, String hash) { super(null); this.context = context; this.callback = callback; this.hash = hash; } /** * @return the context */ public ClientMessageContext getContext() { return context; } /** * @return the callback */ public String getCallback() { return callback; } public void invoke(String reason) { context.executeInBrowser(callback + "('" + reason + "','" + hash + "','" + getDownloadURL() + "')"); } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/browser/msg/0000755000175000017500000000000011310377632022252 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/swt/browser/msg/MessageDispatcherSWT.java0000644000175000017500000001440111305664420027104 0ustar adrianadrian/* * Created on Jun 29, 2006 10:16:26 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.browser.msg; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.browser.*; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.ui.swt.Utils; import com.aelitis.azureus.core.messenger.ClientMessageContext; import com.aelitis.azureus.core.messenger.browser.BrowserMessage; import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher; import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener; import com.aelitis.azureus.util.JSONUtils; import com.aelitis.azureus.util.UrlFilter; /** * Dispatches messages to listeners registered with unique IDs. */ public class MessageDispatcherSWT implements BrowserMessageDispatcher { private ClientMessageContext context; private Map listeners = new HashMap(); private Browser browser; private BrowserFunction browserFunction; /** * Registers itself as a listener to receive sequence number reset message. */ public MessageDispatcherSWT(ClientMessageContext context) { this.context = context; } public void registerBrowser(final Browser browser) { this.browser = browser; browserFunction = new BrowserFunction(browser, "sendMessageToAZ") { public Object function(Object[] args) { if (args == null) { context.debug("sendMessageToAZ: arguments null on " + browser.getUrl()); return null; } if (args.length != 3 && args.length != 2) { context.debug("sendMessageToAZ: # arguments not 2 or 3 (" + args.length + ") on " + browser.getUrl()); return null; } if (!(args[0] instanceof String)) { context.debug("sendMessageToAZ: Param 1 not String"); return null; } if (!(args[1] instanceof String)) { context.debug("sendMessageToAZ: Param 2 not String"); return null; } Map params = Collections.EMPTY_MAP; if (args.length == 3) { if (!(args[2] instanceof String)) { context.debug("sendMessageToAZ: Param 3 not String"); return null; } params = JSONUtils.decodeJSON((String)args[2]); } BrowserMessage message = new BrowserMessage((String) args[0], (String) args[1], params); dispatch(message); return null; } }; } /** * Detaches this dispatcher from the given {@link Browser}. * This dispatcher listens for dispose events from the browser * and calls this method in response. * * @param browser {@link Browser} which will no longer send messages */ public void deregisterBrowser(Browser browser) { if (browserFunction != null && !browserFunction.isDisposed()) { browserFunction.dispose(); } } /** * Registers the given listener for the given ID. * * @param id unique identifier used when dispatching messages * @param listener receives messages targetted at the given ID * * @throws IllegalStateException * if another listener is already registered under the same ID */ public synchronized void addListener(BrowserMessageListener listener) { String id = listener.getId(); BrowserMessageListener registered = listeners.get(id); if (registered != null) { if (registered != listener) { throw new IllegalStateException("Listener " + registered.getClass().getName() + " already registered for ID " + id); } } else { listener.setContext(context); listeners.put(id, listener); } } /** * Deregisters the listener with the given ID. * * @param id unique identifier of the listener to be removed */ public synchronized void removeListener(BrowserMessageListener listener) { removeListener(listener.getId()); } /** * Deregisters the listener with the given ID. * * @param id unique identifier of the listener to be removed */ public synchronized void removeListener(String id) { BrowserMessageListener removed = listeners.remove(id); if (removed == null) { // throw new IllegalStateException("No listener is registered for ID " + id); } else { removed.setContext(null); } } // @see com.aelitis.azureus.ui.swt.browser.msg.MessageDispatcher#getListener(java.lang.String) public BrowserMessageListener getListener(String id) { return listeners.get(id); } // @see com.aelitis.azureus.ui.swt.browser.msg.MessageDispatcher#dispatch(com.aelitis.azureus.core.messenger.browser.BrowserMessage) public void dispatch(final BrowserMessage message) { if (message == null) { return; } String referer = message.getReferer(); if (referer != null && !UrlFilter.getInstance().urlCanRPC(referer)) { context.debug("blocked " + message + "\n " + referer); return; } context.debug("Received " + message); if (browser != null && !browser.isDisposed() && Utils.isThisThreadSWT()) { context.debug(" browser url: " + browser.getUrl()); } // handle messages for dispatcher and context regardless of sequence number String listenerId = message.getListenerId(); if ("lightbox-browser".equals(listenerId)) { listenerId = "display"; } final BrowserMessageListener listener = getListener(listenerId); if (listener == null) { context.debug("No listener registered with ID " + listenerId); } else { new AEThread2("dispatch for " + listenerId, true) { public void run() { listener.handleMessage(message); message.complete(true, true, null); } }.start(); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/browser/ClientMessageContextSWT.java0000644000175000017500000000343611021114520027003 0ustar adrianadrian/** * Created on Jun 1, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.browser; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.widgets.Control; import com.aelitis.azureus.core.messenger.ClientMessageContext; /** * @author TuxPaper * @created Jun 1, 2008 * */ public interface ClientMessageContextSWT extends ClientMessageContext { /** * Attaches this context and its message dispatcher to the browser. * * @param browser the browser to be attached * @param widgetWaitingIndicator Widget to be shown when browser is loading */ public abstract void registerBrowser(final Browser browser, Control widgetWaitingIndicator); /** * Detaches everything from this context's browser. */ public abstract void deregisterBrowser(); /** * Deregisters the browser before it's disposed. * * @param event used to verify it's the correct context * * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent) */ public abstract void widgetDisposed(DisposeEvent event); } azureus-4.3.0.6/com/aelitis/azureus/ui/swt/browser/BrowserContext.java0000644000175000017500000005774211305664420025334 0ustar adrianadrian/* * Created on Jul 19, 2006 10:16:26 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.browser; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.*; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.program.Program; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.utils.StaticUtilities; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.shells.MessageBoxShell; import com.aelitis.azureus.core.messenger.ClientMessageContextImpl; import com.aelitis.azureus.core.messenger.browser.BrowserMessage; import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.core.vuzefile.VuzeFileHandler; import com.aelitis.azureus.ui.swt.browser.msg.MessageDispatcherSWT; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.JSONUtils; import com.aelitis.azureus.util.UrlFilter; /** * Manages the context for a single SWT {@link Browser} component, * including listeners and messages. * * @author dharkness * @created Jul 19, 2006 */ public class BrowserContext extends ClientMessageContextImpl implements DisposeListener { private static final String CONTEXT_KEY = "BrowserContext"; private static final String KEY_ENABLE_MENU = "browser.menu.enable"; private Browser browser; private Display display; private boolean pageLoading = false; private long pageLoadingStart = 0; private String lastValidURL = null; private final boolean forceVisibleAfterLoad; private TimerEventPeriodic checkURLEvent; private Control widgetWaitIndicator; private MessageDispatcherSWT messageDispatcherSWT; protected boolean wiggleBrowser = Utils.isCarbon; private torrentURLHandler torrentURLHandler; private List loadingListeners = Collections.EMPTY_LIST; private long pageLoadTime; private long contentNetworkID = ConstantsVuze.DEFAULT_CONTENT_NETWORK_ID; private AEMonitor mon_listJS = new AEMonitor("listJS"); private List listJS = new ArrayList(1); /** * Creates a context and registers the given browser. * * @param id unique identifier of this context * @param browser the browser to be registered */ public BrowserContext( String _id, Browser _browser, Control _widgetWaitingIndicator, boolean _forceVisibleAfterLoad ) { super( _id, null ); browser = _browser; forceVisibleAfterLoad = _forceVisibleAfterLoad; widgetWaitIndicator = _widgetWaitingIndicator; // System.out.println( "Registered browser context: id=" + getID()); messageDispatcherSWT = new MessageDispatcherSWT(this); setMessageDispatcher( messageDispatcherSWT ); final TimerEventPerformer showBrowersPerformer = new TimerEventPerformer() { public void perform(TimerEvent event) { if (browser != null && !browser.isDisposed()) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (forceVisibleAfterLoad && browser != null && !browser.isDisposed() && !browser.isVisible()) { browser.setVisible(true); } } }); } } }; final TimerEventPerformer hideIndicatorPerformer = new TimerEventPerformer() { public void perform(TimerEvent event) { setPageLoading(false, browser.getUrl()); if (widgetWaitIndicator != null && !widgetWaitIndicator.isDisposed()) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (widgetWaitIndicator != null && !widgetWaitIndicator.isDisposed()) { widgetWaitIndicator.setVisible(false); } } }); } } }; final TimerEventPerformer checkURLEventPerformer = new TimerEventPerformer() { public void perform(TimerEvent event) { if (browser != null && !browser.isDisposed()) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { if (browser != null && !browser.isDisposed()) { browser.execute("try { " + "tuxLocString = document.location.toString();" + "if (tuxLocString.indexOf('res://') == 0) {" + " document.title = 'err: ' + tuxLocString;" + "} else {" + " tuxTitleString = document.title.toString();" + " if (tuxTitleString.indexOf('408 ') == 0 || tuxTitleString.indexOf('503 ') == 0 || tuxTitleString.indexOf('500 ') == 0) " + " { document.title = 'err: ' + tuxTitleString; } " + "}" + "} catch (e) { }"); } } }); } } }; if (forceVisibleAfterLoad) { browser.setVisible(false); } setPageLoading(false, browser.getUrl()); if (widgetWaitIndicator != null && !widgetWaitIndicator.isDisposed()) { widgetWaitIndicator.setVisible(false); } browser.addTitleListener(new TitleListener() { public void changed(TitleEvent event) { /* * The browser might have been disposed already by the time this method is called */ if (browser.isDisposed() || browser.getShell().isDisposed()) { return; } if (!browser.isVisible()) { SimpleTimer.addEvent("Show Browser", System.currentTimeMillis() + 700, showBrowersPerformer); } if (event.title.startsWith("err: ")) { fillWithRetry(event.title, "err in title"); } } }); browser.addProgressListener(new ProgressListener() { public void changed(ProgressEvent event) { //int pct = event.total == 0 ? 0 : 100 * event.current / event.total; //System.out.println(pct + "%/" + event.current + "/" + event.total); } public void completed(ProgressEvent event) { /* * The browser might have been disposed already by the time this method is called */ if (browser.isDisposed() || browser.getShell().isDisposed()) { return; } checkURLEventPerformer.perform(null); if (forceVisibleAfterLoad && !browser.isVisible()) { browser.setVisible(true); } browser.execute("try { if (azureusClientWelcome) { azureusClientWelcome('" + ConstantsVuze.AZID + "'," + "{ 'azv':'" + org.gudy.azureus2.core3.util.Constants.AZUREUS_VERSION + "', 'browser-id':'" + getID() + "' }" + ");} } catch (e) { }"); if (org.gudy.azureus2.core3.util.Constants.isCVSVersion() || System.getProperty("debug.https", null) != null) { if (browser.getUrl().indexOf("https") == 0) { browser.execute("try { o = document.getElementsByTagName('body'); if (o) o[0].style.borderTop = '2px dotted #3b3b3b'; } catch (e) {}"); } } if (wiggleBrowser ) { Shell shell = browser.getShell(); Point size = shell.getSize(); size.x -= 1; size.y -= 1; shell.setSize(size); size.x += 1; size.y += 1; shell.setSize(size); } } }); checkURLEvent = SimpleTimer.addPeriodicEvent("checkURL", 10000, checkURLEventPerformer); browser.addOpenWindowListener(new OpenWindowListener() { public void open(WindowEvent event) { if (browser.isDisposed() || browser.getShell().isDisposed()) { return; } event.required = true; if (browser.getUrl().contains("js.debug=1")) { Shell shell = ShellFactory.createMainShell(SWT.SHELL_TRIM); shell.setLayout(new FillLayout()); Browser subBrowser = new Browser(shell, Utils.getInitialBrowserStyle(SWT.NONE)); shell.open(); event.browser = subBrowser; } else { final Browser subBrowser = new Browser(browser, Utils.getInitialBrowserStyle(SWT.NONE)); subBrowser.addLocationListener(new LocationListener() { public void changed(LocationEvent arg0) { // TODO Auto-generated method stub } public void changing(LocationEvent event) { event.doit = false; if (!UrlFilter.getInstance().urlIsBlocked(event.location) && (event.location.startsWith("http://") || event.location.startsWith("https://"))) { debug("open sub browser: " + event.location); Program.launch(event.location); } else { debug("blocked open sub browser: " + event.location); } Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { subBrowser.dispose(); } }); } }); event.browser = subBrowser; } } }); browser.addLocationListener(new LocationListener() { private TimerEvent timerevent; public void changed(LocationEvent event) { if (browser.isDisposed() || browser.getShell().isDisposed()) { return; } debug("browser.changed " + event.location); if (timerevent != null) { timerevent.cancel(); } checkURLEventPerformer.perform(null); setPageLoading(false, event.top ? event.location : null); if (widgetWaitIndicator != null && !widgetWaitIndicator.isDisposed()) { widgetWaitIndicator.setVisible(false); } // event.top is only filled on changed event (not changing!) if (!event.top) { return; } String location = event.location.toLowerCase(); boolean isWebURL = location.startsWith("http://") || location.startsWith("https://"); if (!isWebURL) { if (event.location.startsWith("res://")) { fillWithRetry(event.location, "top changed"); return; } // we don't get a changed state on non URLs (mailto, javascript, etc) } if (UrlFilter.getInstance().isWhitelisted(event.location)) { lastValidURL = event.location; } //System.out.println("cd" + event.location); } public void changing(LocationEvent event) { debug("browser.changing " + event.location); /* * The browser might have been disposed already by the time this method is called */ if (browser.isDisposed() || browser.getShell().isDisposed()) { return; } String event_location = event.location; //Utils.openMessageBox(Utils.findAnyShell(), SWT.OK, "Location Changing", "Navigating to " + event_location ); if (event_location.startsWith("javascript") && event_location.indexOf("back()") > 0) { if (browser.isBackEnabled()) { browser.back(); } else if (lastValidURL != null) { fillWithRetry(event_location, "back"); } return; } String lowerLocation = event_location.toLowerCase(); boolean isOurURI = lowerLocation.startsWith("magnet:") || lowerLocation.startsWith("vuze:") || lowerLocation.startsWith("dht:"); if (isOurURI) { event.doit = false; TorrentOpener.openTorrent(event_location); return; } boolean isWebURL = lowerLocation.startsWith("http://") || lowerLocation.startsWith("https://"); if (!isWebURL) { // we don't get a changed state on non URLs (mailto, javascript, etc) return; } boolean blocked = UrlFilter.getInstance().urlIsBlocked(event_location); if (blocked) { event.doit = false; new MessageBoxShell(SWT.OK, "URL blocked", "Tried to open " + event_location + " but it's blocked").open(null); browser.back(); } else { if (UrlFilter.getInstance().isWhitelisted(event_location)) { lastValidURL = event_location; } setPageLoading(true, event.location); if(event.top) { if (widgetWaitIndicator != null && !widgetWaitIndicator.isDisposed()) { widgetWaitIndicator.setVisible(true); } // Backup in case changed(..) is never called timerevent = SimpleTimer.addEvent("Hide Indicator", System.currentTimeMillis() + 20000, hideIndicatorPerformer); } else { boolean isTorrent = false; boolean isVuzeFile = false; //Try to catch .torrent files if(event_location.endsWith(".torrent")) { isTorrent = true; } else { //If it's not obviously a web page boolean can_rpc = UrlFilter.getInstance().urlCanRPC(event_location); boolean test_for_torrent = !can_rpc && event_location.indexOf(".htm") == -1; boolean test_for_vuze = can_rpc && ( event_location.endsWith( ".xml" ) || event_location.endsWith( ".vuze" )); if ( test_for_torrent || test_for_vuze ){ try { //See what the content type is URL url = new URL(event_location); URLConnection conn = url.openConnection(); // we're only trying to get the content type so just use head ((HttpURLConnection)conn).setRequestMethod("HEAD"); String referer_str = null; try{ URL referer = new URL(((Browser)event.widget).getUrl()); if ( referer != null ){ referer_str = referer.toExternalForm(); } }catch( Throwable e ){ } UrlUtils.setBrowserHeaders( conn, referer_str ); UrlUtils.connectWithTimeouts( conn, 1500, 5000 ); String contentType = conn.getContentType(); if ( contentType != null ){ if ( test_for_torrent && contentType.indexOf("torrent") != -1 ) { isTorrent = true; } if ( test_for_vuze && contentType.indexOf("vuze") != -1 ) { isVuzeFile = true; } } String contentDisposition = conn.getHeaderField("Content-Disposition"); if (contentDisposition != null ){ if ( test_for_torrent && contentDisposition.indexOf(".torrent") != -1) { isTorrent = true; } if ( test_for_vuze && contentDisposition.indexOf(".vuze") != -1) { isVuzeFile = true; } } }catch( Throwable e){ } //System.out.println( "Test for t/v: " + event_location + " -> " + isTorrent + "/" + isVuzeFile ); } } if ( isTorrent ){ event.doit = false; try { String referer_str = null; try{ referer_str = new URL(((Browser)event.widget).getUrl()).toExternalForm(); }catch( Throwable e ){ } Map headers = UrlUtils.getBrowserHeaders( referer_str ); String cookies = (String) ((Browser)event.widget).getData("current-cookies"); if (cookies != null ){ headers.put("Cookie", cookies); } String url = event_location; if ( torrentURLHandler != null ){ try{ torrentURLHandler.handleTorrentURL(url); }catch( Throwable e ){ Debug.printStackTrace(e); } } PluginInitializer.getDefaultInterface().getDownloadManager().addDownload( new URL(url), headers ); }catch( Throwable e ){ e.printStackTrace(); } }else if ( isVuzeFile ){ event.doit = false; try { String referer_str = null; try{ referer_str = new URL(((Browser)event.widget).getUrl()).toExternalForm(); }catch( Throwable e ){ } Map headers = UrlUtils.getBrowserHeaders( referer_str ); String cookies = (String) ((Browser)event.widget).getData("current-cookies"); if ( cookies != null ){ headers.put("Cookie", cookies); } ResourceDownloader rd = StaticUtilities.getResourceDownloaderFactory().create( new URL( event_location )); VuzeFileHandler vfh = VuzeFileHandler.getSingleton(); VuzeFile vf = vfh.loadVuzeFile( rd.download()); if ( vf == null ){ event.doit = true; }else{ vfh.handleFiles( new VuzeFile[]{ vf }, 0 ); } }catch( Throwable e ){ e.printStackTrace(); } } } } } }); browser.setData(CONTEXT_KEY, this); browser.addDisposeListener(this); // enable right-click context menu only if system property is set final boolean enableMenu = System.getProperty(KEY_ENABLE_MENU, "0").equals( "1"); browser.addListener(SWT.MenuDetect, new Listener() { // @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) public void handleEvent(Event event) { event.doit = enableMenu; } }); messageDispatcherSWT.registerBrowser(browser); this.display = browser.getDisplay(); } /** * @param b * @param url * * @since 3.1.1.1 */ protected void setPageLoading(boolean b, String url) { // we may get multiple "load done"s (from each frame) which we don't // want to skip if (b && pageLoading) { return; } mon_listJS.enter(); try { pageLoading = b; if (pageLoading) { pageLoadingStart = SystemTime.getCurrentTime(); pageLoadTime = -1; } else if (pageLoadingStart > 0 && url != null) { pageLoadTime = SystemTime.getCurrentTime() - pageLoadingStart; executeInBrowser("clientSetLoadTime(" + pageLoadTime + ");"); pageLoadingStart = 0; } if (!pageLoading && listJS.size() > 0) { debug(listJS.size() + " javascripts queued. Executing now.."); for (String js : listJS) { executeInBrowser(js); } listJS.clear(); } } finally { mon_listJS.exit(); } Object[] listeners = loadingListeners.toArray(); for (int i = 0; i < listeners.length; i++) { loadingListener l = (loadingListener) listeners[i]; l.browserLoadingChanged(b, url); } } public void setTorrentURLHandler( torrentURLHandler handler) { torrentURLHandler = handler; } public void fillWithRetry(String s, String s2) { Color bg = browser.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); Color fg = browser.getDisplay().getSystemColor(SWT.COLOR_WIDGET_FOREGROUND); browser.setText("" + "
    Sorry, there was a problem loading this page.
    " + "Please check if your internet connection is working and click retry to continue." + "

    " + s + "

    " + s2 + "
    " + ""); } private void deregisterBrowser() { if (browser == null) { throw new IllegalStateException("Context " + getID() + " doesn't have a registered browser"); } // System.out.println( "Unregistered browser context: id=" + getID()); if (!browser.isDisposed()) { browser.setData(CONTEXT_KEY, null); browser.removeDisposeListener(this); messageDispatcherSWT.deregisterBrowser(browser); } browser = null; if (checkURLEvent != null && !checkURLEvent.isCancelled()) { checkURLEvent.cancel(); checkURLEvent = null; } } /** * Accesses the context associated with the given browser. * * @param browser holds the context in its application data map * @return the browser's context or null if there is none */ public static BrowserContext getContext(Browser browser) { Object data = browser.getData(CONTEXT_KEY); if (data != null && !(data instanceof BrowserContext)) { Debug.out("Data in Browser with key " + CONTEXT_KEY + " is not a BrowserContext"); return null; } return (BrowserContext) data; } public void addMessageListener(BrowserMessageListener listener) { messageDispatcherSWT.addListener(listener); } public Object getBrowserData(String key) { return browser.getData(key); } public void setBrowserData(String key, Object value) { browser.setData(key, value); } public boolean sendBrowserMessage(String key, String op) { return sendBrowserMessage(key, op, (Map) null); } public boolean sendBrowserMessage(String key, String op, Map params) { StringBuffer msg = new StringBuffer(); msg.append("az.msg.dispatch('").append(key).append("', '").append(op).append( "'"); if (params != null) { msg.append(", ").append(JSONUtils.encodeToJSON(params)); } msg.append(")"); return executeInBrowser(msg.toString()); } public boolean sendBrowserMessage(String key, String op, Collection params) { StringBuffer msg = new StringBuffer(); msg.append("az.msg.dispatch('").append(key).append("', '").append(op).append( "'"); if (params != null) { msg.append(", ").append(JSONUtils.encodeToJSON(params)); } msg.append(")"); return executeInBrowser(msg.toString()); } protected boolean maySend(String key, String op, Map params) { return !pageLoading; } public boolean executeInBrowser(final String javascript) { mon_listJS.enter(); try { if (!mayExecute(javascript)) { listJS.add(javascript); return false; } } finally { mon_listJS.exit(); } if (display == null || display.isDisposed()) { debug("CANNOT: browser.execute( " + getShortJavascript(javascript) + " )"); return false; } // swallow errors silently final String reallyExecute = "try { " + javascript + " } catch ( e ) { }"; Utils.execSWTThread(new AERunnable() { public void runSupport() { if (browser == null || browser.isDisposed()) { debug("CANNOT: browser.execute( " + getShortJavascript(javascript) + " )"); } else if (!browser.execute(reallyExecute)) { debug("FAILED: browser.execute( " + getShortJavascript(javascript) + " )"); } else { debug("SUCCESS: browser.execute( " + getShortJavascript(javascript) + " )"); } } }); return true; } protected boolean mayExecute(String javascript) { return !pageLoading; } public void widgetDisposed(DisposeEvent event) { if (event.widget == browser) { deregisterBrowser(); } } private String getShortJavascript(String javascript) { if (javascript.length() < (256 + 3 + 256)) { return javascript; } StringBuffer result = new StringBuffer(); result.append(javascript.substring(0, 256)); result.append("..."); result.append(javascript.substring(javascript.length() - 256)); return result.toString(); } public void setWiggleBrowser(boolean wiggleBrowser) { this.wiggleBrowser = wiggleBrowser; } public boolean isPageLoading() { return pageLoading; } public void addListener(loadingListener l) { if (loadingListeners == Collections.EMPTY_LIST) { loadingListeners = new ArrayList(1); } loadingListeners.add(l); } public static interface loadingListener { public void browserLoadingChanged(boolean loading, String url); } public long getContentNetworkID() { return contentNetworkID; } public void setContentNetworkID(long contentNetworkID) { this.contentNetworkID = contentNetworkID; } }azureus-4.3.0.6/com/aelitis/azureus/ui/UserPrompterResultListener.java0000644000175000017500000000017211267524620025405 0ustar adrianadrianpackage com.aelitis.azureus.ui; public interface UserPrompterResultListener { public void prompterClosed(int result); } azureus-4.3.0.6/com/aelitis/azureus/ui/skin/0000755000175000017500000000000011310377630020126 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_rcm.properties0000644000175000017500000000237711272502266024147 0ustar adrianadrianrcmview.type=container rcmview.onshow.skinviewclass=com.aelitis.azureus.ui.swt.content.SBC_RCMView rcmview.widgets=\ rcmview.toparea,\ rcmview.list rcmview.attach.template=template.fill rcmview.toparea.type=container rcmview.toparea.widgets=\ rcmview.title,\ rcmview.filterarea,\ rcmview.sizeslider rcmview.toparea.attach.template=template.fill rcmview.toparea.attach.bottom= rcmview.toparea.height=30 rcmview.title.type=text,{rcm.view.heading} rcmview.title.view=title rcmview.title.attach.template=template.fill rcmview.title.attach.right= rcmview.title.attach.left=0,5 rcmview.title.v-align=center rcmview.title.text.size=15px rcmview.title.text.style=bold rcmview.filterarea.type=container rcmview.filterarea.view=filterarea rcmview.filterarea.attach.template=template.fill rcmview.filterarea.attach.left=rcmview.title,10 rcmview.filterarea.attach.right=rcmview.sizeslider,-5 rcmview.filterarea.height=30 rcmview.sizeslider.type=container rcmview.sizeslider.view=table-size-slider rcmview.sizeslider.attach.right=100,-5 rcmview.sizeslider.attach.top=0,0 rcmview.sizeslider.attach.bottom=100,0 rcmview.sizeslider.width=75 rcmview.list.type=container rcmview.list.attach.template=template.fill rcmview.list.attach.top=rcmview.toparea,0 rcmview.list.view=rcm-list ##azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_dlg_devicetemplatechooser.properties0000644000175000017500000000322711227776600030572 0ustar adrianadriantemplate.imagedir=com/aelitis/azureus/ui/images border.left=10 border.left2=20 shell.type=container shell.width=400 shell.height=300 shell.color=COLOR_LIST_BACKGROUND shell.fgcolor=COLOR_LIST_FOREGROUND shell.title=Device Playback Selection shell.widgets=shell.top,\ shell.subtitle,\ shell.list, shell.top.type=container shell.top.attach.left=0,0 shell.top.attach.right=100,0 shell.top.attach.top=0,0 shell.top.color=#ffffff shell.top.color.style=gradient,#c9d8df shell.top.widgets=shell.top.title,\ shell.top.beta,\ shell.top.line shell.top.title.type=text shell.top.title.view=title shell.top.title.text.color=#000000 shell.top.title.attach.left=0,{border.left} shell.top.title.attach.top=0,5 shell.top.title.height=16 shell.top.title.text.size=15px shell.top.title.text.style=bold shell.top.beta.type=image,{template.imagedir}/sb/beta.png shell.top.beta.attach.top=shell.top.title,0,top shell.top.beta.attach.left=shell.top.title,5,right shell.top.line.type=container shell.top.line.height=1 shell.top.line.color=COLOR_WIDGET_BORDER shell.top.line.attach.top=shell.top.title,5 shell.top.line.attach.left=0,0 shell.top.line.attach.right=100,0 shell.top.line.attach.bottom=100,0 shell.subtitle.type=text shell.subtitle.view=subtitle shell.subtitle.text.size=+2 shell.subtitle.text.style=bold shell.subtitle.attach.left=0,{border.left2} shell.subtitle.attach.right=100,-{border.left2} shell.subtitle.attach.top=shell.top,4 shell.list.type=container shell.list.view=list shell.list.attach.left=0,{border.left2} shell.list.attach.right=100,-{border.left2} shell.list.attach.top=shell.subtitle,2 azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_sidebar.properties0000644000175000017500000000367511266266270025006 0ustar adrianadrian main.area.body.type=container main.area.body.attach.top=main.area.maintabs,0 main.area.body.attach.bottom=100,0 main.area.body.attach.left=0,0 main.area.body.attach.right=100,0 main.area.body.widgets=main.sidebar.list,main.sidebar.content,main.sidebar.sash main.area.body.view=sidebar main.sidebar.sash.type=v-mysash,main.sidebar.list,main.sidebar.content main.sidebar.sash.noresize=true main.sidebar.sash.border=thin-top,COLOR_WIDGET_NORMAL_SHADOW #main.sidebar.sash.color=#ff0000 main.sidebar.sash.view=sidebar-sash main.sidebar.sash.startpos={sidebar.defaultwidth} main.sidebar.sash.width=3 main.sidebar.sash.attach.left=main.sidebar.list,0 main.sidebar.sash.attach.right= main.sidebar.sash.attach.top=0,0 main.sidebar.sash.attach.bottom=100,0 main.sidebar.sash.above.minwidth=125 main.sidebar.list.type=container main.sidebar.list.doublebuffer=1 main.sidebar.list.attach.top=0,0 main.sidebar.list.attach.bottom=100,0 main.sidebar.list.attach.left=0,0 main.sidebar.list.attach.right= main.sidebar.list.widgets=main.sidebar #main.sidebar.list.minwidth=125 main.sidebar.type=container main.sidebar.attach.top=0,0 main.sidebar.attach.bottom=100,0 main.sidebar.attach.left=0,0 main.sidebar.attach.right=100,0 main.sidebar.widgets=sidebar.middle sidebar.middle.type=container sidebar.middle.view=sidebar-list sidebar.middle.attach.top=0,0 sidebar.middle.attach.bottom=100,0 sidebar.middle.attach.right=100,0 sidebar.middle.attach.left=0,0 #sidebar.middle.color=COLOR_LIST_BACKGROUND #sidebar.middle.fgcolor=COLOR_LIST_FOREGROUND main.sidebar.content.type=container main.sidebar.content.view=sidebar-contents main.sidebar.content.attach.top=0,0 main.sidebar.content.attach.bottom=100,0 main.sidebar.content.attach.left=main.sidebar.sash main.sidebar.content.attach.right=100,0 main.area.welcome.type=browser main.area.welcome.view=welcome main.area.welcome.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.WelcomeView main.area.welcome.attach.template=template.fill azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_dlg_deviceadd_mfchooser.properties0000644000175000017500000000304111227274726030165 0ustar adrianadriantemplate.imagedir=com/aelitis/azureus/ui/images border.left=10 border.left2=20 shell.type=container shell.width=350 shell.height=280 shell.color=COLOR_LIST_BACKGROUND shell.fgcolor=COLOR_LIST_FOREGROUND shell.title={v3.devices.add.title} shell.widgets=shell.top,\ shell.subtitle,\ shell.list shell.top.type=container shell.top.attach.left=0,0 shell.top.attach.right=100,0 shell.top.attach.top=0,0 shell.top.color=#ffffff shell.top.color.style=gradient,#c9d8df shell.top.widgets=shell.top.title,\ shell.top.line shell.top.title.type=text,{v3.devices.choose.manufacturer.title} shell.top.title.view=title shell.top.title.text.color=#000000 shell.top.title.attach.left=0,{border.left} shell.top.title.attach.top=0,5 shell.top.title.height=16 shell.top.title.text.size=15px shell.top.title.text.style=bold shell.top.line.type=container shell.top.line.height=1 shell.top.line.color=COLOR_WIDGET_BORDER shell.top.line.attach.top=shell.top.title,5 shell.top.line.attach.left=0,0 shell.top.line.attach.right=100,0 shell.top.line.attach.bottom=100,0 shell.subtitle.type=text,{v3.devices.choose.manufacturer.subtitle} shell.subtitle.view=subtitle shell.subtitle.text.size=+2 shell.subtitle.text.style=bold shell.subtitle.attach.left=0,{border.left2} shell.subtitle.attach.right=100,-{border.left2} shell.subtitle.attach.top=shell.top,4 shell.list.type=container shell.list.view=list shell.list.attach.left=0,{border.left2} shell.list.attach.right=100,-{border.left2} shell.list.attach.top=shell.subtitle,2 azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_transcodechooser.properties0000644000175000017500000001004211223316432026711 0ustar adrianadriantemplate.imagedir=com/aelitis/azureus/ui/images border.left=10 border.left2=20 shell.type=container shell.width=400 shell.height=300 shell.color=COLOR_LIST_BACKGROUND shell.fgcolor=COLOR_LIST_FOREGROUND shell.title=Device Playback Selection shell.widgets=shell.top,\ shell.subtitle,\ shell.list,\ shell.info,\ shell.bottom,\ shell.buttonbottom shell.top.type=container shell.top.attach.left=0,0 shell.top.attach.right=100,0 shell.top.attach.top=0,0 shell.top.color=#ffffff shell.top.color.style=gradient,#c9d8df shell.top.widgets=shell.top.title,\ shell.top.beta,\ shell.top.line shell.top.title.type=text shell.top.title.view=title shell.top.title.text.color=#000000 shell.top.title.attach.left=0,{border.left} shell.top.title.attach.top=0,5 shell.top.title.height=16 shell.top.title.text.size=15px shell.top.title.text.style=bold shell.top.beta.type=image,{template.imagedir}/sb/beta.png shell.top.beta.attach.top=shell.top.title,0,top shell.top.beta.attach.left=shell.top.title,5,right shell.top.line.type=container shell.top.line.height=1 shell.top.line.color=COLOR_WIDGET_BORDER shell.top.line.attach.top=shell.top.title,5 shell.top.line.attach.left=0,0 shell.top.line.attach.right=100,0 shell.top.line.attach.bottom=100,0 shell.subtitle.type=text shell.subtitle.view=subtitle shell.subtitle.text.size=+2 shell.subtitle.text.style=bold shell.subtitle.attach.left=0,{border.left2} shell.subtitle.attach.right=100,-{border.left2} shell.subtitle.attach.top=shell.top,4 shell.list.type=container shell.list.view=list shell.list.attach.left=0,{border.left2} shell.list.attach.right=100,-{border.left2} shell.list.attach.top=shell.subtitle,2 shell.info.type=container shell.info.attach.left=0,{border.left2} shell.info.attach.right=100,-{border.left2} shell.info.attach.top=shell.list,10 shell.info.attach.bottom=shell.bottom,-10 shell.info.border=1 shell.info.color=#F8F8F8 shell.info.fgcolor=#000000 shell.info.widgets=shell.info.title,shell.info.text #shell.info.height=80 shell.info.title.type=text,{devices.choose.device.info.title} shell.info.title.view=info-title shell.info.title.text.style=bold shell.info.title.attach.left=0,10 shell.info.title.attach.right=100,-10 shell.info.title.attach.top=0,10 shell.info.text.type=text shell.info.text.text={devices.choose.device.info.text} shell.info.text.view=info-text shell.info.text.attach.left=0,10 shell.info.text.attach.right=100,-10 shell.info.text.attach.top=shell.info.title,5 shell.info.text.attach.bottom=100,-10 shell.bottom.type=container shell.bottom.color=COLOR_WIDGET_BACKGROUND shell.bottom.fgcolor=COLOR_WIDGET_FOREGROUND shell.bottom.view=bottom shell.bottom.attach.bottom=shell.buttonbottom,0 shell.bottom.attach.right=100,0 shell.bottom.attach.left=0,0 shell.bottom.widgets=shell.bottom.line,shell.bottom.area shell.bottom.visible=0 shell.bottom.line.type=container shell.bottom.line.height=1 shell.bottom.line.color=COLOR_WIDGET_BORDER shell.bottom.line.attach.top=0,0 shell.bottom.line.attach.left=0,0 shell.bottom.line.attach.right=100,0 shell.bottom.area.type=container shell.bottom.area.view=bottom-area shell.bottom.area.attach.bottom=100,-5 shell.bottom.area.attach.left=0,10 shell.bottom.area.attach.right=100,-10 shell.buttonbottom.type=container shell.buttonbottom.color=COLOR_WIDGET_BACKGROUND shell.buttonbottom.fgcolor=COLOR_WIDGET_FOREGROUND shell.buttonbottom.view=button-bottom shell.buttonbottom.attach.bottom=100,0 shell.buttonbottom.attach.right=100,0 shell.buttonbottom.attach.left=0,0 shell.buttonbottom.widgets=button.ok,button.cancel,shell.bottom.line button.ok.type=button button.ok.text={Button.ok} button.ok.view=ok button.ok.attach.right=button.cancel,-10 button.ok.attach.bottom=100,-5 button.ok.attach.top=0,5 button.ok.minwidth=70 button.cancel.type=button button.cancel.view=cancel button.cancel.text={Button.cancel} button.cancel.attach.right=100,-10 button.cancel.attach.bottom=100,-5 button.cancel.attach.top=0,5 button.cancel.minwidth=70 azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_topbar.properties0000644000175000017500000000476011164370260024650 0ustar adrianadrian#=============================================================================== #main.area.topbar #=============================================================================== main.area.topbar.widgets=widget.area.line main.area.topbar.type=container main.area.topbar.view=pluginbar main.area.topbar.attach.left=0,0 main.area.topbar.attach.right=100,0 main.area.topbar.visible=0 main.area.topbar.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.TopBarView #================== # Unattached Views. Anyone requesting a skinobject with skin view id of [1] # will cause [2] to be created in [3] # UnattachedView.[1]=[2],[3] #================== UnattachedView.topbar-area-plugin=widget.area.plugins,main.area.topbar widget.area.line.type=container widget.area.line.attach.template=template.fill widget.area.line.attach.top= widget.area.line.height=1 widget.area.line.color=COLOR_WIDGET_NORMAL_SHADOW ############ widget.area.plugins.type=container widget.area.plugins.view=topbar-area-plugin widget.area.plugins.widgets=widget.area.plugins.split,\ widget.plugins,\ widget.plugins.list widget.area.plugins.attach.left=0,10 #widget.area.plugins.attach.right=widget.area.search,-15 widget.area.plugins.attach.right=100,-10 widget.area.plugins.attach.top=0,5 widget.area.plugins.attach.bottom=100,-5 # hack because SWT has some min height. widget will still fill in appropriately widget.area.plugins.height=10 widget.area.plugins.split.type=v-mysash,widget.plugins.list,widget.plugins widget.area.plugins.split.width={template.padding} widget.area.plugins.split.background={template.imagedir}/dot.png widget.area.plugins.split.background.drawmode=center-y widget.area.plugins.split.attach.left=widget.plugins.list,0 widget.area.plugins.split.attach.right= widget.area.plugins.split.attach.top=0,0 widget.area.plugins.split.attach.bottom=100,0 widget.area.plugins.split.startpos=100 widget.plugins.type=container widget.plugins.view=topbar-plugins widget.plugins.attach.right=100,0 widget.plugins.attach.left=widget.area.plugins.split,0 widget.plugins.attach.top=0,0 widget.plugins.attach.bottom=100,0 # hack because SWT has some min height. widget will still fill in appropriately widget.plugins.height=10 widget.plugins.list.type=container widget.plugins.list.view=topbar-plugin-list widget.plugins.list.attach.right= widget.plugins.list.attach.left=0,0 widget.plugins.list.attach.top=0,0 widget.plugins.list.attach.bottom=100,0 #widget.plugins.list.fgcolor={color.text.fg} azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3.properties0000644000175000017500000000136411266266270023306 0ustar adrianadrian#TODO: A lot of widgets can be switched to clone skin.include=skin3_topbar,\ skin3_maintabs,\ skin3_sidebar,\ skin3_activities,\ skin3_tab_browse,\ skin3_tab_searchresults,\ skin3_constants,\ skin3_sbc_library,\ skin3_devices,\ skin3_devices_od,\ skin3_rcm main.shell.widgets=main.shell.area main.shell.area.type=container main.shell.area.visible=0 main.shell.area.view=main main.shell.area.attach.template=template.fill main.shell.area.widgets=main.area.topbar,\ main.area.middle,\ maintabs.statusbarline,\ main.area.statusbar #main.shell.color={color.mainshell} azureus-4.3.0.6/com/aelitis/azureus/ui/skin/SkinConstants.java0000644000175000017500000000444311266266270023606 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.skin; /** * @author TuxPaper * @created Mar 4, 2007 * */ public class SkinConstants { public static final String TABSET_DASHBOARD_LEFT = "hometab-left"; public static final String VIEWID_BROWSER_BROWSE = "browse"; public static final String VIEWID_BROWSER_SEARCHRESULTS = "searchresults"; public static final String VIEWID_PLUGINBAR = "pluginbar"; public static final String VIEWID_TAB_BAR = "tabbar"; public static final String VIEWID_LIBRARY = "library-area"; public static final String VIEWID_TOOLBAR = "global-toolbar"; public static final String VIEWID_SIDEBAR_LIBRARY = "sidebar-library-area"; public static final String VIEWID_SIDEBAR_LIBRARY_BIG = "library-big-area"; public static final String VIEWID_SIDEBAR_LIBRARY_SMALL = "library-small-area"; public static final String VIEWID_SIDEBAR_LIBRARY_OLD = "library-oldtable-area"; public static final String VIEWID_SIDEBAR_ACTIVITY_PARENT = "sidebar-activity-area"; public static final String VIEWID_SIDEBAR_ACTIVITY_BIG = "activity-big-area"; public static final String VIEWID_SIDEBAR_ACTIVITY_SMALL = "activity-small-area"; public static final String VIEWID_SIDEBAR = "sidebar"; public static final String VIEWID_LIBRARY_TOOLBAR = "library-list-button-smalltable"; public static final String VIEWID_LIBRARY_TOOLBAR_BIG = "library-list-button-bigtable"; public static final String VIEWID_BROWSER_WELCOME = "welcome"; } azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_activities.properties0000644000175000017500000000152511267767470025542 0ustar adrianadrianactivity.type=container activity.view=sidebar-activity-area activity.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.SBC_ActivityView activity.widgets=activity.top,activity.list activity.attach.template=template.fill ## Top (tools) activity.top.type=container activity.top.view=activity-list-tools activity.top.attach.top=0,0 activity.top.attach.left=0,0 activity.top.attach.right=100,0 ## List activity.list.type=container activity.list.view=activity-list-area activity.list.attach.top=activity.top,0 activity.list.attach.left=0,0 activity.list.attach.right=100,0 activity.list.attach.bottom=100,0 activity.table.small.type=container activity.table.small.view=activity-small-area activity.table.small.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.SBC_ActivityTableView activity.table.small.attach.template=template.fill azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_tab_searchresults.properties0000644000175000017500000000323011276447730027100 0ustar adrianadrian#=============================================================================== #main.area.searchresultstab #(The browse tab) #=============================================================================== main.area.searchresultstab.type=container main.area.searchresultstab.view=searchresults-area main.area.searchresultstab.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.SearchResultsTabArea main.area.searchresultstab.attach.template=template.tabcontentarea main.area.searchresultstab.widgets=searchresults.area.search-results,searchresults.area.content,searchresultsr.area.wait searchresults.area.content.type=browser searchresults.area.content.view=searchresults searchresults.area.content.indicator=maintabs.waitindicator searchresults.area.content.attach.left=0,0 searchresults.area.content.attach.right=100,0 searchresults.area.content.attach.top=0,0 searchresults.area.content.attach.bottom=searchresults.area.search-results searchresultsr.area.wait.type=text searchresultsr.area.wait.text.color={color.text.fg} searchresultsr.area.wait.text.size=12 searchresultsr.area.wait.attach.template=template.fill searchresultsr.area.wait.v-align=center searchresultsr.area.wait.align=center searchresults.area.search-results.type=browser searchresults.area.search-results.browser.nolisteners=1 searchresults.area.search-results.view=searchresults-search-results searchresults.area.search-results.attach.bottom=100,0 searchresults.area.search-results.attach.top= searchresults.area.search-results.attach.left=0,0 searchresults.area.search-results.attach.right=100,0 searchresults.area.search-results.height=0 searchresults.area.search-results.forceVisibleAfterLoad=falseazureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_close_notification.properties0000644000175000017500000001011211223307650027217 0ustar adrianadrian template.imagedir=com/aelitis/azureus/ui/images color.links.normal=#3030d0 #156dff color.links.hover=#000080 icon.notification={template.imagedir}/notification_icon.png icon.preview={template.imagedir}/network_closed_preview.png border.left=10 border.left2=15 close-notification.body.type=container close-notification.body.width=400 close-notification.body.height=260 close-notification.body.widgets=close-notification.top,\ close-notification.text1,\ close-notification.line1,\ close-notification.text2,\ close-notification.preview,\ close-notification.close-button,\ close-notification.noshowagain close-notification.top.type=container close-notification.top.attach.left=0,0 close-notification.top.attach.right=100,0 close-notification.top.attach.top=0,0 close-notification.top.color=#fcfdfd close-notification.top.color.style=gradient,#e0e3e5 close-notification.top.height=43 close-notification.top.widgets=close-notification.top.image,\ close-notification.top.title,\ close-notification.top.line close-notification.top.image.type=image,{icon.notification} close-notification.top.image.attach.left=0,{border.left} close-notification.top.image.attach.top=10,5 close-notification.top.title.type=text close-notification.top.title.text={v3.dialog.cnclose.subtitle} close-notification.top.title.text.color=#000000 close-notification.top.title.attach.left=close-notification.top.image,15 close-notification.top.title.attach.bottom=close-notification.top.image,bottom,0 close-notification.top.title.attach.right=100,-10 close-notification.top.title.text.size=30px close-notification.top.title.text.style=bold close-notification.top.line.type=container close-notification.top.line.height=1 close-notification.top.line.color=COLOR_WIDGET_BORDER close-notification.top.line.attach.top=close-notification.top.image,5 close-notification.top.line.attach.left=0,0 close-notification.top.line.attach.right=100,0 close-notification.top.line.attach.bottom=100,0 close-notification.text1.type=text,{v3.dialog.cnclose.info1} close-notification.text1.attach.top=close-notification.top,5 close-notification.text1.attach.left=0,{border.left} close-notification.text1.attach.right=100,-10 close-notification.line1.type=container close-notification.line1.height=1 close-notification.line1.color=COLOR_WIDGET_NORMAL_SHADOW close-notification.line1.attach.top=close-notification.text1,5 close-notification.line1.attach.left=0,0 close-notification.line1.attach.right=100,0 close-notification.text2.type=text close-notification.text2.text={v3.dialog.cnclose.info2} close-notification.text2.attach.top=close-notification.line1,10 close-notification.text2.attach.left=0,{border.left2} close-notification.text2.attach.right=close-notification.preview,-10 close-notification.text2.attach.bottom=close-notification.close-button,-10 close-notification.preview.type=image,{icon.preview} close-notification.preview.attach.top=close-notification.line1,10 close-notification.preview.attach.left= close-notification.preview.attach.right=100,-{border.left2} close-notification.close-button.type=button close-notification.close-button.text={Button.close} close-notification.close-button.view=close close-notification.close-button.attach.top= #close-notification.close-button.attach.left=0,{border.left2} close-notification.close-button.attach.right=100,-{border.left2} close-notification.close-button.attach.bottom=100,-10 close-notification.noshowagain.type=checkbox close-notification.noshowagain.view=noshowagain close-notification.noshowagain.text={v3.dialog.cnclose.noshow} close-notification.noshowagain.v-align=center #close-notification.noshowagain.attach.right=100,-{border.left2} close-notification.noshowagain.attach.left=0,{border.left2} close-notification.noshowagain.attach.top=close-notification.close-button,top,0 close-notification.noshowagain.attach.bottom=100,-10 azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_devices.properties0000644000175000017500000001404511160651174025002 0ustar adrianadriandevicesview.type=container devicesview.onshow.skinviewclass=com.aelitis.azureus.ui.swt.devices.SBC_DevicesView devicesview.widgets=\ devicesview.title,\ devicesview.list,\ devicesview.advinfo.title,\ advinfo.area devicesview.attach.template=template.fill devicesview.title.type=text,{devices.view.heading} devicesview.title.text.v-padding=10 devicesview.title.text.h-padding=5 devicesview.title.view=title devicesview.title.attach.template=template.fill devicesview.title.attach.bottom= devicesview.title.attach.right= devicesview.title.text.size=15px devicesview.title.text.style=bold devicesview.list.type=container devicesview.list.attach.template=template.fill devicesview.list.attach.top=devicesview.title,0 devicesview.list.attach.bottom=devicesview.advinfo.title,0 devicesview.list.view=transcode-queue devicesview.advinfo.title.type=container devicesview.advinfo.title.widgets=advinfo.title,advinfo.button devicesview.advinfo.title.attach.bottom=advinfo.area devicesview.advinfo.title.attach.left=0,0 devicesview.advinfo.title.attach.right=100,0 devicesview.advinfo.title.attach.top= #devicesview.advinfo.title.view=advinfo devicesview.advinfo.title.visible=0 ## Devices info bar devicesview.infobar.type=container devicesview.infobar.height=75 devicesview.infobar.color=#F1F9F8 devicesview.infobar.widgets=\ infobar.image1,\ infobar.line1,\ infobar.line2,\ infobar.link,\ infobar.feedback,\ infobar.close devicesview.infobar.attach.template=template.fill infobar.image1.type=image infobar.image1.image={template.imagedir}/device.png infobar.image1.attach.left=0,15 infobar.image1.attach.top=0,15 infobar.line1.type=text,{v3.deviceview.infobar.line1} #infobar.line1.text.size=22px infobar.line1.text.size=19px infobar.line1.view=line1 infobar.line1.text.style._windows=bold infobar.line1.text.color=#707070 infobar.line1.attach.left=infobar.image1,10 infobar.line1.attach.top=0,15 infobar.line1.attach.right=infobar.close,-5 infobar.line2.type=text,{v3.deviceview.infobar.line2} infobar.line2.view=line2 infobar.line2.text.color=#808080 infobar.line2.text.size=15px infobar.line2.attach.left=infobar.image1,10 infobar.line2.attach.top=infobar.line1,4 infobar.link.type=text,{label.learnmore} infobar.link.text.urlcolor={color.links.normal} infobar.link.text.size=15px infobar.link.attach.left=infobar.line2,10 infobar.link.attach.bottom=infobar.line2,0,bottom infobar.feedback.type=text,Send Devices Feedback infobar.feedback.text.urlcolor={color.links.normal} infobar.feedback.attach.right=100,-10 infobar.feedback.attach.bottom=infobar.line2,-1,bottom infobar.close.type=image,{template.imagedir}/dismissX.gif infobar.close.view=close infobar.close.cursor=hand infobar.close.attach.right=100,-10 infobar.close.attach.top=0,7 ## iTunes info bar itunes.infobar.type=container itunes.infobar.height=75 itunes.infobar.color=#F1F9F8 itunes.infobar.widgets=\ itunes.image1,\ itunes.line1,\ itunes.line2,\ itunes.link,\ itunes.feedback,\ itunes.close itunes.infobar.attach.template=template.fill itunes.image1.type=image,{template.imagedir}/device.png itunes.image1.attach.left=0,15 itunes.image1.attach.top=0,15 itunes.line1.type=text itunes.line1.view=line1 #itunes.line1.text.size=22px itunes.line1.text.size=19px itunes.line1.text.style._windows=bold itunes.line1.text.color=#707070 itunes.line1.attach.left=itunes.image1,10 itunes.line1.attach.top=0,15 itunes.line1.attach.right=itunes.close,-5 itunes.line2.type=text itunes.line2.view=line2 itunes.line2.text.color=#808080 itunes.line2.text.size=15px itunes.line2.attach.left=itunes.image1,10 itunes.line2.attach.top=itunes.line1,4 itunes.link.type=text,{label.learnmore} itunes.link.text.urlcolor={color.links.normal} itunes.link.text.size=15px itunes.link.attach.left=itunes.line2,10 itunes.link.attach.bottom=itunes.line2,0,bottom itunes.feedback.type=text,Send Devices Feedback itunes.feedback.text.urlcolor={color.links.normal} itunes.feedback.attach.right=100,-10 itunes.feedback.attach.bottom=itunes.line2,-1,bottom itunes.close.type=image,{template.imagedir}/dismissX.gif itunes.close.view=close itunes.close.cursor=hand itunes.close.attach.right=100,-10 itunes.close.attach.top=0,7 ## devicerendererview.type=container devicerendererview.onshow.skinviewclass=com.aelitis.azureus.ui.swt.devices.SBC_DevicesView devicerendererview.widgets=\ devicerendererview.title,\ devicerendererview.list,\ devicerendererview.advinfo.title,\ advinfo.area devicerendererview.attach.template=template.fill devicerendererview.title.type=text devicerendererview.title.text.v-padding=10 devicerendererview.title.text.h-padding=5 devicerendererview.title.view=title devicerendererview.title.attach.template=template.fill devicerendererview.title.attach.bottom= devicerendererview.title.text.size=15px devicerendererview.title.text.style=bold devicerendererview.list.type=container devicerendererview.list.attach.template=template.fill devicerendererview.list.attach.top=devicerendererview.title,0 devicerendererview.list.attach.bottom=devicerendererview.advinfo.title,0 devicerendererview.list.view=transcode-queue devicerendererview.advinfo.title.type=container devicerendererview.advinfo.title.widgets=advinfo.title,advinfo.button devicerendererview.advinfo.title.attach.bottom=advinfo.area devicerendererview.advinfo.title.attach.left=0,0 devicerendererview.advinfo.title.attach.right=100,0 devicerendererview.advinfo.title.attach.top= #devicerendererview.advinfo.title.view=advinfo devicerendererview.advinfo.title.visible=0 advinfo.title.type=text advinfo.title.text.v-padding=5 advinfo.title.attach.left=advinfo.button,10 advinfo.title.view=advinfo-title advinfo.button.type=image advinfo.button.view=advinfo-button advinfo.area.type=container advinfo.area.onshow.skinviewclass=com.aelitis.azureus.ui.swt.devices.DeviceInfoArea advinfo.area.view=advinfo-area advinfo.area.attach.template=template.fill advinfo.area.attach.top= advinfo.area.visible=0 ##azureus-4.3.0.6/com/aelitis/azureus/ui/skin/SkinPropertiesImpl.java0000644000175000017500000002144611267204372024606 0ustar adrianadrian/* * Created on May 29, 2006 4:23:01 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.skin; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.gudy.azureus2.core3.internat.IntegratedResourceBundle; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; /** * Implementation of SkinProperties using a IntegratedResourceBundle loaded from * hard coded paths. *

    * Three level lookup of keys: *

  • (plugin) skin property file *
  • defaults property file *
  • Azureus MessageText class *
    * Additionally, checks each for platform specific keys. *


    * Values containing "{*}" are replaced with a lookup of * * * @author TuxPaper * @created May 29, 2006 * */ public class SkinPropertiesImpl implements SkinProperties { private static final LogIDs LOGID = LogIDs.UI3; private static final String PATH_SKIN_DEFS = "com/aelitis/azureus/ui/skin/"; private static final String FILE_SKIN_DEFS = "skin3.properties"; private static final Pattern PAT_PARAM_ALPHA = Pattern.compile("\\{([^0-9].+?)\\}"); private static final Pattern PAT_PARAM_NUM = Pattern.compile("\\{([0-9]+?)\\}"); private IntegratedResourceBundle rb; private final ClassLoader classLoader; public SkinPropertiesImpl() { this(SkinPropertiesImpl.class.getClassLoader(), PATH_SKIN_DEFS, FILE_SKIN_DEFS); } public SkinPropertiesImpl(ClassLoader classLoader, String skinPath, String mainSkinFile) { this.classLoader = classLoader; skinPath = skinPath.replaceAll("/", "."); if (!skinPath.endsWith(".")) { skinPath += "."; } if (mainSkinFile.endsWith(".properties")) { mainSkinFile = mainSkinFile.substring(0, mainSkinFile.length() - 11); } ResourceBundle bundle = ResourceBundle.getBundle(skinPath + mainSkinFile, Locale.getDefault(), classLoader); rb = new IntegratedResourceBundle(bundle, Collections.EMPTY_MAP, 1200); rb.setUseNullList(true); String sFiles = rb.getString("skin.include", null); if (sFiles != null) { String[] sFilesArray = sFiles.split(","); for (int i = 0; i < sFilesArray.length; i++) { String sFile = (sFilesArray[i].startsWith("/") ? sFilesArray[i].substring(1) : skinPath + sFilesArray[i]); sFile = sFile.replaceAll("/", "."); try { ResourceBundle subBundle = ResourceBundle.getBundle(sFile, Locale.getDefault(), classLoader); rb.addResourceMessages(subBundle); } catch (Throwable t) { Debug.out("Err loading skin include: " + sFile, t); } } } } public void addResourceBundle(ResourceBundle subBundle) { try { rb.addResourceMessages(subBundle); } catch (Throwable t) { Debug.out("Err loading skin include: " + subBundle, t); } } // public Properties getProperties() { // return properties; // } public void addProperty(String name, String value) { rb.addString(name, value); } public boolean hasKey(String name) { if (name == null) { return false; } String osName = null; if (Constants.isWindows) { osName = name + "._windows"; } else if (Constants.isOSX) { osName = name + "._mac"; } else if (Constants.isUnix) { osName = name + "._unix"; } else if (Constants.isFreeBSD) { osName = name + "._freebsd"; } else if (Constants.isLinux) { osName = name + "._linux"; } else if (Constants.isSolaris) { osName = name + "._solaris"; } boolean contains = false; if (osName != null) { // can't use containsKey on IntegratedResourceBundle :( contains = rb.getString(osName, null) != null; } if (!contains) { contains = rb.getString(name, null) != null; } return contains; } public String getReferenceID(String name) { String value = getValue(name, null, false); if (value == null || value.length() < 2) { return null; } if (value.charAt(0) == '{' && value.charAt(value.length() - 1) == '}') { return value.substring(1, value.length() - 1); } return null; } private String getValue(String name, String[] params) { return getValue(name, params, true); } private String getValue(String name, String[] params, boolean expandReferences) { String value = null; String osName = null; if (name == null) { return null; } if (Constants.isWindows) { osName = name + "._windows"; } else if (Constants.isOSX) { osName = name + "._mac"; } else if (Constants.isUnix) { osName = name + "._unix"; } else if (Constants.isFreeBSD) { osName = name + "._freebsd"; } else if (Constants.isLinux) { osName = name + "._linux"; } else if (Constants.isSolaris) { osName = name + "._solaris"; } if (osName != null) { value = rb.getString(osName, null); } if (value == null) { value = rb.getString(name, null); } if (expandReferences && value != null && value.indexOf('}') > 0) { Matcher matcher; if (params != null) { matcher = PAT_PARAM_NUM.matcher(value); while (matcher.find()) { String key = matcher.group(1); try { int i = Integer.parseInt(key); if (i < params.length) { value = value.replaceAll("\\Q{" + key + "}\\E", params[i]); } else { value = value.replaceAll("\\Q{" + key + "}\\E", ""); } } catch (Exception e) { } } } matcher = PAT_PARAM_ALPHA.matcher(value); while (matcher.find()) { String key = matcher.group(1); String text = getValue(key, params); if (text == null) { text = MessageText.getString(key); } value = value.replaceAll("\\Q{" + key + "}\\E", text); } } return value; } public int getIntValue(String name, int def) { String value = getValue(name, null); if (value == null) { return def; } int result = def; try { result = Integer.parseInt(value); } catch (NumberFormatException e) { // ignore error.. it might be valid to store a non-numeric.. //e.printStackTrace(); } return result; } public int[] getColorValue(String name) { int[] colors = new int[3]; String value = getValue(name, null); if (value == null || value.length() == 0 || value.startsWith("COLOR_")) { colors[0] = colors[1] = colors[2] = -1; return colors; } try { if (value.charAt(0) == '#') { // hex color string long l = Long.parseLong(value.substring(1), 16); colors[0] = (int) ((l >> 16) & 255); colors[1] = (int) ((l >> 8) & 255); colors[2] = (int) (l & 255); } else { StringTokenizer st = new StringTokenizer(value, ","); colors[0] = Integer.parseInt(st.nextToken()); colors[1] = Integer.parseInt(st.nextToken()); colors[2] = Integer.parseInt(st.nextToken()); } } catch (Exception e) { //e.printStackTrace(); colors[0] = colors[1] = colors[2] = -1; } return colors; } public String getStringValue(String name) { return getStringValue(name, (String[]) null); } public String getStringValue(String name, String def) { return getStringValue(name, (String[]) null, def); } public String[] getStringArray(String name) { return getStringArray(name, (String[]) null); } public String[] getStringArray(String name, String[] params) { String s = getValue(name, params); if (s == null) { return null; } String[] values = s.split("\\s*,\\s*"); if (values == null) { return new String[] { s }; } return values; } public String getStringValue(String name, String[] params) { return getValue(name, params); } public String getStringValue(String name, String[] params, String def) { String s = getValue(name, params); return (s == null) ? def : s; } // @see com.aelitis.azureus.ui.skin.SkinProperties#getBooleanValue(java.lang.String, boolean) public boolean getBooleanValue(String name, boolean def) { String s = getStringValue(name, (String) null); if (s == null) { return def; } return s.toLowerCase().equals("true") || s.equals("1"); } public void clearCache() { rb.clearUsedMessagesMap(1); } public ClassLoader getClassLoader() { return classLoader; } } azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_dlg_coreloading.properties0000644000175000017500000000337211276715164026505 0ustar adrianadriantemplate.imagedir=com/aelitis/azureus/ui/images image.logo={template.imagedir}/logo-150.png template.fill.attach.top=0,0 template.fill.attach.bottom=100,0 template.fill.attach.left=0,0 template.fill.attach.right=100,0 coreloading.body.type=container coreloading.body.width=400 coreloading.body.height=175 coreloading.body.widgets=coreloading.main coreloading.main.type=container coreloading.main.attach.template=template.fill coreloading.main.widgets=coreloading.logo,\ coreloading.info,\ coreloading.task,\ coreloading.progress coreloading.main.color=#f3fbff coreloading.logo.type=image,{image.logo} coreloading.logo.width=95 coreloading.logo.height=95 coreloading.logo.drawmode=stretch coreloading.logo.attach.top=0,20 coreloading.logo.attach.left=0,20 coreloading.progress.type=container coreloading.progress.view=progress coreloading.progress.height=2 coreloading.progress.attach.top=coreloading.info,15 coreloading.progress.attach.left=coreloading.info,-5,left coreloading.progress.attach.right=100,-20 coreloading.progress.color=#a0a0a0 coreloading.task.type=text coreloading.task.view=task coreloading.task.text.size=10px coreloading.task.text.color=#999999 coreloading.task.attach.top=coreloading.progress,2 coreloading.task.attach.left=coreloading.info,-5,left coreloading.task.attach.right=100,-20 coreloading.task.attach.bottom=100,-2 coreloading.info.type=text,{dlg.corewait.text} coreloading.info.text.size=14px coreloading.info.text.color=#1c5682 coreloading.info.attach.top=coreloading.logo,5,top coreloading.info.attach.left=coreloading.logo,12 coreloading.info.attach.right=100,-15 coreloading.cancel.type=button coreloading.cancel.view=close coreloading.cancel.text=Cancel coreloading.cancel.attach.bottom=100,-10 coreloading.cancel.attach.right=100,-20azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_maintabs.properties0000644000175000017500000003261211276715164025166 0ustar adrianadrian#=============================================================================== #main.area.middle #=============================================================================== main.area.middle.type=container main.area.middle.widgets=main.area.maintabs,main.area.body main.area.middle.attach.top=main.area.topbar,0 main.area.middle.attach.bottom=maintabs.statusbarline,0 main.area.middle.attach.left=0,0 main.area.middle.attach.right=100,0 ################# # used to be where the main tabs where. Now it's search and user info ################## main.area.maintabs.type=container main.area.maintabs.widgets=main.area.topgap,\ main.area.toolbar,\ main.area.toolbar.2nd,\ main.area.toolbar.gap,\ maintabs.area.search,\ maintabs.line,\ maintabs.vcenter,\ maintabs.area.sidebarpop main.area.maintabs.view=tabbar main.area.maintabs.attach.top=0,0 main.area.maintabs.attach.left=0,0 main.area.maintabs.attach.right=100,0 main.area.maintabs.color=#e1e6e8 main.area.maintabs.color.style=gradient,#a9b7c0,0.76 main.area.maintabs.background.drawmode=tile-x main.area.maintabs.height=50 main.area.maintabs.propogateDown=1 main.area.topgap.type=container main.area.topgap.view=topgap main.area.topgap.attach.top=0,0 main.area.topgap.height=6 main.area.topgap.attach.right=100,0 maintabs.line.type=container maintabs.line.attach.template=template.fill maintabs.line.attach.top= maintabs.line.height=1 maintabs.line.color=COLOR_WIDGET_NORMAL_SHADOW maintabs.vcenter.type=container maintabs.vcenter.attach.top=0,0 maintabs.vcenter.attach.bottom=100,0 maintabs.vcenter.attach.left=0,0 maintabs.vcenter.attach.right= maintabs.vcenter.width=1 maintabs.area.sidebarpop.type=container maintabs.area.sidebarpop.view=sidebar-pop maintabs.area.sidebarpop.attach.left=0,0 maintabs.area.sidebarpop.attach.top= maintabs.area.sidebarpop.attach.bottom=100,0 maintabs.area.sidebarpop.width=0 maintabs.area.sidebarpop.color=#dfe8ea #maintabs.area.sidebarpop.color=COLOR_WIDGET_BACKGROUND maintabs.area.sidebarpop.widgets=sidebarpop.dropdown,sidebarpop.expand,sidebarpop.top,sidebarpop.right,sidebarpop.left sidebarpop.top.type=container sidebarpop.top.height=1 sidebarpop.top.attach.right=100,0 sidebarpop.top.attach.top= sidebarpop.top.attach.left=0,0 sidebarpop.top.color=COLOR_WIDGET_NORMAL_SHADOW sidebarpop.right.type=container sidebarpop.right.width=1 sidebarpop.right.attach.top=sidebarpop.top,0 sidebarpop.right.attach.bottom=100,0 sidebarpop.right.attach.left= sidebarpop.right.attach.right=100,0 sidebarpop.right.color=COLOR_WIDGET_NORMAL_SHADOW sidebarpop.left.type=container sidebarpop.left.width=1 sidebarpop.left.attach.top=sidebarpop.top,0 sidebarpop.left.attach.bottom=100,0 sidebarpop.left.attach.left=0,0 sidebarpop.left.attach.right= sidebarpop.left.color=COLOR_WIDGET_NORMAL_SHADOW sidebarpop.dropdown.type=image,{image.sidebar.dropdown} sidebarpop.dropdown.view=sidebar-dropdown sidebarpop.dropdown.attach.top=sidebarpop.top,1 sidebarpop.dropdown.attach.left=sidebarpop.expand,4 sidebarpop.dropdown.attach.right=sidebarpop.right,-3 sidebarpop.dropdown.attach.bottom=100,-1 sidebarpop.dropdown.tooltip={sidebar.dropdown.tooltip} sidebarpop.dropdown.cursor=hand sidebarpop.expand.type=image,{image.sidebar.expand} sidebarpop.expand.attach.top=sidebarpop.top,1 sidebarpop.expand.attach.bottom=100,-1 sidebarpop.expand.attach.left=0,4 sidebarpop.expand.view=sidebar-expand sidebarpop.expand.tooltip={sidebar.expand.tooltip} sidebarpop.expand.cursor=hand main.area.toolbar.type=container main.area.toolbar.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.ToolBarView main.area.toolbar.view=global-toolbar main.area.toolbar.attach.top=main.area.topgap,-1 main.area.toolbar.attach.bottom=100,-3 main.area.toolbar.attach.left=maintabs.area.search,18 main.area.toolbar.gap.type=container main.area.toolbar.gap.view=toolbar-gap main.area.toolbar.gap.width=18 main.area.toolbar.gap.attach.left=main.area.toolbar,0 main.area.toolbar.2nd.type=container main.area.toolbar.2nd.view=global-toolbar-2nd main.area.toolbar.2nd.attach.top=main.area.topgap,0 main.area.toolbar.2nd.attach.bottom=100,-3 main.area.toolbar.2nd.attach.left=main.area.toolbar.gap,0 maintabs.area.search.type=container maintabs.area.search.view=topbar-area-search maintabs.area.search.propogate=1 maintabs.area.search.widgets=widget.search-button1,\ widget.search-area,\ widget.search-line maintabs.area.search.attach.left=0,5 maintabs.area.search.attach.top=main.area.topgap,0 maintabs.area.search.attach.bottom=100,0 maintabs.area.search.width=200 widget.search-line.type=container widget.search-line.height=1 widget.search-line.attach.top= widget.search-line.attach.bottom=100,0 widget.search-line.attach.left=0,0 widget.search-line.attach.right=100,0 widget.search-line.color=COLOR_WIDGET_NORMAL_SHADOW widget.search-area.type=container widget.search-area.widgets=widget.search-text2 widget.search-area.attach.left=widget.search-button1,0 widget.search-area.attach.top=0,2 widget.search-area.attach.right=100,0 widget.search-area.attach.top-small=0,10 widget.search-area.background={image.searchbox} widget.search-area.background-small={image.ssearchbox} widget.search-area.background.drawmode=tile-x widget.search-text2.type=container widget.search-text2.view=search-text widget.search-text2.attach.left=0,5 widget.search-text2.attach.right=100,-6 widget.search-text2.attach.top=0,6 widget.search-text2.attach.bottom=100,-3 widget.search-button1.type=image widget.search-button1.image={image.search.dropdown} widget.search-button1.image-small={image.ssearch.dropdown} widget.search-button1.image-over-small={image.ssearch.dropdown} widget.search-button1.view=search-dropdown widget.search-button1.attach.left=0,0 widget.search-button1.attach.top=widget.search-area,0,top widget.search-button1.attach.bottom=widget.search-area,0,bottom ########## toolbar.area.item.type=container toolbar.area.item.widgets=toolbar.area.item.image,toolbar.area.item.title toolbar.area.item.attach.top=0,1 toolbar.area.item.cursor=hand #toolbar.area.item.debug=1 toolbar.area.item.image.type=image toolbar.area.item.image.view=toolbar-item-image toolbar.area.item.image.attach.left=0,0 toolbar.area.item.image.attach.right=100,0 toolbar.area.item.image.attach.top=0,0 toolbar.area.item.image.attach.bottom=toolbar.area.item.title,0 toolbar.area.item.image.width=50 toolbar.area.item.image.height=27 toolbar.area.item.image.align=center toolbar.area.item.image.v-align=top toolbar.area.item.image.cursor=hand toolbar.area.item.title.type=text toolbar.area.item.title.view=toolbar-item-title toolbar.area.item.title.attach.left=0,2 toolbar.area.item.title.attach.right=100,-2 toolbar.area.item.title.attach.bottom=100,0 toolbar.area.item.title.attach.top= toolbar.area.item.title.align=center toolbar.area.item.title.text.font=verdana toolbar.area.item.title.text.font._mac= toolbar.area.item.title.text.size=11px toolbar.area.item.title.fgcolor=#333333 toolbar.area.item.title.fgcolor-disabled=#808080 toolbar.area.item.title.width=50 #toolbar.area.item.title.debug=1 toolbar.area.sitem.type=container toolbar.area.sitem.widgets=toolbar.area.sitem.imagearea,toolbar.area.sitem.title toolbar.area.sitem.propogate=1 toolbar.area.sitem.attach.top=0,1 toolbar.area.sitem.cursor=hand toolbar.area.sitem.imagearea.type=container toolbar.area.sitem.imagearea.widgets=toolbar.area.sitem.image toolbar.area.sitem.imagearea.attach.bottom=toolbar.area.sitem.title,-1 #toolbar.area.sitem.imagearea.attach.left=toolbar.area.sitem.title,center toolbar.area.sitem.imagearea.attach.left=0,0 toolbar.area.sitem.imagearea.attach.right=100,0 toolbar.area.sitem.imagearea.background={template.imagedir}/tb/sec_m.png toolbar.area.sitem.imagearea.background-over={template.imagedir}/tb/sec_m.png toolbar.area.sitem.imagearea.background-down={template.imagedir}/tb/sec_r_l_down.png,{template.imagedir}/tb/sec_m_down.png,{template.imagedir}/tb/sec_l_r_down.png toolbar.area.sitem.imagearea.background.drawmode=tile-x toolbar.area.sitem.imagearea.minwidth=38 toolbar.area.sitem.image.type=image toolbar.area.sitem.image.view=toolbar-item-image toolbar.area.sitem.image.attach.left=0,0 toolbar.area.sitem.image.attach.right=100,0 toolbar.area.sitem.image.attach.top=0,2 toolbar.area.sitem.image.attach.bottom=100,0 toolbar.area.sitem.image.align=center toolbar.area.sitem.image.v-align=center toolbar.area.sitem.image.cursor=hand toolbar.area.sitem.image.drawmode=center toolbar.area.sitem.image.width=1 toolbar.area.sitem.title.type=text toolbar.area.sitem.title.view=toolbar-item-title toolbar.area.sitem.title.attach.left=0,0 toolbar.area.sitem.title.attach.right=100,0 toolbar.area.sitem.title.attach.bottom=100,0 #toolbar.area.sitem.title.color=#ff0000 toolbar.area.sitem.title.attach.top= toolbar.area.sitem.title.align=center toolbar.area.sitem.title.text.font=verdana toolbar.area.sitem.title.text.font._mac= toolbar.area.sitem.title.text.size=11px toolbar.area.sitem.title.text.h-padding=2 toolbar.area.sitem.title.fgcolor=#333333 toolbar.area.sitem.title.fgcolor-disabled=#808080 ### toolbar.area.sitem.left.type=container toolbar.area.sitem.left.widgets=toolbar.area.sitem.l.imagearea,toolbar.area.sitem.title toolbar.area.sitem.left.attach.top=0,1 toolbar.area.sitem.left.cursor=hand toolbar.area.sitem.left.propogate=1 toolbar.area.sitem.l.imagearea.type=container toolbar.area.sitem.l.imagearea.widgets=toolbar.area.sitem.image toolbar.area.sitem.l.imagearea.attach.bottom=toolbar.area.sitem.title,-1 toolbar.area.sitem.l.imagearea.attach.left=0,0 toolbar.area.sitem.l.imagearea.attach.right=100,0 toolbar.area.sitem.l.imagearea.background={image.toolbar.2nd.l-bg} toolbar.area.sitem.l.imagearea.background-over={image.toolbar.2nd.l-bg} toolbar.area.sitem.l.imagearea.background-down={image.toolbar.2nd.l-bg-down} toolbar.area.sitem.l.imagearea.background.drawmode=tile-x toolbar.area.sitem.l.imagearea.minwidth=38 ### toolbar.area.sitem.right.type=container toolbar.area.sitem.right.widgets=toolbar.area.sitem.r.imagearea,toolbar.area.sitem.title toolbar.area.sitem.right.attach.top=0,1 toolbar.area.sitem.right.cursor=hand toolbar.area.sitem.right.propogate=1 toolbar.area.sitem.r.imagearea.type=container toolbar.area.sitem.r.imagearea.widgets=toolbar.area.sitem.image toolbar.area.sitem.r.imagearea.attach.bottom=toolbar.area.sitem.title,-1 toolbar.area.sitem.r.imagearea.attach.left=0,0 toolbar.area.sitem.r.imagearea.attach.right=100,0 toolbar.area.sitem.r.imagearea.background={image.toolbar.2nd.r-bg} toolbar.area.sitem.r.imagearea.background-over={image.toolbar.2nd.r-bg} toolbar.area.sitem.r.imagearea.background-down={image.toolbar.2nd.r-bg-down} toolbar.area.sitem.r.imagearea.background.drawmode=tile-x toolbar.area.sitem.r.imagearea.minwidth=38 ### toolbar.area.vitem.left.type=container toolbar.area.vitem.left.widgets=toolbar.area.vitem.l.imagearea,toolbar.area.vitem.title toolbar.area.vitem.left.attach.top=0,1 toolbar.area.vitem.left.cursor=hand toolbar.area.vitem.left.propogate=1 toolbar.area.vitem.l.imagearea.type=container toolbar.area.vitem.l.imagearea.widgets=toolbar.area.sitem.image toolbar.area.vitem.l.imagearea.attach.bottom=toolbar.area.vitem.title,-1 toolbar.area.vitem.l.imagearea.attach.left=0,0 toolbar.area.vitem.l.imagearea.attach.right=100,0 toolbar.area.vitem.l.imagearea.background={image.toolbar.2nd-view.l-bg} toolbar.area.vitem.l.imagearea.background-over={image.toolbar.2nd-view.l-bg} toolbar.area.vitem.l.imagearea.background-down={image.toolbar.2nd-view.l-bg-down} toolbar.area.vitem.l.imagearea.background.drawmode=tile-x toolbar.area.vitem.l.imagearea.minwidth=32 ### toolbar.area.vitem.right.type=container toolbar.area.vitem.right.widgets=toolbar.area.vitem.r.imagearea,toolbar.area.vitem.title toolbar.area.vitem.right.attach.top=0,1 toolbar.area.vitem.right.cursor=hand toolbar.area.vitem.right.propogate=1 toolbar.area.vitem.r.imagearea.type=container toolbar.area.vitem.r.imagearea.widgets=toolbar.area.sitem.image toolbar.area.vitem.r.imagearea.attach.bottom=toolbar.area.vitem.title,-1 toolbar.area.vitem.r.imagearea.attach.left=0,0 toolbar.area.vitem.r.imagearea.attach.right=100,0 toolbar.area.vitem.r.imagearea.background={image.toolbar.2nd-view.r-bg} toolbar.area.vitem.r.imagearea.background-over={image.toolbar.2nd-view.r-bg} toolbar.area.vitem.r.imagearea.background-down={image.toolbar.2nd-view.r-bg-down} toolbar.area.vitem.r.imagearea.background.drawmode=tile-x toolbar.area.vitem.r.imagearea.minwidth=32 toolbar.area.vitem.title.type=text toolbar.area.vitem.title.view=toolbar-item-title toolbar.area.vitem.title.attach.left=0,0 toolbar.area.vitem.title.attach.right=100,0 toolbar.area.vitem.title.attach.bottom=100,0 toolbar.area.vitem.title.attach.top= toolbar.area.vitem.title.align=center toolbar.area.vitem.title.text.font=verdana toolbar.area.vitem.title.text.font._mac= toolbar.area.vitem.title.text.size=11px toolbar.area.vitem.title.fgcolor=#333333 toolbar.area.vitem.title.fgcolor-disabled=#808080 ### toolbar.area.sitem.left2.type=container toolbar.area.sitem.left2.attach.top=0,1 toolbar.area.sitem.left2.attach.left=0,18 toolbar.area.sitem.sep.type=image,{template.imagedir}/tb/sec_sep.png toolbar.area.sitem.sep.attach.top=0,1 toolbar.area.item.sep.type=image,{image.toolbar.spacer} toolbar.area.item.sep.attach.top=0,0 toolbar.area.item.sep.attach.left=0,7 toolbar.area.item.sep3.type=image,{image.toolbar.spacer} toolbar.area.item.sep3.attach.top=0,0 toolbar.area.item.sep3.attach.left=0,18 azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_tab_browse.properties0000644000175000017500000000207111276447730025514 0ustar adrianadrian#=============================================================================== #main.area.browsetab #(The browse tab) #=============================================================================== main.area.browsetab.type=container main.area.browsetab.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.Browse main.area.browsetab.view=browse-area main.area.browsetab.attach.template=template.tabcontentarea main.area.browsetab.attach.top=0,0 main.area.browsetab.widgets=browse.area.content,browser.area.wait #main.area.browsetab.border=1 browse.area.content.type=browser browse.area.content.view=browse browse.area.content.indicator=maintabs.waitindicator browse.area.content.attach.left=0,0 browse.area.content.attach.right=100,0 browse.area.content.attach.top=0,0 browse.area.content.attach.bottom=100,0 browse.area.content.forceVisibleAfterLoad=0 browser.area.wait.type=text browser.area.wait.text.color={color.text.fg} browser.area.wait.text.size=12 browser.area.wait.attach.template=template.fill browser.area.wait.v-align=center browser.area.wait.align=center azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_manageCN.properties0000644000175000017500000000170711133002656025025 0ustar adrianadrian manageCN.body.type=container manageCN.body.title={v3.dialog.cnmanage.title} manageCN.body.width=380 manageCN.body.height=200 manageCN.body.widgets=manageCN.intro,\ manageCN.list,\ manageCN.button.close manageCN.intro.type=text,{v3.dialog.cnmanage.intro} manageCN.intro.attach.top=0,10 manageCN.intro.attach.left=0,10 manageCN.intro.attach.right=100,-10 manageCN.list.type=container manageCN.list.view=list-area manageCN.list.border=1 manageCN.list.attach.top=manageCN.intro,10 manageCN.list.attach.bottom=manageCN.button.close,-10 manageCN.list.attach.left=0,10 manageCN.list.attach.right=100,-10 manageCN.button.close.type=button manageCN.button.close.minwidth=45 manageCN.button.close.text={Button.close} manageCN.button.close.view=close manageCN.button.close.attach.top= manageCN.button.close.attach.bottom=100,-10 manageCN.button.close.attach.left= manageCN.button.close.attach.right=100,-10 azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_sbc_library.properties0000644000175000017500000000706311276741424025663 0ustar adrianadrian library.type=container library.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.SBC_LibraryView library.view=sidebar-library-area library.widgets=library.wait,library.list,library.top library.attach.template=template.fill library.attach.top=library.top,0 ## library.top.type=container library.top.view=library-list-info library.top.attach.top=0,0 library.top.attach.left=0,0 library.top.attach.right=100,0 library.top.height=40 library.top.visible=0 library.top.color=#F1F9F8 #library.top.widgets=library.top.info ## List library.list.type=container library.list.view=library-list-area library.list.attach.top=library.top,0 library.list.attach.left=0,0 library.list.attach.right=100,0 library.list.attach.bottom=100,0 library.table.small.type=container library.table.small.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.SBC_LibraryTableView library.table.small.view=library-small-area library.table.small.attach.template=template.fill library.table.big.type=container library.table.big.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.SBC_LibraryTableView_Big library.table.big.view=library-big-area library.table.big.attach.template=template.fill #### library.top.info.type=container library.top.info.height=40 library.top.info.color=#F1F9F8 library.top.info.widgets=library.info.close,library.info.title1,library.info.title2 library.top.info.attach.template=template.fill library.info.title2.type=text library.info.title2.view=infobar-title-2 library.info.title2.attach.left=library.info.title1,10 library.info.title2.attach.top=0,0 library.info.title2.attach.bottom=100,0 library.info.title2.attach.right=library.info.close,-15 library.info.title2.v-align=center library.info.title2.text.size=15px library.info.title2.text.size._mac=14px library.info.title2.text.color=#808080 library.info.title1.type=text library.info.title1.view=infobar-title-1 library.info.title1.attach.left=0,20 library.info.title1.attach.top=0,0 library.info.title1.attach.bottom=100,0 library.info.title1.align=right library.info.title1.v-align=center library.info.title1.text.size=15px library.info.title1.text.size._mac=14px library.info.title1.text.color=#808080 library.info.title1.text.style=bold library.info.close.type=image,{template.imagedir}/dismissX.gif library.info.close.view=close library.info.close.cursor=hand library.info.close.attach.right=100,-10 library.info.close.attach.top=0,7 ########### library.wait.type=container library.wait.visible=0 library.wait.view=library-wait library.wait.attach.template=template.fill library.wait.widgets=library.wait.icon,library.wait.task,library.wait.progress,library.wait.text library.wait.color=#f3fbff library.wait.icon.type=image,{image.logo} library.wait.icon.align=center library.wait.icon.attach.top=50,-150 library.wait.icon.attach.left=50,-75 library.wait.task.type=text library.wait.task.view=library-wait-task library.wait.task.text.size=10px library.wait.task.text.color=#999999 library.wait.task.width=300 library.wait.task.attach.left=50,-150 library.wait.task.attach.top=library.wait.icon,20 library.wait.progress.type=container library.wait.progress.view=library-wait-progress library.wait.progress.attach.top=library.wait.task,2 library.wait.progress.height=4 library.wait.progress.width=300 library.wait.progress.attach.left=50,-150 library.wait.progress.color=#666666 library.wait.text.type=text,Loading library.wait.text.align=center library.wait.text.text.size=17px library.wait.text.text.color=#1c5682 library.wait.text.width=300 library.wait.text.attach.left=50,-150 library.wait.text.attach.top=library.wait.progress,10 azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_devices_od.properties0000644000175000017500000000136711247443312025466 0ustar adrianadriandevicesodview.type=container devicesodview.onshow.skinviewclass=com.aelitis.azureus.ui.swt.devices.SBC_DevicesODView devicesodview.widgets=\ devicesodview.title,\ devicesodview.list devicesodview.attach.template=template.fill devicesodview.title.type=text,{devices.od.view.heading} devicesodview.title.text.v-padding=10 devicesodview.title.text.h-padding=5 devicesodview.title.view=title devicesodview.title.attach.template=template.fill devicesodview.title.attach.bottom= devicesodview.title.attach.right= devicesodview.title.text.size=15px devicesodview.title.text.style=bold devicesodview.list.type=container devicesodview.list.attach.template=template.fill devicesodview.list.attach.top=devicesodview.title,0 devicesodview.list.view=devicesod-list ##azureus-4.3.0.6/com/aelitis/azureus/ui/skin/SkinProperties.java0000644000175000017500000000504011127403350023744 0ustar adrianadrian/* * Created on Jun 26, 2006 8:34:56 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.skin; import java.util.ResourceBundle; /** * Interface for reading Skin properties (might be better) * * @author TuxPaper * @created Jun 26, 2006 * */ public interface SkinProperties { /** * Retrieve all the properties * * @return all the properties */ //Properties getProperties(); /** * Add a property key/value pair to the list * * @param name Name of Property * @param value Value of Property */ void addProperty(String name, String value); /** * Retrieve a property's int value * * @param name Name of property * @param def Default value if property not found * @return value */ int getIntValue(String name, int def); /** * Retrieve a string value * * @param name Name of property * @return the String value, or null if not found */ String getStringValue(String name); String getStringValue(String name, String def); String[] getStringArray(String name); String getStringValue(String name, String[] params); String getStringValue(String name, String[] params, String def); String[] getStringArray(String name, String[] params); int[] getColorValue(String name); boolean getBooleanValue(String name, boolean def); /** * * * @since 3.1.1.1 */ void clearCache(); /** * @param name * @return * * @since 3.1.1.1 */ boolean hasKey(String name); /** * @param name * @return * * @since 3.1.1.1 */ String getReferenceID(String name); /** * @param subBundle * * @since 4.0.0.5 */ void addResourceBundle(ResourceBundle subBundle); /** * @return * * @since 4.0.0.5 */ ClassLoader getClassLoader(); } azureus-4.3.0.6/com/aelitis/azureus/ui/skin/skin3_constants.properties0000644000175000017500000003041311277132246025374 0ustar adrianadrian#=============================================================================== #Templates #=============================================================================== template.tableheader.height=24 template.imagedir=com/aelitis/azureus/ui/images template.imagedir2=org/gudy/azureus2/ui/icons template.padding=10 template.advanced.offset=-25 template.fill.attach.top=0,0 template.fill.attach.bottom=100,0 template.fill.attach.left=0,0 template.fill.attach.right=100,0 template.tabcontentarea.attach.top=main.area.maintabs,{template.padding} template.tabcontentarea.attach.bottom=100,-{template.padding} template.tabcontentarea.attach.left=0,{template.padding} template.tabcontentarea.attach.right=100,-{template.padding} #colors #=============================================================================== color.text.fg=#c2c2c2 color.text.fg.disabled=#414141 color.text.over=#B3D0FF color.text.disabled=#555555 color.row.odd.bg=altrow color.row.even.bg=COLOR_LIST_BACKGROUND table.Media-Mini.row.focus.style=solid table.Media.row.focus.style=solid table.VuzeActivity.row.focus.style=solid color.list.header.fg=COLOR_WIDGET_FOREGROUND color.list.header.bg=COLOR_WIDGET_BACKGROUND color.list.header.divider=COLOR_WIDGET_BORDER color.list.header.line=COLOR_WIDGET_BORDER color.VuzeActivity.sort.bg=#202020 color.library.incomplete=#808080 #color.view.background=#101010 color.mainshell=#1B1B1B color.section.header=#9e9e9e color.section.header.size=15px color.section.header.selected=#F2F2F2 color.table.buttonbar=#000000 color.progress.bg=#8dc9ff color.progress.fg=#ebfeff color.progress.text=#005acf color.progress.border=#005acf color.rating.good=#608fd4 color.rating.odd.good.darker=#2e2e2e color.rating.even.good.darker=#3a3a3a color.rating.bad={color.row.fg} color.rating.odd.bad.darker=#2e2e2e color.rating.even.bad.darker=#3a3a3a color.topbar.speed.bg2=#4568ac color.topbar.speed.bg1=#4568ac color.topbar.speed.bg3=#4568ac color.topbar.speed.average=#30a1ff color.topbar.speed.value1=#d0d7ed color.topbar.speed.overhead=#f0d7ed color.topbar.speed.value0=#7783a8 color.topbar.speed.value2plus=#5c0080 color.topbar.speed.trimmed=#5c0080 #color.links.normal=BLUE.9 #color.links.hover=BLUE.FADED.9 color.links.normal=#156dff color.links.hover=#000080 #color.activity.row.header.bg=COLOR_WIDGET_LIGHT_SHADOW #color.activity.row.header.bg=#101010 #This one is to spec, but too dark #color.activity.row.divider=#232323 #color.activity.row.divider=#303030 #color.activity.row.header.fg=#707070 table.Activity.color.row.divider=COLOR_WIDGET_LIGHT_SHADOW table.Activity.color.row.odd.bg=COLOR_LIST_BACKGROUND table.Activity.color.row.odd.fg=COLOR_LIST_TEXT table.Activity.color.row.odd.selected.fg=COLOR_WIDGET_FOREGROUND table.Activity.color.row.odd.selected.bg=COLOR_WIDGET_BACKGROUND color.vuze-entry.news.bg=#252932 color.vuze-entry.news.fg=#FFFFFF #== Color for the heading for widgets such as the title for a text entry box color.widget.heading={color.list.header.fg} color.widget.bg={color.view.background} color.widget.container.bg=#232323 color.widget.border=#313131 color.tab.header=#FFFFFF color.maintabs.selected=#ffffff color.maintabs.fg=#c2c2c2 color.maintabs.over=#e0e0e0 color.sidebar.bg=#dfe8ea color.sidebar.fg=#2B3D32 color.sidebar.selected.bg=COLOR_LIST_SELECTION color.sidebar.selected.fg=#FFFFFF color.sidebar.focus=#FFFFFF color.pieceview.alldone=BLUE.FADED.9 color.pieceview.notdone=#F0F0F0 color.pieceview.uploading=#800000 color.pieceview.downloading=#A00000 color.pieceview.noavail=#000000 color.pieceview.havesome=BLUE.9 color.search.text.bg=#ffffff color.search.text.fg=#333333 color.search.text.fg.default=#999999 #=============================================================================== #main.area.statusbar #=============================================================================== maintabs.statusbarline.type=container maintabs.statusbarline.attach.template=template.fill maintabs.statusbarline.attach.top= maintabs.statusbarline.attach.bottom=main.area.statusbar maintabs.statusbarline.height=1 maintabs.statusbarline.color=COLOR_WIDGET_NORMAL_SHADOW main.area.statusbar.type=container main.area.statusbar.view=statusbar main.area.statusbar.attach.bottom=100,0 main.area.statusbar.attach.left=0,0 main.area.statusbar.attach.right=100,0 #main.area.statusbar.border=1 #main.area.statusbar.height=25 #=============================================================================== #icons #=============================================================================== column.azproduct.product={template.imagedir}/icon-AzureusProduct-24x24.png column.azproduct.globe={template.imagedir}/icon-Globe-24x24.png icon.editpencil={template.imagedir}/icon-pencil-14x15.png image.media.rollover={template.imagedir}/media-rollover.png image.check={template.imagedir}/checkMark-14x14.png image.rateitdd={template.imagedir}/RateItDD.png image.sort.asc={template.imagedir}/bullet_arrow_up.png image.sort.desc={template.imagedir}/bullet_arrow_down.png image.torrent.up-mouseonrow={template.imagedir}/torrent_up.png image.torrent.down-mouseonrow={template.imagedir}/torrent_down.png image.button.play={template.imagedir}/tb/play.png image.button.download={template.imagedir}/tb/download.png image.button.share={template.imagedir}/tb/ic_share.png image.button.transcode={template.imagedir}/tb/ic_device.png image.vuze-entry.comments={template.imagedir}/entry_comments.png image.vuze-entry.featured={template.imagedir}/entry_featured.png image.vuze-entry.news={template.imagedir}/entry_news.png image.vuze-entry.frog={template.imagedir}/entry_frog.png image.help={template.imagedir}/help.png image.separator={template.imagedir}/separator.gif image.searchbox={template.imagedir}/tb/search_bg_lft.png,{template.imagedir}/tb/search_bg_mid.png,{template.imagedir}/tb/search_bg_rgt.png image.searchbox.middle={template.imagedir}/tb/search_bg_mid.png image.search.dropdown={template.imagedir}/tb/search_btn.png image.ssearchbox={template.imagedir}/tb/search_bg_lft_small.png,{template.imagedir}/tb/search_bg_mid_small.png,{template.imagedir}/tb/search_bg_rgt_small.png image.ssearchbox.middle={template.imagedir}/tb/search_bg_mid_small.png image.ssearch.dropdown={template.imagedir}/tb/search_btn_small.png image.toolbar.open={template.imagedir2}/toolbar/open_no_default.gif image.toolbar.new={template.imagedir2}/toolbar/new.gif image.toolbar.up={template.imagedir}/tb/ic_up.png image.toolbar.down={template.imagedir}/tb/ic_down.png image.toolbar.run={template.imagedir}/tb/ic_launch.png image.toolbar.start={template.imagedir}/tb/ic_start.png image.toolbar.stop={template.imagedir}/tb/ic_stop.png image.toolbar.remove={template.imagedir}/tb/ic_delete.png image.toolbar.spacer={template.imagedir}/tb/spacer.png image.bullet.arrow.down={template.imagedir}/bullet_arrow_down.png image.toolbar.table_normal={template.imagedir}/tb/ic_list_small.png image.toolbar.table_large={template.imagedir}/tb/ic_list_big.png image.toolbar.2nd.l-bg={template.imagedir}/tb/sec_l_l.png,{template.imagedir}/tb/sec_m.png image.toolbar.2nd.l-bg-down={template.imagedir}/tb/sec_l_l_down.png,{template.imagedir}/tb/sec_m_down.png image.toolbar.2nd.r-bg={template.imagedir}/tb/sec_m.png,{template.imagedir}/tb/sec_m.png,{template.imagedir}/tb/sec_r_r.png image.toolbar.2nd.r-bg-down={template.imagedir}/tb/sec_m_down.png,{template.imagedir}/tb/sec_m_down.png,{template.imagedir}/tb/sec_r_r_down.png image.toolbar.2nd-view.l-bg={template.imagedir}/tb/view_l_l.png,{template.imagedir}/tb/view_l_m.png,{template.imagedir}/tb/view_l_r.png image.toolbar.2nd-view.l-bg-down={template.imagedir}/tb/view_l_l_down.png,{template.imagedir}/tb/view_l_m_down.png,{template.imagedir}/tb/view_l_r_down.png image.toolbar.2nd-view.r-bg={template.imagedir}/tb/view_r_l.png,{template.imagedir}/tb/view_r_m.png,{template.imagedir}/tb/view_r_r.png image.toolbar.2nd-view.r-bg-down={template.imagedir}/tb/view_r_l_down.png,{template.imagedir}/tb/view_r_m_down.png,{template.imagedir}/tb/view_r_r_down.png image.sidebar.closeitem={template.imagedir}/sb/ic_x.png image.sidebar.expand={template.imagedir}/sb_expand.png image.sidebar.dropdown={template.imagedir}/sb_menu.png image.sidebar.activity={template.imagedir}/sb/ic_activity.png image.sidebar.vuze={template.imagedir}/sb/ic_vuze.png image.sidebar.subscriptions={template.imagedir}/sb/ic_rss.png image.sidebar.rcm={template.imagedir}/sb/ic_rcm.png image.sidebar.welcome={template.imagedir}/sb/ic_welcome.png image.sidebar.library={template.imagedir}/sb/ic_library.png image.sidebar.search={template.imagedir}/sb/ic_search.png image.sidebar.vitality.dots=multi,18,{template.imagedir}/sb/ic_loading.png image.sidebar.vitality.dl.delay=150 image.sidebar.vitality.dl=multi,16,{template.imagedir}/sb/ic_download.png image.sidebar.vitality.info={template.imagedir}/sb/ic_info.png image.sidebar.vitality.info-selected={template.imagedir}/sb/ic_info.png image.sidebar.vitality.alert={template.imagedir}/sb/ic_alert.png image.sidebar.vitality.alert-selected={template.imagedir}/sb/ic_alert.png image.sidebar.vitality.auth={template.imagedir}/sb/ic_auth.png image.sidebar.vitality.auth-selected={template.imagedir}/sb/ic_auth.png image.sidebar.subs.add={template.imagedir}/sb/ic_add.png image.sidebar.sashbg={template.imagedir}/sb/sash_bg.png image.sidebar.devices={template.imagedir}/sb/ic_device.png image.sidebar.device.renderer={template.imagedir}/sb/ic_device_rend.png image.sidebar.device.mediaserver={template.imagedir}/sb/ic_device_ms.png image.sidebar.device.router={template.imagedir}/sb/ic_device_rout.png image.sidebar.device.offlinedownloader={template.imagedir}/sb/ic_device_od.png image.sidebar.device.internet={template.imagedir}/sb/ic_device_int.png image.sidebar.device.2.big={template.imagedir}/30px-xbox.png image.sidebar.device.2.small={template.imagedir}/sb/20px-xbox.png image.sidebar.device.1.big={template.imagedir}/30px-ps3.png image.sidebar.device.1.small={template.imagedir}/sb/20px-ps3.png image.sidebar.device.3.big={template.imagedir}/30px-itunes.png image.sidebar.device.3.small={template.imagedir}/sb/20px-itunes.png image.sidebar.device.4.small={template.imagedir}/sb/20px-wii.png image.sidebar.device.5.small={template.imagedir}/sb/20px-other.png image.sidebar.device.6.small={template.imagedir}/sb/20px-other.png image.sidebar.device.psp.small={template.imagedir}/sb/20px-psp.png image.sidebar.device.tivo.small={template.imagedir}/sb/20px-tivo.png image.sidebar.device.od.bel.small={template.imagedir}/sb/20px-od-bel.png image.sidebar.device.od.vuze.small={template.imagedir}/sb/20px-od-vuze.png image.sidebar.device.od.other.small={template.imagedir}/sb/20px-od-other.png image.sidebar.turnon={template.imagedir}/sb/btn-turnon.png image.sidebar.beta={template.imagedir}/sb/beta.png image.device.logo.belkin={template.imagedir}/device_bel_logo.png image.activity.unread={template.imagedir}/new_dot.png image.unopened={template.imagedir}/new_dot.png image.activity.read={template.imagedir}/old_dot.png image.opened={template.imagedir}/old_dot.png image.trash={template.imagedir}/icon_trash_matte.png image.dismissX={template.imagedir}/dismissX.gif ic_view={template.imagedir}/ic_view.png image.logo={template.imagedir}/logo-150.png #Subscription icons rss=org/gudy/azureus2/ui/icons/rss.png btn_rss_add=org/gudy/azureus2/ui/icons/btn_add_rss.png btn_sidebar_add=com/aelitis/azureus/ui/images/sb/ic_add.png icon_check=com/aelitis/azureus/ui/images/icon_bullet_check.png rss_bg=com/aelitis/azureus/ui/images/rss_bg.png search_bg=com/aelitis/azureus/ui/images/search_bg.png icon_rss=com/aelitis/azureus/ui/images/icon_rss.png ranking_bars=com/aelitis/azureus/ui/images/ranking_bars.png wizard_header_bg=com/aelitis/azureus/ui/images/wizard_header_bg.png tc_bar_end=com/aelitis/azureus/ui/images/tc_bar_end.png tc_bar_0=com/aelitis/azureus/ui/images/tc_bar_0.png tc_bar_1=com/aelitis/azureus/ui/images/tc_bar_1.png #================ table.Media-Mini.row.height=50 table.Media-Mini.row.margin.height=9 table.Media.row.height=50 table.Media.row.margin.height=9 table.library-big.row.height=68 table.library-big.row.margin.height=9 table.library-small.row.height=18 table.library-small.row.margin.height=2 #================== # Unattached Views. Anyone requesting a skinobject with skin view id of [1] # will cause [2] to be created in [3] # UnattachedView.[1]=[2],[3] #================== UnattachedView.advanced=main.area.advancedtab,sidebar.middle UnattachedView.browse=main.area.browse,main.area.middle ### sidebar.defaultwidth=205 azureus-4.3.0.6/com/aelitis/azureus/ui/UIFunctionsManager.java0000644000175000017500000000243710455543164023542 0ustar adrianadrian/* * Created on Jul 12, 2006 2:47:29 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui; /** * @author TuxPaper * @created Jul 12, 2006 * */ public class UIFunctionsManager { private static UIFunctions instance = null; public static UIFunctions getUIFunctions() { return instance; } public static void setUIFunctions(UIFunctions uiFunctions) { instance = uiFunctions; } // TODO: Listener to trigger when instance set } azureus-4.3.0.6/com/aelitis/azureus/ui/UIFunctionsUserPrompter.java0000644000175000017500000000665211267524620024640 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui; /** * @author TuxPaper * @created Mar 18, 2007 * */ public interface UIFunctionsUserPrompter { /** * Returns the number milliseconds the prompt will wait around until it auto * closes. Timer starts after the user is prompted (when {@link #open()} is * called), and typically does not decrease while the user is viewing the * prompt (certain implementations may operate differently) * * @return MS before prompt auto-closes, 0 for no auto-close * * @since 3.0.0.9 */ int getAutoCloseInMS(); /** * Returns the HTML that will be displayed along with the prompt *

    * TODO: Create a boolean canHandleHTML() * * @return * * @since 3.0.0.9 */ String getHtml(); /** * Retrieves the Remember ID associated with this prompt * * @return Remember ID * * @since 3.0.0.9 */ String getRememberID(); /** * Retrieves the text to be displayed by the "Remember this Action" checkbox * * @return Remember text * * @since 3.0.0.9 */ String getRememberText(); /** * Opens the prompt. returns when user has chosen an action, or auto-close * * @since 3.0.0.9 */ void open(UserPrompterResultListener l); int waitUntilClosed(); /** * Sets the # of milliseconds before auto closing. * Timer starts after the user is prompted (when {@link #open()} is * called), and typically does not decrease while the user is viewing the * prompt (certain implementations may operate differently) * @param autoCloseInMS * * @since 3.0.0.9 */ void setAutoCloseInMS(int autoCloseInMS); /** * @param html * * @since 3.0.0.9 */ void setHtml(String html); /** * @param rememberID * @param rememberByDefault * * @since 4.2.0.9 */ void setRemember(String rememberID, boolean rememberByDefault, String rememberText); /** * @param rememberText * * @since 3.0.0.9 */ void setRememberText(String rememberText); /** * @param url * * @since 3.0.0.9 */ void setUrl(String url); /** * Determines if the prompt was auto closed after {@link #open()} was * called, or if the user chose an option. * * @return true: auto-closed after timeout
    * false: user chose an option * * @since 3.0.0.9 */ boolean isAutoClosed(); /** * @since 3.0.4.3 * @param resource image repository resource name (e.g. "error", "warning", "info") */ void setIconResource( String resource ); void setRelatedObjects(Object[] relatedObjects); /** * @param relatedObject * * @since 3.0.0.9 */ void setRelatedObject(Object relatedObject); } azureus-4.3.0.6/com/aelitis/azureus/ui/InitializerListener.java0000644000175000017500000000213410623451040024010 0ustar adrianadrian/* * Created on 27 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui; public interface InitializerListener { public void reportCurrentTask(String currentTask); public void reportPercent(int percent); } azureus-4.3.0.6/com/aelitis/azureus/ui/utils/0000755000175000017500000000000011310377614020324 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/utils/ImageBytesDownloader.java0000644000175000017500000000562611233514242025242 0ustar adrianadrian/** * Created on Apr 28, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.utils; import java.io.InputStream; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader.ResourceDownloaderFactoryImpl; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderAdapter; /** * @author TuxPaper * @created Apr 28, 2008 * */ public class ImageBytesDownloader { static final Map> map = new HashMap>(); static final AEMonitor mon_map = new AEMonitor("ImageDownloaderMap"); public static void loadImage(final String url, final ImageDownloaderListener l) { //System.out.println("download " + url); mon_map.enter(); try { List list = map.get(url); if (list != null) { list.add(l); return; } list = new ArrayList(1); list.add(l); map.put(url, list); } finally { mon_map.exit(); } try { ResourceDownloader rd = ResourceDownloaderFactoryImpl.getSingleton().create( new URL(url)); rd.addListener(new ResourceDownloaderAdapter() { public boolean completed(ResourceDownloader downloader, InputStream is) { mon_map.enter(); try { List list = map.get(url); if (list != null) { try { if (is != null && is.available() > 0) { byte[] newImageBytes = new byte[is.available()]; is.read(newImageBytes); for (ImageDownloaderListener l : list) { try { l.imageDownloaded(newImageBytes); } catch (Exception e) { Debug.out(e); } } } } catch (Exception e) { Debug.out(e); } } map.remove(url); } finally { mon_map.exit(); } return false; } }); rd.asyncDownload(); } catch (Exception e) { Debug.out(url, e); } } public static interface ImageDownloaderListener { public void imageDownloaded(byte[] image); } } azureus-4.3.0.6/com/aelitis/azureus/ui/common/0000755000175000017500000000000011310377630020452 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/common/updater/0000755000175000017500000000000011310377630022116 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/common/updater/UIUpdatable.java0000644000175000017500000000242311036613130025112 0ustar adrianadrian/* * Created on Jun 15, 2006 1:05:17 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.common.updater; /** * {@link UIUpdater} * * @author TuxPaper */ public interface UIUpdatable { /** * Update your UI! * * @since 3.1.1.1 */ public void updateUI(); /** * A name for this UIUpdatable so we can track who's being bad * * @return some name * * @since 3.1.1.1 */ public String getUpdateUIName(); } azureus-4.3.0.6/com/aelitis/azureus/ui/common/updater/UIUpdater.java0000644000175000017500000000227411036613130024621 0ustar adrianadrian/* * Created on Jun 15, 2006 1:41:18 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.common.updater; /** * @author TuxPaper * @created Jun 15, 2006 * */ public interface UIUpdater { public void addUpdater(UIUpdatable updateable); public void removeUpdater(UIUpdatable updateable); public void stopIt(); public void start(); }azureus-4.3.0.6/com/aelitis/azureus/ui/common/updater/UIUpdatableAlways.java0000644000175000017500000000201711036613130026272 0ustar adrianadrian/** * Created on Jul 13, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.common.updater; /** * Sometimes we don't update the UI (such as when nothing is visible). This * class overrides this ability. * * @author TuxPaper * @created Jul 13, 2008 * */ public interface UIUpdatableAlways extends UIUpdatable { } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/0000755000175000017500000000000011310377630021541 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableColumnSortObject.java0000644000175000017500000000231010753000572026602 0ustar adrianadrian/** * Created on Feb 2, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.common.table; /** * If cell.setSortValue is set to an object of this type, the column will * not be set to "Live". Live columns get invalidated every single refresh. * If you use this object, it's wise to {@link TableColumnCore#setLastSortValueChange(long)} * when you know you've changed the sort value. * * * @author TuxPaper * @created Feb 2, 2008 * */ public interface TableColumnSortObject extends Comparable { } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableSelectionListener.java0000644000175000017500000000246411072556246027024 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.common.table; /** * @author TuxPaper * @created Feb 2, 2007 * */ public interface TableSelectionListener { public void selected(TableRowCore[] row); public void deselected(TableRowCore[] rows); public void focusChanged(TableRowCore focus); public void defaultSelected(TableRowCore[] rows, int stateMask); public void mouseEnter(TableRowCore row); public void mouseExit(TableRowCore row); } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableRefreshListener.java0000644000175000017500000000016510566514576026500 0ustar adrianadrianpackage com.aelitis.azureus.ui.common.table; public interface TableRefreshListener { public void tableRefresh(); } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableSelectionAdapter.java0000644000175000017500000000420011072556246026605 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.common.table; /** * @author TuxPaper * @created Feb 6, 2007 * */ public abstract class TableSelectionAdapter implements TableSelectionListener { // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#defaultSelected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void defaultSelected(TableRowCore[] rows, int stateMask) { } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#deselected(com.aelitis.azureus.ui.common.table.TableRowCore) public void deselected(TableRowCore[] rows) { } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#focusChanged(com.aelitis.azureus.ui.common.table.TableRowCore) public void focusChanged(TableRowCore focus) { } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#selected(com.aelitis.azureus.ui.common.table.TableRowCore) public void selected(TableRowCore[] rows) { } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#mouseEnter(com.aelitis.azureus.ui.common.table.TableRowCore) public void mouseEnter(TableRowCore row) { } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#mouseExit(com.aelitis.azureus.ui.common.table.TableRowCore) public void mouseExit(TableRowCore row) { } } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/impl/0000755000175000017500000000000011310377630022502 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/common/table/impl/TableColumnImpl.java0000644000175000017500000010707111271456442026407 0ustar adrianadrian/** * Copyright (C) 2004-2007 Aelitis SAS, All rights Reserved * * Date: July 14, 2004 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.common.table.impl; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager; import com.aelitis.azureus.ui.common.table.*; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadTypeComplete; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.peers.Peer; import org.gudy.azureus2.plugins.sharing.ShareResource; import org.gudy.azureus2.plugins.tracker.TrackerTorrent; import org.gudy.azureus2.plugins.ui.UIRuntimeException; import org.gudy.azureus2.plugins.ui.tables.*; import org.gudy.azureus2.pluginsimpl.local.ui.tables.TableContextMenuItemImpl; /** * Table Column definition and modification routines. * Implements both the plugin API and the core API. *

    * A column is defined in relation to a table. When one column is in * multiple tables of different table ids, each table has it's own column * instance * * @author TuxPaper * * @see org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager */ public class TableColumnImpl implements TableColumnCore { private static final String CFG_SORTDIRECTION = "config.style.table.defaultSortOrder"; /** Internal Name/ID of the column **/ private String sName; /** key of the displayed title for the column. If null, uses default calc */ private String sTitleLanguageKey = null; private int iAlignment; private int iType; private int iPosition; private int iWidth; private int iDefaultWidth; private int iInterval; private long lLastSortValueChange; /** Table the column belongs to */ private String sTableID; private boolean bColumnAdded; private boolean bCoreDataSource; private ArrayList cellRefreshListeners; private ArrayList cellAddedListeners; private ArrayList cellDisposeListeners; private ArrayList cellToolTipListeners; private ArrayList cellMouseListeners; private ArrayList cellMouseMoveListeners; private ArrayList cellVisibilityListeners; private ArrayList columnExtraInfoListeners; private Map mapOtherCellListeners; private int iConsecutiveErrCount; private ArrayList menuItemsHeader; private ArrayList menuItemsColumn; private boolean bObfusticateData; protected AEMonitor this_mon = new AEMonitor("TableColumn"); private boolean bSortValueLive; private long lStatsRefreshTotalTime; private long lStatsRefreshCount = 0; private long lStatsRefreshZeroCount = 0; private boolean bSortAscending; private boolean editable; private int iMinWidth = -1; private int iMaxWidth = -1; private boolean bVisible; private boolean bMaxWidthAuto = false; private boolean bWidthAuto; private int iPreferredWidth; private boolean bPreferredWidthAuto = true; private int iPreferredWidthMax = -1; private boolean auto_tooltip = false; private Map userData; private boolean removed; private Class forPluginDataSourceType; /** * @deprecated */ public TableColumnImpl(String tableID, String columnID) { // Guess forPluginDataSourceType based on tableID Class forPluginDataSourceType = null; if (TableManager.TABLE_MYTORRENTS_ALL_BIG.equals(tableID) || TableManager.TABLE_MYTORRENTS_UNOPENED.equals(tableID) || TableManager.TABLE_MYTORRENTS_UNOPENED_BIG.equals(tableID)) { forPluginDataSourceType = Download.class; } else if (TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG.equals(tableID) || TableManager.TABLE_MYTORRENTS_INCOMPLETE.equals(tableID)) { forPluginDataSourceType = DownloadTypeIncomplete.class; } else if (TableManager.TABLE_MYTORRENTS_COMPLETE.equals(tableID) || TableManager.TABLE_MYTORRENTS_COMPLETE_BIG.equals(tableID)) { forPluginDataSourceType = DownloadTypeComplete.class; } else if (TableManager.TABLE_TORRENT_PEERS.equals(tableID)) { forPluginDataSourceType = Peer.class; } else if (TableManager.TABLE_TORRENT_FILES.equals(tableID)) { forPluginDataSourceType = DiskManagerFileInfo.class; } else if (TableManager.TABLE_MYTRACKER.equals(tableID)) { forPluginDataSourceType = TrackerTorrent.class; } else if (TableManager.TABLE_MYSHARES.equals(tableID)) { forPluginDataSourceType = ShareResource.class; } init(forPluginDataSourceType, tableID, columnID); } /** Create a column object for the specified table. * * @param tableID table in which the column belongs to * @param columnID name/id of the column */ public TableColumnImpl(Class forDataSourceType, String tableID, String columnID) { init(forDataSourceType, tableID, columnID); } private void init(Class forDataSourceType, String tableID, String columnID) { this.forPluginDataSourceType = forDataSourceType; sTableID = tableID; sName = columnID; iType = TYPE_TEXT_ONLY; iWidth = 50; iAlignment = ALIGN_LEAD; bColumnAdded = false; bCoreDataSource = false; iInterval = INTERVAL_INVALID_ONLY; iConsecutiveErrCount = 0; lLastSortValueChange = 0; bVisible = false; iMinWidth = 16; iPosition = POSITION_INVISIBLE; int iSortDirection = COConfigurationManager.getIntParameter(CFG_SORTDIRECTION); bSortAscending = iSortDirection == 1 ? false : true; } public void initialize(int iAlignment, int iPosition, int iWidth, int iInterval) { if (bColumnAdded) { throw (new UIRuntimeException("Can't set properties. Column '" + sName + " already added")); } this.iAlignment = iAlignment; setPosition(iPosition); this.iWidth = this.iDefaultWidth = iWidth; this.iMinWidth = 16; this.iInterval = iInterval; } public void initialize(int iAlignment, int iPosition, int iWidth) { if (bColumnAdded) { throw (new UIRuntimeException("Can't set properties. Column '" + sName + " already added")); } this.iAlignment = iAlignment; setPosition(iPosition); this.iWidth = this.iDefaultWidth = iWidth; this.iMinWidth = 16; } public String getName() { return sName; } public String getTableID() { return sTableID; } public void setType(int type) { if (bColumnAdded) { throw (new UIRuntimeException("Can't set properties. Column '" + sName + " already added")); } iType = type; } public int getType() { return iType; } public void setWidth(int width) { if (width == iWidth || width < 0) { return; } if (iMinWidth > 0 && width < iMinWidth) { return; } if (iMaxWidth > 0 && width > iMaxWidth) { if (width == iMaxWidth) { return; } width = iMaxWidth; } if (iMinWidth < 0) { iMinWidth = width; } // if (iPreferredWidth <= 0) { // iPreferredWidth = iWidth; // } iWidth = width; if (iDefaultWidth == 0) { iDefaultWidth = width; } if (bColumnAdded && bVisible) { triggerColumnSizeChange(); } } public void triggerColumnSizeChange() { TableStructureEventDispatcher tsed = TableStructureEventDispatcher.getInstance(sTableID); tsed.columnSizeChanged(this); if (iType == TYPE_GRAPHIC) { invalidateCells(); } } public int getWidth() { return iWidth; } public void setPosition(int position) { if (bColumnAdded) { throw (new UIRuntimeException("Can't set properties. Column '" + sName + " already added")); } if (iPosition == POSITION_INVISIBLE && position != POSITION_INVISIBLE) { setVisible(true); } iPosition = position; if (position == POSITION_INVISIBLE) { setVisible(false); } } public int getPosition() { return iPosition; } public void setAlignment(int alignment) { if (bColumnAdded) { throw (new UIRuntimeException("Can't set properties. Column '" + sName + " already added")); } iAlignment = alignment; } public int getAlignment() { return iAlignment; } public void addCellRefreshListener(TableCellRefreshListener listener) { try { this_mon.enter(); if (cellRefreshListeners == null) { cellRefreshListeners = new ArrayList(1); } cellRefreshListeners.add(listener); //System.out.println(this + " :: addCellRefreshListener " + listener + ". " + cellRefreshListeners.size()); } finally { this_mon.exit(); } } public List getCellRefreshListeners() { try { this_mon.enter(); if (cellRefreshListeners == null) { return (new ArrayList(0)); } return (new ArrayList(cellRefreshListeners)); } finally { this_mon.exit(); } } public void removeCellRefreshListener(TableCellRefreshListener listener) { try { this_mon.enter(); if (cellRefreshListeners == null) { return; } cellRefreshListeners.remove(listener); } finally { this_mon.exit(); } } public boolean hasCellRefreshListener() { return cellRefreshListeners != null && cellRefreshListeners.size() > 0; } public void setRefreshInterval(int interval) { iInterval = interval; } public int getRefreshInterval() { return iInterval; } public void addCellAddedListener(TableCellAddedListener listener) { try { this_mon.enter(); if (cellAddedListeners == null) { cellAddedListeners = new ArrayList(1); } cellAddedListeners.add(listener); } finally { this_mon.exit(); } } public void addCellOtherListener(String listenerID, Object listener) { try { this_mon.enter(); if (mapOtherCellListeners == null) { mapOtherCellListeners = new HashMap(1); } List list = (List) mapOtherCellListeners.get(listenerID); if (list == null) { list = new ArrayList(1); mapOtherCellListeners.put(listenerID, list); } list.add(listener); } finally { this_mon.exit(); } } public Object[] getCellOtherListeners(String listenerID) { if (mapOtherCellListeners == null) { return null; } List list = (List) mapOtherCellListeners.get(listenerID); if (list == null) { return null; } return list.toArray(); } // @see com.aelitis.azureus.ui.common.table.TableColumnCore#hasCellOtherListeners(java.lang.String) public boolean hasCellOtherListeners(String listenerID) { return mapOtherCellListeners != null && mapOtherCellListeners.get(listenerID) != null; } public List getCellAddedListeners() { try { this_mon.enter(); if (cellAddedListeners == null) { return (new ArrayList(0)); } return (new ArrayList(cellAddedListeners)); } finally { this_mon.exit(); } } public void removeCellAddedListener(TableCellAddedListener listener) { try { this_mon.enter(); if (cellAddedListeners == null) { return; } cellAddedListeners.remove(listener); } finally { this_mon.exit(); } } public void addCellDisposeListener(TableCellDisposeListener listener) { try { this_mon.enter(); if (cellDisposeListeners == null) { cellDisposeListeners = new ArrayList(1); } cellDisposeListeners.add(listener); } finally { this_mon.exit(); } } public void removeCellDisposeListener(TableCellDisposeListener listener) { try { this_mon.enter(); if (cellDisposeListeners == null) { return; } cellDisposeListeners.remove(listener); } finally { this_mon.exit(); } } public void addCellToolTipListener(TableCellToolTipListener listener) { try { this_mon.enter(); if (cellToolTipListeners == null) { cellToolTipListeners = new ArrayList(1); } cellToolTipListeners.add(listener); } finally { this_mon.exit(); } } public void removeCellToolTipListener(TableCellToolTipListener listener) { try { this_mon.enter(); if (cellToolTipListeners == null) { return; } cellToolTipListeners.remove(listener); } finally { this_mon.exit(); } } public void addCellMouseListener(TableCellMouseListener listener) { try { this_mon.enter(); if (cellMouseListeners == null) { cellMouseListeners = new ArrayList(1); } cellMouseListeners.add(listener); } finally { this_mon.exit(); } } public void removeCellMouseListener(TableCellMouseListener listener) { try { this_mon.enter(); if (cellMouseListeners == null) { return; } cellMouseListeners.remove(listener); } finally { this_mon.exit(); } } public boolean hasCellMouseMoveListener() { return cellMouseMoveListeners != null && cellMouseMoveListeners.size() > 0; } public void addCellMouseMoveListener(TableCellMouseMoveListener listener) { try { this_mon.enter(); if (cellMouseMoveListeners == null) { cellMouseMoveListeners = new ArrayList(1); } cellMouseMoveListeners.add(listener); } finally { this_mon.exit(); } } public void removeCellMouseMoveListener(TableCellMouseMoveListener listener) { try { this_mon.enter(); if (cellMouseMoveListeners == null) { return; } cellMouseMoveListeners.remove(listener); } finally { this_mon.exit(); } } public void addCellVisibilityListener(TableCellVisibilityListener listener) { try { this_mon.enter(); if (cellVisibilityListeners == null) { cellVisibilityListeners = new ArrayList(1); } cellVisibilityListeners.add(listener); } finally { this_mon.exit(); } } public void removeCellVisibilityListener(TableCellVisibilityListener listener) { try { this_mon.enter(); if (cellVisibilityListeners == null) { return; } cellVisibilityListeners.remove(listener); } finally { this_mon.exit(); } } public List getColumnExtraInfoListeners() { try { this_mon.enter(); if (columnExtraInfoListeners == null) { return (new ArrayList(0)); } return (new ArrayList(columnExtraInfoListeners)); } finally { this_mon.exit(); } } public void addColumnExtraInfoListener(TableColumnExtraInfoListener listener) { try { this_mon.enter(); if (columnExtraInfoListeners == null) { columnExtraInfoListeners = new ArrayList(1); } columnExtraInfoListeners.add(listener); } finally { this_mon.exit(); } } public void removeColumnExtraInfoListener(TableColumnExtraInfoListener listener) { try { this_mon.enter(); if (columnExtraInfoListeners == null) { return; } columnExtraInfoListeners.remove(listener); } finally { this_mon.exit(); } } public void invalidateCells() { TableStructureEventDispatcher tsed = TableStructureEventDispatcher.getInstance(sTableID); tsed.columnInvalidate(this); } public void invalidateCell(Object data_source) { TableStructureEventDispatcher tsed = TableStructureEventDispatcher.getInstance(sTableID); tsed.cellInvalidate(this, data_source); } public void addListeners(Object listenerObject) { if (listenerObject instanceof TableCellDisposeListener) { addCellDisposeListener((TableCellDisposeListener) listenerObject); } if (listenerObject instanceof TableCellRefreshListener) { addCellRefreshListener((TableCellRefreshListener) listenerObject); } if (listenerObject instanceof TableCellToolTipListener) { addCellToolTipListener((TableCellToolTipListener) listenerObject); } if (listenerObject instanceof TableCellAddedListener) { addCellAddedListener((TableCellAddedListener) listenerObject); } if (listenerObject instanceof TableCellMouseMoveListener) { addCellMouseMoveListener((TableCellMouseMoveListener) listenerObject); } if (listenerObject instanceof TableCellMouseListener) { addCellMouseListener((TableCellMouseListener) listenerObject); } if (listenerObject instanceof TableCellVisibilityListener) { addCellVisibilityListener((TableCellVisibilityListener) listenerObject); } if (listenerObject instanceof TableColumnExtraInfoListener) { addColumnExtraInfoListener((TableColumnExtraInfoListener) listenerObject); } } /* Start of not plugin public API functions */ ////////////////////////////////////////////// public void setColumnAdded(boolean bAdded) { bColumnAdded = bAdded; } public boolean getColumnAdded() { return bColumnAdded; } public void setUseCoreDataSource(boolean bCoreDataSource) { this.bCoreDataSource = bCoreDataSource; } public boolean getUseCoreDataSource() { return bCoreDataSource; } public void invokeCellRefreshListeners(TableCell cell, boolean fastRefresh) throws Throwable { //System.out.println(this + " :: invokeCellRefreshListeners" + cellRefreshListeners); if (cellRefreshListeners == null) { return; } Throwable firstError = null; //System.out.println(this + " :: invokeCellRefreshListeners" + cellRefreshListeners.size()); for (int i = 0; i < cellRefreshListeners.size(); i++) { TableCellRefreshListener l = (TableCellRefreshListener)cellRefreshListeners.get(i); try { if(l instanceof TableCellLightRefreshListener) ((TableCellLightRefreshListener)l).refresh(cell, fastRefresh); else l.refresh(cell); } catch (Throwable e) { if (firstError == null) { firstError = e; } Debug.printStackTrace(e); } } if (firstError != null) { throw firstError; } } public void invokeCellAddedListeners(TableCell cell) { if (cellAddedListeners == null) { return; } for (int i = 0; i < cellAddedListeners.size(); i++) { try { ((TableCellAddedListener) (cellAddedListeners.get(i))).cellAdded(cell); } catch (Throwable e) { Debug.printStackTrace(e); } } } public void invokeCellDisposeListeners(TableCell cell) { if (cellDisposeListeners == null) { return; } for (int i = 0; i < cellDisposeListeners.size(); i++) { try { ((TableCellDisposeListener) (cellDisposeListeners.get(i))).dispose(cell); } catch (Throwable e) { Debug.printStackTrace(e); } } } public void invokeCellToolTipListeners(TableCellCore cell, int type) { if (cellToolTipListeners == null) { return; } if (type == TableCellCore.TOOLTIPLISTENER_HOVER) { for (int i = 0; i < cellToolTipListeners.size(); i++) { try { ((TableCellToolTipListener) (cellToolTipListeners.get(i))).cellHover(cell); } catch (Throwable e) { Debug.printStackTrace(e); } } } else { for (int i = 0; i < cellToolTipListeners.size(); i++) { try { ((TableCellToolTipListener) (cellToolTipListeners.get(i))).cellHoverComplete(cell); } catch (Throwable e) { Debug.printStackTrace(e); } } } } public void invokeCellMouseListeners(TableCellMouseEvent event) { ArrayList listeners = event.eventType == TableCellMouseEvent.EVENT_MOUSEMOVE ? cellMouseMoveListeners : this.cellMouseListeners; if (listeners == null) { return; } for (int i = 0; i < listeners.size(); i++) { try { TableCellMouseListener l = (TableCellMouseListener) (listeners.get(i)); l.cellMouseTrigger(event); } catch (Throwable e) { Debug.printStackTrace(e); } } } public void invokeCellVisibilityListeners(TableCellCore cell, int visibility) { if (cellVisibilityListeners == null) { return; } for (int i = 0; i < cellVisibilityListeners.size(); i++) { try { TableCellVisibilityListener l = (TableCellVisibilityListener) (cellVisibilityListeners.get(i)); l.cellVisibilityChanged(cell, visibility); } catch (Throwable e) { Debug.printStackTrace(e); } } } public void setPositionNoShift(int position) { //if (iPosition < 0 && position >= 0) { // setVisible(true); //} iPosition = position; //if (position < 0) { // setVisible(false); //} } public Object getUserData(String key) { if(userData != null) return userData.get(key); return null; } public void setUserData(String key, Object value) { if(userData == null) userData = new LightHashMap(2); userData.put(key, value); } public void removeUserData(String key) { if(userData == null) return; userData.remove(key); if(userData.size() < 1) userData = null; } public void remove() { removed = true; TableColumnManager.getInstance().removeColumns( new TableColumnCore[]{ this }); TableStructureEventDispatcher tsed = TableStructureEventDispatcher.getInstance(sTableID); tsed.tableStructureChanged(true, forPluginDataSourceType); } public boolean isRemoved() { return( removed ); } public final void loadSettings(Map mapSettings) { // Format: Key = [TableID].column.[columnname] // Value[] = { visible, width, position, autotooltip, sortorder } String itemPrefix = "Column." + sName; String oldItemPrefix = "Table." + sTableID + "." + sName; Object object = mapSettings.get(itemPrefix); Object[] list; if (object instanceof List) { list = ((List) object).toArray(); } else { list = new String[0]; } int pos = 0; if (list.length >= (pos + 1) && (list[pos] instanceof Number)) { boolean vis = ((Number) list[pos]).intValue() == 1; setVisible(vis); } pos++; if (list.length >= (pos + 1) && (list[pos] instanceof Number)) { int position = ((Number) list[pos]).intValue(); setPositionNoShift(position); } else { int position = COConfigurationManager.getIntParameter(oldItemPrefix + ".position", iPosition); if (iPosition == POSITION_INVISIBLE && position != POSITION_INVISIBLE) { setVisible(true); } setPositionNoShift(position); if (position == POSITION_INVISIBLE) { setVisible(false); } } pos++; if (list.length >= (pos + 1) && (list[pos] instanceof Number)) { int width = ((Number) list[pos]).intValue(); setWidth(width); } else { setWidth(COConfigurationManager.getIntParameter(oldItemPrefix + ".width", iWidth)); } pos++; if (list.length >= (pos + 1) && (list[pos] instanceof Number)) { boolean autoTooltip = ((Number) list[pos]).intValue() == 1; setAutoTooltip(autoTooltip); } else { setAutoTooltip(COConfigurationManager.getBooleanParameter(oldItemPrefix + ".auto_tooltip", auto_tooltip)); } pos++; if (list.length >= (pos + 1) && (list[pos] instanceof Number)) { int sortOrder = ((Number) list[pos]).intValue(); if (sortOrder >= 0) { // dont call setSordOrder, since it will change lLastSortValueChange // which we shouldn't do if we aren't the sorting column bSortAscending = sortOrder == 1; } } pos++; if (list.length >= (pos + 1) && (list[pos] instanceof Map)) { userData = (Map)list[pos]; if(userData.size() < 1) userData = null; } postConfigLoad(); } /* (non-Javadoc) * @see org.gudy.azureus2.plugins.ui.tables.TableColumn#postLoad() */ public void postConfigLoad() {} public void preConfigSave() {} public final void saveSettings(Map mapSettings) { preConfigSave(); if (mapSettings == null) { mapSettings = TableColumnManager.getInstance().getTableConfigMap(sTableID); if (mapSettings == null) { return; } } String sItemPrefix = "Column." + sName; mapSettings.put(sItemPrefix, Arrays.asList(new Object[] { new Integer(bVisible ? 1 : 0), new Integer(iPosition), new Integer(iWidth), new Integer(auto_tooltip ? 1 : 0), new Integer(lLastSortValueChange == 0 ? -1 : (bSortAscending ? 1 : 0)), userData != null ? userData : Collections.EMPTY_MAP })); // cleanup old config sItemPrefix = "Table." + sTableID + "." + sName; if (COConfigurationManager.hasParameter(sItemPrefix + ".width", true)) { COConfigurationManager.removeParameter(sItemPrefix + ".position"); COConfigurationManager.removeParameter(sItemPrefix + ".width"); COConfigurationManager.removeParameter(sItemPrefix + ".auto_tooltip"); } } public String getTitleLanguageKey() { try { this_mon.enter(); if (sTitleLanguageKey == null) { sTitleLanguageKey = sTableID + ".column." + sName; if (MessageText.keyExists(sTitleLanguageKey)) { return sTitleLanguageKey; } String sKeyPrefix; // Support "Old Style" language keys, which have a prefix of TableID + "View." // Also, "MySeeders" is actually stored in "MyTorrents".. sKeyPrefix = (sTableID.equals(TableManager.TABLE_MYTORRENTS_COMPLETE) ? TableManager.TABLE_MYTORRENTS_INCOMPLETE : sTableID) + "View."; if (MessageText.keyExists(sKeyPrefix + sName)) { sTitleLanguageKey = sKeyPrefix + sName; return sTitleLanguageKey; } // The "all peers" view should just share the same peer columns, so reuse them. if (sTableID.equals(TableManager.TABLE_ALL_PEERS)) { sKeyPrefix = TableManager.TABLE_TORRENT_PEERS + ".column."; if (MessageText.keyExists(sKeyPrefix + sName)) { sTitleLanguageKey = sKeyPrefix + sName; return sTitleLanguageKey; } // Or try "PeersView". sKeyPrefix = "PeersView."; if (MessageText.keyExists(sKeyPrefix + sName)) { sTitleLanguageKey = sKeyPrefix + sName; return sTitleLanguageKey; } } // Try a generic one of "TableColumn." + columnid sKeyPrefix = "TableColumn.header."; if (MessageText.keyExists(sKeyPrefix + sName)) { sTitleLanguageKey = sKeyPrefix + sName; return sTitleLanguageKey; } // another "Old Style" // 99% sure this can be removed now, but why risk it.. sKeyPrefix = "MyTorrentsView." + sName; //System.out.println(sKeyPrefix + ";" + MessageText.getString(sKeyPrefix)); if (MessageText.keyExists(sKeyPrefix)) { sTitleLanguageKey = sKeyPrefix; return sTitleLanguageKey; } } return sTitleLanguageKey; } finally { this_mon.exit(); } } public int getConsecutiveErrCount() { return iConsecutiveErrCount; } public void setConsecutiveErrCount(int iCount) { iConsecutiveErrCount = iCount; } public void removeContextMenuItem(TableContextMenuItem menuItem) { if (menuItemsColumn != null) { menuItemsColumn.remove(menuItem); } if (menuItemsHeader != null) { menuItemsColumn.remove(menuItem); } } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#addContextMenuItem(java.lang.String, int) public TableContextMenuItem addContextMenuItem(String key) { return addContextMenuItem(key, MENU_STYLE_COLUMN_DATA); } public TableContextMenuItem addContextMenuItem(String key, int menuStyle) { ArrayList menuItems; if (menuStyle == MENU_STYLE_COLUMN_DATA) { if (menuItemsColumn == null) { menuItemsColumn = new ArrayList(); } menuItems = menuItemsColumn; } else { if (menuItemsHeader == null) { menuItemsHeader = new ArrayList(); } menuItems = menuItemsHeader; } // Hack.. should be using our own implementation.. TableContextMenuItemImpl item = new TableContextMenuItemImpl(null,"", key); menuItems.add(item); return item; } public TableContextMenuItem[] getContextMenuItems(int menuStyle) { ArrayList menuItems; if (menuStyle == MENU_STYLE_COLUMN_DATA) { menuItems = menuItemsColumn; } else { menuItems = menuItemsHeader; } if (menuItems == null) { return new TableContextMenuItem[0]; } return menuItems.toArray(new TableContextMenuItem[0]); } public boolean isObfusticated() { return bObfusticateData; } public void setObfustication(boolean hideData) { bObfusticateData = hideData; } public long getLastSortValueChange() { if (bSortValueLive) { return SystemTime.getCurrentTime(); } return lLastSortValueChange; } public void setLastSortValueChange(long lastSortValueChange) { lLastSortValueChange = lastSortValueChange; } public boolean isSortValueLive() { return bSortValueLive; } public void setSortValueLive(boolean live) { // if (live && !bSortValueLive) { // System.out.println("Setting " + sTableID + ": " + sName + " to live sort value"); // } bSortValueLive = live; } public void addRefreshTime(long ms) { if (ms == 0) { lStatsRefreshZeroCount++; } else { lStatsRefreshTotalTime += ms; lStatsRefreshCount++; } } public void generateDiagnostics(IndentWriter writer) { writer.println("Column " + sTableID + ":" + sName + (bSortValueLive ? " (Live Sort)" : "")); try { writer.indent(); if (lStatsRefreshCount > 0) { writer.println("Avg refresh time (" + lStatsRefreshCount + " samples): " + (lStatsRefreshTotalTime / lStatsRefreshCount) + " (" + lStatsRefreshZeroCount + " zero ms refreshes not included)"); } writer.println("Listeners: refresh=" + getListCountString(cellRefreshListeners) + "; dispose=" + getListCountString(cellDisposeListeners) + "; mouse=" + getListCountString(cellMouseListeners) + "; mm=" + getListCountString(cellMouseMoveListeners) + "; vis=" + getListCountString(cellVisibilityListeners) + "; added=" + getListCountString(cellAddedListeners) + "; tooltip=" + getListCountString(cellToolTipListeners)); writer.println("lLastSortValueChange=" + lLastSortValueChange); } catch (Exception e) { } finally { writer.exdent(); } } private String getListCountString(List l) { if (l == null) { return "-0"; } return "" + l.size(); } public void setTableID(String tableID) { sTableID = tableID; } // @see java.util.Comparator#compare(T, T) public int compare(Object arg0, Object arg1) { TableCellCore cell0 = ((TableRowCore) arg0).getTableCellCore(sName); TableCellCore cell1 = ((TableRowCore) arg1).getTableCellCore(sName); Comparable c0 = (cell0 == null) ? "" : cell0.getSortValue(); Comparable c1 = (cell1 == null) ? "" : cell1.getSortValue(); // Put nulls and empty strings at bottom. boolean c0_is_null = (c0 == null || c0.equals("")); boolean c1_is_null = (c1 == null || c1.equals("")); if (c1_is_null) { return (c0_is_null) ? 0 : -1; } else if (c0_is_null) { return 1; } try { boolean c0isString = c0 instanceof String; boolean c1isString = c1 instanceof String; if (c0isString && c1isString) { if (bSortAscending) { return ((String) c0).compareToIgnoreCase((String) c1); } return ((String) c1).compareToIgnoreCase((String) c0); } int val; if (c0isString && !c1isString) { val = -1; } else if (c1isString && !c0isString) { val = 1; } else { val = c1.compareTo(c0); } return bSortAscending ? -val : val; } catch (ClassCastException e) { int c0_index = (cell0 == null) ? -999 : cell0.getTableRowCore().getIndex(); int c1_index = (cell1 == null) ? -999 : cell1.getTableRowCore().getIndex(); System.err.println("Can't compare " + c0.getClass().getName() + "(" + c0.toString() + ") from row #" + c0_index + " to " + c1.getClass().getName() + "(" + c1.toString() + ") from row #" + c1_index + " while sorting column " + sName); e.printStackTrace(); return 0; } } /** * @param bAscending The bAscending to set. */ public void setSortAscending(boolean bAscending) { if (this.bSortAscending == bAscending) { return; } setLastSortValueChange(SystemTime.getCurrentTime()); this.bSortAscending = bAscending; } /** * @return Returns the bAscending. */ public boolean isSortAscending() { return bSortAscending; } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#getMinWidth() public int getMinWidth() { if (iMinWidth < 0) { return iWidth; } return iMinWidth; } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setMinWidth(int) public void setMinWidth(int minwidth) { if (minwidth > iMaxWidth && iMaxWidth >= 0) { iMaxWidth = minwidth; } if (iPreferredWidth > 0 && iPreferredWidth < minwidth) { iPreferredWidth = minwidth; } iMinWidth = minwidth; if (iWidth < minwidth) { setWidth(minwidth); } } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#getMaxWidth() public int getMaxWidth() { return iMaxWidth; } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setMaxWidth(int) public void setMaxWidth(int maxwidth) { if (maxwidth >= 0 && maxwidth < iMinWidth) { iMinWidth = maxwidth; } if (iPreferredWidth > maxwidth) { iPreferredWidth = maxwidth; } iMaxWidth = maxwidth; if (maxwidth >= 0 && iWidth > iMaxWidth) { setWidth(maxwidth); } } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setWidthLimits(int, int) public void setWidthLimits(int min, int max) { setMinWidth(min); setMaxWidth(max); } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#isVisible() public boolean isVisible() { return bVisible; } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setVisible(boolean) public void setVisible(boolean visible) { if (bVisible == visible) { return; } //System.out.println("set " + sTableID + "/" + sName + " to " + visible // + " via " + Debug.getCompressedStackTrace()); bVisible = visible; if (bVisible && iPosition == POSITION_INVISIBLE) { iPosition = POSITION_LAST; } invalidateCells(); } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#isMaxWidthAuto() public boolean isMaxWidthAuto() { return bMaxWidthAuto; } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setMaxWidthAuto(boolean) public void setMaxWidthAuto(boolean automaxwidth) { bMaxWidthAuto = automaxwidth; } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#isMinWidthAuto() public boolean isMinWidthAuto() { return bWidthAuto; } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setMinWidthAuto(boolean) public void setMinWidthAuto(boolean autominwidth) { bWidthAuto = autominwidth; } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#getPreferredWidth() public int getPreferredWidth() { return iPreferredWidth; } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setPreferredWidthAuto(boolean) public void setPreferredWidthAuto(boolean auto) { bPreferredWidthAuto = auto; } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#isPreferredWidthAuto() public boolean isPreferredWidthAuto() { return bPreferredWidthAuto; } // dead public void setPreferredWidthMax(int maxprefwidth) { iPreferredWidthMax = maxprefwidth; if (iPreferredWidth > iPreferredWidthMax) { setPreferredWidth(maxprefwidth); } } // dead public int getPreferredWidthMax() { return iPreferredWidthMax; } // @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setPreferredWidth(int) public void setPreferredWidth(int width) { if (iPreferredWidthMax > 0 && width > iPreferredWidthMax) { width = iPreferredWidthMax; } if (width < iMinWidth) { iPreferredWidth = iMinWidth; } else if (iMaxWidth > 0 && width > iMaxWidth) { iPreferredWidth = iMaxWidth; } else { iPreferredWidth = width; } if (bColumnAdded && bVisible) { triggerColumnSizeChange(); } } public void setAutoTooltip(boolean auto_tooltip) { this.auto_tooltip = auto_tooltip; } public boolean doesAutoTooltip() { return this.auto_tooltip; } public boolean isInplaceEdit() { return editable; } public void setInplaceEdit(boolean editable) { this.editable = editable; } public boolean inplaceValueSet(TableCell cell, String value, boolean finalEdit) { return false; } public Class getForDataSourceType() { return forPluginDataSourceType; } public void setForDataSourceType(Class forDataSourceType) { this.forPluginDataSourceType = forDataSourceType; } public void reset() { if (iDefaultWidth != 0) { setWidth(iDefaultWidth); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/impl/TableViewImpl.java0000644000175000017500000001507011267524616026065 0ustar adrianadrian/** * */ package com.aelitis.azureus.ui.common.table.impl; import java.util.Iterator; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.ui.common.table.*; /** * @author TuxPaper * @created Feb 6, 2007 */ public abstract class TableViewImpl implements TableView { // List of DataSourceChangedListener private CopyOnWriteList listenersDataSourceChanged = new CopyOnWriteList(); private CopyOnWriteList listenersSelection = new CopyOnWriteList(); private CopyOnWriteList listenersLifeCycle = new CopyOnWriteList(); private CopyOnWriteList listenersRefresh = new CopyOnWriteList(); private CopyOnWriteList listenersCountChange = new CopyOnWriteList(1); private Object parentDataSource; public void addSelectionListener(TableSelectionListener listener, boolean bFireSelection) { listenersSelection.add(listener); if (bFireSelection) { TableRowCore[] rows = getSelectedRows(); listener.selected(rows); listener.focusChanged(getFocusedRow()); } } // @see com.aelitis.azureus.ui.common.table.TableView#addTableDataSourceChangedListener(com.aelitis.azureus.ui.common.table.TableDataSourceChangedListener, boolean) public void addTableDataSourceChangedListener( TableDataSourceChangedListener l, boolean trigger) { listenersDataSourceChanged.add(l); if (trigger) { l.tableDataSourceChanged(parentDataSource); } } // @see com.aelitis.azureus.ui.common.table.TableView#removeTableDataSourceChangedListener(com.aelitis.azureus.ui.common.table.TableDataSourceChangedListener) public void removeTableDataSourceChangedListener( TableDataSourceChangedListener l) { listenersDataSourceChanged.remove(l); } // @see com.aelitis.azureus.ui.common.table.TableView#setParentDataSource(java.lang.Object) public void setParentDataSource(Object newDataSource) { parentDataSource = newDataSource; Object[] listeners = listenersDataSourceChanged.toArray(); for (int i = 0; i < listeners.length; i++) { TableDataSourceChangedListener l = (TableDataSourceChangedListener) listeners[i]; l.tableDataSourceChanged(newDataSource); } } /** * @param selectedRows */ protected void triggerDefaultSelectedListeners(TableRowCore[] selectedRows, int keyMask) { for (Iterator iter = listenersSelection.iterator(); iter.hasNext();) { TableSelectionListener l = (TableSelectionListener) iter.next(); l.defaultSelected(selectedRows, keyMask); } } /** * @param eventType */ protected void triggerLifeCycleListener(int eventType) { Object[] listeners = listenersLifeCycle.toArray(); if (eventType == TableLifeCycleListener.EVENT_INITIALIZED) { for (int i = 0; i < listeners.length; i++) { TableLifeCycleListener l = (TableLifeCycleListener) listeners[i]; try { l.tableViewInitialized(); } catch (Exception e) { Debug.out(e); } } } else { for (int i = 0; i < listeners.length; i++) { TableLifeCycleListener l = (TableLifeCycleListener) listeners[i]; try { l.tableViewDestroyed(); } catch (Exception e) { Debug.out(e); } } } } protected void triggerSelectionListeners(TableRowCore[] rows) { if (rows == null || rows.length == 0) { return; } Object[] listeners = listenersSelection.toArray(); for (int i = 0; i < listeners.length; i++) { TableSelectionListener l = (TableSelectionListener) listeners[i]; l.selected(rows); } } protected void triggerDeselectionListeners(TableRowCore[] rows) { if (rows == null) { return; } Object[] listeners = listenersSelection.toArray(); for (int i = 0; i < listeners.length; i++) { TableSelectionListener l = (TableSelectionListener) listeners[i]; try { l.deselected(rows); } catch (Exception e) { Debug.out(e); } } } protected void triggerMouseEnterExitRow(TableRowCore row, boolean enter) { if (row == null) { return; } Object[] listeners = listenersSelection.toArray(); for (int i = 0; i < listeners.length; i++) { TableSelectionListener l = (TableSelectionListener) listeners[i]; if (enter) { l.mouseEnter(row); } else { l.mouseExit(row); } } } protected void triggerFocusChangedListeners(TableRowCore row) { Object[] listeners = listenersSelection.toArray(); for (int i = 0; i < listeners.length; i++) { TableSelectionListener l = (TableSelectionListener) listeners[i]; l.focusChanged(row); } } /** * */ protected void triggerTableRefreshListeners() { Object[] listeners = listenersRefresh.toArray(); for (int i = 0; i < listeners.length; i++) { TableRefreshListener l = (TableRefreshListener) listeners[i]; l.tableRefresh(); } } // @see com.aelitis.azureus.ui.common.table.TableView#addLifeCycleListener(com.aelitis.azureus.ui.common.table.TableLifeCycleListener) public void addLifeCycleListener(TableLifeCycleListener l) { listenersLifeCycle.add(l); if (!isDisposed()) { l.tableViewInitialized(); } } // @see com.aelitis.azureus.ui.common.table.TableView#addRefreshListener(com.aelitis.azureus.ui.common.table.TableRefreshListener, boolean) public void addRefreshListener(TableRefreshListener l, boolean trigger) { listenersRefresh.add(l); if (trigger) { l.tableRefresh(); } } // @see com.aelitis.azureus.ui.common.table.TableView#addCountChangeListener(com.aelitis.azureus.ui.common.table.TableCountChangeListener) public void addCountChangeListener(TableCountChangeListener listener) { listenersCountChange.add(listener); } public void removeCountChangeListener(TableCountChangeListener listener) { listenersCountChange.remove(listener); } protected void triggerListenerRowAdded(TableRowCore row) { for (Iterator iter = listenersCountChange.iterator(); iter.hasNext();) { TableCountChangeListener l = (TableCountChangeListener) iter.next(); l.rowAdded(row); } } protected void triggerListenerRowRemoved(TableRowCore row) { for (Iterator iter = listenersCountChange.iterator(); iter.hasNext();) { TableCountChangeListener l = (TableCountChangeListener) iter.next(); l.rowRemoved(row); } } public void runForAllRows(TableGroupRowRunner runner) { // put to array instead of synchronised iterator, so that runner can remove TableRowCore[] rows = getRows(); if (runner.run(rows)) { return; } for (int i = 0; i < rows.length; i++) { runner.run(rows[i]); } } }azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableGroupRowRunner.java0000644000175000017500000000073210772026144026336 0ustar adrianadrianpackage com.aelitis.azureus.ui.common.table; /** * Used with {@link TableView#runForSelectedRows} */ public abstract class TableGroupRowRunner { /** Code to run * @param row TableRowCore to run code against */ public void run(TableRowCore row) { } /** * Code to run against multiple rows. * * Return true if this object supports it, false otherwise. * * @param rows * @return */ public boolean run(TableRowCore[] rows) { return false; } } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableDataSourceChangedListener.java0000644000175000017500000000212110566514576030400 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.common.table; /** * @author TuxPaper * @created Feb 2, 2007 * */ public interface TableDataSourceChangedListener { public void tableDataSourceChanged(Object newDataSource); } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableRowCore.java0000644000175000017500000000762611017153542024745 0ustar adrianadrian/** * Copyright (C) 2004-2007 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.common.table; import java.util.List; import org.gudy.azureus2.plugins.ui.tables.TableRow; import org.gudy.azureus2.plugins.ui.tables.TableRowMouseEvent; /** * Core Table Row functions are those available to plugins plus * some core-only functions. The core-only functions are listed here. * * @author TuxPaper * @since 2.0.8.5 2004/May/14 */ public interface TableRowCore extends TableRow { /** Invalidates Row */ public void invalidate(); /** * Delete the row */ public void delete(); /** Refresh all the cells in the row * * @param bDoGraphics Refresh graphic cells to */ public List refresh(boolean bDoGraphics); /** Location of a column has changed * * @param iStartColumn Cells starting at this value may need repainting * * XXX Rename to cellLocationChanged? */ public void locationChanged(int iStartColumn); /** Retrieve the Data Source related to this row * * @param bCoreObject true - return a core object
    * false - return a plugin object * @return the Data Source Object related to the row */ public Object getDataSource(boolean bCoreObject); public int getIndex(); /** Adjust cell height. Don't use if any other column/cell uses setImage() * * @param iHeight new Row Height. Will not reduce row's height (SWT) * @return success level */ public boolean setHeight(int iHeight); /** Retrieve a cell based on the supplied value * * @param field Column name of the cell to be returned * @return TableCellCore object related to this row and the specified column */ public TableCellCore getTableCellCore(String field); /** Retreive whether the row is visible to the user. In SWT, when the table * is not VIRTUAL, all rows are "visible" * * @return visibility state */ public boolean isVisible(); /** * Link the row to a SWT TableItem * * @param newIndex new position row should be * @return false - already linked to that item at that index */ public boolean setTableItem(int newIndex); public boolean setTableItem(int newIndex, boolean isVisible); public void setSelected(boolean bSelected); public boolean isRowDisposed(); public void setUpToDate(boolean upToDate); /** * @param bDoGraphics * @param bVisible */ public List refresh(boolean bDoGraphics, boolean bVisible); /** * like refresh, except a different name to confuse us. */ public void redraw(); /** * @param bEvenIfNotVisible */ public void setAlternatingBGColor(boolean bEvenIfNotVisible); /** * @return */ public TableView getView(); /** * @param event * * @since 3.0.1.7 */ void invokeMouseListeners(TableRowMouseEvent event); /** * * @return * * @since 3.0.4.3 */ public boolean isMouseOver(); /** * @param id * @return * * @since 3.0.4.3 */ Object getData(String id); /** * @param id * @param data * * @since 3.0.4.3 */ void setData(String id, Object data); /** * @param height * @return * * @since 3.0.4.3 */ public boolean setDrawableHeight(int height); } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableCellCore.java0000644000175000017500000001151111066073412025042 0ustar adrianadrian/** * File : TableCellCore.java * Created : 2004/May/14 * * Copyright (C) 2004-2007 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.common.table; import org.gudy.azureus2.plugins.ui.tables.TableCell; import org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent; import org.gudy.azureus2.plugins.ui.tables.TableCellVisibilityListener; /** * Core Table Cell functions are those available to plugins plus * some core-only functions. The core-only functions are listed here. * * @see org.gudy.azureus2.ui.swt.views.table.impl.TableCellImpl */ public interface TableCellCore extends TableCell, Comparable { static final int TOOLTIPLISTENER_HOVER = 0; static final int TOOLTIPLISTENER_HOVERCOMPLETE = 1; public void invalidate(boolean bMustRefresh); /** * Refresh the cell * * @param bDoGraphics Whether to update graphic cells */ public boolean refresh(boolean bDoGraphics); /** * Refresh the cell, including graphic types */ public boolean refresh(); /** * Refresh the cell. This method overide takes a bRowVisible paramater * and a bCellVisible parameter in order to reduce the number of calls to * TableRow.isVisible() and calculations of cell visibility. * * @param bDoGraphics Whether to update graphic cells * @param bRowVisible Assumed visibility state of row * @param bCellVisible Assumed visibility state of the cell */ public boolean refresh(boolean bDoGraphics, boolean bRowVisible, boolean bCellVisible); /** * Refresh the cell. This method override takes a bRowVisible parameter in * order to reduce the number of calls to TableRow.isVisible() in cases where * multiple cells on the same row are being refreshed. * * @param bDoGraphics Whether to update graphic cells * @param bRowVisible Visibility state of row */ public boolean refresh(boolean bDoGraphics, boolean bRowVisible); /** * dispose of the cell */ public void dispose(); /** * Retrieve whether the cell need any paint calls (graphic) * * @return whether the cell needs painting */ public boolean needsPainting(); /** * Location of the cell has changed */ public void locationChanged(); /** * Retrieve the row that this cell belongs to * * @return the row that this cell belongs to */ public TableRowCore getTableRowCore(); /** * Trigger all the tooltip listeners that have been added to this cell * * @param type {@link #TOOLTIPLISTENER_HOVER}, {@link #TOOLTIPLISTENER_HOVERCOMPLETE} */ public void invokeToolTipListeners(int type); /** * Trigger all the mouse listeners that have been addded to this cell * * @param event event to trigger */ public void invokeMouseListeners(TableCellMouseEvent event); /** * Trigger all the visibility listeners that have been added to this cell.
    * * @param visibility See {@link TableCellVisibilityListener}.VISIBILITY_* constants */ public void invokeVisibilityListeners(int visibility, boolean invokeColumnListeners); /** * Sets whether the cell will need updating when it's visible again * * @param upToDate */ public void setUpToDate(boolean upToDate); /** * Returns whether the cell will need updating when it's visible again * * @return */ boolean isUpToDate(); /** * Return the text used when generating diagnostics * * @return */ String getObfusticatedText(); /** * Get the cursor ID we are currently using * * XXX Should NOT be SWT.CURSOR_ constants! * * @return */ public int getCursorID(); /** * Set the cursor ID that should be used for the cell * * @param cursor_hand */ public void setCursorID(int cursorID); /** * * @since 3.0.1.7 */ public boolean isMouseOver(); /** * Returns whether the cell has visually changed since the last refresh call. * Could be used to prevent a refresh, or refresh early. * * @return visually changed since refresh state */ boolean getVisuallyChangedSinceRefresh(); /** * * * @since 3.0.5.3 */ void refreshAsync(); /** * * * @since 3.1.1.1 */ void redraw(); } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableGroupRowVisibilityRunner.java0000644000175000017500000000214510566514576030422 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.common.table; public abstract class TableGroupRowVisibilityRunner { /** Code to run * @param row TableRowCore to run code against */ public void run(TableRowCore row, boolean bVisible) { } } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableCountChangeAdapter.java0000644000175000017500000000262310566514576027074 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.common.table; /** * @author TuxPaper * @created Oct 25, 2006 * */ public class TableCountChangeAdapter implements TableCountChangeListener { // @see com.aelitis.azureus.ui.common.table.TableCountChangeListener#rowAdded(com.aelitis.azureus.ui.swt.views.list.ListRow) public void rowAdded(TableRowCore row) { } // @see com.aelitis.azureus.ui.common.table.TableCountChangeListener#rowRemoved(com.aelitis.azureus.ui.swt.views.list.ListRow) public void rowRemoved(TableRowCore row) { } } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableLifeCycleListener.java0000644000175000017500000000225110566514576026737 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.common.table; /** * @author TuxPaper * @created Feb 2, 2007 * */ public interface TableLifeCycleListener { public final int EVENT_INITIALIZED = 0; public final int EVENT_DESTROYED = 1; public void tableViewInitialized(); public void tableViewDestroyed(); } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableStructureModificationListener.java0000644000175000017500000000264011167275622031422 0ustar adrianadrian/** * File : ITableStructureModificationListener.java * Created : 26 nov. 2003 * By : Olivier * * Copyright (C) 2004-2007 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.common.table; /** * @author Olivier * */ public interface TableStructureModificationListener { void tableStructureChanged(boolean columnAddedOrRemoved, Class forPluginDataSourceType ); void columnOrderChanged(int[] iPositions); void columnSizeChanged(TableColumnCore tableColumn); void columnInvalidate(TableColumnCore tableColumn); void cellInvalidate(TableColumnCore tableColumn, T data_source); } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableColumnCore.java0000644000175000017500000001735211271456442025437 0ustar adrianadrian/** * Copyright (C) 2004-2007 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.common.table; import java.util.Comparator; import java.util.List; import java.util.Map; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.plugins.ui.tables.*; /** * Core Table Column functions are those available to plugins plus * some core-only functions. The core-only functions are listed here. * * @see TableColumnManager */ public interface TableColumnCore extends TableColumn, Comparator { /** * Set the internal flag specifying whether the column has been added to the * TableColumnManager. Some functions can not be run after a column has been * added. * * @param bAdded true - Column has been added
    * false - Column has not been added * * @since 2.1.0.0 */ public void setColumnAdded(boolean bAdded); /** * Retrieve whether the column has been added to the TableColumnManager * * @return true - Column has been added
    * false - Column has not been added * * @since 2.1.0.0 */ public boolean getColumnAdded(); /** * Changes what {@link TableCellCore.getDataSource()} and * {@link TableRowCore.getDataSource()} return. * * @param bCoreDataSource true - returns a core object
    * false - returns a plugin object (if available) * * @since 2.1.0.0 */ public void setUseCoreDataSource(boolean bCoreDataSource); /** * Retrieve whether a core or plugin object is sent via getDataSource() * * @return true - returns a core object
    * false - returns a plugin object (if available) * * @since 2.1.0.0 */ public boolean getUseCoreDataSource(); /** * Send a refresh trigger to all listeners stored in TableColumn * * @param cell the cell is being refreshed * @throws Throwable * * @since 2.1.0.0 */ public void invokeCellRefreshListeners(TableCell cell, boolean fastRefresh) throws Throwable; /** * Retrieve all the refresh listeners for the cell * * @return Cell refresh listeners * * @since 2.5.0.0 */ public List getCellRefreshListeners(); /** * Send a cellAdded trigger to all listeners stored in TableColumn * * @param cell the cell is being added * * @since 2.1.0.0 */ public void invokeCellAddedListeners(TableCell cell); /** * Retreive all the Cell Added listeners * * @return cell added listeners for this cell * * @since 2.5.0.0 */ public List getCellAddedListeners(); /** * Send a dispose trigger to all listeners stored in TableColumn * * @param cell the cell is being disposed * * @since 2.1.0.0 */ public void invokeCellDisposeListeners(TableCell cell); /** * Send a tool tip event to the tool tip listeners * * @param cell Cell to get the tool tip event * @param type * * @since 2.1.0.2 */ public void invokeCellToolTipListeners(TableCellCore cell, int type); /** * Send a mouse event to the cell mouse listeners * * @param event Mouse Event to send * * @since 2.4.0.0 */ public void invokeCellMouseListeners(TableCellMouseEvent event); /** * Send a visibility event to the cell's visibility listeners * * @param visibility Visibility state * * @since 2.5.0.2 */ public void invokeCellVisibilityListeners(TableCellCore cell, int visibility); /** * Sets the position of the column without adjusting the other columns. * This will cause duplicate columns, and is only usefull if you are * adjusting the positions of multiple columns at once. * * @param position new position (0 based) * * @see TableColumnManager.ensureIntegrity() * * @since 2.1.0.0 */ public void setPositionNoShift(int position); /** * Load width and position settings from config. * @param mapSettings map to place settings into * * @since 2.1.0.0 */ public void loadSettings(Map mapSettings); /** * Save width and position settings to config. * @param mapSettings map to place settings into * * @since 2.1.0.0 */ public void saveSettings(Map mapSettings); /** * Returns the key in the properties bundle that has the title of the * column. * * @return Title's language key */ public String getTitleLanguageKey(); /** * @return # of consecutive errors * * @since 2.1.0.0 */ public int getConsecutiveErrCount(); /** * @param iCount # of consecutive errors * * @since 2.1.0.0 */ public void setConsecutiveErrCount(int iCount); /** * @param menuItem * * @since 2.1.0.0 */ public void removeContextMenuItem(TableContextMenuItem menuItem); /** * * @return * * @since 2.1.0.0 */ public TableContextMenuItem[] getContextMenuItems(int menuStyle); /** * @return * * @since 2.5.0.0 */ boolean hasCellRefreshListener(); /** * @return * * @since 2.5.0.0 */ long getLastSortValueChange(); /** * @param lastSortValueChange * * @since 2.5.0.0 */ void setLastSortValueChange(long lastSortValueChange); /** * @param live * * @since 2.5.0.0 */ public void setSortValueLive(boolean live); /** * @return * * @since 2.5.0.0 */ public boolean isSortValueLive(); /** * @param ms * * @since 2.5.0.0 */ public void addRefreshTime(long ms); /** * @param writer * * @since 2.5.0.0 */ void generateDiagnostics(IndentWriter writer); /** * @param tableID * * @since 2.5.0.2 */ void setTableID(String tableID); /** * @return * * @since 2.5.0.2 */ boolean isSortAscending(); /** * @param bAscending * * @since 2.5.0.2 */ void setSortAscending(boolean bAscending); /** * @return * * @since 3.0.1.1 */ boolean hasCellMouseMoveListener(); void triggerColumnSizeChange(); void setAutoTooltip(boolean auto_tooltip); boolean doesAutoTooltip(); boolean isInplaceEdit(); void setInplaceEdit(boolean editable); /** * Override this function to obtain edited values * @param cell that is being edited * @param value the new value * @param finalEdit true if the user finalizes his editing * @return should be false if the currently entered value is invalid */ boolean inplaceValueSet(TableCell cell, String value, boolean finalEdit); /** * @param listenerID * @param listener * * @since 3.1.1.1 */ void addCellOtherListener(String listenerID, Object listener); /** * @param listenerID * @return * * @since 3.1.1.1 */ Object[] getCellOtherListeners(String listenerID); /** * @param listenerID * @return * * @since 4.1.0.5 */ boolean hasCellOtherListeners(String listenerID); /** * @since 4005 * @return */ public boolean isRemoved(); /** * @return * * @since 4.0.0.5 */ List getColumnExtraInfoListeners(); void reset(); } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableSelectedRowsListener.java0000644000175000017500000000147210566514576027507 0ustar adrianadrianpackage com.aelitis.azureus.ui.common.table; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; /** * Listener primarily for Menu Selection. Implement run(TableRowCore) and it * will get called for each row the user has selected. */ public abstract class TableSelectedRowsListener extends TableGroupRowRunner implements Listener { /** * */ private final TableView tv; /** * @param impl */ public TableSelectedRowsListener(TableView impl) { tv = impl; } /** Event information passed in via the Listener. Accessible in * run(TableRowSWT). */ protected Event event; /** Process the trapped event. This function does not need to be overidden. * @param e event information */ public void handleEvent(Event e) { event = e; tv.runForSelectedRows(this); } } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableCountChangeListener.java0000644000175000017500000000216510566514576027302 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.common.table; /** * @author TuxPaper * @created Feb 4, 2007 * */ public interface TableCountChangeListener { public abstract void rowAdded(TableRowCore row); public abstract void rowRemoved(TableRowCore row); }azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableStructureEventDispatcher.java0000644000175000017500000001015611167275622030400 0ustar adrianadrian/** * File : TableStructureEventDispatcher.java * Created : 27 nov. 2003 * By : Olivier * * Copyright (C) 2004-2007 Aelitis SAS, All rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.common.table; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.util.CopyOnWriteList; /** * @author Olivier * */ public class TableStructureEventDispatcher implements TableStructureModificationListener { private static Map instances = new HashMap(); private static AEMonitor class_mon = new AEMonitor( "TableStructureEventDispatcher:class"); private CopyOnWriteList listeners; private AEMonitor listeners_mon = new AEMonitor( "TableStructureEventDispatcher:L"); /** * */ private TableStructureEventDispatcher() { listeners = new CopyOnWriteList(2); } public static TableStructureEventDispatcher getInstance(String tableID) { try { class_mon.enter(); TableStructureEventDispatcher instance = instances.get(tableID); if (instance == null) { instance = new TableStructureEventDispatcher(); instances.put(tableID, instance); } return instance; } finally { class_mon.exit(); } } public void addListener(TableStructureModificationListener listener) { try { listeners_mon.enter(); if (!listeners.contains(listener)) { listeners.add(listener); } } finally { listeners_mon.exit(); } } public void removeListener(TableStructureModificationListener listener) { try { listeners_mon.enter(); listeners.remove(listener); } finally { listeners_mon.exit(); } } public void tableStructureChanged( boolean columnAddedOrRemoved, Class forPluginDataSourceType ) { Iterator iter = listeners.iterator(); while (iter.hasNext()) { TableStructureModificationListener listener = (TableStructureModificationListener) iter.next(); try{ listener.tableStructureChanged(columnAddedOrRemoved, forPluginDataSourceType); }catch( Throwable e ){ Debug.printStackTrace(e); } } } public void columnSizeChanged(TableColumnCore tableColumn) { Iterator iter = listeners.iterator(); while (iter.hasNext()) { TableStructureModificationListener listener = (TableStructureModificationListener) iter.next(); listener.columnSizeChanged(tableColumn); } } public void columnInvalidate(TableColumnCore tableColumn) { Iterator iter = listeners.iterator(); while (iter.hasNext()) { TableStructureModificationListener listener = (TableStructureModificationListener) iter.next(); listener.columnInvalidate(tableColumn); } } public void cellInvalidate(TableColumnCore tableColumn, Object data_source) { Iterator iter = listeners.iterator(); while (iter.hasNext()) { TableStructureModificationListener listener = (TableStructureModificationListener) iter.next(); listener.cellInvalidate(tableColumn, data_source); } } public void columnOrderChanged(int[] iPositions) { Iterator iter = listeners.iterator(); while (iter.hasNext()) { TableStructureModificationListener listener = (TableStructureModificationListener) iter.next(); listener.columnOrderChanged(iPositions); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/common/table/TableView.java0000644000175000017500000001744111264300532024270 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.common.table; import java.util.List; import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator; import org.gudy.azureus2.plugins.ui.tables.TableColumn; /** * @author TuxPaper * @created Feb 2, 2007 * */ public interface TableView extends AEDiagnosticsEvidenceGenerator { /** * @param listener */ void addCountChangeListener(TableCountChangeListener listener); /** Adds a dataSource to the table as a new row. If the data source is * already added, a new row will not be added. This function runs * asynchronously, so the rows creation is not guaranteed directly after * calling this function. * * You can't add datasources until the table is initialized * * @param dataSource data source to add to the table */ void addDataSource(DATASOURCETYPE dataSource); /** * Add a list of dataSources to the table. The array passed in may be * modified, so make sure you don't need it afterwards. * * You can't add datasources until the table is initialized * * @param dataSources */ void addDataSources(DATASOURCETYPE[] dataSources); void addLifeCycleListener(TableLifeCycleListener l); void addRefreshListener(TableRefreshListener l, boolean trigger); /** * @param listener * @param bFireSelection */ void addSelectionListener(TableSelectionListener listener, boolean trigger); /** * The data set that this table represents has been changed. This is not * for listening on changes to data sources changing within the table * * @param l * @param trigger */ void addTableDataSourceChangedListener(TableDataSourceChangedListener l, boolean trigger); /** * Send Selected rows to the clipboard in a SpreadSheet friendly format * (tab/cr delimited) */ void clipboardSelected(); /** * Invalidate all the cells in a column * * @param sColumnName Name of column to invalidate */ void columnInvalidate(String sColumnName); /** * @param tableColumn */ void columnInvalidate(TableColumnCore tableColumn); void delete(); /** * Retrieve a list of

    TableCell
    s, in the last sorted order. * The order will not be of the supplied cell's sort unless the table * has been sorted by that column previously. *

    * ie. You can sort on the 5th column, and retrieve the cells for the * 3rd column, but they will be in order of the 5th columns sort. * * @param sColumnName Which column cell's to return. This does not sort * the array on the column. * @return array of cells */ TableCellCore[] getColumnCells(String columnName); /** * @return not sorted */ List getDataSources(); /** * @return */ DATASOURCETYPE getFirstSelectedDataSource(); /** * @return */ String getPropertiesPrefix(); /** * Get the row associated with a datasource * @param dataSource a reference to a core Datasource object * (not a plugin datasource object) * @return The row, or null */ TableRowCore getRow(DATASOURCETYPE dataSource); /** Get all the rows for this table, in the order they are displayed * * @return a list of TableRowSWT objects in the order the user sees them */ TableRowCore[] getRows(); /** Returns an array of all selected Data Sources. Null data sources are * ommitted. * * @return an array containing the selected data sources */ List getSelectedDataSources(); /** * Returns an array of all selected Data Sources. Null data sources are * ommitted. * * @param bCoreDataSource * @return an array containing the selected data sources */ Object[] getSelectedDataSources(boolean bCoreDataSource); /** * Returns an array of all selected TableRowSWT. Null data sources are * ommitted. * * @return an array containing the selected data sources */ TableRowCore[] getSelectedRows(); /** * @return */ TableColumnCore getSortColumn(); /** * @return */ boolean isDisposed(); boolean isTableFocus(); /** * Process the queue of datasources to be added and removed * */ void processDataSourceQueue(); /** * @param bForceSort */ void refreshTable(boolean bForceSort); /** * Remove all the data sources (table rows) from the table. */ void removeAllTableRows(); /** * @param dataSource */ void removeDataSource(DATASOURCETYPE dataSource); /** * @param l */ void removeTableDataSourceChangedListener(TableDataSourceChangedListener l); /** For every row source, run the code provided by the specified * parameter. * * @param runner Code to run for each row/datasource */ void runForAllRows(TableGroupRowRunner runner); /** For every row source, run the code provided by the specified * parameter. * * @param runner Code to run for each row/datasource */ void runForAllRows(TableGroupRowVisibilityRunner runner); /** * @param runner */ void runForSelectedRows(TableGroupRowRunner runner); /** * Does not fire off selection events */ void selectAll(); /** * @param enableTabViews */ void setEnableTabViews(boolean enableTabViews); void setFocus(); /** * @param newDataSource */ void setParentDataSource(Object newDataSource); /** * @param iHeight */ void setRowDefaultHeight(int iHeight); void setSelectedRows(TableRowCore[] rows); /** * @param bIncludeQueue * @return */ int size(boolean bIncludeQueue); void updateLanguage(); /** * @return */ TableRowCore getFocusedRow(); /** * @return */ String getTableID(); /** * @param x * @param y * @return */ TableRowCore getRow(int x, int y); /** * @param dataSource * @return */ boolean dataSourceExists(DATASOURCETYPE dataSource); /** * @return */ TableColumnCore[] getVisibleColumns(); /** * @param columns * @param defaultSortColumnID * @param titleIsMinWidth TODO */ public void setColumnList(TableColumnCore[] columns, String defaultSortColumnID, boolean defaultSortAscending, boolean titleIsMinWidth); /** * @param dataSources */ void removeDataSources(DATASOURCETYPE[] dataSources); /** * @return * * @since 3.0.0.7 */ int getSelectedRowsSize(); /** * @param row * @return * * @since 3.0.0.7 */ int indexOf(TableRowCore row); /** * @param row * @return * * @since 3.0.4.3 */ boolean isRowVisible(TableRowCore row); /** * @return * * @since 3.0.4.3 */ TableCellCore getTableCellWithCursor(); /** * Retrieves the row that has the cursor over it * * @return null if mouse isn't over a row * * @since 3.0.4.3 */ TableRowCore getTableRowWithCursor(); /** * @return * * @since 3.0.4.3 */ int getRowDefaultHeight(); boolean isColumnVisible(TableColumn column); /** * @param position * @return * * @since 3.0.4.3 */ TableRowCore getRow(int position); /** * @return * * @since 3.1.1.1 */ Class getDataSourceType(); /** * @param columnName * @return * * @since 3.1.1.1 */ TableColumn getTableColumn(String columnName); } azureus-4.3.0.6/com/aelitis/azureus/ui/common/viewtitleinfo/0000755000175000017500000000000011310377630023342 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfoListener.java0000644000175000017500000000171511036613122030441 0ustar adrianadrian/** * Created on Jul 8, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.common.viewtitleinfo; /** * @author TuxPaper * @created Jul 8, 2008 * */ public interface ViewTitleInfoListener { public void viewTitleInfoRefresh(ViewTitleInfo titleInfo); } azureus-4.3.0.6/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfoManager.java0000644000175000017500000000256111062122554030231 0ustar adrianadrian/** * Created on Jul 8, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.common.viewtitleinfo; import java.util.ArrayList; import java.util.List; /** * @author TuxPaper * @created Jul 8, 2008 * */ public class ViewTitleInfoManager { public static List listeners = new ArrayList(); public static void addListener(ViewTitleInfoListener l) { listeners.add(l); } public static void refreshTitleInfo(ViewTitleInfo titleinfo) { if (titleinfo == null) { return; } Object[] array = listeners.toArray(); for (int i = 0; i < array.length; i++) { ViewTitleInfoListener l = (ViewTitleInfoListener) array[i]; l.viewTitleInfoRefresh(titleinfo); } } } azureus-4.3.0.6/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfo.java0000644000175000017500000000310211236147276026741 0ustar adrianadrian/** * Created on Jul 8, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.common.viewtitleinfo; /** * @author TuxPaper * @created Jul 8, 2008 * */ public interface ViewTitleInfo { public static int TITLE_TEXT = 5; public static int TITLE_INDICATOR_TEXT = 0; public static int TITLE_INDICATOR_COLOR = 8; public static int TITLE_ACTIVE_STATE = 9; // -> Long: 0 - not supported; 1 - active; 2 - inactive public static int TITLE_INDICATOR_TEXT_TOOLTIP = 1; public static int TITLE_IMAGEID = 2; public static int TITLE_IMAGE_TOOLTIP = 3; /** * Retreive the skin object related to this view indicator */ public static int TITLE_SKINVIEW = 4; public static int TITLE_LOGID = 7; /** * * @param propertyID TITLE_* * @return value, or null if you don't want to set it * * @since 3.1.1.1 */ public Object getTitleInfoProperty(int propertyID); } azureus-4.3.0.6/com/aelitis/azureus/ui/common/RememberedDecisionsManager.java0000644000175000017500000000463011071061432026515 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui.common; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.config.COConfigurationManager; /** * Remembers Decisions (usually from message boxes) * * @author TuxPaper * @created May 6, 2007 * */ public class RememberedDecisionsManager { public static int getRememberedDecision(String id) { return getRememberedDecision(id, -1); } public static int getRememberedDecision(String id, int onlyIfInMask) { if (id == null || onlyIfInMask == 0) { return -1; } Map remembered_decisions = COConfigurationManager.getMapParameter( "MessageBoxWindow.decisions", new HashMap()); Long l = (Long) remembered_decisions.get(id); //System.out.println("getR " + id + " -> " + l); if (l != null) { int i = l.intValue(); if (onlyIfInMask == -1 || (i & onlyIfInMask) != 0) { return i; } } return -1; } /** * Set a remembered value * * @param id remember id * @param value value to store. -1 to remove * * @since 3.0.1.3 */ public static void setRemembered(String id, int value) { if (id == null) { return; } Map remembered_decisions = COConfigurationManager.getMapParameter( "MessageBoxWindow.decisions", new HashMap()); if (value == -1) { remembered_decisions.remove(id); } else { remembered_decisions.put(id, new Long(value)); } // System.out.println("setR " + id + " -> " + value); COConfigurationManager.setParameter("MessageBoxWindow.decisions", remembered_decisions); COConfigurationManager.save(); } } azureus-4.3.0.6/com/aelitis/azureus/ui/UIStatusTextClickListener.java0000644000175000017500000000206610560521432025070 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.ui; /** * @author TuxPaper * @created Feb 1, 2007 * */ public abstract class UIStatusTextClickListener { public abstract void UIStatusTextClicked(); } azureus-4.3.0.6/com/aelitis/azureus/util/0000755000175000017500000000000011310377632017524 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/util/JSONUtils.java0000644000175000017500000001135511150677520022167 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.util; import java.io.UnsupportedEncodingException; import java.util.*; import org.bouncycastle.util.encoders.Base64; import org.gudy.azureus2.core3.util.Debug; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; /** * @author TuxPaper * @created Feb 14, 2007 * */ public class JSONUtils { /** * decodes JSON formatted text into a map. * * @return Map parsed from a JSON formatted string *

    * If the json text is not a map, a map with the key "value" will be returned. * the value of "value" will either be an List, String, Number, Boolean, or null *

    * if the String is formatted badly, null is returned */ public static Map decodeJSON(String json) { try { Object object = JSONValue.parse(json); if (object instanceof Map) { return (Map) object; } // could be : ArrayList, String, Number, Boolean Map map = new HashMap(); map.put("value", object); return map; } catch (Throwable t) { Debug.out("Warning: Bad JSON String: " + json, t); return null; } } /** * encodes a map into a JSONObject. *

    * It's recommended that you use {@link #encodeToJSON(Map)} instead * * @param map * @return * * @since 3.0.1.5 */ public static Map encodeToJSONObject(Map map) { Map newMap = new JSONObject(); for (Iterator iter = map.keySet().iterator(); iter.hasNext();) { String key = (String) iter.next(); Object value = map.get(key); if (value instanceof byte[]) { key += ".B64"; value = Base64.encode((byte[]) value); } value = coerce(value); newMap.put(key, value); } return newMap; } /** * Encodes a map into a JSON formatted string. *

    * Handles multiple layers of Maps and Lists. Handls String, Number, * Boolean, and null values. * * @param map Map to change into a JSON formatted string * @return JSON formatted string * * @since 3.0.1.5 */ public static String encodeToJSON(Map map) { return encodeToJSONObject(map).toString(); } public static String encodeToJSON(Collection list) { return encodeToJSONArray(list).toString(); } private static Object coerce(Object value) { if ((value instanceof Map) && !(value instanceof JSONObject)) { value = encodeToJSONObject((Map) value); } else if ((value instanceof List) && !(value instanceof JSONArray)) { value = encodeToJSONArray((List) value); } else if (value instanceof Object[]) { Object[] array = (Object[]) value; value = encodeToJSONArray(Arrays.asList(array)); } else if (value instanceof byte[]) { try { value = new String((byte[]) value, "utf-8"); } catch (UnsupportedEncodingException e) { } } return value; } /** * @param value * @return * * @since 3.0.1.5 */ private static List encodeToJSONArray(Collection list) { List newList = new JSONArray(list); for (int i = 0; i < newList.size(); i++) { Object value = newList.get(i); newList.set(i, coerce(value)); } return newList; } public static void main(String[] args) { Map mapBefore = new HashMap(); byte[] b = { 0, 1, 2 }; mapBefore.put("Hi", b); String jsonByteArray = JSONUtils.encodeToJSON(mapBefore); System.out.println(jsonByteArray); Map mapAfter = JSONUtils.decodeJSON(jsonByteArray); b = MapUtils.getMapByteArray(mapAfter, "Hi", null); System.out.println(b.length); for (int i = 0; i < b.length; i++) { byte c = b[i]; System.out.println("--" + c); } Map map = new HashMap(); map.put("Test", "TestValue"); Map map2 = new HashMap(); map2.put("Test2", "test2value"); map.put("TestMap", map2); List list = new ArrayList(); list.add(new Long(5)); list.add("five"); map2.put("ListTest", list); Map map3 = new HashMap(); map3.put("Test3", "test3value"); list.add(map3); System.out.println(encodeToJSON(map)); System.out.println(encodeToJSON(list)); } } azureus-4.3.0.6/com/aelitis/azureus/util/win32/0000755000175000017500000000000011310377632020466 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/util/win32/Win32Utils.java0000644000175000017500000000302110564737012023252 0ustar adrianadrian/** * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.util.win32; import org.gudy.azureus2.platform.win32.access.AEWin32Access; import org.gudy.azureus2.platform.win32.access.AEWin32Manager; /** * @author TuxPaper * @created Feb 13, 2007 * */ public class Win32Utils { /** * Get the location of Windows Media Player executable * @return */ public static String getWMP() { AEWin32Access accessor = AEWin32Manager.getAccessor(true); if (accessor == null) { return null; } try { return accessor.readStringValue(AEWin32Access.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Multimedia\\WMPlayer", "Player.Path"); } catch (Exception e) { } return null; } } azureus-4.3.0.6/com/aelitis/azureus/util/ImportExportUtils.java0000644000175000017500000001402111306116372024057 0ustar adrianadrianpackage com.aelitis.azureus.util; import java.io.IOException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.gudy.azureus2.core3.util.UrlUtils; import org.json.simple.JSONArray; public final class ImportExportUtils { public final static void exportString( Map map, String key, String value ) throws IOException { if ( value != null ){ map.put( key, value.getBytes( "UTF-8" )); } } public final static void exportJSONString( Map map, String key, String value ) throws IOException { if ( value != null ){ map.put( key, value ); } } public final static String importString( Map map, String key, String def ) throws IOException { String res = importString( map, key ); if ( res == null ){ res = def; } return( res ); } public final static String importString( Map map, String key ) throws IOException { if ( map == null ){ return( null ); } Object obj = map.get( key ); if ( obj instanceof String ){ return((String)obj); }else if ( obj instanceof byte[]){ return( new String((byte[])obj, "UTF-8" )); } return( null ); } public final static long importLong( Map map, String key ) throws IOException { return( importLong( map, key, 0 )); } public final static long importLong( Map map, String key, long def ) throws IOException { if ( map == null ){ return( def ); } Object obj = map.get( key ); if ( obj instanceof Long){ return(((Long)obj).longValue()); }else if ( obj instanceof String ){ return( Long.parseLong((String)obj)); } return( def ); } public final static void exportLong( Map map, String key, long value ) { map.put( key, value ); } public final static void exportInt( Map map, String key, int value ) { map.put( key, new Long( value )); } public final static int importInt( Map map, String key ) throws IOException { return((int)importLong( map, key, 0 )); } public final static int importInt( Map map, String key, int def ) throws IOException { return((int)importLong( map, key, def )); } public final static void exportFloat( Map map, String key, float value ) throws IOException { exportString( map, key, String.valueOf( value )); } public final static float importFloat( Map map, String key, float def ) throws IOException { String str = importString( map, key ); if ( str == null ){ return( def ); } return( Float.parseFloat( str )); } public final static void exportBoolean( Map map, String key, boolean value ) throws IOException { map.put( key, new Long( value?1:0 )); } public final static boolean importBoolean( Map map, String key ) throws IOException { return( importBoolean( map, key, false )); } public final static boolean importBoolean( Map map, String key, boolean def ) throws IOException { if ( map == null ){ return( def ); } Object obj = map.get( key ); if ( obj instanceof Long){ return(((Long)obj).longValue() == 1 ); }else if ( obj instanceof Boolean ){ return(((Boolean)obj).booleanValue()); } return( def ); } public final static void exportJSONBoolean( Map map, String key, boolean value ) throws IOException { map.put( key, new Boolean( value )); } public static final String importURL( Map map, String key ) throws IOException { String url = importString( map, key ); if ( url != null ){ url = url.trim(); if ( url.length() == 0 ){ url = null; }else{ url = URLDecoder.decode( url, "UTF-8" ); } } return( url ); } public final static void exportURL( Map map, String key, String value ) throws IOException { exportString( map, key, value ); } public final static void exportJSONURL( Map map, String key, String value ) throws IOException { exportJSONString( map, key, UrlUtils.encode( value )); } public static final String[] importStringArray( Map map, String key ) throws IOException { List list = (List)map.get( key ); if ( list == null ){ return( new String[0] ); } String[] res = new String[list.size()]; for (int i=0;i>> 24); bytes[pos++] = (byte)(v >>> 16); bytes[pos++] = (byte)(v >>> 8); bytes[pos++] = (byte)(v); } map.put( key, bytes ); } public static final int[] importIntArray( Map map, String key ) { byte[] bytes = (byte[])map.get( key ); if ( bytes == null ){ return( null ); } int[] values = new int[bytes.length/4]; int pos = 0; for (int i=0;i " + result); } return (result); } } } azureus-4.3.0.6/com/aelitis/azureus/util/DataSourceUtils.java0000644000175000017500000002260611271263334023447 0ustar adrianadrian/** * Created on Jun 1, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.util; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.HashWrapper; import com.aelitis.azureus.activities.VuzeActivitiesEntry; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.core.content.RelatedContent; import com.aelitis.azureus.core.devices.DeviceOfflineDownload; import com.aelitis.azureus.core.devices.TranscodeFile; import com.aelitis.azureus.core.devices.TranscodeJob; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadException; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; /** * @author TuxPaper * @created Jun 1, 2008 * */ public class DataSourceUtils { public static DownloadManager getDM(Object ds) { try { if (ds instanceof DownloadManager) { return (DownloadManager) ds; } else if (ds instanceof VuzeActivitiesEntry) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) ds; DownloadManager dm = entry.getDownloadManger(); if (dm == null) { String assetHash = entry.getAssetHash(); if (assetHash != null && AzureusCoreFactory.isCoreRunning()) { GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); dm = gm.getDownloadManager(new HashWrapper(Base32.decode(assetHash))); entry.setDownloadManager(dm); } } return dm; } else if ((ds instanceof TOTorrent) && AzureusCoreFactory.isCoreRunning()) { GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); return gm.getDownloadManager((TOTorrent) ds); } else if (ds instanceof ISelectedContent) { return getDM(((ISelectedContent)ds).getDownloadManager()); } else if (ds instanceof TranscodeJob) { TranscodeJob tj = (TranscodeJob) ds; try { DiskManagerFileInfo file = tj.getFile(); if (file != null) { Download download = tj.getFile().getDownload(); if (download != null) { return PluginCoreUtils.unwrap(download); } } } catch (DownloadException e) { } } else if (ds instanceof TranscodeFile) { TranscodeFile tf = (TranscodeFile) ds; try { DiskManagerFileInfo file = tf.getSourceFile(); if (file != null) { Download download = file.getDownload(); if (download != null) { return PluginCoreUtils.unwrap(download); } } } catch (DownloadException e) { } } else if (ds instanceof DeviceOfflineDownload ) { return( PluginCoreUtils.unwrap(((DeviceOfflineDownload)ds).getDownload())); } } catch (Exception e) { Debug.printStackTrace(e); } return null; } public static TOTorrent getTorrent(Object ds) { if (ds instanceof TOTorrent) { return (TOTorrent) ds; } if (ds instanceof DownloadManager) { TOTorrent torrent = ((DownloadManager) ds).getTorrent(); if (torrent != null) { return torrent; } } if (ds instanceof VuzeActivitiesEntry) { TOTorrent torrent = ((VuzeActivitiesEntry) ds).getTorrent(); if (torrent == null) { // getDM will check hash as well DownloadManager dm = getDM(ds); if (dm != null) { torrent = dm.getTorrent(); } } return torrent; } if (ds instanceof TranscodeFile) { TranscodeFile tf = (TranscodeFile) ds; try { DiskManagerFileInfo file = tf.getSourceFile(); if (file != null) { Download download = file.getDownload(); if (download != null) { Torrent torrent = download.getTorrent(); if (torrent != null) { return PluginCoreUtils.unwrap(torrent); } } } } catch (Throwable e) { } } if (ds instanceof TranscodeJob) { TranscodeJob tj = (TranscodeJob) ds; try { DiskManagerFileInfo file = tj.getFile(); if (file != null) { Download download = tj.getFile().getDownload(); if (download != null) { Torrent torrent = download.getTorrent(); if (torrent != null) { return PluginCoreUtils.unwrap(torrent); } } } } catch (DownloadException e) { } } if (ds instanceof DeviceOfflineDownload ){ Torrent torrent = ((DeviceOfflineDownload) ds).getDownload().getTorrent(); if (torrent != null) { return PluginCoreUtils.unwrap(torrent); } } if (ds instanceof ISelectedContent) { return ((ISelectedContent)ds).getTorrent(); } if (ds instanceof String) { String hash = (String) ds; try { GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); DownloadManager dm = gm.getDownloadManager(new HashWrapper(Base32.decode(hash))); if (dm != null) { return dm.getTorrent(); } } catch (Exception e) { // ignore } } return null; } /** * @return * * @since 3.0.5.3 */ public static boolean isPlatformContent(Object ds) { TOTorrent torrent = getTorrent(ds); if (torrent != null) { return PlatformTorrentUtils.isContent(torrent, true); } if ((ds instanceof VuzeActivitiesEntry) && ((VuzeActivitiesEntry) ds).isPlatformContent()) { return true; } return false; } public static String getHash(Object ds) { try { if (ds instanceof DownloadManager) { return ((DownloadManager) ds).getTorrent().getHashWrapper().toBase32String(); } else if (ds instanceof TOTorrent) { return ((TOTorrent) ds).getHashWrapper().toBase32String(); } else if (ds instanceof DeviceOfflineDownload) { return( getHash(PluginCoreUtils.unwrap(((DeviceOfflineDownload)ds).getDownload()))); } else if (ds instanceof VuzeActivitiesEntry) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) ds; return entry.getAssetHash(); } else if (ds instanceof ISelectedContent) { return ((ISelectedContent)ds).getHash(); } else if (ds instanceof String) { return (String) ds; } } catch (Exception e) { Debug.printStackTrace(e); } return null; } public static ContentNetwork getContentNetwork(Object ds) { long id = -1; try { if (ds instanceof DownloadManager) { id = PlatformTorrentUtils.getContentNetworkID(((DownloadManager) ds).getTorrent()); } else if (ds instanceof TOTorrent) { id = PlatformTorrentUtils.getContentNetworkID((TOTorrent) ds); } else if (ds instanceof DeviceOfflineDownload) { return( getContentNetwork(PluginCoreUtils.unwrap(((DeviceOfflineDownload)ds).getDownload()))); } else if (ds instanceof VuzeActivitiesEntry) { VuzeActivitiesEntry entry = (VuzeActivitiesEntry) ds; return entry.getContentNetwork(); } else if (ds instanceof ISelectedContent) { return getContentNetwork(((ISelectedContent)ds).getDownloadManager()); } else if ((ds instanceof String) && ((String)ds).length() == 32) { // assume 32 byte string is a hash and that it belongs to the def. network id = ConstantsVuze.getDefaultContentNetwork().getID(); } else if (ds instanceof TranscodeJob) { TranscodeJob tj = (TranscodeJob) ds; try { DiskManagerFileInfo file = tj.getFile(); if (file != null) { Download download = tj.getFile().getDownload(); if (download != null) { DownloadManager dm = PluginCoreUtils.unwrap(download); return getContentNetwork(dm); } } } catch (DownloadException e) { } } else if (ds instanceof TranscodeFile) { TranscodeFile tf = (TranscodeFile) ds; try { DiskManagerFileInfo file = tf.getSourceFile(); if (file != null) { Download download = file.getDownload(); if (download != null) { DownloadManager dm = PluginCoreUtils.unwrap(download); return getContentNetwork(dm); } } } catch (Throwable e) { } } else if (ds instanceof RelatedContent) { id = ((RelatedContent)ds).getContentNetwork(); } else { Debug.out("Tux: UH OH NO CN for " + ds + "\n" + Debug.getCompressedStackTrace()); } } catch (Exception e) { Debug.printStackTrace(e); } ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetwork( id); return cn; } /** * @param ds * * @since 3.1.1.1 */ public static DownloadUrlInfo getDownloadInfo(Object ds) { if (ds instanceof ISelectedContent) { return ((ISelectedContent)ds).getDownloadInfo(); } return null; } } azureus-4.3.0.6/com/aelitis/azureus/util/DownloadUtils.java0000644000175000017500000000642211250057530023156 0ustar adrianadrian/* * Created on May 14, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.util; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.torrent.TorrentManager; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; public class DownloadUtils { private static TorrentAttribute ta_tracker_extensions; public static synchronized void initialise() { if ( ta_tracker_extensions == null ){ TorrentManager tm = PluginInitializer.getDefaultInterface().getTorrentManager(); ta_tracker_extensions = tm.getAttribute( TorrentAttribute.TA_TRACKER_CLIENT_EXTENSIONS ); } } public static synchronized void addTrackerExtension( Download download, String extension_prefix, String extension_value ) { String extension = "&" + extension_prefix + "=" + extension_value; String value = download.getAttribute( ta_tracker_extensions ); if ( value != null ){ // if already exists then bail if ( value.indexOf( extension ) != -1 ){ return; } // if prefix exists then remove existing value if ( value.indexOf( extension_prefix ) != -1 ){ String[] bits = value.split("&"); value = ""; for ( int i=0; i listUrlBlacklist = new CopyOnWriteList(); private CopyOnWriteList listUrlWhitelist = new CopyOnWriteList(); private AEMonitor mon = new AEMonitor("UrlFilter"); public static UrlFilter getInstance() { synchronized (UrlFilter.class) { if (instance == null) { instance = new UrlFilter(); } return instance; } } public UrlFilter() { listUrlWhitelist.add(DEFAULT_RPC_WHITELIST); ContentNetworkManager cmn = ContentNetworkManagerFactory.getSingleton(); ContentNetwork[] contentNetworks = cmn.getContentNetworks(); cmn.addListener(new ContentNetworkListener() { public void networkRemoved(ContentNetwork network) { } public void networkChanged(ContentNetwork network) { } public void networkAdded(ContentNetwork network) { addNetworkFilters(network); } public void networkAddFailed(long network_id, Throwable error) { } }); for (ContentNetwork cn : contentNetworks) { addNetworkFilters(cn); } } /** * Ensure whitelist has important network urls * * @param network * * @since 4.0.0.5 */ protected void addNetworkFilters(ContentNetwork network) { if (network == null) { return; } int[] whitelist_services = { ContentNetwork.SERVICE_SITE, ContentNetwork.SERVICE_AUTH_RPC, ContentNetwork.SERVICE_RELAY_RPC, ContentNetwork.SERVICE_RPC, }; for ( int service: whitelist_services ){ if ( network.isServiceSupported( service )){ addUrlWhitelist( network.getServiceURL( service ) + ".*" ); } } } public void addUrlWhitelist(String string) { mon.enter(); try { if (!listUrlWhitelist.contains(string)) { PlatformMessenger.debug("add whitelist of " + string); listUrlWhitelist.add(string); } else { PlatformMessenger.debug("whitelist already exists: " + string); } } finally { mon.exit(); } } public void addUrlBlacklist(String string) { mon.enter(); try { if (!listUrlBlacklist.contains(string)) { PlatformMessenger.debug("add blacklist of " + string); listUrlBlacklist.add(string); } } finally { mon.exit(); } } public String[] getUrlWhitelist() { return listUrlWhitelist.toArray(new String[0]); } public boolean isWhitelisted( String url ) { Iterator it = listUrlWhitelist.iterator(); while( it.hasNext()){ if (url.matches(it.next())) { return true; } } return( false ); } public boolean urlCanRPC(String url) { return urlCanRPC(url, false); } public boolean urlCanRPC(String url,boolean showDebug) { if (url == null) { Debug.out("URL null and should be blocked"); return false; } if (Constants.isCVSVersion() && url.startsWith("file://")) { return true; } if ( isWhitelisted( url )){ return( true ); } if(showDebug) { Debug.out("urlCanRPC: URL '" + url + "' " + " does not match one of the " + listUrlWhitelist.size() + " whitelist entries"); } return false; } public boolean urlIsBlocked(String url) { if (url == null) { Debug.out("URL null and should be blocked"); return true; } for (Iterator iter = listUrlBlacklist.iterator(); iter.hasNext();) { String blackListed = iter.next(); if (url.matches(blackListed)) { Debug.out("URL '" + url + "' " + " is blocked by " + blackListed); return true; } } return false; } } azureus-4.3.0.6/com/aelitis/azureus/util/ContentNetworkUtils.java0000644000175000017500000000666011145221760024400 0ustar adrianadrian/** * Created on Dec 10, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.util; import java.net.MalformedURLException; import java.net.URL; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; /** * @author TuxPaper * @created Dec 10, 2008 * */ public class ContentNetworkUtils { /** * Get content network url based on service id. * @param cn * @param serviceID * @return null if service is not supported * * @since 4.0.0.5 */ public static String getUrl(ContentNetwork cn, int serviceID) { try { if (!cn.isServiceSupported(serviceID)) { return null; } return cn.getServiceURL(serviceID); } catch (Throwable t) { return null; } } public static String getUrl(ContentNetwork cn, int serviceID, Object[] params) { try { if (!cn.isServiceSupported(serviceID)) { return null; } return cn.getServiceURL(serviceID, params); } catch (Throwable t) { return null; } } public static ContentNetwork getContentNetworkFromTarget(String target) { ContentNetwork cn = null; if (target != null && target.startsWith("ContentNetwork.")) { long networkID = Long.parseLong(target.substring(15)); cn = ContentNetworkManagerFactory.getSingleton().getContentNetwork( networkID); } if (cn == null) { cn = ConstantsVuze.getDefaultContentNetwork(); } return cn; } public static String getTarget(ContentNetwork cn) { return "ContentNetwork." + (cn == null ? ConstantsVuze.getDefaultContentNetwork().getID() : cn.getID()); } public static void setSourceRef(String target, String sourceRef, boolean override) { setSourceRef(getContentNetworkFromTarget(target), sourceRef, override); } public static void setSourceRef(ContentNetwork cn, String sourceRef, boolean override) { if (cn == ConstantsVuze.getDefaultContentNetwork()) { return; } // always override old source ref if the content network requires // authorization and the user hasn't authorized yet. if (cn.isServiceSupported(ContentNetwork.SERVICE_AUTHORIZE)) { boolean authShown = false; Object oAuthShown = cn.getPersistentProperty(ContentNetwork.PP_AUTH_PAGE_SHOWN); if (oAuthShown instanceof Boolean) { authShown = ((Boolean) oAuthShown).booleanValue(); } if (!authShown) { override = true; } } String old = (String) cn.getPersistentProperty(ContentNetwork.PP_SOURCE_REF); if (old == null || override) { if (sourceRef != null && sourceRef.startsWith("http")) { // trim down try { URL url = new URL(sourceRef); sourceRef = url.getHost() + url.getPath(); } catch (MalformedURLException e) { } } cn.setPersistentProperty(ContentNetwork.PP_SOURCE_REF, sourceRef); } } } azureus-4.3.0.6/com/aelitis/azureus/util/ConstantsV3.java0000644000175000017500000000321011145221760022544 0ustar adrianadrian/* * Created on Aug 30, 2006 * Created by Alon Rohter * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.util; import com.aelitis.azureus.core.cnetwork.ContentNetwork; /** * @deprecated Only for EMP */ public class ConstantsV3 { /** @deprecated Used by UMP only.. */ public static boolean isOSX = org.gudy.azureus2.core3.util.Constants.isOSX; /** @deprecated Used by UMP only.. */ public static boolean isWindows = org.gudy.azureus2.core3.util.Constants.isWindows; /** @deprecated Use {@link ConstantsVuze#DEFAULT_CONTENT_NETWORK_ID} **/ public static final ContentNetwork DEFAULT_CONTENT_NETWORK = ConstantsVuze.getDefaultContentNetwork(); /** @deprecated Used by UMP only.. */ public static final String URL_PREFIX = DEFAULT_CONTENT_NETWORK.getServiceURL(ContentNetwork.SERVICE_SITE); } azureus-4.3.0.6/com/aelitis/azureus/util/Constants.java0000644000175000017500000000240511146735122022343 0ustar adrianadrian/* * Created on Aug 30, 2006 * Created by Alon Rohter * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.util; /** * @deprecated Only for UMP */ public class Constants { /** @deprecated Used by UMP only.. */ public static boolean isOSX = org.gudy.azureus2.core3.util.Constants.isOSX; /** @deprecated Used by UMP only.. */ public static boolean isWindows = org.gudy.azureus2.core3.util.Constants.isWindows; } azureus-4.3.0.6/com/aelitis/azureus/core/0000755000175000017500000000000011310377616017501 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/drivedetector/0000755000175000017500000000000011310377624022343 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/drivedetector/impl/0000755000175000017500000000000011310377624023304 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/drivedetector/impl/DriveDetectedInfoImpl.java0000644000175000017500000000250011233435732030314 0ustar adrianadrian/* * Created on Jul 26, 2009 5:36:43 PM * Copyright (C) 2009 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.drivedetector.impl; import java.io.File; import com.aelitis.azureus.core.drivedetector.DriveDetectedInfo; /** * @author TuxPaper * @created Jul 26, 2009 * */ public class DriveDetectedInfoImpl implements DriveDetectedInfo { File location; public DriveDetectedInfoImpl(File location) { this.location = location; } public File getLocation() { return location; } } azureus-4.3.0.6/com/aelitis/azureus/core/drivedetector/impl/DriveDetectorImpl.java0000644000175000017500000000630211236505210027524 0ustar adrianadrian/* * Created on Jul 26, 2009 5:18:54 PM * Copyright (C) 2009 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.drivedetector.impl; import java.io.File; import java.util.ArrayList; import java.util.List; import org.gudy.azureus2.core3.util.AEMonitor2; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.drivedetector.*; import com.aelitis.azureus.core.util.CopyOnWriteList; /** * @author TuxPaper * @created Jul 26, 2009 * */ public class DriveDetectorImpl implements DriveDetector { private AEMonitor2 mon_driveDetector = new AEMonitor2("driveDetector"); private CopyOnWriteList listListeners = new CopyOnWriteList(1); private List listDrives = new ArrayList(1); public void addListener(DriveDetectedListener l) { File[] drives; mon_driveDetector.enter(); try { if (!listListeners.contains(l)) { listListeners.add(l); } else { // already added, skip trigger return; } drives = listDrives.toArray(new File[0]); } finally { mon_driveDetector.exit(); } for (File drive : drives) { try { l.driveDetected(new DriveDetectedInfoImpl(drive)); } catch (Throwable e) { Debug.out(e); } } } public void removeListener(DriveDetectedListener l) { listListeners.remove(l); } public void driveDetected(File location) { location = normaliseFile( location ); mon_driveDetector.enter(); try { if (!listDrives.contains(location)) { listDrives.add(location); } else { // already there, no trigger return; } } finally { mon_driveDetector.exit(); } for (DriveDetectedListener l : listListeners) { try { l.driveDetected(new DriveDetectedInfoImpl(location)); } catch (Throwable e) { Debug.out(e); } } } public void driveRemoved(File location) { location = normaliseFile( location ); mon_driveDetector.enter(); try { if (!listDrives.remove(location)) { // not there, no trigger return; } } finally { mon_driveDetector.exit(); } for (DriveDetectedListener l : listListeners) { try { l.driveRemoved(new DriveDetectedInfoImpl(location)); } catch (Throwable e) { Debug.out(e); } } } protected File normaliseFile( File f ) { try{ return( f.getCanonicalFile()); }catch( Throwable e ){ Debug.out( e ); return( f ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/drivedetector/DriveDetectedInfo.java0000644000175000017500000000214211233435732026533 0ustar adrianadrian/* * Created on Jul 26, 2009 5:34:26 PM * Copyright (C) 2009 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.drivedetector; import java.io.File; /** * @author TuxPaper * @created Jul 26, 2009 * */ public interface DriveDetectedInfo { public File getLocation(); } azureus-4.3.0.6/com/aelitis/azureus/core/drivedetector/DriveDetector.java0000644000175000017500000000240711233435732025753 0ustar adrianadrian/* * Created on Jul 26, 2009 5:00:17 PM * Copyright (C) 2009 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.drivedetector; import java.io.File; /** * @author TuxPaper * @created Jul 26, 2009 * */ public interface DriveDetector { public void driveDetected(File location); public void driveRemoved(File location); public void addListener(DriveDetectedListener l); public void removeListener(DriveDetectedListener l); } azureus-4.3.0.6/com/aelitis/azureus/core/drivedetector/DriveDetectorFactory.java0000644000175000017500000000242611233435732027304 0ustar adrianadrian/* * Created on Jul 26, 2009 5:17:41 PM * Copyright (C) 2009 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.drivedetector; import com.aelitis.azureus.core.drivedetector.impl.DriveDetectorImpl; /** * @author TuxPaper * @created Jul 26, 2009 * */ public class DriveDetectorFactory { private static DriveDetector dd; public static DriveDetector getDeviceDetector() { if (dd == null) { dd = new DriveDetectorImpl(); } return dd; } } azureus-4.3.0.6/com/aelitis/azureus/core/drivedetector/DriveDetectedListener.java0000644000175000017500000000223611233435732027431 0ustar adrianadrian/* * Created on Jul 26, 2009 5:03:07 PM * Copyright (C) 2009 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.drivedetector; /** * @author TuxPaper * @created Jul 26, 2009 * */ public interface DriveDetectedListener { public void driveDetected(DriveDetectedInfo info); public void driveRemoved(DriveDetectedInfo info); } azureus-4.3.0.6/com/aelitis/azureus/core/vuzefile/0000755000175000017500000000000011310377630021326 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/vuzefile/VuzeFileHandler.java0000644000175000017500000000772611061452534025234 0ustar adrianadrian/* * Created on May 16, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.vuzefile; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.net.URI; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.utils.StaticUtilities; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import com.aelitis.azureus.core.util.CopyOnWriteList; public class VuzeFileHandler { private static VuzeFileHandler singleton = new VuzeFileHandler(); public static VuzeFileHandler getSingleton() { return( singleton ); } private CopyOnWriteList processors = new CopyOnWriteList(); protected VuzeFileHandler() { } public VuzeFile loadVuzeFile( String target ) { try{ File test_file = new File( target ); if ( test_file.isFile()){ return( getVuzeFile( new FileInputStream( test_file ))); }else{ URL url = new URI( target ).toURL(); String protocol = url.getProtocol().toLowerCase(); if ( protocol.equals( "http" ) || protocol.equals( "https" )){ ResourceDownloader rd = StaticUtilities.getResourceDownloaderFactory().create( url ); return( getVuzeFile(rd.download())); } } }catch( Throwable e ){ } return( null ); } public VuzeFile loadVuzeFile( byte[] bytes ) { return( loadVuzeFile( new ByteArrayInputStream( bytes ))); } public VuzeFile loadVuzeFile( InputStream is ) { return( getVuzeFile( is )); } protected VuzeFile getVuzeFile( InputStream is ) { try{ BufferedInputStream bis = new BufferedInputStream( is ); try{ Map map = BDecoder.decode(bis); return( loadVuzeFile( map )); }finally{ is.close(); } }catch( Throwable e ){ } return( null ); } public VuzeFile loadVuzeFile( Map map ) { if ( map.containsKey( "vuze" ) && !map.containsKey( "info" )){ return( new VuzeFileImpl( this, (Map)map.get( "vuze" ))); } return( null ); } public VuzeFile loadAndHandleVuzeFile( String target, int expected_types ) { VuzeFile vf = loadVuzeFile( target ); if ( vf == null ){ return( null ); } handleFiles( new VuzeFile[]{ vf }, expected_types ); return( vf ); } public void handleFiles( VuzeFile[] files, int expected_types ) { Iterator it = processors.iterator(); while( it.hasNext()){ VuzeFileProcessor proc = (VuzeFileProcessor)it.next(); try{ proc.process( files, expected_types ); }catch( Throwable e ){ Debug.printStackTrace(e); } } for (int i=0;i" ); System.exit(1); } public static void main( String[] args ) { new VuzeFileMerger( args ); } } azureus-4.3.0.6/com/aelitis/azureus/core/vuzefile/VuzeFile.java0000644000175000017500000000232211167543452023730 0ustar adrianadrian/* * Created on May 16, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.vuzefile; import java.io.File; import java.io.IOException; import java.util.Map; public interface VuzeFile { public VuzeFileComponent[] getComponents(); public VuzeFileComponent addComponent( int type, Map content ); public byte[] exportToBytes() throws IOException; public Map exportToMap() throws IOException; public void write( File target ) throws IOException; } azureus-4.3.0.6/com/aelitis/azureus/core/vuzefile/VuzeFileComponent.java0000644000175000017500000000326011111446702025602 0ustar adrianadrian/* * Created on May 19, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.vuzefile; import java.util.*; public interface VuzeFileComponent { public static final int COMP_TYPE_NONE = 0x00000000; public static final int COMP_TYPE_METASEARCH_TEMPLATE = 0x00000001; public static final int COMP_TYPE_V3_NAVIGATION = 0x00000002; public static final int COMP_TYPE_V3_CONDITION_CHECK = 0x00000004; public static final int COMP_TYPE_PLUGIN = 0x00000008; public static final int COMP_TYPE_SUBSCRIPTION = 0x00000010; public static final int COMP_TYPE_SUBSCRIPTION_SINGLETON = 0x00000020; public static final int COMP_TYPE_CUSTOMIZATION = 0x00000040; public static final int COMP_TYPE_CONTENT_NETWORK = 0x00000080; public int getType(); public Map getContent(); public void setProcessed(); public boolean isProcessed(); public void setData( Object key, Object value ); public Object getData( Object key ); } azureus-4.3.0.6/com/aelitis/azureus/core/security/0000755000175000017500000000000011310377630021344 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/security/CryptoHandler.java0000644000175000017500000000563411012725234024771 0ustar adrianadrian/* * Created on 15 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.security; public interface CryptoHandler { public int getType(); /** * Explicit unlock request * @throws CryptoManagerException */ public void unlock() throws CryptoManagerException; /** * Puts the handler back into a state where password will be required to access private stuff */ public void lock(); public boolean isUnlocked(); public int getUnlockTimeoutSeconds(); /** * * @param secs 0-> infinite */ public void setUnlockTimeoutSeconds( int secs ); public byte[] sign( byte[] data, String reason ) throws CryptoManagerException; public boolean verify( byte[] public_key, byte[] data, byte[] signature ) throws CryptoManagerException; public byte[] encrypt( byte[] other_public_key, byte[] data, String reason ) throws CryptoManagerException; public byte[] decrypt( byte[] other_public_key, byte[] data, String reason ) throws CryptoManagerException; public CryptoSTSEngine getSTSEngine( String reason ) throws CryptoManagerException; public byte[] peekPublicKey(); public byte[] getPublicKey( String reason ) throws CryptoManagerException; public byte[] getEncryptedPrivateKey( String reason ) throws CryptoManagerException; public boolean verifyPublicKey( byte[] encoded ); public void recoverKeys( byte[] public_key, byte[] encrypted_private_key ) throws CryptoManagerException; public void resetKeys( String reason ) throws CryptoManagerException; public String exportKeys() throws CryptoManagerException; public int getDefaultPasswordHandlerType(); public void setDefaultPasswordHandlerType( int new_type ) throws CryptoManagerException; /** * * @param str * @return true if an Azureus restart is required * @throws CryptoManagerException */ public boolean importKeys( String str ) throws CryptoManagerException; } azureus-4.3.0.6/com/aelitis/azureus/core/security/impl/0000755000175000017500000000000011310377630022305 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/security/impl/CryptoSTSEngineImpl.java0000644000175000017500000002161711036323574027004 0ustar adrianadrian/* * Created on 15 Jun 2006 * Created by Aaron Grunthal and Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.security.impl; import java.nio.ByteBuffer; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import org.bouncycastle.jce.provider.JCEECDHKeyAgreement; import com.aelitis.azureus.core.security.CryptoECCUtils; import com.aelitis.azureus.core.security.CryptoManagerException; import com.aelitis.azureus.core.security.CryptoSTSEngine; /** * STS authentication protocol using a symmetric 4 message ECDH/ECDSA handshake */ final class CryptoSTSEngineImpl implements CryptoSTSEngine { public static final int VERSION = 1; private KeyPair ephemeralKeyPair; private PublicKey myPublicKey; private PrivateKey myPrivateKey; private PublicKey remotePubKey; private byte[] sharedSecret; private InternalDH ecDH; /** * * @param myIdent keypair representing our current identity */ CryptoSTSEngineImpl( PublicKey _myPub, PrivateKey _myPriv ) throws CryptoManagerException { myPublicKey = _myPub; myPrivateKey = _myPriv; ephemeralKeyPair = CryptoECCUtils.createKeys(); try{ ecDH = new InternalDH(); //ecDH = KeyAgreement.getInstance("ECDH", "BC"); ecDH.init(ephemeralKeyPair.getPrivate()); }catch (Exception e){ throw new CryptoManagerException("Couldn't initialize crypto handshake", e); } } public void getKeys( ByteBuffer message ) throws CryptoManagerException { getMessage( message, true ); } public void putKeys( ByteBuffer message ) throws CryptoManagerException { putMessage( message, true ); } public void getAuth( ByteBuffer message ) throws CryptoManagerException { getMessage( message, false ); } public void putAuth( ByteBuffer message ) throws CryptoManagerException { putMessage( message, false ); } public void putMessage( ByteBuffer message, boolean keys ) throws CryptoManagerException { // System.out.println( "put( " + keys + ") " + this ); try{ int version = getInt( message, 255 ); if ( version != VERSION ){ throw( new CryptoManagerException( "invalid version (" + version + ")" )); } if ( keys ){ if ( sharedSecret != null ){ throw( new CryptoManagerException( "phase error: keys already received" )); } final byte[] rawRemoteOtherPubkey = getBytes( message, 65535 ); final byte[] rawRemoteEphemeralPubkey = getBytes( message, 65535 ); final byte[] remoteSig = getBytes( message, 65535 ); final byte[] pad = getBytes( message, 65535 ); remotePubKey = CryptoECCUtils.rawdataToPubkey(rawRemoteOtherPubkey); Signature check = CryptoECCUtils.getSignature(remotePubKey); check.update(rawRemoteOtherPubkey); check.update(rawRemoteEphemeralPubkey); if ( check.verify(remoteSig)){ ecDH.doPhase(CryptoECCUtils.rawdataToPubkey(rawRemoteEphemeralPubkey), true); sharedSecret = ecDH.generateSecret(); }else{ throw( new CryptoManagerException( "Signature check failed" )); } }else{ if ( sharedSecret == null ){ throw( new CryptoManagerException( "phase error: keys not received" )); } final byte[] IV = getBytes( message, 65535 ); final byte[] remoteSig = getBytes( message, 65535); Signature check = CryptoECCUtils.getSignature( remotePubKey ); check.update(IV); check.update(sharedSecret); if ( !check.verify(remoteSig)){ throw( new CryptoManagerException( "Signature check failed" )); } } }catch( CryptoManagerException e ){ throw( e ); }catch( Throwable e ){ throw( new CryptoManagerException( "Failed to generate message" )); } } public void getMessage( ByteBuffer buffer, boolean keys ) throws CryptoManagerException { // System.out.println( "get( " + keys + ") " + this ); try{ putInt( buffer, VERSION, 255 ); SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); Signature sig = CryptoECCUtils.getSignature(myPrivateKey); if ( keys ){ final byte[] rawMyPubkey = CryptoECCUtils.keyToRawdata(myPublicKey); final byte[] rawEphemeralPubkey = CryptoECCUtils.keyToRawdata(ephemeralKeyPair.getPublic()); sig.update(rawMyPubkey); sig.update(rawEphemeralPubkey); final byte[] rawSign = sig.sign(); final byte[] pad = new byte[random.nextInt(32)]; random.nextBytes(pad); putBytes( buffer, rawMyPubkey, 65535 ); putBytes( buffer, rawEphemeralPubkey, 65535 ); putBytes( buffer, rawSign, 65535 ); putBytes( buffer, pad, 65535 ); }else{ if ( sharedSecret == null ){ throw( new CryptoManagerException( "phase error: keys not received" )); } final byte[] IV = new byte[20 + random.nextInt(32)]; random.nextBytes(IV); sig.update(IV); sig.update(sharedSecret); final byte[] rawSig = sig.sign(); putBytes( buffer, IV, 65535 ); putBytes( buffer, rawSig, 65535 ); } }catch( CryptoManagerException e ){ throw( e ); }catch( Throwable e ){ throw( new CryptoManagerException( "Failed to generate message" )); } } public byte[] getSharedSecret() throws CryptoManagerException { if ( sharedSecret == null ){ throw( new CryptoManagerException( "secret not yet available" )); } return sharedSecret; } public byte[] getRemotePublicKey() throws CryptoManagerException { if ( remotePubKey == null ){ throw( new CryptoManagerException( "key not yet available" )); } return( CryptoECCUtils.keyToRawdata( remotePubKey )); } protected int getInt( ByteBuffer buffer, int max_size ) throws CryptoManagerException { try{ if ( max_size < 256 ){ return( buffer.get() & 0xff); }else if ( max_size < 65536 ){ return( buffer.getShort() & 0xffff); }else{ return( buffer.getInt()); } }catch( Throwable e ){ throw( new CryptoManagerException( "Failed to get int", e )); } } protected byte[] getBytes( ByteBuffer buffer, int max_size ) throws CryptoManagerException { int len = getInt( buffer, max_size ); if ( len > max_size ){ throw( new CryptoManagerException( "Invalid length" )); } try{ byte[] res = new byte[len]; buffer.get( res ); return( res ); }catch( Throwable e ){ throw( new CryptoManagerException( "Failed to get byte[]", e )); } } protected void putInt( ByteBuffer buffer, int value, int max_size ) throws CryptoManagerException { try{ if ( max_size < 256 ){ buffer.put((byte)value); }else if ( max_size < 65536 ){ buffer.putShort((short)value ); }else{ buffer.putInt( value ); } }catch( Throwable e ){ throw( new CryptoManagerException( "Failed to put int", e )); } } protected void putBytes( ByteBuffer buffer, byte[] value, int max_size ) throws CryptoManagerException { putInt( buffer, value.length, max_size ); try{ buffer.put( value ); }catch( Throwable e ){ throw( new CryptoManagerException( "Failed to put byte[]", e )); } } class InternalDH extends JCEECDHKeyAgreement.DH { // we use this class to obtain compatability with BC public void init( Key key ) throws InvalidKeyException, InvalidAlgorithmParameterException { engineInit( key, null ); } public Key doPhase( Key key, boolean lastPhase ) throws InvalidKeyException, IllegalStateException { return( engineDoPhase( key, lastPhase )); } public byte[] generateSecret() throws IllegalStateException { return( engineGenerateSecret()); } } }azureus-4.3.0.6/com/aelitis/azureus/core/security/impl/CryptoHandlerECC.java0000644000175000017500000005050411272275146026253 0ustar adrianadrian/* * Created on 15 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.security.impl; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.spec.AlgorithmParameterSpec; import java.util.Arrays; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import org.bouncycastle.jce.provider.JCEIESCipher; import org.bouncycastle.jce.spec.IEKeySpec; import org.bouncycastle.jce.spec.IESParameterSpec; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.RandomUtils; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.security.CryptoECCUtils; import com.aelitis.azureus.core.security.CryptoHandler; import com.aelitis.azureus.core.security.CryptoManager; import com.aelitis.azureus.core.security.CryptoManagerException; import com.aelitis.azureus.core.security.CryptoManagerPasswordException; import com.aelitis.azureus.core.security.CryptoManagerPasswordHandler; import com.aelitis.azureus.core.security.CryptoSTSEngine; public class CryptoHandlerECC implements CryptoHandler { private static final String DEFAULT_PASSWORD = ""; private static final Long DEFAULT_TIMEOUT = Long.MAX_VALUE; private static final int TIMEOUT_DEFAULT_SECS = 60*60; private CryptoManagerImpl manager; private String CONFIG_PREFIX = CryptoManager.CRYPTO_CONFIG_PREFIX + "ecc."; private PrivateKey use_method_private_key; private PublicKey use_method_public_key; private long last_unlock_time; protected CryptoHandlerECC( CryptoManagerImpl _manager, int _instance_id ) { manager = _manager; CONFIG_PREFIX += _instance_id + "."; // migration away from system managed keys if ( getDefaultPasswordHandlerType() != CryptoManagerPasswordHandler.HANDLER_TYPE_USER ){ COConfigurationManager.setParameter( CONFIG_PREFIX + "default_pwtype", CryptoManagerPasswordHandler.HANDLER_TYPE_USER ); } if ( getCurrentPasswordType() == CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM || COConfigurationManager.getByteParameter( CONFIG_PREFIX + "publickey", null ) == null ){ try{ createAndStoreKeys( manager.setPassword( CryptoManager.HANDLER_ECC, CryptoManagerPasswordHandler.HANDLER_TYPE_USER, DEFAULT_PASSWORD.toCharArray(), DEFAULT_TIMEOUT )); Debug.outNoStack( "Successfully migrated key management" ); }catch( Throwable e ){ Debug.out( "Failed to migrate key management", e ); } } } public int getType() { return( CryptoManager.HANDLER_ECC ); } public void unlock() throws CryptoManagerException { getMyPrivateKey( "unlock" ); } public synchronized boolean isUnlocked() { return( use_method_private_key != null ); } public void lock() { boolean changed = false; synchronized( this ){ changed = use_method_private_key != null; use_method_private_key = null; } if ( changed ){ manager.lockChanged( this ); } } public int getUnlockTimeoutSeconds() { return( COConfigurationManager.getIntParameter( CONFIG_PREFIX + "timeout", TIMEOUT_DEFAULT_SECS )); } public void setUnlockTimeoutSeconds( int secs ) { COConfigurationManager.setParameter( CONFIG_PREFIX + "timeout", secs ); } public byte[] sign( byte[] data, String reason ) throws CryptoManagerException { PrivateKey priv = getMyPrivateKey( reason ); Signature sig = CryptoECCUtils.getSignature( priv ); try{ sig.update( data ); return( sig.sign()); }catch( Throwable e ){ throw( new CryptoManagerException( "Signature failed", e )); } } public boolean verify( byte[] public_key, byte[] data, byte[] signature ) throws CryptoManagerException { PublicKey pub = CryptoECCUtils.rawdataToPubkey( public_key ); Signature sig = CryptoECCUtils.getSignature( pub ); try{ sig.update( data ); return( sig.verify( signature )); }catch( Throwable e ){ throw( new CryptoManagerException( "Signature failed", e )); } } public byte[] encrypt( byte[] other_public_key, byte[] data, String reason ) throws CryptoManagerException { try{ IEKeySpec key_spec = new IEKeySpec( getMyPrivateKey( reason ), CryptoECCUtils.rawdataToPubkey( other_public_key )); byte[] d = new byte[16]; byte[] e = new byte[16]; RandomUtils.nextSecureBytes( d ); RandomUtils.nextSecureBytes( e ); IESParameterSpec param = new IESParameterSpec( d, e, 128); InternalECIES cipher = new InternalECIES(); cipher.internalEngineInit( Cipher.ENCRYPT_MODE, key_spec, param, null ); byte[] encrypted = cipher.internalEngineDoFinal(data, 0, data.length ); byte[] result = new byte[32+encrypted.length]; System.arraycopy( d, 0, result, 0, 16 ); System.arraycopy( e, 0, result, 16, 16 ); System.arraycopy( encrypted, 0, result, 32, encrypted.length ); return( result ); }catch( CryptoManagerException e ){ throw( e ); }catch( Throwable e){ throw( new CryptoManagerException( "Encrypt failed", e )); } } public byte[] decrypt( byte[] other_public_key, byte[] data, String reason ) throws CryptoManagerException { try{ IEKeySpec key_spec = new IEKeySpec( getMyPrivateKey( reason ), CryptoECCUtils.rawdataToPubkey( other_public_key )); byte[] d = new byte[16]; byte[] e = new byte[16]; System.arraycopy( data, 0, d, 0, 16 ); System.arraycopy( data, 16, e, 0, 16 ); IESParameterSpec param = new IESParameterSpec( d, e, 128); InternalECIES cipher = new InternalECIES(); cipher.internalEngineInit( Cipher.DECRYPT_MODE, key_spec, param, null ); return( cipher.internalEngineDoFinal( data, 32, data.length - 32 )); }catch( CryptoManagerException e ){ throw( e ); }catch( Throwable e){ throw( new CryptoManagerException( "Decrypt failed", e )); } } public CryptoSTSEngine getSTSEngine( String reason ) throws CryptoManagerException { return( new CryptoSTSEngineImpl( getMyPublicKey( reason, true ), getMyPrivateKey( reason ))); } public byte[] peekPublicKey() { try{ return( CryptoECCUtils.keyToRawdata( getMyPublicKey( "peek", false ))); }catch( Throwable e ){ return( null ); } } public byte[] getPublicKey( String reason ) throws CryptoManagerException { return( CryptoECCUtils.keyToRawdata( getMyPublicKey( reason, true ))); } public byte[] getEncryptedPrivateKey( String reason ) throws CryptoManagerException { getMyPrivateKey( reason ); byte[] pk = COConfigurationManager.getByteParameter( CONFIG_PREFIX + "privatekey", null ); if ( pk == null ){ throw( new CryptoManagerException( "Private key unavailable" )); } int pw_type = getCurrentPasswordType(); byte[] res = new byte[pk.length+1]; res[0] = (byte)pw_type; System.arraycopy( pk, 0, res, 1, pk.length ); return( res ); } public void recoverKeys( byte[] public_key, byte[] encrypted_private_key_and_type ) throws CryptoManagerException { boolean lock_changed = false; synchronized( this ){ lock_changed = use_method_private_key != null; use_method_private_key = null; use_method_public_key = null; manager.clearPassword( CryptoManager.HANDLER_ECC, CryptoManagerPasswordHandler.HANDLER_TYPE_ALL ); COConfigurationManager.setParameter( CONFIG_PREFIX + "publickey", public_key ); int type = (int)encrypted_private_key_and_type[0]&0xff; COConfigurationManager.setParameter( CONFIG_PREFIX + "pwtype", type ); byte[] encrypted_private_key = new byte[encrypted_private_key_and_type.length-1]; System.arraycopy( encrypted_private_key_and_type, 1, encrypted_private_key, 0, encrypted_private_key.length ); COConfigurationManager.setParameter( CONFIG_PREFIX + "privatekey", encrypted_private_key ); COConfigurationManager.save(); } manager.keyChanged( this ); if ( lock_changed ){ manager.lockChanged( this ); } } public void resetKeys( String reason ) throws CryptoManagerException { boolean lock_changed = false; synchronized( this ){ lock_changed = use_method_private_key != null; use_method_private_key = null; use_method_public_key = null; manager.clearPassword( CryptoManager.HANDLER_ECC, CryptoManagerPasswordHandler.HANDLER_TYPE_ALL ); COConfigurationManager.removeParameter( CONFIG_PREFIX + "publickey" ); COConfigurationManager.removeParameter( CONFIG_PREFIX + "privatekey" ); COConfigurationManager.save(); } if ( lock_changed ){ manager.lockChanged( this ); } try{ createAndStoreKeys( "resetting keys" ); }catch( CryptoManagerException e ){ manager.keyChanged( this ); throw( e ); } } protected PrivateKey getMyPrivateKey( String reason ) throws CryptoManagerException { boolean lock_change = false; try{ synchronized( this ){ if ( use_method_private_key != null ){ int timeout_secs = getUnlockTimeoutSeconds(); if ( timeout_secs > 0 ){ if ( SystemTime.getCurrentTime() - last_unlock_time >= timeout_secs * 1000 ){ lock_change = true; use_method_private_key = null; } } } if ( use_method_private_key != null ){ return( use_method_private_key ); } } final byte[] encoded = COConfigurationManager.getByteParameter( CONFIG_PREFIX + "privatekey", null ); if ( encoded == null ){ return((PrivateKey)createAndStoreKeys( reason )[1]); }else{ CryptoManagerImpl.passwordDetails password_details = manager.getPassword( CryptoManager.HANDLER_ECC, CryptoManagerPasswordHandler.ACTION_DECRYPT, reason, new CryptoManagerImpl.passwordTester() { public boolean testPassword( char[] password ) { try{ manager.decryptWithPBE( encoded, password ); return( true ); }catch( Throwable e ){ return( false ); } } }, getCurrentPasswordType()); synchronized( this ){ boolean ok = false; try{ use_method_private_key = CryptoECCUtils.rawdataToPrivkey( manager.decryptWithPBE( encoded, password_details.getPassword())); lock_change = true; last_unlock_time = SystemTime.getCurrentTime(); if ( !checkKeysOK( reason )){ throw( new CryptoManagerPasswordException( true, "Password incorrect" )); } ok = true; }catch( CryptoManagerException e ){ throw( e ); }catch( Throwable e ){ throw( new CryptoManagerException( "Password incorrect", e )); }finally{ if ( !ok ){ manager.clearPassword( CryptoManager.HANDLER_ECC, CryptoManagerPasswordHandler.HANDLER_TYPE_ALL ); lock_change = true; use_method_private_key = null; } } } if ( use_method_private_key == null ){ throw( new CryptoManagerException( "Failed to get private key" )); } return( use_method_private_key ); } }finally{ if ( lock_change ){ manager.lockChanged( this ); } } } protected boolean checkKeysOK( String reason ) throws CryptoManagerException { byte[] test_data = "test".getBytes(); return( verify( CryptoECCUtils.keyToRawdata( getMyPublicKey( reason, true )), test_data, sign( test_data, reason ))); } protected PublicKey getMyPublicKey( String reason, boolean create_if_needed ) throws CryptoManagerException { boolean create_new = false; synchronized( this ){ if ( use_method_public_key == null ){ byte[] key_bytes = COConfigurationManager.getByteParameter( CONFIG_PREFIX + "publickey", null ); if ( key_bytes == null ){ if ( create_if_needed ){ create_new = true; }else{ return( null ); } }else{ use_method_public_key = CryptoECCUtils.rawdataToPubkey( key_bytes ); } } if ( !create_new ){ if ( use_method_public_key == null ){ throw( new CryptoManagerException( "Failed to get public key" )); } return( use_method_public_key ); } } return((PublicKey)createAndStoreKeys( reason )[0] ); } public int getDefaultPasswordHandlerType() { return( COConfigurationManager.getIntParameter( CONFIG_PREFIX + "default_pwtype", CryptoManagerPasswordHandler.HANDLER_TYPE_USER )); } public void setDefaultPasswordHandlerType( int new_type ) throws CryptoManagerException { String reason = "Changing password handler"; boolean have_existing_keys = COConfigurationManager.getByteParameter( CONFIG_PREFIX + "privatekey", null ) != null; // ensure we unlock the private key so we can then re-persist it with new password if ( have_existing_keys ){ if ( new_type == getCurrentPasswordType()){ return; } getMyPrivateKey( reason ); CryptoManagerImpl.passwordDetails password_details = manager.getPassword( CryptoManager.HANDLER_ECC, CryptoManagerPasswordHandler.ACTION_ENCRYPT, reason, null, new_type ); synchronized( this ){ if ( use_method_private_key == null ){ throw( new CryptoManagerException( "Private key not available" )); } byte[] priv_raw = CryptoECCUtils.keyToRawdata( use_method_private_key ); byte[] priv_enc = manager.encryptWithPBE( priv_raw, password_details.getPassword()); COConfigurationManager.setParameter( CONFIG_PREFIX + "privatekey", priv_enc ); COConfigurationManager.setParameter( CONFIG_PREFIX + "pwtype", password_details.getHandlerType()); COConfigurationManager.setParameter( CONFIG_PREFIX + "default_pwtype", password_details.getHandlerType()); COConfigurationManager.save(); } }else{ // not much to do as keys not yet created synchronized( this ){ if ( COConfigurationManager.getByteParameter( CONFIG_PREFIX + "privatekey", null ) == null ){ COConfigurationManager.setParameter( CONFIG_PREFIX + "default_pwtype", new_type ); COConfigurationManager.save(); } } } } protected Key[] createAndStoreKeys( String reason ) throws CryptoManagerException { CryptoManagerImpl.passwordDetails password_details = manager.getPassword( CryptoManager.HANDLER_ECC, CryptoManagerPasswordHandler.ACTION_ENCRYPT, reason, null, getDefaultPasswordHandlerType()); return( createAndStoreKeys( password_details )); } protected Key[] createAndStoreKeys( CryptoManagerImpl.passwordDetails password_details ) throws CryptoManagerException { try{ synchronized( this ){ if ( use_method_public_key == null || use_method_private_key == null ){ KeyPair keys = CryptoECCUtils.createKeys(); use_method_public_key = keys.getPublic(); use_method_private_key = keys.getPrivate(); last_unlock_time = SystemTime.getCurrentTime(); COConfigurationManager.setParameter( CONFIG_PREFIX + "publickey", CryptoECCUtils.keyToRawdata( use_method_public_key )); byte[] priv_raw = CryptoECCUtils.keyToRawdata( use_method_private_key ); byte[] priv_enc = manager.encryptWithPBE( priv_raw, password_details.getPassword()); COConfigurationManager.setParameter( CONFIG_PREFIX + "privatekey", priv_enc ); COConfigurationManager.setParameter( CONFIG_PREFIX + "pwtype", password_details.getHandlerType()); COConfigurationManager.save(); } return( new Key[]{ use_method_public_key, use_method_private_key }); } }finally{ manager.keyChanged( this ); manager.lockChanged( this ); } } public boolean verifyPublicKey( byte[] encoded ) { try{ CryptoECCUtils.rawdataToPubkey( encoded ); // we can't actually verify the key size as although it should be 192 bits // it can be less due to leading bits being 0 return( true ); }catch( Throwable e ){ return( false ); } } public String exportKeys() throws CryptoManagerException { return( "id: " + Base32.encode(manager.getSecureID()) + "\r\n" + "public: " + Base32.encode(getPublicKey( "Key export" )) + "\r\n" + "private: " + Base32.encode(getEncryptedPrivateKey( "Key export" ))); } public boolean importKeys( String str ) throws CryptoManagerException { String reason = "Key import"; byte[] existing_id = manager.getSecureID(); byte[] existing_public_key = peekPublicKey(); byte[] existing_private_key = existing_public_key==null?null:getEncryptedPrivateKey( reason ); byte[] recovered_id = null; byte[] recovered_public_key = null; byte[] recovered_private_key = null; String[] bits = str.split( "\n" ); for (int i=0;i timeout ){ COConfigurationManager.setParameter( persist_timeout_key, 0 ); COConfigurationManager.setParameter( persist_pw_key, "" ); }else{ addPasswordTimer( persist_timeout_key, persist_pw_key, timeout ); } } ecc_handler = new CryptoHandlerECC( this, 1 ); } protected void addPasswordTimer( final String timeout_key, final String pw_key, final long timeout ) { SimpleTimer.addEvent( "CryptoManager:pw_timeout", timeout, new TimerEventPerformer() { public void perform( TimerEvent event) { synchronized( CryptoManagerImpl.this ){ if ( COConfigurationManager.getLongParameter( timeout_key, 0 ) == timeout ){ COConfigurationManager.removeParameter( timeout_key ); COConfigurationManager.removeParameter( pw_key ); } } } }); } public byte[] getSecureID() { String key = CryptoManager.CRYPTO_CONFIG_PREFIX + "id"; if ( secure_id == null ){ secure_id = COConfigurationManager.getByteParameter( key, null ); } if ( secure_id == null ){ secure_id = new byte[20]; RandomUtils.SECURE_RANDOM.nextBytes( secure_id ); COConfigurationManager.setParameter( key, secure_id ); COConfigurationManager.save(); } return( secure_id ); } public CryptoHandler getECCHandler() { return( ecc_handler ); } protected byte[] encryptWithPBE( byte[] data, char[] password ) throws CryptoManagerException { try{ byte[] salt = new byte[8]; RandomUtils.SECURE_RANDOM.nextBytes( salt ); PBEKeySpec keySpec = new PBEKeySpec(password); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( PBE_ALG ); SecretKey key = keyFactory.generateSecret(keySpec); PBEParameterSpec paramSpec = new PBEParameterSpec( salt, PBE_ITERATIONS ); Cipher cipher = Cipher.getInstance( PBE_ALG ); cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); byte[] enc = cipher.doFinal( data ); byte[] res = new byte[salt.length + enc.length]; System.arraycopy( salt, 0, res, 0, salt.length ); System.arraycopy( enc, 0, res, salt.length, enc.length ); return( res ); }catch( Throwable e ){ throw( new CryptoManagerException( "PBE encryption failed", e )); } } protected byte[] decryptWithPBE( byte[] data, char[] password ) throws CryptoManagerException { boolean fail_is_pw_error = false; try{ byte[] salt = new byte[8]; System.arraycopy( data, 0, salt, 0, 8 ); PBEKeySpec keySpec = new PBEKeySpec(password); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( PBE_ALG ); SecretKey key = keyFactory.generateSecret(keySpec); PBEParameterSpec paramSpec = new PBEParameterSpec(salt, PBE_ITERATIONS); Cipher cipher = Cipher.getInstance( PBE_ALG ); cipher.init(Cipher.DECRYPT_MODE, key, paramSpec); fail_is_pw_error = true; return( cipher.doFinal( data, 8, data.length-8 )); }catch( Throwable e ){ if ( fail_is_pw_error ){ throw( new CryptoManagerPasswordException( true, "Password incorrect", e )); }else{ throw( new CryptoManagerException( "PBE decryption failed", e )); } } } public void clearPasswords() { clearPasswords( CryptoManagerPasswordHandler.HANDLER_TYPE_ALL ); } public void clearPasswords( int password_handler_type ) { session_passwords.clear(); for (int i=0;i SystemTime.getCurrentTime()){ String current_pw = COConfigurationManager.getStringParameter( persist_pw_key, "" ); if ( current_pw.length() > 0 ){ int type = (int)COConfigurationManager.getLongParameter( persist_pw_key_type, CryptoManagerPasswordHandler.HANDLER_TYPE_USER ); if ( type == pw_type ){ return( new passwordDetails( current_pw.toCharArray(), type )); } } } Iterator it = password_handlers.iterator(); while( it.hasNext()){ int retry_count = 0; char[] last_pw_chars = null; CryptoManagerPasswordHandler provider = (CryptoManagerPasswordHandler)it.next(); if ( pw_type != CryptoManagerPasswordHandler.HANDLER_TYPE_UNKNOWN && pw_type != provider.getHandlerType()){ continue; } while( retry_count < 64 ){ try{ CryptoManagerPasswordHandler.passwordDetails details = provider.getPassword( handler, action, retry_count > 0, reason ); if ( details == null ){ // try next password provider break; } char[] pw_chars = details.getPassword(); if ( last_pw_chars != null && Arrays.equals( last_pw_chars, pw_chars )){ // no point in going through verification if same as last retry_count++; continue; } last_pw_chars = pw_chars; // transform password so we can persist if needed byte[] salt = getPasswordSalt(); byte[] pw_bytes = new String( pw_chars ).getBytes( "UTF8" ); SHA1 sha1 = new SHA1(); sha1.update( ByteBuffer.wrap( salt )); sha1.update( ByteBuffer.wrap( pw_bytes )); String encoded_pw = ByteFormatter.encodeString( sha1.digest()); if ( tester != null && !tester.testPassword( encoded_pw.toCharArray())){ // retry retry_count++; continue; } int persist_secs = details.getPersistForSeconds(); long timeout; if ( persist_secs == 0 ){ timeout = 0; }else if ( persist_secs == Integer.MAX_VALUE ){ timeout = Long.MAX_VALUE; }else if ( persist_secs < 0 ){ // session only timeout = -1; }else{ timeout = SystemTime.getCurrentTime() + persist_secs * 1000L; } passwordDetails result = new passwordDetails( encoded_pw.toCharArray(), provider.getHandlerType()); synchronized( this ){ COConfigurationManager.setParameter( persist_timeout_key, timeout ); COConfigurationManager.setParameter( persist_pw_key_type, provider.getHandlerType()); session_passwords.remove( persist_pw_key ); COConfigurationManager.removeParameter( persist_pw_key ); if ( timeout < 0 ){ session_passwords.put( persist_pw_key, result ); }else if ( timeout > 0 ){ COConfigurationManager.setParameter( persist_pw_key, encoded_pw ); addPasswordTimer( persist_timeout_key, persist_pw_key, timeout ); } } provider.passwordOK( handler, details ); return( result ); }catch( Throwable e ){ Debug.printStackTrace(e); // next provider break; } } } throw( new CryptoManagerPasswordException( false, "No password handlers returned a password" )); } protected byte[] getPasswordSalt() { return( getSecureID()); } protected void setSecureID( byte[] id ) { String key = CryptoManager.CRYPTO_CONFIG_PREFIX + "id"; COConfigurationManager.setParameter( key, id ); COConfigurationManager.save(); secure_id = id; } protected void keyChanged( CryptoHandler handler ) { Iterator it = keychange_listeners.iterator(); while( it.hasNext()){ try{ ((CryptoManagerKeyListener)it.next()).keyChanged( handler ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } protected void lockChanged( CryptoHandler handler ) { Iterator it = keychange_listeners.iterator(); while( it.hasNext()){ try{ ((CryptoManagerKeyListener)it.next()).keyLockStatusChanged( handler ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } public void addPasswordHandler( CryptoManagerPasswordHandler handler ) { password_handlers.add( handler ); } public void removePasswordHandler( CryptoManagerPasswordHandler handler ) { password_handlers.remove( handler ); } public void addKeyListener( CryptoManagerKeyListener listener ) { keychange_listeners.add( listener ); } public void removeKeyListener( CryptoManagerKeyListener listener ) { keychange_listeners.remove( listener ); } public interface passwordTester { public boolean testPassword( char[] pw ); } public class passwordDetails { private char[] password; private int type; protected passwordDetails( char[] _password, int _type ) { password = _password; type = _type; } public char[] getPassword() { return( password ); } public int getHandlerType() { return( type ); } } public static void main( String[] args ) { try{ String stuff = "12345"; CryptoManagerImpl man = (CryptoManagerImpl)getSingleton(); man.addPasswordHandler( new CryptoManagerPasswordHandler() { public int getHandlerType() { return( HANDLER_TYPE_USER ); } public passwordDetails getPassword( int handler_type, int action_type, boolean last_pw_incorrect, String reason ) { return( new passwordDetails() { public char[] getPassword() { return( "trout".toCharArray()); } public int getPersistForSeconds() { return( 10 ); } }); } public void passwordOK( int handler_type, passwordDetails details) { } }); CryptoHandler handler1 = man.getECCHandler(); CryptoHandler handler2 = new CryptoHandlerECC( man, 2 ); // handler1.resetKeys( null ); // handler2.resetKeys( null ); byte[] sig = handler1.sign( stuff.getBytes(), "h1: sign" ); System.out.println( handler1.verify( handler1.getPublicKey( "h1: Test verify" ), stuff.getBytes(), sig )); handler1.lock(); byte[] enc = handler1.encrypt( handler2.getPublicKey( "h2: getPublic" ), stuff.getBytes(), "h1: encrypt" ); System.out.println( "pk1 = " + ByteFormatter.encodeString( handler1.getPublicKey("h1: getPublic"))); System.out.println( "pk2 = " + ByteFormatter.encodeString( handler2.getPublicKey("h2: getPublic"))); System.out.println( "dec: " + new String( handler2.decrypt(handler1.getPublicKey( "h1: getPublic" ), enc, "h2: decrypt" ))); }catch( Throwable e ){ e.printStackTrace(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/security/CryptoManagerFactory.java0000644000175000017500000000252010527001666026313 0ustar adrianadrian/* * Created on 15 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.security; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.security.impl.CryptoManagerImpl; public class CryptoManagerFactory { public static CryptoManager getSingleton() { try{ return( CryptoManagerImpl.getSingleton()); }catch( Throwable e ){ Debug.out( "Failed to create crypto manager", e ); return( null ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/security/CryptoManagerPasswordException.java0000644000175000017500000000267211012742132030363 0ustar adrianadrian/* * Created on 15 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.security; public class CryptoManagerPasswordException extends CryptoManagerException { private boolean incorrect; public CryptoManagerPasswordException( boolean _incorrect, String _str ) { super( _str ); incorrect = _incorrect; } public CryptoManagerPasswordException( boolean _incorrect, String _str, Throwable _cause ) { super( _str, _cause ); incorrect = _incorrect; } public boolean wasIncorrect() { return( incorrect ); } } azureus-4.3.0.6/com/aelitis/azureus/core/security/CryptoManager.java0000644000175000017500000000327311021145720024757 0ustar adrianadrian/* * Created on 15 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.security; public interface CryptoManager { // don't even THINK about changing this!!!! public static final String CRYPTO_CONFIG_PREFIX = "core.crypto."; public static final int HANDLER_ECC = 1; public static final int[] HANDLERS = { HANDLER_ECC }; public byte[] getSecureID(); public CryptoHandler getECCHandler(); public void clearPasswords(); public void clearPasswords( int password_handler_type ); public void addPasswordHandler( CryptoManagerPasswordHandler handler ); public void removePasswordHandler( CryptoManagerPasswordHandler handler ); public void addKeyListener( CryptoManagerKeyListener listener ); public void removeKeyListener( CryptoManagerKeyListener listener ); } azureus-4.3.0.6/com/aelitis/azureus/core/security/CryptoSTSEngine.java0000644000175000017500000000301010446051054025177 0ustar adrianadrian/* * Created on 20 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.security; import java.nio.ByteBuffer; public interface CryptoSTSEngine { public void getKeys( ByteBuffer message ) throws CryptoManagerException; public void putKeys( ByteBuffer message ) throws CryptoManagerException; public void getAuth( ByteBuffer message ) throws CryptoManagerException; public void putAuth( ByteBuffer message ) throws CryptoManagerException; public byte[] getSharedSecret() throws CryptoManagerException; public byte[] getRemotePublicKey() throws CryptoManagerException; } azureus-4.3.0.6/com/aelitis/azureus/core/security/CryptoManagerPasswordHandler.java0000644000175000017500000000424711022702760030006 0ustar adrianadrian/* * Created on 15 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.security; public interface CryptoManagerPasswordHandler { /** * HANDLER_TYPE_UNKNOWN is not for public use **/ public static final int HANDLER_TYPE_UNKNOWN = 0; public static final int HANDLER_TYPE_USER = 1; public static final int HANDLER_TYPE_SYSTEM = 2; public static final int HANDLER_TYPE_ALL = 3; // just for clearing passwords... public static final int ACTION_ENCRYPT = 1; public static final int ACTION_DECRYPT = 2; public int getHandlerType(); /** * Gets a password * @param handler_type from AESecurityManager.HANDLER_x enum * @param action_type from above ACTION_x enum * @param reason reason for the password being sought * @return password details or null if no password available */ public passwordDetails getPassword( int handler_type, int action_type, boolean last_pw_incorrect, String reason ); public void passwordOK( int handler_type, passwordDetails details ); public interface passwordDetails { public char[] getPassword(); /** * @return 0 -> don't persist, Integer.MAX_VALUE -> persist forever * < 0 -> current session; other -> seconds to persist */ public int getPersistForSeconds(); } } azureus-4.3.0.6/com/aelitis/azureus/core/security/CryptoManagerException.java0000644000175000017500000000231011012742132026625 0ustar adrianadrian/* * Created on 15 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.security; public class CryptoManagerException extends Exception { public CryptoManagerException( String str ) { super( str ); } public CryptoManagerException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/com/aelitis/azureus/core/security/CryptoECCUtils.java0000644000175000017500000001027411036323574025032 0ustar adrianadrian/* * Created on Jul 12, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.security; import java.math.BigInteger; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.spec.KeySpec; import org.bouncycastle.jce.ECNamedCurveTable; import org.bouncycastle.jce.interfaces.ECPrivateKey; import org.bouncycastle.jce.interfaces.ECPublicKey; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.jce.spec.ECParameterSpec; import org.bouncycastle.jce.spec.ECPrivateKeySpec; import org.bouncycastle.jce.spec.ECPublicKeySpec; import org.bouncycastle.math.ec.ECPoint; public class CryptoECCUtils { private static final ECNamedCurveParameterSpec ECCparam = ECNamedCurveTable.getParameterSpec("prime192v2"); public static KeyPair createKeys() throws CryptoManagerException { try { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDSA", "BC"); keyGen.initialize(ECCparam); return keyGen.genKeyPair(); }catch(Throwable e){ throw( new CryptoManagerException( "Failed to create keys", e )); } } public static Signature getSignature( Key key ) throws CryptoManagerException { try { Signature ECCsig = Signature.getInstance("SHA1withECDSA", "BC"); if( key instanceof ECPrivateKey ){ ECCsig.initSign((ECPrivateKey)key); }else if( key instanceof ECPublicKey ){ ECCsig.initVerify((ECPublicKey)key); }else{ throw new CryptoManagerException("Invalid Key Type, ECC keys required"); } return ECCsig; }catch( CryptoManagerException e ){ throw( e ); }catch( Throwable e ){ throw( new CryptoManagerException( "Failed to create Signature", e )); } } public static byte[] keyToRawdata( PrivateKey privkey ) throws CryptoManagerException { if(!(privkey instanceof ECPrivateKey)){ throw( new CryptoManagerException( "Invalid private key" )); } return ((ECPrivateKey)privkey).getD().toByteArray(); } public static PrivateKey rawdataToPrivkey( byte[] input ) throws CryptoManagerException { BigInteger D = new BigInteger(input); KeySpec keyspec = new ECPrivateKeySpec(D,(ECParameterSpec)ECCparam); PrivateKey privkey = null; try{ privkey = KeyFactory.getInstance("ECDSA","BC").generatePrivate(keyspec); return privkey; }catch( Throwable e ){ throw( new CryptoManagerException( "Failed to decode private key" )); } } public static byte[] keyToRawdata( PublicKey pubkey ) throws CryptoManagerException { if(!(pubkey instanceof ECPublicKey)){ throw( new CryptoManagerException( "Invalid public key" )); } return ((ECPublicKey)pubkey).getQ().getEncoded(); } public static PublicKey rawdataToPubkey( byte[] input ) throws CryptoManagerException { ECPoint W = ECCparam.getCurve().decodePoint(input); KeySpec keyspec = new ECPublicKeySpec(W,(ECParameterSpec)ECCparam); try{ return KeyFactory.getInstance("ECDSA", "BC").generatePublic(keyspec); }catch (Throwable e){ throw( new CryptoManagerException( "Failed to decode public key" )); } } } azureus-4.3.0.6/com/aelitis/azureus/core/security/CryptoManagerKeyListener.java0000644000175000017500000000175411021145720027140 0ustar adrianadrian/* * Created on Mar 19, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.security; public interface CryptoManagerKeyListener { public void keyChanged( CryptoHandler handler ); public void keyLockStatusChanged( CryptoHandler handler ); } azureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/0000755000175000017500000000000011310377616023705 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/ClientMessageServiceClient.java0000644000175000017500000000336710373051022031750 0ustar adrianadrian/* * Created on Oct 31, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice; import com.aelitis.azureus.core.clientmessageservice.impl.AEClientService; /** * */ public class ClientMessageServiceClient { /** * Create a new message server service connection. * @param server_address of service * @param server_port of service * @param message type id to use for messages * @return server service connection */ public static ClientMessageService getServerService( String server_address, int server_port, int timeout_secs, String msg_type_id ) { return new AEClientService( server_address, server_port, timeout_secs, msg_type_id ); } public static ClientMessageService getServerService( String server_address, int server_port, String msg_type_id ) { return new AEClientService( server_address, server_port, msg_type_id ); } } azureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/impl/0000755000175000017500000000000011310377620024641 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/impl/ClientMessage.java0000644000175000017500000000437210526772126030245 0ustar adrianadrian/* * Created on Oct 29, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.impl; import java.util.Map; import com.aelitis.azureus.core.clientmessageservice.impl.ClientConnection; /** * */ public class ClientMessage { private final String message_id; private final ClientConnection client; private final Map payload; private ClientMessageHandler handler; private boolean outcome_reported; public ClientMessage( String msg_id, ClientConnection _client, Map msg_payload, ClientMessageHandler _handler ) { this.message_id = msg_id; this.client = _client; this.payload = msg_payload; this.handler = _handler; } public String getMessageID(){ return message_id; } public ClientConnection getClient(){ return client; } public Map getPayload(){ return payload; } public ClientMessageHandler getHandler(){ return handler; } public void setHandler( ClientMessageHandler new_handler ) { this.handler = new_handler; } public void reportComplete() { synchronized( this ){ if ( outcome_reported ){ return; } outcome_reported = true; } handler.sendAttemptCompleted( this ); } public void reportFailed( Throwable error ) { synchronized( this ){ if ( outcome_reported ){ return; } outcome_reported = true; } handler.sendAttemptFailed( this, error ); } } azureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/impl/ClientMessageHandler.java0000644000175000017500000000334610526772126031543 0ustar adrianadrian/* * Created on Oct 24, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.impl; public interface ClientMessageHandler { /** * Get the message type id that this handler handles. * @return */ public String getMessageTypeID(); /** * Process the given message received from a client. * @param message from client to process */ public void processMessage( ClientMessage message ); /** * Notification of reply message send attempt completion. * NOTE: This method will always be called once for every preceeding ClientMessageServer.sendReplyMessage() call. * @param message sent * @param success true if reply send was successful, false if reply send failed */ public void sendAttemptCompleted( ClientMessage message ); public void sendAttemptFailed( ClientMessage message, Throwable error ); } azureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/impl/AEClientService.java0000644000175000017500000001511410776600716030465 0ustar adrianadrian/* * Created on Oct 31, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.impl; import java.io.IOException; import java.nio.ByteBuffer; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Map; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.clientmessageservice.*; import com.aelitis.azureus.core.networkmanager.*; import com.aelitis.azureus.core.networkmanager.impl.tcp.ProtocolEndpointTCP; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPTransportImpl; import com.aelitis.azureus.core.peermanager.messaging.MessageException; import com.aelitis.azureus.core.peermanager.messaging.azureus.*; /** * */ public class AEClientService implements ClientMessageService { private final String address; private final int port; private final String msg_type_id; private final int timeout_secs; private int max_message_bytes = -1; private ClientConnection conn; private final AESemaphore read_block = new AESemaphore( "AEClientService:R" ); private final AESemaphore write_block = new AESemaphore( "AEClientService:W" ); private final ArrayList received_messages = new ArrayList(); private final NonBlockingReadWriteService rw_service; private volatile Throwable error; public AEClientService( String server_address, int server_port, String _msg_type_id ) { this( server_address, server_port, 30, _msg_type_id ); } public AEClientService( String server_address, int server_port, int timeout, String _msg_type_id ) { this.address = server_address; this.port = server_port; this.timeout_secs = timeout; this.msg_type_id = _msg_type_id; try { AZMessageFactory.registerGenericMapPayloadMessageType( msg_type_id ); //register for incoming type decoding } catch( MessageException me ) { /*ignore, since message type probably already registered*/ } rw_service = new NonBlockingReadWriteService( msg_type_id, timeout, 0, new NonBlockingReadWriteService.ServiceListener() { public void messageReceived( ClientMessage message ) { received_messages.add( message.getPayload() ); read_block.release(); } public void connectionError( ClientConnection connection, Throwable msg ) { error = msg; read_block.releaseForever(); write_block.releaseForever(); } }); } //NOTE: blocking op private void connect() throws IOException { InetSocketAddress tcp_target = new InetSocketAddress( address, port ); ConnectionEndpoint ce = new ConnectionEndpoint( tcp_target ); new ProtocolEndpointTCP( ce, tcp_target ); final AESemaphore connect_block = new AESemaphore( "AEClientService:C" ); ce.connectOutbound( false, false, null, null, ProtocolEndpoint.CONNECT_PRIORITY_MEDIUM, new Transport.ConnectListener() { //NOTE: async operation! public void connectAttemptStarted() { /*nothing*/ } public void connectSuccess(Transport transport, ByteBuffer remaining_initial_data ){ conn = new ClientConnection((TCPTransportImpl)transport ); if ( max_message_bytes != -1 ){ conn.setMaximumMessageSize( max_message_bytes ); } connect_block.release(); } public void connectFailure( Throwable failure_msg ) { error = failure_msg; connect_block.release(); } }); if ( !connect_block.reserve( timeout_secs*1000 )){ throw new IOException( "connect op failed: timeout" ); } //connect op finished if( error != null ) { //connect failure close(); throw new IOException( "connect op failed: " + error.getMessage() == null ? "[]" : error.getMessage() ); } rw_service.addClientConnection( conn ); //register for read/write handling } public void sendMessage( Map message ) throws IOException { if( conn == null ) { //not yet connected connect(); } if( error != null ) { close(); throw new IOException( "send op failed: " + error.getMessage() == null ? "[]" : error.getMessage() ); } ClientMessage client_msg = new ClientMessage( msg_type_id, conn, message, new ClientMessageHandler() { public String getMessageTypeID(){ return msg_type_id; } public void processMessage( ClientMessage message ) { Debug.out( "ERROR: should never be called" ); } public void sendAttemptCompleted( ClientMessage message ){ write_block.release(); } public void sendAttemptFailed( ClientMessage message, Throwable cause) { error = cause; write_block.release(); } }); rw_service.sendMessage( client_msg ); //queue message for sending write_block.reserve(); //block until send completes //send op finished if( error != null ) { //connect failure close(); throw new IOException( "send op failed: " + error.getMessage() == null ? "[]" : error.getMessage() ); } } public Map receiveMessage() throws IOException { if( conn == null ) { //not yet connected connect(); } read_block.reserve(); //block until receive completes if( !received_messages.isEmpty() ) { //there were still read messages left from the previous read call Map recv_msg = (Map)received_messages.remove( 0 ); return recv_msg; } //receive op finished if (error == null ){ error = new IOException( "receive op inconsistent" ); } close(); throw new IOException( "receive op failed: " + error.getMessage() == null ? "[]" : error.getMessage() ); } //no handler notification public void close() { if( conn != null ) { rw_service.removeClientConnection( conn ); conn.close( new Exception( "Connection closed" )); } rw_service.destroy(); } public void setMaximumMessageSize( int max_bytes ) { max_message_bytes = max_bytes; } } azureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/impl/NonBlockingReadWriteService.java0000644000175000017500000002351511066631520033045 0ustar adrianadrian/* * Created on Nov 3, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.impl; import java.nio.channels.SocketChannel; import java.util.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.azureus.AZGenericMapPayload; /** * */ public class NonBlockingReadWriteService { private final VirtualChannelSelector read_selector; private final VirtualChannelSelector write_selector; private final ArrayList connections = new ArrayList(); private final AEMonitor connections_mon = new AEMonitor( "connections" ); private final ServiceListener listener; private final String service_name; private volatile boolean destroyed; private long last_timeout_check_time = 0; private static final int TIMEOUT_CHECK_INTERVAL_MS = 10*1000; //check for timeouts every 10sec private final int activity_timeout_period_ms; private final int close_delay_period_ms; public NonBlockingReadWriteService( String _service_name, int timeout, ServiceListener _listener ) { this( _service_name, timeout, 0, _listener ); } public NonBlockingReadWriteService( String _service_name, int timeout, int close_delay, ServiceListener _listener ) { this.service_name = _service_name; this.listener = _listener; read_selector = new VirtualChannelSelector( service_name, VirtualChannelSelector.OP_READ, false ); write_selector = new VirtualChannelSelector( service_name, VirtualChannelSelector.OP_WRITE, true ); if( timeout < TIMEOUT_CHECK_INTERVAL_MS /1000 ) timeout = TIMEOUT_CHECK_INTERVAL_MS /1000; this.activity_timeout_period_ms = timeout *1000; close_delay_period_ms = close_delay * 1000; new AEThread2( "[" +service_name+ "] Service Select", true ) { public void run() { while( true ) { boolean stop_after_select = destroyed; if ( stop_after_select ){ read_selector.destroy(); write_selector.destroy(); } try{ read_selector.select( 50 ); write_selector.select( 50 ); } catch( Throwable t ) { Debug.out( "[" +service_name+ "] SelectorLoop() EXCEPTION: ", t ); } if (stop_after_select){ break; } doConnectionTimeoutChecks(); // check this at the end so we have one last run through the selectors to do cancels // before exiting } } }.start(); } public void destroy() { try { connections_mon.enter(); connections.clear(); destroyed = true; }finally{ connections_mon.exit(); } } public void addClientConnection( ClientConnection connection ) { //add to active list try { connections_mon.enter(); if ( destroyed ){ Debug.out( "connection added after destroy" ); } connections.add( connection ); }finally { connections_mon.exit(); } registerForSelection( connection ); } public void removeClientConnection( ClientConnection connection ) { read_selector.cancel( connection.getSocketChannel() ); write_selector.cancel( connection.getSocketChannel() ); //remove from active list try { connections_mon.enter(); connections.remove( connection ); } finally { connections_mon.exit(); } } private void registerForSelection( final ClientConnection client ) { //READS VirtualChannelSelector.VirtualSelectorListener read_listener = new VirtualChannelSelector.VirtualSelectorListener() { //SUCCESS public boolean selectSuccess( VirtualChannelSelector selector, SocketChannel sc, Object attachment ) { try{ Message[] messages = client.readMessages(); if( messages != null ) { for( int i=0; i < messages.length; i++ ) { AZGenericMapPayload msg = (AZGenericMapPayload)messages[i]; ClientMessage client_msg = new ClientMessage( msg.getID(), client, msg.getMapPayload(), null ); //note no handler. we let the listener attach it listener.messageReceived( client_msg ); } } return( client.getLastReadMadeProgress()); } catch( Throwable t ) { if ( !client.isClosePending()){ System.out.println( "[" +new Date()+ "] Connection read error [" +sc.socket().getInetAddress()+ "] [" +client.getDebugString()+ "]: " +t.getMessage() ); } listener.connectionError( client, t ); return( false ); } } //FAILURE public void selectFailure( VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg ) { if ( !destroyed ){ msg.printStackTrace(); } listener.connectionError( client, msg ); } }; //WRITES final VirtualChannelSelector.VirtualSelectorListener write_listener = new VirtualChannelSelector.VirtualSelectorListener() { public boolean selectSuccess( VirtualChannelSelector selector, SocketChannel sc, Object attachment ) { try{ boolean more_writes_needed = client.writeMessages(); if( more_writes_needed ) { write_selector.resumeSelects( client.getSocketChannel() ); //we need to resume since write selects are auto-paused after select op } return( client.getLastWriteMadeProgress()); } catch( Throwable t ) { System.out.println( "[" +new Date()+ "] Connection write error [" +sc.socket().getInetAddress()+ "] [" +client.getDebugString()+ "]: " +t.getMessage() ); listener.connectionError( client, t ); return( false ); } } public void selectFailure( VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg ) { if ( !destroyed ){ msg.printStackTrace(); } listener.connectionError( client, msg ); } }; write_selector.register( client.getSocketChannel(), write_listener, null ); //start writing back to the connection write_selector.pauseSelects( client.getSocketChannel() ); //wait until we've got something to send before selecting read_selector.register( client.getSocketChannel(), read_listener, null ); //start reading from the connection } private void doConnectionTimeoutChecks() { //check timeouts long time = System.currentTimeMillis(); if( time < last_timeout_check_time || time - last_timeout_check_time > TIMEOUT_CHECK_INTERVAL_MS ) { ArrayList timed_out = new ArrayList(); try { connections_mon.enter(); long current_time = System.currentTimeMillis(); for( int i=0; i < connections.size(); i++ ) { ClientConnection vconn = (ClientConnection)connections.get( i ); if( current_time < vconn.getLastActivityTime() ) { //time went backwards! vconn.resetLastActivityTime(); } else{ if( current_time - vconn.getLastActivityTime() > activity_timeout_period_ms || ( close_delay_period_ms > 0 && current_time - vconn.getLastActivityTime() > close_delay_period_ms )){ timed_out.add( vconn ); //do actual removal outside the check loop } } } } finally { connections_mon.exit(); } for( int i=0; i < timed_out.size(); i++ ) { ClientConnection vconn = (ClientConnection)timed_out.get( i ); // don't change the exception text - it is used elsewhere listener.connectionError( vconn, new Exception( "Timeout" )); } last_timeout_check_time = System.currentTimeMillis(); } } public void sendMessage( ClientMessage message ) { ClientConnection vconn = message.getClient(); boolean still_connected; try { connections_mon.enter(); still_connected = connections.contains( vconn ); } finally { connections_mon.exit(); } if( !still_connected ) { System.out.println( "[" +new Date()+ "] Connection message send error [connection no longer connected]: " +vconn.getDebugString()+ "]" ); message.reportFailed( new Exception("No longer connected" )); //listener.connectionError( vconn ); //no need to call this, as there is no connection to remove return; } Message reply = new AZGenericMapPayload( message.getMessageID(), message.getPayload(), (byte)1 ); vconn.sendMessage( message, reply ); write_selector.resumeSelects( vconn.getSocketChannel() ); //start write selecting now that there's something to send } public interface ServiceListener { public void messageReceived( ClientMessage message ); public void connectionError( ClientConnection connection, Throwable error ); } } azureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/impl/ClientConnection.java0000644000175000017500000001727210757735634030774 0ustar adrianadrian/* * Created on Oct 28, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.impl; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SocketChannel; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.util.AEMonitor; import com.aelitis.azureus.core.networkmanager.*; import com.aelitis.azureus.core.networkmanager.impl.OutgoingMessageQueueImpl; import com.aelitis.azureus.core.networkmanager.impl.tcp.ProtocolEndpointTCP; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPTransportImpl; import com.aelitis.azureus.core.networkmanager.impl.tcp.TransportEndpointTCP; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.azureus.*; /** * */ public class ClientConnection { private Transport parent_transport; private final Transport light_transport; private final OutgoingMessageQueue out_queue; private final AZMessageDecoder decoder; private static final AZMessageEncoder encoder = new AZMessageEncoder( false ); private long last_activity_time; private final AEMonitor msg_mon = new AEMonitor( "ClientConnection" ); private final ArrayList sending_msgs = new ArrayList(); private Map user_data; private boolean close_pending; private boolean closed; private boolean last_write_made_progress; private String debug_string = "<>"; private Throwable closing_reason; /** * Create a new connection based on an incoming socket. * @param channel */ public ClientConnection( SocketChannel channel ) { decoder = new AZMessageDecoder(); InetSocketAddress remote = null; // unfortunately we don't have an address at this point (see NATTestService) ProtocolEndpointTCP pe = new ProtocolEndpointTCP( remote ); light_transport = pe.connectLightWeight( channel ); out_queue = new OutgoingMessageQueueImpl( encoder ); out_queue.setTransport( light_transport ); last_activity_time = System.currentTimeMillis(); } /** * Create a new connection based on an already-established outgoing socket. * @param transport parent */ public ClientConnection( TCPTransportImpl transport ) { this( transport.getSocketChannel() ); //run as a lightweight parent_transport = transport; //save parent for close } /** * Get any messages read from the client. * @return read messages, or null of no new messages were read * @throws IOException on error */ public Message[] readMessages() throws IOException { int bytes_read = decoder.performStreamDecode( light_transport, 1024*1024 ); if( bytes_read > 0 ) last_activity_time = System.currentTimeMillis(); return decoder.removeDecodedMessages(); } public boolean getLastReadMadeProgress() { return( decoder.getLastReadMadeProgress()); } public boolean getLastWriteMadeProgress() { return( last_write_made_progress ); } public void sendMessage( final ClientMessage client_msg, final Message msg ) { try{ msg_mon.enter(); sending_msgs.add( client_msg ); } finally{ msg_mon.exit(); } out_queue.registerQueueListener( new OutgoingMessageQueue.MessageQueueListener() { public boolean messageAdded( Message message ){ return true; } public void messageQueued( Message message ){} public void messageRemoved( Message message ){} public void protocolBytesSent( int byte_count ){} public void dataBytesSent( int byte_count ){} public void flush() {} public void messageSent( Message message ){ if( message.equals( msg ) ) { try{ msg_mon.enter(); sending_msgs.remove( client_msg ); } finally{ msg_mon.exit(); } client_msg.reportComplete(); } } }); out_queue.addMessage( msg, false ); } /** * Write any queued messages back to the client. * @return true if more writing is required, false if all message data has been sent * @throws IOException on error */ public boolean writeMessages() throws IOException { int bytes_written = out_queue.deliverToTransport( 1024*1024, false ); if( bytes_written > 0 ) last_activity_time = System.currentTimeMillis(); last_write_made_progress = bytes_written > 0; return out_queue.getTotalSize() > 0; } //public boolean hasDataToSend() { // return out_queue.getTotalSize() > 0; //} public void close( Throwable reason ) { ClientMessage[] messages = null; try{ msg_mon.enter(); if ( closed ){ return; } closed = true; if( !sending_msgs.isEmpty() ) { messages = (ClientMessage[])sending_msgs.toArray( new ClientMessage[sending_msgs.size()] ); } } finally{ msg_mon.exit(); } if( messages != null ) { if ( reason == null ){ reason = new Exception( "Connection closed" ); } for( int i=0; i < messages.length; i++ ) { ClientMessage msg = messages[i]; msg.reportFailed( reason ); } } decoder.destroy(); out_queue.destroy(); if( parent_transport != null ) { parent_transport.close( "Tidy close"); //have the parent do the close if possible } else { light_transport.close("Tidy close"); } } /** * Marks the socket as complete and ready to undergo any close-delay prior to it being closed * by the server */ public void closePending() { last_activity_time = System.currentTimeMillis(); close_pending = true; } public boolean isClosePending() { return( close_pending ); } public SocketChannel getSocketChannel(){ return ((TransportEndpointTCP)light_transport.getTransportEndpoint()).getSocketChannel(); } /** * Get the last time this connection had read or write activity. * @return system time of last activity */ public long getLastActivityTime() { return last_activity_time; } /** * Reset the last activity time to the current time. */ public void resetLastActivityTime() { last_activity_time = System.currentTimeMillis(); } public void setClosingReason( Throwable r ) { closing_reason = r; } public Throwable getClosingReason() { return( closing_reason ); } public Object getUserData( Object key ) { Map m = user_data; if ( m == null ){ return( null ); } return( m.get(key)); } public void setUserData( Object key, Object data ) { try{ msg_mon.enter(); // assumption is write infrequently, read often -> copy-on-write Map m = (user_data==null)?new HashMap():new HashMap( user_data ); m.put( key, data ); user_data = m; }finally{ msg_mon.exit(); } } public void setDebugString( String debug ) { debug_string = debug; } public String getDebugString() { return debug_string; } public void setMaximumMessageSize( int max_bytes ) { if ( decoder != null ){ decoder.setMaximumMessageSize( max_bytes ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/ClientMessageService.java0000644000175000017500000000332210507034156030610 0ustar adrianadrian/* * Created on Oct 31, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice; import java.io.IOException; import java.util.Map; /** * */ public interface ClientMessageService { /** * Send the given message to the server service. * NOTE: blocking op * @param message (bencode-able) to send * @throws IOException on error */ public void sendMessage( Map message ) throws IOException; /** * Receive the next message from the server. * NOTE: blocking op * @return message received * @throws IOException on error */ public Map receiveMessage() throws IOException; /** * Drop and closedown the connection with the server. */ public void close(); /** * Override the default max message size * @param max_bytes */ public void setMaximumMessageSize( int max_bytes ); } azureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/0000755000175000017500000000000011310377620025166 5ustar adrianadrian././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientMessage.javaazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientMessa0000644000175000017500000000233110373051004033305 0ustar adrianadrian/* * Created on 07-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.secure; import java.util.Map; public interface SecureMessageServiceClientMessage { public Map getRequest(); public Map getReply(); public Object getClientData(); public void cancel(); public String getString(); } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientAdapter.javaazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientAdapt0000644000175000017500000000263310373051004033273 0ustar adrianadrian/* * Created on 11-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.secure; public interface SecureMessageServiceClientAdapter { public void serverOK(); public void serverFailed( Throwable cause ); public String getUser(); public byte[] getPassword(); public void authenticationFailed(); public long getMessageSequence(); public void setMessageSequence( long sequence ); public void log( String str ); public void log( String str, Throwable e ); } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClient.javaazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClient.java0000644000175000017500000000336410373051004033243 0ustar adrianadrian/* * Created on 03-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.secure; import java.util.Map; public interface SecureMessageServiceClient { public SecureMessageServiceClientMessage sendMessage( Map request, Object client_data, String description ); /** * This shouldn't be required under normal circumstances as message addition causes * dispatch and the server handles retries itself. However, sometimes it is necessary to * force a dispatch to occur (e.g. to validate new authentication information immediately * rather than wait for it to happen naturally) */ public void sendMessages(); public SecureMessageServiceClientMessage[] getMessages(); public void addListener( SecureMessageServiceClientListener l ); public void removeListener( SecureMessageServiceClientListener l ); } azureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/impl/0000755000175000017500000000000011310377620026127 5ustar adrianadrian././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientImpl.javaazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClient0000644000175000017500000002553310377315722033304 0ustar adrianadrian/* * Created on 03-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.secure.impl; import java.security.interfaces.RSAPublicKey; import java.util.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.clientmessageservice.ClientMessageService; import com.aelitis.azureus.core.clientmessageservice.secure.SecureMessageServiceClient; import com.aelitis.azureus.core.clientmessageservice.secure.SecureMessageServiceClientAdapter; import com.aelitis.azureus.core.clientmessageservice.secure.SecureMessageServiceClientListener; import com.aelitis.azureus.core.clientmessageservice.secure.SecureMessageServiceClientMessage; public class SecureMessageServiceClientImpl implements SecureMessageServiceClient { // these also occur in the server public static final int STATUS_OK = 0; public static final int STATUS_LOGON_FAIL = 1; public static final int STATUS_INVALID_SEQUENCE = 2; public static final int STATUS_FAILED = 3; public static final int STATUS_ABORT = 4; public static final String SERVICE_NAME = "SecureMsgServ"; private static final long MIN_RETRY_PERIOD = 5*60*1000; private static final long MAX_RETRY_PERIOD = 2*60*60*1000; private String host; private int port; private int timeout_secs; private RSAPublicKey public_key; private SecureMessageServiceClientAdapter adapter; private long retry_millis = MIN_RETRY_PERIOD; private int connect_failure_count = 0; private AEMonitor message_mon; private AESemaphore message_sem; private String last_failed_user_pw = ""; private long last_failed_user_pw_time; private List messages = new ArrayList(); private List listeners = new ArrayList(); public SecureMessageServiceClientImpl( String _host, int _port, int _timeout_secs, RSAPublicKey _key, SecureMessageServiceClientAdapter _adapter ) { host = _host; port = _port; timeout_secs = _timeout_secs; public_key = _key; adapter = _adapter; message_mon = new AEMonitor( "SecureService:messages" ); message_sem = new AESemaphore( "SecureService:messages" ); new AEThread( "SecureService::messageSender", true ) { public void runSupport() { while( true ){ long time = retry_millis; if ( connect_failure_count > 0 ){ for (int i=0;i MAX_RETRY_PERIOD ){ time = MAX_RETRY_PERIOD; break; } } } message_sem.reserve( time ); try{ sendMessagesSupport(); }catch( Throwable e ){ adapter.log( "Request processing failed", e); } } } }.start(); } public void sendMessages() { message_sem.release(); } protected void sendMessagesSupport() { String user = adapter.getUser(); byte[] password = adapter.getPassword(); String user_password = user + "/" + new String( password ); // user name must be defined, however we allow a blank password if ( user.length() == 0 ){ adapter.authenticationFailed(); return; } // if user-name + password hasn't changed recently and logon failed then // don't re-attempt if ( user_password.equals( last_failed_user_pw )){ final long now =SystemTime.getCurrentTime(); if (now >last_failed_user_pw_time &&now -last_failed_user_pw_time <60 *1000){ adapter.authenticationFailed(); return; } } List outstanding_messages; try{ message_mon.enter(); outstanding_messages = new ArrayList( messages ); }finally{ message_mon.exit(); } if ( outstanding_messages.size() == 0 ){ return; } List complete_messages = new ArrayList(); boolean failed = false; try{ Iterator it = outstanding_messages.iterator(); while( it.hasNext() && !failed ){ SecureMessageServiceClientMessageImpl message = (SecureMessageServiceClientMessageImpl)it.next(); boolean retry = true; int retry_count = 0; while( retry && !failed ){ retry = false; ClientMessageService message_service = null; boolean got_reply = false; try{ Map content = new HashMap(); long sequence = adapter.getMessageSequence(); content.put( "user", user ); content.put( "password", password ); content.put( "seq", new Long( sequence )); content.put( "request", message.getRequest()); last_failed_user_pw = ""; message_service = SecureMessageServiceClientHelper.getServerService( host, port, timeout_secs, SERVICE_NAME, public_key ); message_service.sendMessage( content ); Map reply = message_service.receiveMessage(); got_reply = true; long status = ((Long)reply.get( "status" )).longValue(); Long new_retry = (Long)reply.get( "retry" ); if ( new_retry != null ){ retry_millis = new_retry.longValue(); if ( retry_millis < MIN_RETRY_PERIOD ){ retry_millis = MIN_RETRY_PERIOD; } adapter.log( "Server requested retry period of " + (retry_millis/1000) + " seconds" ); }else{ retry_millis = MIN_RETRY_PERIOD; } if ( status == STATUS_OK ){ message.setReply( (Map)reply.get( "reply" )); adapter.log( "Request successfully sent: " + message.getRequest() + "->" + message.getReply()); adapter.setMessageSequence( sequence + 1 ); adapter.serverOK(); for (Iterator l_it=listeners.iterator();l_it.hasNext();){ try{ ((SecureMessageServiceClientListener)l_it.next()).complete( message ); }catch( Throwable e ){ e.printStackTrace(); } } complete_messages.add( message ); }else if ( status == STATUS_LOGON_FAIL ){ last_failed_user_pw = user_password; last_failed_user_pw_time = SystemTime.getCurrentTime(); adapter.serverOK(); adapter.authenticationFailed(); failed = true; }else if ( status == STATUS_INVALID_SEQUENCE ){ if ( retry_count == 1 ){ adapter.serverFailed( new Exception( "Sequence resynchronisation failed" )); failed = true; }else{ retry_count++; retry = true; long expected_sequence = ((Long)reply.get( "seq" )).longValue(); adapter.log( "Sequence resynchronise: local = " + sequence + ", remote = " + expected_sequence ); adapter.setMessageSequence( expected_sequence ); } }else if ( status == STATUS_FAILED ){ adapter.serverFailed( new Exception( new String( (byte[])reply.get( "error" )))); failed = true; }else{// if ( status == STATUS_ABORT ){ // this is when things have gone badly wrong server-side - we just // dump the message adapter.serverFailed( new Exception( "Server requested abort" )); for (Iterator l_it=listeners.iterator();l_it.hasNext();){ try{ ((SecureMessageServiceClientListener)l_it.next()).aborted( message, new String( (byte[])reply.get( "error" ))); }catch( Throwable e ){ e.printStackTrace(); } } complete_messages.add( message ); } }catch( Throwable e ){ adapter.serverFailed( e ); failed = true; }finally{ if ( got_reply ){ connect_failure_count = 0; }else{ connect_failure_count++; if ( connect_failure_count > 1 ){ try{ adapter.log( "Failed to contact server " + connect_failure_count + " times in a row" ); }catch( Throwable e ){ e.printStackTrace(); } } } if ( message_service != null ){ message_service.close(); } } } } }catch( Throwable e ){ adapter.serverFailed( e ); }finally{ try{ message_mon.enter(); messages.removeAll( complete_messages ); }finally{ message_mon.exit(); } } } public SecureMessageServiceClientMessage sendMessage( Map request, Object data, String description ) { try{ message_mon.enter(); SecureMessageServiceClientMessage res = new SecureMessageServiceClientMessageImpl( this, request, data, description ); messages.add( res ); message_sem.release(); return( res ); }finally{ message_mon.exit(); } } protected void cancel( SecureMessageServiceClientMessage message ) { boolean inform = false; try{ message_mon.enter(); if ( messages.remove( message )){ inform = true; } }finally{ message_mon.exit(); } if ( inform ){ for (Iterator it=listeners.iterator();it.hasNext();){ try{ ((SecureMessageServiceClientListener)it.next()).cancelled( message ); }catch( Throwable e ){ e.printStackTrace(); } } } } public SecureMessageServiceClientMessage[] getMessages() { try{ message_mon.enter(); return((SecureMessageServiceClientMessage[])messages.toArray( new SecureMessageServiceClientMessage[ messages.size()])); }finally{ message_mon.exit(); } } public void addListener( SecureMessageServiceClientListener l ) { listeners.add( l ); } public void removeListener( SecureMessageServiceClientListener l ) { listeners.remove( l ); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientHelper.javaazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClient0000644000175000017500000001237711147377516033313 0ustar adrianadrian/* * Created on 08-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.secure.impl; import java.io.IOException; import java.security.SecureRandom; import java.security.interfaces.RSAPublicKey; import java.util.HashMap; import java.util.Map; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.encodings.PKCS1Encoding; import org.bouncycastle.crypto.engines.RSAEngine; import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.jce.provider.RSAUtil; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.RandomUtils; import org.gudy.azureus2.plugins.utils.StaticUtilities; import com.aelitis.azureus.core.clientmessageservice.ClientMessageService; import com.aelitis.azureus.core.clientmessageservice.ClientMessageServiceClient; public class SecureMessageServiceClientHelper implements ClientMessageService { public static ClientMessageService getServerService( String server_address, int server_port, int timeout_secs, String msg_type_id, RSAPublicKey public_key ) throws IOException { return new SecureMessageServiceClientHelper( server_address, server_port, timeout_secs, msg_type_id, public_key ); } private ClientMessageService delegate; private SecretKey session_key; private byte[] encryped_session_key; protected SecureMessageServiceClientHelper( String server_address, int server_port, int timeout_secs, String msg_type_id, RSAPublicKey public_key ) throws IOException { try{ KeyGenerator secret_key_gen = KeyGenerator.getInstance("DESede"); session_key = secret_key_gen.generateKey(); byte[] secret_bytes = session_key.getEncoded(); try{ Cipher rsa_cipher = Cipher.getInstance( "RSA" ); rsa_cipher.init( Cipher.ENCRYPT_MODE, public_key ); encryped_session_key = rsa_cipher.doFinal( secret_bytes ); }catch( Throwable e ){ // fallback to the BC implementation for jdk1.4.2 as JCE RSA not available RSAEngine eng = new RSAEngine(); PKCS1Encoding padded_eng = new PKCS1Encoding( eng ); CipherParameters param = RSAUtil.generatePublicKeyParameter(public_key); param = new ParametersWithRandom(param, RandomUtils.SECURE_RANDOM); padded_eng.init( true, param ); encryped_session_key = padded_eng.processBlock(secret_bytes, 0, secret_bytes.length); } }catch( Throwable e ){ e.printStackTrace(); throw( new IOException( "Secure client message service initialisation fails - " + Debug.getNestedExceptionMessage(e))); } delegate = ClientMessageServiceClient.getServerService( server_address, server_port, msg_type_id ); } public void sendMessage( Map plain_payload ) throws IOException { Map secure_payload = new HashMap(); try{ byte[] message_bytes = StaticUtilities.getFormatters().bEncode( plain_payload ); Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, session_key ); byte[] encrypted_message = cipher.doFinal( message_bytes ); secure_payload.put( "ver", "1" ); secure_payload.put( "alg", "DESede" ); secure_payload.put( "key", encryped_session_key ); secure_payload.put( "content", encrypted_message ); }catch( Throwable e ){ throw( new IOException( "send message failed - " + Debug.getNestedExceptionMessage(e))); } delegate.sendMessage( secure_payload ); } public Map receiveMessage() throws IOException { Map secure_payload = delegate.receiveMessage(); byte[] encrypted_message = (byte[])secure_payload.get( "content" ); try{ Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, session_key ); byte[] message_bytes = cipher.doFinal( encrypted_message ); Map plain_payload = StaticUtilities.getFormatters().bDecode( message_bytes ); return( plain_payload ); }catch( Throwable e ){ throw( new IOException( "send message failed - " + Debug.getNestedExceptionMessage(e))); } } public void close() { delegate.close(); } public void setMaximumMessageSize( int max_bytes ) { delegate.setMaximumMessageSize( max_bytes ); } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientMessageImpl.javaazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClient0000644000175000017500000000375710373051032033273 0ustar adrianadrian/* * Created on 07-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.secure.impl; import java.util.Map; import com.aelitis.azureus.core.clientmessageservice.secure.SecureMessageServiceClientMessage; public class SecureMessageServiceClientMessageImpl implements SecureMessageServiceClientMessage { private SecureMessageServiceClientImpl service; private Map request; private Map reply; private Object client_data; private String description; protected SecureMessageServiceClientMessageImpl( SecureMessageServiceClientImpl _service, Map _content, Object _data, String _description ) { service = _service; request = _content; client_data = _data; description = _description; } public Map getRequest() { return( request ); } protected void setReply( Map _reply ) { reply = _reply; } public Map getReply() { return( reply ); } public Object getClientData() { return( client_data ); } public void cancel() { service.cancel( this ); } public String getString() { return( description ); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientFactory.javaazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientFacto0000644000175000017500000000276611045724240033313 0ustar adrianadrian/* * Created on 03-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.secure; import java.security.interfaces.RSAPublicKey; import com.aelitis.azureus.core.clientmessageservice.secure.impl.SecureMessageServiceClientImpl; public class SecureMessageServiceClientFactory { /** * Used by the SMS plugin. */ public static SecureMessageServiceClient create( String host, int port, int timeout_secs, RSAPublicKey key, SecureMessageServiceClientAdapter adapter ) { return( new SecureMessageServiceClientImpl(host, port, timeout_secs, key, adapter)); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientListener.javaazureus-4.3.0.6/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientListe0000644000175000017500000000244310373051004033321 0ustar adrianadrian/* * Created on 07-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.clientmessageservice.secure; public interface SecureMessageServiceClientListener { public void complete( SecureMessageServiceClientMessage message ); public void cancelled( SecureMessageServiceClientMessage message ); public void aborted( SecureMessageServiceClientMessage message, String reason ); } azureus-4.3.0.6/com/aelitis/azureus/core/AzureusCore.java0000644000175000017500000000754411001076456022620 0ustar adrianadrian/* * Created on 13-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core; /** * @author parg * */ import org.gudy.azureus2.core3.tracker.host.TRHost; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.ipfilter.IpFilterManager; import org.gudy.azureus2.core3.internat.LocaleUtil; import org.gudy.azureus2.plugins.*; import com.aelitis.azureus.core.instancemanager.AZInstanceManager; import com.aelitis.azureus.core.nat.NATTraverser; import com.aelitis.azureus.core.security.CryptoManager; import com.aelitis.azureus.core.speedmanager.SpeedManager; public interface AzureusCore { public void start() throws AzureusCoreException; public boolean isStarted(); /** * stop the core and inform lifecycle listeners of stopping * @throws AzureusCoreException */ public void stop() throws AzureusCoreException; /** * ask lifecycle listeners to perform a stop. they may veto this by throwing an exception, or do nothing * if nothing is done then it will be stopped as per "stop" above * @throws AzureusCoreException */ public void requestStop() throws AzureusCoreException; /** * checks if restart operation is supported - if not an alert will be raised and an exception thrown * @throws AzureusCoreException */ public void checkRestartSupported() throws AzureusCoreException; /** * restart the system */ public void restart(); /** * request a restart of the system - currently only available for swt based systems * @throws AzureusCoreException */ public void requestRestart() throws AzureusCoreException; /** * * @return * @since 3053 */ public boolean isRestarting(); public LocaleUtil getLocaleUtil(); public GlobalManager getGlobalManager() throws AzureusCoreException; public PluginManagerDefaults getPluginManagerDefaults() throws AzureusCoreException; public PluginManager getPluginManager() throws AzureusCoreException; public TRHost getTrackerHost() throws AzureusCoreException; public IpFilterManager getIpFilterManager() throws AzureusCoreException; public AZInstanceManager getInstanceManager(); public SpeedManager getSpeedManager(); public CryptoManager getCryptoManager(); public NATTraverser getNATTraverser(); public AzureusCoreOperation createOperation( int type ); public void createOperation( int type, AzureusCoreOperationTask task ); public void addLifecycleListener( AzureusCoreLifecycleListener l ); public void removeLifecycleListener( AzureusCoreLifecycleListener l ); public void addListener( AzureusCoreListener l ); public void removeListener( AzureusCoreListener l ); public void addOperationListener( AzureusCoreOperationListener l ); public void removeOperationListener( AzureusCoreOperationListener l ); /** * @param component */ void triggerLifeCycleComponentCreated(AzureusCoreComponent component); } azureus-4.3.0.6/com/aelitis/azureus/core/download/0000755000175000017500000000000011310377624021307 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/download/DiskManagerFileInfoFile.java0000644000175000017500000001623511156364746026573 0ustar adrianadrian/* * Created on Feb 11, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.download; import java.io.File; import java.io.RandomAccessFile; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SHA1Simple; import org.gudy.azureus2.plugins.disk.DiskManagerChannel; import org.gudy.azureus2.plugins.disk.DiskManagerEvent; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.disk.DiskManagerListener; import org.gudy.azureus2.plugins.disk.DiskManagerRequest; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadException; import org.gudy.azureus2.plugins.utils.PooledByteBuffer; import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl; import com.aelitis.azureus.core.util.CopyOnWriteList; public class DiskManagerFileInfoFile implements DiskManagerFileInfo { private byte[] hash; private File file; public DiskManagerFileInfoFile( File _file ) { file = _file; try{ hash = new SHA1Simple().calculateHash( file.getAbsolutePath().getBytes( "UTF-8" )); }catch( Throwable e ){ Debug.out(e); } } public void setPriority( boolean b ) { } public void setSkipped( boolean b ) { throw( new RuntimeException( "Not supported" )); } public void setDeleted(boolean b) { } public void setLink( File link_destination ) { throw( new RuntimeException( "Not supported" )); } public File getLink() { return( null ); } public int getAccessMode() { return( READ ); } public long getDownloaded() { return( getLength()); } public long getLength() { return( file.length()); } public File getFile() { return( file ); } public int getIndex() { return( 0 ); } public int getFirstPieceNumber() { return( 0 ); } public long getPieceSize() { return( 32*1024 ); } public int getNumPieces() { long piece_size = getPieceSize(); return((int)(( getLength() + piece_size - 1 ) / piece_size )); } public boolean isPriority() { return( false ); } public boolean isSkipped() { return( false ); } public boolean isDeleted() { return( false ); } public byte[] getDownloadHash() { return( hash ); } public Download getDownload() throws DownloadException { throw( new DownloadException( "Not supported" )); } public DiskManagerChannel createChannel() throws DownloadException { return( new channel()); } protected class channel implements DiskManagerChannel { private volatile boolean destroyed; public DiskManagerRequest createRequest() { return( new request()); } public DiskManagerFileInfo getFile() { return( DiskManagerFileInfoFile.this ); } public void destroy() { destroyed = true; } protected class request implements DiskManagerRequest { private long offset; private long length; private long position; private int max_read_chunk = 128*1024;; private volatile boolean cancelled; private CopyOnWriteList listeners = new CopyOnWriteList(); public void setType( int type ) { if ( type != DiskManagerRequest.REQUEST_READ ){ throw( new RuntimeException( "Not supported" )); } } public void setOffset( long _offset ) { offset = _offset; } public void setLength( long _length ) { if ( _length < 0 ){ throw( new RuntimeException( "Illegal argument" )); } length = _length; } public void setMaximumReadChunkSize( int size ) { max_read_chunk = size; } public long getAvailableBytes() { return( getRemaining()); } public long getRemaining() { return( offset + length - position ); } public void run() { RandomAccessFile raf = null; try{ raf = new RandomAccessFile( file, "r" ); raf.seek( offset ); byte[] buffer = new byte[max_read_chunk]; long rem = length; long pos = offset; while( rem > 0 ){ if ( cancelled ){ throw( new Exception( "Cancelled" )); }else if ( destroyed ){ throw( new Exception( "Destroyed" )); } int chunk = (int)Math.min( rem, max_read_chunk ); int len = raf.read( buffer, 0, chunk ); sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len )); rem -= len; pos += len; } }catch( Throwable e ){ sendEvent( new event( e )); }finally{ if ( raf != null ){ try{ raf.close(); }catch( Throwable e ){ Debug.out( e ); } } } } public void cancel() { cancelled = true; } public void setUserAgent( String agent ) { } protected void sendEvent( event ev ) { for ( DiskManagerListener l: listeners ){ l.eventOccurred( ev ); } } public void addListener( DiskManagerListener listener ) { listeners.add( listener ); } public void removeListener( DiskManagerListener listener ) { listeners.remove( listener ); } protected class event implements DiskManagerEvent { private int event_type; private Throwable error; private PooledByteBuffer buffer; private long event_offset; private int event_length; protected event( Throwable _error ) { event_type = DiskManagerEvent.EVENT_TYPE_FAILED; error = _error; } protected event( PooledByteBuffer _buffer, long _offset, int _length ) { event_type = DiskManagerEvent.EVENT_TYPE_SUCCESS; buffer = _buffer; event_offset = _offset; event_length = _length; } public int getType() { return( event_type ); } public DiskManagerRequest getRequest() { return( request.this ); } public long getOffset() { return( event_offset ); } public int getLength() { return( event_length ); } public PooledByteBuffer getBuffer() { return( buffer ); } public Throwable getFailure() { return( error ); } } } } } azureus-4.3.0.6/com/aelitis/azureus/core/download/EnhancedDownloadManagerFile.java0000644000175000017500000000661310737575136027462 0ustar adrianadrian/* * Created on Sep 9, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.download; import java.util.*; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.util.Debug; public class EnhancedDownloadManagerFile { private DiskManagerFileInfo file; private long offset; private int header_size; private int[][] speeds; protected EnhancedDownloadManagerFile( DiskManagerFileInfo _file, long _offset, Map _map ) { file = _file; offset = _offset; try{ if ( _map != null ){ Long l_header_size = (Long)_map.get( "header_size" ); if ( l_header_size != null ){ header_size = l_header_size.intValue(); } List stream_info = (List)_map.get( "stream_info" ); if ( stream_info != null ){ speeds = new int[stream_info.size()][]; for (int i=0;i 0 ){ boolean found = false; int k_rate = (int)rate/1024; for (int i=0;i speeds[i][0] ){ // use the init buffer rather than the worst one buffer_size = speeds[i][2] * 1024; found = true; break; } } if ( !found ){ buffer_size = speeds[speeds.length-1][2] * 1024; } } // System.out.println( "getInitialBufferBytes(" + rate + ") -> " + header_size + "/" + buffer_size ); return( header_size + buffer_size ); } public String getString() { String speeds_str = ""; if ( speeds != null ){ speeds_str = ",speeds="; for (int i=0;i it = download_map.values().iterator(); while( it.hasNext()){ EnhancedDownloadManager edm = it.next(); if ( b_hash != null ){ byte[] d_hash = edm.getHash(); if ( d_hash != null && Arrays.equals( b_hash, d_hash )){ // if its complete then obviously 0 if ( edm.getDownloadManager().isDownloadComplete( false )){ return( 0 ); } if ( !edm.supportsProgressiveMode()){ return( Integer.MIN_VALUE ); } if ( !edm.getProgressiveMode()){ edm.setProgressiveMode( true ); } long eta = edm.getProgressivePlayETA(); if ( eta > Integer.MAX_VALUE ){ return( Integer.MAX_VALUE ); } return((int)eta); } }else{ if ( edm.getProgressiveMode()){ long eta = edm.getProgressivePlayETA(); if ( eta > Integer.MAX_VALUE ){ return( Integer.MAX_VALUE ); } return((int)eta); } } } } } return( Integer.MIN_VALUE ); } }); SimpleTimer.addPeriodicEvent( "DownloadManagerEnhancer:speedChecker", TICK_PERIOD, new TimerEventPerformer() { private int tick_count; public void perform( TimerEvent event ) { tick_count++; List downloads = core.getGlobalManager().getDownloadManagers(); for ( int i=0;i iter = download_map.keySet().iterator(); iter.hasNext();) { DownloadManager dm = iter.next(); TOTorrent torrent = dm.getTorrent(); if (PlatformTorrentUtils.isContent(torrent, true)) { String thisHash = PlatformTorrentUtils.getContentHash(torrent); if (hash.equals(thisHash)) { return dm; } } } } return null; } } azureus-4.3.0.6/com/aelitis/azureus/core/download/EnhancedDownloadManager.java0000644000175000017500000021671311300722006026637 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.download; import java.net.InetAddress; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.disk.DiskManagerPiece; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerListener; import org.gudy.azureus2.core3.download.DownloadManagerPeerListener; import org.gudy.azureus2.core3.download.impl.DownloadManagerAdapter; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.peer.*; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peer.cache.CacheDiscovery; import com.aelitis.azureus.core.peer.cache.CachePeer; import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker; import com.aelitis.azureus.core.peermanager.piecepicker.PieceRTAProvider; import com.aelitis.azureus.core.peermanager.utils.PeerClassifier; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.core.util.average.Average; import com.aelitis.azureus.core.util.average.AverageFactory; import com.aelitis.azureus.plugins.extseed.ExternalSeedException; import com.aelitis.azureus.plugins.extseed.ExternalSeedManualPeer; import com.aelitis.azureus.plugins.extseed.ExternalSeedPlugin; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.DownloadUtils; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.peers.PeerManager; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl; public class EnhancedDownloadManager { public static int DEFAULT_MINIMUM_INITIAL_BUFFER_SECS_FOR_ETA = 30; public static int WMP_MINIMUM_INITIAL_BUFFER_SECS_FOR_ETA = 60; // number of seconds of buffer required before we fall back to normal bt mode public static int MINIMUM_INITIAL_BUFFER_SECS; static{ COConfigurationManager.addAndFireParameterListeners( new String[]{ "filechannel.rt.buffer.millis" }, new ParameterListener() { public void parameterChanged( String parameterName ) { int channel_buffer_millis = COConfigurationManager.getIntParameter( "filechannel.rt.buffer.millis" ); MINIMUM_INITIAL_BUFFER_SECS = (2 * channel_buffer_millis )/1000; } }); } public static final int SPEED_CONTROL_INITIAL_DELAY = 10*1000; public static final int SPEED_INCREASE_GRACE_PERIOD = 3*1000; public static final int PEER_INJECT_GRACE_PERIOD = 3*1000; public static final int IDLE_PEER_DISCONNECT_PERIOD = 60*1000; public static final int IDLE_SEED_DISCONNECT_PERIOD = 60*1000; public static final int MIN_SEED_CONNECTION_TIME = 60*1000; public static final int IDLE_SEED_DISCONNECT_SECS = IDLE_SEED_DISCONNECT_PERIOD/1000; public static final int CACHE_RECONNECT_MIN_PERIOD = 15*60*1000; public static final int CACHE_REQUERY_MIN_PERIOD = 60*60*1000; public static final int TARGET_SPEED_EXCESS_MARGIN = 2*1024; public static final int DISCONNECT_CHECK_PERIOD = 10*1000; public static final int DISCONNECT_CHECK_TICKS = DISCONNECT_CHECK_PERIOD/DownloadManagerEnhancer.TICK_PERIOD; public static final int REACTIVATE_PROVIDER_PERIOD = 5*1000; public static final int REACTIVATE_PROVIDER_PERIOD_TICKS = REACTIVATE_PROVIDER_PERIOD/DownloadManagerEnhancer.TICK_PERIOD; public static final int LOG_PROG_STATS_PERIOD = 10*1000; public static final int LOG_PROG_STATS_TICKS = LOG_PROG_STATS_PERIOD/DownloadManagerEnhancer.TICK_PERIOD; private static final String TRACKER_PROG_PREFIX = "azprog"; private static final String PM_SEED_TIME_KEY = "EnhancedDownloadManager:seedtime"; private static final String PEER_CACHE_KEY = "EnhancedDownloadManager:cachepeer"; private static int internal_content_stream_bps_increase_ratio = 5; private static int internal_content_stream_bps_increase_absolute = 0; // these are here to allow other components (e.g. a plugin) to modify behaviour // while we verify that things work ok public static void setInternalContentStreamBPSIncreaseRatio( String caller_id, int ratio ) { internal_content_stream_bps_increase_ratio = ratio; } public static void setInternalContentStreamBPSIncreaseAbsolute( String caller_id, int abs ) { internal_content_stream_bps_increase_absolute = abs; } private DownloadManagerEnhancer enhancer; private DownloadManager download_manager; private boolean platform_content; private transient PiecePicker current_piece_pickler; private boolean progressive_active = false; private long content_min_delivery_bps; private int minimum_initial_buffer_secs_for_eta; private int explicit_minimum_buffer_bytes; private bufferETAProvider buffer_provider = new bufferETAProvider(); private boostETAProvider boost_provider = new boostETAProvider(); private progressiveStats progressive_stats; private boolean progressive_informed = false; private long time_download_started; private Average download_speed_average = AverageFactory.MovingImmediateAverage( 5 ); private boolean marked_active; private boolean destroyed; private DownloadManagerListener dmListener; private static final int STALLED_TIMEOUT = 2*60*1000; private boolean publish_handling_complete; private long publish_sent = -1; private long publish_sent_time; private EnhancedDownloadManagerFile[] enhanced_files; private EnhancedDownloadManagerFile primary_file; // ********* reset these in resetVars *********** private long last_speed_increase; private long last_peer_inject; private long last_lookup_time; private LinkedList new_peers; private List cache_peers; private List disconnected_cache_peers; private CachePeer[] lookup_peers; private void resetVars() { last_speed_increase = 0; last_peer_inject = 0; last_lookup_time = 0; new_peers = null; cache_peers = null; disconnected_cache_peers = null; lookup_peers = null; } protected EnhancedDownloadManager( DownloadManagerEnhancer _enhancer, DownloadManager _download_manager ) { enhancer = _enhancer; download_manager = _download_manager; DiskManagerFileInfo[] files = download_manager.getDiskManagerFileInfo(); // hack - we don't know the actual player until play starts so we just use the file name // TODO: we can probably read the registry to work out what player is associated with // the file extension? boolean found_wmv = false; for (int i=0;i= 0 && primary_index < files.length ){ primary_file = enhanced_files[primary_index]; }else{ primary_file = enhanced_files[0]; } }else{ enhanced_files = new EnhancedDownloadManagerFile[0]; } progressive_stats = createProgressiveStats( download_manager, primary_file ); download_manager.addPeerListener( new DownloadManagerPeerListener() { public void peerManagerWillBeAdded( PEPeerManager peer_manager ) { } public void peerManagerAdded( PEPeerManager manager ) { synchronized( EnhancedDownloadManager.this ){ time_download_started = SystemTime.getCurrentTime(); current_piece_pickler = manager.getPiecePicker(); if ( progressive_active && current_piece_pickler != null ){ buffer_provider.activate( current_piece_pickler ); boost_provider.activate( current_piece_pickler ); } resetVars(); } } public void peerManagerRemoved( PEPeerManager manager ) { synchronized( EnhancedDownloadManager.this ){ time_download_started = 0; progressive_active = false; if ( current_piece_pickler != null ){ buffer_provider.deactivate( current_piece_pickler ); boost_provider.deactivate( current_piece_pickler ); current_piece_pickler = null; } resetVars(); } } public void peerAdded( PEPeer peer ) { if ( platform_content ){ synchronized( EnhancedDownloadManager.this ){ if ( new_peers == null ){ new_peers = new LinkedList(); } new_peers.add( peer ); } } } public void peerRemoved( PEPeer peer ) { if ( platform_content ){ synchronized( EnhancedDownloadManager.this ){ if ( new_peers != null ){ new_peers.remove( peer ); if ( new_peers.size() == 0 ){ new_peers = null; } } if ( cache_peers != null ){ cache_peers.remove( peer ); if ( cache_peers.size() == 0 ){ cache_peers = null; } } CachePeer cache_peer = (CachePeer)peer.getData( PEER_CACHE_KEY ); if ( cache_peer == null ){ // we can disconnect before getting peer-id etc if ( lookup_peers != null ){ for (int i=0;i infinite if ( secs_since_last_up == -1 ){ Long seed_time = (Long)pm.getData( PM_SEED_TIME_KEY ); if ( seed_time == null ){ seed_time = new Long( now ); pm.setData( PM_SEED_TIME_KEY, seed_time ); } secs_since_last_up = (int)(( now - seed_time.longValue()) / 1000); } List peers_to_kick = new ArrayList(); synchronized( this ){ if ( new_peers != null ){ Iterator it = new_peers.iterator(); while( it.hasNext()){ PEPeer peer = (PEPeer)it.next(); CachePeer cache_peer = (CachePeer)peer.getData( PEER_CACHE_KEY ); if ( cache_peer == null ){ byte[] peer_id = peer.getId(); if ( peer_id != null ){ try{ cache_peer = CacheDiscovery.categorisePeer( peer_id, InetAddress.getByName( peer.getIp()), peer.getPort()); peer.setData( PEER_CACHE_KEY, cache_peer ); if ( cache_peer.getType() == CachePeer.PT_CACHE_LOGIC ){ if ( state == DownloadManager.STATE_SEEDING ){ if ( now - cache_peer.getCreateTime( now ) >= MIN_SEED_CONNECTION_TIME && secs_since_last_up >= IDLE_SEED_DISCONNECT_SECS ){ peers_to_kick.add( peer ); addToDisconnectedCachePeers( cache_peer ); }else{ if ( cache_peers == null ){ cache_peers = new LinkedList(); } cache_peers.add( peer ); } }else{ // cache logic rely on timely have messages to control both // piece allocation and client-speed peer.setHaveAggregationEnabled( false ); if ( target_speed <= 0 ){ setPeerSpeed( peer, -1, now ); peers_to_kick.add( peer ); addToDisconnectedCachePeers( cache_peer ); }else{ long current_speed = (long)download_speed_average.getAverage(); // if we are already exceeding required speed, block // the cache peer download if ( current_speed + TARGET_SPEED_EXCESS_MARGIN > target_speed ){ setPeerSpeed( peer, -1, now ); } if ( cache_peers == null ){ cache_peers = new LinkedList(); } cache_peers.add( peer ); } } } }catch( Throwable e ){ Debug.printStackTrace(e); } it.remove(); } }else{ it.remove(); } } if ( new_peers.size() == 0 ){ new_peers = null; } } } for (int i=0;i SPEED_CONTROL_INITIAL_DELAY ){ long current_average = (long)download_speed_average.getAverage(); if ( current_average < target_speed ){ long current_speed = getCurrentSpeed(); // increase cache peer contribution // due to latencies we need to give speed increases a time to take // effect to see if the limits can be reached long difference = target_speed - current_speed; if ( last_speed_increase > now || now - last_speed_increase > SPEED_INCREASE_GRACE_PERIOD ){ synchronized( this ){ if ( cache_peers != null ){ Iterator it = cache_peers.iterator(); while( it.hasNext() && difference > 0 ){ PEPeer peer = (PEPeer)it.next(); PEPeerStats peer_stats = peer.getStats(); long peer_limit = peer_stats.getDownloadRateLimitBytesPerSecond(); // try simple approach - find first cache peer that is limited // to less than the target if ( peer_limit == 0 ){ }else{ if ( peer_limit < target_speed ){ setPeerSpeed( peer, (int)target_speed, now ); last_speed_increase = now; difference = 0; } } } } } if ( difference > 0 && last_peer_inject > now || now - last_peer_inject > PEER_INJECT_GRACE_PERIOD ){ Set connected_peers = new HashSet(); List peers_to_try = new ArrayList(); if ( cache_peers != null ){ Iterator it = cache_peers.iterator(); while( it.hasNext() && difference > 0 ){ PEPeer peer = (PEPeer)it.next(); connected_peers.add( peer.getIp() + ":" + peer.getPort()); } } // if we explicitly disconnected peers in the past then reuse them first if ( disconnected_cache_peers != null ){ while( disconnected_cache_peers.size() > 0 ){ CachePeer cp = (CachePeer)disconnected_cache_peers.remove(0); if ( !connected_peers.contains( cp.getAddress().getHostAddress() + ":" + cp.getPort())){ // check that this peer isn't already available as a lookup result if ( lookup_peers != null ){ for (int i=0;i CACHE_REQUERY_MIN_PERIOD ){ last_lookup_time = now; lookup_peers = CacheDiscovery.lookup( download_manager.getTorrent()); } for (int i=0;i CACHE_RECONNECT_MIN_PERIOD ){ if ( !connected_peers.contains( cp.getAddress().getHostAddress() + ":" + cp.getPort())){ peers_to_try.add( cp ); } } } } if ( peers_to_try.size() > 0 ){ CachePeer peer = (CachePeer)peers_to_try.get((int)( Math.random() * peers_to_try.size())); // System.out.println( "Injecting cache peer " + peer.getAddress() + ":" + peer.getPort()); peer.setInjectTime( now ); pm.addPeer( peer.getAddress().getHostAddress(), peer.getPort(), 0, false, null ); last_peer_inject = now; } } } }else if ( current_average > target_speed + TARGET_SPEED_EXCESS_MARGIN){ long current_speed = getCurrentSpeed(); // decrease cache peer contribution long difference = current_speed - ( target_speed + TARGET_SPEED_EXCESS_MARGIN ); synchronized( this ){ if ( cache_peers != null ){ Iterator it = cache_peers.iterator(); while( it.hasNext() && difference > 0 ){ PEPeer peer = (PEPeer)it.next(); PEPeerStats peer_stats = peer.getStats(); long peer_rate = peer_stats.getDataReceiveRate(); long peer_limit = peer_stats.getDownloadRateLimitBytesPerSecond(); if ( peer_limit == -1 ){ // blocked, take into account adjustment in progress difference -= peer_rate; }else if ( peer_limit != 0 && peer_rate > peer_limit ){ // adjusting difference -= peer_rate - peer_limit; }else{ if ( peer_rate > difference ){ setPeerSpeed( peer, (int)( peer_rate - difference ), now ); difference = 0; }else{ setPeerSpeed( peer, -1, now ); difference -= peer_rate; } } } } } } } } if ( tick_count % DISCONNECT_CHECK_TICKS == 0 ){ peers_to_kick.clear(); synchronized( this ){ if ( cache_peers != null ){ Iterator it = cache_peers.iterator(); while( it.hasNext()){ PEPeer peer = (PEPeer)it.next(); CachePeer cache_peer = (CachePeer)peer.getData( PEER_CACHE_KEY ); if ( state == DownloadManager.STATE_SEEDING ){ if ( now - cache_peer.getCreateTime( now ) >= MIN_SEED_CONNECTION_TIME && secs_since_last_up >= IDLE_SEED_DISCONNECT_SECS ){ peers_to_kick.add( peer ); addToDisconnectedCachePeers( cache_peer ); } }else{ PEPeerStats peer_stats = peer.getStats(); if ( peer_stats.getDownloadRateLimitBytesPerSecond() == -1 ){ long time = cache_peer.getSpeedChangeTime( now ); if ( now - time > IDLE_PEER_DISCONNECT_PERIOD ){ peers_to_kick.add( peer ); addToDisconnectedCachePeers( cache_peer ); } } } } } } for (int i=0;i first_piece_offset ){ available = piece_offset - first_piece_offset; } }else{ available += block_size; } }else{ break; } } } }else{ available = first_piece.getLength() - first_piece_offset; for (int i=first_piece_index+1;i<=last_piece_index;i++){ DiskManagerPiece piece = pieces[i]; if ( piece.isDone()){ available += piece.getLength(); }else{ boolean[] blocks = piece.getWritten(); if ( blocks == null ){ if ( piece.isDone()){ available += piece.getLength(); }else{ break; } }else{ for (int j=0;j max_available ){ available = max_available; } return( available ); } public void setViewerPosition( DiskManagerFileInfo file_info, long bytes) { if (file_info != null) { int index = file_info.getIndex(); if ( index < enhanced_files.length ){ bytes += enhanced_files[index].getByteOffestInTorrent(); } } progressive_stats.setViewerBytePosition( bytes ); } public DownloadManager getDownloadManager() { return download_manager; } protected void destroy() { synchronized( this ){ setRTA( false ); destroyed = true; } } protected void log( String str ) { log( str, true ); } protected void log( String str, boolean to_file ) { log( download_manager, str, to_file ); } protected void log( DownloadManager dm, String str, boolean to_file ) { str = dm.getDisplayName() + ": " + str; if ( to_file ){ AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("v3.Stream"); diag_logger.log(str); } if ( ConstantsVuze.DIAG_TO_STDOUT ) { System.out.println(Thread.currentThread().getName() + "|" + System.currentTimeMillis() + "] " + str); } } protected class bufferETAProvider implements PieceRTAProvider { private long[] piece_rtas; private long last_buffer_size; private long last_buffer_size_time; private boolean active; protected void activate( PiecePicker picker ) { log( "Activating buffer provider" ); synchronized( EnhancedDownloadManager.this ){ active = true; piece_rtas = new long[ picker.getNumberOfPieces()]; long now = SystemTime.getCurrentTime(); for (int i=0;i 0 ){ synchronized( EnhancedDownloadManager.this ){ if ( piece_rtas == null ){ activate( picker ); } } } } public long[] updateRTAs( PiecePicker picker ) { // force linear downloading until we have enough to allow the user to // potentially start playing. If they don't do so immediately then until that // time we'll be doing normal BT download DiskManager dm = download_manager.getDiskManager(); if ( dm != null ){ if ( getProgressivePlayETA() <= 0 ){ deactivate( picker ); } } long[] rtas = piece_rtas; if ( rtas != null ){ long buffer_size = progressive_stats.getInitialBytesDownloaded(); long now = SystemTime.getCurrentTime(); if ( last_buffer_size != buffer_size ){ last_buffer_size = buffer_size; last_buffer_size_time = now; }else{ if ( now < last_buffer_size_time ){ last_buffer_size_time = now; }else{ long stalled_for = now - last_buffer_size_time; long dl_speed = progressive_stats.getDownloadBytesPerSecond(); if ( dl_speed > 0 ){ long block_time = (DiskManager.BLOCK_SIZE * 1000) / dl_speed; if ( stalled_for > Math.max( 5000, 5*block_time )){ long target_rta = now + block_time; int blocked_piece_index = (int)( buffer_size / dm.getPieceLength()); DiskManagerPiece[] pieces = dm.getPieces(); if ( blocked_piece_index < pieces.length ){ if ( pieces[blocked_piece_index].isDone()){ blocked_piece_index++; if ( blocked_piece_index < pieces.length ){ if ( pieces[blocked_piece_index].isDone()){ blocked_piece_index = -1; } }else{ blocked_piece_index = -1; } } } if ( blocked_piece_index >= 0 ){ long existing_rta = rtas[blocked_piece_index]; if ( target_rta < existing_rta ){ rtas[blocked_piece_index] = target_rta; log( "Buffer provider: reprioritising lagging piece " + blocked_piece_index + " with rta " + block_time ); } } } } } } } return( rtas ); } public long getCurrentPosition() { return( 0 ); } public long getStartTime() { return( 0 ); } public long getStartPosition() { return( 0 ); } public long getBlockingPosition() { return( 0 ); } public void setBufferMillis( long seconds ) { } public String getUserAgent() { return( null ); } } protected class boostETAProvider implements PieceRTAProvider { private long[] piece_rtas; private long last_recalc; private int aggression; private boolean active; private interventionHandler intervention_handler = new interventionHandler(); private long last_intervention; protected void activate( PiecePicker picker ) { if ( supportsProgressiveMode()){ log( "Activating boost provider" ); synchronized( EnhancedDownloadManager.this ){ intervention_handler.activate(); active = true; picker.addRTAProvider( this ); } } } protected void deactivate( PiecePicker picker ) { if ( active ){ log( "Deactivating boost provider" ); } synchronized( EnhancedDownloadManager.this ){ picker.removeRTAProvider( this ); piece_rtas = null; active = false; intervention_handler.deactivate(); } } public long[] updateRTAs( PiecePicker picker ) { long now = SystemTime.getCurrentTime(); if ( now < last_recalc || now - last_recalc > 1000 ){ last_recalc = now; DiskManager disk_manager = download_manager.getDiskManager(); // if it'll take less time to download than watch then the channel-based rta logic // will do the job. progressiveStats stats = getProgressiveStats(); long max_bps = stats.getStreamBytesPerSecondMax(); if ( disk_manager == null || !stats.isProviderActive() || stats.getETA(false) < -MINIMUM_INITIAL_BUFFER_SECS || max_bps == 0 ){ if ( piece_rtas != null ){ log( "Suspending boost provider" ); } piece_rtas = null; }else{ if ( piece_rtas == null ){ log( "Resuming boost provider" ); } long[] local_rtas = piece_rtas = new long[disk_manager.getNbPieces()]; // need to force piece order - set RTAs for all outstanding pieces long piece_size = disk_manager.getPieceLength(); int start_piece = (int)( stats.getBytePosition() / piece_size ); long bytes_offset = 0; // we need to be more aggresive if we have an explicit min buffer size // as the emp will auto-pause when the contiguous available bytes falls // below this min int last_aggressive_piece = -1; long time_to_stall = 0; if ( explicit_minimum_buffer_bytes > 0 ){ long total_avail = getContiguousAvailableBytes( getPrimaryFile()); long viewer_pos = stats.getViewerBytePosition(); long avail = total_avail - viewer_pos; time_to_stall = ( avail - explicit_minimum_buffer_bytes )*1000/max_bps; long buffer_zone = 3*explicit_minimum_buffer_bytes; if ( avail <= buffer_zone ){ if ( avail < 0 ){ avail = 0; } if ( avail <= explicit_minimum_buffer_bytes ){ aggression = 10; }else{ aggression = (int)( ( buffer_zone - avail )*10/( buffer_zone - explicit_minimum_buffer_bytes )); } last_aggressive_piece = start_piece + (int)(( buffer_zone + piece_size -1 ) / piece_size); }else{ aggression = 0; } }else{ aggression = 0; } DiskManagerPiece[] dm_pieces = disk_manager.getPieces(); for ( int i=start_piece;i= 7 && !dm_pieces[i].isDone() && time_to_stall <= 10*1000 ){ if ( now < last_intervention || now - last_intervention >= 500 ){ last_intervention = now; /* long total_avail = getContiguousAvailableBytes( getPrimaryFile()); long viewer_pos = stats.getViewerBytePosition(); long avail = total_avail - viewer_pos; long buffer_zone = 3*explicit_minimum_buffer_bytes; System.out.println( "Aggression = " + aggression + ", time factor=" + time_factor + ", stall=" + time_to_stall + ", avail=" + avail + ", buffer=" + buffer_zone ); */ intervention_handler.addPiece( i, SystemTime.getCurrentTime() + time_to_stall ); } } }else{ time_factor = 1000; } local_rtas[i] = now + ( time_factor* ( bytes_offset / max_bps )); bytes_offset += piece_size; } } } return( piece_rtas ); } public long getCurrentPosition() { return( 0 ); } public long getBlockingPosition() { return( 0 ); } public long getStartTime() { return( 0 ); } public long getStartPosition() { return( 0 ); } public void setBufferMillis( long seconds ) { } public String getUserAgent() { return( null ); } protected class interventionHandler { private AEThread2 thread; private AESemaphore request_sem; private List request_list; private List http_peers; private boolean borked; protected void activate() { synchronized( this ){ active = true; } } protected void deactivate() { synchronized( this ){ active = false; if ( thread != null ){ thread = null; request_list = null; request_sem.release(); } } } protected void addPiece( int piece_number, long stall_time ) { synchronized( this ){ if ( !active || borked ){ return; } if ( thread == null ){ PluginInterface pi = enhancer.getCore().getPluginManager().getPluginInterfaceByClass( ExternalSeedPlugin.class ); if ( pi == null ){ borked = true; return; } ExternalSeedPlugin ext_seed = (ExternalSeedPlugin)pi.getPlugin(); ExternalSeedManualPeer[] peers = ext_seed.getManualWebSeeds( PluginCoreUtils.wrap( download_manager )); http_peers = null; for ( int i=0;i 0 ){ break; } } block_pos++; } if ( block_num == 0 ){ break; } int block_start_offset = 0; int blocks_length = 0; for (int i=0;i 0 ){ actual_bytes_to_download += bytes_this_piece; int diff = i - first_incomplete_piece; if ( diff == 0 ){ weighted_bytes_to_download += bytes_this_piece; }else{ int weighted_bytes_done = piece.getLength() - bytes_this_piece; weighted_bytes_done = ( weighted_bytes_done * ( pieces.length - i )) / (pieces.length - first_incomplete_piece); weighted_bytes_to_download += piece.getLength() - weighted_bytes_done; } } } } log( getString(), tick_count % LOG_PROG_STATS_TICKS == 0 ); } protected abstract void updateViewerPosition(); protected abstract long getInitialBufferBytes( long dl_rate, boolean ignore_min_buffer_size ); protected long getETA( boolean ignore_min_buffer_size ) { DiskManager dm = download_manager.getDiskManager(); if ( dm == null ){ return( Long.MAX_VALUE ); } if ( dm.getRemainingExcludingDND() == 0 ){ return( 0 ); } long download_rate = getDownloadBytesPerSecond(); if ( download_rate <= 0 ){ return( Long.MAX_VALUE ); } final long min_dl = getInitialBufferBytes( download_rate, ignore_min_buffer_size ); long initial_downloaded = getInitialBytesDownloaded( min_dl ); long rem_dl = min_dl - initial_downloaded; // ok as initial dl is forced in order byte buffer-rta long rem_secs = rem_dl / download_rate; long secs_to_download = getSecondsToDownload(); // increase time to download a bit so we don't start streaming too soon // we'll always lose time due to speed variations, discards, hashfails... secs_to_download = secs_to_download + (secs_to_download/10); long secs_to_watch = getSecondsToWatch(); long eta = secs_to_download - secs_to_watch; if ( rem_secs > eta ){ eta = rem_secs; } if ( !ignore_min_buffer_size ){ if ( eta == 0 && last_eta != 0 ){ last_eta = eta; log( "ETA=0: rate=" + DisplayFormatters.formatByteCountToKiBEtcPerSec( download_rate ) + ",init_buff=" + min_dl +",to_dl=" + secs_to_download + ",to_watch=" + secs_to_watch ); } } return( eta ); } public long getInitialBytesDownloaded() { return( getInitialBytesDownloaded( Long.MAX_VALUE )); } protected long getDownloadBytesPerSecond() { long original = (long)capped_download_rate_average.getAverage(); long current = original; int dl_limit = download_manager.getStats().getDownloadRateLimitBytesPerSecond(); if ( dl_limit > 0 ){ current = Math.min( current, dl_limit ); } int global_limit = TransferSpeedValidator.getGlobalDownloadRateLimitBytesPerSecond(); if ( global_limit > 0 ){ current = Math.min( current, global_limit ); } return( current ); } public long getInitialBytesDownloaded( long stop_counting_after ) { DiskManager dm = download_manager.getDiskManager(); if ( dm == null ){ return( 0 ); } long initial_downloaded = 0; DiskManagerPiece[] pieces = dm.getPieces(); for (int i=0;i= stop_counting_after ){ break; } } return( initial_downloaded ); } protected long getSecondsToDownload() { long download_rate = getDownloadBytesPerSecond(); if ( download_rate == 0 ){ return( Long.MAX_VALUE ); } return( weighted_bytes_to_download / download_rate ); } protected long getSecondsToWatch() { return((total_file_length - getViewerBytePosition()) / getStreamBytesPerSecondMin()); } protected long getBytePosition() { return( getViewerBytePosition()); } protected long getViewerBufferSeconds() { return((provider_byte_position - getViewerBytePosition() ) / getStreamBytesPerSecondMax() ); } protected String getString() { long dl_rate = getDownloadBytesPerSecond(); long init_bytes = getInitialBufferBytes(dl_rate,false); return( "play_eta=" + getETA(false) + "/d=" + getSecondsToDownload() + "/w=" + getSecondsToWatch()+ ", dl_rate=" + formatSpeed(dl_rate)+ ", download_rem=" + formatBytes(weighted_bytes_to_download) + "/" + formatBytes(actual_bytes_to_download) + ", discard_rate=" + formatSpeed((long)discard_rate_average.getAverage()) + ", init_done=" + getInitialBytesDownloaded(init_bytes) + ", init_buff=" + init_bytes + ", viewer: byte=" + formatBytes( getViewerBytePosition()) + " secs=" + ( getViewerBytePosition()/getStreamBytesPerSecondMin() ) + ", prov: byte=" + formatBytes( provider_byte_position ) + " secs=" + ( provider_byte_position/getStreamBytesPerSecondMin()) + " speed=" + formatSpeed((long)provider_speed_average.getAverage()) + " block= " + formatBytes( provider_blocking_byte_position ) + " buffer=" + formatBytes( provider_byte_position - getViewerBytePosition() ) + "/" + getViewerBufferSeconds()); } } protected class progressiveStatsExternal extends progressiveStatsCommon { private long content_stream_bps_min; private long content_stream_bps_max; private long viewer_byte_position; protected progressiveStatsExternal( DownloadManager download_manager, EnhancedDownloadManagerFile primary_file ) { super( download_manager, primary_file ); } protected void calculateSpeeds( DownloadManager download_manager, EnhancedDownloadManagerFile primary_file ) { TOTorrent torrent = download_manager.getTorrent(); if ( torrent == null ){ return; } content_stream_bps_min = PlatformTorrentUtils.getContentStreamSpeedBps( torrent ); if ( content_stream_bps_min == 0 ){ // hack in some test values for torrents that don't have a bps in them yet long size = torrent.getSize(); if ( size < 200*1024*1024 ){ content_stream_bps_min = 30*1024; }else if ( size < 1000*1024*1024L ){ content_stream_bps_min = 200*1024; }else{ content_stream_bps_min = 400*1024; } } // bump it up by a bit to be conservative to deal with fluctuations, discards etc. content_stream_bps_max = content_stream_bps_min + ( content_stream_bps_min / 5 ); } protected long getStreamBytesPerSecondMax() { return( content_stream_bps_max ); } protected long getStreamBytesPerSecondMin() { return( content_stream_bps_min ); } public long getInitialBufferBytes( long download_rate, boolean ignore_min_buffer_size ) { long min_dl = minimum_initial_buffer_secs_for_eta * getStreamBytesPerSecondMax(); // factor in any explicit minimum buffer bytes min_dl = Math.max( min_dl, ignore_min_buffer_size?0:explicit_minimum_buffer_bytes ); // see if we have any stream-specific advice long advice = primary_file.getInitialBufferBytes( download_rate ); min_dl = Math.max( advice, min_dl ); return( min_dl ); } protected void updateViewerPosition() { viewer_byte_position = getInitialProviderPosition() + (getStreamBytesPerSecondMax() * getProviderLifeSecs()); if ( viewer_byte_position > total_file_length ){ viewer_byte_position = total_file_length; } if ( viewer_byte_position > getProviderBytePosition()){ viewer_byte_position = getProviderBytePosition(); } } protected void setViewerBytePosition( long bytes) { // nothing for external viewer case as this doesn't get called } protected long getViewerBytePosition() { return( viewer_byte_position ); } } protected class progressiveStatsInternal extends progressiveStatsCommon { private long content_stream_bps_min; private long content_stream_bps_max; private long viewer_byte_position; private long viewer_byte_position_set_time; private long last_warning; protected progressiveStatsInternal( DownloadManager dm, EnhancedDownloadManagerFile primary_file ) { super( dm, primary_file ); } protected void calculateSpeeds( DownloadManager download_manager, EnhancedDownloadManagerFile primary_file ) { TOTorrent torrent = download_manager.getTorrent(); if ( torrent == null ){ return; } content_stream_bps_min = PlatformTorrentUtils.getContentStreamSpeedBps( torrent ); if ( content_stream_bps_min == 0 ){ // hack in some test values for torrents that don't have a bps in them yet long size = torrent.getSize(); if ( size < 200*1024*1024 ){ content_stream_bps_min = 30*1024; }else if ( size < 1000*1024*1024L ){ content_stream_bps_min = 200*1024; }else{ content_stream_bps_min = 400*1024; } } // bump it up by a bit to be conservative to deal with fluctuations, discards etc. content_stream_bps_min += internal_content_stream_bps_increase_absolute; content_stream_bps_max = content_stream_bps_min + ( content_stream_bps_min / internal_content_stream_bps_increase_ratio ); } protected long getStreamBytesPerSecondMax() { return( content_stream_bps_max ); } protected long getStreamBytesPerSecondMin() { return( content_stream_bps_min ); } public long getInitialBufferBytes( long download_rate, boolean ignore_min_buffer_size ) { long min_dl = ignore_min_buffer_size?0:explicit_minimum_buffer_bytes; // see if we have any stream-specific advice long advice = primary_file.getInitialBufferBytes( download_rate ); if ( advice == 0 ){ // no advice, fall back to computed min advice = minimum_initial_buffer_secs_for_eta * getStreamBytesPerSecondMax(); }else{ // currently the player will auto-pause if the buffer falls below the // explicit minimum so we need to add the explicit to the advice to // get a value that will prevent a stall if ( !ignore_min_buffer_size ){ advice += explicit_minimum_buffer_bytes; } } min_dl = Math.max( advice, min_dl ); return( min_dl ); } protected void updateViewerPosition() { } protected void setViewerBytePosition( long bytes) { viewer_byte_position_set_time = SystemTime.getCurrentTime(); viewer_byte_position = bytes; } protected long getViewerBytePosition() { long now = SystemTime.getCurrentTime(); if ( now < viewer_byte_position_set_time ){ viewer_byte_position_set_time = now; }else if ( now - viewer_byte_position_set_time > 10000 ){ if ( viewer_byte_position != 0 ){ if ( now < last_warning || now - last_warning >= 1000 ){ last_warning = now; log( "No recent viewer position update (current=" + viewer_byte_position + ")" ); } } } return( viewer_byte_position ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/download/DiskManagerFileInfoStream.java0000644000175000017500000003224511234166300027125 0ustar adrianadrian/* * Created on Feb 11, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.download; import java.io.*; import java.util.*; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SHA1Simple; import org.gudy.azureus2.plugins.disk.DiskManagerChannel; import org.gudy.azureus2.plugins.disk.DiskManagerEvent; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.disk.DiskManagerListener; import org.gudy.azureus2.plugins.disk.DiskManagerRequest; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadException; import org.gudy.azureus2.plugins.utils.PooledByteBuffer; import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl; import com.aelitis.azureus.core.util.CopyOnWriteList; public class DiskManagerFileInfoStream implements DiskManagerFileInfo { private StreamFactory stream_factory; private File save_to; private byte[] hash; private context current_context; private Object lock = this; public DiskManagerFileInfoStream( StreamFactory _stream_factory, File _save_to ) { stream_factory = _stream_factory; save_to = _save_to; try{ hash = new SHA1Simple().calculateHash( _save_to.getAbsolutePath().getBytes( "UTF-8" )); }catch( Throwable e ){ Debug.out(e); } } public boolean isComplete() { synchronized( lock ){ return( save_to.exists()); } } public void reset() { synchronized( lock ){ if ( current_context != null ){ current_context.destroy( new Exception( "Reset" )); } save_to.delete(); } } public void setPriority( boolean b ) { } public void setSkipped( boolean b ) { throw( new RuntimeException( "Not supported" )); } public void setDeleted(boolean b) { } public void setLink( File link_destination ) { throw( new RuntimeException( "Not supported" )); } public File getLink() { return( null ); } public int getAccessMode() { return( READ ); } public long getDownloaded() { return( getLength()); } public long getLength() { return( -1 ); } public File getFile() { return( save_to ); } public int getIndex() { return( 0 ); } public int getFirstPieceNumber() { return( 0 ); } public long getPieceSize() { return( 32*1024 ); } public int getNumPieces() { return( -1 ); } public boolean isPriority() { return( false ); } public boolean isSkipped() { return( false ); } public boolean isDeleted() { return( false ); } public byte[] getDownloadHash() throws DownloadException { return( hash ); } public Download getDownload() throws DownloadException { throw( new DownloadException( "Not supported" )); } public DiskManagerChannel createChannel() throws DownloadException { try{ synchronized( lock ){ if ( current_context == null ){ current_context = new context(); } return( current_context.createChannel()); } }catch( Throwable e ){ throw( new DownloadException( "Channel creation failed", e )); } } protected void destroyed( context c ) { synchronized( lock ){ if ( current_context == c ){ current_context = null; } } stream_factory.destroyed( c ); } protected class context { private RandomAccessFile raf; private StreamFactory.StreamDetails stream_details; private boolean stream_got_eof; private List channels = new ArrayList(); private List waiters = new ArrayList(); private boolean context_destroyed; protected context() throws Exception { if ( save_to.exists()){ raf = new RandomAccessFile( save_to, "r" ); stream_got_eof = true; }else{ final File temp_file = new File( save_to.getAbsolutePath() + "._tmp_" ); raf = new RandomAccessFile( temp_file, "rw" ); stream_details = stream_factory.getStream( this ); final InputStream stream = stream_details.getStream(); new AEThread2( "DMS:reader", true ) { public void run() { final int BUFF_SIZE = 128*1024; byte[] buffer = new byte[BUFF_SIZE]; try{ while( true ){ int len = stream.read( buffer ); if ( len <= 0 ){ if ( stream_details.hasFailed()){ throw( new IOException( "Stream failed" )); } stream_got_eof = true; break; } synchronized( lock ){ raf.seek( raf.length()); raf.write( buffer, 0, len ); for ( AESemaphore waiter: waiters ){ waiter.release(); } } } }catch( Throwable e ){ context.this.destroy( e ); }finally{ try{ stream.close(); }catch( Throwable e ){ } Throwable failed = null; synchronized( lock ){ stream_details = null; if ( stream_got_eof ){ try{ raf.close(); save_to.delete(); temp_file.renameTo( save_to ); raf = new RandomAccessFile( save_to, "r" ); }catch( Throwable e ){ failed = e; } } } if ( failed != null ){ context.this.destroy( failed ); } } } }.start(); } } protected int read( byte[] buffer, long offset, int length ) throws IOException { AESemaphore sem; synchronized( lock ){ if ( raf.length() > offset ){ raf.seek( offset ); return( raf.read( buffer, 0, length )); } if ( stream_details == null ){ if ( stream_got_eof ){ return( -1 ); } throw( new IOException( "Premature end of stream (read)" )); } sem = new AESemaphore( "DMS:block" ); waiters.add( sem ); } try{ sem.reserve( 1000 ); }finally{ synchronized( lock ){ waiters.remove( sem ); } } return( 0 ); } protected channel createChannel() { synchronized( lock ){ channel c = new channel(); channels.add( c ); return( c ); } } protected void removeChannel( channel c ) { synchronized( lock ){ channels.remove( c ); if ( channels.size() == 0 && save_to.exists()){ destroy( null ); } } } protected void destroy( Throwable error ) { if ( error != null ){ Debug.out( error ); } synchronized( lock ){ if ( context_destroyed ){ return; } context_destroyed = true; if ( channels != null ){ List channels_copy = new ArrayList( channels ); for ( channel c: channels_copy ){ c.destroy(); } } if ( raf != null ){ try{ raf.close(); }catch( Throwable e ){ } raf = null; } if ( stream_details != null ){ try{ stream_details.getStream().close(); }catch( Throwable e ){ } stream_details = null; } if ( error != null ){ save_to.delete(); } } DiskManagerFileInfoStream.this.destroyed( this ); } protected class channel implements DiskManagerChannel { private volatile boolean channel_destroyed; public DiskManagerRequest createRequest() { return( new request()); } public DiskManagerFileInfo getFile() { return( DiskManagerFileInfoStream.this ); } public void destroy() { channel_destroyed = true; removeChannel( this ); } protected class request implements DiskManagerRequest { private long offset; private long length; private long position; private int max_read_chunk = 128*1024;; private volatile boolean request_cancelled; private CopyOnWriteList listeners = new CopyOnWriteList(); public void setType( int type ) { if ( type != DiskManagerRequest.REQUEST_READ ){ throw( new RuntimeException( "Not supported" )); } } public void setOffset( long _offset ) { offset = _offset; } public void setLength( long _length ) { // length can be -1 here meaning 'to the end' length = _length==-1?Long.MAX_VALUE:_length; } public void setMaximumReadChunkSize( int size ) { if ( size > 16*1024 ){ max_read_chunk = size; } } public long getAvailableBytes() { return( getRemaining()); } public long getRemaining() { return( length==Long.MAX_VALUE?length:(offset + length - position )); } public void run() { try{ byte[] buffer = new byte[max_read_chunk]; long rem = length; long pos = offset; while( rem > 0 ){ if ( request_cancelled ){ throw( new Exception( "Cancelled" )); }else if ( channel_destroyed ){ throw( new Exception( "Destroyed" )); } int chunk = (int)Math.min( rem, max_read_chunk ); int len = read( buffer, pos, chunk ); if ( len == -1 ){ if ( length == Long.MAX_VALUE ){ break; }else{ throw( new Exception( "Premature end of stream (complete)" )); } }else if ( len == 0 ){ sendEvent( new event( pos )); }else{ sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len )); rem -= len; pos += len; } } }catch( Throwable e ){ sendEvent( new event( e )); } } public void cancel() { request_cancelled = true; } public void setUserAgent( String agent ) { } protected void sendEvent( event ev ) { for ( DiskManagerListener l: listeners ){ l.eventOccurred( ev ); } } public void addListener( DiskManagerListener listener ) { listeners.add( listener ); } public void removeListener( DiskManagerListener listener ) { listeners.remove( listener ); } protected class event implements DiskManagerEvent { private int event_type; private Throwable error; private PooledByteBuffer buffer; private long event_offset; private int event_length; protected event( Throwable _error ) { event_type = DiskManagerEvent.EVENT_TYPE_FAILED; error = _error; } protected event( long _offset ) { event_type = DiskManagerEvent.EVENT_TYPE_BLOCKED; event_offset = _offset; } protected event( PooledByteBuffer _buffer, long _offset, int _length ) { event_type = DiskManagerEvent.EVENT_TYPE_SUCCESS; buffer = _buffer; event_offset = _offset; event_length = _length; } public int getType() { return( event_type ); } public DiskManagerRequest getRequest() { return( request.this ); } public long getOffset() { return( event_offset ); } public int getLength() { return( event_length ); } public PooledByteBuffer getBuffer() { return( buffer ); } public Throwable getFailure() { return( error ); } } } } } public interface StreamFactory { public StreamDetails getStream( Object requester ) throws IOException; public void destroyed( Object requester ); public interface StreamDetails { public InputStream getStream(); public boolean hasFailed(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/stats/0000755000175000017500000000000011310377630020633 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/stats/AzureusCoreStatsProvider.java0000644000175000017500000000216511137533042026501 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.stats; import java.util.*; public interface AzureusCoreStatsProvider { public void updateStats( Set types, Map values ); } azureus-4.3.0.6/com/aelitis/azureus/core/stats/AzureusCoreStats.java0000644000175000017500000004631511033255236024774 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.stats; import java.util.*; import java.util.regex.Pattern; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.Timer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.util.average.Average; import com.aelitis.azureus.core.util.average.AverageFactory; public class AzureusCoreStats { public static final int AVERAGE_PERIOD = 1000; public static final String ST_ALL = ".*"; // DISK public static final String ST_DISK = "disk.*"; public static final String ST_DISK_READ_QUEUE_LENGTH = "disk.read.queue.length"; public static final String ST_DISK_READ_QUEUE_BYTES = "disk.read.queue.bytes"; public static final String ST_DISK_READ_REQUEST_COUNT = "disk.read.request.count"; public static final String ST_DISK_READ_REQUEST_SINGLE = "disk.read.request.single"; public static final String ST_DISK_READ_REQUEST_MULTIPLE = "disk.read.request.multiple"; public static final String ST_DISK_READ_REQUEST_BLOCKS = "disk.read.request.blocks"; public static final String ST_DISK_READ_BYTES_TOTAL = "disk.read.bytes.total"; public static final String ST_DISK_READ_BYTES_SINGLE = "disk.read.bytes.single"; public static final String ST_DISK_READ_BYTES_MULTIPLE = "disk.read.bytes.multiple"; public static final String ST_DISK_READ_IO_TIME = "disk.read.io.time"; public static final String ST_DISK_READ_IO_COUNT = "disk.read.io.count"; public static final String ST_DISK_WRITE_QUEUE_LENGTH = "disk.write.queue.length"; public static final String ST_DISK_WRITE_QUEUE_BYTES = "disk.write.queue.bytes"; public static final String ST_DISK_WRITE_REQUEST_COUNT = "disk.write.request.count"; public static final String ST_DISK_WRITE_REQUEST_BLOCKS = "disk.write.request.blocks"; public static final String ST_DISK_WRITE_BYTES_TOTAL = "disk.write.bytes.total"; public static final String ST_DISK_WRITE_BYTES_SINGLE = "disk.write.bytes.single"; public static final String ST_DISK_WRITE_BYTES_MULTIPLE = "disk.write.bytes.multiple"; public static final String ST_DISK_WRITE_IO_TIME = "disk.write.io.time"; public static final String ST_DISK_WRITE_IO_COUNT = "disk.write.io.count"; // NETWORK public static final String ST_NET_WRITE_CONTROL_WAIT_COUNT = "net.write.control.wait.count"; public static final String ST_NET_WRITE_CONTROL_NP_COUNT = "net.write.control.np.count"; public static final String ST_NET_WRITE_CONTROL_P_COUNT = "net.write.control.p.count"; public static final String ST_NET_WRITE_CONTROL_ENTITY_COUNT = "net.write.control.entity.count"; public static final String ST_NET_WRITE_CONTROL_CON_COUNT = "net.write.control.con.count"; public static final String ST_NET_WRITE_CONTROL_READY_CON_COUNT = "net.write.control.ready.con.count"; public static final String ST_NET_WRITE_CONTROL_READY_BYTE_COUNT = "net.write.control.ready.byte.count"; public static final String ST_NET_READ_CONTROL_LOOP_COUNT = "net.read.control.loop.count"; public static final String ST_NET_READ_CONTROL_NP_COUNT = "net.read.control.np.count"; public static final String ST_NET_READ_CONTROL_P_COUNT = "net.read.control.p.count"; public static final String ST_NET_READ_CONTROL_WAIT_COUNT = "net.read.control.wait.count"; public static final String ST_NET_READ_CONTROL_ENTITY_COUNT = "net.read.control.entity.count"; public static final String ST_NET_READ_CONTROL_CON_COUNT = "net.read.control.con.count"; public static final String ST_NET_READ_CONTROL_READY_CON_COUNT = "net.read.control.ready.con.count"; // TCP public static final String ST_NET_TCP_OUT_CONNECT_QUEUE_LENGTH = "net.tcp.outbound.connect.queue.length"; public static final String ST_NET_TCP_OUT_PENDING_QUEUE_LENGTH = "net.tcp.outbound.pending.queue.length"; public static final String ST_NET_TCP_OUT_CANCEL_QUEUE_LENGTH = "net.tcp.outbound.cancel.queue.length"; public static final String ST_NET_TCP_OUT_CLOSE_QUEUE_LENGTH = "net.tcp.outbound.close.queue.length"; public static final String ST_NET_TCP_SELECT_WRITE_COUNT = "net.tcp.select.write.count"; public static final String ST_NET_TCP_SELECT_READ_COUNT = "net.tcp.select.read.count"; // HTTP public static final String ST_NET_HTTP_IN_REQUEST_COUNT = "net.http.inbound.request.count"; public static final String ST_NET_HTTP_IN_REQUEST_OK_COUNT = "net.http.inbound.request.ok.count"; public static final String ST_NET_HTTP_IN_REQUEST_INVALID_COUNT = "net.http.inbound.request.invalid.count"; public static final String ST_NET_HTTP_IN_REQUEST_WEBSEED_COUNT = "net.http.inbound.request.webseed.count"; public static final String ST_NET_HTTP_IN_REQUEST_GETRIGHT_COUNT = "net.http.inbound.request.getright.count"; // Peer Control public static final String ST_PEER_CONTROL_SCHEDULE_COUNT = "peer.control.schedule.count"; public static final String ST_PEER_CONTROL_LOOP_COUNT = "peer.control.loop.count"; public static final String ST_PEER_CONTROL_YIELD_COUNT = "peer.control.yield.count"; public static final String ST_PEER_CONTROL_WAIT_COUNT = "peer.control.wait.count"; public static final String ST_PEER_CONTROL_WAIT_TIME = "peer.control.wait.time"; // Peer Manager public static final String ST_PEER_MANAGER_COUNT = "peer.manager.count"; public static final String ST_PEER_MANAGER_PEER_COUNT = "peer.manager.peer.count"; public static final String ST_PEER_MANAGER_PEER_SNUBBED_COUNT = "peer.manager.peer.snubbed.count"; public static final String ST_PEER_MANAGER_PEER_STALLED_DISK_COUNT = "peer.manager.peer.stalled.disk.count"; // Tracker public static final String ST_TRACKER_READ_BYTES = "tracker.read.bytes.total"; public static final String ST_TRACKER_WRITE_BYTES = "tracker.write.bytes.total"; public static final String ST_TRACKER_ANNOUNCE_COUNT = "tracker.announce.count"; public static final String ST_TRACKER_ANNOUNCE_TIME = "tracker.announce.time"; public static final String ST_TRACKER_SCRAPE_COUNT = "tracker.scrape.count"; public static final String ST_TRACKER_SCRAPE_TIME = "tracker.scrape.time"; // xfer (persistent) public static final String ST_XFER_UPLOADED_PROTOCOL_BYTES = "xfer.upload.protocol.bytes.total"; public static final String ST_XFER_UPLOADED_DATA_BYTES = "xfer.upload.data.bytes.total"; public static final String ST_XFER_DOWNLOADED_PROTOCOL_BYTES = "xfer.download.protocol.bytes.total"; public static final String ST_XFER_DOWNLOADED_DATA_BYTES = "xfer.download.data.bytes.total"; public static final String POINT = "Point"; public static final String CUMULATIVE = "Cumulative"; private static final List stats_names = new ArrayList(); private static final Map stats_types = new HashMap(); private static final String[][] _ST_ALL = { { ST_DISK_READ_QUEUE_LENGTH, POINT }, { ST_DISK_READ_QUEUE_BYTES, POINT }, { ST_DISK_READ_REQUEST_COUNT, CUMULATIVE }, { ST_DISK_READ_REQUEST_SINGLE, CUMULATIVE }, { ST_DISK_READ_REQUEST_MULTIPLE, CUMULATIVE }, { ST_DISK_READ_REQUEST_BLOCKS, CUMULATIVE }, { ST_DISK_READ_BYTES_TOTAL, CUMULATIVE }, { ST_DISK_READ_BYTES_SINGLE, CUMULATIVE }, { ST_DISK_READ_BYTES_MULTIPLE, CUMULATIVE }, { ST_DISK_READ_IO_TIME, CUMULATIVE }, { ST_DISK_READ_IO_COUNT, CUMULATIVE }, { ST_DISK_WRITE_QUEUE_LENGTH, POINT }, { ST_DISK_WRITE_QUEUE_BYTES, POINT }, { ST_DISK_WRITE_REQUEST_COUNT, CUMULATIVE }, { ST_DISK_WRITE_REQUEST_BLOCKS, CUMULATIVE }, { ST_DISK_WRITE_BYTES_TOTAL, CUMULATIVE }, { ST_DISK_WRITE_BYTES_SINGLE, CUMULATIVE }, { ST_DISK_WRITE_BYTES_MULTIPLE, CUMULATIVE }, { ST_DISK_WRITE_IO_TIME, CUMULATIVE }, { ST_DISK_WRITE_IO_COUNT, CUMULATIVE }, { ST_NET_WRITE_CONTROL_WAIT_COUNT, CUMULATIVE }, { ST_NET_WRITE_CONTROL_P_COUNT, CUMULATIVE }, { ST_NET_WRITE_CONTROL_NP_COUNT, CUMULATIVE }, { ST_NET_WRITE_CONTROL_ENTITY_COUNT, POINT }, { ST_NET_WRITE_CONTROL_CON_COUNT, POINT }, { ST_NET_WRITE_CONTROL_READY_CON_COUNT, POINT }, { ST_NET_WRITE_CONTROL_READY_BYTE_COUNT, POINT }, { ST_NET_READ_CONTROL_LOOP_COUNT, CUMULATIVE }, { ST_NET_READ_CONTROL_P_COUNT, CUMULATIVE }, { ST_NET_READ_CONTROL_NP_COUNT, CUMULATIVE }, { ST_NET_READ_CONTROL_WAIT_COUNT, CUMULATIVE }, { ST_NET_READ_CONTROL_ENTITY_COUNT, POINT }, { ST_NET_READ_CONTROL_CON_COUNT, POINT }, { ST_NET_READ_CONTROL_READY_CON_COUNT, POINT }, { ST_NET_TCP_OUT_CONNECT_QUEUE_LENGTH, POINT }, { ST_NET_TCP_OUT_PENDING_QUEUE_LENGTH, POINT }, { ST_NET_TCP_OUT_CANCEL_QUEUE_LENGTH, POINT }, { ST_NET_TCP_OUT_CLOSE_QUEUE_LENGTH, POINT }, { ST_NET_TCP_SELECT_WRITE_COUNT, CUMULATIVE }, { ST_NET_TCP_SELECT_READ_COUNT, CUMULATIVE }, { ST_NET_HTTP_IN_REQUEST_COUNT, CUMULATIVE }, { ST_NET_HTTP_IN_REQUEST_OK_COUNT, CUMULATIVE }, { ST_NET_HTTP_IN_REQUEST_INVALID_COUNT, CUMULATIVE }, { ST_NET_HTTP_IN_REQUEST_WEBSEED_COUNT, CUMULATIVE }, { ST_NET_HTTP_IN_REQUEST_GETRIGHT_COUNT, CUMULATIVE }, { ST_PEER_CONTROL_SCHEDULE_COUNT, CUMULATIVE }, { ST_PEER_CONTROL_LOOP_COUNT, CUMULATIVE }, { ST_PEER_CONTROL_YIELD_COUNT, CUMULATIVE }, { ST_PEER_CONTROL_WAIT_COUNT, CUMULATIVE }, { ST_PEER_CONTROL_WAIT_TIME, CUMULATIVE }, { ST_PEER_MANAGER_COUNT, POINT }, { ST_PEER_MANAGER_PEER_COUNT, POINT }, { ST_PEER_MANAGER_PEER_SNUBBED_COUNT, POINT }, { ST_PEER_MANAGER_PEER_STALLED_DISK_COUNT, POINT }, { ST_TRACKER_READ_BYTES, CUMULATIVE }, { ST_TRACKER_WRITE_BYTES, CUMULATIVE }, { ST_TRACKER_ANNOUNCE_COUNT, CUMULATIVE }, { ST_TRACKER_ANNOUNCE_TIME, CUMULATIVE }, { ST_TRACKER_SCRAPE_COUNT, CUMULATIVE }, { ST_TRACKER_SCRAPE_TIME, CUMULATIVE }, { ST_XFER_UPLOADED_PROTOCOL_BYTES, CUMULATIVE }, { ST_XFER_UPLOADED_DATA_BYTES, CUMULATIVE }, { ST_XFER_DOWNLOADED_PROTOCOL_BYTES, CUMULATIVE }, { ST_XFER_DOWNLOADED_DATA_BYTES, CUMULATIVE }, }; static{ addStatsDefinitions( _ST_ALL ); AEDiagnostics.addEvidenceGenerator( new AEDiagnosticsEvidenceGenerator() { public void generate( IndentWriter writer ) { writer.println( "Stats" ); boolean turn_on_averages = !getEnableAverages(); try{ writer.indent(); if ( turn_on_averages ){ setEnableAverages( true ); try{ Thread.sleep( AVERAGE_PERIOD * 5 ); }catch( Throwable e ){ } } Set types = new HashSet(); types.add( ST_ALL ); Map reply = getStats( types ); Iterator it = reply.entrySet().iterator(); List lines = new ArrayList(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); lines.add( entry.getKey() + " -> " + entry.getValue()); } Collections.sort( lines ); for ( int i=0;i 0 ){ map.put( "explicit", new Long(1)); byte[] explicit_data = BEncoder.encode( map ); Iterator it = explicit_peers.iterator(); while( it.hasNext()){ mc_group.sendToMember((InetSocketAddress)it.next(), explicit_data ); } } }else{ if ( explicit_peers.contains( member )){ map.put( "explicit", new Long(1)); } byte[] explicit_data = BEncoder.encode( map ); mc_group.sendToMember( member, explicit_data ); } }catch( Throwable e ){ } } public void received( NetworkInterface network_interface, InetAddress local_address, InetSocketAddress originator, byte[] data, int length ) { try{ Map map = BDecoder.decode( data, 0, length ); long version = ((Long)map.get( "ver" )).longValue(); long type = ((Long)map.get( "type" )).longValue(); InetAddress originator_address = originator.getAddress(); if ( map.get( "explicit" ) != null ){ addInstanceSupport( originator_address, false ); } AZOtherInstanceImpl instance = AZOtherInstanceImpl.decode( originator_address, (Map)map.get( "orig" )); if ( instance != null ){ if ( type == MT_ALIVE ){ checkAdd( instance ); }else if ( type == MT_BYE ){ checkRemove( instance ); }else{ checkAdd( instance ); Map body = (Map)map.get( "body" ); if ( type == MT_REQUEST ){ String originator_id = instance.getID(); if ( !originator_id.equals( my_instance.getID())){ Map reply = requestReceived( instance, body ); if ( reply != null ){ reply.put( "oid", originator_id.getBytes()); reply.put( "rid", body.get( "rid" )); sendMessage( MT_REPLY, reply, originator ); } } }else if ( type == MT_REPLY ){ String originator_id = new String((byte[])body.get( "oid" )); if ( originator_id.equals( my_instance.getID())){ long req_id = ((Long)body.get("rid")).longValue(); try{ this_mon.enter(); for (int i=0;i " + value + " - " + (add?"add":"remove")); InetSocketAddress old_value = (InetSocketAddress)map.get(key); boolean same = old_value != null && old_value.equals( value ); Map new_map = map; if ( add ){ if ( !same ){ new_map = new HashMap( map ); new_map.put( key, value ); } }else{ if ( same ){ new_map = new HashMap( map ); new_map.remove( key ); } } return( new_map ); } public InetSocketAddress getLANAddress( InetSocketAddress external_address, int address_type ) { Map map; if ( address_type == AT_TCP ){ map = tcp_ext_to_lan; }else if ( address_type == AT_UDP ){ map = udp_ext_to_lan; }else{ map = udp2_ext_to_lan; } if ( map.size() == 0 ){ return( null ); } return((InetSocketAddress)map.get( external_address )); } public InetSocketAddress getExternalAddress( InetSocketAddress lan_address, int address_type ) { Map map; if ( address_type == AT_TCP ){ map = tcp_lan_to_ext; }else if ( address_type == AT_UDP ){ map = udp_lan_to_ext; }else{ map = udp2_lan_to_ext; } if ( map.size() == 0 ){ return( null ); } return((InetSocketAddress)map.get( lan_address )); } public boolean isLANAddress( InetAddress address ) { if ( DISABLE_LAN_LOCAL_STUFF ){ return( false ); } if ( address == null ){ return( false ); } String sp = socks_proxy; if ( sp != null ){ if ( sp.equals( address.getHostAddress())){ return( false ); } } if ( include_well_known_lans ){ if ( address.isLoopbackAddress() || address.isLinkLocalAddress() || address.isSiteLocalAddress()){ return( true ); } } String host_address = address.getHostAddress(); for (int i=0;i 0 ){ Iterator it = explicit_peers.iterator(); while( it.hasNext()){ if (((InetSocketAddress)it.next()).getAddress().equals( address )){ return( true ); } } } return( false ); } public boolean addLANSubnet( String subnet ) throws PatternSyntaxException { String str = ""; for (int i=0;i ALIVE_PERIOD * 2.5 ){ removed.add( inst ); it.remove(); } } }finally{ this_mon.exit(); } for (int i=0;i now ){ last_force_read_ext = now; } boolean ok_to_try_ext = now - last_force_read_ext > FORCE_READ_EXT_MIN; // try upnp - limit frequency unless external read is possible in which // case we try upnp first // currently we only use UPnP to validate our current external address, not // to deduce new ones (as for example there may be multiple upnp devices and // we don't know which one to believe if ( external_address == null && last_external_address != null ){ if ( last_upnp_read > now ){ last_upnp_read = now; } if ( now - last_upnp_read > UPNP_READ_MIN || ok_to_try_ext ){ last_upnp_read = now; try{ UPnPPlugin upnp = adapter.getUPnPPlugin(); if ( upnp != null ){ String[] addresses = upnp.getExternalIPAddresses(); for (int i=0;i map ) { map.put( "id", getID().getBytes()); map.put( "ai", getApplicationID().getBytes()); map.put( "iip", getInternalAddress().getHostAddress().getBytes()); map.put( "eip", getExternalAddress().getHostAddress().getBytes()); map.put( "tp", new Long( getTCPListenPort())); map.put( "dp", new Long( getUDPListenPort())); map.put( "dp2", new Long( getUDPNonDataListenPort())); } public String getString() { String id = getID(); if ( id.length() > 8 ){ id = id.substring(0,8) + "..."; } return( "id=" + id + ",ap=" + getApplicationID() + ",int=" + getInternalAddress().getHostAddress() + ",ext=" + getExternalAddress().getHostAddress() + ",tcp=" + getTCPListenPort() + ",udp=" + getUDPListenPort() + ",udp2=" + getUDPNonDataListenPort()); } } azureus-4.3.0.6/com/aelitis/azureus/core/instancemanager/impl/AZOtherInstanceImpl.java0000644000175000017500000001141011212355540030255 0ustar adrianadrian/* * Created on 20-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.instancemanager.impl; import java.net.Inet4Address; import java.net.InetAddress; import java.util.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.core3.util.SystemTime; public class AZOtherInstanceImpl extends AZInstanceImpl { protected static AZOtherInstanceImpl decode( InetAddress internal_address, Map map ) { String id = new String((byte[])map.get( "id" )); String int_ip = new String((byte[])map.get( "iip" )); String ext_ip = new String((byte[])map.get( "eip" )); int tcp = ((Long)map.get("tp" )).intValue(); int udp = ((Long)map.get("dp" )).intValue(); Long l_udp_other = (Long)map.get("dp2" ); int udp_other = l_udp_other==null?udp:l_udp_other.intValue(); byte[] app_id_bytes = (byte[])map.get( "ai" ); String app_id; if ( app_id_bytes == null ){ app_id = SystemProperties.AZ_APP_ID + "_4.2.0.2"; // we dont know, but this is most likely }else{ app_id = new String( app_id_bytes ); } try{ if ( !int_ip.equals("0.0.0.0")){ internal_address = InetAddress.getByName( int_ip ); } InetAddress external_address = InetAddress.getByName( ext_ip ); // ignore incompatible address mappings if ( internal_address instanceof Inet4Address == external_address instanceof Inet4Address ){ return( new AZOtherInstanceImpl(id, app_id, internal_address, external_address, tcp, udp, udp_other )); } return( null ); }catch( Throwable e ){ Debug.printStackTrace(e); } return( null ); } private String id; private String app_id; private List internal_addresses = new ArrayList(); private InetAddress external_address; private int tcp_port; private int udp_port; private int udp_non_data_port; private long alive_time; protected AZOtherInstanceImpl( String _id, String _app_id, InetAddress _internal_address, InetAddress _external_address, int _tcp_port, int _udp_port, int _udp_non_data_port ) { id = _id; app_id = _app_id; internal_addresses.add( _internal_address ); external_address = _external_address; tcp_port = _tcp_port; udp_port = _udp_port; udp_non_data_port = _udp_non_data_port; alive_time = SystemTime.getCurrentTime(); } protected boolean update( AZOtherInstanceImpl new_inst ) { alive_time = SystemTime.getCurrentTime(); InetAddress new_address = new_inst.getInternalAddress(); boolean same = true; if ( !internal_addresses.contains( new_address )){ same = false; List new_addresses = new ArrayList( internal_addresses ); new_addresses.add( 0, new_address ); internal_addresses = new_addresses; } same = same && external_address.equals( new_inst.external_address ) && tcp_port == new_inst.tcp_port && udp_port == new_inst.udp_port; external_address = new_inst.external_address; tcp_port = new_inst.tcp_port; udp_port = new_inst.udp_port; return( !same ); } public String getID() { return( id ); } public String getApplicationID() { return( app_id ); } public InetAddress getInternalAddress() { return((InetAddress)internal_addresses.get(0)); } public List getInternalAddresses() { return( new ArrayList( internal_addresses )); } public InetAddress getExternalAddress() { return( external_address ); } public int getTCPListenPort() { return( tcp_port ); } public int getUDPListenPort() { return( udp_port ); } public int getUDPNonDataListenPort() { return( udp_non_data_port ); } protected long getAliveTime() { long now = SystemTime.getCurrentTime(); if ( now < alive_time ){ alive_time = now; } return( alive_time ); } } azureus-4.3.0.6/com/aelitis/azureus/core/instancemanager/impl/AZPortClashHandler.java0000644000175000017500000000704410457041776030107 0ustar adrianadrian/* * Created on 03-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.instancemanager.impl; import java.net.InetAddress; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.RandomUtils; import com.aelitis.azureus.core.instancemanager.AZInstance; import com.aelitis.azureus.core.instancemanager.AZInstanceManagerListener; import com.aelitis.azureus.core.instancemanager.AZInstanceTracked; public class AZPortClashHandler implements AZInstanceManagerListener { private AZInstance my_instance; private int last_warned_tcp; private int last_warned_udp; private int last_warned_udp2; protected AZPortClashHandler( AZInstanceManagerImpl inst_man ) { my_instance = inst_man.getMyInstance(); inst_man.addListener( this ); } protected void check( AZInstance instance ) { if ( instance == my_instance ){ return; } InetAddress my_ext = my_instance.getExternalAddress(); InetAddress other_ext = instance.getExternalAddress(); if ( my_ext.isLoopbackAddress() || other_ext.isLoopbackAddress() || my_ext.equals( other_ext )){ String warning = null; int my_tcp = my_instance.getTCPListenPort(); if ( my_tcp != 0 && my_tcp != last_warned_tcp && my_tcp == instance.getTCPListenPort()){ warning = "TCP " + my_tcp; last_warned_tcp = my_tcp; } int my_udp = my_instance.getUDPListenPort(); int my_udp2 = my_instance.getUDPNonDataListenPort(); int other_udp = instance.getUDPListenPort(); int other_udp2 = instance.getUDPNonDataListenPort(); if ( my_udp != 0 && my_udp != last_warned_udp && ( my_udp == other_udp || my_udp == other_udp2 )){ warning = (warning==null?"":(warning + ", ")) + "UDP " + my_udp; last_warned_udp = my_udp; } if ( my_udp != my_udp2 && my_udp2 != 0 && my_udp2 != last_warned_udp2 && ( my_udp2 == other_udp || my_udp2 == other_udp2 )){ warning = (warning==null?"":(warning + ", ")) + "UDP " + my_udp2; last_warned_udp2 = my_udp2; } if ( warning != null ){ Logger.logTextResource( new LogAlert(true, LogAlert.AT_WARNING,"azinstancehandler.alert.portclash"), new String[]{ warning, String.valueOf(RandomUtils.LISTEN_PORT_MIN ), String.valueOf(RandomUtils.LISTEN_PORT_MAX)}); } } } public void instanceFound( AZInstance instance ) { check( instance ); } public void instanceChanged( AZInstance instance ) { check( instance ); } public void instanceLost( AZInstance instance ) { } public void instanceTracked( AZInstanceTracked instance ) { } } azureus-4.3.0.6/com/aelitis/azureus/core/instancemanager/AZInstanceManager.java0000644000175000017500000000440111210152054026756 0ustar adrianadrian/* * Created on 20-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.instancemanager; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.regex.PatternSyntaxException; public interface AZInstanceManager { public static final int AT_TCP = 1; public static final int AT_UDP = 2; public static final int AT_UDP_NON_DATA = 3; public void initialize(); public boolean isInitialized(); public AZInstance getMyInstance(); public AZInstance[] getOtherInstances(); public AZInstanceTracked[] track( byte[] hash, AZInstanceTracked.TrackTarget target ); public InetSocketAddress getLANAddress( InetSocketAddress external_address, int address_type ); public InetSocketAddress getExternalAddress( InetSocketAddress lan_address, int address_type ); public boolean isLANAddress( InetAddress address ); public boolean isExternalAddress( InetAddress address ); public boolean addLANSubnet( String subnet ) throws PatternSyntaxException; public boolean getIncludeWellKnownLANs(); public void setIncludeWellKnownLANs( boolean include ); public long getClockSkew(); public boolean addInstance( InetAddress explicit_address ); public void addListener( AZInstanceManagerListener l ); public void removeListener( AZInstanceManagerListener l ); } azureus-4.3.0.6/com/aelitis/azureus/core/instancemanager/AZInstanceManagerListener.java0000644000175000017500000000241210373051044030472 0ustar adrianadrian/* * Created on 23-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.instancemanager; public interface AZInstanceManagerListener { public void instanceFound( AZInstance instance ); public void instanceChanged( AZInstance instance ); public void instanceLost( AZInstance instance ); public void instanceTracked( AZInstanceTracked instance ); } azureus-4.3.0.6/com/aelitis/azureus/core/instancemanager/AZInstance.java0000644000175000017500000000262311212352026025472 0ustar adrianadrian/* * Created on 20-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.instancemanager; import java.util.List; import java.net.InetAddress; public interface AZInstance { public String getID(); public String getApplicationID(); public InetAddress getInternalAddress(); public List getInternalAddresses(); public InetAddress getExternalAddress(); public int getTCPListenPort(); public int getUDPListenPort(); public int getUDPNonDataListenPort(); public String getString(); } azureus-4.3.0.6/com/aelitis/azureus/core/instancemanager/AZInstanceTracked.java0000644000175000017500000000232411210152054026763 0ustar adrianadrian/* * Created on 05-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.instancemanager; public interface AZInstanceTracked { public AZInstance getInstance(); public TrackTarget getTarget(); public boolean isSeed(); interface TrackTarget { public Object getTarget(); public boolean isSeed(); } } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/0000755000175000017500000000000011310377626021472 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/messenger/config/0000755000175000017500000000000011310377626022737 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/messenger/config/PlatformMetaSearchMessenger.java0000644000175000017500000001731111306116372031171 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.messenger.config; import java.util.*; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.messenger.PlatformMessenger; import com.aelitis.azureus.core.messenger.PlatformMessengerException; public class PlatformMetaSearchMessenger { private static final int MAX_TEMPLATE_LIST = 512; private static final PlatformMessengerConfig dispatcher = new PlatformMessengerConfig( "searchtemplate", true ); private static final String OP_GET_TEMPLATE = "get-template"; private static final String OP_GET_TEMPLATES = "get-templates"; private static final String OP_LIST_POPULAR_TEMPLATES = "list-popular"; private static final String OP_LIST_FEATURED_TEMPLATES = "list-featured"; private static final String OP_TEMPLATE_SELECTED = "template-selected"; public static templateDetails getTemplate( long template_id ) throws PlatformMessengerException { Map reply = dispatcher.syncInvoke( OP_GET_TEMPLATE, getParameter( template_id ) ); templateInfo info = getTemplateInfo( reply ); if ( info == null ){ throw( new PlatformMessengerException( "Invalid reply: " + reply )); } String name = (String)reply.get( "name" ); String value = (String)reply.get( "value" ); String engine_type = (String)reply.get( "engine_id" ); if ( name == null || value == null || engine_type == null ){ throw( new PlatformMessengerException( "Invalid reply; field missing: " + reply )); } int type; if ( engine_type.equals( "json" )){ type = templateDetails.ENGINE_TYPE_JSON; }else if ( engine_type.equals( "regexp" )){ type = templateDetails.ENGINE_TYPE_REGEXP; }else{ throw( new PlatformMessengerException( "Invalid type '" + engine_type + ": " + reply )); } return( new templateDetails( info, type, name, value )); } public static templateInfo[] getTemplateDetails( long[] ids ) throws PlatformMessengerException { if( ids.length == 0 ){ return( new templateInfo[0]); } String str = ""; for (int i=0;i getAssociations(Map reply) { try { Map result = (Map) reply.get("results"); Map results = new HashMap(); for(String key : result.keySet()) { results.put(key, getAssociationFromMap(result.get(key))); } return results; } catch (Exception e) { e.printStackTrace(); return new HashMap(); } } public static Map getAssociations( String[] hashes ) throws PlatformMessengerException { Map result = new HashMap(); if( hashes.length == 0 ){ return result; } Map reply = dispatcher.syncInvoke( OP_LOOKUP, getParameters(hashes) ); return( getAssociations( reply )); } public static void addSubmission(Association assoc) throws PlatformMessengerException { Map parameters = new HashMap(); Map submission = new HashMap(); submission.put("hash",assoc.hash); submission.put("db", assoc.db); submission.put("db_id",assoc.db_id); if(assoc instanceof MovieAssociation) { submission.put("type", "movie"); submission.put("quality", ((MovieAssociation)assoc).quality.quality); submission.put("language", ((MovieAssociation)assoc).language.getLanguage()); } if(assoc instanceof TvShowAssociation) { submission.put("type", "tv"); submission.put("quality", ((MovieAssociation)assoc).quality.quality); submission.put("language", ((MovieAssociation)assoc).language.getLanguage()); } if(assoc instanceof MusicAssociation) { submission.put("type", "music"); submission.put("quality", ((MovieAssociation)assoc).quality.quality); } parameters.put("submission", submission); dispatcher.syncInvoke( OP_SUBMIT, parameters ); } public static SearchResult[] search(String title) throws PlatformMessengerException { Map parameters = new HashMap(); parameters.put("title", title); Map reply = dispatcher.syncInvoke( OP_SEARCH, parameters ); List results = (List)reply.get("results"); SearchResult[] searchResults = new SearchResult[results.size()]; int i = 0; for(Map result : results) { SearchResult searchResult = new SearchResult(); searchResult.title = (String)result.get("title"); searchResult.db = (String)result.get("db"); searchResult.db_id = (String)result.get("db_id"); searchResults[i++] = searchResult; } return searchResults; } public static class SearchResult { String title; String db; String db_id; @Override public String toString() { return db + "." + db_id + " : " + title; } } protected static Map getParameter( String hash ) { Map parameters = new HashMap(); parameters.put( "hash", hash ); return( parameters ); } protected static Map getParameters( String[] hashes ) { Map parameters = new HashMap(); parameters.put( "hashes", hashes); return( parameters ); } public static abstract class Association { public String hash; public String db; public String db_id; //Cached but not stored public String title; @Override public String toString() { return hash + " > " + db + "." + db_id + " : " + title; } } public static class EmptyAssociation extends Association { } public static abstract class VideoAssociation extends Association { public VideoQuality quality; public Locale language; } public static class MovieAssociation extends VideoAssociation { } public static class TvShowAssociation extends VideoAssociation { } public static class MusicAssociation extends Association { public AudioQuality quality; } public static enum VideoQuality { LOW("low"),DVD("dvd"),HD_720p("720p"),HD_1080p("1080p"); String quality; private VideoQuality(String quality) { this.quality = quality; } public static VideoQuality fromString(String quality) { quality = quality.toLowerCase(); if(LOW.quality.equals(quality)) return LOW; if(DVD.quality.equals(quality)) return DVD; if(HD_720p.quality.equals(quality)) return HD_720p; if(HD_1080p.quality.equals(quality)) return HD_1080p; return null; } } public static enum AudioQuality { LOW("low"),HIGH("high"),LOSSLESS("lossless"); String quality; private AudioQuality(String quality) { this.quality = quality; } public static AudioQuality fromString(String quality) { quality = quality.toLowerCase(); if(LOW.quality.equals(quality)) return LOW; if(HIGH.quality.equals(quality)) return HIGH; if(LOSSLESS.quality.equals(quality)) return LOSSLESS; return null; } } public static void main(String[] args) throws Exception { SearchResult[] results = search("Dark Knight"); for(SearchResult result : results) { System.out.println(result); } MovieAssociation assoc = new MovieAssociation(); assoc.db = "tmdb"; assoc.db_id = "155"; assoc.hash = "test"; assoc.quality = VideoQuality.DVD; assoc.language = new Locale("en"); addSubmission(assoc); Association assocL = getAssociation("test"); System.out.println(assocL); } } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/config/PlatformTorrentMessenger.java0000644000175000017500000000557011266266266030633 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.messenger.config; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import com.aelitis.azureus.core.messenger.PlatformMessage; import com.aelitis.azureus.core.messenger.PlatformMessenger; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; /** * @author TuxPaper * @created Oct 13, 2006 * */ public class PlatformTorrentMessenger { public static String LISTENER_ID = "torrent"; public static String OP_STREAMCOMPLETE = "stream-complete"; public static void streamComplete(TOTorrent torrent, long waitTime, int maxSeekAheadSecs, int numRebuffers, int numHardRebuffers) { String hash = null; try { hash = torrent.getHashWrapper().toBase32String(); } catch (TOTorrentException e) { } if (hash == null) { return; } Map mapParameters = new HashMap(); mapParameters.put("torrent-hash", hash); mapParameters.put("wait-time", new Long(waitTime)); mapParameters.put("max-seek", new Long(maxSeekAheadSecs)); mapParameters.put("num-rebuffers", new Long(numRebuffers)); mapParameters.put("num-hard-rebuffers", new Long(numHardRebuffers)); PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID, OP_STREAMCOMPLETE, mapParameters, 3000); message.setContentNetworkID(PlatformTorrentUtils.getContentNetworkID(torrent)); PlatformMessenger.queueMessage(message, null); } public static void streamComplete(TOTorrent torrent, Map info) { String hash = null; try { hash = torrent.getHashWrapper().toBase32String(); } catch (TOTorrentException e) { } if (hash == null) { return; } Map mapParameters = new HashMap(info); mapParameters.put("torrent-hash", hash); PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID, OP_STREAMCOMPLETE, mapParameters, 3000); message.setContentNetworkID(PlatformTorrentUtils.getContentNetworkID(torrent)); PlatformMessenger.queueMessage(message, null); } } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/config/PlatformContentNetworkMessenger.java0000644000175000017500000001030711274425254032145 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.messenger.config; import java.util.*; import org.gudy.azureus2.core3.util.Constants; import org.json.simple.JSONObject; import com.aelitis.azureus.core.messenger.*; public class PlatformContentNetworkMessenger { private static final String LISTENER_ID = "cnetworks"; private static final PlatformMessengerConfig dispatcher = new PlatformMessengerConfig( LISTENER_ID, true ); private static final String OP_LIST_CNETORKS = "list-networks"; public static List listNetworks() throws PlatformMessengerException { if (true) { return new ArrayList(0); } JSONObject parameters = new JSONObject(); parameters.put( "azver", Constants.AZUREUS_VERSION ); Map reply = dispatcher.syncInvoke( OP_LIST_CNETORKS, parameters ); List networks = (List)reply.get( "networks" ); if ( networks == null ){ throw( new PlatformMessengerException( "No networks returned" )); } List result = new ArrayList(); for ( Map map: networks ){ result.add( new contentNetworkDetails( map )); } return( result ); } public static void listNetworksAync(final listNetworksListener l, int maxDelayMS) { if (l != null) { l.networkListReturned(new ArrayList(0)); return; } JSONObject parameters = new JSONObject(); parameters.put("azver", Constants.AZUREUS_VERSION); PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID, OP_LIST_CNETORKS, parameters, maxDelayMS); PlatformMessengerListener listener = new PlatformMessengerListener() { // @see com.aelitis.azureus.core.messenger.PlatformMessengerListener#replyReceived(com.aelitis.azureus.core.messenger.PlatformMessage, java.lang.String, java.util.Map) public void replyReceived(PlatformMessage message, String replyType, Map reply) { List networks = (List) reply.get("networks"); List result; if (networks == null) { result = null; } else { result = new ArrayList(); for (Map map : networks) { result.add(new contentNetworkDetails(map)); } } if (l != null) { l.networkListReturned(result); } } // @see com.aelitis.azureus.core.messenger.PlatformMessengerListener#messageSent(com.aelitis.azureus.core.messenger.PlatformMessage) public void messageSent(PlatformMessage message) { } }; PlatformMessenger.queueMessage(message, listener); } public static class contentNetworkDetails { private Map details; protected contentNetworkDetails( Map _details ) { details = _details; } public long getID() { return(((Long)details.get( "id" )).longValue()); } public long getVersion() { return(((Long)details.get( "version" )).longValue()); } public String getName() { return((String)details.get( "name" )); } public String getIconURL() { return((String)details.get( "iconUrl" )); } public String getMainURL() { return((String)details.get( "baseUrl" )); } public String getString() { return( "id=" + getID() + ";version=" + getVersion() + ";name=" + getName()); } } public static interface listNetworksListener { public void networkListReturned(List list); } } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/config/PlatformConfigMessenger.java0000644000175000017500000001672211274702176030376 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.messenger.config; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerFactory; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.core.messenger.PlatformMessage; import com.aelitis.azureus.core.messenger.PlatformMessenger; import com.aelitis.azureus.core.messenger.PlatformMessengerListener; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.util.*; import org.gudy.azureus2.plugins.platform.PlatformManagerException; /** * @author TuxPaper * @created Sep 26, 2006 * */ public class PlatformConfigMessenger { public static final String LISTENER_ID = "config"; private static boolean allowSendDeviceList = false; private static int iRPCVersion = 0; private static String playAfterURL = null; private static boolean sendStats = true; private static boolean doUrlQOS = false; private static boolean platformLoginComplete = false; protected static List platformLoginCompleteListeners = Collections.EMPTY_LIST; public static void login(long contentNetworkID, long maxDelayMS) { PlatformManager pm = PlatformManagerFactory.getPlatformManager(); String azComputerID = ""; try { azComputerID = pm.getAzComputerID(); } catch (PlatformManagerException e) { } String sourceRef = null; if (contentNetworkID != ConstantsVuze.DEFAULT_CONTENT_NETWORK_ID) { ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetwork(contentNetworkID); sourceRef = (String) cn.getPersistentProperty(ContentNetwork.PP_SOURCE_REF); } if (sourceRef == null) { sourceRef = "unknown"; } Object[] params = new Object[] { "version", org.gudy.azureus2.core3.util.Constants.AZUREUS_VERSION, "locale", Locale.getDefault().toString(), "azCID", azComputerID, "vid", COConfigurationManager.getStringParameter("ID"), "source-ref", sourceRef }; PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID, "login", params, maxDelayMS); message.setContentNetworkID(contentNetworkID); PlatformMessengerListener listener = new PlatformMessengerListener() { public void replyReceived(PlatformMessage message, String replyType, Map reply) { if (reply == null) { return; } boolean allowMulti = MapUtils.getMapBoolean(reply, "allow-multi-rpc", PlatformMessenger.getAllowMulti()); PlatformMessenger.setAllowMulti(allowMulti); try { List listURLs = (List) MapUtils.getMapObject(reply, "url-whitelist", null, List.class); if (listURLs != null) { for (int i = 0; i < listURLs.size(); i++) { String string = (String) listURLs.get(i); UrlFilter.getInstance().addUrlWhitelist(string); } } } catch (Exception e) { Debug.out(e); } try { List listURLs = (List) MapUtils.getMapObject(reply, "url-blacklist", null, List.class); if (listURLs != null) { for (int i = 0; i < listURLs.size(); i++) { String string = (String) listURLs.get(i); UrlFilter.getInstance().addUrlBlacklist(string); } } } catch (Exception e) { Debug.out(e); } try { List listDomains = (List) MapUtils.getMapObject(reply, "tracker-domains", null, List.class); if (listDomains != null) { for (int i = 0; i < listDomains.size(); i++) { String s = (String) listDomains.get(i); PlatformTorrentUtils.addPlatformHost(s); PlatformMessenger.debug("v3.login: got tracker domain of " + s); } } } catch (Exception e) { Debug.out(e); } if (message.getContentNetworkID() != ConstantsVuze.getDefaultContentNetwork().getID()) { return; } try { sendStats = MapUtils.getMapBoolean(reply, "send-stats", false); doUrlQOS = MapUtils.getMapBoolean(reply, "do-url-qos", false); allowSendDeviceList = MapUtils.getMapBoolean(reply, "send-device-list", false); } catch (Exception e) { } try { iRPCVersion = MapUtils.getMapInt(reply, "rpc-version", 0); playAfterURL = (String) MapUtils.getMapString(reply, "play-after-url", null); } catch (Exception e) { Debug.out(e); } platformLoginComplete = true; Object[] listeners = platformLoginCompleteListeners.toArray(); platformLoginCompleteListeners = Collections.EMPTY_LIST; for (int i = 0; i < listeners.length; i++) { try { PlatformLoginCompleteListener l = (PlatformLoginCompleteListener) listeners[i]; l.platformLoginComplete(); } catch (Exception e) { Debug.out(e); } } } public void messageSent(PlatformMessage message) { } }; PlatformMessenger.pushMessageNow(message, listener); } public static void sendUsageStats(Map stats, long timestamp, String version, PlatformMessengerListener l) { if (!sendStats) { return; } try { PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID, "send-usage-stats2", new Object[] { "stats", stats, "version", version, "timestamp", new Long(timestamp), "ago-ms", new Long(SystemTime.getCurrentTime() - timestamp), }, 5000); PlatformMessenger.queueMessage(message, l); } catch (Exception e) { Debug.out(e); } } public static interface GetBrowseSectionsReplyListener { public void messageSent(); public void replyReceived(Map[] browseSections); } /** * @return the iRPCVersion */ public static int getRPCVersion() { return iRPCVersion; } public static String getPlayAfterURL() { return playAfterURL; } public static boolean allowSendStats() { return sendStats; } /** * @return * * @since 4.0.0.1 */ public static boolean doUrlQOS() { return doUrlQOS; } public static void addPlatformLoginCompleteListener( PlatformLoginCompleteListener l) { try { if (l == null) { return; } if (platformLoginComplete) { l.platformLoginComplete(); return; } if (platformLoginCompleteListeners == Collections.EMPTY_LIST) { platformLoginCompleteListeners = new ArrayList(1); } platformLoginCompleteListeners.add(l); } catch (Exception e) { Debug.out(e); } } public static interface PlatformLoginCompleteListener { public void platformLoginComplete(); } public static boolean allowSendDeviceList() { return allowSendDeviceList; } } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/config/PlatformSubscriptionsMessenger.java0000644000175000017500000001535111265012716032027 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.messenger.config; import java.security.Signature; import java.util.*; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.ByteFormatter; import org.json.simple.JSONArray; import com.aelitis.azureus.core.messenger.PlatformMessengerException; import com.aelitis.azureus.core.security.CryptoECCUtils; public class PlatformSubscriptionsMessenger { private static final boolean MESSAGING_ENABLED = true; private static final PlatformMessengerConfig dispatcher = new PlatformMessengerConfig( "subscription", false ); private static final String OP_CREATE_SUBS = "create-subscription"; private static final String OP_UPDATE_SUBS = "update-subscription"; private static final String OP_GET_SUBS_BY_SID = "get-subscriptions"; private static final String OP_GET_POP_BY_SID = "get-subscription-infos"; private static final String OP_SET_SELECTED = "set-selected"; public static void updateSubscription( boolean create, String name, byte[] public_key, byte[] private_key, byte[] sid, int version, String content ) throws PlatformMessengerException { String operation = create?OP_CREATE_SUBS:OP_UPDATE_SUBS; checkEnabled( operation ); Map parameters = new HashMap(); String sid_str = Base32.encode( sid ); String pk_str = Base32.encode(public_key) ; parameters.put( "name", name ); parameters.put( "subscription_id", sid_str ); parameters.put( "version_number", new Long( version )); parameters.put( "content", content ); if ( create ){ parameters.put( "public_key", pk_str ); } try{ Signature sig = CryptoECCUtils.getSignature( CryptoECCUtils.rawdataToPrivkey( private_key )); sig.update( ( name + pk_str + sid_str + version + content ).getBytes( "UTF-8" )); byte[] sig_bytes = sig.sign(); /* Signature verify = CryptoECCUtils.getSignature( CryptoECCUtils.rawdataToPubkey( public_key )); verify.update( ( name + pk_str + sid_str + version + content ).getBytes( "UTF-8" )); boolean ok = verify.verify( sig_bytes ); */ parameters.put( "signature", Base32.encode( sig_bytes )); dispatcher.syncInvoke( operation, parameters ); }catch( Throwable e ){ throw( new PlatformMessengerException( "Failed to create/update subscription", e )); } } public static subscriptionDetails getSubscriptionBySID( byte[] sid ) throws PlatformMessengerException { checkEnabled( OP_GET_SUBS_BY_SID ); Map parameters = new HashMap(); List sid_list = new JSONArray(); sid_list.add( Base32.encode( sid )); parameters.put( "subscription_ids", sid_list); Map reply = dispatcher.syncInvoke( OP_GET_SUBS_BY_SID, parameters ); for (int i=0;i map = new HashMap(); addPluginVersionsToMap(map); map.put("device-name", device.getName()); map.put("device-type", new Integer(device.getType())); if (device instanceof DeviceMediaRenderer) { DeviceMediaRenderer renderer = (DeviceMediaRenderer) device; map.put("renderer-species", Integer.valueOf(renderer.getRendererSpecies())); } PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID, OP_QOS_FOUND_DEVICE, map, 5000); message.setSendAZID(false); PlatformMessenger.queueMessage(message, null); } private static void addPluginVersionsToMap(Map map) { if (AzureusCoreFactory.isCoreRunning()) { PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager(); PluginInterface pi; pi = pm.getPluginInterfaceByID("vuzexcode"); if (pi != null) { map.put("xcode-plugin-version", pi.getPluginVersion()); } pi = pm.getPluginInterfaceByID("azitunes"); if (pi != null) { map.put("itunes-plugin-version", pi.getPluginVersion()); } } map.put("os-name", Constants.OSName); } public static void qosTranscodeRequest(TranscodeTarget transcodeTarget, String sourceRef) { if (!COConfigurationManager.getBooleanParameter(CFG_SEND_QOS, false) || transcodeTarget == null) { return; } HashMap map = new HashMap(); addPluginVersionsToMap(map); Device device = transcodeTarget.getDevice(); if (device != null) { // should never be null.. map.put("device-name", device.getName()); map.put("device-type", new Integer(device.getType())); } if (transcodeTarget instanceof DeviceMediaRenderer) { DeviceMediaRenderer renderer = (DeviceMediaRenderer) transcodeTarget; map.put("renderer-species", Integer.valueOf(renderer.getRendererSpecies())); } map.put("source-ref", sourceRef); PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID, OP_QOS_TRANSCODE_REQUEST, map, 5000); message.setSendAZID(false); PlatformMessenger.queueMessage(message, null); } public static void qosTranscode(TranscodeJob job, int stateOveride) { if (!COConfigurationManager.getBooleanParameter(CFG_SEND_QOS, false) || job == null) { return; } TranscodeFile transcodeFile = job.getTranscodeFile(); DiskManagerFileInfo sourceFileInfo = null; try { sourceFileInfo = transcodeFile.getSourceFile(); } catch (Throwable t) { } DiskManagerFileInfo targetFileInfo = null; try { targetFileInfo = transcodeFile.getTargetFile(); } catch (Throwable t) { } TranscodeProfile profile = job.getProfile(); TranscodeTarget target = job.getTarget(); Device device = target.getDevice(); HashMap map = new HashMap(); addPluginVersionsToMap(map); map.put("job-state", Integer.valueOf(stateOveride)); if ((stateOveride & 0xff) == TranscodeJob.ST_FAILED) { String error = job.getError(); if (error != null) { if (error.endsWith("\r\n")) { error.substring(0, error.length() - 2); } else if (error.endsWith("\r") || error.endsWith("\n")) { error.substring(0, error.length() - 1); } } map.put("job-error", error); } try { Torrent torrent = job.getFile().getDownload().getTorrent(); if (PlatformTorrentUtils.isContent(torrent, true)) { map.put("asset-hash", new HashWrapper(torrent.getHash()).toBase32String()); } } catch (Throwable t) { } map.put("transcode-mode", new Integer(job.getTranscodeRequirement())); map.put("transcode-required", new Boolean(transcodeFile.getTranscodeRequired())); // These help us determine if the transcode is taking too long map.put("transcode-video-width", new Long(transcodeFile.getVideoWidth())); map.put("transcode-video-height", new Long(transcodeFile.getVideoHeight())); map.put("transcode-video-duration-ms", new Long(transcodeFile.getDurationMillis())); map.put("process-time-ms", new Long(job.getProcessTime())); // Gotta know which device/profile/renderer we are transcoding to so we // know what's should be worked on more map.put("device-name", device.getName()); map.put("device-type", new Integer(device.getType())); if (profile != null) { map.put("profile-name", profile.getName()); } if (target instanceof DeviceMediaRenderer) { DeviceMediaRenderer renderer = (DeviceMediaRenderer) target; map.put("renderer-species", Integer.valueOf(renderer.getRendererSpecies())); } // Don't worry, we don't send the filename, just the extension. This // helps us figure out which file types are failing/succeeding the most if (sourceFileInfo != null) { map.put("source-file-ext", FileUtil.getExtension(sourceFileInfo.getFile().getName())); map.put("source-file-size", new Long(sourceFileInfo.getLength())); } if (targetFileInfo != null) { map.put("target-file-ext", FileUtil.getExtension(targetFileInfo.getFile().getName())); map.put("target-file-size", new Long(targetFileInfo.getLength())); } PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID, OP_QOS_TRANSCODE, map, 5000); message.setSendAZID(false); PlatformMessenger.queueMessage(message, null); } public static void setupDeviceSender() { final DeviceManager deviceManager = DeviceManagerFactory.getSingleton(); Device[] devices = deviceManager.getDevices(); if (devices == null || devices.length == 0) { deviceManager.addListener(new DeviceManagerListener() { public void deviceRemoved(Device device) { } public void deviceChanged(Device device) { } public void deviceAttentionRequest(Device device) { } public void deviceAdded(Device device) { } public void deviceManagerLoaded() { deviceManager.removeListener(this); Device[] devices = deviceManager.getDevices(); if (devices != null && devices.length > 0) { sendDeviceList(devices); } } }); } else { sendDeviceList(devices); } } private static void sendDeviceList(Device[] devices) { if (!PlatformConfigMessenger.allowSendDeviceList()) { return; } List listRenderers = new ArrayList(devices.length); for (Device dev : devices) { if (dev.getType() == Device.DT_MEDIA_RENDERER) { listRenderers.add(dev.getClassification()); } } if (listRenderers.size() == 0) { return; } PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID, OP_REPORT_DEVICES, new Object[] { "renderers", listRenderers }, 500); PlatformMessenger.queueMessage(message, null); } } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/config/PlatformVuzeActivitiesMessenger.java0000644000175000017500000000615411267001364032136 0ustar adrianadrian/** * Created on Jan 28, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.messenger.config; import java.util.Iterator; import java.util.List; import java.util.Map; import com.aelitis.azureus.activities.VuzeActivitiesEntry; import com.aelitis.azureus.activities.VuzeActivitiesManager; import com.aelitis.azureus.core.messenger.PlatformMessage; import com.aelitis.azureus.core.messenger.PlatformMessenger; import com.aelitis.azureus.core.messenger.PlatformMessengerListener; import com.aelitis.azureus.util.MapUtils; /** * @author TuxPaper * @created Jan 28, 2008 * */ public class PlatformVuzeActivitiesMessenger { public static final String LISTENER_ID = "vuzenews"; public static final String OP_GET = "get-entries"; public static final long DEFAULT_RETRY_MS = 1000L * 60 * 60 * 24; public static void getEntries(final long contentNetworkID, final long agoMS, long maxDelayMS, final GetEntriesReplyListener replyListener) { PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID, OP_GET, new Object[] { "ago-ms", new Long(agoMS), }, maxDelayMS); message.setContentNetworkID(contentNetworkID); PlatformMessengerListener listener = null; if (replyListener != null) { listener = new PlatformMessengerListener() { public void messageSent(PlatformMessage message) { } public void replyReceived(PlatformMessage message, String replyType, Map reply) { VuzeActivitiesEntry[] entries = new VuzeActivitiesEntry[0]; List entriesList = (List) MapUtils.getMapObject(reply, "entries", null, List.class); if (entriesList != null && entriesList.size() > 0) { entries = new VuzeActivitiesEntry[entriesList.size()]; int i = 0; for (Iterator iter = entriesList.iterator(); iter.hasNext();) { Map platformEntry = (Map) iter.next(); if (platformEntry == null) { continue; } entries[i] = VuzeActivitiesManager.createEntryFromMap( contentNetworkID, platformEntry, false); if (entries[i] != null) { i++; } } } long refreshInMS = MapUtils.getMapLong(reply, "refresh-in-ms", DEFAULT_RETRY_MS); replyListener.gotVuzeNewsEntries(entries, refreshInMS); } }; } PlatformMessenger.queueMessage(message, listener); } public static interface GetEntriesReplyListener { public void gotVuzeNewsEntries(VuzeActivitiesEntry[] entries, long refreshInMS); } } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/PlatformMessengerListener.java0000644000175000017500000000225610631203646027500 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.messenger; import java.util.Map; /** * @author TuxPaper * @created Sep 25, 2006 * */ public interface PlatformMessengerListener { public void messageSent(PlatformMessage message); public void replyReceived(PlatformMessage message, String replyType, Map reply); } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/ClientMessageContextImpl.java0000644000175000017500000000627711267001364027255 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.messenger; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEDiagnosticsLogger; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher; import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener; import com.aelitis.azureus.util.ConstantsVuze; /** * @author TuxPaper * @created Oct 9, 2006 * */ public abstract class ClientMessageContextImpl implements ClientMessageContext { private String id; private BrowserMessageDispatcher dispatcher; public ClientMessageContextImpl(String id, BrowserMessageDispatcher dispatcher) { this.id = id; this.dispatcher = dispatcher; } public void addMessageListener(BrowserMessageListener listener) { if (dispatcher != null) { dispatcher.addListener(listener); } else { debug("No dispatcher when trying to add MessageListener " + listener.getId() + ";" + Debug.getCompressedStackTrace()); } } public void debug(String message) { AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("v3.CMsgr"); diag_logger.log("[" + id + "] " + message); if (ConstantsVuze.DIAG_TO_STDOUT) { System.out.println("[" + id + "] " + message); } } public void debug(String message, Throwable t) { AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("v3.CMsgr"); diag_logger.log("[" + id + "] " + message); diag_logger.log(t); if (ConstantsVuze.DIAG_TO_STDOUT) { System.err.println("[" + id + "] " + message); t.printStackTrace(); } } public void removeMessageListener(String listenerId) { if (dispatcher != null) { dispatcher.removeListener(listenerId); } else { debug("No dispatcher when trying to remove MessageListener " + listenerId + ";" + Debug.getCompressedStackTrace()); } } public void removeMessageListener(BrowserMessageListener listener) { if (dispatcher != null) { dispatcher.removeListener(listener); } else { debug("No dispatcher when trying to remove MessageListener " + listener.getId() + ";" + Debug.getCompressedStackTrace()); } } public BrowserMessageDispatcher getDispatcher() { return dispatcher; } public String getID() { return id; } public void setMessageDispatcher(BrowserMessageDispatcher dispatcher) { this.dispatcher = dispatcher; } } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/PlatformMessengerException.java0000644000175000017500000000207011010526006027631 0ustar adrianadrian/* * Created on May 7, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.messenger; public class PlatformMessengerException extends Exception { public PlatformMessengerException( String str ) { super( str ); } public PlatformMessengerException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/PlatformMessenger.java0000644000175000017500000004355411274674176026016 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.messenger; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLEncoder; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Timer; import org.gudy.azureus2.plugins.utils.StaticUtilities; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.util.*; /** * @author TuxPaper * @created Sep 25, 2006 * */ public class PlatformMessenger { private static final boolean DEBUG_URL = System.getProperty( "platform.messenger.debug.url", "0").equals("1"); private static final String URL_PLATFORM_MESSAGE = "?service=rpc"; private static final String URL_POST_PLATFORM_DATA = "service=rpc"; private static final int MAX_POST_LENGTH = 1024 * 512 * 3; // 1.5M private static boolean USE_HTTP_POST = true; public static String REPLY_EXCEPTION = "exception"; public static String REPLY_ACTION = "action"; public static String REPLY_RESULT = "response"; /** Key: id of queue; Value: Map of queued messages & listeners */ static private Map mapQueues = new HashMap(); private static final String QUEUE_NOAZID = "noazid."; private static final String QUEUE_NORMAL = "msg."; static private AEMonitor queue_mon = new AEMonitor( "v3.PlatformMessenger.queue"); static private Timer timerProcess = new Timer("v3.PlatformMessenger.queue"); //static private TimerEvent timerEvent = null; static private Map mapTimerEvents = new HashMap(); static private AEMonitor mon_mapTimerEvents = new AEMonitor("mapTimerEvents"); private static boolean initialized; private static fakeContext context; private static boolean allowMulti = false; private static AsyncDispatcher dispatcher = new AsyncDispatcher(5000); public static synchronized void init() { if (initialized) { return; } initialized = true; // The UI will initialize this context = new fakeContext(); } public static ClientMessageContext getClientMessageContext() { if (!initialized) { init(); } return context; } public static void queueMessage(PlatformMessage message, PlatformMessengerListener listener) { queueMessage(message, listener, true); } public static void queueMessage(PlatformMessage message, PlatformMessengerListener listener, boolean addToBottom) { if ( COConfigurationManager.getStringParameter( "ui", "az3" ).equals( "az2" )){ Debug.out( "**** PlatformMessenger shouldn't be used with az2 UI ****" ); } if (!initialized) { init(); } if (message == null) { debug("fire timerevent"); } queue_mon.enter(); try { long fireBefore; String queueID = null; if (message != null) { long networkID = message.getContentNetworkID(); if (networkID <= 0) { debug("Content Network invalid for " + message); return; } if (!message.sendAZID()) { queueID = QUEUE_NOAZID; } else { queueID = QUEUE_NORMAL; } queueID += networkID; Map mapQueue = (Map) mapQueues.get(queueID); if (mapQueue == null) { mapQueue = new LinkedHashMap(); mapQueues.put(queueID, mapQueue); } mapQueue.put(message, listener); debug("q " + queueID + "(" + mapQueue.size() + ") " + message.toShortString() + ": " + message + " @ " + new Date(message.getFireBefore()) + "; in " + (message.getFireBefore() - SystemTime.getCurrentTime()) + "ms"); fireBefore = message.getFireBefore(); } else { fireBefore = SystemTime.getCurrentTime(); } if (queueID != null) { try { mon_mapTimerEvents.enter(); TimerEvent timerEvent = mapTimerEvents.get(queueID); if (timerEvent == null || timerEvent.hasRun() || fireBefore < timerEvent.getWhen()) { if (timerEvent != null) { mapTimerEvents.remove(timerEvent); timerEvent.cancel(); } final String fQueueID = queueID; timerEvent = timerProcess.addEvent(fireBefore, new TimerEventPerformer() { public void perform(TimerEvent event) { try { mon_mapTimerEvents.enter(); mapTimerEvents.remove(event); } finally { mon_mapTimerEvents.exit(); } Map mapQueue = mapQueues.get(fQueueID); while (mapQueue != null && mapQueue.size() > 0) { processQueue(fQueueID, mapQueue); } /* Object[] keys = mapQueues.keySet().toArray(); for (int i = 0; i < keys.length; i++) { Map mapQueue = mapQueues.get(keys[i]); while (mapQueue != null && mapQueue.size() > 0) { processQueue(mapQueue); } } */ } }); mapTimerEvents.put(queueID, timerEvent); } if (timerEvent != null) { debug(" next q process for " + queueID + " in " + (timerEvent.getWhen() - SystemTime.getCurrentTime())); } } finally { mon_mapTimerEvents.exit(); } } } finally { queue_mon.exit(); } } /** * @param string */ public static void debug(String string) { AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("v3.PMsgr"); diag_logger.log(string); if (ConstantsVuze.DIAG_TO_STDOUT) { System.out.println(Thread.currentThread().getName() + "|" + System.currentTimeMillis() + "] " + string); } } protected static void debug(String string, Throwable e) { debug(string + "\n\t" + e.getClass().getName() + ": " + e.getMessage() + ", " + Debug.getCompressedStackTrace(e, 1, 80)); } /** * Sends the message almost immediately, skipping delayauthorization check * @param message * @param listener * * @since 3.0.5.3 */ public static void pushMessageNow(PlatformMessage message, PlatformMessengerListener listener) { debug("push " + message.toShortString() + ": " + message); Map map = new HashMap(1); map.put(message, listener); processQueue(null, map); } /** * @param requiresAuthorization * */ protected static void processQueue(String queueID, Map mapQueue) { if (!initialized) { init(); } final Map mapProcessing = new HashMap(); boolean sendAZID = true; long contentNetworkID = ContentNetwork.CONTENT_NETWORK_VUZE; // Create urlStem (or post data) boolean isMulti = false; StringBuffer urlStem = new StringBuffer(); long sequenceNo = 0; Map mapPayload = new HashMap(); mapPayload.put("azid", ConstantsVuze.AZID); mapPayload.put("azv", Constants.AZUREUS_VERSION); List listCommands = new ArrayList(); mapPayload.put("commands", listCommands); queue_mon.enter(); try { String lastServer = null; // add one at a time, ensure relay server messages are seperate boolean first = true; for (Iterator iter = mapQueue.keySet().iterator(); iter.hasNext();) { PlatformMessage message = (PlatformMessage) iter.next(); Object value = mapQueue.get(message); Map mapCmd = new HashMap(); if (first) { sendAZID = message.sendAZID(); contentNetworkID = message.getContentNetworkID(); first = false; } // build urlStem message.setSequenceNo(sequenceNo); if (urlStem.length() > 0) { urlStem.append('&'); } String listenerID = message.getListenerID(); String messageID = message.getMessageID(); Map params = message.getParameters(); try { urlStem.append("msg="); urlStem.append(URLEncoder.encode(listenerID, "UTF-8")); urlStem.append(":"); urlStem.append(URLEncoder.encode(message.getOperationID(), "UTF-8")); } catch (UnsupportedEncodingException e) { } mapCmd.put("seq-id", sequenceNo); mapCmd.put("listener-id", listenerID); mapCmd.put("op-id", message.getOperationID()); if (params != null) { mapCmd.put("values", params); } listCommands.add(mapCmd); // We used to check on MAX_POST_LENGTH, but with the changes that // would require converting the map to JSON on every iteration to get // the length. For now, just limit to 10 if (sequenceNo > 10) { debug("breaking up batch at " + sequenceNo + " because max limit would be exceeded"); break; } String curServer = messageID + "-" + listenerID; if (lastServer != null && !lastServer.equals(curServer)) { isMulti = true; } lastServer = curServer; PlatformMessengerListener listener = (PlatformMessengerListener) mapProcessing.get(message); if (listener != null) { listener.messageSent(message); } sequenceNo++; // Adjust lists mapProcessing.put(message, value); iter.remove(); if (!getAllowMulti() ) { break; } } } finally { queue_mon.exit(); } //debug("about to process " + mapProcessing.size()); if (mapProcessing.size() == 0) { return; } // Build base RPC url based on listener and server // one day all this URL hacking should be moved into the ContentNetwork... ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetwork( contentNetworkID); if (cn == null) { cn = ConstantsVuze.getDefaultContentNetwork(); } String sURL_RPC = ContentNetworkUtils.getUrl(cn, ContentNetwork.SERVICE_RPC) + "?" + urlStem.toString(); // Build full url and data to send String sURL; String sPostData = null; String sJSONPayload = UrlUtils.encode(JSONUtils.encodeToJSON(mapPayload)); if (USE_HTTP_POST) { sURL = sURL_RPC; sPostData = URL_POST_PLATFORM_DATA + "&payload=" + sJSONPayload; sPostData = cn.appendURLSuffix(sPostData, true, sendAZID); if (DEBUG_URL) { debug("POST for " + mapProcessing.size() + ": " + sURL + "\n DATA: " + sPostData); } else { debug("POST for " + mapProcessing.size() + ": " + sURL); } } else { sURL = sURL_RPC + URL_PLATFORM_MESSAGE + "&payload=" + sJSONPayload; sURL = cn.appendURLSuffix(sURL, false, sendAZID); if (DEBUG_URL) { debug("GET: " + sURL); } else { debug("GET: " + sURL_RPC + URL_PLATFORM_MESSAGE); } } final String fURL = sURL; final String fPostData = sPostData; // one at a time to take advantage of keep-alive connections dispatcher.dispatch( new AERunnable() { public void runSupport() { try { processQueueAsync(fURL, fPostData, mapProcessing); } catch (Throwable e) { if (e instanceof ResourceDownloaderException) { debug("Error while sending message(s) to Platform: " + e.toString()); } else { debug("Error while sending message(s) to Platform", e); } for (Iterator iter = mapProcessing.keySet().iterator(); iter.hasNext();) { PlatformMessage message = (PlatformMessage) iter.next(); PlatformMessengerListener l = (PlatformMessengerListener) mapProcessing.get(message); if (l != null) { try { HashMap map = new HashMap(); map.put("text", e.toString()); map.put("Throwable", e); l.replyReceived(message, REPLY_EXCEPTION, map); } catch (Throwable e2) { debug("Error while sending replyReceived", e2); } } } } } }); } /** * @param mapProcessing * @param surl * @throws Exception */ protected static void processQueueAsync(String sURL, String sData, Map mapProcessing) throws Exception { URL url; url = new URL(sURL); String s; byte[] bytes = downloadURL(url, sData); s = new String(bytes, "UTF8"); Map mapAllReplies = JSONUtils.decodeJSON(s); List listReplies = MapUtils.getMapList(mapAllReplies, "replies", null); if (mapAllReplies == null || listReplies == null || listReplies.isEmpty()) { debug("Error while sending message(s) to Platform: reply: " + s + "\nurl: " + sURL + "\nPostData: " + sData); for (Iterator iter = mapProcessing.keySet().iterator(); iter.hasNext();) { PlatformMessage message = (PlatformMessage) iter.next(); PlatformMessengerListener l = (PlatformMessengerListener) mapProcessing.get(message); if (l != null) { try { HashMap map = new HashMap(); map.put("text", "result was " + s); l.replyReceived(message, REPLY_EXCEPTION, map); } catch (Throwable e2) { debug("Error while sending replyReceived" + "\nurl: " + sURL + "\nPostData: " + sData, e2); } } } return; } Map mapOrder = new HashMap(); for (Object reply : listReplies) { if (reply instanceof Map) { mapOrder.put(MapUtils.getMapLong((Map) reply, "seq-id", -1), (Map) reply); } } for (Iterator iter = mapProcessing.keySet().iterator(); iter.hasNext();) { PlatformMessage message = (PlatformMessage) iter.next(); PlatformMessengerListener l = (PlatformMessengerListener) mapProcessing.get(message); if (l == null) { continue; } Map mapReply = mapOrder.get(new Long(message.getSequenceNo())); if (mapReply == null) { debug("No reply for " + message.toShortString()); } String replyType = MapUtils.getMapString(mapReply, "type", "payload"); Map payload; if (replyType.equalsIgnoreCase("payload")) { payload = MapUtils.getMapMap(mapReply, "payload", Collections.EMPTY_MAP); } else { payload = new HashMap(); payload.put("message", MapUtils.getMapString(mapReply, "message", "?")); } if (mapReply != null) { String reply = JSONUtils.encodeToJSON(payload); debug("Got a reply for " + message.toShortString() + "\n\t" + reply.substring(0, Math.min(8192, reply.length()))); } try { l.replyReceived(message, replyType, payload); } catch (Exception e2) { debug("Error while sending replyReceived", e2); } } } private static byte[] downloadURL(URL url, String postData) throws Exception { ResourceDownloaderFactory rdf = StaticUtilities.getResourceDownloaderFactory(); ResourceDownloader rd = rdf.create(url, postData); rd.setProperty( "URL_Connection", "Keep-Alive" ); rd = rdf.getRetryDownloader(rd, 3); // We could report percentage to listeners, but there's no need to atm // rd.addListener(new ResourceDownloaderListener() { // // public void reportPercentComplete(ResourceDownloader downloader, // int percentage) { // } // // public void reportActivity(ResourceDownloader downloader, String activity) { // } // // public void failed(ResourceDownloader downloader, // ResourceDownloaderException e) { // } // // public boolean completed(ResourceDownloader downloader, InputStream data) { // return true; // } // }); InputStream is = rd.download(); byte data[]; try { int length = is.available(); data = new byte[length]; is.read(data); } finally { is.close(); } return (data); } public static void setAllowMulti(boolean allowMulti) { PlatformMessenger.allowMulti = allowMulti; } public static boolean getAllowMulti() { return allowMulti; } private static class fakeContext extends ClientMessageContextImpl { private long contentNetworkID = ConstantsVuze.DEFAULT_CONTENT_NETWORK_ID; private void log(String str) { if (System.getProperty("browser.route.all.external.stimuli.for.testing", "false").equalsIgnoreCase("true")) { System.err.println(str); } debug(str); } public fakeContext() { super("fakeContext", null); } public void deregisterBrowser() { log("deregisterBrowser"); } public void displayBrowserMessage(String message) { log("displayBrowserMessage - " + message); } public boolean executeInBrowser(String javascript) { log("executeInBrowser - " + javascript); return false; } public Object getBrowserData(String key) { log("getBrowserData - " + key); return null; } public boolean sendBrowserMessage(String key, String op) { log("sendBrowserMessage - " + key + "/" + op); return false; } public boolean sendBrowserMessage(String key, String op, Map params) { log("sendBrowserMessage - " + key + "/" + op + "/" + params); return false; } public void setBrowserData(String key, Object value) { log("setBrowserData - " + key + "/" + value); } public boolean sendBrowserMessage(String key, String op, Collection params) { log("sendBrowserMessage - " + key + "/" + op + "/" + params); return false; } public void setTorrentURLHandler(torrentURLHandler handler) { log("setTorrentURLHandler - " + handler); } public long getContentNetworkID() { return contentNetworkID; } public void setContentNetworkID(long contentNetwork) { this.contentNetworkID = contentNetwork; } } } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/PlatformAuthorizedSender.java0000644000175000017500000000240311133772112027310 0ustar adrianadrian/** * Created on Apr 23, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.messenger; import java.net.URL; import org.gudy.azureus2.core3.util.AESemaphore; /** * @author TuxPaper * @created Apr 23, 2008 * */ public interface PlatformAuthorizedSender { /** * @param url * @param data * @param sem_waitDL * @param loginAndRetry * @return * * @since 3.0.5.3 */ void startDownload(URL url, String data, AESemaphore sem_waitDL, boolean loginAndRetry); String getResults(); /** * * * @since 4.0.0.5 */ void clearResults(); } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/ClientMessageContext.java0000644000175000017500000000633711267001364026430 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.messenger; import java.util.Collection; import java.util.Map; import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher; import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener; /** * @author TuxPaper * @created Oct 9, 2006 * */ public interface ClientMessageContext { public abstract void addMessageListener(BrowserMessageListener listener); public abstract void removeMessageListener(String listenerId); public abstract void removeMessageListener(BrowserMessageListener listener); public abstract Object getBrowserData(String key); public abstract void setBrowserData(String key, Object value); /** * Sends a message to the JavaScript message dispatcher in the page. * * @param key identifies the listener to receive the message * @param op identifies the operation to perform */ public abstract boolean sendBrowserMessage(String key, String op); /** * Sends a message to the JavaScript message dispatcher in the page. * * @param key identifies the listener to receive the message * @param op identifies the operation to perform * @param params optional message parameters */ public abstract boolean sendBrowserMessage(String key, String op, Map params); public abstract boolean executeInBrowser(final String javascript); /** * Displays a debug message tagged with the context ID. * * @param message sent to the debug log */ public abstract void debug(String message); /** * Displays a debug message and exception tagged with the context ID. * * @param message sent to the debug log * @param t exception to log with message */ public abstract void debug(String message, Throwable t); public BrowserMessageDispatcher getDispatcher(); /** * @param key * @param op * @param params * @return * * @since 3.0.1.5 */ boolean sendBrowserMessage(String key, String op, Collection params); /** * @param dispatcher * * @since 3.0.5.3 */ void setMessageDispatcher(BrowserMessageDispatcher dispatcher); void setTorrentURLHandler( torrentURLHandler handler ); public interface torrentURLHandler { public void handleTorrentURL( String url ); } /** * @param contentNetwork * * @since 4.0.0.5 */ void setContentNetworkID(long id); /** * @return * * @since 4.0.0.5 */ long getContentNetworkID(); }azureus-4.3.0.6/com/aelitis/azureus/core/messenger/PlatformMessage.java0000644000175000017500000001155111266266270025433 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.messenger; import java.util.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.util.JSONUtils; /** * @author TuxPaper * @created Sep 25, 2006 * */ public class PlatformMessage { private final String messageID; private final String listenerID; private final String operationID; private final Map parameters; private final long fireBeforeDate; private final long messageCreatedOn; private long lSequenceNo = -1; private boolean requiresAuthorization = false; private boolean loginAndRetry = false; private boolean sendAZID = true; private long contentNetworkID; /** * @param messageID * @param listenerID * @param operationID * @param parameters * @param maxDelay */ public PlatformMessage(String messageID, String listenerID, String operationID, Map parameters, long maxDelayMS) { this.messageID = messageID; this.listenerID = listenerID; this.operationID = operationID; this.parameters = JSONUtils.encodeToJSONObject(parameters); this.contentNetworkID = ContentNetwork.CONTENT_NETWORK_VUZE; messageCreatedOn = SystemTime.getCurrentTime(); fireBeforeDate = messageCreatedOn + maxDelayMS; } public PlatformMessage(String messageID, String listenerID, String operationID, Object[] parameters, long maxDelayMS) { this.messageID = messageID; this.listenerID = listenerID; this.operationID = operationID; this.parameters = JSONUtils.encodeToJSONObject(parseParams(parameters)); this.contentNetworkID = ContentNetwork.CONTENT_NETWORK_VUZE; messageCreatedOn = SystemTime.getCurrentTime(); fireBeforeDate = messageCreatedOn + maxDelayMS; } public static Map parseParams(Object[] parameters) { Map result = new HashMap(); for (int i = 0; i < parameters.length - 1; i += 2) { try { if (parameters[i] instanceof String) { if (parameters[i + 1] instanceof String[]) { List list = Arrays.asList((String[]) parameters[i + 1]); result.put((String) parameters[i], list); } else if (parameters[i + 1] instanceof Object[]) { result.put((String) parameters[i], parseParams((Object[]) parameters[i + 1])); } else if (parameters[i + 1] instanceof Map) { result.put((String) parameters[i], (Map) parameters[i + 1]); } else { result.put((String) parameters[i], parameters[i + 1]); } } } catch (Exception e) { Debug.out("making JSONObject out of parsedParams", e); } } return result; } public long getFireBefore() { return fireBeforeDate; } public long getMessageCreated() { return messageCreatedOn; } public Map getParameters() { return parameters; } public String getListenerID() { return listenerID; } public String getMessageID() { return messageID; } public String getOperationID() { return operationID; } protected long getSequenceNo() { return lSequenceNo; } protected void setSequenceNo(long sequenceNo) { lSequenceNo = sequenceNo; } public String toString() { String paramString = parameters.toString(); return "PlaformMessage {" + "cn" + contentNetworkID + ", " + lSequenceNo + ", " + messageID + ", " + listenerID + ", " + operationID + ", " + (paramString.length() > 32767 ? paramString.substring(0, 32767) : paramString) + "}"; } public String toShortString() { return (requiresAuthorization ? "AUTH: " : "") + getMessageID() + "." + getListenerID() + "." + getOperationID(); } /** * @return * * @since 3.1.1.1 */ public boolean sendAZID() { return sendAZID; } public void setSendAZID(boolean send) { sendAZID = send; if (send && requiresAuthorization) { System.err.println("requiresAuthorization overrides sendAZID disabling"); } } public long getContentNetworkID() { return contentNetworkID; } public void setContentNetworkID(long contentNetworkID) { this.contentNetworkID = contentNetworkID; } } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/browser/0000755000175000017500000000000011310377626023155 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/messenger/browser/BrowserMessageDispatcher.java0000644000175000017500000000431311305664420030753 0ustar adrianadrian/** * Created on Jun 2, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.messenger.browser; import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener; /** * @author TuxPaper * @created Jun 2, 2008 * */ public interface BrowserMessageDispatcher { /** * Registers the given listener for the given ID. * * @param id unique identifier used when dispatching messages * @param listener receives messages targetted at the given ID * * @throws IllegalStateException * if another listener is already registered under the same ID */ public abstract void addListener(BrowserMessageListener listener); /** * Dispatches the given message to the appropriate listener. * * @param message holds the listener ID, operation ID and parameters * * @throws IllegalArgumentException * if no listener is registered with the given ID */ public abstract void dispatch(final BrowserMessage message); /** * Returns the listener with the given ID. * * @param id unique identifier of the listener to be returned * @return the located listener */ public abstract BrowserMessageListener getListener(String id); /** * Deregisters the listener with the given ID. * * @param id unique identifier of the listener to be removed */ void removeListener(BrowserMessageListener listener); /** * Deregisters the listener with the given ID. * * @param id unique identifier of the listener to be removed */ void removeListener(String id); }azureus-4.3.0.6/com/aelitis/azureus/core/messenger/browser/listeners/0000755000175000017500000000000011310377626025165 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/messenger/browser/listeners/BrowserMessageListener.java0000644000175000017500000000417111034521066032461 0ustar adrianadrian/* * Created on Jun 29, 2006 10:16:26 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.messenger.browser.listeners; import com.aelitis.azureus.core.messenger.ClientMessageContext; import com.aelitis.azureus.core.messenger.browser.BrowserMessage; import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher; /** * Accepts and handles messages dispatched from {@link BrowserMessageDispatcher}. * Subclasses should use the message's operation ID and parameters to perform * the requested operation. * * @author dharkness * @created Jul 18, 2006 */ public interface BrowserMessageListener { /** * Returns the context for this listener. * * @return listener's context */ public ClientMessageContext getContext(); /** * Returns the unique ID for this listener. * * @return listener's unique ID */ public String getId(); /** * Handles the given message, usually by parsing the parameters * and calling the appropriate operation. * * @param message holds all message information */ public void handleMessage(BrowserMessage message); /** * Sets the context for this listener. Called by its dispatcher when attached. * * @param context the new context for this listener */ public void setContext(ClientMessageContext context); } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/messenger/browser/listeners/AbstractBrowserMessageListener.javaazureus-4.3.0.6/com/aelitis/azureus/core/messenger/browser/listeners/AbstractBrowserMessageListener.0000644000175000017500000000601011034521066033275 0ustar adrianadrian/* * Created on Jun 29, 2006 10:16:26 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.messenger.browser.listeners; import com.aelitis.azureus.core.messenger.ClientMessageContext; import com.aelitis.azureus.core.messenger.browser.BrowserMessage; import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher; /** * Accepts and handles messages dispatched from {@link BrowserMessageDispatcher}. * Subclasses should use the message's operation ID and parameters to perform * the requested operation. * * @author dharkness * @created Jul 18, 2006 */ public abstract class AbstractBrowserMessageListener implements BrowserMessageListener { protected ClientMessageContext context = null; private String id; /** * Stores the given context for accessing the browser and its services. * * @param context used to access the browser */ public AbstractBrowserMessageListener(String id) { this.id = id; } /** * Displays a debug message tagged with the listener ID. * * @param message sent to the debug log */ protected void debug(String message) { context.debug("[" + id + "] " + message); } /** * Displays a debug message and exception tagged with the listener ID. * * @param message sent to the debug log * @param t exception to log with message */ public void debug(String message, Throwable t) { context.debug("[" + id + "] " + message, t); } /** * Returns the context for this listener. * * @return listener's context */ public ClientMessageContext getContext() { return context; } /** * Returns the unique ID for this listener. * * @return listener's unique ID */ public String getId() { return id; } /** * Handles the given message, usually by parsing the parameters * and calling the appropriate operation. * * @param message holds all message information */ public abstract void handleMessage(BrowserMessage message); /** * Sets the context for this listener. Called by its dispatcher when attached. * * @param context the new context for this listener */ public void setContext(ClientMessageContext context) { if (this.context == null) { this.context = context; } } } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/browser/listeners/MessageCompletionListener.java0000644000175000017500000000213111021114522033130 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.messenger.browser.listeners; /** * @author TuxPaper * @created Oct 10, 2006 * */ public interface MessageCompletionListener { public void completed(boolean success, Object data); } azureus-4.3.0.6/com/aelitis/azureus/core/messenger/browser/BrowserMessage.java0000644000175000017500000001172111305664420026745 0ustar adrianadrian/* * Created on Jun 29, 2006 10:16:26 PM * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.messenger.browser; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.*; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEDiagnosticsLogger; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener; import com.aelitis.azureus.core.messenger.browser.listeners.MessageCompletionListener; import com.aelitis.azureus.util.ConstantsVuze; /** * Holds a message being dispatched to a {@link BrowserMessageListener}. * * @author dharkness * @created Jul 18, 2006 */ public class BrowserMessage { /** All messages must start with this prefix. */ public static final String MESSAGE_PREFIX = "AZMSG"; /** Separates prefix and listener ID from rest of message. */ public static final String MESSAGE_DELIM = ";"; public static String MESSAGE_DELIM_ENCODED; /** There were no parameters passed with the message. */ public static final int NO_PARAM = 0; /** Parameters were an encoded JSONObject. */ public static final int OBJECT_PARAM = 1; /** Parameters were an encoded JSONArray. */ public static final int ARRAY_PARAM = 2; static { try { MESSAGE_DELIM_ENCODED = URLEncoder.encode(";", "UTF-8"); } catch (UnsupportedEncodingException e) { MESSAGE_DELIM_ENCODED = MESSAGE_DELIM; } } private String listenerId; private String operationId; private String params; private Map decodedParams; private ArrayList completionListeners = new ArrayList(); private boolean completed; private boolean completeDelayed; private String referer; public BrowserMessage(String listenerId, String operationId, Map params) { this.listenerId = listenerId; this.operationId = operationId; decodedParams = params; } public void addCompletionListener(MessageCompletionListener l) { completionListeners.add(l); } /** * Sets the message complete and fires of the listeners who are waiting * for a response. * * @param bOnlyNonDelayed Only mark complete if this message does not have a delayed reponse * @param success Success level of the message * @param data Any data the message results wants to send */ public void complete(boolean bOnlyNonDelayed, boolean success, Object data) { //System.out.println("complete called with " + bOnlyNonDelayed); if (completed || (bOnlyNonDelayed && completeDelayed)) { //System.out.println("exit early" + completed); return; } triggerCompletionListeners(success, data); completed = true; } public void debug(String message) { debug(message, null); } public void debug(String message, Throwable t) { try { AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("v3.CMsgr"); String out = "[" + getListenerId() + ":" + getOperationId() + "] " + message; diag_logger.log(out); if (t != null) { diag_logger.log(t); } if (ConstantsVuze.DIAG_TO_STDOUT) { System.out.println(out); if (t != null) { t.printStackTrace(); } } } catch (Throwable t2) { Debug.out(t2); } } public Map getDecodedMap() { return decodedParams == null ? Collections.EMPTY_MAP : decodedParams; } public String getListenerId() { return listenerId; } public String getOperationId() { return operationId; } public String getReferer() { return referer; } public void removeCompletionListener(MessageCompletionListener l) { completionListeners.remove(l); } public void setCompleteDelayed(boolean bCompleteDelayed) { completeDelayed = bCompleteDelayed; } public void setReferer(String referer) { this.referer = referer; } public String toString() { return listenerId + "." + operationId + "(" + (params == null ? decodedParams : params) + ")"; } private void triggerCompletionListeners(boolean success, Object data) { for (Iterator iterator = completionListeners.iterator(); iterator.hasNext();) { MessageCompletionListener l = (MessageCompletionListener) iterator.next(); try { l.completed(success, data); } catch (Throwable e) { Debug.out(e); } } } } azureus-4.3.0.6/com/aelitis/azureus/core/impl/0000755000175000017500000000000011310377624020441 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/impl/AzureusCoreSingleInstanceClient.java0000644000175000017500000000710210501505006027525 0ustar adrianadrian/* * Created on 11-Sep-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.impl; import java.net.*; import java.io.*; /** * Single instance management is a bit of a mess. For some reason the UIs have their own implementations of clients and servers. * We also have a more generic plugin-accessible single instance service that can be used by launchable plugins but don't give * a generic mechanism for dealing with the basic mechanism used by the UIs (that run on 6880). * I have introduced this class to give a programmatic way of passing arguments using the existing 6880 port. Perhaps one day * the various UI implementations will be rewritten to use this... * @author Parg */ public class AzureusCoreSingleInstanceClient { public static final String ACCESS_STRING = "Azureus Start Server Access"; private static final int CONNECT_TIMEOUT = 500; private static final int READ_TIMEOUT = 5000; public boolean sendArgs( String[] args, int max_millis_to_wait ) { // limit the subset here as we're looping waiting for something to be alive and we can't afford to take ages getting back to the start long start = System.currentTimeMillis(); while( true ){ long connect_start = System.currentTimeMillis(); if ( connect_start < start ){ start = connect_start; } if ( connect_start - start > max_millis_to_wait ){ return( false ); } Socket sock = null; try{ sock = new Socket(); sock.connect( new InetSocketAddress( "127.0.0.1", 6880 ), CONNECT_TIMEOUT ); sock.setSoTimeout( READ_TIMEOUT ); PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream(),"UTF-8")); StringBuffer buffer = new StringBuffer( ACCESS_STRING + ";args;"); for ( int i = 0 ; i < args.length ; i++ ){ String arg = args[i].replaceAll("&","&&").replaceAll(";","&;"); buffer.append(arg); buffer.append(';'); } pw.println(buffer.toString()); pw.flush(); return( true ); }catch( Throwable e ){ long connect_end = System.currentTimeMillis(); long time_taken = connect_end - connect_start; if ( time_taken < CONNECT_TIMEOUT ){ try{ Thread.sleep( CONNECT_TIMEOUT - time_taken ); }catch( Throwable f ){ } } }finally{ try{ if ( sock != null ){ sock.close(); } }catch( Throwable e ){ } } } } public static void main( String[] args ) { new AzureusCoreSingleInstanceClient().sendArgs( new String[]{ "6C0B39D9897AF42F624AC2DE010CF33F55CB45EC" }, 30000 ); } } azureus-4.3.0.6/com/aelitis/azureus/core/impl/AzureusCoreImpl.java0000644000175000017500000012533211306360242024374 0ustar adrianadrian/* * Created on 13-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.impl; import java.net.InetAddress; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerAdapter; import org.gudy.azureus2.core3.global.GlobalManagerFactory; import org.gudy.azureus2.core3.global.GlobalManagerStats; import org.gudy.azureus2.core3.global.GlobalMangerProgressListener; import org.gudy.azureus2.core3.internat.*; import org.gudy.azureus2.core3.ipfilter.IpFilterManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.ipfilter.*; import org.gudy.azureus2.core3.peer.PEPeerSource; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.platform.PlatformManagerListener; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl; import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; import com.aelitis.azureus.core.*; import com.aelitis.azureus.core.custom.CustomizationManagerFactory; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.instancemanager.AZInstanceManager; import com.aelitis.azureus.core.instancemanager.AZInstanceManagerAdapter; import com.aelitis.azureus.core.instancemanager.AZInstanceManagerFactory; import com.aelitis.azureus.core.instancemanager.AZInstanceTracked; import com.aelitis.azureus.core.nat.NATTraverser; import com.aelitis.azureus.core.networkmanager.NetworkManager; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminNetworkInterface; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminNetworkInterfaceAddress; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminPropertyChangeListener; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager; import com.aelitis.azureus.core.networkmanager.impl.udp.UDPNetworkManager; import com.aelitis.azureus.core.pairing.PairingManagerFactory; import com.aelitis.azureus.core.peermanager.PeerManager; import com.aelitis.azureus.core.peermanager.nat.PeerNATTraverser; import com.aelitis.azureus.plugins.clientid.ClientIDPlugin; import com.aelitis.azureus.core.security.CryptoManager; import com.aelitis.azureus.core.security.CryptoManagerFactory; import com.aelitis.azureus.core.speedmanager.SpeedManager; import com.aelitis.azureus.core.speedmanager.SpeedManagerAdapter; import com.aelitis.azureus.core.speedmanager.SpeedManagerFactory; import com.aelitis.azureus.core.update.AzureusRestarterFactory; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; import com.aelitis.azureus.launcher.classloading.PrimaryClassloader; import com.aelitis.azureus.plugins.dht.DHTPlugin; import com.aelitis.azureus.plugins.tracker.dht.DHTTrackerPlugin; import com.aelitis.azureus.plugins.upnp.UPnPPlugin; /** * @author parg * */ public class AzureusCoreImpl implements AzureusCore { private final static LogIDs LOGID = LogIDs.CORE; protected static AzureusCore singleton; protected static AEMonitor class_mon = new AEMonitor( "AzureusCore:class" ); private static final String DM_ANNOUNCE_KEY = "AzureusCore:announce_key"; private static final boolean LOAD_PLUGINS_IN_OTHER_THREAD = true; /** * Listeners that will be fired after core has completed initialization */ static List coreRunningListeners = new ArrayList(1); static AEMonitor mon_coreRunningListeners = new AEMonitor("CoreCreationListeners"); public static AzureusCore create() throws AzureusCoreException { try{ class_mon.enter(); if ( singleton != null ){ throw( new AzureusCoreException( "Azureus core already instantiated" )); } singleton = new AzureusCoreImpl(); return( singleton ); }finally{ class_mon.exit(); } } public static boolean isCoreAvailable() { return( singleton != null ); } public static boolean isCoreRunning() { return( singleton != null && singleton.isStarted() ); } public static AzureusCore getSingleton() throws AzureusCoreException { if ( singleton == null ){ throw( new AzureusCoreException( "core not instantiated")); } return( singleton ); } private PluginInitializer pi; private GlobalManager global_manager; private AZInstanceManager instance_manager; private SpeedManager speed_manager; private CryptoManager crypto_manager; private NATTraverser nat_traverser; private long create_time = SystemTime.getCurrentTime(); private volatile boolean started; private volatile boolean stopped; private volatile boolean restarting; private CopyOnWriteList listeners = new CopyOnWriteList(); private CopyOnWriteList lifecycle_listeners = new CopyOnWriteList(); private List operation_listeners = new ArrayList(); private AESemaphore stopping_sem = new AESemaphore( "AzureusCore::stopping" ); private AEMonitor this_mon = new AEMonitor( "AzureusCore" ); private AzureusCoreOperation initialisation_op = createOperation( AzureusCoreOperation.OP_INITIALISATION ); public static boolean SUPPRESS_CLASSLOADER_ERRORS = false; protected AzureusCoreImpl() { if(!SUPPRESS_CLASSLOADER_ERRORS && !(this.getClass().getClassLoader() instanceof PrimaryClassloader)) System.out.println("###\nWarning: Core not instantiated through a PrimaryClassloader, this can lead to restricted functionality or bugs in future versions\n###"); COConfigurationManager.initialise(); MessageText.loadBundle(); AEDiagnostics.startup( COConfigurationManager.getBooleanParameter( "diags.enable.pending.writes", false )); COConfigurationManager.setParameter( "diags.enable.pending.writes", false ); AEDiagnostics.markDirty(); AETemporaryFileHandler.startup(); AEThread2.setOurThread(); // set up a backwards pointer from config -> app dir so we can derive one from the other. It'll get saved on closedown, no need to do so now COConfigurationManager.setParameter( "azureus.application.directory", SystemProperties.getApplicationPath()); crypto_manager = CryptoManagerFactory.getSingleton(); PlatformManagerFactory.getPlatformManager().addListener( new PlatformManagerListener() { public void eventOccurred( int type ) { if ( type == ET_SHUTDOWN ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Platform manager requested shutdown")); } stop(); }else if ( type == ET_SUSPEND ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Platform manager requested suspend")); } COConfigurationManager.save(); }else if ( type == ET_RESUME ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Platform manager requested resume")); } announceAll( true ); } } }); //ensure early initialization CustomizationManagerFactory.getSingleton(); NetworkManager.getSingleton(); PeerManager.getSingleton(); // Used to be a plugin, but not any more... ClientIDPlugin.initialize(); pi = PluginInitializer.getSingleton( this, initialisation_op ); instance_manager = AZInstanceManagerFactory.getSingleton( new AZInstanceManagerAdapter() { public String getID() { return( COConfigurationManager.getStringParameter( "ID", "" )); } public InetAddress getPublicAddress() { return( PluginInitializer.getDefaultInterface().getUtilities().getPublicAddress()); } public int[] getPorts() { return( new int[]{ TCPNetworkManager.getSingleton().getTCPListeningPortNumber(), UDPNetworkManager.getSingleton().getUDPListeningPortNumber(), UDPNetworkManager.getSingleton().getUDPNonDataListeningPortNumber()}); } public VCPublicAddress getVCPublicAddress() { return( new VCPublicAddress() { private VersionCheckClient vcc = VersionCheckClient.getSingleton(); public String getAddress() { return( vcc.getExternalIpAddress( true, false )); } public long getCacheTime() { return( vcc.getSingleton().getCacheTime( false )); } }); } public AZInstanceTracked.TrackTarget track( byte[] hash ) { List dms = getGlobalManager().getDownloadManagers(); Iterator it = dms.iterator(); DownloadManager matching_dm = null; try{ while( it.hasNext()){ DownloadManager dm = (DownloadManager)it.next(); TOTorrent torrent = dm.getTorrent(); if ( torrent == null ){ continue; } byte[] sha1_hash = (byte[])dm.getData( "AZInstanceManager::sha1_hash" ); if ( sha1_hash == null ){ sha1_hash = new SHA1Simple().calculateHash( torrent.getHash()); dm.setData( "AZInstanceManager::sha1_hash", sha1_hash ); } if ( Arrays.equals( hash, sha1_hash )){ matching_dm = dm; break; } } }catch( Throwable e ){ Debug.printStackTrace(e); } if ( matching_dm == null ){ return( null ); } if ( !matching_dm.getDownloadState().isPeerSourceEnabled( PEPeerSource.PS_PLUGIN )){ return( null ); } int dm_state = matching_dm.getState(); if ( dm_state == DownloadManager.STATE_ERROR || dm_state == DownloadManager.STATE_STOPPED ){ return( null ); } try{ final Object target = DownloadManagerImpl.getDownloadStatic( matching_dm ); final boolean is_seed = matching_dm.isDownloadComplete(true); return( new AZInstanceTracked.TrackTarget() { public Object getTarget() { return( target ); } public boolean isSeed() { return( is_seed ); } }); }catch( Throwable e ){ return( null ); } } public DHTPlugin getDHTPlugin() { PluginInterface pi = getPluginManager().getPluginInterfaceByClass( DHTPlugin.class ); if ( pi != null ){ return( (DHTPlugin)pi.getPlugin()); } return( null ); } public UPnPPlugin getUPnPPlugin() { PluginInterface pi = getPluginManager().getPluginInterfaceByClass( UPnPPlugin.class ); if ( pi != null ){ return((UPnPPlugin)pi.getPlugin()); } return( null ); } public void addListener( final StateListener listener) { AzureusCoreImpl.this.addLifecycleListener( new AzureusCoreLifecycleAdapter() { public void started( AzureusCore core) { listener.started(); } public void stopping( AzureusCore core ) { listener.stopped(); } }); } }); speed_manager = SpeedManagerFactory.createSpeedManager( this, new SpeedManagerAdapter() { private final int UPLOAD_SPEED_ADJUST_MIN_KB_SEC = 10; private final int DOWNLOAD_SPEED_ADJUST_MIN_KB_SEC = 300; private boolean setting_limits; public int getCurrentProtocolUploadSpeed( int average_period ) { if ( global_manager != null ){ GlobalManagerStats stats = global_manager.getStats(); return( stats.getProtocolSendRateNoLAN( average_period )); }else{ return(0); } } public int getCurrentDataUploadSpeed( int average_period ) { if ( global_manager != null ){ GlobalManagerStats stats = global_manager.getStats(); return( stats.getDataSendRateNoLAN( average_period )); }else{ return(0); } } public int getCurrentProtocolDownloadSpeed( int average_period ) { if( global_manager != null ){ GlobalManagerStats stats = global_manager.getStats(); return (stats.getProtocolReceiveRateNoLAN( average_period ) ); }else{ return(0); } } public int getCurrentDataDownloadSpeed( int average_period ) { if( global_manager != null ){ GlobalManagerStats stats = global_manager.getStats(); return (stats.getDataReceiveRateNoLAN( average_period ) ); }else{ return(0); } } public int getCurrentUploadLimit() { String key = TransferSpeedValidator.getActiveUploadParameter( global_manager ); int k_per_second = COConfigurationManager.getIntParameter( key ); int bytes_per_second; if ( k_per_second == 0 ){ bytes_per_second = Integer.MAX_VALUE; }else{ bytes_per_second = k_per_second*1024; } return( bytes_per_second ); } public void setCurrentUploadLimit( int bytes_per_second ) { if ( bytes_per_second != getCurrentUploadLimit()){ String key = TransferSpeedValidator.getActiveUploadParameter( global_manager ); int k_per_second; if ( bytes_per_second == Integer.MAX_VALUE ){ k_per_second = 0; }else{ k_per_second = (bytes_per_second+1023)/1024; } if ( k_per_second > 0 ){ k_per_second = Math.max( k_per_second, UPLOAD_SPEED_ADJUST_MIN_KB_SEC ); } COConfigurationManager.setParameter( key, k_per_second ); } } public int getCurrentDownloadLimit() { return( TransferSpeedValidator.getGlobalDownloadRateLimitBytesPerSecond()); } public void setCurrentDownloadLimit( int bytes_per_second ) { if ( bytes_per_second == Integer.MAX_VALUE ){ bytes_per_second = 0; } if ( bytes_per_second > 0 ){ bytes_per_second = Math.max( bytes_per_second, DOWNLOAD_SPEED_ADJUST_MIN_KB_SEC*1024 ); } TransferSpeedValidator.setGlobalDownloadRateLimitBytesPerSecond( bytes_per_second ); } public Object getLimits() { String up_key = TransferSpeedValidator.getActiveUploadParameter( global_manager ); String down_key = TransferSpeedValidator.getDownloadParameter(); return( new Object[]{ up_key, new Integer( COConfigurationManager.getIntParameter( up_key )), down_key, new Integer( COConfigurationManager.getIntParameter( down_key )), }); } public void setLimits( Object limits, boolean do_up, boolean do_down ) { if ( limits == null ){ return; } try{ if ( setting_limits ){ return; } setting_limits = true; Object[] bits = (Object[])limits; if ( do_up ){ COConfigurationManager.setParameter((String)bits[0], ((Integer)bits[1]).intValue()); } if ( do_down ){ COConfigurationManager.setParameter((String)bits[2], ((Integer)bits[3]).intValue()); } }finally{ setting_limits = false; } } }); nat_traverser = new NATTraverser( this ); PeerNATTraverser.initialise( this ); // one off explicit GC to clear up initialisation mem SimpleTimer.addEvent( "AzureusCore:gc", SystemTime.getOffsetTime(60*1000), new TimerEventPerformer() { public void perform( TimerEvent event) { System.gc(); } }); } protected void announceAll( boolean force ) { Logger.log( new LogEvent(LOGID, "Updating trackers" )); GlobalManager gm = getGlobalManager(); if ( gm != null ){ List downloads = gm.getDownloadManagers(); long now = SystemTime.getCurrentTime(); for (int i=0;i 15*60*1000 || last_announce_response == null || last_announce_response.getStatus() == TRTrackerAnnouncerResponse.ST_OFFLINE || force ){ dm.setUserData( DM_ANNOUNCE_KEY, new Long( now )); Logger.log( new LogEvent(LOGID, " updating tracker for " + dm.getDisplayName())); dm.requestTrackerAnnounce( true ); } } } } PluginInterface dht_tracker_pi = getPluginManager().getPluginInterfaceByClass( DHTTrackerPlugin.class ); if ( dht_tracker_pi != null ){ ((DHTTrackerPlugin)dht_tracker_pi.getPlugin()).announceAll(); } } public LocaleUtil getLocaleUtil() { return( LocaleUtil.getSingleton()); } public void start() throws AzureusCoreException { AEThread2.setOurThread(); try{ this_mon.enter(); if ( started ){ throw( new AzureusCoreException( "Core: already started" )); } if ( stopped ){ throw( new AzureusCoreException( "Core: already stopped" )); } started = true; }finally{ this_mon.exit(); } // If a user sets this property, it is an alias for the following settings. if ("1".equals(System.getProperty("azureus.safemode"))) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Safe mode enabled")); Constants.isSafeMode = true; System.setProperty("azureus.loadplugins", "0"); System.setProperty("azureus.disabledownloads", "1"); System.setProperty("azureus.skipSWTcheck", "1"); // Not using localised text - not sure it's safe to this early. Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogEvent.LT_WARNING, "You are running " + Constants.APP_NAME + " in safe mode - you " + "can change your configuration, but any downloads added will " + "not be remembered when you close " + Constants.APP_NAME + "." )); } /** * test to see if UI plays nicely with a really slow initialization */ String sDelayCore = System.getProperty("delay.core", null); if (sDelayCore != null) { try { long delayCore = Long.parseLong(sDelayCore); Thread.sleep(delayCore); } catch (Exception e) { e.printStackTrace(); } } // run plugin loading in parallel to the global manager loading AEThread2 pluginload = new AEThread2("PluginLoader",true) { public void run() { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Loading of Plugins starts")); pi.loadPlugins(AzureusCoreImpl.this, false, !"0".equals(System.getProperty("azureus.loadplugins")), true, true); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Loading of Plugins complete")); } }; if (LOAD_PLUGINS_IN_OTHER_THREAD) { pluginload.start(); } else { pluginload.run(); } // Disable async loading of existing torrents, because there are many things // (like hosting) that require all the torrents to be loaded. While we // can write code for each of these cases to wait until the torrents are // loaded, it's a pretty big job to find them all and fix all their quirks. // Too big of a job for this late in the release stage. // Other example is the tracker plugin that is coded in a way where it must // always publish a complete rss feed global_manager = GlobalManagerFactory.create( this, new GlobalMangerProgressListener() { public void reportCurrentTask( String currentTask ) { initialisation_op.reportCurrentTask( currentTask ); } public void reportPercent( int percent ) { initialisation_op.reportPercent( percent ); } }, 0); if (stopped) { System.err.println("Core stopped while starting"); return; } // wait until plugin loading is done if (LOAD_PLUGINS_IN_OTHER_THREAD) { pluginload.join(); } if (stopped) { System.err.println("Core stopped while starting"); return; } triggerLifeCycleComponentCreated(global_manager); pi.initialisePlugins(); if (stopped) { System.err.println("Core stopped while starting"); return; } if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Initializing Plugins complete")); try{ PluginInterface dht_pi = getPluginManager().getPluginInterfaceByClass( DHTPlugin.class ); if ( dht_pi != null ){ dht_pi.addEventListener( new PluginEventListener() { private boolean first_dht = true; public void handleEvent( PluginEvent ev ) { if ( ev.getType() == DHTPlugin.EVENT_DHT_AVAILABLE ){ if ( first_dht ){ first_dht = false; DHT dht = (DHT)ev.getValue(); speed_manager.setSpeedTester( dht.getSpeedTester()); global_manager.addListener( new GlobalManagerAdapter() { public void seedingStatusChanged( boolean seeding_only_mode, boolean b ) { checkConfig(); } }); COConfigurationManager.addAndFireParameterListeners( new String[]{ TransferSpeedValidator.AUTO_UPLOAD_ENABLED_CONFIGKEY, TransferSpeedValidator.AUTO_UPLOAD_SEEDING_ENABLED_CONFIGKEY }, new ParameterListener() { public void parameterChanged( String parameterName ) { checkConfig(); } }); } } } protected void checkConfig() { speed_manager.setEnabled( TransferSpeedValidator.isAutoSpeedActive(global_manager) ); } }); } }catch( Throwable e ){ } if ( COConfigurationManager.getBooleanParameter( "Resume Downloads On Start" )){ global_manager.resumeDownloads(); } VersionCheckClient.getSingleton().initialise(); instance_manager.initialize(); NetworkManager.getSingleton().initialize(this); Runtime.getRuntime().addShutdownHook( new AEThread("Shutdown Hook") { public void runSupport() { Logger.log(new LogEvent(LOGID, "Shutdown hook triggered" )); AzureusCoreImpl.this.stop(); } }); DelayedTask delayed_task = UtilitiesImpl.addDelayedTask( "Core", new Runnable() { public void run() { new AEThread2( "core:delayTask", true ) { public void run() { AEDiagnostics.checkDumpsAndNatives(); COConfigurationManager.setParameter( "diags.enable.pending.writes", true ); AEDiagnostics.flushPendingLogs(); NetworkAdmin na = NetworkAdmin.getSingleton(); na.runInitialChecks(AzureusCoreImpl.this); na.addPropertyChangeListener( new NetworkAdminPropertyChangeListener() { private String last_as; public void propertyChanged( String property ) { NetworkAdmin na = NetworkAdmin.getSingleton(); if ( property.equals( NetworkAdmin.PR_NETWORK_INTERFACES )){ boolean found_usable = false; NetworkAdminNetworkInterface[] intf = na.getInterfaces(); for (int i=0;i 0 ){ AzureusRestarterFactory.create( this ).restart( true ); } try { Class c = Class.forName( "sun.awt.AWTAutoShutdown" ); if (c != null) { c.getMethod( "notifyToolkitThreadFree", new Class[]{} ).invoke( null, new Object[]{} ); } } catch (Throwable t) { } try{ ThreadGroup tg = Thread.currentThread().getThreadGroup(); Thread[] threads = new Thread[tg.activeCount()+32]; tg.enumerate( threads ); for (int i=0;i 0) { folder = new File(folder_path); if (!folder.isDirectory()) { if (!folder.exists()) { FileUtil.mkdirs(folder); } if (!folder.isDirectory()) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "[Watch Torrent Folder Path] " + "does not exist or " + "is not a dir")); folder = null; } } } if (folder == null) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "[Watch Torrent Folder Path] not configured")); return; } File f = null; if (data_save_path != null && data_save_path.length() > 0) { f = new File(data_save_path); // Path is not an existing directory. if (!f.isDirectory()) { if (!f.exists()) {FileUtil.mkdirs(f);} // If path is still not a directory, abort. if (!f.isDirectory()) { if (Logger.isEnabled()) { Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "[Default save path] does not exist or is not a dir")); } Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "[Default save path] does not exist or is not a dir")); return; } } } // If we get here, and this is true, then data_save_path isn't valid. if (f == null){ if (Logger.isEnabled()) { Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "[Default save path] needs to be set for auto-.torrent-import to work")); } Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "[Default save path] needs to be set for auto-.torrent-import to work")); } // if we are saving torrents to the same location as we import them from // then we can't assume that its safe to delete the torrent after import! if (torrent_save_path.length() == 0 || torrent_save_path.equals(folder_path) || !new File(torrent_save_path).isDirectory()) { save_torrents = false; } //delete torrents from the previous import run for (int i = 0; i < to_delete.size(); i++) { TOTorrent torrent = (TOTorrent) to_delete.get(i); try { TorrentUtils.delete(torrent); } catch (Throwable e) { Debug.printStackTrace(e); } } to_delete.clear(); String[] currentFileList = folder.list(filename_filter); if (currentFileList == null) { Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "There was a problem trying to get a listing of torrents from " + folder)); return; } for (int i = 0; i < currentFileList.length; i++) { File file = new File(folder, currentFileList[i]); // make sure we've got a valid torrent file before proceeding try { TOTorrent torrent = TorrentUtils.readFromFile(file, false); if (global_manager.getDownloadManager(torrent) != null) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, file.getAbsolutePath() + " is already being downloaded")); // we can't touch the torrent file as it is (probably) // being used for the download } else { byte[] hash = null; try { hash = torrent.getHash(); } catch (Exception e) { } if (!save_torrents) { File imported = new File(folder, file.getName() + ".imported"); TorrentUtils.move(file, imported); global_manager.addDownloadManager(imported.getAbsolutePath(), hash, data_save_path, start_state, true); } else { global_manager.addDownloadManager(file.getAbsolutePath(), hash, data_save_path, start_state, true); // add torrent for deletion, since there will be a // saved copy elsewhere to_delete.add(torrent); } if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Auto-imported " + file.getAbsolutePath())); } } catch (Throwable e) { Debug.out("Failed to auto-import torrent file '" + file.getAbsolutePath() + "' - " + Debug.getNestedExceptionMessage(e)); Debug.printStackTrace(e); } } } finally { this_mon.exit(); } } }azureus-4.3.0.6/com/aelitis/azureus/core/AzureusCoreOperationTask.java0000644000175000017500000000207610462211552025315 0ustar adrianadrian/* * Created on 27 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core; public interface AzureusCoreOperationTask { public void run( AzureusCoreOperation operation ); } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/0000755000175000017500000000000011310377630022130 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/SpeedManager.java0000644000175000017500000000405710650037630025333 0ustar adrianadrian/* * Created on 16-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager; import com.aelitis.azureus.core.dht.speed.DHTSpeedTester; public interface SpeedManager { public boolean isAvailable(); public void setEnabled( boolean enabled ); public boolean isEnabled(); public String getASN(); public SpeedManagerLimitEstimate getEstimatedUploadCapacityBytesPerSec(); /** * * @param bytes_per_sec * @param rating see constants above for help */ public void setEstimatedUploadCapacityBytesPerSec( int bytes_per_sec, float estimate_type ); public SpeedManagerLimitEstimate getEstimatedDownloadCapacityBytesPerSec(); public void setEstimatedDownloadCapacityBytesPerSec( int bytes_per_sec, float estimate_type ); public void setSpeedTester( DHTSpeedTester tester ); public DHTSpeedTester getSpeedTester(); public SpeedManagerPingSource[] getPingSources(); public SpeedManagerPingMapper getActiveMapper(); public SpeedManagerPingMapper[] getMappers(); public void reset(); public void addListener( SpeedManagerListener l ); public void removeListener( SpeedManagerListener l ); } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/SpeedManagerPingZone.java0000644000175000017500000000233310643300462026776 0ustar adrianadrian/* * Created on Jul 2, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager; public interface SpeedManagerPingZone { public int getUploadStartBytesPerSec(); public int getUploadEndBytesPerSec(); public int getDownloadStartBytesPerSec(); public int getDownloadEndBytesPerSec(); public int getMetric(); } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/SpeedManagerPingMapper.java0000644000175000017500000000337110645601672027323 0ustar adrianadrian/* * Created on Jul 3, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager; public interface SpeedManagerPingMapper { public String getName(); public int[][] getHistory(); public SpeedManagerPingZone[] getZones(); public SpeedManagerLimitEstimate getEstimatedUploadLimit( boolean persistent ); public SpeedManagerLimitEstimate getEstimatedDownloadLimit( boolean persistent ); /** * +1 : good * -1 : bad * >-1 <+1 : relative goodness/badness * @return */ public double getCurrentMetricRating(); public SpeedManagerLimitEstimate getLastBadUploadLimit(); public SpeedManagerLimitEstimate getLastBadDownloadLimit(); public SpeedManagerLimitEstimate[] getBadUploadHistory(); public SpeedManagerLimitEstimate[] getBadDownloadHistory(); public boolean isActive(); public void destroy(); } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/0000755000175000017500000000000011310377630023071 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/0000755000175000017500000000000011310377630023420 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SaturatedMode.java0000644000175000017500000000762110653605116027034 0ustar adrianadrian/** * Created on May 21, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager.impl.v2; public class SaturatedMode implements Comparable { public static final SaturatedMode AT_LIMIT = new SaturatedMode("AT_LIMIT",0.95f); public static final SaturatedMode HIGH = new SaturatedMode("HIGH",0.75f); public static final SaturatedMode MED = new SaturatedMode("MED",0.25f); public static final SaturatedMode LOW = new SaturatedMode("LOW",0.03f); public static final SaturatedMode NONE = new SaturatedMode("NONE",0.0f); private final String name; private final float percentCapacity; private SaturatedMode(String _name, float _percent) { name = _name; percentCapacity = _percent; } private float getThreshold(){ return percentCapacity; } /** * From the currentRate and limit determine the mode. * @param currentRate - * @param limit - * @return - SaturatedMode */ public static SaturatedMode getSaturatedMode(int currentRate,int limit){ //unlimited mode has this value as zero. if(limit==0){ //put a value in so it will not stay in downloading mode. limit = SMConst.START_DOWNLOAD_RATE_MAX; } float percent = (float)currentRate/(float)limit; if( percent > AT_LIMIT.getThreshold() ){ return AT_LIMIT; } else if( percent > HIGH.getThreshold() ){ return HIGH; } else if( percent > MED.getThreshold() ){ return MED; } else if( percent > LOW.getThreshold() ){ return LOW; } return NONE; } public String toString() { return name; } /** * * @param mode * @return */ public boolean isGreater( SaturatedMode mode ) { if( this.compareTo(mode)>0 ){ return true; } return false; } /** * @param satMode the SaturatedMode to be compared. * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. */ public int compareTo(SaturatedMode satMode) { if( percentCapacity < satMode.getThreshold() ){ return -1; } else if( percentCapacity > satMode.getThreshold() ){ return +1; } return 0; } /** * @param obj the Object to be compared. * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. * @throws ClassCastException if the specified object's type prevents it * from being compared to this Object. */ public int compareTo(Object obj) { if( !(obj instanceof SaturatedMode) ){ throw new ClassCastException("Only comparable to SaturatedMode class."); } SaturatedMode casted = (SaturatedMode) obj; return compareTo(casted); } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControlSetting.java0000644000175000017500000000251110646001200030223 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; /** * Created on Jul 12, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class LimitControlSetting { float value; public LimitControlSetting(float startValue){ value = startValue; } /** * * @return float between 0.0 and 1.0f */ public float getValue(){ return value; } public void adjust(float increment){ value += increment; } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControlPreferDownload.java0000644000175000017500000000537110652317144031546 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; /** * Created on Jul 12, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ /** * Prefer the download, but something like 80,20 */ public class LimitControlPreferDownload implements LimitControl { LimitControlSetting setting; float upMidPoint = 0.2f; float downMidPoint = 0.8f; int upMax; int upMin; int downMax; int downMin; TransferMode mode; float percentUpMaxUsed=0.6f; boolean isDownloadUnlimited=false; public SMUpdate adjust(float amount) { setting.adjust( amount ); int upMaxUsed = upMax; if( mode.getMode() == TransferMode.State.DOWNLOADING ){ upMaxUsed = Math.round( upMax*percentUpMaxUsed ); } float normalizedUp; float normalizedDown; if( setting.getValue()>0.5f ){ //calculate rates above this limit. }else{ //calculate rates below this limit. } return new SMUpdate(0,true,0,true);//Till implemented. //return null; //To change body of implemented methods use File | Settings | File Templates. } public void updateLimits(int upMax, int upMin, int downMax, int downMin) { //To change body of implemented methods use File | Settings | File Templates. } public void updateSeedSettings(float downloadModeUsed) { //To change body of implemented methods use File | Settings | File Templates. } public void updateStatus(int currUpLimit, SaturatedMode uploadUsage, int currDownLimit, SaturatedMode downloadUsage, TransferMode transferMode) { //To change body of implemented methods use File | Settings | File Templates. } public void setDownloadUnlimitedMode(boolean isUnlimited) { isDownloadUnlimited = isUnlimited; } public boolean isDownloadUnlimitedMode() { return isDownloadUnlimited; } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMonitor.java0000644000175000017500000001447510643623054027521 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import org.gudy.azureus2.core3.util.SystemTime; /** * Created on Jun 29, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class PingSpaceMonitor { PingSpaceMapper pingMap; long startTime; private static final long INTERVAL = 1000 * 60 * 5L; //five min interval. int maxGoodPing; int minBadPing; //ping counters int nBadPings,nGoodPings,nNeutralPings=0; //saturated mode counters int upNone,upLow,upMed,upHigh,upAtLimit=0; int downNone,downLow,downMed,downHigh,downAtLimit=0; TransferMode transferMode; //To get new limit back to application public static final int UPLOAD = 88; public static final int DOWNLOAD = 89; public static final int NONE = 0; boolean hasNewLimit=false; int newLimit=-2; int limitType=NONE; public PingSpaceMonitor(int _maxGoodPing,int _minBadPing, TransferMode mode) { maxGoodPing=_maxGoodPing; minBadPing=_minBadPing; reset(mode); } /** * * @param downRate - * @param upRate - */ public void setCurrentTransferRates(int downRate, int upRate){ pingMap.setCurrentTransferRates(downRate,upRate); } /** * Do a check and decide if the limits should be dropped. * @param lastMetricValue - * @param mode - the TransferMode * @return - true if the limits should be dropped. */ public boolean addToPingMapData(int lastMetricValue,TransferMode mode){ //reset if we are changing modes. if( transferMode==null ){ transferMode=mode; } //reset everything if we change modes. if( !transferMode.equals(mode) ){ reset(mode); transferMode = mode; return false; } transferMode = mode; if(lastMetricValueminBadPing){ nBadPings++; }else{ nNeutralPings++; } pingMap.addMetricToMap(lastMetricValue); //If the interval is up, we need to either recommend new limits or reset. long curr = SystemTime.getCurrentTime(); if( curr > startTime+INTERVAL ){ boolean needLowerLimts = checkForLowerLimits(); if( needLowerLimts ){ //prepare the package for lowering the limit. if( transferMode.isConfTestingLimits() ){ reset(mode); return false; }else if( transferMode.isDownloadMode() ){ //recommend a new downloading limit. newLimit = pingMap.guessDownloadLimit(); SpeedManagerLogger.trace("PingSpaceMonitor -> guessDownloadLimit: newLimit="+newLimit); //on cable modems uploads can be over-estimated by 3x. int uploadLimitGuess = pingMap.guessUploadLimit(); SpeedManagerLogger.trace("PingSpaceMonitor -> guessUploadLimit: guessUploadLimit="+uploadLimitGuess); //download limit cannot be less the 40k if(newLimit<40960){ newLimit=40960; } hasNewLimit = true; limitType = DOWNLOAD; reset(mode); return true; }else{ //only seeding mode is left recommend a new upload limit. newLimit = pingMap.guessUploadLimit(); //upload limit cannot be less the 20k if(newLimit<20480){ newLimit=20480; } hasNewLimit = true; limitType = UPLOAD; reset(mode); return true; } }else{ //No need for lower limits. reset(mode); } }//if return false; } //Simple test currently. 15% bad pings. private boolean checkForLowerLimits() { int totalPings = nGoodPings+nBadPings+nNeutralPings; float percentBad = (float)nBadPings/(float)totalPings; if(percentBad>0.15f){ return true; }else{ return false; } } public void reset(TransferMode mode){ //log results. StringBuffer sb = new StringBuffer("ping-monitor:"); sb.append("good=").append(nGoodPings).append(":"); sb.append("bad=").append(nBadPings).append(":"); sb.append("neutral=").append(nNeutralPings); SpeedManagerLogger.log( sb.toString() ); //reset all the counters. nBadPings=nGoodPings=nNeutralPings=0; //saturated mode counters upNone=upLow=upMed=upHigh=upAtLimit=0; downNone=downLow=downMed=downHigh=downAtLimit=0; pingMap = new PingSpaceMapper(maxGoodPing,minBadPing); startTime = SystemTime.getCurrentTime(); transferMode = mode; } /** * True if we have a new limit. * @return - true if there is a new limit. */ boolean hasNewLimit(){ return hasNewLimit; } public int getNewLimit(){ return newLimit; } public int limitType(){ return limitType; } /** * Call after getting new limits. */ public void resetNewLimit(){ hasNewLimit = false; newLimit = -2; limitType = NONE; } }//class azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SMSearchManager.java0000644000175000017500000000265410653605116027234 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; /** * Created on Jul 30, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ /** * deals with when a search should start. uses the history of previous searches * more effectively. */ public interface SMSearchManager { public static final String UPLOAD = "Upload"; public static final String DOWNLOAD = "Download"; public void setEndOfSearch(String type, int measuredRate); public void setEndOfSearch(String type, int measuredRate, int pingMapType); public boolean startSearch(String type); } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitMonitor.java0000644000175000017500000016351411032573750027706 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.RealTimeInfo; import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate; import com.aelitis.azureus.core.speedmanager.SpeedManagerPingMapper; import com.aelitis.azureus.core.speedmanager.SpeedManager; import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProviderAdapter; import com.aelitis.azureus.core.AzureusCoreFactory; /** * Created on May 23, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ /** * This class is responsible for re-adjusting the limits used by AutoSpeedV2. * * This class will keep track of the "status" (i.e. seeding, downloading)of the * application. It will then re-adjust the MAX limits when it thinks limits * are being reached. * * Here are the rules it will use. * * #1) When seeding. If the upload is AT_LIMIT for a period of time it will allow * that to adjust upward. * #2) When downloading. If the download is AT_LIMIT for a period of time it will * allow that to adjust upward. * * #3) When downloading, if a down-tick is detected and the upload is near a limit, * it will drop the upload limit to 80% of MAX_UPLOAD. * * #4) Once that limit is reached it will drop both the upload and download limits together. * * #5) Seeding mode is triggered when - download bandwidth at LOW - compared to CAPACITY for 5 minutes continously. * * #6) Download mode is triggered when - download bandwidth reaches MEDIUM - compared to CURRENT_LIMIT for the first time. * * Rules #5 and #6 favor downloading over seeding. * */ public class SpeedLimitMonitor implements PSMonitorListener { //use for home network. private int uploadLimitMax = SMConst.START_UPLOAD_RATE_MAX; private int uploadLimitMin = SMConst.calculateMinUpload( uploadLimitMax ); private int downloadLimitMax = SMConst.START_DOWNLOAD_RATE_MAX; private int downloadLimitMin = SMConst.calculateMinDownload( downloadLimitMax ); private TransferMode transferMode = new TransferMode(); //Upload and Download bandwidth usage modes. Compare usage to current limit. private SaturatedMode uploadBandwidthStatus =SaturatedMode.NONE; private SaturatedMode downloadBandwidthStatus =SaturatedMode.NONE; //Compare current limit to max limit. private SaturatedMode uploadLimitSettingStatus=SaturatedMode.AT_LIMIT; private SaturatedMode downloadLimitSettingStatus=SaturatedMode.AT_LIMIT; //How much confidence to we have in the current limits? private SpeedLimitConfidence uploadLimitConf = SpeedLimitConfidence.NONE; private SpeedLimitConfidence downloadLimitConf = SpeedLimitConfidence.NONE; private long clLastIncreaseTime =-1; private long clFirstBadPingTime=-1; private boolean currTestDone; private boolean beginLimitTest; private int highestUploadRate=0; private int highestDownloadRate=0; private int preTestUploadCapacity=5042; private int preTestUploadLimit=5142; private int preTestDownloadCapacity=5042; private int preTestDownloadLimit=5142; public static final String UPLOAD_CONF_LIMIT_SETTING="SpeedLimitMonitor.setting.upload.limit.conf"; public static final String DOWNLOAD_CONF_LIMIT_SETTING="SpeedLimitMonitor.setting.download.limit.conf"; public static final String UPLOAD_CHOKE_PING_COUNT="SpeedLimitMonitor.setting.choke.ping.count"; private static final long CONF_LIMIT_TEST_LENGTH=1000*30; //these methods are used to see how high limits can go. private boolean isUploadMaxPinned=true; private boolean isDownloadMaxPinned=true; private long uploadAtLimitStartTime =SystemTime.getCurrentTime(); private long downloadAtLimitStartTime = SystemTime.getCurrentTime(); private int uploadChokePingCount = 1; private int uploadPinCounter = 0; private static final long TIME_AT_LIMIT_BEFORE_UNPINNING = 30 * 1000; //30 seconds. //which percent of the measured upload capacity to use in download and seeding mode. public static final String USED_UPLOAD_CAPACITY_DOWNLOAD_MODE = "SpeedLimitMonitor.setting.upload.used.download.mode"; public static final String USED_UPLOAD_CAPACITY_SEEDING_MODE = "SpeedLimitMonitor.setting.upload.used.seeding.mode"; private float percentUploadCapacityDownloadMode = 0.6f; //PingSpaceMaps for the entire session. PingSpaceMapper pingMapOfDownloadMode; PingSpaceMapper pingMapOfSeedingMode; boolean useVariancePingMap = false; SpeedManagerPingMapper transientPingMap; PingSpaceMon longTermMonitor = new PingSpaceMon(); LimitControl slider = new LimitControlDropUploadFirst(); SpeedLimitListener persistentMapListener; public SpeedLimitMonitor(SpeedManager sm){ // longTermMonitor.addListener( this ); persistentMapListener = new SpeedLimitListener( this ); sm.addListener( persistentMapListener ); } /** * Splitting the limits our from other setting for SpeedManagerAlgorithmTI. */ public void updateSettingsFromCOConfigManager(){ percentUploadCapacityDownloadMode = (float) COConfigurationManager.getIntParameter(SpeedLimitMonitor.USED_UPLOAD_CAPACITY_DOWNLOAD_MODE, 60)/100.0f; slider.updateSeedSettings(percentUploadCapacityDownloadMode); } public void updateFromCOConfigManager(){ uploadLimitMax = COConfigurationManager.getIntParameter(SpeedManagerAlgorithmProviderV2.SETTING_UPLOAD_MAX_LIMIT); uploadLimitMin = SMConst.calculateMinUpload( uploadLimitMax ); downloadLimitMax =COConfigurationManager.getIntParameter(SpeedManagerAlgorithmProviderV2.SETTING_DOWNLOAD_MAX_LIMIT); downloadLimitMin=SMConst.calculateMinDownload( downloadLimitMax ); uploadLimitConf = SpeedLimitConfidence.parseString( COConfigurationManager.getStringParameter( SpeedLimitMonitor.UPLOAD_CONF_LIMIT_SETTING )); downloadLimitConf = SpeedLimitConfidence.parseString( COConfigurationManager.getStringParameter( SpeedLimitMonitor.DOWNLOAD_CONF_LIMIT_SETTING)); percentUploadCapacityDownloadMode = (float) COConfigurationManager.getIntParameter(SpeedLimitMonitor.USED_UPLOAD_CAPACITY_DOWNLOAD_MODE, 60)/100.0f; uploadChokePingCount = Math.min( COConfigurationManager.getIntParameter(SpeedLimitMonitor.UPLOAD_CHOKE_PING_COUNT), 30 ); slider.updateLimits(uploadLimitMax,uploadLimitMin,downloadLimitMax,downloadLimitMin); slider.updateSeedSettings(percentUploadCapacityDownloadMode); if( isSettingDownloadUnlimited() ){ slider.setDownloadUnlimitedMode( true ); } }//updateFromCOConfigManager /** * replaces - updateFromCOConfigManager() */ public void readFromPersistentMap(){ //get persistent mapper. SpeedManager sm = AzureusCoreFactory.getSingleton().getSpeedManager(); //get upload estimate. SpeedManagerLimitEstimate uEst = SMConst.filterEstimate( sm.getEstimatedUploadCapacityBytesPerSec(), SMConst.START_UPLOAD_RATE_MAX ); int upPingMapLimit = uEst.getBytesPerSec(); if(upPingMapLimit update.newDownloadLimit && update.newDownloadLimit!=0 ) { log( "Active Progressive download in progress. Overriding limit. curr="+update.newDownloadLimit +" progDownloadLimit="+prgDownLimit*MULTIPLE ); update.newDownloadLimit = (int)prgDownLimit*MULTIPLE; }//if return update; }//checkActiveProgressiveDownloadLimit /** * Log debug info needed during beta period. */ private void logPinningInfo() { StringBuffer sb = new StringBuffer("pin: "); if(isUploadMaxPinned){ sb.append("ul-pinned:"); }else{ sb.append("ul-unpinned:"); } if(isDownloadMaxPinned){ sb.append("dl-pinned:"); }else{ sb.append("dl-unpinned:"); } long currTime = SystemTime.getCurrentTime(); long upWait = currTime - uploadAtLimitStartTime; long downWait = currTime - downloadAtLimitStartTime; sb.append(upWait).append(":").append(downWait); log( sb.toString() ); } /** * * @param signalStrength - * @return - */ public SMUpdate calculateNewUnpinnedLimits(float signalStrength){ //first verify that is this is an up signal. if(signalStrength<0.0f){ //down-tick is a signal to stop moving the files up. isUploadMaxPinned=true; isDownloadMaxPinned=true; }//if //just verify settings to make sure everything is sane before updating. boolean updateUpload=false; boolean updateDownload=false; if( uploadBandwidthStatus.compareTo(SaturatedMode.AT_LIMIT)==0 && uploadLimitSettingStatus.compareTo(SaturatedMode.AT_LIMIT)==0 ){ updateUpload=true; } if( downloadBandwidthStatus.compareTo(SaturatedMode.AT_LIMIT)==0 && downloadLimitSettingStatus.compareTo(SaturatedMode.AT_LIMIT)==0 ){ updateDownload=true; } boolean uploadChanged=false; boolean downloadChanged=false; if(updateUpload && !transferMode.isDownloadMode() ){ //slow the upload rate the more. uploadPinCounter++; if( uploadPinCounter%(Math.ceil(Math.sqrt(uploadChokePingCount)))==0 ){ //increase limit by calculated amount, but only if not in downloading mode. uploadLimitMax += calculateUnpinnedStepSize(uploadLimitMax); uploadChanged=true; COConfigurationManager.setParameter( SpeedManagerAlgorithmProviderV2.SETTING_UPLOAD_MAX_LIMIT, uploadLimitMax); COConfigurationManager.setParameter( SpeedLimitMonitor.UPLOAD_CHOKE_PING_COUNT,uploadChokePingCount); }//if } if(updateDownload && !slider.isDownloadUnlimitedMode() ){ //increase limit by calculated amount. downloadLimitMax += calculateUnpinnedStepSize(downloadLimitMax); downloadChanged=true; COConfigurationManager.setParameter( SpeedManagerAlgorithmProviderV2.SETTING_DOWNLOAD_MAX_LIMIT, downloadLimitMax); } //apply any rules that need applied. //The download limit can never be less then the upload limit. (Unless zero. UNLIMITED) if( uploadLimitMax > downloadLimitMax){ downloadLimitMax = uploadLimitMax; downloadChanged=true; COConfigurationManager.setParameter( SpeedManagerAlgorithmProviderV2.SETTING_DOWNLOAD_MAX_LIMIT, downloadLimitMax); } uploadLimitMin = SMConst.calculateMinUpload( uploadLimitMax ); downloadLimitMin = SMConst.calculateMinDownload( downloadLimitMax ); if( slider.isDownloadUnlimitedMode() ){ SpeedManagerLogger.trace("upload unpinned while download is unlimited."); return new SMUpdate(uploadLimitMax,uploadChanged, 0,false); } return new SMUpdate(uploadLimitMax,uploadChanged, downloadLimitMax,downloadChanged); }//calculateNewUnpinnedLimits /** * If setting is less then 100kBytes take 1 kByte steps. * If setting is less then 500kBytes take 5 kByte steps. * if setting is larger take 10 kBytes steps. * @param currLimitMax - current limit setting. * @return - set size for next change. */ private int calculateUnpinnedStepSize(int currLimitMax){ if(currLimitMax<102400){ return 1024; }else if(currLimitMax<409600){ return 1024*5; }else if(currLimitMax>=409600){ return 1024*10; } return 1024; }// /** * Make a decision about unpinning either the upload or download limit. This is based on the * time we are saturating the limit without a down-tick signal. */ public void checkForUnpinningCondition(){ long currTime = SystemTime.getCurrentTime(); //verify the download is not unlimited. slider.setDownloadUnlimitedMode( isSettingDownloadUnlimited() ); //upload useage must be at limits for a set period of time before unpinning. if( !uploadBandwidthStatus.equals(SaturatedMode.AT_LIMIT) || !uploadLimitSettingStatus.equals(SaturatedMode.AT_LIMIT) ) { //start the clock over. uploadAtLimitStartTime = currTime; }else{ //check to see if we have been here for the time limit. if( uploadAtLimitStartTime+(TIME_AT_LIMIT_BEFORE_UNPINNING* uploadChokePingCount) < currTime ){ if( isUploadConfidenceLow() ){ if( !transferMode.isDownloadMode() ){ //alway slow search the upload limit. isUploadMaxPinned = false; } }else{ //Don't unpin the limit is we have absolute confidence in it. if( !isUploadConfidenceAbsolute() ){ //we have been AT_LIMIT long enough. Time to un-pin the limit see if we can go higher. isUploadMaxPinned = false; SpeedManagerLogger.trace("unpinning the upload max limit!! #choke-pings="+uploadChokePingCount+ ", pin-counter="+uploadPinCounter); } } } } //download usage must be at limits for a set period of time before unpinning. if( !downloadBandwidthStatus.equals(SaturatedMode.AT_LIMIT) || !downloadLimitSettingStatus.equals(SaturatedMode.AT_LIMIT) ) { //start the clock over. downloadAtLimitStartTime = currTime; }else{ //check to see if we have been here for the time limit. if( downloadAtLimitStartTime+TIME_AT_LIMIT_BEFORE_UNPINNING < currTime ){ if( isDownloadConfidenceLow() ){ if( transferMode.isDownloadMode() ){ triggerLimitTestingFlag(); } }else{ if( !isDownloadConfidenceAbsolute() ){ //we have been AT_LIMIT long enough. Time to un-pin the limit see if we can go higher. isDownloadMaxPinned = false; SpeedManagerLogger.trace("unpinning the download max limit!!"); } } } } logPinningInfo(); } /** * If we have a down-tick signal then resetTimer all the counters for increasing the limits. */ public void notifyOfDownSignal(){ if( !isUploadMaxPinned ){ uploadChokePingCount++; String msg = "pinning the upload max limit, due to downtick signal. #downtick="+ uploadChokePingCount; SpeedManagerLogger.trace(msg); SMSearchLogger.log(msg); } if( !isDownloadMaxPinned ){ String msg = "pinning the download max limit, due to downtick signal."; SpeedManagerLogger.trace(msg); SMSearchLogger.log(msg); } resetPinSearch(); } void resetPinSearch(){ long currTime = SystemTime.getCurrentTime(); uploadAtLimitStartTime = currTime; downloadAtLimitStartTime = currTime; isUploadMaxPinned = true; isDownloadMaxPinned = true; } void resetPinSearch(SpeedManagerLimitEstimate estimate){ //chocking ping needs higher limit. float type = estimate.getEstimateType(); if(type>=SpeedManagerLimitEstimate.TYPE_CHOKE_ESTIMATED){ uploadChokePingCount++; } resetPinSearch(); } /** * Return true if we are confidence testing the limits. * @return - SMUpdate */ public boolean isConfTestingLimits(){ return transferMode.isConfTestingLimits(); }// /** * Determine if we have low confidence in this limit. * @return - true if the confidence setting is LOW or NONE. Otherwise return true. */ public boolean isDownloadConfidenceLow(){ return ( downloadLimitConf.compareTo(SpeedLimitConfidence.MED) < 0 ); } public boolean isUploadConfidenceLow(){ return ( uploadLimitConf.compareTo(SpeedLimitConfidence.MED) < 0 ); } public boolean isDownloadConfidenceAbsolute(){ return ( downloadLimitConf.compareTo(SpeedLimitConfidence.ABSOLUTE)==0 ); } public boolean isUploadConfidenceAbsolute(){ return ( uploadLimitConf.compareTo(SpeedLimitConfidence.ABSOLUTE)==0 ); } /** * * @param downloadRate - currentUploadRate in bytes/sec * @param uploadRate - currentUploadRate in bytes/sec */ public synchronized void updateLimitTestingData( int downloadRate, int uploadRate ){ if( downloadRate>highestDownloadRate ){ highestDownloadRate=downloadRate; } if( uploadRate>highestUploadRate){ highestUploadRate=uploadRate; } //The exit criteria for this test is 30 seconds without an increase in the limits. long currTime = SystemTime.getCurrentTime(); if( currTime > clLastIncreaseTime+CONF_LIMIT_TEST_LENGTH){ //set the test done flag. currTestDone=true; } // or 30 seconds after its first bad ping. if( clFirstBadPingTime!=-1){ if( currTime > clFirstBadPingTime+CONF_LIMIT_TEST_LENGTH){ //set the test done flag. currTestDone=true; } } }//updateLimitTestingData. /** * Convert raw ping value to new metric. * @param lastMetric - */ public void updateLimitTestingPing(int lastMetric){ //Convert raw - pings into a rating. if(lastMetric>500){ updateLimitTestingPing(-1.0f); } } /** * New metric from the PingMapper is value between -1.0 and +1.0f. * @param lastMetric - */ public void updateLimitTestingPing(float lastMetric){ if( lastMetric<-0.3f){ //Setting this time is a signal to end soon. clFirstBadPingTime = SystemTime.getCurrentTime(); } } /** * Call this method to start the limit testing. * @param currUploadLimit - * @param currDownloadLimit - * @return - SMUpdate */ public SMUpdate startLimitTesting(int currUploadLimit, int currDownloadLimit){ clLastIncreaseTime =SystemTime.getCurrentTime(); clFirstBadPingTime =-1; highestUploadRate=0; highestDownloadRate=0; currTestDone=false; //reset the flag. beginLimitTest=false; //get the limits before the test, we are restoring them after the test. preTestUploadLimit = currUploadLimit; preTestDownloadLimit = currDownloadLimit; //configure the limits for this test. One will be at min and the other unlimited. SMUpdate retVal; if( transferMode.isDownloadMode() ){ //test the download limit. retVal = new SMUpdate(uploadLimitMin,true, Math.round(downloadLimitMax *1.2f),true); preTestDownloadCapacity = downloadLimitMax; transferMode.setMode( TransferMode.State.DOWNLOAD_LIMIT_SEARCH ); }else{ //test the upload limit. retVal = new SMUpdate( Math.round(uploadLimitMax *1.2f),true, downloadLimitMin,true); preTestUploadCapacity = uploadLimitMax; transferMode.setMode( TransferMode.State.UPLOAD_LIMIT_SEARCH ); } return retVal; } /** * Ramp the upload and download rates higher, so ping-times are relevant. * @param uploadLimit - * @param downloadLimit - * @return - */ public SMUpdate rampTestingLimit(int uploadLimit, int downloadLimit){ SMUpdate retVal; if( transferMode.getMode() == TransferMode.State.DOWNLOAD_LIMIT_SEARCH && downloadBandwidthStatus.isGreater( SaturatedMode.MED ) ) { downloadLimit *= 1.1f; clLastIncreaseTime = SystemTime.getCurrentTime(); retVal = new SMUpdate(uploadLimit,false,downloadLimit,true); }else if( transferMode.getMode() == TransferMode.State.UPLOAD_LIMIT_SEARCH && uploadBandwidthStatus.isGreater( SaturatedMode.MED )) { uploadLimit *= 1.1f; clLastIncreaseTime = SystemTime.getCurrentTime(); retVal = new SMUpdate(uploadLimit,true,downloadLimit,false); }else{ retVal = new SMUpdate(uploadLimit,false,downloadLimit,false); SpeedManagerLogger.trace("ERROR: rampTestLimit should only be called during limit testing. "); } return retVal; }//rampTestingLimit public void triggerLimitTestingFlag(){ SpeedManagerLogger.trace("triggerd fast limit test."); beginLimitTest=true; //if we are using a persistent PingSource then get that here. if( useVariancePingMap ){ SMInstance pm = SMInstance.getInstance(); SpeedManagerAlgorithmProviderAdapter adapter = pm.getAdapter(); //start a new transientPingMap; if(transientPingMap!=null){ transientPingMap.destroy(); } transientPingMap = adapter.createTransientPingMapper(); } } public synchronized boolean isStartLimitTestFlagSet(){ return beginLimitTest; } public synchronized boolean isConfLimitTestFinished(){ return currTestDone; } public synchronized SMUpdate endLimitTesting(int downloadCapacityGuess, int uploadCapacityGuess){ SpeedManagerLogger.trace(" repalce highestDownloadRate: "+highestDownloadRate+" with "+downloadCapacityGuess); SpeedManagerLogger.trace(" replace highestUploadRate: "+highestUploadRate+" with "+uploadCapacityGuess); highestDownloadRate = downloadCapacityGuess; highestUploadRate = uploadCapacityGuess; return endLimitTesting(); } /** * Call this method to end the limit testing. * @return - SMUpdate */ public synchronized SMUpdate endLimitTesting(){ SMUpdate retVal; //determine if the new setting is different then the old setting. if( transferMode.getMode()==TransferMode.State.DOWNLOAD_LIMIT_SEARCH ){ downloadLimitConf = determineConfidenceLevel(); //set that value. SpeedManagerLogger.trace("pre-upload-setting="+ preTestUploadCapacity +" up-capacity"+ uploadLimitMax +" pre-download-setting="+ preTestDownloadCapacity +" down-capacity="+ downloadLimitMax); retVal = new SMUpdate(preTestUploadLimit,true, downloadLimitMax,true); //change back to original mode. transferMode.setMode( TransferMode.State.DOWNLOADING ); }else if( transferMode.getMode()==TransferMode.State.UPLOAD_LIMIT_SEARCH){ uploadLimitConf = determineConfidenceLevel(); //set that value. retVal = new SMUpdate(uploadLimitMax,true, downloadLimitMax,true); //change back to original mode. transferMode.setMode( TransferMode.State.SEEDING ); }else{ //This is an "illegal state" make it in the logs, but try to recover by setting back to original state. SpeedManagerLogger.log("SpeedLimitMonitor had IllegalState during endLimitTesting."); retVal = new SMUpdate(preTestUploadLimit,true, preTestDownloadLimit,true); } currTestDone=true; //reset the counter uploadAtLimitStartTime = SystemTime.getCurrentTime(); downloadAtLimitStartTime = SystemTime.getCurrentTime(); return retVal; } /** * After a test is complete determine how condifent the client should be in it * based on how different it is from the previous result. If the new result is within * 20% of the old result then give it a MED. If it is great then give it a LOW. * @return - what the new confidence interval should be. */ public SpeedLimitConfidence determineConfidenceLevel(){ SpeedLimitConfidence retVal=SpeedLimitConfidence.NONE; String settingMaxLimitName; //String settingMinLimitName; boolean isDownload; String settingConfidenceName; int preTestValue; int highestValue; if(transferMode.getMode()==TransferMode.State.DOWNLOAD_LIMIT_SEARCH){ settingConfidenceName = DOWNLOAD_CONF_LIMIT_SETTING; settingMaxLimitName = SpeedManagerAlgorithmProviderV2.SETTING_DOWNLOAD_MAX_LIMIT; isDownload=true; preTestValue = preTestDownloadCapacity; highestValue = highestDownloadRate; }else if(transferMode.getMode()==TransferMode.State.UPLOAD_LIMIT_SEARCH){ settingConfidenceName = UPLOAD_CONF_LIMIT_SETTING; settingMaxLimitName = SpeedManagerAlgorithmProviderV2.SETTING_UPLOAD_MAX_LIMIT; isDownload=false; preTestValue = preTestUploadCapacity; highestValue = highestUploadRate; }else{ // SpeedManagerLogger.log("IllegalState in determineConfidenceLevel(). Setting level to NONE."); return SpeedLimitConfidence.NONE; } boolean hadChockingPing = hadChockingPing(); float percentDiff = (float)Math.abs( highestValue-preTestValue )/(float)(Math.max(highestValue,preTestValue)); if( percentDiff<0.15f && hadChockingPing ){ //Only set to medium if had both a chocking ping and two tests with similar results. retVal = SpeedLimitConfidence.MED; }else{ retVal = SpeedLimitConfidence.LOW; } //update the values. COConfigurationManager.setParameter(settingConfidenceName, retVal.getString() ); int newMaxLimitSetting = highestValue; COConfigurationManager.setParameter(settingMaxLimitName, newMaxLimitSetting); int newMinLimitSetting; if( isDownload ){ newMinLimitSetting = SMConst.calculateMinDownload( newMaxLimitSetting ); }else{ newMinLimitSetting = SMConst.calculateMinUpload( newMaxLimitSetting ); } StringBuffer sb = new StringBuffer(); if( transferMode.getMode()==TransferMode.State.UPLOAD_LIMIT_SEARCH ){ sb.append("new upload limits: "); uploadLimitMax =newMaxLimitSetting; uploadLimitMin=newMinLimitSetting; //downloadCapacity can never be less then upload capacity. if( downloadLimitMax < uploadLimitMax){ downloadLimitMax = uploadLimitMax; COConfigurationManager.setParameter( SpeedManagerAlgorithmProviderV2.SETTING_DOWNLOAD_MAX_LIMIT, downloadLimitMax); } sb.append(uploadLimitMax); }else{ sb.append("new download limits: "); downloadLimitMax =newMaxLimitSetting; downloadLimitMin=newMinLimitSetting; //upload capacity should never be 40x less then download. if( uploadLimitMax * 40 < downloadLimitMax){ uploadLimitMax = downloadLimitMax /40; COConfigurationManager.setParameter( SpeedManagerAlgorithmProviderV2.SETTING_UPLOAD_MAX_LIMIT, uploadLimitMax); uploadLimitMin = SMConst.calculateMinUpload( uploadLimitMax ); }//if sb.append(downloadLimitMax); } slider.updateLimits(uploadLimitMax,uploadLimitMin,downloadLimitMax,downloadLimitMin); SpeedManagerLogger.trace( sb.toString() ); return retVal; } /** * If the user changes the line capacity settings on the configuration panel and adjustment * needs to occur even if the signal is NO-CHANGE-NEEDED. Test for that condition here. * @param currUploadLimit - reported upload capacity from the adapter * @param currDownloadLimit - reported download capacity from the adapter. * @return - true if the "capacity" is lower then the current limit. */ public boolean areSettingsInSpec(int currUploadLimit, int currDownloadLimit){ //during a confidence level test, anything goes. if( isConfTestingLimits() ){ return true; } boolean retVal = true; if( currUploadLimit> uploadLimitMax){ retVal = false; } if( currDownloadLimit> downloadLimitMax && slider.isDownloadUnlimitedMode() ){ retVal = false; } return retVal; } private int choseBestLimit(SpeedManagerLimitEstimate estimate, int currMaxLimit, SpeedLimitConfidence currConf) { float type = estimate.getEstimateType(); int estBytesPerSec = estimate.getBytesPerSec(); int chosenLimit; //no estimate less then 20k accepted. if( (estBytesPerSec= 0.0 ){ // things looking good, this is just a new limit estimate and shouldn't // affect the actual limit in force return( currMaxLimit ); }else{ chosenLimit = estBytesPerSec; reason = "estimate and bad metric"; } }else{ //chose ping mapper. chosenLimit = estBytesPerSec; } SpeedManagerLogger.trace("bestChosenLimit: reason="+reason+",chosenLimit="+chosenLimit); return chosenLimit; } /** * Make some choices about how usable the limits are before passing them on. * @param estUp - * @param estDown - */ public void setRefLimits(SpeedManagerLimitEstimate estUp,SpeedManagerLimitEstimate estDown){ SpeedManagerLimitEstimate up = SMConst.filterEstimate(estUp,SMConst.MIN_UPLOAD_BYTES_PER_SEC); int upMax = choseBestLimit(up, uploadLimitMax, uploadLimitConf); SpeedManagerLimitEstimate down = SMConst.filterEstimate(estDown, SMConst.MIN_DOWNLOAD_BYTES_PER_SEC); int downMax = choseBestLimit(down, downloadLimitMax, downloadLimitConf); if(downMax uploadLimitMax && uploadLimitMax!=0){ newUploadLimit = uploadLimitMax; uploadChanged = true; reason.append(" (a) upload line-speed cap below current limit. "); } if(uploadLimitMax==0){ reason.append("** uploadLimitMax=0 (Unlimited)! ** "); } //check for the case when the min setting has been moved above the current limit. if( currDownloadLimit> downloadLimitMax && !slider.isDownloadUnlimitedMode() ){ newDownloadLimit = downloadLimitMax; downloadChanged = true; reason.append(" (b) download line-speed cap below current limit. "); } //Another possibility is the min limits have been raised. if( currUploadLimit sessionMaxUploadRate ){ sessionMaxUploadRate = upRateBitsPerSec; } //"curr-data" .... logCurrentData(downRateBitsPerSec, currDownLimit, upRateBitsPerSec, currUploadLimit); } /** * log "curr-data" line to the AutoSpeed-Beta file. * @param downRate - * @param currDownLimit - * @param upRate - * @param currUploadLimit - */ private void logCurrentData(int downRate, int currDownLimit, int upRate, int currUploadLimit) { StringBuffer sb = new StringBuffer("curr-data-v:"+downRate+":"+currDownLimit+":"); sb.append( limitMonitor.getDownloadMaxLimit() ).append(":"); sb.append(limitMonitor.getDownloadBandwidthMode()).append(":"); sb.append(limitMonitor.getDownloadLimitSettingMode()).append(":"); sb.append(upRate).append(":").append(currUploadLimit).append(":"); sb.append( limitMonitor.getUploadMaxLimit() ).append(":"); sb.append(limitMonitor.getUploadBandwidthMode()).append(":"); sb.append(limitMonitor.getUploadLimitSettingMode()).append(":"); sb.append(limitMonitor.getTransferModeAsString()); SpeedManagerLogger.log( sb.toString() ); } /** * Called when a new source of ping times has been found * * @param source - * @param is_replacement One of the initial sources or a replacement for a failed one */ public void pingSourceFound(SpeedManagerPingSource source, boolean is_replacement) { //We might not use ping source if the vivaldi data is available. log("pingSourceFound"); //add a new ping source to the list. pingSourceManager.pingSourceFound(source, is_replacement); } /** * Ping source has failed * * @param source - */ public void pingSourceFailed(SpeedManagerPingSource source) { //Where does the vivaldi data for the chart come from. log("pingSourceFailed"); pingSourceManager.pingSourceFailed(source); } /** * Called whenever a new set of ping values is available for processing * * @param sources - */ public void calculate(SpeedManagerPingSource[] sources) { limitMonitor.logPMDataEx(); //Get new data to ping-source-manager. int len = sources.length; for(int i=0; i0){ pingTimeList.add( new Integer( sources[i].getPingTime() ) ); intervalCount++; }//if }//for //if we are in a limit finding mode then don't even bother with this calculation. if( limitMonitor.isConfTestingLimits() ){ if( limitMonitor.isConfLimitTestFinished() ){ endLimitTesting(); return; }else{ //will increase the limit each cycle. SMUpdate ramp = limitMonitor.rampTestingLimit( adapter.getCurrentUploadLimit(), adapter.getCurrentDownloadLimit() ); logNewLimits( ramp ); setNewLimits( ramp ); } }//if - isConfTestingLimits long currTime = SystemTime.getCurrentTime(); if( timeSinceLastUpdate==0 ){ timeSinceLastUpdate=currTime; } //use the DHT ping times instead. if ( calculateMediaDHTPingTime() ){ return; } log("metric:"+ lastMetricValue); logLimitStatus(); //update the metric data limitMonitor.addToPingMapData(lastMetricValue); float signalStrength = determineSignalStrength(lastMetricValue); //if are are NOT looking for limits and we have a signal then make an adjustment. if( signalStrength!=0.0f && !limitMonitor.isConfTestingLimits() ){ hadAdjustmentLastInterval=true; float multiple = consectiveMultiplier(); int currUpLimit = adapter.getCurrentUploadLimit(); int currDownLimit = adapter.getCurrentDownloadLimit(); limitMonitor.checkForUnpinningCondition(); SMUpdate update = limitMonitor.modifyLimits(signalStrength,multiple,currUpLimit, currDownLimit); //log logNewLimits(update); //setting new setNewLimits( update ); }else{ hadAdjustmentLastInterval=false; //verify the limits. It is possible for the user to adjust the capacity down below the current limit, so check that condition here. int currUploadLimit = adapter.getCurrentUploadLimit(); int currDownloadLimit = adapter.getCurrentDownloadLimit(); if( !limitMonitor.areSettingsInSpec(currUploadLimit, currDownloadLimit) ){ SMUpdate update = limitMonitor.adjustLimitsToSpec(currUploadLimit, currDownloadLimit); logNewLimits( update ); setNewLimits( update ); } } //determine if we need to drop a ping source. pingSourceManager.checkPingSources(sources); } private void endLimitTesting() { int downLimitGuess = limitMonitor.guessDownloadLimit(); int upLimitGuess = limitMonitor.guessUploadLimit(); SMUpdate update = limitMonitor.endLimitTesting(downLimitGuess, upLimitGuess ); //print out the PingMap data to compare. limitMonitor.logPingMapData(); //reset Ping Space Map for next round. limitMonitor.resetPingSpace(); //log logNewLimits(update); //setting new setNewLimits( update ); } /** * Log the limit status. Max, Min and Conf. * log("limits:down-max:down-min:down-conf:up-max:up-min:up-conf"); */ private void logLimitStatus(){ StringBuffer msg = new StringBuffer(); msg.append("limits:"); msg.append(limitMonitor.getUploadMaxLimit()).append(":"); msg.append(limitMonitor.getUploadMinLimit()).append(":"); msg.append(limitMonitor.getUploadConfidence()).append(":"); msg.append(limitMonitor.getDownloadMaxLimit()).append(":"); msg.append(limitMonitor.getDownloadMinLimit()).append(":"); msg.append(limitMonitor.getDownloadConfidence()); SpeedManagerLogger.log( msg.toString() ); }//logLimitStatus /** * DHT Ping data is one of the metrics used. Calculate it here. * @return - true if should exit early from the caluculate method. */ private boolean calculateMediaDHTPingTime() { //Don't count this data point, if we skip the next ping times after an adjustment. if(skipIntervalAfterAdjustment && hadAdjustmentLastInterval){ hadAdjustmentLastInterval=false; pingTimeList = new ArrayList(); intervalCount=0; return true; } //have we accululated enough data to make an adjustment? if( intervalCount < numIntervalsBetweenCal ){ //get more data before making another calculation. return true; } //we have enough data. find the median ping time. Collections.sort( pingTimeList ); //if we don't have any pings, then either the connection is lost or very bad network congestion. //force an adjustment down. if( pingTimeList.size()==0 ){ lastMetricValue =10000; //This is a high value to force an adjusment down. }else{ int medianIndex = pingTimeList.size()/2; Integer medianPingTime = (Integer) pingTimeList.get(medianIndex); lastMetricValue = medianPingTime.intValue(); } //we have now consumed this data. reset the counters. intervalCount=0; pingTimeList = new ArrayList(); return false; } private void logNewLimits( SMUpdate update ) { if( update.hasNewUploadLimit ){ int kbpsUpoadLimit = update.newUploadLimit/1024; log(" new up limit : "+ kbpsUpoadLimit +" kb/s"); } if( update.hasNewDownloadLimit ){ int kpbsDownloadLimit = update.newDownloadLimit/1024; log(" new down limit: "+kpbsDownloadLimit+" kb/s"); } } /** * Just update the limits. * @param update - SMUpdate */ private void setNewLimits( SMUpdate update ){ adapter.setCurrentUploadLimit( update.newUploadLimit ); adapter.setCurrentDownloadLimit( update.newDownloadLimit ); } /** * Determined by the vivaldi value and the number of consecutive calculations * with the same result. * @param currMetricValue - * @return - */ private float determineSignalStrength(int currMetricValue){ //determine if this is an up-tick (+1), down-tick (-1) or neutral (0). float signal=0.0f; if( currMetricValue< metricGoodResult){ //strong up signal. signal=1.0f; consecutiveUpticks++; consecutiveDownticks=0; } else if( currMetricValue < (metricGoodResult + metricGoodTolerance)){ //weak up signal. signal = (float)(currMetricValue- metricGoodResult)/ metricGoodTolerance; consecutiveUpticks++; consecutiveDownticks=0; } else if( currMetricValue > metricBadResult){ //strong down signal signal = -1.0f; consecutiveUpticks=0; consecutiveDownticks++; } else if( currMetricValue > (metricBadResult - metricBadTolerance) ){ //weak down signal consecutiveUpticks=0; consecutiveDownticks++; int lowerBound= metricBadResult - metricBadTolerance; signal = (currMetricValue-lowerBound) / metricBadTolerance; signal -= 1.0f; } else{ //This is a neutral signal. } log("consecutive:"+consecutiveUpticks+":"+consecutiveDownticks); return signal; } /** * The longer were get the same signal the stronger it is. On upticks however we only increase the * rates when if the upload or download is saturated. * * @return - */ private float consectiveMultiplier(){ float multiple; if( consecutiveUpticks > consecutiveDownticks ){ //Set the consecutive upticks back to zero if the bandwidth is not being used. if( limitMonitor.bandwidthUsageLow() ){ consecutiveUpticks=0; } multiple = calculateUpTickMultiple(consecutiveUpticks); }else{ multiple = calculateDownTickMultiple(consecutiveDownticks); limitMonitor.notifyOfDownSignal(); } return multiple; } /** * Want to rise much slower then drop. * @param c - number of upsignals recieved in a row * @return - multiple factor. */ private float calculateUpTickMultiple(int c) { float multiple=0.0f; if(c<0){ return multiple; } switch(c){ case 0: case 1: multiple=0.25f; break; case 2: multiple=0.5f; break; case 3: multiple=1.0f; break; case 4: multiple=1.25f; break; case 5: multiple=1.5f; break; case 6: multiple=1.75f; break; case 7: multiple=2.0f; break; case 8: multiple=2.25f; break; case 9: multiple=2.5f; break; default: multiple=3.0f; }//switch //decrease the signal strength if bandwith usage is only in MED use. if( limitMonitor.bandwidthUsageMedium() ){ multiple /= 2.0f; } return multiple; } /** * Want to drop rate faster then increase. * @param c - * @return - */ private float calculateDownTickMultiple(int c) { float multiple=0.0f; if(c<0){ return multiple; } switch(c){ case 0: case 1: multiple=0.25f; break; case 2: multiple=0.5f; break; case 3: multiple=1.0f; break; case 4: multiple=2.0f; break; case 5: multiple=3.0f; break; case 6: multiple=4.0f; break; case 7: multiple=6.0f; break; case 8: multiple=9.0f; break; case 9: multiple=15.0f; break; default: multiple=20.0f; }//switch return multiple; } /** * Various getters for interesting info shown in stats view * * @return - */ public int getIdlePingMillis() { //return the vivaldi time. return lastMetricValue; }//getIdlePingMillis public int getCurrentPingMillis() { return 0; } public int getMaxPingMillis() { return 912; //Currently a fixed number to be sure of algorightm. } /** * Returns the current view of when choking occurs * * @return speed in bytes/sec */ public int getCurrentChokeSpeed() { return 0; } public int getMaxUploadSpeed() { return sessionMaxUploadRate; } public boolean getAdjustsDownloadLimits() { // TODO Auto-generated method stub return true; } protected void log(String str){ SpeedManagerLogger.log(str); }//log } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderPingMap.javaazureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderPingMap.j0000644000175000017500000004633511075015710032773 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProvider; import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProviderAdapter; import com.aelitis.azureus.core.speedmanager.SpeedManagerPingSource; import org.gudy.azureus2.core3.config.COConfigurationListener; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.SystemTime; import java.util.List; import java.util.ArrayList; /** * Created on Aug 5, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class SpeedManagerAlgorithmProviderPingMap implements SpeedManagerAlgorithmProvider, COConfigurationListener { private SpeedManagerAlgorithmProviderAdapter adapter; private long timeSinceLastUpdate; private int consecutiveUpticks=0; private int consecutiveDownticks=0; //SpeedLimitMonitor private SpeedLimitMonitor limitMonitor; //variables for display and vivaldi. //private int lastMetricValue; private float lastMetricValue; //use for ping. private static int numIntervalsBetweenCal = 2; private static boolean skipIntervalAfterAdjustment = true; private List pingTimeList = new ArrayList(); // //if we want to average variance pings. private boolean hadAdjustmentLastInterval = false; private int intervalCount = 0; //for managing ping sources. PingSourceManager pingSourceManager = new PingSourceManager(); //NOTE:: PingSourceManager is something that should be moved up one level!!! int sessionMaxUploadRate = 0; SpeedManagerAlgorithmProviderPingMap(SpeedManagerAlgorithmProviderAdapter _adapter){ adapter = _adapter; SpeedManagerLogger.setAdapter( "pm", adapter ); limitMonitor = new SpeedLimitMonitor( adapter.getSpeedManager()); COConfigurationManager.addListener( this ); SMInstance.init( _adapter ); limitMonitor.initPingSpaceMap(); } public void destroy() { COConfigurationManager.removeListener( this ); } public void configurationSaved(){ try{ limitMonitor.readFromPersistentMap(); limitMonitor.updateFromCOConfigManager(); skipIntervalAfterAdjustment=COConfigurationManager.getBooleanParameter( SpeedManagerAlgorithmProviderV2.SETTING_WAIT_AFTER_ADJUST); numIntervalsBetweenCal=COConfigurationManager.getIntParameter( SpeedManagerAlgorithmProviderV2.SETTING_INTERVALS_BETWEEN_ADJUST); limitMonitor.initPingSpaceMap(); SpeedManagerLogger.trace("..VariancePingMap - configurationSaved called."); }catch( Throwable t ){ SpeedManagerLogger.log(t.getMessage()); } }//configurationSaved /** * Reset any state to start of day values */ public void reset() { log("reset"); log("curr-data-m: curr-down-rate : curr-down-limit : down-capacity : down-bandwith-mode : down-limit-mode : curr-up-rate : curr-up-limit : up-capacity : upload-bandwidth-mode : upload-limit-mode : transfer-mode"); log("new-limit:newLimit:currStep:signalStrength:multiple:currUpLimit:maxStep:uploadLimitMax:uploadLimitMin:transferMode" ); log("consecutive:up:down"); log("metric:value:type"); log("user-comment:log"); log("pin:upload-status,download-status,upload-unpin-timer,download-unpin-timer"); log("limits:down-max:down-min:down-conf:up-max:up-min:up-conf"); limitMonitor.resetPingSpace(); } /** * Called periodically (see period above) to allow stats to be updated. */ public void updateStats() { //update some stats used in the UI. int currUploadLimit = adapter.getCurrentUploadLimit(); int currDataUploadSpeed = adapter.getCurrentDataUploadSpeed(); int currProtoUploadSpeed = adapter.getCurrentProtocolUploadSpeed(); int upRateBitsPerSec = currDataUploadSpeed + currProtoUploadSpeed; int currDownLimit = adapter.getCurrentDownloadLimit(); int downDataRate = adapter.getCurrentDataDownloadSpeed(); int downProtoRate = adapter.getCurrentProtocolDownloadSpeed(); int downRateBitsPerSec = downDataRate+downProtoRate; //update the bandwidth status limitMonitor.setDownloadBandwidthMode(downRateBitsPerSec,currDownLimit); limitMonitor.setUploadBandwidthMode(upRateBitsPerSec,currUploadLimit); //update the limts status. (is it near a forced max or min?) limitMonitor.setDownloadLimitSettingMode(currDownLimit); limitMonitor.setUploadLimitSettingMode(currUploadLimit); limitMonitor.updateTransferMode(); if( limitMonitor.isConfTestingLimits() ){ limitMonitor.updateLimitTestingData(downRateBitsPerSec,upRateBitsPerSec); } //update ping maps limitMonitor.setCurrentTransferRates(downRateBitsPerSec,upRateBitsPerSec); //only for the UI. if( upRateBitsPerSec > sessionMaxUploadRate ){ sessionMaxUploadRate = upRateBitsPerSec; } //"curr-data" .... logCurrentData(downRateBitsPerSec, currDownLimit, upRateBitsPerSec, currUploadLimit); } /** * log "curr-data" line to the AutoSpeed-Beta file. * @param downRate - * @param currDownLimit - * @param upRate - * @param currUploadLimit - */ private void logCurrentData(int downRate, int currDownLimit, int upRate, int currUploadLimit) { StringBuffer sb = new StringBuffer("curr-data-m:"+downRate+":"+currDownLimit+":"); sb.append( limitMonitor.getDownloadMaxLimit() ).append(":"); sb.append(limitMonitor.getDownloadBandwidthMode()).append(":"); sb.append(limitMonitor.getDownloadLimitSettingMode()).append(":"); sb.append(upRate).append(":").append(currUploadLimit).append(":"); sb.append( limitMonitor.getUploadMaxLimit() ).append(":"); sb.append(limitMonitor.getUploadBandwidthMode()).append(":"); sb.append(limitMonitor.getUploadLimitSettingMode()).append(":"); sb.append(limitMonitor.getTransferModeAsString()); SpeedManagerLogger.log( sb.toString() ); } /** * Called when a new source of ping times has been found * * @param source - * @param is_replacement One of the initial sources or a replacement for a failed one */ public void pingSourceFound(SpeedManagerPingSource source, boolean is_replacement) { //We might not use ping source if the vivaldi data is available. log("pingSourceFound"); //add a new ping source to the list. pingSourceManager.pingSourceFound(source, is_replacement); } /** * Ping source has failed * * @param source - */ public void pingSourceFailed(SpeedManagerPingSource source) { //Where does the vivaldi data for the chart come from. log("pingSourceFailed"); pingSourceManager.pingSourceFailed(source); } /** * Called whenever a new set of ping values is available for processing * * @param sources - */ public void calculate(SpeedManagerPingSource[] sources) { limitMonitor.logPMDataEx(); //Get new data to ping-source-manager. int len = sources.length; for(int i=0; i0){ //pingTimeList.add( new Integer( sources[i].getPingTime() ) ); intervalCount++; }//if }//for //if we are in a limit finding mode then don't even bother with this calculation. if( limitMonitor.isConfTestingLimits() ){ if( limitMonitor.isConfLimitTestFinished() ){ endLimitTesting(); return; }else{ //will increase the limit each cycle. SMUpdate ramp = limitMonitor.rampTestingLimit( adapter.getCurrentUploadLimit(), adapter.getCurrentDownloadLimit() ); logNewLimits( ramp ); setNewLimits( ramp ); } }//if - isConfTestingLimits long currTime = SystemTime.getCurrentTime(); if( timeSinceLastUpdate==0 ){ timeSinceLastUpdate=currTime; } //use the variance ping times instead. if ( calculatePingMetric() ){ return; } log("metric:"+ lastMetricValue); logLimitStatus(); //update the metric data //limitMonitor.addToPingMapData(lastMetricValue); float signalStrength = determineSignalStrength(lastMetricValue); //if are are NOT looking for limits and we have a signal then make an adjustment. if( signalStrength!=0.0f && !limitMonitor.isConfTestingLimits() ){ hadAdjustmentLastInterval=true; float multiple = consectiveMultiplier(); int currUpLimit = adapter.getCurrentUploadLimit(); int currDownLimit = adapter.getCurrentDownloadLimit(); limitMonitor.checkForUnpinningCondition(); SMUpdate update = limitMonitor.modifyLimits(signalStrength,multiple,currUpLimit, currDownLimit); //log logNewLimits(update); //setting new setNewLimits( update ); }else{ hadAdjustmentLastInterval=false; //verify the limits. It is possible for the user to adjust the capacity down below the current limit, so check that condition here. int currUploadLimit = adapter.getCurrentUploadLimit(); int currDownloadLimit = adapter.getCurrentDownloadLimit(); if( !limitMonitor.areSettingsInSpec(currUploadLimit, currDownloadLimit) ){ SMUpdate update = limitMonitor.adjustLimitsToSpec(currUploadLimit, currDownloadLimit); logNewLimits( update ); setNewLimits( update ); } } //determine if we need to drop a ping source. pingSourceManager.checkPingSources(sources); } private void endLimitTesting() { int downLimitGuess = limitMonitor.guessDownloadLimit(); int upLimitGuess = limitMonitor.guessUploadLimit(); SMUpdate update = limitMonitor.endLimitTesting(downLimitGuess, upLimitGuess ); //print out the PingMap data to compare. limitMonitor.logPingMapData(); //reset Ping Space Map for next round. limitMonitor.resetPingSpace(); //log logNewLimits(update); //setting new setNewLimits( update ); } /** * Log the limit status. Max, Min and Conf. * log("limits:down-max:down-min:down-conf:up-max:up-min:up-conf"); */ private void logLimitStatus(){ StringBuffer msg = new StringBuffer(); msg.append("limits:"); msg.append(limitMonitor.getUploadMaxLimit()).append(":"); msg.append(limitMonitor.getUploadMinLimit()).append(":"); msg.append(limitMonitor.getUploadConfidence()).append(":"); msg.append(limitMonitor.getDownloadMaxLimit()).append(":"); msg.append(limitMonitor.getDownloadMinLimit()).append(":"); msg.append(limitMonitor.getDownloadConfidence()); SpeedManagerLogger.log( msg.toString() ); }//logLimitStatus /** * Variance PingMap data is the metrics used. Calculate it here. * @return - true if should exit early from the caluculate method. */ private boolean calculatePingMetric() { //Don't count this data point, if we skip the next ping times after an adjustment. if(skipIntervalAfterAdjustment && hadAdjustmentLastInterval){ hadAdjustmentLastInterval=false; pingTimeList = new ArrayList(); intervalCount=0; return true; } //have we accululated enough data to make an adjustment? if( intervalCount < numIntervalsBetweenCal ){ //get more data before making another calculation. return true; } //we have enough data. find the median ping time. lastMetricValue = (float)adapter.getPingMapper().getCurrentMetricRating(); //we have now consumed this data. reset the counters. intervalCount=0; return false; } private void logNewLimits( SMUpdate update ) { if( update.hasNewUploadLimit ){ int kbpsUpoadLimit = update.newUploadLimit/1024; log(" new up limit : "+ kbpsUpoadLimit +" kb/s"); } if( update.hasNewDownloadLimit ){ int kpbsDownloadLimit = update.newDownloadLimit/1024; log(" new down limit: "+kpbsDownloadLimit+" kb/s"); } } /** * Just update the limits. * @param update - SMUpdate */ private void setNewLimits( SMUpdate update ){ adapter.setCurrentUploadLimit( update.newUploadLimit ); adapter.setCurrentDownloadLimit( update.newDownloadLimit ); } private float determineSignalStrength(float lastMetric){ //determine if this is an up-tick (+1), down-tick (-1) or neutral (0). // range should be -1.0 (bad) to +1.0 (good) float signal = convertTestMetricToSignal( lastMetric ); if( signal > 0.0f){ consecutiveUpticks++; consecutiveDownticks=0; }else if(signal < 0.0f ){ consecutiveUpticks=0; consecutiveDownticks++; }else{ //This is a neutral signal. } log("consecutive:"+consecutiveUpticks+":"+consecutiveDownticks); return signal; } /** * * @param testMetric - float -1.0f to +1.0f * @return signal as float with 0.0 meaning don't make an adjustment. */ private float convertTestMetricToSignal( float testMetric ){ if( testMetric>=1.0f ){ return 1.0f; } if(testMetric<=-1.0f){ return -1.0f; } //here we will map the neutral region to -0.5f to +0.5f to singal = 0; if( testMetric>-0.5f && testMetric<0.5f ){ return 0.0f; } //map weak up signal. if( testMetric > 0.0f ){ return ( (testMetric - 0.5f) * 2.0f ); } //map weak down signal return ( ( testMetric+0.5f ) * 2.0f ); } /** * The longer were get the same signal the stronger it is. On upticks however we only increase the * rates when if the upload or download is saturated. * * @return - */ private float consectiveMultiplier(){ float multiple; if( consecutiveUpticks > consecutiveDownticks ){ //Set the consecutive upticks back to zero if the bandwidth is not being used. if( limitMonitor.bandwidthUsageLow() ){ consecutiveUpticks=0; } multiple = calculateUpTickMultiple(consecutiveUpticks); }else{ multiple = calculateDownTickMultiple(consecutiveDownticks); limitMonitor.notifyOfDownSignal(); } return multiple; } /** * Want to rise much slower then drop. * @param c - number of upsignals recieved in a row * @return - multiple factor. */ private float calculateUpTickMultiple(int c) { float multiple=0.0f; if(c<0){ return multiple; } switch(c){ case 0: case 1: multiple=0.25f; break; case 2: multiple=0.5f; break; case 3: multiple=1.0f; break; case 4: multiple=1.25f; break; case 5: multiple=1.5f; break; case 6: multiple=1.75f; break; case 7: multiple=2.0f; break; case 8: multiple=2.25f; break; case 9: multiple=2.5f; break; default: multiple=3.0f; }//switch //decrease the signal strength if bandwith usage is only in MED use. if( limitMonitor.bandwidthUsageMedium() ){ multiple /= 2.0f; } return multiple; } /** * Want to drop rate faster then increase. * @param c - * @return - */ private float calculateDownTickMultiple(int c) { float multiple=0.0f; if(c<0){ return multiple; } switch(c){ case 0: case 1: multiple=0.25f; break; case 2: multiple=0.5f; break; case 3: multiple=1.0f; break; case 4: multiple=2.0f; break; case 5: multiple=3.0f; break; case 6: multiple=4.0f; break; case 7: multiple=6.0f; break; case 8: multiple=9.0f; break; case 9: multiple=15.0f; break; default: multiple=20.0f; }//switch return multiple; } /** * Various getters for interesting info shown in stats view * * @return - */ public int getIdlePingMillis() { //return the vivaldi time. return 0;//lastMetricValue; }//getIdlePingMillis public int getCurrentPingMillis() { return 0; } public int getMaxPingMillis() { return 910; //Currently a fixed number to be sure of algorightm. } /** * Returns the current view of when choking occurs * * @return speed in bytes/sec */ public int getCurrentChokeSpeed() { return 0; } public int getMaxUploadSpeed() { return sessionMaxUploadRate; } public boolean getAdjustsDownloadLimits() { // TODO Auto-generated method stub return true; } protected void log(String str){ SpeedManagerLogger.log(str); }//log } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControl.java0000644000175000017500000000273610652317144026714 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; /** * Created on Jul 12, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public interface LimitControl { SMUpdate adjust(float amount); void updateLimits(int upMax, int upMin, int downMax, int downMin); void updateSeedSettings(float downloadModeUsed); void updateStatus(int currUpLimit, SaturatedMode uploadUsage, int currDownLimit, SaturatedMode downloadUsage, TransferMode transferMode); void setDownloadUnlimitedMode(boolean isUnlimited); boolean isDownloadUnlimitedMode(); } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SMConst.java0000644000175000017500000001054710651610202025610 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate; /** * Created on Jul 18, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class SMConst { //strictly a utility class. private SMConst(){} public static final int START_DOWNLOAD_RATE_MAX = 61440; public static final int START_UPLOAD_RATE_MAX = 30720; public static final int MIN_UPLOAD_BYTES_PER_SEC = 5120; public static final int MIN_DOWNLOAD_BYTES_PER_SEC = 20480; public static final int RATE_UNLIMITED = 0; /** * No limit should go below 5k bytes/sec. * @param rateBytesPerSec - * @return - "bytes/sec" rate. */ public static int checkForMinUploadValue(int rateBytesPerSec){ if( rateBytesPerSec < MIN_UPLOAD_BYTES_PER_SEC ){ return MIN_UPLOAD_BYTES_PER_SEC; } return rateBytesPerSec; } public static int checkForMinDownloadValue(int rateBytesPerSec){ if( rateBytesPerSec < MIN_DOWNLOAD_BYTES_PER_SEC ){ return MIN_DOWNLOAD_BYTES_PER_SEC; } return rateBytesPerSec; } /** * Rule: Min value is alway 10% of max, but not below 5k. * @param maxBytesPerSec - * @return - minRate. */ public static int calculateMinUpload(int maxBytesPerSec){ int min = maxBytesPerSec/10; return checkForMinUploadValue( min ); } public static int calculateMinDownload(int maxBytesPerSec){ int min = maxBytesPerSec/10; return checkForMinDownloadValue( min ); } /** * Early in the search process the ping-mapper can give estimates that are too low due to * a lack of information. The starting upload and download limits is 60K/30K should not go * below the starting value a slow DSL lines should. * @param estimate - download rate estimate. * @param startValue - starting upload/download value. * @return - */ public static SpeedManagerLimitEstimate filterEstimate(SpeedManagerLimitEstimate estimate, int startValue){ int estBytesPerSec = filterLimit(estimate.getBytesPerSec(), startValue); return new FilteredLimitEstimate(estBytesPerSec, estimate.getEstimateType(), estimate.getMetricRating(), estimate.getString() ); }//filterDownEstimate public static int filterLimit(int bytesPerSec, int startValue){ int retVal = Math.max(bytesPerSec, startValue); // Zero is unlimited. Don't filter that value. if( bytesPerSec==0 ){ return bytesPerSec; } return retVal; } static class FilteredLimitEstimate implements SpeedManagerLimitEstimate { int bytesPerSec; float type; float metric; String name; public FilteredLimitEstimate(int _bytesPerSec, float _type, float _metric, String _name){ bytesPerSec = _bytesPerSec; type = _type; metric = _metric; name = _name; } public int getBytesPerSec() { return bytesPerSec; } public float getEstimateType() { return type; } public float getMetricRating() { return metric; } public int[][] getSegments() { return new int[0][]; } public String getString() { return name; } }//static class } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SMInstance.java0000644000175000017500000000331510653605116026273 0ustar adrianadrian/** * Created on Jul 11, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager.impl.v2; import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProviderAdapter; public class SMInstance { private static SMInstance instance = new SMInstance(); private static SpeedManagerAlgorithmProviderAdapter adapter; private static SMConfigurationAdapter conf; public static void init(SpeedManagerAlgorithmProviderAdapter _adapter){ adapter = _adapter; conf = new SMConfigurationAdapterImpl(); } public static SMInstance getInstance() { return instance; } private SMInstance() { } public SpeedManagerAlgorithmProviderAdapter getAdapter(){ return adapter; } public SMConfigurationAdapter getConfigManager(){ return conf; } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SMSearchLogger.java0000644000175000017500000000531610653605116027077 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.AEDiagnosticsLogger; import org.gudy.azureus2.core3.util.AEDiagnostics; import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate; import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProviderAdapter; /** * Created on Jul 30, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ /** * Limit search diagnostics. */ public class SMSearchLogger { private static final LogIDs ID = LogIDs.NWMAN; private static final AEDiagnosticsLogger dLog = AEDiagnostics.getLogger("AutoSpeedSearchHistory"); private SMSearchLogger(){} public static void log(String str){ //get the adapter values. SpeedManagerAlgorithmProviderAdapter adpter = SMInstance.getInstance().getAdapter(); int adptCurrUpLimit = adpter.getCurrentUploadLimit(); int adptCurrDownLimit = adpter.getCurrentDownloadLimit(); //get the COConfigurationManager values. SMConfigurationAdapter conf = SMInstance.getInstance().getConfigManager(); SpeedManagerLimitEstimate uploadSetting = conf.getUploadLimit(); SpeedManagerLimitEstimate downloadSetting = conf.getDownloadLimit(); StringBuffer sb = new StringBuffer(str); sb.append(", Download current =").append(adptCurrDownLimit); sb.append(", max limit =").append(downloadSetting.getString()); sb.append(", Upload current = ").append(adptCurrUpLimit); sb.append(", max limit = ").append(uploadSetting.getString()); String msg = sb.toString(); LogEvent e = new LogEvent(ID,msg); Logger.log(e); if(dLog!=null){ dLog.log(msg); } }//log } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/TransferMode.java0000644000175000017500000001074210643623054026662 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import org.gudy.azureus2.core3.util.SystemTime; /** * Created on Jun 1, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ /** * Is the application in a "download" mode? Or is it in a "seeding" mode? This is * used to determine up we cut back on upload bandwidth limit. * * Here is how to determine the mode. If the download rate is LOW compared to the capacity * for five minutes continously then it will be considered in a SEEDING mode. * * If the download bandwidth ever goes into the MED range then it switches to DOWNLOADING * mode immediately. * * The application will favor DOWNLOADING mode to SEEDING mode. * */ public class TransferMode { private State mode = State.DOWNLOADING; private long lastTimeDownloadDetected = SystemTime.getCurrentTime(); private static final long WAIT_TIME_FOR_SEEDING_MODE = 1000 * 60; public TransferMode() { } /** * If the download bandwidth is ever in MED or above switch immediately to DOWNLOADING mode. * If th download bandwidth is LOW or less for more then 5 min, switch to SEEDING mode. * @param downloadBandwidth - current download status. */ public void updateStatus(SaturatedMode downloadBandwidth){ //this setting have no effect while testing the limits. if( isConfTestingLimits() ){ if( mode==State.DOWNLOAD_LIMIT_SEARCH ){ lastTimeDownloadDetected = SystemTime.getCurrentTime(); } return; } if( downloadBandwidth.compareTo(SaturatedMode.LOW)<=0 ){ //we don't seem to be downloading at the moment. //see if this state has persisted for more then five minutes. long time = SystemTime.getCurrentTime(); if( time > lastTimeDownloadDetected+WAIT_TIME_FOR_SEEDING_MODE ){ mode = State.SEEDING; } }else{ //Some downloading is happening. Remove from SEEDING mode. mode = State.DOWNLOADING; lastTimeDownloadDetected = SystemTime.getCurrentTime(); } } public String getString(){ return mode.getString(); } public State getMode(){ return mode; } public void setMode( State newMode ){ SpeedManagerLogger.trace( " setting transfer mode to: "+newMode.getString() ); mode = newMode; } /** * Are we in downloading mode? * @return - boolean - true if in downloading mode. Otherwise false. */ public boolean isDownloadMode(){ return ( mode==State.DOWNLOADING ); }//isDownloadMode /** * We have two types of limit testing. If we are doing a "confidence test" for the limits then * return true. This mode is putting one value at the min setting and the other at unlimited. * @return - true if doing a "conf test of the limits" */ public boolean isConfTestingLimits(){ return ( mode==State.DOWNLOAD_LIMIT_SEARCH || mode==State.UPLOAD_LIMIT_SEARCH ); } /** * Java 1.4 enumeration. - Seeding mode or Downloading mode. */ static class State{ public static final State DOWNLOADING = new State("downloading"); public static final State SEEDING = new State("seeding"); public static final State DOWNLOAD_LIMIT_SEARCH = new State("download limit search"); public static final State UPLOAD_LIMIT_SEARCH = new State("upload limit search"); String mode; private State(String _mode){ mode = _mode; } public String getString(){ return mode; } }//class State } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMon.java0000644000175000017500000001603510660412106026606 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate; import com.aelitis.azureus.core.speedmanager.SpeedManagerPingMapper; import com.aelitis.azureus.core.speedmanager.SpeedManager; import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProviderAdapter; import java.util.List; import java.util.ArrayList; /** * Created on Jul 16, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class PingSpaceMon { private static final long INTERVAL = 1000 * 60 * 15L; long nextCheck = System.currentTimeMillis() + INTERVAL; TransferMode mode; List listeners = new ArrayList();//List public void addListener(PSMonitorListener listener){ //don't register the same listener twice. for(int i=0; i * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class SMUpdate { public int newUploadLimit; public int newDownloadLimit; public boolean hasNewUploadLimit; public boolean hasNewDownloadLimit; public SMUpdate(int upLimit, boolean newUpLimit, int downLimit, boolean newDownLimit) { newUploadLimit = upLimit; newDownloadLimit = downLimit; hasNewUploadLimit = newUpLimit; hasNewDownloadLimit = newDownLimit; } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitConfidence.java0000644000175000017500000001261510654327350030311 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import org.gudy.azureus2.core3.internat.MessageText; import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate; /** * Created on Jun 5, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class SpeedLimitConfidence implements Comparable { public static final SpeedLimitConfidence NONE = new SpeedLimitConfidence("NONE",0, SpeedManagerLimitEstimate.TYPE_UNKNOWN); public static final SpeedLimitConfidence LOW = new SpeedLimitConfidence("LOW",1, SpeedManagerLimitEstimate.TYPE_ESTIMATED); public static final SpeedLimitConfidence MED = new SpeedLimitConfidence("MED",2, SpeedManagerLimitEstimate.TYPE_CHOKE_ESTIMATED); public static final SpeedLimitConfidence HIGH = new SpeedLimitConfidence("HIGH",3, SpeedManagerLimitEstimate.TYPE_MEASURED_MIN); public static final SpeedLimitConfidence ABSOLUTE = new SpeedLimitConfidence("ABSOLUTE",4, SpeedManagerLimitEstimate.TYPE_MANUAL); private final String name; private final int order; private final float estimateType; private SpeedLimitConfidence(String _name, int _order, float _speedLimitEstimateType){ name = _name; order = _order; estimateType = _speedLimitEstimateType; } public static SpeedLimitConfidence convertType( float type ){ if( type <= SpeedLimitConfidence.NONE.estimateType ){ return NONE; }else if( type <= SpeedLimitConfidence.LOW.estimateType ){ return LOW; }else if( type <= SpeedLimitConfidence.MED.estimateType ){ return MED; }else if( type <= SpeedLimitConfidence.HIGH.estimateType ){ return HIGH; }else{ return ABSOLUTE; } }//convertType /** * Turns a string into a SpeedLimitConfidence class. * @param setting - String is expected to be one of: NONE, LOW, MED, HIGH, ABSOLUE. * @return - class corresponding to String. If it isn't one of the know values then NONE is returned. */ public static SpeedLimitConfidence parseString(String setting){ SpeedLimitConfidence retVal = SpeedLimitConfidence.NONE; if(setting==null){ return retVal; } if( "NONE".equalsIgnoreCase(setting) ){ return SpeedLimitConfidence.NONE; }else if("LOW".equalsIgnoreCase(setting)){ return SpeedLimitConfidence.LOW; }else if("MED".equalsIgnoreCase(setting)){ return SpeedLimitConfidence.MED; }else if("HIGH".equalsIgnoreCase(setting)){ return SpeedLimitConfidence.HIGH; }else if("ABSOLUTE".equalsIgnoreCase(setting)){ return SpeedLimitConfidence.ABSOLUTE; } return retVal; } public float asEstimateType(){ return estimateType; } public static String asEstimateTypeString(float type){ //ToDo: move to proper class. This is to do something now. if( type==SpeedManagerLimitEstimate.TYPE_UNKNOWN ){ return "Unknown"; }else if( type==SpeedManagerLimitEstimate.TYPE_ESTIMATED){ return "Estimate"; }else if( type==SpeedManagerLimitEstimate.TYPE_MANUAL){ return "Fixed"; } return ""; } public String getString(){ return name; } private static final String MESSAGE_BUNDLE_PREFIX = "SpeedTestWizard.name.conf.level."; /** * Get the internationalized string for UI panels and * drop downs. * @return - Internationalized String. */ public String getInternationalizedString(){ return MessageText.getString( MESSAGE_BUNDLE_PREFIX + name.toLowerCase() ); } /** * compareTo to with boolean syntax. * * @param limitConf - * @return - true if greater then, false if equal or less. */ public boolean isGreater(SpeedLimitConfidence limitConf) { if( this.compareTo(limitConf)>0 ){ return true; } return false; } /** * Comparable interface * @param limitConf - Item to compare with. * @return - */ public int compareTo(SpeedLimitConfidence limitConf){ return (order - limitConf.order); } /** * Comparable interface. * @param obj - * @return - */ public int compareTo(Object obj){ if( !(obj instanceof SpeedLimitConfidence) ){ throw new ClassCastException("Only comparable to SpeedLimitConfidence class."); } SpeedLimitConfidence casted = (SpeedLimitConfidence) obj; return compareTo(casted); } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/PingSourceManager.java0000644000175000017500000002355511152064564027651 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import com.aelitis.azureus.core.speedmanager.SpeedManagerPingSource; import com.aelitis.azureus.core.util.average.Average; import java.util.Map; import java.util.HashMap; import org.gudy.azureus2.core3.util.SystemTime; /** * Created on May 31, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ /** * This class manage cycling though the PingSources. It keep track of PingSource stats and * applies rules on if/when to cycle though a ping-source. * * #1) If the slowest ping-source is 10x the the best for a 1 min average. kick it. * #2) If a ping-source is slower then two combined sources (2x) for a 5 min average. then kick it. * #3) Every 30 minutes kick the slowest ping source and request a new one. Just to keep things fresh. * * Also maintain logic do determine if a new source is better then the previous one. (To determine * if these rules lead to good data.) * */ public class PingSourceManager { // private final Map pingAverages = new HashMap(); // private long lastPingRemoval=0; private static final long TIME_BETWEEN_BAD_PING_REMOVALS = 2 * 60 * 1000; // two minutes. private static final long TIME_BETWEEN_SLOW_PING_REMOVALS = 5 * 60 * 1000;// fifteen minutes. private static final long TIME_BETWEEN_FORCED_CYCLE_REMOVALS = 30 * 60 * 1000;// thirty minutes. /** * Determine if we should drop any ping sources. * Sort them, if one significantly higher then the other two. then drop it. * @param sources - SpeedManagerPingSource[] inputs */ public void checkPingSources(SpeedManagerPingSource[] sources){ //if the long term average of one source is 10 the lowest and twice a large as the //two lowest then drop the highest at the moment. Also, don't force sources to //drop to frequently. //no sources. if( sources==null ){ return; } //if we have only two sources then don't do this test. if( sources.length<3 ){ return; } //Test for a very bad ping source. i.e. slowest source is 10x slower then the fastest, if( checkForBadPing(sources) ){ return; } //Test for slower then average source. i.e. slowest source is 3x media. if( checkForSlowSource(sources) ){ return; } //Even if everything is going well then force a change every 30 minutes. forcePingSourceChange(sources); }//checkPingSources /** * If one ping source is twice the fastest then replace it. Otherwise reset the timer. * @param sources - * @return - true is a souce has been changed. */ private boolean forcePingSourceChange(SpeedManagerPingSource[] sources){ //We only apply this rule if nothing has been removed in the past 30 minutes. long currTime = SystemTime.getCurrentTime(); if( currTimeslowestPing ){ slowestPing = pingTime; slowestSource=sources[i]; } //find sped of fastest. if( pingTime 2*fastestPing ){ if(slowestSource!=null){ slowestSource.destroy(); return true; } } return false; }//forcePingSourceChange /** * A slow source is something that is 2x the slower then the two fastest. * @param sources - * @return - true is a source has been removed. */ private boolean checkForSlowSource(SpeedManagerPingSource[] sources){ //We only apply this rule if nothing has been removed in the past 15 minutes. long currTime = SystemTime.getCurrentTime(); if( currTimeslowest){ slowest = pingTime; slowestSource = sources[i]; resetTimer(); } }//for double sumFastest = fastA+fastB; boolean removedSource = false; if( sumFastest*2 < slowest ){ //destroy this source. It is a bit too slow. if(slowestSource!=null){ slowestSource.destroy(); SpeedManagerLogger.log("dropping ping source: "+slowestSource.getAddress()+" for being 2x slower then two fastest."); removedSource = true; resetTimer(); } }//if return removedSource; }//checkForSlowSource /** * If the slowest ping in 10x the fastest then remove it. * @param sources - * @return - true is a source has been removed. */ private boolean checkForBadPing(SpeedManagerPingSource[] sources) { //if we just recently removed a ping source then wait. long currTime = SystemTime.getCurrentTime(); if( currTimehighestLongTermPing ){ highestLongTermPing = avePingTime; highestSource = sources[i]; } //is this a new lowest value? if( avePingTime0){ pss.addPingTime( source.getPingTime() ); } }//addPingTime /** * After a ping-source has been removed, need to resetTimer the timer. */ private void resetTimer(){ lastPingRemoval = SystemTime.getCurrentTime(); } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SMConfigurationAdapter.java0000644000175000017500000000254010653605116030636 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate; /** * Created on Jul 30, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public interface SMConfigurationAdapter { public SpeedManagerLimitEstimate getUploadLimit(); public SpeedManagerLimitEstimate getDownloadLimit(); public void setUploadLimit(SpeedManagerLimitEstimate est); public void setDownloadLimit(SpeedManagerLimitEstimate est); } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SMConfigurationAdapterImpl.java0000644000175000017500000000750410653605116031465 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate; import org.gudy.azureus2.core3.config.COConfigurationManager; /** * Created on Jul 30, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class SMConfigurationAdapterImpl implements SMConfigurationAdapter { public SMConfigurationAdapterImpl(){} public SpeedManagerLimitEstimate getUploadLimit() { int upMax = COConfigurationManager.getIntParameter(SpeedManagerAlgorithmProviderV2.SETTING_UPLOAD_MAX_LIMIT); SpeedLimitConfidence upConf = SpeedLimitConfidence.parseString( COConfigurationManager.getStringParameter( SpeedLimitMonitor.UPLOAD_CONF_LIMIT_SETTING ) ); return new SMConfigLimitEstimate(upMax,upConf); } public SpeedManagerLimitEstimate getDownloadLimit() { int upMax = COConfigurationManager.getIntParameter(SpeedManagerAlgorithmProviderV2.SETTING_DOWNLOAD_MAX_LIMIT); SpeedLimitConfidence upConf = SpeedLimitConfidence.parseString( COConfigurationManager.getStringParameter( SpeedLimitMonitor.DOWNLOAD_CONF_LIMIT_SETTING ) ); return new SMConfigLimitEstimate(upMax,upConf); } public void setUploadLimit(SpeedManagerLimitEstimate est) { //To change body of implemented methods use File | Settings | File Templates. } public void setDownloadLimit(SpeedManagerLimitEstimate est) { //To change body of implemented methods use File | Settings | File Templates. } //conversion routines need to be here. static class SMConfigLimitEstimate implements SpeedManagerLimitEstimate{ final int bytesPerSec; final float limitEstimateType; public SMConfigLimitEstimate(int rateInBytesPerSec, SpeedLimitConfidence conf){ bytesPerSec = rateInBytesPerSec; limitEstimateType = conf.asEstimateType(); } public int getBytesPerSec() { return bytesPerSec; } /** * One of the above constants * * @return */ public float getEstimateType() { return limitEstimateType; } /** * For estimated limits: * -1 = estimate derived from bad metrics * +1 = estimate derived from good metric * <1 x > -1 = relative goodness of metric * * @return */ public float getMetricRating() { return 0.0f; } /** * Don't call this method. * @return */ public int[][] getSegments() { return new int[0][]; } /** * * @return */ public String getString() { StringBuffer sb = new StringBuffer("estiamte: "); sb.append(bytesPerSec); sb.append(" (").append(limitEstimateType).append(") "); return sb.toString(); } }//class SMConfigLimitEstimate } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/PingSourceStats.java0000644000175000017500000001122610643623054027364 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import com.aelitis.azureus.core.util.average.AverageFactory; import com.aelitis.azureus.core.util.average.Average; import com.aelitis.azureus.core.speedmanager.SpeedManagerPingSource; /** * Created on May 8, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ /** * Keeps the ping time stats for a single source. Should calculate averages for the data. * */ public class PingSourceStats { final SpeedManagerPingSource source; double currPing; Average shortTerm = AverageFactory.MovingImmediateAverage( 3 ); Average medTerm = AverageFactory.MovingImmediateAverage( 6 ); Average longTerm = AverageFactory.MovingImmediateAverage( 10 ); Average forChecks = AverageFactory.MovingImmediateAverage( 100 ); public PingSourceStats(SpeedManagerPingSource _source){ source = _source; } public void madeChange(){ //want to make all the values NAN until it is ready to compare again. } public void addPingTime(int ping){ currPing = (double) ping; shortTerm.update( (double)ping ); medTerm.update( (double)ping ); longTerm.update( (double)ping ); } /** * Speculative method to see if it can determine a trend. The larger the number * the stronger the trend. * @return current - interger. A positive number is an increasing trend. A negative number is a decreasing trend. */ public int getTrend(){ int retVal = 0; //based on current ping values. if(currPing<0.0){ retVal--; }else{ if( currPing < shortTerm.getAverage() ){ retVal++; }else{ retVal--; } if( currPing < medTerm.getAverage() ){ retVal++; }else{ retVal--; } if( currPing < longTerm.getAverage() ){ retVal++; }else{ retVal--; } } //compare shortTerm and medium term averages. if(shortTerm.getAverage() < medTerm.getAverage() ){ retVal++; }else{ retVal--; } //compare short-term with long term. if(shortTerm.getAverage() < longTerm.getAverage() ){ retVal++; }else{ retVal--; } //compare medium-term with long-term. if(medTerm.getAverage() < longTerm.getAverage() ){ retVal++; }else{ retVal--; } //modify results based on absolute ping values. final int ABSOLUTE_GOOD_PING_VALUE = 30; if(currPingABSOLUTE_BAD_PING_VALUE){ retVal--; } if(shortTerm.getAverage()>ABSOLUTE_BAD_PING_VALUE){ retVal--; } if(medTerm.getAverage()>ABSOLUTE_BAD_PING_VALUE){ retVal--; } if(longTerm.getAverage()>ABSOLUTE_BAD_PING_VALUE){ retVal--; } return retVal; }//getTrend /** * Get the long-term average. * @return Average - longTerm */ public Average getLongTermAve(){ return longTerm; } /** * Get the average that should be used for checking ping times. * @return - ping time of history. */ public Average getHistory(){ return forChecks; } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMapper.java0000644000175000017500000002323710646001200027274 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; /** * Created on Jun 14, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ /** * Classifies the ping-times and then maps them against the a * grid of upload and download rates. * * Create a two dimensional map of upload and download rates. Map onto this * space ping times. * * The mesh size will be smaller near zero, and larger higher up. * * 0 - 100 kByte/sec - 10 kBytes mesh size. * 100 - 500 kBytes/sec - 50 kBytes mesh size. * 500 - 5000 kBytes/sec - 100 kBytes mesh size. * Anything above 5 MBytes/sec is one region. * */ public class PingSpaceMapper { //ToDo: use the SpeedManagerPingMapper interface and move this up a level. GridRegion[][] gridRegion; //here upIndex,downIndex int lastDownloadBitsPerSec; int lastUploadBitsPerSec; int goodPingInMilliSec; int badPingInMilliSec; int totalPointsInMap = 0; private static final int maxMeshIndex=70; /** * Create a grid and define good and bad ping times. * @param _goodPingInMilliSec - * @param _badPingInMilliSec - */ public PingSpaceMapper(int _goodPingInMilliSec, int _badPingInMilliSec){ createNewGrid(); goodPingInMilliSec = _goodPingInMilliSec; badPingInMilliSec = _badPingInMilliSec; } private void createNewGrid() { //create the mesh. We will have 70 by 70 grid. Even though we only use 63. gridRegion = null; gridRegion = new GridRegion[maxMeshIndex][maxMeshIndex]; for(int upIndex=0;upIndex mesh index calculation. * @param meshIndex - value between 0 and 70 * @return lowest BitsPerSecond that meets that criteria. */ private int convertMeshIndex2bitsPerSec(int meshIndex){ int bytesPerSec=0; if(meshIndex<=0){ return 0; } if(meshIndex<=10){ bytesPerSec = meshIndex*10; }else if(meshIndex<=18){ bytesPerSec = 100 + (meshIndex-10) * 50; }else{ bytesPerSec = 500 + (meshIndex-18) * 100; } return bytesPerSec*1024; }//convertMeshIndex2bitsPerSec public void setCurrentTransferRates(int downloadBitPerSec, int uploadBitsPerSec){ lastDownloadBitsPerSec = downloadBitPerSec; lastUploadBitsPerSec = uploadBitsPerSec; } public void addMetricToMap(int metric){ int downIndex = convertBitsPerSec2meshIndex(lastDownloadBitsPerSec); int upIndex = convertBitsPerSec2meshIndex(lastUploadBitsPerSec); totalPointsInMap++; if( metricgoodPingIndex); } static final int GOOD_PING_INDEX = 0; static final int ANY_PING_INDEX = 1; /** * Look at the Map and find the highest index for each catagory. * @return Result[2], where index 0 is goodPing, index 1 is anyPing */ private Result[] calculate(){ Result[] retVal = new Result[2]; retVal[GOOD_PING_INDEX] = new Result(); retVal[ANY_PING_INDEX] = new Result(); for(int upIndex=0;upIndex0.0f ){ retVal[GOOD_PING_INDEX].checkAndUpdate(upIndex,downIndex); } //Register this grid point if it has any ping values. int count = gridRegion[upIndex][downIndex].getTotal(); if( count>0 ){ retVal[ANY_PING_INDEX].checkAndUpdate(upIndex,downIndex); } }//for }//for return retVal; } /** * Make a guess at the upload capacity based on metric data. * @return - */ public int guessUploadLimit(){ Result result = getHighestMeshIndexWithGoodPing(); int upMeshIndex = result.getUploadIndex(); return convertMeshIndex2bitsPerSec( upMeshIndex ); } /** * Make a guess at the download capacity based on metric data. * @return - */ public int guessDownloadLimit(){ Result result = getHighestMeshIndexWithGoodPing(); int downMeshIndex = result.getDownloadIndex(); return convertMeshIndex2bitsPerSec( downMeshIndex ); } /** * Class to return a result. */ static class Result{ int highestUploadIndex=0; int highestDownloadIndex=0; /** * If the input index is higher then stored, update it with the new value. * @param uploadIndex - * @param downloadIndex - */ public void checkAndUpdate(int uploadIndex, int downloadIndex){ if( uploadIndex>highestUploadIndex ){ highestUploadIndex=uploadIndex; } if( downloadIndex>highestDownloadIndex ){ highestDownloadIndex=downloadIndex; } } public int getUploadIndex(){ return highestUploadIndex; } public int getDownloadIndex(){ return highestDownloadIndex; } }//class Result /** * A region on the grid for accumulating counts. */ static class GridRegion{ public static final int INDEX_PING_GOOD = 0; public static final int INDEX_PING_NEUTRAL = 1; public static final int INDEX_PING_BAD = 2; int pingCount[] = new int[3]; int uploadBound[] = new int[2]; int downloadBound[] = new int[2]; public void incrementMetricCount( int pingIndex){ if(pingIndex>=0 && pingIndex<=3){ ++pingCount[pingIndex]; } }//incrementMetricCount public float getRating(){ int total = getTotal(); if( total==0 ){ return 0.0f; } float score = (pingCount[INDEX_PING_GOOD] + 0.3f * pingCount[INDEX_PING_NEUTRAL] - pingCount[INDEX_PING_BAD]); return ( score / (float) total ); }//getRating public int getTotal(){ return pingCount[INDEX_PING_GOOD] +pingCount[INDEX_PING_NEUTRAL] +pingCount[INDEX_PING_BAD]; }//getTotal }//class } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerLogger.java0000644000175000017500000000260611075015710027756 0ustar adrianadrian/* * Created on Oct 13, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.speedmanager.impl.v2; import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProviderAdapter; public class SpeedManagerLogger { private static String prefix; private static SpeedManagerAlgorithmProviderAdapter adapter; protected static void setAdapter( String _prefix, SpeedManagerAlgorithmProviderAdapter _adapter ) { prefix = _prefix; adapter = _adapter; } public static void log( String str ) { if ( adapter != null ){ adapter.log( prefix + ": " + str ); } } public static void trace( String str ) { } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControlDropUploadFirst.java0000644000175000017500000001567510773040322031717 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; /** * Created on Jul 9, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public class LimitControlDropUploadFirst implements LimitControl { private float valueUp=0.5f;//number between 0.0 - 1.0 int upMax; int upCurr; int upMin; SaturatedMode upUsage; private float valueDown=1.0f; int downMax; int downCurr; int downMin; SaturatedMode downUsage; TransferMode mode; float usedUpMaxDownloadMode=0.6f; boolean isDownloadUnlimited = false; // Here is how the LimitControl will handle the "unlimited" case. // #1) Download is allowed to be unlimited. // #2) Upload is not allowed to be unlimited. // a) Only the isDownloadUlimited boolean and upCurr value - used for unlimited case. // b) In upload unlimited. valueDown is set to 1.0. // c) upMax and upMin values keep there non-zero values. public void updateStatus(int currUpLimit, SaturatedMode uploadUsage, int currDownLimit, SaturatedMode downloadUsage, TransferMode transferMode){ upCurr = currUpLimit; upUsage = uploadUsage; downCurr = currDownLimit; downUsage = downloadUsage; mode=transferMode; } public void setDownloadUnlimitedMode(boolean isUnlimited) { isDownloadUnlimited = isUnlimited; if(isUnlimited){ valueDown = 1.0f; } } public boolean isDownloadUnlimitedMode(){ return isDownloadUnlimited; } public void updateLimits(int _upMax, int _upMin, int _downMax, int _downMin){ //verify the limits. if(_upMax < SMConst.START_UPLOAD_RATE_MAX ){ _upMax = SMConst.START_UPLOAD_RATE_MAX; } if(_downMax < SMConst.START_DOWNLOAD_RATE_MAX){ _downMax = SMConst.START_DOWNLOAD_RATE_MAX; } if(_downMax<_upMax){ _downMax=_upMax; } _upMin = SMConst.calculateMinUpload(_upMax); _downMin = SMConst.calculateMinDownload(_downMax); upMax = _upMax; upMin = _upMin; downMax = _downMax; downMin = _downMin; } private int usedUploadCapacity(){ float usedUpMax = upMax; if( mode.getMode() == TransferMode.State.SEEDING ){ usedUpMax = upMax; }else if( mode.getMode()==TransferMode.State.DOWNLOADING ){ usedUpMax = upMax*usedUpMaxDownloadMode; }else if( mode.getMode()==TransferMode.State.DOWNLOAD_LIMIT_SEARCH ){ usedUpMax = upMax*usedUpMaxDownloadMode; }else if( mode.getMode()==TransferMode.State.UPLOAD_LIMIT_SEARCH ){ usedUpMax = upMax; }else{ SpeedManagerLogger.trace("LimitControlDropUploadFirst -> unrecognized transfer mode. "); } return Math.round( usedUpMax ); } public void updateSeedSettings(float downloadModeUsed) { if( downloadModeUsed < 1.0f && downloadModeUsed > 0.1f){ usedUpMaxDownloadMode = downloadModeUsed; SpeedManagerLogger.trace("LimitControlDropUploadFirst %used upload used while downloading: "+downloadModeUsed); } } public SMUpdate adjust( float amount ){ boolean increase = true; if( amount<0.0f ){ increase = false; } float factor = amount/10.0f; int usedUpMax = usedUploadCapacity(); float gamma = (float) usedUpMax/downMax; if( increase ){ //increase download first if( valueDown<0.99f ){ valueDown = calculateNewValue(valueDown,factor); }else{ //only increase upload if used. if( upUsage==SaturatedMode.AT_LIMIT ){ valueUp = calculateNewValue(valueUp,gamma*0.5f*factor); } } }else{ //decrease upload first if( valueUp > 0.01f){ valueUp = calculateNewValue(valueUp,gamma*factor); }else{ valueDown = calculateNewValue(valueDown,factor); } } return update(); }//adjust private SMUpdate update(){ int upLimit; int downLimit; int usedUpMax = usedUploadCapacity(); upLimit = Math.round( ((usedUpMax-upMin)*valueUp)+upMin ); //ToDo: remove diagnotics later. if( upLimit>upMax || Float.isNaN(valueUp)){ SpeedManagerLogger.trace("Limit - should upload have an unlimited condition? Setting to usedUpMax"); upLimit = usedUpMax; } if(isDownloadUnlimited){ downLimit = SMConst.RATE_UNLIMITED; //zero means to unlimit the download rate. }else{ downLimit = Math.round( ((downMax-downMin)*valueDown)+downMin ); } //Don't show a download limit unless it is needed. if( valueDown == 1.0 ){ downLimit = SMConst.RATE_UNLIMITED; //only apply a limit to the download when needed. } //log this change. StringBuffer msg = new StringBuffer(" create-update: valueUp="+valueUp+",upLimit="+upLimit+",valueDown="); if(valueDown== 1.0 ) msg.append("_unlimited_"); else msg.append(valueDown); msg.append(",downLimit="+downLimit+",upMax="+upMax+",usedUpMax="+usedUpMax+",upMin="+upMin+",downMax="+downMax); msg.append(",downMin="+downMin+",transferMode="+mode.getString()+",isDownUnlimited="+isDownloadUnlimited); SpeedManagerLogger.log( msg.toString() ); return new SMUpdate(upLimit,true,downLimit,true); } private float calculateNewValue(float curr, float amount){ if(Float.isNaN(curr)){ SpeedManagerLogger.trace("calculateNewValue - curr=NaN"); } if(Float.isNaN(amount)){ SpeedManagerLogger.trace("calculateNewValue = amount=NaN"); } curr += amount; if( curr > 1.0f){ curr = 1.0f; } if( curr < 0.0f ){ curr = 0.0f; } if(Float.isNaN(curr)){ curr=0.0f; } return curr; } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/PSMonitorListener.java0000644000175000017500000000235510647253146027677 0ustar adrianadrianpackage com.aelitis.azureus.core.speedmanager.impl.v2; import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate; /** * Created on Jul 16, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. *

    * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

    * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ public interface PSMonitorListener { public void notifyUpload(SpeedManagerLimitEstimate estimate); public void notifyDownload(SpeedManagerLimitEstimate estimate); } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderV2.java0000644000175000017500000001166611075015710032416 0ustar adrianadrian/* * Created on May 7, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager.impl.v2; import com.aelitis.azureus.core.speedmanager.SpeedManagerPingSource; import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProvider; import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProviderAdapter; public class SpeedManagerAlgorithmProviderV2 implements SpeedManagerAlgorithmProvider { private SpeedManagerAlgorithmProviderAdapter adapter; //Test algorithms below. private SpeedManagerAlgorithmProvider strategy; //key names are below. public static final String SETTING_DOWNLOAD_MAX_LIMIT = "SpeedManagerAlgorithmProviderV2.setting.download.max.limit"; public static final String SETTING_UPLOAD_MAX_LIMIT = "SpeedManagerAlgorithmProviderV2.setting.upload.max.limit"; //temporary two names for upload/download max until we sort out which. public static final String SETTING_UPLOAD_LIMIT_ESTIMATE_TYPE_FROM_UI = "AutoSpeed Network Upload Speed Type (temp)"; public static final String SETTING_DOWNLOAD_LIMIT_ESTIMATE_TYPE_FROM_UI = "AutoSpeed Network Download Speed Type (temp)"; //sets the input source, vivaldi, DHT ping, ICMP pint, etc .... public static final String SETTING_DATA_SOURCE_INPUT = "SpeedManagerAlgorithmProviderV2.source.data.input"; //DHT ping settings. public static final String SETTING_DHT_GOOD_SET_POINT = "SpeedManagerAlgorithmProviderV2.setting.dht.good.setpoint"; public static final String SETTING_DHT_GOOD_TOLERANCE = "SpeedManagerAlgorithmProviderV2.setting.dht.good.tolerance"; public static final String SETTING_DHT_BAD_SET_POINT = "SpeedManagerAlgorithmProviderV2.setting.dht.bad.setpoint"; public static final String SETTING_DHT_BAD_TOLERANCE = "SpeedManagerAlgorithmProviderV2.setting.dht.bad.tolerance"; //ping factors settings. public static final String SETTING_WAIT_AFTER_ADJUST = "SpeedManagerAlgorithmProviderV2.setting.wait.after.adjust"; public static final String SETTING_INTERVALS_BETWEEN_ADJUST = "SpeedManagerAlgorithmProviderV2.intervals.between.adjust"; //enable this mode. public static final String SETTING_V2_BETA_ENABLED = "SpeedManagerAlgorithmProviderV2.setting.beta.enabled"; public SpeedManagerAlgorithmProviderV2( SpeedManagerAlgorithmProviderAdapter _adapter ) { adapter = _adapter; SpeedManagerLogger.setAdapter( "v2", adapter ); //strategy = new SpeedManagerAlgorithmProviderDHTPing(_adapter); strategy = new SpeedManagerAlgorithmProviderPingMap(_adapter); } public void destroy() { strategy.destroy(); } public void reset() { strategy.reset(); } public void updateStats() { strategy.updateStats(); } public void pingSourceFound( SpeedManagerPingSource source, boolean is_replacement ) { log( "Found ping source: " + source.getAddress()); strategy.pingSourceFound(source,is_replacement); } public void pingSourceFailed( SpeedManagerPingSource source ) { log( "Lost ping source: " + source.getAddress()); strategy.pingSourceFailed(source); } public void calculate( SpeedManagerPingSource[] sources ) { String str = ""; for (int i=0;i " + sources[i].getPingTime(); } log( "ping-data: " + str ); strategy.calculate(sources); } public int getIdlePingMillis() { return strategy.getIdlePingMillis(); } public int getCurrentPingMillis() { return strategy.getCurrentPingMillis(); } public int getMaxPingMillis() { return strategy.getMaxPingMillis(); } public int getCurrentChokeSpeed() { return strategy.getCurrentChokeSpeed(); } public int getMaxUploadSpeed() { return strategy.getMaxUploadSpeed(); } public boolean getAdjustsDownloadLimits() { // TODO Auto-generated method stub return false; } protected void log( String str ) { SpeedManagerLogger.log( str ); } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerAlgorithmProviderAdapter.javaazureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerAlgorithmProviderAdapter.java0000644000175000017500000000365711075015710033161 0ustar adrianadrian/* * Created on May 7, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager.impl; import com.aelitis.azureus.core.speedmanager.SpeedManager; import com.aelitis.azureus.core.speedmanager.SpeedManagerPingMapper; public interface SpeedManagerAlgorithmProviderAdapter { public SpeedManager getSpeedManager(); public int getCurrentProtocolUploadSpeed(); public int getCurrentDataUploadSpeed(); public int getCurrentUploadLimit(); public void setCurrentUploadLimit( int bytes_per_second ); public int getCurrentProtocolDownloadSpeed(); public int getCurrentDataDownloadSpeed(); public int getCurrentDownloadLimit(); public void setCurrentDownloadLimit(int bytes_per_second); public SpeedManagerPingMapper getPingMapper(); /** * Creates a mapper starting from current time. Must be destroyed by calling "destroy" when * done with * @return */ public SpeedManagerPingMapper createTransientPingMapper(); public void log( String str ); } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/TestPingSourceImpl.java0000644000175000017500000001161210656443216027503 0ustar adrianadrian/* * Created on Aug 8, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager.impl; import java.net.InetSocketAddress; import java.util.*; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import com.aelitis.azureus.core.dht.speed.DHTSpeedTester; import com.aelitis.azureus.core.dht.speed.DHTSpeedTesterContact; import com.aelitis.azureus.core.dht.speed.DHTSpeedTesterContactListener; import com.aelitis.azureus.core.dht.speed.DHTSpeedTesterListener; import com.aelitis.azureus.core.util.CopyOnWriteList; public abstract class TestPingSourceImpl implements DHTSpeedTester { private SpeedManagerAlgorithmProviderAdapter adapter; private volatile int contact_num; private List listeners = new ArrayList(); private CopyOnWriteList sources = new CopyOnWriteList(); private int period; protected TestPingSourceImpl( SpeedManagerAlgorithmProviderAdapter _adapter ) { adapter = _adapter; SimpleTimer.addPeriodicEvent( "TestPingSourceImpl", 1000, new TimerEventPerformer() { private int ticks; public void perform( TimerEvent event ) { ticks++; List sources_to_update; synchronized( sources ){ while( sources.size() < contact_num ){ addContact( new testSource()); } sources_to_update = sources.getList(); } if ( period > 0 ){ if ( ticks % period == 0 ){ testSource[] contacts = new testSource[sources_to_update.size()]; sources_to_update.toArray( contacts ); update( contacts ); } } } }); } protected SpeedManagerAlgorithmProviderAdapter getAdapter() { return( adapter ); } protected void update( testSource[] contacts ) { int[] round_trip_times = new int[contacts.length]; updateSources( contacts ); for (int i=0;i= 0 && rtt < min_rtt ){ min_rtt = rtt; } } String str = ""; int ping_total = 0; int ping_count = 0; for (int i=0;i max_ping ){ max_ping = ping_average; } int up_average = (int)upload_average.getAverage(); // if we're uploading slowly or the current ping rate is better than our current idle average // then we count this towards establishing the baseline if ( up_average <= IDLE_UPLOAD_SPEED || ( running_average < idle_average && !idle_average_set )){ idle_ticks++; if ( idle_ticks >= PING_AVERAGE_HISTORY_COUNT ){ idle_average = Math.max( running_average, MIN_IDLE_AVERAGE ); log( "New idle average: " + idle_average ); idle_average_set = true; } }else{ if ( up_average > max_upload_average ){ max_upload_average = up_average; log( "New max upload:" + max_upload_average ); } idle_ticks = 0; } if ( idle_average_set && running_average < idle_average ){ // bump down if we happen to come across lower idle values idle_average = Math.max( running_average, MIN_IDLE_AVERAGE ); } int current_speed = adapter.getCurrentDataUploadSpeed() + adapter.getCurrentProtocolUploadSpeed(); int current_limit = adapter.getCurrentUploadLimit(); int new_limit = current_limit; log( "Pings: " + str + ", average=" + ping_average +", running_average=" + running_average + ",idle_average=" + idle_average + ", speed=" + current_speed + ",limit=" + current_limit + ",choke = " + (int)choke_speed_average.getAverage()); if ( mode == MODE_FORCED_MAX ){ if ( mode_ticks > FORCED_MAX_TICKS ){ mode = MODE_RUNNING; current_limit = new_limit = saved_limit; } }else if ( mode == MODE_FORCED_MIN ){ if ( idle_average_set || mode_ticks > FORCED_MIN_TICKS ){ log( "Mode -> running" ); if ( !idle_average_set ){ idle_average = Math.max( running_average, MIN_IDLE_AVERAGE ); idle_average_set = true; } mode = MODE_RUNNING; mode_ticks = 0; current_limit = new_limit = saved_limit; }else if ( mode_ticks == 5 ){ // we've had 5 secs of min up speed, clear out the ping average now // to get accurate times ping_average_history.reset(); } } if ( mode == MODE_RUNNING ){ if ( ( ticks > FORCED_MIN_AT_START_TICK_LIMIT && !idle_average_set ) || ( replacement_contacts >= 2 && idle_average_set )){ // we've been running a while but no min set, or we've got some new untested // contacts - force it log( "Mode -> forced min" ); mode = MODE_FORCED_MIN; mode_ticks = 0; saved_limit = current_limit; idle_average_set = false; idle_ticks = 0; replacement_contacts= 0; new_limit = FORCED_MIN_SPEED; }else{ int short_up = (int)upload_short_average.getAverage(); int choke_speed = (int)choke_speed_average.getAverage(); int choke_time = PING_CHOKE_TIME; int latency_factor = LATENCY_FACTOR; if ( running_average < 2* idle_average && ping_average < choke_time ){ direction = INCREASING; int diff = running_average - idle_average; if ( diff < 100 ){ diff = 100; } int increment = 1024 * ( diff / latency_factor ); // if we're close to the last choke-speed then decrease increments int max_inc = MAX_INCREMENT; if ( new_limit + 2*1024 > choke_speed ){ max_inc = 1024; }else if ( new_limit + 5*1024 > choke_speed ){ max_inc += 3*1024; } new_limit += Math.min( increment, max_inc ); }else if ( ping_average > 4*idle_average || ping_average > choke_time ){ if ( direction == INCREASING ){ if ( idle_average_set ){ choke_speed_average.update( short_up ); } } direction = DECREASING; int decrement = 1024 * (( ping_average - (3*idle_average )) / latency_factor ); new_limit -= Math.min( decrement, MAX_DECREMENT ); // don't drop below the current protocol upload speed. This is to address // the situation whereby it is downloading that is choking the line - killing // protocol upspeed kills the downspeed if ( new_limit < upload_short_prot_average.getAverage() + 1024 ){ new_limit = (int)upload_short_prot_average.getAverage() + 1024; } } if ( new_limit < 1024 ){ new_limit = 1024; } } // final tidy up int min_up = MIN_UP; int max_up = MAX_UP; if ( min_up > 0 && new_limit < min_up && mode != MODE_FORCED_MIN ){ new_limit = min_up; }else if ( max_up > 0 && new_limit > max_up && mode != MODE_FORCED_MAX ){ new_limit = max_up; } // if we're not achieving the current limit and the advice is to increase it, don't // bother if ( new_limit > current_limit && current_speed < ( current_limit - 10*1024 )){ new_limit = current_limit; } } // round limit up to nearest K new_limit = (( new_limit + 1023 )/1024) * 1024; adapter.setCurrentUploadLimit( new_limit ); if ( ADJUST_DOWNLOAD_ENABLE && !( Float.isInfinite( ADJUST_DOWNLOAD_RATIO ) || Float.isNaN( ADJUST_DOWNLOAD_RATIO ))){ int dl_limit = (int)(new_limit * ADJUST_DOWNLOAD_RATIO); adapter.setCurrentDownloadLimit( dl_limit ); } } public int getIdlePingMillis() { return( idle_average ); } public int getCurrentPingMillis() { return( (int)ping_average_history.getAverage()); } public int getMaxPingMillis() { return( max_ping ); } /** * Returns the current view of when choking occurs * @return speed in bytes/sec */ public int getCurrentChokeSpeed() { return((int)choke_speed_average.getAverage()); } public int getMaxUploadSpeed() { return( max_upload_average ); } public boolean getAdjustsDownloadLimits() { return( ADJUST_DOWNLOAD_ENABLE ); } protected void log( String str ) { adapter.log( str ); } protected class pingSource { private SpeedManagerPingSource source; private int last_good_ping; private int bad_pings; protected pingSource( SpeedManagerPingSource _source ) { source = _source; } public void pingReceived( int time, boolean good_ping ) { if ( good_ping ){ bad_pings = 0; last_good_ping = time; }else{ bad_pings++; } // three strikes and you're out! if ( bad_pings == 3 ){ source.destroy(); } } } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/TestPingSourceRandom.java0000644000175000017500000000257411012726646030027 0ustar adrianadrian/* * Created on Aug 8, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager.impl; import java.util.Random; public class TestPingSourceRandom extends TestPingSourceImpl { private Random random = new Random(); protected TestPingSourceRandom( SpeedManagerAlgorithmProviderAdapter adapter ) { super( adapter ); } protected void updateSources( testSource[] sources ) { for (int i=0;i 32 ){ Debug.out( "Transient mappers are growing too large" ); } return( res ); } protected void destroy( SpeedManagerPingMapper mapper ) { transient_mappers.remove( mapper ); } public void setSpeedTester( DHTSpeedTester _tester ) { if ( speed_tester != null ){ if ( !emulated_ping_source ){ Debug.out( "speed tester already set!" ); } return; } COConfigurationManager.setParameter( CONFIG_AVAIL, true ); speed_tester = _tester; speed_tester.addListener( new DHTSpeedTesterListener() { private DHTSpeedTesterContact[] last_contact_group = new DHTSpeedTesterContact[0]; public void contactAdded( DHTSpeedTesterContact contact ) { if ( core.getInstanceManager().isLANAddress(contact.getAddress().getAddress())){ contact.destroy(); }else{ log( "activePing: " + contact.getString()); contact.setPingPeriod( CONTACT_PING_SECS ); synchronized( contacts ){ pingContact source = new pingContact( contact ); contacts.put( contact, source ); contacts_array = new pingContact[ contacts.size() ]; contacts.values().toArray( contacts_array ); total_contacts++; provider.pingSourceFound( source, total_contacts > CONTACT_NUMBER ); } contact.addListener( new DHTSpeedTesterContactListener() { public void ping( DHTSpeedTesterContact contact, int round_trip_time ) { } public void pingFailed( DHTSpeedTesterContact contact ) { } public void contactDied( DHTSpeedTesterContact contact ) { log( "deadPing: " + contact.getString()); synchronized( contacts ){ pingContact source = (pingContact)contacts.remove( contact ); if ( source != null ){ contacts_array = new pingContact[ contacts.size() ]; contacts.values().toArray( contacts_array ); provider.pingSourceFailed( source ); } } } }); } } public void resultGroup( DHTSpeedTesterContact[] st_contacts, int[] round_trip_times ) { if ( !enabled ){ for (int i=0;i= 0 ){ if ( rtt > worst_value ){ worst_value = rtt; } if ( rtt < min_value ){ min_value = rtt; } num_values++; total += rtt; } source.setPingTime( rtt ); }else{ miss = true; } } } if ( miss ){ Debug.out( "Auto-speed: source missing" ); }else{ provider.calculate( sources ); // remove worst value if we have > 1 if ( num_values > 1 ){ total -= worst_value; num_values--; } if ( num_values > 0 ){ int average = total/num_values; // bias towards min average = ( average + min_value ) / 2; addPingHistory( average, sources_changed ); } } } }); SimpleTimer.addPeriodicEvent( "SpeedManager:stats", SpeedManagerAlgorithmProvider.UPDATE_PERIOD_MILLIS, new TimerEventPerformer() { public void perform( TimerEvent event ) { if ( enabled ){ provider.updateStats(); } } }); } protected void addPingHistory( int rtt, boolean re_base ) { int x = (adapter.getCurrentDataUploadSpeed(SPEED_AVERAGE_PERIOD) + adapter.getCurrentProtocolUploadSpeed(SPEED_AVERAGE_PERIOD)); int y = (adapter.getCurrentDataDownloadSpeed(SPEED_AVERAGE_PERIOD) + adapter.getCurrentProtocolDownloadSpeed(SPEED_AVERAGE_PERIOD)); for (int i=0;i= 0 && rtt < min_rtt ){ min_rtt = rtt; } } String str = ""; int ping_total = 0; int ping_count = 0; for (int i=0;i max_ping ){ max_ping = ping_average; } int up_average = (int)upload_average.getAverage(); // if we're uploading slowly or the current ping rate is better than our current idle average // then we count this towards establishing the baseline if ( up_average <= IDLE_UPLOAD_SPEED || ( running_average < idle_average && !idle_average_set )){ idle_ticks++; if ( idle_ticks >= PING_AVERAGE_HISTORY_COUNT ){ idle_average = Math.max( running_average, MIN_IDLE_AVERAGE ); log( "New idle average: " + idle_average ); idle_average_set = true; } }else{ if ( up_average > max_upload_average ){ max_upload_average = up_average; log( "New max upload:" + max_upload_average ); } idle_ticks = 0; } if ( idle_average_set && running_average < idle_average ){ // bump down if we happen to come across lower idle values idle_average = Math.max( running_average, MIN_IDLE_AVERAGE ); } int current_speed = adapter.getCurrentDataUploadSpeed() + adapter.getCurrentProtocolUploadSpeed(); int current_limit = adapter.getCurrentUploadLimit(); int new_limit = current_limit; log( "Pings: " + str + ", average=" + ping_average +", running_average=" + running_average + ",idle_average=" + idle_average + ", speed=" + current_speed + ",limit=" + current_limit + ",choke = " + (int)choke_speed_average.getAverage()); if ( mode == MODE_FORCED_MAX ){ if ( mode_ticks > FORCED_MAX_TICKS ){ mode = MODE_RUNNING; current_limit = new_limit = saved_limit; } }else if ( mode == MODE_FORCED_MIN ){ if ( idle_average_set || mode_ticks > FORCED_MIN_TICKS ){ log( "Mode -> running" ); if ( !idle_average_set ){ idle_average = Math.max( running_average, MIN_IDLE_AVERAGE ); idle_average_set = true; } mode = MODE_RUNNING; mode_ticks = 0; current_limit = new_limit = saved_limit; }else if ( mode_ticks == 5 ){ // we've had 5 secs of min up speed, clear out the ping average now // to get accurate times ping_average_history.reset(); } } if ( mode == MODE_RUNNING ){ if ( ( ticks > FORCED_MIN_AT_START_TICK_LIMIT && !idle_average_set ) || ( replacement_contacts >= 2 && idle_average_set )){ // we've been running a while but no min set, or we've got some new untested // contacts - force it log( "Mode -> forced min" ); mode = MODE_FORCED_MIN; mode_ticks = 0; saved_limit = current_limit; idle_average_set = false; idle_ticks = 0; replacement_contacts= 0; new_limit = FORCED_MIN_SPEED; }else{ limiter.setDlSpeed(adapter.getCurrentDataDownloadSpeed()); limiter.setUlSpeed(adapter.getCurrentDataUploadSpeed()); limiter.setMaxDlSpeed(adapter.getSpeedManager().getEstimatedDownloadCapacityBytesPerSec().getBytesPerSec()); limiter.setMaxUlSpeed(adapter.getSpeedManager().getEstimatedUploadCapacityBytesPerSec().getBytesPerSec()); limiter.setLatency(ping_average); limiter.setMinLatency(idle_average); limiter.setMaxLatency(1500); if(limiter.shouldLimitDownload()) { adapter.setCurrentDownloadLimit( (int) limiter.getDownloadLimit() ); } else { adapter.setCurrentDownloadLimit(0); } if(limiter.shouldLimitUpload()) { adapter.setCurrentUploadLimit( (int) limiter.getUploadLimit() ); } else { adapter.setCurrentUploadLimit(0); } } } } public int getIdlePingMillis() { return( idle_average ); } public int getCurrentPingMillis() { return( (int)ping_average_history.getAverage()); } public int getMaxPingMillis() { return( max_ping ); } /** * Returns the current view of when choking occurs * @return speed in bytes/sec */ public int getCurrentChokeSpeed() { return((int)choke_speed_average.getAverage()); } public int getMaxUploadSpeed() { return( max_upload_average ); } public boolean getAdjustsDownloadLimits() { return( ADJUST_DOWNLOAD_ENABLE ); } protected void log( String str ) { adapter.log( str ); } protected class pingSource { private SpeedManagerPingSource source; private int last_good_ping; private int bad_pings; protected pingSource( SpeedManagerPingSource _source ) { source = _source; } public void pingReceived( int time, boolean good_ping ) { if ( good_ping ){ bad_pings = 0; last_good_ping = time; }else{ bad_pings++; } // three strikes and you're out! if ( bad_pings == 3 ){ source.destroy(); } } } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerPingMapperImpl.java0000644000175000017500000011052211164317360031076 0ustar adrianadrian/* * Created on Jul 6, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager.impl; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Random; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate; import com.aelitis.azureus.core.speedmanager.SpeedManagerPingMapper; import com.aelitis.azureus.core.speedmanager.SpeedManagerPingZone; class SpeedManagerPingMapperImpl implements SpeedManagerPingMapper { static final int VARIANCE_GOOD_VALUE = 50; static final int VARIANCE_BAD_VALUE = 150; static final int VARIANCE_MAX = VARIANCE_BAD_VALUE*10; static final int RTT_BAD_MIN = 350; static final int RTT_BAD_MAX = 500; static final int RTT_MAX = 30*1000; // don't make this too large as we don't start considering capacity decreases until this // is full static final int MAX_BAD_LIMIT_HISTORY = 16; static final int SPEED_DIVISOR = 256; private static final int SPEED_HISTORY_PERIOD = 3*60*1000; // 3 min private static final int SPEED_HISTORY_COUNT = SPEED_HISTORY_PERIOD / SpeedManagerImpl.UPDATE_PERIOD_MILLIS; private SpeedManagerImpl speed_manager; private String name; private boolean variance; private boolean trans; private int ping_count; private pingValue[] pings; private int max_pings; private pingValue prev_ping; private int[] x_speeds = new int[ SPEED_HISTORY_COUNT ]; private int[] y_speeds = new int[ SPEED_HISTORY_COUNT ]; private int speeds_next; private LinkedList regions; private int last_x; private int last_y; private int[] recent_metrics = new int[3]; private int recent_metrics_next; private limitEstimate up_estimate; private limitEstimate down_estimate; private LinkedList last_bad_ups; private LinkedList last_bad_downs; private static final int BAD_PROGRESS_COUNTDOWN = 5; private limitEstimate last_bad_up; private int bad_up_in_progress_count; private limitEstimate last_bad_down; private int bad_down_in_progress_count; private limitEstimate best_good_up; private limitEstimate best_good_down; private limitEstimate up_capacity = getNullLimit(); private limitEstimate down_capacity = getNullLimit(); private File history_file; protected SpeedManagerPingMapperImpl( SpeedManagerImpl _speed_manager, String _name, int _entries , boolean _variance, boolean _transient ) { speed_manager = _speed_manager; name = _name; max_pings = _entries; variance = _variance; trans = _transient; init(); } protected void init() { pings = new pingValue[max_pings]; ping_count = 0; regions = new LinkedList(); up_estimate = getNullLimit(); down_estimate = getNullLimit(); last_bad_ups = new LinkedList(); last_bad_downs = new LinkedList(); last_bad_up = null; bad_up_in_progress_count = 0; last_bad_down = null; bad_down_in_progress_count = 0; best_good_up = null; best_good_down = null; up_capacity = getNullLimit(); down_capacity = getNullLimit(); prev_ping = null; recent_metrics_next = 0; } protected synchronized void loadHistory( File file ) { try{ if ( history_file != null && history_file.equals( file )){ return; } if ( history_file != null ){ saveHistory(); } history_file = file; init(); if ( history_file.exists()){ // skip key intern to save CPU as there are a lot of keys // and we end up ditching the map after it's processed Map map = FileUtil.readResilientFile( history_file.getParentFile(), history_file.getName(), false, false ); List p = (List)map.get( "pings" ); if ( p != null ){ for (int i=0;i VARIANCE_MAX ){ metric = VARIANCE_MAX; } }else{ if ( metric > RTT_MAX ){ metric = RTT_MAX; } } addPingSupport( x, y, -1, metric ); } } last_bad_ups = loadLimits( map, "lbus" ); last_bad_downs = loadLimits( map, "lbds" ); if ( last_bad_ups.size() > 0 ){ last_bad_up = (limitEstimate)last_bad_ups.get(last_bad_ups.size()-1); } if ( last_bad_downs.size() > 0 ){ last_bad_down = (limitEstimate)last_bad_downs.get(last_bad_downs.size()-1); } best_good_up = loadLimit((Map)map.get( "bgu" )); best_good_down = loadLimit((Map)map.get( "bgd" )); up_capacity = loadLimit((Map)map.get( "upcap" )); down_capacity = loadLimit((Map)map.get( "downcap" )); log( "Loaded " + ping_count + " entries from " + history_file + ": bad_up=" + getLimitString(last_bad_ups) + ", bad_down=" + getLimitString(last_bad_downs)); } prev_ping = null; recent_metrics_next = 0; updateLimitEstimates(); }catch( Throwable e ){ Debug.printStackTrace(e); } } protected synchronized void saveHistory() { try{ if ( history_file == null ){ return; } Map map = new HashMap(); List p = new ArrayList(ping_count); // NOTE: add to this you will need to modify the "reset" method appropriately map.put( "pings", p ); for (int i=0;i 65535 )x = 65535; if ( y > 65535 )y = 65535; addSpeedSupport( x, y ); } protected synchronized void addSpeedSupport( int x, int y ) { x_speeds[speeds_next] = x; y_speeds[speeds_next] = y; speeds_next = (speeds_next+1)%SPEED_HISTORY_COUNT; int min_x = Integer.MAX_VALUE; int min_y = Integer.MAX_VALUE; for (int i=0;i up_capacity.getBytesPerSec()){ up_capacity.setBytesPerSec( min_x ); up_capacity.setMetricRating( 0 ); up_capacity.setEstimateType( SpeedManagerLimitEstimate.TYPE_ESTIMATED); speed_manager.informUpCapChanged(); } } if ( down_capacity.getEstimateType() != SpeedManagerLimitEstimate.TYPE_MANUAL){ if ( min_y > down_capacity.getBytesPerSec()){ down_capacity.setBytesPerSec( min_y ); down_capacity.setMetricRating( 0 ); down_capacity.setEstimateType( SpeedManagerLimitEstimate.TYPE_ESTIMATED); speed_manager.informDownCapChanged(); } } } protected synchronized void addPing( int x, int y, int rtt, boolean re_base ) { x = x/SPEED_DIVISOR; y = y/SPEED_DIVISOR; if ( x > 65535 )x = 65535; if ( y > 65535 )y = 65535; if ( rtt > 65535 )rtt = variance?VARIANCE_MAX:RTT_MAX; if ( rtt == 0 )rtt = 1; // ping time won't refer to current x+y due to latencies, apply to average between // current and previous int average_x = (x + last_x )/2; int average_y = (y + last_y )/2; last_x = x; last_y = y; x = average_x; y = average_y; int metric; if ( variance ){ if ( re_base ){ log( "Re-based variance" ); recent_metrics_next = 0; } recent_metrics[recent_metrics_next++%recent_metrics.length] = rtt; int var_metric = 0; int rtt_metric = 0; if ( recent_metrics_next > 1 ){ int entries = Math.min( recent_metrics_next, recent_metrics.length ); int total = 0; for (int i=0;i= RTT_BAD_MAX ){ rtt_metric = VARIANCE_BAD_VALUE; }else if ( average_rtt > RTT_BAD_MIN ){ int rtt_diff = RTT_BAD_MAX - RTT_BAD_MIN; int rtt_base = average_rtt - RTT_BAD_MIN; rtt_metric = VARIANCE_GOOD_VALUE + (( VARIANCE_BAD_VALUE - VARIANCE_GOOD_VALUE ) * rtt_base ) / rtt_diff; } } } metric = Math.max( var_metric, rtt_metric ); if ( metric < VARIANCE_BAD_VALUE ){ addSpeedSupport( x, y ); }else{ addSpeedSupport( 0, 0 ); } }else{ metric = rtt; } region new_region = addPingSupport( x, y, rtt, metric ); updateLimitEstimates(); if ( variance ){ String up_e = getShortString( getEstimatedUploadLimit( false )) + "," + getShortString(getEstimatedUploadLimit( true )) + "," + getShortString(getEstimatedUploadCapacityBytesPerSec()); String down_e = getShortString(getEstimatedDownloadLimit( false )) + "," + getShortString(getEstimatedDownloadLimit( true )) + "," + getShortString(getEstimatedDownloadCapacityBytesPerSec()); log( "Ping: rtt="+rtt+",x="+x+",y="+y+",m="+metric + (new_region==null?"":(",region=" + new_region.getString())) + ",mr=" + getCurrentMetricRating() + ",up=[" + up_e + (best_good_up==null?"":(":"+getShortString(best_good_up))) + "],down=[" + down_e + (best_good_down==null?"":(":"+getShortString(best_good_down))) + "]" + ",bu="+getLimitStr(last_bad_ups,true)+",bd="+getLimitStr(last_bad_downs,true)); } } protected region addPingSupport( int x, int y, int rtt, int metric ) { if ( ping_count == pings.length ){ // discard oldest pings and reset int to_discard = pings.length/10; if ( to_discard < 3 ){ to_discard = 3; } ping_count = pings.length - to_discard; System.arraycopy(pings, to_discard, pings, 0, ping_count); for (int i=0;i best_good.getWhen()){ persistent_limit = last_bad; }else{ if ( best_good.getBytesPerSec() > last_bad.getBytesPerSec()){ persistent_limit = best_good; }else{ persistent_limit = last_bad; } } }else if ( best_good != null ){ persistent_limit = best_good; }else if ( last_bad != null ){ persistent_limit = last_bad; } if ( persistent_limit == null ){ return( estimate ); } if ( estimate.getBytesPerSec() > persistent_limit.getBytesPerSec()){ return( estimate ); }else{ // need to convert this into a good rating to correspond to the // actual estimate type we have limitEstimate res = estimate.getClone(); res.setBytesPerSec(persistent_limit.getBytesPerSec()); return( res ); } }else{ return( estimate ); } } protected void updateLimitEstimates() { double cm = getCurrentMetricRating(); up_estimate = getEstimatedLimit( true ); if ( up_estimate != null ){ double metric = up_estimate.getMetricRating(); if ( metric == -1 ){ if ( bad_up_in_progress_count == 0 ){ // don't count the duplicates we naturally get when sitting here with a bad limit // and nothing going on to change this situation if ( last_bad_up == null || last_bad_up.getBytesPerSec() != up_estimate.getBytesPerSec()){ bad_up_in_progress_count = BAD_PROGRESS_COUNTDOWN; last_bad_ups.addLast( up_estimate ); if ( last_bad_ups.size() > MAX_BAD_LIMIT_HISTORY ){ last_bad_ups.removeFirst(); } checkCapacityDecrease( true, up_capacity, last_bad_ups ); } } last_bad_up = up_estimate; }else if ( metric == 1 ){ if ( best_good_up == null ){ best_good_up = up_estimate; }else{ if ( best_good_up.getBytesPerSec() < up_estimate.getBytesPerSec()){ best_good_up = up_estimate; } } } if ( bad_up_in_progress_count > 0 ){ if ( cm == -1 ){ bad_up_in_progress_count = BAD_PROGRESS_COUNTDOWN; }else if ( cm == 1 ){ bad_up_in_progress_count--; } } } down_estimate = getEstimatedLimit( false ); if ( down_estimate != null ){ double metric = down_estimate.getMetricRating(); if ( metric == -1 ){ if ( bad_down_in_progress_count == 0 ){ if ( last_bad_down == null || last_bad_down.getBytesPerSec() != down_estimate.getBytesPerSec()){ bad_down_in_progress_count = BAD_PROGRESS_COUNTDOWN; last_bad_downs.addLast( down_estimate ); if ( last_bad_downs.size() > MAX_BAD_LIMIT_HISTORY ){ last_bad_downs.removeFirst(); } checkCapacityDecrease( false, down_capacity, last_bad_downs ); } } last_bad_down = down_estimate; }else if ( metric == 1 ){ if ( best_good_down == null ){ best_good_down = down_estimate; }else{ if ( best_good_down.getBytesPerSec() < down_estimate.getBytesPerSec()){ best_good_down = down_estimate; } } } if ( bad_down_in_progress_count > 0 ){ if ( cm == -1 ){ bad_down_in_progress_count = BAD_PROGRESS_COUNTDOWN; }else if ( cm == 1 ){ bad_down_in_progress_count--; } } } } protected void checkCapacityDecrease( boolean is_up, limitEstimate capacity, LinkedList bads ) { if ( capacity.getEstimateType() == SpeedManagerLimitEstimate.TYPE_MANUAL){ return; } if ( bads.size() < MAX_BAD_LIMIT_HISTORY ){ return; } // remeber, 0 means UNLIMITED!!! int cap = capacity.getBytesPerSec(); // sanity check if ( cap > 0 && cap < 10*1024 ){ return; } List b = new ArrayList( bads ); Collections.sort( b, new Comparator() { public int compare( Object o1, Object o2 ) { limitEstimate l1 = (limitEstimate)o1; limitEstimate l2 = (limitEstimate)o2; return( l1.getBytesPerSec() - l2.getBytesPerSec()); } }); // drop top bottom quarter of measurements int start = MAX_BAD_LIMIT_HISTORY/4; int end = MAX_BAD_LIMIT_HISTORY - start; int total = 0; int num = 0; for (int i=start;i 0 && average >= cap ){ log( "Not reducing " + (is_up?"up":"down") + " capacity - average=" + DisplayFormatters.formatByteCountToKiBEtcPerSec( average ) + ",capacity=" + DisplayFormatters.formatByteCountToKiBEtcPerSec( cap )); return; } int total_deviation = 0; for (int i=start;i -1 = relative goodness of metric * @return */ public float getMetricRating(); public int[][] getSegments(); public String getString(); } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/SpeedManagerListener.java0000644000175000017500000000231310645071302027030 0ustar adrianadrian/* * Created on Jul 10, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager; public interface SpeedManagerListener { public static final int PR_ASN = 1; public static final int PR_UP_CAPACITY = 2; public static final int PR_DOWN_CAPACITY = 3; public void propertyChanged( int property ); } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/SpeedManagerFactory.java0000644000175000017500000000243610406634550026665 0ustar adrianadrian/* * Created on 16-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerImpl; public class SpeedManagerFactory { public static SpeedManager createSpeedManager( AzureusCore core, SpeedManagerAdapter adapter ) { return( new SpeedManagerImpl( core, adapter )); } } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/SpeedManagerPingSource.java0000644000175000017500000000223010620017470027316 0ustar adrianadrian/* * Created on 22-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager; import java.net.InetSocketAddress; public interface SpeedManagerPingSource { public InetSocketAddress getAddress(); public int getPingTime(); public void destroy(); } azureus-4.3.0.6/com/aelitis/azureus/core/speedmanager/SpeedManagerAdapter.java0000644000175000017500000000317610641337734026645 0ustar adrianadrian/* * Created on 16-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.speedmanager; public interface SpeedManagerAdapter { public int getCurrentProtocolUploadSpeed( int average_period ); public int getCurrentDataUploadSpeed( int average_period ); public int getCurrentUploadLimit(); public void setCurrentUploadLimit( int bytes_per_second ); public int getCurrentDownloadLimit(); public void setCurrentDownloadLimit( int bytes_per_second ); public int getCurrentProtocolDownloadSpeed( int average_period ); public int getCurrentDataDownloadSpeed( int average_period ); public Object getLimits(); public void setLimits( Object limits, boolean do_up, boolean do_down ); } azureus-4.3.0.6/com/aelitis/azureus/core/cnetwork/0000755000175000017500000000000011310377620021330 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/cnetwork/ContentNetworkManager.java0000644000175000017500000000304411145221760026452 0ustar adrianadrian/* * Created on Nov 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.cnetwork; public interface ContentNetworkManager { public ContentNetwork[] getContentNetworks(); public ContentNetwork getContentNetwork( long id ); public ContentNetwork getStartupContentNetwork(); /** * Checks networks for those that have this URL as their site * @return matching network, null if none */ public ContentNetwork getContentNetworkForURL( String url ); /** * {@link ContentNetworkListener#networkAdded(ContentNetwork)} will be called * once the network is added */ public void addContentNetwork( long id ) throws ContentNetworkException; public void addListener( ContentNetworkListener listener ); public void removeListener( ContentNetworkListener listener ); } azureus-4.3.0.6/com/aelitis/azureus/core/cnetwork/ContentNetworkException.java0000644000175000017500000000206311113404416027032 0ustar adrianadrian/* * Created on Nov 26, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.cnetwork; public class ContentNetworkException extends Exception { public ContentNetworkException( String str ) { super( str ); } public ContentNetworkException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/com/aelitis/azureus/core/cnetwork/impl/0000755000175000017500000000000011310377620022271 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuzeGeneric.java0000644000175000017500000003331111307366134030274 0ustar adrianadrian/* * Created by Paul Gardner * Created on Nov 25, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.cnetwork.impl; import java.io.IOException; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.UrlUtils; import com.aelitis.azureus.core.crypto.VuzeCryptoManager; import com.aelitis.azureus.util.ImportExportUtils; public class ContentNetworkVuzeGeneric extends ContentNetworkImpl { private static String URL_SUFFIX; static{ COConfigurationManager.addAndFireParameterListener( "locale", new ParameterListener(){ public void parameterChanged( String parameterName ) { // Don't change the order of the params as there's some code somewhere // that depends on them (I think its code that removes the azid so // we can fix this up when that code's migrated here I guess URL_SUFFIX = "azid=" + Base32.encode(VuzeCryptoManager.getSingleton().getPlatformAZID()) + "&azv=" + Constants.AZUREUS_VERSION + "&locale=" + Locale.getDefault().toString() + "&os.name=" + UrlUtils.encode(System.getProperty("os.name")); String suffix = System.getProperty("url.suffix", null); if (suffix != null) { URL_SUFFIX += "&" + suffix; } } }); } private Map service_map = new HashMap(); private Set service_exclusions; private String SITE_HOST; private String URL_PREFIX; private String URL_ICON; private String URL_RELAY_RPC; private String URL_AUTHORIZED_RPC; private String URL_FAQ; private String URL_BLOG; private String URL_FORUMS; private String URL_WIKI; public ContentNetworkVuzeGeneric( ContentNetworkManagerImpl _manager, long _content_network, long _version, String _name, Map _pprop_defaults, Set _service_exclusions, String _site_host, String _url_prefix, String _url_icon, String _url_relay_rpc, String _url_authorised_rpc, String _url_faq, String _url_blog, String _url_forums, String _url_wiki ) { super( _manager, TYPE_VUZE_GENERIC, _content_network, _version, _name, _pprop_defaults ); SITE_HOST = _site_host; URL_PREFIX = _url_prefix; URL_ICON = _url_icon; URL_RELAY_RPC = _url_relay_rpc; URL_AUTHORIZED_RPC = _url_authorised_rpc; URL_FAQ = _url_faq; URL_BLOG = _url_blog; URL_FORUMS = _url_forums; URL_WIKI = _url_wiki; service_exclusions = _service_exclusions; init(); } protected ContentNetworkVuzeGeneric( ContentNetworkManagerImpl _manager, Map _map ) throws IOException { super( _manager ); importFromBEncodedMap( _map ); } protected void importFromBEncodedMap( Map map ) throws IOException { super.importFromBEncodedMap( map ); SITE_HOST = ImportExportUtils.importString(map, "vg_site" ); URL_PREFIX = ImportExportUtils.importString(map, "vg_prefix" ); URL_ICON = ImportExportUtils.importString(map, "vg_icon" ); URL_RELAY_RPC = ImportExportUtils.importString(map, "vg_relay_rpc" ); URL_AUTHORIZED_RPC = ImportExportUtils.importString(map, "vg_auth_rpc" ); URL_FAQ = ImportExportUtils.importString(map, "vg_faq" ); URL_BLOG = ImportExportUtils.importString(map, "vg_blog" ); URL_FORUMS = ImportExportUtils.importString(map, "vg_forums" ); URL_WIKI = ImportExportUtils.importString(map, "vg_wiki" ); List sex = (List)map.get( "vg_sex" ); if ( sex != null ){ service_exclusions = new HashSet(); for ( Long l: sex ){ service_exclusions.add( l.intValue()); } } init(); } protected void exportToBEncodedMap( Map map ) throws IOException { super.exportToBEncodedMap( map ); ImportExportUtils.exportString(map, "vg_site", SITE_HOST ); ImportExportUtils.exportString(map, "vg_prefix", URL_PREFIX ); ImportExportUtils.exportString(map, "vg_icon", URL_ICON ); ImportExportUtils.exportString(map, "vg_relay_rpc", URL_RELAY_RPC ); ImportExportUtils.exportString(map, "vg_auth_rpc", URL_AUTHORIZED_RPC ); ImportExportUtils.exportString(map, "vg_faq", URL_FAQ ); ImportExportUtils.exportString(map, "vg_blog", URL_BLOG ); ImportExportUtils.exportString(map, "vg_forums", URL_FORUMS ); ImportExportUtils.exportString(map, "vg_wiki", URL_WIKI ); if ( service_exclusions != null ){ List sex = new ArrayList(); for (Integer i: service_exclusions){ sex.add( i.longValue()); } map.put( "vg_sex", sex ); } } protected void init() { service_map.clear(); addService( SERVICE_SEARCH, URL_PREFIX + "search?q=" ); addService( SERVICE_XSEARCH, URL_PREFIX + "xsearch/index.php?q=" ); addService( SERVICE_RPC, "http://vrpc.vuze.com/vzrpc/rpc.php" ); addService( SERVICE_BIG_BROWSE, URL_PREFIX + "browse.start?" ); addService( SERVICE_PUBLISH, URL_PREFIX + "publish.start?" ); addService( SERVICE_WELCOME, URL_PREFIX + "welcome.start?" ); addService( SERVICE_ABOUT, URL_PREFIX + "about.start?" ); addService( SERVICE_PUBLISH_NEW, URL_PREFIX + "publishnew.start?" ); addService( SERVICE_PUBLISH_ABOUT, URL_PREFIX + "publishinfo.start" ); addService( SERVICE_CONTENT_DETAILS, URL_PREFIX + "details/" ); addService( SERVICE_COMMENT, URL_PREFIX + "comment/" ); addService( SERVICE_PROFILE, URL_PREFIX + "profile/" ); addService( SERVICE_TORRENT_DOWNLOAD, URL_PREFIX + "download/" ); addService( SERVICE_SITE, URL_PREFIX ); addService( SERVICE_SUPPORT, URL_PREFIX + "support/" ); addService( SERVICE_LOGIN, URL_PREFIX + "login.start?" ); addService( SERVICE_LOGOUT, URL_PREFIX + "logout.start?" ); addService( SERVICE_REGISTER, URL_PREFIX + "register.start?" ); addService( SERVICE_MY_PROFILE, URL_PREFIX + "profile.start?" ); addService( SERVICE_MY_ACCOUNT, URL_PREFIX + "account.start?" ); addService( SERVICE_SITE_RELATIVE, URL_PREFIX ); addService( SERVICE_ADD_FRIEND, URL_PREFIX + "user/AddFriend.html?" ); addService( SERVICE_SUBSCRIPTION, URL_PREFIX + "xsearch/index.php?" ); addService( SERVICE_AUTHORIZE, URL_PREFIX + "ip.start?" ); addService( SERVICE_GET_ICON, URL_ICON ); addService( SERVICE_PREPLAYBACK, URL_PREFIX + "emp/load/" ); addService( SERVICE_POSTPLAYBACK, URL_PREFIX + "emp/recommend/" ); addService( SERVICE_SIDEBAR_CLOSE, URL_PREFIX + "sidebar.close" ); addService( SERVICE_IDENTIFY, "http://pixel.quantserve.com/pixel/p-64Ix1G_SXwOa-.gif" ); if ( URL_RELAY_RPC != null ){ addService( SERVICE_RELAY_RPC, URL_RELAY_RPC ); } if ( URL_AUTHORIZED_RPC != null ){ addService( SERVICE_AUTH_RPC, URL_AUTHORIZED_RPC ); } if ( URL_FAQ != null ){ addService( SERVICE_FAQ, URL_FAQ ); addService( SERVICE_FAQ_TOPIC, URL_FAQ + "?View=entry&EntryID=" ); } if ( URL_BLOG != null ){ addService( SERVICE_BLOG, URL_BLOG ); } if ( URL_FORUMS != null ){ addService( SERVICE_FORUMS, URL_FORUMS ); } if ( URL_WIKI != null ){ addService( SERVICE_WIKI, URL_WIKI ); } } protected void addService( int type, String url_str ) { service_map.put( type, url_str ); } protected Set getServiceExclusions() { return( service_exclusions ); } public Object getProperty( int property ) { if ( property == PROPERTY_SITE_HOST ){ return( SITE_HOST ); }else if ( property == PROPERTY_REMOVEABLE ){ return( getID() != CONTENT_NETWORK_VUZE ); }else if ( property == PROPERTY_ORDER ){ return( String.valueOf( getID())); }else{ debug( "Unknown property" ); return( null ); } } public boolean isServiceSupported( int service_type ) { if ( service_exclusions != null && service_exclusions.contains( service_type )){ return( false ); } return( service_map.get( service_type ) != null ); } public String getServiceURL( int service_type ) { return( getServiceURL( service_type, new Object[0])); } public String getServiceURL( int service_type, Object[] params ) { if ( service_exclusions != null && service_exclusions.contains( service_type )){ debug( "Service type '" + service_type + "' is excluded" ); return( null ); } String base = service_map.get( service_type ); if ( base == null ){ debug( "Unknown service type '" + service_type + "'" ); return( null ); } switch( service_type ){ case SERVICE_SEARCH:{ String query = (String)params[0]; return( base + UrlUtils.encode(query) + "&" + URL_SUFFIX + "&rand=" + SystemTime.getCurrentTime()); } case SERVICE_XSEARCH:{ String query = (String)params[0]; boolean to_subscribe = (Boolean)params[1]; String url_str = base + UrlUtils.encode(query) + "&" + URL_SUFFIX + "&rand=" + SystemTime.getCurrentTime(); if ( to_subscribe ){ url_str += "&createSubscription=1"; } return( url_str ); } case SERVICE_CONTENT_DETAILS:{ String hash = (String)params[0]; String client_ref = (String)params[1]; String url_str = base + hash + ".html?" + URL_SUFFIX; if ( client_ref != null ){ url_str += "&client_ref=" + UrlUtils.encode( client_ref ); } return( url_str ); } case SERVICE_POSTPLAYBACK: case SERVICE_PREPLAYBACK:{ String hash = (String)params[0]; String url_str = base + hash + "?" + URL_SUFFIX; return( url_str ); } case SERVICE_COMMENT:{ String hash = (String)params[0]; return( base + hash + ".html?" + URL_SUFFIX + "&rnd=" + Math.random()); } case SERVICE_PROFILE:{ String login_id = (String)params[0]; String client_ref = (String)params[1]; return( base + UrlUtils.encode( login_id ) + "?" + URL_SUFFIX + "&client_ref=" + UrlUtils.encode( client_ref )); } case SERVICE_TORRENT_DOWNLOAD:{ String hash = (String)params[0]; String client_ref = (String)params[1]; String url_str = base + hash + ".torrent"; if ( client_ref != null ){ url_str += "?referal=" + UrlUtils.encode( client_ref ); } url_str = appendURLSuffix(url_str, false, true); return( url_str ); } case SERVICE_FAQ_TOPIC:{ String topic = (String)params[0]; return( base + topic ); } case SERVICE_LOGIN:{ String message = (String)params[0]; if ( message == null || message.length() == 0 ){ base += URL_SUFFIX; }else{ base += "msg=" + UrlUtils.encode( message ); base += "&" + URL_SUFFIX; } return( base ); } case SERVICE_MY_PROFILE: case SERVICE_MY_ACCOUNT:{ base += URL_SUFFIX + "&rand=" + SystemTime.getCurrentTime(); return( base ); } case SERVICE_SITE_RELATIVE:{ String relative_url = (String)params[0]; boolean append_suffix = (Boolean)params[1]; base += relative_url.startsWith("/")?relative_url.substring(1):relative_url; if ( append_suffix ){ base = appendURLSuffix( base, false, true ); } return( base ); } case SERVICE_ADD_FRIEND:{ String colour = (String)params[0]; base += "ts=" + Math.random() + "&bg_color=" + colour + "&" + URL_SUFFIX; return( base ); } case SERVICE_SUBSCRIPTION:{ String subs_id = (String)params[0]; base += "subscription=" + subs_id + "&" + URL_SUFFIX; return( base ); } case SERVICE_AUTHORIZE:{ String sourceRef = params.length > 0 ? (String) params[0] : null; if (sourceRef != null) { base += "sourceref=" + UrlUtils.encode(sourceRef) + "&" + URL_SUFFIX; } return( base ); } case SERVICE_BIG_BROWSE: case SERVICE_PUBLISH: case SERVICE_WELCOME: case SERVICE_LOGOUT: case SERVICE_REGISTER:{ return( base + URL_SUFFIX ); } case SERVICE_ABOUT: { // no azid needed (+ makes URL ugly) return base + "azv=" + Constants.AZUREUS_VERSION + "&locale=" + Locale.getDefault().toString(); } default:{ return( base ); } } } public String appendURLSuffix( String url_in, boolean for_post, boolean include_azid ) { if ( url_in.indexOf( "azid=" ) != -1 ){ // already present return( url_in ); } String suffix = URL_SUFFIX; if ( !include_azid ){ suffix = suffix.replaceAll( "azid=.*?&", "" ); } if ( for_post ){ if ( url_in.length() == 0 ){ return( suffix ); }else{ return( url_in + "&" + suffix ); } }else{ if ( url_in.indexOf("?") >= 0 ){ return( url_in + "&" + suffix ); }else{ return( url_in + "?" + suffix ); } } } } azureus-4.3.0.6/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkImpl.java0000644000175000017500000002320111137476130026743 0ustar adrianadrian/* * Created on Nov 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.cnetwork.impl; import java.io.IOException; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.BEncoder; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.cnetwork.*; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.core.vuzefile.VuzeFileComponent; import com.aelitis.azureus.core.vuzefile.VuzeFileHandler; import com.aelitis.azureus.util.ImportExportUtils; import com.aelitis.azureus.util.MapUtils; public abstract class ContentNetworkImpl implements ContentNetwork { protected static final long TYPE_VUZE_GENERIC = 1; private static final String PP_STARTUP_NETWORK = "startup_network"; // Boolean protected static ContentNetworkImpl importFromBEncodedMapStatic( ContentNetworkManagerImpl manager, Map map ) throws IOException { long type = ImportExportUtils.importLong( map, "type" ); if ( type == TYPE_VUZE_GENERIC ){ return( new ContentNetworkVuzeGeneric( manager, map )); }else{ throw( new IOException( "Unsupported network type: " + type )); } } private ContentNetworkManagerImpl manager; private long type; private long version; private long id; private String name; private Map pprop_defaults; private Map transient_properties = Collections.synchronizedMap( new HashMap()); private CopyOnWriteList persistent_listeners = new CopyOnWriteList(); protected ContentNetworkImpl( ContentNetworkManagerImpl _manager, long _type, long _id, long _version, String _name, Map _pprop_defaults ) { manager = _manager; type = _type; version = _version; id = _id; name = _name; pprop_defaults = _pprop_defaults; } protected ContentNetworkImpl( ContentNetworkManagerImpl _manager ) { manager = _manager; } protected void importFromBEncodedMap( Map map ) throws IOException { type = ImportExportUtils.importLong( map, "type" ); id = ImportExportUtils.importLong( map, "id" ); version = ImportExportUtils.importLong( map, "version" ); name = ImportExportUtils.importString( map, "name" ); pprop_defaults = (Map)map.get( "pprop_defaults" ); } protected void exportToBEncodedMap( Map map ) throws IOException { ImportExportUtils.exportLong( map, "type", type ); ImportExportUtils.exportLong( map, "id", id ); ImportExportUtils.exportLong( map, "version", version ); ImportExportUtils.exportString( map, "name", name ); if ( pprop_defaults != null ){ map.put( "pprop_defaults", pprop_defaults ); } } protected void updateFrom( ContentNetworkImpl other ) throws IOException { Map map = new HashMap(); other.exportToBEncodedMap(map); importFromBEncodedMap( map ); } public long getID() { return( id ); } protected long getVersion() { return( version ); } public String getName() { return( name ); } protected boolean isSameAs( ContentNetworkImpl other ) { try{ Map map1 = new HashMap(); Map map2 = new HashMap(); exportToBEncodedMap( map1 ); other.exportToBEncodedMap( map2 ); return( BEncoder.mapsAreIdentical( map1, map2 )); }catch( Throwable e ){ Debug.out( e ); return( false ); } } public String getSearchService( String query ) { return( getServiceURL( SERVICE_SEARCH, new Object[]{ query } )); } public String getXSearchService( String query, boolean to_subscribe ) { return( getServiceURL( SERVICE_XSEARCH, new Object[]{ query, to_subscribe } )); } public String getContentDetailsService( String hash, String client_ref ) { return( getServiceURL( SERVICE_CONTENT_DETAILS, new Object[]{ hash, client_ref })); } public String getCommentService( String hash ) { return( getServiceURL( SERVICE_COMMENT, new Object[]{ hash })); } public String getProfileService( String login_id, String client_ref ) { return( getServiceURL( SERVICE_PROFILE, new Object[]{ login_id, client_ref })); } public String getTorrentDownloadService( String hash, String client_ref ) { return( getServiceURL( SERVICE_TORRENT_DOWNLOAD, new Object[]{ hash, client_ref })); } public String getFAQTopicService( String topic ) { return( getServiceURL( SERVICE_FAQ_TOPIC, new Object[]{ topic })); } public String getLoginService( String message ) { return( getServiceURL( SERVICE_LOGIN, new Object[]{ message })); } public String getSiteRelativeURL( String relative_url, boolean append_suffix ) { return( getServiceURL( SERVICE_SITE_RELATIVE, new Object[]{ relative_url, append_suffix })); } public String getAddFriendURL( String colour ) { return( getServiceURL( SERVICE_ADD_FRIEND, new Object[]{ colour })); } public String getSubscriptionURL( String subs_id ) { return( getServiceURL( SERVICE_SUBSCRIPTION, new Object[]{ subs_id })); } public VuzeFile getVuzeFile() { VuzeFile vf = VuzeFileHandler.getSingleton().create(); Map map = new HashMap(); try{ exportToBEncodedMap( map ); vf.addComponent( VuzeFileComponent.COMP_TYPE_CONTENT_NETWORK, map ); }catch( Throwable e ){ Debug.printStackTrace( e ); } return( vf ); } public boolean isStartupNetwork() { if ( hasPersistentProperty( PP_STARTUP_NETWORK )){ return((Boolean)getPersistentProperty( PP_STARTUP_NETWORK )); } return((Boolean)getPersistentProperty( ContentNetwork.PP_IS_CUSTOMIZATION )); } public void setStartupNetwork( boolean b ) { setPersistentProperty( PP_STARTUP_NETWORK, new Boolean(b)); } public void setTransientProperty( Object key, Object value ) { transient_properties.put( key, value ); } public Object getTransientProperty( Object key ) { return( transient_properties.get( key )); } protected String getPropertiesKey() { return( "cnetwork.net." + id + ".props" ); } public void setPersistentProperty( String name, Object new_value ) { synchronized( this ){ String key = getPropertiesKey(); if ( new_value instanceof Boolean ){ new_value = new Long(((Boolean)new_value)?1:0); } Map props = new HashMap( COConfigurationManager.getMapParameter( key , new HashMap())); Object old_value = props.get( key ); if ( BEncoder.objectsAreIdentical( old_value, new_value )){ return; } props.put( name, new_value ); COConfigurationManager.setParameter( key, props ); } Iterator it = persistent_listeners.iterator(); while( it.hasNext()){ try{ ((ContentNetworkPropertyChangeListener)it.next()).propertyChanged(name); }catch( Throwable e ){ Debug.printStackTrace(e); } } } public Object getPersistentProperty( String name ) { synchronized( this ){ String key = getPropertiesKey(); Map props = COConfigurationManager.getMapParameter( key , new HashMap()); if ( name == PP_SOURCE_REF ) { return MapUtils.getMapString(props, name, MapUtils.getMapString( pprop_defaults, name, null)); } Object obj = props.get( name ); if ( name == PP_AUTH_PAGE_SHOWN || name == PP_IS_CUSTOMIZATION || name == PP_ACTIVE || name == PP_SHOW_IN_MENU || name == PP_STARTUP_NETWORK ){ if ( obj == null && pprop_defaults != null ){ obj = pprop_defaults.get( name ); } if ( obj == null ){ return( false ); }else{ return(((Long)obj)==1); } } return( obj ); } } protected boolean hasPersistentProperty( String name ) { synchronized( this ){ String key = getPropertiesKey(); Map props = COConfigurationManager.getMapParameter( key , new HashMap()); return( props.containsKey( name )); } } protected Map getPersistentPropertyDefaults() { return( pprop_defaults ); } public void addPersistentPropertyChangeListener( ContentNetworkPropertyChangeListener listener ) { persistent_listeners.add( listener ); } public void removePersistentPropertyChangeListener( ContentNetworkPropertyChangeListener listener ) { persistent_listeners.remove( listener ); } protected void destroy() { String key = getPropertiesKey(); COConfigurationManager.setParameter( key, new HashMap()); } public void remove() { manager.removeNetwork( this ); } protected void debug( String str ) { Debug.out( getString() + ": " + str ); } protected String getString() { return( getID() + " - " + getName() + ": version=" + getVersion() + ", site=" + getProperty( PROPERTY_SITE_HOST )); } } azureus-4.3.0.6/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuze.java0000644000175000017500000000527211274223200026771 0ustar adrianadrian/* * Created on Nov 24, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.cnetwork.impl; import com.aelitis.azureus.core.cnetwork.ContentNetwork; public class ContentNetworkVuze extends ContentNetworkVuzeGeneric { private static final String DEFAULT_ADDRESS = "client.vuze.com"; //DO NOT TOUCH !!!! use the -Dplatform_address=ip override instead private static final String DEFAULT_PORT = "80"; private static final String DEFAULT_RELAY_ADDRESS = "www.vuze.com"; //DO NOT TOUCH !!!! use the -Drelay_address=ip override instead private static final String DEFAULT_RELAY_PORT = "80"; private static final String URL_ADDRESS = System.getProperty( "platform_address", DEFAULT_ADDRESS ); private static final String URL_PORT = System.getProperty( "platform_port", DEFAULT_PORT ); private static final String URL_PREFIX = "http://" + URL_ADDRESS + ":" + URL_PORT + "/"; private static final String DEFAULT_AUTHORIZED_RPC = "https://" + URL_ADDRESS + ":443/rpc"; private static String URL_RELAY_RPC = System.getProperty("relay_url", "http://" + System.getProperty("relay_address", DEFAULT_RELAY_ADDRESS) + ":" + System.getProperty("relay_port", DEFAULT_RELAY_PORT) + "/msgrelay/rpc"); private static final String URL_AUTHORIZED_RPC = System.getProperty( "authorized_rpc", "1").equals("1") ? DEFAULT_AUTHORIZED_RPC : URL_PREFIX + "app"; private static final String URL_FAQ = "http://faq.vuze.com/"; private static final String URL_BLOG = "http://blog.vuze.com/"; private static final String URL_FORUMS = "http://forum.vuze.com/"; private static final String URL_WIKI = "http://wiki.vuze.com/"; protected ContentNetworkVuze( ContentNetworkManagerImpl manager ) { super( manager, ContentNetwork.CONTENT_NETWORK_VUZE, 1, "Vuze HD Network", null, null, URL_ADDRESS, URL_PREFIX, null, // no icon URL_RELAY_RPC, URL_AUTHORIZED_RPC, URL_FAQ, URL_BLOG, URL_FORUMS, URL_WIKI ); } } azureus-4.3.0.6/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkManagerImpl.java0000644000175000017500000004012411145221762030237 0ustar adrianadrian/* * Created on Nov 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.cnetwork.impl; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator; import org.gudy.azureus2.core3.util.AEDiagnosticsLogger; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkException; import com.aelitis.azureus.core.cnetwork.ContentNetworkListener; import com.aelitis.azureus.core.cnetwork.ContentNetworkManager; import com.aelitis.azureus.core.custom.Customization; import com.aelitis.azureus.core.custom.CustomizationManager; import com.aelitis.azureus.core.custom.CustomizationManagerFactory; import com.aelitis.azureus.core.messenger.PlatformMessengerException; import com.aelitis.azureus.core.messenger.config.PlatformContentNetworkMessenger; import com.aelitis.azureus.core.messenger.config.PlatformContentNetworkMessenger.contentNetworkDetails; import com.aelitis.azureus.core.messenger.config.PlatformContentNetworkMessenger.listNetworksListener; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.core.vuzefile.VuzeFileComponent; import com.aelitis.azureus.core.vuzefile.VuzeFileHandler; import com.aelitis.azureus.core.vuzefile.VuzeFileProcessor; public class ContentNetworkManagerImpl implements ContentNetworkManager, AEDiagnosticsEvidenceGenerator { private static final boolean LOAD_ALL_NETWORKS = true; private static final String CONFIG_FILE = "cnetworks.config"; private static ContentNetworkManagerImpl singleton = new ContentNetworkManagerImpl(); public static void preInitialise() { VuzeFileHandler.getSingleton().addProcessor( new VuzeFileProcessor() { public void process( VuzeFile[] files, int expected_types ) { for (int i=0;i networks = new ArrayList(); private CopyOnWriteList listeners = new CopyOnWriteList(); protected ContentNetworkManagerImpl() { loadConfig(); addNetwork( new ContentNetworkVuze( this )); AEDiagnostics.addEvidenceGenerator( this ); CustomizationManager cust_man = CustomizationManagerFactory.getSingleton(); Customization cust = cust_man.getActiveCustomization(); if ( cust != null ){ String cust_name = COConfigurationManager.getStringParameter( "cnetworks.custom.name", "" ); String cust_version = COConfigurationManager.getStringParameter( "cnetworks.custom.version", "0" ); boolean new_name = !cust_name.equals( cust.getName()); boolean new_version = Constants.compareVersions( cust_version, cust.getVersion() ) < 0; if ( new_name || new_version ){ try{ InputStream[] streams = cust.getResources( Customization.RT_CNETWORKS ); for (int i=0;i 1 || LOAD_ALL_NETWORKS ){ new AEThread2( "CNetwork:init", true ) { public void run() { checkForUpdates(); } }.start(); } } protected void checkForUpdates() { synchronized( this ){ // vuze network always present, no need to check this for updates as we don't auto // update it if ( networks.size() < 2 && !LOAD_ALL_NETWORKS ){ return; } } PlatformContentNetworkMessenger.listNetworksAync(new listNetworksListener() { public void networkListReturned(List cnets) { try{ String str = ""; for ( contentNetworkDetails details: cnets ){ str += (str.length()==0?"":", ") + details.getString(); ContentNetwork existing = getContentNetwork( details.getID()); if ( existing != null ){ ContentNetworkImpl new_net = createNetwork( details ); addNetwork( new_net ); }else{ if ( LOAD_ALL_NETWORKS ){ ContentNetworkImpl new_net = createNetwork( details ); addNetwork( new_net ); } } } log( "Latest networks: " + str ); }catch( Throwable e ){ log( "Failed to load network list", e ); } } }, 11110); } protected ContentNetworkImpl importNetwork( Map content ) throws IOException { ContentNetworkImpl network = ContentNetworkImpl.importFromBEncodedMapStatic( this, content ); return( addNetwork( network )); } // @see com.aelitis.azureus.core.cnetwork.ContentNetworkManager#addContentNetwork(long) public void addContentNetwork( final long id ) throws ContentNetworkException { try{ PlatformContentNetworkMessenger.listNetworksAync(new listNetworksListener() { public void networkListReturned(List cnets) { if (cnets == null) { Exception e = new PlatformMessengerException( "No networks returned" ); for ( ContentNetworkListener l : listeners ) { l.networkAddFailed(id, e); } return; } for ( contentNetworkDetails details: cnets ){ if ( details.getID() == id ){ ContentNetworkImpl new_net; try { new_net = createNetwork( details ); addNetwork( new_net ); } catch (ContentNetworkException e) { for ( ContentNetworkListener l : listeners ) { l.networkAddFailed(id, e); } } return; } } Exception e = new ContentNetworkException( "Content Network with id " + id + " not found"); for ( ContentNetworkListener l : listeners ) { l.networkAddFailed(id, e); } } }, 500); }catch( Throwable e ){ ContentNetworkException e2 = new ContentNetworkException( "Failed to list permitted networks", e ); for ( ContentNetworkListener l : listeners ) { l.networkAddFailed(id, e2); } throw e2; } } public ContentNetwork getContentNetworkForURL( String url ) { try{ String host = new URL( url ).getHost(); for ( ContentNetwork cn: getContentNetworks()){ String site = (String)cn.getProperty( ContentNetwork.PROPERTY_SITE_HOST ); if ( site != null && site.endsWith( host )){ return( cn ); } } }catch( Throwable e ){ Debug.printStackTrace(e); } return( null ); } public ContentNetwork getStartupContentNetwork() { ContentNetwork[] networks = getContentNetworks(); for ( ContentNetwork network: networks ){ if ( network.isStartupNetwork()){ return( network ); } } return( getContentNetwork( ContentNetwork.CONTENT_NETWORK_VUZE )); } protected ContentNetworkImpl createNetwork( contentNetworkDetails details ) throws ContentNetworkException { String main_url = details.getMainURL(); String icon_url = details.getIconURL(); String site_dns; try{ site_dns = new URL( main_url ).getHost(); }catch( Throwable e ){ log( "Failed to get main-url host", e ); throw( new ContentNetworkException( "main url invald", e )); } // propagate persistent property defaults and exclusions as currently not returned by webapp ContentNetworkImpl existing = getContentNetwork( details.getID()); Map pprop_defaults = null; Set service_exclusions = null; if ( existing != null ){ pprop_defaults = existing.getPersistentPropertyDefaults(); if ( existing instanceof ContentNetworkVuzeGeneric ){ service_exclusions = ((ContentNetworkVuzeGeneric)existing).getServiceExclusions(); } } return( new ContentNetworkVuzeGeneric( this, details.getID(), details.getVersion(), details.getName(), pprop_defaults, service_exclusions, site_dns, main_url, icon_url, null, null, null, null, null, null )); } public ContentNetwork[] getContentNetworks() { synchronized( this ){ return((ContentNetwork[])networks.toArray( new ContentNetworkImpl[ networks.size()] )); } } public ContentNetworkImpl getContentNetwork( long id ) { synchronized( this ){ for ( int i=0;i it = networks.iterator(); while( it.hasNext()){ ContentNetworkImpl existing_network = it.next(); if ( existing_network.getID() == network.getID()){ if ( network.getVersion() > existing_network.getVersion()){ try{ existing_network.updateFrom( network ); }catch( Throwable e ){ Debug.printStackTrace( e ); } network = existing_network; replace = true; break; }else{ log( "Network " + existing_network.getString() + " already up to date" ); return( existing_network ); } } } if ( replace ){ log( "Updated network: " + network.getString()); }else{ log( "Added network: " + network.getString()); networks.add( network ); } // we never persist the vuze network if ( network.getID() != ContentNetwork.CONTENT_NETWORK_VUZE ){ saveConfig(); } } Iterator it = (Iterator)listeners.iterator(); while( it.hasNext()){ try{ if ( replace ){ it.next().networkChanged( network ); }else{ it.next().networkAdded( network ); } }catch( Throwable e ){ Debug.out( e ); } } return( network ); } protected void removeNetwork( ContentNetworkImpl network ) { synchronized( this ){ if ( !networks.remove( network )){ return; } network.destroy(); saveConfig(); } log( "Removed network: " + network.getString()); Iterator it = (Iterator)listeners.iterator(); while( it.hasNext()){ try{ it.next().networkRemoved( network ); }catch( Throwable e ){ Debug.out( e ); } } } protected void loadConfig() { if ( FileUtil.resilientConfigFileExists( CONFIG_FILE )){ Map map = FileUtil.readResilientConfigFile( CONFIG_FILE ); List list = (List)map.get( "networks" ); if ( list != null ){ for (int i=0;i it = networks.iterator(); while( it.hasNext()){ ContentNetworkImpl network = it.next(); if ( network.getID() == ContentNetwork.CONTENT_NETWORK_VUZE ){ continue; } Map cnet_map = new HashMap(); try{ network.exportToBEncodedMap( cnet_map ); list.add( cnet_map ); }catch( Throwable e ){ log( "Failed to save " + network.getName(), e ); } } if ( list.size() == 0 ){ FileUtil.deleteResilientConfigFile( CONFIG_FILE ); }else{ FileUtil.writeResilientConfigFile( CONFIG_FILE, map ); } } public void addListener( ContentNetworkListener listener ) { listeners.add( listener ); } public void removeListener( ContentNetworkListener listener ) { listeners.remove( listener ); } public void generate( IndentWriter writer ) { writer.println( "Content Networks" ); try{ writer.indent(); synchronized( this ){ Iterator it = networks.iterator(); while( it.hasNext()){ ContentNetworkImpl network = it.next(); writer.println( network.getString()); } } }finally{ writer.exdent(); } } public static void log( String s, Throwable e ) { AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( "CNetworks" ); diag_logger.log( s ); diag_logger.log( e ); } public static void log( String s ) { AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( "CNetworks" ); diag_logger.log( s ); } } azureus-4.3.0.6/com/aelitis/azureus/core/cnetwork/ContentNetwork.java0000644000175000017500000001717411307366134025175 0ustar adrianadrian/* * Created on Nov 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.cnetwork; import com.aelitis.azureus.core.vuzefile.VuzeFile; public interface ContentNetwork { public static final long CONTENT_NETWORK_UNKNOWN = -1; public static final long CONTENT_NETWORK_VUZE = 1; /** * You should normally NOT refer explicitly to this constant without consideration * as we don't want network-specific code proliferating */ public static final long CONTENT_NETWORK_RFN = 2; public static final long CONTENT_NETWORK_VHDNL = 3; // test networks public static final long CONTENT_NETWORK_JR = 10000; public static final long CONTENT_NETWORK_CHUN = 10001; public static final long CONTENT_NETWORK_SOUK = 10002; public static final long CONTENT_NETWORK_DEV02 = 10003; public static final int SERVICE_SEARCH = 1; // String - query text public static final int SERVICE_XSEARCH = 2; // String - query text; Boolean - toSubscribe public static final int SERVICE_RPC = 3; public static final int SERVICE_RELAY_RPC = 4; public static final int SERVICE_AUTH_RPC = 5; public static final int SERVICE_BIG_BROWSE = 6; public static final int SERVICE_PUBLISH = 7; public static final int SERVICE_WELCOME = 8; public static final int SERVICE_PUBLISH_NEW = 9; public static final int SERVICE_PUBLISH_ABOUT = 10; public static final int SERVICE_CONTENT_DETAILS = 11; // String - hash; String (can be null) - client ref public static final int SERVICE_COMMENT = 12; // String - hash public static final int SERVICE_PROFILE = 13; // String - login_id; String - client ref public static final int SERVICE_TORRENT_DOWNLOAD = 14; // String - hash; String (can be null) - client ref public static final int SERVICE_SITE = 15; public static final int SERVICE_SUPPORT = 16; public static final int SERVICE_FAQ = 17; public static final int SERVICE_FAQ_TOPIC = 18; // String - topic entry public static final int SERVICE_BLOG = 19; public static final int SERVICE_FORUMS = 20; public static final int SERVICE_WIKI = 21; public static final int SERVICE_LOGIN = 22; // String - message (can be null) public static final int SERVICE_LOGOUT = 23; public static final int SERVICE_REGISTER = 24; public static final int SERVICE_MY_PROFILE = 25; public static final int SERVICE_MY_ACCOUNT = 26; public static final int SERVICE_SITE_RELATIVE = 27; // String - relative URL public static final int SERVICE_ADD_FRIEND = 28; // String - bg colour public static final int SERVICE_SUBSCRIPTION = 29; // String - subscription ID public static final int SERVICE_GET_ICON = 30; public static final int SERVICE_AUTHORIZE = 31; public static final int SERVICE_PREPLAYBACK = 32; public static final int SERVICE_POSTPLAYBACK = 33; public static final int SERVICE_SIDEBAR_CLOSE = 34; public static final int SERVICE_ABOUT = 35; public static final int SERVICE_IDENTIFY = 36; // content network properties public static final int PROPERTY_SITE_HOST = 1; // String public static final int PROPERTY_REMOVEABLE = 2; // Boolean public static final int PROPERTY_ORDER = 3; // String (Tux prefers to Integer) // persistent (and local) properties public static final String PP_AUTH_PAGE_SHOWN = "auth_shown"; // Boolean, default false public static final String PP_IS_CUSTOMIZATION = "is_cust"; // Boolean, default false public static final String PP_ACTIVE = "active"; // Boolean public static final String PP_SHOW_IN_MENU = "in_menu"; // Boolean public static final String PP_SOURCE_REF = "source_ref"; // String /** * Returns one of the above CONTENT_NETWORK constants * @return */ public long getID(); public String getName(); public Object getProperty( int property ); public boolean isStartupNetwork(); public void setStartupNetwork( boolean is_startup ); /** * Test if the network supports a particular service * @param service_type * @return */ public boolean isServiceSupported( int service_type ); /** * Returns the base URL of the service. If not parameterised then this is sufficient to * invoke the service * @param service_type * @return */ public String getServiceURL( int service_type ); /** * Generic parameterised service method * @param service_type * @param params * @return */ public String getServiceURL( int service_type, Object[] params ); /** * search service helper method * @param query * @return */ public String getSearchService( String query ); public String getXSearchService( String query, boolean to_subscribe ); public String getContentDetailsService( String hash, String client_ref ); public String getCommentService( String hash ); public String getProfileService( String login_id, String client_ref ); public String getTorrentDownloadService( String hash, String client_ref ); /** * @param topic The topic number or a pre-defined topic constant found in FAQTopics */ public String getFAQTopicService( String topic ); public String getLoginService( String message ); public String getSiteRelativeURL( String relative_url, boolean append_suffix ); public String getAddFriendURL( String bg_colour ); public String getSubscriptionURL( String subs_id ); /** * I'd rather this function we embedded into the ContentNetwork service getting logic, but for * the moment expose it for simplicity * @param url_in base URL onto which the suffix should be appended * @param for_post whether this is for an HTTP 'POST' operation, in which case the parameter * separator is always an '&' (for 'GET' the first param uses a '?' sep) * @param include_azid whether or not we should include the azid in the suffix * @return */ public String appendURLSuffix( String url_in, boolean for_post, boolean include_azid ); /** * export to vuze file * @return */ public VuzeFile getVuzeFile(); /** * Sets a locally persistent property. Name should be from the PP_ names above so keep track * of what attributes exist * * @param name PP_ constant * @param value must be bencodable! */ public void setPersistentProperty( String name, Object value ); public Object getPersistentProperty( String name ); public void addPersistentPropertyChangeListener( ContentNetworkPropertyChangeListener listener ); public void removePersistentPropertyChangeListener( ContentNetworkPropertyChangeListener listener ); /** * Set a non-persistent property of the content network * @param key * @param value */ public void setTransientProperty( Object key, Object value ); public Object getTransientProperty( Object key ); public void remove(); } azureus-4.3.0.6/com/aelitis/azureus/core/cnetwork/ContentNetworkListener.java0000644000175000017500000000215111145221760026663 0ustar adrianadrian/* * Created on Nov 21, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.cnetwork; public interface ContentNetworkListener { public void networkAdded( ContentNetwork network ); public void networkAddFailed( long network_id, Throwable error ); public void networkChanged( ContentNetwork network ); public void networkRemoved( ContentNetwork network ); } azureus-4.3.0.6/com/aelitis/azureus/core/cnetwork/ContentNetworkPropertyChangeListener.java0000644000175000017500000000166011117662660031551 0ustar adrianadrian/* * Created on Dec 9, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.cnetwork; public interface ContentNetworkPropertyChangeListener { public void propertyChanged( String name ); } azureus-4.3.0.6/com/aelitis/azureus/core/cnetwork/ContentNetworkManagerFactory.java0000644000175000017500000000221011112642672027777 0ustar adrianadrian/* * Created on Nov 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.cnetwork; import com.aelitis.azureus.core.cnetwork.impl.ContentNetworkManagerImpl; public class ContentNetworkManagerFactory { public static void preInitialise() { ContentNetworkManagerImpl.preInitialise(); } public static ContentNetworkManager getSingleton() { return( ContentNetworkManagerImpl.getSingleton()); } } azureus-4.3.0.6/com/aelitis/azureus/core/AzureusCoreOperationListener.java0000644000175000017500000000232510462211552026175 0ustar adrianadrian/* * Created on 27 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core; public interface AzureusCoreOperationListener { /** * * @param operation * @return true if the listener has taken responsibility for running an operation task */ public boolean operationCreated( AzureusCoreOperation operation ); } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/0000755000175000017500000000000011310377630020656 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/proxy/AEProxyAddressMapper.java0000644000175000017500000000316710373051004025522 0ustar adrianadrian/* * Created on 15-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy; import java.net.URL; /** * @author parg * */ public interface AEProxyAddressMapper { /** * SOCKS 5 is limited to 255 char DNS names. So for longer ones (e.g. I2P 'names') * we have to replace then with somethin shorter to get through the SOCKS layer * and then remap them on the otherside. * These functions are only active if a SOCKS proxy is enabled and looping back * (in process is the assumption) * @param address * @return */ public String internalise( String address ); public String externalise( String address ); public URL internalise( URL url ); public URL externalise( URL url ); } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/AEProxyException.java0000644000175000017500000000231711012742134024724 0ustar adrianadrian/* * Created on 06-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy; /** * @author parg * */ public class AEProxyException extends Exception { public AEProxyException( String str ) { super(str); } public AEProxyException( String str, Throwable e ) { super(str,e); } } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/AEProxyConnectionListener.java0000644000175000017500000000217010373051004026566 0ustar adrianadrian/* * Created on 08-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy; /** * @author parg * */ public interface AEProxyConnectionListener { public void connectionClosed( AEProxyConnection connection ); } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/AEProxy.java0000644000175000017500000000217510527476620023065 0ustar adrianadrian/* * Created on 06-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy; /** * @author parg * */ public interface AEProxy { public int getPort(); public void setAllowExternalConnections( boolean permit ); } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/impl/0000755000175000017500000000000011310377630021617 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/proxy/impl/AEProxyImpl.java0000644000175000017500000002423510527476620024651 0ustar adrianadrian/* * Created on 06-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy.impl; import java.util.*; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector; import com.aelitis.azureus.core.proxy.*; /** * @author parg * */ public class AEProxyImpl implements AEProxy, VirtualChannelSelector.VirtualSelectorListener { private static final LogIDs LOGID = LogIDs.NET; private static final int DEBUG_PERIOD = 60000; private long last_debug; private int port; private long connect_timeout; private long read_timeout; private AEProxyHandler proxy_handler; private VirtualChannelSelector read_selector; private VirtualChannelSelector connect_selector; private VirtualChannelSelector write_selector; private List processors = new ArrayList(); private final HashMap write_select_regs = new HashMap(); private boolean allow_external_access; private AEMonitor this_mon = new AEMonitor( "AEProxyImpl" ); public AEProxyImpl( int _port, long _connect_timeout, long _read_timeout, AEProxyHandler _proxy_handler ) throws AEProxyException { port = _port; connect_timeout = _connect_timeout; read_timeout = _read_timeout; proxy_handler = _proxy_handler; String name = "Proxy:" + port; read_selector = new VirtualChannelSelector( name, VirtualChannelSelector.OP_READ, false ); connect_selector = new VirtualChannelSelector( name, VirtualChannelSelector.OP_CONNECT, true ); write_selector = new VirtualChannelSelector( name, VirtualChannelSelector.OP_WRITE, true ); try{ final ServerSocketChannel ssc = ServerSocketChannel.open(); ServerSocket ss = ssc.socket(); ss.setReuseAddress(true); ss.bind( new InetSocketAddress( InetAddress.getByName("127.0.0.1"), port), 128 ); if ( port == 0 ){ port = ss.getLocalPort(); } Thread connect_thread = new AEThread("AEProxy:connect.loop") { public void runSupport() { selectLoop( connect_selector ); } }; connect_thread.setDaemon( true ); connect_thread.start(); Thread read_thread = new AEThread("AEProxy:read.loop") { public void runSupport() { selectLoop( read_selector ); } }; read_thread.setDaemon( true ); read_thread.start(); Thread write_thread = new AEThread("AEProxy:write.loop") { public void runSupport() { selectLoop( write_selector ); } }; write_thread.setDaemon( true ); write_thread.start(); Thread accept_thread = new AEThread("AEProxy:accept.loop") { public void runSupport() { acceptLoop( ssc ); } }; accept_thread.setDaemon( true ); accept_thread.start(); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "AEProxy: listener established on port " + port)); }catch( Throwable e){ Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Tracker.alert.listenfail"), new String[] { "" + port }); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "AEProxy: listener failed on port " + port, e)); throw( new AEProxyException( "AEProxy: accept fails: " + e.toString())); } } public void setAllowExternalConnections( boolean permit ) { allow_external_access = permit; } protected void acceptLoop( ServerSocketChannel ssc ) { long successfull_accepts = 0; long failed_accepts = 0; while(true){ try{ SocketChannel socket_channel = ssc.accept(); successfull_accepts++; if ( !( allow_external_access || socket_channel.socket().getInetAddress().isLoopbackAddress())){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "AEProxy: incoming connection from '" + socket_channel.socket().getInetAddress() + "' - closed as not local")); socket_channel.close(); }else{ socket_channel.configureBlocking(false); AEProxyConnectionImpl processor = new AEProxyConnectionImpl(this, socket_channel, proxy_handler); if ( !processor.isClosed()){ try{ this_mon.enter(); processors.add( processor ); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "AEProxy: active processors = " + processors.size())); }finally{ this_mon.exit(); } read_selector.register( socket_channel, this, processor ); } } }catch( Throwable e ){ failed_accepts++; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "AEProxy: listener failed on port " + port, e)); if ( failed_accepts > 100 && successfull_accepts == 0 ){ // looks like its not going to work... // some kind of socket problem Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Network.alert.acceptfail"), new String[] { "" + port, "TCP" }); break; } } } } protected void close( AEProxyConnectionImpl processor ) { try{ this_mon.enter(); processors.remove( processor ); }finally{ this_mon.exit(); } } protected void selectLoop( VirtualChannelSelector selector ) { long last_time = 0; while( true ){ try{ selector.select( 100 ); // only use one selector to trigger the timeouts! if ( selector == read_selector ){ long now = SystemTime.getCurrentTime(); if ( now < last_time ){ last_time = now; }else if ( now - last_time >= 5000 ){ last_time = now; checkTimeouts(); } } }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected void checkTimeouts() { long now = SystemTime.getCurrentTime(); if ( now - last_debug > DEBUG_PERIOD ){ last_debug = now; try{ this_mon.enter(); Iterator it = processors.iterator(); while( it.hasNext()){ AEProxyConnectionImpl processor = (AEProxyConnectionImpl)it.next(); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "AEProxy: active processor: " + processor.getStateString())); } }finally{ this_mon.exit(); } } if ( connect_timeout <= 0 && read_timeout <= 0 ){ return; } List closes = new ArrayList(); try{ this_mon.enter(); Iterator it = processors.iterator(); while( it.hasNext()){ AEProxyConnectionImpl processor = (AEProxyConnectionImpl)it.next(); long diff = now - processor.getTimeStamp(); if ( connect_timeout > 0 && diff >= connect_timeout && !processor.isConnected()){ closes.add( processor ); }else if ( read_timeout > 0 && diff >= read_timeout && processor.isConnected()){ closes.add( processor ); } } }finally{ this_mon.exit(); } for (int i=0;i 0 && InetAddress.getByName(host).isLoopbackAddress()){ enabled = true; byte[] b = new byte[120]; for (int i=0;i " + target ); return( target ); } public String externalise( String address ) { if ( !enabled || address.length() < 255 ){ return( address ); } String target = (String)map.get( address ); if ( target == null ){ target = address; } // System.out.println( "AEProxyAddressMapper: externalise " + address + " -> " + target ); return( target ); } public URL internalise( URL url ) { if ( !enabled ){ return( url ); } String host = url.getHost(); if ( host.length() < 256 ){ return( url ); } String new_host = internalise( host ); String url_str = url.toString(); int pos = url_str.indexOf( host ); if ( pos == -1 ){ Debug.out( "inconsistent url '" + url_str + "' / '" + host + "'" ); return( url ); } String new_url_str = url_str.substring(0,pos) + new_host + url_str.substring(pos+host.length()); try{ return( new URL( new_url_str )); }catch( MalformedURLException e ){ Debug.printStackTrace(e); return( url ); } } public URL externalise( URL url ) { if ( !enabled ){ return( url ); } String host = url.getHost(); if ( host.length() < 255 ){ return( url ); } String new_host = externalise( host ); String url_str = url.toString(); int pos = url_str.indexOf( host ); if ( pos == -1 ){ Debug.out( "inconsistent url '" + url_str + "' / '" + host + "'" ); return( url ); } String new_url_str = url_str.substring(0,pos) + new_host + url_str.substring(pos+host.length()); try{ return( new URL( new_url_str )); }catch( MalformedURLException e ){ Debug.printStackTrace(e); return( url ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/impl/AEProxyConnectionImpl.java0000644000175000017500000001264010373051022026646 0ustar adrianadrian/* * Created on 06-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy.impl; import java.util.*; import java.nio.channels.*; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.proxy.*; /** * @author parg * */ public class AEProxyConnectionImpl implements AEProxyConnection { private static final LogIDs LOGID = LogIDs.NET; protected AEProxyImpl server; protected SocketChannel source_channel; protected volatile AEProxyState proxy_read_state = null; protected volatile AEProxyState proxy_write_state = null; protected volatile AEProxyState proxy_connect_state = null; protected long time_stamp; protected boolean is_connected; protected boolean is_closed; protected List listeners = new ArrayList(1); protected AEProxyConnectionImpl( AEProxyImpl _server, SocketChannel _socket, AEProxyHandler _handler ) { server = _server; source_channel = _socket; setTimeStamp(); try{ proxy_read_state = _handler.getInitialState( this ); }catch( Throwable e ){ failed(e); } } public String getName() { String name = source_channel.socket().getInetAddress() + ":" + source_channel.socket().getPort() + " -> "; return( name ); } public SocketChannel getSourceChannel() { return( source_channel ); } public void setReadState( AEProxyState state ) { proxy_read_state = state; } public void setWriteState( AEProxyState state ) { proxy_write_state = state; } public void setConnectState( AEProxyState state ) { proxy_connect_state = state; } protected boolean read( SocketChannel sc ) { try{ return( proxy_read_state.read(sc)); }catch( Throwable e ){ failed(e); return( false ); } } protected boolean write( SocketChannel sc ) { try{ return( proxy_write_state.write(sc)); }catch( Throwable e ){ failed(e); return( false ); } } protected boolean connect( SocketChannel sc ) { try{ return( proxy_connect_state.connect(sc)); }catch( Throwable e ){ failed(e); return( false ); } } public void requestWriteSelect( SocketChannel sc ) { server.requestWriteSelect( this, sc ); } public void cancelWriteSelect( SocketChannel sc ) { server.cancelWriteSelect( sc ); } public void requestConnectSelect( SocketChannel sc ) { server.requestConnectSelect( this, sc ); } public void cancelConnectSelect( SocketChannel sc ) { server.cancelConnectSelect( sc ); } public void requestReadSelect( SocketChannel sc ) { server.requestReadSelect( this, sc ); } public void cancelReadSelect( SocketChannel sc ) { server.cancelReadSelect( sc ); } public void failed( Throwable reason ) { try{ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "AEProxyProcessor: " + getName() + " failed", reason)); close(); }catch( Throwable e ){ Debug.printStackTrace(e); } } public void close() { is_closed = true; try{ try{ cancelReadSelect( source_channel ); cancelWriteSelect( source_channel ); source_channel.close(); }catch( Throwable e ){ Debug.printStackTrace(e); } for (int i=0;i 4096 ){ throw( new IOException( "DNS name too long" )); } // ready for next byte buffer.flip(); } return( true ); } } protected class proxyStateV4Reply extends AESocksProxyState { protected proxyStateV4Reply() throws IOException { super( AESocksProxyConnectionImpl.this ); /* +----+----+----+----+----+----+----+----+ | VN | CD | DSTPORT | DSTIP | +----+----+----+----+----+----+----+----+ # of bytes: 1 1 2 4 */ connection.setWriteState( this ); byte[] addr = plugable_connection.getLocalAddress().getAddress(); int port = plugable_connection.getLocalPort(); buffer = ByteBuffer.wrap( new byte[]{ (byte)0,(byte)90, (byte)((port>>8)&0xff), (byte)(port&0xff), addr[0],addr[1],addr[2],addr[3]}); write( source_channel ); } protected boolean writeSupport( SocketChannel sc ) throws IOException { int len = sc.write( buffer ); if ( buffer.hasRemaining()){ connection.requestWriteSelect( sc ); }else{ plugable_connection.relayData(); } return( len > 0 ); } } // V5 protected class proxyStateV5MethodNumber extends AESocksProxyState { protected proxyStateV5MethodNumber() { super( AESocksProxyConnectionImpl.this ); connection.setReadState( this ); buffer = ByteBuffer.allocate(1); } protected boolean readSupport( SocketChannel sc ) throws IOException { int len = sc.read( buffer ); if ( len == 0 ){ return( false ); }else if ( len == -1 ){ throw( new IOException( "read channel shutdown" )); } if ( buffer.hasRemaining()){ return( true ); } buffer.flip(); int num_methods = buffer.get(); new proxyStateV5Methods(num_methods); return( true ); } } protected class proxyStateV5Methods extends AESocksProxyState { protected proxyStateV5Methods( int methods ) { super( AESocksProxyConnectionImpl.this ); connection.setReadState( this ); buffer = ByteBuffer.allocate(methods); } protected boolean readSupport( SocketChannel sc ) throws IOException { int len = sc.read( buffer ); if ( len == 0 ){ return( false ); }else if ( len == -1 ){ throw( new IOException( "read channel shutdown" )); } if ( buffer.hasRemaining()){ return( true ); } // we just ignore actual method values new proxyStateV5MethodsReply(); return( true ); } } protected class proxyStateV5MethodsReply extends AESocksProxyState { protected proxyStateV5MethodsReply() throws IOException { super( AESocksProxyConnectionImpl.this ); new proxyStateV5Request(); connection.setWriteState( this ); buffer = ByteBuffer.wrap(new byte[]{(byte)5,(byte)0}); write( source_channel ); } protected boolean writeSupport( SocketChannel sc ) throws IOException { int len = sc.write( buffer ); if ( buffer.hasRemaining()){ connection.requestWriteSelect( sc ); } return( len > 0 ); } } /* +----+-----+-------+------+----------+----------+ |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | +----+-----+-------+------+----------+----------+ | 1 | 1 | X'00' | 1 | Variable | 2 | +----+-----+-------+------+----------+----------+ Where: o VER protocol version: X'05' o CMD o CONNECT X'01' o BIND X'02' o UDP ASSOCIATE X'03' o RSV RESERVED o ATYP address type of following address o IP V4 address: X'01' o DOMAINNAME: X'03' o IP V6 address: X'04' o DST.ADDR desired destination address o DST.PORT desired destination port in network octet order */ protected class proxyStateV5Request extends AESocksProxyState { protected proxyStateV5Request() { super( AESocksProxyConnectionImpl.this ); connection.setReadState( this ); buffer = ByteBuffer.allocate(4); } protected boolean readSupport( SocketChannel sc ) throws IOException { int len = sc.read( buffer ); if ( len == 0 ){ return( false ); }else if ( len == -1 ){ throw( new IOException( "read channel shutdown" )); } if ( buffer.hasRemaining()){ return( true ); } buffer.flip(); buffer.get(); // version int command = buffer.get(); buffer.get(); // reserved int address_type = buffer.get(); if ( command != 1 ){ throw( new IOException( "V5: Only connect supported")); } if ( address_type == 1 ){ new proxyStateV5RequestIP(); }else if ( address_type == 3 ){ new proxyStateV5RequestDNS(); }else{ throw( new IOException( "V5: Unsupported address type" )); } return( true ); } } protected class proxyStateV5RequestIP extends AESocksProxyState { protected proxyStateV5RequestIP() { super( AESocksProxyConnectionImpl.this ); connection.setReadState( this ); buffer = ByteBuffer.allocate(4); } protected boolean readSupport( SocketChannel sc ) throws IOException { int len = sc.read( buffer ); if ( len == 0 ){ return( false ); }else if ( len == -1 ){ throw( new IOException( "read channel shutdown" )); } if ( buffer.hasRemaining()){ return( true ); } buffer.flip(); byte[] bytes = new byte[4]; buffer.get( bytes ); InetAddress inet_address = InetAddress.getByAddress( bytes ); new proxyStateV5RequestPort( "", inet_address ); return( true ); } } protected class proxyStateV5RequestDNS extends AESocksProxyState { boolean got_length = false; protected proxyStateV5RequestDNS() { super( AESocksProxyConnectionImpl.this ); connection.setReadState( this ); buffer = ByteBuffer.allocate(1); } protected boolean readSupport( final SocketChannel sc ) throws IOException { int len = sc.read( buffer ); if ( len == 0 ){ return( false ); }else if ( len == -1 ){ throw( new IOException( "read channel shutdown" )); } if ( buffer.hasRemaining()){ return( true ); } buffer.flip(); if ( !got_length){ int length = ((int)buffer.get()) & 0xff; buffer = ByteBuffer.allocate( length ); got_length = true; }else{ String dns_address = ""; while( buffer.hasRemaining()){ dns_address += (char)buffer.get(); } if ( disable_dns_lookups ){ new proxyStateV5RequestPort( dns_address, null ); }else{ final String f_dns_address = dns_address; connection.cancelReadSelect( sc ); HostNameToIPResolver.addResolverRequest( dns_address, new HostNameToIPResolverListener() { public void hostNameResolutionComplete( InetAddress address ) { new proxyStateV5RequestPort( f_dns_address, address); connection.requestReadSelect( sc ); } }); } } return( true ); } } protected class proxyStateV5RequestPort extends AESocksProxyState { protected String unresolved_address; protected InetAddress address; protected proxyStateV5RequestPort( String _unresolved_address, InetAddress _address ) { super( AESocksProxyConnectionImpl.this ); unresolved_address = _unresolved_address; address = _address; connection.setReadState( this ); buffer = ByteBuffer.allocate(2); } protected boolean readSupport( SocketChannel sc ) throws IOException { int len = sc.read( buffer ); if ( len == 0 ){ return( false ); }else if ( len == -1 ){ throw( new IOException( "read channel shutdown" )); } if ( buffer.hasRemaining()){ return( true ); } buffer.flip(); int port = (((int)buffer.get() & 0xff) << 8 ) + ((int)buffer.get() & 0xff); socks_version = 5; plugable_connection.connect( new AESocksProxyAddressImpl( unresolved_address, address, port )); return( true ); } } /* +----+-----+-------+------+----------+----------+ |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | +----+-----+-------+------+----------+----------+ | 1 | 1 | X'00' | 1 | Variable | 2 | +----+-----+-------+------+----------+----------+ Where: o VER protocol version: X'05' o REP Reply field: o X'00' succeeded o X'01' general SOCKS server failure o X'02' connection not allowed by ruleset o X'03' Network unreachable o X'04' Host unreachable o X'05' Connection refused o X'06' TTL expired o X'07' Command not supported o X'08' Address type not supported o X'09' to X'FF' unassigned o RSV RESERVED o ATYP address type of following address o IP V4 address: X'01' o DOMAINNAME: X'03' o IP V6 address: X'04' o BND.ADDR server bound address o BND.PORT server bound port in network octet order */ protected class proxyStateV5Reply extends AESocksProxyState { protected proxyStateV5Reply() throws IOException { super( AESocksProxyConnectionImpl.this ); connection.setWriteState( this ); byte[] addr = plugable_connection.getLocalAddress().getAddress(); int port = plugable_connection.getLocalPort(); buffer = ByteBuffer.wrap( new byte[]{(byte)5,(byte)0,(byte)0,(byte)1, addr[0],addr[1],addr[2],addr[3], (byte)((port>>8)&0xff), (byte)(port&0xff)}); write( source_channel ); } protected boolean writeSupport( SocketChannel sc ) throws IOException { int len = sc.write( buffer ); if ( buffer.hasRemaining()){ connection.requestWriteSelect( sc ); }else{ plugable_connection.relayData(); } return( len > 0 ); } } public void connected() throws IOException { if ( socks_version == 4 ){ new proxyStateV4Reply(); }else{ new proxyStateV5Reply(); } } protected class proxyStateClose extends AESocksProxyState { protected proxyStateClose() throws IOException { super( AESocksProxyConnectionImpl.this ); connection.close(); connection.setReadState( null); connection.setWriteState( null); connection.setConnectState( null); } } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyPlugableConnectionDefault.javaazureus-4.3.0.6/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyPlugableConnectionDefault.java0000644000175000017500000002063111034022546033135 0ustar adrianadrian/* * Created on 13-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy.socks.impl; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.channels.SocketChannel; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.DirectByteBufferPool; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.proxy.AEProxyConnection; import com.aelitis.azureus.core.proxy.socks.AESocksProxy; import com.aelitis.azureus.core.proxy.socks.AESocksProxyAddress; import com.aelitis.azureus.core.proxy.socks.AESocksProxyConnection; import com.aelitis.azureus.core.proxy.socks.AESocksProxyPlugableConnection; /** * @author parg * */ public class AESocksProxyPlugableConnectionDefault implements AESocksProxyPlugableConnection { protected AESocksProxyConnection socks_connection; protected AEProxyConnection connection; protected SocketChannel source_channel; protected SocketChannel target_channel; protected proxyStateRelayData relay_data_state; public AESocksProxyPlugableConnectionDefault( AESocksProxyConnection _socks_connection ) { socks_connection = _socks_connection; connection = socks_connection.getConnection(); source_channel = connection.getSourceChannel(); } public String getName() { if ( target_channel != null ){ return( target_channel.socket().getInetAddress() + ":" + target_channel.socket().getPort()); } return( "" ); } public InetAddress getLocalAddress() { return( target_channel.socket().getInetAddress()); } public int getLocalPort() { return( target_channel.socket().getPort()); } public void connect( AESocksProxyAddress _address ) throws IOException { if ( _address.getAddress() == null ){ throw( new IOException( "DNS lookup of '" + _address.getUnresolvedAddress() + "' fails" )); } new proxyStateRelayConnect( new InetSocketAddress(_address.getAddress(), _address.getPort())); } public void relayData() throws IOException { new proxyStateRelayData(); } public void close() { if ( target_channel != null ){ try{ connection.cancelReadSelect( target_channel ); connection.cancelWriteSelect( target_channel ); target_channel.close(); }catch( Throwable e ){ Debug.printStackTrace(e); } } if ( relay_data_state != null ){ relay_data_state.destroy(); } } protected class proxyStateRelayConnect extends AESocksProxyState { protected InetSocketAddress address; protected proxyStateRelayConnect( InetSocketAddress _address ) throws IOException { super( socks_connection ); address = _address; // OK, we're almost ready to roll. Unregister the read select until we're // connected connection.cancelReadSelect( source_channel ); connection.setConnectState( this ); target_channel = SocketChannel.open(); InetAddress bindIP = NetworkAdmin.getSingleton().getMultiHomedOutgoingRoundRobinBindAddress(address.getAddress()); if ( bindIP != null ){ target_channel.socket().bind( new InetSocketAddress( bindIP, 0 ) ); } target_channel.configureBlocking( false ); target_channel.connect( address ); connection.requestConnectSelect( target_channel ); } protected boolean connectSupport( SocketChannel sc ) throws IOException { if( !sc.finishConnect()){ throw( new IOException( "finishConnect returned false" )); } // if we've got a proxy chain, now's the time to negotiate the connection AESocksProxy proxy = socks_connection.getProxy(); if ( proxy.getNextSOCKSProxyHost() != null ){ } socks_connection.connected(); return( true ); } } protected class proxyStateRelayData extends AESocksProxyState { protected DirectByteBuffer source_buffer; protected DirectByteBuffer target_buffer; protected long outward_bytes = 0; protected long inward_bytes = 0; protected proxyStateRelayData() throws IOException { super( socks_connection ); source_buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_PROXY_RELAY, 1024 ); target_buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_PROXY_RELAY, 1024 ); relay_data_state = this; if ( connection.isClosed()){ destroy(); throw( new IOException( "connection closed" )); } connection.setReadState( this ); connection.setWriteState( this ); connection.requestReadSelect( source_channel ); connection.requestReadSelect( target_channel ); connection.setConnected(); } protected void destroy() { if ( source_buffer != null ){ source_buffer.returnToPool(); source_buffer = null; } if ( target_buffer != null ){ target_buffer.returnToPool(); target_buffer = null; } } protected boolean readSupport( SocketChannel sc ) throws IOException { connection.setTimeStamp(); SocketChannel chan1 = sc; SocketChannel chan2 = sc==source_channel?target_channel:source_channel; DirectByteBuffer read_buffer = sc==source_channel?source_buffer:target_buffer; int len = read_buffer.read( DirectByteBuffer.SS_PROXY, chan1 ); if ( len == -1 ){ //means that the channel has been shutdown connection.close(); }else{ if ( read_buffer.position( DirectByteBuffer.SS_PROXY ) > 0 ){ read_buffer.flip(DirectByteBuffer.SS_PROXY); int written = read_buffer.write( DirectByteBuffer.SS_PROXY, chan2 ); if ( chan1 == source_channel ){ outward_bytes += written; }else{ inward_bytes += written; } if ( read_buffer.hasRemaining(DirectByteBuffer.SS_PROXY)){ connection.cancelReadSelect( chan1 ); connection.requestWriteSelect( chan2 ); }else{ read_buffer.position(DirectByteBuffer.SS_PROXY, 0); read_buffer.limit( DirectByteBuffer.SS_PROXY, read_buffer.capacity(DirectByteBuffer.SS_PROXY)); } } } return( len > 0 ); } protected boolean writeSupport( SocketChannel sc ) throws IOException { // socket SX -> SY via BX // so if SX = source_channel then BX is target buffer SocketChannel chan1 = sc; SocketChannel chan2 = sc==source_channel?target_channel:source_channel; DirectByteBuffer read_buffer = sc==source_channel?target_buffer:source_buffer; int written = read_buffer.write( DirectByteBuffer.SS_PROXY, chan1 ); if ( chan1 == target_channel ){ outward_bytes += written; }else{ inward_bytes += written; } if ( read_buffer.hasRemaining(DirectByteBuffer.SS_PROXY)){ connection.requestWriteSelect( chan1 ); }else{ read_buffer.position(DirectByteBuffer.SS_PROXY,0); read_buffer.limit( DirectByteBuffer.SS_PROXY, read_buffer.capacity(DirectByteBuffer.SS_PROXY)); connection.requestReadSelect( chan2 ); } return( written > 0 ); } public String getStateName() { String state = this.getClass().getName(); int pos = state.indexOf( "$"); state = state.substring(pos+1); return( state +" [out=" + outward_bytes +",in=" + inward_bytes +"] " + source_buffer + " / " + target_buffer ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyAddressImpl.java0000644000175000017500000000507610373051014030267 0ustar adrianadrian/* * Created on 13-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy.socks.impl; import java.net.InetAddress; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.HostNameToIPResolver; import com.aelitis.azureus.core.proxy.socks.AESocksProxyAddress; /** * @author parg * */ public class AESocksProxyAddressImpl implements AESocksProxyAddress { protected String unresolved_address; protected InetAddress address; protected int port; protected AESocksProxyAddressImpl( String _unresolved_address, InetAddress _address, int _port ) { unresolved_address = _unresolved_address; address = _address; port = _port; if ( address == null ){ // see if we've been passed an IP address as unresolved // TODO: IPV6 one day? int dots = 0; boolean ok = true; for (int i=0;i3 ){ ok = false; break; } }else if ( !Character.isDigit( c )){ ok = false; break; }else{ // nnn.nnn.nnn.nnn if ( i > 15 ){ ok = false; break; } } } if ( ok && dots == 3 ){ try{ address = HostNameToIPResolver.syncResolve( unresolved_address ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } } public String getUnresolvedAddress() { return( unresolved_address ); } public InetAddress getAddress() { return( address ); } public int getPort() { return( port ); } } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/socks/AESocksProxyAddress.java0000644000175000017500000000227310373051006026501 0ustar adrianadrian/* * Created on 13-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy.socks; import java.net.InetAddress; /** * @author parg * */ public interface AESocksProxyAddress { public String getUnresolvedAddress(); public InetAddress getAddress(); public int getPort(); } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/socks/AESocksProxy.java0000644000175000017500000000343110527476622025210 0ustar adrianadrian/* * Created on 08-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy.socks; /** * @author parg * */ public interface AESocksProxy { public static final String PV_4 = "V4"; public static final String PV_4a = "V4a"; public static final String PV_5 = "V5"; public int getPort(); public AESocksProxyPlugableConnection getDefaultPlugableConnection( AESocksProxyConnection basis ); /** * Set the next SOCKS proxy in a chain - i.e. this socks proxy's default plugable connection * will connect onwards using this SOCKS proxy * * @param host * @param port */ public void setNextSOCKSProxy( String host, int port, String proxy_version ); public String getNextSOCKSProxyHost(); public int getNextSOCKSProxyPort(); public String getNextSOCKSProxyVersion(); public void setAllowExternalConnections( boolean permit ); } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/socks/AESocksProxyPlugableConnection.java0000644000175000017500000000262610373051006030671 0ustar adrianadrian/* * Created on 13-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy.socks; import java.io.IOException; import java.net.InetAddress; /** * @author parg * */ public interface AESocksProxyPlugableConnection { public String getName(); public InetAddress getLocalAddress(); public int getLocalPort(); public void connect( AESocksProxyAddress address ) throws IOException; public void relayData() throws IOException; public void close() throws IOException; } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/socks/AESocksProxyPlugableConnectionFactory.java0000644000175000017500000000236410373051006032220 0ustar adrianadrian/* * Created on 13-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy.socks; import com.aelitis.azureus.core.proxy.AEProxyException; /** * @author parg * */ public interface AESocksProxyPlugableConnectionFactory { public AESocksProxyPlugableConnection create( AESocksProxyConnection connection ) throws AEProxyException; } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/socks/AESocksProxyConnection.java0000644000175000017500000000276510373051006027221 0ustar adrianadrian/* * Created on 13-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy.socks; import java.io.IOException; import com.aelitis.azureus.core.proxy.AEProxyConnection; /** * @author parg * */ public interface AESocksProxyConnection { public AESocksProxy getProxy(); public AEProxyConnection getConnection(); public void disableDNSLookups(); public void enableDNSLookups(); public void connected() throws IOException; public boolean isClosed(); public void close() throws IOException; public void setDelegate( AESocksProxyPlugableConnection target ); } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/AEProxyHandler.java0000644000175000017500000000225010373051004024335 0ustar adrianadrian/* * Created on 08-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy; import java.io.IOException; /** * @author parg * */ public interface AEProxyHandler { public AEProxyState getInitialState( AEProxyConnection connection ) throws IOException; } azureus-4.3.0.6/com/aelitis/azureus/core/proxy/AEProxyFactory.java0000644000175000017500000000315610373051004024375 0ustar adrianadrian/* * Created on 06-Dec-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.proxy; import com.aelitis.azureus.core.proxy.impl.*; /** * @author parg * */ public class AEProxyFactory { /** * @param port 0 = free port * @param connect_timeout 0 = no timeout * @param read_timeout 0 = no timeout * @return * @throws AEProxyException */ public static AEProxy create( int port, long connect_timeout, long read_timeout, AEProxyHandler state_factory ) throws AEProxyException { return( new AEProxyImpl(port,connect_timeout,read_timeout,state_factory)); } public static AEProxyAddressMapper getAddressMapper() { return( AEProxyAddressMapperImpl.getSingleton()); } } azureus-4.3.0.6/com/aelitis/azureus/core/content/0000755000175000017500000000000011310377620021146 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/content/AzureusPlatformContentDirectory.java0000644000175000017500000002315711224751000030374 0ustar adrianadrian/* * Created on Dec 19, 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.content; import java.io.InputStream; import java.net.URL; import java.util.Map; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadAttributeListener; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl; import org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader.ResourceDownloaderFactoryImpl; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.util.ConstantsVuze; public class AzureusPlatformContentDirectory implements AzureusContentDirectory { private static boolean registered = false; private static TorrentAttribute ta_category; public static synchronized void register() { if ( !registered ){ registered = true; ta_category = PluginInitializer.getDefaultInterface().getTorrentManager().getAttribute( TorrentAttribute.TA_CATEGORY ); AzureusContentDirectoryManager.registerDirectory( new AzureusPlatformContentDirectory()); } } private static CopyOnWriteList listeners = new CopyOnWriteList(); public AzureusContent lookupContent( Map attributes ) { byte[] hash = (byte[])attributes.get( AT_BTIH ); if ( hash == null ){ return( null ); } String url_str = ConstantsVuze.getDefaultContentNetwork().getTorrentDownloadService( Base32.encode( hash ), null ); ResourceDownloaderFactory rdf = ResourceDownloaderFactoryImpl.getSingleton(); try{ ResourceDownloader rd = rdf.create( new URL( url_str )); InputStream is = rd.download(); try{ TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedInputStream( is ); return( new AzureusPlatformContent( new TorrentImpl( torrent ))); }finally{ is.close(); } }catch( Throwable e ){ e.printStackTrace(); return( null ); } } public AzureusContentDownload lookupContentDownload( Map attributes ) { byte[] hash = (byte[])attributes.get( AT_BTIH ); try{ final Download download = PluginInitializer.getDefaultInterface().getDownloadManager().getDownload(hash); if ( download == null ){ return( null ); } return( new AzureusContentDownload() { public Download getDownload() { return( download ); } public Object getProperty( String name ) { return( null ); } }); }catch( Throwable e ){ return( null ); } } public AzureusContentFile lookupContentFile( Map attributes) { byte[] hash = (byte[])attributes.get( AT_BTIH ); int index = ((Integer)attributes.get( AT_FILE_INDEX )).intValue(); try{ Download download = PluginInitializer.getDefaultInterface().getDownloadManager().getDownload(hash); if ( download == null ){ return( null ); } Torrent t_torrent = download.getTorrent(); if ( t_torrent == null ){ return( null ); } String ud_key = "AzureusPlatformContentDirectory" + ":" + index; AzureusContentFile acf = (AzureusContentFile)download.getUserData( ud_key ); if ( acf != null ){ return( acf ); } final TOTorrent torrent = ((TorrentImpl)t_torrent).getTorrent(); final DiskManagerFileInfo file = download.getDiskManagerFileInfo()[index]; if ( PlatformTorrentUtils.isContent( torrent, false )){ acf = new AzureusContentFile() { public DiskManagerFileInfo getFile() { return( file ); } public Object getProperty( String name ) { try{ if ( name.equals( PT_DURATION )){ long duration = PlatformTorrentUtils.getContentVideoRunningTime( torrent ); if ( duration > 0 ){ // secs -> millis return( new Long( duration*1000 )); } }else if ( name.equals( PT_VIDEO_WIDTH )){ int[] res = PlatformTorrentUtils.getContentVideoResolution(torrent); if ( res != null ){ return(new Long( res[0])); } }else if ( name.equals( PT_VIDEO_HEIGHT )){ int[] res = PlatformTorrentUtils.getContentVideoResolution(torrent); if ( res != null ){ return(new Long( res[1] )); } }else if ( name.equals( PT_DATE )){ return( new Long( file.getDownload().getCreationTime())); }else if ( name.equals( PT_CATEGORIES )){ try{ String cat = file.getDownload().getCategoryName(); if ( cat != null && cat.length() > 0 ){ if ( !cat.equalsIgnoreCase( "Categories.uncategorized" )){ return( new String[]{ cat }); } } }catch( Throwable e ){ } return( new String[0] ); }else if ( name.equals( PT_PERCENT_DONE )){ long size = file.getLength(); return( new Long( size==0?100:(1000*file.getDownloaded()/size ))); }else if ( name.equals( PT_ETA )){ return( getETA( file )); } }catch( Throwable e ){ } return( null ); } }; }else{ acf = new AzureusContentFile() { public DiskManagerFileInfo getFile() { return( file ); } public Object getProperty( String name ) { try{ if ( name.equals( PT_DATE )){ return( new Long( file.getDownload().getCreationTime())); }else if ( name.equals( PT_CATEGORIES )){ try{ String cat = file.getDownload().getCategoryName(); if ( cat != null && cat.length() > 0 ){ if ( !cat.equalsIgnoreCase( "Categories.uncategorized" )){ return( new String[]{ cat }); } } }catch( Throwable e ){ } return( new String[0] ); }else if ( name.equals( PT_PERCENT_DONE )){ long size = file.getLength(); return( new Long( size==0?100:(1000*file.getDownloaded()/size ))); }else if ( name.equals( PT_ETA )){ return( getETA( file )); } }catch( Throwable e ){ } return( null ); } }; } download.setUserData( ud_key, acf ); final AzureusContentFile f_acf = acf; download.addAttributeListener( new DownloadAttributeListener() { public void attributeEventOccurred( Download download, TorrentAttribute attribute, int eventType ) { fireChanged( f_acf ); } }, ta_category, DownloadAttributeListener.WRITTEN ); return( acf ); }catch( Throwable e ){ return( null ); } } protected long getETA( DiskManagerFileInfo file ) { try{ if ( file.getDownloaded() == file.getLength()){ return( 0 ); } if ( file.isDeleted() || file.isSkipped()){ return( Long.MAX_VALUE ); } long eta = file.getDownload().getStats().getETASecs(); if ( eta < 0 ){ return( Long.MAX_VALUE ); } return( eta ); }catch( Throwable e ){ return( Long.MAX_VALUE ); } } public static void fireChanged( AzureusContentFile acf ) { for ( AzureusContentDirectoryListener l: listeners ){ l.contentChanged( acf, AzureusContentFile.PT_CATEGORIES ); } } public void addListener( AzureusContentDirectoryListener listener ) { listeners.add( listener ); } public void removeListener( AzureusContentDirectoryListener listener ) { listeners.remove( listener ); } protected class AzureusPlatformContent implements AzureusContent { private Torrent torrent; protected AzureusPlatformContent( Torrent _torrent ) { torrent = _torrent; } public Torrent getTorrent() { return( torrent ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/content/AzureusContent.java0000644000175000017500000000213110542171430024774 0ustar adrianadrian/* * Created on Dec 19, 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.content; import org.gudy.azureus2.plugins.torrent.Torrent; public interface AzureusContent { public Torrent getTorrent(); } azureus-4.3.0.6/com/aelitis/azureus/core/content/AzureusContentDirectoryManager.java0000644000175000017500000000271610542171430030165 0ustar adrianadrian/* * Created on Dec 19, 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.content; import java.util.*; public class AzureusContentDirectoryManager { private static List directories = new ArrayList(); public static void registerDirectory( AzureusContentDirectory directory ) { synchronized( directories ){ directories.add( directory ); } } public static AzureusContentDirectory[] getDirectories() { synchronized( directories ){ return((AzureusContentDirectory[])directories.toArray( new AzureusContentDirectory[directories.size()])); } } } azureus-4.3.0.6/com/aelitis/azureus/core/content/RelatedContentLookupListener.java0000644000175000017500000000205511230273374027630 0ustar adrianadrian/* * Created on Jul 15, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.content; public interface RelatedContentLookupListener { public void lookupStart(); public void contentFound( RelatedContent[] content ); public void lookupComplete(); public void lookupFailed( ContentException error ); } azureus-4.3.0.6/com/aelitis/azureus/core/content/AzureusContentFile.java0000644000175000017500000000316011224751004025576 0ustar adrianadrian/* * Created on Feb 11, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.content; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; public interface AzureusContentFile { public static final String PT_TITLE = "title"; // String public static final String PT_CREATOR = "creator"; // String public static final String PT_DATE = "date"; // Long, millis public static final String PT_DURATION = "duration"; // Long, millis public static final String PT_VIDEO_WIDTH = "video_width"; // Long public static final String PT_VIDEO_HEIGHT = "video_height"; // Long public static final String PT_CATEGORIES = "cats"; // String[] public static final String PT_PERCENT_DONE = "percent"; // Long, thousandths public static final String PT_ETA = "eta"; // Long, seconds public DiskManagerFileInfo getFile(); public Object getProperty( String name ); } azureus-4.3.0.6/com/aelitis/azureus/core/content/AzureusContentFilter.java0000644000175000017500000000207611150725256026161 0ustar adrianadrian/* * Created on Feb 23, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.content; import java.util.Map; public interface AzureusContentFilter { public boolean isVisible( AzureusContentDownload download, Map args ); public boolean isVisible( AzureusContentFile file, Map args ); } azureus-4.3.0.6/com/aelitis/azureus/core/content/AzureusContentDirectory.java0000644000175000017500000000302611171063172026667 0ustar adrianadrian/* * Created on Dec 19, 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.content; import java.util.Map; public interface AzureusContentDirectory { public static final String AT_BTIH = "btih"; // byte[] public static final String AT_FILE_INDEX = "file_index"; // Integer public AzureusContent lookupContent( Map attributes ); public AzureusContentFile lookupContentFile( Map attributes ); public AzureusContentDownload lookupContentDownload( Map attributes ); public void addListener( AzureusContentDirectoryListener listener ); public void removeListener( AzureusContentDirectoryListener listener ); } azureus-4.3.0.6/com/aelitis/azureus/core/content/RelatedContent.java0000644000175000017500000000722711271763644024747 0ustar adrianadrian/* * Created on Jul 9, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.content; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.plugins.download.Download; import com.aelitis.azureus.core.cnetwork.ContentNetwork; public abstract class RelatedContent { final private String title; final private byte[] hash; final private String tracker; final private long size; private int date; private int seeds_leechers; private byte content_network; private byte[] related_to_hash; protected RelatedContent( byte[] _related_to_hash, String _title, byte[] _hash, String _tracker, long _size, int _date, int _seeds_leechers, byte _cnet ) { related_to_hash = _related_to_hash; title = _title; hash = _hash; tracker = _tracker; size = _size; date = _date; seeds_leechers = _seeds_leechers; content_network = _cnet; } protected RelatedContent( String _title, byte[] _hash, String _tracker, long _size, int _date, int _seeds_leechers, byte _cnet ) { title = _title; hash = _hash; tracker = _tracker; size = _size; date = _date; seeds_leechers = _seeds_leechers; content_network = _cnet; } protected void setRelatedToHash( byte[] h ) { related_to_hash = h; } public byte[] getRelatedToHash() { return( related_to_hash ); } public abstract Download getRelatedToDownload(); public String getTitle() { return( title ); } public abstract int getRank(); public byte[] getHash() { return( hash ); } public abstract int getLevel(); public abstract boolean isUnread(); public abstract void setUnread( boolean unread ); public abstract int getLastSeenSecs(); public String getTracker() { return( tracker ); } public long getSize() { return( size ); } public long getPublishDate() { return( date*60*60*1000L ); } protected int getDateHours() { return( date ); } protected void setDateHours( int _date ) { date = _date; } public int getLeechers() { if ( seeds_leechers == -1 ){ return( -1 ); } return( seeds_leechers&0xffff ); } public int getSeeds() { if ( seeds_leechers == -1 ){ return( -1 ); } return( (seeds_leechers>>16) & 0xffff ); } protected int getSeedsLeechers() { return( seeds_leechers ); } protected void setSeedsLeechers( int _sl ) { seeds_leechers = _sl; } public long getContentNetwork() { return((content_network&0xff)==0xff?ContentNetwork.CONTENT_NETWORK_UNKNOWN:(content_network&0xff)); } protected void setContentNetwork( long cnet ) { content_network = (byte)cnet; } public abstract void delete(); public String getString() { return( "title=" + title + ", hash=" + (hash==null?"null":Base32.encode( hash )) + ", tracker=" + tracker +", date=" + date + ", sl=" + seeds_leechers + ", cnet=" + content_network ); } } azureus-4.3.0.6/com/aelitis/azureus/core/content/RelatedContentManagerListener.java0000644000175000017500000000215611230273374027733 0ustar adrianadrian/* * Created on Jul 9, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.content; public interface RelatedContentManagerListener { public void contentFound( RelatedContent[] content ); public void contentChanged( RelatedContent[] content ); public void contentRemoved( RelatedContent[] content ); public void contentChanged(); public void contentReset(); } azureus-4.3.0.6/com/aelitis/azureus/core/content/AzureusContentDownload.java0000644000175000017500000000177111151450620026473 0ustar adrianadrian/* * Created on Feb 23, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.content; import org.gudy.azureus2.plugins.download.Download; public interface AzureusContentDownload { public Download getDownload(); public Object getProperty( String name ); } azureus-4.3.0.6/com/aelitis/azureus/core/content/RelatedContentManager.java0000644000175000017500000025055711306326106026233 0ustar adrianadrian/* * Created on Jul 8, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.content; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.lang.ref.WeakReference; import java.net.InetSocketAddress; import java.net.URL; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Pattern; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.AsyncDispatcher; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.BEncoder; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.ByteArrayHashMap; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.RandomUtils; import org.gudy.azureus2.core3.util.SHA1Simple; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.StringInterner; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.PluginListener; import org.gudy.azureus2.plugins.ddb.DistributedDatabase; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseContact; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseException; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseKey; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseProgressListener; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseTransferHandler; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseTransferType; import org.gudy.azureus2.plugins.ddb.DistributedDatabaseValue; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadManager; import org.gudy.azureus2.plugins.download.DownloadManagerListener; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.utils.search.SearchException; import org.gudy.azureus2.plugins.utils.search.SearchInstance; import org.gudy.azureus2.plugins.utils.search.SearchObserver; import org.gudy.azureus2.plugins.utils.search.SearchProvider; import org.gudy.azureus2.plugins.utils.search.SearchResult; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.util.FeatureAvailability; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.core.util.bloom.BloomFilterFactory; import com.aelitis.azureus.plugins.dht.DHTPlugin; import com.aelitis.azureus.plugins.dht.DHTPluginContact; import com.aelitis.azureus.plugins.dht.DHTPluginOperationListener; import com.aelitis.azureus.plugins.dht.DHTPluginValue; import com.aelitis.azureus.util.ImportExportUtils; import com.aelitis.net.magneturi.MagnetURIHandler; public class RelatedContentManager implements DistributedDatabaseTransferHandler { private static final boolean TRACE = false; private static final boolean DISABLE_ALL_UI = !Constants.isCVSVersion(); private static final int MAX_HISTORY = 16; private static final int MAX_TITLE_LENGTH = 80; private static final int MAX_CONCURRENT_PUBLISH = 2; private static final int MAX_REMOTE_SEARCH_RESULTS = 30; private static final int MAX_REMOTE_SEARCH_CONTACTS = 50; private static final int MAX_REMOTE_SEARCH_MILLIS = 25*1000; private static final int TEMPORARY_SPACE_DELTA = 50; private static final int MAX_RANK = 100; private static final String CONFIG_FILE = "rcm.config"; private static final String PERSIST_DEL_FILE = "rcmx.config"; private static final String CONFIG_TOTAL_UNREAD = "rcm.numunread.cache"; private static RelatedContentManager singleton; private static AzureusCore core; public static synchronized void preInitialise( AzureusCore _core ) { core = _core; } public static synchronized RelatedContentManager getSingleton() throws ContentException { if ( singleton == null ){ singleton = new RelatedContentManager(); } return( singleton ); } private PluginInterface plugin_interface; private TorrentAttribute ta_networks; private DHTPlugin dht_plugin; private long global_random_id = -1; private LinkedList download_infos1 = new LinkedList(); private LinkedList download_infos2 = new LinkedList(); private ByteArrayHashMapEx download_info_map = new ByteArrayHashMapEx(); private Set download_priv_set = new HashSet(); private final boolean enabled; private boolean ui_enabled; private int max_search_level; private int max_results; private AtomicInteger temporary_space = new AtomicInteger(); private int publishing_count = 0; private CopyOnWriteList listeners = new CopyOnWriteList(); private AESemaphore initialisation_complete_sem = new AESemaphore( "RCM:init" ); private static final int TIMER_PERIOD = 30*1000; private static final int CONFIG_SAVE_PERIOD = 60*1000; private static final int CONFIG_SAVE_TICKS = CONFIG_SAVE_PERIOD/TIMER_PERIOD; private static final int PUBLISH_CHECK_PERIOD = 30*1000; private static final int PUBLISH_CHECK_TICKS = PUBLISH_CHECK_PERIOD/TIMER_PERIOD; private static final int SECONDARY_LOOKUP_PERIOD = 15*60*1000; private static final int SECONDARY_LOOKUP_TICKS = SECONDARY_LOOKUP_PERIOD/TIMER_PERIOD; private static final int REPUBLISH_PERIOD = 8*60*60*1000; private static final int REPUBLISH_TICKS = REPUBLISH_PERIOD/TIMER_PERIOD; private static final int INITIAL_PUBLISH_DELAY = 3*60*1000; private static final int INITIAL_PUBLISH_TICKS = INITIAL_PUBLISH_DELAY/TIMER_PERIOD; private static final int CONFIG_DISCARD_MILLIS = 60*1000; private ContentCache content_cache_ref; private WeakReference content_cache; private boolean content_dirty; private long last_config_access; private int content_discard_ticks; private AtomicInteger total_unread = new AtomicInteger( COConfigurationManager.getIntParameter( CONFIG_TOTAL_UNREAD, 0 )); private AsyncDispatcher content_change_dispatcher = new AsyncDispatcher(); private static final int SECONDARY_LOOKUP_CACHE_MAX = 10; private LinkedList secondary_lookups = new LinkedList(); private boolean secondary_lookup_in_progress; private long secondary_lookup_complete_time; private DistributedDatabase ddb; private RCMSearchXFer transfer_type = new RCMSearchXFer(); protected RelatedContentManager() throws ContentException { if ( !FeatureAvailability.isRCMEnabled()){ enabled = false; ui_enabled = false; return; } enabled = true; try{ if ( core == null ){ throw( new ContentException( "getSingleton called before pre-initialisation" )); } while( global_random_id == -1 ){ global_random_id = COConfigurationManager.getLongParameter( "rcm.random.id", -1 ); if ( global_random_id == -1 ){ global_random_id = RandomUtils.nextLong(); COConfigurationManager.setParameter( "rcm.random.id", global_random_id ); } } plugin_interface = core.getPluginManager().getDefaultPluginInterface(); ta_networks = plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_NETWORKS ); COConfigurationManager.addAndFireParameterListeners( new String[]{ "rcm.ui.enabled", "rcm.max_search_level", "rcm.max_results", }, new ParameterListener() { public void parameterChanged( String name ) { ui_enabled = COConfigurationManager.getBooleanParameter( "rcm.ui.enabled", true ) && !DISABLE_ALL_UI; max_search_level = COConfigurationManager.getIntParameter( "rcm.max_search_level", 3 ); max_results = COConfigurationManager.getIntParameter( "rcm.max_results", 500 ); } }); if ( enabled ){ if ( ui_enabled ){ try{ plugin_interface.getUtilities().registerSearchProvider( new SearchProvider() { private Map properties = new HashMap(); { properties.put( PR_NAME, MessageText.getString( "rcm.search.provider" )); try{ URL url = MagnetURIHandler.getSingleton().registerResource( new MagnetURIHandler.ResourceProvider() { public String getUID() { return( RelatedContentManager.class.getName() + ".1" ); } public String getFileType() { return( "png" ); } public byte[] getData() { InputStream is = getClass().getClassLoader().getResourceAsStream( "org/gudy/azureus2/ui/icons/rcm.png" ); if ( is == null ){ return( null ); } try{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); try{ byte[] buffer = new byte[8192]; while( true ){ int len = is.read( buffer ); if ( len <= 0 ){ break; } baos.write( buffer, 0, len ); } }finally{ is.close(); } return( baos.toByteArray()); }catch( Throwable e ){ return( null ); } } }); properties.put( PR_ICON_URL, url.toExternalForm()); }catch( Throwable e ){ Debug.out( e ); } } public SearchInstance search( Map search_parameters, SearchObserver observer ) throws SearchException { initialisation_complete_sem.reserve(); return( searchRCM( search_parameters, observer )); } public Object getProperty( int property ) { return( properties.get( property )); } public void setProperty( int property, Object value ) { properties.put( property, value ); } }); }catch( Throwable e ){ Debug.out( "Failed to register search provider" ); } } } SimpleTimer.addEvent( "rcm.delay.init", SystemTime.getOffsetTime( 15*1000 ), new TimerEventPerformer() { public void perform( TimerEvent event ) { plugin_interface.addListener( new PluginListener() { public void initializationComplete() { try{ PluginInterface dht_pi = plugin_interface.getPluginManager().getPluginInterfaceByClass( DHTPlugin.class ); if ( dht_pi != null ){ dht_plugin = (DHTPlugin)dht_pi.getPlugin(); DownloadManager dm = plugin_interface.getDownloadManager(); Download[] downloads = dm.getDownloads(); addDownloads( downloads, true ); dm.addListener( new DownloadManagerListener() { public void downloadAdded( Download download ) { addDownloads( new Download[]{ download }, false ); } public void downloadRemoved( Download download ) { } }, false ); SimpleTimer.addPeriodicEvent( "RCM:publisher", TIMER_PERIOD, new TimerEventPerformer() { private int tick_count; public void perform( TimerEvent event ) { tick_count++; if ( tick_count == 1 ){ try{ ddb = plugin_interface.getDistributedDatabase(); ddb.addTransferHandler( transfer_type, RelatedContentManager.this ); }catch( Throwable e ){ Debug.out( e ); } } if ( enabled ){ if ( tick_count >= INITIAL_PUBLISH_TICKS ){ if ( tick_count % PUBLISH_CHECK_TICKS == 0 ){ publish(); } if ( tick_count % SECONDARY_LOOKUP_TICKS == 0 ){ secondaryLookup(); } if ( tick_count % REPUBLISH_TICKS == 0 ){ republish(); } if ( tick_count % CONFIG_SAVE_TICKS == 0 ){ saveRelatedContent(); } } } } }); } }finally{ initialisation_complete_sem.releaseForever(); } } public void closedownInitiated() { saveRelatedContent(); } public void closedownComplete() { } }); } }); }catch( Throwable e ){ initialisation_complete_sem.releaseForever(); if ( e instanceof ContentException ){ throw((ContentException)e); } throw( new ContentException( "Initialisation failed", e )); } } public boolean isEnabled() { return( enabled ); } public boolean isUIEnabled() { return( ui_enabled ); } public void setUIEnabled( boolean _ui_enabled ) { COConfigurationManager.setParameter( "rcm.ui.enabled", _ui_enabled ); } public int getMaxSearchLevel() { return( max_search_level ); } public void setMaxSearchLevel( int _level ) { COConfigurationManager.setParameter( "rcm.max_search_level", _level ); } public int getMaxResults() { return( max_results ); } public void setMaxResults( int _max ) { COConfigurationManager.setParameter( "rcm.max_results", _max ); enforceMaxResults( false ); } protected void addDownloads( Download[] downloads, boolean initialising ) { synchronized( this ){ List new_info = new ArrayList( downloads.length ); for ( Download download: downloads ){ try{ if ( !download.isPersistent()){ continue; } Torrent torrent = download.getTorrent(); if ( torrent == null ){ continue; } byte[] hash = torrent.getHash(); if ( download_info_map.containsKey( hash )){ continue; } String[] networks = download.getListAttribute( ta_networks ); if ( networks == null ){ continue; } boolean public_net = false; for (int i=0;i>32)&0x00ffffff); int leechers = (int)(cache&0x00ffffff); seeds_leechers = (int)((seeds<<16)|(leechers&0xffff)); } DownloadInfo info = new DownloadInfo( hash, hash, download.getName(), (int)rand, torrent.isPrivate()?StringInterner.intern(torrent.getAnnounceURL().getHost()):null, 0, false, torrent.getSize(), (int)( to_torrent.getCreationDate()/(60*60)), seeds_leechers, (byte)PlatformTorrentUtils.getContentNetworkID( to_torrent )); new_info.add( info ); if ( initialising || download_infos1.size() == 0 ){ download_infos1.add( info ); }else{ download_infos1.add( RandomUtils.nextInt( download_infos1.size()), info ); } download_infos2.add( info ); download_info_map.put( hash, info ); if ( info.getTracker() != null ){ download_priv_set.add( getPrivateInfoKey( info )); } } }catch( Throwable e ){ Debug.out( e ); } } List> history = (List>)COConfigurationManager.getListParameter( "rcm.dlinfo.history", new ArrayList>()); if ( initialising ){ int padd = MAX_HISTORY - download_info_map.size(); for ( int i=0;i 0;i++ ){ try{ DownloadInfo info = deserialiseDI((Map)history.get(i), null); if ( info != null && !download_info_map.containsKey( info.getHash())){ download_info_map.put( info.getHash(), info ); if ( info.getTracker() != null ){ download_priv_set.add( getPrivateInfoKey( info )); } download_infos1.add( info ); download_infos2.add( info ); padd--; } }catch( Throwable e ){ } } Collections.shuffle( download_infos1 ); }else{ if ( new_info.size() > 0 ){ for ( DownloadInfo info: new_info ){ Map map = serialiseDI( info, null ); if ( map != null ){ history.add( map ); } } while( history.size() > MAX_HISTORY ){ history.remove(0); } COConfigurationManager.setParameter( "rcm.dlinfo.history", history ); } } } } protected void republish() { synchronized( this ){ if( publishing_count > 0 ){ return; } if ( download_infos1.isEmpty()){ List list = download_info_map.values(); download_infos1.addAll( list ); download_infos2.addAll( list ); Collections.shuffle( download_infos1 ); } } } protected void publish() { while( true ){ DownloadInfo info1 = null; DownloadInfo info2 = null; synchronized( this ){ if ( publishing_count >= MAX_CONCURRENT_PUBLISH ){ return; } if ( download_infos1.isEmpty() || download_info_map.size() == 1 ){ return; } info1 = download_infos1.removeFirst(); Iterator it = download_infos2.iterator(); while( it.hasNext()){ info2 = it.next(); if ( info1 != info2 || download_infos2.size() == 1 ){ it.remove(); break; } } if ( info1 == info2 ){ info2 = download_info_map.getRandomValueExcluding( info1 ); if ( info2 == null || info1 == info2 ){ Debug.out( "Inconsistent!" ); return; } } publishing_count++; } try{ publish( info1, info2 ); }catch( Throwable e ){ synchronized( this ){ publishing_count--; } Debug.out( e ); } } } protected void publishNext() { synchronized( this ){ publishing_count--; if ( publishing_count < 0 ){ // shouldn't happen but whatever publishing_count = 0; } } publish(); } protected void publish( final DownloadInfo from_info, final DownloadInfo to_info ) throws Exception { final String from_hash = ByteFormatter.encodeString( from_info.getHash()); final String to_hash = ByteFormatter.encodeString( to_info.getHash()); final byte[] key_bytes = ( "az:rcm:assoc:" + from_hash ).getBytes( "UTF-8" ); String title = to_info.getTitle(); if ( title.length() > MAX_TITLE_LENGTH ){ title = title.substring( 0, MAX_TITLE_LENGTH ); } Map map = new HashMap(); map.put( "d", title ); map.put( "r", new Long( Math.abs( to_info.getRand()%1000 ))); String tracker = to_info.getTracker(); if ( tracker == null ){ map.put( "h", to_info.getHash()); }else{ map.put( "t", tracker ); } if ( to_info.getLevel() == 0 ){ try{ Download d = to_info.getRelatedToDownload(); if ( d != null ){ Torrent torrent = d.getTorrent(); if ( torrent != null ){ long cnet = PlatformTorrentUtils.getContentNetworkID( PluginCoreUtils.unwrap( torrent )); if ( cnet != ContentNetwork.CONTENT_NETWORK_UNKNOWN ){ map.put( "c", new Long( cnet )); } long secs = torrent.getCreationDate(); long hours = secs/(60*60); if ( hours > 0 ){ map.put( "p", new Long( hours )); } } int leechers = -1; int seeds = -1; long cache = PluginCoreUtils.unwrap( d ).getDownloadState().getLongAttribute( DownloadManagerState.AT_SCRAPE_CACHE ); if ( cache != -1 ){ seeds = (int)((cache>>32)&0x00ffffff); leechers = (int)(cache&0x00ffffff); } if ( leechers > 0 ){ map.put( "l", new Long( leechers )); } if ( seeds > 0 ){ map.put( "z", new Long( seeds )); } } }catch( Throwable e ){ } } long size = to_info.getSize(); if ( size != 0 ){ map.put( "s", new Long( size )); } final byte[] map_bytes = BEncoder.encode( map ); final int max_hits = 30; dht_plugin.get( key_bytes, "Content relationship read: " + from_hash, DHTPlugin.FLAG_SINGLE_VALUE, max_hits, 30*1000, false, false, new DHTPluginOperationListener() { private boolean diversified; private int hits; private Set entries = new HashSet(); public void starts( byte[] key ) { } public void diversified() { diversified = true; } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { try{ Map map = (Map)BDecoder.decode( value.getValue()); String title = new String((byte[])map.get( "d" ), "UTF-8" ); String tracker = null; byte[] hash = (byte[])map.get( "h" ); if ( hash == null ){ tracker = new String((byte[])map.get( "t" ), "UTF-8" ); } int rand = ((Long)map.get( "r" )).intValue(); String key = title + " % " + rand; synchronized( entries ){ if ( entries.contains( key )){ return; } entries.add( key ); } Long l_size = (Long)map.get( "s" ); long size = l_size==null?0:l_size.longValue(); Long cnet = (Long)map.get( "c" ); Long published = (Long)map.get( "p" ); Long leechers = (Long)map.get( "l" ); Long seeds = (Long)map.get( "z" ); // System.out.println( "p=" + published + ", l=" + leechers + ", s=" + seeds ); int seeds_leechers; if ( leechers == null && seeds == null ){ seeds_leechers = -1; }else if ( leechers == null ){ seeds_leechers = seeds.intValue()<<16; }else if ( seeds == null ){ seeds_leechers = leechers.intValue()&0xffff; }else{ seeds_leechers = (seeds.intValue()<<16)|(leechers.intValue()&0xffff); } analyseResponse( new DownloadInfo( from_info.getHash(), hash, title, rand, tracker, 1, false, size, published==null?0:published.intValue(), seeds_leechers, (byte)(cnet==null?ContentNetwork.CONTENT_NETWORK_UNKNOWN:cnet.byteValue())), null ); }catch( Throwable e ){ } hits++; } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] key, boolean timeout_occurred ) { boolean do_it; // System.out.println( from_hash + ": hits=" + hits + ", div=" + diversified ); if ( diversified || hits >= 10 ){ do_it = false; }else if ( hits <= 5 ){ do_it = true; }else{ do_it = RandomUtils.nextInt( hits - 5 + 1 ) == 0; } if ( do_it ){ try{ dht_plugin.put( key_bytes, "Content relationship: " + from_hash + " -> " + to_hash, map_bytes, DHTPlugin.FLAG_ANON, new DHTPluginOperationListener() { public void diversified() { } public void starts( byte[] key ) { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] key, boolean timeout_occurred ) { publishNext(); } }); }catch( Throwable e ){ Debug.printStackTrace(e); publishNext(); } }else{ publishNext(); } } }); } public void lookupContent( final byte[] hash, final RelatedContentLookupListener listener ) throws ContentException { if ( hash == null ){ throw( new ContentException( "hash is null" )); } if ( !initialisation_complete_sem.isReleasedForever() || ( dht_plugin != null && dht_plugin.isInitialising())){ AsyncDispatcher dispatcher = new AsyncDispatcher(); dispatcher.dispatch( new AERunnable() { public void runSupport() { try{ initialisation_complete_sem.reserve(); lookupContentSupport( hash, 0, true, listener ); }catch( ContentException e ){ Debug.out( e ); } } }); }else{ lookupContentSupport( hash, 0, true, listener ); } } private void lookupContentSupport( final byte[] from_hash, final int level, final boolean explicit, final RelatedContentLookupListener listener ) throws ContentException { try{ if ( dht_plugin == null ){ throw( new ContentException( "DHT plugin unavailable" )); } final String from_hash_str = ByteFormatter.encodeString( from_hash ); final byte[] key_bytes = ( "az:rcm:assoc:" + from_hash_str ).getBytes( "UTF-8" ); final int max_hits = 30; dht_plugin.get( key_bytes, "Content relationship read: " + from_hash_str, DHTPlugin.FLAG_SINGLE_VALUE, max_hits, 60*1000, false, true, new DHTPluginOperationListener() { private Set entries = new HashSet(); private RelatedContentManagerListener manager_listener = new RelatedContentManagerListener() { private Set content_list = new HashSet(); public void contentFound( RelatedContent[] content ) { handle( content ); } public void contentChanged( RelatedContent[] content ) { handle( content ); } public void contentRemoved( RelatedContent[] content ) { } public void contentChanged() { } public void contentReset() { } private void handle( RelatedContent[] content ) { synchronized( content_list ){ if ( content_list.contains( content )){ return; } for ( RelatedContent c: content ){ content_list.add( c ); } } listener.contentFound( content ); } }; public void starts( byte[] key ) { if ( listener != null ){ try{ listener.lookupStart(); }catch( Throwable e ){ Debug.out( e ); } } } public void diversified() { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { try{ Map map = (Map)BDecoder.decode( value.getValue()); String title = new String((byte[])map.get( "d" ), "UTF-8" ); String tracker = null; byte[] hash = (byte[])map.get( "h" ); if ( hash == null ){ tracker = new String((byte[])map.get( "t" ), "UTF-8" ); } int rand = ((Long)map.get( "r" )).intValue(); String key = title + " % " + rand; synchronized( entries ){ if ( entries.contains( key )){ return; } entries.add( key ); } Long l_size = (Long)map.get( "s" ); long size = l_size==null?0:l_size.longValue(); Long cnet = (Long)map.get( "c" ); Long published = (Long)map.get( "p" ); Long leechers = (Long)map.get( "l" ); Long seeds = (Long)map.get( "z" ); int seeds_leechers; if ( leechers == null && seeds == null ){ seeds_leechers = -1; }else if ( leechers == null ){ seeds_leechers = seeds.intValue()<<16; }else if ( seeds == null ){ seeds_leechers = leechers.intValue()&0xffff; }else{ seeds_leechers = (seeds.intValue()<<16)|(leechers.intValue()&0xffff); } analyseResponse( new DownloadInfo( from_hash, hash, title, rand, tracker, level+1, explicit, size, published==null?0:published.intValue(), seeds_leechers, (byte)(cnet==null?ContentNetwork.CONTENT_NETWORK_UNKNOWN:cnet.byteValue())), listener==null?null:manager_listener ); }catch( Throwable e ){ } } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] key, boolean timeout_occurred ) { if ( listener != null ){ try{ listener.lookupComplete(); }catch( Throwable e ){ Debug.out( e ); } } } }); }catch( Throwable e ){ ContentException ce; if ( ( e instanceof ContentException )){ ce = (ContentException)e; }else{ ce = new ContentException( "Lookup failed", e ); } if ( listener != null ){ try{ listener.lookupFailed( ce ); }catch( Throwable f ){ Debug.out( f ); } } throw( ce ); } } protected void popuplateSecondaryLookups( ContentCache content_cache ) { Random rand = new Random(); secondary_lookups.clear(); // stuff in a couple primarys List primaries = download_info_map.values(); int primary_count = primaries.size(); int primaries_to_add; if ( primary_count < 2 ){ primaries_to_add = 0; }else if ( primary_count < 5 ){ if ( rand.nextInt(4) == 0 ){ primaries_to_add = 1; }else{ primaries_to_add = 0; } }else if ( primary_count < 10 ){ primaries_to_add = 1; }else{ primaries_to_add = 2; } if ( primaries_to_add > 0 ){ Set added = new HashSet(); for (int i=0;i related_content = content_cache.related_content; Iterator it = related_content.values().iterator(); List secondary_cache_temp = new ArrayList( related_content.size()); while( it.hasNext()){ DownloadInfo di = it.next(); if ( di.getHash() != null && di.getLevel() < max_search_level ){ secondary_cache_temp.add( di ); } } final int cache_size = Math.min( secondary_cache_temp.size(), SECONDARY_LOOKUP_CACHE_MAX - secondary_lookups.size()); if ( cache_size > 0 ){ for( int i=0;i related_content = content_cache.related_content; Iterator it = related_content.values().iterator(); while( it.hasNext()){ DownloadInfo di = it.next(); for ( RelatedContent c: content ){ if ( c == di ){ it.remove(); if ( di.isUnread()){ decrementUnread(); } } } } ByteArrayHashMapEx> related_content_map = content_cache.related_content_map; List delete = new ArrayList(); for ( byte[] key: related_content_map.keys()){ ArrayList infos = related_content_map.get( key ); for ( RelatedContent c: content ){ if ( infos.remove( c )){ if ( infos.size() == 0 ){ delete.add( key ); break; } } } } for ( byte[] key: delete ){ related_content_map.remove( key ); } setConfigDirty(); content_change_dispatcher.dispatch( new AERunnable() { public void runSupport() { for ( RelatedContentManagerListener l: listeners ){ try{ l.contentRemoved( content ); }catch( Throwable e ){ Debug.out( e ); } } } }); } protected String getPrivateInfoKey( RelatedContent info ) { return( info.getTitle() + ":" + info.getTracker()); } protected void analyseResponse( DownloadInfo to_info, final RelatedContentManagerListener listener ) { try{ synchronized( this ){ byte[] target = to_info.getHash(); String key; if ( target != null ){ if ( download_info_map.containsKey( target )){ // target refers to downoad we already have return; } key = Base32.encode( target ); }else{ key = getPrivateInfoKey( to_info ); if ( download_priv_set.contains( key )){ // target refers to downoad we already have return; } } if ( isPersistentlyDeleted( to_info )){ return; } ContentCache content_cache = loadRelatedContent(); DownloadInfo target_info = null; boolean changed_content = false; boolean new_content = false; target_info = content_cache.related_content.get( key ); if ( target_info == null ){ if ( enoughSpaceFor( content_cache, to_info )){ target_info = to_info; content_cache.related_content.put( key, target_info ); byte[] from_hash = to_info.getRelatedToHash(); ArrayList links = content_cache.related_content_map.get( from_hash ); if ( links == null ){ links = new ArrayList(1); content_cache.related_content_map.put( from_hash, links ); } links.add( target_info ); links.trimToSize(); target_info.setPublic( content_cache ); if ( secondary_lookups.size() < SECONDARY_LOOKUP_CACHE_MAX ){ byte[] hash = target_info.getHash(); int level = target_info.getLevel(); if ( hash != null && level < max_search_level ){ secondary_lookups.add( new SecondaryLookup( hash, level )); } } new_content = true; } }else{ // we already know about this, see if new info changed_content = target_info.addInfo( to_info ); } if ( target_info != null ){ final RelatedContent[] f_target = new RelatedContent[]{ target_info }; final boolean f_change = changed_content; final boolean something_changed = changed_content || new_content; if ( something_changed ){ setConfigDirty(); } content_change_dispatcher.dispatch( new AERunnable() { public void runSupport() { if ( something_changed ){ for ( RelatedContentManagerListener l: listeners ){ try{ if ( f_change ){ l.contentChanged( f_target ); }else{ l.contentFound( f_target ); } }catch( Throwable e ){ Debug.out( e ); } } } if ( listener != null ){ try{ if ( f_change ){ listener.contentChanged( f_target ); }else{ listener.contentFound( f_target ); } }catch( Throwable e ){ Debug.out( e ); } } } }); } } }catch( Throwable e ){ Debug.out( e ); } } protected boolean enoughSpaceFor( ContentCache content_cache, DownloadInfo fi ) { Map related_content = content_cache.related_content; if ( related_content.size() < max_results + temporary_space.get()){ return( true ); } Iterator> it = related_content.entrySet().iterator(); int level = fi.getLevel(); // delete oldest at highest level >= level with minimum rank Map oldest_per_rank = new HashMap(); int min_rank = Integer.MAX_VALUE; while( it.hasNext()){ Map.Entry entry = it.next(); DownloadInfo info = entry.getValue(); if ( info.isExplicit()){ continue; } int info_level = info.getLevel(); if ( info_level >= level ){ if ( info_level > level ){ level = info_level; min_rank = Integer.MAX_VALUE; oldest_per_rank.clear(); } int rank = info.getRank(); if ( rank < min_rank ){ min_rank = rank; } DownloadInfo oldest = oldest_per_rank.get( rank ); if ( oldest == null ){ oldest_per_rank.put( rank, info ); }else{ if ( info.getLastSeenSecs() < oldest.getLastSeenSecs()){ oldest_per_rank.put( rank, info ); } } } } DownloadInfo to_remove = oldest_per_rank.get( min_rank ); if ( to_remove != null ){ delete( new RelatedContent[]{ to_remove }, content_cache, false ); return( true ); } return( false ); } public RelatedContent[] getRelatedContent() { synchronized( this ){ ContentCache content_cache = loadRelatedContent(); return( content_cache.related_content.values().toArray( new DownloadInfo[ content_cache.related_content.size()])); } } public void reset() { reset( true ); } protected void reset( boolean reset_perm_dels ) { synchronized( this ){ ContentCache cc = content_cache==null?null:content_cache.get(); if ( cc == null ){ FileUtil.deleteResilientConfigFile( CONFIG_FILE ); }else{ cc.related_content = new HashMap(); cc.related_content_map = new ByteArrayHashMapEx>(); } download_infos1.clear(); download_infos2.clear(); List list = download_info_map.values(); download_infos1.addAll( list ); download_infos2.addAll( list ); Collections.shuffle( download_infos1 ); total_unread.set( 0 ); if ( reset_perm_dels ){ resetPersistentlyDeleted(); } setConfigDirty(); } content_change_dispatcher.dispatch( new AERunnable() { public void runSupport() { for ( RelatedContentManagerListener l: listeners ){ l.contentReset(); } } }); } protected List matchContent( String term ) { // term is made up of space separated bits - all bits must match // each bit can be prefixed by + or -, a leading - means 'bit doesn't match'. + doesn't mean anything // each bit (with prefix removed) can be "(" regexp ")" // if bit isn't regexp but has "|" in it it is turned into a regexp so a|b means 'a or b' List result = new ArrayList(); RelatedContent[] content = getRelatedContent(); String[] bits = term.toLowerCase().split( " " ); int[] bit_types = new int[bits.length]; Pattern[] bit_patterns = new Pattern[bits.length]; for (int i=0;i 0 ){ char c = bit.charAt(0); if ( c == '+' ){ bit_types[i] = 1; bit = bits[i] = bit.substring(1); }else if ( c == '-' ){ bit_types[i] = 2; bit = bits[i] = bit.substring(1); } if ( bit.startsWith( "(" ) && bit.endsWith((")"))){ bit = bit.substring( 1, bit.length()-1 ); try{ bit_patterns[i] = Pattern.compile( bit, Pattern.CASE_INSENSITIVE ); }catch( Throwable e ){ } }else if ( bit.contains( "|" )){ try{ bit_patterns[i] = Pattern.compile( bit, Pattern.CASE_INSENSITIVE ); }catch( Throwable e ){ } } } } for ( final RelatedContent c: content ){ String title = c.getTitle().toLowerCase(); boolean match = true; boolean at_least_one = false; for (int i=0;i 0 ){ boolean hit; if ( bit_patterns[i] == null ){ hit = title.contains( bit ); }else{ hit = bit_patterns[i].matcher( title ).find(); } int type = bit_types[i]; if ( hit ){ if ( type == 2 ){ match = false; break; }else{ at_least_one = true; } }else{ if ( type == 2 ){ at_least_one = true; }else{ match = false; break; } } } } if ( match && at_least_one ){ result.add( c ); } } return( result ); } protected SearchInstance searchRCM( Map search_parameters, final SearchObserver observer ) throws SearchException { final String term = (String)search_parameters.get( SearchProvider.SP_SEARCH_TERM ); final SearchInstance si = new SearchInstance() { public void cancel() { Debug.out( "Cancelled" ); } }; if ( term == null ){ observer.complete(); }else{ new AEThread2( "RCM:search", true ) { public void run() { final Set hashes = new HashSet(); try{ List matches = matchContent( term ); for ( final RelatedContent c: matches ){ final byte[] hash = c.getHash(); if ( hash == null ){ continue; } hashes.add( Base32.encode( hash )); SearchResult result = new SearchResult() { public Object getProperty( int property_name ) { if ( property_name == SearchResult.PR_NAME ){ return( c.getTitle()); }else if ( property_name == SearchResult.PR_SIZE ){ return( c.getSize()); }else if ( property_name == SearchResult.PR_HASH ){ return( hash ); }else if ( property_name == SearchResult.PR_RANK ){ // this rank isn't that accurate, scale down return( new Long( c.getRank() / 4 )); }else if ( property_name == SearchResult.PR_SEED_COUNT ){ return( new Long( c.getSeeds())); }else if ( property_name == SearchResult.PR_LEECHER_COUNT ){ return( new Long( c.getLeechers())); }else if ( property_name == SearchResult.PR_SUPER_SEED_COUNT ){ if ( c.getContentNetwork() != ContentNetwork.CONTENT_NETWORK_UNKNOWN ){ return( new Long( 1 )); }else{ return( new Long( 0 )); } }else if ( property_name == SearchResult.PR_PUB_DATE ){ long date = c.getPublishDate(); if ( date <= 0 ){ return( null ); } return( new Date( date )); }else if ( property_name == SearchResult.PR_DOWNLOAD_LINK || property_name == SearchResult.PR_DOWNLOAD_BUTTON_LINK ){ byte[] hash = c.getHash(); if ( hash != null ){ return( UrlUtils.getMagnetURI( hash )); } } return( null ); } }; observer.resultReceived( si, result ); } }finally{ try{ DHT[] dhts = dht_plugin.getDHTs(); Set addresses = new HashSet(); for ( DHT dht: dhts ){ DHTTransportContact[] contacts = dht.getTransport().getReachableContacts(); for ( DHTTransportContact c: contacts ){ if ( c.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ){ addresses.add( c.getAddress()); } } } if ( addresses.size() < MAX_REMOTE_SEARCH_CONTACTS ){ for ( DHT dht: dhts ){ DHTTransportContact[] contacts = dht.getTransport().getRecentContacts(); for ( DHTTransportContact c: contacts ){ if ( c.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ){ addresses.add( c.getAddress()); if ( addresses.size() >= MAX_REMOTE_SEARCH_CONTACTS ){ break; } } } if ( addresses.size() >= MAX_REMOTE_SEARCH_CONTACTS ){ break; } } } List list = new ArrayList( addresses ); Collections.shuffle( list ); List ddb_contacts = new ArrayList(); for (int i=0;i= ddb_contacts.size() / 2 ){ start = SystemTime.getMonotonousTime(); max = 5*1000; break; } } if ( i > 10 ){ try{ Thread.sleep( 250 ); }catch( Throwable e ){ } } } for (int i=0;i sent*4/5 ){ break; } long elapsed = SystemTime.getMonotonousTime() - start; if ( elapsed < max ){ sem.reserve( max - elapsed ); }else{ break; } } }finally{ observer.complete(); } } } }.start(); } return( si ); } protected void sendRemoteSearch( SearchInstance si, Set hashes, DistributedDatabaseContact contact, String term, SearchObserver observer ) { try{ Map request = new HashMap(); request.put( "t", term ); DistributedDatabaseKey key = ddb.createKey( BEncoder.encode( request )); DistributedDatabaseValue value = contact.read( new DistributedDatabaseProgressListener() { public void reportSize( long size ) { } public void reportActivity( String str ) { } public void reportCompleteness( int percent ) { } }, transfer_type, key, 10000 ); // System.out.println( "search result=" + value ); if ( value == null ){ return; } Map reply = (Map)BDecoder.decode((byte[])value.getValue( byte[].class )); List> list = (List>)reply.get( "l" ); for ( final Map map: list ){ final String title = ImportExportUtils.importString( map, "n" ); final byte[] hash = (byte[])map.get( "h" ); if ( hash == null ){ continue; } String hash_str = Base32.encode( hash ); if ( hashes.contains( hash_str )){ continue; } hashes.add( hash_str ); SearchResult result = new SearchResult() { public Object getProperty( int property_name ) { try{ if ( property_name == SearchResult.PR_NAME ){ return( title ); }else if ( property_name == SearchResult.PR_SIZE ){ return( ImportExportUtils.importLong( map, "s" )); }else if ( property_name == SearchResult.PR_HASH ){ return( hash ); }else if ( property_name == SearchResult.PR_RANK ){ return( ImportExportUtils.importLong( map, "r" ) / 4 ); }else if ( property_name == SearchResult.PR_SUPER_SEED_COUNT ){ long cnet = ImportExportUtils.importLong( map, "c", ContentNetwork.CONTENT_NETWORK_UNKNOWN ); if ( cnet == ContentNetwork.CONTENT_NETWORK_UNKNOWN ){ return( 0L ); }else{ return( 1L ); } }else if ( property_name == SearchResult.PR_SEED_COUNT ){ return( ImportExportUtils.importLong( map, "z" )); }else if ( property_name == SearchResult.PR_LEECHER_COUNT ){ return( ImportExportUtils.importLong( map, "l" )); }else if ( property_name == SearchResult.PR_PUB_DATE ){ long date = ImportExportUtils.importLong( map, "p", 0 )*60*60*1000L; if ( date <= 0 ){ return( null ); } return( new Date( date )); }else if ( property_name == SearchResult.PR_DOWNLOAD_LINK || property_name == SearchResult.PR_DOWNLOAD_BUTTON_LINK ){ byte[] hash = (byte[])map.get( "h" ); if ( hash != null ){ return( UrlUtils.getMagnetURI( hash )); } } }catch( Throwable e ){ } return( null ); } }; observer.resultReceived( si, result ); } }catch( Throwable e ){ } } protected Map receiveRemoteSearch( Map request ) { Map response = new HashMap(); try{ String term = ImportExportUtils.importString( request, "t" ); if ( term != null ){ List matches = matchContent( term ); if ( matches.size() > MAX_REMOTE_SEARCH_RESULTS ){ Collections.sort( matches, new Comparator() { public int compare( RelatedContent o1, RelatedContent o2) { return( o2.getRank() - o1.getRank()); } }); } List> list = new ArrayList>(); for (int i=0;i map = new HashMap(); list.add( map ); ImportExportUtils.exportString( map, "n", c.getTitle()); ImportExportUtils.exportLong( map, "s", c.getSize()); ImportExportUtils.exportLong( map, "r", c.getRank()); ImportExportUtils.exportLong( map, "d", c.getLastSeenSecs()); ImportExportUtils.exportLong( map, "p", c.getPublishDate()/(60*60*1000)); ImportExportUtils.exportLong( map, "l", c.getLeechers()); ImportExportUtils.exportLong( map, "z", c.getSeeds()); ImportExportUtils.exportLong( map, "c", c.getContentNetwork()); byte[] hash = c.getHash(); if ( hash != null ){ map.put( "h", hash ); } } response.put( "l", list ); } }catch( Throwable e ){ } return( response ); } public DistributedDatabaseValue read( DistributedDatabaseContact contact, DistributedDatabaseTransferType type, DistributedDatabaseKey ddb_key ) throws DistributedDatabaseException { Object o_key = ddb_key.getKey(); try{ byte[] key = (byte[])o_key; // TODO bloom Map request = BDecoder.decode( key ); Map result = receiveRemoteSearch( request ); return( ddb.createValue( BEncoder.encode( result ))); }catch( Throwable e ){ Debug.out( e ); return( null ); } } public void write( DistributedDatabaseContact contact, DistributedDatabaseTransferType type, DistributedDatabaseKey key, DistributedDatabaseValue value ) throws DistributedDatabaseException { } protected void setConfigDirty() { synchronized( this ){ content_dirty = true; } } protected ContentCache loadRelatedContent() { boolean fire_event = false; try{ synchronized( this ){ last_config_access = SystemTime.getMonotonousTime(); ContentCache cc = content_cache==null?null:content_cache.get(); if ( cc == null ){ if ( TRACE ){ System.out.println( "rcm: load new" ); } fire_event = true; cc = new ContentCache(); content_cache = new WeakReference( cc ); try{ int new_total_unread = 0; if ( FileUtil.resilientConfigFileExists( CONFIG_FILE )){ Map map = FileUtil.readResilientConfigFile( CONFIG_FILE ); Map related_content = cc.related_content; ByteArrayHashMapEx> related_content_map = cc.related_content_map; Map rcm_map = (Map)map.get( "rcm" ); Object rc_map_stuff = map.get( "rc" ); if ( rc_map_stuff != null && rcm_map != null ){ Map id_map = new HashMap(); if ( rc_map_stuff instanceof Map ){ // migration from when it was a Map with non-ascii key issues Map> rc_map = (Map>)rc_map_stuff; for ( Map.Entry> entry: rc_map.entrySet()){ try{ String key = entry.getKey(); Map info_map = entry.getValue(); DownloadInfo info = deserialiseDI( info_map, cc ); if ( info.isUnread()){ new_total_unread++; } related_content.put( key, info ); int id = ((Long)info_map.get( "_i" )).intValue(); id_map.put( id, info ); }catch( Throwable e ){ Debug.out( e ); } } }else{ List> rc_map_list = (List>)rc_map_stuff; for ( Map info_map: rc_map_list ){ try{ String key = new String((byte[])info_map.get( "_k" ), "UTF-8" ); DownloadInfo info = deserialiseDI( info_map, cc ); if ( info.isUnread()){ new_total_unread++; } related_content.put( key, info ); int id = ((Long)info_map.get( "_i" )).intValue(); id_map.put( id, info ); }catch( Throwable e ){ Debug.out( e ); } } } if ( rcm_map.size() != 0 && id_map.size() != 0 ){ for ( String key: rcm_map.keySet()){ try{ byte[] hash = Base32.decode( key ); int[] ids = ImportExportUtils.importIntArray( rcm_map, key ); if ( ids == null || ids.length == 0 ){ Debug.out( "Inconsistent - no ids" ); }else{ ArrayList di_list = new ArrayList(ids.length); for ( int id: ids ){ DownloadInfo di = id_map.get( id ); if ( di == null ){ Debug.out( "Inconsistent: id " + id + " missing" ); }else{ // we don't currently remember all originators, just one that works di.setRelatedToHash( hash ); di_list.add( di ); } } if ( di_list.size() > 0 ){ related_content_map.put( hash, di_list ); } } }catch( Throwable e ){ Debug.out( e ); } } } Iterator it = related_content.values().iterator(); while( it.hasNext()){ DownloadInfo di = it.next(); if ( di.getRelatedToHash() == null ){ Debug.out( "Inconsistent: info not referenced" ); if ( di.isUnread()){ new_total_unread--; } it.remove(); } } popuplateSecondaryLookups( cc ); } } if ( total_unread.get() != new_total_unread ){ Debug.out( "total_unread - inconsistent (" + total_unread + "/" + new_total_unread + ")" ); total_unread.set( new_total_unread ); COConfigurationManager.setParameter( CONFIG_TOTAL_UNREAD, new_total_unread ); } }catch( Throwable e ){ Debug.out( e ); } enforceMaxResults( cc, false ); }else{ if ( TRACE ){ System.out.println( "rcm: load existing" ); } } content_cache_ref = cc; return( cc ); } }finally{ if ( fire_event ){ contentChanged( false ); } } } protected void saveRelatedContent() { synchronized( this ){ COConfigurationManager.setParameter( CONFIG_TOTAL_UNREAD, total_unread.get()); long now = SystemTime.getMonotonousTime();; ContentCache cc = content_cache==null?null:content_cache.get(); if ( !content_dirty ){ if ( cc != null ){ if ( now - last_config_access > CONFIG_DISCARD_MILLIS ){ if ( content_cache_ref != null ){ content_discard_ticks = 0; } if ( TRACE ){ System.out.println( "rcm: discard: tick count=" + content_discard_ticks++ ); } content_cache_ref = null; } }else{ if ( TRACE ){ System.out.println( "rcm: discarded" ); } } return; } last_config_access = now; content_dirty = false; if ( cc == null ){ Debug.out( "RCM: cache inconsistent" ); }else{ if ( TRACE ){ System.out.println( "rcm: save" ); } Map related_content = cc.related_content; ByteArrayHashMapEx> related_content_map = cc.related_content_map; if ( related_content.size() == 0 ){ FileUtil.deleteResilientConfigFile( CONFIG_FILE ); }else{ Map map = new HashMap(); Set> rcs = related_content.entrySet(); List> rc_map_list = new ArrayList>( rcs.size()); map.put( "rc", rc_map_list ); int id = 0; Map info_map = new HashMap(); for ( Map.Entry entry: rcs ){ DownloadInfo info = entry.getValue(); Map di_map = serialiseDI( info, cc ); if ( di_map != null ){ info_map.put( info, id ); di_map.put( "_i", new Long( id )); di_map.put( "_k", entry.getKey()); if ( rc_map_list.add( di_map )); id++; } } Map rcm_map = new HashMap(); map.put( "rcm", rcm_map ); for ( byte[] hash: related_content_map.keys()){ List dis = related_content_map.get( hash ); int[] ids = new int[dis.size()]; int pos = 0; for ( DownloadInfo di: dis ){ Integer index = info_map.get( di ); if ( index == null ){ Debug.out( "inconsistent: info missing for " + di ); break; }else{ ids[pos++] = index; } } if ( pos == ids.length ){ ImportExportUtils.exportIntArray( rcm_map, Base32.encode( hash), ids ); } } FileUtil.writeResilientConfigFile( CONFIG_FILE, map ); } } } } public int getNumUnread() { return( total_unread.get()); } public void setAllRead() { boolean changed = false; synchronized( this ){ DownloadInfo[] content = (DownloadInfo[])getRelatedContent(); for ( DownloadInfo c: content ){ if ( c.isUnread()){ changed = true; c.setUnreadInternal( false ); } } total_unread.set( 0 ); } if ( changed ){ contentChanged( true ); } } public void deleteAll() { synchronized( this ){ ContentCache content_cache = loadRelatedContent(); addPersistentlyDeleted( content_cache.related_content.values().toArray( new DownloadInfo[ content_cache.related_content.size()])); reset( false ); } } protected void incrementUnread() { total_unread.incrementAndGet(); } protected void decrementUnread() { synchronized( this ){ int val = total_unread.decrementAndGet(); if ( val < 0 ){ Debug.out( "inconsistent" ); total_unread.set( 0 ); } } } protected Download getDownload( byte[] hash ) { try{ return( plugin_interface.getDownloadManager().getDownload( hash )); }catch( Throwable e ){ return( null ); } } private static final int PD_BLOOM_INITIAL_SIZE = 1000; private static final int PD_BLOOM_INCREMENT_SIZE = 1000; private BloomFilter persist_del_bloom; protected byte[] getPermDelKey( RelatedContent info ) { byte[] bytes = info.getHash(); if ( bytes == null ){ try{ bytes = new SHA1Simple().calculateHash( getPrivateInfoKey(info).getBytes( "ISO-8859-1" )); }catch( Throwable e ){ Debug.out( e ); return( null ); } } byte[] key = new byte[8]; System.arraycopy( bytes, 0, key, 0, 8 ); return( key ); } protected List loadPersistentlyDeleted() { List entries = null; if ( FileUtil.resilientConfigFileExists( PERSIST_DEL_FILE )){ Map map = (Map)FileUtil.readResilientConfigFile( PERSIST_DEL_FILE ); entries = (List)map.get( "entries" ); } if ( entries == null ){ entries = new ArrayList(0); } return( entries ); } protected void addPersistentlyDeleted( RelatedContent[] content ) { if ( content.length == 0 ){ return; } List entries = loadPersistentlyDeleted(); List new_keys = new ArrayList( content.length ); for ( RelatedContent rc: content ){ byte[] key = getPermDelKey( rc ); new_keys.add( key ); entries.add( key ); } Map map = new HashMap(); map.put( "entries", entries ); FileUtil.writeResilientConfigFile( PERSIST_DEL_FILE, map ); if ( persist_del_bloom != null ){ if ( persist_del_bloom.getSize() / ( persist_del_bloom.getEntryCount() + content.length ) < 10 ){ persist_del_bloom = BloomFilterFactory.createAddOnly( Math.max( PD_BLOOM_INITIAL_SIZE, persist_del_bloom.getSize() *10 + PD_BLOOM_INCREMENT_SIZE + content.length )); for ( byte[] k: entries ){ persist_del_bloom.add( k ); } }else{ for ( byte[] k: new_keys ){ persist_del_bloom.add( k ); } } } } protected boolean isPersistentlyDeleted( RelatedContent content ) { if ( persist_del_bloom == null ){ List entries = loadPersistentlyDeleted(); persist_del_bloom = BloomFilterFactory.createAddOnly( Math.max( PD_BLOOM_INITIAL_SIZE, entries.size()*10 + PD_BLOOM_INCREMENT_SIZE )); for ( byte[] k: entries ){ persist_del_bloom.add( k ); } } byte[] key = getPermDelKey( content ); return( persist_del_bloom.contains( key )); } protected void resetPersistentlyDeleted() { FileUtil.deleteResilientConfigFile( PERSIST_DEL_FILE ); persist_del_bloom = BloomFilterFactory.createAddOnly( PD_BLOOM_INITIAL_SIZE ); } public void reserveTemporarySpace() { temporary_space.addAndGet( TEMPORARY_SPACE_DELTA ); } public void releaseTemporarySpace() { boolean reset_explicit = temporary_space.addAndGet( -TEMPORARY_SPACE_DELTA ) == 0; enforceMaxResults( reset_explicit ); } protected void enforceMaxResults( boolean reset_explicit ) { synchronized( this ){ ContentCache content_cache = loadRelatedContent(); enforceMaxResults( content_cache, reset_explicit ); } } protected void enforceMaxResults( ContentCache content_cache, boolean reset_explicit ) { Map related_content = content_cache.related_content; int num_to_remove = related_content.size() - ( max_results + temporary_space.get()); if ( num_to_remove > 0 ){ List infos = new ArrayList(related_content.values()); if ( reset_explicit ){ for ( DownloadInfo info: infos ){ if ( info.isExplicit()){ info.setExplicit( false ); } } } Collections.sort( infos, new Comparator() { public int compare( DownloadInfo o1, DownloadInfo o2) { int res = o2.getLevel() - o1.getLevel(); if ( res != 0 ){ return( res ); } res = o1.getRank() - o2.getRank(); if ( res != 0 ){ return( res ); } return( o1.getLastSeenSecs() - o2.getLastSeenSecs()); } }); List to_remove = new ArrayList(); for (int i=0;i 0 ){ delete( to_remove.toArray( new RelatedContent[to_remove.size()]), content_cache, false ); } } } public void addListener( RelatedContentManagerListener listener ) { listeners.add( listener ); } public void removeListener( RelatedContentManagerListener listener ) { listeners.remove( listener ); } protected static class ByteArrayHashMapEx extends ByteArrayHashMap { public T getRandomValueExcluding( T excluded ) { int num = RandomUtils.nextInt( size ); T result = null; for (int j = 0; j < table.length; j++) { Entry e = table[j]; while( e != null ){ T value = e.value; if ( value != excluded ){ result = value; } if ( num <= 0 && result != null ){ return( result ); } num--; e = e.next; } } return( result ); } } private Map serialiseDI( DownloadInfo info, ContentCache cc ) { try{ Map info_map = new HashMap(); info_map.put( "h", info.getHash()); ImportExportUtils.exportString( info_map, "d", info.getTitle()); ImportExportUtils.exportInt( info_map, "r", info.getRand()); ImportExportUtils.exportString( info_map, "t", info.getTracker()); ImportExportUtils.exportLong( info_map, "z", info.getSize()); ImportExportUtils.exportInt( info_map, "p", (int)( info.getPublishDate()/(60*60*1000))); ImportExportUtils.exportInt( info_map, "q", (info.getSeeds()<<16)|(info.getLeechers()&0xffff)); ImportExportUtils.exportInt( info_map, "c", (int)info.getContentNetwork()); if ( cc != null ){ ImportExportUtils.exportBoolean( info_map, "u", info.isUnread()); ImportExportUtils.exportIntArray( info_map, "l", info.getRandList()); ImportExportUtils.exportInt( info_map, "s", info.getLastSeenSecs()); ImportExportUtils.exportInt( info_map, "e", info.getLevel()); } return( info_map ); }catch( Throwable e ){ Debug.out( e ); return( null ); } } private DownloadInfo deserialiseDI( Map info_map, ContentCache cc ) { try{ byte[] hash = (byte[])info_map.get("h"); String title = ImportExportUtils.importString( info_map, "d" ); int rand = ImportExportUtils.importInt( info_map, "r" ); String tracker = ImportExportUtils.importString( info_map, "t" ); long size = ImportExportUtils.importLong( info_map, "z" ); int date = ImportExportUtils.importInt( info_map, "p", 0 ); int seeds_leechers = ImportExportUtils.importInt( info_map, "q", -1 ); byte cnet = (byte)ImportExportUtils.importInt( info_map, "c", (int)ContentNetwork.CONTENT_NETWORK_UNKNOWN ); if ( cc == null ){ return( new DownloadInfo( hash, hash, title, rand, tracker, 0, false, size, date, seeds_leechers, cnet )); }else{ boolean unread = ImportExportUtils.importBoolean( info_map, "u" ); int[] rand_list = ImportExportUtils.importIntArray( info_map, "l" ); int last_seen = ImportExportUtils.importInt( info_map, "s" ); int level = ImportExportUtils.importInt( info_map, "e" ); return( new DownloadInfo( hash, title, rand, tracker, unread, rand_list, last_seen, level, size, date, seeds_leechers, cnet, cc )); } }catch( Throwable e ){ Debug.out( e ); return( null ); } } protected class DownloadInfo extends RelatedContent { final private int rand; private boolean unread = true; private int[] rand_list; private int last_seen; private int level; private boolean explicit; // we *need* this reference here to maange garbage collection correctly private ContentCache cc; protected DownloadInfo( byte[] _related_to, byte[] _hash, String _title, int _rand, String _tracker, int _level, boolean _explicit, long _size, int _date, int _seeds_leechers, byte _cnet ) { super( _related_to, _title, _hash, _tracker, _size, _date, _seeds_leechers, _cnet ); rand = _rand; level = _level; explicit = _explicit; updateLastSeen(); } protected DownloadInfo( byte[] _hash, String _title, int _rand, String _tracker, boolean _unread, int[] _rand_list, int _last_seen, int _level, long _size, int _date, int _seeds_leechers, byte _cnet, ContentCache _cc ) { super( _title, _hash, _tracker, _size, _date, _seeds_leechers, _cnet ); rand = _rand; unread = _unread; rand_list = _rand_list; last_seen = _last_seen; level = _level; cc = _cc; if ( rand_list != null ){ if ( rand_list.length > MAX_RANK ){ int[] temp = new int[ MAX_RANK ]; System.arraycopy( rand_list, 0, temp, 0, MAX_RANK ); rand_list = temp; } } } protected boolean addInfo( DownloadInfo info ) { boolean result = false; synchronized( this ){ updateLastSeen(); int r = info.getRand(); if ( rand_list == null ){ rand_list = new int[]{ r }; result = true; }else{ boolean match = false; for (int i=0;i 0 && d != getDateHours()){ setDateHours( d ); result = true; } } return( result ); } public int getLevel() { return( level ); } protected boolean isExplicit() { return( explicit ); } protected void setExplicit( boolean b ) { explicit = b; } protected void updateLastSeen() { // persistence of this is piggy-backed on other saves to limit resource usage // only therefore a vague measure last_seen = (int)( SystemTime.getCurrentTime()/1000 ); } public int getRank() { return( rand_list==null?0:rand_list.length ); } public boolean isUnread() { return( unread ); } protected void setPublic( ContentCache _cc ) { cc = _cc; if ( unread ){ incrementUnread(); } rand_list = new int[]{ rand }; } public int getLastSeenSecs() { return( last_seen ); } protected void setUnreadInternal( boolean _unread ) { synchronized( this ){ unread = _unread; } } public void setUnread( boolean _unread ) { boolean changed = false; synchronized( this ){ if ( unread != _unread ){ unread = _unread; changed = true; } } if ( changed ){ if ( _unread ){ incrementUnread(); }else{ decrementUnread(); } contentChanged( this ); } } protected int getRand() { return( rand ); } protected int[] getRandList() { return( rand_list ); } public Download getRelatedToDownload() { try{ return( getDownload( getRelatedToHash())); }catch( Throwable e ){ Debug.out( e ); return( null ); } } public void delete() { RelatedContentManager.this.delete( new RelatedContent[]{ this }); } public String getString() { return( super.getString() + ", " + rand + ", rl=" + rand_list + ", last_seen=" + last_seen + ", level=" + level ); } } private static class ContentCache { private Map related_content = new HashMap(); private ByteArrayHashMapEx> related_content_map = new ByteArrayHashMapEx>(); } private static class SecondaryLookup { final private byte[] hash; final private int level; protected SecondaryLookup( byte[] _hash, int _level ) { hash = _hash; level = _level; } protected byte[] getHash() { return( hash ); } protected int getLevel() { return( level ); } } protected class RCMSearchXFer implements DistributedDatabaseTransferType { } } azureus-4.3.0.6/com/aelitis/azureus/core/content/ContentException.java0000644000175000017500000000201611226745144025307 0ustar adrianadrian/* * Created on Jul 8, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.content; public class ContentException extends Exception { public ContentException( String str ) { super( str ); } public ContentException( String str, Throwable e ) { super( str, e ); } } azureus-4.3.0.6/com/aelitis/azureus/core/content/AzureusContentDirectoryListener.java0000644000175000017500000000171511171063172030400 0ustar adrianadrian/* * Created on Apr 13, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.content; public interface AzureusContentDirectoryListener { public void contentChanged( AzureusContentFile file, String property ); } azureus-4.3.0.6/com/aelitis/azureus/core/torrent/0000755000175000017500000000000011310377630021172 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/torrent/HasBeenOpenedListener.java0000644000175000017500000000201011073032300026160 0ustar adrianadrian/** * Created on Sep 28, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.torrent; import org.gudy.azureus2.core3.download.DownloadManager; /** * @author TuxPaper * @created Sep 28, 2008 * */ public interface HasBeenOpenedListener { public void hasBeenOpenedChanged(DownloadManager dm, boolean opened); } azureus-4.3.0.6/com/aelitis/azureus/core/torrent/PlatformTorrentUtils.java0000644000175000017500000005047111306337236026232 0ustar adrianadrian/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.torrent; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.cnetwork.ContentNetwork; /** * @author TuxPaper * @created Sep 27, 2006 * */ public class PlatformTorrentUtils { private static final long MIN_SPEED_DEFAULT = 100 * 1024; public static final String AELITIS_HOST_CORE = ".aelitis.com"; // needs to be lowercase public static final String VUZE_HOST_CORE = ".vuze.com"; // needs to be lowercase public static final boolean DEBUG_CACHING = System.getProperty( "az3.debug.caching", "0").equals("1"); private static final String TOR_AZ_PROP_MAP = "Content"; private static final String TOR_AZ_PROP_HASH = "Content Hash"; private static final String TOR_AZ_PROP_TITLE = "Title"; private static final String TOR_AZ_PROP_DESCRIPTION = "Description"; private static final String TOR_AZ_PROP_CONTENT_TYPE = "Content Type"; private static final String TOR_AZ_PROP_AUTHOR = "Author"; private static final String TOR_AZ_PROP_PUBLISHER = "Publisher"; private static final String TOR_AZ_PROP_URL = "URL"; private static final String TOR_AZ_PROP_THUMBNAIL = "Thumbnail"; private static final String TOR_AZ_PROP_THUMBNAIL_URL = "Thumbnail.url"; private static final String TOR_AZ_PROP_QUALITY = "Quality"; private static final String TOR_AZ_PROP_PROGRESSIVE = "Progressive"; private static final String TOR_AZ_PROP_SPEED = "Speed Bps"; private static final String TOR_AZ_PROP_MIN_SPEED = "Min Speed Bps"; private static final String TOR_AZ_PROP_DRM = "DRM"; private static final String TOR_AZ_PROP_PURCHASED = "Purchased"; private static final String TOR_AZ_PROP_QOS_CLASS = "QOS Class"; private static final String TOR_AZ_PROP_CONTENT_NETWORK = "Content Network"; private static final String TOR_AZ_PROP_EXPIRESON = "Expires On"; private static final String TOR_AZ_PROP_PRIMARY_FILE = "Primary File Index"; private static final ArrayList hasBeenOpenedListeners = new ArrayList(1); private static final String TOR_AZ_PROP_USE_EMP = "useEMP"; private static final String TOR_AZ_PROP_FILE_METADATA = "File MetaData"; private static final String TOR_AZ_PROP_VIDEO_WIDTH = "Video Width"; private static final String TOR_AZ_PROP_VIDEO_HEIGHT = "Video Height"; private static final String TOR_AZ_PROP_VIDEO_RUNNINGTIME = "Running Time"; private static final String TOR_AZ_PROP_DURATION_MILLIS = "Duration"; private static final String TOR_AZ_PROP_OPENED = "Opened"; private static ArrayList listPlatformHosts = null; private static final Map mapPlatformTrackerTorrents = new WeakHashMap(); private static boolean embeddedPlayerAvail = false; public static Map getContentMap(TOTorrent torrent) { if (torrent == null) { return Collections.EMPTY_MAP; } Map mapAZProps = torrent.getAdditionalMapProperty(TOTorrent.AZUREUS_PROPERTIES); if (mapAZProps == null) { mapAZProps = new HashMap(); torrent.setAdditionalMapProperty(TOTorrent.AZUREUS_PROPERTIES, mapAZProps); } Object objExistingContentMap = mapAZProps.get(TOR_AZ_PROP_MAP); Map mapContent; if (objExistingContentMap instanceof Map) { mapContent = (Map) objExistingContentMap; } else { mapContent = new HashMap(); mapAZProps.put(TOR_AZ_PROP_MAP, mapContent); } return mapContent; } static Map getTempContentMap(TOTorrent torrent) { if (torrent == null) { return new HashMap(); } Map mapAZProps = torrent.getAdditionalMapProperty("attributes"); if (mapAZProps == null) { mapAZProps = new HashMap(); torrent.setAdditionalMapProperty("attributes", mapAZProps); } Object objExistingContentMap = mapAZProps.get(TOR_AZ_PROP_MAP); Map mapContent; if (objExistingContentMap instanceof Map) { mapContent = (Map) objExistingContentMap; } else { mapContent = new HashMap(); mapAZProps.put(TOR_AZ_PROP_MAP, mapContent); } return mapContent; } public static String getContentMapString(TOTorrent torrent, String key) { if (torrent == null) { return null; } Map mapContent = getContentMap(torrent); Object obj = mapContent.get(key); if (obj instanceof String) { return (String) obj; } else if (obj instanceof byte[]) { try { return new String((byte[]) obj, Constants.DEFAULT_ENCODING); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } private static void setContentMapString(TOTorrent torrent, String key, String value) { if (torrent == null) { return; } Map mapContent = getContentMap(torrent); mapContent.put(key, value); } private static long getContentMapLong(TOTorrent torrent, String key, long def) { if (torrent == null) { return def; } Map mapContent = getContentMap(torrent); Object obj = mapContent.get(key); try { if (obj instanceof Long) { return ((Long) obj).longValue(); } else if (obj instanceof Integer) { return ((Integer) obj).longValue(); } else if (obj instanceof String) { return Long.parseLong((String) obj); } else if (obj instanceof byte[]) { return Long.parseLong(new String((byte[]) obj)); } } catch (Exception e) { } return def; } public static Map getContentMapMap(TOTorrent torrent, String key ){ if ( torrent == null ){ return( null ); } Map mapContent = getContentMap(torrent); Object obj = mapContent.get(key); if ( obj instanceof Map ){ return((Map)obj); } return( null ); } private static void setContentMapLong(TOTorrent torrent, String key, long value) { if (torrent == null) { return; } Map mapContent = getContentMap(torrent); mapContent.put(key, new Long(value)); } public static void setContentMapMap(TOTorrent torrent, String key, Map value) { if (torrent == null) { return; } Map mapContent = getContentMap(torrent); mapContent.put(key, value); } public static String getContentHash(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_HASH); } public static String getContentTitle(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_TITLE); } public static void setContentTitle(TOTorrent torrent, String title) { setContentMapString(torrent, TOR_AZ_PROP_TITLE, title); } public static String getContentDescription(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_DESCRIPTION); } public static void setContentDescription(TOTorrent torrent, String desc) { setContentMapString(torrent, TOR_AZ_PROP_DESCRIPTION,desc); } public static String getContentType(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_CONTENT_TYPE); } public static String getContentAuthor(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_AUTHOR); } public static String getContentPublisher(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_PUBLISHER); } public static String getContentURL(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_URL); } public static String getContentQuality(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_QUALITY); } public static boolean isContentDRM(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_DRM, -1) >= 0; } public static boolean isContentPurchased(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_PURCHASED, 0) == 1; } public static long getQOSClass(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_QOS_CLASS, 0); } public static void setQOSClass(TOTorrent torrent, long cla) { setContentMapLong(torrent, TOR_AZ_PROP_QOS_CLASS, cla); } public static long getContentNetworkID(TOTorrent torrent){ return( getContentNetworkID( torrent, ContentNetwork.CONTENT_NETWORK_UNKNOWN )); } public static long getContentNetworkID(TOTorrent torrent, long def) { long id = getContentMapLong(torrent, TOR_AZ_PROP_CONTENT_NETWORK, ContentNetwork.CONTENT_NETWORK_UNKNOWN); if (id == ContentNetwork.CONTENT_NETWORK_UNKNOWN) { return isContent(torrent, false) ? ContentNetwork.CONTENT_NETWORK_VUZE : def; } return id; } public static void setContentNetworkID(TOTorrent torrent, long cnet) { setContentMapLong(torrent, TOR_AZ_PROP_CONTENT_NETWORK, cnet); } private static void putOrRemove(Map map, String key, Object obj) { if (obj == null || obj.equals(null)) { map.remove(key); } else { map.put(key, obj); } } public static void setContentQuality(TOTorrent torrent, String sQualityID) { Map mapContent = getContentMap(torrent); putOrRemove(mapContent, TOR_AZ_PROP_QUALITY, sQualityID); writeTorrentIfExists(torrent); } private static void writeTorrentIfExists(TOTorrent torrent) { if (!AzureusCoreFactory.isCoreRunning()) { return; } AzureusCore core = AzureusCoreFactory.getSingleton(); if (core == null || !core.isStarted()) { return; } GlobalManager gm = core.getGlobalManager(); if (gm == null || gm.getDownloadManager(torrent) == null) { return; } try { TorrentUtils.writeToFile(torrent); } catch (TOTorrentException e) { Debug.out(e); } } public static byte[] getContentThumbnail(TOTorrent torrent) { Map mapContent = getContentMap(torrent); Object obj = mapContent.get(TOR_AZ_PROP_THUMBNAIL); if (obj instanceof byte[]) { return (byte[]) obj; } return null; } public static String getContentThumbnailUrl(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_THUMBNAIL_URL); } public static void setContentThumbnailUrl(TOTorrent torrent, String url) { setContentMapString(torrent, TOR_AZ_PROP_THUMBNAIL_URL, url); } public static void setContentThumbnail(TOTorrent torrent, byte[] thumbnail) { Map mapContent = getContentMap(torrent); putOrRemove(mapContent, TOR_AZ_PROP_THUMBNAIL, thumbnail); writeTorrentIfExists(torrent); } public static boolean isContent(TOTorrent torrent, boolean requirePlatformTracker) { if (torrent == null) { return false; } boolean bContent = PlatformTorrentUtils.getContentHash(torrent) != null; if (!bContent || (bContent && !requirePlatformTracker)) { return bContent; } return isPlatformTracker(torrent); } public static boolean isContent(Torrent torrent, boolean requirePlatformTracker) { if (torrent instanceof TorrentImpl) { return isContent(((TorrentImpl) torrent).getTorrent(), requirePlatformTracker); } return false; } public static List getPlatformHosts() { if (listPlatformHosts == null) { listPlatformHosts = new ArrayList(); for (int i = 0; i < Constants.AZUREUS_DOMAINS.length; i++) { listPlatformHosts.add(Constants.AZUREUS_DOMAINS[i].toLowerCase()); } } return listPlatformHosts; } public static void addPlatformHost(String host) { List platformHosts = getPlatformHosts(); host = host.toLowerCase(); if (!platformHosts.contains(host)) { platformHosts.add(host); mapPlatformTrackerTorrents.clear(); } } public static boolean isPlatformHost(String host) { Object[] domains = getPlatformHosts().toArray(); host = host.toLowerCase(); for (int i = 0; i < domains.length; i++) { String domain = (String) domains[i]; if (domain.equals(host)) { return (true); } if (host.endsWith("." + domain)) { return (true); } } if ( Constants.isCVSVersion()){ // allow local addresses for testing try{ InetAddress ia = InetAddress.getByName( host ); return( ia.isLoopbackAddress() || ia.isLinkLocalAddress() || ia.isSiteLocalAddress()); }catch( Throwable e ){ } } return (false); } public static boolean isPlatformTracker(TOTorrent torrent) { try { if (torrent == null) { return false; } Object oCache = mapPlatformTrackerTorrents.get(torrent); if (oCache instanceof Boolean) { return ((Boolean) oCache).booleanValue(); } // check them all incase someone includes one of our trackers in a multi-tracker // torrent URL announceURL = torrent.getAnnounceURL(); if (announceURL != null) { if (!isPlatformHost(announceURL.getHost())) { mapPlatformTrackerTorrents.put(torrent, new Boolean(false)); return (false); } } TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets(); for (int i = 0; i < sets.length; i++) { URL[] urls = sets[i].getAnnounceURLs(); for (int j = 0; j < urls.length; j++) { if (!isPlatformHost(urls[j].getHost())) { mapPlatformTrackerTorrents.put(torrent, new Boolean(false)); return (false); } } } boolean b = announceURL != null; mapPlatformTrackerTorrents.put(torrent, new Boolean(b)); return b; } catch (Throwable e) { Debug.printStackTrace(e); mapPlatformTrackerTorrents.put(torrent, new Boolean(false)); return (false); } } public static boolean isPlatformTracker(Torrent torrent) { if (torrent instanceof TorrentImpl) { return isPlatformTracker(((TorrentImpl) torrent).getTorrent()); } return false; } public static boolean isAdvancedViewOnly(DownloadManager dm) { Boolean oisUpdate = (Boolean) dm.getUserData("isAdvancedViewOnly"); if (oisUpdate != null) { return oisUpdate.booleanValue(); } boolean advanced_view = true; if ( !dm.getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE )){ TOTorrent torrent = dm.getTorrent(); if (torrent == null) { advanced_view = false; } else { URL announceURL = torrent.getAnnounceURL(); if (announceURL != null) { String host = announceURL.getHost(); if (!( host.endsWith(AELITIS_HOST_CORE)|| host.endsWith( VUZE_HOST_CORE ))){ advanced_view = false; } } if (advanced_view) { TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets(); for (int i = 0; i < sets.length; i++) { URL[] urls = sets[i].getAnnounceURLs(); for (int j = 0; j < urls.length; j++) { String host = urls[j].getHost(); if (!( host.endsWith(AELITIS_HOST_CORE)|| host.endsWith( VUZE_HOST_CORE ))){ advanced_view = false; break; } } } } } } dm.setUserData("isAdvancedViewOnly", new Boolean(advanced_view)); return advanced_view; } public static boolean isContentProgressive(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_PROGRESSIVE, 0) == 1; } public static long getContentStreamSpeedBps(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_SPEED, 0); } public static long getContentMinimumSpeedBps(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_MIN_SPEED, MIN_SPEED_DEFAULT); } public static boolean useEMP(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_USE_EMP, 0) == 1; } public static void setUseEMP(TOTorrent torrent, boolean useEMP) { setContentMapLong(torrent, TOR_AZ_PROP_USE_EMP, useEMP ? 1 : 0); } public static void setFileMetaData(TOTorrent torrent, Map map) { setContentMapMap(torrent, TOR_AZ_PROP_FILE_METADATA, map ); } public static Map getFileMetaData(TOTorrent torrent ){ return getContentMapMap( torrent, TOR_AZ_PROP_FILE_METADATA ); } public static long getExpiresOn(TOTorrent torrent) { Map mapContent = getContentMap(torrent); Long l = (Long) mapContent.get(TOR_AZ_PROP_EXPIRESON); if (l == null) { return 0; } return l.longValue(); } public static int getContentPrimaryFileIndex(TOTorrent torrent ){ return (int)getContentMapLong(torrent, TOR_AZ_PROP_PRIMARY_FILE, -1 ); } private static long getContentVideoWidth(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_VIDEO_WIDTH, -1); } private static long getContentVideoHeight(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_VIDEO_HEIGHT, -1); } public static long getContentVideoRunningTime(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_VIDEO_RUNNINGTIME, -1); } public static long getContentDurationMillis(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_DURATION_MILLIS, -1); } public static void setContentDurationMillis(TOTorrent torrent, long millis ) { setContentMapLong(torrent, TOR_AZ_PROP_DURATION_MILLIS, millis ); } public static int[] getContentVideoResolution(TOTorrent torrent) { long width = getContentVideoWidth(torrent); if (width <= 0) { return null; } long height = getContentVideoHeight(torrent); if (height <= 0) { return null; } return new int[] { (int) width, (int) height }; } public static void log(String str) { AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("v3.MD"); diag_logger.log(str); if (DEBUG_CACHING) { System.out.println(Thread.currentThread().getName() + "|" + System.currentTimeMillis() + "] " + str); } } /** * @param torrent * @param string * * @since 3.0.1.5 */ public static void log(TOTorrent torrent, String string) { String hash = ""; try { hash = torrent.getHashWrapper().toBase32String(); } catch (Exception e) { } log(hash + "] " + string); } public static boolean embeddedPlayerAvail() { // cache true, always recheck false in case plugin installs. if (embeddedPlayerAvail) { return true; } try { PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( "azemp", true); if (pi != null) { embeddedPlayerAvail = true; } } catch (Throwable e1) { } return embeddedPlayerAvail; } /** * @param torrent * * @since 3.0.4.3 */ public static String getContentTitle2(DownloadManager dm) { if (dm == null) { return null; } // DM state's display name can be set by user, so show that if we have it String name = dm.getDownloadState().getDisplayName(); if (name == null || name.length() == 0) { name = PlatformTorrentUtils.getContentTitle(dm.getTorrent()); if (name == null) { name = dm.getDisplayName(); } } return name; } public static void setHasBeenOpened(DownloadManager dm, boolean opened) { TOTorrent torrent = dm.getTorrent(); if (torrent == null) { return; } if (opened == getHasBeenOpened(dm)) { return; } setContentMapLong(torrent, TOR_AZ_PROP_OPENED, opened ? 1 : 0); writeTorrentIfExists(torrent); Object[] array = hasBeenOpenedListeners.toArray(); for (int i = 0; i < array.length; i++) { try { HasBeenOpenedListener l = (HasBeenOpenedListener) array[i]; l.hasBeenOpenedChanged(dm, opened); } catch (Exception e) { Debug.out(e); } } } public static boolean getHasBeenOpened(DownloadManager dm) { TOTorrent torrent = dm.getTorrent(); if (torrent == null) { return true; } boolean opened = getContentMapLong(torrent, TOR_AZ_PROP_OPENED, -1) > 0; if (opened || isAdvancedViewOnly(dm)) { return true; } return false; } public static void addHasBeenOpenedListener(HasBeenOpenedListener l) { hasBeenOpenedListeners.add(l); } } azureus-4.3.0.6/com/aelitis/azureus/core/AzureusCoreLifecycleListener.java0000644000175000017500000000452210766345644026156 0ustar adrianadrian/* * Created on 14-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core; /** * @author parg * */ public interface AzureusCoreLifecycleListener { public void componentCreated( AzureusCore core, AzureusCoreComponent component ); public void started( AzureusCore core ); public void stopping( AzureusCore core ); public void stopped( AzureusCore core ); /** * return true if the request has been accepted (and hence the listener will arrange for a stop to occur * @param core * @return */ public boolean stopRequested( AzureusCore core ) throws AzureusCoreException; public boolean restartRequested( AzureusCore core ) throws AzureusCoreException; /** * Some listeners must be invoked on the same thread that initiates a core closedown. In particular * the show-alerts-raised-during-closedown logic requires that it is invoked on the swt thread that * initiated the closedown. * @return */ public boolean syncInvokeRequired(); /** * hack - original semantics of the "started" event was that all plugins init complete * However, some can take a long time (and even block if attempting to acquire, say, public * IP address and version server is down...) so added this flag to allow listeners to * indicate that they're happy to be "started" before plugin init complete * @return */ public boolean requiresPluginInitCompleteBeforeStartedEvent(); } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/0000755000175000017500000000000011310377626022526 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/VirtualServerChannelSelector.java0000644000175000017500000000323110374716174031203 0ustar adrianadrian/* * Created on Dec 4, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager; import java.net.*; import java.nio.channels.*; /** * Virtual server socket channel for listening and accepting incoming connections. */ public interface VirtualServerChannelSelector { public void start(); public void stop(); public boolean isRunning(); public InetAddress getBoundToAddress(); public long getTimeOfLastAccept(); /** * Listener notified when a new incoming connection is accepted. */ public interface SelectListener { /** * The given connection has just been accepted. * @param channel new connection */ public void newConnectionAccepted( ServerSocketChannel server, SocketChannel channel ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/TransportEndpoint.java0000644000175000017500000000210010444636732027062 0ustar adrianadrian/* * Created on 16 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager; public interface TransportEndpoint { public ProtocolEndpoint getProtocolEndpoint(); } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/0000755000175000017500000000000011310377630023462 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/OutgoingMessageQueueImpl.java0000644000175000017500000006560410757735636031311 0ustar adrianadrian/* * Created on May 8, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.lang.ref.WeakReference; import java.nio.ByteBuffer; import java.util.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.NetworkManager; import com.aelitis.azureus.core.networkmanager.OutgoingMessageQueue; import com.aelitis.azureus.core.networkmanager.RawMessage; import com.aelitis.azureus.core.networkmanager.Transport; import com.aelitis.azureus.core.peermanager.messaging.*; /** * Priority-based outbound peer message queue. */ public class OutgoingMessageQueueImpl implements OutgoingMessageQueue { private final LinkedList queue = new LinkedList(); private final AEMonitor queue_mon = new AEMonitor( "OutgoingMessageQueue:queue" ); private final ArrayList delayed_notifications = new ArrayList(); private final AEMonitor delayed_notifications_mon = new AEMonitor( "OutgoingMessageQueue:DN" ); private volatile ArrayList listeners = new ArrayList(); //copied-on-write private final AEMonitor listeners_mon = new AEMonitor( "OutgoingMessageQueue:L"); private int total_size = 0; private RawMessage urgent_message = null; private boolean destroyed = false; private MessageStreamEncoder stream_encoder; private Transport transport; private int percent_complete = -1; private static final boolean TRACE_HISTORY = false; //TODO private static final int MAX_HISTORY_TRACES = 30; private final LinkedList prev_sent = new LinkedList(); private boolean trace; /** * Create a new outgoing message queue. * @param stream_encoder default message encoder */ public OutgoingMessageQueueImpl( MessageStreamEncoder stream_encoder ) { this.stream_encoder = stream_encoder; } public void setTransport( Transport _transport ) { transport = _transport; } public int getMssSize() { return( transport==null?NetworkManager.getMinMssSize():transport.getMssSize()); } /** * Set the message stream encoder that will be used to encode outgoing messages. * @param stream_encoder to use */ public void setEncoder( MessageStreamEncoder stream_encoder ) { this.stream_encoder = stream_encoder; } public MessageStreamEncoder getEncoder() { return( stream_encoder ); } /** * Get the percentage of the current message that has already been sent out. * @return percentage complete (0-99), or -1 if no message is currently being sent */ public int getPercentDoneOfCurrentMessage() { return percent_complete; } /** * Destroy this queue; i.e. perform cleanup actions. */ public void destroy() { destroyed = true; try{ queue_mon.enter(); while( !queue.isEmpty() ) { ((RawMessage)queue.remove( 0 )).destroy(); } }finally{ queue_mon.exit(); } total_size = 0; prev_sent.clear(); listeners = new ArrayList(); urgent_message = null; } /** * Get the total number of bytes ready to be transported. * @return total bytes remaining */ public int getTotalSize() { return total_size; } /** * Whether or not an urgent message (one that needs an immediate send, i.e. a no-delay message) is queued. * @return true if there's a message tagged for immediate write */ public boolean hasUrgentMessage() { return urgent_message == null ? false : true; } /** * Add a message to the message queue. * NOTE: Allows for manual listener notification at some later time, * using doListenerNotifications(), instead of notifying immediately * from within this method. This is useful if you want to invoke * listeners outside of some greater synchronised block to avoid * deadlock. * @param message message to add * @param manual_listener_notify true for manual notification, false for automatic */ public void addMessage( Message message, boolean manual_listener_notify ) { //do message add notifications boolean allowed = true; ArrayList list_ref = listeners; for( int i=0; i < list_ref.size(); i++ ) { MessageQueueListener listener = (MessageQueueListener)list_ref.get( i ); allowed = allowed && listener.messageAdded( message ); } if( !allowed ) { //message addition not allowed //LGLogger.log( "Message [" +message.getDescription()+ "] not allowed for queueing, message addition skipped." ); //message.destroy(); //TODO destroy???? return; } RawMessage[] rmesgs = stream_encoder.encodeMessage( message ); if( destroyed ) { //queue is shutdown, drop any added messages for (int i=0;i msg.getPriority() && msg.getRawData()[0].position(DirectByteBuffer.SS_NET) == 0 ) { //but don't insert in front of a half-sent message break; } pos++; } if( rmesg.isNoDelay() ) { urgent_message = rmesg; } queue.add( pos, rmesg ); DirectByteBuffer[] payload = rmesg.getRawData(); for( int j=0; j < payload.length; j++ ) { total_size += payload[j].remaining(DirectByteBuffer.SS_NET); } }finally{ queue_mon.exit(); } if( manual_listener_notify ) { //register listener event for later, manual notification NotificationItem item = new NotificationItem( NotificationItem.MESSAGE_ADDED ); item.message = rmesg; try { delayed_notifications_mon.enter(); delayed_notifications.add( item ); } finally { delayed_notifications_mon.exit(); } } else { //do listener notification now ArrayList listeners_ref = listeners; for( int j=0; j < listeners_ref.size(); j++ ) { MessageQueueListener listener = (MessageQueueListener)listeners_ref.get( j ); listener.messageQueued( rmesg.getBaseMessage() ); } } } } /** * Remove all messages of the given types from the queue. * NOTE: Allows for manual listener notification at some later time, * using doListenerNotifications(), instead of notifying immediately * from within this method. This is useful if you want to invoke * listeners outside of some greater synchronised block to avoid * deadlock. * @param message_types type to remove * @param manual_listener_notify true for manual notification, false for automatic */ public void removeMessagesOfType( Message[] message_types, boolean manual_listener_notify ) { if( message_types == null ) return; ArrayList messages_removed = null; try{ queue_mon.enter(); for( Iterator i = queue.iterator(); i.hasNext(); ) { RawMessage msg = (RawMessage)i.next(); for( int t=0; t < message_types.length; t++ ) { boolean same_type = message_types[t].getID().equals( msg.getID() ); if( same_type && msg.getRawData()[0].position(DirectByteBuffer.SS_NET) == 0 ) { //dont remove a half-sent message if( msg == urgent_message ) urgent_message = null; DirectByteBuffer[] payload = msg.getRawData(); for( int x=0; x < payload.length; x++ ) { total_size -= payload[x].remaining(DirectByteBuffer.SS_NET); } if( manual_listener_notify ) { NotificationItem item = new NotificationItem( NotificationItem.MESSAGE_REMOVED ); item.message = msg; try { delayed_notifications_mon.enter(); delayed_notifications.add( item ); } finally { delayed_notifications_mon.exit(); } } else { if ( messages_removed == null ){ messages_removed = new ArrayList(); } messages_removed.add( msg ); } i.remove(); break; } } } }finally{ queue_mon.exit(); } if( !manual_listener_notify && messages_removed != null ) { //do listener notifications now ArrayList listeners_ref = listeners; for( int x=0; x < messages_removed.size(); x++ ) { RawMessage msg = (RawMessage)messages_removed.get( x ); for( int i=0; i < listeners_ref.size(); i++ ) { MessageQueueListener listener = (MessageQueueListener)listeners_ref.get( i ); listener.messageRemoved( msg.getBaseMessage() ); } msg.destroy(); } } } /** * Remove a particular message from the queue. * NOTE: Only the original message found in the queue will be destroyed upon removal, * which may not necessarily be the one passed as the method parameter, * as some messages override equals() (i.e. BTRequest messages) instead of using reference * equality, and could be a completely different object, and would need to be destroyed * manually. If the message does not override equals, then any such method will likely * *not* be found and removed, as internal queued object was a new allocation on insertion. * NOTE: Allows for manual listener notification at some later time, * using doListenerNotifications(), instead of notifying immediately * from within this method. This is useful if you want to invoke * listeners outside of some greater synchronised block to avoid * deadlock. * @param message to remove * @param manual_listener_notify true for manual notification, false for automatic * @return true if the message was removed, false otherwise */ public boolean removeMessage( Message message, boolean manual_listener_notify ) { RawMessage msg_removed = null; try{ queue_mon.enter(); for( Iterator it = queue.iterator(); it.hasNext(); ) { RawMessage raw = (RawMessage)it.next(); if( message.equals( raw.getBaseMessage() ) ) { if( raw.getRawData()[0].position(DirectByteBuffer.SS_NET) == 0 ) { //dont remove a half-sent message if( raw == urgent_message ) urgent_message = null; DirectByteBuffer[] payload = raw.getRawData(); for( int x=0; x < payload.length; x++ ) { total_size -= payload[x].remaining(DirectByteBuffer.SS_NET); } queue.remove( raw ); msg_removed = raw; } break; } } }finally{ queue_mon.exit(); } if( msg_removed != null ) { if( manual_listener_notify ) { //delayed manual notification NotificationItem item = new NotificationItem( NotificationItem.MESSAGE_REMOVED ); item.message = msg_removed; try { delayed_notifications_mon.enter(); delayed_notifications.add( item ); } finally { delayed_notifications_mon.exit(); } } else { //do listener notification now ArrayList listeners_ref = listeners; for( int i=0; i < listeners_ref.size(); i++ ) { MessageQueueListener listener = (MessageQueueListener)listeners_ref.get( i ); listener.messageRemoved( msg_removed.getBaseMessage() ); } msg_removed.destroy(); } return true; } return false; } private WeakReference rawBufferCache = new WeakReference(null); private WeakReference origPositionsCache = new WeakReference(null); /** * Deliver (write) message(s) data to the underlying transport. * * NOTE: Allows for manual listener notification at some later time, * using doListenerNotifications(), instead of notifying immediately * from within this method. This is useful if you want to invoke * listeners outside of some greater synchronised block to avoid * deadlock. * @param max_bytes maximum number of bytes to deliver * @param manual_listener_notify true for manual notification, false for automatic * @return number of bytes delivered * @throws IOException on delivery error */ public int deliverToTransport( int max_bytes, boolean manual_listener_notify ) throws IOException { if( max_bytes < 1 ) { Debug.out( "max_bytes < 1: " +max_bytes ); return 0; } if ( transport == null ){ throw( new IOException( "not ready to deliver data" )); } int data_written = 0; int protocol_written = 0; ArrayList messages_sent = null; try{ queue_mon.enter(); if( !queue.isEmpty() ){ int buffer_limit = 64; ByteBuffer[] raw_buffers = (ByteBuffer[])rawBufferCache.get(); if(raw_buffers == null) { raw_buffers = new ByteBuffer[buffer_limit]; rawBufferCache = new WeakReference(raw_buffers); } else { Arrays.fill(raw_buffers, null); } int[] orig_positions = (int[])origPositionsCache.get(); if(orig_positions == null) { orig_positions = new int[buffer_limit]; origPositionsCache = new WeakReference(orig_positions); } else { Arrays.fill(orig_positions, 0); } int buffer_count = 0; int total_sofar = 0; outer: for( Iterator i = queue.iterator(); i.hasNext(); ){ DirectByteBuffer[] payloads = ((RawMessage)i.next()).getRawData(); for( int x=0; x < payloads.length; x++ ){ ByteBuffer buff = payloads[x].getBuffer( DirectByteBuffer.SS_NET ); raw_buffers[buffer_count] = buff; orig_positions[buffer_count] = buff.position(); total_sofar += buff.remaining(); buffer_count++; if ( total_sofar >= max_bytes ){ break outer; } if ( buffer_count == buffer_limit ) { int new_buffer_limit = buffer_limit * 2; ByteBuffer[] new_raw_buffers = new ByteBuffer[new_buffer_limit]; int[] new_orig_positions = new int[new_buffer_limit]; System.arraycopy( raw_buffers, 0, new_raw_buffers, 0, buffer_limit ); System.arraycopy( orig_positions, 0, new_orig_positions, 0, buffer_limit ); raw_buffers = new_raw_buffers; orig_positions = new_orig_positions; buffer_limit = new_buffer_limit; } } } ByteBuffer last_buff = (ByteBuffer)raw_buffers[buffer_count - 1 ]; int orig_last_limit = last_buff.limit(); if ( total_sofar > max_bytes ){ last_buff.limit( orig_last_limit - (total_sofar - max_bytes) ); } transport.write( raw_buffers, 0, buffer_count ); last_buff.limit( orig_last_limit ); int pos = 0; boolean stop = false; while( !queue.isEmpty() && !stop ) { RawMessage msg = (RawMessage)queue.get( 0 ); DirectByteBuffer[] payloads = msg.getRawData(); for( int x=0; x < payloads.length; x++ ) { ByteBuffer bb = payloads[x].getBuffer( DirectByteBuffer.SS_NET ); int bytes_written = (bb.limit() - bb.remaining()) - orig_positions[ pos ]; total_size -= bytes_written; if( x > 0 && msg.getType() == Message.TYPE_DATA_PAYLOAD ) { //assumes the first buffer is message header data_written += bytes_written; } else { protocol_written += bytes_written; } if( bb.hasRemaining() ) { //still data left to send in this message stop = true; //so don't bother checking later messages for completion //compute send percentage int message_size = 0; int written = 0; for( int i=0; i < payloads.length; i++ ) { ByteBuffer buff = payloads[i].getBuffer( DirectByteBuffer.SS_NET ); message_size += buff.limit(); if( i < x ) { //if in front of non-empty buffer written += buff.limit(); } else if( i == x ) { //is non-empty buffer written += buff.position(); } } percent_complete = (written * 100) / message_size; break; } else if( x == payloads.length - 1 ) { //last payload buffer of message is empty if( msg == urgent_message ) urgent_message = null; queue.remove( 0 ); if( TRACE_HISTORY ) { prev_sent.addLast( msg ); if( prev_sent.size() > MAX_HISTORY_TRACES ) prev_sent.removeFirst(); } percent_complete = -1; //reset send percentage if( manual_listener_notify ) { NotificationItem item = new NotificationItem( NotificationItem.MESSAGE_SENT ); item.message = msg; try { delayed_notifications_mon.enter(); delayed_notifications.add( item ); } finally { delayed_notifications_mon.exit(); } } else { if( messages_sent == null ) { messages_sent = new ArrayList(); } messages_sent.add( msg ); } } pos++; if( pos >= buffer_count ) { stop = true; break; } } } } }finally{ queue_mon.exit(); } // we can have messages that end up getting serialised as 0 bytes (for http // connections for example) - we still need to notify them of being sent... if( data_written + protocol_written > 0 || messages_sent != null ) { if ( trace ){ TimeFormatter.milliTrace( "omq:deliver: " + (data_written + protocol_written) + ", q=" + queue.size() + "/" + total_size ); } if( manual_listener_notify ) { if( data_written > 0 ) { //data bytes notify NotificationItem item = new NotificationItem( NotificationItem.DATA_BYTES_SENT ); item.byte_count = data_written; try { delayed_notifications_mon.enter(); delayed_notifications.add( item ); } finally { delayed_notifications_mon.exit(); } } if( protocol_written > 0 ) { //protocol bytes notify NotificationItem item = new NotificationItem( NotificationItem.PROTOCOL_BYTES_SENT ); item.byte_count = protocol_written; try { delayed_notifications_mon.enter(); delayed_notifications.add( item ); } finally { delayed_notifications_mon.exit(); } } } else { //do listener notification now ArrayList listeners_ref = listeners; int num_listeners = listeners_ref.size(); for( int i=0; i < num_listeners; i++ ) { MessageQueueListener listener = (MessageQueueListener)listeners_ref.get( i ); if( data_written > 0 ) listener.dataBytesSent( data_written ); if( protocol_written > 0 ) listener.protocolBytesSent( protocol_written ); if ( messages_sent != null ){ for( int x=0; x < messages_sent.size(); x++ ) { RawMessage msg = (RawMessage)messages_sent.get( x ); listener.messageSent( msg.getBaseMessage() ); if( i == num_listeners - 1 ) { //the last listener notification, so destroy msg.destroy(); } } } } } }else{ if ( trace ){ TimeFormatter.milliTrace( "omq:deliver: 0, q=" + queue.size() + "/" + total_size ); } } return data_written + protocol_written; } public void flush() { try{ queue_mon.enter(); if ( queue.isEmpty()){ return; } for (int i=0;i mss ) num_bytes_allowed = mss; int bytes_read = 0; try { bytes_read = connection.getIncomingMessageQueue().receiveFromTransport( num_bytes_allowed ); } catch( Throwable e ) { if( AEDiagnostics.TRACE_CONNECTION_DROPS ) { if( e.getMessage() == null ) { Debug.out( "null read exception message: ", e ); } else { if( e.getMessage().indexOf( "end of stream on socket read" ) == -1 && e.getMessage().indexOf( "An existing connection was forcibly closed by the remote host" ) == -1 && e.getMessage().indexOf( "Connection reset by peer" ) == -1 && e.getMessage().indexOf( "An established connection was aborted by the software in your host machine" ) == -1 ) { System.out.println( "SP: read exception [" +connection.getTransportBase().getDescription()+ "]: " +e.getMessage() ); } } } if (! (e instanceof IOException )){ Debug.printStackTrace(e); } connection.notifyOfException( e ); return false; } if( bytes_read < 1 ) { return false; } rate_handler.bytesProcessed( bytes_read ); return true; } public int getPriority() { return RateControlledEntity.PRIORITY_NORMAL; } public long getBytesReadyToWrite() { return( 0 ); } public int getConnectionCount() { return( 1 ); } public int getReadyConnectionCount( EventWaiter waiter ) { if ( connection.getTransportBase().isReadyForRead( waiter) == 0 ){ return( 1 ); } return( 0 ); } public String getString() { return( "SPD: " + connection.getString()); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/IncomingMessageQueueImpl.java0000644000175000017500000002002210734653210031220 0ustar adrianadrian/* * Created on Oct 17, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.nio.ByteBuffer; import java.util.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.IncomingMessageQueue; import com.aelitis.azureus.core.networkmanager.NetworkConnection; import com.aelitis.azureus.core.peermanager.messaging.*; /** * Inbound peer message queue. */ public class IncomingMessageQueueImpl implements IncomingMessageQueue{ private volatile ArrayList listeners = new ArrayList(); //copy-on-write private final AEMonitor listeners_mon = new AEMonitor( "IncomingMessageQueue:listeners" ); private MessageStreamDecoder stream_decoder; private final NetworkConnection connection; /** * Create a new incoming message queue. * @param stream_decoder default message stream decoder * @param connection owner to read from */ public IncomingMessageQueueImpl( MessageStreamDecoder stream_decoder, NetworkConnection connection ) { if (stream_decoder == null) { throw new NullPointerException("stream_decoder is null"); } this.connection = connection; this.stream_decoder = stream_decoder; } /** * Set the message stream decoder that will be used to decode incoming messages. * @param new_stream_decoder to use */ public void setDecoder( MessageStreamDecoder new_stream_decoder ) { ByteBuffer already_read = stream_decoder.destroy(); connection.getTransport().setAlreadyRead( already_read ); stream_decoder = new_stream_decoder; stream_decoder.resumeDecoding(); } public MessageStreamDecoder getDecoder() { return( stream_decoder ); } /** * Get the percentage of the current message that has already been received. * @return percentage complete (0-99), or -1 if no message is currently being received */ public int getPercentDoneOfCurrentMessage() { return stream_decoder.getPercentDoneOfCurrentMessage(); } /** * Receive (read) message(s) data from the underlying transport. * @param max_bytes to read * @return number of bytes received * @throws IOException on receive error */ public int receiveFromTransport( int max_bytes ) throws IOException { if( max_bytes < 1 ) { Debug.out( "max_bytes < 1: " +max_bytes ); return 0; } if( listeners.isEmpty() ) { Debug.out( "no queue listeners registered!" ); throw new IOException( "no queue listeners registered!" ); } int bytes_read; try{ //perform decode op bytes_read = stream_decoder.performStreamDecode( connection.getTransport(), max_bytes ); }catch( RuntimeException e ){ Debug.out( "Stream decode for " + connection.getString() + " failed: " + Debug.getNestedExceptionMessageAndStack(e)); throw( e ); } //check if anything was decoded and notify listeners if so Message[] messages = stream_decoder.removeDecodedMessages(); if( messages != null ) { for( int i=0; i < messages.length; i++ ) { Message msg = messages[ i ]; if( msg == null ) { System.out.println( "received msg == null [messages.length=" +messages.length+ ", #" +i+ "]: " +connection.getTransport().getDescription() ); continue; } ArrayList listeners_ref = listeners; //copy-on-write boolean handled = false; for( int x=0; x < listeners_ref.size(); x++ ) { MessageQueueListener mql = (MessageQueueListener)listeners_ref.get( x ); handled = handled || mql.messageReceived( msg ); } if( !handled ) { if( listeners_ref.size() > 0 ) { System.out.println( "no registered listeners [out of " +listeners_ref.size()+ "] handled decoded message [" +msg.getDescription()+ "]" ); } DirectByteBuffer[] buffs = msg.getData(); for( int x=0; x < buffs.length; x++ ) { buffs[ x ].returnToPool(); } } } } int protocol_read = stream_decoder.getProtocolBytesDecoded(); if( protocol_read > 0 ) { ArrayList listeners_ref = listeners; //copy-on-write for( int i=0; i < listeners_ref.size(); i++ ) { MessageQueueListener mql = (MessageQueueListener)listeners_ref.get( i ); mql.protocolBytesReceived( protocol_read ); } } int data_read = stream_decoder.getDataBytesDecoded(); if( data_read > 0 ) { ArrayList listeners_ref = listeners; //copy-on-write for( int i=0; i < listeners_ref.size(); i++ ) { MessageQueueListener mql = (MessageQueueListener)listeners_ref.get( i ); mql.dataBytesReceived( data_read ); } } return bytes_read; } /** * Notifty the queue (and its listeners) of a message received externally on the queue's behalf. * @param message received externally */ public void notifyOfExternallyReceivedMessage( Message message ) { ArrayList listeners_ref = listeners; //copy-on-write boolean handled = false; DirectByteBuffer[] dbbs = message.getData(); int size = 0; for( int i=0; i < dbbs.length; i++ ) { size += dbbs[i].remaining( DirectByteBuffer.SS_NET ); } for( int x=0; x < listeners_ref.size(); x++ ) { MessageQueueListener mql = (MessageQueueListener)listeners_ref.get( x ); handled = handled || mql.messageReceived( message ); if( message.getType() == Message.TYPE_DATA_PAYLOAD ) { mql.dataBytesReceived( size ); } else { mql.protocolBytesReceived( size ); } } if( !handled ) { if( listeners_ref.size() > 0 ) { System.out.println( "no registered listeners [out of " +listeners_ref.size()+ "] handled decoded message [" +message.getDescription()+ "]" ); } DirectByteBuffer[] buffs = message.getData(); for( int x=0; x < buffs.length; x++ ) { buffs[ x ].returnToPool(); } } } /** * Manually resume processing (reading) incoming messages. * NOTE: Allows us to resume docoding externally, in case it was auto-paused internally. */ public void resumeQueueProcessing() { stream_decoder.resumeDecoding(); } /** * Add a listener to be notified of queue events. * @param listener */ public void registerQueueListener( MessageQueueListener listener ) { try{ listeners_mon.enter(); //copy-on-write ArrayList new_list = new ArrayList( listeners.size() + 1 ); new_list.addAll( listeners ); new_list.add( listener ); listeners = new_list; } finally{ listeners_mon.exit(); } } /** * Cancel queue event notification listener. * @param listener */ public void cancelQueueListener( MessageQueueListener listener ) { try{ listeners_mon.enter(); //copy-on-write ArrayList new_list = new ArrayList( listeners ); new_list.remove( listener ); listeners = new_list; } finally{ listeners_mon.exit(); } } /** * Destroy this queue. */ public void destroy() { stream_decoder.destroy(); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderPHE.java0000644000175000017500000014717611067014554027773 0ustar adrianadrian/* * Created on 17-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.math.BigInteger; import java.nio.ByteBuffer; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PublicKey; import java.security.SecureRandom; import java.util.*; import javax.crypto.Cipher; import javax.crypto.KeyAgreement; import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.DHPublicKeySpec; import javax.crypto.spec.SecretKeySpec; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.HashWrapper; import org.gudy.azureus2.core3.util.LightHashMap; import org.gudy.azureus2.core3.util.RandomUtils; import org.gudy.azureus2.core3.util.SHA1Hasher; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.networkmanager.NetworkManager; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.core.util.bloom.BloomFilterFactory; public class ProtocolDecoderPHE extends ProtocolDecoder { private static final LogIDs LOGID = LogIDs.NWMAN; private static final byte CRYPTO_PLAIN = 0x01; private static final byte CRYPTO_RC4 = 0x02; private static final byte CRYPTO_XOR = 0x04; private static final byte CRYPTO_AES = 0x08; //private static final String DH_P = "92d862b3a95bff4e6cbdce3a266ff4b46e6e1ecad76c0a877d92a3dae4999e6414efde56fc14d1cca6d5408a8ef9ea248389168876b6e8f4503845dfe373549f"; //private static final String DH_G = "4383b53ee650fd73e41e8c9e8527997ab8cb41e1cbd73ac7685493e1e5d091e3e3789dea03ab9d5b2c368faa617bb30e427cbaeb23c268edb38eb8c747756080"; // private static final String DH_P = "f3f90c790c63b119f9c1be43fdb12dc6ed6f26325999c01ba6ed373e75d6b2dee8d1c0475652a987c8df57b23d395bdb142be316d780b9361f85629535030873"; private static final String DH_P = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563"; private static final String DH_G = "02"; private static final int DH_L = 160; private static final int DH_SIZE_BYTES = DH_P.length()/2; public static final int MIN_INCOMING_INITIAL_PACKET_SIZE = DH_SIZE_BYTES; private static final BigInteger DH_P_BI = new BigInteger( DH_P, 16 ); private static final BigInteger DH_G_BI = new BigInteger( DH_G, 16 ); private static KeyPairGenerator dh_key_generator; private static long last_dh_incoming_key_generate; private static final int BLOOM_RECREATE = 30*1000; private static final int BLOOM_INCREASE = 1000; private static BloomFilter generate_bloom = BloomFilterFactory.createAddRemove4Bit(BLOOM_INCREASE); private static long generate_bloom_create_time = SystemTime.getCurrentTime(); private static boolean crypto_setup_done; private static boolean crypto_ok; //private static boolean aes_ok; /* private static final String AES_STREAM_ALG = "AES"; private static final String AES_STREAM_CIPHER = "AES/CFB8/NoPadding"; private static final int AES_STREAM_KEY_SIZE = 128; private static final int AES_STREAM_KEY_SIZE_BYTES = AES_STREAM_KEY_SIZE/8; */ //private static final byte[] AES_STREAM_IV = // { (byte)0x15, (byte)0xE0, (byte)0x6B, (byte)0x7E, (byte)0x98, (byte)0x59, (byte)0xE4, (byte)0xA7, // (byte)0x34, (byte)0x66, (byte)0xAD, (byte)0x48, (byte)0x35, (byte)0xE2, (byte)0xD0, (byte)0x24 }; private static final String RC4_STREAM_ALG = "RC4"; private static final String RC4_STREAM_CIPHER = "RC4"; private static final int RC4_STREAM_KEY_SIZE = 128; private static final int RC4_STREAM_KEY_SIZE_BYTES = RC4_STREAM_KEY_SIZE/8; private static final int PADDING_MAX = 512; private static final int PADDING_MAX_NORMAL = PADDING_MAX; private static final int PADDING_MAX_LIMITED = 128; public static int getMaxIncomingInitialPacketSize( boolean min_overheads ) { return( MIN_INCOMING_INITIAL_PACKET_SIZE + (min_overheads?PADDING_MAX_LIMITED:PADDING_MAX_NORMAL)/2 ); } private static Random random = RandomUtils.SECURE_RANDOM; private static Map global_shared_secrets = new LightHashMap(); private static void cryptoSetup() { synchronized( global_shared_secrets ){ if ( crypto_setup_done ){ return; } crypto_setup_done = true; try{ DHParameterSpec dh_param_spec = new DHParameterSpec( DH_P_BI, DH_G_BI, DH_L ); dh_key_generator = KeyPairGenerator.getInstance("DH"); dh_key_generator.initialize(dh_param_spec); dh_key_generator.generateKeyPair(); byte[] rc4_test_secret = new byte[RC4_STREAM_KEY_SIZE_BYTES]; SecretKeySpec rc4_test_secret_key_spec = new SecretKeySpec(rc4_test_secret, 0, RC4_STREAM_KEY_SIZE_BYTES, RC4_STREAM_ALG ); TransportCipher rc4_cipher = new TransportCipher( RC4_STREAM_CIPHER, Cipher.ENCRYPT_MODE, rc4_test_secret_key_spec ); rc4_cipher = new TransportCipher( RC4_STREAM_CIPHER, Cipher.DECRYPT_MODE, rc4_test_secret_key_spec ); /* try{ byte[] aes_test_secret = new byte[AES_STREAM_KEY_SIZE_BYTES]; SecretKeySpec aes_test_secret_key_spec = new SecretKeySpec(aes_test_secret, 0, AES_STREAM_KEY_SIZE_BYTES, AES_STREAM_ALG ); AlgorithmParameterSpec spec = new IvParameterSpec( aes_test_secret ); TCPTransportCipher aes_cipher = new TCPTransportCipher( AES_STREAM_CIPHER, Cipher.ENCRYPT_MODE, aes_test_secret_key_spec, spec ); aes_cipher = new TCPTransportCipher( AES_STREAM_CIPHER, Cipher.DECRYPT_MODE, aes_test_secret_key_spec, spec ); aes_ok = true; }catch( Throwable e ){ Logger.log( new LogEvent(LOGID, "AES Unavailable", e )); } */ crypto_ok = true; if (Logger.isEnabled()){ Logger.log( new LogEvent(LOGID, "PHE crypto initialised" )); } }catch( NoClassDefFoundError e ){ // running without PHE classes, not such a severe error Logger.log( new LogEvent(LOGID, "PHE crypto disabled as classes unavailable" )); crypto_ok = false; }catch( Throwable e ){ Logger.log( new LogEvent(LOGID, "PHE crypto initialisation failed", e )); crypto_ok = false; } } } public static boolean isCryptoOK() { cryptoSetup(); return( crypto_ok ); } public static void addSecretsSupport( byte[][] secrets ) { for (int i=0;iB: Diffie Hellman Ya, PadA X_2 B->A: Diffie Hellman Yb, PadB X_3 A->B: HASH('req1', S), HASH('req2', SKEY)^HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA) X_4 B->A: ENCRYPT(VC, crypto_select, len(padD), padD ) // , len(IB)), ENCRYPT(IB) */ protected void process() throws IOException { try{ process_mon.enter(); if ( handshake_complete ){ Debug.out( "Handshake process already completed" ); return; } boolean loop = true; while( loop ){ // System.out.println( this + ":" + (outbound?"out: ":"in : ") + protocol_state + "/" + protocol_substate + ": r " + bytes_read + " - " + read_buffer + ", w " + bytes_written + " - " + write_buffer ); if ( protocol_state == PS_OUTBOUND_1 ){ if ( write_buffer == null ){ // A sends B Ya + Pa byte[] padding_a = getRandomPadding(getPaddingMax()/2); // note that /2 also used in calculating max initial packet size above write_buffer = ByteBuffer.allocate( dh_public_key_bytes.length + padding_a.length ); write_buffer.put( dh_public_key_bytes ); write_buffer.put( padding_a ); write_buffer.flip(); } write( write_buffer ); if ( !write_buffer.hasRemaining()){ write_buffer = null; protocol_state = PS_INBOUND_2; } }else if ( protocol_state == PS_INBOUND_1 ){ // B receives Ya read( read_buffer ); if ( !read_buffer.hasRemaining()){ read_buffer.flip(); byte[] other_dh_public_key_bytes = new byte[read_buffer.remaining()]; read_buffer.get( other_dh_public_key_bytes ); completeDH( other_dh_public_key_bytes ); read_buffer = null; protocol_state = PS_OUTBOUND_2; } }else if ( protocol_state == PS_OUTBOUND_2 ){ // B->A: Yb PadB if ( write_buffer == null ){ byte[] padding_b = getRandomPadding( getPaddingMax()/2 ); write_buffer = ByteBuffer.allocate( dh_public_key_bytes.length + padding_b.length ); write_buffer.put( dh_public_key_bytes ); write_buffer.put( padding_b ); write_buffer.flip(); } write( write_buffer ); if ( !write_buffer.hasRemaining()){ write_buffer = null; protocol_state = PS_INBOUND_3; } }else if ( protocol_state == PS_INBOUND_2 ){ // A receives: Yb if ( read_buffer == null ){ read_buffer = ByteBuffer.allocate( dh_public_key_bytes.length ); } read( read_buffer ); if ( !read_buffer.hasRemaining()){ read_buffer.flip(); byte[] other_dh_public_key_bytes = new byte[read_buffer.remaining()]; read_buffer.get( other_dh_public_key_bytes ); completeDH( other_dh_public_key_bytes ); // A initiates SKEY so we can now set up crypto setupCrypto(); read_buffer = null; protocol_state = PS_OUTBOUND_3; } }else if ( protocol_state == PS_OUTBOUND_3 ){ // A->B: HASH('req1', S), HASH('req2', SKEY)^HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA) if ( write_buffer == null ){ int initial_data_out_len = initial_data_out==null?0:initial_data_out.remaining(); // padding_a here is half of the padding from before int pad_max = getPaddingMax(); byte[] padding_a = getRandomPadding(pad_max/2); byte[] padding_c = getZeroPadding(pad_max); write_buffer = ByteBuffer.allocate( padding_a.length + 20 + 20 + ( VC.length + 4 + 2 + padding_c.length + 2 ) + initial_data_out_len ); write_buffer.put( padding_a ); // HASH('req1', S) SHA1Hasher hasher = new SHA1Hasher(); hasher.update( REQ1_IV ); hasher.update( secret_bytes ); byte[] sha1 = hasher.getDigest(); write_buffer.put( sha1 ); // HASH('req2', SKEY)^HASH('req3', S) hasher = new SHA1Hasher(); hasher.update( REQ2_IV ); hasher.update( shared_secret ); byte[] sha1_1 = hasher.getDigest(); hasher = new SHA1Hasher(); hasher.update( REQ3_IV ); hasher.update( secret_bytes ); byte[] sha1_2 = hasher.getDigest(); for (int i=0;i>8),(byte)padding_c.length })); write_buffer.put( write_cipher.update( padding_c )); write_buffer.put( write_cipher.update( new byte[]{ (byte)(initial_data_out_len>>8),(byte)initial_data_out_len })); if ( initial_data_out_len > 0 ){ int save_pos = initial_data_out.position(); write_cipher.update( initial_data_out, write_buffer ); // reset in case buffer needs to be used again by caller initial_data_out.position( save_pos ); initial_data_out = null; } write_buffer.flip(); } write( write_buffer ); if ( !write_buffer.hasRemaining()){ write_buffer = null; protocol_state = PS_INBOUND_4; } }else if ( protocol_state == PS_INBOUND_3 ){ // B receives: HASH('req1', S), HASH('req2', SKEY)^HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA) if ( read_buffer == null ){ read_buffer = ByteBuffer.allocate( 20 + PADDING_MAX ); read_buffer.limit( 20 ); SHA1Hasher hasher = new SHA1Hasher(); hasher.update( REQ1_IV ); hasher.update( secret_bytes ); padding_skip_marker = hasher.getDigest(); protocol_substate = 1; } while( true ){ read( read_buffer ); if ( read_buffer.hasRemaining()){ break; } if ( protocol_substate == 1 ){ //skip up to HASH('req1', S) int limit = read_buffer.limit(); read_buffer.position( limit - 20 ); boolean match = true; for (int i=0;i<20;i++){ if ( read_buffer.get() != padding_skip_marker[i] ){ match = false; break; } } if ( match ){ read_buffer = ByteBuffer.allocate( 20 + VC.length + 4 + 2 ); protocol_substate = 2; break; }else{ if ( limit == read_buffer.capacity()){ throw( new IOException( "PHE skip to SHA1 marker failed" )); } read_buffer.limit( limit + 1 ); read_buffer.position( limit ); } }else if ( protocol_substate == 2 ){ // find SKEY using HASH('req2', SKEY)^HASH('req3', S) , ENCRYPT(VC, crypto_provide, len(PadC), read_buffer.flip(); final byte[] decode = new byte[20]; read_buffer.get( decode ); SHA1Hasher hasher = new SHA1Hasher(); hasher.update( REQ3_IV ); hasher.update( secret_bytes ); byte[] sha1 = hasher.getDigest(); for (int i=0;i 65535 ){ throw( new IOException( "Invalid IA length '" + ia_len + "'" )); } if ( ia_len > 0 ){ read_buffer = ByteBuffer.allocate( ia_len ); // skip the padding protocol_substate = 4; }else{ read_buffer = null; protocol_state = PS_OUTBOUND_4; break; } }else if ( protocol_substate == 4 ){ // ENCRYPT(IA) read_buffer.flip(); byte[] data = new byte[read_buffer.remaining()]; read_buffer.get( data ); data = read_cipher.update( data ); // hack alert - we can delay the writing of the outbound_4 packet if this is an incoming packet with // a piggybacked bt handshake as we know that we'll be sending our own handshake back out pretty soon // and it'll take the delayed data with it. To be more generic we'd need to add a callback to the pattern // matcher to allow it to decide whether delaying was sensible / or stick a timer on the delayed data delay_outbound_4 = new String( data ).indexOf( "BitTorrent" ) != -1; // System.out.println( "Initial Data In: " + new String( data ) + "->delay=" +delay_outbound_4 ); initial_data_in = ByteBuffer.wrap( data ); read_buffer = null; protocol_state = PS_OUTBOUND_4; break; } } }else if ( protocol_state == PS_OUTBOUND_4 ){ // B->A: ENCRYPT(VC, crypto_select, len(padD), padD, // len(IB)), ENCRYPT(IB) if ( write_buffer == null ){ int pad_max = getPaddingMax(); byte[] padding_b = getRandomPadding( pad_max/2 ); // half padding b sent here byte[] padding_d = getZeroPadding( pad_max ); write_buffer = ByteBuffer.allocate( padding_b.length + VC.length + 4 + 2 + padding_d.length ); // + 2 + initial_data_out.length ); write_buffer.put( padding_b ); write_buffer.put( write_cipher.update( VC )); write_buffer.put( write_cipher.update( new byte[]{ 0, 0, 0, selected_protocol })); write_buffer.put( write_cipher.update( new byte[]{ (byte)(padding_d.length>>8),(byte)padding_d.length })); write_buffer.put( write_cipher.update( padding_d )); //write_buffer.put( write_cipher.update( new byte[]{ (byte)(initial_data_out.length>>8),(byte)initial_data_out.length })); //write_buffer.put( write_cipher.update( initial_data_out )); write_buffer.flip(); } if ( delay_outbound_4 ){ if ( transport.delayWrite( write_buffer )){ write_buffer = null; handshakeComplete(); }else{ delay_outbound_4 = false; } } if ( !delay_outbound_4 ){ write( write_buffer ); if ( !write_buffer.hasRemaining()){ write_buffer = null; handshakeComplete(); } } }else if ( protocol_state == PS_INBOUND_4 ){ // B->A: ENCRYPT(VC, crypto_select, len(padD), padD // , len(IB)), ENCRYPT(IB) if ( read_buffer == null ){ read_buffer = ByteBuffer.allocate( VC.length + PADDING_MAX ); read_buffer.limit( VC.length ); padding_skip_marker = new byte[VC.length]; padding_skip_marker = read_cipher.update( padding_skip_marker ); protocol_substate = 1; } while( true ){ read( read_buffer ); if ( read_buffer.hasRemaining()){ break; } if ( protocol_substate == 1 ){ //skip up to marker int limit = read_buffer.limit(); read_buffer.position( limit - VC.length ); boolean match = true; for (int i=0;i 65535 ){ throw( new IOException( "Invalid IB length '" + ib_len + "'" )); } read_buffer = ByteBuffer.allocate( ib_len ); protocol_substate = 4; }else{ read_buffer.flip(); byte[] data = new byte[read_buffer.remaining()]; read_buffer.get( data ); initial_data_in = read_cipher.update( data ); handshakeComplete(); read_buffer = null; break; */ } } } if ( handshake_complete ){ transport.cancelReadSelects(); transport.cancelWriteSelects(); loop = false; complete(); }else{ if ( read_buffer == null ){ transport.pauseReadSelects(); }else{ transport.resumeReadSelects(); loop = false; } if ( write_buffer == null ){ transport.pauseWriteSelects(); }else{ transport.resumeWriteSelects(); loop = false; } } } }catch( Throwable e ){ failed( e ); if ( e instanceof IOException ){ throw((IOException)e); }else{ throw( new IOException( Debug.getNestedExceptionMessage(e))); } }finally{ process_mon.exit(); } } /* **** OUTBOUND_1 A sends B odd/even byte + Ya + Pa **** INBOUND_1 B receives Ya B computes Yb B computes S and HS **** OUTBOUND_2 B sends A Yb + HS( "supported methods" + len(Pb)) + Pb **** INBOUND_2 A receives Yb A computes S and HS A receives HS( "supported methods" + len(Pb)) and decrypts using HS A skips len(Pb) random bytes **** OUTBOUND_3 A sends SHA1(S) + HS( "selected method" + len(Pc)) + Pc + selectedCrypt( payload ) **** INBOUND_3 B skips Pa bytes until receives SHA1(S) B decrypts "selected method" + len(Pc) and skips len(Pc) bytes to get to selectedCrypt( payload... ) B sends A selectedCrypt( payload... ) */ /* protected void process() throws IOException { try{ process_mon.enter(); if ( handshake_complete ){ Debug.out( "Handshake process already completed" ); return; } boolean loop = true; while( loop ){ if ( protocol_state == PS_OUTBOUND_1 ){ if ( write_buffer == null ){ // A sends B odd/even Ya + Pa byte[] padding = getPadding(); write_buffer = ByteBuffer.allocate( dh_public_key_bytes.length + padding.length ); write_buffer.put( dh_public_key_bytes ); write_buffer.put( padding ); write_buffer.flip(); } write( write_buffer ); if ( !write_buffer.hasRemaining()){ write_buffer = null; protocol_state = PS_INBOUND_2; } }else if ( protocol_state == PS_OUTBOUND_2 ){ // B sends A Yb + HS( "supported methods" + len(Pb)) + Pb if ( write_buffer == null ){ byte[] padding = getPadding(); write_buffer = ByteBuffer.allocate( dh_public_key_bytes.length + 4 + 2 + padding.length ); write_buffer.put( dh_public_key_bytes ); // 4 bytes for my supported protocols write_buffer.put( write_cipher.update( new byte[]{ 0, 0, 0, my_supported_protocols })); write_buffer.put( write_cipher.update( new byte[]{ (byte)(padding.length>>8),(byte)padding.length })); write_buffer.put( padding ); write_buffer.flip(); } write( write_buffer ); if ( !write_buffer.hasRemaining()){ write_buffer = null; protocol_state = PS_INBOUND_3; } }else if ( protocol_state == PS_OUTBOUND_3 ){ // A sends SHA1(S) + HS( "selected method" + len(Pc)) + Pc + selectedCrypt( payload ) if ( write_buffer == null ){ byte[] padding = getPadding(); write_buffer = ByteBuffer.allocate( 20 + 4 + 2 + padding.length ); write_buffer.put( sha1_secret_bytes ); write_buffer.put( write_cipher.update( new byte[]{ 0, 0, 0, selected_protocol })); write_buffer.put( write_cipher.update( new byte[]{ (byte)(padding.length>>8),(byte)padding.length })); write_buffer.put( padding ); write_buffer.flip(); } write( write_buffer ); if ( !write_buffer.hasRemaining()){ write_buffer = null; handshakeComplete(); } }else if ( protocol_state == PS_INBOUND_1 ){ // B receives marker + Ya read( read_buffer ); if ( !read_buffer.hasRemaining()){ read_buffer.flip(); byte[] other_dh_public_key_bytes = new byte[read_buffer.remaining()]; read_buffer.get( other_dh_public_key_bytes ); completeDH( other_dh_public_key_bytes ); read_buffer = null; protocol_state = PS_OUTBOUND_2; } }else if ( protocol_state == PS_INBOUND_2 ){ //A receives Yb //A computes S and HS //A receives HS( "supported methods" + len(Pb)) and decrypts using HS //A skips len(Pb) random bytes if ( read_buffer == null ){ read_buffer = ByteBuffer.allocate( dh_public_key_bytes.length + 6 ); protocol_substate = 1; } while( true ){ read( read_buffer ); if ( read_buffer.hasRemaining()){ break; } if ( protocol_substate == 1 ){ read_buffer.flip(); byte[] other_dh_public_key_bytes_etc = read_buffer.array(); completeDH( other_dh_public_key_bytes_etc ); byte[] etc = read_cipher.update( other_dh_public_key_bytes_etc, DH_SIZE_BYTES, 6 ); byte other_supported_protocols = etc[3]; int common_protocols = my_supported_protocols & other_supported_protocols; if (( common_protocols & CRYPTO_PLAIN )!= 0 ){ selected_protocol = CRYPTO_PLAIN; }else if (( common_protocols & CRYPTO_XOR )!= 0 ){ selected_protocol = CRYPTO_XOR; }else if (( common_protocols & CRYPTO_RC4 )!= 0 ){ selected_protocol = CRYPTO_RC4; }else if (( common_protocols & CRYPTO_AES )!= 0 ){ selected_protocol = CRYPTO_AES; }else{ throw( new IOException( "No crypto protocol in common: mine = " + Integer.toHexString((byte)my_supported_protocols) + ", theirs = " + Integer.toHexString((byte)other_supported_protocols))); } int padding = (( etc[4] & 0xff ) << 8 ) + ( etc[5] & 0xff ); if ( padding > PADDING_MAX ){ throw( new IOException( "Invalid padding '" + padding + "'" )); } read_buffer = ByteBuffer.allocate( padding ); protocol_substate = 2; }else{ read_buffer = null; protocol_state = PS_OUTBOUND_3; break; } } }else if ( protocol_state == PS_INBOUND_3 ){ // B skips Pa bytes until receives SHA1(S) // B decrypts "selected method" + len(Pc) and skips len(Pc) bytes if ( read_buffer == null ){ read_buffer = ByteBuffer.allocate( 20 + PADDING_MAX ); read_buffer.limit( 20 ); protocol_substate = 1; } while( true ){ read( read_buffer ); if ( read_buffer.hasRemaining()){ break; } if ( protocol_substate == 1 ){ int limit = read_buffer.limit(); read_buffer.position( limit - 20 ); boolean match = true; for (int i=0;i<20;i++){ if ( read_buffer.get() != sha1_secret_bytes[i] ){ match = false; break; } } if ( match ){ read_buffer = ByteBuffer.allocate( 6 ); protocol_substate = 2; break; }else{ if ( limit == read_buffer.capacity()){ throw( new IOException( "PHE skip to SHA1 marker failed" )); } read_buffer.limit( limit + 1 ); read_buffer.position( limit ); } }else if ( protocol_substate == 2 ){ read_buffer.flip(); byte[] etc = read_cipher.update( read_buffer.array()); selected_protocol = etc[3]; int padding = (( etc[4] & 0xff ) << 8 ) + ( etc[5] & 0xff ); if ( padding > PADDING_MAX ){ throw( new IOException( "Invalid padding '" + padding + "'" )); } read_buffer = ByteBuffer.allocate( padding ); protocol_substate = 3; }else{ read_buffer = null; handshakeComplete(); break; } } } if ( handshake_complete ){ read_selector.cancel( channel ); write_selector.cancel( channel ); loop = false; complete(); }else{ if ( read_buffer == null ){ read_selector.pauseSelects( channel ); }else{ read_selector.resumeSelects ( channel ); loop = false; } if ( write_buffer == null ){ write_selector.pauseSelects( channel ); }else{ write_selector.resumeSelects ( channel ); loop = false; } } } }catch( Throwable e ){ failed( e ); if ( e instanceof IOException ){ throw((IOException)e); }else{ throw( new IOException( Debug.getNestedExceptionMessage(e))); } }finally{ process_mon.exit(); } } */ protected void read( ByteBuffer buffer ) throws IOException { int len = transport.read( buffer ); //System.out.println( "read:" + this + "/" + protocol_state + "/" + protocol_substate + " -> " + len +"[" + buffer +"]"); if ( len < 0 ){ throw( new IOException( "end of stream on socket read - phe: " + getString())); } bytes_read += len; } protected void write( ByteBuffer buffer ) throws IOException { //System.out.println( "write pre:" + this + "/" + protocol_state + "/" + protocol_substate + " - " + buffer ); int len = transport.write( buffer, false ); //System.out.println( "write:" + this + "/" + protocol_state + "/" + protocol_substate + " -> " + len +"[" + buffer +"]"); if ( len < 0 ){ throw( new IOException( "bytes written < 0 " )); } bytes_written += len; } public boolean selectSuccess( TransportHelper transport, Object attachment, boolean write_operation ) { try{ int old_bytes_read = bytes_read; int old_bytes_written = bytes_written; process(); if ( write_operation ){ return( bytes_written != old_bytes_written ); }else{ boolean progress = bytes_read != old_bytes_read; if ( progress ){ last_read_time = SystemTime.getCurrentTime(); } return( progress ); } }catch( Throwable e ){ failed( e ); return( false ); } } public void selectFailure( TransportHelper transport, Object attachment, Throwable msg ) { failed( msg ); } protected byte[] bigIntegerToBytes( BigInteger bi, int num_bytes ) { String str = bi.toString(16); while( str.length() < num_bytes*2 ){ str = "0" + str; } return( ByteFormatter.decodeString(str)); } protected BigInteger bytesToBigInteger( byte[] bytes, int offset, int len ) { return( new BigInteger( ByteFormatter.encodeString( bytes, offset, len ), 16 )); } protected int getPaddingMax() { if ( transport.minimiseOverheads()){ return( PADDING_MAX_LIMITED ); }else{ return( PADDING_MAX_NORMAL ); } } protected static synchronized byte[] getRandomPadding( int max_len ) { byte[] bytes = new byte[ random.nextInt(max_len)]; random.nextBytes(bytes); return( bytes ); } protected static synchronized byte[] getZeroPadding( int max_len ) { byte[] bytes = new byte[ random.nextInt(max_len)]; return( bytes ); } protected static KeyPair generateDHKeyPair( TransportHelper transport, boolean outbound ) throws IOException { if ( dh_key_generator == null ){ throw( new IOException( "Crypto not setup" )); } synchronized( dh_key_generator ){ if ( !outbound ){ byte[] address = transport.getAddress().getAddress().getAddress(); int hit_count = generate_bloom.add( address ); long now = SystemTime.getCurrentTime(); // allow up to 10% bloom filter utilisation if ( generate_bloom.getSize() / generate_bloom.getEntryCount() < 10 ){ generate_bloom = BloomFilterFactory.createAddRemove4Bit(generate_bloom.getSize() + BLOOM_INCREASE ); generate_bloom_create_time = now; Logger.log( new LogEvent(LOGID, "PHE bloom: size increased to " + generate_bloom.getSize())); }else if ( now < generate_bloom_create_time || now - generate_bloom_create_time > BLOOM_RECREATE ){ generate_bloom = BloomFilterFactory.createAddRemove4Bit(generate_bloom.getSize()); generate_bloom_create_time = now; } if ( hit_count >= 15 ){ Logger.log( new LogEvent(LOGID, "PHE bloom: too many recent connection attempts from " + transport.getAddress())); throw( new IOException( "Too many recent connection attempts (phe)")); } long since_last = now - last_dh_incoming_key_generate; long delay = 100 - since_last; // limit key gen operations to 10 a second if ( delay > 0 && delay < 100 ){ try{ Thread.sleep( delay ); }catch( Throwable e ){ } } last_dh_incoming_key_generate = now; } KeyPair res = dh_key_generator.generateKeyPair(); return( res ); } } protected void complete() { // System.out.println( (outbound?"out: ":"in :") + " complete, r " + bytes_read + ", w " + bytes_written + ", initial data = " + initial_data_in.length + "/" + initial_data_out.length ); processing_complete = true; adapter.decodeComplete( this, initial_data_out ); } protected void failed( Throwable cause ) { // System.out.println( (outbound?"out: ":"in :") + " failed, " + cause.getMessage()); processing_complete = true; transport.cancelReadSelects(); transport.cancelWriteSelects(); adapter.decodeFailed( this, cause ); } public boolean isComplete( long now ) { return( processing_complete ); } public TransportHelperFilter getFilter() { return( filter ); } public long getLastReadTime() { long now = SystemTime.getCurrentTime(); if ( last_read_time > now ){ last_read_time = now; } return( last_read_time ); } public String getString() { return( "state=" + protocol_state + ",sub=" + protocol_substate + ",in=" + bytes_read + ",out=" + bytes_written); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/EntityHandler.java0000644000175000017500000001731411166501252027103 0ustar adrianadrian/* * Created on Sep 23, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.util.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.networkmanager.*; /** * Manages transfer entities on behalf of peer connections. * Each entity handler has a global pool which manages all * connections by default. Connections can also be "upgraded" * to a higher connection control level, i.e. each connection * has its own specialized entity for performance purposes. */ public class EntityHandler { private final HashMap upgraded_connections = new HashMap(); private final AEMonitor lock = new AEMonitor( "EntityHandler" ); private final MultiPeerUploader global_uploader; private final MultiPeerDownloader2 global_downloader; private boolean global_registered = false; private final int handler_type; /** * Create a new entity handler using the given rate handler. * @param type read or write type handler * @param rate_handler global max rate handler */ public EntityHandler( int type, RateHandler rate_handler ) { this.handler_type = type; if( handler_type == TransferProcessor.TYPE_UPLOAD ) { global_uploader = new MultiPeerUploader( rate_handler ); global_downloader = null; } else { //download type global_downloader = new MultiPeerDownloader2( rate_handler ); global_uploader = null; } } /** * Register a peer connection for management by the handler. * @param connection to add to the global pool */ public void registerPeerConnection( NetworkConnectionBase connection ) { try { lock.enter(); if( !global_registered ) { if( handler_type == TransferProcessor.TYPE_UPLOAD ) { NetworkManager.getSingleton().addWriteEntity( global_uploader, -1 ); //register global upload entity } else { NetworkManager.getSingleton().addReadEntity( global_downloader, -1 ); //register global download entity } global_registered = true; } } finally { lock.exit(); } if( handler_type == TransferProcessor.TYPE_UPLOAD ) { global_uploader.addPeerConnection( connection ); } else { global_downloader.addPeerConnection( connection ); } } /** * Remove a peer connection from the entity handler. * @param connection to cancel */ public void cancelPeerConnection( NetworkConnectionBase connection ) { if( handler_type == TransferProcessor.TYPE_UPLOAD ) { if( !global_uploader.removePeerConnection( connection ) ) { //if not found in the pool entity SinglePeerUploader upload_entity = (SinglePeerUploader)upgraded_connections.remove( connection ); //check for it in the upgraded list if( upload_entity != null ) { NetworkManager.getSingleton().removeWriteEntity( upload_entity ); //cancel from write processing } } } else { if( !global_downloader.removePeerConnection( connection ) ) { //if not found in the pool entity SinglePeerDownloader download_entity = (SinglePeerDownloader)upgraded_connections.remove( connection ); //check for it in the upgraded list if( download_entity != null ) { NetworkManager.getSingleton().removeReadEntity( download_entity ); //cancel from read processing } } } } /** * Upgrade a peer connection from the general pool to its own high-speed entity. * @param connection to upgrade from global management * @param handler individual connection rate handler */ public void upgradePeerConnection( NetworkConnectionBase connection, RateHandler handler, int partition_id ) { try { lock.enter(); if( handler_type == TransferProcessor.TYPE_UPLOAD ) { SinglePeerUploader upload_entity = new SinglePeerUploader( connection, handler ); if( !global_uploader.removePeerConnection( connection ) ) { //remove it from the general upload pool Debug.out( "upgradePeerConnection:: upload entity not found/removed !" ); } NetworkManager.getSingleton().addWriteEntity( upload_entity, partition_id ); //register it for write processing upgraded_connections.put( connection, upload_entity ); //add it to the upgraded list } else { SinglePeerDownloader download_entity = new SinglePeerDownloader( connection, handler ); if( !global_downloader.removePeerConnection( connection ) ) { //remove it from the general upload pool Debug.out( "upgradePeerConnection:: download entity not found/removed !" ); } NetworkManager.getSingleton().addReadEntity( download_entity, partition_id ); //register it for read processing upgraded_connections.put( connection, download_entity ); //add it to the upgraded list } } finally { lock.exit(); } } /** * Downgrade (return) a peer connection back into the general pool. * @param connection to downgrade back into the global entity */ public void downgradePeerConnection( NetworkConnectionBase connection ) { try { lock.enter(); if( handler_type == TransferProcessor.TYPE_UPLOAD ) { SinglePeerUploader upload_entity = (SinglePeerUploader)upgraded_connections.remove( connection ); //remove from the upgraded list if( upload_entity != null ) { NetworkManager.getSingleton().removeWriteEntity( upload_entity ); //cancel from write processing } else { Debug.out( "upload_entity == null" ); } global_uploader.addPeerConnection( connection ); //move back to the general pool } else { SinglePeerDownloader download_entity = (SinglePeerDownloader)upgraded_connections.remove( connection ); //remove from the upgraded list if( download_entity != null ) { NetworkManager.getSingleton().removeReadEntity( download_entity ); //cancel from read processing } else { Debug.out( "download_entity == null" ); } global_downloader.addPeerConnection( connection ); //move back to the general pool } } finally { lock.exit(); } } /** * Is the general pool entity in need of a transfer op. * NOTE: Because the general pool is backed by a MultiPeer entity, * it requires at least MSS available bytes before it will/can perform * a successful transfer. This method allows higher-level bandwidth allocation to * determine if it should reserve the necessary MSS bytes for the general pool's needs. * @return true of it has data to transfer, false if not */ /* public boolean isGeneralPoolReserveNeeded() { if( handler_type == TransferProcessor.TYPE_UPLOAD ) { return global_uploader.hasWriteDataAvailable(); } return global_downloader.hasReadDataAvailable(); } */ } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterInserter.java0000644000175000017500000000621411001746712032344 0ustar adrianadrian/* * Created on 26-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.nio.ByteBuffer; public class TransportHelperFilterInserter implements TransportHelperFilter { private TransportHelperFilter target_filter; private ByteBuffer read_insert; public TransportHelperFilterInserter( TransportHelperFilter _target_filter, ByteBuffer _read_insert ) { target_filter = _target_filter; read_insert = _read_insert; } public long write( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { return( target_filter.write( buffers, array_offset, length )); } public long read( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { long total_read = 0; if ( read_insert != null ){ int pos_before = read_insert.position(); for (int i=array_offset;i 0 ){ if ( space < read_insert.remaining()){ int old_limit = read_insert.limit(); read_insert.limit( read_insert.position() + space ); buffer.put( read_insert ); read_insert.limit( old_limit ); }else{ buffer.put( read_insert ); } if ( !read_insert.hasRemaining()){ break; } } } total_read = read_insert.position() - pos_before; if ( read_insert.hasRemaining()){ return( total_read ); }else{ read_insert = null; } } total_read += target_filter.read( buffers, array_offset, length ); return( total_read ); } public boolean hasBufferedWrite() { return( target_filter.hasBufferedWrite()); } public boolean hasBufferedRead() { return( read_insert != null || target_filter.hasBufferedRead()); } public TransportHelper getHelper() { return( target_filter.getHelper()); } public void setTrace( boolean on ) { target_filter.setTrace( on ); } public boolean isEncrypted() { return( target_filter.isEncrypted()); } public String getName(boolean verbose) { return( target_filter.getName(verbose)); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStream.java0000644000175000017500000001704010572024436032007 0ustar adrianadrian/* * Created on 19-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.nio.ByteBuffer; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.DirectByteBufferPool; public abstract class TransportHelperFilterStream implements TransportHelperFilter { private TransportHelper transport; private DirectByteBuffer write_buffer_pending_db; private ByteBuffer write_buffer_pending_byte; protected TransportHelperFilterStream( TransportHelper _transport ) { transport = _transport; } public boolean hasBufferedWrite() { return( write_buffer_pending_db != null || write_buffer_pending_byte != null || transport.hasDelayedWrite()); } public boolean hasBufferedRead() { return false; } public TransportHelper getHelper() { return( transport ); } public long write( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { // deal with any outstanding cached crypted data first if ( write_buffer_pending_byte != null ){ if ( transport.write( write_buffer_pending_byte, false ) == 0 ){ return( 0 ); } write_buffer_pending_byte = null; } long total_written = 0; if ( write_buffer_pending_db != null ){ ByteBuffer write_buffer_pending = write_buffer_pending_db.getBuffer( DirectByteBuffer.SS_NET ); int max_writable = 0; for (int i=array_offset;i max_writable ){ pending_writable = max_writable; write_buffer_pending.limit( pending_position + pending_writable ); } int written = transport.write( write_buffer_pending, false ); write_buffer_pending.limit( pending_limit ); if ( written > 0 ){ total_written = written; if ( write_buffer_pending.remaining() == 0 ){ write_buffer_pending_db.returnToPool(); write_buffer_pending_db = null; } // skip "written" bytes in the source int skip = written; for (int i=array_offset;i 0 ){ copy_db[i] = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_NET_CRYPT, size ); copy[i] = copy_db[i].getBuffer( DirectByteBuffer.SS_NET ); }else{ copy[i] = ByteBuffer.allocate(0); } } total_read += transport.read( copy, array_offset, length ); for (int i=array_offset;i 0 ){ source_buffer.flip(); cryptoIn( source_buffer, target_buffer ); } } } // System.out.println( "...read " + total_read ); return( total_read ); }finally{ for (int i=0;iRawMessage conversions. */ public class RawMessageImpl implements RawMessage { private final Message message; private final DirectByteBuffer[] payload; private final int priority; private boolean is_no_delay; private final Message[] to_remove; /** * Create a new raw message using the given parameters. * @param source original message * @param raw_payload headers + original message data * @param priority in queue * @param is_no_delay is an urgent message * @param to_remove message types to auto-remove upon queue */ public RawMessageImpl( Message source, DirectByteBuffer[] raw_payload, int _priority, boolean _is_no_delay, Message[] _to_remove ) { this.message = source; this.payload = raw_payload; this.priority = _priority; this.is_no_delay = _is_no_delay; this.to_remove = _to_remove; } //message impl public String getID() { return message.getID(); } public byte[] getIDBytes() { return message.getIDBytes(); } public String getFeatureID() { return message.getFeatureID(); } public int getFeatureSubID() { return message.getFeatureSubID(); } public int getType() { return message.getType(); } public byte getVersion() { return message.getVersion(); } public String getDescription() { return message.getDescription(); } public DirectByteBuffer[] getData() { return message.getData(); } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { return message.deserialize( data, version ); } //rawmessage impl public DirectByteBuffer[] getRawData() { return payload; } public int getPriority() { return priority; } public boolean isNoDelay() { return is_no_delay; } public void setNoDelay() { is_no_delay = true; } public Message[] messagesToRemove() { return to_remove; } public Message getBaseMessage() { return message; } public void destroy() { //NOTE: Assumes that the raw payload is made up of the original // message data buffers plus some header data, so returning // the raw buffers will therefore also take care of the data // buffers return. for( int i=0; i < payload.length; i++ ) { payload[i].returnToPool(); } } /* public boolean equals( Object obj ) { //ensure we are comparing the underlying Message (and its equals() override if exists) if( obj instanceof RawMessage ) { obj = ((RawMessage)obj).getBaseMessage(); } return message.equals( obj ); } public int hashCode() { return message.hashCode(); } */ } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderInitial.java0000644000175000017500000002021710770547172030741 0ustar adrianadrian/* * Created on 18-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.nio.ByteBuffer; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.AddressUtils; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.networkmanager.NetworkManager; public class ProtocolDecoderInitial extends ProtocolDecoder { private static final LogIDs LOGID = LogIDs.NWMAN; private ProtocolDecoderAdapter adapter; private TransportHelperFilter filter; private TransportHelper transport; private byte[][] shared_secrets; private ByteBuffer initial_data; private ByteBuffer decode_buffer; private int decode_read; private long start_time = SystemTime.getCurrentTime(); private ProtocolDecoderPHE phe_decoder; private long last_read_time = 0; private boolean processing_complete; public ProtocolDecoderInitial( TransportHelper _transport, byte[][] _shared_secrets, boolean _outgoing, ByteBuffer _initial_data, ProtocolDecoderAdapter _adapter ) throws IOException { super( true ); transport = _transport; shared_secrets = _shared_secrets; initial_data = _initial_data; adapter = _adapter; final TransportHelperFilterTransparent transparent_filter = new TransportHelperFilterTransparent( transport, false ); filter = transparent_filter; if ( _outgoing ){ //we assume that for outgoing connections, if we are here, we want to use crypto if ( ProtocolDecoderPHE.isCryptoOK()){ decodePHE( null ); }else{ throw( new IOException( "Crypto required but unavailable" )); } }else{ decode_buffer = ByteBuffer.allocate( adapter.getMaximumPlainHeaderLength()); transport.registerForReadSelects( new TransportHelper.selectListener() { public boolean selectSuccess( TransportHelper helper, Object attachment ) { try{ int len = helper.read( decode_buffer ); if ( len < 0 ){ failed( new IOException( "end of stream on socket read: in=" + decode_buffer.position())); }else if ( len == 0 ){ return( false ); } last_read_time = SystemTime.getCurrentTime(); decode_read += len; int match = adapter.matchPlainHeader( decode_buffer ); if ( match != ProtocolDecoderAdapter.MATCH_NONE ){ helper.cancelReadSelects(); if ( NetworkManager.REQUIRE_CRYPTO_HANDSHAKE && match == ProtocolDecoderAdapter.MATCH_CRYPTO_NO_AUTO_FALLBACK ){ if ( NetworkManager.INCOMING_HANDSHAKE_FALLBACK_ALLOWED ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Incoming connection ["+ transport.getAddress() + "] is not encrypted but has been accepted as fallback is enabled" )); } else if( AddressUtils.isLANLocalAddress( transport.getAddress().getAddress().getHostAddress() ) == AddressUtils.LAN_LOCAL_YES ) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Incoming connection ["+ transport.getAddress() + "] is not encrypted but has been accepted as lan-local" )); } else{ throw( new IOException( "Crypto required but incoming connection has none" )); } } decode_buffer.flip(); transparent_filter.insertRead( decode_buffer ); complete( initial_data ); }else{ if ( !decode_buffer.hasRemaining()){ helper.cancelReadSelects(); if ( NetworkManager.INCOMING_CRYPTO_ALLOWED ){ decode_buffer.flip(); decodePHE( decode_buffer ); }else{ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Incoming connection ["+ transport.getAddress() + "] encrypted but rejected as not permitted" )); throw( new IOException( "Incoming crypto connection not permitted" )); } } } return( true ); }catch( Throwable e ){ selectFailure( helper, attachment, e ); return( false ); } } public void selectFailure( TransportHelper helper, Object attachment, Throwable msg) { helper.cancelReadSelects(); failed( msg ); } }, this ); } } protected void decodePHE( ByteBuffer buffer ) throws IOException { ProtocolDecoderAdapter phe_adapter = new ProtocolDecoderAdapter() { public void decodeComplete( ProtocolDecoder decoder, ByteBuffer remaining_initial_data ) { filter = decoder.getFilter(); complete( remaining_initial_data ); } public void decodeFailed( ProtocolDecoder decoder, Throwable cause ) { failed( cause ); } public void gotSecret( byte[] session_secret ) { adapter.gotSecret( session_secret ); } public int getMaximumPlainHeaderLength() { throw( new RuntimeException()); } public int matchPlainHeader( ByteBuffer buffer ) { throw( new RuntimeException()); } }; phe_decoder = new ProtocolDecoderPHE( transport, shared_secrets, buffer, initial_data, phe_adapter ); } public boolean isComplete( long now ) { if ( !processing_complete ){ if ( start_time > now ){ start_time = now; } if ( last_read_time > now ){ last_read_time = now; } if ( phe_decoder != null ){ last_read_time = phe_decoder.getLastReadTime(); } long timeout; long time; if ( last_read_time == 0 ){ timeout = transport.getConnectTimeout(); time = start_time; }else{ timeout = transport.getReadTimeout(); time = last_read_time; } if ( now - time > timeout ){ try{ transport.cancelReadSelects(); transport.cancelWriteSelects(); }catch( Throwable e ){ } String phe_str = ""; if ( phe_decoder != null ){ phe_str = ", crypto: " + phe_decoder.getString(); } if ( Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Connection [" + transport.getAddress() + "] forcibly timed out after " + timeout/1000 + "sec due to socket inactivity")); } failed( new Throwable( "Protocol decode aborted: timed out after " + timeout/1000+ "sec: " + decode_read + " bytes read" + phe_str )); } } return( processing_complete ); } public TransportHelperFilter getFilter() { return( filter ); } protected void complete( ByteBuffer remaining_initial_data ) { if ( !processing_complete ){ processing_complete = true; adapter.decodeComplete( this, remaining_initial_data ); } } protected void failed( Throwable reason ) { if ( !processing_complete ){ processing_complete = true; adapter.decodeFailed( this, reason ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/RateControlledEntity.java0000644000175000017500000000421610540461530030443 0ustar adrianadrian/* * Created on Sep 27, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import com.aelitis.azureus.core.networkmanager.EventWaiter; /** * Interface designation for rate-limited entities controlled by a handler. */ public interface RateControlledEntity { /** * Uses fair round-robin scheduling of processing ops. */ public static final int PRIORITY_NORMAL = 0; /** * Guaranteed scheduling of processing ops, with preference over normal-priority entities. */ public static final int PRIORITY_HIGH = 1; /** * Is ready for a processing op. * @return true if it can process >0 bytes, false if not ready */ public boolean canProcess( EventWaiter waiter ); /** * Attempt to do a processing operation. * @return true if >0 bytes were processed (success), false if 0 bytes were processed (failure) */ public boolean doProcessing( EventWaiter waiter ); /** * Get this entity's priority level. * @return priority */ public int getPriority(); /** * stats functions * @return */ public long getBytesReadyToWrite(); public int getConnectionCount(); public int getReadyConnectionCount( EventWaiter waiter ); public String getString(); } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/NetworkConnectionImpl.java0000644000175000017500000002453511166501256030633 0ustar adrianadrian/* * Created on Jul 29, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.nio.ByteBuffer; import org.gudy.azureus2.core3.util.AddressUtils; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.networkmanager.*; import com.aelitis.azureus.core.peermanager.messaging.MessageStreamDecoder; import com.aelitis.azureus.core.peermanager.messaging.MessageStreamEncoder; /** * */ public class NetworkConnectionImpl extends NetworkConnectionHelper implements NetworkConnection { private final ConnectionEndpoint connection_endpoint; private boolean connect_with_crypto; private boolean allow_fallback; private byte[][] shared_secrets; private ConnectionListener connection_listener; private boolean is_connected; private byte is_lan_local = AddressUtils.LAN_LOCAL_MAYBE; private final OutgoingMessageQueueImpl outgoing_message_queue; private final IncomingMessageQueueImpl incoming_message_queue; private Transport transport; private volatile ConnectionAttempt connection_attempt; private volatile boolean closed; /** * Constructor for new OUTbound connection. * The connection is not yet established upon instantiation; use connect() to do so. * @param _remote_address to connect to * @param encoder default message stream encoder to use for the outgoing queue * @param decoder default message stream decoder to use for the incoming queue */ public NetworkConnectionImpl( ConnectionEndpoint _target, MessageStreamEncoder encoder, MessageStreamDecoder decoder, boolean _connect_with_crypto, boolean _allow_fallback, byte[][] _shared_secrets ) { connection_endpoint = _target; connect_with_crypto = _connect_with_crypto; allow_fallback = _allow_fallback; shared_secrets = _shared_secrets; is_connected = false; outgoing_message_queue = new OutgoingMessageQueueImpl( encoder ); incoming_message_queue = new IncomingMessageQueueImpl( decoder, this ); } /** * Constructor for new INbound connection. * The connection is assumed to be already established, by the given already-connected channel. * @param _remote_channel connected by * @param data_already_read bytestream already read during routing * @param encoder default message stream encoder to use for the outgoing queue * @param decoder default message stream decoder to use for the incoming queue */ public NetworkConnectionImpl( Transport _transport, MessageStreamEncoder encoder, MessageStreamDecoder decoder ) { transport = _transport; connection_endpoint = transport.getTransportEndpoint().getProtocolEndpoint().getConnectionEndpoint(); is_connected = true; outgoing_message_queue = new OutgoingMessageQueueImpl( encoder ); outgoing_message_queue.setTransport( transport ); incoming_message_queue = new IncomingMessageQueueImpl( decoder, this ); } public ConnectionEndpoint getEndpoint() { return( connection_endpoint ); } public void connect( int priority, ConnectionListener listener ) { connect( null, priority, listener ); } public void connect( ByteBuffer initial_outbound_data, int priority, ConnectionListener listener ) { this.connection_listener = listener; if( is_connected ){ connection_listener.connectStarted(); connection_listener.connectSuccess( initial_outbound_data ); return; } if ( connection_attempt != null ){ Debug.out( "Connection attempt already active" ); listener.connectFailure( new Throwable( "Connection attempt already active" )); return; } connection_attempt = connection_endpoint.connectOutbound( connect_with_crypto, allow_fallback, shared_secrets, initial_outbound_data, priority, new Transport.ConnectListener() { public void connectAttemptStarted() { connection_listener.connectStarted(); } public void connectSuccess( Transport _transport, ByteBuffer remaining_initial_data ) { is_connected = true; transport = _transport; outgoing_message_queue.setTransport( transport ); connection_listener.connectSuccess( remaining_initial_data ); connection_attempt = null; } public void connectFailure( Throwable failure_msg ) { is_connected = false; connection_listener.connectFailure( failure_msg ); } }); if ( closed ){ ConnectionAttempt ca = connection_attempt; if ( ca != null ){ ca.abandon(); } } } public Transport detachTransport() { Transport t = transport; transport = new bogusTransport( transport ); close(); return( t ); } public void close() { NetworkManager.getSingleton().stopTransferProcessing( this ); closed = true; if ( connection_attempt != null ){ connection_attempt.abandon(); } if ( transport != null ){ transport.close( "Tidy close" ); } incoming_message_queue.destroy(); outgoing_message_queue.destroy(); is_connected = false; } public void notifyOfException( Throwable error ) { if( connection_listener != null ) { connection_listener.exceptionThrown( error ); } else { Debug.out( "notifyOfException():: connection_listener == null for exception: " +error.getMessage() ); } } public OutgoingMessageQueue getOutgoingMessageQueue() { return outgoing_message_queue; } public IncomingMessageQueue getIncomingMessageQueue() { return incoming_message_queue; } public void startMessageProcessing() { NetworkManager.getSingleton().startTransferProcessing( this ); } public void enableEnhancedMessageProcessing( boolean enable, int partition_id ) { if( enable ) { NetworkManager.getSingleton().upgradeTransferProcessing( this, partition_id ); }else{ NetworkManager.getSingleton().downgradeTransferProcessing( this ); } } public Transport getTransport() { return transport; } public TransportBase getTransportBase() { return transport; } public int getMssSize() { if ( transport == null ){ return( NetworkManager.getMinMssSize()); }else{ return( transport.getMssSize()); } } public String toString() { return( transport==null?connection_endpoint.getDescription():transport.getDescription() ); } public boolean isConnected() { return is_connected; } public boolean isLANLocal() { if ( is_lan_local == AddressUtils.LAN_LOCAL_MAYBE ){ is_lan_local = AddressUtils.isLANLocalAddress( connection_endpoint.getNotionalAddress()); } return( is_lan_local == AddressUtils.LAN_LOCAL_YES ); } public String getString() { return( "tran=" + (transport==null?"null":transport.getDescription()+",w_ready=" + transport.isReadyForWrite(null)+",r_ready=" + transport.isReadyForRead( null ))+ ",in=" + incoming_message_queue.getPercentDoneOfCurrentMessage() + ",out=" + (outgoing_message_queue==null?0:outgoing_message_queue.getTotalSize()) + ",owner=" + (connection_listener==null?"null":connection_listener.getDescription())); } protected static class bogusTransport implements Transport { private Transport transport; protected bogusTransport( Transport _transport ) { transport = _transport; } public boolean isReadyForWrite( EventWaiter waiter ) { return( false ); } public long isReadyForRead( EventWaiter waiter ) { return( Long.MAX_VALUE ); } public boolean isTCP() { return( transport.isTCP()); } public String getDescription() { return( transport.getDescription()); } public int getMssSize() { return( transport.getMssSize()); } public void setAlreadyRead( ByteBuffer bytes_already_read ) { Debug.out( "Bogus Transport Operation" ); } public TransportEndpoint getTransportEndpoint() { return( transport.getTransportEndpoint()); } public boolean isEncrypted() { return( transport.isEncrypted()); } public String getEncryption( boolean verbose) { return( transport.getEncryption( verbose )); } public void setReadyForRead() { Debug.out( "Bogus Transport Operation" ); } public long write( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { Debug.out( "Bogus Transport Operation" ); throw( new IOException( "Bogus transport!" )); } public long read( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { Debug.out( "Bogus Transport Operation" ); throw( new IOException( "Bogus transport!" )); } public void setTransportMode( int mode ) { Debug.out( "Bogus Transport Operation" ); } public int getTransportMode() { return( transport.getTransportMode()); } public void connectOutbound( ByteBuffer initial_data, ConnectListener listener, int priority ) { Debug.out( "Bogus Transport Operation" ); listener.connectFailure( new Throwable( "Bogus Transport" )); } public void connectedInbound() { Debug.out( "Bogus Transport Operation" ); } public void close( String reason ) { // we get here after detaching a transport and then closing the peer connection } public void setTrace( boolean on ) { } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/IncomingConnectionManager.java0000644000175000017500000003442611036620504031410 0ustar adrianadrian/* * Created on 22 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.nio.ByteBuffer; import java.util.*; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.NetworkManager; import com.aelitis.azureus.core.networkmanager.Transport; public class IncomingConnectionManager { private static final LogIDs LOGID = LogIDs.NWMAN; private static IncomingConnectionManager singleton = new IncomingConnectionManager(); public static IncomingConnectionManager getSingleton() { return( singleton ); } private volatile Map match_buffers_cow = new HashMap(); // copy-on-write private final AEMonitor match_buffers_mon = new AEMonitor( "IncomingConnectionManager:match" ); private int max_match_buffer_size = 0; private int max_min_match_buffer_size = 0; private final ArrayList connections = new ArrayList(); private final AEMonitor connections_mon = new AEMonitor( "IncomingConnectionManager:conns" ); protected IncomingConnectionManager() { SimpleTimer.addPeriodicEvent( "IncomingConnectionManager:timeouts", 5000, new TimerEventPerformer() { public void perform( TimerEvent ev ) { doTimeoutChecks(); } } ); } public boolean isEmpty() { return( match_buffers_cow.isEmpty()); } // returns MatchListener,RoutingData if matched public Object[] checkForMatch( TransportHelper transport, int incoming_port, ByteBuffer to_check, boolean min_match ) { //remember original values for later restore int orig_position = to_check.position(); int orig_limit = to_check.limit(); //rewind to_check.position( 0 ); MatchListener listener = null; Object routing_data = null; for( Iterator i = match_buffers_cow.entrySet().iterator(); i.hasNext(); ) { Map.Entry entry = (Map.Entry)i.next(); NetworkManager.ByteMatcher bm = (NetworkManager.ByteMatcher)entry.getKey(); MatchListener this_listener = (MatchListener)entry.getValue(); int specific_port = bm.getSpecificPort(); if ( specific_port != -1 && specific_port != incoming_port ){ continue; } if ( min_match ){ if( orig_position < bm.minSize() ) { //not enough bytes yet to compare continue; } routing_data = bm.minMatches( transport, to_check, incoming_port ); if ( routing_data != null ){ listener = this_listener; break; } }else{ if( orig_position < bm.matchThisSizeOrBigger() ) { //not enough bytes yet to compare continue; } routing_data = bm.matches( transport, to_check, incoming_port ); if ( routing_data != null ){ listener = this_listener; break; } } } //restore original values in case the checks changed them to_check.position( orig_position ); to_check.limit( orig_limit ); if ( listener == null ){ return( null ); } return( new Object[]{ listener, routing_data }); } /** * Register the given byte sequence matcher to handle matching against new incoming connection * initial data; i.e. the first bytes read from a connection must match in order for the given * listener to be invoked. * @param matcher byte filter sequence * @param listener to call upon match */ public void registerMatchBytes( NetworkManager.ByteMatcher matcher, MatchListener listener ) { try { match_buffers_mon.enter(); if( matcher.maxSize() > max_match_buffer_size ) { max_match_buffer_size = matcher.maxSize(); } if ( matcher.minSize() > max_min_match_buffer_size ){ max_min_match_buffer_size = matcher.minSize(); } Map new_match_buffers = new HashMap( match_buffers_cow ); new_match_buffers.put( matcher, listener ); match_buffers_cow = new_match_buffers; addSharedSecrets( matcher.getSharedSecrets()); }finally { match_buffers_mon.exit(); } } /** * Remove the given byte sequence match from the registration list. * @param to_remove byte sequence originally used to register */ public void deregisterMatchBytes( NetworkManager.ByteMatcher to_remove ) { try { match_buffers_mon.enter(); Map new_match_buffers = new HashMap( match_buffers_cow ); new_match_buffers.remove( to_remove ); if( to_remove.maxSize() == max_match_buffer_size ) { //recalc longest buffer if necessary max_match_buffer_size = 0; for( Iterator i = new_match_buffers.keySet().iterator(); i.hasNext(); ) { NetworkManager.ByteMatcher bm = (NetworkManager.ByteMatcher)i.next(); if( bm.maxSize() > max_match_buffer_size ) { max_match_buffer_size = bm.maxSize(); } } } match_buffers_cow = new_match_buffers; removeSharedSecrets( to_remove.getSharedSecrets()); } finally { match_buffers_mon.exit(); } } public void addSharedSecrets( byte[][] secrets ) { if ( secrets != null ){ ProtocolDecoder.addSecrets( secrets ); } } public void removeSharedSecrets( byte[][] secrets ) { if ( secrets != null ){ ProtocolDecoder.removeSecrets( secrets ); } } public int getMaxMatchBufferSize() { return( max_match_buffer_size ); } public int getMaxMinMatchBufferSize() { return( max_min_match_buffer_size ); } public void addConnection( int local_port, TransportHelperFilter filter, Transport new_transport ) { TransportHelper transport_helper = filter.getHelper(); if ( isEmpty()) { //no match registrations, just close if ( Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Incoming connection from [" + transport_helper.getAddress() + "] dropped because zero routing handlers registered")); } transport_helper.close( "No routing handler" ); return; } // note that the filter may have some data internally queued in it after the crypto handshake decode // (in particular the BT header). However, there should be some data right behind it that will trigger // a read-select below, thus giving prompt access to the queued data final IncomingConnection ic = new IncomingConnection( filter, getMaxMatchBufferSize()); TransportHelper.selectListener sel_listener = new SelectorListener( local_port, new_transport ); try{ connections_mon.enter(); connections.add( ic ); transport_helper.registerForReadSelects( sel_listener, ic ); }finally{ connections_mon.exit(); } // might be stuff queued up in the filter - force one process cycle (NAT check in particular ) sel_listener.selectSuccess( transport_helper, ic ); } protected void removeConnection( IncomingConnection connection, boolean close_as_well ) { try{ connections_mon.enter(); connection.filter.getHelper().cancelReadSelects(); connections.remove( connection ); //remove from connection list }finally{ connections_mon.exit(); } if( close_as_well ) { connection.filter.getHelper().close( "Tidy close" ); } } protected void doTimeoutChecks() { try{ connections_mon.enter(); ArrayList to_close = null; long now = SystemTime.getCurrentTime(); for( int i=0; i < connections.size(); i++ ){ IncomingConnection ic = (IncomingConnection)connections.get( i ); TransportHelper transport_helper = ic.filter.getHelper(); if( ic.last_read_time > 0 ) { //at least one read op has occured if( now < ic.last_read_time ) { //time went backwards! ic.last_read_time = now; } else if( now - ic.last_read_time > transport_helper.getReadTimeout()) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Incoming connection [" + transport_helper.getAddress() + "] forcibly timed out due to socket read inactivity [" + ic.buffer.position() + " bytes read: " + new String(ic.buffer.array()) + "]")); if( to_close == null ) to_close = new ArrayList(); to_close.add( ic ); } } else { //no bytes have been read yet if( now < ic.initial_connect_time ) { //time went backwards! ic.initial_connect_time = now; } else if( now - ic.initial_connect_time > transport_helper.getConnectTimeout()) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Incoming connection [" + transport_helper.getAddress() + "] forcibly timed out after " + "60sec due to socket inactivity")); if( to_close == null ) to_close = new ArrayList(); to_close.add( ic ); } } } if( to_close != null ) { for( int i=0; i < to_close.size(); i++ ) { IncomingConnection ic = (IncomingConnection)to_close.get( i ); removeConnection( ic, true ); } } } finally { connections_mon.exit(); } } protected static class IncomingConnection { protected final TransportHelperFilter filter; protected final ByteBuffer buffer; protected long initial_connect_time; protected long last_read_time = -1; protected IncomingConnection( TransportHelperFilter filter, int buff_size ) { this.filter = filter; this.buffer = ByteBuffer.allocate( buff_size ); this.initial_connect_time = SystemTime.getCurrentTime(); } } protected class SelectorListener implements TransportHelper.selectListener { private int local_port; private Transport transport; protected SelectorListener( int _local_port, Transport _transport ) { local_port = _local_port; transport = _transport; } public boolean selectSuccess( TransportHelper transport_helper, Object attachment ) { IncomingConnection ic = (IncomingConnection)attachment; try { long bytes_read = ic.filter.read( new ByteBuffer[]{ ic.buffer }, 0, 1 ); if( bytes_read < 0 ) { throw new IOException( "end of stream on socket read" ); } if( bytes_read == 0 ) { return false; } ic.last_read_time = SystemTime.getCurrentTime(); Object[] match_data = checkForMatch( transport_helper, local_port, ic.buffer, false ); if( match_data == null ) { //no match found if( ic.buffer.position() >= getMaxMatchBufferSize()) { //we've already read in enough bytes to have compared against all potential match buffers ic.buffer.flip(); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Incoming stream from [" + transport_helper.getAddress() + "] does not match " + "any known byte pattern: " + ByteFormatter.nicePrint(ic.buffer.array(), 128))); removeConnection( ic, true ); } } else { //match found! ic.buffer.flip(); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Incoming stream from [" + transport_helper.getAddress() + "] recognized as " + "known byte pattern: " + ByteFormatter.nicePrint(ic.buffer.array(), 64))); removeConnection( ic, false ); transport.setAlreadyRead( ic.buffer ); transport.connectedInbound(); IncomingConnectionManager.MatchListener listener = (IncomingConnectionManager.MatchListener)match_data[0]; listener.connectionMatched( transport, match_data[1] ); } return( true ); } catch( Throwable t ) { try { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Incoming connection [" + transport_helper.getAddress() + "] socket read exception: " + t.getMessage())); } catch( Throwable x ) { Debug.out( "Caught exception on incoming exception log:" ); x.printStackTrace(); System.out.println( "CAUSED BY:" ); t.printStackTrace(); } removeConnection( ic, true ); return( false ); } } //FAILURE public void selectFailure( TransportHelper transport_helper, Object attachment, Throwable msg ) { IncomingConnection ic = (IncomingConnection)attachment; if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Incoming connection [" + transport_helper.getAddress() + "] socket select op failure: " + msg.getMessage())); } removeConnection( ic, true ); } } /** * Listener for byte matches. */ public interface MatchListener { /** * Currently if message crypto is on and default fallback for incoming not * enabled then we would bounce incoming messages from non-crypto transports * For example, NAT check * This method allows auto-fallback for such transports * @return */ public boolean autoCryptoFallback(); /** * The given socket has been accepted as matching the byte filter. * @param channel matching accepted connection * @param read_so_far bytes already read */ public void connectionMatched( Transport transport, Object routing_data ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterSwitcher.java0000644000175000017500000001420211001746712032335 0ustar adrianadrian/* * Created on 26-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.nio.ByteBuffer; public class TransportHelperFilterSwitcher implements TransportHelperFilter { private TransportHelperFilter current_reader; private TransportHelperFilter current_writer; private TransportHelperFilter first_filter; private TransportHelperFilter second_filter; private int read_rem; private int write_rem; private ByteBuffer read_insert; public TransportHelperFilterSwitcher( TransportHelperFilter _filter1, TransportHelperFilter _filter2, int _switch_read, int _switch_write ) { first_filter = _filter1; second_filter = _filter2; read_rem = _switch_read; write_rem = _switch_write; current_reader = read_rem<=0?second_filter:first_filter; current_writer = write_rem<=0?second_filter:first_filter; } public TransportHelperFilterSwitcher( TransportHelperFilter _filter1, TransportHelperFilter _filter2, ByteBuffer _read_insert ) { first_filter = _filter1; second_filter = _filter2; read_insert = _read_insert; current_reader = read_rem<=0?second_filter:first_filter; current_writer = write_rem<=0?second_filter:first_filter; } public long write( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { long total_written = 0; if ( current_writer != second_filter ){ int[] limits = new int[buffers.length]; int to_write = write_rem; for (int i=array_offset;i to_write ){ buffer.limit( buffer.position() + to_write ); to_write = 0; }else{ to_write -= rem; } } try{ total_written = current_writer.write( buffers, array_offset, length ); if ( total_written <= 0 ){ return( total_written ); } }finally{ for (int i=array_offset;i 0 ){ if ( space < read_insert.remaining()){ int old_limit = read_insert.limit(); read_insert.limit( read_insert.position() + space ); buffer.put( read_insert ); read_insert.limit( old_limit ); }else{ buffer.put( read_insert ); } if ( !read_insert.hasRemaining()){ break; } } } total_read = read_insert.position() - pos_before; if ( read_insert.hasRemaining()){ return( total_read ); }else{ read_insert = null; } } if ( current_reader != second_filter ){ int[] limits = new int[buffers.length]; int to_read = read_rem; for (int i=array_offset;i to_read ){ buffer.limit( buffer.position() + to_read ); to_read = 0; }else{ to_read -= rem; } } long read; try{ read = current_reader.read( buffers, array_offset, length ); if ( read <= 0 ){ return( total_read ); } total_read += read; }finally{ for (int i=array_offset;i= POLL_FREQUENCY ){ manager.poll(); last_poll = now; } if ( ready_sem.reserve(POLL_FREQUENCY/2)){ Object[] entry; synchronized( ready_set ){ if ( ready_set.size() == 0 ){ continue; } entry = (Object[])ready_set.remove(0); } TransportHelper transport = (TransportHelper)entry[0]; TransportHelper.selectListener listener = (TransportHelper.selectListener)entry[1]; if ( listener == null ){ Debug.out( "Null listener" ); }else{ Object attachment = entry[2]; try{ if ( entry.length == 3 ){ listener.selectSuccess( transport, attachment ); }else{ listener.selectFailure( transport, attachment, (Throwable)entry[3] ); } }catch( Throwable e ){ Debug.printStackTrace(e); } } } } } }.start(); } protected void destroy() { synchronized( ready_set ){ destroyed = true; } } protected void ready( TransportHelper transport, TransportHelper.selectListener listener, Object attachment ) { boolean removed = false; synchronized( ready_set ){ if( destroyed ){ Debug.out( "Selector has been destroyed" ); throw( new RuntimeException( "Selector has been destroyed" )); } Iterator it = ready_set.iterator(); while( it.hasNext()){ Object[] entry = (Object[])it.next(); if ( entry[1] == listener ){ it.remove(); removed = true; break; } } ready_set.add( new Object[]{ transport, listener, attachment }); } if ( !removed ){ ready_sem.release(); } } protected void ready( TransportHelper transport, TransportHelper.selectListener listener, Object attachment, Throwable error ) { boolean removed = false; synchronized( ready_set ){ if( destroyed ){ Debug.out( "Selector has been destroyed" ); throw( new RuntimeException( "Selector has been destroyed" )); } Iterator it = ready_set.iterator(); while( it.hasNext()){ Object[] entry = (Object[])it.next(); if ( entry[1] == listener ){ it.remove(); removed = true; break; } } ready_set.add( new Object[]{ transport, listener, attachment, error }); } if ( !removed ){ ready_sem.release(); } } protected void cancel( TransportHelper transport, TransportHelper.selectListener listener ) { synchronized( ready_set ){ Iterator it = ready_set.iterator(); while( it.hasNext()){ Object[] entry = (Object[])it.next(); if ( entry[0] == transport && entry[1] == listener ){ it.remove(); break; } } } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/udp/ProtocolEndpointUDP.java0000644000175000017500000000475710776600712031012 0ustar adrianadrian/* * Created on 21 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.udp; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import com.aelitis.azureus.core.networkmanager.ConnectionEndpoint; import com.aelitis.azureus.core.networkmanager.ProtocolEndpoint; import com.aelitis.azureus.core.networkmanager.Transport; import com.aelitis.azureus.core.networkmanager.Transport.ConnectListener; public class ProtocolEndpointUDP implements ProtocolEndpoint { private ConnectionEndpoint ce; private InetSocketAddress address; public ProtocolEndpointUDP( ConnectionEndpoint _ce, InetSocketAddress _address ) { ce = _ce; address = _address; ce.addProtocol( this ); } public ProtocolEndpointUDP( InetSocketAddress _address ) { ce = new ConnectionEndpoint(_address ); address = _address; ce.addProtocol( this ); } public void setConnectionEndpoint( ConnectionEndpoint _ce ) { ce = _ce; ce.addProtocol( this ); } public int getType() { return( PROTOCOL_UDP ); } public InetSocketAddress getAddress() { return( address ); } public ConnectionEndpoint getConnectionEndpoint() { return( ce ); } public Transport connectOutbound( boolean connect_with_crypto, boolean allow_fallback, byte[][] shared_secrets, ByteBuffer initial_data, int priority, ConnectListener listener ) { UDPTransport t = new UDPTransport( this, shared_secrets ); t.connectOutbound( initial_data, listener, priority ); return( t ); } public String getDescription() { return( address.toString()); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueUDP.java0000644000175000017500000001311710715201212027725 0ustar adrianadrian/* * Created on 22 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.udp; import java.util.*; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetSocketAddress; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.net.udp.uc.PRUDPPacketHandler; import com.aelitis.net.udp.uc.PRUDPPacketHandlerFactory; import com.aelitis.net.udp.uc.PRUDPPrimordialHandler; public class NetworkGlueUDP implements NetworkGlue, PRUDPPrimordialHandler { private static final LogIDs LOGID = LogIDs.NET; private NetworkGlueListener listener; private PRUDPPacketHandler handler; private LinkedList msg_queue = new LinkedList(); private AESemaphore msg_queue_sem = new AESemaphore( "NetworkGlueUDP" ); private AESemaphore msg_queue_slot_sem = new AESemaphore( "NetworkGlueUDP", 128 ); private long total_packets_received; private long total_bytes_received; private long total_packets_sent; private long total_bytes_sent; protected NetworkGlueUDP( NetworkGlueListener _listener ) { listener = _listener; COConfigurationManager.addAndFireParameterListeners( new String[]{ "UDP.Listen.Port", "UDP.Listen.Port.Enable" }, new ParameterListener() { public void parameterChanged( String name ) { boolean enabled = COConfigurationManager.getBooleanParameter( "UDP.Listen.Port.Enable" ); if ( enabled ){ int port = COConfigurationManager.getIntParameter( "UDP.Listen.Port" ); if ( handler == null || port != handler.getPort()){ if ( handler != null ){ Logger.log(new LogEvent(LOGID, "Deactivating UDP listener on port " + handler.getPort())); handler.setPrimordialHandler( null ); } Logger.log(new LogEvent(LOGID, "Activating UDP listener on port " + port )); handler = PRUDPPacketHandlerFactory.getHandler( port ); handler.setPrimordialHandler( NetworkGlueUDP.this ); } }else{ if ( handler != null ){ Logger.log(new LogEvent(LOGID, "Deactivating UDP listener on port " + handler.getPort())); handler.setPrimordialHandler( null ); } } } }); new AEThread( "NetworkGlueUDP", true ) { public void runSupport() { while( true ){ InetSocketAddress target_address = null; byte[] data = null; msg_queue_sem.reserve(); synchronized( msg_queue ){ Object[] entry = (Object[])msg_queue.removeFirst(); target_address = (InetSocketAddress)entry[0]; data = (byte[])entry[1]; } msg_queue_slot_sem.release(); total_packets_sent++; total_bytes_sent += data.length; try{ handler.primordialSend( data, target_address ); }catch( Throwable e ){ Logger.log(new LogEvent( LOGID, "Primordial UDP send failed: " + Debug.getNestedExceptionMessage(e))); }finally{ try{ Thread.sleep(3); }catch( Throwable e ){ } } } } }.start(); } public boolean packetReceived( DatagramPacket packet ) { if ( packet.getLength() >= 12 ){ byte[] data = packet.getData(); // first and third word must have something set in mask: 0xfffff800 if ( ( ( data[0] & 0xff ) != 0 || ( data[1] & 0xff ) != 0 || ( data[2] & 0xf8 ) != 0 ) && ( ( data[8] & 0xff ) != 0 || ( data[9] & 0xff ) != 0 || ( data[10]& 0xf8 ) != 0 )){ total_packets_received++; total_bytes_received += packet.getLength(); listener.receive( handler.getPort(), new InetSocketAddress( packet.getAddress(), packet.getPort()), packet.getData(), packet.getLength()); // consume this packet return( true ); } } // don't consume it, allow it to be passed on for further processing return( false ); } public int send( int local_port, InetSocketAddress target, byte[] data ) throws IOException { msg_queue_slot_sem.reserve(); synchronized( msg_queue ){ msg_queue.add( new Object[]{ target, data }); } msg_queue_sem.release(); return( data.length ); } public long[] getStats() { return( new long[]{ total_packets_sent, total_bytes_sent, total_packets_received, total_bytes_received }); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionSet.java0000644000175000017500000017202210454235520030244 0ustar adrianadrian/* * Created on 22 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.udp; import java.util.*; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.engines.RC4Engine; import org.bouncycastle.crypto.params.KeyParameter; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SHA1Hasher; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.net.udp.uc.PRUDPPacketReply; public class UDPConnectionSet { private static final LogIDs LOGID = LogIDs.NET; public static final int PROTOCOL_DATA_HEADER_SIZE = 30; private static final boolean DEBUG_SEQUENCES = false; static{ if ( DEBUG_SEQUENCES ){ System.out.println( "**** UDPConnectionSet: debug sequences is on ****" ); } } private static final byte[] KEYA_IV = "UDPDriverKeyA".getBytes(); private static final byte[] KEYB_IV = "UDPDriverKeyB".getBytes(); private static final byte[] KEYC_IV = "UDPDriverKeyC".getBytes(); private static final byte[] KEYD_IV = "UDPDriverKeyD".getBytes(); private static final int MIN_MSS = 256; private static final int MAX_HEADER = 128; public static final int MIN_WRITE_PAYLOAD = MIN_MSS - MAX_HEADER; private UDPConnectionManager manager; private UDPSelector selector; private int local_port; private InetSocketAddress remote_address; private boolean outgoing; private String connection_key; private Random random; private UDPConnection lead_connection; private RC4Engine header_cipher_out; private RC4Engine header_cipher_in; private SequenceGenerator in_seq_generator; private SequenceGenerator out_seq_generator; private volatile boolean crypto_done; private volatile boolean failed; private Map connections = new HashMap(); private LinkedList connection_writers = new LinkedList(); private long total_tick_count; private static final int STATS_LOG_TIMER = 60*1000; private static final int STATS_LOG_TICKS = Math.max( 1, STATS_LOG_TIMER / UDPConnectionManager.TIMER_TICK_MILLIS ); private int stats_log_ticks = STATS_LOG_TICKS; private static final int IDLE_TIMER = 10*1000; private static final int IDLE_TICKS = Math.max( 1, IDLE_TIMER / UDPConnectionManager.TIMER_TICK_MILLIS ); private int idle_ticks = 0; private static final int TIMER_BASE_DEFAULT = 300; private static final int TIMER_BASE_MIN = 100; private static final int TIMER_BASE_MAX = 15*1000; private int current_timer_base = TIMER_BASE_DEFAULT; private int old_timer_base = current_timer_base; private boolean timer_is_adjusting; // these stats_ values are reset periodically private int stats_packets_unique_sent; // unique packets sent private int stats_packets_resent_via_timer; // total resent due to resend timer expiry private int stats_packets_unique_received; // unique packets received (not resends) private int stats_packets_duplicates; // duplicates received private static final int STATS_RESET_TIMER = 30*1000; private long stats_reset_time = SystemTime.getCurrentTime(); // cumulative stats private int total_packets_sent = 0; private int total_data_sent = 0; private int total_data_resent = 0; private int total_protocol_sent = 0; private int total_protocol_resent = 0; private int total_packets_unique_sent = 0; private int total_packets_received = 0; private int total_packets_unique_received = 0; private int total_packets_duplicates = 0; private int total_packets_out_of_order = 0; private int total_packets_resent_via_timer = 0; private int total_packets_resent_via_ack = 0; // transmit private int retransmit_ticks = 0; private UDPPacket current_retransmit_target; private static final int RETRANSMIT_COUNT_LIMIT = 5; private static final int MIN_RETRANSMIT_TIMER = 100; private static final int MIN_RETRANSMIT_TICKS = Math.max( 1, MIN_RETRANSMIT_TIMER / UDPConnectionManager.TIMER_TICK_MILLIS ); private static final int MAX_RETRANSMIT_TIMER = 20*1000; private static final int MAX_RETRANSMIT_TICKS = Math.max( 1, MAX_RETRANSMIT_TIMER / UDPConnectionManager.TIMER_TICK_MILLIS ); private static final int MAX_TRANSMIT_UNACK_DATA_PACKETS = 10; private static final int MAX_TRANSMIT_UNACK_PACKETS = MAX_TRANSMIT_UNACK_DATA_PACKETS + 4; // + protocol packets private List transmit_unack_packets = new ArrayList(); private static final int MAX_CONTIGUOUS_RETRANS_FOR_ACK = 3; private static final int MIN_KEEPALIVE_TIMER = 10*1000; private static final int MIN_KEEPALIVE_TICKS = Math.max( 1, MIN_KEEPALIVE_TIMER / UDPConnectionManager.TIMER_TICK_MILLIS ); private static final int MAX_KEEPALIVE_TIMER = 20*1000; private static final int MAX_KEEPALIVE_TICKS = Math.max( 1, MAX_KEEPALIVE_TIMER / UDPConnectionManager.TIMER_TICK_MILLIS ); private int keep_alive_ticks; // receive private int receive_last_inorder_sequence = -1; private int receive_last_inorder_alt_sequence = -1; private int receive_their_last_inorder_sequence = -1; private static final int RECEIVE_UNACK_IN_SEQUENCE_LIMIT = 3; private long current_receive_unack_in_sequence_count = 0; private long sent_receive_unack_in_sequence_count = 0; private static final int RECEIVE_OUT_OF_ORDER_ACK_LIMIT = 3; private long current_receive_out_of_order_count = 0; private long sent_receive_out_of_order_count = 0; private static final int RECEIVE_DONE_SEQ_MAX = 128; private LinkedList receive_done_sequences = new LinkedList(); private static final int RECEIVE_OUT_OF_ORDER_PACKETS_MAX = 64; private List receive_out_of_order_packets = new LinkedList(); private int explicitack_ticks = 0; private static final int MAX_SEQ_MEMORY = Math.max( RECEIVE_OUT_OF_ORDER_PACKETS_MAX, MAX_TRANSMIT_UNACK_PACKETS ); protected UDPConnectionSet( UDPConnectionManager _manager, String _connection_key, UDPSelector _selector, int _local_port, InetSocketAddress _remote_address ) { manager = _manager; connection_key = _connection_key; selector = _selector; local_port = _local_port; remote_address = _remote_address; } protected UDPSelector getSelector() { return( selector ); } protected InetSocketAddress getRemoteAddress() { return( remote_address ); } protected String getKey() { return( connection_key ); } protected void add( UDPConnection connection ) throws IOException { UDPConnection old_connection = null; synchronized( connections ){ if ( failed ){ throw( new IOException( "Connection set has failed" )); } old_connection = (UDPConnection)connections.put( new Integer( connection.getID()), connection ); if ( connections.size() == 1 && lead_connection == null ){ lead_connection = connection; outgoing = true; } } if ( old_connection != null ){ Debug.out( "Duplicate connection" ); old_connection.close( "Duplication connection" ); } } protected boolean remove( UDPConnection connection ) { synchronized( connections ){ connections.remove( new Integer( connection.getID())); return( connections.size() == 0 ); } } protected void poll() { synchronized( connections ){ Iterator it = connections.values().iterator(); while( it.hasNext()){ ((UDPConnection)it.next()).poll(); } } } protected void setSecret( UDPConnection connection, byte[] session_secret ) { try{ if ( connection == lead_connection ){ if ( manager.trace() ){ trace( "crypto done" ); } SHA1Hasher hasher = new SHA1Hasher(); hasher.update( KEYA_IV ); hasher.update( session_secret ); byte[] a_key = hasher.getDigest(); hasher = new SHA1Hasher(); hasher.update( KEYB_IV ); hasher.update( session_secret ); byte[] b_key = hasher.getDigest(); hasher = new SHA1Hasher(); hasher.update( KEYC_IV ); hasher.update( session_secret ); byte[] c_key = hasher.getDigest(); hasher = new SHA1Hasher(); hasher.update( KEYD_IV ); hasher.update( session_secret ); byte[] d_key = hasher.getDigest(); // for RC4 enc/dec is irrelevant RC4Engine rc4_engine_a = getCipher( a_key ); RC4Engine rc4_engine_b = getCipher( b_key ); RC4Engine rc4_engine_c = getCipher( c_key ); RC4Engine rc4_engine_d = getCipher( d_key ); if ( lead_connection.isIncoming()){ header_cipher_out = rc4_engine_a; header_cipher_in = rc4_engine_b; out_seq_generator = new SequenceGenerator( new Random( bytesToLong( d_key )), rc4_engine_c, false ); in_seq_generator = new SequenceGenerator( new Random( bytesToLong( c_key )), rc4_engine_d, true ); random = new Random( bytesToLong( d_key, 8 )); }else{ header_cipher_out = rc4_engine_b; header_cipher_in = rc4_engine_a; in_seq_generator = new SequenceGenerator( new Random( bytesToLong( d_key )), rc4_engine_c, true ); out_seq_generator = new SequenceGenerator( new Random( bytesToLong( c_key )), rc4_engine_d, false ); random = new Random( bytesToLong( c_key, 8 )); } // as the first packet each way is crypto we skip a sequence number from each generator // to represent this and initialise the last-in-order seq appropriately so a sensible value is // spliced into the next packet out_seq_generator.getNextSequenceNumber(); int[] initial_in_seqs = in_seq_generator.getNextSequenceNumber(); receive_last_inorder_alt_sequence = initial_in_seqs[3]; crypto_done = true; }else if ( !crypto_done ){ Debug.out( "Secondary setSecret but crypto not done" ); } }catch( Throwable e ){ Debug.printStackTrace(e); connection.close( "Crypto problems: "+ Debug.getNestedExceptionMessage(e)); } } protected RC4Engine getCipher( byte[] key ) { SecretKeySpec secret_key_spec = new SecretKeySpec( key, "RC4" ); RC4Engine rc4_engine = new RC4Engine(); CipherParameters params_a = new KeyParameter( secret_key_spec.getEncoded()); // for RC4 enc/dec is irrelevant rc4_engine.init( true, params_a ); // skip first 1024 bytes of stream to protected against a Fluhrer, Mantin and Shamir attack byte[] temp = new byte[1024]; rc4_engine.processBytes( temp, 0, temp.length, temp, 0 ); return( rc4_engine ); } protected void sendTimerBase() { // only the outgoing side of a connection can initiate changes in timer base if ( !outgoing ){ return; } // the thing that kills a connection is too many retransmits so we need to keep these minimised during timer changes // when we increase our base timer we can immediately increase our retransmit timer but need to wait until they have // modified their timer before increasing the ack. Otherwise they won't be receiving acks as fast as they expect and therefore // trigger retransmits // when we decrease our base timer it is the opposite way around - we can immediately decrease acks but delay retrans synchronized( this ){ if ( timer_is_adjusting ){ return; } // only consider the stats if we've sent at least a few this interval if ( stats_packets_unique_sent > 2 ){ int new_timer_base = current_timer_base; if ( stats_packets_resent_via_timer > 0 ){ float resend_ratio = (float)stats_packets_resent_via_timer / stats_packets_unique_sent; // System.out.println( "resend ratio: " + resend_ratio ); if ( resend_ratio >= 0.25 ){ new_timer_base = (int)( current_timer_base * ( resend_ratio + 1 )); // round to 100th sec as we send 100ths over the wire and expect to get it back new_timer_base = (new_timer_base/10)*10; new_timer_base = Math.min( TIMER_BASE_MAX, new_timer_base ); if ( new_timer_base != current_timer_base ){ if ( manager.trace()){ trace( "Increasing timer base from " + current_timer_base + " to " + new_timer_base + " due to resends (ratio=" + resend_ratio + ")" ); } } } } if ( new_timer_base == current_timer_base && stats_packets_unique_received > 2 ){ float duplicate_ratio = (float)stats_packets_duplicates / stats_packets_unique_received; // we use duplicate packets sometimes to force sequence numbers through, so // reduce our sensitivity this them duplicate_ratio = duplicate_ratio/2; // System.out.println( "duplicate ratio: " + duplicate_ratio ); if ( duplicate_ratio >= 0.25 ){ new_timer_base = (int)( current_timer_base * ( duplicate_ratio + 1 )); new_timer_base = (new_timer_base/10)*10; new_timer_base = Math.min( TIMER_BASE_MAX, new_timer_base ); if ( new_timer_base != current_timer_base ){ if ( manager.trace() ){ trace( "Increasing timer base from " + current_timer_base + " to " + new_timer_base + " due to duplicates (ratio=" + duplicate_ratio + ")" ); } } } } if ( new_timer_base == current_timer_base && stats_packets_unique_received > 2 ){ // conservative approach - reduce by 10% if we've had no errors if ( stats_packets_resent_via_timer == 0 && stats_packets_duplicates == 0 ){ new_timer_base = current_timer_base - (current_timer_base/10); new_timer_base = (new_timer_base/10)*10; new_timer_base = Math.max( new_timer_base, TIMER_BASE_MIN ); if ( new_timer_base != current_timer_base ){ if ( manager.trace()){ trace( "Decreasing timer base from " + current_timer_base + " to " + new_timer_base ); } } } } boolean reset_stats = false; long now = SystemTime.getCurrentTime(); if ( new_timer_base == current_timer_base ){ if ( now < stats_reset_time || now - stats_reset_time > STATS_RESET_TIMER ){ reset_stats = true; } }else{ timer_is_adjusting = true; old_timer_base = current_timer_base; current_timer_base = new_timer_base; reset_stats = true; } if ( reset_stats ){ resetTimerStats(); } } } } protected void resetTimerStats() { stats_reset_time = SystemTime.getCurrentTime(); stats_packets_unique_sent = 0; stats_packets_resent_via_timer = 0; stats_packets_duplicates = 0; stats_packets_unique_received = 0; } protected void receiveTimerBase( int theirs ) { synchronized( this ){ if ( theirs != current_timer_base){ if ( manager.trace() ){ trace( "Received timer base: current=" + current_timer_base + ",theirs=" + theirs + "(adj=" + timer_is_adjusting + ")" ); } } if ( outgoing ){ if ( theirs == current_timer_base ){ if ( timer_is_adjusting ){ timer_is_adjusting = false; resetTimerStats(); } } }else{ // simply use the new value current_timer_base = theirs; } } } protected void timerTick() throws IOException { boolean retrans_expired = false; boolean ack_expired = false; boolean keep_alive_expired = false; synchronized( this ){ if ( connections.size() == 0 ){ idle_ticks++; }else{ idle_ticks = 0; } total_tick_count++; if ( retransmit_ticks > 0 ){ retransmit_ticks--; if ( retransmit_ticks == 0 ){ retrans_expired = true; } } if ( explicitack_ticks > 0 ){ explicitack_ticks--; if ( explicitack_ticks == 0 ){ ack_expired = true; } } if ( keep_alive_ticks > 0 ){ keep_alive_ticks--; if ( keep_alive_ticks == 0 ){ keep_alive_expired = true; } } stats_log_ticks--; if ( stats_log_ticks == 0 ){ logStats(); stats_log_ticks = STATS_LOG_TICKS; } } if ( retrans_expired ){ retransmitExpired(); } if ( ack_expired ){ sendAckCommand( true ); } if ( keep_alive_expired ){ sendStatsRequest(); } } protected int getRetransmitTicks() { int timer_to_use; synchronized( this ){ if ( timer_is_adjusting ){ if ( current_timer_base > old_timer_base ){ timer_to_use = current_timer_base; }else{ timer_to_use = old_timer_base; } }else{ timer_to_use = current_timer_base; } } // 5/3 of base int timer = ( timer_to_use * 5 ) / 3; return( Math.max( 1, timer / UDPConnectionManager.TIMER_TICK_MILLIS )); } protected int getExplicitAckTicks() { int timer_to_use; synchronized( this ){ if ( timer_is_adjusting ){ if ( current_timer_base > old_timer_base ){ timer_to_use = old_timer_base; }else{ timer_to_use = current_timer_base; } }else{ timer_to_use = current_timer_base; } } return( Math.max( 1, timer_to_use / UDPConnectionManager.TIMER_TICK_MILLIS )); } protected void startKeepAliveTimer() { keep_alive_ticks = MIN_KEEPALIVE_TICKS + random.nextInt( MAX_KEEPALIVE_TICKS - MIN_KEEPALIVE_TICKS ); } protected void stopKeepAliveTimer() { keep_alive_ticks = 0; } protected boolean idleLimitExceeded() { if ( idle_ticks > IDLE_TICKS + (int)(Math.random()*2000)){ synchronized( connections ){ if ( connections.size() == 0 ){ failed = true; return( true ); } } } return( false ); } protected UDPPacket getRetransmitPacket() { Iterator it = transmit_unack_packets.iterator(); while( it.hasNext()){ UDPPacket p = (UDPPacket)it.next(); if ( !p.hasBeenReceived()){ boolean auto_retrans = p.isAutoRetransmit(); // non-auto-retrans only applies to packets if they are the last packet sent if ( auto_retrans || it.hasNext()){ return( p ); } } } return( null ); } protected int getRetransmitTicks( int resend_count ) { int ticks = getRetransmitTicks(); int res; if ( resend_count == 0 ){ res = ticks; }else{ res = ticks + (( MAX_RETRANSMIT_TICKS - ticks ) * resend_count ) / ( RETRANSMIT_COUNT_LIMIT-1 ); } // System.out.println( "retry: " + res ); return( res ); } protected void retransmitExpired() throws IOException { UDPPacket packet_to_send = null; synchronized( this ){ packet_to_send = getRetransmitPacket(); if ( packet_to_send != null ){ stats_packets_resent_via_timer++; total_packets_resent_via_timer++; packet_to_send.resent(); } } if ( packet_to_send != null ){ if ( manager.trace() ){ trace( "Retransmit: " + packet_to_send.getString()); } send( packet_to_send ); } } protected boolean remoteLastInSequence( int alt_sequence ) { // if we find this packet then we can also discard any prior to it as they are implicitly // ack too synchronized( this ){ for (int i=0;i RETRANSMIT_COUNT_LIMIT ){ throw( new IOException( "Packet resend limit exceeded" )); } // all packets carry an implicit ack, pick up the corresponding count here long unackin = packet.getUnAckInSequenceCount(); if ( unackin > sent_receive_unack_in_sequence_count ){ sent_receive_unack_in_sequence_count = unackin; } // trigger the retransmit timer if any sent packets have the auto-retransmit property UDPPacket retransmit_target = getRetransmitPacket(); if ( retransmit_target == null ){ // no auto-retransmit packet, cancel timer retransmit_ticks = 0; }else if ( retransmit_target != current_retransmit_target || retransmit_target == packet){ // auto-retransmit packet has changed or we are currently retransmitting it, reset timer retransmit_ticks = getRetransmitTicks( resend_count ); }else{ // current retry target timer expired, restart it if ( retransmit_ticks == 0 ){ retransmit_ticks = getRetransmitTicks( resend_count ); } } current_retransmit_target = retransmit_target; // splice in the latest received in sequence alternative seq if non-crypto packet if ( packet.getAlternativeSequence() != -1 ){ byte[] alt = intToBytes( receive_last_inorder_alt_sequence ); payload[0] = alt[0]; payload[1] = alt[1]; payload[8] = alt[2]; payload[9] = alt[3]; } int send_count = packet.sent( total_tick_count ); if ( send_count == 1 ){ if ( packet.getCommand() == UDPPacket.COMMAND_DATA ){ total_data_sent++; }else{ total_protocol_sent++; } }else{ if ( packet.getCommand() == UDPPacket.COMMAND_DATA ){ total_data_resent++; }else{ total_protocol_resent++; } } } manager.send( local_port, remote_address, payload ); } public void receive( byte[] initial_data, int initial_data_length ) throws IOException { if ( failed ){ throw( new IOException( "Connection set has failed" )); } dumpState(); if ( manager.trace() ){ trace( "Read: total=" + initial_data_length ); } synchronized( this ){ total_packets_received++; } ByteBuffer initial_buffer = ByteBuffer.wrap( initial_data ); initial_buffer.limit( initial_data_length ); if ( !crypto_done ){ // first packet - connection setup and crypto handshake // derive the sequence number in the normal way so that if a retranmission occurs // after crypto has been setup then it'll get handled correctly as a dupliate packet // below initial_buffer.position( 4 ); Integer pseudo_seq = new Integer( initial_buffer.getInt()); initial_buffer.position( 0 ); if ( !receive_done_sequences.contains( pseudo_seq )){ receive_done_sequences.addFirst( pseudo_seq ); if ( receive_done_sequences.size() > RECEIVE_DONE_SEQ_MAX ){ receive_done_sequences.removeLast(); } } if ( outgoing ){ // a reply received by the initiator acknowledges that the initial message sent has // been received remoteLastInSequence( -1 ); } receiveCrypto( initial_buffer ); }else{ // pull out the alternative last-in-order seq byte[] alt_seq = new byte[4]; alt_seq[0] = initial_data[0]; alt_seq[1] = initial_data[1]; alt_seq[2] = initial_data[8]; alt_seq[3] = initial_data[9]; int alt = bytesToInt( alt_seq, 0 ); boolean write_select = remoteLastInSequence( alt ); boolean lazy_ack_found = false; try{ initial_buffer.getInt(); // seq1 Integer seq2 = new Integer( initial_buffer.getInt()); initial_buffer.getInt(); // seq3 // first see if we know about this sequence number already if ( receive_done_sequences.contains( seq2 )){ if ( manager.trace() ){ trace( "Duplicate processed packet: " + seq2 ); } // if we're gone quiescent and our lazy-ack packet failed to be delivered we end up here with the other end // resending their last message. We pick up this delivery failure and resend the packet UDPPacket packet_to_send = null; synchronized( this ){ stats_packets_duplicates++; total_packets_duplicates++; if ( transmit_unack_packets.size() == 1 ){ UDPPacket packet = (UDPPacket)transmit_unack_packets.get(0); if ( !packet.isAutoRetransmit()){ if ( total_tick_count - packet.getSendTickCount() >= MIN_RETRANSMIT_TICKS ){ if ( manager.trace() ){ trace( "Retrans non-auto-retrans packet" ); } packet_to_send = packet; } } } } if ( packet_to_send != null ){ send( packet_to_send ); } return; } if ( !out_seq_generator.isValidAlterativeSequence( alt )){ if ( manager.trace() ){ trace( "Received invalid alternative sequence " + alt + " - dropping packet" ); } return; } boolean oop = false; for (int i=0;i RECEIVE_DONE_SEQ_MAX ){ receive_done_sequences.removeLast(); } } header_cipher_in.processBytes( data, 12, 2, data, 12 ); int header_len = buffer.getShort()&0xffff; if ( header_len > data.length ){ if ( manager.trace() ){ trace( "Header length too large" ); } return; } header_cipher_in.processBytes( data, 14, header_len-14, data, 14 ); SHA1Hasher hasher = new SHA1Hasher(); hasher.update( data, 4, 4 ); hasher.update( data, 12, header_len - 4 - 12 ); byte[] hash = hasher.getDigest(); for (int i=0;i<4;i++){ if ( hash[i] != data[header_len-4+i] ){ if ( manager.trace() ){ trace( "hash incorrect" ); } return; } } byte version = buffer.get(); if ( version != UDPPacket.PROTOCOL_VERSION ){ // continue, assumption is that version changes are backward compatible // throw( new IOException( "Invalid protocol version '" + version + "'" )); } byte flags = buffer.get(); if ( ( flags & UDPPacket.FLAG_LAZY_ACK ) != 0 ){ lazy_ack_found = true; } int their_timer_base = (buffer.getShort()&0xffff)*10; receiveTimerBase( their_timer_base ); byte command = buffer.get(); if ( command == UDPPacket.COMMAND_DATA ){ receiveDataCommand( seq.intValue(), buffer, header_len ); }else if ( command == UDPPacket.COMMAND_ACK ){ receiveAckCommand( buffer ); }else if ( command == UDPPacket.COMMAND_CLOSE ){ receiveCloseCommand( buffer ); }else if ( command == UDPPacket.COMMAND_STAT_REQUEST ){ receiveStatsRequest( buffer ); }else if ( command == UDPPacket.COMMAND_STAT_REPLY ){ receiveStatsReply( buffer ); }else{ // ignore unrecognised commands to support future change } } if ( this_is_oop ){ synchronized( this ){ current_receive_out_of_order_count++; total_packets_out_of_order++; } } }finally{ boolean send_ack = false; synchronized( this ){ long unack_diff = current_receive_unack_in_sequence_count - sent_receive_unack_in_sequence_count; long oos_diff = current_receive_out_of_order_count - sent_receive_out_of_order_count; if ( unack_diff > RECEIVE_UNACK_IN_SEQUENCE_LIMIT || oos_diff > RECEIVE_OUT_OF_ORDER_ACK_LIMIT ){ send_ack = true; } } if ( send_ack ){ sendAckCommand( false ); } synchronized( this ){ // if we have either received in-order packets that we haven't sent an ack for or // out-of-order packets start the ack timer // only exception is if we have only a lazy-ack packet outstanding and no out-of-order long unack_diff = current_receive_unack_in_sequence_count - sent_receive_unack_in_sequence_count; if ( unack_diff == 1 && lazy_ack_found && receive_out_of_order_packets.size() == 0 ){ if ( manager.trace() ){ trace( "Not starting ack timer, only lazy ack received" ); } startKeepAliveTimer(); }else{ stopKeepAliveTimer(); if ( unack_diff > 0 || receive_out_of_order_packets.size() > 0 ){ if ( explicitack_ticks == 0 ){ explicitack_ticks = getExplicitAckTicks(); } } } } if ( write_select ){ synchronized( connection_writers ){ Iterator it = connection_writers.iterator(); while( it.hasNext()){ UDPConnection c = (UDPConnection)it.next(); if ( c.isConnected()){ // we can safely do this while holding monitor as this simply queues an async selector notification if required c.sent(); }else{ it.remove(); } } } } } } } protected int sendCrypto( ByteBuffer[] buffers, int offset, int length ) throws IOException { // regardless of mss we have to get the first phe handshake messages into a single packet int payload_to_send = 0; for (int i=offset;i current_receive_out_of_order_count ){ sent_receive_out_of_order_count = current_receive_out_of_order_count; } } int size = writeHeaderEnd( header, true ); byte[] packet_bytes = new byte[size]; System.arraycopy( header_bytes, 0, packet_bytes, 0, size ); packet_to_send = new UDPPacket( lead_connection, sequences, UDPPacket.COMMAND_ACK, packet_bytes, unack_in_sequence_count ); if ( no_retrans){ packet_to_send.setAutoRetransmit( false ); startKeepAliveTimer(); } transmit_unack_packets.add( packet_to_send ); if ( manager.trace() ){ trace( lead_connection, "sendAck: in_seq=" + receive_last_inorder_sequence + ",out_of_seq=" + oos_str ); } } } /* if ( timer_expired ){ System.out.println( getName() + ": ack timer"); } */ send( packet_to_send ); } protected void receiveAckCommand( ByteBuffer buffer ) throws IOException { List resend_list = new ArrayList(); String oos_str = ""; synchronized( this ){ Iterator it = transmit_unack_packets.iterator(); while( resend_list.size() < MAX_CONTIGUOUS_RETRANS_FOR_ACK ){ int out_of_order_seq = buffer.getInt(); if ( out_of_order_seq == -1 ){ break; }else{ if ( manager.trace() ){ oos_str += (oos_str.length()==0?"":",") + out_of_order_seq; } while( it.hasNext() && resend_list.size() < MAX_CONTIGUOUS_RETRANS_FOR_ACK ){ UDPPacket packet = (UDPPacket)it.next(); if ( packet.getSequence() == out_of_order_seq ){ // can't remove the packet here as its presence is required to allow an in-order // ack to correctly remove prior packets packet.setHasBeenReceived(); break; } if ( total_tick_count - packet.getSendTickCount() >= MIN_RETRANSMIT_TICKS ){ if ( !resend_list.contains( packet )){ resend_list.add( packet ); } } } } } total_packets_resent_via_ack += resend_list.size(); } if ( manager.trace() ){ trace( "receiveAck: in_seq=" + receive_their_last_inorder_sequence + ",out_of_seq=" + oos_str ); } for (int i=0;i= MIN_RETRANSMIT_TICKS ){ if ( manager.trace() ){ trace( packet.getConnection(), "retransStatsRequest:" + packet.getString()); } packet_to_send = packet; break; }else{ // sent too recently, bail out return; } } } if ( packet_to_send == null ){ byte[] header_bytes = new byte[256]; ByteBuffer header = ByteBuffer.wrap( header_bytes ); long unack_in_sequence_count = current_receive_unack_in_sequence_count; int[] sequences = writeHeaderStart( header, UDPPacket.COMMAND_STAT_REQUEST, UDPPacket.FLAG_NONE ); int size = writeHeaderEnd( header, true ); byte[] packet_bytes = new byte[size]; System.arraycopy( header_bytes, 0, packet_bytes, 0, size ); packet_to_send = new UDPPacket( lead_connection, sequences, UDPPacket.COMMAND_STAT_REQUEST, packet_bytes, unack_in_sequence_count ); transmit_unack_packets.add( packet_to_send ); if ( manager.trace() ){ trace( lead_connection, "sendStatsRequest" ); } } } send( packet_to_send ); } protected void receiveStatsRequest( ByteBuffer buffer ) throws IOException { UDPPacket packet_to_send = null; if ( manager.trace() ){ trace( "ReceiveStatsRequest" ); } synchronized( this ){ // if there's already an stats reply packet outstanding then we just resend that one Iterator it = transmit_unack_packets.iterator(); while( it.hasNext()){ UDPPacket packet = (UDPPacket)it.next(); if ( packet.getCommand() == UDPPacket.COMMAND_STAT_REPLY ){ if ( total_tick_count - packet.getSendTickCount() >= MIN_RETRANSMIT_TICKS ){ if ( manager.trace() ){ trace( packet.getConnection(), "retransStatsReply:" + packet.getString()); } packet_to_send = packet; break; }else{ // sent too recently, bail out return; } } } if ( packet_to_send == null ){ byte[] header_bytes = new byte[256]; ByteBuffer header = ByteBuffer.wrap( header_bytes ); long unack_in_sequence_count = current_receive_unack_in_sequence_count; boolean no_retrans = transmit_unack_packets.size() == 0 && receive_out_of_order_packets.size() == 0; int[] sequences = writeHeaderStart( header, UDPPacket.COMMAND_STAT_REPLY, no_retrans?UDPPacket.FLAG_LAZY_ACK:UDPPacket.FLAG_NONE ); int size = writeHeaderEnd( header, true ); byte[] packet_bytes = new byte[size]; System.arraycopy( header_bytes, 0, packet_bytes, 0, size ); packet_to_send = new UDPPacket( lead_connection, sequences, UDPPacket.COMMAND_STAT_REPLY, packet_bytes, unack_in_sequence_count ); if ( no_retrans ){ packet_to_send.setAutoRetransmit( false ); } transmit_unack_packets.add( packet_to_send ); if ( manager.trace() ){ trace( lead_connection, "sendStatsReply" ); } } } send( packet_to_send ); } protected void receiveStatsReply( ByteBuffer buffer ) throws IOException { if ( manager.trace() ){ trace( "receiveStatsReply" ); } } protected void sendCloseCommand( UDPConnection connection ) throws IOException { if ( crypto_done ){ UDPPacket packet_to_send; synchronized( this ){ byte[] header_bytes = new byte[256]; ByteBuffer header = ByteBuffer.wrap( header_bytes ); long unack_in_sequence_count = current_receive_unack_in_sequence_count; int[] sequences = writeHeaderStart( header, UDPPacket.COMMAND_CLOSE, UDPPacket.FLAG_NONE ); header.putInt( connection.getID()); int size = writeHeaderEnd( header, true ); byte[] packet_bytes = new byte[size]; System.arraycopy( header_bytes, 0, packet_bytes, 0, size ); if ( manager.trace() ){ trace( connection, "sendClose" ); } packet_to_send = new UDPPacket( lead_connection, sequences, UDPPacket.COMMAND_CLOSE, packet_bytes, unack_in_sequence_count ); transmit_unack_packets.add( packet_to_send ); } send( packet_to_send ); }else{ IOException failure = new IOException( "Connection failed during setup phase" ); failed( failure ); throw( failure ); } } protected void receiveCloseCommand( ByteBuffer buffer ) throws IOException { int connection_id = buffer.getInt(); UDPConnection connection = null; synchronized( connections ){ if ( failed ){ throw( new IOException( "Connection set has failed" )); } connection = (UDPConnection)connections.get( new Integer( connection_id )); } if ( manager.trace() ){ trace( "receiveClose: con=" + (connection==null?"":(""+connection.getID()))); } if ( connection != null ){ connection.close( "Remote has closed the connection" ); } } protected int[] writeHeaderStart( ByteBuffer buffer, byte command, byte flags ) throws IOException { // packet format // int[3] sequence numbers // short header length starting from version // byte version // byte flags // short timer base in 100ths second // byte command: data, close, re-request // // command specific data // data: int connection_id // close: int connection_id.... // ... // for non-data packets: random 0->7 bytes // int checksum // for data packets: payload // ***** Change this for DATA and you must change PROTOCOL_DATA_HEADER_SIZE **** sendTimerBase(); stats_packets_unique_sent++; total_packets_unique_sent++; int[] sequence_numbers = out_seq_generator.getNextSequenceNumber(); int seq = sequence_numbers[1]; buffer.putInt( sequence_numbers[0] ); buffer.putInt( seq ); buffer.putInt( sequence_numbers[2] ); // insert space for length added later buffer.putShort((short)0 ); buffer.put((byte)UDPPacket.PROTOCOL_VERSION); buffer.put( flags ); buffer.putShort((short)(current_timer_base/10)); buffer.put((byte)command); return( sequence_numbers ); } protected int writeHeaderEnd( ByteBuffer buffer, boolean randomise_size ) throws IOException { if ( randomise_size ){ int pad = random.nextInt( 8 ); for (int i=0;i MAX_HEADER ){ Debug.out( "MAX_HEADER exceeded!!!!" ); throw( new IOException( "MAX_HEADER exceeded" )); } return( total_length ); } protected int write( UDPConnection connection, ByteBuffer[] buffers, int offset, int length ) throws IOException { if ( !canWrite( connection )){ return( 0 ); } synchronized( connection_writers ){ int size = connection_writers.size(); if ( size == 0 ){ connection_writers.add( connection ); }else if ( connection_writers.size() == 1 && connection_writers.get(0) == connection ){ }else{ connection_writers.remove( connection ); connection_writers.addLast( connection ); } } if ( total_packets_sent == 0 ){ return( sendCrypto( buffers, offset, length )); }else{ return( sendDataCommand( connection, buffers, offset, length )); } } protected boolean canWrite( UDPConnection connection ) { if ( !crypto_done ){ if ( connection != lead_connection ){ return( false ); } if ( total_packets_sent > 0 ){ return( false ); } } boolean space = transmit_unack_packets.size() < MAX_TRANSMIT_UNACK_DATA_PACKETS; /* boolean old_log = LOG; LOG = !space; if ( manager.trace() != old_log ){ System.out.println( "Log: " + (LOG?"On":"Off")); } */ return( space ); } public void close( UDPConnection connection, String reason ) { if ( manager.trace() ){ trace( connection, "close: " + reason ); } boolean found; synchronized( connections ){ found = connections.containsValue( connection ); } if ( found ){ try{ sendCloseCommand( connection ); }catch( Throwable e ){ failed( e ); } } // final poll incase there are ignorant listeners connection.poll(); manager.remove( this, connection ); } public void failed( UDPConnection connection, Throwable reason ) { if ( manager.trace() ){ trace( connection, "Failed: " + Debug.getNestedExceptionMessage(reason)); } // run a final poll operation to inform any selector listeners of the failure connection.poll(); manager.remove( this, connection ); } protected void failed( Throwable e ) { List conns = null; synchronized( connections ){ if ( !failed ){ if ( manager.trace() ){ trace( "Connection set failed: " + Debug.getNestedExceptionMessage( e )); } failed = true; conns = new ArrayList( connections.values()); } } if ( conns != null ){ for (int i=0;i>24), (byte)(i>>16), (byte)(i>>8), (byte)i }; return( res ); } protected long bytesToLong( byte[] bytes ) { return( bytesToLong( bytes, 0 )); } protected long bytesToLong( byte[] bytes, int offset ) { long i1 = (bytes[offset++]<<24)&0xff000000L | (bytes[offset++]<<16)&0x00ff0000L | (bytes[offset++]<<8)&0x0000ff00L | bytes[offset++]&0x000000ffL; long i2 = (bytes[offset++]<<24)&0xff000000L | (bytes[offset++]<<16)&0x00ff0000L | (bytes[offset++]<<8)&0x0000ff00L | bytes[offset++]&0x000000ffL; long res = ( i1 << 32 ) | i2; return( res ); } protected String getName() { return( "loc="+local_port + " - " + remote_address ); } protected void logStats() { if ( Logger.isEnabled()){ synchronized( this ){ String str = "sent: tot=" + total_packets_sent + ",uni=" + total_packets_unique_sent + ",ds=" + total_data_sent + ",dr=" + total_data_resent + ",ps=" + total_protocol_sent + ",pr=" + total_protocol_resent + ",rt=" + total_packets_resent_via_timer + ",ra=" + total_packets_resent_via_ack; str += " recv: tot=" + total_packets_received + ",uni=" + total_packets_unique_received + ",du=" + total_packets_duplicates + ",oo=" + total_packets_out_of_order; str += " timer=" + current_timer_base + ",adj=" + timer_is_adjusting; Logger.log(new LogEvent(LOGID, "UDP " + getName() + " - " + str )); } } } protected void trace( String str ) { if ( manager.trace()){ manager.trace( "UDP " + getName() + ": " + str ); } } protected void trace( UDPConnection connection, String str ) { if ( manager.trace()){ manager.trace( "UDP " + getName() + " (" + connection.getID() + "): " + str ); } } protected class SequenceGenerator { private Random generator; private RC4Engine cipher; private boolean in; private final int[] seq_memory; private final int[] alt_seq_memory; private int seq_memory_pos; private int debug_seq_in_next = outgoing?0:1000000; private int debug_seq_out_next = outgoing?1000000:0; protected SequenceGenerator( Random _generator, RC4Engine _cipher, boolean _in ) { generator = _generator; cipher = _cipher; in = _in; seq_memory = new int[MAX_SEQ_MEMORY]; alt_seq_memory = new int[MAX_SEQ_MEMORY]; Arrays.fill( seq_memory, -1 ); Arrays.fill( alt_seq_memory, -1 ); } protected synchronized int[] getNextSequenceNumber() { // damn tracker udp protocol has: // request: long (random connection id) int (action) // reply: int (action) int (random txn id) // now action is always < 2048 so all other uses of udp packets will have either // 0x000007ff in either bytes 9 or 0 onwards. So we're forced to use 12 byte sequence numbers // internally we use the middle integer as the packet sequence // a secondary identifier for the sequence is also generated to be used in header position // 0-2 and 8-10 when reporting last sequences in the clear final int mask = 0xfffff800; while( true ){ int seq1; int seq2; int seq3; int seq4; if ( DEBUG_SEQUENCES ){ if ( in ){ seq1 = 0xffffffff; seq2 = debug_seq_in_next; seq3 = 0xffffffff; seq4 = debug_seq_in_next; debug_seq_in_next++; }else{ seq1 = 0xffffffff; seq2 = debug_seq_out_next; seq3 = 0xffffffff; seq4 = debug_seq_out_next; debug_seq_out_next++; } }else{ seq1 = generator.nextInt(); seq2 = generator.nextInt(); seq3 = generator.nextInt(); seq4 = generator.nextInt(); seq1 = cipherInt( cipher, seq1 ); seq2 = cipherInt( cipher, seq2 ); seq3 = cipherInt( cipher, seq3 ); seq4 = cipherInt( cipher, seq4 ); } if (( seq1 & mask ) != 0 && seq2 != -1 && ( seq3 & mask ) != 0){ if ( (seq4 & 0xffff0000) != 0 && (seq4 & 0x0000ffff) != 0 ){ boolean bad = false; for (int i=0;i 0 ){ Object[] entry = (Object[])message_queue.get(0); if (((Long)entry[0]).longValue() < now ){ message_queue.remove(0); source_address = (InetSocketAddress)entry[1]; target_address = (InetSocketAddress)entry[2]; data = (byte[])entry[3]; } } } if ( source_address != null ){ listener.receive( target_address.getPort(), source_address, data, data.length ); } } } }.start(); } public int send( int local_port, InetSocketAddress target, byte[] data ) throws IOException { Long expires = new Long( SystemTime.getCurrentTime() + latency ); InetSocketAddress local_address = new InetSocketAddress( target.getAddress(), local_port ); synchronized( message_queue ){ if ( random.nextInt(4) != 9 ){ message_queue.add( new Object[]{ expires, local_address, target, data }); } } return( data.length ); } public long[] getStats() { return( new long[]{ 0,0,0,0 }); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/udp/UDPNetworkManager.java0000644000175000017500000001344111066631520030414 0ustar adrianadrian/* * Created on 22 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.udp; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.RandomUtils; import com.aelitis.azureus.core.networkmanager.impl.ProtocolDecoderPHE; import com.aelitis.net.udp.uc.PRUDPPacket; public class UDPNetworkManager { public static final int PROTOCOL_HEADER_SIZE = UDPConnectionSet.PROTOCOL_DATA_HEADER_SIZE; public static final boolean MINIMISE_OVERHEADS = true; public static final int MIN_INCOMING_INITIAL_PACKET_SIZE = ProtocolDecoderPHE.MIN_INCOMING_INITIAL_PACKET_SIZE; public static final int MAX_INCOMING_INITIAL_PACKET_SIZE = ProtocolDecoderPHE.getMaxIncomingInitialPacketSize(MINIMISE_OVERHEADS); private static final int MIN_MSS = 128; private static final int MAX_MSS = PRUDPPacket.MAX_PACKET_SIZE; private static int udp_mss_size; public static boolean UDP_INCOMING_ENABLED; public static boolean UDP_OUTGOING_ENABLED; static{ COConfigurationManager.addAndFireParameterListener( "UDP.Listen.Port.Enable", new ParameterListener() { public void parameterChanged( String name ) { UDP_INCOMING_ENABLED = UDP_OUTGOING_ENABLED = COConfigurationManager.getBooleanParameter( name ); } }); } public static int getUdpMssSize() { return udp_mss_size; } public static void refreshRates( int min_rate ) { udp_mss_size = COConfigurationManager.getIntParameter( "network.udp.mtu.size" ) - PROTOCOL_HEADER_SIZE; if( udp_mss_size > min_rate ) udp_mss_size = min_rate - 1; if( udp_mss_size < MIN_MSS ) udp_mss_size = MIN_MSS; if ( udp_mss_size > MAX_MSS ) udp_mss_size = MAX_MSS; } private static UDPNetworkManager singleton; public static UDPNetworkManager getSingleton() { synchronized( UDPNetworkManager.class ){ if ( singleton == null ){ singleton = new UDPNetworkManager(); } } return( singleton ); } private int udp_listen_port = -1; private int udp_non_data_listen_port = -1; private UDPConnectionManager _connection_manager; protected UDPNetworkManager() { COConfigurationManager.addAndFireParameterListener( "UDP.Listen.Port", new ParameterListener() { public void parameterChanged(String name) { int port = COConfigurationManager.getIntParameter( name ); if ( port == udp_listen_port ){ return; } if ( port < 0 || port > 65535 || port == 6880 ) { String msg = "Invalid incoming UDP listen port configured, " +port+ ". The port has been reset. Please check your config!"; Debug.out( msg ); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, msg)); udp_listen_port = RandomUtils.generateRandomNetworkListenPort(); COConfigurationManager.setParameter( name, udp_listen_port ); }else{ udp_listen_port = port; } } }); COConfigurationManager.addAndFireParameterListener( "UDP.NonData.Listen.Port", new ParameterListener() { public void parameterChanged(String name) { int port = COConfigurationManager.getIntParameter( name ); if ( port == udp_non_data_listen_port ){ return; } if ( port < 0 || port > 65535 || port == 6880 ) { String msg = "Invalid incoming UDP non-data listen port configured, " +port+ ". The port has been reset. Please check your config!"; Debug.out( msg ); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, msg)); udp_non_data_listen_port = RandomUtils.generateRandomNetworkListenPort(); COConfigurationManager.setParameter( name, udp_non_data_listen_port ); }else{ udp_non_data_listen_port = port; } } }); } public boolean isUDPListenerEnabled() { return( UDP_INCOMING_ENABLED ); } public int getUDPListeningPortNumber() { return( udp_listen_port ); } public boolean isUDPNonDataListenerEnabled() { return( UDP_INCOMING_ENABLED ); } public int getUDPNonDataListeningPortNumber() { return( udp_non_data_listen_port ); } public UDPConnectionManager getConnectionManager() { synchronized( this ){ if ( _connection_manager == null ){ _connection_manager = new UDPConnectionManager(); } } return( _connection_manager ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlue.java0000644000175000017500000000234010457217666027377 0ustar adrianadrian/* * Created on 22 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.udp; import java.io.IOException; import java.net.InetSocketAddress; public interface NetworkGlue { public int send( int local_port, InetSocketAddress target, byte[] data ) throws IOException; public long[] getStats(); } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/udp/UDPTransportHelper.java0000644000175000017500000002605211014306704030622 0ustar adrianadrian/* * Created on 22 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.udp; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.networkmanager.impl.TransportHelper; public class UDPTransportHelper implements TransportHelper { public static final int READ_TIMEOUT = 30*1000; public static final int CONNECT_TIMEOUT = 60*1000; private UDPConnectionManager manager; private UDPSelector selector; private InetSocketAddress address; private UDPTransport transport; private boolean incoming; private UDPConnection connection; private selectListener read_listener; private Object read_attachment; private boolean read_selects_paused; private selectListener write_listener; private Object write_attachment; private boolean write_selects_paused = true; // default is paused private boolean closed; private IOException failed; private ByteBuffer pending_partial_write; private Map user_data; public UDPTransportHelper( UDPConnectionManager _manager, InetSocketAddress _address, UDPTransport _transport ) throws IOException { // outgoing manager = _manager; address = _address; transport = _transport; incoming = false; connection = manager.registerOutgoing( this ); selector = connection.getSelector(); } public UDPTransportHelper( UDPConnectionManager _manager, InetSocketAddress _address, UDPConnection _connection ) { // incoming manager = _manager; address = _address; connection = _connection; incoming = true; selector = connection.getSelector(); } protected void setTransport( UDPTransport _transport ) { transport = _transport; } protected UDPTransport getTransport() { return( transport ); } protected int getMss() { if ( transport == null ){ return( UDPNetworkManager.getUdpMssSize()); } return( transport.getMssSize()); } public boolean minimiseOverheads() { return( UDPNetworkManager.MINIMISE_OVERHEADS ); } public int getConnectTimeout() { return( CONNECT_TIMEOUT ); } public int getReadTimeout() { return( READ_TIMEOUT ); } public InetSocketAddress getAddress() { return( address ); } public String getName( boolean verbose ) { return( "UDP" ); } public boolean isIncoming() { return( incoming ); } protected UDPConnection getConnection() { return( connection ); } public boolean delayWrite( ByteBuffer buffer) { // TODO: support this one day? return false; } public boolean hasDelayedWrite() { return( false ); } public int write( ByteBuffer buffer, boolean partial_write ) throws IOException { synchronized( this ){ if ( failed != null ){ throw( failed ); } if ( closed ){ throw( new IOException( "Transport closed" )); } } if ( partial_write ){ if ( pending_partial_write == null ){ if ( buffer.remaining() < UDPConnectionSet.MIN_WRITE_PAYLOAD ){ ByteBuffer copy = ByteBuffer.allocate( buffer.remaining()); copy.put( buffer ); copy.position( 0 ); pending_partial_write = copy; return( copy.remaining()); } } } if ( pending_partial_write != null ){ try{ int pw_len = pending_partial_write.remaining(); int written = connection.write( new ByteBuffer[]{ pending_partial_write, buffer }, 0, 2 ); if ( written >= pw_len ){ return( written - pw_len ); }else{ return( 0 ); } }finally{ if ( pending_partial_write.remaining() == 0 ){ pending_partial_write = null; } } }else{ return( connection.write( new ByteBuffer[]{ buffer }, 0, 1 )); } } public long write( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { synchronized( this ){ if ( failed != null ){ throw( failed ); } if ( closed ){ throw( new IOException( "Transport closed" )); } } if ( pending_partial_write != null ){ ByteBuffer[] buffers2 = new ByteBuffer[length+1]; buffers2[0] = pending_partial_write; int pos = 1; for (int i=array_offset;i= pw_len ){ return( written - pw_len ); }else{ return( 0 ); } }finally{ if ( pending_partial_write.remaining() == 0 ){ pending_partial_write = null; } } }else{ return( connection.write( buffers, array_offset, length )); } } public int read( ByteBuffer buffer ) throws IOException { synchronized( this ){ if ( failed != null ){ throw( failed ); } if ( closed ){ throw( new IOException( "Transport closed" )); } } return( connection.read( buffer )); } public long read( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { synchronized( this ){ if ( failed != null ){ throw( failed ); } if ( closed ){ throw( new IOException( "Transport closed" )); } } long total = 0; for (int i=array_offset;i= max_outbound_connections ){ if ( !max_conn_exceeded_logged ){ max_conn_exceeded_logged = true; Debug.out( "UDPConnectionManager: max outbound connection limit reached (" + max_outbound_connections + ")" ); } } } try{ TransportCryptoManager.getSingleton().manageCrypto( helper, shared_secrets, false, initial_data, new TransportCryptoManager.HandshakeListener() { public void handshakeSuccess( ProtocolDecoder decoder, ByteBuffer remaining_initial_data ) { synchronized( UDPConnectionManager.this ){ if ( outbound_connection_count > 0 ){ outbound_connection_count--; } } TransportHelperFilter filter = decoder.getFilter(); try{ udp_transport.setFilter( filter ); if ( udp_transport.isClosed()){ udp_transport.close( "Already closed" ); listener.connectFailure( new Exception( "Connection already closed" )); }else{ if ( Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Outgoing UDP stream to " + address + " established, type = " + filter.getName(false))); } udp_transport.connectedOutbound(); listener.connectSuccess( udp_transport, remaining_initial_data ); } }catch( Throwable e ){ Debug.printStackTrace(e); udp_transport.close( Debug.getNestedExceptionMessageAndStack(e)); listener.connectFailure( e ); } } public void handshakeFailure( Throwable failure_msg ) { synchronized( UDPConnectionManager.this ){ if ( outbound_connection_count > 0 ){ outbound_connection_count--; } } f_helper.close( Debug.getNestedExceptionMessageAndStack(failure_msg)); listener.connectFailure( failure_msg ); } public void gotSecret( byte[] session_secret ) { f_helper.getConnection().setSecret( session_secret ); } public int getMaximumPlainHeaderLength() { throw( new RuntimeException()); // this is outgoing } public int matchPlainHeader( ByteBuffer buffer ) { throw( new RuntimeException()); // this is outgoing } }); }catch( Throwable e ){ synchronized( this ){ if ( outbound_connection_count > 0 ){ outbound_connection_count--; } } throw( e ); } }catch( Throwable e ){ Debug.printStackTrace(e); if ( helper != null ){ helper.close( Debug.getNestedExceptionMessage( e )); } listener.connectFailure( e ); } } public int getMaxOutboundPermitted() { return( Math.max( max_outbound_connections - outbound_connection_count, 0 )); } protected UDPSelector checkThreadCreation() { // called while holding the "connections" monitor if ( selector == null ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "UDPConnectionManager: activating" )); } selector = new UDPSelector(this ); protocol_timer = new ProtocolTimer(); } return( selector ); } protected void checkThreadDeath( boolean connections_running ) { // called while holding the "connections" monitor if ( connections_running ){ idle_start = 0; }else{ long now = SystemTime.getCurrentTime(); if ( idle_start == 0 ){ idle_start = now; }else if ( idle_start > now ){ idle_start = now; }else if ( now - idle_start > THREAD_LINGER_ON_IDLE_PERIOD ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "UDPConnectionManager: deactivating" )); } selector.destroy(); selector = null; protocol_timer.destroy(); protocol_timer = null; } } } protected void poll() { synchronized( connection_sets ){ Iterator it = connection_sets.values().iterator(); while( it.hasNext()){ ((UDPConnectionSet)it.next()).poll(); } } } public void remove( UDPConnectionSet set, UDPConnection connection ) { synchronized( connection_sets ){ if ( set.remove( connection )){ String key = set.getKey(); if ( set.hasFailed()){ if ( connection_sets.remove( key ) != null ){ set.removed(); recently_dead_keys.put( key, new Long( SystemTime.getCurrentTime())); if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Connection set " + key + " failed")); } } } } } } public void failed( UDPConnectionSet set ) { synchronized( connection_sets ){ String key = set.getKey(); if ( connection_sets.remove( key ) != null ){ set.removed(); recently_dead_keys.put( key, new Long( SystemTime.getCurrentTime())); if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Connection set " + key + " failed")); } } } } protected UDPConnection registerOutgoing( UDPTransportHelper helper ) throws IOException { int local_port = UDPNetworkManager.getSingleton().getUDPListeningPortNumber(); InetSocketAddress address = helper.getAddress(); String key = local_port + ":" + address.getAddress().getHostAddress() + ":" + address.getPort(); synchronized( connection_sets ){ UDPSelector current_selector = checkThreadCreation(); UDPConnectionSet connection_set = (UDPConnectionSet)connection_sets.get( key ); if ( connection_set == null ){ timeoutDeadKeys(); connection_set = new UDPConnectionSet( this, key, current_selector, local_port, address ); if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Created new set - " + connection_set.getName() + ", outgoing")); } connection_sets.put( key, connection_set ); } UDPConnection connection = new UDPConnection( connection_set, allocationConnectionID(), helper ); connection_set.add( connection ); return( connection ); } } public void receive( int local_port, InetSocketAddress remote_address, byte[] data, int data_length ) { String key = local_port + ":" + remote_address.getAddress().getHostAddress() + ":" + remote_address.getPort(); UDPConnectionSet connection_set; synchronized( connection_sets ){ UDPSelector current_selector = checkThreadCreation(); connection_set = (UDPConnectionSet)connection_sets.get( key ); if ( connection_set == null ){ timeoutDeadKeys(); // check that this at least looks like an initial crypto packet if ( data_length >= UDPNetworkManager.MIN_INCOMING_INITIAL_PACKET_SIZE && data_length <= UDPNetworkManager.MAX_INCOMING_INITIAL_PACKET_SIZE ){ if ( !rateLimitIncoming( remote_address )){ rate_limit_discard_packets++; rate_limit_discard_bytes += data_length; return; } connection_set = new UDPConnectionSet( this, key, current_selector, local_port, remote_address ); if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Created new set - " + connection_set.getName() + ", incoming")); } connection_sets.put( key, connection_set ); }else{ if ( recently_dead_keys.get( key ) == null ){ // we can get quite a lot of these if things get out of sync // Debug.out( "Incoming UDP packet mismatch for connection establishment: " + key ); } setup_discard_packets++; setup_discard_bytes += data_length; return; } } } try{ //System.out.println( "recv:" + ByteFormatter.encodeString( data, 0, data_length>64?64:data_length ) + (data_length>64?"...":"")); connection_set.receive( data, data_length ); }catch( IOException e ){ connection_set.failed( e ); }catch( Throwable e ){ Debug.printStackTrace( e ); connection_set.failed( e ); } } protected boolean rateLimitIncoming( InetSocketAddress s_address ) { long now = SystemTime.getCurrentTime(); byte[] address = s_address.getAddress().getAddress(); long delay; synchronized( this ){ int hit_count = incoming_bloom.add( address ); // allow up to 10% bloom filter utilisation if ( incoming_bloom.getSize() / incoming_bloom.getEntryCount() < 10 ){ incoming_bloom = BloomFilterFactory.createAddRemove4Bit(incoming_bloom.getSize() + BLOOM_INCREASE ); incoming_bloom_create_time = now; Logger.log( new LogEvent(LOGID, "UDP connnection bloom: size increased to " + incoming_bloom.getSize())); }else if ( now < incoming_bloom_create_time || now - incoming_bloom_create_time > BLOOM_RECREATE ){ incoming_bloom = BloomFilterFactory.createAddRemove4Bit(incoming_bloom.getSize()); incoming_bloom_create_time = now; } if ( hit_count >= 15 ){ Logger.log( new LogEvent(LOGID, "UDP incoming: too many recent connection attempts from " + s_address )); return( false ); } long since_last = now - last_incoming; delay = 100 - since_last; last_incoming = now; } // limit to 10 a second if ( delay > 0 && delay < 100 ){ try{ Thread.sleep( delay ); }catch( Throwable e ){ } } return( true ); } public int send( int local_port, InetSocketAddress remote_address, byte[] data ) throws IOException { return( network_glue.send( local_port, remote_address, data )); } protected void accept( final int local_port, final InetSocketAddress remote_address, final UDPConnection connection ) { final UDPTransportHelper helper = new UDPTransportHelper( this, remote_address, connection ); try{ connection.setTransport( helper ); TransportCryptoManager.getSingleton().manageCrypto( helper, null, true, null, new TransportCryptoManager.HandshakeListener() { public void handshakeSuccess( ProtocolDecoder decoder, ByteBuffer remaining_initial_data ) { TransportHelperFilter filter = decoder.getFilter(); ConnectionEndpoint co_ep = new ConnectionEndpoint( remote_address); ProtocolEndpointUDP pe_udp = new ProtocolEndpointUDP( co_ep, remote_address ); UDPTransport transport = new UDPTransport( pe_udp, filter ); helper.setTransport( transport ); incoming_manager.addConnection( local_port, filter, transport ); } public void handshakeFailure( Throwable failure_msg ) { if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "incoming crypto handshake failure: " + Debug.getNestedExceptionMessage( failure_msg ))); } connection.close( "handshake failure: " + Debug.getNestedExceptionMessage(failure_msg)); } public void gotSecret( byte[] session_secret ) { helper.getConnection().setSecret( session_secret ); } public int getMaximumPlainHeaderLength() { return( incoming_manager.getMaxMinMatchBufferSize()); } public int matchPlainHeader( ByteBuffer buffer ) { Object[] match_data = incoming_manager.checkForMatch( helper, local_port, buffer, true ); if ( match_data == null ){ return( TransportCryptoManager.HandshakeListener.MATCH_NONE ); }else{ // no fallback for UDP return( TransportCryptoManager.HandshakeListener.MATCH_CRYPTO_NO_AUTO_FALLBACK ); } } }); }catch( Throwable e ){ Debug.printStackTrace( e ); helper.close( Debug.getNestedExceptionMessage(e)); } } protected synchronized int allocationConnectionID() { int id = next_connection_id++; if ( id < 0 ){ id = 0; next_connection_id = 1; } return( id ); } protected void timeoutDeadKeys() { Iterator it = recently_dead_keys.values().iterator(); long now = SystemTime.getCurrentTime(); while( it.hasNext()){ long dead_time = ((Long)it.next()).longValue(); if ( dead_time > now || now - dead_time > DEAD_KEY_RETENTION_PERIOD ){ it.remove(); } } } protected class ProtocolTimer { private volatile boolean destroyed; protected ProtocolTimer() { new AEThread2( "UDPConnectionManager:timer", true ) { private int tick_count; public void run() { Thread.currentThread().setPriority( Thread.NORM_PRIORITY + 1 ); while( !destroyed ){ try{ Thread.sleep( TIMER_TICK_MILLIS ); }catch( Throwable e ){ } tick_count++; if ( tick_count % STATS_TICKS == 0 ){ logStats(); } List failed_sets = null; synchronized( connection_sets ){ int cs_size = connection_sets.size(); checkThreadDeath( cs_size > 0 ); if ( cs_size > 0 ){ Iterator it = connection_sets.values().iterator(); while( it.hasNext()){ UDPConnectionSet set = (UDPConnectionSet)it.next(); try{ set.timerTick(); if ( set.idleLimitExceeded()){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Idle limit exceeded for " + set.getName() + ", removing" )); } recently_dead_keys.put( set.getKey(), new Long( SystemTime.getCurrentTime())); it.remove(); set.removed(); } }catch( Throwable e ){ if ( failed_sets == null ){ failed_sets = new ArrayList(); } failed_sets.add( new Object[]{ set, e }); } } } } if ( failed_sets != null ){ for (int i=0;i 0 ); } } protected boolean canWrite() { return( set.canWrite( this )); } protected int write( ByteBuffer[] buffers, int offset, int length ) throws IOException { int written = set.write( this, buffers, offset, length ); // System.out.println( "Connection(" + getID() + ") - write -> " + written ); return( written ); } protected int read( ByteBuffer buffer ) throws IOException { int total = 0; synchronized( read_buffers ){ while( read_buffers.size() > 0 ){ int rem = buffer.remaining(); if ( rem == 0 ){ break; } ByteBuffer b = (ByteBuffer)read_buffers.get(0); int old_limit = b.limit(); if ( b.remaining() > rem ){ b.limit( b.position() + rem ); } buffer.put( b ); b.limit( old_limit ); total += rem - buffer.remaining(); if ( b.hasRemaining()){ break; }else{ read_buffers.remove(0); read_buffer_sem.release(); } } } // System.out.println( "Connection(" + getID() + ") - read -> " +total ); return( total ); } protected void close( String reason ) { if ( transport != null ){ transport.close( reason ); }else{ closeSupport( reason ); } } protected void failed( Throwable reason ) { if ( transport != null ){ transport.failed( reason ); }else{ failedSupport( reason ); } } protected void closeSupport( String reason ) { connected = false; read_buffer_sem.releaseForever(); set.close( this, reason ); } protected void failedSupport( Throwable reason ) { connected = false; read_buffer_sem.releaseForever(); set.failed( this, reason ); } protected boolean isConnected() { return( connected ); } protected void poll() { if ( transport != null ){ transport.poll(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/udp/UDPPacket.java0000644000175000017500000000662310452310522026675 0ustar adrianadrian/* * Created on 26 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.udp; public class UDPPacket { public static final byte PROTOCOL_VERSION = 1; public static final byte COMMAND_CRYPTO = 0; public static final byte COMMAND_DATA = 1; public static final byte COMMAND_ACK = 2; public static final byte COMMAND_CLOSE = 3; public static final byte COMMAND_STAT_REQUEST = 4; public static final byte COMMAND_STAT_REPLY = 5; public static final byte FLAG_NONE = 0x00; public static final byte FLAG_LAZY_ACK = 0x01; private final UDPConnection connection; private final int sequence; private final int alt_sequence; private final byte command; private final byte[] buffer; private final long unack_in_sequence_count; private boolean auto_retransmit = true; private short sent_count; private short resend_count; private boolean received; private long send_tick_count; protected UDPPacket( UDPConnection _connection, int[] _sequences, byte _command, byte[] _buffer, long _unack_in_sequence_count ) { connection = _connection; sequence = _sequences[1]; alt_sequence = _sequences[3]; command = _command; buffer = _buffer; unack_in_sequence_count = _unack_in_sequence_count; } protected UDPConnection getConnection() { return( connection ); } protected int getSequence() { return( sequence ); } protected int getAlternativeSequence() { return( alt_sequence ); } protected byte getCommand() { return( command ); } protected byte[] getBuffer() { return( buffer ); } protected long getUnAckInSequenceCount() { return( unack_in_sequence_count ); } protected boolean isAutoRetransmit() { return( auto_retransmit ); } protected void setAutoRetransmit( boolean b ) { auto_retransmit = b; } protected short sent( long tick_count ) { sent_count++; send_tick_count = tick_count; return( sent_count ); } protected short getResendCount() { return( resend_count ); } protected void resent() { resend_count++ ; } protected long getSendTickCount() { return( send_tick_count ); } protected void setHasBeenReceived() { received = true; } protected boolean hasBeenReceived() { return( received ); } protected int getSentCount() { return( sent_count ); } protected String getString() { return( "seq=" + sequence + ",type=" + command + ",retrans=" + auto_retransmit + ",sent=" + sent_count +",len=" + buffer.length ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStreamXOR.java0000644000175000017500000000461611001746712032401 0ustar adrianadrian/* * Created on 17-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.nio.ByteBuffer; public class TransportHelperFilterStreamXOR extends TransportHelperFilterStream { private byte[] mask; private int read_position; private int write_position; protected TransportHelperFilterStreamXOR( TransportHelper _transport, byte[] _mask ) { super( _transport ); mask = _mask; } protected void cryptoOut( ByteBuffer source_buffer, ByteBuffer target_buffer ) throws IOException { int rem = source_buffer.remaining(); for (int i=0;i 0 ){ proto_str = " (" + proto_str + ")"; } return( "XOR-" + mask.length*8 + proto_str ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/NetworkManagerUtilities.java0000644000175000017500000000314010373051016031136 0ustar adrianadrian/* * Created on Apr 19, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import com.aelitis.azureus.core.networkmanager.LimitedRateGroup; import com.aelitis.azureus.core.networkmanager.NetworkManager; /** * */ public class NetworkManagerUtilities { /** * Translate the group speed limit to a proper real rate. * @param group to use * @return rate real limit in bytes per second */ public static int getGroupRateLimit( LimitedRateGroup group ) { int limit = group.getRateLimitBytesPerSecond(); if( limit == 0 ) { //unlimited limit = NetworkManager.UNLIMITED_RATE; } else if( limit < 0 ) { //disabled limit = 0; } return limit; } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/RateHandler.java0000644000175000017500000000266310373051016026520 0ustar adrianadrian/* * Created on Oct 6, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; /** * Handler to allow external control of an entity's byte processing rate. */ public interface RateHandler { /** * Get the current number of bytes allowed to be processed by the entity. * @return number of bytes allowed */ public int getCurrentNumBytesAllowed(); /** * Notification of any bytes processed by the entity. * @param num_bytes_processed */ public void bytesProcessed( int num_bytes_processed ); } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/TransportHelper.java0000644000175000017500000000566311001746712027471 0ustar adrianadrian/* * Created on 21 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; public interface TransportHelper { public InetSocketAddress getAddress(); public String getName(boolean verbose); public boolean minimiseOverheads(); public int getConnectTimeout(); public int getReadTimeout(); public boolean delayWrite( ByteBuffer buffer ); public boolean hasDelayedWrite(); public int write( ByteBuffer buffer, boolean partial_write ) throws IOException; public long write( ByteBuffer[] buffers, int array_offset, int length ) throws IOException; public int read( ByteBuffer buffer ) throws IOException; public long read( ByteBuffer[] buffers, int array_offset, int length ) throws IOException; public void pauseReadSelects(); public void pauseWriteSelects(); public void resumeReadSelects(); public void resumeWriteSelects(); public void registerForReadSelects( selectListener listener, Object attachment ); public void registerForWriteSelects( selectListener listener, Object attachment ); public void cancelReadSelects(); public void cancelWriteSelects(); public void close( String reason ); public void failed( Throwable reason ); public interface selectListener { public boolean selectSuccess( TransportHelper helper, Object attachment ); public void selectFailure( TransportHelper helper, Object attachment, Throwable msg); } public void setUserData( Object key, Object data ); public Object getUserData( Object key ); public void setTrace( boolean on ); public void setScatteringMode(long forBytes); } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/ReadController.java0000644000175000017500000002630511115177256027257 0ustar adrianadrian/* * Created on Oct 16, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.util.ArrayList; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.EventWaiter; import com.aelitis.azureus.core.stats.AzureusCoreStats; import com.aelitis.azureus.core.stats.AzureusCoreStatsProvider; /** * Processes reads of read-entities and handles the read selector. */ public class ReadController implements AzureusCoreStatsProvider{ private static int IDLE_SLEEP_TIME = 50; private static boolean AGGRESIVE_READ = false; static{ COConfigurationManager.addAndFireParameterListeners( new String[]{ "network.control.read.idle.time", "network.control.read.aggressive", }, new ParameterListener() { public void parameterChanged( String name ) { IDLE_SLEEP_TIME = COConfigurationManager.getIntParameter( "network.control.read.idle.time" ); AGGRESIVE_READ = COConfigurationManager.getBooleanParameter( "network.control.read.aggressive" ); } }); } private volatile ArrayList normal_priority_entities = new ArrayList(); //copied-on-write private volatile ArrayList high_priority_entities = new ArrayList(); //copied-on-write private final AEMonitor entities_mon = new AEMonitor( "ReadController:EM" ); private int next_normal_position = 0; private int next_high_position = 0; private long loop_count; private long wait_count; private long non_progress_count; private long progress_count; private long entity_check_count; private long last_entity_check_count; private EventWaiter read_waiter = new EventWaiter(); private int entity_count; public ReadController() { //start read handler processing Thread read_processor_thread = new AEThread( "ReadController:ReadProcessor" ) { public void runSupport() { readProcessorLoop(); } }; read_processor_thread.setDaemon( true ); read_processor_thread.setPriority( Thread.MAX_PRIORITY - 1 ); read_processor_thread.start(); Set types = new HashSet(); types.add( AzureusCoreStats.ST_NET_READ_CONTROL_LOOP_COUNT ); types.add( AzureusCoreStats.ST_NET_READ_CONTROL_NP_COUNT ); types.add( AzureusCoreStats.ST_NET_READ_CONTROL_P_COUNT ); types.add( AzureusCoreStats.ST_NET_READ_CONTROL_WAIT_COUNT ); types.add( AzureusCoreStats.ST_NET_READ_CONTROL_ENTITY_COUNT ); types.add( AzureusCoreStats.ST_NET_READ_CONTROL_CON_COUNT ); types.add( AzureusCoreStats.ST_NET_READ_CONTROL_READY_CON_COUNT ); AzureusCoreStats.registerProvider( types, this ); AEDiagnostics.addEvidenceGenerator( new AEDiagnosticsEvidenceGenerator() { public void generate( IndentWriter writer ) { writer.println( "Read Controller" ); try{ writer.indent(); ArrayList ref = normal_priority_entities; writer.println( "normal - " + ref.size()); for (int i=0;i= normal_priority_entities.size() + high_priority_entities.size() ){ last_entity_check_count = entity_check_count; // force a wait if ( read_waiter.waitForEvent( IDLE_SLEEP_TIME )){ wait_count++; } return( false); } return( true ); } }else{ return( ready_entity.doProcessing( read_waiter )); } } return false; } private RateControlledEntity getNextReadyNormalPriorityEntity() { ArrayList ref = normal_priority_entities; int size = ref.size(); int num_checked = 0; while( num_checked < size ) { entity_check_count++; next_normal_position = next_normal_position >= size ? 0 : next_normal_position; //make circular RateControlledEntity entity = (RateControlledEntity)ref.get( next_normal_position ); next_normal_position++; num_checked++; if( entity.canProcess( read_waiter ) ) { //is ready return entity; } } return null; //none found ready } private RateControlledEntity getNextReadyHighPriorityEntity() { ArrayList ref = high_priority_entities; int size = ref.size(); int num_checked = 0; while( num_checked < size ) { entity_check_count++; next_high_position = next_high_position >= size ? 0 : next_high_position; //make circular RateControlledEntity entity = (RateControlledEntity)ref.get( next_high_position ); next_high_position++; num_checked++; if( entity.canProcess( read_waiter ) ) { //is ready return entity; } } return null; //none found ready } /** * Add the given entity to the controller for read processing. * @param entity to process reads for */ public void addReadEntity( RateControlledEntity entity ) { try { entities_mon.enter(); if( entity.getPriority() == RateControlledEntity.PRIORITY_HIGH ) { //copy-on-write ArrayList high_new = new ArrayList( high_priority_entities.size() + 1 ); high_new.addAll( high_priority_entities ); high_new.add( entity ); high_priority_entities = high_new; } else { //copy-on-write ArrayList norm_new = new ArrayList( normal_priority_entities.size() + 1 ); norm_new.addAll( normal_priority_entities ); norm_new.add( entity ); normal_priority_entities = norm_new; } entity_count = normal_priority_entities.size() + high_priority_entities.size(); } finally { entities_mon.exit(); } } /** * Remove the given entity from the controller. * @param entity to remove from read processing */ public void removeReadEntity( RateControlledEntity entity ) { try { entities_mon.enter(); if( entity.getPriority() == RateControlledEntity.PRIORITY_HIGH ) { //copy-on-write ArrayList high_new = new ArrayList( high_priority_entities ); high_new.remove( entity ); high_priority_entities = high_new; } else { //copy-on-write ArrayList norm_new = new ArrayList( normal_priority_entities ); norm_new.remove( entity ); normal_priority_entities = norm_new; } entity_count = normal_priority_entities.size() + high_priority_entities.size(); } finally { entities_mon.exit(); } } public int getEntityCount() { return( entity_count ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/ByteBucketST.java0000644000175000017500000001121511274534270026641 0ustar adrianadrian/* * Created on Dec 1, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.networkmanager.impl; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.networkmanager.NetworkManager; public class ByteBucketST implements ByteBucket { private int rate; private int burst_rate; private long avail_bytes; private long prev_update_time; /** * Create a new byte-bucket with the given byte fill (guaranteed) rate. * Burst rate is set to default 1.2X of given fill rate. * @param rate_bytes_per_sec fill rate */ public ByteBucketST( int rate_bytes_per_sec ) { this( rate_bytes_per_sec, rate_bytes_per_sec + (rate_bytes_per_sec/5) ); } /** * Create a new byte-bucket with the given byte fill (guaranteed) rate * and the given burst rate. * @param rate_bytes_per_sec fill rate * @param burst_rate max rate */ private ByteBucketST( int rate_bytes_per_sec, int burst_rate ) { this.rate = rate_bytes_per_sec; this.burst_rate = burst_rate; avail_bytes = 0; //start bucket empty prev_update_time = SystemTime.getSteppedMonotonousTime(); ensureByteBucketMinBurstRate(); } /** * Get the number of bytes currently available for use. * @return number of free bytes */ public int getAvailableByteCount() { if ( avail_bytes < NetworkManager.UNLIMITED_RATE ){ update_avail_byte_count(); } return (int)avail_bytes; } /** * Update the bucket with the number of bytes just used. * @param bytes_used */ public void setBytesUsed( int bytes_used ) { if ( avail_bytes >= NetworkManager.UNLIMITED_RATE ){ return; } avail_bytes -= bytes_used; if( avail_bytes < 0 ) Debug.out( "avail_bytes < 0: " + avail_bytes); } /** * Get the configured fill rate. * @return guaranteed rate in bytes per sec */ public int getRate() { return rate; } /** * Get the configured burst rate. * @return burst rate in bytes per sec */ public int getBurstRate() { return burst_rate; } /** * Set the current fill/guaranteed rate, with a burst rate of 1.2X the given rate. * @param rate_bytes_per_sec */ public void setRate( int rate_bytes_per_sec ) { setRate( rate_bytes_per_sec, rate_bytes_per_sec + (rate_bytes_per_sec/5)); } /** * Set the current fill/guaranteed rate, along with the burst rate. * @param rate_bytes_per_sec * @param burst_rate */ public void setRate( int rate_bytes_per_sec, int burst_rate ) { if( rate_bytes_per_sec < 0 ) { Debug.out("rate_bytes_per_sec [" +rate_bytes_per_sec+ "] < 0"); rate_bytes_per_sec = 0; } if( burst_rate < rate_bytes_per_sec ) { Debug.out("burst_rate [" +burst_rate+ "] < rate_bytes_per_sec [" +rate_bytes_per_sec+ "]"); burst_rate = rate_bytes_per_sec; } this.rate = rate_bytes_per_sec; this.burst_rate = burst_rate; if ( avail_bytes > burst_rate ){ avail_bytes = burst_rate; } ensureByteBucketMinBurstRate(); } private void update_avail_byte_count() { final long now =SystemTime.getSteppedMonotonousTime(); if (prev_update_time burst_rate ) avail_bytes = burst_rate; else if( avail_bytes < 0 ) Debug.out("ERROR: avail_bytes < 0: " + avail_bytes); } } /** * Make sure the bucket's burst rate is at least MSS-sized, * otherwise it will never allow a full packet's worth of data. */ private void ensureByteBucketMinBurstRate() { int mss = NetworkManager.getMinMssSize(); if( burst_rate < mss ) { //oops, this won't ever allow a full packet burst_rate = mss; //so increase the max byte size } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/ByteBucket.java0000644000175000017500000000255311115226770026374 0ustar adrianadrian/* * Created on Jul 26, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; /** * Byte-bucket implementation based on the token bucket algorithm. * Buckets can be configured with a guaranteed normal rate, along with * a burst rate. */ public interface ByteBucket { public int getRate(); public void setRate( int rate_bytes_per_sec ); public int getAvailableByteCount(); public void setBytesUsed( int bytes_used ); } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStreamCipher.java0000644000175000017500000000410111013656316033133 0ustar adrianadrian/* * Created on 17-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.nio.ByteBuffer; public class TransportHelperFilterStreamCipher extends TransportHelperFilterStream { private TransportCipher read_cipher; private TransportCipher write_cipher; public TransportHelperFilterStreamCipher( TransportHelper _transport, TransportCipher _read_cipher, TransportCipher _write_cipher ) { super( _transport ); read_cipher = _read_cipher; write_cipher = _write_cipher; } protected void cryptoOut( ByteBuffer source_buffer, ByteBuffer target_buffer ) throws IOException { write_cipher.update( source_buffer, target_buffer ); } protected void cryptoIn( ByteBuffer source_buffer, ByteBuffer target_buffer ) throws IOException { read_cipher.update( source_buffer, target_buffer ); } public boolean isEncrypted() { return( true ); } public String getName(boolean verbose) { String proto_str = getHelper().getName(verbose); if ( proto_str.length() > 0 ){ proto_str = " (" + proto_str + ")"; } return( read_cipher.getName() + proto_str ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilter.java0000644000175000017500000000304711001746712030631 0ustar adrianadrian/* * Created on 17-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.nio.ByteBuffer; public interface TransportHelperFilter { public long write( ByteBuffer[] buffers, int array_offset, int length ) throws IOException; public long read( ByteBuffer[] buffers, int array_offset, int length ) throws IOException; public boolean hasBufferedWrite(); public boolean hasBufferedRead(); public TransportHelper getHelper(); public String getName(boolean verbose); public boolean isEncrypted(); public void setTrace( boolean on ); } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/MultiPeerDownloader2.java0000644000175000017500000002550711035306026030340 0ustar adrianadrian/* * Created on Apr 22, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.util.*; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.networkmanager.*; /** * */ public class MultiPeerDownloader2 implements RateControlledEntity { private static final int MOVE_TO_IDLE_TIME = 500; private static final Object ADD_ACTION = new Object(); private static final Object REMOVE_ACTION = new Object(); private volatile ArrayList connections_cow = new ArrayList(); //copied-on-write private final AEMonitor connections_mon = new AEMonitor( "MultiPeerDownloader" ); private final RateHandler main_handler; private List pending_actions; private connectionList active_connections = new connectionList(); private connectionList idle_connections = new connectionList(); private long last_idle_check; /** * Create new downloader using the given "global" rate handler to limit all peers managed by this downloader. * @param main_handler */ public MultiPeerDownloader2( RateHandler _main_handler ) { main_handler = _main_handler; } /** * Add the given connection to the downloader. * @param connection to add */ public void addPeerConnection( NetworkConnectionBase connection ) { try{ connections_mon.enter(); //copy-on-write ArrayList conn_new = new ArrayList( connections_cow.size() + 1 ); conn_new.addAll( connections_cow ); conn_new.add( connection ); connections_cow = conn_new; if ( pending_actions == null ){ pending_actions = new ArrayList(); } pending_actions.add( new Object[]{ ADD_ACTION, connection }); }finally{ connections_mon.exit(); } } /** * Remove the given connection from the downloader. * @param connection to remove * @return true if the connection was found and removed, false if not removed */ public boolean removePeerConnection( NetworkConnectionBase connection ) { try{ connections_mon.enter(); //copy-on-write ArrayList conn_new = new ArrayList( connections_cow ); boolean removed = conn_new.remove( connection ); if( !removed ) return false; connections_cow = conn_new; if ( pending_actions == null ){ pending_actions = new ArrayList(); } pending_actions.add( new Object[]{ REMOVE_ACTION, connection }); return true; }finally{ connections_mon.exit(); } } public boolean canProcess( EventWaiter waiter ) { if( main_handler.getCurrentNumBytesAllowed() < 1/*NetworkManager.getTcpMssSize()*/ ) return false; return true; } public long getBytesReadyToWrite() { return( 0 ); } public int getConnectionCount() { return(connections_cow.size()); } public int getReadyConnectionCount( EventWaiter waiter ) { int res = 0; for (Iterator it=connections_cow.iterator();it.hasNext();){ NetworkConnectionBase connection = (NetworkConnectionBase)it.next(); if ( connection.getTransportBase().isReadyForRead( waiter ) == 0 ){ res++; } } return( res ); } public boolean doProcessing( EventWaiter waiter ) { // Note - this is single threaded // System.out.println( "MPD: do process - " + connections_cow.size() + "/" + active_connections.size() + "/" + idle_connections.size()); int num_bytes_allowed = main_handler.getCurrentNumBytesAllowed(); if ( num_bytes_allowed < 1 ){ return false; } if ( pending_actions != null ){ try{ connections_mon.enter(); for (int i=0;i MOVE_TO_IDLE_TIME ){ last_idle_check = now; // move any active ones off of the idle queue connectionEntry entry = idle_connections.head(); while( entry != null ){ NetworkConnectionBase connection = entry.connection; connectionEntry next = entry.next; if ( connection.getTransportBase().isReadyForRead( waiter ) == 0 ){ // System.out.println( " moving to active " + connection.getString()); idle_connections.remove( entry ); active_connections.addToStart( entry ); } entry = next; } } // process the active set int num_bytes_remaining = num_bytes_allowed; connectionEntry entry = active_connections.head(); int num_entries = active_connections.size(); for (int i=0; i 0;i++ ){ NetworkConnectionBase connection = entry.connection; connectionEntry next = entry.next; long ready = connection.getTransportBase().isReadyForRead( waiter ); // System.out.println( " " + connection.getString() + " - " + ready ); if ( ready == 0 ){ int mss = connection.getMssSize(); int allowed = num_bytes_remaining > mss ? mss : num_bytes_remaining; int bytes_read = 0; try{ bytes_read = connection.getIncomingMessageQueue().receiveFromTransport( allowed ); }catch( Throwable e ) { if( AEDiagnostics.TRACE_CONNECTION_DROPS ) { if( e.getMessage() == null ) { Debug.out( "null read exception message: ", e ); } else { if( e.getMessage().indexOf( "end of stream on socket read" ) == -1 && e.getMessage().indexOf( "An existing connection was forcibly closed by the remote host" ) == -1 && e.getMessage().indexOf( "Connection reset by peer" ) == -1 && e.getMessage().indexOf( "An established connection was aborted by the software in your host machine" ) == -1 ) { System.out.println( "MP: read exception [" +connection.getTransportBase().getDescription()+ "]: " +e.getMessage() ); } } } if (! (e instanceof IOException )){ Debug.printStackTrace(e); } connection.notifyOfException( e ); } num_bytes_remaining -= bytes_read; // System.out.println( " moving to end " + connection.getString()); active_connections.moveToEnd( entry ); }else if ( ready > MOVE_TO_IDLE_TIME ){ // System.out.println( " moving to idle " + connection.getString()); active_connections.remove( entry ); idle_connections.addToEnd( entry ); } entry = next; } int total_bytes_read = num_bytes_allowed - num_bytes_remaining; if( total_bytes_read > 0 ){ main_handler.bytesProcessed( total_bytes_read ); return true; } return false; //zero bytes read } public int getPriority() { return RateControlledEntity.PRIORITY_HIGH; } public String getString() { StringBuffer str = new StringBuffer(); str.append( "MPD (" + connections_cow.size() + "/" + active_connections.size() + "/" + idle_connections.size() + ": " ); int num = 0; for (Iterator it=connections_cow.iterator();it.hasNext();){ NetworkConnectionBase connection = (NetworkConnectionBase)it.next(); if ( num++ > 0 ){ str.append( "," ); } str.append( connection.getString()); } return( str.toString()); } protected static class connectionList { private int size; private connectionEntry head; private connectionEntry tail; protected connectionEntry add( NetworkConnectionBase connection ) { connectionEntry entry = new connectionEntry( connection ); if ( head == null ){ head = tail = entry; }else{ tail.next = entry; entry.prev = tail; tail = entry; } size++; return( entry ); } protected void addToEnd( connectionEntry entry ) { entry.next = null; entry.prev = tail; if ( tail == null ){ head = tail = entry; }else{ tail.next = entry; tail = entry; } size++; } protected void addToStart( connectionEntry entry ) { entry.next = head; entry.prev = null; if ( head == null ){ head = tail = entry; }else{ head.prev = entry; head = entry; } size++; } protected void moveToEnd( connectionEntry entry ) { if ( entry != tail ){ connectionEntry prev = entry.prev; connectionEntry next = entry.next; if ( prev == null ){ head = next; }else{ prev.next = next; } next.prev = prev; entry.prev = tail; entry.next = null; tail.next = entry; tail = entry; } } protected connectionEntry remove( NetworkConnectionBase connection ) { connectionEntry entry = head; while( entry != null ){ if ( entry.connection == connection ){ remove( entry ); return( entry ); }else{ entry = entry.next; } } return( null ); } protected void remove( connectionEntry entry ) { connectionEntry prev = entry.prev; connectionEntry next = entry.next; if ( prev == null ){ head = next; }else{ prev.next = next; } if ( next == null ){ tail = prev; }else{ next.prev = prev; } size--; } protected int size() { return( size ); } protected connectionEntry head() { return( head ); } } protected static class connectionEntry { private connectionEntry next; private connectionEntry prev; private NetworkConnectionBase connection; protected connectionEntry( NetworkConnectionBase _connection ) { connection = _connection; } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoder.java0000644000175000017500000000614511004266444027422 0ustar adrianadrian/* * Created on 18-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.util.*; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; public abstract class ProtocolDecoder { private static final LogIDs LOGID = LogIDs.NWMAN; private static final int TIMEOUT_CHECK = 5000; private static final int LOG_TICKS = 60000 / TIMEOUT_CHECK; private static List decoders = new ArrayList(); private static AEMonitor class_mon = new AEMonitor( "TCPProtocolDecoder:class" ); private static int loop = 0; static{ SimpleTimer.addPeriodicEvent( "ProtocolDecoder:timeouts", 5000, new TimerEventPerformer() { public void perform( TimerEvent ev ) { loop++; long now = SystemTime.getCurrentTime(); try{ class_mon.enter(); if ( loop % LOG_TICKS == 0 ){ if (Logger.isEnabled()){ if ( decoders.size() > 0 ){ Logger.log( new LogEvent(LOGID, "Active protocol decoders = " + decoders.size())); } } } // isComplete can synchronously modify 'decoders' so we // can't continue looping after a removal, rather we have // to restart boolean retry = true; while( retry ){ retry = false; for (int i=0;i " + group_data ); } */ } group_data.group_size++; group_datas[i] = group_data; /* if ( log ){ System.out.println( "Applying RL1: " + group.getName() + " -> " + connection ); } */ } conn_data.groups = groups; conn_data.group_datas = group_datas; conn_data.state = ConnectionData.STATE_NORMAL; connections.put( connection, conn_data ); } finally { connections_mon.exit(); } main_controller.registerPeerConnection( connection ); } public boolean isRegistered( NetworkConnectionBase connection ){ try{ connections_mon.enter(); return( connections.containsKey( connection )); } finally{ connections_mon.exit(); } } /** * Cancel upload handling for the given peer connection. * @param connection to cancel */ public void deregisterPeerConnection( NetworkConnectionBase connection ) { try{ connections_mon.enter(); ConnectionData conn_data = (ConnectionData)connections.remove( connection ); if( conn_data != null ) { GroupData[] group_datas = conn_data.group_datas; //do groups de-registration for (int i=0;i " + group_data ); } */ group_buckets.put( group, group_data ); } /* if ( log ){ System.out.println( "Applying RL2: " + group.getName() + " -> " + connection ); } */ group_data.group_size++; GroupData[] group_datas = conn_data.group_datas; int len = groups.length; LimitedRateGroup[] new_groups = new LimitedRateGroup[ len + 1 ]; System.arraycopy( groups, 0, new_groups, 0, len ); new_groups[len] = group; conn_data.groups = new_groups; GroupData[] new_group_datas = new GroupData[ len + 1 ]; System.arraycopy( group_datas, 0, new_group_datas, 0, len ); new_group_datas[len] = group_data; conn_data.group_datas = new_group_datas; } }finally{ connections_mon.exit(); } } public void removeRateLimiter( NetworkConnectionBase connection, LimitedRateGroup group ) { try{ connections_mon.enter(); ConnectionData conn_data = (ConnectionData)connections.get( connection ); if ( conn_data != null ){ LimitedRateGroup[] groups = conn_data.groups; GroupData[] group_datas = conn_data.group_datas; int len = groups.length; if ( len == 0 ){ return; } LimitedRateGroup[] new_groups = new LimitedRateGroup[ len - 1 ]; GroupData[] new_group_datas = new GroupData[ len - 1 ]; int pos = 0; for (int i=0;i 500 ){ last_log = now; System.out.println( " " + group.getName() + " -> " + group_rate + "/" + group_bucket.getAvailableByteCount()); } } */ if ( group_bucket.getRate() != group_rate ){ group_bucket.setRate( group_rate ); } int group_allowed = group_bucket.getAvailableByteCount(); if ( group_allowed < allowed ){ allowed = group_allowed; } } }catch( Throwable e ){ // conn_data.group stuff is not synchronized for speed but can cause borkage if new // limiters added so trap here if (!( e instanceof IndexOutOfBoundsException )){ Debug.printStackTrace(e); } } } return allowed; } public void bytesProcessed( int num_bytes_written ) { if ( RATE_LIMIT_LAN_TOO || !( connection.isLANLocal() && NetworkManager.isLANRateEnabled())){ for (int i=0;i= NetworkManager.UNLIMITED_RATE ){ return; } avail_bytes -= bytes_used; //if( avail_bytes < 0 ) Debug.out( "avail_bytes < 0: " + avail_bytes); } /** * Get the configured fill rate. * @return guaranteed rate in bytes per sec */ public int getRate() { return rate; } /** * Get the configured burst rate. * @return burst rate in bytes per sec */ public int getBurstRate() { return burst_rate; } /** * Set the current fill/guaranteed rate, with a burst rate of 1.2X the given rate. * @param rate_bytes_per_sec */ public void setRate( int rate_bytes_per_sec ) { setRate( rate_bytes_per_sec, rate_bytes_per_sec + (rate_bytes_per_sec/5)); } /** * Set the current fill/guaranteed rate, along with the burst rate. * @param rate_bytes_per_sec * @param burst_rate */ public void setRate( int rate_bytes_per_sec, int burst_rate ) { if( rate_bytes_per_sec < 0 ) { Debug.out("rate_bytes_per_sec [" +rate_bytes_per_sec+ "] < 0"); rate_bytes_per_sec = 0; } if( burst_rate < rate_bytes_per_sec ) { Debug.out("burst_rate [" +burst_rate+ "] < rate_bytes_per_sec [" +rate_bytes_per_sec+ "]"); burst_rate = rate_bytes_per_sec; } this.rate = rate_bytes_per_sec; this.burst_rate = burst_rate; if ( avail_bytes > burst_rate ){ avail_bytes = burst_rate; } ensureByteBucketMinBurstRate(); } private void update_avail_byte_count() { synchronized( this ){ final long now =SystemTime.getMonotonousTime(); if (prev_update_time burst_rate ) avail_bytes = burst_rate; else if( avail_bytes < 0 ){ //Debug.out("ERROR: avail_bytes < 0: " + avail_bytes); } } } } /** * Make sure the bucket's burst rate is at least MSS-sized, * otherwise it will never allow a full packet's worth of data. */ private void ensureByteBucketMinBurstRate() { int mss = NetworkManager.getMinMssSize(); if( burst_rate < mss ) { //oops, this won't ever allow a full packet burst_rate = mss; //so increase the max byte size } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/WriteController.java0000644000175000017500000002675211115177256027504 0ustar adrianadrian/* * Created on Sep 27, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.EventWaiter; import com.aelitis.azureus.core.stats.AzureusCoreStats; import com.aelitis.azureus.core.stats.AzureusCoreStatsProvider; /** * Processes writes of write-entities and handles the write selector. */ public class WriteController implements AzureusCoreStatsProvider{ private static int IDLE_SLEEP_TIME = 50; private static boolean AGGRESIVE_WRITE = false; static{ COConfigurationManager.addAndFireParameterListeners( new String[]{ "network.control.write.idle.time", "network.control.write.aggressive", }, new ParameterListener() { public void parameterChanged( String name ) { IDLE_SLEEP_TIME = COConfigurationManager.getIntParameter( "network.control.write.idle.time" ); AGGRESIVE_WRITE = COConfigurationManager.getBooleanParameter( "network.control.write.aggressive" ); } }); } private volatile ArrayList normal_priority_entities = new ArrayList(); //copied-on-write private volatile ArrayList high_priority_entities = new ArrayList(); //copied-on-write private final AEMonitor entities_mon = new AEMonitor( "WriteController:EM" ); private int next_normal_position = 0; private int next_high_position = 0; private int aggressive_np_normal_priority_count; private int aggressive_np_high_priority_count; private long wait_count; private long progress_count; private long non_progress_count; private EventWaiter write_waiter = new EventWaiter(); private int entity_count = 0; /** * Create a new write controller. */ public WriteController() { //start write handler processing Thread write_processor_thread = new AEThread( "WriteController:WriteProcessor" ) { public void runSupport() { writeProcessorLoop(); } }; write_processor_thread.setDaemon( true ); write_processor_thread.setPriority( Thread.MAX_PRIORITY - 1 ); write_processor_thread.start(); Set types = new HashSet(); types.add( AzureusCoreStats.ST_NET_WRITE_CONTROL_WAIT_COUNT ); types.add( AzureusCoreStats.ST_NET_WRITE_CONTROL_NP_COUNT ); types.add( AzureusCoreStats.ST_NET_WRITE_CONTROL_P_COUNT ); types.add( AzureusCoreStats.ST_NET_WRITE_CONTROL_ENTITY_COUNT ); types.add( AzureusCoreStats.ST_NET_WRITE_CONTROL_CON_COUNT ); types.add( AzureusCoreStats.ST_NET_WRITE_CONTROL_READY_CON_COUNT ); types.add( AzureusCoreStats.ST_NET_WRITE_CONTROL_READY_BYTE_COUNT ); AzureusCoreStats.registerProvider( types, this ); AEDiagnostics.addEvidenceGenerator( new AEDiagnosticsEvidenceGenerator() { public void generate( IndentWriter writer ) { writer.println( "Write Controller" ); try{ writer.indent(); ArrayList ref = normal_priority_entities; writer.println( "normal - " + ref.size()); for (int i=0;i= size ? 0 : next_normal_position; //make circular RateControlledEntity entity = (RateControlledEntity)ref.get( next_normal_position ); next_normal_position++; num_checked++; if( entity.canProcess( write_waiter ) ) { //is ready return entity; } } return null; //none found ready } private RateControlledEntity getNextReadyHighPriorityEntity() { ArrayList ref = high_priority_entities; int size = ref.size(); int num_checked = 0; while( num_checked < size ) { next_high_position = next_high_position >= size ? 0 : next_high_position; //make circular RateControlledEntity entity = (RateControlledEntity)ref.get( next_high_position ); next_high_position++; num_checked++; if( entity.canProcess( write_waiter ) ) { //is ready return entity; } } return null; //none found ready } /** * Add the given entity to the controller for write processing. * @param entity to process writes for */ public void addWriteEntity( RateControlledEntity entity ) { try { entities_mon.enter(); if( entity.getPriority() == RateControlledEntity.PRIORITY_HIGH ) { //copy-on-write ArrayList high_new = new ArrayList( high_priority_entities.size() + 1 ); high_new.addAll( high_priority_entities ); high_new.add( entity ); high_priority_entities = high_new; } else { //copy-on-write ArrayList norm_new = new ArrayList( normal_priority_entities.size() + 1 ); norm_new.addAll( normal_priority_entities ); norm_new.add( entity ); normal_priority_entities = norm_new; } entity_count = normal_priority_entities.size() + high_priority_entities.size(); } finally { entities_mon.exit(); } } /** * Remove the given entity from the controller. * @param entity to remove from write processing */ public void removeWriteEntity( RateControlledEntity entity ) { try { entities_mon.enter(); if( entity.getPriority() == RateControlledEntity.PRIORITY_HIGH ) { //copy-on-write ArrayList high_new = new ArrayList( high_priority_entities ); high_new.remove( entity ); high_priority_entities = high_new; } else { //copy-on-write ArrayList norm_new = new ArrayList( normal_priority_entities ); norm_new.remove( entity ); normal_priority_entities = norm_new; } entity_count = normal_priority_entities.size() + high_priority_entities.size(); } finally { entities_mon.exit(); } } public int getEntityCount() { return( entity_count ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterTransparent.java0000644000175000017500000000720011001746712033046 0ustar adrianadrian/* * Created on 17-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.nio.ByteBuffer; public class TransportHelperFilterTransparent implements TransportHelperFilter { private TransportHelper transport; private boolean is_plain; private ByteBuffer read_insert; public TransportHelperFilterTransparent( TransportHelper _transport, boolean _is_plain ) { transport = _transport; is_plain = _is_plain; } protected void insertRead( ByteBuffer _read_insert ) { read_insert = _read_insert; } public boolean hasBufferedWrite() { return( transport.hasDelayedWrite()); } public boolean hasBufferedRead() { return( read_insert != null && read_insert.remaining() > 0 ); } public long write( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { return( transport.write( buffers, array_offset, length )); } public int write( ByteBuffer buffer, boolean partial_write ) throws IOException { return( transport.write( buffer, partial_write )); } public long read( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { int len = 0; if ( read_insert != null ){ int pos_before = read_insert.position(); for (int i=array_offset;i 0 ){ if ( space < read_insert.remaining()){ int old_limit = read_insert.limit(); read_insert.limit( read_insert.position() + space ); buffer.put( read_insert ); read_insert.limit( old_limit ); }else{ buffer.put( read_insert ); } if ( !read_insert.hasRemaining()){ break; } } } len = read_insert.position() - pos_before; if ( read_insert.hasRemaining()){ return( len ); }else{ read_insert = null; } } return( len + transport.read( buffers, array_offset, length )); } public int read( ByteBuffer buffer ) throws IOException { if ( read_insert != null ){ return((int)read( new ByteBuffer[]{ buffer }, 0, 1 )); } return( transport.read( buffer )); } public TransportHelper getHelper() { return( transport ); } public void setTrace( boolean on ) { transport.setTrace( on ); } public boolean isEncrypted() { return( false ); } public String getName(boolean verbose) { String proto_str = getHelper().getName(verbose); if ( proto_str.length() > 0 ){ proto_str = " (" + proto_str + ")"; } return((is_plain?"Plain":"None") + proto_str ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/TransportImpl.java0000644000175000017500000002401611167455604027156 0ustar adrianadrian/* * Created on 22 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.nio.ByteBuffer; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimeFormatter; import com.aelitis.azureus.core.networkmanager.EventWaiter; import com.aelitis.azureus.core.networkmanager.Transport; public abstract class TransportImpl implements Transport { private TransportHelperFilter filter; private static final TransportStats stats = AEDiagnostics.TRACE_TCP_TRANSPORT_STATS ? new TransportStats() : null; private ByteBuffer data_already_read = null; private volatile EventWaiter read_waiter; private volatile EventWaiter write_waiter; private volatile boolean is_ready_for_write = false; private volatile boolean is_ready_for_read = false; private Throwable write_select_failure = null; private Throwable read_select_failure = null; private long last_ready_for_read = SystemTime.getSteppedMonotonousTime(); private boolean trace; protected TransportImpl() { } public void setFilter( TransportHelperFilter _filter ) { filter = _filter; if ( trace && _filter != null ){ _filter.setTrace( true ); } } public TransportHelperFilter getFilter() { return( filter ); } public void setAlreadyRead( ByteBuffer bytes_already_read ) { if ( bytes_already_read != null && bytes_already_read.hasRemaining()){ if ( data_already_read != null ) { ByteBuffer new_bb = ByteBuffer.allocate(data_already_read.remaining() + bytes_already_read.remaining()); new_bb.put(bytes_already_read); new_bb.put(data_already_read); new_bb.position(0); data_already_read = new_bb; } else { data_already_read = bytes_already_read; } is_ready_for_read = true; } } public String getEncryption(boolean verbose) { return( filter==null?"":filter.getName(verbose)); } public boolean isEncrypted() { return( filter==null?false:filter.isEncrypted()); } /** * Is the transport ready to write, * i.e. will a write request result in >0 bytes written. * @return true if the transport is write ready, false if not yet ready */ public boolean isReadyForWrite( EventWaiter waiter ) { if ( waiter != null ){ write_waiter = waiter; } return is_ready_for_write; } protected boolean readyForWrite( boolean ready ) { if ( trace ){ TimeFormatter.milliTrace( "trans: readyForWrite -> " + ready ); } if ( ready ){ boolean progress = !is_ready_for_write; is_ready_for_write = true; EventWaiter ww = write_waiter; if ( ww != null ){ ww.eventOccurred(); } return progress; }else{ is_ready_for_write = false; return( false ); } } protected void writeFailed( Throwable msg ) { msg.fillInStackTrace(); write_select_failure = msg; is_ready_for_write = true; //set to true so that the next write attempt will throw an exception } /** * Is the transport ready to read, * i.e. will a read request result in >0 bytes read. * @return 0 if the transport is read ready, millis since last ready or -1 if never ready */ public long isReadyForRead( EventWaiter waiter ) { if ( waiter != null ){ read_waiter = waiter; } boolean ready = is_ready_for_read || data_already_read != null || ( filter != null && filter.hasBufferedRead()); long now = SystemTime.getSteppedMonotonousTime(); if ( ready ){ last_ready_for_read = now; return( 0 ); } long diff = now - last_ready_for_read + 1; // make sure > 0 return( diff ); } protected boolean readyForRead( boolean ready ) { if ( ready ){ boolean progress = !is_ready_for_read; is_ready_for_read = true; EventWaiter rw = read_waiter; if ( rw != null ){ rw.eventOccurred(); } return progress; }else{ is_ready_for_read = false; return( false ); } } public void setReadyForRead() { readyForRead( true ); } protected void readFailed( Throwable msg ) { msg.fillInStackTrace(); // msg picked up on another thread - make sure trace is available read_select_failure = msg; is_ready_for_read = true; //set to true so that the next read attempt will throw an exception } /** * Write data to the transport from the given buffers. * NOTE: Works like GatheringByteChannel. * @param buffers from which bytes are to be retrieved * @param array_offset offset within the buffer array of the first buffer from which bytes are to be retrieved * @param length maximum number of buffers to be accessed * @return number of bytes written * @throws IOException on write error */ public long write( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { if ( write_select_failure != null ){ throw new IOException( "write_select_failure: " + write_select_failure.getMessage() ); } if ( filter == null ) return 0; long written = filter.write( buffers, array_offset, length ); if ( stats != null ) stats.bytesWritten( (int)written ); //TODO if ( written < 1 ) requestWriteSelect(); return written; } /** * Read data from the transport into the given buffers. * NOTE: Works like ScatteringByteChannel. * @param buffers into which bytes are to be placed * @param array_offset offset within the buffer array of the first buffer into which bytes are to be placed * @param length maximum number of buffers to be accessed * @return number of bytes read * @throws IOException on read error */ public long read( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { if( read_select_failure != null ) { throw new IOException( "read_select_failure: " + read_select_failure.getMessage() ); } //insert already-read data into the front of the stream if ( data_already_read != null ) { int inserted = 0; for( int i = array_offset; i < (array_offset + length); i++ ) { ByteBuffer bb = buffers[ i ]; int orig_limit = data_already_read.limit(); if( data_already_read.remaining() > bb.remaining() ) { data_already_read.limit( data_already_read.position() + bb.remaining() ); } inserted += data_already_read.remaining(); bb.put( data_already_read ); data_already_read.limit( orig_limit ); if( !data_already_read.hasRemaining() ) { data_already_read = null; break; } } if( !buffers[ array_offset + length - 1 ].hasRemaining() ) { //the last buffer has nothing left to read into normally return inserted; //so return right away, skipping socket read } } if ( filter == null ){ throw( new IOException( "Transport not ready" )); } long bytes_read = filter.read( buffers, array_offset, length ); if( stats != null ) stats.bytesRead( (int)bytes_read ); //TODO if( bytes_read == 0 ){ requestReadSelect(); } return bytes_read; } private void requestWriteSelect() { is_ready_for_write = false; if( filter != null ){ filter.getHelper().resumeWriteSelects(); } } private void requestReadSelect() { is_ready_for_read = false; if ( filter != null ){ filter.getHelper().resumeReadSelects(); } } public void connectedInbound() { registerSelectHandling(); } public void connectedOutbound() { registerSelectHandling(); } private void registerSelectHandling() { TransportHelperFilter filter = getFilter(); if( filter == null ) { Debug.out( "ERROR: registerSelectHandling():: filter == null" ); return; } TransportHelper helper = filter.getHelper(); //read selection helper.registerForReadSelects( new TransportHelper.selectListener() { public boolean selectSuccess( TransportHelper helper, Object attachment ) { return( readyForRead( true )); } public void selectFailure( TransportHelper helper, Object attachment, Throwable msg) { readFailed( msg ); } }, null ); helper.registerForWriteSelects( new TransportHelper.selectListener() { public boolean selectSuccess( TransportHelper helper, Object attachment ) { return( readyForWrite( true )); } public void selectFailure( TransportHelper helper, Object attachment, Throwable msg) { writeFailed( msg ); } }, null ); } public void setTrace( boolean on ) { trace = on; TransportHelperFilter filter = getFilter(); if ( filter != null ){ filter.setTrace( on ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/TransportStats.java0000644000175000017500000000715710373051016027345 0ustar adrianadrian/* * Created on May 19, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.util.*; import org.gudy.azureus2.core3.util.Timer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; public class TransportStats { private static final int PRINT_INTERVAL = 60*1000; private static final int GRANULARITY = 10; //bytes private final TreeMap read_sizes = new TreeMap(); private final TreeMap write_sizes = new TreeMap(); private long total_reads = 0; private long total_writes = 0; public TransportStats() { Timer printer = new Timer("TransportStats:Printer"); printer.addPeriodicEvent( PRINT_INTERVAL, new TimerEventPerformer() { public void perform( TimerEvent ev ) { printStats(); } } ); } public void bytesRead( int num_bytes_read ) { total_reads++; updateSizes( read_sizes, num_bytes_read ); } public void bytesWritten( int num_bytes_written ) { total_writes++; updateSizes( write_sizes, num_bytes_written ); } private void updateSizes( TreeMap io_sizes, int num_bytes ) { Integer size_key; if( num_bytes == 0 ) { size_key = new Integer( 0 ); } else { size_key = new Integer( (num_bytes / GRANULARITY) +1 ); } Long count = (Long)io_sizes.get( size_key ); if( count == null ) { io_sizes.put( size_key, new Long( 1 ) ); } else { io_sizes.put( size_key, new Long( count.longValue() +1 ) ); } } private void printStats() { System.out.println( "\n------------------------------" ); System.out.println( "***** TCP SOCKET READ SIZE STATS *****" ); printSizes( read_sizes, total_reads ); System.out.println( "\n***** TCP SOCKET WRITE SIZE STATS *****" ); printSizes( write_sizes, total_writes ); System.out.println( "------------------------------" ); } private void printSizes( TreeMap size_map, long num_total ) { int prev_high = 1; for( Iterator it = size_map.entrySet().iterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry)it.next(); int key = ((Integer)entry.getKey()).intValue(); long count = ((Long)entry.getValue()).longValue(); long percentage = (count *100) / num_total; if( key == 0 ) { if( percentage > 3 ) { System.out.println( "[0 bytes]= x" +percentage+ "%" ); } } else { int high = key * GRANULARITY; if( percentage > 3 ) { System.out.println( "[" +prev_high+ "-" +(high -1)+ " bytes]= x" +percentage+ "%" ); } prev_high = high; } } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/MultiPeerUploader.java0000644000175000017500000004376011035306030027727 0ustar adrianadrian/* * Created on Sep 28, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.util.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.*; import com.aelitis.azureus.core.peermanager.messaging.*; /** * A rate-controlled write entity backed by multiple peer connections, with an * emphasis on transmitting packets with full payloads, i.e. it writes to the * transport in mss-sized chunks if at all possible. It also employs fair, * round-robin write scheduling, where connections each take turns writing a * single full packet per round. */ public class MultiPeerUploader implements RateControlledEntity { private static final int FLUSH_CHECK_LOOP_TIME = 500; //500ms private static final int FLUSH_WAIT_TIME = 3*1000; //3sec no-new-data wait before forcing write flush private long last_flush_check_time = 0; private final RateHandler rate_handler; private boolean destroyed = false; private final HashMap waiting_connections = new HashMap(); private final LinkedList ready_connections = new LinkedList(); private final AEMonitor lists_lock = new AEMonitor( "PacketFillingMultiPeerUploader:lists_lock" ); /** * Create a new packet-filling multi-peer upload entity, * rate-controlled by the given handler. * @param rate_handler listener to handle upload rate limits */ public MultiPeerUploader( RateHandler rate_handler ) { this.rate_handler = rate_handler; } /** * Checks the connections in the waiting list to see if it's time to be force-flushed. */ private void flushCheck() { long diff = SystemTime.getCurrentTime() - last_flush_check_time; if( !destroyed && (diff > FLUSH_CHECK_LOOP_TIME || diff < 0 ) ) { try { lists_lock.enter(); long current_time = SystemTime.getCurrentTime(); for( Iterator i = waiting_connections.entrySet().iterator(); i.hasNext(); ) { Map.Entry entry = (Map.Entry)i.next(); PeerData peer_data = (PeerData)entry.getValue(); long wait_time = current_time - peer_data.last_message_added_time; if( wait_time > FLUSH_WAIT_TIME || wait_time < 0 ) { //time to force flush NetworkConnectionBase conn = (NetworkConnectionBase)entry.getKey(); if( conn.getOutgoingMessageQueue().getTotalSize() > 0 ) { //has data to flush conn.getOutgoingMessageQueue().cancelQueueListener( peer_data.queue_listener ); //cancel the listener i.remove(); //remove from the waiting list addToReadyList( conn ); } else { //no data, so reset flush wait time peer_data.last_message_added_time = current_time; } } } } finally { lists_lock.exit(); } last_flush_check_time = SystemTime.getCurrentTime(); } } /** * Destroy this upload entity. * Note: Removes all peer connections in the process. */ public void destroy() { destroyed = true; try { lists_lock.enter(); //remove and cancel all connections in waiting list for( Iterator i = waiting_connections.entrySet().iterator(); i.hasNext(); ) { Map.Entry entry = (Map.Entry)i.next(); NetworkConnectionBase conn = (NetworkConnectionBase)entry.getKey(); PeerData data = (PeerData)entry.getValue(); conn.getOutgoingMessageQueue().cancelQueueListener( data.queue_listener ); } waiting_connections.clear(); //remove from ready list ready_connections.clear(); } finally { lists_lock.exit(); } } /** * Add the given connection to be managed by this upload entity. * @param peer_connection to be write managed */ public void addPeerConnection( NetworkConnectionBase peer_connection ) { int mss_size = peer_connection.getMssSize(); boolean has_urgent_data = peer_connection.getOutgoingMessageQueue().hasUrgentMessage(); int num_bytes_ready = peer_connection.getOutgoingMessageQueue().getTotalSize(); if( num_bytes_ready >= mss_size || has_urgent_data ) { //has a full packet's worth, or has urgent data addToReadyList( peer_connection ); } else { //has data to send, but not enough for a full packet addToWaitingList( peer_connection ); } } /** * Remove the given connection from this upload entity. * @param peer_connection to be removed * @return true if the connection was found and removed, false if not removed */ public boolean removePeerConnection( NetworkConnectionBase peer_connection ) { try { lists_lock.enter(); //look for the connection in the waiting list and cancel listener if found PeerData peer_data = (PeerData)waiting_connections.remove( peer_connection ); if( peer_data != null ) { peer_connection.getOutgoingMessageQueue().cancelQueueListener( peer_data.queue_listener ); return true; } //look for the connection in the ready list if( ready_connections.remove( peer_connection ) ) { return true; } return false; } finally { lists_lock.exit(); } } //connections with less than a packet's worth of data private void addToWaitingList( final NetworkConnectionBase conn ) { final PeerData peer_data = new PeerData(); OutgoingMessageQueue.MessageQueueListener listener = new OutgoingMessageQueue.MessageQueueListener() { public boolean messageAdded( Message message ) { return true; } public void messageQueued( Message message ) { //connection now has more data to send try { lists_lock.enter(); if( waiting_connections.get( conn ) == null ) { //connection has already been removed from the waiting list return; //stop further processing } int mss_size = conn.getMssSize(); boolean has_urgent_data = conn.getOutgoingMessageQueue().hasUrgentMessage(); int num_bytes_ready = conn.getOutgoingMessageQueue().getTotalSize(); if( num_bytes_ready >= mss_size || has_urgent_data ) { //has a full packet's worth, or has urgent data waiting_connections.remove( conn ); //remove from waiting list conn.getOutgoingMessageQueue().cancelQueueListener( this ); //cancel this listener addToReadyList( conn ); } else { //still not enough data for a full packet if ( !peer_data.bumped ){ // only do this once to avoid the possibility that, for example, sending a have // every 2.9 seconds can result in them being delayed for a significant amount // of time (e.g. 60 seconds +...) peer_data.bumped = true; peer_data.last_message_added_time = SystemTime.getCurrentTime(); //update last message added time } } } finally { lists_lock.exit(); } } public void flush() { try{ lists_lock.enter(); if ( waiting_connections.remove( conn ) != null ){ conn.getOutgoingMessageQueue().cancelQueueListener( this ); addToReadyList( conn ); } }finally{ lists_lock.exit(); } } public void messageRemoved( Message message ) {/*ignore*/} public void messageSent( Message message ) {/*ignore*/} public void protocolBytesSent( int byte_count ) {/*ignore*/} public void dataBytesSent( int byte_count ) {/*ignore*/} }; peer_data.queue_listener = listener; //attach listener peer_data.last_message_added_time = SystemTime.getCurrentTime(); //start flush wait time peer_data.bumped = false; try { lists_lock.enter(); waiting_connections.put( conn, peer_data ); //add to waiting list conn.getOutgoingMessageQueue().registerQueueListener( listener ); //listen for added data } finally { lists_lock.exit(); } } //connections ready to write private void addToReadyList( final NetworkConnectionBase conn ) { try { lists_lock.enter(); ready_connections.addLast( conn ); //add to ready list } finally { lists_lock.exit(); } } private int write( EventWaiter waiter, int num_bytes_to_write ) { //TODO: model this class after the simplicity of MultiPeerDownloader if( num_bytes_to_write < 1 ) { Debug.out( "num_bytes_to_write < 1" ); return 0; //not allowed to write } HashMap connections_to_notify_of_exception = new HashMap(); ArrayList manual_notifications = new ArrayList(); int num_bytes_remaining = num_bytes_to_write; try { lists_lock.enter(); int num_unusable_connections = 0; while( num_bytes_remaining > 0 && num_unusable_connections < ready_connections.size() ) { NetworkConnectionBase conn = (NetworkConnectionBase)ready_connections.removeFirst(); if( !conn.getTransportBase().isReadyForWrite( waiter ) ) { //not yet ready for writing ready_connections.addLast( conn ); //re-add to end as currently unusable num_unusable_connections++; continue; //move on to the next connection } int total_size = conn.getOutgoingMessageQueue().getTotalSize(); if( total_size < 1 ) { //oops, all messages have been removed addToWaitingList( conn ); continue; //move on to the next connection } int mss_size = conn.getMssSize(); int num_bytes_allowed = num_bytes_remaining > mss_size ? mss_size : num_bytes_remaining; //allow a single full packet at most int num_bytes_available = total_size > mss_size ? mss_size : total_size; //allow a single full packet at most if( num_bytes_allowed >= num_bytes_available ) { //we're allowed enough (for either a full packet or to drain any remaining data) int written = 0; try { written = conn.getOutgoingMessageQueue().deliverToTransport( num_bytes_available, true ); if( written > 0 ) { manual_notifications.add( conn ); //register it for manual listener notification } boolean has_urgent_data = conn.getOutgoingMessageQueue().hasUrgentMessage(); int remaining = conn.getOutgoingMessageQueue().getTotalSize(); if( remaining >= mss_size || has_urgent_data ) { //still has a full packet's worth, or has urgent data ready_connections.addLast( conn ); //re-add to end for further writing num_unusable_connections = 0; //reset the unusable count so that it has a chance to try this connection again in the loop } else { //connection does not have enough for a full packet, so remove and place into waiting list addToWaitingList( conn ); } } catch( Throwable e ) { //write exception, so move to waiting list while it waits for removal if( AEDiagnostics.TRACE_CONNECTION_DROPS ) { if( e.getMessage() == null ) { Debug.out( "null write exception message: ", e ); } else { if( e.getMessage().indexOf( "An existing connection was forcibly closed by the remote host" ) == -1 && e.getMessage().indexOf( "Connection reset by peer" ) == -1 && e.getMessage().indexOf( "Broken pipe" ) == -1 && e.getMessage().indexOf( "An established connection was aborted by the software in your host machine" ) == -1 ) { System.out.println( "MP: write exception [" +conn.getTransportBase().getDescription()+ "]: " +e.getMessage() ); } } } if (! (e instanceof IOException )){ Debug.printStackTrace(e); } connections_to_notify_of_exception.put( conn, e ); //do exception notification outside of sync'd block addToWaitingList( conn ); } num_bytes_remaining -= written; } else { //we're not allowed enough to maximize the packet payload ready_connections.addLast( conn ); //re-add to end as currently unusable num_unusable_connections++; continue; //move on to the next connection } } } finally { lists_lock.exit(); } //manual queue listener notifications for( int i=0; i < manual_notifications.size(); i++ ) { NetworkConnectionBase conn = (NetworkConnectionBase)manual_notifications.get( i ); conn.getOutgoingMessageQueue().doListenerNotifications(); } //exception notifications for( Iterator i = connections_to_notify_of_exception.entrySet().iterator(); i.hasNext(); ) { Map.Entry entry = (Map.Entry)i.next(); NetworkConnectionBase conn = (NetworkConnectionBase)entry.getKey(); Throwable exception = (Throwable)entry.getValue(); conn.notifyOfException( exception ); } int num_bytes_written = num_bytes_to_write - num_bytes_remaining; if( num_bytes_written > 0 ) { rate_handler.bytesProcessed( num_bytes_written ); } return num_bytes_written; } /** * Does this entity have data ready for writing. * @return true if it has data to send, false if empty */ /* public boolean hasWriteDataAvailable() { if( ready_connections.isEmpty() ) return false; return true; } */ private static class PeerData { private OutgoingMessageQueue.MessageQueueListener queue_listener; private long last_message_added_time; private boolean bumped; } public long getBytesReadyToWrite() { long total = 0; try { lists_lock.enter(); for( Iterator i = waiting_connections.keySet().iterator(); i.hasNext(); ) { NetworkConnectionBase conn = (NetworkConnectionBase)i.next(); total += conn.getOutgoingMessageQueue().getTotalSize(); } for( Iterator i = ready_connections.iterator(); i.hasNext(); ) { NetworkConnectionBase conn = (NetworkConnectionBase)i.next(); total += conn.getOutgoingMessageQueue().getTotalSize(); } }finally{ lists_lock.exit(); } return( total ); } public int getConnectionCount() { return( waiting_connections.size() + ready_connections.size()); } public int getReadyConnectionCount( EventWaiter waiter ) { int total = 0; try { lists_lock.enter(); for( Iterator i = waiting_connections.keySet().iterator(); i.hasNext(); ) { NetworkConnectionBase conn = (NetworkConnectionBase)i.next(); if ( conn.getTransportBase().isReadyForWrite(waiter)){ total++; } } for( Iterator i = ready_connections.iterator(); i.hasNext(); ) { NetworkConnectionBase conn = (NetworkConnectionBase)i.next(); if ( conn.getTransportBase().isReadyForWrite(waiter)){ total++; } } }finally{ lists_lock.exit(); } return( total ); } //////////////// RateControlledWriteEntity implementation //////////////////// public boolean canProcess( EventWaiter waiter ) { flushCheck(); //since this method is called repeatedly from a loop, we can use it to check flushes if( ready_connections.isEmpty() ) return false; //no data to send if( rate_handler.getCurrentNumBytesAllowed() < 1/*NetworkManager.getTcpMssSize()*/ ) return false; return true; } public boolean doProcessing( EventWaiter waiter ) { int num_bytes_allowed = rate_handler.getCurrentNumBytesAllowed(); if( num_bytes_allowed < 1 ) return false; return write( waiter, num_bytes_allowed ) > 0 ? true : false; } public int getPriority() { return RateControlledEntity.PRIORITY_HIGH; } public String getString() { StringBuffer str = new StringBuffer(); str.append( "MPU (" + waiting_connections.size() + "/" + ready_connections.size() + "): " ); str.append( "can_process=" + canProcess(null) + ",bytes_allowed=" + rate_handler.getCurrentNumBytesAllowed() + ", waiting=" ); try { lists_lock.enter(); int num = 0; for( Iterator i = waiting_connections.keySet().iterator(); i.hasNext(); ) { NetworkConnectionBase conn = (NetworkConnectionBase)i.next(); if ( num++ > 0 ){ str.append( "," ); } str.append( conn.getString()); } str.append( ": ready=" ); num = 0; for( Iterator i = ready_connections.iterator(); i.hasNext(); ) { NetworkConnectionBase conn = (NetworkConnectionBase)i.next(); if ( num++ > 0 ){ str.append( "," ); } str.append( conn.getString()); } }finally{ lists_lock.exit(); } return( str.toString()); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/test/0000755000175000017500000000000011310377630024441 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/test/PHETester.java0000644000175000017500000002340711155434160027114 0ustar adrianadrian/* * Created on 17-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.test; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector; import com.aelitis.azureus.core.networkmanager.VirtualServerChannelSelector; import com.aelitis.azureus.core.networkmanager.VirtualServerChannelSelectorFactory; import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector.VirtualSelectorListener; import com.aelitis.azureus.core.networkmanager.impl.ProtocolDecoder; import com.aelitis.azureus.core.networkmanager.impl.ProtocolDecoderInitial; import com.aelitis.azureus.core.networkmanager.impl.ProtocolDecoderAdapter; import com.aelitis.azureus.core.networkmanager.impl.TransportHelperFilter; import com.aelitis.azureus.core.networkmanager.impl.TransportHelper; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPTransportHelper; public class PHETester { private final VirtualChannelSelector connect_selector = new VirtualChannelSelector( "PHETester", VirtualChannelSelector.OP_CONNECT, true ); private byte[] TEST_HEADER = "TestHeader".getBytes(); private static boolean OUTGOING_PLAIN = false; private static byte[] shared_secret = "sdsjdksjdkj".getBytes(); public PHETester() { ProtocolDecoder.addSecrets( new byte[][]{ shared_secret }); VirtualServerChannelSelector accept_server = VirtualServerChannelSelectorFactory.createNonBlocking( new InetSocketAddress( 8765 ), 0, new VirtualServerChannelSelector.SelectListener() { public void newConnectionAccepted( ServerSocketChannel server, SocketChannel channel ) { incoming( channel ); } }); accept_server.start(); new Thread() { public void run() { while( true ){ try{ connect_selector.select( 100 ); } catch( Throwable t ) { Debug.out( "connnectSelectLoop() EXCEPTION: ", t ); } } } }.start(); outgoings(); } protected void incoming( SocketChannel channel ) { try{ TransportHelper helper = new TCPTransportHelper( channel ); final ProtocolDecoderInitial decoder = new ProtocolDecoderInitial( helper, null, false, null, new ProtocolDecoderAdapter() { public void decodeComplete( ProtocolDecoder decoder, ByteBuffer remaining_initial_data ) { System.out.println( "incoming decode complete: " + decoder.getFilter().getName(false)); readStream( "incoming", decoder.getFilter() ); writeStream( "ten fat monkies", decoder.getFilter() ); } public void decodeFailed( ProtocolDecoder decoder, Throwable cause ) { System.out.println( "incoming decode failed: " + Debug.getNestedExceptionMessage(cause)); } public void gotSecret( byte[] session_secret ) { } public int getMaximumPlainHeaderLength() { return( TEST_HEADER.length ); } public int matchPlainHeader( ByteBuffer buffer ) { int pos = buffer.position(); int lim = buffer.limit(); buffer.flip(); boolean match = buffer.compareTo( ByteBuffer.wrap( TEST_HEADER )) == 0; buffer.position( pos ); buffer.limit( lim ); System.out.println( "Match - " + match ); return( match?ProtocolDecoderAdapter.MATCH_CRYPTO_NO_AUTO_FALLBACK:ProtocolDecoderAdapter.MATCH_NONE ); } }); }catch( Throwable e ){ e.printStackTrace(); } } protected void outgoings() { while( true ){ outgoing(); try{ Thread.sleep(1000000); }catch( Throwable e ){ } } } protected void outgoing() { try{ final SocketChannel channel = SocketChannel.open(); channel.configureBlocking( false ); if ( channel.connect( new InetSocketAddress("localhost", 8765 ))){ outgoing( channel ); }else{ connect_selector.register( channel, new VirtualSelectorListener() { public boolean selectSuccess( VirtualChannelSelector selector, SocketChannel sc, Object attachment) { try{ if ( channel.finishConnect()){ outgoing( channel ); return( true ); }else{ throw( new IOException( "finishConnect failed" )); } }catch( Throwable e ){ e.printStackTrace(); return( false ); } } public void selectFailure( VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg) { msg.printStackTrace(); } }, null ); } }catch( Throwable e ){ e.printStackTrace(); } } protected void outgoing( SocketChannel channel ) { try{ if ( OUTGOING_PLAIN ){ writeStream( TEST_HEADER, channel); writeStream( "two jolly porkers".getBytes(), channel ); }else{ TransportHelper helper = new TCPTransportHelper( channel ); final ProtocolDecoderInitial decoder = new ProtocolDecoderInitial( helper, new byte[][]{ shared_secret }, true, null, new ProtocolDecoderAdapter() { public void decodeComplete( ProtocolDecoder decoder, ByteBuffer remaining_initial_data ) { System.out.println( "outgoing decode complete: " + decoder.getFilter().getName(false)); readStream( "incoming", decoder.getFilter() ); writeStream( TEST_HEADER, decoder.getFilter()); writeStream( "two jolly porkers", decoder.getFilter() ); } public void decodeFailed( ProtocolDecoder decoder, Throwable cause ) { System.out.println( "outgoing decode failed: " + Debug.getNestedExceptionMessage(cause)); } public void gotSecret( byte[] session_secret ) { } public int getMaximumPlainHeaderLength() { throw( new RuntimeException()); } public int matchPlainHeader( ByteBuffer buffer ) { throw( new RuntimeException()); } }); } }catch( Throwable e ){ e.printStackTrace(); } } protected void readStream( final String str, final TransportHelperFilter filter ) { try{ TCPNetworkManager.getSingleton().getReadSelector().register( ((TCPTransportHelper)filter.getHelper()).getSocketChannel(), new VirtualSelectorListener() { public boolean selectSuccess( VirtualChannelSelector selector, SocketChannel sc, Object attachment) { ByteBuffer buffer = ByteBuffer.allocate(1024); try{ long len = filter.read( new ByteBuffer[]{ buffer }, 0, 1 ); byte[] data = new byte[buffer.position()]; buffer.flip(); buffer.get( data ); System.out.println( str + ": " + new String(data)); return( len > 0 ); }catch( Throwable e ){ e.printStackTrace(); return( false ); } } public void selectFailure( VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg) { msg.printStackTrace(); } }, null ); }catch( Throwable e ){ e.printStackTrace(); } } protected void writeStream( String str, TransportHelperFilter filter ) { writeStream( str.getBytes(), filter ); } protected void writeStream( byte[] data, TransportHelperFilter filter ) { try{ filter.write( new ByteBuffer[]{ ByteBuffer.wrap(data)}, 0, 1 ); }catch( Throwable e ){ e.printStackTrace(); } } protected void writeStream( byte[] data, SocketChannel channel ) { try{ channel.write( new ByteBuffer[]{ ByteBuffer.wrap(data)}, 0, 1 ); }catch( Throwable e ){ e.printStackTrace(); } } public static void main( String[] args ) { AEDiagnostics.startup( false ); // OUTGOING_PLAIN = true; COConfigurationManager.setParameter( "network.transport.encrypted.require", true ); COConfigurationManager.setParameter( "network.transport.encrypted.min_level", "Plain" ); new PHETester(); try{ Thread.sleep(10000000); }catch( Throwable e ){ } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/MultiPeerDownloader.java0000644000175000017500000001346011035306024030247 0ustar adrianadrian/* * Created on Apr 22, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import java.util.*; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.networkmanager.*; /** * */ public class MultiPeerDownloader implements RateControlledEntity { private volatile ArrayList connections_cow = new ArrayList(); //copied-on-write private final AEMonitor connections_mon = new AEMonitor( "MultiPeerDownloader" ); private final RateHandler main_handler; private int next_position = 0; /** * Create new downloader using the given "global" rate handler to limit all peers managed by this downloader. * @param main_handler */ public MultiPeerDownloader( RateHandler main_handler ) { this.main_handler = main_handler; } /** * Add the given connection to the downloader. * @param connection to add */ public void addPeerConnection( NetworkConnectionBase connection ) { try { connections_mon.enter(); //copy-on-write ArrayList conn_new = new ArrayList( connections_cow.size() + 1 ); conn_new.addAll( connections_cow ); conn_new.add( connection ); connections_cow = conn_new; } finally{ connections_mon.exit(); } } /** * Remove the given connection from the downloader. * @param connection to remove * @return true if the connection was found and removed, false if not removed */ public boolean removePeerConnection( NetworkConnectionBase connection ) { try { connections_mon.enter(); //copy-on-write ArrayList conn_new = new ArrayList( connections_cow ); boolean removed = conn_new.remove( connection ); if( !removed ) return false; connections_cow = conn_new; return true; } finally{ connections_mon.exit(); } } public boolean canProcess( EventWaiter waiter ) { if( main_handler.getCurrentNumBytesAllowed() < 1/*NetworkManager.getTcpMssSize()*/ ) return false; return true; } public long getBytesReadyToWrite() { return( 0 ); } public int getConnectionCount() { return(connections_cow.size()); } public int getReadyConnectionCount( EventWaiter waiter ) { int res = 0; for (Iterator it=connections_cow.iterator();it.hasNext();){ NetworkConnectionBase connection = (NetworkConnectionBase)it.next(); if ( connection.getTransportBase().isReadyForRead( waiter ) == 0 ){ res++; } } return( res ); } public boolean doProcessing( EventWaiter waiter ) { int num_bytes_allowed = main_handler.getCurrentNumBytesAllowed(); if( num_bytes_allowed < 1 ) return false; ArrayList connections = connections_cow; int num_checked = 0; int num_bytes_remaining = num_bytes_allowed; while( num_bytes_remaining > 0 && num_checked < connections.size() ) { next_position = next_position >= connections.size() ? 0 : next_position; //make circular NetworkConnectionBase connection = (NetworkConnectionBase)connections.get( next_position ); next_position++; num_checked++; long ready = connection.getTransportBase().isReadyForRead( waiter ); if ( ready == 0 ) { int mss = connection.getMssSize(); int allowed = num_bytes_remaining > mss ? mss : num_bytes_remaining; int bytes_read = 0; try { bytes_read = connection.getIncomingMessageQueue().receiveFromTransport( allowed ); } catch( Throwable e ) { if( AEDiagnostics.TRACE_CONNECTION_DROPS ) { if( e.getMessage() == null ) { Debug.out( "null read exception message: ", e ); } else { if( e.getMessage().indexOf( "end of stream on socket read" ) == -1 && e.getMessage().indexOf( "An existing connection was forcibly closed by the remote host" ) == -1 && e.getMessage().indexOf( "Connection reset by peer" ) == -1 && e.getMessage().indexOf( "An established connection was aborted by the software in your host machine" ) == -1 ) { System.out.println( "MP: read exception [" +connection.getTransportBase().getDescription()+ "]: " +e.getMessage() ); } } } if (! (e instanceof IOException )){ Debug.printStackTrace(e); } connection.notifyOfException( e ); } num_bytes_remaining -= bytes_read; } } int total_bytes_read = num_bytes_allowed - num_bytes_remaining; if( total_bytes_read > 0 ) { main_handler.bytesProcessed( total_bytes_read ); return true; } return false; //zero bytes read } public int getPriority() { return RateControlledEntity.PRIORITY_HIGH; } public String getString() { StringBuffer str = new StringBuffer(); str.append( "MPD (" + connections_cow.size() + "): " ); int num = 0; for (Iterator it=connections_cow.iterator();it.hasNext();){ NetworkConnectionBase connection = (NetworkConnectionBase)it.next(); if ( num++ > 0 ){ str.append( "," ); } str.append( connection.getString()); } return( str.toString()); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/http/0000755000175000017500000000000011310377630024441 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnection.java0000644000175000017500000006722511232000056031455 0ustar adrianadrian/* * Created on 3 Oct 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.http; import java.io.IOException; import java.nio.ByteBuffer; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.peer.impl.PEPeerControl; import org.gudy.azureus2.core3.peer.impl.PEPeerTransport; import org.gudy.azureus2.core3.peer.util.PeerUtils; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import com.aelitis.azureus.core.networkmanager.NetworkConnection; import com.aelitis.azureus.core.networkmanager.OutgoingMessageQueue; import com.aelitis.azureus.core.networkmanager.RawMessage; import com.aelitis.azureus.core.networkmanager.impl.RawMessageImpl; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTBitfield; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTHandshake; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTHave; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTInterested; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTPiece; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTRequest; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.util.HTTPUtils; public abstract class HTTPNetworkConnection { protected static final LogIDs LOGID = LogIDs.NWMAN; private static final int MAX_OUTSTANDING_BT_REQUESTS = 16; protected static final String NL = "\r\n"; private static final String HDR_SERVER = "Server: " + Constants.AZUREUS_NAME + " " + Constants.AZUREUS_VERSION + NL; private static final String HDR_KEEP_ALIVE_TIMEOUT = "Keep-Alive: timeout=30" + NL; private static final String HDR_CACHE_CONTROL = "Cache-Control: public, max-age=86400" + NL; private static final String DEFAULT_CONTENT_TYPE = HTTPUtils.guessContentTypeFromFileType(null); private static int max_read_block_size; static{ ParameterListener param_listener = new ParameterListener() { public void parameterChanged( String str ) { max_read_block_size = COConfigurationManager.getIntParameter( "BT Request Max Block Size" ); } }; COConfigurationManager.addAndFireParameterListener( "BT Request Max Block Size", param_listener); } private static final int TIMEOUT_CHECK_PERIOD = 15*1000; private static final int DEAD_CONNECTION_TIMEOUT_PERIOD = 30*1000; private static final int MAX_CON_PER_ENDPOINT = 5*1000; private static Map> http_connection_map = new HashMap>(); static{ SimpleTimer.addPeriodicEvent( "HTTPNetworkConnection:timer", TIMEOUT_CHECK_PERIOD, new TimerEventPerformer() { public void perform( TimerEvent event ) { synchronized( http_connection_map ){ boolean check = true; while( check ){ check = false; Iterator>> it = http_connection_map.entrySet().iterator(); while( it.hasNext()){ Map.Entry> entry = it.next(); networkConnectionKey key = (networkConnectionKey)entry.getKey(); List connections = entry.getValue(); /* String times = ""; for (int i=0;i " + connections.size() + " - " + times ); */ if ( checkConnections( connections )){ // might have a concurrent mod to the iterator if ( !http_connection_map.containsKey( key )){ check = true; break; } } } } } } }); } protected static boolean checkConnections( List connections ) { boolean some_closed = false; HTTPNetworkConnection oldest = null; long oldest_time = -1; Iterator it = connections.iterator(); List timed_out = new ArrayList(); while( it.hasNext()){ HTTPNetworkConnection connection = (HTTPNetworkConnection)it.next(); long time = connection.getTimeSinceLastActivity(); if ( time > DEAD_CONNECTION_TIMEOUT_PERIOD ){ if ( connection.getRequestCount() == 0 ){ timed_out.add( connection ); continue; } } if ( time > oldest_time && !connection.isClosing()){ oldest_time = time; oldest = connection; } } for (int i=0;i MAX_CON_PER_ENDPOINT ){ oldest.close( "Too many connections from initiator"); some_closed = true; } return( some_closed ); } private HTTPNetworkManager manager; private NetworkConnection connection; private PEPeerTransport peer; private HTTPMessageDecoder decoder; private HTTPMessageEncoder encoder; private boolean sent_handshake = false; private byte[] peer_id = PeerUtils.createWebSeedPeerID(); private boolean choked = true; private List http_requests = new ArrayList(); private List choked_requests = new ArrayList(); private List outstanding_requests = new ArrayList(); private BitSet piece_map = new BitSet(); private long last_http_activity_time; private networkConnectionKey network_connection_key; private boolean closing; private boolean destroyed; private String last_modified_date; private String content_type = DEFAULT_CONTENT_TYPE; private CopyOnWriteList request_listeners = null; protected HTTPNetworkConnection( HTTPNetworkManager _manager, NetworkConnection _connection, PEPeerTransport _peer ) { manager = _manager; connection = _connection; peer = _peer; DiskManager dm = peer.getManager().getDiskManager(); long last_modified = 0; try{ last_modified = dm.getFiles()[0].getFile(true).lastModified(); }catch( Throwable e ){ } last_modified_date = TimeFormatter.getHTTPDate( last_modified ); network_connection_key = new networkConnectionKey(); last_http_activity_time = SystemTime.getCurrentTime(); decoder = (HTTPMessageDecoder)connection.getIncomingMessageQueue().getDecoder(); encoder = (HTTPMessageEncoder)connection.getOutgoingMessageQueue().getEncoder(); synchronized( http_connection_map ){ List connections = http_connection_map.get( network_connection_key ); if ( connections == null ){ connections = new ArrayList(); http_connection_map.put( network_connection_key, connections ); } connections.add( this ); if ( connections.size() > MAX_CON_PER_ENDPOINT ){ checkConnections( connections ); } } // note that the decoder can synchronously call-back if is preloaded with a header // here... encoder.setConnection( this ); decoder.setConnection( this ); } protected boolean isSeed() { if ( ( !peer.getControl().isSeeding()) || peer.getControl().getHiddenBytes() > 0 ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(peer,LOGID, "Download is not seeding" )); } sendAndClose( manager.getNotFound()); return( false ); } return( true ); } protected void setContentType( String ct ) { content_type = ct; } protected HTTPNetworkManager getManager() { return( manager ); } protected NetworkConnection getConnection() { return( connection ); } protected PEPeerTransport getPeer() { return( peer ); } protected PEPeerControl getPeerControl() { return( peer.getControl()); } protected RawMessage encodeChoke() { synchronized( outstanding_requests ){ choked = true; } return( null ); } protected RawMessage encodeUnchoke() { synchronized( outstanding_requests ){ choked = false; for (int i=0;i 0 ){ res.append( "Content-Range: bytes " + offsets[0] + "-" + (offsets[0]+lengths[0]-1) + "/" + content_length ); res.append( NL ); } } res.append( "Connection: " ); res.append( request.keepAlive()?"Keep-Alive":"Close" ); res.append( NL ); if ( request.keepAlive()){ res.append( HDR_KEEP_ALIVE_TIMEOUT ); } res.append( "Content-Length: " ); res.append( request.getTotalLength()); res.append( NL ); res.append( NL ); return( res.toString()); } protected void addRequest( httpRequest request ) throws IOException { last_http_activity_time = SystemTime.getCurrentTime(); PEPeerControl control = getPeerControl(); if ( !sent_handshake ){ sent_handshake = true; decoder.addMessage( new BTHandshake( control.getHash(), peer_id, false, (byte)1 )); byte[] bits = new byte[(control.getPieces().length +7) /8]; DirectByteBuffer buffer = new DirectByteBuffer( ByteBuffer.wrap( bits )); decoder.addMessage( new BTBitfield( buffer, (byte)1 )); } synchronized( outstanding_requests ){ http_requests.add( request ); } submitBTRequests(); } protected void submitBTRequests() throws IOException { PEPeerControl control = getPeerControl(); long piece_size = control.getPieceLength(0); synchronized( outstanding_requests ){ while( outstanding_requests.size() < MAX_OUTSTANDING_BT_REQUESTS && http_requests.size() > 0 ){ httpRequest http_request = (httpRequest)http_requests.get(0); long[] offsets = http_request.getModifiableOffsets(); long[] lengths = http_request.getModifiableLengths(); int index = http_request.getIndex(); long offset = offsets[index]; long length = lengths[index]; int this_piece_number = (int)(offset / piece_size); int this_piece_size = control.getPieceLength( this_piece_number ); int offset_in_piece = (int)( offset - ( this_piece_number * piece_size )); int space_this_piece = this_piece_size - offset_in_piece; int request_size = (int)Math.min( length, space_this_piece ); request_size = Math.min( request_size, max_read_block_size ); addBTRequest( new BTRequest( this_piece_number, offset_in_piece, request_size, (byte)1), http_request ); if ( request_size == length ){ if ( index == offsets.length - 1 ){ http_requests.remove(0); }else{ http_request.setIndex( index+1 ); } }else{ offsets[index] += request_size; lengths[index] -= request_size; } } } } protected void addBTRequest( BTRequest request, httpRequest http_request ) throws IOException { synchronized( outstanding_requests ){ if ( destroyed ){ throw( new IOException( "HTTP connection destroyed" )); } outstanding_requests.add( new pendingRequest( request, http_request )); if ( choked ){ if ( choked_requests.size() > 1024 ){ Debug.out( "pending request limit exceeded" ); }else{ choked_requests.add( request ); } }else{ decoder.addMessage( request ); } } } protected RawMessage[] encodePiece( Message message ) { last_http_activity_time = SystemTime.getCurrentTime(); BTPiece piece = (BTPiece)message; List ready_requests = new ArrayList(); boolean found = false; synchronized( outstanding_requests ){ if ( destroyed ){ return( new RawMessage[]{ getEmptyRawMessage( message )}); } for (int i=0;i it = outstanding_requests.iterator(); while( it.hasNext()){ pendingRequest r = it.next(); BTPiece btp = r.getBTPiece(); if ( btp == null ){ break; } it.remove(); ready_requests.add( r ); } } break; } } } } if ( !found ){ Debug.out( "request not matched" ); return( new RawMessage[]{ getEmptyRawMessage( message )}); } if ( ready_requests.size() == 0 ){ return( new RawMessage[]{ getEmptyRawMessage( message )}); } try{ submitBTRequests(); }catch( IOException e ){ } pendingRequest req = (pendingRequest)ready_requests.get(0); DirectByteBuffer[] buffers; httpRequest http_request = req.getHTTPRequest(); RawMessage[] raw_messages = new RawMessage[ ready_requests.size()]; for (int i=0;i it = request_listeners.iterator(); while( it.hasNext()){ ((requestListener)it.next()).requestComplete( req ); } } raw_messages[i] = new RawMessageImpl( this_piece, buffers, RawMessage.PRIORITY_HIGH, true, new Message[0] ); } return( raw_messages ); } protected int getRequestCount() { synchronized( outstanding_requests ){ return( http_requests.size()); } } protected boolean isClosing() { return( closing ); } protected void close( String reason ) { closing = true; peer.getControl().removePeer( peer ); } protected void destroy() { synchronized( http_connection_map ){ List connections = http_connection_map.get( network_connection_key ); if ( connections != null ){ connections.remove( this ); if ( connections.size() == 0 ){ http_connection_map.remove( network_connection_key ); } } } synchronized( outstanding_requests ){ destroyed = true; for (int i=0;i(); } request_listeners.add( new requestListener() { int num_to_go = request_count; public void requestComplete( pendingRequest r ) { num_to_go--; if ( num_to_go == 0 ){ request_listeners.remove( this ); flushRequestsSupport( l ); } } }); } } if ( sync_fire ){ flushRequestsSupport( l ); } } protected void flushRequestsSupport( final flushListener l ) { OutgoingMessageQueue omq = getConnection().getOutgoingMessageQueue(); final Message http_message = new HTTPMessage( new byte[0] ); omq.registerQueueListener( new OutgoingMessageQueue.MessageQueueListener() { public boolean messageAdded( Message message ) { return( true ); } public void messageQueued( Message message ) { } public void messageRemoved( Message message ) { } public void messageSent( Message message ) { if ( message == http_message ){ l.flushed(); } } public void protocolBytesSent( int byte_count ) { } public void dataBytesSent( int byte_count ) { } public void flush(){} }); omq.addMessage( http_message, false ); // if after adding the message there's no bytes on the queue then we need to trigger an // immediate flushed event as the queue won't get processed (0 bytes on it...) if ( omq.getTotalSize() == 0 ){ l.flushed(); } } protected class httpRequest { private final long[] orig_offsets; private final long[] orig_lengths; private final long content_length; private final boolean partial_content; private final boolean keep_alive; private final long[] mod_offsets; private final long[] mod_lengths; private int index; private long total_length; private boolean sent_first_reply; protected httpRequest( long[] _offsets, long[] _lengths, long _content_length, boolean _partial_content, boolean _keep_alive ) { orig_offsets = _offsets; orig_lengths = _lengths; content_length = _content_length; partial_content = _partial_content; keep_alive = _keep_alive; /* String str =""; for (int i=0;i ranges = new ArrayList(); boolean keep_alive = false; for (int i=1;i " + line ); if ( line_num == 1 ){ line = line.substring( line.indexOf( "files/" ) + 6 ); int hash_end = line.indexOf( "/" ); final byte[] old_hash = control.getHash(); final byte[] new_hash = URLDecoder.decode(line.substring(0, hash_end), "ISO-8859-1").getBytes( "ISO-8859-1" ); if ( !Arrays.equals( new_hash, old_hash )){ switching = true; decoder.pauseInternally(); flushRequests( new flushListener() { private boolean triggered; public void flushed() { synchronized( this ){ if ( triggered ){ return; } triggered = true; } getManager().reRoute( HTTPNetworkConnectionFile.this, old_hash, new_hash, header ); } }); return; } line = line.substring( hash_end + 1 ); line = line.substring( 0, line.lastIndexOf( ' ' )); String file = line; if ( to_torrent.isSimpleTorrent()){ // optimise for simple torrents. also support the case where // client has the hash but doesn't know the file name target_file = dm.getFiles()[0]; }else{ target_str = file; StringTokenizer tok = new StringTokenizer( file, "/" ); List bits = new ArrayList(); while( tok.hasMoreTokens()){ bits.add( URLDecoder.decode(tok.nextToken(), "ISO-8859-1").getBytes( "ISO-8859-1" )); } // latest spec has torrent file name encoded first for non-simple torrents // remove it if we find it so we have some backward compat if ( !to_torrent.isSimpleTorrent() && bits.size() > 1 ){ if ( Arrays.equals( to_torrent.getName(), (byte[])bits.get(0))){ bits.remove(0); } } DiskManagerFileInfo[] files = dm.getFiles(); file_offset = 0; for (int j=0;j 0; if ( !partial_content ){ ranges.add( new long[]{ 0, file_length - 1}); } long[] offsets = new long[ranges.size()]; long[] lengths = new long[ranges.size()]; for (int i=0;i= file_length || end < 0 || end >= file_length || start > end ){ log( "Invalid range specification: '" + start + "-" + end + "'" ); sendAndClose( getManager().getRangeNotSatisfiable()); return; } offsets[i] = file_offset + start; lengths[i] = ( end - start ) + 1; } addRequest( new httpRequest( offsets, lengths, file_length, partial_content, keep_alive )); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessage.java0000644000175000017500000000533210647335460027402 0ustar adrianadrian/* * Created on 5 Oct 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.http; import java.nio.ByteBuffer; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.networkmanager.RawMessage; import com.aelitis.azureus.core.networkmanager.impl.RawMessageImpl; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; public class HTTPMessage implements Message { public static final String MSG_ID = "HTTP_DATA"; private static final byte[] MSG_ID_BYTES = MSG_ID.getBytes(); private static final String MSG_DESC = "HTTP data"; private DirectByteBuffer[] data; protected HTTPMessage( String stuff ) { data = new DirectByteBuffer[]{ new DirectByteBuffer( ByteBuffer.wrap( stuff.getBytes())) }; } protected HTTPMessage( byte[] stuff ) { data = new DirectByteBuffer[]{ new DirectByteBuffer( ByteBuffer.wrap( stuff )) }; } public String getID() { return( MSG_ID ); } public byte[] getIDBytes() { return( MSG_ID_BYTES ); } public String getFeatureID() { return( null ); } public int getFeatureSubID() { return( 0 ); } public int getType() { return( TYPE_DATA_PAYLOAD ); } public byte getVersion() { return( 1 ); } public String getDescription() { return( MSG_DESC ); } public DirectByteBuffer[] getData() { return( data ); } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { throw( new MessageException( "not supported" )); } protected RawMessage encode( Message message ) { return( new RawMessageImpl( message, data, RawMessage.PRIORITY_HIGH, true, new Message[0] )); } public void destroy() { data[0].returnToPool(); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessageDecoder.java0000644000175000017500000001240510647335460030667 0ustar adrianadrian/* * Created on 2 Oct 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.http; import java.io.IOException; import java.nio.ByteBuffer; import java.util.*; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.networkmanager.Transport; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageStreamDecoder; public class HTTPMessageDecoder implements MessageStreamDecoder { private static final int MAX_HEADER = 1024; private static final String NL = "\r\n"; private HTTPNetworkConnection http_connection; private volatile boolean paused; private volatile boolean paused_internally; private volatile boolean destroyed; private StringBuffer header_so_far = new StringBuffer(); private boolean header_ready; private List messages = new ArrayList(); private int protocol_bytes_read; public HTTPMessageDecoder() { } public HTTPMessageDecoder( String pre_read_header ) { header_so_far.append( pre_read_header ); header_ready = true; } public void setConnection( HTTPNetworkConnection _http_connection ) { http_connection = _http_connection; if ( destroyed ){ http_connection.destroy(); } } public int performStreamDecode( Transport transport, int max_bytes ) throws IOException { // before we start message processing we should have had the connection bound if ( http_connection == null ){ Debug.out( "connection not yet assigned" ); throw( new IOException( "Internal error - connection not yet assigned" )); } // System.out.println( "performStreamDecode" ); protocol_bytes_read = 0; if ( paused_internally ){ return( 0 ); } if ( header_ready ){ header_ready = false; int len = header_so_far.length(); http_connection.decodeHeader( this, header_so_far.toString()); header_so_far.setLength(0); return( len ); }else{ int rem = max_bytes; byte[] bytes = new byte[1]; ByteBuffer bb = ByteBuffer.wrap( bytes ); ByteBuffer[] bbs = { bb }; while( rem > 0 && !( paused || paused_internally )){ if ( transport.read( bbs,0, 1 ) == 0 ){ break; } rem--; protocol_bytes_read++; bb.flip(); char c = (char)(bytes[0]&0xff); header_so_far.append( c ); if ( header_so_far.length() > MAX_HEADER ){ throw( new IOException( "HTTP header exceeded maximum of " + MAX_HEADER )); } if ( c == '\n' ){ String header_str = header_so_far.toString(); if ( header_str.endsWith( NL + NL )){ http_connection.decodeHeader( this, header_str ); header_so_far.setLength(0); } } } return( max_bytes - rem ); } } protected void addMessage( Message message ) { synchronized( messages ){ messages.add( message ); } http_connection.readWakeup(); } public Message[] removeDecodedMessages() { synchronized( messages ){ if ( messages.isEmpty()){ return null; } Message[] msgs = (Message[])messages.toArray( new Message[messages.size()] ); messages.clear(); return( msgs ); } } public int getProtocolBytesDecoded() { return( protocol_bytes_read ); } public int getDataBytesDecoded() { return( 0 ); } public int getPercentDoneOfCurrentMessage() { return( 0 ); } protected void pauseInternally() { paused_internally = true; } public void pauseDecoding() { paused = true; } public void resumeDecoding() { if ( !destroyed ){ paused = false; } } protected int getQueueSize() { return( messages.size()); } public ByteBuffer destroy() { paused = true; destroyed = true; if ( http_connection != null ){ http_connection.destroy(); } try{ for( int i=0; i url_handlers = new CopyOnWriteList(); private HTTPNetworkManager() { Set types = new HashSet(); types.add( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_COUNT ); types.add( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_OK_COUNT ); types.add( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_INVALID_COUNT ); types.add( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_WEBSEED_COUNT ); types.add( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_GETRIGHT_COUNT ); AzureusCoreStats.registerProvider( types, new AzureusCoreStatsProvider() { public void updateStats( Set types, Map values ) { if ( types.contains( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_COUNT )){ values.put( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_COUNT, new Long( total_requests )); } if ( types.contains( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_OK_COUNT )){ values.put( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_OK_COUNT, new Long( total_ok_requests )); } if ( types.contains( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_INVALID_COUNT )){ values.put( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_INVALID_COUNT, new Long( total_invalid_requests )); } if ( types.contains( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_WEBSEED_COUNT )){ values.put( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_WEBSEED_COUNT, new Long( total_webseed_requests )); } if ( types.contains( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_GETRIGHT_COUNT )){ values.put( AzureusCoreStats.ST_NET_HTTP_IN_REQUEST_GETRIGHT_COUNT, new Long( total_getright_requests)); } } }); /* try{ System.out.println( "/webseed?info_hash=" + URLEncoder.encode( new String( ByteFormatter.decodeString("C9C04D96F11FB5C5ECC99D418D3575FBFC2208B0"), "ISO-8859-1"), "ISO-8859-1" )); }catch( Throwable e ){ e.printStackTrace(); } */ http_incoming_manager = new IncomingSocketChannelManager( "HTTP.Data.Listen.Port", "HTTP.Data.Listen.Port.Enable" ); NetworkManager.ByteMatcher matcher = new NetworkManager.ByteMatcher() { public int matchThisSizeOrBigger(){ return( 4 + 1 + 11 ); } // GET ' ' ' HTTP/1.1' public int maxSize() { return 256; } // max GET size - boiler plate plus small url plus hash public int minSize() { return 3; } // enough to match GET public Object matches( TransportHelper transport, ByteBuffer to_compare, int port ) { total_requests++; InetSocketAddress address = transport.getAddress(); int old_limit = to_compare.limit(); int old_position = to_compare.position(); boolean ok = false; try{ byte[] head = new byte[3]; to_compare.get( head ); // note duplication of this in min-matches below if ( head[0] != 'G' || head[1] != 'E' || head[2] != 'T' ){ return( null ); } byte[] line_bytes = new byte[to_compare.remaining()]; to_compare.get( line_bytes ); try{ // format is GET url HTTP/1.1 String url = new String( line_bytes, "ISO-8859-1" ); int space = url.indexOf(' '); if ( space == -1 ){ return( null ); } // note that we don't insist on a full URL here, just the start of one url = url.substring( space + 1 ).trim(); if ( url.indexOf( "/index.html") != -1 ){ ok = true; return( new Object[]{ transport, getIndexPage() }); }else if ( url.indexOf( "/ping.html") != -1 ){ // ping is used for inbound HTTP port checking ok = true; return( new Object[]{ transport, getPingPage( url ) }); }else if ( url.indexOf( "/test503.html" ) != -1 ){ ok = true; return( new Object[]{ transport, getTest503()}); } String hash_str = null; int hash_pos = url.indexOf( "?info_hash=" ); if ( hash_pos != -1 ){ int hash_start = hash_pos + 11; int hash_end = url.indexOf( '&', hash_pos ); if ( hash_end == -1 ){ // not read the end yet return( null ); }else{ hash_str = url.substring( hash_start, hash_end ); } }else{ hash_pos = url.indexOf( "/files/" ); if ( hash_pos != -1 ){ int hash_start = hash_pos + 7; int hash_end = url.indexOf('/', hash_start ); if ( hash_end == -1 ){ // not read the end of the hash yet return( null ); }else{ hash_str = url.substring( hash_start, hash_end ); } } } if ( hash_str != null ){ byte[] hash = URLDecoder.decode( hash_str, "ISO-8859-1" ).getBytes( "ISO-8859-1" ); PeerManagerRegistration reg_data = PeerManager.getSingleton().manualMatchHash( address, hash ); if ( reg_data != null ){ // trim back URL as it currently has header in it too int pos = url.indexOf( ' ' ); String trimmed = pos==-1?url:url.substring(0,pos); ok = true; return( new Object[]{ trimmed, reg_data }); } }else{ int link_pos = url.indexOf( "/links/" ); if ( link_pos != -1 ){ int pos = url.indexOf( ' ', link_pos ); if ( pos == -1 ){ return( null ); } String link = url.substring(0,pos).substring( link_pos+7 ); link = URLDecoder.decode( link, "UTF-8" ); PeerManagerRegistration reg_data = PeerManager.getSingleton().manualMatchLink( address, link ); if ( reg_data != null ){ TOTorrentFile file = reg_data.getLink( link ); if ( file != null ){ StringBuffer target_url = new StringBuffer( 512 ); target_url.append( "/files/" ); target_url.append( URLEncoder.encode( new String( file.getTorrent().getHash(), "ISO-8859-1" ), "ISO-8859-1" )); byte[][] bits = file.getPathComponents(); for (int i=0;i 0 ){ transport.registerForWriteSelects( new TransportHelper.selectListener() { public boolean selectSuccess( TransportHelper helper, Object attachment ) { try{ int written = helper.write( bb, false ); if ( bb.remaining() > 0 ){ helper.registerForWriteSelects( this, null ); }else{ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "HTTP connection from " + connection.getEndpoint().getNotionalAddress() + " closed" )); } connection.close(); } return( written > 0 ); }catch( Throwable e ){ helper.cancelWriteSelects(); if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "HTTP connection from " + connection.getEndpoint().getNotionalAddress() + " failed to write error '" + data + "'" )); } connection.close(); return( false ); } } public void selectFailure( TransportHelper helper, Object attachment, Throwable msg) { helper.cancelWriteSelects(); if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "HTTP connection from " + connection.getEndpoint().getNotionalAddress() + " failed to write error '" + data + "'" )); } connection.close(); } }, null ); }else{ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "HTTP connection from " + connection.getEndpoint().getNotionalAddress() + " closed" )); } connection.close(); } }catch( Throwable e ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "HTTP connection from " + connection.getEndpoint().getNotionalAddress() + " failed to write error '" + data + "'" )); } connection.close(); } } public void addURLHandler( URLHandler handler ) { url_handlers.add( handler ); } public void removeURLHandler( URLHandler handler ) { url_handlers.remove( handler ); } public interface URLHandler { public boolean matches( String url ); public void handle( TransportHelper transport, String header_so_far ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnectionWebSeed.java0000644000175000017500000001360111220776674032730 0ustar adrianadrian/* * Created on 4 Oct 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.http; import java.io.IOException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.StringTokenizer; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.impl.PEPeerControl; import org.gudy.azureus2.core3.peer.impl.PEPeerTransport; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.networkmanager.NetworkConnection; public class HTTPNetworkConnectionWebSeed extends HTTPNetworkConnection { private boolean switching; protected HTTPNetworkConnectionWebSeed( HTTPNetworkManager _manager, NetworkConnection _connection, PEPeerTransport _peer ) { super( _manager, _connection, _peer ); } protected void decodeHeader( final HTTPMessageDecoder decoder, final String header ) throws IOException { if ( switching ){ Debug.out( "new header received while paused" ); throw( new IOException( "Bork" )); } if ( !isSeed()){ return; } PEPeerControl control = getPeerControl(); try{ int pos = header.indexOf( NL ); String line = header.substring(4,pos); pos = line.lastIndexOf( ' ' ); String url = line.substring( 0, pos ).trim(); pos = url.indexOf( '?' ); if ( pos != -1 ){ url = url.substring( pos+1 ); } StringTokenizer tok = new StringTokenizer( url, "&" ); int piece = -1; List ranges = new ArrayList(); while( tok.hasMoreElements()){ String token = tok.nextToken(); pos = token.indexOf('='); if ( pos != -1 ){ String lhs = token.substring(0,pos).toLowerCase( MessageText.LOCALE_ENGLISH ); String rhs = token.substring(pos+1); if ( lhs.equals( "info_hash" )){ final byte[] old_hash = control.getHash(); final byte[] new_hash = URLDecoder.decode( rhs, "ISO-8859-1" ).getBytes( "ISO-8859-1" ); if ( !Arrays.equals( new_hash, old_hash )){ switching = true; decoder.pauseInternally(); flushRequests( new flushListener() { private boolean triggered; public void flushed() { synchronized( this ){ if ( triggered ){ return; } triggered = true; } getManager().reRoute( HTTPNetworkConnectionWebSeed.this, old_hash, new_hash, header ); } }); return; } }else if ( lhs.equals( "piece" )){ try{ piece = Integer.parseInt( rhs ); }catch( Throwable e ){ throw( new IOException( "Invalid piece number '" + rhs +"'" )); } }else if ( lhs.equals( "ranges" )){ StringTokenizer range_tok = new StringTokenizer( rhs, "," ); while( range_tok.hasMoreTokens()){ String range = range_tok.nextToken(); int sep = range.indexOf( '-' ); if ( sep == -1 ){ throw( new IOException( "Invalid range specification '" + rhs + "'" )); } try{ ranges.add( new int[]{ Integer.parseInt( range.substring(0,sep)), Integer.parseInt( range.substring( sep+1 ))}); }catch( Throwable e ){ throw( new IOException( "Invalid range specification '" + rhs + "'" )); } } } } } if ( piece == -1 ){ throw( new IOException( "Piece number not specified" )); } boolean keep_alive = header.toLowerCase( MessageText.LOCALE_ENGLISH ).indexOf( "keep-alive" ) != -1; int this_piece_size = control.getPieceLength( piece ); if ( ranges.size() == 0 ){ ranges.add( new int[]{ 0, this_piece_size-1}); } long[] offsets = new long[ranges.size()]; long[] lengths = new long[ranges.size()]; long piece_offset = piece * control.getPieceLength(0); for (int i=0;i= this_piece_size || end < 0 || end >= this_piece_size || start > end ){ throw( new IOException( "Invalid range specification '" + start + "-" + end + "'" )); } offsets[i] = piece_offset + start; lengths[i] = ( end - start ) + 1; } addRequest( new httpRequest( offsets, lengths, 0, false, keep_alive )); }catch( Throwable e ){ Debug.outNoStack( "Decode of '" + (header.length()>128?(header.substring(0,128) + "..."):header) + "' - " + Debug.getNestedExceptionMessageAndStack(e)); if ( e instanceof IOException ){ throw((IOException)e); }else{ throw( new IOException( "Decode failed: " + Debug.getNestedExceptionMessage(e))); } } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/0000755000175000017500000000000011310377630024250 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualChannelSelectorImpl.java0000644000175000017500000006772211300347336032372 0ustar adrianadrian/* * Created on Jul 28, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.tcp; import java.nio.channels.*; import java.nio.channels.spi.AbstractSelectableChannel; import java.util.*; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector; /** * Provides a simplified and safe (selectable-channel) socket single-op selector. */ public class VirtualChannelSelectorImpl { private static final LogIDs LOGID = LogIDs.NWMAN; private static final boolean MAYBE_BROKEN_SELECT; static{ // freebsd 7.x and diablo 1.6 no works as selector returns none ready even though // there's a bunch readable // Seems to not just be diablo java, but general 7.1 problem String jvm_name = System.getProperty( "java.vm.name", "" ); boolean is_diablo = jvm_name.startsWith( "Diablo" ); boolean is_freebsd_7_or_higher = false; // hack for 10.6 - will switch to not doing System.setProperty( "java.nio.preferSelect", "true" ); later boolean is_osx_16 = false; try{ // unfortunately the package maintainer has set os.name to Linux for FreeBSD... if ( Constants.isFreeBSD || Constants.isLinux ){ String os_type = System.getenv( "OSTYPE" ); if ( os_type != null && os_type.equals( "FreeBSD" )){ String os_version = System.getProperty( "os.version", "" ); String digits = ""; for ( int i=0;i 0 ){ is_freebsd_7_or_higher = Integer.parseInt(digits) >= 7; } } }else if ( Constants.isOSX ){ String os_version = System.getProperty( "os.version", "" ); if ( os_version.startsWith( "10.6" )){ is_osx_16 = true; } } }catch( Throwable e ){ e.printStackTrace(); } MAYBE_BROKEN_SELECT = is_freebsd_7_or_higher || is_diablo || is_osx_16; if ( MAYBE_BROKEN_SELECT ){ System.out.println( "Enabling broken select detection: diablo=" + is_diablo + ", freebsd 7+=" + is_freebsd_7_or_higher + ", osx 10.6=" + is_osx_16 ); } } private boolean select_is_broken; private int select_looks_broken_count; private boolean logged_broken_select; /* static boolean rm_trace = false; static boolean rm_test_fix = false; static{ COConfigurationManager.addAndFireParameterListeners( new String[]{ "user.rm.trace", "user.rm.testfix" }, new ParameterListener() { public void parameterChanged( String parameterName) { rm_trace = COConfigurationManager.getBooleanParameter( "user.rm.trace", false ); rm_test_fix = COConfigurationManager.getBooleanParameter( "user.rm.testfix", false ); } }); } private long rm_flag_last_log; private Map rm_listener_map = new HashMap(); */ protected Selector selector; private final SelectorGuard selector_guard; private final LinkedList register_cancel_list = new LinkedList(); private final AEMonitor register_cancel_list_mon = new AEMonitor( "VirtualChannelSelector:RCL"); private final HashMap paused_states = new HashMap(); private final int INTEREST_OP; private final boolean pause_after_select; protected final VirtualChannelSelector parent; //private int[] select_counts = new int[ 50 ]; //private int round = 0; private volatile boolean destroyed; private boolean randomise_keys; private int next_select_loop_pos = 0; private static final int WRITE_SELECTOR_DEBUG_CHECK_PERIOD = 10000; private static final int WRITE_SELECTOR_DEBUG_MAX_TIME = 20000; private long last_write_select_debug; private long last_select_debug; public VirtualChannelSelectorImpl( VirtualChannelSelector _parent, int _interest_op, boolean _pause_after_select, boolean _randomise_keys ) { this.parent = _parent; INTEREST_OP = _interest_op; pause_after_select = _pause_after_select; randomise_keys = _randomise_keys; String type; switch( INTEREST_OP ) { case VirtualChannelSelector.OP_CONNECT: type = "OP_CONNECT"; break; case VirtualChannelSelector.OP_READ: type = "OP_READ"; break; default: type = "OP_WRITE"; break; } selector_guard = new SelectorGuard( type, new SelectorGuard.GuardListener() { public boolean safeModeSelectEnabled() { return parent.isSafeSelectionModeEnabled(); } public void spinDetected() { closeExistingSelector(); try { Thread.sleep( 1000 ); }catch( Throwable x ) {x.printStackTrace();} parent.enableSafeSelectionMode(); } public void failureDetected() { try { Thread.sleep( 10000 ); }catch( Throwable x ) {x.printStackTrace();} closeExistingSelector(); try { Thread.sleep( 1000 ); }catch( Throwable x ) {x.printStackTrace();} selector = openNewSelector(); } }); selector = openNewSelector(); } protected Selector openNewSelector() { Selector sel = null; try { sel = Selector.open(); AEDiagnostics.logWithStack( "seltrace", "Selector created for '" + parent.getName() + "'," + selector_guard.getType()); } catch (Throwable t) { Debug.out( "ERROR: caught exception on Selector.open()", t ); try { Thread.sleep( 3000 ); }catch( Throwable x ) {x.printStackTrace();} int fail_count = 1; while( fail_count < 10 ) { try { sel = Selector.open(); AEDiagnostics.logWithStack( "seltrace", "Selector created for '" + parent.getName() + "'," + selector_guard.getType()); break; } catch( Throwable f ) { Debug.out( f ); fail_count++; try { Thread.sleep( 3000 ); }catch( Throwable x ) {x.printStackTrace();} } } if( fail_count < 10 ) { //success ! Debug.out( "NOTICE: socket Selector successfully opened after " +fail_count+ " failures." ); } else { //failure Logger.log(new LogAlert(LogAlert.REPEATABLE, LogAlert.AT_ERROR, "ERROR: socket Selector.open() failed 10 times in a row, aborting." + "\nAzureus / Java is likely being firewalled!")); } } return sel; } public void setRandomiseKeys( boolean r ) { randomise_keys = r; } public void pauseSelects( AbstractSelectableChannel channel ) { //System.out.println( "pauseSelects: " + channel + " - " + Debug.getCompressedStackTrace() ); if( channel == null ) { return; } SelectionKey key = channel.keyFor( selector ); if( key != null && key.isValid() ) { key.interestOps( key.interestOps() & ~INTEREST_OP ); } else { //channel not (yet?) registered if( channel.isOpen() ) { //only bother if channel has not already been closed try{ register_cancel_list_mon.enter(); paused_states.put( channel, new Boolean( true ) ); //ensure the op is paused upon reg select-time reg } finally{ register_cancel_list_mon.exit(); } } } } public void resumeSelects( AbstractSelectableChannel channel ) { //System.out.println( "resumeSelects: " + channel + " - " + Debug.getCompressedStackTrace() ); if( channel == null ) { Debug.printStackTrace( new Exception( "resumeSelects():: channel == null" ) ); return; } SelectionKey key = channel.keyFor( selector ); if( key != null && key.isValid() ) { // if we're resuming a non-interested key then reset the metrics if (( key.interestOps() & INTEREST_OP ) == 0 ){ RegistrationData data = (RegistrationData)key.attachment(); data.last_select_success_time = SystemTime.getCurrentTime(); data.non_progress_count = 0; } key.interestOps( key.interestOps() | INTEREST_OP ); } else { //channel not (yet?) registered try{ register_cancel_list_mon.enter(); paused_states.remove( channel ); //check if the channel's op has been already paused before select-time reg } finally{ register_cancel_list_mon.exit(); } } //try{ // selector.wakeup(); //} //catch( Throwable t ) { Debug.out( "selector.wakeup():: caught exception: ", t ); } } public void cancel( AbstractSelectableChannel channel ) { //System.out.println( "cancel: " + channel + " - " + Debug.getCompressedStackTrace() ); if ( destroyed ){ // don't worry too much about cancels } if ( channel == null ){ Debug.out( "Attempt to cancel selects for null channel" ); return; } try{ register_cancel_list_mon.enter(); // ensure that there's only one operation outstanding for a given channel // at any one time (the latest operation requested ) for (Iterator it = register_cancel_list.iterator();it.hasNext();){ Object obj = it.next(); if ( channel == obj || ( obj instanceof RegistrationData && ((RegistrationData)obj).channel == channel )){ // remove existing cancel or register it.remove(); break; } } pauseSelects((AbstractSelectableChannel)channel ); register_cancel_list.add( channel ); }finally{ register_cancel_list_mon.exit(); } } public void register( AbstractSelectableChannel channel, VirtualChannelSelector.VirtualAbstractSelectorListener listener, Object attachment ) { if ( destroyed ){ Debug.out( "register called after selector destroyed" ); } if ( channel == null ){ Debug.out( "Attempt to register selects for null channel" ); return; } try{ register_cancel_list_mon.enter(); // ensure that there's only one operation outstanding for a given channel // at any one time (the latest operation requested ) for (Iterator it = register_cancel_list.iterator();it.hasNext();){ Object obj = it.next(); if ( channel == obj || ( obj instanceof RegistrationData && ((RegistrationData)obj).channel == channel )){ it.remove(); break; } } paused_states.remove( channel ); register_cancel_list.add( new RegistrationData( channel, listener, attachment )); }finally{ register_cancel_list_mon.exit(); } } public int select( long timeout ) { long select_start_time = SystemTime.getCurrentTime(); if( selector == null ) { Debug.out( "VirtualChannelSelector.select() op called with null selector" ); try { Thread.sleep( 3000 ); }catch( Throwable x ) {x.printStackTrace();} return 0; } if( !selector.isOpen()) { Debug.out( "VirtualChannelSelector.select() op called with closed selector" ); try { Thread.sleep( 3000 ); }catch( Throwable x ) {x.printStackTrace();} return 0; } // store these when they occur so they can be raised *outside* of the monitor to avoid // potential deadlocks RegistrationData select_fail_data = null; Throwable select_fail_excep = null; //process cancellations try { register_cancel_list_mon.enter(); // don't use an iterator here as it is possible that error notifications to listeners // can result in the addition of a cancel request. // Note that this can only happen for registrations, and this *should* only result in // possibly a cancel being added (i.e. not a further registration), hence this can't // loop. Also note the approach of removing the entry before processing. This is so // that the logic used when adding a cancel (the removal of any matching entries) does // not cause the entry we're processing to be removed while( register_cancel_list.size() > 0 ){ Object obj = register_cancel_list.remove(0); if ( obj instanceof AbstractSelectableChannel ){ // process cancellation AbstractSelectableChannel canceled_channel = (AbstractSelectableChannel)obj; try{ SelectionKey key = canceled_channel.keyFor( selector ); if( key != null ){ key.cancel(); //cancel the key, since already registered } }catch( Throwable e ){ Debug.printStackTrace(e); } }else{ //process new registrations RegistrationData data = (RegistrationData)obj; if( data == null ) { Debug.out( "data == null" ); } else if( data.channel == null ) { Debug.out( "data.channel == null" ); } try { if( data.channel.isOpen() ){ // see if already registered SelectionKey key = data.channel.keyFor( selector ); if ( key != null && key.isValid() ) { //already registered key.attach( data ); key.interestOps( key.interestOps() | INTEREST_OP ); //ensure op is enabled } else{ data.channel.register( selector, INTEREST_OP, data ); } //check if op has been paused before registration moment Object paused = paused_states.get( data.channel ); if( paused != null ) { pauseSelects( data.channel ); //pause it } } else{ select_fail_data = data; select_fail_excep = new Throwable( "select registration: channel is closed" ); } }catch (Throwable t){ Debug.printStackTrace(t); select_fail_data = data; select_fail_excep = t; } } } paused_states.clear(); //reset after every registration round }finally { register_cancel_list_mon.exit(); } if ( select_fail_data != null ){ try{ parent.selectFailure( select_fail_data.listener, select_fail_data.channel, select_fail_data.attachment, select_fail_excep ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } //do the actual select int count = 0; selector_guard.markPreSelectTime(); try { count = selector.select( timeout ); } catch (Throwable t) { long now = SystemTime.getCurrentTime(); if ( last_select_debug > now || now - last_select_debug > 5000 ){ last_select_debug = now; Debug.out( "Caught exception on selector.select() op: " +t.getMessage(), t ); } try { Thread.sleep( timeout ); }catch(Throwable e) { e.printStackTrace(); } } // do this after the select so that any pending cancels (prior to destroy) are processed // by the selector before we kill it if ( destroyed ){ closeExistingSelector(); return( 0 ); } if ( MAYBE_BROKEN_SELECT && !select_is_broken && ( INTEREST_OP == VirtualChannelSelector.OP_READ || INTEREST_OP == VirtualChannelSelector.OP_WRITE )){ if ( selector.selectedKeys().size() == 0 ){ Set keys = selector.keys(); for ( SelectionKey key: keys ){ if (( key.readyOps() & INTEREST_OP ) != 0 ){ select_looks_broken_count++; break; } } if ( select_looks_broken_count >= 5 ){ select_is_broken = true; if ( !logged_broken_select ){ logged_broken_select = true; Debug.outNoStack( "Select operation looks broken, trying workaround" ); } } }else{ select_looks_broken_count = 0; } } /* if( INTEREST_OP == VirtualChannelSelector.OP_READ ) { //TODO select_counts[ round ] = count; round++; if( round == select_counts.length ) { StringBuffer buf = new StringBuffer( select_counts.length * 3 ); buf.append( "select_counts=" ); for( int i=0; i < select_counts.length; i++ ) { buf.append( select_counts[i] ); buf.append( ' ' ); } //System.out.println( buf.toString() ); round = 0; } } */ selector_guard.verifySelectorIntegrity( count, SystemTime.TIME_GRANULARITY_MILLIS /2 ); if( !selector.isOpen() ) return count; int progress_made_key_count = 0; int total_key_count = 0; long now = SystemTime.getCurrentTime(); //notification of ready keys via listener callback // debug handling for channels stuck pending write select for long periods Set non_selected_keys = null; if ( INTEREST_OP == VirtualChannelSelector.OP_WRITE ){ if ( now < last_write_select_debug || now - last_write_select_debug > WRITE_SELECTOR_DEBUG_CHECK_PERIOD ){ last_write_select_debug = now; non_selected_keys = new HashSet( selector.keys()); } } List ready_keys; if ( MAYBE_BROKEN_SELECT && select_is_broken ){ Set all_keys = selector.keys(); ready_keys = new ArrayList(); for ( SelectionKey key: all_keys ){ if (( key.readyOps() & INTEREST_OP ) != 0 ){ ready_keys.add( key ); } } }else{ ready_keys = new ArrayList( selector.selectedKeys()); } boolean randy = randomise_keys; if ( randy ){ Collections.shuffle( ready_keys ); } Set selected_keys = selector.selectedKeys(); final int ready_key_size = ready_keys.size();; final int start_pos = next_select_loop_pos++; final int end_pos = start_pos + ready_key_size; for ( int i=start_pos; i 0 ){ Debug.out( "VirtualChannelSelector: No progress for op " + INTEREST_OP + ": listener = " + data.listener.getClass() + ", count = " + data.non_progress_count + ", socket: open = " + data.channel.isOpen() + (INTEREST_OP==VirtualChannelSelector.OP_ACCEPT?"": (", connected = " + ((SocketChannel)data.channel).isConnected()))); if ( data.non_progress_count == 1000 ){ Debug.out( "No progress for " + data.non_progress_count + ", closing connection" ); try{ data.channel.close(); }catch( Throwable e ){ e.printStackTrace(); } } } } } }else{ // rm_type = 3; key.cancel(); parent.selectFailure( data.listener, data.channel, data.attachment, new Throwable( "key is invalid" ) ); // can get this if socket has been closed between select and here } /* if ( rm_trace ){ Object rm_key = data.listener.getClass(); int[] rm_count = (int[])rm_listener_map.get( rm_key ); if ( rm_count == null ){ rm_count = new int[]{0,0,0,0}; rm_listener_map.put( rm_key, rm_count ); } rm_count[rm_type]++; } */ } if ( non_selected_keys != null ){ for( Iterator i = non_selected_keys.iterator(); i.hasNext(); ) { SelectionKey key = i.next(); RegistrationData data = (RegistrationData)key.attachment(); if (( key.interestOps() & INTEREST_OP) == 0 ) { continue; } long stall_time = now - data.last_select_success_time; if ( stall_time < 0 ){ data.last_select_success_time = now; }else{ if ( stall_time > WRITE_SELECTOR_DEBUG_MAX_TIME ){ Logger.log( new LogEvent(LOGID,LogEvent.LT_WARNING,"Write select for " + key.channel() + " stalled for " + stall_time )); // hack - trigger a dummy write select to see if things are still OK if( key.isValid() ) { if( pause_after_select ) { key.interestOps( key.interestOps() & ~INTEREST_OP ); } if ( parent.selectSuccess( data.listener, data.channel, data.attachment )){ data.non_progress_count = 0; } }else{ key.cancel(); parent.selectFailure( data.listener, data.channel, data.attachment, new Throwable( "key is invalid" ) ); } } } } } // if any of the ready keys hasn't made any progress then enforce minimum sleep period to avoid // spinning if ( total_key_count == 0 || progress_made_key_count != total_key_count ){ long time_diff = SystemTime.getCurrentTime() - select_start_time; if( time_diff < timeout && time_diff >= 0 ) { //ensure that it always takes at least 'timeout' time to complete the select op try { Thread.sleep( timeout - time_diff ); }catch(Throwable e) { e.printStackTrace(); } } }else{ /* if ( rm_test_fix ){ long time_diff = SystemTime.getCurrentTime() - select_start_time; if( time_diff < 10 && time_diff >= 0 ) { try { Thread.sleep( 10 - time_diff ); }catch(Throwable e) { e.printStackTrace(); } } } */ } /* if ( rm_trace ){ if ( select_start_time - rm_flag_last_log > 10000 ){ rm_flag_last_log = select_start_time; Iterator it = rm_listener_map.entrySet().iterator(); String str = ""; while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); Class cla = (Class)entry.getKey(); String name = cla.getName(); int pos = name.lastIndexOf('.'); name = name.substring( pos+1 ); int[] counts = (int[])entry.getValue(); str += (str.length()==0?"":",")+ name + ":" + counts[0]+"/"+counts[1]+"/"+counts[2]+"/"+counts[3]; } Debug.outNoStack( "RM trace: " + hashCode() + ": op=" + INTEREST_OP + "-" + str ); } } */ return count; } /** * Note that you have to ensure that a select operation is performed on the normal select * loop *after* destroying the selector to actually cause the destroy to occur */ public void destroy() { destroyed = true; } protected void closeExistingSelector() { for( Iterator i = selector.keys().iterator(); i.hasNext(); ) { SelectionKey key = i.next(); RegistrationData data = (RegistrationData)key.attachment(); parent.selectFailure(data.listener, data.channel, data.attachment, new Throwable( "selector destroyed" ) ); } try{ selector.close(); AEDiagnostics.log( "seltrace", "Selector destroyed for '" + parent.getName() + "'," + selector_guard.getType()); } catch( Throwable t ) { t.printStackTrace(); } } private static class RegistrationData { protected final AbstractSelectableChannel channel; protected final VirtualChannelSelector.VirtualAbstractSelectorListener listener; protected final Object attachment; protected int non_progress_count; protected long last_select_success_time; private RegistrationData( AbstractSelectableChannel _channel, VirtualChannelSelector.VirtualAbstractSelectorListener _listener, Object _attachment ) { channel = _channel; listener = _listener; attachment = _attachment; last_select_success_time = SystemTime.getCurrentTime(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPNetworkManager.java0000644000175000017500000002215111046460116030405 0ustar adrianadrian/* * Created on 21 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.tcp; import java.net.InetAddress; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector; import com.aelitis.azureus.core.stats.AzureusCoreStats; import com.aelitis.azureus.core.stats.AzureusCoreStatsProvider; public class TCPNetworkManager { private static int WRITE_SELECT_LOOP_TIME = 25; private static int WRITE_SELECT_MIN_LOOP_TIME = 0; private static int READ_SELECT_LOOP_TIME = 25; private static int READ_SELECT_MIN_LOOP_TIME = 0; protected static int tcp_mss_size; private static final TCPNetworkManager instance = new TCPNetworkManager(); public static TCPNetworkManager getSingleton(){ return( instance ); } public static boolean TCP_INCOMING_ENABLED; public static boolean TCP_OUTGOING_ENABLED; static{ COConfigurationManager.addAndFireParameterListener( "TCP.Listen.Port.Enable", new ParameterListener() { public void parameterChanged( String name ) { TCP_INCOMING_ENABLED = TCP_OUTGOING_ENABLED = COConfigurationManager.getBooleanParameter( name ); } }); COConfigurationManager.addAndFireParameterListeners( new String[]{ "network.tcp.read.select.time", "network.tcp.read.select.min.time", "network.tcp.write.select.time", "network.tcp.write.select.min.time", }, new ParameterListener() { public void parameterChanged( String name ) { WRITE_SELECT_LOOP_TIME = COConfigurationManager.getIntParameter( "network.tcp.write.select.time" ); WRITE_SELECT_MIN_LOOP_TIME = COConfigurationManager.getIntParameter( "network.tcp.write.select.min.time" ); READ_SELECT_LOOP_TIME = COConfigurationManager.getIntParameter( "network.tcp.read.select.time" ); READ_SELECT_MIN_LOOP_TIME = COConfigurationManager.getIntParameter( "network.tcp.read.select.min.time" ); } }); } /** * Get the configured TCP MSS (Maximum Segment Size) unit, i.e. the max (preferred) packet payload size. * NOTE: MSS is MTU-40bytes for TCPIP headers, usually 1460 (1500-40) for standard ethernet * connections, or 1452 (1492-40) for PPPOE connections. * @return mss size in bytes */ public static int getTcpMssSize() { return tcp_mss_size; } public static void refreshRates( int min_rate ) { tcp_mss_size = COConfigurationManager.getIntParameter( "network.tcp.mtu.size" ) - 40; if( tcp_mss_size > min_rate ) tcp_mss_size = min_rate - 1; if( tcp_mss_size < 512 ) tcp_mss_size = 512; } private final VirtualChannelSelector read_selector = new VirtualChannelSelector( "TCP network manager", VirtualChannelSelector.OP_READ, true ); private final VirtualChannelSelector write_selector = new VirtualChannelSelector( "TCP network manager", VirtualChannelSelector.OP_WRITE, true ); private final TCPConnectionManager connect_disconnect_manager = new TCPConnectionManager(); private final IncomingSocketChannelManager incoming_socketchannel_manager = new IncomingSocketChannelManager( "TCP.Listen.Port", "TCP.Listen.Port.Enable" ); private long read_select_count; private long write_select_count; protected TCPNetworkManager() { Set types = new HashSet(); types.add( AzureusCoreStats.ST_NET_TCP_SELECT_READ_COUNT ); types.add( AzureusCoreStats.ST_NET_TCP_SELECT_WRITE_COUNT ); AzureusCoreStats.registerProvider( types, new AzureusCoreStatsProvider() { public void updateStats( Set types, Map values ) { if ( types.contains( AzureusCoreStats.ST_NET_TCP_SELECT_READ_COUNT )){ values.put( AzureusCoreStats.ST_NET_TCP_SELECT_READ_COUNT, new Long( read_select_count )); } if ( types.contains( AzureusCoreStats.ST_NET_TCP_SELECT_WRITE_COUNT )){ values.put( AzureusCoreStats.ST_NET_TCP_SELECT_WRITE_COUNT, new Long( write_select_count )); } } }); //start read selector processing AEThread2 read_selector_thread = new AEThread2( "ReadController:ReadSelector", true ) { public void run() { while( true ) { try{ if ( READ_SELECT_MIN_LOOP_TIME > 0 ){ long start = SystemTime.getHighPrecisionCounter(); read_selector.select( READ_SELECT_LOOP_TIME ); long duration = SystemTime.getHighPrecisionCounter() - start; duration = duration/1000000; long sleep = READ_SELECT_MIN_LOOP_TIME - duration; if ( sleep > 0 ){ try{ Thread.sleep( sleep ); }catch( Throwable e ){ } } }else{ read_selector.select( READ_SELECT_LOOP_TIME ); } read_select_count++; }catch( Throwable t ) { Debug.out( "readSelectorLoop() EXCEPTION: ", t ); } } } }; read_selector_thread.setPriority( Thread.MAX_PRIORITY - 2 ); read_selector_thread.start(); //start write selector processing AEThread2 write_selector_thread = new AEThread2( "WriteController:WriteSelector", true ) { public void run() { while( true ){ try{ if ( WRITE_SELECT_MIN_LOOP_TIME > 0 ){ long start = SystemTime.getHighPrecisionCounter(); write_selector.select( WRITE_SELECT_LOOP_TIME ); long duration = SystemTime.getHighPrecisionCounter() - start; duration = duration/1000000; long sleep = WRITE_SELECT_MIN_LOOP_TIME - duration; if ( sleep > 0 ){ try{ Thread.sleep( sleep ); }catch( Throwable e ){ } } }else{ write_selector.select( WRITE_SELECT_LOOP_TIME ); write_select_count++; } }catch( Throwable t ) { Debug.out( "writeSelectorLoop() EXCEPTION: ", t ); } } } }; write_selector_thread.setPriority( Thread.MAX_PRIORITY - 2 ); write_selector_thread.start(); } public void setExplicitBindAddress( InetAddress address ) { incoming_socketchannel_manager.setExplicitBindAddress( address ); } public void clearExplicitBindAddress() { incoming_socketchannel_manager.clearExplicitBindAddress(); } public boolean isEffectiveBindAddress( InetAddress address ) { return( incoming_socketchannel_manager.isEffectiveBindAddress( address )); } /** * Get the socket channel connect / disconnect manager. * @return connect manager */ public TCPConnectionManager getConnectDisconnectManager() { return connect_disconnect_manager; } /** * Get the virtual selector used for socket channel read readiness. * @return read readiness selector */ public VirtualChannelSelector getReadSelector() { return read_selector; } /** * Get the virtual selector used for socket channel write readiness. * @return write readiness selector */ public VirtualChannelSelector getWriteSelector() { return write_selector; } public boolean isTCPListenerEnabled() { return( incoming_socketchannel_manager.isEnabled()); } /** * Get port that the TCP server socket is listening for incoming connections on. * @return port number */ public int getTCPListeningPortNumber() { return( incoming_socketchannel_manager.getTCPListeningPortNumber()); } public long getLastIncomingNonLocalConnectionTime() { return( incoming_socketchannel_manager.getLastNonLocalConnectionTime()); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/SelectorGuard.java0000644000175000017500000001327210665542732027674 0ustar adrianadrian/* * Created on Jul 28, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.tcp; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; /** * Temp class designed to help detect Selector anomalies and cleanly re-open if necessary. * * NOTE: * As of JVM 1.4.2_03, after network connection disconnect/reconnect, usually-blocking * select() and select(long) calls no longer block, and will instead return immediately. * This can cause selector spinning and 100% cpu usage. * See: * http://forum.java.sun.com/thread.jsp?forum=4&thread=293213 * http://developer.java.sun.com/developer/bugParade/bugs/4850373.html * http://developer.java.sun.com/developer/bugParade/bugs/4881228.html * Fixed in JVM 1.4.2_05+ and 1.5b2+ */ public class SelectorGuard { private static final int SELECTOR_SPIN_THRESHOLD = 200; private static final int SELECTOR_FAILURE_THRESHOLD = 10000; private static final int MAX_IGNORES = 5; private boolean marked = false; private int consecutiveZeroSelects = 0; private long beforeSelectTime; private long select_op_time; private final String type; private final GuardListener listener; private int ignores = 0; /** * Create a new SelectorGuard with the given failed count threshold. */ public SelectorGuard( String _type, GuardListener _listener ) { this.type = _type; this.listener = _listener; } public String getType() { return( type ); } /** * Run this method right before the select() operation to * mark the start time. */ public void markPreSelectTime() { beforeSelectTime = SystemTime.getCurrentTime(); marked = true; } /** * Checks whether selector is still OK, and not spinning. */ public void verifySelectorIntegrity( int num_keys_ready, long time_threshold ) { if( num_keys_ready > 0 ) { //non-zero select, so OK ignores++; if( ignores > MAX_IGNORES ) { //allow MAX_IGNORES / SELECTOR_SPIN_THRESHOLD to be successful select ops and still trigger a spin alert ignores = 0; consecutiveZeroSelects = 0; } return; } if (marked) marked = false; else Debug.out("Error: You must run markPreSelectTime() before calling isSelectorOK"); select_op_time = SystemTime.getCurrentTime() - beforeSelectTime; if( select_op_time > time_threshold || select_op_time < 0 ) { //zero-select, but over the time threshold, so OK consecutiveZeroSelects = 0; return; } //if we've gotten here, then we have a potential selector anomalie consecutiveZeroSelects++; if( consecutiveZeroSelects % 20 == 0 && Constants.isWindows ) { // getting triggered with 20 +_ sometimes 40 due to general high CPU usage if ( consecutiveZeroSelects > 40 ){ Debug.out( "consecutiveZeroSelects=" +consecutiveZeroSelects ); } } if( consecutiveZeroSelects > SELECTOR_SPIN_THRESHOLD ) { if( Constants.isWindows && (Constants.JAVA_VERSION.startsWith("1.4") || Constants.JAVA_VERSION.startsWith("1.5"))) { //Under windows, it seems that selector spin can sometimes appear when >63 socket channels are registered with a selector //Should be fixed in later 1.5, but play it safe and assume 1.6 or newer only. if( !listener.safeModeSelectEnabled() ) { String msg = "Likely faulty socket selector detected: reverting to safe-mode socket selection. [JRE " +Constants.JAVA_VERSION+"]\n"; msg += "Please see " +Constants.AZUREUS_WIKI+ "LikelyFaultySocketSelector for help."; Debug.out( msg ); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_WARNING, msg)); consecutiveZeroSelects = 0; listener.spinDetected(); return; } } else { //under linux, it seems that selector spin is somewhat common, but normal??? behavior, so just sleep a bit consecutiveZeroSelects = 0; try{ Thread.sleep( 50 ); }catch( Throwable t) {t.printStackTrace();} return; } } if( consecutiveZeroSelects > SELECTOR_FAILURE_THRESHOLD ) { //should only happen under Windows + JRE 1.4 String msg = "Likely network disconnect/reconnect: Repairing socket channel selector. [JRE " +Constants.JAVA_VERSION+"]\n"; msg += "Please see " +Constants.AZUREUS_WIKI+ "LikelyNetworkDisconnectReconnect for help."; Debug.out( msg ); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_WARNING, msg)); consecutiveZeroSelects = 0; listener.failureDetected(); return; } //not yet over the count threshold } public interface GuardListener { public boolean safeModeSelectEnabled(); public void spinDetected(); public void failureDetected(); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/TransportEndpointTCP.java0000644000175000017500000000302610446362572031170 0ustar adrianadrian/* * Created on 16 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.tcp; import java.nio.channels.SocketChannel; import com.aelitis.azureus.core.networkmanager.ProtocolEndpoint; import com.aelitis.azureus.core.networkmanager.TransportEndpoint; public class TransportEndpointTCP implements TransportEndpoint { private ProtocolEndpoint pe; private SocketChannel sc; public TransportEndpointTCP( ProtocolEndpoint _pe, SocketChannel _sc ) { pe = _pe; sc = _sc; } public ProtocolEndpoint getProtocolEndpoint() { return( pe ); } public SocketChannel getSocketChannel() { return( sc ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportImpl.java0000644000175000017500000003235611027643026030311 0ustar adrianadrian/* * Created on May 8, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.tcp; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.*; import com.aelitis.azureus.core.networkmanager.impl.ProtocolDecoder; import com.aelitis.azureus.core.networkmanager.impl.TransportHelperFilter; import com.aelitis.azureus.core.networkmanager.impl.TransportCryptoManager; import com.aelitis.azureus.core.networkmanager.impl.TransportHelper; import com.aelitis.azureus.core.networkmanager.impl.TransportImpl; /** * Represents a peer TCP transport connection (eg. a network socket). */ public class TCPTransportImpl extends TransportImpl implements Transport { private static final LogIDs LOGID = LogIDs.NET; protected ProtocolEndpointTCP protocol_endpoint; private TCPConnectionManager.ConnectListener connect_request_key = null; private String description = ""; private final boolean is_inbound_connection; private int transport_mode = TRANSPORT_MODE_NORMAL; public volatile boolean has_been_closed = false; private boolean connect_with_crypto; private byte[][] shared_secrets; private int fallback_count; private final boolean fallback_allowed; /** * Constructor for disconnected (outbound) transport. */ public TCPTransportImpl( ProtocolEndpointTCP endpoint, boolean use_crypto, boolean allow_fallback, byte[][] _shared_secrets ) { protocol_endpoint = endpoint; is_inbound_connection = false; connect_with_crypto = use_crypto; shared_secrets = _shared_secrets; fallback_allowed = allow_fallback; } /** * Constructor for connected (inbound) transport. * @param channel connection * @param already_read bytes from the channel */ public TCPTransportImpl( ProtocolEndpointTCP endpoint, TransportHelperFilter filter ) { protocol_endpoint = endpoint; setFilter( filter ); is_inbound_connection = true; connect_with_crypto = false; //inbound connections will automatically be using crypto if necessary fallback_allowed = false; description = ( is_inbound_connection ? "R" : "L" ) + ": " + getSocketChannel().socket().getInetAddress().getHostAddress() + ": " + getSocketChannel().socket().getPort(); } /** * Get the socket channel used by the transport. * @return the socket channel */ public SocketChannel getSocketChannel() { TransportHelperFilter filter = getFilter(); if (filter == null) { return null; } TCPTransportHelper helper = (TCPTransportHelper)filter.getHelper(); if (helper == null) { return null; } return helper.getSocketChannel(); } public TransportEndpoint getTransportEndpoint() { return( new TransportEndpointTCP( protocol_endpoint, getSocketChannel())); } public int getMssSize() { return( TCPNetworkManager.getTcpMssSize()); } public boolean isTCP() { return( true ); } /** * Get a textual description for this transport. * @return description */ public String getDescription() { return description; } /** * Request the transport connection be established. * NOTE: Will automatically connect via configured proxy if necessary. * @param address remote peer address to connect to * @param listener establishment failure/success listener */ public void connectOutbound( final ByteBuffer initial_data, final ConnectListener listener, final int priority ) { if ( !TCPNetworkManager.TCP_OUTGOING_ENABLED ){ listener.connectFailure( new Throwable( "Outbound TCP connections disabled" )); return; } if( has_been_closed ) return; if( getFilter() != null ) { //already connected Debug.out( "socket_channel != null" ); listener.connectSuccess( this, initial_data ); return; } final boolean use_proxy = COConfigurationManager.getBooleanParameter( "Proxy.Data.Enable" ); final TCPTransportImpl transport_instance = this; final InetSocketAddress address = protocol_endpoint.getAddress(); TCPConnectionManager.ConnectListener connect_listener = new TCPConnectionManager.ConnectListener() { public void connectAttemptStarted() { listener.connectAttemptStarted(); } public void connectSuccess( final SocketChannel channel ) { if( channel == null ) { String msg = "connectSuccess:: given channel == null"; Debug.out( msg ); listener.connectFailure( new Exception( msg ) ); return; } if( has_been_closed ) { //closed between select ops TCPNetworkManager.getSingleton().getConnectDisconnectManager().closeConnection( channel ); //just close it return; } connect_request_key = null; description = ( is_inbound_connection ? "R" : "L" ) + ": " + channel.socket().getInetAddress().getHostAddress() + ": " + channel.socket().getPort(); if( use_proxy ) { //proxy server connection established, login if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID,"Socket connection established to proxy server [" +description+ "], login initiated...")); // set up a transparent filter for socks negotiation setFilter( TCPTransportHelperFilterFactory.createTransparentFilter( channel )); new ProxyLoginHandler( transport_instance, address, new ProxyLoginHandler.ProxyListener() { public void connectSuccess() { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Proxy [" +description+ "] login successful." )); handleCrypto( address, channel, initial_data, priority, listener ); } public void connectFailure( Throwable failure_msg ) { close( "Proxy login failed" ); listener.connectFailure( failure_msg ); } }); } else { //direct connection established, notify handleCrypto( address, channel, initial_data, priority, listener ); } } public void connectFailure( Throwable failure_msg ) { connect_request_key = null; listener.connectFailure( failure_msg ); } }; connect_request_key = connect_listener; InetSocketAddress to_connect = use_proxy ? ProxyLoginHandler.DEFAULT_SOCKS_SERVER_ADDRESS : address; TCPNetworkManager.getSingleton().getConnectDisconnectManager().requestNewConnection( to_connect, connect_listener, priority ); } protected void handleCrypto( final InetSocketAddress address, final SocketChannel channel, final ByteBuffer initial_data, final int priority, final ConnectListener listener ) { if( connect_with_crypto ) { //attempt encrypted transport final TransportHelper helper = new TCPTransportHelper( channel ); TransportCryptoManager.getSingleton().manageCrypto( helper, shared_secrets, false, initial_data, new TransportCryptoManager.HandshakeListener() { public void handshakeSuccess( ProtocolDecoder decoder, ByteBuffer remaining_initial_data ) { //System.out.println( description+ " | crypto handshake success [" +_filter.getName()+ "]" ); TransportHelperFilter filter = decoder.getFilter(); setFilter( filter ); if ( Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Outgoing TCP stream to " + channel.socket().getRemoteSocketAddress() + " established, type = " + filter.getName(false))); } connectedOutbound( remaining_initial_data, listener ); } public void handshakeFailure( Throwable failure_msg ) { if( fallback_allowed && NetworkManager.OUTGOING_HANDSHAKE_FALLBACK_ALLOWED && !has_been_closed ) { if( Logger.isEnabled() ) Logger.log(new LogEvent(LOGID, description+ " | crypto handshake failure [" +failure_msg.getMessage()+ "], attempting non-crypto fallback." )); connect_with_crypto = false; fallback_count++; close( helper, "Handshake failure and retry" ); has_been_closed = false; if ( initial_data != null ){ initial_data.position( 0 ); } connectOutbound( initial_data, listener, priority ); } else { close( helper, "Handshake failure" ); listener.connectFailure( failure_msg ); } } public void gotSecret( byte[] session_secret ) { } public int getMaximumPlainHeaderLength() { throw( new RuntimeException()); // this is outgoing } public int matchPlainHeader( ByteBuffer buffer ) { throw( new RuntimeException()); // this is outgoing } }); } else { //no crypto //if( fallback_count > 0 ) { // System.out.println( channel.socket()+ " | non-crypto fallback successful!" ); //} setFilter( TCPTransportHelperFilterFactory.createTransparentFilter( channel )); if ( Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Outgoing TCP stream to " + channel.socket().getRemoteSocketAddress() + " established, type = " + getFilter().getName(false) + ", fallback = " + (fallback_count==0?"no":"yes" ))); } connectedOutbound( initial_data, listener ); } } private void setTransportBuffersSize( int size_in_bytes ) { if( getFilter() == null ) { Debug.out( "socket_channel == null" ); return; } try{ SocketChannel channel = getSocketChannel(); channel.socket().setSendBufferSize( size_in_bytes ); channel.socket().setReceiveBufferSize( size_in_bytes ); int snd_real = channel.socket().getSendBufferSize(); int rcv_real = channel.socket().getReceiveBufferSize(); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Setting new transport [" + description + "] buffer sizes: SND=" + size_in_bytes + " [" + snd_real + "] , RCV=" + size_in_bytes + " [" + rcv_real + "]")); } catch( Throwable t ) { Debug.out( t ); } } /** * Set the transport to the given speed mode. * @param mode to change to */ public void setTransportMode( int mode ) { if( mode == transport_mode ) return; //already in mode switch( mode ) { case TRANSPORT_MODE_NORMAL: setTransportBuffersSize( 8 * 1024 ); break; case TRANSPORT_MODE_FAST: setTransportBuffersSize( 64 * 1024 ); break; case TRANSPORT_MODE_TURBO: setTransportBuffersSize( 512 * 1024 ); break; default: Debug.out( "invalid transport mode given: " +mode ); } transport_mode = mode; } protected void connectedOutbound( ByteBuffer remaining_initial_data, ConnectListener listener ) { if ( has_been_closed ){ TransportHelperFilter filter = getFilter(); if ( filter != null ){ filter.getHelper().close( "Connection closed" ); setFilter( null ); } listener.connectFailure( new Throwable( "Connection closed" )); }else{ connectedOutbound(); listener.connectSuccess( this, remaining_initial_data ); } } /** * Get the transport's speed mode. * @return current mode */ public int getTransportMode() { return transport_mode; } protected void close( TransportHelper helper, String reason ) { helper.close( reason ); close( reason ); } /** * Close the transport connection. */ public void close( String reason ) { has_been_closed = true; if( connect_request_key != null ) { TCPNetworkManager.getSingleton().getConnectDisconnectManager().cancelRequest( connect_request_key ); } readyForRead( false ); readyForWrite( false ); TransportHelperFilter filter = getFilter(); if ( filter != null ){ filter.getHelper().close( reason ); setFilter( null ); } // we need to set it ready for reading so that the other scheduling thread wakes up // and discovers that this connection has been closed setReadyForRead(); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportHelper.java0000644000175000017500000003246411001746714030627 0ustar adrianadrian/* * Created on Nov 1, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.tcp; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.*; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector; import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector.VirtualSelectorListener; import com.aelitis.azureus.core.networkmanager.impl.TransportHelper; /** * */ public class TCPTransportHelper implements TransportHelper { public static final int READ_TIMEOUT = 10*1000; public static final int CONNECT_TIMEOUT = 60*1000; public static final int MAX_PARTIAL_WRITE_RETAIN = 64; // aim here is to catch headers private long remainingBytesToScatter = 0; private static boolean enable_efficient_io = !Constants.JAVA_VERSION.startsWith("1.4"); private final SocketChannel channel; private ByteBuffer delayed_write; private Map user_data; private boolean trace; public TCPTransportHelper( SocketChannel _channel ) { channel = _channel; } public InetSocketAddress getAddress() { return( new InetSocketAddress( channel.socket().getInetAddress(), channel.socket().getPort())); } public String getName(boolean verbose) { // default is TCP so don't clutter up views with this info if ( verbose ){ return( "TCP" ); }else{ return( "" ); } } public boolean minimiseOverheads() { return( false ); } public int getConnectTimeout() { return( CONNECT_TIMEOUT ); } public int getReadTimeout() { return( READ_TIMEOUT ); } public boolean delayWrite( ByteBuffer buffer) { if ( delayed_write != null ){ Debug.out( "secondary delayed write" ); return( false ); } delayed_write = buffer; return( true ); } public boolean hasDelayedWrite() { return( delayed_write != null ); } public int write( ByteBuffer buffer, boolean partial_write ) throws IOException { if ( channel == null ){ Debug.out( "channel == null" ); return 0; } // partial-write means we are guaranteed to get hit with another write straight away if ( partial_write && delayed_write == null ){ if ( buffer.remaining() < MAX_PARTIAL_WRITE_RETAIN ){ ByteBuffer copy = ByteBuffer.allocate( buffer.remaining()); copy.put( buffer ); copy.position( 0 ); delayed_write = copy; return( copy.remaining()); } } long written = 0; if ( delayed_write != null ){ // System.out.println( "delayed write: single" ); ByteBuffer[] buffers = new ByteBuffer[]{ delayed_write, buffer }; int delay_remaining = delayed_write.remaining(); delayed_write = null; written = write( buffers, 0, 2 ); // note that we can't report delayed bytes actually written as these have already been accounted for and confuse // the layers above if we report them now if ( buffers[0].hasRemaining()){ delayed_write = buffers[0]; written = 0; // System.out.println( "delayed write: single incomp" ); }else{ written -= delay_remaining; } }else{ // log( buffer ); written = channelWrite(buffer); } if ( trace ){ TimeFormatter.milliTrace( "tcp: write " + written ); } return((int)written ); } public long write( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { if( channel == null ){ Debug.out( "channel == null" ); return 0; } long written_sofar = 0; if ( delayed_write != null ){ ByteBuffer[] buffers2 = new ByteBuffer[length+1]; buffers2[0] = delayed_write; int pos = 1; for (int i=array_offset;i 0 && buf.remaining() > 0) { int currentWritten = channel.write((ByteBuffer)(buf.slice().limit(Math.min(50+rnd.nextInt(100),buf.remaining())))); if(currentWritten == 0) break; buf.position(buf.position()+currentWritten); remainingBytesToScatter -= currentWritten; if(remainingBytesToScatter <= 0) { remainingBytesToScatter = 0; try { channel.socket().setTcpNoDelay(false); } catch (SocketException e) { Debug.printStackTrace(e); } } written += currentWritten; } if(buf.remaining() > 0) written += channel.write(buf); return written; } public int read( ByteBuffer buffer ) throws IOException { if( channel == null ) { Debug.out( "channel == null" ); return 0; } int res = channel.read( buffer ); if ( trace ){ TimeFormatter.milliTrace( "tcp: read " + res ); } return( res ); } public long read( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { if( channel == null ) { Debug.out( "channel == null" ); return 0; } if( buffers == null ) { Debug.out( "read: buffers == null" ); return 0; } long bytes_read = 0; if( enable_efficient_io ) { try{ bytes_read = channel.read( buffers, array_offset, length ); } catch( IOException ioe ) { //a bug only fixed in Tiger (1.5 series): //http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4854354 String msg = ioe.getMessage(); if( msg != null && msg.equals( "A non-blocking socket operation could not be completed immediately" ) ) { enable_efficient_io = false; Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_WARNING, "WARNING: Multi-buffer socket read failed; switching to single-buffer mode.\n" + "Upgrade to JRE 1.5 (5.0) series to fix this problem!")); } throw ioe; } }else{ //single-buffer mode for( int i=array_offset; i < (array_offset + length); i++ ) { int data_length = buffers[ i ].remaining(); int read = channel.read( buffers[ i ] ); bytes_read += read; if( read < data_length ) { break; } } } if ( bytes_read < 0 ){ throw new IOException( "end of stream on socket read" ); } if ( trace ){ TimeFormatter.milliTrace( "tcp: read " + bytes_read ); } return bytes_read; } public void registerForReadSelects( final selectListener listener, Object attachment ) { TCPNetworkManager.getSingleton().getReadSelector().register( channel, new VirtualSelectorListener() { public boolean selectSuccess( VirtualChannelSelector selector, SocketChannel sc, Object attachment ) { return( listener.selectSuccess( TCPTransportHelper.this, attachment )); } public void selectFailure( VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg) { listener.selectFailure( TCPTransportHelper.this, attachment, msg ); } }, attachment ); } public void registerForWriteSelects( final selectListener listener, Object attachment ) { TCPNetworkManager.getSingleton().getWriteSelector().register( channel, new VirtualSelectorListener() { public boolean selectSuccess( VirtualChannelSelector selector, SocketChannel sc, Object attachment ) { if ( trace ){ TimeFormatter.milliTrace( "tcp: write select" ); } return( listener.selectSuccess( TCPTransportHelper.this, attachment )); } public void selectFailure( VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg) { listener.selectFailure( TCPTransportHelper.this, attachment, msg ); } }, attachment ); } public void cancelReadSelects() { TCPNetworkManager.getSingleton().getReadSelector().cancel( channel ); } public void cancelWriteSelects() { if ( trace ){ TimeFormatter.milliTrace( "tcp: cancel write selects" ); } TCPNetworkManager.getSingleton().getWriteSelector().cancel( channel ); } public void resumeReadSelects() { TCPNetworkManager.getSingleton().getReadSelector().resumeSelects( channel ); } public void resumeWriteSelects() { if ( trace ){ TimeFormatter.milliTrace( "tcp: resume write selects" ); } TCPNetworkManager.getSingleton().getWriteSelector().resumeSelects( channel ); } public void pauseReadSelects() { TCPNetworkManager.getSingleton().getReadSelector().pauseSelects( channel ); } public void pauseWriteSelects() { if ( trace ){ TimeFormatter.milliTrace( "tcp: pause write selects" ); } TCPNetworkManager.getSingleton().getWriteSelector().pauseSelects( channel ); } public void close( String reason ) { TCPNetworkManager.getSingleton().getReadSelector().cancel( channel ); TCPNetworkManager.getSingleton().getWriteSelector().cancel( channel ); TCPNetworkManager.getSingleton().getConnectDisconnectManager().closeConnection( channel ); } public void failed( Throwable reason ) { close( Debug.getNestedExceptionMessage( reason )); } public SocketChannel getSocketChannel(){ return channel; } public synchronized void setUserData( Object key, Object data ) { if ( user_data == null ){ user_data = new HashMap(); } user_data.put( key, data ); } public synchronized Object getUserData( Object key ) { if ( user_data == null ){ return(null); } return( user_data.get( key )); } /* protected void log( ByteBuffer[] buffers, int array_offset, int length ) { System.out.println( "Writing group of " + length ); for( int i=array_offset; i < (array_offset + length); i++ ) { log( buffers[i]); } } protected void log( ByteBuffer buffer ) { int position = buffer.position(); int rem = buffer.remaining(); byte[] temp = new byte[rem>64?64:rem]; buffer.get( temp ); buffer.position( position ); System.out.println( " writing " + rem + ": " + new String(temp)); } */ public void setTrace( boolean on ) { trace = on; } public void setScatteringMode(long forBytes) { if(forBytes > 0) { if(remainingBytesToScatter == 0) try { channel.socket().setTcpNoDelay(true); } catch (SocketException e) { Debug.printStackTrace(e); } remainingBytesToScatter = forBytes; } else { if(remainingBytesToScatter > 0) try { channel.socket().setTcpNoDelay(false); } catch (SocketException e) { Debug.printStackTrace(e); } remainingBytesToScatter = 0; } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/ProxyLoginHandler.java0000644000175000017500000004430310542714702030530 0ustar adrianadrian/* * Created on Feb 1, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.tcp; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.ArrayList; import org.gudy.azureus2.core3.config.COConfigurationListener; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.*; import com.aelitis.azureus.core.proxy.AEProxyFactory; /** * Handles the process of proxy login/authentication/setup. */ public class ProxyLoginHandler { private static final int READ_DONE = 0; private static final int READ_NOT_DONE = 1; private static final int READ_NO_PROGRESS = 2; public static InetSocketAddress DEFAULT_SOCKS_SERVER_ADDRESS; private static String default_socks_version; private static String default_socks_user; private static String default_socks_password; static{ COConfigurationManager.addListener( new COConfigurationListener() { public void configurationSaved() { readConfig(); } }); readConfig(); } static void readConfig() { boolean socks_same = COConfigurationManager.getBooleanParameter( "Proxy.Data.Same" ); String socks_host = COConfigurationManager.getStringParameter( socks_same ? "Proxy.Host" : "Proxy.Data.Host" ); int socks_port = 0; try{ String socks_port_str = COConfigurationManager.getStringParameter( socks_same ? "Proxy.Port" : "Proxy.Data.Port" ); socks_port_str = socks_port_str.trim(); if ( socks_port_str.length() > 0 ){ socks_port = Integer.parseInt( COConfigurationManager.getStringParameter( socks_same ? "Proxy.Port" : "Proxy.Data.Port" ) ); } }catch( Throwable e ){ Debug.printStackTrace(e); } DEFAULT_SOCKS_SERVER_ADDRESS = new InetSocketAddress( socks_host, socks_port ); default_socks_version = COConfigurationManager.getStringParameter( "Proxy.Data.SOCKS.version" ); default_socks_user = COConfigurationManager.getStringParameter( socks_same ? "Proxy.Username" : "Proxy.Data.Username" ); if ( default_socks_user.trim().equalsIgnoreCase("")){ default_socks_user = ""; } default_socks_password = COConfigurationManager.getStringParameter( socks_same ? "Proxy.Password" : "Proxy.Data.Password" ); } private final TCPTransportImpl proxy_connection; private final InetSocketAddress remote_address; private final ProxyListener proxy_listener; private final String mapped_ip; private int socks5_handshake_phase = 0; private int socks5_address_length; private long read_start_time = 0; private final String socks_version; private final String socks_user; private final String socks_password; /** * Do proxy login. * @param proxy_connection transport connected to proxy server * @param remote_address address to proxy to * @param listener for proxy login success or faulure */ public ProxyLoginHandler( TCPTransportImpl proxy_connection, InetSocketAddress remote_address, ProxyListener listener ) { this( proxy_connection, remote_address, listener, default_socks_version, default_socks_user, default_socks_password ); } public ProxyLoginHandler( TCPTransportImpl _proxy_connection, InetSocketAddress _remote_address, ProxyListener _listener, String _socks_version, String _socks_user, String _socks_password ) { proxy_connection = _proxy_connection; remote_address = _remote_address; proxy_listener = _listener; socks_version = _socks_version; socks_user = _socks_user; socks_password = _socks_password; if ( remote_address.isUnresolved() || remote_address.getAddress() == null ){ // deal with long "hostnames" that we get for, e.g., I2P destinations mapped_ip = AEProxyFactory.getAddressMapper().internalise( remote_address.getHostName() ); } else{ mapped_ip = remote_address.getAddress().getHostName(); } if( socks_version.equals( "V4" ) ) { try{ doSocks4Login( createSocks4Message() ); } catch( Throwable t ) { Debug.out( t ); proxy_listener.connectFailure( t ); } } else if( socks_version.equals( "V4a" ) ) { try{ doSocks4Login( createSocks4aMessage() ); } catch( Throwable t ) { Debug.out( t ); proxy_listener.connectFailure( t ); } } else { //"V5" doSocks5Login(); } } private void doSocks4Login( final ByteBuffer[] data ) { try { sendMessage( data[0] ); //send initial handshake to get things started //register for read ops TCPNetworkManager.getSingleton().getReadSelector().register( proxy_connection.getSocketChannel(), new VirtualChannelSelector.VirtualSelectorListener() { public boolean selectSuccess( VirtualChannelSelector selector, SocketChannel sc,Object attachment ) { try { int result = readMessage( data[1] ); if( result == READ_DONE ) { TCPNetworkManager.getSingleton().getReadSelector().cancel( proxy_connection.getSocketChannel() ); parseSocks4Reply( data[1] ); //will throw exception on error proxy_listener.connectSuccess(); } else { TCPNetworkManager.getSingleton().getReadSelector().resumeSelects( proxy_connection.getSocketChannel() ); //resume read ops } return( result != READ_NO_PROGRESS ); } catch( Throwable t ) { //Debug.out( t ); TCPNetworkManager.getSingleton().getReadSelector().cancel( proxy_connection.getSocketChannel() ); proxy_listener.connectFailure( t ); return false; } } public void selectFailure( VirtualChannelSelector selector, SocketChannel sc,Object attachment, Throwable msg ) { Debug.out( msg ); TCPNetworkManager.getSingleton().getReadSelector().cancel( proxy_connection.getSocketChannel() ); proxy_listener.connectFailure( msg ); } }, null ); } catch( Throwable t ) { Debug.out( t ); TCPNetworkManager.getSingleton().getReadSelector().cancel( proxy_connection.getSocketChannel() ); proxy_listener.connectFailure( t ); } } private void doSocks5Login() { try { final ArrayList data = new ArrayList(2); ByteBuffer[] header = createSocks5Message(); data.add( header[0] ); //message data.add( header[1] ); //reply buff sendMessage( (ByteBuffer)data.get(0) ); //send initial handshake to get things started //register for read ops TCPNetworkManager.getSingleton().getReadSelector().register( proxy_connection.getSocketChannel(), new VirtualChannelSelector.VirtualSelectorListener() { public boolean selectSuccess( VirtualChannelSelector selector, SocketChannel sc,Object attachment ) { try { int result = readMessage( (ByteBuffer)data.get(1) ); if( result == READ_DONE ) { boolean done = parseSocks5Reply( (ByteBuffer)data.get(1) ); //will throw exception on error if( done ) { TCPNetworkManager.getSingleton().getReadSelector().cancel( proxy_connection.getSocketChannel() ); proxy_listener.connectSuccess(); } else { ByteBuffer[] raw = createSocks5Message(); data.set( 0, raw[0] ); data.set( 1, raw[1] ); if( raw[0] != null ) sendMessage( raw[0] ); TCPNetworkManager.getSingleton().getReadSelector().resumeSelects( proxy_connection.getSocketChannel() ); //resume read ops } } else { TCPNetworkManager.getSingleton().getReadSelector().resumeSelects( proxy_connection.getSocketChannel() ); //resume read ops } return( result != READ_NO_PROGRESS ); } catch( Throwable t ) { //Debug.out( t ); TCPNetworkManager.getSingleton().getReadSelector().cancel( proxy_connection.getSocketChannel() ); proxy_listener.connectFailure( t ); return false; } } public void selectFailure( VirtualChannelSelector selector, SocketChannel sc,Object attachment, Throwable msg ) { Debug.out( msg ); TCPNetworkManager.getSingleton().getReadSelector().cancel( proxy_connection.getSocketChannel() ); proxy_listener.connectFailure( msg ); } }, null ); } catch( Throwable t ) { Debug.out( t ); SocketChannel chan = proxy_connection.getSocketChannel(); if ( chan != null ){ TCPNetworkManager.getSingleton().getReadSelector().cancel( chan ); } proxy_listener.connectFailure( t ); } } private void parseSocks4Reply( ByteBuffer reply ) throws IOException { byte ver = reply.get(); byte resp = reply.get(); if( ver != 0 || resp != 90 ) { throw new IOException( "SOCKS 4(a): connection declined [" +ver+ "/" + resp + "]" ); } } private void sendMessage( ByteBuffer msg ) throws IOException { long start_time = SystemTime.getCurrentTime(); while( msg.hasRemaining() ) { if( proxy_connection.write( new ByteBuffer[]{ msg }, 0, 1 ) < 1 ) { if( SystemTime.getCurrentTime() - start_time > 30*1000 ) { String error = "proxy handshake message send timed out after 30sec"; Debug.out( error ); throw new IOException( error ); } try { Thread.sleep( 10 ); }catch( Throwable t ) {t.printStackTrace();} } } } private int readMessage( ByteBuffer msg ) throws IOException { if( read_start_time == 0 ) read_start_time = SystemTime.getCurrentTime(); long bytes_read = proxy_connection.read( new ByteBuffer[]{ msg }, 0, 1 ); if( !msg.hasRemaining() ) { msg.position( 0 ); read_start_time = 0; //reset for next round return READ_DONE; } if( SystemTime.getCurrentTime() - read_start_time > 30*1000 ) { String error = "proxy message read timed out after 30sec"; Debug.out( error ); throw new IOException( error ); } return( bytes_read==0?READ_NO_PROGRESS:READ_NOT_DONE); } private ByteBuffer[] createSocks4Message() throws Exception { ByteBuffer handshake = ByteBuffer.allocate( 256 + mapped_ip.length() ); //TODO convert to direct? handshake.put( (byte)4 ); // socks 4(a) handshake.put( (byte)1 ); // command = CONNECT handshake.putShort( (short)remote_address.getPort() ); byte[] ip_bytes = HostNameToIPResolver.syncResolve( remote_address.getAddress().getHostAddress() ).getAddress(); handshake.put( ip_bytes[ 0 ] ); handshake.put( ip_bytes[ 1 ] ); handshake.put( ip_bytes[ 2 ] ); handshake.put( ip_bytes[ 3 ] ); if( socks_user.length() > 0 ) { handshake.put( socks_user.getBytes() ); } handshake.put( (byte)0 ); handshake.flip(); return new ByteBuffer[] { handshake, ByteBuffer.allocate( 8 ) }; //TODO convert to direct? } private ByteBuffer[] createSocks4aMessage() { ByteBuffer handshake = ByteBuffer.allocate( 256 + mapped_ip.length() ); //TODO convert to direct? handshake.put( (byte)4 ); // socks 4(a) handshake.put( (byte)1 ); // command = CONNECT handshake.putShort( (short)remote_address.getPort() ); // port handshake.put( (byte)0 ); handshake.put( (byte)0 ); handshake.put( (byte)0 ); handshake.put( (byte)1 ); // indicates socks 4a if( socks_user.length() > 0 ) { handshake.put( socks_user.getBytes() ); } handshake.put( (byte)0 ); handshake.put( mapped_ip.getBytes() ); handshake.put( (byte)0 ); handshake.flip(); return new ByteBuffer[] { handshake, ByteBuffer.allocate( 8 ) }; //TODO convert to direct? } private ByteBuffer[] createSocks5Message() { ByteBuffer handshake = ByteBuffer.allocate( 256 + mapped_ip.length() ); //TODO convert to direct? if( socks5_handshake_phase == 0 ) { // say hello //System.out.println( "socks5 write phase 0" ); handshake.put( (byte)5 ); // socks 5 handshake.put( (byte)2 ); // 2 methods handshake.put( (byte)0 ); // no auth handshake.put( (byte)2 ); // user/pw handshake.flip(); socks5_handshake_phase = 1; return new ByteBuffer[] { handshake, ByteBuffer.allocate( 2 ) }; //TODO convert to direct? } if( socks5_handshake_phase == 1 ) { // user/password auth //System.out.println( "socks5 write phase 1" ); handshake.put( (byte)1 ); // user/pw version handshake.put( (byte)socks_user.length() ); // user length handshake.put( socks_user.getBytes() ); handshake.put( (byte)socks_password.length() ); // password length handshake.put( socks_password.getBytes() ); handshake.flip(); socks5_handshake_phase = 2; return new ByteBuffer[] { handshake, ByteBuffer.allocate( 2 ) }; //TODO convert to direct? } if( socks5_handshake_phase == 2 ) { // request //System.out.println( "socks5 write phase 2" ); handshake.put( (byte)5 ); // version handshake.put( (byte)1 ); // connect handshake.put( (byte)0 ); // reserved // use the maped ip for dns resolution so we don't leak the // actual address if this is a secure one (e.g. I2P one) try { byte[] ip_bytes = HostNameToIPResolver.syncResolve( mapped_ip ).getAddress(); handshake.put( (byte)1 ); // IP4 handshake.put( ip_bytes[ 0 ] ); handshake.put( ip_bytes[ 1 ] ); handshake.put( ip_bytes[ 2 ] ); handshake.put( ip_bytes[ 3 ] ); } catch (Throwable e) { handshake.put( (byte)3 ); // address type = domain name handshake.put( (byte)mapped_ip.length() ); // address type = domain name handshake.put( mapped_ip.getBytes() ); } handshake.putShort( (short)remote_address.getPort() ); // port handshake.flip(); socks5_handshake_phase = 3; return new ByteBuffer[] { handshake, ByteBuffer.allocate( 5 ) }; //TODO convert to direct? } //System.out.println( "socks5 write phase 3..." ); //reply has to be processed in two parts as it has variable length component at the end //socks5_handshake_phase == 3, part two socks5_handshake_phase = 4; return new ByteBuffer[] { null, ByteBuffer.allocate( socks5_address_length ) }; //TODO convert to direct? } private boolean parseSocks5Reply( ByteBuffer reply ) throws IOException { if( socks5_handshake_phase == 1 ) { // reply from hello //System.out.println( "socks5 read phase 1" ); reply.get(); // version byte byte method = reply.get(); if( method != 0 && method != 2 ) { throw new IOException( "SOCKS 5: no valid method [" + method + "]" ); } // no auth -> go to request phase if( method == 0 ) { socks5_handshake_phase = 2; } return false; } if( socks5_handshake_phase == 2 ) { // reply from auth //System.out.println( "socks5 read phase 2" ); reply.get(); // version byte byte status = reply.get(); if( status != 0 ) { throw new IOException( "SOCKS 5: authentication fails [status=" +status+ "]" ); } return false; } if( socks5_handshake_phase == 3 ) { // reply from request, first part //System.out.println( "socks5 read phase 3" ); reply.get(); // version byte byte rep = reply.get(); if( rep != 0 ) { String error_msgs[] = { "", "General SOCKS server failure", "connection not allowed by ruleset", "Network unreachable", "Host unreachable", "Connection refused", "TTL expired", "Command not supported", "Address type not supported" }; String error_msg = rep < error_msgs.length ? error_msgs[ rep ] : "Unknown error"; throw new IOException( "SOCKS request failure [" + error_msg + "/" + rep + "]" ); } reply.get(); // reserved byte byte atype = reply.get(); byte first_address_byte = reply.get(); if( atype == 1 ) { socks5_address_length = 3; // already read one } else if( atype == 3 ) { socks5_address_length = first_address_byte; // domain name, first byte gives length of remainder } else { socks5_address_length = 15; // already read one } socks5_address_length += 2; // 2 bytes for port return false; } //System.out.println( "socks5 read phase 4..." ); //socks5_handshake_phase 4 //reply from request, last part return true; //only done AFTER last part of request reply has been read from stream } public interface ProxyListener { /** * The proxied connection attempt succeeded. */ public void connectSuccess() ; /** * The proxied connection attempt failed. * @param failure_msg failure reason */ public void connectFailure( Throwable failure_msg ); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualNonBlockingServerChannelSelector.javaazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualNonBlockingServerChannelSele0000644000175000017500000001323510445314762033247 0ustar adrianadrian/* * Created on Dec 4, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.tcp; import java.net.*; import java.nio.channels.*; import java.util.*; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.VirtualServerChannelSelector; /** * Virtual server socket channel for listening and accepting incoming connections. */ public class VirtualNonBlockingServerChannelSelector implements VirtualServerChannelSelector { private static final LogIDs LOGID = LogIDs.NWMAN; private List server_channels = new ArrayList(); private final InetAddress bind_address; private int start_port; private int num_ports; private final int receive_buffer_size; private final VirtualBlockingServerChannelSelector.SelectListener listener; protected AEMonitor this_mon = new AEMonitor( "VirtualNonBlockingServerChannelSelector" ); private long last_accept_time; /** * Create a new server listening on the given address and reporting to the given listener. * @param bind_address ip+port to listen on * @param so_rcvbuf_size new socket receive buffer size * @param listener to notify of incoming connections */ public VirtualNonBlockingServerChannelSelector( InetSocketAddress bind_address, int so_rcvbuf_size, VirtualBlockingServerChannelSelector.SelectListener listener ) { this( bind_address.getAddress(), bind_address.getPort(), 1, so_rcvbuf_size, listener ); } public VirtualNonBlockingServerChannelSelector( InetAddress _bind_address, int _start_port, int _num_ports, int _so_rcvbuf_size, VirtualBlockingServerChannelSelector.SelectListener _listener ) { bind_address = _bind_address; start_port = _start_port; num_ports = _num_ports; receive_buffer_size = _so_rcvbuf_size; listener = _listener; } /** * Start the server and begin accepting incoming connections. * */ public void start() { try{ this_mon.enter(); if( !isRunning() ) { for (int i=start_port;i 0 ) server_channel.socket().setReceiveBufferSize( receive_buffer_size ); server_channel.socket().bind( new InetSocketAddress( bind_address, i ), 1024 ); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "TCP incoming server socket " + bind_address)); server_channel.configureBlocking( false ); VirtualAcceptSelector.getSingleton().register( server_channel, new VirtualAcceptSelector.AcceptListener() { public void newConnectionAccepted( SocketChannel channel ) { last_accept_time = SystemTime.getCurrentTime(); listener.newConnectionAccepted( server_channel, channel ); } }); }catch( Throwable t ) { Debug.out( t ); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "ERROR, unable to bind TCP incoming server socket to " +i, t)); } } last_accept_time = SystemTime.getCurrentTime(); //init to now } }finally{ this_mon.exit(); } } /** * Stop the server. */ public void stop() { try{ this_mon.enter(); for (int i=0;i 10 * 60 * 1000) { //the socket server hasn't accepted any new connections in the last 10min //so manually test the listen port for connectivity InetAddress inet_address = server_selector.getBoundToAddress(); try { if (inet_address == null) inet_address = InetAddress.getByName("127.0.0.1"); //failback Socket sock = new Socket(inet_address, tcp_listen_port, inet_address, 0); sock.close(); listenFailCounts[i] = 0; } catch (Throwable t) { //ok, let's try again without the explicit local bind try { Socket sock = new Socket(InetAddress.getByName("127.0.0.1"), tcp_listen_port); sock.close(); listenFailCounts[i] = 0; } catch (Throwable x) { listenFailCounts[i]++; Debug.out(new Date() + ": listen port on [" + inet_address + ": " + tcp_listen_port + "] seems CLOSED [" + listenFailCounts[i] + "x]"); if (listenFailCounts[i] > 4) { String error = t.getMessage() == null ? "" : t.getMessage(); String msg = "Listen server socket on [" + inet_address + ": " + tcp_listen_port + "] does not appear to be accepting inbound connections.\n[" + error + "]\nAuto-repairing listen service....\n"; Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_WARNING, msg)); restart(); listenFailCounts[i] = 0; } } } } else { //it's recently accepted an inbound connection listenFailCounts[i] = 0; } } } } }); } public boolean isEnabled() { return( COConfigurationManager.getBooleanParameter(port_enable_config_key )); } /** * Get port that the TCP server socket is listening for incoming connections * on. * * @return port number */ public int getTCPListeningPortNumber() { return tcp_listen_port; } public void setExplicitBindAddress( InetAddress address ) { explicit_bind_address = address; explicit_bind_address_set = true; restart(); } public void clearExplicitBindAddress() { explicit_bind_address = null; explicit_bind_address_set = false; restart(); } protected InetAddress[] getEffectiveBindAddresses() { if ( explicit_bind_address_set ){ return( new InetAddress[] {explicit_bind_address}); }else{ return( default_bind_addresses ); } } public boolean isEffectiveBindAddress( InetAddress address ) { InetAddress[] effective = getEffectiveBindAddresses(); return Arrays.asList(effective).contains(address); } private final class TcpSelectListener implements VirtualServerChannelSelector.SelectListener { public void newConnectionAccepted( final ServerSocketChannel server, final SocketChannel channel ) { InetAddress remote_ia = channel.socket().getInetAddress(); if ( !( remote_ia.isLoopbackAddress() || remote_ia.isLinkLocalAddress() || remote_ia.isSiteLocalAddress())){ last_non_local_connection_time = SystemTime.getCurrentTime(); } //check for encrypted transport final TCPTransportHelper helper = new TCPTransportHelper( channel ); TransportCryptoManager.getSingleton().manageCrypto( helper, null, true, null, new TransportCryptoManager.HandshakeListener() { public void handshakeSuccess( ProtocolDecoder decoder, ByteBuffer remaining_initial_data ) { process( server.socket().getLocalPort(), decoder.getFilter()); } public void handshakeFailure( Throwable failure_msg ) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "incoming crypto handshake failure: " + Debug.getNestedExceptionMessage( failure_msg ))); /* // we can have problems with sockets stuck in a TIME_WAIT state if we just // close an incoming channel - to clear things down properly the client needs // to initiate the close. So what we do is send some random bytes to the client // under the assumption this will cause them to close, and we delay our socket close // for 10 seconds to give them a chance to do so. try{ Random random = new Random(); byte[] random_bytes = new byte[68+random.nextInt(128-68)]; random.nextBytes( random_bytes ); channel.write( ByteBuffer.wrap( random_bytes )); }catch( Throwable e ){ // ignore anything here } NetworkManager.getSingleton().closeSocketChannel( channel, 10*1000 ); */ helper.close( "Handshake failure: " + Debug.getNestedExceptionMessage( failure_msg )); } public void gotSecret( byte[] session_secret ) { } public int getMaximumPlainHeaderLength() { return( incoming_manager.getMaxMinMatchBufferSize()); } public int matchPlainHeader( ByteBuffer buffer ) { Object[] match_data = incoming_manager.checkForMatch( helper, server.socket().getLocalPort(), buffer, true ); if ( match_data == null ){ return( TransportCryptoManager.HandshakeListener.MATCH_NONE ); }else{ IncomingConnectionManager.MatchListener match = (IncomingConnectionManager.MatchListener)match_data[0]; if ( match.autoCryptoFallback()){ return( TransportCryptoManager.HandshakeListener.MATCH_CRYPTO_AUTO_FALLBACK ); }else{ return( TransportCryptoManager.HandshakeListener.MATCH_CRYPTO_NO_AUTO_FALLBACK ); } } } }); } } private final VirtualServerChannelSelector.SelectListener selectListener = new TcpSelectListener(); private void start() { try { this_mon.enter(); if (tcp_listen_port < 0 || tcp_listen_port > 65535 || tcp_listen_port == 6880) { String msg = "Invalid incoming TCP listen port configured, " + tcp_listen_port + ". Port reset to default. Please check your config!"; Debug.out(msg); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, msg)); tcp_listen_port = RandomUtils.generateRandomNetworkListenPort(); COConfigurationManager.setParameter(port_config_key, tcp_listen_port); } if (COConfigurationManager.getBooleanParameter(port_enable_config_key)) { last_non_local_connection_time = COConfigurationManager.getLongParameter( "network.tcp.port." + tcp_listen_port + ".last.nonlocal.incoming", 0 ); if ( last_non_local_connection_time > SystemTime.getCurrentTime()){ last_non_local_connection_time = SystemTime.getCurrentTime(); } if (serverSelectors.length == 0) { InetSocketAddress address; InetAddress[] bindAddresses = getEffectiveBindAddresses(); List tempSelectors = new ArrayList(bindAddresses.length); listenFailCounts = new int[bindAddresses.length]; for (int i = 0; i < bindAddresses.length; i++) { InetAddress bindAddress = bindAddresses[i]; if(!NetworkAdmin.getSingleton().hasIPV6Potential(true) && bindAddress instanceof Inet6Address) continue; if (bindAddress != null) address = new InetSocketAddress(bindAddress, tcp_listen_port); else address = new InetSocketAddress(tcp_listen_port); VirtualServerChannelSelector serverSelector; if(bindAddresses.length == 1) serverSelector = VirtualServerChannelSelectorFactory.createBlocking(address, so_rcvbuf_size, selectListener); else serverSelector = VirtualServerChannelSelectorFactory.createNonBlocking(address, so_rcvbuf_size, selectListener); serverSelector.start(); tempSelectors.add(serverSelector); } if(tempSelectors.size() == 0) Logger.log(new LogAlert(true,LogAlert.AT_WARNING,MessageText.getString("network.bindError"))); serverSelectors = (VirtualServerChannelSelector[])tempSelectors.toArray(new VirtualServerChannelSelector[tempSelectors.size()]); } } else { Logger.log(new LogEvent(LOGID, "Not starting TCP listener on port " + tcp_listen_port + " as protocol disabled")); } } finally { this_mon.exit(); } } protected void process( int local_port, TransportHelperFilter filter ) { SocketChannel channel = ((TCPTransportHelper)filter.getHelper()).getSocketChannel(); //set advanced socket options try { int so_sndbuf_size = COConfigurationManager.getIntParameter( "network.tcp.socket.SO_SNDBUF" ); if( so_sndbuf_size > 0 ) channel.socket().setSendBufferSize( so_sndbuf_size ); String ip_tos = COConfigurationManager.getStringParameter( "network.tcp.socket.IPDiffServ" ); if( ip_tos.length() > 0 ) channel.socket().setTrafficClass( Integer.decode( ip_tos ).intValue() ); } catch( Throwable t ) { t.printStackTrace(); } InetSocketAddress tcp_address = new InetSocketAddress( channel.socket().getInetAddress(), channel.socket().getPort()); ConnectionEndpoint co_ep = new ConnectionEndpoint(tcp_address); ProtocolEndpointTCP pe_tcp = new ProtocolEndpointTCP( co_ep, tcp_address ); Transport transport = new TCPTransportImpl( pe_tcp, filter ); incoming_manager.addConnection( local_port, filter, transport ); } protected long getLastNonLocalConnectionTime() { return( last_non_local_connection_time ); } private void restart() { try{ this_mon.enter(); for(int i=0;i new_requests = new TreeSet( new Comparator() { public int compare( ConnectionRequest r1, ConnectionRequest r2 ) { int res = r1.getPriority() - r2.getPriority(); if ( res == 0 ){ res = r1.getRandom() - r2.getRandom(); if ( res == 0 ){ long l = r1.getID() - r2.getID(); if ( l < 0 ){ res = -1; }else if ( l > 0 ){ res = 1; }else{ Debug.out( "arghhh, borkage" ); } } } return( res ); } }); private final List canceled_requests = new ArrayList(); private final AEMonitor new_canceled_mon = new AEMonitor( "ConnectDisconnectManager:NCM"); private final Map pending_attempts = new HashMap(); private final LinkedList pending_closes = new LinkedList(); private final Map delayed_closes = new HashMap(); private final AEMonitor pending_closes_mon = new AEMonitor( "ConnectDisconnectManager:PC"); private boolean max_conn_exceeded_logged; public TCPConnectionManager() { Set types = new HashSet(); types.add( AzureusCoreStats.ST_NET_TCP_OUT_CONNECT_QUEUE_LENGTH ); types.add( AzureusCoreStats.ST_NET_TCP_OUT_CANCEL_QUEUE_LENGTH ); types.add( AzureusCoreStats.ST_NET_TCP_OUT_CLOSE_QUEUE_LENGTH ); types.add( AzureusCoreStats.ST_NET_TCP_OUT_PENDING_QUEUE_LENGTH ); AzureusCoreStats.registerProvider( types, new AzureusCoreStatsProvider() { public void updateStats( Set types, Map values ) { if ( types.contains( AzureusCoreStats.ST_NET_TCP_OUT_CONNECT_QUEUE_LENGTH )){ values.put( AzureusCoreStats.ST_NET_TCP_OUT_CONNECT_QUEUE_LENGTH, new Long( new_requests.size())); } if ( types.contains( AzureusCoreStats.ST_NET_TCP_OUT_CANCEL_QUEUE_LENGTH )){ values.put( AzureusCoreStats.ST_NET_TCP_OUT_CANCEL_QUEUE_LENGTH, new Long( canceled_requests.size())); } if ( types.contains( AzureusCoreStats.ST_NET_TCP_OUT_CLOSE_QUEUE_LENGTH )){ values.put( AzureusCoreStats.ST_NET_TCP_OUT_CLOSE_QUEUE_LENGTH, new Long( pending_closes.size())); } if ( types.contains( AzureusCoreStats.ST_NET_TCP_OUT_PENDING_QUEUE_LENGTH )){ values.put( AzureusCoreStats.ST_NET_TCP_OUT_PENDING_QUEUE_LENGTH, new Long( pending_attempts.size())); } } }); new AEThread2( "ConnectDisconnectManager", true ) { public void run() { while( true ){ addNewOutboundRequests(); runSelect(); doClosings(); } } }.start(); } public int getMaxOutboundPermitted() { return( Math.max( max_outbound_connections - new_requests.size(), 0 )); } private void addNewOutboundRequests() { while( pending_attempts.size() < MIN_SIMULTANIOUS_CONNECT_ATTEMPTS ){ ConnectionRequest cr = null; try{ new_canceled_mon.enter(); if( new_requests.isEmpty() ) break; Iterator it = new_requests.iterator(); cr = it.next(); it.remove(); }finally{ new_canceled_mon.exit(); } if( cr != null ){ addNewRequest( cr ); } } } private void addNewRequest( final ConnectionRequest request ) { request.listener.connectAttemptStarted(); boolean ipv6problem = false; try { request.channel = SocketChannel.open(); try { //advanced socket options int rcv_size = COConfigurationManager.getIntParameter( "network.tcp.socket.SO_RCVBUF" ); if( rcv_size > 0 ) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Setting socket receive buffer size" + " for outgoing connection [" + request.address + "] to: " + rcv_size)); request.channel.socket().setReceiveBufferSize( rcv_size ); } int snd_size = COConfigurationManager.getIntParameter( "network.tcp.socket.SO_SNDBUF" ); if( snd_size > 0 ) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Setting socket send buffer size " + "for outgoing connection [" + request.address + "] to: " + snd_size)); request.channel.socket().setSendBufferSize( snd_size ); } String ip_tos = COConfigurationManager.getStringParameter( "network.tcp.socket.IPDiffServ" ); if( ip_tos.length() > 0 ) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Setting socket TOS field " + "for outgoing connection [" + request.address + "] to: " + ip_tos)); request.channel.socket().setTrafficClass( Integer.decode( ip_tos ).intValue() ); } int local_bind_port = COConfigurationManager.getIntParameter( "network.bind.local.port" ); if( local_bind_port > 0 ) { request.channel.socket().setReuseAddress( true ); } try { InetAddress bindIP = NetworkAdmin.getSingleton().getMultiHomedOutgoingRoundRobinBindAddress(request.address.getAddress()); if ( bindIP != null ) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Binding outgoing connection [" + request.address + "] to local IP address: " + bindIP+":"+local_bind_port)); request.channel.socket().bind( new InetSocketAddress( bindIP, local_bind_port ) ); } else if( local_bind_port > 0 ) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Binding outgoing connection [" + request.address + "] to local port #: " +local_bind_port)); request.channel.socket().bind( new InetSocketAddress( local_bind_port ) ); } } catch(SocketException e) { if(e.getMessage().equals("Address family not supported by protocol family: bind") && !NetworkAdmin.getSingleton().hasIPV6Potential(true)); ipv6problem = true; throw e; } } catch( Throwable t ) { if(!ipv6problem) { //dont pass the exception outwards, so we will continue processing connection without advanced options set String msg = "Error while processing advanced socket options."; Debug.out( msg, t ); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, msg, t)); } else { // can't support NIO + ipv6 on this system, pass on and don't raise an alert throw t; } } request.channel.configureBlocking( false ); request.connect_start_time = SystemTime.getCurrentTime(); if ( request.channel.connect( request.address ) ) { //already connected finishConnect( request ); }else{ //not yet connected, so register for connect selection try{ new_canceled_mon.enter(); pending_attempts.put( request, null ); }finally{ new_canceled_mon.exit(); } connect_selector.register( request.channel, new VirtualChannelSelector.VirtualSelectorListener() { public boolean selectSuccess( VirtualChannelSelector selector, SocketChannel sc, Object attachment ) { try{ new_canceled_mon.enter(); pending_attempts.remove( request ); }finally{ new_canceled_mon.exit(); } finishConnect( request ); return true; } public void selectFailure( VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg ) { try{ new_canceled_mon.enter(); pending_attempts.remove( request ); }finally{ new_canceled_mon.exit(); } closeConnection( request.channel ); request.listener.connectFailure( msg ); } }, null ); } }catch( Throwable t ){ String full = request.address.toString(); String hostname = request.address.getHostName(); int port = request.address.getPort(); boolean unresolved = request.address.isUnresolved(); InetAddress inet_address = request.address.getAddress(); String full_sub = inet_address==null?request.address.toString():inet_address.toString(); String host_address = inet_address==null?request.address.toString():inet_address.getHostAddress(); String msg = "ConnectDisconnectManager::address exception: full="+full+ ", hostname="+hostname+ ", port="+port+ ", unresolved="+unresolved+ ", full_sub="+full_sub+ ", host_address="+host_address; if( request.channel != null ) { String channel = request.channel.toString(); String socket = request.channel.socket().toString(); String local_address = request.channel.socket().getLocalAddress().toString(); int local_port = request.channel.socket().getLocalPort(); SocketAddress ra = request.channel.socket().getRemoteSocketAddress(); String remote_address; if( ra != null ) remote_address = ra.toString(); else remote_address = ""; int remote_port = request.channel.socket().getPort(); msg += "\n channel="+channel+ ", socket="+socket+ ", local_address="+local_address+ ", local_port="+local_port+ ", remote_address="+remote_address+ ", remote_port="+remote_port; } else { msg += "\n channel="; } if (ipv6problem || t instanceof UnresolvedAddressException || t instanceof NoRouteToHostException ){ Logger.log(new LogEvent(LOGID,LogEvent.LT_WARNING,msg)); }else{ Logger.log(new LogEvent(LOGID,LogEvent.LT_ERROR,msg,t)); } if( request.channel != null ){ closeConnection( request.channel ); } request.listener.connectFailure( t ); } } private void finishConnect( ConnectionRequest request ) { try { if( request.channel.finishConnect() ) { if( SHOW_CONNECT_STATS ) { long queue_wait_time = request.connect_start_time - request.request_start_time; long connect_time = SystemTime.getCurrentTime() - request.connect_start_time; int num_queued = new_requests.size(); int num_connecting = pending_attempts.size(); System.out.println("S: queue_wait_time="+queue_wait_time+ ", connect_time="+connect_time+ ", num_queued="+num_queued+ ", num_connecting="+num_connecting); } //ensure the request hasn't been canceled during the select op boolean canceled = false; try{ new_canceled_mon.enter(); canceled = canceled_requests.contains( request.listener ); }finally{ new_canceled_mon.exit(); } if( canceled ){ closeConnection( request.channel ); }else{ connect_selector.cancel( request.channel ); request.listener.connectSuccess( request.channel ); } }else{ //should never happen Debug.out( "finishConnect() failed" ); request.listener.connectFailure( new Throwable( "finishConnect() failed" ) ); closeConnection( request.channel ); } }catch( Throwable t ) { if( SHOW_CONNECT_STATS ) { long queue_wait_time = request.connect_start_time - request.request_start_time; long connect_time = SystemTime.getCurrentTime() - request.connect_start_time; int num_queued = new_requests.size(); int num_connecting = pending_attempts.size(); System.out.println("F: queue_wait_time="+queue_wait_time+ ", connect_time="+connect_time+ ", num_queued="+num_queued+ ", num_connecting="+num_connecting); } request.listener.connectFailure( t ); closeConnection( request.channel ); } } private void runSelect() { //do cancellations try{ new_canceled_mon.enter(); for (Iterator can_it = canceled_requests.iterator(); can_it.hasNext();){ ConnectListener key =can_it.next(); for (Iterator pen_it = pending_attempts.keySet().iterator(); pen_it.hasNext();) { ConnectionRequest request =pen_it.next(); if ( request.listener == key ){ connect_selector.cancel(request.channel); closeConnection(request.channel); pen_it.remove(); break; } } } canceled_requests.clear(); }finally{ new_canceled_mon.exit(); } //run select try{ connect_selector.select(100); } catch( Throwable t ) { Debug.out("connnectSelectLoop() EXCEPTION: ", t); } //do connect attempt timeout checks int num_stalled_requests =0; final long now =SystemTime.getCurrentTime(); List timeouts = null; try{ new_canceled_mon.enter(); for (Iterator i =pending_attempts.keySet().iterator(); i.hasNext();) { final ConnectionRequest request =i.next(); final long waiting_time =now -request.connect_start_time; if( waiting_time > request.connect_timeout ) { i.remove(); SocketChannel channel = request.channel; connect_selector.cancel( channel ); closeConnection( channel ); if ( timeouts == null ){ timeouts = new ArrayList(); } timeouts.add( request ); }else if( waiting_time >= CONNECT_ATTEMPT_STALL_TIME ) { num_stalled_requests++; }else if( waiting_time < 0 ) { //time went backwards request.connect_start_time =now; } } }finally{ new_canceled_mon.exit(); } if ( timeouts != null ){ for ( ConnectionRequest request: timeouts ){ InetSocketAddress sock_address = request.address; InetAddress a = sock_address.getAddress(); String target; if ( a != null ){ target = a.getHostAddress() + ":" + sock_address.getPort(); }else{ target = sock_address.toString(); } request.listener.connectFailure( new SocketTimeoutException( "Connection attempt to " + target + " aborted: timed out after " + request.connect_timeout/1000+ "sec" ) ); } } //check if our connect queue is stalled, and expand if so if ( num_stalled_requests == pending_attempts.size() && pending_attempts.size() it = new_requests.iterator(); cr = it.next(); it.remove(); } }finally{ new_canceled_mon.exit(); } if( cr != null ) { addNewRequest( cr ); } } } private void doClosings() { try{ pending_closes_mon.enter(); long now = SystemTime.getCurrentTime(); if ( delayed_closes.size() > 0 ){ Iterator> it = delayed_closes.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); long wait = ((Long)entry.getValue()).longValue() - now; if ( wait < 0 || wait > 60*1000 ){ pending_closes.addLast( entry.getKey()); it.remove(); } } } while( !pending_closes.isEmpty() ) { SocketChannel channel = pending_closes.removeFirst(); if( channel != null ) { connect_selector.cancel( channel ); try{ channel.close(); }catch( Throwable t ){ /*Debug.printStackTrace(t);*/ } } } }finally{ pending_closes_mon.exit(); } } /** * Request that a new connection be made out to the given address. * @param address remote ip+port to connect to * @param listener to receive notification of connect attempt success/failure */ public void requestNewConnection( InetSocketAddress address, ConnectListener listener, int priority ) { requestNewConnection( address, listener, CONNECT_ATTEMPT_TIMEOUT, priority ); } public void requestNewConnection( InetSocketAddress address, ConnectListener listener, long connect_timeout, int priority ) { List kicked = null; try{ new_canceled_mon.enter(); //insert at a random position because new connections are usually added in 50-peer //chunks, i.e. from a tracker announce reply, and we want to evenly distribute the //connect attempts if there are multiple torrents running ConnectionRequest cr = new ConnectionRequest( connection_request_id_next++, address, listener, connect_timeout, priority ); new_requests.add( cr ); if ( new_requests.size() >= max_outbound_connections ){ if ( !max_conn_exceeded_logged ){ max_conn_exceeded_logged = true; Debug.out( "TCPConnectionManager: max outbound connection limit reached (" + max_outbound_connections + ")" ); } } if ( priority == ProtocolEndpoint.CONNECT_PRIORITY_HIGHEST ){ for (Iterator pen_it = pending_attempts.keySet().iterator(); pen_it.hasNext();){ ConnectionRequest request =(ConnectionRequest) pen_it.next(); if ( request.priority == ProtocolEndpoint.CONNECT_PRIORITY_LOW ){ if ( !canceled_requests.contains( request.listener )){ canceled_requests.add( request.listener ); if ( kicked == null ){ kicked = new ArrayList(); } kicked.add( request ); } } } } }finally{ new_canceled_mon.exit(); } if ( kicked != null ){ for (int i=0;i i = new_requests.iterator(); i.hasNext(); ) { ConnectionRequest request = i.next(); if( request.listener == listener_key ) { i.remove(); return; } } canceled_requests.add( listener_key ); //else add for later removal during select } finally{ new_canceled_mon.exit(); } } private static class ConnectionRequest { private final InetSocketAddress address; private final ConnectListener listener; private final long request_start_time; private long connect_start_time; private final long connect_timeout; private SocketChannel channel; private final short rand; private final int priority; private final long id; private ConnectionRequest( long _id, InetSocketAddress _address, ConnectListener _listener, long _connect_timeout, int _priority ) { id = _id; address = _address; listener = _listener; connect_timeout = _connect_timeout; request_start_time = SystemTime.getCurrentTime(); rand = (short)( Short.MAX_VALUE*Math.random()); priority = _priority; } private long getID() { return( id ); } private int getPriority() { return( priority ); } private short getRandom() { return( rand ); } } /////////////////////////////////////////////////////////// /** * Listener for notification of connection establishment. */ public interface ConnectListener { /** * The connection establishment process has started, * i.e. the connection is actively being attempted. */ public void connectAttemptStarted(); /** * The connection attempt succeeded. * @param channel connected socket channel */ public void connectSuccess( SocketChannel channel ) ; /** * The connection attempt failed. * @param failure_msg failure reason */ public void connectFailure( Throwable failure_msg ); } ///////////////////////////////////////////////////////////// } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/LightweightTCPTransport.java0000644000175000017500000001021611035306020031643 0ustar adrianadrian/* * Created on Oct 28, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.tcp; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import com.aelitis.azureus.core.networkmanager.EventWaiter; import com.aelitis.azureus.core.networkmanager.ProtocolEndpoint; import com.aelitis.azureus.core.networkmanager.Transport; import com.aelitis.azureus.core.networkmanager.TransportEndpoint; import com.aelitis.azureus.core.networkmanager.impl.TransportHelperFilter; /** * This class is essentially a socket channel wrapper to support working with az message encoders/decoders. */ public class LightweightTCPTransport implements Transport { private final TransportEndpoint transport_endpoint; private final TransportHelperFilter filter; public LightweightTCPTransport( ProtocolEndpoint pe, TransportHelperFilter filter ) { SocketChannel channel = ((TCPTransportHelper)filter.getHelper()).getSocketChannel(); transport_endpoint = new TransportEndpointTCP( pe, channel ); this.filter = filter; } public TransportEndpoint getTransportEndpoint() { return( transport_endpoint ); } public long write( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { return filter.write( buffers, array_offset, length ); } public long read( ByteBuffer[] buffers, int array_offset, int length ) throws IOException { return filter.read( buffers, array_offset, length ); } public SocketChannel getSocketChannel(){ return ((TCPTransportHelper)filter.getHelper()).getSocketChannel(); } public InetSocketAddress getRemoteAddress() { return( new InetSocketAddress( getSocketChannel().socket().getInetAddress(), getSocketChannel().socket().getPort())); } public String getDescription(){ return getSocketChannel().socket().getInetAddress().getHostAddress() + ": " + getSocketChannel().socket().getPort(); } public void close( String reason ){ try { getSocketChannel().close(); //close() can block } catch( Throwable t) { t.printStackTrace(); } } public int getMssSize() { return( TCPNetworkManager.getTcpMssSize()); } public void setAlreadyRead( ByteBuffer bytes_already_read ){ throw new RuntimeException( "not implemented" ); } public boolean isReadyForWrite(EventWaiter waiter){ throw new RuntimeException( "not implemented" ); } public long isReadyForRead(EventWaiter waiter){ throw new RuntimeException( "not implemented" ); } public void setReadyForRead(){ throw new RuntimeException( "not implemented" ); } public void connectOutbound( ByteBuffer initial_data, ConnectListener listener, int priority ){ throw new RuntimeException( "not implemented" ); } public void connectedInbound(){ throw new RuntimeException( "not implemented" ); } public void setTransportMode( int mode ){ throw new RuntimeException( "not implemented" ); } public int getTransportMode(){ throw new RuntimeException( "not implemented" ); } public void setTrace(boolean on) { // TODO Auto-generated method stub } public String getEncryption(boolean verbose){ return( filter.getName(verbose)); } public boolean isEncrypted(){ return( filter.isEncrypted());} public boolean isTCP(){ return true; } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualBlockingServerChannelSelector.javaazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualBlockingServerChannelSelecto0000644000175000017500000001145110445314762033300 0ustar adrianadrian/* * Created on Dec 4, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl.tcp; import java.net.*; import java.nio.channels.*; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.VirtualServerChannelSelector; /** * Virtual server socket channel for listening and accepting incoming connections. */ public class VirtualBlockingServerChannelSelector implements VirtualServerChannelSelector{ private static final LogIDs LOGID = LogIDs.NWMAN; private ServerSocketChannel server_channel = null; private final InetSocketAddress bind_address; private final int receive_buffer_size; private final SelectListener listener; protected AEMonitor this_mon = new AEMonitor( "VirtualServerChannelSelector" ); private long last_accept_time; /** * Create a new server listening on the given address and reporting to the given listener. * @param bind_address ip+port to listen on * @param so_rcvbuf_size new socket receive buffer size * @param listener to notify of incoming connections */ public VirtualBlockingServerChannelSelector( InetSocketAddress _bind_address, int so_rcvbuf_size, SelectListener listener ) { this.bind_address = _bind_address; this.receive_buffer_size = so_rcvbuf_size; this.listener = listener; } /** * Start the server and begin accepting incoming connections. * */ public void start() { try{ this_mon.enter(); if( !isRunning() ) { try { server_channel = ServerSocketChannel.open(); server_channel.socket().setReuseAddress( true ); if( receive_buffer_size > 0 ) server_channel.socket().setReceiveBufferSize( receive_buffer_size ); server_channel.socket().bind( bind_address, 1024 ); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "TCP incoming server socket " + bind_address)); AEThread accept_thread = new AEThread( "VServerSelector:port" + bind_address.getPort() ) { public void runSupport() { accept_loop(); } }; accept_thread.setDaemon( true ); accept_thread.start(); } catch( Throwable t ) { Debug.out( t ); Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "ERROR, unable to bind TCP incoming server socket to " +bind_address.getPort(), t)); } last_accept_time = SystemTime.getCurrentTime(); //init to now } }finally{ this_mon.exit(); } } /** * Stop the server. */ public void stop() { try{ this_mon.enter(); if( server_channel != null ) { try { server_channel.close(); server_channel = null; } catch( Throwable t ) { Debug.out( t ); } } }finally{ this_mon.exit(); } } protected void accept_loop() { while( isRunning() ) { try { SocketChannel client_channel = server_channel.accept(); last_accept_time = SystemTime.getCurrentTime(); client_channel.configureBlocking( false ); listener.newConnectionAccepted( server_channel, client_channel ); } catch( AsynchronousCloseException e ) { /* is thrown when stop() is called */ } catch( Throwable t ) { Debug.out( t ); try { Thread.sleep( 500 ); }catch( Exception e ) { e.printStackTrace(); } } } } /** * Is this selector actively running * @return true if enabled, false if not running */ public boolean isRunning() { if( server_channel != null && server_channel.isOpen() ) return true; return false; } public InetAddress getBoundToAddress() { if( server_channel != null ) { return server_channel.socket().getInetAddress(); } return null; } public long getTimeOfLastAccept() { return last_accept_time; } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/TransportCryptoManager.java0000644000175000017500000000614710530765170031030 0ustar adrianadrian/* * Created on Jan 18, 2006 * Created by Alon Rohter * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.nio.ByteBuffer; /** * */ public class TransportCryptoManager { private static final TransportCryptoManager instance = new TransportCryptoManager(); public static TransportCryptoManager getSingleton() { return instance; } public void manageCrypto( TransportHelper transport, byte[][] shared_secrets, boolean is_incoming, ByteBuffer initial_data, final HandshakeListener listener ) { try{ new ProtocolDecoderInitial( transport, shared_secrets, !is_incoming, initial_data, new ProtocolDecoderAdapter() { public int getMaximumPlainHeaderLength() { return( listener.getMaximumPlainHeaderLength()); } public int matchPlainHeader( ByteBuffer buffer ) { return( listener.matchPlainHeader( buffer )); } public void gotSecret( byte[] session_secret ) { listener.gotSecret( session_secret ); } public void decodeComplete( ProtocolDecoder decoder, ByteBuffer remaining_initial_data ) { listener.handshakeSuccess( decoder, remaining_initial_data ); } public void decodeFailed( ProtocolDecoder decoder, Throwable cause ) { listener.handshakeFailure( cause ); } }); }catch( Throwable e ){ listener.handshakeFailure( e ); } } public interface HandshakeListener { public static final int MATCH_NONE = ProtocolDecoderAdapter.MATCH_NONE; public static final int MATCH_CRYPTO_NO_AUTO_FALLBACK = ProtocolDecoderAdapter.MATCH_CRYPTO_NO_AUTO_FALLBACK; public static final int MATCH_CRYPTO_AUTO_FALLBACK = ProtocolDecoderAdapter.MATCH_CRYPTO_AUTO_FALLBACK; public void handshakeSuccess( ProtocolDecoder decoder, ByteBuffer remaining_initial_data ); public void handshakeFailure( Throwable failure_msg ); public void gotSecret( byte[] session_secret ); public int getMaximumPlainHeaderLength(); public int matchPlainHeader( ByteBuffer buffer ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/impl/SinglePeerUploader.java0000644000175000017500000001143410647532652030072 0ustar adrianadrian/* * Created on Sep 28, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.impl; import java.io.IOException; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.networkmanager.EventWaiter; import com.aelitis.azureus.core.networkmanager.NetworkConnectionBase; /** * A fast write entity backed by a single peer connection. */ public class SinglePeerUploader implements RateControlledEntity { private final NetworkConnectionBase connection; private final RateHandler rate_handler; public SinglePeerUploader( NetworkConnectionBase connection, RateHandler rate_handler ) { this.connection = connection; this.rate_handler = rate_handler; } ////////////////RateControlledWriteEntity implementation //////////////////// public boolean canProcess(EventWaiter waiter) { if( !connection.getTransportBase().isReadyForWrite(waiter) ) { return false; //underlying transport not ready } if( connection.getOutgoingMessageQueue().getTotalSize() < 1 ) { return false; //no data to send } if( rate_handler.getCurrentNumBytesAllowed() < 1 ) { return false; //not allowed to send any bytes } return true; } public boolean doProcessing(EventWaiter waiter) { if( !connection.getTransportBase().isReadyForWrite(waiter) ) { //Debug.out("dW:not ready"); happens sometimes, just live with it as non-fatal return false; } int num_bytes_allowed = rate_handler.getCurrentNumBytesAllowed(); if( num_bytes_allowed < 1 ) { return false; } int num_bytes_available = connection.getOutgoingMessageQueue().getTotalSize(); if( num_bytes_available < 1 ) { if ( !connection.getOutgoingMessageQueue().isDestroyed()){ //Debug.out("dW:not avail"); happens sometimes, just live with it as non-fatal } return false; } int num_bytes_to_write = num_bytes_allowed > num_bytes_available ? num_bytes_available : num_bytes_allowed; //int mss = NetworkManager.getTcpMssSize(); //if( num_bytes_to_write > mss ) num_bytes_to_write = mss; int written = 0; try { written = connection.getOutgoingMessageQueue().deliverToTransport( num_bytes_to_write, false ); } catch( Throwable e ) { if( AEDiagnostics.TRACE_CONNECTION_DROPS ) { if( e.getMessage() == null ) { Debug.out( "null write exception message: ", e ); } else { if( e.getMessage().indexOf( "An existing connection was forcibly closed by the remote host" ) == -1 && e.getMessage().indexOf( "Connection reset by peer" ) == -1 && e.getMessage().indexOf( "Broken pipe" ) == -1 && e.getMessage().indexOf( "An established connection was aborted by the software in your host machine" ) == -1 ) { System.out.println( "SP: write exception [" +connection.getTransportBase().getDescription()+ "]: " +e.getMessage() ); } } } if (! (e instanceof IOException )){ Debug.printStackTrace(e); } connection.notifyOfException( e ); return false; } if( written < 1 ) { return false; } rate_handler.bytesProcessed( written ); return true; } public int getPriority() { return RateControlledEntity.PRIORITY_NORMAL; } public long getBytesReadyToWrite() { return( connection.getOutgoingMessageQueue().getTotalSize()); } public int getConnectionCount() { return( 1 ); } public int getReadyConnectionCount( EventWaiter waiter ) { if ( connection.getTransportBase().isReadyForWrite(waiter)){ return( 1 ); } return( 0 ); } public String getString() { return( "SPU: bytes_allowed=" + rate_handler.getCurrentNumBytesAllowed() + " " + connection.getString()); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/NetworkManagerStats.java0000644000175000017500000000264511057130352027332 0ustar adrianadrian/* * Created on 21-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager; /** * XXX: This class seems to be unused. */ public class NetworkManagerStats { public static final int ATTEMPTED = 0; public static final int SUCCESSFUL = 1; public static final int ENCRYPTED = 2; private long[] outbound = new long[3]; private long[] inbound = new long[3]; public long getOutbound( int type ) { return( outbound[type] ); } public long getInbound( int type ) { return( inbound[type] ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/NetworkConnectionBase.java0000644000175000017500000000450410565004542027633 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager; public interface NetworkConnectionBase { public ConnectionEndpoint getEndpoint(); /** * Inform connection of a thrown exception. * @param error exception */ public void notifyOfException( Throwable error ); /** * Get the connection's outgoing message queue. * @return outbound message queue */ public OutgoingMessageQueue getOutgoingMessageQueue(); /** * Get the connection's incoming message queue. * @return inbound message queue */ public IncomingMessageQueue getIncomingMessageQueue(); /** * Get the connection's data transport interface. * @return the transport - MAY BE NULL if not yet fully connected */ public TransportBase getTransportBase(); public int getMssSize(); /** * Is the connection within the local LAN network. * @return true if within LAN, false of outside the LAN segment */ public boolean isLANLocal(); public void setUploadLimit( int limit ); public int getUploadLimit(); public void setDownloadLimit( int limit ); public int getDownloadLimit(); public LimitedRateGroup[] getRateLimiters( boolean upload ); public void addRateLimiter( LimitedRateGroup limiter, boolean upload ); public void removeRateLimiter( LimitedRateGroup limiter, boolean upload ); public String getString(); } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/VirtualChannelSelector.java0000644000175000017500000003704011156364760030020 0ustar adrianadrian/* * Created on Jun 5, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager; import java.nio.channels.*; import java.nio.channels.spi.AbstractSelectableChannel; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.networkmanager.impl.tcp.VirtualChannelSelectorImpl; public class VirtualChannelSelector { private static final LogIDs LOGID = LogIDs.NWMAN; public static final int OP_ACCEPT = SelectionKey.OP_ACCEPT; public static final int OP_CONNECT = SelectionKey.OP_CONNECT; public static final int OP_READ = SelectionKey.OP_READ; public static final int OP_WRITE = SelectionKey.OP_WRITE; private boolean SAFE_SELECTOR_MODE_ENABLED = TEST_SAFE_MODE || COConfigurationManager.getBooleanParameter( "network.tcp.enable_safe_selector_mode" ); private static final boolean TEST_SAFE_MODE = false; private static final int MAX_CHANNELS_PER_SAFE_SELECTOR = COConfigurationManager.getIntParameter( "network.tcp.safe_selector_mode.chunk_size" ); private static final int MAX_SAFEMODE_SELECTORS = 20000 / MAX_CHANNELS_PER_SAFE_SELECTOR; private String name; private VirtualChannelSelectorImpl selector_impl; private volatile boolean destroyed; //ONLY USED IN FAULTY MODE private HashMap> selectors; private HashSet selectors_keyset_cow; private AEMonitor selectors_mon; private final int op; private final boolean pause; private boolean randomise_keys; /** * Create a new virtual selectable-channel selector, selecting over the given interest-op. * @param interest_op operation set of OP_CONNECT, OP_ACCEPT, OP_READ, or OP_WRITE * @param pause_after_select whether or not to auto-disable interest op after select */ public VirtualChannelSelector( String name, int interest_op, boolean pause_after_select ) { this.name = name; this.op = interest_op; this.pause = pause_after_select; if( SAFE_SELECTOR_MODE_ENABLED ) { initSafeMode(); } else { selector_impl = new VirtualChannelSelectorImpl( this, op, pause, randomise_keys ); selectors = null; selectors_keyset_cow = null; selectors_mon = null; } } public String getName() { return( name ); } private void initSafeMode() { //System.out.println( "***************** SAFE SOCKET SELECTOR MODE ENABLED *****************" ); if (Logger.isEnabled()) { Logger.log(new LogEvent(LOGID, "***************** SAFE SOCKET SELECTOR MODE ENABLED *****************")); } selector_impl = null; selectors = new HashMap>(); selectors_mon = new AEMonitor( "VirtualChannelSelector:FM" ); selectors.put( new VirtualChannelSelectorImpl( this, op, pause, randomise_keys ), new ArrayList() ); selectors_keyset_cow = new HashSet( selectors.keySet()); } public void register( SocketChannel channel, VirtualSelectorListener listener, Object attachment ) { registerSupport( channel, listener, attachment ); } public void register( ServerSocketChannel channel, VirtualAcceptSelectorListener listener, Object attachment ) { registerSupport( channel, listener, attachment ); } /** * Register the given selectable channel, using the given listener for notification * of completed select operations. * NOTE: For OP_CONNECT and OP_WRITE -type selectors, once a selection request op * completes, the channel's op registration is automatically disabled (paused); any * future wanted selection notification requires re-enabling via resume. For OP_READ selectors, * it stays enabled until actively paused, no matter how many times it is selected. * @param channel socket to listen for * @param listener op-complete listener * @param attachment object to be passed back with listener notification */ protected void registerSupport( AbstractSelectableChannel channel, VirtualAbstractSelectorListener listener, Object attachment ) { if( SAFE_SELECTOR_MODE_ENABLED ) { try{ selectors_mon.enter(); //System.out.println( "register - " + channel.hashCode() + " - " + Debug.getCompressedStackTrace()); for( Map.Entry> entry: selectors.entrySet()) { VirtualChannelSelectorImpl sel = entry.getKey(); ArrayList channels = entry.getValue(); if( channels.size() >= ( TEST_SAFE_MODE?0:MAX_CHANNELS_PER_SAFE_SELECTOR )) { // it seems that we have a bug somewhere where a selector is being registered // but not cancelled on close. As an interim fix scan channels and remove any // closed ones Iterator chan_it = channels.iterator(); while( chan_it.hasNext()){ AbstractSelectableChannel chan = chan_it.next(); if ( !chan.isOpen()){ Debug.out( "Selector '" + getName() + "' - removing orphaned safe channel registration" ); chan_it.remove(); } } } if( channels.size() < MAX_CHANNELS_PER_SAFE_SELECTOR ) { //there's room in the current selector sel.register( channel, listener, attachment ); channels.add( channel ); return; } } //we couldnt find room in any of the existing selectors, so start up a new one if allowed //max limit to the number of Selectors we are allowed to create if( selectors.size() >= MAX_SAFEMODE_SELECTORS ) { String msg = "Error: MAX_SAFEMODE_SELECTORS reached [" +selectors.size()+ "], no more socket channels can be registered. Too many peer connections."; Debug.out( msg ); selectFailure( listener, channel, attachment, new Throwable( msg ) ); //reject registration return; } if ( destroyed ){ String msg = "socket registered after controller destroyed"; Debug.out( msg ); selectFailure( listener, channel, attachment, new Throwable( msg ) ); //reject registration return; } VirtualChannelSelectorImpl sel = new VirtualChannelSelectorImpl( this, op, pause , randomise_keys); ArrayList chans = new ArrayList(); selectors.put( sel, chans ); sel.register( channel, listener, attachment ); chans.add( channel ); selectors_keyset_cow = new HashSet( selectors.keySet()); } finally{ selectors_mon.exit(); } } else { selector_impl.register( channel, listener, attachment ); } } /** * Pause selection operations for the given channel * @param channel to pause */ public void pauseSelects( AbstractSelectableChannel channel ) { if( SAFE_SELECTOR_MODE_ENABLED ) { try{ selectors_mon.enter(); //System.out.println( "pause - " + channel.hashCode() + " - " + Debug.getCompressedStackTrace()); for( Map.Entry> entry: selectors.entrySet()) { VirtualChannelSelectorImpl sel = entry.getKey(); ArrayList channels = entry.getValue(); if( channels.contains( channel ) ) { sel.pauseSelects( channel ); return; } } Debug.out( "pauseSelects():: channel not found!" ); } finally{ selectors_mon.exit(); } } else { selector_impl.pauseSelects( channel ); } } /** * Resume selection operations for the given channel * @param channel to resume */ public void resumeSelects( AbstractSelectableChannel channel ) { if( SAFE_SELECTOR_MODE_ENABLED ) { try{ selectors_mon.enter(); //System.out.println( "resume - " + channel.hashCode() + " - " + Debug.getCompressedStackTrace()); for( Map.Entry> entry: selectors.entrySet()) { VirtualChannelSelectorImpl sel = entry.getKey(); ArrayList channels = entry.getValue(); if( channels.contains( channel ) ) { sel.resumeSelects( channel ); return; } } Debug.out( "resumeSelects():: channel not found!" ); } finally{ selectors_mon.exit(); } } else { selector_impl.resumeSelects( channel ); } } /** * Cancel the selection operations for the given channel. * @param channel channel originally registered */ public void cancel( AbstractSelectableChannel channel ) { if( SAFE_SELECTOR_MODE_ENABLED ) { try{ selectors_mon.enter(); //System.out.println( "cancel - " + channel.hashCode() + " - " + Debug.getCompressedStackTrace()); for( Map.Entry> entry: selectors.entrySet()) { VirtualChannelSelectorImpl sel = entry.getKey(); ArrayList channels = entry.getValue(); if( channels.remove( channel ) ) { sel.cancel( channel ); return; } } } finally{ selectors_mon.exit(); } } else { if( selector_impl != null ) selector_impl.cancel( channel ); } } public void setRandomiseKeys( boolean _rk ) { randomise_keys = _rk; if( SAFE_SELECTOR_MODE_ENABLED ) { try{ selectors_mon.enter(); for( VirtualChannelSelectorImpl sel: selectors.keySet()){ sel.setRandomiseKeys( randomise_keys ); } } finally{ selectors_mon.exit(); } } else { if( selector_impl != null ) selector_impl.setRandomiseKeys( randomise_keys ); } } /** * Run a virtual select() operation, with the given selection timeout value; * (1) cancellations are processed (2) the select operation is performed; (3) * listener notification of completed selects (4) new registrations are processed * @param timeout in ms; if zero, block indefinitely * @return number of sockets selected */ public int select(long timeout) { if( SAFE_SELECTOR_MODE_ENABLED ) { boolean was_destroyed = destroyed; try{ int count = 0; for( VirtualChannelSelectorImpl sel: selectors_keyset_cow ){ count += sel.select( timeout ); } return count; }finally{ if ( was_destroyed ){ // destruction process requires select op after destroy... try{ selectors_mon.enter(); selectors.clear(); selectors_keyset_cow = new HashSet(); }finally{ selectors_mon.exit(); } } } } return selector_impl.select( timeout ); } public void destroy() { destroyed = true; if ( SAFE_SELECTOR_MODE_ENABLED ){ for( VirtualChannelSelectorImpl sel: selectors_keyset_cow ){ sel.destroy(); } }else{ selector_impl.destroy(); } } public boolean isDestroyed() { return( destroyed ); } public boolean isSafeSelectionModeEnabled() { return SAFE_SELECTOR_MODE_ENABLED; } public void enableSafeSelectionMode() { if( !SAFE_SELECTOR_MODE_ENABLED ) { SAFE_SELECTOR_MODE_ENABLED = true; COConfigurationManager.setParameter( "network.tcp.enable_safe_selector_mode", true ); initSafeMode(); } } public boolean selectSuccess( VirtualAbstractSelectorListener listener, AbstractSelectableChannel sc, Object attachment ) { if ( op == OP_ACCEPT ){ return(((VirtualAcceptSelectorListener)listener).selectSuccess( VirtualChannelSelector.this, (ServerSocketChannel)sc, attachment )); }else{ return(((VirtualSelectorListener)listener).selectSuccess( VirtualChannelSelector.this, (SocketChannel)sc, attachment )); } } public void selectFailure( VirtualAbstractSelectorListener listener, AbstractSelectableChannel sc, Object attachment, Throwable msg) { if ( op == OP_ACCEPT ){ ((VirtualAcceptSelectorListener)listener).selectFailure( VirtualChannelSelector.this, (ServerSocketChannel)sc, attachment, msg ); }else{ ((VirtualSelectorListener)listener).selectFailure( VirtualChannelSelector.this, (SocketChannel)sc, attachment, msg ); } } public interface VirtualAbstractSelectorListener { } /** * Listener for notification upon socket channel selection. */ public interface VirtualSelectorListener extends VirtualAbstractSelectorListener{ /** * Called when a channel is successfully selected for readyness. * @param attachment originally given with the channel's registration * @return indicator of whether or not any 'progress' was made due to this select * null -> progress made, String -> location of non progress * e.g. read-select -> read >0 bytes, write-select -> wrote > 0 bytes */ public boolean selectSuccess(VirtualChannelSelector selector, SocketChannel sc, Object attachment); /** * Called when a channel selection fails. * @param msg failure message */ public void selectFailure(VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg); } public interface VirtualAcceptSelectorListener extends VirtualAbstractSelectorListener{ /** * Called when a channel is successfully selected for readyness. * @param attachment originally given with the channel's registration * @return indicator of whether or not any 'progress' was made due to this select * e.g. read-select -> read >0 bytes, write-select -> wrote > 0 bytes */ public boolean selectSuccess(VirtualChannelSelector selector, ServerSocketChannel sc, Object attachment); /** * Called when a channel selection fails. * @param msg failure message */ public void selectFailure(VirtualChannelSelector selector, ServerSocketChannel sc, Object attachment, Throwable msg); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/OutgoingMessageQueue.java0000644000175000017500000001661010757735634027515 0ustar adrianadrian/* * Created on May 8, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager; import java.io.IOException; import com.aelitis.azureus.core.peermanager.messaging.*; /** * Priority-based outbound peer message queue. */ public interface OutgoingMessageQueue { public void setTransport( Transport _transport ); public int getMssSize(); /** * Set the message stream encoder that will be used to encode outgoing messages. * @param stream_encoder to use */ public void setEncoder( MessageStreamEncoder stream_encoder ) ; public MessageStreamEncoder getEncoder(); /** * Get the percentage of the current message that has already been sent out. * @return percentage complete (0-99), or -1 if no message is currently being sent */ public int getPercentDoneOfCurrentMessage(); /** * Destroy this queue; i.e. perform cleanup actions. */ public void destroy(); public boolean isDestroyed(); /** * Get the total number of bytes ready to be transported. * @return total bytes remaining */ public int getTotalSize(); /** * Whether or not an urgent message (one that needs an immediate send, i.e. a no-delay message) is queued. * @return true if there's a message tagged for immediate write */ public boolean hasUrgentMessage(); /** * Add a message to the message queue. * NOTE: Allows for manual listener notification at some later time, * using doListenerNotifications(), instead of notifying immediately * from within this method. This is useful if you want to invoke * listeners outside of some greater synchronised block to avoid * deadlock. * @param message message to add * @param manual_listener_notify true for manual notification, false for automatic */ public void addMessage( Message message, boolean manual_listener_notify ) ; /** * Remove all messages of the given types from the queue. * NOTE: Allows for manual listener notification at some later time, * using doListenerNotifications(), instead of notifying immediately * from within this method. This is useful if you want to invoke * listeners outside of some greater synchronised block to avoid * deadlock. * @param message_types type to remove * @param manual_listener_notify true for manual notification, false for automatic */ public void removeMessagesOfType( Message[] message_types, boolean manual_listener_notify ); /** * Remove a particular message from the queue. * NOTE: Only the original message found in the queue will be destroyed upon removal, * which may not necessarily be the one passed as the method parameter, * as some messages override equals() (i.e. BTRequest messages) instead of using reference * equality, and could be a completely different object, and would need to be destroyed * manually. If the message does not override equals, then any such method will likely * *not* be found and removed, as internal queued object was a new allocation on insertion. * NOTE: Allows for manual listener notification at some later time, * using doListenerNotifications(), instead of notifying immediately * from within this method. This is useful if you want to invoke * listeners outside of some greater synchronised block to avoid * deadlock. * @param message to remove * @param manual_listener_notify true for manual notification, false for automatic * @return true if the message was removed, false otherwise */ public boolean removeMessage( Message message, boolean manual_listener_notify ); /** * Deliver (write) message(s) data to the underlying transport. * * NOTE: Allows for manual listener notification at some later time, * using doListenerNotifications(), instead of notifying immediately * from within this method. This is useful if you want to invoke * listeners outside of some greater synchronised block to avoid * deadlock. * @param max_bytes maximum number of bytes to deliver * @param manual_listener_notify true for manual notification, false for automatic * @return number of bytes delivered * @throws IOException on delivery error */ public int deliverToTransport( int max_bytes, boolean manual_listener_notify ) throws IOException; /** * Manually send any unsent listener notifications. */ public void doListenerNotifications(); /** * Force all pending messages to be delivered */ public void flush(); public void setTrace( boolean on ); public String getQueueTrace(); /** * Add a listener to be notified of queue events. * @param listener */ public void registerQueueListener( MessageQueueListener listener ); /** * Cancel queue event notification listener. * @param listener */ public void cancelQueueListener( MessageQueueListener listener ); /** * Notifty the queue (and its listeners) of a message sent externally on the queue's behalf. * @param message sent externally */ public void notifyOfExternallySentMessage( Message message ); ///////////////////////////////////////////////////////////////// /** * Receive notification of queue events. */ public interface MessageQueueListener { /** * The given message has just been added to the queue. * @param message added for queuing * @return true if this message addition is allowed, false if it should be immediately removed without being queued or sent */ public boolean messageAdded( Message message ); /** * The given message has just been queued for sending out the transport. * @param message queued */ public void messageQueued( Message message ); /** * The given message has just been forcibly removed from the queue, * i.e. it was *not* sent out the transport. * @param message removed */ public void messageRemoved( Message message ); /** * The given message has been completely sent out through the transport. * @param message sent */ public void messageSent( Message message ); /** * The given number of protocol (overhead) bytes has been written to the transport. * @param byte_count number of protocol bytes */ public void protocolBytesSent( int byte_count ); /** * The given number of (piece) data bytes has been written to the transport. * @param byte_count number of data bytes */ public void dataBytesSent( int byte_count ); public void flush(); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/0000755000175000017500000000000011310377626023616 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminHTTPProxy.java0000644000175000017500000000276110750744030030625 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin; public interface NetworkAdminHTTPProxy { public String getName(); public String getHTTPHost(); public String getHTTPPort(); public String getHTTPSHost(); public String getHTTPSPort(); public String getUser(); public String[] getNonProxyHosts(); public Details getDetails() throws NetworkAdminException; public String getString(); interface Details { public String getServerName(); public String getResponse(); public String getAuthenticationType(); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminASNListener.java0000644000175000017500000000175111124570336031133 0ustar adrianadrian/* * Created on Dec 24, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.networkmanager.admin; public interface NetworkAdminASNListener { public void success( NetworkAdminASN asn ); public void failed( NetworkAdminException error ); } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/0000755000175000017500000000000011310377630024552 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminImpl.java0000644000175000017500000020003611305326642030643 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.io.IOException; import java.io.PrintWriter; import java.net.*; import java.nio.channels.ServerSocketChannel; import java.nio.channels.UnsupportedAddressTypeException; import java.util.*; import java.util.regex.Pattern; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.platform.PlatformManagerPingCallback; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.platform.PlatformManagerException; import org.gudy.azureus2.plugins.utils.Utilities; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.instancemanager.AZInstance; import com.aelitis.azureus.core.instancemanager.AZInstanceManager; import com.aelitis.azureus.core.instancemanager.AZInstanceManagerListener; import com.aelitis.azureus.core.instancemanager.AZInstanceTracked; import com.aelitis.azureus.core.networkmanager.admin.*; import com.aelitis.azureus.core.networkmanager.impl.http.HTTPNetworkManager; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager; import com.aelitis.azureus.core.networkmanager.impl.udp.UDPNetworkManager; import com.aelitis.azureus.core.proxy.socks.AESocksProxy; import com.aelitis.azureus.core.proxy.socks.AESocksProxyFactory; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.plugins.upnp.UPnPPlugin; import com.aelitis.azureus.plugins.upnp.UPnPPluginService; public class NetworkAdminImpl extends NetworkAdmin implements AEDiagnosticsEvidenceGenerator { private static final LogIDs LOGID = LogIDs.NWMAN; private static final boolean FULL_INTF_PROBE = false; private static InetAddress anyLocalAddress; private static InetAddress anyLocalAddressIPv4; private static InetAddress anyLocalAddressIPv6; private static InetAddress localhostV4; private static InetAddress localhostV6; static { try { anyLocalAddressIPv4 = InetAddress.getByAddress(new byte[] { 0,0,0,0 }); anyLocalAddressIPv6 = InetAddress.getByAddress(new byte[] {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}); anyLocalAddress = new InetSocketAddress(0).getAddress(); localhostV4 = InetAddress.getByAddress(new byte[] {127,0,0,1}); localhostV6 = InetAddress.getByAddress(new byte[] {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1}); } catch (UnknownHostException e) { e.printStackTrace(); } } private Set old_network_interfaces; private InetAddress[] currentBindIPs = new InetAddress[] { null }; private boolean supportsIPv6withNIO = true; private boolean supportsIPv6 = true; private boolean supportsIPv4 = true; private boolean IPv6_enabled; { COConfigurationManager.addAndFireParameterListener( "IPV6 Enable Support", new ParameterListener() { public void parameterChanged( String parameterName ) { setIPv6Enabled( COConfigurationManager.getBooleanParameter("IPV6 Enable Support")); } }); } private int roundRobinCounterV4 = 0; private int roundRobinCounterV6 = 0; private CopyOnWriteList listeners = new CopyOnWriteList(); private NetworkAdminRouteListener trace_route_listener = new NetworkAdminRouteListener() { private int node_count = 0; public boolean foundNode( NetworkAdminNode node, int distance, int rtt ) { node_count++; return( true ); } public boolean timeout( int distance ) { if ( distance == 3 && node_count == 0 ){ return( false ); } return( true ); } }; private static final int ASN_MIN_CHECK = 30*60*1000; private long last_asn_lookup_time; private List asn_ips_checked = new ArrayList(0); private List as_history = new ArrayList(); private AsyncDispatcher async_asn_dispacher = new AsyncDispatcher(); private static final int MAX_ASYNC_ASN_LOOKUPS = 1024; private Map async_asn_history = new LinkedHashMap(256,0.75f,true) { protected boolean removeEldestEntry( Map.Entry eldest) { return size() > 256; } }; private boolean initialised; public NetworkAdminImpl() { COConfigurationManager.addParameterListener( new String[] {"Bind IP","Enforce Bind IP"}, new ParameterListener() { public void parameterChanged( String parameterName ) { checkDefaultBindAddress( false ); } }); SimpleTimer.addPeriodicEvent( "NetworkAdmin:checker", 15000, new TimerEventPerformer() { public void perform( TimerEvent event ) { checkNetworkInterfaces( false, false ); } }); // populate initial values checkNetworkInterfaces( true, true ); checkDefaultBindAddress( true ); AEDiagnostics.addEvidenceGenerator( this ); initialised = true; } protected void setIPv6Enabled( boolean enabled ) { IPv6_enabled = enabled; supportsIPv6withNIO = enabled; supportsIPv6 = enabled; if ( initialised ){ checkNetworkInterfaces( false, true ); checkDefaultBindAddress( false ); } } protected void checkNetworkInterfaces( boolean first_time, boolean force ) { try{ Enumeration nis = NetworkInterface.getNetworkInterfaces(); boolean changed = false; if ( nis == null && old_network_interfaces == null ){ }else if ( nis == null ){ old_network_interfaces = null; changed = true; }else if ( old_network_interfaces == null ){ Set new_network_interfaces = new HashSet(); while( nis.hasMoreElements()){ new_network_interfaces.add( nis.nextElement()); } old_network_interfaces = new_network_interfaces; changed = true; }else{ Set new_network_interfaces = new HashSet(); while( nis.hasMoreElements()){ Object ni = nis.nextElement(); // NetworkInterface's "equals" method is based on ni name + addresses if ( !old_network_interfaces.contains( ni )){ changed = true; } new_network_interfaces.add( ni ); } if ( old_network_interfaces.size() != new_network_interfaces.size()){ changed = true; } old_network_interfaces = new_network_interfaces; } if ( changed || force ){ boolean newV6 = false; boolean newV4 = false; Set interfaces = old_network_interfaces; if (interfaces != null) { Iterator it = interfaces.iterator(); while (it.hasNext()) { NetworkInterface ni = it.next(); Enumeration addresses = ni.getInetAddresses(); while (addresses.hasMoreElements()) { InetAddress ia = (InetAddress) addresses.nextElement(); if (ia.isLoopbackAddress()){ continue; } if (ia instanceof Inet6Address && !ia.isLinkLocalAddress()){ if ( IPv6_enabled ){ newV6 = true; } }else if (ia instanceof Inet4Address){ newV4 = true; } } } } supportsIPv4 = newV4; supportsIPv6 = newV6; Logger.log(new LogEvent(LOGID, "NetworkAdmin: ipv4 supported: "+supportsIPv4+"; ipv6: "+supportsIPv6+"; probing v6+nio functionality")); if(newV6) { ServerSocketChannel channel = ServerSocketChannel.open(); try { channel.configureBlocking(false); channel.socket().bind(new InetSocketAddress(anyLocalAddressIPv6, 0)); Logger.log(new LogEvent(LOGID, "NetworkAdmin: testing nio + ipv6 bind successful")); supportsIPv6withNIO = true; } catch (Exception e) { Logger.log(new LogEvent(LOGID,LogEvent.LT_WARNING, "nio + ipv6 test failed",e)); supportsIPv6withNIO = false; } channel.close(); } else supportsIPv6withNIO = false; if ( !first_time ){ Logger.log( new LogEvent(LOGID, "NetworkAdmin: network interfaces have changed" )); } firePropertyChange( NetworkAdmin.PR_NETWORK_INTERFACES ); checkDefaultBindAddress( first_time ); } }catch( Throwable e ){ } } public InetAddress getMultiHomedOutgoingRoundRobinBindAddress(InetAddress target) { InetAddress[] addresses = currentBindIPs; boolean v6 = target instanceof Inet6Address; int previous = (v6 ? roundRobinCounterV6 : roundRobinCounterV4) % addresses.length; InetAddress toReturn = null; int i = previous; do { i++;i%= addresses.length; if (target == null || (v6 && addresses[i] instanceof Inet6Address) || (!v6 && addresses[i] instanceof Inet4Address)) { toReturn = addresses[i]; break; } else if(!v6 && addresses[i].isAnyLocalAddress()) { toReturn = anyLocalAddressIPv4; break; } } while(i!=previous); if(v6) roundRobinCounterV6 = i; else roundRobinCounterV4 = i; return toReturn != null ? toReturn : (v6 ? localhostV6 : localhostV4); } public InetAddress[] getMultiHomedServiceBindAddresses(boolean nio) { InetAddress[] bindIPs = currentBindIPs; for(int i=0;i res = new ArrayList(); InetAddress[] bind_ips = currentBindIPs; for ( InetAddress ip: bind_ips ){ if( !ip.isAnyLocalAddress()){ res.add( ip ); } } return( res.toArray( new InetAddress[ res.size()])); } } private InetAddress[] calcBindAddresses(final String addressString, boolean enforceBind) { ArrayList addrs = new ArrayList(); Pattern addressSplitter = Pattern.compile(";"); Pattern interfaceSplitter = Pattern.compile("[\\]\\[]"); String[] tokens = addressSplitter.split(addressString); addressLoop: for(int i=0;i 0) && NetworkInterface.getByInetAddress(parsedAddress) == null) continue; } catch (SocketException e) { Debug.printStackTrace(e); continue; } addrs.add(parsedAddress); continue; } // interface name String[] ifaces = interfaceSplitter.split(currentAddress); NetworkInterface netInterface = null; try { netInterface = NetworkInterface.getByName(ifaces[0]); } catch (SocketException e) { e.printStackTrace(); // should not happen } if(netInterface == null) continue; Enumeration interfaceAddresses = netInterface.getInetAddresses(); if(ifaces.length != 2) while(interfaceAddresses.hasMoreElements()) addrs.add((InetAddress)interfaceAddresses.nextElement()); else { int selectedAddress = 0; try { selectedAddress = Integer.parseInt(ifaces[1]); } catch (NumberFormatException e) {} // ignore, user could by typing atm for(int j=0;interfaceAddresses.hasMoreElements();j++,interfaceAddresses.nextElement()) if(j==selectedAddress) { addrs.add((InetAddress)interfaceAddresses.nextElement()); continue addressLoop; } } } if ( !IPv6_enabled ){ Iterator it = addrs.iterator(); while( it.hasNext()){ if ( it.next() instanceof Inet6Address ){ it.remove(); } } } if(addrs.size() < 1){ return new InetAddress[] {enforceBind ? localhostV4 : (hasIPV6Potential() ? anyLocalAddressIPv6 : anyLocalAddressIPv4)}; } return( addrs.toArray(new InetAddress[addrs.size()])); } protected void checkDefaultBindAddress(boolean first_time) { boolean changed = false; String bind_ip = COConfigurationManager.getStringParameter("Bind IP", "").trim(); boolean enforceBind = COConfigurationManager.getBooleanParameter("Enforce Bind IP"); InetAddress[] addrs = calcBindAddresses(bind_ip, enforceBind); changed = !Arrays.equals(currentBindIPs, addrs); if(changed){ currentBindIPs = addrs; if (!first_time) { String logmsg = "NetworkAdmin: default bind ip has changed to '"; for(int i=0;i bindable = new ArrayList(); NetworkAdminNetworkInterface[] interfaces = NetworkAdmin.getSingleton().getInterfaces(); for ( NetworkAdminNetworkInterface intf: interfaces ){ NetworkAdminNetworkInterfaceAddress[] addresses = intf.getAddresses(); for ( NetworkAdminNetworkInterfaceAddress address: addresses ){ InetAddress a = address.getAddress(); if ( canBind( a )){ bindable.add( a ); } } } return( bindable.toArray( new InetAddress[ bindable.size()])); } protected boolean canBind( InetAddress bind_ip ) { ServerSocketChannel ssc = null; try{ ssc = ServerSocketChannel.open(); ssc.socket().bind( new InetSocketAddress(bind_ip,0), 16 ); return( true ); }catch( Throwable e ){ return( false ); }finally{ if ( ssc != null ){ try{ ssc.close(); }catch( Throwable e ){ Debug.out( e ); } } } } public int getBindablePort( int prefer_port ) throws IOException { final int tries = 1024; Random random = new Random(); for ( int i=1;i<=tries;i++ ){ int port; if ( i == 1 && prefer_port != 0 ){ port = prefer_port; }else{ port = i==tries?0:random.nextInt(20000) + 40000; } ServerSocketChannel ssc = null; try{ ssc = ServerSocketChannel.open(); ssc.socket().setReuseAddress( true ); bind( ssc, null, port ); port = ssc.socket().getLocalPort(); ssc.close(); return( port ); }catch( Throwable e ){ if ( ssc != null ){ try{ ssc.close(); }catch( Throwable f ){ Debug.printStackTrace(e); } ssc = null; } } } throw( new IOException( "No bindable ports found" )); } protected void bind( ServerSocketChannel ssc, InetAddress address, int port ) throws IOException { if ( address == null ){ ssc.socket().bind( new InetSocketAddress( port ), 1024 ); }else{ ssc.socket().bind( new InetSocketAddress( address, port ), 1024 ); } } public InetAddress guessRoutableBindAddress() { try{ // see if we have a choice List local_addresses = new ArrayList(); List non_local_addresses = new ArrayList(); try{ NetworkAdminNetworkInterface[] interfaces = getInterfaces(); List possible = new ArrayList(); for (int i=0;i 0 ){ return( mapAddressToBindIP( InetAddress.getByName( socks[0].getHost()))); } }catch( Throwable e ){ } // next, same for nat devices try{ NetworkAdminNATDevice[] nat = getNATDevices(AzureusCoreFactory.getSingleton()); if ( nat.length > 0 ){ return( mapAddressToBindIP( nat[0].getAddress())); } }catch( Throwable e ){ } try{ final AESemaphore sem = new AESemaphore( "NA:conTest" ); final InetAddress[] can_connect = { null }; final int timeout = 10*1000; for (int i=0;i 0 ){ return( guessAddress( non_local_addresses )); } // lastly, select local one at random if ( local_addresses.size() > 0 ){ return( guessAddress( local_addresses )); } // ho hum return( null ); }catch( Throwable e ){ Debug.printStackTrace(e); return( null ); } } protected boolean canConnectWithBind( InetAddress bind_address, int timeout ) { Socket socket = null; try{ socket = new Socket(); socket.bind( new InetSocketAddress( bind_address, 0 )); socket.setSoTimeout( timeout ); socket.connect( new InetSocketAddress( "www.google.com", 80 ), timeout ); return( true ); }catch( Throwable e ){ return( false ); }finally{ if ( socket != null ){ try{ socket.close(); }catch( Throwable f ){ } } } } protected InetAddress mapAddressToBindIP( InetAddress address ) { boolean[] address_bits = bytesToBits( address.getAddress()); NetworkAdminNetworkInterface[] interfaces = getInterfaces(); InetAddress best_bind_address = null; int best_prefix = 0; for (int i=0;i best_prefix ){ best_prefix = k; best_bind_address = ba; } } } } } return( best_bind_address ); } protected boolean[] bytesToBits( byte[] bytes ) { boolean[] res = new boolean[bytes.length*8]; for (int i=0;i 0 ){ return((InetAddress)addresses.get(0)); } return( null ); } public InetAddress getDefaultPublicAddress() { Utilities utils = PluginInitializer.getDefaultInterface().getUtilities(); InetAddress address = utils.getPublicAddress(); if ( address != null ){ return( address ); } return( utils.getPublicAddress( true )); } @Override public InetAddress getDefaultPublicAddressV6() { if(!supportsIPv6) return null; // check bindings first for(InetAddress addr : currentBindIPs) { // found a specific bind address, use that one if(AddressUtils.isGlobalAddressV6(addr)) return addr; // found v6 any-local address, check interfaces for a best match if(addr instanceof Inet6Address && addr.isAnyLocalAddress()) { ArrayList addrs = new ArrayList(); for(NetworkInterface iface : old_network_interfaces) addrs.addAll(Collections.list(iface.getInetAddresses())); return AddressUtils.pickBestGlobalV6Address(addrs); } } return null; } public boolean hasDHTIPV6() { if ( hasIPV6Potential(false)){ InetAddress v6 = getDefaultPublicAddressV6(); return( v6 != null && !AddressUtils.isTeredo( v6 )); } return( false ); } protected void firePropertyChange( String property ) { Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((NetworkAdminPropertyChangeListener)it.next()).propertyChanged( property ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } public NetworkAdminNetworkInterface[] getInterfaces() { Set interfaces = old_network_interfaces; if ( interfaces == null ){ return( new NetworkAdminNetworkInterface[0] ); } NetworkAdminNetworkInterface[] res = new NetworkAdminNetworkInterface[interfaces.size()]; Iterator it = interfaces.iterator(); int pos = 0; while( it.hasNext()){ NetworkInterface ni = (NetworkInterface)it.next(); res[pos++] = new networkInterface( ni ); } return( res ); } public NetworkAdminProtocol[] getOutboundProtocols( AzureusCore azureus_core) { NetworkAdminProtocol[] res = { new NetworkAdminProtocolImpl( azureus_core, NetworkAdminProtocol.PT_HTTP ), new NetworkAdminProtocolImpl( azureus_core, NetworkAdminProtocol.PT_TCP ), new NetworkAdminProtocolImpl( azureus_core, NetworkAdminProtocol.PT_UDP ), }; return( res ); } public NetworkAdminProtocol[] getInboundProtocols( AzureusCore azureus_core) { List protocols = new ArrayList(); TCPNetworkManager tcp_manager = TCPNetworkManager.getSingleton(); if ( tcp_manager.isTCPListenerEnabled()){ protocols.add( new NetworkAdminProtocolImpl( azureus_core, NetworkAdminProtocol.PT_TCP, tcp_manager.getTCPListeningPortNumber())); } UDPNetworkManager udp_manager = UDPNetworkManager.getSingleton(); int done_udp = -1; if ( udp_manager.isUDPListenerEnabled()){ protocols.add( new NetworkAdminProtocolImpl( azureus_core, NetworkAdminProtocol.PT_UDP, done_udp = udp_manager.getUDPListeningPortNumber())); } if ( udp_manager.isUDPNonDataListenerEnabled()){ int port = udp_manager.getUDPNonDataListeningPortNumber(); if ( port != done_udp ){ protocols.add( new NetworkAdminProtocolImpl( azureus_core, NetworkAdminProtocol.PT_UDP, done_udp = udp_manager.getUDPNonDataListeningPortNumber())); } } HTTPNetworkManager http_manager = HTTPNetworkManager.getSingleton(); if ( http_manager.isHTTPListenerEnabled()){ protocols.add( new NetworkAdminProtocolImpl( azureus_core, NetworkAdminProtocol.PT_HTTP, http_manager.getHTTPListeningPortNumber())); } return((NetworkAdminProtocol[])protocols.toArray( new NetworkAdminProtocol[protocols.size()])); } public InetAddress testProtocol( NetworkAdminProtocol protocol ) throws NetworkAdminException { return( protocol.test( null )); } public NetworkAdminSocksProxy[] getSocksProxies() { String host = System.getProperty( "socksProxyHost", "" ).trim(); String port = System.getProperty( "socksProxyPort", "" ).trim(); String user = System.getProperty("java.net.socks.username", "" ).trim(); String password = System.getProperty("java.net.socks.password", "").trim(); List res = new ArrayList(); NetworkAdminSocksProxyImpl p1 = new NetworkAdminSocksProxyImpl( host, port, user, password ); if ( p1.isConfigured()){ res.add( p1 ); } if ( COConfigurationManager.getBooleanParameter( "Proxy.Data.Enable" ) && !COConfigurationManager.getBooleanParameter( "Proxy.Data.Same" )){ host = COConfigurationManager.getStringParameter( "Proxy.Data.Host" ); port = COConfigurationManager.getStringParameter( "Proxy.Data.Port" ); user = COConfigurationManager.getStringParameter( "Proxy.Data.Username" ); if ( user.trim().equalsIgnoreCase("")){ user = ""; } password = COConfigurationManager.getStringParameter( "Proxy.Data.Password" ); NetworkAdminSocksProxyImpl p2 = new NetworkAdminSocksProxyImpl( host, port, user, password ); if ( p2.isConfigured()){ res.add( p2 ); } } return((NetworkAdminSocksProxy[])res.toArray(new NetworkAdminSocksProxy[res.size()])); } public NetworkAdminHTTPProxy getHTTPProxy() { NetworkAdminHTTPProxyImpl res = new NetworkAdminHTTPProxyImpl(); if ( !res.isConfigured()){ res = null; } return( res ); } public NetworkAdminNATDevice[] getNATDevices( AzureusCore azureus_core ) { List devices = new ArrayList(); try{ PluginInterface upnp_pi = azureus_core.getPluginManager().getPluginInterfaceByClass( UPnPPlugin.class ); if ( upnp_pi != null ){ UPnPPlugin upnp = (UPnPPlugin)upnp_pi.getPlugin(); UPnPPluginService[] services = upnp.getServices(); for ( UPnPPluginService service: services ){ NetworkAdminNATDeviceImpl dev = new NetworkAdminNATDeviceImpl( service ); boolean same = false; for ( NetworkAdminNATDeviceImpl d: devices ){ if ( d.sameAs( dev )){ same = true; break; } } if ( !same ){ devices.add( dev ); } } } }catch( Throwable e ){ Debug.printStackTrace( e ); } return((NetworkAdminNATDevice[])devices.toArray(new NetworkAdminNATDevice[devices.size()])); } public NetworkAdminASN getCurrentASN() { List asns = COConfigurationManager.getListParameter( "ASN Details", new ArrayList()); if ( asns.size() == 0 ){ // migration from when we only persisted a single AS String as = ""; String asn = ""; String bgp = ""; try{ as = COConfigurationManager.getStringParameter( "ASN AS" ); asn = COConfigurationManager.getStringParameter( "ASN ASN" ); bgp = COConfigurationManager.getStringParameter( "ASN BGP" ); }catch( Throwable e ){ Debug.printStackTrace(e); } COConfigurationManager.removeParameter( "ASN AS" ); COConfigurationManager.removeParameter( "ASN ASN" ); COConfigurationManager.removeParameter( "ASN BGP" ); COConfigurationManager.removeParameter( "ASN Autocheck Performed Time" ); asns.add(ASNToMap(new NetworkAdminASNImpl(as, asn, bgp ))); COConfigurationManager.setParameter( "ASN Details", asns ); } if ( asns.size() > 0 ){ Map m = (Map)asns.get(0); return( ASNFromMap( m )); } return( new NetworkAdminASNImpl( "", "", "" )); } protected Map ASNToMap( NetworkAdminASNImpl x ) { Map m = new HashMap(); byte[] as = new byte[0]; byte[] asn = new byte[0]; byte[] bgp = new byte[0]; try{ as = x.getAS().getBytes("UTF-8"); asn = x.getASName().getBytes("UTF-8"); bgp = x.getBGPPrefix().getBytes("UTF-8"); }catch( Throwable e ){ Debug.printStackTrace(e); } m.put( "as", as ); m.put( "name", asn ); m.put( "bgp", bgp ); return( m ); } protected NetworkAdminASNImpl ASNFromMap( Map m ) { String as = ""; String asn = ""; String bgp = ""; try{ as = new String((byte[])m.get("as"),"UTF-8"); asn = new String((byte[])m.get("name"),"UTF-8"); bgp = new String((byte[])m.get("bgp"),"UTF-8"); }catch( Throwable e ){ Debug.printStackTrace(e); } return( new NetworkAdminASNImpl( as, asn, bgp )); } public NetworkAdminASN lookupCurrentASN( InetAddress address ) throws NetworkAdminException { NetworkAdminASN current = getCurrentASN(); if ( current.matchesCIDR( address )){ return( current ); } List asns = COConfigurationManager.getListParameter( "ASN Details", new ArrayList()); for (int i=0;i ASN_MIN_CHECK ){ last_asn_lookup_time = now; NetworkAdminASNLookupImpl lookup = new NetworkAdminASNLookupImpl( address ); NetworkAdminASNImpl x = lookup.lookup(); asn_ips_checked.add( address ); asns.add( 0, ASNToMap( x )); firePropertyChange( PR_AS ); return( x ); } return( current ); } public NetworkAdminASN lookupASN( InetAddress address ) throws NetworkAdminException { NetworkAdminASN existing = getFromASHistory( address ); if ( existing != null ){ return( existing ); } NetworkAdminASNLookupImpl lookup = new NetworkAdminASNLookupImpl( address ); NetworkAdminASNImpl result = lookup.lookup(); addToASHistory( result ); return( result ); } public void lookupASN( final InetAddress address, final NetworkAdminASNListener listener ) { synchronized( async_asn_history ){ NetworkAdminASN existing = async_asn_history.get( address ); if ( existing != null ){ listener.success( existing ); } } int queue_size = async_asn_dispacher.getQueueSize(); if ( queue_size >= MAX_ASYNC_ASN_LOOKUPS ){ listener.failed( new NetworkAdminException( "Too many outstanding lookups" )); }else{ async_asn_dispacher.dispatch( new AERunnable() { public void runSupport() { synchronized( async_asn_history ){ NetworkAdminASN existing = async_asn_history.get( address ); if ( existing != null ){ listener.success( existing ); return; } } try{ NetworkAdminASNLookupImpl lookup = new NetworkAdminASNLookupImpl( address ); NetworkAdminASNImpl result = lookup.lookup(); synchronized( async_asn_history ){ async_asn_history.put( address, result ); } listener.success( result ); }catch( NetworkAdminException e ){ listener.failed( e ); }catch( Throwable e ){ listener.failed( new NetworkAdminException( "lookup failed", e )); } } }); } } protected void addToASHistory( NetworkAdminASN asn ) { synchronized( as_history ){ boolean found = false; for (int i=0;i 256 ){ as_history.remove(0); } } } } protected NetworkAdminASN getFromASHistory( InetAddress address ) { synchronized( as_history ){ for (int i=0;i= 0 ){ long now = SystemTime.getCurrentTime(); if ( now < start_time ){ start_time = now; } if ( now - start_time >= max_millis ){ timeout = true; } } NetworkAdminNode node = null; if ( address != null ){ node = new networkNode( address, distance, millis ); nodes.add( node ); } boolean result; if ( listener == null ){ result = true; }else{ if ( node == null ){ result = listener.timeout( distance ); }else{ result = listener.foundNode( node, distance, millis ); } } return( result && !timeout ); } }); }catch( PlatformManagerException e ){ throw( new NetworkAdminException( "trace-route failed", e )); } return((NetworkAdminNode[])nodes.toArray( new NetworkAdminNode[nodes.size()])); } public boolean canPing() { PlatformManager pm = PlatformManagerFactory.getPlatformManager(); return( pm.hasCapability( PlatformManagerCapabilities.PingAvailability )); } public NetworkAdminNode pingTarget( InetAddress interface_address, InetAddress target, final int max_millis, final NetworkAdminRouteListener listener ) throws NetworkAdminException { PlatformManager pm = PlatformManagerFactory.getPlatformManager(); if ( !canPing()){ throw( new NetworkAdminException( "No ping capability on platform" )); } final NetworkAdminNode[] nodes = { null }; try{ pm.ping( interface_address, target, new PlatformManagerPingCallback() { private long start_time = SystemTime.getCurrentTime(); public boolean reportNode( int distance, InetAddress address, int millis ) { boolean timeout = false; if ( max_millis >= 0 ){ long now = SystemTime.getCurrentTime(); if ( now < start_time ){ start_time = now; } if ( now - start_time >= max_millis ){ timeout = true; } } NetworkAdminNode node = null; if ( address != null ){ node = new networkNode( address, distance, millis ); nodes[0] = node; } boolean result; if ( listener == null ){ result = false; }else{ if ( node == null ){ result = listener.timeout( distance ); }else{ result = listener.foundNode( node, distance, millis ); } } return( result && !timeout ); } }); }catch( PlatformManagerException e ){ throw( new NetworkAdminException( "ping failed", e )); } return( nodes[0] ); } public void getRoutes( final InetAddress target, final int max_millis, final NetworkAdminRoutesListener listener ) throws NetworkAdminException { final List sems = new ArrayList(); final List traces = new ArrayList(); NetworkAdminNetworkInterface[] interfaces = getInterfaces(); for (int i=0;i " + e.toString()); } writer.println( "Interfaces" ); writer.println( " " + getNetworkInterfacesAsString()); }finally{ writer.exdent(); } } private String getString( InetAddress[] addresses ) { String str = ""; for ( InetAddress address: addresses ){ str += (str.length()==0?"":", ") + address.getHostAddress(); } return( str ); } public void generateDiagnostics( final IndentWriter iw ) { Set public_addresses = new HashSet(); NetworkAdminHTTPProxy proxy = getHTTPProxy(); if ( proxy == null ){ iw.println( "HTTP proxy: none" ); }else{ iw.println( "HTTP proxy: " + proxy.getName()); try{ NetworkAdminHTTPProxy.Details details = proxy.getDetails(); iw.println( " name: " + details.getServerName()); iw.println( " resp: " + details.getResponse()); iw.println( " auth: " + details.getAuthenticationType()); }catch( NetworkAdminException e ){ iw.println( " failed: " + e.getLocalizedMessage()); } } NetworkAdminSocksProxy[] socks = getSocksProxies(); if ( socks.length == 0 ){ iw.println( "Socks proxy: none" ); }else{ for (int i=0;i " + e.toString()); } iw.println( "Interfaces" ); NetworkAdminNetworkInterface[] interfaces = getInterfaces(); if ( FULL_INTF_PROBE ){ if ( interfaces.length > 0 ){ if ( interfaces.length > 1 || interfaces[0].getAddresses().length > 1 ){ for (int i=0;i 0 ){ networkInterface.networkAddress address = (networkInterface.networkAddress)interfaces[0].getAddresses()[0]; try{ NetworkAdminNode[] nodes = address.getRoute( InetAddress.getByName("www.google.com"), 30000, trace_route_listener ); for (int i=0;i " + res.getAS() + "/" + res.getASName()); }catch( Throwable e ){ iw.println( " " + pub_address.getHostAddress() + " -> " + Debug.getNestedExceptionMessage(e)); } } } protected class networkInterface implements NetworkAdminNetworkInterface { private NetworkInterface ni; protected networkInterface( NetworkInterface _ni ) { ni = _ni; } public String getDisplayName() { return( ni.getDisplayName()); } public String getName() { return( ni.getName()); } public NetworkAdminNetworkInterfaceAddress[] getAddresses() { // BAH NetworkInterface has lots of goodies but is 1.6 Enumeration e = ni.getInetAddresses(); List addresses = new ArrayList(); while( e.hasMoreElements()){ InetAddress address = (InetAddress)e.nextElement(); if ((address instanceof Inet6Address) && !IPv6_enabled ){ continue; } addresses.add( new networkAddress(address)); } return((NetworkAdminNetworkInterfaceAddress[])addresses.toArray( new NetworkAdminNetworkInterfaceAddress[addresses.size()])); } public String getString() { String str = getDisplayName() + "/" + getName() + " ["; NetworkAdminNetworkInterfaceAddress[] addresses = getAddresses(); for (int i=0;i OK, public address=" + ext_addr ); }catch( NetworkAdminException e ){ iw.println( " -> Failed: " + Debug.getNestedExceptionMessage(e)); } } } public void logNATStatus( IndentWriter iw ) { if (AzureusCoreFactory.isCoreRunning()) { generateDiagnostics( iw, getInboundProtocols(AzureusCoreFactory.getSingleton())); } } public static void main( String[] args ) { boolean TEST_SOCKS_PROXY = false; boolean TEST_HTTP_PROXY = false; try{ if ( TEST_SOCKS_PROXY ){ AESocksProxy proxy = AESocksProxyFactory.create( 4567, 10000, 10000 ); proxy.setAllowExternalConnections( true ); System.setProperty( "socksProxyHost", "localhost" ); System.setProperty( "socksProxyPort", "4567" ); } if ( TEST_HTTP_PROXY ){ System.setProperty("http.proxyHost", "localhost" ); System.setProperty("http.proxyPort", "3128" ); System.setProperty("https.proxyHost", "localhost" ); System.setProperty("https.proxyPort", "3128" ); Authenticator.setDefault( new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return( new PasswordAuthentication( "fred", "bill".toCharArray())); } }); } IndentWriter iw = new IndentWriter( new PrintWriter( System.out )); iw.setForce( true ); COConfigurationManager.initialise(); AzureusCoreFactory.create(); NetworkAdmin admin = getSingleton(); //admin.logNATStatus( iw ); admin.generateDiagnostics( iw ); }catch( Throwable e){ e.printStackTrace(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTesterImpl.java0000644000175000017500000000542210620232042033002 0ustar adrianadrian/* * Created on May 1, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.util.Iterator; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTester; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTesterListener; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTesterResult; import com.aelitis.azureus.core.util.CopyOnWriteList; public abstract class NetworkAdminSpeedTesterImpl implements NetworkAdminSpeedTester { private CopyOnWriteList listeners = new CopyOnWriteList(); private boolean result_reported; protected abstract void abort( String reason ); protected abstract void abort( String reason, Throwable cause ); public void addListener(NetworkAdminSpeedTesterListener listener) { listeners.add( listener ); } public void removeListener(NetworkAdminSpeedTesterListener listener) { listeners.remove( listener ); } /** * Send a Result to all of the NetworkAdminSpeedTestListeners. * @param r - Result of the test. */ protected void sendResultToListeners( NetworkAdminSpeedTesterResult r ) { // just report the first result in case an implementation hits this more than once synchronized( this ){ if ( result_reported ){ return; } result_reported = true; } Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((NetworkAdminSpeedTesterListener)it.next()).complete( this, r ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected void sendStageUpdateToListeners( String status ) { Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((NetworkAdminSpeedTesterListener)it.next()).stage( this, status ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTesterBTImpl.javaazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTesterBTImpl.jav0000644000175000017500000007263111171750562033113 0ustar adrianadrian/** * Created on Apr 17, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.io.File; import java.net.URL; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.*; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.disk.DiskManagerPiece; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerPeerListener; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.security.SECertificateListener; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.*; import org.gudy.azureus2.plugins.peers.Peer; import org.gudy.azureus2.plugins.peers.PeerManager; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl; import com.aelitis.azureus.core.networkmanager.NetworkManager; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTestScheduler; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTester; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTesterResult; public class NetworkAdminSpeedTesterBTImpl extends NetworkAdminSpeedTesterImpl implements NetworkAdminSpeedTester { public static final String DOWNLOAD_AVE = "download-ave"; public static final String UPLOAD_AVE = "upload-ave"; public static final String DOWNLOAD_STD_DEV = "download-std-dev"; public static final String UPLOAD_STD_DEV = "upload-std-dev"; private static int testMode = TEST_TYPE_UPLOAD_ONLY; private static TorrentAttribute speedTestAttrib; private static NetworkAdminSpeedTesterResult lastResult; protected static void startUp() { PluginInterface plugin = PluginInitializer.getDefaultInterface(); speedTestAttrib = plugin.getTorrentManager().getPluginAttribute(NetworkAdminSpeedTesterBTImpl.class.getName()+".test.attrib"); org.gudy.azureus2.plugins.download.DownloadManager dm = plugin.getDownloadManager(); Download[] downloads = dm.getDownloads(); if(downloads!=null){ int num = downloads.length; for(int i=0; ireportedProgress ) reportedProgress=percentDownload; int progressBarVal = Math.round( reportedProgress*100.0f ); StringBuffer msg = new StringBuffer("progress: "); msg.append( progressBarVal ); //include the upload and download values. msg.append(" : download ave "); msg.append( stats.getDownloadAverage() ); msg.append(" : upload ave "); msg.append( stats.getUploadAverage() ); msg.append(" : "); int totalTimeLeft = (int)((MAX_TEST_TIME-totalDownloadTimeUsed)/1000); msg.append(totalTimeLeft); msg.append(" : "); int testTimeLeft = (int)((MAX_PEAK_TIME-totalTestTimeUsed)/1000); msg.append(testTimeLeft); sendStageUpdateToListeners( msg.toString() ); }//updateTestProgress /** * Calculate the avererage and standard deviation for a history. * @param history - List of Long values but that contains the sum downloaded at that time. * @return Map with values "ave" and "stddev" set */ //Map calculate(List history) private Map calculate(List history){ //convert the list of long values that sum the value into a list of deltas. List deltas = convertSumToDeltas(history); //sort Collections.sort(deltas); //remove the top and bottom 10% of the sample. This removes outliers from the mean. final int nSamples = deltas.size(); final int nRemove = nSamples/10; //removing high values. for(int i=nSamples-1; i retVal = new HashMap(); Map retVal = new HashMap(); retVal.put(AVE, autoboxDouble(aveRate)); retVal.put(STD_DEV,autoboxDouble(stddev)); return retVal; }//calculate /** * Convert a list of sums into a list of download rates per second. * @param sumHistory - List with download sum for each second. * @return - List with the download rate for each second. */ private List convertSumToDeltas(List sumHistory){ //find the first element to inlcude in the stat. int numStats = sumHistory.size(); int i = findIndexPeak(numStats); List deltas = new ArrayList(numStats); if (i == 0) {return deltas;} long prevSumDownload = autoboxLong(sumHistory.get(i-1)); long currSumDownload; while(ipeakTime){ break; } }//for return i; } /** * Based on the previous data cancluate an average and a standard deviation. * Return this data in a Map object. * @return Map as a contain for stats. Map keys are "ave" and "dev". */ NetworkAdminSpeedTesterResult calculateDownloadRate() { //calculate the BT download rate. //Map resDown = calculate(historyDownloadSpeed); Map resDown = calculate(historyDownloadSpeed); //calculate the BT upload rate. //Map resUp = calculate(historyUploadSpeed); Map resUp = calculate(historyUploadSpeed); return new BitTorrentResult(resUp,resDown); }//calculateDownloadRate /** * In this version the test is limited to MAX_TEST_TIME since the start of the test * of MAX_PEAK_TIME (i.e. time since the peak download rate has been reached). Which * ever condition is first will finish the download. * @return true if the test done condition has been reached. */ boolean checkForTestDone(){ long currTime = SystemTime.getCurrentTime(); //have we reached the max time for this test? if( (currTime-startTime)>MAX_TEST_TIME ){ return true; } //have we been near the peak download value for max time? return (currTime - peakTime) > MAX_PEAK_TIME; }//checkForTestDone /** * We set a new "peak" value if it has exceeded the previous peak value by 10%. * @param stat - * @param lastTotalDownload - * @param currTime - * @return total downloaded so far. */ long checkForNewPeakValue(DownloadStats stat, long lastTotalDownload, long currTime) { //upload only used the "uploaded" data. The "download only" and "both" uses download. long totTransferred; if(testMode==TEST_TYPE_UPLOAD_ONLY){ totTransferred = stat.getUploaded(); }else{ totTransferred = stat.getDownloaded(); } long currTransferRate = totTransferred-lastTotalDownload; //if the current rate is 10% greater then the previous max, reset the max, and test timer. if( currTransferRate > peakRate ){ peakRate = (long) (currTransferRate*1.1); peakTime = currTime; } return totTransferred; }//checkForNewPeakValue }//class TorrentSpeedTestMonitorThread class BitTorrentResult implements NetworkAdminSpeedTesterResult{ long time; int downspeed; int upspeed; boolean hadError = false; String lastError = ""; /** * Build a Result for a successful test. * @param uploadRes - Map of upload results. * @param downloadRes - Map of download results. */ public BitTorrentResult(Map uploadRes, Map downloadRes){ time = SystemTime.getCurrentTime(); Double dAve = (Double)downloadRes.get(TorrentSpeedTestMonitorThread.AVE); Double uAve = (Double)uploadRes.get(TorrentSpeedTestMonitorThread.AVE); downspeed = dAve.intValue(); upspeed = uAve.intValue(); } /** * Build a Result if the test failed with an error. * @param errorMsg - why the test failed. */ public BitTorrentResult(String errorMsg){ time = SystemTime.getCurrentTime(); hadError=true; lastError = errorMsg; } public NetworkAdminSpeedTester getTest() { return( NetworkAdminSpeedTesterBTImpl.this ); } public long getTestTime() { return time; } public int getDownloadSpeed() { return downspeed; } public int getUploadSpeed() { return upspeed; } public boolean hadError() { return hadError; } public String getLastError() { return lastError; } public String getResultString(){ StringBuffer sb = new StringBuffer(); //Time SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmss z"); String d = format.format( new Date(time) ); sb.append(d).append(" "); sb.append("type: BT test "); //Get test info. sb.append("mode: ").append( getMode() ); //Get crypto sb.append(" encrypted: "); if( use_crypto ){ sb.append("y"); }else{ sb.append("n"); } if(hadError){ //Error sb.append(" Last Error: ").append(lastError); }else{ //Result sb.append(" download speed: ").append(downspeed).append(" bits/sec"); sb.append(" upload speed: ").append(upspeed).append(" bits/sec"); } return sb.toString(); }//getString public String toString(){ StringBuffer sb = new StringBuffer("[com.aelitis.azureus.core.networkmanager.admin.impl.NetworkAdminSpeedTesterBTImpl"); sb.append(" ").append( getResultString() ).append(" "); sb.append("]"); return sb.toString(); } }//class BitTorrentResult private static long autoboxLong(Object o){ return autoboxLong( (Long) o ); } private static long autoboxLong(Long l){ return l.longValue(); } private static Long autoboxLong(long l){ return new Long(l); } private static Double autoboxDouble(double d){ return new Double(d); } }//class azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminASNLookupImpl.java0000644000175000017500000001712411214303632032374 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import javax.naming.*; import javax.naming.directory.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminException; import com.aelitis.azureus.core.util.DNSUtils; public class NetworkAdminASNLookupImpl { private static final String WHOIS_ADDRESS = "whois.cymru.com"; private static final int WHOIS_PORT = 43; private static final int TIMEOUT = 30000; private InetAddress address; protected NetworkAdminASNLookupImpl( InetAddress _address ) { address= _address; } protected NetworkAdminASNImpl lookup() throws NetworkAdminException { // Debug.outDiagLoggerOnly( "ASN lookup for '" + address + "'" ); return( lookupDNS( address )); } protected NetworkAdminASNImpl lookupTCP( InetAddress address ) throws NetworkAdminException { try{ Socket socket = new Socket(); int timeout = TIMEOUT; long start = SystemTime.getCurrentTime(); socket.connect( new InetSocketAddress( WHOIS_ADDRESS, WHOIS_PORT ), timeout ); long end = SystemTime.getCurrentTime(); timeout -= (end - start ); if ( timeout <= 0 ){ throw( new NetworkAdminException( "Timeout on connect" )); }else if ( timeout > TIMEOUT ){ timeout = TIMEOUT; } socket.setSoTimeout( timeout ); try{ OutputStream os = socket.getOutputStream(); String command = "-u -p " + address.getHostAddress() + "\r\n"; os.write( command.getBytes()); os.flush(); InputStream is = socket.getInputStream(); byte[] buffer = new byte[1024]; String result = ""; while( true ){ int len = is.read( buffer ); if ( len <= 0 ){ break; } result += new String( buffer, 0, len ); } return( processResult( result )); }finally{ socket.close(); } }catch( Throwable e ){ throw( new NetworkAdminException( "whois connection failed", e )); } } protected NetworkAdminASNImpl lookupDNS( InetAddress address ) throws NetworkAdminException { // first query for the as byte[] bytes = address.getAddress(); String ip_query = "origin.asn.cymru.com"; for (int i=0;i<4;i++){ ip_query = ( bytes[i] & 0xff ) + "." + ip_query; } // "33544 | 64.71.0.0/20 | US | arin | 2006-05-04" String ip_result = lookupDNS( ip_query ); NetworkAdminASNImpl result = processResult( "AS | BGP Prefix | CC | Reg | Date | AS Name" + "\n" + ip_result + " | n/a" ); String as = result.getAS(); if ( as.length() > 0 ){ // now query for ASN // 33544 | US | arin | 2005-01-19 | WILINE - WiLine Networks Inc. String asn_query = "AS" + as + ".asn.cymru.com"; try{ String asn_result = lookupDNS( asn_query ); if ( asn_result != null ){ int pos = asn_result.lastIndexOf( '|' ); if ( pos != -1 ){ String asn = asn_result.substring( pos+1 ).trim(); result.setASName( asn ); } } }catch( Throwable e ){ Debug.outNoStack( "ASN lookup for '" + asn_query+ "' failed: " + e.getMessage()); } } return( result ); } protected String lookupDNS( String query ) throws NetworkAdminException { DirContext context = null; try{ context = DNSUtils.getInitialDirContext(); Attributes attrs = context.getAttributes( query, new String[]{ "TXT" }); NamingEnumeration n_enum = attrs.getAll(); while( n_enum.hasMoreElements()){ Attribute attr = (Attribute)n_enum.next(); NamingEnumeration n_enum2 = attr.getAll(); while( n_enum2.hasMoreElements()){ String attribute = (String)n_enum2.nextElement(); if ( attribute != null ){ attribute = attribute.trim(); if ( attribute.startsWith( "\"" )){ attribute = attribute.substring(1); } if ( attribute.endsWith( "\"" )){ attribute = attribute.substring(0,attribute.length()-1); } if ( attribute.length() > 0 ){ return( attribute ); } } } } throw( new NetworkAdminException( "DNS query returned no results" )); }catch( Throwable e ){ throw( new NetworkAdminException( "DNS query failed", e )); }finally{ if ( context != null ){ try{ context.close(); }catch( Throwable e ){ } } } } protected NetworkAdminASNImpl processResult( String result ) { StringTokenizer lines = new StringTokenizer( result, "\n" ); int line_number = 0; List keywords = new ArrayList(); Map map = new HashMap(); while( lines.hasMoreTokens()){ String line = lines.nextToken().trim(); line_number++; if ( line_number > 2 ){ break; } StringTokenizer tok = new StringTokenizer( line, "|" ); int token_number = 0; while( tok.hasMoreTokens()){ String token = tok.nextToken().trim(); if ( line_number == 1 ){ keywords.add( token.toLowerCase( MessageText.LOCALE_ENGLISH )); }else{ if ( token_number >= keywords.size()){ break; }else{ String kw = (String)keywords.get( token_number ); map.put( kw, token ); } } token_number++; } } String as = (String)map.get( "as" ); String asn = (String)map.get( "as name" ); String bgp_prefix = (String)map.get( "bgp prefix" ); if ( bgp_prefix != null ){ int pos = bgp_prefix.indexOf(' '); if ( pos != -1 ){ bgp_prefix = bgp_prefix.substring(pos+1).trim(); } if ( bgp_prefix.indexOf('/') == -1 ){ bgp_prefix = null; } } return( new NetworkAdminASNImpl( as, asn, bgp_prefix )); } public static void main( String[] args ) { try{ NetworkAdminASNLookupImpl lookup = new NetworkAdminASNLookupImpl( InetAddress.getByName( "64.71.8.82" )); System.out.println( lookup.lookup().getString()); /* InetAddress test = InetAddress.getByName( "255.71.15.1" ); System.out.println( test + " -> " + matchesCIDR( "255.71.0.0/20", test )); */ }catch( Throwable e ){ e.printStackTrace(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminHTTPProxyImpl.java0000644000175000017500000002755611166774660032437 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.StringTokenizer; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.networkmanager.ProtocolEndpoint; import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminException; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminHTTPProxy; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPConnectionManager; import com.aelitis.azureus.core.networkmanager.impl.tcp.ProtocolEndpointTCP; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPTransportHelperFilterFactory; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPTransportImpl; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; public class NetworkAdminHTTPProxyImpl implements NetworkAdminHTTPProxy { private static final String NL = "\015\012"; private final String TARGET_HOST = VersionCheckClient.HTTP_SERVER_ADDRESS_V4; private final int TARGET_PORT = VersionCheckClient.HTTP_SERVER_PORT; private String http_host; private String http_port; private String https_host; private String https_port; private String user; private String password; private String[] non_proxy_hosts; protected NetworkAdminHTTPProxyImpl() { http_host = System.getProperty("http.proxyHost", "" ).trim(); http_port = System.getProperty("http.proxyPort", "" ).trim(); https_host = System.getProperty("https.proxyHost", "" ).trim(); https_port = System.getProperty("https.proxyPort", "" ).trim(); user = System.getProperty("http.proxyUser", "" ).trim(); password = System.getProperty("http.proxyPassword", "" ).trim(); String nph = System.getProperty("http.nonProxyHosts", "" ).trim(); StringTokenizer tok = new StringTokenizer( nph, "|" ); non_proxy_hosts = new String[tok.countTokens()]; int pos = 0; while( tok.hasMoreTokens()){ non_proxy_hosts[pos++] = tok.nextToken(); } } public String getName() { String res = ""; if ( http_host.length() > 0 ){ res = "http=" + http_host + ":" + http_port; } if ( https_host.length() > 0 ){ res += (res.length()==0?"":", " ) + "https=" + https_host + ":" + https_port; } return( res ); } protected boolean isConfigured() { return( http_host.length() > 0 || https_host.length() > 0 ); } public String getHTTPHost() { return( http_host ); } public String getHTTPPort() { return( http_port ); } public String getHTTPSHost() { return( https_host ); } public String getHTTPSPort() { return( https_port ); } public String getUser() { return( user ); } public String[] getNonProxyHosts() { return( non_proxy_hosts ); } public String getString() { String res = getName(); if ( user.length() > 0 ){ res += " [auth=" + user + "]"; } try{ NetworkAdminHTTPProxy.Details details = getDetails(); res += " server=" + details.getServerName(); res += ", response=" + details.getResponse(); res += ", auth=" + details.getAuthenticationType(); }catch( NetworkAdminException e ){ res += " failed to query proxy - " + e.getLocalizedMessage(); } return( res ); } public Details getDetails() throws NetworkAdminException { final int RES_CONNECT_FAILED = 0; final int RES_PROXY_FAILED = 1; final int RES_OK = 3; final AESemaphore sem = new AESemaphore( "NetworkAdminSocksProxy:test" ); final int[] result = { RES_CONNECT_FAILED }; final NetworkAdminException[] error = { null }; final ProxyDetails[] details = {null}; try{ InetSocketAddress socks_address = new InetSocketAddress( InetAddress.getByName( http_host ), Integer.parseInt(http_port)); final InetSocketAddress target_address = new InetSocketAddress( TARGET_HOST, TARGET_PORT ); TCPConnectionManager.ConnectListener connect_listener = new TCPConnectionManager.ConnectListener() { public void connectAttemptStarted() { } public void connectSuccess( SocketChannel channel ) { final TCPTransportImpl transport = new TCPTransportImpl( new ProtocolEndpointTCP( target_address ), false, false, null ); transport.setFilter( TCPTransportHelperFilterFactory.createTransparentFilter( channel )); final long start_time = SystemTime.getCurrentTime(); try{ String get_str = VersionCheckClient.getSingleton().getHTTPGetString( true, false ); ByteBuffer request = ByteBuffer.wrap( get_str.getBytes()); while( request.hasRemaining()){ if ( transport.write( new ByteBuffer[]{ request }, 0, 1 ) < 1 ) { if( SystemTime.getCurrentTime() - start_time > 30*1000 ) { String error = "proxy handshake message send timed out after 30sec"; Debug.out( error ); throw new IOException( error ); } try{ Thread.sleep( 50 ); }catch( Throwable t ){ t.printStackTrace(); } } } TCPNetworkManager.getSingleton().getReadSelector().register( transport.getSocketChannel(), new VirtualChannelSelector.VirtualSelectorListener() { private byte[] reply_buffer = new byte[8192]; private ByteBuffer reply = ByteBuffer.wrap( reply_buffer ); public boolean selectSuccess( VirtualChannelSelector selector, SocketChannel sc, Object attachment ) { try{ if( SystemTime.getCurrentTime() - start_time > 30*1000 ){ throw( new Exception( "Timeout" )); } long len = transport.read( new ByteBuffer[]{ reply }, 0, 1 ); if ( len <= 0 ){ return( false ); } String str = new String( reply_buffer, 0, reply.position()); if ( str.indexOf( NL + NL ) != -1 ){ System.out.println( str ); String server_name = "unknown"; String auth = "none"; String response = "unknown"; StringTokenizer tok = new StringTokenizer( str, "\n" ); int line_num = 0; while( tok.hasMoreTokens()){ String token = tok.nextToken().trim(); if ( token.length() == 0 ){ continue; } line_num++; if ( line_num == 1 ){ int pos = token.indexOf(' '); if ( pos != -1 ){ response = token.substring( pos + 1 ).trim(); } }else{ int pos = token.indexOf(':'); if ( pos != -1 ){ String lhs = token.substring( 0, pos ).trim().toLowerCase( MessageText.LOCALE_ENGLISH ); String rhs = token.substring( pos+1 ).trim(); if ( lhs.equals( "server" )){ if ( !response.startsWith( "200" )){ server_name = rhs; } }else if ( lhs.equals( "via" )){ server_name = rhs; int p = server_name.indexOf(' '); if ( p != -1 ){ server_name = server_name.substring( p+1 ).trim(); } }else if ( lhs.equals( "proxy-authenticate" )){ auth = rhs; } } } } details[0] = new ProxyDetails( server_name, response, auth ); transport.close( "Done" ); result[0] = RES_OK; sem.release(); }else{ TCPNetworkManager.getSingleton().getReadSelector().resumeSelects( transport.getSocketChannel() ); } return( true ); } catch( Throwable t ) { return false; } } public void selectFailure( VirtualChannelSelector selector, SocketChannel sc, Object attachment, Throwable msg ) { result[0] = RES_PROXY_FAILED; error[0] = new NetworkAdminException( "Proxy error", msg ); transport.close( "Proxy error" ); sem.release(); } }, null ); }catch( Throwable t ) { result[0] = RES_PROXY_FAILED; error[0] = new NetworkAdminException( "Proxy connect failed", t ); sem.release(); } } public void connectFailure( Throwable failure_msg ) { result[0] = RES_CONNECT_FAILED; error[0] = new NetworkAdminException( "Connect failed", failure_msg ); sem.release(); } }; TCPNetworkManager.getSingleton().getConnectDisconnectManager().requestNewConnection( socks_address, connect_listener, ProtocolEndpoint.CONNECT_PRIORITY_MEDIUM ); }catch( Throwable e ){ result[0] = RES_CONNECT_FAILED; error[0] = new NetworkAdminException( "Connect failed", e ); sem.release(); } if ( !sem.reserve(10000)){ result[0] = RES_CONNECT_FAILED; error[0] = new NetworkAdminException( "Connect timeout" ); } if ( result[0] == RES_OK ){ return( details[0] ); } throw( error[0] ); } protected class ProxyDetails implements Details { private String name; private String response; private String auth_type; protected ProxyDetails( String _name, String _response, String _auth_type ) { name = _name; response = _response; auth_type = _auth_type; } public String getServerName() { return( name ); } public String getResponse() { return( response ); } public String getAuthenticationType() { return( auth_type ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminProtocolTester.java0000644000175000017500000000257010533501454032733 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.net.InetAddress; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminException; public interface NetworkAdminProtocolTester { public InetAddress testOutbound( InetAddress bind_ip, int bind_port ) throws NetworkAdminException; public InetAddress testInbound( InetAddress bind_ip, int local_port ) throws NetworkAdminException; } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminTCPTester.java0000644000175000017500000000576611141701400031557 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import org.gudy.azureus2.core3.ipchecker.natchecker.NatChecker; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminException; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminProgressListener; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; public class NetworkAdminTCPTester implements NetworkAdminProtocolTester { private AzureusCore core; private NetworkAdminProgressListener listener; protected NetworkAdminTCPTester( AzureusCore _core, NetworkAdminProgressListener _listener ) { core = _core; listener = _listener; } public InetAddress testOutbound( InetAddress bind_ip, int bind_port ) throws NetworkAdminException { try{ // try to use our service first return( VersionCheckClient.getSingleton().getExternalIpAddressTCP( bind_ip, bind_port, false )); }catch( Throwable e ){ // fallback to something else try{ Socket socket = new Socket(); if ( bind_ip != null ){ socket.bind( new InetSocketAddress( bind_ip, bind_port )); }else if ( bind_port != 0 ){ socket.bind( new InetSocketAddress( bind_port )); } socket.setSoTimeout( 10000 ); socket.connect( new InetSocketAddress( "www.google.com", 80 ), 10000 ); socket.close(); return( null ); }catch( Throwable f ){ throw( new NetworkAdminException( "Outbound test failed", e )); } } } public InetAddress testInbound( InetAddress bind_ip, int local_port ) throws NetworkAdminException { NatChecker checker = new NatChecker( core, bind_ip, local_port, false ); if ( checker.getResult() == NatChecker.NAT_OK ){ return( checker.getExternalAddress()); }else{ throw( new NetworkAdminException( "NAT test failed: " + checker.getAdditionalInfo())); } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminASNImpl.java0000644000175000017500000001021110645412416031200 0ustar adrianadrian/* * Created on Jul 11, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.net.InetAddress; import org.gudy.azureus2.core3.tracker.protocol.PRHelpers; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminASN; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminException; public class NetworkAdminASNImpl implements NetworkAdminASN { private String as; private String asn; private String bgp_prefix; protected NetworkAdminASNImpl( String _as, String _asn, String _bgp ) { as = _as; asn = _asn; bgp_prefix = _bgp; } public String getAS() { return( as==null?"":as ); } public String getASName() { return( asn==null?"":asn ); } protected void setASName( String s ) { asn = s; } public String getBGPPrefix() { return( bgp_prefix==null?"":bgp_prefix ); } public InetAddress getBGPStartAddress() { if ( bgp_prefix == null ){ return( null ); } try{ return( getCIDRStartAddress()); }catch( NetworkAdminException e ){ Debug.out(e); return( null ); } } protected InetAddress getCIDRStartAddress() throws NetworkAdminException { int pos = bgp_prefix.indexOf('/'); try{ return( InetAddress.getByName( bgp_prefix.substring(0,pos))); }catch( Throwable e ){ throw( new NetworkAdminException( "Parse failure for '" + bgp_prefix + "'", e )); } } protected InetAddress getCIDREndAddress() throws NetworkAdminException { int pos = bgp_prefix.indexOf('/'); try{ InetAddress start = InetAddress.getByName( bgp_prefix.substring(0,pos)); int cidr_mask = Integer.parseInt( bgp_prefix.substring( pos+1 )); int rev_mask = 0; for (int i=0;i<32-cidr_mask;i++){ rev_mask = ( rev_mask << 1 ) | 1; } byte[] bytes = start.getAddress(); bytes[0] |= (rev_mask>>24)&0xff; bytes[1] |= (rev_mask>>16)&0xff; bytes[2] |= (rev_mask>>8)&0xff; bytes[3] |= (rev_mask)&0xff; return( InetAddress.getByAddress( bytes )); }catch( Throwable e ){ throw( new NetworkAdminException( "Parse failure for '" + bgp_prefix + "'", e )); } } public boolean matchesCIDR( InetAddress address ) { if ( bgp_prefix == null || bgp_prefix.length() == 0 ){ return( false ); } try{ InetAddress start = getCIDRStartAddress(); InetAddress end = getCIDREndAddress(); long l_start = PRHelpers.addressToLong( start ); long l_end = PRHelpers.addressToLong( end ); long test = PRHelpers.addressToLong( address ); return( test >= l_start && test <= l_end ); }catch( Throwable e ){ Debug.printStackTrace(e); return( false ); } } public InetAddress getBGPEndAddress() { if ( bgp_prefix == null ){ return( null ); } try{ return( getCIDREndAddress()); }catch( NetworkAdminException e ){ Debug.out(e); return( null ); } } public boolean sameAs( NetworkAdminASN other ) { return( getAS().equals( other.getAS())); } public String getString() { return( "as=" + getAS() + ",asn=" + getASName() + ", bgp_prefx=" + getBGPPrefix() + "[" +getBGPStartAddress() + "-" + getBGPEndAddress() + "]" ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATDeviceImpl.java0000644000175000017500000000605011141701400032311 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.net.InetAddress; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminNATDevice; import com.aelitis.azureus.plugins.upnp.UPnPPluginService; public class NetworkAdminNATDeviceImpl implements NetworkAdminNATDevice { private UPnPPluginService service; private InetAddress external_address; private long address_time; protected NetworkAdminNATDeviceImpl( UPnPPluginService _service ) { service = _service; } public String getName() { return( service.getName()); } public InetAddress getAddress() { try{ return( InetAddress.getByName(service.getAddress())); }catch( Throwable e ){ Debug.printStackTrace(e); return( null ); } } public int getPort() { return( service.getPort()); } public InetAddress getExternalAddress() { long now = SystemTime.getCurrentTime(); if ( external_address != null && now > address_time && now - address_time < 60*1000 ){ return( external_address ); } try{ external_address = InetAddress.getByName(service.getExternalAddress()); address_time = now; }catch( Throwable e ){ Debug.printStackTrace(e); } return( external_address ); } protected boolean sameAs( NetworkAdminNATDeviceImpl other ) { if ( !getAddress().equals( other.getAddress()) || getPort() != other.getPort()){ return( false ); } InetAddress e1 = getExternalAddress(); InetAddress e2 = other.getExternalAddress(); if ( e1 == null && e2 == null ){ return( true ); } if ( e1 == null || e2 == null ){ return( false ); } return( e1.equals( e2 )); } public String getString() { String res = getName(); res += ": address=" + service.getAddress() + ":" + service.getPort(); InetAddress ext = getExternalAddress(); if ( ext == null ){ res += ", no public address available"; }else{ res += ", public address=" + ext.getHostAddress(); } return( res ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminHTTPTester.java0000644000175000017500000000560311141701400031676 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.net.InetAddress; import java.net.URL; import java.net.URLConnection; import org.gudy.azureus2.core3.ipchecker.natchecker.NatChecker; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminException; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminProgressListener; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; public class NetworkAdminHTTPTester implements NetworkAdminProtocolTester { private AzureusCore core; private NetworkAdminProgressListener listener; protected NetworkAdminHTTPTester( AzureusCore _core, NetworkAdminProgressListener _listener ) { core = _core; listener = _listener; } public InetAddress testOutbound( InetAddress bind_ip, int bind_port ) throws NetworkAdminException { if ( bind_ip != null || bind_port != 0 ){ throw( new NetworkAdminException("HTTP tester doesn't support local bind options")); } try{ // try to use our service first return( VersionCheckClient.getSingleton().getExternalIpAddressHTTP(false)); }catch( Throwable e ){ // fallback to something else try{ URL url = new URL( "http://www.google.com/" ); URLConnection connection = url.openConnection(); connection.setConnectTimeout( 10000 ); connection.connect(); return( null ); }catch( Throwable f ){ throw( new NetworkAdminException( "Outbound test failed", e )); } } } public InetAddress testInbound( InetAddress bind_ip, int local_port ) throws NetworkAdminException { NatChecker checker = new NatChecker( core, bind_ip, local_port, true ); if ( checker.getResult() == NatChecker.NAT_OK ){ return( checker.getExternalAddress()); }else{ throw( new NetworkAdminException( "NAT check failed: " + checker.getAdditionalInfo())); } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTestSchedulerImpl.javaazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTestSchedulerImp0000644000175000017500000000652411234500262033226 0ustar adrianadrian/** * Created on Apr 17, 2007 * Created by Alan Snyder * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import com.aelitis.azureus.core.networkmanager.admin.*; public class NetworkAdminSpeedTestSchedulerImpl implements NetworkAdminSpeedTestScheduler { private static NetworkAdminSpeedTestSchedulerImpl instance = null; private NetworkAdminSpeedTestScheduledTestImpl currentTest = null; public static synchronized NetworkAdminSpeedTestScheduler getInstance(){ if(instance==null){ instance = new NetworkAdminSpeedTestSchedulerImpl(); } return instance; } private NetworkAdminSpeedTestSchedulerImpl(){ } public void initialise() { NetworkAdminSpeedTesterBTImpl.startUp(); } public synchronized NetworkAdminSpeedTestScheduledTest getCurrentTest() { return( currentTest ); } public synchronized NetworkAdminSpeedTestScheduledTest scheduleTest(int type) throws NetworkAdminException { if ( currentTest != null ){ throw( new NetworkAdminException( "Test already scheduled" )); } if ( type == TEST_TYPE_BT ){ PluginInterface plugin = PluginInitializer.getDefaultInterface(); currentTest = new NetworkAdminSpeedTestScheduledTestImpl(plugin, new NetworkAdminSpeedTesterBTImpl(plugin) ); currentTest.getTester().setMode(type); currentTest.addListener( new NetworkAdminSpeedTestScheduledTestListener() { public void stage(NetworkAdminSpeedTestScheduledTest test, String step){} public void complete(NetworkAdminSpeedTestScheduledTest test ) { synchronized( NetworkAdminSpeedTestSchedulerImpl.this ){ currentTest = null; } } }); }else{ throw( new NetworkAdminException( "Unknown test type" )); } return( currentTest ); } /** * Get the most recent result for the test. * * @return - Result */ public NetworkAdminSpeedTesterResult getLastResult(int type) { if ( type == TEST_TYPE_BT ){ return( NetworkAdminSpeedTesterBTImpl.getLastResult()); }else{ Debug.out( "Unknown test type" ); return( null ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminProtocolImpl.java0000644000175000017500000000620411142421402032353 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.net.InetAddress; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminException; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminNetworkInterfaceAddress; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminProgressListener; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminProtocol; public class NetworkAdminProtocolImpl implements NetworkAdminProtocol { private AzureusCore core; private int type; private int port; protected NetworkAdminProtocolImpl( AzureusCore _core, int _type ) { core = _core; type = _type; port = -1; } protected NetworkAdminProtocolImpl( AzureusCore _core, int _type, int _port ) { core = _core; type = _type; port = _port; } public int getType() { return( type ); } public int getPort() { return( port ); } public InetAddress test( NetworkAdminNetworkInterfaceAddress address ) throws NetworkAdminException { return( test( address, null )); } public InetAddress test( NetworkAdminNetworkInterfaceAddress address, NetworkAdminProgressListener listener ) throws NetworkAdminException { InetAddress bind_ip = address==null?null:address.getAddress(); NetworkAdminProtocolTester tester; if ( type == PT_HTTP ){ tester = new NetworkAdminHTTPTester( core, listener ); }else if ( type == PT_TCP ){ tester = new NetworkAdminTCPTester( core, listener ); }else{ tester = new NetworkAdminUDPTester( core, listener ); } InetAddress res; if ( port <= 0 ){ res = tester.testOutbound( bind_ip, 0 ); }else{ res = tester.testInbound( bind_ip, port ); } return( res ); } public String getTypeString() { String res; if ( type == PT_HTTP ){ res = "HTTP"; }else if ( type == PT_TCP ){ res = "TCP"; }else{ res = "UDP"; } return( res ); } public String getName() { String res = getTypeString(); if ( port == -1 ){ return( res + " outbound" ); }else{ return( res + " port " + port + " inbound" ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPReply.java0000644000175000017500000000434610533443714031761 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Map; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.BEncoder; import com.aelitis.net.udp.uc.PRUDPPacketReply; public class NetworkAdminNATUDPReply extends PRUDPPacketReply { private Map payload; public NetworkAdminNATUDPReply( int trans_id ) { super( NetworkAdminNATUDPCodecs.ACT_NAT_REPLY, trans_id ); } protected NetworkAdminNATUDPReply( DataInputStream is, int trans_id ) throws IOException { super( NetworkAdminNATUDPCodecs.ACT_NAT_REPLY, trans_id ); short len = is.readShort(); if ( len <= 0 ){ throw( new IOException( "invalid length" )); } byte[] bytes = new byte[len]; is.read( bytes ); payload = BDecoder.decode( bytes ); } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); byte[] bytes = BEncoder.encode( payload ); os.writeShort( (short)bytes.length ); os.write( bytes ); } public Map getPayload() { return( payload ); } public void setPayload( Map _payload ) { payload = _payload; } public String getString() { return( super.getString()); } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTestScheduledTestImpl.javaazureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTestScheduledTes0000644000175000017500000006737310645033472033240 0ustar adrianadrian/* * Created on May 1, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.lang.reflect.Field; import java.net.URL; import java.net.URLClassLoader; import java.net.URLEncoder; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.BEncoder; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadManagerListener; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl; import org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader.ResourceDownloaderFactoryImpl; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTestScheduledTest; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTestScheduledTestListener; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTestScheduler; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTester; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTesterListener; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTesterResult; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.plugins.upnp.UPnPPlugin; public class NetworkAdminSpeedTestScheduledTestImpl implements NetworkAdminSpeedTestScheduledTest { //Types of requests sent to SpeedTest scheduler. private static final long REQUEST_TEST = 0; private static final long CHALLENGE_REPLY = 1; private static final long TEST_RESULT = 2; private static int ZERO_DOWNLOAD_SETTING = -1; private PluginInterface plugin; private NetworkAdminSpeedTesterImpl tester; private String detectedRouter; private SpeedTestDownloadState preTestSettings; private byte[] challenge_id; private long delay_millis; private long max_speed; private TOTorrent test_torrent; private volatile boolean aborted; private CopyOnWriteList listeners = new CopyOnWriteList(); protected NetworkAdminSpeedTestScheduledTestImpl( PluginInterface _plugin, NetworkAdminSpeedTesterImpl _tester ) { plugin = _plugin; tester = _tester; //detect the router. PluginInterface upnp = plugin.getPluginManager().getPluginInterfaceByClass( UPnPPlugin.class ); if( upnp != null ){ detectedRouter = upnp.getPluginconfig().getPluginStringParameter("plugin.info"); } tester.addListener( new NetworkAdminSpeedTesterListener() { public void complete( NetworkAdminSpeedTester tester, NetworkAdminSpeedTesterResult result ) { try{ sendResult( result ); }finally{ reportComplete(); } } public void stage( NetworkAdminSpeedTester tester, String step ) { } }); } public NetworkAdminSpeedTester getTester() { return( tester ); } public long getMaxUpBytePerSec() { return( max_speed ); } public long getMaxDownBytePerSec() { return( max_speed ); } public boolean start() { if ( schedule()){ new AEThread( "NetworkAdminSpeedTestScheduledTest:delay", true ) { public void runSupport() { long delay_ticks = delay_millis/1000; for (int i=0;i props.put(TORRENT_UPLOAD_LIMIT, new Integer(uploadLimit) ); props.put(TORRENT_DOWNLOAD_LIMIT, new Integer(downloadLimit) ); torrentLimits.put(d,props); } /** * Get the upload or download limit for this Download object before the test started. * @param d - Download * @param param - String * @return - limit as int. */ private int getDownloadDetails(Download d, String param){ if(d==null || param==null ) throw new IllegalArgumentException("null inputs."); if(!param.equals(TORRENT_UPLOAD_LIMIT) && !param.equals(TORRENT_DOWNLOAD_LIMIT)) throw new IllegalArgumentException("invalid param. param="+param); Map out = (Map) torrentLimits.get(d); Integer limit = (Integer) out.get(param); return limit.intValue(); } /** * Get all the Download keys in this Map. * @return - Download[] */ private Download[] getAllDownloads(){ Download[] a = new Download[0]; return (Download[]) torrentLimits.keySet().toArray(a); } } protected void reportStage( String str ) { Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((NetworkAdminSpeedTestScheduledTestListener)it.next()).stage( this, str ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } protected void reportComplete() { resetSpeedLimits(); Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((NetworkAdminSpeedTestScheduledTestListener)it.next()).complete( this ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } public void addListener( NetworkAdminSpeedTestScheduledTestListener listener ) { listeners.add( listener ); } public void removeListener( NetworkAdminSpeedTestScheduledTestListener listener ) { listeners.remove( listener ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminUDPTester.java0000644000175000017500000001535410757223332031572 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.plugins.PluginInterface; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminASN; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminException; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminProgressListener; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; import com.aelitis.azureus.plugins.upnp.UPnPPlugin; import com.aelitis.azureus.plugins.upnp.UPnPPluginService; import com.aelitis.net.udp.uc.PRUDPPacketHandler; import com.aelitis.net.udp.uc.PRUDPPacketHandlerFactory; import com.aelitis.net.udp.uc.PRUDPReleasablePacketHandler; public class NetworkAdminUDPTester implements NetworkAdminProtocolTester { public static final String UDP_SERVER_ADDRESS = Constants.NAT_TEST_SERVER; public static final int UDP_SERVER_PORT = 2081; // 2084; static{ NetworkAdminNATUDPCodecs.registerCodecs(); } private AzureusCore core; private NetworkAdminProgressListener listener; protected NetworkAdminUDPTester( AzureusCore _core, NetworkAdminProgressListener _listener ) { core = _core; listener = _listener; } public InetAddress testOutbound( InetAddress bind_ip, int bind_port ) throws NetworkAdminException { try{ return( VersionCheckClient.getSingleton().getExternalIpAddressUDP(bind_ip, bind_port,false)); }catch( Throwable e ){ throw( new NetworkAdminException( "Outbound test failed", e )); } } public InetAddress testInbound( InetAddress bind_ip, int bind_port ) throws NetworkAdminException { PRUDPReleasablePacketHandler handler = PRUDPPacketHandlerFactory.getReleasableHandler( bind_port ); PRUDPPacketHandler packet_handler = handler.getHandler(); HashMap data_to_send = new HashMap(); PluginInterface pi_upnp = core.getPluginManager().getPluginInterfaceByClass( UPnPPlugin.class ); String upnp_str = null; if( pi_upnp != null ) { UPnPPlugin upnp = (UPnPPlugin)pi_upnp.getPlugin(); /* UPnPMapping mapping = upnp.getMapping( true, port ); if ( mapping == null ) { new_mapping = mapping = upnp.addMapping( "NAT Tester", true, port, true ); // give UPnP a chance to work try { Thread.sleep( 500 ); } catch (Throwable e) { Debug.printStackTrace( e ); } } */ UPnPPluginService[] services = upnp.getServices(); if ( services.length > 0 ){ upnp_str = ""; for (int i=0;i 0 ){ data_to_send.put( "as", as ); } if ( asn.length() > 0 ){ data_to_send.put( "asn", asn ); } data_to_send.put( "locale", MessageText.getCurrentLocale().toString()); Random random = new Random(); data_to_send.put( "id", new Long( random.nextLong())); try{ packet_handler.setExplicitBindAddress( bind_ip ); Throwable last_error = null; long timeout = 5000; long timeout_inc = 5000; try{ for (int i=0;i<3;i++){ data_to_send.put( "seq", new Long(i)); try{ // connection ids for requests must always have their msb set... // apart from the original darn udp tracker spec.... long connection_id = 0x8000000000000000L | random.nextLong(); NetworkAdminNATUDPRequest request_packet = new NetworkAdminNATUDPRequest( connection_id ); request_packet.setPayload( data_to_send ); listener.reportProgress( "Sending outbound packet and waiting for reply probe (timeout=" + timeout + ")" ); NetworkAdminNATUDPReply reply_packet = (NetworkAdminNATUDPReply)packet_handler.sendAndReceive( null, request_packet, new InetSocketAddress( UDP_SERVER_ADDRESS, UDP_SERVER_PORT ), timeout, PRUDPPacketHandler.PRIORITY_IMMEDIATE ); Map reply = reply_packet.getPayload(); byte[] ip_bytes = (byte[])reply.get( "ip_address" ); if ( ip_bytes == null ){ throw( new NetworkAdminException( "IP address missing in reply" )); } byte[] reason = (byte[])reply.get( "reason" ); if ( reason != null ) { throw( new NetworkAdminException( new String( reason, "UTF8"))); } return( InetAddress.getByAddress( ip_bytes )); }catch( Throwable e){ last_error = e; timeout += timeout_inc; } } if ( last_error != null ){ throw( last_error ); } throw( new NetworkAdminException( "Timeout" )); }finally{ try{ data_to_send.put( "seq", new Long(99)); long connection_id = 0x8000000000000000L | random.nextLong(); NetworkAdminNATUDPRequest request_packet = new NetworkAdminNATUDPRequest( connection_id ); request_packet.setPayload( data_to_send ); // fire off one last packet in attempt to inform server of completion listener.reportProgress( "Sending completion event" ); packet_handler.send( request_packet, new InetSocketAddress( UDP_SERVER_ADDRESS, UDP_SERVER_PORT )); }catch( Throwable e){ } } }catch( NetworkAdminException e ){ throw( e ); }catch( Throwable e ){ throw( new NetworkAdminException( "Inbound test failed", e )); }finally{ packet_handler.setExplicitBindAddress( null ); handler.release(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSocksProxyImpl.java0000644000175000017500000001442210776600716032722 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager.admin.impl; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.channels.SocketChannel; import java.util.*; import org.gudy.azureus2.core3.util.AESemaphore; import com.aelitis.azureus.core.networkmanager.ProtocolEndpoint; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminException; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSocksProxy; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPConnectionManager; import com.aelitis.azureus.core.networkmanager.impl.tcp.ProtocolEndpointTCP; import com.aelitis.azureus.core.networkmanager.impl.tcp.ProxyLoginHandler; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPTransportHelperFilterFactory; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPTransportImpl; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; public class NetworkAdminSocksProxyImpl implements NetworkAdminSocksProxy { private final String TARGET_HOST = VersionCheckClient.HTTP_SERVER_ADDRESS_V4; private final int TARGET_PORT = VersionCheckClient.HTTP_SERVER_PORT; private String host; private String port; private String user; private String password; protected NetworkAdminSocksProxyImpl( String _host, String _port, String _user, String _password ) { host = _host; port = _port; user = _user; password = _password; } protected boolean isConfigured() { return( host.length() > 0 ); } public String getName() { return( host + ":" + port ); } public String getHost() { return( host ); } public String getPort() { return( port ); } public String getUser() { return( user ); } public String[] getVersionsSupported() throws NetworkAdminException { NetworkAdminException failure = null; List versions = new ArrayList(); try{ testVersion( "V4" ); versions.add( "4" ); }catch( NetworkAdminException e ){ failure = e; } try{ testVersion( "V4a" ); versions.add( "4a" ); }catch( NetworkAdminException e ){ failure = e; } try{ testVersion( "V5" ); versions.add( "5" ); }catch( NetworkAdminException e ){ failure = e; } if ( versions.size() > 0 ){ return((String[])versions.toArray( new String[versions.size()])); } throw( failure ); } public String getString() { String res = getName(); if ( user.length() > 0 ){ res += " [auth=" + user + "]"; } res += ", versions="; try{ String[] versions = getVersionsSupported(); for (int j=0;j0 bytes written. * @return true if the transport is write ready, false if not yet ready */ public boolean isReadyForWrite( EventWaiter waiter ); /** * Is the transport ready to read, * i.e. will a read request result in >0 bytes read. * @return 0 if the transport is read ready, ms since last ready or created if never ready */ public long isReadyForRead( EventWaiter waiter ); public boolean isTCP(); /** * Get a textual description for this transport. * @return description */ public String getDescription(); } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/ConnectionEndpoint.java0000644000175000017500000001124610776600714027177 0ustar adrianadrian/* * Created on 16 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import org.gudy.azureus2.core3.util.AddressUtils; import com.aelitis.azureus.core.networkmanager.Transport.ConnectListener; import com.aelitis.azureus.core.networkmanager.impl.tcp.ProtocolEndpointTCP; import com.aelitis.azureus.core.networkmanager.impl.udp.ProtocolEndpointUDP; public class ConnectionEndpoint { private InetSocketAddress notional_address; private ProtocolEndpoint[] protocols; public ConnectionEndpoint( InetSocketAddress _notional_address ) { notional_address = _notional_address; } public InetSocketAddress getNotionalAddress() { return( notional_address ); } public boolean matchIP( String ip ) { if ( matchIP( ip, notional_address )){ return( true ); } ProtocolEndpoint[] peps = getProtocols(); for (int i=0;i UNLIMITED_RATE ) max_upload_rate_bps_normal = UNLIMITED_RATE; max_lan_upload_rate_bps = COConfigurationManager.getIntParameter( "Max LAN Upload Speed KBs" ) * 1024; if( max_lan_upload_rate_bps < 1024 ) max_lan_upload_rate_bps = UNLIMITED_RATE; if( max_lan_upload_rate_bps > UNLIMITED_RATE ) max_lan_upload_rate_bps = UNLIMITED_RATE; max_upload_rate_bps_seeding_only = COConfigurationManager.getIntParameter( "Max Upload Speed Seeding KBs" ) * 1024; if( max_upload_rate_bps_seeding_only < 1024 ) max_upload_rate_bps_seeding_only = UNLIMITED_RATE; if( max_upload_rate_bps_seeding_only > UNLIMITED_RATE ) max_upload_rate_bps_seeding_only = UNLIMITED_RATE; seeding_only_mode_allowed = COConfigurationManager.getBooleanParameter( "enable.seedingonly.upload.rate" ); external_max_download_rate_bps = max_download_rate_bps = (int)(COConfigurationManager.getIntParameter( "Max Download Speed KBs" ) * 1024); // leave 5KiB/s room for the request limiting if( max_download_rate_bps < 1024 || max_download_rate_bps > UNLIMITED_RATE) max_download_rate_bps = UNLIMITED_RATE; else if(USE_REQUEST_LIMITING && FeatureAvailability.isRequestLimitingEnabled()) max_download_rate_bps += Math.max(max_download_rate_bps * 0.1, 5*1024); lan_rate_enabled = COConfigurationManager.getBooleanParameter("LAN Speed Enabled"); max_lan_download_rate_bps = COConfigurationManager.getIntParameter( "Max LAN Download Speed KBs" ) * 1024; if( max_lan_download_rate_bps < 1024 ) max_lan_download_rate_bps = UNLIMITED_RATE; if( max_lan_download_rate_bps > UNLIMITED_RATE ) max_lan_download_rate_bps = UNLIMITED_RATE; refreshRates(); } }); } private final List write_controllers; private final List read_controllers; { int num_read = COConfigurationManager.getIntParameter( "network.control.read.processor.count" ); read_controllers = new ArrayList(num_read); for (int i=0;i(num_write); for (int i=0;i 1 ); private final TransferProcessor download_processor = new TransferProcessor( TransferProcessor.TYPE_DOWNLOAD, new LimitedRateGroup() { public String getName() { return( "global_down" ); } public int getRateLimitBytesPerSecond() { return max_download_rate_bps; } }, read_controllers.size() > 1 ); private final TransferProcessor lan_upload_processor = new TransferProcessor( TransferProcessor.TYPE_UPLOAD, new LimitedRateGroup() { public String getName() { return( "global_lan_up" ); } public int getRateLimitBytesPerSecond() { return max_lan_upload_rate_bps; } }, write_controllers.size() > 1 ); private final TransferProcessor lan_download_processor = new TransferProcessor( TransferProcessor.TYPE_DOWNLOAD, new LimitedRateGroup() { public String getName() { return( "global_lan_down" ); } public int getRateLimitBytesPerSecond() { return max_lan_download_rate_bps; } }, read_controllers.size() > 1 ); public static boolean isLANRateEnabled() { return( lan_rate_enabled ); } private NetworkManagerStats stats = new NetworkManagerStats(); private NetworkManager() { } public static int getMinMssSize() { return Math.min( TCPNetworkManager.getTcpMssSize(), UDPNetworkManager.getUdpMssSize()); } private static void refreshRates() { if( isSeedingOnlyUploadRate() ) { max_upload_rate_bps = max_upload_rate_bps_seeding_only; } else { max_upload_rate_bps = max_upload_rate_bps_normal; } if( max_upload_rate_bps < 1024 ) { Debug.out( "max_upload_rate_bps < 1024=" +max_upload_rate_bps); } //ensure that mss isn't greater than up/down rate limits int min_rate = Math.min( max_upload_rate_bps, Math.min( max_download_rate_bps, Math.min( max_lan_upload_rate_bps, max_lan_download_rate_bps ))); TCPNetworkManager.refreshRates( min_rate ); UDPNetworkManager.refreshRates( min_rate ); } public static boolean isSeedingOnlyUploadRate() { return seeding_only_mode_allowed && seeding_only_mode; } public static int getMaxUploadRateBPSNormal() { if( max_upload_rate_bps_normal == UNLIMITED_RATE ) return 0; return max_upload_rate_bps_normal; } public static int getMaxUploadRateBPSSeedingOnly() { if( max_upload_rate_bps_seeding_only == UNLIMITED_RATE ) return 0; return max_upload_rate_bps_seeding_only; } /** * This method is for display purposes only, the internal rate limiting is 10% higher than returned by this method! */ public static int getMaxDownloadRateBPS() { if( max_download_rate_bps == UNLIMITED_RATE ) return 0; return external_max_download_rate_bps; } public static final int CRYPTO_OVERRIDE_NONE = 0; public static final int CRYPTO_OVERRIDE_REQUIRED = 1; public static final int CRYPTO_OVERRIDE_NOT_REQUIRED = 2; public static boolean getCryptoRequired( int override_level ) { if ( override_level == CRYPTO_OVERRIDE_NONE ){ return( REQUIRE_CRYPTO_HANDSHAKE ); }else if ( override_level == CRYPTO_OVERRIDE_REQUIRED ){ return( true ); }else{ return( false ); } } public void initialize(AzureusCore core) { HTTPNetworkManager.getSingleton(); core.getGlobalManager().addListener( new GlobalManagerListener() { public void downloadManagerAdded( DownloadManager dm ){} public void downloadManagerRemoved( DownloadManager dm ){} public void destroyInitiated(){} public void destroyed(){} public void seedingStatusChanged( boolean seeding_only, boolean b ) { seeding_only_mode = seeding_only; refreshRates(); } }); } /** * Get the singleton instance of the network manager. * @return the network manager */ public static NetworkManager getSingleton() { return instance; } /** * Create a new unconnected remote network connection (for outbound-initiated connections). * @param remote_address to connect to * @param encoder default message stream encoder to use for the outgoing queue * @param decoder default message stream decoder to use for the incoming queue * @return a new connection */ public NetworkConnection createConnection( ConnectionEndpoint target, MessageStreamEncoder encoder, MessageStreamDecoder decoder, boolean connect_with_crypto, boolean allow_fallback, byte[][] shared_secrets ) { return NetworkConnectionFactory.create( target, encoder, decoder, connect_with_crypto, allow_fallback, shared_secrets ); } /** * Request the acceptance and routing of new incoming connections that match the given initial byte sequence. * @param matcher initial byte sequence used for routing * @param listener for handling new inbound connections * @param factory to use for creating default stream encoder/decoders */ public void requestIncomingConnectionRouting( ByteMatcher matcher, final RoutingListener listener, final MessageStreamFactory factory ) { IncomingConnectionManager.getSingleton().registerMatchBytes( matcher, new IncomingConnectionManager.MatchListener() { public boolean autoCryptoFallback() { return( listener.autoCryptoFallback()); } public void connectionMatched( Transport transport, Object routing_data ) { listener.connectionRouted( NetworkConnectionFactory.create( transport, factory.createEncoder(), factory.createDecoder() ), routing_data ); } }); } public NetworkConnection bindTransport( Transport transport, MessageStreamEncoder encoder, MessageStreamDecoder decoder ) { return( NetworkConnectionFactory.create( transport, encoder, decoder )); } /** * Cancel a request for inbound connection routing. * @param matcher byte sequence originally used to register */ public void cancelIncomingConnectionRouting( ByteMatcher matcher ) { IncomingConnectionManager.getSingleton().deregisterMatchBytes( matcher ); } /** * Add an upload entity for write processing. * @param entity to add */ public void addWriteEntity( RateControlledEntity entity, int partition_id ) { if ( write_controllers.size() == 1 || partition_id < 0 ){ write_controllers.get(0).addWriteEntity(entity); }else{ WriteController controller = write_controllers.get((partition_id%(write_controllers.size()-1))+1 ); controller.addWriteEntity( entity ); } } /** * Remove an upload entity from write processing. * @param entity to remove */ public void removeWriteEntity( RateControlledEntity entity ) { if ( write_controllers.size() == 1 ){ write_controllers.get(0).removeWriteEntity( entity ); }else{ for (WriteController write_controller: write_controllers ){ write_controller.removeWriteEntity( entity ); } } } /** * Add a download entity for read processing. * @param entity to add */ public void addReadEntity( RateControlledEntity entity, int partition_id ) { if ( read_controllers.size() == 1 || partition_id < 0 ){ read_controllers.get(0).addReadEntity(entity); }else{ ReadController controller = read_controllers.get((partition_id%(read_controllers.size()-1))+1 ); controller.addReadEntity( entity ); } } /** * Remove a download entity from read processing. * @param entity to remove */ public void removeReadEntity( RateControlledEntity entity ) { if ( read_controllers.size() == 1 ){ read_controllers.get(0).removeReadEntity( entity ); }else{ for (ReadController read_controller: read_controllers ){ read_controller.removeReadEntity( entity ); } } } /** * Register peer connection for network upload and download handling. * NOTE: The given max rate limits are ignored until the connection is upgraded. * NOTE: The given max rate limits are ignored for LANLocal connections. * @param peer_connection to register for network transfer processing * @param upload_group upload rate limit group * @param download_group download rate limit group */ public void startTransferProcessing( NetworkConnectionBase peer_connection ) { if( peer_connection.isLANLocal() && lan_rate_enabled ) { lan_upload_processor.registerPeerConnection( peer_connection, true ); lan_download_processor.registerPeerConnection( peer_connection, false ); } else { upload_processor.registerPeerConnection( peer_connection, true ); download_processor.registerPeerConnection( peer_connection, false ); } } /** * Cancel network upload and download handling for the given connection. * @param peer_connection to cancel */ public void stopTransferProcessing( NetworkConnectionBase peer_connection ) { if( lan_upload_processor.isRegistered( peer_connection )) { lan_upload_processor.deregisterPeerConnection( peer_connection ); lan_download_processor.deregisterPeerConnection( peer_connection ); } else { upload_processor.deregisterPeerConnection( peer_connection ); download_processor.deregisterPeerConnection( peer_connection ); } } /** * Upgrade the given connection to high-speed network transfer handling. * @param peer_connection to upgrade */ public void upgradeTransferProcessing( NetworkConnectionBase peer_connection, int partition_id ) { if( lan_upload_processor.isRegistered( peer_connection )) { lan_upload_processor.upgradePeerConnection( peer_connection, partition_id ); lan_download_processor.upgradePeerConnection( peer_connection, partition_id ); } else { upload_processor.upgradePeerConnection( peer_connection, partition_id ); download_processor.upgradePeerConnection( peer_connection, partition_id ); } } /** * Downgrade the given connection back to a normal-speed network transfer handling. * @param peer_connection to downgrade */ public void downgradeTransferProcessing( NetworkConnectionBase peer_connection ) { if( lan_upload_processor.isRegistered( peer_connection )) { lan_upload_processor.downgradePeerConnection( peer_connection ); lan_download_processor.downgradePeerConnection( peer_connection ); } else { upload_processor.downgradePeerConnection( peer_connection ); download_processor.downgradePeerConnection( peer_connection ); } } public void addRateLimiter( NetworkConnectionBase peer_connection, LimitedRateGroup group, boolean upload ) { if ( upload ){ if ( lan_upload_processor.isRegistered( peer_connection )){ lan_upload_processor.addRateLimiter( peer_connection, group ); }else{ upload_processor.addRateLimiter( peer_connection, group ); } }else{ if ( lan_download_processor.isRegistered( peer_connection )){ lan_download_processor.addRateLimiter( peer_connection, group ); }else{ download_processor.addRateLimiter( peer_connection, group ); } } } public void removeRateLimiter( NetworkConnectionBase peer_connection, LimitedRateGroup group, boolean upload ) { if ( upload ){ if ( lan_upload_processor.isRegistered( peer_connection )){ lan_upload_processor.removeRateLimiter( peer_connection, group ); }else{ upload_processor.removeRateLimiter( peer_connection, group ); } }else{ if ( lan_download_processor.isRegistered( peer_connection )){ lan_download_processor.removeRateLimiter( peer_connection, group ); }else{ download_processor.removeRateLimiter( peer_connection, group ); } } } public NetworkManagerStats getStats() { return( stats ); } /** * Byte stream match filter for routing. */ public interface ByteMatcher { /** * Number of bytes of buffer at or beyond which the "match" method will be called to test for a match * @return */ public int matchThisSizeOrBigger(); /** * Get the max number of bytes this matcher requires. If it fails with this (or more) bytes then * the connection will be dropped * @return size in bytes */ public int maxSize(); /** * Get the minimum number of bytes required to determine if this matcher applies * @return */ public int minSize(); /** * Check byte stream for match. * @param address the originator of the connection * @param to_compare * @return return "routing data" in case of a match, null otherwise */ public Object matches( TransportHelper transport, ByteBuffer to_compare, int port ); /** * Check for a minimum match * @param to_compare * @return return "routing data" in case of a match, null otherwise */ public Object minMatches( TransportHelper transport, ByteBuffer to_compare, int port ); public byte[][] getSharedSecrets(); public int getSpecificPort(); } /** * Listener for routing events. */ public interface RoutingListener { /** * Currently if message crypto is on and default fallback for incoming not * enabled then we would bounce incoming messages from non-crypto transports * For example, NAT check * This method allows auto-fallback for such transports * @return */ public boolean autoCryptoFallback(); /** * The given incoming connection has been accepted. * @param connection accepted */ public void connectionRouted( NetworkConnection connection, Object routing_data ); } } azureus-4.3.0.6/com/aelitis/azureus/core/networkmanager/NetworkConnectionFactory.java0000644000175000017500000000415210530765172030374 0ustar adrianadrian/* * Created on Feb 21, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.networkmanager; import com.aelitis.azureus.core.networkmanager.impl.NetworkConnectionImpl; import com.aelitis.azureus.core.peermanager.messaging.MessageStreamDecoder; import com.aelitis.azureus.core.peermanager.messaging.MessageStreamEncoder; /** * */ public class NetworkConnectionFactory { /** * Create an OUTGOING connection. * @param remote_address * @param encoder * @param decoder * @return outbound connection */ protected static NetworkConnection create( ConnectionEndpoint target, MessageStreamEncoder encoder, MessageStreamDecoder decoder, boolean connect_with_crypto, boolean allow_fallback, byte[][] shared_secrets ) { return new NetworkConnectionImpl( target, encoder, decoder, connect_with_crypto, allow_fallback, shared_secrets ); } /** * Create an INCOMING connection. * @param remote_channel * @param data_already_read * @param encoder * @param decoder * @return inbound connection */ protected static NetworkConnection create( Transport transport, MessageStreamEncoder encoder, MessageStreamDecoder decoder ) { return new NetworkConnectionImpl( transport, encoder, decoder ); } } azureus-4.3.0.6/com/aelitis/azureus/core/AzureusCoreOperation.java0000644000175000017500000000251411033314670024467 0ustar adrianadrian/* * Created on 27 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core; public interface AzureusCoreOperation { public static final int OP_INITIALISATION = 1; public static final int OP_FILE_MOVE = 2; public static final int OP_PROGRESS = 3; public int getOperationType(); public AzureusCoreOperationTask getTask(); public void reportCurrentTask( String currentTask ); public void reportPercent( int percent ); } azureus-4.3.0.6/com/aelitis/azureus/core/AzureusCoreException.java0000644000175000017500000000234611012741116024464 0ustar adrianadrian/* * Created on 13-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core; /** * @author parg * */ public class AzureusCoreException extends RuntimeException { public AzureusCoreException( String str ) { super(str); } public AzureusCoreException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/com/aelitis/azureus/core/AzureusCoreLifecycleAdapter.java0000644000175000017500000000332410766345644025750 0ustar adrianadrian/* * Created on 14-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core; /** * @author parg * */ public class AzureusCoreLifecycleAdapter implements AzureusCoreLifecycleListener { public void componentCreated( AzureusCore core, AzureusCoreComponent component ) { } public void started( AzureusCore core ) { } public void stopping( AzureusCore core ) { } public void stopped( AzureusCore core ) { } public boolean stopRequested( AzureusCore core ) throws AzureusCoreException { return( true ); } public boolean restartRequested( AzureusCore core ) throws AzureusCoreException { return( true ); } public boolean syncInvokeRequired() { return( false ); } public boolean requiresPluginInitCompleteBeforeStartedEvent() { return( true ); } }azureus-4.3.0.6/com/aelitis/azureus/core/util/0000755000175000017500000000000011310377630020452 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/util/CopyOnWriteList.java0000644000175000017500000001303311307611554024375 0ustar adrianadrian/* * Created on 15-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator; import org.gudy.azureus2.core3.util.IndentWriter; public class CopyOnWriteList implements Iterable { private static final boolean LOG_STATS = false; //private int mutation_count = 0; private List list = Collections.EMPTY_LIST; private boolean visible = false; private int initialCapacity; private static CopyOnWriteList stats; static { if (LOG_STATS) { stats = new CopyOnWriteList(10); AEDiagnostics.addEvidenceGenerator(new AEDiagnosticsEvidenceGenerator() { public void generate(IndentWriter writer) { writer.println("COWList Info"); writer.indent(); try { long count = 0; long size = 0; for (Iterator iter = stats.iterator(); iter.hasNext();) { WeakReference wf = (WeakReference) iter.next(); CopyOnWriteList cowList = (CopyOnWriteList) wf.get(); if (cowList != null) { count++; size += cowList.size(); } } writer.println(count + " lists with " + size + " total entries"); writer.println((size/count) + " avg size"); } catch (Throwable t) { } finally { writer.exdent(); } } }); } } /** * @param i */ public CopyOnWriteList(int initialCapacity) { this.initialCapacity = initialCapacity; if (stats != null) { stats.add(new WeakReference(this)); } } /** * */ public CopyOnWriteList() { // Smaller default initial capacity as most of our lists are small // Last check on 7/24/2008: 444 lists with 456 total entries this.initialCapacity = 1; if (stats != null) { stats.add(new WeakReference(this)); } } public void add( T obj ) { synchronized( this ){ if ( visible ){ List new_list = new ArrayList( list ); //mutated(); new_list.add( obj ); list = new_list; visible = false; }else{ if (list == Collections.EMPTY_LIST) { list = new ArrayList(initialCapacity); } list.add( obj ); } } } public T get( int index ) { synchronized( this ){ return( list.get(index)); } } public boolean remove( T obj ) { synchronized( this ){ if ( visible ){ List new_list = new ArrayList( list ); //mutated(); boolean result = new_list.remove( obj ); list = new_list; visible = false; return( result ); }else{ return( list.remove( obj )); } } } public void clear() { synchronized( this ){ list = Collections.EMPTY_LIST; visible = false; } } public boolean contains( T obj ) { synchronized( this ){ return( list.contains( obj )); } } public Iterator iterator() { synchronized( this ){ visible = true; return( new CopyOnWriteListIterator( list.iterator())); } } public List getList() { // TODO: we need to either make this a read-only-list or obey the copy-on-write semantics correctly... synchronized( this ){ visible = true; return( list ); } } public int size() { synchronized( this ){ return( list.size()); } } public boolean isEmpty() { synchronized( this ){ return list.isEmpty(); } } public Object[] toArray() { synchronized( this ){ return( list.toArray()); } } public T[] toArray( T[] x ) { synchronized( this ){ return( list.toArray(x)); } } /* private void mutated() { mutation_count++; if ( mutation_count%10 == 0 ){ System.out.println( this + ": mut=" + mutation_count ); } } */ private class CopyOnWriteListIterator implements Iterator { private Iterator it; private T last; protected CopyOnWriteListIterator( Iterator _it ) { it = _it; } public boolean hasNext() { return( it.hasNext()); } public T next() { last = it.next(); return( last ); } public void remove() { // don't actually remove it from the iterator. can't go backwards with this iterator so this is // not a problem if ( last == null ){ throw( new IllegalStateException( "next has not been called!" )); } CopyOnWriteList.this.remove( last ); } } public int getInitialCapacity() { return initialCapacity; } public void setInitialCapacity(int initialCapacity) { this.initialCapacity = initialCapacity; } } azureus-4.3.0.6/com/aelitis/azureus/core/util/GeneralUtils.java0000644000175000017500000000635711044763540023731 0ustar adrianadrian/* * Created on Jun 9, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util; import java.util.regex.Pattern; public class GeneralUtils { /** * string.replaceAll does \\ and $ expansion in replacement, this doesn't, in fact it * doesn't do any pattern matching at all, it is a literal replacement * @param str * @param from_str = NOTE, no regex support * @param replacement * @return */ // XXX: This doesn't appear to be used... public static String replaceAll( String str, String from_str, String replacement ) { StringBuffer res = null; int pos = 0; while( true ){ int p1 = str.indexOf( from_str, pos ); if ( p1 == -1 ){ if ( res == null ){ return( str ); } res.append( str.substring( pos )); return( res.toString()); }else{ if ( res == null ){ res = new StringBuffer( str.length() * 2 ); } if ( p1 > pos ){ res.append( str.substring( pos, p1 )); } res.append( replacement ); pos = p1 + from_str.length(); } } } /** * as above but does safe replacement of multiple strings (i.e. a match in the replacement * of one string won't be substituted by another) * @param str * @param from_strs * @param to_strs * @return */ public static String replaceAll( String str, String[] from_strs, String[] to_strs ) { StringBuffer res = null; int pos = 0; while( true ){ int min_match_pos = Integer.MAX_VALUE; int match_index = -1; for ( int i=0;i pos ){ res.append( str.substring( pos, min_match_pos )); } res.append( to_strs[match_index] ); pos = min_match_pos + from_strs[match_index].length(); } } } private final static String REGEX_URLHTML = "(.+?)"; public static String stripOutHyperlinks(String message) { return Pattern.compile(REGEX_URLHTML, Pattern.CASE_INSENSITIVE).matcher( message).replaceAll("$2"); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/MultiPartDecoder.java0000644000175000017500000001761011254566742024544 0ustar adrianadrian/* * Created on 23-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util; /** * @author parg * */ import java.io.*; import java.util.*; public class MultiPartDecoder { public FormField[] decode( String boundary, InputStream is ) throws IOException { // -----------------------------7d4f2a310bca //Content-Disposition: form-data; name="upfile"; filename="C:\Temp\banana_custard.torrent" //Content-Type: application/octet-stream // // // -----------------------------7d4f2a310bca // Content-Disposition: form-data; name="category" // //Music // -----------------------------7d4f2a310bca-- byte[] header_end_bytes = "\r\n\r\n".getBytes( "ISO-8859-1" ); byte[] boundary_bytes = ( "\r\n--" + boundary ).getBytes( "ISO-8859-1" ); int boundary_len = boundary_bytes.length; byte[] buffer = new byte[65536]; int buffer_pos = 0; boolean in_header = true; byte[] current_target = header_end_bytes; int current_target_length = 4; FormField current_field = null; List fields = new ArrayList(); while( true ){ int buffer_pos_start = buffer_pos; int len = is.read( buffer, buffer_pos, buffer.length - buffer_pos ); if ( len < 0 ){ len = 0; } buffer_pos += len; boolean found_target = false; for (int i=0;i<=buffer_pos-current_target_length;i++){ if ( buffer[i] == current_target[0] ){ found_target = true; for (int j=1;j 0 ){ System.arraycopy( buffer, i+current_target_length, buffer, 0, rem ); } buffer_pos = rem; if ( in_header ){ in_header = false; current_target = boundary_bytes; current_target_length = boundary_len; }else{ in_header = true; current_target = header_end_bytes; current_target_length = 4; } break; } } } // if we didn't find the target and we're not in the header then // any remaining data in the buffer (less current target length) // is part of a body and can be written out if ( !(found_target || in_header )){ int rem = buffer_pos - current_target_length; if ( rem > 0 ){ // process buffer 0 length rem current_field.write( buffer, 0, rem ); System.arraycopy( buffer, rem, buffer, 0, current_target_length ); buffer_pos = current_target_length; } } if ( len == 0 && buffer_pos == buffer_pos_start ){ // nothing read and no progress made break; } } // should end in -- if ( buffer_pos < 2 || buffer[0] != '-' || buffer[1] != '-' ){ throw( new IOException( "Incorrect termination of form upload data")); } current_field.complete(); FormField[] res = new FormField[fields.size()]; fields.toArray( res ); return( res ); } public static class FormField { protected String name; protected Map attributes; protected long total_len; ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); File file; FileOutputStream fos; InputStream returned_stream; protected FormField( String _name, Map _attributes ) { name = _name; attributes = _attributes; // System.out.println( "formField:" + name ); } public String getName() { return( name ); } public String getAttribute( String attr_name ) { return((String)attributes.get(attr_name.toLowerCase())); } public InputStream getInputStream() throws IOException { if ( file == null ){ returned_stream = new ByteArrayInputStream( baos.toByteArray()); }else{ returned_stream = new FileInputStream( file ); } return( returned_stream ); } public String getString() throws IOException { String str = new LineNumberReader(new InputStreamReader( getInputStream())).readLine(); if ( str == null ){ str = ""; } return( str ); } public void destroy() { if ( returned_stream != null ){ try{ returned_stream.close(); }catch( Throwable e ){ } } if ( file != null ){ file.delete(); } } protected void write( byte[] buffer, int start, int len ) throws IOException { total_len += len; if ( fos != null ){ fos.write( buffer, start, len ); }else{ if ( total_len > 1024 ){ file = File.createTempFile( "AZU", null ); file.deleteOnExit(); fos = new FileOutputStream( file ); fos.write( baos.toByteArray()); fos.write( buffer, start, len ); }else{ baos.write( buffer, start, len ); } } } protected void complete() throws IOException { // System.out.println( " total_len = " + total_len ); if ( fos != null ){ fos.close(); } } } } azureus-4.3.0.6/com/aelitis/azureus/core/util/CopyOnWriteMap.java0000644000175000017500000000356211264071660024205 0ustar adrianadrian/* * Created on 13 May 2008 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.util; import java.util.HashMap; import java.util.Map; /** * @author Allan Crooks * */ public class CopyOnWriteMap { private volatile Map map; public CopyOnWriteMap() { this.map = new HashMap(0); } public void put(Object key, Object val) { synchronized(map) { HashMap new_map = new HashMap(map); new_map.put(key, val); this.map = new_map; } } public Object remove(Object key) { synchronized(map) { HashMap new_map = new HashMap(map); Object res = new_map.remove(key); this.map = new_map; return res; } } public Object get(Object key) { return this.map.get(key); } public int size() { return this.map.size(); } public boolean isEmpty() { return this.map.isEmpty(); } /* * shouldn't return underlying map directly as open to abuse. either wrap in unmodifyable * map or implement desired features explicitly public Map getMap() { return this.map; } */ } azureus-4.3.0.6/com/aelitis/azureus/core/util/CopyOnWriteSet.java0000644000175000017500000000424011135270206024207 0ustar adrianadrian/* * Created on May 30, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class CopyOnWriteSet { private volatile Set set = new HashSet(); public void add( T o ) { synchronized( set ){ Set new_set = new HashSet( set ); new_set.add( o ); set = new_set; } } public boolean remove( T o ) { synchronized( set ){ Set new_set = new HashSet( set ); boolean res = new_set.remove( o ); set = new_set; return( res ); } } public boolean contains( T o ) { return( set.contains( o )); } public int size() { return( set.size()); } public Iterator iterator() { return( new CopyOnWriteSetIterator( set.iterator())); } private class CopyOnWriteSetIterator implements Iterator { private Iterator it; private T last; protected CopyOnWriteSetIterator( Iterator _it ) { it = _it; } public boolean hasNext() { return( it.hasNext()); } public T next() { last = it.next(); return( last ); } public void remove() { // don't actually remove it from the iterator. can't go backwards with this iterator so this is // not a problem if ( last == null ){ throw( new IllegalStateException( "next has not been called!" )); } CopyOnWriteSet.this.remove( last ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/util/DeleteFileOnCloseInputStream.java0000644000175000017500000000536111070334174027002 0ustar adrianadrian/* * Created on Feb 8, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import org.gudy.azureus2.core3.util.Debug; public class DeleteFileOnCloseInputStream extends InputStream { private InputStream in; private File file; private boolean closed; private long pos; private long mark; public DeleteFileOnCloseInputStream( File _file ) throws IOException { file = _file; in = new FileInputStream( file ); } public void close() throws IOException { if ( closed ){ return; } closed = true; try{ in.close(); }finally{ if ( !file.delete()){ Debug.out( "Failed to delete file '" + file + "'" ); } } } public int read() throws IOException { int result = in.read(); pos++; return( result ); } public int read( byte b[] ) throws IOException { int res = read( b, 0, b.length ); if ( res > 0 ){ pos += res; } return( res ); } public int read( byte b[], int off, int len ) throws IOException { int res = in.read( b, off, len ); if ( res > 0 ){ pos += res; } return( res ); } public long skip( long n ) throws IOException { long res = in.skip( n ); pos += res; return( res ); } public int available() throws IOException { return( in.available()); } public synchronized void mark( int readlimit ) { mark = pos; } public synchronized void reset() throws IOException { in.close(); in = new FileInputStream( file ); in.skip( mark ); pos = mark; } public boolean markSupported() { return( true ); } /** * @return * * @since 3.1.1.1 */ public File getFile() { return file; } }azureus-4.3.0.6/com/aelitis/azureus/core/util/CaseSensitiveFileMap.java0000644000175000017500000000436010410023004025302 0ustar adrianadrian/* * Created on 21-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util; import java.util.*; import java.io.*; public class CaseSensitiveFileMap { private Map map = new HashMap(); public File get( File key ) { return((File)map.get( new wrapper( key ))); } public void put( File key, File value ) { map.put( new wrapper( key ), value ); } public void remove( File key ) { map.remove( new wrapper( key )); } public Iterator keySetIterator() { return( new Iterator() { private Iterator iterator = map.keySet().iterator(); public boolean hasNext() { return( iterator.hasNext()); } public Object next() { wrapper wrap = (wrapper)iterator.next(); return( wrap.getFile()); } public void remove() { iterator.remove(); } }); } public static class wrapper { private File file; private String file_str; protected wrapper( File _file ) { file = _file; file_str = file.toString(); } protected File getFile() { return( file ); } public boolean equals( Object other ) { if ( other instanceof wrapper ){ return( file_str.equals(((wrapper)other).file_str )); } return( false ); } public int hashCode() { return( file_str.hashCode()); } } } azureus-4.3.0.6/com/aelitis/azureus/core/util/average/0000755000175000017500000000000011310377630022064 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/util/average/RunningAverage.java0000644000175000017500000000311511111661624025640 0ustar adrianadrian/* * Created on Oct 08, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util.average; /** * Implements a simple running average. */ public class RunningAverage implements Average { private long count = 0; private double sum; /** * Create a new running average. */ public RunningAverage() { this.sum = 0; } public void reset(){ count = 0; sum = 0; } /** * Update average and return average-so-far. */ public double update(final double newValue) { sum += newValue; count++; return sum / count; } /** * Return average-so-far. */ public double getAverage() { return count==0?0:(sum / count ); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/average/MovingAverage.java0000644000175000017500000000366110410146036025461 0ustar adrianadrian/* * Created on Oct 08, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util.average; /** * Implements a basic moving average. */ public class MovingAverage implements Average { private final int periods; private double data[]; private int pos = 0; /** * Create a new moving average. */ public MovingAverage(int periods) { this.periods = periods; this.data = new double[periods]; reset(); } public void reset(){ pos = 0; for (int i=0; i < periods; i++) { data[i] = 0.0; } } /** * Update average and return average-so-far. */ public double update(final double newValue) { data[pos] = newValue; pos++; if (pos == periods) pos = 0; return calculateAve(); } /** * Return average-so-far. */ public double getAverage() { return calculateAve(); } private double calculateAve() { double sum = 0.0; for (int i=0; i < periods; i++) { sum += data[i]; } return sum / periods; } } azureus-4.3.0.6/com/aelitis/azureus/core/util/average/MovingImmediateAverage.java0000644000175000017500000000452011111664336027302 0ustar adrianadrian/* * Created on Oct 08, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util.average; /** * Implements a basic moving average. */ public class MovingImmediateAverage implements Average { private final int periods; private double data[]; private int pos = 0; /** * Create a new moving average. */ public MovingImmediateAverage(int periods) { this.periods = periods; this.data = new double[periods]; for (int i=0; i < periods; i++) { data[i] = 0.0; } } public void reset() { pos = 0; } /** * Update average and return average-so-far. */ public double update(final double newValue) { data[pos++%periods] = newValue; if ( pos==Integer.MAX_VALUE){ pos = pos%periods; } return calculateAve(); } public double[] getValues() { double[] res = new double[periods]; int p = pos; for (int i=0;iperiods?periods:pos ); } private double calculateAve() { int lim = pos>periods?periods:pos; if ( lim == 0 ){ return( 0 ); }else{ double sum = 0.0; for (int i=0; i < lim; i++) { sum += data[i]; } return sum / lim; } } } azureus-4.3.0.6/com/aelitis/azureus/core/util/average/AverageFactory.java0000644000175000017500000000471610744255314025645 0ustar adrianadrian/* * Created on Oct 08, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util.average; /** * Generates different types of averages. */ public abstract class AverageFactory { /** * Create a simple running average. */ public static RunningAverage RunningAverage() { return new RunningAverage(); } /** * Create a moving average, that moves over the given number of periods. */ public static MovingAverage MovingAverage(int periods) { return new MovingAverage(periods); } /** * Create a moving average, that moves over the given number of periods and gives immediate * results (i.e. after the first update of X the average will be X */ public static MovingImmediateAverage MovingImmediateAverage(int periods) { return new MovingImmediateAverage(periods); } /** * Create an exponential moving average, smoothing over the given number * of periods, using a default smoothing weight value of 2/(1 + periods). */ public static ExponentialMovingAverage ExponentialMovingAverage(int periods) { return new ExponentialMovingAverage(periods); } /** * Create an exponential moving average, with the given smoothing weight. * Larger weigths (closer to 1.0) will give more influence to * recent data and smaller weights (closer to 0.00) will provide * smoother averaging (give more influence to older data). */ public static ExponentialMovingAverage ExponentialMovingAverage(float weight) { return new ExponentialMovingAverage(weight); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/average/Average.java0000644000175000017500000000254610410146036024302 0ustar adrianadrian/* * Created on Oct 08, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util.average; /** * Standard methods for different types of long-term averages. */ public interface Average { /** * Update average and return average-so-far. */ public double update(final double newValue); /** * Return average-so-far. */ public double getAverage(); /** * sets back to start-of-day * */ public void reset(); } azureus-4.3.0.6/com/aelitis/azureus/core/util/average/ExponentialMovingAverage.java0000644000175000017500000000434310410146034027664 0ustar adrianadrian/* * Created on Oct 08, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util.average; /** * Implements an exponential moving average. */ public class ExponentialMovingAverage implements Average { private final float weight; private double prevEMA; /** * Create a new exponential moving average which smooths over the * given number of periods. */ public ExponentialMovingAverage(final int periods) { if (periods < 1) { System.out.println("ExponentialMovingAverage:: ERROR: bad periods: " + periods); } this.weight = 2 / (float)(1 + periods); this.prevEMA = 0; } /** * Create a new exponential moving average, using the given * smoothing rate weight. */ public ExponentialMovingAverage(final float weight) { if ((weight < 0.0) || (weight > 1.0)) { System.out.println("ExponentialMovingAverage:: ERROR: bad weight: " + weight); } this.weight = weight; this.prevEMA = 0; } public void reset(){ this.prevEMA = 0; } /** * Update average and return average-so-far. */ public double update(final double newValue) { prevEMA = (weight * (newValue - prevEMA)) + prevEMA; return prevEMA; } /** * Return average-so-far. */ public double getAverage() { return prevEMA; } }azureus-4.3.0.6/com/aelitis/azureus/core/util/FeatureAvailability.java0000644000175000017500000000547011301145334025243 0ustar adrianadrian/* * Created on Nov 6, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; public class FeatureAvailability { private static final long FT_DISABLE_REQUEST_LIMITING = 0x0000000000000001; private static final long FT_DISABLE_PEER_GENERAL_RECONNECT = 0x0000000000000002; private static final long FT_DISABLE_PEER_UDP_RECONNECT = 0x0000000000000004; private static final long FT_AUTO_SPEED_DEFAULT_CLASSIC = 0x0000000000000008; private static final long FT_DISABLE_RCM = 0x0000000000000010; private static final long FT_DISABLE_DHT_REP_V2 = 0x0000000000000020; private static final long FT_DISABLE_MAGNET_SL = 0x0000000000000040; private static VersionCheckClient vcc = VersionCheckClient.getSingleton(); public static boolean isRequestLimitingEnabled() { final boolean result = ( vcc.getFeatureFlags() & FT_DISABLE_REQUEST_LIMITING ) == 0; return( result ); } public static boolean isGeneralPeerReconnectEnabled() { final boolean result = ( vcc.getFeatureFlags() & FT_DISABLE_PEER_GENERAL_RECONNECT ) == 0; return( result ); } public static boolean isUDPPeerReconnectEnabled() { final boolean result = ( vcc.getFeatureFlags() & FT_DISABLE_PEER_UDP_RECONNECT ) == 0; return( result ); } public static boolean isAutoSpeedDefaultClassic() { final boolean result = ( vcc.getFeatureFlags() & FT_AUTO_SPEED_DEFAULT_CLASSIC ) != 0; return( result ); } public static boolean isRCMEnabled() { final boolean result = ( vcc.getFeatureFlags() & FT_DISABLE_RCM ) == 0; return( result ); } public static boolean isDHTRepV2Enabled() { final boolean result = ( vcc.getFeatureFlags() & FT_DISABLE_DHT_REP_V2 ) == 0; return( result ); } public static boolean isMagnetSLEnabled() { final boolean result = ( vcc.getFeatureFlags() & FT_DISABLE_MAGNET_SL ) == 0; return( result ); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/png/0000755000175000017500000000000011310377630021236 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/util/png/Chunk.java0000644000175000017500000000162410752273640023161 0ustar adrianadrian/* * Created on Feb 5, 2008 * Created by Olivier Chalouhi * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util.png; public abstract class Chunk { public abstract byte[] getChunkPayload(); } azureus-4.3.0.6/com/aelitis/azureus/core/util/png/PngSignatureChunk.java0000644000175000017500000000207310752273640025507 0ustar adrianadrian/* * Created on Feb 5, 2008 * Created by Olivier Chalouhi * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util.png; public class PngSignatureChunk extends Chunk { private static final byte[] signature = {(byte) 137, (byte) 80, (byte) 78, (byte) 71, (byte) 13, (byte) 10, (byte) 26, (byte) 10}; public byte[] getChunkPayload() { return signature; } } azureus-4.3.0.6/com/aelitis/azureus/core/util/png/IDATChunk.java0000644000175000017500000000370610752346142023624 0ustar adrianadrian/* * Created on Feb 5, 2008 * Created by Olivier Chalouhi * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util.png; import java.io.ByteArrayOutputStream; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; public class IDATChunk extends CRCedChunk { private static final byte[] type = {(byte) 73, (byte) 68, (byte) 65, (byte) 84 }; private int width; private int height; public IDATChunk(int width, int height) { super(type); this.width = width; this.height = height; } public byte[] getContentPayload() { byte[] payload = new byte[(width+1)*height]; for(int i = 0; i> 1) & 0x0FFFFFFFF); else c = c >> 1; c = c & 0x0FFFFFFFF; } crc_table[n] = c; } crc_table_computed = true; } /* Update a running CRC with the bytes buf[0..len-1]--the CRC should be initialized to all 1's, and the transmitted value is the 1's complement of the final running CRC (see the crc() routine below). */ private static long update_crc(long crc, ByteBuffer buf) { long c = crc; if (!crc_table_computed) { make_crc_table(); } while(buf.hasRemaining()) { c = crc_table[(int) ((c ^ buf.get()) & 0xff)] ^ (c >> 8); } return c; } /* Return the CRC of the bytes buf[0..len-1]. */ private static long crc(ByteBuffer buf) { return update_crc(0xffffffffL, buf) ^ 0xffffffffL; } } azureus-4.3.0.6/com/aelitis/azureus/core/util/png/PNG.java0000644000175000017500000000344210752346142022533 0ustar adrianadrian/* * Created on Feb 5, 2008 * Created by Olivier Chalouhi * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util.png; import java.io.File; import java.io.FileOutputStream; import java.nio.ByteBuffer; public class PNG { public static byte[] getPNGBytesForWidth(int width) { return getPNGBytesForSize(width,1); } public static byte[] getPNGBytesForSize(int width,int height) { byte[] signature = new PngSignatureChunk().getChunkPayload(); byte[] ihdr = new IHDRChunk(width,height).getChunkPayload(); byte[] idat = new IDATChunk(width,height).getChunkPayload(); byte[] iend = new IENDChunk().getChunkPayload(); ByteBuffer buffer = ByteBuffer.allocate(signature.length + ihdr.length + idat.length + iend.length); buffer.put(signature); buffer.put(ihdr); buffer.put(idat); buffer.put(iend); buffer.position(0); return buffer.array(); } public static void main(String args[]) throws Exception { File test = new File("/Users/olivier/Desktop/test.png"); FileOutputStream fos = new FileOutputStream(test); fos.write(getPNGBytesForSize(600,400)); fos.close(); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/png/IHDRChunk.java0000644000175000017500000000314510752346142023626 0ustar adrianadrian/* * Created on Feb 5, 2008 * Created by Olivier Chalouhi * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util.png; import java.nio.ByteBuffer; public class IHDRChunk extends CRCedChunk { private static final byte[] type = {(byte) 73, (byte) 72, (byte) 68, (byte) 82}; private int width; private int height; public IHDRChunk(int width, int height) { super(type); this.width = width; this.height = height; } public byte[] getContentPayload() { ByteBuffer buffer = ByteBuffer.allocate(13); //width : 4 bytes buffer.putInt(width); //height : 4 bytes buffer.putInt(height); //color depth : 1 byte buffer.put((byte)8); //color type : 1 byte buffer.put((byte)0); //compression method : 1 byte buffer.put((byte)0); //filter method : 1 byte buffer.put((byte)0); //interlace method : 1 byte buffer.put((byte)0); return buffer.array(); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/png/IENDChunk.java0000644000175000017500000000206310752273640023617 0ustar adrianadrian/* * Created on Feb 5, 2008 * Created by Olivier Chalouhi * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util.png; public class IENDChunk extends CRCedChunk { private static final byte[] type = {(byte) 73, (byte) 69, (byte) 78, (byte) 68 }; public IENDChunk() { super(type); } public byte[] getContentPayload() { return new byte[0]; } } azureus-4.3.0.6/com/aelitis/azureus/core/util/bloom/0000755000175000017500000000000011310377630021562 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/util/bloom/BloomFilter.java0000644000175000017500000000276211270760040024646 0ustar adrianadrian/* * Created on 29-Apr-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util.bloom; import java.util.Map; public interface BloomFilter { public int add( byte[] value ); public int remove( byte[] value ); public boolean contains( byte[] value ); public int count( byte[] value ); /** * Returns number of unique entries * @return */ public int getEntryCount(); /** * Returns overall capacity * @return */ public int getSize(); public BloomFilter getReplica(); public Map serialiseToMap(); public String getString(); } azureus-4.3.0.6/com/aelitis/azureus/core/util/bloom/impl/0000755000175000017500000000000011310377630022523 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/util/bloom/impl/BloomFilterImpl.java0000644000175000017500000002652511270760042026436 0ustar adrianadrian/* * Created on 29-Apr-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util.bloom.impl; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Map; import java.util.Random; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.util.MapUtils; public abstract class BloomFilterImpl implements BloomFilter { protected static final String MY_PACKAGE = "com.aelitis.azureus.core.util.bloom.impl"; /* private static final boolean USE_BIG_INTS = false; private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray(); private static final BigInteger bi_zero = new BigInteger("0"); private static final BigInteger bi_a2 = new BigInteger(""+a2); private static final BigInteger bi_a3 = new BigInteger(""+a3); private static final BigInteger bi_a4 = new BigInteger(""+a4); private static final BigInteger bi_b2 = new BigInteger(""+b2); private static final BigInteger bi_b3 = new BigInteger(""+b3); private static final BigInteger bi_b4 = new BigInteger(""+b4); */ // change the hash num and you gotta change the hash function below!!!! private static final int HASH_NUM = 5; private static final int a2 = 2; private static final int a3 = 3; private static final int a4 = 5; private static final int b2 = 51; private static final int b3 = 145; private static final int b4 = 216; public static BloomFilter deserialiseFromMap( Map map ) { String impl = MapUtils.getMapString( map, "_impl", "" ); if ( impl.startsWith( "." )){ impl = MY_PACKAGE + impl; } try{ Class cla = (Class)Class.forName( impl ); Constructor cons = cla.getDeclaredConstructor( Map.class ); cons.setAccessible( true ); return( cons.newInstance( map )); }catch( Throwable e ){ Debug.out( "Can't construct bloom filter for " + impl, e ); return( null ); } } private int max_entries; //private BigInteger bi_max_entries; private int entry_count; public BloomFilterImpl( int _max_entries ) { //bi_max_entries = new BigInteger( ""+(((_max_entries/2)*2)+1)); max_entries = ((_max_entries/2)*2)+1; } public BloomFilterImpl( Map x ) { max_entries = ((Long)x.get( "_max" )).intValue(); entry_count = ((Long)x.get( "_count" )).intValue(); } protected void serialiseToMap( Map x ) { String cla = this.getClass().getName(); if ( cla.startsWith( MY_PACKAGE )){ cla = cla.substring( MY_PACKAGE.length()); } x.put( "_impl", cla ); x.put( "_max", new Long( max_entries )); x.put( "_count", new Long( entry_count )); } public Map serialiseToMap() { Map m = new HashMap(); serialiseToMap( m ); return( m ); } protected int getMaxEntries() { return( max_entries ); } public int add( byte[] value ) { return( add( bytesToInteger( value ))); } public int remove( byte[] value ) { return( remove( bytesToInteger( value ))); } public int count( byte[] value ) { return( count( bytesToInteger( value ))); } public boolean contains( byte[] value ) { return( contains( bytesToInteger( value ))); } protected int add( int value ) { int count = 0xffff; for (int i=0;i 0 ){ entry_count--; } // count is the value BEFORE dec, decrease one further return( trimValue( count - 1 )); } protected int count( int value ) { int count = 0xffff; for (int i=0;i" + r ); return( Math.abs( (int)res % max_entries )); } protected int bytesToInteger( byte[] data ) { int res = 0x51f7ac81; for (int i=0;i 0 ){ setValue( index, (byte)(v-1)); } } } public boolean contains( BigInteger value ) { for (int i=0;i" + r ); return( r % max_entries ); } protected BigInteger bytesToBigInteger( byte[] data ) { StringBuffer buffer = new StringBuffer(data.length*2); for (int i=0;i>4)&0x0f] ); buffer.append( HEX_CHARS[data[i]&0x0f] ); } BigInteger res = new BigInteger( new String(buffer), 16 ); return( res ); } */ public int getEntryCount() { return( entry_count ); } public int getSize() { return( max_entries ); } protected static byte[] getSerialization( byte[] address, int port ) { //combine address and port bytes into one byte[] full_address = new byte[ address.length +2 ]; System.arraycopy( address, 0, full_address, 0, address.length ); full_address[ address.length ] = (byte)(port >> 8); full_address[ address.length +1 ] = (byte)(port & 0xff); return full_address; } public String getString() { return( "ent=" + entry_count + ",max=" + max_entries ); } public static void main( String[] args ) { Random rand = new Random(); /* BloomFilter b1 = new BloomFilterAddRemove8Bit(10000); for (int i=0;i<260;i++){ System.out.println( b1.add( "parp".getBytes()) + ", count = " + b1.count( "parp".getBytes()) + ", ent = " + b1.getEntryCount()); } for (int i=0;i<260;i++){ System.out.println( b1.remove( "parp".getBytes())+ ", count = " + b1.count( "parp".getBytes()) + ", ent = " + b1.getEntryCount()); } */ /* BloomFilter b1 = new BloomFilterAddOnly(90*10/3); byte[] key1 = new byte[4]; for (int i=0;i<200;i++){ if ( i%2==0){ rand.nextBytes( key1 ); } b1.add( key1 ); System.out.println( "entries = " + b1.getEntryCount() + ", act = " + i ); } System.exit(0); */ int fp_count = 0; for (int j=0;j<1000;j++){ long start = System.currentTimeMillis(); BloomFilter b = new BloomFilterAddRemove8Bit(10000); //BloomFilter b = new BloomFilterAddOnly(10000); int fp = 0; for (int i=0;i<1000;i++){ //String key = "" + rand.nextInt(); byte[] key = new byte[6]; rand.nextBytes( key ); //key = getSerialization( key, 6881 ); if ( i%2 == 0 ){ b.add( key ); if ( !b.contains( key )){ System.out.println( "false negative on add!!!!" ); } }else{ if ( b.contains( key )){ fp++; } } /* if ( i%2 == 0 ){ b.remove( key ); if ( b.contains( key )){ System.out.println( "false positive" ); } } */ } System.out.println( "" + (System.currentTimeMillis() - start + ", fp = " + fp )); if ( fp > 0 ){ fp_count++; } } System.out.println( fp_count ); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/bloom/impl/BloomFilterRotator.java0000644000175000017500000001071511270760042027161 0ustar adrianadrian/* * Created on Oct 29, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util.bloom.impl; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.aelitis.azureus.core.util.bloom.BloomFilter; public class BloomFilterRotator implements BloomFilter { private volatile BloomFilter current_filter; private int current_filter_index; private final BloomFilter[] filters; public BloomFilterRotator( BloomFilter _target, int _num ) { filters = new BloomFilter[_num]; filters[0] = _target; for (int i=1;i x ) { List> list = (List>)x.get( "list" ); filters = new BloomFilter[ list.size() ]; for (int i=0;i serialiseToMap() { Map m = new HashMap(); serialiseToMap( m ); return( m ); } protected void serialiseToMap( Map x ) { String cla = this.getClass().getName(); if ( cla.startsWith( BloomFilterImpl.MY_PACKAGE )){ cla = cla.substring( BloomFilterImpl.MY_PACKAGE.length()); } x.put( "_impl", cla ); List> list = new ArrayList>(); for ( BloomFilter filter: filters ){ list.add( filter.serialiseToMap()); } x.put( "list", list ); x.put( "index", new Long( current_filter_index )); } public int add( byte[] value ) { synchronized( filters ){ int filter_size = current_filter.getSize(); int filter_entries = current_filter.getEntryCount(); int limit = filter_size / 8; // capacity limit if ( filter_entries > limit ){ filter_entries = limit; } int update_chunk = limit / filters.length; int num_to_update = ( filter_entries / update_chunk ) + 1; if ( num_to_update > filters.length ){ num_to_update = filters.length; } //System.out.println( "rot_bloom: cur=" + current_filter_index + ", upd=" + num_to_update + ",ent=" + filter_entries ); int res = 0; for (int i=current_filter_index;i limit ){ filters[current_filter_index] = current_filter.getReplica(); current_filter_index = (current_filter_index+1)%filters.length; current_filter = filters[ current_filter_index ]; } return( res ); } } public int remove( byte[] value ) { int res = 0; for (int i=0;i x ) { super.serialiseToMap( x ); x.put( "map", map.clone()); } public BloomFilter getReplica() { return( new BloomFilterAddRemove4Bit( getMaxEntries())); } protected int trimValue( int value ) { if ( value < 0 ){ return( 0 ); }else if ( value > 15 ){ return( 15 ); }else{ return( value ); } } protected int getValue( int index ) { byte b = map[index/2]; if ( index % 2 == 0 ){ return(( b&0x0f ) & 0xff ); }else{ return(((b>>4)&0x0f) & 0xff ); } } protected int incValue( int index ) { int original_value = getValue( index ); if ( original_value >= 15 ){ return( 15 ); } setValue( index, (byte)(original_value+1) ); return( original_value ); } protected int decValue( int index ) { int original_value = getValue( index ); if ( original_value <= 0 ){ return( 0 ); } setValue( index, (byte)(original_value-1)); return( original_value ); } private void setValue( int index, byte value ) { byte b = map[index/2]; if ( index % 2 == 0 ){ b = (byte)((b&0xf0) | value ); }else{ b = (byte)((b&0x0f) | (value<<4)&0xf0 ); } // System.out.println( "setValue[" + index + "]:" + Integer.toHexString( map[index/2]&0xff) + "->" + Integer.toHexString( b&0xff )); map[index/2] = b; } } azureus-4.3.0.6/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddOnly.java0000644000175000017500000000554211270760042027063 0ustar adrianadrian/* * Created on 13-May-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util.bloom.impl; import java.util.Map; import com.aelitis.azureus.core.util.bloom.BloomFilter; public class BloomFilterAddOnly extends BloomFilterImpl { private byte[] map; public BloomFilterAddOnly( int _max_entries ) { super( _max_entries ); map = new byte[(getMaxEntries()+7)/8]; } public BloomFilterAddOnly( Map x ) { super( x ); map = (byte[])x.get( "map" ); } protected void serialiseToMap( Map x ) { super.serialiseToMap( x ); x.put( "map", map.clone()); } public BloomFilter getReplica() { return( new BloomFilterAddOnly( getMaxEntries())); } protected int trimValue( int value ) { if ( value < 0 ){ return( 0 ); }else if ( value > 1 ){ return( 1); }else{ return( value ); } } protected int getValue( int index ) { byte b = map[index/8]; return(((b>>(index%8))&0x01)); } /** * returns the value BEFORE increment */ protected int incValue( int index ) { int original_value = getValue( index ); if ( original_value >= 1 ){ return( 1 ); } setValue( index, (byte)(original_value+1) ); return( original_value ); } /** * returns the value BEFORE decrement */ protected int decValue( int index ) { int original_value = getValue( index ); if ( original_value <= 0 ){ return( 0 ); } setValue( index, (byte)(original_value-1) ); return( original_value ); } private void setValue( int index, byte value ) { byte b = map[index/8]; if ( value == 0 ){ // b = (byte)(b&~(0x01<<(index%8))); throw( new RuntimeException( "remove not supported" )); }else{ b = (byte)(b|(0x01<<(index%8))); } // System.out.println( "setValue[" + index + "]:" + Integer.toHexString( map[index/2]&0xff) + "->" + Integer.toHexString( b&0xff )); map[index/8] = b; } } azureus-4.3.0.6/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove8Bit.java0000644000175000017500000000461311270760040030122 0ustar adrianadrian/* * Created on 13-May-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util.bloom.impl; import java.util.Map; import com.aelitis.azureus.core.util.bloom.BloomFilter; public class BloomFilterAddRemove8Bit extends BloomFilterImpl { private byte[] map; public BloomFilterAddRemove8Bit( int _max_entries ) { super( _max_entries ); map = new byte[getMaxEntries()]; } public BloomFilterAddRemove8Bit( Map x ) { super( x ); map = (byte[])x.get( "map" ); } protected void serialiseToMap( Map x ) { super.serialiseToMap( x ); x.put( "map", map.clone()); } public BloomFilter getReplica() { return( new BloomFilterAddRemove8Bit( getMaxEntries())); } protected int trimValue( int value ) { if ( value < 0 ){ return( 0 ); }else if ( value > 255 ){ return( 255 ); }else{ return( value ); } } protected int getValue( int index ) { return( map[index] & 0xff ); } protected int incValue( int index ) { int original_value = getValue( index ); if ( original_value >= 255 ){ return( 255 ); } setValue( index, (byte)(original_value+1)); return( original_value ); } protected int decValue( int index ) { int original_value = getValue( index ); if ( original_value <= 0 ){ return( 0 ); } setValue( index, (byte)(original_value-1)); return( original_value ); } private void setValue( int index, byte value ) { map[index] = value; } } azureus-4.3.0.6/com/aelitis/azureus/core/util/bloom/BloomFilterFactory.java0000644000175000017500000000416111270760036026176 0ustar adrianadrian/* * Created on 29-Apr-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util.bloom; import java.util.Map; import com.aelitis.azureus.core.util.bloom.impl.*; public class BloomFilterFactory { /** * Creates a new bloom filter. * @param max_entries The filter size. * a size of 10 * expected entries gives a false-positive of around 0.01% * 17* -> 0.001 * 29* -> 0.0001 * Each entry takes 1, 4 or 8 bits depending on type * So, if 0.01% is acceptable and expected max entries is 100, use a filter * size of 1000. * @return */ public static BloomFilter createAddRemove4Bit( int filter_size ) { return( new BloomFilterAddRemove4Bit( filter_size )); } public static BloomFilter createAddRemove8Bit( int filter_size ) { return( new BloomFilterAddRemove8Bit( filter_size )); } public static BloomFilter createAddOnly( int filter_size ) { return( new BloomFilterAddOnly( filter_size )); } public static BloomFilter createRotating( BloomFilter basis, int number ) { { return( new BloomFilterRotator( basis, number )); } } public static BloomFilter deserialiseFromMap( Map map ) { return( BloomFilterImpl.deserialiseFromMap(map)); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/NetUtils.java0000644000175000017500000000377010537412532023074 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util; import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.UnknownHostException; import java.util.Enumeration; public class NetUtils { public static InetAddress getLocalHost() throws UnknownHostException { try{ return( InetAddress.getLocalHost()); }catch( Throwable e ){ // sometimes get this when changing host name // return first non-loopback one try{ Enumeration nis = NetworkInterface.getNetworkInterfaces(); while( nis.hasMoreElements()){ NetworkInterface ni = (NetworkInterface)nis.nextElement(); Enumeration addresses = ni.getInetAddresses(); while( addresses.hasMoreElements()){ InetAddress address = (InetAddress)addresses.nextElement(); if ( address.isLoopbackAddress() || address instanceof Inet6Address ){ continue; } return( address ); } } }catch( Throwable f ){ } return( InetAddress.getByName( "127.0.0.1" )); } } } azureus-4.3.0.6/com/aelitis/azureus/core/util/loopcontrol/0000755000175000017500000000000011310377630023024 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/util/loopcontrol/impl/0000755000175000017500000000000011310377630023765 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/util/loopcontrol/impl/PIDLoopControler.java0000644000175000017500000000207310524747564030005 0ustar adrianadrianpackage com.aelitis.azureus.core.util.loopcontrol.impl; import com.aelitis.azureus.core.util.loopcontrol.LoopControler; public class PIDLoopControler implements LoopControler { double pGain; double iGain; double dGain; double iState; double iMin = -5000; double iMax = 5000; double dState; public PIDLoopControler(double pGain,double iGain, double dGain) { this.pGain = pGain; this.iGain = iGain; this.dGain = dGain; } public double updateControler(double error, double position) { //Proportional double pTerm = pGain * error; iState += error; if(iState > iMax) iState = iMax; if(iState < iMin) iState = iMin; double iTerm = iGain * iState; double d = dState - position; double dTerm = dGain * d; dState = position; double result = pTerm + iTerm - dTerm; System.out.println("PID p,i,d (" + pGain + "," + iGain + "," + dGain +") : is,ds (" + iState + "," + d + ") p,i,d (" + pTerm + "," + iTerm + "," + dTerm + ") => " + result); return result; } public void reset() { dState = 0; iState = 0; } } azureus-4.3.0.6/com/aelitis/azureus/core/util/loopcontrol/LoopControler.java0000644000175000017500000000035411054405162026467 0ustar adrianadrianpackage com.aelitis.azureus.core.util.loopcontrol; /** * XXX: I can't find anywhere where this is used... */ public interface LoopControler { public double updateControler(double error,double position); public void reset(); } azureus-4.3.0.6/com/aelitis/azureus/core/util/DNSUtils.java0000644000175000017500000000525111305332420022755 0ustar adrianadrian/* * Created on Jun 11, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util; import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; public class DNSUtils { private static String getFactory() { return( System.getProperty( "azureus.dns.context.factory", "com.sun.jndi.dns.DnsContextFactory" )); } public static DirContext getInitialDirContext() throws NamingException { Hashtable env = new Hashtable(); env.put ("java.naming.factory.initial", getFactory()); return( new InitialDirContext( env )); } public static Inet6Address getIPV6ByName( String host ) throws UnknownHostException { List all = getAllIPV6ByName( host ); return( all.get(0)); } public static List getAllIPV6ByName( String host ) throws UnknownHostException { List result = new ArrayList(); try{ DirContext context = getInitialDirContext(); Attributes attrs = context.getAttributes( host, new String[]{ "AAAA" }); if ( attrs != null ){ Attribute attr = attrs.get( "aaaa" ); if ( attr != null ){ NamingEnumeration values = attr.getAll(); while( values.hasMore()){ Object value = values.next(); if ( value instanceof String ){ try{ result.add( (Inet6Address)InetAddress.getByName((String)value)); }catch( Throwable e ){ } } } } } }catch( Throwable e ){ } if ( result.size() > 0 ){ return( result ); } throw( new UnknownHostException( host )); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/ByteCountedInputStream.java0000644000175000017500000000412710563174622025747 0ustar adrianadrian/* * Created on Feb 8, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; public class ByteCountedInputStream extends FilterInputStream { private long position; private long mark; public ByteCountedInputStream( InputStream is ) { super( is ); } public int read() throws IOException { int read = in.read(); position += read; return( read ); } public int read(byte b[]) throws IOException { int read = read(b, 0, b.length); position += read; return( read ); } public int read(byte b[], int off, int len) throws IOException { int read = in.read(b, off, len); position += read; return( read ); } public long skip(long n) throws IOException { long skipped = in.skip(n); position += skipped; return( skipped ); } public synchronized void mark(int readlimit) { in.mark(readlimit); mark = position; } public synchronized void reset() throws IOException { in.reset(); position = mark; } public long getPosition() { return( position ); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/AEThreadMonitor.java0000644000175000017500000002125411305665622024313 0ustar adrianadrian/* * Created on 05-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import java.util.*; import org.gudy.azureus2.core3.util.*; public class AEThreadMonitor { private static boolean disable_getThreadCpuTime = false; public static void initialise() { String java_version = (String)System.getProperty("java.runtime.version"); // getThreadCpuTime crashes on OSX with 1.5.0_06 disable_getThreadCpuTime = Constants.isOSX && java_version.startsWith("1.5.0_06"); AEDiagnostics.addEvidenceGenerator(new EvidenceGenerateor()); if ( !disable_getThreadCpuTime ){ AEThread thread = new AEThread( "AEThreadMonitor" ) { public void runSupport() { try{ try{ Class.forName( "java.lang.management.ManagementFactory" ); monitor15(); }catch( Throwable e ){ //monitor14(); } }catch( Throwable e ){ } } }; thread.setPriority( Thread.MAX_PRIORITY ); thread.setDaemon( true ); thread.start(); /* new AEThread( "parp", true ) { public void runSupport() { try{ while( true ){ //Thread.sleep(1); } }catch( Throwable e ){ } } }.start(); */ } } private static void monitor14() { AEDiagnosticsLogger log = AEDiagnostics.getLogger( "thread" ); int num_processors = Runtime.getRuntime().availableProcessors(); if ( num_processors < 1 ){ num_processors = 1; } log.log( "Monitoring starts [1.4] (processors =" + num_processors + ")" ); while( true ){ try{ Thread.sleep(10000); }catch( Throwable e ){ log.log(e); } try{ ThreadGroup group = Thread.currentThread().getThreadGroup(); Thread[] threads = new Thread[group.activeCount()]; group.enumerate( threads ); for (int i=0;i last_times = new HashMap(); long time_available = 10000; while( true ){ long start = System.currentTimeMillis(); try{ Thread.sleep(time_available); }catch( Throwable e ){ log.log(e); } long end = System.currentTimeMillis(); long elapsed = end - start; long[] ids = bean.getAllThreadIds(); long[] diffs = new long[ids.length]; long total_diffs = 0; long biggest_diff = 0; int biggest_index = 0; Map new_times = new HashMap(); for (int i=0;i millis Long old_time = last_times.get( id ); if ( old_time != null ){ long diff = time - old_time.longValue(); if ( diff > biggest_diff ){ biggest_diff = diff; biggest_index = i; } diffs[i] = diff; total_diffs += diff; } new_times.put( id, time ); } ThreadInfo info = bean.getThreadInfo( ids[biggest_index ]); String thread_name = info==null?"":info.getThreadName(); int percent = (int)( 100*biggest_diff / time_available ); Runtime rt = Runtime.getRuntime(); log.log( "Thread state: elapsed=" + elapsed + ",cpu=" + total_diffs + ",max=" + thread_name + "(" + biggest_diff + "/" + percent + "%),mem:max=" + (rt.maxMemory()/1024)+",tot=" + (rt.totalMemory()/1024) +",free=" + (rt.freeMemory()/1024)); if ( biggest_diff > time_available/4 ){ info = bean.getThreadInfo( ids[biggest_index ], 255 ); if ( info == null ){ log.log( " no info for max thread" ); }else{ StackTraceElement[] elts = info.getStackTrace(); StringBuilder str = new StringBuilder(elts.length * 20); str.append(" "); for (int i=0;i threadInfos = new ArrayList(allThreadIds.length); for (int i = 0; i < allThreadIds.length; i++) { ThreadInfo info = threadBean.getThreadInfo(allThreadIds[i], 32); if(info != null) threadInfos.add(info); } if (!disable_getThreadCpuTime) { Collections.sort(threadInfos, new Comparator() { public int compare(ThreadInfo o1, ThreadInfo o2) { long diff = threadBean.getThreadCpuTime(o2.getThreadId()) - threadBean.getThreadCpuTime(o1.getThreadId()); if (diff == 0) { return o1.getThreadName().compareToIgnoreCase(o2.getThreadName()); } return diff > 0 ? 1 : -1; } }); } for (int i = 0; i < threadInfos.size(); i++) { try { ThreadInfo threadInfo = threadInfos.get(i); long lCpuTime = disable_getThreadCpuTime ? -1 : threadBean.getThreadCpuTime(threadInfo.getThreadId()); if (lCpuTime == 0) break; String sState; switch (threadInfo.getThreadState()) { case BLOCKED: sState = "Blocked"; break; case RUNNABLE: sState = "Runnable"; break; case NEW: sState = "New"; break; case TERMINATED: sState = "Terminated"; break; case TIMED_WAITING: sState = "Timed Waiting"; break; case WAITING: sState = "Waiting"; break; default: sState = "" + threadInfo.getThreadState(); break; } String sName = threadInfo.getThreadName(); String sLockName = threadInfo.getLockName(); writer.println(sName + ": " + sState + ", " + (lCpuTime / 1000000) + "ms CPU, " + "B/W: " + threadInfo.getBlockedCount() + "/" + threadInfo.getWaitedCount() + (sLockName == null ? "" : "; Locked by " + sLockName + "/" + threadInfo.getLockOwnerName())); writer.indent(); try { StackTraceElement[] stackTrace = threadInfo.getStackTrace(); for (int j = 0; j < stackTrace.length; j++) { writer.println(stackTrace[j].toString()); } } finally { writer.exdent(); } } catch (Exception e) { // TODO: handle exception } } writer.exdent(); } private static class EvidenceGenerateor implements AEDiagnosticsEvidenceGenerator { public void generate(IndentWriter writer) { dumpThreads( writer ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/util/UUIDGenerator.java0000644000175000017500000000376111166774660023756 0ustar adrianadrian/* * Created on 28-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util; import java.security.SecureRandom; import java.util.Random; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.RandomUtils; public class UUIDGenerator { /** * 128 bit UUID using random method * @return */ public static synchronized byte[] generateUUID() { byte[] bytes = new byte[16]; RandomUtils.SECURE_RANDOM.nextBytes( bytes ); return( bytes ); } /** * 129 byte random UUID formatted as standard 36 char hex and hyphen string * @return */ public static String generateUUIDString() { byte[] bytes = generateUUID(); String res = ByteFormatter.encodeString( bytes ).toLowerCase( MessageText.LOCALE_ENGLISH ); return( res.substring(0,8) + "-" + res.substring(8,12) + "-" + res.substring(12,16) + "-" + res.substring(16,20) + "-" + res.substring( 20 )); } public static void main( String[] args ) { for (int i=0;i<100;i++){ System.out.println( generateUUIDString()); } } } azureus-4.3.0.6/com/aelitis/azureus/core/util/http/0000755000175000017500000000000011310377626021436 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/util/http/HTTPAuthHelper.java0000644000175000017500000007321311147377516025056 0ustar adrianadrian/* * Created on Oct 2, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util.http; import java.net.*; import java.nio.charset.Charset; import java.util.*; import java.util.zip.GZIPInputStream; import java.util.zip.InflaterInputStream; import java.io.*; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.util.CopyOnWriteList; public class HTTPAuthHelper { public static final boolean TRACE = false; public static final int MAX_PROCESSORS = 32; public static final int CONNECT_TIMEOUT = 30*1000; public static final int READ_TIMEOUT = 30*1000; private HTTPAuthHelper parent; private Map children = new HashMap(); private URL delegate_to; private String delegate_to_host; private int delegate_to_port; private boolean delegate_is_https; private CopyOnWriteList listeners = new CopyOnWriteList(); private int port; private ServerSocket server_socket; private boolean http_only_detected; private Map cookie_names_set = new HashMap(); private ThreadPool thread_pool = new ThreadPool("HTTPSniffer", MAX_PROCESSORS, true ); private List processors = new ArrayList(); private volatile boolean destroyed; public HTTPAuthHelper( URL url ) throws Exception { this( null, url ); } protected HTTPAuthHelper( HTTPAuthHelper _parent, URL _delegate_to ) throws Exception { parent = _parent; delegate_to = _delegate_to; delegate_to_host = delegate_to.getHost(); delegate_is_https = delegate_to.getProtocol().toLowerCase().equals( "https" ); delegate_to_port = delegate_to.getPort()==-1?delegate_to.getDefaultPort():delegate_to.getPort(); server_socket = new ServerSocket(); server_socket.setReuseAddress( true ); server_socket.bind( new InetSocketAddress( "127.0.0.1", 0 )); port = server_socket.getLocalPort(); } public void start() { new AEThread2( "HTTPSniffingProxy: " + delegate_to_host + ":" + delegate_to_port + "/" + delegate_is_https + "/" + port, true ) { public void run() { try{ while( !destroyed ){ Socket socket = server_socket.accept(); socket.setSoTimeout( READ_TIMEOUT ); synchronized( HTTPAuthHelper.this ){ if ( processors.size() >= MAX_PROCESSORS ){ try{ Debug.out( "Too many processors" ); socket.close(); }catch( Throwable e ){ } }else{ processor proc = new processor( socket ); processors.add( proc ); proc.start(); } } } }catch( Throwable e ){ if ( !destroyed ){ Debug.printStackTrace( e ); } } } }.start(); } public int getPort() { return( port ); } public boolean wasHTTPOnlyCookieDetected() { return( http_only_detected ); } protected void setHTTPOnlyCookieDetected() { http_only_detected = true; if ( parent != null ){ parent.setHTTPOnlyCookieDetected(); } } protected String getKey( URL url ) { int child_port = url.getPort()==-1?url.getDefaultPort():url.getPort(); String key = url.getProtocol() + ":" + url.getHost() + ":" + child_port; return( key ); } protected HTTPAuthHelper getChild( String url_str, boolean optional ) throws Exception { if ( parent != null ){ return( parent.getChild( url_str,optional )); } String lc_url_str = url_str.toLowerCase(); if ( lc_url_str.startsWith( "http://" ) || lc_url_str.startsWith( "https://")){ URL child_url = new URL( url_str ); String child_key = getKey( child_url ); if ( child_key.equals( getKey( delegate_to ))){ return( this ); } synchronized( this ){ if ( destroyed ){ throw( new Exception( "Destroyed" )); } HTTPAuthHelper child = (HTTPAuthHelper)children.get( child_key ); if ( optional ){ // create children for related domains String base_host = delegate_to.getHost(); String child_host = child_url.getHost(); int base_pos = base_host.lastIndexOf( '.' ); base_pos = base_host.lastIndexOf( '.', base_pos-1 ); int child_pos = child_host.lastIndexOf( '.' ); child_pos = child_host.lastIndexOf( '.', child_pos-1 ); String base_dom = base_host.substring( base_pos, base_host.length()); String child_dom = child_host.substring( child_pos, child_host.length()); if ( base_dom.equals( child_dom )){ optional = false; } } if ( child == null && !optional ){ child = new HTTPAuthHelper( this, new URL( url_str )); children.put( child_key, child ); child.start(); } return( child ); } }else{ //relative return( this ); } } protected void addSetCookieName( String name, String value ) { if ( parent != null ){ parent.addSetCookieName( name, value ); }else{ boolean new_entry; synchronized( cookie_names_set ){ trace( "SetCookieName: " + name ); String old_value = (String)cookie_names_set.put( name, value ); new_entry = old_value==null || !old_value.equals( value ); } if ( new_entry ){ Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((HTTPAuthHelperListener)it.next()).cookieFound( this, name, value ); }catch( Throwable e ){ Debug.printStackTrace(e ); } } } } } protected boolean hasSetCookieName( String name ) { if ( parent != null ){ return( parent.hasSetCookieName( name )); }else{ synchronized( cookie_names_set ){ trace( "GetCookieName: " + name ); return( cookie_names_set.containsKey( name )); } } } public void addListener( HTTPAuthHelperListener listener ) { listeners.add( listener ); } public void destroy() { List processors_to_destroy; List chidren_to_destroy; synchronized( this ){ if ( destroyed ){ return; } destroyed = true; chidren_to_destroy = new ArrayList( children.values()); children.clear(); processors_to_destroy = new ArrayList( processors ); processors.clear(); try{ server_socket.close(); }catch( Throwable e ){ } } for (int i=0;i= 2 ){ String lhs = bits[0].trim(); if ( lhs.equals( "host" )){ String port_str; if ( delegate_to_port == 80 || delegate_to_port == 443 ){ port_str = ""; }else{ port_str = ":" + delegate_to_port; } line_out = "Host: " + delegate_to_host + port_str; }else if ( lhs.equals( "connection" )){ line_out = "Connection: close"; }else if ( lhs.equals( "referer" )){ String page = line_out.substring( line_out.indexOf( ':' )+1).trim(); page = page.substring( page.indexOf( "://") + 3); int pos = page.indexOf( '/' ); if ( pos >= 0 ){ page = page.substring( pos ); }else{ page = "/"; } String port_str; if ( delegate_to_port == 80 || delegate_to_port == 443 ){ port_str = ""; }else{ port_str = ":" + delegate_to_port; } line_out = "Referer: http" + (delegate_is_https?"s":"") + "://" + delegate_to_host + port_str + page; }else if ( lhs.equals( "cookie" )){ String cookies_str = line_out.substring( line_out.indexOf( ':' )+1).trim(); String[] cookies = cookies_str.split( ";" ); String cookies_out = ""; for (int j=0;j 0 ){ line_out = "Cookie: " + cookies_out; }else{ line_out = null; } } } if ( line_out != null ){ trace( "-> " + line_out ); target_os.write((line_out+NL).getBytes()); } } target_os.write( NL.getBytes()); target_os.flush(); new AEThread2( "HTTPSniffingProxy:proc:2", true ) { public void run() { try{ InputStream source_is = socket_in.getInputStream(); byte[] buffer = new byte[32000]; while( !destroyed ){ int len = source_is.read( buffer ); if ( len <= 0 ){ break; } target_os.write( buffer, 0, len ); trace( "POST:" + new String( buffer, 0, len )); } }catch( Throwable e ){ } } }.start(); InputStream target_is = socket_out.getInputStream(); OutputStream source_os = socket_in.getOutputStream(); String reply_header = readHeader( target_is ); String[] reply_lines = splitHeader( reply_header ); String content_type = null; String content_charset = "ISO-8859-1"; for (int i=0;i= 2 ){ String lhs = bits[0].trim(); if ( lhs.equals( "content-type" )){ String rhs = reply_lines[i].substring( line_in.indexOf( ':' ) + 1 ).trim(); String[] x = rhs.split( ";" ); content_type = x[0]; if ( x.length > 1 ){ int pos = rhs.toLowerCase().indexOf( "charset" ); if ( pos >= 0 ){ String cc = rhs.substring( pos+1 ); pos = cc.indexOf('='); if ( pos != -1 ){ cc = cc.substring( pos+1 ).trim(); if ( Charset.isSupported( cc )){ content_charset = cc; } } } } } } } boolean rewrite = false; boolean chunked = false; String content_encoding = null; if ( content_type == null ){ rewrite = true; }else{ content_type = content_type.toLowerCase(); if ( content_type.indexOf( "text/" ) != -1 ){ rewrite = true; } } for (int i=0;i= 2 ){ String lhs = bits[0].trim(); if ( lhs.equals( "set-cookie" )){ String cookies_in = line_out.substring( line_out.indexOf( ':' )+1 ); String[] cookies; if ( cookies_in.toLowerCase().indexOf( "expires" ) == -1 ){ cookies = cookies_in.split( "," ); }else{ cookies = new String[]{ cookies_in }; } String cookies_out = ""; for (int c=0;c= 0 ){ // absolute page = page.substring( pos + 3); pos = page.indexOf( '/' ); if ( pos >= 0 ){ page = page.substring( pos ); }else{ page = "/"; } }else{ // relative. actually illegal as must be absolute if ( !page.startsWith( "/" )){ String temp = target_url; int marker = temp.indexOf( "://" ); if ( marker != -1 ){ // strip out absolute part temp = temp.substring( marker + 3 ); marker = temp.indexOf( "/" ); if ( marker == -1 ){ temp = "/"; }else{ temp = temp.substring( marker ); } }else{ if ( !temp.startsWith( "/" )){ temp = "/" + temp; } } marker = temp.lastIndexOf( "/" ); if ( marker >= 0 ){ temp = temp.substring( 0, marker+1 ); } page = temp + page; } } line_out = "Location: http://127.0.0.1:" + child.getPort() + page; }else if ( lhs.equals( "content-encoding" )){ if ( rewrite ){ String encoding = bits[1].trim(); if ( encoding.equalsIgnoreCase( "gzip" ) || encoding.equalsIgnoreCase( "deflate" )){ content_encoding = encoding; line_out = null; } } }else if ( lhs.equals( "content-length" )){ if ( rewrite ){ line_out = null; } }else if ( lhs.equals( "transfer-encoding" )){ if ( bits[1].indexOf( "chunked" ) != -1 ){ chunked = true; if ( rewrite ){ line_out = null; } } } } if ( line_out != null ){ trace( "<- " + line_out ); source_os.write((line_out+NL).getBytes()); } } for ( int i=0;i 2 ){ int semi_pos = chunk.indexOf( ';' ); if ( semi_pos != -1 ){ chunk = chunk.substring( 0, semi_pos ); } chunk = chunk.trim(); int chunk_length = Integer.parseInt( chunk, 16 ); if ( chunk_length <= 0 ){ break; } total_length += chunk_length; if ( total_length > 2*1024*1024 ){ throw (new IOException("Chunk size " + chunk_length + " too large")); } char[] chunk_buffer = new char[chunk_length]; sb.getChars( sb_pos, sb_pos + chunk_length, chunk_buffer, 0 ); sb_dechunked.append( chunk_buffer ); sb_pos += chunk_length; chunk = ""; } } // dechunked ISO-8859-1 - unzip if required and then apply correct charset target_is = new ByteArrayInputStream( sb_dechunked.toString().getBytes( "ISO-8859-1" )); } if ( content_encoding != null ){ if ( content_encoding.equalsIgnoreCase( "gzip" )){ target_is = new GZIPInputStream( target_is ); }else if ( content_encoding.equalsIgnoreCase( "deflate" )){ target_is = new InflaterInputStream( target_is ); } } sb.setLength(0); while( !destroyed ){ int len = target_is.read( buffer ); if ( len <= 0 ){ break; } sb.append(new String( buffer, 0, len, content_charset )); } String str = sb.toString(); String lc_str = str.toLowerCase(); StringBuffer result = null; int str_pos = 0; // FileUtil.writeBytesAsFile( "C:\\temp\\xxx" + new Random().nextInt(100000) + ".txt", str.getBytes()); while( true ){ // http://a.b int url_start = str.length() - str_pos >=10?lc_str.indexOf( "http", str_pos ):-1; if ( url_start == -1 ){ break; } int match_pos; if ( lc_str.charAt( url_start + 4 ) == 's' ){ match_pos = url_start + 5; }else{ match_pos = url_start + 4; } if ( lc_str.substring( match_pos, match_pos+3 ).equals( "://" )){ int url_end = -1; for (int i=match_pos+3;;i++){ char c = lc_str.charAt(i); if ( c == '/' ){ url_end = i+1; break; }else if ( c == '.' || c == '-' || c == ':' ){ }else if ( c >= '0' && c <= '9' ){ }else if ( c >= 'a' && c <= 'z' ){ }else{ url_end = i; break; } if ( i == lc_str.length()-1 ){ url_end = i; } } if ( url_end > url_start ){ String url_str = str.substring( url_start, url_end ); boolean appended = false; try{ // make sure vald URL URL url = new URL( url_str ); if ( url.getHost().length() > 0 ){ boolean existing_only = true; // override if form action or meta for (int i=url_start-1;i>=0&&url_start-i<512;i--){ if ( lc_str.charAt( i ) == '<' ){ String prefix = lc_str.substring(i, url_start); if ( prefix.indexOf( "form" ) != -1 ){ existing_only = false; }else if ( prefix.indexOf( "meta" ) != -1 && prefix.indexOf( "http-equiv" ) != -1 ){ existing_only = false; } break; } } HTTPAuthHelper child = getChild( url_str, existing_only ); if ( child != null ){ String replacement = "http://127.0.0.1:" + child.getPort(); if ( url_str.endsWith( "/" )){ replacement += "/"; } if ( result == null ){ result = new StringBuffer( str.length()); if ( url_start > 0 ){ result.append( str.subSequence( 0, url_start )); } }else if ( url_start > str_pos ){ result.append( str.subSequence( str_pos, url_start )); } trace( "Replacing " + url_str + " with " + replacement ); result.append( replacement ); appended = true; }else{ trace( " No child for " + url_str ); } } }catch( Throwable e ){ } if ( result != null && !appended ){ result.append( str.subSequence( str_pos, url_end )); } str_pos = url_end; }else{ break; } }else{ if ( result != null ){ result.append( str.subSequence( str_pos, match_pos )); } str_pos = match_pos; } } if ( result != null ){ if ( str_pos < str.length() ){ result.append( str.subSequence( str_pos, str.length())); } sb = result; } source_os.write( ( "Content-Length: " + sb.length() + NL ).getBytes()); source_os.write( NL.getBytes()); source_os.write( sb.toString().getBytes( content_charset )); }else{ source_os.write( NL.getBytes()); while( !destroyed ){ int len = target_is.read( buffer ); if ( len <= 0 ){ break; } source_os.write( buffer, 0, len ); } } } protected String readHeader( InputStream is ) throws IOException { String header = ""; byte[] buffer = new byte[1]; while( true ){ if ( is.read( buffer ) != 1 ){ break; } header += (char)buffer[0]; if ( header.endsWith( NL + NL )){ break; } } return( header ); } protected String[] splitHeader( String str ) { String[] bits = str.split( NL ); return( bits ); } protected void destroy() { synchronized( this ){ if ( destroyed ){ return; } destroyed = true; } if ( socket_out != null ){ try{ socket_out.close(); }catch( Throwable e ){ } } try{ socket_in.close(); }catch( Throwable e ){ } } } protected void trace( String str ) { if ( TRACE ){ System.out.println( str ); } } public static void main( String[] args ) { try{ HTTPAuthHelper proxy = new HTTPAuthHelper( new URL( "http://www.sf.net/" )); proxy.start(); System.out.println( "port=" + proxy.getPort()); while( true ){ Thread.sleep(1000); } }catch( Throwable e ){ e.printStackTrace(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/util/http/HTTPAuthHelperListener.java0000644000175000017500000000173411073522624026551 0ustar adrianadrian/* * Created on Oct 9, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util.http; public interface HTTPAuthHelperListener { public void cookieFound( HTTPAuthHelper helper, String cookie_name, String cookie_value ); } azureus-4.3.0.6/com/aelitis/azureus/core/util/HTTPUtils.java0000644000175000017500000001636611247370232023131 0ustar adrianadrian/* * Created on Feb 15, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.Socket; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.FileUtil; public class HTTPUtils { public static final String NL = "\r\n"; private static final String default_type = "application/octet-stream"; private static final Map file_types = new HashMap(); private static final Set compression = new HashSet(); static { file_types.put("html", "text/html"); file_types.put("htm", "text/html"); file_types.put("css", "text/css"); file_types.put("js", "text/javascript"); file_types.put("xml", "text/xml"); file_types.put("xsl", "text/xml"); file_types.put("jpg", "image/jpeg"); file_types.put("jpeg", "image/jpeg"); file_types.put("gif", "image/gif"); file_types.put("tiff", "image/tiff"); file_types.put("bmp", "image/bmp"); file_types.put("png", "image/png"); file_types.put("torrent", "application/x-bittorrent"); file_types.put("tor", "application/x-bittorrent"); file_types.put("vuze", "application/x-vuze"); file_types.put("vuz", "application/x-vuze"); file_types.put("zip", "application/zip"); file_types.put("txt", "text/plain"); file_types.put("jar", "application/java-archive"); file_types.put("jnlp", "application/x-java-jnlp-file"); file_types.put("mp3", "audio/x-mpeg"); file_types.put("flv", "video/x-flv"); file_types.put("swf", "application/x-shockwave-flash"); file_types.put("mkv", "video/x-matroska"); file_types.put("mp4", "video/mp4"); file_types.put("mov", "video/quicktime"); file_types.put("avi", "video/avi"); file_types.put("xap", "application/x-silverlight-app"); compression.add("text/html"); compression.add("text/css"); compression.add("text/xml"); compression.add("text/plain"); compression.add("text/javascript"); } /** * @param file_type file extension * @return apropriate content type string if found */ public static String guessContentTypeFromFileType(String file_type) { if (file_type != null) { String type = (String) file_types.get(file_type.toLowerCase( Constants.LOCALE_ENGLISH )); if (type != null) { return (type); } } return (default_type); } public static boolean canGZIP( String accept_encoding ) { boolean gzip_reply = false; if ( accept_encoding != null ){ accept_encoding = accept_encoding.toLowerCase( Constants.LOCALE_ENGLISH ); int gzip_index = accept_encoding.indexOf( "gzip" ); if ( gzip_index != -1 ){ gzip_reply = true; if ( accept_encoding.length() - gzip_index >= 8 ){ // gzip;q=0 // look to see if there's a q=0 (or 0.0) disabling gzip char[] chars = accept_encoding.toCharArray(); boolean q_value = false; for (int i=gzip_index+4;i 2) { int semi_pos = chunk.indexOf(';'); if (semi_pos != -1) { chunk = chunk.substring(0, semi_pos); } chunk = chunk.trim(); int chunk_length = Integer.parseInt(chunk, 16); if (chunk_length <= 0) { break; } total_length += chunk_length; if (total_length > 1024 * 1024) { throw (new IOException("Chunk size " + chunk_length + " too large")); } byte[] buffer = new byte[chunk_length]; int buffer_pos = 0; int rem = chunk_length; while (rem > 0) { int len = is.read(buffer, buffer_pos, rem); if (len <= 0) { throw (new IOException( "Premature end of stream")); } buffer_pos += len; rem -= len; } baos.write(buffer); chunk = ""; } } return (new ByteArrayInputStream(baos.toByteArray())); } } return (is); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/AZ3Functions.java0000644000175000017500000000275011134300662023602 0ustar adrianadrian/* * Created on Jan 7, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util; import java.net.URL; import org.gudy.azureus2.core3.download.DownloadManager; public class AZ3Functions { private static volatile provider provider; public static void setProvider( provider _p ) { provider = _p; } public static provider getProvider() { return( provider ); } public interface provider { public void subscribeToRSS( String name, URL url, int interval, boolean is_public, String creator_ref ) throws Exception; public boolean canShowCDP( DownloadManager dm ); public void showCDP( DownloadManager dm, String ref ); public String getCDPURL( DownloadManager dm ); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/Java15Utils.java0000644000175000017500000000350311305665622023373 0ustar adrianadrian/* * Created on Feb 11, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.util; import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.management.ThreadMXBean; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; public class Java15Utils { private static ThreadMXBean thread_bean; static{ try{ thread_bean = ManagementFactory.getThreadMXBean(); }catch( Throwable e ){ e.printStackTrace(); } } public static void setConnectTimeout( URLConnection con, int timeout ) { con.setConnectTimeout( timeout ); } public static void setReadTimeout( URLConnection con, int timeout ) { con.setReadTimeout( timeout ); } public static long getThreadCPUTime() { if ( thread_bean == null ){ return( 0 ); } return( thread_bean.getCurrentThreadCpuTime()); } public static void dumpThreads() { AEThreadMonitor.dumpThreads(); } public static URLConnection openConnectionForceNoProxy( URL url) throws IOException { return url.openConnection(Proxy.NO_PROXY); } } azureus-4.3.0.6/com/aelitis/azureus/core/util/HashCodeUtils.java0000644000175000017500000000451010734553146024023 0ustar adrianadrian/* * Created by Joseph Bridgewater * Created on Feb 24, 2006 * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util; /** * @author MjrTom Feb 24, 2006 * This is for utilities for calculating custom object hashCode() values */ public final class HashCodeUtils { public static final int hashMore(final int hash, final int more) { int result =hash <<1; if (result <0) result |=1; return result ^more; } public static final int hashMore(final int hash, final long more) { int result =hashMore(hash, (int)(more >>>32)); return hashMore(result, (int)(more &0xffff)); } public static final int hashMore(final int hash, final boolean[] more) { int result =hash <<1; if (result <0) result |=1; if (more[0]) result ^=1; for (int i =1; i > 6); } hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15); return hash; } } azureus-4.3.0.6/com/aelitis/azureus/core/peer/0000755000175000017500000000000011310377556020437 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/peer/cache/0000755000175000017500000000000011310377630021473 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/peer/cache/CacheDiscovery.java0000644000175000017500000001566611135746222025251 0ustar adrianadrian/* * Created on Feb 1, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peer.cache; import java.net.InetAddress; import java.util.*; import org.gudy.azureus2.core3.ipfilter.BannedIp; import org.gudy.azureus2.core3.ipfilter.IPFilterListener; import org.gudy.azureus2.core3.ipfilter.IpFilter; import org.gudy.azureus2.core3.ipfilter.IpFilterManagerFactory; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.HostNameToIPResolver; import org.gudy.azureus2.core3.util.IPToHostNameResolver; import org.gudy.azureus2.core3.util.IPToHostNameResolverListener; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.download.DownloadManagerEnhancer; import com.aelitis.azureus.core.download.EnhancedDownloadManager; // import com.aelitis.azureus.core.peer.cache.cachelogic.CLCacheDiscovery; public class CacheDiscovery { private static final IpFilter ip_filter = IpFilterManagerFactory.getSingleton().getIPFilter(); private static final CacheDiscoverer[] discoverers = { // No longer supported: new CLCacheDiscovery(), }; private static Set cache_ips = Collections.synchronizedSet(new HashSet()); public static void initialise( final DownloadManagerEnhancer dme ) { ip_filter.addListener( new IPFilterListener() { public boolean canIPBeBanned( String ip ) { return( canBan( ip )); } public void IPBanned( BannedIp ip ) { } public void IPBlockedListChanged( IpFilter filter) { } public boolean canIPBeBlocked( String ip, byte[] torrent_hash) { EnhancedDownloadManager dm = dme.getEnhancedDownload( torrent_hash ); if ( dm == null ){ return( true ); } if ( dm.isPlatform()){ return( canBan( ip )); } return( true ); } }); new AEThread2( "CacheDiscovery:ban checker", true ) { public void run() { BannedIp[] bans = ip_filter.getBannedIps(); for (int i=0;i result = new ArrayList(); for (int i=0;i now ){ create_time = now; } return( create_time ); } public long getInjectTime( long now ) { if ( inject_time > now ){ inject_time = now; } return( inject_time ); } public void setInjectTime( long time ) { inject_time = time; } public long getSpeedChangeTime( long now ) { if ( speed_change_time > now ){ speed_change_time = now; } return( speed_change_time ); } public void setSpeedChangeTime( long time ) { speed_change_time = time; } public boolean getAutoReconnect() { return( auto_reconnect ); } public void setAutoReconnect( boolean auto ) { auto_reconnect = auto; } public boolean sameAs( CachePeer other ) { return( getType() == other.getType() && getAddress().getHostAddress().equals( other.getAddress().getHostAddress()) && getPort() == other.getPort()); } public String getString() { return( "type=" + getType() + ",address=" + getAddress() + ",port=" + getPort()); } } } azureus-4.3.0.6/com/aelitis/azureus/core/peer/cache/CacheDiscoverer.java0000644000175000017500000000234510561016354025373 0ustar adrianadrian/* * Created on Feb 1, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peer.cache; import java.net.InetAddress; import org.gudy.azureus2.core3.torrent.TOTorrent; public interface CacheDiscoverer { public CachePeer[] lookup( TOTorrent torent ); public CachePeer lookup( byte[] peer_id, InetAddress ip, int port ); } azureus-4.3.0.6/com/aelitis/azureus/core/peer/cache/cachelogic/0000755000175000017500000000000011310377630023554 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/peer/cache/cachelogic/CLCacheDiscovery.java0000644000175000017500000002052010621226246027530 0ustar adrianadrian/* * Created on Jan 31, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ /** * * This class handles communication with the CDP server. * Original code from * @author Matthias Scheler * */ package com.aelitis.azureus.core.peer.cache.cachelogic; import java.io.File; import java.net.*; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SHA1Hasher; import com.aelitis.azureus.core.peer.cache.CacheDiscoverer; import com.aelitis.azureus.core.peer.cache.CacheDiscovery; import com.aelitis.azureus.core.peer.cache.CachePeer; import com.aelitis.azureus.core.peermanager.utils.PeerClassifier; public class CLCacheDiscovery implements CacheDiscoverer { public static final String CDPDomainName = ".find-cache.com"; public static final String CDPServerName = "cls" + CDPDomainName; public static final int CDPPort = 19523; public static final int CDPVersion = 0; public static final int CDPTimeout = 5000; static CDPResponse Response; /* Convert an array of bytes into a its hexadecimal representation. */ private String byteArrayToHex(byte[] Bytes, int Max) { int Length, Index, Value; String Result; Length = Bytes.length; if (Length > Max) Length = Max; Result = new String(); for (Index = 0; Index < Length; Index++) { Value = Bytes[Index] & 0xff; if (Value < 16) Result += "0"; Result += Integer.toHexString(Value); } return Result; } /* Find out the farm name via CDP. */ private String lookupFarm() { if (Response != null) { if (Response.isStillValid()){ return Response.getFarmID(); } Response = null; } try { InetAddress CDPServer; DatagramSocket Socket; CDPQuery Query; byte[] Buffer; DatagramPacket Packet; /* Get the IP address of the CDP servers. */ CDPServer = InetAddress.getByName(CDPServerName); /* Create a UDP socket for the CDP query. */ Socket = new DatagramSocket(); Socket.setSoTimeout(CDPTimeout); /* Build the CDP query. */ Query = new CDPQuery(Constants.AZUREUS_NAME + " " + Constants.AZUREUS_VERSION); Buffer = Query.getBytes(); Packet = new DatagramPacket(Buffer, Buffer.length, CDPServer, CDPPort); /* Send the query to the CDP server. */ Socket.send(Packet); /* Receive the CDP response. */ Buffer = new byte[CDPResponse.MaxSize]; Packet.setData(Buffer); Socket.receive(Packet); if (Packet.getAddress() != CDPServer || Packet.getPort() != CDPPort) throw(new Exception("CDP server address mismatch on response")); /* Parse the CDP response. */ Response = new CDPResponse(Packet.getData()); /* Return the farmID from the CDP response. */ return Response.getFarmID(); } catch (Throwable Excpt) { if ( Excpt instanceof UnknownHostException ){ }else{ Excpt.printStackTrace(); } return "default"; } } /* Calculate publisher string for DNS query from announce URL. */ private String hashAnnounceURL( URL announce_url ) { /* Calculate SHA1 hash of the hostname. */ byte[] Digest = new SHA1Hasher().calculateHash( announce_url.getHost().getBytes()); /* * Return first 32 characters of the hexadecimal representation of the * SHA1 hash. */ return byteArrayToHex(Digest, 16); } /* Find a cache for a given announce URL and BitTorrent hash. */ public InetAddress[] findCache( URL announce_url, String hex_hash ) { String Hostname; InetAddress[] Caches; /* * Build the hostname for the DNS query: * bt-.bt--.find-cache.com * * short hash: first four hexadecimal digits of the BitTorrent hash * announce hash: see hashAnnounceURL() * farm: farm name returned by CDP query. */ Hostname = "bt-" + hex_hash.substring(0, 4) + ".bt-" + hashAnnounceURL(announce_url) + "-" + lookupFarm() + CDPDomainName; // System.out.println("findCache(): " + announce_url + " " + hex_hash + " --> " + Hostname); try { Caches = InetAddress.getAllByName(Hostname); } catch (UnknownHostException NoCache) { Caches = new InetAddress[0]; } return Caches; } /* Find a cache for a given announce URL and BitTorrent hash. */ public InetAddress[] findCache( URL announce_url, byte[] hash ) { return findCache(announce_url, byteArrayToHex(hash, 4)); } public CachePeer[] lookup( TOTorrent torrent ) { try{ InetAddress[] addresses = findCache( torrent.getAnnounceURL(), torrent.getHash()); CachePeer[] result = new CachePeer[addresses.length]; for (int i=0;i * */ class CDPResponse { public static final int MinSize = 7; public static final int MaxSize = 262; /* The CDP farm ID. */ String farmID; /* This CDP response is valid until this point of time. */ long validUntil; /* Create a response object from a given binary encoded CDP message. */ public CDPResponse(byte[] Bytes) throws Exception { int Index; long Timeout; if (Bytes.length < MinSize || MinSize + Bytes[6] > Bytes.length) throw new Exception("CDP response too short"); if (Bytes[0] != CDPVersion) throw new Exception("Unsupported CDP version"); farmID = new String(); for (Index = 0; Index < Bytes[6]; Index++) farmID += (char)Bytes[MinSize + Index]; Timeout = 0; for (Index = 2; Index < 6; Index++) Timeout = (Timeout << 8) + ((int)Bytes[Index] & 0xff); validUntil = System.currentTimeMillis() + Timeout * 1000; } /* Return the farm ID. */ public String getFarmID() { return farmID; } /* Is the information in this CDP response still valid? */ public boolean isStillValid() { return (System.currentTimeMillis() < validUntil); } } public static void main( String[] args ) { try{ TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedFile( new File( "C:\\temp\\test.torrent" )); CachePeer[] peers = new CLCacheDiscovery().lookup( torrent ); System.out.println( "peers=" + peers.length ); for (int i=0;i> 8)); buffer.put(DirectByteBuffer.SS_MSG, (byte)(s_port & 0xff)); buffer.flip(DirectByteBuffer.SS_MSG); } return new DirectByteBuffer[] {buffer}; } public String getDescription() { return getID() + " (port " + port + ")"; } public void destroy() { if (buffer != null) {buffer.returnToPool();} } public String getFeatureID() {return BTMessage.BT_FEATURE_ID;} public int getFeatureSubID() {return BTMessage.SUBID_BT_DHT_PORT;} public String getID() {return BTMessage.ID_BT_DHT_PORT;} public byte[] getIDBytes() {return BTMessage.ID_BT_DHT_PORT_BYTES;} public int getType() {return Message.TYPE_PROTOCOL_PAYLOAD;} public byte getVersion() {return (byte)1;} public int getDHTPort() {return port;} } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTCancel.java0000644000175000017500000001000410572775040030413 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; /** * BitTorrent cancel message. */ public class BTCancel implements BTMessage { private DirectByteBuffer buffer = null; private byte version; private String description = null; private final int piece_number; private final int piece_offset; private final int length; public BTCancel( int piece_number, int piece_offset, int length, byte version ) { this.piece_number = piece_number; this.piece_offset = piece_offset; this.length = length; this.version = version; } public int getPieceNumber() { return piece_number; } public int getPieceOffset() { return piece_offset; } public int getLength() { return length; } public String getID() { return BTMessage.ID_BT_CANCEL; } public byte[] getIDBytes() { return BTMessage.ID_BT_CANCEL_BYTES; } public String getFeatureID() { return BTMessage.BT_FEATURE_ID; } public int getFeatureSubID() { return BTMessage.SUBID_BT_CANCEL; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { if( description == null ) { description = BTMessage.ID_BT_CANCEL + " piece #" + piece_number + ":" + piece_offset + "->" + (piece_offset + length -1); } return description; } public DirectByteBuffer[] getData() { if( buffer == null ) { buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_CANCEL, 12 ); buffer.putInt( DirectByteBuffer.SS_MSG, piece_number ); buffer.putInt( DirectByteBuffer.SS_MSG, piece_offset ); buffer.putInt( DirectByteBuffer.SS_MSG, length ); buffer.flip( DirectByteBuffer.SS_MSG ); } return new DirectByteBuffer[]{ buffer }; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { if( data == null ) { throw new MessageException( "[" +getID() +"] decode error: data == null" ); } if( data.remaining( DirectByteBuffer.SS_MSG ) != 12 ) { throw new MessageException( "[" +getID() + "] decode error: payload.remaining[" +data.remaining( DirectByteBuffer.SS_MSG )+ "] != 12" ); } int num = data.getInt( DirectByteBuffer.SS_MSG ); if( num < 0 ) { throw new MessageException( "[" +getID() + "] decode error: num < 0" ); } int offset = data.getInt( DirectByteBuffer.SS_MSG ); if( offset < 0 ) { throw new MessageException( "[" +getID()+ "] decode error: offset < 0" ); } int length = data.getInt( DirectByteBuffer.SS_MSG ); if( length < 0 ) { throw new MessageException( "[" +getID() + "] decode error: lngth < 0" ); } data.returnToPool(); return new BTCancel( num, offset, length, version ); } public void destroy() { if( buffer != null ) buffer.returnToPool(); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTChoke.java0000644000175000017500000000452110572775040030266 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; /** * BitTorrent choke message. */ public class BTChoke implements BTMessage { private byte version; public BTChoke(byte _version) { version = _version; } public String getID() { return BTMessage.ID_BT_CHOKE; } public byte[] getIDBytes() { return BTMessage.ID_BT_CHOKE_BYTES; } public String getFeatureID() { return BTMessage.BT_FEATURE_ID; } public int getFeatureSubID() { return BTMessage.SUBID_BT_CHOKE; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { return BTMessage.ID_BT_CHOKE; } public DirectByteBuffer[] getData() { return new DirectByteBuffer[] {}; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { if( data != null && data.hasRemaining( DirectByteBuffer.SS_MSG ) ) { throw new MessageException( "[" +getID() + "] decode error: payload not empty [" +data.remaining(DirectByteBuffer.SS_MSG)+ "]" ); } if( data != null ) data.returnToPool(); return new BTChoke(version); } public void destroy() { /*nothing*/ } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTBitfield.java0000644000175000017500000000470710572775040030765 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; /** * BitTorrent bitfield message. */ public class BTBitfield implements BTMessage { private final DirectByteBuffer[] buffer; private final byte version; public BTBitfield( DirectByteBuffer bitfield, byte _version ) { buffer = new DirectByteBuffer[] { bitfield }; version = _version; } public DirectByteBuffer getBitfield() { return buffer[0]; } public String getID() { return BTMessage.ID_BT_BITFIELD; } public byte[] getIDBytes() { return BTMessage.ID_BT_BITFIELD_BYTES; } public String getFeatureID() { return BTMessage.BT_FEATURE_ID; } public int getFeatureSubID() { return BTMessage.SUBID_BT_BITFIELD; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { return BTMessage.ID_BT_BITFIELD; } public DirectByteBuffer[] getData() { return buffer; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { if( data == null ) { throw new MessageException( "[" +getID() +"] decode error: data == null" ); } return new BTBitfield( data, version ); } public void destroy() { if( buffer[0] != null ) buffer[0].returnToPool(); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRequest.java0000644000175000017500000001114010572775040030660 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; /** * BitTorrent request message. * NOTE: Overrides equals() */ public class BTRequest implements BTMessage { private byte version; private DirectByteBuffer buffer = null; private String description = null; private final int piece_number; private final int piece_offset; private final int length; private final int hashcode; public BTRequest( int piece_number, int piece_offset, int length, byte version ) { this.piece_number = piece_number; this.piece_offset = piece_offset; this.length = length; this.version = version; this.hashcode = piece_number + piece_offset + length; } public int getPieceNumber() { return piece_number; } public int getPieceOffset() { return piece_offset; } public int getLength() { return length; } public String getID() { return BTMessage.ID_BT_REQUEST; } public byte[] getIDBytes() { return BTMessage.ID_BT_REQUEST_BYTES; } public String getFeatureID() { return BTMessage.BT_FEATURE_ID; } public int getFeatureSubID() { return BTMessage.SUBID_BT_REQUEST; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { if( description == null ) { description = BTMessage.ID_BT_REQUEST + " piece #" + piece_number + ":" + piece_offset + "->" + (piece_offset + length -1); } return description; } public DirectByteBuffer[] getData() { if( buffer == null ) { buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_REQUEST, 12 ); buffer.putInt( DirectByteBuffer.SS_MSG, piece_number ); buffer.putInt( DirectByteBuffer.SS_MSG, piece_offset ); buffer.putInt( DirectByteBuffer.SS_MSG, length ); buffer.flip( DirectByteBuffer.SS_MSG ); } return new DirectByteBuffer[]{ buffer }; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { if( data == null ) { throw new MessageException( "[" +getID() + "] decode error: data == null" ); } if( data.remaining( DirectByteBuffer.SS_MSG ) != 12 ) { throw new MessageException( "[" +getID() + "] decode error: payload.remaining[" +data.remaining( DirectByteBuffer.SS_MSG )+ "] != 12" ); } int num = data.getInt( DirectByteBuffer.SS_MSG ); if( num < 0 ) { throw new MessageException( "[" +getID() + "] decode error: num < 0" ); } int offset = data.getInt( DirectByteBuffer.SS_MSG ); if( offset < 0 ) { throw new MessageException( "[" +getID() + "] decode error: offset < 0" ); } int length = data.getInt( DirectByteBuffer.SS_MSG ); if( length < 0 ) { throw new MessageException( "[" +getID() + "] decode error: length < 0" ); } data.returnToPool(); return new BTRequest( num, offset, length, version ); } public void destroy() { if( buffer != null ) buffer.returnToPool(); } //used for removing individual requests from the message queue public boolean equals( Object obj ) { if( this == obj ) return true; if( obj != null && obj instanceof BTRequest ) { BTRequest other = (BTRequest)obj; if( other.piece_number == this.piece_number && other.piece_offset == this.piece_offset && other.length == this.length ) return true; } return false; } public int hashCode() { return hashcode; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageFactory.java0000644000175000017500000002457111012174754032153 0ustar adrianadrian/* * Created on Feb 9, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import java.util.HashMap; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.DirectByteBufferPool; import com.aelitis.azureus.core.networkmanager.RawMessage; import com.aelitis.azureus.core.networkmanager.impl.RawMessageImpl; import com.aelitis.azureus.core.peermanager.messaging.*; /** * */ public class BTMessageFactory { public static final byte MESSAGE_VERSION_INITIAL = 1; public static final byte MESSAGE_VERSION_SUPPORTS_PADDING = 2; // most of these messages are also used by AZ code private static final LogIDs LOGID = LogIDs.PEER; /** * Initialize the factory, i.e. register the messages with the message manager. */ public static void init() { try { MessageManager.getSingleton().registerMessageType( new BTBitfield( null, MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new BTCancel( -1, -1, -1, MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new BTChoke( MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new BTHandshake( new byte[0], new byte[0], true, MESSAGE_VERSION_INITIAL )); MessageManager.getSingleton().registerMessageType( new BTHave( -1, MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new BTInterested( MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new BTKeepAlive(MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new BTPiece( -1, -1, null, MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new BTRequest( -1, -1 , -1, MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new BTUnchoke( MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new BTUninterested( MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new BTLTMessage( null, MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new BTDHTPort(-1)); } catch( MessageException me ) { me.printStackTrace(); } } private static final String[] id_to_name = new String[21]; private static final HashMap legacy_data = new HashMap(); static { legacy_data.put( BTMessage.ID_BT_CHOKE, new LegacyData( RawMessage.PRIORITY_HIGH, true, new Message[]{new BTUnchoke((byte)0), new BTPiece( -1, -1, null,(byte)0 )}, (byte)0 ) ); id_to_name[0] = BTMessage.ID_BT_CHOKE; legacy_data.put( BTMessage.ID_BT_UNCHOKE, new LegacyData( RawMessage.PRIORITY_NORMAL, true, new Message[]{new BTChoke((byte)0)}, (byte)1 ) ); id_to_name[1] = BTMessage.ID_BT_UNCHOKE; legacy_data.put( BTMessage.ID_BT_INTERESTED, new LegacyData( RawMessage.PRIORITY_HIGH, true, new Message[]{new BTUninterested((byte)0)}, (byte)2 ) ); id_to_name[2] = BTMessage.ID_BT_INTERESTED; legacy_data.put( BTMessage.ID_BT_UNINTERESTED, new LegacyData( RawMessage.PRIORITY_NORMAL, false, new Message[]{new BTInterested((byte)0)}, (byte)3 ) ); id_to_name[3] = BTMessage.ID_BT_UNINTERESTED; legacy_data.put( BTMessage.ID_BT_HAVE, new LegacyData( RawMessage.PRIORITY_LOW, false, null, (byte)4 ) ); id_to_name[4] = BTMessage.ID_BT_HAVE; legacy_data.put( BTMessage.ID_BT_BITFIELD, new LegacyData( RawMessage.PRIORITY_HIGH, true, null, (byte)5 ) ); id_to_name[5] = BTMessage.ID_BT_BITFIELD; legacy_data.put( BTMessage.ID_BT_REQUEST, new LegacyData( RawMessage.PRIORITY_NORMAL, true, null, (byte)6 ) ); id_to_name[6] = BTMessage.ID_BT_REQUEST; legacy_data.put( BTMessage.ID_BT_PIECE, new LegacyData( RawMessage.PRIORITY_LOW, false, null, (byte)7 ) ); id_to_name[7] = BTMessage.ID_BT_PIECE; legacy_data.put( BTMessage.ID_BT_CANCEL, new LegacyData( RawMessage.PRIORITY_HIGH, true, null, (byte)8 ) ); id_to_name[8] = BTMessage.ID_BT_CANCEL; legacy_data.put( BTMessage.ID_BT_DHT_PORT, new LegacyData( RawMessage.PRIORITY_LOW, true, null, (byte)9 ) ); id_to_name[9] = BTMessage.ID_BT_DHT_PORT; legacy_data.put( BTMessage.ID_BT_LT_EXT_MESSAGE, new LegacyData( RawMessage.PRIORITY_HIGH, true, null, (byte)20 ) ); id_to_name[20] = BTMessage.ID_BT_LT_EXT_MESSAGE; } /** * Construct a new BT message instance from the given message raw byte stream. * @param stream_payload data * @return decoded/deserialized BT message * @throws MessageException if message creation failed * NOTE: Does not auto-return given direct buffer on thrown exception. */ public static Message createBTMessage( DirectByteBuffer stream_payload) throws MessageException { byte id = stream_payload.get( DirectByteBuffer.SS_MSG ); switch( id ) { case 0: return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_CHOKE_BYTES, stream_payload, (byte)1 ); case 1: return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_UNCHOKE_BYTES, stream_payload, (byte)1 ); case 2: return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_INTERESTED_BYTES, stream_payload, (byte)1 ); case 3: return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_UNINTERESTED_BYTES, stream_payload, (byte)1 ); case 4: return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_HAVE_BYTES, stream_payload, (byte)1 ); case 5: return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_BITFIELD_BYTES, stream_payload, (byte)1 ); case 6: return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_REQUEST_BYTES, stream_payload, (byte)1 ); case 7: return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_PIECE_BYTES, stream_payload, (byte)1 ); case 8: return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_CANCEL_BYTES, stream_payload, (byte)1 ); case 9: return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_DHT_PORT_BYTES, stream_payload, (byte)1 ); case 20: //Clients seeing our handshake reserved bit will send us the old 'extended' messaging hello message accidentally. //Instead of throwing an exception and dropping the peer connection, we'll just fake it as a keep-alive :) if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Old extended messaging hello received (or malformed LT extension message), " + "ignoring and faking as keep-alive.")); return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_KEEP_ALIVE_BYTES, null, (byte)1 ); default: { System.out.println( "Unknown BT message id [" +id+ "]" ); throw new MessageException( "Unknown BT message id [" +id+ "]" ); } } } public static int getMessageType( DirectByteBuffer stream_payload ) { byte id = stream_payload.get( DirectByteBuffer.SS_MSG, 0 ); if( id == 84 ) return Message.TYPE_PROTOCOL_PAYLOAD; //handshake message byte in position 4 if ( id >= 0 && id < id_to_name.length ){ String name = id_to_name[ id ]; if ( name != null ){ Message message = MessageManager.getSingleton().lookupMessage( name ); if ( message != null ){ return( message.getType()); } } } // invalid, return whatever return Message.TYPE_PROTOCOL_PAYLOAD; } /** * Create the proper BT raw message from the given base message. * @param base_message to create from * @return BT raw message */ public static RawMessage createBTRawMessage( Message base_message ) { if( base_message instanceof RawMessage ) { //used for handshake and keep-alive messages return (RawMessage)base_message; } LegacyData ld = (LegacyData)legacy_data.get( base_message.getID() ); if( ld == null ) { Debug.out( "legacy message type id not found for [" +base_message.getID()+ "]" ); return null; //message id type not found } DirectByteBuffer[] payload = base_message.getData(); int payload_size = 0; for( int i=0; i < payload.length; i++ ) { payload_size += payload[i].remaining( DirectByteBuffer.SS_MSG ); } DirectByteBuffer header = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_HEADER, 5 ); header.putInt( DirectByteBuffer.SS_MSG, 1 + payload_size ); header.put( DirectByteBuffer.SS_MSG, ld.bt_id ); header.flip( DirectByteBuffer.SS_MSG ); DirectByteBuffer[] raw_buffs = new DirectByteBuffer[ payload.length + 1 ]; raw_buffs[0] = header; for( int i=0; i < payload.length; i++ ) { raw_buffs[i+1] = payload[i]; } return new RawMessageImpl( base_message, raw_buffs, ld.priority, ld.is_no_delay, ld.to_remove ); } protected static class LegacyData { protected final int priority; protected final boolean is_no_delay; protected final Message[] to_remove; protected final byte bt_id; protected LegacyData( int prio, boolean no_delay, Message[] remove, byte btid ) { this.priority = prio; this.is_no_delay = no_delay; this.to_remove = remove; this.bt_id = btid; } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHandshake.java0000644000175000017500000001475611070304234031121 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.RawMessage; import com.aelitis.azureus.core.peermanager.messaging.*; import com.aelitis.azureus.core.peermanager.utils.PeerClassifier; /** * BitTorrent handshake message. */ public class BTHandshake implements BTMessage, RawMessage { public static final String PROTOCOL = "BitTorrent protocol"; // No reserve bits set. private static final byte[] BT_RESERVED = new byte[]{0, 0, 0, 0, 0, 0, 0, 0 }; // Set first bit of first byte to indicate advanced AZ messaging support. (128) // Set fourth bit of fifth byte to indicate LT messaging support. (16) // Set seventh bit (2) and eight bit (1) to force AZMP over LTEP. [current behaviour] // Set seventh bit (2) only to prefer AZMP over LTEP. // Set eighth bit (1) only to prefer LTEP over AZMP. private static final byte[] AZ_RESERVED = new byte[]{(byte)128, 0, 0, 0, 0, (byte)19, 0, 0 }; public static void setMainlineDHTEnabled(boolean enabled) { if (enabled) { //BT_RESERVED[7] = (byte)(BT_RESERVED[7] | 0x01); AZ_RESERVED[7] = (byte)(AZ_RESERVED[7] | 0x01); } else { //BT_RESERVED[7] = (byte)(BT_RESERVED[7] & 0xFE); AZ_RESERVED[7] = (byte)(AZ_RESERVED[7] & 0xFE); } } private DirectByteBuffer buffer = null; private String description = null; private final byte[] reserved_bytes; private final byte[] datahash_bytes; private final byte[] peer_id_bytes; private final byte version; private static byte[] duplicate(byte[] b) { byte[] r = new byte[b.length]; System.arraycopy(b, 0, r, 0, b.length); return r; } /** * Used for outgoing handshake message. * @param data_hash * @param peer_id * @param set_reserve_bit */ public BTHandshake( byte[] data_hash, byte[] peer_id, boolean set_reserve_bit, byte version ) { this( duplicate(set_reserve_bit ? AZ_RESERVED : BT_RESERVED), data_hash, peer_id, version ); } private BTHandshake( byte[] reserved, byte[] data_hash, byte[] peer_id, byte version ) { this.reserved_bytes = reserved; this.datahash_bytes = data_hash; this.peer_id_bytes = peer_id; this.version = version; } private void constructBuffer() { buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_HAND, 68 ); buffer.put( DirectByteBuffer.SS_MSG, (byte)PROTOCOL.length() ); buffer.put( DirectByteBuffer.SS_MSG, PROTOCOL.getBytes() ); buffer.put( DirectByteBuffer.SS_MSG, reserved_bytes ); buffer.put( DirectByteBuffer.SS_MSG, datahash_bytes ); buffer.put( DirectByteBuffer.SS_MSG, peer_id_bytes ); buffer.flip( DirectByteBuffer.SS_MSG ); } public byte[] getReserved() { return reserved_bytes; } public byte[] getDataHash() { return datahash_bytes; } public byte[] getPeerId() { return peer_id_bytes; } // message public String getID() { return BTMessage.ID_BT_HANDSHAKE; } public byte[] getIDBytes() { return BTMessage.ID_BT_HANDSHAKE_BYTES; } public String getFeatureID() { return BTMessage.BT_FEATURE_ID; } public int getFeatureSubID() { return BTMessage.SUBID_BT_HANDSHAKE; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { if( description == null ) { description = BTMessage.ID_BT_HANDSHAKE + " of dataID: " +ByteFormatter.nicePrint( datahash_bytes, true ) + " peerID: " +PeerClassifier.getPrintablePeerID( peer_id_bytes ); } return description; } public DirectByteBuffer[] getData() { if( buffer == null ) { constructBuffer(); } return new DirectByteBuffer[]{ buffer }; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { if( data == null ) { throw new MessageException( "[" +getID() + "] decode error: data == null" ); } if( data.remaining( DirectByteBuffer.SS_MSG ) != 68 ) { throw new MessageException( "[" +getID() + "] decode error: payload.remaining[" +data.remaining( DirectByteBuffer.SS_MSG )+ "] != 68" ); } if( data.get( DirectByteBuffer.SS_MSG ) != (byte)PROTOCOL.length() ) { throw new MessageException( "[" +getID() + "] decode error: payload.get() != (byte)PROTOCOL.length()" ); } byte[] header = new byte[ PROTOCOL.getBytes().length ]; data.get( DirectByteBuffer.SS_MSG, header ); if( !PROTOCOL.equals( new String( header ) ) ) { throw new MessageException( "[" +getID() + "] decode error: invalid protocol given: " + new String( header ) ); } byte[] reserved = new byte[ 8 ]; data.get( DirectByteBuffer.SS_MSG, reserved ); byte[] infohash = new byte[ 20 ]; data.get( DirectByteBuffer.SS_MSG, infohash ); byte[] peerid = new byte[ 20 ]; data.get( DirectByteBuffer.SS_MSG, peerid ); data.returnToPool(); return new BTHandshake( reserved, infohash, peerid, version ); } // raw message public DirectByteBuffer[] getRawData() { if( buffer == null ) { constructBuffer(); } return new DirectByteBuffer[]{ buffer }; } public int getPriority() { return RawMessage.PRIORITY_HIGH; } public boolean isNoDelay() { return true; } public void setNoDelay(){} public Message[] messagesToRemove() { return null; } public void destroy() { if( buffer != null ) buffer.returnToPool(); } public Message getBaseMessage() { return this; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTUninterested.java0000644000175000017500000000453710572775040031715 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; /** * BitTorrent uninterested message. */ public class BTUninterested implements BTMessage { private final byte version; public BTUninterested(byte _version) { version = _version; } public String getID() { return BTMessage.ID_BT_UNINTERESTED; } public byte[] getIDBytes() { return BTMessage.ID_BT_UNINTERESTED_BYTES; } public String getFeatureID() { return BTMessage.BT_FEATURE_ID; } public int getFeatureSubID() { return BTMessage.SUBID_BT_UNINTERESTED; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { return BTMessage.ID_BT_UNINTERESTED; } public DirectByteBuffer[] getData() { return new DirectByteBuffer[] {}; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { if( data != null && data.hasRemaining( DirectByteBuffer.SS_MSG ) ) { throw new MessageException( "[" +getID() +"] decode error: payload not empty" ); } if( data != null ) data.returnToPool(); return new BTUninterested(version); } public void destroy() { /*nothing*/ } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageDecoder.java0000644000175000017500000003147311301416454032105 0ustar adrianadrian/* * Created on Jan 24, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import java.io.IOException; import java.nio.ByteBuffer; import java.util.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.Transport; import com.aelitis.azureus.core.peermanager.messaging.*; /** * */ public class BTMessageDecoder implements MessageStreamDecoder { private static final int MIN_MESSAGE_LENGTH = 1; //for type id private static final int MAX_MESSAGE_LENGTH = 16*1024+128; //should never be > 16KB+9B, as we never request chunks > 16KB - update, some LT extensions can be bigger private static final int HANDSHAKE_FAKE_LENGTH = 323119476; //(byte)19 + "Bit" readInt() value of header private static final byte SS = DirectByteBuffer.SS_MSG; private DirectByteBuffer payload_buffer = null; private final DirectByteBuffer length_buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG, 4 ); private final ByteBuffer[] decode_array = new ByteBuffer[] { null, length_buffer.getBuffer( SS ) }; private boolean reading_length_mode = true; private boolean reading_handshake_message = false; private int message_length; private int pre_read_start_buffer; private int pre_read_start_position; private boolean last_received_was_keepalive = false; private volatile boolean destroyed = false; private volatile boolean is_paused = false; private ArrayList messages_last_read = new ArrayList(); private int protocol_bytes_last_read = 0; private int data_bytes_last_read = 0; private int percent_complete = -1; public BTMessageDecoder() { /* nothing */ } public int performStreamDecode( Transport transport, int max_bytes ) throws IOException { protocol_bytes_last_read = 0; data_bytes_last_read = 0; int bytes_remaining = max_bytes; while( bytes_remaining > 0 ) { if( destroyed ) { // destruction currently isn't thread safe so one thread can destroy the decoder (e.g. when closing a connection) // while the read-controller is still actively processing the us //throw( new IOException( "BTMessageDecoder already destroyed" )); break; } if( is_paused ) { break; } int bytes_possible = preReadProcess( bytes_remaining ); if( bytes_possible < 1 ) { Debug.out( "ERROR BT: bytes_possible < 1" ); break; } if( reading_length_mode ) { transport.read( decode_array, 1, 1 ); //only read into length buffer } else { transport.read( decode_array, 0, 2 ); //read into payload buffer, and possibly next message length } int bytes_read = postReadProcess(); bytes_remaining -= bytes_read; if( bytes_read < bytes_possible ) { break; } if( reading_length_mode && last_received_was_keepalive ) { //hack to stop a 0-byte-read after receiving a keep-alive message //otherwise we won't realize there's nothing left on the line until trying to read again last_received_was_keepalive = false; break; } } return max_bytes - bytes_remaining; } public int getPercentDoneOfCurrentMessage() { return percent_complete; } public Message[] removeDecodedMessages() { if( messages_last_read.isEmpty() ) return null; Message[] msgs = (Message[])messages_last_read.toArray( new Message[messages_last_read.size()] ); messages_last_read.clear(); return msgs; } public int getProtocolBytesDecoded() { return protocol_bytes_last_read; } public int getDataBytesDecoded() { return data_bytes_last_read; } public ByteBuffer destroy() { if (destroyed) { Debug.out("Trying to redestroy message decoder, stack trace follows: " + this); Debug.outStackTrace(); } is_paused = true; destroyed = true; int lbuff_read = 0; int pbuff_read = 0; length_buffer.limit( SS, 4 ); if( reading_length_mode ) { lbuff_read = length_buffer.position( SS ); } else { //reading payload length_buffer.position( SS, 4 ); lbuff_read = 4; pbuff_read = payload_buffer == null ? 0 : payload_buffer.position( SS ); } ByteBuffer unused = ByteBuffer.allocate( lbuff_read + pbuff_read ); //TODO convert to direct? length_buffer.flip( SS ); unused.put( length_buffer.getBuffer( SS ) ); if ( payload_buffer != null ) { payload_buffer.flip( SS ); unused.put( payload_buffer.getBuffer( SS ) ); // Got a buffer overflow exception here in the past - related to PEX? } unused.flip(); length_buffer.returnToPool(); if( payload_buffer != null ) { payload_buffer.returnToPool(); payload_buffer = null; } for( int i=0; i < messages_last_read.size(); i++ ) { Message msg = (Message)messages_last_read.get( i ); msg.destroy(); } messages_last_read.clear(); return unused; } private int preReadProcess( int allowed ) { if( allowed < 1 ) { Debug.out( "allowed < 1" ); } decode_array[ 0 ] = payload_buffer == null ? null : payload_buffer.getBuffer( SS ); //ensure the decode array has the latest payload pointer int bytes_available = 0; boolean shrink_remaining_buffers = false; int start_buff = reading_length_mode ? 1 : 0; boolean marked = false; for( int i = start_buff; i < 2; i++ ) { //set buffer limits according to bytes allowed ByteBuffer bb = decode_array[ i ]; if( bb == null ) { Debug.out( "preReadProcess:: bb["+i+"] == null, decoder destroyed=" +destroyed ); } if( shrink_remaining_buffers ) { bb.limit( 0 ); //ensure no read into this next buffer is possible } else { int remaining = bb.remaining(); if( remaining < 1 ) continue; //skip full buffer if( !marked ) { pre_read_start_buffer = i; pre_read_start_position = bb.position(); marked = true; } if( remaining > allowed ) { //read only part of this buffer bb.limit( bb.position() + allowed ); //limit current buffer bytes_available += bb.remaining(); shrink_remaining_buffers = true; //shrink any tail buffers } else { //full buffer is allowed to be read bytes_available += remaining; allowed -= remaining; //count this buffer toward allowed and move on to the next } } } return bytes_available; } private int postReadProcess() throws IOException { int prot_bytes_read = 0; int data_bytes_read = 0; if( !reading_length_mode && !destroyed ) { //reading payload data mode //ensure-restore proper buffer limits payload_buffer.limit( SS, message_length ); length_buffer.limit( SS, 4 ); int read = payload_buffer.position( SS ) - pre_read_start_position; if( payload_buffer.position( SS ) > 0 ) { //need to have read the message id first byte if( BTMessageFactory.getMessageType( payload_buffer) == Message.TYPE_DATA_PAYLOAD ) { data_bytes_read += read; } else { prot_bytes_read += read; } } if( !payload_buffer.hasRemaining( SS ) && !is_paused ) { //full message received! payload_buffer.position( SS, 0 ); DirectByteBuffer ref_buff = payload_buffer; payload_buffer = null; if( reading_handshake_message ) { //decode handshake reading_handshake_message = false; DirectByteBuffer handshake_data = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_HAND, 68 ); handshake_data.putInt( SS, HANDSHAKE_FAKE_LENGTH ); handshake_data.put( SS, ref_buff ); handshake_data.flip( SS ); ref_buff.returnToPool(); try { Message handshake = MessageManager.getSingleton().createMessage( BTMessage.ID_BT_HANDSHAKE_BYTES, handshake_data, (byte)1 ); messages_last_read.add( handshake ); } catch( MessageException me ) { handshake_data.returnToPool(); throw new IOException( "BT message decode failed: " + me.getMessage() ); } //we need to auto-pause decoding until we're told to start again externally, //as we don't want to accidentally read the next message on the stream if it's an AZ-format handshake pauseDecoding(); } else { //decode normal message try { messages_last_read.add(createMessage(ref_buff)); } catch( Throwable e ) { ref_buff.returnToPoolIfNotFree(); // maintain unexpected errors as such so they get logged later if ( e instanceof RuntimeException ){ throw((RuntimeException)e ); } throw new IOException( "BT message decode failed: " +e.getMessage() ); } } reading_length_mode = true; //see if we've already read the next message's length percent_complete = -1; //reset receive percentage } else { //only partial received so far percent_complete = (payload_buffer.position( SS ) * 100) / message_length; //compute receive percentage } } if( reading_length_mode && !destroyed ) { length_buffer.limit( SS, 4 ); //ensure proper buffer limit prot_bytes_read += (pre_read_start_buffer == 1) ? length_buffer.position( SS ) - pre_read_start_position : length_buffer.position( SS ); if( !length_buffer.hasRemaining( SS ) ) { //done reading the length reading_length_mode = false; length_buffer.position( SS, 0 ); message_length = length_buffer.getInt( SS ); length_buffer.position( SS, 0 ); //reset it for next length read if( message_length == HANDSHAKE_FAKE_LENGTH ) { //handshake message reading_handshake_message = true; message_length = 64; //restore 'real' length payload_buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_HAND, message_length ); } else if( message_length == 0 ) { //keep-alive message reading_length_mode = true; last_received_was_keepalive = true; try{ Message keep_alive = MessageManager.getSingleton().createMessage( BTMessage.ID_BT_KEEP_ALIVE_BYTES, null, (byte)1 ); messages_last_read.add( keep_alive ); } catch( MessageException me ) { throw new IOException( "BT message decode failed: " + me.getMessage() ); } } else if( message_length < MIN_MESSAGE_LENGTH || message_length > MAX_MESSAGE_LENGTH ) { throw new IOException( "Invalid message length given for BT message decode: " + message_length ); } else { //normal message payload_buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_PAYLOAD, message_length ); } } } protocol_bytes_last_read += prot_bytes_read; data_bytes_last_read += data_bytes_read; return prot_bytes_read + data_bytes_read; } public void pauseDecoding() { is_paused = true; } public void resumeDecoding() { is_paused = false; } // Overridden by LTMessageDecoder. protected Message createMessage(DirectByteBuffer ref_buff) throws MessageException { try {return BTMessageFactory.createBTMessage(ref_buff);} catch (MessageException me) { /*if (identifier != null && me.getMessage() != null && me.getMessage().startsWith("Unknown BT message id")) { System.out.println(identifier + " " + me.getMessage()); }*/ throw me; } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageEncoder.java0000644000175000017500000000307010565520424032113 0ustar adrianadrian/* * Created on Feb 8, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import com.aelitis.azureus.core.networkmanager.RawMessage; import com.aelitis.azureus.core.peermanager.messaging.*; /** * Creates legacy (i.e. traditional BitTorrent wire protocol) raw messages. * NOTE: wire format: [total message length] + [message id byte] + [payload bytes] */ public class BTMessageEncoder implements MessageStreamEncoder { public BTMessageEncoder() { /*nothing*/ } public RawMessage[] encodeMessage( Message message ) { return new RawMessage[]{ BTMessageFactory.createBTRawMessage( message )}; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHave.java0000644000175000017500000000633510572775040030125 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; /** * BitTorrent have message. */ public class BTHave implements BTMessage { private byte version; private DirectByteBuffer buffer = null; private String description = null; private final int piece_number; public BTHave( int piece_number, byte version ) { this.piece_number = piece_number; this.version = version; } public int getPieceNumber() { return piece_number; } public String getID() { return BTMessage.ID_BT_HAVE; } public byte[] getIDBytes() { return BTMessage.ID_BT_HAVE_BYTES; } public String getFeatureID() { return BTMessage.BT_FEATURE_ID; } public int getFeatureSubID() { return BTMessage.SUBID_BT_HAVE; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { if( description == null ) { description = BTMessage.ID_BT_HAVE + " piece #" + piece_number; } return description; } public DirectByteBuffer[] getData() { if( buffer == null ) { buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_HAVE, 4 ); buffer.putInt( DirectByteBuffer.SS_MSG, piece_number ); buffer.flip( DirectByteBuffer.SS_MSG ); } return new DirectByteBuffer[]{ buffer }; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { if( data == null ) { throw new MessageException( "[" +getID() + "] decode error: data == null" ); } if( data.remaining( DirectByteBuffer.SS_MSG ) != 4 ) { throw new MessageException( "[" +getID() + "] decode error: payload.remaining[" +data.remaining( DirectByteBuffer.SS_MSG )+ "] != 4" ); } int number = data.getInt( DirectByteBuffer.SS_MSG ); if( number < 0 ) { throw new MessageException( "[" +getID() + "] decode error: number < 0" ); } data.returnToPool(); return new BTHave( number, version ); } public void destroy() { if( buffer != null ) buffer.returnToPool(); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRawMessage.java0000644000175000017500000000456311062635530031273 0ustar adrianadrian/* * Created on Mar 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.networkmanager.RawMessage; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; public class BTRawMessage implements BTMessage, RawMessage { private DirectByteBuffer buffer; public BTRawMessage( DirectByteBuffer _buffer ) { buffer = _buffer; } public String getID() { return( "" ); } public byte[] getIDBytes() { return( null ); } public String getFeatureID() { return( null ); } public int getFeatureSubID() { return(0); } public int getType() { return( TYPE_DATA_PAYLOAD ); } public String getDescription() { return( "" ); } public byte getVersion() { return( 1 ); } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { throw( new MessageException( "not imp" )); } public DirectByteBuffer[] getData() { return new DirectByteBuffer[]{ buffer }; } public DirectByteBuffer[] getRawData() { return( new DirectByteBuffer[]{ buffer }); } public int getPriority() { return( PRIORITY_HIGH ); } public boolean isNoDelay() { return( true ); } public void setNoDelay() { } public Message[] messagesToRemove() { return( null ); } public Message getBaseMessage() { return( this ); } public void destroy() { if( buffer != null ) buffer.returnToPool(); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTKeepAlive.java0000644000175000017500000000625010757735636031117 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.RawMessage; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; /** * BitTorrent keep-alive message. */ public class BTKeepAlive implements BTMessage, RawMessage { private byte version; private DirectByteBuffer[] buffer = null; private boolean no_delay = false; public BTKeepAlive(byte _version) { version = _version; } // message public String getID() { return BTMessage.ID_BT_KEEP_ALIVE; } public byte[] getIDBytes() { return BTMessage.ID_BT_KEEP_ALIVE_BYTES; } public String getFeatureID() { return BTMessage.BT_FEATURE_ID; } public int getFeatureSubID() { return BTMessage.SUBID_BT_KEEP_ALIVE; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { return BTMessage.ID_BT_KEEP_ALIVE; } public DirectByteBuffer[] getData() { return new DirectByteBuffer[]{}; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { if( data != null && data.hasRemaining( DirectByteBuffer.SS_MSG ) ) { throw new MessageException( "[" +getID() +"] decode error: payload not empty" ); } if( data != null ) data.returnToPool(); return new BTKeepAlive(version); } // raw message public DirectByteBuffer[] getRawData() { if( buffer == null ) { DirectByteBuffer dbb = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_KEEPALIVE, 4 ); dbb.putInt( DirectByteBuffer.SS_BT, 0 ); dbb.flip( DirectByteBuffer.SS_BT ); buffer = new DirectByteBuffer[]{ dbb }; } return buffer; } public int getPriority() { return RawMessage.PRIORITY_LOW; } public boolean isNoDelay() { return no_delay; } public void setNoDelay() { no_delay = true; } public Message[] messagesToRemove() { return null; } public void destroy() { if( buffer != null ) { buffer[0].returnToPool(); } } public Message getBaseMessage() { return this; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTLTMessage.java0000644000175000017500000000573510743530474031071 0ustar adrianadrian/* * Created on 17 Sep 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.DirectByteBufferPool; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; /** * @author Allan Crooks * */ public class BTLTMessage implements BTMessage { public byte extension_id; public Message base_message; public DirectByteBuffer buffer_header; public BTLTMessage(Message base_message, byte extension_id) { this.base_message = base_message; this.extension_id = extension_id; } // This class should not be used for deserialisation! public Message deserialize(DirectByteBuffer data, byte version) throws MessageException { throw new MessageException("BTLTMessage cannot be used for message deserialization!"); } public void destroy() { if (base_message != null) {base_message.destroy();} if (buffer_header != null) { buffer_header.returnToPool(); buffer_header = null; } } public DirectByteBuffer[] getData() { DirectByteBuffer[] orig_data = this.base_message.getData(); DirectByteBuffer[] new_data = new DirectByteBuffer[orig_data.length + 1]; if (buffer_header == null ) { buffer_header = DirectByteBufferPool.getBuffer(DirectByteBuffer.AL_MSG_LT_EXT_MESSAGE, 1); buffer_header.put(DirectByteBuffer.SS_MSG, this.extension_id); buffer_header.flip(DirectByteBuffer.SS_MSG); } new_data[0] = buffer_header; System.arraycopy(orig_data, 0, new_data, 1, orig_data.length); return new_data; } public String getDescription() { return base_message.getDescription(); } public String getFeatureID() { return base_message.getFeatureID(); } public int getFeatureSubID() { return base_message.getFeatureSubID(); } public String getID() { return BTMessage.ID_BT_LT_EXT_MESSAGE; } public byte[] getIDBytes() { return BTMessage.ID_BT_LT_EXT_MESSAGE_BYTES; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return 0; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/0000755000175000017500000000000011310377630027100 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTHandshake.java0000644000175000017500000001057711257507206032107 0ustar adrianadrianpackage com.aelitis.azureus.core.peermanager.messaging.bittorrent.ltep; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Collections; import java.util.Map; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; import com.aelitis.azureus.core.peermanager.messaging.MessagingUtil; public class LTHandshake implements LTMessage { private Map data_dict; private byte[] bencoded_data; private String bencoded_string; private String description; private byte version; private DirectByteBuffer[] buffer_array; public LTHandshake(Map data_dict, byte version) { this.data_dict = (data_dict == null) ? Collections.EMPTY_MAP : data_dict; this.version = version; } public Message deserialize(DirectByteBuffer data, byte version) throws MessageException { if (data == null) { throw new MessageException( "[" +getID() + "] decode error: data == null"); } if (data.remaining(DirectByteBuffer.SS_MSG ) < 1) { throw new MessageException( "[" +getID() + "] decode error: less than 1 byte in payload"); } // Try decoding the data now. Map res_data_dict = MessagingUtil.convertBencodedByteStreamToPayload(data, 1, getID()); LTHandshake result = new LTHandshake(res_data_dict, this.version); return result; } public DirectByteBuffer[] getData() { if (buffer_array == null) { buffer_array = new DirectByteBuffer[1]; DirectByteBuffer buffer = DirectByteBufferPool.getBuffer(DirectByteBuffer.AL_MSG_LT_HANDSHAKE, getBencodedData().length); buffer_array[0] = buffer; buffer.put(DirectByteBuffer.SS_MSG, getBencodedData()); buffer.flip(DirectByteBuffer.SS_MSG); } return buffer_array; } public void destroy() { this.data_dict = null; this.bencoded_data = null; this.description = null; if (buffer_array != null) { buffer_array[0].returnToPool(); } this.buffer_array = null; } public String getDescription() { if (description == null) { description = LTMessage.ID_LT_HANDSHAKE.toUpperCase() + ": " + this.getBencodedString(); } return description; } public String getBencodedString() { if (this.bencoded_string == null) { try { this.bencoded_string = new String(this.getBencodedData(), Constants.BYTE_ENCODING); } catch (java.io.UnsupportedEncodingException uee) { this.bencoded_string = ""; Debug.printStackTrace(uee); } } return this.bencoded_string; } public byte[] getBencodedData() { if (this.bencoded_data == null) { try {this.bencoded_data = BEncoder.encode(this.data_dict);} catch (java.io.IOException ioe) { this.bencoded_data = new byte[0]; Debug.printStackTrace(ioe); } } return this.bencoded_data; } public Map getDataMap() { return this.data_dict; } public String getClientName() { byte[] client_name = (byte[])data_dict.get("v"); if (client_name == null) {return null;} try {return new String(client_name, Constants.DEFAULT_ENCODING);} catch (java.io.IOException ioe) {return null;} } public boolean isUploadOnly() { Long ulOnly = (Long)data_dict.get("upload_only"); return ulOnly != null && ulOnly.longValue() > 0L; } public InetAddress getIPv6() { byte[] addr = (byte[])data_dict.get("ipv6"); if(addr != null && addr.length == 16) { try { return InetAddress.getByAddress(addr); } catch (UnknownHostException e) { // should not happen e.printStackTrace(); } } return null; } public int getTCPListeningPort() { Long port = (Long)data_dict.get("p"); if(port == null) return 0; int val = port.intValue(); if(val <= 65535 && val > 0) return val; return 0; } public Boolean isCryptoRequested() { Long crypto = (Long)data_dict.get("e"); if(crypto == null) return null; return Boolean.valueOf(crypto.longValue() == 1); } public Map getExtensionMapping() { Map result = (Map)data_dict.get("m"); return (result == null) ? Collections.EMPTY_MAP : result; } public String getFeatureID() {return LTMessage.LT_FEATURE_ID;} public int getFeatureSubID() {return LTMessage.SUBID_LT_HANDSHAKE;} public String getID() {return LTHandshake.ID_LT_HANDSHAKE;} public byte[] getIDBytes() {return LTHandshake.ID_LT_HANDSHAKE_BYTES;} public int getType() {return Message.TYPE_PROTOCOL_PAYLOAD;} public byte getVersion() {return this.version;} } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageEncoder.javaazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageEncoder.java0000644000175000017500000001143111017342534033066 0ustar adrianadrian/* * Created on 17 Sep 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent.ltep; import com.aelitis.azureus.core.networkmanager.RawMessage; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageStreamEncoder; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTLTMessage; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTMessageFactory; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.Constants; /** * @author Allan Crooks * */ public class LTMessageEncoder implements MessageStreamEncoder { protected final static LogIDs LOGID = LogIDs.PEER; private Object log_object; private HashMap extension_map; public LTMessageEncoder(Object log_object) { this.log_object = log_object; this.extension_map = null; // Only instantiate it when we need to. } public RawMessage[] encodeMessage(Message message) { if (!(message instanceof LTMessage)) { return new RawMessage[] {BTMessageFactory.createBTRawMessage(message)}; } // What type of message is it? LT_handshake messages are always straight forward. if (message instanceof LTHandshake) { return new RawMessage[] {BTMessageFactory.createBTRawMessage(new BTLTMessage(message, (byte)0))}; } // Other message types have to be matched up against the appropriate ID. if (extension_map != null) { Byte ext_id = (Byte)this.extension_map.get(message.getID()); if (ext_id != null) { //Logger.log(new LogEvent(this.log_object, LOGID, "Converting LT message to BT message, ext id is " + ext_id)); return new RawMessage[] {BTMessageFactory.createBTRawMessage(new BTLTMessage(message, ext_id.byteValue()))}; } } // Anything else means that the client doesn't support that extension. // We'll drop the message instead. if (Logger.isEnabled()) Logger.log(new LogEvent(this.log_object, LOGID, "Unable to send LT message of type " + message.getID() + ", not supported by peer - dropping message.")); return new RawMessage[0]; } public void updateSupportedExtensions(Map map) { try { Iterator itr = map.entrySet().iterator(); while (itr.hasNext()) { Map.Entry extension = (Map.Entry)itr.next(); String ext_name; Object ext_key = extension.getKey(); if (ext_key instanceof byte[]) { ext_name = new String((byte[])ext_key, Constants.DEFAULT_ENCODING); } else if (ext_key instanceof String) { ext_name = (String)ext_key; } else { throw new RuntimeException("unexpected type for extension name: " + ext_key.getClass()); } int ext_value; Object ext_value_obj = extension.getValue(); if (ext_value_obj instanceof Long) { ext_value = ((Long)extension.getValue()).intValue(); } else if (ext_value_obj instanceof byte[]) { byte[] ext_value_bytes = (byte[])ext_value_obj; if (ext_value_bytes.length == 1) { ext_value = (int)ext_value_bytes[0]; } else { throw new RuntimeException("extension id byte array format length != 1: " + ext_value_bytes.length); } } else { throw new RuntimeException("unsupported extension id type: " + ext_value_obj.getClass().getName()); } if (extension_map == null) { this.extension_map = new HashMap(); } if (ext_value == 0) {this.extension_map.remove(ext_name);} else {this.extension_map.put(ext_name, new Byte((byte)ext_value));} } } catch (Exception e) { if (Logger.isEnabled()) Logger.log(new LogEvent(this.log_object, LOGID, "Unable to update LT extension list for peer", e)); } } public boolean supportsUTPEX() { if (this.extension_map == null) {return false;} return this.extension_map.containsKey("ut_pex"); } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTDisabledExtensionMessage.javaazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTDisabledExtensionMe0000644000175000017500000000446410735701464033167 0ustar adrianadrian/* * Created on 17 Sep 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent.ltep; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; /** * @author Allan Crooks * */ public class LTDisabledExtensionMessage implements LTMessage { public static LTDisabledExtensionMessage INSTANCE = new LTDisabledExtensionMessage(); private LTDisabledExtensionMessage() {} public Message deserialize(DirectByteBuffer data, byte version) { return INSTANCE; } public void destroy() {} // Not meant to be used for outgoing messages, so raise an error if anyone tries to do it. public DirectByteBuffer[] getData() { throw new RuntimeException("Disabled extension message not meant to be used for serialisation!"); } /* (non-Javadoc) * @see com.aelitis.azureus.core.peermanager.messaging.Message#getDescription() */ public String getDescription() { return "Disabled extension message over LTEP (ignored)"; } public String getFeatureID() {return LTMessage.LT_FEATURE_ID;} public int getFeatureSubID() {return LTMessage.SUBID_DISABLED_EXT;} public String getID() {return LTMessage.ID_DISABLED_EXT;} public byte[] getIDBytes() {return LTMessage.ID_DISABLED_EXT_BYTES;} public int getType() {return Message.TYPE_PROTOCOL_PAYLOAD;} public byte getVersion() {return 0;} } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessage.java0000644000175000017500000000361110735701360031571 0ustar adrianadrian/* * Created on 17 Sep 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent.ltep; import com.aelitis.azureus.core.peermanager.messaging.Message; /** * @author Allan Crooks * */ public interface LTMessage extends Message { public static final String LT_FEATURE_ID = "LT1"; public static final String ID_LT_HANDSHAKE = "lt_handshake"; public static final byte[] ID_LT_HANDSHAKE_BYTES = ID_LT_HANDSHAKE.getBytes(); public static final int SUBID_LT_HANDSHAKE = 0; public static final String ID_UT_PEX = "ut_pex"; public static final byte[] ID_UT_PEX_BYTES = ID_UT_PEX.getBytes(); public static final int SUBID_UT_PEX = 1; // Placeholder message indicating that a message was sent for an extension which has // been disabled. public static final String ID_DISABLED_EXT = "disabled_extension"; public static final byte[] ID_DISABLED_EXT_BYTES = ID_DISABLED_EXT.getBytes(); public static final int SUBID_DISABLED_EXT = 2; } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTPeerExchange.java0000644000175000017500000003323411007130216032545 0ustar adrianadrian/* * Created on 18 Sep 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent.ltep; import java.util.*; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.networkmanager.NetworkManager; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; import com.aelitis.azureus.core.peermanager.messaging.MessagingUtil; import com.aelitis.azureus.core.peermanager.messaging.azureus.AZStylePeerExchange; import com.aelitis.azureus.core.peermanager.peerdb.PeerItem; import com.aelitis.azureus.core.peermanager.peerdb.PeerItemFactory; /** * @author Allan Crooks * * Largely copied from AZPeerExchange. */ public class UTPeerExchange implements AZStylePeerExchange, LTMessage { // Debug flag for testing purposes - currently disabled by default. public static final boolean ENABLED = true; private static final LogIDs LOGID = LogIDs.NET; private static final int IPv4_SIZE_WITH_PORT = 6; private static final int IPv6_SIZE_WITH_PORT = 18; private DirectByteBuffer buffer = null; private String description = null; private final byte version; private final PeerItem[] peers_added; private final PeerItem[] peersAddedNoSeeds; private final PeerItem[] peers_dropped; public UTPeerExchange(PeerItem[] _peers_added, PeerItem[] _peers_dropped, PeerItem[] peersAddedNoSeeds, byte version ) { this.peers_added = _peers_added; this.peers_dropped = _peers_dropped; this.version = version; this.peersAddedNoSeeds = peersAddedNoSeeds != null ? peersAddedNoSeeds : _peers_added; } private void insertPeers(String key_name, Map root_map, boolean include_flags, PeerItem[] peers) { if (peers == null) {return;} if (peers.length == 0) {return;} List v4_peers = null; List v6_peers = null; for (int i=0; i " + serialised_peer.length + ":" + peer_byte_size);} System.arraycopy(serialised_peer, 0, raw_peers, i * peer_byte_size, peer_byte_size); if (peer_flags != null && NetworkManager.getCryptoRequired(peer.getCryptoLevel())) { peer_flags[i] |= 0x01; // Encrypted connection. } // 0x02 indicates if the peer is a seed, but that's difficult to determine // so we'll leave it. } // end for root_map.put(key_name, raw_peers); if (peer_flags != null) { root_map.put(key_name + ".f", peer_flags); } } private List extractPeers(String key_name, Map root_map, int peer_byte_size, boolean noSeeds) { ArrayList peers = new ArrayList(); byte[] raw_peer_data = (byte[])root_map.get(key_name); if( raw_peer_data != null ) { if (raw_peer_data.length % peer_byte_size != 0) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "PEX (UT): peer data size not multiple of " + peer_byte_size + ": " + raw_peer_data.length)); } int peer_num = raw_peer_data.length / peer_byte_size; byte[] flags = null; if (root_map != null) { Object flags_obj = root_map.get(key_name + ".f"); // For some reason, some peers send flags as longs. I haven't seen // it myself, so I don't know how to extract data from it. So we'll // just stick to byte arrays. if (flags_obj instanceof byte[]) {flags = (byte[])flags_obj;} } if (flags != null && flags.length != peer_num) { if (flags.length > 0) { if (Logger.isEnabled()) { Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "PEX (UT): invalid peer flags: peers=" + peer_num + ", flags=" + flags.length )); } } flags = null; } for (int i=0; i entension_handlers = new HashMap(); public LTMessageDecoder() {} protected Message createMessage(DirectByteBuffer ref_buff) throws MessageException { // Check to see if it is a LT-extension message. If not, delegate to BTMessageDecoder. int old_position = ref_buff.position(DirectByteBuffer.SS_MSG); byte id = ref_buff.get(DirectByteBuffer.SS_MSG); if (id != 20) { ref_buff.position(DirectByteBuffer.SS_MSG, old_position); return super.createMessage(ref_buff); } // Here is where we decode the message. id = ref_buff.get(DirectByteBuffer.SS_MSG); switch(id) { case 0: return MessageManager.getSingleton().createMessage(LTMessage.ID_LT_HANDSHAKE_BYTES, ref_buff, (byte)1); case 1: return MessageManager.getSingleton().createMessage(LTMessage.ID_UT_PEX_BYTES, ref_buff, (byte)1); default: { byte[] message_id; synchronized( entension_handlers ){ message_id = entension_handlers.get( id ); } if ( message_id != null ){ return MessageManager.getSingleton().createMessage( message_id, ref_buff, (byte)1); } System.out.println( "Unknown LTEP message id [" +id+ "]" ); throw new MessageException( "Unknown LTEP message id [" +id+ "]" ); } } } public void addExtensionHandler( byte id, byte[] message_id ) { synchronized( entension_handlers ){ entension_handlers.put( id, message_id ); } } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageFactory.javaazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageFactory.java0000644000175000017500000000333111007130216033105 0ustar adrianadrian/* * Created on 17 Sep 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent.ltep; import com.aelitis.azureus.core.peermanager.messaging.MessageException; import com.aelitis.azureus.core.peermanager.messaging.MessageManager; /** * @author Allan Crooks * */ public class LTMessageFactory { public static final byte MESSAGE_VERSION_INITIAL = 1; public static final byte MESSAGE_VERSION_SUPPORTS_PADDING = 2; // most of these messages are also used by AZ code public static void init() { try { MessageManager.getSingleton().registerMessageType(new LTHandshake(null, MESSAGE_VERSION_SUPPORTS_PADDING)); MessageManager.getSingleton().registerMessageType(new UTPeerExchange(null, null, null, MESSAGE_VERSION_SUPPORTS_PADDING)); } catch( MessageException me ) { me.printStackTrace(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTUnchoke.java0000644000175000017500000000447410572775040030640 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; /** * BitTorrent unchoke message. */ public class BTUnchoke implements BTMessage { private final byte version; public BTUnchoke(byte _version) { version = _version; } public String getID() { return BTMessage.ID_BT_UNCHOKE; } public byte[] getIDBytes() { return BTMessage.ID_BT_UNCHOKE_BYTES; } public String getFeatureID() { return BTMessage.BT_FEATURE_ID; } public int getFeatureSubID() { return BTMessage.SUBID_BT_UNCHOKE; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { return BTMessage.ID_BT_UNCHOKE; } public DirectByteBuffer[] getData() { return new DirectByteBuffer[] {}; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { if( data != null && data.hasRemaining( DirectByteBuffer.SS_MSG ) ) { throw new MessageException( "[" +getID() +"] decode error: payload not empty" ); } if( data != null ) data.returnToPool(); return new BTUnchoke( version ); } public void destroy() { /*nothing*/ } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessage.java0000644000175000017500000000745310743534366030634 0ustar adrianadrian/* * Created on Jul 17, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import com.aelitis.azureus.core.peermanager.messaging.Message; /** * A bittorrent peer protocol message. */ public interface BTMessage extends Message { public static final String BT_FEATURE_ID = "BT1"; public static final String ID_BT_CHOKE = "BT_CHOKE"; public static final byte[] ID_BT_CHOKE_BYTES = ID_BT_CHOKE.getBytes(); public static final int SUBID_BT_CHOKE = 0; public static final String ID_BT_UNCHOKE = "BT_UNCHOKE"; public static final byte[] ID_BT_UNCHOKE_BYTES = ID_BT_UNCHOKE.getBytes(); public static final int SUBID_BT_UNCHOKE = 1; public static final String ID_BT_INTERESTED = "BT_INTERESTED"; public static final byte[] ID_BT_INTERESTED_BYTES = ID_BT_INTERESTED.getBytes(); public static final int SUBID_BT_INTERESTED = 2; public static final String ID_BT_UNINTERESTED = "BT_UNINTERESTED"; public static final byte[] ID_BT_UNINTERESTED_BYTES = ID_BT_UNINTERESTED.getBytes(); public static final int SUBID_BT_UNINTERESTED = 3; public static final String ID_BT_HAVE = "BT_HAVE"; public static final byte[] ID_BT_HAVE_BYTES = ID_BT_HAVE.getBytes(); public static final int SUBID_BT_HAVE = 4; public static final String ID_BT_BITFIELD = "BT_BITFIELD"; public static final byte[] ID_BT_BITFIELD_BYTES = ID_BT_BITFIELD.getBytes(); public static final int SUBID_BT_BITFIELD = 5; public static final String ID_BT_REQUEST = "BT_REQUEST"; public static final byte[] ID_BT_REQUEST_BYTES = ID_BT_REQUEST.getBytes(); public static final int SUBID_BT_REQUEST = 6; public static final String ID_BT_PIECE = "BT_PIECE"; public static final byte[] ID_BT_PIECE_BYTES = ID_BT_PIECE.getBytes(); public static final int SUBID_BT_PIECE = 7; public static final String ID_BT_CANCEL = "BT_CANCEL"; public static final byte[] ID_BT_CANCEL_BYTES = ID_BT_CANCEL.getBytes(); public static final int SUBID_BT_CANCEL = 8; public static final String ID_BT_DHT_PORT = "BT_DHT_PORT"; public static final byte[] ID_BT_DHT_PORT_BYTES = ID_BT_DHT_PORT.getBytes(); public static final int SUBID_BT_DHT_PORT = 9; public static final String ID_BT_HANDSHAKE = "BT_HANDSHAKE"; public static final byte[] ID_BT_HANDSHAKE_BYTES = ID_BT_HANDSHAKE.getBytes(); public static final int SUBID_BT_HANDSHAKE = 10; public static final String ID_BT_KEEP_ALIVE = "BT_KEEP_ALIVE"; public static final byte[] ID_BT_KEEP_ALIVE_BYTES = ID_BT_KEEP_ALIVE.getBytes(); public static final int SUBID_BT_KEEP_ALIVE = 11; public static final String ID_BT_LT_EXT_MESSAGE = "BT_LT_EXT_MESSAGE"; public static final byte[] ID_BT_LT_EXT_MESSAGE_BYTES = ID_BT_LT_EXT_MESSAGE.getBytes(); public static final int SUBID_BT_LT_EXT_MESSAGE = 20; } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTInterested.java0000644000175000017500000000451110572775040031342 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; /** * BitTorrent interested message. */ public class BTInterested implements BTMessage { private byte version; public BTInterested(byte _version) { version = _version; } public String getID() { return BTMessage.ID_BT_INTERESTED; } public byte[] getIDBytes() { return BTMessage.ID_BT_INTERESTED_BYTES; } public String getFeatureID() { return BTMessage.BT_FEATURE_ID; } public int getFeatureSubID() { return BTMessage.SUBID_BT_INTERESTED; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { return BTMessage.ID_BT_INTERESTED; } public DirectByteBuffer[] getData() { return new DirectByteBuffer[] {}; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { if( data != null && data.hasRemaining( DirectByteBuffer.SS_MSG ) ) { throw new MessageException( "[" +getID() +"] decode error: payload not empty" ); } if( data != null ) data.returnToPool(); return new BTInterested(version); } public void destroy() { /*nothing*/ } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTPiece.java0000644000175000017500000000771310572775040030270 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.bittorrent; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; /** * BitTorrent piece message. */ public class BTPiece implements BTMessage { private byte version; private final DirectByteBuffer[] buffer = new DirectByteBuffer[ 2 ]; private String description; private final int piece_number; private final int piece_offset; private final int piece_length; public BTPiece( int piece_number, int piece_offset, DirectByteBuffer data, byte version ) { this.piece_number = piece_number; this.piece_offset = piece_offset; this.piece_length = data == null ? 0 : data.remaining( DirectByteBuffer.SS_MSG ); buffer[1] = data; this.version = version; } public int getPieceNumber() { return piece_number; } public int getPieceOffset() { return piece_offset; } public DirectByteBuffer getPieceData() { return buffer[1]; } public String getID() { return BTMessage.ID_BT_PIECE; } public byte[] getIDBytes() { return BTMessage.ID_BT_PIECE_BYTES; } public String getFeatureID() { return BTMessage.BT_FEATURE_ID; } public int getFeatureSubID() { return BTMessage.SUBID_BT_PIECE; } public int getType() { return Message.TYPE_DATA_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { if( description == null ) { description = BTMessage.ID_BT_PIECE + " data for piece #" + piece_number + ":" + piece_offset + "->" + (piece_offset + piece_length -1); } return description; } public DirectByteBuffer[] getData() { if( buffer[0] == null ) { buffer[0] = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_PIECE, 8 ); buffer[0].putInt( DirectByteBuffer.SS_MSG, piece_number ); buffer[0].putInt( DirectByteBuffer.SS_MSG, piece_offset ); buffer[0].flip( DirectByteBuffer.SS_MSG ); } return buffer; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { if( data == null ) { throw new MessageException( "[" +getID() + "] decode error: data == null" ); } if( data.remaining( DirectByteBuffer.SS_MSG ) < 8 ) { throw new MessageException( "[" +getID()+ "] decode error: payload.remaining[" +data.remaining( DirectByteBuffer.SS_MSG )+ "] < 8" ); } int number = data.getInt( DirectByteBuffer.SS_MSG ); if( number < 0 ) { throw new MessageException( "[" +getID() +"] decode error: number < 0" ); } int offset = data.getInt( DirectByteBuffer.SS_MSG ); if( offset < 0 ) { throw new MessageException( "[" +getID() + "] decode error: offset < 0" ); } return new BTPiece( number, offset, data, version ); } public void destroy() { if( buffer[0] != null ) buffer[0].returnToPool(); if( buffer[1] != null ) buffer[1].returnToPool(); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/MessageManager.java0000644000175000017500000001035510735675736027510 0ustar adrianadrian/* * Created on Jan 8, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging; import java.util.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.messaging.azureus.AZMessageFactory; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTMessageFactory; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.ltep.LTMessageFactory; /** * */ public class MessageManager { private static final MessageManager instance = new MessageManager(); private final ByteArrayHashMap message_map = new ByteArrayHashMap(); private final List messages = new ArrayList(); protected AEMonitor this_mon = new AEMonitor( "MessageManager" ); private MessageManager() { /*nothing*/ } public static MessageManager getSingleton() { return instance; } /** * Perform manager initialization. */ public void initialize() { AZMessageFactory.init(); //register AZ message types BTMessageFactory.init(); //register BT message types LTMessageFactory.init(); //register LT message types } /** * Register the given message type with the manager for processing. * @param message instance to use for decoding * @throws MessageException if this message type has already been registered */ public void registerMessageType( Message message ) throws MessageException { try{ this_mon.enter(); byte[] id_bytes = message.getIDBytes(); if( message_map.containsKey( id_bytes ) ) { throw new MessageException( "message type [" +message.getID()+ "] already registered!" ); } message_map.put( id_bytes, message ); messages.add( message ); }finally{ this_mon.exit(); } } /** * Remove registration of given message type from manager. * @param message type to remove */ public void deregisterMessageType( Message message ) { try{ this_mon.enter(); message_map.remove( message.getIDBytes() ); messages.remove( message ); } finally{ this_mon.exit(); } } /** * Construct a new message instance from the given message information. * @param id of message * @param message_data payload * @return decoded/deserialized message * @throws MessageException if message creation failed */ public Message createMessage( byte[] id_bytes, DirectByteBuffer message_data, byte version ) throws MessageException { Message message = (Message)message_map.get( id_bytes ); if( message == null ) { throw new MessageException( "message id[" + new String( id_bytes) + "] not registered" ); } return message.deserialize( message_data, version ); } /** * Lookup a registered message type via id and version. * @param id to look for * @return the default registered message instance if found, otherwise returns null if this message type is not registered */ public Message lookupMessage( String id ) { return (Message)message_map.get( id.getBytes()); } public Message lookupMessage( byte[] id_bytes ) { return (Message)message_map.get( id_bytes ); } /** * Get a list of the registered messages. * @return messages */ public Message[] getRegisteredMessages() { return (Message[])messages.toArray( new Message[messages.size()] ); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/azureus/0000755000175000017500000000000011310377630025436 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStylePeerExchange.java0000644000175000017500000000273510742013156032120 0ustar adrianadrian/* * Created on 18 Sep 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.peermanager.messaging.azureus; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.peerdb.PeerItem; /** * Represents a class which supports AZ style peer exchange (with a list of * added peers and a list of dropped peers). * * @author Allan Crooks */ public interface AZStylePeerExchange extends Message { public PeerItem[] getAddedPeers(); public PeerItem[] getDroppedPeers(); public int getMaxAllowedPeersPerVolley(boolean initial, boolean added); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/azureus/AZGenericMapPayload.java0000644000175000017500000000550410572775036032077 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.azureus; import java.util.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.messaging.*; /** * This is a helper class for creating messages with a Map'd beencode-able payload. */ public class AZGenericMapPayload implements AZMessage { private final byte version; private DirectByteBuffer buffer = null; private final String type_id; private final Map msg_map; /** * Create a new AZ message with the given message type id, with the given bencode-able map payload. * @param message_type of message * @param message payload (to be bencoded) */ public AZGenericMapPayload( String message_type, Map message, byte version ) { this.type_id = message_type; this.msg_map = message; this.version = version; } public String getID() { return type_id; } public byte[] getIDBytes() { return type_id.getBytes(); } public String getFeatureID() { return AZMessage.AZ_FEATURE_ID; } public int getFeatureSubID() { return AZMessage.SUBID_AZ_GENERIC_MAP; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public Map getMapPayload() { return msg_map; } public String getDescription() { return getID(); } public DirectByteBuffer[] getData() { if( buffer == null ) { buffer = MessagingUtil.convertPayloadToBencodedByteStream( msg_map, DirectByteBuffer.AL_MSG ); } return new DirectByteBuffer[]{ buffer }; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { Map payload = MessagingUtil.convertBencodedByteStreamToPayload( data, 1, getID() ); return new AZGenericMapPayload( getID(), payload, version ); } public void destroy() { if( buffer != null ) buffer.returnToPool(); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHandshake.java0000644000175000017500000002467711263750536030451 0ustar adrianadrian/* * Created on Apr 30, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.azureus; import java.net.InetAddress; import java.util.*; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.HashWrapper; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; import com.aelitis.azureus.core.peermanager.messaging.MessagingUtil; /** * AZ handshake message. */ public class AZHandshake implements AZMessage { public static final int HANDSHAKE_TYPE_PLAIN = 0; public static final int HANDSHAKE_TYPE_CRYPTO = 1; private static final byte bss = DirectByteBuffer.SS_MSG; private final byte version; private DirectByteBuffer buffer = null; private String description = null; private final byte[] identity; private final HashWrapper sessionID; private final HashWrapper reconnectID; private final String client; private final String client_version; private final String[] avail_ids; private final byte[] avail_versions; private int tcp_port; private int udp_port; private int udp_non_data_port; private final int handshake_type; private final boolean uploadOnly; private final InetAddress ipv6; public AZHandshake( byte[] peer_identity, HashWrapper sessionID, HashWrapper reconnectID, String _client, String version, int tcp_listen_port, int udp_listen_port, int udp_non_data_listen_port, InetAddress ipv6addr, String[] avail_msg_ids, byte[] avail_msg_versions, int _handshake_type, byte _version, boolean uploadOnly) { this.identity = peer_identity; this.sessionID = sessionID; this.reconnectID = reconnectID; this.client = _client; this.client_version = version; this.avail_ids = avail_msg_ids; this.avail_versions = avail_msg_versions; this.tcp_port = tcp_listen_port; this.udp_port = udp_listen_port; this.udp_non_data_port = udp_non_data_listen_port; this.handshake_type = _handshake_type; this.version = _version; this.uploadOnly = uploadOnly; this.ipv6 = ipv6addr; //verify given port info is ok if( tcp_port < 0 || tcp_port > 65535 ) { Debug.out( "given TCP listen port is invalid: " +tcp_port ); tcp_port = 0; } if( udp_port < 0 || udp_port > 65535 ) { Debug.out( "given UDP listen port is invalid: " +udp_port ); udp_port = 0; } if( udp_non_data_port < 0 || udp_non_data_port > 65535 ) { Debug.out( "given UDP non-data listen port is invalid: " +udp_non_data_port ); udp_non_data_port = 0; } } public byte[] getIdentity() { return identity; } public HashWrapper getRemoteSessionID() { return sessionID; } public HashWrapper getReconnectSessionID() { return reconnectID; } public boolean isUploadOnly() {return uploadOnly;} public String getClient() { return client; } public String getClientVersion() { return client_version; } public String[] getMessageIDs() { return avail_ids; } public byte[] getMessageVersions() { return avail_versions; } public int getTCPListenPort() { return tcp_port; } public int getUDPListenPort() { return udp_port; } public int getUDPNonDataListenPort() { return udp_non_data_port; } public InetAddress getIPv6() { return ipv6; } public int getHandshakeType() { return handshake_type; } public String getID() { return AZMessage.ID_AZ_HANDSHAKE; } public byte[] getIDBytes() { return AZMessage.ID_AZ_HANDSHAKE_BYTES; } public String getFeatureID() { return AZMessage.AZ_FEATURE_ID; } public int getFeatureSubID() { return AZMessage.SUBID_AZ_HANDSHAKE; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { if( description == null ) { String msgs_desc = ""; for( int i=0; i < avail_ids.length; i++ ) { String id = avail_ids[ i ]; byte ver = avail_versions[ i ]; if( id.equals( getID() ) ) continue; //skip ourself msgs_desc += "[" +id+ ":" +ver+ "]"; } description = getID()+ " from [" +ByteFormatter.nicePrint( identity, true )+ ", " + client+ " " +client_version+ ", TCP/UDP ports " +tcp_port+ "/" +udp_port+ "/" + udp_non_data_port + ", handshake " + (getHandshakeType() == HANDSHAKE_TYPE_PLAIN ? "plain" : "crypto") + ", upload_only = " + (isUploadOnly() ? "1" : "0") + (ipv6 != null ? ", ipv6 = "+ipv6.getHostAddress() : "") + (sessionID != null ? ", sessionID: "+sessionID.toBase32String() : "") + (reconnectID != null ? ", reconnect request: "+reconnectID.toBase32String() : "") + "] supports " +msgs_desc; } return description; } public DirectByteBuffer[] getData() { if (buffer == null) { Map payload_map = new HashMap(); //client info payload_map.put("identity", identity); if (sessionID != null) payload_map.put("session", sessionID.getBytes()); if (reconnectID != null) payload_map.put("reconn", reconnectID.getBytes()); payload_map.put("client", client); payload_map.put("version", client_version); payload_map.put("tcp_port", new Long(tcp_port)); payload_map.put("udp_port", new Long(udp_port)); payload_map.put("udp2_port", new Long(udp_non_data_port)); payload_map.put("handshake_type", new Long(handshake_type)); payload_map.put("upload_only", new Long(uploadOnly ? 1L : 0L)); if(ipv6 != null) payload_map.put("ipv6", ipv6.getAddress()); //available message list List message_list = new ArrayList(); for (int i = 0; i < avail_ids.length; i++) { String id = avail_ids[i]; byte ver = avail_versions[i]; if (id.equals(getID())) continue; //skip ourself Map msg = new HashMap(); msg.put("id", id); msg.put("ver", new byte[] { ver }); message_list.add(msg); } payload_map.put("messages", message_list); // random padding if crypto if (handshake_type == AZHandshake.HANDSHAKE_TYPE_CRYPTO) payload_map.put("pad", new byte[(int) (Math.random() * AZMessageFactory.AZ_HANDSHAKE_PAD_MAX)]); buffer = MessagingUtil.convertPayloadToBencodedByteStream(payload_map, DirectByteBuffer.AL_MSG_AZ_HAND); if (buffer.remaining(bss) > 1200) System.out.println("Generated AZHandshake size = " + buffer.remaining(bss) + " bytes"); } return new DirectByteBuffer[] { buffer }; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { Map root = MessagingUtil.convertBencodedByteStreamToPayload( data, 100, getID() ); byte[] id = (byte[])root.get( "identity" ); if( id == null ) throw new MessageException( "id == null" ); if( id.length != 20 ) throw new MessageException( "id.length != 20: " +id.length ); byte[] session = (byte[])root.get("session"); byte[] reconnect = (byte[])root.get("reconn"); byte[] raw_name = (byte[])root.get( "client" ); if( raw_name == null ) throw new MessageException( "raw_name == null" ); String name = new String( raw_name ); byte[] raw_ver = (byte[])root.get( "version" ); if( raw_ver == null ) throw new MessageException( "raw_ver == null" ); String client_version = new String( raw_ver ); Long tcp_lport = (Long)root.get( "tcp_port" ); if( tcp_lport == null ) { //old handshake tcp_lport = new Long( 0 ); } Long udp_lport = (Long)root.get( "udp_port" ); if( udp_lport == null ) { //old handshake udp_lport = new Long( 0 ); } Long udp2_lport = (Long)root.get( "udp2_port" ); if( udp2_lport == null ) { //old handshake udp2_lport = udp_lport; } Long h_type = (Long)root.get( "handshake_type" ); if( h_type == null ) { //only 2307+ send type h_type = new Long( HANDSHAKE_TYPE_PLAIN ); } InetAddress ipv6 = null; if(root.get("ipv6") instanceof byte[]) { try { InetAddress.getByAddress((byte[]) root.get("ipv6")); } catch (Exception e) { } } List raw_msgs = (List) root.get("messages"); if (raw_msgs == null) throw new MessageException("raw_msgs == null"); String[] ids = new String[raw_msgs.size()]; byte[] vers = new byte[raw_msgs.size()]; int pos = 0; for (Iterator i = raw_msgs.iterator(); i.hasNext();) { Map msg = (Map) i.next(); byte[] mid = (byte[]) msg.get("id"); if (mid == null) throw new MessageException("mid == null"); ids[pos] = new String(mid); byte[] ver = (byte[]) msg.get("ver"); if (ver == null) throw new MessageException("ver == null"); if (ver.length != 1) throw new MessageException("ver.length != 1"); vers[pos] = ver[0]; pos++; } Long ulOnly = (Long)root.get("upload_only"); boolean uploadOnly = ulOnly != null && ulOnly.longValue() > 0L ? true : false; return new AZHandshake( id, session == null ? null : new HashWrapper(session),reconnect == null ? null : new HashWrapper(reconnect), name, client_version, tcp_lport.intValue(), udp_lport.intValue(), udp2_lport.intValue(), ipv6 ,ids, vers, h_type.intValue(), version , uploadOnly); } public void destroy() { if( buffer != null ) buffer.returnToPool(); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessage.java0000644000175000017500000000741011062635410030117 0ustar adrianadrian/* * Created on Feb 20, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.azureus; import com.aelitis.azureus.core.peermanager.messaging.Message; /** * A core AZ type peer message. */ public interface AZMessage extends Message { public static final String AZ_FEATURE_ID = "AZ1"; public static final String ID_AZ_HANDSHAKE = "AZ_HANDSHAKE"; public static final byte[] ID_AZ_HANDSHAKE_BYTES = ID_AZ_HANDSHAKE.getBytes(); public static final int SUBID_AZ_HANDSHAKE = 0; public static final String ID_AZ_PEER_EXCHANGE = "AZ_PEER_EXCHANGE"; public static final byte[] ID_AZ_PEER_EXCHANGE_BYTES = ID_AZ_PEER_EXCHANGE.getBytes(); public static final int SUBID_AZ_PEER_EXCHANGE = 1; public static final String ID_AZ_GENERIC_MAP = "AZ_GENERIC_MAP"; public static final byte[] ID_AZ_GENERIC_MAP_BYTES = ID_AZ_GENERIC_MAP.getBytes(); public static final int SUBID_AZ_GENERIC_MAP = 2; public static final String ID_AZ_REQUEST_HINT = "AZ_REQUEST_HINT"; public static final byte[] ID_AZ_REQUEST_HINT_BYTES = ID_AZ_REQUEST_HINT.getBytes(); public static final int SUBID_ID_AZ_REQUEST_HINT = 3; public static final String ID_AZ_HAVE = "AZ_HAVE"; public static final byte[] ID_AZ_HAVE_BYTES = ID_AZ_HAVE.getBytes(); public static final int SUBID_ID_AZ_HAVE = 4; public static final String ID_AZ_BAD_PIECE = "AZ_BAD_PIECE"; public static final byte[] ID_AZ_BAD_PIECE_BYTES = ID_AZ_BAD_PIECE.getBytes(); public static final int SUBID_ID_AZ_BAD_PIECE = 5; //TODO public static final String ID_AZ_SESSION_SYN = "AZ_SESSION_SYN"; public static final byte[] ID_AZ_SESSION_SYN_BYTES = ID_AZ_SESSION_SYN.getBytes(); public static final String ID_AZ_SESSION_ACK = "AZ_SESSION_ACK"; public static final byte[] ID_AZ_SESSION_ACK_BYTES = ID_AZ_SESSION_ACK.getBytes(); public static final String ID_AZ_SESSION_END = "AZ_SESSION_END"; public static final byte[] ID_AZ_SESSION_END_BYTES = ID_AZ_SESSION_END.getBytes(); public static final String ID_AZ_SESSION_BITFIELD = "AZ_SESSION_BITFIELD"; public static final byte[] ID_AZ_SESSION_BITFIELD_BYTES = ID_AZ_SESSION_BITFIELD.getBytes(); public static final String ID_AZ_SESSION_CANCEL = "AZ_SESSION_CANCEL"; public static final byte[] ID_AZ_SESSION_CANCEL_BYTES = ID_AZ_SESSION_CANCEL.getBytes(); public static final String ID_AZ_SESSION_HAVE = "AZ_SESSION_HAVE"; public static final byte[] ID_AZ_SESSION_HAVE_BYTES = ID_AZ_SESSION_HAVE.getBytes(); public static final String ID_AZ_SESSION_PIECE = "AZ_SESSION_PIECE"; public static final byte[] ID_AZ_SESSION_PIECE_BYTES = ID_AZ_SESSION_PIECE.getBytes(); public static final String ID_AZ_SESSION_REQUEST = "AZ_SESSION_REQUEST"; public static final byte[] ID_AZ_SESSION_REQUEST_BYTES = ID_AZ_SESSION_REQUEST.getBytes(); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/azureus/AZBadPiece.java0000644000175000017500000000561510647525062030205 0ustar adrianadrian/* * Created on Jan 19, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.azureus; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; import com.aelitis.azureus.core.peermanager.messaging.MessagingUtil; public class AZBadPiece implements AZMessage { private final byte version; private DirectByteBuffer buffer = null; private int piece_number; public AZBadPiece( int _piece_number, byte _version ) { piece_number = _piece_number; version = _version; } public String getID() { return( AZMessage.ID_AZ_BAD_PIECE ); } public byte[] getIDBytes() { return( AZMessage.ID_AZ_BAD_PIECE_BYTES ); } public String getFeatureID() { return( AZMessage.AZ_FEATURE_ID ); } public int getFeatureSubID() { return( AZMessage.SUBID_ID_AZ_BAD_PIECE ); } public int getType() { return( Message.TYPE_PROTOCOL_PAYLOAD ); } public byte getVersion() { return version; }; public String getDescription() { return( getID() + " " + piece_number ); } public int getPieceNumber() { return( piece_number ); } public DirectByteBuffer[] getData() { if ( buffer == null ){ Map map = new HashMap(); map.put( "piece", new Long( piece_number )); buffer = MessagingUtil.convertPayloadToBencodedByteStream( map, DirectByteBuffer.AL_MSG ); } return new DirectByteBuffer[]{ buffer }; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { Map payload = MessagingUtil.convertBencodedByteStreamToPayload( data, 1, getID() ); int piece_number = ((Long)payload.get( "piece")).intValue(); AZBadPiece message = new AZBadPiece( piece_number, version ); return( message ); } public void destroy() { if ( buffer != null ){ buffer.returnToPool(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageFactory.java0000644000175000017500000002567311257512376031475 0ustar adrianadrian/* * Created on Feb 19, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.azureus; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.DirectByteBufferPool; import com.aelitis.azureus.core.networkmanager.RawMessage; import com.aelitis.azureus.core.networkmanager.impl.RawMessageImpl; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; import com.aelitis.azureus.core.peermanager.messaging.MessageManager; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.*; /** * Factory for handling AZ message creation. * NOTE: wire format: [total message length] + [id length] + [id bytes] + [version byte] + [payload bytes] */ public class AZMessageFactory { public static final byte MESSAGE_VERSION_INITIAL = BTMessageFactory.MESSAGE_VERSION_INITIAL; public static final byte MESSAGE_VERSION_SUPPORTS_PADDING = BTMessageFactory.MESSAGE_VERSION_SUPPORTS_PADDING; public static final int AZ_HANDSHAKE_PAD_MAX = 64; public static final int SMALL_PAD_MAX = 8; public static final int BIG_PAD_MAX = 20; private static final byte bss = DirectByteBuffer.SS_MSG; private static final Map legacy_data = new HashMap(); static { legacy_data.put( BTMessage.ID_BT_CHOKE, new LegacyData( RawMessage.PRIORITY_HIGH, true, new Message[]{new BTUnchoke((byte)0), new BTPiece(-1, -1, null,(byte)0 )} ) ); legacy_data.put( BTMessage.ID_BT_UNCHOKE, new LegacyData( RawMessage.PRIORITY_NORMAL, true, new Message[]{new BTChoke((byte)0)} ) ); legacy_data.put( BTMessage.ID_BT_INTERESTED, new LegacyData( RawMessage.PRIORITY_HIGH, true, new Message[]{new BTUninterested((byte)0)} ) ); legacy_data.put( BTMessage.ID_BT_UNINTERESTED, new LegacyData( RawMessage.PRIORITY_NORMAL, false, new Message[]{new BTInterested((byte)0)} ) ); legacy_data.put( BTMessage.ID_BT_HAVE, new LegacyData( RawMessage.PRIORITY_LOW, false, null ) ); legacy_data.put( BTMessage.ID_BT_BITFIELD, new LegacyData( RawMessage.PRIORITY_HIGH, true, null ) ); legacy_data.put( BTMessage.ID_BT_REQUEST, new LegacyData( RawMessage.PRIORITY_NORMAL, true, null ) ); legacy_data.put( BTMessage.ID_BT_PIECE, new LegacyData( RawMessage.PRIORITY_LOW, false, null ) ); legacy_data.put( BTMessage.ID_BT_CANCEL, new LegacyData( RawMessage.PRIORITY_HIGH, true, null ) ); legacy_data.put( BTMessage.ID_BT_HANDSHAKE, new LegacyData( RawMessage.PRIORITY_HIGH, true, null ) ); legacy_data.put( BTMessage.ID_BT_KEEP_ALIVE, new LegacyData( RawMessage.PRIORITY_LOW, false, null ) ); legacy_data.put( BTMessage.ID_BT_DHT_PORT, new LegacyData( RawMessage.PRIORITY_LOW, false, null ) ); } /** * Initialize the factory, i.e. register the messages with the message manager. */ public static void init() { try { MessageManager.getSingleton().registerMessageType( new AZHandshake( new byte[20], null, null, "", "", 0, 0, 0, null, new String[0], new byte[0], 0, MESSAGE_VERSION_SUPPORTS_PADDING,false ) ); MessageManager.getSingleton().registerMessageType( new AZPeerExchange( new byte[20], null, null, MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new AZRequestHint( -1, -1, -1, -1, MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new AZHave( new int[0], MESSAGE_VERSION_SUPPORTS_PADDING )); MessageManager.getSingleton().registerMessageType( new AZBadPiece( -1, MESSAGE_VERSION_SUPPORTS_PADDING )); /* MessageManager.getSingleton().registerMessageType( new AZSessionSyn( new byte[20], -1, null) ); MessageManager.getSingleton().registerMessageType( new AZSessionAck( new byte[20], -1, null) ); MessageManager.getSingleton().registerMessageType( new AZSessionEnd( new byte[20], "" ) ); MessageManager.getSingleton().registerMessageType( new AZSessionBitfield( -1, null ) ); MessageManager.getSingleton().registerMessageType( new AZSessionCancel( -1, -1, -1, -1 ) ); MessageManager.getSingleton().registerMessageType( new AZSessionHave( -1, new int[]{-1} ) ); MessageManager.getSingleton().registerMessageType( new AZSessionPiece( -1, -1, -1, null ) ); MessageManager.getSingleton().registerMessageType( new AZSessionRequest( -1, (byte)-1, -1, -1, -1 ) ); */ } catch( MessageException me ) { me.printStackTrace(); } } /** * Register a generic map payload type with the factory. * @param type_id to register * @throws MessageException on registration error */ public static void registerGenericMapPayloadMessageType( String type_id ) throws MessageException { MessageManager.getSingleton().registerMessageType( new AZGenericMapPayload( type_id, null, MESSAGE_VERSION_INITIAL ) ); } /** * Construct a new AZ message instance from the given message raw byte stream. * @param stream_payload data * @return decoded/deserialized AZ message * @throws MessageException if message creation failed. * NOTE: Does not auto-return to buffer pool the given direct buffer on thrown exception. */ public static Message createAZMessage( DirectByteBuffer stream_payload ) throws MessageException { int id_length = stream_payload.getInt( bss ); if( id_length < 1 || id_length > 1024 || id_length > stream_payload.remaining( bss ) - 1 ) { byte bt_id = stream_payload.get( (byte)0, 0 ); throw new MessageException( "invalid AZ id length given: " +id_length+ ", stream_payload.remaining(): " +stream_payload.remaining( bss )+ ", BT id?=" +bt_id ); } byte[] id_bytes = new byte[ id_length ]; stream_payload.get( bss, id_bytes ); // if only the version came first we could save a lot of space by changing the id length + id.... // in the meantime we overload the version byte to have a version number and flags // flags = top 4 bits, version = bottom 4 bits byte version_and_flags = stream_payload.get( bss ); byte version = (byte)( version_and_flags & 0x0f ); if ( version >= MESSAGE_VERSION_SUPPORTS_PADDING ){ byte flags = (byte)(( version_and_flags >> 4 ) & 0x0f ); if ( ( flags & 0x01 ) != 0 ){ short padding_length = stream_payload.getShort( bss ); byte[] padding = new byte[padding_length]; stream_payload.get( bss, padding ); } } return MessageManager.getSingleton().createMessage( id_bytes, stream_payload, version ); } /** * Create the proper AZ raw message from the given base message. * @param base_message to create from * @return AZ raw message */ public static RawMessage createAZRawMessage( Message base_message, boolean enable_padding ) { byte[] id_bytes = base_message.getIDBytes(); byte version = base_message.getVersion(); DirectByteBuffer[] payload = base_message.getData(); int payload_size = 0; for( int i=0; i < payload.length; i++ ) { payload_size += payload[i].remaining( bss ); } //create and fill header buffer DirectByteBuffer header; if ( version >= MESSAGE_VERSION_SUPPORTS_PADDING ){ short padding_length = enable_padding?(short)(( Math.random() * ( payload_size>256?SMALL_PAD_MAX:BIG_PAD_MAX ))+1):0; byte flags = enable_padding?(byte)0x01:(byte)0x00; int header_size = 4 + 4 + id_bytes.length + 1 + (enable_padding?(2+padding_length):0); header = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_AZ_HEADER, header_size ); header.putInt( bss, header_size - 4 + payload_size ); header.putInt( bss, id_bytes.length ); header.put( bss, id_bytes ); byte version_and_flags = (byte)( ( flags << 4 ) | version ); header.put( bss, version_and_flags ); if ( enable_padding ){ byte[] padding = new byte[padding_length]; header.putShort( bss, padding_length ); header.put( bss, padding ); } }else{ int header_size = 4 + 4 + id_bytes.length + 1; header = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_AZ_HEADER, header_size ); header.putInt( bss, header_size - 4 + payload_size ); header.putInt( bss, id_bytes.length ); header.put( bss, id_bytes ); header.put( bss, version ); } header.flip( bss ); DirectByteBuffer[] raw_buffs = new DirectByteBuffer[ payload.length + 1 ]; raw_buffs[0] = header; for( int i=0; i < payload.length; i++ ) { raw_buffs[i+1] = payload[i]; } String message_id = base_message.getID(); LegacyData ld = (LegacyData)legacy_data.get( message_id ); //determine if a legacy BT message if( ld != null ) { //legacy message, use pre-configured values return new RawMessageImpl( base_message, raw_buffs, ld.priority, ld.is_no_delay, ld.to_remove ); } // these should really be properties of the message... int priority; boolean no_delay = true; if ( message_id == AZMessage.ID_AZ_HANDSHAKE ){ // handshake needs to go out first - if not high then bitfield can get in front of it... priority = RawMessage.PRIORITY_HIGH; }else if ( message_id == AZMessage.ID_AZ_HAVE ){ priority = RawMessage.PRIORITY_LOW; no_delay = false; }else{ //standard message, ensure that protocol messages have wire priority over data payload messages priority = base_message.getType() == Message.TYPE_DATA_PAYLOAD ? RawMessage.PRIORITY_LOW : RawMessage.PRIORITY_NORMAL; } return new RawMessageImpl( base_message, raw_buffs, priority, no_delay, null ); } protected static class LegacyData { protected final int priority; protected final boolean is_no_delay; protected final Message[] to_remove; protected LegacyData( int prio, boolean no_delay, Message[] remove ) { this.priority = prio; this.is_no_delay = no_delay; this.to_remove = remove; } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/azureus/AZRequestHint.java0000644000175000017500000000707410572775036031032 0ustar adrianadrian/* * Created on Jan 19, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.azureus; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; import com.aelitis.azureus.core.peermanager.messaging.MessagingUtil; public class AZRequestHint implements AZMessage { private final byte version; private DirectByteBuffer buffer = null; private int piece_number; private int offset; private int length; private int life; public AZRequestHint( int _piece_number, int _offset, int _length, int _life, byte _version ) { piece_number = _piece_number; offset = _offset; length = _length; life = _life; version = _version; } public String getID() { return( AZMessage.ID_AZ_REQUEST_HINT ); } public byte[] getIDBytes() { return( AZMessage.ID_AZ_REQUEST_HINT_BYTES ); } public String getFeatureID() { return( AZMessage.AZ_FEATURE_ID ); } public int getFeatureSubID() { return( AZMessage.SUBID_ID_AZ_REQUEST_HINT ); } public int getType() { return( Message.TYPE_PROTOCOL_PAYLOAD ); } public byte getVersion() { return version; }; public String getDescription() { return( getID() + " piece #" + piece_number + ":" + offset + "->" + (offset + length -1) + "/" + life ); } public int getPieceNumber() { return( piece_number ); } public int getOffset() { return( offset ); } public int getLength() { return( length ); } public int getLife() { return( life ); } public DirectByteBuffer[] getData() { if ( buffer == null ){ Map map = new HashMap(); map.put( "piece", new Long( piece_number )); map.put( "offset", new Long( offset )); map.put( "length", new Long( length )); map.put( "life", new Long( life )); buffer = MessagingUtil.convertPayloadToBencodedByteStream( map, DirectByteBuffer.AL_MSG ); } return new DirectByteBuffer[]{ buffer }; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { Map payload = MessagingUtil.convertBencodedByteStreamToPayload( data, 1, getID() ); int piece_number = ((Long)payload.get( "piece")).intValue(); int offset = ((Long)payload.get( "offset")).intValue(); int length = ((Long)payload.get( "length")).intValue(); int life = ((Long)payload.get( "life" )).intValue(); return( new AZRequestHint( piece_number, offset, length, life, version )); } public void destroy() { if ( buffer != null ){ buffer.returnToPool(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHave.java0000644000175000017500000000652410640124260027420 0ustar adrianadrian/* * Created on Jan 19, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.azureus; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; import com.aelitis.azureus.core.peermanager.messaging.MessagingUtil; public class AZHave implements AZMessage { private final byte version; private DirectByteBuffer buffer = null; private int[] piece_numbers; public AZHave( int[] _piece_numbers, byte _version ) { piece_numbers = _piece_numbers; version = _version; } public String getID() { return( AZMessage.ID_AZ_HAVE ); } public byte[] getIDBytes() { return( AZMessage.ID_AZ_HAVE_BYTES ); } public String getFeatureID() { return( AZMessage.AZ_FEATURE_ID ); } public int getFeatureSubID() { return( AZMessage.SUBID_ID_AZ_HAVE ); } public int getType() { return( Message.TYPE_PROTOCOL_PAYLOAD ); } public byte getVersion() { return version; }; public String getDescription() { StringBuffer str = new StringBuffer(piece_numbers.length*10); for (int i=0;i 0 ){ str.append(","); } str.append( piece_numbers[i] ); } return( getID() + " " + str ); } public int[] getPieceNumbers() { return( piece_numbers ); } public DirectByteBuffer[] getData() { if ( buffer == null ){ Map map = new HashMap(); List l = new ArrayList( piece_numbers.length ); for (int i=0;i 0 ) { ArrayList raw_peers = new ArrayList(); byte[] handshake_types = new byte[ peers.length ]; byte[] udp_ports = new byte[peers.length*2]; // 2403 B55+ int num_valid_udp = 0; for( int i=0; i < peers.length; i++ ) { raw_peers.add( peers[i].getSerialization() ); handshake_types[i] = (byte)peers[i].getHandshakeType(); int udp_port = peers[i].getUDPPort(); if ( udp_port > 0 ){ num_valid_udp++; udp_ports[i*2] = (byte)(udp_port>>8); udp_ports[i*2+1] = (byte)udp_port; } } root_map.put( key_name, raw_peers ); root_map.put( key_name + "_HST", handshake_types ); if ( num_valid_udp > 0 ){ root_map.put( key_name + "_UDP", udp_ports ); } } } private PeerItem[] extractPeers( String key_name, Map root_map ) { PeerItem[] return_peers = null; ArrayList peers = new ArrayList(); List raw_peers = (List)root_map.get( key_name ); if( raw_peers != null ) { int peer_num = raw_peers.size(); byte[] handshake_types = (byte[])root_map.get( key_name + "_HST" ); byte[] udp_ports = (byte[])root_map.get( key_name + "_UDP" ); // 2403 B55+ int pos = 0; if ( handshake_types != null && handshake_types.length != peer_num ){ Logger.log(new LogEvent( LOGID, LogEvent.LT_WARNING,"PEX: invalid handshake types received: peers=" + peer_num + ",handshakes=" + handshake_types.length )); handshake_types = null; } if ( udp_ports != null && udp_ports.length != peer_num*2 ){ Logger.log(new LogEvent( LOGID, LogEvent.LT_WARNING,"PEX: invalid udp ports received: peers=" + peer_num + ",udp_ports=" + udp_ports.length )); udp_ports = null; } for( Iterator it = raw_peers.iterator(); it.hasNext(); ) { byte[] full_address = (byte[])it.next(); byte type = PeerItemFactory.HANDSHAKE_TYPE_PLAIN; if( handshake_types != null ) { //only 2307+ send types type = handshake_types[pos]; } int udp_port = 0; if ( udp_ports != null ){ udp_port = ((udp_ports[pos*2]<<8)&0xff00) + (udp_ports[pos*2+1]&0xff); } try{ PeerItem peer = PeerItemFactory.createPeerItem( full_address, PeerItemFactory.PEER_SOURCE_PEER_EXCHANGE, type, udp_port ); peers.add( peer ); }catch( Exception t ){ Logger.log(new LogEvent( LOGID, LogEvent.LT_WARNING,"PEX: invalid peer received" )); } pos++; } } if( !peers.isEmpty() ) { return_peers = new PeerItem[ peers.size() ]; peers.toArray( return_peers ); } return return_peers; } public byte[] getInfoHash() { return infohash; } public PeerItem[] getAddedPeers() { return peers_added; } public PeerItem[] getDroppedPeers() { return peers_dropped; } public String getID() { return AZMessage.ID_AZ_PEER_EXCHANGE; } public byte[] getIDBytes() { return AZMessage.ID_AZ_PEER_EXCHANGE_BYTES; } public String getFeatureID() { return AZMessage.AZ_FEATURE_ID; } public int getFeatureSubID() { return AZMessage.SUBID_AZ_PEER_EXCHANGE; } public int getType() { return Message.TYPE_PROTOCOL_PAYLOAD; } public byte getVersion() { return version; }; public String getDescription() { if( description == null ) { int add_count = peers_added == null ? 0 : peers_added.length; int drop_count = peers_dropped == null ? 0 : peers_dropped.length; description = getID()+ " for infohash " +ByteFormatter.nicePrint( infohash, true )+ " with " +add_count+ " added and " +drop_count+ " dropped peers"; } return description; } public DirectByteBuffer[] getData() { if( buffer == null ) { Map payload_map = new HashMap(); payload_map.put( "infohash", infohash ); insertPeers( "added", payload_map, peers_added ); insertPeers( "dropped", payload_map, peers_dropped ); buffer = MessagingUtil.convertPayloadToBencodedByteStream( payload_map, DirectByteBuffer.AL_MSG_AZ_PEX ); if( buffer.remaining( bss ) > 2000 ) System.out.println( "Generated AZPeerExchange size = " +buffer.remaining( bss )+ " bytes" ); } return new DirectByteBuffer[]{ buffer }; } public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { if( data.remaining( bss ) > 2000 ) System.out.println( "Received PEX msg byte size = " +data.remaining( bss ) ); Map root = MessagingUtil.convertBencodedByteStreamToPayload( data, 10, getID() ); byte[] hash = (byte[])root.get( "infohash" ); if( hash == null ) throw new MessageException( "hash == null" ); if( hash.length != 20 ) throw new MessageException( "hash.length != 20: " +hash.length ); PeerItem[] added = extractPeers( "added", root ); PeerItem[] dropped = extractPeers( "dropped", root ); if( added == null && dropped == null ) throw new MessageException( "[" +getID()+ "] received exchange message without any adds or drops" ); return new AZPeerExchange( hash, added, dropped, version ); } public void destroy() { if( buffer != null ) buffer.returnToPool(); } public int getMaxAllowedPeersPerVolley(boolean initial, boolean added) { return PeerExchangerItem.MAX_PEERS_PER_VOLLEY; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageEncoder.java0000644000175000017500000000276410573172256031440 0ustar adrianadrian/* * Created on Feb 8, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.azureus; import com.aelitis.azureus.core.networkmanager.RawMessage; import com.aelitis.azureus.core.peermanager.messaging.*; /** * * */ public class AZMessageEncoder implements MessageStreamEncoder { private boolean enable_padding; public AZMessageEncoder( boolean _enable_padding ) { enable_padding = _enable_padding; } public RawMessage[] encodeMessage( Message message ) { return new RawMessage[]{ AZMessageFactory.createAZRawMessage( message, enable_padding )}; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageDecoder.java0000644000175000017500000002746110734656570031434 0ustar adrianadrian/* * Created on Feb 8, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging.azureus; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.Transport; import com.aelitis.azureus.core.peermanager.messaging.*; /** * Length-prefixed message decoding. */ public class AZMessageDecoder implements MessageStreamDecoder { private static final int MIN_MESSAGE_LENGTH = 6; //4 byte id length + at least 1 byte for id + 1 byte version private static final int MAX_MESSAGE_LENGTH = 131072; //128K arbitrary limit private static final byte SS = DirectByteBuffer.SS_MSG; private DirectByteBuffer payload_buffer = null; private final DirectByteBuffer length_buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG, 4 ); private final ByteBuffer[] decode_array = new ByteBuffer[] { null, length_buffer.getBuffer( SS ) }; private boolean reading_length_mode = true; private int message_length; private int pre_read_start_buffer; private int pre_read_start_position; private volatile boolean destroyed = false; private volatile boolean is_paused = false; private ArrayList messages_last_read = new ArrayList(); private int protocol_bytes_last_read = 0; private int data_bytes_last_read = 0; private int percent_complete = -1; private byte[] msg_id_bytes = null; private boolean msg_id_read_complete = false; private boolean last_read_made_progress; private int maximum_message_size = MAX_MESSAGE_LENGTH; public AZMessageDecoder() { /*nothing*/ } public void setMaximumMessageSize( int max_bytes ) { maximum_message_size = max_bytes; } public int performStreamDecode( Transport transport, int max_bytes ) throws IOException { protocol_bytes_last_read = 0; data_bytes_last_read = 0; int bytes_remaining = max_bytes; while( bytes_remaining > 0 ) { if( destroyed ) { //destruction currently isn't thread safe so one thread can destroy the decoder (e.g. when closing a connection) //while the read-controller is still actively processing the us //Debug.out( "AZ decoder already destroyed: " +transport.getDescription() ); break; } if( is_paused ) { Debug.out( "AZ decoder paused" ); break; } int bytes_possible = preReadProcess( bytes_remaining ); if( bytes_possible < 1 ) { Debug.out( "ERROR AZ: bytes_possible < 1" ); break; } long actual_read; if( reading_length_mode ) { actual_read = transport.read( decode_array, 1, 1 ); //only read into length buffer } else { actual_read = transport.read( decode_array, 0, 2 ); //read payload buffer, and possibly next message length buffer } last_read_made_progress = actual_read > 0; int bytes_read = postReadProcess(); bytes_remaining -= bytes_read; if( bytes_read < bytes_possible ) { break; } } return max_bytes - bytes_remaining; } public int getPercentDoneOfCurrentMessage() { return percent_complete; } public Message[] removeDecodedMessages() { if( messages_last_read.isEmpty() ) return null; Message[] msgs = (Message[])messages_last_read.toArray( new Message[messages_last_read.size()] ); messages_last_read.clear(); return msgs; } public int getProtocolBytesDecoded() { return protocol_bytes_last_read; } public int getDataBytesDecoded() { return data_bytes_last_read; } public boolean getLastReadMadeProgress(){ return last_read_made_progress; }; public ByteBuffer destroy() { is_paused = true; destroyed = true; /* int lbuff_read = 0; int pbuff_read = 0; length_buffer.limit( SS, 4 ); if( reading_length_mode ) { lbuff_read = length_buffer.position( SS ); } else { //reading payload length_buffer.position( SS, 4 ); lbuff_read = 4; pbuff_read = payload_buffer == null ? 0 : payload_buffer.position( SS ); } ByteBuffer unused = ByteBuffer.allocate( lbuff_read + pbuff_read ); length_buffer.flip( SS ); unused.put( length_buffer.getBuffer( SS ) ); if ( payload_buffer != null ) { payload_buffer.flip( SS ); unused.put( payload_buffer.getBuffer( SS ) ); } unused.flip(); */ length_buffer.returnToPool(); if( payload_buffer != null ) { payload_buffer.returnToPool(); payload_buffer = null; } try{ for( int i=0; i < messages_last_read.size(); i++ ) { Message msg = (Message)messages_last_read.get( i ); msg.destroy(); } }catch( IndexOutOfBoundsException e ){ // as access to messages_last_read isn't synchronized we can get this error if we destroy the // decoder in parallel with messages being removed. We don't really want to synchronize access // to this so we'll take the hit here } messages_last_read.clear(); //return unused; return null; //NOTE: we don't bother returning any already-read data } private int preReadProcess( int allowed ) { if( allowed < 1 ) { Debug.out( "allowed < 1" ); } decode_array[ 0 ] = payload_buffer == null ? null : payload_buffer.getBuffer( SS ); //ensure the decode array has the latest payload pointer int bytes_available = 0; boolean shrink_remaining_buffers = false; int start_buff = reading_length_mode ? 1 : 0; boolean marked = false; for( int i = start_buff; i < 2; i++ ) { //set buffer limits according to bytes allowed ByteBuffer bb = decode_array[ i ]; if( bb == null ) { Debug.out( "preReadProcess:: bb["+i+"] == null, decoder destroyed=" +destroyed ); } if( shrink_remaining_buffers ) { bb.limit( 0 ); //ensure no read into this next buffer is possible } else { int remaining = bb.remaining(); if( remaining < 1 ) continue; //skip full buffer if( !marked ) { pre_read_start_buffer = i; pre_read_start_position = bb.position(); marked = true; } if( remaining > allowed ) { //read only part of this buffer bb.limit( bb.position() + allowed ); //limit current buffer bytes_available += bb.remaining(); shrink_remaining_buffers = true; //shrink any tail buffers } else { //full buffer is allowed to be read bytes_available += remaining; allowed -= remaining; //count this buffer toward allowed and move on to the next } } } return bytes_available; } private int postReadProcess() throws IOException { int prot_bytes_read = 0; int data_bytes_read = 0; if( !reading_length_mode && !destroyed ) { //reading payload data mode //ensure-restore proper buffer limits payload_buffer.limit( SS, message_length ); length_buffer.limit( SS, 4 ); int curr_position = payload_buffer.position( SS ); int read = curr_position - pre_read_start_position; if( msg_id_bytes == null && curr_position >= 4 ) { //need to have read the message id length first 4 bytes payload_buffer.position( SS, 0 ); int id_size = payload_buffer.getInt( SS ); payload_buffer.position( SS, curr_position ); //restore if( id_size < 1 || id_size > 1024 ) throw new IOException( "invalid id_size [" +id_size+ "]" ); msg_id_bytes = new byte[ id_size ]; } if( msg_id_bytes != null && curr_position >= msg_id_bytes.length + 4 ) { //need to have also read the message id bytes if( !msg_id_read_complete ) { payload_buffer.position( SS, 4 ); payload_buffer.get( SS, msg_id_bytes ); payload_buffer.position( SS, curr_position ); //restore msg_id_read_complete = true; } Message message = MessageManager.getSingleton().lookupMessage( msg_id_bytes ); if ( message == null ){ Debug.out( "Unknown message type '" + new String( msg_id_bytes ) + "'" ); throw( new IOException( "Unknown message type" )); } if( message.getType() == Message.TYPE_DATA_PAYLOAD ) { data_bytes_read += read; }else{ prot_bytes_read += read; } } else { prot_bytes_read += read; } if( !payload_buffer.hasRemaining( SS ) && !is_paused ) { //full message received! payload_buffer.position( SS, 0 ); //prepare for use DirectByteBuffer ref_buff = payload_buffer; payload_buffer = null; try { Message msg = AZMessageFactory.createAZMessage( ref_buff ); messages_last_read.add( msg ); } catch( Throwable e ) { ref_buff.returnToPoolIfNotFree(); // maintain unexpected erorrs as such so they get logged later if ( e instanceof RuntimeException ){ throw((RuntimeException)e ); } throw new IOException( "AZ message decode failed: " + e.getMessage() ); } reading_length_mode = true; //see if we've already read the next message's length percent_complete = -1; //reset receive percentage msg_id_bytes = null; msg_id_read_complete = false; } else { //only partial received so far percent_complete = (payload_buffer.position( SS ) * 100) / message_length; //compute receive percentage } } if( reading_length_mode && !destroyed ) { length_buffer.limit( SS, 4 ); //ensure proper buffer limit prot_bytes_read += (pre_read_start_buffer == 1) ? length_buffer.position( SS ) - pre_read_start_position : length_buffer.position( SS ); if( !length_buffer.hasRemaining( SS ) ) { //done reading the length reading_length_mode = false; length_buffer.position( SS, 0 ); message_length = length_buffer.getInt( SS ); length_buffer.position( SS, 0 ); //reset it for next length read if( message_length < MIN_MESSAGE_LENGTH || message_length > maximum_message_size ) { throw new IOException( "Invalid message length given for AZ message decode: " + message_length + " (max=" + maximum_message_size + ")" ); } payload_buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_AZ_PAYLOAD, message_length ); } } protocol_bytes_last_read += prot_bytes_read; data_bytes_last_read += data_bytes_read; return prot_bytes_read + data_bytes_read; } public void pauseDecoding() { is_paused = true; } public void resumeDecoding() { is_paused = false; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/Message.java0000644000175000017500000000516210572775040026201 0ustar adrianadrian/* * Created on Jan 8, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging; import org.gudy.azureus2.core3.util.DirectByteBuffer; /** * Basic peer message. * A message is uniquely identified by the combination of ID and version. */ public interface Message { /** * Is a protocol-bearing message, i.e. messaging/overhead data. */ public static final int TYPE_PROTOCOL_PAYLOAD = 0; /** * Is a data-bearing message, i.e. file data. */ public static final int TYPE_DATA_PAYLOAD = 1; /** * Get message id. * @return id */ public String getID(); public byte[] getIDBytes(); /** * Get the main feature set name this message belongs to. * @return feature id */ public String getFeatureID(); /** * Get the static message sub-id for the feature. * @return sub id */ public int getFeatureSubID(); public byte getVersion(); /** * Get message type. * @return type */ public int getType(); /** * Get textual description of this particular message. * @return description */ public String getDescription(); /** * Get message payload data. * @return message data buffers */ public DirectByteBuffer[] getData(); /** * Create a new instance of this message by decoding the given byte serialization. * @param data to deserialize * @return decoded message instance * @throws MessageException if the decoding process fails * NOTE: Does not auto-return given direct buffer on thrown exception. */ public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException; /** * Destroy the message; i.e. perform cleanup actions. */ public void destroy(); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/MessageStreamFactory.java0000644000175000017500000000253110373051026030670 0ustar adrianadrian/* * Created on Feb 23, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging; /** * Factory interface for creating stream encoders and decoders. */ public interface MessageStreamFactory { /** * Create message stream encoder. * @return encoder */ public MessageStreamEncoder createEncoder(); /** * Create message stream decoder. * @return decoder */ public MessageStreamDecoder createDecoder(); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/MessageException.java0000644000175000017500000000232311012741354030043 0ustar adrianadrian/* * Created on Jan 8, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging; /** * */ public class MessageException extends Exception { public MessageException( String reason ) { super( reason ); } public MessageException( String reason, Throwable cause) { super(reason, cause); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/messaging/MessageStreamDecoder.java0000644000175000017500000000530610444636734030647 0ustar adrianadrian/* * Created on Jan 25, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.messaging; import java.io.IOException; import java.nio.ByteBuffer; import com.aelitis.azureus.core.networkmanager.Transport; /** * Decodes a message stream into separate messages. */ public interface MessageStreamDecoder { /** * Decode message stream from the given transport. * @param transport to decode from * @param max_bytes to decode/read from the stream * @return number of bytes decoded * @throws IOException on decoding error */ public int performStreamDecode( Transport transport, int max_bytes ) throws IOException; /** * Get the messages decoded from the transport, if any, from the last decode op. * @return decoded messages, or null if no new complete messages were decoded */ public Message[] removeDecodedMessages(); /** * Get the number of protocol (overhead) bytes decoded from the transport, from the last decode op. * @return number of protocol bytes recevied */ public int getProtocolBytesDecoded(); /** * Get the number of (piece) data bytes decoded from the transport, from the last decode op. * @return number of data bytes received */ public int getDataBytesDecoded(); /** * Get the percentage of the current message that has already been received (read from the transport). * @return percentage complete (0-99), or -1 if no message is currently being received */ public int getPercentDoneOfCurrentMessage(); /** * Pause message decoding. */ public void pauseDecoding(); /** * Resume message decoding. */ public void resumeDecoding(); /** * Destroy this decoder, i.e. perform cleanup. * @return any bytes already-read and still remaining within the decoder */ public ByteBuffer destroy(); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/control/0000755000175000017500000000000011310377630023443 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/control/impl/0000755000175000017500000000000011310377630024404 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerImpl.java0000644000175000017500000001166311165063202032166 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.peermanager.control.impl; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.peermanager.control.PeerControlScheduler; import com.aelitis.azureus.core.stats.AzureusCoreStats; import com.aelitis.azureus.core.stats.AzureusCoreStatsProvider; public abstract class PeerControlSchedulerImpl implements PeerControlScheduler, AzureusCoreStatsProvider, ParameterListener { private static final PeerControlSchedulerImpl[] singletons; static{ int num = COConfigurationManager.getIntParameter( "peercontrol.scheduler.parallelism", 1 ); if ( num < 1 ){ num = 1; }else if ( num > 1 ){ if ( COConfigurationManager.getBooleanParameter( "peercontrol.scheduler.use.priorities" )){ Debug.out( "Multiple peer schedulers not supported for prioritised scheduling" ); num = 1; }else{ System.out.println( "Peer control scheduler parallelism=" + num ); } } singletons = new PeerControlSchedulerImpl[ num ]; } protected boolean useWeights = true; { COConfigurationManager.addAndFireParameterListener("Use Request Limiting Priorities", this); } public void parameterChanged(String parameterName) { useWeights = COConfigurationManager.getBooleanParameter("Use Request Limiting Priorities"); } static{ for (int i=0;i currentTime ){ lastTime = currentTime; return; } if ( bucket < 0 ){ Debug.out( "Bucket is more than empty! - " + bucket ); bucket = 0; } long delta = currentTime - lastTime; lastTime = currentTime; // upcast to long since we might exceed int-max when rate and delta are // large enough; then downcast again... long tickDelta = ( rateKiB * 1024L * delta) / 1000; //System.out.println("threshold:" + threshold + " update: " + bucket + " time delta:" + delta); bucket += tickDelta; if (bucket > threshold) bucket = threshold; } public int dispense(int numberOfChunks, int chunkSize) { if (rateKiB == 0) return numberOfChunks; if (chunkSize > bucket) return 0; if (chunkSize * numberOfChunks <= bucket) { bucket -= chunkSize * numberOfChunks; return numberOfChunks; } int availableChunks = (int)( bucket / chunkSize ); bucket -= chunkSize * availableChunks; return availableChunks; } public void returnUnusedChunks(int unused, int chunkSize) { bucket += unused * chunkSize; } public int peek(int chunkSize) { if (rateKiB != 0) return (int)( bucket / chunkSize ); else return Integer.MAX_VALUE; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerBasic.java0000644000175000017500000001535211165324620032311 0ustar adrianadrian/* * Created on Oct 23, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.control.impl; import java.util.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.peermanager.control.PeerControlInstance; import com.aelitis.azureus.core.peermanager.control.SpeedTokenDispenser; import com.aelitis.azureus.core.stats.AzureusCoreStatsProvider; public class PeerControlSchedulerBasic extends PeerControlSchedulerImpl implements AzureusCoreStatsProvider { private Random random = new Random(); private Map instance_map = new HashMap(); private List pending_registrations = new ArrayList(); private volatile boolean registrations_changed; protected AEMonitor this_mon = new AEMonitor( "PeerControlSchedulerBasic" ); private final SpeedTokenDispenserBasic tokenDispenser = new SpeedTokenDispenserBasic(); private long latest_time; private long last_lag_log; protected void schedule() { SystemTime.registerMonotonousConsumer( new SystemTime.TickConsumer() { public void consume( long time ) { synchronized( PeerControlSchedulerBasic.this ){ PeerControlSchedulerBasic.this.notify(); } } }); List instances = new LinkedList(); long tick_count = 0; long last_stats_time = SystemTime.getMonotonousTime(); while( true ){ if ( registrations_changed ){ try{ this_mon.enter(); Iterator it = instances.iterator(); while( it.hasNext()){ if ( it.next().isUnregistered()){ it.remove(); } } for (int i=0;i= 0 ){ tick_count++; inst.schedule( latest_time ); schedule_count++; long new_target = target + SCHEDULE_PERIOD_MILLIS; if ( new_target <= latest_time ){ new_target = latest_time + ( target % SCHEDULE_PERIOD_MILLIS ); } inst.setNextTick( new_target ); } } synchronized( this ){ if ( current_schedule_count == schedule_count ){ wait_count++; try{ long wait_start = SystemTime.getHighPrecisionCounter(); wait( SCHEDULE_PERIOD_MILLIS ); long wait_time = SystemTime.getHighPrecisionCounter() - wait_start; total_wait_time += wait_time; }catch( Throwable e ){ Debug.printStackTrace(e); } }else{ yield_count++; Thread.yield(); } } long stats_diff = latest_time - last_stats_time; if ( stats_diff > 10000 ){ // System.out.println( "stats: time = " + stats_diff + ", ticks = " + tick_count + ", inst = " + instances.size()); last_stats_time = latest_time; tick_count = 0; } } } public void register( PeerControlInstance instance ) { instanceWrapper wrapper = new instanceWrapper( instance ); wrapper.setNextTick( latest_time + random.nextInt( SCHEDULE_PERIOD_MILLIS )); try{ this_mon.enter(); Map new_map = new HashMap( instance_map ); new_map.put( instance, wrapper ); instance_map = new_map; pending_registrations.add( wrapper ); registrations_changed = true; }finally{ this_mon.exit(); } } public void unregister( PeerControlInstance instance ) { try{ this_mon.enter(); Map new_map = new HashMap( instance_map ); instanceWrapper wrapper = new_map.remove(instance); if ( wrapper == null ){ Debug.out( "instance wrapper not found" ); return; } wrapper.unregister(); instance_map = new_map; registrations_changed = true; }finally{ this_mon.exit(); } } public SpeedTokenDispenser getSpeedTokenDispenser() { return( tokenDispenser ); } public void updateScheduleOrdering() { } protected class instanceWrapper { private PeerControlInstance instance; private boolean unregistered; private long next_tick; private long last_schedule; protected instanceWrapper( PeerControlInstance _instance ) { instance = _instance; } protected void unregister() { unregistered = true; } protected boolean isUnregistered() { return( unregistered ); } protected void setNextTick( long t ) { next_tick = t; } protected long getNextTick() { return( next_tick ); } protected String getName() { return( instance.getName()); } protected void schedule( long mono_now ) { if ( mono_now < 100000 ){ Debug.out("eh?"); } if ( last_schedule > 0 ){ if ( mono_now - last_schedule > 1000 ){ if ( mono_now - last_lag_log > 1000 ){ last_lag_log = mono_now; System.out.println( "Scheduling lagging: " + (mono_now - last_schedule ) + " - instances=" + instance_map.size()); } } } last_schedule = mono_now; try{ instance.schedule(); }catch( Throwable e ){ Debug.printStackTrace(e); } } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/control/impl/SpeedTokenDispenserBasic.java0000644000175000017500000000254210707503506032134 0ustar adrianadrian/* * Created on Oct 23, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.control.impl; import com.aelitis.azureus.core.peermanager.control.SpeedTokenDispenser; public class SpeedTokenDispenserBasic implements SpeedTokenDispenser { public int dispense(int numberOfChunks, int chunkSize) { return( numberOfChunks ); } public void returnUnusedChunks(int unused, int chunkSize) { } public int peek(int chunkSize) { return( chunkSize ); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerPrioritised.javaazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerPrioritised.ja0000644000175000017500000001654511015661754033251 0ustar adrianadrian/* * Created on Oct 23, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.control.impl; import java.util.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.peermanager.control.PeerControlInstance; import com.aelitis.azureus.core.peermanager.control.SpeedTokenDispenser; import com.aelitis.azureus.core.stats.AzureusCoreStatsProvider; public class PeerControlSchedulerPrioritised extends PeerControlSchedulerImpl implements AzureusCoreStatsProvider { private Map instance_map = new HashMap(); private List pending_registrations = new ArrayList(); private volatile boolean registrations_changed; private volatile long latest_time; protected AEMonitor this_mon = new AEMonitor( "PeerControlSchedulerPrioritised" ); private final SpeedTokenDispenserPrioritised tokenDispenser = new SpeedTokenDispenserPrioritised(); protected void schedule() { latest_time = SystemTime.getMonotonousTime(); SystemTime.registerMonotonousConsumer( new SystemTime.TickConsumer() { public void consume( long time ) { synchronized( PeerControlSchedulerPrioritised.this ){ latest_time = time; PeerControlSchedulerPrioritised.this.notify(); } } }); ArrayList instances = new ArrayList(); long latest_time_used = 0; int scheduledNext = 0; long currentScheduleStart = latest_time; long last_stats_time = latest_time; while( true ){ if ( registrations_changed ){ try{ this_mon.enter(); Iterator it = instances.iterator(); while( it.hasNext()){ if (((instanceWrapper)it.next()).isUnregistered()){ it.remove(); } } for (int i=0;i 0) { for(int i=0;i latest_time_used) break; // too early for next task, continue waiting if (i == 0 || !useWeights) tokenDispenser.refill(); // System.out.println("scheduling "+i+" time:"+latest_time); inst.schedule(); schedule_count++; scheduledNext++; if (scheduledNext >= instances.size()) { scheduledNext = 0; // try to run every task every SCHEDULE_PERIOD_MILLIS on average currentScheduleStart += SCHEDULE_PERIOD_MILLIS; // if tasks hog too much time then delay to prevent massive // catch-up-hammering if (latest_time_used - currentScheduleStart > SCHEDULE_PERIOD_MAX_CATCHUP ) currentScheduleStart = latest_time_used + SCHEDULE_PERIOD_MILLIS; } } /* for (Iterator it=instances.iterator();it.hasNext();){ instanceWrapper inst = (instanceWrapper)it.next(); long target = inst.getNextTick(); long diff = target - latest_time_used; if ( diff <= 0 || diff > SCHEDULE_PERIOD_MILLIS ){ inst.schedule(); long new_target = target + SCHEDULE_PERIOD_MILLIS; diff = new_target - latest_time_used; if ( diff <= 0 || diff > SCHEDULE_PERIOD_MILLIS ) new_target = latest_time_used + SCHEDULE_PERIOD_MILLIS; inst.setNextTick( new_target ); } }*/ synchronized( this ){ if ( latest_time == latest_time_used ){ wait_count++; try{ long wait_start = SystemTime.getHighPrecisionCounter(); wait(); long wait_time = SystemTime.getHighPrecisionCounter() - wait_start; total_wait_time += wait_time; }catch( Throwable e ){ Debug.printStackTrace(e); } }else{ yield_count++; Thread.yield(); } latest_time_used = latest_time; } long stats_diff = latest_time_used - last_stats_time; if ( stats_diff > 10000 ){ // System.out.println( "stats: time = " + stats_diff + ", ticks = " + tick_count + ", inst = " + instances.size()); last_stats_time = latest_time_used; } } } public void register( PeerControlInstance instance ) { instanceWrapper wrapper = new instanceWrapper( instance ); try{ this_mon.enter(); Map new_map = new HashMap( instance_map ); new_map.put( instance, wrapper ); instance_map = new_map; pending_registrations.add( wrapper ); registrations_changed = true; }finally{ this_mon.exit(); } } public void unregister( PeerControlInstance instance ) { try{ this_mon.enter(); Map new_map = new HashMap( instance_map ); instanceWrapper wrapper = (instanceWrapper)new_map.remove(instance); if ( wrapper == null ){ Debug.out( "instance wrapper not found" ); return; } wrapper.unregister(); instance_map = new_map; registrations_changed = true; }finally{ this_mon.exit(); } } public SpeedTokenDispenser getSpeedTokenDispenser() { return( tokenDispenser ); } public void updateScheduleOrdering() { registrations_changed = true; } protected static class instanceWrapper implements Comparable { private PeerControlInstance instance; private boolean unregistered; private long offset; protected instanceWrapper( PeerControlInstance _instance ) { instance = _instance; } protected void unregister() { unregistered = true; } protected boolean isUnregistered() { return( unregistered ); } protected void setScheduleOffset( long t ) { offset = t; } protected long getScheduleOffset() { return( offset ); } protected PeerControlInstance getInstance() { return( instance ); } protected void schedule() { try{ instance.schedule(); }catch( Throwable e ){ Debug.printStackTrace(e); } } public int compareTo(Object o) { return instance.getSchedulePriority()-((instanceWrapper)o).instance.getSchedulePriority(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/control/SpeedTokenDispenser.java0000644000175000017500000000225310707503510030223 0ustar adrianadrian/* * Created on Oct 23, 2007 * Created by The8472 * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.control; public interface SpeedTokenDispenser { public int dispense(int numberOfChunks, int chunkSize); public void returnUnusedChunks(int unused, int chunkSize); public int peek(int chunkSize); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/control/PeerControlSchedulerFactory.java0000644000175000017500000000265311165063176031744 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.peermanager.control; import com.aelitis.azureus.core.peermanager.control.impl.PeerControlSchedulerImpl; public class PeerControlSchedulerFactory { public static PeerControlScheduler getSingleton( int id ) { return( PeerControlSchedulerImpl.getSingleton( id )); } public static void overrideWeightedPriorities( boolean b ) { PeerControlSchedulerImpl.overrideAllWeightedPriorities( b ); } public static void updateScheduleOrdering() { PeerControlSchedulerImpl.updateAllScheduleOrdering(); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/control/PeerControlInstance.java0000644000175000017500000000210011165324612030220 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.peermanager.control; public interface PeerControlInstance { public void schedule(); public int getSchedulePriority(); public String getName(); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/control/PeerControlScheduler.java0000644000175000017500000000320010726407124030376 0ustar adrianadrian/* * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.peermanager.control; import org.gudy.azureus2.core3.config.COConfigurationManager; public interface PeerControlScheduler { public static final int SCHEDULE_PERIOD_MILLIS = COConfigurationManager.getIntParameter( "peermanager.schedule.time" ); public static final int SCHEDULE_PERIOD_MAX_CATCHUP = SCHEDULE_PERIOD_MILLIS>>2; public void register( PeerControlInstance instance ); public void unregister( PeerControlInstance instance ); public void updateScheduleOrdering(); public SpeedTokenDispenser getSpeedTokenDispenser(); /** * * @param override, set to true to disable weighted priorities, false to use user-configureable default */ public void overrideWeightedPriorities(boolean override); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/peerdb/0000755000175000017500000000000011310377630023224 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/peerdb/PeerItemFactory.java0000644000175000017500000000517610776254672027161 0ustar adrianadrian/* * Created on Apr 27, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.peerdb; import org.gudy.azureus2.core3.util.StringInterner; /** * */ public class PeerItemFactory { public static final byte PEER_SOURCE_TRACKER = 0; public static final byte PEER_SOURCE_DHT = 1; public static final byte PEER_SOURCE_PEER_EXCHANGE = 2; public static final byte PEER_SOURCE_PLUGIN = 3; public static final byte PEER_SOURCE_INCOMING = 4; public static final byte HANDSHAKE_TYPE_PLAIN = 0; public static final byte HANDSHAKE_TYPE_CRYPTO = 1; public static final byte CRYPTO_LEVEL_1 = 1; public static final byte CRYPTO_LEVEL_2 = 2; public static final byte CRYPTO_LEVEL_CURRENT = CRYPTO_LEVEL_2; /** * Create a peer item using the given peer address and port information. * @param address of peer * @param port of peer * @param source this peer info was obtained from * @return peer */ public static PeerItem createPeerItem( String address, int tcp_port, byte source, byte handshake_type, int udp_port, byte crypto_level, int up_speed ) { return (PeerItem)StringInterner.internObject( new PeerItem( address, tcp_port, source, handshake_type, udp_port, crypto_level, up_speed ) ); } /** * Create a peer item using the given peer raw byte serialization (address and port). * @param serialization bytes * @param source this peer info was obtained from * @return peer */ public static PeerItem createPeerItem( byte[] serialization, byte source, byte handshake_type, int udp_port ) throws Exception { return (PeerItem)StringInterner.internObject( new PeerItem( serialization, source, handshake_type, udp_port ) ); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/peerdb/PeerItem.java0000644000175000017500000001436111124122754025604 0ustar adrianadrian/* * Created on Apr 26, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.peerdb; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; import org.gudy.azureus2.core3.peer.PEPeerSource; import org.gudy.azureus2.plugins.peers.PeerDescriptor; /** * Represents a peer item, unique by ip address + port combo. * NOTE: Overrides equals(). */ public class PeerItem implements PeerDescriptor { private final byte[] address; private final short udp_port; private final short tcp_port; private final byte source; private final int hashcode; private final byte handshake; private final byte crypto_level; private final short up_speed; protected PeerItem( String _address, int _tcp_port, byte _source, byte _handshake, int _udp_port, byte _crypto_level, int _up_speed ) { byte[] raw; try{ //see if we can resolve the address into a compact raw IPv4/6 byte array (4 or 16 bytes) InetAddress ip = InetAddress.getByName( _address ); raw = ip.getAddress(); } catch( UnknownHostException e ) { //not a standard IPv4/6 address, so just use the full string bytes raw = _address.getBytes(); } address = raw; tcp_port = (short)_tcp_port; udp_port = (short)_udp_port; source = _source; hashcode = new String( address ).hashCode() + tcp_port; handshake = _handshake; crypto_level = _crypto_level; up_speed = (short)_up_speed; } protected PeerItem( byte[] _serialization, byte _source, byte _handshake, int _udp_port ) throws Exception{ if ( _serialization.length < 6 || _serialization.length > 32){ throw( new Exception( "PeerItem: invalid serialisation length - " + _serialization.length )); } //extract address and port address = new byte[ _serialization.length -2 ]; System.arraycopy( _serialization, 0, address, 0, _serialization.length -2 ); byte p0 = _serialization[ _serialization.length -2 ]; byte p1 = _serialization[ _serialization.length -1 ]; tcp_port = (short)((p1 & 0xFF) + ((p0 & 0xFF) << 8)); source = _source; hashcode = new String( address ).hashCode() + tcp_port; handshake = _handshake; udp_port = (short)_udp_port; crypto_level = PeerItemFactory.CRYPTO_LEVEL_1; // TODO: serialise this... up_speed = 0; // TODO:... } public byte[] getSerialization() { //combine address and port bytes into one byte[] full_address = new byte[ address.length +2 ]; System.arraycopy( address, 0, full_address, 0, address.length ); full_address[ address.length ] = (byte)(tcp_port >> 8); full_address[ address.length +1 ] = (byte)(tcp_port & 0xff); return full_address; } public String getAddressString() { try{ //see if it's an IPv4/6 address (4 or 16 bytes) return InetAddress.getByAddress( address ).getHostAddress(); } catch( UnknownHostException e ) { //not a standard IPv4/6 address, so just return as full string return new String( address ); } } public String getIP() { return( getAddressString()); } public int getTCPPort() { return tcp_port&0xffff; } public int getUDPPort() { return udp_port&0xffff; } public byte getSource() { return source; } public byte getHandshakeType() { return handshake; } public byte getCryptoLevel() { return crypto_level; } public boolean useCrypto() { return( crypto_level != PeerItemFactory.HANDSHAKE_TYPE_PLAIN ); } public boolean equals( Object obj ) { if( this == obj ) return true; if( obj != null && obj instanceof PeerItem ) { PeerItem other = (PeerItem)obj; if( this.tcp_port == other.tcp_port && this.udp_port == other.udp_port && this.handshake == other.handshake && Arrays.equals( this.address, other.address ) ) return true; } return false; } public int hashCode() { return hashcode; } public static String convertSourceString( byte source_id ) { //we use an int to store the source text string as this class is supposed to be lightweight switch( source_id ) { case PeerItemFactory.PEER_SOURCE_TRACKER: return PEPeerSource.PS_BT_TRACKER; case PeerItemFactory.PEER_SOURCE_DHT: return PEPeerSource.PS_DHT; case PeerItemFactory.PEER_SOURCE_PEER_EXCHANGE: return PEPeerSource.PS_OTHER_PEER; case PeerItemFactory.PEER_SOURCE_PLUGIN: return PEPeerSource.PS_PLUGIN; case PeerItemFactory.PEER_SOURCE_INCOMING: return PEPeerSource.PS_INCOMING; default: return ""; } } public static byte convertSourceID( String source ) { if( source.equals( PEPeerSource.PS_BT_TRACKER ) ) return PeerItemFactory.PEER_SOURCE_TRACKER; if( source.equals( PEPeerSource.PS_DHT ) ) return PeerItemFactory.PEER_SOURCE_DHT; if( source.equals( PEPeerSource.PS_OTHER_PEER ) ) return PeerItemFactory.PEER_SOURCE_PEER_EXCHANGE; if( source.equals( PEPeerSource.PS_PLUGIN ) ) return PeerItemFactory.PEER_SOURCE_PLUGIN; if( source.equals( PEPeerSource.PS_INCOMING ) ) return PeerItemFactory.PEER_SOURCE_INCOMING; return -1; } public boolean isIPv4() { return address.length == 4; } /* public String toString() { return org.gudy.azureus2.core3.util.ByteFormatter.encodeString(this.address) + ":" + this.tcp_port; } */ } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/peerdb/PeerDatabase.java0000644000175000017500000003137011124122754026411 0ustar adrianadrian/* * Created on Apr 26, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.peerdb; import java.util.*; import org.gudy.azureus2.core3.peer.util.PeerUtils; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.util.bloom.*; /** * */ public class PeerDatabase { private static final int MIN_REBUILD_WAIT_TIME = 60*1000; private static final int MAX_DISCOVERED_PEERS = 500; private static final int BLOOM_ROTATION_PERIOD = 7*60*1000; private static final int BLOOM_FILTER_SIZE = 10000; private final HashMap peer_connections = new HashMap(); private final LinkedList discovered_peers = new LinkedList(); private final AEMonitor map_mon = new AEMonitor( "PeerDatabase" ); private PeerItem[] cached_peer_popularities = null; private int popularity_pos = 0; private long last_rebuild_time = 0; private long last_rotation_time = 0; private PeerItem self_peer; private BloomFilter filter_one = null; private BloomFilter filter_two = BloomFilterFactory.createAddOnly( BLOOM_FILTER_SIZE ); protected PeerDatabase() { /* nothing */ } /** * Register a new peer connection with the database. * @param base_peer_item key * @return registered connection */ public PeerExchangerItem registerPeerConnection( PeerItem base_peer_item, PeerExchangerItem.Helper helper ) { try{ map_mon.enter(); PeerExchangerItem new_connection = new PeerExchangerItem( this, base_peer_item, helper ); //update connection adds for( Iterator it = peer_connections.entrySet().iterator(); it.hasNext(); ) { //go through all existing connections Map.Entry entry = (Map.Entry)it.next(); PeerItem old_key = (PeerItem)entry.getKey(); PeerExchangerItem old_connection = (PeerExchangerItem)entry.getValue(); if( old_connection.getHelper().isSeed() && new_connection.getHelper().isSeed() ) { continue; //dont exchange seed peers to other seeds } old_connection.notifyAdded( base_peer_item ); //notify existing connection of new one new_connection.notifyAdded( old_key ); //notify new connection of existing one for initial exchange } peer_connections.put( base_peer_item, new_connection ); return new_connection; } finally{ map_mon.exit(); } } protected void deregisterPeerConnection( PeerItem base_peer_key ) { try{ map_mon.enter(); peer_connections.remove( base_peer_key ); //update connection drops for( Iterator it = peer_connections.values().iterator(); it.hasNext(); ) { //go through all remaining connections PeerExchangerItem old_connection = (PeerExchangerItem)it.next(); //dont skip seed2seed drop notification, as the dropped peer may not have been seeding initially old_connection.notifyDropped( base_peer_key ); //notify existing connection of drop } } finally{ map_mon.exit(); } } public void seedStatusChanged( PeerExchangerItem item ) { // only bother with non-seed -> seed transitions, the opposite are too rate to bother with if ( item.getHelper().isSeed()){ try{ map_mon.enter(); for ( Iterator it = peer_connections.values().iterator(); it.hasNext(); ){ PeerExchangerItem connection = (PeerExchangerItem)it.next(); if ( connection != item && connection.getHelper().isSeed()){ // System.out.println( "seedStatusChanged: dropping: originator= " + item.getBasePeer().getAddressString() + ",target=" + connection.getBasePeer().getAddressString()); connection.notifyDropped( item.getBasePeer() ); item.notifyDropped( connection.getBasePeer() ); } } }finally{ map_mon.exit(); } } } /** * Add a potential peer obtained via tracker announce, DHT announce, plugin, etc. * @param peer to add */ public void addDiscoveredPeer( PeerItem peer ) { try{ map_mon.enter(); for( Iterator it = peer_connections.values().iterator(); it.hasNext(); ) { //check to make sure we dont already know about this peer PeerExchangerItem connection = (PeerExchangerItem)it.next(); if( connection.isConnectedToPeer( peer ) ) return; //we already know about this peer via exchange, so ignore discovery } if( !discovered_peers.contains( peer ) ) { discovered_peers.addLast( peer ); //add unknown peer int max_cache_size = PeerUtils.MAX_CONNECTIONS_PER_TORRENT; if( max_cache_size < 1 || max_cache_size > MAX_DISCOVERED_PEERS ) max_cache_size = MAX_DISCOVERED_PEERS; if( discovered_peers.size() > max_cache_size ) { discovered_peers.removeFirst(); } } } finally{ map_mon.exit(); } } /** * Mark the given peer as ourself. * @param self peer */ public void setSelfPeer( PeerItem self ) { self_peer = self; } /** * Get the peer item that represents ourself. * @return self peer, or null if unknown */ public PeerItem getSelfPeer() { /* //disabled for now, as getExternalIpAddress() will potential run a full version check every 60s if( self_peer == null ) { //determine our 'self' info from config String ip = VersionCheckClient.getSingleton().getExternalIpAddress(); if( ip != null && ip.length() > 0 ) { self_peer = PeerItemFactory.createPeerItem( ip, NetworkManager.getSingleton().getTCPListeningPortNumber(), 0 ); } } */ return self_peer; } public PeerItem[] getDiscoveredPeers() { try{ map_mon.enter(); return((PeerItem[])discovered_peers.toArray( new PeerItem[discovered_peers.size()] )); }finally{ map_mon.exit(); } } public PeerItem[] getDiscoveredPeers( String address ) { List result = null; try{ map_mon.enter(); for (int i=0;i(); } result.add( peer ); } } }finally{ map_mon.exit(); } if ( result == null ){ return( new PeerItem[0]); }else{ return( result.toArray( new PeerItem[result.size()] )); } } public int getDiscoveredPeerCount() { try{ map_mon.enter(); return( discovered_peers.size()); }finally{ map_mon.exit(); } } /** * Get the next potential peer for optimistic connect. * @return peer to connect, or null of no optimistic peer available */ public PeerItem getNextOptimisticConnectPeer( ) { return(getNextOptimisticConnectPeer(0)); } protected PeerItem getNextOptimisticConnectPeer( int recursion_count ) { PeerItem peer = null; boolean discovered_peer = false; //first see if there are any unknown peers to try try{ map_mon.enter(); if( !discovered_peers.isEmpty() ) { peer = (PeerItem)discovered_peers.removeFirst(); discovered_peer = true; } } finally{ map_mon.exit(); } //pick one from those obtained via peer exchange if needed if( peer == null ) { if( cached_peer_popularities == null || popularity_pos == cached_peer_popularities.length ) { //rebuild needed cached_peer_popularities = null; //clear cache long time_since_rebuild = SystemTime.getCurrentTime() - last_rebuild_time; //only allow exchange list rebuild every few min, otherwise we'll spam attempts endlessly if( time_since_rebuild > MIN_REBUILD_WAIT_TIME || time_since_rebuild < 0 ) { cached_peer_popularities = getExchangedPeersSortedByLeastPopularFirst(); popularity_pos = 0; last_rebuild_time = SystemTime.getCurrentTime(); } } if( cached_peer_popularities != null && cached_peer_popularities.length > 0 ) { peer = cached_peer_popularities[ popularity_pos ]; popularity_pos++; last_rebuild_time = SystemTime.getCurrentTime(); //ensure rebuild waits min rebuild time after the cache is depleted before trying attempts again } } //to reduce the number of wasted outgoing attempts, we limit how frequently we hand out the same optimistic peer in a given time period if( peer != null ) { //check if it's time to rotate the bloom filters long diff = SystemTime.getCurrentTime() - last_rotation_time; if( diff < 0 || diff > BLOOM_ROTATION_PERIOD ) { filter_one = filter_two; filter_two = BloomFilterFactory.createAddOnly( BLOOM_FILTER_SIZE ); last_rotation_time = SystemTime.getCurrentTime(); } //check to see if we've already given this peer out optimistically in the last 5-10min boolean already_recorded = false; byte[] peer_serialisation = peer.getSerialization(); if( filter_one.contains( peer_serialisation ) && recursion_count < 100 ) { // we've recently given this peer, so recursively find another peer to try PeerItem next_peer = getNextOptimisticConnectPeer( recursion_count + 1); if ( next_peer != null ){ // we've found a better peer that this one. If the existing peer was discovered (as opposed to PEX) // then we'll save it for later as it might come in useful if ( discovered_peer ){ try{ map_mon.enter(); discovered_peers.addLast( peer ); }finally{ map_mon.exit(); } } peer = next_peer; already_recorded = true; // this peer's already in the bloom filters as it has been returned // by a recursive call } } if( !already_recorded ) { //we've found a suitable peer filter_one.add( peer_serialisation ); filter_two.add( peer_serialisation ); } } return peer; } private PeerItem[] getExchangedPeersSortedByLeastPopularFirst() { HashMap popularity_counts = new HashMap(); try{ map_mon.enter(); //count popularity of all known peers for( Iterator it = peer_connections.values().iterator(); it.hasNext(); ) { PeerExchangerItem connection = (PeerExchangerItem)it.next(); PeerItem[] peers = connection.getConnectedPeers(); for( int i=0; i < peers.length; i++ ) { PeerItem peer = peers[i]; Integer count = (Integer)popularity_counts.get( peer ); if( count == null ) { count = new Integer( 1 ); } else { count = new Integer( count.intValue() + 1 ); } popularity_counts.put( peer, count ); } } } finally{ map_mon.exit(); } if( popularity_counts.isEmpty() ) return null; //now sort by popularity Map.Entry[] sorted_entries = new Map.Entry[ popularity_counts.size() ]; popularity_counts.entrySet().toArray( sorted_entries ); Arrays.sort( sorted_entries, new Comparator() { public int compare( Object obj1, Object obj2 ) { Map.Entry en1 = (Map.Entry)obj1; Map.Entry en2 = (Map.Entry)obj2; return ((Integer)en1.getValue()).compareTo( (Integer)en2.getValue() ); //we want least popular in front } }); PeerItem[] sorted_peers = new PeerItem[ sorted_entries.length ]; for( int i=0; i < sorted_entries.length; i++ ) { Map.Entry entry = sorted_entries[i]; sorted_peers[i] = (PeerItem)entry.getKey(); } return sorted_peers; } //TODO destroy() method? public String getString() { return("pc=" + peer_connections.size() + ",dp=" + discovered_peers.size()); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/peerdb/PeerDatabaseFactory.java0000644000175000017500000000221010373051044027726 0ustar adrianadrian/* * Created on Apr 27, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.peerdb; /** * */ public class PeerDatabaseFactory { public static PeerDatabase createPeerDatabase() { return new PeerDatabase(); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/peerdb/PeerExchangerItem.java0000644000175000017500000001510611135772006027432 0ustar adrianadrian/* * Created on Apr 27, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.peerdb; import java.util.*; import org.gudy.azureus2.core3.peer.util.PeerUtils; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.LightHashMap; /** * */ public class PeerExchangerItem { public static final int MAX_PEERS_PER_VOLLEY = 50; private static final int MAX_KNOWN_PER_PEER = 500; private final PeerDatabase parent_db; private final PeerItem base_peer; private final LinkedList connections_added = new LinkedList(); private final LinkedList connections_dropped = new LinkedList(); private final Map connected_peers = new LightHashMap(); private final AEMonitor peers_mon = new AEMonitor( "PeerConnectionItem" ); private boolean maintain_peers_state = true; //assume we do until explicitly disabled private final Helper helper; protected PeerExchangerItem( PeerDatabase parent_db, PeerItem peer, Helper helper ) { this.parent_db = parent_db; this.base_peer = peer; this.helper = helper; } protected PeerItem getBasePeer(){ return base_peer; } protected Helper getHelper() { return helper; } /** * Add peer info obtained via peer exchange. * @param peer to add */ public void addConnectedPeer( PeerItem peer ) { try{ peers_mon.enter(); if( !maintain_peers_state ) return; int max_cache_size = PeerUtils.MAX_CONNECTIONS_PER_TORRENT; if( max_cache_size < 1 || max_cache_size > MAX_KNOWN_PER_PEER ) max_cache_size = MAX_KNOWN_PER_PEER; if( connected_peers.size() < max_cache_size ) { connected_peers.put( peer, null ); } } finally{ peers_mon.exit(); } } /** * Remove peer info obtained via peer exchange. * @param peer to remove */ public void dropConnectedPeer( PeerItem peer ) { try{ peers_mon.enter(); connected_peers.remove( peer ); } finally{ peers_mon.exit(); } } protected void notifyAdded( PeerItem peer_connection ) { try{ peers_mon.enter(); if( !maintain_peers_state ) return; if( !connections_dropped.contains( peer_connection ) ) { if( !connections_added.contains( peer_connection ) ) { connections_added.addLast( peer_connection ); //register new add } } else { //was dropped and then re-added connections_dropped.remove( peer_connection ); //pull drop and ignore add } } finally{ peers_mon.exit(); } } protected void notifyDropped( PeerItem peer_connection ) { try{ peers_mon.enter(); if( !maintain_peers_state ) return; if( !connections_added.contains( peer_connection ) ) { if( !connections_dropped.contains( peer_connection ) ) { connections_dropped.addLast( peer_connection ); //register new drop } } else { //was added and then re-dropped connections_added.remove( peer_connection ); //pull add and ignore drop } } finally{ peers_mon.exit(); } } public void seedStatusChanged() { parent_db.seedStatusChanged( this ); } /** * Get the list of peer connections added since this method was last called. * @return new peer connections */ public PeerItem[] getNewlyAddedPeerConnections() { try{ peers_mon.enter(); if( connections_added.isEmpty() ) return null; int num_to_send = connections_added.size() > MAX_PEERS_PER_VOLLEY ? MAX_PEERS_PER_VOLLEY : connections_added.size(); PeerItem[] peers = new PeerItem[ num_to_send ]; for( int i=0; i < num_to_send; i++ ) { peers[i] = (PeerItem)connections_added.removeFirst(); } return peers; } finally{ peers_mon.exit(); } } /** * Get the list of peer connections dropped since this method was last called. * @return dropped peer connections */ public PeerItem[] getNewlyDroppedPeerConnections() { try{ peers_mon.enter(); if( connections_dropped.isEmpty() ) return null; int num_to_send = connections_dropped.size() > MAX_PEERS_PER_VOLLEY ? MAX_PEERS_PER_VOLLEY : connections_dropped.size(); PeerItem[] peers = new PeerItem[ num_to_send ]; for( int i=0; i < num_to_send; i++ ) { peers[i] = (PeerItem)connections_dropped.removeFirst(); } return peers; } finally{ peers_mon.exit(); } } /** * Clears all current peer state records and stops any future state maintenance. */ public void disableStateMaintenance() { try{ peers_mon.enter(); maintain_peers_state = false; connections_added.clear(); connections_dropped.clear(); connected_peers.clear(); } finally{ peers_mon.exit(); } } protected boolean isConnectedToPeer( PeerItem peer ) { try{ peers_mon.enter(); return connected_peers.containsKey( peer ); } finally{ peers_mon.exit(); } } protected PeerItem[] getConnectedPeers() { try{ peers_mon.enter(); PeerItem[] peers = new PeerItem[ connected_peers.size() ]; connected_peers.keySet().toArray( peers ); return peers; } finally{ peers_mon.exit(); } } public void destroy() { parent_db.deregisterPeerConnection( base_peer ); try{ peers_mon.enter(); connections_added.clear(); connections_dropped.clear(); connected_peers.clear(); } finally{ peers_mon.exit(); } } public interface Helper { /** * Does this connection item represent a seed peer? * @return true if seeding, false if not */ public boolean isSeed(); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/unchoker/0000755000175000017500000000000011310377630023601 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/unchoker/Unchoker.java0000644000175000017500000000424511244607062026230 0ustar adrianadrian/* * Created on Apr 5, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.unchoker; import java.util.*; import org.gudy.azureus2.core3.peer.PEPeer; /** * Performs peer choke/unchoke calculations. */ public interface Unchoker { public boolean isSeedingUnchoker(); /** * Get any unchokes that should be performed immediately. * @param max_to_unchoke maximum number of peers allowed to be unchoked * @param all_peers list of peers to choose from * @return peers to unchoke */ public ArrayList getImmediateUnchokes( int max_to_unchoke, ArrayList all_peers ); /** * Perform peer choke, unchoke and optimistic calculations * @param max_to_unchoke maximum number of peers allowed to be unchoked * @param all_peers list of peers to choose from * @param force_refresh force a refresh of optimistic unchokes */ public void calculateUnchokes( int max_to_unchoke, ArrayList all_peers, boolean force_refresh, boolean check_priority_connections ); /** * Get the list of peers calculated to be choked. * @return peers to choke */ public ArrayList getChokes(); /** * Get the list of peers calculated to be unchoked. * @return peers to unchoke */ public ArrayList getUnchokes(); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/unchoker/UnchokerUtil.java0000644000175000017500000001641011244607062027063 0ustar adrianadrian/* * Created on Apr 5, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.unchoker; import java.util.*; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.impl.PEPeerTransport; import org.gudy.azureus2.core3.util.RandomUtils; /** * Utility collection for unchokers. */ public class UnchokerUtil { /** * Test whether or not the given peer is allowed to be unchoked. * @param peer to test * @param allow_snubbed if true, ignore snubbed state * @return true if peer is allowed to be unchoked, false if not */ public static boolean isUnchokable( PEPeer peer, boolean allow_snubbed ) { return peer.getPeerState() == PEPeer.TRANSFERING && !peer.isSeed() && !peer.isRelativeSeed() && peer.isInterested() && ( !peer.isSnubbed() || allow_snubbed ); } /** * Update (if necessary) the given list with the given value while maintaining a largest-value-first (as seen so far) sort order. * NOTE: You will need to initialize the values array to Long.MIN_VALUE if you want to store negative values! * @param new_value to use * @param values existing values array * @param new_item to insert * @param items existing items * @param start_pos index at which to start compare */ public static void updateLargestValueFirstSort( long new_value, long[] values, PEPeer new_item, ArrayList items, int start_pos ) { items.ensureCapacity( values.length ); for( int i=start_pos; i < values.length; i++ ) { if( new_value >= values[ i ] ) { for( int j = values.length - 2; j >= i; j-- ) { //shift displaced values to the right values[j + 1] = values[ j ]; } if( items.size() == values.length ) { //throw away last item if list too large items.remove( values.length - 1 ); } values[ i ] = new_value; items.add( i, new_item ); return; } } } /** * Choose the next peer, optimistically, that should be unchoked. * @param all_peers list of peer to choose from * @param factor_reciprocated if true, factor in how much (if any) this peer has reciprocated when choosing * @param allow_snubbed allow the picking of snubbed-state peers as last resort * @return the next peer to optimistically unchoke, or null if there are no peers available */ public static PEPeer getNextOptimisticPeer( ArrayList all_peers, boolean factor_reciprocated, boolean allow_snubbed ) { ArrayList peers = getNextOptimisticPeers( all_peers, factor_reciprocated, allow_snubbed, 1 ); if ( peers != null ){ return((PEPeerTransport)peers.get(0)); } return( null ); } public static ArrayList getNextOptimisticPeers( ArrayList all_peers, boolean factor_reciprocated, boolean allow_snubbed, int num_needed ) { //find all potential optimistic peers ArrayList optimistics = new ArrayList(); for( int i=0; i < all_peers.size(); i++ ) { PEPeer peer = all_peers.get( i ); if( isUnchokable( peer, false ) && peer.isChokedByMe() ) { optimistics.add( peer ); } } if( optimistics.isEmpty() && allow_snubbed ) { //try again, allowing snubbed peers as last resort for( int i=0; i < all_peers.size(); i++ ) { PEPeer peer = all_peers.get( i ); if( isUnchokable( peer, true ) && peer.isChokedByMe() ) { optimistics.add( peer ); } } } if( optimistics.isEmpty() ) return null; //no unchokable peers avail //factor in peer reciprocation ratio when picking optimistic peers ArrayList result = new ArrayList(optimistics.size()); if ( factor_reciprocated ){ ArrayList ratioed_peers = new ArrayList( optimistics.size() ); long[] ratios = new long[ optimistics.size() ]; Arrays.fill( ratios, Long.MIN_VALUE ); //order by upload ratio for( int i=0; i < optimistics.size(); i++ ) { PEPeer peer = optimistics.get( i ); //score of >0 means we've uploaded more, <0 means we've downloaded more long score = peer.getStats().getTotalDataBytesSent() - peer.getStats().getTotalDataBytesReceived(); UnchokerUtil.updateLargestValueFirstSort( score, ratios, peer, ratioed_peers, 0 ); //higher value = worse score } for (int i=0;i 0;i++ ){ double factor = 1F / ( 0.8 + 0.2 * Math.pow( RandomUtils.nextFloat(), -1 ) ); //map to sorted list using a logistic curve int pos = (int)(factor * ratioed_peers.size()); result.add(ratioed_peers.remove( pos )); } }else{ for (int i=0;i 0;i++ ){ int rand_pos = new Random().nextInt( optimistics.size() ); result.add( optimistics.remove( rand_pos )); } } return( result ); //TODO: //in downloading mode, we would be better off optimistically unchoking just peers we are interested in ourselves, //as they could potentially reciprocate. however, new peers have no pieces to share, and are not interesting to //us, and would never be unchoked, and thus would never get any data. //we could use a deterministic method for new peers to get their very first piece from us } /** * Send choke/unchoke messages to the given peers. * @param peers_to_choke * @param peers_to_unchoke */ public static void performChokes( ArrayList peers_to_choke, ArrayList peers_to_unchoke ) { //do chokes if( peers_to_choke != null ) { for( int i=0; i < peers_to_choke.size(); i++ ) { final PEPeerTransport peer = (PEPeerTransport)peers_to_choke.get( i ); if( !peer.isChokedByMe() ) { peer.sendChoke(); } } } //do unchokes if( peers_to_unchoke != null ) { for( int i=0; i < peers_to_unchoke.size(); i++ ) { final PEPeer peer = peers_to_unchoke.get( i ); if( peer.isChokedByMe() ) { //TODO add UnchokerUtil.isUnchokable() test here to be safe? peer.sendUnChoke(); } } } } public static void performChokeUnchoke( PEPeer to_choke, PEPeer to_unchoke ) { if( to_choke != null && !to_choke.isChokedByMe() ) { to_choke.sendChoke(); } if( to_unchoke != null && to_unchoke.isChokedByMe() ) { to_unchoke.sendUnChoke(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/unchoker/UnchokerUtilTest.java0000644000175000017500000002633011257507206027730 0ustar adrianadrian/* * Created on May 28, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.unchoker; import java.net.InetAddress; import java.util.*; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerListener; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.peer.PEPeerStats; import org.gudy.azureus2.core3.util.RandomUtils; import org.gudy.azureus2.plugins.network.Connection; import com.aelitis.azureus.core.networkmanager.LimitedRateGroup; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags; /** * @author MjrTom * 2005/Oct/08: s/getLastPiece * 2006/Jan/02: use RandomUtils */ public class UnchokerUtilTest { private static final int NUM_PEERS_TO_TEST = 100; private static final int BYTE_RANGE = 100*1024*1024; private static final int TEST_ROUNDS = 1000000; public static void main(String[] args) { TreeMap counts = new TreeMap( new Comparator(){ public int compare( Object o1, Object o2 ) { PEPeer peer1 = (PEPeer)o1; PEPeer peer2 = (PEPeer)o2; long score1 = peer1.getStats().getTotalDataBytesSent() - peer1.getStats().getTotalDataBytesReceived(); long score2 = peer2.getStats().getTotalDataBytesSent() - peer2.getStats().getTotalDataBytesReceived(); return (int)(score1 - score2); } }); ArrayList test_peers = generateTestPeers(); for( int i=0; i < TEST_ROUNDS; i++ ) { if( i % 100000 == 0 ) System.out.println( "round=" +i ); PEPeer opt_peer = UnchokerUtil.getNextOptimisticPeer( test_peers, true, false ); Integer count = (Integer)counts.get( opt_peer ); if( count == null ) count = new Integer( 0 ); counts.put( opt_peer, new Integer( count.intValue() + 1 ) ); } int max_picked = 0; for( Iterator it = counts.values().iterator(); it.hasNext(); ) { int count = ((Integer)it.next()).intValue(); if( count > max_picked ) max_picked = count; } int pos = 0; for( Iterator it = counts.entrySet().iterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry)it.next(); PEPeer peer = (PEPeer)entry.getKey(); int count = ((Integer)entry.getValue()).intValue(); long score = peer.getStats().getTotalDataBytesSent() - peer.getStats().getTotalDataBytesReceived(); float ratio = (float)peer.getStats().getTotalDataBytesSent() / (peer.getStats().getTotalDataBytesReceived() + 1); int percentile = (count *100) / max_picked; System.out.println( "[" +pos+ "] score=" +score+ ", ratio=" +ratio+ ", picked=" +count+ "x, percentile=" +percentile+ "%" ); pos++; } } private static ArrayList generateTestPeers() { ArrayList peers = new ArrayList(); for( int i=0; i < NUM_PEERS_TO_TEST; i++ ) { final int bytes_received = RandomUtils.nextInt( BYTE_RANGE ); final int bytes_sent = RandomUtils.nextInt( BYTE_RANGE ); final PEPeerStats[] f_stats = { null }; final PEPeer peer = new PEPeer() { public InetAddress getAlternativeIPv6() { return null; } public void addListener( PEPeerListener listener ){} public void removeListener( PEPeerListener listener ){} public int getPeerState(){ return PEPeer.TRANSFERING; } public PEPeerManager getManager(){ return null; } public String getPeerSource(){ return null; } public byte[] getId(){ return null; } public String getIp(){ return null; } public int getPort(){ return 0; } public String getIPHostName(){ return null; } public int getTCPListenPort(){ return 0; } public int getUDPListenPort(){ return 0; } public int getUDPNonDataListenPort() { return 0;} public BitFlags getAvailable(){ return null; } public boolean isPieceAvailable(int pieceNumber){ return false; } public boolean transferAvailable(){ return true; } public boolean isDownloadPossible() { return true; } public void setSnubbed(boolean b){} public boolean isChokingMe(){ return true; } public boolean isChokedByMe() { return true; } public void sendChoke(){} public void sendUnChoke(){} public boolean isInteresting(){ return true; } public boolean isInterested(){ return true; } public boolean isRelativeSeed() { return false; } public boolean isSeed(){ return false; } public boolean isSnubbed(){ return false; } public long getSnubbedTime() { return 0; } public boolean hasReceivedBitField() {return false; } public PEPeerStats getStats(){ return f_stats[0]; } public boolean isIncoming(){ return false; } public int getPercentDoneInThousandNotation(){ return 0; } public String getClient(){ return null; } public boolean isOptimisticUnchoke(){ return false; } public void setOptimisticUnchoke( boolean is_optimistic ){} public void setUploadHint(int timeToSpread){} public int getUploadHint(){ return 0; } public void setUniqueAnnounce(int uniquePieceNumber){} public int getUniqueAnnounce(){ return 0; } public Object getData (String key){ return null; } public void setData (String key, Object value){} public Connection getPluginConnection(){ return null; } public boolean supportsMessaging(){ return false; } public int getMessagingMode(){ return PEPeer.MESSAGING_BT_ONLY; } public Message[] getSupportedMessages(){ return null; } public String getEncryption(){ return( "" ); } public int getReservedPieceNumber() { return -1; } public void setReservedPieceNumber(int pieceNumber) {} public int[] getIncomingRequestedPieceNumbers() { return null; } public int[] getOutgoingRequestedPieceNumbers() { return null; } public int getPercentDoneOfCurrentIncomingRequest(){ return 0; } public int getPercentDoneOfCurrentOutgoingRequest(){ return 0; } public long getTimeSinceConnectionEstablished(){ return 0; } public int getLastPiece() { return -1; } public void setLastPiece(int pieceNumber) {} public int getConsecutiveNoRequestCount() {return 0; } public void setConsecutiveNoRequestCount(int num) {} public int getIncomingRequestCount() { // TODO Auto-generated method stub return 0; } public int getOutgoingRequestCount() { // TODO Auto-generated method stub return 0; } public boolean isLANLocal() { // TODO Auto-generated method stub return false; } public boolean sendRequestHint(int piece_number, int offset, int length, int life) { // TODO Auto-generated method stub return false; } public int[] getRequestHint() { // TODO Auto-generated method stub return null; } public void clearRequestHint() { } public void setUploadRateLimitBytesPerSecond( int bytes ){} public void setDownloadRateLimitBytesPerSecond( int bytes ){} public int getUploadRateLimitBytesPerSecond(){ return 0 ;} public int getDownloadRateLimitBytesPerSecond(){ return 0; } public void addRateLimiter(LimitedRateGroup limiter, boolean upload) { // TODO Auto-generated method stub } public void removeRateLimiter(LimitedRateGroup limiter, boolean upload) { // TODO Auto-generated method stub } public void setHaveAggregationEnabled(boolean enabled) { // TODO Auto-generated method stub } public int getOutboundDataQueueSize() { // TODO Auto-generated method stub return 0; } public byte[] getHandshakeReservedBytes() { return null; } public String getClientNameFromExtensionHandshake() {return null;} public String getClientNameFromPeerID() {return null;} public long getBytesRemaining() { // TODO Auto-generated method stub return 0; } public Object getUserData(Object key) { // TODO Auto-generated method stub return null; } public void setUserData(Object key, Object value) { // TODO Auto-generated method stub } public boolean isPriorityConnection() { // TODO Auto-generated method stub return false; } public void setPriorityConnection(boolean is_priority) { // TODO Auto-generated method stub } }; f_stats[0] = new PEPeerStats() { public PEPeer getPeer() {return( peer );} public void setPeer(PEPeer p) {} public void dataBytesSent( int num_bytes ){} public void protocolBytesSent( int num_bytes ){} public void dataBytesReceived( int num_bytes ){} public void protocolBytesReceived( int num_bytes ){} public void bytesDiscarded( int num_bytes ){} public void hasNewPiece( int piece_size ){} public void statisticalSentPiece( int piece_size ){} public long getDataReceiveRate(){ return 0; } public long getProtocolReceiveRate(){ return 0; } public long getTotalDataBytesReceived(){ return bytes_received; } public long getTotalProtocolBytesReceived(){ return 0; } public long getDataSendRate(){ return 0; } public long getProtocolSendRate(){ return 0; } public long getTotalDataBytesSent(){ return bytes_sent; } public long getTotalProtocolBytesSent(){ return 0; } public long getSmoothDataReceiveRate(){ return 0; } public long getTotalBytesDiscarded(){ return 0; } public long getEstimatedDownloadRateOfPeer(){ return 0; } public long getEstimatedUploadRateOfPeer(){ return 0; } public long getTotalBytesDownloadedByPeer(){ return 0; } public void diskReadComplete( long bytes ){}; public int getTotalDiskReadCount(){ return 0; } public int getAggregatedDiskReadCount(){ return 0; } public long getTotalDiskReadBytes(){ return 0; } public void setUploadRateLimitBytesPerSecond( int bytes ){} public void setDownloadRateLimitBytesPerSecond( int bytes ){} public int getUploadRateLimitBytesPerSecond(){return 0;} public int getDownloadRateLimitBytesPerSecond(){return 0;} public long getEstimatedSecondsToCompletion(){return(0);}; }; peers.add( peer ); } return peers; } public static class UF extends UnchokerFactory { public Unchoker getUnchoker( boolean seeding) { return super.getUnchoker(seeding); } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/unchoker/DownloadingUnchoker.java0000644000175000017500000001637011244607062030420 0ustar adrianadrian/* * Created on Apr 5, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.unchoker; import java.util.ArrayList; import java.util.Iterator; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.peer.PEPeer; /** * Unchoker implementation to be used while in downloading mode. */ public class DownloadingUnchoker implements Unchoker { private ArrayList chokes = new ArrayList(); private ArrayList unchokes = new ArrayList(); protected DownloadingUnchoker() { /* nothing */ } public boolean isSeedingUnchoker() { return( false ); } public ArrayList getImmediateUnchokes( int max_to_unchoke, ArrayList all_peers ) { ArrayList to_unchoke = new ArrayList(); //count all the currently unchoked peers int num_unchoked = 0; for( int i=0; i < all_peers.size(); i++ ) { PEPeer peer = all_peers.get( i ); if( !peer.isChokedByMe() ) num_unchoked++; } //if not enough unchokes int needed = max_to_unchoke - num_unchoked; if( needed > 0 ) { for( int i=0; i < needed; i++ ) { PEPeer peer = UnchokerUtil.getNextOptimisticPeer( all_peers, true, true ); if( peer == null ) break; //no more new unchokes avail to_unchoke.add( peer ); peer.setOptimisticUnchoke( true ); } } return to_unchoke; } public void calculateUnchokes( int max_to_unchoke, ArrayList all_peers, boolean force_refresh, boolean check_priority_connections ) { int max_optimistic = ((max_to_unchoke - 1) / 10) + 1; //one optimistic unchoke for every 10 upload slots ArrayList optimistic_unchokes = new ArrayList(); ArrayList best_peers = new ArrayList(); long[] bests = new long[ max_to_unchoke ]; //ensure we never pick more slots than allowed to unchoke //get all the currently unchoked peers for( int i=0; i < all_peers.size(); i++ ) { PEPeer peer = all_peers.get( i ); if( !peer.isChokedByMe() ) { if( UnchokerUtil.isUnchokable( peer, true ) ) { unchokes.add( peer ); if( peer.isOptimisticUnchoke() ) { optimistic_unchokes.add( peer ); } } else { //should be immediately choked chokes.add( peer ); } } } if( !force_refresh ) { //ensure current optimistic unchokes remain unchoked for( int i=0; i < optimistic_unchokes.size(); i++ ) { PEPeer peer = optimistic_unchokes.get( i ); if( i < max_optimistic ) { best_peers.add( peer ); //add them to the front of the "best" list } else { //too many optimistics peer.setOptimisticUnchoke( false ); } } } //fill slots with peers who we are currently downloading the fastest from int start_pos = best_peers.size(); for( int i=0; i < all_peers.size(); i++ ) { PEPeer peer = all_peers.get( i ); if( peer.isInteresting() && UnchokerUtil.isUnchokable( peer, false ) && !best_peers.contains( peer ) ) { //viable peer found long rate = peer.getStats().getSmoothDataReceiveRate(); if( rate > 256 ) { //filter out really slow peers UnchokerUtil.updateLargestValueFirstSort( rate, bests, peer, best_peers, start_pos ); } } } //if we havent yet picked enough slots if( best_peers.size() < max_to_unchoke ) { start_pos = best_peers.size(); //fill the remaining slots with peers that we have downloaded from in the past for( int i=0; i < all_peers.size(); i++ ) { PEPeer peer = all_peers.get( i ); if( peer.isInteresting() && UnchokerUtil.isUnchokable( peer, false ) && !best_peers.contains( peer ) ) { //viable peer found long uploaded_ratio = peer.getStats().getTotalDataBytesSent() / (peer.getStats().getTotalDataBytesReceived() + (DiskManager.BLOCK_SIZE-1)); //make sure we haven't already uploaded several times as much data as they've sent us if( uploaded_ratio <3) { UnchokerUtil.updateLargestValueFirstSort( peer.getStats().getTotalDataBytesReceived(), bests, peer, best_peers, start_pos ); } } } } if( force_refresh ) { //make space for new optimistic unchokes while( best_peers.size() > max_to_unchoke - max_optimistic ) { best_peers.remove( best_peers.size() - 1 ); } } //if we still have remaining slots while( best_peers.size() < max_to_unchoke ) { PEPeer peer = UnchokerUtil.getNextOptimisticPeer( all_peers, true, true ); //just pick one optimistically if( peer == null ) break; //no more new unchokes avail if( !best_peers.contains( peer ) ) { best_peers.add( peer ); peer.setOptimisticUnchoke( true ); } else { //we're here because the given optimistic peer is already "best", but is choked still, //which means it will continually get picked by the getNextOptimisticPeer() method, //and we'll loop forever if there are no other peers to choose from peer.sendUnChoke(); //send unchoke immediately, so it won't get picked optimistically anymore //all_peers.remove( peer ); //remove from all_peers list, so it won't get picked optimistically anymore //TODO } } //update chokes for( Iterator it = unchokes.iterator(); it.hasNext(); ) { PEPeer peer = it.next(); if( !best_peers.contains( peer ) ) { //should be choked if( best_peers.size() < max_to_unchoke ) { //but there are still slots needed (no optimistics avail), so don't bother choking them best_peers.add( peer ); } else { chokes.add( peer ); it.remove(); } } } //update unchokes for( int i=0; i < best_peers.size(); i++ ) { PEPeer peer = best_peers.get( i ); if( !unchokes.contains( peer ) ) { unchokes.add( peer ); } } } public ArrayList getChokes() { ArrayList to_choke = chokes; chokes = new ArrayList(); return to_choke; } public ArrayList getUnchokes() { ArrayList to_unchoke = unchokes; unchokes = new ArrayList(); return to_unchoke; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/unchoker/UnchokerFactory.java0000644000175000017500000000365311244607062027562 0ustar adrianadrian/* * Created on Aug 24, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.peermanager.unchoker; import org.gudy.azureus2.core3.util.Debug; public class UnchokerFactory { public static final String DEFAULT_MANAGER = "com.aelitis.azureus.core.peermanager.unchoker.UnchokerFactory"; private static UnchokerFactory factory = getSingleton( null ); public static UnchokerFactory getSingleton() { return( factory ); } private static UnchokerFactory getSingleton( String explicit_implementation ) { String impl = explicit_implementation; if ( impl == null ){ impl = System.getProperty( DEFAULT_MANAGER ); } if ( impl == null ){ impl = DEFAULT_MANAGER; } try{ Class impl_class = UnchokerFactory.class.getClassLoader().loadClass( impl ); factory = (UnchokerFactory)impl_class.newInstance(); }catch( Throwable e ){ Debug.out( "Failed to instantiate unchoker factory '" + impl + "'", e ); factory = new UnchokerFactory(); } return( factory ); } public Unchoker getUnchoker( boolean seeding ) { if ( seeding ){ return( new SeedingUnchoker()); }else{ return( new DownloadingUnchoker()); } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/unchoker/SeedingUnchoker.java0000644000175000017500000002051611244607062027526 0ustar adrianadrian/* * Created on Apr 5, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.unchoker; import java.util.*; import org.gudy.azureus2.core3.peer.PEPeer; /** * Unchoker implementation to be used while in seeding mode. */ public class SeedingUnchoker implements Unchoker { private ArrayList chokes = new ArrayList(); private ArrayList unchokes = new ArrayList(); protected SeedingUnchoker() { /* nothing */ } public boolean isSeedingUnchoker() { return( true ); } public ArrayList getImmediateUnchokes( int max_to_unchoke, ArrayList all_peers ) { int peer_count = all_peers.size(); if ( max_to_unchoke > peer_count ){ max_to_unchoke = peer_count; } //count all the currently unchoked peers int num_unchoked = 0; for( int i=0; i < all_peers.size(); i++ ) { PEPeer peer = all_peers.get( i ); if( !peer.isChokedByMe() ) num_unchoked++; } //if not enough unchokes int needed = max_to_unchoke - num_unchoked; if ( needed > 0 ) { ArrayList to_unchoke = UnchokerUtil.getNextOptimisticPeers( all_peers, false, false, needed ); if ( to_unchoke == null ){ return( new ArrayList(0)); } for ( int i=0;i(0)); } } public void calculateUnchokes( int max_to_unchoke, ArrayList all_peers, boolean force_refresh, boolean check_priority_connections ) { int max_optimistic = ((max_to_unchoke - 1) / 5) + 1; //one optimistic unchoke for every 5 upload slots //get all the currently unchoked peers for( int i=0; i < all_peers.size(); i++ ) { PEPeer peer = all_peers.get( i ); if( !peer.isChokedByMe() ) { if( UnchokerUtil.isUnchokable( peer, false ) ) { unchokes.add( peer ); } else { //should be immediately choked chokes.add( peer ); } } } //if too many unchokes while( unchokes.size() > max_to_unchoke ) { chokes.add( unchokes.remove( unchokes.size() - 1 ) ); } //we only recalculate the uploads when we're forced to refresh the optimistic unchokes if( force_refresh ) { //we need to make room for new opt unchokes by finding the "worst" peers ArrayList peers_ordered_by_rate = new ArrayList(); ArrayList peers_ordered_by_uploaded = new ArrayList(); long[] rates = new long[ unchokes.size() ]; //0-initialized long[] uploaded = new long[ rates.length ]; //0-initialized //calculate factor rankings for( int i=0; i < unchokes.size(); i++ ) { PEPeer peer = unchokes.get( i ); long rate = peer.getStats().getDataSendRate(); if( rate > 256 ) { //filter out really slow peers //calculate reverse order by our upload rate to them UnchokerUtil.updateLargestValueFirstSort( rate, rates, peer, peers_ordered_by_rate, 0 ); //calculate order by the total number of bytes we've uploaded to them UnchokerUtil.updateLargestValueFirstSort( peer.getStats().getTotalDataBytesSent(), uploaded, peer, peers_ordered_by_uploaded, 0 ); } } Collections.reverse( peers_ordered_by_rate ); //we want higher rates at the end ArrayList peers_ordered_by_rank = new ArrayList(); long[] ranks = new long[ peers_ordered_by_rate.size() ]; Arrays.fill( ranks, Long.MIN_VALUE ); //combine factor rankings to get best for( int i=0; i < unchokes.size(); i++ ) { PEPeer peer = unchokes.get( i ); //"better" peers have high indexes (toward the end of each list) long rate_factor = peers_ordered_by_rate.indexOf( peer ); long uploaded_factor = peers_ordered_by_uploaded.indexOf( peer ); if( rate_factor == -1 ) continue; //wasn't downloading fast enough, skip add so it will be choked automatically long rank_factor = rate_factor + uploaded_factor; UnchokerUtil.updateLargestValueFirstSort( rank_factor, ranks, peer, peers_ordered_by_rank, 0 ); } //make space for new optimistic unchokes while( peers_ordered_by_rank.size() > max_to_unchoke - max_optimistic ) { peers_ordered_by_rank.remove( peers_ordered_by_rank.size() - 1 ); } //update choke list with drops and unchoke list with optimistic unchokes ArrayList to_unchoke = new ArrayList(); for( Iterator it = unchokes.iterator(); it.hasNext(); ) { PEPeer peer = it.next(); peer.setOptimisticUnchoke( false ); if( !peers_ordered_by_rank.contains( peer ) ) { //should be choked //we assume that any/all chokes are to be replace by optimistics PEPeer optimistic_peer = UnchokerUtil.getNextOptimisticPeer( all_peers, false, false ); if( optimistic_peer != null ) { //only choke if we've got a peer to replace it with chokes.add( peer ); it.remove(); to_unchoke.add( optimistic_peer ); optimistic_peer.setOptimisticUnchoke( true ); } } } for( int i=0; i < to_unchoke.size(); i++ ) { unchokes.add( to_unchoke.get( i ) ); } } if( check_priority_connections ) { //add Friend peers preferentially, leaving room for 1 non-friend peer for every 5 upload slots setBuddyUnchokes( max_to_unchoke - max_optimistic, all_peers ); } } private void setBuddyUnchokes( int max_buddies, ArrayList all_peers ) { if( unchokes.isEmpty() ) return; //don't bother trying to replace peers in an empty list ArrayList buddies = new ArrayList(); //find all buddies for( int i=0; i < all_peers.size(); i++ ) { PEPeer peer = all_peers.get( i ); if( peer.isPriorityConnection() && UnchokerUtil.isUnchokable( peer, true ) ) { buddies.add( peer ); } } //we want to give all connected friends an equal chance if there are more than max_friends allowed Collections.shuffle( buddies ); int num_unchoked = 0; int max = max_buddies > unchokes.size() ? unchokes.size() : max_buddies; while( num_unchoked < max && !buddies.isEmpty() ) { //go through unchoke list and replace non-buddy peers with buddy ones PEPeer peer = unchokes.remove( 0 ); //pop peer from front of unchoke list if( buddies.remove( peer ) ) { //peer is already in the buddy list unchokes.add( peer ); //so insert confirmed buddy peer back into list at the end } else { //not a buddy, so replace PEPeer buddy = buddies.remove( buddies.size() - 1 ); //get next buddy chokes.remove( buddy ); //just in case unchokes.add( buddy ); //add buddy to back of list } num_unchoked++; } } public ArrayList getChokes() { ArrayList to_choke = chokes; chokes = new ArrayList(); return to_choke; } public ArrayList getUnchokes() { ArrayList to_unchoke = unchokes; unchokes = new ArrayList(); return to_unchoke; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/PeerManager.java0000644000175000017500000005537011035717110025021 0ustar adrianadrian/* * Created on Jan 20, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerListener; import org.gudy.azureus2.core3.peer.PEPeerSource; import org.gudy.azureus2.core3.peer.impl.*; import org.gudy.azureus2.core3.peer.util.PeerIdentityManager; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.HashWrapper; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.networkmanager.*; import com.aelitis.azureus.core.networkmanager.impl.IncomingConnectionManager; import com.aelitis.azureus.core.networkmanager.impl.TransportHelper; import com.aelitis.azureus.core.peermanager.messaging.*; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.*; import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags; import com.aelitis.azureus.core.stats.AzureusCoreStats; import com.aelitis.azureus.core.stats.AzureusCoreStatsProvider; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.core.util.bloom.BloomFilterFactory; /** * */ public class PeerManager implements AzureusCoreStatsProvider{ private static final LogIDs LOGID = LogIDs.PEER; private static final PeerManager instance = new PeerManager(); private static final int PENDING_TIMEOUT = 10*1000; private static final AEMonitor timer_mon = new AEMonitor( "PeerManager:timeouts" ); private static AEThread2 timer_thread; private static Set timer_targets = new HashSet(); protected static void registerForTimeouts( PeerManagerRegistrationImpl reg ) { try{ timer_mon.enter(); timer_targets.add( reg ); if ( timer_thread == null ){ timer_thread = new AEThread2( "PeerManager:timeouts", true ) { public void run() { int idle_time = 0; while( true ){ try{ Thread.sleep( PENDING_TIMEOUT / 2 ); }catch( Throwable e ){ } try{ timer_mon.enter(); if ( timer_targets.size() == 0 ){ idle_time += PENDING_TIMEOUT / 2; if ( idle_time >= 30*1000 ){ timer_thread = null; break; } }else{ idle_time = 0; Iterator it = timer_targets.iterator(); while( it.hasNext()){ PeerManagerRegistrationImpl registration = (PeerManagerRegistrationImpl)it.next(); if ( !registration.timeoutCheck()){ it.remove(); } } } }finally{ timer_mon.exit(); } } } }; timer_thread.start(); } }finally{ timer_mon.exit(); } } /** * Get the singleton instance of the peer manager. * @return the peer manager */ public static PeerManager getSingleton() { return instance; } private final Map registered_legacy_managers = new HashMap(); private final Map registered_links = new HashMap(); private final ByteBuffer legacy_handshake_header; private final AEMonitor managers_mon = new AEMonitor( "PeerManager:managers" ); private PeerManager() { legacy_handshake_header = ByteBuffer.allocate( 20 ); legacy_handshake_header.put( (byte)BTHandshake.PROTOCOL.length() ); legacy_handshake_header.put( BTHandshake.PROTOCOL.getBytes() ); legacy_handshake_header.flip(); Set types = new HashSet(); types.add( AzureusCoreStats.ST_PEER_MANAGER_COUNT ); types.add( AzureusCoreStats.ST_PEER_MANAGER_PEER_COUNT ); types.add( AzureusCoreStats.ST_PEER_MANAGER_PEER_SNUBBED_COUNT ); types.add( AzureusCoreStats.ST_PEER_MANAGER_PEER_STALLED_DISK_COUNT ); AzureusCoreStats.registerProvider( types, this ); init(); } public void updateStats( Set types, Map values ) { if ( types.contains( AzureusCoreStats.ST_PEER_MANAGER_COUNT )){ values.put( AzureusCoreStats.ST_PEER_MANAGER_COUNT, new Long( registered_legacy_managers.size())); } if ( types.contains( AzureusCoreStats.ST_PEER_MANAGER_PEER_COUNT ) || types.contains( AzureusCoreStats.ST_PEER_MANAGER_PEER_SNUBBED_COUNT ) || types.contains( AzureusCoreStats.ST_PEER_MANAGER_PEER_STALLED_DISK_COUNT )){ long total_peers = 0; long total_snubbed_peers = 0; long total_stalled_pending_load = 0; try{ managers_mon.enter(); Iterator it = registered_legacy_managers.values().iterator(); while( it.hasNext()){ List registrations = (List)it.next(); Iterator it2 = registrations.iterator(); while( it2.hasNext()){ PeerManagerRegistrationImpl reg = (PeerManagerRegistrationImpl)it2.next(); PEPeerControl control = reg.getActiveControl(); if ( control != null ){ total_peers += control.getNbPeers(); total_snubbed_peers += control.getNbPeersSnubbed(); total_stalled_pending_load += control.getNbPeersStalledPendingLoad(); } } } }finally{ managers_mon.exit(); } if ( types.contains( AzureusCoreStats.ST_PEER_MANAGER_PEER_COUNT )){ values.put( AzureusCoreStats.ST_PEER_MANAGER_PEER_COUNT, new Long( total_peers )); } if ( types.contains( AzureusCoreStats.ST_PEER_MANAGER_PEER_SNUBBED_COUNT )){ values.put( AzureusCoreStats.ST_PEER_MANAGER_PEER_SNUBBED_COUNT, new Long( total_snubbed_peers )); } if ( types.contains( AzureusCoreStats.ST_PEER_MANAGER_PEER_STALLED_DISK_COUNT )){ values.put( AzureusCoreStats.ST_PEER_MANAGER_PEER_STALLED_DISK_COUNT, new Long( total_stalled_pending_load )); } } } protected void init() { MessageManager.getSingleton().initialize(); //ensure it gets initialized NetworkManager.ByteMatcher matcher = new NetworkManager.ByteMatcher() { public int matchThisSizeOrBigger(){ return( 48 );} public int maxSize() { return 48; } public int minSize() { return 20; } public Object matches( TransportHelper transport, ByteBuffer to_compare, int port ) { InetSocketAddress address = transport.getAddress(); int old_limit = to_compare.limit(); int old_position = to_compare.position(); to_compare.limit( old_position + 20 ); PeerManagerRegistrationImpl routing_data = null; if( to_compare.equals( legacy_handshake_header ) ) { //compare header to_compare.limit( old_position + 48 ); to_compare.position( old_position + 28 ); byte[] hash = new byte[to_compare.remaining()]; to_compare.get( hash ); try{ managers_mon.enter(); List registrations = (List)registered_legacy_managers.get( new HashWrapper( hash )); if ( registrations != null ){ routing_data = (PeerManagerRegistrationImpl)registrations.get(0); } }finally{ managers_mon.exit(); } } //restore buffer structure to_compare.limit( old_limit ); to_compare.position( old_position ); if ( routing_data != null ){ if ( !routing_data.isActive()){ if ( routing_data.isKnownSeed( address )){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Activation request from " + address + " denied as known seed" )); } routing_data = null; }else{ if ( !routing_data.getAdapter().activateRequest( address )){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Activation request from " + address + " denied by rules" )); } routing_data = null; } } } } return routing_data; } public Object minMatches( TransportHelper transport, ByteBuffer to_compare, int port ) { boolean matches = false; int old_limit = to_compare.limit(); int old_position = to_compare.position(); to_compare.limit( old_position + 20 ); if( to_compare.equals( legacy_handshake_header ) ) { matches = true; } //restore buffer structure to_compare.limit( old_limit ); to_compare.position( old_position ); return matches?"":null; } public byte[][] getSharedSecrets() { return( null ); // registered manually above } public int getSpecificPort() { return( -1 ); } }; // register for incoming connection routing NetworkManager.getSingleton().requestIncomingConnectionRouting( matcher, new NetworkManager.RoutingListener() { public void connectionRouted( NetworkConnection connection, Object routing_data ) { PeerManagerRegistrationImpl registration = (PeerManagerRegistrationImpl)routing_data; registration.route( connection, null ); } public boolean autoCryptoFallback() { return( false ); } }, new MessageStreamFactory() { public MessageStreamEncoder createEncoder() { return new BTMessageEncoder(); } public MessageStreamDecoder createDecoder() { return new BTMessageDecoder(); } }); } public PeerManagerRegistration manualMatchHash( InetSocketAddress address, byte[] hash ) { PeerManagerRegistrationImpl routing_data = null; try{ managers_mon.enter(); List registrations = (List)registered_legacy_managers.get( new HashWrapper( hash )); if ( registrations != null ){ routing_data = (PeerManagerRegistrationImpl)registrations.get(0); } }finally{ managers_mon.exit(); } if ( routing_data != null ){ if ( !routing_data.isActive()){ if ( routing_data.isKnownSeed( address )){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Activation request from " + address + " denied as known seed" )); } routing_data = null; }else{ if ( !routing_data.getAdapter().activateRequest( address )){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Activation request from " + address + " denied by rules" )); } routing_data = null; } } } } return routing_data; } public PeerManagerRegistration manualMatchLink( InetSocketAddress address, String link ) { byte[] hash; try{ managers_mon.enter(); PeerManagerRegistrationImpl registration = (PeerManagerRegistrationImpl)registered_links.get( link ); if ( registration == null ){ return( null ); } hash = registration.getHash(); }finally{ managers_mon.exit(); } return( manualMatchHash( address, hash )); } public void manualRoute( PeerManagerRegistration _registration, NetworkConnection _connection, PeerManagerRoutingListener _listener ) { PeerManagerRegistrationImpl registration = (PeerManagerRegistrationImpl)_registration; registration.route( _connection, _listener ); } public PeerManagerRegistration registerLegacyManager( HashWrapper hash, PeerManagerRegistrationAdapter adapter ) { try{ managers_mon.enter(); // normally we only get a max of 1 of these. However, due to DownloadManager crazyness // we can get an extra one when adding a download that already exists... List registrations = (List)registered_legacy_managers.get( hash ); byte[][] secrets = adapter.getSecrets(); if ( registrations == null ){ registrations = new ArrayList(1); registered_legacy_managers.put( hash, registrations ); IncomingConnectionManager.getSingleton().addSharedSecrets( secrets ); } PeerManagerRegistration registration = new PeerManagerRegistrationImpl( hash, adapter ); registrations.add( registration ); return( registration ); }finally{ managers_mon.exit(); } } private class PeerManagerRegistrationImpl implements PeerManagerRegistration { private HashWrapper hash; private PeerManagerRegistrationAdapter adapter; private PEPeerControl download; private volatile PEPeerControl active_control; private List pending_connections; private BloomFilter known_seeds; private Map links; protected PeerManagerRegistrationImpl( HashWrapper _hash, PeerManagerRegistrationAdapter _adapter ) { hash = _hash; adapter = _adapter; } protected PeerManagerRegistrationAdapter getAdapter() { return( adapter ); } protected byte[] getHash() { return( hash.getBytes() ); } public synchronized TOTorrentFile getLink( String target ) { if ( links == null ){ return( null ); } return((TOTorrentFile)links.get(target)); } public void addLink( String link, TOTorrentFile target ) throws Exception { try{ managers_mon.enter(); if ( registered_links.get( link ) != null ){ throw( new Exception( "Duplicate link '" + link + "'" )); } registered_links.put( link, this ); System.out.println( "Added link '" + link + "'" ); }finally{ managers_mon.exit(); } synchronized( this ){ if ( links == null ){ links = new HashMap(); } links.put( link, target ); } } public void removeLink( String link ) { try{ managers_mon.enter(); registered_links.remove( link ); }finally{ managers_mon.exit(); } synchronized( this ){ if ( links != null ){ links.remove( link ); } } } public boolean isActive() { return( active_control != null ); } public void activate( PEPeerControl _active_control ) { List connections = null; try{ managers_mon.enter(); active_control = _active_control; if ( download != null ){ Debug.out( "Already activated" ); } download = _active_control; connections = pending_connections; pending_connections = null; }finally{ managers_mon.exit(); } if ( connections != null ){ for (int i=0;i 10 ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Incoming connection from [" + connection + "] to " + adapter.getDescription() + " dropped too many pending activations" )); connection.close(); return; }else{ if ( pending_connections == null ){ pending_connections = new ArrayList(); } pending_connections.add( new Object[]{ connection, new Long( SystemTime.getCurrentTime()), listener }); if ( pending_connections.size() == 1 ){ register_for_timeouts = true; } } } }finally{ managers_mon.exit(); } // do this outside the monitor as the timeout code calls us back holding the timeout monitor // and we need to grab managers_mon inside this to run timeouts if ( register_for_timeouts ){ registerForTimeouts( this ); } if ( control != null ){ route( control, connection, false, listener ); } } protected boolean timeoutCheck() { try{ managers_mon.enter(); if ( pending_connections == null ){ return( false ); } Iterator it = pending_connections.iterator(); long now = SystemTime.getCurrentTime(); while( it.hasNext()){ Object[] entry = (Object[])it.next(); long start_time = ((Long)entry[1]).longValue(); if ( now < start_time ){ entry[1] = new Long( now ); }else if ( now - start_time > PENDING_TIMEOUT ){ it.remove(); NetworkConnection connection = (NetworkConnection)entry[0]; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Incoming connection from [" + connection + "] to " + adapter.getDescription() + " closed due to activation timeout" )); connection.close(); } } if ( pending_connections.size() == 0 ){ pending_connections = null; } return( pending_connections != null ); }finally{ managers_mon.exit(); } } protected void route( PEPeerControl control, final NetworkConnection connection, boolean is_activation, PeerManagerRoutingListener listener ) { // make sure not already connected to the same IP address; allow // loopback connects for co-located proxy-based connections and // testing String host_address = connection.getEndpoint().getNotionalAddress().getAddress().getHostAddress(); boolean same_allowed = COConfigurationManager.getBooleanParameter( "Allow Same IP Peers" ) || host_address.equals( "127.0.0.1" ); if( !same_allowed && PeerIdentityManager.containsIPAddress( control.getPeerIdentityDataID(), host_address ) ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Incoming connection from [" + connection + "] dropped as IP address already " + "connected for [" + control.getDisplayName() + "]")); connection.close(); return; } if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Incoming connection from [" + connection + "] routed to legacy download [" + control.getDisplayName() + "]")); PEPeerTransport pt = PEPeerTransportFactory.createTransport( control, PEPeerSource.PS_INCOMING, connection, null ); if ( listener != null ){ boolean ok = false; try{ if ( listener.routed( pt )){ ok = true; } }catch( Throwable e ){ Debug.printStackTrace(e); } if ( !ok ){ connection.close(); return; } } pt.start(); if ( is_activation ){ pt.addListener( new PEPeerListener() { public void stateChanged( PEPeer peer, int new_state ) { if ( new_state == PEPeer.CLOSING ){ if ( peer.isSeed()){ InetSocketAddress address = connection.getEndpoint().getNotionalAddress(); setKnownSeed( address ); // this is mainly to deal with seeds that incorrectly connect to us adapter.deactivateRequest( address ); } } } public void sentBadChunk(PEPeer peer, int piece_num, int total_bad_chunks ){} public void addAvailability(final PEPeer peer, final BitFlags peerHavePieces){} public void removeAvailability(final PEPeer peer, final BitFlags peerHavePieces){} }); } control.addPeerTransport( pt ); } public String getDescription() { PEPeerControl control = active_control; return( ByteFormatter.encodeString( hash.getBytes()) + ", control=" + (control==null?null:control.getDisplayName()) + ": " + adapter.getDescription()); } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/PeerManagerRoutingListener.java0000644000175000017500000000236010522570512030071 0ustar adrianadrian/* * Created on 3 Oct 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager; import org.gudy.azureus2.core3.peer.impl.PEPeerTransport; public interface PeerManagerRoutingListener { /** * Returns true if the routing has been accepted by the listener * @param peer * @return */ public boolean routed( PEPeerTransport peer ); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/piecepicker/0000755000175000017500000000000011310377630024246 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/piecepicker/PiecePickerFactory.java0000644000175000017500000000247010373051052030622 0ustar adrianadrian/* * Created by Joseph Bridgewater * Created on Jan 2, 2006 * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.piecepicker; import org.gudy.azureus2.core3.peer.impl.PEPeerControl; import com.aelitis.azureus.core.peermanager.piecepicker.impl.PiecePickerImpl; /** * @author MjrTom * */ public class PiecePickerFactory { public static PiecePicker create(PEPeerControl peer_control) { return new PiecePickerImpl(peer_control); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/piecepicker/impl/0000755000175000017500000000000011310377630025207 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/piecepicker/impl/PiecePickerImpl.java0000644000175000017500000023550311274472052031072 0ustar adrianadrian/* * Created by Joseph Bridgewater * Created on Jan 2, 2006 * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.piecepicker.impl; import java.util.*; import org.gudy.azureus2.core3.config.*; import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.disk.impl.DiskManagerFileInfoImpl; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceList; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceMap; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.peer.*; import org.gudy.azureus2.core3.peer.impl.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.control.PeerControlScheduler; import com.aelitis.azureus.core.peermanager.control.PeerControlSchedulerFactory; import com.aelitis.azureus.core.peermanager.control.SpeedTokenDispenser; import com.aelitis.azureus.core.peermanager.peerdb.PeerItem; import com.aelitis.azureus.core.peermanager.piecepicker.*; import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags; import com.aelitis.azureus.core.util.CopyOnWriteList; /** * @author MjrTom * */ public class PiecePickerImpl implements PiecePicker { private static final boolean LOG_RTA = false; private static final LogIDs LOGID = LogIDs.PIECES; /** min ms for recalculating availability - reducing this has serious ramifications */ private static final long TIME_MIN_AVAILABILITY =974; /** min ms for recalculating base priorities */ private static final long TIME_MIN_PRIORITIES =999; /** min ms for forced availability rebuild */ private static final long TIME_AVAIL_REBUILD =5*60*1000 -24; // The following are added to the base User setting based priorities (for all inspected pieces) /** user select prioritize first/last */ private static final int PRIORITY_W_FIRSTLAST =1300; /** min # pieces in file for first/last prioritization */ private static final long FIRST_PIECE_MIN_NB =4; /** number of pieces for first pieces prioritization */ // private static final int FIRST_PIECE_RANGE_PERCENT= 10; /** user sets file as "High" */ private static final int PRIORITY_W_FILE =1000; /** Additional boost for more completed High priority */ private static final int PRIORITY_W_COMPLETION =2000; // The following are only used when resuming already running pieces /** priority boost due to being too old */ private static final int PRIORITY_W_AGE =900; /** ms a block is expected to complete in */ private static final int PRIORITY_DW_AGE =60 *1000; /** ms since last write */ private static final int PRIORITY_DW_STALE =120 *1000; /** finish pieces already almost done */ private static final int PRIORITY_W_PIECE_DONE =900; /** keep working on same piece */ private static final int PRIORITY_W_SAME_PIECE =700; /** currently webseeds + other explicit priorities are around 10000 or more - at this point we ignore rarity */ private static final int PRIORITY_OVERRIDES_RAREST = 9000; private static final int PRIORITY_REQUEST_HINT = 3000; /** priority at and above which pieces require real-time scheduling */ private static final int PRIORITY_REALTIME = 9999999; /** Min number of requests sent to a peer */ private static final int REQUESTS_MIN =2; /** Max number of request sent to a peer */ private static final int REQUESTS_MAX =256; /** Default number of requests sent to a peer, (for each X B/s another request will be used) */ private static final int SLOPE_REQUESTS = 4*1024; private static final long RTA_END_GAME_MODE_SIZE_TRIGGER = 16 * DiskManager.BLOCK_SIZE; private static final long END_GAME_MODE_SIZE_TRIGGER = 20 * 1024*1024; private static final long END_GAME_MODE_TIMEOUT = 60 * END_GAME_MODE_SIZE_TRIGGER / DiskManager.BLOCK_SIZE; protected static volatile boolean firstPiecePriority =COConfigurationManager.getBooleanParameter("Prioritize First Piece" ); protected static volatile boolean completionPriority =COConfigurationManager.getBooleanParameter("Prioritize Most Completed Files"); /** event # of user settings controlling priority changes */ protected static volatile long paramPriorityChange =Long.MIN_VALUE; private static final int NO_REQUEST_BACKOFF_MAX_MILLIS = 5*1000; private static final int NO_REQUEST_BACKOFF_MAX_LOOPS = NO_REQUEST_BACKOFF_MAX_MILLIS / PeerControlScheduler.SCHEDULE_PERIOD_MILLIS; private static Random random = new Random(); private final DiskManager diskManager; private final PEPeerControl peerControl; private final DiskManagerListenerImpl diskManagerListener; protected final Map peerListeners; private final PEPeerManagerListener peerManagerListener; protected final int nbPieces; protected final DiskManagerPiece[] dmPieces; protected final PEPiece[] pePieces; private List rarestStartedPieces; //List of pieces started as rarest first protected final AEMonitor availabilityMon = new AEMonitor("PiecePicker:avail"); private final AEMonitor endGameModeChunks_mon =new AEMonitor("PiecePicker:EGM"); protected volatile int nbPiecesDone; /** asyncronously updated availability */ protected volatile int[] availabilityAsynch; /** indicates availability needs to be recomputed due to detected drift */ protected volatile long availabilityDrift; private long timeAvailRebuild =TIME_AVAIL_REBUILD; /** periodically updated consistent view of availability for calculating */ protected volatile int[] availability; private long time_last_avail; protected volatile long availabilityChange; private volatile long availabilityComputeChange; private long time_last_rebuild; private long timeAvailLessThanOne; private float globalAvail; private float globalAvgAvail; private int nbRarestActive; private int globalMin; private int globalMax; /** * The rarest availability level of pieces that we affirmatively want to try to request from others soonest * ie; our prime targets for requesting rarest pieces */ private volatile int globalMinOthers; /** event # of user file priority settings changes */ protected volatile long filePriorityChange; /** last user parameter settings event # when priority bases were calculated */ private volatile long priorityParamChange; /** last user priority event # when priority bases were calculated */ private volatile long priorityFileChange; /** last availability event # when priority bases were calculated */ private volatile long priorityAvailChange; private boolean priorityRTAexists; /** time that base priorities were last computed */ private long timeLastPriorities; /** the priority for starting each piece/base priority for resuming */ private int[] startPriorities; protected volatile boolean hasNeededUndonePiece; protected volatile long neededUndonePieceChange; /** A flag to indicate when we're in endgame mode */ private volatile boolean endGameMode; private volatile boolean endGameModeAbandoned; private volatile long timeEndGameModeEntered; /** The list of chunks needing to be downloaded (the mechanism change when entering end-game mode) */ private List endGameModeChunks; private long lastProviderRecalcTime; private CopyOnWriteList rta_providers = new CopyOnWriteList(); private long[] provider_piece_rtas; private CopyOnWriteList priority_providers = new CopyOnWriteList(); private long[] provider_piece_priorities; private int allocate_request_loop_count; private static boolean enable_request_hints; private static boolean includeLanPeersInReqLimiting; private CopyOnWriteList listeners = new CopyOnWriteList(); static { class ParameterListenerImpl implements ParameterListener { public final void parameterChanged(final String parameterName) { if (parameterName.equals("Prioritize Most Completed Files")) { completionPriority =COConfigurationManager.getBooleanParameter(parameterName); paramPriorityChange++; // this is a user's priority change event } else if (parameterName.equals("Prioritize First Piece")) { firstPiecePriority =COConfigurationManager.getBooleanParameter(parameterName); paramPriorityChange++; // this is a user's priority change event }else if ( parameterName.equals( "Piece Picker Request Hint Enabled" )){ enable_request_hints = COConfigurationManager.getBooleanParameter(parameterName); } includeLanPeersInReqLimiting = ! COConfigurationManager.getBooleanParameter("LAN Speed Enabled"); } } final ParameterListenerImpl parameterListener =new ParameterListenerImpl(); COConfigurationManager.addParameterListener("Prioritize Most Completed Files", parameterListener); COConfigurationManager.addAndFireParameterListener("Prioritize First Piece", parameterListener); COConfigurationManager.addAndFireParameterListener("Piece Picker Request Hint Enabled", parameterListener); COConfigurationManager.addAndFireParameterListener("LAN Speed Enabled", parameterListener); } public PiecePickerImpl(final PEPeerControl pc) { // class administration first peerControl = pc; diskManager = peerControl.getDiskManager(); dmPieces =diskManager.getPieces(); nbPieces =diskManager.getNbPieces(); nbPiecesDone =0; pePieces = pc.getPieces(); // now do stuff related to availability availability =new int[nbPieces]; //always needed hasNeededUndonePiece =false; neededUndonePieceChange =Long.MIN_VALUE; // ensure all periodic calculaters perform operations at least once time_last_avail =Long.MIN_VALUE; availabilityChange =Long.MIN_VALUE +1; availabilityComputeChange =Long.MIN_VALUE; availabilityDrift =nbPieces; // initialize each piece; on going changes will use event driven tracking for (int i =0; i =time_last_avail &&now 0 || now < time_last_rebuild || (now - time_last_rebuild) > timeAvailRebuild){ try { availabilityMon.enter(); time_last_rebuild = now; final int[] new_availability = recomputeAvailability(); if (Constants.isCVSVersion()) { final int[] old_availability =availabilityAsynch ==null ?availability :availabilityAsynch; int errors = 0; for (int i=0;i0 &&errors !=nbPieces) { if (Logger.isEnabled()) Logger.log(new LogEvent(peerControl, LOGID, LogEvent.LT_ERROR, "updateAvailability(): availability rebuild errors = " +errors +" timeAvailRebuild =" +timeAvailRebuild )); timeAvailRebuild -=errors; } else timeAvailRebuild++; } availabilityAsynch = new_availability; availabilityDrift =0; availabilityChange++; } finally {availabilityMon.exit();} }else if (availabilityComputeChange >=availabilityChange){ return; } try { availabilityMon.enter(); time_last_avail =now; availabilityComputeChange =availabilityChange; // take a snapshot of availabilityAsynch if ( availabilityAsynch != null ){ availability = availabilityAsynch; availabilityAsynch = null; } } finally {availabilityMon.exit();} int i; int allMin =Integer.MAX_VALUE; int allMax =0; int rarestMin =Integer.MAX_VALUE; for (i =0; i 0 &&avail allMax) allMax =avail; } // copy updated local variables into globals globalMin =allMin; globalMax =allMax; globalMinOthers =rarestMin; int total =0; int rarestActive =0; long totalAvail =0; for (i =0; i 0) { if (avail >allMin) total++; if (avail <=rarestMin &&dmPiece.isDownloadable() && pePiece != null && !pePiece.isRequested()) rarestActive++; totalAvail +=avail; } } // copy updated local variables into globals float newGlobalAvail = (total /(float) nbPieces) +allMin; if ( globalAvail >= 1.0 && newGlobalAvail < 1.0 ){ timeAvailLessThanOne = now; }else if ( newGlobalAvail >= 1.0 ){ timeAvailLessThanOne= 0; } globalAvail = newGlobalAvail; nbRarestActive =rarestActive; globalAvgAvail =totalAvail /(float)(nbPieces) /(1 +peerControl.getNbSeeds() +peerControl.getNbPeers()); } private final int[] recomputeAvailability() { if (availabilityDrift >0 &&availabilityDrift !=nbPieces &&Logger.isEnabled()) Logger.log(new LogEvent(diskManager.getTorrent(), LOGID, LogEvent.LT_INFORMATION, "Recomputing availabiliy. Drift="+availabilityDrift+":"+peerControl.getDisplayName())); final List peers =peerControl.getPeers(); final int[] newAvailability = new int[nbPieces]; int j; int i; // first our pieces for (j =0; j 0) { for (j =peerHavePieces.start; j <=peerHavePieces.end; j++) { if (peerHavePieces.flags[j]) ++newAvailability[j]; } } } } return newAvailability; } public int getNumberOfPieces() { return( nbPieces ); } public final int[] getAvailability() { return availability; } public final int getAvailability(final int pieceNumber) { return availability[pieceNumber]; } //this only gets called when the My Torrents view is displayed public final float getMinAvailability() { return globalAvail; } public final long getAvailWentBadTime() { return(timeAvailLessThanOne); } public final int getMaxAvailability() { return globalMax; } public final float getAvgAvail() { return globalAvgAvail; } public int getNbPiecesDone() { return nbPiecesDone; } /** * Early-outs when finds a downloadable piece * Either way sets hasNeededUndonePiece and neededUndonePieceChange if necessary */ protected final void checkDownloadablePiece() { for (int i =0; i 0) toReturn = 1; if(toReturn == 0 && stats1.getTotalDataBytesReceived() == 0 && stats2.getTotalDataBytesReceived() > 0) toReturn = -1; /* // still nothing, next try peers from which we have downloaded most in the past // NO, we don't want to focus on what may have become a bad peer if(toReturn == 0) toReturn = (int)(stats2.getTotalDataBytesReceived() - stats1.getTotalDataBytesReceived()); */ return toReturn; } }); final int uploadersSize =bestUploaders.size(); if ( uploadersSize ==0 ){ // no usable peers, bail out early return; } boolean done_priorities = false; if ( priorityRTAexists ){ final Map[] peer_randomiser = { null }; // to keep the ordering consistent we need to use a fixed metric unless // we remove + re-add a peer, at which point we need to take account of // the fact that it has a new request allocated final Map block_time_order_peers_metrics = new HashMap( uploadersSize ); Set block_time_order_peers = new TreeSet( new Comparator() { public int compare( Object arg1, Object arg2) { PEPeerTransport pt1 = (PEPeerTransport)arg1; PEPeerTransport pt2 = (PEPeerTransport)arg2; Integer m1 = (Integer)block_time_order_peers_metrics.get( pt1 ); if ( m1 == null ){ m1 = new Integer( getNextBlockETAFromNow( pt1 )); block_time_order_peers_metrics.put( pt1, m1 ); } Integer m2 = (Integer)block_time_order_peers_metrics.get( pt2 ); if ( m2 == null ){ m2 = new Integer( getNextBlockETAFromNow( pt2 )); block_time_order_peers_metrics.put( pt2, m2 ); } int result = m1.intValue() - m2.intValue(); if ( result == 0 ){ Map pr = peer_randomiser[0]; if ( pr == null ){ pr = peer_randomiser[0] = new LightHashMap( bestUploaders.size()); } Integer r_1 = (Integer)pr.get( pt1 ); if ( r_1 == null ){ r_1 = new Integer(random.nextInt()); pr.put( pt1, r_1 ); } Integer r_2 = (Integer)pr.get( pt2 ); if ( r_2 == null ){ r_2 = new Integer(random.nextInt()); pr.put( pt2, r_2 ); } result = r_1.intValue() - r_2.intValue(); if ( result == 0 ){ result = pt1.hashCode() - pt2.hashCode(); if ( result == 0 ){ // v unlikely - inconsistent but better than losing a peer result = 1; } } } return( result ); } }); block_time_order_peers.addAll( bestUploaders ); PEPeerTransport best_uploader = (PEPeerTransport)bestUploaders.get(0); long best_block_eta = SystemTime.getCurrentTime() + getNextBlockETAFromNow( best_uploader ); // give priority pieces the first look-in // we need to sort by how quickly the peer can get a block, not just its base speed boolean allocated_request = true; Set allocations_started = new HashSet(); try{ while( allocated_request && priorityRTAexists ){ allocated_request = false; while( !block_time_order_peers.isEmpty()){ Iterator it = block_time_order_peers.iterator(); PEPeerTransport pt =(PEPeerTransport)it.next(); it.remove(); if ( !pt.isDownloadPossible() || pt.isSnubbed()){ continue; } // ignore request number advice from peers in RTA mode, we gotta do what we can int maxRequests = REQUESTS_MIN +(int)( pt.getStats().getDataReceiveRate() /SLOPE_REQUESTS ) + 1; if ( maxRequests > REQUESTS_MAX || maxRequests < 0 ){ maxRequests = REQUESTS_MAX; } int currentRequests = pt.getNbRequests(); int allowed_requests = maxRequests - currentRequests; if ( allowed_requests > 0 ){ if ( !done_priorities ){ done_priorities = true; computeBasePriorities(); if ( !priorityRTAexists ){ // might have stopped RTA as this is calculated in computeBasePriorities break; } } if ( !allocations_started.contains( pt )){ pt.requestAllocationStarts( startPriorities ); allocations_started.add( pt ); } if ( findRTAPieceToDownload( pt, pt == best_uploader, best_block_eta )){ // add back in to see if we can allocate a further request if ( allowed_requests > 1 ){ block_time_order_peers_metrics.remove( pt ); block_time_order_peers.add( pt ); } } } } } }finally{ Iterator it = allocations_started.iterator(); while( it.hasNext()){ ((PEPeerTransport)it.next()).requestAllocationComplete(); } } } checkEndGameMode(); //dispenser.refill(); for (int i =0; i REQUESTS_MAX ||maxRequests <0) maxRequests =REQUESTS_MAX; }else{ maxRequests =2; } }else{ maxRequests =1; } } // Only loop when 3/5 of the queue is empty, in order to make more consecutive requests, // and improve cache efficiency if ( pt.getNbRequests() <=(maxRequests *3) /5){ //if ( pt.getNbRequests() <= maxRequests){ // System.out.println("\treqesting from peer; speed:"+pt.getStats().getDataReceiveRate()+" outstanding requests:"+pt.getNbRequests()+" max:"+maxRequests); if ( !done_priorities ){ done_priorities = true; computeBasePriorities(); } int total_allocated = 0; try{ boolean peer_managing_requests = pt.requestAllocationStarts( startPriorities ); while ( pt.isDownloadPossible() && pt.getNbRequests() < maxRequests ){ // is there anything else to download? int allocated; if ( peer_managing_requests || !endGameMode ){ allocated = findPieceToDownload(pt, maxRequests ); }else{ allocated = findPieceInEndGameMode(pt, maxRequests); } if ( allocated == 0 ) break; else total_allocated += allocated; } }finally{ pt.requestAllocationComplete(); } if ( total_allocated == 0 ){ // there are various reasons that we might not allocate any requests to a peer // such as them not having any pieces we're interested in. Keep track of the // number of consecutive "no requests" outcomes so we can reduce the scheduling // frequency of such peers int no_req_count = pt.getConsecutiveNoRequestCount(); if ( no_req_count < NO_REQUEST_BACKOFF_MAX_LOOPS ){ pt.setConsecutiveNoRequestCount( no_req_count + 2 ); } // System.out.println( pt.getIp() + ": nb=" + pt.getNbRequests() + ",max=" + maxRequests + ",nrc=" + no_req_count +",loop=" + allocate_request_loop_count); }else{ pt.setConsecutiveNoRequestCount( 0 ); } } } } } protected int getNextBlockETAFromNow( PEPeerTransport pt ) { long upRate = pt.getStats().getDataReceiveRate(); if ( upRate < 1 ){ upRate = 1; } int next_block_bytes = ( pt.getNbRequests() + 1 ) * DiskManager.BLOCK_SIZE; return((int)(( next_block_bytes * 1000 )/ upRate)); } /** * Count current global min avail pieces in progress * (not counting non-rarest pieces but keep them to compensate high churn, remove completed ones, ignore idle ones) * @return number of pieces that may be started due to the "rarest first" picking rule */ private int calcRarestAllowed() { // initial adjustment depending on swarm needs int RarestAllowed = 1; if (globalMinOthers < 20) {RarestAllowed = 2;} if (globalMinOthers < 8) {RarestAllowed = 3;} if (globalMinOthers < 4) {RarestAllowed = 4;} //avoid rarest start until we have finished some pieces to share if(nbPiecesDone < 4 ) {RarestAllowed = 0;} // avoid rarest start during startup (high churn, inaccurate data) if(SystemTime.getCurrentTime()-peerControl.getTimeStarted() < 180*1000) {RarestAllowed = 0;} // more churn avoidance if(rarestStartedPieces.size() > RarestAllowed+2) {RarestAllowed = 0;} //decrement number of allowed rarest by already running rarest pieces PEPiece rarestStarted; for (int i=0;i globalMin ) && ( SystemTime.getCurrentTime()-rarestStarted.getLastDownloadTime(SystemTime.getCurrentTime()) < 60*1000 || rarestStarted.getNbWritten() == 0 ) && !rarestStarted.isDownloaded() ) RarestAllowed--; } return RarestAllowed; } /** This computes the base priority for all pieces that need requesting if there's * been any availability change or user priority setting changes since the last * call, which will be most of the time since availability changes so dynamicaly * It will change startPriorities[] (unless there was nothing to do) */ private final void computeBasePriorities() { final long now =SystemTime.getCurrentTime(); if ( now < lastProviderRecalcTime || now - lastProviderRecalcTime > 1000 ){ lastProviderRecalcTime = now; priorityRTAexists = computeProviderPriorities(); } if ( !priorityRTAexists ){ if (startPriorities !=null &&((now >timeLastPriorities &&now =paramPriorityChange &&priorityFileChange >=filePriorityChange &&priorityAvailChange >=availabilityChange))) return; // *somehow* nothing changed, so nothing to do } // store the latest change indicators before we start making dependent calculations so that a // further change while computing stuff doesn't get lost timeLastPriorities =now; priorityParamChange =paramPriorityChange; priorityFileChange =filePriorityChange; priorityAvailChange =availabilityChange; boolean foundPieceToDownload =false; final int[] newPriorities =new int[nbPieces]; // locals are a tiny bit faster final boolean firstPiecePriorityL =firstPiecePriority; final boolean completionPriorityL =completionPriority; final DMPieceMap pieceMap = diskManager.getPieceMap(); try { final boolean rarestOverride = calcRarestAllowed() < 1; // calculate all base (starting) priorities for all pieces needing requesting final int nbConnects =peerControl.getNbPeers() +peerControl.getNbSeeds(); for (int i =0; i 0 &&downloaded FIRST_PIECE_MIN_NB) { /* backed out for the moment - reverting to old first/last piece only int lastFirstPiece = fileInfo.getFirstPieceNumber() + FIRST_PIECE_RANGE_PERCENT * (fileInfo.getLastPieceNumber() - fileInfo.getFirstPieceNumber()) / 100; if ( (i >=fileInfo.getFirstPieceNumber() && i<= lastFirstPiece ) ) { priority +=PRIORITY_W_FIRSTLAST + 10 * (lastFirstPiece - i) ; } if( i ==fileInfo.getLastPieceNumber() ) { priority +=PRIORITY_W_FIRSTLAST; } */ if (i == fileInfo.getFirstPieceNumber() ||i == fileInfo.getLastPieceNumber()) priority +=PRIORITY_W_FIRSTLAST; } // if the file is high-priority // startPriority +=(1000 *fileInfo.getPriority()) /255; if (fileInfo.isPriority()) { priority +=PRIORITY_W_FILE; if (completionPriorityL) { final long percent =(1000 *downloaded) /length; if (percent >=900) priority +=(PRIORITY_W_COMPLETION *downloaded) /diskManager.getTotalLength(); } } if (priority >startPriority) startPriority =priority; } } if (startPriority >=0) { dmPiece.setNeeded(); foundPieceToDownload =true; final int avail =availability[i]; // nbconnects is async calculate so may be wrong - make sure we don't decrease pri by accident if (avail >0 && nbConnects > avail ) { // boost priority for rarity startPriority +=nbConnects -avail; // startPriority +=(PRIORITY_W_RARE +peerControl.getNbPeers()) /avail; // Boost priority even a little more if it's a globally rarest piece if (!rarestOverride &&avail <=globalMinOthers) startPriority +=nbConnects /avail; } if ( provider_piece_rtas != null ){ if ( provider_piece_rtas[i] > 0 ){ startPriority = PRIORITY_REALTIME; } }else if ( provider_piece_priorities != null ){ startPriority += provider_piece_priorities[i]; } }else{ dmPiece.clearNeeded(); } newPriorities[i] =startPriority; } } catch (Throwable e) { Debug.printStackTrace(e); } if (foundPieceToDownload !=hasNeededUndonePiece) { hasNeededUndonePiece =foundPieceToDownload; neededUndonePieceChange++; } startPriorities =newPriorities; } private final boolean isRarestOverride() { final int nbSeeds =peerControl.getNbSeeds(); final int nbPeers =peerControl.getNbPeers(); final int nbMost =(nbPeers >nbSeeds ?nbPeers :nbSeeds); final int nbActive =peerControl.getNbActivePieces(); // Dont seek rarest under a few circumstances, so that other factors work better // never seek rarest when bootstrapping torrent boolean rarestOverride =nbPiecesDone <4 ||endGameMode ||(globalMinOthers >1 &&(nbRarestActive >=nbMost ||nbActive >=nbMost)); if (!rarestOverride &&nbRarestActive >1 &&globalMinOthers >1) { // if already getting some rarest, dont get more if swarm is healthy or too many pieces running rarestOverride =globalMinOthers >globalMin ||(globalMinOthers >=(2 *nbSeeds) &&(2 *globalMinOthers) >=nbPeers); // Interest in Rarest pieces (compared to user priority settings) could be influenced by several factors; // less demand closer to 0% and 100% of torrent completion/farther from 50% of torrent completion // less demand closer to 0% and 100% of peers interestd in us/farther from 50% of peers interested in us // less demand the more pieces are in progress (compared to swarm size) // less demand the farther ahead from absolute global minimum we're at already // less demand the healthier a swarm is (rarity compared to # seeds and # peers) } return rarestOverride; } private final SpeedTokenDispenser dispenser = PeerControlSchedulerFactory.getSingleton(0).getSpeedTokenDispenser(); /** * @param pt the PEPeerTransport we're working on * @return int # of blocks that were requested (0 if no requests were made) */ protected final int findPieceToDownload(PEPeerTransport pt, int nbWanted) { final int pieceNumber =getRequestCandidate(pt); if (pieceNumber <0) { // probaly should have found something since chose to try; probably not interested anymore // (or maybe Needed but not Done pieces are otherwise not requestable) // pt.checkInterested(); return 0; } int peerSpeed =(int) pt.getStats().getDataReceiveRate() /1000; if(peerSpeed < 0) peerSpeed = 0; if(pt.isSnubbed()) peerSpeed = 0; final PEPiece pePiece; if (pePieces[pieceNumber] != null) pePiece = pePieces[pieceNumber]; else { //create piece manually int[] peer_priority_offsets = pt.getPriorityOffsets(); int this_offset = peer_priority_offsets==null?0:peer_priority_offsets[pieceNumber]; //create piece manually pePiece =new PEPieceImpl(pt.getManager(), dmPieces[pieceNumber], peerSpeed >>1); // Assign the created piece to the pieces array. peerControl.addPiece(pePiece, pieceNumber); if (startPriorities !=null){ pePiece.setResumePriority(startPriorities[pieceNumber] + this_offset); }else{ pePiece.setResumePriority( this_offset ); } if (availability[pieceNumber] <=globalMinOthers) nbRarestActive++; } if(!pt.isLANLocal() || includeLanPeersInReqLimiting) nbWanted = dispenser.dispense(nbWanted, DiskManager.BLOCK_SIZE); final int[] blocksFound =pePiece.getAndMarkBlocks(pt, nbWanted,enable_request_hints ); final int blockNumber =blocksFound[0]; final int nbBlocks =blocksFound[1]; if((!pt.isLANLocal() || includeLanPeersInReqLimiting) && nbBlocks != nbWanted) dispenser.returnUnusedChunks(nbWanted-nbBlocks, DiskManager.BLOCK_SIZE); if (nbBlocks <=0) return 0; int requested =0; // really try to send the request to the peer for (int i =0; i 0 && pePiece.getAvailability() <= globalMinOthers && calcRarestAllowed() > 0 && !rarestStartedPieces.contains(pePiece) ) rarestStartedPieces.add(pePiece); return requested; } protected final boolean findRTAPieceToDownload( PEPeerTransport pt, boolean best_uploader, long best_uploader_next_block_eta ) { if ( pt == null || pt.getPeerState() != PEPeer.TRANSFERING ){ return( false ); } final BitFlags peerHavePieces =pt.getAvailable(); if ( peerHavePieces ==null || peerHavePieces.nbSet <=0 ){ return( false ); } String rta_log_str = LOG_RTA?pt.getIp():null; try{ final int peerSpeed =(int) pt.getStats().getDataReceiveRate() /1024; // how many KB/s has the peer has been sending final int startI = peerHavePieces.start; final int endI = peerHavePieces.end; int piece_min_rta_index = -1; int piece_min_rta_block = 0; long piece_min_rta_time = Long.MAX_VALUE; long now = SystemTime.getCurrentTime(); long my_next_block_eta = now + getNextBlockETAFromNow( pt ); for ( int i=startI; i <=endI; i++){ long piece_rta = provider_piece_rtas[i]; if ( peerHavePieces.flags[i] && startPriorities[i] == PRIORITY_REALTIME && piece_rta > 0 ){ final DiskManagerPiece dmPiece =dmPieces[i]; if ( !dmPiece.isDownloadable()){ continue; } final PEPiece pePiece = pePieces[i]; if ( pePiece != null && pePiece.isDownloaded()){ continue; } Object realtime_data = null; boolean try_allocate_even_though_late = my_next_block_eta > piece_rta && best_uploader_next_block_eta > piece_rta; if ( piece_rta >= piece_min_rta_time ){ // piece is less urgent than an already found one }else if ( my_next_block_eta > piece_rta && !( best_uploader || best_uploader_next_block_eta > piece_rta )){ // only allocate if we have a chance of getting this block in time or we're // the best uploader we've got/even the best uploader can't get it // the second part is important for when we get to the point whereby no peers // can get a block in time. Here we need to allocate someone to get it as // otherwise we'll concentrate on getting lower priority pieces that we can // get in time and leave the stuck ones for just the best uploader to get }else if ( pePiece == null || ( realtime_data = pePiece.getRealTimeData()) == null ){ if ( LOG_RTA ) rta_log_str += "{alloc_new=" + i + ",time=" + (piece_rta-now)+"}"; // no real-time block allocated yet piece_min_rta_time = piece_rta; piece_min_rta_index = i; }else{ RealTimeData rtd = (RealTimeData)realtime_data; // check the blocks to see if any are now lagging behind their ETA given current peer speed List[] peer_requests = rtd.getRequests(); for (int j=0;j piece_rta && ( best_uploader || !try_allocate_even_though_late )){ // don't re-allocate when we're already running late as we'll end up // with a lot of discard if ( LOG_RTA ) rta_log_str += "{lagging=" + i + ",block=" + j+ ",time=" + ( best_eta - piece_rta) + "}"; // if we can do better than existing best effort allocate if ( my_next_block_eta < best_eta ){ if ( LOG_RTA ) rta_log_str += "{taking over, time=" + ( best_eta - my_next_block_eta) + "}"; piece_min_rta_time = piece_rta; piece_min_rta_index = i; piece_min_rta_block = j; break; // earlier blocks always have priority } } } } } } } if ( piece_min_rta_index != -1 ){ if ( LOG_RTA ) rta_log_str += ",{select_piece=" + piece_min_rta_index + ",block=" + piece_min_rta_block + ",time=" + (piece_min_rta_time-now) + "}"; if ( dispenser.dispense(1, DiskManager.BLOCK_SIZE) == 1 || (pt.isLANLocal() && !includeLanPeersInReqLimiting)){ PEPiece pePiece = pePieces[piece_min_rta_index]; if ( pePiece == null ){ // create piece manually pePiece = new PEPieceImpl( pt.getManager(), dmPieces[piece_min_rta_index], peerSpeed >>1 ); // Assign the created piece to the pieces array. peerControl.addPiece(pePiece, piece_min_rta_index); pePiece.setResumePriority( PRIORITY_REALTIME ); if ( availability[piece_min_rta_index] <=globalMinOthers ){ nbRarestActive++; } } RealTimeData rtd = (RealTimeData)pePiece.getRealTimeData(); if ( rtd == null ){ rtd = new RealTimeData( pePiece ); pePiece.setRealTimeData( rtd ); } pePiece.getAndMarkBlock( pt, piece_min_rta_block ); DiskManagerReadRequest request = pt.request(piece_min_rta_index, piece_min_rta_block *DiskManager.BLOCK_SIZE, pePiece.getBlockSize(piece_min_rta_block)); if ( request != null ){ List real_time_requests = rtd.getRequests()[piece_min_rta_block]; real_time_requests.add( new RealTimePeerRequest( pt, request )); pt.setLastPiece(piece_min_rta_index); pePiece.setLastRequestedPeerSpeed( peerSpeed ); return( true ); }else{ if ( LOG_RTA ) rta_log_str += "{request failed}"; if(!pt.isLANLocal() || includeLanPeersInReqLimiting) dispenser.returnUnusedChunks(1, DiskManager.BLOCK_SIZE); return( false ); } }else{ if ( LOG_RTA ) rta_log_str += "{dispenser denied}"; return( false ); } }else{ if ( LOG_RTA ) rta_log_str += "{no piece found}"; return( false ); } }finally{ if ( LOG_RTA ){ System.out.println( rta_log_str ); } } } /** * This method is the downloading core. It decides, for a given peer, * which block should be requested. Here is the overall algorithm : * 0. If there a FORCED_PIECE or reserved piece, that will be started/resumed if possible * 1. Scan all the active pieces and find the rarest piece (and highest priority among equally rarest) * that can possibly be continued by this peer, if any * 2. While scanning the active pieces, develop a list of equally highest priority pieces * (and equally rarest among those) as candidates for starting a new piece * 3. If it can't find any piece, this means all pieces are * already downloaded/full requested * 4. Returns int[] pieceNumber, blockNumber if a request to be made is found, * or null if none could be found * @param pc PEPeerTransport to work with * * @return int with pieceNumberto be requested or -1 if no request could be found */ private final int getRequestCandidate(final PEPeerTransport pt ) { if (pt ==null ||pt.getPeerState() !=PEPeer.TRANSFERING) return -1; final BitFlags peerHavePieces =pt.getAvailable(); if (peerHavePieces ==null ||peerHavePieces.nbSet <=0) return -1; // piece number and its block number that we'll try to DL int reservedPieceNumber = pt.getReservedPieceNumber(); // If there's a piece seserved to this peer resume it and only it (if possible) if ( reservedPieceNumber >=0 ){ PEPiece pePiece = pePieces[reservedPieceNumber]; if ( pePiece != null ){ String peerReserved = pePiece.getReservedBy(); if ( peerReserved != null && peerReserved.equals( pt.getIp())){ if ( peerHavePieces.flags[reservedPieceNumber] &&pePiece.isRequestable()){ return reservedPieceNumber; } } } // reserved piece is no longer valid, dump it pt.setReservedPieceNumber(-1); // clear the reservation if the piece is still allocated to the peer if ( pePiece != null ) { String peerReserved = pePiece.getReservedBy(); if ( peerReserved != null ) { if ( peerReserved.equals(pt.getIp())) { pePiece.setReservedBy( null ); } } } // note, pieces reserved to peers that get disconnected are released in pepeercontrol reservedPieceNumber = -1; } final int peerSpeed =(int) pt.getStats().getDataReceiveRate() /1024; // how many KB/s has the peer has been sending final int lastPiece =pt.getLastPiece(); //final boolean rarestOverride = calcRarestAllowed() > 0; final int nbSnubbed =peerControl.getNbPeersSnubbed(); long resumeMinAvail =Long.MAX_VALUE; int resumeMaxPriority =Integer.MIN_VALUE; boolean resumeIsRarest = false; // can the peer continuea piece with lowest avail of all pieces we want int secondChoiceResume = -1; BitFlags startCandidates =null; int startMaxPriority =Integer.MIN_VALUE; int startMinAvail =Integer.MAX_VALUE; boolean startIsRarest =false; boolean forceStart=false; int priority; // aggregate priority of piece under inspection (start priority or resume priority for pieces to be resumed) int avail =0; // the swarm-wide availability level of the piece under inspection long pieceAge; // how long since the PEPiece first started downloading (requesting, actually) final boolean rarestAllowed = calcRarestAllowed() > 0; final int startI =peerHavePieces.start; final int endI =peerHavePieces.end; int i; final int[] peerPriorities = pt.getPriorityOffsets(); final long now =SystemTime.getCurrentTime(); int[] request_hint = pt.getRequestHint(); int request_hint_piece_number; if ( request_hint != null ){ request_hint_piece_number = request_hint[0]; if ( dmPieces[request_hint_piece_number].isDone()){ pt.clearRequestHint(); request_hint_piece_number = -1; } }else{ request_hint_piece_number = -1; } // Try to continue a piece already loaded, according to priority for (i =startI; i <=endI; i++) { // is the piece available from this peer? if (peerHavePieces.flags[i]) { priority =startPriorities[i]; final DiskManagerPiece dmPiece =dmPieces[i]; if ( priority >=0 && dmPiece.isDownloadable()) { if ( peerPriorities != null ) priority += peerPriorities[i]; if ( enable_request_hints && i == request_hint_piece_number ) { priority += PRIORITY_REQUEST_HINT; PEPiece pePiece = pePieces[i]; if ( pePiece == null ){ forceStart = true; }else{ if ( reservedPieceNumber != i ){ pePiece.setReservedBy( pt.getIp()); pt.setReservedPieceNumber( i ); } } } final PEPiece pePiece = pePieces[i]; // if we are considering realtime pieces then don't bother with non-realtime ones if ( pePiece == null || pePiece.isRequestable()) { // if this priority exceeds the priority-override threshold then we override rarity boolean pieceRarestOverride = priority>=PRIORITY_OVERRIDES_RAREST?true:rarestAllowed; // piece is: Needed, not fully: Requested, Downloaded, Written, hash-Checking or Done avail =availability[i]; if (avail ==0) { // maybe we didn't know we could get it before availability[i] =1; // but the peer says s/he has it avail =1; } // is the piece active if (pePiece !=null) { if ( priority != startPriorities[i]) pePiece.setResumePriority( priority ); // maintained for display purposes only boolean startedRarest = rarestStartedPieces.contains(pePiece); boolean rarestPrio = avail <=globalMinOthers && ( startedRarest || rarestAllowed); // How many requests can still be made on this piece? final int freeReqs =pePiece.getNbUnrequested(); if (freeReqs <=0) { pePiece.setRequested(); continue; } // Don't touch pieces reserved for others final String peerReserved =pePiece.getReservedBy(); if (peerReserved !=null) { if (!peerReserved.equals(pt.getIp())) continue; //reserved to somebody else // the peer forgot this is reserved to him; re-associate it pt.setReservedPieceNumber(i); return i; } int pieceSpeed =pePiece.getSpeed(); // ### Piece/Peer speed checks boolean mayResume = true; if(pt.isSnubbed()) { // snubbed peers shouldn't stall fast pieces under ANY condition // may lead to trouble when the snubbed peer is the only seed, needs further testing mayResume &= pieceSpeed < 1; mayResume &= freeReqs > 2 || avail <= nbSnubbed; } else { // slower peers are allowed as long as there is enough free room mayResume &= freeReqs*peerSpeed >= pieceSpeed/2; //|| rarestPrio; // prevent non-subbed peers from resuming on snubbed-peer-pieces but still allow them to resume stalled pieces mayResume &= peerSpeed < 2 || pieceSpeed > 0 || pePiece.getNbRequests() == 0; mayResume |= i == pt.getLastPiece(); } // find a fallback piece in case the peer could theoretically contribute // to an existing piece but is prevented by the snubbing rules etc. // this will prevent unecessary piece starting if(secondChoiceResume == -1 || avail > availability[secondChoiceResume]) secondChoiceResume = i; if(!mayResume) continue; if (avail > resumeMinAvail) continue; priority +=pieceSpeed; priority +=(i ==lastPiece) ?PRIORITY_W_SAME_PIECE :0; // Adjust priority for purpose of continuing pieces // how long since last written to (if written to) priority +=pePiece.getTimeSinceLastActivity() /PRIORITY_DW_STALE; // how long since piece was started pieceAge =now -pePiece.getCreationTime(); if (pieceAge >0) priority +=PRIORITY_W_AGE *pieceAge /(PRIORITY_DW_AGE *dmPiece.getNbBlocks()); // how much is already written to disk priority +=(PRIORITY_W_PIECE_DONE *dmPiece.getNbWritten()) /dmPiece.getNbBlocks(); pePiece.setResumePriority(priority); // this is only for display if (avail < resumeMinAvail || (avail == resumeMinAvail && priority > resumeMaxPriority)) { // this piece seems like best choice for resuming // Verify it's still possible to get a block to request from this piece if (pePiece.hasUnrequestedBlock()) { // change the different variables to reflect interest in this block reservedPieceNumber = i; resumeMinAvail =avail; resumeMaxPriority = priority; resumeMinAvail = avail; resumeIsRarest = rarestPrio; } } } else if (avail <=globalMinOthers && rarestAllowed) { // rarest pieces only from now on if (!startIsRarest) { // 1st rarest piece if (startCandidates ==null) startCandidates =new BitFlags(nbPieces); startMaxPriority =priority; startMinAvail =avail; startIsRarest =avail <=globalMinOthers; startCandidates.setOnly(i); // clear the non-rarest bits in favor of only rarest } else if (priority >startMaxPriority) { // continuing rarest, higher priority level if (startCandidates ==null) startCandidates =new BitFlags(nbPieces); startMaxPriority =priority; startCandidates.setOnly(i); } else if (priority ==startMaxPriority) { // continuing rares, same priority level startCandidates.setEnd(i); } } else if (!startIsRarest ||!rarestAllowed) { // not doing rarest pieces if (priority >startMaxPriority) { // new priority level if (startCandidates ==null) startCandidates =new BitFlags(nbPieces); startMaxPriority =priority; startMinAvail =avail; startIsRarest =avail <=globalMinOthers; startCandidates.setOnly(i); } else if (priority ==startMaxPriority) { // continuing same priority level if (avail 1) return pieceNumber; */ if ( !forceStart || startCandidates ==null ||startCandidates.nbSet <=0 ){ // can & should or must resume a piece? if (reservedPieceNumber >=0 &&(resumeIsRarest ||!startIsRarest || !rarestAllowed || startCandidates ==null ||startCandidates.nbSet <=0)) return reservedPieceNumber; if(secondChoiceResume != -1 && (startCandidates ==null ||startCandidates.nbSet <=0)) { //System.out.println("second choice resume:"+secondChoiceResume); return secondChoiceResume; } // this would allow more non-rarest pieces to be resumed so they get completed so they can be re-shared, // which can make us intersting to more peers, and generally improve the speed of the swarm, // however, it can sometimes be hard to get the rarest pieces, such as when a holder unchokes very infrequently // 20060312[MjrTom] this can lead to TOO many active pieces, so do the extra check with arbitrary # of active pieces final boolean resumeIsBetter; if (reservedPieceNumber >=0 &&globalMinOthers >0 &&peerControl.getNbActivePieces() >32) // check at arbitrary figure of 32 pieces { resumeIsBetter =(resumeMaxPriority /resumeMinAvail) >(startMaxPriority /globalMinOthers); if (Constants.isCVSVersion() &&Logger.isEnabled()) Logger.log(new LogEvent(new Object[] {pt, peerControl}, LOGID, "Start/resume choice; piece #:" +reservedPieceNumber +" resumeIsBetter:" +resumeIsBetter +" globalMinOthers=" +globalMinOthers +" startMaxPriority=" +startMaxPriority +" startMinAvail=" +startMinAvail +" resumeMaxPriority=" +resumeMaxPriority +" resumeMinAvail=" +resumeMinAvail +" : " +pt)); if (resumeIsBetter) return reservedPieceNumber; } } // start a new piece; select piece from start candidates bitfield return getPieceToStart(startCandidates); } /** * @param startCandidates BitFlags of potential candidates to choose from * @return int the piece number that was chosen to be started. Note it's possible for * the chosen piece to have been started already (by another thread). * This method considers that potential to not be relevant. */ protected final int getPieceToStart(final BitFlags startCandidates) { if (startCandidates ==null ||startCandidates.nbSet <=0) return -1; if (startCandidates.nbSet ==1) return startCandidates.start; final int direction =RandomUtils.generateRandomPlusMinus1(); final int startI; if (direction ==1) startI =startCandidates.start; else startI =startCandidates.end; // randomly select a bit flag to be the one final int targetNb =RandomUtils.generateRandomIntUpto(startCandidates.nbSet); // figure out the piece number of that selected bitflag int foundNb =-1; for (int i =startI; i <=startCandidates.end &&i >=startCandidates.start; i +=direction) { // is piece flagged if (startCandidates.flags[i]) { foundNb++; if (foundNb >=targetNb) return i; } } return -1; } public final boolean hasDownloadablePiece() { return hasNeededUndonePiece; } public final long getNeededUndonePieceChange() { return neededUndonePieceChange; } private final void checkEndGameMode() { if (peerControl.getNbSeeds() +peerControl.getNbPeers() <3){ return; } final long now =SystemTime.getCurrentTime(); if (endGameMode ||endGameModeAbandoned){ if (!endGameModeAbandoned){ if (now -timeEndGameModeEntered >END_GAME_MODE_TIMEOUT){ abandonEndGameMode(); } } return; } int active_pieces =0; for (int i =0; i 0; long remaining = active_pieces * diskManager.getPieceLength(); long trigger = use_rta_egm?RTA_END_GAME_MODE_SIZE_TRIGGER:END_GAME_MODE_SIZE_TRIGGER; // only flip into end-game mode if < trigger size left if ( remaining <= trigger ){ try{ endGameModeChunks_mon.enter(); endGameModeChunks =new ArrayList(); timeEndGameModeEntered =now; endGameMode =true; computeEndGameModeChunks(); if (Logger.isEnabled()) Logger.log(new LogEvent(diskManager.getTorrent(), LOGID, "Entering end-game mode: " +peerControl.getDisplayName())); // System.out.println("End-Game Mode activated"); }finally{ endGameModeChunks_mon.exit(); } } } private final void computeEndGameModeChunks() { try{ endGameModeChunks_mon.enter(); for (int i =0; i 0){ final int random =RandomUtils.generateRandomIntUpto(nbChunks); final EndGameModeChunk chunk =(EndGameModeChunk) endGameModeChunks.get(random); final int pieceNumber =chunk.getPieceNumber(); if (dmPieces[pieceNumber].isWritten(chunk.getBlockNumber())){ endGameModeChunks.remove(chunk); return 0; } final PEPiece pePiece = pePieces[pieceNumber]; if ( pt.isPieceAvailable(pieceNumber) &&pePiece != null &&(!pt.isSnubbed() ||availability[pieceNumber] <=peerControl.getNbPeersSnubbed()) &&pt.request(pieceNumber, chunk.getOffset(), chunk.getLength()) != null ){ pePiece.setRequested(pt, chunk.getBlockNumber()); pt.setLastPiece(pieceNumber); return 1; } } // we're here because there are no endgame mode chunks left // either the torrent is done or something unusual happened // cleanup anyway and allow a proper re-entry into endgame mode if neccessary leaveEndGameMode(); }finally{ endGameModeChunks_mon.exit(); } return 0; } public final void removeFromEndGameModeChunks( final int pieceNumber, final int offset ) { if (!endGameMode){ return; } try{ endGameModeChunks_mon.enter(); final Iterator iter =endGameModeChunks.iterator(); while (iter.hasNext()){ EndGameModeChunk chunk =(EndGameModeChunk) iter.next(); if ( chunk.equals(pieceNumber, offset)){ iter.remove(); } } }finally{ endGameModeChunks_mon.exit(); } } public final void clearEndGameChunks() { if ( !endGameMode ){ return; } try{ endGameModeChunks_mon.enter(); endGameModeChunks.clear(); endGameMode = false; }finally{ endGameModeChunks_mon.exit(); } } protected void leaveEndGameMode() { try{ endGameModeChunks_mon.enter(); if ( endGameMode ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(diskManager.getTorrent(), LOGID, "Leaving end-game mode: " +peerControl.getDisplayName())); } endGameMode = false; endGameModeChunks.clear(); timeEndGameModeEntered = 0; } }finally{ endGameModeChunks_mon.exit(); } } protected void abandonEndGameMode() { if ( !endGameModeAbandoned ){ try{ endGameModeChunks_mon.enter(); endGameModeAbandoned = true; endGameMode = false; clearEndGameChunks(); if (Logger.isEnabled()) Logger.log(new LogEvent(diskManager.getTorrent(), LOGID, "Abandoning end-game mode: " +peerControl.getDisplayName())); }finally{ endGameModeChunks_mon.exit(); } } } private boolean computeProviderPriorities() { List p_ps = priority_providers.getList(); if ( p_ps.size() == 0 ){ if ( provider_piece_priorities != null ){ paramPriorityChange++; provider_piece_priorities = null; } }else{ paramPriorityChange++; provider_piece_priorities = new long[nbPieces]; for (int i=0;i 0 ){ if ( provider_piece_rtas[j] == 0 ){ provider_piece_rtas[j] = rta; }else{ provider_piece_rtas[j] = Math.min( provider_piece_rtas[j], rta ); } has_rta = true; } } } return( has_rta ); } } public void addRTAProvider( PieceRTAProvider provider ) { rta_providers.add( provider ); Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((PiecePickerListener)it.next()).providerAdded( provider ); }catch( Throwable e ){ Debug.printStackTrace(e); } } // we don't want end-game mode kicking in and screwing with the RTA logic // at the end of the download. simplest way is to abandon it for this // download. if someone gives up RT later then the download will just complete // without EGM leaveEndGameMode(); } public void removeRTAProvider( PieceRTAProvider provider ) { rta_providers.remove( provider ); Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((PiecePickerListener)it.next()).providerRemoved( provider ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } public List getRTAProviders() { return( rta_providers.getList()); } public void addPriorityProvider( PiecePriorityProvider provider ) { priority_providers.add( provider ); Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((PiecePickerListener)it.next()).providerAdded( provider ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } public void removePriorityProvider( PiecePriorityProvider provider ) { priority_providers.remove( provider ); Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((PiecePickerListener)it.next()).providerRemoved( provider ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } public List getPriorityProviders() { return( rta_providers.getList()); } public void addListener( PiecePickerListener listener ) { listeners.add( listener ); Iterator it = rta_providers.iterator(); while( it.hasNext()){ listener.providerAdded((PieceRTAProvider)it.next()); } } public void removeListener( PiecePickerListener listener ) { listeners.remove( listener ); } /** * An instance of this listener is registered with peerControl * Through this, we learn of peers joining and leaving * and attach/detach listeners to them */ private class PEPeerManagerListenerImpl implements PEPeerManagerListener { public final void peerAdded(final PEPeerManager manager, PEPeer peer ) { PEPeerListenerImpl peerListener; peerListener =(PEPeerListenerImpl)peerListeners.get(peer); if (peerListener ==null) { peerListener =new PEPeerListenerImpl(); peerListeners.put(peer, peerListener); } peer.addListener(peerListener); } public final void peerRemoved(final PEPeerManager manager, PEPeer peer) { // remove this listener from list of listeners and from the peer final PEPeerListenerImpl peerListener =(PEPeerListenerImpl)peerListeners.remove(peer); peer.removeListener(peerListener); } public void peerDiscovered(PEPeerManager manager, PeerItem peer, PEPeer finder) { } public void peerSentBadData( PEPeerManager manager, PEPeer peer, int pieceNumber) { } public void destroyed() { } } /** * An instance of this listener is registered with each peer */ private class PEPeerListenerImpl implements PEPeerListener { public final void stateChanged(PEPeer peer, final int newState) { /* switch (newState) { case PEPeer.CONNECTING: return; case PEPeer.HANDSHAKING: return; case PEPeer.TRANSFERING: return; case PEPeer.CLOSING: return; case PEPeer.DISCONNECTED: return; } */ } public final void sentBadChunk(final PEPeer peer, final int piece_num, final int total_bad_chunks ) { /* nothing to do here */ } public final void addAvailability(final PEPeer peer, final BitFlags peerHavePieces) { if (peerHavePieces ==null ||peerHavePieces.nbSet <=0) return; try { availabilityMon.enter(); if ( availabilityAsynch == null ){ availabilityAsynch = (int[])availability.clone(); } for (int i =peerHavePieces.start; i <=peerHavePieces.end; i++) { if ( peerHavePieces.flags[i] ){ ++availabilityAsynch[i]; } } availabilityChange++; } finally {availabilityMon.exit();} } /** * Takes away the given pieces from global availability * @param PEPeer peer this is about * @param peerHasPieces BitFlags of the pieces */ public final void removeAvailability(final PEPeer peer, final BitFlags peerHavePieces) { if (peerHavePieces ==null ||peerHavePieces.nbSet <=0) return; try { availabilityMon.enter(); if (availabilityAsynch ==null) { availabilityAsynch = (int[])availability.clone(); } for (int i =peerHavePieces.start; i <=peerHavePieces.end; i++) { if (peerHavePieces.flags[i]) { if (availabilityAsynch[i] >(dmPieces[i].isDone() ?1 :0)) --availabilityAsynch[i]; else availabilityDrift++; } } availabilityChange++; } finally {availabilityMon.exit();} } } /** * An instance of this listener is registered with peerControl * @author MjrTom */ private class DiskManagerListenerImpl implements DiskManagerListener { public final void stateChanged(int oldState, int newState) { //starting torrent } public final void filePriorityChanged(DiskManagerFileInfo file) { // record that user-based priorities changed filePriorityChange++; // this is a user's priority change event // only need to re-calc Needed on file's pieces; priority is calculated seperatly boolean foundPieceToDownload =false; // if didn't have anything to do before, now only need to check if we need // to DL from this file, but if had something to do before, // must rescan all pieces to see if now nothing to do final int startI; final int endI; if (hasNeededUndonePiece) { startI =0; endI =nbPieces; } else { startI =file.getFirstPieceNumber(); endI =file.getLastPieceNumber() +1; } for (int i =startI; i =nbPieces) checkDownloadablePiece(); }else { try { availabilityMon.enter(); if ( availabilityAsynch == null ){ availabilityAsynch = (int[])availability.clone(); } if (availabilityAsynch[pieceNumber] >0) --availabilityAsynch[pieceNumber]; else availabilityDrift++; availabilityChange++; } finally {availabilityMon.exit();} nbPiecesDone--; if (dmPiece.calcNeeded() &&!hasNeededUndonePiece) { hasNeededUndonePiece =true; neededUndonePieceChange++; } } } public final void fileAccessModeChanged(DiskManagerFileInfo file, int old_mode, int new_mode) { //file done (write to read) //starting to upload from the file (read to write) } } public void destroy() { } public String getPieceString( int piece_number ) { String str; long priority = startPriorities==null?0:startPriorities[piece_number]; if ( priority == PRIORITY_REALTIME ){ long[] rta = provider_piece_rtas; str = "pri=rta:" + (rta==null?"?":("" + (rta[piece_number] - SystemTime.getCurrentTime()))); }else{ str = "pri=" + priority; } long[] exts = provider_piece_priorities; if ( exts != null ){ str += ",ext=" + exts[piece_number]; } return( str ); } public void generateEvidence( IndentWriter writer ) { writer.println( "Piece Picker" ); try{ writer.indent(); writer.println( "globalAvail: " + globalAvail ); writer.println( "globalAvgAvail: " + globalAvgAvail ); writer.println( "nbRarestActive: " + nbRarestActive ); writer.println( "globalMin: " + globalMin ); writer.println( "globalMinOthers: " + globalMinOthers ); writer.println( "hasNeededUndonePiece: " + hasNeededUndonePiece ); writer.println( "endGameMode: " + endGameMode ); writer.println( "endGameModeAbandoned: " + endGameModeAbandoned ); writer.println( "endGameModeChunks: " + endGameModeChunks ); }finally{ writer.exdent(); } } protected class RealTimeData { private List[] peer_requests; protected RealTimeData( PEPiece piece ) { int nb = piece.getNbBlocks(); peer_requests = new List[nb]; for (int i=0;ii) start =i; if (end 0 &&other.nbSet >0) { // setup outer union bounds int i =this.start >other.start ?this.start :other.start; final int endI =this.end 0; last_ver_num_index--) { if (peer_id.charAt(last_ver_num_index) != '-') {break;} } // For each digit in the version string, check it is a valid version identifier. char c; for (int i=1; i<=last_ver_num_index; i++) { c = peer_id.charAt(i); if (c == '-') {return false;} if (decodeAlphaNumericChar(c) == null) {return false;} } return true; } public static boolean isMainlineStyle(String peer_id) { /** * One of the following styles will be used: * Mx-y-z-- * Mx-yy-z- */ return peer_id.charAt(2) == '-' && peer_id.charAt(7) == '-' && ( peer_id.charAt(4) == '-' || peer_id.charAt(5) == '-'); } public static boolean isPossibleSpoofClient(String peer_id) { return peer_id.endsWith("UDP0") || peer_id.endsWith("HTTPBT"); } public static String getMainlineStyleVersionNumber(String peer_id) { boolean two_digit_in_middle = peer_id.charAt(5) == '-'; String middle_part = decodeNumericChar(peer_id.charAt(3)); if (two_digit_in_middle) { middle_part = join(middle_part, decodeNumericChar(peer_id.charAt(4))); } return joinAsDotted( decodeNumericChar(peer_id.charAt(1)), middle_part, decodeNumericChar(peer_id.charAt(two_digit_in_middle ? 6 : 5)) ); } public static String getShadowStyleVersionNumber(String peer_id) { String ver_number = decodeAlphaNumericChar(peer_id.charAt(1)); if (ver_number == null) {return null;} for (int i=2; i<6 && ver_number != null; i++) { char c = peer_id.charAt(i); if (c == '-') {break;} ver_number = joinAsDotted(ver_number, decodeAlphaNumericChar(peer_id.charAt(i))); } // We'll strip off trailing redundant zeroes. while (ver_number.endsWith(".0")) {ver_number = ver_number.substring(0, ver_number.length()-2);} return ver_number; } public static String decodeAzStyleVersionNumber(String version_data, String version_scheme) { char a = version_data.charAt(0); char b = version_data.charAt(1); char c = version_data.charAt(2); char d = version_data.charAt(3); /** * Specialness for Transmission - thanks to BentMyWookie for the information, * I'm sure he'll be reading this comment anyway... ;) */ if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_TRANSMISSION_STYLE) { // Very old client style: -TR0006- is 0.6. if (version_data.startsWith("000")) { version_scheme = "3.4"; } // Previous client style: -TR0072- is 0.72. else if (version_data.startsWith("00")) { version_scheme = BTPeerIDByteDecoderDefinitions.VER_AZ_SKIP_FIRST_ONE_MAJ_TWO_MIN; } // Current client style: -TR072Z- is 0.72 (Dev). else { version_scheme = BTPeerIDByteDecoderDefinitions.VER_AZ_ONE_MAJ_TWO_MIN_PLUS_MNEMONIC; } } if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_FOUR_DIGITS) { return intchar(a) + "." + intchar(b) + "." + intchar(c) + "." + intchar(d); } else if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_THREE_DIGITS || version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_THREE_DIGITS_PLUS_MNEMONIC || version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_ONE_MAJ_TWO_MIN_PLUS_MNEMONIC) { String result; if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_ONE_MAJ_TWO_MIN_PLUS_MNEMONIC) { result = intchar(a) + "." + intchar(b) + intchar(c); } else { result = intchar(a) + "." + intchar(b) + "." + intchar(c); } if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_THREE_DIGITS_PLUS_MNEMONIC || version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_ONE_MAJ_TWO_MIN_PLUS_MNEMONIC) { String mnemonic = decodeMnemonic(d); if (mnemonic != null) {result += " " + mnemonic;} } return result; } else if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_TWO_MAJ_TWO_MIN) { return (a == '0' ? "" : intchar(a)) + intchar(b) + "." + intchar(c) + intchar(d); } else if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_LAST_THREE_DIGITS) { return intchar(b) + "." + intchar(c) + "." + intchar(d); } else if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_THREE_ALPHANUMERIC_DIGITS) { return decodeAlphaNumericChar(a) + "." + decodeAlphaNumericChar(b) + "." + decodeAlphaNumericChar(c); } else if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_SKIP_FIRST_ONE_MAJ_TWO_MIN) { return intchar(b) + "." + intchar(c) + intchar(d); } else if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_KTORRENT_STYLE) { // Either something like this: // 1.2 RC 4 [where 3 == 'R') // 1.2 Dev [where 3 == 'D') // 1.2 [where 3 doesn't equal the above] switch (c) { case 'R': return intchar(a) + "." + intchar(b) + " RC" + intchar(d); case 'D': return intchar(a) + "." + intchar(b) + " Dev"; default: return intchar(a) + "." + intchar(b); } } else if (version_scheme.equals("1.234")) { return intchar(a) + "." + intchar(b) + intchar(c) + intchar(d); } else if (version_scheme.equals("1.2(34)")) { return intchar(a) + "." + intchar(b) + "(" + intchar(c) + intchar(d) + ")"; } else if (version_scheme.equals("1.2.34")) { return intchar(a) + "." + intchar(b) + "." + intchar(c) + intchar(d); } else if (version_scheme.equals("v1234")) { return "v" + intchar(a) + intchar(b) + intchar(c) + intchar(d); } else if (version_scheme.equals("1.2")) { return intchar(a) + "." + intchar(b); } else if (version_scheme.equals("3.4")) { return intchar(c) + "." + intchar(d); } else if (version_scheme.equals("12.3-4")) { return decodeAlphaNumericChar(a) + decodeAlphaNumericChar(b) + "." + decodeAlphaNumericChar(c) + "-" + decodeAlphaNumericChar(d); } else { throw new RuntimeException("unknown AZ style version number scheme - " + version_scheme); } } public static String getTwoByteThreePartVersion(byte b1, byte b2) { String min_part = decodeNumericValueOfByte(b2, 2); return joinAsDotted(decodeNumericValueOfByte(b1), min_part.substring(0, 1), min_part.substring(1, 2)); } /** * Look at the peer ID and just grab as many readable characters to form the version * substring as possible. */ public static String extractReadableVersionSubstringFromPeerID(String peer_id) { for (int i=0; i>... if (Character.isLetter(c)) continue; if (Character.isDigit(c)) continue; if (c == '.') continue; // Must be delimiter character. return peer_id.substring(0, i); } return peer_id; } public static String decodeCustomVersionNumber(String version_data, String version_scheme) { if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_BLOCK) { return version_data; } else if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_DOTTED_BLOCK || version_scheme == BTPeerIDByteDecoderDefinitions.VER_BYTE_BLOCK_DOTTED_CHAR) { int inc_size = (version_scheme == BTPeerIDByteDecoderDefinitions.VER_DOTTED_BLOCK) ? 2 : 1; String result = version_data.substring(0, 1); for (int i=0+inc_size; i data.max_counts ) { //we've potentially reached our count limit long cutoff = now - data.time_limit; //prune out any expired counts for( Iterator it = data.counts.iterator(); it.hasNext(); ) { long time = ((Long)it.next()).longValue(); if( time < cutoff ) { //this count is older than the limit allows it.remove(); //drop it } else { //still within limit break; } } if( data.counts.size() > data.max_counts ) { //too many counts within the time limit return false; //return error } } return true; } private static class CountData { private final int max_counts; private final int time_limit; private final LinkedList counts = new LinkedList(); private CountData( int max_counts, int time_limit ) { this.max_counts = max_counts; this.time_limit = time_limit; } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderDefinitions.java0000644000175000017500000004576511271030566031653 0ustar adrianadrian/* * Created on 7 Jun 2007 * Created by Allan Crooks * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.core.peermanager.utils; import java.util.ArrayList; import java.util.HashMap; import org.gudy.azureus2.core3.internat.MessageText; public class BTPeerIDByteDecoderDefinitions { // Az style two byte code identifiers to real client name. private static HashMap az_style_code_map = new HashMap(); private static HashMap az_client_version_map = new HashMap(); // Shadow's style one byte code identifiers to real client name. private static HashMap shadow_style_code_map = new HashMap(); private static HashMap shadow_client_version_map = new HashMap(); // Mainline's new style uses one byte code identifiers too. private static HashMap mainline_style_code_map = new HashMap(); /** * List of objects which describes clients with their own custom * naming scheme. */ private static ArrayList custom_style_client_list = new ArrayList(); // Version number formats. static String VER_AZ_THREE_DIGITS = "1.2.3"; static String VER_AZ_THREE_DIGITS_PLUS_MNEMONIC = "1.2.3 [4]"; static String VER_AZ_ONE_MAJ_TWO_MIN_PLUS_MNEMONIC = "1.23 [4]"; static String VER_AZ_FOUR_DIGITS = "1.2.3.4"; static String VER_AZ_TWO_MAJ_TWO_MIN = "12.34"; static String VER_AZ_SKIP_FIRST_ONE_MAJ_TWO_MIN = "2.34"; static String VER_AZ_KTORRENT_STYLE = "1.2.3=[RD].4"; static String VER_AZ_TRANSMISSION_STYLE = "transmission"; static String VER_AZ_LAST_THREE_DIGITS = "2.3.4"; static String VER_AZ_THREE_ALPHANUMERIC_DIGITS = "2.33.4"; // So 'B' = 11, for example, like Shadow's style of numbering. // These are used to describe how the version number is extracted from the // peer ID as well as how that version number is formatted. static String VER_BLOCK = "abcde"; // Is given as a block in the peer ID, we show the same block static String VER_DOTTED_BLOCK = "a.b.c.d.e"; // Is given as a dotted block in the peer ID, we show the block in the same dotted format. static String VER_BYTE_BLOCK_DOTTED_CHAR = "abcde -> a.b.c.d.e"; // Is given a block in the peer ID, but should be displayed in a dotted format. static String VER_BITS_ON_WHEELS = "BOW-STYLE"; static String VER_TWO_BYTE_THREE_PART = "ab -> a . b/10 . b%10"; static String NO_VERSION = "NO_VERSION"; // Used to register client information. private static void addAzStyle(String id, String client) { addAzStyle(id, client, VER_AZ_FOUR_DIGITS); } private static void addAzStyle(String id, String client, String version_style) { if (id.length() != 2) {throw new RuntimeException("not two chars long - " + id);} az_style_code_map.put(id, client); az_client_version_map.put(client, version_style); } private static void addShadowStyle(char id, String client) { addShadowStyle(id, client, VER_AZ_THREE_DIGITS); } private static void addShadowStyle(char id, String client, String version_style) { shadow_style_code_map.put("" + id, client); shadow_client_version_map.put(client, version_style); } private static void addMainlineStyle(char id, String client) { mainline_style_code_map.put("" + id, client); } private static ClientData addSimpleClient(String client_name, String identifier) { return addSimpleClient(client_name, identifier, 0); } private static ClientData addSimpleClient(String client_name, String identifier, int position) { ClientData result = new ClientData(client_name, identifier, position); custom_style_client_list.add(result); return result; } private static void addVersionedClient(ClientData client, String version_type, int length) { addVersionedClient(client, version_type, length, null); } private static void addVersionedClient(ClientData client, String version_type, int length, String format) { addVersionedClient(client, version_type, length, format, client.simple_string.length() + client.simple_string_pos); } private static void addVersionedClient(ClientData client, String version_type, int length, int version_pos) { addVersionedClient(client, version_type, length, null, version_pos); } private static void addVersionedClient(ClientData client, String version_type, int length, String format, int version_pos) { client.version_data = new VersionNumberData(version_type, length, format, version_pos); } public static String getAzStyleClientName(String peer_id) { return (String)az_style_code_map.get(peer_id.substring(1, 3)); } public static String getShadowStyleClientName(String peer_id) { return (String)shadow_style_code_map.get(peer_id.substring(0, 1)); } public static String getMainlineStyleClientName(String peer_id) { return (String)mainline_style_code_map.get(peer_id.substring(0, 1)); } public static String getAzStyleClientVersion(String client_name, String peer_id) { String version_scheme = (String)az_client_version_map.get(client_name); if (version_scheme == NO_VERSION) {return null;} try { return client_name + " " + BTPeerIDByteDecoderUtils.decodeAzStyleVersionNumber( peer_id.substring(3, 7), version_scheme ); } catch (Exception e) { BTPeerIDByteDecoder.logUnknownClient(peer_id); return null; } } public static ClientData getSubstringStyleClient(String peer_id) { ClientData cd = null; for (int i=0; i= 3.6 addAzStyle("SS", "SwarmScope"); addAzStyle("ST", "SymTorrent", "2.34"); addAzStyle("st", "SharkTorrent"); addAzStyle("SZ", "Shareaza"); addAzStyle("TN", "Torrent.NET"); addAzStyle("TR", "Transmission", VER_AZ_TRANSMISSION_STYLE); addAzStyle("TS", "TorrentStorm"); addAzStyle("TT", "TuoTu", VER_AZ_THREE_DIGITS); addAzStyle("UL", "uLeecher!"); addAzStyle("UT", "\u00B5Torrent", VER_AZ_THREE_DIGITS_PLUS_MNEMONIC); addAzStyle("UM", "\u00B5Torrent Mac", VER_AZ_THREE_DIGITS_PLUS_MNEMONIC); addAzStyle("WT", "Bitlet"); addAzStyle("WY", "FireTorrent"); // formerly Wyzo. addAzStyle("VG", "\u54c7\u560E (Vagaa)", VER_AZ_FOUR_DIGITS); addAzStyle("XL", "\u8FC5\u96F7\u5728\u7EBF (Xunlei)"); // Apparently, the English name of the client is "Thunderbolt". addAzStyle("XT", "XanTorrent"); addAzStyle("XX", "XTorrent", "1.2.34"); addAzStyle("XC", "XTorrent", "1.2.34"); addAzStyle("ZT", "ZipTorrent"); addShadowStyle('A', "ABC"); addShadowStyle('O', "Osprey Permaseed"); addShadowStyle('Q', "BTQueue"); addShadowStyle('R', "Tribler"); addShadowStyle('S', "Shad0w"); addShadowStyle('T', "BitTornado"); addShadowStyle('U', "UPnP NAT"); addMainlineStyle('M', "Mainline"); addMainlineStyle('Q', "Queen Bee"); // Simple clients with no version number. addSimpleClient("\u00B5Torrent 1.7.0 RC", "-UT170-"); // http://forum.utorrent.com/viewtopic.php?pid=260927#p260927 addSimpleClient("Azureus 1", "Azureus"); addSimpleClient("Azureus 2.0.3.2", "Azureus", 5); addSimpleClient("Aria 2", "-aria2-"); addSimpleClient("BitTorrent Plus! II", "PRC.P---"); addSimpleClient("BitTorrent Plus!", "P87.P---"); addSimpleClient("BitTorrent Plus!", "S587Plus"); addSimpleClient("BitTyrant (Azureus Mod)", "AZ2500BT"); addSimpleClient("Blizzard Downloader", "BLZ"); addSimpleClient("BTGetit", "BG", 10); addSimpleClient("BTugaXP", "btuga"); addSimpleClient("BTugaXP", "BTuga", 5); addSimpleClient("BTugaXP", "oernu"); addSimpleClient("Deadman Walking", "BTDWV-"); addSimpleClient("Deadman", "Deadman Walking-"); addSimpleClient("External Webseed", "Ext"); addSimpleClient("G3 Torrent", "-G3"); addSimpleClient("GreedBT 2.7.1", "271-"); addSimpleClient("Hurricane Electric", "arclight"); addSimpleClient("HTTP Seed", "-WS" ); // used internally to denote incoming webseed connections addSimpleClient("JVtorrent", "10-------"); addSimpleClient("Limewire", "LIME"); addSimpleClient("Martini Man", "martini"); addSimpleClient("Pando", "Pando"); addSimpleClient("PeerApp", "PEERAPP"); addSimpleClient("SimpleBT", "btfans", 4); addSimpleClient("Swarmy", "a00---0"); addSimpleClient("Swarmy", "a02---0"); addSimpleClient("Teeweety", "T00---0"); addSimpleClient("TorrentTopia", "346-"); addSimpleClient("XanTorrent", "DansClient"); /** * This is interesting - it uses Mainline style, except uses two characters instead of one. * And then - the particular numbering style it uses would actually break the way we decode * version numbers (our code is too hardcoded to "-x-y-z--" style version numbers). * * This should really be declared as a Mainline style peer ID, but I would have to * make my code more generic. Not a bad thing - just something I'm not doing right * now. */ addSimpleClient("Amazon AWS S3", "S3-"); // Clients with their own custom format and version number style. ClientData client = null; // DNA01000 becomes version 1.0 - we'll ignore the other digits for now. client = addSimpleClient("BitTorrent DNA", "DNA"); addVersionedClient(client, VER_BYTE_BLOCK_DOTTED_CHAR, 2, 4); // Pre build 10000 versions. client = addSimpleClient("Opera", "OP"); addVersionedClient(client, VER_BLOCK, 4, " (Build %s)"); // Post build 10000 versions. client = addSimpleClient("Opera", "O"); addVersionedClient(client, VER_BLOCK, 5, " (Build %s)"); client = addSimpleClient("Burst!", "Mbrst"); addVersionedClient(client, VER_DOTTED_BLOCK, 5); // 3 version components, 5 chars which describe it client = addSimpleClient("TurboBT", "turbobt"); addVersionedClient(client, VER_BLOCK, 5); client = addSimpleClient("BT Protocol Daemon", "btpd"); addVersionedClient(client, VER_BLOCK, 3, 5); client = addSimpleClient("Plus!", "Plus"); addVersionedClient(client, VER_BYTE_BLOCK_DOTTED_CHAR, 3); client = addSimpleClient("XBT", "XBT"); addVersionedClient(client, VER_BYTE_BLOCK_DOTTED_CHAR, 3); client = addSimpleClient("BitsOnWheels", "-BOW"); addVersionedClient(client, VER_BITS_ON_WHEELS, 3); client = addSimpleClient("eXeem", "eX"); addVersionedClient(client, VER_BLOCK, 18, " [%s]"); // Refers to user ID. client = addSimpleClient("MLdonkey", "-ML"); addVersionedClient(client, VER_DOTTED_BLOCK, 5); client = addSimpleClient("Bitlet", "BitLet"); addVersionedClient(client, VER_BYTE_BLOCK_DOTTED_CHAR, 2); client = addSimpleClient("AllPeers", "AP"); addVersionedClient(client, VER_BLOCK, -1); client = addSimpleClient("BTuga Revolution", "BTM"); addVersionedClient(client, VER_BYTE_BLOCK_DOTTED_CHAR, 2); client = addSimpleClient("Rufus", "RS", 2); addVersionedClient(client, VER_TWO_BYTE_THREE_PART, 2, 0); // BitMagnet - predecessor to Rufus. client = addSimpleClient("BitMagnet", "BM", 2); addVersionedClient(client, VER_TWO_BYTE_THREE_PART, 2, 0); client = addSimpleClient("QVOD", "QVOD"); addVersionedClient(client, VER_BLOCK, 4, " (Build %s)"); // Top-BT - based on BitTornado, but doesn't quite stick // to Shadow's naming conventions - so we'll use substring // matching instead. client = addSimpleClient("Top-BT", "TB"); addVersionedClient(client, VER_BYTE_BLOCK_DOTTED_CHAR, 3); } static class ClientData { String client_name; private int simple_string_pos; private String simple_string; private VersionNumberData version_data; ClientData(String client_name, String simple_string, int simple_string_pos) { this.simple_string_pos = simple_string_pos; this.simple_string = simple_string; this.client_name = client_name; this.version_data = null; } } static class VersionNumberData { private String type; // How to extract and put digit components together private int pos; // Where does this appear in a client ID string? private String fmt; // How do we display that version number? private int length; // How long is the version number? VersionNumberData(String type, int length, String formatter, int position) { this.type = type; this.pos = position; this.fmt = formatter; this.length = length; } } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/utils/OutgoingBTPieceMessageHandlerAdapter.javaazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/utils/OutgoingBTPieceMessageHandlerAdapter.java0000644000175000017500000000213410556302602033057 0ustar adrianadrian/* * Created on Jan 17, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.utils; public interface OutgoingBTPieceMessageHandlerAdapter { public void diskRequestCompleted( long bytes ); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/utils/ClientIdentifier.java0000644000175000017500000004131011053167052027205 0ustar adrianadrianpackage com.aelitis.azureus.core.peermanager.utils; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.ByteFormatter; public class ClientIdentifier { public static String identifyBTOnly(String peer_id_client, byte[] handshake_bytes) { // BitThief check. if (peer_id_client.equals("Mainline 4.4.0") && (handshake_bytes[7] & (byte)1) == 0) { return asDiscrepancy("BitThief*", peer_id_client, "fake_client"); } // We do care if something is claiming to be Azureus when it isn't. If // it's a recent version of Azureus, but doesn't support advanced messaging, we // know it's a fake. if (!peer_id_client.startsWith("Azureus ")) {return peer_id_client;} // Older versions of Azureus won't have support, so discount these first. String version = peer_id_client.substring(8); if (version.startsWith("1") || version.startsWith("2.0") || version.startsWith("2.1") || version.startsWith("2.2")) { return peer_id_client; } // Must be a fake. return asDiscrepancy(null, peer_id_client, "fake_client"); } public static String identifyAZMP(String peer_id_client_name, String az_msg_client_name, String az_msg_client_version, byte[] peer_id) { /** * Hack for BitTyrant - the handshake resembles this: * Client: AzureusBitTyrant * ClientVersion: 2.5.0.0BitTyrant * * Yuck - let's format it so it resembles something pleasant. */ if (az_msg_client_name.endsWith("BitTyrant")) { return "BitTyrant " + az_msg_client_version.replaceAll("BitTyrant", "") + " (Azureus Mod)"; } String msg_client_name = az_msg_client_name + " " + az_msg_client_version; /** * Do both names seem to match? */ if (msg_client_name.equals(peer_id_client_name)) {return msg_client_name;} /** * There may be some discrepancy - a different version number perhaps. * If the main client name still seems to be the same, then return the one * given to us in the AZ handshake. */ String peer_id_client = peer_id_client_name.split(" ", 2)[0]; String az_client_name = az_msg_client_name.split(" ", 2)[0]; if (peer_id_client.equals(az_client_name)) { /** * If both are Azureus, the version numbers shouldn't differ. This is what * we should have - 15 characters both the same (sometimes beta version * is included in the version number but not in the peer ID, but we can deal * with that. * "Azureus a.b.c.d" */ if (az_client_name.equals("Azureus") && peer_id_client.equals("Azureus")) { if (!msg_client_name.substring(0, 15).equals(peer_id_client_name.substring(0, 15))) { return asDiscrepancy("Azureus (Hacked)", peer_id_client_name, msg_client_name, "fake_client", "AZMP", peer_id); } } return msg_client_name; } // Transmission and XTorrent. String res = checkForTransmissionBasedClients(msg_client_name, peer_id_client, peer_id_client_name, msg_client_name, peer_id, "AZMP"); if (res != null) {return res;} // There is an inconsistency. Let's try figuring out what we can. String client_displayed_name = null; boolean is_peer_id_azureus = peer_id_client_name.startsWith("Azureus "); boolean is_msg_client_azureus = az_msg_client_name.equals("Azureus"); boolean is_fake = false; boolean is_mismatch = true; boolean is_peer_id_unknown = peer_id_client_name.startsWith(MessageText.getString("PeerSocket.unknown")); if (is_peer_id_azureus) { // Shouldn't happen. if (is_msg_client_azureus) { throw new RuntimeException("logic error in getExtendedClientName - both clients are Azureus"); } else { // We've got a peer ID that says Azureus, but it doesn't say Azureus in the handshake. // It's definitely fake. is_fake = true; // It might be XTorrent - it does use AZ2504 in the peer ID and "Transmission 0.7-svn" // in the handshake. if (msg_client_name.equals("Transmission 0.7-svn")) {client_displayed_name = "XTorrent";} } } else { if (is_msg_client_azureus) {is_fake = true;} else if (is_peer_id_unknown) { // Our peer ID decoding can't decode it, but the client identifies itself anyway. // In that case, we won't say that it is a mismatch, and we'll just use the name // provided to us. client_displayed_name = msg_client_name; is_mismatch = false; // Log it though. BTPeerIDByteDecoder.logClientDiscrepancy(peer_id_client_name, msg_client_name, "unknown_client", "AZMP", peer_id); } else { // We've got a general mismatch, we don't know what client it is - in most cases. // Ares Galaxy sometimes uses the same peer ID as Arctic Torrent, so allow it to be // overridden. if (msg_client_name.startsWith("Ares") && peer_id_client.equals("ArcticTorrent")) { return msg_client_name; } } } String discrepancy_type; if (is_fake) {discrepancy_type = "fake_client";} else if (is_mismatch) {discrepancy_type = "mismatch_id";} else {discrepancy_type = null;} if (discrepancy_type != null) { return asDiscrepancy(null, peer_id_client_name, msg_client_name, discrepancy_type, "AZMP", peer_id); } return client_displayed_name; } public static String identifyLTEP(String peer_id_name, String handshake_name, byte[] peer_id) { if (handshake_name == null) {return peer_id_name;} /** * Official BitTorrent clients should still be shown as Mainline. * This is to be consistent with previous Azureus behaviour. */ String handshake_name_to_process = handshake_name; if (handshake_name.startsWith("BitTorrent ")) { handshake_name_to_process = handshake_name.replaceFirst("BitTorrent", "Mainline"); } if (peer_id_name.startsWith("\u00B5Torrent")) { // 1.6.0 misidentifies itself as 1.5 in the handshake. if (peer_id_name.equals("\u00B5Torrent 1.6.0")) { return peer_id_name; } // Older �Torrent versions will not always use the appropriate character for the // first letter, so compensate here. if (!handshake_name.startsWith("\u00B5Torrent") && handshake_name.startsWith("Torrent", 1)) { handshake_name_to_process = "\u00B5" + handshake_name.substring(1); } // Some versions indicate they are the beta version in the peer ID, but not in the // handshake - we prefer to keep the beta identifier. if (peer_id_name.endsWith("Beta") && peer_id_name.startsWith(handshake_name_to_process)) { return peer_id_name; } } // Some Mainline 4.x versions identify themselves as �Torrent - according to alus, // this was a bug, so just identify as Mainline. if (peer_id_name.startsWith("Mainline 4.") && handshake_name.startsWith("Torrent", 1)) { return peer_id_name; } // Azureus should never be using LTEP when connected to another Azureus client! if (peer_id_name.startsWith("Azureus") && handshake_name.startsWith("Azureus")) { return asDiscrepancy(null, peer_id_name, handshake_name, "fake_client", "LTEP", peer_id); } // We allow a client to have a different version number than the one decoded from // the peer ID. Some clients separate version and client name using a forward slash, // so we split on that as well. String client_type_peer = peer_id_name.split(" ", 2)[0]; String client_type_handshake = handshake_name_to_process.split(" ", 2)[0].split("/", 2)[0]; // Transmission and XTorrent. String res = checkForTransmissionBasedClients(handshake_name_to_process, client_type_peer, peer_id_name, handshake_name, peer_id, "LTEP"); if (res != null) {return res;} if (client_type_peer.toLowerCase().equals(client_type_handshake.toLowerCase())) {return handshake_name_to_process;} // Like we do with AZMP peers, allow the handshake to define the client even if we can't extract the // name from the peer ID, but log it so we can possibly identify it in future. if (peer_id_name.startsWith(MessageText.getString("PeerSocket.unknown"))) { BTPeerIDByteDecoder.logClientDiscrepancy(peer_id_name, handshake_name, "unknown_client", "LTEP", peer_id); return handshake_name_to_process; } /** * libtorrent is... unsurprisingly... a torrent library. Many clients use it, so cope with clients * which don't identify themselves through the peer ID, but *do* identify themselves through the * handshake. */ if (peer_id_name.startsWith("libtorrent (Rasterbar)")) { if (handshake_name_to_process.toLowerCase().indexOf("libtorrent") == -1) { handshake_name_to_process += " (" + peer_id_name + ")"; } return handshake_name_to_process; } /** * And some clients do things the other way round - they don't bother with the handshake name, * but do remember to change the peer ID name. */ if (client_type_handshake.startsWith("libtorrent")) { // Peer ID doesn't mention libtorrent (just the client name) and the handshake name doesn't // mention the client name (just "libtorrent"), then combine them together. if (client_type_peer.toLowerCase().indexOf("libtorrent") == -1 && client_type_handshake.toLowerCase().indexOf(client_type_peer.toLowerCase()) == -1) { return peer_id_name + " (" + handshake_name_to_process + ")"; } } // Can't determine what the client is. return asDiscrepancy(null, peer_id_name, handshake_name, "mismatch_id", "LTEP", peer_id); } private static String checkForTransmissionBasedClients(String handshake_name_to_process, String client_type_peer, String peer_id_name, String handshake_name, byte[] peer_id, String protocol) { // Bloody XTorrent. if (handshake_name_to_process.equals("Transmission 0.7-svn") && client_type_peer.equals("Azureus")) { return asDiscrepancy("XTorrent", peer_id_name, handshake_name, "fake_client", protocol, peer_id); } // Bloody XTorrent! if (handshake_name_to_process.startsWith("Transmission") && client_type_peer.startsWith("XTorrent")) { return asDiscrepancy(client_type_peer, handshake_name_to_process, "fake_client"); } // Transmission 0.96 still uses 0.95 in the LT handshake, so cope with that and just display // 0.96. if (peer_id_name.equals("Transmission 0.96") && handshake_name.equals("Transmission 0.95")) { return peer_id_name; } return null; } private static String asDiscrepancy(String client_name, String peer_id_name, String handshake_name, String discrepancy_type, String protocol_type, byte[] peer_id) { if (client_name == null) { BTPeerIDByteDecoder.logClientDiscrepancy(peer_id_name, handshake_name, discrepancy_type, protocol_type, peer_id); } // Use this form as it is shorter. if (peer_id_name.equals(handshake_name)) {return asDiscrepancy(client_name, peer_id_name, discrepancy_type);} return asDiscrepancy(client_name, peer_id_name + "\" / \"" + handshake_name, discrepancy_type); } private static String asDiscrepancy(String real_client, String dodgy_client, String discrepancy_type) { if (real_client == null) { real_client = MessageText.getString("PeerSocket.unknown"); } return real_client + " [" + MessageText.getString("PeerSocket." + discrepancy_type) + ": \"" + dodgy_client + "\"]"; } private static int test_count = 1; private static void assertDecode(String client_name, String peer_id, String handshake_name, String handshake_version, byte[] handshake_reserved, String type) throws Exception { byte[] byte_peer_id = BTPeerIDByteDecoder.peerIDStringToBytes(peer_id); String peer_id_client = BTPeerIDByteDecoder.decode(byte_peer_id); String decoded_client; if (type.equals("AZMP")) {decoded_client = identifyAZMP(peer_id_client, handshake_name, handshake_version, byte_peer_id);} else if (type.equals("LTEP")) {decoded_client = identifyLTEP(peer_id_client, handshake_name, byte_peer_id);} else if (type.equals("BT")) {decoded_client = identifyBTOnly(peer_id_client, handshake_reserved);} else {throw new RuntimeException("invalid extension type: " + type);} boolean passed = client_name.equals(decoded_client); System.out.println(" Test " + test_count++ + ": \"" + client_name + "\" - " + (passed ? "PASSED" : "FAILED")); if (!passed) { throw new Exception("\n" + "Decoded : " + decoded_client + "\n" + "Peer ID name : " + peer_id_client + "\n" + "Extended name: " + handshake_name + "\n"); //throw new Exception("Client name decoded - " + decoded_client); } } private static void assertDecodeAZMP(String client_name, String peer_id, String handshake_name, String handshake_version) throws Exception { assertDecode(client_name, peer_id, handshake_name, handshake_version, null, "AZMP"); } private static void assertDecodeLTEP(String client_name, String peer_id, String handshake_name) throws Exception { assertDecode(client_name, peer_id, handshake_name, null, null, "LTEP"); } private static void assertDecodeExtProtocol(String client_name, String peer_id, String handshake_name, String handshake_version) throws Exception { assertDecodeAZMP(client_name, peer_id, handshake_name, handshake_version); assertDecodeLTEP(client_name, peer_id, handshake_name + " " + handshake_version); } private static void assertDecodeBT(String client_name, String peer_id, String handshake_reserved) throws Exception { if (handshake_reserved == null) {handshake_reserved = "0000000000000000";} handshake_reserved = handshake_reserved.replaceAll("[ ]", ""); byte[] handshake_reserved_bytes = ByteFormatter.decodeString(handshake_reserved); if (handshake_reserved_bytes.length != 8) {throw new RuntimeException("invalid handshake reserved bytes");} assertDecode(client_name, peer_id, null, null, handshake_reserved_bytes, "BT"); } public static void main(String[] args) throws Exception { System.setProperty("transitory.startup", "1"); BTPeerIDByteDecoder.client_logging_allowed = false; System.out.println("Testing simple BT clients:"); assertDecodeBT("BitThief* [FAKE: \"Mainline 4.4.0\"]", "M4-4-0--9aa757efd5be", "0000000000000000"); assertDecodeBT("Mainline 4.4.0", "M4-4-0--9aa757efd5be", "0000000000000001"); assertDecodeBT("Unknown [FAKE: \"Azureus 3.0.3.4\"]", "-AZ3034-6wfG2wk6wWLc", "0000000000000000"); System.out.println(""); System.out.println("Testing AZMP clients:"); assertDecodeAZMP("Azureus 3.0.4.2", "-AZ3042-6ozMq5q6Q3NX", "Azureus", "3.0.4.2"); assertDecodeAZMP("Azureus 3.0.4.3_B02", "-AZ3043-6ozMq5q6Q3NX", "Azureus", "3.0.4.3_B02"); assertDecodeAZMP("BitTyrant 2.5.0.0 (Azureus Mod)", "AZ2500BTeyuzyabAfo6U", "AzureusBitTyrant", "2.5.0.0BitTyrant"); //assertDecodeAZMP("", "-BS5820-oy4La2MWGEFj", "Bearshare Premium P2P", "5.8.2.0"); //assertDecodeAZMP("", "-AR6360-6oZyyMWoOOBe", "Imesh Turbo", "6.3.6.0"); assertDecodeAZMP("Azureus (Hacked) [FAKE: \"Azureus 2.4.0.2\" / \"Azureus 2.3.0.6\"]", "2D415A32 3430322D 2E414794 2C57D644 4989CA58", "Azureus", "2.3.0.6"); //assertDecodeAZMP("", "-AG2083-s1hiF8vGAAg0", "Ares", "2.0.8.3029"); //assertDecodeAZMP("", "-AG3003-lEl2Mm4NEO4n", "Ares Destiny", "3.0.0.3805"); System.out.println(""); System.out.println("Testing LTEP clients:"); assertDecodeLTEP("\u00B5Torrent 1.7.6", "2D555431 3736302D B39EC7AD F6B94610 AA4ACD4A", "\u00B5Torrent 1.7.6"); assertDecodeLTEP("\u00B5Torrent 1.6.1", "2D5554313631302DEA818D43F5E5EC3D67BF8D67", "\uFDFFTorrent 1.6.1"); assertDecodeLTEP("Unknown [FAKE: \"Azureus 3.0.4.2\"]", "-AZ3042-6ozMq5q6Q3NX", "Azureus 3.0.4.2"); assertDecodeLTEP("Mainline 6.0", "4D362D30 2D302D2D 8B92860D 05055DF5 B01C2D94", "BitTorrent 6.0"); //assertDecodeLTEP("libTorrent 0.11.9", "2D6C7430 4239302D 11F3EB39 5D44EEFD CEA07E79", "libTorrent 0.11.9"); assertDecodeLTEP("\u00B5Torrent 1.8.0 Beta", "2D555431 3830422D E69C9942 D1A5A6C2 0BE2E4BD", "\u00B5Torrent 1.8"); assertDecodeLTEP("Miro 1.1.0.0 (libtorrent/0.13.0.0)", "-MR1100-00HS~T7*65rm", "libtorrent/0.13.0.0"); assertDecodeLTEP("linkage/0.1.4 libtorrent/0.12.0.0", "-LK0140-ATIV~nbEQAMr", "linkage/0.1.4 libtorrent/0.12.0.0"); assertDecodeLTEP("KTorrent 2.2.2", "-KT2210-347143496631", "KTorrent 2.2.2"); //assertDecodeLTEP("", "B5546F72 72656E74 2F333037 36202020 20202020", "\uFDFFTorrent/3.0.7.6"); assertDecodeLTEP("Transmission 0.96", "-TR0960-6ep6svaa61r4", "Transmission 0.95"); assertDecodeLTEP("Opera 9.50", "O100634008270e29150a", "Opera 9.50"); System.out.println(""); System.out.println("Testing common clients:"); //assertDecodeExtProtocol("", "-XX1150-dv220cotgj4d", "Transmission", "0.72Z"); assertDecodeExtProtocol("XTorrent [FAKE: \"Azureus 2.5.0.4\" / \"Transmission 0.7-svn\"]", "-AZ2504-192gwethivju", "Transmission", "0.7-svn"); System.out.println(""); System.out.println("Done."); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/utils/OutgoingBTPieceMessageHandler.java0000644000175000017500000002766610757735634031621 0ustar adrianadrian/* * Created on Jul 19, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.utils; import java.util.*; import org.gudy.azureus2.core3.disk.*; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.OutgoingMessageQueue; import com.aelitis.azureus.core.peermanager.messaging.*; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.*; /** * Front-end manager for handling requested outgoing bittorrent Piece messages. * Peers often make piece requests in batch, with multiple requests always * outstanding, all of which won't necessarily be honored (i.e. we choke them), * so we don't want to waste time reading in the piece data from disk ahead * of time for all the requests. Thus, we only want to perform read-aheads for a * small subset of the requested data at any given time, which is what this handler * does, before passing the messages onto the outgoing message queue for transmission. */ public class OutgoingBTPieceMessageHandler { private final PEPeer peer; private final OutgoingMessageQueue outgoing_message_queue; private byte piece_version; private final LinkedList requests = new LinkedList(); private final ArrayList loading_messages = new ArrayList(); private final HashMap queued_messages = new HashMap(); private final AEMonitor lock_mon = new AEMonitor( "OutgoingBTPieceMessageHandler:lock"); private boolean destroyed = false; private int request_read_ahead = 2; private OutgoingBTPieceMessageHandlerAdapter adapter; /** * Create a new handler for outbound piece messages, * reading piece data from the given disk manager * and transmitting the messages out the given message queue. * @param disk_manager * @param outgoing_message_q */ public OutgoingBTPieceMessageHandler( PEPeer _peer, OutgoingMessageQueue _outgoing_message_q, OutgoingBTPieceMessageHandlerAdapter _adapter, byte _piece_version ) { peer = _peer; outgoing_message_queue = _outgoing_message_q; adapter = _adapter; piece_version = _piece_version; outgoing_message_queue.registerQueueListener( sent_message_listener ); } public void setPieceVersion( byte version ) { piece_version = version; } private final DiskManagerReadRequestListener read_req_listener = new DiskManagerReadRequestListener() { public void readCompleted( DiskManagerReadRequest request, DirectByteBuffer data ) { try{ lock_mon.enter(); if( !loading_messages.contains( request ) || destroyed ) { //was canceled data.returnToPool(); return; } loading_messages.remove( request ); BTPiece msg = new BTPiece( request.getPieceNumber(), request.getOffset(), data, piece_version ); queued_messages.put( msg, request ); outgoing_message_queue.addMessage( msg, true ); } finally{ lock_mon.exit(); } outgoing_message_queue.doListenerNotifications(); } public void readFailed( DiskManagerReadRequest request, Throwable cause ) { try{ lock_mon.enter(); if( !loading_messages.contains( request ) || destroyed ) { //was canceled return; } loading_messages.remove( request ); } finally{ lock_mon.exit(); } } public int getPriority() { return( -1 ); } public void requestExecuted(long bytes) { adapter.diskRequestCompleted( bytes ); } }; private final OutgoingMessageQueue.MessageQueueListener sent_message_listener = new OutgoingMessageQueue.MessageQueueListener() { public boolean messageAdded( Message message ) { return true; } public void messageSent( Message message ) { if( message.getID().equals( BTMessage.ID_BT_PIECE ) ) { try{ lock_mon.enter(); // due to timing issues we can get in here with a message already removed queued_messages.remove( message ); }finally{ lock_mon.exit(); } /* if ( peer.getIp().equals( "64.71.5.2" )){ outgoing_message_queue.setTrace( true ); // BTPiece p = (BTPiece)message; // TimeFormatter.milliTrace( "obt sent: " + p.getPieceNumber() + "/" + p.getPieceOffset()); } */ doReadAheadLoads(); } } public void messageQueued( Message message ) {/*nothing*/} public void messageRemoved( Message message ) {/*nothing*/} public void protocolBytesSent( int byte_count ) {/*ignore*/} public void dataBytesSent( int byte_count ) {/*ignore*/} public void flush(){} }; /** * Register a new piece data request. * @param piece_number * @param piece_offset * @param length */ public void addPieceRequest( int piece_number, int piece_offset, int length ) { if( destroyed ) return; DiskManagerReadRequest dmr = peer.getManager().getDiskManager().createReadRequest( piece_number, piece_offset, length ); try{ lock_mon.enter(); requests.addLast( dmr ); }finally{ lock_mon.exit(); } doReadAheadLoads(); } /** * Remove an outstanding piece data request. * @param piece_number * @param piece_offset * @param length */ public void removePieceRequest( int piece_number, int piece_offset, int length ) { if( destroyed ) return; DiskManagerReadRequest dmr = peer.getManager().getDiskManager().createReadRequest( piece_number, piece_offset, length ); try{ lock_mon.enter(); if( requests.contains( dmr ) ) { requests.remove( dmr ); return; } if( loading_messages.contains( dmr ) ) { loading_messages.remove( dmr ); return; } for( Iterator i = queued_messages.entrySet().iterator(); i.hasNext(); ) { Map.Entry entry = (Map.Entry)i.next(); if( entry.getValue().equals( dmr ) ) { //it's already been queued BTPiece msg = (BTPiece)entry.getKey(); if( outgoing_message_queue.removeMessage( msg, true ) ) { i.remove(); } break; //do manual listener notify } } } finally{ lock_mon.exit(); } outgoing_message_queue.doListenerNotifications(); } /** * Remove all outstanding piece data requests. */ public void removeAllPieceRequests() { if( destroyed ) return; try{ lock_mon.enter(); // removed this trace as Alon can't remember why the trace is here anyway and as far as I can // see there's nothing to stop a piece being delivered to transport and removed from // the message queue before we're notified of this and thus it is entirely possible that // our view of queued messages is lagging. // String before_trace = outgoing_message_queue.getQueueTrace(); /* int num_queued = queued_messages.size(); int num_removed = 0; for( Iterator i = queued_messages.keySet().iterator(); i.hasNext(); ) { BTPiece msg = (BTPiece)i.next(); if( outgoing_message_queue.removeMessage( msg, true ) ) { i.remove(); num_removed++; } } if( num_removed < num_queued -2 ) { Debug.out( "num_removed[" +num_removed+ "] < num_queued[" +num_queued+ "]:\nBEFORE:\n" +before_trace+ "\nAFTER:\n" +outgoing_message_queue.getQueueTrace() ); } */ for( Iterator i = queued_messages.keySet().iterator(); i.hasNext(); ) { BTPiece msg = (BTPiece)i.next(); outgoing_message_queue.removeMessage( msg, true ); } queued_messages.clear(); // this replaces stuff above requests.clear(); loading_messages.clear(); } finally{ lock_mon.exit(); } outgoing_message_queue.doListenerNotifications(); } public void setRequestReadAhead( int num_to_read_ahead ) { request_read_ahead = num_to_read_ahead; } public void destroy() { try{ lock_mon.enter(); removeAllPieceRequests(); queued_messages.clear(); destroyed = true; outgoing_message_queue.cancelQueueListener(sent_message_listener); } finally{ lock_mon.exit(); } } private void doReadAheadLoads() { List to_submit = null; try{ lock_mon.enter(); while( loading_messages.size() + queued_messages.size() < request_read_ahead && !requests.isEmpty() && !destroyed ) { DiskManagerReadRequest dmr = (DiskManagerReadRequest)requests.removeFirst(); loading_messages.add( dmr ); if( to_submit == null ) to_submit = new ArrayList(); to_submit.add( dmr ); } }finally{ lock_mon.exit(); } /* if ( peer.getIp().equals( "64.71.5.2")){ TimeFormatter.milliTrace( "obt read_ahead: -> " + (to_submit==null?0:to_submit.size()) + " [lo=" + loading_messages.size() + ",qm=" + queued_messages.size() + ",re=" + requests.size() + ",rl=" + request_read_ahead + "]"); } */ if ( to_submit != null ){ for (int i=0;i 0 ); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/utils/OutgoingBTHaveMessageAggregator.java0000644000175000017500000001363010757735634032146 0ustar adrianadrian/* * Created on Jul 18, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.utils; import java.util.*; import org.gudy.azureus2.core3.util.AEMonitor; import com.aelitis.azureus.core.networkmanager.*; import com.aelitis.azureus.core.peermanager.messaging.*; import com.aelitis.azureus.core.peermanager.messaging.azureus.AZHave; import com.aelitis.azureus.core.peermanager.messaging.azureus.AZMessage; import com.aelitis.azureus.core.peermanager.messaging.bittorrent.*; /** * Utility class to enable write aggregation of BT Have messages, * in order to save bandwidth by not wasting a whole network packet * on a single small 9-byte message, and instead pad them onto other * messages. */ public class OutgoingBTHaveMessageAggregator { private final ArrayList pending_haves = new ArrayList(); private final AEMonitor pending_haves_mon = new AEMonitor( "OutgoingBTHaveMessageAggregator:PH"); private byte bt_have_version; private byte az_have_version; private boolean destroyed = false; private final OutgoingMessageQueue outgoing_message_q; private final OutgoingMessageQueue.MessageQueueListener added_message_listener = new OutgoingMessageQueue.MessageQueueListener() { public boolean messageAdded( Message message ) { return true; } public void messageQueued( Message message ) { //if another message is going to be sent anyway, add our haves as well String message_id = message.getID(); if( ! ( message_id.equals( BTMessage.ID_BT_HAVE ) || message_id.equals( AZMessage.ID_AZ_HAVE ))) { sendPendingHaves(); } } public void messageRemoved( Message message ) {/*nothing*/} public void messageSent( Message message ) {/*nothing*/} public void protocolBytesSent( int byte_count ) {/*ignore*/} public void dataBytesSent( int byte_count ) {/*ignore*/} public void flush(){} }; /** * Create a new aggregator, which will send messages out the given queue. * @param outgoing_message_q */ public OutgoingBTHaveMessageAggregator( OutgoingMessageQueue outgoing_message_q, byte _bt_have_version, byte _az_have_version ) { this.outgoing_message_q = outgoing_message_q; bt_have_version = _bt_have_version; az_have_version = _az_have_version; outgoing_message_q.registerQueueListener( added_message_listener ); } public void setHaveVersion( byte bt_version, byte az_version ) { bt_have_version = bt_version; az_have_version = az_version; } /** * Queue a new have message for aggregated sending. * @param piece_number of the have message * @param force if true, send this and any other pending haves right away */ public void queueHaveMessage( int piece_number, boolean force ) { if( destroyed ) return; try{ pending_haves_mon.enter(); pending_haves.add( new Integer( piece_number ) ); if( force ) { sendPendingHaves(); } else { int pending_bytes = pending_haves.size() * 9; if( pending_bytes >= outgoing_message_q.getMssSize() ) { //System.out.println("enough pending haves for a full packet!"); //there's enough pending bytes to fill a packet payload sendPendingHaves(); } } }finally{ pending_haves_mon.exit(); } } /** * Destroy the aggregator, along with any pending messages. */ public void destroy() { try{ pending_haves_mon.enter(); pending_haves.clear(); destroyed = true; } finally{ pending_haves_mon.exit(); } } /** * Force send of any aggregated/pending have messages. */ public void forceSendOfPending() { sendPendingHaves(); } /** * Are there Haves messages pending? * @return true if there are any unsent haves, false otherwise */ public boolean hasPending() { return !pending_haves.isEmpty(); } private void sendPendingHaves() { if ( destroyed ){ return; } try{ pending_haves_mon.enter(); int num_haves = pending_haves.size(); if ( num_haves == 0 ){ return; } // single have -> use BT if ( num_haves == 1 || az_have_version < BTMessageFactory.MESSAGE_VERSION_SUPPORTS_PADDING ){ for( int i=0; i < num_haves; i++ ){ Integer piece_num = (Integer)pending_haves.get( i ); outgoing_message_q.addMessage( new BTHave( piece_num.intValue(), bt_have_version ), true ); } }else{ int[] piece_numbers = new int[num_haves]; for( int i=0; i < num_haves; i++ ) { piece_numbers[i] = ((Integer)pending_haves.get( i )).intValue(); } outgoing_message_q.addMessage( new AZHave( piece_numbers, az_have_version ), true ); } outgoing_message_q.doListenerNotifications(); pending_haves.clear(); }finally{ pending_haves_mon.exit(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/utils/PeerClassifier.java0000644000175000017500000000647110764402660026702 0ustar adrianadrian/* * Created on Sep 9, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.utils; import java.net.InetAddress; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.HostNameToIPResolver; import org.gudy.azureus2.core3.util.IPToHostNameResolver; /** * Handles peer client identification and banning. */ public class PeerClassifier { public static final String CACHE_LOGIC = "CacheLogic"; /** * Get a client description (name and version) from the given peerID byte array. * @param peer_id peerID sent in handshake * @return description */ public static String getClientDescription( byte[] peer_id ) { return BTPeerIDByteDecoder.decode( peer_id ); } /** * Get a printable representation of the given raw peerID byte array, * i.e. filter out the first 32 non-printing ascii chars. * @param peer_id peerID sent in handshake * @return printable peerID */ public static String getPrintablePeerID( byte[] peer_id ) { return BTPeerIDByteDecoder.getPrintablePeerID(peer_id); } /** * Check if the client type is allowed to connect. * @param client_description given by getClientDescription * @return true if allowed, false if banned */ public static boolean isClientTypeAllowed( String client_description ) { //if( client_description.startsWith( "BitComet" ) ) return false; return true; } private static Set platform_ips = Collections.synchronizedSet(new HashSet()); /** * This only works for ones that have been explicitly set as AZ ips * @param ip * @return */ public static boolean isAzureusIP( final String ip ) { return( platform_ips.contains( ip )); } public static void setAzureusIP( final String ip ) { platform_ips.add( ip ); } /** * SYNC call! * @param ip * @return */ public static boolean testIfAzureusIP( final String ip ) { try{ InetAddress address = HostNameToIPResolver.syncResolve( ip ); final String host_address = address.getHostAddress(); if ( platform_ips.contains( host_address )){ return( true ); } String name = IPToHostNameResolver.syncResolve( ip, 10000 ); if ( Constants.isAzureusDomain( name )){ platform_ips.add( host_address ); return( true ); } }catch( Throwable e ){ } return( false ); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/utils/AZPeerIdentityManager.java0000644000175000017500000000301610373051012030110 0ustar adrianadrian/* * Created on Feb 21, 2005 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.utils; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.RandomUtils; /** * */ public class AZPeerIdentityManager { private static byte[] identity = COConfigurationManager.getByteParameter( "az_identity", null ); static { if( identity == null || identity.length != 20 ) { identity = RandomUtils.generateRandomBytes( 20 ); COConfigurationManager.setParameter( "az_identity", identity ); } } public static byte[] getAZPeerIdentity() { return identity; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoder.java0000644000175000017500000005620711223232722027443 0ustar adrianadrian/* * Created on Nov 12, 2003 * Created by Alon Rohter * Copyright (C) 2003-2004 Alon Rohter, All Rights Reserved. * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.utils; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEDiagnosticsLogger; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import java.io.*; import java.util.HashSet; /** * Used for identifying clients by their peerID. */ public class BTPeerIDByteDecoder { final static boolean LOG_UNKNOWN; static { String prop = System.getProperty("log.unknown.peerids"); LOG_UNKNOWN = prop == null || prop.equals("1"); } private static String logUnknownClient0(byte[] peer_id_bytes) throws IOException { String text = new String(peer_id_bytes, 0, 20, Constants.BYTE_ENCODING); text = text.replace((char)12, (char)32); text = text.replace((char)10, (char)32); return "[" + text + "] " + ByteFormatter.encodeString(peer_id_bytes) + " "; } private static String asUTF8ByteString(String text) { try { byte[] utf_bytes = text.getBytes(Constants.DEFAULT_ENCODING); return ByteFormatter.encodeString(utf_bytes); } catch (UnsupportedEncodingException uee) {return "";} } private static HashSet logged_discrepancies = new HashSet(); public static void logClientDiscrepancy(String peer_id_name, String handshake_name, String discrepancy, String protocol, byte[] peer_id) { if (!client_logging_allowed) {return;} // Generate the string used that we will log. String line_to_log = discrepancy + " [" + protocol + "]: "; line_to_log += "\"" + peer_id_name + "\" / \"" + handshake_name + "\" "; // We'll encode the name in byte form to help us decode it. line_to_log += "[" + asUTF8ByteString(handshake_name) + "]"; // Avoid logging the same combination of things again. boolean log_to_debug_out = Constants.isCVSVersion(); if (log_to_debug_out || LOG_UNKNOWN) { // If this text has been recorded before, then avoid doing it again. if (!logged_discrepancies.add(line_to_log)) {return;} } // Add peer ID bytes. if (peer_id != null) { line_to_log += ", Peer ID: " + ByteFormatter.encodeString(peer_id); } // Enable this block for now - just until we get more feedback about // problematic clients. if (log_to_debug_out) { Debug.outNoStack("Conflicting peer identification: " + line_to_log); } if (!LOG_UNKNOWN) {return;} logClientDiscrepancyToFile(line_to_log); } private static AEDiagnosticsLogger logger = null; private synchronized static void logClientDiscrepancyToFile(String line_to_log) { if (logger == null) {logger = AEDiagnostics.getLogger("clientid");} try {logger.log(line_to_log);} catch (Throwable e) {Debug.printStackTrace(e);} } static boolean client_logging_allowed = true; // I don't expect this to grow too big, and it won't grow if there's no logging going on. private static HashSet logged_ids = new HashSet(); static void logUnknownClient(byte[] peer_id_bytes) {logUnknownClient(peer_id_bytes, true);} static void logUnknownClient(byte[] peer_id_bytes, boolean to_debug_out) { if (!client_logging_allowed) {return;} // Avoid logging the same client ID multiple times. boolean log_to_debug_out = to_debug_out && Constants.isCVSVersion(); if (log_to_debug_out || LOG_UNKNOWN) { // If the ID has been recorded before, then avoid doing it again. if (!logged_ids.add(makePeerIDReadableAndUsable(peer_id_bytes))) {return;} } // Enable this block for now - just until we get more feedback about // unknown clients. if (log_to_debug_out) { Debug.outNoStack("Unable to decode peer correctly - peer ID bytes: " + makePeerIDReadableAndUsable(peer_id_bytes)); } if (!LOG_UNKNOWN) {return;} try {logClientDiscrepancyToFile(logUnknownClient0(peer_id_bytes));} catch (Throwable t) {Debug.printStackTrace(t);} } static void logUnknownClient(String peer_id) { try {logUnknownClient(peer_id.getBytes(Constants.BYTE_ENCODING));} catch (UnsupportedEncodingException uee) {} } public static String decode0(byte[] peer_id_bytes) { final String UNKNOWN = MessageText.getString("PeerSocket.unknown"); final String FAKE = MessageText.getString("PeerSocket.fake_client"); final String BAD_PEER_ID = MessageText.getString("PeerSocket.bad_peer_id"); String peer_id = null; try {peer_id = new String(peer_id_bytes, Constants.BYTE_ENCODING);} catch (UnsupportedEncodingException uee) {return "";} // We store the result here. String client = null; /** * If the client reuses parts of the peer ID of other peers, then try to determine this * first (before we misidentify the client). */ if (BTPeerIDByteDecoderUtils.isPossibleSpoofClient(peer_id)) { client = decodeBitSpiritClient(peer_id, peer_id_bytes); if (client != null) {return client;} client = decodeBitCometClient(peer_id, peer_id_bytes); if (client != null) {return client;} return "BitSpirit? (" + BAD_PEER_ID + ")"; } /** * See if the client uses Az style identification. */ if (BTPeerIDByteDecoderUtils.isAzStyle(peer_id)) { client = BTPeerIDByteDecoderDefinitions.getAzStyleClientName(peer_id); if (client != null) { String client_with_version = BTPeerIDByteDecoderDefinitions.getAzStyleClientVersion(client, peer_id); /** * Hack for fake ZipTorrent clients - there seems to be some clients * which use the same identifier, but they aren't valid ZipTorrent clients. */ if (client.startsWith("ZipTorrent") && peer_id.startsWith("bLAde", 8)) { String client_name = (client_with_version == null) ? client : client_with_version; return UNKNOWN + " [" + FAKE + ": " + client_name + "]"; } /** * BitTorrent 6.0 Beta currently misidentifies itself. */ if ("\u00B5Torrent 6.0.0 Beta".equals(client_with_version)) { return "Mainline 6.0 Beta"; } /** * If it's the rakshasa libtorrent, then it's probably rTorrent. */ if (client.startsWith("libTorrent (Rakshasa)")) { String client_name = (client_with_version == null) ? client : client_with_version; return client_name + " / rTorrent*"; } if (client_with_version != null) {return client_with_version;} return client; } } /** * See if the client uses Shadow style identification. */ if (BTPeerIDByteDecoderUtils.isShadowStyle(peer_id)) { client = BTPeerIDByteDecoderDefinitions.getShadowStyleClientName(peer_id); if (client != null) { String client_ver = BTPeerIDByteDecoderUtils.getShadowStyleVersionNumber(peer_id); if (client_ver != null) {return client + " " + client_ver;} return client; } } /** * See if the client uses Mainline style identification. */ client = BTPeerIDByteDecoderDefinitions.getMainlineStyleClientName(peer_id); if (client != null) { /** * We haven't got a good way of detecting whether this is a Mainline style * version of peer ID until we start decoding peer ID information. So for * that reason, we wait until we get client version information here - if * we don't manage to determine a version number, then we assume that it * has been misidentified and carry on with it. */ String client_ver = BTPeerIDByteDecoderUtils.getMainlineStyleVersionNumber(peer_id); if (client_ver != null) { String result = client + " " + client_ver; return result; } } /** * Check for BitSpirit / BitComet (non possible spoof client mode). */ client = decodeBitSpiritClient(peer_id, peer_id_bytes); if (client != null) {return client;} client = decodeBitCometClient(peer_id, peer_id_bytes); if (client != null) {return client;} /** * See if the client identifies itself using a particular substring. */ BTPeerIDByteDecoderDefinitions.ClientData client_data = BTPeerIDByteDecoderDefinitions.getSubstringStyleClient(peer_id); if (client_data != null) { client = client_data.client_name; String client_with_version = BTPeerIDByteDecoderDefinitions.getSubstringStyleClientVersion(client_data, peer_id, peer_id_bytes); if (client_with_version != null) {return client_with_version;} return client; } client = identifyAwkwardClient(peer_id_bytes); if (client != null) {return client;} return null; } /** * Decodes the given peerID, returning an identification string. */ public static String decode(byte[] peer_id) { if ( peer_id.length > 0 ){ try { String client = decode0(peer_id); if (client != null ){ return client; } }catch (Throwable e) { Debug.out( "Failed to decode peer id " + ByteFormatter.encodeString(peer_id) + ": " + Debug.getNestedExceptionMessageAndStack( e )); } try { String peer_id_as_string = new String(peer_id, Constants.BYTE_ENCODING); boolean is_az_style = BTPeerIDByteDecoderUtils.isAzStyle(peer_id_as_string); boolean is_shadow_style = BTPeerIDByteDecoderUtils.isShadowStyle(peer_id_as_string); logUnknownClient(peer_id, !(is_az_style || is_shadow_style)); if (is_az_style) { return BTPeerIDByteDecoderDefinitions.formatUnknownAzStyleClient(peer_id_as_string); } else if (is_shadow_style) { return BTPeerIDByteDecoderDefinitions.formatUnknownShadowStyleClient(peer_id_as_string); } }catch( Throwable e ){ Debug.out( "Failed to decode peer id " + ByteFormatter.encodeString(peer_id) + ": " + Debug.getNestedExceptionMessageAndStack( e )); } } String sPeerID = getPrintablePeerID(peer_id); return MessageText.getString("PeerSocket.unknown") + " [" + sPeerID + "]"; } public static String identifyAwkwardClient(byte[] peer_id) { int iFirstNonZeroPos = 0; iFirstNonZeroPos = 20; for( int i=0; i < 20; i++ ) { if( peer_id[i] != (byte)0 ) { iFirstNonZeroPos = i; break; } } //Shareaza check if( iFirstNonZeroPos == 0 ) { boolean bShareaza = true; for( int i=0; i < 16; i++ ) { if( peer_id[i] == (byte)0 ) { bShareaza = false; break; } } if( bShareaza ) { for( int i=16; i < 20; i++ ) { if( peer_id[i] != ( peer_id[i % 16] ^ peer_id[15 - (i % 16)] ) ) { bShareaza = false; break; } } if( bShareaza ) return "Shareaza"; } } byte three = (byte)3; if ((iFirstNonZeroPos == 9) && (peer_id[9] == three) && (peer_id[10] == three) && (peer_id[11] == three)) { return "Snark"; } if ((iFirstNonZeroPos == 12) && (peer_id[12] == (byte)97) && (peer_id[13] == (byte)97)) { return "Experimental 3.2.1b2"; } if ((iFirstNonZeroPos == 12) && (peer_id[12] == (byte)0) && (peer_id[13] == (byte)0)) { return "Experimental 3.1"; } if (iFirstNonZeroPos == 12) return "Mainline"; return null; } private static String decodeBitSpiritClient(String peer_id, byte[] peer_id_bytes) { if (!peer_id.substring(2, 4).equals("BS")) {return null;} String version = BTPeerIDByteDecoderUtils.decodeNumericValueOfByte(peer_id_bytes[1]); if ("0".equals(version)) {version = "1";} return "BitSpirit v" + version; } private static String decodeBitCometClient(String peer_id, byte[] peer_id_bytes) { String mod_name = null; if (peer_id.startsWith("exbc")) {mod_name = "";} else if (peer_id.startsWith("FUTB")) {mod_name = "(Solidox Mod) ";} else if (peer_id.startsWith("xUTB")) {mod_name = "(Mod 2) ";} else {return null;} boolean is_bitlord = (peer_id.substring(6, 10).equals("LORD")); /** * Older versions of BitLord are of the form x.yy, whereas new versions (1 and onwards), * are of the form x.y. BitComet is of the form x.yy. */ String client_name = (is_bitlord) ? "BitLord " : "BitComet "; String maj_version = BTPeerIDByteDecoderUtils.decodeNumericValueOfByte(peer_id_bytes[4]); int min_version_length = (is_bitlord && !maj_version.equals("0")) ? 1 : 2; return client_name + mod_name + maj_version + "." + BTPeerIDByteDecoderUtils.decodeNumericValueOfByte(peer_id_bytes[5], min_version_length); } protected static String getPrintablePeerID(byte[] peer_id) { return getPrintablePeerID(peer_id, '-'); } protected static String getPrintablePeerID(byte[] peer_id, char fallback_char) { String sPeerID = ""; byte[] peerID = new byte[ peer_id.length ]; System.arraycopy( peer_id, 0, peerID, 0, peer_id.length ); try { for (int i = 0; i < peerID.length; i++) { int b = (0xFF & peerID[i]); if (b < 32 || b > 127) peerID[i] = (byte)fallback_char; } sPeerID = new String(peerID, Constants.BYTE_ENCODING); } catch (UnsupportedEncodingException ignore) {} catch (Throwable e) {} return( sPeerID ); } private static String makePeerIDReadableAndUsable(byte[] peer_id) { boolean as_ascii = true; for (int i=0; i 127 || b == 10 || b == 9 || b==13) { as_ascii = false; break; } } if (as_ascii) { try {return new String(peer_id, Constants.BYTE_ENCODING);} catch (UnsupportedEncodingException uee) {return "";} } else {return ByteFormatter.encodeString(peer_id);} } static byte[] peerIDStringToBytes(String peer_id) throws Exception { if (peer_id.length() > 40) { peer_id = peer_id.replaceAll("[ ]", ""); } byte[] byte_peer_id = null; if (peer_id.length() == 40) { byte_peer_id = ByteFormatter.decodeString(peer_id); String readable_peer_id = makePeerIDReadableAndUsable(byte_peer_id); if (!peer_id.equals(readable_peer_id)) { throw new RuntimeException("Use alternative format for peer ID - from " + peer_id + " to " + readable_peer_id); } } else if (peer_id.length() == 20) { byte_peer_id = peer_id.getBytes(Constants.BYTE_ENCODING); } else { throw new IllegalArgumentException(peer_id); } return byte_peer_id; } private static void assertDecode(String client_result, String peer_id) throws Exception { assertDecode(client_result, peerIDStringToBytes(peer_id)); } private static void assertDecode(String client_result, byte[] peer_id) throws Exception { String peer_id_as_string = getPrintablePeerID(peer_id, '*'); System.out.println(" Peer ID: " + peer_id_as_string + " Client: " + client_result); // Do not log any clients. String decoded_result = decode(peer_id); if (client_result.equals(decoded_result)) {return;} throw new RuntimeException("assertion failure - expected \"" + client_result + "\", got \"" + decoded_result + "\": " + peer_id_as_string); } public static void main(String[] args) throws Exception { client_logging_allowed = false; final String FAKE = MessageText.getString("PeerSocket.fake_client"); final String UNKNOWN = MessageText.getString("PeerSocket.unknown"); final String BAD_PEER_ID = MessageText.getString("PeerSocket.bad_peer_id"); System.out.println("Testing AZ style clients..."); assertDecode("Ares 2.0.5.3", "-AG2053-Em6o1EmvwLtD"); assertDecode("Ares 1.6.7.0", "-AR1670-3Ql6wM3hgtCc"); assertDecode("Artemis 2.5.2.0", "-AT2520-vEEt0wO6v0cr"); assertDecode("Azureus 2.2.0.0", "-AZ2200-6wfG2wk6wWLc"); assertDecode("BT Next Evolution 1.0.9", "-NE1090002IKyMn4g7Ko"); assertDecode("BitRocket 0.3(32)", "-BR0332-!XVceSn(*KIl"); assertDecode("Mainline 6.0 Beta", "2D555436 3030422D A78DC290 C3F7BDE0 15EC3CC7"); assertDecode("FlashGet 1.80", "2D464730 31383075 F8005782 1359D64B B3DFD265"); assertDecode("GetRight 6.3", "-GR6300-13s3iFKmbArc"); assertDecode("Halite 0.2.9", "-HL0290-xUO*9ugvENUE"); assertDecode("KTorrent 1.1 RC1", "-KT11R1-693649213030"); assertDecode("KTorrent 3.0", "2D4B543330302D006A7139727958377731756A4B"); assertDecode("libTorrent (Rakshasa) 0.11.2 / rTorrent*", "2D6C74304232302D0D739B93E6BE21FEBB557B20"); assertDecode("libtorrent (Rasterbar) 0.13.0", "-LT0D00-eZ0PwaDDr-~v"); // The latest version at time of writing is v0.12, but I'll assume this is valid. assertDecode("linkage 0.1.4", "-LK0140-ATIV~nbEQAMr"); assertDecode("LimeWire", "2D4C57303030312D31E0B3A0B46F7D4E954F4103"); assertDecode("Lphant 3.02", "2D4C5030 3330322D 00383336 35363935 37373030"); assertDecode("Shareaza 2.1.3.2", "2D535A323133322D000000000000000000000000"); assertDecode("SymTorrent 1.17", "-ST0117-01234567890!"); assertDecode("Transmission 0.6", "-TR0006-01234567890!"); assertDecode("Transmission 0.72 (Dev)", "-TR072Z-zihst5yvg22f"); assertDecode("Transmission 0.72", "-TR0072-8vd6hrmp04an"); assertDecode("TuoTu 2.1.0", "-TT210w-dq!nWf~Qcext"); assertDecode("\u00B5Torrent 1.7.0 Beta", "2D555431 3730422D 92844644 1DB0A094 A01C01E5"); assertDecode("\u54c7\u560E (Vagaa) 2.6.4.4", "2D5647323634342D4FD62CDA69E235717E3BB94B"); assertDecode("Wyzo 0.3.0.0", "-WY0300-6huHF5Pr7Vde"); assertDecode("CacheLogic 25.1-26", "-PC251Q-6huHF5Pr7Vde"); System.out.println(); // Shadow style clients. System.out.println("Testing Shadow style clients..."); assertDecode("ABC", "A--------YMyoBPXYy2L"); // Seen this quite a bit - not sure that it is ABC, but I guess we should default to that... assertDecode("ABC 2.6.9", "413236392D2D2D2D345077199FAEC4A673BECA01"); assertDecode("ABC 3.1", "A310--001v5Gysr4NxNK"); assertDecode("BitTornado 0.3.12", "T03C-----6tYolxhVUFS"); assertDecode("BitTornado 0.3.18", "T03I--008gY6iB6Aq27C"); assertDecode("BitTornado 0.3.9", "T0390----5uL5NvjBe2z"); assertDecode("Tribler 1", "R100--003hR6s07XWcov"); // Seen recently - is this really Tribler? assertDecode("Tribler 3.7", "R37---003uApHy851-Pq"); System.out.println(); // Simple substring style clients. System.out.println("Testing simple substring clients..."); assertDecode("Azureus 1", "417A7572 65757300 00000000 000000A0 76F0AEF7"); assertDecode("Azureus 2.0.3.2", "2D2D2D2D2D417A757265757354694E7A2A6454A7"); assertDecode("G3 Torrent", "2D473341 6E6F6E79 6D6F7573 70E8D9CB 30250AD4"); assertDecode("Hurricane Electric", "6172636C696768742E68652EA5860C157A5ADC35"); assertDecode("Pando", "Pando-6B511B691CAC2E"); // Seen recently, have they changed peer ID format? assertDecode("\u00B5Torrent 1.7.0 RC", "2D55543137302D00AF8BC5ACCC4631481EB3EB60"); System.out.println(); // Version substring style clients. System.out.println("Testing versioned substring clients..."); assertDecode("Bitlet 0.1", "4269744C657430319AEA4E02A09E318D70CCF47D"); assertDecode("BitsOnWheels", "-BOWP05-EPICNZOGQPHP"); // Seen in the wild - no idea what version that's meant to be - a pre-release? assertDecode("Burst! 1.1.3", "Mbrst1-1-32e3c394b43"); assertDecode("Opera (Build 7685)", "OP7685f2c1495b1680bf"); assertDecode("Opera (Build 10063)", "O100634008270e29150a"); assertDecode("Rufus 0.6.9", "00455253 416E6F6E 796D6F75 7382BE42 75024AE3"); assertDecode("BitTorrent DNA 1.0", "444E413031303030DD01C9B2DA689E6E02803E91"); assertDecode("BTuga Revolution 2.1", "BTM21abcdefghijklmno"); assertDecode("AllPeers 0.70rc30", "4150302E3730726333302D3E3EB87B31F241DBFE"); // AP0.70rc30->>-{1-A--]" assertDecode("External Webseed", "45787420EC7CC30033D7801FEEB713FBB0557AC4"); assertDecode("QVOD (Build 0054)", "QVOD00541234567890AB"); // Based on description on wiki.theory.org. assertDecode("Top-BT 1.0.0", "TB100----abcdefghijk"); System.out.println(); // BitComet/Lord/Spirit System.out.println("Testing BitComet/Lord/Spirit clients..."); assertDecode("BitComet 0.56", "6578626300387A4463102D6E9AD6723B339F35A9"); assertDecode("BitLord 0.56", "6578626300384C4F52443200048ECED57BD71028"); assertDecode("BitSpirit? (" + BAD_PEER_ID + ")", "4D342D302D322D2D6898D9D0CAF25E4555445030"); assertDecode("BitSpirit v2", "000242539B7ED3E058A8384AA748485454504254"); assertDecode("BitSpirit v3", "00034253 07248896 44C59530 8A5FF2CA 55445030"); System.out.println(); // Mainline style clients. System.out.println("Testing new mainline style clients..."); assertDecode("Mainline 5.0.7", "M5-0-7--9aa757efd5be"); assertDecode("Amazon AWS S3", "S3-1-0-0--0123456789"); // Not currently decoded as mainline style... System.out.println(); // Various specialised clients. System.out.println("Testing various specialised clients..."); assertDecode("Mainline", "0000000000000000000000004C53441933104277"); assertDecode(UNKNOWN + " [" + FAKE + ": ZipTorrent 1.6.0.0]", "-ZT1600-bLAdeY9rdjbe"); System.out.println(); // Unknown clients - may be random bytes. System.out.println("Testing unknown (random byte?) clients..."); assertDecode(UNKNOWN + " [--------1}-/---A---<]", "0000000000000000317DA32F831FF041A515FE3C"); assertDecode(UNKNOWN + " [------- -- ------@(]", "000000DF05020020100020200008000000004028"); assertDecode(UNKNOWN + " [-----------D-y-I--aO]", "0000000000000000F106CE44F179A2498FAC614F"); assertDecode(UNKNOWN + " [--c--_-5-\\----t-#---]", "E7F163BB0E5FCD35005C09A11BC274C42385A1A0"); System.out.println(); // Unknown AZ style clients. System.out.println("Testing unknown AZ style clients..."); String unknown_az; unknown_az = MessageText.getString("PeerSocket.unknown_az_style", new String[]{"BD", "0.3.0.0"}); assertDecode(unknown_az, "-BD0300-1SGiRZ8uWpWH"); unknown_az = MessageText.getString("PeerSocket.unknown_az_style", new String[]{"wF", "2.2.0.0"}); assertDecode(unknown_az, "2D7746323230302D9DFF296B56AFC2DF751C609C"); unknown_az = MessageText.getString("PeerSocket.unknown_az_style", new String[]{"X1", "0.0.6.4"}); assertDecode(unknown_az, "2D5831303036342D12FB8A5B954153A114267F1F"); unknown_az = MessageText.getString("PeerSocket.unknown_az_style", new String[]{"bF", "2q00"}); // I made this one up. assertDecode(unknown_az, "2D6246327130302D9DFF296B56AFC2DF751C609C"); System.out.println(); // Unknown Shadow style clients. System.out.println("Testing unknown Shadow style clients..."); String unknown_shadow; unknown_shadow = MessageText.getString("PeerSocket.unknown_shadow_style", new String[]{"B", "1.2"}); assertDecode(unknown_shadow, "B12------xgTofhetSVQ"); System.out.println(); // TODO //assertDecode("KTorrent 2.2", "-KT22B1-695754334315"); // We could use the B1 information... //assertDecode("KTorrent 2.1.4", "-KT2140-584815613993"); // Currently shows as 2.1. //assertDecode("", "C8F2D9CD3A90455354426578626300362D2D2D92"); // Looks like a BitLord client - ESTBexbc? //assertDecode("", "303030302D2D0000005433585859684B59584C72"); // Seen in the wild, appears to be a modified version of Azureus 2.5.0.0 (that's what was in the AZMP handshake)? //assertDecode("", "B5546F7272656E742F3330323520202020202020"); System.out.println("Done."); } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/nat/0000755000175000017500000000000011310377630022545 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/peermanager/nat/PeerNATInitiator.java0000644000175000017500000000206110454610524026530 0ustar adrianadrian/* * Created on 10 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.nat; public interface PeerNATInitiator { public String getDisplayName(); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/nat/PeerNATTraverser.java0000644000175000017500000003067610670072436026564 0ustar adrianadrian/* * Created on 10 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.nat; import java.net.InetSocketAddress; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.Average; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.nat.NATTraversal; import com.aelitis.azureus.core.nat.NATTraversalHandler; import com.aelitis.azureus.core.nat.NATTraversalObserver; import com.aelitis.azureus.core.nat.NATTraverser; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.core.util.bloom.BloomFilterFactory; public class PeerNATTraverser implements NATTraversalHandler { private static final LogIDs LOGID = LogIDs.PEER; private static final int OUTCOME_SUCCESS = 0; private static final int OUTCOME_FAILED_NO_REND = 1; private static final int OUTCOME_FAILED_OTHER = 2; private static PeerNATTraverser singleton; public static void initialise( AzureusCore core ) { singleton = new PeerNATTraverser( core ); } public static PeerNATTraverser getSingleton() { return( singleton ); } private static int MAX_ACTIVE_REQUESTS; static{ COConfigurationManager.addAndFireParameterListener( "peer.nat.traversal.request.conc.max", new ParameterListener() { public void parameterChanged( String name ) { MAX_ACTIVE_REQUESTS = COConfigurationManager.getIntParameter( name ); } }); } private static final int TIMER_PERIOD = 10*1000; private static final int USAGE_PERIOD = TIMER_PERIOD; private static final int USAGE_DURATION_SECS = 60; private static final int MAX_USAGE_PER_MIN = MAX_ACTIVE_REQUESTS*5*1000; private static final int STATS_TICK_COUNT = 120*1000 / TIMER_PERIOD; private NATTraverser nat_traverser; private Map initiators = new HashMap(); private LinkedList pending_requests = new LinkedList(); private List active_requests = new ArrayList(); private Average usage_average = Average.getInstance(USAGE_PERIOD,USAGE_DURATION_SECS); private int attempted_count = 0; private int success_count = 0; private int failed_no_rendezvous = 0; private int failed_negative_bloom = 0; private BloomFilter negative_result_bloom = BloomFilterFactory.createAddOnly( BLOOM_SIZE ); private static final int BLOOM_SIZE = MAX_ACTIVE_REQUESTS*1024; private static final int BLOOM_REBUILD_PERIOD = 5*60*1000; private static final int BLOOM_REBUILD_TICKS = BLOOM_REBUILD_PERIOD/TIMER_PERIOD; public PeerNATTraverser( AzureusCore core ) { nat_traverser = core.getNATTraverser(); nat_traverser.registerHandler( this ); SimpleTimer.addPeriodicEvent( "PeerNAT:stats", TIMER_PERIOD, new TimerEventPerformer() { private int ticks; public void perform( TimerEvent event ) { ticks++; List to_run = null; synchronized( initiators ){ if ( ticks % BLOOM_REBUILD_TICKS == 0 ){ int size = negative_result_bloom.getEntryCount(); if (Logger.isEnabled()){ if ( size > 0 ){ Logger.log( new LogEvent(LOGID, "PeerNATTraverser: negative bloom size = " + size )); } } negative_result_bloom = BloomFilterFactory.createAddOnly( BLOOM_SIZE ); } if ( ticks % STATS_TICK_COUNT == 0 ){ String msg = "NAT traversal stats: active=" + active_requests.size() + ",pending=" + pending_requests.size() + ",attempted=" + attempted_count + ",no rendezvous=" + failed_no_rendezvous + ",negative bloom=" + failed_negative_bloom + ",successful=" + success_count; // System.out.println( msg ); if (Logger.isEnabled()){ Logger.log( new LogEvent(LOGID, msg )); } } int used = 0; for (int i=0;i MAX_USAGE_PER_MIN ){ return; } // System.out.println( "usage = " + usage ); while( true ){ if ( pending_requests.size() == 0 || active_requests.size() >= MAX_ACTIVE_REQUESTS ){ break; } // TODO: prioritisation based on initiator connections etc? PeerNATTraversal traversal = (PeerNATTraversal)pending_requests.removeFirst(); active_requests.add( traversal ); if ( to_run == null ){ to_run = new ArrayList(); } to_run.add( traversal ); attempted_count++; } } if ( to_run != null ){ for (int i=0;i all_peers ) { return UnchokerUtil.getNextOptimisticPeer( all_peers, true, true ); //TODO extract and optimize? } public ArrayList rankPeers( int max_to_unchoke, ArrayList all_peers ) { ArrayList best_peers = new ArrayList(); long[] bests = new long[ max_to_unchoke ]; //ensure we never rank more peers than needed //fill slots with peers who we are currently downloading the fastest from for( int i=0; i < all_peers.size(); i++ ) { PEPeer peer = all_peers.get( i ); if( peer.isInteresting() && UnchokerUtil.isUnchokable( peer, false ) ) { //viable peer found long rate = peer.getStats().getSmoothDataReceiveRate(); if( rate > 256 ) { //filter out really slow peers UnchokerUtil.updateLargestValueFirstSort( rate, bests, peer, best_peers, 0 ); } } } //if we havent yet picked enough slots if( best_peers.size() < max_to_unchoke ) { int start_pos = best_peers.size(); //fill the remaining slots with peers that we have downloaded from in the past for( int i=0; i < all_peers.size(); i++ ) { PEPeer peer = all_peers.get( i ); if( peer.isInteresting() && UnchokerUtil.isUnchokable( peer, false ) && !best_peers.contains( peer ) ) { //viable peer found long uploaded_ratio = peer.getStats().getTotalDataBytesSent() / (peer.getStats().getTotalDataBytesReceived() + (DiskManager.BLOCK_SIZE-1)); //make sure we haven't already uploaded several times as much data as they've sent us if( uploaded_ratio <3) { UnchokerUtil.updateLargestValueFirstSort( peer.getStats().getTotalDataBytesReceived(), bests, peer, best_peers, start_pos ); } } } } return best_peers; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/uploadslots/UploadSession.java0000644000175000017500000000452411244607062027775 0ustar adrianadrian/* * Created on Jul 17, 2006 * Created by Alon Rohter * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.uploadslots; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.DisplayFormatters; import com.aelitis.azureus.core.peermanager.unchoker.UnchokerUtil; /** * */ public class UploadSession { protected static final int TYPE_DOWNLOAD = 0; protected static final int TYPE_SEED = 1; private final PEPeer peer; private final int session_type; protected UploadSession( PEPeer _peer, int _session_type ) { this.peer = _peer; this.session_type = _session_type; } protected int getSessionType() { return session_type; } protected void start() { UnchokerUtil.performChokeUnchoke( null, peer ); } protected void stop() { UnchokerUtil.performChokeUnchoke( peer, null ); } protected boolean isSameSession( UploadSession session ) { if( session == null ) return false; return this.peer == session.peer; } protected String getStatsTrace() { String n = peer.getManager().getDisplayName(); String t = session_type == TYPE_DOWNLOAD ? "DOWNLOADING" : "SEEDING"; String p = " : [" +peer.getClient()+ "] " +peer.getIp()+ " :" +peer.getPort(); String s = " || (D: " +DisplayFormatters.formatByteCountToKiBEtcPerSec( peer.getStats().getDataReceiveRate() )+ ") (U: " +DisplayFormatters.formatByteCountToKiBEtcPerSec( peer.getStats().getDataSendRate() )+ ")"; return "[" +n+ "] " + t + p + s; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/uploadslots/SeedingRanker.java0000644000175000017500000000465710461537146027742 0ustar adrianadrian/* * Created on Apr 5, 2005 * Created by Alon Rohter * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.uploadslots; import java.util.*; import org.gudy.azureus2.core3.peer.impl.PEPeerTransport; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.peermanager.unchoker.UnchokerUtil; /** * Unchoker implementation to be used while in seeding mode. */ public class SeedingRanker { public SeedingRanker() { /* nothing */ } private PEPeerTransport getNextOptimisticPeerExec( ArrayList all_peers ) { if( all_peers.isEmpty() ) { //no connected peers Debug.out( "all_peers.isEmpty()" ); return null; } int pos = RandomUtils.nextInt( all_peers.size() ); //pick a random peer to start for( int i=0; i < all_peers.size(); i++ ) { //ensure we only loop once PEPeerTransport peer = (PEPeerTransport)all_peers.get( pos ); //get next potential peer if( peer.isChokedByMe() && UnchokerUtil.isUnchokable( peer, true ) ) { //filter out peers already unchoked, and unchokable return peer; //found the next optimistic! } pos++; //try next if( pos >= all_peers.size() ) { //loop 'round if necessary pos = 0; } } Debug.out( "no optimistic-able seeding peers found" ); return null; } public PEPeerTransport getNextOptimisticPeer( ArrayList all_peers ) { PEPeerTransport picked = getNextOptimisticPeerExec( all_peers ); //TODO test to see if peers really are picked evenly return picked; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/uploadslots/UploadSlot.java0000644000175000017500000000324610457414600027272 0ustar adrianadrian/* * Created on Jul 15, 2006 * Created by Alon Rohter * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.uploadslots; /** * */ public class UploadSlot { protected static final int TYPE_NORMAL = 0; protected static final int TYPE_OPTIMISTIC = 1; private final int slot_type; private long expire_round = 0; //slot is expired by default private UploadSession session; protected UploadSlot( int _slot_type ) { this.slot_type = _slot_type; } protected int getSlotType() { return slot_type; } protected void setSession( UploadSession _session ) { this.session = _session; } protected UploadSession getSession() { return session; } protected void setExpireRound( long round ) { this.expire_round = round; } protected long getExpireRound(){ return expire_round; } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/uploadslots/UploadSlotManager.java0000644000175000017500000002065011165063176030570 0ustar adrianadrian/* * Created on Jul 15, 2006 * Created by Alon Rohter * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.uploadslots; import java.util.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.peermanager.control.*; /** * */ public class UploadSlotManager { private static final int EXPIRE_NORMAL = 1; //1 round = 10sec upload private static final int EXPIRE_OPTIMISTIC = 3; //3 rounds = 30sec upload private static final int EXPIRE_SEED = 6; //6 rounds = 60sec upload // change this to true and you'll have to fix the scheduleing code below public static final boolean AUTO_SLOT_ENABLE = false; //TODO private long last_process_time; private static final UploadSlotManager instance = new UploadSlotManager(); public static UploadSlotManager getSingleton() { return instance; } private final UploadSessionPicker picker = new UploadSessionPicker(); //init with empty slots, optimistic first in line private final UploadSlot[] slots = new UploadSlot[] { new UploadSlot( UploadSlot.TYPE_OPTIMISTIC ), //TODO dynamic # of slots new UploadSlot( UploadSlot.TYPE_NORMAL ), new UploadSlot( UploadSlot.TYPE_NORMAL ), new UploadSlot( UploadSlot.TYPE_NORMAL ) }; private long current_round = 0; private UploadSlotManager() { if( AUTO_SLOT_ENABLE ) { System.out.println( "UPLOAD_SLOT_MANAGER SCHEDULAR STARTED" ); /* removed pending rework PeerControlSchedulerFactory.getSingleton().register( new PeerControlInstance() { public void schedule() { long now = SystemTime.getCurrentTime(); if( now - last_process_time >= 10000 ) { //10sec process loop process(); last_process_time = now; } else if( last_process_time > now ) { Debug.out( "OOPS, time went backwards!" ); last_process_time = now; } } public int getSchedulePriority() { return 0; } }); */ } else { //System.out.println( "AUTO UPLOAD SLOT *DISABLED*" ); } } public void registerHelper( UploadHelper helper ) { if( AUTO_SLOT_ENABLE ) { picker.registerHelper( helper ); } } public void deregisterHelper( UploadHelper helper ) { if( AUTO_SLOT_ENABLE ) { picker.deregisterHelper( helper ); } } /** * Notify of helper state change (i.e. priority changed) * @param helper */ public void updateHelper( UploadHelper helper ) { if( AUTO_SLOT_ENABLE ) { picker.updateHelper( helper ); } } private void process() { if( !AUTO_SLOT_ENABLE ) return; current_round++; ArrayList to_stop = new ArrayList(); //get a list of the best sessions, peers who are uploading to us in download mode LinkedList best_sessions = picker.pickBestDownloadSessions( slots.length ); int best_size = best_sessions.size(); //go through all currently expired slots and pick sessions for next round for( int i=0; i < slots.length; i++ ) { UploadSlot slot = slots[i]; if( slot.getExpireRound() <= current_round ) { //expired UploadSession session = slot.getSession(); if( session != null ) { to_stop.add( session ); //make sure it gets stopped slot.setSession( null ); //clear slot } if( slot.getSlotType() == UploadSlot.TYPE_OPTIMISTIC ) { //optimistic //pick new session for optimistic upload session = pickOptSession(); if( session == null ) { continue; } if( session.getSessionType() == UploadSession.TYPE_SEED ) { //place first seed session in a normal slot best_sessions.addFirst( session ); //put at front of good list to ensure it gets picked //pick a new optimistic session, whatever type session = pickOptSession(); if( session == null ) continue; } slot.setSession( session ); //place the new session in the slot slot.setExpireRound( current_round + EXPIRE_OPTIMISTIC ); //set the new expire time } else { //normal session = getNextBestSession( best_sessions ); //get the next "best" session if( session == null && best_size == slots.length ) { Debug.out( "session == null && best_size == slots.length" ); } if( session == null ) { //no download mode peers, must be only seeding; or all best are already slotted session = pickOptSession(); //just pick the next optimistic if( session == null ) continue; //no optimistic either } slot.setSession( session ); //place the session in the slot slot.setExpireRound( current_round + ( session.getSessionType() == UploadSession.TYPE_SEED ? EXPIRE_SEED : EXPIRE_NORMAL ) ); //set the new expire time } } } //start and stop sessions for the round //filter out sessions allowed to continue another round, so we don't stop-start them for( Iterator it = to_stop.iterator(); it.hasNext(); ) { UploadSession stop_s = (UploadSession)it.next(); for( int i=0; i < slots.length; i++ ) { if( stop_s.isSameSession( slots[i].getSession() ) ) { //need to do this because two session objects can represent the same peer it.remove(); break; } } } //stop discontinued sessions for( Iterator it = to_stop.iterator(); it.hasNext(); ) { UploadSession session = (UploadSession)it.next(); session.stop(); } //ensure sessions are started for( int i=0; i < slots.length; i++ ) { UploadSession s = slots[i].getSession(); if( s != null ) s.start(); } printSlotStats(); } int count = 0; private UploadSession getNextBestSession( LinkedList best ) { count++; System.out.print( "getNextBestSession [" +count+"] best.size=" +best.size()+ " " ); if( !best.isEmpty() ) { UploadSession session = (UploadSession)best.removeFirst(); //get next if( !isAlreadySlotted( session ) ) { //found an unslotted session System.out.println( "OK found session [" +session.getStatsTrace()+ "]" ); return session; } System.out.println( "FAIL already-slotted session [" +session.getStatsTrace()+ "]" ); return getNextBestSession( best ); //oops, already been slotted, try again } return null; } private UploadSession pickOptSession() { int max = picker.getHelperCount(); //max number of sessions the picker will return before it loops back 'round for( int i=0; i < max; i++ ) { //make sure we don't loop UploadSession session = picker.pickNextOptimisticSession(); if( session != null && !isAlreadySlotted( session ) ) { return session; //found! } } return null; //no optimistic sessions } private boolean isAlreadySlotted( UploadSession session ) { for( int i=0; i < slots.length; i++ ) { UploadSession s = slots[i].getSession(); if( s != null && s.isSameSession( session ) ) return true; } return false; } private void printSlotStats() { System.out.println( "\nUPLOAD SLOTS [" +current_round+ "x]:" ); for( int i=0; i < slots.length; i++ ) { UploadSlot slot = slots[i]; System.out.print( "[" +i+ "]: " ); String slot_type = slot.getSlotType() == UploadSlot.TYPE_NORMAL ? "NORM" : "OPTI"; long rem = slot.getExpireRound() - current_round; String remaining = rem < 0 ? "" : " [" +rem+ "]rr"; String ses_trace = slot.getSession() == null ? "EMPTY" : slot.getSession().getStatsTrace(); System.out.println( slot_type + remaining+ " : " +ses_trace ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/uploadslots/UploadHelper.java0000644000175000017500000000337511135270206027567 0ustar adrianadrian/* * Created on Mar 20, 2006 * Created by Alon Rohter * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.uploadslots; import java.util.ArrayList; import org.gudy.azureus2.core3.peer.PEPeer; /** * */ public interface UploadHelper { public static final int PRIORITY_DISABLED = 0; public static final int PRIORITY_LOWEST = 1; public static final int PRIORITY_LOW = 2; public static final int PRIORITY_NORMAL = 4; public static final int PRIORITY_HIGH = 8; public static final int PRIORITY_HIGHEST = 16; /** * Get download opt unchoke priority. * @return */ public int getPriority(); /** * Get all (PEPeerTransport) peers for this download. * @return non-mutable list of peers */ public ArrayList getAllPeers(); /** * Is this download in seeding mode. * @return true if seeding, false if downloading */ public boolean isSeeding(); } azureus-4.3.0.6/com/aelitis/azureus/core/peermanager/uploadslots/UploadSessionPicker.java0000644000175000017500000001367411244607062031141 0ustar adrianadrian/* * Created on Jul 17, 2006 * Created by Alon Rohter * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.peermanager.uploadslots; import java.util.*; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.util.*; /** * */ public class UploadSessionPicker { private final LinkedList next_optimistics = new LinkedList(); private final AEMonitor next_optimistics_mon = new AEMonitor( "UploadSessionPicker" ); private final LinkedList helpers = new LinkedList(); private final DownloadingRanker down_ranker = new DownloadingRanker(); private final SeedingRanker seed_ranker = new SeedingRanker(); protected UploadSessionPicker() { /*nothing*/ } protected void registerHelper( UploadHelper helper ) { try { next_optimistics_mon.enter(); helpers.add( helper ); int priority = helper.getPriority(); //the higher the priority, the more optimistic unchoke chances they get for( int i=0; i < priority; i++ ) { insertHelper( helper ); } } finally { next_optimistics_mon.exit(); } } protected void deregisterHelper( UploadHelper helper ) { try { next_optimistics_mon.enter(); helpers.remove( helper ); boolean rem = next_optimistics.removeAll( Collections.singleton( helper ) ); if( !rem ) Debug.out( "!rem" ); } finally { next_optimistics_mon.exit(); } } protected void updateHelper( UploadHelper helper ) { try { next_optimistics_mon.enter(); int priority = helper.getPriority(); //new priority int count = 0; for( Iterator it = next_optimistics.iterator(); it.hasNext(); ) { UploadHelper h = (UploadHelper)it.next(); if( h == helper ) { count++; if( count > priority ) { //new priority is lower it.remove(); //trim } } } if( count < priority ) { //new priority is higher for( int i=count; i < priority; i++ ) { insertHelper( helper ); //add } } } finally { next_optimistics_mon.exit(); } } private void insertHelper( UploadHelper helper ) { int pos = RandomUtils.nextInt( next_optimistics.size() + 1 ); //pick a random location next_optimistics.add( pos, helper ); //store into location } protected int getHelperCount() { try { next_optimistics_mon.enter(); return next_optimistics.size(); } finally { next_optimistics_mon.exit(); } } //this picks both downloading and seeding sessions protected UploadSession pickNextOptimisticSession() { try { next_optimistics_mon.enter(); HashSet failed_helpers = null; int loops_allowed = next_optimistics.size(); while( loops_allowed > 0 ) { UploadHelper helper = (UploadHelper)next_optimistics.removeFirst(); //take from front next_optimistics.addLast( helper ); //add back at end if( failed_helpers == null || !failed_helpers.contains( helper ) ) { //pre-emptive check to see if we've already tried this helper PEPeer peer; if( helper.isSeeding() ) { peer = seed_ranker.getNextOptimisticPeer( helper.getAllPeers() ); } else { peer = down_ranker.getNextOptimisticPeer( helper.getAllPeers() ); } if( peer == null ) { //no peers from this helper to unchoke if( failed_helpers == null ) failed_helpers = new HashSet(); //lazy alloc failed_helpers.add( helper ); //remember this helper in case we get it again in another loop round } else { //found an optimistic peer! return new UploadSession( peer, helper.isSeeding() ? UploadSession.TYPE_SEED : UploadSession.TYPE_DOWNLOAD ); } } loops_allowed--; } return null; //no optimistic peer found } finally { next_optimistics_mon.exit(); } } private ArrayList globalGetAllDownloadPeers() { try { next_optimistics_mon.enter(); ArrayList all = new ArrayList(); for( Iterator it = helpers.iterator(); it.hasNext(); ) { UploadHelper helper = (UploadHelper)it.next(); if( !helper.isSeeding() ) { //filter out seeding all.addAll( helper.getAllPeers() ); } } return all; } finally { next_optimistics_mon.exit(); } } //this picks downloading sessions only protected LinkedList pickBestDownloadSessions( int max_sessions ) { //TODO factor download priority into best calculation? ArrayList all_peers = globalGetAllDownloadPeers(); if( all_peers.isEmpty() ) return new LinkedList(); ArrayList best = down_ranker.rankPeers( max_sessions, all_peers ); if( best.size() != max_sessions ) { Debug.outNoStack( "best.size()[" +best.size()+ "] != max_sessions[" +max_sessions+ "]" ); } if( best.isEmpty() ) { return new LinkedList(); } LinkedList best_sessions = new LinkedList(); for( Iterator it = best.iterator(); it.hasNext(); ) { PEPeer peer = it.next(); UploadSession session = new UploadSession( peer, UploadSession.TYPE_DOWNLOAD ); best_sessions.add( session ); } return best_sessions; } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/0000755000175000017500000000000011310377620021116 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceInternetGateway.java0000644000175000017500000000160011140225434026204 0ustar adrianadrian/* * Created on Jan 28, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface DeviceInternetGateway extends Device { } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceManagerException.java0000644000175000017500000000210011141775140026324 0ustar adrianadrian/* * Created on Feb 2, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; @SuppressWarnings("serial") public class DeviceManagerException extends Exception { public DeviceManagerException( String str ) { super( str ); } public DeviceManagerException( String str, Throwable e ) { super( str, e ); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeProvider.java0000644000175000017500000000304611231244042025412 0ustar adrianadrian/* * Created on Feb 4, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; import java.io.File; import java.net.URL; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; public interface TranscodeProvider { public String getName(); public TranscodeProfile[] getProfiles(); public TranscodeProfile getProfile( String UID ); public TranscodeProviderAnalysis analyse( TranscodeProviderAdapter adapter, DiskManagerFileInfo input, TranscodeProfile profile ) throws TranscodeException; public TranscodeProviderJob transcode( TranscodeProviderAdapter adapter, TranscodeProviderAnalysis analysis, boolean force, DiskManagerFileInfo input, TranscodeProfile profile, URL output ) throws TranscodeException; public File getAssetDirectory(); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/0000755000175000017500000000000011310377622022061 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererImpl.java0000644000175000017500000001053711236202400027366 0ustar adrianadrian/* * Created on Jan 28, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.IndentWriter; import com.aelitis.azureus.core.devices.*; import com.aelitis.net.upnp.UPnPDevice; public class DeviceMediaRendererImpl extends DeviceUPnPImpl implements DeviceMediaRenderer { protected DeviceMediaRendererImpl( DeviceManagerImpl _manager, UPnPDevice _device ) { super( _manager, _device, Device.DT_MEDIA_RENDERER ); } protected DeviceMediaRendererImpl( DeviceManagerImpl _manager, String _classification ) { super( _manager, Device.DT_MEDIA_RENDERER, _classification ); } protected DeviceMediaRendererImpl( DeviceManagerImpl _manager, String _classification, boolean _manual, String _name ) { super( _manager, Device.DT_MEDIA_RENDERER, _classification, _manual, _name ); } protected DeviceMediaRendererImpl( DeviceManagerImpl _manager, String _uuid, String _classification, boolean _manual ) { super( _manager, Device.DT_MEDIA_RENDERER, _uuid, _classification, _manual ); } protected DeviceMediaRendererImpl( DeviceManagerImpl _manager, Map _map ) throws IOException { super(_manager, _map ); } @Override protected boolean updateFrom( DeviceImpl _other, boolean _is_alive ) { if ( !super.updateFrom( _other, _is_alive )){ return( false ); } if ( !( _other instanceof DeviceMediaRendererImpl )){ Debug.out( "Inconsistent" ); return( false ); } DeviceMediaRendererImpl other = (DeviceMediaRendererImpl)_other; return( true ); } @Override protected void initialise() { super.initialise(); } @Override protected void destroy() { super.destroy(); } public boolean canCopyToDevice() { return( false ); } public int getCopyToDevicePending() { return( 0 ); } public boolean canAutoStartDevice() { return( false ); } public boolean getAutoStartDevice() { return( false ); } public void setAutoStartDevice( boolean auto ) { } public boolean canCopyToFolder() { return( false ); } public File getCopyToFolder() { return( null ); } public void setCopyToFolder( File file ) { } public int getCopyToFolderPending() { return( 0 ); } public boolean getAutoCopyToFolder() { return( false ); } public void setAutoCopyToFolder( boolean auto ) { } public void manualCopy() throws DeviceManagerException { throw( new DeviceManagerException( "Unsupported" )); } public boolean canShowCategories() { return( false ); } public void setShowCategories( boolean b ) { setPersistentBooleanProperty( PP_REND_SHOW_CAT, b ); } public boolean getShowCategories() { return( getPersistentBooleanProperty( PP_REND_SHOW_CAT, getShowCategoriesDefault())); } protected boolean getShowCategoriesDefault() { return( false ); } @Override protected void getDisplayProperties( List dp ) { super.getDisplayProperties( dp ); if ( canCopyToFolder()){ addDP( dp, "devices.copy.folder.auto", getAutoCopyToFolder()); addDP( dp, "devices.copy.folder.dest", getCopyToFolder()); } if ( canShowCategories()){ addDP( dp, "devices.cat.show", getShowCategories()); } super.getTTDisplayProperties( dp ); } @Override public void generate( IndentWriter writer ) { super.generate( writer ); try{ writer.indent(); generateTT( writer ); }finally{ writer.exdent(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceInternetGatewayImpl.java0000644000175000017500000001527311236202400027774 0ustar adrianadrian/* * Created on Jan 28, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.IOException; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginInterface; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.devices.*; import com.aelitis.azureus.plugins.upnp.UPnPMapping; import com.aelitis.azureus.plugins.upnp.UPnPPlugin; import com.aelitis.azureus.plugins.upnp.UPnPPluginService; import com.aelitis.net.upnp.UPnPDevice; import com.aelitis.net.upnp.services.UPnPWANConnection; public class DeviceInternetGatewayImpl extends DeviceUPnPImpl implements DeviceInternetGateway { private static final int CHECK_MAPPINGS_PERIOD = 30*1000; private static final int CHECK_MAPPINGS_TICK_COUNT = CHECK_MAPPINGS_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD; private static UPnPPlugin upnp_plugin; static{ AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { try { PluginInterface pi_upnp = core.getPluginManager().getPluginInterfaceByClass( UPnPPlugin.class); if (pi_upnp != null) { upnp_plugin = (UPnPPlugin) pi_upnp.getPlugin(); } } catch (Throwable e) { } } }); } private static List igds; private boolean mapper_enabled; private UPnPPluginService[] current_services; private UPnPMapping[] current_mappings; protected DeviceInternetGatewayImpl( DeviceManagerImpl _manager, UPnPDevice _device, List _connections ) { super( _manager, _device, Device.DT_INTERNET_GATEWAY ); updateStatus( 0 ); } protected DeviceInternetGatewayImpl( DeviceManagerImpl _manager, Map _map ) throws IOException { super(_manager, _map ); } protected boolean updateFrom( DeviceImpl _other, boolean _is_alive ) { if ( !super.updateFrom( _other, _is_alive )){ return( false ); } if ( !( _other instanceof DeviceInternetGatewayImpl )){ Debug.out( "Inconsistent" ); return( false ); } DeviceInternetGatewayImpl other = (DeviceInternetGatewayImpl)_other; return( true ); } @Override protected void updateStatus( int tick_count ) { super.updateStatus( tick_count ); if ( tick_count % CHECK_MAPPINGS_TICK_COUNT != 0 ){ return; } mapper_enabled = upnp_plugin != null && upnp_plugin.isEnabled(); UPnPDevice device = getUPnPDevice(); if ( mapper_enabled && device != null ){ current_services = upnp_plugin.getServices( device ); current_mappings = upnp_plugin.getMappings(); } } protected URL getPresentationURL( UPnPDevice device ) { URL url = super.getPresentationURL( device ); if ( url == null ){ try{ // no explicit one, try hitting location URL loc = device.getRootDevice().getLocation(); URL test_loc = new URL( loc.getProtocol() + "://" + loc.getHost() + "/" ); test_loc.openConnection().connect(); return( test_loc ); }catch( Throwable e ){ } } return( url ); } protected Set getRequiredMappings() { Set res = new TreeSet(); UPnPMapping[] required_mappings = current_mappings; if ( required_mappings != null ){ for ( UPnPMapping mapping: required_mappings ){ if ( mapping.isEnabled()){ res.add( new mapping( mapping )); } } } return( res ); } protected Set getActualMappings( UPnPPluginService service ) { UPnPPluginService.serviceMapping[] actual_mappings = service.getMappings(); Set actual = new TreeSet(); for ( UPnPPluginService.serviceMapping act_mapping: actual_mappings ){ mapping m = new mapping( act_mapping ); actual.add( m ); } return( actual ); } protected void getDisplayProperties( List dp ) { super.getDisplayProperties( dp ); addDP(dp, "device.router.is_mapping", mapper_enabled ); UPnPPluginService[] services = current_services; String req_map_str = ""; Set required = getRequiredMappings(); for ( mapping m: required ){ req_map_str += (req_map_str.length()==0?"":",") + m.getString(); } addDP( dp, "device.router.req_map", req_map_str ); if ( services != null ){ for ( UPnPPluginService service: services ){ Set actual = getActualMappings( service ); String act_map_str = ""; for ( mapping m: actual ){ if ( required.contains(m)){ act_map_str += (act_map_str.length()==0?"":",") + m.getString(); } } String service_name = MessageText.getString( "device.router.con_type", new String[]{ service.getService().getConnectionType() }); addDP( dp, "! " + service_name + "!", act_map_str ); } } } protected static class mapping implements Comparable { private boolean is_tcp; private int port; protected mapping( UPnPMapping m ) { is_tcp = m.isTCP(); port = m.getPort(); } protected mapping( UPnPPluginService.serviceMapping m ) { is_tcp = m.isTCP(); port = m.getPort(); } public int compareTo( mapping o ) { int res = port - o.port; if ( res == 0 ){ res = (is_tcp?1:0) - (o.is_tcp?1:0); } return( res ); } public boolean equals( Object _other ) { if ( _other instanceof mapping ){ mapping other = (mapping)_other; return( is_tcp == other.is_tcp && port == other.port ); }else{ return( false ); } } public int hashCode() { return((port<<16) + (is_tcp?1:0)); } public String getString() { return( (is_tcp?"TCP":"UDP") + " " + port ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceManagerUPnPImpl.java0000644000175000017500000004613111247323674027017 0ustar adrianadrian/* * Created on Jan 27, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginEvent; import org.gudy.azureus2.plugins.PluginEventListener; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.PluginListener; import org.gudy.azureus2.plugins.ipc.IPCInterface; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest; import org.gudy.azureus2.plugins.utils.UTTimer; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentException; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.ipc.IPCInterfaceImpl; import com.aelitis.azureus.core.content.AzureusContentDownload; import com.aelitis.azureus.core.content.AzureusContentFile; import com.aelitis.azureus.core.content.AzureusContentFilter; import com.aelitis.azureus.core.devices.DeviceMediaRenderer; import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice; import com.aelitis.azureus.core.util.UUIDGenerator; import com.aelitis.net.upnp.UPnP; import com.aelitis.net.upnp.UPnPAdapter; import com.aelitis.net.upnp.UPnPDevice; import com.aelitis.net.upnp.UPnPFactory; import com.aelitis.net.upnp.UPnPListener; import com.aelitis.net.upnp.UPnPRootDevice; import com.aelitis.net.upnp.UPnPRootDeviceListener; import com.aelitis.net.upnp.UPnPService; import com.aelitis.net.upnp.services.UPnPOfflineDownloader; import com.aelitis.net.upnp.services.UPnPWANConnection; public class DeviceManagerUPnPImpl { private final static Object KEY_ROOT_DEVICE = new Object(); private DeviceManagerImpl manager; private PluginInterface plugin_interface; private UPnP upnp; private TorrentAttribute ta_category; private volatile IPCInterface upnpav_ipc; private Map unassociated_devices = new HashMap(); protected DeviceManagerUPnPImpl( DeviceManagerImpl _manager ) { manager = _manager; } protected void initialise() { plugin_interface = PluginInitializer.getDefaultInterface(); ta_category = plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_CATEGORY ); plugin_interface.addListener( new PluginListener() { public void initializationComplete() { // startup can take a while as adding the upnp listener can sync call back device added and result // in device details loading etc new AEThread2( "DMUPnPAsyncStart", true ) { public void run() { startUp(); } }.start(); } public void closedownInitiated() { } public void closedownComplete() { } }); } protected DeviceManagerImpl getManager() { return( manager ); } protected TorrentAttribute getCategoryAttibute() { return( ta_category ); } protected void startUp() { UPnPAdapter adapter = new UPnPAdapter() { public SimpleXMLParserDocument parseXML( String data ) throws SimpleXMLParserDocumentException { return( plugin_interface.getUtilities().getSimpleXMLParserDocumentFactory().create( data )); } public ResourceDownloaderFactory getResourceDownloaderFactory() { return( plugin_interface.getUtilities().getResourceDownloaderFactory()); } public UTTimer createTimer( String name ) { return( plugin_interface.getUtilities().createTimer( name )); } public void createThread( String name, final Runnable runnable ) { plugin_interface.getUtilities().createThread( name, runnable ); } public Comparator getAlphanumericComparator() { return( plugin_interface.getUtilities().getFormatters().getAlphanumericComparator( true )); } public void log( Throwable e ) { Debug.printStackTrace(e); } public void trace( String str ) { // System.out.println( str ); } public void log( String str ) { // System.out.println( str ); } public String getTraceDir() { return( plugin_interface.getPluginDirectoryName()); } }; try{ upnp = UPnPFactory.getSingleton( adapter, null ); upnp.addRootDeviceListener( new UPnPListener() { public boolean deviceDiscovered( String USN, URL location ) { return( true ); } public void rootDeviceFound( UPnPRootDevice device ) { handleDevice( device, true ); } }); }catch( Throwable e ){ manager.log( "UPnP device manager failed", e ); } try{ plugin_interface.addEventListener( new PluginEventListener() { public void handleEvent( PluginEvent ev ) { int type = ev.getType(); if ( type == PluginEvent.PEV_PLUGIN_OPERATIONAL || type == PluginEvent.PEV_PLUGIN_NOT_OPERATIONAL ){ PluginInterface pi = (PluginInterface)ev.getValue(); if ( pi.getPluginID().equals( "azupnpav" )){ if ( type == PluginEvent.PEV_PLUGIN_OPERATIONAL ){ upnpav_ipc = pi.getIPC(); addListener( pi ); }else{ upnpav_ipc = null; } } } } }); PluginInterface pi = plugin_interface.getPluginManager().getPluginInterfaceByID( "azupnpav" ); if ( pi == null ){ manager.log( "No UPnPAV plugin found" ); }else{ upnpav_ipc = pi.getIPC(); addListener( pi ); } }catch( Throwable e ){ manager.log( "Failed to hook into UPnPAV", e ); } manager.UPnPManagerStarted(); } protected void addListener( PluginInterface pi ) { try{ IPCInterface my_ipc = new IPCInterfaceImpl( new Object() { public Map browseReceived( TrackerWebPageRequest request, Map browser_args ) { Map headers = request.getHeaders(); String user_agent = (String)headers.get( "user-agent" ); String client_info = (String)headers.get( "x-av-client-info" ); InetSocketAddress client_address = request.getClientAddress2(); boolean handled = false; if ( user_agent != null ){ String lc_agent = user_agent.toLowerCase(); if ( lc_agent.contains( "playstation 3")){ handlePS3( client_address ); handled = true; }else if ( lc_agent.contains( "xbox")){ handleXBox( client_address ); handled = true; }else if ( lc_agent.contains( "nintendo wii")){ handleWii( client_address ); handled = true; } } if ( client_info != null ){ String lc_info = client_info.toLowerCase(); if ( lc_info.contains( "playstation 3")){ handlePS3( client_address ); handled = true; } } if ( !handled ){ String source = (String)browser_args.get( "source" ); if ( source != null && source.equalsIgnoreCase( "http" )){ handleBrowser( client_address ); handled = true; } } /* System.out.println( "Received browse: " + request.getClientAddress() + ", agent=" + user_agent + ", info=" + client_info ); */ DeviceImpl[] devices = manager.getDevices(); final List browse_devices = new ArrayList(); for ( DeviceImpl device: devices ){ if ( device instanceof DeviceMediaRendererImpl ){ DeviceMediaRendererImpl renderer = (DeviceMediaRendererImpl)device; InetAddress device_address = renderer.getAddress(); try{ if ( device_address != null ){ // just test on IP, should be OK if ( device_address.equals( client_address.getAddress())){ if ( renderer.canFilterFilesView()){ browse_devices.add( renderer ); renderer.browseReceived(); } } } }catch( Throwable e ){ Debug.out( e ); } } } Map result = new HashMap(); if ( browse_devices.size() > 0 ){ synchronized( unassociated_devices ){ unassociated_devices.remove( client_address.getAddress() ); } result.put( "filter", new AzureusContentFilter() { public boolean isVisible( AzureusContentDownload download, Map browse_args ) { boolean visible = false; for ( DeviceUPnPImpl device: browse_devices ){ if ( device.isVisible( download )){ visible = true; } } return( visible ); } public boolean isVisible( AzureusContentFile file, Map browse_args ) { boolean visible = false; for ( DeviceUPnPImpl device: browse_devices ){ if ( device.isVisible( file )){ visible = true; } } return( visible ); } }); }else{ if ( request.getHeader().substring(0,4).equalsIgnoreCase( "POST" )){ synchronized( unassociated_devices ){ unassociated_devices.put( client_address.getAddress(), user_agent ); } } } return( result ); } }); if ( upnpav_ipc.canInvoke( "addBrowseListener", new Object[]{ my_ipc })){ upnpav_ipc.invoke( "addBrowseListener", new Object[]{ my_ipc }); DeviceImpl[] devices = manager.getDevices(); for ( DeviceImpl device: devices ){ if ( device instanceof DeviceUPnPImpl ){ DeviceUPnPImpl u_d = (DeviceUPnPImpl)device; u_d.resetUPNPAV(); } } }else{ manager.log( "UPnPAV plugin needs upgrading" ); } }catch( Throwable e ){ manager.log( "Failed to hook into UPnPAV", e ); } } protected void injectDiscoveryCache( Map cache ) { try{ upnp.injectDiscoveryCache( cache ); }catch( Throwable e ){ Debug.out( e ); } } public UnassociatedDevice[] getUnassociatedDevices() { List result = new ArrayList(); Map ud; synchronized( unassociated_devices ){ ud = new HashMap( unassociated_devices ); } DeviceImpl[] devices = manager.getDevices(); for ( final Map.Entry entry: ud.entrySet()){ InetAddress address = entry.getKey(); boolean already_assoc = false; for ( DeviceImpl d: devices ){ if ( d instanceof DeviceMediaRendererImpl ){ DeviceMediaRendererImpl r = (DeviceMediaRendererImpl)d; if ( d.isAlive() && r.getAddress().equals( address )){ already_assoc = true; break; } } } if ( !already_assoc ){ result.add( new UnassociatedDevice() { public InetAddress getAddress() { return( entry.getKey()); } public String getDescription() { return( entry.getValue()); } }); } } return( result.toArray( new UnassociatedDevice[result.size()])); } public PluginInterface getPluginInterface() { return( plugin_interface ); } protected IPCInterface getUPnPAVIPC() { return( upnpav_ipc ); } public void search() { if ( upnp != null ){ // if the user has removed items we need to re-inject them UPnPRootDevice[] devices = upnp.getRootDevices(); for ( UPnPRootDevice device: devices ){ handleDevice( device, false ); } String[] STs = { "upnp:rootdevice", "urn:schemas-upnp-org:device:MediaRenderer:1" }; upnp.search( STs ); } } protected void handleXBox( InetSocketAddress address ) { // normally we can detect the xbox renderer and things work automagically. However, on // occasion we receive the browse before detection and if the device's IP has changed // we need to associate its new address here otherwise association of browse to device // fails DeviceImpl[] devices = manager.getDevices(); boolean found = false; for ( DeviceImpl device: devices ){ if ( device instanceof DeviceMediaRendererImpl ){ DeviceMediaRendererImpl renderer = (DeviceMediaRendererImpl)device; if ( device.getRendererSpecies() == DeviceMediaRenderer.RS_XBOX ){ found = true; if (!device.isAlive()){ renderer.setAddress( address.getAddress()); device.alive(); } } } } if ( !found ){ manager.addDevice( new DeviceMediaRendererImpl( manager, "Xbox 360" )); } } protected void handlePS3( InetSocketAddress address ) { handleGeneric( address, "ps3", "PS3" ); } protected void handleWii( InetSocketAddress address ) { handleGeneric( address, "wii", "Wii" ); } protected void handleBrowser( InetSocketAddress address ) { handleGeneric( address, "browser", "Browser" ); } protected void handleGeneric( InetSocketAddress address, String unique_name, String display_name ) { String uid; synchronized( this ){ uid = COConfigurationManager.getStringParameter( "devices.upnp.uid." + unique_name, "" ); if ( uid.length() == 0 ){ uid = UUIDGenerator.generateUUIDString(); COConfigurationManager.setParameter( "devices.upnp.uid." + unique_name, uid ); COConfigurationManager.save(); } } DeviceMediaRendererImpl device = new DeviceMediaRendererImpl( manager, uid, display_name, false ); device = (DeviceMediaRendererImpl)manager.addDevice( device ); device.setAddress( address.getAddress()); device.alive(); } protected void handleDevice( UPnPRootDevice root_device, boolean update_if_found ) { if ( !manager.getAutoSearch()){ if ( !manager.isExplicitSearch()){ return; } } handleDevice( root_device.getDevice(), update_if_found ); } protected void handleDevice( UPnPDevice device, boolean update_if_found ) { UPnPService[] services = device.getServices(); List new_devices = new ArrayList(); List igd_services = new ArrayList(); for ( UPnPService service: services ){ String service_type = service.getServiceType(); if ( service_type.equalsIgnoreCase( "urn:schemas-upnp-org:service:WANIPConnection:1") || service_type.equalsIgnoreCase( "urn:schemas-upnp-org:service:WANPPPConnection:1")){ UPnPWANConnection wan_service = (UPnPWANConnection)service.getSpecificService(); igd_services.add( wan_service ); }else if ( service_type.equals( "urn:schemas-upnp-org:service:ContentDirectory:1" )){ new_devices.add( new DeviceContentDirectoryImpl( manager, device, service )); }else if ( service_type.equals( "urn:schemas-upnp-org:service:VuzeOfflineDownloaderService:1" )){ // ignore local offline downloader try{ PluginInterface od_pi = plugin_interface.getPluginManager().getPluginInterfaceByID( "azofflinedownloader" ); if ( od_pi != null ){ String local_usn = (String)od_pi.getIPC().invoke( "getUSN", new Object[0] ); String od_usn = device.getRootDevice().getUSN(); // we end up with "::upnp:rootdevice" on the end of this - remove int pos = od_usn.indexOf( "::upnp:rootdevice" ); if ( pos > 0 ){ od_usn = od_usn.substring( 0, pos ); } if ( od_usn.equals( local_usn )){ continue; } } }catch( Throwable e ){ Debug.out( e ); } UPnPOfflineDownloader downloader = (UPnPOfflineDownloader)service.getSpecificService(); if ( downloader != null ){ new_devices.add( new DeviceOfflineDownloaderImpl( manager, device, downloader )); } } } if ( igd_services.size() > 0 ){ new_devices.add( new DeviceInternetGatewayImpl( manager, device, igd_services )); } if ( device.getDeviceType().equals( "urn:schemas-upnp-org:device:MediaRenderer:1" )){ new_devices.add( new DeviceMediaRendererImpl( manager, device )); } for ( final DeviceUPnPImpl new_device: new_devices ){ final DeviceImpl actual_device; DeviceImpl existing = manager.getDevice( new_device.getID()); if ( !update_if_found && existing != null ){ actual_device = existing; }else{ // grab the actual device as the 'addDevice' call will update an existing one // with same id actual_device = manager.addDevice( new_device ); } UPnPRootDevice current_root = device.getRootDevice(); UPnPRootDevice existing_root = (UPnPRootDevice)actual_device.getTransientProperty( KEY_ROOT_DEVICE ); if ( current_root != existing_root ){ actual_device.setTransientProperty( KEY_ROOT_DEVICE, current_root ); current_root.addListener( new UPnPRootDeviceListener() { public void lost( UPnPRootDevice root, boolean replaced ) { if ( !replaced ){ actual_device.dead(); } } }); } } for (UPnPDevice d: device.getSubDevices()){ handleDevice( d, update_if_found ); } } }azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceManagerRSSFeed.java0000644000175000017500000002560411264473526026611 0ustar adrianadrian/* * Created on Jul 13, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetSocketAddress; import java.net.URL; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.core3.xml.util.XUXmlWriter; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse; import com.aelitis.azureus.core.devices.Device; import com.aelitis.azureus.core.rssgen.RSSGeneratorPlugin; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; public class DeviceManagerRSSFeed implements RSSGeneratorPlugin.Provider { private static final String PROVIDER = "devices"; private DeviceManagerImpl manager; private RSSGeneratorPlugin generator; protected DeviceManagerRSSFeed( DeviceManagerImpl _manager ) { manager = _manager; generator = RSSGeneratorPlugin.getSingleton(); generator.registerProvider( PROVIDER, this ); } public boolean isEnabled() { return( manager.isRSSPublishEnabled()); } public String getFeedURL() { return( generator.getURL() + PROVIDER ); } public boolean generate( TrackerWebPageRequest request, TrackerWebPageResponse response ) throws IOException { InetSocketAddress local_address = request.getLocalAddress(); if ( local_address == null ){ return( false ); } URL url = request.getAbsoluteURL(); String path = url.getPath(); path = path.substring( PROVIDER.length()+1); DeviceImpl[] devices = manager.getDevices(); OutputStream os = response.getOutputStream(); PrintWriter pw = new PrintWriter(new OutputStreamWriter( os, "UTF-8" )); if ( path.length() <= 1 ){ response.setContentType( "text/html; charset=UTF-8" ); pw.println( "Vuze Device Feeds" ); for ( DeviceImpl d: devices ){ if ( d.getType() != Device.DT_MEDIA_RENDERER || d.isHidden() || !d.isRSSPublishEnabled()){ continue; } String name = d.getName(); pw.println( "
  • " + name + "
  • " ); } pw.println( "" ); }else{ String device_name = URLDecoder.decode( path.substring( 1 ), "UTF-8" ); DeviceImpl device = null; for ( DeviceImpl d: devices ){ if ( d.getName().equals( device_name ) && d.isRSSPublishEnabled()){ device = d; break; } } if ( device == null ){ response.setReplyStatus( 404 ); return( true ); } URL feed_url = url; // absolute url is borked as it doesn't set the host properly. hack String host = (String)request.getHeaders().get( "host" ); if ( host != null ){ int pos = host.indexOf( ':' ); if ( pos != -1 ){ host = host.substring( 0, pos ); } feed_url = UrlUtils.setHost( url, host ); } if ( device instanceof DeviceMediaRendererImpl ){ ((DeviceMediaRendererImpl)device).browseReceived(); } response.setContentType( "application/xml" ); pw.println( "" ); pw.println( "" ); pw.println( "" ); String channel_title = "Vuze Device: " + escape( device.getName()); pw.println( "" + channel_title + "" ); pw.println( "http://vuze.com" ); pw.println( "" ); pw.println( "Vuze RSS Feed for device " + escape( device.getName()) + "" ); pw.println(""); pw.println("http://www.vuze.com/img/vuze_icon_128.png" + channel_title + "http://vuze.com"); TranscodeFileImpl[] _files = device.getFiles(); List files = new ArrayList( _files.length ); files.addAll( Arrays.asList( _files )); Collections.sort( files, new Comparator() { public int compare( TranscodeFileImpl f1, TranscodeFileImpl f2) { long added1 = f1.getCreationDateMillis()/1000; long added2 = f2.getCreationDateMillis()/1000; return((int)(added2 - added1 )); } }); String feed_date_key = "devices.feed_date." + device.getID(); long feed_date = COConfigurationManager.getLongParameter( feed_date_key ); boolean new_date = false; for ( TranscodeFileImpl file: files ){ long file_date = file.getCreationDateMillis(); if ( file_date > feed_date ){ new_date = true; feed_date = file_date; } } if ( new_date ){ COConfigurationManager.setParameter( feed_date_key, feed_date ); } pw.println( "" + TimeFormatter.getHTTPDate( feed_date ) + "" ); for ( TranscodeFileImpl file: files ){ if ( !file.isComplete()){ if ( !file.isTemplate()){ continue; } } try{ pw.println( "" ); pw.println( "" + escape( file.getName()) + "" ); pw.println( "" + TimeFormatter.getHTTPDate( file.getCreationDateMillis()) + "" ); pw.println( "" + escape( file.getKey()) + "" ); String[] categories = file.getCategories(); for ( String category: categories ){ pw.println( "" + category + "" ); } String mediaContent = ""; URL stream_url = file.getStreamURL( feed_url.getHost() ); if ( stream_url != null ){ String url_ext = stream_url.toExternalForm(); long fileSize = file.getTargetFile().getLength(); pw.println( "" + url_ext + "" ); mediaContent = ""); } String thumb_url = null; String author = null; String description = null; try{ Torrent torrent = file.getSourceFile().getDownload().getTorrent(); TOTorrent toTorrent = PluginCoreUtils.unwrap(torrent); long duration_secs = PlatformTorrentUtils.getContentVideoRunningTime(toTorrent); if ( mediaContent.length() > 0 && duration_secs > 0 ){ mediaContent += " duration=\"" + duration_secs + "\""; } thumb_url = PlatformTorrentUtils.getContentThumbnailUrl(toTorrent); author = PlatformTorrentUtils.getContentAuthor(toTorrent); description= PlatformTorrentUtils.getContentDescription(toTorrent); if ( description != null ){ description = escapeMultiline( description ); /* if ( thumb_url != null ){ pw.println( "" + escape( "
    " ) + description + escape( "
    " ) + "
    " ); }else{ */ pw.println( "" + description + ""); //} } }catch( Throwable e ){ } // media elements if ( mediaContent.length() > 0 ){ pw.println( mediaContent += ">
    " ); } pw.println( "" + escape( file.getName()) + "" ); if ( description != null ){ pw.println( "" + description + "" ); } if ( thumb_url != null ) { pw.println("" ); } // iTunes elements if ( thumb_url != null ) { pw.println(""); } if ( author != null ){ pw.println("" + escape(author) + ""); } pw.println( "" + escape( file.getName()) + "" ); pw.println( "" + TimeFormatter.formatColon( file.getDurationMillis()/1000 ) + "" ); pw.println( "
    " ); }catch( Throwable e ){ Debug.out(e); } } pw.println( "
    " ); pw.println( "
    " ); } pw.flush(); return( true ); } protected String escape( String str ) { return( XUXmlWriter.escapeXML(str)); } protected String escapeMultiline( String str ) { return( XUXmlWriter.escapeXML(str.replaceAll("[\r\n]+", "
    "))); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceiTunesManager.java0000644000175000017500000000707011236202400026576 0ustar adrianadrian/* * Created on Feb 10, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import org.gudy.azureus2.plugins.PluginEvent; import org.gudy.azureus2.plugins.PluginEventListener; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.PluginListener; import org.gudy.azureus2.plugins.PluginManager; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; public class DeviceiTunesManager { private DeviceManagerImpl device_manager; private DeviceiTunes itunes_device; protected DeviceiTunesManager( DeviceManagerImpl _dm ) { device_manager = _dm; AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { init(core); } }); } private void init( AzureusCore azureus_core ) { final PluginManager pm = azureus_core.getPluginManager(); final PluginInterface default_pi = pm.getDefaultPluginInterface(); default_pi.addListener( new PluginListener() { public void initializationComplete() { default_pi.addEventListener( new PluginEventListener() { public void handleEvent( PluginEvent ev ) { int type = ev.getType(); if ( type == PluginEvent.PEV_PLUGIN_OPERATIONAL ){ pluginAdded((PluginInterface)ev.getValue()); } if ( type == PluginEvent.PEV_PLUGIN_NOT_OPERATIONAL ){ pluginRemoved((PluginInterface)ev.getValue()); } } }); PluginInterface[] plugins = pm.getPlugins(); for ( PluginInterface pi: plugins ){ if ( pi.getPluginState().isOperational()){ pluginAdded( pi ); } } } public void closedownInitiated() { } public void closedownComplete() { } }); } protected void pluginAdded( PluginInterface pi ) { if ( pi.getPluginState().isBuiltIn()){ return; } String plugin_id = pi.getPluginID(); if ( plugin_id.equals( "azitunes" )){ DeviceiTunes new_device; synchronized( this ){ if ( itunes_device == null ){ itunes_device = new_device = new DeviceiTunes( device_manager, pi ); }else{ return; } } device_manager.addDevice( new_device, false ); } } protected void pluginRemoved( PluginInterface pi ) { String plugin_id = pi.getPluginID(); if ( plugin_id.equals( "azitunes" )){ DeviceiTunes existing_device; synchronized( this ){ if ( itunes_device != null ){ existing_device = itunes_device; itunes_device = null; }else{ return; } } existing_device.remove(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererManual.java0000644000175000017500000002531411252046360027712 0ustar adrianadrian/* * Created on Jul 10, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.AsyncDispatcher; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.IndentWriter; import com.aelitis.azureus.core.devices.DeviceManagerException; import com.aelitis.azureus.core.devices.TranscodeException; import com.aelitis.azureus.core.devices.TranscodeFile; import com.aelitis.azureus.core.devices.TranscodeTargetListener; public class DeviceMediaRendererManual extends DeviceMediaRendererImpl { private static final Object COPY_ERROR_KEY = new Object(); private static final Object COPY_PENDING_KEY = new Object(); private boolean copy_outstanding; private boolean copy_outstanding_set; private AEThread2 copy_thread; private AESemaphore copy_sem = new AESemaphore( "Device:copy" ); private AsyncDispatcher async_dispatcher = new AsyncDispatcher( 5000 ); protected DeviceMediaRendererManual( DeviceManagerImpl _manager, String _classification, boolean _manual, String _name ) { super( _manager,_classification, _manual, _name ); } protected DeviceMediaRendererManual( DeviceManagerImpl _manager, Map _map ) throws IOException { super(_manager, _map ); } protected void initialise() { super.initialise(); if ( getPersistentBooleanProperty( PP_COPY_OUTSTANDING, false )){ setCopyOutstanding(); } addListener( new TranscodeTargetListener() { public void fileAdded( TranscodeFile file ) { if ( file.isComplete() && !file.isCopiedToDevice()){ setCopyOutstanding(); } } public void fileChanged( TranscodeFile file, int type, Object data ) { if ( file.isComplete() && !file.isCopiedToDevice()){ setCopyOutstanding(); } } public void fileRemoved( TranscodeFile file ) { copy_sem.release(); } }); } public boolean canAssociate() { return( false ); } public boolean canFilterFilesView() { return( false ); } public boolean isBrowsable() { return( false ); } public boolean canCopyToFolder() { return( true ); } public File getCopyToFolder() { String str = getPersistentStringProperty( PP_COPY_TO_FOLDER, null ); if ( str == null ){ return( null ); } return( new File( str )); } public void setCopyToFolder( File file ) { setPersistentStringProperty( PP_COPY_TO_FOLDER, file==null?null:file.getAbsolutePath()); if ( getAutoCopyToFolder()){ setCopyOutstanding(); } } public boolean isLivenessDetectable() { return( getPersistentBooleanProperty( PP_LIVENESS_DETECTABLE, false )); } public void setLivenessDetectable( boolean b ) { setPersistentBooleanProperty( PP_LIVENESS_DETECTABLE, true ); } public int getCopyToFolderPending() { synchronized( this ){ if ( !copy_outstanding ){ return( 0 ); } } TranscodeFileImpl[] files = getFiles(); int result = 0; for ( TranscodeFileImpl file: files ){ if ( file.isComplete() && !file.isCopiedToDevice()){ result++; } } return( result ); } public boolean getAutoCopyToFolder() { return( getPersistentBooleanProperty( PP_AUTO_COPY, PP_AUTO_COPY_DEFAULT )); } public void setAutoCopyToFolder( boolean auto ) { setPersistentBooleanProperty( PP_AUTO_COPY, auto ); setCopyOutstanding(); } public void manualCopy() throws DeviceManagerException { if ( getAutoCopyToFolder()){ throw( new DeviceManagerException( "Operation prohibited - auto copy enabled" )); } doCopy(); } protected void setCopyOutstanding() { synchronized( this ){ copy_outstanding_set = true; if ( copy_thread == null ){ copy_thread = new AEThread2( "Device:copier", true ) { public void run() { performCopy(); } }; copy_thread.start(); } copy_sem.release(); } } public boolean isAudioCompatible( TranscodeFile transcode_file ) { if ( getDeviceClassification().equals( "sony.PSP" )){ try{ File file = transcode_file.getSourceFile().getFile(); if ( file.exists()){ String name = file.getName().toLowerCase(); if ( name.endsWith( ".mp3" ) || name.endsWith( ".wma" )){ ((TranscodeFileImpl)transcode_file).setCopyToFolderOverride( ".." + File.separator + "MUSIC" ); return( true ); } } }catch( Throwable e ){ log( "audio compatible check failed", e ); } } return( false ); } protected void performCopy() { synchronized( this ){ copy_outstanding = true; async_dispatcher.dispatch( new AERunnable() { public void runSupport() { setPersistentBooleanProperty( PP_COPY_OUTSTANDING, true ); } }); } while( true ){ if ( copy_sem.reserve( 60*1000 )){ while( copy_sem.reserveIfAvailable()); } boolean auto_copy = getAutoCopyToFolder(); boolean nothing_to_do = false; synchronized( this ){ if ( !auto_copy ){ copy_thread = null; nothing_to_do = true; }else{ copy_outstanding_set = false; } } if ( nothing_to_do ){ setError( COPY_ERROR_KEY, null ); int pending = getCopyToFolderPending(); if ( pending == 0 ){ setInfo( COPY_PENDING_KEY, null ); }else{ String str = MessageText.getString( "devices.info.copypending", new String[]{ String.valueOf( pending ) }); setInfo( COPY_PENDING_KEY, str ); } return; } if ( doCopy()){ break; } } } protected boolean doCopy() { setInfo( COPY_PENDING_KEY, null ); File copy_to = getCopyToFolder(); List to_copy = new ArrayList(); boolean borked = false; TranscodeFileImpl[] files = getFiles(); int pending = 0; for ( TranscodeFileImpl file: files ){ if ( file.isComplete() && !file.isCopiedToDevice()){ pending++; if ( file.getCopyToDeviceFails() < 3 ){ to_copy.add( file ); }else{ String info = (String)file.getTransientProperty( COPY_ERROR_KEY ); setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copyfail") + (info==null?"":(" - " + info))); borked = true; } } } boolean try_copy = false; if ( to_copy.size() > 0 ){ // handle case where device is auto-detectable and copy-to is missing if ( isLivenessDetectable() && !isAlive() && ( copy_to == null || !copy_to.exists())){ String str = MessageText.getString( "devices.info.copypending2", new String[]{ String.valueOf( pending ) }); setInfo( COPY_PENDING_KEY, str ); borked = true; }else{ if ( copy_to == null ){ setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copytonotset" )); borked = true; }else if ( !copy_to.exists()){ setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copytomissing", new String[]{copy_to.getAbsolutePath()})); borked = true; }else if ( !copy_to.canWrite()){ setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copytonowrite", new String[]{copy_to.getAbsolutePath()})); borked = true; }else{ try_copy = true; setError( COPY_ERROR_KEY, null ); } } } synchronized( this ){ // all done, tidy up and exit if ( to_copy.size() == 0 && !copy_outstanding_set && !borked ){ copy_outstanding = false; async_dispatcher.dispatch( new AERunnable() { public void runSupport() { setError( COPY_ERROR_KEY, null ); setPersistentBooleanProperty( PP_COPY_OUTSTANDING, false ); } }); copy_thread = null; return( true ); } } if ( try_copy ){ try{ setBusy( true ); for ( TranscodeFileImpl transcode_file: to_copy ){ try{ File file = transcode_file.getTargetFile().getFile(); File target = new File( copy_to, file.getName()); String override_str = transcode_file.getCopyToFolderOverride(); if ( override_str != null ){ File override_dir = new File( copy_to, override_str ); if ( override_dir.exists()){ target = new File( override_dir, file.getName()); } } try{ FileUtil.copyFileWithException( file, target ); log( "Copied file '" + file + ": to " + copy_to ); transcode_file.setCopiedToDevice( true ); }catch( Throwable e ){ copy_to.delete(); transcode_file.setCopyToDeviceFailed(); transcode_file.setTransientProperty( COPY_ERROR_KEY, Debug.getNestedExceptionMessage( e )); log( "Failed to copy file " + file, e ); } }catch( TranscodeException e ){ // file has been deleted } } }finally{ setBusy( false ); } } return( false ); } protected void getDisplayProperties( List dp ) { super.getDisplayProperties( dp ); addDP( dp, "devices.copy.pending", copy_outstanding ); } public void generate( IndentWriter writer ) { super.generate( writer ); try{ writer.indent(); writer.println( "auto_copy=" + getAutoCopyToFolder() + ", copy_to=" + getCopyToFolder() + ", copy_os=" + copy_outstanding ); }finally{ writer.exdent(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceTivo.java0000644000175000017500000005174311236202400024763 0ustar adrianadrian/* * Created on Jul 24, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.URL; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.xml.util.XUXmlWriter; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse; import org.gudy.azureus2.pluginsimpl.local.utils.FormattersImpl; import com.aelitis.azureus.core.devices.TranscodeFile; public class DeviceTivo extends DeviceMediaRendererImpl { private static final boolean TRACE = false; private static final String NL = "\r\n"; private static Map> sort_comparators = new HashMap>(); static { sort_comparators.put( "Type", new Comparator() { public int compare( ItemInfo o1, ItemInfo o2 ) { if ( o1.isContainer() == o2.isContainer()){ return( 0 ); } if ( o1.isContainer()){ return( -1 ); } return( 1 ); } }); sort_comparators.put( "Title", new Comparator() { Comparator c = new FormattersImpl().getAlphanumericComparator( true ); public int compare( ItemInfo o1, ItemInfo o2 ) { return( c.compare( o1.getName(), o2.getName())); } }); sort_comparators.put( "CreationDate", new Comparator() { public int compare( ItemInfo o1, ItemInfo o2 ) { long res = o1.getCreationMillis() - o2.getCreationMillis(); if ( res < 0 ){ return( -1 ); }else if ( res > 0 ){ return( 1 ); }else{ return( 0 ); } } }); sort_comparators.put( "LastChangeDate", sort_comparators.get( "CreationDate" )); sort_comparators.put( "CaptureDate", sort_comparators.get( "CreationDate" )); } private String server_name; private boolean tried_tcp_beacon; protected DeviceTivo( DeviceManagerImpl _manager, String _uid, String _classification ) { super( _manager, _uid, _classification, false ); setName( "TiVo" ); } protected DeviceTivo( DeviceManagerImpl _manager, Map _map ) throws IOException { super( _manager, _map ); } protected boolean updateFrom( DeviceImpl _other, boolean _is_alive ) { if ( !super.updateFrom( _other, _is_alive )){ return( false ); } if ( !( _other instanceof DeviceTivo )){ Debug.out( "Inconsistent" ); return( false ); } DeviceTivo other = (DeviceTivo)_other; return( true ); } protected void initialise() { super.initialise(); } public boolean canFilterFilesView() { return( false ); } public boolean canAssociate() { return( true ); } public boolean canShowCategories() { return( true ); } protected boolean getShowCategoriesDefault() { return( true ); } protected String getMachineName() { return( getPersistentStringProperty( PP_TIVO_MACHINE, null )); } protected void found( DeviceTivoManager _tivo_manager, InetAddress _address, String _server_name, String _machine ) { boolean first_time = false; synchronized( this ){ if ( server_name == null ){ server_name = _server_name; first_time = true; } } if ( _machine == null && !tried_tcp_beacon ){ try{ Socket socket = new Socket(); try{ socket.connect( new InetSocketAddress( _address, 2190 ), 5000 ); socket.setSoTimeout( 5000 ); DataOutputStream dos = new DataOutputStream( socket.getOutputStream()); byte[] beacon_out = _tivo_manager.encodeBeacon( false, 0 ); dos.writeInt( beacon_out.length ); dos.write( beacon_out ); DataInputStream dis = new DataInputStream( socket.getInputStream()); int len = dis.readInt(); if ( len < 65536 ){ byte[] bytes = new byte[len]; int pos = 0; while( pos < len ){ int read = dis.read( bytes, pos, len-pos ); pos += read; } Map beacon_in = _tivo_manager.decodeBeacon( bytes, len ); _machine = beacon_in.get( "machine" ); } }finally{ socket.close(); } }catch( Throwable e ){ }finally{ tried_tcp_beacon = true; } } if ( _machine != null ){ String existing = getMachineName(); if ( existing == null || !existing.equals( _machine )){ setPersistentStringProperty( PP_TIVO_MACHINE, _machine ); } } setAddress( _address ); alive(); if ( first_time ){ browseReceived(); } } protected boolean generate( TrackerWebPageRequest request, TrackerWebPageResponse response ) throws IOException { InetSocketAddress local_address = request.getLocalAddress(); if ( local_address == null ){ return( false ); } String host = local_address.getAddress().getHostAddress(); String url = request.getURL(); if ( TRACE ){ System.out.println( "url: " + url ); } if ( !url.startsWith( "/TiVoConnect?" )){ return( false ); } int pos = url.indexOf( '?' ); if ( pos == -1 ){ return(false ); } String[] bits = url.substring( pos+1 ).split( "&" ); Map args = new HashMap(); for ( String bit: bits ){ String[] x = bit.split( "=" ); args.put( x[0], URLDecoder.decode( x[1], "UTF-8" )); } if ( TRACE ){ System.out.println( "args: " + args ); } // root folder /TiVoConnect?Command=QueryContainer&Container=%2F String command = args.get( "Command" ); if ( command == null ){ return( false ); } String reply = null; if ( command.equals( "QueryContainer" )){ String container = args.get( "Container" ); if ( container == null ){ return( false ); } if ( container.equals( "/" )){ reply = "" + NL + "" + NL + "
    " + NL + " " + server_name + "" + NL + " x-container/tivo-server" + NL + " x-container/folder" + NL + " 1" + NL + "
    " + NL + " " + NL + "
    " + NL + " " + server_name + "" + NL + " x-container/tivo-videos" + NL + " x-container/folder" + NL + "
    " + NL + " " + NL + " " + NL + " /TiVoConnect?Command=QueryContainer&Container=" + urlencode( "/Content" ) + "" + NL + " x-container/tivo-videos" + NL + " " + NL + " " + NL + "
    " + NL + " 0" + NL + " 1" + NL + "
    "; }else if ( container.startsWith( "/Content" )){ boolean show_categories = getShowCategories(); String recurse = args.get( "Recurse" ); if ( recurse != null && recurse.equals( "Yes" )){ show_categories = false; } TranscodeFileImpl[] tfs = getFiles(); String category = null; Map categories = null; if ( show_categories ){ if ( container.startsWith( "/Content/" )){ category = container.substring( container.lastIndexOf( '/' ) + 1 ); }else{ categories = new HashMap(); } } // build list of applicable items List items = new ArrayList( tfs.length ); for ( TranscodeFileImpl file: tfs ){ if ( !file.isComplete()){ // see if we can set up a stream xcode for this but only if we // know the duration and the transcode is in progress (done in setup) if ( !setupStreamXCode( file )){ continue; } } if ( category != null ){ boolean hit = false; String[] cats = file.getCategories(); for ( String c: cats ){ if ( c.equals( category )){ hit = true; } } if ( !hit ){ continue; } } FileInfo info = new FileInfo( file, host ); if ( info.isOK()){ boolean skip = false; if ( categories != null ){ String[] cats = file.getCategories(); if ( cats.length > 0 ){ skip = true; for ( String s: cats ){ ContainerInfo cont = categories.get( s ); if ( cont == null ){ items.add( cont = new ContainerInfo( s )); categories.put( s, cont ); } cont.addChild(); } } } if ( !skip ){ items.add( info ); } } } // sort String sort_order = args.get( "SortOrder" ); if ( sort_order != null ){ String[] keys = sort_order.split( "," ); final List> comparators = new ArrayList>(); final List reverses = new ArrayList(); for ( String key: keys ){ boolean reverse = false; if ( key.startsWith( "!" )){ reverse = true; key = key.substring(1); } Comparator comp = sort_comparators.get( key ); if ( comp != null ){ comparators.add( comp ); reverses.add( reverse ); } } if ( comparators.size() > 0 ){ Collections.sort( items, new Comparator() { public int compare( ItemInfo i1, ItemInfo i2) { for ( int i=0;i comp = comparators.get(i); int res = comp.compare( i1, i2 ); if ( res != 0 ){ if ( reverses.get(i)){ res = -res; } return( res ); } } return( 0 ); } }); } } // select items to return String item_count = args.get( "ItemCount" ); String anchor_offset = args.get( "AnchorOffset" ); String anchor = args.get( "AnchorItem" ); int num_items; if ( item_count == null ){ num_items = items.size(); }else{ // can be negative if X items from end num_items = Integer.parseInt( item_count ); } int anchor_index; // either one before or one after item to be returned depending on count +ve/-ve if ( num_items < 0 ){ anchor_index = items.size(); }else{ anchor_index = -1; } if ( anchor != null ){ for (int i=0;i items.size()){ anchor_index = items.size(); } } int start_index; int end_index; if ( num_items > 0 ){ start_index = anchor_index + 1; end_index = anchor_index + num_items; }else{ start_index = anchor_index + num_items; end_index = anchor_index - 1; } if ( start_index < 0 ){ start_index = 0; } if ( end_index >= items.size()){ end_index = items.size() - 1; } int num_to_return = end_index - start_index + 1; if ( num_to_return < 0 ){ num_to_return = 0; } String machine = getMachineName(); if ( machine == null ){ // default until we find out what it is - can't see any way to get it apart from wait for broadcast machine = "TivoHDDVR"; } String header = "" + NL + "" + NL + " " + NL + " " + machine + "" + NL + " " + NL + " " + start_index + "" + NL + " " + num_to_return + "" + NL + "
    " + NL + " " + escape( container ) + "" + NL + " x-container/tivo-videos" + NL + " x-container/folder" + NL + " " + items.size() + "" + NL + "
    " + NL; reply = header; for ( int i=start_index;i<=end_index;i++ ){ ItemInfo item = items.get(i); if ( item instanceof FileInfo ){ FileInfo file = (FileInfo)item; long file_size = file.getTargetSize(); reply += " " + NL + "
    " + NL + " " + escape( file.getName()) + "" + NL + " video/x-tivo-mpeg" + NL + " video/x-ms-wmv" + NL; if ( file_size > 0 ){ reply += " " + file_size + "" + NL; }else{ long est_size = file.getEstimatedTargetSize(); if ( est_size > 0 ){ reply += " " + est_size + "" + NL; } } reply += " " + file.getDurationMillis() + "" + NL + " " + NL + " 0" + NL + " " + NL + " " + NL + " " + file.getCaptureDate() + "" + NL + "
    " + NL + " " + NL + " " + NL + " video/x-tivo-mpeg" + NL + " No" + NL + " " + file.getLinkURL() + "" + NL + " " + NL + " " + NL + " video/*" + NL + " No" + NL + " urn:tivo:image:save-until-i-delete-recording" + NL + " " + NL + " " + NL + "
    " + NL; }else{ ContainerInfo cont = (ContainerInfo)item; reply += " " + NL + "
    " + NL + " " + cont.getName() + "" + NL + " x-container/tivo-videos" + NL + " x-container/folder" + NL + " " + cont.getChildCount() + "" + NL + "
    " + NL + " " + NL + " " + NL + " " + cont.getLinkURL() + "" + NL + " x-container/tivo-videos" + NL + " " + NL + " " + NL + "
    " + NL; } } String footer = "
    "; reply += footer; } }else if ( command.equals( "QueryFormats")){ String source_format = args.get( "SourceFormat" ); if ( source_format != null && source_format.startsWith( "video" )){ // /TiVoConnect?Command=QueryFormats&SourceFormat=video%2Fx-tivo-mpeg reply = "" + NL + "" + NL + "video/x-tivo-mpeg" + NL + ""; } } if ( reply == null ){ return( false ); } if ( TRACE ){ System.out.println( "->" + reply ); } response.setContentType( "text/xml" ); response.getOutputStream().write( reply.getBytes( "UTF-8" )); return( true ); } protected static String urlencode( String str ) { try{ return( URLEncoder.encode( str, "UTF-8" )); }catch( Throwable e ){ Debug.out( e ); return( str ); } } protected static String escape( String str ) { return( XUXmlWriter.escapeXML( str )); } protected void getDisplayProperties( List dp ) { super.getDisplayProperties( dp ); addDP( dp, "devices.tivo.machine", getMachineName()); } public void generate( IndentWriter writer ) { super.generate( writer ); try{ writer.indent(); writer.println( "tico_machine=" + getMachineName()); }finally{ writer.exdent(); } } protected abstract static class ItemInfo { protected abstract String getName(); protected abstract String getLinkURL(); protected abstract boolean isContainer(); public abstract long getCreationMillis(); } protected static class ContainerInfo extends ItemInfo { private String name; private int child_count; protected ContainerInfo( String _name ) { name = _name; } protected String getName() { return( name ); } protected String getLinkURL() { return( "/TiVoConnect?Command=QueryContainer&Container=" + urlencode( "/Content/" + name )); } protected void addChild() { child_count++; } protected int getChildCount() { return( child_count ); } public long getCreationMillis() { return( 0 ); } protected boolean isContainer() { return( true ); } } protected static class FileInfo extends ItemInfo { private TranscodeFile file; private String stream_url; private long target_size; private long creation_millis; boolean ok; protected FileInfo( TranscodeFile _file, String _host ) { file = _file; try{ URL url = file.getStreamURL( _host ); if ( url == null ){ return; } stream_url = url.toExternalForm(); try{ if ( file.isComplete()){ target_size = file.getTargetFile().getLength(); } }catch( Throwable e ){ } creation_millis = file.getCreationDateMillis(); ok = true; }catch( Throwable e ){ } } protected boolean isOK() { return( ok ); } protected String getName() { return( file.getName()); } protected String getLinkURL() { return( stream_url ); } protected long getTargetSize() { return( target_size ); } protected long getEstimatedTargetSize() { // TODO: we need access to max bitrate info... and then use duration and increase by, say, 5% try{ long duration_secs = getDurationMillis()/1000; if ( duration_secs == 0 ){ long length = file.getSourceFile().getLength(); return( length * 10 ); }else{ long mb_per_sec = 3; // upper limit of 3 MB a sec assumed return( duration_secs * mb_per_sec*1024*1024L ); } }catch( Throwable e ){ } return( 0 ); } protected long getDurationMillis() { return( file.getDurationMillis()); } public long getCreationMillis() { return( creation_millis ); } protected String getCaptureDate() { return( "0x" + Long.toString( creation_millis/1000, 16 )); } protected boolean isContainer() { return( false ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/TranscodePipe.java0000644000175000017500000002374211160046056025471 0ustar adrianadrian/* * Created on Feb 12, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Average; import org.gudy.azureus2.core3.util.Debug; public abstract class TranscodePipe { private final int BUFFER_SIZE = 128*1024; private final int BUFFER_CACHE_SIZE = BUFFER_SIZE*3; protected volatile boolean paused; protected volatile boolean destroyed; protected volatile int bytes_available; protected volatile int max_bytes_per_sec; protected List sockets = new ArrayList(); private ServerSocket server_socket; private AEThread2 refiller; private LinkedList buffer_cache = new LinkedList(); private int buffer_cache_size; private Average connection_speed = Average.getInstance(1000, 10); //average over 10s, update every 1000ms private Average write_speed = Average.getInstance(1000, 10); //average over 10s, update every 1000ms private errorListener error_listener; protected TranscodePipe( errorListener _error_listener ) throws IOException { error_listener = _error_listener; server_socket = new ServerSocket( 0, 50, InetAddress.getByName( "127.0.0.1" )); new AEThread2( "TranscodePipe", true ) { public void run() { while( !destroyed ){ try{ final Socket socket = server_socket.accept(); connection_speed.addValue( 1 ); new AEThread2( "TranscodePipe", true ) { public void run() { handleSocket( socket ); } }.start(); }catch( Throwable e ){ if ( !destroyed ){ destroy(); } break; } } } }.start(); } public long getConnectionRate() { return( connection_speed.getAverage()); } public long getWriteSpeed() { return(write_speed.getAverage()); } protected abstract void handleSocket( Socket socket ); protected void handlePipe( final InputStream is, final OutputStream os ) { new AEThread2( "TranscodePipe:c", true ) { public void run() { final int BUFFER_SIZE = 128*1024; byte[] buffer = new byte[ BUFFER_SIZE ]; while( !destroyed ){ try{ int limit; if ( paused ){ Thread.sleep(250); limit = 1; }else{ if ( max_bytes_per_sec > 0 ){ limit = bytes_available; if ( limit <= 0 ){ Thread.sleep( 25 ); continue; } limit = Math.min( BUFFER_SIZE, limit ); }else{ limit = BUFFER_SIZE; } } int len = is.read( buffer, 0, limit ); if ( len <= 0 ){ break; } if ( max_bytes_per_sec > 0 ){ bytes_available -= len; } os.write( buffer, 0, len ); write_speed.addValue( len ); }catch( Throwable e ){ break; } } try{ os.flush(); }catch( Throwable e ){ } try{ is.close(); }catch( Throwable e ){ } try{ os.close(); }catch( Throwable e ){ } } }.start(); } protected RandomAccessFile reserveRAF() throws IOException { throw( new IOException( "Not implemented" )); } protected void releaseRAF( RandomAccessFile raf ) { } protected void handleRAF( final OutputStream os, final long position, final long length ) { new AEThread2( "TranscodePipe:c", true ) { public void run() { RandomAccessFile raf = null; try{ raf = reserveRAF(); long pos = position; long rem = length; while( !destroyed && rem > 0){ int limit; if ( paused ){ Thread.sleep(250); limit = 1; }else{ if ( max_bytes_per_sec > 0 ){ limit = bytes_available; if ( limit <= 0 ){ Thread.sleep( 25 ); continue; } limit = Math.min( BUFFER_SIZE, limit ); }else{ limit = BUFFER_SIZE; } limit = (int)Math.min( rem, limit ); } int read_length = 0; int buffer_start = 0; byte[] buffer = null; synchronized( TranscodePipe.this ){ int c_num = 0; Iterator it = buffer_cache.iterator(); while( it.hasNext()){ bufferCache b = it.next(); long rel_offset = pos - b.offset; if ( rel_offset >= 0 ){ byte[] data = b.data; long avail = data.length - rel_offset; if ( avail > 0 ){ read_length = (int)Math.min( avail, limit ); buffer = data; buffer_start = (int)rel_offset; //System.out.println( "using cache entry: o_offset=" + pos + ",r_offset=" + rel_offset+",len=" + read_length ); if ( c_num > 0 ){ it.remove(); buffer_cache.addFirst( b ); } break; } } c_num++; } if ( buffer == null ){ buffer = new byte[ limit ]; raf.seek( pos ); read_length = raf.read( buffer ); if ( read_length != limit ){ Debug.out( "eh?"); throw( new IOException( "Inconsistent" )); } bufferCache b = new bufferCache( pos, buffer ); // System.out.println( "adding to cache: o_offset=" + pos + ", size=" + limit ); buffer_cache.addFirst( b ); buffer_cache_size += limit; while( buffer_cache_size > BUFFER_CACHE_SIZE ){ b = buffer_cache.removeLast(); buffer_cache_size -= b.data.length; } } } if ( read_length <= 0 ){ break; } rem -= read_length; pos += read_length; if ( max_bytes_per_sec > 0 ){ bytes_available -= read_length; } os.write( buffer, buffer_start, read_length ); write_speed.addValue( read_length ); } os.flush(); }catch( Throwable e ){ if ( raf != null ){ try{ synchronized( TranscodePipe.this ){ raf.seek( 0 ); raf.read( new byte[1] ); } }catch( Throwable f ){ reportError( e ); } } }finally{ try{ os.close(); }catch( Throwable e ){ } if ( raf != null ){ releaseRAF( raf ); } } } }.start(); } protected void pause() { paused = true; } protected void resume() { paused = false; } public void setMaxBytesPerSecond( int max ) { if ( max == max_bytes_per_sec ){ return; } max_bytes_per_sec = max; synchronized( this ){ if ( refiller == null ){ refiller = new AEThread2( "refiller", true ) { public void run() { int count = 0; while( !destroyed ){ if ( max_bytes_per_sec == 0 ){ synchronized( this ){ if ( max_bytes_per_sec == 0 ){ refiller = null; break; } } } count++; bytes_available += max_bytes_per_sec/10; if ( count%10 == 0 ){ bytes_available += max_bytes_per_sec%10; } try{ Thread.sleep(100); }catch( Throwable e ){ Debug.printStackTrace(e); break; } } } }; refiller.start(); } } } protected int getPort() { return( server_socket.getLocalPort()); } protected boolean destroy() { synchronized( this ){ if ( destroyed ){ return( false ); } destroyed = true; } for (Socket s: sockets ){ try{ s.close(); }catch( Throwable e ){ } } sockets.clear(); try{ server_socket.close(); }catch( Throwable e ){ Debug.printStackTrace(e); } return( true ); } protected void reportError( Throwable error ) { if ( error_listener != null ){ error_listener.error( error ); }else{ Debug.out( error ); } } private class bufferCache { private long offset; private byte[] data; protected bufferCache( long _offset, byte[] _data ) { offset = _offset; data = _data; } } protected interface errorListener { public void error( Throwable e ); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/TranscodeFileImpl.java0000644000175000017500000003343611252045030026267 0ustar adrianadrian/* * Created on Feb 18, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ /** * */ package com.aelitis.azureus.core.devices.impl; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadException; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import com.aelitis.azureus.core.devices.Device; import com.aelitis.azureus.core.devices.TranscodeException; import com.aelitis.azureus.core.devices.TranscodeFile; import com.aelitis.azureus.core.devices.TranscodeJob; import com.aelitis.azureus.core.devices.TranscodeProviderAnalysis; import com.aelitis.azureus.core.devices.TranscodeTargetListener; import com.aelitis.azureus.core.download.DiskManagerFileInfoFile; import com.aelitis.azureus.util.ImportExportUtils; class TranscodeFileImpl implements TranscodeFile { protected static final String KEY_FILE = "file"; private static final String KEY_PROFILE_NAME = "pn"; private static final String KEY_SOURCE_FILE_HASH = "sf_hash"; private static final String KEY_SOURCE_FILE_INDEX = "sf_index"; private static final String KEY_SOURCE_FILE_LINK = "sf_link"; private static final String KEY_NO_XCODE = "no_xcode"; private static final String KEY_FOR_JOB = "fj"; private static final String KEY_DURATION = "at_dur"; private static final String KEY_VIDEO_WIDTH = "at_vw"; private static final String KEY_VIDEO_HEIGHT = "at_vh"; private static final String KEY_DATE = "at_dt"; private static final String KEY_CATEGORIES = PT_CATEGORY; private static final String KEY_COPY_TO_OVERRIDE = "ct_over"; private DeviceImpl device; private String key; private Map> files_map; // don't store any local state here, store it in the map as this is just a wrapper // for the underlying map and there can be multiple such wrappers concurrent protected TranscodeFileImpl( DeviceImpl _device, String _key, String _profile_name, Map> _files_map, File _file, boolean _for_job ) { device = _device; key = _key; files_map = _files_map; getMap( true ); setString( KEY_FILE, _file.getAbsolutePath()); setString( KEY_PROFILE_NAME, _profile_name ); setLong( KEY_DATE, SystemTime.getCurrentTime()); setBoolean( KEY_FOR_JOB, _for_job ); } protected TranscodeFileImpl( DeviceImpl _device, String _key, Map> _map ) throws IOException { device = _device; key = _key; files_map = _map; Map map = getMap(); if ( map == null || !map.containsKey( KEY_FILE )){ throw( new IOException( "File has been deleted" )); } } protected String getKey() { return( key ); } public String getName() { TranscodeJob job = getJob(); String text; if ( job == null){ try{ DiskManagerFileInfo sourceFile = getSourceFile(); try { Download download = sourceFile.getDownload(); if ( download == null ){ text = sourceFile.getFile().getName(); }else{ text = download.getName(); DiskManagerFileInfo[] fileInfo = download.getDiskManagerFileInfo(); if (fileInfo.length > 1) { text += ": " + sourceFile.getFile().getName(); } } }catch (DownloadException e ){ text = sourceFile.getFile().getName(); } }catch( Throwable e ){ text = ""; } }else{ text = job.getName(); } return( text ); } public Device getDevice() { return( device ); } public TranscodeJobImpl getJob() { if ( isComplete()){ return( null ); } return( device.getManager().getTranscodeManager().getQueue().getJob( this )); } public File getCacheFile() throws TranscodeException { String file_str = getString( KEY_FILE ); if ( file_str == null ){ throw( new TranscodeException( "File has been deleted" )); } return(new File( file_str )); } protected void setCacheFile( File file ) { setString( KEY_FILE, file.getAbsolutePath()); } protected void checkDeleted() throws TranscodeException { if ( isDeleted()){ throw( new TranscodeException( "File has been deleted" )); } } public DiskManagerFileInfo getSourceFile() throws TranscodeException { checkDeleted(); // options are either a download file or a link to an existing non-torrent based file String hash = getString( KEY_SOURCE_FILE_HASH ); if ( hash != null ){ try{ Download download = PluginInitializer.getDefaultInterface().getDownloadManager().getDownload( Base32.decode(hash)); if ( download != null ){ int index = (int)getLong( KEY_SOURCE_FILE_INDEX ); return( download.getDiskManagerFileInfo()[index] ); } }catch( Throwable e ){ } } String link = getString( KEY_SOURCE_FILE_LINK ); if ( link != null ){ File link_file = new File( link ); // if we're not transcoding then always return the source even if doesn't exist if ( link_file.exists() || getBoolean( KEY_NO_XCODE )){ return( new DiskManagerFileInfoFile( link_file )); } } // Debug.out( "Source file doesn't exist (hash=" + hash + ",link=" + link +"), returning cache file" ); return( new DiskManagerFileInfoFile( getCacheFile())); } protected void setSourceFile( DiskManagerFileInfo file ) { try{ Download download = file.getDownload(); if ( download != null && download.getTorrent() != null ){ setString( KEY_SOURCE_FILE_HASH, Base32.encode( download.getTorrent().getHash() )); setLong( KEY_SOURCE_FILE_INDEX, file.getIndex()); } }catch( Throwable e ){ } setString( KEY_SOURCE_FILE_LINK, file.getFile().getAbsolutePath()); } public DiskManagerFileInfo getTargetFile() throws TranscodeException { // options are either the cached file, if it exists, or failing that the // source file if transcoding not required File cache_file = getCacheFile(); if ( cache_file.exists() && cache_file.length() > 0 ){ return( new DiskManagerFileInfoFile( cache_file )); } if ( getBoolean( KEY_NO_XCODE )){ return( getSourceFile()); } // Debug.out( "Target file for " + cache_file + " doesn't exist" ); return( new DiskManagerFileInfoFile( cache_file )); } protected void setTranscodeRequired( boolean required ) throws TranscodeException { setBoolean( KEY_NO_XCODE, !required ); if ( !required ){ // reset the file name as previous device.revertFileName( this ); } } public boolean getTranscodeRequired() { return( !getBoolean( KEY_NO_XCODE )); } protected void setComplete( boolean b ) { setBoolean( PT_COMPLETE, b ); } public boolean isComplete() { return( getBoolean( PT_COMPLETE )); } public boolean isTemplate() { return( !getBoolean( KEY_FOR_JOB )); } protected void setCopiedToDevice( boolean b ) { setBoolean( PT_COPIED, b ); setLong( PT_COPY_FAILED, 0 ); } protected void setCopyToDeviceFailed() { setLong( PT_COPY_FAILED, getLong( PT_COPY_FAILED ) + 1 ); } public long getCopyToDeviceFails() { return( getLong( PT_COPY_FAILED )); } public boolean isCopiedToDevice() { return( getBoolean( PT_COPIED )); } public void retryCopyToDevice() { if ( isCopiedToDevice()){ setCopiedToDevice( false ); }else{ setLong( PT_COPY_FAILED, 0 ); } } protected void setProfileName( String s ) { setString( KEY_PROFILE_NAME, s ); } public String getProfileName() { String s = getString( KEY_PROFILE_NAME ); if ( s == null ){ s = "Unknown"; } return( s ); } protected void setCopyToFolderOverride( String s ) { setString( KEY_COPY_TO_OVERRIDE, s ); } public String getCopyToFolderOverride() { return( getString( KEY_COPY_TO_OVERRIDE )); } protected void update( TranscodeProviderAnalysis analysis ) { long duration = analysis.getLongProperty( TranscodeProviderAnalysis.PT_DURATION_MILLIS ); long video_width = analysis.getLongProperty( TranscodeProviderAnalysis.PT_VIDEO_WIDTH ); long video_height = analysis.getLongProperty( TranscodeProviderAnalysis.PT_VIDEO_HEIGHT ); if ( duration > 0 ){ setLong( KEY_DURATION, duration ); } if ( video_width > 0 && video_height > 0 ){ setLong( KEY_VIDEO_WIDTH, video_width ); setLong( KEY_VIDEO_HEIGHT, video_height ); } } protected void setResolution( int video_width, int video_height ) { if ( video_width > 0 && video_height > 0 ){ setLong( KEY_VIDEO_WIDTH, video_width ); setLong( KEY_VIDEO_HEIGHT, video_height ); } } public long getDurationMillis() { return( getLong( KEY_DURATION )); } public long getVideoWidth() { return( getLong( KEY_VIDEO_WIDTH )); } public long getVideoHeight() { return( getLong( KEY_VIDEO_HEIGHT )); } public String[] getCategories() { String cats = getString( KEY_CATEGORIES ); if ( cats == null || cats.length() == 0 ){ return( new String[0] ); } return( cats.split( "," )); } public void setCategories( String[] cats ) { String[] existing = getCategories(); if ( existing.length == 0 && existing.length == cats.length ){ return; } String str = ""; for ( String cat: cats ){ cat = cat.replaceAll( ",", "" ).trim(); if ( cat.length() > 0 ){ str += (str.length()==0?"":",") + cat; } } setString( KEY_CATEGORIES, str ); } public long getCreationDateMillis() { return( getLong( KEY_DATE )); } public File getCacheFileIfExists() { try{ return( getCacheFile()); }catch( Throwable e ){ return( null ); } } public URL getStreamURL() { return( device.getStreamURL( this, null )); } public URL getStreamURL( String host ) { return( device.getStreamURL( this, host )); } public String getMimeType() { return( device.getMimeType( this )); } public void delete( boolean delete_contents ) throws TranscodeException { device.deleteFile( this, delete_contents, true ); } protected void deleteCacheFile() throws TranscodeException { device.deleteFile( this, true, false ); } public boolean isDeleted() { return( getMap() == null ); } private Map getMap() { return( getMap( false )); } private Map getMap( boolean create ) { synchronized( files_map ){ Map map = files_map.get( key ); if ( map == null && create ){ map = new HashMap(); files_map.put( key, map ); } return( map ); } } protected boolean getBoolean( String key ) { return( getLong(key)==1); } protected void setBoolean( String key, boolean b ) { setLong(key,b?1:0); } protected long getLong( String key ) { try{ Map map = getMap(); return(ImportExportUtils.importLong( map, key, 0 )); }catch( Throwable e ){ Debug.out( e ); return( 0 ); } } protected void setLong( String key, long value ) { if ( getLong( key ) == value ){ return; } synchronized( files_map ){ try{ Map map = getMap(); ImportExportUtils.exportLong( map, key, value); }catch( Throwable e ){ Debug.out( e ); } } device.fileDirty( this, TranscodeTargetListener.CT_PROPERTY, key ); } protected String getString( String key ) { try{ Map map = getMap(); return(ImportExportUtils.importString( map, key )); }catch( Throwable e ){ Debug.out( e ); return( "" ); } } protected void setString( String key, String value ) { String existing = getString( key ); if ( existing == null && value == null ){ return; }else if ( existing == null || value == null ){ }else if ( existing.equals( value )){ return; } synchronized( files_map ){ Map map = getMap(); try{ ImportExportUtils.exportString( map, key, value ); }catch( Throwable e ){ Debug.out( e ); } } device.fileDirty( this, TranscodeTargetListener.CT_PROPERTY, key ); } public void setTransientProperty( Object key2, Object value ) { device.setTransientProperty( key, key2, value ); } public Object getTransientProperty( Object key2 ) { return( device.getTransientProperty( key, key2 )); } public boolean equals( Object other ) { if ( other instanceof TranscodeFileImpl ){ return( key.equals(((TranscodeFileImpl)other).key)); } return( false ); } public int hashCode() { return( key.hashCode()); } protected String getString() { Map map = getMap(); if ( map == null ){ return( key + ": deleted" ); }else{ return( key + ": " + map ); } } }azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceImpl.java0000644000175000017500000011523311252045030024740 0ustar adrianadrian/* * Created on Jan 28, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.File; import java.io.IOException; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.net.URL; import java.text.SimpleDateFormat; import java.util.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.BEncoder; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DelayedEvent; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.LightHashMap; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import com.aelitis.azureus.core.devices.Device; import com.aelitis.azureus.core.devices.DeviceListener; import com.aelitis.azureus.core.devices.DeviceMediaRenderer; import com.aelitis.azureus.core.devices.TranscodeException; import com.aelitis.azureus.core.devices.TranscodeFile; import com.aelitis.azureus.core.devices.TranscodeProfile; import com.aelitis.azureus.core.devices.TranscodeProvider; import com.aelitis.azureus.core.devices.TranscodeTarget; import com.aelitis.azureus.core.devices.TranscodeTargetListener; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.util.ImportExportUtils; public abstract class DeviceImpl implements Device { private static final String MY_PACKAGE = "com.aelitis.azureus.core.devices.impl"; protected static DeviceImpl importFromBEncodedMapStatic( DeviceManagerImpl manager, Map map ) throws IOException { String impl = ImportExportUtils.importString( map, "_impl" ); if ( impl.startsWith( "." )){ impl = MY_PACKAGE + impl; } try{ Class cla = (Class) Class.forName( impl ); Constructor cons = cla.getDeclaredConstructor( DeviceManagerImpl.class, Map.class ); cons.setAccessible( true ); return( cons.newInstance( manager, map )); }catch( Throwable e ){ Debug.out( "Can't construct device for " + impl, e ); throw( new IOException( "Construction failed: " + Debug.getNestedExceptionMessage(e))); } } private static final String PP_REND_WORK_DIR = "tt_work_dir"; private static final String PP_REND_DEF_TRANS_PROF = "tt_def_trans_prof"; private static final String PP_REND_TRANS_REQ = "tt_req"; private static final String PP_REND_TRANS_CACHE = "tt_always_cache"; private static final String PP_REND_RSS_PUB = "tt_rss_pub"; protected static final String PP_REND_SHOW_CAT = "tt_show_cat"; protected static final String PP_IP_ADDRESS = "rend_ip"; protected static final String TP_IP_ADDRESS = "DeviceUPnPImpl:ip"; // transient protected static final String PP_FILTER_FILES = "rend_filter"; protected static final String PP_COPY_OUTSTANDING = "copy_outstanding"; protected static final String PP_AUTO_START = "auto_start"; protected static final String PP_COPY_TO_FOLDER = "copy_to_folder"; protected static final String PP_AUTO_COPY = "auto_copy"; protected static final String PP_LIVENESS_DETECTABLE = "live_det"; protected static final String PP_TIVO_MACHINE = "tivo_machine"; protected static final String PP_OD_ENABLED = "od_enabled"; protected static final String PP_OD_SHOWN_FTUX = "od_shown_ftux"; protected static final String PP_OD_MANUFACTURER = "od_manufacturer"; protected static final String PP_OD_STATE_CACHE = "od_state_cache"; protected static final String PP_OD_XFER_CACHE = "od_xfer_cache"; protected static final String PP_OD_UPNP_DISC_CACHE = "od_upnp_cache"; protected static final boolean PR_AUTO_START_DEFAULT = true; protected static final boolean PP_AUTO_COPY_DEFAULT = false; private static final String GENERIC = "generic"; private DeviceManagerImpl manager; private int type; private String uid; private String secondary_uid; private String classification; private String name; private boolean manual; private boolean hidden; private long last_seen; private int busy_count; private boolean online; private boolean transcoding; private Map persistent_properties = new LightHashMap(1); private Map transient_properties = new LightHashMap(1); private long device_files_last_mod; private boolean device_files_dirty; private Map> device_files; private WeakReference>> device_files_ref; private CopyOnWriteList listeners = new CopyOnWriteList(); private Map errors = new HashMap(); private Map infos = new HashMap(); private CopyOnWriteList device_listeners; protected DeviceImpl( DeviceManagerImpl _manager, int _type, String _uid, String _classification, boolean _manual ) { this( _manager, _type, _uid, _classification, _manual, _classification ); } protected DeviceImpl( DeviceManagerImpl _manager, int _type, String _uid, String _classification, boolean _manual, String _name ) { manager = _manager; type = _type; uid = _uid; classification = _classification; name = _name; manual = _manual; } protected DeviceImpl( DeviceManagerImpl _manager, Map map ) throws IOException { manager = _manager; type = (int)ImportExportUtils.importLong( map, "_type" ); uid = ImportExportUtils.importString( map, "_uid" ); classification = ImportExportUtils.importString( map, "_name" ); name = ImportExportUtils.importString( map, "_lname" ); if ( name == null ){ name = classification; } secondary_uid = ImportExportUtils.importString( map, "_suid" ); last_seen = ImportExportUtils.importLong( map, "_ls" ); hidden = ImportExportUtils.importBoolean( map, "_hide" ); manual = ImportExportUtils.importBoolean( map, "_man" ); if ( map.containsKey( "_pprops" )){ persistent_properties = (Map)map.get( "_pprops" ); } } protected void exportToBEncodedMap( Map map ) throws IOException { String cla = this.getClass().getName(); if ( cla.startsWith( MY_PACKAGE )){ cla = cla.substring( MY_PACKAGE.length()); } ImportExportUtils.exportString( map, "_impl", cla ); ImportExportUtils.exportLong( map, "_type", new Long( type )); ImportExportUtils.exportString( map, "_uid", uid ); ImportExportUtils.exportString( map, "_name", classification ); ImportExportUtils.exportString( map, "_lname", name ); if ( secondary_uid != null ){ ImportExportUtils.exportString( map, "_suid", secondary_uid ); } ImportExportUtils.exportLong( map, "_ls", new Long( last_seen )); ImportExportUtils.exportBoolean( map, "_hide", hidden ); ImportExportUtils.exportBoolean( map, "_man", manual ); map.put( "_pprops", persistent_properties ); } protected boolean updateFrom( DeviceImpl other, boolean is_alive ) { if ( type != other.type ){ Debug.out( "Inconsistent update operation (type)" ); return( false ); } String o_uid = other.uid; String o_suid = other.secondary_uid; if ( !uid.equals( o_uid )){ boolean borked = false; if ( secondary_uid == null && o_suid == null ){ borked = true; }else if ( secondary_uid == null && uid.equals( o_suid ) || o_suid == null && o_uid.equals( secondary_uid ) || o_suid.equals( secondary_uid )){ }else{ borked = true; } if ( borked ){ Debug.out( "Inconsistent update operation (uids)" ); return( false ); } } if ( !classification.equals( other.classification )){ classification = other.classification; setDirty(); } /* don't overwite the name as user may have altered it! if ( !name.equals( other.name )){ name = other.name; setDirty(); } */ if ( manual != other.manual ){ manual = other.manual; setDirty(); } if ( is_alive ){ alive(); } return( true ); } protected void initialise() { updateStatus( 0 ); } protected void destroy() { } public int getType() { return( type ); } public String getID() { return( uid ); } protected void setSecondaryID( String str ) { secondary_uid = str; } protected String getSecondaryID() { return( secondary_uid ); } public Device getDevice() { return( this ); } public String getName() { return( name ); } public void setName( String _name ) { if ( !name.equals( _name )){ name = _name; setDirty(); } } public String getClassification() { return( classification ); } public String getShortDescription() { if ( getRendererSpecies() == DeviceMediaRenderer.RS_ITUNES ){ return( "iPhone, iPod, Apple TV" ); } return( null ); } public int getRendererSpecies() { // note, overridden in itunes if ( classification.equalsIgnoreCase( "PS3" )){ return( DeviceMediaRenderer.RS_PS3 ); }else if ( classification.equalsIgnoreCase( "XBox 360" )){ return( DeviceMediaRenderer.RS_XBOX ); }else if ( classification.equalsIgnoreCase( "Wii" )){ return( DeviceMediaRenderer.RS_WII ); }else if ( classification.equalsIgnoreCase( "Browser" )){ return( DeviceMediaRenderer.RS_BROWSER ); }else{ return( DeviceMediaRenderer.RS_OTHER ); } } protected String getDeviceClassification() { // note, overridden in itunes // bit of a mess here. First release used name as classification and mapped to // species + device-classification here. // second release moved to separate name and classification and used the correct // device-classification as the classification // so we deal with both for the moment... // 'generic' means one we don't explicitly support, which are rendereres discovered // by UPnP switch( getRendererSpecies()){ case DeviceMediaRenderer.RS_PS3:{ return( "sony.PS3" ); } case DeviceMediaRenderer.RS_XBOX:{ return( "microsoft.XBox" ); } case DeviceMediaRenderer.RS_WII:{ return( "nintendo.Wii" ); } case DeviceMediaRenderer.RS_BROWSER:{ return( "browser.generic" ); } case DeviceMediaRenderer.RS_OTHER:{ if ( isManual()){ return( classification ); } if ( classification.equals( "sony.PSP" ) || classification.startsWith( "tivo." )){ return( classification ); } return( GENERIC ); } default:{ Debug.out( "Unknown classification" ); return( GENERIC ); } } } public boolean isGeneric() { return( getDeviceClassification() == GENERIC ); } public boolean isManual() { return( manual ); } public boolean isHidden() { return( hidden ); } public void setHidden( boolean h ) { if ( h != hidden ){ hidden = h; setDirty(); } } protected void alive() { last_seen = SystemTime.getCurrentTime(); if ( !online ){ online = true; setDirty( false ); } } public boolean isLivenessDetectable() { return( !manual ); } public boolean isAlive() { return( online ); } protected void dead() { if ( online ){ online = false; setDirty( false ); } } protected void setDirty() { setDirty( true ); } protected void setDirty( boolean save_changes ) { manager.configDirty( this, save_changes ); } protected void updateStatus( int tick_count ) { } public void requestAttention() { manager.requestAttention( this ); } public TranscodeFileImpl[] getFiles() { try{ synchronized( this ){ if ( device_files == null ){ loadDeviceFile(); } List result = new ArrayList(); Iterator>> it = device_files.entrySet().iterator(); while( it.hasNext()){ Map.Entry> entry = it.next(); try{ TranscodeFileImpl tf = new TranscodeFileImpl( this, entry.getKey(), device_files ); result.add( tf ); }catch( Throwable e ){ it.remove(); log( "Failed to deserialise transcode file", e ); } } return( result.toArray( new TranscodeFileImpl[ result.size() ])); } }catch( Throwable e ){ Debug.out( e ); return( new TranscodeFileImpl[0] ); } } public TranscodeFileImpl allocateFile( TranscodeProfile profile, boolean no_xcode, DiskManagerFileInfo file, boolean for_job ) throws TranscodeException { TranscodeFileImpl result = null; try{ synchronized( this ){ if ( device_files == null ){ loadDeviceFile(); } String key = ByteFormatter.encodeString( file.getDownloadHash() ) + ":" + file.getIndex() + ":" + profile.getUID(); if ( device_files.containsKey( key )){ try{ result = new TranscodeFileImpl( this, key, device_files ); }catch( Throwable e ){ device_files.remove( key ); log( "Failed to deserialise transcode file", e ); } } if ( result == null ){ String ext = profile.getFileExtension(); String target_file = file.getFile().getName(); if ( ext != null && !no_xcode ){ int pos = target_file.lastIndexOf( '.' ); if ( pos != -1 ){ target_file = target_file.substring( 0, pos ); } target_file += ext; } target_file = allocateUniqueFileName( target_file ); File output_file = getWorkingDirectory( true ); output_file = new File( output_file.getAbsoluteFile(), target_file ); result = new TranscodeFileImpl( this, key, profile.getName(), device_files, output_file, for_job ); result.setSourceFile( file ); saveDeviceFile(); }else{ result.setSourceFile( file ); result.setProfileName( profile.getName()); } } }catch( Throwable e ){ throw( new TranscodeException( "File allocation failed", e )); } for ( TranscodeTargetListener l: listeners ){ try{ l.fileAdded( result ); }catch( Throwable e ){ Debug.out( e ); } } return( result ); } protected String allocateUniqueFileName( String str ) { Set name_set = new HashSet(); for (Map entry: device_files.values()){ try{ name_set.add( new File( ImportExportUtils.importString( entry, TranscodeFileImpl.KEY_FILE )).getName()); }catch( Throwable e ){ Debug.out( e ); } } for (int i=0;i<1024;i++){ String test_name = i==0?str:( i + "_" + str); if ( !name_set.contains( test_name )){ str = test_name; break; } } return( str ); } protected void revertFileName( TranscodeFileImpl tf ) throws TranscodeException { File cache_file = tf.getCacheFile(); if ( cache_file.exists()){ Debug.out( "Cache file already allocated, can't rename" ); return; } File source_file = tf.getSourceFile().getFile(); String original_name = source_file.getName(); int pos = original_name.indexOf('.'); if ( pos == -1 ){ return; } String cf_name = cache_file.getName(); if ( cf_name.endsWith( original_name.substring(pos))){ return; } try{ synchronized( this ){ if ( device_files == null ){ loadDeviceFile(); } String reverted_name = allocateUniqueFileName( original_name ); tf.setCacheFile( new File( cache_file.getParentFile(), reverted_name )); } }catch( Throwable e ){ throw( new TranscodeException( "File name revertion failed", e )); } } public TranscodeFileImpl lookupFile( TranscodeProfile profile, DiskManagerFileInfo file ) { try{ synchronized( this ){ if ( device_files == null ){ loadDeviceFile(); } String key = ByteFormatter.encodeString( file.getDownloadHash() ) + ":" + file.getIndex() + ":" + profile.getUID(); if ( device_files.containsKey( key )){ try{ return( new TranscodeFileImpl( this, key, device_files )); }catch( Throwable e ){ device_files.remove( key ); log( "Failed to deserialise transcode file", e ); } } } }catch( Throwable e ){ } return( null ); } protected TranscodeFileImpl getTranscodeFile( String key ) { try{ synchronized( this ){ if ( device_files == null ){ loadDeviceFile(); } if ( device_files.containsKey( key )){ try{ return( new TranscodeFileImpl( this, key, device_files )); } catch( Throwable e ){ device_files.remove( key ); log( "Failed to deserialise transcode file", e ); } } } }catch( Throwable e ){ } return( null ); } public File getWorkingDirectory() { return( getWorkingDirectory( false )); } public File getWorkingDirectory( boolean persist ) { String result = getPersistentStringProperty( PP_REND_WORK_DIR ); if ( result.length() == 0 ){ File f = manager.getDefaultWorkingDirectory( persist ); if ( persist ){ f.mkdirs(); } String name = FileUtil.convertOSSpecificChars( getName(), true ); for (int i=0;i<1024;i++){ String test_name = name + (i==0?"":("_"+i)); File test_file = new File( f, test_name ); if ( !test_file.exists()){ f = test_file; break; } } result = f.getAbsolutePath(); if ( persist ){ setPersistentStringProperty( PP_REND_WORK_DIR, result ); } } File f_result = new File( result ); if ( !f_result.exists()){ if ( persist ){ f_result.mkdirs(); } } return( f_result ); } public void setWorkingDirectory( File directory ) { setPersistentStringProperty( PP_REND_WORK_DIR, directory.getAbsolutePath()); } protected void resetWorkingDirectory() { setPersistentStringProperty( PP_REND_WORK_DIR, "" ); } public TranscodeProfile[] getTranscodeProfiles() { List profiles = new ArrayList(); DeviceManagerImpl dm = getManager(); TranscodeManagerImpl tm = dm.getTranscodeManager(); TranscodeProvider[] providers = tm.getProviders(); String classification = getDeviceClassification(); for ( TranscodeProvider provider: providers ){ TranscodeProfile[] ps = provider.getProfiles(); for ( TranscodeProfile p : ps ){ String c = p.getDeviceClassification(); if ( c == null ){ log( "Device classification missing for " + p.getName()); }else{ if ( c.toLowerCase().startsWith( classification.toLowerCase())){ profiles.add( p ); } } } } return( profiles.toArray( new TranscodeProfile[profiles.size()] )); } public TranscodeProfile getDefaultTranscodeProfile() { String uid = getPersistentStringProperty( PP_REND_DEF_TRANS_PROF ); DeviceManagerImpl dm = getManager(); TranscodeManagerImpl tm = dm.getTranscodeManager(); TranscodeProfile profile = tm.getProfileFromUID( uid ); if ( profile != null ){ return( profile ); } return( null ); } public void setDefaultTranscodeProfile( TranscodeProfile profile ) { if ( profile == null ){ removePersistentProperty( PP_REND_DEF_TRANS_PROF ); }else{ setPersistentStringProperty( PP_REND_DEF_TRANS_PROF, profile.getUID()); } } protected void setTranscoding( boolean _transcoding ) { transcoding = _transcoding; manager.deviceChanged( this, false ); } public boolean isTranscoding() { return( transcoding ); } public int getTranscodeRequirement() { return( getPersistentIntProperty( PP_REND_TRANS_REQ, TranscodeTarget.TRANSCODE_WHEN_REQUIRED )); } public void setTranscodeRequirement( int req ) { setPersistentIntProperty( PP_REND_TRANS_REQ, req ); } public boolean isAudioCompatible( TranscodeFile file ) { return( false ); } public boolean getAlwaysCacheFiles() { return( getPersistentBooleanProperty( PP_REND_TRANS_CACHE, false )); } public void setAlwaysCacheFiles( boolean always_cache ) { setPersistentBooleanProperty( PP_REND_TRANS_CACHE, always_cache ); } public boolean isRSSPublishEnabled() { return( getPersistentBooleanProperty( PP_REND_RSS_PUB, true )); } public void setRSSPublishEnabled( boolean enabled ) { setPersistentBooleanProperty( PP_REND_RSS_PUB, enabled ); } public String[][] getDisplayProperties() { List dp = new ArrayList(); getDisplayProperties( dp ); String[][] res = new String[2][dp.size()]; int pos = 0; for ( String[] entry: dp ){ res[0][pos] = entry[0]; res[1][pos] = entry[1]; pos++; } return( res ); } protected void getDisplayProperties( List dp ) { if ( !name.equals( classification )){ addDP( dp, "TableColumn.header.name", name ); } addDP( dp, "TableColumn.header.class", classification.toLowerCase()); addDP( dp, "!UID!", getID()); if ( !manual ){ addDP( dp, "azbuddy.ui.table.online", online ); addDP( dp, "device.lastseen", last_seen==0?"":new SimpleDateFormat().format(new Date( last_seen ))); } } protected void getTTDisplayProperties( List dp ) { addDP( dp, "devices.xcode.working_dir", getWorkingDirectory( false ).getAbsolutePath()); addDP( dp, "devices.xcode.prof_def", getDefaultTranscodeProfile()); addDP( dp, "devices.xcode.profs", getTranscodeProfiles()); int tran_req = getTranscodeRequirement(); String tran_req_str; if ( tran_req == TranscodeTarget.TRANSCODE_ALWAYS ){ tran_req_str = "device.xcode.always"; }else if ( tran_req == TranscodeTarget.TRANSCODE_NEVER ){ tran_req_str = "device.xcode.never"; }else{ tran_req_str = "device.xcode.whenreq"; } addDP( dp, "device.xcode", MessageText.getString( tran_req_str )); } protected void addDP( List dp, String name, String value ) { dp.add( new String[]{ name, value }); } protected void addDP( List dp, String name, File value ) { dp.add( new String[]{ name, value==null?"":value.getAbsolutePath() }); } protected void addDP( List dp, String name, String[] values ) { String value = ""; for ( String v: values ){ value += (value.length()==0?"":",") + v; } dp.add( new String[]{ name, value }); } protected void addDP( List dp, String name, boolean value ) { dp.add( new String[]{ name, MessageText.getString( value?"GeneralView.yes":"GeneralView.no" ) }); } protected void addDP( List dp, String name, TranscodeProfile value ) { addDP( dp, name, value==null?"":value.getName()); } protected void addDP( List dp, String name, TranscodeProfile[] values ) { String[] names = new String[values.length]; for (int i=0;i 0 ); } } protected void setBusy( boolean busy ) { boolean changed = false; synchronized( this ){ if ( busy ){ changed = busy_count++ == 0; }else{ changed = busy_count-- == 1; } } if ( changed ){ manager.deviceChanged( this, false ); } } public void remove() { manager.removeDevice( this ); } public String getPersistentStringProperty( String prop ) { return( getPersistentStringProperty( prop, "" )); } public String getPersistentStringProperty( String prop, String def ) { synchronized( persistent_properties ){ try{ byte[] value = (byte[])persistent_properties.get( prop ); if ( value == null ){ return( def ); } return( new String( value, "UTF-8" )); }catch( Throwable e ){ Debug.printStackTrace(e); return( def ); } } } public void setPersistentStringProperty( String prop, String value ) { boolean dirty = false; synchronized( persistent_properties ){ String existing = getPersistentStringProperty( prop ); if ( !existing.equals( value )){ try{ if ( value == null ){ persistent_properties.remove( prop ); }else{ persistent_properties.put( prop, value.getBytes( "UTF-8" )); } dirty = true; }catch( Throwable e ){ Debug.printStackTrace(e); } } } if ( dirty ){ setDirty(); } } public Map getPersistentMapProperty( String prop, Map def ) { synchronized( persistent_properties ){ try{ Map value = (Map)persistent_properties.get( prop ); if ( value == null ){ return( def ); } return( value ); }catch( Throwable e ){ Debug.printStackTrace(e); return( def ); } } } public void setPersistentMapProperty( String prop, Map value ) { boolean dirty = false; synchronized( persistent_properties ){ Map existing = getPersistentMapProperty( prop, null ); if ( !BEncoder.mapsAreIdentical( value, existing )){ try{ if ( value == null ){ persistent_properties.remove( prop ); }else{ persistent_properties.put( prop, value ); } dirty = true; }catch( Throwable e ){ Debug.printStackTrace(e); } } } if ( dirty ){ setDirty(); } } public void removePersistentProperty( String prop ) { boolean dirty = false; synchronized( persistent_properties ){ String existing = getPersistentStringProperty( prop ); if ( existing != null ){ try{ persistent_properties.remove( prop ); dirty = true; }catch( Throwable e ){ Debug.printStackTrace(e); } } } if ( dirty ){ setDirty(); } } public String getError() { synchronized( errors ){ if ( errors.size() == 0 ){ return( null ); } String res = ""; for ( String s: errors.values()){ res += (res.length()==0?"":"; ") + s; } return( res ); } } protected void setError( Object key, String error ) { boolean changed = false; if ( error == null || error.length() == 0 ){ synchronized( errors ){ changed = errors.remove( key ) != null; } }else{ String existing; synchronized( errors ){ existing = errors.put( key, error ); } changed = existing == null || !existing.equals( error ); } if ( changed ){ manager.deviceChanged( this, false ); } } public String getInfo() { synchronized( infos ){ if ( infos.size() == 0 ){ return( null ); } String res = ""; for ( String s: infos.values()){ res += (res.length()==0?"":"; ") + s; } return( res ); } } protected void setInfo( Object key, String info ) { boolean changed = false; if ( info == null || info.length() == 0 ){ synchronized( infos ){ changed = infos.remove( key ) != null; } }else{ String existing; synchronized( infos ){ existing = infos.put( key, info ); } changed = existing == null || !existing.equals( info ); } if ( changed ){ manager.deviceChanged( this, false ); } } public boolean getPersistentBooleanProperty( String prop, boolean def ) { return( getPersistentStringProperty( prop, def?"true":"false" ).equals( "true" )); } public void setPersistentBooleanProperty( String prop, boolean value ) { setPersistentStringProperty(prop, value?"true":"false" ); } public int getPersistentIntProperty( String prop, int def ) { return( Integer.parseInt( getPersistentStringProperty( prop, String.valueOf(def) ))); } public void setPersistentIntProperty( String prop, int value ) { setPersistentStringProperty(prop, String.valueOf( value )); } public String[] getPersistentStringListProperty( String prop ) { synchronized( persistent_properties ){ try{ List values = (List)persistent_properties.get( prop ); if ( values == null ){ return( new String[0] ); } String[] res = new String[values.size()]; int pos = 0; for (byte[] value: values ){ res[pos++] = new String( value, "UTF-8" ); } return( res ); }catch( Throwable e ){ Debug.printStackTrace(e); return( new String[0] ); } } } public void setPersistentStringListProperty( String prop, String[] values ) { boolean dirty = false; synchronized( persistent_properties ){ try{ List values_list = new ArrayList(); for (String value: values ){ values_list.add( value.getBytes( "UTF-8" )); } persistent_properties.put( prop, values_list ); dirty = true; }catch( Throwable e ){ Debug.printStackTrace(e); } } if ( dirty ){ setDirty(); } } public void setTransientProperty( Object key, Object value ) { synchronized( transient_properties ){ if ( value == null ){ transient_properties.remove( key ); }else{ transient_properties.put( key, value ); } } } public Object getTransientProperty( Object key ) { synchronized( transient_properties ){ return( transient_properties.get( key )); } } public void setTransientProperty( Object key1, Object key2, Object value ) { synchronized( transient_properties ){ Map l1 = (Map)transient_properties.get( key1 ); if ( l1 == null ){ if ( value == null ){ return; } l1 = new HashMap(); transient_properties.put( key1, l1 ); } if ( value == null ){ l1.remove( key2 ); if ( l1.size() == 0 ){ transient_properties.remove( key1 ); } }else{ l1.put( key2, value ); } } } public Object getTransientProperty( Object key1, Object key2 ) { synchronized( transient_properties ){ Map l1 = (Map)transient_properties.get( key1 ); if ( l1 == null ){ return( null ); } return( l1.get( key2 )); } } protected void close() { synchronized( this ){ if ( device_files_dirty ){ saveDeviceFile(); } } } protected void loadDeviceFile() throws IOException { device_files_last_mod = SystemTime.getMonotonousTime(); if ( device_files_ref != null ){ device_files = device_files_ref.get(); } if ( device_files == null ){ Map map = FileUtil.readResilientFile( getDeviceFile()); device_files = (Map>)map.get( "files" ); if ( device_files == null ){ device_files = new HashMap>(); } device_files_ref = new WeakReference>>( device_files ); log( "Loaded device file for " + getName() + ": files=" + device_files.size()); } final int GC_TIME = 15000; new DelayedEvent( "Device:gc", GC_TIME, new AERunnable() { public void runSupport() { synchronized( DeviceImpl.this ){ if ( SystemTime.getMonotonousTime() - device_files_last_mod >= GC_TIME ){ if ( device_files_dirty ){ saveDeviceFile(); } device_files = null; }else{ new DelayedEvent( "Device:gc2", GC_TIME, this ); } } } }); } protected URL getStreamURL( TranscodeFileImpl file, String host ) { return( manager.getStreamURL( file, host )); } protected String getMimeType( TranscodeFileImpl file ) { return( manager.getMimeType( file )); } protected void deleteFile( TranscodeFileImpl file, boolean delete_contents, boolean remove ) throws TranscodeException { if ( file.isDeleted()){ return; } if ( delete_contents ){ File f = file.getCacheFile(); int time = 0; while( f.exists() && !f.delete()){ if ( time > 3000 ){ log( "Failed to remove file '" + f.getAbsolutePath() + "'" ); break; }else{ try{ Thread.sleep(500); }catch( Throwable e ){ } time += 500; } } } if ( remove ){ try{ synchronized( this ){ if ( device_files == null ){ loadDeviceFile(); }else{ device_files_last_mod = SystemTime.getMonotonousTime(); } device_files.remove( file.getKey()); device_files_dirty = true; } for ( TranscodeTargetListener l: listeners ){ try{ l.fileRemoved( file ); }catch( Throwable e ){ Debug.out( e ); } } }catch( Throwable e ){ throw( new TranscodeException( "Delete failed", e )); } } } protected void fileDirty( TranscodeFileImpl file, int type, Object data ) { try{ synchronized( this ){ if ( device_files == null ){ loadDeviceFile(); }else{ device_files_last_mod = SystemTime.getMonotonousTime(); } } device_files_dirty = true; }catch( Throwable e ){ Debug.out( "Failed to load device file", e ); } for ( TranscodeTargetListener l: listeners ){ try{ l.fileChanged( file, type, data ); }catch( Throwable e ){ Debug.out( e ); } } } protected void saveDeviceFile() { device_files_dirty = false; try{ loadDeviceFile(); if ( device_files == null || device_files.size()==0 ){ FileUtil.deleteResilientFile( getDeviceFile()); }else{ Map map = new HashMap(); map.put( "files", device_files ); FileUtil.writeResilientFile( getDeviceFile(), map ); } }catch( Throwable e ){ Debug.out( "Failed to save device file", e ); } } protected File getDeviceFile() throws IOException { File dir = getDevicesDir(); return( new File( dir, FileUtil.convertOSSpecificChars(getID(),false) + ".dat" )); } protected File getDevicesDir() throws IOException { File dir = new File(SystemProperties.getUserPath()); dir = new File( dir, "devices" ); if ( !dir.exists()){ if ( !dir.mkdirs()){ throw( new IOException( "Failed to create '" + dir + "'" )); } } return( dir ); } protected DeviceManagerImpl getManager() { return( manager ); } public void addListener( TranscodeTargetListener listener ) { if (!listeners.contains(listener)) { listeners.add( listener ); } } public void removeListener( TranscodeTargetListener listener ) { listeners.remove( listener ); } protected void fireChanged() { List l; synchronized( this ){ if ( device_listeners != null ){ l = device_listeners.getList(); }else{ return; } } for ( DeviceListener listener: l ){ try{ listener.deviceChanged( this ); }catch( Throwable e ){ Debug.out( e ); } } } public void addListener( DeviceListener listener ) { synchronized( this ){ if ( device_listeners == null ){ device_listeners = new CopyOnWriteList(); } device_listeners.add( listener ); } } public void removeListener( DeviceListener listener ) { synchronized( this ){ if ( device_listeners != null ){ device_listeners.remove( listener ); if ( device_listeners.size() == 0 ){ device_listeners = null; } } } } protected void log( String str ) { manager.log( str ); } protected void log( String str, Throwable e ) { manager.log( str, e ); } public String getString() { return( "type=" + type + ",uid=" + uid + ",class=" + classification ); } public void generate( IndentWriter writer ) { writer.println( getName() + "/" + getID() + "/" + type ); try{ writer.indent(); writer.println( "hidden=" + hidden + ", last_seen=" + new SimpleDateFormat().format(new Date(last_seen)) + ", online=" + online + ", transcoding=" + transcoding ); writer.println( "p_props=" + persistent_properties ); writer.println( "t_props=" + transient_properties ); writer.println( "errors=" + errors ); writer.println( "infos=" + infos ); }finally{ writer.exdent(); } } public void generateTT( IndentWriter writer ) { TranscodeFileImpl[] files = getFiles(); int complete = 0; int copied = 0; int deleted = 0; int template = 0; for ( TranscodeFileImpl f: files ){ if ( f.isComplete()){ complete++; } if ( f.isCopiedToDevice()){ copied++; } if ( f.isDeleted()){ deleted++; } if ( f.isTemplate()){ template++; } } writer.println( "files=" + files.length + ", comp=" + complete + ", copied=" + copied + ", deleted=" + deleted + ", template=" + template ); } protected class browseLocationImpl implements browseLocation { private String name; private URL url; protected browseLocationImpl( String _name, URL _url ) { name = _name; url = _url; } public String getName() { return( name ); } public URL getURL() { return( url ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererTemplateImpl.java0000644000175000017500000000575011227541540031076 0ustar adrianadrian/* * Created on Jul 10, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.util.*; import com.aelitis.azureus.core.devices.Device; import com.aelitis.azureus.core.devices.DeviceManagerException; import com.aelitis.azureus.core.devices.DeviceMediaRenderer; import com.aelitis.azureus.core.devices.DeviceMediaRendererTemplate; import com.aelitis.azureus.core.devices.TranscodeProfile; public class DeviceMediaRendererTemplateImpl implements DeviceMediaRendererTemplate { private List profiles = new ArrayList(); private final DeviceManagerImpl manager; private final String classification; private final String name; private final String manufacturer; private final boolean auto; protected DeviceMediaRendererTemplateImpl( DeviceManagerImpl _manager, String _classification, boolean _auto ) { manager = _manager; classification = _classification; auto = _auto; int pos = classification.indexOf( '.' ); if ( pos == -1 ){ manufacturer = classification; }else{ manufacturer = classification.substring( 0, pos ); } pos = classification.lastIndexOf( '.' ); if ( pos == -1 ){ name = classification; }else{ name = classification.substring( pos+1 ); } } protected void addProfile( TranscodeProfile profile ) { profiles.add( profile ); } public TranscodeProfile[] getProfiles() { return( profiles.toArray(new TranscodeProfile[profiles.size()])); } public int getType() { return( Device.DT_MEDIA_RENDERER ); } public String getName() { return( name ); } public String getManufacturer() { return( manufacturer ); } public String getClassification() { return( classification ); } public String getShortDescription() { return( null ); } public int getRendererSpecies() { return( DeviceMediaRenderer.RS_OTHER ); } public boolean isAuto() { return( auto ); } public Device createInstance( String name ) throws DeviceManagerException { if ( auto ){ throw( new DeviceManagerException( "Device can't be added manually" )); } Device res = manager.createDevice( Device.DT_MEDIA_RENDERER, classification, name ); return( res ); } }azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceUPnPImpl.java0000644000175000017500000006576311246134610025525 0ustar adrianadrian/* * Created on Jan 28, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.WeakHashMap; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadAttributeListener; import org.gudy.azureus2.plugins.download.DownloadManager; import org.gudy.azureus2.plugins.download.DownloadManagerListener; import org.gudy.azureus2.plugins.ipc.IPCInterface; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.content.AzureusContentDownload; import com.aelitis.azureus.core.content.AzureusContentFile; import com.aelitis.azureus.core.content.AzureusPlatformContentDirectory; import com.aelitis.azureus.core.devices.TranscodeException; import com.aelitis.azureus.core.devices.TranscodeFile; import com.aelitis.azureus.core.devices.TranscodeJob; import com.aelitis.azureus.core.devices.TranscodeProfile; import com.aelitis.azureus.core.devices.TranscodeTarget; import com.aelitis.azureus.core.devices.TranscodeTargetListener; import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice; import com.aelitis.azureus.core.download.DiskManagerFileInfoStream; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.core.util.UUIDGenerator; import com.aelitis.net.upnp.UPnPDevice; import com.aelitis.net.upnp.UPnPRootDevice; public abstract class DeviceUPnPImpl extends DeviceImpl implements TranscodeTargetListener, DownloadManagerListener { private static final Object UPNPAV_FILE_KEY = new Object(); private static final Map acf_map = new WeakHashMap(); protected static String getDisplayName( UPnPDevice device ) { UPnPDevice root = device.getRootDevice().getDevice(); String fn = root.getFriendlyName(); if ( fn == null || fn.length() == 0 ){ fn = device.getFriendlyName(); } String dn = root.getModelName(); if ( dn == null || dn.length() == 0 ){ dn = device.getModelName(); } if ( dn != null && dn.length() > 0 ){ if ( !fn.contains( dn ) && ( !dn.contains( "Azureus" ) || dn.contains( "Vuze" ))){ fn += " (" + dn + ")"; } } return( fn ); } private final String MY_ACF_KEY; private final DeviceManagerUPnPImpl upnp_manager; private volatile UPnPDevice device_may_be_null; private IPCInterface upnpav_ipc; private TranscodeProfile dynamic_transcode_profile; private Map dynamic_xcode_map; protected DeviceUPnPImpl( DeviceManagerImpl _manager, UPnPDevice _device, int _type ) { super( _manager, _type, _type + "/" + _device.getRootDevice().getUSN(), getDisplayName( _device ), false ); upnp_manager = _manager.getUPnPManager(); device_may_be_null = _device; MY_ACF_KEY = getACFKey(); } protected DeviceUPnPImpl( DeviceManagerImpl _manager, int _type, String _classification ) { super( _manager, _type, UUIDGenerator.generateUUIDString(), _classification, true ); upnp_manager = _manager.getUPnPManager(); MY_ACF_KEY = getACFKey(); } protected DeviceUPnPImpl( DeviceManagerImpl _manager, int _type, String _classification, boolean _manual, String _name ) { super( _manager, _type, UUIDGenerator.generateUUIDString(), _classification, _manual, _name ); upnp_manager = _manager.getUPnPManager(); MY_ACF_KEY = getACFKey(); } protected DeviceUPnPImpl( DeviceManagerImpl _manager, int _type, String _uuid, String _classification, boolean _manual ) { super( _manager, _type, _uuid, _classification, _manual ); upnp_manager = _manager.getUPnPManager(); MY_ACF_KEY = getACFKey(); } protected DeviceUPnPImpl( DeviceManagerImpl _manager, Map _map ) throws IOException { super(_manager, _map ); upnp_manager = _manager.getUPnPManager(); MY_ACF_KEY = getACFKey(); } protected String getACFKey() { return( "DeviceUPnPImpl:device:" + getID()); } @Override protected boolean updateFrom( DeviceImpl _other, boolean _is_alive ) { if ( !super.updateFrom( _other, _is_alive )){ return( false ); } if ( !( _other instanceof DeviceUPnPImpl )){ Debug.out( "Inconsistent" ); return( false ); } DeviceUPnPImpl other = (DeviceUPnPImpl)_other; device_may_be_null = other.device_may_be_null; return( true ); } @Override protected void initialise() { super.initialise(); } protected void UPnPInitialised() { } @Override protected void destroy() { super.destroy(); } protected DeviceManagerUPnPImpl getUPnPDeviceManager() { return( upnp_manager ); } protected UPnPDevice getUPnPDevice() { return( device_may_be_null ); } public boolean isBrowsable() { return( true ); } public browseLocation[] getBrowseLocations() { List locs = new ArrayList(); UPnPDevice device = device_may_be_null; if ( device != null ){ URL presentation = getPresentationURL( device ); if ( presentation != null ){ locs.add( new browseLocationImpl( "device.upnp.present_url", presentation )); } locs.add( new browseLocationImpl( "device.upnp.desc_url", device.getRootDevice().getLocation())); } return( locs.toArray( new browseLocation[ locs.size() ])); } public boolean canFilterFilesView() { return( true ); } public void setFilterFilesView( boolean filter ) { boolean existing = getFilterFilesView(); if ( existing != filter ){ setPersistentBooleanProperty( PP_FILTER_FILES, filter ); IPCInterface ipc = upnpav_ipc; if ( ipc != null ){ try{ ipc.invoke( "invalidateDirectory", new Object[]{}); }catch( Throwable e ){ } } } } public boolean getFilterFilesView() { return( getPersistentBooleanProperty( PP_FILTER_FILES, true )); } public boolean isLivenessDetectable() { return( true ); } protected URL getLocation() { UPnPDevice device = device_may_be_null; if ( device != null ){ UPnPRootDevice root = device.getRootDevice(); return( root.getLocation()); } return( null ); } public boolean canAssociate() { return( true ); } public void associate( UnassociatedDevice assoc ) { if ( isAlive()){ return; } setAddress( assoc.getAddress()); alive(); } public InetAddress getAddress() { try{ UPnPDevice device = device_may_be_null; if ( device != null ){ UPnPRootDevice root = device.getRootDevice(); URL location = root.getLocation(); return( InetAddress.getByName( location.getHost() )); }else{ InetAddress address = (InetAddress)getTransientProperty( TP_IP_ADDRESS ); if ( address != null ){ return( address ); } String last = getPersistentStringProperty( PP_IP_ADDRESS ); if ( last != null && last.length() > 0 ){ return( InetAddress.getByName( last )); } } }catch( Throwable e ){ Debug.printStackTrace(e); } return( null ); } protected void setAddress( InetAddress address ) { setTransientProperty( TP_IP_ADDRESS, address ); setPersistentStringProperty( PP_IP_ADDRESS, address.getHostAddress()); } protected URL getStreamURL( TranscodeFileImpl file ) { browseReceived(); return( super.getStreamURL( file, null )); } protected void browseReceived() { IPCInterface ipc = upnp_manager.getUPnPAVIPC(); if ( ipc == null ){ return; } TranscodeProfile default_profile = getDefaultTranscodeProfile(); if ( default_profile == null ){ TranscodeProfile[] profiles = getTranscodeProfiles(); for ( TranscodeProfile p: profiles ){ if ( p.isStreamable()){ default_profile = p; break; } } } synchronized( this ){ if ( upnpav_ipc != null ){ return; } upnpav_ipc = ipc; if ( default_profile != null && default_profile.isStreamable()){ dynamic_transcode_profile = default_profile; } } if ( dynamic_transcode_profile != null && this instanceof TranscodeTarget ){ // In theory this is a plugin, so there should be a core.. // However, check just in case AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { DownloadManager dm = PluginInitializer.getDefaultInterface().getDownloadManager(); dm.addListener( DeviceUPnPImpl.this, true ); } }); } addListener( this ); TranscodeFile[] transcode_files = getFiles(); for ( TranscodeFile file: transcode_files ){ fileAdded( file, false ); } } protected void resetUPNPAV() { synchronized( this ){ if ( upnpav_ipc == null ){ return; } upnpav_ipc = null; dynamic_transcode_profile = null; dynamic_xcode_map = null; DownloadManager dm = PluginInitializer.getDefaultInterface().getDownloadManager(); dm.removeListener( this ); removeListener( this ); TranscodeFile[] transcode_files = getFiles(); for ( TranscodeFile file: transcode_files ){ file.setTransientProperty( UPNPAV_FILE_KEY, null ); } } } public void downloadAdded( Download download ) { Torrent torrent = download.getTorrent(); if ( torrent != null && PlatformTorrentUtils.isContent( torrent, false )){ addDynamicXCode( download.getDiskManagerFileInfo()[0]); } } public void downloadRemoved( Download download ) { Torrent torrent = download.getTorrent(); if ( torrent != null && PlatformTorrentUtils.isContent( torrent, false )){ removeDynamicXCode( download.getDiskManagerFileInfo()[0]); } } protected void addDynamicXCode( final DiskManagerFileInfo source ) { final TranscodeProfile profile = dynamic_transcode_profile; IPCInterface ipc = upnpav_ipc; if ( profile == null || ipc == null ){ return; } try{ TranscodeFileImpl transcode_file = allocateFile( profile, false, source, false ); AzureusContentFile acf = (AzureusContentFile)transcode_file.getTransientProperty( UPNPAV_FILE_KEY ); if ( acf != null ){ return; } final String tf_key = transcode_file.getKey(); synchronized( acf_map ){ acf = acf_map.get( tf_key ); } if ( acf != null ){ return; } final DiskManagerFileInfo stream_file = new DiskManagerFileInfoStream( new DiskManagerFileInfoStream.StreamFactory() { private List current_requests = new ArrayList(); public StreamDetails getStream( Object request ) throws IOException { try{ TranscodeJobImpl job = getManager().getTranscodeManager().getQueue().add( (TranscodeTarget)DeviceUPnPImpl.this, profile, source, true ); synchronized( this ){ current_requests.add( request ); } while( true ){ InputStream is = job.getStream( 1000 ); if ( is != null ){ return( new StreamWrapper( is, job )); } int state = job.getState(); if ( state == TranscodeJobImpl.ST_FAILED ){ throw( new IOException( "Transcode failed: " + job.getError())); }else if ( state == TranscodeJobImpl.ST_CANCELLED ){ throw( new IOException( "Transcode failed: job cancelled" )); }else if ( state == TranscodeJobImpl.ST_COMPLETE ){ throw( new IOException( "Job complete but no stream!" )); } synchronized( this ){ if ( !current_requests.contains( request )){ break; } } System.out.println( "waiting for stream" ); } IOException error = new IOException( "Stream request cancelled" ); job.failed( error ); throw( error ); }catch( IOException e ){ throw( e ); }catch( Throwable e ){ throw( new IOException( "Failed to add transcode job: " + Debug.getNestedExceptionMessage(e))); }finally{ synchronized( this ){ current_requests.remove( request ); } } } public void destroyed( Object request ) { synchronized( this ){ current_requests.remove( request ); } } }, transcode_file.getCacheFile()); acf = new AzureusContentFile() { public DiskManagerFileInfo getFile() { return( stream_file ); } public Object getProperty( String name ) { // TODO: duration etc if ( name.equals( MY_ACF_KEY )){ return( new Object[]{ DeviceUPnPImpl.this, tf_key }); }else if ( name.equals( PT_PERCENT_DONE )){ return( new Long(1000)); }else if ( name.equals( PT_ETA )){ return( new Long(0)); } return( null ); } }; synchronized( acf_map ){ acf_map.put( tf_key, acf ); } transcode_file.setTransientProperty( UPNPAV_FILE_KEY, acf ); syncCategories( transcode_file, true ); synchronized( this ){ if ( dynamic_xcode_map == null ){ dynamic_xcode_map = new HashMap(); } dynamic_xcode_map.put( tf_key, acf ); } ipc.invoke( "addContent", new Object[]{ acf }); }catch( Throwable e ){ Debug.out( e ); } } protected void removeDynamicXCode( final DiskManagerFileInfo source ) { final TranscodeProfile profile = dynamic_transcode_profile; IPCInterface ipc = upnpav_ipc; if ( profile == null || ipc == null ){ return; } try{ TranscodeFileImpl transcode_file = lookupFile( profile, source ); // if the file completed transcoding then we leave the result around for // the user to re-use if ( transcode_file != null && !transcode_file.isComplete()){ AzureusContentFile acf = null; synchronized( this ){ if ( dynamic_xcode_map != null ){ acf = dynamic_xcode_map.get( transcode_file.getKey()); } } transcode_file.delete( true ); if ( acf != null ){ ipc.invoke( "removeContent", new Object[]{ acf }); } synchronized( acf_map ){ acf_map.remove( transcode_file.getKey()); } } }catch( Throwable e ){ Debug.out( e ); } } protected boolean setupStreamXCode( TranscodeFileImpl transcode_file ) { final TranscodeJobImpl job = transcode_file.getJob(); if ( job == null ){ // may have just completed, say things are OK as caller can continue return( transcode_file.isComplete()); } final String tf_key = transcode_file.getKey(); AzureusContentFile acf; synchronized( acf_map ){ acf = acf_map.get( tf_key ); } if ( acf != null ){ return( true ); } IPCInterface ipc = upnpav_ipc; if ( ipc == null ){ return( false ); } if ( transcode_file.getDurationMillis() == 0 ){ return( false ); } try{ final DiskManagerFileInfo stream_file = new TranscodeJobOutputLeecher( job, transcode_file ); acf = new AzureusContentFile() { public DiskManagerFileInfo getFile() { return( stream_file ); } public Object getProperty( String name ) { // TODO: duration etc if ( name.equals( MY_ACF_KEY )){ return( new Object[]{ DeviceUPnPImpl.this, tf_key }); }else if ( name.equals( PT_PERCENT_DONE )){ return( new Long(1000)); }else if ( name.equals( PT_ETA )){ return( new Long(0)); } return( null ); } }; synchronized( acf_map ){ acf_map.put( tf_key, acf ); } ipc.invoke( "addContent", new Object[]{ acf }); log( "Set up stream-xcode for " + transcode_file.getName()); return( true ); }catch( Throwable e ){ return( false ); } } protected boolean isVisible( AzureusContentDownload file ) { return( !getFilterFilesView()); } protected boolean isVisible( AzureusContentFile file ) { boolean result; if ( getFilterFilesView()){ Object[] x = (Object[])file.getProperty( MY_ACF_KEY ); if ( x != null && x[0] == this ){ String tf_key = (String)x[1]; result = getTranscodeFile( tf_key ) != null; }else{ result = false; } }else{ result = true; } return( result ); } public void fileAdded( TranscodeFile _transcode_file ) { fileAdded( _transcode_file, true ); } public void fileAdded( TranscodeFile _transcode_file, boolean _new_file ) { TranscodeFileImpl transcode_file = (TranscodeFileImpl)_transcode_file; IPCInterface ipc = upnpav_ipc; synchronized( this ){ if ( ipc == null ){ return; } if ( !transcode_file.isComplete()){ syncCategories( transcode_file, _new_file ); return; } AzureusContentFile acf = (AzureusContentFile)transcode_file.getTransientProperty( UPNPAV_FILE_KEY ); if ( acf != null ){ return; } final String tf_key = transcode_file.getKey(); synchronized( acf_map ){ acf = acf_map.get( tf_key ); } if ( acf != null ){ return; } try{ final DiskManagerFileInfo f = transcode_file.getTargetFile(); acf = new AzureusContentFile() { public DiskManagerFileInfo getFile() { return( f ); } public Object getProperty( String name ) { if( name.equals( MY_ACF_KEY )){ return( new Object[]{ DeviceUPnPImpl.this, tf_key }); }else if ( name.equals( PT_CATEGORIES )){ TranscodeFileImpl tf = getTranscodeFile( tf_key ); if ( tf != null ){ return( tf.getCategories()); } return( new String[0] ); }else{ TranscodeFileImpl tf = getTranscodeFile( tf_key ); if ( tf != null ){ long res = 0; if ( name.equals( PT_DURATION )){ res = tf.getDurationMillis(); }else if ( name.equals( PT_VIDEO_WIDTH )){ res = tf.getVideoWidth(); }else if ( name.equals( PT_VIDEO_HEIGHT )){ res = tf.getVideoHeight(); }else if ( name.equals( PT_DATE )){ res = tf.getCreationDateMillis(); }else if ( name.equals( PT_PERCENT_DONE )){ if ( tf.isComplete()){ res = 1000; }else{ TranscodeJob job = tf.getJob(); if ( job == null ){ res = 0; }else{ res = 10*job.getPercentComplete(); } } return( res ); }else if ( name.equals( PT_ETA )){ if ( tf.isComplete()){ res = 0; }else{ TranscodeJob job = tf.getJob(); if ( job == null ){ res = Long.MAX_VALUE; }else{ res = job.getETASecs(); } } return( res ); } if ( res > 0 ){ return( new Long( res )); } } } return( null ); } }; transcode_file.setTransientProperty( UPNPAV_FILE_KEY, acf ); synchronized( acf_map ){ acf_map.put( tf_key, acf ); } syncCategories( transcode_file, _new_file ); try{ ipc.invoke( "addContent", new Object[]{ acf }); }catch( Throwable e ){ Debug.out( e ); } }catch( TranscodeException e ){ // file deleted } } } protected void syncCategories( TranscodeFileImpl tf, boolean inherit_from_download ) { try{ Download dl = tf.getSourceFile().getDownload(); if ( dl != null ){ // only overwrite categories with the downloads ones if none already set if ( inherit_from_download ){ setCategories( tf, dl ); } final String tf_key = tf.getKey(); dl.addAttributeListener( new DownloadAttributeListener() { public void attributeEventOccurred( Download download, TorrentAttribute attribute, int eventType) { TranscodeFileImpl tf = getTranscodeFile( tf_key ); if ( tf != null ){ setCategories( tf, download ); } } }, upnp_manager.getCategoryAttibute(), DownloadAttributeListener.WRITTEN ); } }catch( Throwable e ){ } } protected void setCategories( TranscodeFileImpl tf, Download dl ) { String cat = dl.getCategoryName(); if ( cat != null && cat.length() > 0 && !cat.equals( "Categories.uncategorized" )){ tf.setCategories( new String[]{ cat }); }else{ tf.setCategories( new String[0] ); } } public void fileChanged( TranscodeFile file, int type, Object data ) { if ( file.isComplete()){ fileAdded( file, false ); } if ( type == TranscodeTargetListener.CT_PROPERTY ){ if ( data == TranscodeFile.PT_CATEGORY ){ AzureusContentFile acf; synchronized( acf_map ){ acf = acf_map.get(((TranscodeFileImpl)file).getKey()); } if ( acf != null ){ AzureusPlatformContentDirectory.fireChanged( acf ); } } } } public void fileRemoved( TranscodeFile file ) { IPCInterface ipc = upnp_manager.getUPnPAVIPC(); if ( ipc == null ){ return; } synchronized( this ){ AzureusContentFile acf = (AzureusContentFile)file.getTransientProperty( UPNPAV_FILE_KEY ); if ( acf == null ){ return; } file.setTransientProperty( UPNPAV_FILE_KEY, null ); try{ ipc.invoke( "removeContent", new Object[]{ acf }); }catch( Throwable e ){ Debug.out( e ); } } synchronized( acf_map ){ acf_map.remove( ((TranscodeFileImpl)file).getKey()); } } protected URL getPresentationURL( UPnPDevice device ) { String presentation = device.getRootDevice().getDevice().getPresentation(); if ( presentation != null ){ try{ URL url = new URL( presentation ); return( url ); }catch( Throwable e ){ } } return( null ); } protected void getDisplayProperties( List dp ) { super.getDisplayProperties( dp ); UPnPDevice device = device_may_be_null; if ( device != null ){ UPnPRootDevice root = device.getRootDevice(); URL location = root.getLocation(); addDP( dp, "dht.reseed.ip", location.getHost() + ":" + location.getPort()); String model_details = device.getModelName(); String model_url = device.getModelURL(); if ( model_url != null && model_url.length() > 0 ){ model_details += " (" + model_url + ")"; } String manu_details = device.getManufacturer(); String manu_url = device.getManufacturerURL(); if ( manu_url != null && manu_url.length() > 0 ){ manu_details += " (" + manu_url + ")"; } addDP( dp, "device.model.desc", device.getModelDescription()); addDP( dp, "device.model.name", model_details ); addDP( dp, "device.model.num", device.getModelNumber()); addDP( dp, "device.manu.desc", manu_details ); }else{ InetAddress ia = getAddress(); if ( ia != null ){ addDP( dp, "dht.reseed.ip", ia.getHostAddress()); } } } public void generate( IndentWriter writer ) { super.generate( writer ); try{ writer.indent(); UPnPDevice device = device_may_be_null; if ( device == null ){ writer.println( "upnp_device=null" ); }else{ writer.println( "upnp_device=" + device.getFriendlyName()); } writer.println( "dyn_xcode=" + (dynamic_transcode_profile==null?"null":dynamic_transcode_profile.getName())); }finally{ writer.exdent(); } } protected static class StreamWrapper implements DiskManagerFileInfoStream.StreamFactory.StreamDetails { private InputStream is; private TranscodeJob job; protected StreamWrapper( InputStream _is, TranscodeJob _job ) { is = _is; job = _job; } public InputStream getStream() { return( is ); } public boolean hasFailed() { long start = SystemTime.getMonotonousTime(); while( true ){ int state = job.getState(); // timing issues - we can get here during teh fail process so // hang around a little if we're still running if ( state == TranscodeJobImpl.ST_RUNNING ){ if ( SystemTime.getMonotonousTime() - start > 5*1000 ){ return( true ); }else{ try{ Thread.sleep(250); continue; }catch( Throwable e ){ return( true ); } } } if ( state == TranscodeJobImpl.ST_FAILED || state == TranscodeJobImpl.ST_CANCELLED || state == TranscodeJobImpl.ST_REMOVED || state == TranscodeJobImpl.ST_STOPPED ){ return( true ); } } } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceContentDirectoryImpl.java0000644000175000017500000000353111236202400030153 0ustar adrianadrian/* * Created on Jan 28, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.IOException; import java.util.Map; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.devices.*; import com.aelitis.net.upnp.UPnPDevice; import com.aelitis.net.upnp.UPnPService; public class DeviceContentDirectoryImpl extends DeviceUPnPImpl implements DeviceContentDirectory { protected DeviceContentDirectoryImpl( DeviceManagerImpl _manager, UPnPDevice _device, UPnPService _service ) { super( _manager, _device, Device.DT_CONTENT_DIRECTORY ); } protected DeviceContentDirectoryImpl( DeviceManagerImpl _manager, Map _map ) throws IOException { super(_manager, _map ); } protected boolean updateFrom( DeviceImpl _other, boolean _is_alive ) { if ( !super.updateFrom( _other, _is_alive )){ return( false ); } if ( !( _other instanceof DeviceContentDirectoryImpl )){ Debug.out( "Inconsistent" ); return( false ); } DeviceContentDirectoryImpl other = (DeviceContentDirectoryImpl)_other; return( true ); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceManagerImpl.java0000644000175000017500000006456111266732670026264 0ustar adrianadrian/* * Created on Jan 27, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.File; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator; import org.gudy.azureus2.core3.util.AEDiagnosticsLogger; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.AsyncDispatcher; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DelayedEvent; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.ListenerManager; import org.gudy.azureus2.core3.util.ListenerManagerDispatcher; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.ipc.IPCInterface; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter; import com.aelitis.azureus.core.devices.*; import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger; public class DeviceManagerImpl implements DeviceManager, DeviceOfflineDownloaderManager, AEDiagnosticsEvidenceGenerator { private static final String LOGGER_NAME = "Devices"; private static final String CONFIG_FILE = "devices.config"; private static final String AUTO_SEARCH_CONFIG_KEY = "devices.config.auto_search"; private static final String RSS_ENABLE_CONFIG_KEY = "devices.config.rss_enable"; private static final String OD_ENABLED_CONFIG_KEY = "devices.config.od.enabled"; private static final String OD_IS_AUTO_CONFIG_KEY = "devices.config.od.auto"; private static final String OD_INCLUDE_PRIVATE_CONFIG_KEY = "devices.config.od.inc_priv"; private static final String CONFIG_DEFAULT_WORK_DIR = "devices.config.def_work_dir"; protected static final int DEVICE_UPDATE_PERIOD = 5*1000; private static DeviceManagerImpl singleton; public static void preInitialise() { } public static DeviceManager getSingleton() { synchronized( DeviceManagerImpl.class ){ if ( singleton == null ){ singleton = new DeviceManagerImpl(); } } return( singleton ); } private AzureusCore azureus_core; private TorrentAttribute od_manual_ta; private List device_list = new ArrayList(); private Map device_map = new HashMap(); private DeviceTivoManager tivo_manager; private DeviceManagerUPnPImpl upnp_manager; private DeviceDriveManager drive_manager; // have to go async on this as there are situations where we end up firing listeners // while holding monitors and this can result in deadlock if sync private static final int LT_DEVICE_ADDED = 1; private static final int LT_DEVICE_CHANGED = 2; private static final int LT_DEVICE_ATTENTION = 3; private static final int LT_DEVICE_REMOVED = 4; private static final int LT_INITIALIZED = 5; private ListenerManager listeners = ListenerManager.createAsyncManager( "DM:ld", new ListenerManagerDispatcher() { public void dispatch( DeviceManagerListener listener, int type, Object value ) { DeviceImpl device = (DeviceImpl)value; switch( type ){ case LT_DEVICE_ADDED:{ listener.deviceAdded( device ); break; } case LT_DEVICE_CHANGED:{ if ( deviceAdded( device )){ device.fireChanged(); listener.deviceChanged( device ); } break; } case LT_DEVICE_ATTENTION:{ if ( deviceAdded( device )){ listener.deviceAttentionRequest( device ); } break; } case LT_DEVICE_REMOVED:{ listener.deviceRemoved( device ); break; } case LT_INITIALIZED:{ listener.deviceManagerLoaded(); break; } } } protected boolean deviceAdded( Device device ) { synchronized( DeviceManagerImpl.this ){ return( device_list.contains( device )); } } }); private boolean auto_search; private DeviceManagerRSSFeed rss_publisher; private boolean od_enabled; private boolean od_is_auto; private boolean od_include_private; private boolean closing; private boolean config_unclean; private boolean config_dirty; private int explicit_search; private TranscodeManagerImpl transcode_manager; private int getMimeType_fails; private AEDiagnosticsLogger logger; private AsyncDispatcher async_dispatcher = new AsyncDispatcher( 10*1000 ); private volatile boolean initialized = false; protected DeviceManagerImpl() { AEDiagnostics.addEvidenceGenerator( this ); AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { initWithCore(core); } }); } private void initWithCore( final AzureusCore core ) { azureus_core = core; od_manual_ta = PluginInitializer.getDefaultInterface().getTorrentManager().getPluginAttribute( "device.manager.od.ta.manual" ); rss_publisher = new DeviceManagerRSSFeed( this ); // need to pick up auto-search early on COConfigurationManager.addAndFireParameterListeners( new String[]{ AUTO_SEARCH_CONFIG_KEY, }, new ParameterListener() { public void parameterChanged( String name ) { auto_search = COConfigurationManager.getBooleanParameter( AUTO_SEARCH_CONFIG_KEY, true ); } }); COConfigurationManager.addAndFireParameterListeners( new String[]{ OD_ENABLED_CONFIG_KEY, OD_IS_AUTO_CONFIG_KEY, OD_INCLUDE_PRIVATE_CONFIG_KEY }, new ParameterListener() { public void parameterChanged( String name ) { boolean new_od_enabled = COConfigurationManager.getBooleanParameter( OD_ENABLED_CONFIG_KEY, true ); boolean new_od_is_auto = COConfigurationManager.getBooleanParameter( OD_IS_AUTO_CONFIG_KEY, true ); boolean new_od_include_private_priv = COConfigurationManager.getBooleanParameter( OD_INCLUDE_PRIVATE_CONFIG_KEY, false ); if ( new_od_enabled != od_enabled || new_od_is_auto != od_is_auto || new_od_include_private_priv != od_include_private ){ od_enabled = new_od_enabled; od_is_auto = new_od_is_auto; od_include_private = new_od_include_private_priv; manageOD(); } } }); // init tivo before upnp as upnp init completion starts up tivo tivo_manager = new DeviceTivoManager( this ); upnp_manager = new DeviceManagerUPnPImpl( this ); loadConfig(); new DeviceiTunesManager( this ); drive_manager = new DeviceDriveManager( this ); transcode_manager = new TranscodeManagerImpl( this ); core.addLifecycleListener( new AzureusCoreLifecycleAdapter() { public void stopping( AzureusCore core ) { synchronized( DeviceManagerImpl.this ){ if ( config_dirty || config_unclean ){ saveConfig(); } closing = true; transcode_manager.close(); DeviceImpl[] devices = getDevices(); for ( DeviceImpl device: devices ){ device.close(); } } } }); upnp_manager.initialise(); SimpleTimer.addPeriodicEvent( "DeviceManager:update", DEVICE_UPDATE_PERIOD, new TimerEventPerformer() { private int tick_count = 0; public void perform( TimerEvent event ) { List copy; tick_count++; transcode_manager.updateStatus( tick_count ); synchronized( DeviceManagerImpl.this ){ if( device_list.size() == 0 ){ return; } copy = new ArrayList( device_list ); } for ( DeviceImpl device: copy ){ device.updateStatus( tick_count ); } } }); initialized = true; listeners.dispatch( LT_INITIALIZED, null ); } protected void manageOD() { DeviceImpl[] devices = getDevices(); for ( DeviceImpl device: devices ){ if ( device.getType() == Device.DT_OFFLINE_DOWNLOADER ){ ((DeviceOfflineDownloaderImpl)device).checkConfig(); } } } protected void UPnPManagerStarted() { tivo_manager.startUp(); DeviceImpl[] devices = getDevices(); for ( DeviceImpl device: devices ){ if ( device instanceof DeviceUPnPImpl ){ ((DeviceUPnPImpl)device).UPnPInitialised(); } } } protected AzureusCore getAzureusCore() { return( azureus_core ); } protected DeviceManagerUPnPImpl getUPnPManager() { return( upnp_manager ); } public boolean isTiVoEnabled() { return( tivo_manager.isEnabled()); } public void setTiVoEnabled( boolean enabled ) { tivo_manager.setEnabled( enabled ); } public DeviceTemplate[] getDeviceTemplates( int device_type ) { if ( transcode_manager == null || device_type != Device.DT_MEDIA_RENDERER ){ return( new DeviceTemplate[0] ); } TranscodeProvider[] providers = transcode_manager.getProviders(); List result = new ArrayList(); for ( TranscodeProvider provider: providers ){ TranscodeProfile[] profiles = provider.getProfiles(); Map class_map = new HashMap(); for ( TranscodeProfile profile: profiles ){ String classification = profile.getDeviceClassification(); if ( classification.startsWith( "apple." )){ classification = "apple."; } boolean auto = classification.equals( "sony.PS3" ) || classification.equals( "microsoft.XBox" ) || classification.equals( "apple." ) || classification.equals( "nintendo.Wii" ) || classification.equals( "browser.generic" ); DeviceMediaRendererTemplateImpl temp = class_map.get( classification ); if ( temp == null ){ temp = new DeviceMediaRendererTemplateImpl( this, classification, auto ); class_map.put( classification, temp ); result.add( temp ); } temp.addProfile( profile ); } } return( result.toArray( new DeviceTemplate[ result.size() ])); } public DeviceManufacturer[] getDeviceManufacturers( int device_type ) { DeviceTemplate[] templates = getDeviceTemplates( device_type ); Map map = new HashMap(); for ( DeviceTemplate template: templates ){ if ( template.getType() != device_type ){ continue; } String man_str = template.getManufacturer(); DeviceManufacturerImpl man = map.get( man_str ); if ( man == null ){ man = new DeviceManufacturerImpl( man_str ); map.put( man_str, man ); } man.addTemplate( template ); } return( map.values().toArray( new DeviceManufacturer[ map.size() ] )); } protected Device createDevice( int device_type, String classification, String name ) throws DeviceManagerException { if ( device_type == Device.DT_MEDIA_RENDERER ){ DeviceImpl res = new DeviceMediaRendererManual( this, classification, true, name ); addDevice( res ); return( res ); }else{ throw( new DeviceManagerException( "Can't manually create this device type" )); } } public void search( final int millis, final DeviceSearchListener listener ) { new AEThread2( "DM:search", true ) { public void run() { synchronized( DeviceManagerImpl.this ){ explicit_search++; } tivo_manager.search(); drive_manager.search(); AESemaphore sem = new AESemaphore( "DM:search" ); DeviceManagerListener dm_listener = new DeviceManagerListener() { public void deviceAdded( Device device ) { listener.deviceFound( device ); } public void deviceChanged( Device device ) { } public void deviceAttentionRequest( Device device ) { } public void deviceRemoved( Device device ) { } public void deviceManagerLoaded() { } }; try{ addListener( dm_listener ); upnp_manager.search(); sem.reserve( millis ); }finally{ synchronized( DeviceManagerImpl.this ){ explicit_search--; } removeListener( dm_listener ); listener.complete(); } } }.start(); } protected DeviceImpl getDevice( String id ) { synchronized( this ){ return( device_map.get( id )); } } protected DeviceImpl addDevice( DeviceImpl device ) { return( addDevice( device, true )); } protected DeviceImpl addDevice( DeviceImpl device, boolean is_alive ) { // for xbox (currently) we automagically replace a manual entry with an auto one as we may have // added the manual one when receiving a previous browse before getting the UPnP renderer details DeviceImpl existing = null; synchronized( this ){ existing = device_map.get( device.getID()); if ( existing != null ){ existing.updateFrom( device, is_alive ); }else{ if ( device.getType() == Device.DT_MEDIA_RENDERER ){ DeviceMediaRenderer renderer = (DeviceMediaRenderer)device; if ( renderer.getRendererSpecies() == DeviceMediaRenderer.RS_XBOX && !renderer.isManual()){ for ( DeviceImpl d: device_list ){ if ( d.getType() == Device.DT_MEDIA_RENDERER ){ DeviceMediaRenderer r = (DeviceMediaRenderer)d; if ( r.getRendererSpecies() == DeviceMediaRenderer.RS_XBOX && r.isManual()){ existing = d; log( "Merging " + device.getString() + " -> " + existing.getString()); String secondary_id = device.getID(); existing.setSecondaryID( secondary_id ); existing.updateFrom( device, is_alive ); } } } } } } if ( existing == null ){ device_list.add( device ); device_map.put( device.getID(), device ); } } if ( existing != null ){ // don't trigger config save here, if anything has changed it will have been handled // by the updateFrom call above // if anything has changed then the updateFrom methods should have indicated this // so there's no need to blindly fire a change event here // deviceChanged( existing, false ); return( existing ); } device.initialise(); if ( is_alive ){ device.alive(); } deviceAdded( device ); configDirty(); return( device ); } protected void removeDevice( DeviceImpl device ) { synchronized( this ){ DeviceImpl existing = device_map.remove( device.getID()); if ( existing == null ){ return; } device_list.remove( device ); String secondary_id = device.getSecondaryID(); if ( secondary_id != null ){ device_map.remove( secondary_id ); } } device.destroy(); deviceRemoved( device ); configDirty(); } public boolean isBusy() { if ( getTranscodeManager().getQueue().isTranscoding()){ return( true ); } synchronized( this ){ for ( DeviceImpl device: device_list ){ if ( device.isBusy()){ return( true ); } } } return( false ); } public DeviceImpl[] getDevices() { synchronized( this ){ return( device_list.toArray( new DeviceImpl[ device_list.size()] )); } } public boolean getAutoSearch() { return( auto_search ); } public void setAutoSearch( boolean auto ) { COConfigurationManager.setParameter( AUTO_SEARCH_CONFIG_KEY, auto ); } public boolean isRSSPublishEnabled() { return( COConfigurationManager.getBooleanParameter( RSS_ENABLE_CONFIG_KEY, false ) ); } public void setRSSPublishEnabled( boolean enabled ) { COConfigurationManager.setParameter( RSS_ENABLE_CONFIG_KEY, enabled ); } public String getRSSLink() { return( rss_publisher.getFeedURL()); } // offline downloader stuff public DeviceOfflineDownloaderManager getOfflineDownlaoderManager() { return( this ); } public boolean isOfflineDownloadingEnabled() { return( od_enabled ); } public void setOfflineDownloadingEnabled( boolean enabled ) { COConfigurationManager.setParameter( OD_ENABLED_CONFIG_KEY, enabled ); } public boolean getOfflineDownloadingIsAuto() { return( od_is_auto ); } public void setOfflineDownloadingIsAuto( boolean auto ) { COConfigurationManager.setParameter( OD_IS_AUTO_CONFIG_KEY, auto ); } public boolean getOfflineDownloadingIncludePrivate() { return( od_include_private ); } public void setOfflineDownloadingIncludePrivate( boolean include ) { COConfigurationManager.setParameter( OD_INCLUDE_PRIVATE_CONFIG_KEY, include ); } public boolean isManualDownload( Download download ) { return( download.getBooleanAttribute( od_manual_ta )); } public void addManualDownloads( Download[] downloads ) { for ( Download d: downloads ){ d.setBooleanAttribute( od_manual_ta, true ); } manageOD(); } public void removeManualDownloads( Download[] downloads ) { for ( Download d: downloads ){ d.setBooleanAttribute( od_manual_ta, false ); } manageOD(); } // sdsd protected boolean isExplicitSearch() { synchronized( this ){ return( explicit_search > 0 ); } } protected boolean isClosing() { return( closing ); } protected void loadConfig() { if ( !FileUtil.resilientConfigFileExists( CONFIG_FILE )){ return; } log( "Loading configuration" ); synchronized( this ){ Map map = FileUtil.readResilientConfigFile( CONFIG_FILE ); List l_devices = (List)map.get( "devices" ); if ( l_devices != null ){ for (int i=0;i it = device_list.iterator(); while( it.hasNext()){ DeviceImpl device = it.next(); try{ Map d = new HashMap(); device.exportToBEncodedMap( d ); l_devices.add( d ); }catch( Throwable e ){ log( "Failed to save device " + device.getString(), e ); } } FileUtil.writeResilientConfigFile( CONFIG_FILE, map ); } } } protected void deviceAdded( DeviceImpl device ) { configDirty(); // I'd rather put this in a listener, but for now this will ensure // it gets QOS'd even before any listeners are added try{ PlatformDevicesMessenger.qosFoundDevice(device); }catch( Throwable e ){ Debug.out(e); } listeners.dispatch( LT_DEVICE_ADDED, device ); } protected void deviceChanged( DeviceImpl device, boolean save_changes ) { if ( save_changes ){ configDirty(); }else{ config_unclean = true; } listeners.dispatch( LT_DEVICE_CHANGED, device ); } protected void deviceRemoved( DeviceImpl device ) { configDirty(); listeners.dispatch( LT_DEVICE_REMOVED, device ); } protected void requestAttention( DeviceImpl device ) { listeners.dispatch( LT_DEVICE_ATTENTION, device ); } protected URL getStreamURL( TranscodeFileImpl file, String host ) { IPCInterface ipc = upnp_manager.getUPnPAVIPC(); if ( ipc != null ){ try{ DiskManagerFileInfo f = file.getTargetFile(); String str = (String)ipc.invoke( "getContentURL", new Object[]{ f }); if ( str != null && str.length() > 0 ){ if ( host != null ){ str = str.replace( "127.0.0.1", host ); } return( new URL( str )); } }catch( Throwable e ){ } } return( null ); } protected String getMimeType( TranscodeFileImpl file ) { if ( getMimeType_fails > 5 ){ return( null ); } IPCInterface ipc = upnp_manager.getUPnPAVIPC(); if ( ipc != null ){ try{ DiskManagerFileInfo f = file.getTargetFile(); String str = (String)ipc.invoke( "getMimeType", new Object[]{ f }); if ( str != null && str.length() > 0 ){ return( str ); } }catch( Throwable e ){ getMimeType_fails++; e.printStackTrace(); } } return( null ); } public File getDefaultWorkingDirectory() { return( getDefaultWorkingDirectory( false )); } public File getDefaultWorkingDirectory( boolean persist ) { String def = COConfigurationManager.getStringParameter( CONFIG_DEFAULT_WORK_DIR, "" ).trim(); if ( def.length() == 0 ){ String def_dir = COConfigurationManager.getStringParameter( "Default save path" ); def = def_dir + File.separator + "transcodes"; } File f = new File( def ); if ( !f.exists()){ if ( persist ){ f.mkdirs(); } } return( f ); } public void setDefaultWorkingDirectory( File dir ) { File existing = getDefaultWorkingDirectory( false ); if ( !existing.getAbsolutePath().equals( dir.getAbsolutePath())){ // default has changed, reset all device save locations so that they pick up the change synchronized( this ){ for ( DeviceImpl d: device_list ){ d.resetWorkingDirectory(); } } } COConfigurationManager.setParameter( CONFIG_DEFAULT_WORK_DIR, dir.getAbsolutePath()); } public TranscodeManagerImpl getTranscodeManager() { return( transcode_manager ); } public UnassociatedDevice[] getUnassociatedDevices() { return( upnp_manager.getUnassociatedDevices()); } public void addListener( DeviceManagerListener listener ) { listeners.addListener( listener ); if (initialized) { listeners.dispatch( listener, LT_INITIALIZED, null ); } } public void removeListener( DeviceManagerListener listener ) { listeners.removeListener( listener ); } protected synchronized AEDiagnosticsLogger getLogger() { if ( logger == null ){ logger = AEDiagnostics.getLogger( LOGGER_NAME ); } return( logger ); } public void log( String s, Throwable e ) { AEDiagnosticsLogger diag_logger = getLogger(); diag_logger.log( s ); diag_logger.log( e ); } public void log( String s ) { AEDiagnosticsLogger diag_logger = getLogger(); diag_logger.log( s ); } public void generate( IndentWriter writer ) { writer.println( "Devices" ); try{ writer.indent(); DeviceImpl[] devices = getDevices(); for ( DeviceImpl device: devices ){ device.generate( writer ); } if ( transcode_manager != null ){ transcode_manager.generate( writer ); } }finally{ writer.exdent(); } } protected static class DeviceManufacturerImpl implements DeviceManufacturer { private String name; private List templates = new ArrayList(); protected DeviceManufacturerImpl( String _name ) { name = _name; } protected void addTemplate( DeviceTemplate t ) { templates.add( t ); } public String getName() { return( name ); } public DeviceTemplate[] getDeviceTemplates() { return( templates.toArray( new DeviceTemplate[ templates.size()] )); } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceiTunes.java0000644000175000017500000002760111244645452025326 0ustar adrianadrian/* * Created on Feb 10, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.AsyncDispatcher; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ipc.IPCInterface; import com.aelitis.azureus.core.devices.*; import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice; public class DeviceiTunes extends DeviceMediaRendererImpl implements DeviceMediaRenderer { private static final String UID = "a5d7869e-1ab9-6098-fef9-88476d988455"; private static final Object ERRROR_KEY_ITUNES = new Object(); private static final int INSTALL_CHECK_PERIOD = 60*1000; private static final int RUNNING_CHECK_PERIOD = 30*1000; private static final int DEVICE_CHECK_PERIOD = 10*1000; private static final int INSTALL_CHECK_TICKS = INSTALL_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD; private static final int RUNNING_CHECK_TICKS = RUNNING_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD; private static final int DEVICE_CHECK_TICKS = DEVICE_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD; private static final Object COPY_ERROR_KEY = new Object(); private PluginInterface itunes; private volatile boolean is_installed; private volatile boolean is_running; private boolean copy_outstanding; private boolean copy_outstanding_set; private AEThread2 copy_thread; private AESemaphore copy_sem = new AESemaphore( "Device:copy" ); private AsyncDispatcher async_dispatcher = new AsyncDispatcher( 5000 ); private long last_update_fail; private int consec_fails; protected DeviceiTunes( DeviceManagerImpl _manager, PluginInterface _itunes ) { super( _manager, UID, "iTunes", true ); itunes = _itunes; } protected DeviceiTunes( DeviceManagerImpl _manager, Map _map ) throws IOException { super( _manager, _map ); } protected boolean updateFrom( DeviceImpl _other, boolean _is_alive ) { if ( !super.updateFrom( _other, _is_alive )){ return( false ); } if ( !( _other instanceof DeviceiTunes )){ Debug.out( "Inconsistent" ); return( false ); } DeviceiTunes other = (DeviceiTunes)_other; itunes = other.itunes; return( true ); } protected void initialise() { super.initialise(); if ( getPersistentBooleanProperty( PP_COPY_OUTSTANDING, false )){ setCopyOutstanding(); } addListener( new TranscodeTargetListener() { public void fileAdded( TranscodeFile file ) { if ( file.isComplete() && !file.isCopiedToDevice()){ setCopyOutstanding(); } } public void fileChanged( TranscodeFile file, int type, Object data ) { if ( file.isComplete() && !file.isCopiedToDevice()){ setCopyOutstanding(); } } public void fileRemoved( TranscodeFile file ) { copy_sem.release(); } }); } protected String getDeviceClassification() { return( "apple." ); } public int getRendererSpecies() { return( RS_ITUNES ); } public InetAddress getAddress() { return( null ); } public boolean canRemove() { // no user-initiated removal, they need to uninstall the plugin return( false ); } public boolean isLivenessDetectable() { return( true ); } protected void destroy() { super.destroy(); } protected void updateStatus( int tick_count ) { super.updateStatus( tick_count ); updateStatusSupport( tick_count ); if ( is_installed && is_running ){ alive(); }else{ dead(); } } protected void updateStatusSupport( int tick_count ) { if ( itunes == null ){ return; } if ( !is_installed ){ if ( tick_count % INSTALL_CHECK_TICKS == 0 ){ updateiTunesStatus(); return; } } if ( !is_running ){ if ( tick_count % RUNNING_CHECK_TICKS == 0 ){ updateiTunesStatus(); return; } } if ( tick_count % DEVICE_CHECK_TICKS == 0 ){ updateiTunesStatus(); } } protected void updateiTunesStatus() { if ( getManager().isClosing()){ return; } IPCInterface ipc = itunes.getIPC(); try{ Map properties = (Map)ipc.invoke( "getProperties", new Object[]{} ); is_installed = (Boolean)properties.get( "installed" ); boolean was_running = is_running; is_running = (Boolean)properties.get( "running" ); if ( is_running && !was_running ){ copy_sem.release(); } if ( !( is_installed || is_running )){ last_update_fail = 0; } String info = null; if ( getCopyToDevicePending() > 0 ){ if ( !is_installed ){ info = MessageText.getString( "device.itunes.install" ); }else if ( !is_running ){ if ( !getAutoStartDevice()){ info = MessageText.getString( "device.itunes.start" ); } } } setInfo( ERRROR_KEY_ITUNES, info ); Throwable error = (Throwable)properties.get( "error" ); if ( error != null ){ throw( error ); } /* List> sources = (List>)properties.get( "sources" ); if ( sources != null ){ for ( Map source: sources ){ System.out.println( source ); } } */ last_update_fail = 0; consec_fails = 0; setError( ERRROR_KEY_ITUNES, null ); }catch( Throwable e ){ long now = SystemTime.getMonotonousTime(); consec_fails++; if ( last_update_fail == 0 ){ last_update_fail = now; }else if ( now - last_update_fail > 60*1000 && consec_fails >= 3 ){ setError( ERRROR_KEY_ITUNES, MessageText.getString( "device.itunes.install_problem" )); } log( "iTunes IPC failed", e ); } } public boolean canCopyToDevice() { return( true ); } public int getCopyToDevicePending() { synchronized( this ){ if ( !copy_outstanding ){ return( 0 ); } } TranscodeFileImpl[] files = getFiles(); int result = 0; for ( TranscodeFileImpl file: files ){ if ( file.isComplete() && !file.isCopiedToDevice()){ result++; } } return( result ); } protected void setCopyOutstanding() { synchronized( this ){ copy_outstanding_set = true; if ( copy_thread == null ){ copy_thread = new AEThread2( "Device:copier", true ) { public void run() { performCopy(); } }; copy_thread.start(); } copy_sem.release(); } } public boolean canAutoStartDevice() { return( true ); } public boolean getAutoStartDevice() { return( getPersistentBooleanProperty( PP_AUTO_START, PR_AUTO_START_DEFAULT )); } public void setAutoStartDevice( boolean auto ) { setPersistentBooleanProperty( PP_AUTO_START, auto ); if ( auto ){ copy_sem.release(); } } public boolean canAssociate() { return( false ); } public void associate( UnassociatedDevice assoc ) { } protected void performCopy() { synchronized( this ){ copy_outstanding = true; async_dispatcher.dispatch( new AERunnable() { public void runSupport() { setPersistentBooleanProperty( PP_COPY_OUTSTANDING, true ); } }); } while( true ){ if ( copy_sem.reserve( 60*1000 )){ while( copy_sem.reserveIfAvailable()); } boolean auto_start = getAutoStartDevice(); synchronized( this ){ if ( itunes == null || ( !is_running && !( auto_start && is_installed ))){ if ( !( copy_outstanding || copy_outstanding_set )){ copy_thread = null; break; } continue; } copy_outstanding_set = false; } TranscodeFileImpl[] files = getFiles(); List to_copy = new ArrayList(); boolean borked_exist = false; for ( TranscodeFileImpl file: files ){ if ( file.isComplete() && !file.isCopiedToDevice()){ if ( file.getCopyToDeviceFails() < 3 ){ to_copy.add( file ); }else{ borked_exist = true; } } } if ( borked_exist ){ setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copyfail2") ); } synchronized( this ){ if ( to_copy.size() == 0 && !copy_outstanding_set && !borked_exist ){ copy_outstanding = false; async_dispatcher.dispatch( new AERunnable() { public void runSupport() { setError( COPY_ERROR_KEY, null ); setPersistentBooleanProperty( PP_COPY_OUTSTANDING, false ); } }); copy_thread = null; break; } } for ( TranscodeFileImpl transcode_file: to_copy ){ try{ File file = transcode_file.getTargetFile().getFile(); try{ IPCInterface ipc = itunes.getIPC(); if ( !is_running ){ log( "Auto-starting iTunes" ); } Map result = (Map)ipc.invoke( "addFileToLibrary", new Object[]{ file } ); Throwable error = (Throwable)result.get( "error" ); if ( error != null ){ throw( error ); } is_running = true; log( "Added file '" + file + ": " + result ); transcode_file.setCopiedToDevice( true ); }catch( Throwable e ){ transcode_file.setCopyToDeviceFailed(); log( "Failed to copy file " + file, e ); } }catch( TranscodeException e ){ // file has been deleted } } } } public boolean isBrowsable() { return( false ); } public browseLocation[] getBrowseLocations() { return null; } protected void getDisplayProperties( List dp ) { super.getDisplayProperties( dp ); if ( itunes == null ){ addDP( dp, "devices.comp.missing", "" ); }else{ updateiTunesStatus(); addDP( dp, "devices.installed", is_installed ); addDP( dp, "MyTrackerView.status.started", is_running ); addDP( dp, "devices.copy.pending", copy_outstanding ); addDP( dp, "devices.auto.start", getAutoStartDevice()); } } public void generate( IndentWriter writer ) { super.generate( writer ); try{ writer.indent(); writer.println( "itunes=" + itunes + ", installed=" + is_installed + ", running=" + is_running + ", auto_start=" + getAutoStartDevice()); writer.println( "copy_os=" + copy_outstanding + ", last_fail=" + new SimpleDateFormat().format( new Date( last_update_fail ))); }finally{ writer.exdent(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceTivoManager.java0000644000175000017500000003157211266732670026300 0ustar adrianadrian/* * Created on Jul 24, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.util.*; import java.io.IOException; import java.net.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DelayedEvent; import org.gudy.azureus2.core3.util.RandomUtils; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.core3.util.TimerEventPeriodic; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.tracker.Tracker; import org.gudy.azureus2.plugins.tracker.web.TrackerWebContext; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageGenerator; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import com.aelitis.azureus.core.devices.Device; import com.aelitis.azureus.core.devices.DeviceManagerException; public class DeviceTivoManager { private static final String LF = "\n"; private static final int CONTROL_PORT = 2190; private DeviceManagerImpl device_manager; private PluginInterface plugin_interface; private boolean is_enabled; private String uid; private String server_name = "Vuze"; private Searcher current_search; private volatile boolean manager_destroyed; protected DeviceTivoManager( DeviceManagerImpl _dm ) { device_manager = _dm; } protected void startUp() { plugin_interface = PluginInitializer.getDefaultInterface(); is_enabled = COConfigurationManager.getBooleanParameter( "devices.tivo.enabled", true ); uid = COConfigurationManager.getStringParameter( "devices.tivo.uid", null ); if ( uid == null ){ byte[] bytes = new byte[8]; RandomUtils.nextBytes( bytes ); uid = Base32.encode( bytes ); COConfigurationManager.setParameter( "devices.tivo.uid", uid ); } // set up default server name try{ String cn = PlatformManagerFactory.getPlatformManager().getComputerName(); if ( cn != null && cn.length() > 0 ){ server_name += " on " + cn; } }catch( Throwable e ){ } // try to use the media server's name try{ server_name = (String)device_manager.getUPnPManager().getUPnPAVIPC().invoke( "getServiceName", new Object[]{}); }catch( Throwable e ){ } boolean found_tivo = false; for ( Device device: device_manager.getDevices()){ if ( device instanceof DeviceTivo ){ found_tivo = true; break; } } if ( found_tivo || device_manager.getAutoSearch()){ search( found_tivo, false ); } } protected boolean isEnabled() { return( is_enabled ); } protected void setEnabled( boolean enabled ) { COConfigurationManager.setParameter( "devices.tivo.enabled", enabled ); if ( enabled ){ search( false, true ); }else{ for ( Device device: device_manager.getDevices()){ if ( device instanceof DeviceTivo ){ device.remove(); } } } } protected void search() { search( false, false ); } protected void search( boolean persistent, boolean async ) { try{ synchronized( this ){ if ( current_search == null ){ current_search = new Searcher( persistent, async ); }else{ if ( !current_search.wakeup()){ current_search = new Searcher( persistent, async ); } } } }catch( Throwable e ){ Debug.out( e ); } } protected byte[] encodeBeacon( boolean is_broadcast, int my_port ) throws IOException { String beacon = "tivoconnect=1" + LF + "swversion=1" + LF + "method=" + (is_broadcast?"broadcast":"connected") + LF + "identity=" + uid + LF + "machine=" + server_name + LF + "platform=pc" + LF + "services=TiVoMediaServer:" + my_port + "/http"; return( beacon.getBytes( "ISO-8859-1" )); } protected Map decodeBeacon( byte[] buffer, int length ) throws IOException { String str = new String( buffer, 0, length, "ISO-8859-1" ); String[] lines = str.split( LF ); Map map = new HashMap(); for (String line:lines ){ int pos = line.indexOf( '=' ); if ( pos > 0 ){ map.put( line.substring( 0, pos ).trim().toLowerCase(), line.substring( pos+ 1 ).trim()); } } return( map ); } protected boolean receiveBeacon( InetAddress sender, byte[] buffer, int length ) { if ( is_enabled ){ try{ Map map = decodeBeacon( buffer, length ); String id = map.get( "identity" ); if ( id == null || id.equals( uid )){ return( false ); } String platform = map.get( "platform" ); if ( platform != null && platform.toLowerCase().startsWith( "tcd/")){ String classification = "tivo." + platform.substring( 4 ).toLowerCase(); foundTiVo( sender, id, classification, (String)map.get( "machine" )); return( true ); } }catch( Throwable e ){ log( "Failed to decode beacon", e ); } } return( false ); } protected DeviceTivo foundTiVo( InetAddress address, String uid, String classification, String machine ) { uid = "tivo:" + uid; DeviceImpl[] devices = device_manager.getDevices(); for ( DeviceImpl device: devices ){ if ( device instanceof DeviceTivo ){ DeviceTivo tivo = (DeviceTivo)device; if ( device.getID().equals( uid )){ tivo.found( this, address, server_name, machine ); return( tivo ); } } } DeviceTivo new_device = new DeviceTivo( device_manager, uid, classification ); DeviceTivo result = (DeviceTivo)device_manager.addDevice( new_device ); // possible race here so handle case where device already present if ( result == new_device ){ new_device.found( this, address, server_name, machine ); } return( result ); } protected void log( String str ) { if ( device_manager == null ){ System.out.println( str ); }else{ device_manager.log( "TiVo: " + str ); } } protected void log( String str, Throwable e ) { if ( device_manager == null ){ System.out.println( str ); e.printStackTrace(); }else{ device_manager.log( "TiVo: " + str, e ); } } protected class Searcher { private static final int LIFE_MILLIS = 10*1000; private long start = SystemTime.getMonotonousTime(); private int tcp_port; private DatagramSocket control_socket; private TrackerWebContext twc; private TimerEventPeriodic timer_event; private volatile boolean persistent; private volatile boolean search_destroyed; protected Searcher( boolean _persistent, boolean _async ) throws DeviceManagerException { try{ int last_port = COConfigurationManager.getIntParameter( "devices.tivo.net.tcp.port", 0 ); if ( last_port > 0 ){ try{ ServerSocket ss = new ServerSocket( last_port ); ss.setReuseAddress( true ); ss.close(); }catch( Throwable e ){ last_port = 0; } } twc = plugin_interface.getTracker().createWebContext( last_port, Tracker.PR_HTTP ); tcp_port = twc.getURLs()[0].getPort(); COConfigurationManager.setParameter( "devices.tivo.net.tcp.port", tcp_port ); twc.addPageGenerator( new TrackerWebPageGenerator() { public boolean generate( TrackerWebPageRequest request, TrackerWebPageResponse response ) throws IOException { String id = (String)request.getHeaders().get( "tsn" ); if ( id == null ){ id = (String)request.getHeaders().get( "tivo_tcd_id" ); } if ( id != null && is_enabled ){ persistent = true; DeviceTivo tivo = foundTiVo( request.getClientAddress2().getAddress(), id, "tivo.series3", null ); return( tivo.generate( request, response )); } return( false ); } }); control_socket = new DatagramSocket( null ); control_socket.setReuseAddress( true ); try{ control_socket.setSoTimeout( 60*1000 ); }catch( Throwable e ){ } control_socket.bind( new InetSocketAddress((InetAddress)null, CONTROL_PORT )); timer_event = SimpleTimer.addPeriodicEvent( "Tivo:Beacon", 60*1000, new TimerEventPerformer() { public void perform( TimerEvent event ) { if ( !( manager_destroyed || search_destroyed )){ sendBeacon(); } // see if time to auto-shutdown searching if ( !persistent ){ synchronized( DeviceTivoManager.this ){ if ( SystemTime.getMonotonousTime() - start >= LIFE_MILLIS ){ log( "Terminating search, no devices found" ); current_search = null; destroy(); } } } } }); final AESemaphore start_sem = new AESemaphore( "TiVo:CtrlListener" ); new AEThread2( "TiVo:CtrlListener", true ) { public void run() { start_sem.release(); long successful_accepts = 0; long failed_accepts = 0; while( !( manager_destroyed || search_destroyed )){ try{ byte[] buf = new byte[8192]; DatagramPacket packet = new DatagramPacket(buf, buf.length ); control_socket.receive( packet ); successful_accepts++; failed_accepts = 0; if ( receiveBeacon( packet.getAddress(), packet.getData(), packet.getLength())){ persistent = true; } }catch( SocketTimeoutException e ){ }catch( Throwable e ){ failed_accepts++; log( "UDP receive on port " + CONTROL_PORT + " failed", e ); if (( failed_accepts > 100 && successful_accepts == 0 ) || failed_accepts > 1000 ){ log( " too many failures, abandoning" ); break; } } } } }.start(); if ( _async ){ new DelayedEvent( "search:delay", 5000, new AERunnable() { public void runSupport() { sendBeacon(); } }); }else{ start_sem.reserve( 5000 ); sendBeacon(); } log( "Initiated device search" ); }catch( Throwable e ){ log( "Failed to initialise search", e ); destroy(); throw( new DeviceManagerException( "Creation failed",e )); } } protected void sendBeacon() { if ( is_enabled ){ try{ byte[] bytes = encodeBeacon( true, tcp_port ); control_socket.send( new DatagramPacket( bytes, bytes.length, InetAddress.getByName( "255.255.255.255" ), CONTROL_PORT )); }catch( Throwable e ){ log( "Failed to send beacon", e ); } } } protected boolean wakeup() { synchronized( DeviceTivoManager.this ){ if ( search_destroyed ){ return( false ); } start = SystemTime.getMonotonousTime(); } sendBeacon(); return( true ); } protected void destroy() { search_destroyed = true; if ( twc != null ){ twc.destroy(); twc = null; } if ( timer_event != null ){ timer_event.cancel(); timer_event = null; } if ( control_socket != null ){ try{ control_socket.close(); }catch( Throwable e ){ } control_socket = null; } } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/TranscodePipeStreamSource.java0000644000175000017500000000404311160046056030017 0ustar adrianadrian/* * Created on Feb 9, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.IOException; import java.net.Socket; public class TranscodePipeStreamSource extends TranscodePipe { private int source_port; protected TranscodePipeStreamSource( int _source_port ) throws IOException { super( null ); source_port = _source_port; } protected void handleSocket( Socket socket1 ) { synchronized( this ){ if ( destroyed ){ try{ socket1.close(); }catch( Throwable e ){ } return; } sockets.add( socket1 ); } try{ Socket socket2 = new Socket( "127.0.0.1", source_port ); synchronized( this ){ if ( destroyed ){ try{ socket1.close(); }catch( Throwable e ){ } try{ socket2.close(); }catch( Throwable e ){ } sockets.remove( socket1 ); return; } sockets.add( socket2 ); } handlePipe( socket1.getInputStream(), socket2.getOutputStream()); handlePipe( socket2.getInputStream(), socket1.getOutputStream()); }catch( Throwable e ){ try{ socket1.close(); }catch( Throwable f ){ } synchronized( this ){ sockets.remove( socket1 ); } } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/TranscodeProviderVuze.java0000644000175000017500000003667711231244042027245 0ustar adrianadrian/* * Created on Feb 5, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.File; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.ipc.IPCInterface; import com.aelitis.azureus.core.devices.TranscodeProfile; import com.aelitis.azureus.core.devices.TranscodeProvider; import com.aelitis.azureus.core.devices.TranscodeProviderAdapter; import com.aelitis.azureus.core.devices.TranscodeException; import com.aelitis.azureus.core.devices.TranscodeProviderAnalysis; import com.aelitis.azureus.core.devices.TranscodeProviderJob; public class TranscodeProviderVuze implements TranscodeProvider { private TranscodeManagerImpl manager; private PluginInterface plugin_interface; private volatile TranscodeProfile[] profiles; protected TranscodeProviderVuze( TranscodeManagerImpl _manager, PluginInterface _plugin_interface ) { manager = _manager; plugin_interface = _plugin_interface; } protected void update( PluginInterface pi ) { plugin_interface = pi; } public String getName() { return( plugin_interface.getPluginName() + ": version=" + plugin_interface.getPluginVersion()); } public TranscodeProfile[] getProfiles() { if ( profiles != null ){ return( profiles ); } try{ Map> profiles_map = (Map>)plugin_interface.getIPC().invoke( "getProfiles", new Object[]{} ); TranscodeProfile[] res = new TranscodeProfile[profiles_map.size()]; int index = 0; for ( Map.Entry> entry : profiles_map.entrySet()){ res[ index++] = new TranscodeProfileImpl( this, "vuzexcode:" + entry.getKey(), entry.getKey(), entry.getValue()); } profiles = res; return( res ); }catch( Throwable e ){ e.printStackTrace(); return( new TranscodeProfile[0] ); } } public TranscodeProfile getProfile( String UID ) { TranscodeProfile[] profiles = getProfiles(); for ( TranscodeProfile profile: profiles ){ if ( profile.getUID().equals( UID )){ return( profile ); } } return( null ); } public TranscodeProviderAnalysis analyse( final TranscodeProviderAdapter _adapter, DiskManagerFileInfo input, TranscodeProfile profile ) throws TranscodeException { try{ URL source_url = null; File source_file = null; long input_length = input.getLength(); if ( input_length > 0 && input_length == input.getDownloaded()){ File file = input.getFile(); if ( file.exists() && file.length() == input_length ){ source_file = file; } } TranscodePipe pipe = null; if ( source_file == null ){ PluginInterface av_pi = plugin_interface.getPluginManager().getPluginInterfaceByID( "azupnpav" ); if ( av_pi == null ){ throw( new TranscodeException( "Media Server plugin not found" )); } IPCInterface av_ipc = av_pi.getIPC(); String url_str = (String)av_ipc.invoke( "getContentURL", new Object[]{ input }); if ( url_str != null && url_str.length() > 0 ){ source_url = new URL( url_str ); pipe = new TranscodePipeStreamSource( source_url.getPort()); source_url = UrlUtils.setPort( source_url, pipe.getPort()); } } if ( source_file == null && source_url == null ){ throw( new TranscodeException( "File doesn't exist" )); } final TranscodePipe f_pipe = pipe; try{ final IPCInterface ipc = plugin_interface.getIPC(); final Object analysis_context; if ( source_url != null ){ analysis_context = ipc.invoke( "analyseContent", new Object[]{ source_url, profile.getName() }); }else{ analysis_context = ipc.invoke( "analyseContent", new Object[]{ source_file, profile.getName() }); } final Map result = new HashMap(); final TranscodeProviderAnalysisImpl analysis = new TranscodeProviderAnalysisImpl() { public void cancel() { try{ ipc.invoke( "cancelAnalysis", new Object[]{ analysis_context }); }catch( Throwable e ){ Debug.printStackTrace( e ); } } public boolean getBooleanProperty( int property ) { if ( property == PT_TRANSCODE_REQUIRED ){ return( getBooleanProperty( "xcode_required", true )); }else{ Debug.out( "Unknown property: " + property ); return( false ); } } public void setBooleanProperty( int property, boolean value ) { if ( property == PT_FORCE_TRANSCODE ){ result.put( "force_xcode", value ); }else{ Debug.out( "Unknown property: " + property ); } } public long getLongProperty( int property ) { if ( property == PT_DURATION_MILLIS ){ return( getLongProperty( "duration_millis", 0 )); }else if ( property == PT_VIDEO_WIDTH ){ return( getLongProperty( "video_width", 0 )); }else if ( property == PT_VIDEO_HEIGHT ){ return( getLongProperty( "video_height", 0 )); }else{ Debug.out( "Unknown property: " + property ); return( 0 ); } } protected boolean getBooleanProperty( String name, boolean def ) { Boolean b = (Boolean)result.get( name ); if ( b != null ){ return( b ); } return( def ); } protected long getLongProperty( String name, long def ) { Long l = (Long)result.get( name ); if ( l != null ){ return( l ); } return( def ); } public Map getResult() { return( result ); } }; new AEThread2( "analysisStatus", true ) { public void run() { try{ while( true ){ try{ Map status = (Map)ipc.invoke( "getAnalysisStatus", new Object[]{ analysis_context }); long state = (Long)status.get( "state" ); if ( state == 0 ){ // running }else if ( state == 1 ){ _adapter.failed( new TranscodeException( "Analysis cancelled" )); return; }else if ( state == 2 ){ _adapter.failed( new TranscodeException( "Analysis failed", (Throwable)status.get( "error" ))); return; }else{ result.putAll((Map)status.get( "result" )); _adapter.complete(); return; } }catch( Throwable e ){ _adapter.failed( new TranscodeException( "Failed to get status", e )); } } }finally{ if ( f_pipe != null ){ f_pipe.destroy(); } } } }.start(); return( analysis ); }catch( Throwable e ){ if ( pipe != null ){ pipe.destroy(); } throw( e ); } }catch( TranscodeException e ){ throw( e ); }catch( Throwable e ){ throw( new TranscodeException( "analysis failed", e )); } } public TranscodeProviderJob transcode( final TranscodeProviderAdapter _adapter, TranscodeProviderAnalysis analysis, boolean direct_input, DiskManagerFileInfo input, TranscodeProfile profile, URL output ) throws TranscodeException { try{ PluginInterface av_pi = plugin_interface.getPluginManager().getPluginInterfaceByID( "azupnpav" ); if ( av_pi == null ){ throw( new TranscodeException( "Media Server plugin not found" )); } final TranscodeProviderJob[] xcode_job = { null }; URL source_url = null; TranscodePipe pipe = null; if ( direct_input ){ if ( input.getDownloaded() == input.getLength()){ File file = input.getFile(); if ( file.exists() && file.length() == input.getLength()){ source_url = file.toURI().toURL(); } } if ( source_url == null ){ manager.log( "Failed to use direct input as source file doesn't exist/incomplete" ); } } if ( source_url == null ){ IPCInterface av_ipc = av_pi.getIPC(); String url_str = (String)av_ipc.invoke( "getContentURL", new Object[]{ input }); if ( url_str == null || url_str.length() == 0 ){ // see if we can use the file directly File source_file = input.getFile(); if ( source_file.exists()){ pipe = new TranscodePipeFileSource( source_file, new TranscodePipe.errorListener() { public void error( Throwable e ) { _adapter.failed( new TranscodeException( "File access error", e )); if ( xcode_job[0] != null ){ xcode_job[0].cancel(); } } }); source_url = new URL( "http://127.0.0.1:" + pipe.getPort() + "/" ); }else{ throw( new TranscodeException( "Source file doesn't exist" )); } }else{ source_url = new URL( url_str ); pipe = new TranscodePipeStreamSource( source_url.getPort()); source_url = UrlUtils.setPort( source_url, pipe.getPort()); } } final TranscodePipe f_pipe = pipe; try{ final IPCInterface ipc = plugin_interface.getIPC(); final Object context; final TranscodeProviderAdapter adapter; if ( output.getProtocol().equals( "tcp" )){ adapter = _adapter; context = ipc.invoke( "transcodeToTCP", new Object[]{ ((TranscodeProviderAnalysisImpl)analysis).getResult(), source_url, profile.getName(), output.getPort() }); }else{ final File file = new File( output.toURI()); adapter = new TranscodeProviderAdapter() { public void updateProgress( int percent, int eta_secs, int width, int height ) { _adapter.updateProgress( percent, eta_secs, width, height ); } public void streamStats( long connect_rate, long write_speed ) { _adapter.streamStats(connect_rate, write_speed); } public void failed( TranscodeException error ) { try{ file.delete(); }finally{ _adapter.failed( error ); } } public void complete() { _adapter.complete(); } }; context = ipc.invoke( "transcodeToFile", new Object[]{ ((TranscodeProviderAnalysisImpl)analysis).getResult(), source_url, profile.getName(), file }); } new AEThread2( "xcodeStatus", true ) { public void run() { try{ boolean in_progress = true; while( in_progress ){ in_progress = false; if ( f_pipe != null ){ adapter.streamStats( f_pipe.getConnectionRate(), f_pipe.getWriteSpeed()); } try{ Map status = (Map)ipc.invoke( "getTranscodeStatus", new Object[]{ context }); long state = (Long)status.get( "state" ); if ( state == 0 ){ int percent = (Integer)status.get( "percent" ); Integer i_eta = (Integer)status.get( "eta_secs" ); int eta = i_eta==null?-1:i_eta; Integer i_width = (Integer)status.get( "new_width" ); int width = i_width==null?0:i_width; Integer i_height = (Integer)status.get( "new_height" ); int height = i_height==null?0:i_height; adapter.updateProgress( percent, eta, width, height ); if ( percent == 100 ){ adapter.complete(); }else{ in_progress = true; Thread.sleep(1000); } }else if ( state == 1 ){ adapter.failed( new TranscodeException( "Transcode cancelled" )); }else{ adapter.failed( new TranscodeException( "Transcode failed", (Throwable)status.get( "error" ))); } }catch( Throwable e ){ adapter.failed( new TranscodeException( "Failed to get status", e )); } } }finally{ if ( f_pipe != null ){ f_pipe.destroy(); } } } }.start(); xcode_job[0] = new TranscodeProviderJob() { public void pause() { if ( f_pipe != null ){ f_pipe.pause(); } } public void resume() { if ( f_pipe != null ){ f_pipe.resume(); } } public void cancel() { try{ ipc.invoke( "cancelTranscode", new Object[]{ context }); }catch( Throwable e ){ Debug.printStackTrace( e ); } } public void setMaxBytesPerSecond( int max ) { if ( f_pipe != null ){ f_pipe.setMaxBytesPerSecond( max ); } } }; return( xcode_job[0] ); }catch( Throwable e ){ if ( pipe != null ){ pipe.destroy(); } throw( e ); } }catch( TranscodeException e ){ throw( e ); }catch( Throwable e ){ throw( new TranscodeException( "transcode failed", e )); } } public File getAssetDirectory() { File file = plugin_interface.getPluginconfig().getPluginUserFile( "assets" ); if ( !file.exists()){ file.mkdirs(); } return( file ); } protected void destroy() { // TODO } protected interface TranscodeProviderAnalysisImpl extends TranscodeProviderAnalysis { public Map getResult(); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/TranscodePipeFileSource.java0000644000175000017500000001535111160046056027447 0ustar adrianadrian/* * Created on Feb 9, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; import java.net.Socket; import java.util.*; public class TranscodePipeFileSource extends TranscodePipe { private static final String NL = "\r\n"; private File source_file; private RandomAccessFile raf; private int raf_count; protected TranscodePipeFileSource( File _source_file, errorListener _error_listener ) throws IOException { super( _error_listener ); source_file = _source_file; } protected void handleSocket( Socket socket ) { synchronized( this ){ if ( destroyed ){ try{ socket.close(); }catch( Throwable e ){ } return; } sockets.add( socket ); } try{ String command = null; Map headers = new HashMap(); InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); while( true ){ String line = ""; while( !line.endsWith( NL )){ byte[] buffer = new byte[1]; is.read( buffer ); line += new String( buffer ); } line = line.trim(); if ( line.length() == 0 ){ break; } if ( command == null ){ command = line; }else{ int pos = line.indexOf(':'); if ( pos == -1 ){ return; } String lhs = line.substring(0,pos).trim().toLowerCase(); String rhs = line.substring(pos+1).trim(); headers.put( lhs, rhs ); } } boolean head = false; //System.out.println( command + ": " + headers ); if ( command.startsWith( "GET " )){ }else if ( command.startsWith( "HEAD " )){ head = true; }else{ throw( new IOException( "unsupported method '" + command + "'" )); } long file_length = source_file.length(); if ( head ){ write( os, "HTTP/1.1 200 OK" + NL ); write( os, "Server: Azureus Media Server 1.0" + NL ); write( os, "Accept-Ranges: bytes" + NL ); write( os, "Content-Length: " + file_length + NL ); write( os, "Content-Range: 0-" + (file_length-1) + "/" + file_length + NL ); os.flush(); }else{ String ranges = (String)headers.get( "range" ); long request_start = 0; long request_length = 0; boolean request_ok = false; if ( ranges == null ){ write( os, "HTTP/1.1 200 OK" + NL ); write( os, "Server: Azureus Media Server 1.0" + NL ); write( os, "Connection: close" + NL ); write( os, "Accept-Ranges: bytes" + NL ); write( os, "Content-Range: 0-" + (file_length-1) + "/" + file_length + NL ); write( os, "Content-Length: " + file_length + NL + NL ); request_length = file_length; request_ok = true; }else{ ranges = ranges.toLowerCase(); if ( !ranges.startsWith("bytes=")){ throw( new IOException( "invalid range: " + ranges )); } ranges = ranges.substring( 6 ); StringTokenizer tok = new StringTokenizer( ranges, "," ); if ( tok.countTokens() != 1 ){ throw( new IOException( "invalid range - only single supported: " + ranges )); } String range = tok.nextToken(); int pos = range.indexOf('-'); long start; long end; if ( pos < range.length()-1 ){ end = Long.parseLong( range.substring(pos+1)); }else{ end = file_length-1; } if ( pos > 0 ){ start = Long.parseLong( range.substring(0,pos)); }else{ // -500 = last 500 bytes of file start = file_length-end; end = file_length-1; } request_length = ( end - start ) + 1; // prevent seeking too far if ( request_length < 0 ){ write( os, "HTTP/1.1 416 Requested Range Not Satisfiable" + NL + NL ); }else{ request_start = start; write( os, "HTTP/1.1 206 Partial content" + NL ); write( os, "Server: Azureus Media Server 1.0" + NL ); write( os, "Connection: close" + NL ); write( os, "Content-Range: bytes " + start + "-" + end + "/" + file_length + NL ); write( os, "Content-Length: " + request_length + NL + NL ); request_ok = true; } } os.flush(); if ( request_ok ){ handleRAF( os, request_start, request_length ); } } synchronized( this ){ if ( destroyed ){ try{ socket.close(); }catch( Throwable e ){ } try{ is.close(); }catch( Throwable e ){ } sockets.remove( socket ); return; } } }catch( Throwable e ){ try{ socket.close(); }catch( Throwable f ){ } synchronized( this ){ sockets.remove( socket ); } } } protected void write( OutputStream os, String str ) throws IOException { os.write( str.getBytes()); } @Override protected RandomAccessFile reserveRAF() throws IOException { synchronized( this ){ if ( destroyed ){ throw( new IOException( "destroyed" )); } if ( raf == null ){ raf = new RandomAccessFile( source_file, "r" ); } raf_count++; return( raf ); } } @Override protected void releaseRAF( RandomAccessFile _raf ) { synchronized( this ){ raf_count--; if ( raf_count == 0 ){ try{ raf.close(); }catch( Throwable e ){ } raf = null; } } } protected boolean destroy() { if ( super.destroy()){ if ( raf != null ){ try{ raf.close(); }catch( Throwable e ){ } raf = null; } return( true ); } return( false ); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/TranscodeQueueImpl.java0000644000175000017500000007065211252045030026475 0ustar adrianadrian/* * Created on Feb 6, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.net.URLConnection; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DelayedEvent; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.ipc.IPCInterface; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; import com.aelitis.azureus.core.devices.*; import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.util.average.Average; import com.aelitis.azureus.core.util.average.AverageFactory; public class TranscodeQueueImpl implements TranscodeQueue { private static final String CONFIG_FILE = "xcodejobs.config"; private static final Object KEY_XCODE_ERROR = new Object(); private TranscodeManagerImpl manager; private List queue = new ArrayList(); private AESemaphore queue_sem = new AESemaphore( "XcodeQ" ); private AEThread2 queue_thread; private volatile TranscodeJobImpl current_job; private CopyOnWriteList listeners = new CopyOnWriteList(); private volatile boolean paused; private volatile int max_bytes_per_sec; private volatile boolean config_dirty; protected TranscodeQueueImpl( TranscodeManagerImpl _manager ) { manager = _manager; } protected void initialise() { loadConfig(); COConfigurationManager.addAndFireParameterListeners( new String[]{ "xcode.queue.paused", "xcode.queue.maxbps", }, new ParameterListener() { public void parameterChanged( String name ) { paused = COConfigurationManager.getBooleanParameter( "xcode.queue.paused", false ); max_bytes_per_sec = COConfigurationManager.getIntParameter( "xcode.queue.maxbps", 0 ); } }); DelayedTask delayed_task = UtilitiesImpl.addDelayedTask( "TranscodeQueue:schedule", new Runnable() { public void run() { schedule(); } }); delayed_task.queue(); } protected boolean process( final TranscodeJobImpl job ) { TranscodePipe pipe = null; current_job = job; DeviceImpl device = job.getDevice(); device.setTranscoding( true ); try{ job.starts(); TranscodeProvider provider = job.getProfile().getProvider(); final Throwable[] error = { null }; TranscodeProfile profile = job.getProfile(); final AESemaphore analysis_sem = new AESemaphore( "analysis:proc" ); TranscodeProviderAdapter analysis_adapter = new TranscodeProviderAdapter() { public void updateProgress( int percent, int eta_secs, int width, int height ) { } public void streamStats( long connect_rate, long write_speed ) { } public void failed( TranscodeException e ) { error[0] = e; analysis_sem.release(); } public void complete() { analysis_sem.release(); } }; final TranscodeProviderAnalysis provider_analysis = provider.analyse( analysis_adapter, job.getFile(), profile ); TranscodeQueueListener analysis_q_listener = new TranscodeQueueListener() { public void jobAdded( TranscodeJob job ) { } public void jobChanged( TranscodeJob changed_job ) { if ( changed_job == job ){ int state = job.getState(); if ( state == TranscodeJob.ST_CANCELLED || state == TranscodeJob.ST_STOPPED ){ provider_analysis.cancel(); } } } public void jobRemoved( TranscodeJob removed_job ) { if ( removed_job == job ){ provider_analysis.cancel(); } } }; try{ addListener( analysis_q_listener ); analysis_sem.reserve(); }finally{ removeListener( analysis_q_listener ); } if ( error[0] != null ){ throw( error[0] ); } boolean xcode_required = provider_analysis.getBooleanProperty( TranscodeProviderAnalysis.PT_TRANSCODE_REQUIRED ); final TranscodeFileImpl transcode_file = job.getTranscodeFile(); transcode_file.update( provider_analysis ); int tt_req; if ( job.isStream()){ // already advertised as a transcoded asset so no option not to // transcode (as name/format would change if decided not to transcode and then // this would confuse the clients) tt_req = TranscodeTarget.TRANSCODE_ALWAYS; }else{ tt_req = job.getTranscodeRequirement(); // audio hack for PSP audio if ( device instanceof TranscodeTarget ){ if ( provider_analysis.getLongProperty( TranscodeProviderAnalysis.PT_VIDEO_HEIGHT ) == 0 ){ if (((TranscodeTarget)device).isAudioCompatible( transcode_file )){ tt_req = TranscodeTarget.TRANSCODE_NEVER; } } } } if ( tt_req == TranscodeTarget.TRANSCODE_NEVER ){ xcode_required = false; }else if ( tt_req == TranscodeTarget.TRANSCODE_ALWAYS ){ xcode_required = true; provider_analysis.setBooleanProperty( TranscodeProviderAnalysis.PT_FORCE_TRANSCODE, true ); } if ( xcode_required ){ final AESemaphore xcode_sem = new AESemaphore( "xcode:proc" ); final TranscodeProviderJob[] provider_job = { null }; TranscodeProviderAdapter xcode_adapter = new TranscodeProviderAdapter() { private boolean resolution_updated; private final int ETA_AVERAGE_SIZE = 10; private int last_eta; private int eta_samples; private Average eta_average = AverageFactory.MovingAverage(ETA_AVERAGE_SIZE); private int last_percent; public void updateProgress( int percent, int eta_secs, int new_width, int new_height ) { last_eta = eta_secs; last_percent = percent; TranscodeProviderJob prov_job = provider_job[0]; if ( prov_job == null ){ return; } int job_state = job.getState(); if ( job_state == TranscodeJob.ST_CANCELLED || job_state == TranscodeJob.ST_REMOVED ){ prov_job.cancel(); }else if ( paused || job_state == TranscodeJob.ST_PAUSED ){ prov_job.pause(); }else{ if ( job_state == TranscodeJob.ST_RUNNING ){ prov_job.resume(); } job.updateProgress( percent, eta_secs ); prov_job.setMaxBytesPerSecond( max_bytes_per_sec ); if ( !resolution_updated ){ if ( new_width > 0 && new_height > 0 ){ transcode_file.setResolution( new_width, new_height ); resolution_updated = true; } } } } public void streamStats( long connect_rate, long write_speed ) { // problem on OSX with some files thrashing the indirect piped input // and eventually failing - try and spot this behaviour and revert // to direct input if needed if ( Constants.isOSX && job.canUseDirectInput() && job.getAutoRetryCount() == 0 ){ if ( connect_rate > 5 && last_percent < 100 ){ long eta = (long)eta_average.update(last_eta ); eta_samples++; if ( eta_samples >= ETA_AVERAGE_SIZE ){ long total_time = (eta*100 )/(100-last_percent); long total_write = total_time*write_speed; DiskManagerFileInfo file = job.getFile(); long length = file.getLength(); if ( length > 0 ){ double over_write = ((double)total_write)/length; if ( over_write > 5.0 ){ failed( new TranscodeException( "Overwrite limit exceeded, abandoning transcode" )); provider_job[0].cancel(); } } } }else{ eta_samples = 0; } } } public void failed( TranscodeException e ) { if ( error[0] == null ){ error[0] = e; } xcode_sem.release(); } public void complete() { xcode_sem.release(); } }; boolean direct_input = job.useDirectInput(); if ( job.isStream()){ /* provider_job[0] = provider.transcode( adapter, job.getFile(), profile, new File( "C:\\temp\\arse").toURI().toURL()); */ pipe = new TranscodePipeStreamSource2( new TranscodePipeStreamSource2.streamListener() { public void gotStream( InputStream is ) { job.setStream( is ); } }); provider_job[0] = provider.transcode( xcode_adapter, provider_analysis, direct_input, job.getFile(), profile, new URL( "tcp://127.0.0.1:" + pipe.getPort())); }else{ File output_file = transcode_file.getCacheFile(); provider_job[0] = provider.transcode( xcode_adapter, provider_analysis, direct_input, job.getFile(), profile, output_file.toURI().toURL()); } provider_job[0].setMaxBytesPerSecond( max_bytes_per_sec ); TranscodeQueueListener listener = new TranscodeQueueListener() { public void jobAdded( TranscodeJob job ) { } public void jobChanged( TranscodeJob changed_job ) { if ( changed_job == job ){ int state = job.getState(); if ( state == TranscodeJob.ST_PAUSED ){ provider_job[0].pause(); }else if ( state == TranscodeJob.ST_RUNNING ){ provider_job[0].resume(); }else if ( state == TranscodeJob.ST_CANCELLED || state == TranscodeJob.ST_STOPPED ){ provider_job[0].cancel(); } } } public void jobRemoved( TranscodeJob removed_job ) { if ( removed_job == job ){ provider_job[0].cancel(); } } }; try{ addListener( listener ); xcode_sem.reserve(); }finally{ removeListener( listener ); } if ( error[0] != null ){ throw( error[0] ); } }else{ // no transcode required... DiskManagerFileInfo source = job.getFile(); transcode_file.setTranscodeRequired( false ); if ( job.isStream()){ PluginInterface av_pi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByID( "azupnpav" ); if ( av_pi == null ){ throw( new TranscodeException( "Media Server plugin not found" )); } IPCInterface av_ipc = av_pi.getIPC(); String url_str = (String)av_ipc.invoke( "getContentURL", new Object[]{ source }); if ( url_str == null || url_str.length() == 0 ){ // see if we can use the file directly File source_file = source.getFile(); if ( source_file.exists()){ job.setStream( new BufferedInputStream( new FileInputStream( source_file ))); }else{ throw( new TranscodeException( "No UPnPAV URL and file doesn't exist" )); } }else{ URL source_url = new URL( url_str ); job.setStream( source_url.openConnection().getInputStream()); } }else{ if ( device.getAlwaysCacheFiles()){ PluginInterface av_pi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByID( "azupnpav" ); if ( av_pi == null ){ throw( new TranscodeException( "Media Server plugin not found" )); } IPCInterface av_ipc = av_pi.getIPC(); String url_str = (String)av_ipc.invoke( "getContentURL", new Object[]{ source }); InputStream is; long length; if ( url_str == null || url_str.length() == 0 ){ // see if we can use the file directly File source_file = source.getFile(); if ( source_file.exists()){ is = new BufferedInputStream( new FileInputStream( source_file )); length = source_file.length(); }else{ throw( new TranscodeException( "No UPnPAV URL and file doesn't exist" )); } }else{ URL source_url = new URL( url_str ); URLConnection connection = source_url.openConnection(); is = source_url.openConnection().getInputStream(); String s = connection.getHeaderField( "content-length" ); if ( s != null ){ length = Long.parseLong( s ); }else{ length = -1; } } OutputStream os = null; final boolean[] cancel_copy = { false }; TranscodeQueueListener copy_listener = new TranscodeQueueListener() { public void jobAdded( TranscodeJob job ) { } public void jobChanged( TranscodeJob changed_job ) { if ( changed_job == job ){ int state = job.getState(); if ( state == TranscodeJob.ST_PAUSED ){ }else if ( state == TranscodeJob.ST_RUNNING ){ }else if ( state == TranscodeJob.ST_CANCELLED || state == TranscodeJob.ST_STOPPED ){ cancel_copy[0] = true; } } } public void jobRemoved( TranscodeJob removed_job ) { if ( removed_job == job ){ cancel_copy[0] = true; } } }; try{ addListener( copy_listener ); os = new FileOutputStream( transcode_file.getCacheFile()); long total_copied = 0; byte[] buffer = new byte[128*1024]; while( true ){ if ( cancel_copy[0] ){ throw( new TranscodeException( "Copy cancelled" )); } int len = is.read( buffer ); if ( len <= 0 ){ break; } os.write( buffer, 0, len ); total_copied += len; if ( length > 0 ){ job.updateProgress((int)( total_copied*100/length ), -1 ); } total_copied += len; } }finally{ try{ is.close(); }catch( Throwable e ){ Debug.out( e ); } try{ if ( os != null ){ os.close(); } }catch( Throwable e ){ Debug.out( e ); } removeListener( copy_listener ); } } } } job.complete(); return( true ); }catch( Throwable e ){ job.failed( e ); if ( !job.isStream() && job.getAutoRetryCount() == 0 && job.canUseDirectInput() && !job.useDirectInput()){ log( "Auto-retrying transcode with direct input" ); job.setUseDirectInput(); job.setAutoRetry( true ); queue_sem.release(); } return( false ); }finally{ if ( pipe != null ){ pipe.destroy(); } device.setTranscoding( false ); current_job = null; } } protected void schedule() { synchronized( this ){ if ( queue.size() > 0 && queue_thread == null ){ queue_thread = new AEThread2( "XcodeQ", true ) { public void run() { try{ while( true ){ checkJobStatus(); boolean got = queue_sem.reserve( 30*1000 ); TranscodeJobImpl job = null; synchronized( TranscodeQueueImpl.this ){ if ( !got ){ if ( queue.size() == 0 ){ queue_thread = null; return; } } for ( TranscodeJobImpl j: queue ){ int state = j.getState(); // pick up any existing paused ones (remember, paused=running but with transcode paused if ( state == TranscodeJob.ST_FAILED && j.isAutoRetry()){ j.setAutoRetry( false ); j.reset(); job = j; break; }else if ( state == TranscodeJob.ST_PAUSED ){ // remember paused here is paused after an azureus // restart as 'process' blocks on pause job = j; }else if ( state == TranscodeJob.ST_QUEUED ){ if ( job == null && j.getDownloadETA() == 0 ){ job = j; } } } } checkJobStatus(); if ( job != null ){ if ( process( job )){ remove( job ); } } } }finally{ checkJobStatus(); } } }; queue_thread.start(); } } } protected void updateStatus( int tick_count ) { if ( queue.size() > 0 ){ TranscodeJobImpl[] jobs = getJobs(); for ( TranscodeJobImpl job: jobs ){ job.updateStatus(); } } } protected void checkJobStatus() { Set devices = new HashSet( Arrays.asList(manager.getManager().getDevices())); synchronized( this ){ for ( TranscodeJobImpl j: queue ){ if ( j.getState() == TranscodeJob.ST_FAILED ){ DeviceImpl device = j.getDevice(); device.setError( KEY_XCODE_ERROR, MessageText.getString( "device.error.xcodefail" )); devices.remove( device ); } } } for ( DeviceImpl device: devices ){ device.setError( KEY_XCODE_ERROR, null ); } } public TranscodeJobImpl add( TranscodeTarget target, TranscodeProfile profile, DiskManagerFileInfo file ) throws TranscodeException { return( add( target, profile, file, false )); } public TranscodeJobImpl add( TranscodeTarget target, TranscodeProfile profile, DiskManagerFileInfo file, int transcode_requirement ) throws TranscodeException { return( add( target, profile, file, false, transcode_requirement )); } public TranscodeJobImpl add( TranscodeTarget target, TranscodeProfile profile, DiskManagerFileInfo file, boolean stream ) throws TranscodeException { return( add( target, profile, file, stream, -1 )); } public TranscodeJobImpl add( TranscodeTarget target, TranscodeProfile profile, DiskManagerFileInfo file, boolean stream, int transcode_requirement ) throws TranscodeException { TranscodeFileImpl existing_tf = ((DeviceImpl)target.getDevice()).lookupFile( profile, file ); if ( existing_tf != null ){ List to_remove = new ArrayList(); synchronized( this ){ for ( TranscodeJobImpl job: queue ){ if ( job.getTarget() == target && job.getTranscodeFile().equals( existing_tf )){ to_remove.add( job ); } } } for ( TranscodeJobImpl job: to_remove ){ job.remove(); } if ( !stream ){ existing_tf.delete( true ); } } TranscodeJobImpl job = new TranscodeJobImpl( this, target, profile, file, transcode_requirement, stream ); try{ synchronized( this ){ queue.add( job ); queue_sem.release(); saveConfig(); } // I'd rather do qos from a listener trigger, but for now this ensures // I get the event even if listeners haven't had a chance to be added try { // force state log to queued just in case it got started (or errored) // between job creation and here PlatformDevicesMessenger.qosTranscode(job, TranscodeJob.ST_QUEUED); } catch (Throwable t) { Debug.out(t); } for ( TranscodeQueueListener listener: listeners ){ try{ listener.jobAdded( job ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } }finally{ schedule(); } return( job ); } protected void remove( TranscodeJobImpl job ) { synchronized( this ){ if ( !queue.remove( job )){ return; } } saveConfig(); job.destroy(); for ( TranscodeQueueListener listener: listeners ){ try{ listener.jobRemoved( job ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } checkJobStatus(); schedule(); } protected void jobChanged( TranscodeJob job, boolean schedule, boolean persistable ) { for ( TranscodeQueueListener listener: listeners ){ try{ listener.jobChanged( job ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } if ( persistable ){ configDirty(); } if ( schedule ){ queue_sem.release(); schedule(); } } protected int getIndex( TranscodeJobImpl job ) { synchronized( this ){ return( queue.indexOf(job)+1); } } public TranscodeJobImpl[] getJobs() { synchronized( this ){ return( queue.toArray( new TranscodeJobImpl[queue.size()])); } } public int getJobCount() { synchronized( this ){ return( queue.size()); } } public TranscodeJob getCurrentJob() { return( current_job ); } public boolean isTranscoding() { return( current_job != null ); } protected TranscodeJobImpl getJob( TranscodeFile for_file ) { synchronized( this ){ for ( TranscodeJobImpl job: queue ){ if ( job.getTranscodeFile().equals( for_file )){ return( job ); } } } return( null ); } public void moveUp( TranscodeJobImpl job ) { TranscodeJob[] updated; synchronized( this ){ int index = queue.indexOf( job ); if ( index <= 0 || queue.size() == 1 ){ return; } queue.remove( job ); queue.add( index-1, job ); updated = getJobs(); } for ( TranscodeJob j: updated ){ jobChanged( j, false, true ); } } public void moveDown( TranscodeJobImpl job ) { TranscodeJob[] updated; synchronized( this ){ int index = queue.indexOf( job ); if ( index < 0 || index == queue.size() - 1 ){ return; } queue.remove( job ); queue.add( index+1, job ); updated = getJobs(); } for ( TranscodeJob j: updated ){ jobChanged( j, false, true ); } } public void pause() { if ( !paused ){ if ( paused ){ COConfigurationManager.setParameter( "xcode.paused", true ); } } } public boolean isPaused() { return( paused ); } public void resume() { if ( paused ){ COConfigurationManager.setParameter( "xcode.queue.paused", false ); } } public long getMaxBytesPerSecond() { return( max_bytes_per_sec ); } public void setMaxBytesPerSecond( long max ) { COConfigurationManager.setParameter( "xcode.queue.maxbps", max ); } protected TranscodeTarget lookupTarget( String target_id ) throws TranscodeException { return( manager.lookupTarget( target_id )); } protected TranscodeProfile lookupProfile( String profile_id ) throws TranscodeException { TranscodeProfile profile = manager.getProfileFromUID( profile_id ); if ( profile == null ){ throw( new TranscodeException( "Transcode profile with id '" + profile_id + "' not found" )); } return( profile ); } protected DiskManagerFileInfo lookupFile( byte[] hash, int index ) throws TranscodeException { return( manager.lookupFile( hash, index )); } protected void configDirty() { synchronized( this ){ if ( config_dirty ){ return; } config_dirty = true; new DelayedEvent( "TranscodeQueue:save", 5000, new AERunnable() { public void runSupport() { synchronized( TranscodeQueueImpl.this ){ if ( !config_dirty ){ return; } saveConfig(); } } }); } } protected void loadConfig() { if ( !FileUtil.resilientConfigFileExists( CONFIG_FILE )){ return; } log( "Loading configuration" ); try{ synchronized( this ){ Map map = FileUtil.readResilientConfigFile( CONFIG_FILE ); List> l_jobs = (List>)map.get( "jobs" ); if ( l_jobs != null ){ for ( Map m: l_jobs ){ try{ TranscodeJobImpl job = new TranscodeJobImpl( this, m ); queue.add(job ); queue_sem.release(); }catch( Throwable e ){ log( "Failed to restore job: " + m, e ); } } } } }catch( Throwable e ){ log( "Configuration load failed", e ); } } protected void saveConfig() { synchronized( this ){ config_dirty = false; if ( queue.size() == 0 ){ FileUtil.deleteResilientConfigFile( CONFIG_FILE ); }else{ Map map = new HashMap(); List> l_jobs = new ArrayList>(); map.put( "jobs", l_jobs ); for ( TranscodeJobImpl job: queue ){ if ( job.isStream()){ continue; } try{ l_jobs.add( job.toMap()); }catch( Throwable e ){ log( "Failed to save job", e ); } } FileUtil.writeResilientConfigFile( CONFIG_FILE, map ); } } } protected void close() { if ( config_dirty ){ saveConfig(); } } public void addListener( TranscodeQueueListener listener ) { if (!listeners.contains(listener)) { listeners.add( listener ); } } public void removeListener( TranscodeQueueListener listener ) { listeners.remove( listener ); } protected void log( String str ) { manager.log( "Queue: " + str ); } protected void log( String str, Throwable e ) { manager.log( "Queue: " + str, e ); } public void generate( IndentWriter writer ) { writer.println( "Transcode Queue: paused=" + paused + ",max_bps=" + max_bytes_per_sec ); try{ writer.indent(); TranscodeJobImpl[] jobs = getJobs(); for ( TranscodeJobImpl job: jobs ){ job.generate( writer ); } }finally{ writer.exdent(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/TranscodePipeStreamSource2.java0000644000175000017500000000332311160046056030101 0ustar adrianadrian/* * Created on Feb 9, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.IOException; import java.io.InputStream; import java.net.Socket; public class TranscodePipeStreamSource2 extends TranscodePipe { private streamListener adapter; protected TranscodePipeStreamSource2( streamListener _adapter ) throws IOException { super( null ); adapter = _adapter; } protected void handleSocket( Socket socket1 ) { synchronized( this ){ if ( destroyed ){ try{ socket1.close(); }catch( Throwable e ){ } return; } sockets.add( socket1 ); } try{ adapter.gotStream( socket1.getInputStream()); }catch( Throwable e ){ synchronized( this ){ try{ socket1.close(); }catch( Throwable f ){ } sockets.remove( socket1 ); } } } interface streamListener { public void gotStream( InputStream is ); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/TranscodeJobOutputLeecher.java0000644000175000017500000002276311234525644030030 0ustar adrianadrian/* * Created on Feb 11, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.*; import java.util.*; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SHA1Simple; import org.gudy.azureus2.plugins.disk.DiskManagerChannel; import org.gudy.azureus2.plugins.disk.DiskManagerEvent; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.disk.DiskManagerListener; import org.gudy.azureus2.plugins.disk.DiskManagerRequest; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadException; import org.gudy.azureus2.plugins.utils.PooledByteBuffer; import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl; import com.aelitis.azureus.core.devices.TranscodeException; import com.aelitis.azureus.core.devices.TranscodeJob; import com.aelitis.azureus.core.util.CopyOnWriteList; public class TranscodeJobOutputLeecher implements DiskManagerFileInfo { private TranscodeJobImpl job; private TranscodeFileImpl file; private File save_to; private byte[] hash; public TranscodeJobOutputLeecher( TranscodeJobImpl _job, TranscodeFileImpl _file ) throws TranscodeException { job = _job; file = _file; save_to = file.getCacheFile(); try{ hash = new SHA1Simple().calculateHash( save_to.getAbsolutePath().getBytes( "UTF-8" )); }catch( Throwable e ){ Debug.out(e); } } public void setPriority( boolean b ) { } public void setSkipped( boolean b ) { throw( new RuntimeException( "Not supported" )); } public void setDeleted(boolean b) { } public void setLink( File link_destination ) { throw( new RuntimeException( "Not supported" )); } public File getLink() { return( null ); } public int getAccessMode() { return( READ ); } public long getDownloaded() { return( getLength()); } public long getLength() { if ( file.isComplete()){ try{ return( file.getTargetFile().getLength()); }catch( Throwable e ){ return( -1 ); } }else{ return( -1 ); } } public File getFile() { return( save_to ); } public int getIndex() { return( 0 ); } public int getFirstPieceNumber() { return( 0 ); } public long getPieceSize() { return( 32*1024 ); } public int getNumPieces() { return( -1 ); } public boolean isPriority() { return( false ); } public boolean isSkipped() { return( false ); } public boolean isDeleted() { return( false ); } public byte[] getDownloadHash() throws DownloadException { return( hash ); } public Download getDownload() throws DownloadException { throw( new DownloadException( "Not supported" )); } public DiskManagerChannel createChannel() throws DownloadException { return( new Channel()); } protected class Channel implements DiskManagerChannel { private volatile boolean channel_destroyed; private RandomAccessFile raf; public DiskManagerRequest createRequest() { return( new request()); } public DiskManagerFileInfo getFile() { return( TranscodeJobOutputLeecher.this ); } public void destroy() { synchronized( this ){ channel_destroyed = true; if ( raf != null ){ try{ raf.close(); }catch( Throwable e ){ } raf = null; } } } protected int read( byte[] buffer, long offset, int length ) throws IOException { synchronized( this ){ if ( channel_destroyed ){ throw( new IOException( "Channel destroyed" )); } if ( raf == null ){ if ( save_to.exists()){ raf = new RandomAccessFile( save_to, "r" ); }else{ int state = job.getState(); if ( state == TranscodeJob.ST_REMOVED ){ throw( new IOException( "Job has been removed" )); }else if ( state == TranscodeJob.ST_FAILED || state == TranscodeJob.ST_CANCELLED ){ throw( new IOException( "Job has failed or been cancelled" )); }else if ( state == TranscodeJob.ST_COMPLETE ){ throw( new IOException( "Job is complete but file missing" )); } // fall through and return 0 read } } if ( raf != null ){ if ( raf.length() > offset ){ raf.seek( offset ); return( raf.read( buffer, 0, length )); }else{ // data not yet available or file complete if ( file.isComplete()){ return( -1 ); } } } } try{ Thread.sleep( 500 ); }catch( Throwable e ){ throw( new IOException( "Interrupted" )); } return( 0 ); } protected class request implements DiskManagerRequest { private long offset; private long length; private long position; private int max_read_chunk = 128*1024;; private volatile boolean request_cancelled; private CopyOnWriteList listeners = new CopyOnWriteList(); public void setType( int type ) { if ( type != DiskManagerRequest.REQUEST_READ ){ throw( new RuntimeException( "Not supported" )); } } public void setOffset( long _offset ) { offset = _offset; } public void setLength( long _length ) { // length can be -1 here meaning 'to the end' length = _length==-1?Long.MAX_VALUE:_length; } public void setMaximumReadChunkSize( int size ) { if ( size > 16*1024 ){ max_read_chunk = size; } } public long getAvailableBytes() { return( getRemaining()); } public long getRemaining() { return( length==Long.MAX_VALUE?length:(offset + length - position )); } public void run() { try{ byte[] buffer = new byte[max_read_chunk]; long rem = length; long pos = offset; while( rem > 0 ){ if ( request_cancelled ){ throw( new Exception( "Cancelled" )); }else if ( channel_destroyed ){ throw( new Exception( "Destroyed" )); } int chunk = (int)Math.min( rem, max_read_chunk ); int len = read( buffer, pos, chunk ); if ( len == -1 ){ if ( length == Long.MAX_VALUE ){ break; }else{ throw( new Exception( "Premature end of stream (complete)" )); } }else if ( len == 0 ){ sendEvent( new event( pos )); }else{ sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len )); rem -= len; pos += len; } } }catch( Throwable e ){ sendEvent( new event( e )); } } public void cancel() { request_cancelled = true; } public void setUserAgent( String agent ) { } protected void sendEvent( event ev ) { for ( DiskManagerListener l: listeners ){ l.eventOccurred( ev ); } } public void addListener( DiskManagerListener listener ) { listeners.add( listener ); } public void removeListener( DiskManagerListener listener ) { listeners.remove( listener ); } protected class event implements DiskManagerEvent { private int event_type; private Throwable error; private PooledByteBuffer buffer; private long event_offset; private int event_length; protected event( Throwable _error ) { event_type = DiskManagerEvent.EVENT_TYPE_FAILED; error = _error; } protected event( long _offset ) { event_type = DiskManagerEvent.EVENT_TYPE_BLOCKED; event_offset = _offset; } protected event( PooledByteBuffer _buffer, long _offset, int _length ) { event_type = DiskManagerEvent.EVENT_TYPE_SUCCESS; buffer = _buffer; event_offset = _offset; event_length = _length; } public int getType() { return( event_type ); } public DiskManagerRequest getRequest() { return( request.this ); } public long getOffset() { return( event_offset ); } public int getLength() { return( event_length ); } public PooledByteBuffer getBuffer() { return( buffer ); } public Throwable getFailure() { return( error ); } } } } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/TranscodeManagerImpl.java0000644000175000017500000001600011171750562026763 0ustar adrianadrian/* * Created on Feb 4, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.devices.*; import com.aelitis.azureus.core.util.CopyOnWriteList; public class TranscodeManagerImpl implements TranscodeManager { private DeviceManagerImpl device_manager; private AzureusCore azureus_core; private TranscodeProviderVuze vuzexcode_provider; private CopyOnWriteList listeners = new CopyOnWriteList(); private TranscodeQueueImpl queue = new TranscodeQueueImpl( this ); private AESemaphore init_sem = new AESemaphore( "TM:init" ); protected TranscodeManagerImpl( DeviceManagerImpl _dm ) { device_manager = _dm; azureus_core = AzureusCoreFactory.getSingleton(); PluginInitializer.getDefaultInterface().addListener( new PluginListener() { public void initializationComplete() { PluginInterface default_pi = PluginInitializer.getDefaultInterface(); default_pi.addEventListener( new PluginEventListener() { public void handleEvent( PluginEvent ev ) { int type = ev.getType(); if ( type == PluginEvent.PEV_PLUGIN_OPERATIONAL ){ pluginAdded((PluginInterface)ev.getValue()); } if ( type == PluginEvent.PEV_PLUGIN_NOT_OPERATIONAL ){ pluginRemoved((PluginInterface)ev.getValue()); } } }); PluginInterface[] plugins = default_pi.getPluginManager().getPlugins(); for ( PluginInterface pi: plugins ){ if ( pi.getPluginState().isOperational()){ pluginAdded( pi ); } } queue.initialise(); init_sem.releaseForever(); } public void closedownInitiated() { } public void closedownComplete() { } }); } protected void pluginAdded( PluginInterface pi ) { if ( pi.getPluginState().isBuiltIn()){ return; } String plugin_id = pi.getPluginID(); if ( plugin_id.equals( "vuzexcode" )){ boolean added = false; boolean updated = false; TranscodeProviderVuze provider = null; synchronized( this ){ if ( vuzexcode_provider == null ){ provider = vuzexcode_provider = new TranscodeProviderVuze( this, pi ); added = true; }else if ( pi != vuzexcode_provider ){ provider = vuzexcode_provider; vuzexcode_provider.update( pi ); updated = true; } } if ( added ){ for ( TranscodeManagerListener listener: listeners ){ try{ listener.providerAdded( provider ); }catch( Throwable e ){ Debug.out( e ); } } }else if ( updated ){ for ( TranscodeManagerListener listener: listeners ){ try{ listener.providerUpdated( provider ); }catch( Throwable e ){ Debug.out( e ); } } } } } protected void pluginRemoved( PluginInterface pi ) { String plugin_id = pi.getPluginID(); if ( plugin_id.equals( "vuzexcode" )){ TranscodeProviderVuze provider = null; synchronized( this ){ if ( vuzexcode_provider != null ){ provider = vuzexcode_provider; vuzexcode_provider.destroy(); vuzexcode_provider = null; } } if ( provider != null ){ for ( TranscodeManagerListener listener: listeners ){ try{ listener.providerRemoved( provider ); }catch( Throwable e ){ Debug.out( e ); } } } } } protected void updateStatus( int tick_count ) { if ( queue != null ){ queue.updateStatus( tick_count ); } } public TranscodeProvider[] getProviders() { TranscodeProviderVuze vp = vuzexcode_provider; if ( vp == null ){ return( new TranscodeProvider[0] ); } return( new TranscodeProvider[]{ vp }); } protected TranscodeProfile getProfileFromUID( String uid ) { for ( TranscodeProvider provider: getProviders()){ TranscodeProfile profile = provider.getProfile( uid ); if ( profile != null ){ return( profile ); } } return( null ); } public TranscodeQueueImpl getQueue() { if ( !init_sem.reserve(10000)){ Debug.out( "Timeout waiting for init" ); } return( queue ); } protected DeviceManagerImpl getManager() { return( device_manager ); } protected TranscodeTarget lookupTarget( String target_id ) throws TranscodeException { Device device = device_manager.getDevice( target_id ); if ( device instanceof TranscodeTarget ){ return((TranscodeTarget)device); } throw( new TranscodeException( "Transcode target with id " + target_id + " not found" )); } protected DiskManagerFileInfo lookupFile( byte[] hash, int index ) throws TranscodeException { try{ Download download = PluginInitializer.getDefaultInterface().getDownloadManager().getDownload( hash ); if ( download == null ){ throw( new TranscodeException( "Download with hash " + ByteFormatter.encodeString( hash ) + " not found" )); } return( download.getDiskManagerFileInfo()[index]); }catch( Throwable e ){ throw( new TranscodeException( "Download with hash " + ByteFormatter.encodeString( hash ) + " not found", e )); } } protected void close() { queue.close(); } public void addListener( TranscodeManagerListener listener ) { listeners.add( listener ); } public void removeListener( TranscodeManagerListener listener ) { listeners.remove( listener ); } protected void log( String str ) { device_manager.log( "Trans: " + str ); } protected void log( String str, Throwable e ) { device_manager.log( "Trans: " + str, e ); } public void generate( IndentWriter writer ) { writer.println( "Transcode Manager: vuze provider=" + vuzexcode_provider ); queue.generate( writer ); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/TranscodeJobImpl.java0000644000175000017500000003651311266000066026126 0ustar adrianadrian/* * Created on Feb 6, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadException; import org.gudy.azureus2.plugins.download.DownloadRemovalVetoException; import org.gudy.azureus2.plugins.download.DownloadWillBeRemovedListener; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import com.aelitis.azureus.core.devices.TranscodeJob; import com.aelitis.azureus.core.devices.TranscodeProfile; import com.aelitis.azureus.core.devices.TranscodeException; import com.aelitis.azureus.core.devices.TranscodeTarget; import com.aelitis.azureus.core.download.DiskManagerFileInfoFile; import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.util.ImportExportUtils; public class TranscodeJobImpl implements TranscodeJob, DownloadWillBeRemovedListener { private static final int TRANSCODE_OK_DL_PERCENT = 90; private TranscodeQueueImpl queue; private TranscodeTarget target; private TranscodeProfile profile; private DiskManagerFileInfo file; private TranscodeFileImpl transcode_file; private boolean is_stream; private volatile InputStream stream; private AESemaphore stream_sem = new AESemaphore( "TJ:s" ); private int transcode_requirement; private int state = ST_QUEUED; private int percent_complete = 0; private int eta = Integer.MAX_VALUE; private String error; private long started_on; private long paused_on; private long process_time; private boolean use_direct_input; private boolean auto_retry; private int auto_retry_count; private Download download; private boolean download_ok; protected TranscodeJobImpl( TranscodeQueueImpl _queue, TranscodeTarget _target, TranscodeProfile _profile, DiskManagerFileInfo _file, int _transcode_requirement, boolean _is_stream ) throws TranscodeException { queue = _queue; target = _target; profile = _profile; file = _file; transcode_requirement = _transcode_requirement; is_stream = _is_stream; init(); } protected TranscodeJobImpl( TranscodeQueueImpl _queue, Map map ) throws IOException, TranscodeException { queue = _queue; state = ImportExportUtils.importInt( map, "state" ); if ( state == ST_RUNNING ){ state = ST_QUEUED; } error = ImportExportUtils.importString( map, "error", null ); String target_id = ImportExportUtils.importString( map, "target" ); target = queue.lookupTarget( target_id ); String profile_id = ImportExportUtils.importString( map, "profile" ); profile = queue.lookupProfile( profile_id ); String file_str = ImportExportUtils.importString( map, "file" ); if ( file_str == null ){ byte[] dl_hash = ByteFormatter.decodeString( ImportExportUtils.importString( map, "dl_hash" )); int file_index = ImportExportUtils.importInt( map, "file_index" ); file = queue.lookupFile( dl_hash, file_index ); }else{ file = new DiskManagerFileInfoFile( new File( file_str )); } transcode_requirement = ImportExportUtils.importInt( map, "trans_req", -1 ); init(); } protected Map toMap() throws IOException { try{ Map map = new HashMap(); ImportExportUtils.exportInt( map, "state", state ); ImportExportUtils.exportString( map, "error", error ); ImportExportUtils.exportString( map, "target", target.getID()); ImportExportUtils.exportString( map, "profile", profile.getUID()); try{ Download download = file.getDownload(); ImportExportUtils.exportString( map, "dl_hash", ByteFormatter.encodeString( download.getTorrent().getHash())); ImportExportUtils.exportInt( map, "file_index", file.getIndex()); }catch( DownloadException e ){ // external file ImportExportUtils.exportString( map, "file", file.getFile().getAbsolutePath()); } ImportExportUtils.exportInt( map, "trans_req", transcode_requirement ); return( map ); }catch( Throwable e ){ throw( new IOException( "Export failed: " + Debug.getNestedExceptionMessage(e))); } } protected void init() throws TranscodeException { transcode_file = ((DeviceImpl)target.getDevice()).allocateFile( profile, getTranscodeRequirement() == TranscodeTarget.TRANSCODE_NEVER, file, true ); try{ download = file.getDownload(); if ( download != null ){ download.addDownloadWillBeRemovedListener( this ); } }catch( Throwable e ){ } updateStatus( false ); } protected void updateStatus() { updateStatus( true ); } protected void updateStatus( boolean report_change ) { synchronized( this ){ if ( download_ok ){ return; } long downloaded = file.getDownloaded(); long length = file.getLength(); if ( download == null || downloaded == length ){ download_ok = true; }else{ if ( PlatformTorrentUtils.isContent( download.getTorrent(), false )){ download_ok = true; }else{ int percent_done = (int)( 100*downloaded/length ); if ( percent_done >= TRANSCODE_OK_DL_PERCENT ){ download_ok = true; } } } } if ( download_ok && report_change ){ queue.jobChanged( this, true, false ); } } public long getDownloadETA() { if ( download_ok ){ return( 0 ); } if ( file.getDownloaded() == file.getLength()){ return( 0 ); } if ( file.isSkipped() || file.isDeleted()){ return( Long.MAX_VALUE ); } try{ long eta = PluginCoreUtils.unwrap( download ).getStats().getETA(); if ( eta < 0 ){ return( Long.MAX_VALUE ); } long adjusted = eta*100/TRANSCODE_OK_DL_PERCENT; if ( adjusted == 0 ){ adjusted = 1; } return( adjusted ); }catch( Throwable e ){ Debug.out( e ); return( Long.MAX_VALUE ); } } protected boolean canUseDirectInput() { long length = file.getLength(); return( file.getDownloaded() == length && file.getFile().length() == length ); } protected boolean useDirectInput() { synchronized( this ){ return( use_direct_input ); } } protected void setUseDirectInput() { synchronized( this ){ use_direct_input = true; } } protected void setAutoRetry( boolean _auto_retry ) { synchronized( this ){ if ( _auto_retry ){ auto_retry = true; auto_retry_count++; }else{ auto_retry = false; } } } protected boolean isAutoRetry() { synchronized( this ){ return( auto_retry ); } } protected int getAutoRetryCount() { synchronized( this ){ return( auto_retry_count ); } } protected boolean isStream() { return( is_stream ); } protected void setStream( InputStream _stream ) { stream = _stream; stream_sem.releaseForever(); } protected InputStream getStream( int wait_for_millis ) throws IOException { if ( state == ST_FAILED ){ throw( new IOException( "Transcode job failed: " + error )); }else if ( state == ST_CANCELLED ){ throw( new IOException( "Transcode job cancelled" )); }else if ( state == ST_REMOVED ){ throw( new IOException( "Transcode job removed" )); } stream_sem.reserve( wait_for_millis ); return( stream ); } public void downloadWillBeRemoved( Download download ) throws DownloadRemovalVetoException { if ( queue.getIndex( this ) == 0 || state == ST_COMPLETE ){ download.removeDownloadWillBeRemovedListener( this ); }else{ throw( new DownloadRemovalVetoException( "Transcode in progress, removal refused" )); } } public String getName() { if ( download != null ){ if ( download.getDiskManagerFileInfo().length == 1 ){ return( download.getName()); } return( download.getName() + ": " + file.getFile().getName()); }else{ return( file.getFile().getName()); } } protected void reset() { state = ST_QUEUED; error = null; percent_complete = 0; eta = Integer.MAX_VALUE; } protected void starts() { synchronized( this ){ started_on = SystemTime.getMonotonousTime(); paused_on = 0; // this is for an Azureus restart with a paused job - we don't want to change the // state as we want it to re-pause... if ( state != ST_PAUSED ){ state = ST_RUNNING; } } queue.jobChanged( this, false, true ); } protected void failed( Throwable e ) { queue.log( "Transcode failed", e ); synchronized( this ){ if ( state != ST_STOPPED ){ state = ST_FAILED; error = Debug.getNestedExceptionMessage( e ); // process_time filled with negative pause time, so add to it process_time += SystemTime.getMonotonousTime() - started_on; started_on = paused_on = 0; } } queue.jobChanged( this, false, true ); // I'd rather do qos from a listener trigger, but for now this ensures // I get the event even if listeners haven't had a chance to be added. // This also ensures only one failed qos gets sent try { int logState = state; if (state != ST_STOPPED && !isStream() && getAutoRetryCount() == 0 && canUseDirectInput() && !useDirectInput()) { // we are going to retry.. logState |= 0x100; } PlatformDevicesMessenger.qosTranscode(this, logState); } catch (Throwable t) { Debug.out(t); } } protected void complete() { synchronized( this ){ state = ST_COMPLETE; // process_time filled with negative pause time, so add to it process_time += SystemTime.getMonotonousTime() - started_on; started_on = paused_on = 0; } if ( download != null ){ download.removeDownloadWillBeRemovedListener( this ); } transcode_file.setComplete( true ); queue.jobChanged( this, false, false ); // I'd rather do qos from a listener trigger, but for now this ensures // I get the event even if listeners haven't had a chance to be added // This also ensures only one completed qos event gets sent try { PlatformDevicesMessenger.qosTranscode(this, TranscodeJob.ST_COMPLETE); } catch (Throwable t) { Debug.out(t); } } protected void updateProgress( int _done, int _eta ) { if ( percent_complete != _done || eta != _eta){ percent_complete = _done; eta = _eta; queue.jobChanged( this, false, false ); } } public TranscodeTarget getTarget() { return( target ); } public int getTranscodeRequirement() { if ( transcode_requirement >= 0 ){ return( transcode_requirement ); } return( getDevice().getTranscodeRequirement()); } protected DeviceImpl getDevice() { return((DeviceImpl)target ); } public TranscodeProfile getProfile() { return( profile ); } public DiskManagerFileInfo getFile() { return( file ); } public TranscodeFileImpl getTranscodeFile() { return( transcode_file ); } public int getIndex() { return( queue.getIndex( this )); } public int getState() { return( state ); } public int getPercentComplete() { return( percent_complete ); } public long getETASecs() { if ( eta <= 0 ){ return( 0 ); }else if ( eta == Integer.MAX_VALUE ){ return( Long.MAX_VALUE ); }else{ return( eta ); } } public String getETA() { if ( eta < 0 ){ return( null ); }else if ( eta == Integer.MAX_VALUE ){ return( Constants.INFINITY_STRING ); }else{ return( TimeFormatter.format( eta )); } } public String getError() { return( error ); } public boolean canPause() { synchronized( this ){ return( !use_direct_input ); } } public void pause() { synchronized( this ){ if ( use_direct_input ){ return; } if ( state == ST_RUNNING ){ state = ST_PAUSED; paused_on = SystemTime.getMonotonousTime(); }else{ return; } } queue.jobChanged( this, false, true ); } public void resume() { synchronized( this ){ if ( state == ST_PAUSED ){ state = ST_RUNNING; if ( paused_on > 0 && started_on > 0 ){ process_time -= SystemTime.getMonotonousTime() - paused_on; } }else{ return; } } queue.jobChanged( this, false, true ); } public void queue() { boolean do_resume; synchronized( this ){ do_resume = state == ST_PAUSED; } if ( do_resume ){ resume(); return; } synchronized( this ){ if ( state != ST_QUEUED ){ if ( state == ST_RUNNING || state == ST_PAUSED ){ stop(); } reset(); // manual start, scrub error details use_direct_input = false; auto_retry = false; auto_retry_count = 0; is_stream = false; }else{ return; } } queue.jobChanged( this, true, true); } public void stop() { synchronized( this ){ if ( state != ST_STOPPED ){ state = ST_STOPPED; process_time = 0; started_on = 0; }else{ return; } } queue.jobChanged( this, true, true ); } public void remove() { queue.remove( this ); } protected void destroy() { boolean delete_file; synchronized( this ){ delete_file = state != ST_COMPLETE; state = ST_REMOVED; } if ( delete_file && !isStream()){ try{ transcode_file.delete( true ); }catch( Throwable e ){ queue.log( "Faile to destroy job", e ); } } } public void moveUp() { queue.moveUp( this ); } public void moveDown() { queue.moveDown( this ); } public long getProcessTime() { if ( state == ST_COMPLETE ){ return process_time; } if ( started_on == 0 ){ if ( process_time > 0 ){ return process_time; } return 0; } // process_time filled with pause return SystemTime.getMonotonousTime() - started_on + process_time; } public void generate( IndentWriter writer ) { writer.println( "target=" + target.getID() + ", profile=" + profile.getName() + ", file=" + file ); writer.println( "tfile=" + transcode_file.getString()); writer.println( "stream=" + is_stream + ", state=" + state + ", treq=" + transcode_requirement + ", %=" + percent_complete + ", error=" + error ); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceOfflineDownloaderImpl.java0000644000175000017500000011147611307644112030276 0ustar adrianadrian/* * Created on Jan 28, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.IOException; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.disk.DiskManagerPiece; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerAdapter; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AsyncDispatcher; import org.gudy.azureus2.core3.util.BEncoder; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.util.FrequencyLimitedDispatcher; import org.gudy.azureus2.core3.util.LightHashMap; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.peers.Peer; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.devices.*; import com.aelitis.azureus.core.security.CryptoManagerFactory; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.util.DownloadUtils; import com.aelitis.net.upnp.UPnPDevice; import com.aelitis.net.upnp.UPnPRootDevice; import com.aelitis.net.upnp.services.UPnPOfflineDownloader; public class DeviceOfflineDownloaderImpl extends DeviceUPnPImpl implements DeviceOfflineDownloader { public static final int UPDATE_MILLIS = 30*1000; public static final int UPDATE_TICKS = UPDATE_MILLIS/DeviceManagerImpl.DEVICE_UPDATE_PERIOD; public static final int UPDATE_SPACE_MILLIS = 3*60*1000; public static final int UPDATE_SPACE_TICKS = UPDATE_SPACE_MILLIS/DeviceManagerImpl.DEVICE_UPDATE_PERIOD; public static final String client_id = ByteFormatter.encodeString( CryptoManagerFactory.getSingleton().getSecureID()); private static final Object ERROR_KEY_OD = new Object(); private volatile UPnPOfflineDownloader service; private volatile String service_ip; private volatile String manufacturer; private long start_time = SystemTime.getMonotonousTime(); private volatile boolean update_space_outstanding = true; private volatile long space_on_device = -1; private volatile boolean closing; private AsyncDispatcher dispatcher = new AsyncDispatcher(); final FrequencyLimitedDispatcher freq_lim_updater = new FrequencyLimitedDispatcher( new AERunnable() { public void runSupport() { updateDownloads(); } }, 5*1000 ); private boolean start_of_day = true; private int consec_errors = 0; private int consec_success = 0; private Map offline_downloads = new HashMap(); private Map transferable = new LinkedHashMap(); private TransferableDownload current_transfer; private boolean is_transferring; private CopyOnWriteList listeners = new CopyOnWriteList(); protected DeviceOfflineDownloaderImpl( DeviceManagerImpl _manager, UPnPDevice _device, UPnPOfflineDownloader _service ) { super( _manager, _device, Device.DT_OFFLINE_DOWNLOADER ); setService( _service ); } protected DeviceOfflineDownloaderImpl( DeviceManagerImpl _manager, Map _map ) throws IOException { super(_manager, _map ); manufacturer = getPersistentStringProperty( PP_OD_MANUFACTURER, "?" ); } protected boolean updateFrom( DeviceImpl _other, boolean _is_alive ) { if ( !super.updateFrom( _other, _is_alive )){ return( false ); } if ( !( _other instanceof DeviceOfflineDownloaderImpl )){ Debug.out( "Inconsistent" ); return( false ); } DeviceOfflineDownloaderImpl other = (DeviceOfflineDownloaderImpl)_other; if ( service == null && other.service != null ){ setService( other.service ); updateDownloads(); } return( true ); } protected void setService( UPnPOfflineDownloader _service ) { service = _service; UPnPRootDevice root = service.getGenericService().getDevice().getRootDevice(); service_ip = root.getLocation().getHost(); try{ service_ip = InetAddress.getByName( service_ip ).getHostAddress(); }catch( Throwable e ){ Debug.out( e ); } Map cache = root.getDiscoveryCache(); if ( cache != null ){ setPersistentMapProperty( PP_OD_UPNP_DISC_CACHE, cache ); } manufacturer = root.getDevice().getManufacturer(); setPersistentStringProperty( PP_OD_MANUFACTURER, manufacturer ); updateDownloads(); } protected void UPnPInitialised() { super.UPnPInitialised(); if ( service == null ){ Map cache = getPersistentMapProperty( PP_OD_UPNP_DISC_CACHE, null ); if ( cache != null ){ getUPnPDeviceManager().injectDiscoveryCache( cache ); } } } protected void updateStatus( int tick_count ) { super.updateStatus( tick_count ); update_space_outstanding |= tick_count % UPDATE_SPACE_TICKS == 0; if ( tick_count % UPDATE_TICKS == 0 ){ updateDownloads(); } } protected void checkConfig() { freq_lim_updater.dispatch(); } protected void updateDownloads() { dispatcher.dispatch( new AERunnable() { public void runSupport() { if ( dispatcher.getQueueSize() == 0 ){ updateDownloadsSupport(); } } }); } protected void updateDownloadsSupport() { AzureusCore core = getManager().getAzureusCore(); if ( core == null || closing ){ // not yet initialised or closing return; } boolean warn_if_dead = SystemTime.getMonotonousTime() - start_time > 3*60*1000; if ( !isAlive() || service == null ){ // no usable service if ( warn_if_dead ){ setError( ERROR_KEY_OD, MessageText.getString( "device.od.error.notfound" )); } return; } String error_status = null; Map new_offline_downloads = new HashMap(); Map new_transferables = new HashMap(); try{ if ( update_space_outstanding ){ try{ space_on_device = service.getFreeSpace( client_id ); update_space_outstanding = false; if ( space_on_device == 0 ){ error_status = MessageText.getString( "device.od.error.nospace" ); } }catch( Throwable e ){ error_status = MessageText.getString( "device.od.error.opfailexcep", new String[]{ "GetFreeSpace", Debug.getNestedExceptionMessage( e )}); log( "Failed to get free space", e ); } } Map old_cache = (Map)getPersistentMapProperty( PP_OD_STATE_CACHE, new HashMap()); Map new_cache = new HashMap(); GlobalManager gm = core.getGlobalManager(); if ( start_of_day ){ start_of_day = false; Map xfer_cache = getPersistentMapProperty( PP_OD_XFER_CACHE, new HashMap()); if ( xfer_cache.size() > 0 ){ List initial_downloads = gm.getDownloadManagers(); for ( DownloadManager download: initial_downloads ){ if ( download.isForceStart()){ TOTorrent torrent = download.getTorrent(); if ( torrent == null ){ continue; } try{ byte[] hash = torrent.getHash(); String hash_str = ByteFormatter.encodeString( hash ); Map m = xfer_cache.get( hash_str ); if ( m != null ){ if ( m.containsKey( "f" )){ log( download, "Resetting force-start" ); download.setForceStart( false ); } } }catch( Throwable e ){ Debug.printStackTrace(e); } } } } gm.addListener( new GlobalManagerAdapter() { public void downloadManagerAdded( DownloadManager dm ) { freq_lim_updater.dispatch(); } public void downloadManagerRemoved( DownloadManager dm ) { freq_lim_updater.dispatch(); } }, false ); } DeviceManager manager = getManager(); DeviceOfflineDownloaderManager dodm = manager.getOfflineDownlaoderManager(); List downloads; if ( dodm.isOfflineDownloadingEnabled() && isEnabled()){ List initial_downloads = gm.getDownloadManagers(); List relevant_downloads = new ArrayList( initial_downloads.size()); // remove uninteresting ones for ( DownloadManager download: initial_downloads ){ int state = download.getState(); if ( state == DownloadManager.STATE_SEEDING ){ // state == DownloadManager.STATE_ERROR ){ removed - might be out of disk space and fixable continue; } // don't include 'stopping' here as we go through stopping on way to queued if ( state == DownloadManager.STATE_STOPPED ){ // don't remove from downloader if simply paused if ( !download.isPaused()){ continue; } } // if it is complete then of no interest if ( download.isDownloadComplete( false )){ continue; } relevant_downloads.add( download ); } downloads = new ArrayList( relevant_downloads.size()); if ( dodm.getOfflineDownloadingIsAuto()){ boolean include_private = dodm.getOfflineDownloadingIncludePrivate(); if ( include_private ){ downloads.addAll( relevant_downloads ); }else{ for ( DownloadManager download: relevant_downloads ){ TOTorrent torrent = download.getTorrent(); if ( !TorrentUtils.isReallyPrivate( torrent )){ downloads.add( download ); } } } }else{ // manual, just use the tagged downloads for ( DownloadManager download: relevant_downloads ){ if ( dodm.isManualDownload( PluginCoreUtils.wrap( download ))){ downloads.add( download ); } } } }else{ downloads = new ArrayList(); } Map download_map = new HashMap(); for ( DownloadManager download: downloads ){ TOTorrent torrent = download.getTorrent(); if ( torrent == null ){ continue; } try{ byte[] hash = torrent.getHash(); String hash_str = ByteFormatter.encodeString( hash ); DiskManager disk = download.getDiskManager(); if ( disk == null ){ byte[] existing = old_cache.get( hash_str ); if ( existing != null ){ new_cache.put( hash_str, existing ); download_map.put( download, existing ); }else{ // assume not yet started and just use the non-skipped files DiskManagerFileInfo[] files = download.getDiskManagerFileInfo(); byte[] needed = new byte[( torrent.getNumberOfPieces() + 7 ) / 8]; int hits = 0; for ( DiskManagerFileInfo file: files ){ if ( file.isSkipped()){ continue; } int first_piece = file.getFirstPieceNumber(); int last_piece = first_piece + file.getNbPieces() - 1; int needed_pos = first_piece/8; int current_byte = 0; for ( int pos=first_piece;pos<=last_piece;pos++ ){ current_byte = current_byte << 1; current_byte += 1; hits++; if (( pos %8 ) == 7 ){ needed[needed_pos++] |= (byte)current_byte; current_byte = 0; } } if ( current_byte != 0 ){ needed[needed_pos++] |= (byte)(current_byte << (8 - (last_piece % 8))); } } if ( hits > 0 ){ new_cache.put( hash_str, needed ); download_map.put( download, needed ); } } }else{ DiskManagerPiece[] pieces = disk.getPieces(); byte[] needed = new byte[( pieces.length + 7 ) / 8]; int needed_pos = 0; int current_byte = 0; int pos = 0; int hits = 0; for ( DiskManagerPiece piece: pieces ){ current_byte = current_byte << 1; if ( piece.isNeeded() && !piece.isDone()){ current_byte += 1; hits++; } if (( pos %8 ) == 7 ){ needed[needed_pos++] = (byte)current_byte; current_byte = 0; } pos++; } if (( pos % 8 ) != 0 ){ needed[needed_pos++] = (byte)(current_byte << (8 - (pos % 8))); } if ( hits > 0 ){ new_cache.put( hash_str, needed ); download_map.put( download, needed ); } } }catch( Throwable e ){ Debug.out( e ); } } // store this so we have consistent record for downloads that queue/pause etc and therefore lose accessible piece details setPersistentMapProperty( PP_OD_STATE_CACHE, new_cache ); // sort by download priority List> entries = new ArrayList>( download_map.entrySet()); Collections.sort( entries, new Comparator>() { public int compare( Map.Entry o1, Map.Entry o2) { return( o1.getKey().getPosition() - o2.getKey().getPosition()); } }); String download_hashes = ""; Iterator> it = entries.iterator(); while( it.hasNext()){ Map.Entry entry = it.next(); DownloadManager download = entry.getKey(); try{ String hash = ByteFormatter.encodeString( download.getTorrent().getHash()); download_hashes += ( download_hashes.length()==0?"":"," ) + hash; new_offline_downloads.put( hash, download ); }catch( Throwable e ){ log( download, "Failed to get download hash", e ); it.remove(); } } try{ String[] set_dl_results = service.setDownloads( client_id, download_hashes ); String set_dl_result = set_dl_results[0].trim(); String set_dl_status = set_dl_results[1]; if ( !set_dl_status.equals( "OK" )){ error_status = MessageText.getString( "device.od.error.opfailstatus", new String[]{ "SetDownloads", set_dl_status }); throw( new Exception( "Failing result returned: " + set_dl_status )); } String[] bits = set_dl_result.split( "," ); int num_bits = set_dl_result.length()==0?0:bits.length; if ( num_bits != entries.size()){ log( "SetDownloads returned an invalid number of results (hashes=" + new_offline_downloads.size() + ",result=" + set_dl_result + ")"); }else{ it = entries.iterator(); int pos = 0; while( it.hasNext()){ Map.Entry entry = it.next(); DownloadManager download = entry.getKey(); try{ TOTorrent torrent = download.getTorrent(); String hash_str = ByteFormatter.encodeString( torrent.getHash()); int status = Integer.parseInt( bits[ pos++ ]); boolean do_update = false; if ( status == 0 ){ do_update = true; }else if ( status == 1 ){ // need to add the torrent try{ // for vuze content add in the azid if ( PlatformTorrentUtils.isContent( torrent, true )){ String ext = DownloadUtils.getTrackerExtensions( PluginCoreUtils.wrap( download )); if ( ext != null && ext.length() > 0 ){ try{ if ( ext.startsWith( "&" )){ ext = ext.substring(1); } torrent = TOTorrentFactory.deserialiseFromMap( torrent.serialiseToMap()); torrent.setAnnounceURL( appendToURL( torrent.getAnnounceURL(), ext )); TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets(); for ( TOTorrentAnnounceURLSet set: sets ){ URL[] urls = set.getAnnounceURLs(); for (int i=0;i 0 ){ byte[] have_map = ByteFormatter.decodeString( have_bitfield ); if ( have_map.length != required_map.length ){ throw( new Exception( "UpdateDownload: Returned bitmap length invalid" )); } for ( int i=0;i>= 1; } } } if ( useful_piece_count > 0 ) { long piece_size = torrent.getPieceLength(); new_transferables.put( hash_str, new TransferableDownload( download, hash_str, have_map, useful_piece_count * piece_size )); } } if ( useful_piece_count > 0 ){ log( download, "They have " + useful_piece_count + " pieces that we don't" ); } }catch( Throwable e ){ error_status = MessageText.getString( "device.od.error.opfailexcep", new String[]{ "UpdateDownload", Debug.getNestedExceptionMessage( e )}); log( download, "UpdateDownload failed", e ); } } }catch( Throwable e ){ log( download, "Processing failed", e ); } } } }catch( Throwable e ){ error_status = MessageText.getString( "device.od.error.opfailexcep", new String[]{ "SetDownloads", Debug.getNestedExceptionMessage( e )}); log( "SetDownloads failed", e ); } }finally{ updateTransferable( new_transferables ); List new_ods = new ArrayList(); List del_ods = new ArrayList(); List cha_ods = new ArrayList(); synchronized( offline_downloads ){ for (Map.Entry entry: new_offline_downloads.entrySet()){ String key = entry.getKey(); if ( !offline_downloads.containsKey( key )){ OfflineDownload new_od = new OfflineDownload( entry.getValue()); offline_downloads.put( key, new_od ); new_ods.add( new_od ); } } Iterator> it = offline_downloads.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = it.next(); String key = entry.getKey(); OfflineDownload od = entry.getValue(); if ( new_offline_downloads.containsKey( key )){ TransferableDownload new_td = transferable.get( key ); TransferableDownload existing_td = od.getTransferable(); if ( new_td != existing_td ){ if ( !new_ods.contains( od )){ cha_ods.add( od ); } od.setTransferable( new_td ); } }else{ it.remove(); del_ods.add( od ); } } } for ( OfflineDownload od: new_ods ){ for ( DeviceOfflineDownloaderListener listener: listeners ){ try{ listener.downloadAdded( od ); }catch( Throwable e ){ Debug.out( e ); } } } for ( OfflineDownload od: cha_ods ){ for ( DeviceOfflineDownloaderListener listener: listeners ){ try{ listener.downloadChanged( od ); }catch( Throwable e ){ Debug.out( e ); } } } for ( OfflineDownload od: del_ods ){ for ( DeviceOfflineDownloaderListener listener: listeners ){ try{ listener.downloadRemoved( od ); }catch( Throwable e ){ Debug.out( e ); } } } updateError( error_status ); } } protected void updateError( String str ) { if ( str == null ){ setError( ERROR_KEY_OD, null ); consec_errors = 0; consec_success++; }else{ consec_errors++; consec_success = 0; if ( consec_errors > 2 ){ setError( ERROR_KEY_OD, str ); } } } protected URL appendToURL( URL url, String ext ) throws MalformedURLException { String url_str = url.toExternalForm(); if ( url_str.indexOf( '?' ) == -1 ){ url_str += "?" + ext; }else{ url_str += "&" + ext; } return( new URL( url_str )); } protected void updateTransferable( Map map ) { // remove non-transferable entries Iterator> it = transferable.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = it.next(); if ( !map.containsKey( entry.getKey())){ TransferableDownload existing = entry.getValue(); if ( existing == current_transfer ){ current_transfer.deactivate(); current_transfer = null; } it.remove(); } } // add in new ones for ( TransferableDownload td: map.values()){ String hash = td.getHash(); if ( !transferable.containsKey( hash )){ transferable.put( hash, td ); } } if ( transferable.size() == 0 ){ if ( is_transferring ){ is_transferring = false; setBusy( false ); } return; } if ( !is_transferring ){ is_transferring = true; setBusy( true ); } // check current if ( current_transfer != null && transferable.size() > 0 ){ // rotate through them in case something's stuck for whatever reason long now = SystemTime.getMonotonousTime(); long runtime = now - current_transfer.getStartTime(); if ( runtime >= 30*1000 ){ boolean rotate = false; PEPeerManager pm = current_transfer.getDownload().getPeerManager(); if ( pm == null ){ rotate = true; }else{ if ( runtime > 3*60*1000 ){ List peers = pm.getPeers( service_ip ); if ( peers.size() == 0 ){ rotate = true; }else{ PEPeer peer = peers.get(0); if ( peer.getStats().getDataReceiveRate() < 1024 ){ rotate = true; } } } } if ( rotate ){ current_transfer.deactivate(); current_transfer = null; } } } if ( current_transfer == null ){ Iterator it2 = transferable.values().iterator(); current_transfer = it2.next(); it2.remove(); transferable.put( current_transfer.getHash(), current_transfer ); } if ( current_transfer != null ){ if ( !current_transfer.isActive()){ current_transfer.activate(); } if ( current_transfer.isForced()){ Map xfer_cache = new HashMap(); Map m = new HashMap(); m.put( "f", new Long(1)); xfer_cache.put( current_transfer.getHash(), m ); setPersistentMapProperty( PP_OD_XFER_CACHE, xfer_cache ); } DownloadManager download = current_transfer.getDownload(); int data_port = current_transfer.getDataPort(); if ( data_port <= 0 ){ try{ String[] start_results = service.startDownload( client_id, current_transfer.getHash()); String start_status = start_results[1]; if ( !start_status.equals( "OK" )){ throw( new Exception( "Failing result returned: " + start_status )); } data_port = Integer.parseInt( start_results[0] ); log( download, "StartDownload succeeded - data port=" + data_port ); }catch( Throwable e ){ log( download, "StartDownload failed", e ); } } if ( data_port > 0 ){ current_transfer.setDataPort( data_port ); } final TransferableDownload transfer = current_transfer; dispatcher.dispatch( new AERunnable() { private final int[] count = { 0 }; public void runSupport() { count[0]++; if ( current_transfer != transfer || !transfer.isActive()){ return; } PEPeerManager pm = transfer.getDownload().getPeerManager(); if ( pm == null ){ return; } List peers = pm.getPeers( service_ip ); if ( peers.size() > 0 ){ return; } Map user_data = new LightHashMap(); user_data.put( Peer.PR_PRIORITY_CONNECTION, new Boolean( true )); pm.addPeer( service_ip, transfer.getDataPort(), 0, false, user_data ); if ( count[0] < 3 ){ final AERunnable target = this; SimpleTimer.addEvent( "OD:retry", SystemTime.getCurrentTime()+5*1000, new TimerEventPerformer() { public void perform( org.gudy.azureus2.core3.util.TimerEvent event ) { dispatcher.dispatch( target ); }; }); } } }); } } protected void close() { super.close(); final AESemaphore sem = new AESemaphore( "DOD:closer" ); dispatcher.dispatch( new AERunnable() { public void runSupport() { try{ closing = true; if ( service != null ){ try{ service.activate( client_id ); }catch( Throwable e ){ } } }finally{ sem.release(); } } }); sem.reserve(250); } public boolean isEnabled() { return( getPersistentBooleanProperty( PP_OD_ENABLED, false )); } public void setEnabled( boolean b ) { setPersistentBooleanProperty( PP_OD_ENABLED, b ); if ( b ){ freq_lim_updater.dispatch(); } } public boolean hasShownFTUX() { return( getPersistentBooleanProperty( PP_OD_SHOWN_FTUX, false )); } public void setShownFTUX() { setPersistentBooleanProperty( PP_OD_SHOWN_FTUX, true ); } public String getManufacturer() { return( manufacturer ); } public long getSpaceAvailable( boolean force ) throws DeviceManagerException { if ( space_on_device >= 0 && !force ){ return( space_on_device ); } if ( service == null ){ throw( new DeviceManagerException( "Device is not online" )); } try{ space_on_device = service.getFreeSpace( client_id ); update_space_outstanding = false; return( space_on_device ); }catch( Throwable e ){ throw( new DeviceManagerException( "Failed to read available space", e )); } } public int getTransferingCount() { return( transferable.size()); } public DeviceOfflineDownload[] getDownloads() { synchronized( offline_downloads ){ return( offline_downloads.values().toArray( new DeviceOfflineDownload[ offline_downloads.size()])); } } public void addListener( DeviceOfflineDownloaderListener listener ) { listeners.add( listener ); } public void removeListener( DeviceOfflineDownloaderListener listener ) { listeners.remove( listener ); } protected void getDisplayProperties( List dp ) { super.getDisplayProperties( dp ); String space_str = ""; if ( space_on_device >= 0 ){ space_str = DisplayFormatters.formatByteCountToKiBEtc( space_on_device ); } addDP( dp, "azbuddy.enabled", isEnabled()); addDP( dp, "device.od.space", space_str ); } protected void log( DownloadManager download, String str ) { log( download.getDisplayName() + ": " + str ); } protected void log( DownloadManager download, String str, Throwable e ) { log( download.getDisplayName() + ": " + str, e ); } protected void log( String str ) { super.log( "OfflineDownloader: " + str ); } protected void log( String str, Throwable e ) { super.log( "OfflineDownloader: " + str, e ); } protected class OfflineDownload implements DeviceOfflineDownload { private DownloadManager core_download; private Download download; private TransferableDownload transferable; protected OfflineDownload( DownloadManager _core_download ) { core_download = _core_download; download = PluginCoreUtils.wrap( core_download ); } public Download getDownload() { return( download ); } public boolean isTransfering() { return( transferable != null ); } public long getCurrentTransferSize() { TransferableDownload t = transferable; if ( t == null ){ return( 0 ); } return( t.getCurrentTransferSize()); } public long getRemaining() { TransferableDownload t = transferable; if ( t == null ){ return( 0 ); } return( t.getRemaining()); } protected void setTransferable( TransferableDownload td ) { transferable = td; } protected TransferableDownload getTransferable() { return( transferable ); } } protected class TransferableDownload { private DownloadManager download; private String hash_str; private byte[] have_map; private boolean active; private long start_time; private boolean forced; private int data_port; private long transfer_size; private volatile long last_calc; private volatile long last_calc_time; protected TransferableDownload( DownloadManager _download, String _hash_str, byte[] _have_map, long _transfer_size_estimate ) { download = _download; hash_str = _hash_str; have_map = _have_map; // not totally accurate, in general will be > required as based purely on piece // size as opposed to blocks. however, we need an initial estimate as the download // may not yet be running and therefore we can't get accurate size now transfer_size = _transfer_size_estimate; last_calc = transfer_size; } protected long calcDiff() { long now = SystemTime.getMonotonousTime(); if ( now - last_calc_time < 2*1000 ){ return( last_calc ); } DiskManager disk = download.getDiskManager(); if ( disk == null ){ return( last_calc ); } DiskManagerPiece[] pieces = disk.getPieces(); int pos = 0; int current = 0; long remaining = 0; for ( int i=0; i properties; protected TranscodeProfileImpl( TranscodeProvider _provider, String _uid, String _name, Map _properties ) { provider = _provider; uid = _uid; name = _name; properties = _properties; } public String getUID() { return( uid ); } public String getName() { return( name ); } public TranscodeProvider getProvider() { return( provider ); } public boolean isStreamable() { String res = (String)properties.get( "streamable" ); return( res != null && res.equalsIgnoreCase( "yes" )); } public String getFileExtension() { return((String)properties.get( "file-ext" )); } public String getDeviceClassification() { return((String)properties.get( "device" )); } public String getDescription() { String res = (String)properties.get( "desc" ); return( res == null?"":res ); } public String getIconURL() { return((String)properties.get( "icon-url" )); } public File getAssetDirectory() { return( provider.getAssetDirectory()); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/impl/DeviceDriveManager.java0000644000175000017500000001431511236502142026406 0ustar adrianadrian/* * Created on Jul 31, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices.impl; import java.io.*; import java.util.*; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AsyncDispatcher; import com.aelitis.azureus.core.devices.Device; import com.aelitis.azureus.core.devices.DeviceTemplate; import com.aelitis.azureus.core.drivedetector.DriveDetectedInfo; import com.aelitis.azureus.core.drivedetector.DriveDetectedListener; import com.aelitis.azureus.core.drivedetector.DriveDetectorFactory; public class DeviceDriveManager implements DriveDetectedListener { private DeviceManagerImpl manager; private Map device_map = new HashMap(); private AsyncDispatcher async_dispatcher = new AsyncDispatcher(); private boolean listener_added; protected DeviceDriveManager( DeviceManagerImpl _manager ) { manager = _manager; if ( manager.getAutoSearch()){ listener_added = true; DriveDetectorFactory.getDeviceDetector().addListener( this ); } } protected void search() { async_dispatcher.dispatch( new AERunnable() { public void runSupport() { if ( listener_added ){ return; } try{ // this should synchronously first any discovered drives DriveDetectorFactory.getDeviceDetector().addListener( DeviceDriveManager.this ); }finally{ DriveDetectorFactory.getDeviceDetector().removeListener( DeviceDriveManager.this ); } } }); } public void driveDetected( final DriveDetectedInfo info ) { async_dispatcher.dispatch( new AERunnable() { public void runSupport() { File root = info.getLocation(); if ( root.exists()){ File[] folders = root.listFiles(); if ( folders != null ){ Set names = new HashSet(); for ( File file: folders ){ names.add( file.getName().toLowerCase()); } if ( names.contains( "psp" ) && names.contains( "video" )){ DeviceImpl[] devices = manager.getDevices(); String target_name = "PSP"; String target_classification = "sony.PSP"; File target_directory = new File( root,"VIDEO" ); for ( DeviceImpl device: devices ){ if ( device instanceof DeviceMediaRendererManual ){ DeviceMediaRendererManual renderer = (DeviceMediaRendererManual)device; String classification = renderer.getClassification(); if ( classification.equalsIgnoreCase( target_classification )){ mapDevice( renderer, root, target_directory ); return; } } } DeviceTemplate[] templates = manager.getDeviceTemplates( Device.DT_MEDIA_RENDERER ); DeviceMediaRendererManual renderer = null; for ( DeviceTemplate template: templates ){ if ( template.getClassification().equalsIgnoreCase( target_classification )){ try{ renderer = (DeviceMediaRendererManual)template.createInstance( target_name ); break; }catch( Throwable e ){ log( "Failed to add device", e ); } } } if ( renderer == null ){ // damn, the above doesn't work until devices is turned on... try{ renderer = (DeviceMediaRendererManual)manager.createDevice( Device.DT_MEDIA_RENDERER, target_classification, target_name ); }catch( Throwable e ){ log( "Failed to add device", e ); } } if ( renderer != null ){ try{ renderer.setAutoCopyToFolder( true ); mapDevice( renderer, root, target_directory ); return; }catch( Throwable e ){ log( "Failed to add device", e ); } } } } } } }); } public void driveRemoved( final DriveDetectedInfo info ) { async_dispatcher.dispatch( new AERunnable() { public void runSupport() { unMapDevice( info.getLocation()); } }); } protected void mapDevice( DeviceMediaRendererManual renderer, File root, File copy_to ) { DeviceMediaRendererManual existing; synchronized( device_map ){ existing = device_map.put( root.getAbsolutePath(), renderer ); } if ( existing != null && existing != renderer ){ log( "Unmapped " + existing.getName() + " from " + root ); existing.setCopyToFolder( null ); } log( "Mapped " + renderer.getName() + " to " + root ); renderer.setCopyToFolder( copy_to ); renderer.setLivenessDetectable( true ); renderer.alive(); } protected void unMapDevice( File root ) { DeviceMediaRendererManual existing; synchronized( device_map ){ existing = device_map.remove( root.getAbsolutePath()); } if ( existing != null ){ log( "Unmapped " + existing.getName() + " from " + root ); existing.setCopyToFolder( null ); existing.dead(); } } protected void log( String str ) { manager.log( "DriveMan: " + str ); } protected void log( String str, Throwable e ) { manager.log( "DriveMan: " + str, e ); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeProfile.java0000644000175000017500000000230211231244042025212 0ustar adrianadrian/* * Created on Feb 4, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; import java.io.File; public interface TranscodeProfile { public String getUID(); public String getName(); public String getDescription(); public boolean isStreamable(); public String getIconURL(); public String getFileExtension(); public String getDeviceClassification(); public TranscodeProvider getProvider(); public File getAssetDirectory(); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeTargetListener.java0000644000175000017500000000217211152153314026556 0ustar adrianadrian/* * Created on Feb 13, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface TranscodeTargetListener { public static final int CT_PROPERTY = 1; // data = String property public void fileAdded( TranscodeFile file ); public void fileChanged( TranscodeFile file, int type, Object data ); public void fileRemoved( TranscodeFile file ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceMediaRendererTemplate.java0000644000175000017500000000173511227541540027312 0ustar adrianadrian/* * Created on Jul 10, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface DeviceMediaRendererTemplate extends DeviceTemplate { public int getRendererSpecies(); public TranscodeProfile[] getProfiles(); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceManagerFactory.java0000644000175000017500000000214011161652114025776 0ustar adrianadrian/* * Created on Jan 27, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; import com.aelitis.azureus.core.devices.impl.DeviceManagerImpl; public class DeviceManagerFactory { public static void preInitialise() { DeviceManagerImpl.preInitialise(); } public static DeviceManager getSingleton() { return( DeviceManagerImpl.getSingleton()); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderListener.java0000644000175000017500000000210611247443312030210 0ustar adrianadrian/* * Created on Sep 1, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface DeviceOfflineDownloaderListener { public void downloadAdded( DeviceOfflineDownload download ); public void downloadChanged( DeviceOfflineDownload download ); public void downloadRemoved( DeviceOfflineDownload download ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceListener.java0000644000175000017500000000163111247643716024702 0ustar adrianadrian/* * Created on Sep 2, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface DeviceListener { public void deviceChanged( Device device ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeProviderAdapter.java0000644000175000017500000000221311157576134026727 0ustar adrianadrian/* * Created on Feb 9, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface TranscodeProviderAdapter { public void updateProgress( int percent, int eta_secs, int new_width, int new_height ); public void streamStats( long connect_rate, long write_speed ); public void failed( TranscodeException error ); public void complete(); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceContentDirectory.java0000644000175000017500000000160011140225434026371 0ustar adrianadrian/* * Created on Jan 27, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface DeviceContentDirectory extends Device { } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceTemplate.java0000644000175000017500000000240211227541540024653 0ustar adrianadrian/* * Created on Jul 10, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface DeviceTemplate { public int getType(); public String getName(); public String getManufacturer(); public String getClassification(); public String getShortDescription(); public boolean isAuto(); /** * auto devices can't be manually created * @param name * @return * @throws DeviceManagerException */ public Device createInstance( String name ) throws DeviceManagerException; } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceMediaRenderer.java0000644000175000017500000000464411233765270025625 0ustar adrianadrian/* * Created on Jan 27, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; import java.io.File; import java.net.InetAddress; import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice; public interface DeviceMediaRenderer extends Device, TranscodeTarget { public static final int RS_PS3 = 1; public static final int RS_XBOX = 2; public static final int RS_ITUNES = 3; public static final int RS_WII = 4; public static final int RS_BROWSER = 5; public static final int RS_OTHER = 6; /** * THIS WILL CHANGE!!! * @return RS_ */ public int getRendererSpecies(); public boolean canFilterFilesView(); public void setFilterFilesView( boolean filter ); public boolean getFilterFilesView(); // copy to device public boolean canCopyToDevice(); public int getCopyToDevicePending(); public boolean canAutoStartDevice(); public boolean getAutoStartDevice(); public void setAutoStartDevice( boolean auto ); // copy to folder public boolean canCopyToFolder(); public File getCopyToFolder(); public void setCopyToFolder( File file ); public int getCopyToFolderPending(); public boolean getAutoCopyToFolder(); public void setAutoCopyToFolder( boolean auto ); public void manualCopy() throws DeviceManagerException; // associate public boolean canAssociate(); public void associate( UnassociatedDevice assoc ); public boolean canShowCategories(); public void setShowCategories( boolean b ); public boolean getShowCategories(); public boolean isRSSPublishEnabled(); public void setRSSPublishEnabled( boolean enabled ); public InetAddress getAddress(); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeQueue.java0000644000175000017500000000331711154144050024707 0ustar adrianadrian/* * Created on Feb 6, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; public interface TranscodeQueue { public TranscodeJob add( TranscodeTarget target, TranscodeProfile profile, DiskManagerFileInfo file ) throws TranscodeException; public TranscodeJob add( TranscodeTarget target, TranscodeProfile profile, DiskManagerFileInfo file, int transcode_requirement ) // from target.TRANSCODE_ throws TranscodeException; public TranscodeJob[] getJobs(); public void pause(); public boolean isPaused(); public void resume(); public int getJobCount(); public TranscodeJob getCurrentJob(); public boolean isTranscoding(); public long getMaxBytesPerSecond(); public void setMaxBytesPerSecond( long max ); public void addListener( TranscodeQueueListener listener ); public void removeListener( TranscodeQueueListener listener ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceManager.java0000644000175000017500000000422311266732670024466 0ustar adrianadrian/* * Created on Jan 27, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; import java.io.File; import java.net.InetAddress; public interface DeviceManager { public DeviceTemplate[] getDeviceTemplates( int device_type ); public DeviceManufacturer[] getDeviceManufacturers( int device_type ); public Device[] getDevices(); public void search( int max_millis, DeviceSearchListener listener ); public boolean getAutoSearch(); public void setAutoSearch( boolean auto ); public boolean isRSSPublishEnabled(); public void setRSSPublishEnabled( boolean enabled ); public String getRSSLink(); public UnassociatedDevice[] getUnassociatedDevices(); public TranscodeManager getTranscodeManager(); public File getDefaultWorkingDirectory(); public void setDefaultWorkingDirectory( File dir ); public boolean isBusy(); public DeviceOfflineDownloaderManager getOfflineDownlaoderManager(); public boolean isTiVoEnabled(); public void setTiVoEnabled( boolean enabled ); public void addListener( DeviceManagerListener listener ); public void removeListener( DeviceManagerListener listener ); public interface UnassociatedDevice { public InetAddress getAddress(); public String getDescription(); } public interface DeviceManufacturer { public String getName(); public DeviceTemplate[] getDeviceTemplates(); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeFile.java0000644000175000017500000000455011233522532024505 0ustar adrianadrian/* * Created on Feb 13, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; import java.io.File; import java.net.URL; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; public interface TranscodeFile { // don't change these, they are serialised public static final String PT_COMPLETE = "comp"; public static final String PT_COPIED = "copied"; public static final String PT_COPY_FAILED = "copy_fail"; public static final String PT_CATEGORY = "cat"; public String getName(); public DiskManagerFileInfo getSourceFile() throws TranscodeException; public DiskManagerFileInfo getTargetFile() throws TranscodeException; public String getProfileName(); public long getCreationDateMillis(); public boolean isComplete(); public boolean getTranscodeRequired(); public boolean isCopiedToDevice(); public long getCopyToDeviceFails(); public void retryCopyToDevice(); public boolean isTemplate(); public long getDurationMillis(); public long getVideoWidth(); public long getVideoHeight(); public String[] getCategories(); public void setCategories( String[] cats ); public Device getDevice(); public File getCacheFileIfExists(); /** * Will return null unless there is a job in existance for this file * @return */ public TranscodeJob getJob(); public URL getStreamURL(); public URL getStreamURL( String host ); public void delete( boolean delete_cache_file ) throws TranscodeException; public void setTransientProperty( Object key, Object value ); public Object getTransientProperty( Object key ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeManager.java0000644000175000017500000000211311143234054025170 0ustar adrianadrian/* * Created on Feb 4, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface TranscodeManager { public TranscodeProvider[] getProviders(); public TranscodeQueue getQueue(); public void addListener( TranscodeManagerListener listener ); public void removeListener( TranscodeManagerListener listener ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderManager.java0000644000175000017500000000272111247370226030003 0ustar adrianadrian/* * Created on Sep 1, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; import org.gudy.azureus2.plugins.download.Download; public interface DeviceOfflineDownloaderManager { public boolean isOfflineDownloadingEnabled(); public void setOfflineDownloadingEnabled( boolean enabled ); public boolean getOfflineDownloadingIsAuto(); public void setOfflineDownloadingIsAuto( boolean auto ); public boolean getOfflineDownloadingIncludePrivate(); public void setOfflineDownloadingIncludePrivate( boolean include ); public boolean isManualDownload( Download download ); public void addManualDownloads( Download[] download ); public void removeManualDownloads( Download[] download ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeTarget.java0000644000175000017500000000361511252045030025047 0ustar adrianadrian/* * Created on Feb 4, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; import java.io.File; public interface TranscodeTarget { public static final int TRANSCODE_NEVER = 1; public static final int TRANSCODE_WHEN_REQUIRED = 2; public static final int TRANSCODE_ALWAYS = 3; public String getID(); public Device getDevice(); public TranscodeFile[] getFiles(); public File getWorkingDirectory(); public void setWorkingDirectory( File directory ); public TranscodeProfile[] getTranscodeProfiles(); public TranscodeProfile getDefaultTranscodeProfile() throws TranscodeException; public void setDefaultTranscodeProfile( TranscodeProfile profile ); public int getTranscodeRequirement(); public void setTranscodeRequirement( int req ); public boolean getAlwaysCacheFiles(); public void setAlwaysCacheFiles( boolean always_cache ); public boolean isTranscoding(); public boolean isGeneric(); public boolean isAudioCompatible( TranscodeFile file ); public void addListener( TranscodeTargetListener listener ); public void removeListener( TranscodeTargetListener listener ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeJob.java0000644000175000017500000000365111224751000024333 0ustar adrianadrian/* * Created on Feb 4, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; public interface TranscodeJob { public static final int ST_QUEUED = 0; public static final int ST_RUNNING = 1; public static final int ST_PAUSED = 2; public static final int ST_COMPLETE = 3; public static final int ST_CANCELLED = 4; public static final int ST_FAILED = 5; public static final int ST_STOPPED = 6; public static final int ST_REMOVED = 7; public String getName(); public TranscodeTarget getTarget(); public TranscodeProfile getProfile(); public DiskManagerFileInfo getFile(); public TranscodeFile getTranscodeFile(); public int getTranscodeRequirement(); public int getIndex(); public int getState(); public long getDownloadETA(); public int getPercentComplete(); public long getETASecs(); public String getETA(); public String getError(); public boolean canPause(); public void pause(); public void resume(); public void queue(); public void stop(); public void remove(); public void moveUp(); public void moveDown(); public long getProcessTime(); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeProviderAnalysis.java0000644000175000017500000000256311156364746027145 0ustar adrianadrian/* * Created on Mar 2, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface TranscodeProviderAnalysis { public static final int PT_TRANSCODE_REQUIRED = 1; // Boolean public static final int PT_DURATION_MILLIS = 2; // Long public static final int PT_VIDEO_WIDTH = 3; // Long public static final int PT_VIDEO_HEIGHT = 4; // Long public static final int PT_FORCE_TRANSCODE = 5; // Boolean (set) public void cancel(); public boolean getBooleanProperty( int property ); public void setBooleanProperty( int property, boolean value ); public long getLongProperty( int property ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeProviderJob.java0000644000175000017500000000175511144435112026055 0ustar adrianadrian/* * Created on Feb 9, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface TranscodeProviderJob { public void pause(); public void resume(); public void cancel(); public void setMaxBytesPerSecond( int max ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceManagerListener.java0000644000175000017500000000214711245135230026161 0ustar adrianadrian/* * Created on Jan 27, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface DeviceManagerListener { public void deviceAdded( Device device ); public void deviceChanged( Device device ); public void deviceAttentionRequest( Device device ); public void deviceRemoved( Device device ); public void deviceManagerLoaded(); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceOfflineDownload.java0000644000175000017500000000206311247605474026166 0ustar adrianadrian/* * Created on Sep 1, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; import org.gudy.azureus2.plugins.download.Download; public interface DeviceOfflineDownload { public Download getDownload(); public boolean isTransfering(); public long getCurrentTransferSize(); public long getRemaining(); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/Device.java0000644000175000017500000000445011247643714023174 0ustar adrianadrian/* * Created on Jan 27, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; import java.net.URL; public interface Device { public static final int DT_UNKNOWN = 0; public static final int DT_INTERNET_GATEWAY = 1; public static final int DT_CONTENT_DIRECTORY = 2; public static final int DT_MEDIA_RENDERER = 3; public static final int DT_INTERNET = 4; public static final int DT_OFFLINE_DOWNLOADER = 5; public int getType(); public String getID(); public String getName(); public void setName( String name ); public String getClassification(); public String getShortDescription(); public boolean isAlive(); public boolean isLivenessDetectable(); public boolean isBusy(); public boolean isManual(); public void setHidden( boolean is_hidden ); public boolean isHidden(); public boolean isBrowsable(); public browseLocation[] getBrowseLocations(); public void setTransientProperty( Object key, Object value ); public Object getTransientProperty( Object key ); /** * Array of resource strings and their associated values * @return */ public String[][] getDisplayProperties(); public void requestAttention(); public void remove(); public boolean canRemove(); public String getInfo(); public String getError(); public void addListener( DeviceListener listener ); public void removeListener( DeviceListener listener ); public String getString(); interface browseLocation { public String getName(); public URL getURL(); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceOfflineDownloader.java0000644000175000017500000000260011307644112026477 0ustar adrianadrian/* * Created on Jan 27, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface DeviceOfflineDownloader extends Device { public boolean isEnabled(); public void setEnabled( boolean b ); public boolean hasShownFTUX(); public void setShownFTUX(); public String getManufacturer(); public long getSpaceAvailable( boolean force ) throws DeviceManagerException; public int getTransferingCount(); public DeviceOfflineDownload[] getDownloads(); public void addListener( DeviceOfflineDownloaderListener listener ); public void removeListener( DeviceOfflineDownloaderListener listener ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeManagerListener.java0000644000175000017500000000206111142773046026710 0ustar adrianadrian/* * Created on Feb 5, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface TranscodeManagerListener { public void providerAdded( TranscodeProvider provider ); public void providerUpdated( TranscodeProvider provider ); public void providerRemoved( TranscodeProvider provider ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeQueueListener.java0000644000175000017500000000200511143234054026410 0ustar adrianadrian/* * Created on Feb 6, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface TranscodeQueueListener { public void jobAdded( TranscodeJob job ); public void jobChanged( TranscodeJob job ); public void jobRemoved( TranscodeJob job ); } azureus-4.3.0.6/com/aelitis/azureus/core/devices/TranscodeException.java0000644000175000017500000000206411145500640025560 0ustar adrianadrian/* * Created on Feb 2, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; @SuppressWarnings("serial") public class TranscodeException extends Exception { public TranscodeException( String str ) { super( str ); } public TranscodeException( String str, Throwable e ) { super( str, e ); } } azureus-4.3.0.6/com/aelitis/azureus/core/devices/DeviceSearchListener.java0000644000175000017500000000167111141756014026021 0ustar adrianadrian/* * Created on Feb 2, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.devices; public interface DeviceSearchListener { public void deviceFound( Device device ); public void complete(); } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/0000755000175000017500000000000011310377626021616 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/metasearch/MetaSearchException.java0000644000175000017500000000204611014473240026344 0ustar adrianadrian/* * Created on May 15, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch; public class MetaSearchException extends Exception { public MetaSearchException( String str ) { super( str ); } public MetaSearchException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/ResultListener.java0000644000175000017500000000233111051226736025441 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch; public interface ResultListener { public void contentReceived(Engine engine, String content ); public void matchFound( Engine engine, String[] fields ); public void resultsReceived(Engine engine,Result[] results); public void resultsComplete(Engine engine); public void engineFailed(Engine engine, Throwable cause ); public void engineRequiresLogin(Engine engine, Throwable cause ); } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/MetaSearchManagerFactory.java0000644000175000017500000000216711014456402027315 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch; import com.aelitis.azureus.core.metasearch.impl.MetaSearchManagerImpl; public class MetaSearchManagerFactory { public static void preInitialise() { MetaSearchManagerImpl.preInitialise(); } public static MetaSearchManager getSingleton() { return( MetaSearchManagerImpl.getSingleton()); } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/MetaSearchManager.java0000644000175000017500000000247211050156250025762 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch; import java.util.Map; public interface MetaSearchManager { public MetaSearch getMetaSearch(); public boolean isAutoMode(); public void setSelectedEngines( long[] ids, boolean auto ) throws MetaSearchException; public Engine addEngine( long id, int type, String name, String json_value ) throws MetaSearchException; public Engine importEngine( Map map, boolean warn_user ) throws MetaSearchException; public void log( String str ); } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/CookieParameter.java0000644000175000017500000000213011017365102025515 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch; public class CookieParameter { String name; String value; public CookieParameter(String name, String value) { super(); this.name = name; this.value = value; } public String getName() { return name; } public String getValue() { return value; } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/Result.java0000644000175000017500000001664511310053052023733 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Random; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.json.simple.JSONObject; import com.aelitis.azureus.core.metasearch.utils.MomentsAgoDateFormatter; public abstract class Result { private Engine engine; public abstract Date getPublishedDate(); public abstract String getCategory(); public abstract void setCategory(String category); public abstract String getContentType(); public abstract void setContentType(String contentType); public abstract String getName(); public abstract long getSize(); public abstract int getNbPeers(); public abstract int getNbSeeds(); public abstract int getNbSuperSeeds(); public abstract int getComments(); public abstract int getVotes(); public abstract int getVotesDown(); public abstract boolean isPrivate(); public abstract String getDRMKey(); //Links public abstract String getDownloadLink(); public abstract String getDownloadButtonLink(); public abstract String getCDPLink(); public abstract String getPlayLink(); public abstract float getAccuracy(); // 0.0 -> 1.0 and -1 if not supported public abstract String getSearchQuery(); public abstract String getUID(); public abstract String getHash(); protected Result( Engine _engine ) { engine = _engine; } public Engine getEngine() { return( engine ); } public String toString() { return getName() + " : " + getNbSeeds() + " s, " + getNbPeers() + "p, " ; } /* public String getNameHTML() { if(getName() != null) { return( getName()); //return( XUXmlWriter.escapeXML( getName())); //return Entities.XML.escape(getName()); } return null; } public String getCategoryHTML() { if(getCategory() != null) { return( getCategory()); //return Entities.XML.escape(getCategory()); } return null; } */ /** * * @return a value between 0 and 1 representing the rank of the result */ public float getRank() { int seeds = getNbSeeds(); int peers = getNbPeers(); if ( seeds < 0 ){ seeds = 0; } if ( peers < 0 ){ peers = 0; } int totalVirtualPeers = 3 * seeds + peers + 2; int superSeeds = getNbSuperSeeds(); if(superSeeds > 0) { totalVirtualPeers += 50 * superSeeds; } int votes = getVotes(); if(votes > 0) { if(votes > 50) { votes = 50; } totalVirtualPeers += 5 * votes; } int votesDown = getVotesDown(); if(votesDown > 0) { totalVirtualPeers -= 200 * votesDown; } if(totalVirtualPeers < 2) totalVirtualPeers = 2; float rank = (float) (Math.log(totalVirtualPeers)/Math.log(10)) / 5f; if(rank > 2f) rank = 2f; if(isPrivate()) { rank /= 2; } String queryString = getSearchQuery(); String name = getName(); if(queryString != null && name != null) { name = name.toLowerCase( Locale.ENGLISH ); String token = ""; List tokens = new ArrayList(); char[] chars = queryString.toCharArray(); for ( char c: chars ){ if ( Character.isLetterOrDigit( c )){ token += String.valueOf(c).toLowerCase( Locale.ENGLISH ); }else{ if ( token.length() > 0 ){ tokens.add( token ); token = ""; } } } if ( token.length() > 0 ){ tokens.add( token ); } for ( String s: tokens ){ if( !name.contains( s )){ rank /= 2; } } } rank = applyRankBias( rank ); return rank; } protected float applyRankBias( float _rank ) { float rank = engine.applyRankBias( _rank ); /* if ( rank != _rank ){ System.out.println( "bias applied for " + engine.getName() + ": " + _rank + "-> " + rank ); } */ return( rank ); } public Map toJSONMap() { Map object = new JSONObject(); try { object.put("d", MomentsAgoDateFormatter.getMomentsAgoString(this.getPublishedDate())); object.put("ts", "" + this.getPublishedDate().getTime()); } catch(Exception e) { object.put("d", "unknown"); object.put("ts", "0"); } object.put("c", this.getCategory()); object.put("n",this.getName()); int super_seeds = getNbSuperSeeds(); int seeds = getNbSeeds(); int seed_total = -1; if ( super_seeds > 0 ){ seed_total = 10*super_seeds + new Random().nextInt(10); } if ( seeds > 0 ){ if ( seed_total == -1 ){ seed_total = 0; } seed_total += seeds; } object.put("s","" + seed_total); if(this.getNbPeers() >= 0) { object.put("p","" + this.getNbPeers()); } else { object.put("p","-1"); } int comments = getComments(); if ( comments >= 0 ){ object.put( "co", "" + comments ); } long size = this.getSize(); if(size >= 0) { // max three digits for display purposes String size_str = DisplayFormatters.formatByteCountToKiBEtc( size ); size_str = DisplayFormatters.trimDigits( size_str, 3 ); object.put("l", size_str ); object.put("lb", "" + size ); } else { object.put("l", "-1"); object.put("lb", "0"); } object.put("r", "" + this.getRank()); object.put("ct", this.getContentType()); float accuracy = getAccuracy(); if ( accuracy >= 0 ){ if ( accuracy > 1 ){ accuracy = 1; } object.put ("ac", "" + accuracy ); } if ( this.getCDPLink().length() > 0 ){ object.put("cdp", this.getCDPLink()); } // This is also used by subscription code to extract download link so if you // change this you'll need to change that too... if ( this.getDownloadLink().length() > 0 ){ object.put("dl", this.getDownloadLink()); } if ( this.getDownloadButtonLink().length() > 0 ){ object.put("dbl", this.getDownloadButtonLink()); } if ( this.getPlayLink().length() > 0 ){ object.put("pl", this.getPlayLink()); } if ( this.getVotes() >= 0 ){ object.put("v", "" + this.getVotes()); } if ( this.getVotesDown() >= 0 ){ object.put("vd", "" + this.getVotesDown()); } String drmKey = getDRMKey(); if(drmKey != null) { object.put("dk",drmKey); } // used by subscriptions... String uid = getUID(); if ( uid != null ){ object.put( "u", uid ); } object.put("pr", this.isPrivate() ? "1" : "0"); String hash = getHash(); if ( hash != null ){ object.put( "h", hash ); } return object; } public static void adjustRelativeTerms( Map map ) { String ts = (String)map.get( "ts" ); if ( ts != null ){ long l_ts = Long.parseLong(ts); if ( l_ts > 0 ){ map.put("d", MomentsAgoDateFormatter.getMomentsAgoString(new Date( l_ts ))); } } } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/0000755000175000017500000000000011310377626022557 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/DateParserClassic.java0000644000175000017500000002147111017365104026753 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.impl; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.StringTokenizer; import java.util.TimeZone; public class DateParserClassic extends DateParser { static boolean DEBUG = false; TimeZone timeZone; DateFormat ddMMMyyyyFormat; DateFormat ddMMMyyFormat; DateFormat MMddyyyyFormat; DateFormat userDateFormat; boolean auto; public DateParserClassic() { this("GMT",true,null); } public DateParserClassic(String timeZone,boolean auto, String dateFormat) { this.timeZone = TimeZone.getTimeZone(timeZone); this.auto = auto; if(!auto) { if(dateFormat != null) { userDateFormat = new SimpleDateFormat(dateFormat); userDateFormat.setTimeZone(this.timeZone); } else { //TODO : in debug mode throw an Exception telling the user he needs to provide a dateFormat in manual mode } } ddMMMyyyyFormat = new SimpleDateFormat("dd MMM yyyy"); ddMMMyyyyFormat.setTimeZone(this.timeZone); ddMMMyyFormat = new SimpleDateFormat("dd MMM yy"); ddMMMyyFormat.setTimeZone(this.timeZone); MMddyyyyFormat = new SimpleDateFormat("MM-dd yyyy"); MMddyyyyFormat.setTimeZone(this.timeZone); } public Date parseDate(String date) { Date result = null; if(auto) { result = parseDateInternal(date); } else { if(userDateFormat != null) { try { result = userDateFormat.parse(date); } catch(Exception e) { //TODO : in debug mode, throw an exception to tell the user that his dateFormat is invalid / didn't parse a date } } } if(DEBUG) { System.out.println(date + " > " + result.toString()); } return result; } private Date parseDateInternal(String s) { if(s == null) { return null; } s = s.toLowerCase().trim(); //"Today hh:mm" and "Y-day hh:mm" cases if(s.startsWith("today ") || s.startsWith("y-day ")) { try { Calendar calendar = new GregorianCalendar(); calendar.setTimeZone(timeZone); String time = s.substring(6); StringTokenizer st = new StringTokenizer(time,":"); int hours = Integer.parseInt(st.nextToken()); int minutes = Integer.parseInt(st.nextToken()); calendar.set(Calendar.HOUR_OF_DAY, hours); calendar.set(Calendar.MINUTE,minutes); if(s.startsWith("y-day ")) { calendar.add(Calendar.DATE, -1); } return calendar.getTime(); } catch(Exception e) { e.printStackTrace(); return null; } } //"07-25 2006", "02-01 02:53" and "03 Mar 2006" cases if(s.length() > 3) { String thirdCharacter = s.substring(2,3); //"07-25 2006" and "02-01 02:53" cases if(thirdCharacter.equals("-")) { if(s.length() > 9) { String ninthCharacter = s.substring(8,9); //"02-01 02:53" case if(ninthCharacter.equals(":")) { try { int month = Integer.parseInt(s.substring(0,2)); int day = Integer.parseInt(s.substring(3,5)); int hours = Integer.parseInt(s.substring(6,8)); int minutes = Integer.parseInt(s.substring(9,11)); Calendar calendar = new GregorianCalendar(); calendar.setTimeZone(timeZone); calendar.set(Calendar.MONTH, month-1); calendar.set(Calendar.DAY_OF_MONTH,day); calendar.set(Calendar.HOUR_OF_DAY, hours); calendar.set(Calendar.MINUTE,minutes); return calendar.getTime(); } catch (Exception e) { e.printStackTrace(); } } //"07-25 2006" else { try { return MMddyyyyFormat.parse(s); } catch (Exception e) { e.printStackTrace(); } } } else { //"03-25" case try { int month = Integer.parseInt(s.substring(0,2)); int day = Integer.parseInt(s.substring(3,5)); Calendar calendar = new GregorianCalendar(); calendar.setTimeZone(timeZone); calendar.set(Calendar.MONTH, month); calendar.set(Calendar.DAY_OF_MONTH,day); return calendar.getTime(); } catch (Exception e) { e.printStackTrace(); } } } else if(s.length() == 9 && s.indexOf(" ") != -1){ //"21 Mar 08" case try { return ddMMMyyFormat.parse(s); } catch (Exception e) { if(DEBUG) {e.printStackTrace();} } } //"03 Mar 2006" case if(thirdCharacter.equals(" ")) { try { return ddMMMyyyyFormat.parse(s); } catch (Exception e) { if(DEBUG) {e.printStackTrace();} } } } //Age based stuff if( s.endsWith(" ago") || s.indexOf("month")!= -1 || s.indexOf("hour") != -1 || s.indexOf("day") != -1 || s.indexOf("week") != -1 || s.indexOf("year") != -1) { s= s.replaceAll(" ago", ""); StringTokenizer st = new StringTokenizer(s," "); if(st.countTokens() >= 2) { try { Calendar calendar = new GregorianCalendar(); while(st.hasMoreTokens()) { float value = Float.parseFloat(st.nextToken()); String unit = st.nextToken(); calendar.setTimeZone(timeZone); if(unit.startsWith("min")) { calendar.add(Calendar.MINUTE, -(int)value); } if(unit.startsWith("hour")) { calendar.add(Calendar.HOUR_OF_DAY, -(int)value); } if(unit.startsWith("day")) { calendar.add(Calendar.DATE, -(int)value); } if(unit.startsWith("week")) { calendar.add(Calendar.WEEK_OF_YEAR, -(int)value); } if(unit.startsWith("month")) { calendar.add(Calendar.MONTH, -(int)value); } if(unit.startsWith("year")) { calendar.add(Calendar.YEAR, -(int)value); } } return calendar.getTime(); } catch (Exception e) { if(DEBUG) {e.printStackTrace();} } } } if(s.equals("today")) { Calendar calendar = new GregorianCalendar(); calendar.setTimeZone(timeZone); //calendar.set(Calendar.HOUR_OF_DAY,12); //calendar.set(Calendar.MINUTE,0); return calendar.getTime(); } if(s.equals("yesterday")) { Calendar calendar = new GregorianCalendar(); calendar.setTimeZone(timeZone); calendar.add(Calendar.DATE, -1); //calendar.set(Calendar.HOUR_OF_DAY,12); //calendar.set(Calendar.MINUTE,0); return calendar.getTime(); } try { StringTokenizer st = new StringTokenizer(s," "); Calendar calendar = new GregorianCalendar(); calendar.setTimeZone(timeZone); while(st.hasMoreTokens()) { String element = st.nextToken(); int field = -1; int end_offset = -1; if(element.endsWith("h")) { field = Calendar.HOUR_OF_DAY; end_offset = 1; } if(element.endsWith("d")) { field = Calendar.DAY_OF_MONTH; end_offset = 1; } if(element.endsWith("w")) { field = Calendar.WEEK_OF_YEAR; end_offset = 1; } if(element.endsWith("m")) { field = Calendar.MONTH; end_offset = 1; } if(element.endsWith("mon")) { field = Calendar.MONTH; end_offset = 3; } if(element.endsWith("y")) { field = Calendar.YEAR; end_offset = 1; } if(field != -1 && end_offset != -1) { int value = (int) (Float.parseFloat(element.substring(0,element.length() - end_offset))); calendar.add(field,-value); } } return calendar.getTime(); } catch (Exception e) { if(DEBUG) {e.printStackTrace();} } return null; } public static void main(String args[]) { DEBUG = true; DateParserClassic dateParser = new DateParserClassic(); dateParser.parseDate("Today 05:34"); dateParser.parseDate("Y-Day 21:55"); dateParser.parseDate("07-25 2006"); dateParser.parseDate("02-01 02:53"); dateParser.parseDate("03 Mar 2006"); dateParser.parseDate("0 minute ago"); dateParser.parseDate("3 hours ago"); dateParser.parseDate("2 days ago"); dateParser.parseDate("10 months ago"); dateParser.parseDate("45 mins ago"); dateParser.parseDate("Today"); dateParser.parseDate("Yesterday"); dateParser.parseDate("16.9w"); dateParser.parseDate("22.6h"); dateParser.parseDate("1.7d"); dateParser.parseDate("2d 7h"); dateParser.parseDate("1w"); dateParser.parseDate("1w 4d"); dateParser.parseDate("1mon 1w"); } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/FieldRemapper.java0000644000175000017500000000437511017366070026145 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.impl; import java.util.regex.Matcher; import com.aelitis.azureus.core.metasearch.Result; import com.aelitis.azureus.core.metasearch.Engine; public class FieldRemapper { private int inField; private int outField; private FieldRemapping[] fieldRemappings; public FieldRemapper( int inField, int outField, FieldRemapping[] fieldRemappings) { super(); this.inField = inField; this.outField = outField; this.fieldRemappings = fieldRemappings; } public int getInField() { return( inField ); } public int getOutField() { return( outField ); } public FieldRemapping[] getMappings() { return( fieldRemappings ); } public void remap( Result r ) { String input = null; switch(inField) { case Engine.FIELD_CATEGORY : input = r.getCategory(); break; } String output = null; if(input != null) { for(int i = 0 ; i < fieldRemappings.length ; i++) { if(fieldRemappings[i].getMatch() != null && fieldRemappings[i].getReplacement() != null) { Matcher matcher = fieldRemappings[i].getMatch().matcher(input); if(matcher.matches()) { output = matcher.replaceAll(fieldRemappings[i].getReplacement()); i = fieldRemappings.length; } } } } if(output != null) { switch(outField) { case Engine.FIELD_CATEGORY : r.setCategory(output); break; case Engine.FIELD_CONTENT_TYPE : r.setContentType(output); break; } } } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/plugin/0000755000175000017500000000000011310377626024055 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/plugin/PluginEngine.java0000644000175000017500000001653211273454510027307 0ustar adrianadrian/* * Created on Jun 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.impl.plugin; import java.io.IOException; import java.util.*; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.utils.search.SearchInstance; import org.gudy.azureus2.plugins.utils.search.SearchObserver; import org.gudy.azureus2.plugins.utils.search.SearchProvider; import org.gudy.azureus2.plugins.utils.search.SearchResult; import com.aelitis.azureus.core.metasearch.*; import com.aelitis.azureus.core.metasearch.impl.*; public class PluginEngine extends EngineImpl { private static int[][] FIELD_MAP = { { SearchResult.PR_CATEGORY, Engine.FIELD_CATEGORY }, { SearchResult.PR_COMMENTS, Engine.FIELD_COMMENTS }, { SearchResult.PR_CONTENT_TYPE, Engine.FIELD_CONTENT_TYPE }, { SearchResult.PR_DETAILS_LINK, Engine.FIELD_CDPLINK }, { SearchResult.PR_DOWNLOAD_BUTTON_LINK, Engine.FIELD_DOWNLOADBTNLINK }, { SearchResult.PR_DOWNLOAD_LINK, Engine.FIELD_TORRENTLINK }, { SearchResult.PR_DRM_KEY, Engine.FIELD_DRMKEY }, { SearchResult.PR_LEECHER_COUNT, Engine.FIELD_PEERS }, { SearchResult.PR_NAME, Engine.FIELD_NAME }, { SearchResult.PR_PLAY_LINK, Engine.FIELD_PLAYLINK }, { SearchResult.PR_PRIVATE, Engine.FIELD_PRIVATE }, { SearchResult.PR_PUB_DATE, Engine.FIELD_DATE }, { SearchResult.PR_SEED_COUNT, Engine.FIELD_SEEDS }, { SearchResult.PR_SIZE, Engine.FIELD_SIZE }, { SearchResult.PR_SUPER_SEED_COUNT, Engine.FIELD_SUPERSEEDS }, { SearchResult.PR_VOTES, Engine.FIELD_VOTES }, }; public static EngineImpl importFromBEncodedMap( MetaSearchImpl meta_search, Map map ) throws IOException { return( new PluginEngine( meta_search, map )); } private SearchProvider provider; public PluginEngine( MetaSearchImpl _meta_search, long _id, SearchProvider _provider ) { super( _meta_search, Engine.ENGINE_TYPE_PLUGIN, _id, 0, (String)_provider.getProperty( SearchProvider.PR_NAME )); provider = _provider; setSource( ENGINE_SOURCE_LOCAL ); } protected PluginEngine( MetaSearchImpl _meta_search, Map _map ) throws IOException { super( _meta_search, _map ); setSource( ENGINE_SOURCE_LOCAL ); } public Map exportToBencodedMap() throws IOException { Map res = new HashMap(); super.exportToBencodedMap( res ); return( res ); } public void setProvider( SearchProvider _provider ) { provider = _provider; } protected boolean useAccuracyForRank() { if ( provider == null ){ return( false ); } Boolean val = (Boolean)provider.getProperty( SearchProvider.PR_USE_ACCURACY_FOR_RANK ); if ( val == null ){ return( false ); } return( val.booleanValue()); } public boolean isActive() { return( provider != null && super.isActive()); } public String getNameEx() { return( super.getName() + ": (plugin)" ); } public String getDownloadLinkCSS() { if ( provider == null ){ return( null ); } return((String)provider.getProperty( SearchProvider.PR_DOWNLOAD_LINK_LOCATOR )); } public boolean supportsField( int field ) { if ( provider == null ){ return( false ); } int[] supports = (int[])provider.getProperty( SearchProvider.PR_SUPPORTS_RESULT_FIELDS ); if ( supports == null ){ return( true ); } for (int i=0;i results = new ArrayList(); final AESemaphore sem = new AESemaphore( "waiter" ); provider.search( search_parameters, new SearchObserver() { private boolean complete = false; public void resultReceived( SearchInstance search, SearchResult result ) { PluginResult p_result = new PluginResult( PluginEngine.this, result, f_term ); synchronized( this ){ if ( complete ){ return; } results.add( p_result ); } if ( listener != null ){ listener.resultsReceived( PluginEngine.this, new Result[]{ p_result }); } synchronized( this ){ if ( absolute_max_matches >= 0 && results.size() >= absolute_max_matches ){ complete = true; sem.release(); } } } public void cancelled() { sem.release(); } public void complete() { sem.release(); } public Object getProperty( int property ) { if ( property == PR_MAX_RESULTS_WANTED ){ return( new Long( desired_max_matches )); } return( null ); } }); sem.reserve(); if ( listener != null ){ listener.resultsComplete( this ); } return((Result[])results.toArray(new Result[results.size()])); }catch( Throwable e ){ throw( new SearchException( "Search failed", e )); } } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/plugin/PluginResult.java0000644000175000017500000001513711306117602027353 0ustar adrianadrian/* * Created on Jun 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.impl.plugin; import java.util.Date; import java.util.Map; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.LightHashMap; import org.gudy.azureus2.plugins.utils.search.SearchResult; import com.aelitis.azureus.core.metasearch.*; public class PluginResult extends Result { private static final Object NULL_OBJECT = PluginResult.class; private SearchResult result; private String search_term; private Map property_cache = new LightHashMap(); protected PluginResult( PluginEngine _engine, SearchResult _result, String _search_term ) { super( _engine ); result = _result; search_term = _search_term; } public Date getPublishedDate() { return((Date)getResultProperty( SearchResult.PR_PUB_DATE )); } public String getCategory() { return(getStringProperty( SearchResult.PR_CATEGORY )); } public void setCategory( String category ) { } public String getContentType() { return(getStringProperty( SearchResult.PR_CONTENT_TYPE )); } public void setContentType( String contentType ) { } public String getName() { return(getStringProperty( SearchResult.PR_NAME )); } public long getSize() { return(getLongProperty( SearchResult.PR_SIZE )); } public int getNbPeers() { return(getIntProperty( SearchResult.PR_LEECHER_COUNT )); } public int getNbSeeds() { return(getIntProperty( SearchResult.PR_SEED_COUNT )); } public int getNbSuperSeeds() { return(getIntProperty( SearchResult.PR_SUPER_SEED_COUNT )); } public int getComments() { return(getIntProperty( SearchResult.PR_COMMENTS )); } public int getVotes() { return(getIntProperty( SearchResult.PR_VOTES )); } public int getVotesDown() { return(getIntProperty( SearchResult.PR_VOTES_DOWN )); } public boolean isPrivate() { return( getBooleanProperty( SearchResult.PR_PRIVATE )); } public String getDRMKey() { return(getStringProperty( SearchResult.PR_DRM_KEY )); } public String getDownloadLink() { return(getStringProperty( SearchResult.PR_DOWNLOAD_LINK )); } public String getDownloadButtonLink() { return(getStringProperty( SearchResult.PR_DOWNLOAD_BUTTON_LINK )); } public String getCDPLink() { return( getStringProperty( SearchResult.PR_DETAILS_LINK )); } public String getPlayLink() { return(getStringProperty( SearchResult.PR_PLAY_LINK )); } public String getUID() { return(getStringProperty( SearchResult.PR_UID )); } public String getHash() { byte[] hash = getByteArrayProperty( SearchResult.PR_HASH ); if ( hash == null ){ return( null ); } return( Base32.encode( hash )); } public float getRank() { if (((PluginEngine)getEngine()).useAccuracyForRank()){ return( applyRankBias( getAccuracy())); } long l_rank = getLongProperty( SearchResult.PR_RANK ); // if we have seeds/peers just use the usual mechanism if ( getLongProperty( SearchResult.PR_SEED_COUNT ) >= 0 && getLongProperty( SearchResult.PR_LEECHER_COUNT ) >= 0 ){ l_rank = Long.MIN_VALUE; } if ( l_rank == Long.MIN_VALUE ){ return( super.getRank()); } float rank = l_rank; if ( rank > 100 ){ rank = 100; }else if ( rank < 0 ){ rank = 0; } return( applyRankBias( rank / 100 )); } public float getAccuracy() { long l_accuracy = getLongProperty( SearchResult.PR_ACCURACY ); if ( l_accuracy == Long.MIN_VALUE ){ return( -1 ); } float accuracy = l_accuracy; if ( accuracy > 100 ){ accuracy = 100; }else if ( accuracy < 0 ){ accuracy = 0; } return( accuracy / 100 ); } public String getSearchQuery() { return( search_term ); } protected int getIntProperty( int name ) { return((int)getLongProperty( name )); } protected long getLongProperty( int name ) { return( getLongProperty( name, Long.MIN_VALUE )); } protected long getLongProperty( int name, long def ) { try{ Long l = (Long)getResultProperty( name ); if ( l == null ){ return( def ); } return( l.longValue()); }catch( Throwable e ){ Debug.out( "Invalid value returned for Long property " + name ); return( def ); } } protected boolean getBooleanProperty( int name ) { return( getBooleanProperty( name, false )); } protected boolean getBooleanProperty( int name, boolean def ) { try{ Boolean b = (Boolean)getResultProperty( name ); if ( b == null ){ return( def ); } return( b.booleanValue()); }catch( Throwable e ){ Debug.out( "Invalid value returned for Boolean property " + name ); return( def ); } } protected String getStringProperty( int name ) { return( getStringProperty( name, "" )); } protected String getStringProperty( int name, String def ) { try{ String l = (String)getResultProperty( name ); if ( l == null ){ return( def ); } return( l ); }catch( Throwable e ){ Debug.out( "Invalid value returned for String property " + name ); return( def ); } } protected byte[] getByteArrayProperty( int name ) { try{ return((byte[])getResultProperty( name )); }catch( Throwable e ){ Debug.out( "Invalid value returned for byte[] property " + name ); return( null ); } } protected synchronized Object getResultProperty( int prop ) { Integer i_prop = new Integer( prop ); Object res = property_cache.get( i_prop ); if ( res == null ){ res = result.getProperty( prop ); if ( res == null ){ res = NULL_OBJECT; } property_cache.put( i_prop, res ); } if ( res == NULL_OBJECT ){ return( null ); } return( res ); } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/ExternalLoginWindow.java0000644000175000017500000002245311275141740027367 0ustar adrianadrianpackage com.aelitis.azureus.core.metasearch.impl; import java.util.*; import java.net.URL; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.ProgressEvent; import org.eclipse.swt.browser.ProgressListener; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.shell.ShellFactory; import org.gudy.azureus2.ui.swt.progress.ProgressWindow; import com.aelitis.azureus.core.metasearch.impl.web.WebEngine; import com.aelitis.azureus.core.util.http.HTTPAuthHelper; import com.aelitis.azureus.core.util.http.HTTPAuthHelperListener; import com.aelitis.azureus.ui.swt.browser.CookiesListener; import com.aelitis.azureus.ui.swt.browser.listener.ExternalLoginCookieListener; public class ExternalLoginWindow { Display display; Shell shell; Browser browser; ExternalLoginListener listener; String originalLoginUrl; Map cookies = new HashMap(); Set sniffer_cookies = new HashSet(); Set js_cookies = new HashSet(); HTTPAuthHelper sniffer; public ExternalLoginWindow( ExternalLoginListener _listener, String name, final String _loginUrl, boolean captureMode, String authMode, boolean isMine ) { listener = _listener; originalLoginUrl = _loginUrl; shell = ShellFactory.createMainShell(SWT.TITLE | SWT.CLOSE); shell.setSize(800,600); Utils.centreWindow(shell); display = shell.getDisplay(); shell.setText(MessageText.getString("externalLogin.title")); shell.setLayout(new FormLayout()); shell.addDisposeListener( new DisposeListener() { public void widgetDisposed( DisposeEvent arg0) { if ( sniffer != null ){ sniffer.destroy(); } } }); Label explain = new Label(shell,SWT.WRAP); if(captureMode) { explain.setText(MessageText.getString("externalLogin.explanation.capture", new String[]{ name })); } else { explain.setText(MessageText.getString("externalLogin.explanation", new String[]{ name })); } browser = Utils.createSafeBrowser(shell, SWT.BORDER); if (browser == null) { shell.dispose(); return; } final ExternalLoginCookieListener cookieListener = new ExternalLoginCookieListener(new CookiesListener() { public void cookiesFound(String cookies){ foundCookies( cookies, true ); } },browser); cookieListener.hook(); Label separator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL); Button alt_method = null; if ( isMine ){ alt_method = new Button(shell,SWT.CHECK); final Button f_alt_method = alt_method; alt_method.setText(MessageText.getString("externalLogin.auth_method_proxy")); alt_method.setSelection( authMode == WebEngine.AM_PROXY ); alt_method.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { setCaptureMethod( browser, !f_alt_method.getSelection(), true ); } }); } setCaptureMethod( browser, authMode == WebEngine.AM_TRANSPARENT, true ); Button cancel = new Button(shell,SWT.PUSH); cancel.setText(MessageText.getString("Button.cancel")); Button done = new Button(shell,SWT.PUSH); done.setText(MessageText.getString("Button.done")); cancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { if(listener != null) { listener.canceled(ExternalLoginWindow.this); } shell.dispose(); } }); done.addListener(SWT.Selection, new Listener() { public void handleEvent(Event arg0) { if(listener != null) { listener.done(ExternalLoginWindow.this,cookiesToString()); } shell.dispose(); } }); FormData data; data = new FormData(); data.left = new FormAttachment(0,5); data.right = new FormAttachment(100,-5); data.top = new FormAttachment(0,5); explain.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0,5); data.right = new FormAttachment(100,-5); data.top = new FormAttachment(explain,5); data.bottom = new FormAttachment(separator,-5); browser.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0,0); data.right = new FormAttachment(100,0); data.bottom = new FormAttachment(cancel,-5); separator.setLayoutData(data); if ( isMine ){ data = new FormData(); data.width = 100; data.left = new FormAttachment(0,5); data.right = new FormAttachment(cancel,-5); data.bottom = new FormAttachment(100,-5); alt_method.setLayoutData(data); } data = new FormData(); data.width = 100; data.right = new FormAttachment(done,-5); data.bottom = new FormAttachment(100,-5); cancel.setLayoutData(data); data = new FormData(); data.width = 100; data.right = new FormAttachment(100,-5); data.bottom = new FormAttachment(100,-5); done.setLayoutData(data); shell.layout(); shell.open(); } protected void setCaptureMethod( final Browser browser, boolean transparent, boolean show_progress ) { if ( sniffer != null ){ sniffer.destroy(); sniffer = null; } if ( show_progress ){ final ProgressWindow prog_wind = new ProgressWindow( shell, "externalLogin.wait", SWT.DIALOG_TRIM, 500 ); browser.addProgressListener( new ProgressListener() { public void changed( ProgressEvent arg0 ) { } public void completed( ProgressEvent arg0 ) { if (browser.isDisposed() || browser.getShell().isDisposed()) { return; } browser.removeProgressListener( this ); prog_wind.destroy(); } }); } if ( transparent ){ browser.setUrl( originalLoginUrl ); }else{ try{ final HTTPAuthHelper this_sniffer = sniffer = new HTTPAuthHelper( new URL( originalLoginUrl )); this_sniffer.addListener( new HTTPAuthHelperListener() { public void cookieFound( HTTPAuthHelper helper, String cookie_name, String cookie_value ) { if ( helper == this_sniffer ){ foundCookies( cookie_name + "=" + cookie_value, false ); } } }); this_sniffer.start(); String str = originalLoginUrl.toString(); int pos = str.indexOf( "://" ); str = str.substring( pos+3 ); pos = str.indexOf( "/" ); if ( pos != -1 ){ str = str.substring( pos ); } if ( !str.startsWith( "/" )){ str = "/" + str; } browser.setUrl( "http://localhost:" + sniffer.getPort() + str ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } protected void foundCookies( String _cookies, boolean _from_js ) { String[] x = _cookies.split( ";" ); synchronized( cookies ){ for (int i=0;i properties = new HashMap(); bits = XUXmlWriter.splitWithEscape( properties_str, ',' ); for ( int i=0; i vuze_selected_ids = new HashMap(); Map vuze_preload_ids = new HashMap(); Set featured_ids = new HashSet(); Set popular_ids = new HashSet(); Set manual_vuze_ids = new HashSet(); boolean auto_mode = isAutoMode(); Engine[] engines = meta_search.getEngines( false, false ); try{ PlatformMetaSearchMessenger.templateInfo[] featured = PlatformMetaSearchMessenger.listFeaturedTemplates(); String featured_str = ""; for (int i=0;i 0 ){ log( "Pre-load templates: " + popular_str ); } } // pick up explicitly selected vuze ones String manual_str = ""; for (int i=0;i 0 ){ long[] manual_ids = new long[manual_vuze_ids.size()]; Iterator it = manual_vuze_ids.iterator(); int pos = 0; while( it.hasNext()){ manual_ids[pos++] = it.next().longValue(); } PlatformMetaSearchMessenger.templateInfo[] manual = PlatformMetaSearchMessenger.getTemplateDetails( manual_ids ); for (int i=0;i existing_engine_map = new HashMap(); String existing_str = ""; for (int i=0;i> it = vuze_selected_ids.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = it.next(); vuze_preload_ids.remove( entry.getKey()); long id = entry.getKey().longValue(); PlatformMetaSearchMessenger.templateInfo template = entry.getValue(); long modified = template.getModifiedDate(); Engine this_engine = (Engine)existing_engine_map.get( new Long(id)); boolean update = this_engine == null || this_engine.getLastUpdated() < modified; if ( update ){ PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( id ); log( "Downloading definition of template " + id ); log( details.getValue()); if ( details.isVisible()){ try{ this_engine = meta_search.importFromJSONString( details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX, details.getId(), details.getModifiedDate(), details.getRankBias(), details.getName(), details.getValue()); this_engine.setSource( Engine.ENGINE_SOURCE_VUZE ); meta_search.addEngine( this_engine ); }catch( Throwable e ){ log( "Failed to import engine '" + details.getValue() + "'", e ); } } }else if ( this_engine.getRankBias() != template.getRankBias()){ this_engine.setRankBias( template.getRankBias()); log( "Updating rank bias for " + this_engine.getString() + " to " + template.getRankBias()); }else{ log( "Not updating " + this_engine.getString() + " as unchanged" ); } if ( this_engine != null ){ if ( this_engine.getSelectionState() == Engine.SEL_STATE_DESELECTED ){ log( "Auto-selecting " + this_engine.getString()); this_engine.setSelectionState( Engine.SEL_STATE_AUTO_SELECTED ); } } } // do any pre-loads it = vuze_preload_ids.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = it.next(); long id = ((Long)entry.getKey()).longValue(); Engine this_engine = (Engine)existing_engine_map.get( new Long(id)); if ( this_engine == null ){ PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( id ); log( "Downloading pre-load definition of template " + id ); log( details.getValue()); if ( details.isVisible()){ try{ this_engine = meta_search.importFromJSONString( details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX, details.getId(), details.getModifiedDate(), details.getRankBias(), details.getName(), details.getValue()); this_engine.setSource( Engine.ENGINE_SOURCE_VUZE ); this_engine.setSelectionState( Engine.SEL_STATE_DESELECTED ); meta_search.addEngine( this_engine ); }catch( Throwable e ){ log( "Failed to import engine '" + details.getValue() + "'", e ); } } } } // deselect any not in use for (int i=0;i engine_map = new HashMap(); for( int i=0;i selected_engine_set = new HashSet(); for (int i=0;i= 0 && id < Integer.MAX_VALUE ){ id = getLocalTemplateID(); engine.setId( id ); } engine.setSource( Engine.ENGINE_SOURCE_LOCAL ); engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED ); meta_search.addEngine( engine ); if ( warn_user ){ UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 ); String details = MessageText.getString( "metasearch.addtemplate.done.desc", new String[]{ engine.getName() }); ui_manager.showMessageBox( "metasearch.addtemplate.done.title", "!" + details + "!", UIManagerEvent.MT_OK ); } return( engine ); }catch( Throwable e ){ if ( warn_user ){ UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 ); String details = MessageText.getString( "metasearch.addtemplate.failed.desc", new String[]{ Debug.getNestedExceptionMessage(e) }); ui_manager.showMessageBox( "metasearch.addtemplate.failed.title", "!" + details + "!", UIManagerEvent.MT_OK ); } throw( new MetaSearchException( "Failed to add engine", e )); } } public Engine[] loadFromVuzeFile( File file ) { VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile( file.getAbsolutePath()); if ( vf != null ){ return( loadFromVuzeFile( vf )); } return( new Engine[0]); } public Engine[] loadFromVuzeFile( VuzeFile vf ) { List result = new ArrayList(); VuzeFileComponent[] comps = vf.getComponents(); for (int j=0;j 0 ){ return( false ); } return( true ); } } protected static class resultWrapper implements SearchResult { private Result result; protected resultWrapper( Result _result ) { result = _result; } public Object getProperty( int property_name ) { switch( property_name ){ case PR_NAME:{ return( result.getName()); } case PR_PUB_DATE:{ return( result.getPublishedDate()); } case PR_SIZE:{ return( result.getSize()); } case PR_LEECHER_COUNT:{ return( new Long( result.getNbPeers())); } case PR_SEED_COUNT:{ return( new Long( result.getNbSeeds())); } case PR_SUPER_SEED_COUNT:{ return( new Long( result.getNbSuperSeeds())); } case PR_CATEGORY:{ return( result.getCategory()); } case PR_COMMENTS:{ return( new Long( result.getComments())); } case PR_VOTES:{ return( new Long( result.getVotes())); } case PR_CONTENT_TYPE:{ return( result.getContentType()); } case PR_DETAILS_LINK:{ return( result.getCDPLink()); } case PR_DOWNLOAD_LINK:{ return( result.getDownloadLink()); } case PR_PLAY_LINK:{ return( result.getPlayLink()); } case PR_PRIVATE:{ return( result.isPrivate()); } case PR_DRM_KEY:{ return( result.getDRMKey()); } case PR_DOWNLOAD_BUTTON_LINK:{ return( result.getDownloadButtonLink()); } case PR_RANK:{ float rank = result.getRank(); return( new Long(rank==-1?-1:(long)( rank * 100 ))); } case PR_ACCURACY:{ float accuracy = result.getAccuracy(); return( new Long(accuracy==-1?-1:(long)( accuracy * 100 ))); } case PR_VOTES_DOWN:{ return( new Long( result.getVotesDown())); } case PR_UID:{ return( result.getUID()); } case PR_HASH:{ String base32_hash = result.getHash(); if ( base32_hash != null ){ return( Base32.decode( base32_hash )); } return( null ); } default:{ Debug.out( "Unknown property type " + property_name ); } } return( null ); } } } protected static class engineInfo implements SearchProvider { private Engine engine; private boolean complete; protected engineInfo( Engine _engine ) { engine = _engine; } protected void setComplete() { complete = true; } protected boolean isComplete() { return( complete ); } public SearchInstance search( Map search_parameters, SearchObserver observer ) throws SearchException { throw( new SearchException( "Not supported" )); } public Object getProperty( int property ) { if ( property == PR_ID ){ return( engine.getId()); }else if ( property == PR_NAME ){ return( engine.getName()); }else{ return( null ); } } public void setProperty( int property, Object value ) { Debug.out( "Not supported" ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/EngineImpl.java0000644000175000017500000007540211310044600025440 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.impl; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.net.URLDecoder; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.BEncoder; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.RandomUtils; import org.gudy.azureus2.core3.util.UrlUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import com.aelitis.azureus.core.messenger.config.PlatformMetaSearchMessenger; import com.aelitis.azureus.core.metasearch.Engine; import com.aelitis.azureus.core.metasearch.Result; import com.aelitis.azureus.core.metasearch.ResultListener; import com.aelitis.azureus.core.metasearch.SearchException; import com.aelitis.azureus.core.metasearch.SearchLoginException; import com.aelitis.azureus.core.metasearch.SearchParameter; import com.aelitis.azureus.core.metasearch.impl.plugin.PluginEngine; import com.aelitis.azureus.core.metasearch.impl.web.json.JSONEngine; import com.aelitis.azureus.core.metasearch.impl.web.regex.RegexEngine; import com.aelitis.azureus.core.metasearch.impl.web.rss.RSSEngine; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.core.vuzefile.VuzeFileComponent; import com.aelitis.azureus.core.vuzefile.VuzeFileHandler; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.ImportExportUtils; import com.aelitis.azureus.util.JSONUtils; public abstract class EngineImpl implements Engine { private static final int DEFAULT_UPDATE_CHECK_SECS = 24*60*60; private static boolean logging_enabled; static{ COConfigurationManager.addAndFireParameterListeners( new String[]{ "Logger.Enabled", }, new ParameterListener() { public void parameterChanged( String parameterName) { logging_enabled = COConfigurationManager.getBooleanParameter( "Logger.Enabled" ); } }); } protected static EngineImpl importFromBEncodedMap( MetaSearchImpl meta_search, Map map ) throws IOException { int type = ((Long)map.get( "type" )).intValue(); if ( type == Engine.ENGINE_TYPE_JSON ){ return( JSONEngine.importFromBEncodedMap( meta_search, map )); }else if ( type == Engine.ENGINE_TYPE_REGEX ){ return( RegexEngine.importFromBEncodedMap( meta_search, map )); }else if ( type == Engine.ENGINE_TYPE_PLUGIN ){ return( PluginEngine.importFromBEncodedMap( meta_search, map )); }else if ( type == Engine.ENGINE_TYPE_RSS ){ return( RSSEngine.importFromBEncodedMap( meta_search, map )); }else{ throw( new IOException( "Unknown engine type " + type )); } } public static Engine importFromJSONString( MetaSearchImpl meta_search, int type, long id, long last_updated, String name, String content ) throws IOException { JSONObject map = (JSONObject)JSONUtils.decodeJSON( content ); if ( type == Engine.ENGINE_TYPE_JSON ){ return( JSONEngine.importFromJSONString( meta_search, id, last_updated, name, map )); }else if ( type == Engine.ENGINE_TYPE_REGEX ){ return( RegexEngine.importFromJSONString( meta_search, id, last_updated, name, map )); }else if ( type == Engine.ENGINE_TYPE_RSS ){ return( RSSEngine.importFromJSONString( meta_search, id, last_updated, name, map )); }else{ throw( new IOException( "Unknown engine type " + type )); } } // if you extend this with state pertaining to what has been downloaded then // make sure you extend the code in reset(); protected static final String LD_COOKIES = "cookies"; protected static final String LD_ETAG = "etag"; protected static final String LD_LAST_MODIFIED = "last_mod"; protected static final String LD_LAST_UPDATE_CHECK = "last_update_check"; protected static final String LD_UPDATE_CHECK_SECS = "update_check_secs"; protected static final String LD_CREATED_BY_ME = "mine"; protected static final String LD_AUTO_DL_SUPPORTED = "auto_dl_supported"; protected static final String LD_LINK_IS_TORRENT = "link_is_torrent"; private MetaSearchImpl meta_search; private int type; private long id; private long last_updated; private String name; private byte[] uid; private int version; private boolean is_public = true; private int az_version; private int selection_state = SEL_STATE_DESELECTED; private boolean selection_state_recorded = true; private int source = ENGINE_SOURCE_UNKNOWN; private float rank_bias = 1; private float preferred_count = 0; // first mappings used to canonicalise names and map field to same field // typically used for categories (musak->music) private List first_level_mapping = new ArrayList(); // second mappings used to generate derived field values // typically used to derive content_type from category (music->AUDIO) private List second_level_mapping = new ArrayList(); // applicable to non-vuze hosted templates private String update_url; private int update_check_default_secs; private Map user_data; // manual constructor protected EngineImpl( MetaSearchImpl _meta_search, int _type, long _id, long _last_updated, String _name ) { meta_search = _meta_search; type = _type; id = _id; last_updated = _last_updated; name = _name; version = 1; az_version = AZ_VERSION; allocateUID( id ); } // bencoded constructor protected EngineImpl( MetaSearchImpl _meta_search, Map map ) throws IOException { meta_search = _meta_search; type = ((Long)map.get( "type" )).intValue(); id = ((Long)map.get( "id")).longValue(); last_updated = ImportExportUtils.importLong( map, "last_updated" ); name = ImportExportUtils.importString( map, "name" ); selection_state = (int)ImportExportUtils.importLong( map, "selected", SEL_STATE_DESELECTED ); selection_state_recorded = ImportExportUtils.importBoolean(map,"select_rec", true ); source = (int)ImportExportUtils.importLong( map, "source", ENGINE_SOURCE_UNKNOWN ); rank_bias = ImportExportUtils.importFloat( map, "rank_bias", 1.0f ); preferred_count = ImportExportUtils.importFloat( map, "pref_count", 0.0f ); first_level_mapping = importBEncodedMappings( map, "l1_map" ); second_level_mapping = importBEncodedMappings( map, "l2_map" ); version = (int)ImportExportUtils.importLong( map, "version", 1 ); az_version = (int)ImportExportUtils.importLong( map, "az_version", AZ_VERSION ); if ( az_version > AZ_VERSION ){ throw( new IOException( MessageText.getString("metasearch.template.version.bad", new String[]{ name }))); } uid = (byte[])map.get( "uid" ); if ( uid == null ){ allocateUID( id ); } update_url = ImportExportUtils.importString( map, "update_url" ); update_check_default_secs = (int)ImportExportUtils.importLong( map, "update_url_check_secs", DEFAULT_UPDATE_CHECK_SECS ); } // bencoded export protected void exportToBencodedMap( Map map ) throws IOException { map.put( "type", new Long( type )); map.put( "id", new Long( id )); map.put( "last_updated", new Long( last_updated )); ImportExportUtils.exportString( map, "name", name ); map.put( "selected", new Long( selection_state )); ImportExportUtils.exportBoolean( map, "select_rec", selection_state_recorded ); map.put( "source", new Long( source )); ImportExportUtils.exportFloat( map, "rank_bias", rank_bias ); ImportExportUtils.exportFloat( map, "pref_count", preferred_count ); exportBEncodedMappings( map, "l1_map", first_level_mapping ); exportBEncodedMappings( map, "l2_map", second_level_mapping ); map.put( "version", new Long( version )); map.put( "az_version", new Long( az_version )); map.put( "uid", uid ); if ( update_url != null ){ ImportExportUtils.exportString( map, "update_url", update_url ); } map.put( "update_url_check_secs", new Long( update_check_default_secs )); } // json constructor protected EngineImpl( MetaSearchImpl meta_search, int type, long id, long last_updated, String name, JSONObject map ) throws IOException { this( meta_search, type, id, last_updated, name ); first_level_mapping = importJSONMappings( map, "value_map", true ); second_level_mapping = importJSONMappings( map, "ctype_map", false ); version = (int)ImportExportUtils.importLong( map, "version", 1 ); az_version = (int)ImportExportUtils.importLong( map, "az_version", AZ_VERSION ); if ( az_version > AZ_VERSION ){ throw( new IOException( MessageText.getString( "metasearch.template.version.bad", new String[]{ name }))); } String uid_str = (String)map.get( "uid" ); if ( uid_str == null ){ allocateUID( id ); }else{ uid = Base32.decode( uid_str ); } update_url = ImportExportUtils.importString( map, "update_url" ); update_check_default_secs = (int)ImportExportUtils.importLong( map, "update_url_check_secs", DEFAULT_UPDATE_CHECK_SECS ); } // json export protected void exportToJSONObject( JSONObject res ) throws IOException { exportJSONMappings( res, "value_map", first_level_mapping, true ); exportJSONMappings( res, "ctype_map", second_level_mapping, false ); res.put( "version", new Long( version )); res.put( "az_version", new Long( az_version )); res.put( "uid", Base32.encode( uid )); if ( update_url != null ){ ImportExportUtils.exportJSONString( res, "update_url", update_url ); } res.put( "update_url_check_secs", new Long( update_check_default_secs )); } protected List importJSONMappings( JSONObject map, String str, boolean level_1 ) throws IOException { List result = new ArrayList(); JSONObject field_map = (JSONObject)map.get( str ); if ( field_map != null ){ Iterator it = field_map.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); String key = (String)entry.getKey(); List mappings = (List)entry.getValue(); // limited support for the moment: // level one always maps to same field // level two always maps to content type int from_field = vuzeFieldToID( key ); if ( from_field == -1 ){ log( "Unrecognised remapping key '" + key + "'" ); continue; } int to_field = level_1?from_field:FIELD_CONTENT_TYPE; List frs_l = new ArrayList(); for (int i=0;i= 0 && id < Integer.MAX_VALUE ){ // id is a vuze one, derive uid from it as already unique uid[0] = (byte)(id>>24); uid[1] = (byte)(id>>16); uid[2] = (byte)(id>>8); uid[3] = (byte)id; }else{ RandomUtils.nextSecureBytes( uid ); configDirty(); } } public boolean sameLogicAs( Engine other ) { try{ Map m1 = exportToBencodedMap(); Map m2 = other.exportToBencodedMap(); String[] to_remove = { "type", "id", "last_updated", "selected", "select_rec", "source", "rank_bias", "pref_count", "version", "az_version", "uid" }; for (int i=0;i results_informed = new HashSet(); final boolean[] complete_informed = { false }; ResultListener interceptor = new ResultListener() { public void contentReceived( Engine engine, String content ) { listener.contentReceived(engine, content); } public void matchFound( Engine engine, String[] fields ) { listener.matchFound(engine, fields); } public void resultsReceived( Engine engine, Result[] results ) { listener.resultsReceived(engine, results); synchronized( results_informed ){ results_informed.addAll( Arrays.asList( results )); } } public void resultsComplete( Engine engine) { listener.resultsComplete(engine); synchronized( results_informed ){ complete_informed[0] = true; } } public void engineFailed( Engine engine, Throwable cause ) { listener.engineFailed(engine, cause); } public void engineRequiresLogin( Engine engine, Throwable cause ) { listener.engineRequiresLogin(engine, cause); } }; Result[] results = searchAndMap( params, context, desired_max_matches, absolute_max_matches, headers, listener==null?null:interceptor ); if ( listener != null ){ boolean inform_complete; List inform_result = new ArrayList(); synchronized( results_informed ){ for ( Result r: results ){ if ( !results_informed.contains( r )){ inform_result.add( r ); } } inform_complete = !complete_informed[0]; } if ( inform_result.size() > 0 ){ listener.resultsReceived( this, inform_result.toArray( new Result[ inform_result.size()] )); } if ( inform_complete ){ listener.resultsComplete( this ); } } return( results ); }catch( Throwable e ){ if ( e instanceof SearchLoginException ){ if ( listener != null ){ listener.engineRequiresLogin(this, e); } throw((SearchLoginException)e); }else if ( e instanceof SearchException ){ if ( listener != null ){ listener.engineFailed( this, e); } throw((SearchException)e); }else{ if ( listener != null ){ listener.engineFailed( this, e); } throw( new SearchException( "Search failed", e )); } } } protected Result[] searchAndMap( SearchParameter[] params, Map context, int desired_max_matches, int absolute_max_matches, String headers, final ResultListener listener ) throws SearchException { // default values context.put( Engine.SC_AZID, ConstantsVuze.AZID ); if ( context.get( Engine.SC_SOURCE ) == null ){ context.put( Engine.SC_SOURCE, "search" ); } Result[] results = searchSupport( params, context, desired_max_matches, absolute_max_matches, headers, new ResultListener() { public void contentReceived( Engine engine, String content ) { if ( listener != null ){ listener.contentReceived(engine, content); } } public void matchFound( Engine engine, String[] fields ) { if ( listener != null ){ listener.matchFound(engine, fields); } } public void resultsReceived( Engine engine, Result[] results) { if ( listener != null ){ listener.resultsReceived(engine, mapResults( results )); } } public void resultsComplete( Engine engine ) { if ( listener != null ){ listener.resultsComplete(engine); } } public void engineFailed( Engine engine, Throwable cause ) { log( "Search failed", cause ); if ( listener != null ){ listener.engineFailed(engine, cause); } } public void engineRequiresLogin( Engine engine, Throwable cause ) { log( "Search requires login", cause ); if ( listener != null ){ listener.engineRequiresLogin(engine, cause); } } }); return( mapResults( results )); } protected Result[] mapResults( Result[] results ) { for (int i=0;i " + result.toString()); } return result; } private Date parseDateInternal(String input) { if(input == null) { return null; } String s = input; Calendar calendar = new GregorianCalendar(timeZone); //Find if there is any time information in the date Matcher matcher = getTimeComponent.matcher(s); //Remove the time information in order to not confuse the date parsing s = matcher.replaceFirst("").trim(); // handle date with format "2009-01-12 at 03:36:38" by removing trailing " at"; if ( s.endsWith( " at" )){ s = s.substring(0,s.length()-3).trim(); } //Find if the date contains letters matcher = hasLettersPattern.matcher(s); if(matcher.find()) { //We have a date with letters, could be age-based or time based (with a literal month) //Try to determine if it is age-based or time-based matcher = isAgeBasedPattern.matcher(s); if(matcher.find()) { //Age Based date matcher = todayPattern.matcher(s); if(matcher.find()) { //Nothing to do for today as we base our initial date on the current one } else { matcher = yesterdayPattern.matcher(s); if(matcher.find()) { calendar.add(Calendar.DATE, -1); } else { //We're in the real "ago" case, let's remove " ago" if it's there s = s.replaceAll("ago","").trim(); matcher = agoSpacerPattern.matcher(s); s = matcher.replaceAll("$1 $2"); matcher = agoTimeRangePattern.matcher(s); boolean seenHoursAsLowerCaseH = false; while(matcher.find()) { String unit = matcher.group(2); if(unit.equals("h")) { seenHoursAsLowerCaseH = true; } String lUnit = unit.toLowerCase(); float value = Float.parseFloat(matcher.group(1)); int intValue = (int) value; if(lUnit.startsWith("sec")) { calendar.add(Calendar.SECOND, -intValue); } else if(lUnit.startsWith("min") || (unit.equals("m") && seenHoursAsLowerCaseH)) { calendar.add(Calendar.MINUTE, -intValue); int seconds = (int) ((value - intValue)*60f); calendar.add(Calendar.SECOND, -seconds); } else if(lUnit.startsWith("h")) { calendar.add(Calendar.HOUR_OF_DAY, -intValue); int seconds = (int) ((value - intValue)*3600f); calendar.add(Calendar.SECOND, -seconds); } else if(lUnit.startsWith("d")) { calendar.add(Calendar.DATE, -intValue); int seconds = (int) ((value - intValue)*86400f); calendar.add(Calendar.SECOND, -seconds); } else if(lUnit.startsWith("w")) { calendar.add(Calendar.WEEK_OF_YEAR, -intValue); //604800 seconds in a week int seconds = (int) ((value - intValue)*640800f); calendar.add(Calendar.SECOND, -seconds); } //The month case when m is not a minute else if(lUnit.startsWith("m")) { calendar.add(Calendar.MONTH, -intValue); //about 720 hours per month int hours = (int) ((value - intValue)*720f); calendar.add(Calendar.HOUR_OF_DAY, -hours); } else if(lUnit.startsWith("y")) { calendar.add(Calendar.YEAR, -intValue); //about 8760 hours per year int hours = (int) ((value - intValue)*8760); calendar.add(Calendar.HOUR_OF_DAY, -hours); } else { //System.out.println("Unit not matched : " + unit); } } } } //System.out.println(input + " > " + calendar.getTime()); } else { //Time based date //System.out.println("DL : " + s); matcher = timeBasedDateWithLettersPattern.matcher(s); if(matcher.find()) { int day = Integer.parseInt(matcher.group(1)); calendar.set(Calendar.DAY_OF_MONTH,day); String monthStr = " " + matcher.group(2).toLowerCase(); int month = -1; for(int i = 0 ; i < MONTHS_LIST.length ; i++) { if(MONTHS_LIST[i].indexOf(monthStr) != -1) { month = i; } } if(month > -1) { calendar.set(Calendar.MONTH,month); } boolean hasYear = matcher.group(3) != null; if(hasYear) { int year = Integer.parseInt(matcher.group(3)); if(year < 100) { year += 2000; } calendar.set(Calendar.YEAR,year); } calendar.set(Calendar.HOUR_OF_DAY,0); calendar.set(Calendar.MINUTE,0); calendar.set(Calendar.SECOND,0); calendar.set(Calendar.MILLISECOND,0); //System.out.println(input + " > " + calendar.getTime() + "( " + calendar.getTimeZone() + " )"); } else { matcher = timeBasedDateWithLettersPatternMonthFirst.matcher(s); if(matcher.find()) { int day = Integer.parseInt(matcher.group(2)); calendar.set(Calendar.DAY_OF_MONTH,day); String monthStr = " " + matcher.group(1).toLowerCase(); int month = -1; for(int i = 0 ; i < MONTHS_LIST.length ; i++) { if(MONTHS_LIST[i].indexOf(monthStr) != -1) { month = i; } } if(month > -1) { calendar.set(Calendar.MONTH,month); } boolean hasYear = matcher.group(3) != null; if(hasYear) { int year = Integer.parseInt(matcher.group(3)); if(year < 100) { year += 2000; } calendar.set(Calendar.YEAR,year); } calendar.set(Calendar.HOUR_OF_DAY,0); calendar.set(Calendar.MINUTE,0); calendar.set(Calendar.SECOND,0); calendar.set(Calendar.MILLISECOND,0); //System.out.println(input + " > " + calendar.getTime() + "( " + calendar.getTimeZone() + " )"); } else { System.err.println("Unparseable date : " + input); } } } } else { //We have a date with only numbers //System.out.println("DN : " + s );//+ "(" + input + ")"); //Let's assume a default order of m/d and switch if it doesn't make sense matcher = numbersOnlyDatePattern.matcher(s); if(matcher.find()) { try { String g1 = matcher.group(1); String g2 = matcher.group(2); String g3 = matcher.group(3); int i1 = Integer.parseInt(g1); int i2 = Integer.parseInt(g2); if(g3 != null) { int i3 = Integer.parseInt(g3); int day = i1; int month = i2; int year = i3; if(month > 12) { day = i2; month = i1; } if(year < 100) { year += 2000; } if(g1.length() == 4) { year = i1; day = i3; } calendar.set(Calendar.YEAR,year); calendar.set(Calendar.MONTH,month-1); calendar.set(Calendar.DAY_OF_MONTH,day); } else { //2 numbers only, we assume it's day and month int month = i1; int day = i2; if(month > 12) { day = i1; month = i2; } if(month > 12) { //TODO : fire an exception ? System.err.println("Unparseable date : " + input); } else { calendar.set(Calendar.MONTH, month-1); calendar.set(Calendar.DAY_OF_MONTH, day); } } calendar.set(Calendar.HOUR_OF_DAY,0); calendar.set(Calendar.MINUTE,0); calendar.set(Calendar.SECOND,0); calendar.set(Calendar.MILLISECOND,0); } catch (Exception e) { e.printStackTrace(); } } //System.out.println(input + " > " + calendar.getTime()); } //Extract the time information matcher = getTimeComponent.matcher(input); if(matcher.find()) { try { int hours = Integer.parseInt(matcher.group(1)); int minutes = Integer.parseInt(matcher.group(2)); calendar.set(Calendar.MINUTE,minutes); boolean amPMModifier = matcher.group(5) != null; boolean hasSeconds = matcher.group(4) != null; if(hasSeconds) { int seconds = Integer.parseInt(matcher.group(4)); calendar.set(Calendar.SECOND, seconds); } if(amPMModifier) { String amPm = matcher.group(5).trim().toLowerCase(); if(amPm.equals("am")) { calendar.set(Calendar.AM_PM,Calendar.AM); } else { calendar.set(Calendar.AM_PM,Calendar.PM); } calendar.set(Calendar.HOUR, hours); } else { calendar.set(Calendar.HOUR_OF_DAY, hours); } } catch(Exception e) { e.printStackTrace(); } } int nbBack = 0; Calendar calendarCompare = new GregorianCalendar(); // if(calendar.after(calendarCompare)) { // System.err.println("maintenant ici: "+calendarCompare.getTimeInMillis()+" -- "+calendarCompare.getTime()+" -- "+calendarCompare); // System.err.println("maintenant la bas: "+calendar.getTimeInMillis()+" -- "+calendar.getTime()+" -- "+calendar); // System.err.println("CALENDARS: after? " + calendar.after(calendarCompare) + " // before? " + calendar.before(calendarCompare)); // } while(calendar.after(calendarCompare) && nbBack++ < 50) { calendar.add(Calendar.YEAR, -1); } //calendar.setTimeZone(TimeZone.getDefault()); return calendar.getTime(); } public static void main(String args[]) { DEBUG = true; DateParserRegex dateParser = new DateParserRegex(); dateParser.parseDate("Today 05:34"); dateParser.parseDate("Y-Day 21:55"); dateParser.parseDate("07-25 2006"); dateParser.parseDate("02-01 02:53"); dateParser.parseDate("02-01 02:53 am"); dateParser.parseDate("02-01 02:53 pm"); dateParser.parseDate("03 Mar 2006"); dateParser.parseDate("0 minute ago"); dateParser.parseDate("3 hours ago"); dateParser.parseDate("2 days ago"); dateParser.parseDate("10 months ago"); dateParser.parseDate("45 mins ago"); dateParser.parseDate("Today"); dateParser.parseDate("Yesterday"); dateParser.parseDate("16.9w"); dateParser.parseDate("22.6h"); dateParser.parseDate("1.7d"); dateParser.parseDate("2d 7h"); dateParser.parseDate("1w"); dateParser.parseDate("1w 4d"); dateParser.parseDate("1mon 1w"); dateParser.parseDate("22.11."); // 22 nov dateParser.parseDate("22 Apr 08"); // dateParser.parseDate("3 months"); // dateParser.parseDate("1 day"); // dateParser.parseDate("3 weeks"); // dateParser.parseDate("1 year"); // dateParser.parseDate("4 hours ago"); // dateParser.parseDate("yesterday"); // dateParser.parseDate("2 days ago"); // dateParser.parseDate("1 month ago"); // dateParser.parseDate("2 months ago"); // dateParser.parseDate("06/18"); // 18 Jun dateParser.parseDate("02:10"); // at 2:10am today dateParser.parseDate("2005-02-26 20:55:10"); // dateParser.parseDate("2005-02-26 10:55:10 PM"); dateParser.parseDate("2005-02-26 10:55:10 AM"); dateParser.parseDate("25-04-08"); // dateParser.parseDate("142 Day(s) ago"); // dateParser.parseDate("6 Minute(s) ago"); // dateParser.parseDate("1 Hour(s) ago"); // dateParser.parseDate("1.4h"); // 1.4 hours ago dateParser.parseDate("3.5d"); // 3 and a half days ago dateParser.parseDate("392w"); // 392 weeks ago dateParser.parseDate("01st Mar"); // dateParser.parseDate("19th Apr"); // dateParser.parseDate("03rd Apr"); // dateParser.parseDate("2nd Apr"); // dateParser.parseDate("3rd Nov"); // dateParser.parseDate("04-28"); // dateParser.parseDate("2007-07-14"); // dateParser.parseDate("2008.04.28"); // dateParser.parseDate("16/04/08"); // dateParser.parseDate("20-Dec-07"); // dateParser.parseDate("2009-01-12 at 03:36:38" ); } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/FieldRemapping.java0000644000175000017500000000245011017365106026303 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.impl; import java.util.regex.Pattern; public class FieldRemapping { private String match_str; private Pattern match; private String replace; public FieldRemapping(String match, String replace) { this.match_str = match; this.match = Pattern.compile(match); this.replace =replace; } public String getMatchString() { return(match_str ); } public Pattern getMatch() { return match; } public String getReplacement() { return replace; } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/ExternalLoginListener.java0000644000175000017500000000043411051471636027702 0ustar adrianadrianpackage com.aelitis.azureus.core.metasearch.impl; public interface ExternalLoginListener { public void cookiesFound(ExternalLoginWindow window,String cookies); public void canceled(ExternalLoginWindow window); public void done(ExternalLoginWindow window,String cookies); } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/MetaSearchImpl.java0000644000175000017500000006762611310044600026260 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.impl; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AsyncDispatcher; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DelayedEvent; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.HashWrapper; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.core3.util.TimerEventPeriodic; import org.gudy.azureus2.plugins.utils.StaticUtilities; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory; import org.gudy.azureus2.plugins.utils.search.SearchProvider; import com.aelitis.azureus.core.messenger.config.PlatformMetaSearchMessenger; import com.aelitis.azureus.core.metasearch.*; import com.aelitis.azureus.core.metasearch.impl.plugin.PluginEngine; import com.aelitis.azureus.core.metasearch.impl.web.FieldMapping; import com.aelitis.azureus.core.metasearch.impl.web.WebEngine; import com.aelitis.azureus.core.metasearch.impl.web.regex.RegexEngine; import com.aelitis.azureus.core.metasearch.impl.web.rss.RSSEngine; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.core.vuzefile.VuzeFileHandler; public class MetaSearchImpl implements MetaSearch { private static final String CONFIG_FILE = "metasearch.config"; private MetaSearchManagerImpl manager; private CopyOnWriteList engines = new CopyOnWriteList(); private Map plugin_map = new HashMap(); private boolean config_dirty; private CopyOnWriteList listeners = new CopyOnWriteList(); private TimerEventPeriodic update_check_timer; private static final int UPDATE_CHECK_PERIOD = 15*60*1000; private static final int MIN_UPDATE_CHECK_SECS = 10*60; private Object MS_UPDATE_CONSEC_FAIL_KEY = new Object(); protected MetaSearchImpl( MetaSearchManagerImpl _manager ) { manager = _manager; loadConfig(); } protected MetaSearchImpl() { } public Engine importFromBEncodedMap( Map map ) throws IOException { return( EngineImpl.importFromBEncodedMap( this, map )); } public Engine importFromJSONString( int type, long id, long last_updated, float rank_bias, String name, String content ) throws IOException { return( EngineImpl.importFromJSONString( this, type, id, last_updated, name, content )); } public EngineImpl importFromPlugin( String pid, SearchProvider provider ) throws IOException { synchronized( this ){ Long l_id = plugin_map.get( pid ); long id; if ( l_id == null ){ id = manager.getLocalTemplateID(); plugin_map.put( pid, new Long( id )); configDirty(); }else{ id = l_id.longValue(); } EngineImpl engine = (EngineImpl)getEngine( id ); if ( engine == null ){ engine = new PluginEngine( this, id, provider ); engine.setSource( Engine.ENGINE_SOURCE_LOCAL ); engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED ); addEngine( engine ); }else{ if ( engine instanceof PluginEngine ){ ((PluginEngine)engine).setProvider( provider ); }else{ Debug.out( "Inconsistent: plugin must be a PluginEngine!" ); plugin_map.remove( pid ); removeEngine( engine ); throw( new IOException( "Inconsistent" )); } } return( engine ); } } public Engine createRSSEngine( String name, URL url ) throws MetaSearchException { EngineImpl engine = new RSSEngine( this, manager.getLocalTemplateID(), SystemTime.getCurrentTime(), name, url.toExternalForm(), false, WebEngine.AM_TRANSPARENT, null, new String[0] ); engine.setSource( Engine.ENGINE_SOURCE_RSS ); addEngine( engine, false ); log( "Created RSS engine '" + url + "'" ); return( engine ); } protected void enableUpdateChecks() { synchronized( this ){ if ( update_check_timer == null ){ update_check_timer = SimpleTimer.addPeriodicEvent( "MS:updater", UPDATE_CHECK_PERIOD, new TimerEventPerformer() { public void perform( TimerEvent event) { checkUpdates(); } }); } } } protected void checkUpdates() { Iterator it = engines.iterator(); while( it.hasNext()){ EngineImpl engine = (EngineImpl)it.next(); String update_url = engine.getUpdateURL(); if ( update_url != null ){ long now = SystemTime.getCurrentTime(); long last_check = engine.getLastUpdateCheck(); if ( last_check > now ){ last_check = now; engine.setLastUpdateCheck( now ); } long check_secs = engine.getUpdateCheckSecs(); if ( check_secs < MIN_UPDATE_CHECK_SECS ){ log( "Engine '" + engine.getName() + "': Update check period too small (" + check_secs + " secs) adjusting to " + MIN_UPDATE_CHECK_SECS + ": " + engine.getName()); check_secs = MIN_UPDATE_CHECK_SECS; } long check_millis = check_secs*1000; long next_check = last_check + check_millis; Object consec_fails_o = engine.getUserData( MS_UPDATE_CONSEC_FAIL_KEY ); int consec_fails = consec_fails_o==null?0:((Integer)consec_fails_o).intValue(); if ( consec_fails > 0 ){ next_check += ( UPDATE_CHECK_PERIOD << consec_fails ); } if ( next_check < now ){ if ( updateEngine( engine )){ consec_fails = 0; engine.setLastUpdateCheck( now ); }else{ consec_fails++; if ( consec_fails > 3 ){ consec_fails = 0; // skip to next scheduled update time engine.setLastUpdateCheck( now ); } } engine.setUserData( MS_UPDATE_CONSEC_FAIL_KEY, consec_fails==0?null:new Integer( consec_fails )); } } } } protected boolean updateEngine( EngineImpl engine ) { String update_url = engine.getUpdateURL(); int pos = update_url.indexOf('?'); if ( pos == -1 ){ update_url += "?"; }else{ update_url += "&"; } update_url += "az_template_uid=" + engine.getUID() + "&az_template_version=" + engine.getVersion() + "&az_version=" + Constants.AZUREUS_VERSION + "&az_locale=" + MessageText.getCurrentLocale().toString() + "&az_rand=" + Math.abs( new Random().nextLong()); log( "Engine " + engine.getName() + ": auto-update check via " + update_url ); try{ ResourceDownloaderFactory rdf = StaticUtilities.getResourceDownloaderFactory(); ResourceDownloader url_rd = rdf.create( new URL( update_url )); ResourceDownloader rd = rdf.getMetaRefreshDownloader( url_rd ); InputStream is = rd.download(); try{ Map map = BDecoder.decode( new BufferedInputStream( is )); log( " update check reply: " + map ); // reply is either "response" meaning "no update" and giving possibly changed update secs // or Vuze file with updated template Map response = (Map)map.get( "response" ); if ( response != null ){ Long update_secs = (Long)response.get( "update_url_check_secs" ); if ( update_secs == null ){ engine.setLocalUpdateCheckSecs( 0 ); }else{ int check_secs = update_secs.intValue(); if ( check_secs < MIN_UPDATE_CHECK_SECS ){ log( " update check secs for to small, min is " + MIN_UPDATE_CHECK_SECS); check_secs = MIN_UPDATE_CHECK_SECS; } engine.setLocalUpdateCheckSecs( check_secs ); } return( true ); }else{ VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile( map ); if ( vf == null ){ log( " failed to decode vuze file" ); return( false ); } Engine[] updated_engines = manager.loadFromVuzeFile( vf ); if ( updated_engines.length > 0 ){ String existing_uid = engine.getUID(); boolean found = false; String engine_str = ""; for (int i=0;i it = engines.iterator(); while( it.hasNext()){ Engine existing_engine = it.next(); if ( existing_engine.getId() == new_engine.getId()){ log( "Updating engine with same ID " + existing_engine.getId() + ": " + existing_engine.getName() + "/" + existing_engine.getUID()); it.remove(); new_engine.setUID( existing_engine.getUID()); if ( existing_engine.sameLogicAs( new_engine )){ new_engine.setVersion( existing_engine.getVersion()); }else{ new_engine.setVersion( existing_engine.getVersion() + 1 ); log( " new version=" + new_engine.getVersion()); } add_op = false; }else if ( existing_engine.getUID().equals( new_engine.getUID())){ log( "Removing engine with same UID " + existing_engine.getUID() + "(" + existing_engine.getName() + ")" ); it.remove(); } } engines.add( new_engine ); } if ( new_engine.getUpdateURL() != null ){ enableUpdateChecks(); } if ( !loading ){ log( "Engine '" + new_engine.getName() + "' added" ); saveConfig(); Iterator it = listeners.iterator(); while( it.hasNext()){ MetaSearchListener listener = it.next(); try{ if ( add_op ){ listener.engineAdded( new_engine ); }else{ listener.engineUpdated( new_engine ); } }catch( Throwable e ){ Debug.printStackTrace(e); } } } } public void removeEngine( Engine engine ) { if ( engines.remove((EngineImpl)engine )){ log( "Engine '" + engine.getName() + "' removed" ); saveConfig(); Iterator it = listeners.iterator(); while( it.hasNext()){ try{ it.next().engineRemoved( engine ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } } public Engine[] getEngines( boolean active_only, boolean ensure_up_to_date ) { if ( ensure_up_to_date ){ manager.ensureEnginesUpToDate(); } List l = engines.getList(); List result; if ( active_only ){ result = new ArrayList(); for (int i=0;i l = engines.getList(); for( int i=0;i l = engines.getList(); for( int i=0;i(), max_results_per_engine )); } public Engine[] search( final ResultListener original_listener, SearchParameter[] searchParameters, String headers, Map context, int max_results_per_engine ) { return( search( null, original_listener, searchParameters, headers, context, max_results_per_engine )); } public Engine[] search( Engine[] engines, final ResultListener listener, SearchParameter[] search_parameters, String headers, final int max_results_per_engine ) { return( search( engines, listener, search_parameters, headers, new HashMap(), max_results_per_engine )); } public void enginePreferred( Engine engine ) { Engine[] engines = getEngines( true, false ); int num_other_preferred = 0; for ( Engine e: engines ){ if ( e.getId() == engine.getId()){ e.setPreferredDelta( +1 ); }else{ if ( e.getPreferredWeighting() > 0 ){ num_other_preferred++; } } } if ( num_other_preferred > 0 ){ float negative_weighting = -1 / num_other_preferred; for ( Engine e: engines ){ if ( e.getId() != engine.getId() && e.getPreferredWeighting() > 0 ){ e.setPreferredDelta( negative_weighting ); } } } } public Engine[] search( Engine[] engines, final ResultListener original_listener, SearchParameter[] searchParameters, String headers, Map context, final int max_results_per_engine ) { String param_str = ""; for (int i=0;i" + param.getValue(); } String batch_millis_str = context.get( Engine.SC_BATCH_PERIOD ); final long batch_millis = batch_millis_str==null?0:Long.parseLong( batch_millis_str ); String rem_dups_str = context.get( Engine.SC_REMOVE_DUP_HASH ); final boolean rem_dups = rem_dups_str==null?false:rem_dups_str.equalsIgnoreCase( "true" ); ResultListener listener = new ResultListener() { // single thread listener calls private AsyncDispatcher dispatcher = new AsyncDispatcher( 5000 ); final private Map> pending_results = new HashMap>(); final private Map> result_hashes = new HashMap>(); public void contentReceived( final Engine engine, final String content ) { dispatcher.dispatch( new AERunnable() { public void runSupport() { original_listener.contentReceived( engine, content ); } }); } public void matchFound( final Engine engine, final String[] fields ) { dispatcher.dispatch( new AERunnable() { public void runSupport() { original_listener.matchFound( engine, fields ); } }); } public void resultsReceived( final Engine engine, final Result[] results ) { dispatcher.dispatch( new AERunnable() { public void runSupport() { Result[] results_to_return = null; if ( batch_millis > 0 ){ List list = pending_results.get( engine ); if ( list == null ){ results_to_return = results; pending_results.put( engine, new ArrayList()); new DelayedEvent( "SearchBatcher", batch_millis, new AERunnable() { public void runSupport() { dispatcher.dispatch( new AERunnable() { public void runSupport() { batchResultsComplete( engine ); } }); } }); }else{ list.add( results ); } }else{ results_to_return = results; } if ( results_to_return != null ){ results_to_return = truncateResults( engine, results_to_return, max_results_per_engine ); original_listener.resultsReceived( engine, results_to_return ); } } }); } public void resultsComplete( final Engine engine ) { dispatcher.dispatch( new AERunnable() { public void runSupport() { if ( batch_millis > 0 ){ batchResultsComplete( engine ); } original_listener.resultsComplete( engine ); } }); } protected void batchResultsComplete( Engine engine ) { List list = pending_results.remove( engine ); if ( list != null ){ List x = new ArrayList(); for ( Result[] y: list ){ x.addAll( Arrays.asList( y )); } Result[] results = x.toArray( new Result[ x.size()]); results = truncateResults( engine, results, max_results_per_engine ); original_listener.resultsReceived( engine, results ); } } protected Result[] truncateResults( Engine engine, Result[] a_results, int max ) { Set hash_set = result_hashes.get( engine ); if ( hash_set == null ){ hash_set = new HashSet(); result_hashes.put( engine, hash_set ); } List results = new ArrayList( a_results.length ); for ( Result r: a_results ){ String name = r.getName(); if ( name == null || name.trim().length() == 0 ){ continue; } if ( rem_dups ){ String hash = r.getHash(); if ( hash == null || hash.length() == 0 ){ results.add( r ); }else{ if ( !hash_set.contains( hash )){ results.add( r ); hash_set.add( hash ); } } }else{ results.add( r ); } } if ( max < results.size() ){ log( "Truncating search results for " + engine.getName() + " from " + results.size() + " to " + max ); Collections.sort( results, new Comparator() { Map ranks = new HashMap(); public int compare( Result r1, Result r2) { Float rank1 = (Float)ranks.get(r1); if ( rank1 == null ){ rank1 = new Float(r1.getRank()); ranks.put( r1, rank1 ); } Float rank2 = (Float)ranks.get(r2); if ( rank2 == null ){ rank2 = new Float(r2.getRank()); ranks.put( r2, rank2 ); } return( -rank1.compareTo( rank2 )); } }); Result[] x = new Result[max]; int pos = 0; while( pos < max ){ x[pos] = results.get( pos ); pos++; } return( x ); }else{ return( results.toArray( new Result[ results.size()] )); } } public void engineFailed( final Engine engine, final Throwable e ) { dispatcher.dispatch( new AERunnable() { public void runSupport() { original_listener.engineFailed( engine, e ); } }); } public void engineRequiresLogin( final Engine engine, final Throwable e ) { dispatcher.dispatch( new AERunnable() { public void runSupport() { original_listener.engineRequiresLogin( engine, e ); } }); } }; SearchExecuter se = new SearchExecuter( context, listener ); if ( engines == null ){ engines = getEngines( true, true ); } String engines_str = ""; for (int i=0;i map = FileUtil.readResilientConfigFile( CONFIG_FILE ); List> l_engines = (List>)map.get( "engines" ); if( l_engines != null ){ for (int i=0;i m = (Map)l_engines.get(i); try{ Engine e = importFromBEncodedMap( m ); addEngine( (EngineImpl)e, true ); log( " loaded " + e.getString()); }catch( Throwable e ){ log( "Failed to import engine from " + m, e ); } } } Map p_map = (Map)map.get( "plugin_map" ); if ( p_map != null ){ plugin_map = p_map; } } if ( update_check_timer != null ){ new AsyncDispatcher().dispatch( new AERunnable() { public void runSupport() { checkUpdates(); } }); } } protected void configDirty() { synchronized( this ){ if ( config_dirty ){ return; } config_dirty = true; new DelayedEvent( "MetaSearch:save", 5000, new AERunnable() { public void runSupport() { synchronized( this ){ if ( !config_dirty ){ return; } saveConfig(); } } }); } } protected void saveConfig() { log( "Saving configuration" ); synchronized( this ){ config_dirty = false; Map map = new HashMap(); List> l_engines = new ArrayList>(); map.put( "engines", l_engines ); Iterator it = engines.iterator(); while( it.hasNext()){ Engine e = it.next(); try{ l_engines.add( e.exportToBencodedMap()); }catch( Throwable f ){ log( "Failed to export engine " + e.getName(), f ); } } if ( plugin_map != null ){ map.put( "plugin_map", plugin_map ); } FileUtil.writeResilientConfigFile( CONFIG_FILE, map ); } } protected void log( String str ) { manager.log( "search :" + str ); } protected void log( String str, Throwable e ) { manager.log( "search :" + str, e ); } protected void generate( IndentWriter writer ) { Iterator it = engines.iterator(); while( it.hasNext()){ EngineImpl e = it.next(); writer.println( e.getString( true )); } } public static void main( String[] args ) { try{ MetaSearchImpl ms = new MetaSearchImpl(); EngineImpl e = new RegexEngine( ms, Integer.MAX_VALUE + 9991, SystemTime.getCurrentTime(), "UpdateTest", "http://localhost:1234/search=%s", "", "GMT", true, null, new FieldMapping[] { new FieldMapping("1",Engine.FIELD_CATEGORY), new FieldMapping("2",Engine.FIELD_CDPLINK), new FieldMapping("3",Engine.FIELD_NAME), new FieldMapping("4",Engine.FIELD_TORRENTLINK), new FieldMapping("5",Engine.FIELD_COMMENTS), new FieldMapping("6",Engine.FIELD_DATE), new FieldMapping("7",Engine.FIELD_SIZE), new FieldMapping("8",Engine.FIELD_VOTES), new FieldMapping("9",Engine.FIELD_SEEDS), new FieldMapping("10",Engine.FIELD_PEERS), }, false, WebEngine.AM_TRANSPARENT, "", new String[] {""} ); e.setUpdateURL( "http://localhost:5678/update" ); e.setDefaultUpdateCheckSecs( 60 ); e.setVersion( 2 ); e.exportToVuzeFile( new File( "c:\\temp\\updatetest.vuze" )); }catch( Throwable e ){ e.printStackTrace(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/web/0000755000175000017500000000000011310377626023334 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/web/json/0000755000175000017500000000000011310377626024305 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/web/json/JSONEngine.java0000644000175000017500000002325711305360742027053 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.impl.web.json; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.TreeMap; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.UrlUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; import com.aelitis.azureus.core.metasearch.Engine; import com.aelitis.azureus.core.metasearch.Result; import com.aelitis.azureus.core.metasearch.ResultListener; import com.aelitis.azureus.core.metasearch.SearchException; import com.aelitis.azureus.core.metasearch.SearchParameter; import com.aelitis.azureus.core.metasearch.impl.EngineImpl; import com.aelitis.azureus.core.metasearch.impl.MetaSearchImpl; import com.aelitis.azureus.core.metasearch.impl.web.FieldMapping; import com.aelitis.azureus.core.metasearch.impl.web.WebEngine; import com.aelitis.azureus.core.metasearch.impl.web.WebResult; import com.aelitis.azureus.util.ImportExportUtils; public class JSONEngine extends WebEngine { public static EngineImpl importFromBEncodedMap( MetaSearchImpl meta_search, Map map ) throws IOException { return( new JSONEngine( meta_search, map )); } public static Engine importFromJSONString( MetaSearchImpl meta_search, long id, long last_updated, String name, JSONObject map ) throws IOException { return( new JSONEngine( meta_search, id, last_updated, name, map )); } private String resultsEntryPath; // explicit test constructor public JSONEngine( MetaSearchImpl meta_search, long id, long last_updated, String name, String searchURLFormat, String timeZone, boolean automaticDateFormat, String userDateFormat, String resultsEntryPath, FieldMapping[] mappings, boolean needs_auth, String auth_method, String login_url, String[] required_cookies ) { super( meta_search, Engine.ENGINE_TYPE_JSON, id, last_updated, name, searchURLFormat, timeZone, automaticDateFormat, userDateFormat, mappings, needs_auth, auth_method, login_url, required_cookies ); this.resultsEntryPath = resultsEntryPath; setSource( Engine.ENGINE_SOURCE_LOCAL ); setSelectionState( SEL_STATE_MANUAL_SELECTED ); } // bencoded constructor protected JSONEngine( MetaSearchImpl meta_search, Map map ) throws IOException { super( meta_search, map ); resultsEntryPath = ImportExportUtils.importString( map, "json.path" ); } // json constructor protected JSONEngine( MetaSearchImpl meta_search, long id, long last_updated, String name, JSONObject map ) throws IOException { super( meta_search, Engine.ENGINE_TYPE_JSON, id, last_updated, name, map ); resultsEntryPath = ImportExportUtils.importString( map, "json_result_key" ); } public Map exportToBencodedMap() throws IOException { Map res = new HashMap(); ImportExportUtils.exportString( res, "json.path", resultsEntryPath ); super.exportToBencodedMap( res ); return( res ); } protected void exportToJSONObject( JSONObject res ) throws IOException { res.put( "json_result_key", resultsEntryPath ); super.exportToJSONObject( res ); } protected Result[] searchSupport( SearchParameter[] searchParameters, Map searchContext, int desired_max_matches, int absolute_max_matches, String headers, ResultListener listener ) throws SearchException { debugStart(); pageDetails page_details = super.getWebPageContent( searchParameters, searchContext, headers, false ); String page = page_details.getContent(); if ( listener != null ){ listener.contentReceived( this, page ); } String searchQuery = null; for(int i = 0 ; i < searchParameters.length ; i++) { if(searchParameters[i].getMatchPattern().equals("s")) { searchQuery = searchParameters[i].getValue(); } } FieldMapping[] mappings = getMappings(); try { Object jsonObject = JSONValue.parse(page); JSONArray resultArray = null; if(resultsEntryPath != null) { StringTokenizer st = new StringTokenizer(resultsEntryPath,"."); if(jsonObject instanceof JSONArray && st.countTokens() > 0) { JSONArray array = (JSONArray) jsonObject; if(array.size() == 1) { jsonObject = array.get(0); } } while(st.hasMoreTokens()) { try { jsonObject = ((JSONObject)jsonObject).get(st.nextToken()); } catch(Throwable t) { throw new SearchException("Invalid entry path : " + resultsEntryPath,t); } } } try{ resultArray = (JSONArray) jsonObject; }catch(Throwable t){ throw new SearchException("Object is not a result array. Check the JSON service and/or the entry path"); } if ( resultArray != null ){ List results = new ArrayList(); for(int i = 0 ; i < resultArray.size() ; i++) { Object obj = resultArray.get(i); if(obj instanceof JSONObject) { JSONObject jsonEntry = (JSONObject) obj; if ( absolute_max_matches >= 0 ){ if ( --absolute_max_matches < 0 ){ break; } } if ( listener != null ){ // sort for consistent order Iterator it = new TreeMap( jsonEntry ).entrySet().iterator(); String[] groups = new String[ jsonEntry.size()]; int pos = 0; while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); Object key = entry.getKey(); Object value = entry.getValue(); if ( key != null && value != null ){ groups[pos++] = key.toString() + "=" + UrlUtils.encode( value.toString()); }else{ groups[pos++] = ""; } } listener.matchFound( this, groups ); } WebResult result = new WebResult(this,getRootPage(),getBasePage(),getDateParser(),searchQuery); for(int j = 0 ; j < mappings.length ; j++) { String fieldFrom = mappings[j].getName(); if(fieldFrom != null) { int fieldTo = mappings[j].getField(); Object fieldContentObj = ((Object)jsonEntry.get(fieldFrom)); if(fieldContentObj != null) { String fieldContent = fieldContentObj.toString(); switch(fieldTo) { case FIELD_NAME : result.setNameFromHTML(fieldContent); break; case FIELD_SIZE : result.setSizeFromHTML(fieldContent); break; case FIELD_PEERS : result.setNbPeersFromHTML(fieldContent); break; case FIELD_SEEDS : result.setNbSeedsFromHTML(fieldContent); break; case FIELD_CATEGORY : result.setCategoryFromHTML(fieldContent); break; case FIELD_DATE : result.setPublishedDateFromHTML(fieldContent); break; case FIELD_COMMENTS : result.setCommentsFromHTML(fieldContent); break; case FIELD_CDPLINK : result.setCDPLink(fieldContent); break; case FIELD_TORRENTLINK : result.setTorrentLink(fieldContent); break; case FIELD_PLAYLINK : result.setPlayLink(fieldContent); break; case FIELD_DOWNLOADBTNLINK : result.setDownloadButtonLink(fieldContent); break; case FIELD_VOTES : result.setVotesFromHTML(fieldContent); break; case FIELD_SUPERSEEDS : result.setNbSuperSeedsFromHTML(fieldContent); break; case FIELD_PRIVATE : result.setPrivateFromHTML(fieldContent); break; case FIELD_DRMKEY : result.setDrmKey(fieldContent); break; case FIELD_VOTES_DOWN : result.setVotesDownFromHTML(fieldContent); break; case FIELD_HASH : result.setHash(fieldContent); break; default: break; } } } } results.add(result); } } Result[] res = (Result[]) results.toArray(new Result[results.size()]); debugLog( "success: found " + res.length + " results" ); return( res ); }else{ debugLog( "success: no result array found so no results" ); return( new Result[0]); } }catch( Throwable e ){ debugLog( "failed: " + Debug.getNestedExceptionMessageAndStack( e )); if ( e instanceof SearchException ){ throw((SearchException)e ); } throw( new SearchException( "JSON matching failed", e )); } } public String getIcon() { String rootPage = getRootPage(); if(rootPage != null) { return rootPage + "/favicon.ico"; } return null; } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/web/CookieParser.java0000644000175000017500000000231211056114640026553 0ustar adrianadrianpackage com.aelitis.azureus.core.metasearch.impl.web; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; public class CookieParser { public static boolean cookiesContain(String[] requiredCookies,String cookies) { if(cookies == null) return false; boolean[] cookieFound = new boolean[requiredCookies.length]; String[] names = getCookiesNames(cookies); for(int j = 0 ; j < names.length ; j++) { String cookieName = names[j]; for(int i = 0 ; i < requiredCookies.length ;i++) { if(requiredCookies[i].equals(cookieName)) { cookieFound[i] = true; } } } for(int i = 0 ; i < cookieFound.length ; i++) { if(!cookieFound[i]) return false; } return true; } public static String[] getCookiesNames(String cookies) { if(cookies == null) return new String[0]; StringTokenizer st = new StringTokenizer(cookies,"; "); List names = new ArrayList(); while(st.hasMoreTokens()) { String cookie = st.nextToken(); int separator = cookie.indexOf("="); if(separator > -1) { names.add(cookie.substring(0,separator)); } } String[] result = (String[]) names.toArray(new String[names.size()]); return result; } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/web/FieldMapping.java0000644000175000017500000000213211017365110026521 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.impl.web; public class FieldMapping { private String name; private int field; public FieldMapping(String name,int field) { this.name = name; this.field = field; } public String getName() { return( name ); } public int getField() { return( field ); } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/web/WebResult.java0000644000175000017500000002474711306117650026123 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.impl.web; import java.util.Date; import java.util.StringTokenizer; import org.apache.commons.lang.*; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.metasearch.Engine; import com.aelitis.azureus.core.metasearch.Result; import com.aelitis.azureus.core.metasearch.impl.DateParser; public class WebResult extends Result { private static final String HTML_TAGS = "(\\<(/?[^\\>]+)\\>)" ; private static final String DUPLICATE_SPACES = "\\s{2,}"; String searchQuery; String rootPageURL; String basePageURL; DateParser dateParser; String contentType = ""; String name; String category = ""; String drmKey = null; Date publishedDate; long size = -1; int nbPeers = -1; int nbSeeds = -1; int nbSuperSeeds = -1; int comments = -1; int votes = -1; int votesDown = -1; float rank = -1; boolean privateTorrent; String cdpLink; String torrentLink; String downloadButtonLink; String playLink; String uid; String hash; public WebResult(Engine engine, String rootPageURL,String basePageURL,DateParser dateParser,String searchQuery) { super( engine ); this.rootPageURL = rootPageURL; this.basePageURL = basePageURL; this.dateParser = dateParser; this.searchQuery = searchQuery; } private static final String removeHTMLTags(String input) { String result = input.replaceAll(HTML_TAGS, " "); return result.replaceAll(DUPLICATE_SPACES, " ").trim(); } public void setName(String name) { if(name != null) { this.name = name; } } public void setNameFromHTML(String name) { if(name != null) { name = removeHTMLTags(name); this.name = Entities.HTML40.unescape(name); } } public void setCommentsFromHTML(String comments) { if(comments != null) { comments = removeHTMLTags(comments); comments = Entities.HTML40.unescape(comments); comments = comments.replaceAll(",", ""); comments = comments.replaceAll(" ", ""); try{ this.comments = Integer.parseInt(comments); }catch( Throwable e ){ //e.printStackTrace(); } } } public void setCategoryFromHTML(String category) { if(category != null) { category = removeHTMLTags(category); this.category = Entities.HTML40.unescape(category).trim(); /*int separator = this.category.indexOf(">"); if(separator != -1) { this.category = this.category.substring(separator+1).trim(); }*/ } } public void setUID( String _uid ) { uid = _uid; } public String getUID() { return( uid ); } public void setNbPeersFromHTML(String nbPeers) { if(nbPeers != null) { nbPeers = removeHTMLTags(nbPeers); String nbPeersS = Entities.HTML40.unescape(nbPeers); nbPeersS = nbPeersS.replaceAll(",", ""); nbPeersS = nbPeersS.replaceAll(" ", ""); try { this.nbPeers = Integer.parseInt(nbPeersS); } catch(Throwable e) { //this.nbPeers = 0; //e.printStackTrace(); } } } public void setNbSeedsFromHTML(String nbSeeds) { if(nbSeeds != null) { nbSeeds = removeHTMLTags(nbSeeds); String nbSeedsS = Entities.HTML40.unescape(nbSeeds); nbSeedsS = nbSeedsS.replaceAll(",", ""); nbSeedsS = nbSeedsS.replaceAll(" ", ""); try { this.nbSeeds = Integer.parseInt(nbSeedsS); } catch(Throwable e) { //this.nbSeeds = 0; //e.printStackTrace(); } } } public void setNbSuperSeedsFromHTML(String nbSuperSeeds) { if(nbSuperSeeds != null) { nbSuperSeeds = removeHTMLTags(nbSuperSeeds); String nbSuperSeedsS = Entities.HTML40.unescape(nbSuperSeeds); nbSuperSeedsS = nbSuperSeedsS.replaceAll(",", ""); nbSuperSeedsS = nbSuperSeedsS.replaceAll(" ", ""); try { this.nbSuperSeeds = Integer.parseInt(nbSuperSeedsS); } catch(Throwable e) { //this.nbSeeds = 0; //e.printStackTrace(); } } } public void setRankFromHTML( String rank_str ){ if ( rank_str != null ){ try{ // either a float 0->1 or integer 0->100 float f = Float.parseFloat( rank_str.trim() ); if ( rank_str.indexOf( "." ) == -1 ){ if ( f >= 0 && f <= 100 ){ rank = f/100; } }else{ if ( f >= 0 && f <= 1 ){ rank = f; } } }catch( Throwable e ){ } } } public float getRank() { if ( rank != -1 ){ return( applyRankBias( rank )); } return( super.getRank()); } public void setPublishedDate(Date date) { this.publishedDate = date; } public void setPublishedDateFromHTML(String publishedDate) { if(publishedDate != null) { publishedDate = removeHTMLTags(publishedDate); String publishedDateS = Entities.HTML40.unescape(publishedDate).replace((char)160,(char)32); this.publishedDate = dateParser.parseDate(publishedDateS); } } public void setSizeFromHTML(String size) { if(size != null) { size = removeHTMLTags(size); String sizeS = Entities.HTML40.unescape(size).replace((char)160,(char)32); sizeS = sizeS.replaceAll("<[^>]+>", " "); //Add a space between the digits and unit if there is none sizeS = sizeS.replaceFirst("(\\d)([a-zA-Z])", "$1 $2"); try { StringTokenizer st = new StringTokenizer(sizeS," "); double base = Double.parseDouble(st.nextToken()); String unit = "b"; try { unit = st.nextToken().toLowerCase(); } catch(Throwable e) { //No unit } long multiplier = 1; long KB_UNIT = 1024; long KIB_UNIT = 1024; if("mb".equals(unit)) { multiplier = KB_UNIT*KB_UNIT; } else if("mib".equals(unit)) { multiplier = KIB_UNIT*KIB_UNIT; } else if("gb".equals(unit)) { multiplier = KB_UNIT*KB_UNIT*KB_UNIT; } else if("gib".equals(unit)) { multiplier = KIB_UNIT*KIB_UNIT*KIB_UNIT; } else if("kb".equals(unit)) { multiplier = KB_UNIT; } else if("kib".equals(unit)) { multiplier = KIB_UNIT; } this.size = (long) (base * multiplier); } catch(Throwable e) { //e.printStackTrace(); } } } public void setVotesFromHTML(String votes_str) { if(votes_str != null) { votes_str = removeHTMLTags(votes_str); votes_str = Entities.HTML40.unescape(votes_str); votes_str = votes_str.replaceAll(",", ""); votes_str = votes_str.replaceAll(" ", ""); try { this.votes = Integer.parseInt(votes_str); } catch(Throwable e) { //e.printStackTrace(); } } } public void setVotesDownFromHTML(String votes_str) { if(votes_str != null) { votes_str = removeHTMLTags(votes_str); votes_str = Entities.HTML40.unescape(votes_str); votes_str = votes_str.replaceAll(",", ""); votes_str = votes_str.replaceAll(" ", ""); try { this.votesDown = Integer.parseInt(votes_str); } catch(Throwable e) { //e.printStackTrace(); } } } public void setPrivateFromHTML(String privateTorrent) { if(privateTorrent != null && ! "".equals(privateTorrent)) { this.privateTorrent = true; } } public int getVotes() { return( votes ); } public int getVotesDown() { return( votesDown ); } public void setCDPLink(String cdpLink) { this.cdpLink = cdpLink; } public void setDownloadButtonLink(String downloadButtonLink) { this.downloadButtonLink = downloadButtonLink; } public void setTorrentLink(String torrentLink) { this.torrentLink = torrentLink; } public void setPlayLink(String playLink) { this.playLink = playLink; } public String getContentType() { return this.contentType; } public String getPlayLink() { return( reConstructLink( playLink )); } public void setCategory(String category) { this.category = category; } public void setContentType(String contentType) { this.contentType = contentType; } public void setDrmKey(String drmKey) { this.drmKey = drmKey; } public void setHash( String _hash ) { try{ hash = _hash.trim(); if ( hash.length() == 32 ){ // base 32 hash }else if ( hash.length() == 40 ){ // base 16 hash = Base32.encode( ByteFormatter.decodeString( hash )); }else{ hash = null; } }catch( Throwable e ){ Debug.printStackTrace(e); hash = null; } } public String getHash() { return( hash ); } public String getCDPLink() { return reConstructLink(cdpLink); } public String getCategory() { return category; } public String getDownloadLink() { return reConstructLink(torrentLink); } public String getDownloadButtonLink() { //If we don't have a download button link, but we do have a direct download link, //then we should use the direct download link... if(downloadButtonLink != null) { return reConstructLink(downloadButtonLink); } else { return getDownloadLink(); } } private String reConstructLink( String link) { if ( link != null ){ String lc_link = link.toLowerCase(); if ( lc_link.startsWith("http://") || lc_link.startsWith("https://") || lc_link.startsWith("azplug:") || lc_link.startsWith("magnet:") || lc_link.startsWith("dht:" )){ return( link ); } if ( link.startsWith("/")){ return((rootPageURL==null?"":rootPageURL) + link ); } return((basePageURL==null?"":basePageURL) + link ); } return( "" ); } public String getName() { return name; } public int getNbPeers() { return nbPeers; } public int getNbSeeds() { return nbSeeds; } public int getNbSuperSeeds() { return nbSuperSeeds; } public Date getPublishedDate() { return publishedDate; } public long getSize() { return size; } public int getComments() { return( comments ); } public String getSearchQuery() { return searchQuery; } public boolean isPrivate() { return privateTorrent; } public String getDRMKey() { return drmKey; } public float getAccuracy() { return -1; } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/web/WebEngine.java0000644000175000017500000006575411233020316026044 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.impl.web; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.Charset; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.plugins.utils.StaticUtilities; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import com.aelitis.azureus.core.metasearch.SearchException; import com.aelitis.azureus.core.metasearch.SearchLoginException; import com.aelitis.azureus.core.metasearch.SearchParameter; import com.aelitis.azureus.core.metasearch.impl.*; import com.aelitis.azureus.core.util.GeneralUtils; import com.aelitis.azureus.util.ImportExportUtils; import com.aelitis.azureus.util.UrlFilter; public abstract class WebEngine extends EngineImpl { public static final String AM_TRANSPARENT = "transparent"; public static final String AM_PROXY = "proxy"; static private final Pattern baseTagPattern = Pattern.compile("(?i)"); static private final Pattern rootURLPattern = Pattern.compile("(https?://[^/]+)"); static private final Pattern baseURLPattern = Pattern.compile("(https?://.*/)"); private String searchURLFormat; private String timeZone; private boolean automaticDateParser; private String userDateFormat; private String downloadLinkCSS; private FieldMapping[] mappings; private String rootPage; private String basePage; private DateParser dateParser; private boolean needsAuth; private String authMethod; private String loginPageUrl; private String[] requiredCookies; private String local_cookies; // manual test constructor public WebEngine( MetaSearchImpl meta_search, int type, long id, long last_updated, String name, String searchURLFormat, String timeZone, boolean automaticDateParser, String userDateFormat, FieldMapping[] mappings, boolean needs_auth, String auth_method, String login_url, String[] required_cookies ) { super( meta_search, type, id, last_updated, name ); this.searchURLFormat = searchURLFormat; this.timeZone = timeZone; this.automaticDateParser = automaticDateParser; this.userDateFormat = userDateFormat; this.mappings = mappings; this.needsAuth = needs_auth; this.authMethod = auth_method; this.loginPageUrl = login_url; this.requiredCookies = required_cookies; init(); } // bencoded constructor protected WebEngine( MetaSearchImpl meta_search, Map map ) throws IOException { super( meta_search, map ); searchURLFormat = ImportExportUtils.importString( map, "web.search_url_format" ); timeZone = ImportExportUtils.importString( map, "web.time_zone" ); userDateFormat = ImportExportUtils.importString( map, "web.date_format" ); downloadLinkCSS = ImportExportUtils.importString( map, "web.dl_link_css" ); needsAuth = ImportExportUtils.importBoolean(map, "web.needs_auth", false ); authMethod = ImportExportUtils.importString( map, "web.auth_method", WebEngine.AM_TRANSPARENT ); loginPageUrl = ImportExportUtils.importString( map, "web.login_page" ); requiredCookies = ImportExportUtils.importStringArray( map, "web.required_cookies" ); automaticDateParser = ImportExportUtils.importBoolean( map, "web.auto_date", true ); List maps = (List)map.get( "web.maps" ); mappings = new FieldMapping[maps.size()]; for (int i=0;i searchContext, String headers, boolean only_if_modified ) throws SearchException { try { if ( requiresLogin()){ throw new SearchLoginException("login required"); } String searchURL = searchURLFormat; String[] from_strs = new String[ searchParameters.length ]; String[] to_strs = new String[ searchParameters.length ]; for( int i = 0 ; i < searchParameters.length ; i++ ){ SearchParameter parameter = searchParameters[i]; from_strs[i] = "%" + parameter.getMatchPattern(); to_strs[i] = URLEncoder.encode(parameter.getValue(),"UTF-8"); } searchURL = GeneralUtils.replaceAll( searchURL, from_strs, to_strs ); Iterator> it = searchContext.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = it.next(); String key = entry.getKey(); if ( supportsContext( key )){ if ( searchURL.indexOf('?') == -1 ){ searchURL += "?"; }else{ searchURL += "&"; } String value = entry.getValue(); searchURL += key + "=" + URLEncoder.encode( value, "UTF-8" ); } } //System.out.println(searchURL); // hack to support POST by encoding into URL // http://xxxx/index.php?main=search&azmethod=post_basic:SearchString1=%s&SearchString=&search=Search ResourceDownloaderFactory rdf = StaticUtilities.getResourceDownloaderFactory(); URL initial_url; ResourceDownloader initial_url_rd; int post_pos = searchURL.indexOf( "azmethod=" ); if ( post_pos > 0 ){ String post_params = searchURL.substring( post_pos+9 ); searchURL = searchURL.substring( 0, post_pos-1 ); debugLog( "search_url: " + searchURL + ", post=" + post_params ); initial_url = new URL(searchURL); int sep = post_params.indexOf( ':' ); String type = post_params.substring( 0, sep ); if ( !type.equals( "post_basic" )){ throw( new SearchException( "Only basic type supported" )); } post_params = post_params.substring( sep+1 ); // already URL encoded initial_url_rd = rdf.create( initial_url, post_params ); initial_url_rd.setProperty( "URL_Content-Type", "application/x-www-form-urlencoded" ); }else{ debugLog( "search_url: " + searchURL ); initial_url = new URL(searchURL); initial_url_rd = rdf.create( initial_url ); } setHeaders( initial_url_rd, headers ); if ( needsAuth && local_cookies != null ){ initial_url_rd.setProperty( "URL_Cookie", local_cookies ); } if ( only_if_modified ){ String last_modified = getLocalString( LD_LAST_MODIFIED ); String etag = getLocalString( LD_ETAG ); if ( last_modified != null ){ initial_url_rd.setProperty( "URL_If-Modified-Since", last_modified ); } if ( etag != null ){ initial_url_rd.setProperty( "URL_If-None-Match", etag ); } } InputStream is; String content_charset = "UTF-8"; ResourceDownloader mr_rd = null; if ( initial_url.getProtocol().equalsIgnoreCase( "file" )){ // handle file://c:/ - map to file:/c:/ String str = initial_url.toExternalForm(); if ( initial_url.getAuthority() != null ){ str = str.replaceFirst( "://", ":/" ); } int pos = str.indexOf( '?' ); if ( pos != -1 ){ str = str.substring( 0, pos ); } is = new FileInputStream( new File( new URL( str ).toURI())); }else{ mr_rd = rdf.getMetaRefreshDownloader( initial_url_rd ); try{ is = mr_rd.download(); }catch( ResourceDownloaderException e ){ Long response = (Long)mr_rd.getProperty( "URL_HTTP_Response" ); if ( response != null && response.longValue() == 304 ){ // not modified return( new pageDetails( initial_url, initial_url, "" )); }else{ throw( e ); } } if ( needsAuth ){ List cookies_list = (List)mr_rd.getProperty( "URL_Set-Cookie" ); List cookies_set = new ArrayList(); if ( cookies_list != null ){ for (int i=0;i 0 ){ String content_type = (String)cts.get(0); int pos = content_type.toLowerCase().indexOf( "charset" ); if ( pos != -1 ){ content_type = content_type.substring( pos+1 ); pos = content_type.indexOf('='); if ( pos != -1 ){ content_type = content_type.substring( pos+1 ).trim(); pos = content_type.indexOf(';'); if ( pos != -1 ){ content_type = content_type.substring(0,pos).trim(); } try{ if ( Charset.isSupported( content_type )){ debugLog( "charset: " + content_type ); content_charset = content_type; } }catch( Throwable e ){ try{ // handle lowercase 'utf-8' for example content_type = content_type.toUpperCase(); if ( Charset.isSupported( content_type )){ debugLog( "charset: " + content_type ); content_charset = content_type; } }catch( Throwable f ){ log( "Content type '" + content_type + "' not supported", f ); } } } } } } ByteArrayOutputStream baos = new ByteArrayOutputStream(8192); byte[] buffer = new byte[8192]; while( true ){ int len = is.read( buffer ); if ( len <= 0 ){ break; } baos.write( buffer, 0, len ); } byte[] data = baos.toByteArray(); String page = null; String content = new String( data, 0, Math.min( data.length, 2048 ), content_charset ); String lc_content = content.toLowerCase(); { // first look for xml charset // e.g. int pos1 = lc_content.indexOf( "" ); if ( pos2 != -1 ){ int pos3 = lc_content.indexOf( "encoding", pos1 ); if ( pos3 != -1 ){ pos3 = lc_content.indexOf( "\"", pos3 ); } if ( pos3 > pos1 && pos3 < pos2 ){ pos3++; int pos4 = lc_content.indexOf( "\"", pos3 ); if ( pos4 > pos3 && pos4 < pos2 ){ String encoding = content.substring( pos3, pos4 ).trim(); try{ if ( Charset.isSupported( encoding )){ debugLog( "charset from xml tag: " + encoding ); content_charset = encoding; // some feeds have crap at the start which makes pos2 mismatch for the above '?' - adjust if necessary int data_start = pos2; int max_skip = 64; while( data[data_start] != '?' && max_skip-- > 0 ){ data_start++; } page = content.substring( 0, pos3 ) + "utf-8" + content.substring( pos4, pos2 ) + new String( data, data_start, data.length - data_start, content_charset ); } }catch( Throwable e ){ log( "Content type '" + encoding + "' not supported", e ); } } } } } } if ( page == null ){ // next look for http-equiv charset // e.g. int pos = 0; while( true ){ int pos1 = lc_content.indexOf( "http-equiv", pos ); if ( pos1 != -1 ){ int pos2 = lc_content.indexOf( ">", pos1 ); if ( pos2 != -1 ){ int pos3 = lc_content.indexOf( "charset", pos1 ); if ( pos3 != -1 && pos3 < pos2 ){ pos3 = lc_content.indexOf( "=", pos3 ); if ( pos3 != -1 ){ pos3++; int pos4 = lc_content.indexOf( "\"", pos3 ); if ( pos4 != -1 ){ int pos5 = lc_content.indexOf( ";", pos3 ); if ( pos5 != -1 && pos5 < pos4 ){ pos4 = pos5; } String encoding = content.substring( pos3, pos4 ).trim(); try{ if ( Charset.isSupported( encoding )){ debugLog( "charset from http-equiv : " + encoding ); content_charset = encoding; // some feeds have crap at the start which makes pos2 mismatch for the above '?' - adjust if necessary int data_start = pos2; int max_skip = 64; while( data[data_start] != '?' && max_skip-- > 0 ){ data_start++; } page = content.substring( 0, pos3 ) + "utf-8" + content.substring( pos4, pos2 ) + new String( data, data_start, data.length - data_start, content_charset ); } }catch( Throwable e ){ log( "Content type '" + encoding + "' not supported", e ); } break; } } } pos = pos2; }else{ break; } }else{ break; } } } if ( page == null ){ page = new String( data, content_charset ); } debugLog( "page:" ); debugLog( page ); // List cookie = (List)url_rd.getProperty( "URL_Set-Cookie" ); try { Matcher m = baseTagPattern.matcher(page); if(m.find()) { basePage = m.group(1); debugLog( "base_page: " + basePage ); } } catch(Exception e) { //No BASE tag in the page } URL final_url = initial_url; if ( mr_rd != null ){ URL x = (URL)mr_rd.getProperty( "URL_URL" ); if ( x != null ){ final_url = x; } } return( new pageDetails( initial_url, final_url, page )); }catch( SearchException e ){ throw( e ); }catch( Throwable e) { // e.printStackTrace(); debugLog( "Failed to load page: " + Debug.getNestedExceptionMessageAndStack(e)); throw( new SearchException( "Failed to load page", e )); } } protected String extractProperty( Object o ) { if ( o instanceof String ){ return((String)o); }else if ( o instanceof List ){ List l = (List)o; if ( l.size() > 0 ){ if ( l.size() > 1 ){ Debug.out( "Property has multiple values!" ); } Object x = l.get(0); if ( x instanceof String ){ return((String)x); }else{ Debug.out( "Property value isn't a String:" + x ); } } } return( null ); } protected void setHeaders( ResourceDownloader rd, String encoded_headers ) { UrlUtils.setBrowserHeaders( rd, encoded_headers, rootPage ); } public String getIcon() { if(rootPage != null) { return rootPage + "/favicon.ico"; } return null; } protected FieldMapping[] getMappings() { return( mappings ); } public boolean supportsField( int field_id ) { for (int i=0;i 60*1000 ){ if ( linkIsToTorrent( url )){ result.setTorrentLink(value); setLocalLong( LD_LINK_IS_TORRENT, 1 ); }else{ setLocalLong( LD_LINK_IS_TORRENT, SystemTime.getCurrentTime()); } } } }catch( Throwable e ){ } }else if ( lc_child_name.equals( "content" ) && rssFeed.isAtomFeed()){ SimpleXMLParserDocumentAttribute srcAtt = child.getAttribute( "src" ); String src = srcAtt==null?null:srcAtt.getValue(); if ( src != null ){ boolean is_dl_link = false; SimpleXMLParserDocumentAttribute typeAtt = child.getAttribute( "type" ); if ( typeAtt != null && typeAtt.getValue().equalsIgnoreCase("application/x-bittorrent")) { is_dl_link = true; } if ( !is_dl_link ){ is_dl_link = src.toLowerCase().indexOf( ".torrent" ) != -1; } if ( is_dl_link ){ try{ new URL( src ); result.setTorrentLink( src ); }catch( Throwable e ){ } } } }else if ( lc_full_child_name.equals( "vuze:size" )){ result.setSizeFromHTML( value ); }else if ( lc_full_child_name.equals( "vuze:seeds" )){ got_seeds_peers = true; result.setNbSeedsFromHTML( value ); }else if ( lc_full_child_name.equals( "vuze:superseeds" )){ got_seeds_peers = true; result.setNbSuperSeedsFromHTML( value ); }else if ( lc_full_child_name.equals( "vuze:peers" )){ got_seeds_peers = true; result.setNbPeersFromHTML( value ); }else if ( lc_full_child_name.equals( "vuze:rank" )){ result.setRankFromHTML( value ); }else if ( lc_full_child_name.equals( "vuze:contenttype" )){ String type = value.toLowerCase(); if ( type.startsWith( "video" )){ type = Engine.CT_VIDEO; }else if ( type.startsWith( "audio" )){ type = Engine.CT_AUDIO; }else if ( type.startsWith( "games" )){ type = Engine.CT_GAME; } result.setContentType( type ); }else if ( lc_full_child_name.equals( "vuze:downloadurl" )){ result.setTorrentLink( value); }else if ( lc_full_child_name.equals( "vuze:playurl" )){ result.setPlayLink( value); }else if ( lc_full_child_name.equals( "vuze:drmkey" )){ result.setDrmKey( value); }else if ( lc_full_child_name.equals( "vuze:assethash" )){ result.setHash( value); } } } if ( !got_seeds_peers ){ try{ SimpleXMLParserDocumentNode desc_node = node.getChild( "description" ); if ( desc_node != null ){ String desc = desc_node.getValue().trim(); // see if we can pull from description Matcher m = seed_leecher_pat.matcher( desc ); while( m.find()){ String num = m.group(1); String type = m.group(2); if ( type.toLowerCase().charAt(0) == 's' ){ result.setNbSeedsFromHTML( num ); }else{ result.setNbPeersFromHTML( num ); } } } }catch( Throwable e ){ } } results.add(result); if ( absolute_max_matches >= 0 && results.size() == absolute_max_matches ){ break; } } } Result[] res = (Result[]) results.toArray(new Result[results.size()]); debugLog( "success: found " + res.length + " results" ); return( res ); }catch ( Throwable e ){ debugLog( "failed: " + Debug.getNestedExceptionMessageAndStack( e )); if ( e instanceof SearchException ){ throw((SearchException)e ); } throw( new SearchException( "RSS matching failed", e )); } } protected boolean linkIsToTorrent( URL url ) { try{ HttpURLConnection con = (HttpURLConnection)url.openConnection(); con.setRequestMethod( "HEAD" ); con.setConnectTimeout( 10*1000 ); con.setReadTimeout( 10*1000 ); String content_type = con.getContentType(); log( "Testing link " + url + " to see if torrent link -> content type=" + content_type ); if ( content_type.equalsIgnoreCase( "application/x-bittorrent" )){ return( true ); } return( false ); }catch( Throwable e ){ return( false ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/web/regex/0000755000175000017500000000000011310377626024446 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/metasearch/impl/web/regex/RegexEngine.java0000644000175000017500000002746011305360742027515 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.impl.web.regex; import java.io.*; import java.net.URLDecoder; import java.util.*; import java.util.regex.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.TimeLimitedTask; import org.gudy.azureus2.core3.util.UrlUtils; import org.json.simple.JSONObject; import com.aelitis.azureus.core.metasearch.Engine; import com.aelitis.azureus.core.metasearch.Result; import com.aelitis.azureus.core.metasearch.ResultListener; import com.aelitis.azureus.core.metasearch.SearchException; import com.aelitis.azureus.core.metasearch.SearchLoginException; import com.aelitis.azureus.core.metasearch.SearchParameter; import com.aelitis.azureus.core.metasearch.impl.EngineImpl; import com.aelitis.azureus.core.metasearch.impl.MetaSearchImpl; import com.aelitis.azureus.core.metasearch.impl.web.FieldMapping; import com.aelitis.azureus.core.metasearch.impl.web.WebEngine; import com.aelitis.azureus.core.metasearch.impl.web.WebResult; import com.aelitis.azureus.util.ImportExportUtils; public class RegexEngine extends WebEngine { public static EngineImpl importFromBEncodedMap( MetaSearchImpl meta_search, Map map ) throws IOException { return( new RegexEngine( meta_search, map )); } public static Engine importFromJSONString( MetaSearchImpl meta_search, long id, long last_updated, String name, JSONObject map ) throws IOException { return( new RegexEngine( meta_search, id, last_updated, name, map )); } private String pattern_str; private Pattern pattern; // explicit test constructor public RegexEngine( MetaSearchImpl meta_search, long id, long last_updated, String name, String searchURLFormat, String resultPattern, String timeZone, boolean automaticDateFormat, String userDateFormat, FieldMapping[] mappings, boolean needs_auth, String auth_method, String login_url, String[] required_cookies ) { super( meta_search, Engine.ENGINE_TYPE_REGEX, id, last_updated, name, searchURLFormat, timeZone, automaticDateFormat, userDateFormat, mappings, needs_auth, auth_method, login_url, required_cookies ); init( resultPattern ); setSource( ENGINE_SOURCE_LOCAL ); setSelectionState( SEL_STATE_MANUAL_SELECTED ); } // bencoded protected RegexEngine( MetaSearchImpl meta_search, Map map ) throws IOException { super( meta_search, map ); String resultPattern = ImportExportUtils.importString( map, "regex.pattern" ); init( resultPattern ); } // json protected RegexEngine( MetaSearchImpl meta_search, long id, long last_updated, String name, JSONObject map ) throws IOException { super( meta_search, Engine.ENGINE_TYPE_REGEX, id, last_updated, name, map ); String resultPattern = ImportExportUtils.importString( map, "regexp" ); resultPattern = URLDecoder.decode( resultPattern, "UTF-8" ); init( resultPattern ); } public Map exportToBencodedMap() throws IOException { Map res = new HashMap(); ImportExportUtils.exportString( res, "regex.pattern", pattern_str ); super.exportToBencodedMap( res ); return( res ); } protected void exportToJSONObject( JSONObject res ) throws IOException { res.put( "regexp", UrlUtils.encode( pattern_str )); super.exportToJSONObject( res ); } protected void init( String resultPattern ) { pattern_str = resultPattern.trim(); pattern = Pattern.compile(pattern_str); } protected Result[] searchSupport( final SearchParameter[] searchParameters, Map searchContext, final int desired_max_matches, final int o_absolute_max_matches, final String headers, final ResultListener listener ) throws SearchException { debugStart(); final pageDetails page_details = getWebPageContent( searchParameters, searchContext, headers, false ); final String page = page_details.getContent(); if ( listener != null ){ listener.contentReceived( this, page ); } debugLog( "pattern: " + pattern_str ); /* if ( getId() == 3 ){ writeToFile( "C:\\temp\\template.txt", page ); writeToFile( "C:\\temp\\pattern.txt", pattern.pattern()); String page2 = readFile( "C:\\temp\\template.txt" ); Set s1 = new HashSet(); Set s2 = new HashSet(); for (int i=0;i 1024 ){ max_matches = 1024; } String searchQuery = null; for(int i = 0 ; i < searchParameters.length ; i++) { if(searchParameters[i].getMatchPattern().equals("s")) { searchQuery = searchParameters[i].getValue(); } } FieldMapping[] mappings = getMappings(); try{ List results = new ArrayList(); Matcher m = pattern.matcher( page ); while( m.find()){ if ( max_matches >= 0 ){ if ( --max_matches < 0 ){ break; } } if ( listener != null ){ String[] groups = new String[m.groupCount()]; for (int i=0;i 0 && group <= m.groupCount()) { int field = mappings[i].getField(); String groupContent = m.group(group); debugLog( " " + field + "=" + groupContent ); fields_matched++; switch(field) { case FIELD_NAME : result.setNameFromHTML(groupContent); break; case FIELD_SIZE : result.setSizeFromHTML(groupContent); break; case FIELD_PEERS : result.setNbPeersFromHTML(groupContent); break; case FIELD_SEEDS : result.setNbSeedsFromHTML(groupContent); break; case FIELD_CATEGORY : result.setCategoryFromHTML(groupContent); break; case FIELD_DATE : result.setPublishedDateFromHTML(groupContent); break; case FIELD_CDPLINK : result.setCDPLink(groupContent); break; case FIELD_TORRENTLINK : result.setTorrentLink(groupContent); break; case FIELD_PLAYLINK : result.setPlayLink(groupContent); break; case FIELD_DOWNLOADBTNLINK : result.setDownloadButtonLink(groupContent); break; case FIELD_COMMENTS : result.setCommentsFromHTML(groupContent); break; case FIELD_VOTES : result.setVotesFromHTML(groupContent); break; case FIELD_SUPERSEEDS : result.setNbSuperSeedsFromHTML(groupContent); break; case FIELD_PRIVATE : result.setPrivateFromHTML(groupContent); break; case FIELD_DRMKEY : result.setDrmKey(groupContent); break; case FIELD_VOTES_DOWN : result.setVotesDownFromHTML(groupContent); break; case FIELD_HASH : result.setHash(groupContent); break; default: fields_matched--; break; } } } // ignore "matches" that don't actually populate any fields if ( fields_matched > 0 ){ results.add(result); } } // hack - if no results and redirected to https and auth required then // assume we need to log in... if ( results.size() == 0 && isNeedsAuth()){ if ( page_details.getInitialURL().getProtocol().equalsIgnoreCase( "http" ) && page_details.getFinalURL().getProtocol().equalsIgnoreCase( "https" )){ throw new SearchLoginException("login possibly required"); } } return (Result[]) results.toArray(new Result[results.size()]); }catch (Throwable e){ log( "Failed process result", e ); if ( e instanceof SearchException ){ throw((SearchException)e ); } throw new SearchException(e); } } }); Result[] res = (Result[])task.run(); debugLog( "success: found " + res.length + " results" ); return( res ); }catch( Throwable e ){ debugLog( "failed: " + Debug.getNestedExceptionMessageAndStack( e )); if ( e instanceof SearchException ){ throw((SearchException)e ); } throw( new SearchException( "Regex matching failed", e )); } } /* protected void writeToFile( String file, String str ) { try{ PrintWriter pw = new PrintWriter( new FileWriter( new File( file ))); pw.println( str ); pw.close(); }catch( Throwable e ){ e.printStackTrace(); } } private static String readFile( String file ) { try{ StringBuffer sb = new StringBuffer(); LineNumberReader lnr = new LineNumberReader( new FileReader( new File( file ))); while( true ){ String line = lnr.readLine(); if ( line == null ){ break; } sb.append( line ); } return( sb.toString()); }catch( Throwable e ){ e.printStackTrace(); return( null ); } } private static void regexptest() throws Exception { Pattern pattern = Pattern.compile( readFile( "C:\\temp\\pattern.txt" )); String page = readFile( "C:\\temp\\template.txt" ); Matcher m = pattern.matcher( page); while(m.find()) { int groups = m.groupCount(); System.out.println( "found match: groups = " + groups ); } } */ } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/SearchException.java0000644000175000017500000000212011017365100025524 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch; public class SearchException extends Exception { public SearchException(Throwable t) { super(t); } public SearchException(String description,Throwable t) { super(description,t); } public SearchException(String description) { super(description); } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/SearchParameter.java0000644000175000017500000000221311017365104025515 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch; public class SearchParameter { private String matchPattern; private String value; public SearchParameter(String matchPattern, String value) { this.matchPattern = matchPattern; this.value = value; } public String getMatchPattern() { return matchPattern; } public String getValue() { return value; } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/MetaSearch.java0000644000175000017500000000456111306150472024474 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch; import java.io.IOException; import java.net.URL; import java.util.Map; public interface MetaSearch { public Engine importFromBEncodedMap( Map map ) throws IOException; public Engine[] search( ResultListener listener, SearchParameter[] searchParameters, String headers, int max_per_engine ); public Engine[] search( ResultListener listener, SearchParameter[] searchParameters, String headers, Map context, int max_per_engine ); public Engine[] search( Engine[] engine, ResultListener listener, SearchParameter[] searchParameters, String headers, int max_per_engine ); public Engine[] search( Engine[] engine, ResultListener listener, SearchParameter[] searchParameters, String headers, Map context, int max_per_engine ); public Engine[] getEngines( boolean active_only, boolean ensure_up_to_date ); public Engine getEngine( long id ); public Engine getEngineByUID( String uid ); public void addEngine( Engine engine ); public Engine addEngine( long id ) throws MetaSearchException; public Engine createRSSEngine( String name, URL url ) throws MetaSearchException; public void removeEngine( Engine engine ); public int getEngineCount(); public void enginePreferred( Engine engine ); public void addListener( MetaSearchListener listener ); public void removeListener( MetaSearchListener listener ); } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/SearchLoginException.java0000644000175000017500000000052411051226736026534 0ustar adrianadrianpackage com.aelitis.azureus.core.metasearch; public class SearchLoginException extends SearchException { public SearchLoginException(Throwable t) { super(t); } public SearchLoginException(String description,Throwable t) { super(description,t); } public SearchLoginException(String description) { super(description); } } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/MetaSearchListener.java0000644000175000017500000000200511050156252026167 0ustar adrianadrian/* * Created on Aug 11, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch; public interface MetaSearchListener { public void engineAdded( Engine engine ); public void engineUpdated( Engine engine ); public void engineRemoved( Engine engine ); } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/Engine.java0000644000175000017500000001410711310044576023664 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch; import java.io.*; import java.util.Map; public interface Engine { public static final int AZ_VERSION = 1; public static final Object VUZE_FILE_COMPONENT_ENGINE_KEY = new Object(); // Don't change these values as they get persisted public static final int FIELD_NAME = 1; public static final int FIELD_DATE = 2; public static final int FIELD_SIZE = 3; public static final int FIELD_PEERS = 4; public static final int FIELD_SEEDS = 5; public static final int FIELD_CATEGORY = 6; public static final int FIELD_COMMENTS = 7; public static final int FIELD_CONTENT_TYPE = 8; public static final int FIELD_DISCARD = 9; public static final int FIELD_VOTES = 10; public static final int FIELD_SUPERSEEDS = 11; public static final int FIELD_PRIVATE = 12; public static final int FIELD_DRMKEY = 13; public static final int FIELD_VOTES_DOWN = 14; public static final int FIELD_TORRENTLINK = 102; public static final int FIELD_CDPLINK = 103; public static final int FIELD_PLAYLINK = 104; public static final int FIELD_DOWNLOADBTNLINK = 105; public static final int FIELD_HASH = 200; public static final int[] FIELD_IDS = { FIELD_NAME, FIELD_DATE, FIELD_SIZE, FIELD_PEERS, FIELD_SEEDS, FIELD_CATEGORY, FIELD_COMMENTS, FIELD_CONTENT_TYPE, FIELD_DISCARD, FIELD_TORRENTLINK, FIELD_CDPLINK, FIELD_PLAYLINK,FIELD_DOWNLOADBTNLINK, FIELD_VOTES, FIELD_SUPERSEEDS, FIELD_PRIVATE, FIELD_DRMKEY, FIELD_VOTES_DOWN, FIELD_HASH }; public static final String[] FIELD_NAMES = { "TITLE", "DATE", "SIZE", "PEERS", "SEEDS", "CAT", "COMMENTS", "CONTENT_TYPE", "DISCARD", "TORRENT", "CDP", "PLAY","DLBTN", "VOTES", "XSEEDS", "PRIVATE", "DRMKEY", "VOTESDOWN", "HASH" }; public static final int ENGINE_TYPE_REGEX = 1; public static final int ENGINE_TYPE_JSON = 2; public static final int ENGINE_TYPE_PLUGIN = 3; public static final int ENGINE_TYPE_RSS = 4; public static final int ENGINE_SOURCE_UNKNOWN = 0; public static final int ENGINE_SOURCE_VUZE = 1; public static final int ENGINE_SOURCE_LOCAL = 2; public static final int ENGINE_SOURCE_RSS = 3; public static final int SEL_STATE_DESELECTED = 0; public static final int SEL_STATE_AUTO_SELECTED = 1; public static final int SEL_STATE_MANUAL_SELECTED = 2; public static final int AUTO_DL_SUPPORTED_UNKNOWN = 0; public static final int AUTO_DL_SUPPORTED_YES = 1; public static final int AUTO_DL_SUPPORTED_NO = 2; /** * don't change these as they are externalised */ public static final String[] ENGINE_SOURCE_STRS = { "unknown","vuze","local","rss","unused" }; public static final String[] SEL_STATE_STRINGS = { "no", "auto", "manual" }; public static final String[] ENGINE_TYPE_STRS = { "unknown","regexp","json", "plugin" }; public static final String SC_SOURCE = "azsrc"; public static final String SC_AZID = "azid"; public static final String SC_FORCE_FULL = "force_full"; // ignore if-modified stuff and force a full search public static final String SC_BATCH_PERIOD = "batch_millis"; public static final String SC_REMOVE_DUP_HASH = "remove_dup_hash"; public static final String CT_VIDEO = "video"; public static final String CT_AUDIO = "audio"; public static final String CT_GAME = "game"; public int getType(); public Result[] search( SearchParameter[] searchParameters, Map context, int desired_max_matches, int absolute_max_matches, String headers, ResultListener listener ) throws SearchException; public String getName(); public String getNameEx(); public long getId(); public String getUID(); public int getVersion(); public long getLastUpdated(); public String getIcon(); public String getDownloadLinkCSS(); public boolean isActive(); public boolean isMine(); public boolean isPublic(); public void setMine( boolean mine ); public int getSelectionState(); public void setSelectionState( int state ); public void recordSelectionState(); public void checkSelectionStateRecorded(); public int getSource(); public void setSource( int source ); public String getReferer(); public float getRankBias(); public void setRankBias( float bias ); public void setPreferredDelta( float delta ); public float getPreferredWeighting(); public float applyRankBias( float rank ); public boolean supportsField( int field_id ); public boolean supportsContext( String context_key ); public boolean isShareable(); /** * @return one of AUTO_DL constants above */ public int getAutoDownloadSupported(); public int getAZVersion(); public Map exportToBencodedMap() throws IOException; public String exportToJSONString() throws IOException; public void exportToVuzeFile( File target ) throws IOException; /** * Tests for sameness in terms of function (ignores id, selection state etc) * @param other * @return */ public boolean sameLogicAs( Engine other ); /** * resets to initial state (e.g. if the engine has state pertaining to what has/hasn't been downloaded * such as etags then this will be cleared) */ public void reset(); public void delete(); public String getString(); } azureus-4.3.0.6/com/aelitis/azureus/core/metasearch/utils/0000755000175000017500000000000011310377626022756 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/metasearch/utils/MomentsAgoDateFormatter.java0000644000175000017500000001353211276651644030366 0ustar adrianadrian/* * Created on May 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.metasearch.utils; import java.text.DateFormat; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.SimpleTimeZone; /** * Improvement based on AZWEB-318. * * @version 3.2.1.0 6/19/2007 * @since 3.2.1.0 6/19/2007 */ public class MomentsAgoDateFormatter { // A list of id's that we use in the two maps to ensure we have valid refs private static final Integer ID_YEAR = new Integer(Calendar.YEAR); private static final Integer ID_MONTH = new Integer(Calendar.MONTH); private static final Integer ID_WEEK_OF_YEAR = new Integer(Calendar.WEEK_OF_YEAR); private static final Integer ID_DAY = new Integer(Calendar.DAY_OF_MONTH); private static final Integer ID_HOUR_OF_DAY = new Integer(Calendar.HOUR_OF_DAY); private static final Integer ID_MINUTE = new Integer(Calendar.MINUTE); private static final Integer ID_SECOND = new Integer(Calendar.SECOND); // A list of units we're comparing. private static final Long MS_IN_YEAR = new Long(31536000000L); private static final Long MS_IN_MONTH = new Long(2678400000L); private static final Long MS_IN_WEEK = new Long(604800000L); private static final Long MS_IN_DAY = new Long(86400000L); private static final Long MS_IN_HOUR = new Long(3600000L); private static final Long MS_IN_MINUTE = new Long(60000L); private static final Long MS_IN_SECOND = new Long(1000L); // A few externalized strings to display to the user private static final String AGO = " ago"; private static final String PLURAL = "s"; private static final Map CONVERSION_MAP = new HashMap(); // Build the map at system start static { CONVERSION_MAP.put(ID_YEAR, MS_IN_YEAR); CONVERSION_MAP.put(ID_MONTH, MS_IN_MONTH); CONVERSION_MAP.put(ID_WEEK_OF_YEAR, MS_IN_WEEK); CONVERSION_MAP.put(ID_DAY, MS_IN_DAY); CONVERSION_MAP.put(ID_HOUR_OF_DAY, MS_IN_HOUR); } private static final Map UNIT_MAP = new HashMap(); // Build the map at system start static { UNIT_MAP.put(ID_YEAR, " yr"); UNIT_MAP.put(ID_MONTH, " mo"); UNIT_MAP.put(ID_WEEK_OF_YEAR, " wk"); UNIT_MAP.put(ID_DAY, " day"); UNIT_MAP.put(ID_HOUR_OF_DAY, " hr"); } /** * Returns "x ago on " by comparing the * given pastDate with the current time. All formats are converted to GMT * time. In the future the user might have their own locale, in which case * we will display the time in their own locale (neat!) * * @param pastDate A date in the past * @param format The format for the pastDate * @return "x ago on " */ public static String getMomentsAgoString(Date pastDate, DateFormat format) { String timeAgo = getMomentsAgoString(pastDate); format.setTimeZone(new SimpleTimeZone(0, "GMT")); if (timeAgo.length() > 0) timeAgo = timeAgo.concat(" on "); return timeAgo.concat(format.format(pastDate)); } /** * Returns "x ago on " by comparing the * given pastDate with the current time. * * @param pastDate A default locale date in the past * @return "x ago" */ public static String getMomentsAgoString(Date pastDate) { Calendar then = Calendar.getInstance(); then.setTime(pastDate); Calendar now = Calendar.getInstance(); String result = null; result = handleUnit(then, now, ID_YEAR); if (result == null) { result = handleUnit(then, now, ID_MONTH); if (result == null) { result = handleUnit(then, now, ID_WEEK_OF_YEAR); if (result == null) { result = handleUnit(then, now, ID_DAY); if (result == null) { result = handleUnit(then, now, ID_HOUR_OF_DAY); if (result == null) { return "< 1 h"; } } } } } return result; } /** * Checks to see if the unit we're comparing is less than the difference of * the given "then" and "now" dates in milliseconds. * * @param then The date we're evaluating * @param now The current time * @param field The field which we're evaluating ("units") * @return null if then is 0 "units" from now, otherwise a displayable * string that will notify the user how long ago then was from now. */ private static String handleUnit(Calendar then, Calendar now, Integer field) { String result = null; long diff = now.getTimeInMillis() - then.getTimeInMillis(); long comparison = ((Long)CONVERSION_MAP.get(field)).longValue(); if (diff > comparison) { long timeAgo = diff / comparison; result = String.valueOf(timeAgo).concat((String)UNIT_MAP.get(field)); //if (timeAgo > 1) result = result.concat(PLURAL); //result = result.concat(AGO); } return result; } }azureus-4.3.0.6/com/aelitis/azureus/core/update/0000755000175000017500000000000011310377630020757 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/update/impl/0000755000175000017500000000000011310377630021720 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/update/impl/AzureusRestarterImpl.java0000644000175000017500000004547311225222414026746 0ustar adrianadrian/* * Created on May 16, 2004 * Created by Olivier Chalouhi * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.update.impl; import java.io.*; import java.util.Properties; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.platform.unix.ScriptAfterShutdown; import org.gudy.azureus2.platform.win32.access.AEWin32Access; import org.gudy.azureus2.platform.win32.access.AEWin32Manager; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.platform.PlatformManagerException; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.update.UpdaterUtils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.update.AzureusRestarter; public class AzureusRestarterImpl implements AzureusRestarter { private static final LogIDs LOGID = LogIDs.CORE; private static final String MAIN_CLASS = "org.gudy.azureus2.update.Updater"; private static final String UPDATER_JAR = "Updater.jar"; private static final String EXE_UPDATER = "AzureusUpdater.exe"; public static final String UPDATE_PROPERTIES = "update.properties"; protected static boolean restarted = false; private static String JAVA_EXEC_DIR = System.getProperty("java.home") + System.getProperty("file.separator") + "bin" + System.getProperty("file.separator"); protected AzureusCore azureus_core; protected String classpath_prefix; public AzureusRestarterImpl( AzureusCore _azureus_core ) { azureus_core = _azureus_core; } public void restart( boolean update_only ) { if ( restarted ){ Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "AzureusRestarter: already restarted!!!!")); return; } restarted = true; PluginInterface pi = azureus_core.getPluginManager().getPluginInterfaceByID( "azupdater" ); if ( pi == null ){ Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Can't restart, mandatory plugin 'azupdater' not found")); return; } String updater_dir = pi.getPluginDirectoryName(); classpath_prefix = updater_dir + File.separator + UPDATER_JAR; String app_path = SystemProperties.getApplicationPath(); while( app_path.endsWith(File.separator)){ app_path = app_path.substring(0,app_path.length()-1); } String user_path = SystemProperties.getUserPath(); while( user_path.endsWith(File.separator)){ user_path = user_path.substring(0,user_path.length()-1); } String config_override = System.getProperty( SystemProperties.SYS_PROP_CONFIG_OVERRIDE ); if ( config_override == null ){ config_override = ""; } String[] parameters = { update_only?"updateonly":"restart", app_path, user_path, config_override, }; FileOutputStream fos = null; try{ Properties restart_properties = new Properties(); long max_mem = Runtime.getRuntime().maxMemory(); restart_properties.put( "max_mem", ""+max_mem ); restart_properties.put( "app_name", SystemProperties.getApplicationName()); restart_properties.put( "app_entry", SystemProperties.getApplicationEntryPoint()); if ( System.getProperty( "azureus.nativelauncher" ) != null || Constants.isOSX ){ //NOTE: new 2306 osx bundle now sets azureus.nativelauncher=1, but older bundles dont try{ String cmd = PlatformManagerFactory.getPlatformManager().getApplicationCommandLine(); if ( cmd != null ){ restart_properties.put( "app_cmd", cmd ); } }catch( Throwable e ){ Debug.printStackTrace(e); } } fos = new FileOutputStream( new File( user_path, UPDATE_PROPERTIES )); // this handles unicode chars by writing \\u escapes restart_properties.store(fos, "Azureus restart properties" ); }catch( Throwable e ){ Debug.printStackTrace( e ); }finally{ if ( fos != null ){ try{ fos.close(); }catch( Throwable e ){ Debug.printStackTrace(e); } } } String[] properties = { "-Duser.dir=\"" + app_path + "\"" }; ByteArrayOutputStream os = new ByteArrayOutputStream(); restartAzureus(new PrintWriter(os) { public void println(String str) { // we intercept these logs and log immediately Logger.log(new LogEvent(LOGID, str)); } }, MAIN_CLASS, properties, parameters, update_only); // just check if any non-logged data exists byte[] bytes = os.toByteArray(); if ( bytes.length > 0 ){ Logger.log(new LogEvent(LOGID, "AzureusRestarter: extra log - " + new String(bytes))); } } private String getClassPath() { String classPath = System.getProperty("java.class.path"); classPath = classpath_prefix + System.getProperty("path.separator") + classPath; return( "-classpath \"" + classPath + "\" " ); } private boolean win32NativeRestart( PrintWriter log, String exec ) { try{ // we need to spawn without inheriting handles PlatformManager pm = PlatformManagerFactory.getPlatformManager(); pm.createProcess( exec, false ); return( true ); }catch(Throwable e) { e.printStackTrace(log); return( false ); } } private String getExeUpdater(PrintWriter log) { try { // Vista test: We will need to run an elevated EXE updater if we can't // write to the program dir. if (Constants.isWindowsVistaOrHigher ) { if (PluginInitializer.getDefaultInterface().getUpdateManager().getInstallers().length > 0) { log.println("Vista restart w/Updates.. checking if EXE needed"); try { final File writeFile = FileUtil.getApplicationFile("write.dll"); // should fail if no perms, but sometimes it's created in // virtualstore (if ran from java(w).exe for example) FileOutputStream fos = new FileOutputStream(writeFile); fos.write(32); fos.close(); writeFile.delete(); File renameFile = FileUtil.getApplicationFile("License.txt"); if (renameFile != null && renameFile.exists()) { File oldFile = FileUtil.getApplicationFile("License.txt"); String oldName = renameFile.getName(); File newFile = new File(renameFile.getParentFile(), oldName + ".bak"); renameFile.renameTo(newFile); if (oldFile.exists()) { log.println("Requiring EXE because rename test failed"); return EXE_UPDATER; } newFile.renameTo(oldFile); } else { log.println("Could not try Permission Test 2. File " + renameFile + " not found"); } } catch (Exception e) { log.println("Permission Test Failed. " + e.getMessage() + ";" + Debug.getCompressedStackTrace()); return EXE_UPDATER; } } } } catch (Throwable t) { // ignore vista test } return null; } private boolean restartViaEXE(PrintWriter log, String exeUpdater, String[] properties, String[] parameters, String backupJavaRunString, boolean update_only) { String azRunner = null; File fileRestart = null; if (!update_only) { try { azRunner = PlatformManagerFactory.getPlatformManager().getApplicationCommandLine(); } catch (PlatformManagerException e) { // TODO Auto-generated catch block e.printStackTrace(); } } try { int result; AEWin32Access accessor = AEWin32Manager.getAccessor(true); if (accessor == null) { result = -123; } else { if (azRunner != null) { // create a batch file to run the updater, then to restart azureus // bceause the updater would restart azureus as administrator user // and confuse the user fileRestart = FileUtil.getUserFile("restart.bat"); String s = "title Azureus Updater Runner\r\n"; s += exeUpdater + " \"updateonly\""; for (int i = 1; i < parameters.length; i++) { s += " \"" + parameters[i].replaceAll("\\\"", "") + "\""; } s += "\r\n"; s += "start \"\" \"" + azRunner + "\""; FileUtil.writeBytesAsFile(fileRestart.getAbsolutePath(), s.getBytes()); result = accessor.shellExecute(null, fileRestart.getAbsolutePath(), null, SystemProperties.getApplicationPath(), AEWin32Access.SW_SHOWMINIMIZED); } else { String execEXE = "\"-J" + getClassPath().replaceAll("\\\"", "") + "\" "; for (int i = 0; i < properties.length; i++) { execEXE += "\"-J" + properties[i].replaceAll("\\\"", "") + "\" "; } for (int i = 0; i < parameters.length; i++) { execEXE += " \"" + parameters[i].replaceAll("\\\"", "") + "\""; } log.println("Launch via " + exeUpdater + " params " + execEXE); result = accessor.shellExecute(null, exeUpdater, execEXE, SystemProperties.getApplicationPath(), AEWin32Access.SW_NORMAL); } } /* * Some results: * 0: OOM * 2: FNF * 3: Path Not Foud * 5: Access Denied (User clicked cancel on admin access dialog) * 8: OOM * 11: Bad Format * 26: Sharing Violation * 27: Association incomplete * 28: DDE Timeout * 29: DDE Fail * 30: DDE Busy * 31: No Association * 32: DLL Not found * >32: OK! */ log.println(" -> " + result); if (result <= 32) { String sErrorReason = ""; String key = null; switch (result) { case 0: case 8: key = "oom"; break; case 2: key = "fnf"; break; case 3: key = "pnf"; break; case 5: key = "denied"; break; case 11: key = "bad"; break; case -123: key = "nowin32"; break; default: sErrorReason = "" + result; break; } if (key != null) { sErrorReason = MessageText.getString("restart.error." + key, new String[] { exeUpdater, SystemProperties.getApplicationPath(), }); } Logger.log(new LogAlert(false, LogAlert.AT_ERROR, MessageText.getString("restart.error", new String[] { sErrorReason }))); return false; } } catch (Throwable f) { f.printStackTrace(log); return javaSpawn(log, backupJavaRunString); } return true; } // ****************** This code is copied into Restarter / Updater so make changes there too !!! public void restartAzureus( PrintWriter log, String mainClass, String[] properties, String[] parameters, boolean update_only) { if(Constants.isOSX){ restartAzureus_OSX(log,mainClass,properties,parameters); }else if( Constants.isUnix ){ restartAzureus_Unix(log,mainClass,properties,parameters); }else{ restartAzureus_win32(log,mainClass,properties,parameters,update_only); } } private void restartAzureus_win32( PrintWriter log, String mainClass, String[] properties, String[] parameters, boolean update_only) { String exeUpdater = getExeUpdater(log); // Not for Updater.java String exec; //Classic restart way using Runtime.exec directly on java(w) exec = "\"" + JAVA_EXEC_DIR + "javaw\" " + getClassPath() + getLibraryPath(); for (int i = 0; i < properties.length; i++) { exec += properties[i] + " "; } exec += mainClass; for (int i = 0; i < parameters.length; i++) { exec += " \"" + parameters[i] + "\""; } if (exeUpdater != null) { restartViaEXE(log, exeUpdater, properties, parameters, exec, update_only); } else { if (log != null) { log.println(" " + exec); } if (!win32NativeRestart(log, exec)) { javaSpawn(log, exec); } } } private boolean javaSpawn( PrintWriter log, String execString) { try { // hmm, try java method - this WILL inherit handles but might work :) log.println("Using java spawn"); //NOTE: no logging done here, as we need the method to return right away, before the external process completes Process p = Runtime.getRuntime().exec(execString); log.println(" -> " + p); return true; } catch (Throwable g) { g.printStackTrace(); return false; } } private void restartAzureus_OSX( PrintWriter log, String mainClass, String[] properties, String[] parameters) { String exec = "\"" + JAVA_EXEC_DIR + "java\" " + getClassPath() + getLibraryPath(); for (int i=0;i= 0 && scriptVersion > 0; if (restartByScript) { exec += "-Dazureus.script.version=\"" + scriptVersion + "\" "; } exec += mainClass ; for(int i = 0 ; i < parameters.length ; i++) { exec += " \"" + parameters[i] + "\""; } if (restartByScript) { // run script after az shutdown to launch updater and then re-run az ScriptAfterShutdown.addExtraCommand("echo \"Applying (possible) patches before restarting..\"\n" + exec + "\n" + "echo \"Restarting Azureus..\"\n" + "$0\n"); ScriptAfterShutdown.setRequiresExit(true); } else { runExternalCommandViaUnixShell( log, exec ); } } private String getLibraryPath() { String libraryPath = System.getProperty("java.library.path"); if ( libraryPath == null ){ libraryPath = ""; }else{ // remove any quotes from the damn thing String temp = ""; for (int i=0;i 0 ){ libraryPath = "-Djava.library.path=\"" + libraryPath + "\" "; } } return( libraryPath ); } /* private void logStream(String message,InputStream stream,PrintWriter log) { BufferedReader br = new BufferedReader (new InputStreamReader(stream)); String line = null; boolean first = true; try { while((line = br.readLine()) != null) { if( first ) { log.println(message); first = false; } log.println(line); } } catch(Exception e) { log.println(e); e.printStackTrace(log); } } private void chMod(String fileName,String rights,PrintWriter log) { String[] execStr = new String[3]; execStr[0] = "chmod"; execStr[1] = rights; execStr[2] = fileName; runExternalCommandsLogged( log, execStr ); } private Process runExternalCommandLogged( PrintWriter log, String command ) { //NOTE: will not return until external command process has completed log.println("About to execute: R:[" +command+ "]" ); try { Process runner = Runtime.getRuntime().exec( command ); runner.waitFor(); logStream( "runtime.exec() output:", runner.getInputStream(), log); logStream( "runtime.exec() error:", runner.getErrorStream(), log); return runner; } catch( Throwable t ) { log.println( t.getMessage() != null ? t.getMessage() : "" ); log.println( t ); t.printStackTrace( log ); return null; } } private Process runExternalCommandsLogged( PrintWriter log, String[] commands ) { //NOTE: will not return until external command process has completed String cmd = "About to execute: R:["; for( int i=0; i < commands.length; i++ ) { cmd += commands[i]; if( i < commands.length -1 ) cmd += " "; } cmd += "]"; log.println( cmd ); try { Process runner = Runtime.getRuntime().exec( commands ); runner.waitFor(); logStream( "runtime.exec() output:", runner.getInputStream(), log); logStream( "runtime.exec() error:", runner.getErrorStream(), log); return runner; } catch( Throwable t ) { log.println( t.getMessage() != null ? t.getMessage() : "" ); log.println( t ); t.printStackTrace( log ); return null; } } */ private void runExternalCommandViaUnixShell( PrintWriter log, String command ) { String[] to_run = new String[3]; to_run[0] = "/bin/sh"; to_run[1] = "-c"; to_run[2] = command; if( log != null ) log.println("Executing: R:[" +to_run[0]+ " " +to_run[1]+ " " +to_run[2]+ "]" ); try { //NOTE: no logging done here, as we need the method to return right away, before the external process completes Runtime.getRuntime().exec( to_run ); } catch(Throwable t) { if( log != null ) { log.println( t.getMessage() != null ? t.getMessage() : "" ); log.println( t ); t.printStackTrace( log ); } else { t.printStackTrace(); } } } } azureus-4.3.0.6/com/aelitis/azureus/core/update/AzureusRestarterFactory.java0000644000175000017500000000242010373051036026477 0ustar adrianadrian/* * Created on 17-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.update; /** * @author parg * */ import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.update.impl.*; public class AzureusRestarterFactory { public static AzureusRestarter create( AzureusCore azureus_core ) { return( new AzureusRestarterImpl( azureus_core )); } } azureus-4.3.0.6/com/aelitis/azureus/core/update/AzureusRestarter.java0000644000175000017500000000213610373051036025153 0ustar adrianadrian/* * Created on 17-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.update; /** * @author parg * */ public interface AzureusRestarter { public void restart( boolean update_only ); } azureus-4.3.0.6/com/aelitis/azureus/core/custom/0000755000175000017500000000000011310377620021006 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/custom/impl/0000755000175000017500000000000011310377620021747 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/custom/impl/CustomizationImpl.java0000644000175000017500000000713111066150752026311 0ustar adrianadrian/* * Created on Sep 22, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.custom.impl; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.custom.Customization; import com.aelitis.azureus.core.custom.CustomizationException; public class CustomizationImpl implements Customization { private CustomizationManagerImpl manager; private String name; private String version; private File contents; protected CustomizationImpl( CustomizationManagerImpl _manager, String _name, String _version, File _contents ) throws CustomizationException { manager = _manager; name = _name; version = _version; contents = _contents; if ( !contents.exists()){ throw( new CustomizationException( "Content file '" + contents + " not found" )); } } public String getName() { return( name ); } public String getVersion() { return( version ); } protected File getContents() { return( contents ); } public Object getProperty( String name ) { return( null ); } public boolean isActive() { return( true ); } public void setActive( boolean active ) { // TODO: } public InputStream getResource( String resource_name ) { return( null ); } public InputStream[] getResources( String resource_name ) { List result = new ArrayList(); ZipInputStream zis = null; try{ zis = new ZipInputStream( new BufferedInputStream( new FileInputStream( contents ) )); while( true ){ ZipEntry entry = zis.getNextEntry(); if ( entry == null ){ break; } String name = entry.getName(); int pos = name.indexOf( resource_name + "/" ); if ( pos != -1 ){ if ( name.endsWith( ".vuze" )){ ByteArrayOutputStream baos = new ByteArrayOutputStream( 16*1024 ); byte[] buffer = new byte[16*1024]; while( true ){ int len = zis.read( buffer ); if ( len <= 0 ){ break; } baos.write( buffer, 0, len ); } result.add( new ByteArrayInputStream( baos.toByteArray())); } } } }catch( Throwable e ){ Debug.out( e ); }finally{ if ( zis != null ){ try{ zis.close(); }catch( Throwable e ){ } } } return((InputStream[])result.toArray( new InputStream[result.size()])); } public void exportToVuzeFile( File file ) throws CustomizationException { manager.exportCustomization( this, file ); } } azureus-4.3.0.6/com/aelitis/azureus/core/custom/impl/CustomizationManagerImpl.java0000644000175000017500000002300011100240656027565 0ustar adrianadrian/* * Created on Sep 9, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.custom.impl; import java.io.*; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import com.aelitis.azureus.core.custom.*; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.core.vuzefile.VuzeFileComponent; import com.aelitis.azureus.core.vuzefile.VuzeFileHandler; import com.aelitis.azureus.core.vuzefile.VuzeFileProcessor; public class CustomizationManagerImpl implements CustomizationManager { private static CustomizationManagerImpl singleton = new CustomizationManagerImpl(); public static CustomizationManager getSingleton() { return( singleton ); } private Map customization_file_map = new HashMap(); private String current_customization_name; private CustomizationImpl current_customization; protected CustomizationManagerImpl() { VuzeFileHandler.getSingleton().addProcessor( new VuzeFileProcessor() { public void process( VuzeFile[] files, int expected_types ) { for (int i=0;i_.zip where version is numeric and dot separated" ); } protected void importCustomization( Map map ) throws CustomizationException { try{ String name = new String((byte[])map.get( "name" ), "UTF-8" ); String version = new String((byte[])map.get( "version" ), "UTF-8" ); if ( !Constants.isValidVersionFormat( version )){ throw( new CustomizationException( "Invalid version specification: " + version )); } byte[] data = (byte[])map.get( "data" ); File user_dir = FileUtil.getUserFile("custom"); if ( !user_dir.exists()){ user_dir.mkdirs(); } File target = new File( user_dir, name + "_" + version + ".zip" ); if ( !target.exists()){ if ( !FileUtil.writeBytesAsFile2( target.getAbsolutePath(), data )){ throw( new CustomizationException( "Failed to save customization to " + target )); } } }catch( CustomizationException e ){ throw( e ); }catch( Throwable e ){ throw( new CustomizationException( "Failed to import customization", e )); } } protected void exportCustomization( CustomizationImpl cust, File to_file ) throws CustomizationException { if ( to_file.isDirectory()){ to_file = new File( to_file, cust.getName() + "_" + cust.getVersion() + ".vuze"); } if ( !to_file.getName().endsWith( ".vuze" )){ to_file = new File( to_file.getParentFile(), to_file.getName() + ".vuze" ); } try{ Map contents = new HashMap(); byte[] data = FileUtil.readFileAsByteArray( cust.getContents()); contents.put( "name", cust.getName()); contents.put( "version", cust.getVersion()); contents.put( "data", data ); VuzeFile vf = VuzeFileHandler.getSingleton().create(); vf.addComponent( VuzeFileComponent.COMP_TYPE_CUSTOMIZATION, contents); vf.write( to_file ); }catch( Throwable e ){ throw( new CustomizationException( "Failed to export customization", e )); } } public Customization getActiveCustomization() { synchronized( this ){ if ( current_customization == null ){ if ( current_customization_name != null ){ String[] entry = (String[])customization_file_map.get( current_customization_name ); if ( entry != null ){ try{ current_customization = new CustomizationImpl( this, current_customization_name, entry[0], new File( entry[1] )); SimpleTimer.addEvent( "Custom:clear", SystemTime.getCurrentTime() + 120*1000, new TimerEventPerformer() { public void perform( TimerEvent event ) { synchronized( CustomizationManagerImpl.this ){ current_customization = null; } } }); }catch( CustomizationException e ){ e.printStackTrace(); } } } } return( current_customization ); } } public Customization[] getCustomizations() { List result = new ArrayList(); synchronized( this ){ Iterator it = customization_file_map.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); String name = (String)entry.getKey(); String[] bits = (String[])entry.getValue(); String version = (String)bits[0]; File file = new File(bits[1]); try{ CustomizationImpl cust = new CustomizationImpl( this, name, version, file ); result.add( cust ); }catch( Throwable e ){ } } } return((Customization[])result.toArray(new Customization[result.size()])); } public static void main( String[] args ) { try{ CustomizationManagerImpl manager = (CustomizationManagerImpl)getSingleton(); CustomizationImpl cust = new CustomizationImpl( manager, "blah", "1.2", new File( "C:\\temp\\cust\\details.zip" )); cust.exportToVuzeFile( new File( "C:\\temp\\cust" )); }catch( Throwable e ){ e.printStackTrace(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/custom/CustomizationManager.java0000644000175000017500000000171611062635754026032 0ustar adrianadrian/* * Created on Sep 9, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.custom; public interface CustomizationManager { public Customization getActiveCustomization(); public Customization[] getCustomizations(); } azureus-4.3.0.6/com/aelitis/azureus/core/custom/Customization.java0000644000175000017500000000302711113203332024510 0ustar adrianadrian/* * Created on Sep 9, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.custom; import java.io.File; import java.io.InputStream; public interface Customization { public static final String RT_META_SEARCH_TEMPLATES = "metasearch"; // InputStream[] public static final String RT_SUBSCRIPTIONS = "subs"; // InputStream[] public static final String RT_CNETWORKS = "cnetworks"; // InputStream[] public String getName(); public String getVersion(); public Object getProperty( String name ); public boolean isActive(); public void setActive( boolean active ); public InputStream getResource( String resource_name ); public InputStream[] getResources( String resource_name ); public void exportToVuzeFile( File file ) throws CustomizationException; } azureus-4.3.0.6/com/aelitis/azureus/core/custom/CustomizationException.java0000644000175000017500000000204111066106654026402 0ustar adrianadrian/* * Created on Sep 22, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.custom; public class CustomizationException extends Exception { public CustomizationException( String str ) { super( str ); } public CustomizationException( String str, Throwable c ) { super( str, c ); } } azureus-4.3.0.6/com/aelitis/azureus/core/custom/CustomizationManagerFactory.java0000644000175000017500000000204511066106654027352 0ustar adrianadrian/* * Created on Sep 9, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.custom; import com.aelitis.azureus.core.custom.impl.CustomizationManagerImpl; public class CustomizationManagerFactory { public static CustomizationManager getSingleton() { return( CustomizationManagerImpl.getSingleton()); } } azureus-4.3.0.6/com/aelitis/azureus/core/AzureusCoreListener.java0000644000175000017500000000234610462170550024321 0ustar adrianadrian/* * Created on 14-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core; /** * @author parg * */ public interface AzureusCoreListener { public void reportCurrentTask( AzureusCoreOperation operation, String currentTask ); public void reportPercent( AzureusCoreOperation operation, int percent ); } azureus-4.3.0.6/com/aelitis/azureus/core/neuronal/0000755000175000017500000000000011310377630021320 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/neuronal/NeuralNetworkLayer.java0000644000175000017500000001021711122373126025756 0ustar adrianadrianpackage com.aelitis.azureus.core.neuronal; public class NeuralNetworkLayer { int numberOfNodes; double[][] weights; double[][] weightChanges; double[] neuronValues; double[] desiredValues; double[] errors; double[] biasWeights; double[] biasValues; double learningRate; boolean linearOutput; boolean useMomentum; double momentumFactor; NeuralNetworkLayer parentLayer; NeuralNetworkLayer childLayer; ActivationFunction activationFunction; public NeuralNetworkLayer(int numberOfNodes) { this.numberOfNodes = numberOfNodes; linearOutput = false; useMomentum = false; momentumFactor = 0.9; } public void initialize(NeuralNetworkLayer parentLayer,NeuralNetworkLayer childLayer) { neuronValues = new double[numberOfNodes]; desiredValues = new double[numberOfNodes]; errors = new double[numberOfNodes]; this.parentLayer = parentLayer; if(childLayer != null) { this.childLayer = childLayer; weights = new double[numberOfNodes][childLayer.getNumberOfNodes()]; weightChanges = new double[numberOfNodes][childLayer.getNumberOfNodes()]; biasValues = new double[childLayer.getNumberOfNodes()]; biasWeights = new double[childLayer.getNumberOfNodes()]; for(int j = 0 ; j < childLayer.getNumberOfNodes() ; j++) { biasValues[j] = -1; biasWeights[j] = 0; } } } public void randomizeWeights() { for(int i = 0 ; i < numberOfNodes ; i++) { for(int j = 0 ; j < childLayer.getNumberOfNodes() ; j++) { weights[i][j] = Math.random() * 2 - 1; } } for(int j = 0 ; j < childLayer.getNumberOfNodes() ; j++) { biasWeights[j] = Math.random() * 2 - 1; } } public void calculateNeuronValues() { if(parentLayer != null) { for(int j = 0 ; j < numberOfNodes ; j++) { double x = 0; for(int i = 0 ; i < parentLayer.getNumberOfNodes() ; i++) { x += parentLayer.neuronValues[i] * parentLayer.weights[i][j]; } x+= parentLayer.biasValues[j] * parentLayer.biasWeights[j]; if(childLayer == null && linearOutput) { neuronValues[j] = x; } else { neuronValues[j] = activationFunction.getValueFor(x); } } } } public void calculateErrors() { if(childLayer == null) { // output layer for(int i = 0 ; i < numberOfNodes ; i++) { errors[i] = (desiredValues[i] - neuronValues[i]) * activationFunction.getDerivedFunctionValueFor(neuronValues[i]); } } else if(parentLayer == null) { //input layer for(int i = 0 ; i < numberOfNodes ; i++) { errors[i] = 0.0; } } else { // hidden layer for(int i = 0 ; i < numberOfNodes ; i++) { double sum = 0; for(int j = 0 ; j < childLayer.getNumberOfNodes() ; j++) { sum += childLayer.errors[j] * weights[i][j]; } errors[i] = sum * activationFunction.getDerivedFunctionValueFor(neuronValues[i]); } } } public void adjustWeights() { if(childLayer != null) { for(int i = 0 ; i < numberOfNodes ; i++) { for(int j = 0 ; j < childLayer.getNumberOfNodes() ; j++) { double dw = learningRate * childLayer.errors[j] * neuronValues[i]; if(useMomentum) { weights[i][j] += dw + momentumFactor * weightChanges[i][j]; weightChanges[i][j] = dw; } else { weights[i][j] += dw; } } } for(int j = 0 ; j < childLayer.getNumberOfNodes() ; j++) { biasWeights[j] += learningRate * childLayer.errors[j] * biasValues[j]; } } } public int getNumberOfNodes() { return numberOfNodes; } public void setActivationFunction(ActivationFunction activationFunction) { this.activationFunction = activationFunction; } public void setMomentum(boolean useMomentum,double factor) { this.useMomentum = useMomentum; this.momentumFactor = factor; } public void setLearningRate(double rate) { this.learningRate = rate; } public String toString() { StringBuffer sb = new StringBuffer(); if(childLayer != null) { for(int j = 0 ; j < childLayer.getNumberOfNodes() ; j++) { sb.append(j); sb.append("\t> "); for(int i = 0 ; i < numberOfNodes ; i++) { sb.append(i); sb.append(":"); sb.append(weights[i][j]); sb.append("\t"); } sb.append("\n"); } } return sb.toString(); } } azureus-4.3.0.6/com/aelitis/azureus/core/neuronal/NeuralNetwork.java0000644000175000017500000000505111122373126024761 0ustar adrianadrianpackage com.aelitis.azureus.core.neuronal; public class NeuralNetwork { NeuralNetworkLayer inputLayer; NeuralNetworkLayer hiddenLayer; NeuralNetworkLayer outputLayer; public NeuralNetwork(int nbInputNodes, int nbHiddenNodes, int nbOutputNodes) { inputLayer = new NeuralNetworkLayer(nbInputNodes); hiddenLayer = new NeuralNetworkLayer(nbHiddenNodes); outputLayer = new NeuralNetworkLayer(nbOutputNodes); inputLayer.initialize(null, hiddenLayer); inputLayer.randomizeWeights(); hiddenLayer.initialize(inputLayer, outputLayer); hiddenLayer.randomizeWeights(); outputLayer.initialize(hiddenLayer, null); } public void setActivationFunction(ActivationFunction activationFunction) { inputLayer.setActivationFunction(activationFunction); hiddenLayer.setActivationFunction(activationFunction); outputLayer.setActivationFunction(activationFunction); } public void setInput(int i, double value) { if(i >= 0 && i < inputLayer.getNumberOfNodes()) { inputLayer.neuronValues[i] = value; } } public double getOutput(int i) { if(i >= 0 && i < outputLayer.getNumberOfNodes()) { return outputLayer.neuronValues[i]; } return Double.NaN; } public void setDesiredOutput(int i, double value) { if(i >= 0 && i < outputLayer.getNumberOfNodes()) { outputLayer.desiredValues[i] = value; } } public void setMomentum(boolean useMomentum, double factor) { inputLayer.setMomentum(useMomentum,factor); hiddenLayer.setMomentum(useMomentum,factor); outputLayer.setMomentum(useMomentum,factor); } public void setLearningRate(double rate) { inputLayer.setLearningRate(rate); hiddenLayer.setLearningRate(rate); outputLayer.setLearningRate(rate); } public void feedForward() { inputLayer.calculateNeuronValues(); hiddenLayer.calculateNeuronValues(); outputLayer.calculateNeuronValues(); } public void backPropagate() { outputLayer.calculateErrors(); hiddenLayer.calculateErrors(); hiddenLayer.adjustWeights(); inputLayer.adjustWeights(); } public double calculateError() { double error = 0.0; for(int i = 0 ; i < outputLayer.numberOfNodes ; i++) { error += Math.pow(outputLayer.neuronValues[i] - outputLayer.desiredValues[i], 2.0); } error /= outputLayer.numberOfNodes; return error; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("Input Layer :\n"); sb.append(inputLayer.toString()); sb.append("\n\n"); sb.append("Hidden Layer :\n"); sb.append(hiddenLayer.toString()); sb.append("\n\n"); return sb.toString(); } } azureus-4.3.0.6/com/aelitis/azureus/core/neuronal/LogisticActivationFunction.java0000644000175000017500000000042511122373126027466 0ustar adrianadrianpackage com.aelitis.azureus.core.neuronal; public class LogisticActivationFunction implements ActivationFunction { public double getDerivedFunctionValueFor(double x) { return x * (1-x); } public double getValueFor(double x) { return 1.0 / (1.0 + Math.exp(-x)); } } azureus-4.3.0.6/com/aelitis/azureus/core/neuronal/ActivationFunction.java0000644000175000017500000000026411122373126025771 0ustar adrianadrianpackage com.aelitis.azureus.core.neuronal; public interface ActivationFunction { public double getValueFor(double x); public double getDerivedFunctionValueFor(double x); } azureus-4.3.0.6/com/aelitis/azureus/core/neuronal/NeuralSpeedLimiter.java0000644000175000017500000001431611130763626025731 0ustar adrianadrianpackage com.aelitis.azureus.core.neuronal; public class NeuralSpeedLimiter { //in bytes / sec long maxDlSpeed; long maxUlSpeed; long ulSpeed; long dlSpeed; //in ms long minLatency; long maxLatency; long latency; NeuralNetwork neuralNetwork; private boolean dirty; private double currentULTarget = 0.6; double trainingSet[][] = new double[][] { //dl speed, ul speed, latency, no_down_limit, down_limit, no_up_limit, up_limit //no latency => no limits {0.0, 0.0, 0.0, 0.9, 0.9, 0.9, 0.9}, {0.0, 1.0, 0.0, 0.9, 0.9, 0.9, 0.9}, {1.0, 0.0, 0.0, 0.9, 0.9, 0.9, 0.9}, {1.0, 1.0, 0.0, 0.9, 0.9, 0.9, 0.9}, //no download, high upload, mid-high latency => limit upload {0.0, 1.0, 1.0, 0.9, 0.9, 0.1, 0.1}, {0.0, 1.0, 0.3, 0.9, 0.9, 0.1, 0.1}, //no download, high upload, low-mid latency => some limit upload {0.0, 1.0, 0.1, 0.9, 0.9, 0.1, 0.8}, {0.0, 1.0, 0.2, 0.9, 0.9, 0.1, 0.6}, //no upload, high download, mid-high latency => limit download {1.0, 0.0, 1.0, 0.1, 0.5, 0.9, 0.9}, {1.0, 0.0, 0.3, 0.1, 0.6, 0.9, 0.9}, //no upload, high download, low-mid latency => some limit download {1.0, 0.0, 0.1, 0.1, 0.9, 0.9, 0.9}, {1.0, 0.0, 0.2, 0.1, 0.8, 0.9, 0.9}, }; public NeuralSpeedLimiter() { neuralNetwork = new NeuralNetwork(3,4,4); neuralNetwork.setLearningRate(0.05); neuralNetwork.setMomentum(true, 0.9); neuralNetwork.setActivationFunction(new LogisticActivationFunction()); train(); dirty = false; } private void train() { //System.out.println(neuralNetwork); double error = 1.0; int c = 0; while(error > 0.002 && c < 200000) { error = 0; for(int i = 0 ; i maxUlSpeed) maxUlSpeed = ulSpeed; if(dlSpeed > maxDlSpeed) maxDlSpeed = dlSpeed; if(latency > maxLatency) maxLatency = latency; if(latency < minLatency) minLatency = latency; double downloadFactor = (double)dlSpeed / maxDlSpeed; double uploadFactor = (double)ulSpeed / maxUlSpeed; double latencyFactor = ((double)latency - (double)minLatency) / maxLatency; neuralNetwork.setInput(0, downloadFactor); neuralNetwork.setInput(1, uploadFactor); neuralNetwork.setInput(2, latencyFactor); dirty = true; } catch(Throwable t) { //Ignore } } private void retrain(double ulTarget) { resetInput(); neuralNetwork.feedForward(); double shouldLimitDownload = neuralNetwork.getOutput(0); double downloadLimit = neuralNetwork.getOutput(1); double downloadFactor = (double)dlSpeed / maxDlSpeed; double uploadFactor = (double)ulSpeed / maxUlSpeed; double latencyFactor = ((double)latency - (double)minLatency) / maxLatency; double error = 1.0; int c = 0; //Only 100 loops at a time while(error > 0.002 && c < 400) { neuralNetwork.setInput(0, downloadFactor); neuralNetwork.setInput(1, uploadFactor); neuralNetwork.setInput(2, latencyFactor); neuralNetwork.setDesiredOutput(0, shouldLimitDownload); neuralNetwork.setDesiredOutput(1, downloadLimit); neuralNetwork.setDesiredOutput(2, 0.9); neuralNetwork.setDesiredOutput(3, ulTarget); neuralNetwork.feedForward(); error = neuralNetwork.calculateError(); neuralNetwork.backPropagate(); c++; } } private void feedForward() { neuralNetwork.feedForward(); dirty = false; double latencyFactor = ((double)latency - (double)minLatency) / maxLatency; if(latencyFactor >= 0.15) { //So, we have a high latency, let's re-train the neural network to lower upload speed in this case currentULTarget = currentULTarget * 0.97; retrain(currentULTarget); } else if(latencyFactor < 0.05) { //So, we have a low latency, let's re-train the neural network to increase upload speed in this case currentULTarget = currentULTarget * 1.02; retrain(currentULTarget); } /*System.out.println("input : " + (double)dlSpeed/maxDlSpeed + ", " + (double)ulSpeed/maxUlSpeed + ", " + ((double)latency-(double)minLatency)/maxLatency); System.out.println("output : " + neuralNetwork.getOutput(0) + ", " + neuralNetwork.getOutput(1) + ", " + neuralNetwork.getOutput(2) + ", " + neuralNetwork.getOutput(3));*/ } public void setMaxDlSpeed(long maxDlSpeed) { if(maxDlSpeed > 0) { this.maxDlSpeed = maxDlSpeed; } resetInput(); } public void setMaxUlSpeed(long maxUlSpeed) { if(maxUlSpeed > 0) { this.maxUlSpeed = maxUlSpeed; } resetInput(); } public void setMinLatency(long minLatency) { if(minLatency >= 0) { this.minLatency = minLatency; } resetInput(); } public void setUlSpeed(long ulSpeed) { if(ulSpeed >= 0) { this.ulSpeed = ulSpeed; } resetInput(); } public void setDlSpeed(long dlSpeed) { if(dlSpeed >= 0) { this.dlSpeed = dlSpeed; } resetInput(); } public void setLatency(long latency) { if(latency >= 0) { this.latency = latency; } resetInput(); } public void setMaxLatency(long maxLatency) { if(maxLatency > 0) { this.maxLatency = maxLatency; } resetInput(); } public boolean shouldLimitDownload() { if(dirty) feedForward(); return neuralNetwork.getOutput(0) < 0.5; } public long getDownloadLimit() { if(dirty) feedForward(); return (long) ( 1.2* maxDlSpeed * neuralNetwork.getOutput(1)); } public boolean shouldLimitUpload() { if(dirty) feedForward(); return neuralNetwork.getOutput(2) < 0.5; } public long getUploadLimit() { if(dirty) feedForward(); return (long) ( 1.2* maxUlSpeed * neuralNetwork.getOutput(3)); } public static void main(String args[]) { new NeuralSpeedLimiter(); } } azureus-4.3.0.6/com/aelitis/azureus/core/pairing/0000755000175000017500000000000011310377630021126 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/pairing/impl/0000755000175000017500000000000011310377630022067 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/pairing/impl/PairingManagerImpl.java0000644000175000017500000006133611272201742026446 0ustar adrianadrian/* * Created on Oct 5, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.pairing.impl; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.URL; import java.text.SimpleDateFormat; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.AEVerifier; import org.gudy.azureus2.core3.util.AsyncDispatcher; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.BEncoder; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DelayedEvent; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.core3.util.TimerEventPeriodic; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.UIManagerEvent; import org.gudy.azureus2.plugins.ui.config.ActionParameter; import org.gudy.azureus2.plugins.ui.config.BooleanParameter; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.plugins.ui.config.HyperlinkParameter; import org.gudy.azureus2.plugins.ui.config.InfoParameter; import org.gudy.azureus2.plugins.ui.config.LabelParameter; import org.gudy.azureus2.plugins.ui.config.Parameter; import org.gudy.azureus2.plugins.ui.config.ParameterListener; import org.gudy.azureus2.plugins.ui.config.StringParameter; import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.plugins.utils.StaticUtilities; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminHTTPProxy; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSocksProxy; import com.aelitis.azureus.core.pairing.*; import com.aelitis.azureus.core.security.CryptoManager; import com.aelitis.azureus.core.security.CryptoManagerFactory; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.plugins.upnp.UPnPPlugin; import com.aelitis.azureus.plugins.upnp.UPnPPluginService; import com.aelitis.net.upnp.UPnPRootDevice; public class PairingManagerImpl implements PairingManager { private static final boolean DEBUG = false; private static final String SERVICE_URL; static{ String url = System.getProperty( "az.pairing.url", "" ); if ( url.length() == 0 ){ SERVICE_URL = Constants.PAIRING_URL; }else{ SERVICE_URL = url; } } private static final PairingManagerImpl singleton = new PairingManagerImpl(); public static PairingManager getSingleton() { return( singleton ); } private static final int GLOBAL_UPDATE_PERIOD = 60*1000; private static final int CD_REFRESH_PERIOD = 23*60*60*1000; private static final int CD_REFRESH_TICKS = CD_REFRESH_PERIOD / GLOBAL_UPDATE_PERIOD; private AzureusCore azureus_core; private BooleanParameter param_enable; private InfoParameter param_ac_info; private InfoParameter param_status_info; private HyperlinkParameter param_view; private BooleanParameter param_e_enable; private StringParameter param_ipv4; private StringParameter param_ipv6; private StringParameter param_host; private Map services = new HashMap(); private AESemaphore init_sem = new AESemaphore( "PM:init" ); private TimerEventPeriodic global_update_event; private InetAddress current_v4; private InetAddress current_v6; private boolean update_outstanding; private boolean updates_enabled; private static final int MIN_UPDATE_PERIOD_DEFAULT = 60*1000; private static final int MAX_UPDATE_PERIOD_DEFAULT = 60*60*1000; private int min_update_period = MIN_UPDATE_PERIOD_DEFAULT; private int max_update_period = MAX_UPDATE_PERIOD_DEFAULT; private AsyncDispatcher dispatcher = new AsyncDispatcher(); private boolean must_update_once; private TimerEvent deferred_update_event; private long last_update_time = -1; private int consec_update_fails; private String last_message; private CopyOnWriteList listeners = new CopyOnWriteList(); protected PairingManagerImpl() { must_update_once = COConfigurationManager.getBooleanParameter( "pairing.updateoutstanding" ); PluginInterface default_pi = PluginInitializer.getDefaultInterface(); final UIManager ui_manager = default_pi.getUIManager(); BasicPluginConfigModel configModel = ui_manager.createBasicPluginConfigModel( ConfigSection.SECTION_CONNECTION, "Pairing"); param_enable = configModel.addBooleanParameter2( "pairing.enable", "pairing.enable", false ); String access_code = readAccessCode(); param_ac_info = configModel.addInfoParameter2( "pairing.accesscode", access_code); param_status_info = configModel.addInfoParameter2( "pairing.status.info", "" ); param_view = configModel.addHyperlinkParameter2( "pairing.view.registered", SERVICE_URL + "/web/view?ac=" + access_code); if ( access_code.length() == 0 ){ param_view.setEnabled( false ); } final ActionParameter ap = configModel.addActionParameter2( "pairing.ac.getnew", "pairing.ac.getnew.create" ); ap.addListener( new ParameterListener() { public void parameterChanged( Parameter param ) { try{ ap.setEnabled( false ); allocateAccessCode( false ); SimpleTimer.addEvent( "PM:enabler", SystemTime.getOffsetTime(30*1000), new TimerEventPerformer() { public void perform( TimerEvent event ) { ap.setEnabled( true ); } }); }catch( Throwable e ){ ap.setEnabled( true ); String details = MessageText.getString( "pairing.alloc.fail", new String[]{ Debug.getNestedExceptionMessage( e )}); ui_manager.showMessageBox( "pairing.op.fail", "!" + details + "!", UIManagerEvent.MT_OK ); } } }); LabelParameter param_e_info = configModel.addLabelParameter2( "pairing.explicit.info" ); param_e_enable = configModel.addBooleanParameter2( "pairing.explicit.enable", "pairing.explicit.enable", false ); param_ipv4 = configModel.addStringParameter2( "pairing.ipv4", "pairing.ipv4", "" ); param_ipv6 = configModel.addStringParameter2( "pairing.ipv6", "pairing.ipv6", "" ); param_host = configModel.addStringParameter2( "pairing.host", "pairing.host", "" ); param_ipv4.setGenerateIntermediateEvents( false ); param_ipv6.setGenerateIntermediateEvents( false ); param_host.setGenerateIntermediateEvents( false ); ParameterListener change_listener = new ParameterListener() { public void parameterChanged( Parameter param ) { updateNeeded(); if ( param == param_enable ){ fireChanged(); } } }; param_enable.addListener( change_listener ); param_e_enable.addListener( change_listener ); param_ipv4.addListener( change_listener ); param_ipv6.addListener( change_listener ); param_host.addListener( change_listener ); param_e_enable.addEnabledOnSelection( param_ipv4 ); param_e_enable.addEnabledOnSelection( param_ipv6 ); param_e_enable.addEnabledOnSelection( param_host ); configModel.createGroup( "pairing.group.explicit", new Parameter[]{ param_e_info, param_e_enable, param_ipv4, param_ipv6, param_host, }); AzureusCoreFactory.addCoreRunningListener( new AzureusCoreRunningListener() { public void azureusCoreRunning( AzureusCore core ) { initialise( core ); } }); } protected void initialise( AzureusCore _core ) { synchronized( this ){ azureus_core = _core; } try{ PluginInterface default_pi = PluginInitializer.getDefaultInterface(); DelayedTask dt = default_pi.getUtilities().createDelayedTask( new Runnable() { public void run() { new DelayedEvent( "PM:delayinit", 30*1000, new AERunnable() { public void runSupport() { enableUpdates(); } }); } }); dt.queue(); }finally{ init_sem.releaseForever(); } } protected void waitForInitialisation() throws PairingException { if ( !init_sem.reserve( 30*1000 )){ throw( new PairingException( "Timeout waiting for initialisation" )); } } public boolean isEnabled() { return( param_enable.getValue()); } protected void setStatus( String str ) { param_status_info.setValue( str ); } protected String readAccessCode() { return( COConfigurationManager.getStringParameter( "pairing.accesscode", "" )); } protected void writeAccessCode( String ac ) { COConfigurationManager.setParameter( "pairing.accesscode", ac ); param_ac_info.setValue( ac ); param_view.setHyperlink( SERVICE_URL + "/web/view?ac=" + ac ); param_view.setEnabled( ac.length() > 0 ); } protected String allocateAccessCode( boolean updating ) throws PairingException { Map request = new HashMap(); String existing = readAccessCode(); request.put( "ac", existing ); Map response = sendRequest( "allocate", request ); try{ String code = getString( response, "ac" ); writeAccessCode( code ); if ( !updating ){ updateNeeded(); } return( code ); }catch( Throwable e ){ throw( new PairingException( "allocation failed", e )); } } public String getAccessCode() throws PairingException { waitForInitialisation(); String ac = readAccessCode(); if ( ac == null || ac.length() == 0 ){ ac = allocateAccessCode( false ); } return( ac ); } public String getReplacementAccessCode() throws PairingException { waitForInitialisation(); String new_code = allocateAccessCode( false ); return( new_code ); } public PairedService addService( String sid ) { synchronized( this ){ PairedServiceImpl result = services.get( sid ); if ( result == null ){ if ( DEBUG ){ System.out.println( "PS: added " + sid ); } result = new PairedServiceImpl( sid ); services.put( sid, result ); } return( result ); } } public PairedService getService( String sid ) { synchronized( this ){ PairedService result = services.get( sid ); return( result ); } } protected void remove( PairedServiceImpl service ) { synchronized( this ){ String sid = service.getSID(); if ( services.remove( sid ) != null ){ if ( DEBUG ){ System.out.println( "PS: removed " + sid ); } } } updateNeeded(); } protected void sync( PairedServiceImpl service ) { updateNeeded(); } protected InetAddress updateAddress( InetAddress current, InetAddress latest, boolean v6 ) { if ( v6 ){ if ( latest instanceof Inet4Address ){ return( current ); } }else{ if ( latest instanceof Inet6Address ){ return( current ); } } if ( current == latest ){ return( current ); } if ( current == null || latest == null ){ return( latest ); } if ( !current.equals( latest )){ return( latest ); } return( current ); } protected void updateGlobals( boolean is_updating ) { synchronized( this ){ NetworkAdmin network_admin = NetworkAdmin.getSingleton(); InetAddress latest_v4 = azureus_core.getInstanceManager().getMyInstance().getExternalAddress(); InetAddress temp_v4 = updateAddress( current_v4, latest_v4, false ); InetAddress latest_v6 = network_admin.getDefaultPublicAddressV6(); InetAddress temp_v6 = updateAddress( current_v6, latest_v6, true ); if ( temp_v4 != current_v4 || temp_v6 != current_v6 ){ current_v4 = temp_v4; current_v6 = temp_v6; if ( !is_updating ){ updateNeeded(); } } } } protected void enableUpdates() { synchronized( this ){ updates_enabled = true; if ( update_outstanding ){ update_outstanding = false; updateNeeded(); } } } protected void updateNeeded() { if ( DEBUG ){ System.out.println( "PS: updateNeeded" ); } synchronized( this ){ if ( updates_enabled ){ dispatcher.dispatch( new AERunnable() { public void runSupport() { doUpdate(); } }); }else{ setStatus( MessageText.getString( "pairing.status.initialising" )); update_outstanding = true; } } } protected void doUpdate() { long now = SystemTime.getMonotonousTime(); synchronized( this ){ if ( deferred_update_event != null ){ return; } long time_since_last_update = now - last_update_time; if ( last_update_time > 0 && time_since_last_update < min_update_period ){ deferUpdate( min_update_period - time_since_last_update ); return; } } try{ Map payload = new HashMap(); boolean is_enabled = param_enable.getValue(); synchronized( this ){ List> list = new ArrayList>(); payload.put( "s", list ); if ( services.size() > 0 && is_enabled ){ if ( global_update_event == null ){ global_update_event = SimpleTimer.addPeriodicEvent( "PM:updater", GLOBAL_UPDATE_PERIOD, new TimerEventPerformer() { private int tick_count; public void perform( TimerEvent event ) { tick_count++; updateGlobals( false ); if ( tick_count % CD_REFRESH_TICKS == 0 ){ updateNeeded(); } } }); updateGlobals( true ); } for ( PairedServiceImpl service: services.values()){ list.add( service.toMap()); } }else{ // when we get to zero services we want to push through the // last update to remove cd if ( global_update_event == null ){ if ( consec_update_fails == 0 && !must_update_once ){ setStatus( MessageText.getString( "pairing.status.disabled" )); return; } }else{ global_update_event.cancel(); global_update_event = null; } } last_update_time = now; } // we need a valid access code here! String ac = readAccessCode(); if ( ac.length() == 0 ){ ac = allocateAccessCode( true ); } payload.put( "ac", ac ); synchronized( this ){ if ( current_v4 != null ){ payload.put( "c_v4", current_v4.getHostAddress()); } if ( current_v6 != null ){ payload.put( "c_v6", current_v6.getHostAddress()); } if ( param_e_enable.getValue()){ String host = param_host.getValue().trim(); if ( host.length() > 0 ){ payload.put( "e_h", host ); } String v4 = param_ipv4.getValue().trim(); if ( v4.length() > 0 ){ payload.put( "e_v4", v4 ); } String v6 = param_ipv6.getValue().trim(); if ( v6.length() > 0 ){ payload.put( "e_v4", v6 ); } } // grab some UPnP info for diagnostics try{ PluginInterface pi_upnp = azureus_core.getPluginManager().getPluginInterfaceByClass( UPnPPlugin.class ); if ( pi_upnp != null ){ UPnPPlugin upnp = (UPnPPlugin)pi_upnp.getPlugin(); if ( upnp.isEnabled()){ List> upnp_list = new ArrayList>(); payload.put( "upnp", upnp_list ); UPnPPluginService[] services = upnp.getServices(); Set devices = new HashSet(); for ( UPnPPluginService service: services ){ UPnPRootDevice root_device = service.getService().getGenericService().getDevice().getRootDevice(); if ( !devices.contains( root_device )){ devices.add( root_device ); Map map = new HashMap(); upnp_list.add( map ); map.put( "i", root_device.getInfo()); } } } } }catch( Throwable e ){ } try{ NetworkAdmin admin = NetworkAdmin.getSingleton(); NetworkAdminHTTPProxy http_proxy = admin.getHTTPProxy(); if ( http_proxy != null ){ payload.put( "hp", http_proxy.getName()); } NetworkAdminSocksProxy[] socks_proxies = admin.getSocksProxies(); if ( socks_proxies.length > 0 ){ payload.put( "sp", socks_proxies[0].getName()); } }catch( Throwable e ){ } payload.put( "_enabled", is_enabled?1L:0L ); } if ( DEBUG ){ System.out.println( "PS: doUpdate: " + payload ); } sendRequest( "update", payload ); synchronized( this ){ consec_update_fails = 0; must_update_once = false; if ( deferred_update_event == null ){ COConfigurationManager.setParameter( "pairing.updateoutstanding", false ); } if ( global_update_event == null ){ setStatus( MessageText.getString( "pairing.status.disabled" )); }else{ setStatus( MessageText.getString( "pairing.status.registered", new String[]{ new SimpleDateFormat().format(new Date( SystemTime.getCurrentTime() ))})); } } }catch( Throwable e ){ synchronized( this ){ consec_update_fails++; long back_off = min_update_period; for (int i=0;i max_update_period ){ back_off = max_update_period; break; } } deferUpdate( back_off ); } } } protected void deferUpdate( long millis ) { millis += 5000; long target = SystemTime.getOffsetTime( millis ); setStatus( MessageText.getString( "pairing.status.pending", new String[]{ new SimpleDateFormat().format(new Date( target ))})); COConfigurationManager.setParameter( "pairing.updateoutstanding", true ); deferred_update_event = SimpleTimer.addEvent( "PM:defer", target, new TimerEventPerformer() { public void perform( TimerEvent event ) { synchronized( PairingManagerImpl.this ){ deferred_update_event = null; } COConfigurationManager.setParameter( "pairing.updateoutstanding", false ); updateNeeded(); } }); } private Map sendRequest( String command, Map payload ) throws PairingException { try{ Map request = new HashMap(); CryptoManager cman = CryptoManagerFactory.getSingleton(); String azid = Base32.encode( cman.getSecureID()); payload.put( "_azid", azid ); try{ String pk = Base32.encode( cman.getECCHandler().getPublicKey( "pairing" )); payload.put( "_pk", pk ); }catch( Throwable e ){ } request.put( "req", payload ); String request_str = Base32.encode( BEncoder.encode( request )); String other_params = "&ver=" + UrlUtils.encode( Constants.AZUREUS_VERSION ) + "&app=" + UrlUtils.encode( SystemProperties.getApplicationName()) + "&locale=" + UrlUtils.encode( MessageText.getCurrentLocale().toString()); URL target = new URL( SERVICE_URL + "/client/" + command + "?request=" + request_str + other_params ); HttpURLConnection connection = (HttpURLConnection)target.openConnection(); InputStream is = connection.getInputStream(); Map response = (Map)BDecoder.decode( new BufferedInputStream( is )); synchronized( this ){ Long min_retry = (Long)response.get( "min_secs" ); if ( min_retry != null ){ min_update_period = min_retry.intValue()*1000; } Long max_retry = (Long)response.get( "max_secs" ); if ( max_retry != null ){ max_update_period = max_retry.intValue()*1000; } } final String message = getString( response, "message" ); if ( message != null ){ if ( last_message == null || !last_message.equals( message )){ last_message = message; try{ byte[] message_sig = (byte[])response.get( "message_sig" ); AEVerifier.verifyData( message, message_sig ); new AEThread2( "PairMsg", true ) { public void run() { UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 ); if ( ui_manager != null ){ ui_manager.showMessageBox( "pairing.server.warning.title", "!" + message + "!", UIManagerEvent.MT_OK ); } } }.start(); }catch( Throwable e ){ } } } String error = getString( response, "error" ); if ( error != null ){ throw( new PairingException( error )); } return((Map)response.get( "rep" )); }catch( Throwable e ){ throw( new PairingException( "invocation failed", e )); } } protected void fireChanged() { for ( PairingManagerListener l: listeners ){ try{ l.somethingChanged( this ); }catch( Throwable e ){ Debug.out( e ); } } } public void addListener( PairingManagerListener l ) { listeners.add( l ); } public void removeListener( PairingManagerListener l ) { listeners.remove( l ); } protected String getString( Map map, String name ) throws IOException { byte[] bytes = (byte[])map.get(name); if ( bytes == null ){ return( null ); } return( new String( bytes, "UTF-8" )); } protected class PairedServiceImpl implements PairedService, PairingConnectionData { private String sid; private Map attributes = new HashMap(); protected PairedServiceImpl( String _sid ) { sid = _sid; } public String getSID() { return( sid ); } public PairingConnectionData getConnectionData() { return( this ); } public void remove() { PairingManagerImpl.this.remove( this ); } public void setAttribute( String name, String value ) { synchronized( this ){ if ( DEBUG ){ System.out.println( "PS: " + sid + ": " + name + " -> " + value ); } attributes.put( name, value ); } } public String getAttribute( String name ) { return( attributes.get( name )); } public void sync() { PairingManagerImpl.this.sync( this ); } protected Map toMap() { Map result = new HashMap(); result.put( "sid", sid ); synchronized( this ){ result.putAll( attributes ); } return( result ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/pairing/PairingConnectionData.java0000644000175000017500000000236611262566444026214 0ustar adrianadrian/* * Created on Oct 5, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.pairing; public interface PairingConnectionData { public static final String ATTR_IP_V4 = "ip4"; public static final String ATTR_IP_V6 = "ip6"; public static final String ATTR_PORT = "port"; public static final String ATTR_PROTOCOL = "protocol"; public static final String ATTR_HOST = "host"; public void setAttribute( String name, String value ); public String getAttribute( String name ); public void sync(); } azureus-4.3.0.6/com/aelitis/azureus/core/pairing/PairingManagerFactory.java0000644000175000017500000000201711262566444026216 0ustar adrianadrian/* * Created on Oct 5, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.pairing; import com.aelitis.azureus.core.pairing.impl.PairingManagerImpl; public class PairingManagerFactory { public static PairingManager getSingleton() { return( PairingManagerImpl.getSingleton()); } } azureus-4.3.0.6/com/aelitis/azureus/core/pairing/PairedService.java0000644000175000017500000000172111262566444024530 0ustar adrianadrian/* * Created on Oct 5, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.pairing; public interface PairedService { public String getSID(); public PairingConnectionData getConnectionData(); public void remove(); } azureus-4.3.0.6/com/aelitis/azureus/core/pairing/PairingManager.java0000644000175000017500000000236411263773456024677 0ustar adrianadrian/* * Created on Oct 5, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.pairing; public interface PairingManager { public boolean isEnabled(); public String getAccessCode() throws PairingException; public String getReplacementAccessCode() throws PairingException; public PairedService addService( String sid ); public PairedService getService( String sid ); public void addListener( PairingManagerListener l ); public void removeListener( PairingManagerListener l ); } azureus-4.3.0.6/com/aelitis/azureus/core/pairing/PairingManagerListener.java0000644000175000017500000000164711263773456026410 0ustar adrianadrian/* * Created on Oct 9, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.pairing; public interface PairingManagerListener { public void somethingChanged( PairingManager pm ); } azureus-4.3.0.6/com/aelitis/azureus/core/pairing/PairingException.java0000644000175000017500000000201611262566444025251 0ustar adrianadrian/* * Created on Oct 5, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.pairing; public class PairingException extends Exception { public PairingException( String str ) { super( str ); } public PairingException( String str, Throwable e ) { super( str, e ); } } azureus-4.3.0.6/com/aelitis/azureus/core/AzureusCoreFactory.java0000644000175000017500000000511611171750562024146 0ustar adrianadrian/* * Created on 13-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core; /** * @author parg * */ import com.aelitis.azureus.core.impl.*; public class AzureusCoreFactory { /** * Azureus core is a singleton that must be initially created by someone, and initialised * @return * @throws AzureusCoreException */ public static AzureusCore create() throws AzureusCoreException { return( AzureusCoreImpl.create()); } /** * Returns whether the core is available. All features * of the core (such as GlobalManager) may not be available yet. * * @return */ public static boolean isCoreAvailable() { return( AzureusCoreImpl.isCoreAvailable()); } /** * Returns whether the core is running. All features of the * core (GlobalManager) should be available when the result * is true. * * @return */ public static boolean isCoreRunning() { return AzureusCoreImpl.isCoreRunning(); } /** * Once created the singleton can be accessed via this method * @return * @throws AzureusCoreException */ public static AzureusCore getSingleton() throws AzureusCoreException { return( AzureusCoreImpl.getSingleton()); } /** * Adds a listener that is triggered once the core is running. *

    * This is in AzureusCoreFactory instead of {@link AzureusCoreLifecycleListener} * so that listeners can be added before the core instance is * even created. * * @param l Listener to trigger when the core is running. If * the core is already running, listener is fired * immediately */ public static void addCoreRunningListener(AzureusCoreRunningListener l) { AzureusCoreImpl.addCoreRunningListener(l); } } azureus-4.3.0.6/com/aelitis/azureus/core/versioncheck/0000755000175000017500000000000011310377630022160 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPCodecs.java0000644000175000017500000000621111033103416030226 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.versioncheck; import java.io.DataInputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.util.HashMap; import java.util.Map; import com.aelitis.net.udp.uc.PRUDPPacketHandler; import com.aelitis.net.udp.uc.PRUDPPacketReply; import com.aelitis.net.udp.uc.PRUDPPacketReplyDecoder; import com.aelitis.net.udp.uc.PRUDPPacketRequest; import com.aelitis.net.udp.uc.PRUDPPacketRequestDecoder; public class VersionCheckClientUDPCodecs { public static final int ACT_VERSION_REQUEST = 32; public static final int ACT_VERSION_REPLY = 33; private static boolean registered = false; public static void registerCodecs() { if ( registered ){ return; } registered = true; PRUDPPacketReplyDecoder reply_decoder = new PRUDPPacketReplyDecoder() { public PRUDPPacketReply decode( PRUDPPacketHandler handler, InetSocketAddress originator, DataInputStream is, int action, int transaction_id ) throws IOException { switch( action ){ case ACT_VERSION_REPLY: { return( new VersionCheckClientUDPReply(is, transaction_id )); } default: { throw( new IOException( "Unrecognised action '" + action + "'" )); } } } }; Map reply_decoders = new HashMap(); reply_decoders.put( new Integer( ACT_VERSION_REPLY ), reply_decoder ); PRUDPPacketReply.registerDecoders( reply_decoders ); PRUDPPacketRequestDecoder request_decoder = new PRUDPPacketRequestDecoder() { public PRUDPPacketRequest decode( PRUDPPacketHandler handler, DataInputStream is, long connection_id, int action, int transaction_id ) throws IOException { switch( action ){ case ACT_VERSION_REQUEST: { return( new VersionCheckClientUDPRequest(is, connection_id, transaction_id )); } default: { throw( new IOException( "unsupported request type")); } } } }; Map request_decoders = new HashMap(); request_decoders.put( new Integer( ACT_VERSION_REQUEST ), request_decoder ); PRUDPPacketRequest.registerDecoders( request_decoders ); } } azureus-4.3.0.6/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPReply.java0000644000175000017500000000436010533443714030140 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.versioncheck; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Map; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.BEncoder; import com.aelitis.net.udp.uc.PRUDPPacketReply; public class VersionCheckClientUDPReply extends PRUDPPacketReply { private Map payload; public VersionCheckClientUDPReply( int trans_id ) { super( VersionCheckClientUDPCodecs.ACT_VERSION_REPLY, trans_id ); } protected VersionCheckClientUDPReply( DataInputStream is, int trans_id ) throws IOException { super( VersionCheckClientUDPCodecs.ACT_VERSION_REPLY, trans_id ); short len = is.readShort(); if ( len <= 0 ){ throw( new IOException( "invalid length" )); } byte[] bytes = new byte[len]; is.read( bytes ); payload = BDecoder.decode( bytes ); } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); byte[] bytes = BEncoder.encode( payload ); os.writeShort( (short)bytes.length ); os.write( bytes ); } public Map getPayload() { return( payload ); } public void setPayload( Map _payload ) { payload = _payload; } public String getString() { return( super.getString()); } } azureus-4.3.0.6/com/aelitis/azureus/core/versioncheck/VersionCheckClient.java0000644000175000017500000011440411307374162026554 0ustar adrianadrian/* * Created on Dec 20, 2004 * Created by Alon Rohter * Copyright (C) 2004-2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.versioncheck; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.net.*; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.download.impl.DownloadManagerStateImpl; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.stats.transfer.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.impl.AzureusCoreImpl; import com.aelitis.azureus.core.clientmessageservice.*; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminASN; import com.aelitis.azureus.core.security.CryptoManagerFactory; import com.aelitis.azureus.core.util.DNSUtils; import com.aelitis.net.udp.uc.PRUDPPacketHandler; import com.aelitis.net.udp.uc.PRUDPPacketHandlerFactory; import com.aelitis.net.udp.uc.PRUDPReleasablePacketHandler; /** * Client for checking version information from a remote server. */ public class VersionCheckClient { private static final LogIDs LOGID = LogIDs.CORE; public static final String REASON_UPDATE_CHECK_START = "us"; public static final String REASON_UPDATE_CHECK_PERIODIC = "up"; public static final String REASON_CHECK_SWT = "sw"; public static final String REASON_DHT_EXTENDED_ALLOWED = "dx"; public static final String REASON_DHT_ENABLE_ALLOWED = "de"; public static final String REASON_EXTERNAL_IP = "ip"; public static final String REASON_RECOMMENDED_PLUGINS = "rp"; public static final String REASON_SECONDARY_CHECK = "sc"; public static final String REASON_PLUGIN_UPDATE = "pu"; private static final String AZ_MSG_SERVER_ADDRESS_V4 = Constants.VERSION_SERVER_V4; private static final int AZ_MSG_SERVER_PORT = 27001; private static final String MESSAGE_TYPE_ID = "AZVER"; public static final String HTTP_SERVER_ADDRESS_V4 = AZ_MSG_SERVER_ADDRESS_V4; public static final int HTTP_SERVER_PORT = 80; public static final String TCP_SERVER_ADDRESS_V4 = AZ_MSG_SERVER_ADDRESS_V4; public static final int TCP_SERVER_PORT = 80; public static final String UDP_SERVER_ADDRESS_V4 = AZ_MSG_SERVER_ADDRESS_V4; public static final int UDP_SERVER_PORT = 2080; public static final String AZ_MSG_SERVER_ADDRESS_V6 = Constants.VERSION_SERVER_V6; public static final String HTTP_SERVER_ADDRESS_V6 = AZ_MSG_SERVER_ADDRESS_V6; public static final String TCP_SERVER_ADDRESS_V6 = AZ_MSG_SERVER_ADDRESS_V6; public static final String UDP_SERVER_ADDRESS_V6 = AZ_MSG_SERVER_ADDRESS_V6; private static final long CACHE_PERIOD = 5*60*1000; private static boolean secondary_check_done; static{ VersionCheckClientUDPCodecs.registerCodecs(); } private static final int AT_V4 = 1; private static final int AT_V6 = 2; private static final int AT_EITHER = 3; private static VersionCheckClient instance; /** * Get the singleton instance of the version check client. * @return version check client */ public static synchronized VersionCheckClient getSingleton() { if ( instance == null ){ instance = new VersionCheckClient(); } return( instance ); } private boolean enable_v6; private boolean prefer_v6; private Map last_check_data_v4 = null; private Map last_check_data_v6 = null; private final AEMonitor check_mon = new AEMonitor( "versioncheckclient" ); private long last_check_time_v4 = 0; private long last_check_time_v6 = 0; private long last_feature_flag_cache; private long last_feature_flag_cache_time; private VersionCheckClient() { COConfigurationManager.addAndFireParameterListeners( new String[]{ "IPV6 Prefer Addresses", "IPV6 Enable Support" }, new ParameterListener() { public void parameterChanged( String name ) { enable_v6 = COConfigurationManager.getBooleanParameter( "IPV6 Enable Support" ); prefer_v6 = COConfigurationManager.getBooleanParameter( "IPV6 Prefer Addresses" ); } }); } public void initialise() { DelayedTask delayed_task = UtilitiesImpl.addDelayedTask( "VersionCheck", new Runnable() { public void run() { final AESemaphore sem = new AESemaphore( "VCC:init" ); new AEThread2( "VCC:init", true ) { public void run() { try{ getVersionCheckInfo( REASON_UPDATE_CHECK_START ); }finally{ sem.release(); } } }.start(); if ( !sem.reserve( 5000 )){ Debug.out( "Timeout waiting for version check to complete" ); } } }); delayed_task.queue(); } /** * Get the version check reply info. * @return reply data, possibly cached, if the server was already checked within the last minute */ public Map getVersionCheckInfo( String reason ) { return( getVersionCheckInfo( reason, AT_EITHER )); } public Map getVersionCheckInfo( String reason, int address_type ) { if ( address_type == AT_V4 ){ return( getVersionCheckInfoSupport( reason, false, false, false )); }else if ( address_type == AT_V6 ){ return( getVersionCheckInfoSupport( reason, false, false, true )); }else{ Map reply = getVersionCheckInfoSupport( reason, false, false, prefer_v6 ); if ( reply == null || reply.size() == 0 ){ reply = getVersionCheckInfoSupport( reason, false, false, !prefer_v6 ); } return( reply ); } } protected Map getVersionCheckInfoSupport( String reason, boolean only_if_cached, boolean force, boolean v6 ) { if ( v6 ){ if ( enable_v6 ){ try { check_mon.enter(); long time_diff = SystemTime.getCurrentTime() - last_check_time_v6; force = force || time_diff > CACHE_PERIOD || time_diff < 0; if( last_check_data_v6 == null || last_check_data_v6.size() == 0 || force ) { // if we've never checked before then we go ahead even if the "only_if_cached" // flag is set as its had not chance of being cached yet! if ( only_if_cached && last_check_data_v6 != null ){ return( new HashMap() ); } try { last_check_data_v6 = performVersionCheck( constructVersionCheckMessage( reason ), true, true, true ); if ( last_check_data_v6 != null && last_check_data_v6.size() > 0 ){ COConfigurationManager.setParameter( "versioncheck.cache.v6", last_check_data_v6 ); } } catch(SocketException t) { // internet is broken // Debug.out(t.getClass().getName() + ": " + t.getMessage()); } catch(UnknownHostException t) { // dns is broken // Debug.out(t.getClass().getName() + ": " + t.getMessage()); } catch( Throwable t ) { Debug.out(t); last_check_data_v6 = new HashMap(); } } else { Logger.log(new LogEvent(LOGID, "VersionCheckClient is using " + "cached version check info. Using " + last_check_data_v6.size() + " reply keys.")); } } finally { check_mon.exit(); } } if( last_check_data_v6 == null ) last_check_data_v6 = new HashMap(); return last_check_data_v6; }else{ try { check_mon.enter(); long time_diff = SystemTime.getCurrentTime() - last_check_time_v4; force = force || time_diff > CACHE_PERIOD || time_diff < 0; if( last_check_data_v4 == null || last_check_data_v4.size() == 0 || force ) { // if we've never checked before then we go ahead even if the "only_if_cached" // flag is set as its had not chance of being cached yet! if ( only_if_cached && last_check_data_v4 != null ){ return( new HashMap() ); } try { last_check_data_v4 = performVersionCheck( constructVersionCheckMessage( reason ), true, true, false ); if ( last_check_data_v4 != null && last_check_data_v4.size() > 0 ){ COConfigurationManager.setParameter( "versioncheck.cache.v4", last_check_data_v4 ); } // clear down any plugin-specific data that has successfully been sent to the version server try{ if ( AzureusCoreFactory.isCoreAvailable()){ //installed plugin IDs PluginInterface[] plugins = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaces(); for (int i=0;i 0; boolean v4_ok = last_check_data_v4 != null && last_check_data_v4.size() > 0; if ( address_type == AT_V4 ){ return( v4_ok ); }else if ( address_type == AT_V6 ){ return( v6_ok ); }else{ return( v4_ok | v6_ok ); } } public Map getMostRecentVersionCheckData() { // currently we maintain v4 much more accurately than v6 if ( last_check_data_v4 != null ){ return( last_check_data_v4 ); } Map res = COConfigurationManager.getMapParameter( "versioncheck.cache.v4", null ); if ( res != null ){ return( res ); } if ( last_check_data_v6 != null ){ return( last_check_data_v6 ); } res = COConfigurationManager.getMapParameter( "versioncheck.cache.v6", null ); return( res ); } public long getFeatureFlags() { long now = SystemTime.getCurrentTime(); if ( now > last_feature_flag_cache_time && now - last_feature_flag_cache_time < 60000 ){ return( last_feature_flag_cache ); } Map m = getMostRecentVersionCheckData(); long result; if ( m == null ){ result = 0; }else{ byte[] b_feat_flags = (byte[])m.get( "feat_flags" ); if ( b_feat_flags != null ){ try{ result = Long.parseLong(new String((byte[])b_feat_flags)); }catch( Throwable e ){ result = 0; } }else{ result = 0; } } last_feature_flag_cache = result; last_feature_flag_cache_time = now; return( result ); } public long getCacheTime( boolean v6 ) { return( v6?last_check_time_v6:last_check_time_v4); } /** * Get the ip address seen by the version check server. * NOTE: This information may be cached, see getVersionCheckInfo(). * @return external ip address, or empty string if no address information found */ public String getExternalIpAddress( boolean only_if_cached, boolean v6 ) { Map reply = getVersionCheckInfoSupport( REASON_EXTERNAL_IP, only_if_cached, false, v6 ); byte[] address = (byte[])reply.get( "source_ip_address" ); if( address != null ) { return new String( address ); } return( null ); } /** * Is the DHT plugin allowed to be enabled. * @return true if DHT can be enabled, false if it should not be enabled */ public boolean DHTEnableAllowed() { Map reply = getVersionCheckInfo( REASON_DHT_ENABLE_ALLOWED, AT_EITHER ); boolean res = false; byte[] value = (byte[])reply.get( "enable_dht" ); if( value != null ) { res = new String( value ).equalsIgnoreCase( "true" ); } // we take the view that if the version check failed then we go ahead // and enable the DHT (i.e. we're being optimistic) if ( !res ){ res = !isVersionCheckDataValid( AT_EITHER ); } return res; } /** * Is the DHT allowed to be used by external plugins. * @return true if extended DHT use is allowed, false if not allowed */ public boolean DHTExtendedUseAllowed() { Map reply = getVersionCheckInfo( REASON_DHT_EXTENDED_ALLOWED, AT_EITHER ); boolean res = false; byte[] value = (byte[])reply.get( "enable_dht_extended_use" ); if( value != null ) { res = new String( value ).equalsIgnoreCase( "true" ); } // be generous and enable extended use if check failed if ( !res ){ res = !isVersionCheckDataValid( AT_EITHER ); } return res; } public String[] getRecommendedPlugins() { Map reply = getVersionCheckInfo( REASON_RECOMMENDED_PLUGINS, AT_EITHER ); List l = (List)reply.get( "recommended_plugins" ); if ( l == null ){ return( new String[0] ); } String[] res = new String[l.size()]; for (int i=0;i 10000 ){ throw( new IOException( "content length too large" )); } break; } if ( header.length() > 2048 ){ throw( new IOException( "header too large" )); } } ByteArrayOutputStream baos = new ByteArrayOutputStream( content_length ); buffer = new byte[content_length]; while( content_length > 0 ){ int len = is.read( buffer ); if ( len <= 0 ){ break; } baos.write( buffer, 0, len ); content_length -= len; } if ( content_length != 0 ){ throw( new IOException( "error reading reply" )); } byte[] reply_bytes = baos.toByteArray(); Map reply = BDecoder.decode( new BufferedInputStream( new ByteArrayInputStream( reply_bytes ))); preProcessReply( reply, v6 ); return( reply ); }finally{ if ( socket != null ){ try{ socket.close(); }catch( Throwable e ){ } } } } private Map executeUDP( Map data_to_send, InetAddress bind_ip, int bind_port, boolean v6 ) throws Exception { if ( v6 && !enable_v6 ){ throw( new Exception( "IPv6 is disabled" )); } String host = getHost( v6, UDP_SERVER_ADDRESS_V6, UDP_SERVER_ADDRESS_V4 ); PRUDPReleasablePacketHandler handler = PRUDPPacketHandlerFactory.getReleasableHandler( bind_port ); PRUDPPacketHandler packet_handler = handler.getHandler(); long timeout = 5; Random random = new Random(); try{ Exception last_error = null; packet_handler.setExplicitBindAddress( bind_ip ); for (int i=0;i<3;i++){ try{ // connection ids for requests must always have their msb set... // apart from the original darn udp tracker spec.... long connection_id = 0x8000000000000000L | random.nextLong(); VersionCheckClientUDPRequest request_packet = new VersionCheckClientUDPRequest( connection_id ); request_packet.setPayload( data_to_send ); VersionCheckClientUDPReply reply_packet = (VersionCheckClientUDPReply)packet_handler.sendAndReceive( null, request_packet, new InetSocketAddress( host, UDP_SERVER_PORT ), timeout ); Map reply = reply_packet.getPayload(); preProcessReply( reply, v6 ); return( reply ); }catch( Exception e){ last_error = e; timeout = timeout * 2; } } if ( last_error != null ){ throw( last_error ); } throw( new Exception( "Timeout" )); }finally{ packet_handler.setExplicitBindAddress( null ); handler.release(); } } protected void preProcessReply( Map reply, final boolean v6 ) { NetworkAdmin admin = NetworkAdmin.getSingleton(); try{ byte[] address = (byte[])reply.get( "source_ip_address" ); InetAddress my_ip = InetAddress.getByName( new String( address )); NetworkAdminASN old_asn = admin.getCurrentASN(); NetworkAdminASN new_asn = admin.lookupCurrentASN( my_ip ); if ( !new_asn.sameAs( old_asn )){ // kick off a secondary version check to communicate the new information if ( !secondary_check_done ){ secondary_check_done = true; new AEThread( "Secondary version check", true ) { public void runSupport() { getVersionCheckInfoSupport( REASON_SECONDARY_CHECK, false, true, v6 ); } }.start(); } } }catch( Throwable e ){ Debug.printStackTrace(e); } Long as_advice = (Long)reply.get( "as_advice" ); if ( as_advice != null ){ NetworkAdminASN current_asn = admin.getCurrentASN(); String asn = current_asn.getASName(); if ( asn != null ){ long advice = as_advice.longValue(); if ( advice != 0 ){ // require crypto String done_asn = COConfigurationManager.getStringParameter( "ASN Advice Followed", "" ); if ( !done_asn.equals( asn )){ COConfigurationManager.setParameter( "ASN Advice Followed", asn ); boolean change = advice == 1 || advice == 2; boolean alert = advice == 1 || advice == 3; if ( !COConfigurationManager.getBooleanParameter( "network.transport.encrypted.require" )){ if ( change ){ COConfigurationManager.setParameter( "network.transport.encrypted.require", true ); } if ( alert ){ String msg = MessageText.getString( "crypto.alert.as.warning", new String[]{ asn }); Logger.log( new LogAlert( false, LogAlert.AT_WARNING, msg )); } } } } } } // set ui.toolbar.uiswitcher based on instructions from tracker // Really shouldn't be in VersionCheck client, but instead have some // listener and have the code elsewhere. Simply calling //getVersionCheckInfo from "code elsewhere" (to get the cached result) //caused a deadlock at startup. Long lEnabledUISwitcher = (Long) reply.get("ui.toolbar.uiswitcher"); if (lEnabledUISwitcher != null) { COConfigurationManager.setBooleanDefault("ui.toolbar.uiswitcher", lEnabledUISwitcher.longValue() == 1); } } public InetAddress getExternalIpAddressHTTP( boolean v6 ) throws Exception { Map reply = executeHTTP( new HashMap(), v6 ); byte[] address = (byte[])reply.get( "source_ip_address" ); return( InetAddress.getByName( new String( address ))); } public InetAddress getExternalIpAddressTCP( InetAddress bind_ip, int bind_port, boolean v6 ) throws Exception { Map reply = executeTCP( new HashMap(), bind_ip, bind_port, v6 ); byte[] address = (byte[])reply.get( "source_ip_address" ); return( InetAddress.getByName( new String( address ))); } public InetAddress getExternalIpAddressUDP( InetAddress bind_ip, int bind_port, boolean v6 ) throws Exception { Map reply = executeUDP( new HashMap(), bind_ip, bind_port, v6 ); byte[] address = (byte[])reply.get( "source_ip_address" ); return( InetAddress.getByName( new String( address ))); } protected String getHost( boolean v6, String v6_address, String v4_address ) { if ( v6 ){ try{ return( InetAddress.getByName( v6_address ).getHostAddress()); }catch( UnknownHostException e ){ try{ return( DNSUtils.getIPV6ByName(v6_address ).getHostAddress()); }catch( UnknownHostException f ){ return( v6_address ); } } }else{ return( v4_address ); } } /** * Construct the default version check message. * @return message to send */ private static Map constructVersionCheckMessage( String reason ) { //only send if anonymous-check flag is not set boolean send_info = COConfigurationManager.getBooleanParameter( "Send Version Info" ); Map message = new HashMap(); //always send message.put( "appid", SystemProperties.getApplicationIdentifier()); message.put( "version", Constants.AZUREUS_VERSION ); message.put( "ui", COConfigurationManager.getStringParameter( "ui", "unknown" ) ); message.put( "os", Constants.OSName ); message.put( "os_version", System.getProperty( "os.version" ) ); message.put( "os_arch", System.getProperty( "os.arch" ) ); //see http://lopica.sourceforge.net/os.html boolean using_phe = COConfigurationManager.getBooleanParameter( "network.transport.encrypted.require" ); message.put( "using_phe", using_phe ? new Long(1) : new Long(0) ); //swt stuff try { Class c = Class.forName( "org.eclipse.swt.SWT" ); String swt_platform = (String)c.getMethod( "getPlatform", new Class[]{} ).invoke( null, new Object[]{} ); message.put( "swt_platform", swt_platform ); Integer swt_version = (Integer)c.getMethod( "getVersion", new Class[]{} ).invoke( null, new Object[]{} ); message.put( "swt_version", new Long( swt_version.longValue() ) ); if ( send_info ){ c = Class.forName("org.gudy.azureus2.ui.swt.mainwindow.MainWindow"); if (c != null) { c.getMethod("addToVersionCheckMessage", new Class[] { Map.class }).invoke( null, new Object[] { message }); } } } catch( ClassNotFoundException e ) { /* ignore */ } catch( NoClassDefFoundError er ) { /* ignore */ } catch( InvocationTargetException err ) { /* ignore */ } catch( Throwable t ) { t.printStackTrace(); } int last_send_time = COConfigurationManager.getIntParameter( "Send Version Info Last Time", -1 ); int current_send_time = (int)(SystemTime.getCurrentTime()/1000); COConfigurationManager.setParameter( "Send Version Info Last Time", current_send_time ); String id = COConfigurationManager.getStringParameter( "ID", null ); if( id != null && send_info ) { message.put( "id", id ); try{ byte[] id2 = CryptoManagerFactory.getSingleton().getSecureID(); message.put( "id2", id2 ); }catch( Throwable e ){ } if ( last_send_time != -1 && last_send_time < current_send_time ){ // time since last message.put( "tsl", new Long(current_send_time-last_send_time)); } message.put( "reason", reason ); String java_version = System.getProperty( "java.version" ); if ( java_version == null ){ java_version = "unknown"; } message.put( "java", java_version ); String java_vendor = System.getProperty( "java.vm.vendor" ); if ( java_vendor == null ){ java_vendor = "unknown"; } message.put( "javavendor", java_vendor ); long max_mem = Runtime.getRuntime().maxMemory()/(1024*1024); message.put( "javamx", new Long( max_mem ) ); String java_rt_name = System.getProperty("java.runtime.name"); if (java_rt_name != null) { message.put( "java_rt_name", java_rt_name); } String java_rt_version = System.getProperty("java.runtime.version"); if (java_rt_version != null) { message.put( "java_rt_version", java_rt_version); } OverallStats stats = StatsFactory.getStats(); if ( stats != null ){ //long total_bytes_downloaded = stats.getDownloadedBytes(); //long total_bytes_uploaded = stats.getUploadedBytes(); long total_uptime = stats.getTotalUpTime(); //removed due to complaints about anonymous stats collection //message.put( "total_bytes_downloaded", new Long( total_bytes_downloaded ) ); //message.put( "total_bytes_uploaded", new Long( total_bytes_uploaded ) ); message.put( "total_uptime", new Long( total_uptime ) ); //message.put( "dlstats", stats.getDownloadStats()); } try{ NetworkAdminASN current_asn = NetworkAdmin.getSingleton().getCurrentASN(); String as = current_asn.getAS(); message.put( "ip_as", current_asn.getAS()); String asn = current_asn.getASName(); if ( asn.length() > 64 ){ asn = asn.substring( 0, 64 ); } message.put( "ip_asn", asn ); }catch( Throwable e ){ Debug.out( e ); } // send locale, so we can determine which languages need attention message.put("locale", Locale.getDefault().toString()); String originalLocale = System.getProperty("user.language") + "_" + System.getProperty("user.country"); String variant = System.getProperty("user.variant"); if (variant != null && variant.length() > 0) { originalLocale += "_" + variant; } message.put("orig_locale", originalLocale); try{ if ( AzureusCoreFactory.isCoreAvailable()){ //installed plugin IDs PluginInterface[] plugins = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaces(); List pids = new ArrayList(); List vs_data = new ArrayList(); for (int i=0;i 0 ) || ( !pid.startsWith( "<" ) && !pid.startsWith( "azbp" ) && !pid.startsWith( "azupdater" ) && !pid.startsWith( "azplatform" ) && !pids.contains( pid ))){ if ( info != null && info.length() > 0 ){ if( info.length() < 256 ){ pid += ":" + info; }else{ Debug.out( "Plugin '" + pid + "' reported excessive info string '" + info + "'" ); } } pids.add( pid ); } Map data = plugin.getPluginconfig().getPluginMapParameter( "plugin.versionserver.data", null ); if ( data != null ){ Map payload = new HashMap(); byte[] data_bytes = BEncoder.encode( data ); if ( data_bytes.length > 16*1024 ){ Debug.out( "Plugin '" + pid + "' reported excessive version server data (length=" + data_bytes.length + ")" ); payload.put( "error", "data too long: " + data_bytes.length ); }else{ payload.put( "data", data_bytes ); } payload.put( "id", pid); payload.put( "version", plugin.getPluginVersion()); vs_data.add( payload ); } } message.put( "plugins", pids ); if ( vs_data.size() > 0 ){ message.put( "plugin_data", vs_data ); } } }catch( Throwable e ){ Debug.out( e ); } } return message; } public static void main( String[] args ) { try{ COConfigurationManager.initialise(); boolean v6= true; // Test connectivity. if (true) { // System.out.println( "UDP: " + getSingleton().getExternalIpAddressUDP(null,0,v6)); // System.out.println( "TCP: " + getSingleton().getExternalIpAddressTCP(null,0,v6)); System.out.println( "HTTP: " + getSingleton().getExternalIpAddressHTTP(v6)); } Map data = constructVersionCheckMessage(VersionCheckClient.REASON_UPDATE_CHECK_START); System.out.println("Sending (pre-initialisation):"); printDataMap(data); System.out.println("-----------"); System.out.println("Receiving (pre-initialisation):"); printDataMap(getSingleton().getVersionCheckInfo(VersionCheckClient.REASON_UPDATE_CHECK_START)); System.out.println("-----------"); System.out.println(); System.out.print("Initialising core... "); /** * Suppress all of these errors being displayed in the output. * * These things should be temporary... */ AzureusCoreImpl.SUPPRESS_CLASSLOADER_ERRORS = true; DownloadManagerStateImpl.SUPPRESS_FIXUP_ERRORS = true; AzureusCore core = AzureusCoreFactory.create(); core.start(); System.out.println("done."); System.out.println(); System.out.println("-----------"); data = constructVersionCheckMessage(VersionCheckClient.REASON_UPDATE_CHECK_START); System.out.println("Sending (post-initialisation):"); printDataMap(data); System.out.println("-----------"); System.out.println("Receiving (post-initialisation):"); printDataMap(getSingleton().getVersionCheckInfo(VersionCheckClient.REASON_UPDATE_CHECK_START)); System.out.println("-----------"); System.out.println(); System.out.print("Shutting down core... "); core.stop(); System.out.println("done."); }catch( Throwable e){ e.printStackTrace(); } } // Used for debugging in main. private static void printDataMap(Map map) throws Exception { TreeMap res = new TreeMap(map); Iterator key_itr = map.keySet().iterator(); while (key_itr.hasNext()) { Object key = key_itr.next(); Object val = map.get(key); if (val instanceof byte[]) { String as_bytes = ByteFormatter.nicePrint((byte[])val); String as_text = new String((byte[])val, Constants.BYTE_ENCODING); res.put(key, as_text + " [" + as_bytes + "]"); } } Iterator entries = res.entrySet().iterator(); Map.Entry entry; while (entries.hasNext()) { entry = (Map.Entry)entries.next(); System.out.print(" "); System.out.print(entry.getKey()); System.out.print(": "); System.out.print(entry.getValue()); System.out.println(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPRequest.java0000644000175000017500000000445710533443714030504 0ustar adrianadrian/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.versioncheck; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Map; import org.gudy.azureus2.core3.util.BDecoder; import org.gudy.azureus2.core3.util.BEncoder; import com.aelitis.net.udp.uc.PRUDPPacketRequest; public class VersionCheckClientUDPRequest extends PRUDPPacketRequest { private Map payload; public VersionCheckClientUDPRequest( long connection_id ) { super( VersionCheckClientUDPCodecs.ACT_VERSION_REQUEST, connection_id ); } protected VersionCheckClientUDPRequest( DataInputStream is, long connection_id , int trans_id ) throws IOException { super( VersionCheckClientUDPCodecs.ACT_VERSION_REQUEST, connection_id, trans_id ); short len = is.readShort(); if ( len <= 0 ){ throw( new IOException( "invalid length" )); } byte[] bytes = new byte[len]; is.read( bytes ); payload = BDecoder.decode( bytes ); } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); byte[] bytes = BEncoder.encode( payload ); os.writeShort( (short)bytes.length ); os.write( bytes ); } public Map getPayload() { return( payload ); } public void setPayload( Map _payload ) { payload = _payload; } public String getString() { return( super.getString()); } } azureus-4.3.0.6/com/aelitis/azureus/core/AzureusCoreRunningListener.java0000644000175000017500000000040211171750562025656 0ustar adrianadrian/** * */ package com.aelitis.azureus.core; /** * See {@link AzureusCoreFactory#addCoreRunningListener(AzureusCoreRunningListener)} * @author vuze * */ public interface AzureusCoreRunningListener { public void azureusCoreRunning(AzureusCore core); } azureus-4.3.0.6/com/aelitis/azureus/core/AzureusCoreComponent.java0000644000175000017500000000205310373051036024467 0ustar adrianadrian/* * Created on 14-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core; /** * @author parg * */ public interface AzureusCoreComponent { } azureus-4.3.0.6/com/aelitis/azureus/core/crypto/0000755000175000017500000000000011310377620021014 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/crypto/VuzeCryptoException.java0000644000175000017500000000172311002222732025662 0ustar adrianadrian/* * Created on Apr 18, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.crypto; public class VuzeCryptoException extends Exception { public VuzeCryptoException( String str, Throwable e ) { super( str, e ); } } azureus-4.3.0.6/com/aelitis/azureus/core/crypto/VuzeCryptoManager.java0000644000175000017500000001472511272146162025317 0ustar adrianadrian/* * Created on Apr 18, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.crypto; import com.aelitis.azureus.core.security.*; public class VuzeCryptoManager { private static VuzeCryptoManager singleton; public static synchronized VuzeCryptoManager getSingleton() { if ( singleton == null ){ singleton = new VuzeCryptoManager(); } return( singleton ); } //private boolean init_tried; private CryptoManager crypt_man; //private CopyOnWriteList listeners = new CopyOnWriteList(); //private volatile CryptoManagerPasswordHandler.passwordDetails session_pw; protected VuzeCryptoManager() { crypt_man = CryptoManagerFactory.getSingleton(); /* crypt_man.addPasswordHandler( new CryptoManagerPasswordHandler() { private boolean error_logged = !Constants.isCVSVersion(); public int getHandlerType() { return( HANDLER_TYPE_SYSTEM ); } public void passwordOK( int handler_type, passwordDetails details) { Iterator it = listeners.iterator(); while( it.hasNext()){ ((VuzeCryptoListener)it.next()).sessionPasswordCorrect(); } } public passwordDetails getPassword( int handler_type, int action_type, boolean last_pw_incorrect, String reason ) { if ( last_pw_incorrect ){ Iterator it = listeners.iterator(); while( it.hasNext()){ ((VuzeCryptoListener)it.next()).sessionPasswordIncorrect(); } return( null ); } if ( session_pw != null ){ return( session_pw ); } Iterator it = listeners.iterator(); while( it.hasNext()){ try{ final char[] pw = ((VuzeCryptoListener)it.next()).getSessionPassword( reason ); session_pw = new passwordDetails() { public char[] getPassword() { return( pw ); } public int getPersistForSeconds() { return( -1 ); // session } }; error_logged = false; return( session_pw ); }catch (VuzeCryptoException ve) { if ( !error_logged ){ error_logged = true; Debug.out( "Listener failed " + ve.toString() + " on " + reason ); if (ve.getCause() != null) { Debug.out(ve.getCause()); } } }catch( Throwable e ){ Debug.out( "Listener failed", e ); } } if ( !error_logged ){ error_logged = true; Debug.out( "VuzeCryptoManager: no listeners returned session key" ); } return( null ); } }); // auto enable buddy plugin and system handler boolean init_done = COConfigurationManager.getBooleanParameter( "vuze.crypto.manager.initial.login.done", false ); if ( !init_done ){ AzureusCoreFactory.addCoreRunningListener( new AzureusCoreRunningListener() { public void azureusCoreRunning( AzureusCore core) { { initialise( core ); } } }); } */ } /* protected void initialise( AzureusCore core ) { synchronized( this ){ if ( init_tried ){ return; } init_tried = true; } PluginInterface pi = core.getPluginManager().getPluginInterfaceByID( "azbuddy" ); if ( pi != null ){ Plugin plugin = pi.getPlugin(); if ( plugin instanceof BuddyPlugin ){ BuddyPlugin buddy_plugin = (BuddyPlugin)plugin; if ( !buddy_plugin.isEnabled()){ CryptoHandler handler = crypt_man.getECCHandler(); // try and switch password handler if no keys yet defined if ( handler.peekPublicKey() == null ){ try{ handler.setDefaultPasswordHandlerType( CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM ); }catch( Throwable e ){ Debug.out( "CRYPTO: Failed to set default password handler type: " + Debug.getNestedExceptionMessage( e )); } } buddy_plugin.setEnabled( true ); COConfigurationManager.setParameter( "vuze.crypto.manager.initial.login.done", true ); COConfigurationManager.save(); Debug.out( "CRYPTO: initialised buddy plugin and default handler type" ); } } } } */ public byte[] getPlatformAZID() { return( crypt_man.getSecureID()); } /* public String getPublicKey( String reason ) throws VuzeCryptoException { try{ return( Base32.encode(crypt_man.getECCHandler().getPublicKey(reason))); }catch( Throwable e ){ throw( new VuzeCryptoException( "Failed to access public key", e )); } } public boolean hasPublicKey() { return crypt_man.getECCHandler().peekPublicKey() != null; } public void clearPassword() { session_pw = null; crypt_man.clearPasswords( CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM ); } public void setPassword( String pw ) { final char[] pw_chars = pw.toCharArray(); session_pw = new CryptoManagerPasswordHandler.passwordDetails() { public char[] getPassword() { return( pw_chars ); } public int getPersistForSeconds() { return( -1 ); // session } }; new AEThread2( "VuzeCryptoManager:testUnlock", true ) { public void run() { try{ crypt_man.getECCHandler().unlock(); }catch( Throwable e ){ Debug.out( "Password incorrect", e ); } } }.start(); } public void addListener( VuzeCryptoListener listener ) { listeners.add( listener ); } public void removeListener( VuzeCryptoListener listener ) { listeners.remove( listener ); } */ } azureus-4.3.0.6/com/aelitis/azureus/core/crypto/VuzeCryptoListener.java0000644000175000017500000000233711022702752025522 0ustar adrianadrian/* * Created on Apr 18, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.crypto; public interface VuzeCryptoListener { public char[] getSessionPassword( String reason ) throws VuzeCryptoException; public void sessionPasswordCorrect(); /** * Indicates that the session password returned is incorrect. This is a bad state of * affairs and the (probable) only solution is to generate a new public/private key * pair */ public void sessionPasswordIncorrect(); } azureus-4.3.0.6/com/aelitis/azureus/core/subs/0000755000175000017500000000000011310377630020451 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/subs/SubscriptionPopularityListener.java0000644000175000017500000000174711044046212027601 0ustar adrianadrian/* * Created on Jul 29, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs; public interface SubscriptionPopularityListener { public void gotPopularity( long popularity ); public void failed( SubscriptionException error ); } azureus-4.3.0.6/com/aelitis/azureus/core/subs/SubscriptionScheduler.java0000644000175000017500000000245011071007322025630 0ustar adrianadrian/* * Created on Aug 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs; public interface SubscriptionScheduler { public void download( Subscription subs, boolean is_auto ) throws SubscriptionException; public void downloadAsync( Subscription subs, boolean is_auto ) throws SubscriptionException; public void download( Subscription subs, boolean is_auto, SubscriptionDownloadListener listener ) throws SubscriptionException; public void download( Subscription subs, SubscriptionResult result ); } azureus-4.3.0.6/com/aelitis/azureus/core/subs/SubscriptionResult.java0000644000175000017500000000254511263261720025204 0ustar adrianadrian/* * Created on Aug 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs; import java.util.Map; import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; public interface SubscriptionResult extends UtilitiesImpl.PluginSubscriptionResult { public String getID(); public Map toJSONMap(); /** * See SearchResult properties for list * @return */ public Map toPropertyMap(); public String getDownloadLink(); public String getPlayLink(); public void setRead( boolean read ); public boolean getRead(); public void delete(); public boolean isDeleted(); } azureus-4.3.0.6/com/aelitis/azureus/core/subs/Subscription.java0000644000175000017500000000634111263261720024003 0ustar adrianadrian/* * Created on Jul 11, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs; import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; import com.aelitis.azureus.core.metasearch.Engine; import com.aelitis.azureus.core.vuzefile.VuzeFile; public interface Subscription extends UtilitiesImpl.PluginSubscription { public static final int AZ_VERSION = 1; public String getName(); public void setName( String str ) throws SubscriptionException; public String getNameEx(); public String getID(); public byte[] getPublicKey(); public int getVersion(); public int getHighestVersion(); public void resetHighestVersion(); public int getAZVersion(); public boolean isMine(); public boolean isPublic(); public void setPublic( boolean is_public ) throws SubscriptionException; public boolean isUpdateable(); public boolean isShareable(); public String getJSON() throws SubscriptionException; public boolean setJSON( String json ) throws SubscriptionException; public boolean isSubscribed(); public void setSubscribed( boolean subscribed ); public void getPopularity( SubscriptionPopularityListener listener ) throws SubscriptionException; public boolean setDetails( String name, boolean is_public, String json ) throws SubscriptionException; public String getReferer(); public long getCachedPopularity(); public void addAssociation( byte[] hash ); public void addPotentialAssociation( String result_id, String key ); public int getAssociationCount(); public boolean hasAssociation( byte[] hash ); public String getCategory(); public void setCategory( String category ); public Engine getEngine() throws SubscriptionException; public boolean isAutoDownloadSupported(); public VuzeFile getVuzeFile() throws SubscriptionException; public void setCreatorRef( String str ); public String getCreatorRef(); public void reset(); public void remove(); public SubscriptionManager getManager(); public SubscriptionHistory getHistory(); /** * shortcut to help plugin interface * @param l */ public SubscriptionResult[] getResults( boolean include_deleted ); public void addListener( SubscriptionListener l ); public void removeListener( SubscriptionListener l ); public void setUserData( Object key, Object data ); public Object getUserData( Object key ); public String getString(); } azureus-4.3.0.6/com/aelitis/azureus/core/subs/SubscriptionAssociationLookup.java0000644000175000017500000000161411043527546027377 0ustar adrianadrian/* * Created on Jul 28, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs; public interface SubscriptionAssociationLookup { public void cancel(); } azureus-4.3.0.6/com/aelitis/azureus/core/subs/SubscriptionListener.java0000644000175000017500000000177111050535016025507 0ustar adrianadrian/* * Created on Aug 5, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs; public interface SubscriptionListener { public void subscriptionChanged( Subscription subs ); public void subscriptionDownloaded( Subscription subs, boolean auto ); } azureus-4.3.0.6/com/aelitis/azureus/core/subs/SubscriptionLookupListener.java0000644000175000017500000000213011042454206026671 0ustar adrianadrian/* * Created on Jul 11, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs; public interface SubscriptionLookupListener { public void found( byte[] hash, Subscription subscription ); public void complete( byte[] hash, Subscription[] subscriptions ); public void failed( byte[] hash, SubscriptionException error ); } azureus-4.3.0.6/com/aelitis/azureus/core/subs/SubscriptionManagerFactory.java0000644000175000017500000000242411062176036026626 0ustar adrianadrian/* * Created on Jul 11, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs; import com.aelitis.azureus.core.subs.impl.SubscriptionManagerImpl; public class SubscriptionManagerFactory { public static void preInitialise() { SubscriptionManagerImpl.preInitialise(); } public static SubscriptionManager getSingleton() { return( SubscriptionManagerImpl.getSingleton( false )); } public static SubscriptionManager getStandaloneSingleton( boolean stand_alone ) { return( SubscriptionManagerImpl.getSingleton( true )); } } azureus-4.3.0.6/com/aelitis/azureus/core/subs/impl/0000755000175000017500000000000011310377630021412 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/subs/impl/SubscriptionRSSFeed.java0000644000175000017500000002062611264725204026125 0ustar adrianadrian/* * Created on Jul 13, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs.impl; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetSocketAddress; import java.net.URL; import java.util.Date; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.TimeFormatter; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.core3.xml.util.XUXmlWriter; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse; import org.gudy.azureus2.plugins.utils.search.SearchResult; import org.gudy.azureus2.plugins.utils.subscriptions.Subscription; import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionManager; import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionResult; import com.aelitis.azureus.core.rssgen.RSSGeneratorPlugin; public class SubscriptionRSSFeed implements RSSGeneratorPlugin.Provider { private static final String PROVIDER = "subscriptions"; private SubscriptionManagerImpl manager; private PluginInterface plugin_interface; private RSSGeneratorPlugin generator; protected SubscriptionRSSFeed( SubscriptionManagerImpl _manager, PluginInterface _plugin_interface ) { manager = _manager; plugin_interface = _plugin_interface; generator = RSSGeneratorPlugin.getSingleton(); generator.registerProvider( PROVIDER, this ); } public boolean isEnabled() { return( manager.isRSSPublishEnabled()); } public String getFeedURL() { return( generator.getURL() + PROVIDER ); } public boolean generate( TrackerWebPageRequest request, TrackerWebPageResponse response ) throws IOException { InetSocketAddress local_address = request.getLocalAddress(); if ( local_address == null ){ return( false ); } URL url = request.getAbsoluteURL(); String path = url.getPath(); path = path.substring( PROVIDER.length()+1); try{ SubscriptionManager sman = plugin_interface.getUtilities().getSubscriptionManager(); Subscription[] subs = sman.getSubscriptions(); OutputStream os = response.getOutputStream(); PrintWriter pw = new PrintWriter(new OutputStreamWriter( os, "UTF-8" )); if ( path.length() <= 1 ){ response.setContentType( "text/html; charset=UTF-8" ); pw.println( "Vuze Subscription Feeds" ); for ( Subscription s: subs ){ String name = s.getName(); pw.println( "

  • " + name + "
  • " ); } pw.println( "" ); }else{ String id = path.substring( 1 ); Subscription subscription = null; for ( Subscription s: subs ){ if ( s.getID().equals( id )){ subscription = s; break; } } if ( subscription == null ){ response.setReplyStatus( 404 ); return( true ); } URL feed_url = url; // absolute url is borked as it doesn't set the host properly. hack String host = (String)request.getHeaders().get( "host" ); if ( host != null ){ int pos = host.indexOf( ':' ); if ( pos != -1 ){ host = host.substring( 0, pos ); } feed_url = UrlUtils.setHost( url, host ); } response.setContentType( "application/xml" ); pw.println( "" ); pw.println( "" ); pw.println( "" ); String channel_title = "Vuze Subscription: " + escape( subscription.getName()); pw.println( "" + channel_title + "" ); pw.println( "http://vuze.com" ); pw.println( "" ); pw.println( "Vuze RSS Feed for subscription " + escape( subscription.getName()) + "" ); pw.println(""); pw.println("http://www.vuze.com/img/vuze_icon_128.png" + channel_title + "http://vuze.com"); SubscriptionResult[] results = subscription.getResults(); String feed_date_key = "subscriptions.feed_date." + subscription.getID(); long feed_date = COConfigurationManager.getLongParameter( feed_date_key ); boolean new_date = false; for ( SubscriptionResult result: results ){ Date date = (Date)result.getProperty( SearchResult.PR_PUB_DATE ); long millis = date.getTime(); if ( millis > feed_date ){ feed_date = millis; new_date = true; } } if ( new_date ){ COConfigurationManager.setParameter( feed_date_key, feed_date ); } pw.println( "" + TimeFormatter.getHTTPDate( feed_date ) + "" ); for ( SubscriptionResult result: results ){ try{ pw.println( "" ); String name = (String)result.getProperty( SearchResult.PR_NAME ); pw.println( "" + escape( name ) + "" ); Date date = (Date)result.getProperty( SearchResult.PR_PUB_DATE ); if ( date != null ){ pw.println( "" + TimeFormatter.getHTTPDate( date.getTime()) + "" ); } String uid = (String)result.getProperty( SearchResult.PR_UID ); if ( uid != null ){ pw.println( "" + escape(uid ) + "" ); } String link = (String)result.getProperty( SearchResult.PR_DOWNLOAD_LINK ); Long size = (Long)result.getProperty( SearchResult.PR_SIZE ); if ( link != null ){ pw.println( "" + link + "" ); if ( size != null ){ pw.println( "" ); } } if ( size != null ){ pw.println( "" + size + "" ); } Long seeds = (Long)result.getProperty( SearchResult.PR_SEED_COUNT ); if ( seeds != null ){ pw.println( "" + seeds + "" ); } Long peers = (Long)result.getProperty( SearchResult.PR_LEECHER_COUNT ); if ( peers != null ){ pw.println( "" + peers + "" ); } Long rank = (Long)result.getProperty( SearchResult.PR_RANK ); if ( rank != null ){ pw.println( "" + rank + "" ); } pw.println( "" ); }catch( Throwable e ){ Debug.out(e); } } pw.println( "" ); pw.println( "" ); } pw.flush(); }catch( Throwable e ){ Debug.out( e ); throw( new IOException( Debug.getNestedExceptionMessage( e ))); } return( true ); } protected String escape( String str ) { return( XUXmlWriter.escapeXML(str)); } protected String escapeMultiline( String str ) { return( XUXmlWriter.escapeXML(str.replaceAll("[\r\n]+", "
    "))); } } azureus-4.3.0.6/com/aelitis/azureus/core/subs/impl/SubscriptionResultFilter.java0000644000175000017500000001244311164756464027327 0ustar adrianadrianpackage com.aelitis.azureus.core.subs.impl; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.regex.Pattern; import com.aelitis.azureus.core.metasearch.Result; import com.aelitis.azureus.util.ImportExportUtils; public class SubscriptionResultFilter { private String[] textFilters; private Pattern[] textFilterPatterns; private String[] excludeTextFilters; private Pattern[] excludeTextFilterPatterns; private String regexFilter; // unused private long minSeeds = -1; private long minSize = -1; private long maxSize = -1; private String categoryFilter = null; public String getString() { String res = addString( "", "+", getString(textFilters)); res = addString( res, "-", getString(excludeTextFilters)); res = addString( res, "regex=", regexFilter ); res = addString( res, "cat=", categoryFilter ); return( res ); } private String addString( String existing, String key, String rest ) { if ( rest == null || rest.length() == 0 ){ return( existing ); } String str = key + rest; if ( existing == null || existing.length() == 0){ return( str ); } return( existing + "," + str ); } private String getString( String[] strs ) { String res = ""; for( int i=0;i filteredResults = new ArrayList(results.length); for(int i = 0 ; i < results.length ; i++) { Result result = results[i]; String name = result.getName(); //Results need a name, or they are by default invalid if(name == null) { continue; } name = name.toLowerCase(); boolean valid = true; for(int j = 0 ; j < textFilters.length ; j++) { //If one of the text filters do not match, let's not keep testing the others // and mark the result as not valid if(name.indexOf(textFilters[j]) == -1) { // double check against reg-expr if exists Pattern p = textFilterPatterns[j]; if ( p == null || !p.matcher( name ).find()){ valid = false; break; } } } //if invalid after name check, let's get to the next result if(!valid) { continue; } for(int j = 0 ; j < excludeTextFilters.length ; j++) { //If one of the text filters do not match, let's not keep testing the others // and mark the result as not valid if(name.indexOf(excludeTextFilters[j]) != -1) { valid = false; break; }else{ Pattern p = excludeTextFilterPatterns[j]; if ( p != null && p.matcher( name ).find()){ valid = false; break; } } } //if invalid after name check, let's get to the next result if(!valid) { continue; } long size = result.getSize(); if(minSize > -1) { if(minSize > size) { continue; } } if(maxSize > -1) { if(maxSize < size) { continue; } } if(minSeeds > -1) { if(minSeeds < result.getNbSeeds()) { continue; } } if(categoryFilter != null) { String category = result.getCategory(); if(category == null || !category.equalsIgnoreCase(categoryFilter)) { continue; } } //All filters are ok, let's add the results to the filtered results filteredResults.add(result); } Result[] fResults = (Result[]) filteredResults.toArray(new Result[filteredResults.size()]); return fResults; } }azureus-4.3.0.6/com/aelitis/azureus/core/subs/impl/SubscriptionSchedulerImpl.java0000644000175000017500000003614211236536722027436 0ustar adrianadrian/* * Created on Aug 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs.impl; import java.io.InputStream; import java.net.URL; import java.text.SimpleDateFormat; import java.util.*; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.AsyncDispatcher; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.core3.util.UrlUtils; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadManager; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.plugins.utils.StaticUtilities; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl; import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; import com.aelitis.azureus.core.subs.Subscription; import com.aelitis.azureus.core.subs.SubscriptionDownloadListener; import com.aelitis.azureus.core.subs.SubscriptionException; import com.aelitis.azureus.core.subs.SubscriptionHistory; import com.aelitis.azureus.core.subs.SubscriptionManagerListener; import com.aelitis.azureus.core.subs.SubscriptionResult; import com.aelitis.azureus.core.subs.SubscriptionScheduler; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.core.metasearch.Engine; import com.aelitis.azureus.core.metasearch.impl.web.WebEngine; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.UrlFilter; public class SubscriptionSchedulerImpl implements SubscriptionScheduler, SubscriptionManagerListener { private static final Object SCHEDULER_NEXT_SCAN_KEY = new Object(); private static final Object SCHEDULER_FAILED_SCAN_CONSEC_KEY = new Object(); private static final Object SCHEDULER_FAILED_SCAN_TIME_KEY = new Object(); private static final int FAIL_INIT_DELAY = 10*60*1000; private static final int FAIL_MAX_DELAY = 8*60*60*1000; private SubscriptionManagerImpl manager; private Map active_subscription_downloaders = new HashMap(); private boolean active_subs_download_is_auto; private Set active_result_downloaders = new HashSet(); private AsyncDispatcher result_downloader = new AsyncDispatcher(); private boolean schedulng_permitted; private TimerEvent schedule_event; private boolean schedule_in_progress; private long last_schedule; protected SubscriptionSchedulerImpl( SubscriptionManagerImpl _manager ) { manager = _manager; manager.addListener( this ); DelayedTask delayed_task = UtilitiesImpl.addDelayedTask( "Subscriptions Scheduler", new Runnable() { public void run() { synchronized( SubscriptionSchedulerImpl.this ){ schedulng_permitted = true; } calculateSchedule(); } }); delayed_task.queue(); } public void downloadAsync( Subscription subs, boolean is_auto ) throws SubscriptionException { download( subs, is_auto, new SubscriptionDownloadListener() { public void complete( Subscription subs ) { } public void failed( Subscription subs, SubscriptionException error ) { log( "Async download of " + subs.getName() + " failed", error ); } }); } public void download( final Subscription subs, final boolean is_auto, final SubscriptionDownloadListener listener ) { new AEThread2( "SS:download", true ) { public void run() { try{ download( subs, is_auto ); listener.complete( subs ); }catch( SubscriptionException e ){ listener.failed( subs, e ); }catch( Throwable e ){ listener.failed( subs, new SubscriptionException( "Download failed", e )); } } }.start(); } public void download( Subscription subs, boolean is_auto ) throws SubscriptionException { SubscriptionDownloader downloader; AESemaphore sem = null; synchronized( active_subscription_downloaders ){ List waiting = (List)active_subscription_downloaders.get( subs ); if ( waiting != null ){ sem = new AESemaphore( "SS:waiter" ); waiting.add( sem ); if ( !is_auto ){ active_subs_download_is_auto = false; } }else{ active_subscription_downloaders.put( subs, new ArrayList()); active_subs_download_is_auto = is_auto; } downloader = new SubscriptionDownloader(manager, (SubscriptionImpl)subs ); } try{ if ( sem == null ){ downloader.download(); }else{ sem.reserve(); } }finally{ boolean was_auto; synchronized( active_subscription_downloaders ){ List waiting = (List)active_subscription_downloaders.remove( subs ); if ( waiting != null ){ for (int i=0;i 0 ){ url_rd.setProperty( "URL_Cookie", cookies ); } } } ResourceDownloader mr_rd = rdf.getMetaRefreshDownloader( url_rd ); InputStream is = mr_rd.download(); Torrent torrent = new TorrentImpl( TOTorrentFactory.deserialiseFromBEncodedInputStream( is )); // PlatformTorrentUtils.setContentTitle(torrent, torr ); DownloadManager dm = PluginInitializer.getDefaultInterface().getDownloadManager(); Download download; boolean auto_start = manager.shouldAutoStart( torrent ); if ( auto_start ){ download = dm.addDownload( torrent ); }else{ download = dm.addDownloadStopped( torrent, null, null ); } log( subs.getName() + ": added download " + download.getName()+ ": auto-start=" + auto_start ); subs.addAssociation( torrent.getHash()); result.setRead( true ); if ( tried_ref_switch ){ subs.getHistory().setDownloadWithReferer( use_ref ); } }catch( Throwable e ){ log( subs.getName() + ": Failed to download result " + dl, e ); if ( e instanceof TOTorrentException && !tried_ref_switch ){ use_ref = !use_ref; tried_ref_switch = true; retry = true; log( subs.getName() + ": Retrying " + (use_ref?"with referer":"without referer" )); } } } }finally{ synchronized( active_result_downloaders ){ active_result_downloaders.remove( key ); } calculateSchedule(); } } }); } } protected void calculateSchedule() { Subscription[] subs = manager.getSubscriptions(); synchronized( this ){ if ( !schedulng_permitted ){ return; } if ( schedule_in_progress ){ return; } long next_ready_time = Long.MAX_VALUE; for (int i=0;i FAIL_MAX_DELAY ){ backoff = FAIL_MAX_DELAY; break; } } return( fail_time + backoff ); } return( history.getNextScanTime() ); } protected void scanSuccess( Subscription sub ) { sub.setUserData( SCHEDULER_FAILED_SCAN_CONSEC_KEY, null ); } protected void scanFailed( Subscription sub ) { sub.setUserData( SCHEDULER_FAILED_SCAN_TIME_KEY, new Long( SystemTime.getCurrentTime())); Long fail_count = (Long)sub.getUserData( SCHEDULER_FAILED_SCAN_CONSEC_KEY ); if ( fail_count == null ){ fail_count = new Long(1); }else{ fail_count = new Long(fail_count.longValue()+1); } sub.setUserData( SCHEDULER_FAILED_SCAN_CONSEC_KEY, fail_count ); } protected void log( String str ) { manager.log( "Scheduler: " + str ); } protected void log( String str, Throwable e ) { manager.log( "Scheduler: " + str, e ); } public void subscriptionAdded( Subscription subscription ) { calculateSchedule(); } public void subscriptionChanged( Subscription subscription ) { calculateSchedule(); } public void subscriptionSelected( Subscription subscription ) { } public void subscriptionRemoved( Subscription subscription ) { calculateSchedule(); } public void associationsChanged( byte[] association_hash ) { } } azureus-4.3.0.6/com/aelitis/azureus/core/subs/impl/SubscriptionResultImpl.java0000644000175000017500000001466111264725204026774 0ustar adrianadrian/* * Created on Aug 7, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs.impl; import java.util.*; import org.gudy.azureus2.core3.util.Base32; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DisplayFormatters; import org.gudy.azureus2.core3.util.SHA1Simple; import org.gudy.azureus2.plugins.utils.search.SearchResult; import com.aelitis.azureus.core.metasearch.Result; import com.aelitis.azureus.core.subs.SubscriptionResult; import com.aelitis.azureus.util.JSONUtils; public class SubscriptionResultImpl implements SubscriptionResult { final private SubscriptionHistoryImpl history; private byte[] key1; private byte[] key2; private boolean read; private boolean deleted; private String result_json; protected SubscriptionResultImpl( SubscriptionHistoryImpl _history, Result result ) { history = _history; Map map = result.toJSONMap(); result_json = JSONUtils.encodeToJSON( map ); read = false; String key1_str = result.getEngine().getId() + ":" + result.getName(); try{ byte[] sha1 = new SHA1Simple().calculateHash( key1_str.getBytes( "UTF-8" )); key1 = new byte[10]; System.arraycopy( sha1, 0, key1, 0, 10 ); }catch( Throwable e ){ Debug.printStackTrace(e); } String uid = result.getUID(); if ( uid != null && uid.length() > 0 ){ String key2_str = result.getEngine().getId() + ":" + uid; try{ byte[] sha1 = new SHA1Simple().calculateHash( key2_str.getBytes( "UTF-8" )); key2 = new byte[10]; System.arraycopy( sha1, 0, key2, 0, 10 ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected SubscriptionResultImpl( SubscriptionHistoryImpl _history, Map map ) { history = _history; key1 = (byte[])map.get( "key" ); key2 = (byte[])map.get( "key2" ); read = ((Long)map.get( "read")).intValue()==1; Long l_deleted = (Long)map.get( "deleted" ); if ( l_deleted != null ){ deleted = true; }else{ try{ result_json = new String((byte[])map.get( "result_json" ), "UTF-8" ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected boolean updateFrom( SubscriptionResultImpl other ) { if ( deleted ){ return( false ); } if ( getJSON().equals( other.getJSON())){ return( false ); }else{ key2 = other.getKey2(); result_json = other.getJSON(); return( true ); } } public String getID() { return( Base32.encode( key1 )); } protected byte[] getKey1() { return( key1 ); } protected byte[] getKey2() { return( key2 ); } public boolean getRead() { return( read ); } public void setRead( boolean _read ) { if ( read != _read ){ read = _read; history.updateResult( this ); } } protected void setReadInternal( boolean _read ) { read = _read; } public void delete() { if ( !deleted ){ deleted = true; history.updateResult( this ); } } protected void deleteInternal() { deleted = true; } public boolean isDeleted() { return( deleted ); } protected Map toBEncodedMap() { Map map = new HashMap(); map.put( "key", key1 ); if ( key2 != null ){ map.put( "key2", key2 ); } map.put( "read", new Long(read?1:0)); if ( deleted ){ map.put( "deleted", new Long(1)); }else{ try{ map.put( "result_json", result_json.getBytes( "UTF-8" )); }catch( Throwable e ){ Debug.printStackTrace(e); } } return( map ); } public Map toJSONMap() { Map map = JSONUtils.decodeJSON( result_json ); map.put( "subs_is_read", new Boolean( read )); map.put( "subs_id", getID()); Result.adjustRelativeTerms( map ); // migration - trim digits String size = (String)map.get( "l" ); if ( size != null ){ size = DisplayFormatters.trimDigits( size, 3 ); map.put( "l", size ); } return( map ); } private String getJSON() { return( result_json ); } public String getDownloadLink() { Map map = toJSONMap(); String link = (String)map.get( "dbl" ); if ( link == null ){ link = (String)map.get( "dl" ); } return( link ); } public String getPlayLink() { return((String)toJSONMap().get( "pl" )); } public String getAssetHash() { return((String)toJSONMap().get( "h" )); } public Map toPropertyMap() { Map map = toJSONMap(); Map result = new HashMap(); String title = (String)map.get( "n" ); result.put( SearchResult.PR_UID, getID()); result.put( SearchResult.PR_NAME, title ); String pub_date = (String)map.get( "ts" ); if ( pub_date != null ){ result.put( SearchResult.PR_PUB_DATE, new Date( Long.parseLong( pub_date ))); } String size = (String)map.get( "lb" ); if ( size != null ){ result.put( SearchResult.PR_SIZE, Long.parseLong( size )); } String link = (String)map.get( "dbl" ); if ( link == null ){ link = (String)map.get( "dl" ); } if ( link != null ){ result.put( SearchResult.PR_DOWNLOAD_LINK, link ); } String hash = (String)map.get( "h" ); if ( hash != null ){ result.put( SearchResult.PR_HASH, hash ); } String seeds = (String)map.get( "s" ); if ( seeds != null ){ result.put( SearchResult.PR_SEED_COUNT, Long.parseLong(seeds) ); } String peers = (String)map.get( "p" ); if ( peers != null ){ result.put( SearchResult.PR_LEECHER_COUNT, Long.parseLong(peers) ); } String rank = (String)map.get( "r" ); if ( rank != null ){ result.put( SearchResult.PR_RANK, (long)(100*Float.parseFloat( rank ))); } return( result ); } } azureus-4.3.0.6/com/aelitis/azureus/core/subs/impl/SubscriptionManagerImpl.java0000644000175000017500000033647311306320346027073 0ustar adrianadrian/* * Created on Jul 11, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs.impl; import java.io.*; import java.net.InetSocketAddress; import java.net.URL; import java.security.KeyPair; import java.util.*; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import org.bouncycastle.util.encoders.Base64; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.download.*; import org.gudy.azureus2.plugins.peers.PeerManager; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.torrent.TorrentManager; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.UIManagerEvent; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.plugins.utils.StaticUtilities; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl; import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.custom.Customization; import com.aelitis.azureus.core.custom.CustomizationManager; import com.aelitis.azureus.core.custom.CustomizationManagerFactory; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.lws.LightWeightSeed; import com.aelitis.azureus.core.lws.LightWeightSeedManager; import com.aelitis.azureus.core.messenger.config.PlatformSubscriptionsMessenger; import com.aelitis.azureus.core.metasearch.Engine; import com.aelitis.azureus.core.metasearch.MetaSearchListener; import com.aelitis.azureus.core.metasearch.MetaSearchManagerFactory; import com.aelitis.azureus.core.metasearch.impl.web.WebEngine; import com.aelitis.azureus.core.security.CryptoECCUtils; import com.aelitis.azureus.core.subs.*; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.vuzefile.*; import com.aelitis.azureus.plugins.dht.*; import com.aelitis.azureus.plugins.magnet.MagnetPlugin; import com.aelitis.azureus.plugins.magnet.MagnetPluginProgressListener; import com.aelitis.azureus.util.ImportExportUtils; import com.aelitis.azureus.util.UrlFilter; public class SubscriptionManagerImpl implements SubscriptionManager, AEDiagnosticsEvidenceGenerator { private static final String CONFIG_FILE = "subscriptions.config"; private static final String LOGGER_NAME = "Subscriptions"; private static final String CONFIG_MAX_RESULTS = "subscriptions.max.non.deleted.results"; private static final String CONFIG_AUTO_START_DLS = "subscriptions.auto.start.downloads"; private static final String CONFIG_AUTO_START_MIN_MB = "subscriptions.auto.start.min.mb"; private static final String CONFIG_AUTO_START_MAX_MB = "subscriptions.auto.start.max.mb"; private static final String RSS_ENABLE_CONFIG_KEY = "subscriptions.config.rss_enable"; private static SubscriptionManagerImpl singleton; private static boolean pre_initialised; private static final int random_seed = RandomUtils.nextInt( 256 ); public static void preInitialise() { synchronized( SubscriptionManagerImpl.class ){ if ( pre_initialised ){ return; } pre_initialised = true; } VuzeFileHandler.getSingleton().addProcessor( new VuzeFileProcessor() { public void process( VuzeFile[] files, int expected_types ) { for (int i=0;i " + subs_str ); recordAssociationsSupport( hash, subs, ((Boolean)entry[1]).booleanValue()); } } } public void downloadRemoved( Download download ) { } }, false ); TorrentUtils.addTorrentAttributeListener( new TorrentUtils.torrentAttributeListener() { public void attributeSet( TOTorrent torrent, String attribute, Object value ) { if ( attribute == TorrentUtils.TORRENT_AZ_PROP_OBTAINED_FROM ){ try{ checkPotentialAssociations( torrent.getHash(), (String)value ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } }); DelayedTask delayed_task = UtilitiesImpl.addDelayedTask( "Subscriptions", new Runnable() { public void run() { new AEThread2( "Subscriptions:delayInit", true ) { public void run() { asyncInit(); } }.start(); } protected void asyncInit() { Download[] downloads = default_pi.getDownloadManager().getDownloads(); for (int i=0;i 64?name.substring(0,64):name; singleton_details.put( "name", name2 ); if ( check_interval_mins != SubscriptionHistoryImpl.DEFAULT_CHECK_INTERVAL_MINS ){ singleton_details.put( "ci", new Long( check_interval_mins )); } return( singleton_details ); }catch( Throwable e ){ throw( new SubscriptionException( "Failed to create subscription", e )); } } protected SubscriptionImpl createSingletonSubscription( Map singleton_details, int add_type, boolean subscribe ) throws SubscriptionException { try{ String name = ImportExportUtils.importString( singleton_details, "name", "(Anonymous)" ); URL url = new URL( ImportExportUtils.importString( singleton_details, "key" )); int check_interval_mins = (int)ImportExportUtils.importLong( singleton_details, "ci", SubscriptionHistoryImpl.DEFAULT_CHECK_INTERVAL_MINS ); // only defined type is singleton rss SubscriptionImpl s = (SubscriptionImpl)createSingletonRSSSupport( name, url, true, check_interval_mins, add_type, subscribe ); return( s ); }catch( Throwable e ){ log( "Creation of singleton from " + singleton_details + " failed", e ); throw( new SubscriptionException( "Creation of singleton from " + singleton_details + " failed", e )); } } public Subscription createRSS( String name, URL url, int check_interval_mins, Map user_data ) throws SubscriptionException { checkURL( url ); try{ name = getUniqueName(name); Engine engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().createRSSEngine( name, url ); String json = SubscriptionImpl.getSkeletonJSON( engine, check_interval_mins ); // engine name may have been modified so re-read it for subscription default SubscriptionImpl subs = new SubscriptionImpl( this, engine.getName(), engine.isPublic(), null, json, SubscriptionImpl.ADD_TYPE_CREATE ); if ( user_data != null ){ Iterator it = user_data.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); subs.setUserData( entry.getKey(), entry.getValue()); } } log( "Created new subscription: " + subs.getString()); subs = addSubscription( subs ); if ( subs.isPublic()){ updatePublicSubscription( subs ); } return( subs ); }catch( Throwable e ){ throw( new SubscriptionException( "Failed to create subscription", e )); } } protected void checkURL( URL url ) throws SubscriptionException { if ( url.getHost().trim().length() == 0 ){ String protocol = url.getProtocol().toLowerCase(); if ( ! ( protocol.equals( "azplug" ) || protocol.equals( "file" ))){ throw( new SubscriptionException( "Invalid URL '" + url + "'" )); } } } protected SubscriptionImpl addSubscription( SubscriptionImpl subs ) { SubscriptionImpl existing; synchronized( this ){ existing = getSubscriptionFromSID( subs.getShortID()); if ( existing == null ){ subscriptions.add( subs ); saveConfig(); } } if ( existing != null ){ log( "Attempted to add subscription when already present: " + subs.getString()); subs.destroy(); return( existing ); } if ( subs.isMine()){ addMetaSearchListener(); } if ( subs.getCachedPopularity() == -1 ){ try{ subs.getPopularity( new SubscriptionPopularityListener() { public void gotPopularity( long popularity ) { } public void failed( SubscriptionException error ) { } }); }catch( Throwable e ){ log( "", e ); } } Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((SubscriptionManagerListener)it.next()).subscriptionAdded( subs ); }catch( Throwable e ){ Debug.printStackTrace(e); } } if ( subs.isSubscribed() && subs.isPublic()){ setSelected( subs ); } if ( dht_plugin != null ){ new AEThread2( "Publish check", true ) { public void run() { publishSubscriptions(); } }.start(); } return( subs ); } protected void addMetaSearchListener() { synchronized( this ){ if ( meta_search_listener_added ){ return; } meta_search_listener_added = true; } MetaSearchManagerFactory.getSingleton().getMetaSearch().addListener( new MetaSearchListener() { public void engineAdded( Engine engine ) { } public void engineUpdated( Engine engine ) { synchronized( this ){ for (int i=0;i 24*60*60*1000 ){ break; } } if ( l_last_pub.longValue() + delay > SystemTime.getMonotonousTime()){ return; } } try{ File vf = getVuzeFile( subs ); byte[] bytes = FileUtil.readFileAsByteArray( vf ); byte[] encoded_subs = Base64.encode( bytes ); PlatformSubscriptionsMessenger.updateSubscription( !subs.getServerPublished(), subs.getName(), subs.getPublicKey(), subs.getPrivateKey(), subs.getShortID(), subs.getVersion(), new String( encoded_subs )); subs.setUserData( SP_LAST_ATTEMPTED, null ); subs.setUserData( SP_CONSEC_FAIL, null ); subs.setServerPublished(); log( " Updated public subscription " + subs.getString()); }catch( Throwable e ){ log( " Failed to update public subscription " + subs.getString(), e ); subs.setUserData( SP_LAST_ATTEMPTED, new Long( SystemTime.getMonotonousTime())); subs.setUserData( SP_CONSEC_FAIL, new Long( l_consec_fail==null?1:(l_consec_fail.longValue()+1))); subs.setServerPublicationOutstanding(); } } } protected void checkSingletonPublish( SubscriptionImpl subs ) throws SubscriptionException { if ( subs.getSingletonPublishAttempted()){ throw( new SubscriptionException( "Singleton publish already attempted" )); } subs.setSingletonPublishAttempted(); try{ File vf = getVuzeFile( subs ); byte[] bytes = FileUtil.readFileAsByteArray( vf ); byte[] encoded_subs = Base64.encode( bytes ); // use a transient key-pair as we won't have the private key in general KeyPair kp = CryptoECCUtils.createKeys(); byte[] public_key = CryptoECCUtils.keyToRawdata( kp.getPublic()); byte[] private_key = CryptoECCUtils.keyToRawdata( kp.getPrivate()); PlatformSubscriptionsMessenger.updateSubscription( true, subs.getName(), public_key, private_key, subs.getShortID(), 1, new String( encoded_subs )); log( " created singleton public subscription " + subs.getString()); }catch( Throwable e ){ throw( new SubscriptionException( "Failed to publish singleton", e )); } } protected void checkServerPublications( List subs ) { for (int i=0;i= body.getVersion()){ log( "Not upgrading subscription: " + existing.getString() + " as supplied (" + body.getVersion() + ") is not more recent than existing (" + existing.getVersion() + ")"); if ( warn_user ){ UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 ); String details = MessageText.getString( "subscript.add.dup.desc", new String[]{ existing.getName()}); ui_manager.showMessageBox( "subscript.add.dup.title", "!" + details + "!", UIManagerEvent.MT_OK ); } // we have a newer one, ignore selectSubscription( existing ); return( existing ); }else{ if ( warn_user ){ UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 ); String details = MessageText.getString( "subscript.add.upgrade.desc", new String[]{ existing.getName()}); long res = ui_manager.showMessageBox( "subscript.add.upgrade.title", "!" + details + "!", UIManagerEvent.MT_YES | UIManagerEvent.MT_NO ); if ( res != UIManagerEvent.MT_YES ){ throw( new SubscriptionException( "User declined upgrade" )); } } log( "Upgrading subscription: " + existing.getString()); existing.upgrade( body ); saveConfig(); subscriptionUpdated(); return( existing ); } }else{ SubscriptionImpl new_subs = new SubscriptionImpl( this, body, SubscriptionImpl.ADD_TYPE_IMPORT, true ); if ( warn_user ){ UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 ); String details = MessageText.getString( "subscript.add.desc", new String[]{ new_subs.getName()}); long res = ui_manager.showMessageBox( "subscript.add.title", "!" + details + "!", UIManagerEvent.MT_YES | UIManagerEvent.MT_NO ); if ( res != UIManagerEvent.MT_YES ){ throw( new SubscriptionException( "User declined addition" )); } } log( "Imported new subscription: " + new_subs.getString()); if ( existing != null ){ existing.remove(); } new_subs = addSubscription( new_subs ); return( new_subs ); } } }catch( Throwable e ){ throw( new SubscriptionException( "Subscription import failed", e )); } }catch( SubscriptionException e ){ if ( warn_user && log_errors ){ UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 ); String details = MessageText.getString( "subscript.import.fail.desc", new String[]{ Debug.getNestedExceptionMessage(e)}); ui_manager.showMessageBox( "subscript.import.fail.title", "!" + details + "!", UIManagerEvent.MT_OK ); } throw( e ); } } public Subscription[] getSubscriptions() { synchronized( this ){ return((SubscriptionImpl[])subscriptions.toArray( new SubscriptionImpl[subscriptions.size()])); } } public Subscription[] getSubscriptions( boolean subscribed_only ) { if ( !subscribed_only ){ return( getSubscriptions()); } List result = new ArrayList(); synchronized( this ){ for (int i=0;i 0 ){ List result = new ArrayList( s.size()); for (int i=0;i 0 ){ for (int i=0;i 0 ){ List result = new ArrayList( s.size()); for (int i=0;i now ){ last_check = now; map.put( "lc", new Long( last_check )); download.setMapAttribute( ta_subscription_info, map ); } List subs = (List)map.get( "s" ); int sub_count = subs==null?0:subs.size(); if ( sub_count > 8 ){ continue; } long create_time = download.getCreationTime(); int time_between_checks = (sub_count + 1) * 24*60*60*1000 + (int)(create_time%4*60*60*1000); if ( now - last_check >= time_between_checks ){ if ( create_time > newest_time ){ newest_time = create_time; newest_download = download; } } } if ( newest_download != null ){ byte[] hash = newest_download.getTorrent().getHash(); log( "Association lookup starts for " + newest_download.getName() + "/" + ByteFormatter.encodeString( hash )); lookupAssociationsSupport( hash, new SubscriptionLookupListener() { public void found( byte[] hash, Subscription subscription ) { } public void failed( byte[] hash, SubscriptionException error ) { log( "Association lookup failed for " + ByteFormatter.encodeString( hash ), error ); associationLookupComplete(); } public void complete( byte[] hash, Subscription[] subs ) { log( "Association lookup complete for " + ByteFormatter.encodeString( hash )); associationLookupComplete(); } }); }else{ associationLookupComplete(); } }catch( Throwable e ){ log( "Association lookup check failed", e ); associationLookupComplete(); } } protected void associationLookupComplete() { boolean recheck; synchronized( SubscriptionManagerImpl.this ){ periodic_lookup_in_progress = false; recheck = priority_lookup_pending > 0; if ( recheck ){ priority_lookup_pending--; } } if ( recheck ){ new AEThread2( "SM:priAssLookup", true ) { public void run() { lookupAssociations( false ); } }.start(); } } protected void setSelected( List subs ) { List sids = new ArrayList(); List used_subs = new ArrayList(); for (int i=0;i 0 ){ try{ List[] result = PlatformSubscriptionsMessenger.setSelected( sids ); List versions = result[0]; List popularities = result[1]; log( "Popularity update: updated " + sids.size()); final List dht_pops = new ArrayList(); for (int i=0;i sub.getVersion()){ updateSubscription( sub, latest_version ); }else{ checkInitialDownload( sub ); } if ( latest_version > 0 ){ try{ long pop = ((Long)popularities.get(i)).longValue(); if ( pop >= 0 && pop != sub.getCachedPopularity()){ sub.setCachedPopularity( pop ); } }catch( Throwable e ){ log( "Popularity update: Failed to extract popularity", e ); } }else{ dht_pops.add( sub ); } } if ( dht_pops.size() <= 3 ){ for (int i=0;i sub.getVersion()){ updateSubscription( sub, latest_version ); }else{ checkInitialDownload( sub ); } if ( latest_version > 0 ){ try{ long pop = ((Long)result[1].get(0)).longValue(); if ( pop >= 0 && pop != sub.getCachedPopularity()){ sub.setCachedPopularity( pop ); } }catch( Throwable e ){ log( "Popularity update: Failed to extract popularity", e ); } }else{ updatePopularityFromDHT( sub, true ); } }catch( Throwable e ){ log( "setSelected: failed for " + sub.getName(), e ); } } }); }else{ checkInitialDownload( sub ); } } } protected void checkInitialDownload( SubscriptionImpl subs ) { if ( subs.getHistory().getLastScanTime() == 0 ){ scheduler.download( subs, true, new SubscriptionDownloadListener() { public void complete( Subscription subs ) { log( "Initial download of " + subs.getName() + " complete" ); } public void failed( Subscription subs, SubscriptionException error ) { log( "Initial download of " + subs.getName() + " failed", error ); } }); } } public SubscriptionAssociationLookup lookupAssociations( final byte[] hash, final SubscriptionLookupListener listener ) throws SubscriptionException { if ( dht_plugin != null && !dht_plugin.isInitialising()){ return( lookupAssociationsSupport( hash, listener )); } final boolean[] cancelled = { false }; final SubscriptionAssociationLookup[] actual_res = { null }; final SubscriptionAssociationLookup res = new SubscriptionAssociationLookup() { public void cancel() { log( " Association lookup cancelled" ); synchronized( actual_res ){ cancelled[0] = true; if ( actual_res[0] != null ){ actual_res[0].cancel(); } } } }; new AEThread2( "SM:initwait", true ) { public void run() { try{ SubscriptionAssociationLookup x = lookupAssociationsSupport( hash, listener ); synchronized( actual_res ){ actual_res[0] = x; if ( cancelled[0] ){ x.cancel(); } } }catch( SubscriptionException e ){ listener.failed( hash, e ); } } }.start(); return( res ); } protected SubscriptionAssociationLookup lookupAssociationsSupport( final byte[] hash, final SubscriptionLookupListener listener ) throws SubscriptionException { log( "Looking up associations for '" + ByteFormatter.encodeString( hash )); final String key = "subscription:assoc:" + ByteFormatter.encodeString( hash ); final boolean[] cancelled = { false }; dht_plugin.get( key.getBytes(), "Subscription association read: " + ByteFormatter.encodeString( hash ), DHTPlugin.FLAG_SINGLE_VALUE, 30, 60*1000, true, true, new DHTPluginOperationListener() { private Map hits = new HashMap(); private AESemaphore hits_sem = new AESemaphore( "Subs:lookup" ); private List found_subscriptions = new ArrayList(); private boolean complete; public void diversified() { } public void starts( byte[] key ) { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { if ( isCancelled2()){ return; } byte[] val = value.getValue(); if ( val.length > 4 ){ int ver = ((val[0]<<16)&0xff0000) | ((val[1]<<8)&0xff00) | (val[2]&0xff); byte[] sid = new byte[ val.length - 4 ]; System.arraycopy( val, 4, sid, 0, sid.length ); HashWrapper hw = new HashWrapper( sid ); boolean new_sid = false; synchronized( this ){ if ( complete ){ return; } Integer v = (Integer)hits.get(hw); if ( v != null ){ if ( ver > v.intValue()){ hits.put( hw, new Integer( ver )); } }else{ new_sid = true; hits.put( hw, new Integer( ver )); } } if ( new_sid ){ log( " Found subscription " + ByteFormatter.encodeString( sid ) + " version " + ver ); // check if already subscribed SubscriptionImpl subs = getSubscriptionFromSID( sid ); if ( subs != null ){ found_subscriptions.add( subs ); try{ listener.found( hash, subs ); }catch( Throwable e ){ Debug.printStackTrace(e); } hits_sem.release(); }else{ lookupSubscription( hash, sid, ver, new subsLookupListener() { private boolean sem_done = false; public void found( byte[] hash, Subscription subscription ) { } public void complete( byte[] hash, Subscription[] subscriptions ) { done( subscriptions ); } public void failed( byte[] hash, SubscriptionException error ) { done( new Subscription[0]); } protected void done( Subscription[] subs ) { if ( isCancelled()){ return; } synchronized( this ){ if ( sem_done ){ return; } sem_done = true; } if ( subs.length > 0 ){ found_subscriptions.add( subs[0] ); try{ listener.found( hash, subs[0] ); }catch( Throwable e ){ Debug.printStackTrace(e); } } hits_sem.release(); } public boolean isCancelled() { return( isCancelled2()); } }); } } } } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] original_key, boolean timeout_occurred ) { new AEThread2( "Subs:lookup wait", true ) { public void run() { int num_hits; synchronized( this ){ if ( complete ){ return; } complete = true; num_hits = hits.size(); } for (int i=0;i= 0 ){ log( "Got popularity of " + subs.getName() + " from platform: " + pop ); listener.gotPopularity( pop ); return; }else{ // unknown sid - if singleton try to register for popularity tracking purposes if ( subs.isSingleton()){ try{ checkSingletonPublish( subs ); listener.gotPopularity( subs.isSubscribed()?1:0 ); return; }catch( Throwable e ){ log( " failed to create singleton public subscription " + subs.getString(), e ); } } } }catch( Throwable e ){ log( "Subscription lookup via platform failed", e ); } getPopularityFromDHT( subs, listener, true ); } protected void getPopularityFromDHT( final SubscriptionImpl subs, final SubscriptionPopularityListener listener, final boolean sync ) { if ( dht_plugin != null && !dht_plugin.isInitialising()){ getPopularitySupport( subs, listener, sync ); }else{ new AEThread2( "SM:popwait", true ) { public void run() { getPopularitySupport( subs, listener, sync ); } }.start(); } } protected void updatePopularityFromDHT( final SubscriptionImpl subs, boolean sync ) { getPopularityFromDHT( subs, new SubscriptionPopularityListener() { public void gotPopularity( long popularity ) { subs.setCachedPopularity( popularity ); } public void failed( SubscriptionException error ) { log( "Failed to update subscription popularity from DHT", error ); } }, sync ); } protected void getPopularitySupport( final SubscriptionImpl subs, final SubscriptionPopularityListener listener, final boolean sync ) { log( "Getting popularity of " + subs.getName() + " from DHT" ); byte[] hash = subs.getPublicationHash(); final AESemaphore sem = new AESemaphore( "SM:pop" ); final long[] result = { -1 }; final int timeout = 15*1000; dht_plugin.get( hash, "Popularity lookup for subscription " + subs.getName(), DHT.FLAG_STATS, 5, timeout, false, true, new DHTPluginOperationListener() { private boolean diversified; private int hits = 0; public void diversified() { diversified = true; } public void starts( byte[] key ) { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { DHTPluginKeyStats stats = dht_plugin.decodeStats( value ); result[0] = Math.max( result[0], stats.getEntryCount()); hits++; if ( hits >= 3 ){ done(); } } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] key, boolean timeout_occurred ) { if ( diversified ){ // TODO: fix? result[0] *= 11; if ( result[0] == 0 ){ result[0] = 10; } } done(); } protected void done() { if ( sync ){ sem.release(); }else{ if ( result[0] == -1 ){ log( "Failed to get popularity of " + subs.getName() + " from DHT" ); listener.failed( new SubscriptionException( "Timeout" )); }else{ log( "Get popularity of " + subs.getName() + " from DHT: " + result[0] ); listener.gotPopularity( result[0] ); } } } }); if ( sync ){ sem.reserve( timeout ); if ( result[0] == -1 ){ log( "Failed to get popularity of " + subs.getName() + " from DHT" ); listener.failed( new SubscriptionException( "Timeout" )); }else{ log( "Get popularity of " + subs.getName() + " from DHT: " + result[0] ); listener.gotPopularity( result[0] ); } } } protected void lookupSubscription( final byte[] association_hash, final byte[] sid, final int version, final subsLookupListener listener ) { try{ SubscriptionImpl subs = getSubscriptionFromPlatform( sid, SubscriptionImpl.ADD_TYPE_LOOKUP ); log( "Added temporary subscription: " + subs.getString()); subs = addSubscription( subs ); listener.complete( association_hash, new Subscription[]{ subs }); return; }catch( Throwable e ){ if ( listener.isCancelled()){ return; } final String sid_str = ByteFormatter.encodeString( sid ); log( "Subscription lookup via platform for " + sid_str + " failed", e ); if ( getSubscriptionDownloadCount() > 8 ){ log( "Too many existing subscription downloads" ); listener.complete( association_hash, new Subscription[0]); return; } // fall back to DHT log( "Subscription lookup via DHT starts for " + sid_str ); final String key = "subscription:publish:" + ByteFormatter.encodeString( sid ) + ":" + version; dht_plugin.get( key.getBytes(), "Subscription lookup read: " + ByteFormatter.encodeString( sid ) + ":" + version, DHTPlugin.FLAG_SINGLE_VALUE, 12, 60*1000, false, true, new DHTPluginOperationListener() { private boolean listener_handled; public void diversified() { } public void starts( byte[] key ) { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { byte[] data = value.getValue(); try{ final Map details = decodeSubscriptionDetails( data ); if ( SubscriptionImpl.getPublicationVersion( details ) == version ){ Map singleton_details = (Map)details.get( "x" ); if ( singleton_details == null ){ synchronized( this ){ if ( listener_handled ){ return; } listener_handled = true; } log( " found " + sid_str + ", non-singleton" ); new AEThread2( "Subs:lookup download", true ) { public void run() { downloadSubscription( association_hash, SubscriptionImpl.getPublicationHash( details ), sid, version, SubscriptionImpl.getPublicationSize( details ), listener ); } }.start(); }else{ synchronized( this ){ if ( listener_handled ){ return; } listener_handled = true; } log( " found " + sid_str + ", singleton" ); try{ SubscriptionImpl subs = createSingletonSubscription( singleton_details, SubscriptionImpl.ADD_TYPE_LOOKUP, false ); listener.complete( association_hash, new Subscription[]{ subs }); }catch( Throwable e ){ listener.failed( association_hash, new SubscriptionException( "Subscription creation failed", e )); } } }else{ log( " found " + sid_str + " but version mismatch" ); } }catch( Throwable e ){ log( " found " + sid_str + " but verification failed", e ); } } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] original_key, boolean timeout_occurred ) { if ( listener.isCancelled()){ return; } log( " " + sid_str + " complete" ); synchronized( this ){ if ( !listener_handled ){ listener_handled = true; listener.complete( association_hash, new Subscription[0] ); } } } }); } } protected SubscriptionImpl getSubscriptionFromPlatform( byte[] sid, int add_type ) throws SubscriptionException { try{ PlatformSubscriptionsMessenger.subscriptionDetails details = PlatformSubscriptionsMessenger.getSubscriptionBySID( sid ); SubscriptionImpl res = getSubscriptionFromVuzeFileContent( sid, add_type, details.getContent()); int pop = details.getPopularity(); if ( pop >= 0 ){ res.setCachedPopularity( pop ); } return( res ); }catch( SubscriptionException e ){ throw( e ); }catch( Throwable e ){ throw( new SubscriptionException( "Failed to read subscription from platform", e )); } } protected SubscriptionImpl getSubscriptionFromVuzeFile( byte[] sid, int add_type, File file ) throws SubscriptionException { VuzeFileHandler vfh = VuzeFileHandler.getSingleton(); String file_str = file.getAbsolutePath(); VuzeFile vf = vfh.loadVuzeFile( file_str ); if ( vf == null ){ log( "Failed to load vuze file from " + file_str ); throw( new SubscriptionException( "Failed to load vuze file from " + file_str )); } return( getSubscriptionFromVuzeFile( sid, add_type, vf )); } protected SubscriptionImpl getSubscriptionFromVuzeFileContent( byte[] sid, int add_type, String content ) throws SubscriptionException { VuzeFileHandler vfh = VuzeFileHandler.getSingleton(); VuzeFile vf = vfh.loadVuzeFile( Base64.decode( content )); if ( vf == null ){ log( "Failed to load vuze file from " + content ); throw( new SubscriptionException( "Failed to load vuze file from content" )); } return( getSubscriptionFromVuzeFile( sid, add_type, vf )); } protected SubscriptionImpl getSubscriptionFromVuzeFile( byte[] sid, int add_type, VuzeFile vf ) throws SubscriptionException { VuzeFileComponent[] comps = vf.getComponents(); for (int j=0;j " + key ); synchronized( potential_associations ){ potential_associations.add( new Object[]{ subs, result_id, key, new Long( System.currentTimeMillis())} ); if ( potential_associations.size() > 512 ){ potential_associations.remove(0); } } } protected void checkPotentialAssociations( byte[] hash, String key ) { log( "Checking potential association: " + key + " -> " + ByteFormatter.encodeString( hash )); SubscriptionImpl subs = null; String result_id = null; synchronized( potential_associations ){ Iterator it = potential_associations.iterator(); while( it.hasNext()){ Object[] entry = (Object[])it.next(); String this_key = (String)entry[2]; // startswith as actual URL may have had additional parameters added such as azid if ( key.startsWith( this_key )){ subs = (SubscriptionImpl)entry[0]; result_id = (String)entry[1]; log( " key matched to subscription " + subs.getName() + "/" + result_id); it.remove(); break; } } } if ( subs == null ){ log( " no potential associations found" ); }else{ SubscriptionResult result = subs.getHistory().getResult( result_id ); if ( result != null ){ log( " result found, marking as read" ); result.setRead( true ); }else{ log( " result not found" ); } log( " adding association" ); subs.addAssociation( hash ); } } protected void tidyPotentialAssociations() { long now = SystemTime.getCurrentTime(); synchronized( potential_associations ){ Iterator it = potential_associations.iterator(); while( it.hasNext() && potential_associations.size() > 16 ){ Object[] entry = (Object[])it.next(); long created = ((Long)entry[3]).longValue(); if ( created > now ){ entry[3] = new Long( now ); }else if ( now - created > 60*60*1000 ){ SubscriptionImpl subs = (SubscriptionImpl)entry[0]; String result_id = (String)entry[1]; String key = (String)entry[2]; log( "Removing expired potential association: " + subs.getName() + "/" + result_id + " -> " + key ); it.remove(); } } } synchronized( potential_associations2 ){ Iterator it = potential_associations2.entrySet().iterator(); while( it.hasNext() && potential_associations2.size() > 16 ){ Map.Entry map_entry = (Map.Entry)it.next(); byte[] hash = ((HashWrapper)map_entry.getKey()).getBytes(); Object[] entry = (Object[])map_entry.getValue(); long created = ((Long)entry[2]).longValue(); if ( created > now ){ entry[2] = new Long( now ); }else if ( now - created > 60*60*1000 ){ SubscriptionImpl[] subs = (SubscriptionImpl[])entry[0]; String subs_str = ""; for (int i=0;i " + subs_str ); it.remove(); } } } } protected void recordAssociations( byte[] association_hash, SubscriptionImpl[] subscriptions, boolean full_lookup ) { HashWrapper hw = new HashWrapper( association_hash ); synchronized( potential_associations2 ){ potential_associations2.put( hw, new Object[]{ subscriptions, new Boolean( full_lookup ), new Long( SystemTime.getCurrentTime())}); } if ( recordAssociationsSupport( association_hash, subscriptions, full_lookup )){ synchronized( potential_associations2 ){ potential_associations2.remove( hw ); } }else{ log( "Deferring association for " + ByteFormatter.encodeString( association_hash )); } } protected boolean recordAssociationsSupport( byte[] association_hash, SubscriptionImpl[] subscriptions, boolean full_lookup ) { PluginInterface pi = PluginInitializer.getDefaultInterface(); boolean download_found = false; boolean changed = false; try{ Download download = pi.getDownloadManager().getDownload( association_hash ); if ( download != null ){ if ( subscriptions.length > 0 ){ String category = subscriptions[0].getCategory(); if ( category != null ){ String existing = download.getAttribute( ta_category ); if ( existing == null ){ download.setAttribute( ta_category, category ); } } } download_found = true; Map map = download.getMapAttribute( ta_subscription_info ); if ( map == null ){ map = new LightHashMap(); }else{ map = new LightHashMap( map ); } List s = (List)map.get( "s" ); for (int i=0;i= PUB_ASSOC_CONC_MAX ){ return( false ); } publish_associations_active++; List shuffled_subs = new ArrayList( subscriptions ); Collections.shuffle( shuffled_subs ); for (int i=0;i '" + assoc.getString() + "'" ); byte[] sub_id = subs.getShortID(); int sub_version = subs.getVersion(); byte[] assoc_hash = assoc.getHash(); final String key = "subscription:assoc:" + ByteFormatter.encodeString( assoc_hash ); final byte[] put_value = new byte[sub_id.length + 4]; System.arraycopy( sub_id, 0, put_value, 4, sub_id.length ); put_value[0] = (byte)(sub_version>>16); put_value[1] = (byte)(sub_version>>8); put_value[2] = (byte)sub_version; put_value[3] = (byte)subs.getFixedRandom(); dht_plugin.get( key.getBytes(), "Subscription association read: " + ByteFormatter.encodeString( assoc_hash ), DHTPlugin.FLAG_SINGLE_VALUE, 30, 60*1000, false, false, new DHTPluginOperationListener() { private int hits; private boolean diversified; private int max_ver; public void diversified() { diversified = true; } public void starts( byte[] key ) { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { byte[] val = value.getValue(); if ( val.length == put_value.length ){ boolean diff = false; for (int i=4;i max_ver ){ max_ver = ver; } } } } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] original_key, boolean timeout_occurred ) { log( "Checked association '" + subs.getString() + "' -> '" + assoc.getString() + "' - max_ver=" + max_ver + ",hits=" + hits + ",div=" + diversified ); if ( max_ver > subs.getVersion()){ if ( !subs.isMine()){ updateSubscription( subs, max_ver ); } } if (( hits == 0 && diversified ) || ( hits < 6 && !diversified )){ log( " Publishing association '" + subs.getString() + "' -> '" + assoc.getString() + "', existing=" + hits ); byte flags = DHTPlugin.FLAG_ANON; if ( hits < 3 && !diversified ){ flags |= DHTPlugin.FLAG_PRECIOUS; } dht_plugin.put( key.getBytes(), "Subscription association write: " + ByteFormatter.encodeString( assoc.getHash()) + " -> " + ByteFormatter.encodeString( subs.getShortID() ) + ":" + subs.getVersion(), put_value, flags, new DHTPluginOperationListener() { public void diversified() { } public void starts( byte[] key ) { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] key, boolean timeout_occurred ) { log( " completed '" + subs.getString() + "' -> '" + assoc.getString() + "'" ); publishNext(); } }); }else{ log( " Not publishing association '" + subs.getString() + "' -> '" + assoc.getString() + "', existing =" + hits ); publishNext(); } } protected void publishNext() { synchronized( this ){ publish_associations_active--; } publishAssociations(); } }); } protected void subscriptionUpdated() { if ( dht_plugin != null ){ publishSubscriptions(); } } protected void publishSubscriptions() { List shuffled_subs; synchronized( this ){ if ( publish_subscription_active ){ return; } shuffled_subs = new ArrayList( subscriptions ); publish_subscription_active = true; } boolean publish_initiated = false; try{ Collections.shuffle( shuffled_subs ); for (int i=0;i= new_version ){ log( " User has already been prompted for version " + new_version + " so ignoring" ); return; } byte[] sub_id = subs.getShortID(); try{ PlatformSubscriptionsMessenger.subscriptionDetails details = PlatformSubscriptionsMessenger.getSubscriptionBySID( sub_id ); if ( !askIfCanUpgrade( subs, new_version )){ return; } VuzeFileHandler vfh = VuzeFileHandler.getSingleton(); VuzeFile vf = vfh.loadVuzeFile( Base64.decode( details.getContent())); vfh.handleFiles( new VuzeFile[]{ vf }, VuzeFileComponent.COMP_TYPE_SUBSCRIPTION ); return; }catch( Throwable e ){ log( "Failed to read subscription from platform, trying DHT" ); } log( "Checking subscription '" + subs.getString() + "' upgrade to version " + new_version ); final String key = "subscription:publish:" + ByteFormatter.encodeString( sub_id ) + ":" + new_version; dht_plugin.get( key.getBytes(), "Subscription update read: " + ByteFormatter.encodeString( sub_id ) + ":" + new_version, DHTPlugin.FLAG_SINGLE_VALUE, 12, 60*1000, false, false, new DHTPluginOperationListener() { private byte[] verified_hash; private int verified_size; public void diversified() { } public void starts( byte[] key ) { } public void valueRead( DHTPluginContact originator, DHTPluginValue value ) { byte[] data = value.getValue(); try{ Map details = decodeSubscriptionDetails( data ); if ( verified_hash == null && subs.getVerifiedPublicationVersion( details ) == new_version ){ verified_hash = SubscriptionImpl.getPublicationHash( details ); verified_size = SubscriptionImpl.getPublicationSize( details ); } }catch( Throwable e ){ } } public void valueWritten( DHTPluginContact target, DHTPluginValue value ) { } public void complete( byte[] original_key, boolean timeout_occurred ) { if ( verified_hash != null ){ log( " Subscription '" + subs.getString() + " upgrade verified as authentic" ); updateSubscription( subs, new_version, verified_hash, verified_size ); }else{ log( " Subscription '" + subs.getString() + " upgrade not verified" ); } } }); } protected byte[] encodeSubscriptionDetails( SubscriptionImpl subs ) throws IOException { Map details = subs.getPublicationDetails(); // inject a random element so we can count occurrences properly (as the DHT logic // removes duplicates) details.put( "!", new Long( random_seed )); byte[] encoded = BEncoder.encode( details ); ByteArrayOutputStream baos = new ByteArrayOutputStream(); GZIPOutputStream os = new GZIPOutputStream( baos ); os.write( encoded ); os.close(); byte[] compressed = baos.toByteArray(); byte header; byte[] data; if ( compressed.length < encoded.length ){ header = 1; data = compressed; }else{ header = 0; data = encoded; } byte[] result = new byte[data.length+1]; result[0] = header; System.arraycopy( data, 0, result, 1, data.length ); return( result ); } protected Map decodeSubscriptionDetails( byte[] data ) throws IOException { byte[] to_decode; if ( data[0] == 0 ){ to_decode = new byte[ data.length-1 ]; System.arraycopy( data, 1, to_decode, 0, data.length - 1 ); }else{ GZIPInputStream is = new GZIPInputStream(new ByteArrayInputStream( data, 1, data.length - 1 )); to_decode = FileUtil.readInputStreamAsByteArray( is ); is.close(); } Map res = BDecoder.decode( to_decode ); // remove any injected random seed res.remove( "!" ); return( res ); } protected void updateSubscription( final SubscriptionImpl subs, final int update_version, final byte[] update_hash, final int update_size ) { log( "Subscription " + subs.getString() + " - update hash=" + ByteFormatter.encodeString( update_hash ) + ", size=" + update_size ); new AEThread2( "SubsUpdate", true ) { public void run() { try{ Object[] res = downloadTorrent( update_hash, update_size ); if ( res != null ){ updateSubscription( subs, update_version, (TOTorrent)res[0], (InetSocketAddress)res[1] ); } }catch( Throwable e ){ log( " update failed", e ); } } }.start(); } protected Object[] downloadTorrent( byte[] hash, int update_size ) { final MagnetPlugin magnet_plugin = getMagnetPlugin(); if ( magnet_plugin == null ){ log( " Can't download, no magnet plugin" ); return( null ); } try{ final InetSocketAddress[] sender = { null }; byte[] torrent_data = magnet_plugin.download( new MagnetPluginProgressListener() { public void reportSize( long size ) { } public void reportActivity( String str ) { log( " MagnetDownload: " + str ); } public void reportCompleteness( int percent ) { } public void reportContributor( InetSocketAddress address ) { synchronized( sender ){ sender[0] = address; } } public boolean verbose() { return( false ); } }, hash, "", new InetSocketAddress[0], 300*1000 ); if ( torrent_data == null ){ log( " download failed - timeout" ); return( null ); } log( "Subscription torrent downloaded" ); TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedByteArray( torrent_data ); // update size is just that of signed content, torrent itself is .vuze file // so take this into account if ( torrent.getSize() > update_size + 10*1024 ){ log( "Subscription download abandoned, torrent size is " + torrent.getSize() + ", underlying data size is " + update_size ); return( null ); } if ( torrent.getSize() > 4*1024*1024 ){ log( "Subscription download abandoned, torrent size is too large (" + torrent.getSize() + ")" ); return( null ); } synchronized( sender ){ return( new Object[]{ torrent, sender[0] }); } }catch( Throwable e ){ log( " download failed", e ); return( null ); } } protected void downloadSubscription( final TOTorrent torrent, final InetSocketAddress peer, byte[] subs_id, int version, String name, final downloadListener listener ) { try{ // testing purposes, see if local exists LightWeightSeed lws = LightWeightSeedManager.getSingleton().get( new HashWrapper( torrent.getHash())); if ( lws != null ){ log( "Light weight seed found" ); listener.complete( lws.getDataLocation()); }else{ String sid = ByteFormatter.encodeString( subs_id ); File dir = getSubsDir(); dir = new File( dir, "temp" ); if ( !dir.exists()){ if ( !dir.mkdirs()){ throw( new IOException( "Failed to create dir '" + dir + "'" )); } } final File torrent_file = new File( dir, sid + "_" + version + ".torrent" ); final File data_file = new File( dir, sid + "_" + version + ".vuze" ); PluginInterface pi = PluginInitializer.getDefaultInterface(); final DownloadManager dm = pi.getDownloadManager(); Download download = dm.getDownload( torrent.getHash()); if ( download == null ){ log( "Adding download for subscription '" + new String(torrent.getName()) + "'" ); boolean is_update = getSubscriptionFromSID( subs_id ) != null; PlatformTorrentUtils.setContentTitle(torrent, (is_update?"Update":"Download") + " for subscription '" + name + "'" ); // PlatformTorrentUtils.setContentThumbnail(torrent, thumbnail); TorrentUtils.setFlag( torrent, TorrentUtils.TORRENT_FLAG_LOW_NOISE, true ); Torrent t = new TorrentImpl( torrent ); t.setDefaultEncoding(); t.writeToFile( torrent_file ); download = dm.addDownload( t, torrent_file, data_file ); download.setFlag( Download.FLAG_DISABLE_AUTO_FILE_MOVE, true ); download.setBooleanAttribute( ta_subs_download, true ); Map rd = listener.getRecoveryData(); if ( rd != null ){ download.setMapAttribute( ta_subs_download_rd, rd ); } }else{ log( "Existing download found for subscription '" + new String(torrent.getName()) + "'" ); } final Download f_download = download; final TimerEventPeriodic[] event = { null }; event[0] = SimpleTimer.addPeriodicEvent( "SM:cancelTimer", 10*1000, new TimerEventPerformer() { private long start_time = SystemTime.getMonotonousTime(); public void perform( TimerEvent ev ) { boolean kill = false; try{ Download download = dm.getDownload( torrent.getHash()); if ( listener.isCancelled() || download == null ){ kill = true; }else{ int state = download.getState(); if ( state == Download.ST_ERROR ){ log( "Download entered error state, removing" ); kill = true; }else{ long now = SystemTime.getMonotonousTime(); long running_for = now - start_time; if ( running_for > 2*60*1000 ){ DownloadScrapeResult scrape = download.getLastScrapeResult(); if ( scrape == null || scrape.getSeedCount() <= 0 ){ log( "Download has no seeds, removing" ); kill = true; } }else if ( running_for > 4*60*1000 ){ if ( download.getStats().getDownloaded() == 0 ){ log( "Download has zero downloaded, removing" ); kill = true; } }else if ( running_for > 10*60*1000 ){ log( "Download hasn't completed in permitted time, removing" ); kill = true; } } } }catch( Throwable e ){ log( "Download failed", e ); kill = true; } if ( kill && event[0] != null ){ try{ event[0].cancel(); if ( !listener.isCancelled()){ listener.failed( new SubscriptionException( "Download abandoned" )); } }finally{ removeDownload( f_download, true ); torrent_file.delete(); } } } }); download.addCompletionListener( new DownloadCompletionListener() { public void onCompletion( Download d ) { listener.complete( d, torrent_file ); } }); if ( download.isComplete()){ listener.complete( download, torrent_file ); }else{ download.setForceStart( true ); if ( peer != null ){ download.addPeerListener( new DownloadPeerListener() { public void peerManagerAdded( Download download, PeerManager peer_manager ) { InetSocketAddress tcp = AddressUtils.adjustTCPAddress( peer, true ); InetSocketAddress udp = AddressUtils.adjustUDPAddress( peer, true ); log( " Injecting peer into download: " + tcp ); peer_manager.addPeer( tcp.getAddress().getHostAddress(), tcp.getPort(), udp.getPort(), true ); } public void peerManagerRemoved( Download download, PeerManager peer_manager ) { } }); } } } }catch( Throwable e ){ log( "Failed to add download", e ); listener.failed( e ); } } protected interface downloadListener { public void complete( File data_file ); public void complete( Download download, File torrent_file ); public void failed( Throwable error ); public Map getRecoveryData(); public boolean isCancelled(); } protected void updateSubscription( final SubscriptionImpl subs, final int new_version, TOTorrent torrent, InetSocketAddress peer ) { log( "Subscription " + subs.getString() + " - update torrent: " + new String( torrent.getName())); if ( !askIfCanUpgrade( subs, new_version )){ return; } downloadSubscription( torrent, peer, subs.getShortID(), new_version, subs.getName(), new downloadListener() { public void complete( File data_file ) { updateSubscription( subs, data_file ); } public void complete( Download download, File torrent_file ) { updateSubscription( subs, download, torrent_file, new File( download.getSavePath())); } public void failed( Throwable error ) { log( "Failed to download subscription", error ); } public Map getRecoveryData() { Map rd = new HashMap(); rd.put( "sid", subs.getShortID()); rd.put( "ver", new Long( new_version )); return( rd ); } public boolean isCancelled() { return( false ); } }); } protected boolean askIfCanUpgrade( SubscriptionImpl subs, int new_version ) { subs.setHighestUserPromptedVersion( new_version ); UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 ); String details = MessageText.getString( "subscript.add.upgradeto.desc", new String[]{ String.valueOf(new_version), subs.getName()}); long res = ui_manager.showMessageBox( "subscript.add.upgrade.title", "!" + details + "!", UIManagerEvent.MT_YES | UIManagerEvent.MT_NO ); if ( res != UIManagerEvent.MT_YES ){ log( " User declined upgrade" ); return( false ); } return( true ); } protected boolean recoverSubscriptionUpdate( Download download, final Map rd ) { byte[] sid = (byte[])rd.get( "sid" ); int version = ((Long)rd.get( "ver" )).intValue(); final SubscriptionImpl subs = getSubscriptionFromSID( sid ); if ( subs == null ){ log( "Can't recover '" + download.getName() + "' - subscription " + ByteFormatter.encodeString( sid ) + " not found" ); return( false ); } downloadSubscription( ((TorrentImpl)download.getTorrent()).getTorrent(), null, subs.getShortID(), version, subs.getName(), new downloadListener() { public void complete( File data_file ) { updateSubscription( subs, data_file ); } public void complete( Download download, File torrent_file ) { updateSubscription( subs, download, torrent_file, new File( download.getSavePath())); } public void failed( Throwable error ) { log( "Failed to download subscription", error ); } public Map getRecoveryData() { return( rd ); } public boolean isCancelled() { return( false ); } }); return( true ); } protected void updateSubscription( SubscriptionImpl subs, Download download, File torrent_file, File data_file ) { try{ removeDownload( download, false ); try{ updateSubscription( subs, data_file ); }finally{ if ( !data_file.delete()){ log( "Failed to delete update file '" + data_file + "'" ); } if ( !torrent_file.delete()){ log( "Failed to delete update torrent '" + torrent_file + "'" ); } } }catch( Throwable e ){ log( "Failed to remove update download", e ); } } protected void removeDownload( Download download, boolean remove_data ) { try{ download.stop(); }catch( Throwable e ){ } try{ download.remove( true, remove_data ); log( "Removed download '" + download.getName() + "'" ); }catch( Throwable e ){ log( "Failed to remove download '" + download.getName() + "'", e ); } } protected void updateSubscription( SubscriptionImpl subs, File data_location ) { log( "Updating subscription '" + subs.getString() + " using '" + data_location + "'" ); VuzeFileHandler vfh = VuzeFileHandler.getSingleton(); VuzeFile vf = vfh.loadVuzeFile( data_location.getAbsolutePath()); vfh.handleFiles( new VuzeFile[]{ vf }, VuzeFileComponent.COMP_TYPE_SUBSCRIPTION ); } protected MagnetPlugin getMagnetPlugin() { PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass( MagnetPlugin.class ); if ( pi == null ){ return( null ); } return((MagnetPlugin)pi.getPlugin()); } protected Engine getEngine( SubscriptionImpl subs, Map json_map, boolean local_only ) throws SubscriptionException { long id = ((Long)json_map.get( "engine_id" )).longValue(); Engine engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().getEngine( id ); if ( engine != null ){ return( engine ); } if ( !local_only ){ try{ if ( id >= 0 && id < Integer.MAX_VALUE ){ log( "Engine " + id + " not present, loading" ); // vuze template but user hasn't yet loaded it try{ engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().addEngine( id ); return( engine ); }catch( Throwable e ){ throw( new SubscriptionException( "Failed to load engine '" + id + "'", e )); } } }catch( Throwable e ){ log( "Failed to load search template", e ); } } engine = subs.extractEngine( json_map, id ); if ( engine != null ){ return( engine ); } throw( new SubscriptionException( "Failed to extract engine id " + id )); } protected SubscriptionResultImpl[] loadResults( SubscriptionImpl subs ) { List results = new ArrayList(); try{ File f = getResultsFile( subs ); Map map = FileUtil.readResilientFile( f ); List list = (List)map.get( "results" ); if ( list != null ){ SubscriptionHistoryImpl history = (SubscriptionHistoryImpl)subs.getHistory(); for (int i=0;i 0 && size < min ){ return( false ); } if ( max > 0 && size > max ){ return( false ); } return( true ); }else{ return( false ); } } protected void saveResults( SubscriptionImpl subs, SubscriptionResultImpl[] results ) { try{ File f = getResultsFile( subs ); Map map = new HashMap(); List list = new ArrayList( results.length ); map.put( "results", list ); for (int i=0;i>24), (byte)(version>>16),(byte)(version>>8),(byte)version } ); } protected static int bytesToInt( byte[] bytes ) { return( (bytes[0]<<24)&0xff000000 | (bytes[1] << 16)&0x00ff0000 | (bytes[2] << 8)&0x0000ff00 | bytes[3]&0x000000ff ); } private SubscriptionManagerImpl manager; private byte[] public_key; private byte[] private_key; private String name; private String name_ex; private int version; private int az_version; private boolean is_public; private Map singleton_details; private byte[] hash; private byte[] sig; private int sig_data_size; private int add_type; private long add_time; private boolean is_subscribed; private int highest_prompted_version; private byte[] short_id; private List associations = new ArrayList(); private int fixed_random; private long popularity = -1; private long last_auto_upgrade_check = -1; private boolean published; private boolean server_published; private boolean server_publication_outstanding; private boolean singleton_sp_attempted; private LightWeightSeed lws; private int lws_skip_check; private boolean destroyed; private Map history_map; private Map schedule_map; private Map user_data = new LightHashMap(); private final SubscriptionHistoryImpl history; private String referer; private CopyOnWriteList listeners = new CopyOnWriteList(); private Map verify_cache_details; private boolean verify_cache_result; private String creator_ref; private String category; protected static String getSkeletonJSON( Engine engine, int check_interval_mins ) { JSONObject map = new JSONObject(); map.put( "engine_id", new Long( engine.getId())); map.put( "search_term", "" ); map.put( "filters", new HashMap()); map.put( "options", new HashMap()); Map schedule = new HashMap(); schedule.put( "interval", new Long( check_interval_mins )); List days = new ArrayList(); for (int i=1;i<=7;i++){ days.add( String.valueOf(i)); } schedule.put( "days", days ); map.put( "schedule", schedule ); embedEngines( map, engine ); return( JSONUtils.encodeToJSON( map )); } // new subs constructor protected SubscriptionImpl( SubscriptionManagerImpl _manager, String _name, boolean _public, Map _singleton_details, String _json_content, int _add_type ) throws SubscriptionException { manager = _manager; history_map = new HashMap(); history = new SubscriptionHistoryImpl( manager, this ); name = _name; is_public = _public; singleton_details = _singleton_details; version = 1; az_version = AZ_VERSION; add_type = _add_type; add_time = SystemTime.getCurrentTime(); is_subscribed = true; try{ KeyPair kp = CryptoECCUtils.createKeys(); public_key = CryptoECCUtils.keyToRawdata( kp.getPublic()); private_key = CryptoECCUtils.keyToRawdata( kp.getPrivate()); fixed_random = new Random().nextInt(); init(); String json_content = embedEngines( _json_content ); SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, name, is_public, json_content, public_key, version, az_version, singleton_details ); syncToBody( body ); }catch( Throwable e ){ throw( new SubscriptionException( "Failed to create subscription", e )); } } // cache detail constructor protected SubscriptionImpl( SubscriptionManagerImpl _manager, Map map ) throws IOException { manager = _manager; fromMap( map ); history = new SubscriptionHistoryImpl( manager, this ); init(); } // import constructor protected SubscriptionImpl( SubscriptionManagerImpl _manager, SubscriptionBodyImpl _body, int _add_type, boolean _is_subscribed ) throws SubscriptionException { manager = _manager; history_map = new HashMap(); history = new SubscriptionHistoryImpl( manager, this ); syncFromBody( _body ); add_type = _add_type; add_time = SystemTime.getCurrentTime(); is_subscribed = _is_subscribed; fixed_random = new Random().nextInt(); init(); syncToBody( _body ); } protected void syncFromBody( SubscriptionBodyImpl body ) throws SubscriptionException { public_key = body.getPublicKey(); version = body.getVersion(); az_version = body.getAZVersion(); name = body.getName(); is_public = body.isPublic(); singleton_details = body.getSingletonDetails(); if ( az_version > AZ_VERSION ){ throw( new SubscriptionException( MessageText.getString( "subscription.version.bad", new String[]{ name }))); } } protected void syncToBody( SubscriptionBodyImpl body ) throws SubscriptionException { // this picks up latest values of version, name + is_public from here body.writeVuzeFile( this ); hash = body.getHash(); sig = body.getSig(); sig_data_size = body.getSigDataSize(); } protected Map toMap() throws IOException { synchronized( this ){ Map map = new HashMap(); map.put( "name", name.getBytes( "UTF-8" )); map.put( "public_key", public_key ); map.put( "version", new Long( version )); map.put( "az_version", new Long( az_version )); map.put( "is_public", new Long( is_public?1:0 )); if ( singleton_details != null ){ map.put( "sin_details", singleton_details ); map.put( "spa", new Long( singleton_sp_attempted?1:0 )); } // body data map.put( "hash", hash ); map.put( "sig", sig ); map.put( "sig_data_size", new Long( sig_data_size )); // local data if ( private_key != null ){ map.put( "private_key", private_key ); } map.put( "add_type", new Long( add_type )); map.put( "add_time", new Long( add_time )); map.put( "subscribed", new Long( is_subscribed?1:0 )); map.put( "pop", new Long( popularity )); map.put( "rand", new Long( fixed_random )); map.put( "hupv", new Long( highest_prompted_version )); map.put( "sp", new Long( server_published?1:0 )); map.put( "spo", new Long( server_publication_outstanding?1:0 )); if ( associations.size() > 0 ){ List l_assoc = new ArrayList(); map.put( "assoc", l_assoc ); for (int i=0;i 0 ){ name_ex += ", query=" + search_term; } if ( filters != null && filters.size() > 0 ){ name_ex += ", filters=" + new SubscriptionResultFilter(filters).getString(); } }catch( Throwable e ){ name_ex = name + ": " + Debug.getNestedExceptionMessage(e); } } return( name_ex ); } public boolean isPublic() { return( is_public ); } public void setPublic( boolean _is_public ) throws SubscriptionException { if ( is_public != _is_public ){ boolean ok = false; boolean old_public = is_public; int old_version = version; try{ is_public = _is_public; version++; SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this ); syncToBody( body ); versionUpdated( body, false ); ok = true; }finally{ if ( !ok ){ version = old_version; is_public = old_public; } } fireChanged(); } } protected boolean getServerPublicationOutstanding() { return( server_publication_outstanding ); } protected void setServerPublicationOutstanding() { if ( !server_publication_outstanding ){ server_publication_outstanding = true; fireChanged(); } } protected void setServerPublished() { if ( server_publication_outstanding || !server_published ){ server_published = true; server_publication_outstanding = false; fireChanged(); } } protected boolean getServerPublished() { return( server_published ); } public String getJSON() throws SubscriptionException { try{ SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this ); return( body.getJSON()); }catch( Throwable e ){ history.setFatalError( Debug.getNestedExceptionMessage(e)); if ( e instanceof SubscriptionException ){ throw((SubscriptionException)e ); } throw( new SubscriptionException( "Failed to read subscription", e )); } } public boolean setJSON( String _json ) throws SubscriptionException { String json = embedEngines( _json ); SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this ); String old_json = body.getJSON(); if ( !json.equals( old_json )){ boolean ok = false; int old_version = version; try{ version++; body.setJSON( json ); syncToBody( body ); versionUpdated( body, true ); referer = null; ok = true; }finally{ if ( !ok ){ version = old_version; } } fireChanged(); return( true ); } return( false ); } protected String embedEngines( String json_in ) { // see if we need to embed private search templates Map map = JSONUtils.decodeJSON( json_in ); long engine_id = ((Long)map.get( "engine_id" )).longValue(); String json_out = json_in; if ( engine_id >= Integer.MAX_VALUE || engine_id < 0 ){ Engine engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().getEngine( engine_id ); if ( engine == null ){ log( "Private search template with id '" + engine_id + "' not found!!!!" ); }else{ try{ embedEngines( map, engine ); json_out = JSONUtils.encodeToJSON( map ); log( "Embedded private search template '" + engine.getName() + "'" ); }catch( Throwable e ){ log( "Failed to embed private search template", e ); } } } return( json_out ); } protected static void embedEngines( Map map, Engine engine ) { Map engines = new HashMap(); map.put( "engines", engines ); Map engine_map = new HashMap(); try{ String engine_str = new String( Base64.encode( BEncoder.encode( engine.exportToBencodedMap())), "UTF-8" ); engine_map.put( "content", engine_str ); engines.put( String.valueOf( engine.getId()), engine_map ); }catch( Throwable e ){ Debug.out( e ); } } protected Engine extractEngine( Map json_map, long id ) { Map engines = (Map)json_map.get( "engines" ); if ( engines != null ){ Map engine_map = (Map)engines.get( String.valueOf( id )); if ( engine_map != null ){ String engine_str = (String)engine_map.get( "content" ); try{ Map map = BDecoder.decode( Base64.decode( engine_str.getBytes( "UTF-8" ))); return( MetaSearchManagerFactory.getSingleton().getMetaSearch().importFromBEncodedMap(map)); }catch( Throwable e ){ log( "failed to import engine", e ); } } } return( null ); } public Engine getEngine() throws SubscriptionException { return( getEngine( true )); } protected Engine getEngine( boolean local_only ) throws SubscriptionException { Map map = JSONUtils.decodeJSON( getJSON()); return( manager.getEngine( this, map, local_only )); } protected void engineUpdated( Engine engine ) { try{ String json = getJSON(); Map map = JSONUtils.decodeJSON( json ); long id = ((Long)map.get( "engine_id" )).longValue(); if ( id == engine.getId()){ if ( setJSON( json )){ log( "Engine has been updated, saved" ); } } }catch( Throwable e ){ log( "Engine update failed", e ); } } public boolean setDetails( String _name, boolean _is_public, String _json ) throws SubscriptionException { _json = embedEngines( _json ); SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this ); String old_json = body.getJSON(); boolean json_changed = !_json.equals( old_json ); if ( !_name.equals( name ) || _is_public != is_public || json_changed ){ boolean ok = false; String old_name = name; boolean old_public = is_public; int old_version = version; try{ is_public = _is_public; name = _name; body.setJSON( _json ); version++; syncToBody( body ); versionUpdated( body, json_changed ); ok = true; }finally{ if ( !ok ){ version = old_version; is_public = old_public; name = old_name; } } fireChanged(); return( true ); } return( false ); } protected void versionUpdated( SubscriptionBodyImpl body, boolean json_changed ) { if ( json_changed ){ try{ Map map = JSONUtils.decodeJSON( body.getJSON()); schedule_map = (Map)map.get( "schedule" ); }catch( Throwable e ){ } } name_ex = null; if ( is_public ){ manager.updatePublicSubscription( this ); setPublished( false ); synchronized( this ){ for (int i=0;i 0 ){ highest_prompted_version = 0; fireChanged(); manager.checkUpgrade(this); } } public boolean isMine() { if ( private_key == null ){ return( false ); } if ( isSingleton() && add_type != ADD_TYPE_CREATE ){ return( false ); } return( true ); } public boolean isUpdateable() { return( private_key != null ); } public boolean isSubscribed() { return( is_subscribed ); } public void setSubscribed( boolean s ) { if ( is_subscribed != s ){ is_subscribed = s; if ( is_subscribed ){ manager.setSelected( this ); } fireChanged(); } } public boolean isAutoDownloadSupported() { return( history.isAutoDownloadSupported()); } public void getPopularity( final SubscriptionPopularityListener listener ) throws SubscriptionException { new AEThread2( "subs:popwait", true ) { public void run() { try{ manager.getPopularity( SubscriptionImpl.this, new SubscriptionPopularityListener() { public void gotPopularity( long pop ) { if ( pop != popularity ){ popularity = pop; fireChanged(); } listener.gotPopularity( popularity ); } public void failed( SubscriptionException e ) { if ( popularity == -1 ){ listener.failed( new SubscriptionException( "Failed to read popularity", e )); }else{ listener.gotPopularity( popularity ); } } }); }catch( Throwable e ){ if ( popularity == -1 ){ listener.failed( new SubscriptionException( "Failed to read popularity", e )); }else{ listener.gotPopularity( popularity ); } } } }.start(); } public long getCachedPopularity() { return( popularity ); } protected void setCachedPopularity( long pop ) { if ( pop != popularity ){ popularity = pop; fireChanged(); } } public String getReferer() { if ( referer == null ){ try{ Map map = JSONUtils.decodeJSON( getJSON()); Engine engine = manager.getEngine( this, map, false ); if ( engine != null ){ referer = engine.getReferer(); } }catch( Throwable e ){ log( "Failed to get referer", e ); } if ( referer == null ){ referer = ""; } } return( referer ); } protected void checkPublish() { synchronized( this ){ if ( destroyed ){ return; } // singleton's not available for upgrade if ( isSingleton()){ return; } // nothing to do for unsubscribed ones if ( !isSubscribed()){ return; } if ( popularity > 100 ){ // one off test on whether to track so we have around 100 active if ( lws_skip_check == 2 ){ return; }else if ( lws_skip_check == 0 ){ if ( new Random().nextInt((int)(( popularity + 99 ) / 100 )) == 0 ){ lws_skip_check = 1; }else{ lws_skip_check = 2; return; } } } if ( hash != null ){ boolean create = false; if ( lws == null ){ create = true; }else{ if ( !Arrays.equals( lws.getHash().getBytes(), hash )){ lws.remove(); create = true; } } if ( create ){ try{ File original_data_location = manager.getVuzeFile( this ); if ( original_data_location.exists()){ // make a version based filename to avoid issues regarding multiple // versions final File versioned_data_location = new File( original_data_location.getParent(), original_data_location.getName() + "." + getVersion()); if ( !versioned_data_location.exists()){ if ( !FileUtil.copyFile( original_data_location, versioned_data_location )){ throw( new Exception( "Failed to copy file to '" + versioned_data_location + "'" )); } } lws = LightWeightSeedManager.getSingleton().add( getName(), new HashWrapper( hash ), TorrentUtils.getDecentralisedEmptyURL(), versioned_data_location, new LightWeightSeedAdapter() { public TOTorrent getTorrent( byte[] hash, URL announce_url, File data_location) throws Exception { log( " - generating torrent: " + Debug.getCompressedStackTrace()); TOTorrentCreator creator = TOTorrentFactory.createFromFileOrDirWithFixedPieceLength( data_location, announce_url, 256*1024 ); TOTorrent t = creator.create(); t.setHashOverride( hash ); return( t ); } }); } }catch( Throwable e ){ log( "Failed to create light-weight-seed", e ); } } } } } protected synchronized boolean canAutoUpgradeCheck() { if ( isSingleton()){ return( false ); } long now = SystemTime.getMonotonousTime(); if ( last_auto_upgrade_check == -1 || now - last_auto_upgrade_check > 4*60*60*1000 ){ last_auto_upgrade_check = now; return( true ); } return( false ); } public void addAssociation( byte[] hash ) { synchronized( this ){ for (int i=0;i MAX_ASSOCIATIONS ){ associations.remove( new Random().nextInt( MAX_ASSOCIATIONS - MIN_RECENT_ASSOC_TO_RETAIN )); } } fireChanged(); manager.associationAdded( this, hash); } public boolean hasAssociation( byte[] hash ) { synchronized( this ){ for (int i=0;i=Math.max( 0, num_assoc-MIN_RECENT_ASSOC_TO_RETAIN);i--){ association assoc = (association)associations.get(i); if ( !assoc.getPublished()){ assoc.setPublished( true ); return( assoc ); } } // remaining randomised int rem = associations.size() - MIN_RECENT_ASSOC_TO_RETAIN; if ( rem > 0 ){ List l = new ArrayList( associations.subList( 0, rem )); Collections.shuffle( l ); for (int i=0;i 0 && (new_unread + new_read ) > max_results ){ for (int i=0;i 0 ){ results = new SubscriptionResultImpl[0]; manager.saveResults( subs, results ); } updateReadUnread( results ); } last_error = null; last_new_result = 0; last_scan = 0; saveConfig(); } protected void checkMaxResults( int max_results ) { if ( max_results <= 0 ){ return; } boolean changed = false; synchronized( this ){ if ((num_unread + num_read ) > max_results ){ SubscriptionResultImpl[] results = manager.loadResults( subs ); for (int i=0;i0):l_auto_dl_s.longValue()==1; Long l_dl_with_ref = (Long)map.get( "dl_with_ref" ); dl_with_ref = l_dl_with_ref==null?true:l_dl_with_ref.longValue()==1; } protected void saveConfig() { Map map = new HashMap(); map.put( "enabled", new Long( enabled?1:0 )); map.put( "auto_dl", new Long( auto_dl?1:0 )); map.put( "auto_dl_supported", new Long( auto_dl_supported?1:0)); map.put( "last_scan", new Long( last_scan )); map.put( "last_new", new Long( last_new_result )); map.put( "num_unread", new Long( num_unread )); map.put( "num_read", new Long( num_read )); map.put( "dl_with_ref", new Long( dl_with_ref?1:0 )); subs.updateHistoryConfig( map ); } protected void log( String str ) { subs.log( "History: " + str ); } protected void log( String str, Throwable e ) { subs.log( "History: " + str, e ); } } azureus-4.3.0.6/com/aelitis/azureus/core/subs/impl/SubscriptionDownloader.java0000644000175000017500000001011411111443600026743 0ustar adrianadrian/* * Created on Aug 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs.impl; import java.util.*; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.metasearch.Engine; import com.aelitis.azureus.core.metasearch.Result; import com.aelitis.azureus.core.metasearch.SearchLoginException; import com.aelitis.azureus.core.metasearch.SearchParameter; import com.aelitis.azureus.core.subs.*; import com.aelitis.azureus.util.JSONUtils; public class SubscriptionDownloader { private SubscriptionManagerImpl manager; private SubscriptionImpl subs; protected SubscriptionDownloader( SubscriptionManagerImpl _manager, SubscriptionImpl _subs ) throws SubscriptionException { manager = _manager; subs = _subs; } protected void download() throws SubscriptionException { log( "Downloading" ); Map map = JSONUtils.decodeJSON( subs.getJSON()); Long engine_id = (Long)map.get( "engine_id" ); String search_term = (String)map.get( "search_term" ); Map filters = (Map)map.get( "filters" ); Engine engine = manager.getEngine( subs, map, false ); if ( engine == null ){ throw( new SubscriptionException( "Download failed, search engine " + engine_id + " not found" )); } List sps = new ArrayList(); if ( search_term != null ){ sps.add( new SearchParameter( "s", search_term )); log( " Using search term '" + search_term + "' for engine " + engine.getString()); } /* if ( mature != null ){ sps.add( new SearchParameter( "m", mature.toString())); } */ SearchParameter[] parameters = (SearchParameter[])sps.toArray(new SearchParameter[ sps.size()] ); SubscriptionHistoryImpl history = (SubscriptionHistoryImpl)subs.getHistory(); try{ Map context = new HashMap(); context.put( Engine.SC_SOURCE, "subscription" ); Result[] results = engine.search( parameters, context, -1, -1, null, null ); log( " Got " + results.length + " results" ); SubscriptionResultFilter result_filter = new SubscriptionResultFilter(filters ); results = result_filter.filter( results ); log( " Post-filter: " + results.length + " results" ); SubscriptionResultImpl[] s_results = new SubscriptionResultImpl[results.length]; for( int i=0;i 0 ){ result.add( new SubscriptionDownloadDetails( dm, subs )); } }catch( Throwable e ){ } } } return((SubscriptionDownloadDetails[])result.toArray( new SubscriptionDownloadDetails[result.size()])); } public static class SubscriptionDownloadDetails { private DownloadManager download; private Subscription[] subscriptions; protected SubscriptionDownloadDetails( DownloadManager dm, Subscription[] subs ) { download = dm; subscriptions = subs; } public DownloadManager getDownload() { return( download ); } public Subscription[] getSubscriptions() { return( subscriptions ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/subs/SubscriptionHistory.java0000644000175000017500000000371411140157754025373 0ustar adrianadrian/* * Created on Aug 6, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs; public interface SubscriptionHistory { public static final int DEFAULT_CHECK_INTERVAL_MINS = 120; public boolean isEnabled(); public void setEnabled( boolean enabled ); public boolean isAutoDownload(); public void setAutoDownload( boolean auto_dl ); public void setDetails( boolean enabled, boolean auto_dl ); public void deleteResults( String[] result_ids ); public void deleteAllResults(); public void markAllResultsRead(); public void markAllResultsUnread(); public void markResults( String[] result_ids, boolean[] read ); public void reset(); public long getLastScanTime(); public long getLastNewResultTime(); public long getNextScanTime(); public int getNumUnread(); public int getNumRead(); public int getCheckFrequencyMins(); public String getLastError(); public boolean isAuthFail(); public int getConsecFails(); public SubscriptionResult[] getResults( boolean include_deleted ); public SubscriptionResult getResult( String result_id ); public boolean getDownloadWithReferer(); public void setDownloadWithReferer( boolean b ); } azureus-4.3.0.6/com/aelitis/azureus/core/subs/SubscriptionException.java0000644000175000017500000000203411037265410025654 0ustar adrianadrian/* * Created on Jul 11, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs; public class SubscriptionException extends Exception { public SubscriptionException( String str ) { super( str ); } public SubscriptionException( String str, Throwable e ) { super( str, e ); } } azureus-4.3.0.6/com/aelitis/azureus/core/subs/SubscriptionManagerListener.java0000644000175000017500000000231111074104550026772 0ustar adrianadrian/* * Created on Jul 29, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs; public interface SubscriptionManagerListener { public void subscriptionAdded( Subscription subscription ); public void subscriptionChanged( Subscription subscription ); public void subscriptionSelected( Subscription subscription ); public void subscriptionRemoved( Subscription subscription ); public void associationsChanged( byte[] association_hash ); } azureus-4.3.0.6/com/aelitis/azureus/core/subs/SubscriptionManager.java0000644000175000017500000000557011264473526025313 0ustar adrianadrian/* * Created on Jul 11, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.subs; import java.net.URL; import java.util.Map; import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; public interface SubscriptionManager extends UtilitiesImpl.PluginSubscriptionManager { public Subscription create( String name, boolean is_public, String json ) throws SubscriptionException; public Subscription createRSS( String name, URL url, int check_interval_mins, Map user_data ) throws SubscriptionException; // creates a subscription that will always have the same identity for the given parameters // and can't be updated public Subscription createSingletonRSS( String name, URL url, int check_interval_mins ) throws SubscriptionException; public Subscription[] getSubscriptions(); public Subscription[] getSubscriptions( boolean subscribed_only ); public Subscription getSubscriptionByID( String id ); /** * Full lookup * @param hash * @param listener * @return * @throws SubscriptionException */ public SubscriptionAssociationLookup lookupAssociations( byte[] hash, SubscriptionLookupListener listener ) throws SubscriptionException; /** * Cached view of hash's subs * @param hash * @return */ public Subscription[] getKnownSubscriptions( byte[] hash ); public Subscription[] getLinkedSubscriptions( byte[] hash ); public SubscriptionScheduler getScheduler(); public int getMaxNonDeletedResults(); public void setMaxNonDeletedResults( int max ); public boolean getAutoStartDownloads(); public void setAutoStartDownloads( boolean auto_start ); public int getAutoStartMinMB(); public void setAutoStartMinMB( int mb ); public int getAutoStartMaxMB(); public void setAutoStartMaxMB( int mb ); public boolean isRSSPublishEnabled(); public void setRSSPublishEnabled( boolean enabled ); public String getRSSLink(); public void addListener( SubscriptionManagerListener listener ); public void removeListener( SubscriptionManagerListener listener ); } azureus-4.3.0.6/com/aelitis/azureus/core/lws/0000755000175000017500000000000011310377626020307 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/lws/LWSDiskManagerState.java0000644000175000017500000001527611306332000024717 0ustar adrianadrian/* * Created on 11-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.lws; import java.io.File; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.category.Category; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.download.DownloadManagerStateAttributeListener; import org.gudy.azureus2.core3.download.DownloadManagerStateListener; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.IndentWriter; import com.aelitis.azureus.core.util.CaseSensitiveFileMap; public class LWSDiskManagerState implements DownloadManagerState { private long flags = FLAG_LOW_NOISE | FLAG_DISABLE_AUTO_FILE_MOVE; protected LWSDiskManagerState() { } public TOTorrent getTorrent() { return( null ); } public File getStateFile( String name ) { return( null ); } public File getStateFile() { return null; } public DownloadManager getDownloadManager() { return( null ); } public void clearResumeData() { } public Map getResumeData() { return( new HashMap()); } public void setResumeData( Map data ) { } public boolean isResumeDataComplete() { return( true ); } public void clearTrackerResponseCache() { } public Map getTrackerResponseCache() { return( new HashMap()); } public void setTrackerResponseCache( Map value ) { } public void setFlag( long flag, boolean set ) { flags |= flag; } public boolean getFlag( long flag ) { return(( flags & flag ) != 0 ); } public long getFlags() { return( flags ); } public boolean isOurContent() { return false; } public int getIntParameter( String name ) { return( 0 ); } public void setIntParameter( String name, int value ) { } public long getLongParameter( String name ) { return( 0 ); } public void setParameterDefault( String name) { } public void setLongParameter( String name, long value ) { } public boolean getBooleanParameter( String name ) { return( false ); } public void setBooleanParameter( String name, boolean value ) { } public void setAttribute( String name, String value ) { } public String getAttribute( String name ) { return( null ); } public void setIntAttribute(String name, int value){} public int getIntAttribute(String name){ return( 0 ); } public void setLongAttribute(String name, long value){} public long getLongAttribute(String name){ return( 0 ); } public void setBooleanAttribute(String name, boolean value){} public boolean getBooleanAttribute(String name){ return( false ); } public boolean hasAttribute(String name){ return( false );} public String getTrackerClientExtensions() { return( null ); } public void setTrackerClientExtensions( String value ) { } public void setListAttribute( String name, String[] values ) { } public String[] getListAttribute( String name ) { return( null ); } public String getListAttribute( String name, int idx) { return null; } public void setMapAttribute( String name, Map value ) { } public Map getMapAttribute( String name ) { return( null ); } public Category getCategory() { return( null ); } public void setCategory( Category cat ) { } public String getPrimaryFile() { return null; } public void setPrimaryFile( String fileFullPath) { } public String[] getNetworks() { return( new String[0] ); } public boolean isNetworkEnabled( String network) { return false; } public void setNetworks( String[] networks ) { } public void setNetworkEnabled( String network, boolean enabled) { } public String[] getPeerSources() { return( new String[0] ); } public boolean isPeerSourcePermitted( String peerSource ) { return( false ); } public void setPeerSourcePermitted( String peerSource, boolean permitted ) { } public boolean isPeerSourceEnabled( String peerSource) { return false; } public void setPeerSources( String[] networks ) { } public void setPeerSourceEnabled( String source, boolean enabled ) { } public void setFileLink( File link_source, File link_destination ) { } public void discardFluff() { } public void clearFileLinks() { } public File getFileLink( File link_source ) { return( null ); } public CaseSensitiveFileMap getFileLinks() { return( new CaseSensitiveFileMap()); } public String getUserComment() { return( "" ); } public void setUserComment( String name ) { } public String getRelativeSavePath() { return null; } public void setRelativeSavePath( String path ) { } public void setActive( boolean a ) { } public void save() { } public void delete() { } public void suppressStateSave( boolean suppress) { } public void addListener( DownloadManagerStateListener l ) { } public void removeListener( DownloadManagerStateListener l ) { } public void addListener( DownloadManagerStateAttributeListener l, String attribute, int event_type) { } public void removeListener( DownloadManagerStateAttributeListener l, String attribute, int event_type) { } public void generateEvidence( IndentWriter writer) { } public String getDisplayName() { return null; } public void setDisplayName( String name) { } public boolean parameterExists( String name) { return false; } public void supressStateSave( boolean supress ) { } } azureus-4.3.0.6/com/aelitis/azureus/core/lws/LightWeightSeedAdapter.java0000644000175000017500000000207611037761642025501 0ustar adrianadrian/* * Created on Jul 16, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.lws; import java.io.File; import java.net.URL; import org.gudy.azureus2.core3.torrent.TOTorrent; public interface LightWeightSeedAdapter { public TOTorrent getTorrent( byte[] hash, URL announce_url, File data_location ) throws Exception; } azureus-4.3.0.6/com/aelitis/azureus/core/lws/LWSDownload.java0000644000175000017500000003231611263244650023311 0ustar adrianadrian/* * Created on Jul 16, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.lws; import java.io.File; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; import org.gudy.azureus2.plugins.download.Download; import org.gudy.azureus2.plugins.download.DownloadActivationEvent; import org.gudy.azureus2.plugins.download.DownloadActivationListener; import org.gudy.azureus2.plugins.download.DownloadAnnounceResult; import org.gudy.azureus2.plugins.download.DownloadAttributeListener; import org.gudy.azureus2.plugins.download.DownloadCompletionListener; import org.gudy.azureus2.plugins.download.DownloadException; import org.gudy.azureus2.plugins.download.DownloadListener; import org.gudy.azureus2.plugins.download.DownloadPeerListener; import org.gudy.azureus2.plugins.download.DownloadPropertyListener; import org.gudy.azureus2.plugins.download.DownloadRemovalVetoException; import org.gudy.azureus2.plugins.download.DownloadScrapeResult; import org.gudy.azureus2.plugins.download.DownloadStats; import org.gudy.azureus2.plugins.download.DownloadTrackerListener; import org.gudy.azureus2.plugins.download.DownloadWillBeRemovedListener; import org.gudy.azureus2.plugins.download.savelocation.SaveLocationChange; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.torrent.TorrentAttribute; import org.gudy.azureus2.plugins.torrent.TorrentManager; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.download.DownloadAnnounceResultImpl; public class LWSDownload implements Download { private LightWeightSeed lws; private TRTrackerAnnouncer announcer; private DownloadAnnounceResultImpl announce_result; private Map user_data = new HashMap(); private Map torrent_attributes = new HashMap(); private DownloadScrapeResult scrape_result = new DownloadScrapeResult() { public Download getDownload() { return( LWSDownload.this ); } public int getResponseType() { return( announce_result.getResponseType() == DownloadAnnounceResult.RT_SUCCESS?RT_SUCCESS:RT_ERROR ); } public int getSeedCount() { return( announce_result.getSeedCount()); } public int getNonSeedCount() { int seeds = getSeedCount(); int reported = announce_result.getReportedPeerCount(); int min_peers = reported - seeds; int peers = announce_result.getNonSeedCount(); if ( peers < min_peers ){ peers = min_peers; } return( peers ); } public long getScrapeStartTime() { return( 0 ); } public void setNextScrapeStartTime( long nextScrapeStartTime ) { } public long getNextScrapeStartTime() { return( 0 ); } public String getStatus() { if ( getResponseType() == RT_SUCCESS ){ return( "OK" ); }else{ return( announce_result.getError()); } } public URL getURL() { return( announce_result.getURL()); } }; protected LWSDownload( LightWeightSeed _lws, TRTrackerAnnouncer _announcer ) { lws = _lws; announcer = _announcer; announce_result = new DownloadAnnounceResultImpl( this, announcer.getLastResponse()); } public int getState() { return( Download.ST_SEEDING ); } public int getSubState() { return( Download.ST_SEEDING ); } public String getErrorStateDetails() { return( "" ); } public void setFlag( long flag, boolean value ) { notSupported(); } public boolean getFlag( long flag ) { return( false ); } public long getFlags() { return 0; } public int getIndex() { return( 0 ); } public File[] calculateDefaultPaths( boolean for_moving) { return new File[2]; } public SaveLocationChange calculateDefaultDownloadLocation() { return null; } public boolean isInDefaultSaveDir() { return false; } public Torrent getTorrent() { return( lws.getTorrent()); } public void initialize() throws DownloadException { } public void start() throws DownloadException { } public void startDownload( boolean force) { } public void stopDownload() { } public void stop() throws DownloadException { } public void stopAndQueue() throws DownloadException { } public void restart() throws DownloadException { } public void pause() { } public void resume() { } public void recheckData() throws DownloadException { } public boolean isStartStopLocked() { return( false ); } public boolean isForceStart() { return( true ); } public void setForceStart( boolean forceStart ) { } public int getPriority() { return( 0 ); } public void setPriority( int priority ) { } public boolean isPriorityLocked() { return( false ); } public boolean isPaused() { return( false ); } public String getName() { return( lws.getName()); } public String getTorrentFileName() { return( getName()); } public String getAttribute( TorrentAttribute attribute ) { synchronized( torrent_attributes ){ return((String)torrent_attributes.get( attribute )); } } public void setAttribute( TorrentAttribute attribute, String value ) { synchronized( torrent_attributes ){ torrent_attributes.put( attribute, value ); } } public String[] getListAttribute( TorrentAttribute attribute ) { TorrentManager tm = PluginInitializer.getDefaultInterface().getTorrentManager(); if ( attribute == tm.getAttribute( TorrentAttribute.TA_NETWORKS )){ return( new String[]{ "Public" }); }else if ( attribute == tm.getAttribute( TorrentAttribute.TA_PEER_SOURCES )){ return( new String[]{ "DHT" }); } return( null ); } public void setListAttribute( TorrentAttribute attribute, String[] value) { notSupported(); } public void setMapAttribute( TorrentAttribute attribute, Map value ) { notSupported(); } public Map getMapAttribute( TorrentAttribute attribute ) { return( null ); } public void setIntAttribute(TorrentAttribute name, int value){notSupported();} public int getIntAttribute(TorrentAttribute name){ return( 0 ); } public void setLongAttribute(TorrentAttribute name, long value){notSupported();} public long getLongAttribute(TorrentAttribute name){ return( 0 ); } public void setBooleanAttribute(TorrentAttribute name, boolean value){notSupported();} public boolean getBooleanAttribute(TorrentAttribute name){ return( false ); } public boolean hasAttribute(TorrentAttribute name){ return( false );} public void addAttributeListener( DownloadAttributeListener l, TorrentAttribute attr, int event_type) { } public void removeAttributeListener( DownloadAttributeListener l, TorrentAttribute attr, int event_type) { } public String getCategoryName() { return( null ); } public void setCategory( String sName) { notSupported(); } public void remove() throws DownloadException, DownloadRemovalVetoException { throw( new DownloadRemovalVetoException( "no way" )); } public void remove( boolean delete_torrent, boolean delete_data ) throws DownloadException, DownloadRemovalVetoException { throw( new DownloadRemovalVetoException( "no way" )); } public boolean isRemoved() { return false; } public int getPosition() { return( 0 ); } public long getCreationTime() { return( 0 ); } public void setPosition( int newPosition) { notSupported(); } public void moveUp() { notSupported(); } public void moveDown() { notSupported(); } public void moveTo( int position ) { notSupported(); } public boolean canBeRemoved() throws DownloadRemovalVetoException { throw( new DownloadRemovalVetoException( "no way" )); } public void setAnnounceResult( DownloadAnnounceResult result ) { announcer.setAnnounceResult( result ); } public void setScrapeResult( DownloadScrapeResult result ) { } public DownloadAnnounceResult getLastAnnounceResult() { announce_result.setContent( announcer.getLastResponse()); return( announce_result ); } public DownloadScrapeResult getLastScrapeResult() { announce_result.setContent( announcer.getLastResponse()); return( scrape_result ); } public DownloadActivationEvent getActivationState() { return( null ); } public DownloadStats getStats() { return( null ); } public boolean isPersistent() { return( false ); } public void setMaximumDownloadKBPerSecond( int kb ) { notSupported(); } public int getMaximumDownloadKBPerSecond() { return( 0 ); } public int getUploadRateLimitBytesPerSecond() { return( 0 ); } public void setUploadRateLimitBytesPerSecond( int max_rate_bps ) { notSupported(); } public int getDownloadRateLimitBytesPerSecond() { return 0; } public void setDownloadRateLimitBytesPerSecond( int max_rate_bps ) { notSupported(); } public boolean isComplete() { return( true ); } public boolean isComplete( boolean bIncludeDND) { return( true ); } public boolean isChecking() { return( false ); } public String getSavePath() { return( "" ); } public void moveDataFiles( File new_parent_dir ) throws DownloadException { notSupported(); } public boolean canMoveDataFiles() { return false; } public void moveTorrentFile( File new_parent_dir ) throws DownloadException { notSupported(); } public void renameDownload( String name ) throws DownloadException { notSupported(); } public org.gudy.azureus2.plugins.peers.PeerManager getPeerManager() { return( null ); } public org.gudy.azureus2.plugins.disk.DiskManager getDiskManager() { return( null ); } public DiskManagerFileInfo[] getDiskManagerFileInfo() { return( null ); } public void requestTrackerAnnounce() { } public void requestTrackerAnnounce( boolean immediate ) { } public void requestTrackerScrape( boolean immediate ) { } public void addListener( DownloadListener l ) { } public void removeListener( DownloadListener l ) { } public void addCompletionListener( DownloadCompletionListener l ) { notSupported(); } public void removeCompletionListener( DownloadCompletionListener l ) { notSupported(); } public void addTrackerListener( DownloadTrackerListener l ) { } public void addTrackerListener( DownloadTrackerListener l, boolean immediateTrigger) { } public void removeTrackerListener( DownloadTrackerListener l ) { } public void addDownloadWillBeRemovedListener( DownloadWillBeRemovedListener l ) { notSupported(); } public void removeDownloadWillBeRemovedListener( DownloadWillBeRemovedListener l ) { notSupported(); } public void addActivationListener( DownloadActivationListener l ) { notSupported(); } public void removeActivationListener( DownloadActivationListener l ) { notSupported(); } public void addPeerListener( DownloadPeerListener l ) { notSupported(); } public void removePeerListener( DownloadPeerListener l ) { notSupported(); } public int getSeedingRank() { return( 0 ); } public void setSeedingRank( int rank) { notSupported(); } public void addPropertyListener( DownloadPropertyListener l ) { notSupported(); } public void removePropertyListener( DownloadPropertyListener l ) { notSupported(); } public byte[] getDownloadPeerId() { return( null ); } public boolean isMessagingEnabled() { return( true ); } public void setMessagingEnabled( boolean enabled ) { } public void moveDataFiles( File new_parent_dir, String new_name ) throws DownloadException { notSupported(); } public Object getUserData( Object key ) { synchronized( user_data ){ return( user_data.get( key )); } } public void setUserData( Object key, Object data ) { synchronized( user_data ){ user_data.put( key, data ); } } public void changeLocation( SaveLocationChange slc ) throws DownloadException { notSupported(); } protected void notSupported() { Debug.out( "Not Supported" ); } }azureus-4.3.0.6/com/aelitis/azureus/core/lws/LWSDiskManager.java0000644000175000017500000004253111274472052023730 0ustar adrianadrian/* * Created on Jul 16, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.lws; import java.io.File; import java.util.List; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.disk.DiskManagerCheckRequest; import org.gudy.azureus2.core3.disk.DiskManagerCheckRequestListener; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.disk.DiskManagerFileInfoSet; import org.gudy.azureus2.core3.disk.DiskManagerListener; import org.gudy.azureus2.core3.disk.DiskManagerPiece; import org.gudy.azureus2.core3.disk.DiskManagerReadRequest; import org.gudy.azureus2.core3.disk.DiskManagerReadRequestListener; import org.gudy.azureus2.core3.disk.DiskManagerWriteRequest; import org.gudy.azureus2.core3.disk.DiskManagerWriteRequestListener; import org.gudy.azureus2.core3.disk.impl.DiskManagerFileInfoImpl; import org.gudy.azureus2.core3.disk.impl.DiskManagerHelper; import org.gudy.azureus2.core3.disk.impl.DiskManagerImpl; import org.gudy.azureus2.core3.disk.impl.DiskManagerPieceImpl; import org.gudy.azureus2.core3.disk.impl.DiskManagerRecheckScheduler; import org.gudy.azureus2.core3.disk.impl.DiskManagerUtil; import org.gudy.azureus2.core3.disk.impl.access.DMAccessFactory; import org.gudy.azureus2.core3.disk.impl.access.DMChecker; import org.gudy.azureus2.core3.disk.impl.access.DMReader; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceList; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceMap; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceMapper; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceMapperFactory; import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceMapperFile; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.internat.LocaleTorrentUtil; import org.gudy.azureus2.core3.internat.LocaleUtilDecoder; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.diskmanager.access.DiskAccessController; import com.aelitis.azureus.core.diskmanager.cache.CacheFile; import com.aelitis.azureus.core.diskmanager.cache.CacheFileOwner; public class LWSDiskManager implements DiskManagerHelper { private static sePiece piece = new sePiece(); private LightWeightSeed lws; private DiskAccessController disk_access_controller; private File save_file; private DMReader reader; private DMChecker checker_use_accessor; private DMPieceMapper piece_mapper; private DMPieceMap piece_map_use_accessor; private sePiece[] pieces; private DiskManagerFileInfoImpl[] files; private String internal_name; private DownloadManagerState download_state; private int state = DiskManager.INITIALIZING; private String error_message = ""; protected LWSDiskManager( LightWeightSeed _lws, File _save_file ) { lws = _lws; save_file = _save_file; disk_access_controller = DiskManagerImpl.getDefaultDiskAccessController(); download_state = new LWSDiskManagerState(); TOTorrent torrent = lws.getTOTorrent( false ); pieces = new sePiece[ torrent.getNumberOfPieces() ]; for (int i=0;i 0 ){ ensureActive( "Tracker[" + peers[0].getAddress()+ "]", ACT_TRACKER_ANNOUNCE ); }else if ( response.getScrapeIncompleteCount() > 0 ){ ensureActive( "Tracker[scrape]", ACT_TRACKER_SCRAPE ); } PEPeerManager pm = peer_manager; if ( pm != null ){ pm.processTrackerResponse( response ); } } public void urlChanged( TRTrackerAnnouncer announcer, URL old_url, URL new_url, boolean explicit ) { } public void urlRefresh() { } }); result.setAnnounceDataProvider( new TRTrackerAnnouncerDataProvider() { public String getName() { return( LightWeightSeed.this.getName()); } public long getTotalSent() { return( 0 ); } public long getTotalReceived() { return( 0 ); } public long getFailedHashCheck() { return( 0 ); } public long getRemaining() { return( 0 ); } public String getExtensions() { return( null ); } public int getMaxNewConnectionsAllowed() { PEPeerManager pm = peer_manager; if ( pm == null ){ // got to ask for at least one to trigger activation! return( 8 ); } return( PeerUtils.numNewConnectionsAllowed( pm.getPeerIdentityDataID(),0)); } public int getUploadSpeedKBSec( boolean estimate) { return 0; } public int getCryptoLevel() { return( NetworkManager.CRYPTO_OVERRIDE_NONE ); } public boolean isPeerSourceEnabled( String peer_source ) { return( true ); } public void setPeerSources( String[] sources ) { } }); return( result ); } protected synchronized void ensureActive( String reason, byte a_reason ) { if ( is_running && activation_state == ACT_NONE ){ activate( reason, a_reason ); } } protected synchronized void checkDeactivation() { if ( activation_state == ACT_NONE ){ return; } if ( peer_manager == null ){ activation_state = ACT_NO_PM; return; } if ( peer_manager.getNbPeers() > 0 ){ activation_state = ACT_HAS_PEERS; return; } long now = SystemTime.getMonotonousTime(); long millis_since_last_act = now - last_activity_time; if ( peer_manager.hasPotentialConnections()){ if ( millis_since_last_act < DEACTIVATION_WITH_POTENTIAL_TIMEOUT ){ activation_state = ACT_HAS_POTENTIAL_PEERS; return; } } if ( millis_since_last_act >= DEACTIVATION_TIMEOUT ){ deactivate(); }else{ activation_state = ACT_TIMING_OUT; } } public void enqueueReadRequest( PEPeer peer, DiskManagerReadRequest request, DiskManagerReadRequestListener listener ) { LWSDiskManager dm = disk_manager; if ( dm == null ){ listener.readFailed( request, new Throwable( "download is stopped" )); }else{ dm.enqueueReadRequest( request, listener ); } } public void remove() { manager.remove( this ); } public String getRelationText() { return "LWS: '" + getName() + "'"; } public Object[] getQueryableInterfaces() { return new Object[]{}; } public LogRelation getRelation() { return( this ); } protected String getString() { return( getName()); } protected void log( String str ) { Logger.log(new LogEvent(this, LogIDs.CORE, str )); } protected void log( String str, Throwable e ) { Logger.log(new LogEvent(this, LogIDs.CORE, str, e )); } } azureus-4.3.0.6/com/aelitis/azureus/core/rssgen/0000755000175000017500000000000011310377622020777 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/rssgen/RSSGeneratorPlugin.java0000644000175000017500000001443211306167326025346 0ustar adrianadrian/* * Created on Oct 9, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.rssgen; import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.URLEncoder; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.SystemProperties; import org.gudy.azureus2.plugins.PluginException; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageGenerator; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest; import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.ui.webplugin.WebPlugin; public class RSSGeneratorPlugin extends WebPlugin { public static final String PLUGIN_NAME = "Local RSS etc."; public static final int DEFAULT_PORT = 6905; public static final String DEFAULT_ACCESS = "all"; private static volatile RSSGeneratorPlugin singleton; private static boolean loaded; private static Properties defaults = new Properties(); public static void load( PluginInterface plugin_interface ) { synchronized( RSSGeneratorPlugin.class ){ if ( loaded ){ return; } loaded = true; } plugin_interface.getPluginProperties().setProperty( "plugin.version", "1.0" ); plugin_interface.getPluginProperties().setProperty( "plugin.name", PLUGIN_NAME ); File root_dir = new File( SystemProperties.getUserPath() + "rss" ); if ( !root_dir.exists()){ root_dir.mkdir(); } Integer rss_port; String rss_access; if ( COConfigurationManager.getBooleanParameter( "rss.internal.migrated", false ) || !COConfigurationManager.getBooleanParameter( "Plugin.default.device.rss.enable", false )){ rss_port = COConfigurationManager.getIntParameter( "rss.internal.config.port", DEFAULT_PORT ); rss_access = COConfigurationManager.getStringParameter( "rss.internal.config.access", DEFAULT_ACCESS ); }else{ // migrate from when the RSS feed was tied to devices int port = COConfigurationManager.getIntParameter( "Plugin.default.device.rss.port", DEFAULT_PORT ); rss_port = port; if ( port != DEFAULT_PORT ){ COConfigurationManager.setParameter( "rss.internal.config.port", port ); } boolean local = COConfigurationManager.getBooleanParameter( "Plugin.default.device.rss.localonly", true ); rss_access = local?"local":"all"; if ( !rss_access.equals( DEFAULT_ACCESS )){ COConfigurationManager.setParameter( "rss.internal.config.access", rss_access ); } COConfigurationManager.setParameter( "rss.internal.migrated", true ); } defaults.put( WebPlugin.PR_ENABLE, new Boolean( COConfigurationManager.getBooleanParameter( "Plugin.default.device.rss.enable", false ))); defaults.put( WebPlugin.PR_DISABLABLE, new Boolean( true )); defaults.put( WebPlugin.PR_PORT, rss_port ); defaults.put( WebPlugin.PR_ACCESS, rss_access ); defaults.put( WebPlugin.PR_ROOT_DIR, root_dir.getAbsolutePath()); defaults.put( WebPlugin.PR_ENABLE_KEEP_ALIVE, new Boolean(true)); defaults.put( WebPlugin.PR_HIDE_RESOURCE_CONFIG, new Boolean(true)); defaults.put( WebPlugin.PR_PAIRING_SID, "rss" ); defaults.put( WebPlugin.PR_CONFIG_MODEL_PARAMS, new String[]{ ConfigSection.SECTION_ROOT, "rss" }); } public static RSSGeneratorPlugin getSingleton() { return( singleton ); } private Map providers = new TreeMap(); public RSSGeneratorPlugin() { super( defaults ); } public String getURL() { return( getProtocol() + "://127.0.0.1:" + getPort() + "/" ); } public void registerProvider( String name, Provider provider ) { synchronized( providers ){ providers.put( name, provider ); } } public void initialize( PluginInterface pi ) throws PluginException { singleton = this; pi.getPluginProperties().setProperty( "plugin.name", PLUGIN_NAME ); super.initialize( pi ); } public boolean generateSupport( TrackerWebPageRequest request, TrackerWebPageResponse response ) throws IOException { String url = request.getURL(); if ( url.startsWith( "/" )){ url = url.substring( 1 ); } if ( url.length() == 0 ){ response.setContentType( "text/html; charset=UTF-8" ); PrintWriter pw = new PrintWriter(new OutputStreamWriter( response.getOutputStream(), "UTF-8" )); pw.println( "Vuze Feeds etc." ); synchronized( providers ){ for ( Map.Entry entry: providers.entrySet()){ Provider provider = entry.getValue(); if ( !provider.isEnabled()){ continue; } String name = entry.getKey(); pw.println( "
  • " + name + "
  • " ); } } pw.println( "" ); pw.flush(); return( true ); }else{ int pos = url.indexOf( '/' ); if ( pos != -1 ){ url = url.substring( 0, pos ); } Provider provider; synchronized( providers ){ provider = providers.get( url ); } if ( provider != null && provider.isEnabled()){ if ( provider.generate(request, response)){ return( true ); } } } response.setReplyStatus( 404 ); return( true ); } public interface Provider extends TrackerWebPageGenerator { public boolean isEnabled(); } } azureus-4.3.0.6/com/aelitis/azureus/core/nat/0000755000175000017500000000000011310377616020263 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/nat/NATTraversalObserver.java0000644000175000017500000000306011001025634025126 0ustar adrianadrian/* * Created on 10 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.nat; import java.net.InetSocketAddress; import java.util.Map; public interface NATTraversalObserver { public static final int FT_NO_RENDEZVOUS = 1; public static final int FT_QUEUE_FULL = 2; public static final int FT_CANCELLED = 3; public static String[] FT_STRINGS = { "Unknown", "No rendezvous", "Queue full", "Operation cancelled" }; public void succeeded( InetSocketAddress rendezvous, InetSocketAddress target, Map reply ); public void failed( int failure_type ); public void failed( Throwable cause ); public void disabled(); } azureus-4.3.0.6/com/aelitis/azureus/core/nat/NATTraversalException.java0000644000175000017500000000213311012741352025301 0ustar adrianadrian/* * Created on 9 Aug 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.nat; public class NATTraversalException extends Exception { public NATTraversalException( String str ) { super( str ); } } azureus-4.3.0.6/com/aelitis/azureus/core/nat/NATTraversalHandler.java0000644000175000017500000000227610455033304024731 0ustar adrianadrian/* * Created on 10 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.nat; import java.net.InetSocketAddress; import java.util.Map; public interface NATTraversalHandler { public int getType(); public String getName(); public Map process( InetSocketAddress originator, Map data ); } azureus-4.3.0.6/com/aelitis/azureus/core/nat/NATTraverser.java0000644000175000017500000001345311030641340023437 0ustar adrianadrian/* * Created on 10 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.nat; import java.net.InetSocketAddress; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.ThreadPool; import org.gudy.azureus2.plugins.PluginInterface; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.nat.DHTNATPuncher; import com.aelitis.azureus.core.dht.nat.DHTNATPuncherAdapter; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.plugins.dht.DHTPlugin; public class NATTraverser implements DHTNATPuncherAdapter { public static final int TRAVERSE_REASON_PEER_DATA = 1; public static final int TRAVERSE_REASON_GENERIC_MESSAGING = 2; private static final int MAX_QUEUE_SIZE = 128; private AzureusCore core; private DHTNATPuncher puncher; private ThreadPool thread_pool = new ThreadPool("NATTraverser", 16, true ); private Map handlers = new HashMap(); public NATTraverser( AzureusCore _core ) { core = _core; } public void registerHandler( NATTraversalHandler handler ) { synchronized( handlers ){ handlers.put( new Integer(handler.getType()), handler ); } } public NATTraversal attemptTraversal( final NATTraversalHandler handler, final InetSocketAddress target, final Map request, boolean sync, final NATTraversalObserver listener ) { final NATTraversal traversal = new NATTraversal() { private boolean cancelled; public void cancel() { cancelled = true; } public boolean isCancelled() { return( cancelled ); } }; if ( sync ){ syncTraverse( handler, target, request, listener ); }else{ if ( thread_pool.getQueueSize() >= MAX_QUEUE_SIZE ){ Debug.out( "NATTraversal queue full" ); listener.failed( NATTraversalObserver.FT_QUEUE_FULL ); }else{ thread_pool.run( new AERunnable() { public void runSupport() { if ( traversal.isCancelled()){ listener.failed( NATTraversalObserver.FT_CANCELLED ); }else{ syncTraverse( handler, target, request, listener ); } } }); } } return( traversal ); } protected void syncTraverse( NATTraversalHandler handler, InetSocketAddress target, Map request, NATTraversalObserver listener ) { try{ int type = handler.getType(); synchronized( this ){ if ( puncher == null ){ PluginInterface dht_pi = core.getPluginManager().getPluginInterfaceByClass( DHTPlugin.class ); if ( dht_pi != null ){ DHTPlugin dht_plugin = (DHTPlugin)dht_pi.getPlugin(); if ( dht_plugin.isEnabled()){ DHT dht = dht_plugin.getDHT( DHT.NW_MAIN ); if ( dht == null ){ dht = dht_plugin.getDHT( DHT.NW_CVS ); } if ( dht != null ){ puncher = dht.getNATPuncher(); } } } } if ( puncher == null ){ listener.disabled(); return; } } if ( request == null ){ request = new HashMap(); } request.put( "_travreas", new Long( type )); InetSocketAddress[] target_a = { target }; DHTTransportContact[] rendezvous_used = {null}; Map reply = puncher.punch( handler.getName(), target_a, rendezvous_used, request ); if ( reply == null ){ if ( rendezvous_used[0] == null ){ listener.failed( NATTraversalObserver.FT_NO_RENDEZVOUS ); }else{ listener.failed( new Exception( "NAT traversal failed" )); } }else{ listener.succeeded( rendezvous_used[0].getAddress(), target_a[0], reply ); } }catch( Throwable e ){ listener.failed( e ); } } public Map sendMessage( NATTraversalHandler handler, InetSocketAddress rendezvous, InetSocketAddress target, Map message ) throws NATTraversalException { if ( puncher == null ){ throw( new NATTraversalException( "Puncher unavailable" )); } message.put( "_travreas", new Long( handler.getType())); Map reply = puncher.sendMessage( rendezvous, target, message ); if ( reply == null ){ throw( new NATTraversalException( "Send message failed" )); } return( reply ); } public Map getClientData( InetSocketAddress originator, Map originator_data ) { Long type = (Long)originator_data.get( "_travreas" ); if ( type != null ){ NATTraversalHandler handler; synchronized( handlers ){ handler = (NATTraversalHandler)handlers.get( new Integer( type.intValue())); } if ( handler != null ){ return( handler.process( originator, originator_data )); } } return( null ); } } azureus-4.3.0.6/com/aelitis/azureus/core/nat/NATTraversal.java0000644000175000017500000000207110454610524023430 0ustar adrianadrian/* * Created on 10 Jul 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.nat; public interface NATTraversal { public void cancel(); public boolean isCancelled(); } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/0000755000175000017500000000000011310377624021765 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/MemoryMappedFile.java0000644000175000017500000001777211012741350026033 0ustar adrianadrian/* * Created on Apr 24, 2004 * Created by Alon Rohter * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager; import java.io.*; import java.nio.*; import java.nio.channels.FileChannel; import java.util.*; import java.security.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DirectByteBuffer; /** * This class implements a virtual disk file backed by a pool of direct * memory MappedByteBuffers, designed for high-speed random reads/writes. * * NOTE: Abandoning this code for now, as JRE 1.4 series does not provide an * unmap() method for MappedByteBuffers, so we have to wait for the VM * to lazily free the underlying direct memory regions, which means we * eventually run out of direct memory when accessing files larger than the * allowed direct memory space, since the unused buffers are not freed * quickly enough. Forcing the memory unmap via sun.misc.Cleaner does not work * properly under Windows, throwing the error described in the clean(x) method * below. * */ public class MemoryMappedFile { public static final int MODE_READ_ONLY = 0; public static final int MODE_READ_WRITE = 1; public static long cache_hits = 0; public static long cache_misses = 0; private static final int BLOCK_SIZE = 10*1024*1024; //10MB private final File file; private int access_mode = MODE_READ_ONLY; private FileChannel channel; private Object[] mapKeys; private int[] counts = new int[ 10000 ]; public MemoryMappedFile( File file ) { this.file = file; mapKeys = new Object[ new Long(file.length()/BLOCK_SIZE).intValue() + 1 ]; Arrays.fill( counts, 0 ); } public int getAccessMode() { return access_mode; } public void setAccessMode( int mode ) { if ( mode == MODE_READ_ONLY && access_mode == MODE_READ_WRITE && channel != null ) { try { channel.close(); } catch( Exception e ) { Debug.printStackTrace( e ); } channel = null; } access_mode = mode; } public void write( DirectByteBuffer buffer, int buffer_offset, long file_offset, int length ) throws IOException { if ( access_mode == MODE_READ_ONLY ) { throw new IOException( "cannot write to a read-only file" ); } if ( buffer.limit(DirectByteBuffer.SS_OTHER) - buffer_offset < length ) { throw new IOException( "not enough buffer remaining to write given length" ); } file.createNewFile(); int key_pos = new Long( file_offset / BLOCK_SIZE ).intValue(); int map_offset = new Long( file_offset % BLOCK_SIZE ).intValue(); int written = 0; while( written < length ) { MappedByteBuffer mbb = null; long f_offset = file_offset + written; int length_to_write = BLOCK_SIZE - map_offset; if ( length - written < length_to_write ) length_to_write = length - written; //try grab the buffer from the pool if ( mapKeys.length > key_pos ) { Object key = mapKeys[ key_pos ]; if ( key != null ) { mbb = MemoryMapPool.getBuffer( key ); //check if the current buff is too small if ( mbb != null && mbb.capacity() < (map_offset + length_to_write ) ) { MemoryMapPool.clean( mbb ); mbb = null; } } } else { //need to extend the key array mapKeys = new Object[ key_pos * 2 ]; } //create new buffer, fully-sized, unless it's extending the file if ( mbb == null ) { int size = BLOCK_SIZE; if ( f_offset + length_to_write > file.length() ) { size = map_offset + length_to_write; } mbb = createMappedBuffer( f_offset - map_offset, size ); cache_misses++; } else cache_hits++; //do the write buffer.position( DirectByteBuffer.SS_OTHER,buffer_offset + written ); buffer.limit( DirectByteBuffer.SS_OTHER,buffer.position(DirectByteBuffer.SS_OTHER) + length_to_write ); mbb.position( map_offset ); mbb.put( buffer.getBuffer(DirectByteBuffer.SS_OTHER) ); written += length_to_write; //add the buffer (back) to the pool mapKeys[ key_pos ] = MemoryMapPool.addBuffer( mbb ); key_pos++; map_offset = 0; } } private MappedByteBuffer createMappedBuffer( long file_offset, int length ) throws IOException { if ( channel == null ) { FileChannel fc = new RandomAccessFile( file, "rw" ).getChannel(); MappedByteBuffer mbb = fc.map( FileChannel.MapMode.READ_WRITE, file_offset, length ); if ( access_mode == MODE_READ_ONLY ) fc.close(); else channel = fc; return mbb; } return channel.map( FileChannel.MapMode.READ_WRITE, file_offset, length ); } private static class MemoryMapPool { private static long MAX_SIZE = 100*1024*1024; //100MB private static final MemoryMapPool instance = new MemoryMapPool(); private long total_size = 0; private final AEMonitor buffers_mon = new AEMonitor( "MemoryMappedFile:buffers" ); private final Map buffers = new LinkedHashMap( (int)(MAX_SIZE/BLOCK_SIZE), .75F, true ){ //This method is called just after a new entry has been added public boolean removeEldestEntry(Map.Entry eldest) { boolean remove = total_size > MAX_SIZE; if ( remove ) { MappedByteBuffer mbb = (MappedByteBuffer)eldest.getValue(); total_size -= mbb.capacity(); clean( mbb ); } return remove; } }; //may return null despite a previously-valid key, because the buffer was GC'd //note: the buffer is removed from the pool private static MappedByteBuffer getBuffer( Object key ) { try{ instance.buffers_mon.enter(); MappedByteBuffer mbb = (MappedByteBuffer)instance.buffers.remove( key ); if ( mbb != null ) instance.total_size -= mbb.capacity(); return mbb; }finally{ instance.buffers_mon.exit(); } } private static Object addBuffer( MappedByteBuffer buffer ) { Object key = new Object(); try{ instance.buffers_mon.enter(); instance.total_size += buffer.capacity(); instance.buffers.put( key, buffer ); }finally{ instance.buffers_mon.exit(); } return key; } //Manually Cleaning the buffer doesn't work properly under windows: //java.lang.Error: Cleaner terminated abnormally: //Caused by: java.io.IOException: The process cannot access the file //because another process has locked a portion of the file //See Sun bug id #4938372. private static void clean( final MappedByteBuffer buffer ) { AccessController.doPrivileged( new PrivilegedAction() { public Object run() { try { //Method getCleanerMethod = buffer.getClass().getMethod( "cleaner", new Class[0] ); //getCleanerMethod.setAccessible( true ); //sun.misc.Cleaner cleaner = (sun.misc.Cleaner)getCleanerMethod.invoke( buffer, new Object[0] ); //cleaner.clean(); } catch (Exception e) { Debug.printStackTrace( e ); } return null; } }); } } } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/access/0000755000175000017500000000000011310377624023226 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/access/DiskAccessControllerStats.java0000644000175000017500000000171111165601656031173 0ustar adrianadrian/* * Created on Apr 3, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.diskmanager.access; public interface DiskAccessControllerStats { public long getTotalReadRequests(); public long getTotalReadBytes(); } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/access/impl/0000755000175000017500000000000011310377624024167 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessControllerImpl.java0000644000175000017500000002324411166512510031733 0ustar adrianadrian/* * Created on 02-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.access.impl; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.diskmanager.access.DiskAccessController; import com.aelitis.azureus.core.diskmanager.access.DiskAccessControllerStats; import com.aelitis.azureus.core.diskmanager.access.DiskAccessRequest; import com.aelitis.azureus.core.diskmanager.access.DiskAccessRequestListener; import com.aelitis.azureus.core.diskmanager.cache.CacheFile; import com.aelitis.azureus.core.stats.AzureusCoreStats; import com.aelitis.azureus.core.stats.AzureusCoreStatsProvider; public class DiskAccessControllerImpl implements DiskAccessController, AzureusCoreStatsProvider { private DiskAccessControllerInstance read_dispatcher; private DiskAccessControllerInstance write_dispatcher; public DiskAccessControllerImpl( String _name, int _max_read_threads, int _max_read_mb, int _max_write_threads, int _max_write_mb ) { boolean enable_read_aggregation = COConfigurationManager.getBooleanParameter( "diskmanager.perf.read.aggregate.enable"); int read_aggregation_request_limit = COConfigurationManager.getIntParameter( "diskmanager.perf.read.aggregate.request.limit", 4 ); int read_aggregation_byte_limit = COConfigurationManager.getIntParameter( "diskmanager.perf.read.aggregate.byte.limit", 64*1024 ); boolean enable_write_aggregation = COConfigurationManager.getBooleanParameter( "diskmanager.perf.write.aggregate.enable"); int write_aggregation_request_limit = COConfigurationManager.getIntParameter( "diskmanager.perf.write.aggregate.request.limit", 8 ); int write_aggregation_byte_limit = COConfigurationManager.getIntParameter( "diskmanager.perf.write.aggregate.byte.limit", 128*1024 ); read_dispatcher = new DiskAccessControllerInstance( _name + "/" + "read", enable_read_aggregation, read_aggregation_request_limit, read_aggregation_byte_limit, _max_read_threads, _max_read_mb ); write_dispatcher = new DiskAccessControllerInstance( _name + "/" + "write", enable_write_aggregation, write_aggregation_request_limit, write_aggregation_byte_limit, _max_write_threads, _max_write_mb ); Set types = new HashSet(); types.add( AzureusCoreStats.ST_DISK_READ_QUEUE_LENGTH ); types.add( AzureusCoreStats.ST_DISK_READ_QUEUE_BYTES ); types.add( AzureusCoreStats.ST_DISK_READ_REQUEST_COUNT ); types.add( AzureusCoreStats.ST_DISK_READ_REQUEST_SINGLE ); types.add( AzureusCoreStats.ST_DISK_READ_REQUEST_MULTIPLE ); types.add( AzureusCoreStats.ST_DISK_READ_REQUEST_BLOCKS ); types.add( AzureusCoreStats.ST_DISK_READ_BYTES_TOTAL ); types.add( AzureusCoreStats.ST_DISK_READ_BYTES_SINGLE ); types.add( AzureusCoreStats.ST_DISK_READ_BYTES_MULTIPLE ); types.add( AzureusCoreStats.ST_DISK_READ_IO_TIME ); types.add( AzureusCoreStats.ST_DISK_READ_IO_COUNT ); types.add( AzureusCoreStats.ST_DISK_WRITE_QUEUE_LENGTH ); types.add( AzureusCoreStats.ST_DISK_WRITE_QUEUE_BYTES ); types.add( AzureusCoreStats.ST_DISK_WRITE_REQUEST_COUNT ); types.add( AzureusCoreStats.ST_DISK_WRITE_REQUEST_BLOCKS ); types.add( AzureusCoreStats.ST_DISK_WRITE_BYTES_TOTAL ); types.add( AzureusCoreStats.ST_DISK_WRITE_BYTES_SINGLE ); types.add( AzureusCoreStats.ST_DISK_WRITE_BYTES_MULTIPLE ); types.add( AzureusCoreStats.ST_DISK_WRITE_IO_TIME ); AzureusCoreStats.registerProvider( types, this ); } public void updateStats( Set types, Map values ) { //read if ( types.contains( AzureusCoreStats.ST_DISK_READ_QUEUE_LENGTH )){ values.put( AzureusCoreStats.ST_DISK_READ_QUEUE_LENGTH, new Long( read_dispatcher.getQueueSize())); } if ( types.contains( AzureusCoreStats.ST_DISK_READ_QUEUE_BYTES )){ values.put( AzureusCoreStats.ST_DISK_READ_QUEUE_BYTES, new Long( read_dispatcher.getQueuedBytes())); } if ( types.contains( AzureusCoreStats.ST_DISK_READ_REQUEST_COUNT )){ values.put( AzureusCoreStats.ST_DISK_READ_REQUEST_COUNT, new Long( read_dispatcher.getTotalRequests())); } if ( types.contains( AzureusCoreStats.ST_DISK_READ_REQUEST_SINGLE )){ values.put( AzureusCoreStats.ST_DISK_READ_REQUEST_SINGLE, new Long( read_dispatcher.getTotalSingleRequests())); } if ( types.contains( AzureusCoreStats.ST_DISK_READ_REQUEST_MULTIPLE )){ values.put( AzureusCoreStats.ST_DISK_READ_REQUEST_MULTIPLE, new Long( read_dispatcher.getTotalAggregatedRequests())); } if ( types.contains( AzureusCoreStats.ST_DISK_READ_REQUEST_BLOCKS )){ values.put( AzureusCoreStats.ST_DISK_READ_REQUEST_BLOCKS, new Long( read_dispatcher.getBlockCount())); } if ( types.contains( AzureusCoreStats.ST_DISK_READ_BYTES_TOTAL )){ values.put( AzureusCoreStats.ST_DISK_READ_BYTES_TOTAL, new Long( read_dispatcher.getTotalBytes())); } if ( types.contains( AzureusCoreStats.ST_DISK_READ_BYTES_SINGLE )){ values.put( AzureusCoreStats.ST_DISK_READ_BYTES_SINGLE, new Long( read_dispatcher.getTotalSingleBytes())); } if ( types.contains( AzureusCoreStats.ST_DISK_READ_BYTES_MULTIPLE )){ values.put( AzureusCoreStats.ST_DISK_READ_BYTES_MULTIPLE, new Long( read_dispatcher.getTotalAggregatedBytes())); } if ( types.contains( AzureusCoreStats.ST_DISK_READ_IO_TIME )){ values.put( AzureusCoreStats.ST_DISK_READ_IO_TIME, new Long( read_dispatcher.getIOTime())); } if ( types.contains( AzureusCoreStats.ST_DISK_READ_IO_COUNT )){ values.put( AzureusCoreStats.ST_DISK_READ_IO_COUNT, new Long( read_dispatcher.getIOCount())); } // write if ( types.contains( AzureusCoreStats.ST_DISK_WRITE_QUEUE_LENGTH )){ values.put( AzureusCoreStats.ST_DISK_WRITE_QUEUE_LENGTH, new Long( write_dispatcher.getQueueSize())); } if ( types.contains( AzureusCoreStats.ST_DISK_WRITE_QUEUE_BYTES )){ values.put( AzureusCoreStats.ST_DISK_WRITE_QUEUE_BYTES, new Long( write_dispatcher.getQueuedBytes())); } if ( types.contains( AzureusCoreStats.ST_DISK_WRITE_REQUEST_COUNT )){ values.put( AzureusCoreStats.ST_DISK_WRITE_REQUEST_COUNT, new Long( write_dispatcher.getTotalRequests())); } if ( types.contains( AzureusCoreStats.ST_DISK_WRITE_REQUEST_BLOCKS )){ values.put( AzureusCoreStats.ST_DISK_WRITE_REQUEST_BLOCKS, new Long( write_dispatcher.getBlockCount())); } if ( types.contains( AzureusCoreStats.ST_DISK_WRITE_BYTES_TOTAL )){ values.put( AzureusCoreStats.ST_DISK_WRITE_BYTES_TOTAL, new Long( write_dispatcher.getTotalBytes())); } if ( types.contains( AzureusCoreStats.ST_DISK_WRITE_BYTES_SINGLE )){ values.put( AzureusCoreStats.ST_DISK_WRITE_BYTES_SINGLE, new Long( write_dispatcher.getTotalSingleBytes())); } if ( types.contains( AzureusCoreStats.ST_DISK_WRITE_BYTES_MULTIPLE )){ values.put( AzureusCoreStats.ST_DISK_WRITE_BYTES_MULTIPLE, new Long( write_dispatcher.getTotalAggregatedBytes())); } if ( types.contains( AzureusCoreStats.ST_DISK_WRITE_IO_TIME )){ values.put( AzureusCoreStats.ST_DISK_WRITE_IO_TIME, new Long( write_dispatcher.getIOTime())); } if ( types.contains( AzureusCoreStats.ST_DISK_WRITE_IO_COUNT )){ values.put( AzureusCoreStats.ST_DISK_WRITE_IO_COUNT, new Long( write_dispatcher.getIOCount())); } } public DiskAccessRequest queueReadRequest( CacheFile file, long offset, DirectByteBuffer buffer, short cache_policy, DiskAccessRequestListener listener ) { DiskAccessRequestImpl request = new DiskAccessRequestImpl( file, offset, buffer, listener, DiskAccessRequestImpl.OP_READ, cache_policy ); read_dispatcher.queueRequest( request ); return( request ); } public DiskAccessRequest queueWriteRequest( CacheFile file, long offset, DirectByteBuffer buffer, boolean free_buffer, DiskAccessRequestListener listener ) { // System.out.println( "write request: " + offset ); DiskAccessRequestImpl request = new DiskAccessRequestImpl( file, offset, buffer, listener, free_buffer?DiskAccessRequestImpl.OP_WRITE_AND_FREE:DiskAccessRequestImpl.OP_WRITE, CacheFile.CP_NONE ); write_dispatcher.queueRequest( request ); return( request ); } public DiskAccessControllerStats getStats() { return( new DiskAccessControllerStats() { long read_total_req = read_dispatcher.getTotalRequests(); long read_total_bytes = read_dispatcher.getTotalBytes(); public long getTotalReadRequests() { return( read_total_req ); } public long getTotalReadBytes() { return( read_total_bytes ); } }); } public String getString() { return( "read: " + read_dispatcher.getString() + ", write: " + write_dispatcher.getString()); } } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessRequestImpl.java0000644000175000017500000001316111165562416031246 0ustar adrianadrian/* * Created on 02-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.access.impl; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.diskmanager.access.DiskAccessRequest; import com.aelitis.azureus.core.diskmanager.access.DiskAccessRequestListener; import com.aelitis.azureus.core.diskmanager.cache.CacheFile; import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerException; public class DiskAccessRequestImpl implements DiskAccessRequest { protected static final short OP_READ = 1; protected static final short OP_WRITE = 2; protected static final short OP_WRITE_AND_FREE = 3; private CacheFile file; private long offset; private DirectByteBuffer buffer; private DiskAccessRequestListener listener; private short op; private short cache_policy; private int size; private volatile boolean cancelled; protected DiskAccessRequestImpl( CacheFile _file, long _offset, DirectByteBuffer _buffer, DiskAccessRequestListener _listener, short _op, short _cache_policy ) { file = _file; offset = _offset; buffer = _buffer; listener = _listener; op = _op; cache_policy = _cache_policy; size = buffer.remaining( DirectByteBuffer.SS_FILE ); } public int getSize() { return( size ); } protected void runRequest() { if ( cancelled ){ listener.requestCancelled( this ); return; } //System.out.println( "DiskReq:" + Thread.currentThread().getName() + ": " + op + " - " + offset ); try{ if ( op == OP_READ ){ file.read( buffer, offset, cache_policy ); }else if ( op == OP_WRITE ){ file.write( buffer, offset ); }else{ file.writeAndHandoverBuffer( buffer, offset ); } listener.requestExecuted( size ); listener.requestComplete( this ); }catch( Throwable e ){ listener.requestFailed( this, e ); } } protected boolean canBeAggregatedWith( DiskAccessRequestImpl other ) { return( op == other.getOperation() && cache_policy == other.getCachePolicy()); } protected static void runAggregated( DiskAccessRequestImpl base_request, DiskAccessRequestImpl[] requests ) { // assumption - they are all for the same file, sequential offsets and aggregatable, not cancelled int op = base_request.getOperation(); CacheFile file = base_request.getFile(); long offset = base_request.getOffset(); short cache_policy = base_request.getCachePolicy(); DirectByteBuffer[] buffers = new DirectByteBuffer[requests.length]; long current_offset = offset; long total_size = 0; for (int i=0;i 60000 || now < last_check ){ check = true; last_check = now; } if ( check ){ Iterator it = torrent_dispatcher_map.values().iterator(); while( it.hasNext()){ requestDispatcher d = (requestDispatcher)it.next(); long last_active = d.getLastRequestTime(); if ( now - last_active > 60000 ){ it.remove(); }else if ( now < last_active ){ d.setLastRequestTime( now ); } } } TOTorrent torrent = request.getFile().getTorrentFile().getTorrent(); dispatcher = (requestDispatcher)torrent_dispatcher_map.get(torrent); if ( dispatcher == null ){ int min_index = 0; int min_size = Integer.MAX_VALUE; for (int i=0;i max_mb_queued ){ // if this request is bigger than the max allowed queueable then easiest // approach is to bump up the limit max_mb_sem.releaseGroup( mb_diff - max_mb_queued ); max_mb_queued = mb_diff; } requests_queued++; if ( requests_queued >= next_request_num_log ){ //System.out.println( "DAC:" + name + ": requests = " + requests_queued ); next_request_num_log += REQUEST_NUM_LOG_CHUNK; } if ( request_bytes_queued >= next_request_byte_log ){ //System.out.println( "DAC:" + name + ": bytes = " + request_bytes_queued ); next_request_byte_log += REQUEST_BYTE_LOG_CHUNK; } } if ( mb_diff > 0 ){ max_mb_sem.reserveGroup( mb_diff ); } } protected void releaseSpaceAllowance( DiskAccessRequestImpl request ) { int mb_diff; synchronized( torrent_dispatcher_map ){ int old_mb = (int)(request_bytes_queued/(1024*1024)); request_bytes_queued -= request.getSize(); int new_mb = (int)(request_bytes_queued/(1024*1024)); mb_diff = old_mb - new_mb; requests_queued--; } if ( mb_diff > 0 ){ max_mb_sem.releaseGroup( mb_diff ); } } protected String getString() { return( name + ",agg=" + enable_aggregation + ",max_t=" + max_threads + ",max_mb=" + max_mb_queued + ",q_byte=" + DisplayFormatters.formatByteCountToKiBEtc( request_bytes_queued ) + ",q_req=" + requests_queued + ",t_req=" + total_requests + ",t_byte=" + DisplayFormatters.formatByteCountToKiBEtc( total_bytes ) + ",io=" + io_count ); } protected class requestDispatcher { private int index; private AEThread2[] threads = new AEThread2[invert_threads?max_threads:1]; private int active_threads; private LinkedList requests = new LinkedList(); private Map request_map = new HashMap(); private long last_request_map_tidy; private AESemaphore request_sem = new AESemaphore("DiskAccessControllerInstance:requestDispatcher:request" ); private AESemaphore schedule_sem = new AESemaphore("DiskAccessControllerInstance:requestDispatcher:schedule", 1 ); private long last_request_time; protected requestDispatcher( int _index ) { index = _index; } protected void queue( DiskAccessRequestImpl request ) { if ( tls.get() != null ){ // let recursive calls straight through synchronized( requests ){ // stats not synced on the right object, but they're only stats... total_requests++; total_single_requests_made++; total_bytes += request.getSize(); total_single_bytes += request.getSize(); } // long io_start = SystemTime.getHighPrecisionCounter(); try{ request.runRequest(); }catch( Throwable e ){ // actually, for recursive calls the time of this request will be // included in the timing of the call resulting in the recursion // long io_end = SystemTime.getHighPrecisionCounter(); // io_time += ( io_end - io_start ); io_count++; Debug.printStackTrace(e); } }else{ getSpaceAllowance( request ); synchronized( requests ){ total_requests++; total_bytes += request.getSize(); boolean added = false; int priority = request.getPriority(); if ( priority >= 0 ){ int pos = 0; for (Iterator it = requests.iterator();it.hasNext();){ DiskAccessRequestImpl r = (DiskAccessRequestImpl)it.next(); if ( r.getPriority() < priority ){ requests.add( pos, request ); added = true; break; } pos++; } } if ( !added ){ requests.add( request ); } if ( enable_aggregation ){ Map m = (Map)request_map.get( request.getFile()); if ( m == null ){ m = new HashMap(); request_map.put( request.getFile(), m ); } m.put( new Long( request.getOffset()), request ); long now = SystemTime.getCurrentTime(); if ( now < last_request_map_tidy || now - last_request_map_tidy > 30000 ){ // check for and discard manky old files from stopped/removed // downloads last_request_map_tidy = now; Iterator it = request_map.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); if (((HashMap)entry.getValue()).size() == 0 ){ if (!((CacheFile)entry.getKey()).isOpen()){ it.remove(); } } } } } // System.out.println( "request queue: req = " + requests.size() + ", bytes = " + request_bytes_queued ); request_sem.release(); requestQueued(); } } } protected long getLastRequestTime() { return( last_request_time ); } protected void setLastRequestTime( long l ) { last_request_time = l; } protected int size() { return( requests.size()); } protected void requestQueued() { // requests monitor held if ( active_threads < threads.length && ( active_threads == 0 || requests.size() > 32 )){ for (int i=0;i 0 as we've removed an element... Debug.out( "shouldn't happen" ); } if ( aggregated == null ){ aggregated = new ArrayList(8); aggregated.add( current ); aggregated_bytes += current_size; } aggregated.add( next ); aggregated_bytes += next.getSize(); if ( aggregated.size() > aggregation_request_limit || aggregated_bytes >= aggregation_byte_limit ){ break; } current = next; } }finally{ if ( aggregated != null ){ total_aggregated_requests_made++; /* System.out.println( "aggregated read: requests=" + aggregated.size() + ", size=" + aggregated_bytes + ", a_reqs=" + requests.size() + ", f_reqs=" + file_map.size()); */ }else{ total_single_requests_made++; } } } } } } }finally{ if ( invert_threads ){ schedule_sem.release(); } } try{ long io_start = SystemTime.getHighPrecisionCounter(); if ( aggregated != null ){ DiskAccessRequestImpl[] requests = (DiskAccessRequestImpl[])aggregated.toArray( new DiskAccessRequestImpl[ aggregated.size()]); try{ DiskAccessRequestImpl.runAggregated( request, requests ); }finally{ long io_end = SystemTime.getHighPrecisionCounter(); io_time += ( io_end - io_start ); io_count++; for (int i=0;i 0 ){ mutableInteger wait = (mutableInteger)waiters.get(0); int wait_num = wait.getValue(); if ( wait_num <= num ){ // we've got enough now to release this waiter wait.release(); waiters.remove(0); num -= wait_num; }else{ wait.setValue( wait_num - num ); num = 0; break; } } // if we have any left over then save it value = num; } } } protected static class mutableInteger { private int i; private boolean released; protected mutableInteger( int _i ) { i = _i; } protected int getValue() { return( i ); } protected void setValue( int _i ) { i = _i; } protected void release() { synchronized( this ){ released = true; notify(); } } protected void reserve() { synchronized( this ){ if ( released ){ return; } try{ int spurious_count = 0; while( true ){ wait(); if ( released ){ break; }else{ spurious_count++; if ( spurious_count > 1024 ){ Debug.out( "DAC::mutableInteger: spurious wakeup limit exceeded" ); throw( new RuntimeException( "die die die" )); }else{ Debug.out("DAC::mutableInteger: spurious wakeup, ignoring" ); } } } }catch( InterruptedException e ){ throw( new RuntimeException("Semaphore: operation interrupted" )); } } } } } public static void main( String[] args ) { final groupSemaphore sem = new groupSemaphore( 9 ); for (int i=0;i<10;i++){ new Thread() { public void run() { int count = 0; while( true ){ int group =RandomUtils.generateRandomIntUpto( 10 ); System.out.println( Thread.currentThread().getName() + " reserving " + group ); sem.reserveGroup( group ); try{ Thread.sleep(5 + RandomUtils.generateRandomIntUpto(5)); }catch( Throwable e ){ } sem.releaseGroup( group ); count++; if ( count %100 == 0 ){ System.out.println( Thread.currentThread().getName() + ": " + count + " ops" ); } } } }.start(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/access/DiskAccessController.java0000644000175000017500000000312011165601656030150 0ustar adrianadrian/* * Created on 02-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.access; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.diskmanager.cache.CacheFile; public interface DiskAccessController { public DiskAccessRequest queueReadRequest( CacheFile file, long offset, DirectByteBuffer buffer, short cache_policy, DiskAccessRequestListener listener ); public DiskAccessRequest queueWriteRequest( CacheFile file, long offset, DirectByteBuffer buffer, boolean free_buffer, DiskAccessRequestListener listener ); public DiskAccessControllerStats getStats(); public String getString(); } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/access/DiskAccessRequest.java0000644000175000017500000000250110547374374027466 0ustar adrianadrian/* * Created on 02-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.access; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.diskmanager.cache.CacheFile; public interface DiskAccessRequest { public CacheFile getFile(); public long getOffset(); public int getSize(); public DirectByteBuffer getBuffer(); public int getPriority(); public void cancel(); } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/access/DiskAccessRequestListener.java0000644000175000017500000000312710556302604031164 0ustar adrianadrian/* * Created on 02-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.access; public interface DiskAccessRequestListener { public void requestComplete( DiskAccessRequest request ); public void requestCancelled( DiskAccessRequest request ); public void requestFailed( DiskAccessRequest request, Throwable cause ); public int getPriority(); /** * Called to indicate that an actual request operation occurred. If this request has * been aggregated with others then the byted reported will be for the contiguous * region and subsequent aggregated requests will be reported with 0 bytes * @param bytes */ public void requestExecuted( long bytes ); } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/access/DiskAccessControllerFactory.java0000644000175000017500000000262711166512510031502 0ustar adrianadrian/* * Created on 02-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.access; import com.aelitis.azureus.core.diskmanager.access.impl.DiskAccessControllerImpl; public class DiskAccessControllerFactory { public static DiskAccessController create( String name, int max_read_threads, int max_read_mb, int max_write_threads, int max_write_mb ) { return( new DiskAccessControllerImpl( name, max_read_threads, max_read_mb, max_write_threads, max_write_mb )); } } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/cache/0000755000175000017500000000000011310377624023030 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/cache/impl/0000755000175000017500000000000011310377624023771 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCache.java0000644000175000017500000001622611252111640030743 0ustar adrianadrian/* * Created on 02-Nov-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.cache.impl; /** * @author parg * */ import java.io.File; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.diskmanager.cache.*; import com.aelitis.azureus.core.diskmanager.file.FMFile; import com.aelitis.azureus.core.diskmanager.file.FMFileManagerException; public class CacheFileWithoutCache implements CacheFile { protected CacheFileManagerImpl manager; protected FMFile file; protected TOTorrentFile torrent_file; protected CacheFileWithoutCache( CacheFileManagerImpl _manager, FMFile _file, TOTorrentFile _torrent_file ) { manager = _manager; file = _file; torrent_file = _torrent_file; // System.out.println( "without cache = " + file.getFile().toString()); } public TOTorrentFile getTorrentFile() { return( torrent_file ); } public boolean exists() { return( file.exists()); } public void moveFile( File new_file ) throws CacheFileManagerException { try{ file.moveFile( new_file ); }catch( FMFileManagerException e ){ manager.rethrow(this,e); } } public void renameFile( String new_file ) throws CacheFileManagerException { try{ file.renameFile( new_file ); }catch( FMFileManagerException e ){ manager.rethrow(this,e); } } public void setAccessMode( int mode ) throws CacheFileManagerException { try{ file.setAccessMode( mode==CF_READ?FMFile.FM_READ:FMFile.FM_WRITE ); }catch( FMFileManagerException e ){ manager.rethrow(this,e); } } public int getAccessMode() { return( file.getAccessMode()==FMFile.FM_READ?CF_READ:CF_WRITE ); } public void setStorageType( int type ) throws CacheFileManagerException { try{ file.setStorageType( CacheFileManagerImpl.convertCacheToFileType( type )); }catch( FMFileManagerException e ){ manager.rethrow(this,e); } } public int getStorageType() { return( CacheFileManagerImpl.convertFileToCacheType( file.getStorageType())); } public long getLength() throws CacheFileManagerException { try{ return( file.exists() ? file.getLength() : 0); }catch( FMFileManagerException e ){ manager.rethrow(this,e); return( 0 ); } } public long compareLength( long compare_to ) throws CacheFileManagerException { return( getLength() - compare_to ); } public void setLength( long length ) throws CacheFileManagerException { try{ file.setLength( length ); }catch( FMFileManagerException e ){ manager.rethrow(this,e); } } public void setPieceComplete( int piece_number, DirectByteBuffer piece_data ) throws CacheFileManagerException { try{ file.setPieceComplete( piece_number, piece_data ); }catch( FMFileManagerException e ){ manager.rethrow(this,e); } } public void read( DirectByteBuffer[] buffers, long position, short policy ) throws CacheFileManagerException { int read_length = 0; for (int i=0;i 75% of made average then increase double ratio = used_average*100/made_average; if ( ratio > 0.75 ){ current_read_ahead_size += 16*1024; // no bigger than a piece current_read_ahead_size = Math.min( current_read_ahead_size, piece_size ); // no bigger than the fixed max size current_read_ahead_size = Math.min( current_read_ahead_size, READAHEAD_HIGH_LIMIT ); // no bigger than a 16th of the cache, in case its really small (e.g. 1M) current_read_ahead_size = Math.min( current_read_ahead_size, (int)(manager.getCacheSize()/16 )); }else if ( ratio < 0.5 ){ current_read_ahead_size -= 16*1024; // no smaller than the min current_read_ahead_size = Math.max( current_read_ahead_size, READAHEAD_LOW_LIMIT ); } } // System.out.println( "read-ahead: done = " + read_ahead_bytes_made + ", used = " + read_ahead_bytes_used + ", done_av = " + read_ahead_made_average.getAverage() + ", used_av = " + read_ahead_used_average.getAverage()+ ", size = " + current_read_ahead_size ); } protected void readCache( final DirectByteBuffer file_buffer, final long file_position, final boolean recursive, final boolean disable_read_cache ) throws CacheFileManagerException { checkPendingException(); final int file_buffer_position = file_buffer.position(SS_CACHE); final int file_buffer_limit = file_buffer.limit(SS_CACHE); final int read_length = file_buffer_limit - file_buffer_position; try{ if ( manager.isCacheEnabled()){ if (TRACE) Logger.log(new LogEvent(torrent, LOGID, "readCache: " + getName() + ", " + file_position + " - " + (file_position + read_length - 1) + ":" + file_buffer_position + "/" + file_buffer_limit)); if ( read_length == 0 ){ return; // nothing to do } long writing_file_position = file_position; int writing_left = read_length; boolean ok = true; int used_entries = 0; long used_read_ahead = 0; // if we can totally satisfy the read from the cache, then use it // otherwise flush the cache (not so smart here to only read missing) try{ this_mon.enter(); if(read_history == null) { read_history = new long[ READAHEAD_HISTORY ]; Arrays.fill( read_history, -1 ); } // record the position of the byte *following* the end of this read read_history[read_history_next++] = file_position + read_length; if ( read_history_next == READAHEAD_HISTORY ){ read_history_next = 0; } Iterator it = cache.iterator(); while( ok && writing_left > 0 && it.hasNext()){ CacheEntry entry = (CacheEntry)it.next(); long entry_file_position = entry.getFilePosition(); int entry_length = entry.getLength(); if ( entry_file_position > writing_file_position ){ // data missing at the start of the read section ok = false; break; }else if ( entry_file_position + entry_length <= writing_file_position ){ // not got there yet }else{ // copy required amount into read buffer int skip = (int)(writing_file_position - entry_file_position); int available = entry_length - skip; if ( available > writing_left ){ available = writing_left; } DirectByteBuffer entry_buffer = entry.getBuffer(); int entry_buffer_position = entry_buffer.position(SS_CACHE); int entry_buffer_limit = entry_buffer.limit(SS_CACHE); try{ entry_buffer.limit( SS_CACHE, entry_buffer_position + skip + available ); entry_buffer.position( SS_CACHE, entry_buffer_position + skip ); if (TRACE) Logger.log(new LogEvent(torrent, LOGID, "cacheRead: using " + entry.getString() + "[" + entry_buffer.position(SS_CACHE) + "/" + entry_buffer.limit(SS_CACHE) + "]" + "to write to [" + file_buffer.position(SS_CACHE) + "/" + file_buffer.limit(SS_CACHE) + "]")); used_entries++; file_buffer.put( SS_CACHE, entry_buffer ); manager.cacheEntryUsed( entry ); }finally{ entry_buffer.limit( SS_CACHE, entry_buffer_limit ); entry_buffer.position( SS_CACHE, entry_buffer_position ); } writing_file_position += available; writing_left -= available; if ( entry.getType() == CacheEntry.CT_READ_AHEAD ){ used_read_ahead += available; } } } }finally{ if ( ok ){ read_ahead_bytes_used += used_read_ahead; } this_mon.exit(); } if ( ok && writing_left == 0 ){ // only record this as a cache read hit if we haven't just read the // data from the file system if ( !recursive ){ manager.cacheBytesRead( read_length ); } if (TRACE) Logger.log(new LogEvent(torrent, LOGID, "cacheRead: cache use ok [entries = " + used_entries + "]")); }else{ if (TRACE) Logger.log(new LogEvent(torrent, LOGID, "cacheRead: cache use fails, reverting to plain read")); // reset in case we've done some partial reads file_buffer.position( SS_CACHE, file_buffer_position ); // If read-ahead fails then we resort to a straight read // Read-ahead can fail if a cache-flush fails (e.g. out of disk space // on a file belonging to a different torrent than this. // We don't want such a failure to break this read operation for (int i=0;i<2;i++){ try{ boolean do_read_ahead = i == 0 && // first time round !recursive && !disable_read_cache && read_history != null && manager.isReadCacheEnabled() && read_length < current_read_ahead_size && file_position + current_read_ahead_size <= file.getLength(); if ( do_read_ahead ){ // only read ahead if this is a continuation of a prior read within history do_read_ahead = false; for (int j=0;j do all from position onwards boolean release_entries, long minimum_to_release, // -1 -> all long oldest_dirty_time, // dirty entries newer than this won't be flushed // 0 -> now long min_chunk_size ) // minimum contiguous size for flushing, -1 -> no limit throws CacheFileManagerException { try{ flushCacheSupport( file_position, length, release_entries, minimum_to_release, oldest_dirty_time, min_chunk_size ); }catch( CacheFileManagerException e ){ if ( !release_entries ){ // make sure we release the offending buffer entries otherwise they'll hang around // in memory causing grief when the next attempt it made to flush them... flushCacheSupport( 0, -1, true, -1, 0, -1 ); } throw( e ); } } protected void flushCacheSupport( long file_position, long length, // -1 -> do all from position onwards boolean release_entries, long minimum_to_release, // -1 -> all long oldest_dirty_time, // dirty entries newer than this won't be flushed // 0 -> now long min_chunk_size ) // minimum contiguous size for flushing, -1 -> no limit throws CacheFileManagerException { try{ this_mon.enter(); if ( cache.size() == 0 ){ return; } Iterator it = cache.iterator(); Throwable last_failure = null; long entry_total_released = 0; List multi_block_entries = new ArrayList(); long multi_block_start = -1; long multi_block_next = -1; while( it.hasNext()){ CacheEntry entry = (CacheEntry)it.next(); long entry_file_position = entry.getFilePosition(); int entry_length = entry.getLength(); if ( entry_file_position + entry_length <= file_position ){ // to the left continue; }else if ( length != -1 && file_position + length <= entry_file_position ){ // to the right, give up break; } // overlap!!!! // we're going to deal with this entry one way or another. In particular if // we are releasing entries then this is guaranteed to be released, either directly // or via a flush if dirty boolean dirty = entry.isDirty(); try{ if ( dirty && ( oldest_dirty_time == 0 || entry.getLastUsed() < oldest_dirty_time )){ if ( multi_block_start == -1 ){ // start of day multi_block_start = entry_file_position; multi_block_next = entry_file_position + entry_length; multi_block_entries.add( entry ); }else if ( multi_block_next == entry_file_position ){ // continuation, add in multi_block_next = entry_file_position + entry_length; multi_block_entries.add( entry ); }else{ // we've got a gap - flush current and start another series // set up ready for next block in case the flush fails - we try // and flush as much as possible in the face of failure boolean skip_chunk = false; if ( min_chunk_size != -1 ){ if ( release_entries ){ Debug.out( "CacheFile: can't use min chunk with release option" ); }else{ skip_chunk = multi_block_next - multi_block_start < min_chunk_size; } } List f_multi_block_entries = multi_block_entries; long f_multi_block_start = multi_block_start; long f_multi_block_next = multi_block_next; multi_block_start = entry_file_position; multi_block_next = entry_file_position + entry_length; multi_block_entries = new ArrayList(); multi_block_entries.add( entry ); if ( skip_chunk ){ if (TRACE) Logger.log(new LogEvent(torrent, LOGID, "flushCache: skipping " + multi_block_entries.size() + " entries, [" + multi_block_start + "," + multi_block_next + "] as too small")); }else{ multiBlockFlush( f_multi_block_entries, f_multi_block_start, f_multi_block_next, release_entries ); } } } }catch( Throwable e ){ last_failure = e; }finally{ if ( release_entries ){ it.remove(); // if it is dirty it will be released when the flush is done if ( !dirty ){ manager.releaseCacheSpace( entry ); } entry_total_released += entry.getLength(); if ( minimum_to_release != -1 && entry_total_released > minimum_to_release ){ // if this entry needs flushing this is done outside the loop break; } } } } if ( multi_block_start != -1 ){ boolean skip_chunk = false; if ( min_chunk_size != -1 ){ if ( release_entries ){ Debug.out( "CacheFile: can't use min chunk with release option" ); }else{ skip_chunk = multi_block_next - multi_block_start < min_chunk_size; } } if ( skip_chunk ){ if (TRACE) Logger .log(new LogEvent(torrent, LOGID, "flushCache: skipping " + multi_block_entries.size() + " entries, [" + multi_block_start + "," + multi_block_next + "] as too small")); }else{ multiBlockFlush( multi_block_entries, multi_block_start, multi_block_next, release_entries ); } } if ( last_failure != null ){ if ( last_failure instanceof CacheFileManagerException ){ throw((CacheFileManagerException)last_failure ); } throw( new CacheFileManagerException( this,"cache flush failed", last_failure )); } }finally{ this_mon.exit(); } } protected void multiBlockFlush( List multi_block_entries, long multi_block_start, long multi_block_next, boolean release_entries ) throws CacheFileManagerException { boolean write_ok = false; try{ if (TRACE) Logger.log(new LogEvent(torrent, LOGID, "multiBlockFlush: writing " + multi_block_entries.size() + " entries, [" + multi_block_start + "," + multi_block_next + "," + release_entries + "]")); DirectByteBuffer[] buffers = new DirectByteBuffer[ multi_block_entries.size()]; long expected_per_entry_write = 0; for (int i=0;i= absoluteOffsets.length) break; doSkipping = false; if(startPos >= absoluteOffsets[i] && endPos >= absoluteOffsets[i]+lengths[i]) { // chunk completely falls into cache entry -> don't invalidate i++; doSkipping = true; } else if(startPos >= lastEnd) { // chunk spans multiple cache entries AND we skipped -> invalidate doSkipping = true; } else if(startPos >= absoluteOffsets[i]+lengths[i]) { // end of a spanning chunk -> don't invalidate i++; doSkipping = true; } if(endPos > last) break; lastEnd = endPos; } } finally { this_mon.exit(); } if(doSkipping) // we fell through the loop but there's still cleanup to do while(i baseOffset+torrent_file.getLength()) { i++; continue; } toModify[i] = false; i++; } } // support methods protected void checkPendingException() throws CacheFileManagerException { if ( pending_exception != null ){ throw( pending_exception ); } } protected void setPendingException( CacheFileManagerException e ) { pending_exception = e; } protected String getName() { return( file.getName()); } protected FMFile getFMFile() { return( file ); } // public methods public boolean exists() { return( file.exists()); } public void moveFile( File new_file ) throws CacheFileManagerException { try{ flushCachePublic( true, -1 ); file.moveFile( new_file ); }catch( FMFileManagerException e ){ manager.rethrow(this,e); } } public void renameFile( String new_name ) throws CacheFileManagerException { try{ flushCachePublic( true, -1 ); file.renameFile( new_name ); }catch( FMFileManagerException e ){ manager.rethrow(this,e); } } public void setAccessMode( int mode ) throws CacheFileManagerException { try{ this_mon.enter(); if ( access_mode != mode ){ flushCachePublic( false, -1 ); } file.setAccessMode( mode==CF_READ?FMFile.FM_READ:FMFile.FM_WRITE ); access_mode = mode; }catch( FMFileManagerException e ){ manager.rethrow(this,e); }finally{ this_mon.exit(); } } public int getAccessMode() { return( access_mode ); } public void setStorageType( int type ) throws CacheFileManagerException { try{ this_mon.enter(); if ( getStorageType() != type ){ flushCachePublic( false, -1 ); } file.setStorageType( CacheFileManagerImpl.convertCacheToFileType( type )); }catch( FMFileManagerException e ){ manager.rethrow(this,e); }finally{ this_mon.exit(); } } public int getStorageType() { return( CacheFileManagerImpl.convertFileToCacheType( file.getStorageType())); } public long getLength() throws CacheFileManagerException { // not sure of the difference between "size" and "length" here. Old code // used to use "size" so I'm going to carry on for the moment in case // there is some weirdness here try{ // bug found here with "incremental creation" failing with lots of hash // fails. Caused by the reported length not taking into account the cache // entries that have yet to be flushed. if ( manager.isCacheEnabled()){ try{ this_mon.enter(); long physical_size = file.exists() ? file.getLength() : 0; Iterator it = cache.iterator(); // last entry is furthest down the file while( it.hasNext()){ CacheEntry entry = (CacheEntry)it.next(); if ( !it.hasNext()){ long entry_file_position = entry.getFilePosition(); int entry_length = entry.getLength(); long logical_size = entry_file_position + entry_length; if ( logical_size > physical_size ){ physical_size = logical_size; } } } return( physical_size ); }finally{ this_mon.exit(); } }else{ return( file.exists() ? file.getLength() : 0); } }catch( FMFileManagerException e ){ manager.rethrow(this,e); return( 0 ); } } public long compareLength( long compare_to ) throws CacheFileManagerException { try{ // we can optimise this if the file's already big enough as cache entries can // only make it bigger long physical_length = file.exists() ? file.getLength() : 0; long res = physical_length - compare_to; if ( res >= 0 ){ return( res ); } return( getLength() - compare_to ); }catch( FMFileManagerException e ){ manager.rethrow(this,e); return( 0 ); } } public void setLength( long length ) throws CacheFileManagerException { try{ // flush in case length change will invalidate cache data (unlikely but possible) flushCachePublic( true, -1 ); file.setLength( length ); }catch( FMFileManagerException e ){ manager.rethrow(this,e); } } public void setPieceComplete( int piece_number, DirectByteBuffer piece_data ) throws CacheFileManagerException { try{ file.setPieceComplete( piece_number, piece_data ); }catch( FMFileManagerException e ){ manager.rethrow(this,e); } } public void read( DirectByteBuffer[] buffers, long position, short policy ) throws CacheFileManagerException { for (int i=0;iB and * B->A classic deadlock situation. However, we must keep the file's cache and our cache in step. * It is not acceptable to have an entry inserted into our records but not in the file's as this * then screws up the flush algorithm (which assumes that if it finds an entry in our list, a flush * of that file is guaranteed to release space). Therefore we add the cache entry in addCacheSpace * so that the caller can safely do this while synchronised firstly on its monitor and then we can * sync on our. Hence we only ever get A->B monitor grabs which won't deadlock * @param file * @param buffer * @param file_position * @param length * @return * @throws CacheFileManagerException */ protected CacheEntry allocateCacheSpace( int entry_type, CacheFileWithCache file, DirectByteBuffer buffer, long file_position, int length ) throws CacheFileManagerException { boolean ok = false; boolean log = false; while( !ok ){ // musn't invoke synchronised CacheFile methods while holding manager lock as this // can cause deadlocks (as CacheFile calls manager methods with locks) CacheEntry oldest_entry = null; try{ this_mon.enter(); if ( length < cache_space_free || cache_space_free == cache_size ){ ok = true; }else{ oldest_entry = (CacheEntry)cache_entries.keySet().iterator().next(); } }finally{ this_mon.exit(); } if ( !ok ){ log = true; long old_free = cache_space_free; CacheFileWithCache oldest_file = oldest_entry.getFile(); try{ oldest_file.flushCache( oldest_entry.getFilePosition(), true, cache_minimum_free_size ); }catch( CacheFileManagerException e ){ // if the flush failed on a file other than this one then we don't report the error here, // rather we tag the existing file as failed so that when it is next accessed the error // will be reported if ( oldest_file != file ){ oldest_file.setPendingException( e ); }else{ throw( e ); } } long flushed = cache_space_free - old_free; if (Logger.isEnabled()) { TOTorrentFile tf = file.getTorrentFile(); TOTorrent torrent = tf == null ? null : tf.getTorrent(); Logger.log(new LogEvent(torrent, LOGID, "DiskCache: cache full, flushed " + flushed + " from " + oldest_file.getName())); } if ( flushed == 0 ){ try{ this_mon.enter(); if ( cache_entries.size() > 0 && (CacheEntry)cache_entries.keySet().iterator().next() == oldest_entry ){ // hmm, something wrong with cache as the flush should have got rid // of at least the oldest entry throw( new CacheFileManagerException( null, "Cache inconsistent: 0 flushed")); } }finally{ this_mon.exit(); } } } } CacheEntry entry = new CacheEntry( entry_type, file, buffer, file_position, length ); if (log && Logger.isEnabled()) { TOTorrentFile tf = file.getTorrentFile(); TOTorrent torrent = tf == null ? null : tf.getTorrent(); Logger.log(new LogEvent(torrent, LOGID, "DiskCache: cr=" + cache_bytes_read + ",cw=" + cache_bytes_written + ",fr=" + file_bytes_read + ",fw=" + file_bytes_written)); } return( entry ); } protected void cacheStatsAndCleaner() { SimpleTimer.addPeriodicEvent( "CacehFile:stats", STATS_UPDATE_FREQUENCY, new TimerEventPerformer() { public void perform( TimerEvent ev ) { stats.update(); // System.out.println( "cache file count = " + cache_files.size()); Iterator cf_it = cache_files.keySet().iterator(); while(cf_it.hasNext()){ ((CacheFileWithCache)cf_it.next()).updateStats(); } if ( --cleaner_ticks == 0 ){ cleaner_ticks = CACHE_CLEANER_TICKS; final Set dirty_files = new HashSet(); final long oldest =SystemTime.getCurrentTime() - DIRTY_CACHE_WRITE_MAX_AGE; try{ this_mon.enter(); if ( updated_cache_files != null ){ cache_files = updated_cache_files; updated_cache_files = null; } if ( cache_entries.size() > 0 ){ Iterator it = cache_entries.keySet().iterator(); while( it.hasNext()){ CacheEntry entry = (CacheEntry)it.next(); // System.out.println( "oldest entry = " + ( now - entry.getLastUsed())); if ( entry.isDirty()){ dirty_files.add( entry.getFile()); } } } // System.out.println( "cache file = " + cache_files.size() + ", torrent map = " + torrent_to_cache_file_map.size()); }finally{ this_mon.exit(); } Iterator it = dirty_files.iterator(); while( it.hasNext()){ CacheFileWithCache file = (CacheFileWithCache)it.next(); try{ TOTorrentFile tf = file.getTorrentFile(); long min_flush_size = -1; if ( tf != null ){ min_flush_size = tf.getTorrent().getPieceLength(); } file.flushOldDirtyData( oldest, min_flush_size ); }catch( CacheFileManagerException e ){ file.setPendingException( e ); // if this fails then the error should reoccur on a "proper" // flush later and be reported Debug.printStackTrace( e ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } } } } ); } // must be called when the cachefileimpl is synchronised to ensure that the file's // cache view and our cache view are consistent protected void addCacheSpace( CacheEntry new_entry ) throws CacheFileManagerException { try{ this_mon.enter(); cache_space_free -= new_entry.getLength(); // System.out.println( "Total cache space = " + cache_space_free ); cache_entries.put( new_entry, new_entry ); if ( DEBUG ){ CacheFileWithCache file = new_entry.getFile(); long total_cache_size = 0; int my_count = 0; Iterator it = cache_entries.keySet().iterator(); while( it.hasNext()){ CacheEntry entry = (CacheEntry)it.next(); total_cache_size += entry.getLength(); if ( entry.getFile() == file ){ my_count++; } } if ( my_count != file.cache.size()){ Debug.out( "Cache inconsistency: my count = " + my_count + ", file = " + file.cache.size()); throw( new CacheFileManagerException( null, "Cache inconsistency: counts differ")); }else{ //System.out.println( "Cache: file_count = " + my_count ); } if ( total_cache_size != cache_size - cache_space_free ){ Debug.out( "Cache inconsistency: used_size = " + total_cache_size + ", free = " + cache_space_free + ", size = " + cache_size ); throw( new CacheFileManagerException( null, "Cache inconsistency: sizes differ")); }else{ //System.out.println( "Cache: usage = " + total_cache_size ); } } }finally{ this_mon.exit(); } } protected void cacheEntryUsed( CacheEntry entry ) throws CacheFileManagerException { try{ this_mon.enter(); // note that the "get" operation update the MRU in cache_entries if ( cache_entries.get( entry ) == null ){ Debug.out( "Cache inconsistency: entry missing on usage" ); throw( new CacheFileManagerException( null, "Cache inconsistency: entry missing on usage")); }else{ entry.used(); } }finally{ this_mon.exit(); } } protected void releaseCacheSpace( CacheEntry entry ) throws CacheFileManagerException { entry.getBuffer().returnToPool(); try{ this_mon.enter(); cache_space_free += entry.getLength(); if ( cache_entries.remove( entry ) == null ){ Debug.out( "Cache inconsistency: entry missing on removal" ); throw( new CacheFileManagerException( null, "Cache inconsistency: entry missing on removal")); } /* if ( entry.getType() == CacheEntry.CT_READ_AHEAD ){ if ( entry.getUsageCount() < 2 ){ System.out.println( "ra: not used" ); }else{ System.out.println( "ra: used" ); } } */ // System.out.println( "Total cache space = " + cache_space_free ); }finally{ this_mon.exit(); } } protected long getCacheSize() { return( cache_size ); } protected long getCacheUsed() { long free = cache_space_free; if ( free < 0 ){ free = 0; } return( cache_size - free ); } protected void cacheBytesWritten( long num ) { try{ this_mon.enter(); cache_bytes_written += num; cache_write_count++; }finally{ this_mon.exit(); } } protected void cacheBytesRead( int num ) { try{ this_mon.enter(); cache_bytes_read += num; cache_read_count++; }finally{ this_mon.exit(); } } protected void fileBytesWritten( long num ) { try{ this_mon.enter(); file_bytes_written += num; file_write_count++; }finally{ this_mon.exit(); } } protected void fileBytesRead( int num ) { try{ this_mon.enter(); file_bytes_read += num; file_read_count++; }finally{ this_mon.exit(); } } protected long getBytesWrittenToCache() { return( cache_bytes_written ); } protected long getBytesWrittenToFile() { return( file_bytes_written ); } protected long getBytesReadFromCache() { return( cache_bytes_read ); } protected long getBytesReadFromFile() { return( file_bytes_read ); } public long getCacheReadCount() { return( cache_read_count ); } public long getCacheWriteCount() { return( cache_write_count ); } public long getFileReadCount() { return( file_read_count ); } public long getFileWriteCount() { return( file_write_count ); } protected void closeFile( CacheFileWithCache file ) { TOTorrentFile tf = file.getTorrentFile(); if ( tf != null && torrent_to_cache_file_map.get( tf ) != null ){ try{ this_mon.enter(); torrent_to_cache_file_map.remove( tf ); }finally{ this_mon.exit(); } } } protected boolean[] getBytesInCache(TOTorrent torrent, long[] absoluteOffsets, long[] lengths) { //sanity checks if(absoluteOffsets.length != lengths.length) throw new IllegalArgumentException("Offsets/Lengths mismatch"); long prevEnding = 0; for(int i = 0;i last) break; if(lockAcquired) { CacheFileWithCache cache_file = (CacheFileWithCache)torrent_to_cache_file_map.get( tf ); localCacheMap.put(tf, cache_file); } fileOffset += length; } } finally { if(lockAcquired) this_mon.exit(); } for (int i=firstFile;-1 < i && i last) break; if(cache_file != null) cache_file.getBytesInCache(results,absoluteOffsets,lengths); else // we have no cache file and thus no cache entries for(int j=0;j fileOffset) || (absoluteOffsets[j]+lengths[j] < fileOffset+length && absoluteOffsets[j]+lengths[j] > fileOffset)) results[j] = false; // no file -> no cache entry } if(!lockAcquired) // never found a matching torrentfile Arrays.fill(results, false); return results; } protected void rethrow( CacheFile file, FMFileManagerException e ) throws CacheFileManagerException { Throwable cause = e.getCause(); if ( cause != null ){ throw( new CacheFileManagerException( file, e.getMessage(), cause )); } throw( new CacheFileManagerException( file, e.getMessage(), e )); } public void generate( IndentWriter writer ) { writer.println( "Cache Manager" ); try{ writer.indent(); Iterator it; // grab a copy to avoid potential deadlock as we never take the manager monitor // and then the file's own monitor, always the other way around try{ this_mon.enter(); it = new ArrayList( cache_entries.keySet()).iterator(); }finally{ this_mon.exit(); } writer.println( "Entries = " + cache_entries.size()); Set files = new HashSet(); while( it.hasNext()){ CacheEntry entry = (CacheEntry)it.next(); CacheFileWithCache file = entry.getFile(); if( !files.contains( file )){ files.add( file ); TOTorrentFile torrentFile = file.getTorrentFile(); String fileLength = ""; try { fileLength = "" + file.getLength(); } catch (Exception e) { if (torrentFile != null) fileLength = "" + torrentFile.getLength(); } String hash = ""; try{ if (torrentFile != null) hash = ByteFormatter.encodeString( torrentFile.getTorrent().getHash()); }catch( Throwable e ){ } String name = file.getName(); writer.println("File: " + Debug.secretFileName(name) + ", size " + fileLength + ", torrent " + hash + ", access = " + file.getAccessMode()); } } }finally{ writer.exdent(); } } public void setFileLinks( TOTorrent torrent, CaseSensitiveFileMap links ) { file_manager.setFileLinks( torrent, links ); } } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCacheMT.java0000644000175000017500000003022211252111640031174 0ustar adrianadrian/* * Created on Sep 27, 2007 * Created by Paul Gardner * Copyright (C) 2007 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.cache.impl; import java.io.File; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.diskmanager.cache.CacheFile; import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerException; import com.aelitis.azureus.core.diskmanager.file.FMFile; import com.aelitis.azureus.core.diskmanager.file.FMFileManagerException; public class CacheFileWithoutCacheMT implements CacheFile { private static final int MAX_CLONES = 20; private static int num_clones; private static int max_clone_depth; private CacheFileManagerImpl manager; private FMFile base_file; private FMFile[] files; private int[] files_use_count; private TOTorrentFile torrent_file; private boolean moving; protected CacheFileWithoutCacheMT( CacheFileManagerImpl _manager, FMFile _file, TOTorrentFile _torrent_file ) { manager = _manager; base_file = _file; torrent_file = _torrent_file; files = new FMFile[]{ base_file }; files_use_count = new int[]{ 0 }; } public TOTorrentFile getTorrentFile() { return( torrent_file ); } public boolean exists() { return( base_file.exists()); } public void moveFile( File new_file ) throws CacheFileManagerException { try{ synchronized( this ){ moving = true; } while( true ){ synchronized( this ){ boolean surviving = false; for (int i=1;i 0 ){ surviving = true; break; } } if ( !surviving ){ for (int i=1;i 0 ){ surviving = true; break; } } if ( !surviving ){ for (int i=1;i 0 ){ count--; } files_use_count[i] = count; break; } } } } public void read( DirectByteBuffer[] buffers, long position, short policy ) throws CacheFileManagerException { int read_length = 0; for (int i=0;i 0 ){ random.nextBytes( buffer ); int to_write = rem>buffer.length?buffer.length:rem; fos.write( buffer, 0, to_write ); rem -= to_write; } fos.close(); source_file_rafs[i] = new RandomAccessFile( source_file, "r" ); } torrent = TOTorrentFactory.createFromFileOrDirWithFixedPieceLength( source_file_or_dir, new URL( "http://a.b.c/" ), piece_size ).create(); final TOTorrentFile[] torrent_files = torrent.getFiles(); // unfortunately the torrent's file order may not be ours... for ( int i=0;i 0 ){ Chunk chunk; if ( write_order == 0 ){ chunk = chunks.remove( 0 ); }else if ( write_order == 1 ){ chunk = chunks.remove( chunks.size() - 1 ); }else{ chunk = chunks.remove( random.nextInt( chunks.size())); } System.out.println( "Processing chunk " + chunk.getString()); List slices = new ArrayList( chunk.getSlices()); if ( write_order == 1 ){ Collections.reverse( slices ); } for ( ChunkSlice slice: slices ){ int file_index = slice.getFileIndex(); long file_offset = slice.getFileOffset(); long length = slice.getLength(); System.out.println( "Processing slice " + slice.getString() + "[file size=" + file_sizes[file_index]); DirectByteBuffer buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_OTHER, (int)length ); try{ RandomAccessFile raf = source_file_rafs[ file_index ]; raf.seek( file_offset ); raf.getChannel().read( buffer.getBuffer( DirectByteBuffer.SS_EXTERNAL )); buffer.flip( DirectByteBuffer.SS_EXTERNAL ); cache_files[file_index].write( buffer, file_offset ); }finally{ buffer.returnToPool(); } } chunk.setDone(); int chunk_piece_start = chunk.getPieceStart(); int chunk_piece_end = chunk.getPieceEnd(); for ( int i=chunk_piece_start;i<=chunk_piece_end;i++){ List pieces = piece_map[i]; boolean complete = true; for ( Chunk c: pieces ){ if ( !c.isDone()){ complete = false; break; } } if ( complete ){ for ( ChunkSlice slice: slices ){ if ( i >= slice.getPieceStart() && i <= slice.getPieceEnd()){ long piece_offset = i*piece_size; int piece_length; if ( i < piece_map.length - 1 ){ piece_length = piece_size; }else{ long total = torrent.getSize(); piece_length = (int)( total - ( total/piece_size )*piece_size ); if ( piece_length == 0 ){ piece_length = piece_size; } } DirectByteBuffer piece_data = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_OTHER, piece_length ); long pos = 0; int file_index = 0; int rem = piece_length; while( rem > 0 ){ long file_size = file_sizes[ file_index ]; long file_end = pos + file_size; long avail = file_end - piece_offset; if ( avail > 0 ){ int to_use = (int)Math.min( avail, rem ); long file_offset = piece_offset - pos; int lim = piece_data.limit( DirectByteBuffer.AL_OTHER ); piece_data.limit( DirectByteBuffer.AL_OTHER, piece_data.position( DirectByteBuffer.AL_OTHER ) + to_use ); cache_files[ file_index ].read( piece_data, file_offset, CacheFile.CP_NONE ); piece_data.limit( DirectByteBuffer.AL_OTHER, lim ); piece_offset += to_use; rem -= to_use; } file_index++; pos += file_size; } try{ cache_files[ slice.getFileIndex()].setPieceComplete( i, piece_data ); }finally{ piece_data.returnToPool(); } } } } } } for (int i=0;i 0 ){ int avail = (int)Math.min( len, buffer1.length ); int r1 = fis1.read( buffer1, 0, avail ); int r2 = fis2.read( buffer2, 0, avail ); if ( r1 != r2 ){ System.err.println( "read lens different: file=" + i + ",pos=" + pos ); failed = true; break; }else{ if ( Arrays.equals( buffer1, buffer2 )){ len -= r1; pos += r1; }else{ int diff_at = -1; for (int j=0;j quanitize_to*quanitize_to_max_consec_read ){ len = quanitize_to*quanitize_to_max_consec_read; } DirectByteBuffer buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_OTHER,len ); System.out.println( "read:" + start + "/" + len ); cf.read( buffer, start, CacheFile.CP_READ_CACHE ); buffer.position(DirectByteBuffer.SS_CACHE, 0); byte[] data_read = new byte[len]; buffer.get( DirectByteBuffer.SS_CACHE, data_read ); for (int i=0;i quanitize_to*quanitize_to_max_consec_write ){ len = quanitize_to*quanitize_to_max_consec_write; } System.out.println( "write:" + start + "/" + len ); DirectByteBuffer buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_OTHER,len ); for (int i=0;i slices; private int piece_start; private int piece_end; private boolean is_done; protected Chunk( long _offset, long _length, List _slices ) { offset = _offset; length = _length; slices = _slices; } protected List getSlices() { return( slices ); } protected void setPieces( int _piece_start, int _piece_end ) { piece_start = _piece_start; piece_end = _piece_end; } protected int getPieceStart() { return( piece_start ); } protected int getPieceEnd() { return( piece_end ); } protected void setDone() { is_done = true; } protected boolean isDone() { return( is_done ); } protected String getString() { String str = ""; for ( ChunkSlice s: slices ){ str += (str.length()==0?"":",") + s.getString(); } return( "offset=" + offset + ",length=" + length + ",slices={" + str + "}" ); } } protected static class ChunkSlice { private int file_index; private long file_offset; private long length; private int piece_start; private int piece_end; protected ChunkSlice( int _file_index, long _file_offset, long _length, int _piece_start, int _piece_end ) { file_index = _file_index; file_offset = _file_offset; length = _length; piece_start = _piece_start; piece_end = _piece_end; } protected int getFileIndex() { return( file_index ); } protected long getFileOffset() { return( file_offset ); } protected long getLength() { return( length ); } protected int getPieceStart() { return( piece_start ); } protected int getPieceEnd() { return( piece_end ); } protected String getString() { return( "fi=" + file_index + ",fo=" + file_offset + ",len=" + length + ",ps=" + piece_start + ",pe=" + piece_end); } } } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerStatsImpl.java0000644000175000017500000001100510655060142031563 0ustar adrianadrian/* * Created on 06-Aug-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.cache.impl; /** * @author parg * */ import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.Average; import com.aelitis.azureus.core.diskmanager.cache.*; import org.gudy.azureus2.core3.util.*; public class CacheFileManagerStatsImpl implements CacheFileManagerStats { protected CacheFileManagerImpl manager; // average over 10 seconds protected Average cache_read_average = Average.getInstance(CacheFileManagerImpl.STATS_UPDATE_FREQUENCY, 10); protected Average cache_write_average = Average.getInstance(CacheFileManagerImpl.STATS_UPDATE_FREQUENCY, 10); protected Average file_read_average = Average.getInstance(CacheFileManagerImpl.STATS_UPDATE_FREQUENCY, 10); // file writes are bursty so use a lower average time protected Average file_write_average = Average.getInstance(CacheFileManagerImpl.STATS_UPDATE_FREQUENCY, 5); protected long last_cache_read; protected long last_cache_write; protected long last_file_read; protected long last_file_write; protected AEMonitor this_mon = new AEMonitor( "CacheFileManagerStats" ); protected CacheFileManagerStatsImpl( CacheFileManagerImpl _manager ) { manager = _manager; } protected void update() { try{ this_mon.enter(); // cache read long cache_read = manager.getBytesReadFromCache(); long cache_read_diff = cache_read - last_cache_read; last_cache_read = cache_read; cache_read_average.addValue( cache_read_diff ); // cache write long cache_write = manager.getBytesWrittenToCache(); long cache_write_diff = cache_write - last_cache_write; last_cache_write = cache_write; cache_write_average.addValue( cache_write_diff ); // file read long file_read = manager.getBytesReadFromFile(); long file_read_diff = file_read - last_file_read; last_file_read = file_read; file_read_average.addValue( file_read_diff ); // file write long file_write = manager.getBytesWrittenToFile(); long file_write_diff = file_write - last_file_write; last_file_write = file_write; file_write_average.addValue( file_write_diff ); }finally{ this_mon.exit(); } } public long getSize() { return( manager.getCacheSize()); } public long getUsedSize() { return( manager.getCacheUsed()); } public long getBytesWrittenToCache() { return( manager.getBytesWrittenToCache()); } public long getBytesWrittenToFile() { return( manager.getBytesWrittenToFile()); } public long getBytesReadFromCache() { return( manager.getBytesReadFromCache()); } public long getBytesReadFromFile() { return( manager.getBytesReadFromFile()); } public long getAverageBytesWrittenToCache() { return( cache_write_average.getAverage()); } public long getAverageBytesWrittenToFile() { return( file_write_average.getAverage() ); } public long getAverageBytesReadFromCache() { return( cache_read_average.getAverage() ); } public long getAverageBytesReadFromFile() { return( file_read_average.getAverage() ); } public long getCacheReadCount() { return( manager.getCacheReadCount()); } public long getCacheWriteCount() { return( manager.getCacheWriteCount()); } public long getFileReadCount() { return( manager.getFileReadCount()); } public long getFileWriteCount() { return( manager.getFileWriteCount()); } public boolean[] getBytesInCache(TOTorrent torrent, long[] absoluteOffsets, long[] lengths) { return manager.getBytesInCache( torrent, absoluteOffsets, lengths); } } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/cache/CacheFile.java0000644000175000017500000000742111252111640025467 0ustar adrianadrian/* * Created on 03-Aug-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.cache; import java.io.File; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.util.DirectByteBuffer; /** * @author parg * */ public interface CacheFile { public static final int CT_LINEAR = 1; public static final int CT_COMPACT = 2; public static final int CT_PIECE_REORDER = 3; public static final int CF_READ = 1; public static final int CF_WRITE = 2; public static final short CP_NONE = 0x0000; public static final short CP_READ_CACHE = 0x0001; public static final short CP_FLUSH = 0x0002; public TOTorrentFile getTorrentFile(); public boolean exists(); public void moveFile( File new_file ) throws CacheFileManagerException; public void renameFile( String new_name ) throws CacheFileManagerException; public void setAccessMode( int mode ) throws CacheFileManagerException; public int getAccessMode(); public void setStorageType( int type ) throws CacheFileManagerException; public int getStorageType(); public long getLength() throws CacheFileManagerException; public long compareLength( long compare_to ) throws CacheFileManagerException; public void setLength( long length ) throws CacheFileManagerException; public void setPieceComplete( int piece_number, DirectByteBuffer piece_data ) throws CacheFileManagerException; public void read( DirectByteBuffer buffer, long offset, short policy ) throws CacheFileManagerException; public void read( DirectByteBuffer[] buffers, long offset, short policy ) throws CacheFileManagerException; public void write( DirectByteBuffer buffer, long position ) throws CacheFileManagerException; public void write( DirectByteBuffer[] buffers, long position ) throws CacheFileManagerException; /** * writes the block to the cache and gives control of the buffer to the cache. * @param buffer * @param position * @throws CacheFileManagerException write failed and buffer *not* taken - i.e. caller must de-allocate */ public void writeAndHandoverBuffer( DirectByteBuffer buffer, long position ) throws CacheFileManagerException; public void writeAndHandoverBuffers( DirectByteBuffer[] buffers, long position ) throws CacheFileManagerException; /** * flushes the cache to disk but retains entries * @throws CacheFileManagerException */ public void flushCache() throws CacheFileManagerException; /** * flushes the cache and discards entries * @throws CacheFileManagerException */ public void clearCache() throws CacheFileManagerException; public void close() throws CacheFileManagerException; public boolean isOpen(); public void delete() throws CacheFileManagerException; } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerStats.java0000644000175000017500000000351410655060142030006 0ustar adrianadrian/* * Created on 06-Aug-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.cache; /** * @author parg * */ import org.gudy.azureus2.core3.torrent.TOTorrent; public interface CacheFileManagerStats { public long getSize(); public long getUsedSize(); public long getBytesWrittenToCache(); public long getBytesWrittenToFile(); public long getBytesReadFromCache(); public long getBytesReadFromFile(); public long getAverageBytesWrittenToCache(); public long getAverageBytesWrittenToFile(); public long getAverageBytesReadFromCache(); public long getAverageBytesReadFromFile(); public long getCacheReadCount(); public long getCacheWriteCount(); public long getFileReadCount(); public long getFileWriteCount(); // returns the number of bytes in the requested range that are in cache public boolean[] getBytesInCache(TOTorrent torrent, long[] absoluteOffsets, long[] lengths); } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/cache/CacheFileManager.java0000644000175000017500000000267610410023006026762 0ustar adrianadrian/* * Created on 03-Aug-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.cache; import java.io.File; import org.gudy.azureus2.core3.torrent.TOTorrent; import com.aelitis.azureus.core.util.CaseSensitiveFileMap; /** * @author parg * */ public interface CacheFileManager { public CacheFile createFile( CacheFileOwner owner, File file, int type ) throws CacheFileManagerException; public CacheFileManagerStats getStats(); public void setFileLinks( TOTorrent torrent, CaseSensitiveFileMap links ); } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerFactory.java0000644000175000017500000000442610373051014030315 0ustar adrianadrian/* * Created on 03-Aug-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.cache; /** * @author parg * */ import org.gudy.azureus2.core3.util.*; public class CacheFileManagerFactory { public static final String DEFAULT_MANAGER = "com.aelitis.azureus.core.diskmanager.cache.impl.CacheFileManagerImpl"; private static CacheFileManager manager; private static AEMonitor class_mon = new AEMonitor("CacheFileManagerFactory"); public static CacheFileManager getSingleton() throws CacheFileManagerException { return( getSingleton( null )); } public static CacheFileManager getSingleton( String explicit_implementation ) throws CacheFileManagerException { try{ class_mon.enter(); if ( manager == null ){ String impl = explicit_implementation; if ( impl == null ){ impl = System.getProperty( "com.aelitis.azureus.core.diskmanager.cache.manager"); } if ( impl == null ){ impl = DEFAULT_MANAGER; } try{ Class impl_class = CacheFileManagerFactory.class.getClassLoader().loadClass( impl ); manager = (CacheFileManager)impl_class.newInstance(); }catch( Throwable e ){ throw( new CacheFileManagerException( null, "Failed to instantiate manager '" + impl + "'", e )); } } return( manager ); }finally{ class_mon.exit(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerException.java0000644000175000017500000000327411012741354030650 0ustar adrianadrian/* * Created on 03-Aug-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.cache; /** * @author parg * */ public class CacheFileManagerException extends Exception { private CacheFile file; private int fail_index; public CacheFileManagerException( CacheFile _file, String _str ) { super(_str); file = _file; } public CacheFileManagerException( CacheFile _file, String _str, Throwable _cause ) { super( _str, _cause ); file = _file; } public CacheFileManagerException( CacheFile _file, String _str, Throwable _cause, int _fail_index ) { super( _str, _cause ); file = _file; fail_index = _fail_index; } public CacheFile getFile() { return( file ); } public int getFailIndex() { return( fail_index ); } } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/cache/CacheFileOwner.java0000644000175000017500000000271611011737132026507 0ustar adrianadrian/* * Created on 03-Aug-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.cache; /** * @author parg * */ import java.io.File; import org.gudy.azureus2.core3.torrent.TOTorrentFile; public interface CacheFileOwner { public static final int CACHE_MODE_NORMAL = 1; public static final int CACHE_MODE_NO_CACHE = 2; public static final int CACHE_MODE_EXPERIMENTAL = 3; public String getCacheFileOwnerName(); public TOTorrentFile getCacheFileTorrentFile(); public File getCacheFileControlFileDir( ); public int getCacheMode(); } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/file/0000755000175000017500000000000011310377624022704 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/file/FMFileManagerException.java0000644000175000017500000000216511012741352030017 0ustar adrianadrian/* * File : FMFileManagerException.java * Created : 12-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.diskmanager.file; /** * @author parg * */ public class FMFileManagerException extends Exception { public FMFileManagerException( String str ) { super(str); } public FMFileManagerException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/file/FMFileOwner.java0000644000175000017500000000214111011737130025650 0ustar adrianadrian/* * File : FMFileOwner.java * Created : 01-Mar-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.diskmanager.file; import java.io.File; import org.gudy.azureus2.core3.torrent.TOTorrentFile; /** * @author parg * */ public interface FMFileOwner { public String getName(); public TOTorrentFile getTorrentFile(); public File getControlFileDir( ); } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/file/impl/0000755000175000017500000000000011310377624023645 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/file/impl/FMFileManagerImpl.java0000644000175000017500000002016110734522044027724 0ustar adrianadrian/* * File : FMFileManagerImpl.java * Created : 12-Feb-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.diskmanager.file.impl; /** * @author parg * */ import java.util.*; import java.io.File; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.config.*; import com.aelitis.azureus.core.diskmanager.file.*; import com.aelitis.azureus.core.util.CaseSensitiveFileMap; public class FMFileManagerImpl implements FMFileManager { public static final boolean DEBUG = false; protected static FMFileManagerImpl singleton; protected static AEMonitor class_mon = new AEMonitor( "FMFileManager:class" ); public static FMFileManager getSingleton() { try{ class_mon.enter(); if ( singleton == null ){ singleton = new FMFileManagerImpl(); } return( singleton ); }finally{ class_mon.exit(); } } protected LinkedHashMap map; protected AEMonitor map_mon = new AEMonitor( "FMFileManager:Map"); protected HashMap links = new HashMap(); protected AEMonitor links_mon = new AEMonitor( "FMFileManager:Links"); protected boolean limited; protected int limit_size; protected AESemaphore close_queue_sem; protected List close_queue; protected AEMonitor close_queue_mon = new AEMonitor( "FMFileManager:CQ"); protected List files; protected AEMonitor files_mon = new AEMonitor( "FMFileManager:File"); protected FMFileManagerImpl() { limit_size = COConfigurationManager.getIntParameter( "File Max Open" ); limited = limit_size > 0; if ( DEBUG ){ System.out.println( "FMFileManager::init: limit = " + limit_size ); files = new ArrayList(); } map = new LinkedHashMap( limit_size, (float)0.75, true ); // ACCESS order selected - this means oldest if ( limited ){ close_queue_sem = new AESemaphore("FMFileManager::closeqsem"); close_queue = new LinkedList(); Thread t = new AEThread("FMFileManager::closeQueueDispatcher") { public void runSupport() { closeQueueDispatch(); } }; t.setDaemon(true); t.start(); } } protected CaseSensitiveFileMap getLinksEntry( TOTorrent torrent ) { Object links_key; try{ links_key = torrent.getHashWrapper(); }catch( Throwable e ){ Debug.printStackTrace(e); links_key = ""; } CaseSensitiveFileMap links_entry = (CaseSensitiveFileMap)links.get( links_key ); if ( links_entry == null ){ links_entry = new CaseSensitiveFileMap(); links.put( links_key, links_entry ); } return( links_entry ); } public void setFileLinks( TOTorrent torrent, CaseSensitiveFileMap new_links ) { try{ links_mon.enter(); CaseSensitiveFileMap links_entry = getLinksEntry( torrent ); Iterator it = new_links.keySetIterator(); while( it.hasNext()){ File source = (File)it.next(); File target = (File)new_links.get(source); // System.out.println( "setLink:" + source + " -> " + target ); if ( target != null && !source.equals(target)){ links_entry.put( source, target ); }else{ links_entry.remove( source ); } } }finally{ links_mon.exit(); } } public File getFileLink( TOTorrent torrent, File file ) { try{ links_mon.enter(); CaseSensitiveFileMap links_entry = getLinksEntry( torrent ); File res = (File)links_entry.get( file ); if ( res == null ){ res = file; } // System.out.println( "getLink:" + file + " -> " + res ); return( res ); }finally{ links_mon.exit(); } } public FMFile createFile( FMFileOwner owner, File file, int type ) throws FMFileManagerException { FMFile res; if ( AEDiagnostics.USE_DUMMY_FILE_DATA ){ res = new FMFileTestImpl( owner, this, file, type ); }else{ if ( limited ){ res = new FMFileLimited( owner, this, file, type ); }else{ res = new FMFileUnlimited( owner, this, file, type ); } } if (DEBUG){ try{ files_mon.enter(); files.add( res ); }finally{ files_mon.exit(); } } return( res ); } protected void getSlot( FMFileLimited file ) { // must close the oldest file outside sync block else we'll get possible deadlock FMFileLimited oldest_file = null; try{ map_mon.enter(); if (DEBUG ){ System.out.println( "FMFileManager::getSlot: " + file.getName() +", map_size = " + map.size()); } if ( map.size() >= limit_size ){ Iterator it = map.keySet().iterator(); oldest_file = (FMFileLimited)it.next(); it.remove(); } map.put( file, file ); }finally{ map_mon.exit(); } if ( oldest_file != null ){ closeFile( oldest_file ); } } protected void releaseSlot( FMFileLimited file ) { if ( DEBUG ){ System.out.println( "FMFileManager::releaseSlot: " + file.getName()); } try{ map_mon.enter(); map.remove( file ); }finally{ map_mon.exit(); } } protected void usedSlot( FMFileLimited file ) { if ( DEBUG ){ System.out.println( "FMFileManager::usedSlot: " + file.getName()); } try{ map_mon.enter(); // only update if already present - might not be due to delay in // closing files if ( map.containsKey( file )){ map.put( file, file ); // update MRU } }finally{ map_mon.exit(); } } protected void closeFile( FMFileLimited file ) { if ( DEBUG ){ System.out.println( "FMFileManager::closeFile: " + file.getName()); } try{ close_queue_mon.enter(); close_queue.add( file ); }finally{ close_queue_mon.exit(); } close_queue_sem.release(); } protected void closeQueueDispatch() { while(true){ if ( DEBUG ){ close_queue_sem.reserve(1000); }else{ close_queue_sem.reserve(); } FMFileLimited file = null; try{ close_queue_mon.enter(); if ( close_queue.size() > 0 ){ file = (FMFileLimited)close_queue.remove(0); if ( DEBUG ){ System.out.println( "FMFileManager::closeQ: " + file.getName() + ", rem = " + close_queue.size()); } } }finally{ close_queue_mon.exit(); } if ( file != null ){ try{ file.close(false); }catch( Throwable e ){ Debug.printStackTrace( e ); } } if ( DEBUG ){ try{ files_mon.enter(); int open = 0; for (int i=0;i= MIN_PIECES_REORDERABLE ){ piece_size = (int)_torrent_file.getTorrent().getPieceLength(); TOTorrent torrent = _torrent_file.getTorrent(); long file_length = _torrent_file.getLength(); long file_offset_in_torrent = 0; TOTorrentFile[] files = torrent.getFiles(); for (int i=0;i= MIN_PIECES_REORDERABLE ){ if ( piece_map == null ){ readConfig(); } return( current_length ); }else{ return( delegate.getLength(raf)); } } public void setLength( RandomAccessFile raf, long length ) throws FMFileManagerException { if ( num_pieces >= MIN_PIECES_REORDERABLE ){ if ( piece_map == null ){ readConfig(); } if ( current_length != length ){ current_length = length; setDirty(); } }else{ delegate.setLength( raf, length ); } } protected long getPieceOffset( RandomAccessFile raf, int piece_number, boolean allocate_if_needed ) throws FMFileManagerException { if ( piece_map == null ){ readConfig(); } int index = getPieceIndex( raf, piece_number, allocate_if_needed ); if ( index < 0 ){ return( index ); }else if ( index == 0 ){ return( 0 ); }else if ( index == 1 ){ return( first_piece_length ); }else{ return( first_piece_length + ((index-1)*piece_size )); } } protected int readWritePiece( RandomAccessFile raf, DirectByteBuffer[] buffers, int piece_number, int piece_offset, boolean is_read ) throws FMFileManagerException { String str = is_read?"read":"write"; if ( piece_number >= num_pieces ){ throw( new FMFileManagerException( "Attempt to " + str + " piece " + piece_number + ": last=" + num_pieces )); } int this_piece_size = piece_number==0?first_piece_length:(piece_number==(num_pieces-1)?last_piece_length:piece_size); final int piece_space = this_piece_size - piece_offset; if ( piece_space <= 0 ){ throw( new FMFileManagerException( "Attempt to " + str + " piece " + piece_number + ", offset " + piece_offset + " - no space in piece" )); } int rem_space = piece_space; int[] limits = new int[buffers.length]; for ( int i=0;i rem_space ){ buffer.limit( SS_FILE, buffer.position( SS_FILE ) + rem_space ); rem_space = 0; }else{ rem_space -= rem; } } try{ long piece_start = getPieceOffset( raf, piece_number, !is_read ); if ( TRACE ){ System.out.println( str + " to " + piece_number + "/" + piece_offset + "/" + this_piece_size + "/" + piece_space + "/" + rem_space + "/" + piece_start ); } if ( piece_start == -1 ){ return( 0 ); } long piece_io_position = piece_start + piece_offset; if ( is_read ){ delegate.read( raf, buffers, piece_io_position ); }else{ delegate.write( raf, buffers, piece_io_position ); } return( piece_space - rem_space ); }finally{ for ( int i=0;i current_length ){ current_length = position + total_length; setDirty(); } long current_position = position; while( total_length > 0 ){ int piece_number; int piece_offset; if ( current_position < first_piece_length ){ piece_number = 0; piece_offset = (int)current_position; }else{ long offset = current_position - first_piece_length; piece_number = (int)( offset / piece_size ) + 1; piece_offset = (int)( offset % piece_size ); } int count = readWritePiece( raf, buffers, piece_number, piece_offset, is_read ); if ( count == 0 ){ if ( is_read ){ // fill remaining space with zeros so we're consistent for ( DirectByteBuffer buffer: buffers ){ ByteBuffer bb = buffer.getBuffer( SS_FILE ); int rem = bb.remaining(); bb.put( new byte[rem] ); } }else{ throw( new FMFileManagerException( "partial write operation" )); } return; } total_length -= count; current_position += count; } } public void read( RandomAccessFile raf, DirectByteBuffer[] buffers, long position ) throws FMFileManagerException { if ( num_pieces >= MIN_PIECES_REORDERABLE ){ readWrite( raf, buffers, position, true ); }else{ delegate.read( raf, buffers, position ); } } public void write( RandomAccessFile raf, DirectByteBuffer[] buffers, long position ) throws FMFileManagerException { if ( num_pieces >= MIN_PIECES_REORDERABLE ){ readWrite( raf, buffers, position, false ); }else{ delegate.write( raf, buffers, position ); } } public void flush() throws FMFileManagerException { if ( num_pieces >= MIN_PIECES_REORDERABLE ){ if ( dirt_state != DIRT_CLEAN ){ writeConfig(); } }else{ delegate.flush(); } } public void setPieceComplete( RandomAccessFile raf, int piece_number, DirectByteBuffer piece_data ) throws FMFileManagerException { if ( num_pieces >= MIN_PIECES_REORDERABLE ){ // note that it is possible to reduce the number of piece moves at the expense // of complicating the allocation process. We have the advantage here of having // the piece data already in memory. We also don't want to defer a mass of IO // until the download completes, hence interfering with other stuff such as // streaming. So I'm going to stick with this approach. piece_number = piece_number - first_piece_number; if ( TRACE ){ System.out.println( "pieceComplete: " + piece_number ); } if ( piece_number >= next_piece_index ){ // nothing stored yet in the location where this piece belongs return; } int store_index = getPieceIndex( raf, piece_number, false ); if ( store_index == -1 ){ throw( new FMFileManagerException( "piece marked as complete but not yet allocated" )); } if ( piece_number == store_index ){ // already in the right place if ( TRACE ){ System.out.println( " already in right place" ); } return; } // find out what's currently stored in the place this piece should be int swap_piece_number = piece_reverse_map[ piece_number ]; if ( swap_piece_number < 1 ){ throw( new FMFileManagerException( "Inconsistent: failed to find piece to swap" )); } if ( TRACE ){ System.out.println( " swapping " + piece_number + " and " + swap_piece_number + ": " + piece_number + " <-> " + store_index ); } DirectByteBuffer temp_buffer = DirectByteBufferPool.getBuffer( SS_FILE, piece_size ); DirectByteBuffer[] temp_buffers = new DirectByteBuffer[]{ temp_buffer }; try{ long store_offset = first_piece_length + ((store_index-1)*piece_size ); long swap_offset = first_piece_length + ((piece_number-1)*piece_size ); delegate.read( raf, temp_buffers, swap_offset ); piece_data.position( SS_FILE, 0 ); delegate.write( raf, new DirectByteBuffer[]{ piece_data }, swap_offset ); temp_buffer.position( SS_FILE, 0 ); delegate.write( raf, temp_buffers, store_offset ); piece_map[ piece_number ] = piece_number; piece_reverse_map[ piece_number ] = piece_number; piece_map[ swap_piece_number ] = store_index; piece_reverse_map[ store_index ] = swap_piece_number; setDirty(); if ( piece_number == num_pieces - 1 ){ long file_length = swap_offset + last_piece_length; if ( delegate.getLength( raf ) > file_length ){ if ( TRACE ){ System.out.println( " truncating file to correct length of " + file_length ); } delegate.setLength( raf, file_length ); } } }finally{ temp_buffer.returnToPool(); } }else{ delegate.setPieceComplete( raf, piece_number, piece_data ); } } protected int getPieceIndex( RandomAccessFile raf, int piece_number, boolean allocate_if_needed ) throws FMFileManagerException { int store_index = piece_map[ piece_number ]; if ( store_index == -1 && allocate_if_needed ){ store_index = next_piece_index++; if ( TRACE ){ System.out.println( "getPiece(" + piece_number + "): allocated " + store_index ); } piece_map[ piece_number ] = store_index; piece_reverse_map[ store_index ] = piece_number; if ( piece_number != store_index ){ // not already in the right place, see if the piece we just allocated // corresponds to a piece previously allocated and swap if so int swap_index = piece_map[ store_index ]; if ( swap_index > 0 ){ if ( TRACE ){ System.out.println( " piece number " + store_index + " already allocated at " + swap_index + ": moving piece "); } DirectByteBuffer temp_buffer = DirectByteBufferPool.getBuffer( SS_FILE, piece_size ); DirectByteBuffer[] temp_buffers = new DirectByteBuffer[]{ temp_buffer }; try{ long store_offset = first_piece_length + ((store_index-1)*piece_size ); long swap_offset = first_piece_length + ((swap_index-1)*piece_size ); delegate.read( raf, temp_buffers, swap_offset ); temp_buffer.position( SS_FILE, 0 ); delegate.write( raf, temp_buffers, store_offset ); piece_map[ store_index ] = store_index; piece_reverse_map[ store_index ] = store_index; piece_map[ piece_number ] = swap_index; piece_reverse_map[ swap_index ] = piece_number; if ( store_index == num_pieces - 1 ){ long file_length = store_offset + last_piece_length; if ( delegate.getLength( raf ) > file_length ){ if ( TRACE ){ System.out.println( " truncating file to correct length of " + file_length ); } delegate.setLength( raf, file_length ); } } store_index = swap_index; }finally{ temp_buffer.returnToPool(); } } } setDirty(); } // System.out.println( "getPiece: " + piece_number + "->" + store_index ); return( store_index ); } protected void readConfig() throws FMFileManagerException { piece_map = new int[num_pieces]; piece_reverse_map = new int[num_pieces]; if ( dirt_state == DIRT_NEVER_WRITTEN ){ Arrays.fill( piece_map, -1 ); piece_map[0] = 0; piece_reverse_map[0] = 0; next_piece_index = 1; current_length = 0; }else{ Map map = FileUtil.readResilientFile( control_dir, control_file, false ); Long l_len = (Long)map.get( "len" ); Long l_next = (Long)map.get( "next" ); byte[] piece_bytes = (byte[])map.get( "pieces" ); if ( l_len == null || l_next == null || piece_bytes == null ){ throw( new FMFileManagerException( "Failed to read control file " + new File( control_dir, control_file ).getAbsolutePath() + ": map invalid - " + map )); } current_length = l_len.longValue(); next_piece_index = l_next.intValue(); if ( piece_bytes.length != num_pieces * 4 ){ throw( new FMFileManagerException( "Failed to read control file " + new File( control_dir, control_file ).getAbsolutePath() + ": piece bytes invalid" )); } int pos = 0; for (int i=0;i= 0 && ( now - dirt_time >= DIRT_FLUSH_MILLIS )){ writeConfig(); } } } } protected void writeConfig() throws FMFileManagerException { if ( piece_map == null ){ readConfig(); } Map map = new HashMap(); map.put( "len", new Long( current_length )); map.put( "next", new Long( next_piece_index )); byte[] pieces_bytes = new byte[ piece_map.length * 4 ]; int pos = 0; for (int i=0;i> 24 ); pieces_bytes[pos++] = (byte)( value >> 16 ); pieces_bytes[pos++] = (byte)( value >> 8 ); pieces_bytes[pos++] = (byte)( value ); } } map.put( "pieces", pieces_bytes ); if ( !control_dir.exists()){ control_dir.mkdirs(); } if ( !FileUtil.writeResilientFileWithResult( control_dir, control_file, map )){ throw( new FMFileManagerException( "Failed to write control file " + new File( control_dir, control_file ).getAbsolutePath())); } if ( TRACE ){ System.out.println( "WriteConfig: length=" + current_length + ", next=" + next_piece_index ); } dirt_state = DIRT_CLEAN; dirt_time = -1; } public String getString() { return( "reorderer" ); } }azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessController.java0000644000175000017500000002340211264673734031012 0ustar adrianadrian/* * Created on 30-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.file.impl; import java.io.File; import java.io.RandomAccessFile; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.DirectByteBufferPool; import org.gudy.azureus2.core3.util.StringInterner; import com.aelitis.azureus.core.diskmanager.file.FMFile; import com.aelitis.azureus.core.diskmanager.file.FMFileManagerException; public class FMFileAccessController implements FMFileAccess { private static final String REORDER_SUFFIX = ".2"; private FMFileImpl owner; private int type = FMFile.FT_LINEAR; private File controlPath; private String controlFileName; private FMFileAccess file_access; protected FMFileAccessController( FMFileImpl _file, int _target_type ) throws FMFileManagerException { // _target_type = FMFile.FT_PIECE_REORDER; owner = _file; // actual file shouldn't exist for change to occur - it is the responsibility // of the caller to delete the file first and take consequent actions (in // particular force recheck the file to ensure that the loss in save state // is represented in the resume view of the world ) // in the future, if we support format conversion, this obviously changes setControlFile(); if ( controlPath == null ){ // Debug.out( "No control file" ); in optimised environments we don't support compact and return null here if ( _target_type == FMFile.FT_LINEAR ){ file_access = new FMFileAccessLinear( owner ); }else{ throw( new FMFileManagerException( "Compact storage not supported: no control file available" )); } }else{ if ( new File( controlPath, controlFileName ).exists()){ type = FMFile.FT_COMPACT; }else if ( new File( controlPath, controlFileName + REORDER_SUFFIX ).exists()){ type = FMFile.FT_PIECE_REORDER; }else{ if ( _target_type == FMFile.FT_PIECE_REORDER && !owner.getLinkedFile().exists()){ type = FMFile.FT_PIECE_REORDER; }else{ type = FMFile.FT_LINEAR; } } if ( type == FMFile.FT_LINEAR ){ file_access = new FMFileAccessLinear( owner ); }else if ( type == FMFile.FT_COMPACT ){ file_access = new FMFileAccessCompact( owner.getOwner().getTorrentFile(), controlPath, controlFileName, new FMFileAccessLinear( owner )); }else{ file_access = new FMFileAccessPieceReorderer( owner.getOwner().getTorrentFile(), controlPath, controlFileName + REORDER_SUFFIX, new FMFileAccessLinear( owner )); } if ( type != _target_type ){ convert( _target_type ); } } } protected void convert( int target_type ) throws FMFileManagerException { if ( type == FMFile.FT_PIECE_REORDER || target_type == FMFile.FT_PIECE_REORDER ){ throw( new FMFileManagerException( "Conversion to/from piece-reorder not supported" )); } File file = owner.getLinkedFile(); RandomAccessFile raf = null; boolean ok = false; try{ FMFileAccess target_access; if ( target_type == FMFile.FT_LINEAR ){ target_access = new FMFileAccessLinear( owner ); }else{ target_access = new FMFileAccessCompact( owner.getOwner().getTorrentFile(),controlPath, controlFileName, new FMFileAccessLinear( owner )); } if ( file.exists()){ raf = new RandomAccessFile( file, FMFileImpl.WRITE_ACCESS_MODE); // due to the simplistic implementation of compact we only actually need to deal with // the last piece of the file (first piece is in the right place already) FMFileAccessCompact compact_access; if ( target_type == FMFile.FT_LINEAR ){ compact_access = (FMFileAccessCompact)file_access; }else{ compact_access = (FMFileAccessCompact)target_access; } long length = file_access.getLength( raf ); long last_piece_start = compact_access.getLastPieceStart(); long last_piece_length = compact_access.getLastPieceLength(); // see if we have any potential data for the last piece if ( last_piece_length > 0 && length > last_piece_start ){ long data_length = length - last_piece_start; if ( data_length > last_piece_length ){ Debug.out("data length inconsistent: len=" + data_length + ",limit=" + last_piece_length ); data_length = last_piece_length; } DirectByteBuffer buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_FILE, (int)data_length ); try{ file_access.read( raf, new DirectByteBuffer[]{ buffer }, last_piece_start ); // see if we need to truncate if ( target_type == FMFile.FT_COMPACT ){ long first_piece_length = compact_access.getFirstPieceLength(); long physical_length = raf.length(); if ( physical_length > first_piece_length ){ raf.setLength( first_piece_length ); } } buffer.flip( DirectByteBuffer.AL_FILE ); target_access.write( raf, new DirectByteBuffer[]{ buffer }, last_piece_start ); }finally{ buffer.returnToPool(); } }else{ // no last piece, truncate after the first piece if ( target_type == FMFile.FT_COMPACT ){ long first_piece_length = compact_access.getFirstPieceLength(); long physical_length = raf.length(); if ( physical_length > first_piece_length ){ raf.setLength( first_piece_length ); } } } target_access.setLength( raf, length ); target_access.flush(); } type = target_type; file_access = target_access; ok = true; }catch( Throwable e ){ Debug.printStackTrace( e ); throw( new FMFileManagerException( "convert fails", e )); }finally{ try{ if ( raf != null ){ try{ raf.close(); }catch( Throwable e ){ // override original exception if there isn't one if ( ok ){ ok = false; throw( new FMFileManagerException( "convert fails", e )); } } } }finally{ if ( !ok ){ // conversion failed - replace with linear access, caller is responsible for // handling this (marking file requiring recheck) type = FMFile.FT_LINEAR; file_access = new FMFileAccessLinear( owner ); } if ( type == FMFile.FT_LINEAR ){ new File(controlPath,controlFileName).delete(); } } } } protected void setControlFile() { TOTorrentFile tf = owner.getOwner().getTorrentFile(); if ( tf == null ){ controlFileName = null; controlPath = null; } TOTorrent torrent = tf.getTorrent(); TOTorrentFile[] files = torrent.getFiles(); int file_index = -1; for (int i=0;i" }); }finally{ file_map_mon.exit(); } } private void reserveAccess( String reason ) throws FMFileManagerException { if ( clone ){ return; } try{ file_map_mon.enter(); //System.out.println( "FMFile::reserveAccess:" + canonical_path + "("+ owner.getName() + ")" + " [" + (access_mode==FM_WRITE?"write":"read") + "]" + " - " + Debug.getCompressedStackTrace()); List owners = (List)file_map.get( canonical_path ); Object[] my_entry = null; if ( owners == null ){ Debug.out( "reserveAccess fail" ); throw( new FMFileManagerException( "File '"+canonical_path+"' has not been reserved (no entries), '" + owner.getName()+"'")); } for (Iterator it=owners.iterator();it.hasNext();){ Object[] entry = (Object[])it.next(); String entry_name = ((FMFileOwner)entry[0]).getName(); //System.out.println( " existing entry: " + entry_name ); if ( owner.getName().equals( entry_name )){ my_entry = entry; } } if ( my_entry == null ){ Debug.out( "reserveAccess fail" ); throw( new FMFileManagerException( "File '"+canonical_path+"' has not been reserved (not found), '" + owner.getName()+"'")); } my_entry[1] = new Boolean( access_mode==FM_WRITE ); my_entry[2] = reason; int read_access = 0; int write_access = 0; int write_access_lax = 0; TOTorrentFile my_torrent_file = owner.getTorrentFile(); String users = ""; for (Iterator it=owners.iterator();it.hasNext();){ Object[] entry = (Object[])it.next(); FMFileOwner this_owner = (FMFileOwner)entry[0]; if (((Boolean)entry[1]).booleanValue()){ write_access++; TOTorrentFile this_tf = this_owner.getTorrentFile(); if ( my_torrent_file != null && this_tf != null && my_torrent_file.getLength() == this_tf.getLength()){ write_access_lax++; } users += (users.length()==0?"":",") + this_owner.getName() + " [write]"; }else{ read_access++; users += (users.length()==0?"":",") + this_owner.getName() + " [read]"; } } if ( write_access > 1 || ( write_access == 1 && read_access > 0 )){ // relax locking if strict is disabled and torrent file is same size if ( !COConfigurationManager.getBooleanParameter( "File.strict.locking" )){ if ( write_access_lax == write_access ){ return; } } Debug.out( "reserveAccess fail" ); throw( new FMFileManagerException( "File '"+canonical_path+"' is in use by '" + users +"'")); } }finally{ file_map_mon.exit(); } } private void releaseFile() { if ( clone ){ return; } try{ file_map_mon.enter(); // System.out.println( "FMFile::releaseFile:" + canonical_path + "("+ owner.getName() + ")" + " - " + Debug.getCompressedStackTrace()); List owners = (List)file_map.get( canonical_path ); if ( owners != null ){ for (Iterator it=owners.iterator();it.hasNext();){ Object[] entry = (Object[])it.next(); if ( owner.getName().equals(((FMFileOwner)entry[0]).getName())){ it.remove(); break; } } if ( owners.size() == 0 ){ file_map.remove( canonical_path ); } } }finally{ file_map_mon.exit(); } } protected void createDirs( File target ) throws FMFileManagerException { if ( clone ){ return; } deleteDirs(); File parent = target.getParentFile(); if ( !parent.exists()){ List new_dirs = new ArrayList(); File current = parent; while( current != null && !current.exists()){ new_dirs.add( current ); current = current.getParentFile(); } created_dirs_leaf = target; created_dirs = new ArrayList(); if (FileUtil.mkdirs(parent)){ created_dirs_leaf = target; created_dirs = new_dirs; /* for (int i=created_dirs.size()-1;i>=0;i--){ System.out.println( "created " + created_dirs.get(i)); } */ }else{ throw( new FMFileManagerException( "Failed to create parent directory '" + parent + "'")); } } } protected void deleteDirs() { if ( clone ){ return; } if ( created_dirs_leaf != null ){ // delete any dirs we created if the target file doesn't exist if ( !created_dirs_leaf.exists()){ Iterator it = created_dirs.iterator(); while( it.hasNext()){ File dir = (File)it.next(); if ( dir.exists() && dir.isDirectory()){ File[] entries = dir.listFiles(); if ( entries == null || entries.length == 0 ){ // System.out.println( "deleted " + dir ); dir.delete(); }else{ break; } }else{ break; } } } created_dirs_leaf = null; created_dirs = null; } } protected String getString() { File cPath = new File(canonical_path); String sPaths; if (cPath.equals(linked_file)) sPaths = "can/link=" + Debug.secretFileName(canonical_path); else sPaths = "can=" + Debug.secretFileName(canonical_path) + ",link=" + Debug.secretFileName(linked_file.toString()); return sPaths + ",raf=" + raf + ",acc=" + access_mode + ",ctrl = " + file_access.getString(); } protected static void generateEvidence( IndentWriter writer ) { writer.println( file_map.size() + " FMFile Reservations" ); try{ writer.indent(); try{ file_map_mon.enter(); Iterator it = file_map.keySet().iterator(); while( it.hasNext()){ String key = (String)it.next(); List owners = (List)file_map.get(key); Iterator it2 = owners.iterator(); String str = ""; while( it2.hasNext()){ Object[] entry = (Object[])it2.next(); FMFileOwner owner = (FMFileOwner)entry[0]; Boolean write = (Boolean)entry[1]; String reason = (String)entry[2]; str += (str.length()==0?"":", ") + owner.getName() + "[" + (write.booleanValue()?"write":"read")+ "/" + reason + "]"; } writer.println( Debug.secretFileName(key) + " -> " + str ); } }finally{ file_map_mon.exit(); } FMFileManagerImpl.generateEvidence( writer ); }finally{ writer.exdent(); } } } azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessLinear.java0000644000175000017500000002332311253077242030071 0ustar adrianadrian/* * Created on 28-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.file.impl; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.diskmanager.file.FMFile; import com.aelitis.azureus.core.diskmanager.file.FMFileManagerException; public class FMFileAccessLinear implements FMFileAccess { private static final int WRITE_RETRY_LIMIT = 10; private static final int WRITE_RETRY_DELAY = 100; private static final int READ_RETRY_LIMIT = 10; private static final int READ_RETRY_DELAY = 100; private static final boolean DEBUG = true; private static final boolean DEBUG_VERBOSE = false; private FMFileImpl owner; protected FMFileAccessLinear( FMFileImpl _owner ) { owner = _owner; } public void aboutToOpen() throws FMFileManagerException { } public long getLength( RandomAccessFile raf ) throws FMFileManagerException { try{ AEThread2.setDebug( owner ); return( raf.length()); }catch( Throwable e ){ throw( new FMFileManagerException( "getLength fails", e )); } } public void setLength( RandomAccessFile raf, long length ) throws FMFileManagerException { try{ AEThread2.setDebug( owner ); raf.setLength( length ); }catch( Throwable e ){ throw( new FMFileManagerException( "setLength fails", e )); } } public void setPieceComplete( RandomAccessFile raf, int piece_number, DirectByteBuffer piece_data ) throws FMFileManagerException { } public void read( RandomAccessFile raf, DirectByteBuffer buffer, long offset ) throws FMFileManagerException { if (raf == null){ throw new FMFileManagerException( "read: raf is null" ); } FileChannel fc = raf.getChannel(); if ( !fc.isOpen()){ Debug.out("FileChannel is closed: " + owner.getName()); throw( new FMFileManagerException( "read - file is closed")); } AEThread2.setDebug( owner ); try{ fc.position(offset); while (fc.position() < fc.size() && buffer.hasRemaining(DirectByteBuffer.SS_FILE)){ buffer.read(DirectByteBuffer.SS_FILE,fc); } }catch ( Exception e ){ Debug.printStackTrace( e ); throw( new FMFileManagerException( "read fails", e )); } } public void read( RandomAccessFile raf, DirectByteBuffer[] buffers, long offset ) throws FMFileManagerException { if ( raf == null ){ throw new FMFileManagerException( "read: raf is null" ); } FileChannel fc = raf.getChannel(); if ( !fc.isOpen()){ Debug.out("FileChannel is closed: " + owner.getName()); throw( new FMFileManagerException( "read - file is closed")); } AEThread2.setDebug( owner ); int[] original_positions = null; long read_start = SystemTime.getHighPrecisionCounter(); try{ fc.position(offset); ByteBuffer[] bbs = new ByteBuffer[buffers.length]; original_positions = new int[buffers.length]; ByteBuffer last_bb = null; for (int i=0;i 0 ){ loop = 0; }else{ loop++; if ( loop == READ_RETRY_LIMIT ){ Debug.out( "FMFile::read: zero length read - abandoning" ); throw( new FMFileManagerException( "read fails: retry limit exceeded")); }else{ if ( DEBUG_VERBOSE ){ Debug.out( "FMFile::read: zero length read - retrying" ); } try{ Thread.sleep( READ_RETRY_DELAY*loop ); }catch( InterruptedException e ){ throw( new FMFileManagerException( "read fails: interrupted" )); } } } } } }catch ( Throwable e ){ try{ Debug.out( "Read failed: " + owner.getString() + ": raf open=" + raf.getChannel().isOpen() + ", len=" + raf.length() + ",off=" + offset ); }catch( IOException f ){ } Debug.printStackTrace( e ); if ( original_positions != null ){ try{ for (int i=0;i 10*1000 ){ System.out.println( "read took " + elapsed_millis + " for " + owner.getString()); } } } public void write( RandomAccessFile raf, DirectByteBuffer[] buffers, long position ) throws FMFileManagerException { if ( raf == null){ throw( new FMFileManagerException( "write fails: raf is null" )); } FileChannel fc = raf.getChannel(); if ( !fc.isOpen()){ Debug.out("FileChannel is closed: " + owner.getName()); throw( new FMFileManagerException( "read - file is closed")); } AEThread2.setDebug( owner ); int[] original_positions = null; try{ long expected_write = 0; long actual_write = 0; boolean partial_write = false; if ( DEBUG ){ for (int i=0;i 0 ){ loop = 0; if ( DEBUG ){ if ( last_bb.position() != last_bb.limit()){ partial_write = true; if ( DEBUG_VERBOSE ){ Debug.out( "FMFile::write: **** partial write **** this = " + written + ", total = " + actual_write + ", target = " + expected_write ); } } } }else{ loop++; if ( loop == WRITE_RETRY_LIMIT ){ Debug.out( "FMFile::write: zero length write - abandoning" ); throw( new FMFileManagerException( "write fails: retry limit exceeded")); }else{ if ( DEBUG_VERBOSE ){ Debug.out( "FMFile::write: zero length write - retrying" ); } try{ Thread.sleep( WRITE_RETRY_DELAY*loop ); }catch( InterruptedException e ){ throw( new FMFileManagerException( "write fails: interrupted" )); } } } } } if ( DEBUG ){ if ( expected_write != actual_write ){ Debug.out( "FMFile::write: **** partial write **** failed: expected = " + expected_write + ", actual = " + actual_write ); throw( new FMFileManagerException( "write fails: expected write/actual write mismatch" )); }else{ if ( partial_write && DEBUG_VERBOSE ){ Debug.out( "FMFile::write: **** partial write **** completed ok" ); } } } }catch ( Throwable e ){ if ( original_positions != null ){ try{ for (int i=0;i= file_length ){ // first piece takes up all the file first_piece_length = file_length; last_piece_start = file_length; last_piece_length = 0; }else{ last_piece_length = ( file_length - piece_offset ) % piece_size; last_piece_start = file_length - last_piece_length; } /* System.out.println( "file " + new String(torrent_file.getPathComponents()[0]) + ": " + "off = " + file_offset_in_torrent + ", len = " + file_length + ", fp = " + first_piece_start + "/" + first_piece_length + ", lp = " + last_piece_start + "/" + last_piece_length ); */ if ( !new File(controlFileDir,controlFileName).exists()){ if (!controlFileDir.isDirectory() && !FileUtil.mkdirs(controlFileDir)) { throw new FMFileManagerException("Directory creation failed: " + controlFileDir); } if(current_length > 0) { write_required = true; writeState(); } }else{ readState(); } }catch( Throwable e ){ throw( new FMFileManagerException( "Compact file init fail", e )); } } protected long getFirstPieceStart() { return( first_piece_start ); } protected long getFirstPieceLength() { return( first_piece_length ); } protected long getLastPieceStart() { return( last_piece_start ); } protected long getLastPieceLength() { return( last_piece_length ); } public void aboutToOpen() throws FMFileManagerException { delegate.aboutToOpen(); } public long getLength( RandomAccessFile raf ) throws FMFileManagerException { return( current_length ); } public void setLength( RandomAccessFile raf, long length ) throws FMFileManagerException { if ( length != current_length ){ current_length = length; write_required = true; } } protected void read( RandomAccessFile raf, DirectByteBuffer buffer, long position ) throws FMFileManagerException { int original_limit = buffer.limit(SS); try{ int len = original_limit - buffer.position(SS); // System.out.println( "compact: read - " + position + "/" + len ); // deal with any read access to the first piece if ( position < first_piece_start + first_piece_length ){ int available = (int)( first_piece_start + first_piece_length - position ); if ( available >= len ){ // all they require is in the first piece // System.out.println( " all in first piece" ); delegate.read( raf, new DirectByteBuffer[]{ buffer }, position ); position += len; len = 0; }else{ // read goes past end of first piece // System.out.println( " part in first piece" ); buffer.limit( SS, buffer.position(SS) + available ); delegate.read( raf, new DirectByteBuffer[]{ buffer }, position ); buffer.limit( SS, original_limit ); position += available; len -= available; } } if ( len == 0 ){ return; } // position is at start of gap between start and end - work out how much, // if any, space has been requested long space = last_piece_start - position; if ( space > 0 ){ if ( space >= len ){ // all they require is space // System.out.println( " all in space" ); buffer.position( SS, original_limit ); position += len; len = 0; }else{ // read goes past end of space // System.out.println( " part in space" ); buffer.position( SS, buffer.position(SS) + (int)space ); position += space; len -= space; } } if ( len == 0 ){ return; } // lastly read from last piece // System.out.println( " some in last piece" ); delegate.read( raf, new DirectByteBuffer[]{ buffer }, ( position - last_piece_start ) + first_piece_length ); }finally{ buffer.limit(SS,original_limit); } } public void read( RandomAccessFile raf, DirectByteBuffer[] buffers, long position ) throws FMFileManagerException { for (int i=0;i 0 ){ break; } } if ( position > current_length ){ setLength( raf, position ); } } protected void write( RandomAccessFile raf, DirectByteBuffer buffer, long position ) throws FMFileManagerException { int original_limit = buffer.limit(SS); try{ int len = original_limit - buffer.position(SS); // System.out.println( "compact: write - " + position + "/" + len ); // deal with any write access to the first piece if ( position < first_piece_start + first_piece_length ){ int available = (int)( first_piece_start + first_piece_length - position ); if ( available >= len ){ // all they require is in the first piece // System.out.println( " all in first piece" ); delegate.write( raf, new DirectByteBuffer[]{buffer}, position ); position += len; len = 0; }else{ // write goes past end of first piece // System.out.println( " part of first piece" ); buffer.limit( SS, buffer.position(SS) + available ); delegate.write( raf, new DirectByteBuffer[]{buffer}, position ); buffer.limit( SS, original_limit ); position += available; len -= available; } } if ( len == 0 ){ return; } // position is at start of gap between start and end - work out how much, // if any, space has been requested long space = last_piece_start - position; if ( space > 0 ){ if ( space >= len ){ // System.out.println( " all in space" ); // all they require is space buffer.position( SS, original_limit ); position += len; len = 0; }else{ // write goes past end of space // System.out.println( " part in space" ); buffer.position( SS, buffer.position(SS) + (int)space ); position += space; len -= space; } } if ( len == 0 ){ return; } // lastly write to last piece // System.out.println( " some in last piece" ); delegate.write( raf, new DirectByteBuffer[]{buffer}, ( position - last_piece_start ) + first_piece_length ); }finally{ buffer.limit(SS,original_limit); } } public void write( RandomAccessFile raf, DirectByteBuffer[] buffers, long position ) throws FMFileManagerException { for (int i=0;i current_length ){ setLength( raf, position ); } } public void flush() throws FMFileManagerException { writeState(); } public void setPieceComplete( RandomAccessFile raf, int piece_number, DirectByteBuffer piece_data ) throws FMFileManagerException { } protected void readState() throws FMFileManagerException { try{ Map data = FileUtil.readResilientFile( controlFileDir, controlFileName, false ); if ( data != null && data.size() > 0 ){ Long version = (Long)data.get( "version" ); Long length = (Long)data.get( "length" ); current_length = length.longValue(); } }catch( Throwable e ){ throw( new FMFileManagerException( "Failed to read control file state", e )); } } protected void writeState() throws FMFileManagerException { boolean write = write_required; if ( write ){ write_required = false; try{ Map data = new HashMap(); data.put( "version", new Long( version )); data.put( "length", new Long( current_length )); FileUtil.writeResilientFile( controlFileDir, controlFileName, data, false ); }catch( Throwable e ){ throw( new FMFileManagerException( "Failed to write control file state", e )); } } } public String getString() { return( "compact" ); } }azureus-4.3.0.6/com/aelitis/azureus/core/diskmanager/file/impl/FMFileTestImpl.java0000644000175000017500000000613010373051036027266 0ustar adrianadrian/* * Created on 13-Oct-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.diskmanager.file.impl; import java.io.File; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.DirectByteBuffer; import com.aelitis.azureus.core.diskmanager.file.*; /** * @author parg * */ public class FMFileTestImpl extends FMFileUnlimited { protected long file_offset_in_torrent; protected FMFileTestImpl( FMFileOwner _owner, FMFileManagerImpl _manager, File _file, int _type ) throws FMFileManagerException { super( _owner, _manager, _file, _type ); TOTorrentFile torrent_file = getOwner().getTorrentFile(); TOTorrent torrent = torrent_file.getTorrent(); for (int i=0;i 5*60*1000 ) return; if(error + ej == 0) return; //Sample weight balances local and remote error. (1) float w = error / (ej + error); //Real error float re = rtt - coordinates.distance(cj); //Compute relative error of this sample. (2) float es = Math.abs(re) / rtt; //Update weighted moving average of local error. (3) float new_error = es * ce * w + error * (1 - ce * w); //Update local coordinates. (4) float delta = cc * w; float scale = delta * re; HeightCoordinatesImpl random_error = new HeightCoordinatesImpl((float)Math.random()/10,(float)Math.random()/10,0f); HeightCoordinatesImpl new_coordinates = (HeightCoordinatesImpl)coordinates.add(coordinates.sub(cj.add(random_error)).unity().scale(scale)); if ( valid( new_error ) && new_coordinates.isValid()){ coordinates = new_coordinates; error = new_error > ERROR_MIN ? new_error : ERROR_MIN; }else{ /* not very interesting and occasionally happen... Debug.out( "VivaldiPosition: resetting as invalid: " + coordinates + "/" + error + " + " + rtt + "," + cj + "," + ej + "->" + new_coordinates + "/" + new_error ); */ coordinates = new HeightCoordinatesImpl(0,0,0); error = initial_error; } if(! cj.atOrigin()) { nbUpdates++; } if(nbUpdates > CONVERGE_EVERY) { nbUpdates = 0; update(10,new HeightCoordinatesImpl(0,0,0),CONVERGE_FACTOR); } }else{ // System.out.println( "rejected vivaldi update:" + rtt + "/" + cj + "/" + ej ); } } public boolean isValid() { return( (!Float.isNaN( getErrorEstimate())) && getCoordinates().isValid()); } private boolean valid( float f ) { return( !(Float.isInfinite( f ) || Float.isNaN( f ))); } public void update(float rtt, float[] data ){ update( rtt, new HeightCoordinatesImpl( data[0], data[1], data[2] ), data[3] ); } public float estimateRTT(Coordinates coordinates) { return this.coordinates.distance(coordinates); } public float[] toFloatArray(){ return( new float[]{ coordinates.getX(), coordinates.getY(), coordinates.getH(), error }); } public void fromFloatArray( float[] data ){ coordinates = new HeightCoordinatesImpl( data[0], data[1], data[2] ); error = data[3]; } public String toString() { return coordinates + " : " + error; } public boolean equals(Object arg0) { if(arg0 instanceof VivaldiPositionImpl) { VivaldiPositionImpl other = (VivaldiPositionImpl) arg0; if(other.error != error) return false; if(! other.coordinates.equals(coordinates)) return false; return true; } return false; } public float estimateRTT( DHTNetworkPosition _other ) { VivaldiPosition other = (VivaldiPosition)_other; Coordinates other_coords = other.getCoordinates(); if ( coordinates.atOrigin() || other_coords.atOrigin()){ return( Float.NaN ); } return( estimateRTT( other_coords )); } public void update( byte[] _other_id, DHTNetworkPosition _other, float rtt ) { VivaldiPositionImpl other = (VivaldiPositionImpl)_other; Coordinates other_coords = other.getCoordinates(); update( rtt, other_coords, other.getErrorEstimate()); } public int getSerialisedSize() { return( 16 ); // 4 floats } public void serialise( DataOutputStream os ) throws IOException { float[] data = toFloatArray(); for (int i=0;i= ELEMENTS_X / 2 && 1 == 0) { positions[i][j] = new VivaldiPositionImpl(realCoordinates[i][j]); positions[i][j].setErrorEstimate(0.01f); } else { positions[i][j] = new VivaldiPositionImpl(new HeightCoordinatesImpl(1000+DISTANCE*i,1000+DISTANCE*j,20)); } lPos.add(positions[i][j]); } } //Main loop for(int iter = 0 ; iter < MAX_ITERATIONS ; iter++) { if(iter%100 == 0) System.out.println(iter); if(display.isDisposed()) return; display.syncExec( new Runnable() { public void run() { panel.refresh(lPos); } }); try { //Thread.sleep(100); } catch (Exception e) { // TODO: handle exception } //For each node : for(int i = 0 ; i < ELEMENTS_X ; i++) { for(int j = 0 ; j < ELEMENTS_Y ; j++) { VivaldiPosition position = positions[i][j]; //Pick N random nodes for(int k = 0 ; k < NB_CONTACTS ; k++) { int i1 = (int) (Math.random() * ELEMENTS_X); int j1 = (int) (Math.random() * ELEMENTS_Y); if(i1 == i && j1 ==j) continue; VivaldiPosition position1 = positions[i1][j1]; float rtt = realCoordinates[i1][j1].distance(realCoordinates[i][j]); //rtt *= (Math.random() - 0.5)/20 + 1; position.update(rtt,position1.getCoordinates(),position1.getErrorEstimate()); } } } } } }; runner.setDaemon(true); runner.start(); while (!shell.isDisposed ()) { if (!display.readAndDispatch ()) display.sleep (); } display.dispose (); } public static void main(String args[]) { new VivaldiVisualTest(); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPositionProvider.java0000644000175000017500000000415310545062560032275 0ustar adrianadrian/* * Created on 24-Apr-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.netcoords.vivaldi.ver1; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionProvider; public class VivaldiPositionProvider implements DHTNetworkPositionProvider { public byte getPositionType() { return( DHTNetworkPosition.POSITION_TYPE_VIVALDI_V1 ); } public DHTNetworkPosition create( byte[] ID, boolean is_local ) { return( VivaldiPositionFactory.createPosition()); } public DHTNetworkPosition getLocalPosition() { return( null ); } public DHTNetworkPosition deserialisePosition( DataInputStream is ) throws IOException { float[] data = new float[4]; for (int i=0;i best_provider ){ best_position = position; } } return( best_position ); } public static DHTNetworkPosition[] createPositions( byte[] ID, boolean is_local ) { DHTNetworkPositionProvider[] prov = providers; DHTNetworkPosition[] res = new DHTNetworkPosition[prov.length]; int skipped = 0; for (int i=0;i 0 ){ DHTNetworkPosition[] x = new DHTNetworkPosition[ res.length - skipped ]; int pos = 0; for (int i=0;i best_provider ){ best_result = f; best_provider = p1_type; } } }catch( Throwable e ){ Debug.printStackTrace(e); } break; } } } return( best_result ); } public static void update( DHTNetworkPosition[] local_positions, byte[] remote_id, DHTNetworkPosition[] remote_positions, float rtt ) { for (int i=0;i 8 ){ res = res.substring(0,8)+"..."; } return( res ); } public static String getFullString( byte[] b ) { return( ByteFormatter.nicePrint(b)); } public static String getString( HashWrapper w ) { if ( logging_on ){ return( getString( w.getHash())); }else{ return( "" ); } } public static String getString( DHTTransportContact[] contacts ) { if ( logging_on ){ String res = "{"; for (int i=0;i"); } String res = ""; for (int i=0;i"); } return( getString( value.getValue()) + " <" + (value.isLocal()?"loc":"rem" ) + ",flag=" + Integer.toHexString(value.getFlags()) + ",life=" + value.getLifeTimeHours() + ",rep=" + Integer.toHexString( value.getReplicationControl())+",orig=" + value.getOriginator().getExternalAddress() +">" ); }else{ return( "" ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/impl/DHTImpl.java0000644000175000017500000002124711267313012023322 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.impl; import java.io.*; import java.util.Properties; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.DHTLogger; import com.aelitis.azureus.core.dht.DHTOperationListener; import com.aelitis.azureus.core.dht.DHTStorageAdapter; import com.aelitis.azureus.core.dht.control.*; import com.aelitis.azureus.core.dht.db.DHTDB; import com.aelitis.azureus.core.dht.nat.DHTNATPuncher; import com.aelitis.azureus.core.dht.nat.DHTNATPuncherAdapter; import com.aelitis.azureus.core.dht.nat.DHTNATPuncherFactory; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionManager; import com.aelitis.azureus.core.dht.router.DHTRouter; import com.aelitis.azureus.core.dht.speed.DHTSpeedTester; import com.aelitis.azureus.core.dht.speed.DHTSpeedTesterFactory; import com.aelitis.azureus.core.dht.transport.*; /** * @author parg * */ public class DHTImpl implements DHT { private DHTStorageAdapter storage_adapter; private DHTNATPuncherAdapter nat_adapter; private DHTControl control; private DHTNATPuncher nat_puncher; private DHTSpeedTester speed_tester; private Properties properties; private DHTLogger logger; public DHTImpl( DHTTransport _transport, Properties _properties, DHTStorageAdapter _storage_adapter, DHTNATPuncherAdapter _nat_adapter, DHTLogger _logger ) { properties = _properties; storage_adapter = _storage_adapter; nat_adapter = _nat_adapter; logger = _logger; DHTNetworkPositionManager.initialise( storage_adapter ); DHTLog.setLogger( logger ); int K = getProp( PR_CONTACTS_PER_NODE, DHTControl.K_DEFAULT ); int B = getProp( PR_NODE_SPLIT_FACTOR, DHTControl.B_DEFAULT ); int max_r = getProp( PR_MAX_REPLACEMENTS_PER_NODE, DHTControl.MAX_REP_PER_NODE_DEFAULT ); int s_conc = getProp( PR_SEARCH_CONCURRENCY, DHTControl.SEARCH_CONCURRENCY_DEFAULT ); int l_conc = getProp( PR_LOOKUP_CONCURRENCY, DHTControl.LOOKUP_CONCURRENCY_DEFAULT ); int o_rep = getProp( PR_ORIGINAL_REPUBLISH_INTERVAL, DHTControl.ORIGINAL_REPUBLISH_INTERVAL_DEFAULT ); int c_rep = getProp( PR_CACHE_REPUBLISH_INTERVAL, DHTControl.CACHE_REPUBLISH_INTERVAL_DEFAULT ); int c_n = getProp( PR_CACHE_AT_CLOSEST_N, DHTControl.CACHE_AT_CLOSEST_N_DEFAULT ); control = DHTControlFactory.create( new DHTControlAdapter() { public DHTStorageAdapter getStorageAdapter() { return( storage_adapter ); } public boolean isDiversified( byte[] key ) { if ( storage_adapter == null ){ return( false ); } return( storage_adapter.isDiversified( key )); } public byte[][] diversify( String description, DHTTransportContact cause, boolean put_operation, boolean existing, byte[] key, byte type, boolean exhaustive, int max_depth ) { boolean valid; if ( existing ){ valid = type == DHT.DT_FREQUENCY || type == DHT.DT_SIZE || type == DHT.DT_NONE; }else{ valid = type == DHT.DT_FREQUENCY || type == DHT.DT_SIZE; } if ( storage_adapter != null && valid ){ if ( existing ){ return( storage_adapter.getExistingDiversification( key, put_operation, exhaustive, max_depth )); }else{ return( storage_adapter.createNewDiversification( description, cause, key, put_operation, type, exhaustive, max_depth )); } }else{ if ( !valid ){ Debug.out( "Invalid diversification received: type = " + type ); } if ( existing ){ return( new byte[][]{ key }); }else{ return( new byte[0][] ); } } } }, _transport, K, B, max_r, s_conc, l_conc, o_rep, c_rep, c_n, logger ); if ( nat_adapter != null ){ nat_puncher = DHTNATPuncherFactory.create( nat_adapter, this ); } speed_tester = DHTSpeedTesterFactory.create( this ); } protected int getProp( String name, int def ) { Integer x = (Integer)properties.get(name); if ( x == null ){ properties.put( name, new Integer( def )); return( def ); } return( x.intValue()); } public int getIntProperty( String name ) { return(((Integer)properties.get(name)).intValue()); } public boolean isDiversified( byte[] key ) { return( control.isDiversified( key )); } public void put( byte[] key, String description, byte[] value, byte flags, DHTOperationListener listener ) { control.put( key, description, value, flags, (byte)0, DHT.REP_FACT_DEFAULT, true, listener ); } public void put( byte[] key, String description, byte[] value, byte flags, boolean high_priority, DHTOperationListener listener ) { control.put( key, description, value, flags, (byte)0, DHT.REP_FACT_DEFAULT, high_priority, listener ); } public void put( byte[] key, String description, byte[] value, byte flags, byte life_hours, boolean high_priority, DHTOperationListener listener ) { control.put( key, description, value, flags, life_hours, DHT.REP_FACT_DEFAULT, high_priority, listener ); } public void put( byte[] key, String description, byte[] value, byte flags, byte life_hours, byte replication_control, boolean high_priority, DHTOperationListener listener ) { control.put( key, description, value, flags, life_hours, replication_control, high_priority, listener ); } public DHTTransportValue getLocalValue( byte[] key ) { return( control.getLocalValue( key )); } public void get( byte[] key, String description, byte flags, int max_values, long timeout, boolean exhaustive, boolean high_priority, DHTOperationListener listener ) { control.get( key, description, flags, max_values, timeout, exhaustive, high_priority, listener ); } public byte[] remove( byte[] key, String description, DHTOperationListener listener ) { return( control.remove( key, description, listener )); } public byte[] remove( DHTTransportContact[] contacts, byte[] key, String description, DHTOperationListener listener ) { return( control.remove( contacts, key, description, listener )); } public DHTTransport getTransport() { return( control.getTransport()); } public DHTRouter getRouter() { return( control.getRouter()); } public DHTControl getControl() { return( control ); } public DHTDB getDataBase() { return( control.getDataBase()); } public DHTNATPuncher getNATPuncher() { return( nat_puncher ); } public DHTSpeedTester getSpeedTester() { return( speed_tester ); } public DHTStorageAdapter getStorageAdapter() { return( storage_adapter ); } public void integrate( boolean full_wait ) { control.seed( full_wait ); if ( nat_puncher!= null ){ nat_puncher.start(); } } public void destroy() { if ( nat_puncher != null ){ nat_puncher.destroy(); } DHTNetworkPositionManager.destroy( storage_adapter ); } public void exportState( DataOutputStream os, int max ) throws IOException { control.exportState( os, max ); } public void importState( DataInputStream is ) throws IOException { control.importState( is ); } public void setLogging( boolean on ) { DHTLog.setLogging( on ); } public DHTLogger getLogger() { return( logger ); } public void print( boolean full ) { control.print( full ); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/impl/Test.java0000644000175000017500000006605011267313014023003 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.impl; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.dht.*; import com.aelitis.azureus.core.dht.control.DHTControlContact; import com.aelitis.azureus.core.dht.db.impl.DHTDBImpl; import com.aelitis.azureus.core.dht.nat.DHTNATPuncherAdapter; import com.aelitis.azureus.core.dht.nat.impl.DHTNATPuncherImpl; import com.aelitis.azureus.core.dht.transport.*; import com.aelitis.azureus.core.dht.transport.loopback.DHTTransportLoopbackImpl; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTTransportUDPImpl; import com.aelitis.azureus.plugins.dht.impl.DHTPluginStorageManager; import java.io.*; import java.math.BigInteger; import java.net.InetSocketAddress; import java.security.KeyFactory; import java.security.Signature; import java.security.interfaces.RSAPrivateKey; import java.security.spec.RSAPrivateKeySpec; import java.util.*; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.SHA1Simple; import org.gudy.azureus2.core3.util.Timer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.logging.LoggerChannel; import org.gudy.azureus2.plugins.logging.LoggerChannelListener; /** * @author parg * */ public class Test implements DHTNATPuncherAdapter { static boolean AELITIS_TEST = false; static InetSocketAddress AELITIS_ADDRESS = new InetSocketAddress("213.186.46.164", 6881); static int DEFAULT_NETWORK = DHT.NW_CVS; static{ DHTTransportUDPImpl.TEST_EXTERNAL_IP = true; } int num_dhts = 6; int num_stores = 0; static int MAX_VALUES = 10000; boolean udp_protocol = true; int udp_timeout = 1000; static int K = 20; static int B = 5; static int ID_BYTES = 20; int fail_percentage = 00; static Properties dht_props = new Properties(); static{ // DHTDBImpl.ORIGINAL_REPUBLISH_INTERVAL_GRACE = 0; dht_props.put( DHT.PR_CONTACTS_PER_NODE, new Integer(K)); dht_props.put( DHT.PR_NODE_SPLIT_FACTOR, new Integer(B)); dht_props.put( DHT.PR_CACHE_REPUBLISH_INTERVAL, new Integer(30000)); dht_props.put( DHT.PR_ORIGINAL_REPUBLISH_INTERVAL, new Integer(60000)); } static byte[] th_key = new byte[]{ 1,1,1,1 }; static Map check = new HashMap(); static DHTLogger logger; static{ final LoggerChannel c_logger = AzureusCoreFactory.create().getPluginManager().getDefaultPluginInterface().getLogger().getNullChannel("test"); c_logger.addListener( new LoggerChannelListener() { public void messageLogged( int type, String content ) { System.out.println( content ); } public void messageLogged( String str, Throwable error ) { System.out.println( str ); error.printStackTrace(); } }); logger = new DHTLogger() { public void log( String str ) { c_logger.log( str ); } public void log( Throwable e ) { c_logger.log( e ); } public void log( int log_type, String str ) { if ( isEnabled( log_type )){ c_logger.log( str ); } } public boolean isEnabled( int log_type ) { return( true ); } public PluginInterface getPluginInterface() { return( c_logger.getLogger().getPluginInterface()); } }; } public static DHTLogger getLogger() { return( logger ); } public static void main( String[] args ) { new Test(); } Map port_map = new HashMap(); protected Test() { try{ DHTLog.setLogging( true ); DHT[] dhts = new DHT[num_dhts*2+30]; DHTTransport[] transports = new DHTTransport[num_dhts*2+30]; for (int i=0;i 0 && i%10 == 0 ){ System.out.println( "Integrated " + i + " DHTs" ); } } if ( AELITIS_TEST ){ ((DHTTransportUDP)transports[num_dhts-1]).importContact( AELITIS_ADDRESS, DHTTransportUDP.PROTOCOL_VERSION_MAIN ); }else{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream daos = new DataOutputStream( baos ); transports[0].getLocalContact().exportContact( daos ); daos.close(); transports[num_dhts-1].importContact( new DataInputStream( new ByteArrayInputStream( baos.toByteArray()))); } dhts[num_dhts-1].integrate( true ); DHTTransportLoopbackImpl.setFailPercentage(fail_percentage); //dht1.print(); //DHTTransportLoopbackImpl.setLatency( 500); /* System.out.println( "before put:" + transports[99].getStats().getString()); dhts[99].put( "fred".getBytes(), new byte[2]); System.out.println( "after put:" + transports[99].getStats().getString()); System.out.println( "get:" + dhts[0].get( "fred".getBytes())); System.out.println( "get:" + dhts[77].get( "fred".getBytes())); */ Map store_index = new HashMap(); for (int i=0;i " ); try{ String str = reader.readLine().trim(); if ( str == null ){ break; } int pos = str.indexOf(' '); if ( pos == -1 || pos == 0 ){ usage(); continue; } int dht_index = (int)(Math.random()*num_dhts); DHT dht = dhts[dht_index]; String lhs = str.substring(0,pos).trim(); String rhs = str.substring(pos+1).trim(); DHTTransportStats stats_before = null; char command = lhs.toLowerCase().charAt(0); if ( command == 'p' ){ pos = rhs.indexOf('='); if ( pos == -1 ){ usage(); }else{ System.out.println( "Using dht " + dht_index ); stats_before = dht.getTransport().getStats().snapshot(); String key = rhs.substring(0,pos); String val = rhs.substring(pos+1); pos = val.indexOf( ' ' ); byte flags = 0; byte life = 0; byte rep_fact = DHT.REP_FACT_DEFAULT; if ( pos != -1 ){ String opts = val.substring( pos+1 ); String[] x = opts.split( "," ); for ( String s: x ){ String[] y = s.split("="); String opt = y[0]; if ( opt.equals( "f" )){ flags = (byte)Integer.parseInt(y[1],16); }else if ( opt.equals( "l" )){ life = (byte)Integer.parseInt(y[1]); }else if ( opt.equals( "r" )){ rep_fact = (byte)Integer.parseInt(y[1]); } } val = val.substring(0,pos); } dht.put( key.getBytes(), "", val.getBytes(), flags, life, rep_fact, false, new DHTOperationAdapter() ); } }else if ( command == 'x' ){ dht = (DHT)store_index.get( rhs ); if ( dht == null ){ System.out.println( "DHT not found" ); }else{ stats_before = dht.getTransport().getStats().snapshot(); byte[] res = dht.remove( rhs.getBytes(), "", new DHTOperationAdapter()); if ( res != null ){ store_index.remove( rhs ); } System.out.println( "-> " + (res==null?"null":new String(res))); } }else if ( command == 'e' ){ dht = (DHT)store_index.get( rhs ); if ( dht == null ){ System.out.println( "DHT not found" ); }else{ DataOutputStream daos = new DataOutputStream( new FileOutputStream( "C:\\temp\\dht.state")); dht.exportState( daos, 0 ); daos.close(); } }else if ( command == 'g' ){ System.out.println( "Using dht " + dht_index ); stats_before = dht.getTransport().getStats().snapshot(); pos = rhs.indexOf( ' ' ); byte flags = 0; if ( pos != -1 ){ String opts = rhs.substring( pos+1 ); String[] x = opts.split( "," ); for ( String s: x ){ String[] y = s.split("="); String opt = y[0]; if ( opt.equals( "f" )){ flags = (byte)Integer.parseInt(y[1]); } } rhs = rhs.substring(0,pos); } dht.get( rhs.getBytes(), "", flags, 32, 0, false, false, new DHTOperationAdapter() { public void read( DHTTransportContact contact, DHTTransportValue value ) { System.out.println( "-> " + getString( value )); } public void complete( boolean timeout ) { System.out.println( "-> complete" ); } }); }else if ( command == '?' ){ System.out.println( "Using dht " + dht_index ); stats_before = dht.getTransport().getStats().snapshot(); final DHT f_dht = dht; dht.get( rhs.getBytes(), "", DHT.FLAG_STATS, 32, 0, false, false, new DHTOperationAdapter() { public void read( DHTTransportContact contact, DHTTransportValue value ) { System.out.println( "-> " + getString( value )); try{ DHTStorageKeyStats stats = f_dht.getStorageAdapter().deserialiseStats( new DataInputStream( new ByteArrayInputStream( value.getValue()))); System.out.println( " stats: size = " + stats.getSize() + ", entries=" + stats.getEntryCount() + ", rpm=" + stats.getReadsPerMinute()); }catch( Throwable e ){ e.printStackTrace(); } } public void complete( boolean timeout ) { System.out.println( "-> complete" ); } }); }else if ( command == 'd' ){ System.out.println( "Using dht " + dht_index ); stats_before = dht.getTransport().getStats().snapshot(); byte[] res = dht.remove( rhs.getBytes(), "", new DHTOperationAdapter()); System.out.println( "-> " + (res==null?"null":new String(res))); }else if ( command == 'z' ){ System.out.println( "Using dht " + dht_index ); stats_before = dht.getTransport().getStats().snapshot(); dht.get( rhs.getBytes(), "", (byte)0, 10, 0, false, false, new DHTOperationListener() { public void searching( DHTTransportContact contact, int level, int active_searches ) { } public void diversified( String desc ) { } public void found( DHTTransportContact contact, boolean is_closest ) { } public void read( final DHTTransportContact contact, final DHTTransportValue value ) { System.out.println( "-> " + value.getString()); new AEThread("blah") { public void runSupport() { DHTTransportFullStats stats = contact.getStats(); System.out.println( " stats = " + stats.getString() ); } }.start(); } public void wrote( final DHTTransportContact contact, DHTTransportValue value ) { } public void complete( boolean timeout ) { System.out.println( "complete"); } }); }else if ( command == 'v' ){ try{ int index = Integer.parseInt( rhs ); dht = dhts[index]; stats_before = dht.getTransport().getStats().snapshot(); dht.print( true ); List l = dht.getControl().getContacts(); for (int i=0;i 0 ){ DHTTransport r_t = (DHTTransport)ok_t.get((int)(Math.random()*(ok_t.size()-1))); r_t.getLocalContact().exportContact( daos ); daos.close(); transports[num_dhts-1].importContact( new DataInputStream( new ByteArrayInputStream( baos.toByteArray()))); }else{ System.out.println( "No comaptible networks found" ); } dht.integrate( true ); dht.print( true ); }else if ( command == 'r' ){ System.out.println( "read - dht0 -> dht1" ); byte[] res = dhts[0].getTransport().readTransfer( new DHTTransportProgressListener() { public void reportSize( long size ) { System.out.println( " read size: " + size ); } public void reportActivity( String str ) { System.out.println( " read act: " + str ); } public void reportCompleteness( int percent ) { System.out.println( " read %: " + percent ); } }, dhts[1].getTransport().getLocalContact(), th_key, new byte[]{1,2,3,4}, 30000 ); System.out.println( "res = " + res ); }else if ( command == 'w' ){ System.out.println( "write - dht0 -> dht1" ); dhts[0].getTransport().writeTransfer( new DHTTransportProgressListener() { public void reportSize( long size ) { System.out.println( " write size: " + size ); } public void reportActivity( String str ) { System.out.println( " write act: " + str ); } public void reportCompleteness( int percent ) { System.out.println( " write %: " + percent ); } }, dhts[1].getTransport().getLocalContact(), th_key, new byte[]{1,2,3,4}, new byte[1000], 60000 ); }else if ( command == 'c' ){ System.out.println( "call - dht0 <-> dht1" ); byte[] res = dhts[0].getTransport().writeReadTransfer( new DHTTransportProgressListener() { public void reportSize( long size ) { System.out.println( " readWrite size: " + size ); } public void reportActivity( String str ) { System.out.println( " readWrite act: " + str ); } public void reportCompleteness( int percent ) { System.out.println( " readWrite %: " + percent ); } }, dhts[1].getTransport().getLocalContact(), th_key, new byte[1000], 60000 ); System.out.println( " reply: len = " + res.length ); }else if ( command == 'b' ){ if ( rhs.equals("1")){ System.out.println( "rendezvous bind: dht2 -> rdv dht1" ); DHTNATPuncherImpl puncher = (DHTNATPuncherImpl)dhts[2].getNATPuncher(); puncher.setRendezvous( dhts[2].getTransport().getLocalContact(), dhts[1].getTransport().getLocalContact()); }else if ( rhs.equals("2" )){ System.out.println( "rendezvous punch: dht0 -> rdv dht2" ); DHTNATPuncherImpl puncher = (DHTNATPuncherImpl)dhts[0].getNATPuncher(); Map originator_data = new HashMap(); originator_data.put( "hello", "mum" ); Map client_data = puncher.punch( "Test", dhts[2].getTransport().getLocalContact(), null, originator_data); System.out.println( " punch client data: " + client_data ); } }else if ( command == 'k' ){ int sp = rhs.indexOf(' '); String key_block; boolean add; if ( sp == -1 ){ key_block = rhs; add = true; }else{ key_block = rhs.substring(0,sp); add = false; } String mod = "123"; String exp = "567"; KeyFactory key_factory = KeyFactory.getInstance("RSA"); RSAPrivateKeySpec private_key_spec = new RSAPrivateKeySpec( new BigInteger(mod,16), new BigInteger(exp,16)); RSAPrivateKey key = (RSAPrivateKey)key_factory.generatePrivate( private_key_spec ); byte[] req = new byte[ 8 + 20 ]; req[0] = (byte)(add?0x01:0x00); int time = (int)(System.currentTimeMillis()/1000); req[4] = (byte)(time>>24); req[5] = (byte)(time>>16); req[6] = (byte)(time>>8); req[7] = (byte)(time); System.arraycopy( new SHA1Simple().calculateHash(key_block.getBytes()), 0, req, 8, 20 ); Signature sig = Signature.getInstance("MD5withRSA" ); sig.initSign( key ); sig.update( req ); dhts[1].getTransport().getLocalContact().sendKeyBlock( new DHTTransportReplyHandlerAdapter() { public void keyBlockReply( DHTTransportContact _contact ) { System.out.println( "key block sent ok" ); } public void failed( DHTTransportContact contact, Throwable error ) { System.out.println( "key block failed" ); error.printStackTrace(); } }, req, sig.sign()); }else{ usage(); } if ( stats_before != null ){ DHTTransportStats stats_after = dht.getTransport().getStats().snapshot(); System.out.println( "before:" + stats_before.getString()); System.out.println( "after:" + stats_after.getString()); } }catch( Throwable e ){ e.printStackTrace(); } } }catch( Throwable e ){ e.printStackTrace(); } } protected String getString( DHTTransportValue value ) { return( new String( value.getValue()) + "; flags=" + Integer.toHexString( value.getFlags()) + "; life=" + value.getLifeTimeHours() + "; rep=" + Integer.toHexString( value.getReplicationControl()) + ", orig=" + value.getOriginator().getAddress()); } protected void createDHT( DHT[] dhts, DHTTransport[] transports, int network, int i ) throws DHTTransportException { DHTTransport transport; if ( udp_protocol ){ Integer next_port = (Integer)port_map.get( new Integer( network )); if ( next_port == null ){ next_port = new Integer(0); }else{ next_port = new Integer( next_port.intValue() + 1 ); } port_map.put( new Integer( network ), next_port ); byte protocol = network==0?DHTTransportUDP.PROTOCOL_VERSION_MAIN:DHTTransportUDP.PROTOCOL_VERSION_CVS; // byte protocol = i%2==0?DHTTransportUDP.PROTOCOL_VERSION_MAIN:DHTTransportUDP.PROTOCOL_VERSION_CVS; transport = DHTTransportFactory.createUDP( protocol, network, false, null, null, 6890 + next_port.intValue(), 5, 3, udp_timeout, 50, 25, false, false, logger ); }else{ transport = DHTTransportFactory.createLoopback(ID_BYTES); } transport.registerTransferHandler( th_key, new DHTTransportTransferHandler() { public String getName() { return( "test" ); } public byte[] handleRead( DHTTransportContact originator, byte[] key ) { byte[] data = new byte[1000]; System.out.println("handle read -> length = " + data.length ); return( data ); } public byte[] handleWrite( DHTTransportContact originator, byte[] key, byte[] value ) { byte[] reply = null; if ( value.length == 1000 ){ reply = new byte[4]; } System.out.println("handle write -> length = " + value.length +", reply = " + reply ); return( reply ); } }); /* HashWrapper id = new HashWrapper( transport.getLocalContact().getID()); if ( check.get(id) != null ){ System.out.println( "Duplicate ID - aborting" ); return; } check.put(id,""); */ DHTStorageAdapter storage_adapter = new DHTPluginStorageManager( network, logger, new File( "C:\\temp\\dht\\" + i)); DHT dht = DHTFactory.create( transport, dht_props, storage_adapter, this, logger ); dhts[i] = dht; transports[i] = transport; } /* public DHTStorageKey keyCreated( HashWrapper key, boolean local ) { System.out.println( "key created" ); return( new DHTStorageKey() { public byte getDiversificationType() { return( DHT.DT_NONE ); } public void serialiseStats( DataOutputStream os ) throws IOException { os.writeInt( 45 ); } }); } public void keyDeleted( DHTStorageKey key ) { System.out.println( "key deleted" ); } public void keyRead( DHTStorageKey adapter_key, DHTTransportContact contact ) { System.out.println( "value read" ); } public void valueAdded( DHTStorageKey key, DHTTransportValue value ) { System.out.println( "value added" ); } public void valueUpdated( DHTStorageKey key, DHTTransportValue old_value, DHTTransportValue new_value) { System.out.println( "value updated" ); } public void valueDeleted( DHTStorageKey key, DHTTransportValue value ) { System.out.println( "value deleted" ); } public byte[][] getExistingDiversification( byte[] key, boolean put_operation ) { System.out.println( "getExistingDiversification: put = " + put_operation ); return( new byte[][]{ key }); } public byte[][] createNewDiversification( byte[] key, boolean put_operation, int diversification_type ) { System.out.println( "createNewDiversification: put = " + put_operation + ", type = " + diversification_type ); return( new byte[0][] ); } */ public Map getClientData( InetSocketAddress originator, Map originator_data ) { System.out.println( "getClientData - " + originator_data + "/" + originator ); Map res = new HashMap(); res.put( "udp_data_port", new Long( 1234 )); res.put( "tcp_data_port", new Long( 5678 )); return( res ); } protected static void usage() { System.out.println( "syntax: [p g] [=]" ); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/0000755000175000017500000000000011310377624022313 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransport.java0000644000175000017500000000550511262527612025517 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; /** * @author parg * */ import java.io.*; public interface DHTTransport { public byte getProtocolVersion(); public int getNetwork(); /** * Gives access to the node ID for this transport * @return */ public DHTTransportContact getLocalContact(); public int getPort(); public void setPort( int port ) throws DHTTransportException; public long getTimeout(); public void setTimeout( long millis ); public DHTTransportContact importContact( DataInputStream is ) throws IOException, DHTTransportException; /** * Set the handler for incoming requests * @param receiver */ public void setRequestHandler( DHTTransportRequestHandler receiver ); public DHTTransportStats getStats(); // direct contact-contact communication public void registerTransferHandler( byte[] handler_key, DHTTransportTransferHandler handler ); public byte[] readTransfer( DHTTransportProgressListener listener, DHTTransportContact target, byte[] handler_key, byte[] key, long timeout ) throws DHTTransportException; public void writeTransfer( DHTTransportProgressListener listener, DHTTransportContact target, byte[] handler_key, byte[] key, byte[] data, long timeout ) throws DHTTransportException; public byte[] writeReadTransfer( DHTTransportProgressListener listener, DHTTransportContact target, byte[] handler_key, byte[] data, long timeout ) throws DHTTransportException; public boolean supportsStorage(); public boolean isReachable(); public DHTTransportContact[] getReachableContacts(); public DHTTransportContact[] getRecentContacts(); public void addListener( DHTTransportListener l ); public void removeListener( DHTTransportListener l ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportContact.java0000644000175000017500000000570511265520562027035 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; /** * @author parg * */ import java.util.*; import java.io.*; import java.net.InetSocketAddress; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition; public interface DHTTransportContact { public int getMaxFailForLiveCount(); public int getMaxFailForUnknownCount(); public int getInstanceID(); public byte[] getID(); public byte getProtocolVersion(); public long getClockSkew(); public void setRandomID( int id ); public int getRandomID(); public String getName(); public InetSocketAddress getAddress(); public InetSocketAddress getExternalAddress(); public boolean isAlive( long timeout ); public void isAlive( DHTTransportReplyHandler handler, long timeout ); public boolean isValid(); public void sendPing( DHTTransportReplyHandler handler ); public void sendImmediatePing( DHTTransportReplyHandler handler, long timeout ); public void sendStats( DHTTransportReplyHandler handler ); public void sendStore( DHTTransportReplyHandler handler, byte[][] keys, DHTTransportValue[][] value_sets, boolean immediate ); public void sendQueryStore( DHTTransportReplyHandler handler, int header_length, List key_details ); public void sendFindNode( DHTTransportReplyHandler handler, byte[] id ); public void sendFindValue( DHTTransportReplyHandler handler, byte[] key, int max_values, byte flags ); public void sendKeyBlock( DHTTransportReplyHandler handler, byte[] key_block_request, byte[] key_block_signature ); public DHTTransportFullStats getStats(); public void exportContact( DataOutputStream os ) throws IOException, DHTTransportException; public void remove(); public DHTNetworkPosition[] getNetworkPositions(); public DHTNetworkPosition getNetworkPosition( byte position_type ); public DHTTransport getTransport(); public String getString(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportFullStats.java0000644000175000017500000000426211061657306027361 0ustar adrianadrian/* * Created on 31-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; /** * @author parg * */ public interface DHTTransportFullStats { // DB public long getDBValueCount(); public long getDBKeyCount(); public long getDBValuesStored(); public long getDBKeysBlocked(); public long getDBKeyDivSizeCount(); public long getDBKeyDivFreqCount(); public long getDBStoreSize(); // Router public long getRouterNodes(); public long getRouterLeaves(); public long getRouterContacts(); public long getRouterUptime(); public int getRouterCount(); // Transport // totals public long getTotalBytesReceived(); public long getTotalBytesSent(); public long getTotalPacketsReceived(); public long getTotalPacketsSent(); public long getTotalPingsReceived(); public long getTotalFindNodesReceived(); public long getTotalFindValuesReceived(); public long getTotalStoresReceived(); public long getTotalKeyBlocksReceived(); public long getIncomingRequests(); // averages public long getAverageBytesReceived(); public long getAverageBytesSent(); public long getAveragePacketsReceived(); public long getAveragePacketsSent(); public String getVersion(); public String getString(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportFindValueReply.java0000644000175000017500000000250710402150270030313 0ustar adrianadrian/* * Created on 10-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; /** * @author parg * */ public interface DHTTransportFindValueReply { public byte getDiversificationType(); public boolean hit(); public DHTTransportValue[] getValues(); public DHTTransportContact[] getContacts(); public boolean blocked(); public byte[] getBlockedKey(); public byte[] getBlockedSignature(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportProgressListener.java0000644000175000017500000000232010373051010030724 0ustar adrianadrian/* * Created on 06-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; /** * @author parg * */ public interface DHTTransportProgressListener { public void reportSize( long size ); public void reportActivity( String str ); public void reportCompleteness( int percent ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportFactory.java0000644000175000017500000000412610641111710027031 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; /** * @author parg * */ import com.aelitis.azureus.core.dht.DHTLogger; import com.aelitis.azureus.core.dht.transport.loopback.*; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTTransportUDPImpl; public class DHTTransportFactory { public static DHTTransport createLoopback( int id_byte_num ) { return( new DHTTransportLoopbackImpl( id_byte_num )); } public static DHTTransportUDP createUDP( byte protocol_version, int network, boolean v6, String ip, String default_ip, int port, int max_fails_for_live, int max_fails_for_unknown, long timeout, int send_delay, int receive_delay, boolean bootstrap_node, boolean reachable, DHTLogger logger ) throws DHTTransportException { return( new DHTTransportUDPImpl( protocol_version, network, v6, ip, default_ip, port, max_fails_for_live, max_fails_for_unknown, timeout, send_delay, receive_delay, bootstrap_node, reachable, logger )); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportTransferHandler.java0000644000175000017500000000242610455333320030513 0ustar adrianadrian/* * Created on 22-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; /** * @author parg * */ public interface DHTTransportTransferHandler { public String getName(); public byte[] handleRead( DHTTransportContact originator, byte[] key ); public byte[] handleWrite( DHTTransportContact originator, byte[] key, byte[] value ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/0000755000175000017500000000000011310377620023077 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/0000755000175000017500000000000011310377624024044 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPImpl.java0000644000175000017500000031062711306100106030427 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.io.*; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.security.SecureRandom; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.ipfilter.IpFilter; import org.gudy.azureus2.core3.ipfilter.IpFilterManagerFactory; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Average; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.DelayedEvent; import org.gudy.azureus2.core3.util.HashWrapper; import org.gudy.azureus2.core3.util.RandomUtils; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.DHTLogger; import com.aelitis.azureus.core.dht.impl.DHTLog; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionManager; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionProvider; import com.aelitis.azureus.core.dht.transport.*; import com.aelitis.azureus.core.dht.transport.udp.*; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketHandler; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketHandlerException; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketHandlerFactory; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketReceiver; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPRequestHandler; import com.aelitis.azureus.core.dht.transport.util.DHTTransportRequestCounter; import com.aelitis.azureus.core.util.average.AverageFactory; import com.aelitis.azureus.core.util.average.MovingImmediateAverage; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.core.util.bloom.BloomFilterFactory; import com.aelitis.net.udp.uc.PRUDPPacketHandler; /** * @author parg * */ public class DHTTransportUDPImpl implements DHTTransportUDP, DHTUDPRequestHandler { public static boolean TEST_EXTERNAL_IP = false; public static final int TRANSFER_QUEUE_MAX = 64; public static final long MAX_TRANSFER_QUEUE_BYTES = 8*1024*1024; public static final long WRITE_XFER_RESEND_DELAY = 12500; public static final long READ_XFER_REREQUEST_DELAY = 5000; public static final long WRITE_REPLY_TIMEOUT = 60000; public static final int MIN_ADDRESS_CHANGE_PERIOD_INIT_DEFAULT = 5*60*1000; public static final int MIN_ADDRESS_CHANGE_PERIOD_NEXT_DEFAULT = 10*60*1000; public static final int STORE_TIMEOUT_MULTIPLIER = 2; private static boolean XFER_TRACE = false; static{ if ( XFER_TRACE ){ System.out.println( "**** DHTTransportUDPImpl xfer trace on ****" ); } } private String external_address; private int min_address_change_period = MIN_ADDRESS_CHANGE_PERIOD_INIT_DEFAULT; private byte protocol_version; private int network; private boolean v6; private String ip_override; private int port; private int max_fails_for_live; private int max_fails_for_unknown; private long request_timeout; private long store_timeout; private boolean reachable; private boolean reachable_accurate; private int dht_send_delay; private int dht_receive_delay; private DHTLogger logger; private DHTUDPPacketHandler packet_handler; private DHTTransportRequestHandler request_handler; private DHTTransportUDPContactImpl local_contact; private Map transfer_handlers = new HashMap(); private Map read_transfers = new HashMap(); private Map write_transfers = new HashMap(); private int active_write_queue_processor_count; private long total_bytes_on_transfer_queues; private Map call_transfers = new HashMap(); private long last_address_change; private List listeners = new ArrayList(); private IpFilter ip_filter = IpFilterManagerFactory.getSingleton().getIPFilter(); private DHTTransportUDPStatsImpl stats; private boolean bootstrap_node = false; private static final int CONTACT_HISTORY_MAX = 32; private static final int CONTACT_HISTORY_PING_SIZE = 24; private Map contact_history = new LinkedHashMap(CONTACT_HISTORY_MAX,0.75f,true) { protected boolean removeEldestEntry( Map.Entry eldest) { return size() > CONTACT_HISTORY_MAX; } }; private static final int ROUTABLE_CONTACT_HISTORY_MAX = 128; private Map routable_contact_history = new LinkedHashMap(ROUTABLE_CONTACT_HISTORY_MAX,0.75f,true) { protected boolean removeEldestEntry( Map.Entry eldest) { return size() > ROUTABLE_CONTACT_HISTORY_MAX; } }; private long other_routable_total; private long other_non_routable_total; private MovingImmediateAverage routeable_percentage_average = AverageFactory.MovingImmediateAverage(8); private static final int RECENT_REPORTS_HISTORY_MAX = 32; private Map recent_reports = new LinkedHashMap(RECENT_REPORTS_HISTORY_MAX,0.75f,true) { protected boolean removeEldestEntry( Map.Entry eldest) { return size() > RECENT_REPORTS_HISTORY_MAX; } }; private static final int STATS_PERIOD = 60*1000; private static final int STATS_DURATION_SECS = 600; // 10 minute average private static final long STATS_INIT_PERIOD = 15*60*1000; // bit more than 10 mins to allow average to establish private long stats_start_time = SystemTime.getCurrentTime(); private long last_alien_count; private long last_alien_fv_count; private Average alien_average = Average.getInstance(STATS_PERIOD,STATS_DURATION_SECS); private Average alien_fv_average = Average.getInstance(STATS_PERIOD,STATS_DURATION_SECS); private Random random; private static final int BAD_IP_BLOOM_FILTER_SIZE = 32000; private BloomFilter bad_ip_bloom_filter; private static AEMonitor class_mon = new AEMonitor( "DHTTransportUDP:class" ); private AEMonitor this_mon = new AEMonitor( "DHTTransportUDP" ); private boolean initial_address_change_deferred; private boolean address_changing; public DHTTransportUDPImpl( byte _protocol_version, int _network, boolean _v6, String _ip, String _default_ip, int _port, int _max_fails_for_live, int _max_fails_for_unknown, long _timeout, int _dht_send_delay, int _dht_receive_delay, boolean _bootstrap_node, boolean _initial_reachability, DHTLogger _logger ) throws DHTTransportException { protocol_version = _protocol_version; network = _network; v6 = _v6; ip_override = _ip; port = _port; max_fails_for_live = _max_fails_for_live; max_fails_for_unknown = _max_fails_for_unknown; request_timeout = _timeout; dht_send_delay = _dht_send_delay; dht_receive_delay = _dht_receive_delay; bootstrap_node = _bootstrap_node; reachable = _initial_reachability; logger = _logger; store_timeout = request_timeout * STORE_TIMEOUT_MULTIPLIER; try{ random = RandomUtils.SECURE_RANDOM; }catch( Throwable e ){ random = new Random(); logger.log( e ); } int last_pct = COConfigurationManager.getIntParameter( "dht.udp.net" + network + ".routeable_pct", -1 ); if ( last_pct > 0 ){ routeable_percentage_average.update( last_pct ); } createPacketHandler(); SimpleTimer.addPeriodicEvent( "DHTUDP:stats", STATS_PERIOD, new TimerEventPerformer() { private int tick_count; public void perform( TimerEvent event ) { updateStats( tick_count++); } }); String default_ip = _default_ip==null?(v6?"::1":"127.0.0.1"):_default_ip; getExternalAddress( default_ip, logger ); InetSocketAddress address = new InetSocketAddress( external_address, port ); logger.log( "Initial external address: " + address ); local_contact = new DHTTransportUDPContactImpl( true, this, address, address, protocol_version, random.nextInt(), 0 ); } protected void createPacketHandler() throws DHTTransportException { DHTUDPPacketHelper.registerCodecs(); // DHTPRUDPPacket relies on the request-handler being an instanceof THIS so watch out // if you change it :) try{ if ( packet_handler != null ){ packet_handler.destroy(); } packet_handler = DHTUDPPacketHandlerFactory.getHandler( this, this ); }catch( Throwable e ){ throw( new DHTTransportException( "Failed to get packet handler", e )); } // limit send and receive rates. Receive rate is lower as we want a stricter limit // on the max speed we generate packets than those we're willing to process. // logger.log( "send delay = " + _dht_send_delay + ", recv = " + _dht_receive_delay ); packet_handler.setDelays( dht_send_delay, dht_receive_delay, (int)request_timeout ); stats_start_time = SystemTime.getCurrentTime(); if ( stats == null ){ stats = new DHTTransportUDPStatsImpl( this, protocol_version, packet_handler.getStats()); }else{ stats.setStats( packet_handler.getStats()); } } protected void updateStats( int tick_count ) { long alien_count = 0; long[] aliens = stats.getAliens(); for (int i=0;i STATS_INIT_PERIOD ){ reachable_accurate = true; boolean old_reachable = reachable; if ( alien_fv_average.getAverage() > 1 ){ reachable = true; }else if ( alien_average.getAverage() > 3 ){ reachable = true; }else{ reachable = false; } if ( old_reachable != reachable ){ for (int i=0;i 0 ){ COConfigurationManager.setParameter("dht.udp.net" + network + ".routeable_pct", pct ); } // System.out.println( "routables=" + other_routable_total + ", non=" + other_non_routable_total ); // System.out.println( "net " + network + ": aliens = " + alien_average.getAverage() + ", alien fv = " + alien_fv_average.getAverage()); } protected void recordSkew( InetSocketAddress originator_address, long skew ) { if ( stats != null ){ stats.recordSkew( originator_address, skew ); } } protected int getNodeStatus() { if ( bootstrap_node ){ // bootstrap node is special case and not generally routable return( 0 ); } if ( reachable_accurate ){ int status = reachable?DHTTransportUDPContactImpl.NODE_STATUS_ROUTABLE:0; return( status ); }else{ return( DHTTransportUDPContactImpl.NODE_STATUS_UNKNOWN ); } } public boolean isReachable() { return( reachable ); } public byte getProtocolVersion() { return( protocol_version ); } public int getPort() { return( port ); } public void setPort( int new_port ) throws DHTTransportException { if ( new_port == port ){ return; } port = new_port; createPacketHandler(); setLocalContact(); } public long getTimeout() { return( request_timeout ); } public void setTimeout( long timeout ) { if ( request_timeout == timeout ){ return; } request_timeout = timeout; store_timeout = request_timeout * STORE_TIMEOUT_MULTIPLIER; packet_handler.setDelays( dht_send_delay, dht_receive_delay, (int)request_timeout ); } public int getNetwork() { return( network ); } public void testInstanceIDChange() throws DHTTransportException { local_contact = new DHTTransportUDPContactImpl( true, this, local_contact.getTransportAddress(), local_contact.getExternalAddress(), protocol_version, random.nextInt(), 0); } public void testTransportIDChange() throws DHTTransportException { if ( external_address.equals("127.0.0.1")){ external_address = "192.168.0.2"; }else{ external_address = "127.0.0.1"; } InetSocketAddress address = new InetSocketAddress( external_address, port ); local_contact = new DHTTransportUDPContactImpl( true, this, address, address, protocol_version, local_contact.getInstanceID(), 0 ); for (int i=0;i vals = routable_contact_history.values(); DHTTransportContact[] res = new DHTTransportContact[vals.size()]; vals.toArray( res ); return( res ); }finally{ this_mon.exit(); } } public DHTTransportContact[] getRecentContacts() { try{ this_mon.enter(); Collection vals = contact_history.values(); DHTTransportContact[] res = new DHTTransportContact[vals.size()]; vals.toArray( res ); return( res ); }finally{ this_mon.exit(); } } protected void updateContactStatus( DHTTransportUDPContactImpl contact, int status, boolean incoming ) { try{ this_mon.enter(); contact.setNodeStatus( status ); if ( contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_XFER_STATUS ){ if ( status != DHTTransportUDPContactImpl.NODE_STATUS_UNKNOWN ){ boolean other_routable = (status & DHTTransportUDPContactImpl.NODE_STATUS_ROUTABLE) != 0; // only maintain stats on incoming requests so we get a fair sample. // in general we'll only get replies from routable contacts so if we // take this into account then everything gets skewed if ( other_routable ){ if ( incoming ){ other_routable_total++; } routable_contact_history.put( contact.getTransportAddress(), contact ); }else{ if ( incoming ){ other_non_routable_total++; } } } } }finally{ this_mon.exit(); } } public int getRouteablePercentage() { synchronized( routeable_percentage_average ){ double average = routeable_percentage_average.getAverage(); long both_total = other_routable_total + other_non_routable_total; int current_percent; if ( both_total == 0 ){ current_percent = 0; }else{ current_percent = (int)(( other_routable_total * 100 )/ both_total ); } if ( both_total >= 300 ){ // add current to average and reset if ( current_percent > 0 ){ average = routeable_percentage_average.update( current_percent ); other_routable_total = other_non_routable_total = 0; } }else if ( both_total >= 100 ){ // if we have enough samples and no existing average then use current if ( average == 0 ){ average = current_percent; }else{ // factor in current percantage int samples = routeable_percentage_average.getSampleCount(); if ( samples > 0 ){ average = (( samples * average ) + current_percent ) / ( samples + 1 ); } } } int result = (int)average; if ( result == 0 ){ // -1 indicates we have no usable value result = -1; } return( result ); } } protected boolean invalidExternalAddress( InetAddress ia ) { return( ia.isLinkLocalAddress() || ia.isLoopbackAddress() || ia.isSiteLocalAddress()); } protected int getMaxFailForLiveCount() { return( max_fails_for_live ); } protected int getMaxFailForUnknownCount() { return( max_fails_for_unknown ); } public DHTTransportContact getLocalContact() { return( local_contact ); } protected void setLocalContact() { InetSocketAddress s_address = new InetSocketAddress( external_address, port ); try{ local_contact = new DHTTransportUDPContactImpl( true, DHTTransportUDPImpl.this, s_address, s_address, protocol_version, random.nextInt(), 0); logger.log( "External address changed: " + s_address ); Debug.out( "DHTTransport: address changed to " + s_address ); for (int i=0;i 60000 ){ last_portmap_dump = now; Iterator it = port_map.keySet().iterator(); Map rev = new TreeMap(); while( it.hasNext()){ Integer key = (Integer)it.next(); Integer val = (Integer)port_map.get(key); rev.put( val, key ); } it = rev.keySet().iterator(); while( it.hasNext()){ Integer val = (Integer)it.next(); Integer key = (Integer)rev.get(val); System.out.println( "port:" + key + "->" + val ); } } }finally{ this_mon.exit(); } */ if ( ip_filter.isEnabled()){ // don't need to synchronize access to the bloom filter as it works fine // without protection (especially as its add only) byte[] addr = contact.getTransportAddress().getAddress().getAddress(); if ( bad_ip_bloom_filter == null ){ bad_ip_bloom_filter = BloomFilterFactory.createAddOnly( BAD_IP_BLOOM_FILTER_SIZE ); }else{ if ( bad_ip_bloom_filter.contains( addr )){ throw( new DHTUDPPacketHandlerException( "IPFilter check fails (repeat)" )); } } if ( ip_filter.isInRange( contact.getTransportAddress().getAddress(), "DHT", null, logger.isEnabled( DHTLogger.LT_IP_FILTER ))){ // don't let an attacker deliberately fill up our filter so we start // rejecting valid addresses if ( bad_ip_bloom_filter.getEntryCount() >= BAD_IP_BLOOM_FILTER_SIZE/10 ){ bad_ip_bloom_filter = BloomFilterFactory.createAddOnly( BAD_IP_BLOOM_FILTER_SIZE ); } bad_ip_bloom_filter.add( addr ); throw( new DHTUDPPacketHandlerException( "IPFilter check fails" )); } } } protected void sendPing( final DHTTransportUDPContactImpl contact, final DHTTransportReplyHandler handler, long timeout, int priority ) { try{ checkAddress( contact ); final long connection_id = getConnectionID(); final DHTUDPPacketRequestPing request = new DHTUDPPacketRequestPing( this, connection_id, local_contact, contact ); stats.pingSent( request ); requestSendRequestProcessor( contact, request ); packet_handler.sendAndReceive( request, contact.getTransportAddress(), new DHTUDPPacketReceiver() { public void packetReceived( DHTUDPPacketReply packet, InetSocketAddress from_address, long elapsed_time ) { try{ if ( packet.getConnectionId() != connection_id ){ throw( new Exception( "connection id mismatch" )); } contact.setInstanceIDAndVersion( packet.getTargetInstanceID(), packet.getProtocolVersion()); requestSendReplyProcessor( contact, handler, packet, elapsed_time ); stats.pingOK(); handler.pingReply( contact, (int)elapsed_time ); }catch( DHTUDPPacketHandlerException e ){ error( e ); }catch( Throwable e ){ Debug.printStackTrace(e); error( new DHTUDPPacketHandlerException( "ping failed", e )); } } public void error( DHTUDPPacketHandlerException e ) { stats.pingFailed(); handler.failed( contact,e ); } }, timeout, priority ); }catch( Throwable e ){ stats.pingFailed(); handler.failed( contact,e ); } } protected void sendPing( final DHTTransportUDPContactImpl contact, final DHTTransportReplyHandler handler ) { sendPing( contact, handler, request_timeout, PRUDPPacketHandler.PRIORITY_MEDIUM ); } protected void sendImmediatePing( final DHTTransportUDPContactImpl contact, final DHTTransportReplyHandler handler, long timeout ) { sendPing( contact, handler, timeout, PRUDPPacketHandler.PRIORITY_IMMEDIATE ); } protected void sendKeyBlockRequest( final DHTTransportUDPContactImpl contact, final DHTTransportReplyHandler handler, byte[] block_request, byte[] block_signature ) { try{ checkAddress( contact ); final long connection_id = getConnectionID(); final DHTUDPPacketRequestKeyBlock request = new DHTUDPPacketRequestKeyBlock( this, connection_id, local_contact, contact ); request.setKeyBlockDetails( block_request, block_signature ); stats.keyBlockSent( request ); request.setRandomID( contact.getRandomID()); requestSendRequestProcessor( contact, request ); packet_handler.sendAndReceive( request, contact.getTransportAddress(), new DHTUDPPacketReceiver() { public void packetReceived( DHTUDPPacketReply packet, InetSocketAddress from_address, long elapsed_time ) { try{ if ( packet.getConnectionId() != connection_id ){ throw( new Exception( "connection id mismatch" )); } contact.setInstanceIDAndVersion( packet.getTargetInstanceID(), packet.getProtocolVersion()); requestSendReplyProcessor( contact, handler, packet, elapsed_time ); stats.keyBlockOK(); handler.keyBlockReply( contact ); }catch( DHTUDPPacketHandlerException e ){ error( e ); }catch( Throwable e ){ Debug.printStackTrace(e); error( new DHTUDPPacketHandlerException( "send key block failed", e )); } } public void error( DHTUDPPacketHandlerException e ) { stats.keyBlockFailed(); handler.failed( contact,e ); } }, request_timeout, PRUDPPacketHandler.PRIORITY_MEDIUM ); }catch( Throwable e ){ stats.keyBlockFailed(); handler.failed( contact,e ); } } // stats protected void sendStats( final DHTTransportUDPContactImpl contact, final DHTTransportReplyHandler handler ) { try{ checkAddress( contact ); final long connection_id = getConnectionID(); final DHTUDPPacketRequestStats request = new DHTUDPPacketRequestStats( this, connection_id, local_contact, contact ); // request.setStatsType( DHTUDPPacketRequestStats.STATS_TYPE_NP_VER2 ); stats.statsSent( request ); requestSendRequestProcessor( contact, request ); packet_handler.sendAndReceive( request, contact.getTransportAddress(), new DHTUDPPacketReceiver() { public void packetReceived( DHTUDPPacketReply packet, InetSocketAddress from_address, long elapsed_time ) { try{ if ( packet.getConnectionId() != connection_id ){ throw( new Exception( "connection id mismatch" )); } contact.setInstanceIDAndVersion( packet.getTargetInstanceID(), packet.getProtocolVersion()); requestSendReplyProcessor( contact, handler, packet, elapsed_time ); DHTUDPPacketReplyStats reply = (DHTUDPPacketReplyStats)packet; stats.statsOK(); if ( reply.getStatsType() == DHTUDPPacketRequestStats.STATS_TYPE_ORIGINAL ){ handler.statsReply( contact, reply.getOriginalStats()); }else{ // currently no handler for new stats System.out.println( "new stats reply:" + reply.getString()); } }catch( DHTUDPPacketHandlerException e ){ error( e ); }catch( Throwable e ){ Debug.printStackTrace(e); error( new DHTUDPPacketHandlerException( "stats failed", e )); } } public void error( DHTUDPPacketHandlerException e ) { stats.statsFailed(); handler.failed( contact, e ); } }, request_timeout, PRUDPPacketHandler.PRIORITY_LOW ); }catch( Throwable e ){ stats.statsFailed(); handler.failed( contact, e ); } } // PING for deducing external IP address protected InetSocketAddress askContactForExternalAddress( DHTTransportUDPContactImpl contact ) { try{ checkAddress( contact ); final long connection_id = getConnectionID(); final DHTUDPPacketRequestPing request = new DHTUDPPacketRequestPing( this, connection_id, local_contact, contact ); stats.pingSent( request ); final AESemaphore sem = new AESemaphore( "DHTTransUDP:extping" ); final InetSocketAddress[] result = new InetSocketAddress[1]; packet_handler.sendAndReceive( request, contact.getTransportAddress(), new DHTUDPPacketReceiver() { public void packetReceived( DHTUDPPacketReply _packet, InetSocketAddress from_address, long elapsed_time ) { try{ if ( _packet instanceof DHTUDPPacketReplyPing ){ // ping was OK so current address is OK result[0] = local_contact.getExternalAddress(); }else if ( _packet instanceof DHTUDPPacketReplyError ){ DHTUDPPacketReplyError packet = (DHTUDPPacketReplyError)_packet; if ( packet.getErrorType() == DHTUDPPacketReplyError.ET_ORIGINATOR_ADDRESS_WRONG ){ result[0] = packet.getOriginatingAddress(); } } }finally{ sem.release(); } } public void error( DHTUDPPacketHandlerException e ) { try{ stats.pingFailed(); }finally{ sem.release(); } } }, 5000, PRUDPPacketHandler.PRIORITY_HIGH ); sem.reserve( 5000 ); return( result[0] ); }catch( Throwable e ){ stats.pingFailed(); return( null ); } } // STORE public void sendStore( final DHTTransportUDPContactImpl contact, final DHTTransportReplyHandler handler, byte[][] keys, DHTTransportValue[][] value_sets, int priority ) { final long connection_id = getConnectionID(); if ( false ){ int total_values = 0; for (int i=0;i key_details ) { try{ checkAddress( contact ); final long connection_id = getConnectionID(); Iterator it = key_details.iterator(); byte[] current_prefix = null; Iterator current_suffixes = null; List requests = new ArrayList(); outer: while( it.hasNext()){ int space = DHTUDPPacketRequestQueryStorage.SPACE; DHTUDPPacketRequestQueryStorage request = new DHTUDPPacketRequestQueryStorage( this, connection_id, local_contact, contact ); List packet_key_details = new ArrayList(); while( space > 0 && it.hasNext()){ if ( current_prefix == null ){ Object[] entry = it.next(); current_prefix = (byte[])entry[0]; List l = (List)entry[1]; current_suffixes = l.iterator(); } if ( current_suffixes.hasNext()){ int min_space = header_size + 3; // 1 byte prefix len, 2 byte num suffix if ( space < min_space ){ request.setDetails( header_size, packet_key_details ); requests.add( request ); continue outer ; } List s = new ArrayList(); packet_key_details.add( new Object[]{ current_prefix, s }); int prefix_size = current_prefix.length; int suffix_size = header_size - prefix_size; space -= ( 3 + prefix_size ); while( space >= suffix_size && current_suffixes.hasNext()){ s.add( current_suffixes.next()); } }else{ current_prefix = null; } } if ( !it.hasNext()){ request.setDetails( header_size, packet_key_details ); requests.add( request ); } } final Object[] replies = new Object[ requests.size() ]; for ( int i=0;i response = new ArrayList(); for ( int i=0;i= data.length ){ logger.log( "dataRequest: invalid start position" ); return( data.length ); } if ( length <= 0 ){ length = data.length; }else if ( start + length > data.length ){ logger.log( "dataRequest: invalid length" ); return( data.length ); } int end = start+length; while( start < end ){ int chunk = end - start; if ( chunk > DHTUDPPacketData.MAX_DATA_SIZE ){ chunk = DHTUDPPacketData.MAX_DATA_SIZE; } if ( write_request ){ sendWriteRequest( connection_id, target, transfer_key, request_key, data, start, chunk, data.length ); if ( first_packet_only ){ break; } }else{ sendReadReply( connection_id, target, transfer_key, request_key, data, start, chunk, data.length ); } start += chunk; } } return( data.length ); } } protected void dataRequest( final DHTTransportUDPContactImpl originator, final DHTUDPPacketData req ) { /* if ((int)(Math.random() * 4 )== 0 ){ System.out.println("dropping request packet:" + req.getString()); return; } */ stats.dataReceived(); // both requests and replies come through here. Currently we only support read // requests so we can safely use the data.length == 0 test to discriminate between // a request and a reply to an existing transfer byte packet_type = req.getPacketType(); if ( XFER_TRACE ){ System.out.println( "dataRequest: originator=" + originator.getAddress() + ",packet=" + req.getString()); } if ( packet_type == DHTUDPPacketData.PT_READ_REPLY ){ transferQueue queue = lookupTransferQueue( read_transfers, req.getConnectionId()); // unmatched -> drop it if ( queue != null ){ queue.add( req ); } }else if ( packet_type == DHTUDPPacketData.PT_WRITE_REPLY ){ transferQueue queue = lookupTransferQueue( write_transfers, req.getConnectionId()); // unmatched -> drop it if ( queue != null ){ queue.add( req ); } }else{ byte[] transfer_key = req.getTransferKey(); if ( packet_type == DHTUDPPacketData.PT_READ_REQUEST ){ try{ handleTransferRequest( originator, req.getConnectionId(), transfer_key, req.getRequestKey(), null, req.getStartPosition(), req.getLength(), false, false ); }catch( DHTTransportException e ){ logger.log(e); } }else{ // write request transferQueue old_queue = lookupTransferQueue( read_transfers, req.getConnectionId()); if ( old_queue != null ){ old_queue.add( req ); }else{ final DHTTransportTransferHandler handler = (DHTTransportTransferHandler)transfer_handlers.get(new HashWrapper( transfer_key )); if ( handler == null ){ logger.log( "No transfer handler registered for key '" + ByteFormatter.encodeString(transfer_key) + "'" ); }else{ try{ final transferQueue new_queue = new transferQueue( read_transfers, req.getConnectionId()); // add the initial data for this write request new_queue.add( req ); // set up the queue processor try{ this_mon.enter(); if ( active_write_queue_processor_count >= TRANSFER_QUEUE_MAX ){ new_queue.destroy(); throw( new DHTTransportException( "Active write queue process thread limit exceeded" )); } active_write_queue_processor_count++; if ( XFER_TRACE ){ System.out.println( "active_write_queue_processor_count=" + active_write_queue_processor_count ); } }finally{ this_mon.exit(); } new AEThread2( "DHTTransportUDP:writeQueueProcessor", true ) { public void run() { try{ byte[] write_data = runTransferQueue( new_queue, new DHTTransportProgressListener() { public void reportSize( long size ) { if ( XFER_TRACE ){ System.out.println( "writeXfer: size=" + size ); } } public void reportActivity( String str ) { if ( XFER_TRACE ){ System.out.println( "writeXfer: act=" + str ); } } public void reportCompleteness( int percent ) { if ( XFER_TRACE ){ System.out.println( "writeXfer: %=" + percent ); } } }, originator, req.getTransferKey(), req.getRequestKey(), 60000, false ); if ( write_data != null ){ // xfer complete, send ack if multi-packet xfer // (ack already sent below if single packet) if ( req.getStartPosition() != 0 || req.getLength() != req.getTotalLength() ){ sendWriteReply( req.getConnectionId(), originator, req.getTransferKey(), req.getRequestKey(), 0, req.getTotalLength()); } byte[] reply_data = handler.handleWrite( originator, req.getRequestKey(), write_data ); if ( reply_data != null ){ writeTransfer( new DHTTransportProgressListener() { public void reportSize( long size ) { if ( XFER_TRACE ){ System.out.println( "writeXferReply: size=" + size ); } } public void reportActivity( String str ) { if ( XFER_TRACE ){ System.out.println( "writeXferReply: act=" + str ); } } public void reportCompleteness( int percent ) { if ( XFER_TRACE ){ System.out.println( "writeXferReply: %=" + percent ); } } }, originator, req.getTransferKey(), req.getRequestKey(), reply_data, WRITE_REPLY_TIMEOUT ); } } }catch( DHTTransportException e ){ logger.log( "Failed to process transfer queue: " + Debug.getNestedExceptionMessage(e)); }finally{ try{ this_mon.enter(); active_write_queue_processor_count--; if ( XFER_TRACE ){ System.out.println( "active_write_queue_processor_count=" + active_write_queue_processor_count ); } }finally{ this_mon.exit(); } } } }.start(); // indicate that at least one packet has been received sendWriteReply( req.getConnectionId(), originator, req.getTransferKey(), req.getRequestKey(), req.getStartPosition(), req.getLength()); }catch( DHTTransportException e ){ logger.log( "Faild to create transfer queue" ); logger.log( e ); } } } } } } public byte[] readTransfer( DHTTransportProgressListener listener, DHTTransportContact target, byte[] handler_key, byte[] key, long timeout ) throws DHTTransportException { long connection_id = getConnectionID(); transferQueue transfer_queue = new transferQueue( read_transfers, connection_id ); return( runTransferQueue( transfer_queue, listener, target, handler_key, key, timeout, true )); } protected byte[] runTransferQueue( transferQueue transfer_queue, DHTTransportProgressListener listener, DHTTransportContact target, byte[] handler_key, byte[] key, long timeout, boolean read_transfer ) throws DHTTransportException { SortedSet packets = new TreeSet( new Comparator() { public int compare( Object o1, Object o2 ) { DHTUDPPacketData p1 = (DHTUDPPacketData)o1; DHTUDPPacketData p2 = (DHTUDPPacketData)o2; return( p1.getStartPosition() - p2.getStartPosition()); } }); int entire_request_count = 0; int transfer_size = -1; int transferred = 0; String target_name = DHTLog.getString2(target.getID()); try{ long start = SystemTime.getCurrentTime(); if ( read_transfer ){ listener.reportActivity( getMessageText( "request_all", target_name )); entire_request_count++; sendReadRequest( transfer_queue.getID(), (DHTTransportUDPContactImpl)target, handler_key, key ); }else{ // write transfer - data already on its way, no need to request it entire_request_count++; } while( SystemTime.getCurrentTime() - start <= timeout ){ DHTUDPPacketData reply = transfer_queue.receive( READ_XFER_REREQUEST_DELAY ); if ( reply != null ){ if ( transfer_size == -1 ){ transfer_size = reply.getTotalLength(); listener.reportSize( transfer_size ); } Iterator it = packets.iterator(); boolean duplicate = false; while( it.hasNext()){ DHTUDPPacketData p = (DHTUDPPacketData)it.next(); // ignore overlaps if ( p.getStartPosition() < reply.getStartPosition() + reply.getLength() && p.getStartPosition() + p.getLength() > reply.getStartPosition()){ duplicate = true; break; } } if ( !duplicate ){ listener.reportActivity( getMessageText( "received_bit", new String[]{ String.valueOf( reply.getStartPosition()), String.valueOf(reply.getStartPosition() + reply.getLength()), target_name })); transferred += reply.getLength(); listener.reportCompleteness( transfer_size==0?100: ( 100 * transferred / transfer_size )); packets.add( reply ); // see if we're done it = packets.iterator(); int pos = 0; int actual_end = -1; while( it.hasNext()){ DHTUDPPacketData p = (DHTUDPPacketData)it.next(); if ( actual_end == -1 ){ actual_end = p.getTotalLength(); } if ( p.getStartPosition() != pos ){ // missing data, give up break; } pos += p.getLength(); if ( pos == actual_end ){ // huzzah, we got the lot listener.reportActivity( getMessageText( "complete" )); byte[] result = new byte[actual_end]; it = packets.iterator(); pos = 0; while( it.hasNext()){ p = (DHTUDPPacketData)it.next(); System.arraycopy( p.getData(), 0, result, pos, p.getLength()); pos += p.getLength(); } return( result ); } } } }else{ // timeout, look for missing bits if ( packets.size() == 0 ){ if ( entire_request_count == 2 ){ listener.reportActivity( getMessageText( "timeout", target_name )); return( null ); } entire_request_count++; listener.reportActivity( getMessageText( "rerequest_all", target_name )); sendReadRequest( transfer_queue.getID(), (DHTTransportUDPContactImpl)target, handler_key, key ); }else{ Iterator it = packets.iterator(); int pos = 0; int actual_end = -1; while( it.hasNext()){ DHTUDPPacketData p = (DHTUDPPacketData)it.next(); if ( actual_end == -1 ){ actual_end = p.getTotalLength(); } if ( p.getStartPosition() != pos ){ listener.reportActivity( getMessageText( "rerequest_bit", new String[]{ String.valueOf( pos ), String.valueOf( p.getStartPosition()), target_name })); sendReadRequest( transfer_queue.getID(), (DHTTransportUDPContactImpl)target, handler_key, key, pos, p.getStartPosition()-pos ); } pos = p.getStartPosition() + p.getLength(); } if ( pos != actual_end ){ listener.reportActivity( getMessageText( "rerequest_bit", new String[]{ String.valueOf( pos ), String.valueOf( actual_end ), target_name })); sendReadRequest( transfer_queue.getID(), (DHTTransportUDPContactImpl)target, handler_key, key, pos, actual_end - pos ); } } } } if ( packets.size()==0 ){ listener.reportActivity( getMessageText( "timeout", target_name )); }else{ listener.reportActivity( getMessageText( "timeout_some", new String[]{ String.valueOf( packets.size()), target_name })); } return( null ); }finally{ transfer_queue.destroy(); } } public void writeTransfer( DHTTransportProgressListener listener, DHTTransportContact target, byte[] handler_key, byte[] key, byte[] data, long timeout ) throws DHTTransportException { transferQueue transfer_queue = null; try{ long connection_id = getConnectionID(); transfer_queue = new transferQueue( write_transfers, connection_id ); boolean ok = false; boolean reply_received = false; int loop = 0; int total_length = data.length; long start = SystemTime.getCurrentTime(); long last_packet_time = 0; while( true ){ long now = SystemTime.getCurrentTime(); if ( now < start ){ start = now; last_packet_time = 0; }else{ if ( now - start > timeout ){ break; } } long time_since_last_packet = now - last_packet_time; if ( time_since_last_packet >= WRITE_XFER_RESEND_DELAY ){ listener.reportActivity( getMessageText( loop==0?"sending":"resending" )); loop++; total_length = handleTransferRequest( (DHTTransportUDPContactImpl)target, connection_id, handler_key, key, data, -1, -1, true, reply_received ); // first packet only if we've has a reply last_packet_time = now; time_since_last_packet = 0; } DHTUDPPacketData packet = transfer_queue.receive( WRITE_XFER_RESEND_DELAY - time_since_last_packet ); if ( packet != null ){ last_packet_time = now; reply_received = true; if ( packet.getStartPosition() == 0 && packet.getLength() == total_length ){ ok = true; break; } } } if ( ok ){ listener.reportCompleteness( 100 ); listener.reportActivity( getMessageText( "send_complete" )); }else{ listener.reportActivity( getMessageText( "send_timeout" )); throw( new DHTTransportException( "Timeout" )); } }finally{ if ( transfer_queue != null ){ transfer_queue.destroy(); } } } public byte[] writeReadTransfer( DHTTransportProgressListener listener, DHTTransportContact target, byte[] handler_key, byte[] data, long timeout ) throws DHTTransportException { byte[] call_key = new byte[20]; random.nextBytes( call_key ); AESemaphore call_sem = new AESemaphore( "DHTTransportUDP:calSem" ); HashWrapper wrapped_key = new HashWrapper( call_key ); try{ this_mon.enter(); call_transfers.put( wrapped_key, call_sem ); }finally{ this_mon.exit(); } writeTransfer( listener, target, handler_key, call_key, data, timeout ); if ( call_sem.reserve( timeout )){ try{ this_mon.enter(); Object res = call_transfers.remove( wrapped_key ); if ( res instanceof byte[] ){ return((byte[])res); } }finally{ this_mon.exit(); } } throw( new DHTTransportException( "timeout" )); } public void process( DHTUDPPacketRequest request, boolean alien ) { if ( request_handler == null ){ logger.log( "Ignoring packet as not yet ready to process" ); return; } try{ stats.incomingRequestReceived( request, alien ); InetSocketAddress transport_address = request.getAddress(); DHTTransportUDPContactImpl originating_contact = new DHTTransportUDPContactImpl( false, this, transport_address, request.getOriginatorAddress(), request.getOriginatorVersion(), request.getOriginatorInstanceID(), request.getClockSkew()); try{ checkAddress( originating_contact ); }catch( DHTUDPPacketHandlerException e ){ return; } requestReceiveRequestProcessor( originating_contact, request ); boolean bad_originator = !originating_contact.addressMatchesID(); // bootstrap node returns details regardless of whether the originator ID matches // as the details will help the sender discover their correct ID (hopefully) if ( bad_originator && !bootstrap_node ){ String contact_string = originating_contact.getString(); if ( recent_reports.get(contact_string) == null ){ recent_reports.put( contact_string, "" ); logger.log( "Node " + contact_string + " has incorrect ID, reporting it to them" ); } DHTUDPPacketReplyError reply = new DHTUDPPacketReplyError( this, request.getTransactionId(), request.getConnectionId(), local_contact, originating_contact ); reply.setErrorType( DHTUDPPacketReplyError.ET_ORIGINATOR_ADDRESS_WRONG ); reply.setOriginatingAddress( originating_contact.getTransportAddress()); requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); }else{ if ( bad_originator ){ // we need to patch the originator up otherwise we'll be populating our // routing table with crap originating_contact = new DHTTransportUDPContactImpl( false, this, transport_address, transport_address, // set originator address to transport request.getOriginatorVersion(), request.getOriginatorInstanceID(), request.getClockSkew()); }else{ contactAlive( originating_contact ); } if ( request instanceof DHTUDPPacketRequestPing ){ if ( !bootstrap_node ){ request_handler.pingRequest( originating_contact ); DHTUDPPacketReplyPing reply = new DHTUDPPacketReplyPing( this, request.getTransactionId(), request.getConnectionId(), local_contact, originating_contact ); requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); } }else if ( request instanceof DHTUDPPacketRequestKeyBlock ){ if ( !bootstrap_node ){ DHTUDPPacketRequestKeyBlock kb_request = (DHTUDPPacketRequestKeyBlock)request; originating_contact.setRandomID( kb_request.getRandomID()); request_handler.keyBlockRequest( originating_contact, kb_request.getKeyBlockRequest(), kb_request.getKeyBlockSignature()); DHTUDPPacketReplyKeyBlock reply = new DHTUDPPacketReplyKeyBlock( this, request.getTransactionId(), request.getConnectionId(), local_contact, originating_contact ); requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); } }else if ( request instanceof DHTUDPPacketRequestStats ){ DHTUDPPacketRequestStats stats_request = (DHTUDPPacketRequestStats)request; DHTUDPPacketReplyStats reply = new DHTUDPPacketReplyStats( this, request.getTransactionId(), request.getConnectionId(), local_contact, originating_contact ); int type = stats_request.getStatsType(); if ( type == DHTUDPPacketRequestStats.STATS_TYPE_ORIGINAL ){ DHTTransportFullStats full_stats = request_handler.statsRequest( originating_contact ); reply.setOriginalStats( full_stats ); }else if ( type == DHTUDPPacketRequestStats.STATS_TYPE_NP_VER2 ){ DHTNetworkPositionProvider prov = DHTNetworkPositionManager.getProvider( DHTNetworkPosition.POSITION_TYPE_VIVALDI_V2 ); byte[] data = new byte[0]; if ( prov != null ){ ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream( baos ); prov.serialiseStats( dos ); dos.flush(); data = baos.toByteArray(); } reply.setNewStats( data, DHTNetworkPosition.POSITION_TYPE_VIVALDI_V2 ); }else{ throw( new IOException( "Uknown stats type '" + type + "'" )); } requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); }else if ( request instanceof DHTUDPPacketRequestStore ){ if ( !bootstrap_node ){ DHTUDPPacketRequestStore store_request = (DHTUDPPacketRequestStore)request; originating_contact.setRandomID( store_request.getRandomID()); DHTTransportStoreReply res = request_handler.storeRequest( originating_contact, store_request.getKeys(), store_request.getValueSets()); if ( res.blocked()){ if ( originating_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_BLOCK_KEYS ){ DHTUDPPacketReplyError reply = new DHTUDPPacketReplyError( this, request.getTransactionId(), request.getConnectionId(), local_contact, originating_contact ); reply.setErrorType( DHTUDPPacketReplyError.ET_KEY_BLOCKED ); reply.setKeyBlockDetails( res.getBlockRequest(), res.getBlockSignature() ); requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); }else{ DHTUDPPacketReplyStore reply = new DHTUDPPacketReplyStore( this, request.getTransactionId(), request.getConnectionId(), local_contact, originating_contact ); reply.setDiversificationTypes( new byte[store_request.getKeys().length] ); requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); } }else{ DHTUDPPacketReplyStore reply = new DHTUDPPacketReplyStore( this, request.getTransactionId(), request.getConnectionId(), local_contact, originating_contact ); reply.setDiversificationTypes( res.getDiversificationTypes()); requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); } } }else if ( request instanceof DHTUDPPacketRequestQueryStorage ){ DHTUDPPacketRequestQueryStorage query_request = (DHTUDPPacketRequestQueryStorage)request; DHTTransportQueryStoreReply res = request_handler.queryStoreRequest( originating_contact, query_request.getHeaderLength(), query_request.getKeys()); DHTUDPPacketReplyQueryStorage reply = new DHTUDPPacketReplyQueryStorage( this, request.getTransactionId(), request.getConnectionId(), local_contact, originating_contact ); reply.setRandomID( originating_contact.getRandomID()); reply.setResponse( res.getHeaderSize(), res.getEntries()); requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); }else if ( request instanceof DHTUDPPacketRequestFindNode ){ DHTUDPPacketRequestFindNode find_request = (DHTUDPPacketRequestFindNode)request; boolean acceptable; // as a bootstrap node we only accept find-node requests for the originator's // ID if ( bootstrap_node ){ // let bad originators through to aid bootstrapping with bad IP acceptable = bad_originator || Arrays.equals( find_request.getID(), originating_contact.getID()); }else{ acceptable = true; } if ( acceptable ){ if ( find_request.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_MORE_NODE_STATUS ){ updateContactStatus( originating_contact, find_request.getNodeStatus(), true ); request_handler.setTransportEstimatedDHTSize( find_request.getEstimatedDHTSize()); } DHTTransportContact[] res = request_handler.findNodeRequest( originating_contact, find_request.getID()); DHTUDPPacketReplyFindNode reply = new DHTUDPPacketReplyFindNode( this, request.getTransactionId(), request.getConnectionId(), local_contact, originating_contact ); reply.setRandomID( originating_contact.getRandomID()); reply.setNodeStatus( getNodeStatus()); reply.setEstimatedDHTSize( request_handler.getTransportEstimatedDHTSize()); reply.setContacts( res ); requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); } }else if ( request instanceof DHTUDPPacketRequestFindValue ){ if ( !bootstrap_node ){ DHTUDPPacketRequestFindValue find_request = (DHTUDPPacketRequestFindValue)request; DHTTransportFindValueReply res = request_handler.findValueRequest( originating_contact, find_request.getID(), find_request.getMaximumValues(), find_request.getFlags()); if ( res.blocked()){ if ( originating_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_BLOCK_KEYS ){ DHTUDPPacketReplyError reply = new DHTUDPPacketReplyError( this, request.getTransactionId(), request.getConnectionId(), local_contact, originating_contact ); reply.setErrorType( DHTUDPPacketReplyError.ET_KEY_BLOCKED ); reply.setKeyBlockDetails( res.getBlockedKey(), res.getBlockedSignature() ); requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); }else{ DHTUDPPacketReplyFindValue reply = new DHTUDPPacketReplyFindValue( this, request.getTransactionId(), request.getConnectionId(), local_contact, originating_contact ); reply.setValues( new DHTTransportValue[0], DHT.DT_NONE, false ); requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); } }else{ DHTUDPPacketReplyFindValue reply = new DHTUDPPacketReplyFindValue( this, request.getTransactionId(), request.getConnectionId(), local_contact, originating_contact ); if ( res.hit()){ DHTTransportValue[] res_values = res.getValues(); int max_size = DHTUDPPacketHelper.PACKET_MAX_BYTES - DHTUDPPacketReplyFindValue.DHT_FIND_VALUE_HEADER_SIZE; List values = new ArrayList(); int values_size = 0; int pos = 0; while( pos < res_values.length ){ DHTTransportValue v = res_values[pos]; int v_len = v.getValue().length + DHTUDPPacketReplyFindValue.DHT_FIND_VALUE_TV_HEADER_SIZE; if ( values_size > 0 && // if value too big, cram it in anyway values_size + v_len > max_size ){ // won't fit, send what we've got DHTTransportValue[] x = new DHTTransportValue[values.size()]; values.toArray( x ); reply.setValues( x, res.getDiversificationType(), true ); // continuation = true packet_handler.send( reply, request.getAddress()); values_size = 0; values = new ArrayList(); }else{ values.add(v); values_size += v_len; pos++; } } // send the remaining (possible zero length) non-continuation values DHTTransportValue[] x = new DHTTransportValue[values.size()]; values.toArray( x ); reply.setValues( x, res.getDiversificationType(), false ); requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); }else{ reply.setContacts(res.getContacts()); requestReceiveReplyProcessor( originating_contact, reply ); packet_handler.send( reply, request.getAddress()); } } } }else if ( request instanceof DHTUDPPacketData ){ if ( !bootstrap_node ){ dataRequest(originating_contact, (DHTUDPPacketData)request ); } }else{ Debug.out( "Unexpected packet:" + request.toString()); } } }catch( DHTUDPPacketHandlerException e ){ // not interesting, send packet fail or something }catch( Throwable e ){ Debug.printStackTrace(e); } } protected void requestReceiveRequestProcessor( DHTTransportUDPContactImpl contact, DHTUDPPacketRequest request ) { // called when request received } protected void requestReceiveReplyProcessor( DHTTransportUDPContactImpl contact, DHTUDPPacketReply reply ) { // called before sending reply to request int action = reply.getAction(); if ( action == DHTUDPPacketHelper.ACT_REPLY_PING || action == DHTUDPPacketHelper.ACT_REPLY_FIND_NODE || action == DHTUDPPacketHelper.ACT_REPLY_FIND_VALUE ){ reply.setNetworkPositions( local_contact.getNetworkPositions()); } } protected void requestSendRequestProcessor( DHTTransportUDPContactImpl contact, DHTUDPPacketRequest request ) { // called before sending request } /** * Returns false if this isn't an error reply, true if it is and a retry can be * performed, throws an exception otherwise * @param reply * @return */ protected void requestSendReplyProcessor( DHTTransportUDPContactImpl remote_contact, DHTTransportReplyHandler handler, DHTUDPPacketReply reply, long elapsed_time ) throws DHTUDPPacketHandlerException { // called after receiving reply to request // System.out.println( "request:" + contact.getAddress() + " = " + elapsed_time ); DHTNetworkPosition[] remote_nps = reply.getNetworkPositions(); if ( remote_nps != null ){ // save current position of target remote_contact.setNetworkPositions( remote_nps ); // update local positions DHTNetworkPositionManager.update( local_contact.getNetworkPositions(), remote_contact.getID(), remote_nps, (float)elapsed_time ); } if ( reply.getAction() == DHTUDPPacketHelper.ACT_REPLY_ERROR ){ DHTUDPPacketReplyError error = (DHTUDPPacketReplyError)reply; switch( error.getErrorType()){ case DHTUDPPacketReplyError.ET_ORIGINATOR_ADDRESS_WRONG: { try{ externalAddressChange( remote_contact, error.getOriginatingAddress(), false ); }catch( DHTTransportException e ){ Debug.printStackTrace(e); } throw( new DHTUDPPacketHandlerException( "address changed notification" )); } case DHTUDPPacketReplyError.ET_KEY_BLOCKED: { handler.keyBlockRequest( remote_contact, error.getKeyBlockRequest(), error.getKeyBlockSignature()); contactAlive( remote_contact ); throw( new DHTUDPPacketHandlerException( "key blocked" )); } } throw( new DHTUDPPacketHandlerException( "unknown error type " + error.getErrorType())); }else{ contactAlive( remote_contact ); } } protected long getConnectionID() { // unfortunately, to reuse the UDP port with the tracker protocol we // have to distinguish our connection ids by setting the MSB. This allows // the decode to work as there is no common header format for the request // and reply packets // note that tracker usage of UDP via this handler is only for outbound // messages, hence for that use a request will never be received by the // handler return( 0x8000000000000000L | random.nextLong()); } public boolean supportsStorage() { return( !bootstrap_node ); } public void addListener( DHTTransportListener l ) { listeners.add(l); if ( external_address != null ){ l.currentAddress( external_address ); } } public void removeListener( DHTTransportListener l ) { listeners.remove(l); } protected transferQueue lookupTransferQueue( Map transfers, long id ) { try{ this_mon.enter(); return((transferQueue)transfers.get(new Long(id))); }finally{ this_mon.exit(); } } protected String getMessageText( String resource ) { return( MessageText.getString( "DHTTransport.report." + resource )); } protected String getMessageText( String resource, String param ) { return( MessageText.getString( "DHTTransport.report." + resource, new String[]{ param })); } protected String getMessageText( String resource, String[] params ) { return( MessageText.getString( "DHTTransport.report." + resource, params)); } protected class transferQueue { private Map transfers; private long id; private boolean destroyed; private List packets = new ArrayList(); private AESemaphore packets_sem = new AESemaphore("DHTUDPTransport:transferQueue"); protected transferQueue( Map _transfers, long _id ) throws DHTTransportException { transfers = _transfers; id = _id; try{ this_mon.enter(); if ( transfers.size() > TRANSFER_QUEUE_MAX ){ Debug.out( "Transfer queue count limit exceeded" ); throw( new DHTTransportException( "Transfer queue limit exceeded" )); } Long l_id = new Long( id ); transferQueue existing = (transferQueue)transfers.get( l_id ); if ( existing != null ){ existing.destroy(); } transfers.put( l_id, this ); }finally{ this_mon.exit(); } } protected long getID() { return( id ); } protected void add( DHTUDPPacketData packet ) { try{ this_mon.enter(); if ( destroyed ){ return; } if ( total_bytes_on_transfer_queues > MAX_TRANSFER_QUEUE_BYTES ){ Debug.out( "Transfer queue byte limit exceeded" ); // just drop the packet return; } int length = packet.getLength(); total_bytes_on_transfer_queues += length; if ( XFER_TRACE ){ System.out.println( "total_bytes_on_transfer_queues=" + total_bytes_on_transfer_queues ); } packets.add( packet ); }finally{ this_mon.exit(); } packets_sem.release(); } protected DHTUDPPacketData receive( long timeout ) { if ( packets_sem.reserve( timeout )){ try{ this_mon.enter(); if ( destroyed ){ return( null ); } DHTUDPPacketData packet = (DHTUDPPacketData)packets.remove(0); int length = packet.getLength(); total_bytes_on_transfer_queues -= length; if ( XFER_TRACE ){ System.out.println( "total_bytes_on_transfer_queues=" + total_bytes_on_transfer_queues ); } return( packet ); }finally{ this_mon.exit(); } }else{ return( null ); } } protected void destroy() { try{ this_mon.enter(); destroyed = true; transfers.remove( new Long( id )); for (int i=0;i= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF ){ random_id = is.readInt(); } if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_XFER_STATUS ){ node_status = is.readInt(); } if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_SIZE_ESTIMATE ){ estimated_dht_size = is.readInt(); } if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_VIVALDI ){ DHTUDPUtils.deserialiseVivaldi( this, is ); } contacts = DHTUDPUtils.deserialiseContacts( getTransport(), is ); } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF ){ os.writeInt( random_id ); } if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_XFER_STATUS ){ os.writeInt( node_status ); } if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_SIZE_ESTIMATE ){ os.writeInt( estimated_dht_size ); } if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_VIVALDI ){ DHTUDPUtils.serialiseVivaldi( this, os ); } DHTUDPUtils.serialiseContacts( os, contacts ); } protected void setContacts( DHTTransportContact[] _contacts ) { contacts = _contacts; } protected void setRandomID( int _random_id ) { random_id = _random_id; } protected int getRandomID() { return( random_id ); } protected void setNodeStatus( int ns ) { node_status = ns; } protected int getNodeStatus() { return( node_status ); } protected void setEstimatedDHTSize( int s ) { estimated_dht_size = s; } protected int getEstimatedDHTSize() { return( estimated_dht_size ); } protected DHTTransportContact[] getContacts() { return( contacts ); } public String getString() { return( super.getString() + ",contacts=" + (contacts==null?"null":(""+contacts.length ))); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestFindValue.java0000644000175000017500000000553210373051014032171 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; /** * @author parg * */ public class DHTUDPPacketRequestFindValue extends DHTUDPPacketRequest { private byte[] id; private byte flags; private byte maximum_values; public DHTUDPPacketRequestFindValue( DHTTransportUDPImpl _transport, long _connection_id, DHTTransportUDPContactImpl _local_contact, DHTTransportUDPContactImpl _remote_contact ) { super( _transport, DHTUDPPacketHelper.ACT_REQUEST_FIND_VALUE, _connection_id, _local_contact, _remote_contact ); } protected DHTUDPPacketRequestFindValue( DHTUDPPacketNetworkHandler network_handler, DataInputStream is, long con_id, int trans_id ) throws IOException { super( network_handler, is, DHTUDPPacketHelper.ACT_REQUEST_FIND_VALUE, con_id, trans_id ); id = DHTUDPUtils.deserialiseByteArray( is, 64 ); flags = is.readByte(); maximum_values = is.readByte(); super.postDeserialise(is); } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); DHTUDPUtils.serialiseByteArray( os, id, 64 ); os.writeByte( flags ); os.writeByte( maximum_values ); super.postSerialise( os ); } protected void setID( byte[] _id ) { id = _id; } protected byte[] getID() { return( id ); } protected byte getFlags() { return( flags ); } protected void setFlags( byte _flags ) { flags = _flags; } protected void setMaximumValues( int max ) { if ( max > 255 ){ max = 255; } maximum_values = (byte)max; } protected int getMaximumValues() { return( maximum_values&0xff ); } public String getString() { return( super.getString()); } }azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestKeyBlock.java0000644000175000017500000000570510402150270032016 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; /** * @author parg * */ public class DHTUDPPacketRequestKeyBlock extends DHTUDPPacketRequest { private int random_id; private byte[] key_block_request; private byte[] key_block_signature; public DHTUDPPacketRequestKeyBlock( DHTTransportUDPImpl _transport, long _connection_id, DHTTransportUDPContactImpl _local_contact, DHTTransportUDPContactImpl _remote_contact ) { super( _transport, DHTUDPPacketHelper.ACT_REQUEST_KEY_BLOCK, _connection_id, _local_contact, _remote_contact ); } protected DHTUDPPacketRequestKeyBlock( DHTUDPPacketNetworkHandler network_handler, DataInputStream is, long con_id, int trans_id ) throws IOException { super( network_handler, is, DHTUDPPacketHelper.ACT_REQUEST_KEY_BLOCK, con_id, trans_id ); random_id = is.readInt(); key_block_request = DHTUDPUtils.deserialiseByteArray( is, 255 ); key_block_signature = DHTUDPUtils.deserialiseByteArray( is, 65535 ); super.postDeserialise(is); } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); os.writeInt( random_id ); DHTUDPUtils.serialiseByteArray( os, key_block_request, 255 ); DHTUDPUtils.serialiseByteArray( os, key_block_signature , 65535); super.postSerialise( os ); } public void setKeyBlockDetails( byte[] req, byte[] sig ) { key_block_request = req; key_block_signature = sig; } protected void setRandomID( int _random_id ) { random_id = _random_id; } protected int getRandomID() { return( random_id ); } public byte[] getKeyBlockRequest() { return( key_block_request ); } public byte[] getKeyBlockSignature() { return( key_block_signature ); } public String getString() { return( super.getString()); } }azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestFindNode.java0000644000175000017500000000611311104431514031776 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; /** * @author parg * */ public class DHTUDPPacketRequestFindNode extends DHTUDPPacketRequest { private byte[] id; private int node_status; private int estimated_dht_size; public DHTUDPPacketRequestFindNode( DHTTransportUDPImpl _transport, long _connection_id, DHTTransportUDPContactImpl _local_contact, DHTTransportUDPContactImpl _remote_contact ) { super( _transport, DHTUDPPacketHelper.ACT_REQUEST_FIND_NODE, _connection_id, _local_contact, _remote_contact ); } protected DHTUDPPacketRequestFindNode( DHTUDPPacketNetworkHandler network_handler, DataInputStream is, long con_id, int trans_id ) throws IOException { super( network_handler, is, DHTUDPPacketHelper.ACT_REQUEST_FIND_NODE, con_id, trans_id ); id = DHTUDPUtils.deserialiseByteArray( is, 64 ); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_MORE_NODE_STATUS ){ node_status = is.readInt(); estimated_dht_size = is.readInt(); } super.postDeserialise(is); } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); DHTUDPUtils.serialiseByteArray( os, id, 64 ); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_MORE_NODE_STATUS ){ os.writeInt( node_status ); os.writeInt( estimated_dht_size ); } super.postSerialise( os ); } protected void setID( byte[] _id ) { id = _id; } protected byte[] getID() { return( id ); } protected void setNodeStatus( int ns ) { node_status = ns; } protected int getNodeStatus() { return( node_status ); } protected void setEstimatedDHTSize( int s ) { estimated_dht_size = s; } protected int getEstimatedDHTSize() { return( estimated_dht_size ); } public String getString() { return( super.getString()); } }azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyError.java0000644000175000017500000000733211033103414031044 0ustar adrianadrian/* * File : PRUDPPacketReplyConnect.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.dht.transport.udp.impl; /** * @author parg * */ import java.io.*; import java.net.InetSocketAddress; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportException; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; public class DHTUDPPacketReplyError extends DHTUDPPacketReply { public static final int ET_UNKNOWN = 0; public static final int ET_ORIGINATOR_ADDRESS_WRONG = 1; public static final int ET_KEY_BLOCKED = 2; private int error_type = ET_UNKNOWN; private InetSocketAddress originator_address; private byte[] key_block_request; private byte[] key_block_signature; public DHTUDPPacketReplyError( DHTTransportUDPImpl transport, int trans_id, long conn_id, DHTTransportContact local_contact, DHTTransportContact remote_contact ) { super( transport, DHTUDPPacketHelper.ACT_REPLY_ERROR, trans_id, conn_id, local_contact, remote_contact ); } protected DHTUDPPacketReplyError( DHTUDPPacketNetworkHandler network_handler, InetSocketAddress originator, DataInputStream is, int trans_id ) throws IOException { super( network_handler, originator, is, DHTUDPPacketHelper.ACT_REPLY_ERROR, trans_id ); error_type = is.readInt(); if ( error_type == ET_ORIGINATOR_ADDRESS_WRONG ){ originator_address = DHTUDPUtils.deserialiseAddress( is ); }else if( error_type == ET_KEY_BLOCKED ){ key_block_request = DHTUDPUtils.deserialiseByteArray( is, 255 ); key_block_signature = DHTUDPUtils.deserialiseByteArray( is, 65535 ); } } protected void setErrorType( int error ) { error_type = error; } protected int getErrorType() { return( error_type ); } protected void setOriginatingAddress( InetSocketAddress a ) { originator_address = a; } protected InetSocketAddress getOriginatingAddress() { return( originator_address ); } protected void setKeyBlockDetails( byte[] kbr, byte[] sig ) { key_block_request = kbr; key_block_signature = sig; } protected byte[] getKeyBlockRequest() { return( key_block_request ); } protected byte[] getKeyBlockSignature() { return( key_block_signature ); } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); os.writeInt( error_type ); if ( error_type == ET_ORIGINATOR_ADDRESS_WRONG ){ try{ DHTUDPUtils.serialiseAddress( os, originator_address ); }catch( DHTTransportException e ){ Debug.printStackTrace( e ); throw( new IOException( e.getMessage())); } }else if( error_type == ET_KEY_BLOCKED ){ DHTUDPUtils.serialiseByteArray( os, key_block_request, 255 ); DHTUDPUtils.serialiseByteArray( os, key_block_signature, 65535 ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStats.java0000644000175000017500000000524510425671370031426 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; /** * @author parg * */ public class DHTUDPPacketRequestStats extends DHTUDPPacketRequest { public static final int STATS_TYPE_ORIGINAL = 1; public static final int STATS_TYPE_NP_VER2 = 2; private int stats_type = STATS_TYPE_ORIGINAL; public DHTUDPPacketRequestStats( DHTTransportUDPImpl _transport, long _connection_id, DHTTransportUDPContactImpl _local_contact, DHTTransportUDPContactImpl _remote_contact ) { super( _transport, DHTUDPPacketHelper.ACT_REQUEST_STATS, _connection_id, _local_contact, _remote_contact ); } protected DHTUDPPacketRequestStats( DHTUDPPacketNetworkHandler network_handler, DataInputStream is, long con_id, int trans_id ) throws IOException { super( network_handler, is, DHTUDPPacketHelper.ACT_REQUEST_STATS, con_id, trans_id ); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_GENERIC_NETPOS ){ stats_type = is.readInt(); } super.postDeserialise(is); } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_GENERIC_NETPOS ){ os.writeInt( stats_type ); } super.postSerialise( os ); } public void setStatsType( int _type ) { stats_type = _type; } public int getStatsType() { return( stats_type ); } public String getString() { return( super.getString()); } }azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketHelper.java0000644000175000017500000002062711256615242030176 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.io.*; import java.net.*; import java.util.*; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; import com.aelitis.net.udp.uc.PRUDPPacketHandler; import com.aelitis.net.udp.uc.PRUDPPacketReply; import com.aelitis.net.udp.uc.PRUDPPacketReplyDecoder; import com.aelitis.net.udp.uc.PRUDPPacketRequest; import com.aelitis.net.udp.uc.PRUDPPacketRequestDecoder; /** * @author parg * */ public class DHTUDPPacketHelper { public static final int PACKET_MAX_BYTES = 1400; // these actions have to co-exist with the tracker ones when the connection // is shared, hence 1024 public static final int ACT_REQUEST_PING = 1024; public static final int ACT_REPLY_PING = 1025; public static final int ACT_REQUEST_STORE = 1026; public static final int ACT_REPLY_STORE = 1027; public static final int ACT_REQUEST_FIND_NODE = 1028; public static final int ACT_REPLY_FIND_NODE = 1029; public static final int ACT_REQUEST_FIND_VALUE = 1030; public static final int ACT_REPLY_FIND_VALUE = 1031; public static final int ACT_REPLY_ERROR = 1032; public static final int ACT_REPLY_STATS = 1033; public static final int ACT_REQUEST_STATS = 1034; public static final int ACT_DATA = 1035; public static final int ACT_REQUEST_KEY_BLOCK = 1036; public static final int ACT_REPLY_KEY_BLOCK = 1037; public static final int ACT_REQUEST_QUERY_STORE = 1038; public static final int ACT_REPLY_QUERY_STORE = 1039; private static boolean registered = false; protected static void registerCodecs() { if ( registered ){ return; } registered = true; PRUDPPacketRequestDecoder request_decoder = new PRUDPPacketRequestDecoder() { public PRUDPPacketRequest decode( PRUDPPacketHandler handler, DataInputStream is, long connection_id, int action, int transaction_id ) throws IOException { if ( handler == null ){ // most likely cause is DHT packet ending up on the UDP tracker as it'll get // router here but with a null-handler throw( new IOException( "No handler available for DHT packet decode" )); } DHTUDPPacketNetworkHandler network_handler = (DHTUDPPacketNetworkHandler)handler.getRequestHandler(); if ( network_handler == null ){ // we an get this after a port change and the old port listener is still running (e.g. // its still doing UDP tracker) throw( new IOException( "No network handler available for DHT packet decode" )); } switch( action ){ case ACT_REQUEST_PING: { return( new DHTUDPPacketRequestPing(network_handler,is, connection_id,transaction_id)); } case ACT_REQUEST_STORE: { return( new DHTUDPPacketRequestStore(network_handler,is, connection_id,transaction_id)); } case ACT_REQUEST_FIND_NODE: { return( new DHTUDPPacketRequestFindNode(network_handler,is, connection_id,transaction_id)); } case ACT_REQUEST_FIND_VALUE: { return( new DHTUDPPacketRequestFindValue(network_handler,is, connection_id,transaction_id)); } case ACT_REQUEST_STATS: { return( new DHTUDPPacketRequestStats(network_handler,is, connection_id, transaction_id)); } case ACT_DATA: { return( new DHTUDPPacketData(network_handler,is, connection_id, transaction_id)); } case ACT_REQUEST_KEY_BLOCK: { return( new DHTUDPPacketRequestKeyBlock(network_handler,is, connection_id, transaction_id)); } case ACT_REQUEST_QUERY_STORE: { return( new DHTUDPPacketRequestQueryStorage(network_handler,is, connection_id, transaction_id)); } default: { throw( new IOException( "Unknown action type" )); } } } }; Map request_decoders = new HashMap(); request_decoders.put( new Integer( ACT_REQUEST_PING ), request_decoder ); request_decoders.put( new Integer( ACT_REQUEST_STORE ), request_decoder ); request_decoders.put( new Integer( ACT_REQUEST_FIND_NODE ), request_decoder ); request_decoders.put( new Integer( ACT_REQUEST_FIND_VALUE ), request_decoder ); request_decoders.put( new Integer( ACT_REQUEST_STATS ), request_decoder ); request_decoders.put( new Integer( ACT_DATA ), request_decoder ); request_decoders.put( new Integer( ACT_REQUEST_KEY_BLOCK ), request_decoder ); request_decoders.put( new Integer( ACT_REQUEST_QUERY_STORE ), request_decoder ); PRUDPPacketRequest.registerDecoders( request_decoders ); PRUDPPacketReplyDecoder reply_decoder = new PRUDPPacketReplyDecoder() { public PRUDPPacketReply decode( PRUDPPacketHandler handler, InetSocketAddress originator, DataInputStream is, int action, int transaction_id ) throws IOException { if ( handler == null ){ // most likely cause is DHT packet ending up on the UDP tracker as it'll get // router here but with a null-handler throw( new IOException( "No handler available for DHT packet decode" )); } DHTUDPPacketNetworkHandler network_handler = (DHTUDPPacketNetworkHandler)handler.getRequestHandler(); if ( network_handler == null ){ // we an get this after a port change and the old port listener is still running (e.g. // its still doing UDP tracker) throw( new IOException( "No network handler available for DHT packet decode" )); } switch( action ){ case ACT_REPLY_PING: { return( new DHTUDPPacketReplyPing(network_handler, originator, is, transaction_id)); } case ACT_REPLY_STORE: { return( new DHTUDPPacketReplyStore(network_handler, originator, is, transaction_id)); } case ACT_REPLY_FIND_NODE: { return( new DHTUDPPacketReplyFindNode(network_handler, originator, is, transaction_id)); } case ACT_REPLY_FIND_VALUE: { return( new DHTUDPPacketReplyFindValue(network_handler, originator, is, transaction_id)); } case ACT_REPLY_ERROR: { return( new DHTUDPPacketReplyError(network_handler, originator, is, transaction_id)); } case ACT_REPLY_STATS: { return( new DHTUDPPacketReplyStats( network_handler, originator, is, transaction_id)); } case ACT_REPLY_KEY_BLOCK: { return( new DHTUDPPacketReplyKeyBlock( network_handler, originator, is, transaction_id)); } case ACT_REPLY_QUERY_STORE: { return( new DHTUDPPacketReplyQueryStorage( network_handler, originator, is, transaction_id)); } default: { throw( new IOException( "Unknown action type" )); } } } }; Map reply_decoders = new HashMap(); reply_decoders.put( new Integer( ACT_REPLY_PING ), reply_decoder ); reply_decoders.put( new Integer( ACT_REPLY_STORE ), reply_decoder ); reply_decoders.put( new Integer( ACT_REPLY_FIND_NODE ), reply_decoder ); reply_decoders.put( new Integer( ACT_REPLY_FIND_VALUE ), reply_decoder ); reply_decoders.put( new Integer( ACT_REPLY_ERROR ), reply_decoder ); reply_decoders.put( new Integer( ACT_REPLY_STATS ), reply_decoder ); reply_decoders.put( new Integer( ACT_REPLY_KEY_BLOCK ), reply_decoder ); reply_decoders.put( new Integer( ACT_REPLY_QUERY_STORE ), reply_decoder ); PRUDPPacketReply.registerDecoders( reply_decoders ); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/0000755000175000017500000000000011310377624026651 5ustar adrianadrian././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPRequestHandler.javaazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPRequestHandler.j0000644000175000017500000000231110373051004032645 0ustar adrianadrian/* * Created on 12-Jun-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl.packethandler; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTUDPPacketRequest; public interface DHTUDPRequestHandler { public void process( DHTUDPPacketRequest request, boolean alien ); } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerFactory.javaazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerFac0000644000175000017500000001220710551530002032611 0ustar adrianadrian/* * Created on 12-Jun-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl.packethandler; import java.io.IOException; import java.util.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTTransportUDPImpl; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTUDPPacketRequest; import com.aelitis.net.udp.uc.PRUDPPacketHandler; import com.aelitis.net.udp.uc.PRUDPPacketHandlerFactory; public class DHTUDPPacketHandlerFactory { private static DHTUDPPacketHandlerFactory singleton = new DHTUDPPacketHandlerFactory(); private Map port_map = new HashMap(); protected AEMonitor this_mon = new AEMonitor("DHTUDPPacketHandlerFactory" ); public static DHTUDPPacketHandler getHandler( DHTTransportUDPImpl transport, DHTUDPRequestHandler request_handler ) throws DHTUDPPacketHandlerException { return( singleton.getHandlerSupport( transport, request_handler )); } protected DHTUDPPacketHandler getHandlerSupport( DHTTransportUDPImpl transport, DHTUDPRequestHandler request_handler ) throws DHTUDPPacketHandlerException { try{ this_mon.enter(); int port = transport.getPort(); int network = transport.getNetwork(); Object[] port_details = (Object[])port_map.get( new Integer( port )); if ( port_details == null ){ PRUDPPacketHandler packet_handler = PRUDPPacketHandlerFactory.getHandler( port, new DHTUDPPacketNetworkHandler( this, port )); port_details = new Object[]{ packet_handler, new HashMap()}; port_map.put( new Integer( port ), port_details ); } Map network_map = (Map)port_details[1]; Object[] network_details = (Object[])network_map.get( new Integer( network )); if ( network_details != null ){ throw( new DHTUDPPacketHandlerException( "Network already added" )); } DHTUDPPacketHandler ph = new DHTUDPPacketHandler( this, network, (PRUDPPacketHandler)port_details[0], request_handler ); network_map.put( new Integer( network ), new Object[]{ transport, ph }); return( ph ); }finally{ this_mon.exit(); } } protected void destroy( DHTUDPPacketHandler handler ) { PRUDPPacketHandler packet_handler = handler.getPacketHandler(); try{ packet_handler.setRequestHandler(null); }catch( Throwable e ){ Debug.printStackTrace(e); } int port = packet_handler.getPort(); int network = handler.getNetwork(); try{ this_mon.enter(); Object[] port_details = (Object[])port_map.remove( new Integer( port )); if ( port_details == null ){ return; } Map network_map = (Map)port_details[1]; network_map.remove( new Integer( network )); }finally{ this_mon.exit(); } } protected void process( int port, DHTUDPPacketRequest request ) { try{ int network = request.getNetwork(); /* if ( network != 0 ){ System.out.println( "process:" + network + ":" + request.getString()); } */ Object[] port_details = (Object[])port_map.get( new Integer( port )); if ( port_details == null ){ throw( new IOException( "Port '" + port + "' not registered" )); } Map network_map = (Map)port_details[1]; Object[] network_details = (Object[])network_map.get( new Integer( network )); if ( network_details == null ){ throw( new IOException( "Network '" + network + "' not registered" )); } DHTUDPPacketHandler res = (DHTUDPPacketHandler)network_details[1]; res.receive( request ); }catch( IOException e ){ Debug.printStackTrace( e ); } } public DHTTransportUDPImpl getTransport( int port, int network ) throws IOException { Object[] port_details = (Object[])port_map.get( new Integer( port )); if ( port_details == null ){ throw( new IOException( "Port '" + port + "' not registered" )); } Map network_map = (Map)port_details[1]; Object[] network_details = (Object[])network_map.get( new Integer( network )); if ( network_details == null ){ throw( new IOException( "Network '" + network + "' not registered" )); } return((DHTTransportUDPImpl)network_details[0]); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerStats.javaazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerSta0000644000175000017500000000525210373051004032653 0ustar adrianadrian/* * Created on 12-Jun-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl.packethandler; import com.aelitis.net.udp.uc.PRUDPPacketHandler; import com.aelitis.net.udp.uc.PRUDPPacketHandlerStats; public class DHTUDPPacketHandlerStats { private long packets_sent; private long packets_received; private long bytes_sent; private long bytes_received; private long timeouts; private PRUDPPacketHandlerStats stats; protected DHTUDPPacketHandlerStats( PRUDPPacketHandler _handler ) { stats = _handler.getStats(); } protected DHTUDPPacketHandlerStats( DHTUDPPacketHandlerStats _originator, PRUDPPacketHandlerStats _stats ) { packets_sent = _originator.packets_sent; packets_received = _originator.packets_received; bytes_sent = _originator.bytes_sent; bytes_received = _originator.bytes_received; timeouts = _originator.timeouts; stats = _stats; } // update protected void timeout() { timeouts++; } protected void packetSent( long bytes ) { packets_sent++; bytes_sent += bytes; } protected void packetReceived( long bytes ) { packets_received++; bytes_received += bytes; } // access public long getPacketsSent() { return( packets_sent ); } public long getPacketsReceived() { return( packets_received ); } public long getRequestsTimedOut() { return( timeouts ); } public long getBytesSent() { return( bytes_sent ); } public long getBytesReceived() { return( bytes_received ); } public long getSendQueueLength() { return( stats.getSendQueueLength()); } public long getReceiveQueueLength() { return( stats.getReceiveQueueLength()); } public DHTUDPPacketHandlerStats snapshot() { return( new DHTUDPPacketHandlerStats( this, stats.snapshot())); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerException.javaazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerExc0000644000175000017500000000260711012741352032647 0ustar adrianadrian/* * Created on 12-Jun-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl.packethandler; public class DHTUDPPacketHandlerException extends Exception { public DHTUDPPacketHandlerException( String str ) { super( str ); } public DHTUDPPacketHandlerException( Throwable cause ) { super( cause.getMessage()==null?cause.toString():cause.getMessage()); } public DHTUDPPacketHandlerException( String str, Throwable cause ) { super( str, cause ); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketNetworkHandler.javaazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketNetworkHan0000644000175000017500000000441511156525426032724 0ustar adrianadrian/* * Created on 12-Jun-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl.packethandler; import java.io.IOException; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTTransportUDPImpl; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTUDPPacket; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTUDPPacketReply; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTUDPPacketRequest; import com.aelitis.net.udp.uc.PRUDPPacketRequest; import com.aelitis.net.udp.uc.PRUDPRequestHandler; public class DHTUDPPacketNetworkHandler implements PRUDPRequestHandler { private DHTUDPPacketHandlerFactory factory; private int port; protected DHTUDPPacketNetworkHandler( DHTUDPPacketHandlerFactory _factory, int _port ) { factory = _factory; port = _port; } public DHTTransportUDPImpl getTransport( DHTUDPPacket packet ) throws IOException { if ( packet instanceof DHTUDPPacketRequest ){ return( factory.getTransport( port, ((DHTUDPPacketRequest)packet).getNetwork())); }else{ return( factory.getTransport( port, ((DHTUDPPacketReply)packet).getNetwork())); } } public void process( PRUDPPacketRequest _request ) { if ( _request instanceof DHTUDPPacketRequest ){ DHTUDPPacketRequest request = (DHTUDPPacketRequest)_request; factory.process( port, request ); } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandler.javaazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandler.ja0000644000175000017500000001722611031020532032572 0ustar adrianadrian/* * Created on 12-Jun-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl.packethandler; import java.net.InetSocketAddress; import org.gudy.azureus2.core3.util.AddressUtils; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTUDPPacketReply; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTUDPPacketRequest; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.core.util.bloom.BloomFilterFactory; import com.aelitis.net.udp.uc.PRUDPPacket; import com.aelitis.net.udp.uc.PRUDPPacketHandler; import com.aelitis.net.udp.uc.PRUDPPacketHandlerException; import com.aelitis.net.udp.uc.PRUDPPacketHandlerRequest; import com.aelitis.net.udp.uc.PRUDPPacketReceiver; public class DHTUDPPacketHandler { private DHTUDPPacketHandlerFactory factory; private int network; private PRUDPPacketHandler packet_handler; private DHTUDPRequestHandler request_handler; private DHTUDPPacketHandlerStats stats; private boolean test_network_alive = true; private int BLOOM_FILTER_SIZE = 10000; private static final int BLOOM_ROTATION_PERIOD = 3*60*1000; private BloomFilter bloom1; private BloomFilter bloom2; private long last_bloom_rotation_time; protected DHTUDPPacketHandler( DHTUDPPacketHandlerFactory _factory, int _network, PRUDPPacketHandler _packet_handler, DHTUDPRequestHandler _request_handler ) { factory = _factory; network = _network; packet_handler = _packet_handler; request_handler = _request_handler; bloom1 = BloomFilterFactory.createAddOnly( BLOOM_FILTER_SIZE ); bloom2 = BloomFilterFactory.createAddOnly( BLOOM_FILTER_SIZE ); stats = new DHTUDPPacketHandlerStats( packet_handler ); } public void testNetworkAlive( boolean alive ) { test_network_alive = alive; } protected DHTUDPRequestHandler getRequestHandler() { return( request_handler ); } protected PRUDPPacketHandler getPacketHandler() { return( packet_handler ); } protected int getNetwork() { return( network ); } protected void updateBloom( InetSocketAddress destination_address ) { long diff = SystemTime.getCurrentTime() - last_bloom_rotation_time; if( diff < 0 || diff > BLOOM_ROTATION_PERIOD ) { // System.out.println( "bloom rotate: entries = " + bloom1.getEntryCount() + "/" + bloom2.getEntryCount()); bloom1 = bloom2; bloom2 = BloomFilterFactory.createAddOnly( BLOOM_FILTER_SIZE ); last_bloom_rotation_time = SystemTime.getCurrentTime(); } byte[] address_bytes = destination_address.getAddress().getAddress(); bloom1.add( address_bytes ); bloom2.add( address_bytes ); } public void sendAndReceive( DHTUDPPacketRequest request, InetSocketAddress destination_address, final DHTUDPPacketReceiver receiver, long timeout, int priority ) throws DHTUDPPacketHandlerException { // send and receive pair destination_address = AddressUtils.adjustDHTAddress( destination_address, true ); try{ request.setNetwork( network ); if ( test_network_alive ){ updateBloom( destination_address ); packet_handler.sendAndReceive( request, destination_address, new PRUDPPacketReceiver() { public void packetReceived( PRUDPPacketHandlerRequest request, PRUDPPacket packet, InetSocketAddress from_address ) { DHTUDPPacketReply reply = (DHTUDPPacketReply)packet; stats.packetReceived( reply.getSerialisedSize() ); if ( reply.getNetwork() == network ){ receiver.packetReceived(reply, from_address, request.getElapsedTime()); }else{ Debug.out( "Non-matching network reply received" ); receiver.error( new DHTUDPPacketHandlerException( new Exception( "Non-matching network reply received" ))); } } public void error( PRUDPPacketHandlerException e ) { receiver.error( new DHTUDPPacketHandlerException( e )); } }, timeout, priority ); }else{ receiver.error( new DHTUDPPacketHandlerException( new Exception( "Test network disabled" ))); } }catch( PRUDPPacketHandlerException e ){ throw( new DHTUDPPacketHandlerException(e )); }finally{ stats.packetSent( request.getSerialisedSize() ); } } public void send( DHTUDPPacketRequest request, InetSocketAddress destination_address ) throws DHTUDPPacketHandlerException { destination_address = AddressUtils.adjustDHTAddress( destination_address, true ); updateBloom( destination_address ); // one way send (no matching reply expected ) try{ request.setNetwork( network ); if ( test_network_alive ){ packet_handler.send( request, destination_address ); } }catch( PRUDPPacketHandlerException e ){ throw( new DHTUDPPacketHandlerException( e )); }finally{ stats.packetSent( request.getSerialisedSize() ); } } public void send( DHTUDPPacketReply reply, InetSocketAddress destination_address ) throws DHTUDPPacketHandlerException { destination_address = AddressUtils.adjustDHTAddress( destination_address, true ); // send reply to a request try{ reply.setNetwork( network ); // outgoing request if ( test_network_alive ){ packet_handler.send( reply, destination_address ); } }catch( PRUDPPacketHandlerException e ){ throw( new DHTUDPPacketHandlerException( e )); }finally{ stats.packetSent( reply.getSerialisedSize()); } } protected void receive( DHTUDPPacketRequest request ) { // incoming request if ( test_network_alive ){ request.setAddress( AddressUtils.adjustDHTAddress( request.getAddress(), false )); // an alien request is one that originates from a peer that we haven't recently // talked to byte[] bloom_key = request.getAddress().getAddress().getAddress(); boolean alien = !bloom1.contains( bloom_key ); if ( alien ){ // avoid counting consecutive requests from same contact more than once bloom1.add( bloom_key ); bloom2.add( bloom_key ); } stats.packetReceived( request.getSerialisedSize()); request_handler.process( request, alien ); } } public void setDelays( int send_delay, int receive_delay, int queued_request_timeout ) { // TODO: hmm packet_handler.setDelays( send_delay, receive_delay, queued_request_timeout ); } public void destroy() { factory.destroy( this ); } public DHTUDPPacketHandlerStats getStats() { return( stats ); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketReceiver.javaazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketReceiver.j0000644000175000017500000000252110373051004032616 0ustar adrianadrian/* * Created on 12-Jun-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl.packethandler; import java.net.InetSocketAddress; import com.aelitis.azureus.core.dht.transport.udp.impl.DHTUDPPacketReply; public interface DHTUDPPacketReceiver { public void packetReceived( DHTUDPPacketReply packet, InetSocketAddress from_address, long elapsed_time ); public void error( DHTUDPPacketHandlerException e ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPContactImpl.java0000644000175000017500000002142611265520560031755 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.io.DataOutputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.util.List; import java.util.Map; import org.gudy.azureus2.core3.util.AESemaphore; import com.aelitis.azureus.core.dht.impl.DHTLog; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionManager; import com.aelitis.azureus.core.dht.netcoords.vivaldi.ver1.VivaldiPositionProvider; import com.aelitis.azureus.core.dht.transport.*; import com.aelitis.azureus.core.dht.transport.udp.*; import com.aelitis.net.udp.uc.PRUDPPacketHandler; /** * @author parg * */ public class DHTTransportUDPContactImpl implements DHTTransportUDPContact { public static final int NODE_STATUS_UNKNOWN = 0xffffffff; public static final int NODE_STATUS_ROUTABLE = 0x00000001; static{ DHTNetworkPositionManager.registerProvider( new VivaldiPositionProvider()); } private DHTTransportUDPImpl transport; private InetSocketAddress external_address; private InetSocketAddress transport_address; private byte[] id; private byte protocol_version; private int instance_id; private long skew; private int random_id; private int node_status = NODE_STATUS_UNKNOWN; private DHTNetworkPosition[] network_positions; protected DHTTransportUDPContactImpl( boolean _is_local, DHTTransportUDPImpl _transport, InetSocketAddress _transport_address, InetSocketAddress _external_address, byte _protocol_version, int _instance_id, long _skew ) throws DHTTransportException { transport = _transport; transport_address = _transport_address; external_address = _external_address; protocol_version = _protocol_version; if ( transport_address.equals( external_address )){ external_address = transport_address; } instance_id = _instance_id; skew = _skew; if ( transport_address == external_address || transport_address.getAddress().equals( external_address.getAddress())){ id = DHTUDPUtils.getNodeID( external_address, protocol_version ); } network_positions = DHTNetworkPositionManager.createPositions( id==null?DHTUDPUtils.getBogusNodeID():id, _is_local ); } public DHTTransport getTransport() { return( transport ); } public byte getProtocolVersion() { return( protocol_version ); } protected void setProtocolVersion( byte v ) { protocol_version = v; } public long getClockSkew() { return( skew ); } public void setRandomID( int _random_id ) { random_id = _random_id; } public int getRandomID() { return( random_id ); } protected int getNodeStatus() { return( node_status ); } protected void setNodeStatus( int ns ) { node_status = ns; } public boolean isValid() { return( addressMatchesID() && !transport.invalidExternalAddress( external_address.getAddress())); } protected boolean addressMatchesID() { return( id != null ); } public InetSocketAddress getTransportAddress() { return( transport_address ); } public void setTransportAddress( InetSocketAddress address ) { transport_address = address; } public InetSocketAddress getExternalAddress() { return( external_address ); } public String getName() { return( DHTLog.getString2( id )); } public InetSocketAddress getAddress() { return( getExternalAddress()); } public int getMaxFailForLiveCount() { return( transport.getMaxFailForLiveCount() ); } public int getMaxFailForUnknownCount() { return( transport.getMaxFailForUnknownCount() ); } public int getInstanceID() { return( instance_id ); } protected void setInstanceIDAndVersion( int _instance_id, byte _protocol_version ) { instance_id = _instance_id; // target supports a higher version than we thought, update if ( _protocol_version > protocol_version ){ protocol_version = _protocol_version; } } public boolean isAlive( long timeout ) { final AESemaphore sem = new AESemaphore( "DHTTransportContact:alive"); final boolean[] alive = { false }; try{ sendPing( new DHTTransportReplyHandlerAdapter() { public void pingReply( DHTTransportContact contact ) { alive[0] = true; sem.release(); } public void failed( DHTTransportContact contact, Throwable cause ) { sem.release(); } }); sem.reserve( timeout ); return( alive[0] ); }catch( Throwable e ){ return( false ); } } public void isAlive( DHTTransportReplyHandler handler, long timeout ) { transport.sendPing( this, handler, timeout, PRUDPPacketHandler.PRIORITY_IMMEDIATE ); } public void sendPing( DHTTransportReplyHandler handler ) { transport.sendPing( this, handler ); } public void sendImmediatePing( DHTTransportReplyHandler handler, long timeout ) { transport.sendImmediatePing( this, handler, timeout ); } public void sendStats( DHTTransportReplyHandler handler ) { transport.sendStats( this, handler ); } public void sendStore( DHTTransportReplyHandler handler, byte[][] keys, DHTTransportValue[][] value_sets, boolean immediate ) { transport.sendStore( this, handler, keys, value_sets, immediate?PRUDPPacketHandler.PRIORITY_IMMEDIATE:PRUDPPacketHandler.PRIORITY_LOW ); } public void sendQueryStore( DHTTransportReplyHandler handler, int header_length, List key_details ) { transport.sendQueryStore( this, handler, header_length, key_details); } public void sendFindNode( DHTTransportReplyHandler handler, byte[] nid ) { transport.sendFindNode( this, handler, nid ); } public void sendFindValue( DHTTransportReplyHandler handler, byte[] key, int max_values, byte flags ) { transport.sendFindValue( this, handler, key, max_values, flags ); } public void sendKeyBlock( final DHTTransportReplyHandler handler, final byte[] request, final byte[] signature ) { // gotta do anti-spoof sendFindNode( new DHTTransportReplyHandlerAdapter() { public void findNodeReply( DHTTransportContact contact, DHTTransportContact[] contacts ) { transport.sendKeyBlockRequest( DHTTransportUDPContactImpl.this, handler, request, signature ); } public void failed( DHTTransportContact _contact, Throwable _error ) { handler.failed( _contact, _error ); } }, new byte[0] ); } public DHTTransportFullStats getStats() { return( transport.getFullStats( this )); } public byte[] getID() { if ( id == null ){ throw( new RuntimeException( "Invalid contact" )); } return( id ); } public void exportContact( DataOutputStream os ) throws IOException, DHTTransportException { transport.exportContact( this, os ); } public void remove() { transport.removeContact( this ); } protected void setNetworkPositions( DHTNetworkPosition[] positions ) { network_positions = positions; } public DHTNetworkPosition[] getNetworkPositions() { return( network_positions ); } public DHTNetworkPosition getNetworkPosition( byte position_type ) { for (int i=0;i _transport.getProtocolVersion() ){ protocol_version = _transport.getProtocolVersion(); } originator_address = _local_contact.getExternalAddress(); originator_instance_id = _local_contact.getInstanceID(); originator_time = SystemTime.getCurrentTime(); } protected DHTUDPPacketRequest( DHTUDPPacketNetworkHandler network_handler, DataInputStream is, int type, long con_id, int trans_id ) throws IOException { super( type, con_id, trans_id ); // deserialisation constructor protocol_version = is.readByte(); if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_VENDOR_ID ){ vendor_id = is.readByte(); } if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_NETWORKS ){ network = is.readInt(); } if ( protocol_version < ( network == DHT.NW_CVS?DHTTransportUDP.PROTOCOL_VERSION_MIN_CVS:DHTTransportUDP.PROTOCOL_VERSION_MIN )){ throw( new IOException( "Invalid DHT protocol version, please update Azureus" )); } // we can only get the correct transport after decoding the network... transport = network_handler.getTransport( this ); if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_FIX_ORIGINATOR ){ originator_version = is.readByte(); }else{ // this should be set correctly in the post-deserialise code, however default // it for now originator_version = protocol_version; } originator_address = DHTUDPUtils.deserialiseAddress( is ); originator_instance_id = is.readInt(); originator_time = is.readLong(); // We maintain a rough view of the clock diff between them and us, // times are then normalised appropriately. // If the skew is positive then this means our clock is ahead of their // clock. Thus any times they send us will need to have the skew added in // so that they're correct relative to us. // For example: X has clock = 01:00, they create a value that expires at // X+8 hours 09:00. They send X to us. Our clock is an hour ahead (skew=+1hr) // We receive it at 02:00 (our time) and therefore time it out an hour early. // We therefore need to adjust the creation time to be 02:00. // Likewise, when we return a time to a caller we need to adjust by - skew to // put the time into their frame of reference. skew = SystemTime.getCurrentTime() - originator_time; transport.recordSkew( originator_address, skew ); } protected void postDeserialise( DataInputStream is ) throws IOException { if ( protocol_version < DHTTransportUDP.PROTOCOL_VERSION_FIX_ORIGINATOR ){ if ( is.available() > 0 ){ originator_version = is.readByte(); }else{ originator_version = protocol_version; } // if the originator is a higher version than us then we can't do anything sensible // working at their version (e.g. we can't reply to them using that version). // Therefore trim their perceived version back to something we can deal with if ( originator_version > getTransport().getProtocolVersion() ){ originator_version = getTransport().getProtocolVersion(); } } } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); // add to this and you need to amend HEADER_SIZE above os.writeByte( protocol_version ); if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_VENDOR_ID ){ os.writeByte( DHTTransportUDP.VENDOR_ID_ME ); } if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_NETWORKS ){ os.writeInt( network ); } if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_FIX_ORIGINATOR ){ // originator version os.writeByte( getTransport().getProtocolVersion()); } try{ DHTUDPUtils.serialiseAddress( os, originator_address ); }catch( DHTTransportException e ){ throw( new IOException( e.getMessage())); } os.writeInt( originator_instance_id ); os.writeLong( originator_time ); } protected void postSerialise( DataOutputStream os ) throws IOException { if ( protocol_version < DHTTransportUDP.PROTOCOL_VERSION_FIX_ORIGINATOR ){ // originator version is at tail so it works with older versions os.writeByte( getTransport().getProtocolVersion()); } } public DHTTransportUDPImpl getTransport() { return( transport ); } protected long getClockSkew() { return( skew ); } public byte getProtocolVersion() { return( protocol_version ); } protected byte getVendorID() { return( vendor_id ); } public int getNetwork() { return( network ); } public void setNetwork( int _network ) { network = _network; } protected byte getOriginatorVersion() { return( originator_version ); } protected InetSocketAddress getOriginatorAddress() { return( originator_address ); } protected void setOriginatorAddress( InetSocketAddress address ) { originator_address = address; } protected int getOriginatorInstanceID() { return( originator_instance_id ); } public String getString() { return( super.getString() + ",[prot=" + protocol_version + ",ven=" + vendor_id + ",net="+network+",ov=" + originator_version + "]"); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyPing.java0000644000175000017500000000425511033103414030651 0ustar adrianadrian/* * File : PRUDPPacketReplyConnect.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.dht.transport.udp.impl; /** * @author parg * */ import java.io.*; import java.net.InetSocketAddress; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; public class DHTUDPPacketReplyPing extends DHTUDPPacketReply { public DHTUDPPacketReplyPing( DHTTransportUDPImpl transport, int trans_id, long conn_id, DHTTransportContact local_contact, DHTTransportContact remote_contact ) { super( transport, DHTUDPPacketHelper.ACT_REPLY_PING, trans_id, conn_id, local_contact, remote_contact ); } protected DHTUDPPacketReplyPing( DHTUDPPacketNetworkHandler network_handler, InetSocketAddress originator, DataInputStream is, int trans_id ) throws IOException { super( network_handler, originator, is, DHTUDPPacketHelper.ACT_REPLY_PING, trans_id ); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_VIVALDI ){ DHTUDPUtils.deserialiseVivaldi( this, is ); } } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_VIVALDI ){ DHTUDPUtils.serialiseVivaldi( this, os ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPStatsImpl.java0000644000175000017500000000537711104431514031457 0ustar adrianadrian/* * Created on 25-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import com.aelitis.azureus.core.dht.transport.DHTTransportStats; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketHandlerStats; import com.aelitis.azureus.core.dht.transport.util.DHTTransportStatsImpl; /** * @author parg * */ public class DHTTransportUDPStatsImpl extends DHTTransportStatsImpl { private DHTTransportUDPImpl transport; private DHTUDPPacketHandlerStats stats; protected DHTTransportUDPStatsImpl( DHTTransportUDPImpl _transport, byte _pv, DHTUDPPacketHandlerStats _stats ) { super( _pv ); transport = _transport; stats = _stats; } protected void setStats( DHTUDPPacketHandlerStats _stats ) { stats = _stats; } public long getPacketsSent() { return( stats.getPacketsSent()); } public long getPacketsReceived() { return( stats.getPacketsReceived()); } public long getRequestsTimedOut() { return( stats.getRequestsTimedOut()); } public long getBytesSent() { return( stats.getBytesSent()); } public long getBytesReceived() { return( stats.getBytesReceived()); } public int getRouteablePercentage() { return( transport.getRouteablePercentage()); } public DHTTransportStats snapshot() { DHTTransportStatsImpl res = new DHTTransportUDPStatsImpl( transport, getProtocolVersion(), stats.snapshot()); snapshotSupport( res ); return( res ); } public String getString() { return( super.getString() + "," + "packsent:" + getPacketsSent() + "," + "packrecv:" + getPacketsReceived() + "," + "bytesent:" + getBytesSent() + "," + "byterecv:" + getBytesReceived() + "," + "timeout:" + getRequestsTimedOut() + "," + "sendq:" + stats.getSendQueueLength() + "," + "recvq:" + stats.getReceiveQueueLength()); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStore.java0000644000175000017500000000744011256071412031415 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import com.aelitis.azureus.core.dht.transport.DHTTransportException; import com.aelitis.azureus.core.dht.transport.DHTTransportValue; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; /** * @author parg * */ public class DHTUDPPacketRequestStore extends DHTUDPPacketRequest { public static final int MAX_KEYS_PER_PACKET = 255; // 1 byte DHTUDPPacket.PACKET_MAX_BYTES / 20; public static final int MAX_VALUES_PER_KEY = 255; // 1 byte DHTUDPPacket.PACKET_MAX_BYTES / DHTUDPUtils.DHTTRANSPORTVALUE_SIZE_WITHOUT_VALUE; private int random_id; private byte[][] keys; private DHTTransportValue[][] value_sets; public DHTUDPPacketRequestStore( DHTTransportUDPImpl _transport, long _connection_id, DHTTransportUDPContactImpl _local_contact, DHTTransportUDPContactImpl _remote_contact ) { super( _transport, DHTUDPPacketHelper.ACT_REQUEST_STORE, _connection_id, _local_contact, _remote_contact ); } protected DHTUDPPacketRequestStore( DHTUDPPacketNetworkHandler network_handler, DataInputStream is, long con_id, int trans_id ) throws IOException { super( network_handler, is, DHTUDPPacketHelper.ACT_REQUEST_STORE, con_id, trans_id ); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF ){ random_id = is.readInt(); } keys = DHTUDPUtils.deserialiseByteArrayArray( is, MAX_KEYS_PER_PACKET ); // times receieved are adjusted by + skew value_sets = DHTUDPUtils.deserialiseTransportValuesArray( this, is, getClockSkew(), MAX_KEYS_PER_PACKET ); super.postDeserialise(is); } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF ){ os.writeInt( random_id ); } DHTUDPUtils.serialiseByteArrayArray( os, keys, MAX_KEYS_PER_PACKET ); try{ DHTUDPUtils.serialiseTransportValuesArray( this, os, value_sets, 0, MAX_KEYS_PER_PACKET ); }catch( DHTTransportException e ){ throw( new IOException( e.getMessage())); } super.postSerialise( os ); } protected void setRandomID( int _random_id ) { random_id = _random_id; } protected int getRandomID() { return( random_id ); } protected void setValueSets( DHTTransportValue[][] _values ) { value_sets = _values; } protected DHTTransportValue[][] getValueSets() { return( value_sets ); } protected void setKeys( byte[][] _key ) { keys = _key; } protected byte[][] getKeys() { return( keys ); } public String getString() { return( super.getString()); } }azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketData.java0000644000175000017500000001142111262037736027623 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import com.aelitis.azureus.core.dht.impl.DHTLog; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; /** * @author parg * */ public class DHTUDPPacketData extends DHTUDPPacketRequest { protected static final byte PT_READ_REQUEST = 0x00; protected static final byte PT_READ_REPLY = 0x01; protected static final byte PT_WRITE_REQUEST = 0x02; protected static final byte PT_WRITE_REPLY = 0x03; private byte packet_type; private byte[] transfer_key; private byte[] key; private byte[] data; private int start_position; private int length; private int total_length; // assume keys are 20 bytes + 1 len, data len is 2 bytes public static int MAX_DATA_SIZE = DHTUDPPacketHelper.PACKET_MAX_BYTES - DHTUDPPacketReply.DHT_HEADER_SIZE - 1- 21 - 21 - 14; public DHTUDPPacketData( DHTTransportUDPImpl _transport, long _connection_id, DHTTransportUDPContactImpl _local_contact, DHTTransportUDPContactImpl _remote_contact ) { super( _transport, DHTUDPPacketHelper.ACT_DATA, _connection_id, _local_contact, _remote_contact ); } protected DHTUDPPacketData( DHTUDPPacketNetworkHandler network_handler, DataInputStream is, long con_id, int trans_id ) throws IOException { super( network_handler, is, DHTUDPPacketHelper.ACT_DATA, con_id, trans_id ); packet_type = is.readByte(); transfer_key = DHTUDPUtils.deserialiseByteArray( is, 64 ); int max_key_size; if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ){ max_key_size = 255; }else{ max_key_size = 64; } key = DHTUDPUtils.deserialiseByteArray( is, max_key_size ); start_position = is.readInt(); length = is.readInt(); total_length = is.readInt(); data = DHTUDPUtils.deserialiseByteArray( is, 65535 ); super.postDeserialise(is); } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); os.writeByte( packet_type ); DHTUDPUtils.serialiseByteArray( os, transfer_key, 64 ); int max_key_size; if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ){ max_key_size = 255; }else{ max_key_size = 64; } DHTUDPUtils.serialiseByteArray( os, key, max_key_size ); os.writeInt( start_position ); os.writeInt( length ); os.writeInt( total_length ); if ( data.length > 0 ){ DHTUDPUtils.serialiseByteArray( os, data, start_position, length, 65535 ); }else{ DHTUDPUtils.serialiseByteArray( os, data, 65535 ); } super.postSerialise( os ); } public void setDetails( byte _packet_type, byte[] _transfer_key, byte[] _key, byte[] _data, int _start_pos, int _length, int _total_length ) { packet_type = _packet_type; transfer_key = _transfer_key; key = _key; data = _data; start_position = _start_pos; length = _length; total_length = _total_length; } public byte getPacketType() { return( packet_type ); } public byte[] getTransferKey() { return( transfer_key ); } public byte[] getRequestKey() { return( key ); } public byte[] getData() { return( data ); } public int getStartPosition() { return( start_position ); } public int getLength() { return( length ); } public int getTotalLength() { return( total_length ); } public String getString() { return( super.getString() + "tk=" + DHTLog.getString2( transfer_key ) + ",rk=" + DHTLog.getString2( key ) + ",data=" + data.length + ",st=" + start_position + ",len=" + length + ",tot=" + total_length ); } }azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyQueryStorage.java0000644000175000017500000000722411260535126032420 0ustar adrianadrian/* * File : PRUDPPacketReplyConnect.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.dht.transport.udp.impl; /** * @author parg * */ import java.util.*; import java.io.*; import java.net.InetSocketAddress; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; public class DHTUDPPacketReplyQueryStorage extends DHTUDPPacketReply { private int random_id; private int header_length; private List response; public DHTUDPPacketReplyQueryStorage( DHTTransportUDPImpl transport, int trans_id, long conn_id, DHTTransportContact local_contact, DHTTransportContact remote_contact ) { super( transport, DHTUDPPacketHelper.ACT_REPLY_QUERY_STORE, trans_id, conn_id, local_contact, remote_contact ); } protected DHTUDPPacketReplyQueryStorage( DHTUDPPacketNetworkHandler network_handler, InetSocketAddress originator, DataInputStream is, int trans_id ) throws IOException { super( network_handler, originator, is, DHTUDPPacketHelper.ACT_REPLY_QUERY_STORE, trans_id ); short size = is.readShort(); response = new ArrayList( size ); if ( size > 0 ){ header_length = is.readByte()&0xff; byte[] bitmap = new byte[size+7/8]; is.read( bitmap ); int pos = 0; int current = 0; for (int i=0;i 0 ){ os.writeByte( header_length ); byte[] bitmap = new byte[size+7/8]; int bitmap_pos = 0; int current_byte = 0; int pos = 0; for ( byte[] x: response ){ current_byte = current_byte << 1; if ( x != null){ current_byte += 1; } if (( pos %8 ) == 7 ){ bitmap[bitmap_pos++] = (byte)current_byte; current_byte = 0; } pos++; } if (( pos % 8 ) != 0 ){ bitmap[bitmap_pos++] = (byte)(current_byte << (8 - (pos % 8))); } os.write( bitmap ); for ( byte[] x: response ){ if ( x != null ){ os.write( x ); } } } } protected void setRandomID( int id ) { random_id = id; } protected int getRandomID() { return( random_id ); } protected void setResponse( int _header_length, List _response ) { header_length = _header_length; response = _response; } protected List getResponse() { return( response ); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPUtils.java0000644000175000017500000006066511267313012026725 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.io.*; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Random; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SHA1Simple; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.impl.DHTLog; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionManager; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportException; import com.aelitis.azureus.core.dht.transport.DHTTransportFullStats; import com.aelitis.azureus.core.dht.transport.DHTTransportValue; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; /** * @author parg * */ public class DHTUDPUtils { protected static final int CT_UDP = 1; private static Map node_id_history = new LinkedHashMap(128,0.75f,true) { protected boolean removeEldestEntry( Map.Entry eldest) { return size() > 128; } }; private static SHA1Simple hasher = new SHA1Simple(); protected static byte[] getNodeID( InetSocketAddress address, byte protocol_version ) throws DHTTransportException { InetAddress ia = address.getAddress(); if ( ia == null ){ // Debug.out( "Address '" + address + "' is unresolved" ); throw( new DHTTransportException( "Address '" + address + "' is unresolved" )); }else{ String key; if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_RESTRICT_ID_PORTS2 ){ // more draconian limit, analysis shows that of 500,000 node addresses only // 0.01% had >= 8 ports active. ( 1% had 2 ports, 0.1% 3) // Having > 1 node with the same ID doesn't actually cause too much grief key = ia.getHostAddress() + ":" + ( address.getPort() % 8 ); }else if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_RESTRICT_ID_PORTS ){ // limit range to around 2000 (1999 is prime) key = ia.getHostAddress() + ":" + ( address.getPort() % 1999 ); }else{ key = ia.getHostAddress() + ":" + address.getPort(); } synchronized( node_id_history ){ byte[] res = node_id_history.get( key ); if ( res == null ){ res = hasher.calculateHash( key.getBytes()); node_id_history.put( key, res ); } // System.out.println( "NodeID: " + address + " -> " + DHTLog.getString( res )); return( res ); } } } protected static byte[] getBogusNodeID() { byte[] id = new byte[20]; new Random().nextBytes( id ); return( id ); } protected static void serialiseLength( DataOutputStream os, int len, int max_length ) throws IOException { if ( len > max_length ){ throw( new IOException( "Invalid DHT data length: max=" + max_length + ",actual=" + len )); } if ( max_length < 256 ){ os.writeByte( len ); }else if ( max_length < 65536 ){ os.writeShort( len ); }else{ os.writeInt( len ); } } protected static int deserialiseLength( DataInputStream is, int max_length ) throws IOException { int len; if ( max_length < 256 ){ len = is.readByte()&0xff; }else if ( max_length < 65536 ){ len = is.readShort()&0xffff; }else{ len = is.readInt(); } if ( len > max_length ){ throw( new IOException( "Invalid DHT data length: max=" + max_length + ",actual=" + len )); } return( len ); } protected static byte[] deserialiseByteArray( DataInputStream is, int max_length ) throws IOException { int len = deserialiseLength( is, max_length ); byte[] data = new byte[len]; is.read(data); return( data ); } protected static void serialiseByteArray( DataOutputStream os, byte[] data, int max_length ) throws IOException { serialiseByteArray( os, data, 0, data.length, max_length ); } protected static void serialiseByteArray( DataOutputStream os, byte[] data, int start, int length, int max_length ) throws IOException { serialiseLength( os, length, max_length ); os.write( data, start, length ); } protected static void serialiseByteArrayArray( DataOutputStream os, byte[][] data, int max_length ) throws IOException { serialiseLength(os,data.length,max_length); for (int i=0;i= DHTTransportUDP.PROTOCOL_VERSION_REMOVE_DIST_ADD_VER ){ version = is.readInt(); //System.out.println( "read: version = " + version ); }else{ version = -1; // int distance = is.readInt(); //System.out.println( "read:" + distance ); } final long created = is.readLong() + skew; // System.out.println( " Adjusted creation time by " + skew ); final byte[] value_bytes = deserialiseByteArray( is, DHT.MAX_VALUE_SIZE ); final DHTTransportContact originator = deserialiseContact( packet.getTransport(), is ); final int flags = is.readByte()&0xff; final int life_hours; if ( packet.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_LONGER_LIFE ){ life_hours = is.readByte()&0xff; }else{ life_hours = 0; } final byte rep_control; if ( packet.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ){ rep_control = is.readByte(); }else{ rep_control = DHT.REP_FACT_DEFAULT; } DHTTransportValue value = new DHTTransportValue() { public boolean isLocal() { return( false ); } public long getCreationTime() { return( created ); } public byte[] getValue() { return( value_bytes ); } public int getVersion() { return( version ); } public DHTTransportContact getOriginator() { return( originator ); } public int getFlags() { return( flags ); } public int getLifeTimeHours() { return( life_hours ); } public byte getReplicationControl() { return( rep_control ); } public byte getReplicationFactor() { return( rep_control == DHT.REP_FACT_DEFAULT?DHT.REP_FACT_DEFAULT:(byte)(rep_control&0x0f)); } public byte getReplicationFrequencyHours() { return( rep_control == DHT.REP_FACT_DEFAULT?DHT.REP_FACT_DEFAULT:(byte)(rep_control>>4)); } public String getString() { long now = SystemTime.getCurrentTime(); return( DHTLog.getString( value_bytes ) + " - " + new String(value_bytes) + "{v=" + version + ",f=" + Integer.toHexString(flags) + ",l=" + life_hours + ",r=" + Integer.toHexString(getReplicationControl()) + ",ca=" + (now - created ) + ",or=" + originator.getString() +"}" ); } }; return( value ); } public static final int DHTTRANSPORTVALUE_SIZE_WITHOUT_VALUE = 17 + DHTTRANSPORTCONTACT_SIZE; protected static void serialiseTransportValue( DHTUDPPacket packet, DataOutputStream os, DHTTransportValue value, long skew ) throws IOException, DHTTransportException { if ( packet.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REMOVE_DIST_ADD_VER ){ int version = value.getVersion(); //System.out.println( "write: version = " + version ); os.writeInt( version ); }else{ //System.out.println( "write: 0" ); os.writeInt( 0 ); } // Don't forget to change the CONSTANT above if you change the size of this! os.writeLong( value.getCreationTime() + skew ); // 12 serialiseByteArray( os, value.getValue(), DHT.MAX_VALUE_SIZE ); // 12+2+X serialiseContact( os, value.getOriginator()); // 12 + 2+X + contact os.writeByte( value.getFlags()); // 13 + 2+ X + contact if ( packet.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_LONGER_LIFE ){ os.writeByte( value.getLifeTimeHours()); // 14 + 2+ X + contact } if ( packet.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ){ os.writeByte( value.getReplicationControl()); // 15 + 2+ X + contact } } protected static void serialiseContacts( DataOutputStream os, DHTTransportContact[] contacts ) throws IOException { serialiseLength( os, contacts.length, 65535 ); for (int i=0;i= DHTTransportUDP.PROTOCOL_VERSION_GENERIC_NETPOS ){ os.writeByte((byte)nps.length); boolean v1_found = false; for (int i=0;i= DHTTransportUDP.PROTOCOL_VERSION_GENERIC_NETPOS ){ int entries = is.readByte()&0xff; nps = new DHTNetworkPosition[ entries ]; int skipped = 0; for (int i=0;i 0 ){ DHTNetworkPosition[] x = new DHTNetworkPosition[ entries - skipped ]; int pos = 0; for (int i=0;i= DHTTransportUDP.PROTOCOL_VERSION_BLOCK_KEYS ){ os.writeLong( stats.getDBKeysBlocked()); os.writeLong( stats.getTotalKeyBlocksReceived()); } if ( version >= DHTTransportUDP.PROTOCOL_VERSION_MORE_STATS ){ os.writeLong( stats.getDBKeyCount()); os.writeLong( stats.getDBValueCount()); os.writeLong( stats.getDBStoreSize()); os.writeLong( stats.getDBKeyDivFreqCount()); os.writeLong( stats.getDBKeyDivSizeCount()); } } protected static DHTTransportFullStats deserialiseStats( int version, DataInputStream is ) throws IOException { final long db_values_stored = is.readLong(); final long router_nodes = is.readLong(); final long router_leaves = is.readLong(); final long router_contacts = is.readLong(); final long total_bytes_received = is.readLong(); final long total_bytes_sent = is.readLong(); final long total_packets_received = is.readLong(); final long total_packets_sent = is.readLong(); final long total_pings_received = is.readLong(); final long total_find_nodes_received = is.readLong(); final long total_find_values_received = is.readLong(); final long total_stores_received = is.readLong(); final long average_bytes_received = is.readLong(); final long average_bytes_sent = is.readLong(); final long average_packets_received = is.readLong(); final long average_packets_sent = is.readLong(); final long incoming_requests = is.readLong(); final String az_version = new String( deserialiseByteArray( is, 64 )); final long router_uptime = is.readLong(); final int router_count = is.readInt(); final long db_keys_blocked; final long total_key_blocks_received; if ( version >= DHTTransportUDP.PROTOCOL_VERSION_BLOCK_KEYS ){ db_keys_blocked = is.readLong(); total_key_blocks_received = is.readLong(); }else{ db_keys_blocked = -1; total_key_blocks_received = -1; } final long db_key_count; final long db_value_count; final long db_store_size; final long db_freq_divs; final long db_size_divs; if ( version >= DHTTransportUDP.PROTOCOL_VERSION_MORE_STATS ){ db_key_count = is.readLong(); db_value_count = is.readLong(); db_store_size = is.readLong(); db_freq_divs = is.readLong(); db_size_divs = is.readLong(); }else{ db_key_count = -1; db_value_count = -1; db_store_size = -1; db_freq_divs = -1; db_size_divs = -1; } DHTTransportFullStats res = new DHTTransportFullStats() { public long getDBValuesStored() { return( db_values_stored ); } public long getDBKeysBlocked() { return( db_keys_blocked ); } public long getDBValueCount() { return( db_value_count ); } public long getDBKeyCount() { return( db_key_count ); } public long getDBKeyDivSizeCount() { return( db_size_divs ); } public long getDBKeyDivFreqCount() { return( db_freq_divs ); } public long getDBStoreSize() { return( db_store_size ); } // Router public long getRouterNodes() { return( router_nodes ); } public long getRouterLeaves() { return( router_leaves ); } public long getRouterContacts() { return( router_contacts ); } public long getRouterUptime() { return( router_uptime ); } public int getRouterCount() { return( router_count ); } public long getTotalBytesReceived() { return( total_bytes_received ); } public long getTotalBytesSent() { return( total_bytes_sent ); } public long getTotalPacketsReceived() { return( total_packets_received ); } public long getTotalPacketsSent() { return( total_packets_sent ); } public long getTotalPingsReceived() { return( total_pings_received ); } public long getTotalFindNodesReceived() { return( total_find_nodes_received ); } public long getTotalFindValuesReceived() { return( total_find_values_received ); } public long getTotalStoresReceived() { return( total_stores_received ); } public long getTotalKeyBlocksReceived() { return( total_key_blocks_received ); } // averages public long getAverageBytesReceived() { return( average_bytes_received ); } public long getAverageBytesSent() { return( average_bytes_sent ); } public long getAveragePacketsReceived() { return( average_packets_received ); } public long getAveragePacketsSent() { return( average_packets_sent ); } public long getIncomingRequests() { return( incoming_requests ); } public String getVersion() { return( az_version ); } public String getString() { return( "transport:" + getTotalBytesReceived() + "," + getTotalBytesSent() + "," + getTotalPacketsReceived() + "," + getTotalPacketsSent() + "," + getTotalPingsReceived() + "," + getTotalFindNodesReceived() + "," + getTotalFindValuesReceived() + "," + getTotalStoresReceived() + "," + getTotalKeyBlocksReceived() + "," + getAverageBytesReceived() + "," + getAverageBytesSent() + "," + getAveragePacketsReceived() + "," + getAveragePacketsSent() + "," + getIncomingRequests() + ",router:" + getRouterNodes() + "," + getRouterLeaves() + "," + getRouterContacts() + ",database:" + getDBKeyCount() + ","+ getDBValueCount() + ","+ getDBValuesStored() + ","+ getDBStoreSize() + ","+ getDBKeyDivFreqCount() + ","+ getDBKeyDivSizeCount() + ","+ getDBKeysBlocked()+ ",version:" + getVersion()+","+ getRouterUptime() + ","+ getRouterCount()); } }; return( res ); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyStats.java0000644000175000017500000000703011033103414031044 0ustar adrianadrian/* * File : PRUDPPacketReplyConnect.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.dht.transport.udp.impl; /** * @author parg * */ import java.io.*; import java.net.InetSocketAddress; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportFullStats; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; public class DHTUDPPacketReplyStats extends DHTUDPPacketReply { private int stats_type = DHTUDPPacketRequestStats.STATS_TYPE_ORIGINAL; private DHTTransportFullStats original_stats; private byte[] new_stats; public DHTUDPPacketReplyStats( DHTTransportUDPImpl transport, int trans_id, long conn_id, DHTTransportContact local_contact, DHTTransportContact remote_contact ) { super( transport, DHTUDPPacketHelper.ACT_REPLY_STATS, trans_id, conn_id, local_contact, remote_contact ); } protected DHTUDPPacketReplyStats( DHTUDPPacketNetworkHandler network_handler, InetSocketAddress originator, DataInputStream is, int trans_id ) throws IOException { super( network_handler, originator, is, DHTUDPPacketHelper.ACT_REPLY_STATS, trans_id ); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_GENERIC_NETPOS ){ stats_type = is.readInt(); if ( stats_type == DHTUDPPacketRequestStats.STATS_TYPE_ORIGINAL ){ original_stats = DHTUDPUtils.deserialiseStats( getProtocolVersion(), is ); }else{ new_stats = DHTUDPUtils.deserialiseByteArray( is, 65535 ); } }else{ original_stats = DHTUDPUtils.deserialiseStats( getProtocolVersion(), is ); } } public int getStatsType() { return( stats_type ); } public DHTTransportFullStats getOriginalStats() { return( original_stats ); } public void setOriginalStats( DHTTransportFullStats _stats ) { stats_type = DHTUDPPacketRequestStats.STATS_TYPE_ORIGINAL; original_stats = _stats; } public byte[] getNewStats() { return( new_stats ); } public void setNewStats( byte[] _stats, int _stats_type ) { stats_type = _stats_type; new_stats = _stats; } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_GENERIC_NETPOS ){ os.writeInt( stats_type ); if ( stats_type == DHTUDPPacketRequestStats.STATS_TYPE_ORIGINAL ){ DHTUDPUtils.serialiseStats( getProtocolVersion(), os, original_stats ); }else{ DHTUDPUtils.serialiseByteArray( os, new_stats, 65535 ); } }else{ DHTUDPUtils.serialiseStats( getProtocolVersion(), os, original_stats ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReply.java0000644000175000017500000001220511056735676030057 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.InetSocketAddress; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; import com.aelitis.azureus.core.dht.netcoords.*; import com.aelitis.net.udp.uc.PRUDPPacketReply; /** * @author parg * */ public class DHTUDPPacketReply extends PRUDPPacketReply implements DHTUDPPacket { public static final int DHT_HEADER_SIZE = PRUDPPacketReply.PR_HEADER_SIZE + 8 + // con id 1 + // ver 1 + // net 4; // instance private DHTTransportUDPImpl transport; private long connection_id; private byte protocol_version; private byte vendor_id = DHTTransportUDP.VENDOR_ID_NONE; private int network; private int target_instance_id; private long skew; private DHTNetworkPosition[] network_positions; public DHTUDPPacketReply( DHTTransportUDPImpl _transport, int _type, int _trans_id, long _conn_id, DHTTransportContact _local_contact, DHTTransportContact _remote_contact ) { super( _type, _trans_id ); transport = _transport; connection_id = _conn_id; protocol_version = _remote_contact.getProtocolVersion(); // the target might be at a higher protocol version that us, so trim back if necessary // as we obviously can't talk a higher version than what we are! if ( protocol_version > _transport.getProtocolVersion()){ protocol_version = _transport.getProtocolVersion(); } target_instance_id = _local_contact.getInstanceID(); skew = _remote_contact.getClockSkew(); } protected DHTUDPPacketReply( DHTUDPPacketNetworkHandler network_handler, InetSocketAddress originator, DataInputStream is, int type, int trans_id ) throws IOException { super( type, trans_id ); setAddress( originator ); connection_id = is.readLong(); protocol_version = is.readByte(); if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_VENDOR_ID ){ vendor_id = is.readByte(); } if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_NETWORKS ){ network = is.readInt(); } if ( protocol_version < ( network == DHT.NW_CVS?DHTTransportUDP.PROTOCOL_VERSION_MIN_CVS:DHTTransportUDP.PROTOCOL_VERSION_MIN )){ throw( new IOException( "Invalid DHT protocol version, please update Azureus" )); } // we can only get the correct transport after decoding the network... transport = network_handler.getTransport( this ); target_instance_id = is.readInt(); } public DHTTransportUDPImpl getTransport() { return( transport ); } protected int getTargetInstanceID() { return( target_instance_id ); } public long getConnectionId() { return( connection_id ); } protected long getClockSkew() { return( skew ); } public byte getProtocolVersion() { return( protocol_version ); } protected byte getVendorID() { return( vendor_id ); } public int getNetwork() { return( network ); } public void setNetwork( int _network ) { network = _network; } protected DHTNetworkPosition[] getNetworkPositions() { return( network_positions ); } protected void setNetworkPositions( DHTNetworkPosition[] _network_positions ) { network_positions = _network_positions; } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); // add to this and you need to adjust HEADER_SIZE above os.writeLong( connection_id ); os.writeByte( protocol_version ); if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_VENDOR_ID ){ os.writeByte( DHTTransportUDP.VENDOR_ID_ME ); } if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_NETWORKS ){ os.writeInt( network ); } os.writeInt( target_instance_id ); } public String getString() { return( super.getString() + ",[con="+connection_id+",prot=" + protocol_version + ",ven=" + vendor_id + ",net="+network+"]"); } }azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyKeyBlock.java0000644000175000017500000000357411033103414031462 0ustar adrianadrian/* * File : PRUDPPacketReplyConnect.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.dht.transport.udp.impl; /** * @author parg * */ import java.io.*; import java.net.InetSocketAddress; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; public class DHTUDPPacketReplyKeyBlock extends DHTUDPPacketReply { public DHTUDPPacketReplyKeyBlock( DHTTransportUDPImpl transport, int trans_id, long conn_id, DHTTransportContact local_contact, DHTTransportContact remote_contact ) { super( transport, DHTUDPPacketHelper.ACT_REPLY_KEY_BLOCK, trans_id, conn_id, local_contact, remote_contact ); } protected DHTUDPPacketReplyKeyBlock( DHTUDPPacketNetworkHandler network_handler, InetSocketAddress originator, DataInputStream is, int trans_id ) throws IOException { super( network_handler, originator, is, DHTUDPPacketHelper.ACT_REPLY_KEY_BLOCK, trans_id ); } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyStore.java0000644000175000017500000000476111033103414031052 0ustar adrianadrian/* * File : PRUDPPacketReplyConnect.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.core.dht.transport.udp.impl; /** * @author parg * */ import java.io.*; import java.net.InetSocketAddress; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; public class DHTUDPPacketReplyStore extends DHTUDPPacketReply { private byte[] diversify; public DHTUDPPacketReplyStore( DHTTransportUDPImpl transport, int trans_id, long conn_id, DHTTransportContact local_contact, DHTTransportContact remote_contact ) { super( transport, DHTUDPPacketHelper.ACT_REPLY_STORE, trans_id, conn_id, local_contact, remote_contact ); } protected DHTUDPPacketReplyStore( DHTUDPPacketNetworkHandler network_handler, InetSocketAddress originator, DataInputStream is, int trans_id ) throws IOException { super( network_handler, originator, is, DHTUDPPacketHelper.ACT_REPLY_STORE, trans_id ); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_DIV_AND_CONT ){ diversify = DHTUDPUtils.deserialiseByteArray( is, DHTUDPPacketRequestStore.MAX_KEYS_PER_PACKET ); } } public void serialise( DataOutputStream os ) throws IOException { super.serialise(os); if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_DIV_AND_CONT ){ DHTUDPUtils.serialiseByteArray( os, diversify, DHTUDPPacketRequestStore.MAX_KEYS_PER_PACKET ); } } public void setDiversificationTypes( byte[] _diversify ) { diversify = _diversify; } public byte[] getDiversificationTypes() { return( diversify ); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/Test.java0000644000175000017500000001773111267313012025627 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.util.List; import java.util.Map; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.transport.*; import com.aelitis.azureus.core.dht.transport.udp.*; /** * @author parg * */ public class Test implements DHTTransportRequestHandler { public static void main( String[] args ) { new Test(); } protected Test() { try{ DHTTransport udp1 = DHTTransportFactory.createUDP( DHTTransportUDP.PROTOCOL_VERSION_MAIN, DHT.NW_MAIN, false, null, null, 6881, 5, 3, 5000, 50, 25, false, false, com.aelitis.azureus.core.dht.impl.Test.getLogger()); udp1.setRequestHandler( this ); DHTTransport udp2 = DHTTransportFactory.createUDP( DHTTransportUDP.PROTOCOL_VERSION_MAIN, DHT.NW_MAIN, false, null, null, 6882, 5, 3, 5000, 50, 25, false, false, com.aelitis.azureus.core.dht.impl.Test.getLogger()); udp2.setRequestHandler( this ); final DHTTransportUDPContact c1 = (DHTTransportUDPContact)udp1.getLocalContact(); for (int i=0;i<10;i++){ final int f_i = i; c1.sendPing( new DHTTransportReplyHandlerAdapter() { public void pingReply( DHTTransportContact contact ) { System.out.println( "ping reply: " + f_i ); } public void failed( DHTTransportContact contact, Throwable error ) { System.out.println( "ping failed" ); } }); } c1.sendStore( new DHTTransportReplyHandlerAdapter() { public void storeReply( DHTTransportContact contact, byte[] types ) { System.out.println( "store reply" ); } public void failed( DHTTransportContact contact, Throwable error ) { System.out.println( "store failed" ); } }, new byte[][]{ new byte[23] }, new DHTTransportValue[][]{{ new DHTTransportValue() { public boolean isLocal() { return( false ); } public long getCreationTime() { return( 2 ); } public byte[] getValue() { return( "sdsd".getBytes()); } public int getVersion() { return( 0 ); } public DHTTransportContact getOriginator() { return( c1 ); } public int getFlags() { return(0); } public int getLifeTimeHours() { return 0; } public byte getReplicationControl() { return 0; } public byte getReplicationFactor() { return 0; } public byte getReplicationFrequencyHours() { return 0; } public String getString() { return( new String(getValue())); } } }}, false ); c1.sendFindNode( new DHTTransportReplyHandlerAdapter() { public void findNodeReply( DHTTransportContact contact, DHTTransportContact[] contacts ) { System.out.println( "findNode reply" ); } public void failed( DHTTransportContact contact, Throwable e ) { System.out.println( "findNode failed" ); } }, new byte[12]); System.out.println( "sending find value" ); c1.sendFindValue( new DHTTransportReplyHandlerAdapter() { public void findValueReply( DHTTransportContact contact, DHTTransportContact[] contacts ) { System.out.println( "findValue contacts reply" ); } public void findValueReply( DHTTransportContact contact, DHTTransportValue[] values, byte diversification_type, boolean more_to_come ) { System.out.println( "findValue value reply" ); } public void failed( DHTTransportContact contact, Throwable error ) { System.out.println( "findValue failed" ); } }, new byte[3], 1, (byte)0 ); System.out.println( "sending complete" ); Thread.sleep(1000000); }catch( Throwable e ){ e.printStackTrace(); } } public void pingRequest( DHTTransportContact contact ) { System.out.println( "TransportHandler: ping" ); } public void keyBlockRequest( DHTTransportContact contact, byte[] key_block_request, byte[] key_block_signature ) { System.out.println( "TransportHandler: keyBlockRequest" ); } public DHTTransportStoreReply storeRequest( DHTTransportContact contact, final byte[][] keys, DHTTransportValue[][] value_sets ) { System.out.println( "TransportHandler: store" ); return( new DHTTransportStoreReply() { public byte[] getDiversificationTypes() { return( new byte[keys.length] ); } public boolean blocked() { return( false ); } public byte[] getBlockRequest() { return( null ); } public byte[] getBlockSignature() { return( null ); } }); } public DHTTransportQueryStoreReply queryStoreRequest( DHTTransportContact contact, int headerLen, List keys) { System.out.println( "TransportHandler: queryStore" ); return null; } public DHTTransportContact[] findNodeRequest( DHTTransportContact contact, byte[] id ) { System.out.println( "TransportHandler: findNode" ); return(new DHTTransportContact[]{ contact }); } public DHTTransportFindValueReply findValueRequest( final DHTTransportContact contact, byte[] key, int max_values, byte flags ) { System.out.println( "TransportHandler: findValue" ); return( new DHTTransportFindValueReply() { public boolean hit() { return( false ); } public byte getDiversificationType() { return( DHT.DT_NONE ); } public DHTTransportValue[] getValues() { return( null ); } public DHTTransportContact[] getContacts() { return( new DHTTransportContact[]{ contact } ); } public boolean blocked() { return( false ); } public byte[] getBlockedKey() { return( null ); } public byte[] getBlockedSignature() { return( null ); } }); } public void contactImported( DHTTransportContact contact ) { } public void contactRemoved( DHTTransportContact contact ) { } public int getTransportEstimatedDHTSize() { return(0); } public void setTransportEstimatedDHTSize( int size ) { } public DHTTransportFullStats statsRequest( DHTTransportContact contact ) { return( null ); } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestQueryStorage.javaazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestQueryStorage.java0000644000175000017500000000727411257322534032765 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; import java.util.*; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler; /** * @author parg * */ public class DHTUDPPacketRequestQueryStorage extends DHTUDPPacketRequest { protected static final int SPACE = DHTUDPPacketHelper.PACKET_MAX_BYTES - DHTUDPPacketRequest.DHT_HEADER_SIZE - 3; private int header_length; private List keys; public DHTUDPPacketRequestQueryStorage( DHTTransportUDPImpl _transport, long _connection_id, DHTTransportUDPContactImpl _local_contact, DHTTransportUDPContactImpl _remote_contact ) { super( _transport, DHTUDPPacketHelper.ACT_REQUEST_QUERY_STORE, _connection_id, _local_contact, _remote_contact ); } protected DHTUDPPacketRequestQueryStorage( DHTUDPPacketNetworkHandler network_handler, DataInputStream is, long con_id, int trans_id ) throws IOException { super( network_handler, is, DHTUDPPacketHelper.ACT_REQUEST_QUERY_STORE, con_id, trans_id ); header_length = is.readByte()&0xff; int num_keys = is.readShort(); keys = new ArrayList( num_keys ); for (int i=0;i suffixes = new ArrayList( num_suffixes ); keys.add( new Object[]{ prefix, suffixes }); int suffix_length = header_length - prefix_length; for (int j=0;j suffixes = (List)entry[1]; os.writeShort( suffixes.size()); for ( byte[] suffix: suffixes ){ os.write( suffix ); } } super.postSerialise( os ); } protected void setDetails( int _header_length, List _keys ) { header_length = _header_length; keys = _keys; } protected int getHeaderLength() { return( header_length ); } protected List getKeys() { return( keys ); } public String getString() { return( super.getString()); } }azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacket.java0000644000175000017500000000215310373051014027016 0ustar adrianadrian/* * Created on 12-Jun-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp.impl; public interface DHTUDPPacket { public DHTTransportUDPImpl getTransport(); public byte getProtocolVersion(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDPContact.java0000644000175000017500000000255410440744656030203 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp; import java.net.InetSocketAddress; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; /** * @author parg * */ public interface DHTTransportUDPContact extends DHTTransportContact { public InetSocketAddress getTransportAddress(); public void setTransportAddress( InetSocketAddress address ); public InetSocketAddress getExternalAddress(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDP.java0000644000175000017500000001225711274125512026656 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.udp; import java.net.InetSocketAddress; import com.aelitis.azureus.core.dht.transport.DHTTransport; import com.aelitis.azureus.core.dht.transport.DHTTransportException; /** * @author parg * */ public interface DHTTransportUDP extends DHTTransport { public static final byte PROTOCOL_VERSION_2304 = 8; public static final byte PROTOCOL_VERSION_2306 = 12; public static final byte PROTOCOL_VERSION_2400 = 13; public static final byte PROTOCOL_VERSION_2402 = 14; public static final byte PROTOCOL_VERSION_2500 = 15; public static final byte PROTOCOL_VERSION_2502 = 16; public static final byte PROTOCOL_VERSION_3111 = 17; public static final byte PROTOCOL_VERSION_4204 = 22; // min -> 17 public static final byte PROTOCOL_VERSION_4208 = 23; public static final byte PROTOCOL_VERSION_DIV_AND_CONT = 6; public static final byte PROTOCOL_VERSION_ANTI_SPOOF = 7; public static final byte PROTOCOL_VERSION_ENCRYPT_TT = 8; // refed from DDBase public static final byte PROTOCOL_VERSION_ANTI_SPOOF2 = 8; // we can't fix the originator position until a previous fix regarding the incorrect // use of a contact's version > sender's version is fixed. This will be done at 2.3.0.4 // We can therefore only apply this fix after then public static final byte PROTOCOL_VERSION_FIX_ORIGINATOR = 9; public static final byte PROTOCOL_VERSION_VIVALDI = 10; public static final byte PROTOCOL_VERSION_REMOVE_DIST_ADD_VER = 11; public static final byte PROTOCOL_VERSION_XFER_STATUS = 12; public static final byte PROTOCOL_VERSION_SIZE_ESTIMATE = 13; public static final byte PROTOCOL_VERSION_VENDOR_ID = 14; public static final byte PROTOCOL_VERSION_BLOCK_KEYS = 14; public static final byte PROTOCOL_VERSION_GENERIC_NETPOS = 15; public static final byte PROTOCOL_VERSION_VIVALDI_FINDVALUE = 16; public static final byte PROTOCOL_VERSION_ANON_VALUES = 17; public static final byte PROTOCOL_VERSION_CVS_FIX_OVERLOAD_V1 = 18; public static final byte PROTOCOL_VERSION_CVS_FIX_OVERLOAD_V2 = 19; public static final byte PROTOCOL_VERSION_MORE_STATS = 20; public static final byte PROTOCOL_VERSION_CVS_FIX_OVERLOAD_V3 = 21; public static final byte PROTOCOL_VERSION_MORE_NODE_STATUS = 22; public static final byte PROTOCOL_VERSION_LONGER_LIFE = 23; public static final byte PROTOCOL_VERSION_REPLICATION_CONTROL = 24; public static final byte PROTOCOL_VERSION_REPLICATION_CONTROL2 = 25; public static final byte PROTOCOL_VERSION_REPLICATION_CONTROL3 = 26; public static final byte PROTOCOL_VERSION_RESTRICT_ID_PORTS = 32; // introduced now (2403/V15) to support possible future change to id allocation // If/when introduced the min DHT version must be set to 15 at the same time public static final byte PROTOCOL_VERSION_RESTRICT_ID_PORTS2 = 33; public static final byte PROTOCOL_VERSION_RESTRICT_ID_PORTS2X = 34; // nothing new here - added to we can track CVS user's access to replication control public static final byte PROTOCOL_VERSION_RESTRICT_ID_PORTS2Y = 35; // another one to track fix to broken rep factor handling public static final byte PROTOCOL_VERSION_RESTRICT_ID_PORTS2Z = 36; // hopefully last one - needed to excluded nodes that don't support replication frequency // multiple networks reformats the requests and therefore needs the above fix to work public static final byte PROTOCOL_VERSION_NETWORKS = PROTOCOL_VERSION_FIX_ORIGINATOR; // current versions public static final byte PROTOCOL_VERSION_MAIN = PROTOCOL_VERSION_REPLICATION_CONTROL3; public static final byte PROTOCOL_VERSION_CVS = PROTOCOL_VERSION_RESTRICT_ID_PORTS2Z; public static final byte PROTOCOL_VERSION_MIN = PROTOCOL_VERSION_MORE_NODE_STATUS; public static final byte PROTOCOL_VERSION_MIN_CVS = PROTOCOL_VERSION_RESTRICT_ID_PORTS2Z; public static final byte VENDOR_ID_AELITIS = 0x00; public static final byte VENDOR_ID_ShareNET = 0x01; // http://www.sharep2p.net/ public static final byte VENDOR_ID_NONE = (byte)0xff; public static final byte VENDOR_ID_ME = VENDOR_ID_AELITIS; public DHTTransportUDPContact importContact( InetSocketAddress address, byte protocol_version ) throws DHTTransportException; } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportRequestHandler.java0000644000175000017500000000427511260535130030361 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; /** * @author parg * */ import java.util.*; public interface DHTTransportRequestHandler { public void pingRequest( DHTTransportContact contact ); public void keyBlockRequest( DHTTransportContact contact, byte[] key_block_request, byte[] key_block_signature ); public DHTTransportFullStats statsRequest( DHTTransportContact contact ); public DHTTransportStoreReply storeRequest( DHTTransportContact contact, byte[][] keys, DHTTransportValue[][] value_sets ); public DHTTransportQueryStoreReply queryStoreRequest( DHTTransportContact contact, int header_len, List keys ); public DHTTransportContact[] findNodeRequest( DHTTransportContact contact, byte[] id ); public DHTTransportFindValueReply findValueRequest( DHTTransportContact contact, byte[] key, int max_values, byte flags ); /** * Mechanism for reporting that a contact has been imported * @param contact */ public void contactImported( DHTTransportContact contact ); public void contactRemoved( DHTTransportContact contact ); public int getTransportEstimatedDHTSize(); public void setTransportEstimatedDHTSize( int size ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/loopback/0000755000175000017500000000000011310377624024105 5ustar adrianadrian././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackContactImpl.javaazureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackContactImpl.java0000644000175000017500000001054211265520564033121 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.loopback; import java.io.*; import java.net.InetSocketAddress; import java.util.List; import java.util.Map; import com.aelitis.azureus.core.dht.impl.DHTLog; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition; import com.aelitis.azureus.core.dht.transport.*; /** * @author parg * */ public class DHTTransportLoopbackContactImpl implements DHTTransportContact { private DHTTransportLoopbackImpl transport; private byte[] id; private int random_id; protected DHTTransportLoopbackContactImpl( DHTTransportLoopbackImpl _transport, byte[] _id ) { transport = _transport; id = _id; } public DHTTransport getTransport() { return( transport ); } public int getInstanceID() { return( 0 ); } public byte getProtocolVersion() { return( 0 ); } public long getClockSkew() { return( 0 ); } public int getRandomID() { return( random_id ); } public void setRandomID( int _random_id ) { random_id = _random_id; } public boolean isValid() { return( true ); } public int getMaxFailForLiveCount() { return( 5 ); } public int getMaxFailForUnknownCount() { return( 3 ); } public String getName() { return( "" ); } public InetSocketAddress getAddress() { return( null ); } public InetSocketAddress getExternalAddress() { return null; } public boolean isAlive( long timeout ) { return( true ); } public void isAlive( DHTTransportReplyHandler handler, long timeout ) { transport.sendPing( this, handler ); } public void sendPing( DHTTransportReplyHandler handler ) { transport.sendPing( this, handler ); } public void sendImmediatePing( DHTTransportReplyHandler handler, long timeout ) { transport.sendPing( this, handler ); } public void sendKeyBlock( DHTTransportReplyHandler handler, byte[] request, byte[] signature ) { transport.sendKeyBlock( this, handler, request, signature ); } public void sendStats( DHTTransportReplyHandler handler ) { transport.sendStats( this, handler ); } public void sendStore( DHTTransportReplyHandler handler, byte[][] keys, DHTTransportValue[][] value_sets, boolean immediate ) { transport.sendStore( this, handler, keys, value_sets, false ); } public void sendQueryStore( DHTTransportReplyHandler handler, int header_length, List key_details ) { transport.sendQueryStore( this, handler, header_length, key_details); } public void sendFindNode( DHTTransportReplyHandler handler, byte[] nid ) { transport.sendFindNode( this, handler, nid ); } public void sendFindValue( DHTTransportReplyHandler handler, byte[] key, int max, byte flags ) { transport.sendFindValue( this, handler, key, max, flags ); } public DHTTransportFullStats getStats() { return( null ); } public byte[] getID() { return( id ); } public void exportContact( DataOutputStream os ) throws IOException { transport.exportContact( this, os ); } public void remove() { transport.removeContact( this ); } public DHTNetworkPosition[] getNetworkPositions() { return( new DHTNetworkPosition[0] ); } public DHTNetworkPosition getNetworkPosition( byte type ) { return( null ); } public String getString() { return( DHTLog.getString( this )); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackStatsImpl.java0000644000175000017500000000351011104431514032605 0ustar adrianadrian/* * Created on 01-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.loopback; import com.aelitis.azureus.core.dht.transport.DHTTransportStats; import com.aelitis.azureus.core.dht.transport.util.DHTTransportStatsImpl; /** * @author parg * */ public class DHTTransportLoopbackStatsImpl extends DHTTransportStatsImpl { protected DHTTransportLoopbackStatsImpl( byte pv ) { super( pv ); } public long getPacketsSent() { return( 0 ); } public long getPacketsReceived() { return( 0 ); } public long getRequestsTimedOut() { return( 0 ); } public long getBytesSent() { return( 0 ); } public long getBytesReceived() { return( 0 ); } public int getRouteablePercentage() { return -1; } public DHTTransportStats snapshot() { DHTTransportStatsImpl res = new DHTTransportLoopbackStatsImpl(getProtocolVersion()); snapshotSupport( res ); return( res ); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackImpl.java0000644000175000017500000003453711262527612031615 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport.loopback; import java.util.*; import java.io.*; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.transport.*; import com.aelitis.azureus.core.dht.transport.util.DHTTransportRequestCounter; import com.aelitis.azureus.core.dht.transport.util.DHTTransportStatsImpl; /** * @author parg * */ public class DHTTransportLoopbackImpl implements DHTTransport { public static byte VERSION = 1; public static int LATENCY = 0; public static int FAIL_PERCENTAGE = 0; public byte getProtocolVersion() { return( VERSION ); } public int getNetwork() { return( DHT.NW_MAIN ); } public static void setLatency( int _latency ) { LATENCY = _latency; } public static void setFailPercentage( int p ) { FAIL_PERCENTAGE = p; } private static long node_id_seed_next = 0; private static Map node_map = new HashMap(); private static List dispatch_queue = new ArrayList(); private static AESemaphore dispatch_queue_sem = new AESemaphore("DHTTransportLoopback" ); private static AEMonitor class_mon = new AEMonitor( "DHTTransportLoopback:class" ); static{ AEThread dispatcher = new AEThread("DHTTransportLoopback") { public void runSupport() { while(true){ dispatch_queue_sem.reserve(); Runnable r; try{ class_mon.enter(); r = (Runnable)dispatch_queue.remove(0); }finally{ class_mon.exit(); } if ( LATENCY > 0 ){ try{ Thread.sleep( LATENCY ); }catch( Throwable e ){ } } r.run(); } } }; dispatcher.start(); } private byte[] node_id; private DHTTransportContact local_contact; private int id_byte_length; private DHTTransportRequestHandler request_handler; private DHTTransportStatsImpl stats = new DHTTransportLoopbackStatsImpl( VERSION ); private List listeners = new ArrayList(); public static DHTTransportStats getOverallStats() { try{ class_mon.enter(); DHTTransportStatsImpl overall_stats = new DHTTransportLoopbackStatsImpl( VERSION ); Iterator it = node_map.values().iterator(); while( it.hasNext()){ overall_stats.add((DHTTransportStatsImpl)((DHTTransportLoopbackImpl)it.next()).getStats()); } return( overall_stats ); }finally{ class_mon.exit(); } } public DHTTransportLoopbackImpl( int _id_byte_length ) { id_byte_length = _id_byte_length; try{ class_mon.enter(); byte[] temp = new SHA1Simple().calculateHash( ( "" + ( node_id_seed_next++ )).getBytes()); node_id = new byte[id_byte_length]; System.arraycopy( temp, 0, node_id, 0, id_byte_length ); node_map.put( new HashWrapper( node_id ), this ); local_contact = new DHTTransportLoopbackContactImpl( this, node_id ); }finally{ class_mon.exit(); } } public DHTTransportContact getLocalContact() { return( local_contact ); } public void setPort( int port ) { } public int getPort() { return( 0 ); } public long getTimeout() { return( 0 ); } public void setTimeout( long millis ) { } public boolean isReachable() { return( true ); } public DHTTransportContact[] getReachableContacts() { return( new DHTTransportContact[0] ); } public DHTTransportContact[] getRecentContacts() { return( new DHTTransportContact[0] ); } protected DHTTransportLoopbackImpl findTarget( byte[] id ) { try{ class_mon.enter(); return((DHTTransportLoopbackImpl)node_map.get( new HashWrapper( id ))); }finally{ class_mon.exit(); } } public void setRequestHandler( DHTTransportRequestHandler _request_handler ) { request_handler = new DHTTransportRequestCounter( _request_handler, stats ); } protected DHTTransportRequestHandler getRequestHandler() { return( request_handler ); } public void exportContact( DHTTransportContact contact, DataOutputStream os ) throws IOException { os.writeInt( VERSION ); os.writeInt( id_byte_length ); os.write( contact.getID()); } public DHTTransportContact importContact( DataInputStream is ) throws IOException { int version = is.readInt(); if ( version != VERSION ){ throw( new IOException( "Unsuported version" )); } int id_len = is.readInt(); if ( id_len != id_byte_length ){ throw( new IOException( "Imported contact has incorrect ID length" )); } byte[] id = new byte[id_byte_length]; is.read( id ); DHTTransportContact contact = new DHTTransportLoopbackContactImpl( this, id ); request_handler.contactImported( contact ); return( contact ); } public void removeContact( DHTTransportContact contact ) { } protected void run( final AERunnable r ) { try{ class_mon.enter(); dispatch_queue.add( r ); }finally{ class_mon.exit(); } dispatch_queue_sem.release(); } public DHTTransportStats getStats() { return( stats ); } // transport // PING public void sendPing( final DHTTransportContact contact, final DHTTransportReplyHandler handler ) { AERunnable runnable = new AERunnable() { public void runSupport() { sendPingSupport( contact, handler ); } }; run( runnable ); } public void sendPingSupport( DHTTransportContact contact, DHTTransportReplyHandler handler ) { DHTTransportLoopbackImpl target = findTarget( contact.getID()); stats.pingSent(null); if ( target == null || triggerFailure()){ stats.pingFailed(); handler.failed(contact, new Exception( "failed" )); }else{ stats.pingOK(); target.getRequestHandler().pingRequest( new DHTTransportLoopbackContactImpl( target, node_id )); handler.pingReply(contact,0); } } public void sendKeyBlock( final DHTTransportContact contact, final DHTTransportReplyHandler handler, final byte[] request, final byte[] sig ) { AERunnable runnable = new AERunnable() { public void runSupport() { sendKeyBlockSupport( contact, handler, request, sig ); } }; run( runnable ); } public void sendKeyBlockSupport( DHTTransportContact contact, DHTTransportReplyHandler handler, byte[] request, byte[] sig ) { DHTTransportLoopbackImpl target = findTarget( contact.getID()); stats.keyBlockSent(null); if ( target == null || triggerFailure()){ stats.keyBlockFailed(); handler.failed(contact, new Exception( "failed" )); }else{ stats.keyBlockOK(); target.getRequestHandler().keyBlockRequest( new DHTTransportLoopbackContactImpl( target, node_id ), request, sig ); handler.keyBlockReply(contact); } } // STATS public void sendStats( final DHTTransportContact contact, final DHTTransportReplyHandler handler ) { AERunnable runnable = new AERunnable() { public void runSupport() { sendStatsSupport( contact, handler ); } }; run( runnable ); } public void sendStatsSupport( DHTTransportContact contact, DHTTransportReplyHandler handler ) { DHTTransportLoopbackImpl target = findTarget( contact.getID()); stats.statsSent(null); if ( target == null || triggerFailure()){ stats.statsFailed(); handler.failed(contact, new Exception( "failed")); }else{ stats.statsOK(); DHTTransportFullStats res = target.getRequestHandler().statsRequest( new DHTTransportLoopbackContactImpl( target, node_id )); handler.statsReply(contact,res); } } // STORE public void sendStore( final DHTTransportContact contact, final DHTTransportReplyHandler handler, final byte[][] keys, final DHTTransportValue[][] value_sets, final boolean immediate ) { AERunnable runnable = new AERunnable() { public void runSupport() { sendStoreSupport( contact, handler, keys, value_sets ); } }; run( runnable ); } public void sendStoreSupport( DHTTransportContact contact, DHTTransportReplyHandler handler, byte[][] keys, DHTTransportValue[][] value_sets ) { DHTTransportLoopbackImpl target = findTarget( contact.getID()); stats.storeSent(null); if ( target == null || triggerFailure()){ stats.storeFailed(); handler.failed(contact,new Exception( "failed")); }else{ stats.storeOK(); DHTTransportContact temp = new DHTTransportLoopbackContactImpl( target, node_id ); temp.setRandomID( contact.getRandomID()); DHTTransportStoreReply rep = target.getRequestHandler().storeRequest( temp, keys, value_sets ); if ( rep.blocked()){ handler.keyBlockRequest( contact, rep.getBlockRequest(), rep.getBlockSignature()); handler.failed( contact, new Throwable( "key blocked" )); }else{ handler.storeReply( contact, rep.getDiversificationTypes()); } } } // QUERY STORE public void sendQueryStore( DHTTransportContact contact, DHTTransportReplyHandler handler, int header_length, List key_details ) { handler.failed( contact, new Throwable( "not implemented" )); } // FIND NODE public void sendFindNode( final DHTTransportContact contact, final DHTTransportReplyHandler handler, final byte[] nid ) { AERunnable runnable = new AERunnable() { public void runSupport() { sendFindNodeSupport( contact, handler, nid ); } }; run( runnable ); } public void sendFindNodeSupport( DHTTransportContact contact, DHTTransportReplyHandler handler, byte[] nid ) { DHTTransportLoopbackImpl target = findTarget( contact.getID()); stats.findNodeSent(null); if ( target == null || triggerFailure() ){ stats.findNodeFailed(); handler.failed(contact,new Exception( "failed")); }else{ stats.findNodeOK(); DHTTransportContact temp = new DHTTransportLoopbackContactImpl( target, node_id ); DHTTransportContact[] res = target.getRequestHandler().findNodeRequest( temp, nid ); contact.setRandomID( temp.getRandomID()); DHTTransportContact[] trans_res = new DHTTransportContact[res.length]; for (int i=0;i= 0 && protocol_version < outgoing_request_versions.length ){ outgoing_request_versions[ protocol_version ]++; outgoing_version_requests++; if ( outgoing_version_requests%100 == 0 ){ String str= ""; for (int i=0;i 0 ){ str += (str.length()==0?"":", ") + i + "=" + count + "[" + ((outgoing_request_versions[i]*100)/outgoing_version_requests) + "]"; } } System.out.println( "net " + request.getTransport().getNetwork() + ": Outgoing versions: tot = " + outgoing_requests +"/" + outgoing_version_requests + ": " + str ); } if ( outgoing_version_requests%1000 == 0 ){ for (int i=0;i 0 ){ str += (str.length()==0?"":", ") + i + "=" + count + "[" + ((incoming_request_versions[i]*100)/incoming_version_requests) + "]"; } } System.out.println( "net " + request.getTransport().getNetwork() + ": Incoming versions: tot = " + incoming_requests +"/" + incoming_version_requests + ": " + str ); } if ( incoming_version_requests%1000 == 0 ){ for (int i=0;i 30000 ){ int[] values = (int[])skew_values.clone(); int pos = skew_pos; int num_values; if ( values[pos] == Integer.MAX_VALUE ){ num_values = pos; }else{ num_values = SKEW_VALUE_MAX; } Arrays.sort( values, 0, num_values ); // remove outliers int start = num_values/3; int end = 2*num_values/3; int entries = end - start; if ( entries < 5 ){ last_skew_average = 0; }else{ long total = 0; for (int i=start;i keys ) { stats.queryStoreReceived(); return( delegate.queryStoreRequest( contact, header_len, keys )); } public DHTTransportContact[] findNodeRequest( DHTTransportContact contact, byte[] id ) { stats.findNodeReceived(); return( delegate.findNodeRequest( contact, id )); } public DHTTransportFindValueReply findValueRequest( DHTTransportContact contact, byte[] key, int max, byte flags ) { stats.findValueReceived(); return( delegate.findValueRequest( contact, key, max, flags )); } public void contactImported( DHTTransportContact contact ) { delegate.contactImported( contact ); } public void contactRemoved( DHTTransportContact contact ) { delegate.contactRemoved( contact ); } public int getTransportEstimatedDHTSize() { return( delegate.getTransportEstimatedDHTSize()); } public void setTransportEstimatedDHTSize( int size ) { delegate.setTransportEstimatedDHTSize(size); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportListener.java0000644000175000017500000000236510373051010027210 0ustar adrianadrian/* * Created on 24-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; /** * @author parg * */ public interface DHTTransportListener { public void localContactChanged( DHTTransportContact local_contact ); public void currentAddress( String address ); public void reachabilityChanged( boolean reacheable ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportException.java0000644000175000017500000000236411012741350027364 0ustar adrianadrian/* * Created on 25-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; /** * @author parg * */ public class DHTTransportException extends Exception { public DHTTransportException( String str ) { super( str ); } public DHTTransportException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandler.java0000644000175000017500000000404011257035612030020 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; /** * @author parg * */ import java.util.*; public interface DHTTransportReplyHandler { public void pingReply( DHTTransportContact contact, int elapsed_time ); public void statsReply( DHTTransportContact contact, DHTTransportFullStats stats ); public void storeReply( DHTTransportContact contact, byte[] diversifications ); public void queryStoreReply( DHTTransportContact contact, List response ); public void findNodeReply( DHTTransportContact contact, DHTTransportContact[] contacts ); public void findValueReply( DHTTransportContact contact, DHTTransportValue[] values, byte diversification_type, boolean more_to_come ); public void findValueReply( DHTTransportContact contact, DHTTransportContact[] contacts ); public void keyBlockReply( DHTTransportContact contact ); public void keyBlockRequest( DHTTransportContact contact, byte[] key, byte[] key_signature ); public void failed( DHTTransportContact contact, Throwable error ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportQueryStoreReply.java0000644000175000017500000000173011260535126030567 0ustar adrianadrian/* * Created on Sep 29, 2009 * Created by Paul Gardner * * Copyright 2009 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.core.dht.transport; import java.util.List; public interface DHTTransportQueryStoreReply { public int getHeaderSize(); public List getEntries(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandlerAdapter.java0000644000175000017500000000535311257035612031331 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; import java.util.List; import org.gudy.azureus2.core3.util.Debug; /** * @author parg * */ public abstract class DHTTransportReplyHandlerAdapter implements DHTTransportReplyHandler { private int elapsed; public void pingReply( DHTTransportContact contact, int _elapsed ) { elapsed = _elapsed; pingReply( contact ); } public void pingReply( DHTTransportContact contact ) { throw( new RuntimeException( "Not implemented" )); } public int getElapsed() { return( elapsed ); } public void statsReply( DHTTransportContact contact, DHTTransportFullStats stats ) { throw( new RuntimeException( "Not implemented" )); } public void storeReply( DHTTransportContact contact, byte[] diversifications ) { throw( new RuntimeException( "Not implemented" )); } public void queryStoreReply( DHTTransportContact contact, List response ) { throw( new RuntimeException( "Not implemented" )); } public void findNodeReply( DHTTransportContact contact, DHTTransportContact[] contacts ) { throw( new RuntimeException( "Not implemented" )); } public void findValueReply( DHTTransportContact contact, DHTTransportValue[] values, byte diversification_type, boolean more_to_come ) { throw( new RuntimeException( "Not implemented" )); } public void findValueReply( DHTTransportContact contact, DHTTransportContact[] contacts ) { throw( new RuntimeException( "Not implemented" )); } public void keyBlockRequest( DHTTransportContact contact, byte[] key, byte[] key_signature ) { Debug.out( "keyblock not handled" ); } public void keyBlockReply( DHTTransportContact _contact ) { throw( new RuntimeException( "Not implemented" )); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/transport/DHTTransportStoreReply.java0000644000175000017500000000225010402150270027525 0ustar adrianadrian/* * Created on 02-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.transport; public interface DHTTransportStoreReply { public byte[] getDiversificationTypes(); public boolean blocked(); public byte[] getBlockRequest(); public byte[] getBlockSignature(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/DHTStorageKey.java0000644000175000017500000000233710434652646023552 0ustar adrianadrian/* * Created on 12-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht; import java.io.DataOutputStream; import java.io.IOException; /** * @author parg * */ public interface DHTStorageKey { public byte getDiversificationType(); public void serialiseStats( DataOutputStream os ) throws IOException; } azureus-4.3.0.6/com/aelitis/azureus/core/dht/DHTOperationListener.java0000644000175000017500000000316511256357140025135 0ustar adrianadrian/* * Created on 31-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportValue; /** * @author parg * */ public interface DHTOperationListener { public void searching( DHTTransportContact contact, int level, int active_searches ); public void diversified( String desc ); public void found( DHTTransportContact contact, boolean is_closest ); public void read( DHTTransportContact contact, DHTTransportValue value ); public void wrote( DHTTransportContact contact, DHTTransportValue value ); public void complete( boolean timeout ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/db/0000755000175000017500000000000011310377622020642 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/dht/db/DHTDB.java0000644000175000017500000000641111274464546022347 0ustar adrianadrian/* * Created on 28-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.db; import java.util.Iterator; import java.util.List; import org.gudy.azureus2.core3.util.HashWrapper; import com.aelitis.azureus.core.dht.DHTStorageBlock; import com.aelitis.azureus.core.dht.control.DHTControl; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportQueryStoreReply; import com.aelitis.azureus.core.dht.transport.DHTTransportValue; /** * @author parg * */ public interface DHTDB { public void setControl( DHTControl control ); /** * Local store * @param key * @param value * @param flags * @return */ public DHTDBValue store( HashWrapper key, byte[] value, byte flags, byte life_hours, byte replication_control ); /** * Remote store * * @param sender * @param key * @param values * @return diversification state */ public byte store( DHTTransportContact sender, HashWrapper key, DHTTransportValue[] values ); public DHTTransportQueryStoreReply queryStore( DHTTransportContact originating_contact, int header_len, List keys ); /** * Internal lookup for locally originated values * @param key * @return */ public DHTDBValue get( HashWrapper key ); public boolean hasKey( HashWrapper key ); public DHTDBLookupResult get( DHTTransportContact reader, HashWrapper key, int max_values, byte flags, boolean external_request ); /** * Local remove - returns a value suitable for putting in the DHT * @param sender * @param key * @return */ public DHTDBValue remove( DHTTransportContact sender, HashWrapper key ); public DHTStorageBlock keyBlockRequest( DHTTransportContact direct_sender, byte[] request, byte[] signature ); public DHTStorageBlock getKeyBlockDetails( byte[] key ); public boolean isKeyBlocked( byte[] key ); public DHTStorageBlock[] getDirectKeyBlocks(); public boolean isEmpty(); /** * Returns an iterator over HashWrapper values denoting the snapshot of keys * Thus by the time a key is used the entry may no longer exist * @return */ public Iterator getKeys(); public DHTDBStats getStats(); public void print( boolean full ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/db/impl/0000755000175000017500000000000011310377622021603 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/dht/db/impl/DHTDBValueImpl.java0000644000175000017500000001271611267313014025115 0ustar adrianadrian/* * Created on 18-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.db.impl; import org.gudy.azureus2.core3.util.SystemTime; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.db.DHTDBValue; import com.aelitis.azureus.core.dht.impl.DHTLog; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportValue; /** * @author parg * */ public class DHTDBValueImpl implements DHTDBValue { private static final byte[] ZERO_LENGTH_BYTE_ARRAY = {}; private long creation_time; private byte[] value; private DHTTransportContact originator; private DHTTransportContact sender; private boolean local; private byte flags; private byte life_hours; private byte rep_control; private int version; private long store_time; /** * constructor for the originator of values only * @param _creation_time * @param _value * @param _originator * @param _sender * @param _distance * @param _flags */ protected DHTDBValueImpl( long _creation_time, byte[] _value, int _version, DHTTransportContact _originator, DHTTransportContact _sender, boolean _local, int _flags, int _life_hours, byte _rep_control ) { creation_time = _creation_time; value = _value; version = _version; originator = _originator; sender = _sender; local = _local; flags = (byte)_flags; life_hours = (byte)_life_hours; rep_control = _rep_control; // we get quite a few zero length values - optimise mem usage if ( value != null && value.length == 0 ){ value = ZERO_LENGTH_BYTE_ARRAY; } reset(); } /** * Constructor used to generate values for relaying to other contacts * or receiving a value from another contact - adjusts the sender * Originator, creation time, flags and value are fixed. * @param _sender * @param _other */ protected DHTDBValueImpl( DHTTransportContact _sender, DHTTransportValue _other, boolean _local ) { this( _other.getCreationTime(), _other.getValue(), _other.getVersion(), _other.getOriginator(), _sender, _local, _other.getFlags(), _other.getLifeTimeHours(), _other.getReplicationControl()); } protected void reset() { store_time = SystemTime.getCurrentTime(); // make sure someone hasn't sent us a stupid creation time if ( creation_time > store_time ){ creation_time = store_time; } } public long getCreationTime() { return( creation_time ); } protected void setCreationTime() { creation_time = SystemTime.getCurrentTime(); } protected void setStoreTime( long l ) { store_time = l; } protected long getStoreTime() { return( store_time ); } public boolean isLocal() { return( local ); } public byte[] getValue() { return( value ); } public int getVersion() { return( version ); } public DHTTransportContact getOriginator() { return( originator); } public DHTTransportContact getSender() { return( sender ); } public int getFlags() { return( flags&0xff ); } public void setFlags( byte _flags ) { flags = _flags; } public int getLifeTimeHours() { return( life_hours&0xff ); } public byte getReplicationControl() { return( rep_control ); } public byte getReplicationFactor() { return( rep_control == DHT.REP_FACT_DEFAULT?DHT.REP_FACT_DEFAULT:(byte)(rep_control&0x0f)); } public byte getReplicationFrequencyHours() { return( rep_control == DHT.REP_FACT_DEFAULT?DHT.REP_FACT_DEFAULT:(byte)((rep_control&0xf0)>>4)); } protected void setOriginatorAndSender( DHTTransportContact _originator ) { originator = _originator; sender = _originator; } public DHTDBValue getValueForRelay( DHTTransportContact _sender ) { return( new DHTDBValueImpl( _sender, this, local )); } public DHTDBValue getValueForDeletion( int _version ) { DHTDBValueImpl res = new DHTDBValueImpl( originator, this, local ); res.value = ZERO_LENGTH_BYTE_ARRAY; // delete -> 0 length value res.setCreationTime(); res.version = _version; return( res ); } public String getString() { long now = SystemTime.getCurrentTime(); return( DHTLog.getString( value ) + " - " + new String(value) + "{v=" + version + ",f=" + Integer.toHexString(flags) + ",l=" + life_hours + ",r=" + Integer.toHexString( rep_control ) + ",ca=" + (now - creation_time ) + ",sa=" + (now-store_time)+ ",se=" + sender.getString() + ",or=" + originator.getString() +"}" ); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/db/impl/DHTDBMapping.java0000644000175000017500000006624211261070632024615 0ustar adrianadrian/* * Created on 03-Feb-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.db.impl; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.util.*; import org.gudy.azureus2.core3.util.ByteFormatter; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.HashWrapper; import org.gudy.azureus2.core3.util.SystemTime; // import org.gudy.azureus2.core3.util.SHA1Hasher; import com.aelitis.azureus.core.dht.*; import com.aelitis.azureus.core.dht.impl.DHTLog; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.core.util.bloom.BloomFilterFactory; /** * @author parg * */ public class DHTDBMapping { private static final boolean TRACE_ADDS = false; private DHTDBImpl db; private HashWrapper key; private ShortHash short_key; private DHTStorageKey adapter_key; // maps are access order, most recently used at tail, so we cycle values private Map direct_originator_map_may_be_null; private Map indirect_originator_value_map = createLinkedMap(); private int hits; private int direct_data_size; private int indirect_data_size; private int local_size; private byte diversification_state = DHT.DT_NONE; private static final int IP_COUNT_BLOOM_SIZE_INCREASE_CHUNK = 50; // 4 bit filter - counts up to 15 private Object ip_count_bloom_filter; protected DHTDBMapping( DHTDBImpl _db, HashWrapper _key, boolean _local ) { db = _db; key = _key; short_key = new ShortHash( key.getBytes()); try{ if ( db.getAdapter() != null ){ adapter_key = db.getAdapter().keyCreated( key, _local ); if ( adapter_key != null ){ diversification_state = adapter_key.getDiversificationType(); } } }catch( Throwable e ){ Debug.printStackTrace(e); } } protected Map createLinkedMap() { return( new LinkedHashMap(1, 0.75f, true )); } protected HashWrapper getKey() { return( key ); } protected ShortHash getShortKey() { return( short_key ); } protected void updateLocalContact( DHTTransportContact contact ) { // pull out all the local values, reset the originator and then // re-add them if ( direct_originator_map_may_be_null == null ){ return; } List changed = new ArrayList(); Iterator it = direct_originator_map_may_be_null.values().iterator(); while( it.hasNext()){ DHTDBValueImpl value = it.next(); if ( value.isLocal()){ value.setOriginatorAndSender( contact ); changed.add( value ); direct_data_size -= value.getValue().length; local_size -= value.getValue().length; it.remove(); informDeleted( value ); } } for (int i=0;ivalue mapping being held multiple times when sent by different caches // c) prevents multiple senders from same IP filling up, but supports multiple machines behind NAT // d) optimises responses. // Note that we can't trust the originator value in cache forwards, we therefore // need to prevent someone from overwriting a valid originator->value1 mapping // with an invalid originator->value2 mapping - that is we can't use uniqueness of // originator // a value can be "volatile" - this means that the cacher can ping the originator // periodically and delete the value if it is dead // the aim here is to // 1) reduce ability for single contacts to spam the key while supporting up to 8 // contacts on a given IP (assuming NAT is being used) // 2) stop one contact deleting or overwriting another contact's entry // 3) support garbage collection for contacts that don't delete entries on exit // TODO: we should enforce a max-values-per-sender restriction to stop a sender from spamming // lots of keys - however, for a small DHT we need to be careful protected void add( DHTDBValueImpl new_value ) { // don't replace a closer cache value with a further away one. in particular // we have to avoid the case where the original publisher of a key happens to // be close to it and be asked by another node to cache it! DHTTransportContact originator = new_value.getOriginator(); DHTTransportContact sender = new_value.getSender(); HashWrapper originator_id = new HashWrapper( originator.getID()); boolean direct = Arrays.equals( originator.getID(), sender.getID()); if ( direct ){ // direct contact from the originator is straight forward addDirectValue( originator_id, new_value ); // remove any indirect values we might already have for this Iterator> it = indirect_originator_value_map.entrySet().iterator(); List to_remove = new ArrayList(); while( it.hasNext()){ Map.Entry entry = it.next(); HashWrapper existing_key = entry.getKey(); DHTDBValueImpl existing_value = entry.getValue(); if ( Arrays.equals( existing_value.getOriginator().getID(), originator.getID())){ to_remove.add( existing_key ); } } for (int i=0;i res = new ArrayList(); Set duplicate_check = new HashSet(); Map[] maps = new Map[]{ direct_originator_map_may_be_null, indirect_originator_value_map }; for (int i=0;i map = maps[i]; if ( map == null ){ continue; } List keys_used = new ArrayList(); Iterator> it = map.entrySet().iterator(); while( it.hasNext() && ( max==0 || res.size()< max )){ Map.Entry entry = it.next(); HashWrapper entry_key = entry.getKey(); DHTDBValueImpl entry_value = entry.getValue(); HashWrapper x = new HashWrapper( entry_value.getValue()); if ( duplicate_check.contains( x )){ continue; } duplicate_check.add( x ); // zero length values imply deleted values so don't return them if ( entry_value.getValue().length > 0 ){ res.add( entry_value ); keys_used.add( entry_key ); } } // now update the access order so values get cycled for (int j=0;j getValues() { return( new valueIterator( true, true )); } protected Iterator getDirectValues() { return( new valueIterator( true, false )); } protected Iterator getIndirectValues() { return( new valueIterator( false, true )); } protected byte getDiversificationType() { return( diversification_state ); } protected void addDirectValue( HashWrapper value_key, DHTDBValueImpl value ) { if ( direct_originator_map_may_be_null == null ){ direct_originator_map_may_be_null = createLinkedMap(); } DHTDBValueImpl old = (DHTDBValueImpl)direct_originator_map_may_be_null.put( value_key, value ); if ( old != null ){ int old_version = old.getVersion(); int new_version = value.getVersion(); if ( old_version != -1 && new_version != -1 && old_version >= new_version ){ if ( old_version == new_version ){ if ( TRACE_ADDS ){ System.out.println( "addDirect[reset]:" + old.getString() + "/" + value.getString()); } old.reset(); // update store time as this means we don't need to republish // as someone else has just done it }else{ // its important to ignore old versions as a peer's increasing version sequence may // have been reset and if this is the case we want the "future" values to timeout if ( TRACE_ADDS ){ System.out.println( "addDirect[ignore]:" + old.getString() + "/" + value.getString()); } } // put the old value back! direct_originator_map_may_be_null.put( value_key, old ); return; } if ( TRACE_ADDS ){ System.out.println( "addDirect:" + old.getString() + "/" + value.getString()); } direct_data_size -= old.getValue().length; if ( old.isLocal()){ local_size -= old.getValue().length; } }else{ if ( TRACE_ADDS ){ System.out.println( "addDirect:[new]" + value.getString()); } } direct_data_size += value.getValue().length; if ( value.isLocal()){ local_size += value.getValue().length; } if ( old == null ){ informAdded( value ); }else{ informUpdated( old, value ); } } protected DHTDBValueImpl removeDirectValue( HashWrapper value_key ) { if ( direct_originator_map_may_be_null == null ){ return( null ); } DHTDBValueImpl old = (DHTDBValueImpl)direct_originator_map_may_be_null.remove( value_key ); if ( old != null ){ direct_data_size -= old.getValue().length; if ( old.isLocal()){ local_size -= old.getValue().length; } informDeleted( old ); } return( old ); } protected void addIndirectValue( HashWrapper value_key, DHTDBValueImpl value ) { DHTDBValueImpl old = (DHTDBValueImpl)indirect_originator_value_map.put( value_key, value ); if ( old != null ){ // discard updates that are older than current value int old_version = old.getVersion(); int new_version = value.getVersion(); if ( old_version != -1 && new_version != -1 && old_version >= new_version ){ if ( old_version == new_version ){ if ( TRACE_ADDS ){ System.out.println( "addIndirect[reset]:" + old.getString() + "/" + value.getString()); } old.reset(); // update store time as this means we don't need to republish // as someone else has just done it }else{ if ( TRACE_ADDS ){ System.out.println( "addIndirect[ignore]:" + old.getString() + "/" + value.getString()); } } // put the old value back! indirect_originator_value_map.put( value_key, old ); return; } // vague backwards compatability - if the creation date of the "new" value is significantly // less than the old then we ignore it (given that creation date is adjusted for time-skew you can // see the problem with this approach...) if ( old_version == -1 || new_version == -1 ){ if ( old.getCreationTime() > value.getCreationTime() + 30000 ){ if ( TRACE_ADDS ){ System.out.println( "backward compat: ignoring store: " + old.getString() + "/" + value.getString()); } // put the old value back! indirect_originator_value_map.put( value_key, old ); return; } } if ( TRACE_ADDS ){ System.out.println( "addIndirect:" + old.getString() + "/" + value.getString()); } indirect_data_size -= old.getValue().length; if ( old.isLocal()){ local_size -= old.getValue().length; } }else{ if ( TRACE_ADDS ){ System.out.println( "addIndirect:[new]" + value.getString()); } } indirect_data_size += value.getValue().length; if ( value.isLocal()){ local_size += value.getValue().length; } if ( old == null ){ informAdded( value ); }else{ informUpdated( old, value ); } } protected DHTDBValueImpl removeIndirectValue( HashWrapper value_key ) { DHTDBValueImpl old = (DHTDBValueImpl)indirect_originator_value_map.remove( value_key ); if ( old != null ){ indirect_data_size -= old.getValue().length; if ( old.isLocal()){ local_size -= old.getValue().length; } informDeleted( old ); } return( old ); } protected void destroy() { try{ if ( adapter_key != null ){ Iterator it = getValues(); while( it.hasNext()){ it.next(); it.remove(); } db.getAdapter().keyDeleted( adapter_key ); } }catch( Throwable e ){ Debug.printStackTrace(e); } } private void informDeleted( DHTDBValueImpl value ) { boolean direct = (!value.isLocal())&& Arrays.equals( value.getOriginator().getID(), value.getSender().getID()); if ( direct ){ removeFromBloom( value ); } try{ if ( adapter_key != null ){ db.getAdapter().valueDeleted( adapter_key, value ); diversification_state = adapter_key.getDiversificationType(); } }catch( Throwable e ){ Debug.printStackTrace(e); } } private void informAdded( DHTDBValueImpl value ) { boolean direct = (!value.isLocal()) && Arrays.equals( value.getOriginator().getID(), value.getSender().getID()); if ( direct ){ addToBloom( value ); } try{ if ( adapter_key != null ){ db.getAdapter().valueAdded( adapter_key, value ); diversification_state = adapter_key.getDiversificationType(); } }catch( Throwable e ){ Debug.printStackTrace(e); } } private void informUpdated( DHTDBValueImpl old_value, DHTDBValueImpl new_value) { boolean old_direct = (!old_value.isLocal()) && Arrays.equals( old_value.getOriginator().getID(), old_value.getSender().getID()); boolean new_direct = (!new_value.isLocal()) && Arrays.equals( new_value.getOriginator().getID(), new_value.getSender().getID()); if ( new_direct && !old_direct ){ addToBloom( new_value ); } try{ if ( adapter_key != null ){ db.getAdapter().valueUpdated( adapter_key, old_value, new_value ); diversification_state = adapter_key.getDiversificationType(); } }catch( Throwable e ){ Debug.printStackTrace(e); } } private void informRead( DHTTransportContact contact ){ try{ if ( adapter_key != null && contact != null ){ db.getAdapter().keyRead( adapter_key, contact ); diversification_state = adapter_key.getDiversificationType(); } }catch( Throwable e ){ Debug.printStackTrace(e); } } protected void addToBloom( DHTDBValueImpl value ) { // we don't check for flooding on indirect stores as this could be used to force a // direct store to be bounced (flood a node with indirect stores before the direct // store occurs) DHTTransportContact originator = value.getOriginator(); byte[] address_bytes = originator.getAddress().getAddress().getAddress(); // System.out.println( "addToBloom: existing=" + ip_count_bloom_filter ); if ( ip_count_bloom_filter == null ){ ip_count_bloom_filter = address_bytes; return; } BloomFilter filter; if ( ip_count_bloom_filter instanceof byte[] ){ byte[] existing_address = (byte[])ip_count_bloom_filter; ip_count_bloom_filter = filter = BloomFilterFactory.createAddRemove4Bit( IP_COUNT_BLOOM_SIZE_INCREASE_CHUNK ); filter.add( existing_address ); }else{ filter = (BloomFilter)ip_count_bloom_filter; } int hit_count = filter.add( address_bytes ); if ( DHTLog.LOCAL_BLOOM_TRACE ){ System.out.println( "direct local add from " + originator.getAddress() + ", hit count = " + hit_count ); } // allow up to 10% bloom filter utilisation if ( filter.getSize() / filter.getEntryCount() < 10 ){ rebuildIPBloomFilter( true ); } if ( hit_count >= 15 ){ db.banContact( originator, "local flood on '" + DHTLog.getFullString( key.getBytes()) + "'" ); } } protected void removeFromBloom( DHTDBValueImpl value ) { DHTTransportContact originator = value.getOriginator(); if ( ip_count_bloom_filter == null ){ return; } byte[] address_bytes = originator.getAddress().getAddress().getAddress(); if ( ip_count_bloom_filter instanceof byte[] ){ byte[] existing_address = (byte[])ip_count_bloom_filter; if ( Arrays.equals( address_bytes, existing_address )){ ip_count_bloom_filter = null; } return; } BloomFilter filter = (BloomFilter)ip_count_bloom_filter; int hit_count = filter.remove( address_bytes ); if ( DHTLog.LOCAL_BLOOM_TRACE ){ System.out.println( "direct local remove from " + originator.getAddress() + ", hit count = " + hit_count ); } } protected void rebuildIPBloomFilter( boolean increase_size ) { BloomFilter new_filter; int old_size; if ( ip_count_bloom_filter instanceof BloomFilter ){ old_size = ((BloomFilter)ip_count_bloom_filter).getSize(); }else{ old_size = IP_COUNT_BLOOM_SIZE_INCREASE_CHUNK; } if ( increase_size ){ new_filter = BloomFilterFactory.createAddRemove4Bit( old_size + IP_COUNT_BLOOM_SIZE_INCREASE_CHUNK ); }else{ new_filter = BloomFilterFactory.createAddRemove4Bit( old_size ); } try{ // only do flood prevention on direct stores as we can't trust the originator // details for indirect and this can be used to DOS a direct store later Iterator it = getDirectValues(); int max_hits = 0; while( it.hasNext()){ DHTDBValueImpl val = it.next(); if ( !val.isLocal()){ // logger.log( " adding " + val.getOriginator().getAddress()); int hits = new_filter.add( val.getOriginator().getAddress().getAddress().getAddress()); if ( hits > max_hits ){ max_hits = hits; } } } if ( DHTLog.LOCAL_BLOOM_TRACE ){ db.log( "Rebuilt local IP bloom filter, size = " + new_filter.getSize() + ", entries =" + new_filter.getEntryCount()+", max hits = " + max_hits ); } }finally{ ip_count_bloom_filter = new_filter; } } protected void print() { int entries; if ( ip_count_bloom_filter == null ){ entries = 0; }else if ( ip_count_bloom_filter instanceof byte[] ){ entries = 1; }else{ entries = ((BloomFilter)ip_count_bloom_filter).getEntryCount(); } System.out.println( ByteFormatter.encodeString( key.getBytes()) + ": " + "dir=" + (direct_originator_map_may_be_null==null?0:direct_originator_map_may_be_null.size()) + "," + "indir=" + indirect_originator_value_map.size() + "," + "bloom=" + entries ); System.out.println( " indirect" ); Iterator it = getIndirectValues(); while( it.hasNext()){ DHTDBValueImpl val = (DHTDBValueImpl)it.next(); System.out.println( " " + val.getOriginator().getString() + ": " + new String( val.getValue())); } } protected class valueIterator implements Iterator { private List> maps = new ArrayList>(2); private int map_index = 0; private Map map; private Iterator it; private DHTDBValueImpl value; protected valueIterator( boolean direct, boolean indirect ) { if ( direct && direct_originator_map_may_be_null != null ){ maps.add( direct_originator_map_may_be_null ); } if ( indirect ){ maps.add( indirect_originator_value_map ); } } public boolean hasNext() { if ( it != null && it.hasNext()){ return( true ); } while( map_index < maps.size() ){ map = maps.get(map_index++); it = map.values().iterator(); if ( it.hasNext()){ return( true ); } } return( false ); } public DHTDBValueImpl next() { if ( hasNext()){ value = (DHTDBValueImpl)it.next(); return( value ); } throw( new NoSuchElementException()); } public void remove() { if ( it == null ){ throw( new IllegalStateException()); } if ( value != null ){ if( value.isLocal()){ local_size -= value.getValue().length; } if ( map == indirect_originator_value_map ){ indirect_data_size -= value.getValue().length; }else{ direct_data_size -= value.getValue().length; } // remove before informing it.remove(); informDeleted( value ); value = null; }else{ throw( new IllegalStateException()); } } } public static class ShortHash { private byte[] bytes; private int hash_code; protected ShortHash( byte[] _bytes ) { bytes = _bytes; int hc = 0; for (int i=0; i stored_values = new HashMap(); private Map stored_values_prefix_map = new HashMap(); private DHTControl control; private DHTStorageAdapter adapter; private DHTRouter router; private DHTTransportContact local_contact; private DHTLogger logger; private static final long MAX_TOTAL_SIZE = 4*1024*1024; private int total_size; private int total_values; private int total_keys; private int total_local_keys; private boolean force_original_republish; private IpFilter ip_filter = IpFilterManagerFactory.getSingleton().getIPFilter(); private AEMonitor this_mon = new AEMonitor( "DHTDB" ); private static final boolean DEBUG_SURVEY = false; private static final boolean SURVEY_ONLY_RF_KEYS = true; private static final int SURVEY_PERIOD = DEBUG_SURVEY?1*60*1000:15*60*1000; private static final int SURVEY_STATE_INACT_TIMEOUT = DEBUG_SURVEY?5*60*1000:60*60*1000; private static final int SURVEY_STATE_MAX_LIFE_TIMEOUT = 3*60*60*1000 + 30*60*1000; private static final int SURVEY_STATE_MAX_LIFE_RAND = 1*60*60*1000; private static final int MAX_SURVEY_SIZE = 100; private static final int MAX_SURVEY_STATE_SIZE = 150; private final boolean survey_enabled; private volatile boolean survey_in_progress; private Map survey_mapping_times = new HashMap(); private Map survey_state = new LinkedHashMap(MAX_SURVEY_STATE_SIZE,0.75f,true) { protected boolean removeEldestEntry( Map.Entry eldest) { return size() > MAX_SURVEY_STATE_SIZE; } }; public DHTDBImpl( DHTStorageAdapter _adapter, int _original_republish_interval, int _cache_republish_interval, byte _protocol_version, DHTLogger _logger ) { adapter = _adapter==null?null:new adapterFacade( _adapter ); original_republish_interval = _original_republish_interval; cache_republish_interval = _cache_republish_interval; logger = _logger; survey_enabled = _protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL3 && ( adapter == null || adapter.getNetwork() == DHT.NW_CVS || FeatureAvailability.isDHTRepV2Enabled()); if ( ENABLE_PRECIOUS_STUFF ){ SimpleTimer.addPeriodicEvent( "DHTDB:precious", PRECIOUS_CHECK_INTERVAL/4, true, // absolute, we don't want effective time changes (computer suspend/resume) to shift these new TimerEventPerformer() { public void perform( TimerEvent event ) { checkPreciousStuff(); } }); } SimpleTimer.addPeriodicEvent( "DHTDB:op", original_republish_interval, true, // absolute, we don't want effective time changes (computer suspend/resume) to shift these new TimerEventPerformer() { public void perform( TimerEvent event ) { logger.log( "Republish of original mappings starts" ); long start = SystemTime.getCurrentTime(); int stats = republishOriginalMappings(); long end = SystemTime.getCurrentTime(); logger.log( "Republish of original mappings completed in " + (end-start) + ": " + "values = " + stats ); } }); // random skew here so that cache refresh isn't very synchronised, as the optimisations // regarding non-republising benefit from this SimpleTimer.addPeriodicEvent( "DHTDB:cp", cache_republish_interval + 10000 - (int)(Math.random()*20000), true, // absolute, we don't want effective time changes (computer suspend/resume) to shift these new TimerEventPerformer() { public void perform( TimerEvent event ) { logger.log( "Republish of cached mappings starts" ); long start = SystemTime.getCurrentTime(); int[] stats = republishCachedMappings(); long end = SystemTime.getCurrentTime(); logger.log( "Republish of cached mappings completed in " + (end-start) + ": " + "values = " + stats[0] + ", keys = " + stats[1] + ", ops = " + stats[2]); if ( force_original_republish ){ force_original_republish = false; logger.log( "Force republish of original mappings due to router change starts" ); start = SystemTime.getCurrentTime(); int stats2 = republishOriginalMappings(); end = SystemTime.getCurrentTime(); logger.log( "Force republish of original mappings due to router change completed in " + (end-start) + ": " + "values = " + stats2 ); } } }); SimpleTimer.addPeriodicEvent( "DHTDB:bloom", IP_BLOOM_FILTER_REBUILD_PERIOD, new TimerEventPerformer() { public void perform( TimerEvent event ) { try{ this_mon.enter(); rebuildIPBloomFilter( false ); }finally{ this_mon.exit(); } } }); if ( survey_enabled ){ SimpleTimer.addPeriodicEvent( "DHTDB:survey", SURVEY_PERIOD, true, new TimerEventPerformer() { public void perform( TimerEvent event ) { survey(); } }); } } public void setControl( DHTControl _control ) { control = _control; // trigger an "original value republish" if router has changed force_original_republish = router != null; router = control.getRouter(); local_contact = control.getTransport().getLocalContact(); // our ID has changed - amend the originator of all our values try{ this_mon.enter(); survey_state.clear(); Iterator it = stored_values.values().iterator(); while( it.hasNext()){ DHTDBMapping mapping = it.next(); mapping.updateLocalContact( local_contact ); } }finally{ this_mon.exit(); } } public DHTDBValue store( HashWrapper key, byte[] value, byte flags, byte life_hours, byte replication_control ) { // local store if ( (flags & DHT.FLAG_PUT_AND_FORGET ) == 0 ){ if (( flags & DHT.FLAG_OBFUSCATE_LOOKUP ) != 0 ){ Debug.out( "Obfuscated puts without 'put-and-forget' are not supported as original-republishing of them is not implemented" ); } if ( life_hours > 0 ){ if ( life_hours*60*60*1000 < original_republish_interval ){ Debug.out( "Don't put persistent values with a lifetime less than republish period - lifetime over-ridden" ); life_hours = 0; } } try{ this_mon.enter(); total_local_keys++; // don't police max check for locally stored data // only that received DHTDBMapping mapping = (DHTDBMapping)stored_values.get( key ); if ( mapping == null ){ mapping = new DHTDBMapping( this, key, true ); stored_values.put( key, mapping ); addToPrefixMap( mapping ); } DHTDBValueImpl res = new DHTDBValueImpl( SystemTime.getCurrentTime(), value, getNextValueVersion(), local_contact, local_contact, true, flags, life_hours, replication_control ); mapping.add( res ); return( res ); }finally{ this_mon.exit(); } }else{ DHTDBValueImpl res = new DHTDBValueImpl( SystemTime.getCurrentTime(), value, getNextValueVersion(), local_contact, local_contact, true, flags, life_hours, replication_control ); return( res ); } } /* private long store_ops; private long store_ops_bad1; private long store_ops_bad2; private void logStoreOps() { System.out.println( "sops (" + control.getTransport().getNetwork() + ")=" + store_ops + ",bad1=" + store_ops_bad1 + ",bad2=" + store_ops_bad2 ); } */ public byte store( DHTTransportContact sender, HashWrapper key, DHTTransportValue[] values ) { // allow 4 bytes per value entry to deal with overhead (prolly should be more but we're really // trying to deal with 0-length value stores) if ( total_size + ( total_values*4 ) > MAX_TOTAL_SIZE ){ DHTLog.log( "Not storing " + DHTLog.getString2(key.getHash()) + " as maximum storage limit exceeded" ); return( DHT.DT_SIZE ); } // logStoreOps(); try{ this_mon.enter(); checkCacheExpiration( false ); DHTDBMapping mapping = (DHTDBMapping)stored_values.get( key ); if ( mapping == null ){ mapping = new DHTDBMapping( this, key, false ); stored_values.put( key, mapping ); addToPrefixMap( mapping ); } // we carry on an update as its ok to replace existing entries // even if diversified for (int i=0;i all byte flags, boolean external_request ) { try{ this_mon.enter(); checkCacheExpiration( false ); final DHTDBMapping mapping = (DHTDBMapping)stored_values.get(key); if ( mapping == null ){ return( null ); } if ( external_request ){ mapping.addHit(); } final DHTDBValue[] values = mapping.get( reader, max_values, flags ); return( new DHTDBLookupResult() { public DHTDBValue[] getValues() { return( values ); } public byte getDiversificationType() { return( mapping.getDiversificationType()); } }); }finally{ this_mon.exit(); } } public DHTDBValue get( HashWrapper key ) { // local remove try{ this_mon.enter(); DHTDBMapping mapping = (DHTDBMapping)stored_values.get( key ); if ( mapping != null ){ return( mapping.get( local_contact )); } return( null ); }finally{ this_mon.exit(); } } public boolean hasKey( HashWrapper key ) { try{ this_mon.enter(); return( stored_values.containsKey( key )); }finally{ this_mon.exit(); } } public DHTDBValue remove( DHTTransportContact originator, HashWrapper key ) { // local remove try{ this_mon.enter(); DHTDBMapping mapping = (DHTDBMapping)stored_values.get( key ); if ( mapping != null ){ DHTDBValueImpl res = mapping.remove( originator ); if ( res != null ){ total_local_keys--; return( res.getValueForDeletion( getNextValueVersion())); } return( null ); } return( null ); }finally{ this_mon.exit(); } } public DHTStorageBlock keyBlockRequest( DHTTransportContact direct_sender, byte[] request, byte[] signature ) { if ( adapter == null ){ return( null ); } // for block requests sent to us (as opposed to being returned from other operations) // make sure that the key is close enough to us if ( direct_sender != null ){ byte[] key = adapter.getKeyForKeyBlock( request ); List closest_contacts = control.getClosestKContactsList( key, true ); boolean process_it = false; for (int i=0;i it = stored_values.values().iterator(); while( it.hasNext()){ DHTDBMapping mapping = it.next(); res[DHTDBStats.VD_VALUE_COUNT] += mapping.getValueCount(); res[DHTDBStats.VD_LOCAL_SIZE] += mapping.getLocalSize(); res[DHTDBStats.VD_DIRECT_SIZE] += mapping.getDirectSize(); res[DHTDBStats.VD_INDIRECT_SIZE] += mapping.getIndirectSize(); int dt = mapping.getDiversificationType(); if ( dt == DHT.DT_FREQUENCY ){ res[DHTDBStats.VD_DIV_FREQ]++; }else if ( dt == DHT.DT_SIZE ){ res[DHTDBStats.VD_DIV_SIZE]++; /* Iterator it2 = mapping.getIndirectValues(); System.out.println( "values=" + mapping.getValueCount()); while( it2.hasNext()){ DHTDBValueImpl val = it2.next(); System.out.println( new String( val.getValue()) + " - " + val.getOriginator().getAddress()); } */ } } return( res ); }finally{ this_mon.exit(); } } public int getKeyBlockCount() { if ( adapter == null ){ return( 0 ); } return( adapter.getDirectKeyBlocks().length ); } public Iterator getKeys() { try{ this_mon.enter(); return( new ArrayList( stored_values.keySet()).iterator()); }finally{ this_mon.exit(); } } protected int republishOriginalMappings() { int values_published = 0; Map> republish = new HashMap>(); try{ this_mon.enter(); Iterator> it = stored_values.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = it.next(); HashWrapper key = (HashWrapper)entry.getKey(); DHTDBMapping mapping = (DHTDBMapping)entry.getValue(); Iterator it2 = mapping.getValues(); List values = new ArrayList(); while( it2.hasNext()){ DHTDBValueImpl value = it2.next(); if ( value != null && value.isLocal()){ // we're republising the data, reset the creation time value.setCreationTime(); values.add( value ); } } if ( values.size() > 0 ){ republish.put( key, values ); } } }finally{ this_mon.exit(); } Iterator>> it = republish.entrySet().iterator(); while( it.hasNext()){ Map.Entry> entry = it.next(); HashWrapper key = (HashWrapper)entry.getKey(); List values = entry.getValue(); // no point in worry about multi-value puts here as it is extremely unlikely that // > 1 value will locally stored, or > 1 value will go to the same contact for (int i=0;i> republish = new HashMap>(); List republish_via_survey = new ArrayList(); long now = System.currentTimeMillis(); try{ this_mon.enter(); checkCacheExpiration( true ); Iterator> it = stored_values.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = it.next(); HashWrapper key = entry.getKey(); DHTDBMapping mapping = entry.getValue(); // assume that if we've diversified then the other k-1 locations are under similar // stress and will have done likewise - no point in republishing cache values to them // New nodes joining will have had stuff forwarded to them regardless of diversification // status if ( mapping.getDiversificationType() != DHT.DT_NONE ){ continue; } Iterator it2 = mapping.getValues(); boolean all_rf_values = it2.hasNext(); List values = new ArrayList(); while( it2.hasNext()){ DHTDBValueImpl value = it2.next(); if ( !value.isLocal()){ if ( value.getReplicationFactor() == DHT.REP_FACT_DEFAULT ){ all_rf_values = false; } // if this value was stored < period ago then we assume that it was // also stored to the other k-1 locations at the same time and therefore // we don't need to re-store it if ( now < value.getStoreTime()){ // deal with clock changes value.setStoreTime( now ); }else if ( now - value.getStoreTime() <= cache_republish_interval ){ // System.out.println( "skipping store" ); }else{ values.add( value ); } } } if ( all_rf_values ){ // if surveying is disabled then we swallow values here to prevent them // from being replicated using the existing technique and muddying the waters values.clear(); // handled by the survey process republish_via_survey.add( mapping ); } if ( values.size() > 0 ){ republish.put( key, values ); } } }finally{ this_mon.exit(); } if ( republish_via_survey.size() > 0 ){ // we still check for being too far away here List stop_caching = new ArrayList(); for ( DHTDBMapping mapping: republish_via_survey ){ HashWrapper key = mapping.getKey(); byte[] lookup_id = key.getHash(); List contacts = control.getClosestKContactsList( lookup_id, false ); // if we are no longer one of the K closest contacts then we shouldn't // cache the value boolean keep_caching = false; for (int j=0;j 0 ){ try{ this_mon.enter(); for (int i=0;i anti_spoof_done = new HashSet(); if ( republish.size() > 0 ){ // System.out.println( "cache replublish" ); // The approach is to refresh all leaves in the smallest subtree, thus populating the tree with // sufficient information to directly know which nodes to republish the values // to. // However, I'm going to rely on the "refresh idle leaves" logic above // (that's required to keep the DHT alive in general) to ensure that all // k-buckets are reasonably up-to-date Iterator>> it1 = republish.entrySet().iterator(); List stop_caching = new ArrayList(); // build a map of contact -> list of keys to republish Map contact_map = new HashMap(); while( it1.hasNext()){ Map.Entry> entry = it1.next(); HashWrapper key = entry.getKey(); byte[] lookup_id = key.getHash(); // just use the closest contacts - if some have failed then they'll // get flushed out by this operation. Grabbing just the live ones // is a bad idea as failures may rack up against the live ones due // to network problems and kill them, leaving the dead ones! List contacts = control.getClosestKContactsList( lookup_id, false ); // if we are no longer one of the K closest contacts then we shouldn't // cache the value boolean keep_caching = false; for (int j=0;j()}; contact_map.put( new HashWrapper(contact.getID()), data ); } ((List)data[1]).add( key ); } } Iterator it2 = contact_map.values().iterator(); while( it2.hasNext()){ final Object[] data = it2.next(); final DHTTransportContact contact = (DHTTransportContact)data[0]; // move to anti-spoof on cache forwards - gotta do a find-node first // to get the random id final AESemaphore sem = new AESemaphore( "DHTDB:cacheForward" ); contact.sendFindNode( new DHTTransportReplyHandlerAdapter() { public void findNodeReply( DHTTransportContact _contact, DHTTransportContact[] _contacts ) { anti_spoof_done.add( _contact ); try{ // System.out.println( "cacheForward: pre-store findNode OK" ); List keys = (List)data[1]; byte[][] store_keys = new byte[keys.size()][]; DHTTransportValue[][] store_values = new DHTTransportValue[store_keys.length][]; keys_published[0] += store_keys.length; for (int i=0;i values = republish.get( wrapper ); store_values[i] = new DHTTransportValue[values.size()]; values_published[0] += store_values[i].length; for (int j=0;j contacts = new ArrayList(); contacts.add( contact ); republish_ops[0]++; control.putDirectEncodedKeys( store_keys, "Republish cache", store_values, contacts ); }finally{ sem.release(); } } public void failed( DHTTransportContact _contact, Throwable _error ) { try{ // System.out.println( "cacheForward: pre-store findNode Failed" ); DHTLog.log( "cacheForward: pre-store findNode failed " + DHTLog.getString( _contact ) + " -> failed: " + _error.getMessage()); router.contactDead( _contact.getID(), false); }finally{ sem.release(); } } }, contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20] ); sem.reserve(); } try{ this_mon.enter(); for (int i=0;i 0 ){ for (int i=0;i= DHTTransportUDP.PROTOCOL_VERSION_BLOCK_KEYS ){ final Runnable task = new Runnable() { public void run() { contact.sendKeyBlock( new DHTTransportReplyHandlerAdapter() { public void keyBlockReply( DHTTransportContact _contact ) { DHTLog.log( "key block forward ok " + DHTLog.getString( _contact )); key_block.sentTo( _contact ); } public void failed( DHTTransportContact _contact, Throwable _error ) { DHTLog.log( "key block forward failed " + DHTLog.getString( _contact ) + " -> failed: " + _error.getMessage()); } }, key_block.getRequest(), key_block.getCertificate()); } }; if ( anti_spoof_done.contains( contact )){ task.run(); }else{ contact.sendFindNode( new DHTTransportReplyHandlerAdapter() { public void findNodeReply( DHTTransportContact contact, DHTTransportContact[] contacts ) { task.run(); } public void failed( DHTTransportContact _contact, Throwable _error ) { // System.out.println( "nodeAdded: pre-store findNode Failed" ); DHTLog.log( "pre-kb findNode failed " + DHTLog.getString( _contact ) + " -> failed: " + _error.getMessage()); router.contactDead( _contact.getID(), false); } }, contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20] ); } } } } } return( new int[]{ values_published[0], keys_published[0], republish_ops[0] }); } protected void checkCacheExpiration( boolean force ) { long now = SystemTime.getCurrentTime(); if ( !force ){ long elapsed = now - last_cache_expiry_check; if ( elapsed > 0 && elapsed < MIN_CACHE_EXPIRY_CHECK_INTERVAL ){ return; } } try{ this_mon.enter(); last_cache_expiry_check = now; Iterator it = stored_values.values().iterator(); while( it.hasNext()){ DHTDBMapping mapping = it.next(); if ( mapping.getValueCount() == 0 ){ it.remove(); removeFromPrefixMap( mapping ); mapping.destroy(); }else{ Iterator it2 = mapping.getValues(); while( it2.hasNext()){ DHTDBValueImpl value = it2.next(); if ( !value.isLocal()){ // distance 1 = initial store location. We use the initial creation date // when deciding whether or not to remove this, plus a bit, as the // original publisher is supposed to republish these int life_hours = value.getLifeTimeHours(); int max_age; if ( life_hours < 1 ){ max_age = original_republish_interval; }else{ max_age = life_hours * 60*60*1000; if ( max_age > MAX_VALUE_LIFETIME ){ max_age = MAX_VALUE_LIFETIME; } } int grace; if (( value.getFlags() & DHT.FLAG_PUT_AND_FORGET ) != 0 ){ grace = 0; }else{ // scale the grace period for short lifetimes grace = Math.min( ORIGINAL_REPUBLISH_INTERVAL_GRACE, max_age/4 ); } if ( now > value.getCreationTime() + max_age + grace ){ DHTLog.log( "removing cache entry (" + value.getString() + ")" ); it2.remove(); } } } } } }finally{ this_mon.exit(); } } protected void addToPrefixMap( DHTDBMapping mapping ) { DHTDBMapping.ShortHash key = mapping.getShortKey(); DHTDBMapping existing = stored_values_prefix_map.get( key ); // possible to have clashes, be consistent in which one we use to avoid // confusing other nodes if ( existing != null ){ byte[] existing_full = existing.getKey().getBytes(); byte[] new_full = mapping.getKey().getBytes(); if ( control.computeAndCompareDistances( existing_full, new_full, local_contact.getID()) < 0 ){ return; } } stored_values_prefix_map.put( key, mapping ); if ( stored_values_prefix_map.size() > stored_values.size()){ Debug.out( "inconsistent" ); } } protected void removeFromPrefixMap( DHTDBMapping mapping ) { DHTDBMapping.ShortHash key = mapping.getShortKey(); DHTDBMapping existing = stored_values_prefix_map.get( key ); if ( existing == mapping ){ stored_values_prefix_map.remove( key ); } } protected void checkPreciousStuff() { long now = SystemTime.getCurrentTime(); Map> republish = new HashMap>(); try{ this_mon.enter(); Iterator> it = stored_values.entrySet().iterator(); while( it.hasNext()){ Map.Entry entry = it.next(); HashWrapper key = entry.getKey(); DHTDBMapping mapping = entry.getValue(); Iterator it2 = mapping.getValues(); List values = new ArrayList(); while( it2.hasNext()){ DHTDBValueImpl value = it2.next(); if ( value.isLocal()){ if (( value.getFlags() | DHT.FLAG_PRECIOUS ) != 0 ){ if ( now - value.getCreationTime() > PRECIOUS_CHECK_INTERVAL ){ value.setCreationTime(); values.add( value ); } } } } if ( values.size() > 0 ){ republish.put( key, values ); } } }finally{ this_mon.exit(); } Iterator>> it = republish.entrySet().iterator(); while( it.hasNext()){ Map.Entry> entry = it.next(); HashWrapper key = entry.getKey(); List values = entry.getValue(); // no point in worry about multi-value puts here as it is extremely unlikely that // > 1 value will locally stored, or > 1 value will go to the same contact for (int i=0;i contacts = new ArrayList(); private boolean survey_complete; public void found( DHTTransportContact contact, boolean is_closest ) { if ( is_closest ){ synchronized( contacts ){ if ( !survey_complete ){ contacts.add( contact ); } } } } public void complete( boolean timeout ) { boolean requeried = false; try{ int hits = 0; int misses = 0; // find the closest miss to us and recursively search byte[] min_dist = null; byte[] min_id = null; synchronized( contacts ){ for ( DHTTransportContact c: contacts ){ byte[] id = c.getID(); if ( id_map.containsKey( id )){ hits++; }else{ misses++; if ( id_map.size() >= MAX_SURVEY_SIZE ){ log( "Max survery size exceeded" ); break; } id_map.put( id, c ); byte[] distance = control.computeDistance( my_id, id ); if ( min_dist == null || control.compareDistances( distance, min_dist ) < 0 ){ min_dist = distance; min_id = id; } } } contacts.clear(); } // if significant misses then re-query if ( misses > 0 && misses*100/(hits+misses) >= 25 && id_map.size()< MAX_SURVEY_SIZE ){ if ( requery_count[0]++ < 5 ){ if ( DEBUG_SURVEY ){ System.out.println( "requery at " + ByteFormatter.encodeString( min_id )); } // don't need to obscure here as its a node-id control.lookupEncoded( min_id, "Neighbourhood survey: level=" + requery_count[0], 0, true, this ); requeried = true; }else{ if ( DEBUG_SURVEY ){ System.out.println( "requery limit exceeded" ); } } }else{ if ( DEBUG_SURVEY ){ System.out.println( "super-neighbourhood=" + id_map.size() + " (hits=" + hits + ", misses=" + misses + ", level=" + requery_count[0] + ")" ); } } }finally{ if ( !requeried ){ synchronized( contacts ){ survey_complete = true; } if ( DEBUG_SURVEY ){ System.out.println( "survey complete: nodes=" + id_map.size()); } processSurvey( my_id, applicable_keys, id_map ); processing[0] = true; } } } }); }catch( Throwable e ){ if ( !processing[0] ){ logger.log( "Survey complete - no applicable nodes" ); survey_in_progress = false; } } } protected void processSurvey( byte[] survey_my_id, List applicable_keys, ByteArrayHashMap survey ) { boolean went_async = false; try{ byte[][] node_ids = new byte[survey.size()][]; int pos = 0; for ( byte[] id: survey.keys()){ node_ids[pos++] = id; } ByteArrayHashMap> value_map = new ByteArrayHashMap>(); Map>> request_map = new HashMap>>(); Map> mapping_to_node_map = new HashMap>(); int max_nodes = Math.min( node_ids.length, router.getK()); try{ this_mon.enter(); Iterator it = applicable_keys.iterator(); int value_count = 0; while( it.hasNext()){ DHTDBMapping mapping = stored_values.get( it.next()); if ( mapping == null ){ continue; } value_count++; final byte[] key = mapping.getKey().getBytes(); // find closest nodes to this key in order to asses availability Arrays.sort( node_ids, new Comparator() { public int compare( byte[] o1, byte[] o2 ) { return( control.computeAndCompareDistances( o1, o2, key )); } }); boolean found_myself = false; for ( int i=0;i node_list = new ArrayList(max_nodes); mapping_to_node_map.put( mapping, node_list ); for ( int i=0;i list = value_map.get( id ); if ( list == null ){ list = new ArrayList(); value_map.put( id, list ); } list.add( mapping ); node_list.add( survey.get( id )); } } if ( DEBUG_SURVEY ){ System.out.println( "Total values: " + value_count ); } // build a list of requests to send to nodes to check their replicas for ( byte[] id: node_ids ){ final int MAX_PREFIX_TEST = 3; List all_entries = value_map.remove( id ); ByteArrayHashMap> prefix_map = new ByteArrayHashMap>(); if ( all_entries != null ){ prefix_map.put( new byte[0], all_entries ); for (int i=0;i prefixes = prefix_map.keys(); for ( byte[] prefix: prefixes ){ if ( prefix.length == i ){ List list = prefix_map.get( prefix ); if ( list.size() < 2 ){ continue; } ByteArrayHashMap> temp_map = new ByteArrayHashMap>(); for ( DHTDBMapping mapping: list ){ byte[] key = mapping.getKey().getBytes(); byte[] sub_prefix = new byte[ i+1 ]; System.arraycopy( key, 0, sub_prefix, 0, i+1 ); List entries = temp_map.get( sub_prefix ); if ( entries == null ){ entries = new ArrayList(); temp_map.put( sub_prefix, entries ); } entries.add( mapping ); } List new_list = new ArrayList( list.size()); List temp_keys = temp_map.keys(); for ( byte[] k: temp_keys ){ List entries = temp_map.get( k ); int num = entries.size(); // prefix spread over multiple entries so ignore and just count suffix cost int outer_cost = num * ( QUERY_STORE_REQUEST_ENTRY_SIZE - i ); // include new prefix, one byte prefix len, 2 bytes num-suffixes, then suffixes // yes, this code should be elsewhere, but whatever int inner_cost = i+4 + num * (QUERY_STORE_REQUEST_ENTRY_SIZE - i - 1 ); if ( inner_cost < outer_cost ){ prefix_map.put( k, entries ); }else{ new_list.addAll( entries ); } } if ( new_list.size() == 0 ){ prefix_map.remove( prefix ); }else{ prefix_map.put( prefix, new_list ); } } } } String str = ""; int encoded_size = 1; // header size List prefixes = prefix_map.keys(); for ( byte[] prefix: prefixes ){ encoded_size += 3 + prefix.length; List entries = prefix_map.get( prefix ); encoded_size += ( QUERY_STORE_REQUEST_ENTRY_SIZE - prefix.length ) * entries.size(); str += (str.length()==0?"":", ")+ ByteFormatter.encodeString( prefix ) + "->" + entries.size(); } if ( DEBUG_SURVEY ){ System.out.println( "node " + ByteFormatter.encodeString( id ) + " -> " + (all_entries==null?0:all_entries.size()) + ", encoded=" + encoded_size + ", prefix=" + str ); } if ( prefixes.size() > 0 ){ request_map.put( survey.get( id ), prefix_map ); } } } }finally{ this_mon.exit(); } LinkedList>>> to_do = new LinkedList>>>( request_map.entrySet()); Map replies = new HashMap(); for ( int i=0;i it2 = mapping.getValues(); if ( !it2.hasNext()){ return( false ); } int min_period = Integer.MAX_VALUE; long min_create = Long.MAX_VALUE; while( it2.hasNext()){ DHTDBValueImpl value = it2.next(); byte rep_fact = value.getReplicationFactor(); if ( rep_fact == DHT.REP_FACT_DEFAULT || rep_fact == 0 ){ return( false ); } int hours = value.getReplicationFrequencyHours()&0xff; if ( hours < min_period ){ min_period = hours; } min_create = Math.min( min_create, value.getCreationTime()); } if ( min_period > 0 ){ HashWrapper hw = mapping.getKey(); Long next_time = survey_mapping_times.get( hw ); long now = SystemTime.getMonotonousTime(); if ( next_time != null && next_time > now ){ return( false ); } long period = min_period*60*60*1000; long offset_time = ( SystemTime.getCurrentTime() - min_create ) % period; long rand = RandomUtils.nextInt( 30*60*1000 ) - 15*60*1000; long new_next_time = now - offset_time + period + rand; if ( new_next_time < now + 30*60*1000 ){ new_next_time += period; } if ( DEBUG_SURVEY ){ System.out.println( "allocated next time with value relative " + (new_next_time-now) + ": period=" + period + ", offset=" + offset_time + ", rand=" + rand ); } survey_mapping_times.put( hw, new_next_time ); if ( next_time == null ){ return( false ); } } } return( true ); } protected void doQuery( final byte[] survey_my_id, final int total, final Map> mapping_to_node_map, final LinkedList>>> to_do, final Map replies, DHTTransportContact done_contact, List done_mappings, List done_reply ) { Map.Entry>> entry; synchronized( to_do ){ if ( done_contact != null ){ replies.put( done_contact, new Object[]{ done_mappings, done_reply }); } if ( to_do.size() == 0 ){ if ( replies.size() == total ){ queriesComplete( survey_my_id, mapping_to_node_map, replies ); } return; } entry = to_do.removeFirst(); } DHTTransportContact contact = entry.getKey(); boolean handled = false; try{ if ( contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL3 ){ if ( DEBUG_SURVEY ){ System.out.println( "Hitting " + contact.getString()); } final List mapping_list = new ArrayList(); ByteArrayHashMap> map = entry.getValue(); List prefixes = map.keys(); List encoded = new ArrayList( prefixes.size() ); try{ this_mon.enter(); SurveyContactState contact_state = survey_state.get( new HashWrapper( contact.getID())); for ( byte[] prefix: prefixes ){ int prefix_len = prefix.length; int suffix_len = QUERY_STORE_REQUEST_ENTRY_SIZE - prefix_len; List mappings = map.get( prefix ); List l = new ArrayList( mappings.size()); encoded.add( new Object[]{ prefix, l }); // remove entries that we know the contact already has // and then add them back in in the query-reply. note that we // still need to hit the contact if we end up with no values to // query as need to ascertain liveness. We might want to wait until, // say, 2 subsequent fails before treating contact as dead for ( DHTDBMapping m: mappings ){ if ( contact_state != null ){ if ( contact_state.testMapping(m)){ if ( DEBUG_SURVEY ){ System.out.println( " skipping " + ByteFormatter.encodeString( m.getKey().getBytes()) + " as contact already has" ); } continue; } } mapping_list.add( m ); byte[] k = m.getKey().getBytes(); byte[] suffix = new byte[ suffix_len ]; System.arraycopy( k, prefix_len, suffix, 0, suffix_len ); l.add( suffix ); } } if ( contact.getID().equals( survey_my_id )){ Debug.out( "inconsistent - we shouldn't query ourselves!" ); } contact.sendQueryStore( new DHTTransportReplyHandlerAdapter() { public void queryStoreReply( DHTTransportContact contact, List response ) { try{ if ( DEBUG_SURVEY ){ System.out.println( "response " + response.size()); for (int i=0;i mapping_list = new ArrayList(); ByteArrayHashMap> map = entry.getValue(); List prefixes = map.keys(); for ( byte[] prefix: prefixes ){ mapping_list.addAll( map.get( prefix )); } doQuery( survey_my_id, total, mapping_to_node_map, to_do, replies, contact, mapping_list, null ); } } } protected void queriesComplete( byte[] survey_my_id, Map> mapping_to_node_map, Map replies ) { Map> store_ops = new HashMap>(); try{ this_mon.enter(); if ( !Arrays.equals( survey_my_id, router.getID())){ logger.log( "Survey abandoned - router changed" ); return; } if ( DEBUG_SURVEY ){ System.out.println( "Queries complete (replies=" + replies.size() + ")" ); } Map totals = new HashMap(); for ( Map.Entry entry: replies.entrySet()){ DHTTransportContact contact = entry.getKey(); HashWrapper hw = new HashWrapper( contact.getID()); SurveyContactState contact_state = survey_state.get( hw ); if ( contact_state != null ){ contact_state.updateContactDetails( contact ); }else{ contact_state = new SurveyContactState( contact ); survey_state.put( hw, contact_state ); } contact_state.updateUseTime(); Object[] temp = entry.getValue(); List mappings = (List)temp[0]; List reply = (List)temp[1]; if ( reply == null ){ contact_state.contactFailed(); }else{ contact_state.contactOK(); if ( mappings.size() != reply.size()){ Debug.out( "Inconsistent: mappings=" + mappings.size() + ", reply=" + reply.size()); continue; } Iterator it1 = mappings.iterator(); Iterator it2 = reply.iterator(); while( it1.hasNext()){ DHTDBMapping mapping = it1.next(); byte[] rep = it2.next(); if ( rep == null ){ contact_state.removeMapping( mapping ); }else{ // must match against our short-key mapping for consistency DHTDBMapping mapping_to_check = stored_values_prefix_map.get( mapping.getShortKey()); if ( mapping_to_check == null ){ // deleted }else{ byte[] k = mapping_to_check.getKey().getBytes(); int rep_len = rep.length; if ( rep_len < 2 || rep_len >= k.length ){ Debug.out( "Invalid rep_len: " + rep_len ); continue; } boolean match = true; int offset = k.length-rep_len; for (int i=0;i contact_mappings = contact_state.getMappings(); for ( DHTDBMapping m: contact_mappings ){ int[] t = totals.get( m ); if ( t == null ){ t = new int[]{ 2 }; // one for local node + 1 for them totals.put( m, t ); }else{ t[0]++; } } } } for (Map.Entry> entry: mapping_to_node_map.entrySet()){ DHTDBMapping mapping = entry.getKey(); List contacts = entry.getValue(); int[] t = totals.get( mapping ); int copies; if ( t == null ){ copies = 1; // us! }else{ copies = t[0]; } Iterator values = mapping.getValues(); if ( values.hasNext()){ int max_replication_factor = -1; while( values.hasNext()){ DHTDBValueImpl value = values.next(); int rf = value.getReplicationFactor(); if ( rf > max_replication_factor ){ max_replication_factor = rf; } } if ( max_replication_factor == 0 ){ continue; } if ( max_replication_factor > router.getK()){ max_replication_factor = router.getK(); } if ( copies < max_replication_factor ){ int required = max_replication_factor - copies; List potential_targets = new ArrayList(); List addresses = new ArrayList( contacts.size()); for ( DHTTransportContact c: contacts ){ if ( c.getProtocolVersion() < DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL3 ){ continue; } addresses.add( c.getAddress().getAddress().getAddress()); SurveyContactState contact_state = survey_state.get( new HashWrapper( c.getID())); if ( contact_state != null && !contact_state.testMapping( mapping )){ potential_targets.add( contact_state ); } } Set bad_addresses = new HashSet(); for ( byte[] a1: addresses ){ for ( byte[] a2: addresses ){ // ignore ipv6 for the moment... if ( a1 == a2 || a1.length != a2.length || a1.length != 4 ){ continue; } // ignore common /16 s if ( a1[0] == a2[0] && a1[1] == a2[1] ){ log( "/16 match on " + ByteFormatter.encodeString( a1 ) + "/" + ByteFormatter.encodeString( a2 )); bad_addresses.add( new HashWrapper( a1 )); bad_addresses.add( new HashWrapper( a2 )); } } } final byte[] key = mapping.getKey().getBytes(); Collections.sort( potential_targets, new Comparator() { public int compare( SurveyContactState o1, SurveyContactState o2) { boolean o1_bad = o1.getConsecFails() >= 2; boolean o2_bad = o2.getConsecFails() >= 2; if ( o1_bad == o2_bad ){ // switch from age based to closest as per Roxana's advice if ( false ){ long res = o2.getCreationTime() - o1.getCreationTime(); if ( res < 0 ){ return( -1 ); }else if ( res > 0 ){ return( 1 ); }else{ return( 0 ); } }else{ return( control.computeAndCompareDistances( o1.getContact().getID(), o2.getContact().getID(), key )); } }else{ if ( o1_bad ){ return( 1 ); }else{ return( -1 ); } } } }); int avail = Math.min( required, potential_targets.size()); for (int i=0;i 0 && bad_addresses.contains( new HashWrapper( target.getContact().getAddress().getAddress().getAddress()))){ // make it look like this target has the mapping as we don't want to store it there but we want to treat it as // if it has it, effectively reducing availability but not skewing storage in favour of potentially malicious nodes target.addMapping( mapping ); }else{ List m = store_ops.get( target ); if ( m == null ){ m = new ArrayList(); store_ops.put( target, m ); } m.add( mapping ); } } } } } }finally{ this_mon.exit(); survey_in_progress = false; } logger.log( "Survey complete - " + store_ops.size() + " store ops" ); if ( DEBUG_SURVEY ){ System.out.println( "Store ops: " + store_ops.size()); } for ( Map.Entry> store_op: store_ops.entrySet()){ final SurveyContactState contact = store_op.getKey(); final List keys = store_op.getValue(); final byte[][] store_keys = new byte[keys.size()][]; final DHTTransportValue[][] store_values = new DHTTransportValue[store_keys.length][]; for (int i=0;i v = new ArrayList(); Iterator it = mapping.getValues(); while( it.hasNext()){ DHTDBValueImpl value = it.next(); if ( !value.isLocal()){ v.add( value.getValueForRelay(local_contact)); } } store_values[i] = v.toArray( new DHTTransportValue[v.size()]); } final DHTTransportContact d_contact = contact.getContact(); final Runnable store_exec = new Runnable() { public void run() { if ( DEBUG_SURVEY ){ System.out.println( "Storing " + keys.size() + " on " + d_contact.getString() + " - rand=" + d_contact.getRandomID()); } control.putDirectEncodedKeys( store_keys, "Replication forward", store_values, d_contact, new DHTOperationAdapter() { public void complete( boolean timeout ) { try{ this_mon.enter(); if ( timeout ){ contact.contactFailed(); }else{ contact.contactOK(); for ( DHTDBMapping m: keys ){ contact.addMapping( m ); } } }finally{ this_mon.exit(); } } }); } }; if ( d_contact.getRandomID() == 0 ){ d_contact.sendFindNode( new DHTTransportReplyHandlerAdapter() { public void findNodeReply( DHTTransportContact _contact, DHTTransportContact[] _contacts ) { store_exec.run(); } public void failed( DHTTransportContact _contact, Throwable _error ) { try{ this_mon.enter(); contact.contactFailed(); }finally{ this_mon.exit(); } } }, d_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20] ); }else{ store_exec.run(); } } } public DHTTransportQueryStoreReply queryStore( DHTTransportContact originating_contact, int header_len, List keys ) { final List reply = new ArrayList(); try{ this_mon.enter(); SurveyContactState existing_state = survey_state.get( new HashWrapper( originating_contact.getID())); if ( existing_state != null ){ existing_state.updateContactDetails( originating_contact ); } for (Object[] entry: keys ){ byte[] prefix = (byte[])entry[0]; List suffixes = (List)entry[1]; byte[] header = new byte[header_len]; int prefix_len = prefix.length; int suffix_len = header_len - prefix_len; System.arraycopy( prefix, 0, header, 0, prefix_len ); for ( byte[] suffix: suffixes ){ System.arraycopy( suffix, 0, header, prefix_len, suffix_len ); DHTDBMapping mapping = stored_values_prefix_map.get( new DHTDBMapping.ShortHash( header )); if ( mapping == null ){ reply.add( null ); }else{ if ( existing_state != null ){ existing_state.addMapping( mapping ); } byte[] k = mapping.getKey().getBytes(); byte[] r = new byte[QUERY_STORE_REPLY_ENTRY_SIZE]; System.arraycopy( k, k.length-QUERY_STORE_REPLY_ENTRY_SIZE, r, 0, QUERY_STORE_REPLY_ENTRY_SIZE ); reply.add( r ); } } } return( new DHTTransportQueryStoreReply() { public int getHeaderSize() { return( QUERY_STORE_REPLY_ENTRY_SIZE ); } public List getEntries() { return( reply ); } }); }finally{ this_mon.exit(); } } public void print( boolean full ) { Map count = new TreeMap(); try{ this_mon.enter(); logger.log( "Stored keys = " + stored_values.size() + ", values = " + getValueDetails()[DHTDBStats.VD_VALUE_COUNT]); if ( !full ){ return; } Iterator> it1 = stored_values.entrySet().iterator(); // ByteArrayHashMap blah = new ByteArrayHashMap(); while( it1.hasNext()){ Map.Entry entry = it1.next(); HashWrapper value_key = entry.getKey(); DHTDBMapping mapping = entry.getValue(); /* if ( mapping.getIndirectSize() > 1000 ){ mapping.print(); } */ DHTDBValue[] values = mapping.get(null,0,(byte)0); for (int i=0;i " + c ); } } System.out.println( "Total dup: " + total_dup ); */ Iterator it2 = count.keySet().iterator(); while( it2.hasNext()){ Integer k = it2.next(); Object[] data = (Object[])count.get(k); logger.log( " " + k + " -> " + data[0] + " entries" ); // ": " + data[1]); } Iterator> it3 = stored_values.entrySet().iterator(); String str = " "; int str_entries = 0; while( it3.hasNext()){ Map.Entry entry = it3.next(); HashWrapper value_key = entry.getKey(); DHTDBMapping mapping = entry.getValue(); if ( str_entries == 16 ){ logger.log( str ); str = " "; str_entries = 0; } str_entries++; str += (str_entries==1?"":", ") + DHTLog.getString2(value_key.getHash()) + " -> " + mapping.getValueCount() + "/" + mapping.getHits()+"["+mapping.getLocalSize()+","+mapping.getDirectSize()+","+mapping.getIndirectSize() + "]"; } if ( str_entries > 0 ){ logger.log( str ); } }finally{ this_mon.exit(); } } protected void banContact( final DHTTransportContact contact, final String reason ) { // CVS DHT can be significantly smaller than mainline (e.g. 1000) so will trigger // un-necessary banning which then obviously affects the main DHTs. So we disable // banning for CVS final boolean ban_ip = control.getTransport().getNetwork() != DHT.NW_CVS; new AEThread2( "DHTDBImpl:delayed flood delete", true ) { public void run() { // delete their data on a separate thread so as not to // interfere with the current action try{ this_mon.enter(); Iterator it = stored_values.values().iterator(); boolean overall_deleted = false; HashWrapper value_id = new HashWrapper( contact.getID()); while( it.hasNext()){ DHTDBMapping mapping = it.next(); boolean deleted = false; if ( mapping.removeDirectValue( value_id ) != null ){ deleted = true; } if ( mapping.removeIndirectValue( value_id ) != null ){ deleted = true; } if ( deleted && !ban_ip ){ // if we're not banning then rebuild bloom to avoid us continually // going through this ban code mapping.rebuildIPBloomFilter( false ); overall_deleted = true; } } if ( overall_deleted && !ban_ip ){ rebuildIPBloomFilter( false ); } }finally{ this_mon.exit(); } } }.start(); if ( ban_ip ){ logger.log( "Banning " + contact.getString() + " due to store flooding (" + reason + ")" ); ip_filter.ban( contact.getAddress().getAddress().getHostAddress(), "DHT: Sender stored excessive entries at this node (" + reason + ")", false ); } } protected void incrementValueAdds( DHTTransportContact contact ) { // assume a node stores 1000 values at 20 (K) locations -> 20,000 values // assume a DHT size of 100,000 nodes // that is, on average, 1 value per 5 nodes // assume NAT of up to 30 ports per address // this gives 6 values per address // with a factor of 10 error this is still only 60 per address // However, for CVS DHTs we can have sizes of 1000 or less. int hit_count = ip_count_bloom_filter.add( contact.getAddress().getAddress().getAddress()); if ( DHTLog.GLOBAL_BLOOM_TRACE ){ System.out.println( "direct add from " + contact.getAddress() + ", hit count = " + hit_count ); } // allow up to 10% bloom filter utilisation if ( ip_count_bloom_filter.getSize() / ip_count_bloom_filter.getEntryCount() < 10 ){ rebuildIPBloomFilter( true ); } if ( hit_count > 64 ){ // obviously being spammed, drop all data originated by this IP and ban it banContact( contact, "global flood" ); } } protected void decrementValueAdds( DHTTransportContact contact ) { int hit_count = ip_count_bloom_filter.remove( contact.getAddress().getAddress().getAddress()); if ( DHTLog.GLOBAL_BLOOM_TRACE ){ System.out.println( "direct remove from " + contact.getAddress() + ", hit count = " + hit_count ); } } protected void rebuildIPBloomFilter( boolean increase_size ) { BloomFilter new_filter; if ( increase_size ){ new_filter = BloomFilterFactory.createAddRemove8Bit( ip_count_bloom_filter.getSize() + IP_COUNT_BLOOM_SIZE_INCREASE_CHUNK ); }else{ new_filter = BloomFilterFactory.createAddRemove8Bit( ip_count_bloom_filter.getSize()); } try{ //Map sender_map = new HashMap(); //List senders = new ArrayList(); Iterator it = stored_values.values().iterator(); int max_hits = 0; while( it.hasNext()){ DHTDBMapping mapping = it.next(); mapping.rebuildIPBloomFilter( false ); Iterator it2 = mapping.getDirectValues(); while( it2.hasNext()){ DHTDBValueImpl val = it2.next(); if ( !val.isLocal()){ // logger.log( " adding " + val.getOriginator().getAddress()); int hits = new_filter.add( val.getOriginator().getAddress().getAddress().getAddress()); if ( hits > max_hits ){ max_hits = hits; } } } // survey our neighbourhood /* * its is non-trivial to do anything about nodes that get "close" to us and then * spam us with crap. Ultimately, of course, to take a key out you "just" create * the 20 closest nodes to the key and then run nodes that swallow all registrations * and return nothing. * Protecting against one or two such nodes that flood crap requires crap to be * identified. Tracing shows a large disparity between number of values registered * per neighbour (factors of 100), so an approach based on number of registrations * is non-trivial (assuming future scaling of the DHT, what do we consider crap?) * A further approach would be to query the claimed originators of values (obviously * a low bandwith approach, e.g. query 3 values from the contact with highest number * of forwarded values). This requires originators to support long term knowledge of * what they've published (we don't want to blacklist a neighbour because an originator * has deleted a value/been restarted). We also then have to consider how to deal with * non-responses to queries (assuming an affirmative Yes -> value has been forwarded * correnctly, No -> probably crap). We can't treat non-replies as No. Thus a bad * neighbour only has to forward crap with originators that aren't AZ nodes (very * easy to do!) to break this aproach. * * it2 = mapping.getIndirectValues(); while( it2.hasNext()){ DHTDBValueImpl val = (DHTDBValueImpl)it2.next(); DHTTransportContact sender = val.getSender(); HashWrapper hw = new HashWrapper( sender.getID()); Integer sender_count = (Integer)sender_map.get( hw ); if ( sender_count == null ){ sender_count = new Integer(1); senders.add( sender ); }else{ sender_count = new Integer( sender_count.intValue() + 1 ); } sender_map.put( hw, sender_count ); } */ } logger.log( "Rebuilt global IP bloom filter, size=" + new_filter.getSize() + ", entries=" + new_filter.getEntryCount()+", max hits=" + max_hits ); /* senders = control.sortContactsByDistance( senders ); for (int i=0;i " + sender_map.get(new HashWrapper(sender.getID()))); } */ }finally{ ip_count_bloom_filter = new_filter; } } protected void reportSizes( String op ) { /* if ( !this_mon.isHeld()){ Debug.out( "Monitor not held" ); } int actual_keys = stored_values.size(); int actual_values = 0; int actual_size = 0; Iterator it = stored_values.values().iterator(); while( it.hasNext()){ DHTDBMapping mapping = (DHTDBMapping)it.next(); int reported_size = mapping.getLocalSize() + mapping.getDirectSize() + mapping.getIndirectSize(); actual_values += mapping.getValueCount(); Iterator it2 = mapping.getValues(); int sz = 0; while( it2.hasNext()){ DHTDBValue val = (DHTDBValue)it2.next(); sz += val.getValue().length; } if ( sz != reported_size ){ Debug.out( "Reported mapping size != actual: " + reported_size + "/" + sz ); } actual_size += sz; } if ( actual_keys != total_keys ){ Debug.out( "Actual keys != total: " + actual_keys + "/" + total_keys ); } if ( adapter.getKeyCount() != actual_keys ){ Debug.out( "SM keys != total: " + actual_keys + "/" + adapter.getKeyCount()); } if ( actual_values != total_values ){ Debug.out( "Actual values != total: " + actual_values + "/" + total_values ); } if ( actual_size != total_size ){ Debug.out( "Actual size != total: " + actual_size + "/" + total_size ); } if ( actual_values < actual_keys ){ Debug.out( "Actual values < actual keys: " + actual_values + "/" + actual_keys ); } System.out.println( "DHTDB: " + op + " - keys=" + total_keys + ", values=" + total_values + ", size=" + total_size ); */ } protected int getNextValueVersion() { try{ this_mon.enter(); if ( next_value_version_left == 0 ){ next_value_version_left = VALUE_VERSION_CHUNK; if ( adapter == null ){ // no persistent manager, just carry on incrementing }else{ next_value_version = adapter.getNextValueVersions( VALUE_VERSION_CHUNK ); } //System.out.println( "next chunk:" + next_value_version ); } next_value_version_left--; int res = next_value_version++; //System.out.println( "next value version = " + res ); return( res ); }finally{ this_mon.exit(); } } protected class adapterFacade implements DHTStorageAdapter { private DHTStorageAdapter delegate; protected adapterFacade( DHTStorageAdapter _delegate ) { delegate = _delegate; } public int getNetwork() { return( delegate.getNetwork()); } public DHTStorageKey keyCreated( HashWrapper key, boolean local ) { // report *before* incrementing as this occurs before the key is locally added reportSizes( "keyAdded" ); total_keys++; return( delegate.keyCreated( key, local )); } public void keyDeleted( DHTStorageKey adapter_key ) { total_keys--; delegate.keyDeleted( adapter_key ); reportSizes( "keyDeleted" ); } public int getKeyCount() { return( delegate.getKeyCount()); } public void keyRead( DHTStorageKey adapter_key, DHTTransportContact contact ) { reportSizes( "keyRead" ); delegate.keyRead( adapter_key, contact ); } public DHTStorageKeyStats deserialiseStats( DataInputStream is ) throws IOException { return( delegate.deserialiseStats( is )); } public void valueAdded( DHTStorageKey key, DHTTransportValue value ) { total_values++; total_size += value.getValue().length; reportSizes( "valueAdded"); if ( !value.isLocal() ){ DHTDBValueImpl val = (DHTDBValueImpl)value; boolean direct = Arrays.equals( value.getOriginator().getID(), val.getSender().getID()); if ( direct ){ incrementValueAdds( value.getOriginator()); } } delegate.valueAdded( key, value ); } public void valueUpdated( DHTStorageKey key, DHTTransportValue old_value, DHTTransportValue new_value ) { total_size += (new_value.getValue().length - old_value.getValue().length ); reportSizes("valueUpdated"); delegate.valueUpdated( key, old_value, new_value ); } public void valueDeleted( DHTStorageKey key, DHTTransportValue value ) { total_values--; total_size -= value.getValue().length; reportSizes("valueDeleted"); if ( !value.isLocal() ){ DHTDBValueImpl val = (DHTDBValueImpl)value; boolean direct = Arrays.equals( value.getOriginator().getID(), val.getSender().getID()); if ( direct ){ decrementValueAdds( value.getOriginator()); } } delegate.valueDeleted( key, value ); } // local lookup/put operations public boolean isDiversified( byte[] key ) { return( delegate.isDiversified( key )); } public byte[][] getExistingDiversification( byte[] key, boolean put_operation, boolean exhaustive_get, int max_depth ) { return( delegate.getExistingDiversification( key, put_operation, exhaustive_get, max_depth )); } public byte[][] createNewDiversification( String description, DHTTransportContact cause, byte[] key, boolean put_operation, byte diversification_type, boolean exhaustive_get, int max_depth ) { return( delegate.createNewDiversification( description, cause, key, put_operation, diversification_type, exhaustive_get, max_depth )); } public int getNextValueVersions( int num ) { return( delegate.getNextValueVersions(num)); } public DHTStorageBlock keyBlockRequest( DHTTransportContact direct_sender, byte[] request, byte[] signature ) { return( delegate.keyBlockRequest( direct_sender, request, signature )); } public DHTStorageBlock getKeyBlockDetails( byte[] key ) { return( delegate.getKeyBlockDetails(key)); } public DHTStorageBlock[] getDirectKeyBlocks() { return( delegate.getDirectKeyBlocks()); } public byte[] getKeyForKeyBlock( byte[] request ) { return( delegate.getKeyForKeyBlock( request )); } public void setStorageForKey( String key, byte[] data ) { delegate.setStorageForKey( key, data ); } public byte[] getStorageForKey( String key ) { return( delegate.getStorageForKey(key)); } public int getRemoteFreqDivCount() { return( delegate.getRemoteFreqDivCount()); } public int getRemoteSizeDivCount() { return( delegate.getRemoteSizeDivCount()); } } protected static class SurveyContactState { private DHTTransportContact contact; private long creation_time = SystemTime.getMonotonousTime(); private long timeout = creation_time + SURVEY_STATE_MAX_LIFE_TIMEOUT + RandomUtils.nextInt( SURVEY_STATE_MAX_LIFE_RAND ); private long last_used = creation_time; private Set mappings = new HashSet(); private int consec_fails; protected SurveyContactState( DHTTransportContact c ) { contact = c; log( "new" ); } protected boolean timeout( long now ) { return( now - last_used > SURVEY_STATE_INACT_TIMEOUT || now > timeout ); } protected DHTTransportContact getContact() { return( contact ); } protected long getCreationTime() { return( creation_time ); } protected void updateContactDetails( DHTTransportContact c ) { if ( c.getInstanceID() != contact.getInstanceID()){ log( "instance id changed" ); mappings.clear(); } contact = c; } protected void updateUseTime() { last_used = SystemTime.getMonotonousTime(); } protected long getLastUseTime() { return( last_used ); } protected void contactOK() { log( "contact ok" ); consec_fails = 0; } protected void contactFailed() { consec_fails++; log( "failed, consec=" + consec_fails ); if ( consec_fails >= 2 ){ mappings.clear(); } } protected int getConsecFails() { return( consec_fails ); } protected boolean testMapping( DHTDBMapping mapping ) { return( mappings.contains( mapping )); } protected Set getMappings() { return( mappings ); } protected void addMapping( DHTDBMapping mapping ) { if ( mappings.add( mapping )){ log( "add mapping" ); } } protected void removeMapping( DHTDBMapping mapping ) { if ( mappings.remove( mapping )){ log( "remove mapping" ); } } protected void log( String str ) { if ( DEBUG_SURVEY ){ System.out.println( "s_state: " + contact.getString() + ": " + str ); } } } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/db/DHTDBValue.java0000644000175000017500000000235510373051030023322 0ustar adrianadrian/* * Created on 28-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.db; import com.aelitis.azureus.core.dht.transport.*; /** * @author parg * */ public interface DHTDBValue extends DHTTransportValue { public void setFlags( byte flags ); public DHTDBValue getValueForRelay( DHTTransportContact new_originator ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/db/DHTDBFactory.java0000644000175000017500000000302511261037754023666 0ustar adrianadrian/* * Created on 28-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.db; import com.aelitis.azureus.core.dht.DHTLogger; import com.aelitis.azureus.core.dht.DHTStorageAdapter; import com.aelitis.azureus.core.dht.db.impl.DHTDBImpl; /** * @author parg * */ public class DHTDBFactory { public static DHTDB create( DHTStorageAdapter adapter, int original_republish_interval, int cache_republish_interval, byte protocol_version, DHTLogger logger ) { return( new DHTDBImpl( adapter, original_republish_interval, cache_republish_interval, protocol_version, logger )); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/db/DHTDBStats.java0000644000175000017500000000337211065032272023352 0ustar adrianadrian/* * Created on 25-Apr-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.db; public interface DHTDBStats { public static final int VD_VALUE_COUNT = 0; // total values public static final int VD_LOCAL_SIZE = 1; // locally stored data size public static final int VD_DIRECT_SIZE = 2; // directly stored to us by others public static final int VD_INDIRECT_SIZE = 3; // indirectly (cache forwarded) stored public static final int VD_DIV_FREQ = 4; // diversifications caused by frequency public static final int VD_DIV_SIZE = 5; // diversifications caused by size public int getKeyCount(); public int getLocalKeyCount(); public int getKeyBlockCount(); public int getSize(); public int getValueCount(); /** * returned values indexed by above VD_ constants for meaning * @return */ public int[] getValueDetails(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/db/DHTDBLookupResult.java0000644000175000017500000000217410373051030024715 0ustar adrianadrian/* * Created on 10-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.db; /** * @author parg * */ public interface DHTDBLookupResult { public DHTDBValue[] getValues(); public byte getDiversificationType(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/DHTStorageAdapter.java0000644000175000017500000000607711255101712024370 0ustar adrianadrian/* * Created on 12-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht; import java.io.DataInputStream; import java.io.IOException; import org.gudy.azureus2.core3.util.HashWrapper; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportValue; /** * @author parg * */ public interface DHTStorageAdapter { public int getNetwork(); // local value operations /** * Create a new storage key for a given key * @return null if the key shouldn't be allocated (e.g.out of space) */ public DHTStorageKey keyCreated( HashWrapper key, boolean local ); public void keyDeleted( DHTStorageKey adapter_key ); public void keyRead( DHTStorageKey adapter_key, DHTTransportContact contact ); public DHTStorageKeyStats deserialiseStats( DataInputStream is ) throws IOException; public void valueAdded( DHTStorageKey key, DHTTransportValue value ); public void valueUpdated( DHTStorageKey key, DHTTransportValue old_value, DHTTransportValue new_value ); public void valueDeleted( DHTStorageKey key, DHTTransportValue value ); // local lookup/put operations public boolean isDiversified( byte[] key ); public byte[][] getExistingDiversification( byte[] key, boolean put_operation, boolean exhaustive_get, int max_depth ); public byte[][] createNewDiversification( String description, DHTTransportContact cause, byte[] key, boolean put_operation, byte diversification_type, boolean exhaustive_get, int max_depth ); public int getNextValueVersions( int num ); public DHTStorageBlock keyBlockRequest( DHTTransportContact direct_sender, byte[] request, byte[] signature ); public DHTStorageBlock getKeyBlockDetails( byte[] key ); public DHTStorageBlock[] getDirectKeyBlocks(); public byte[] getKeyForKeyBlock( byte[] request ); public void setStorageForKey( String key, byte[] data ); public byte[] getStorageForKey( String key ); public int getRemoteFreqDivCount(); public int getRemoteSizeDivCount(); public int getKeyCount(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/DHTStorageBlock.java0000644000175000017500000000244010402150270024024 0ustar adrianadrian/* * Created on 03-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; public interface DHTStorageBlock { public byte[] getKey(); public byte[] getRequest(); public byte[] getCertificate(); public boolean hasBeenSentTo( DHTTransportContact contact ); public void sentTo( DHTTransportContact contact ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/DHT.java0000644000175000017500000001422211267313014021534 0ustar adrianadrian/* * Created on 11-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht; import java.io.*; import com.aelitis.azureus.core.dht.control.DHTControl; import com.aelitis.azureus.core.dht.db.DHTDB; import com.aelitis.azureus.core.dht.nat.DHTNATPuncher; import com.aelitis.azureus.core.dht.router.DHTRouter; import com.aelitis.azureus.core.dht.speed.DHTSpeedTester; import com.aelitis.azureus.core.dht.transport.DHTTransport; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportValue; /** * @author parg * */ public interface DHT { // all property values are Integer values public static final String PR_CONTACTS_PER_NODE = "EntriesPerNode"; public static final String PR_NODE_SPLIT_FACTOR = "NodeSplitFactor"; public static final String PR_SEARCH_CONCURRENCY = "SearchConcurrency"; public static final String PR_LOOKUP_CONCURRENCY = "LookupConcurrency"; public static final String PR_MAX_REPLACEMENTS_PER_NODE = "ReplacementsPerNode"; public static final String PR_CACHE_AT_CLOSEST_N = "CacheClosestN"; public static final String PR_ORIGINAL_REPUBLISH_INTERVAL = "OriginalRepublishInterval"; public static final String PR_CACHE_REPUBLISH_INTERVAL = "CacheRepublishInterval"; public static final byte FLAG_SINGLE_VALUE = 0x00; public static final byte FLAG_DOWNLOADING = 0x01; public static final byte FLAG_SEEDING = 0x02; public static final byte FLAG_MULTI_VALUE = 0x04; public static final byte FLAG_STATS = 0x08; public static final byte FLAG_ANON = 0x10; public static final byte FLAG_PRECIOUS = 0x20; public static final byte FLAG_PUT_AND_FORGET = 0x40; // local only public static final byte FLAG_OBFUSCATE_LOOKUP = (byte)0x80; // local only public static final int MAX_VALUE_SIZE = 512; public static final byte REP_FACT_NONE = 0; public static final byte REP_FACT_DEFAULT = (byte)0xff; // diversification types, don't change as serialised!!!! public static final byte DT_NONE = 1; public static final byte DT_FREQUENCY = 2; public static final byte DT_SIZE = 3; public static final String[] DT_STRINGS = { "", "None", "Freq", "Size" }; public static final int NW_MAIN = 0; public static final int NW_CVS = 1; public static final int NW_MAIN_V6 = 3; public void put( byte[] key, String description, byte[] value, byte flags, DHTOperationListener listener ); /** * default is HIGH PRIORITY. if you change to low priority then do so consistently as * operations can get out of order otherwise * @param key * @param description * @param value * @param flags * @param high_priority * @param listener */ public void put( byte[] key, String description, byte[] value, byte flags, boolean high_priority, DHTOperationListener listener ); public void put( byte[] key, String description, byte[] value, byte flags, byte life_hours, boolean high_priority, DHTOperationListener listener ); public void put( byte[] key, String description, byte[] value, byte flags, byte life_hours, byte replication_control, // 4 bits 1->14 republish hours; 0=vuze default | 4 bits 0->15 maintain replicas; [ff=no replication control-use default] boolean high_priority, DHTOperationListener listener ); /** * Returns value if originated from here for key * @param key * @return */ public DHTTransportValue getLocalValue( byte[] key ); /** * @param key * @param max_values * @param timeout * @param listener */ public void get( byte[] key, String description, byte flags, int max_values, long timeout, boolean exhaustive, boolean high_priority, DHTOperationListener listener ); public byte[] remove( byte[] key, String description, DHTOperationListener listener ); public byte[] remove( DHTTransportContact[] contacts, byte[] key, String description, DHTOperationListener listener ); public boolean isDiversified( byte[] key ); public int getIntProperty( String name ); public DHTTransport getTransport(); public DHTRouter getRouter(); public DHTControl getControl(); public DHTDB getDataBase(); public DHTNATPuncher getNATPuncher(); public DHTSpeedTester getSpeedTester(); public DHTStorageAdapter getStorageAdapter(); /** * externalises information that allows the DHT to be recreated at a later date * and populated via the import method * @param os * @param max maximum to export, 0 -> all * @throws IOException */ public void exportState( DataOutputStream os, int max ) throws IOException; /** * populate the DHT with previously exported state * @param is * @throws IOException */ public void importState( DataInputStream is ) throws IOException; /** * Integrate the node into the DHT * Can be invoked more than once if additional state is imported */ public void integrate( boolean full_wait ); public void destroy(); public void setLogging( boolean on ); public DHTLogger getLogger(); public void print( boolean full ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/control/0000755000175000017500000000000011310377622021735 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/dht/control/DHTControlAdapter.java0000644000175000017500000000275211255101712026060 0ustar adrianadrian/* * Created on 10-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.control; import com.aelitis.azureus.core.dht.DHTStorageAdapter; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; /** * @author parg * */ public interface DHTControlAdapter { public DHTStorageAdapter getStorageAdapter(); public byte[][] diversify( String description, DHTTransportContact cause, boolean put_operation, boolean existing, byte[] key, byte type, boolean exhaustive, int max_depth ); public boolean isDiversified( byte[] key ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/control/impl/0000755000175000017500000000000011310377622022676 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/dht/control/impl/DHTControlImpl.java0000644000175000017500000033626611274464546026376 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.control.impl; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.math.BigInteger; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.*; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.engines.RC4Engine; import org.bouncycastle.crypto.params.KeyParameter; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.dht.*; import com.aelitis.azureus.core.dht.control.*; import com.aelitis.azureus.core.dht.db.DHTDB; import com.aelitis.azureus.core.dht.db.DHTDBFactory; import com.aelitis.azureus.core.dht.db.DHTDBLookupResult; import com.aelitis.azureus.core.dht.db.DHTDBValue; import com.aelitis.azureus.core.dht.impl.DHTLog; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionManager; import com.aelitis.azureus.core.dht.router.DHTRouter; import com.aelitis.azureus.core.dht.router.DHTRouterAdapter; import com.aelitis.azureus.core.dht.router.DHTRouterContact; import com.aelitis.azureus.core.dht.router.DHTRouterFactory; import com.aelitis.azureus.core.dht.transport.*; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; /** * @author parg * */ public class DHTControlImpl implements DHTControl, DHTTransportRequestHandler { private static final boolean DISABLE_REPLICATE_ON_JOIN = true; private static final int EXTERNAL_LOOKUP_CONCURRENCY = 16; private static final int EXTERNAL_PUT_CONCURRENCY = 8; private static final int RANDOM_QUERY_PERIOD = 5*60*1000; private static final int INTEGRATION_TIME_MAX = 15*1000; private DHTControlAdapter adapter; private DHTTransport transport; private DHTTransportContact local_contact; private DHTRouter router; private DHTDB database; private DHTControlStatsImpl stats; private DHTLogger logger; private int node_id_byte_count; private int search_concurrency; private int lookup_concurrency; private int cache_at_closest_n; private int K; private int B; private int max_rep_per_node; private long router_start_time; private int router_count; private ThreadPool internal_lookup_pool; private ThreadPool external_lookup_pool; private ThreadPool internal_put_pool; private ThreadPool external_put_pool; private Map imported_state = new HashMap(); private volatile boolean seeded; private long last_lookup; private ListenerManager listeners = ListenerManager.createAsyncManager( "DHTControl:listenDispatcher", new ListenerManagerDispatcher() { public void dispatch( Object _listener, int type, Object value ) { DHTControlListener target = (DHTControlListener)_listener; target.activityChanged((DHTControlActivity)value, type ); } }); private List activities = new ArrayList(); private AEMonitor activity_mon = new AEMonitor( "DHTControl:activities" ); protected AEMonitor estimate_mon = new AEMonitor( "DHTControl:estimate" ); private long last_dht_estimate_time; private long local_dht_estimate; private long combined_dht_estimate; private int combined_dht_estimate_mag; private static final int LOCAL_ESTIMATE_HISTORY = 32; private Map local_estimate_values = new LinkedHashMap(LOCAL_ESTIMATE_HISTORY,0.75f,true) { protected boolean removeEldestEntry( Map.Entry eldest) { return( size() > LOCAL_ESTIMATE_HISTORY ); } }; private static final int REMOTE_ESTIMATE_HISTORY = 128; private List remote_estimate_values = new LinkedList(); protected AEMonitor spoof_mon = new AEMonitor( "DHTControl:spoof" ); private Cipher spoof_cipher; private SecretKey spoof_key; private DHTTransportContact spoof_last_verify_contact; private int spoof_last_verify_result; private long last_node_add_check; private byte[] node_add_check_uninteresting_limit; private long rbs_time; private byte[] rbs_id = {}; public DHTControlImpl( DHTControlAdapter _adapter, DHTTransport _transport, int _K, int _B, int _max_rep_per_node, int _search_concurrency, int _lookup_concurrency, int _original_republish_interval, int _cache_republish_interval, int _cache_at_closest_n, DHTLogger _logger ) { adapter = _adapter; transport = _transport; logger = _logger; K = _K; B = _B; max_rep_per_node = _max_rep_per_node; search_concurrency = _search_concurrency; lookup_concurrency = _lookup_concurrency; cache_at_closest_n = _cache_at_closest_n; // set this so we don't do initial calculation until reasonably populated last_dht_estimate_time = SystemTime.getCurrentTime(); database = DHTDBFactory.create( adapter.getStorageAdapter(), _original_republish_interval, _cache_republish_interval, transport.getProtocolVersion(), logger ); internal_lookup_pool = new ThreadPool("DHTControl:internallookups", lookup_concurrency ); internal_put_pool = new ThreadPool("DHTControl:internalputs", lookup_concurrency ); // external pools queue when full ( as opposed to blocking ) external_lookup_pool = new ThreadPool("DHTControl:externallookups", EXTERNAL_LOOKUP_CONCURRENCY, true ); external_put_pool = new ThreadPool("DHTControl:puts", EXTERNAL_PUT_CONCURRENCY, true ); createRouter( transport.getLocalContact()); node_id_byte_count = router.getID().length; stats = new DHTControlStatsImpl( this ); // don't bother computing anti-spoof stuff if we don't support value storage if ( transport.supportsStorage()){ try{ spoof_cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); KeyGenerator keyGen = KeyGenerator.getInstance("DESede"); spoof_key = keyGen.generateKey(); }catch( Throwable e ){ Debug.printStackTrace( e ); logger.log( e ); } } transport.setRequestHandler( this ); transport.addListener( new DHTTransportListener() { public void localContactChanged( DHTTransportContact new_local_contact ) { logger.log( "Transport ID changed, recreating router" ); List old_contacts = router.findBestContacts( 0 ); byte[] old_router_id = router.getID(); createRouter( new_local_contact ); // sort for closeness to new router id Set sorted_contacts = new sortedTransportContactSet( router.getID(), true ).getSet(); for (int i=0;i 500 && !full_wait ){ logger.log( "Initial integration completed, waiting " + remaining + " ms for second phase to start" ); try{ Thread.sleep( remaining ); }catch( Throwable e ){ Debug.out(e); } } } public boolean isSeeded() { return( seeded ); } protected void poke() { long now = SystemTime.getCurrentTime(); if ( now < last_lookup || now - last_lookup > RANDOM_QUERY_PERIOD ){ last_lookup = now; // we don't want this to be blocking as it'll stuff the stats external_lookup_pool.run( new DhtTask(external_lookup_pool) { private byte[] target = {}; public void runSupport() { target = router.refreshRandom(); } protected void cancel() { } public byte[] getTarget() { return( target ); } public String getDescription() { return( "Random Query" ); } }); } } public void put( byte[] _unencoded_key, String _description, byte[] _value, byte _flags, byte _life_hours, byte _replication_control, boolean _high_priority, DHTOperationListener _listener ) { // public entry point for explicit publishes if ( _value.length == 0 ){ // zero length denotes value removal throw( new RuntimeException( "zero length values not supported")); } byte[] encoded_key = encodeKey( _unencoded_key ); if ( DHTLog.isOn()){ DHTLog.log( "put for " + DHTLog.getString( encoded_key )); } DHTDBValue value = database.store( new HashWrapper( encoded_key ), _value, _flags, _life_hours, _replication_control ); put( external_put_pool, _high_priority, encoded_key, _description, value, _flags, 0, true, new HashSet(), 1, _listener instanceof DHTOperationListenerDemuxer? (DHTOperationListenerDemuxer)_listener: new DHTOperationListenerDemuxer(_listener)); } public void putEncodedKey( byte[] encoded_key, String description, DHTTransportValue value, long timeout, boolean original_mappings ) { put( internal_put_pool, false, encoded_key, description, value, (byte)0, timeout, original_mappings, new HashSet(), 1, new DHTOperationListenerDemuxer( new DHTOperationAdapter())); } protected void put( ThreadPool thread_pool, boolean high_priority, byte[] initial_encoded_key, String description, DHTTransportValue value, byte flags, long timeout, boolean original_mappings, Set things_written, int put_level, DHTOperationListenerDemuxer listener ) { put( thread_pool, high_priority, initial_encoded_key, description, new DHTTransportValue[]{ value }, flags, timeout, original_mappings, things_written, put_level, listener ); } protected void put( final ThreadPool thread_pool, final boolean high_priority, final byte[] initial_encoded_key, final String description, final DHTTransportValue[] values, final byte flags, final long timeout, final boolean original_mappings, final Set things_written, final int put_level, final DHTOperationListenerDemuxer listener ) { // get the initial starting point for the put - may have previously been diversified byte[][] encoded_keys = adapter.diversify( description, null, true, true, initial_encoded_key, DHT.DT_NONE, original_mappings, getMaxDivDepth()); if ( encoded_keys.length == 0 ){ // over-diversified listener.diversified( "Over-diversification of [" + description + "]" ); listener.complete( false ); return; } // may be > 1 if diversification is replicating (for load balancing) for (int i=0;i contacts = new ArrayList(1); contacts.add( contact ); put( internal_put_pool, false, encoded_keys, description, value_sets, (byte)0, contacts, 0, new DHTOperationListenerDemuxer( listener ), false, new HashSet(), 1, false ); } public byte[] getObfuscatedKey( byte[] plain_key ) { int length = plain_key.length; byte[] obs_key = new byte[ length ]; System.arraycopy( plain_key, 0, obs_key, 0, 5 ); // ensure plain key and obfuscated one differ at subsequent bytes to prevent potential // clashes with code that uses 'n' byte prefix (e.g. DB survey code) for (int i=6;i max_depth ){ Debug.out( "Put level exceeded, terminating diversification (level=" + put_level + ",max=" + max_depth + ")" ); listener.incrementCompletes(); listener.complete( false ); return; } boolean[] ok = new boolean[initial_encoded_keys.length]; int failed = 0; for (int i=0;i 0 ){ int pos = 0; for (int i=0;i failed: " + _error.getMessage()); } listener.complete( true ); } }, obs_keys, obs_vals, immediate ); complete_is_async = true; } } }finally{ if ( !complete_is_async ){ listener.complete( false ); } } } public void failed( DHTTransportContact _contact, Throwable _error ) { try{ if ( DHTLog.isOn()){ DHTLog.log( "Store failed " + DHTLog.getString( _contact ) + " -> failed: " + _error.getMessage()); } router.contactDead( _contact.getID(), false ); }finally{ listener.complete( true ); } } public void keyBlockRequest( DHTTransportContact contact, byte[] request, byte[] key_signature ) { DHTStorageBlock key_block = database.keyBlockRequest( null, request, key_signature ); if ( key_block != null ){ // remove this key for any subsequent publishes. Quickest hack // is to change it into a random key value - this will be rejected // by the recipient as not being close enough anyway for (int i=0;i " + div_str ); new AEThread2( "sdsd", true ) { public void run() { DHTTransportFullStats stats = contact.getStats(); System.out.println( contact.getString() + "-> " +(stats==null?"":stats.getString())); } }.start(); */ } public DHTTransportValue getLocalValue( byte[] unencoded_key ) { final byte[] encoded_key = encodeKey( unencoded_key ); if ( DHTLog.isOn()){ DHTLog.log( "getLocalValue for " + DHTLog.getString( encoded_key )); } DHTDBValue res = database.get( new HashWrapper( encoded_key )); if ( res == null ){ return( null ); } return( res ); } public void get( byte[] unencoded_key, String description, byte flags, int max_values, long timeout, boolean exhaustive, boolean high_priority, final DHTOperationListener get_listener ) { final byte[] encoded_key = encodeKey( unencoded_key ); if ( DHTLog.isOn()){ DHTLog.log( "get for " + DHTLog.getString( encoded_key )); } final DhtTaskSet[] task_set = { null }; DHTOperationListenerDemuxer demuxer = new DHTOperationListenerDemuxer( new DHTOperationListener() { public void searching( DHTTransportContact contact, int level, int active_searches ) { get_listener.searching(contact, level, active_searches); } public void diversified( String desc ) { get_listener.diversified(desc); } public void found( DHTTransportContact contact, boolean is_closest ) { get_listener.found(contact,is_closest); } public void read( DHTTransportContact contact, DHTTransportValue value ) { get_listener.read(contact, value); } public void wrote( DHTTransportContact contact, DHTTransportValue value ) { get_listener.wrote(contact, value); } public void complete( boolean timeout ) { get_listener.complete(timeout); if ( task_set[0] != null ){ task_set[0].cancel(); } } }); task_set[0] = getSupport( encoded_key, description, flags, max_values, timeout, exhaustive, high_priority, demuxer ); } public boolean isDiversified( byte[] unencoded_key ) { final byte[] encoded_key = encodeKey( unencoded_key ); return( adapter.isDiversified( encoded_key )); } public boolean lookup( byte[] unencoded_key, String description, long timeout, final DHTOperationListener lookup_listener ) { return( lookupEncoded( encodeKey( unencoded_key ), description, timeout, false, lookup_listener )); } public boolean lookupEncoded( byte[] encoded_key, String description, long timeout, boolean high_priority, final DHTOperationListener lookup_listener ) { if ( DHTLog.isOn()){ DHTLog.log( "lookup for " + DHTLog.getString( encoded_key )); } final AESemaphore sem = new AESemaphore( "DHTControl:lookup" ); final boolean[] diversified = { false }; DHTOperationListener delegate = new DHTOperationListener() { public void searching( DHTTransportContact contact, int level, int active_searches ) { lookup_listener.searching( contact, level, active_searches ); } public void found( DHTTransportContact contact, boolean is_closest ) { } public void diversified( String desc ) { lookup_listener.diversified( desc ); } public void read( DHTTransportContact contact, DHTTransportValue value ) { } public void wrote( DHTTransportContact contact, DHTTransportValue value ) { } public void complete( boolean timeout ) { lookup_listener.complete( timeout ); sem.release(); } }; lookup( external_lookup_pool, high_priority, encoded_key, description, (byte)0, false, timeout, search_concurrency, 1, router.getK(), new lookupResultHandler( delegate ) { public void diversify( DHTTransportContact cause, byte diversification_type ) { diversified( "Diversification of [lookup]" ); diversified[0] = true; } public void closest( List closest ) { for (int i=0;i 0 ){ byte[][] diversified_keys = adapter.diversify( description, cause, false, false, encoded_key, diversification_type, exhaustive, getMaxDivDepth()); if ( diversified_keys.length > 0 ){ // should return a max of 1 (0 if diversification refused) // however, could change one day to search > 1 for (int j=0;j 0 ){ DHTTransportValue[] values = new DHTTransportValue[found_values.size()]; found_values.toArray( values ); // cache the values at the 'n' closest seen locations for (int k=0;k failed: " + _error.getMessage()); router.contactDead( _contact.getID(), false ); } }, new byte[][]{ encoded_key }, new DHTTransportValue[][]{ values }); } } */ } })); } return( result ); } public byte[] remove( byte[] unencoded_key, String description, DHTOperationListener listener ) { final byte[] encoded_key = encodeKey( unencoded_key ); if ( DHTLog.isOn()){ DHTLog.log( "remove for " + DHTLog.getString( encoded_key )); } DHTDBValue res = database.remove( local_contact, new HashWrapper( encoded_key )); if ( res == null ){ // not found locally, nothing to do return( null ); }else{ // we remove a key by pushing it back out again with zero length value put( external_put_pool, false, encoded_key, description, res, (byte)res.getFlags(), 0, true, new HashSet(), 1, new DHTOperationListenerDemuxer( listener )); return( res.getValue()); } } public byte[] remove( DHTTransportContact[] contacts, byte[] unencoded_key, String description, DHTOperationListener listener ) { final byte[] encoded_key = encodeKey( unencoded_key ); if ( DHTLog.isOn()){ DHTLog.log( "remove for " + DHTLog.getString( encoded_key )); } DHTDBValue res = database.remove( local_contact, new HashWrapper( encoded_key )); if ( res == null ){ // not found locally, nothing to do return( null ); }else{ List contacts_l = new ArrayList( contacts.length ); for (int i=0;i 0) { timeoutEvent = SimpleTimer.addEvent("DHT lookup timeout", SystemTime.getCurrentTime()+timeout, new TimerEventPerformer() { public void perform(TimerEvent event) { if ( DHTLog.isOn()){ DHTLog.log("lookup: terminates - timeout"); } //System.out.println("timeout"); timeout_occurred = true; terminateLookup(false); } }); } lookupSteps(); } private void terminateLookup(boolean error) { if(timeoutEvent != null) timeoutEvent.cancel(); synchronized (this) { if(runningState == -1) return; runningState = -1; } if(!error) { // maybe unterminated searches still going on so protect ourselves // against concurrent modification of result set List closest_res = null; try { contacts_to_query_mon.enter(); if (DHTLog.isOn()) { DHTLog.log("lookup complete for " + DHTLog.getString(lookup_id)); DHTLog.log(" queried = " + DHTLog.getString(contacts_queried)); DHTLog.log(" to query = " + DHTLog.getString(contacts_to_query)); DHTLog.log(" ok = " + DHTLog.getString(ok_contacts)); } closest_res = new ArrayList(ok_contacts); // we need to reverse the list as currently closest is at the end Collections.reverse(closest_res); if (timeout <= 0 && !value_search) // we can use the results of this to estimate the DHT size estimateDHTSize(lookup_id, contacts_queried, search_accuracy); } finally { contacts_to_query_mon.exit(); } handler.closest(closest_res); } handler.complete(timeout_occurred); releaseToPool(); } private synchronized boolean reserve() { if(freeTasksCount <= 0 || runningState == -1) { //System.out.println("reserve-exit"); if(runningState == 1) runningState = 0; return false; } freeTasksCount--; return true; } private synchronized void release() { freeTasksCount++; if(runningState == 0) { //System.out.println("release-start"); runningState = 1; new AEThread2("DHT lookup runner",true) { public void run() { thread_pool.registerThreadAsChild(worker); lookupSteps(); thread_pool.deregisterThreadAsChild(worker); } }.start(); } } protected synchronized void cancel() { if ( runningState != -1 ){ // System.out.println( "Task cancelled" ); } cancelled = true; } // individual lookup steps private void lookupSteps() { try { boolean terminate = false; while ( !cancelled ) { if (timeout > 0) { long now = SystemTime.getMonotonousTime(); long remaining = timeout - (now - start); if (remaining <= 0) { if ( DHTLog.isOn()){ DHTLog.log("lookup: terminates - timeout"); } timeout_occurred = true; terminate = true; break; } if(!reserve()) break; // temporary stop, will be revived by release() or until a timeout occurs } else if(!reserve()) break; // temporary stop, will be revived by release()*/ try { contacts_to_query_mon.enter(); // for stats queries the values returned are unique to target so don't assume 2 replies sufficient if (values_found >= max_values || (( flags & DHT.FLAG_STATS ) == 0 && value_replies >= 2 )) { // all hits should have the same values anyway... terminate = true; break; } // if we've received a key block then easiest way to terminate the query is to // dump any outstanding targets if (key_blocked) contacts_to_query.clear(); // if nothing pending then we need to wait for the results of a previous // search to arrive. Of course, if there are no searches active then // we've run out of things to do if (contacts_to_query.size() == 0) { if (active_searches == 0) { if ( DHTLog.isOn()){ DHTLog.log("lookup: terminates - no contacts left to query"); } terminate = true; break; } idle_searches++; continue; } // select the next contact to search DHTTransportContact closest = (DHTTransportContact) contacts_to_query.iterator().next(); // if the next closest is further away than the furthest successful hit so // far and we have K hits, we're done if (ok_contacts.size() == search_accuracy) { DHTTransportContact furthest_ok = (DHTTransportContact) ok_contacts.iterator().next(); int distance = computeAndCompareDistances(furthest_ok.getID(), closest.getID(), lookup_id); if (distance <= 0) { if ( DHTLog.isOn()){ DHTLog.log("lookup: terminates - we've searched the closest " + search_accuracy + " contacts"); } terminate = true; break; } } // we optimise the first few entries based on their Vivaldi distance. Only a few // however as we don't want to start too far away from the target. if (contacts_queried.size() < concurrency) { DHTNetworkPosition[] loc_nps = local_contact.getNetworkPositions(); DHTTransportContact vp_closest = null; Iterator vp_it = contacts_to_query.iterator(); int vp_count_limit = (concurrency * 2) - contacts_queried.size(); int vp_count = 0; float best_dist = Float.MAX_VALUE; while (vp_it.hasNext() && vp_count < vp_count_limit) { vp_count++; DHTTransportContact entry = (DHTTransportContact) vp_it.next(); DHTNetworkPosition[] rem_nps = entry.getNetworkPositions(); float dist = DHTNetworkPositionManager.estimateRTT(loc_nps, rem_nps); if ((!Float.isNaN(dist)) && dist < best_dist) { best_dist = dist; vp_closest = entry; // System.out.println( start + ": lookup for " + DHTLog.getString2( lookup_id ) + ": vp override (dist = " + dist + ")"); } if (vp_closest != null) // override ID closest with VP closes closest = vp_closest; } } final DHTTransportContact f_closest = closest; contacts_to_query.remove(closest); contacts_queried.put(new HashWrapper(closest.getID()), closest); // never search ourselves! if (router.isID(closest.getID())) { release(); continue; } final int search_level = ((Integer) level_map.get(closest)).intValue(); active_searches++; handler.searching(closest, search_level, active_searches); DHTTransportReplyHandlerAdapter replyHandler = new DHTTransportReplyHandlerAdapter() { private boolean value_reply_received = false; public void findNodeReply(DHTTransportContact target_contact, DHTTransportContact[] reply_contacts) { try { if ( DHTLog.isOn()){ DHTLog.log("findNodeReply: " + DHTLog.getString(reply_contacts)); } router.contactAlive(target_contact.getID(), new DHTControlContactImpl(target_contact)); for (int i = 0; i < reply_contacts.length; i++) { DHTTransportContact contact = reply_contacts[i]; // ignore responses that are ourselves if (compareDistances(router.getID(), contact.getID()) == 0) continue; // dunno if its alive or not, however record its existance router.contactKnown(contact.getID(), new DHTControlContactImpl(contact)); } try { contacts_to_query_mon.enter(); ok_contacts.add(target_contact); if (ok_contacts.size() > search_accuracy) { // delete the furthest away Iterator ok_it = ok_contacts.iterator(); ok_it.next(); ok_it.remove(); } for (int i = 0; i < reply_contacts.length; i++) { DHTTransportContact contact = reply_contacts[i]; // ignore responses that are ourselves if (compareDistances(router.getID(), contact.getID()) == 0) continue; if (contacts_queried.get(new HashWrapper(contact.getID())) == null && (!contacts_to_query.contains(contact))) { if ( DHTLog.isOn()){ DHTLog.log(" new contact for query: " + DHTLog.getString(contact)); } contacts_to_query.add(contact); handler.found(contact,false); level_map.put(contact, new Integer(search_level + 1)); if (idle_searches > 0) { idle_searches--; release(); } } else { // DHTLog.log( " already queried: " + DHTLog.getString( contact )); } } } finally { contacts_to_query_mon.exit(); } } finally { try { contacts_to_query_mon.enter(); active_searches--; } finally { contacts_to_query_mon.exit(); } release(); } } public void findValueReply( DHTTransportContact contact, DHTTransportValue[] values, byte diversification_type, // hack - this is set to 99 when recursing here during obsfuscated lookup boolean more_to_come ) { if ( DHTLog.isOn()){ DHTLog.log("findValueReply: " + DHTLog.getString(values) + ",mtc=" + more_to_come + ", dt=" + diversification_type); } boolean obs_recurse = false; if ( diversification_type == 99 ){ obs_recurse = true; diversification_type = DHT.DT_NONE; } try { if (!key_blocked && diversification_type != DHT.DT_NONE){ // diversification instruction if (( flags & DHT.FLAG_STATS ) == 0 ){ // ignore for stats queries as we're after the // target key's stats, not the diversification // thereof handler.diversify(contact, diversification_type); } } value_reply_received = true; router.contactAlive(contact.getID(), new DHTControlContactImpl(contact)); int new_values = 0; if (!key_blocked) { for (int i = 0; i < values.length; i++) { DHTTransportValue value = values[i]; DHTTransportContact originator = value.getOriginator(); // can't just use originator id as this value can be DOSed (see DB code) byte[] originator_id = originator.getID(); byte[] value_bytes = value.getValue(); byte[] value_id = new byte[originator_id.length + value_bytes.length]; System.arraycopy(originator_id, 0, value_id, 0, originator_id.length); System.arraycopy(value_bytes, 0, value_id, originator_id.length, value_bytes.length); HashWrapper x = new HashWrapper(value_id); if ( !values_found_set.contains(x)){ if ( obs_value != null && ! obs_recurse ){ // we have read the marker value, now issue a direct read with the // real key if ( Arrays.equals( obs_value, value_bytes )){ more_to_come = true; final DHTTransportReplyHandlerAdapter f_outer = this; f_closest.sendFindValue( new DHTTransportReplyHandlerAdapter() { public void findValueReply( DHTTransportContact contact, DHTTransportValue[] values, byte diversification_type, boolean more_to_come ) { if ( diversification_type == DHT.DT_NONE ){ f_outer.findValueReply( contact, values, (byte)99, false ); } } public void failed( DHTTransportContact contact, Throwable error ) { f_outer.failed( contact, error ); } }, _lookup_id, 1, flags ); break; } }else{ new_values++; values_found_set.add(x); handler.read(contact, values[i]); } } } } try { contacts_to_query_mon.enter(); if (!more_to_come) value_replies++; values_found += new_values; } finally { contacts_to_query_mon.exit(); } } finally { if (!more_to_come) { try { contacts_to_query_mon.enter(); active_searches--; } finally { contacts_to_query_mon.exit(); } release(); } } } public void findValueReply(DHTTransportContact contact, DHTTransportContact[] contacts) { findNodeReply(contact, contacts); } public void failed(DHTTransportContact target_contact, Throwable error) { try { // if at least one reply has been received then we // don't treat subsequent failure as indication of // a contact failure (just packet loss) if (!value_reply_received) { if ( DHTLog.isOn()){ DHTLog.log("findNode/findValue " + DHTLog.getString(target_contact) + " -> failed: " + error.getMessage()); } router.contactDead(target_contact.getID(), false); } } finally { try { contacts_to_query_mon.enter(); active_searches--; } finally { contacts_to_query_mon.exit(); } release(); } } public void keyBlockRequest(DHTTransportContact contact, byte[] request, byte[] key_signature) { // we don't want to kill the contact due to this so indicate that // it is ok by setting the flag if (database.keyBlockRequest(null, request, key_signature) != null) key_blocked = true; } }; router.recordLookup(lookup_id); if (value_search) { int rem = max_values - values_found; if (rem <= 0) { Debug.out("eh?"); rem = 1; } closest.sendFindValue(replyHandler, lookup_id, rem, flags); } else { closest.sendFindNode(replyHandler, lookup_id); } } finally { contacts_to_query_mon.exit(); } } if(terminate){ terminateLookup(false); }else if ( cancelled ){ terminateLookup( true ); } } catch (Throwable e) { Debug.printStackTrace(e); terminateLookup(true); } } public byte[] getTarget() { return (lookup_id); } public String getDescription() { return (description); } }; thread_pool.run( task, high_priority, true); return( task ); } // Request methods public void pingRequest( DHTTransportContact originating_contact ) { if ( DHTLog.isOn()){ DHTLog.log( "pingRequest from " + DHTLog.getString( originating_contact.getID())); } router.contactAlive( originating_contact.getID(), new DHTControlContactImpl(originating_contact)); } public void keyBlockRequest( DHTTransportContact originating_contact, byte[] request, byte[] sig ) { if ( DHTLog.isOn()){ DHTLog.log( "keyBlockRequest from " + DHTLog.getString( originating_contact.getID())); } router.contactAlive( originating_contact.getID(), new DHTControlContactImpl(originating_contact)); database.keyBlockRequest( originating_contact, request, sig ); } public DHTTransportStoreReply storeRequest( DHTTransportContact originating_contact, byte[][] keys, DHTTransportValue[][] value_sets ) { byte[] originator_id = originating_contact.getID(); router.contactAlive( originator_id, new DHTControlContactImpl(originating_contact)); if ( DHTLog.isOn()){ DHTLog.log( "storeRequest from " + DHTLog.getString( originating_contact )+ ", keys = " + keys.length ); } byte[] diverse_res = new byte[ keys.length]; Arrays.fill( diverse_res, DHT.DT_NONE ); if ( keys.length != value_sets.length ){ Debug.out( "DHTControl:storeRequest - invalid request received from " + originating_contact.getString() + ", keys and values length mismatch"); return( new DHTTransportStoreReplyImpl( diverse_res )); } DHTStorageBlock blocked_details = null; // System.out.println( "storeRequest: received " + originating_contact.getRandomID() + " from " + originating_contact.getAddress()); //System.out.println( "store request: keys=" + keys.length ); if ( keys.length > 0 ){ boolean cache_forward = false; for ( DHTTransportValue[] values: value_sets ){ for ( DHTTransportValue value: values ){ if ( !Arrays.equals( originator_id, value.getOriginator().getID())){ cache_forward = true; break; } } if ( cache_forward ){ break; } } // don't start accepting cache forwards until we have a good idea of our // acceptable key space if ( cache_forward && !isSeeded()){ //System.out.println( "not seeded" ); if ( DHTLog.isOn()){ DHTLog.log( "Not storing keys as not yet seeded" ); } }else if ( !verifyContact( originating_contact, !cache_forward )){ //System.out.println( "verification fail" ); logger.log( "Verification of contact '" + originating_contact.getName() + "' failed for store operation" ); }else{ // get the closest contacts to me byte[] my_id = local_contact.getID(); int c_factor = router.getK(); if ( adapter.getStorageAdapter().getNetwork() != DHT.NW_CVS ){ c_factor += ( c_factor/2 ); } boolean store_it = true; if ( cache_forward ){ long now = SystemTime.getMonotonousTime(); if ( now - rbs_time < 10*1000 && Arrays.equals( originator_id, rbs_id )){ // System.out.println( "contact too far away - repeat" ); store_it = false; }else{ // make sure the originator is in our group Listclosest_contacts = getClosestContactsList( my_id, c_factor, true ); DHTTransportContact furthest = closest_contacts.get( closest_contacts.size()-1); if ( computeAndCompareDistances( furthest.getID(), originator_id, my_id ) < 0 ){ rbs_id = originator_id; rbs_time = now; // System.out.println( "contact too far away" ); if ( DHTLog.isOn()){ DHTLog.log( "Not storing keys as cache forward and sender too far away" ); } store_it = false; } } } if ( store_it ){ for (int i=0;i keys ) { router.contactAlive( originating_contact.getID(), new DHTControlContactImpl(originating_contact)); if ( DHTLog.isOn()){ DHTLog.log( "queryStoreRequest from " + DHTLog.getString( originating_contact )+ ", header_len=" + header_len + ", keys=" + keys.size()); } int rand = generateSpoofID( originating_contact ); originating_contact.setRandomID( rand ); return( database.queryStore( originating_contact, header_len, keys )); } public DHTTransportContact[] findNodeRequest( DHTTransportContact originating_contact, byte[] id ) { if ( DHTLog.isOn()){ DHTLog.log( "findNodeRequest from " + DHTLog.getString( originating_contact.getID())); } router.contactAlive( originating_contact.getID(), new DHTControlContactImpl(originating_contact)); List l; if ( id.length == router.getID().length ){ l = getClosestKContactsList( id, false ); }else{ // this helps both protect against idiot queries and also saved bytes when we use findNode // to just get a random ID prior to cache-forwards l = new ArrayList(); } final DHTTransportContact[] res = new DHTTransportContact[l.size()]; l.toArray( res ); int rand = generateSpoofID( originating_contact ); originating_contact.setRandomID( rand ); return( res ); } public DHTTransportFindValueReply findValueRequest( DHTTransportContact originating_contact, byte[] key, int max_values, byte flags ) { if ( DHTLog.isOn()){ DHTLog.log( "findValueRequest from " + DHTLog.getString( originating_contact.getID())); } DHTDBLookupResult result = database.get( originating_contact, new HashWrapper( key ), max_values, flags, true ); if ( result != null ){ router.contactAlive( originating_contact.getID(), new DHTControlContactImpl(originating_contact)); DHTStorageBlock block_details = database.getKeyBlockDetails( key ); if ( block_details == null ){ return( new DHTTransportFindValueReplyImpl( result.getDiversificationType(), result.getValues())); }else{ return( new DHTTransportFindValueReplyImpl( block_details.getRequest(), block_details.getCertificate())); } }else{ return( new DHTTransportFindValueReplyImpl( findNodeRequest( originating_contact, key ))); } } public DHTTransportFullStats statsRequest( DHTTransportContact contact ) { return( stats ); } protected void requestPing( DHTRouterContact contact ) { ((DHTControlContactImpl)contact.getAttachment()).getTransportContact().sendPing( new DHTTransportReplyHandlerAdapter() { public void pingReply( DHTTransportContact _contact ) { if ( DHTLog.isOn()){ DHTLog.log( "ping OK " + DHTLog.getString( _contact )); } router.contactAlive( _contact.getID(), new DHTControlContactImpl(_contact)); } public void failed( DHTTransportContact _contact, Throwable _error ) { if ( DHTLog.isOn()){ DHTLog.log( "ping " + DHTLog.getString( _contact ) + " -> failed: " + _error.getMessage()); } router.contactDead( _contact.getID(), false ); } }); } protected void nodeAddedToRouter( DHTRouterContact new_contact ) { if ( DISABLE_REPLICATE_ON_JOIN ){ if ( !new_contact.hasBeenAlive()){ requestPing( new_contact ); } return; } // ignore ourselves if ( router.isID( new_contact.getID())){ return; } // when a new node is added we must check to see if we need to transfer // any of our values to it. Map keys_to_store = new HashMap(); DHTStorageBlock[] direct_key_blocks = database.getDirectKeyBlocks(); if ( database.isEmpty() && direct_key_blocks.length == 0 ){ // nothing to do, ping it if it isn't known to be alive if ( !new_contact.hasBeenAlive()){ requestPing( new_contact ); } return; } // see if we're one of the K closest to the new node // optimise to avoid calculating for things obviously too far away boolean perform_closeness_check = true; byte[] router_id = router.getID(); byte[] contact_id = new_contact.getID(); byte[] distance = computeDistance( router_id, contact_id ); long now = SystemTime.getCurrentTime(); byte[] nacul = node_add_check_uninteresting_limit; // time limit to pick up router changes caused by contacts being deleted if ( now - last_node_add_check < 30*1000 && nacul != null ){ int res = compareDistances( nacul, distance ); /* System.out.println( "r=" + ByteFormatter.encodeString( router_id ) + ",c=" + ByteFormatter.encodeString( contact_id ) + ",d=" + ByteFormatter.encodeString( distance ) + ",l=" + ByteFormatter.encodeString( nacul ) + ",r=" + res ); */ if ( res < 0 ){ perform_closeness_check = false; } }else{ last_node_add_check = now; node_add_check_uninteresting_limit = nacul = null; } boolean close = false; if ( perform_closeness_check ){ List closest_contacts = getClosestKContactsList( new_contact.getID(), false ); for (int i=0;i 0 ){ node_add_check_uninteresting_limit = distance; } } } } if ( !close ){ if ( !new_contact.hasBeenAlive()){ requestPing( new_contact ); } return; } // System.out.println( "Node added to router: id=" + ByteFormatter.encodeString( contact_id )); // ok, we're close enough to worry about transferring values Iterator it = database.getKeys(); while( it.hasNext()){ HashWrapper key = (HashWrapper)it.next(); byte[] encoded_key = key.getHash(); if ( database.isKeyBlocked( encoded_key )){ continue; } DHTDBLookupResult result = database.get( null, key, 0, (byte)0, false ); if ( result == null ){ // deleted in the meantime continue; } // even if a result has been diversified we continue to maintain the base value set // until the original publisher picks up the diversification (next publish period) and // publishes to the correct place DHTDBValue[] values = result.getValues(); if ( values.length == 0 ){ continue; } // we don't consider any cached further away than the initial location, for transfer // however, we *do* include ones we originate as, if we're the closest, we have to // take responsibility for xfer (as others won't) List sorted_contacts = getClosestKContactsList( encoded_key, false ); // if we're closest to the key, or the new node is closest and // we're second closest, then we take responsibility for storing // the value boolean store_it = false; if ( sorted_contacts.size() > 0 ){ DHTTransportContact first = (DHTTransportContact)sorted_contacts.get(0); if ( router.isID( first.getID())){ store_it = true; }else if ( Arrays.equals( first.getID(), new_contact.getID()) && sorted_contacts.size() > 1 ){ store_it = router.isID(((DHTTransportContact)sorted_contacts.get(1)).getID()); } } if ( store_it ){ List values_to_store = new ArrayList(values.length); for (int i=0;i 0 ){ it = keys_to_store.entrySet().iterator(); final byte[][] keys = new byte[keys_to_store.size()][]; final DHTTransportValue[][] value_sets = new DHTTransportValue[keys.length][]; int index = 0; while( it.hasNext()){ Map.Entry entry = (Map.Entry)it.next(); HashWrapper key = (HashWrapper)entry.getKey(); List values = (List)entry.getValue(); keys[index] = key.getHash(); value_sets[index] = new DHTTransportValue[values.size()]; for (int i=0;i failed: " + _error.getMessage()); } router.contactDead( _contact.getID(), false); } public void keyBlockRequest( DHTTransportContact contact, byte[] request, byte[] signature ) { database.keyBlockRequest( null, request, signature ); } }, keys, value_sets, false ); } public void failed( DHTTransportContact _contact, Throwable _error ) { // System.out.println( "nodeAdded: pre-store findNode Failed" ); if ( DHTLog.isOn()){ DHTLog.log( "pre-store findNode failed " + DHTLog.getString( _contact ) + " -> failed: " + _error.getMessage()); } router.contactDead( _contact.getID(), false); } }, t_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20] ); }else{ if ( !new_contact.hasBeenAlive()){ requestPing( new_contact ); } } // finally transfer any key-blocks if ( t_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_BLOCK_KEYS ){ for (int i=0;i failed: " + _error.getMessage()); } } }, key_block.getRequest(), key_block.getCertificate()); } }; if ( anti_spoof_done[0] ){ task.run(); }else{ t_contact.sendFindNode( new DHTTransportReplyHandlerAdapter() { public void findNodeReply( DHTTransportContact contact, DHTTransportContact[] contacts ) { task.run(); } public void failed( DHTTransportContact _contact, Throwable _error ) { // System.out.println( "nodeAdded: pre-store findNode Failed" ); if ( DHTLog.isOn()){ DHTLog.log( "pre-kb findNode failed " + DHTLog.getString( _contact ) + " -> failed: " + _error.getMessage()); } router.contactDead( _contact.getID(), false); } }, t_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20] ); } } } } protected Set getClosestContactsSet( byte[] id, int num_to_return, boolean live_only ) { List l = router.findClosestContacts( id, num_to_return, live_only ); Set sorted_set = new sortedTransportContactSet( id, true ).getSet(); // profilers says l.size() is taking CPU (!) so put it into a variable // this is safe since the list returned is created for us only long size = l.size(); for (int i=0;i getClosestKContactsList( byte[] id, boolean live_only ) { return( getClosestContactsList( id, K, live_only )); } public List getClosestContactsList( byte[] id, int num_to_return, boolean live_only ) { Set sorted_set = getClosestContactsSet( id, num_to_return, live_only ); List res = new ArrayList(num_to_return); Iterator it = sorted_set.iterator(); while( it.hasNext() && res.size() < num_to_return ){ res.add( it.next()); } return( res ); } protected boolean isIDInClosestContacts( byte[] test_id, byte[] target_id, int num_to_consider, boolean live_only ) { List l = router.findClosestContacts( target_id, num_to_consider, live_only ); boolean found = false; int num_closer = 0; for ( DHTRouterContact c: l ){ byte[] c_id = c.getID(); if ( Arrays.equals( test_id, c_id )){ found = true; }else{ if ( computeAndCompareDistances( c_id, test_id, target_id ) < 0 ){ num_closer++; } } } return( found && num_closer < num_to_consider ); } protected byte[] encodeKey( byte[] key ) { byte[] temp = new SHA1Simple().calculateHash( key ); byte[] result = new byte[node_id_byte_count]; System.arraycopy( temp, 0, result, 0, node_id_byte_count ); return( result ); } public int computeAndCompareDistances( byte[] t1, byte[] t2, byte[] pivot ) { return( computeAndCompareDistances2( t1, t2, pivot )); } protected static int computeAndCompareDistances2( byte[] t1, byte[] t2, byte[] pivot ) { for (int i=0;i n1 < n2 * @param n1 * @param n2 * @return */ public int compareDistances( byte[] n1, byte[] n2 ) { return( compareDistances2( n1,n2 )); } protected static int compareDistances2( byte[] n1, byte[] n2 ) { for (int i=0;i 0 ){ try{ estimate_mon.enter(); remote_estimate_values.add( new Integer( size )); if ( remote_estimate_values.size() > REMOTE_ESTIMATE_HISTORY ){ remote_estimate_values.remove(0); } }finally{ estimate_mon.exit(); } } // System.out.println( "estimated dht size: " + size ); } public int getTransportEstimatedDHTSize() { return((int)local_dht_estimate ); } public int getEstimatedDHTSize() { // public method, trigger actual computation periodically long now = SystemTime.getCurrentTime(); long diff = now - last_dht_estimate_time; if ( diff < 0 || diff > 60*1000 ){ estimateDHTSize( router.getID(), null, router.getK()); } // with recent changes we pretty much have a router that only contains routeable contacts // therefore the apparent size of the DHT is less than real and we need to adjust by the // routeable percentage to get an accurate figure int percent = transport.getStats().getRouteablePercentage(); // current assumption is that around 50% are firewalled, so if less (at least during migration) assume unusable if ( percent < 25 ){ return((int)combined_dht_estimate ); } double mult = 100.0 / percent; return((int)( mult * combined_dht_estimate )); } protected void estimateDHTSize( byte[] id, Map contacts, int contacts_to_use ) { // if called with contacts then this is in internal estimation based on lookup values long now = SystemTime.getCurrentTime(); long diff = now - last_dht_estimate_time; // 5 second limiter here if ( diff < 0 || diff > 5*1000 ){ try{ estimate_mon.enter(); last_dht_estimate_time = now; List l; if ( contacts == null ){ l = getClosestKContactsList( id, false ); }else{ Set sorted_set = new sortedTransportContactSet( id, true ).getSet(); sorted_set.addAll( contacts.values()); l = new ArrayList( sorted_set ); if ( l.size() > 0 ){ // algorithm works relative to a starting point in the ID space so we grab // the first here rather than using the initial lookup target id = ((DHTTransportContact)l.get(0)).getID(); } /* String str = ""; for (int i=0;i 2 ){ /* if you call N0 yourself, N1 the nearest peer, N2 the 2nd nearest peer ... Np the pth nearest peer that you know (for example, N1 .. N20) and if you call D1 the Kad distance between you and N1, D2 between you and N2 ... then you have to compute : Dc = sum(i * Di) / sum( i * i) and then : NbPeers = 2^160 / Dc */ BigInteger sum1 = new BigInteger("0"); BigInteger sum2 = new BigInteger("0"); // first entry should be us for (int i=1;i" + dht_estimate + " (id=" + DHTLog.getString2(id) + ",cont=" + (contacts==null?"null":(""+contacts.size())) + ",use=" + contacts_to_use ); } List rems = new ArrayList(new TreeSet( remote_estimate_values )); // ignore largest and smallest few values long rem_average = local_dht_estimate; int rem_vals = 1; for (int i=3;i " + ok + ", version = " + c.getProtocolVersion()); } return( ok ); } public List getContacts() { List contacts = router.getAllContacts(); List res = new ArrayList( contacts.size()); for (int i=0;i tree_set; private byte[] pivot; private boolean ascending; protected sortedTransportContactSet( byte[] _pivot, boolean _ascending ) { pivot = _pivot; ascending = _ascending; tree_set = new TreeSet( new Comparator() { public int compare( DHTTransportContact t1, DHTTransportContact t2 ) { // this comparator ensures that the closest to the key // is first in the iterator traversal int distance = computeAndCompareDistances2( t1.getID(), t2.getID(), pivot ); if ( ascending ){ return( distance ); }else{ return( -distance ); } } }); } public Set getSet() { return( tree_set ); } } protected static class DHTOperationListenerDemuxer implements DHTOperationListener { private AEMonitor this_mon = new AEMonitor( "DHTOperationListenerDemuxer" ); private DHTOperationListener delegate; private boolean complete_fired; private boolean complete_included_ok; private int complete_count = 0; protected DHTOperationListenerDemuxer( DHTOperationListener _delegate ) { delegate = _delegate; if ( delegate == null ){ Debug.out( "invalid: null delegate" ); } } public void incrementCompletes() { try{ this_mon.enter(); complete_count++; }finally{ this_mon.exit(); } } public void searching( DHTTransportContact contact, int level, int active_searches ) { delegate.searching( contact, level, active_searches ); } public void diversified( String desc ) { delegate.diversified( desc ); } public void found( DHTTransportContact contact, boolean is_closest ) { delegate.found( contact, is_closest ); } public void read( DHTTransportContact contact, DHTTransportValue value ) { delegate.read( contact, value ); } public void wrote( DHTTransportContact contact, DHTTransportValue value ) { delegate.wrote( contact, value ); } public void complete( boolean timeout ) { boolean fire = false; try{ this_mon.enter(); if ( !timeout ){ complete_included_ok = true; } complete_count--; if (complete_count <= 0 && !complete_fired ){ complete_fired = true; fire = true; } }finally{ this_mon.exit(); } if ( fire ){ delegate.complete( !complete_included_ok ); } } } abstract static class lookupResultHandler extends DHTOperationListenerDemuxer { protected lookupResultHandler( DHTOperationListener delegate ) { super( delegate ); } public abstract void closest( List res ); public abstract void diversify( DHTTransportContact cause, byte diversification_type ); } protected static class DHTTransportFindValueReplyImpl implements DHTTransportFindValueReply { private byte dt = DHT.DT_NONE; private DHTTransportValue[] values; private DHTTransportContact[] contacts; private byte[] blocked_key; private byte[] blocked_sig; protected DHTTransportFindValueReplyImpl( byte _dt, DHTTransportValue[] _values ) { dt = _dt; values = _values; boolean copied = false; for (int i=0;i key_details ) { delegate.sendQueryStore( handler, header_length, key_details ); } public void sendFindNode( DHTTransportReplyHandler handler, byte[] id ) { delegate.sendFindNode(handler, id); } public void sendFindValue( DHTTransportReplyHandler handler, byte[] key, int max_values, byte flags ) { delegate.sendFindValue(handler, key, max_values, flags); } public void sendKeyBlock( DHTTransportReplyHandler handler, byte[] key_block_request, byte[] key_block_signature ) { delegate.sendKeyBlock(handler, key_block_request, key_block_signature); } public DHTTransportFullStats getStats() { return( delegate.getStats()); } public void exportContact( DataOutputStream os ) throws IOException, DHTTransportException { delegate.exportContact( os ); } public void remove() { delegate.remove(); } public DHTNetworkPosition[] getNetworkPositions() { return( delegate.getNetworkPositions()); } public DHTNetworkPosition getNetworkPosition( byte position_type ) { return( delegate.getNetworkPosition( position_type )); } public DHTTransport getTransport() { return( delegate.getTransport()); } public String getString() { return( delegate.getString()); } } protected static class DHTTransportStoreReplyImpl implements DHTTransportStoreReply { private byte[] divs; private byte[] block_request; private byte[] block_sig; protected DHTTransportStoreReplyImpl( byte[] _divs ) { divs = _divs; } protected DHTTransportStoreReplyImpl( byte[] _bk, byte[] _bs ) { block_request = _bk; block_sig = _bs; } public byte[] getDiversificationTypes() { return( divs ); } public boolean blocked() { return( block_request != null ); } public byte[] getBlockRequest() { return( block_request ); } public byte[] getBlockSignature() { return( block_sig ); } } protected abstract class DhtTask extends ThreadPoolTask { private controlActivity activity; protected DhtTask( ThreadPool thread_pool ) { activity = new controlActivity( thread_pool, this ); try{ activity_mon.enter(); activities.add( activity ); listeners.dispatch( DHTControlListener.CT_ADDED, activity ); // System.out.println( "activity added:" + activities.size()); }finally{ activity_mon.exit(); } } public void taskStarted() { listeners.dispatch( DHTControlListener.CT_CHANGED, activity ); //System.out.println( "activity changed:" + activities.size()); } public void taskCompleted() { try{ activity_mon.enter(); activities.remove( activity ); listeners.dispatch( DHTControlListener.CT_REMOVED, activity ); // System.out.println( "activity removed:" + activities.size()); }finally{ activity_mon.exit(); } } public void interruptTask() { } protected abstract void cancel(); public abstract byte[] getTarget(); public abstract String getDescription(); } protected static class DhtTaskSet { private boolean cancelled; private Object things; private void add( DhtTask task ) { synchronized( this ){ if ( cancelled ){ task.cancel(); return; } addToThings( task ); } } private void add( DhtTaskSet task_set ) { synchronized( this ){ if ( cancelled ){ task_set.cancel(); return; } addToThings( task_set ); } } private void addToThings( Object obj ) { if ( things == null ){ things = obj; }else{ if ( things instanceof List ){ ((List)things).add( obj ); }else{ List l = new ArrayList(2); l.add( things ); l.add( obj ); things = l; } } } private void cancel() { Object to_cancel; synchronized( this ){ if ( cancelled ){ return; } cancelled = true; to_cancel = things; things = null; } if ( to_cancel != null ){ if ( to_cancel instanceof DhtTask ){ ((DhtTask)to_cancel).cancel(); }else if ( to_cancel instanceof DhtTaskSet ){ ((DhtTaskSet)to_cancel).cancel(); }else{ List l = (List)to_cancel; for (int i=0;i " + ByteFormatter.nicePrint(d1)); System.out.println( "dist:" + ByteFormatter.nicePrint((byte[])o2) + " -> " + ByteFormatter.nicePrint(d2)); return( DHTControlImpl.compareDistances2( d1, d2 )); } }); set.add( t1 ); set.add( t2 ); //set.add( new byte[]{ (byte)0xF0, (byte)0x48 ,(byte)0x3F, (byte)0x25 }); //set.add( new byte[]{ (byte)0xF1, (byte)0xF8, (byte)0x36, (byte)0xCB }); //set.add( new byte[]{ (byte)0xF2, (byte)0x2F, (byte)0xE1, (byte)0x0D }); Iterator it = set.iterator(); while( it.hasNext()){ byte[] val = (byte[])it.next(); System.out.println( ByteFormatter.nicePrint( val )); } } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/control/DHTControlFactory.java0000644000175000017500000000345710423311516026113 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.control; import com.aelitis.azureus.core.dht.DHTLogger; import com.aelitis.azureus.core.dht.control.impl.DHTControlImpl; import com.aelitis.azureus.core.dht.transport.DHTTransport; /** * @author parg * */ public class DHTControlFactory { public static DHTControl create( DHTControlAdapter adapter, DHTTransport transport, int K, int B, int max_rep_per_node, int search_concurrency, int lookup_concurrency, int original_republish_interval, int cache_republish_interval, int cache_at_closest_n, DHTLogger logger ) { return( new DHTControlImpl( adapter, transport, K, B, max_rep_per_node, search_concurrency, lookup_concurrency, original_republish_interval, cache_republish_interval, cache_at_closest_n, logger)); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/control/DHTControlStats.java0000644000175000017500000000251410373051004025570 0ustar adrianadrian/* * Created on 21-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.control; /** * @author parg * */ public interface DHTControlStats { /** * Uptime of the latest router instance * @return */ public long getRouterUptime(); /** * Number of routers instantiated - new one created if our external IP changes * @return */ public int getRouterCount(); public long getEstimatedDHTSize(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/control/DHTControlActivity.java0000644000175000017500000000261410373051004026267 0ustar adrianadrian/* * Created on 22-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.control; /** * @author parg * */ public interface DHTControlActivity { public static final int AT_INTERNAL_GET = 1; public static final int AT_EXTERNAL_GET = 2; public static final int AT_INTERNAL_PUT = 3; public static final int AT_EXTERNAL_PUT = 4; public byte[] getTarget(); public String getDescription(); public int getType(); public boolean isQueued(); public String getString(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/control/DHTControlListener.java0000644000175000017500000000233710373051004026262 0ustar adrianadrian/* * Created on 26-Apr-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.control; public interface DHTControlListener { public static final int CT_ADDED = 1; public static final int CT_CHANGED = 2; public static final int CT_REMOVED = 3; public void activityChanged( DHTControlActivity activity, int type ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/control/DHTControlContact.java0000644000175000017500000000236710373051004026073 0ustar adrianadrian/* * Created on 22-Jun-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.control; import com.aelitis.azureus.core.dht.router.DHTRouterContact; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; public interface DHTControlContact { public DHTRouterContact getRouterContact(); public DHTTransportContact getTransportContact(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/control/DHTControl.java0000644000175000017500000001140211274446322024561 0ustar adrianadrian/* * Created on 12-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.control; import java.io.IOException; import java.io.DataInputStream; import java.io.DataOutputStream; import java.util.List; import com.aelitis.azureus.core.dht.DHTOperationListener; import com.aelitis.azureus.core.dht.db.DHTDB; import com.aelitis.azureus.core.dht.router.DHTRouter; import com.aelitis.azureus.core.dht.transport.*; /** * @author parg * */ public interface DHTControl { public static final int K_DEFAULT = 20; public static final int B_DEFAULT = 4; public static final int MAX_REP_PER_NODE_DEFAULT = 5; public static final int SEARCH_CONCURRENCY_DEFAULT = 5; public static final int LOOKUP_CONCURRENCY_DEFAULT = 10; public static final int CACHE_AT_CLOSEST_N_DEFAULT = 1; public static final int ORIGINAL_REPUBLISH_INTERVAL_DEFAULT = 8*60*60*1000; public static final int CACHE_REPUBLISH_INTERVAL_DEFAULT = 30*60*1000; public void seed( boolean full_wait ); public boolean isSeeded(); public void put( byte[] key, String description, byte[] value, byte flags, byte life_hours, byte replication_control, boolean high_priority, DHTOperationListener listener ); public boolean isDiversified( byte[] key ); public DHTTransportValue getLocalValue( byte[] key ); public void get( byte[] key, String description, byte flags, int max_values, long timeout, boolean exhaustive, boolean high_priority, DHTOperationListener listener ); public byte[] remove( byte[] key, String description, DHTOperationListener listener ); public byte[] remove( DHTTransportContact[] contacts, byte[] key, String description, DHTOperationListener listener ); public DHTControlStats getStats(); public DHTTransport getTransport(); public DHTRouter getRouter(); public DHTDB getDataBase(); public DHTControlActivity[] getActivities(); public void exportState( DataOutputStream os, int max ) throws IOException; public void importState( DataInputStream is ) throws IOException; // support methods for DB public List getClosestKContactsList( byte[] id, boolean live_only ); public List getClosestContactsList( byte[] id, int num_to_return, boolean live_only ); public void putEncodedKey( byte[] key, String description, DHTTransportValue value, long timeout, boolean original_mappings ); public void putDirectEncodedKeys( byte[][] keys, String description, DHTTransportValue[][] value_sets, List contacts ); public void putDirectEncodedKeys( byte[][] keys, String description, DHTTransportValue[][] value_sets, DHTTransportContact contact, DHTOperationListener listener ); public int computeAndCompareDistances( byte[] n1, byte[] n2, byte[] pivot ); public byte[] computeDistance( byte[] n1, byte[] n2 ); public int compareDistances( byte[] n1, byte[] n2 ); public boolean verifyContact( DHTTransportContact c, boolean direct ); public boolean lookup( byte[] id, String description, long timeout, DHTOperationListener listener ); public boolean lookupEncoded( byte[] id, String description, long timeout, boolean high_priority, DHTOperationListener listener ); public byte[] getObfuscatedKey( byte[] plain_key ); /** * Returns a list of DHTTransportContact objects * @return */ public List getContacts(); // debug method only public void pingAll(); public void addListener( DHTControlListener l ); public void removeListener( DHTControlListener l ); public void print( boolean full ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/DHTLogger.java0000644000175000017500000000255610373051006022700 0ustar adrianadrian/* * Created on 09-Aug-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht; import org.gudy.azureus2.plugins.PluginInterface; public interface DHTLogger { public static final int LT_GENERAL = 1; public static final int LT_IP_FILTER = 2; public void log( String str ); public void log( Throwable e ); public void log( int log_type, String str ); public boolean isEnabled( int log_type ); public PluginInterface getPluginInterface(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/speed/0000755000175000017500000000000011310377624021357 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterContact.java0000644000175000017500000000301110656443216026323 0ustar adrianadrian/* * Created on 15-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.speed; import java.net.InetSocketAddress; public interface DHTSpeedTesterContact { public InetSocketAddress getAddress(); public int getPingPeriod(); public void setPingPeriod( int period_secs ); /** * If you don't like the ping times from this contact you can always kill it, a new one will be * created in its place */ public void destroy(); public void addListener( DHTSpeedTesterContactListener listener ); public void removeListener( DHTSpeedTesterContactListener listener ); public String getString(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/speed/impl/0000755000175000017500000000000011310377624022320 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/dht/speed/impl/DHTSpeedTesterImpl.java0000644000175000017500000003556610656443216026616 0ustar adrianadrian/* * Created on 15-Mar-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.speed.impl; import java.net.InetSocketAddress; import java.util.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.utils.UTTimer; import org.gudy.azureus2.plugins.utils.UTTimerEvent; import org.gudy.azureus2.plugins.utils.UTTimerEventPerformer; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionManager; import com.aelitis.azureus.core.dht.speed.DHTSpeedTester; import com.aelitis.azureus.core.dht.speed.DHTSpeedTesterContact; import com.aelitis.azureus.core.dht.speed.DHTSpeedTesterContactListener; import com.aelitis.azureus.core.dht.speed.DHTSpeedTesterListener; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportReplyHandlerAdapter; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.util.bloom.BloomFilter; import com.aelitis.azureus.core.util.bloom.BloomFilterFactory; public class DHTSpeedTesterImpl implements DHTSpeedTester { private static final long PING_TIMEOUT = 5000; private PluginInterface plugin_interface; private DHT dht; private int contact_num; private BloomFilter tried_bloom; private LinkedList pending_contacts = new LinkedList(); private List active_pings = new ArrayList(); private List new_listeners = new ArrayList(); private CopyOnWriteList listeners = new CopyOnWriteList(); public DHTSpeedTesterImpl( DHT _dht ) { dht = _dht; plugin_interface = dht.getLogger().getPluginInterface(); UTTimer timer = plugin_interface.getUtilities().createTimer( "DHTSpeedTester:finder", true ); timer.addPeriodicEvent( 5000, new UTTimerEventPerformer() { public void perform( UTTimerEvent event) { findContacts(); } }); timer.addPeriodicEvent( 1000, new UTTimerEventPerformer() { int tick_count; public void perform( UTTimerEvent event) { try{ pingContacts( tick_count ); }finally{ tick_count++; } } }); } public int getContactNumber() { return( contact_num ); } public void setContactNumber( int number ) { contact_num = number; } protected void findContacts() { DHTTransportContact[] reachables = dht.getTransport().getReachableContacts(); for (int i=0;i 500 ){ tried_bloom = BloomFilterFactory.createAddOnly( 4096 ); } if ( !tried_bloom.contains( address )){ tried_bloom.add( address ); synchronized( pending_contacts ){ potentialPing ping = new potentialPing( contact, DHTNetworkPositionManager.estimateRTT( contact.getNetworkPositions(), dht.getTransport().getLocalContact().getNetworkPositions())); pending_contacts.add( 0, ping ); if ( pending_contacts.size() > 60 ){ pending_contacts.removeLast(); } } } } } protected void pingContacts( int tick_count ) { List copy = null; synchronized( new_listeners ){ if ( new_listeners.size() > 0 ){ copy = new ArrayList( new_listeners ); new_listeners.clear(); } } if ( copy != null ){ for (int i=0;i= 3){ // find best candidates List pps = new ArrayList(); for (int i=0;i<3;i++){ potentialPing pp = (potentialPing)it.next(); pps.add( pp ); it.remove(); synchronized( pending_contacts ){ pending_contacts.remove( pp ); } } active_pings.add( new activePing( pps )); } }else if ( num_active > contact_num ){ for (int i=0;i 0 ){ return( false ); } if ( best_pingee == null ){ dead = true; return( false ); } } if ( tick_count % period == 0 ){ ping( ping_set, best_pingee ); } return( true ); } protected void ping( pingInstanceSet ping_set, DHTTransportContact contact ) { final pingInstance pi = new pingInstance( ping_set ); outstanding++; try{ contact.sendImmediatePing( new DHTTransportReplyHandlerAdapter() { public void pingReply( DHTTransportContact contact ) { int rtt = getElapsed(); try{ synchronized( activePing.this ){ outstanding--; if ( !running ){ if ( rtt < best_ping ){ best_pingee = contact; best_ping = rtt; } if ( outstanding == 0 ){ running = true; } }else{ total_ok++; consec_fails = 0; } } Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((DHTSpeedTesterContactListener)it.next()).ping( activePing.this, getElapsed()); }catch( Throwable e ){ Debug.printStackTrace(e); } } }finally{ pi.setResult( activePing.this, rtt ); } // System.out.println( " " + contact.getString() + ": " + getElapsed() + ", " + contact.getVivaldiPosition().estimateRTT( dht.getTransport().getLocalContact().getVivaldiPosition().getCoordinates())); } public void failed( DHTTransportContact contact, Throwable error ) { try{ synchronized( activePing.this ){ outstanding--; if ( !running ){ if ( outstanding == 0 ){ running = true; } }else{ consec_fails++; total_fails++; if ( consec_fails == 3 ){ dead = true; }else if ( total_ok > 10 && total_fails > 0 && total_ok / total_fails < 1 ){ // failing too often dead = true; }else if ( total_ok > 100 ){ total_ok = 0; total_fails = 0; } } } if ( !dead ){ Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((DHTSpeedTesterContactListener)it.next()).pingFailed( activePing.this ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } // System.out.println( " " + contact.getString() + ": failed" ); }finally{ pi.setResult( activePing.this, -1 ); } } }, PING_TIMEOUT ); }catch( Throwable e ){ pi.setResult( this, -1 ); dead = true; outstanding--; Debug.printStackTrace(e); } } public void destroy() { dead = true; } protected boolean isDead() { return( dead ); } protected boolean isInformedAlive() { return( informed_alive ); } protected void setInformedAlive() { informed_alive = true; } protected void informDead() { if ( informed_alive ){ Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((DHTSpeedTesterContactListener)it.next()).contactDied( this ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } } public DHTTransportContact getContact() { return( best_pingee ); } public InetSocketAddress getAddress() { return( getContact().getAddress()); } public String getString() { return( getContact().getString()); } public int getPingPeriod() { return( period ); } public void setPingPeriod( int _period ) { period = _period; } public void addListener( DHTSpeedTesterContactListener listener ) { listeners.add( listener ); } public void removeListener( DHTSpeedTesterContactListener listener ) { listeners.remove( listener ); } } protected class pingInstance { private activePing contact; private pingInstanceSet set; private int result; protected pingInstance( pingInstanceSet _set ) { set = _set; set.add( this ); } protected activePing getContact() { return( contact ); } protected int getResult() { return( result ); } protected void setResult( activePing _contact, int _result ) { contact = _contact; result = _result; set.complete( this ); } } protected class pingInstanceSet { private boolean active; private int instances; private boolean full; List results = new ArrayList(); protected pingInstanceSet( boolean _active ) { active = _active; } protected void add( pingInstance instance ) { synchronized( this ){ instances++; } } protected void setFull() { synchronized( this ){ full = true; if ( results.size() == instances ){ sendResult(); } } } protected void complete( pingInstance instance ) { synchronized( this ){ results.add( instance ); if ( results.size() == instances && full ){ sendResult(); } } } protected void sendResult() { if ( active && results.size() > 0 ){ DHTSpeedTesterContact[] contacts = new DHTSpeedTesterContact[results.size()]; int[] rtts = new int[contacts.length]; for (int i=0;i 30000 ){ for (int i=0;i 0 ){ // take most recent alive one and add to buckets boolean replaced = false; for (int i=replacements.size()-1;i>=0;i--){ DHTRouterContactImpl rep = (DHTRouterContactImpl)replacements.get(i); if ( rep.hasBeenAlive()){ DHTLog.log( DHTLog.getString( contact.getID()) + ": using live replacement " + DHTLog.getString(rep.getID())); // MGP: notify that a replacement was promoted to the bucket rep.setBucketEntry(); router.notifyLocationChanged(rep); replacements.remove( rep ); buckets.add( rep ); replaced = true; requestNodeAdd( rep, false ); break; } } // non alive - just take most recently added if ( !replaced ){ DHTRouterContactImpl rep = (DHTRouterContactImpl)replacements.remove( replacements.size() - 1 ); DHTLog.log( DHTLog.getString( contact.getID()) + ": using unknown replacement " + DHTLog.getString(rep.getID())); // MGP: notify that a replacement was promoted to the bucket rep.setBucketEntry(); router.notifyLocationChanged(rep); buckets.add( rep ); // add-node logic will ping the node if its not known to // be alive requestNodeAdd( rep, false ); } } }else{ if (!was_failing) { // MGP: first notify observers that now failing router.notifyNowFailing(contact); } // MGP: notify that removed from replacement list router.notifyRemoved(contact); replacements.remove( contact ); } } } protected void requestNodeAdd( DHTRouterContactImpl contact, boolean definite_change ) { // DOS problem here - if a node deliberately flicked between // instance IDs we'll get into an update frenzy. long now = SystemTime.getCurrentTime(); if ( now - contact.getLastAddedTime() > 10000 ){ contact.setLastAddedTime( now ); router.requestNodeAdd( contact ); }else{ // only produce a warning if this is a definite change from one id to // another (as opposed to a change from "unknown" to another) if ( definite_change ){ router.log( "requestNodeAdd for " + contact.getString() + " denied as too soon after previous "); } } } protected long getTimeSinceLastLookup() { long now = SystemTime.getCurrentTime(); if ( now < last_lookup_time ){ // clock changed, don't know so make as large as possible return( Long.MAX_VALUE ); } return( now - last_lookup_time ); } protected void setLastLookupTime() { last_lookup_time = SystemTime.getCurrentTime(); } public void print( String indent, String prefix ) { if ( left == null ){ router.log( indent + prefix + ": buckets = " + buckets.size() + contactsToString( buckets) + ", replacements = " + (replacements==null?"null":( replacements.size() + contactsToString( replacements ))) + (contains_router_node_id?" *":" ") + (this==router.getSmallestSubtree()?"SST":"") + " tsll=" + getTimeSinceLastLookup()); }else{ router.log( indent + prefix + ":" + (contains_router_node_id?" *":" ") + (this==router.getSmallestSubtree()?"SST":"")); left.print( indent + " ", prefix + "1" ); right.print( indent + " ", prefix + "0" ); } } protected String contactsToString( List contacts ) { String res = "{"; for (int i=0;i 0 ){ seed_in_ticks--; if ( seed_in_ticks == 0 ){ seedSupport(); } } } }); } protected void notifyAdded(DHTRouterContact contact) { for (Iterator i = observers.iterator(); i.hasNext(); ) { DHTRouterObserver rto = (DHTRouterObserver) i.next(); try{ rto.added(contact); }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected void notifyRemoved(DHTRouterContact contact) { for (Iterator i = observers.iterator(); i.hasNext(); ) { DHTRouterObserver rto = (DHTRouterObserver) i.next(); try{ rto.removed(contact); }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected void notifyLocationChanged(DHTRouterContact contact) { for (Iterator i = observers.iterator(); i.hasNext(); ) { DHTRouterObserver rto = (DHTRouterObserver) i.next(); try{ rto.locationChanged(contact); }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected void notifyNowAlive(DHTRouterContact contact) { for (Iterator i = observers.iterator(); i.hasNext(); ) { DHTRouterObserver rto = (DHTRouterObserver) i.next(); try{ rto.nowAlive(contact); }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected void notifyNowFailing(DHTRouterContact contact) { for (Iterator i = observers.iterator(); i.hasNext(); ) { DHTRouterObserver rto = (DHTRouterObserver) i.next(); try{ rto.nowFailing(contact); }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected void notifyDead() { for (Iterator i = observers.iterator(); i.hasNext(); ) { DHTRouterObserver rto = (DHTRouterObserver) i.next(); try{ rto.destroyed(this); }catch( Throwable e ){ Debug.printStackTrace(e); } } } public boolean addObserver(DHTRouterObserver rto) { if ((rto != null) && !observers.contains(rto)) { observers.add(rto); return true; } return false; } public boolean containsObserver(DHTRouterObserver rto) { return ((rto != null) && observers.contains(rto)); } public boolean removeObserver(DHTRouterObserver rto) { return ((rto != null) && observers.remove(rto)); } public DHTRouterStats getStats() { return( stats ); } public int getK() { return( K ); } public byte[] getID() { return( router_node_id ); } public boolean isID( byte[] id ) { return( Arrays.equals( id, router_node_id )); } public DHTRouterContact getLocalContact() { return( local_contact ); } public void setAdapter( DHTRouterAdapter _adapter ) { adapter = _adapter; } public void contactKnown( byte[] node_id, DHTRouterContactAttachment attachment ) { if ( recent_contact_bloom.contains( node_id )){ return; } recent_contact_bloom.add( node_id ); addContact( node_id, attachment, false ); } public DHTRouterContact contactAlive( byte[] node_id, DHTRouterContactAttachment attachment ) { return( addContact( node_id, attachment, true )); } // all incoming node actions come through either contactDead or addContact // A side effect of processing // the node is that either a ping can be requested (if a replacement node // is available and the router wants to check the liveness of an existing node) // or a new node can be added (either directly to a node or indirectly via // a replacement becoming "live" // To avoid requesting these actions while synchronised these are recorded // in lists and then kicked off separately here public DHTRouterContact contactDead( byte[] node_id, boolean force ) { if ( Arrays.equals( router_node_id, node_id )){ // we should never become dead ourselves as this screws up things like // checking that stored values are close enough to the K livest nodes (as if we are // dead we don't return ourselves and it all goes doo daa ) Debug.out( "DHTRouter: contactDead called on router node!" ); return( local_contact ); } try{ try{ this_mon.enter(); consecutive_dead++; /* if ( consecutive_dead != 0 && consecutive_dead % 10 == 0 ){ System.out.println( "consecutive_dead: " + consecutive_dead ); } */ Object[] res = findContactSupport( node_id ); DHTRouterNodeImpl node = (DHTRouterNodeImpl)res[0]; DHTRouterContactImpl contact = (DHTRouterContactImpl)res[1]; if ( contact != null ){ // some protection against network drop outs - start ignoring dead // notifications if we're getting significant continous fails if ( consecutive_dead < 100 || force ){ node.dead( contact, force ); } } return( contact ); }finally{ this_mon.exit(); } }finally{ dispatchPings(); dispatchNodeAdds(); } } public void contactRemoved( byte[] node_id ) { } public DHTRouterContact addContact( byte[] node_id, DHTRouterContactAttachment attachment, boolean known_to_be_alive ) { try{ try{ this_mon.enter(); if ( known_to_be_alive ){ consecutive_dead = 0; } return( addContactSupport( node_id, attachment, known_to_be_alive )); }finally{ this_mon.exit(); } }finally{ dispatchPings(); dispatchNodeAdds(); } } protected DHTRouterContact addContactSupport( byte[] node_id, DHTRouterContactAttachment attachment, boolean known_to_be_alive ) { DHTRouterNodeImpl current_node = root; boolean part_of_smallest_subtree = false; for (int i=0;i= 0 ){ if ( current_node == smallest_subtree ){ part_of_smallest_subtree = true; } boolean bit = ((b>>j)&0x01)==1?true:false; DHTRouterNodeImpl next_node; if ( bit ){ next_node = current_node.getLeft(); }else{ next_node = current_node.getRight(); } if ( next_node == null ){ DHTRouterContact existing_contact = current_node.updateExistingNode( node_id, attachment, known_to_be_alive ); if ( existing_contact != null ){ return( existing_contact ); } List buckets = current_node.getBuckets(); if ( buckets.size() == K ){ // split if either // 1) this list contains router_node_id or // 2) depth % B is not 0 // 3) this is part of the smallest subtree boolean contains_router_node_id = current_node.containsRouterNodeID(); int depth = current_node.getDepth(); boolean too_deep_to_split = depth % B == 0; // note this will be true for 0 but other // conditions will allow the split if ( contains_router_node_id || (!too_deep_to_split) || part_of_smallest_subtree ){ // the smallest-subtree bit is to ensure that we remember all of // our closest neighbours as ultimately they are the ones responsible // for returning our identity to queries (due to binary choppery in // general the query will home in on our neighbours before // hitting us. It is therefore important that we keep ourselves live // in their tree by refreshing. If we blindly chopped at K entries // (down to B levels) then a highly unbalanced tree would result in // us dropping some of them and therefore not refreshing them and // therefore dropping out of their trees. There are also other benefits // of maintaining this tree regarding stored value refresh // Note that it is rare for such an unbalanced tree. // However, a possible DOS here would be for a rogue node to // deliberately try and create such a tree with a large number // of entries. if ( part_of_smallest_subtree && too_deep_to_split && ( !contains_router_node_id ) && getContactCount( smallest_subtree ) > smallest_subtree_max ){ Debug.out( "DHTRouter: smallest subtree max size violation" ); return( null ); } // split!!!! List left_buckets = new ArrayList(); List right_buckets = new ArrayList(); for (int k=0;k>(7-(depth%8)))&0x01 ) == 0 ){ right_buckets.add( contact ); }else{ left_buckets.add( contact ); } } boolean right_contains_rid = false; boolean left_contains_rid = false; if ( contains_router_node_id ){ right_contains_rid = ((router_node_id[depth/8]>>(7-(depth%8)))&0x01 ) == 0; left_contains_rid = !right_contains_rid; } DHTRouterNodeImpl new_left = new DHTRouterNodeImpl( this, depth+1, left_contains_rid, left_buckets ); DHTRouterNodeImpl new_right = new DHTRouterNodeImpl( this, depth+1, right_contains_rid, right_buckets ); current_node.split( new_left, new_right ); if ( right_contains_rid ){ // we've created a new smallest subtree // TODO: tidy up old smallest subtree - remember to factor in B... smallest_subtree = new_left; }else if ( left_contains_rid ){ // TODO: tidy up old smallest subtree - remember to factor in B... smallest_subtree = new_right; } // not complete, retry addition }else{ // split not appropriate, add as a replacemnet DHTRouterContactImpl new_contact = new DHTRouterContactImpl( node_id, attachment, known_to_be_alive ); return( current_node.addReplacement( new_contact, max_rep_per_node )); } }else{ // bucket space free, just add it DHTRouterContactImpl new_contact = new DHTRouterContactImpl( node_id, attachment, known_to_be_alive ); current_node.addNode( new_contact ); // complete - added to bucket return( new_contact ); } }else{ current_node = next_node; j--; } } } Debug.out( "DHTRouter inconsistency" ); return( null ); } public List findClosestContacts( byte[] node_id, int num_to_return, boolean live_only ) { // find the num_to_return-ish closest nodes - consider all buckets, not just the closest try{ this_mon.enter(); List res = new ArrayList(); findClosestContacts( node_id, num_to_return, 0, root, live_only, res ); return( res ); }finally{ this_mon.exit(); } } protected void findClosestContacts( byte[] node_id, int num_to_return, int depth, DHTRouterNodeImpl current_node, boolean live_only, List res ) { List buckets = current_node.getBuckets(); if ( buckets != null ){ // add everything from the buckets - caller will sort and select // the best ones as required for (int i=0;i>(7-(depth%8)))&0x01 ) == 1; DHTRouterNodeImpl best_node; DHTRouterNodeImpl worse_node; if ( bit ){ best_node = current_node.getLeft(); worse_node = current_node.getRight(); }else{ best_node = current_node.getRight(); worse_node = current_node.getLeft(); } findClosestContacts( node_id, num_to_return, depth+1, best_node, live_only, res ); if ( res.size() < num_to_return ){ findClosestContacts( node_id, num_to_return, depth+1, worse_node, live_only, res ); } } } public DHTRouterContact findContact( byte[] node_id ) { Object[] res = findContactSupport( node_id ); return((DHTRouterContact)res[1]); } protected DHTRouterNodeImpl findNode( byte[] node_id ) { Object[] res = findContactSupport( node_id ); return((DHTRouterNodeImpl)res[0]); } protected Object[] findContactSupport( byte[] node_id ) { try{ this_mon.enter(); DHTRouterNodeImpl current_node = root; for (int i=0;i= 0 ){ boolean bit = ((b>>j)&0x01)==1?true:false; if ( current_node.getBuckets() != null ){ break; } if ( bit ){ current_node = current_node.getLeft(); }else{ current_node = current_node.getRight(); } j--; } } List buckets = current_node.getBuckets(); for (int k=0;k don't check { // when seeding we don't do the smallest subtree if ( seeding && node == smallest_subtree ){ return; } if ( max_permitted_idle != 0 ){ if ( node.getTimeSinceLastLookup() <= max_permitted_idle ){ return; } } if ( node.getBuckets() != null ){ // and we also don't refresh the bucket containing the router id when seeding if ( seeding && node.containsRouterNodeID()){ return; } refreshNode( nodes_to_refresh, node, path ); } // synchronous refresh may result in this bucket being split // so we retest here to refresh sub-buckets as required if ( node.getBuckets() == null ){ int depth = node.getDepth(); byte mask = (byte)( 0x01<<(7-(depth%8))); path[depth/8] = (byte)( path[depth/8] | mask ); refreshNodes( nodes_to_refresh, node.getLeft(), path,seeding, max_permitted_idle ); path[depth/8] = (byte)( path[depth/8] & ~mask ); refreshNodes( nodes_to_refresh, node.getRight(), path,seeding, max_permitted_idle ); } } protected void refreshNode( List nodes_to_refresh, DHTRouterNodeImpl node, byte[] path ) { // pick a random id in the node's range. byte[] id = new byte[router_node_id.length]; random.nextBytes( id ); int depth = node.getDepth(); for (int i=0;i>(7-(i%8)))&0x01 ) == 1; if ( bit ){ id[i/8] = (byte)( id[i/8] | mask ); }else{ id[i/8] = (byte)( id[i/8] & ~mask ); } } nodes_to_refresh.add( id ); } protected DHTRouterNodeImpl getSmallestSubtree() { return( smallest_subtree ); } public void recordLookup( byte[] node_id ) { findNode( node_id ).setLastLookupTime(); } public void refreshIdleLeaves( long idle_max) { // while we are synchronously refreshing the smallest subtree the tree can mutate underneath us // as new contacts are discovered. We NEVER merge things back together byte[] path = new byte[router_node_id.length]; List ids = new ArrayList(); try{ this_mon.enter(); refreshNodes( ids, root, path, false, idle_max ); }finally{ this_mon.exit(); } for (int i=0;i max_fails ){ max_fails = fails; max_fails_contact = contact; } } } if ( max_fails_contact != null ){ requestPing( max_fails_contact ); return; } if ( stack.size() == 0 ){ break; } node = (DHTRouterNodeImpl)stack.removeLast(); } } }finally{ this_mon.exit(); dispatchPings(); } } protected void requestNodeAdd( DHTRouterContactImpl contact ) { // make sure we don't do the addition when synchronised DHTLog.log( "DHTRouter: requestNodeAdd:" + DHTLog.getString( contact.getID())); if ( contact == local_contact ){ Debug.out( "adding local contact" ); } try{ this_mon.enter(); if ( !outstanding_adds.contains( contact )){ outstanding_adds.add( contact ); } }finally{ this_mon.exit(); } } protected void dispatchNodeAdds() { if ( outstanding_adds.size() == 0 ){ return; } List adds; try{ this_mon.enter(); adds = outstanding_adds; outstanding_adds = new ArrayList(); }finally{ this_mon.exit(); } for (int i=0;i 0 ){ stats_array[DHTRouterStats.ST_CONTACTS_DEAD]++; }else if ( contact.hasBeenAlive()){ stats_array[DHTRouterStats.ST_CONTACTS_LIVE]++; }else{ stats_array[DHTRouterStats.ST_CONTACTS_UNKNOWN]++; } } List rep = node.getReplacements(); if ( rep != null ){ stats_array[DHTRouterStats.ST_REPLACEMENTS] += rep.size(); } } } protected long[] getStatsSupport() { /* number of nodes * number of leaves * number of contacts * number of replacements * number of live contacts * number of unknown contacts * number of dying contacts */ try{ this_mon.enter(); long[] res = new long[7]; getStatsSupport( res, root ); return( res ); }finally{ this_mon.exit(); } } protected void log( String str ) { logger.log( str ); } public void print() { try{ this_mon.enter(); log( "DHT: " + DHTLog.getString2(router_node_id) + ", node count = " + getNodeCount()+ ", contacts =" + getContactCount()); root.print( "", "" ); }finally{ this_mon.exit(); } } public void destroy() { timer_event.cancel(); notifyDead(); } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/router/impl/Test.java0000644000175000017500000000632211103226576024324 0ustar adrianadrian/* * Created on 11-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.router.impl; /** * @author parg * */ import org.gudy.azureus2.core3.util.SHA1Simple; import com.aelitis.azureus.core.dht.router.*; public class Test { public static void main( String[] args ) { randomTest(); } protected static void simpleTest() { DHTRouter router = DHTRouterFactory.create( 1, 1,1, new byte[]{ 0 }, null, com.aelitis.azureus.core.dht.impl.Test.getLogger()); router.setAdapter( new DHTRouterAdapter() { public void requestAdd(DHTRouterContact contact) { // TODO Auto-generated method stub } public void requestLookup(byte[] id, String description) { // TODO Auto-generated method stub } public void requestPing(DHTRouterContact contact) { // TODO Auto-generated method stub } }); byte[][] node_ids ={ { toByte( "11111111" ) }, { toByte( "01111111" ) }, { toByte( "00101111" ) }, { toByte( "00100111" ) }, //{ toByte( "00111111" ) }, }; for (int i=0;i 0 ); } protected int getFailCount() { return( fail_count ); } public long getTimeAlive() { if ( fail_count > 0 || first_alive_time == 0 ){ return( 0 ); } return( SystemTime.getCurrentTime() - first_alive_time ); } protected boolean setFailed() { fail_count++; if ( fail_count == 1 ){ first_fail_or_last_alive_time = SystemTime.getCurrentTime(); } return( hasFailed()); } protected boolean hasFailed() { if ( has_been_alive ){ return( fail_count >= attachment.getMaxFailForLiveCount()); }else{ return( fail_count >= attachment.getMaxFailForUnknownCount()); } } protected long getFirstFailTime() { return( fail_count==0?0:first_fail_or_last_alive_time ); } protected long getLastAliveTime() { return( fail_count==0?first_fail_or_last_alive_time:0 ); } protected long getFirstFailOrLastAliveTime() { return( first_fail_or_last_alive_time ); } protected long getFirstAliveTime() { return( first_alive_time ); } protected long getLastAddedTime() { return( last_added_time ); } protected void setLastAddedTime( long l ) { last_added_time = l; } protected void setPingOutstanding( boolean b ) { ping_outstanding = b; } protected boolean getPingOutstanding() { return( ping_outstanding ); } public String getString() { return( DHTLog.getString2(node_id) + "[hba=" + (has_been_alive?"Y":"N" ) + ",bad=" + fail_count + ",OK=" + getTimeAlive() + "]"); } public boolean isBucketEntry() { return is_bucket_entry; } public void setBucketEntry() { is_bucket_entry = true; } public boolean isReplacement() { return !is_bucket_entry; } public void setReplacement() { is_bucket_entry = false; } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/router/DHTRouterStats.java0000644000175000017500000000315110373051032025267 0ustar adrianadrian/* * Created on 18-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.router; /** * @author parg * */ public interface DHTRouterStats { public static final int ST_NODES = 0; public static final int ST_LEAVES = 1; public static final int ST_CONTACTS = 2; public static final int ST_REPLACEMENTS = 3; public static final int ST_CONTACTS_LIVE = 4; public static final int ST_CONTACTS_UNKNOWN = 5; public static final int ST_CONTACTS_DEAD = 6; /** * returns * number of nodes * number of leaves * number of contacts * number of replacements * number of live contacts * number of unknown contacts * number of dying contacts */ public long[] getStats(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/router/DHTRouterContact.java0000644000175000017500000000422310423311514025565 0ustar adrianadrian/* * Created on 11-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.router; /** * @author parg * */ public interface DHTRouterContact { public byte[] getID(); public DHTRouterContactAttachment getAttachment(); /** * indicates whether or not a message has been received from, or an operation has * successfully been made to, the contact. * @return */ public boolean hasBeenAlive(); /** * Whether or not the contact has failed once or more since last alive (if ever) * @return */ public boolean isFailing(); /** * Whether or not the contact's last interaction was successful * @return */ public boolean isAlive(); /** * time between first establishing the contact was alive and now, assuming that its * not failing. 0 -> failing * @return */ public long getTimeAlive(); public String getString(); /** * Returns whether this router contact is in a bucket. * * @return * true if in a bucket, false otherwise */ public boolean isBucketEntry(); /** * Returns whether this router contact is a replacement. * * @return * true if a replacement, false otherwise */ public boolean isReplacement(); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/router/DHTRouterFactory.java0000644000175000017500000000373410423311514025607 0ustar adrianadrian/* * Created on 11-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.router; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.azureus.core.dht.DHTLogger; import com.aelitis.azureus.core.dht.router.impl.*; public class DHTRouterFactory { private static final List observers = new ArrayList(); public static DHTRouter create( int K, int B, int max_rep_per_node, byte[] id, DHTRouterContactAttachment attachment, DHTLogger logger ) { DHTRouterImpl res = new DHTRouterImpl( K, B, max_rep_per_node, id, attachment, logger ); for( int i=0;i findClosestContacts( byte[] node_id, int num_to_return, boolean live_only ); public void recordLookup( byte[] node_id ); public boolean requestPing( byte[] node_id ); public void refreshIdleLeaves( long idle_max ); public byte[] refreshRandom(); /** * returns a list of best contacts in terms of uptime, best first * @param max * @return */ public List findBestContacts( int max ); /** * Returns a list of DHTRouterContact objects * @return */ public List getAllContacts(); public DHTRouterStats getStats(); public void destroy(); public void print(); /** * Adds a routing table observer if it is not already observing. * * @param rto * the observer to add * @return true if now observing, false otherwise */ public boolean addObserver(DHTRouterObserver rto); /** * Returns whether the given observer is already observing. * * @param rto * the observer to query as observing * @return true if observing, false otherwise */ public boolean containsObserver(DHTRouterObserver rto); /** * Removes the observer if it is already observing. * * @param rto * the observer to remove * @return true if no longer observing, false otherwise */ public boolean removeObserver(DHTRouterObserver rto); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/nat/0000755000175000017500000000000011310377622021037 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/dht/nat/DHTNATPuncherAdapter.java0000644000175000017500000000224510454610524025514 0ustar adrianadrian/* * Created on 04-Jun-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.nat; import java.net.InetSocketAddress; import java.util.Map; public interface DHTNATPuncherAdapter { public Map getClientData( InetSocketAddress originator, Map originator_client_data ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/nat/DHTNATPuncher.java0000644000175000017500000000402610466500140024205 0ustar adrianadrian/* * Created on 11-Aug-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.nat; import java.net.InetSocketAddress; import java.util.Map; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; public interface DHTNATPuncher { public void start(); public void destroy(); /** * We're trying to run a rendezvous * @return */ public boolean active(); /** * Got a good running rendezvous * @return */ public boolean operational(); public Map punch( String reason, DHTTransportContact target, DHTTransportContact[] rendezvous_used, Map client_data ); /** * * @param target input/output parameter for target of traversal * @param client_data * @return */ public Map punch( String reason, InetSocketAddress[] target, DHTTransportContact[] rendezvous_used, Map client_data ); /** * @param target * @param rendezvous */ public void setRendezvous( DHTTransportContact target, DHTTransportContact rendezvous ); public Map sendMessage( InetSocketAddress rendezvous, InetSocketAddress target, Map message ); } azureus-4.3.0.6/com/aelitis/azureus/core/dht/nat/impl/0000755000175000017500000000000011310377624022002 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/core/dht/nat/impl/DHTNATPuncherImpl.java0000644000175000017500000013211211256357140025776 0ustar adrianadrian/* * Created on 11-Aug-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.nat.impl; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.InetSocketAddress; import java.util.*; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SHA1Simple; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.utils.*; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.DHTLogger; import com.aelitis.azureus.core.dht.DHTOperationAdapter; import com.aelitis.azureus.core.dht.DHTOperationListener; import com.aelitis.azureus.core.dht.nat.*; import com.aelitis.azureus.core.dht.transport.DHTTransport; import com.aelitis.azureus.core.dht.transport.DHTTransportContact; import com.aelitis.azureus.core.dht.transport.DHTTransportException; import com.aelitis.azureus.core.dht.transport.DHTTransportListener; import com.aelitis.azureus.core.dht.transport.DHTTransportProgressListener; import com.aelitis.azureus.core.dht.transport.DHTTransportReplyHandlerAdapter; import com.aelitis.azureus.core.dht.transport.DHTTransportTransferHandler; import com.aelitis.azureus.core.dht.transport.DHTTransportValue; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP; import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDPContact; public class DHTNATPuncherImpl implements DHTNATPuncher { private static boolean TESTING = false; private static boolean TRACE = false; static{ if ( TESTING ){ System.out.println( "**** DHTNATPuncher test on ****" ); } if ( TRACE ){ System.out.println( "**** DHTNATPuncher trace on ****" ); } } private static final int RT_BIND_REQUEST = 0; private static final int RT_BIND_REPLY = 1; private static final int RT_PUNCH_REQUEST = 2; private static final int RT_PUNCH_REPLY = 3; private static final int RT_CONNECT_REQUEST = 4; private static final int RT_CONNECT_REPLY = 5; private static final int RT_TUNNEL_INBOUND = 6; private static final int RT_TUNNEL_OUTBOUND = 7; private static final int RT_QUERY_REQUEST = 8; private static final int RT_QUERY_REPLY = 9; private static final int RT_CLOSE_REQUEST = 10; private static final int RT_CLOSE_REPLY = 11; private static final int RESP_OK = 0; private static final int RESP_NOT_OK = 1; private static final int RESP_FAILED = 2; private static byte[] transfer_handler_key = new SHA1Simple().calculateHash("Aelitis:NATPuncher:TransferHandlerKey".getBytes()); private boolean started; private DHTNATPuncherAdapter adapter; private DHT dht; private DHTLogger logger; private PluginInterface plugin_interface; private Formatters formatters; private UTTimer timer; private static final int REPUBLISH_TIME_MIN = 5*60*1000; private static final int TRANSFER_TIMEOUT = 30*1000; private static final int RENDEZVOUS_LOOKUP_TIMEOUT = 30*1000; private static final int TUNNEL_TIMEOUT = 3*1000; private static final int RENDEZVOUS_SERVER_MAX = 8; private static final int RENDEZVOUS_SERVER_TIMEOUT = 5*60*1000; private static final int RENDEZVOUS_CLIENT_PING_PERIOD = 50*1000; // some routers only hold tunnel for 60s private static final int RENDEZVOUS_PING_FAIL_LIMIT = 4; // if you make this < 2 change code below! private Monitor server_mon; private Map rendezvous_bindings = new HashMap(); private long last_publish; private Monitor pub_mon; private boolean publish_in_progress; private volatile DHTTransportContact rendezvous_local_contact; private volatile DHTTransportContact rendezvous_target; private volatile DHTTransportContact last_ok_rendezvous; private static final int FAILED_RENDEZVOUS_HISTORY_MAX = 16; private Map failed_rendezvous = new LinkedHashMap(FAILED_RENDEZVOUS_HISTORY_MAX,0.75f,true) { protected boolean removeEldestEntry( Map.Entry eldest) { return size() > FAILED_RENDEZVOUS_HISTORY_MAX; } }; private boolean rendezvous_thread_running; private Map explicit_rendezvous_map = new HashMap(); private Monitor punch_mon; private List oustanding_punches = new ArrayList(); private DHTTransportContact current_local = null; private DHTTransportContact current_target = null; private int rendevzous_fail_count = 0; public DHTNATPuncherImpl( DHTNATPuncherAdapter _adapter, DHT _dht ) { adapter = _adapter; dht = _dht; logger = dht.getLogger(); plugin_interface = dht.getLogger().getPluginInterface(); formatters = plugin_interface.getUtilities().getFormatters(); pub_mon = plugin_interface.getUtilities().getMonitor(); server_mon = plugin_interface.getUtilities().getMonitor(); punch_mon = plugin_interface.getUtilities().getMonitor(); timer = plugin_interface.getUtilities().createTimer( "DHTNATPuncher:refresher", true ); } public void start() { if ( started ){ return; } started = true; DHTTransport transport = dht.getTransport(); transport.addListener( new DHTTransportListener() { public void localContactChanged( DHTTransportContact local_contact ) { publish( false ); } public void currentAddress( String address ) { } public void reachabilityChanged( boolean reacheable ) { publish( false ); } }); transport.registerTransferHandler( transfer_handler_key, new DHTTransportTransferHandler() { public String getName() { return( "NAT Traversal" ); } public byte[] handleRead( DHTTransportContact originator, byte[] key ) { return( null ); } public byte[] handleWrite( DHTTransportContact originator, byte[] key, byte[] value ) { return( receiveRequest((DHTTransportUDPContact)originator, value )); } }); timer.addPeriodicEvent( REPUBLISH_TIME_MIN, new UTTimerEventPerformer() { public void perform( UTTimerEvent event ) { publish( false ); } }); timer.addPeriodicEvent( RENDEZVOUS_SERVER_TIMEOUT/2, new UTTimerEventPerformer() { public void perform( UTTimerEvent event ) { long now = plugin_interface.getUtilities().getCurrentSystemTime(); try{ server_mon.enter(); Iterator it = rendezvous_bindings.values().iterator(); while( it.hasNext()){ Object[] entry = (Object[])it.next(); long time = ((Long)entry[1]).longValue(); boolean removed = false; if ( time > now ){ // clock change, easiest approach is to remove it it.remove(); removed = true; }else if ( now - time > RENDEZVOUS_SERVER_TIMEOUT ){ // timeout it.remove(); removed = true; } if ( removed ){ log( "Rendezvous " + ((DHTTransportContact)entry[0]).getString() + " removed due to inactivity" ); } } }finally{ server_mon.exit(); } } }); publish( false ); } public boolean active() { return( rendezvous_local_contact != null ); } public boolean operational() { DHTTransportContact ok = last_ok_rendezvous; if ( ok != null && ok == rendezvous_target ){ return( true ); } return( false ); } protected void publish( final boolean force ) { long now = plugin_interface.getUtilities().getCurrentSystemTime(); if ( now < last_publish && !force ){ last_publish = now; }else{ if ( force || now - last_publish >= REPUBLISH_TIME_MIN ){ last_publish = now; plugin_interface.getUtilities().createThread( "DHTNATPuncher:publisher", new Runnable() { public void run() { try{ pub_mon.enter(); if ( publish_in_progress ){ return; } publish_in_progress = true; }finally{ pub_mon.exit(); } try{ publishSupport(); }finally{ try{ pub_mon.enter(); publish_in_progress = false; }finally{ pub_mon.exit(); } } } }); } } } protected void publishSupport() { DHTTransport transport = dht.getTransport(); if ( TESTING || !transport.isReachable() ){ DHTTransportContact local_contact = transport.getLocalContact(); // see if the rendezvous has failed and therefore we are required to find a new one boolean force = rendezvous_target != null && failed_rendezvous.containsKey( rendezvous_target.getAddress()); if ( rendezvous_local_contact != null && !force ){ if ( local_contact.getAddress().equals( rendezvous_local_contact.getAddress())){ // already running for the current local contact return; } } DHTTransportContact explicit = (DHTTransportContact)explicit_rendezvous_map.get( local_contact.getAddress()); if ( explicit != null ){ try{ pub_mon.enter(); rendezvous_local_contact = local_contact; rendezvous_target = explicit; runRendezvous(); }finally{ pub_mon.exit(); } }else{ final DHTTransportContact[] new_rendezvous_target = { null }; DHTTransportContact[] reachables = dht.getTransport().getReachableContacts(); int reachables_tried = 0; int reachables_skipped = 0; final Semaphore sem = plugin_interface.getUtilities().getSemaphore(); for (int i=0;i 0 ){ try{ Thread.sleep( 1000 ); }catch( Throwable e ){ } } reachables_tried++; contact.sendPing( new DHTTransportReplyHandlerAdapter() { public void pingReply( DHTTransportContact ok_contact ) { trace( "Punch:" + ok_contact.getString() + " OK" ); try{ pub_mon.enter(); if ( new_rendezvous_target[0] == null ){ new_rendezvous_target[0] = ok_contact; } }finally{ pub_mon.exit(); sem.release(); } } public void failed( DHTTransportContact failed_contact, Throwable e ) { try{ trace( "Punch:" + failed_contact.getString() + " Failed" ); }finally{ sem.release(); } } }); } for (int i=0;i " + rendezvous_target.getString()); runRendezvous(); break; } }finally{ pub_mon.exit(); } } if ( new_rendezvous_target[0] == null ){ log( "No rendezvous found: candidates=" + reachables.length +",tried="+ reachables_tried+",skipped=" +reachables_skipped ); try{ pub_mon.enter(); rendezvous_local_contact = null; rendezvous_target = null; }finally{ pub_mon.exit(); } } } }else{ try{ pub_mon.enter(); rendezvous_local_contact = null; rendezvous_target = null; }finally{ pub_mon.exit(); } } } protected void runRendezvous() { try{ pub_mon.enter(); if ( !rendezvous_thread_running ){ rendezvous_thread_running = true; plugin_interface.getUtilities().createThread( "DHTNatPuncher:rendevzous", new Runnable() { public void run() { runRendezvousSupport(); } }); } }finally{ pub_mon.exit(); } } protected void runRendezvousSupport() { SimpleTimer.addPeriodicEvent( "DHTNAT:cp", RENDEZVOUS_CLIENT_PING_PERIOD, new TimerEventPerformer() { public void perform( TimerEvent ev ) { try{ DHTTransportContact latest_local; DHTTransportContact latest_target; try{ pub_mon.enter(); latest_local = rendezvous_local_contact; latest_target = rendezvous_target; }finally{ pub_mon.exit(); } if ( current_local != null || latest_local != null ){ // one's not null, worthwhile further investigation if ( current_local != latest_local ){ // local has changed, remove existing publish if ( current_local != null ){ log( "Removing publish for " + current_local.getString() + " -> " + current_target.getString()); dht.remove( getPublishKey( current_local ), "DHTNatPuncher: removal of publish", new DHTOperationListener() { public void searching( DHTTransportContact contact, int level, int active_searches ) {} public void found( DHTTransportContact contact, boolean is_closest ) {} public void diversified( String desc ) { } public void read( DHTTransportContact contact, DHTTransportValue value ) {} public void wrote( DHTTransportContact contact, DHTTransportValue value ) {} public void complete( boolean timeout ) {} }); } if ( latest_local != null ){ log( "Adding publish for " + latest_local.getString() + " -> " + latest_target.getString()); rendevzous_fail_count = RENDEZVOUS_PING_FAIL_LIMIT - 2; // only 2 attempts to start with dht.put( getPublishKey( latest_local ), "NAT Traversal: rendezvous publish", encodePublishValue( latest_target ), DHT.FLAG_SINGLE_VALUE, new DHTOperationListener() { public void searching( DHTTransportContact contact, int level, int active_searches ) {} public void found( DHTTransportContact contact, boolean is_closest ) {} public void diversified( String desc ) { } public void read( DHTTransportContact contact, DHTTransportValue value ) {} public void wrote( DHTTransportContact contact, DHTTransportValue value ) {} public void complete( boolean timeout ) {} }); } }else if ( current_target != latest_target ){ // here current_local == latest_local and neither is null! // target changed, update publish log( "Updating publish for " + latest_local.getString() + " -> " + latest_target.getString()); rendevzous_fail_count = RENDEZVOUS_PING_FAIL_LIMIT - 2; // only 2 attempts to start with dht.put( getPublishKey( latest_local ), "DHTNatPuncher: update publish", encodePublishValue( latest_target ), DHT.FLAG_SINGLE_VALUE, new DHTOperationListener() { public void searching( DHTTransportContact contact, int level, int active_searches ) {} public void found( DHTTransportContact contact, boolean is_closest ) {} public void diversified( String desc ) { } public void read( DHTTransportContact contact, DHTTransportValue value ) {} public void wrote( DHTTransportContact contact, DHTTransportValue value ) {} public void complete( boolean timeout ) {} }); } } current_local = latest_local; current_target = latest_target; if ( current_target != null ){ int bind_result = sendBind( current_target ); if ( bind_result == RESP_OK ){ trace( "Rendezvous:" + current_target.getString() + " OK" ); rendevzous_fail_count = 0; if ( last_ok_rendezvous != current_target ){ last_ok_rendezvous = current_target; log( "Rendezvous " + latest_target.getString() + " operational" ); } }else{ if ( bind_result == RESP_NOT_OK ){ // denied access rendevzous_fail_count = RENDEZVOUS_PING_FAIL_LIMIT; }else{ rendevzous_fail_count++; } if ( rendevzous_fail_count == RENDEZVOUS_PING_FAIL_LIMIT ){ rendezvousFailed( current_target, false ); } } } }catch( Throwable e ){ log(e); } } } ); } protected void rendezvousFailed( DHTTransportContact current_target, boolean tidy ) { log( "Rendezvous " + (tidy?"closed":"failed") + ": " + current_target.getString()); try{ pub_mon.enter(); failed_rendezvous.put( current_target.getAddress(), "" ); }finally{ pub_mon.exit(); } publish( true ); } protected byte[] sendRequest( DHTTransportContact target, byte[] data, int timeout ) { try{ return( dht.getTransport().writeReadTransfer( new DHTTransportProgressListener() { public void reportSize( long size ) { } public void reportActivity( String str ) { } public void reportCompleteness( int percent ) { } }, target, transfer_handler_key, data, timeout )); }catch( DHTTransportException e ){ // log(e); timeout most likely return( null ); } } protected byte[] receiveRequest( DHTTransportUDPContact originator, byte[] data ) { try{ Map res = receiveRequest( originator, formatters.bDecode( data )); if ( res == null ){ return( null ); } return( formatters.bEncode( res )); }catch( Throwable e ){ log(e); return( null ); } } protected Map sendRequest( DHTTransportContact target, Map data, int timeout ) { try{ byte[] res = sendRequest( target, formatters.bEncode( data ), timeout ); if ( res == null ){ return( null ); } return( formatters.bDecode( res )); }catch( Throwable e ){ log(e); return( null ); } } protected Map receiveRequest( DHTTransportUDPContact originator, Map data ) { int type = ((Long)data.get("type")).intValue(); Map response = new HashMap(); switch( type ){ case RT_BIND_REQUEST: { response.put( "type", new Long( RT_BIND_REPLY )); receiveBind( originator, data, response ); break; } case RT_CLOSE_REQUEST: { response.put( "type", new Long( RT_CLOSE_REPLY )); receiveClose( originator, data, response ); break; } case RT_QUERY_REQUEST: { response.put( "type", new Long( RT_QUERY_REPLY )); receiveQuery( originator, data, response ); break; } case RT_PUNCH_REQUEST: { response.put( "type", new Long( RT_PUNCH_REPLY )); receivePunch( originator, data, response ); break; } case RT_CONNECT_REQUEST: { response.put( "type", new Long( RT_CONNECT_REPLY )); receiveConnect( originator, data, response ); break; } case RT_TUNNEL_INBOUND: { receiveTunnelInbound( originator, data ); response = null; break; } case RT_TUNNEL_OUTBOUND: { receiveTunnelOutbound( originator, data ); response = null; break; } default: { response = null; break; } } return( response ); } protected boolean sendTunnelMessage( DHTTransportContact target, Map data ) { try{ return( sendTunnelMessage( target, formatters.bEncode( data ))); }catch( Throwable e ){ log(e); return( false ); } } protected boolean sendTunnelMessage( DHTTransportContact target, byte[] data ) { try{ dht.getTransport().writeTransfer( new DHTTransportProgressListener() { public void reportSize( long size ) { } public void reportActivity( String str ) { } public void reportCompleteness( int percent ) { } }, target, transfer_handler_key, new byte[0], data, TUNNEL_TIMEOUT ); return( true ); }catch( DHTTransportException e ){ // log(e); timeout most likely return( false ); } } protected int sendBind( DHTTransportContact target ) { try{ Map request = new HashMap(); request.put("type", new Long( RT_BIND_REQUEST )); Map response = sendRequest( target, request, TRANSFER_TIMEOUT ); if ( response == null ){ return( RESP_FAILED ); } if (((Long)response.get( "type" )).intValue() == RT_BIND_REPLY ){ int result = ((Long)response.get("ok")).intValue(); trace( "received bind reply: " + (result==0?"failed":"ok" )); if ( result == 1 ){ return( RESP_OK ); } } return( RESP_NOT_OK ); }catch( Throwable e ){ log(e); return( RESP_FAILED ); } } protected void receiveBind( DHTTransportUDPContact originator, Map request, Map response ) { trace( "received bind request" ); boolean ok = true; boolean log = true; try{ server_mon.enter(); Object[] entry = (Object[])rendezvous_bindings.get( originator.getAddress().toString()); if ( entry == null ){ if ( rendezvous_bindings.size() == RENDEZVOUS_SERVER_MAX ){ ok = false; } }else{ // already present, no need to log again log = false; } if ( ok ){ long now = plugin_interface.getUtilities().getCurrentSystemTime(); rendezvous_bindings.put( originator.getAddress().toString(), new Object[]{ originator, new Long( now )}); response.put( "port", new Long( originator.getAddress().getPort())); } }finally{ server_mon.exit(); } if ( log ){ log( "Rendezvous request from " + originator.getString() + " " + (ok?"accepted":"denied" )); } response.put( "ok", new Long(ok?1:0)); } public void destroy() { try{ server_mon.enter(); Iterator it = rendezvous_bindings.values().iterator(); while( it.hasNext()){ Object[] entry = (Object[])it.next(); final DHTTransportUDPContact contact = (DHTTransportUDPContact)entry[0]; new AEThread2( "DHTNATPuncher:destroy", true ) { public void run() { sendClose( contact ); } }.start(); } }catch( Throwable e ){ log( e ); }finally{ server_mon.exit(); } } protected int sendClose( DHTTransportContact target ) { try{ Map request = new HashMap(); request.put("type", new Long( RT_CLOSE_REQUEST )); Map response = sendRequest( target, request, TRANSFER_TIMEOUT ); if ( response == null ){ return( RESP_FAILED ); } if (((Long)response.get( "type" )).intValue() == RT_CLOSE_REPLY ){ int result = ((Long)response.get("ok")).intValue(); trace( "received close reply: " + (result==0?"failed":"ok" )); if ( result == 1 ){ return( RESP_OK ); } } return( RESP_NOT_OK ); }catch( Throwable e ){ log(e); return( RESP_FAILED ); } } protected void receiveClose( DHTTransportUDPContact originator, Map request, Map response ) { trace( "received close request" ); final DHTTransportContact current_target = rendezvous_target; if ( current_target != null && Arrays.equals( current_target.getID(), originator.getID())){ new AEThread2( "DHTNATPuncher:close", true ) { public void run() { rendezvousFailed( current_target, true ); } }.start(); } response.put( "ok", new Long(1)); } /** * XXX: unused */ private int sendQuery( DHTTransportContact target ) { try{ Map request = new HashMap(); request.put("type", new Long( RT_QUERY_REQUEST )); Map response = sendRequest( target, request, TRANSFER_TIMEOUT ); if ( response == null ){ return( RESP_FAILED ); } if (((Long)response.get( "type" )).intValue() == RT_QUERY_REPLY ){ int result = ((Long)response.get("ok")).intValue(); trace( "received query reply: " + (result==0?"failed":"ok" )); if ( result == 1 ){ return( RESP_OK ); } } return( RESP_NOT_OK ); }catch( Throwable e ){ log(e); return( RESP_FAILED ); } } protected void receiveQuery( DHTTransportUDPContact originator, Map request, Map response ) { trace( "received query request" ); InetSocketAddress address = originator.getTransportAddress(); response.put( "ip", address.getAddress().getHostAddress().getBytes()); response.put( "port", new Long( address.getPort())); response.put( "ok", new Long(1)); } protected Map sendPunch( DHTTransportContact rendezvous, final DHTTransportUDPContact target, Map originator_client_data, boolean no_tunnel ) { AESemaphore wait_sem = new AESemaphore( "DHTNatPuncher::sendPunch" ); Object[] wait_data = new Object[]{ target, wait_sem, new Integer(0)}; try{ try{ punch_mon.enter(); oustanding_punches.add( wait_data ); }finally{ punch_mon.exit(); } Map request = new HashMap(); request.put("type", new Long( RT_PUNCH_REQUEST )); request.put("target", target.getAddress().toString().getBytes()); if ( originator_client_data != null ){ if ( no_tunnel ){ originator_client_data.put( "_notunnel", new Long(1)); } request.put( "client_data", originator_client_data ); } // for a message payload (i.e. no_tunnel) we double the initiator timeout to give // more chance for reasonable size messages to get through as they have to go through // 2 xfer processes Map response = sendRequest( rendezvous, request, no_tunnel?TRANSFER_TIMEOUT*2:TRANSFER_TIMEOUT ); if ( response == null ){ return( null ); } if (((Long)response.get( "type" )).intValue() == RT_PUNCH_REPLY ){ int result = ((Long)response.get("ok")).intValue(); trace( "received " + ( no_tunnel?"message":"punch") + " reply: " + (result==0?"failed":"ok" )); if ( result == 1 ){ // pick up port changes from the rendezvous Long indirect_port = (Long)response.get( "port" ); if ( indirect_port != null ){ int transport_port = indirect_port.intValue(); if ( transport_port != 0 ){ InetSocketAddress existing_address = target.getTransportAddress(); if ( transport_port != existing_address.getPort()){ target.setTransportAddress( new InetSocketAddress(existing_address.getAddress(), transport_port )); } } } if ( !no_tunnel ){ // ping the target a few times to try and establish a tunnel UTTimerEvent event = timer.addPeriodicEvent( 3000, new UTTimerEventPerformer() { private int pings = 1; public void perform( UTTimerEvent event ) { if ( pings > 3 ){ event.cancel(); return; } pings++; if ( sendTunnelOutbound( target )){ event.cancel(); } } }); if ( sendTunnelOutbound( target )){ event.cancel(); } // give the other end a few seconds to kick off some tunnel events to us if ( wait_sem.reserve(10000)){ event.cancel(); } } // routers often fiddle with the port when not mapped so we need to grab the right one to use // for direct communication // first priority goes to direct tunnel messages received int transport_port = 0; try{ punch_mon.enter(); transport_port = ((Integer)wait_data[2]).intValue(); }finally{ punch_mon.exit(); } if ( transport_port != 0 ){ InetSocketAddress existing_address = target.getTransportAddress(); if ( transport_port != existing_address.getPort()){ target.setTransportAddress( new InetSocketAddress(existing_address.getAddress(), transport_port )); } } Map target_client_data = (Map)response.get( "client_data" ); if ( target_client_data == null ){ target_client_data = new HashMap(); } return( target_client_data ); } } return( null ); }catch( Throwable e ){ log(e); return( null ); }finally{ try{ punch_mon.enter(); oustanding_punches.remove( wait_data ); }finally{ punch_mon.exit(); } } } protected void receivePunch( DHTTransportUDPContact originator, Map request, Map response ) { trace( "received punch request" ); boolean ok = false; String target_str = new String((byte[])request.get( "target" )); Object[] entry; try{ server_mon.enter(); entry = (Object[])rendezvous_bindings.get( target_str ); }finally{ server_mon.exit(); } if ( entry != null ){ DHTTransportUDPContact target = (DHTTransportUDPContact)entry[0]; Map target_client_data = sendConnect( target, originator, (Map)request.get( "client_data" )); if ( target_client_data != null ){ response.put( "client_data", target_client_data ); response.put( "port", new Long( target.getTransportAddress().getPort())); ok = true; } } log( "Rendezvous punch request from " + originator.getString() + " to " + target_str + " " + (ok?"initiated":"failed")); response.put( "ok", new Long(ok?1:0)); } protected Map sendConnect( DHTTransportContact target, DHTTransportContact originator, Map originator_client_data ) { try{ Map request = new HashMap(); request.put("type", new Long( RT_CONNECT_REQUEST )); request.put("origin", encodeContact( originator )); request.put( "port", new Long( ((DHTTransportUDPContact)originator).getTransportAddress().getPort())); if ( originator_client_data != null ){ request.put( "client_data", originator_client_data ); } Map response = sendRequest( target, request, TRANSFER_TIMEOUT ); if ( response == null ){ return( null ); } if (((Long)response.get( "type" )).intValue() == RT_CONNECT_REPLY ){ int result = ((Long)response.get("ok")).intValue(); trace( "received connect reply: " + (result==0?"failed":"ok" )); if ( result == 1 ){ Map target_client_data = (Map)response.get( "client_data" ); if ( target_client_data == null ){ target_client_data = new HashMap(); } return( target_client_data ); } } return( null ); }catch( Throwable e ){ log(e); return( null ); } } protected void receiveConnect( DHTTransportContact rendezvous, Map request, Map response ) { trace( "received connect request" ); boolean ok = false; // ensure that we've received this from our current rendezvous node DHTTransportContact rt = rendezvous_target; if ( rt != null && rt.getAddress().equals( rendezvous.getAddress())){ final DHTTransportUDPContact target = decodeContact( (byte[])request.get( "origin" )); if ( target != null ){ int transport_port = 0; Long indirect_port = (Long)request.get( "port" ); if ( indirect_port != null ){ transport_port = indirect_port.intValue(); } if ( transport_port != 0 ){ InetSocketAddress existing_address = target.getTransportAddress(); if ( transport_port != existing_address.getPort()){ target.setTransportAddress( new InetSocketAddress(existing_address.getAddress(), transport_port )); } } Map originator_client_data = (Map)request.get( "client_data" ); boolean no_tunnel = false; if ( originator_client_data == null ){ originator_client_data = new HashMap(); }else{ no_tunnel = originator_client_data.get( "_notunnel" ) != null; } if ( no_tunnel ){ log( "Received message from " + target.getString()); }else{ log( "Received connect request from " + target.getString()); // ping the origin a few times to try and establish a tunnel UTTimerEvent event = timer.addPeriodicEvent( 3000, new UTTimerEventPerformer() { private int pings = 1; public void perform( UTTimerEvent ev ) { if ( pings > 3 ){ ev.cancel(); return; } pings++; if ( sendTunnelInbound( target )){ ev.cancel(); } } }); if ( sendTunnelInbound( target )){ event.cancel(); } } Map client_data = adapter.getClientData( target.getTransportAddress(), originator_client_data ); if ( client_data == null ){ client_data = new HashMap(); } response.put( "client_data", client_data ); ok = true; }else{ log( "Connect request: failed to decode target" ); } }else{ log( "Connect request from invalid rendezvous: " + rendezvous.getString()); } response.put( "ok", new Long(ok?1:0)); } protected boolean sendTunnelInbound( DHTTransportContact target ) { log( "Sending tunnel inbound message to " + target.getString()); try{ Map message = new HashMap(); message.put( "type", new Long( RT_TUNNEL_INBOUND )); return( sendTunnelMessage( target, message )); }catch( Throwable e ){ log(e); return( false ); } } protected void receiveTunnelInbound( DHTTransportUDPContact originator, Map data ) { log( "Received tunnel inbound message from " + originator.getString()); try{ punch_mon.enter(); for (int i=0;i 0 ){ rendezvous_used[0] = rendezvous; } if ( rendezvous == null ){ return( null ); } Map target_client_data = sendPunch( rendezvous, target, originator_client_data, false ); if ( target_client_data != null ){ log( " punch to " + target.getString() + " succeeded" ); return( target_client_data ); } }catch( Throwable e ){ log( e ); } log( " punch to " + target.getString() + " failed" ); return( null ); } public Map sendMessage( InetSocketAddress rendezvous, InetSocketAddress target, Map message ) { try{ DHTTransportUDP transport = (DHTTransportUDP)dht.getTransport(); DHTTransportUDPContact rend_contact = transport.importContact( rendezvous, transport.getProtocolVersion()); DHTTransportUDPContact target_contact = transport.importContact( target, transport.getProtocolVersion()); Map result = sendPunch( rend_contact, target_contact, message, true ); return( result ); }catch( Throwable e ){ Debug.printStackTrace(e); return( null ); } } public void setRendezvous( DHTTransportContact target, DHTTransportContact rendezvous ) { explicit_rendezvous_map.put( target.getAddress(), rendezvous ); if ( target.getAddress().equals( dht.getTransport().getLocalContact().getAddress())){ publish( true ); } } protected DHTTransportContact getRendezvous( String reason, DHTTransportContact target ) { DHTTransportContact explicit = (DHTTransportContact)explicit_rendezvous_map.get( target.getAddress()); if ( explicit != null ){ return( explicit ); } byte[] key = getPublishKey( target ); final DHTTransportValue[] result_value = {null}; final Semaphore sem = plugin_interface.getUtilities().getSemaphore(); dht.get( key, reason + ": lookup for '" + target.getString() + "'", (byte)0, 1, RENDEZVOUS_LOOKUP_TIMEOUT, false, true, new DHTOperationAdapter() { public void read( DHTTransportContact contact, DHTTransportValue value ) { result_value[0] = value; sem.release(); } public void complete( boolean timeout ) { sem.release(); } }); sem.reserve(); DHTTransportContact result = null; if ( result_value[0] != null ){ byte[] bytes = result_value[0].getValue(); try{ ByteArrayInputStream bais = new ByteArrayInputStream( bytes ); DataInputStream dis = new DataInputStream( bais ); byte version = dis.readByte(); if ( version != 0 ){ throw( new Exception( "Unsupported rendezvous version '" + version + "'" )); } result = dht.getTransport().importContact( dis ); }catch( Throwable e ){ log(e); } } log( "Lookup of rendezvous for " + target.getString() + " -> " + ( result==null?"None":result.getString())); return( result ); } protected byte[] getPublishKey( DHTTransportContact contact ) { byte[] id = contact.getID(); byte[] suffix = ":DHTNATPuncher".getBytes(); byte[] res = new byte[id.length + suffix.length]; System.arraycopy( id, 0, res, 0, id.length ); System.arraycopy( suffix, 0, res, id.length, suffix.length ); return( res ); } protected byte[] encodePublishValue( DHTTransportContact contact ) { try{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeByte( 0 ); // version contact.exportContact( dos ); dos.close(); return( baos.toByteArray()); }catch( Throwable e ){ log( e ); return( new byte[0]); } } protected byte[] encodeContact( DHTTransportContact contact ) { try{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); contact.exportContact( dos ); dos.close(); return( baos.toByteArray()); }catch( Throwable e ){ log( e ); return( null ); } } protected DHTTransportUDPContact decodeContact( byte[] bytes ) { try{ ByteArrayInputStream bais = new ByteArrayInputStream( bytes ); DataInputStream dis = new DataInputStream( bais ); return((DHTTransportUDPContact)dht.getTransport().importContact( dis )); }catch( Throwable e ){ log(e); return( null ); } } protected void log( String str ) { if ( TRACE ){ System.out.println( str ); } logger.log( "NATPuncher: " + str ); } protected void log( Throwable e ) { if ( TRACE ){ e.printStackTrace(); } logger.log( "NATPuncher: error occurred" ); logger.log(e); } protected void trace( String str ) { if ( TRACE ){ System.out.println( str ); } } } azureus-4.3.0.6/com/aelitis/azureus/core/dht/nat/DHTNATPuncherFactory.java0000644000175000017500000000240610440744354025546 0ustar adrianadrian/* * Created on 11-Aug-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.dht.nat; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.nat.impl.DHTNATPuncherImpl; public class DHTNATPuncherFactory { public static DHTNATPuncher create( DHTNATPuncherAdapter adapter, DHT dht ) { return( new DHTNATPuncherImpl( adapter, dht )); } } azureus-4.3.0.6/com/aelitis/azureus/activities/0000755000175000017500000000000011310377616020715 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/azureus/activities/VuzeActivitiesListener.java0000644000175000017500000000211511003233026026224 0ustar adrianadrian/** * Created on Jan 28, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.activities; /** * @author TuxPaper * @created Jan 28, 2008 * */ public interface VuzeActivitiesListener { public void vuzeNewsEntriesAdded(VuzeActivitiesEntry[] entries); public void vuzeNewsEntriesRemoved(VuzeActivitiesEntry[] entries); public void vuzeNewsEntryChanged(VuzeActivitiesEntry entry); } azureus-4.3.0.6/com/aelitis/azureus/activities/VuzeActivitiesManager.java0000644000175000017500000003737211307366134026044 0ustar adrianadrian/** * Created on Jan 28, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.activities; import java.net.HttpURLConnection; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter; import com.aelitis.azureus.core.cnetwork.*; import com.aelitis.azureus.core.messenger.config.PlatformVuzeActivitiesMessenger; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.MapUtils; /** * Manage Vuze News Entries. Loads, Saves, and expires them * * @author TuxPaper * @created Jan 28, 2008 * */ public class VuzeActivitiesManager { public static final long MAX_LIFE_MS = 1000L * 60 * 60 * 24 * 30; private static final long DEFAULT_PLATFORM_REFRESH = 60 * 60 * 1000L * 24; private static final String SAVE_FILENAME = "VuzeActivities.config"; private static ArrayList listeners = new ArrayList(); private static ArrayList allEntries = new ArrayList(); private static AEMonitor allEntries_mon = new AEMonitor("VuzeActivityMan"); private static List removedEntries = new ArrayList(); private static PlatformVuzeActivitiesMessenger.GetEntriesReplyListener replyListener; private static AEDiagnosticsLogger diag_logger; /** Key: NetworkID, Value: last time we pulled news **/ private static Map lastNewsAt = new HashMap(); private static boolean skipAutoSave = true; private static AEMonitor config_mon = new AEMonitor("ConfigMon"); private static boolean saveEventsOnClose = false; static { if (System.getProperty("debug.vuzenews", "0").equals("1")) { diag_logger = AEDiagnostics.getLogger("v3.vuzenews"); diag_logger.log("\n\nVuze News Logging Starts"); } else { diag_logger = null; } } public static void initialize(final AzureusCore core) { new AEThread2("lazy init", true) { public void run() { _initialize(core); } }.start(); } private static void _initialize(AzureusCore core) { if (diag_logger != null) { diag_logger.log("Initialize Called"); } core.addLifecycleListener(new AzureusCoreLifecycleAdapter() { public void stopping(AzureusCore core) { if (saveEventsOnClose) { saveEventsNow(); } } }); loadEvents(); ContentNetworkManager cnm = ContentNetworkManagerFactory.getSingleton(); if (cnm != null) { ContentNetwork[] contentNetworks = cnm.getContentNetworks(); cnm.addListener(new ContentNetworkListener() { public void networkRemoved(ContentNetwork network) { } public void networkChanged(ContentNetwork network) { } public void networkAdded(ContentNetwork cn) { setupContentNetwork(cn); } public void networkAddFailed(long network_id, Throwable error) { } }); for (ContentNetwork cn : contentNetworks) { setupContentNetwork(cn); } } replyListener = new PlatformVuzeActivitiesMessenger.GetEntriesReplyListener() { public void gotVuzeNewsEntries(VuzeActivitiesEntry[] entries, long refreshInMS) { if (diag_logger != null) { diag_logger.log("Received Reply from platform with " + entries.length + " entries. Refresh in " + refreshInMS); } addEntries(entries); if (refreshInMS <= 0) { refreshInMS = DEFAULT_PLATFORM_REFRESH; } SimpleTimer.addEvent("GetVuzeNews", SystemTime.getOffsetTime(refreshInMS), new TimerEventPerformer() { public void perform(TimerEvent event) { pullActivitiesNow(5000); } }); } }; pullActivitiesNow(5000); } /** * @param cn * * @since 4.0.0.5 */ private static void setupContentNetwork(final ContentNetwork cn) { cn.addPersistentPropertyChangeListener(new ContentNetworkPropertyChangeListener() { // @see com.aelitis.azureus.core.cnetwork.ContentNetworkPropertyChangeListener#propertyChanged(java.lang.String) public void propertyChanged(String name) { if (!ContentNetwork.PP_ACTIVE.equals(name)) { return; } Object oIsActive = cn.getPersistentProperty(ContentNetwork.PP_ACTIVE); boolean isActive = (oIsActive instanceof Boolean) ? ((Boolean) oIsActive).booleanValue() : false; if (isActive) { pullActivitiesNow(2000); } } }); final String id_str = cn.getServiceURL( ContentNetwork.SERVICE_IDENTIFY ); if ( id_str != null && id_str.length() > 0 ){ try{ SimpleTimer.addPeriodicEvent( "act:id", 23*60*60*1000, new TimerEventPerformer() { public void perform( TimerEvent event ) { identify( cn, id_str ); } }); identify( cn, id_str ); }catch( Throwable e ){ Debug.out( e ); } } } private static void identify( ContentNetwork cn, String str ) { try{ URL url = new URL( str ); HttpURLConnection con = (HttpURLConnection)url.openConnection(); String key = "cn." + cn.getID() + ".identify.cookie"; String cookie = COConfigurationManager.getStringParameter( key, null ); if ( cookie != null ){ con.setRequestProperty( "Cookie", cookie + ";" ); } con.setRequestProperty( "Connection", "close" ); con.getResponseCode(); cookie = con.getHeaderField( "Set-Cookie" ); if ( cookie != null ){ String[] bits = cookie.split( ";" ); if ( bits.length > 0 && bits[0].length() > 0 ){ COConfigurationManager.setParameter( key, bits[0] ); } } }catch( Throwable e ){ } } /** * Pull entries from webapp * * @param agoMS Pull all events within this timespan (ms) * @param delay max time to wait before running request * * @since 3.0.4.3 */ public static void pullActivitiesNow(long delay) { /* ContentNetworkManager cnm = ContentNetworkManagerFactory.getSingleton(); if (cnm == null) { return; } ContentNetwork[] contentNetworks = cnm.getContentNetworks(); for (ContentNetwork cn : contentNetworks) { */ { // short circuit.. only get vuzenews from default network ContentNetwork cn = ConstantsVuze.getDefaultContentNetwork(); if (cn == null) { return; //continue; } Object oIsActive = cn.getPersistentProperty(ContentNetwork.PP_ACTIVE); boolean isActive = (oIsActive instanceof Boolean) ? ((Boolean) oIsActive).booleanValue() : false; if (!isActive) { return; //continue; } String id = "" + cn.getID(); Long oLastPullTime = lastNewsAt.get(id); long lastPullTime = oLastPullTime != null ? oLastPullTime.longValue() : 0; long now = SystemTime.getCurrentTime(); long diff = now - lastPullTime; if (diff < 5000) { return; } if (diff > MAX_LIFE_MS) { diff = MAX_LIFE_MS; } PlatformVuzeActivitiesMessenger.getEntries(cn.getID(), diff, delay, replyListener); lastNewsAt.put(id, new Long(now)); } } public static void clearLastPullTimes() { lastNewsAt = new HashMap(); } /** * Clear the removed entries list so that an entry that was once deleted will * will be able to be added again * * * @since 3.0.4.3 */ public static void resetRemovedEntries() { removedEntries.clear(); saveEvents(); } /** * * * @since 3.1.1.1 */ private static void saveEvents() { saveEventsOnClose = true; } /** * * * @since 3.0.4.3 */ private static void loadEvents() { skipAutoSave = true; try { Map map = FileUtil.readResilientConfigFile(SAVE_FILENAME); // Clear all entries if we aren't on v2 if (map != null && map.size() > 0 && MapUtils.getMapLong(map, "version", 0) < 2) { clearLastPullTimes(); skipAutoSave = false; saveEventsNow(); return; } long cutoffTime = getCutoffTime(); try { lastNewsAt = MapUtils.getMapMap(map, "LastChecks", new HashMap()); } catch (Exception e) { Debug.out(e); } // "LastCheck" backward compat if (lastNewsAt.size() == 0) { long lastVuzeNewsAt = MapUtils.getMapLong(map, "LastCheck", 0); if (lastVuzeNewsAt > 0) { if (lastVuzeNewsAt < cutoffTime) { lastVuzeNewsAt = cutoffTime; } lastNewsAt.put("" + ContentNetwork.CONTENT_NETWORK_VUZE, new Long( lastVuzeNewsAt)); } } Object value; List newRemovedEntries = (List) MapUtils.getMapObject(map, "removed-entries", null, List.class); if (newRemovedEntries != null) { for (Iterator iter = newRemovedEntries.iterator(); iter.hasNext();) { value = iter.next(); if (!(value instanceof Map)) { continue; } VuzeActivitiesEntry entry = createEntryFromMap((Map) value, true); if (entry != null && entry.getTimestamp() > cutoffTime) { removedEntries.add(entry); } } } value = map.get("entries"); if (!(value instanceof List)) { return; } List entries = (List) value; List entriesToAdd = new ArrayList(entries.size()); for (Iterator iter = entries.iterator(); iter.hasNext();) { value = iter.next(); if (!(value instanceof Map)) { continue; } VuzeActivitiesEntry entry = createEntryFromMap((Map) value, true); if (entry != null) { if (entry.getTimestamp() > cutoffTime) { entriesToAdd.add(entry); } } } int num = entriesToAdd.size(); if (num > 0) { addEntries((VuzeActivitiesEntry[]) entriesToAdd.toArray(new VuzeActivitiesEntry[num])); } } finally { skipAutoSave = false; } } private static void saveEventsNow() { if (skipAutoSave) { return; } try { config_mon.enter(); Map mapSave = new HashMap(); mapSave.put("LastChecks", lastNewsAt); mapSave.put("version", new Long(2)); List entriesList = new ArrayList(); VuzeActivitiesEntry[] allEntriesArray = getAllEntries(); for (int i = 0; i < allEntriesArray.length; i++) { VuzeActivitiesEntry entry = allEntriesArray[i]; if (entry == null) { continue; } boolean isHeader = VuzeActivitiesConstants.TYPEID_HEADER.equals(entry.getTypeID()); if (!isHeader) { entriesList.add(entry.toMap()); } } mapSave.put("entries", entriesList); List removedEntriesList = new ArrayList(); for (Iterator iter = removedEntries.iterator(); iter.hasNext();) { VuzeActivitiesEntry entry = iter.next(); removedEntriesList.add(entry.toDeletedMap()); } mapSave.put("removed-entries", removedEntriesList); FileUtil.writeResilientConfigFile(SAVE_FILENAME, mapSave); } catch (Throwable t) { Debug.out(t); } finally { config_mon.exit(); } } public static long getCutoffTime() { return SystemTime.getOffsetTime(-MAX_LIFE_MS); } public static void addListener(VuzeActivitiesListener l) { listeners.add(l); } public static void removeListener(VuzeActivitiesListener l) { listeners.remove(l); } /** * * @param entries * @return list of entries actually added (no dups) * * @since 3.0.4.3 */ public static VuzeActivitiesEntry[] addEntries(VuzeActivitiesEntry[] entries) { long cutoffTime = getCutoffTime(); ArrayList newEntries = new ArrayList(entries.length); ArrayList existingEntries = new ArrayList(0); try { allEntries_mon.enter(); for (int i = 0; i < entries.length; i++) { VuzeActivitiesEntry entry = entries[i]; boolean isHeader = VuzeActivitiesConstants.TYPEID_HEADER.equals(entry.getTypeID()); if ((entry.getTimestamp() >= cutoffTime || isHeader) && !removedEntries.contains(entry)) { if (allEntries.contains(entry)) { existingEntries.add(entry); } else { newEntries.add(entry); allEntries.add(entry); } } } } finally { allEntries_mon.exit(); } VuzeActivitiesEntry[] newEntriesArray = (VuzeActivitiesEntry[]) newEntries.toArray(new VuzeActivitiesEntry[newEntries.size()]); if (newEntriesArray.length > 0) { saveEventsNow(); Object[] listenersArray = listeners.toArray(); for (int i = 0; i < listenersArray.length; i++) { VuzeActivitiesListener l = (VuzeActivitiesListener) listenersArray[i]; l.vuzeNewsEntriesAdded(newEntriesArray); } } if (existingEntries.size() > 0) { if (newEntriesArray.length == 0) { saveEvents(); } for (Iterator iter = existingEntries.iterator(); iter.hasNext();) { VuzeActivitiesEntry entry = iter.next(); triggerEntryChanged(entry); } } return newEntriesArray; } public static void removeEntries(VuzeActivitiesEntry[] entries) { removeEntries(entries, false); } public static void removeEntries(VuzeActivitiesEntry[] entries, boolean allowReAdd) { long cutoffTime = getCutoffTime(); try { allEntries_mon.enter(); for (int i = 0; i < entries.length; i++) { VuzeActivitiesEntry entry = entries[i]; if (entry == null) { continue; } allEntries.remove(entry); boolean isHeader = VuzeActivitiesConstants.TYPEID_HEADER.equals(entry.getTypeID()); if (!allowReAdd && entry.getTimestamp() > cutoffTime && !isHeader) { removedEntries.add(entry); } } } finally { allEntries_mon.exit(); } Object[] listenersArray = listeners.toArray(); for (int i = 0; i < listenersArray.length; i++) { VuzeActivitiesListener l = (VuzeActivitiesListener) listenersArray[i]; l.vuzeNewsEntriesRemoved(entries); } saveEventsNow(); } public static VuzeActivitiesEntry getEntryByID(String id) { try { allEntries_mon.enter(); for (Iterator iter = allEntries.iterator(); iter.hasNext();) { VuzeActivitiesEntry entry = iter.next(); if (entry == null) { continue; } String entryID = entry.getID(); if (entryID != null && entryID.equals(id)) { return entry; } } } finally { allEntries_mon.exit(); } return null; } public static VuzeActivitiesEntry[] getAllEntries() { return allEntries.toArray(new VuzeActivitiesEntry[allEntries.size()]); } public static int getNumEntries() { return allEntries.size(); } public static void log(String s) { if (diag_logger != null) { diag_logger.log(s); } } /** * @param vuzeActivitiesEntry * * @since 3.0.4.3 */ public static void triggerEntryChanged(VuzeActivitiesEntry entry) { Object[] listenersArray = listeners.toArray(); for (int i = 0; i < listenersArray.length; i++) { VuzeActivitiesListener l = (VuzeActivitiesListener) listenersArray[i]; l.vuzeNewsEntryChanged(entry); } saveEvents(); } public static VuzeActivitiesEntry createEntryFromMap(Map map, boolean internalMap) { return createEntryFromMap(ContentNetwork.CONTENT_NETWORK_VUZE, map, internalMap); } /** * @param map * @return * * @since 3.0.5.3 */ public static VuzeActivitiesEntry createEntryFromMap( long defaultContentNetworkID, Map map, boolean internalMap) { VuzeActivitiesEntry entry; String typeID = MapUtils.getMapString(map, "typeID", MapUtils.getMapString( map, "type-id", null)); entry = new VuzeActivitiesEntry(); entry.setContentNetworkID(defaultContentNetworkID); if (internalMap) { entry.loadFromInternalMap(map); } else { entry.loadFromExternalMap(map); } return entry; } } azureus-4.3.0.6/com/aelitis/azureus/activities/VuzeActivitiesEntry.java0000644000175000017500000003576311267524522025577 0ustar adrianadrian/** * Created on Jan 28, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.activities; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.torrent.TOTorrentFactory; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.common.table.TableColumnSortObject; import com.aelitis.azureus.ui.selectedcontent.SelectedContentV3; import com.aelitis.azureus.ui.utils.ImageBytesDownloader; import com.aelitis.azureus.ui.utils.ImageBytesDownloader.ImageDownloaderListener; import com.aelitis.azureus.util.*; /** * * Comparable implementation sorts on timestamp.

    * equals() implementation compares IDs * * @author TuxPaper * @created Jan 28, 2008 * */ public class VuzeActivitiesEntry implements TableColumnSortObject { private String text; private String iconID; private String id; private long timestamp; private String typeID; private String assetHash; private String assetImageURL; private DownloadManager dm; public Object urlInfo; public TableColumnCore tableColumn; private byte[] imageBytes; private boolean showThumb = true; private String torrentName; private TOTorrent torrent; private boolean isDRM; private boolean isPlatformContent; private boolean playable; private long readOn; private GlobalManager gm = null; private long contentNetworkID = ContentNetwork.CONTENT_NETWORK_VUZE; public VuzeActivitiesEntry(long timestamp, String text, String typeID) { this.setText(text); this.timestamp = timestamp; this.setTypeID(typeID, true); } public VuzeActivitiesEntry(long timestamp, String text, String icon, String id, String typeID, String assetHash) { this.timestamp = timestamp; this.setText(text); this.setIconID(icon); this.setID(id); this.setTypeID(typeID, true); this.setAssetHash(assetHash); } /** * */ public VuzeActivitiesEntry() { this.timestamp = SystemTime.getCurrentTime(); } /** * @param platformEntry */ public void loadFromExternalMap(Map platformEntry) { timestamp = SystemTime.getCurrentTime() - MapUtils.getMapLong(platformEntry, "age-ms", 0); setIconID(MapUtils.getMapString(platformEntry, "icon-url", MapUtils.getMapString(platformEntry, "icon-id", null))); setTypeID(MapUtils.getMapString(platformEntry, "type-id", null), true); setAssetHash(MapUtils.getMapString(platformEntry, "related-asset-hash", null)); setAssetImageURL(MapUtils.getMapString(platformEntry, "related-image-url", null)); setDRM(MapUtils.getMapBoolean(platformEntry, "no-play", false)); setTorrentName(MapUtils.getMapString(platformEntry, "related-asset-name", null)); setReadOn(MapUtils.getMapLong(platformEntry, "readOn", 0)); loadCommonFromMap(platformEntry); } public void loadFromInternalMap(Map map) { timestamp = MapUtils.getMapLong(map, "timestamp", 0); if (timestamp == 0) { timestamp = SystemTime.getCurrentTime(); } setAssetHash(MapUtils.getMapString(map, "assetHash", null)); setIconID(MapUtils.getMapString(map, "icon", null)); setTypeID(MapUtils.getMapString(map, "typeID", null), true); setShowThumb(MapUtils.getMapLong(map, "showThumb", 1) == 1); setAssetImageURL(MapUtils.getMapString(map, "assetImageURL", null)); setImageBytes(MapUtils.getMapByteArray(map, "imageBytes", null)); setDRM(MapUtils.getMapBoolean(map, "isDRM", false)); setReadOn(MapUtils.getMapLong(map, "readOn", SystemTime.getCurrentTime())); loadCommonFromMap(map); } public void loadCommonFromMap(Map map) { if (!isPlatformContent) { setIsPlatformContent(MapUtils.getMapBoolean(map, "is-platform", isPlatformContent)); } if (!playable) { setPlayable(MapUtils.getMapBoolean(map, "playable", false)); } setID(MapUtils.getMapString(map, "id", null)); setText(MapUtils.getMapString(map, "text", null)); Map torrentMap = MapUtils.getMapMap(map, "torrent", null); if (torrentMap != null) { TOTorrent torrent = null; try { torrent = TOTorrentFactory.deserialiseFromMap(torrentMap); setTorrent(torrent); } catch (TOTorrentException e) { } } if (dm == null && torrentName == null) { setTorrentName(MapUtils.getMapString(map, "torrent-name", null)); } setContentNetworkID(MapUtils.getMapLong(map, "contentNetworkID", contentNetworkID)); } // @see java.lang.Object#equals(java.lang.Object) public boolean equals(Object obj) { if ((obj instanceof VuzeActivitiesEntry) && id != null) { return id.equals(((VuzeActivitiesEntry) obj).id); } return super.equals(obj); } // @see java.lang.Comparable#compareTo(java.lang.Object) public int compareTo(Object obj) { if (obj instanceof VuzeActivitiesEntry) { VuzeActivitiesEntry otherEntry = (VuzeActivitiesEntry) obj; long x = (timestamp - otherEntry.timestamp); return x == 0 ? 0 : x > 0 ? 1 : -1; } // we are bigger return 1; } public void setAssetImageURL(final String url) { if (url == null && assetImageURL == null) { return; } if (url == null || url.length() == 0) { assetImageURL = null; VuzeActivitiesManager.triggerEntryChanged(VuzeActivitiesEntry.this); return; } if (url.equals(assetImageURL)) { return; } assetImageURL = url; ImageBytesDownloader.loadImage(url, new ImageDownloaderListener() { public void imageDownloaded(byte[] image) { setImageBytes(image); VuzeActivitiesManager.triggerEntryChanged(VuzeActivitiesEntry.this); } }); } public String getAssetImageURL() { return assetImageURL; } public Map toDeletedMap() { Map map = new HashMap(); map.put("timestamp", new Long(timestamp)); map.put("id", id); return map; } public Map toMap() { Map map = new HashMap(); map.put("timestamp", new Long(timestamp)); if (assetHash != null) { map.put("assetHash", assetHash); } map.put("icon", getIconID()); map.put("id", id); map.put("text", getText()); map.put("typeID", getTypeID()); map.put("assetImageURL", assetImageURL); map.put("showThumb", new Long(getShowThumb() ? 1 : 0)); if (imageBytes != null) { map.put("imageBytes", imageBytes); } else if (dm != null) { byte[] thumbnail = PlatformTorrentUtils.getContentThumbnail(dm.getTorrent()); if (thumbnail != null) { map.put("imageBytes", thumbnail); } } if (torrent != null && (dm == null || assetHash == null)) { try { // make a copy of the torrent Map torrent_map = torrent.serialiseToMap(); TOTorrent torrent_to_send = TOTorrentFactory.deserialiseFromMap( torrent_map ); Map vuze_map = (Map)torrent_map.get( "vuze" ); // remove any non-standard stuff (e.g. resume data) torrent_to_send.removeAdditionalProperties(); torrent_map = torrent_to_send.serialiseToMap(); if ( vuze_map != null ){ torrent_map.put( "vuze", vuze_map ); } map.put("torrent", torrent_map ); } catch (TOTorrentException e) { Debug.outNoStack("VuzeActivityEntry.toMap: " + e.toString()); } } map.put("isDRM", new Long(isDRM() ? 1 : 0)); if (torrentName != null) { map.put("torrent-name", torrentName); } map.put("is-platform", new Long(isPlatformContent ? 1 : 0)); if (playable) { map.put("playable", new Long(playable ? 1 : 0)); } map.put("readOn", new Long(readOn)); map.put("contentNetworkID", new Long(contentNetworkID)); return map; } public long getTimestamp() { return timestamp; } public void setTimestamp(long timestamp) { if (this.timestamp == timestamp) { return; } this.timestamp = timestamp; if (tableColumn != null) { tableColumn.setLastSortValueChange(SystemTime.getCurrentTime()); } } /** * @param typeID the typeID to set */ public void setTypeID(String typeID, boolean autoSetIcon) { this.typeID = typeID; if (getIconID() == null && typeID != null) { setIconID("image.vuze-entry." + typeID.toLowerCase()); } if (VuzeActivitiesConstants.TYPEID_CONTENT_PROMO.equals(typeID)) { setIsPlatformContent(true); setPlayable(true); } } /** * @return the typeID */ public String getTypeID() { return typeID; } /** * @param iconID the iconID to set */ public void setIconID(String iconID) { if (iconID != null && iconID.indexOf("image.") < 0 && !iconID.startsWith("http")) { iconID = "image.vuze-entry." + iconID; } this.iconID = iconID; } /** * @return the iconID */ public String getIconID() { return iconID; } /** * @param text the text to set */ public void setText(String text) { this.text = text; } /** * @return the text */ public String getText() { return text; } /** * @param id the id to set */ public void setID(String id) { this.id = id; } /** * @return the id */ public String getID() { return id; } /** * @param assetHash the assetHash to set */ public void setAssetHash(String assetHash) { this.assetHash = assetHash; if (assetHash != null) { try { if (gm == null) { gm = AzureusCoreFactory.getSingleton().getGlobalManager(); } setDownloadManager(gm.getDownloadManager(new HashWrapper( Base32.decode(assetHash)))); } catch (Exception e) { setDownloadManager(null); Debug.out("Core not ready", e); } } else { setDownloadManager(null); } } /** * @return the assetHash */ public String getAssetHash() { return assetHash; } /** * @param dm the dm to set */ public void setDownloadManager(DownloadManager dm) { if (this.dm == dm) { return; } if (gm == null) { try { gm = AzureusCoreFactory.getSingleton().getGlobalManager(); } catch (Exception e) { // ignore } } this.dm = dm; if (dm != null) { setTorrent(dm.getTorrent()); } } /** * @return the dm */ public DownloadManager getDownloadManger() { if (gm != null && !gm.contains(dm)) { setDownloadManager(null); return null; } return dm; } /** * @param imageBytes the imageBytes to set */ public void setImageBytes(byte[] imageBytes) { this.imageBytes = imageBytes; } /** * @return the imageBytes */ public byte[] getImageBytes() { return imageBytes; } /** * @param showThumb the showThumb to set */ public void setShowThumb(boolean showThumb) { this.showThumb = showThumb; } /** * @return the showThumb */ public boolean getShowThumb() { return showThumb; } /** * Independant for {@link #getDownloadManger()}. This will be written to * the map. * * @return Only returns TOTorrent set via {@link #setTorrent(TOTorrent)} * * @since 3.0.5.3 */ public TOTorrent getTorrent() { return torrent; } /** * Not needed if you {@link #setDownloadManager(DownloadManager)}. This will * be written the map. * * @param torrent * * @since 3.0.5.3 */ public void setTorrent(TOTorrent torrent) { this.torrent = torrent; try { assetHash = torrent.getHashWrapper().toBase32String(); } catch (Exception e) { } setContentNetworkID(PlatformTorrentUtils.getContentNetworkID(torrent)); setDRM(torrent == null ? false : PlatformTorrentUtils.isContentDRM(torrent)); setIsPlatformContent(torrent == null ? false : PlatformTorrentUtils.isContent(torrent, true)); } public boolean isDRM() { return isDRM; } public void setDRM(boolean isDRM) { this.isDRM = isDRM; } public String getTorrentName() { if (torrentName == null) { if (dm != null) { return PlatformTorrentUtils.getContentTitle2(dm); } if (torrent != null) { return TorrentUtils.getLocalisedName(torrent); } } return torrentName; } public void setTorrentName(String torrentName) { this.torrentName = torrentName; } public SelectedContentV3 createSelectedContentObject() throws Exception { boolean ourContent = DataSourceUtils.isPlatformContent(this); SelectedContentV3 sc = new SelectedContentV3(); if (assetHash == null) { // Contains no content return sc; } dm = getDownloadManger(); if (dm != null) { sc.setDisplayName(PlatformTorrentUtils.getContentTitle2(dm)); sc.setDownloadManager(dm); return sc; }else{ if ( torrent != null ){ sc.setTorrent( torrent ); } } sc.setDisplayName(getTorrentName()); if (sc.getDisplayName() == null) { TOTorrent torrent = getTorrent(); if (torrent != null) { sc.setDisplayName(TorrentUtils.getLocalisedName(torrent)); sc.setHash(torrent.getHashWrapper().toBase32String(), ourContent); } } if (sc.getHash() == null ){ if ( assetHash != null ){ sc.setHash(assetHash, true); } } sc.setThumbURL(assetImageURL); sc.setImageBytes(imageBytes); return sc; } public boolean isPlatformContent() { return isPlatformContent; } public void setIsPlatformContent(boolean isPlatformContent) { this.isPlatformContent = isPlatformContent; } public boolean isPlayable() { // our variable is an override if (playable) { return true; } // use torrent so we don't recurse return PlayUtils.canPlayDS(DataSourceUtils.getTorrent(this)); } public void setPlayable(boolean playable) { this.playable = playable; } public long getReadOn() { return readOn; } public void setReadOn(long readOn) { if (this.readOn == readOn) { return; } this.readOn = readOn; VuzeActivitiesManager.triggerEntryChanged(VuzeActivitiesEntry.this); } public void setRead(boolean read) { long now = SystemTime.getCurrentTime(); if (read) { setReadOn(now); } else { setReadOn(now * -1); } } public boolean isRead() { return readOn > 0; } public boolean canFlipRead() { long ofs = SystemTime.getOffsetTime(-300); if (readOn > 0) { return ofs > readOn; } else { return ofs > (-1 * readOn); } } public long getContentNetworkID() { return contentNetworkID; } public ContentNetwork getContentNetwork() { ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetwork(contentNetworkID); if (cn == null) { cn = ConstantsVuze.getDefaultContentNetwork(); } return cn; } public void setContentNetworkID(long contentNetworkID) { this.contentNetworkID = contentNetworkID; } } azureus-4.3.0.6/com/aelitis/azureus/activities/VuzeActivitiesConstants.java0000644000175000017500000000221211267001364026423 0ustar adrianadrian/** * Created on May 28, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.activities; /** * @author TuxPaper * @created May 28, 2008 * */ public class VuzeActivitiesConstants { public static final String TYPEID_HEADER = "Header"; public static final String TYPEID_VUZENEWS = "VUZE_NEWS_ITEM"; public static final String TYPEID_CHANNEL_ANNOUNCE = "CHANNEL_ANNOUNCE"; public static final String TYPEID_CONTENT_PROMO = "CONTENT_PROMO"; } azureus-4.3.0.6/com/aelitis/net/0000755000175000017500000000000011310377330015632 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/upnp/0000755000175000017500000000000011310377632016621 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/upnp/UPnPException.java0000644000175000017500000000231011012742132022147 0ustar adrianadrian/* * Created on 14-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; /** * @author parg * */ public class UPnPException extends Exception { public UPnPException( String str ) { super( str ); } public UPnPException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPActionInvocation.java0000644000175000017500000000252610417310750023476 0ustar adrianadrian/* * Created on 15-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; import java.util.Map; /** * @author parg * */ public interface UPnPActionInvocation { public void addArgument( String name, String value ); /** * returns the out/parameters and response * @return * @throws UPnPException */ public UPnPActionArgument[] invoke() throws UPnPException; public Map invoke2() throws UPnPException; } azureus-4.3.0.6/com/aelitis/net/upnp/UPnP.java0000644000175000017500000000331211246134570020305 0ustar adrianadrian/* * Created on 14-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; import java.util.Map; /** * @author parg * */ public interface UPnP { public UPnPRootDevice[] getRootDevices(); /** * resets by removing all root devices and then rediscovering them * */ public void reset(); /** * scan for new */ public void search(); public void search( String[] STs ); public void injectDiscoveryCache( Map cache ); /** * Logs a message to all registered log listeners * @param str */ public void log( String str ); public void addRootDeviceListener( UPnPListener l ); public void removeRootDeviceListener( UPnPListener l ); public void addLogListener( UPnPLogListener l ); public void removeLogListener( UPnPLogListener l ); } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPActionArgument.java0000644000175000017500000000213510373051020023134 0ustar adrianadrian/* * Created on 15-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; /** * @author parg * */ public interface UPnPActionArgument { public String getName(); public String getValue(); } azureus-4.3.0.6/com/aelitis/net/upnp/impl/0000755000175000017500000000000011310377632017562 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/upnp/impl/SSDPIGD.java0000644000175000017500000000244411142674624021532 0ustar adrianadrian/* * Created on 14-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp.impl; /** * @author parg * */ import com.aelitis.net.upnp.*; public interface SSDPIGD { public void start() throws UPnPException; public void searchNow(); public void searchNow( String[] STs ); public void addListener( SSDPIGDListener l ); public void removeListener( SSDPIGDListener l ); } azureus-4.3.0.6/com/aelitis/net/upnp/impl/services/0000755000175000017500000000000011310377632021405 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/upnp/impl/services/UPnPActionInvocationImpl.java0000644000175000017500000001012610577014714027107 0ustar adrianadrian/* * Created on 15-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp.impl.services; /** * @author parg * */ import java.util.*; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentNode; import com.aelitis.net.upnp.*; import com.aelitis.net.upnp.impl.device.UPnPDeviceImpl; public class UPnPActionInvocationImpl implements UPnPActionInvocation { protected UPnPActionImpl action; protected List arg_names = new ArrayList(); protected List arg_values = new ArrayList(); protected UPnPActionInvocationImpl( UPnPActionImpl _action ) { action = _action; } public void addArgument( String name, String value ) { arg_names.add( name ); arg_values.add( value ); } public UPnPActionArgument[] invoke() throws UPnPException { UPnPService service = action.getService(); String soap_action = service.getServiceType() + "#" + action.getName(); try{ String request = "\n"+ "\n"+ " \n"; request += " \n"; for (int i=0;i" + value + "\n"; } request += " \n"; request += " \n"+ ""; // try standard POST SimpleXMLParserDocument resp_doc = ((UPnPDeviceImpl)action.getService().getDevice()).getUPnP().performSOAPRequest( service, soap_action, request ); SimpleXMLParserDocumentNode body = resp_doc.getChild( "Body" ); SimpleXMLParserDocumentNode fault = body.getChild( "Fault" ); if ( fault != null ){ throw( new UPnPException( "Invoke of '" + soap_action + "' failed - fault reported: " + fault.getValue())); } SimpleXMLParserDocumentNode resp_node = body.getChild( action.getName() + "Response" ); if ( resp_node == null ){ throw( new UPnPException( "Invoke of '" + soap_action + "' failed - response missing: " + body.getValue())); } SimpleXMLParserDocumentNode[] out_nodes = resp_node.getChildren(); UPnPActionArgument[] resp = new UPnPActionArgument[out_nodes.length]; for (int i=0;i"+ ""+ ""; request += "" + "" + name + "" + ""; request += ""+ ""; SimpleXMLParserDocument resp_doc = ((UPnPDeviceImpl)service.getDevice()).getUPnP().performSOAPRequest( service, soap_action, request ); SimpleXMLParserDocumentNode body = resp_doc.getChild( "Body" ); SimpleXMLParserDocumentNode fault = body.getChild( "Fault" ); if ( fault != null ){ throw( new UPnPException( "Invoke fails - fault reported: " + fault.getValue())); } SimpleXMLParserDocumentNode resp_node = body.getChild( "QueryStateVariableResponse" ); if ( resp_node == null ){ throw( new UPnPException( "Invoke fails - response missing: " + body.getValue())); } SimpleXMLParserDocumentNode value_node = resp_node.getChild( "return" ); return( value_node.getValue()); }catch( Throwable e ){ if ( e instanceof UPnPException ){ throw((UPnPException)e); } throw( new UPnPException( "Invoke fails", e )); } } }azureus-4.3.0.6/com/aelitis/net/upnp/impl/services/UPnPActionImpl.java0000644000175000017500000000321010373051012025033 0ustar adrianadrian/* * Created on 15-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp.impl.services; /** * @author parg * */ import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentNode; import com.aelitis.net.upnp.*; public class UPnPActionImpl implements UPnPAction { protected UPnPServiceImpl service; protected String name; protected UPnPActionImpl( UPnPServiceImpl _service, SimpleXMLParserDocumentNode node ) { service = _service; name = node.getChild( "name" ).getValue().trim(); } public String getName() { return( name ); } public UPnPService getService() { return( service ); } public UPnPActionInvocation getInvocation() { return( new UPnPActionInvocationImpl( this )); } } azureus-4.3.0.6/com/aelitis/net/upnp/impl/services/UPnPSSOfflineDownloaderImpl.java0000644000175000017500000001733211245670722027515 0ustar adrianadrian/* * Created on 16-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp.impl.services; import com.aelitis.net.upnp.UPnPAction; import com.aelitis.net.upnp.UPnPActionArgument; import com.aelitis.net.upnp.UPnPActionInvocation; import com.aelitis.net.upnp.UPnPException; import com.aelitis.net.upnp.UPnPService; import com.aelitis.net.upnp.services.UPnPOfflineDownloader; public class UPnPSSOfflineDownloaderImpl implements UPnPOfflineDownloader { private UPnPServiceImpl service; protected UPnPSSOfflineDownloaderImpl( UPnPServiceImpl _service ) { service = _service; } public UPnPService getGenericService() { return( service ); } public long getFreeSpace( String client_id ) throws UPnPException { UPnPAction act = service.getAction( "GetFreeSpace" ); if ( act == null ){ throw( new UPnPException( "GetFreeSpace not supported" )); }else{ UPnPActionInvocation inv = act.getInvocation(); inv.addArgument( "NewClientID", client_id ); UPnPActionArgument[] args = inv.invoke(); for (int i=0;i 0 ){ if ( !last_mapping_check_failed ){ last_mapping_check_failed = true; log = true; } }else{ last_mapping_check_failed = false; } it = mappings_copy.iterator(); while( it.hasNext()){ portMapping mapping = (portMapping)it.next(); try{ // some routers appear to continually fail to report the mappings - avoid // reporting this if ( log ){ log( "Re-establishing mapping " + mapping.getString()); } addPortMapping( mapping.isTCP(), mapping.getExternalPort(), mapping.getDescription()); }catch( Throwable e ){ Debug.printStackTrace(e); } } } public void addPortMapping( boolean tcp, // false -> UDP int port, String description ) throws UPnPException { UPnPAction act = service.getAction( "AddPortMapping" ); if ( act == null ){ log( "Action 'AddPortMapping' not supported, binding not established" ); }else{ UPnPActionInvocation add_inv = act.getInvocation(); add_inv.addArgument( "NewRemoteHost", "" ); // "" = wildcard for hosts, 0 = wildcard for ports add_inv.addArgument( "NewExternalPort", "" + port ); add_inv.addArgument( "NewProtocol", tcp?"TCP":"UDP" ); add_inv.addArgument( "NewInternalPort", "" + port ); add_inv.addArgument( "NewInternalClient", service.getDevice().getRootDevice().getLocalAddress().getHostAddress()); add_inv.addArgument( "NewEnabled", "1" ); add_inv.addArgument( "NewPortMappingDescription", description ); add_inv.addArgument( "NewLeaseDuration", "0" ); // 0 -> infinite (?) boolean ok = false; try{ add_inv.invoke(); ok = true; }catch( UPnPException original_error ){ // some routers won't add properly if the mapping's already there try{ log("Problem when adding port mapping - will try to see if an existing mapping is in the way"); deletePortMapping(tcp, port); }catch( Throwable e ){ throw( original_error ); } add_inv.invoke(); ok = true; }finally{ ((UPnPRootDeviceImpl)service.getDevice().getRootDevice()).portMappingResult(ok); for (int i=0;i 4000 ){ String info = service.getDevice().getRootDevice().getInfo(); ((UPnPImpl)service.getDevice().getRootDevice().getUPnP()).logAlert( "UPnP device '" + info + "' is taking a long time to release port mappings, consider disabling this via the UPnP configuration.", false, UPnPLogListener.TYPE_ONCE_EVER ); } }catch( UPnPException e ){ // only bitch about the failure if we believed we mapped it in the first place if ( mapping_found ){ throw( e ); }else{ log( "Removal of mapping failed but not established explicitly so ignoring error" ); } } } } public UPnPWANConnectionPortMapping[] getPortMappings() throws UPnPException { boolean ok = true; try{ //UPnPStateVariable noe = service.getStateVariable("PortMappingNumberOfEntries"); //System.out.println( "NOE = " + noe.getValue()); int entries = 0; //Integer.parseInt( noe.getValue()); // some routers (e.g. Gudy's) return 0 here whatever! // In this case take mindless approach // hmm, even for my router the state variable isn't accurate... UPnPAction act = service.getAction( "GetGenericPortMappingEntry" ); if ( act == null ){ log( "Action 'GetGenericPortMappingEntry' not supported, can't enumerate bindings" ); return( new UPnPWANConnectionPortMapping[0] ); }else{ List res = new ArrayList(); // I've also seen some routers loop here rather than failing when the index gets too large (they // seem to keep returning the last entry) - check for a duplicate entry and exit if found portMapping prev_mapping = null; for (int i=0;i<(entries==0?512:entries);i++){ UPnPActionInvocation inv = act.getInvocation(); inv.addArgument( "NewPortMappingIndex", "" + i ); try{ UPnPActionArgument[] outs = inv.invoke(); int port = 0; boolean tcp = false; String internal_host = null; String description = ""; for (int j=0;j3Com ADSL 11g 1.07 http://www.3com.com/ */ manufacturer = getOptionalField( device_node, "manufacturer" ); manufacturer_url = getOptionalField( device_node, "manufacturerURL" ); model_description = getOptionalField( device_node, "modelDescription" ); model_name = getOptionalField( device_node, "modelName" ); model_number = getOptionalField( device_node, "modelNumber"); model_url = getOptionalField( device_node, "modelURL"); presentation_url = getOptionalField( device_node, "presentationURL"); boolean interested = device_type.equalsIgnoreCase( "urn:schemas-upnp-org:device:WANConnectionDevice:1" ); root_device.getUPnP().log( indent + friendly_name + (interested?" *":"")); SimpleXMLParserDocumentNode service_list = device_node.getChild( "ServiceList" ); if ( service_list != null ){ SimpleXMLParserDocumentNode[] service_nodes = service_list.getChildren(); for (int i=0;i" ); } return( child.getValue().trim()); } } azureus-4.3.0.6/com/aelitis/net/upnp/impl/device/UPnPRootDeviceImpl.java0000644000175000017500000002252211246134570025317 0ustar adrianadrian/* * Created on 14-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp.impl.device; /** * @author parg * */ import java.util.*; import java.net.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentNode; import com.aelitis.net.upnp.*; import com.aelitis.net.upnp.impl.UPnPImpl; public class UPnPRootDeviceImpl implements UPnPRootDevice { public static final String ROUTERS[] = { "3Com ADSL 11g", //"WRT54G", }; public static final String BAD_ROUTER_VERSIONS[] = { "2.05", //"any", }; public static final boolean BAD_ROUTER_REPORT_FAIL[] = { true, // report on fail //true, // report always removed, apparently it works OK now according to manufacturer }; final private UPnPImpl upnp; final private NetworkInterface network_interface; final private InetAddress local_address; final private String usn; final private URL location; private URL url_base_for_relative_urls; private URL saved_url_base_for_relative_urls; private String info; private UPnPDeviceImpl root_device; private boolean port_mapping_result_received; private boolean destroyed; private List listeners = new ArrayList(); public UPnPRootDeviceImpl( UPnPImpl _upnp, NetworkInterface _network_interface, InetAddress _local_address, String _usn, URL _location ) throws UPnPException { upnp = _upnp; network_interface = _network_interface; local_address = _local_address; usn = _usn; location = _location; SimpleXMLParserDocument doc = upnp.downloadXML( this, location ); SimpleXMLParserDocumentNode url_base_node = doc.getChild("URLBase"); try{ if ( url_base_node != null ){ String url_str = url_base_node.getValue().trim(); // url_str is sometimes blank if ( url_str.length() > 0 ){ url_base_for_relative_urls = new URL(url_str); } } upnp.log( "Relative URL base is " + (url_base_for_relative_urls==null?"unspecified":url_base_for_relative_urls.toString())); }catch( MalformedURLException e ){ upnp.log( "Invalid URLBase - " + (url_base_node==null?"mill":url_base_node.getValue())); upnp.log( e ); Debug.printStackTrace( e ); } SimpleXMLParserDocumentNode device = doc.getChild( "Device" ); if ( device == null ){ throw( new UPnPException( "Root device '" + usn + "(" + location + ") is missing the device description" )); } root_device = new UPnPDeviceImpl( this, "", device ); info = root_device.getFriendlyName(); String version = root_device.getModelNumber(); if ( version != null ){ info += "/" + version; } } public Map getDiscoveryCache() { try{ Map cache = new HashMap(); cache.put( "ni", network_interface.getName().getBytes( "UTF-8" )); cache.put( "la", local_address.getHostAddress().getBytes( "UTF-8" )); cache.put( "usn", usn.getBytes( "UTF-8" )); cache.put( "loc", location.toExternalForm().getBytes( "UTF-8" )); return( cache ); }catch( Throwable e ){ Debug.printStackTrace(e); return( null ); } } public void portMappingResult( boolean ok ) { if ( port_mapping_result_received ){ return; } port_mapping_result_received = true; if ( ok ){ info += "/OK"; }else{ info += "/Failed"; } String model = root_device.getModelName(); String version = root_device.getModelNumber(); if ( model == null || version == null ){ return; } for (int i=0;i 20 ) Comparator comp = upnp.getAdapter().getAlphanumericComparator(); //Comparator comp = getAlphanumericComparator( true ); // look for a delimiter (non alpha/numeric) Set delimiters = new HashSet(); char current_delim = '1'; char bad_delim = '1'; for (int i=0;i " + isBadVersion( test_current[i], test_bad[i] )); System.out.println( test_bad[i] + " / " + test_current[i] + " -> " + isBadVersion( test_bad[i], test_current[i] )); } } */ } azureus-4.3.0.6/com/aelitis/net/upnp/impl/UPnPImpl.java0000644000175000017500000006407111265533066022105 0ustar adrianadrian/* * Created on 14-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp.impl; /** * @author parg * */ import java.util.*; import java.net.*; import java.io.*; import com.aelitis.azureus.core.util.Java15Utils; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.core3.util.ThreadPool; import org.gudy.azureus2.core3.util.TorrentUtils; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderAdapter; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentException; import com.aelitis.azureus.core.util.HTTPUtils; import com.aelitis.net.upnp.*; import com.aelitis.net.upnp.impl.device.*; public class UPnPImpl extends ResourceDownloaderAdapter implements UPnP, SSDPIGDListener { public static final String NL = "\r\n"; private static UPnPImpl singleton; private static AEMonitor class_mon = new AEMonitor( "UPnP:class" ); public static UPnP getSingleton( UPnPAdapter adapter, String[] selected_interfaces ) throws UPnPException { try{ class_mon.enter(); if ( singleton == null ){ singleton = new UPnPImpl( adapter, selected_interfaces ); } return( singleton ); }finally{ class_mon.exit(); } } private UPnPAdapter adapter; private SSDPIGD ssdp; private Map root_locations = new HashMap(); private List log_listeners = new ArrayList(); private List log_history = new ArrayList(); private List log_alert_history = new ArrayList(); private List rd_listeners = new ArrayList(); private AEMonitor rd_listeners_mon = new AEMonitor( "UPnP:L" ); private int http_calls_ok = 0; private int direct_calls_ok = 0; private int trace_index = 0; private ThreadPool device_dispatcher = new ThreadPool("UPnPDispatcher", 1, true ); private Set device_dispatcher_pending = new HashSet(); private Map failed_urls = new HashMap(); protected AEMonitor this_mon = new AEMonitor( "UPnP" ); protected UPnPImpl( UPnPAdapter _adapter, String[] _selected_interfaces ) throws UPnPException { adapter = _adapter; ssdp = SSDPIGDFactory.create( this, _selected_interfaces ); ssdp.addListener(this); ssdp.start(); } public void injectDiscoveryCache( Map cache ) { try{ String ni_s = new String((byte[])cache.get( "ni" ), "UTF-8" ); String la_s = new String((byte[])cache.get( "la" ), "UTF-8" ); String usn = new String((byte[])cache.get( "usn" ), "UTF-8" ); String loc_s = new String((byte[])cache.get( "loc" ), "UTF-8" ); NetworkInterface network_interface = NetworkInterface.getByName( ni_s ); if ( network_interface == null ){ return; } InetAddress local_address = InetAddress.getByName( la_s ); URL location = new URL( loc_s ); rootDiscovered( network_interface, local_address, usn, location ); }catch( Throwable e ){ Debug.out( e ); } } public void rootDiscovered( final NetworkInterface network_interface, final InetAddress local_address, final String usn, final URL location ) { // we need to take this operation off the main thread as it can take some time. This is a single // concurrency queued thread pool so things get done serially in the right order try{ rd_listeners_mon.enter(); if ( device_dispatcher_pending.contains( usn )){ // System.out.println( "UPnP: skipping discovery of " + usn + " as already pending (queue=" + device_dispatcher_pending.size() + ")" ); return; } if ( device_dispatcher_pending.size() > 512 ){ Debug.out( "Device dispatcher queue is full - dropping discovery of " + usn + "/" + location ); } device_dispatcher_pending.add( usn ); }finally{ rd_listeners_mon.exit(); } device_dispatcher.run( new AERunnable() { public void runSupport() { final UPnPRootDeviceImpl old_root_device; try{ rd_listeners_mon.enter(); old_root_device = (UPnPRootDeviceImpl)root_locations.get( usn ); device_dispatcher_pending.remove( usn ); }finally{ rd_listeners_mon.exit(); } if ( old_root_device != null ){ // we remember one route to the device - if the network interfaces change // we do a full reset so we don't need to deal with that here if ( !old_root_device.getNetworkInterface().getName().equals( network_interface.getName())){ return; } // check that the device's location is the same if ( old_root_device.getLocation().equals( location )){ return; } } if ( old_root_device != null ){ // something changed, resetablish everything try{ // not the best "atomic" code here but it'll do as the code that adds roots (this) // is single threaded via the dispatcher rd_listeners_mon.enter(); root_locations.remove( usn ); }finally{ rd_listeners_mon.exit(); } old_root_device.destroy( true ); } List listeners; try{ rd_listeners_mon.enter(); listeners = new ArrayList( rd_listeners ); }finally{ rd_listeners_mon.exit(); } for (int i=0;i= max_period ){ period = max_period; break; } } if ( SystemTime.getMonotonousTime() - last_fail < period ){ record_failure = false; throw( new UPnPException( "Download failed too recently, ignoring" )); } retries = 1; } } ResourceDownloader rd = rdf.getRetryDownloader( rdf.create( url, true ), retries ); rd.addListener( this ); InputStream data = rd.download(); try{ SimpleXMLParserDocument res = parseXML( data ); synchronized( failed_urls ){ failed_urls.remove( url_str ); } return( res ); }finally{ data.close(); } }catch( Throwable e ){ if ( record_failure ){ synchronized( failed_urls ){ if ( failed_urls.size() >= 64 ){ failed_urls.clear(); } long[] fails = failed_urls.get( url_str ); if ( fails == null ){ fails = new long[2]; failed_urls.put( url_str, fails ); } fails[0]++; fails[1] = SystemTime.getMonotonousTime(); } adapter.log( Debug.getNestedExceptionMessageAndStack(e)); } if (e instanceof UPnPException ){ throw((UPnPException)e); } throw( new UPnPException( "Root device location '" + url + "' - data read failed", e )); }finally{ TorrentUtils.setTLSDescription( null ); } } protected boolean forceDirect() { String http_proxy = System.getProperty( "http.proxyHost" ); String socks_proxy = System.getProperty( "socksProxyHost" ); // extremely unlikely we want to proxy upnp requests boolean force_direct = ( http_proxy != null && http_proxy.trim().length() > 0 ) || ( socks_proxy != null && socks_proxy.trim().length() > 0 ); return( force_direct ); } public SimpleXMLParserDocument performSOAPRequest( UPnPService service, String soap_action, String request ) throws SimpleXMLParserDocumentException, UPnPException, IOException { SimpleXMLParserDocument res; if ( service.getDirectInvocations() || forceDirect()){ res = performSOAPRequest( service, soap_action, request, false ); }else{ try{ res = performSOAPRequest( service, soap_action, request, true ); http_calls_ok++; }catch( IOException e ){ res = performSOAPRequest( service, soap_action, request, false ); direct_calls_ok++; if ( direct_calls_ok == 1 ){ log( "Invocation via http connection failed (" + e.getMessage() + ") but socket connection succeeded" ); } } } return( res ); } /** * The use_http_connection flag is set to false sometimes to avoid using * the URLConnection library for some dopey UPnP routers. */ public SimpleXMLParserDocument performSOAPRequest( UPnPService service, String soap_action, String request, boolean use_http_connection) throws SimpleXMLParserDocumentException, UPnPException, IOException { //long start = SystemTime.getMonotonousTime(); URL control = service.getControlURL(); try{ adapter.trace( "UPnP:Request: -> " + control + "," + request ); if ( use_http_connection ){ try{ TorrentUtils.setTLSDescription( "UPnP Device: " + service.getDevice().getFriendlyName()); HttpURLConnection con1 = (HttpURLConnection)Java15Utils.openConnectionForceNoProxy(control); con1.setRequestProperty( "SOAPAction", "\""+ soap_action + "\""); con1.setRequestProperty( "Content-Type", "text/xml; charset=\"utf-8\"" ); con1.setRequestProperty( "User-Agent", "Azureus (UPnP/1.0)" ); con1.setRequestMethod( "POST" ); con1.setDoInput( true ); con1.setDoOutput( true ); OutputStream os = con1.getOutputStream(); PrintWriter pw = new PrintWriter( new OutputStreamWriter(os, "UTF-8" )); pw.println( request ); pw.flush(); con1.connect(); if ( con1.getResponseCode() == 405 || con1.getResponseCode() == 500 ){ // gotta retry with M-POST method try{ HttpURLConnection con2 = (HttpURLConnection)control.openConnection(); con2.setRequestProperty( "Content-Type", "text/xml; charset=\"utf-8\"" ); con2.setRequestMethod( "M-POST" ); con2.setRequestProperty( "MAN", "\"http://schemas.xmlsoap.org/soap/envelope/\"; ns=01" ); con2.setRequestProperty( "01-SOAPACTION", "\""+ soap_action + "\""); con2.setDoInput( true ); con2.setDoOutput( true ); os = con2.getOutputStream(); pw = new PrintWriter( new OutputStreamWriter(os, "UTF-8" )); pw.println( request ); pw.flush(); con2.connect(); return( parseXML(con2.getInputStream())); }catch( Throwable e ){ } InputStream es = con1.getErrorStream(); String info = null; try{ info = FileUtil.readInputStreamAsString( es, 512 ); }catch( Throwable e ){ } String error = "SOAP RPC failed: " + con1.getResponseCode() + " " + con1.getResponseMessage(); if ( info != null ){ error += " - " + info; } throw( new IOException ( error )); }else{ return( parseXML(con1.getInputStream())); } }finally{ TorrentUtils.setTLSDescription( null ); } }else{ final int CONNECT_TIMEOUT = 15*1000; final int READ_TIMEOUT = 30*1000; Socket socket = new Socket( Proxy.NO_PROXY ); socket.connect( new InetSocketAddress( control.getHost(), control.getPort()), CONNECT_TIMEOUT ); socket.setSoTimeout( READ_TIMEOUT ); try{ PrintWriter pw = new PrintWriter(new OutputStreamWriter( socket.getOutputStream(), "UTF8" )); String url_target = control.toString(); int p1 = url_target.indexOf( "://" ) + 3; p1 = url_target.indexOf( "/", p1 ); url_target = url_target.substring( p1 ); pw.print( "POST " + url_target + " HTTP/1.1" + NL ); pw.print( "Content-Type: text/xml; charset=\"utf-8\"" + NL ); pw.print( "SOAPAction: \"" + soap_action + "\"" + NL ); pw.print( "User-Agent: Azureus (UPnP/1.0)" + NL ); pw.print( "Host: " + control.getHost() + NL ); pw.print( "Content-Length: " + request.getBytes( "UTF8" ).length + NL ); pw.print( "Connection: Keep-Alive" + NL ); pw.print( "Pragma: no-cache" + NL + NL ); pw.print( request ); pw.flush(); InputStream is = HTTPUtils.decodeChunkedEncoding( socket ); return( parseXML( is )); }finally{ try{ socket.close(); }catch( Throwable e ){ Debug.printStackTrace(e); } } } }finally{ //System.out.println( "UPnP: invocation of " + control + "/" + soap_action + " took " + ( SystemTime.getMonotonousTime() - start )); } } protected File getTraceFile() { try{ this_mon.enter(); trace_index++; if ( trace_index == 6 ){ trace_index = 1; } return( new File( adapter.getTraceDir(), "upnp_trace" + trace_index + ".log" )); }finally{ this_mon.exit(); } } public UPnPAdapter getAdapter() { return( adapter ); } public void reportActivity( ResourceDownloader downloader, String activity ) { log( activity ); } public void failed( ResourceDownloader downloader, ResourceDownloaderException e ) { log( e ); } public void log( Throwable e ) { log( e.toString()); } public void log( String str ) { List old_listeners; try{ this_mon.enter(); old_listeners = new ArrayList(log_listeners); log_history.add( str ); if ( log_history.size() > 32 ){ log_history.remove(0); } }finally{ this_mon.exit(); } for (int i=0;i 32 ){ log_alert_history.remove(0); } }finally{ this_mon.exit(); } for (int i=0;i ignore_mx = new HashSet(); private SSDPCore( UPnPSSDPAdapter _adapter, String _group_address, int _group_port, int _control_port, String[] _selected_interfaces ) throws UPnPException { adapter = _adapter; group_address_str = _group_address; group_port = _group_port; try{ mc_group = MCGroupFactory.getSingleton( this, _group_address, group_port, _control_port, _selected_interfaces ); }catch( Throwable e ){ throw( new UPnPException( "Failed to initialise SSDP", e )); } } public int getControlPort() { return( mc_group.getControlPort()); } public void trace( String str ) { adapter.log( str ); } public void log( Throwable e ) { adapter.log( e ); } public void notify( String NT, String NTS, String UUID, String url ) { /* NOTIFY * HTTP/1.1 HOST: 239.255.255.250:1900 CACHE-CONTROL: max-age=3600 LOCATION: http://192.168.0.1:49152/gateway.xml NT: urn:schemas-upnp-org:service:WANIPConnection:1 NTS: ssdp:byebye SERVER: Linux/2.4.17_mvl21-malta-mips_fp_le, UPnP/1.0, Intel SDK for UPnP devices /1.2 USN: uuid:ab5d9077-0710-4373-a4ea-5192c8781666::urn:schemas-upnp-org:service:WANIPConnection:1 */ if ( url.startsWith("/")){ url = url.substring(1); } String str = "NOTIFY * HTTP/" + HTTP_VERSION + NL + "HOST: " + group_address_str + ":" + group_port + NL + "CACHE-CONTROL: max-age=3600" + NL + "LOCATION: http://%AZINTERFACE%:" + mc_group.getControlPort() + "/" + url + NL + "NT: " + NT + NL + "NTS: " + NTS + NL + "SERVER: " + getServerName() + NL + "USN: " + (UUID==null?"":(UUID + "::")) + NT + NL + NL; try{ mc_group.sendToGroup( str ); }catch( Throwable e ){ } } protected String getServerName() { return( System.getProperty( "os.name" ) + "/" + System.getProperty("os.version") + " UPnP/1.0 " + Constants.AZUREUS_NAME + "/" + Constants.AZUREUS_VERSION ); } public void search( String[] STs ) { for ( String ST: STs ){ String str = "M-SEARCH * HTTP/" + HTTP_VERSION + NL + "ST: " + ST + NL + "MX: 3" + NL + "MAN: \"ssdp:discover\"" + NL + "HOST: " + group_address_str + ":" + group_port + NL + NL; sendMC( str ); } } protected void sendMC( String str ) { byte[] data = str.getBytes(); try{ mc_group.sendToGroup( data ); }catch( Throwable e ){ } } public void interfaceChanged( NetworkInterface network_interface ) { for (int i=0;i lines = new ArrayList(); int pos = 0; while(true){ int p1 = str.indexOf( NL, pos ); String line; if ( p1 == -1 ){ line = str.substring(pos); }else{ line = str.substring(pos,p1); pos = p1+1; } lines.add( line.trim()); if ( p1 == -1 ){ break; } } if ( lines.size() == 0 ){ adapter.trace( "SSDP::receive packet - 0 line reply" ); return; } String header = (String)lines.get(0); // Gudy's Root: http://192.168.0.1:5678/igd.xml, uuid:upnp-InternetGatewayDevice-1_0-12345678900001::upnp:rootdevice, upnp:rootdevice // Parg's Root: http://192.168.0.1:49152/gateway.xml, uuid:824ff22b-8c7d-41c5-a131-44f534e12555::upnp:rootdevice, upnp:rootdevice URL location = null; String usn = null; String nt = null; String nts = null; String st = null; String al = null; String mx = null; String server = null; for (int i=1;i 0 ){ t = (Runnable)timer_queue.remove(0); }else{ time_event_next = 0; return; } } try{ t.run(); }catch( Throwable e ){ Debug.printStackTrace(e); } } } }); } } } }else{ adapter.trace( "SSDP::receive M-SEARCH - bad header:" + header ); } }else if ( header.startsWith( "NOTIFY" )){ // location is null for byebye if ( nt != null && nts != null ){ informNotify( network_interface, local_address, originator.getAddress(), usn, location, nt, nts ); }else{ adapter.trace( "SSDP::receive NOTIFY - bad header:" + header ); } }else if ( header.startsWith( "HTTP") && header.indexOf( "200") != -1 ){ if ( location != null && st != null ){ informResult( network_interface, local_address, originator.getAddress(), usn, location, st, al ); }else{ adapter.trace( "SSDP::receive HTTP - bad header:" + header ); } }else{ adapter.trace( "SSDP::receive packet - bad header:" + header ); } } protected void informResult( NetworkInterface network_interface, InetAddress local_address, InetAddress originator, String usn, URL location, String st, String al ) { for (int i=0;i best_prefix ){ best_prefix = i; best_ni = this_ni; best_addr = this_address; } } } } } if ( best_ni != null ){ if ( first_result ){ upnp.log( location + " -> " + best_ni.getDisplayName() + "/" + best_addr + " (prefix=" + (best_prefix + 1 ) + ")"); } gotRoot( best_ni, best_addr, usn, location ); }else{ gotAlive( usn, location ); } }catch( Throwable e ){ gotAlive( usn, location ); } }else if ( nts.indexOf( "byebye") != -1 ){ lostRoot( local_address, usn ); } } }finally{ first_result = false; this_mon.exit(); } } public String[] receivedSearch( NetworkInterface network_interface, InetAddress local_address, InetAddress originator, String ST ) { // not interested, loopback or other search return( null ); } protected boolean[] bytesToBits( byte[] bytes ) { boolean[] res = new boolean[bytes.length*8]; for (int i=0;i UDP int port, String description ) throws UPnPException; public UPnPWANConnectionPortMapping[] getPortMappings() throws UPnPException; public void deletePortMapping( boolean tcp, int port ) throws UPnPException; public String[] getStatusInfo() throws UPnPException; public void periodicallyRecheckMappings( boolean on ); public int getCapabilities(); public String getExternalIPAddress() throws UPnPException; public void addListener( UPnPWANConnectionListener listener ); public void removeListener( UPnPWANConnectionListener listener ); } azureus-4.3.0.6/com/aelitis/net/upnp/services/UPnPWANCommonInterfaceConfig.java0000644000175000017500000000232010373051032026603 0ustar adrianadrian/* * Created on 16-Sep-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp.services; import com.aelitis.net.upnp.UPnPException; public interface UPnPWANCommonInterfaceConfig extends UPnPSpecificService { // returns link down/up speed in bits/sec public long[] getCommonLinkProperties() throws UPnPException; } azureus-4.3.0.6/com/aelitis/net/upnp/services/UPnPWANConnectionPortMapping.java0000644000175000017500000000227510373051032026675 0ustar adrianadrian/* * Created on 15-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp.services; /** * @author parg * */ public interface UPnPWANConnectionPortMapping { public boolean isTCP(); public int getExternalPort(); public String getInternalHost(); public String getDescription(); } azureus-4.3.0.6/com/aelitis/net/upnp/services/UPnPOfflineDownloader.java0000644000175000017500000000346211245670722025463 0ustar adrianadrian/* * Created on 15-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp.services; import com.aelitis.net.upnp.UPnPException; /** * @author parg * */ public interface UPnPOfflineDownloader extends UPnPSpecificService { public long getFreeSpace( String client_id ) throws UPnPException; public void activate( String client_id ) throws UPnPException; public String addDownload( String client_id, String hash_list, String torrent ) throws UPnPException; public String[] updateDownload( String client_id, String hash_list, String required_map ) throws UPnPException; public String[] setDownloads( String client_id, String hash_list ) throws UPnPException; public String removeDownload( String client_id, String hash ) throws UPnPException; public String[] startDownload( String client_id, String hash ) throws UPnPException; } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPSSDP.java0000644000175000017500000000260711245660472021011 0ustar adrianadrian/* * Created on 20-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; public interface UPnPSSDP { public static final String SSDP_GROUP_ADDRESS = "239.255.255.250"; public static final int SSDP_GROUP_PORT = 1900; public int getControlPort(); public void search( String[] STs ); public void notify( String NT, String NTS, String UUID, String url ); public void addListener( UPnPSSDPListener l ); public void removeListener( UPnPSSDPListener l ); } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPSSDPAdapter.java0000644000175000017500000000256510373051020022275 0ustar adrianadrian/* * Created on 20-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; import org.gudy.azureus2.plugins.utils.UTTimer; public interface UPnPSSDPAdapter { public UTTimer createTimer( String name ); public void createThread( String name, Runnable runnable ); public void trace( String str ); /** * Logs are generally more informative for the user than trace * @param str */ public void log( String str ); public void log( Throwable e ); } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPListener.java0000644000175000017500000000227010431212040021775 0ustar adrianadrian/* * Created on 15-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; import java.net.URL; /** * @author parg * */ public interface UPnPListener { public boolean deviceDiscovered( String USN, URL location ); public void rootDeviceFound( UPnPRootDevice device ); } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPStateVariable.java0000644000175000017500000000223310373051020022741 0ustar adrianadrian/* * Created on 15-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; /** * @author parg * */ public interface UPnPStateVariable { public String getName(); public UPnPService getService(); public String getValue() throws UPnPException; } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPRootDevice.java0000644000175000017500000000307311246134570022275 0ustar adrianadrian/* * Created on 15-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; import java.net.NetworkInterface; import java.net.URL; import java.net.InetAddress; import java.util.Map; /** * @author parg * */ public interface UPnPRootDevice { public UPnP getUPnP(); public String getUSN(); public URL getLocation(); public InetAddress getLocalAddress(); public NetworkInterface getNetworkInterface(); public String getInfo(); public UPnPDevice getDevice(); public boolean isDestroyed(); public Map getDiscoveryCache(); public void addListener( UPnPRootDeviceListener l ); public void removeListener( UPnPRootDeviceListener l ); } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPSSDPListener.java0000644000175000017500000000330510416072300022475 0ustar adrianadrian/* * Created on 20-Dec-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.URL; public interface UPnPSSDPListener { public void receivedResult( NetworkInterface network_interface, InetAddress local_address, InetAddress originator, String USN, URL location, String ST, String AL ); public void receivedNotify( NetworkInterface network_interface, InetAddress local_address, InetAddress originator, String USN, URL location, String NT, String NTS ); public String[] receivedSearch( NetworkInterface network_interface, InetAddress local_address, InetAddress originator, String ST ); public void interfaceChanged( NetworkInterface network_interface ); } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPDevice.java0000644000175000017500000000274111140756664021441 0ustar adrianadrian/* * Created on 15-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; /** * @author parg * */ public interface UPnPDevice { public String getDeviceType(); public String getFriendlyName(); public String getManufacturer(); public String getManufacturerURL(); public String getModelDescription(); public String getModelName(); public String getModelNumber(); public String getModelURL(); public String getPresentation(); public UPnPDevice[] getSubDevices(); public UPnPService[] getServices(); public UPnPRootDevice getRootDevice(); } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPService.java0000644000175000017500000000336510417310750021631 0ustar adrianadrian/* * Created on 15-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; /** * @author parg * */ import java.net.URL; import com.aelitis.net.upnp.services.*; public interface UPnPService { public UPnPDevice getDevice(); public String getServiceType(); public URL getControlURL() throws UPnPException; public UPnPAction[] getActions() throws UPnPException; public UPnPAction getAction( String name ) throws UPnPException; public UPnPStateVariable[] getStateVariables() throws UPnPException; public UPnPStateVariable getStateVariable( String name ) throws UPnPException; /** * gets a specific service if such is supported * @return */ public UPnPSpecificService getSpecificService(); public boolean getDirectInvocations(); public void setDirectInvocations( boolean force ); } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPFactory.java0000644000175000017500000000314410373051020021624 0ustar adrianadrian/* * Created on 14-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; /** * @author parg * */ import com.aelitis.net.upnp.impl.*; import com.aelitis.net.upnp.impl.ssdp.SSDPCore; public class UPnPFactory { public static UPnP getSingleton( UPnPAdapter adapter, String[] selected_interfaces ) throws UPnPException { return( UPnPImpl.getSingleton( adapter, selected_interfaces )); } public static UPnPSSDP getSSDP( UPnPSSDPAdapter adapter, String group_address, int group_port, int control_port, String[] selected_interfaces ) throws UPnPException { return( SSDPCore.getSingleton( adapter, group_address, group_port, control_port, selected_interfaces )); } } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPAdapter.java0000644000175000017500000000306410373051020021576 0ustar adrianadrian/* * Created on 28-Nov-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 40,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; import java.util.Comparator; import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument; import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentException; public interface UPnPAdapter extends UPnPSSDPAdapter { public SimpleXMLParserDocument parseXML( String data ) throws SimpleXMLParserDocumentException; public ResourceDownloaderFactory getResourceDownloaderFactory(); public Comparator getAlphanumericComparator(); public String getTraceDir(); } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPLogListener.java0000644000175000017500000000244710373051020022451 0ustar adrianadrian/* * Created on 14-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; /** * @author parg * */ public interface UPnPLogListener { public static final int TYPE_ALWAYS = 1; public static final int TYPE_ONCE_PER_SESSION = 2; public static final int TYPE_ONCE_EVER = 3; public void log( String str ); public void logAlert( String str, boolean error, int type ); } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPRootDeviceListener.java0000644000175000017500000000215410373051020023766 0ustar adrianadrian/* * Created on 16-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; /** * @author parg * */ public interface UPnPRootDeviceListener { public void lost( UPnPRootDevice root, boolean replaced ); } azureus-4.3.0.6/com/aelitis/net/upnp/UPnPAction.java0000644000175000017500000000221610373051020021431 0ustar adrianadrian/* * Created on 15-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.upnp; /** * @author parg * */ public interface UPnPAction { public String getName(); public UPnPService getService(); public UPnPActionInvocation getInvocation(); } azureus-4.3.0.6/com/aelitis/net/udp/0000755000175000017500000000000011310377330016422 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/udp/mc/0000755000175000017500000000000011310377632017026 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/udp/mc/MCGroupException.java0000644000175000017500000000232311012742130023050 0ustar adrianadrian/* * Created on 14-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.udp.mc; /** * @author parg * */ public class MCGroupException extends Exception { public MCGroupException( String str ) { super( str ); } public MCGroupException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/com/aelitis/net/udp/mc/MCGroupFactory.java0000644000175000017500000000254510365202720022535 0ustar adrianadrian/* * Created on 05-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.udp.mc; import com.aelitis.net.udp.mc.impl.MCGroupImpl; public class MCGroupFactory { public static MCGroup getSingleton( MCGroupAdapter adapter, String group_address, int group_port, int control_port, String[] selected_interfaces ) throws MCGroupException { return( MCGroupImpl.getSingleton( adapter, group_address, group_port, control_port, selected_interfaces )); } } azureus-4.3.0.6/com/aelitis/net/udp/mc/impl/0000755000175000017500000000000011310377632017767 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/udp/mc/impl/MCGroupImpl.java0000644000175000017500000004113211210203004022745 0ustar adrianadrian/* * Created on 14-Jun-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.udp.mc.impl; import java.net.*; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.AEThread; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import com.aelitis.net.udp.mc.MCGroup; import com.aelitis.net.udp.mc.MCGroupAdapter; import com.aelitis.net.udp.mc.MCGroupException; /** * @author parg * */ public class MCGroupImpl implements MCGroup { private final static int TTL = 4; private final static int PACKET_SIZE = 8192; private static Map singletons = new HashMap(); private static AEMonitor class_mon = new AEMonitor( "MCGroup:class" ); public static MCGroupImpl getSingleton( MCGroupAdapter adapter, String group_address, int group_port, int control_port, String[] interfaces ) throws MCGroupException { try{ class_mon.enter(); String key = group_address + ":" + group_port + ":" + control_port; MCGroupImpl singleton = (MCGroupImpl)singletons.get( key ); if ( singleton == null ){ if ( control_port == 0 ){ int last_allocated = COConfigurationManager.getIntParameter( "mcgroup.ports." + key, 0 ); if ( last_allocated != 0 ){ try{ DatagramSocket test_socket = new DatagramSocket( null ); test_socket.setReuseAddress( false ); test_socket.bind( new InetSocketAddress( last_allocated )); test_socket.close(); control_port = last_allocated; }catch( Throwable e ){ e.printStackTrace(); } } } singleton = new MCGroupImpl( adapter, group_address, group_port, control_port, interfaces ); if ( control_port == 0 ){ control_port = singleton.getControlPort(); COConfigurationManager.setParameter( "mcgroup.ports." + key, control_port ); } singletons.put( key, singleton ); } return( singleton ); }finally{ class_mon.exit(); } } private MCGroupAdapter adapter; private String group_address_str; private int group_port; private int control_port; protected InetSocketAddress group_address; private String[] selected_interfaces; private boolean ttl_problem_reported = true; // remove these diagnostic reports on win98 private boolean sso_problem_reported = true; // remove these diagnostic reports on win98 protected AEMonitor this_mon = new AEMonitor( "MCGroup" ); private Map current_registrations = new HashMap(); public MCGroupImpl( MCGroupAdapter _adapter, String _group_address, int _group_port, int _control_port, String[] _interfaces ) throws MCGroupException { adapter = _adapter; group_address_str = _group_address; group_port = _group_port; control_port = _control_port; selected_interfaces = _interfaces; try{ group_address = new InetSocketAddress(InetAddress.getByName(group_address_str), 0 ); processNetworkInterfaces( true ); SimpleTimer.addPeriodicEvent( "MCGroup:refresher", 60*1000, new TimerEventPerformer() { public void perform( TimerEvent event ) { try{ processNetworkInterfaces( false ); }catch( Throwable e ){ adapter.log(e); } } }); }catch( Throwable e ){ throw( new MCGroupException( "Failed to initialise MCGroup", e )); } } protected void processNetworkInterfaces( boolean start_of_day ) throws SocketException { Map new_registrations = new HashMap(); List changed_interfaces = new ArrayList(); try{ this_mon.enter(); Enumeration network_interfaces = NetworkInterface.getNetworkInterfaces(); while (network_interfaces.hasMoreElements()){ final NetworkInterface network_interface = (NetworkInterface)network_interfaces.nextElement(); if ( !interfaceSelected( network_interface )){ if ( start_of_day ){ adapter.trace( "ignoring interface " + network_interface.getName() + ":" + network_interface.getDisplayName() + ", not selected" ); } continue; } Set old_address_set = (Set)current_registrations.get( network_interface ); if ( old_address_set == null ){ old_address_set = new HashSet(); } Set new_address_set = new HashSet(); new_registrations.put( network_interface, new_address_set ); Enumeration ni_addresses = network_interface.getInetAddresses(); while (ni_addresses.hasMoreElements()){ final InetAddress ni_address = (InetAddress)ni_addresses.nextElement(); new_address_set.add( ni_address ); if ( old_address_set.contains( ni_address )){ // already established continue; } // turn on loopback to see if it helps for local host UPnP devices // nah, turn it off again, it didn;t if ( ni_address.isLoopbackAddress()){ if ( start_of_day ){ adapter.trace( "ignoring loopback address " + ni_address + ", interface " + network_interface.getName()); } continue; } if ( ni_address instanceof Inet6Address ){ if ( start_of_day ){ adapter.trace( "ignoring IPv6 address " + ni_address + ", interface " + network_interface.getName()); } continue; } if ( !start_of_day ){ if ( !changed_interfaces.contains( network_interface )){ changed_interfaces.add( network_interface ); } } try{ // set up group final MulticastSocket mc_sock = new MulticastSocket( group_port ); mc_sock.setReuseAddress(true); // windows 98 doesn't support setTimeToLive try{ mc_sock.setTimeToLive(TTL); }catch( Throwable e ){ if ( !ttl_problem_reported ){ ttl_problem_reported = true; adapter.log( e ); } } String addresses_string = ""; Enumeration it = network_interface.getInetAddresses(); while (it.hasMoreElements()){ InetAddress addr = (InetAddress)it.nextElement(); addresses_string += (addresses_string.length()==0?"":",") + addr; } adapter.trace( "group = " + group_address +"/" + network_interface.getName()+":"+ network_interface.getDisplayName() + "-" + addresses_string +": started" ); mc_sock.joinGroup( group_address, network_interface ); mc_sock.setNetworkInterface( network_interface ); // note that false ENABLES loopback mode which is what we want mc_sock.setLoopbackMode(false); Runtime.getRuntime().addShutdownHook( new AEThread("MCGroup:VMShutdown") { public void runSupport() { try{ mc_sock.leaveGroup( group_address, network_interface ); }catch( Throwable e ){ adapter.log( e ); } } }); new AEThread2("MCGroup:MCListener", true ) { public void run() { handleSocket( network_interface, ni_address, mc_sock, true ); } }.start(); }catch( Throwable e ){ adapter.log( e ); } // now do the incoming control listener try{ final DatagramSocket control_socket = new DatagramSocket( null ); control_socket.setReuseAddress( true ); control_socket.bind( new InetSocketAddress(ni_address, control_port )); if ( control_port == 0 ){ control_port = control_socket.getLocalPort(); // System.out.println( "local port = " + control_port ); } new AEThread2( "MCGroup:CtrlListener", true ) { public void run() { handleSocket( network_interface, ni_address, control_socket, false ); } }.start(); }catch( Throwable e ){ adapter.log( e ); } } } }finally{ current_registrations = new_registrations; this_mon.exit(); } for (int i=0;i 0 ){ boolean ok = false; for (int i=0;i 100 && successful_accepts == 0 ) || failed_accepts > 1000 ){ adapter.trace( " too many failures, abandoning" ); break; } } } } protected void receivePacket( NetworkInterface network_interface, InetAddress local_address, DatagramPacket packet ) { byte[] data = packet.getData(); int len = packet.getLength(); // System.out.println( "receive: add = " + local_address + ", data = " + new String( data, 0, len )); adapter.received( network_interface, local_address, (InetSocketAddress)packet.getSocketAddress(), data, len ); } public void sendToMember( InetSocketAddress address, byte[] data ) throws MCGroupException { DatagramSocket reply_socket = null; // System.out.println( "sendToMember: add = " + address + ", data = " +new String( data )); try{ reply_socket = new DatagramSocket( null ); reply_socket.setReuseAddress(true); reply_socket.bind( new InetSocketAddress( group_port )); DatagramPacket reply_packet = new DatagramPacket(data,data.length,address); reply_socket.send( reply_packet ); }catch( Throwable e ){ throw( new MCGroupException( "sendToMember failed", e )); }finally{ if ( reply_socket != null ){ try{ reply_socket.close(); }catch( Throwable e ){ } } } } } azureus-4.3.0.6/com/aelitis/net/udp/mc/MCGroupAdapter.java0000644000175000017500000000263110411101676022502 0ustar adrianadrian/* * Created on 05-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.udp.mc; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.NetworkInterface; public interface MCGroupAdapter { public void received( NetworkInterface network_interface, InetAddress local_address, InetSocketAddress originator, byte[] data, int length ); public void interfaceChanged( NetworkInterface network_interface ); public void trace( String str ); public void log( Throwable e ); } azureus-4.3.0.6/com/aelitis/net/udp/mc/MCGroup.java0000644000175000017500000000300610416072300021172 0ustar adrianadrian/* * Created on 05-Jan-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.udp.mc; import java.net.InetSocketAddress; public interface MCGroup { public int getControlPort(); public void sendToGroup( byte[] data ) throws MCGroupException; /** * Sends to the group but will replace any occurrence of %AZINTERFACE% in the string with the * interface being used for the send * @param param_data * @throws MCGroupException */ public void sendToGroup( String param_data ) throws MCGroupException; public void sendToMember( InetSocketAddress address, byte[] data ) throws MCGroupException; } azureus-4.3.0.6/com/aelitis/net/udp/uc/0000755000175000017500000000000011310377632017036 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/udp/uc/PRUDPPacketReceiver.java0000644000175000017500000000250310373051006023400 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.udp.uc; import java.net.InetSocketAddress; /** * @author parg * */ public interface PRUDPPacketReceiver { public void packetReceived( PRUDPPacketHandlerRequest request, PRUDPPacket packet, InetSocketAddress from_address ); /** * receive failed - timeout * @param e */ public void error( PRUDPPacketHandlerException e ); } azureus-4.3.0.6/com/aelitis/net/udp/uc/PRUDPPacketReply.java0000644000175000017500000000535711033103414022734 0ustar adrianadrian/* * File : PRUDPPacketReply.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.net.udp.uc; /** * @author parg * */ import java.io.*; import java.net.InetSocketAddress; import java.util.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; public abstract class PRUDPPacketReply extends PRUDPPacket { public static final int PR_HEADER_SIZE = 8; private static AEMonitor class_mon = new AEMonitor( "PRUDPPacketReply:class" ); private static Map packet_decoders = new HashMap(); public static void registerDecoders( Map _decoders ) { try{ class_mon.enter(); Map new_decoders = new HashMap( packet_decoders ); Iterator it = _decoders.keySet().iterator(); while( it.hasNext()){ Integer action = (Integer)it.next(); if ( packet_decoders.containsKey( action )){ Debug.out( "Duplicate codec! " + action ); } } new_decoders.putAll( _decoders ); packet_decoders = new_decoders; }finally{ class_mon.exit(); } } public PRUDPPacketReply( int _action, int _tran_id ) { super( _action, _tran_id ); } public void serialise( DataOutputStream os ) throws IOException { // add to this and you need to adjust HEADER_SIZE above os.writeInt( getAction()); os.writeInt( getTransactionId() ); } public static PRUDPPacketReply deserialiseReply( PRUDPPacketHandler handler, InetSocketAddress originator, DataInputStream is ) throws IOException { int action = is.readInt(); PRUDPPacketReplyDecoder decoder = (PRUDPPacketReplyDecoder)packet_decoders.get( new Integer( action )); if ( decoder == null ){ throw( new IOException( "No decoder registered for action '" + action + "'" )); } int transaction_id = is.readInt(); return( decoder.decode( handler, originator, is, action, transaction_id )); } public String getString() { return( super.getString() + ":reply[trans=" + getTransactionId() + "]" ); } }azureus-4.3.0.6/com/aelitis/net/udp/uc/PRUDPPacketRequestDecoder.java0000644000175000017500000000244110373051006024553 0ustar adrianadrian/* * Created on 21-Jan-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.udp.uc; import java.io.DataInputStream; import java.io.IOException; /** * @author parg * */ public interface PRUDPPacketRequestDecoder { public PRUDPPacketRequest decode( PRUDPPacketHandler handler, DataInputStream is, long connection_id, int action, int transaction_id ) throws IOException; } azureus-4.3.0.6/com/aelitis/net/udp/uc/PRUDPPacketHandler.java0000644000175000017500000000616510750744024023231 0ustar adrianadrian/* * File : PRUDPPacketReceiver.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.net.udp.uc; /** * @author parg * */ import java.net.*; public interface PRUDPPacketHandler { public static final int PRIORITY_LOW = 2; public static final int PRIORITY_MEDIUM = 1; public static final int PRIORITY_HIGH = 0; public static final int PRIORITY_IMMEDIATE = 99; /** * Asynchronous send and receive * @param request_packet * @param destination_address * @param receiver * @throws PRUDPPacketHandlerException */ public void sendAndReceive( PRUDPPacket request_packet, InetSocketAddress destination_address, PRUDPPacketReceiver receiver, long timeout, int priority ) throws PRUDPPacketHandlerException; /** * Synchronous send and receive * @param auth * @param request_packet * @param destination_address * @return * @throws PRUDPPacketHandlerException */ public PRUDPPacket sendAndReceive( PasswordAuthentication auth, PRUDPPacket request_packet, InetSocketAddress destination_address ) throws PRUDPPacketHandlerException; public PRUDPPacket sendAndReceive( PasswordAuthentication auth, PRUDPPacket request_packet, InetSocketAddress destination_address, long timeout_millis ) throws PRUDPPacketHandlerException; public PRUDPPacket sendAndReceive( PasswordAuthentication auth, PRUDPPacket request_packet, InetSocketAddress destination_address, long timeout_millis, int priority ) throws PRUDPPacketHandlerException; /** * Send only * @param request_packet * @param destination_address * @throws PRUDPPacketHandlerException */ public void send( PRUDPPacket request_packet, InetSocketAddress destination_address ) throws PRUDPPacketHandlerException; public PRUDPRequestHandler getRequestHandler(); public void setRequestHandler( PRUDPRequestHandler request_handler ); public void primordialSend( byte[] data, InetSocketAddress target ) throws PRUDPPacketHandlerException; public void setPrimordialHandler( PRUDPPrimordialHandler handler ); public int getPort(); public void setDelays( int send_delay, int receive_delay, int queued_request_timeout ); public void setExplicitBindAddress( InetAddress address ); public PRUDPPacketHandlerStats getStats(); } azureus-4.3.0.6/com/aelitis/net/udp/uc/PRUDPPacketHandlerRequest.java0000644000175000017500000000205410373051006024563 0ustar adrianadrian/* * Created on 22-Jun-2005 * Created by Paul Gardner * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.udp.uc; public interface PRUDPPacketHandlerRequest { public long getElapsedTime(); } azureus-4.3.0.6/com/aelitis/net/udp/uc/impl/0000755000175000017500000000000011310377632017777 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerRequestImpl.java0000644000175000017500000000676510406421772026373 0ustar adrianadrian/* * File : PRUDPPacketHandlerRequest.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.net.udp.uc.impl; /** * @author parg * */ import java.net.InetSocketAddress; import org.gudy.azureus2.core3.util.*; import com.aelitis.net.udp.uc.PRUDPPacket; import com.aelitis.net.udp.uc.PRUDPPacketHandlerException; import com.aelitis.net.udp.uc.PRUDPPacketHandlerRequest; import com.aelitis.net.udp.uc.PRUDPPacketReceiver; public class PRUDPPacketHandlerRequestImpl implements PRUDPPacketHandlerRequest { private AESemaphore sem = new AESemaphore("PRUDPPacketHandlerRequest"); private long timeout; private PRUDPPacketReceiver receiver; private PRUDPPacketHandlerException exception; private PRUDPPacket reply; private long send_time; private long reply_time; protected PRUDPPacketHandlerRequestImpl( PRUDPPacketReceiver _receiver, long _timeout ) { receiver = _receiver; timeout = _timeout; } protected void sent() { send_time = SystemTime.getCurrentTime(); } protected long getSendTime() { return( send_time ); } protected long getTimeout() { return( timeout ); } public long getElapsedTime() { if ( send_time == 0 || reply_time == 0 ){ return( -1 ); } long res = reply_time - send_time; if ( res < 0 ){ res = 0; } // do something sensible with 0 time! if ( res == 0 ){ res = SystemTime.TIME_GRANULARITY_MILLIS / 2; } return( res ); } protected void setReply( PRUDPPacket packet, InetSocketAddress originator, long receive_time ) { if ( reply == null ){ reply_time = receive_time; reply = packet; }else{ packet.setPreviousPacket( reply ); reply = packet; } if( !packet.hasContinuation()){ sem.release(); } if ( receiver != null ){ receiver.packetReceived( this, packet, originator ); } } protected void setException( PRUDPPacketHandlerException e ) { // don't override existing reply for synchronous callers as they can // do what they want with it if ( reply == null ){ reply_time = SystemTime.getCurrentTime(); exception = e; } sem.release(); // still report errors to asyn clients (even when a reply has been received) // as they need something to indicate that a continuation packet wasn't received // and that the request has timed-out. ie. a multi-packet reply must terminate // either with the reception of a non-continuation (i.e. last) packet *or* a // timeout/error if ( receiver != null ){ receiver.error( e ); } } protected PRUDPPacket getReply() throws PRUDPPacketHandlerException { sem.reserve(); if ( exception != null ){ throw( exception ); } return( reply ); } } azureus-4.3.0.6/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerFactoryImpl.java0000644000175000017500000001077210533245410026335 0ustar adrianadrian/* * File : PRUDPPacketReceiverFactoryImpl.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.net.udp.uc.impl; /** * @author parg * */ import java.net.InetAddress; import java.util.*; import org.gudy.azureus2.core3.util.AEMonitor; import org.gudy.azureus2.core3.util.Debug; import com.aelitis.net.udp.uc.PRUDPPacketHandler; import com.aelitis.net.udp.uc.PRUDPReleasablePacketHandler; import com.aelitis.net.udp.uc.PRUDPRequestHandler; public class PRUDPPacketHandlerFactoryImpl { private static Map receiver_map = new HashMap(); private static AEMonitor class_mon = new AEMonitor( "PRUDPPHF" ); private static Map releasable_map = new HashMap(); private static Set non_releasable_set = new HashSet(); public static PRUDPPacketHandler getHandler( int port, InetAddress bind_ip, PRUDPRequestHandler request_handler) { final Integer f_port = new Integer( port ); try{ class_mon.enter(); non_releasable_set.add( f_port ); PRUDPPacketHandlerImpl receiver = (PRUDPPacketHandlerImpl)receiver_map.get( f_port ); if ( receiver == null ){ receiver = new PRUDPPacketHandlerImpl( port, bind_ip ); receiver_map.put( f_port, receiver ); } // only set the incoming request handler if one has been specified. This is important when // the port is shared (e.g. default udp tracker and dht) and only one usage has need to handle // unsolicited inbound requests as we don't want the tracker null handler to erase the dht's // one if ( request_handler != null ){ receiver.setRequestHandler( request_handler ); } return( receiver ); }finally{ class_mon.exit(); } } public static PRUDPReleasablePacketHandler getReleasableHandler( int port, PRUDPRequestHandler request_handler) { final Integer f_port = new Integer( port ); try{ class_mon.enter(); PRUDPPacketHandlerImpl receiver = (PRUDPPacketHandlerImpl)receiver_map.get( f_port ); if ( receiver == null ){ receiver = new PRUDPPacketHandlerImpl( port, null ); receiver_map.put( f_port, receiver ); } // only set the incoming request handler if one has been specified. This is important when // the port is shared (e.g. default udp tracker and dht) and only one usage has need to handle // unsolicited inbound requests as we don't want the tracker null handler to erase the dht's // one if ( request_handler != null ){ receiver.setRequestHandler( request_handler ); } final PRUDPPacketHandlerImpl f_receiver = receiver; final PRUDPReleasablePacketHandler rel = new PRUDPReleasablePacketHandler() { public PRUDPPacketHandler getHandler() { return( f_receiver ); } public void release() { try{ class_mon.enter(); List l = (List)releasable_map.get( f_port ); if ( l == null ){ Debug.out( "hmm" ); }else{ if ( !l.remove( this )){ Debug.out( "hmm" ); }else{ if ( l.size() == 0 ){ if ( !non_releasable_set.contains( f_port )){ f_receiver.destroy(); receiver_map.remove( f_port ); } releasable_map.remove( f_port ); } } } }finally{ class_mon.exit(); } } }; List l = (List)releasable_map.get( f_port ); if ( l == null ){ l = new ArrayList(); releasable_map.put( f_port, l ); } l.add( rel ); if ( l.size() > 1024 ){ Debug.out( "things going wrong here" ); } return( rel ); }finally{ class_mon.exit(); } } } azureus-4.3.0.6/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerImpl.java0000644000175000017500000011014111225222414024772 0ustar adrianadrian/* * File : PRUDPPacketReceiverImpl.java * Created : 20-Jan-2004 * By : parg * * Azureus - a Java Bittorrent client * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details ( see the LICENSE file ). * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.net.udp.uc.impl; /** * @author parg * */ import java.io.*; import java.net.*; import java.nio.channels.UnsupportedAddressTypeException; import java.util.*; import org.bouncycastle.util.encoders.Base64; import org.gudy.azureus2.core3.logging.LogAlert; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminPropertyChangeListener; import com.aelitis.net.udp.uc.*; public class PRUDPPacketHandlerImpl implements PRUDPPacketHandler { private static final LogIDs LOGID = LogIDs.NET; private boolean TRACE_REQUESTS = false; private static final long MAX_SEND_QUEUE_DATA_SIZE = 2*1024*1024; private static final long MAX_RECV_QUEUE_DATA_SIZE = 1*1024*1024; private int port; private DatagramSocket socket; private PRUDPPrimordialHandler primordial_handler; private PRUDPRequestHandler request_handler; private PRUDPPacketHandlerStatsImpl stats = new PRUDPPacketHandlerStatsImpl( this ); private Map requests = new LightHashMap(); private AEMonitor2 requests_mon = new AEMonitor2( "PRUDPPH:req" ); private AEMonitor2 send_queue_mon = new AEMonitor2( "PRUDPPH:sd" ); private long send_queue_data_size; private List[] send_queues = new List[]{ new LinkedList(),new LinkedList(),new LinkedList()}; private AESemaphore send_queue_sem = new AESemaphore( "PRUDPPH:sq" ); private AEThread send_thread; private AEMonitor recv_queue_mon = new AEMonitor( "PRUDPPH:rq" ); private long recv_queue_data_size; private List recv_queue = new ArrayList(); private AESemaphore recv_queue_sem = new AESemaphore( "PRUDPPH:rq" ); private AEThread recv_thread; private int send_delay = 0; private int receive_delay = 0; private int queued_request_timeout = 0; private long total_requests_received; private long total_requests_processed; private long total_replies; private long last_error_report; private AEMonitor bind_address_mon = new AEMonitor( "PRUDPPH:bind" ); private InetAddress default_bind_ip; private InetAddress explicit_bind_ip; private volatile InetAddress current_bind_ip; private volatile InetAddress target_bind_ip; private volatile boolean failed; private volatile boolean destroyed; private AESemaphore destroy_sem = new AESemaphore("PRUDPPacketHandler:destroy"); private Throwable init_error; private PRUDPPacketHandlerImpl altProtocolDelegate; protected PRUDPPacketHandlerImpl( int _port, InetAddress _bind_ip ) { port = _port; explicit_bind_ip = _bind_ip; default_bind_ip = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress(); calcBind(); final AESemaphore init_sem = new AESemaphore("PRUDPPacketHandler:init"); new AEThread2( "PRUDPPacketReciever:" + port, true ) { public void run() { receiveLoop(init_sem); } }.start(); final TimerEventPeriodic[] f_ev = {null}; TimerEventPeriodic ev = SimpleTimer.addPeriodicEvent( "PRUDP:timeouts", 5000, new TimerEventPerformer() { public void perform( TimerEvent event ) { if ( destroyed && f_ev[0] != null ){ f_ev[0].cancel(); } checkTimeouts(); } }); f_ev[0] = ev; init_sem.reserve(); } public void setPrimordialHandler( PRUDPPrimordialHandler handler ) { if ( primordial_handler != null && handler != null ){ Debug.out( "Primordial handler replaced!" ); } primordial_handler = handler; PRUDPPacketHandlerImpl delegate = altProtocolDelegate; if(delegate != null) delegate.setPrimordialHandler(handler); } public void setRequestHandler( PRUDPRequestHandler _request_handler ) { if ( request_handler != null ){ if ( _request_handler != null ){ // if we need to support this then the handler will have to be associated // with a message type map, or we chain together and give each handler // a bite at processing the message throw( new RuntimeException( "Multiple handlers per endpoint not supported" )); } } request_handler = _request_handler; PRUDPPacketHandlerImpl delegate = altProtocolDelegate; if(delegate != null) delegate.setRequestHandler(_request_handler); } public PRUDPRequestHandler getRequestHandler() { return( request_handler ); } public int getPort() { return( port ); } protected void setDefaultBindAddress( InetAddress address ) { try{ bind_address_mon.enter(); default_bind_ip = address; calcBind(); }finally{ bind_address_mon.exit(); } } public void setExplicitBindAddress( InetAddress address ) { try{ bind_address_mon.enter(); explicit_bind_ip = address; calcBind(); }finally{ bind_address_mon.exit(); } int loops = 0; while( current_bind_ip != target_bind_ip && !(failed || destroyed)){ if ( loops >= 100 ){ Debug.out( "Giving up on wait for bind ip change to take effect" ); break; } try{ Thread.sleep(50); loops++; }catch( Throwable e ){ break; } } } protected void calcBind() { if ( explicit_bind_ip != null ){ if(altProtocolDelegate != null) { altProtocolDelegate.destroy(); altProtocolDelegate = null; } target_bind_ip = explicit_bind_ip; }else{ InetAddress altAddress = null; NetworkAdmin adm = NetworkAdmin.getSingleton(); try { if (default_bind_ip instanceof Inet6Address && !default_bind_ip.isAnyLocalAddress() && adm.hasIPV4Potential()) altAddress = adm.getSingleHomedServiceBindAddress(NetworkAdmin.IP_PROTOCOL_VERSION_REQUIRE_V4); else if (default_bind_ip instanceof Inet4Address && adm.hasIPV6Potential()) altAddress = adm.getSingleHomedServiceBindAddress(NetworkAdmin.IP_PROTOCOL_VERSION_REQUIRE_V6); } catch (UnsupportedAddressTypeException e) { } if(altProtocolDelegate != null && !altProtocolDelegate.explicit_bind_ip.equals(altAddress)) { altProtocolDelegate.destroy(); altProtocolDelegate = null; } if(altAddress != null && altProtocolDelegate == null) { altProtocolDelegate = new PRUDPPacketHandlerImpl(port,altAddress); altProtocolDelegate.stats = stats; altProtocolDelegate.primordial_handler = primordial_handler; altProtocolDelegate.request_handler = request_handler; } target_bind_ip = default_bind_ip; } } protected void receiveLoop( AESemaphore init_sem ) { long last_socket_close_time = 0; NetworkAdminPropertyChangeListener prop_listener = new NetworkAdminPropertyChangeListener() { public void propertyChanged( String property ) { if ( property == NetworkAdmin.PR_DEFAULT_BIND_ADDRESS ){ setDefaultBindAddress( NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress()); } } }; NetworkAdmin.getSingleton().addPropertyChangeListener( prop_listener ); try{ // outter loop picks up bind-ip changes while( !( failed || destroyed )){ if ( socket != null ){ try{ socket.close(); }catch( Throwable e ){ Debug.printStackTrace(e); } } InetSocketAddress address; DatagramSocket new_socket; try{ if ( target_bind_ip == null ){ address = new InetSocketAddress("127.0.0.1",port); new_socket = new DatagramSocket( port ); }else{ address = new InetSocketAddress( target_bind_ip, port ); new_socket = new DatagramSocket( address ); } }catch( BindException e ){ // one off attempt to recover by selecting an explicit one. // on Vista (at least) we sometimes fail with wildcard but succeeed // with explicit (see http://forum.vuze.com/thread.jspa?threadID=77574&tstart=0) if ( target_bind_ip.isAnyLocalAddress()){ InetAddress guess = NetworkAdmin.getSingleton().guessRoutableBindAddress(); if ( guess != null ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID,"PRUDPPacketReceiver: retrying with bind IP guess of " + guess )); try{ InetSocketAddress guess_address = new InetSocketAddress( guess, port ); new_socket = new DatagramSocket( guess_address ); target_bind_ip = guess; address = guess_address; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID,"PRUDPPacketReceiver: Switched to explicit bind ip " + target_bind_ip + " after initial bind failure with wildcard (" + e.getMessage() + ")" )); }catch( Throwable f ){ throw( e ); } }else{ throw( e ); } }else{ throw( e ); } } new_socket.setReuseAddress(true); // short timeout on receive so that we can interrupt a receive fairly quickly new_socket.setSoTimeout( 1000 ); // only make the socket public once fully configured socket = new_socket; current_bind_ip = target_bind_ip; init_sem.release(); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "PRUDPPacketReceiver: receiver established on port " + port + (current_bind_ip==null?"":(", bound to " + current_bind_ip )))); byte[] buffer = null; long successful_accepts = 0; long failed_accepts = 0; while( !( failed || destroyed )){ if ( current_bind_ip != target_bind_ip ){ break; } try{ if ( buffer == null ){ buffer = new byte[PRUDPPacket.MAX_PACKET_SIZE]; } DatagramPacket packet = new DatagramPacket( buffer, buffer.length, address ); socket.receive( packet ); long receive_time = SystemTime.getCurrentTime(); successful_accepts++; failed_accepts = 0; PRUDPPrimordialHandler prim_hand = primordial_handler; if ( prim_hand != null ){ if ( prim_hand.packetReceived( packet )){ // primordial handlers get their own buffer as we can't guarantee // that they don't need to hang onto the data buffer = null; stats.primordialPacketReceived( packet.getLength()); } } if ( buffer != null ){ process( packet, receive_time ); } }catch( SocketTimeoutException e ){ }catch( Throwable e ){ // on vista we get periodic socket closures String message = e.getMessage(); if ( socket.isClosed() || ( message != null && message.toLowerCase().indexOf( "socket closed" ) != -1 )){ long now = SystemTime.getCurrentTime(); // can't guarantee there aren't situations where we get into a screaming // closed loop so guard against this somewhat if ( now - last_socket_close_time < 500 ){ Thread.sleep( 250 ); } last_socket_close_time = now; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "PRUDPPacketReceiver: recycled UDP port " + port + " after close: ok=" + successful_accepts )); break; } failed_accepts++; if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "PRUDPPacketReceiver: receive failed on port " + port + ": ok=" + successful_accepts + ", fails=" + failed_accepts, e)); if (( failed_accepts > 100 && successful_accepts == 0 ) || failed_accepts > 1000 ){ Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Network.alert.acceptfail"), new String[] { "" + port, "UDP" }); // break, sometimes get a screaming loop. e.g. /* [2:01:55] DEBUG::Tue Dec 07 02:01:55 EST 2004 [2:01:55] java.net.SocketException: Socket operation on nonsocket: timeout in datagram socket peek [2:01:55] at java.net.PlainDatagramSocketImpl.peekData(Native Method) [2:01:55] at java.net.DatagramSocket.receive(Unknown Source) [2:01:55] at org.gudy.azureus2.core3.tracker.server.impl.udp.TRTrackerServerUDP.recvLoop(TRTrackerServerUDP.java:118) [2:01:55] at org.gudy.azureus2.core3.tracker.server.impl.udp.TRTrackerServerUDP$1.runSupport(TRTrackerServerUDP.java:90) [2:01:55] at org.gudy.azureus2.core3.util.AEThread.run(AEThread.java:45) */ init_error = e; failed = true; } } } } }catch( Throwable e ){ init_error = e; if (!( e instanceof BindException && Constants.isWindowsVistaOrHigher )){ Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, "Tracker.alert.listenfail"), new String[] { "UDP:" + port }); } Logger.log(new LogEvent(LOGID, "PRUDPPacketReceiver: " + "DatagramSocket bind failed on port " + port, e)); }finally{ init_sem.release(); destroy_sem.releaseForever(); if ( socket != null ){ try{ socket.close(); }catch( Throwable e ){ Debug.printStackTrace(e); } } // make sure we destroy the delegate too if something happend PRUDPPacketHandlerImpl delegate = altProtocolDelegate; if(delegate != null) delegate.destroy(); NetworkAdmin.getSingleton().removePropertyChangeListener( prop_listener ); } } protected void checkTimeouts() { long now = SystemTime.getCurrentTime(); List timed_out = new ArrayList(); try{ requests_mon.enter(); Iterator it = requests.values().iterator(); while( it.hasNext()){ PRUDPPacketHandlerRequestImpl request = (PRUDPPacketHandlerRequestImpl)it.next(); long sent_time = request.getSendTime(); if ( sent_time != 0 && now - sent_time >= request.getTimeout()){ it.remove(); stats.requestTimedOut(); timed_out.add( request ); } } }finally{ requests_mon.exit(); } for (int i=0;i 0 ){ // we take the processing offline so that these incoming requests don't // interfere with replies to outgoing requests try{ recv_queue_mon.enter(); if ( recv_queue_data_size > MAX_RECV_QUEUE_DATA_SIZE ){ long now = SystemTime.getCurrentTime(); if ( now - last_error_report > 30000 ){ last_error_report = now; Debug.out( "Receive queue size limit exceeded (" + MAX_RECV_QUEUE_DATA_SIZE + "), dropping request packet [" + total_requests_received + "/" + total_requests_processed + ":" + total_replies + "]"); } }else if ( receive_delay * recv_queue.size() > queued_request_timeout ){ // by the time this request gets processed it'll have timed out // in the caller anyway, so discard it long now = SystemTime.getCurrentTime(); if ( now - last_error_report > 30000 ){ last_error_report = now; Debug.out( "Receive queue entry limit exceeded (" + recv_queue.size() + "), dropping request packet ]" + total_requests_received + "/" + total_requests_processed + ":" + total_replies + "]"); } }else{ recv_queue.add( new Object[]{ packet, new Integer( dg_packet.getLength()) }); recv_queue_data_size += dg_packet.getLength(); recv_queue_sem.release(); if ( recv_thread == null ){ recv_thread = new AEThread( "PRUDPPacketHandler:receiver" ) { public void runSupport() { while( true ){ try{ recv_queue_sem.reserve(); Object[] data; try{ recv_queue_mon.enter(); data = (Object[])recv_queue.remove(0); total_requests_processed++; }finally{ recv_queue_mon.exit(); } PRUDPPacketRequest p = (PRUDPPacketRequest)data[0]; recv_queue_data_size -= ((Integer)data[1]).intValue(); PRUDPRequestHandler handler = request_handler; if ( handler != null ){ handler.process( p ); Thread.sleep( receive_delay ); } }catch( Throwable e ){ Debug.printStackTrace(e); } } } }; recv_thread.setDaemon( true ); recv_thread.start(); } } }finally{ recv_queue_mon.exit(); } }else{ PRUDPRequestHandler handler = request_handler; if ( handler != null ){ handler.process( (PRUDPPacketRequest)packet ); } } }else{ total_replies++; if ( TRACE_REQUESTS ){ Logger.log(new LogEvent(LOGID, "PRUDPPacketHandler: reply packet received: " + packet.getString())); } PRUDPPacketHandlerRequestImpl request; try{ requests_mon.enter(); if ( packet.hasContinuation()){ // don't remove the request if there are more replies to come request = (PRUDPPacketHandlerRequestImpl)requests.get(new Integer(packet.getTransactionId())); }else{ request = (PRUDPPacketHandlerRequestImpl)requests.remove(new Integer(packet.getTransactionId())); } }finally{ requests_mon.exit(); } if ( request == null ){ if ( TRACE_REQUESTS ){ Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "PRUDPPacketReceiver: unmatched reply received, discarding:" + packet.getString())); } }else{ request.setReply( packet, (InetSocketAddress)dg_packet.getSocketAddress(), receive_time ); } } }catch( Throwable e ){ // if someone's sending us junk we just log and continue if ( e instanceof IOException ){ // generally uninteresting }else{ Logger.log(new LogEvent(LOGID, "", e)); } } } public PRUDPPacket sendAndReceive( PRUDPPacket request_packet, InetSocketAddress destination_address ) throws PRUDPPacketHandlerException { return( sendAndReceive( null,request_packet, destination_address )); } public PRUDPPacket sendAndReceive( PasswordAuthentication auth, PRUDPPacket request_packet, InetSocketAddress destination_address ) throws PRUDPPacketHandlerException { return( sendAndReceive( auth, request_packet, destination_address, PRUDPPacket.DEFAULT_UDP_TIMEOUT )); } public PRUDPPacket sendAndReceive( PasswordAuthentication auth, PRUDPPacket request_packet, InetSocketAddress destination_address, long timeout ) throws PRUDPPacketHandlerException { PRUDPPacketHandlerRequestImpl request = sendAndReceive( auth, request_packet, destination_address, null, timeout, PRUDPPacketHandler.PRIORITY_MEDIUM ); return( request.getReply()); } public PRUDPPacket sendAndReceive( PasswordAuthentication auth, PRUDPPacket request_packet, InetSocketAddress destination_address, long timeout, int priority ) throws PRUDPPacketHandlerException { PRUDPPacketHandlerRequestImpl request = sendAndReceive( auth, request_packet, destination_address, null, timeout, priority ); return( request.getReply()); } public void sendAndReceive( PRUDPPacket request_packet, InetSocketAddress destination_address, PRUDPPacketReceiver receiver, long timeout, int priority ) throws PRUDPPacketHandlerException { sendAndReceive( null, request_packet, destination_address, receiver, timeout, priority ); } public PRUDPPacketHandlerRequestImpl sendAndReceive( PasswordAuthentication auth, PRUDPPacket request_packet, InetSocketAddress destination_address, PRUDPPacketReceiver receiver, long timeout, int priority ) throws PRUDPPacketHandlerException { if ( socket == null ){ if ( init_error != null ){ throw( new PRUDPPacketHandlerException( "Transport unavailable", init_error )); } throw( new PRUDPPacketHandlerException( "Transport unavailable" )); } PRUDPPacketHandlerImpl delegate = altProtocolDelegate; if(delegate != null && destination_address.getAddress().getClass().isInstance(delegate.explicit_bind_ip)) return delegate.sendAndReceive(auth, request_packet, destination_address, receiver, timeout, priority); try{ checkTargetAddress( destination_address ); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream os = new DataOutputStream( baos ); request_packet.serialise(os); byte[] buffer = baos.toByteArray(); request_packet.setSerialisedSize( buffer.length ); if ( auth != null ){ // so = + + // where = first 8 bytes of sha1( + + sha1(pass)) // Yes SHA1Hasher hasher = new SHA1Hasher(); String user_name = auth.getUserName(); String password = new String(auth.getPassword()); byte[] sha1_password; if ( user_name.equals( "")){ sha1_password = Base64.decode(password); }else{ sha1_password = hasher.calculateHash(password.getBytes()); } byte[] user_bytes = new byte[8]; Arrays.fill( user_bytes, (byte)0); for (int i=0;i 0 && priority != PRUDPPacketHandler.PRIORITY_IMMEDIATE ){ try{ send_queue_mon.enter(); if ( send_queue_data_size > MAX_SEND_QUEUE_DATA_SIZE ){ request.sent(); // synchronous write holding lock to block senders socket.send( dg_packet ); stats.packetSent( buffer.length ); if ( TRACE_REQUESTS ){ Logger.log(new LogEvent(LOGID, "PRUDPPacketHandler: request packet sent to " + destination_address + ": " + request_packet.getString())); } Thread.sleep( send_delay ); }else{ send_queue_data_size += dg_packet.getLength(); send_queues[priority].add( new Object[]{ dg_packet, request }); if ( TRACE_REQUESTS ){ String str = ""; for (int i=0;i 0 ){ selected_priority = i; if ( consecutive_sends[i] >= 4 || ( i < send_queues.length - 1 && send_queues[i+1].size() - queue_size > 500 )){ // too many consecutive or too imbalanced, see if there are // lower priority queues with entries consecutive_sends[i] = 0; }else{ consecutive_sends[i]++; break; } }else{ consecutive_sends[i] = 0; } } data = (Object[])send_queues[selected_priority].remove(0); }finally{ send_queue_mon.exit(); } DatagramPacket p = (DatagramPacket)data[0]; PRUDPPacketHandlerRequestImpl r = (PRUDPPacketHandlerRequestImpl)data[1]; // mark as sent before sending in case send fails // and we then rely on timeout to pick this up send_queue_data_size -= p.getLength(); r.sent(); socket.send( p ); stats.packetSent( p.getLength() ); if ( TRACE_REQUESTS ){ Logger.log(new LogEvent(LOGID, "PRUDPPacketHandler: request packet sent to " + p.getAddress())); } long delay = send_delay; if ( selected_priority == PRIORITY_HIGH ){ delay = delay/2; } Thread.sleep( delay ); }catch( Throwable e ){ // get occasional send fails, not very interesting Logger.log( new LogEvent( LOGID, LogEvent.LT_WARNING, "PRUDPPacketHandler: send failed: " + Debug.getNestedExceptionMessage(e))); } } } }; send_thread.setDaemon( true ); send_thread.start(); } } }finally{ send_queue_mon.exit(); } }else{ request.sent(); if (dg_packet == null) {throw new NullPointerException("dg_packet is null");} socket.send( dg_packet ); // System.out.println( "sent:" + buffer.length ); stats.packetSent( buffer.length ); if ( TRACE_REQUESTS ){ Logger.log(new LogEvent(LOGID, "PRUDPPacketHandler: " + "request packet sent to " + destination_address + ": " + request_packet.getString())); } } // if the send is ok then the request will be removed from the queue // either when a reply comes back or when it gets timed-out return( request ); }catch( Throwable e ){ // never got sent, remove it immediately try{ requests_mon.enter(); requests.remove( new Integer( request_packet.getTransactionId())); }finally{ requests_mon.exit(); } throw( e ); } }catch( PRUDPPacketHandlerException e ){ throw( e ); }catch( Throwable e ){ // AMC: I've seen this in debug logs - just wonder where it's // coming from. if (e instanceof NullPointerException) { Debug.out(e); } String msg = Debug.getNestedExceptionMessage(e); Logger.log(new LogEvent(LOGID,LogEvent.LT_ERROR, "PRUDPPacketHandler: sendAndReceive to " + destination_address + " failed: " + msg )); if ( msg.indexOf( "Invalid data length" ) != -1 ){ Debug.out( "packet=" + request_packet.getString() + ",auth=" + auth ); Debug.out( e ); } throw( new PRUDPPacketHandlerException( "PRUDPPacketHandler:sendAndReceive failed", e )); } } public void send( PRUDPPacket request_packet, InetSocketAddress destination_address ) throws PRUDPPacketHandlerException { if ( socket == null || socket.isClosed()){ if ( init_error != null ){ throw( new PRUDPPacketHandlerException( "Transport unavailable", init_error )); } throw( new PRUDPPacketHandlerException( "Transport unavailable" )); } PRUDPPacketHandlerImpl delegate = altProtocolDelegate; if(delegate != null && destination_address.getAddress().getClass().isInstance(delegate.explicit_bind_ip)) { delegate.send(request_packet, destination_address); return; } try{ checkTargetAddress( destination_address ); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream os = new DataOutputStream( baos ); request_packet.serialise(os); byte[] buffer = baos.toByteArray(); request_packet.setSerialisedSize( buffer.length ); DatagramPacket dg_packet = new DatagramPacket(buffer, buffer.length, destination_address ); // System.out.println( "Outgoing to " + dg_packet.getAddress()); if ( TRACE_REQUESTS ){ Logger.log(new LogEvent(LOGID, "PRUDPPacketHandler: reply packet sent: " + request_packet.getString())); } socket.send( dg_packet ); stats.packetSent( buffer.length ); // this is a reply to a request, no time delays considered here }catch( PRUDPPacketHandlerException e ){ throw( e ); }catch( Throwable e ){ e.printStackTrace(); Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "PRUDPPacketHandler: send to " + destination_address + " failed: " + Debug.getNestedExceptionMessage(e))); throw( new PRUDPPacketHandlerException( "PRUDPPacketHandler:send failed", e )); } } protected void checkTargetAddress( InetSocketAddress address ) throws PRUDPPacketHandlerException { if ( address.getPort() == 0 ){ throw( new PRUDPPacketHandlerException( "Invalid port - 0" )); } if ( address.getAddress() == null ){ throw( new PRUDPPacketHandlerException( "Unresolved host '" + address.getHostName() + "'" )); } } public void setDelays( int _send_delay, int _receive_delay, int _queued_request_timeout ) { send_delay = _send_delay; receive_delay = _receive_delay; // trim a bit off this limit to include processing time queued_request_timeout = _queued_request_timeout-5000; if ( queued_request_timeout < 5000 ){ queued_request_timeout = 5000; } PRUDPPacketHandlerImpl delegate = altProtocolDelegate; if(delegate != null) delegate.setDelays(_send_delay, _receive_delay, _queued_request_timeout); } public long getSendQueueLength() { int res = 0; for (int i=0;i * Tested with * * This code is ugly, but it works. * * Some assumptions: * - The NAT device will be at xxx.xxx.xxx.1 * * This needs to be threaded. * - It could take upto 2 minutes to timeout during any request * - We need to listen for address changes (using link-local multicast?)! * - We need to request the mapping again before it expires * * Some hints and to dos: * - The draft spec says that the device could set max lease life time * to be less than requested. this should be checked. * - Need to make something to renew port mappings - recommend that * the client SHOULD begin trying to renew the mapping halfway to * * expiry time, like DHCP * - Need to listen for public address changes * * Version 0.1b */ package com.aelitis.net.natpmp.impl; import java.net.*; import com.aelitis.azureus.core.util.NetUtils; import com.aelitis.net.natpmp.NATPMPDeviceAdapter; import com.aelitis.net.natpmp.NatPMPDevice; /** * * Main class * * */ public class NatPMPDeviceImpl implements NatPMPDevice { static final int NATMAP_VER = 0; static final int NATMAP_PORT = 5351; static final int NATMAP_RESPONSE_MASK = 128; static final int NATMAP_INIT_RETRY = 250; // ms static final int NATMAP_MAX_RETRY = 2250; // gives us three tries // lease life in seconds // 24 hours static final int NATMAP_DEFAULT_LEASE = 60*60*24; // link-local multicast address - for address changes // not implemented static final String NATMAP_LLM = "224.0.0.1"; // Opcodes used for .. static final byte NATOp_AddrRequest = 0; // Ask for a NAT-PMP device static final byte NATOp_MapUDP = 1; // Map a UDP Port static final byte NATOp_MapTCP = 2; // Map a TCP Port /* Length of Requests in bytes */ static final int NATAddrRequest = 2; static final int NATPortMapRequestLen = 4 * 3; // 4 bytes by 3 /* Length of Replies in Bytes */ static final int NATAddrReplyLen = 4 * 3; static final int NATPortMapReplyLen = 4 * 4; /* Current Result Codes */ static final int NATResultSuccess = 0; static final int NATResultUnsupportedVer = 1; /** * Not Authorized/Refused * (e.g. box supports mapping, but user has turned feature off) **/ static final int NATResultNotAuth = 2; /** * Network Failure * (e.g. NAT box itself has not obtained a DHCP lease) **/ static final int NATResultNetFailure = 3; static final int NATResultNoResc = 4; // Out of resources static final int NATResultUnsupportedOp = 5; // Unsupported opcode /* Instance specific globals */ String current_router_address = "?"; InetAddress hostInet; // Our address InetAddress natPriInet; // NAT's private (interal) address InetAddress natPubInet; // NAT's public address NetworkInterface networkInterface; // natPriInet network interface InetAddress llmInet; boolean nat_pmp_found = false; int nat_epoch = 0; // This gets updated each request private NATPMPDeviceAdapter adapter; /** * Singleton creation **/ private static NatPMPDeviceImpl NatPMPDeviceSingletonRef; public static synchronized NatPMPDeviceImpl getSingletonObject(NATPMPDeviceAdapter adapter) throws Exception { if (NatPMPDeviceSingletonRef == null) NatPMPDeviceSingletonRef = new NatPMPDeviceImpl(adapter); return NatPMPDeviceSingletonRef; } private NatPMPDeviceImpl( NATPMPDeviceAdapter _adapter) throws Exception { adapter = _adapter; hostInet = NetUtils.getLocalHost(); checkRouterAddress(); } protected void checkRouterAddress() throws Exception { String natAddr = adapter.getRouterAddress().trim(); if ( natAddr.length() == 0 ){ natAddr = convertHost2RouterAddress(hostInet); } if ( natAddr.equals( current_router_address )){ return; } current_router_address = natAddr; log("Using Router IP: " + natAddr); natPriInet = InetAddress.getByName(natAddr); networkInterface = NetworkInterface.getByInetAddress( natPriInet ); } /** * Send a request and wait for reply * This class should be threaded!!! * * This sends to the default NATPMP_PORT. * * @param dstInet destination address (should be the private NAT address) * @param dstPkt packet to send * @param recBuf byte buffer big enough to hold received **/ public DatagramPacket sendNATMsg(InetAddress dstInet, DatagramPacket dstPkt, byte[] recBuf) throws Exception { int retryInterval = NATMAP_INIT_RETRY; boolean recRep = false; DatagramSocket skt = new DatagramSocket(); skt.connect( dstInet, NATMAP_PORT ); skt.setSoTimeout( NATMAP_INIT_RETRY ); skt.send(dstPkt); // how do we know we hit something? DatagramPacket recPkt = new DatagramPacket(recBuf, recBuf.length); // We have several tries at this (like 3) while ( !recRep && (retryInterval < NATMAP_MAX_RETRY) ) { try { skt.receive(recPkt); recRep = true; } catch (SocketTimeoutException ste) { //log("Timed Out!"); //log( ste.getMessage() ); // sleep before trying again // this.sleep(retryInterval); Thread.sleep(retryInterval); // not sleeping?!? // increase retry interval retryInterval += (retryInterval * 2); } } if ( !recRep ){ throw( new PortUnreachableException()); } // check recRep for true!!! return recPkt; } /** * Try to connect with a NAT-PMP device. * This could take sometime. * * @return true if it found one **/ public boolean connect() throws Exception { checkRouterAddress(); try{ // Send NAT request to find out if it is PMP happy byte reqBuf[] = {NATMAP_VER, NATOp_AddrRequest}; DatagramPacket dstPkt = new DatagramPacket(reqBuf, reqBuf.length); byte recBuf[] = new byte[NATAddrReplyLen]; /* DatagramPacket recPkt = */ sendNATMsg(natPriInet, dstPkt, recBuf); //int recVer = unsigned8ByteArrayToInt( recBuf, 0 ); //int recOp = unsigned8ByteArrayToInt( recBuf, 1 ); int recErr = unsigned16ByteArrayToInt( recBuf, 2 ); int recEpoch = unsigned32ByteArrayToInt( recBuf, 4 ); String recPubAddr = unsigned8ByteArrayToInt( recBuf, 8 ) + "." + unsigned8ByteArrayToInt( recBuf, 9 ) + "." + unsigned8ByteArrayToInt( recBuf, 10 ) + "." + unsigned8ByteArrayToInt( recBuf, 11 ); /* set the global NAT public address */ natPubInet = InetAddress.getByName(recPubAddr); /* set the global NAT Epoch time (in seconds) */ nat_epoch = recEpoch; if (recErr != 0) throw( new Exception("NAT-PMP connection error: " + recErr) ); log("Err: " +recErr); log("Uptime: " + recEpoch); log("Public Address: " + recPubAddr); /** * TO DO: * Set up listner for announcements from the device for * address changes (public address changes) **/ nat_pmp_found = true; return true; }catch( PortUnreachableException e ){ return( false ); } } /** * Asks for a public port to be mapped to a private port from this host. * * NAP-PMP allows the device to assign another public port if the * requested one is taken. So, you should check the returned port. * * @param tcp true TCP, false UDP * @return the returned publicPort. -1 if error occured * @todo either take a class (like UPnPMapping) or return a class **/ public int addPortMapping( boolean tcp, int publicPort, int privatePort ) throws Exception { // check for actual connection! return portMappingProtocol( tcp, publicPort, privatePort, NATMAP_DEFAULT_LEASE ); } /** * Delete a mapped public port * * @param tcp true TCP, false UDP port * @param publicPort the public port to close * @param privatePort the private port that it is mapped to * @warn untested */ public void deletePortMapping( boolean tcp, int publicPort, int privatePort ) throws Exception { /** * if the request was successful, a zero lifetime will * delete the mapping and return a public port of 0 **/ // check for actual connection /*int result = */ portMappingProtocol(tcp, publicPort, privatePort, 0); } /** * General port mapping protocol * * * **/ public int portMappingProtocol( boolean tcp, int publicPort, int privatePort, int lifetime ) throws Exception { byte NATOp = (tcp?NATOp_MapTCP:NATOp_MapUDP); // Should check for errors - only using lower 2 bytes byte pubPort[] = intToByteArray(publicPort); byte priPort[] = intToByteArray(privatePort); byte portLifeTime[] = intToByteArray(lifetime); // Generate Port Map request packet byte dstBuf[] = new byte[NATPortMapRequestLen]; dstBuf[0] = NATMAP_VER; // Ver dstBuf[1] = NATOp; // OP dstBuf[2] = 0; // Reserved - 2 bytes dstBuf[3] = 0; dstBuf[4] = priPort[2]; // Private Port - 2 bytes dstBuf[5] = priPort[3]; dstBuf[6] = pubPort[2]; // Requested Public Port - 2 bytes dstBuf[7] = pubPort[3]; for (int i = 0; i < 4; i++) { dstBuf[8 + i] = portLifeTime[i]; } DatagramPacket dstPkt = new DatagramPacket(dstBuf, dstBuf.length); byte recBuf[] = new byte[NATPortMapReplyLen]; /* DatagramPacket recPkt = */ sendNATMsg(natPriInet, dstPkt, recBuf); // Unpack this and check codes //int recVers = unsigned8ByteArrayToInt( recBuf, 0 ); int recOP = unsigned8ByteArrayToInt( recBuf, 1 ); int recCode = unsigned16ByteArrayToInt( recBuf, 2 ); int recEpoch = unsigned32ByteArrayToInt( recBuf, 4); //int recPriPort = unsigned16ByteArrayToInt( recBuf, 8 ); int recPubPort = unsigned16ByteArrayToInt( recBuf, 10 ); int recLifetime = unsigned32ByteArrayToInt( recBuf, 12); /** * Should save the epoch. This can be used to determine the * time the mapping will be deleted. **/ log("Seconds since Start of Epoch: " + recEpoch); log("Returned Mapped Port Lifetime: " + recLifetime); if ( recCode != 0 ) throw( new Exception( "An error occured while getting a port mapping: " + recCode ) ); if ( recOP != ( NATOp + 128) ) throw( new Exception( "Received the incorrect port type: " + recOP) ); if ( lifetime != recLifetime ) log("Received different port life time!"); return recPubPort; } public InetAddress getLocalAddress() { return( hostInet ); } public NetworkInterface getNetworkInterface() { return( networkInterface ); } public String getExternalIPAddress() { return( natPubInet.getHostAddress()); } public int getEpoch() { return( nat_epoch ); } protected void log( String str ) { adapter.log( str ); } /** * * Bunch of conversion functions * **/ /** * Convert the byte array containing 32-bit to an int starting from * the given offset. * * @param b The byte array * @param offset The array offset * @return The integer */ public static int unsigned32ByteArrayToInt(byte[] b, int offset) { int value = 0; for (int i = 0; i < 4; i++) { int shift = (4 - 1 - i) * 8; value += ( (int) b[i + offset] & 0xFF) << shift; } return value; } /** * Convert the byte array containing 16-bits to an int starting from * the given offset. * * @param b The byte array * @param offset The array offset * @return The integer */ public static int unsigned16ByteArrayToInt(byte[] b, int offset) { int value = 0; for (int i = 0; i < 2; i++) { int shift = (2 - 1 - i) * 8; value += ( (int) b[i + offset] & 0xFF) << shift; } return value; } /** * Convert the byte array containing 8-bits to an int starting from * the given offset. * * @param b The byte array * @param offset The array offset * @return The integer */ public static int unsigned8ByteArrayToInt(byte[] b, int offset) { return (int) b[offset] & 0xFF; } public short unsignedByteArrayToShort(byte[] buf) { if (buf.length == 2) { int i; i = ( ( ( (int) buf[0] & 0xFF) << 8) | ( (int) buf[1] & 0xFF) ); return (short) i; } return -1; } /** * Convert a 16-bit short into a 2 byte array * * @return unsigned byte array **/ public byte[] shortToByteArray(short v) { byte b[] = new byte[2]; b[0] = (byte) ( 0xFF & (v >> 8) ); b[1] = (byte) ( 0xFF & (v >> 0) ); return b; } /** * Convert a 32-bit int into a 4 byte array * * @return unsigned byte array **/ public byte[] intToByteArray(int v) { byte b[] = new byte[4]; int i, shift; for(i = 0, shift = 24; i < 4; i++, shift -= 8) b[i] = (byte)(0xFF & (v >> shift)); return b; } public String intArrayString(int[] buf) { StringBuffer sb = new StringBuffer(); for(int i = 0; i < buf.length; i++) { sb.append(buf[i]).append(" "); } return sb.toString(); } public String byteArrayString(byte[] buf) { StringBuffer sb = new StringBuffer(); for(int i = 0; i < buf.length; i++) { sb.append(buf[i]).append(" "); } return sb.toString(); } /** * * @param init takes the host address * @return String the address as (xxx.xxx.xxx.1) **/ private String convertHost2RouterAddress(InetAddress inet) { byte rawIP[] = inet.getAddress(); // assume router is at xxx.xxx.xxx.1 rawIP[3] = 1; // is there no printf in java? String newIP = (rawIP[0]&0xff) +"."+(rawIP[1]&0xff)+"."+(rawIP[2]&0xff)+"."+(rawIP[3]&0xff); return newIP; } }azureus-4.3.0.6/com/aelitis/net/natpmp/upnp/0000755000175000017500000000000011310377632020120 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/natpmp/upnp/NatPMPUPnPFactory.java0000644000175000017500000000253110551527774024170 0ustar adrianadrian/* * Created on 12 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.natpmp.upnp; import com.aelitis.net.natpmp.NatPMPDevice; import com.aelitis.net.natpmp.upnp.impl.NatPMPUPnPImpl; import com.aelitis.net.upnp.UPnP; import com.aelitis.net.upnp.UPnPException; public class NatPMPUPnPFactory { public static NatPMPUPnP create( UPnP upnp, NatPMPDevice nat_pmp_device ) throws UPnPException { return( new NatPMPUPnPImpl( upnp, nat_pmp_device )); } } azureus-4.3.0.6/com/aelitis/net/natpmp/upnp/impl/0000755000175000017500000000000011310377632021061 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPImpl.java0000644000175000017500000000603510471670406024416 0ustar adrianadrian/* * Created on 12 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.natpmp.upnp.impl; import java.util.*; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import com.aelitis.net.natpmp.NatPMPDevice; import com.aelitis.net.natpmp.upnp.NatPMPUPnP; import com.aelitis.net.upnp.UPnP; import com.aelitis.net.upnp.UPnPListener; public class NatPMPUPnPImpl implements NatPMPUPnP { private UPnP upnp; private NatPMPDevice nat_device; private NatPMPUPnPRootDeviceImpl root_device; private List listeners = new ArrayList(); private boolean enabled = true; private boolean started; public NatPMPUPnPImpl( UPnP _upnp, NatPMPDevice _nat_device ) { upnp = _upnp; nat_device = _nat_device; } protected void start() { SimpleTimer.addPeriodicEvent( "NATPMP:search", 60*1000, new TimerEventPerformer() { public void perform( TimerEvent event ) { search(); } }); search(); } public void setEnabled( boolean _enabled ) { enabled = _enabled; } public boolean isEnabled() { return( enabled ); } protected void search() { if ( !enabled ){ return; } if ( root_device != null ){ return; } try{ boolean found = nat_device.connect(); if ( found ){ root_device = new NatPMPUPnPRootDeviceImpl(upnp, nat_device ); for (int i=0;i UDP int port, String description ) throws UPnPException { try{ /* use public port for internal port */ natDevice.addPortMapping( tcp, port, port ); } catch( Exception e) { throw( new UPnPException( "addPortMapping failed", e )); } synchronized( this ){ /* Find and remove old mapping, if any */ Iterator it = mappings.iterator(); while( it.hasNext() ) { portMapping m = (portMapping)it.next(); if (m.getExternalPort() == port && m.isTCP() == tcp) it.remove() ; } /* add new port to list */ mappings.add( new portMapping( port, tcp, natDevice.getLocalAddress().getHostAddress(), description) ); } } public void deletePortMapping( boolean tcp, int port) throws UPnPException { try { natDevice.deletePortMapping( tcp, port, port ); } catch ( Exception e) { throw( new UPnPException("deletePortMapping failed", e) ); } synchronized( this ){ /* Delete from the mappings */ Iterator it = mappings.iterator(); while( it.hasNext() ) { portMapping m = (portMapping)it.next(); if (m.getExternalPort() == port && m.isTCP() == tcp) it.remove() ; } } } public UPnPWANConnectionPortMapping[] getPortMappings() throws UPnPException { synchronized( this ){ /* Check UPnPSSWANConnectionImpl.java for hints */ UPnPWANConnectionPortMapping[] res2 = new UPnPWANConnectionPortMapping[mappings.size()]; mappings.toArray(res2); return res2; } } public String[] getStatusInfo() throws UPnPException { String connection_status = null; String connection_error = null; String uptime = null; /* can we ping the NAT for this info? */ uptime = "" + natDevice.getEpoch(); return( new String[] { connection_status, connection_error, uptime } ); } public String getExternalIPAddress() { return(natDevice.getExternalIPAddress()); } protected class portMapping implements UPnPWANConnectionPortMapping { protected int external_port; protected boolean tcp; protected String internal_host; protected String description; protected portMapping( int _external_port, boolean _tcp, String _internal_host, String _description ) { external_port = _external_port; tcp = _tcp; internal_host = _internal_host; description = _description; } public boolean isTCP() { return( tcp ); } public int getExternalPort() { return( external_port ); } public String getInternalHost() { return( internal_host ); } public String getDescription() { return( description ); } protected String getString() { return( getDescription() + " [" + getExternalPort() + ":" + (isTCP()?"TCP":"UDP") + "]"); } } /* end protected class portMapping */ } /* end public class NatPMPImpl */azureus-4.3.0.6/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPRootDeviceImpl.java0000644000175000017500000001557611246134570026412 0ustar adrianadrian/* * Created on 12 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.natpmp.upnp.impl; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.URL; import java.util.Map; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.ThreadPool; import com.aelitis.net.natpmp.NatPMPDevice; import com.aelitis.net.upnp.UPnP; import com.aelitis.net.upnp.UPnPAction; import com.aelitis.net.upnp.UPnPDevice; import com.aelitis.net.upnp.UPnPException; import com.aelitis.net.upnp.UPnPRootDevice; import com.aelitis.net.upnp.UPnPRootDeviceListener; import com.aelitis.net.upnp.UPnPService; import com.aelitis.net.upnp.UPnPStateVariable; import com.aelitis.net.upnp.services.UPnPSpecificService; import com.aelitis.net.upnp.services.UPnPWANConnection; import com.aelitis.net.upnp.services.UPnPWANConnectionListener; import com.aelitis.net.upnp.services.UPnPWANConnectionPortMapping; public class NatPMPUPnPRootDeviceImpl implements UPnPRootDevice { private UPnP upnp; private NatPMPDevice nat_device; private String USN = "natpmp"; private URL location; private UPnPDevice device; private UPnPService[] services; private ThreadPool thread_pool; public NatPMPUPnPRootDeviceImpl( UPnP _upnp, NatPMPDevice _nat_device ) throws Exception { upnp = _upnp; nat_device = _nat_device; location = new URL( "http://undefined/" ); device = new NatPMPUPnPDevice(); services = new UPnPService[]{ new NatPMPUPnPWANConnection() }; thread_pool = new ThreadPool( "NatPMPUPnP", 1, true ); } public UPnP getUPnP() { return( upnp ); } public String getUSN() { return( USN ); } public URL getLocation() { return( location ); } public InetAddress getLocalAddress() { return( nat_device.getLocalAddress()); } public NetworkInterface getNetworkInterface() { return( nat_device.getNetworkInterface()); } public String getInfo() { return( "Nat-PMP" ); } public UPnPDevice getDevice() { return( device ); } public boolean isDestroyed() { return( false ); } public Map getDiscoveryCache() { return( null ); } public void addListener( UPnPRootDeviceListener l ) { } public void removeListener( UPnPRootDeviceListener l ) { } protected class NatPMPUPnPDevice implements UPnPDevice { public String getDeviceType() { return( "NatPMP" ); } public String getFriendlyName() { return( "NatPMP" ); } public String getManufacturer() { return( "" ); } public String getManufacturerURL() { return( "" ); } public String getModelDescription() { return( "" ); } public String getModelName() { return( "" ); } public String getModelNumber() { return( "" ); } public String getModelURL() { return( "" ); } public String getPresentation() { return( "" ); } public UPnPDevice[] getSubDevices() { return( new UPnPDevice[0]); } public UPnPService[] getServices() { return( services ); } public UPnPRootDevice getRootDevice() { return( NatPMPUPnPRootDeviceImpl.this ); } } protected class NatPMPUPnPWANConnection implements UPnPWANConnection, UPnPService { private NatPMPImpl nat_impl; protected NatPMPUPnPWANConnection() throws UPnPException { nat_impl = new NatPMPImpl( nat_device ); } public UPnPDevice getDevice() { return( device ); } public String getServiceType() { // pretend to be an ip connection return( "urn:schemas-upnp-org:service:WANIPConnection:1" ); } public String getConnectionType() { return( "IP" ); // ?? } public URL getControlURL() throws UPnPException { return( null ); } public UPnPAction[] getActions() throws UPnPException { return( new UPnPAction[0] ); } public UPnPAction getAction( String name ) throws UPnPException { return( null ); } public UPnPStateVariable[] getStateVariables() throws UPnPException { return( new UPnPStateVariable[0] ); } public UPnPStateVariable getStateVariable( String name ) throws UPnPException { return( null ); } /** * gets a specific service if such is supported * @return */ public UPnPSpecificService getSpecificService() { return( this ); } public UPnPService getGenericService() { return( this ); } public boolean getDirectInvocations() { return( true ); } public void setDirectInvocations( boolean force ) { } public void addPortMapping( final boolean tcp, final int port, final String description ) throws UPnPException { thread_pool.run( new AERunnable() { public void runSupport() { try{ nat_impl.addPortMapping( tcp, port, description ); }catch( UPnPException e ){ e.printStackTrace(); } } }); } public UPnPWANConnectionPortMapping[] getPortMappings() throws UPnPException { return( nat_impl.getPortMappings()); } public void deletePortMapping( final boolean tcp, final int port ) throws UPnPException { thread_pool.run( new AERunnable() { public void runSupport() { try{ nat_impl.deletePortMapping( tcp, port ); }catch( UPnPException e ){ e.printStackTrace(); } } }); } public String[] getStatusInfo() throws UPnPException { return( nat_impl.getStatusInfo()); } public String getExternalIPAddress() throws UPnPException { return( nat_impl.getExternalIPAddress()); } public void periodicallyRecheckMappings( boolean on ) { } public int getCapabilities() { return( CAP_ALL ); } public void addListener( UPnPWANConnectionListener listener ) { } public void removeListener( UPnPWANConnectionListener listener ) { } } } azureus-4.3.0.6/com/aelitis/net/natpmp/upnp/NatPMPUPnP.java0000644000175000017500000000235010447312500022616 0ustar adrianadrian/* * Created on 12 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.natpmp.upnp; import com.aelitis.net.upnp.UPnPListener; public interface NatPMPUPnP { public void setEnabled( boolean enabled ); public boolean isEnabled(); public void addListener( UPnPListener listener ); public void removeListener( UPnPListener listener ); } azureus-4.3.0.6/com/aelitis/net/natpmp/NATPMPDeviceAdapter.java0000644000175000017500000000211010454746742023425 0ustar adrianadrian/* * Created on 24 Jun 2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.natpmp; public interface NATPMPDeviceAdapter { public String getRouterAddress(); public void log( String str ); } azureus-4.3.0.6/com/aelitis/net/magneturi/0000755000175000017500000000000011310377632017632 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/magneturi/impl/0000755000175000017500000000000011310377632020573 5ustar adrianadrianazureus-4.3.0.6/com/aelitis/net/magneturi/impl/MagnetURIHandlerImpl.java0000644000175000017500000006244511306320304025351 0ustar adrianadrian/* * Created on 03-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.magneturi.impl; import java.io.*; import java.net.*; import java.util.*; import org.bouncycastle.util.encoders.Base64; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.util.*; import com.aelitis.azureus.core.util.HTTPUtils; import com.aelitis.azureus.core.util.png.PNG; import com.aelitis.net.magneturi.MagnetURIHandler; import com.aelitis.net.magneturi.MagnetURIHandlerListener; import com.aelitis.net.magneturi.MagnetURIHandlerProgressListener; /** * @author parg * */ public class MagnetURIHandlerImpl extends MagnetURIHandler { private static final LogIDs LOGID = LogIDs.NET; // see http://magnet-uri.sourceforge.net/magnet-draft-overview.txt private static MagnetURIHandlerImpl singleton; private static AEMonitor class_mon = new AEMonitor( "MagnetURLHandler:class" ); private static final int DOWNLOAD_TIMEOUT = 3*60*1000; protected static final String NL = "\015\012"; private final static boolean DEBUG = false; public static MagnetURIHandler getSingleton() { try{ class_mon.enter(); if ( singleton == null ){ singleton = new MagnetURIHandlerImpl(); } return( singleton ); }finally{ class_mon.exit(); } } private int port; private List listeners = new ArrayList(); private Map info_map = new HashMap(); private Map resources = new HashMap(); protected MagnetURIHandlerImpl() { ServerSocket socket = null; for (int i=45100;i<=45199;i++){ try{ socket = new ServerSocket(i, 50, InetAddress.getByName("127.0.0.1")); port = i; break; }catch( Throwable e ){ } } if ( socket == null ){ // no free sockets, not much we can do if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "MagnetURI: no free sockets, giving up")); }else{ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "MagnetURI: bound on " + socket.getLocalPort())); final ServerSocket f_socket = socket; Thread t = new AEThread("MagnetURIHandler") { public void runSupport() { int errors = 0; int ok = 0; while(true){ try{ final Socket sck = f_socket.accept(); ok++; errors = 0; new AEThread2( "MagnetURIHandler:processor",true) { public void run() { boolean close_socket = true; try{ String address = sck.getInetAddress().getHostAddress(); if ( address.equals("localhost") || address.equals("127.0.0.1")) { BufferedReader br = new BufferedReader(new InputStreamReader(sck.getInputStream(),Constants.DEFAULT_ENCODING)); String line = br.readLine(); if (DEBUG) { System.out.println("====="); System.out.println("Traffic Class: " + sck.getTrafficClass()); System.out.println("OS: " + sck.getOutputStream()); System.out.println("isBound? " + sck.isBound() + "; isClosed=" + sck.isClosed() + "; isConn=" + sck.isConnected() + ";isIShutD " + sck.isInputShutdown() + ";isOShutD " + sck.isOutputShutdown()); System.out.println("- - - -"); System.out.println(line); while (br.ready()) { String extraline = br.readLine(); System.out.println(extraline); } System.out.println("====="); } if ( line != null ){ if ( line.toUpperCase().startsWith( "GET " )){ Logger.log(new LogEvent(LOGID, "MagnetURIHandler: processing '" + line + "'")); line = line.substring(4); int pos = line.lastIndexOf(' '); line = line.substring( 0, pos ); close_socket = process( line, br, sck.getOutputStream() ); }else{ Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "MagnetURIHandler: invalid command - '" + line + "'")); } }else{ Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "MagnetURIHandler: connect from " + "'" + address + "': no data read")); } }else{ Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "MagnetURIHandler: connect from " + "invalid address '" + address + "'")); } }catch( Throwable e ){ if ( !(e instanceof IOException || e instanceof SocketException )){ Debug.printStackTrace(e); } }finally{ try{ // leave client to close socket if not requested if ( close_socket ){ sck.close(); } }catch( Throwable e ){ } } } }.start(); }catch( Throwable e ){ Debug.printStackTrace(e); errors++; if ( errors > 100 ){ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "MagnetURIHandler: bailing out, too many socket errors")); } } } } }; t.setDaemon( true ); t.start(); } } public void process( final String get, final InputStream is, final OutputStream os ) throws IOException { new AEThread2( "MagnetProcessor", true ) { public void run() { boolean close = false; try{ close = process( get, new BufferedReader( new InputStreamReader( is )), os ); }catch( Throwable e ){ Debug.out( "Magnet processing failed", e ); }finally{ if ( close ){ try{ is.close(); }catch( Throwable e ){ Debug.out( e ); } } try{ os.flush(); }catch( Throwable e ){ Debug.out( e ); } if ( close ){ try{ os.close(); }catch( Throwable e ){ Debug.out( e ); } } } } }.start(); } protected boolean process( String get, BufferedReader is, OutputStream os ) throws IOException { //System.out.println( "get = " + get ); // magnet:?xt=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C Map original_params = new HashMap(); Map lc_params = new HashMap(); List source_params = new ArrayList(); int pos = get.indexOf( '?' ); String arg_str; if ( pos == -1 ){ arg_str = ""; }else{ arg_str = get.substring( pos+1 ); StringTokenizer tok = new StringTokenizer( arg_str, "&" ); if (DEBUG) { System.out.println("params:" + get.substring( pos+1 )); } while( tok.hasMoreTokens()){ String arg = tok.nextToken(); pos = arg.indexOf( '=' ); if ( pos == -1 ){ String lhs = arg.trim(); original_params.put( lhs, "" ); lc_params.put( lhs.toLowerCase( MessageText.LOCALE_ENGLISH ), "" ); }else{ try{ String lhs = arg.substring( 0, pos ).trim(); String lc_lhs = lhs.toLowerCase( MessageText.LOCALE_ENGLISH ); String rhs = URLDecoder.decode( arg.substring( pos+1 ).trim(), Constants.DEFAULT_ENCODING); original_params.put( lhs, rhs ); lc_params.put( lc_lhs, rhs ); if ( lc_lhs.equals( "xsource" )){ source_params.add( rhs ); } }catch( UnsupportedEncodingException e ){ Debug.printStackTrace( e ); } } } } if ( get.startsWith( "/magnet10/badge.img" )){ for (int i=0;i" ); resp += getJSS( "" ); resp += getJSS( "Download with Azureus" ); resp += getJSS( "" ); resp += getJS( "magnetOptionsPostamble" ); resp += "magnetOptionsPollSuccesses++"; writeReply( os, "application/x-javascript", resp ); return( true ); }else if ( get.startsWith( "/magnet10/pause" )){ try{ Thread.sleep( 250 ); }catch( Throwable e ){ } writeNotFound( os ); return( true ); }else if ( get.startsWith( "/select/" )){ String fail_reason = ""; boolean ok = false; String urn = (String)lc_params.get( "xt" ); if ( urn == null ){ fail_reason = "xt missing"; }else{ String lc_urn = urn.toLowerCase( MessageText.LOCALE_ENGLISH ); try{ URL url; if ( lc_urn.startsWith( "http:") || lc_urn.startsWith( "https:" )){ url = new URL( urn ); }else{ url = new URL( "magnet:?xt=" + urn ); } for (int i=0;i sources = new ArrayList(); for (int i=0;i max ){ value = max; } }catch( Throwable e ){ Debug.printStackTrace(e); } } } if ( value != Integer.MIN_VALUE ){ if ( value < 0 ){ value = 0; } // need to trim if too large if ( value > 1024 * 1024 ){ value = 1024 * 1024; } // see if we need to div/mod for clients that don't support huge images // e.g. http://localhost:45100/getinfo?name=Plugin.azupnpav.content_port&mod=8 int width = value; int height = 1; // divmod -> encode div+1 as width, mod+1 as height String div_mod = (String)lc_params.get( "divmod" ); if ( div_mod != null ){ int n = Integer.parseInt( div_mod ); width = ( value / n ) + 1; height = ( value % n ) + 1; }else{ String div = (String)lc_params.get( "div" ); if ( div != null ){ width = value / Integer.parseInt( div ); }else{ String mod = (String)lc_params.get( "mod" ); if ( mod != null ){ width = value % Integer.parseInt( mod ); } } } String img_type = (String)lc_params.get( "img_type" ); if ( img_type != null && img_type.equals( "png" )){ byte[] data = PNG.getPNGBytesForSize( width, height ); writeReply( os, "image/png", data ); }else{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); writeImage( baos, width, height ); byte[] data = baos.toByteArray(); writeReply( os, "image/bmp", data ); } return( true ); } } writeNotFound( os ); return( true ); }else if ( get.startsWith( "/setinfo?" )){ String name = (String)lc_params.get( "name" ); if ( name != null ){ boolean result = false; for (int i=0;i> 8) & 0xFF)); os.write((int) ((l >> 16) & 0xFF)); os.write((int) ((l >> 24) & 0xFF)); } catch (IOException e) { Debug.out(e); } } protected String getMessageText( String resource ) { return( MessageText.getString( "MagnetURLHandler.report." + resource )); } protected String getMessageText( String resource, String param ) { return( MessageText.getString( "MagnetURLHandler.report." + resource, new String[]{ param } )); } protected String getJS( String s ) { return( "document.write(" + s + ");" + NL ); } protected String getJSS( String s ) { return( "document.write(\"" + s + "\");" + NL ); } protected void writeReply( OutputStream os, String content_type, String content ) throws IOException { writeReply( os, content_type, content.getBytes()); } protected void writeReply( OutputStream os, String content_type, byte[] content ) throws IOException { PrintWriter pw = new PrintWriter( new OutputStreamWriter( os )); pw.print( "HTTP/1.1 200 OK" + NL ); pw.print( "Cache-Control: no-cache" + NL ); pw.print( "Pragma: no-cache" + NL ); pw.print( "Content-Type: " + content_type + NL ); pw.print( "Content-Length: " + content.length + NL + NL ); pw.flush(); os.write( content ); } protected void writeNotFound( OutputStream os ) throws IOException { PrintWriter pw = new PrintWriter( new OutputStreamWriter( os )); pw.print( "HTTP/1.0 404 Not Found" + NL + NL ); pw.flush(); } public int getPort() { return( port ); } public void addInfo( String name, int info ) { info_map.put( name, new Integer(info)); Logger.log(new LogEvent(LOGID, LogEvent.LT_INFORMATION,"MagnetURIHandler: global info registered: " + name + " -> " + info )); } public void addListener( MagnetURIHandlerListener l ) { listeners.add( l ); } public void removeListener( MagnetURIHandlerListener l ) { listeners.remove( l ); } public static void main( String[] args ) { new MagnetURIHandlerImpl(); try{ Thread.sleep(1000000); }catch( Throwable e ){ } } public URL registerResource( ResourceProvider provider ) { try{ String rid = URLEncoder.encode( provider.getUID(), "UTF-8" ); synchronized( resources ){ resources.put( rid, provider ); } return( new URL( "http://127.0.0.1:" + port + "/resource." + provider.getFileType() + "?rid=" + rid )); }catch( Throwable e ){ Debug.out( e ); return( null ); } } } azureus-4.3.0.6/com/aelitis/net/magneturi/impl/MagnetURIHandlerClient.java0000644000175000017500000000756510720754360025704 0ustar adrianadrian/* * Created on 11-Sep-2006 * Created by Paul Gardner * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.magneturi.impl; import java.net.*; import java.io.*; public class MagnetURIHandlerClient { protected static final String NL = "\015\012"; private byte[] load( String url, int max_millis_to_wait ) { // limit the subset here as we're looping waiting for something to be alive and we can't afford to take ages getting back to the start long start = System.currentTimeMillis(); while( true ){ outer: for (int i=45100;i<=45108;i++){ long now = System.currentTimeMillis(); if ( now < start ){ start = now; } if ( now - start > max_millis_to_wait ){ return( null ); } Socket sock = null; try{ sock = new Socket(); sock.connect( new InetSocketAddress( "127.0.0.1", i ), 500 ); sock.setSoTimeout( 5000 ); PrintWriter pw = new PrintWriter( sock.getOutputStream()); pw.println( "GET " + url + " HTTP/1.1" + NL + NL ); pw.flush(); InputStream is = sock.getInputStream(); String header = ""; byte[] buffer = new byte[1]; while( true ){ int len = is.read( buffer ); if ( len <= 0 ){ break outer; } header += new String( buffer, 0, len ); if ( header.endsWith( NL + NL )){ break; } } int pos = header.indexOf( NL ); String first_line = header.substring( 0, pos ); if ( first_line.indexOf( "200" ) == -1 ){ continue; } ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); buffer = new byte[2048]; while( true ){ int len = is.read( buffer ); if ( len <= 0 ){ break; } baos.write( buffer, 0, len ); if ( baos.size() > 512*1024 ){ break outer; } } return( baos.toByteArray()); }catch( Throwable e ){ }finally{ if ( sock != null ){ try{ sock.close(); }catch( Throwable e ){ } } } } } } public boolean sendSetValue( String name, String value, int max_millis ) { String msg = "/setinfo?name=" + name + "&value=" + value; byte[] response = load( msg, max_millis ); if ( response == null ){ return( false ); } // 40 x 40 image is encoded as 134 bytes... boolean success = response.length == 134; System.out.println( name+"="+value + " -> " + success ); return( success ); } public static void main( String[] args ) { new MagnetURIHandlerClient().sendSetValue( "AZMSG", "AZMSG;1;torrent;is-ready", 30000 ); new MagnetURIHandlerClient().sendSetValue( "AZMSG", "AZMSG;1;torrent;load-torrent;{\"url\":\"http://www.vuze.com/download/VCCBRHY5GYNGFKPJSYQID4GB3XPTYGIG.torrent?referal=jws\",\"play-now\":true}", 30000 ); } } azureus-4.3.0.6/com/aelitis/net/magneturi/MagnetURIHandlerException.java0000644000175000017500000000224411012742130025433 0ustar adrianadrian/* * Created on 07-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.magneturi; /** * @author parg * */ public class MagnetURIHandlerException extends Exception { public MagnetURIHandlerException( String str, Throwable cause ) { super( str, cause ); } } azureus-4.3.0.6/com/aelitis/net/magneturi/MagnetURIHandlerListener.java0000644000175000017500000000306111301443256025270 0ustar adrianadrian/* * Created on 03-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.magneturi; import java.net.InetSocketAddress; import java.net.URL; import java.util.Map; /** * @author parg * */ public interface MagnetURIHandlerListener { public byte[] badge(); public byte[] download( MagnetURIHandlerProgressListener progress, byte[] hash, String args, InetSocketAddress[] sources, long timeout ) throws MagnetURIHandlerException; public boolean download( URL magnet_url ) throws MagnetURIHandlerException; public boolean set( String name, Map values ); public int get( String name, Map values ); } azureus-4.3.0.6/com/aelitis/net/magneturi/MagnetURIHandlerProgressListener.java0000644000175000017500000000234611306320304027013 0ustar adrianadrian/* * Created on 07-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.magneturi; /** * @author parg * */ public interface MagnetURIHandlerProgressListener { public void reportSize( long size ); public void reportActivity( String str ); public void reportCompleteness( int percent ); public boolean verbose(); } azureus-4.3.0.6/com/aelitis/net/magneturi/MagnetURIHandler.java0000644000175000017500000000357011305630416023567 0ustar adrianadrian/* * Created on 03-Mar-2005 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.net.magneturi; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import com.aelitis.net.magneturi.impl.MagnetURIHandlerImpl; /** * @author parg * */ public abstract class MagnetURIHandler { public static MagnetURIHandler getSingleton() { return( MagnetURIHandlerImpl.getSingleton()); } public abstract int getPort(); public abstract void process( String get, InputStream is, OutputStream os ) throws IOException; public abstract void addListener( MagnetURIHandlerListener l ); public abstract void removeListener( MagnetURIHandlerListener l ); public abstract void addInfo( String name, int info ); public abstract URL registerResource( ResourceProvider provider ); public interface ResourceProvider { public String getUID(); public String getFileType(); public byte[] getData(); } }